summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore68
-rw-r--r--BUILD/FINISH.sh16
-rw-r--r--BUILD/Makefile.am2
-rwxr-xr-xBUILD/SETUP.sh18
-rwxr-xr-xBUILD/autorun.sh21
-rwxr-xr-xBUILD/check-cpu6
-rwxr-xr-xBUILD/compile-alpha-ccc4
-rwxr-xr-xBUILD/compile-alpha-cxx4
-rwxr-xr-xBUILD/compile-alpha-debug4
-rwxr-xr-xBUILD/compile-hpux11-parisc2-aCC9
-rwxr-xr-xBUILD/compile-ia64-debug-max9
-rwxr-xr-xBUILD/compile-irix-mips64-mipspro9
-rwxr-xr-xBUILD/compile-pentium-debug2
-rwxr-xr-xBUILD/compile-pentium-debug-max2
-rwxr-xr-xBUILD/compile-pentium-debug-max-no-embedded2
-rwxr-xr-xBUILD/compile-pentium-debug-yassl13
-rwxr-xr-xBUILD/compile-pentium-icc24
-rwxr-xr-xBUILD/compile-pentium-icc-valgrind-max34
-rw-r--r--BUILD/compile-pentium-icc-yassl24
-rwxr-xr-xBUILD/compile-pentium-pgcc10
-rw-r--r--BUILD/compile-pentium64-valgrind-max29
-rwxr-xr-xBUILD/compile-sap9
-rwxr-xr-xBUILD/compile-sap-debug9
-rwxr-xr-xBUILD/compile-solaris-sparc11
-rwxr-xr-xBUILD/compile-solaris-sparc-debug9
-rwxr-xr-xBUILD/compile-solaris-sparc-forte9
-rwxr-xr-xBUILD/compile-solaris-sparc-purify33
-rw-r--r--BitKeeper/etc/RESYNC_TREE0
-rw-r--r--BitKeeper/etc/config1
-rw-r--r--BitKeeper/etc/gone437
-rw-r--r--BitKeeper/etc/logging_ok36
-rwxr-xr-xBitKeeper/triggers/post-commit6
-rwxr-xr-xDocs/changelog-5.0.xml18
-rw-r--r--Docs/sp-imp-spec.txt1100
-rw-r--r--Docs/sp-implemented.txt112
-rw-r--r--Makefile.am32
-rwxr-xr-xVC++Files/bdb/bdb.vcproj3227
-rw-r--r--VC++Files/client/mysql.dsp16
-rwxr-xr-xVC++Files/client/mysql.vcproj318
-rw-r--r--VC++Files/client/mysqladmin.dsp6
-rwxr-xr-xVC++Files/client/mysqladmin.vcproj232
-rw-r--r--VC++Files/client/mysqlclient.dsp30
-rwxr-xr-xVC++Files/client/mysqlclient.vcproj3333
-rw-r--r--VC++Files/client/mysqlclient_ia64.dsp16
-rw-r--r--VC++Files/client/mysqldump.dsp6
-rwxr-xr-xVC++Files/client/mysqldump.vcproj232
-rw-r--r--VC++Files/client/mysqlimport.dsp8
-rwxr-xr-xVC++Files/client/mysqlimport.vcproj232
-rw-r--r--VC++Files/client/mysqlshow.dsp8
-rwxr-xr-xVC++Files/client/mysqlshow.vcproj232
-rw-r--r--VC++Files/client/mysqltest.dsp24
-rwxr-xr-xVC++Files/client/mysqltest.vcproj264
-rwxr-xr-xVC++Files/comp_err/comp_err.vcproj93
-rwxr-xr-xVC++Files/dbug/dbug.vcproj249
-rwxr-xr-xVC++Files/heap/heap.vcproj1061
-rwxr-xr-xVC++Files/innobase/innobase.vcproj2958
-rw-r--r--VC++Files/libmysql/libmysql.dsp36
-rwxr-xr-xVC++Files/libmysql/libmysql.vcproj2298
-rw-r--r--VC++Files/libmysql/libmysql_ia64.dsp16
-rw-r--r--VC++Files/libmysqld/examples/test_libmysqld.dsp8
-rwxr-xr-xVC++Files/libmysqld/examples/test_libmysqld.vcproj130
-rw-r--r--VC++Files/libmysqld/libmysqld.dsp84
-rwxr-xr-xVC++Files/libmysqld/libmysqld.vcproj4500
-rw-r--r--VC++Files/libmysqld/libmysqld_ia64.dsp4
-rwxr-xr-xVC++Files/libmysqltest/myTest.vcproj162
-rw-r--r--VC++Files/libmysqltest/mytest.c1
-rwxr-xr-xVC++Files/my_print_defaults/my_print_defaults.vcproj245
-rwxr-xr-xVC++Files/myisam/myisam.vcproj2094
-rwxr-xr-xVC++Files/myisam_ftdump/myisam_ftdump.vcproj174
-rwxr-xr-xVC++Files/myisamchk/myisamchk.vcproj244
-rwxr-xr-xVC++Files/myisamlog/myisamlog.vcproj244
-rwxr-xr-xVC++Files/myisammrg/myisammrg.vcproj968
-rwxr-xr-xVC++Files/myisampack/myisampack.vcproj247
-rwxr-xr-xVC++Files/mysql-test/mysql_test_run_new.vcproj204
-rw-r--r--VC++Files/mysql.dsw136
-rwxr-xr-xVC++Files/mysql.sln1249
-rw-r--r--VC++Files/mysql_ia64.dsw27
-rw-r--r--VC++Files/mysqlbinlog/mysqlbinlog.dsp6
-rwxr-xr-xVC++Files/mysqlbinlog/mysqlbinlog.vcproj271
-rw-r--r--VC++Files/mysqlcheck/mysqlcheck.dsp6
-rwxr-xr-xVC++Files/mysqlcheck/mysqlcheck.vcproj244
-rw-r--r--VC++Files/mysqldemb/mysqldemb.dsp4
-rwxr-xr-xVC++Files/mysqldemb/mysqldemb.vcproj2960
-rw-r--r--VC++Files/mysqlmanager/MySqlManager_ia64.dsp276
-rw-r--r--VC++Files/mysqlmanager/README.TXT102
-rw-r--r--VC++Files/mysqlmanager/RES/bitmap1.bmpbin630 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/bitmap3.bmpbin630 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/bmp00001.bmpbin246 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/bmp00002.bmpbin238 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/database.bmpbin238 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/fontd.bmpbin246 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/fontu.bmpbin246 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/mysqlmanager.icobin1078 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/mysqlmanager.rc213
-rw-r--r--VC++Files/mysqlmanager/RES/mysqlmanagerdoc.icobin1078 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/query_ex.bmpbin246 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/RES/toolbar.bmpbin1078 -> 0 bytes
-rw-r--r--VC++Files/mysqlmanager/childfrm.cpp65
-rw-r--r--VC++Files/mysqlmanager/childfrm.h52
-rw-r--r--VC++Files/mysqlmanager/cresource.h134
-rw-r--r--VC++Files/mysqlmanager/mainfrm.cpp137
-rw-r--r--VC++Files/mysqlmanager/mainfrm.h69
-rw-r--r--VC++Files/mysqlmanager/mysqlmanager.cpp168
-rw-r--r--VC++Files/mysqlmanager/mysqlmanager.dsp277
-rw-r--r--VC++Files/mysqlmanager/mysqlmanager.h50
-rw-r--r--VC++Files/mysqlmanager/mysqlmanager.mak327
-rw-r--r--VC++Files/mysqlmanager/mysqlmanager.rc572
-rw-r--r--VC++Files/mysqlmanager/mysqlmanagerdoc.cpp84
-rw-r--r--VC++Files/mysqlmanager/mysqlmanagerdoc.h57
-rw-r--r--VC++Files/mysqlmanager/mysqlmanagerview.cpp849
-rw-r--r--VC++Files/mysqlmanager/mysqlmanagerview.h89
-rw-r--r--VC++Files/mysqlmanager/registerserver.cpp51
-rw-r--r--VC++Files/mysqlmanager/registerserver.h50
-rw-r--r--VC++Files/mysqlmanager/resource.h55
-rw-r--r--VC++Files/mysqlmanager/stdafx.cpp5
-rw-r--r--VC++Files/mysqlmanager/stdafx.h28
-rw-r--r--VC++Files/mysqlmanager/toolsql.cpp687
-rw-r--r--VC++Files/mysqlmanager/toolsql.h102
-rw-r--r--VC++Files/mysqlmanager/toolsqlquery.cpp110
-rw-r--r--VC++Files/mysqlmanager/toolsqlquery.h60
-rw-r--r--VC++Files/mysqlmanager/toolsqlresults.cpp73
-rw-r--r--VC++Files/mysqlmanager/toolsqlresults.h53
-rw-r--r--VC++Files/mysqlmanager/toolsqlstatus.cpp50
-rw-r--r--VC++Files/mysqlmanager/toolsqlstatus.h47
-rwxr-xr-xVC++Files/mysqlserver/mysqlserver.vcproj123
-rw-r--r--VC++Files/mysqlshutdown/myshutdown.dsp101
-rw-r--r--VC++Files/mysqlshutdown/myshutdown_ia64.dsp101
-rw-r--r--VC++Files/mysqlshutdown/mysql.icobin318 -> 0 bytes
-rw-r--r--VC++Files/mysqlshutdown/mysqlshutdown.c198
-rw-r--r--VC++Files/mysqlshutdown/mysqlshutdown.dsp119
-rw-r--r--VC++Files/mysqlshutdown/mysqlshutdown.rc2
-rw-r--r--VC++Files/mysqlshutdown/mysqlshutdown_ia64.dsp119
-rw-r--r--VC++Files/mysqlwatch/mysqlwatch.c745
-rw-r--r--VC++Files/mysqlwatch/mysqlwatch.dsp70
-rw-r--r--VC++Files/mysqlwatch/mysqlwatch_ia64.dsp71
-rw-r--r--VC++Files/mysys/mysys.dsp17
-rwxr-xr-xVC++Files/mysys/mysys.vcproj4792
-rw-r--r--VC++Files/mysys/mysys_ia64.dsp4
-rwxr-xr-xVC++Files/perror/perror.vcproj255
-rwxr-xr-xVC++Files/prepare5
-rwxr-xr-xVC++Files/regex/regex.vcproj252
-rwxr-xr-xVC++Files/replace/replace.vcproj229
-rw-r--r--VC++Files/sql/mysqld.dsp113
-rwxr-xr-xVC++Files/sql/mysqld.vcproj8659
-rw-r--r--VC++Files/sql/mysqldmax.dsp14
-rw-r--r--VC++Files/strings/backup/strings.dsp7
-rw-r--r--VC++Files/strings/noMASM/strings.dsp4
-rw-r--r--VC++Files/strings/strings.dsp12
-rwxr-xr-xVC++Files/strings/strings.vcproj1034
-rw-r--r--VC++Files/strings/strings_ia64.dsp12
-rw-r--r--VC++Files/test1/mysql_thr.c1
-rwxr-xr-xVC++Files/test1/test1.vcproj161
-rw-r--r--VC++Files/tests/mysql_client_test.dsp8
-rwxr-xr-xVC++Files/tests/mysql_client_test.vcproj163
-rwxr-xr-xVC++Files/thr_test/thr_test.vcproj162
-rw-r--r--VC++Files/vio/vio.dsp4
-rwxr-xr-xVC++Files/vio/vio.vcproj204
-rw-r--r--VC++Files/winmysqladmin/db.cpp80
-rw-r--r--VC++Files/winmysqladmin/db.h32
-rw-r--r--VC++Files/winmysqladmin/images/Goahead.icobin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/HELP.ICObin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/INFO.ICObin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/Info.bmpbin644 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/MYINI.ICObin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/Myini.bmpbin644 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/Noentry.icobin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/SETUP.BMPbin86878 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/Setup 16.bmpbin86880 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/Table.icobin1078 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/Working.icobin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/database.icobin1078 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/find.icobin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/green.icobin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/help.bmpbin644 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/initsetup.cpp42
-rw-r--r--VC++Files/winmysqladmin/images/killdb.icobin1078 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/logo.icobin2022 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/multitrg.icobin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/mysql-07.bmpbin9618 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/mysql-17.bmpbin3806 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/mysql.BMPbin8760 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/red.icobin766 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/red22.BMPbin2104 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/images/see.bmpbin644 -> 0 bytes
-rw-r--r--VC++Files/winmysqladmin/initsetup.cpp40
-rw-r--r--VC++Files/winmysqladmin/initsetup.h38
-rw-r--r--VC++Files/winmysqladmin/main.cpp2529
-rw-r--r--VC++Files/winmysqladmin/main.h314
-rw-r--r--VC++Files/winmysqladmin/mysql.h295
-rw-r--r--VC++Files/winmysqladmin/mysql_com.h275
-rw-r--r--VC++Files/winmysqladmin/mysql_version.h20
-rw-r--r--VC++Files/winmysqladmin/winmysqladmin.cpp38
-rwxr-xr-xVC++Files/zlib/zlib.vcproj483
-rw-r--r--acinclude.m41999
-rw-r--r--bdb/dist/configure.ac3
-rw-r--r--client/Makefile.am31
-rw-r--r--client/client_priv.h7
-rw-r--r--client/mysql.cc262
-rw-r--r--client/mysqladmin.cc6
-rw-r--r--client/mysqlbinlog.cc624
-rw-r--r--client/mysqlcheck.c1
-rw-r--r--client/mysqldump.c631
-rw-r--r--client/mysqlimport.c1
-rw-r--r--client/mysqlshow.c138
-rw-r--r--client/mysqltest.c825
-rw-r--r--client/sql_string.cc649
-rw-r--r--client/sql_string.h127
-rw-r--r--cmd-line-utils/readline/INSTALL2
-rw-r--r--cmd-line-utils/readline/Makefile.am3
-rw-r--r--cmd-line-utils/readline/README2
-rw-r--r--cmd-line-utils/readline/bind.c152
-rw-r--r--cmd-line-utils/readline/callback.c2
-rw-r--r--cmd-line-utils/readline/chardefs.h6
-rw-r--r--cmd-line-utils/readline/compat.c111
-rw-r--r--cmd-line-utils/readline/complete.c300
-rw-r--r--cmd-line-utils/readline/configure.in15
-rw-r--r--cmd-line-utils/readline/display.c234
-rw-r--r--cmd-line-utils/readline/funmap.c1
-rw-r--r--cmd-line-utils/readline/histexpand.c336
-rw-r--r--cmd-line-utils/readline/histfile.c133
-rw-r--r--cmd-line-utils/readline/history.c90
-rw-r--r--cmd-line-utils/readline/history.h28
-rw-r--r--cmd-line-utils/readline/histsearch.c6
-rw-r--r--cmd-line-utils/readline/input.c26
-rw-r--r--cmd-line-utils/readline/isearch.c8
-rw-r--r--cmd-line-utils/readline/keymaps.c13
-rw-r--r--cmd-line-utils/readline/kill.c57
-rw-r--r--cmd-line-utils/readline/macro.c6
-rw-r--r--cmd-line-utils/readline/mbutil.c53
-rw-r--r--cmd-line-utils/readline/misc.c34
-rw-r--r--cmd-line-utils/readline/nls.c37
-rw-r--r--cmd-line-utils/readline/parens.c4
-rw-r--r--cmd-line-utils/readline/posixdir.h10
-rw-r--r--cmd-line-utils/readline/readline.c69
-rw-r--r--cmd-line-utils/readline/readline.h63
-rw-r--r--cmd-line-utils/readline/rldefs.h6
-rw-r--r--cmd-line-utils/readline/rlmbutil.h19
-rw-r--r--cmd-line-utils/readline/rlprivate.h32
-rw-r--r--cmd-line-utils/readline/rlstdc.h2
-rw-r--r--cmd-line-utils/readline/rltty.c153
-rw-r--r--cmd-line-utils/readline/rltty.h32
-rw-r--r--cmd-line-utils/readline/rltypedefs.h8
-rw-r--r--cmd-line-utils/readline/savestring.c38
-rw-r--r--cmd-line-utils/readline/search.c20
-rw-r--r--cmd-line-utils/readline/shell.c4
-rw-r--r--cmd-line-utils/readline/signals.c8
-rw-r--r--cmd-line-utils/readline/terminal.c93
-rw-r--r--cmd-line-utils/readline/text.c67
-rw-r--r--cmd-line-utils/readline/tilde.c4
-rw-r--r--cmd-line-utils/readline/undo.c7
-rw-r--r--cmd-line-utils/readline/util.c8
-rw-r--r--cmd-line-utils/readline/vi_mode.c132
-rwxr-xr-xconfig.guess1416
-rwxr-xr-xconfig.sub1501
-rw-r--r--config/ac-macros/alloca.m468
-rw-r--r--config/ac-macros/character_sets.m4431
-rw-r--r--config/ac-macros/check_cpu.m447
-rw-r--r--config/ac-macros/compiler_flag.m440
-rw-r--r--config/ac-macros/ha_archive.m429
-rw-r--r--config/ac-macros/ha_berkeley.m4267
-rw-r--r--config/ac-macros/ha_blackhole.m429
-rw-r--r--config/ac-macros/ha_example.m430
-rw-r--r--config/ac-macros/ha_federated.m429
-rw-r--r--config/ac-macros/ha_innodb.m477
-rw-r--r--config/ac-macros/ha_ndbcluster.m4163
-rw-r--r--config/ac-macros/ha_tina.m429
-rw-r--r--config/ac-macros/large_file.m4140
-rw-r--r--config/ac-macros/misc.m4768
-rw-r--r--config/ac-macros/openssl.m4133
-rw-r--r--config/ac-macros/readline.m461
-rw-r--r--config/ac-macros/yassl.m442
-rw-r--r--config/ac-macros/zlib.m4116
-rw-r--r--configure.in868
-rw-r--r--dbug/Makefile.am62
-rw-r--r--dbug/dbug.c38
-rw-r--r--dbug/dbug_analyze.c28
-rw-r--r--dbug/dbug_long.h1
-rw-r--r--dbug/example1.c3
-rw-r--r--dbug/example2.c3
-rw-r--r--dbug/example3.c3
-rw-r--r--dbug/main.c39
-rw-r--r--dbug/monty.doc2
-rw-r--r--dbug/my_main.c41
-rw-r--r--dbug/user.r250
-rwxr-xr-xdepcomp411
-rw-r--r--extra/Makefile.am25
-rw-r--r--extra/charset2html.c (renamed from mysys/charset2html.c)0
-rw-r--r--extra/comp_err.c1065
-rw-r--r--extra/innochecksum.c328
-rw-r--r--extra/my_print_defaults.c47
-rw-r--r--extra/perror.c3
-rw-r--r--extra/replace.c110
-rw-r--r--extra/yassl/AUTHORS0
-rw-r--r--extra/yassl/ChangeLog0
-rw-r--r--extra/yassl/INSTALL229
-rw-r--r--extra/yassl/Makefile.am2
-rw-r--r--extra/yassl/NEWS0
-rw-r--r--extra/yassl/README263
-rw-r--r--extra/yassl/include/buffer.hpp207
-rw-r--r--extra/yassl/include/cert_wrapper.hpp124
-rw-r--r--extra/yassl/include/crypto_wrapper.hpp418
-rw-r--r--extra/yassl/include/factory.hpp105
-rw-r--r--extra/yassl/include/handshake.hpp72
-rw-r--r--extra/yassl/include/lock.hpp90
-rw-r--r--extra/yassl/include/log.hpp58
-rw-r--r--extra/yassl/include/openssl/crypto.h13
-rw-r--r--extra/yassl/include/openssl/des.h1
-rw-r--r--extra/yassl/include/openssl/err.h8
-rw-r--r--extra/yassl/include/openssl/lhash.h2
-rw-r--r--extra/yassl/include/openssl/md5.h1
-rw-r--r--extra/yassl/include/openssl/opensslv.h12
-rw-r--r--extra/yassl/include/openssl/rand.h2
-rw-r--r--extra/yassl/include/openssl/rsa.h10
-rw-r--r--extra/yassl/include/openssl/ssl.h401
-rw-r--r--extra/yassl/include/socket_wrapper.hpp95
-rw-r--r--extra/yassl/include/timer.hpp43
-rw-r--r--extra/yassl/include/yassl_error.hpp78
-rw-r--r--extra/yassl/include/yassl_imp.hpp742
-rw-r--r--extra/yassl/include/yassl_int.hpp550
-rw-r--r--extra/yassl/include/yassl_types.hpp460
-rw-r--r--extra/yassl/mySTL/algorithm.hpp111
-rw-r--r--extra/yassl/mySTL/helpers.hpp108
-rw-r--r--extra/yassl/mySTL/list.hpp383
-rw-r--r--extra/yassl/mySTL/memory.hpp142
-rw-r--r--extra/yassl/mySTL/pair.hpp61
-rw-r--r--extra/yassl/mySTL/stdexcept.hpp80
-rw-r--r--extra/yassl/mySTL/vector.hpp153
-rw-r--r--extra/yassl/src/Makefile.am8
-rw-r--r--extra/yassl/src/buffer.cpp281
-rw-r--r--extra/yassl/src/cert_wrapper.cpp318
-rw-r--r--extra/yassl/src/crypto_wrapper.cpp994
-rw-r--r--extra/yassl/src/dummy.cpp4
-rw-r--r--extra/yassl/src/handshake.cpp1011
-rw-r--r--extra/yassl/src/lock.cpp90
-rw-r--r--extra/yassl/src/log.cpp149
-rw-r--r--extra/yassl/src/socket_wrapper.cpp171
-rw-r--r--extra/yassl/src/ssl.cpp1051
-rw-r--r--extra/yassl/src/template_instnt.cpp95
-rw-r--r--extra/yassl/src/timer.cpp82
-rw-r--r--extra/yassl/src/yassl_error.cpp53
-rw-r--r--extra/yassl/src/yassl_imp.cpp2093
-rw-r--r--extra/yassl/src/yassl_int.cpp1997
-rw-r--r--extra/yassl/taocrypt/Makefile.am2
-rw-r--r--extra/yassl/taocrypt/include/aes.hpp90
-rw-r--r--extra/yassl/taocrypt/include/algebra.hpp228
-rw-r--r--extra/yassl/taocrypt/include/arc4.hpp59
-rw-r--r--extra/yassl/taocrypt/include/asn.hpp327
-rw-r--r--extra/yassl/taocrypt/include/block.hpp202
-rw-r--r--extra/yassl/taocrypt/include/coding.hpp94
-rw-r--r--extra/yassl/taocrypt/include/des.hpp122
-rw-r--r--extra/yassl/taocrypt/include/dh.hpp89
-rw-r--r--extra/yassl/taocrypt/include/dsa.hpp129
-rw-r--r--extra/yassl/taocrypt/include/error.hpp87
-rw-r--r--extra/yassl/taocrypt/include/file.hpp124
-rw-r--r--extra/yassl/taocrypt/include/hash.hpp73
-rw-r--r--extra/yassl/taocrypt/include/hmac.hpp141
-rw-r--r--extra/yassl/taocrypt/include/integer.hpp330
-rw-r--r--extra/yassl/taocrypt/include/md2.hpp67
-rw-r--r--extra/yassl/taocrypt/include/md5.hpp63
-rw-r--r--extra/yassl/taocrypt/include/misc.hpp751
-rw-r--r--extra/yassl/taocrypt/include/modarith.hpp168
-rw-r--r--extra/yassl/taocrypt/include/modes.hpp141
-rw-r--r--extra/yassl/taocrypt/include/random.hpp87
-rw-r--r--extra/yassl/taocrypt/include/ripemd.hpp63
-rw-r--r--extra/yassl/taocrypt/include/rsa.hpp252
-rw-r--r--extra/yassl/taocrypt/include/runtime.hpp52
-rw-r--r--extra/yassl/taocrypt/include/sha.hpp65
-rw-r--r--extra/yassl/taocrypt/include/type_traits.hpp80
-rw-r--r--extra/yassl/taocrypt/include/types.hpp97
-rw-r--r--extra/yassl/taocrypt/src/Makefile.am12
-rw-r--r--extra/yassl/taocrypt/src/aes.cpp400
-rw-r--r--extra/yassl/taocrypt/src/aestables.cpp724
-rw-r--r--extra/yassl/taocrypt/src/algebra.cpp329
-rw-r--r--extra/yassl/taocrypt/src/arc4.cpp93
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp1050
-rw-r--r--extra/yassl/taocrypt/src/coding.cpp250
-rw-r--r--extra/yassl/taocrypt/src/des.cpp435
-rw-r--r--extra/yassl/taocrypt/src/dh.cpp84
-rw-r--r--extra/yassl/taocrypt/src/dsa.cpp274
-rw-r--r--extra/yassl/taocrypt/src/file.cpp118
-rw-r--r--extra/yassl/taocrypt/src/hash.cpp99
-rw-r--r--extra/yassl/taocrypt/src/integer.cpp3971
-rw-r--r--extra/yassl/taocrypt/src/md2.cpp128
-rw-r--r--extra/yassl/taocrypt/src/md5.cpp170
-rw-r--r--extra/yassl/taocrypt/src/misc.cpp143
-rw-r--r--extra/yassl/taocrypt/src/random.cpp130
-rw-r--r--extra/yassl/taocrypt/src/ripemd.cpp290
-rw-r--r--extra/yassl/taocrypt/src/rsa.cpp213
-rw-r--r--extra/yassl/taocrypt/src/sha.cpp145
-rw-r--r--extra/yassl/taocrypt/src/template_instnt.cpp65
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsp260
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsw (renamed from VC++Files/mysqlmanager/mysqlmanager.dsw)20
-rwxr-xr-xextra/yassl/taocrypt/taocrypt.vcproj602
-rw-r--r--extra/yassl/yassl.dsp192
-rw-r--r--extra/yassl/yassl.dsw137
-rwxr-xr-xextra/yassl/yassl.vcproj425
-rw-r--r--heap/Makefile.am3
-rw-r--r--heap/_check.c4
-rw-r--r--heap/heapdef.h4
-rw-r--r--heap/hp_create.c35
-rw-r--r--heap/hp_delete.c6
-rw-r--r--heap/hp_hash.c246
-rw-r--r--heap/hp_open.c4
-rw-r--r--heap/hp_rkey.c4
-rw-r--r--heap/hp_rrnd.c8
-rw-r--r--heap/hp_update.c6
-rw-r--r--heap/hp_write.c6
-rw-r--r--include/Makefile.am17
-rw-r--r--include/config-netware.h2
-rw-r--r--include/config-win.h17
-rw-r--r--include/decimal.h107
-rw-r--r--include/errmsg.h9
-rw-r--r--include/m_ctype.h47
-rw-r--r--include/m_string.h7
-rw-r--r--include/merge.h93
-rw-r--r--include/my_base.h55
-rw-r--r--include/my_bitmap.h7
-rw-r--r--include/my_dbug.h10
-rw-r--r--include/my_global.h97
-rw-r--r--include/my_handler.h35
-rw-r--r--include/my_net.h5
-rw-r--r--include/my_pthread.h18
-rw-r--r--include/my_sys.h116
-rw-r--r--include/my_time.h24
-rw-r--r--include/myisam.h96
-rw-r--r--include/mysql.h132
-rw-r--r--include/mysql_com.h57
-rw-r--r--include/mysql_embed.h1
-rw-r--r--include/mysqld_error.h322
-rw-r--r--include/mysys_err.h17
-rw-r--r--include/nisam.h212
-rw-r--r--include/queues.h1
-rw-r--r--include/sql_state.h164
-rw-r--r--include/thr_lock.h45
-rw-r--r--include/violite.h21
-rw-r--r--innobase/btr/btr0btr.c621
-rw-r--r--innobase/btr/btr0cur.c727
-rw-r--r--innobase/btr/btr0pcur.c119
-rw-r--r--innobase/btr/btr0sea.c411
-rw-r--r--innobase/buf/buf0buf.c123
-rw-r--r--innobase/buf/buf0flu.c19
-rw-r--r--innobase/buf/buf0lru.c7
-rw-r--r--innobase/buf/buf0rea.c15
-rw-r--r--innobase/configure.in7
-rw-r--r--innobase/data/data0data.c15
-rw-r--r--innobase/data/data0type.c64
-rw-r--r--innobase/dict/dict0boot.c61
-rw-r--r--innobase/dict/dict0crea.c175
-rw-r--r--innobase/dict/dict0dict.c211
-rw-r--r--innobase/dict/dict0load.c172
-rw-r--r--innobase/dict/dict0mem.c10
-rw-r--r--innobase/fil/fil0fil.c63
-rw-r--r--innobase/fsp/fsp0fsp.c6
-rw-r--r--innobase/ibuf/ibuf0ibuf.c456
-rw-r--r--innobase/include/Makefile.am2
-rw-r--r--innobase/include/btr0btr.h37
-rw-r--r--innobase/include/btr0btr.ic13
-rw-r--r--innobase/include/btr0cur.h58
-rw-r--r--innobase/include/btr0cur.ic8
-rw-r--r--innobase/include/btr0pcur.h1
-rw-r--r--innobase/include/btr0sea.h10
-rw-r--r--innobase/include/buf0buf.h28
-rw-r--r--innobase/include/buf0buf.ic29
-rw-r--r--innobase/include/buf0flu.ic2
-rw-r--r--innobase/include/buf0lru.h2
-rw-r--r--innobase/include/data0type.h111
-rw-r--r--innobase/include/data0type.ic248
-rw-r--r--innobase/include/dict0boot.h1
-rw-r--r--innobase/include/dict0crea.h15
-rw-r--r--innobase/include/dict0dict.h37
-rw-r--r--innobase/include/dict0dict.ic71
-rw-r--r--innobase/include/dict0mem.h13
-rw-r--r--innobase/include/dyn0dyn.h2
-rw-r--r--innobase/include/dyn0dyn.ic7
-rw-r--r--innobase/include/fil0fil.h2
-rw-r--r--innobase/include/lock0lock.h58
-rw-r--r--innobase/include/lock0lock.ic5
-rw-r--r--innobase/include/log0log.h4
-rw-r--r--innobase/include/mach0data.h21
-rw-r--r--innobase/include/mach0data.ic31
-rw-r--r--innobase/include/mem0mem.ic2
-rw-r--r--innobase/include/mtr0log.h47
-rw-r--r--innobase/include/mtr0mtr.h30
-rw-r--r--innobase/include/os0file.h16
-rw-r--r--innobase/include/os0proc.h28
-rw-r--r--innobase/include/page0cur.h78
-rw-r--r--innobase/include/page0cur.ic43
-rw-r--r--innobase/include/page0page.h265
-rw-r--r--innobase/include/page0page.ic377
-rw-r--r--innobase/include/que0que.h7
-rw-r--r--innobase/include/read0read.h41
-rw-r--r--innobase/include/read0read.ic9
-rw-r--r--innobase/include/read0types.h1
-rw-r--r--innobase/include/rem0cmp.h24
-rw-r--r--innobase/include/rem0cmp.ic5
-rw-r--r--innobase/include/rem0rec.h446
-rw-r--r--innobase/include/rem0rec.ic1052
-rw-r--r--innobase/include/row0mysql.h160
-rw-r--r--innobase/include/row0mysql.ic119
-rw-r--r--innobase/include/row0row.h30
-rw-r--r--innobase/include/row0row.ic49
-rw-r--r--innobase/include/row0sel.ic2
-rw-r--r--innobase/include/row0upd.h17
-rw-r--r--innobase/include/row0upd.ic8
-rw-r--r--innobase/include/row0vers.h7
-rw-r--r--innobase/include/row0vers.ic70
-rw-r--r--innobase/include/srv0srv.h139
-rw-r--r--innobase/include/srv0start.h10
-rw-r--r--innobase/include/sync0rw.h7
-rw-r--r--innobase/include/sync0rw.ic39
-rw-r--r--innobase/include/sync0sync.h31
-rw-r--r--innobase/include/sync0sync.ic8
-rw-r--r--innobase/include/trx0rec.h1
-rw-r--r--innobase/include/trx0roll.h32
-rw-r--r--innobase/include/trx0rseg.ic4
-rw-r--r--innobase/include/trx0sys.ic7
-rw-r--r--innobase/include/trx0trx.h131
-rw-r--r--innobase/include/trx0trx.ic56
-rw-r--r--innobase/include/trx0undo.h48
-rw-r--r--innobase/include/trx0xa.h182
-rw-r--r--innobase/include/univ.i31
-rw-r--r--innobase/include/ut0byte.h15
-rw-r--r--innobase/include/ut0byte.ic21
-rw-r--r--innobase/include/ut0dbg.h119
-rw-r--r--innobase/include/ut0rnd.ic6
-rw-r--r--innobase/include/ut0ut.h8
-rw-r--r--innobase/lock/lock0lock.c627
-rw-r--r--innobase/log/log0log.c150
-rw-r--r--innobase/log/log0recv.c255
-rw-r--r--innobase/mtr/mtr0log.c180
-rw-r--r--innobase/mtr/mtr0mtr.c12
-rw-r--r--innobase/os/os0file.c85
-rw-r--r--innobase/os/os0proc.c87
-rw-r--r--innobase/os/os0sync.c6
-rw-r--r--innobase/os/os0thread.c2
-rw-r--r--innobase/page/page0cur.c564
-rw-r--r--innobase/page/page0page.c656
-rw-r--r--innobase/pars/lexyy.c5
-rw-r--r--innobase/pars/pars0lex.l3
-rw-r--r--innobase/pars/pars0pars.c7
-rw-r--r--innobase/pars/pars0sym.c2
-rw-r--r--innobase/que/que0que.c1
-rw-r--r--innobase/read/read0read.c159
-rw-r--r--innobase/rem/rem0cmp.c208
-rw-r--r--innobase/rem/rem0rec.c1099
-rw-r--r--innobase/row/row0ins.c336
-rw-r--r--innobase/row/row0mysql.c755
-rw-r--r--innobase/row/row0purge.c17
-rw-r--r--innobase/row/row0row.c128
-rw-r--r--innobase/row/row0sel.c1199
-rw-r--r--innobase/row/row0umod.c19
-rw-r--r--innobase/row/row0undo.c14
-rw-r--r--innobase/row/row0upd.c189
-rw-r--r--innobase/row/row0vers.c128
-rw-r--r--innobase/srv/srv0srv.c264
-rw-r--r--innobase/srv/srv0start.c49
-rw-r--r--innobase/sync/sync0rw.c9
-rw-r--r--innobase/sync/sync0sync.c281
-rw-r--r--innobase/trx/trx0rec.c114
-rw-r--r--innobase/trx/trx0roll.c135
-rw-r--r--innobase/trx/trx0sys.c25
-rw-r--r--innobase/trx/trx0trx.c416
-rw-r--r--innobase/trx/trx0undo.c258
-rw-r--r--innobase/ut/ut0dbg.c65
-rw-r--r--innobase/ut/ut0mem.c2
-rw-r--r--innobase/ut/ut0ut.c26
-rwxr-xr-xinstall-sh251
-rw-r--r--isam/.cvsignore10
-rw-r--r--isam/ChangeLog186
-rw-r--r--isam/Makefile.am46
-rw-r--r--isam/_cache.c92
-rw-r--r--isam/_dbug.c132
-rw-r--r--isam/_dynrec.c1247
-rw-r--r--isam/_key.c238
-rw-r--r--isam/_locking.c345
-rw-r--r--isam/_packrec.c1184
-rw-r--r--isam/_page.c143
-rw-r--r--isam/_search.c889
-rw-r--r--isam/_statrec.c265
-rw-r--r--isam/close.c92
-rw-r--r--isam/create.c329
-rw-r--r--isam/delete.c615
-rw-r--r--isam/extra.c271
-rw-r--r--isam/info.c77
-rw-r--r--isam/isamchk.c3433
-rw-r--r--isam/isamdef.h418
-rw-r--r--isam/isamlog.c853
-rw-r--r--isam/log.c156
-rwxr-xr-xisam/make-ccc3
-rw-r--r--isam/open.c477
-rw-r--r--isam/pack_isam.c2046
-rw-r--r--isam/panic.c135
-rw-r--r--isam/range.c191
-rw-r--r--isam/rfirst.c34
-rw-r--r--isam/rkey.c63
-rw-r--r--isam/rlast.c34
-rw-r--r--isam/rnext.c67
-rw-r--r--isam/rprev.c64
-rw-r--r--isam/rrnd.c55
-rw-r--r--isam/rsame.c70
-rw-r--r--isam/rsamepos.c59
-rw-r--r--isam/sort.c561
-rw-r--r--isam/static.c45
-rw-r--r--isam/test1.c179
-rw-r--r--isam/test2.c841
-rw-r--r--isam/test3.c494
-rwxr-xr-xisam/test_all30
-rw-r--r--isam/test_all.res30
-rw-r--r--isam/update.c117
-rw-r--r--isam/write.c840
-rw-r--r--libmysql/Makefile.shared14
-rw-r--r--libmysql/client_settings.h6
-rw-r--r--libmysql/errmsg.c34
-rw-r--r--libmysql/libmysql.c1045
-rw-r--r--libmysql/libmysql.def8
-rw-r--r--libmysql_r/Makefile.am4
-rw-r--r--libmysqld/Makefile.am39
-rw-r--r--libmysqld/examples/Makefile.am18
-rw-r--r--libmysqld/examples/builder-sample/emb_samples.cpp1
-rw-r--r--libmysqld/lib_sql.cc19
-rw-r--r--libmysqld/libmysqld.c13
-rw-r--r--libmysqld/libmysqld.def10
-rw-r--r--[-rwxr-xr-x]libmysqld/libmysqld.rc0
-rw-r--r--[-rwxr-xr-x]libmysqld/resource.h0
-rwxr-xr-xltconfig3154
-rw-r--r--ltmain.sh6297
-rw-r--r--man/Makefile.am4
-rw-r--r--man/isamchk.1.in145
-rw-r--r--man/isamlog.1.in107
-rw-r--r--merge/.cvsignore3
-rw-r--r--merge/Makefile.am26
-rwxr-xr-xmerge/make-ccc3
-rw-r--r--merge/mrg_close.c40
-rw-r--r--merge/mrg_create.c61
-rw-r--r--merge/mrg_extra.c46
-rw-r--r--merge/mrg_info.c60
-rw-r--r--merge/mrg_open.c150
-rw-r--r--merge/mrg_panic.c47
-rw-r--r--merge/mrg_rrnd.c110
-rw-r--r--merge/mrg_rsame.c36
-rwxr-xr-xmissing283
-rwxr-xr-xmkinstalldirs38
-rw-r--r--myisam/Makefile.am3
-rw-r--r--myisam/ft_boolean_search.c92
-rw-r--r--myisam/ft_parser.c39
-rw-r--r--myisam/ft_static.c36
-rw-r--r--myisam/ft_stopwords.c2
-rw-r--r--myisam/ft_test1.c85
-rw-r--r--myisam/ft_update.c35
-rw-r--r--myisam/ftdefs.h3
-rw-r--r--myisam/mi_check.c38
-rw-r--r--myisam/mi_checksum.c8
-rw-r--r--myisam/mi_create.c101
-rw-r--r--myisam/mi_dbug.c16
-rw-r--r--myisam/mi_delete.c49
-rw-r--r--myisam/mi_dynrec.c87
-rw-r--r--myisam/mi_extra.c11
-rw-r--r--myisam/mi_info.c33
-rw-r--r--myisam/mi_key.c81
-rw-r--r--myisam/mi_keycache.c1
-rw-r--r--myisam/mi_locking.c51
-rw-r--r--myisam/mi_open.c68
-rw-r--r--myisam/mi_packrec.c53
-rw-r--r--myisam/mi_page.c2
-rw-r--r--myisam/mi_preload.c2
-rw-r--r--myisam/mi_range.c19
-rw-r--r--myisam/mi_rkey.c1
-rw-r--r--myisam/mi_rsame.c2
-rw-r--r--myisam/mi_rsamepos.c2
-rw-r--r--myisam/mi_search.c35
-rw-r--r--myisam/mi_static.c7
-rw-r--r--myisam/mi_statrec.c3
-rw-r--r--myisam/mi_test1.c80
-rw-r--r--myisam/mi_test3.c1
-rw-r--r--myisam/mi_test_all.res73
-rw-r--r--myisam/mi_unique.c95
-rw-r--r--myisam/mi_update.c11
-rw-r--r--myisam/mi_write.c32
-rw-r--r--myisam/myisamchk.c24
-rw-r--r--myisam/myisamdef.h12
-rw-r--r--myisam/myisamlog.c2
-rw-r--r--myisam/myisampack.c1310
-rw-r--r--myisam/rt_split.c19
-rw-r--r--myisam/sort.c5
-rw-r--r--myisammrg/Makefile.am3
-rw-r--r--mysql-test/Makefile.am16
-rwxr-xr-xmysql-test/create-test-result4
-rw-r--r--mysql-test/include/big_test.inc4
-rw-r--r--mysql-test/include/federated.inc21
-rw-r--r--mysql-test/include/federated_cleanup.inc11
-rw-r--r--mysql-test/include/have_eucjpms.inc4
-rw-r--r--mysql-test/include/have_federated_db.inc4
-rw-r--r--mysql-test/include/have_isam.inc4
-rw-r--r--mysql-test/include/have_lowercase0.inc4
-rw-r--r--mysql-test/include/have_ndb.inc4
-rw-r--r--mysql-test/include/ndb_default_cluster.inc4
-rw-r--r--mysql-test/include/ps_conv.inc2
-rw-r--r--mysql-test/include/ps_create.inc4
-rw-r--r--mysql-test/include/ps_modify.inc8
-rw-r--r--mysql-test/include/ps_query.inc6
-rw-r--r--mysql-test/include/rpl_stmt_seq.inc2
-rwxr-xr-xmysql-test/include/show_msg.inc25
-rwxr-xr-xmysql-test/include/show_msg80.inc118
-rw-r--r--mysql-test/include/system_db_struct.inc2
-rw-r--r--mysql-test/include/testdb_only.inc30
-rw-r--r--mysql-test/include/varchar.inc239
-rw-r--r--mysql-test/lib/init_db.sql110
-rw-r--r--mysql-test/lib/mtr_cases.pl118
-rw-r--r--mysql-test/lib/mtr_process.pl2
-rwxr-xr-xmysql-test/mysql-test-run.pl317
-rw-r--r--mysql-test/mysql-test-run.sh211
-rw-r--r--mysql-test/mysql_test_run_new.c63
-rw-r--r--mysql-test/ndb/Makefile.am1
-rw-r--r--mysql-test/ndb/basic.result10
-rw-r--r--mysql-test/ndb/ndb_config_2_node.ini4
-rw-r--r--mysql-test/ndb/ndb_range_bounds.pl190
-rw-r--r--mysql-test/ndb/ndbcluster.sh4
-rw-r--r--mysql-test/ndb/restart.test2
-rw-r--r--mysql-test/r/alias.result4
-rw-r--r--mysql-test/r/alter_table.result37
-rw-r--r--mysql-test/r/analyse.result43
-rw-r--r--mysql-test/r/ansi.result2
-rw-r--r--mysql-test/r/archive.result3682
-rw-r--r--mysql-test/r/auto_increment.result45
-rw-r--r--mysql-test/r/backup.result6
-rw-r--r--mysql-test/r/bdb.result619
-rw-r--r--mysql-test/r/bench_count_distinct.result2
-rw-r--r--mysql-test/r/bigint.result217
-rw-r--r--mysql-test/r/binlog.result135
-rw-r--r--mysql-test/r/blackhole.result10
-rw-r--r--mysql-test/r/bool.result18
-rw-r--r--mysql-test/r/case.result59
-rw-r--r--mysql-test/r/cast.result129
-rw-r--r--mysql-test/r/check.result9
-rw-r--r--mysql-test/r/client_xml.result74
-rw-r--r--mysql-test/r/connect.result6
-rw-r--r--mysql-test/r/count_distinct.result13
-rw-r--r--mysql-test/r/count_distinct2.result2
-rw-r--r--mysql-test/r/create.result98
-rw-r--r--mysql-test/r/ctype_collate.result4
-rwxr-xr-x[-rw-r--r--]mysql-test/r/ctype_cp932.result5865
-rwxr-xr-xmysql-test/r/ctype_eucjpms.result9821
-rw-r--r--mysql-test/r/ctype_latin1_de.result10
-rw-r--r--mysql-test/r/ctype_many.result22
-rw-r--r--mysql-test/r/ctype_mb.result8
-rw-r--r--mysql-test/r/ctype_recoding.result12
-rw-r--r--mysql-test/r/ctype_tis620.result68
-rw-r--r--mysql-test/r/ctype_uca.result134
-rw-r--r--mysql-test/r/ctype_ucs.result55
-rw-r--r--mysql-test/r/ctype_ucs_binlog.result15
-rw-r--r--mysql-test/r/ctype_ujis.result2
-rw-r--r--mysql-test/r/ctype_utf8.result98
-rw-r--r--mysql-test/r/date_formats.result41
-rw-r--r--mysql-test/r/default.result138
-rw-r--r--mysql-test/r/delayed.result10
-rw-r--r--mysql-test/r/delete.result22
-rw-r--r--mysql-test/r/derived.result20
-rw-r--r--mysql-test/r/distinct.result18
-rw-r--r--mysql-test/r/drop.result2
-rw-r--r--mysql-test/r/drop_temp_table.result5
-rw-r--r--mysql-test/r/endspace.result44
-rw-r--r--mysql-test/r/errors.result9
-rw-r--r--mysql-test/r/federated.result1463
-rw-r--r--mysql-test/r/federated_archive.result48
-rw-r--r--mysql-test/r/federated_bug_13118.result39
-rw-r--r--mysql-test/r/flush.result2
-rw-r--r--mysql-test/r/flush_block_commit.result15
-rw-r--r--mysql-test/r/flush_read_lock_kill.result9
-rw-r--r--mysql-test/r/flush_table.result3
-rw-r--r--mysql-test/r/fulltext.result25
-rw-r--r--mysql-test/r/fulltext_order_by.result6
-rw-r--r--mysql-test/r/func_concat.result6
-rw-r--r--mysql-test/r/func_date_add.result28
-rw-r--r--mysql-test/r/func_default.result7
-rw-r--r--mysql-test/r/func_equal.result12
-rw-r--r--mysql-test/r/func_gconcat.result17
-rw-r--r--mysql-test/r/func_group.result241
-rw-r--r--mysql-test/r/func_if.result36
-rw-r--r--mysql-test/r/func_in.result27
-rw-r--r--mysql-test/r/func_like.result4
-rw-r--r--mysql-test/r/func_math.result27
-rw-r--r--mysql-test/r/func_misc.result45
-rw-r--r--mysql-test/r/func_op.result2
-rw-r--r--mysql-test/r/func_regexp.result2
-rw-r--r--mysql-test/r/func_sapdb.result49
-rw-r--r--mysql-test/r/func_set.result6
-rw-r--r--mysql-test/r/func_str.result103
-rw-r--r--mysql-test/r/func_system.result8
-rw-r--r--mysql-test/r/func_test.result31
-rw-r--r--mysql-test/r/func_time.result142
-rw-r--r--mysql-test/r/gis-rtree.result9
-rw-r--r--mysql-test/r/gis.result61
-rw-r--r--mysql-test/r/grant.result189
-rw-r--r--mysql-test/r/grant2.result196
-rw-r--r--mysql-test/r/grant3.result18
-rw-r--r--mysql-test/r/grant_cache.result16
-rw-r--r--mysql-test/r/greedy_optimizer.result657
-rw-r--r--mysql-test/r/group_by.result55
-rw-r--r--mysql-test/r/group_min_max.result2010
-rw-r--r--mysql-test/r/have_eucjpms.require2
-rw-r--r--mysql-test/r/have_federated_db.require2
-rw-r--r--mysql-test/r/having.result205
-rw-r--r--mysql-test/r/heap.result452
-rw-r--r--mysql-test/r/heap_btree.result6
-rw-r--r--mysql-test/r/heap_hash.result26
-rw-r--r--mysql-test/r/help.result16
-rw-r--r--mysql-test/r/index_merge.result386
-rw-r--r--mysql-test/r/index_merge_bdb.result136
-rw-r--r--mysql-test/r/index_merge_innodb.result205
-rw-r--r--mysql-test/r/index_merge_innodb2.result136
-rw-r--r--mysql-test/r/index_merge_ror.result196
-rw-r--r--mysql-test/r/index_merge_ror_cpk.result120
-rw-r--r--mysql-test/r/information_schema.result1014
-rw-r--r--mysql-test/r/information_schema_db.result30
-rw-r--r--mysql-test/r/information_schema_inno.result27
-rw-r--r--mysql-test/r/init_connect.result2
-rw-r--r--mysql-test/r/innodb-big.result34
-rw-r--r--mysql-test/r/innodb.result957
-rw-r--r--mysql-test/r/insert.result156
-rw-r--r--mysql-test/r/insert_select-binlog.result10
-rw-r--r--mysql-test/r/insert_select.result18
-rw-r--r--mysql-test/r/insert_update.result6
-rw-r--r--mysql-test/r/isam.result12
-rw-r--r--mysql-test/r/join.result77
-rw-r--r--mysql-test/r/join_crash.result15
-rw-r--r--mysql-test/r/join_nested.result1377
-rw-r--r--mysql-test/r/join_outer.result210
-rw-r--r--mysql-test/r/key.result65
-rw-r--r--mysql-test/r/key_cache.result8
-rw-r--r--mysql-test/r/keywords.result16
-rw-r--r--mysql-test/r/kill.result12
-rw-r--r--mysql-test/r/limit.result2
-rw-r--r--mysql-test/r/loaddata.result62
-rw-r--r--mysql-test/r/lock.result2
-rw-r--r--mysql-test/r/lock_multi.result7
-rw-r--r--mysql-test/r/lowercase_table.result1
-rw-r--r--mysql-test/r/lowercase_table3.result2
-rw-r--r--mysql-test/r/lowercase_table_grant.result8
-rw-r--r--mysql-test/r/lowercase_view.result133
-rw-r--r--mysql-test/r/merge.result48
-rw-r--r--mysql-test/r/metadata.result6
-rw-r--r--mysql-test/r/mix_innodb_myisam_binlog.result145
-rw-r--r--mysql-test/r/multi_update.result60
-rw-r--r--mysql-test/r/myisam.result733
-rw-r--r--mysql-test/r/mysql.result60
-rw-r--r--mysql-test/r/mysqlbinlog.result94
-rw-r--r--mysql-test/r/mysqlbinlog2.result201
-rw-r--r--mysql-test/r/mysqldump.result615
-rw-r--r--mysql-test/r/mysqlshow.result76
-rw-r--r--mysql-test/r/mysqltest.result25
-rw-r--r--mysql-test/r/ndb_alter_table.result8
-rw-r--r--mysql-test/r/ndb_autodiscover.result39
-rw-r--r--mysql-test/r/ndb_basic.result8
-rw-r--r--mysql-test/r/ndb_bitfield.result210
-rw-r--r--mysql-test/r/ndb_blob.result2
-rw-r--r--mysql-test/r/ndb_cache.result182
-rw-r--r--mysql-test/r/ndb_cache2.result623
-rw-r--r--mysql-test/r/ndb_cache_multi.result72
-rw-r--r--mysql-test/r/ndb_cache_multi2.result82
-rw-r--r--mysql-test/r/ndb_charset.result117
-rw-r--r--mysql-test/r/ndb_condition_pushdown.result1770
-rw-r--r--mysql-test/r/ndb_config.result2
-rw-r--r--mysql-test/r/ndb_default_cluster.require2
-rw-r--r--mysql-test/r/ndb_grant.result38
-rw-r--r--mysql-test/r/ndb_index_ordered.result115
-rw-r--r--mysql-test/r/ndb_index_unique.result10
-rw-r--r--mysql-test/r/ndb_read_multi_range.result265
-rw-r--r--mysql-test/r/ndb_subquery.result19
-rw-r--r--mysql-test/r/ndb_types.result29
-rw-r--r--mysql-test/r/negation_elimination.result2
-rw-r--r--mysql-test/r/not_embedded_server.result2
-rw-r--r--mysql-test/r/null.result53
-rw-r--r--mysql-test/r/null_key.result13
-rw-r--r--mysql-test/r/odbc.result2
-rw-r--r--mysql-test/r/olap.result183
-rw-r--r--mysql-test/r/openssl_1.result8
-rw-r--r--mysql-test/r/order_by.result50
-rw-r--r--mysql-test/r/preload.result41
-rw-r--r--mysql-test/r/ps.result163
-rw-r--r--mysql-test/r/ps_1general.result74
-rw-r--r--mysql-test/r/ps_2myisam.result898
-rw-r--r--mysql-test/r/ps_3innodb.result898
-rw-r--r--mysql-test/r/ps_4heap.result904
-rw-r--r--mysql-test/r/ps_5merge.result1788
-rw-r--r--mysql-test/r/ps_6bdb.result898
-rw-r--r--mysql-test/r/ps_7ndb.result898
-rw-r--r--mysql-test/r/ps_grant.result18
-rw-r--r--mysql-test/r/query_cache.result158
-rw-r--r--mysql-test/r/range.result173
-rw-r--r--mysql-test/r/repair.result6
-rw-r--r--mysql-test/r/replace.result4
-rw-r--r--mysql-test/r/row.result19
-rw-r--r--mysql-test/r/rowid_order_bdb.result186
-rw-r--r--mysql-test/r/rowid_order_innodb.result186
-rw-r--r--mysql-test/r/rpl000001.result23
-rw-r--r--mysql-test/r/rpl000009.result3
-rw-r--r--mysql-test/r/rpl000015.result8
-rw-r--r--mysql-test/r/rpl_EE_error.result4
-rw-r--r--mysql-test/r/rpl_auto_increment.result185
-rw-r--r--mysql-test/r/rpl_change_master.result18
-rw-r--r--mysql-test/r/rpl_charset.result182
-rw-r--r--mysql-test/r/rpl_create_database.result32
-rw-r--r--mysql-test/r/rpl_ddl.result182
-rw-r--r--mysql-test/r/rpl_deadlock.result16
-rw-r--r--mysql-test/r/rpl_delete_all.result2
-rw-r--r--mysql-test/r/rpl_error_ignored_table.result24
-rw-r--r--mysql-test/r/rpl_failed_optimize.result4
-rw-r--r--mysql-test/r/rpl_flush_log_loop.result2
-rw-r--r--mysql-test/r/rpl_flush_tables.result38
-rw-r--r--mysql-test/r/rpl_loaddata.result29
-rw-r--r--mysql-test/r/rpl_loaddata_rule_m.result10
-rw-r--r--mysql-test/r/rpl_loaddata_rule_s.result4
-rw-r--r--mysql-test/r/rpl_loaddatalocal.result17
-rw-r--r--mysql-test/r/rpl_log.result120
-rw-r--r--mysql-test/r/rpl_log_pos.result14
-rw-r--r--mysql-test/r/rpl_max_relay_size.result14
-rw-r--r--mysql-test/r/rpl_multi_query.result4
-rw-r--r--mysql-test/r/rpl_openssl.result6
-rw-r--r--mysql-test/r/rpl_relayrotate.result7
-rw-r--r--mysql-test/r/rpl_replicate_do.result2
-rw-r--r--mysql-test/r/rpl_reset_slave.result8
-rw-r--r--mysql-test/r/rpl_rewrite_db.result6
-rw-r--r--mysql-test/r/rpl_rotate_logs.result31
-rw-r--r--mysql-test/r/rpl_server_id1.result2
-rw-r--r--mysql-test/r/rpl_server_id2.result2
-rw-r--r--mysql-test/r/rpl_session_var.result43
-rw-r--r--mysql-test/r/rpl_sp.result269
-rw-r--r--mysql-test/r/rpl_sp_effects.result215
-rw-r--r--mysql-test/r/rpl_temporary.result32
-rw-r--r--mysql-test/r/rpl_timezone.result81
-rw-r--r--mysql-test/r/rpl_trigger.result108
-rw-r--r--mysql-test/r/rpl_trunc_binlog.result13
-rw-r--r--mysql-test/r/rpl_until.result34
-rw-r--r--mysql-test/r/rpl_user_variables.result59
-rw-r--r--mysql-test/r/rpl_variables.result9
-rw-r--r--mysql-test/r/rpl_view.result56
-rw-r--r--mysql-test/r/schema.result11
-rw-r--r--mysql-test/r/select.result721
-rw-r--r--mysql-test/r/select_found.result2
-rw-r--r--mysql-test/r/select_safe.result5
-rw-r--r--mysql-test/r/server_id.require (renamed from mysql-test/r/have_isam.require)2
-rw-r--r--mysql-test/r/server_id1.require2
-rw-r--r--mysql-test/r/show_check.result184
-rw-r--r--mysql-test/r/skip_grants.result10
-rw-r--r--mysql-test/r/sp-big.result15
-rw-r--r--mysql-test/r/sp-dynamic.result364
-rw-r--r--mysql-test/r/sp-error.result835
-rw-r--r--mysql-test/r/sp-goto.result205
-rw-r--r--mysql-test/r/sp-prelocking.result215
-rw-r--r--mysql-test/r/sp-security.result253
-rw-r--r--mysql-test/r/sp-threads.result91
-rw-r--r--mysql-test/r/sp.result3351
-rw-r--r--mysql-test/r/sp_trans.result176
-rw-r--r--mysql-test/r/sql_mode.result334
-rw-r--r--mysql-test/r/strict.result1290
-rw-r--r--mysql-test/r/subselect.result311
-rw-r--r--mysql-test/r/subselect2.result14
-rw-r--r--mysql-test/r/sum_distinct-big.result108
-rw-r--r--mysql-test/r/sum_distinct.result97
-rw-r--r--mysql-test/r/symlink.result25
-rw-r--r--mysql-test/r/synchronization.result1
-rw-r--r--mysql-test/r/system_mysql_db.result64
-rw-r--r--mysql-test/r/temp_table.result28
-rw-r--r--mysql-test/r/testdb_only.require2
-rw-r--r--mysql-test/r/timezone2.result27
-rw-r--r--mysql-test/r/timezone_grant.result8
-rw-r--r--mysql-test/r/trigger.result740
-rw-r--r--mysql-test/r/type_bit.result555
-rw-r--r--mysql-test/r/type_bit_innodb.result404
-rw-r--r--mysql-test/r/type_blob.result56
-rw-r--r--mysql-test/r/type_date.result2
-rw-r--r--mysql-test/r/type_datetime.result32
-rw-r--r--mysql-test/r/type_decimal.result407
-rw-r--r--mysql-test/r/type_enum.result8
-rw-r--r--mysql-test/r/type_float.result48
-rw-r--r--mysql-test/r/type_newdecimal.result1021
-rw-r--r--mysql-test/r/type_ranges.result218
-rw-r--r--mysql-test/r/type_set.result2
-rw-r--r--mysql-test/r/type_time.result6
-rw-r--r--mysql-test/r/type_timestamp.result12
-rw-r--r--mysql-test/r/type_uint.result4
-rw-r--r--mysql-test/r/type_varchar.result417
-rw-r--r--mysql-test/r/union.result53
-rw-r--r--mysql-test/r/update.result4
-rw-r--r--mysql-test/r/user_limits.result96
-rw-r--r--mysql-test/r/user_var-binlog.result21
-rw-r--r--mysql-test/r/user_var.result51
-rw-r--r--mysql-test/r/varbinary.result2
-rw-r--r--mysql-test/r/variables.result107
-rw-r--r--mysql-test/r/view.result2264
-rw-r--r--mysql-test/r/view_grant.result309
-rw-r--r--mysql-test/r/view_query_cache.result126
-rw-r--r--mysql-test/r/warnings.result78
-rw-r--r--mysql-test/r/xa.result47
-rw-r--r--mysql-test/std_data/loaddata5.dat3
-rw-r--r--mysql-test/std_data/rpl_timezone.dat2
-rw-r--r--mysql-test/std_data/trunc_binlog.000001bin119 -> 174 bytes
-rw-r--r--mysql-test/std_data/vchar.frmbin0 -> 8616 bytes
-rw-r--r--mysql-test/t/alias.test5
-rw-r--r--mysql-test/t/alter_table.test8
-rw-r--r--mysql-test/t/analyse.test9
-rw-r--r--mysql-test/t/archive.test45
-rw-r--r--mysql-test/t/auto_increment.test36
-rw-r--r--mysql-test/t/backup.test5
-rw-r--r--mysql-test/t/bdb.test46
-rw-r--r--mysql-test/t/bigint.test164
-rw-r--r--mysql-test/t/binlog-master.opt1
-rw-r--r--mysql-test/t/binlog.test48
-rw-r--r--mysql-test/t/bool.test10
-rw-r--r--mysql-test/t/case.test25
-rw-r--r--mysql-test/t/cast.test44
-rw-r--r--mysql-test/t/check.test13
-rw-r--r--mysql-test/t/client_xml.test21
-rw-r--r--mysql-test/t/connect.test2
-rw-r--r--mysql-test/t/count_distinct.test21
-rw-r--r--mysql-test/t/count_distinct2.test2
-rw-r--r--mysql-test/t/create.test33
-rw-r--r--mysql-test/t/ctype_cp932.test26
-rw-r--r--mysql-test/t/ctype_eucjpms.test365
-rw-r--r--mysql-test/t/ctype_latin1_de.test10
-rw-r--r--mysql-test/t/ctype_many.test6
-rw-r--r--mysql-test/t/ctype_uca.test16
-rw-r--r--mysql-test/t/ctype_ucs.test33
-rw-r--r--mysql-test/t/ctype_ucs_binlog.test2
-rw-r--r--mysql-test/t/ctype_utf8.test56
-rw-r--r--mysql-test/t/date_formats.test1
-rw-r--r--mysql-test/t/default.test85
-rw-r--r--mysql-test/t/delayed.test13
-rw-r--r--mysql-test/t/delete.test19
-rw-r--r--mysql-test/t/derived.test25
-rw-r--r--mysql-test/t/disabled.def17
-rw-r--r--mysql-test/t/distinct.test11
-rw-r--r--mysql-test/t/endspace.test8
-rw-r--r--mysql-test/t/errors.test15
-rw-r--r--mysql-test/t/federated.test1147
-rw-r--r--mysql-test/t/federated_archive.test58
-rw-r--r--mysql-test/t/federated_bug_13118.test42
-rw-r--r--mysql-test/t/flush.test2
-rw-r--r--mysql-test/t/flush_block_commit.test21
-rw-r--r--mysql-test/t/flush_read_lock_kill-master.opt1
-rw-r--r--mysql-test/t/flush_read_lock_kill.test49
-rw-r--r--mysql-test/t/flush_table.test7
-rw-r--r--mysql-test/t/fulltext.test14
-rw-r--r--mysql-test/t/fulltext_order_by.test6
-rw-r--r--mysql-test/t/func_compress.test2
-rw-r--r--mysql-test/t/func_concat.test6
-rw-r--r--mysql-test/t/func_date_add.test25
-rw-r--r--mysql-test/t/func_default.test10
-rw-r--r--mysql-test/t/func_equal.test4
-rw-r--r--mysql-test/t/func_gconcat.test7
-rw-r--r--mysql-test/t/func_group.test108
-rw-r--r--mysql-test/t/func_if.test19
-rw-r--r--mysql-test/t/func_in.test18
-rw-r--r--mysql-test/t/func_math.test30
-rw-r--r--mysql-test/t/func_misc.test39
-rw-r--r--mysql-test/t/func_sapdb.test13
-rw-r--r--mysql-test/t/func_set.test2
-rw-r--r--mysql-test/t/func_str.test10
-rw-r--r--mysql-test/t/func_test.test18
-rw-r--r--mysql-test/t/func_time.test93
-rw-r--r--mysql-test/t/gis-rtree.test3
-rw-r--r--mysql-test/t/gis.test38
-rw-r--r--mysql-test/t/grant.test92
-rw-r--r--mysql-test/t/grant2.test194
-rw-r--r--mysql-test/t/grant3-master.opt1
-rw-r--r--mysql-test/t/grant3.test36
-rw-r--r--mysql-test/t/grant_cache.test14
-rw-r--r--mysql-test/t/greedy_optimizer.test313
-rw-r--r--mysql-test/t/group_by.test51
-rw-r--r--mysql-test/t/group_min_max.test700
-rw-r--r--mysql-test/t/having.test197
-rw-r--r--mysql-test/t/heap.test253
-rw-r--r--mysql-test/t/heap_btree.test2
-rw-r--r--mysql-test/t/heap_hash.test2
-rw-r--r--mysql-test/t/index_merge.test329
-rw-r--r--mysql-test/t/index_merge_bdb.test52
-rw-r--r--mysql-test/t/index_merge_innodb.test206
-rw-r--r--mysql-test/t/index_merge_innodb2.test52
-rw-r--r--mysql-test/t/index_merge_ror.test252
-rw-r--r--mysql-test/t/index_merge_ror_cpk.test111
-rw-r--r--mysql-test/t/information_schema.test716
-rw-r--r--mysql-test/t/information_schema_db.test11
-rw-r--r--mysql-test/t/information_schema_inno.test23
-rw-r--r--mysql-test/t/init_connect.test2
-rw-r--r--mysql-test/t/innodb-big.test46
-rw-r--r--mysql-test/t/innodb.test264
-rw-r--r--mysql-test/t/insert.test46
-rw-r--r--mysql-test/t/insert_select.test16
-rw-r--r--mysql-test/t/insert_update.test2
-rw-r--r--mysql-test/t/isam.test249
-rw-r--r--mysql-test/t/join.test7
-rw-r--r--mysql-test/t/join_crash.test15
-rw-r--r--mysql-test/t/join_nested.test803
-rw-r--r--mysql-test/t/join_outer.test130
-rw-r--r--mysql-test/t/key.test38
-rw-r--r--mysql-test/t/key_cache.test7
-rw-r--r--mysql-test/t/keywords.test8
-rw-r--r--mysql-test/t/kill.test21
-rw-r--r--mysql-test/t/limit.test2
-rw-r--r--mysql-test/t/loaddata.test46
-rw-r--r--mysql-test/t/lock.test2
-rw-r--r--mysql-test/t/lock_multi.test11
-rw-r--r--mysql-test/t/lowercase_table.test1
-rw-r--r--mysql-test/t/lowercase_table3.test10
-rw-r--r--mysql-test/t/lowercase_view-master.opt1
-rw-r--r--mysql-test/t/lowercase_view.test140
-rw-r--r--mysql-test/t/merge.test6
-rw-r--r--mysql-test/t/mix_innodb_myisam_binlog.test47
-rw-r--r--mysql-test/t/multi_update.test77
-rw-r--r--mysql-test/t/myisam.test145
-rw-r--r--mysql-test/t/mysql.test43
-rw-r--r--mysql-test/t/mysql_delimiter.sql51
-rw-r--r--mysql-test/t/mysql_delimiter_source.sql8
-rw-r--r--mysql-test/t/mysqlbinlog.test15
-rw-r--r--mysql-test/t/mysqlbinlog2.test16
-rw-r--r--mysql-test/t/mysqldump.test301
-rw-r--r--mysql-test/t/mysqlshow.test23
-rw-r--r--mysql-test/t/mysqltest.test49
-rw-r--r--mysql-test/t/ndb_alter_table.test5
-rw-r--r--mysql-test/t/ndb_autodiscover.test45
-rw-r--r--mysql-test/t/ndb_basic.test10
-rw-r--r--mysql-test/t/ndb_bitfield.test114
-rw-r--r--mysql-test/t/ndb_cache.test106
-rw-r--r--mysql-test/t/ndb_cache2.test361
-rw-r--r--mysql-test/t/ndb_cache_multi.test65
-rw-r--r--mysql-test/t/ndb_cache_multi2.test82
-rw-r--r--mysql-test/t/ndb_charset.test80
-rw-r--r--mysql-test/t/ndb_condition_pushdown.test1643
-rw-r--r--mysql-test/t/ndb_config.test1
-rw-r--r--mysql-test/t/ndb_grant.later13
-rw-r--r--mysql-test/t/ndb_index_ordered.test37
-rw-r--r--mysql-test/t/ndb_index_unique.test10
-rw-r--r--mysql-test/t/ndb_read_multi_range.test202
-rw-r--r--mysql-test/t/ndb_restore.test1
-rw-r--r--mysql-test/t/ndb_subquery.test24
-rw-r--r--mysql-test/t/ndb_types.test21
-rw-r--r--mysql-test/t/null.test9
-rw-r--r--mysql-test/t/null_key.test2
-rw-r--r--mysql-test/t/olap.test52
-rw-r--r--mysql-test/t/openssl_1.test8
-rw-r--r--mysql-test/t/order_by.test20
-rw-r--r--mysql-test/t/ps.test156
-rw-r--r--mysql-test/t/ps_1general.test46
-rw-r--r--mysql-test/t/ps_4heap.test10
-rw-r--r--mysql-test/t/ps_5merge.test8
-rw-r--r--mysql-test/t/ps_grant.test16
-rw-r--r--mysql-test/t/query_cache.test111
-rw-r--r--mysql-test/t/range.test107
-rw-r--r--mysql-test/t/replace.test8
-rw-r--r--mysql-test/t/row.test10
-rw-r--r--mysql-test/t/rowid_order_bdb.test108
-rw-r--r--mysql-test/t/rowid_order_innodb.test108
-rw-r--r--mysql-test/t/rpl000001.test23
-rw-r--r--mysql-test/t/rpl000010-slave.opt2
-rw-r--r--mysql-test/t/rpl000015.test10
-rw-r--r--mysql-test/t/rpl000017.test2
-rw-r--r--mysql-test/t/rpl000018.test2
-rw-r--r--mysql-test/t/rpl_EE_error.test2
-rw-r--r--mysql-test/t/rpl_auto_increment-master.opt1
-rw-r--r--mysql-test/t/rpl_auto_increment.test104
-rw-r--r--mysql-test/t/rpl_change_master.test23
-rw-r--r--mysql-test/t/rpl_charset.test45
-rw-r--r--mysql-test/t/rpl_create_database.test1
-rw-r--r--mysql-test/t/rpl_ddl.test57
-rw-r--r--mysql-test/t/rpl_deadlock.test4
-rw-r--r--mysql-test/t/rpl_delete_all.test2
-rw-r--r--mysql-test/t/rpl_empty_master_crash.test2
-rw-r--r--mysql-test/t/rpl_error_ignored_table.test6
-rw-r--r--mysql-test/t/rpl_flush_log_loop.test2
-rw-r--r--mysql-test/t/rpl_flush_tables.test3
-rw-r--r--mysql-test/t/rpl_get_lock.test7
-rw-r--r--mysql-test/t/rpl_heap.test2
-rw-r--r--mysql-test/t/rpl_loaddata.test38
-rw-r--r--mysql-test/t/rpl_loaddata_rule_m.test7
-rw-r--r--mysql-test/t/rpl_loaddata_rule_s.test2
-rw-r--r--mysql-test/t/rpl_loaddatalocal.test24
-rw-r--r--mysql-test/t/rpl_log.test10
-rw-r--r--mysql-test/t/rpl_log_pos.test10
-rw-r--r--mysql-test/t/rpl_max_relay_size.test13
-rw-r--r--mysql-test/t/rpl_multi_query.test3
-rw-r--r--mysql-test/t/rpl_openssl.test6
-rw-r--r--mysql-test/t/rpl_redirect.test2
-rw-r--r--mysql-test/t/rpl_relayrotate-slave.opt3
-rw-r--r--mysql-test/t/rpl_relayrotate.test6
-rw-r--r--mysql-test/t/rpl_replicate_do.test2
-rw-r--r--mysql-test/t/rpl_reset_slave.test9
-rw-r--r--mysql-test/t/rpl_rotate_logs.test11
-rw-r--r--mysql-test/t/rpl_session_var.test42
-rw-r--r--mysql-test/t/rpl_sp-master.opt1
-rw-r--r--mysql-test/t/rpl_sp-slave.opt1
-rw-r--r--mysql-test/t/rpl_sp.test266
-rw-r--r--mysql-test/t/rpl_sp_effects-master.opt1
-rw-r--r--mysql-test/t/rpl_sp_effects-slave.opt1
-rw-r--r--mysql-test/t/rpl_sp_effects.test203
-rw-r--r--mysql-test/t/rpl_temporary.test1
-rw-r--r--mysql-test/t/rpl_timezone-slave.opt2
-rw-r--r--mysql-test/t/rpl_timezone.test62
-rw-r--r--mysql-test/t/rpl_trigger.test118
-rw-r--r--mysql-test/t/rpl_trunc_binlog.test27
-rw-r--r--mysql-test/t/rpl_until.test21
-rw-r--r--mysql-test/t/rpl_user_variables.test3
-rw-r--r--mysql-test/t/rpl_variables-master.opt1
-rw-r--r--mysql-test/t/rpl_variables.test8
-rw-r--r--mysql-test/t/rpl_view.test47
-rw-r--r--mysql-test/t/schema.test8
-rw-r--r--mysql-test/t/select.test382
-rw-r--r--mysql-test/t/select_safe.test3
-rw-r--r--mysql-test/t/show_check.test61
-rw-r--r--mysql-test/t/skip_grants-master.opt1
-rw-r--r--mysql-test/t/skip_grants.test21
-rw-r--r--mysql-test/t/sp-big.test33
-rw-r--r--mysql-test/t/sp-dynamic.test335
-rw-r--r--mysql-test/t/sp-error.test1197
-rw-r--r--mysql-test/t/sp-goto.test238
-rw-r--r--mysql-test/t/sp-prelocking.test242
-rw-r--r--mysql-test/t/sp-security.test415
-rw-r--r--mysql-test/t/sp-threads.test183
-rw-r--r--mysql-test/t/sp.test4221
-rw-r--r--mysql-test/t/sp_trans.test186
-rw-r--r--mysql-test/t/sql_mode.test156
-rw-r--r--mysql-test/t/strict.test1147
-rw-r--r--mysql-test/t/subselect.test156
-rw-r--r--mysql-test/t/sum_distinct-big.test67
-rw-r--r--mysql-test/t/sum_distinct.test95
-rw-r--r--mysql-test/t/symlink.test8
-rw-r--r--mysql-test/t/synchronization.test7
-rw-r--r--mysql-test/t/system_mysql_db.test5
-rw-r--r--mysql-test/t/system_mysql_db_fix.test10
-rw-r--r--mysql-test/t/temp_table.test14
-rw-r--r--mysql-test/t/timezone2.test7
-rw-r--r--mysql-test/t/timezone_grant.test4
-rw-r--r--mysql-test/t/trigger.test877
-rw-r--r--mysql-test/t/type_bit.test226
-rw-r--r--mysql-test/t/type_bit_innodb.test135
-rw-r--r--mysql-test/t/type_blob.test31
-rw-r--r--mysql-test/t/type_decimal.test105
-rw-r--r--mysql-test/t/type_float.test7
-rw-r--r--mysql-test/t/type_newdecimal.test1046
-rw-r--r--mysql-test/t/type_ranges.test21
-rw-r--r--mysql-test/t/type_timestamp.test2
-rw-r--r--mysql-test/t/type_varchar.test132
-rw-r--r--mysql-test/t/union.test38
-rw-r--r--mysql-test/t/update.test4
-rw-r--r--mysql-test/t/user_limits.test169
-rw-r--r--mysql-test/t/user_var-binlog.test2
-rw-r--r--mysql-test/t/user_var.test29
-rw-r--r--mysql-test/t/variables.test74
-rw-r--r--mysql-test/t/view.test2139
-rw-r--r--mysql-test/t/view_grant.test408
-rw-r--r--mysql-test/t/view_query_cache.test87
-rw-r--r--mysql-test/t/warnings.test6
-rw-r--r--mysql-test/t/xa.test62
-rw-r--r--mysql-test/valgrind.supp134
-rw-r--r--mysys/Makefile.am19
-rw-r--r--mysys/charset-def.c9
-rw-r--r--mysys/charset.c183
-rw-r--r--mysys/default.c640
-rw-r--r--mysys/default_modify.c228
-rw-r--r--mysys/errors.c10
-rw-r--r--mysys/hash.c5
-rw-r--r--mysys/list.c2
-rw-r--r--mysys/mf_format.c2
-rw-r--r--mysys/mf_getdate.c42
-rw-r--r--mysys/mf_iocache.c21
-rw-r--r--mysys/mf_iocache2.c7
-rw-r--r--mysys/mf_keycache.c12
-rw-r--r--mysys/my_access.c2
-rw-r--r--mysys/my_alloc.c44
-rw-r--r--mysys/my_bit.c5
-rw-r--r--mysys/my_bitmap.c147
-rw-r--r--mysys/my_chsize.c14
-rw-r--r--mysys/my_copy.c18
-rw-r--r--mysys/my_error.c266
-rw-r--r--mysys/my_getopt.c31
-rw-r--r--mysys/my_handler.c25
-rw-r--r--mysys/my_init.c4
-rw-r--r--mysys/my_largepage.c167
-rw-r--r--mysys/my_mmap.c91
-rw-r--r--mysys/my_new.cc9
-rw-r--r--mysys/my_once.c2
-rw-r--r--mysys/my_open.c9
-rw-r--r--mysys/my_os2cond.c2
-rw-r--r--mysys/my_static.c11
-rw-r--r--mysys/my_sync.c32
-rw-r--r--mysys/my_tempnam.c173
-rw-r--r--mysys/my_thr_init.c11
-rw-r--r--mysys/ptr_cmp.c39
-rw-r--r--mysys/raid.cc14
-rw-r--r--mysys/string.c2
-rw-r--r--mysys/thr_lock.c223
-rw-r--r--mysys/tree.c3
-rw-r--r--ndb/Makefile.am3
-rw-r--r--ndb/docs/Makefile.am36
-rw-r--r--ndb/docs/doxygen/Doxyfile.mgmapi15
-rw-r--r--ndb/docs/doxygen/Doxyfile.ndb26
-rw-r--r--ndb/docs/doxygen/Doxyfile.ndbapi16
-rw-r--r--ndb/docs/doxygen/Doxyfile.odbc14
-rw-r--r--ndb/docs/doxygen/Doxyfile.test14
-rwxr-xr-xndb/docs/doxygen/predoxy.pl2
-rw-r--r--ndb/examples/configurations/demos.tarbin40960 -> 0 bytes
-rw-r--r--ndb/examples/ndbapi_async_example/Makefile34
-rw-r--r--ndb/examples/ndbapi_example1/Makefile33
-rw-r--r--ndb/examples/ndbapi_example1/ndbapi_example1.cpp194
-rw-r--r--ndb/examples/ndbapi_example2/Makefile33
-rw-r--r--ndb/examples/ndbapi_example3/Makefile33
-rw-r--r--ndb/examples/ndbapi_example4/Makefile33
-rw-r--r--ndb/examples/ndbapi_example4/ndbapi_example4.cpp253
-rw-r--r--ndb/examples/ndbapi_example5/Makefile33
-rw-r--r--ndb/examples/ndbapi_scan_example/Makefile35
-rw-r--r--ndb/examples/select_all/Makefile33
-rw-r--r--ndb/examples/select_all/select_all.cpp259
-rw-r--r--ndb/include/Makefile.am11
-rw-r--r--ndb/include/debugger/EventLogger.hpp29
-rw-r--r--ndb/include/debugger/SignalLoggerManager.hpp2
-rw-r--r--ndb/include/kernel/AttributeDescriptor.hpp89
-rw-r--r--ndb/include/kernel/AttributeHeader.hpp10
-rw-r--r--ndb/include/kernel/AttributeList.hpp2
-rw-r--r--ndb/include/kernel/LogLevel.hpp4
-rw-r--r--ndb/include/kernel/NodeInfo.hpp2
-rw-r--r--ndb/include/kernel/ndb_limits.h15
-rw-r--r--ndb/include/kernel/signaldata/AccScan.hpp34
-rw-r--r--ndb/include/kernel/signaldata/CreateEvnt.hpp15
-rw-r--r--ndb/include/kernel/signaldata/CreateIndx.hpp3
-rw-r--r--ndb/include/kernel/signaldata/CreateTable.hpp1
-rw-r--r--ndb/include/kernel/signaldata/DictTabInfo.hpp220
-rw-r--r--ndb/include/kernel/signaldata/EventReport.hpp88
-rw-r--r--ndb/include/kernel/signaldata/GetTabInfo.hpp32
-rw-r--r--ndb/include/kernel/signaldata/NextScan.hpp2
-rw-r--r--ndb/include/kernel/signaldata/ScanFrag.hpp36
-rw-r--r--ndb/include/kernel/signaldata/ScanTab.hpp73
-rw-r--r--ndb/include/kernel/signaldata/SignalData.hpp11
-rw-r--r--ndb/include/kernel/signaldata/SumaImpl.hpp2
-rw-r--r--ndb/include/kernel/signaldata/TcCommit.hpp7
-rw-r--r--ndb/include/kernel/signaldata/TcHbRep.hpp2
-rw-r--r--ndb/include/kernel/signaldata/TcIndx.hpp406
-rw-r--r--ndb/include/kernel/signaldata/TcKeyConf.hpp2
-rw-r--r--ndb/include/kernel/signaldata/TcKeyFailConf.hpp2
-rw-r--r--ndb/include/kernel/signaldata/TcKeyReq.hpp16
-rw-r--r--ndb/include/kernel/signaldata/TcRollbackRep.hpp2
-rwxr-xr-xndb/include/kernel/signaldata/TransIdAI.hpp2
-rw-r--r--ndb/include/kernel/signaldata/TupFrag.hpp15
-rw-r--r--ndb/include/kernel/signaldata/TuxBound.hpp6
-rw-r--r--ndb/include/kernel/trigger_definitions.h1
-rw-r--r--ndb/include/mgmapi/mgmapi.h895
-rw-r--r--ndb/include/mgmapi/mgmapi_config_parameters.h2
-rw-r--r--ndb/include/mgmapi/mgmapi_debug.h1
-rw-r--r--ndb/include/mgmapi/ndb_logevent.h618
-rw-r--r--ndb/include/mgmcommon/ConfigRetriever.hpp3
-rw-r--r--ndb/include/ndb_constants.h72
-rw-r--r--ndb/include/ndb_global.h.in33
-rw-r--r--ndb/include/ndb_types.h.in81
-rw-r--r--ndb/include/ndbapi/Ndb.hpp1554
-rw-r--r--ndb/include/ndbapi/NdbApi.hpp3
-rw-r--r--ndb/include/ndbapi/NdbBlob.hpp47
-rw-r--r--ndb/include/ndbapi/NdbDictionary.hpp917
-rw-r--r--ndb/include/ndbapi/NdbError.hpp11
-rw-r--r--ndb/include/ndbapi/NdbEventOperation.hpp144
-rw-r--r--ndb/include/ndbapi/NdbIndexOperation.hpp53
-rw-r--r--ndb/include/ndbapi/NdbIndexScanOperation.hpp80
-rw-r--r--ndb/include/ndbapi/NdbOperation.hpp219
-rw-r--r--ndb/include/ndbapi/NdbRecAttr.hpp41
-rw-r--r--ndb/include/ndbapi/NdbReceiver.hpp14
-rw-r--r--ndb/include/ndbapi/NdbResultSet.hpp162
-rw-r--r--ndb/include/ndbapi/NdbScanFilter.hpp73
-rw-r--r--ndb/include/ndbapi/NdbScanOperation.hpp204
-rw-r--r--ndb/include/ndbapi/NdbTransaction.hpp (renamed from ndb/include/ndbapi/NdbConnection.hpp)412
-rw-r--r--ndb/include/ndbapi/ndb_cluster_connection.hpp52
-rw-r--r--ndb/include/ndbapi/ndb_opt_defaults.h4
-rw-r--r--ndb/include/ndbapi/ndbapi_limits.h4
-rw-r--r--ndb/include/ndbapi/ndberror.h7
-rw-r--r--ndb/include/portlib/NdbTCP.h2
-rw-r--r--ndb/include/transporter/TransporterCallback.hpp3
-rw-r--r--ndb/include/transporter/TransporterDefinitions.hpp98
-rw-r--r--ndb/include/transporter/TransporterRegistry.hpp46
-rw-r--r--ndb/include/util/Base64.hpp1
-rw-r--r--ndb/include/util/Bitmask.hpp57
-rw-r--r--ndb/include/util/NdbSqlUtil.hpp145
-rw-r--r--ndb/include/util/SimpleProperties.hpp4
-rw-r--r--ndb/include/util/SocketClient.hpp6
-rw-r--r--ndb/include/util/SocketServer.hpp2
-rw-r--r--ndb/include/util/Vector.hpp8
-rw-r--r--ndb/include/util/md5_hash.hpp11
-rw-r--r--ndb/include/util/ndb_opts.h66
-rw-r--r--ndb/ndbapi-examples/Makefile (renamed from ndb/examples/Makefile)18
-rw-r--r--ndb/ndbapi-examples/mgmapi_logevent_example/Makefile23
-rw-r--r--ndb/ndbapi-examples/mgmapi_logevent_example/mgmapi_logevent.cpp140
-rw-r--r--ndb/ndbapi-examples/ndbapi_async_example/Makefile23
-rw-r--r--ndb/ndbapi-examples/ndbapi_async_example/ndbapi_async.cpp (renamed from ndb/examples/ndbapi_async_example/ndbapi_async.cpp)194
-rw-r--r--ndb/ndbapi-examples/ndbapi_async_example/readme.txt (renamed from ndb/examples/ndbapi_async_example/readme.txt)0
-rw-r--r--ndb/ndbapi-examples/ndbapi_async_example1/Makefile21
-rw-r--r--ndb/ndbapi-examples/ndbapi_async_example1/ndbapi_async1.cpp (renamed from ndb/examples/ndbapi_example2/ndbapi_example2.cpp)75
-rw-r--r--ndb/ndbapi-examples/ndbapi_event_example/Makefile23
-rw-r--r--ndb/ndbapi-examples/ndbapi_event_example/ndbapi_event.cpp (renamed from ndb/examples/ndbapi_example5/ndbapi_example5.cpp)210
-rw-r--r--ndb/ndbapi-examples/ndbapi_retries_example/Makefile21
-rw-r--r--ndb/ndbapi-examples/ndbapi_retries_example/ndbapi_retries.cpp (renamed from ndb/examples/ndbapi_example3/ndbapi_example3.cpp)107
-rw-r--r--ndb/ndbapi-examples/ndbapi_scan_example/Makefile23
-rw-r--r--ndb/ndbapi-examples/ndbapi_scan_example/ndbapi_scan.cpp (renamed from ndb/examples/ndbapi_scan_example/ndbapi_scan.cpp)587
-rw-r--r--ndb/ndbapi-examples/ndbapi_scan_example/readme.txt (renamed from ndb/examples/ndbapi_scan_example/readme.txt)0
-rw-r--r--ndb/ndbapi-examples/ndbapi_simple_example/Makefile23
-rw-r--r--ndb/ndbapi-examples/ndbapi_simple_example/ndbapi_simple.cpp278
-rw-r--r--ndb/ndbapi-examples/ndbapi_simple_index_example/Makefile23
-rw-r--r--ndb/ndbapi-examples/ndbapi_simple_index_example/ndbapi_simple_index.cpp254
-rw-r--r--ndb/src/Makefile.am2
-rw-r--r--ndb/src/common/debugger/EventLogger.cpp1967
-rw-r--r--ndb/src/common/debugger/SignalLoggerManager.cpp9
-rw-r--r--ndb/src/common/debugger/signaldata/DictTabInfo.cpp24
-rw-r--r--ndb/src/common/debugger/signaldata/ScanTab.cpp12
-rw-r--r--ndb/src/common/debugger/signaldata/SignalDataPrint.cpp13
-rw-r--r--ndb/src/common/debugger/signaldata/SignalNames.cpp3
-rw-r--r--ndb/src/common/debugger/signaldata/SumaImpl.cpp76
-rw-r--r--ndb/src/common/debugger/signaldata/TcIndx.cpp85
-rw-r--r--ndb/src/common/debugger/signaldata/TcKeyReq.cpp5
-rw-r--r--ndb/src/common/mgmcommon/ConfigRetriever.cpp6
-rw-r--r--ndb/src/common/mgmcommon/IPCConfig.cpp387
-rw-r--r--ndb/src/common/portlib/NdbTCP.cpp47
-rw-r--r--ndb/src/common/portlib/gcc.cpp2
-rw-r--r--ndb/src/common/portlib/win32/NdbTCP.c32
-rw-r--r--ndb/src/common/transporter/Makefile.am2
-rw-r--r--ndb/src/common/transporter/OSE_Transporter.cpp2
-rw-r--r--ndb/src/common/transporter/OSE_Transporter.hpp1
-rw-r--r--ndb/src/common/transporter/Packer.cpp1
-rw-r--r--ndb/src/common/transporter/SCI_Transporter.cpp8
-rw-r--r--ndb/src/common/transporter/SCI_Transporter.hpp4
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.cpp7
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.hpp4
-rw-r--r--ndb/src/common/transporter/TCP_Transporter.cpp5
-rw-r--r--ndb/src/common/transporter/TCP_Transporter.hpp4
-rw-r--r--ndb/src/common/transporter/Transporter.cpp47
-rw-r--r--ndb/src/common/transporter/Transporter.hpp31
-rw-r--r--ndb/src/common/transporter/TransporterRegistry.cpp319
-rw-r--r--ndb/src/common/util/Base64.cpp13
-rw-r--r--ndb/src/common/util/Bitmask.cpp351
-rw-r--r--ndb/src/common/util/Makefile.am19
-rw-r--r--ndb/src/common/util/NdbSqlUtil.cpp1127
-rw-r--r--ndb/src/common/util/SimpleProperties.cpp34
-rw-r--r--ndb/src/common/util/SocketServer.cpp38
-rw-r--r--ndb/src/common/util/md5_hash.cpp20
-rw-r--r--ndb/src/common/util/new.cpp2
-rw-r--r--ndb/src/common/util/version.c4
-rw-r--r--ndb/src/cw/cpcd/APIService.cpp15
-rw-r--r--ndb/src/cw/cpcd/APIService.hpp1
-rw-r--r--ndb/src/cw/cpcd/main.cpp3
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt8
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp28
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.hpp3
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp17
-rw-r--r--ndb/src/kernel/blocks/dbacc/Dbacc.hpp157
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccInit.cpp77
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccMain.cpp2494
-rw-r--r--ndb/src/kernel/blocks/dbacc/Makefile.am2
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp665
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.hpp62
-rw-r--r--ndb/src/kernel/blocks/dbdict/SchemaFile.hpp44
-rw-r--r--ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp206
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp255
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp35
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhInit.cpp2
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp700
-rw-r--r--ndb/src/kernel/blocks/dbtc/Dbtc.hpp31
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp305
-rw-r--r--ndb/src/kernel/blocks/dbtup/Dbtup.hpp82
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp117
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupGen.cpp18
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp26
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp53
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp357
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupScan.cpp315
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp8
-rw-r--r--ndb/src/kernel/blocks/dbtup/Makefile.am1
-rw-r--r--ndb/src/kernel/blocks/dbtux/Dbtux.hpp15
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp44
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp6
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp23
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp5
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp12
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp240
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp124
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp3
-rw-r--r--ndb/src/kernel/blocks/dbtux/Times.txt10
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp16
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp61
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp3
-rw-r--r--ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp4
-rw-r--r--ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp12
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp25
-rw-r--r--ndb/src/kernel/blocks/qmgr/Qmgr.hpp5
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrInit.cpp3
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrMain.cpp87
-rw-r--r--ndb/src/kernel/blocks/suma/Suma.cpp142
-rw-r--r--ndb/src/kernel/blocks/suma/Suma.hpp2
-rw-r--r--ndb/src/kernel/main.cpp18
-rw-r--r--ndb/src/kernel/vm/Configuration.cpp19
-rw-r--r--ndb/src/kernel/vm/Configuration.hpp6
-rw-r--r--ndb/src/kernel/vm/FastScheduler.cpp2
-rw-r--r--ndb/src/kernel/vm/KeyDescriptor.hpp (renamed from ndb/include/ndbapi/NdbCursorOperation.hpp)25
-rw-r--r--ndb/src/kernel/vm/MetaData.hpp7
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.cpp119
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.hpp20
-rw-r--r--ndb/src/kernel/vm/SuperPool.cpp442
-rw-r--r--ndb/src/kernel/vm/SuperPool.hpp561
-rw-r--r--ndb/src/kernel/vm/TransporterCallback.cpp14
-rw-r--r--ndb/src/kernel/vm/VMSignal.hpp10
-rw-r--r--ndb/src/kernel/vm/testSuperPool.cpp220
-rw-r--r--ndb/src/mgmapi/LocalConfig.cpp57
-rw-r--r--ndb/src/mgmapi/Makefile.am2
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp382
-rw-r--r--ndb/src/mgmapi/mgmapi_configuration.hpp16
-rw-r--r--ndb/src/mgmapi/mgmapi_internal.h77
-rw-r--r--ndb/src/mgmapi/ndb_logevent.cpp501
-rw-r--r--ndb/src/mgmapi/ndb_logevent.hpp (renamed from isam/changed.c)31
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.cpp59
-rw-r--r--ndb/src/mgmclient/main.cpp13
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.cpp345
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.hpp92
-rw-r--r--ndb/src/mgmsrv/ConfigInfo.cpp73
-rw-r--r--ndb/src/mgmsrv/Makefile.am13
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp255
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp13
-rw-r--r--ndb/src/mgmsrv/Services.cpp140
-rw-r--r--ndb/src/mgmsrv/Services.hpp9
-rw-r--r--ndb/src/mgmsrv/main.cpp131
-rw-r--r--ndb/src/ndbapi/ClusterMgr.cpp39
-rw-r--r--ndb/src/ndbapi/ClusterMgr.hpp10
-rw-r--r--ndb/src/ndbapi/DictCache.cpp108
-rw-r--r--ndb/src/ndbapi/DictCache.hpp2
-rw-r--r--ndb/src/ndbapi/Makefile.am5
-rw-r--r--ndb/src/ndbapi/Ndb.cpp345
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.cpp2
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.hpp2
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp484
-rw-r--r--ndb/src/ndbapi/NdbCursorOperation.cpp51
-rw-r--r--ndb/src/ndbapi/NdbDictionary.cpp165
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp914
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.hpp143
-rw-r--r--ndb/src/ndbapi/NdbEventOperation.cpp20
-rw-r--r--ndb/src/ndbapi/NdbEventOperationImpl.cpp523
-rw-r--r--ndb/src/ndbapi/NdbEventOperationImpl.hpp31
-rw-r--r--ndb/src/ndbapi/NdbImpl.hpp19
-rw-r--r--ndb/src/ndbapi/NdbIndexOperation.cpp452
-rw-r--r--ndb/src/ndbapi/NdbLinHash.hpp5
-rw-r--r--ndb/src/ndbapi/NdbOperation.cpp47
-rw-r--r--ndb/src/ndbapi/NdbOperationDefine.cpp108
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp27
-rw-r--r--ndb/src/ndbapi/NdbOperationInt.cpp86
-rw-r--r--ndb/src/ndbapi/NdbOperationSearch.cpp363
-rw-r--r--ndb/src/ndbapi/NdbPool.cpp6
-rw-r--r--ndb/src/ndbapi/NdbPoolImpl.cpp13
-rw-r--r--ndb/src/ndbapi/NdbPoolImpl.hpp8
-rw-r--r--ndb/src/ndbapi/NdbRecAttr.cpp78
-rw-r--r--ndb/src/ndbapi/NdbReceiver.cpp29
-rw-r--r--ndb/src/ndbapi/NdbResultSet.cpp103
-rw-r--r--ndb/src/ndbapi/NdbScanFilter.cpp266
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp377
-rw-r--r--ndb/src/ndbapi/NdbTransaction.cpp (renamed from ndb/src/ndbapi/NdbConnection.cpp)439
-rw-r--r--ndb/src/ndbapi/NdbTransactionScan.cpp (renamed from ndb/src/ndbapi/NdbConnectionScan.cpp)18
-rw-r--r--ndb/src/ndbapi/Ndberr.cpp13
-rw-r--r--ndb/src/ndbapi/Ndbif.cpp178
-rw-r--r--ndb/src/ndbapi/Ndbinit.cpp85
-rw-r--r--ndb/src/ndbapi/Ndblist.cpp53
-rw-r--r--ndb/src/ndbapi/TransporterFacade.cpp65
-rw-r--r--ndb/src/ndbapi/TransporterFacade.hpp22
-rw-r--r--ndb/src/ndbapi/ndb_cluster_connection.cpp163
-rw-r--r--ndb/src/ndbapi/ndb_cluster_connection_impl.hpp18
-rw-r--r--ndb/src/ndbapi/ndberror.c55
-rw-r--r--ndb/test/include/HugoCalculator.hpp9
-rw-r--r--ndb/test/include/HugoOperations.hpp29
-rw-r--r--ndb/test/include/HugoTransactions.hpp8
-rw-r--r--ndb/test/include/NDBT_Error.hpp6
-rw-r--r--ndb/test/include/NDBT_ResultRow.hpp7
-rw-r--r--ndb/test/include/NDBT_Tables.hpp6
-rw-r--r--ndb/test/include/NDBT_Test.hpp22
-rw-r--r--ndb/test/include/NdbSchemaOp.hpp51
-rw-r--r--ndb/test/include/UtilTransactions.hpp30
-rw-r--r--ndb/test/ndbapi/Makefile.am12
-rw-r--r--ndb/test/ndbapi/ScanFunctions.hpp23
-rw-r--r--ndb/test/ndbapi/ScanInterpretTest.hpp17
-rw-r--r--ndb/test/ndbapi/bank/Bank.cpp64
-rw-r--r--ndb/test/ndbapi/bank/Bank.hpp2
-rw-r--r--ndb/test/ndbapi/bank/BankLoad.cpp11
-rw-r--r--ndb/test/ndbapi/bank/bankCreator.cpp8
-rw-r--r--ndb/test/ndbapi/bank/bankMakeGL.cpp8
-rw-r--r--ndb/test/ndbapi/bank/bankSumAccounts.cpp8
-rw-r--r--ndb/test/ndbapi/bank/bankTimer.cpp8
-rw-r--r--ndb/test/ndbapi/bank/bankTransactionMaker.cpp8
-rw-r--r--ndb/test/ndbapi/bank/bankValidateAllGLs.cpp8
-rw-r--r--ndb/test/ndbapi/bank/testBank.cpp12
-rw-r--r--ndb/test/ndbapi/bench/userInterface.cpp6
-rw-r--r--ndb/test/ndbapi/bench/userInterface.h2
-rw-r--r--ndb/test/ndbapi/create_all_tabs.cpp7
-rw-r--r--ndb/test/ndbapi/create_tab.cpp8
-rw-r--r--ndb/test/ndbapi/drop_all_tabs.cpp8
-rw-r--r--ndb/test/ndbapi/flexAsynch.cpp16
-rw-r--r--ndb/test/ndbapi/flexBench.cpp15
-rw-r--r--ndb/test/ndbapi/flexHammer.cpp13
-rw-r--r--ndb/test/ndbapi/flexTT.cpp13
-rw-r--r--ndb/test/ndbapi/flex_bench_mysql.cpp2
-rw-r--r--ndb/test/ndbapi/slow_select.cpp28
-rw-r--r--ndb/test/ndbapi/testBackup.cpp16
-rw-r--r--ndb/test/ndbapi/testBitfield.cpp198
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp37
-rw-r--r--ndb/test/ndbapi/testDataBuffers.cpp21
-rw-r--r--ndb/test/ndbapi/testDeadlock.cpp27
-rw-r--r--ndb/test/ndbapi/testDict.cpp171
-rw-r--r--ndb/test/ndbapi/testIndex.cpp19
-rw-r--r--ndb/test/ndbapi/testLcp.cpp12
-rw-r--r--ndb/test/ndbapi/testNdbApi.cpp209
-rw-r--r--ndb/test/ndbapi/testNodeRestart.cpp2
-rw-r--r--ndb/test/ndbapi/testOIBasic.cpp2770
-rw-r--r--ndb/test/ndbapi/testPartitioning.cpp430
-rw-r--r--ndb/test/ndbapi/testReadPerf.cpp32
-rw-r--r--ndb/test/ndbapi/testSRBank.cpp14
-rw-r--r--ndb/test/ndbapi/testScan.cpp77
-rw-r--r--ndb/test/ndbapi/testScanPerf.cpp105
-rw-r--r--ndb/test/ndbapi/testTimeout.cpp62
-rw-r--r--ndb/test/ndbapi/test_event.cpp390
-rw-r--r--ndb/test/ndbapi/test_event_multi_table.cpp487
-rw-r--r--ndb/test/run-test/16node-tests.txt733
-rw-r--r--ndb/test/run-test/Makefile.am2
-rw-r--r--ndb/test/run-test/basic.txt2
-rw-r--r--ndb/test/run-test/daily-basic-tests.txt95
-rw-r--r--ndb/test/run-test/daily-devel-tests.txt31
-rw-r--r--ndb/test/src/HugoAsynchTransactions.cpp11
-rw-r--r--ndb/test/src/HugoCalculator.cpp298
-rw-r--r--ndb/test/src/HugoOperations.cpp360
-rw-r--r--ndb/test/src/HugoTransactions.cpp843
-rw-r--r--ndb/test/src/NDBT_ResultRow.cpp9
-rw-r--r--ndb/test/src/NDBT_Tables.cpp19
-rw-r--r--ndb/test/src/NDBT_Test.cpp50
-rw-r--r--ndb/test/src/NdbBackup.cpp2
-rw-r--r--ndb/test/src/NdbRestarts.cpp30
-rw-r--r--ndb/test/src/NdbSchemaOp.cpp3
-rw-r--r--ndb/test/src/UtilTransactions.cpp755
-rw-r--r--ndb/test/tools/Makefile.am3
-rw-r--r--ndb/test/tools/copy_tab.cpp9
-rw-r--r--ndb/test/tools/create_index.cpp7
-rw-r--r--ndb/test/tools/hugoFill.cpp7
-rw-r--r--ndb/test/tools/hugoLoad.cpp7
-rw-r--r--ndb/test/tools/hugoLockRecords.cpp7
-rw-r--r--ndb/test/tools/hugoPkDelete.cpp7
-rw-r--r--ndb/test/tools/hugoPkRead.cpp7
-rw-r--r--ndb/test/tools/hugoPkReadRecord.cpp7
-rw-r--r--ndb/test/tools/hugoPkUpdate.cpp7
-rw-r--r--ndb/test/tools/hugoScanRead.cpp10
-rw-r--r--ndb/test/tools/hugoScanUpdate.cpp7
-rw-r--r--ndb/test/tools/verify_index.cpp7
-rw-r--r--ndb/tools/Makefile.am4
-rw-r--r--ndb/tools/delete_all.cpp47
-rw-r--r--ndb/tools/desc.cpp42
-rw-r--r--ndb/tools/drop_index.cpp31
-rw-r--r--ndb/tools/drop_tab.cpp31
-rw-r--r--ndb/tools/listTables.cpp24
-rw-r--r--ndb/tools/ndb_test_platform.cpp6
-rw-r--r--ndb/tools/restore/Restore.cpp15
-rw-r--r--ndb/tools/restore/consumer.cpp2
-rw-r--r--ndb/tools/restore/consumer_printer.hpp2
-rw-r--r--ndb/tools/restore/consumer_restore.cpp34
-rw-r--r--ndb/tools/restore/consumer_restore.hpp4
-rw-r--r--ndb/tools/restore/consumer_restorem.cpp17
-rw-r--r--ndb/tools/restore/restore_main.cpp18
-rw-r--r--ndb/tools/select_all.cpp68
-rw-r--r--ndb/tools/select_count.cpp50
-rw-r--r--ndb/tools/waiter.cpp15
-rwxr-xr-xnetware/BUILD/compile-linux-tools8
-rwxr-xr-xnetware/BUILD/compile-netware-END5
-rwxr-xr-xnetware/BUILD/compile-netware-START2
-rwxr-xr-xnetware/BUILD/mwenv6
-rwxr-xr-xnetware/BUILD/nwbootstrap4
-rw-r--r--netware/Makefile.am6
-rw-r--r--netware/my_manage.c4
-rw-r--r--netware/my_manage.h34
-rw-r--r--netware/my_print_defaults.def3
-rw-r--r--netware/mysql_test_run.c9
-rw-r--r--netware/mysqladmin.def1
-rw-r--r--netware/mysqld_safe.c2
-rw-r--r--os2/ChangeLog.os23
-rw-r--r--os2/MySQL-Source.icc24
-rw-r--r--os2/MySQL-Sql.icc2
-rw-r--r--os2/MySQL-Util.icc12
-rw-r--r--regex/Makefile.am3
-rw-r--r--regex/engine.c2
-rw-r--r--regex/main.c2
-rw-r--r--scripts/Makefile.am2
-rw-r--r--scripts/fill_func_tables.sh8
-rw-r--r--scripts/make_binary_distribution.sh62
-rw-r--r--scripts/make_win_src_distribution.sh24
-rw-r--r--scripts/mysql_create_system_tables.sh131
-rw-r--r--scripts/mysql_fix_privilege_tables.sh47
-rw-r--r--scripts/mysql_fix_privilege_tables.sql230
-rw-r--r--scripts/mysql_install_db.sh2
-rw-r--r--scripts/mysql_tableinfo.sh32
-rw-r--r--scripts/mysqld_multi.sh74
-rw-r--r--scripts/mysqld_safe.sh54
-rw-r--r--server-tools/Makefile.am1
-rw-r--r--server-tools/instance-manager/IMService.cpp82
-rw-r--r--server-tools/instance-manager/IMService.h14
-rw-r--r--server-tools/instance-manager/Makefile.am95
-rw-r--r--server-tools/instance-manager/README11
-rw-r--r--server-tools/instance-manager/WindowsService.cpp203
-rw-r--r--server-tools/instance-manager/WindowsService.h43
-rw-r--r--server-tools/instance-manager/buffer.cc109
-rw-r--r--server-tools/instance-manager/buffer.h66
-rw-r--r--server-tools/instance-manager/command.cc (renamed from ndb/include/ndb_types.h)20
-rw-r--r--server-tools/instance-manager/command.h47
-rw-r--r--server-tools/instance-manager/commands.cc794
-rw-r--r--server-tools/instance-manager/commands.h215
-rw-r--r--server-tools/instance-manager/guardian.cc439
-rw-r--r--server-tools/instance-manager/guardian.h127
-rw-r--r--server-tools/instance-manager/instance.cc594
-rw-r--r--server-tools/instance-manager/instance.h69
-rw-r--r--server-tools/instance-manager/instance_map.cc270
-rw-r--r--server-tools/instance-manager/instance_map.h87
-rw-r--r--server-tools/instance-manager/instance_options.cc537
-rw-r--r--server-tools/instance-manager/instance_options.h106
-rw-r--r--server-tools/instance-manager/listener.cc392
-rw-r--r--server-tools/instance-manager/listener.h56
-rw-r--r--server-tools/instance-manager/log.cc169
-rw-r--r--server-tools/instance-manager/log.h81
-rw-r--r--server-tools/instance-manager/manager.cc263
-rw-r--r--server-tools/instance-manager/manager.h (renamed from merge/mrg_static.c)15
-rw-r--r--server-tools/instance-manager/messages.cc89
-rw-r--r--server-tools/instance-manager/messages.h (renamed from merge/mrg_def.h)18
-rw-r--r--server-tools/instance-manager/mysql_connection.cc389
-rw-r--r--server-tools/instance-manager/mysql_connection.h54
-rw-r--r--server-tools/instance-manager/mysql_manager_error.h33
-rw-r--r--server-tools/instance-manager/mysqlmanager.cc361
-rw-r--r--server-tools/instance-manager/mysqlmanager.vcproj373
-rw-r--r--server-tools/instance-manager/options.cc321
-rw-r--r--server-tools/instance-manager/options.h60
-rw-r--r--server-tools/instance-manager/parse.cc323
-rw-r--r--server-tools/instance-manager/parse.h65
-rw-r--r--server-tools/instance-manager/parse_output.cc117
-rw-r--r--server-tools/instance-manager/parse_output.h (renamed from merge/mrg_delete.c)21
-rw-r--r--server-tools/instance-manager/portability.h25
-rw-r--r--server-tools/instance-manager/priv.cc54
-rw-r--r--server-tools/instance-manager/priv.h83
-rw-r--r--server-tools/instance-manager/protocol.cc215
-rw-r--r--server-tools/instance-manager/protocol.h51
-rw-r--r--server-tools/instance-manager/thread_registry.cc233
-rw-r--r--server-tools/instance-manager/thread_registry.h118
-rw-r--r--server-tools/instance-manager/user_map.cc183
-rw-r--r--server-tools/instance-manager/user_map.h (renamed from merge/mrg_locking.c)41
-rw-r--r--sql-bench/limits/mysql-4.0.cfg557
-rw-r--r--sql-bench/limits/mysql-4.1.cfg7056
-rw-r--r--sql-bench/limits/mysql.cfg6047
-rw-r--r--sql-common/client.c140
-rw-r--r--sql-common/my_time.c257
-rw-r--r--sql/Makefile.am32
-rw-r--r--sql/derror.cc67
-rw-r--r--sql/des_key_file.cc2
-rw-r--r--sql/examples/ha_archive.cc543
-rw-r--r--sql/examples/ha_archive.h66
-rw-r--r--sql/examples/ha_example.cc35
-rw-r--r--sql/examples/ha_example.h4
-rw-r--r--sql/examples/ha_tina.cc66
-rw-r--r--sql/examples/ha_tina.h14
-rw-r--r--sql/field.cc3727
-rw-r--r--sql/field.h520
-rw-r--r--sql/field_conv.cc124
-rw-r--r--sql/filesort.cc278
-rw-r--r--sql/gen_lex_hash.cc30
-rw-r--r--sql/gstream.cc4
-rw-r--r--sql/ha_berkeley.cc572
-rw-r--r--sql/ha_berkeley.h21
-rw-r--r--sql/ha_blackhole.cc40
-rw-r--r--sql/ha_blackhole.h4
-rw-r--r--sql/ha_federated.cc2652
-rw-r--r--sql/ha_federated.h304
-rw-r--r--sql/ha_heap.cc139
-rw-r--r--sql/ha_heap.h19
-rw-r--r--sql/ha_innodb.cc3021
-rw-r--r--sql/ha_innodb.h195
-rw-r--r--sql/ha_isam.cc401
-rw-r--r--sql/ha_isam.h79
-rw-r--r--sql/ha_isammrg.cc209
-rw-r--r--sql/ha_isammrg.h69
-rw-r--r--sql/ha_myisam.cc389
-rw-r--r--sql/ha_myisam.h10
-rw-r--r--sql/ha_myisammrg.cc127
-rw-r--r--sql/ha_myisammrg.h2
-rw-r--r--sql/ha_ndbcluster.cc4274
-rw-r--r--sql/ha_ndbcluster.h553
-rw-r--r--sql/handler.cc1769
-rw-r--r--sql/handler.h478
-rw-r--r--sql/hostname.cc4
-rw-r--r--sql/init.cc3
-rw-r--r--sql/item.cc3526
-rw-r--r--sql/item.h1307
-rw-r--r--sql/item_buff.cc72
-rw-r--r--sql/item_cmpfunc.cc1156
-rw-r--r--sql/item_cmpfunc.h344
-rw-r--r--sql/item_create.cc59
-rw-r--r--sql/item_create.h6
-rw-r--r--sql/item_func.cc2313
-rw-r--r--sql/item_func.h627
-rw-r--r--sql/item_geofunc.cc19
-rw-r--r--sql/item_geofunc.h8
-rw-r--r--sql/item_row.cc24
-rw-r--r--sql/item_row.h10
-rw-r--r--sql/item_strfunc.cc285
-rw-r--r--sql/item_strfunc.h94
-rw-r--r--sql/item_subselect.cc454
-rw-r--r--sql/item_subselect.h47
-rw-r--r--sql/item_sum.cc2159
-rw-r--r--sql/item_sum.h533
-rw-r--r--sql/item_timefunc.cc419
-rw-r--r--sql/item_timefunc.h89
-rw-r--r--sql/item_uniq.cc6
-rw-r--r--sql/item_uniq.h11
-rw-r--r--sql/key.cc219
-rw-r--r--sql/lex.h108
-rw-r--r--sql/lock.cc184
-rw-r--r--sql/log.cc1858
-rw-r--r--sql/log_event.cc2507
-rw-r--r--sql/log_event.h1012
-rw-r--r--sql/my_decimal.cc235
-rw-r--r--sql/my_decimal.h359
-rw-r--r--sql/mysql_priv.h843
-rw-r--r--sql/mysqld.cc1522
-rw-r--r--sql/net_serv.cc30
-rw-r--r--sql/nt_servc.h5
-rw-r--r--sql/opt_range.cc6781
-rw-r--r--sql/opt_range.h643
-rw-r--r--sql/opt_sum.cc44
-rw-r--r--sql/parse_file.cc885
-rw-r--r--sql/parse_file.h74
-rw-r--r--sql/password.c16
-rw-r--r--sql/procedure.cc31
-rw-r--r--sql/procedure.h27
-rw-r--r--sql/protocol.cc268
-rw-r--r--sql/protocol.h26
-rw-r--r--sql/protocol_cursor.cc41
-rw-r--r--sql/records.cc53
-rw-r--r--sql/repl_failsafe.cc62
-rw-r--r--sql/repl_failsafe.h6
-rw-r--r--sql/set_var.cc474
-rw-r--r--sql/set_var.h52
-rw-r--r--sql/share/Makefile.am22
-rw-r--r--sql/share/charsets/Index.xml29
-rw-r--r--sql/share/czech/errmsg.txt334
-rw-r--r--sql/share/danish/errmsg.txt325
-rw-r--r--sql/share/dutch/errmsg.txt334
-rw-r--r--sql/share/english/errmsg.txt322
-rw-r--r--sql/share/errmsg.txt5417
-rw-r--r--sql/share/estonian/errmsg.txt327
-rw-r--r--sql/share/french/errmsg.txt322
-rw-r--r--sql/share/german/errmsg.txt335
-rw-r--r--sql/share/greek/errmsg.txt322
-rw-r--r--sql/share/hungarian/errmsg.txt327
-rw-r--r--sql/share/italian/errmsg.txt322
-rw-r--r--sql/share/japanese-sjis/errmsg.txt326
-rw-r--r--sql/share/japanese/errmsg.txt326
-rw-r--r--sql/share/korean/errmsg.txt322
-rw-r--r--sql/share/norwegian-ny/errmsg.txt324
-rw-r--r--sql/share/norwegian/errmsg.txt324
-rw-r--r--sql/share/polish/errmsg.txt327
-rw-r--r--sql/share/portuguese/errmsg.txt324
-rw-r--r--sql/share/romanian/errmsg.txt327
-rw-r--r--sql/share/russian/errmsg.txt327
-rw-r--r--sql/share/serbian/errmsg.txt315
-rw-r--r--sql/share/slovak/errmsg.txt330
-rw-r--r--sql/share/spanish/errmsg.txt326
-rw-r--r--sql/share/swedish/errmsg.txt322
-rw-r--r--sql/share/ukrainian/errmsg.txt328
-rw-r--r--sql/slave.cc1088
-rw-r--r--sql/slave.h55
-rw-r--r--sql/sp.cc1675
-rw-r--r--sql/sp.h116
-rw-r--r--sql/sp_cache.cc261
-rw-r--r--sql/sp_cache.h63
-rw-r--r--sql/sp_head.cc2924
-rw-r--r--sql/sp_head.h1044
-rw-r--r--sql/sp_pcontext.cc333
-rw-r--r--sql/sp_pcontext.h303
-rw-r--r--sql/sp_rcontext.cc352
-rw-r--r--sql/sp_rcontext.h271
-rw-r--r--sql/spatial.cc2
-rw-r--r--sql/spatial.h5
-rw-r--r--sql/sql_acl.cc3029
-rw-r--r--sql/sql_acl.h124
-rw-r--r--sql/sql_analyse.cc213
-rw-r--r--sql/sql_analyse.h31
-rw-r--r--sql/sql_array.h69
-rw-r--r--sql/sql_base.cc3535
-rw-r--r--sql/sql_bitmap.h34
-rw-r--r--sql/sql_cache.cc425
-rw-r--r--sql/sql_cache.h17
-rw-r--r--sql/sql_class.cc771
-rw-r--r--sql/sql_class.h941
-rw-r--r--sql/sql_db.cc338
-rw-r--r--sql/sql_delete.cc455
-rw-r--r--sql/sql_derived.cc296
-rw-r--r--sql/sql_do.cc8
-rw-r--r--sql/sql_error.cc82
-rw-r--r--sql/sql_error.h42
-rw-r--r--sql/sql_handler.cc228
-rw-r--r--sql/sql_help.cc170
-rw-r--r--sql/sql_insert.cc1228
-rw-r--r--sql/sql_lex.cc944
-rw-r--r--sql/sql_lex.h466
-rw-r--r--sql/sql_list.h82
-rw-r--r--sql/sql_load.cc455
-rw-r--r--sql/sql_map.cc20
-rw-r--r--sql/sql_olap.cc13
-rw-r--r--sql/sql_parse.cc4346
-rw-r--r--sql/sql_prepare.cc2161
-rw-r--r--sql/sql_rename.cc70
-rw-r--r--sql/sql_repl.cc567
-rw-r--r--sql/sql_repl.h26
-rw-r--r--sql/sql_select.cc5948
-rw-r--r--sql/sql_select.h172
-rw-r--r--sql/sql_show.cc4127
-rw-r--r--sql/sql_sort.h1
-rw-r--r--sql/sql_string.cc17
-rw-r--r--sql/sql_string.h41
-rw-r--r--sql/sql_table.cc1532
-rw-r--r--sql/sql_test.cc148
-rw-r--r--sql/sql_trigger.cc926
-rw-r--r--sql/sql_trigger.h112
-rw-r--r--sql/sql_udf.cc69
-rw-r--r--sql/sql_udf.h5
-rw-r--r--sql/sql_union.cc273
-rw-r--r--sql/sql_update.cc816
-rw-r--r--sql/sql_view.cc1449
-rw-r--r--sql/sql_view.h40
-rw-r--r--sql/sql_yacc.yy5677
-rw-r--r--sql/strfunc.cc6
-rw-r--r--sql/structs.h69
-rw-r--r--sql/table.cc1740
-rw-r--r--sql/table.h737
-rw-r--r--sql/time.cc214
-rw-r--r--sql/tztime.cc191
-rw-r--r--sql/tztime.h12
-rw-r--r--sql/udf_example.cc45
-rw-r--r--sql/uniques.cc477
-rw-r--r--sql/unireg.cc113
-rw-r--r--sql/unireg.h27
-rw-r--r--strings/Makefile.am31
-rw-r--r--strings/conf_to_src.c2
-rw-r--r--strings/ctype-big5.c46
-rw-r--r--strings/ctype-bin.c43
-rw-r--r--strings/ctype-cp932.c23
-rw-r--r--strings/ctype-czech.c24
-rw-r--r--strings/ctype-euc_kr.c8
-rw-r--r--strings/ctype-eucjpms.c8749
-rw-r--r--strings/ctype-extra.c3
-rw-r--r--strings/ctype-gb2312.c8
-rw-r--r--strings/ctype-gbk.c35
-rw-r--r--strings/ctype-latin1.c30
-rw-r--r--strings/ctype-mb.c83
-rw-r--r--strings/ctype-simple.c137
-rw-r--r--strings/ctype-sjis.c39
-rw-r--r--strings/ctype-tis620.c45
-rw-r--r--strings/ctype-uca.c225
-rw-r--r--strings/ctype-ucs2.c123
-rw-r--r--strings/ctype-ujis.c10
-rw-r--r--strings/ctype-utf8.c337
-rw-r--r--strings/ctype-win1250ch.c25
-rw-r--r--strings/ctype.c10
-rw-r--r--strings/decimal.c3065
-rw-r--r--strings/llstr.c2
-rw-r--r--strings/my_strtoll10.c8
-rw-r--r--strings/my_vsnprintf.c37
-rw-r--r--strings/str_alloc.c (renamed from merge/mrg_update.c)27
-rw-r--r--strings/xml.c77
-rw-r--r--support-files/MacOSX/Info.plist.sh6
-rw-r--r--support-files/MacOSX/Makefile.am1
-rw-r--r--support-files/MySQL-shared-compat.spec.sh22
-rw-r--r--support-files/debian/gomi2
-rw-r--r--support-files/my-huge.cnf.sh4
-rw-r--r--support-files/my-innodb-heavy-4G.cnf.sh2
-rw-r--r--support-files/my-large.cnf.sh4
-rw-r--r--support-files/my-medium.cnf.sh4
-rw-r--r--support-files/my-small.cnf.sh2
-rw-r--r--support-files/mysql.server.sh131
-rw-r--r--support-files/mysql.spec.sh53
-rw-r--r--tests/Makefile.am16
-rw-r--r--tests/connect_test.c1
-rw-r--r--tests/deadlock_test.c1
-rw-r--r--tests/fork_big2.pl2
-rw-r--r--tests/grant.pl4
-rw-r--r--tests/insert_test.c1
-rw-r--r--tests/list_test.c1
-rwxr-xr-xtests/mail_to_db.pl54
-rw-r--r--tests/mysql_client_test.c3005
-rwxr-xr-xtests/pmail.pl283
-rw-r--r--tests/select_test.c1
-rw-r--r--tests/showdb_test.c1
-rw-r--r--tests/ssl_test.c1
-rw-r--r--tests/thread_test.c1
-rw-r--r--tests/udf_test3
-rw-r--r--tests/udf_test.res24
-rw-r--r--tools/Makefile.am21
-rw-r--r--tools/mysqlmanager.c12
-rw-r--r--vio/Makefile.am11
-rw-r--r--vio/test-sslserver.c7
-rw-r--r--vio/vio.c46
-rw-r--r--vio/viosocket.c60
-rw-r--r--vio/viossl.c26
-rw-r--r--vio/viosslfactories.c10
2002 files changed, 335501 insertions, 117085 deletions
diff --git a/.bzrignore b/.bzrignore
index d8be10eacdb..3932ed4d127 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -9,6 +9,7 @@
*.lo
*.o
*.reject
+*.so
*.spec
*/*_pure_*warnings
*/.pure
@@ -101,9 +102,12 @@ Makefile.in
Makefile.in'
PENDING/*
TAGS
+VC++Files/client/mysql_amd64.dsp
ac_available_languages_fragment
+acinclude.m4
aclocal.m4
analyse.test
+autom4te-2.53.cache/*
autom4te-2.53.cache/output.0
autom4te-2.53.cache/requests
autom4te-2.53.cache/traces.0
@@ -155,6 +159,7 @@ bdb/db/crdel_auto.c
bdb/db/db_auto.c
bdb/dbinc_auto/*.*
bdb/dbreg/dbreg_auto.c
+bdb/dist/autom4te-2.53.cache/*
bdb/dist/autom4te-2.53.cache/output.0
bdb/dist/autom4te-2.53.cache/requests
bdb/dist/autom4te-2.53.cache/traces.0
@@ -241,19 +246,24 @@ bdb/test/logtrack.list
bdb/txn/txn_auto.c
binary/*
bkpull.log
+bkpull.log*
bkpull.log.2
bkpull.log.3
bkpull.log.4
bkpull.log.5
bkpull.log.6
bkpush.log
+bkpush.log*
build.log
build_tags.sh
+client/decimal.c
client/insert_test
client/log_event.cc
client/log_event.h
client/mf_iocache.c
client/mf_iocache.cc
+client/my_decimal.cc
+client/my_decimal.h
client/mysql
client/mysqladmin
client/mysqladmin.c
@@ -265,6 +275,8 @@ client/mysqlmanager-pwgen
client/mysqlmanagerc
client/mysqlshow
client/mysqltest
+client/mysqltestmanager-pwgen
+client/mysqltestmanagerc
client/mysys_priv.h
client/select_test
client/ssl_test
@@ -275,30 +287,47 @@ cmd-line-utils/libedit/common.h
cmd-line-utils/libedit/makelist
comon.h
config.cache
+config.guess
config.h
config.h.in
config.log
config.status
+config.sub
configure
configure.lineno
core
+core.*
core.2430
db-*.*.*
+dbug/dbug_analyze
+dbug/example*.r
+dbug/factorial
+dbug/factorial.r
+dbug/main.r
+dbug/output*.r
+dbug/user.ps
dbug/user.t
depcomp
emacs.h
+extra/charset2html
extra/comp_err
+extra/created_include_files
+extra/innochecksum
extra/my_print_defaults
extra/mysql_install
extra/mysql_tzinfo_to_sql
extra/mysql_waitpid
+extra/mysqld_ername.h
+extra/mysqld_error.h
extra/perror
extra/replace
extra/resolve_stack_dump
extra/resolveip
+extra/sql_state.h
extra/tztime.cc
fcns.c
fcns.h
+gdbinit
gmon.out
hardcopy.0
heap/hp_test1
@@ -309,10 +338,14 @@ help.h
include/my_config.h
include/my_global.h
include/mysql_version.h
+include/mysqld_ername.h
+include/mysqld_error.h
include/readline
include/readline/*.h
include/readline/readline.h
+include/sql_state.h
include/widec.h
+innobase/autom4te-2.53.cache/*
innobase/autom4te-2.53.cache/output.0
innobase/autom4te-2.53.cache/requests
innobase/autom4te-2.53.cache/traces.0
@@ -325,9 +358,11 @@ innobase/conftest.s1
innobase/conftest.subs
innobase/ib_config.h
innobase/ib_config.h.in
+innobase/mkinstalldirs
innobase/stamp-h1
insert_test
install
+install-sh
isam/isamchk
isam/isamlog
isam/pack_isam
@@ -355,6 +390,7 @@ libmysqld/derror.cc
libmysqld/discover.cc
libmysqld/errmsg.c
libmysqld/examples/client_test.c
+libmysqld/examples/client_test.cc
libmysqld/examples/completion_hash.cc
libmysqld/examples/completion_hash.h
libmysqld/examples/link_sources
@@ -378,6 +414,7 @@ libmysqld/gstream.cc
libmysqld/ha_archive.cc
libmysqld/ha_berkeley.cc
libmysqld/ha_example.cc
+libmysqld/ha_federated.cc
libmysqld/ha_heap.cc
libmysqld/ha_innobase.cc
libmysqld/ha_innodb.cc
@@ -410,6 +447,7 @@ libmysqld/log_event.cc
libmysqld/md5.c
libmysqld/mf_iocache.cc
libmysqld/mini_client.cc
+libmysqld/my_decimal.cc
libmysqld/my_time.c
libmysqld/net_pkg.cc
libmysqld/net_serv.cc
@@ -417,14 +455,21 @@ libmysqld/opt_ft.cc
libmysqld/opt_range.cc
libmysqld/opt_sum.cc
libmysqld/pack.c
+libmysqld/parse_file.cc
libmysqld/password.c
libmysqld/procedure.cc
libmysqld/protocol.cc
+libmysqld/protocol_cursor.cc
libmysqld/records.cc
libmysqld/repl_failsafe.cc
libmysqld/set_var.cc
libmysqld/simple-test
libmysqld/slave.cc
+libmysqld/sp.cc
+libmysqld/sp_cache.cc
+libmysqld/sp_head.cc
+libmysqld/sp_pcontext.cc
+libmysqld/sp_rcontext.cc
libmysqld/spatial.cc
libmysqld/sql_acl.cc
libmysqld/sql_analyse.cc
@@ -437,6 +482,7 @@ libmysqld/sql_db.cc
libmysqld/sql_delete.cc
libmysqld/sql_derived.cc
libmysqld/sql_do.cc
+libmysqld/sql_error.cc
libmysqld/sql_handler.cc
libmysqld/sql_help.cc
libmysqld/sql_insert.cc
@@ -447,6 +493,7 @@ libmysqld/sql_manager.cc
libmysqld/sql_map.cc
libmysqld/sql_olap.cc
libmysqld/sql_parse.cc
+libmysqld/sql_prepare.cc
libmysqld/sql_rename.cc
libmysqld/sql_repl.cc
libmysqld/sql_select.cc
@@ -455,10 +502,12 @@ libmysqld/sql_state.c
libmysqld/sql_string.cc
libmysqld/sql_table.cc
libmysqld/sql_test.cc
+libmysqld/sql_trigger.cc
libmysqld/sql_udf.cc
libmysqld/sql_union.cc
libmysqld/sql_unions.cc
libmysqld/sql_update.cc
+libmysqld/sql_view.cc
libmysqld/sql_yacc.cc
libmysqld/stacktrace.c
libmysqld/strfunc.cc
@@ -478,7 +527,9 @@ linked_libmysqldex_sources
linked_server_sources
linked_tools_sources
locked
+ltmain.sh
man/*.1
+missing
mit-pthreads/config.flags
mit-pthreads/include/bits
mit-pthreads/include/pthread/machdep.h
@@ -488,6 +539,7 @@ mit-pthreads/machdep.c
mit-pthreads/pg++
mit-pthreads/pgcc
mit-pthreads/syscall.S
+mkinstalldirs
myisam/FT1.MYD
myisam/FT1.MYI
myisam/ft_dump
@@ -516,6 +568,7 @@ myisam/test2.MYI
mysql-4.0.2-alpha-pc-linux-gnu-i686.tar.gz
mysql-4.0.2-alpha.tar.gz
mysql-4.1.8-win-src.zip
+mysql-5.0.2-alpha.tar.gz
mysql-max-4.0.2-alpha-pc-linux-gnu-i686.tar.gz
mysql-test/gmon.out
mysql-test/install_test_db
@@ -538,6 +591,7 @@ mysql-test/r/ctype_ucs.err
mysql-test/r/derived.err
mysql-test/r/exampledb.err
mysql-test/r/func_encrypt.err
+mysql-test/r/index_merge_load.result
mysql-test/r/isam.err
mysql-test/r/lowercase_table2.err
mysql-test/r/multi_update.err
@@ -587,9 +641,12 @@ mysql-test/r/slave-running.eval
mysql-test/r/slave-stopped.eval
mysql-test/share/mysql
mysql-test/std_data/*.pem
+mysql-test/t/index_merge.load
+mysql-test/var
mysql-test/var/*
mysql.kdevprj
mysql.proj
+mysql_priv.h
mysqld.S
mysqld.sym
mysys/#mf_iocache.c#
@@ -721,6 +778,7 @@ ndb/examples/ndbapi_example3/ndbapi_example3
ndb/examples/ndbapi_example5/ndbapi_example5
ndb/examples/select_all/select_all
ndb/include/ndb_global.h
+ndb/include/ndb_types.h
ndb/include/ndb_version.h
ndb/lib/libMGM_API.so
ndb/lib/libNDB_API.so
@@ -739,6 +797,7 @@ ndb/src/common/portlib/libportlib.dsp
ndb/src/common/transporter/libtransporter.dsp
ndb/src/common/util/libgeneral.dsp
ndb/src/cw/cpcd/ndb_cpcd
+ndb/src/dummy.cpp
ndb/src/kernel/blocks/backup/libbackup.dsp
ndb/src/kernel/blocks/backup/restore/ndb_restore
ndb/src/kernel/blocks/cmvmi/libcmvmi.dsp
@@ -895,6 +954,11 @@ scripts/mysqlhotcopy
scripts/mysqlhotcopy.sh.rej
scripts/safe_mysqld
select_test
+server-tools/instance-manager/client.c
+server-tools/instance-manager/client_settings.h
+server-tools/instance-manager/errmsg.c
+server-tools/instance-manager/mysqlmanager
+server-tools/instance-manager/thr_alarm.c
sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686
sql-bench/bench-count-distinct
sql-bench/bench-init.pl
@@ -959,7 +1023,9 @@ sql_prepare.cc
stamp-h
stamp-h.in
stamp-h1
+stamp-h1.in
stamp-h2
+stamp-h2.in
stamp-h3
stamp-h4
start_mysqld.sh
@@ -967,6 +1033,7 @@ strings/conf_to_src
strings/ctype_autoconf.c
strings/ctype_extra_sources.c
strings/str_test
+strings/test_decimal
support-files/MacOSX/Description.plist
support-files/MacOSX/Info.plist
support-files/MacOSX/ReadMe.txt
@@ -1051,6 +1118,7 @@ tmp/*
tools/my_vsnprintf.c
tools/mysqlmanager
tools/mysqlmngd
+tools/mysqltestmanager
tools/mysys_priv.h
vi.h
vio/test-ssl
diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh
index 143db3e0692..8cd78bf4165 100644
--- a/BUILD/FINISH.sh
+++ b/BUILD/FINISH.sh
@@ -4,20 +4,12 @@ extra_configs="$extra_configs $local_infile_configs"
configure="./configure $base_configs $extra_configs"
commands="\
-$make -k clean || true
+$make -k distclean || true
/bin/rm -rf */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache bdb/dist/autom4te.cache autom4te.cache innobase/autom4te.cache;
-aclocal || (echo \"Can't execute aclocal\" && exit 1)
-autoheader || (echo \"Can't execute autoheader\" && exit 1)
-aclocal || (echo \"Can't execute aclocal\" && exit 1)
-automake || (echo \"Can't execute automake\" && exit 1)
-autoconf || (echo \"Can't execute autoconf\" && exit 1)
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
-if [ -d gemini ]
-then
- (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
-fi"
+
+path=`dirname $0`
+. \"$path/autorun.sh\""
if [ -z "$just_clean" ]
then
diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am
index 4e27ffd5e7f..45c1aaa1a76 100644
--- a/BUILD/Makefile.am
+++ b/BUILD/Makefile.am
@@ -19,6 +19,7 @@
EXTRA_DIST = FINISH.sh \
SETUP.sh \
+ autorun.sh \
check-cpu \
compile-alpha \
compile-alpha-ccc \
@@ -30,6 +31,7 @@ EXTRA_DIST = FINISH.sh \
compile-pentium-debug-max \
compile-pentium-debug-no-bdb \
compile-pentium-debug-openssl \
+ compile-pentium-debug-yassl \
compile-pentium-gcov \
compile-pentium-gprof \
compile-pentium-max \
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index 3f8a9ccaf22..1bf3bad5abe 100755
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -10,6 +10,11 @@ prefix_configs="--prefix=/usr/local/mysql"
just_print=
just_configure=
full_debug=
+if test -n $MYSQL_BUILD_PREFIX
+then
+ prefix_configs="--prefix=$MYSQL_BUILD_PREFIX"
+fi
+
while test $# -gt 0
do
case "$1" in
@@ -48,16 +53,15 @@ global_warnings="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wch
c_warnings="$global_warnings -Wunused"
cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor"
-base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-raid --with-openssl --with-raid --with-vio"
-max_leave_isam_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-raid --with-openssl --with-raid --with-vio --with-embedded-server"
-max_no_es_configs="$max_leave_isam_configs --without-isam"
-max_configs="$max_no_es_configs --with-embedded-server"
+base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-openssl --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine"
+max_leave_isam_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-blackhole-storage-engine --with-openssl --with-embedded-server --with-big-tables"
+max_configs="$base_max_configs --with-embedded-server"
path=`dirname $0`
. "$path/check-cpu"
alpha_cflags="$check_cpu_cflags -Wa,-m$cpu_flag"
-amd64_cflags="$check_cpu_cflags -DBIG_TABLES"
+amd64_cflags="$check_cpu_cflags"
pentium_cflags="$check_cpu_cflags"
pentium64_cflags="$check_cpu_cflags -m64"
ppc_cflags="$check_cpu_cflags"
@@ -73,9 +77,9 @@ debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMA
debug_extra_cflags="-O1 -Wuninitialized"
base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti"
-amd64_cxxflags="-DBIG_TABLES"
+amd64_cxxflags="" # If dropping '--with-big-tables', add here "-DBIG_TABLES"
-base_configs="$prefix_configs --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-readline"
+base_configs="$prefix_configs --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-readline --with-big-tables"
static_link="--with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static"
amd64_configs=""
alpha_configs="" # Not used yet
diff --git a/BUILD/autorun.sh b/BUILD/autorun.sh
new file mode 100755
index 00000000000..f5986720b48
--- /dev/null
+++ b/BUILD/autorun.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+# Create MySQL autotools infrastructure
+
+die() { echo "$@"; exit 1; }
+
+aclocal || die "Can't execute aclocal"
+autoheader || die "Can't execute autoheader"
+# --force means overwrite ltmain.sh script if it already exists
+# Added glibtoolize reference to make native OSX autotools work
+if test -f /usr/bin/glibtoolize ; then
+ glibtoolize --automake --force || die "Can't execute glibtoolize"
+else
+ libtoolize --automake --force || die "Can't execute libtoolize"
+fi
+
+# --add-missing instructs automake to install missing auxiliary files
+# and --force to overwrite them if they already exist
+automake --add-missing --force || die "Can't execute automake"
+autoconf || die "Can't execute autoconf"
+(cd bdb/dist && sh s_all)
+(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
diff --git a/BUILD/check-cpu b/BUILD/check-cpu
index b970a4b9a5b..dc894c91cbd 100755
--- a/BUILD/check-cpu
+++ b/BUILD/check-cpu
@@ -90,6 +90,9 @@ case "$cpu_family--$model_name" in
*Athlon*)
cpu_arg="athlon";
;;
+ *Opteron*)
+ cpu_arg="opteron";
+ ;;
# Intel ia64
*Itanium*)
@@ -147,6 +150,9 @@ case "$cc_ver--$cc_verno" in
ppc-*)
check_cpu_args='-mcpu=$cpu_arg -mtune=$cpu_arg'
;;
+ x86_64-*)
+ check_cpu_args='-mtune=$cpu_arg'
+ ;;
*)
check_cpu_cflags=""
return
diff --git a/BUILD/compile-alpha-ccc b/BUILD/compile-alpha-ccc
index 48cc0857cbf..889592295b5 100755
--- a/BUILD/compile-alpha-ccc
+++ b/BUILD/compile-alpha-ccc
@@ -2,7 +2,9 @@
make -k clean
/bin/rm -f */.deps/*.P */*.o
/bin/rm -f config.cache mysql-*.tar.gz
-aclocal; autoheader; aclocal; automake; autoconf
+
+path=`dirname $0`
+. "$path/autorun.sh"
CC=ccc CFLAGS="-fast -O3 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti -mcpu=ev6 -Wa,-mev6" CXXLDFLAGS='/usr/lib/compaq/libots-2.2.7/libots.so /usr/lib/compaq/cpml-5.0.0/libcpml_ev6.a' ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-thread-safe-client
make
diff --git a/BUILD/compile-alpha-cxx b/BUILD/compile-alpha-cxx
index a342d927868..c49846fd964 100755
--- a/BUILD/compile-alpha-cxx
+++ b/BUILD/compile-alpha-cxx
@@ -2,7 +2,9 @@
make -k clean
/bin/rm -f */.deps/*.P */*.o
/bin/rm -f */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache mysql-*.tar.gz
-aclocal; autoheader; aclocal; automake; autoconf
+
+path=`dirname $0`
+. "$path/autorun.sh"
CC=ccc CFLAGS="-fast" CXX=cxx CXXFLAGS="-fast -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared --without-extra-tools --disable-dependency-tracking
diff --git a/BUILD/compile-alpha-debug b/BUILD/compile-alpha-debug
index 60d1b9af659..113c2151461 100755
--- a/BUILD/compile-alpha-debug
+++ b/BUILD/compile-alpha-debug
@@ -2,7 +2,9 @@
make -k clean
/bin/rm -f */.deps/*.P */*.o
/bin/rm -f */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache mysql-*.tar.gz
-aclocal; autoheader; aclocal; automake; autoconf
+
+path=`dirname $0`
+. "$path/autorun.sh"
CFLAGS=-O1 CC=gcc CXX=gcc CXXFLAGS="-O1 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-debug --with-extra-charsets=complex --without-extra-tools
make
diff --git a/BUILD/compile-hpux11-parisc2-aCC b/BUILD/compile-hpux11-parisc2-aCC
index 2fc7a6d2b6e..c286488bb26 100755
--- a/BUILD/compile-hpux11-parisc2-aCC
+++ b/BUILD/compile-hpux11-parisc2-aCC
@@ -62,14 +62,9 @@ done
set -x
make distclean
-aclocal
-autoheader
-libtoolize --automake --force
-automake --force --add-missing
-autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
+path=`dirname $0`
+. "$path/autorun.sh"
CC=cc CXX=aCC CFLAGS="$cflags" CXXFLAGS="$cxxflags" \
./configure --prefix=/usr/local/mysql --disable-shared \
diff --git a/BUILD/compile-ia64-debug-max b/BUILD/compile-ia64-debug-max
index 56c36059ea9..5082844f088 100755
--- a/BUILD/compile-ia64-debug-max
+++ b/BUILD/compile-ia64-debug-max
@@ -1,13 +1,8 @@
gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache
-aclocal && autoheader && aclocal && automake && autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
-if [ -d gemini ]
-then
- (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
-fi
+path=`dirname $0`
+. "$path/autorun.sh"
CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server --with-archive-storage-engine
gmake
diff --git a/BUILD/compile-irix-mips64-mipspro b/BUILD/compile-irix-mips64-mipspro
index 1987fa13b1f..0cebb4b9f5b 100755
--- a/BUILD/compile-irix-mips64-mipspro
+++ b/BUILD/compile-irix-mips64-mipspro
@@ -34,14 +34,9 @@ fi
set -x
make distclean
-aclocal
-autoheader
-libtoolize --automake --force
-automake --force --add-missing
-autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
+path=`dirname $0`
+. "$path/autorun.sh"
# C options:
# -apo - auto-parallize for multiprocessors (implies -mp)
diff --git a/BUILD/compile-pentium-debug b/BUILD/compile-pentium-debug
index 4a9d0e74599..7957caead29 100755
--- a/BUILD/compile-pentium-debug
+++ b/BUILD/compile-pentium-debug
@@ -1,7 +1,7 @@
#! /bin/sh
path=`dirname $0`
-. "$path/SETUP.sh"
+. "$path/SETUP.sh" $@ --with-debug=full
extra_flags="$pentium_cflags $debug_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
diff --git a/BUILD/compile-pentium-debug-max b/BUILD/compile-pentium-debug-max
index 420657e0b73..7a11ad24c44 100755
--- a/BUILD/compile-pentium-debug-max
+++ b/BUILD/compile-pentium-debug-max
@@ -1,7 +1,7 @@
#! /bin/sh
path=`dirname $0`
-. "$path/SETUP.sh"
+. "$path/SETUP.sh" $@ --with-debug=full
extra_flags="$pentium_cflags $debug_cflags $max_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
diff --git a/BUILD/compile-pentium-debug-max-no-embedded b/BUILD/compile-pentium-debug-max-no-embedded
index 803a6a9d6d3..dfdf7d0a5e1 100755
--- a/BUILD/compile-pentium-debug-max-no-embedded
+++ b/BUILD/compile-pentium-debug-max-no-embedded
@@ -6,6 +6,6 @@ path=`dirname $0`
extra_flags="$pentium_cflags $debug_cflags $max_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
-extra_configs="$pentium_configs $debug_configs $max_no_es_configs"
+extra_configs="$pentium_configs $debug_configs $base_max_configs"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-debug-yassl b/BUILD/compile-pentium-debug-yassl
new file mode 100755
index 00000000000..666e73d0267
--- /dev/null
+++ b/BUILD/compile-pentium-debug-yassl
@@ -0,0 +1,13 @@
+#! /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 --with-debug=full --with-yassl"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-icc b/BUILD/compile-pentium-icc
new file mode 100755
index 00000000000..bf550a4b574
--- /dev/null
+++ b/BUILD/compile-pentium-icc
@@ -0,0 +1,24 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+# Note that we can't use ccache with icc as the generated .deps file will
+# then contain wrong information
+CC=icc
+CXX=icpc
+CXXLD="$CXX -static-libcxa"
+export CC CXX CXXLD
+
+c_warnings=""
+cxx_warnings=""
+extra_flags="$fast_cflags -unroll2 -ip -mp -restrict"
+
+# Use -no-ipo if you get this error
+# IPO link: can not find "-lstdc++_shared"
+# icpc: error: problem during multi-file optimization compilation (code 1)
+extra_flags="$extra_flags -no-ipo"
+base_cxxflags="-fno-exceptions -fno-rtti"
+extra_configs="$pentium_configs $static_link"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-icc-valgrind-max b/BUILD/compile-pentium-icc-valgrind-max
new file mode 100755
index 00000000000..b765c777e2b
--- /dev/null
+++ b/BUILD/compile-pentium-icc-valgrind-max
@@ -0,0 +1,34 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+# Note that we can't use ccache with icc as the generated .deps file will
+# then contain wrong information
+CC=icc
+CXX=icpc
+export CC CXX
+
+extra_flags="$pentium_cflags $debug_cflags $max_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify -DMYSQL_SERVER_SUFFIX=-valgrind-max"
+
+# Disable following warnings as these are generated by header files:
+# 161 unrecognized pragma
+# 444 destructor for base class xxx is not virtual
+# 279 controlling expression is constant
+# 810 conversion from ulonglong to ulong with cast
+# 981 operands are evaluated in unspecified order
+# 1292 warning for unknown 'attribute' options
+# 1469 "xxx" clobber ignored
+# 1572 floating-point equality and inequality comparisons are unreliable
+
+# In C++
+# 869 parameter "xxx" was never referenced
+# (Problem with virtual functions)
+# 874 support for placement delete is disabled
+
+c_warnings="-Wall -Wcheck -wd161,444,279,810,981,1292,1469,1572"
+cxx_warnings="$c_warnings -wd869,874"
+base_cxxflags="-fno-exceptions -fno-rtti"
+extra_configs="$pentium_configs $debug_configs"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-icc-yassl b/BUILD/compile-pentium-icc-yassl
new file mode 100644
index 00000000000..53b191e4db3
--- /dev/null
+++ b/BUILD/compile-pentium-icc-yassl
@@ -0,0 +1,24 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+# Note that we can't use ccache with icc as the generated .deps file will
+# then contain wrong information
+CC=icc
+CXX=icpc
+CXXLD="$CXX -static-libcxa"
+export CC CXX CXXLD
+
+c_warnings=""
+cxx_warnings=""
+extra_flags="$fast_cflags -unroll2 -ip -mp -restrict"
+
+# Use -no-ipo if you get this error
+# IPO link: can not find "-lstdc++_shared"
+# icpc: error: problem during multi-file optimization compilation (code 1)
+extra_flags="$extra_flags -no-ipo"
+base_cxxflags="-fno-exceptions -fno-rtti"
+extra_configs="$pentium_configs $static_link --with-yassl"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium-pgcc b/BUILD/compile-pentium-pgcc
index 2d806009b21..639f108bb2b 100755
--- a/BUILD/compile-pentium-pgcc
+++ b/BUILD/compile-pentium-pgcc
@@ -2,13 +2,9 @@ AM_MAKEFLAGS="-j 2"
gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache
-aclocal && autoheader && aclocal && automake && autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
-if [ -d gemini ]
-then
- (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
-fi
+
+path=`dirname $0`
+. "$path/autorun.sh"
export PATH=/usr/local/pgcc/bin:$PATH
CFLAGS="-Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O6 -mpentiumpro -fomit-frame-pointer -mstack-align-double" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wextern-inline -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O6 -fomit-frame-pointer -mpentiumpro -mstack-align-double" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static
diff --git a/BUILD/compile-pentium64-valgrind-max b/BUILD/compile-pentium64-valgrind-max
new file mode 100644
index 00000000000..2e4ff8e0082
--- /dev/null
+++ b/BUILD/compile-pentium64-valgrind-max
@@ -0,0 +1,29 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium64_cflags $debug_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify -DMYSQL_SERVER_SUFFIX=-valgrind-max"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$pentium_configs $debug_configs"
+
+# We want to test isam when building with valgrind
+extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-isam --with-embedded-server --with-openssl --with-raid --with-ndbcluster"
+
+. "$path/FINISH.sh"
+
+if test -z "$just_print"
+then
+ set +v +x
+ echo "\
+******************************************************************************
+Note that by default BUILD/compile-pentium-valgrind-max calls 'configure' with
+--enable-assembler. When Valgrind detects an error involving an assembly
+function (for example an uninitialized value used as an argument of an
+assembly function), Valgrind will not print the stacktrace and 'valgrind
+--gdb-attach=yes' will not work either. If you need a stacktrace in those
+cases, you have to run BUILD/compile-pentium-valgrind-max with the
+--disable-assembler argument.
+******************************************************************************"
+fi
diff --git a/BUILD/compile-sap b/BUILD/compile-sap
new file mode 100755
index 00000000000..376afaf6f56
--- /dev/null
+++ b/BUILD/compile-sap
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium_cflags"
+extra_configs="$pentium_configs --without-berkeley-db"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-sap-debug b/BUILD/compile-sap-debug
new file mode 100755
index 00000000000..d7e70f868cc
--- /dev/null
+++ b/BUILD/compile-sap-debug
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium_cflags $debug_cflags"
+extra_configs="$pentium_configs $debug_configs --without-berkeley-db $static_link"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-solaris-sparc b/BUILD/compile-solaris-sparc
index 143a4b7867d..0c05bf8a101 100755
--- a/BUILD/compile-solaris-sparc
+++ b/BUILD/compile-solaris-sparc
@@ -3,14 +3,9 @@
gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache
-aclocal && autoheader && aclocal && automake && autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
-if [ -d gemini ]
-then
- (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
-fi
-
+path=`dirname $0`
+. "$path/autorun.sh"
+
CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
gmake -j 4
diff --git a/BUILD/compile-solaris-sparc-debug b/BUILD/compile-solaris-sparc-debug
index 527f135ac62..3384b623ccb 100755
--- a/BUILD/compile-solaris-sparc-debug
+++ b/BUILD/compile-solaris-sparc-debug
@@ -3,13 +3,8 @@
gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache
-aclocal && autoheader && aclocal && automake && autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
-if [ -d gemini ]
-then
- (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
-fi
+path=`dirname $0`
+. "$path/autorun.sh"
CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-debug
diff --git a/BUILD/compile-solaris-sparc-forte b/BUILD/compile-solaris-sparc-forte
index afd106afc67..7cdbff6ae4a 100755
--- a/BUILD/compile-solaris-sparc-forte
+++ b/BUILD/compile-solaris-sparc-forte
@@ -3,13 +3,8 @@
gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache
-aclocal && autoheader && aclocal && automake && autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
-if [ -d gemini ]
-then
- (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
-fi
+path=`dirname $0`
+. "$path/autorun.sh"
# Assume Forte is installed in /opt/SUNWSpro
diff --git a/BUILD/compile-solaris-sparc-purify b/BUILD/compile-solaris-sparc-purify
index 5f5ba81396f..29cf5671432 100755
--- a/BUILD/compile-solaris-sparc-purify
+++ b/BUILD/compile-solaris-sparc-purify
@@ -15,30 +15,29 @@ do
--purecov*) mode=purecov ;;
--quantify) mode=quantify ;;
--cxxfilt) shift ; cxxfilt=$1 ;;
- -h | --help ) cat <<EOF; exit 0 ;;
-Usage: $0 [ options ]
-
-Where the 'options' are
-
- --debug Compile with DBUG enabled
- --purify Only prepare for Purify
- --purecov Only prepare for PureCover
- --quantify Only prepare for Quantify
- --cxxfilt <cxxfilt> Path to cxxfilt/c++filt program
- This program is needed for gcc 3.X
-EOF
- *) echo "No such option '$1'" ; exit 1 ;;
+ -h | --help )
+ echo "Usage: $0 [ options ]"
+ echo "Where the 'options' are"
+ echo " --help | -h Display this help"
+ echo " --debug Compile with DBUG enabled"
+ echo " --purify Only prepare for Purify"
+ echo " --purecov Only prepare for PureCover"
+ echo " --quantify Only prepare for Quantify"
+ echo " --cxxfilt <cxxfilt> Path to cxxfilt/c++filt program"
+ echo " This program is needed for gcc 3.X"
+ exit 0 ;;
+ *) echo "No such option '$1'" ; exit 1 ;;
esac
shift
done
gmake -k clean || true
/bin/rm -f */.deps/*.P config.cache
-aclocal && autoheader && aclocal && automake && autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
+
+path=`dirname $0`
+. "$path/autorun.sh"
-CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -DHAVE_purify -DEXTRA_DEBUG -O2" CXX=gcc CXXLD=g++ CXXFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -DHAVE_purify -DEXTRA_DEBUG -O2" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-berkeley-db --with-innodb $EXTRA_CONFIG_FLAGS
+CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -DHAVE_purify -DEXTRA_DEBUG -O2" CXX=gcc CXXLD=g++ CXXFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -DHAVE_purify -DEXTRA_DEBUG -O2" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-berkeley-db --with-embedded-server --with-innodb $EXTRA_CONFIG_FLAGS
gmake -j 4
diff --git a/BitKeeper/etc/RESYNC_TREE b/BitKeeper/etc/RESYNC_TREE
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/BitKeeper/etc/RESYNC_TREE
diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config
index af93117a517..81e867e514f 100644
--- a/BitKeeper/etc/config
+++ b/BitKeeper/etc/config
@@ -69,6 +69,7 @@ pager:
hours:
[serg:]checkout:get
[arjen:]checkout:get
+[kostja:]checkout:get
[nick:]checkout:get
[jonas:]checkout:get
[tomas:]checkout:get
diff --git a/BitKeeper/etc/gone b/BitKeeper/etc/gone
index 2d5522899d2..7c9741f7e79 100644
--- a/BitKeeper/etc/gone
+++ b/BitKeeper/etc/gone
@@ -455,8 +455,444 @@ arjen@co3064164-a.bitbike.com|Docs/section.Comparisons.texi|20011108043647|22614
arjen@fred.bitbike.com|scripts/mysql_fix_extensions.sh|20020516001337|12363|f1048a78f4759b4d
ccarkner@nslinuxw10.bedford.progress.com|mysql-test/r/isolation.result|20010327145543|25059|4da11e109a3d93a9
ccarkner@nslinuxw10.bedford.progress.com|mysql-test/t/isolation.test|20010327145543|39049|6a39e4138dd4a456
+fs
jani@hynda.mysql.fi|client/mysqlcheck|20010419221207|26716|363e3278166d84ec
jcole@tetra.bedford.progress.com|BitKeeper/etc/logging_ok|20001004201211|30554
+jimw@mysql.com|mysql-test/t/ndb_alter_table.disabled|20050311230559|27526|411e026940e7a0aa
+jimw@mysql.com|mysql-test/t/ndb_alter_table.disabled|20050311230559|27526|411e026940e7a0aajimw@mysql.com|mysql-test/t/ndb_autodiscover2.disabled|20050311230559|22363|afa8e5b6e46a3ea1jimw@mysql.com|mysql-test/t/ndb_autodiscover.disabled|20050311230559|58101|dda20d04dddbb06jimw@mysql.com|mysql-test/t/ndb_cache_multi2.disabled|20050311230600|47901|84fed1a78c0d3e6djimw@mysql.com|mysql-test/t/ndb_cache_multi.disabled|20050311230600|18039|9657b6eff7deb27ajimw@mysql.com|mysql-test/t/ndb_multi.disabled|20050311230600|12240|2599367ad06100f6jimw@mysql.com|mysql-test/t/ndb_restore.disabled|20050311230600|30718|3c2453d6164b1a30jimw@mysql.com|mysql-test/t/ndb_alter_table.disabled|20050311230559|27526|411e026940e7a0aajimw@mysql.com|mysql-test/t/ndb_autodiscover2.disabled|20050311230559|22363|afa8e5b6e46a3ea1jimw@mysql.com|mysql-test/t/ndb_autodiscover.disabled|20050311230559|58101|dda20d04dddbb06jimw@mysql.com|mysql-test/t/ndb_cache_multi2.disabled|20050311230600|47901|84fed1a78c0d3e6djimw@mysql.com|mysql-test/t/ndb_cache_multi.disabled|20050311230600|18039|9657b6eff7deb27ajimw@mysql.com|mysql-test/t/ndb_multi.disabled|20050311230600|12240|2599367ad06100f6jimw@mysql.com|mysql-test/t/ndb_restore.disabled|20050311230600|30718|3c2453d6164b1a30magnus@neptunus.(none)|ndb/src/client/Makefile|20040414084436|02010|6c2778d2bf4954a2
+jimw@mysql.com|mysql-test/t/ndb_autodiscover.disabled|20050311230559|58101|dda20d04dddbb06
+jimw@mysql.com|mysql-test/t/ndb_autodiscover2.disabled|20050311230559|22363|afa8e5b6e46a3ea1
+jimw@mysql.com|mysql-test/t/ndb_cache_multi.disabled|20050311230600|18039|9657b6eff7deb27a
+jimw@mysql.com|mysql-test/t/ndb_cache_multi2.disabled|20050311230600|47901|84fed1a78c0d3e6d
+jimw@mysql.com|mysql-test/t/ndb_multi.disabled|20050311230600|12240|2599367ad06100f6
+jimw@mysql.com|mysql-test/t/ndb_restore.disabled|20050311230600|30718|3c2453d6164b1a30
+korbit-kernel-2.4.1
+magnus@neptunus.(none)|ndb/src/client/Makefile|20040414084436|02010|6c2778d2bf4954a2
+magnus@neptunus.(none)|ndb/src/client/odbc/Extra.mk|20040414082358|47442|eabbb28986ca817d
+magnus@neptunus.(none)|ndb/src/client/odbc/Makefile|20040414084435|33394|9bc928a18aa88d66
+magnus@neptunus.(none)|ndb/src/client/odbc/NdbOdbc.cpp|20040414082358|49599|aa491b06c9172d11
+magnus@neptunus.(none)|ndb/src/client/odbc/NdbOdbc.def|20040414082358|51708|cd3eed2c4a0121e9
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/CodeGen.cpp|20040414082358|53823|170c83c0765b9160
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/CodeGen.hpp|20040414082358|56074|738f834f80cceba8
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_base.cpp|20040414082358|58196|96f8ceaac8138bfe
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_base.hpp|20040414082358|60340|794baaed32588409
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_column.cpp|20040414082358|62566|5dd0e5c1215bd8bf
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_column.hpp|20040414082358|64739|5d5816d1c496e588
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_comp_op.cpp|20040414082358|01507|6ab02cc3b1e08985
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_comp_op.hpp|20040414082358|03757|37cf1e4cee3a6bf1
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_create_index.cpp|20040414082358|06374|d1f95c5917afab9
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_create_index.hpp|20040414082358|08625|12bcb33350fc35c1
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_create_row.cpp|20040414082358|11036|33f73454f8ddf2d5
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_create_row.hpp|20040414082358|13441|38cb00cc1baa9ee7
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_create_table.cpp|20040414082358|15724|c25e7cc06414a927
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_create_table.hpp|20040414082358|18032|9648f467f3f0418e
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_data_type.cpp|20040414082358|20759|9e46a7ef85345d4
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_data_type.hpp|20040414082358|23055|5e8928968d3c0107
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_ddl.cpp|20040414082358|25484|c38ee5368efaf688
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_ddl.hpp|20040414082358|27775|75482ddd87b65036
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_ddl_column.cpp|20040414082358|32443|c524862773dd9f38
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_ddl_column.hpp|20040414082358|33650|c9e534e381b21599
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_ddl_constr.cpp|20040414082359|02893|80ae32f83a6c2f00
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_ddl_constr.hpp|20040414082359|05185|bca16806c57bc97e
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_ddl_row.cpp|20040414082359|07481|ec2fbc3b8ab08a52
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_ddl_row.hpp|20040414082359|09844|c18a43b3770ad25a
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_delete.cpp|20040414082359|12149|feac77b440d04327
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_delete.hpp|20040414082359|14544|c852ee069a761aab
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_delete_index.cpp|20040414082359|17020|17ed96eca90fe4e7
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_delete_index.hpp|20040414082359|19336|18a9bb119b04636
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_delete_lookup.cpp|20040414082359|23008|1a3728f8c896684
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_delete_lookup.hpp|20040414082359|26530|1be71525ed9ee69
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_delete_scan.cpp|20040414082359|29062|b040ad7670c24eb5
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_delete_scan.hpp|20040414082359|31380|b9a11b4ec895d159
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_dml.cpp|20040414082359|33830|6826ad60f0f566e7
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_dml.hpp|20040414082359|36167|8fdbf19ad3174ca2
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_dml_column.cpp|20040414082359|38509|b71ce6186edf1655
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_dml_column.hpp|20040414082359|40901|a843b3418b30b7a3
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_dml_row.cpp|20040414082359|43239|17c791507b36cc06
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_dml_row.hpp|20040414082359|46942|33c4cffdd238728d
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_drop_index.cpp|20040414082359|54231|fc5cab67ae58d9f6
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_drop_index.hpp|20040414082359|55474|377c9eb280ec2ee2
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_drop_table.cpp|20040414082359|57899|9637d93efa68996a
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_drop_table.hpp|20040414082359|60249|d671379125e4bbbe
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr.cpp|20040414082359|64572|fafd271880c70cf3
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr.hpp|20040414082359|01410|9e8243e99e0ec84
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_column.cpp|20040414082359|03836|4c4fbcd5741cc8cf
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_column.hpp|20040414082359|06355|9c4cbbdf432dc475
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_const.cpp|20040414082359|08702|bdb29dcd94ac5e73
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_const.hpp|20040414082359|12473|9c8789cff376b832
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_conv.cpp|20040414082359|15160|d252fbfe8ef55fff
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_conv.hpp|20040414082359|18741|5cbea39eecb92a43
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_func.cpp|20040414082359|21099|5d3996f062fa3f52
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_func.hpp|20040414082359|23589|22aee1e4f92c49b9
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_op.cpp|20040414082359|25965|e1aaa0244f2efa4
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_op.hpp|20040414082359|28432|4eb8c02dd0602f
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_param.cpp|20040414082359|30810|a5e94ee7c5821611
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_param.hpp|20040414082359|33263|ec441ad8ef21aa2b
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_row.cpp|20040414082400|01179|bc73d8f9c681d418
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_expr_row.hpp|20040414082400|03567|c541c49ea8c0c4f2
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_idx_column.cpp|20040414082400|06012|7d4d074ce5daea0a
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_idx_column.hpp|20040414082400|08377|caabaafa34722be7
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_insert.cpp|20040414082400|10799|7d0ef7cc8f657fd5
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_insert.hpp|20040414082400|14354|cc96fa9b81169471
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_pred.cpp|20040414082400|16798|56faa755aa42ddfa
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_pred.hpp|20040414082400|19159|eada43753e8b1e6c
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_pred_op.cpp|20040414082400|21533|47d693dde1a6d907
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_pred_op.hpp|20040414082400|23992|b42256983d2bda7b
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query.cpp|20040414082400|26355|4ac293821c9b4602
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query.hpp|20040414082400|28888|f86fbd9a108206c0
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_count.cpp|20040414082400|31247|9fa96a57d2dde660
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_count.hpp|20040414082400|33607|bdbe6e4734abc0c5
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_distinct.cpp|20040414082400|37150|3ba18528aa67b9dd
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_distinct.hpp|20040414082400|39517|c12b2b7ff6b2e7b3
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_filter.cpp|20040414082400|41984|a3d067d5d8fb40c
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_filter.hpp|20040414082400|44363|d0a341f2e40f0183
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_group.cpp|20040414082400|46860|4443c844308f9a98
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_group.hpp|20040414082400|49266|ba4691be942c6e2a
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_index.cpp|20040414082400|51663|f0312c9e2f22daf6
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_index.hpp|20040414082400|54471|6baaf1abbb704bb1
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_join.cpp|20040414082400|56943|36e07422c67d6838
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_join.hpp|20040414082400|59419|c4d17d18c4e3b4a0
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_lookup.cpp|20040414082400|61998|3d80e3ddbdae531d
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_lookup.hpp|20040414082400|00081|73332533e5196630
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_project.cpp|20040414082400|01373|ebc22f71bb7ec98c
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_project.hpp|20040414082400|03788|2734cdf1f907e0a4
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_range.cpp|20040414082400|06316|62ddafd2d17063cc
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_range.hpp|20040414082400|09865|81546843616efefa
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_repeat.cpp|20040414082400|11154|ce8f2a065897d6e3
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_repeat.hpp|20040414082400|13697|c20e10d0db9ad53c
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_scan.cpp|20040414082400|16320|855e56d6f56de938
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_scan.hpp|20040414082400|20784|b93c277da5b2509b
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_sort.cpp|20040414082400|24684|c08fc07f739de097
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_sort.hpp|20040414082400|25997|84edb5e128eda962
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_sys.cpp|20040414082400|28427|1d6a4a1cec789001
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_query_sys.hpp|20040414082400|31003|f5182823da25f097
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_root.cpp|20040414082400|33423|4c26a01ced583e41
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_root.hpp|20040414082401|01466|de1fd878505d9e26
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_select.cpp|20040414082401|04049|75b2a39f282d8ef5
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_select.hpp|20040414082401|06512|f9fadc322d78033a
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_set_row.cpp|20040414082401|08991|1bda7e6f86f18aef
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_set_row.hpp|20040414082401|12465|32ac3de384b91229
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_stmt.cpp|20040414082401|13817|c0e9903aa90df90b
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_stmt.hpp|20040414082401|17310|fab11fc487e74d05
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_table.cpp|20040414082401|20990|c46b7a6e2ecf4f61
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_table.hpp|20040414082401|22331|a48d57a0375a6d56
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_table_list.cpp|20040414082402|33460|40948eccedfae7bb
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_table_list.hpp|20040414082402|34739|c1e880e9949d3a
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_update.cpp|20040414082402|37093|ed36f4a7a928a91b
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_update.hpp|20040414082402|39546|c1de760c7b580b0c
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_update_index.cpp|20040414082402|42086|a0c6ad33ffbbc00e
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_update_index.hpp|20040414082402|44472|b57bbe5c8d927df9
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_update_lookup.cpp|20040414082402|46928|3491782088e97384
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_update_lookup.hpp|20040414082402|49343|ee335822c3496863
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_update_scan.cpp|20040414082402|51785|35e5b7d4619b3e09
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Code_update_scan.hpp|20040414082402|54180|287f193ad48fbefd
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/Makefile|20040414084435|20906|420b8378d374f069
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/SimpleGram.ypp|20040414082402|57791|6301cedf92524710
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/SimpleParser.cpp|20040414082402|60351|549f93e2a7fd01b5
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/SimpleParser.hpp|20040414082402|62814|4fdff7ee3839efc4
+magnus@neptunus.(none)|ndb/src/client/odbc/codegen/SimpleScan.lpp|20040414082402|65230|e11862b97fe39faf
+magnus@neptunus.(none)|ndb/src/client/odbc/common/AttrArea.cpp|20040414082402|03357|1570da617a1a6c4b
+magnus@neptunus.(none)|ndb/src/client/odbc/common/AttrArea.hpp|20040414082402|06048|f3d78ccd37af4e6
+magnus@neptunus.(none)|ndb/src/client/odbc/common/CodeTree.cpp|20040414082402|08438|1a4912632b0a61ee
+magnus@neptunus.(none)|ndb/src/client/odbc/common/CodeTree.hpp|20040414082402|10916|dcb603cce390eafa
+magnus@neptunus.(none)|ndb/src/client/odbc/common/ConnArea.cpp|20040414082402|13287|103182cf445f0bc3
+magnus@neptunus.(none)|ndb/src/client/odbc/common/ConnArea.hpp|20040414082402|16782|ffe99deedf7dc1ee
+magnus@neptunus.(none)|ndb/src/client/odbc/common/Ctx.cpp|20040414082402|18121|ce1c13ba8a312eba
+magnus@neptunus.(none)|ndb/src/client/odbc/common/Ctx.hpp|20040414082402|20500|bc88aba55ab71063
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DataField.cpp|20040414082402|22982|6bb1fe1cb971c8f9
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DataField.hpp|20040414082402|25733|d324898a9a86463d
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DataRow.cpp|20040414082402|29367|8764a23cee4f9481
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DataRow.hpp|20040414082402|31983|66a65eee1a1b2f23
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DataType.cpp|20040414082402|34382|29b8ddd51fdd3a2f
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DataType.hpp|20040414082403|02299|adef26bc1dc940eb
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DescArea.cpp|20040414082403|04653|aab4edd7e336acdd
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DescArea.hpp|20040414082403|07055|20ba9b6484762f0f
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DiagArea.cpp|20040414082403|09406|e3662d8977947e67
+magnus@neptunus.(none)|ndb/src/client/odbc/common/DiagArea.hpp|20040414082403|11824|1c6595b5fac06eb2
+magnus@neptunus.(none)|ndb/src/client/odbc/common/Makefile|20040414084435|27122|8505f6b38fe5c219
+magnus@neptunus.(none)|ndb/src/client/odbc/common/OdbcData.cpp|20040414082403|16621|e557009c1ed1e017
+magnus@neptunus.(none)|ndb/src/client/odbc/common/OdbcData.hpp|20040414082403|19077|2125814c1293c0b3
+magnus@neptunus.(none)|ndb/src/client/odbc/common/ResultArea.cpp|20040414082403|21436|8bcc2a2d9a98b9b0
+magnus@neptunus.(none)|ndb/src/client/odbc/common/ResultArea.hpp|20040414082403|23832|8d4646b94be475d1
+magnus@neptunus.(none)|ndb/src/client/odbc/common/Sqlstate.cpp|20040414082403|26171|b844144af963c22c
+magnus@neptunus.(none)|ndb/src/client/odbc/common/Sqlstate.hpp|20040414082403|29665|60006ee1c27c6e5
+magnus@neptunus.(none)|ndb/src/client/odbc/common/StmtArea.cpp|20040414082403|32310|5c5f8613156e06b2
+magnus@neptunus.(none)|ndb/src/client/odbc/common/StmtArea.hpp|20040414082403|34785|9662e56ae164eb7f
+magnus@neptunus.(none)|ndb/src/client/odbc/common/StmtInfo.cpp|20040414082403|37141|54ee4040e5807214
+magnus@neptunus.(none)|ndb/src/client/odbc/common/StmtInfo.hpp|20040414082403|39465|6698d657391692fc
+magnus@neptunus.(none)|ndb/src/client/odbc/common/common.cpp|20040414082403|41862|4792b9ecddd99482
+magnus@neptunus.(none)|ndb/src/client/odbc/common/common.hpp|20040414082403|45229|25369fa6c80eff53
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictCatalog.cpp|20040414082403|46524|9804b0ff3eac2f8
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictCatalog.hpp|20040414082403|50152|cace2fb2f6bb65e5
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictColumn.cpp|20040414082403|56647|b69d90c53e5b618
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictColumn.hpp|20040414082403|58973|c2da1b7bd0408bd1
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictIndex.cpp|20040414082403|62455|a456d3039e6a39e3
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictIndex.hpp|20040414082403|64865|f53b91a41bb96663
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictSchema.cpp|20040414082403|01679|639403c84a47dfdd
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictSchema.hpp|20040414082403|04043|5aa7dc8ade17e94c
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictSys.cpp|20040414082403|06523|fb89465b10c32bb0
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictSys.hpp|20040414082403|08917|76583ba8aa88fd6f
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictTable.cpp|20040414082403|11346|8f4a9ee5a8038f87
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/DictTable.hpp|20040414082403|13733|cf99a9ac3dd49206
+magnus@neptunus.(none)|ndb/src/client/odbc/dictionary/Makefile|20040414084435|30267|4c1a6148787bdc2f
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/class.fig|20040414082403|16124|c0754ccad74d380a
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/descfield.pl|20040414082403|18935|e0bd59c2824824cc
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/diag.txt|20040414082403|21798|b66a7e227391335f
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/getinfo.pl|20040414082403|24266|2142ecf1567a66f6
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/gettypeinfo.pl|20040414082403|27572|2ea4c0589eac4e73
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/handleattr.pl|20040414082403|31383|b0c2a2901b68342e
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/main.hpp|20040414082404|00011|7b15eb7ffad488a0
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/ndbodbc.html|20040414082404|02501|a2f14fdd978b62cc
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/select.fig|20040414082404|04967|34f5222b5012e1d7
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/systables.pl|20040414082404|07386|1fa2191648bdb629
+magnus@neptunus.(none)|ndb/src/client/odbc/docs/type.txt|20040414082404|10311|feec700c81f5095f
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/Func.data|20040414082404|12860|9e75f15d921063f3
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/Func.pl|20040414082404|16530|aefb901bc3941d32
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/Makefile|20040414084435|24049|80d21270fc3ad931
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLAllocConnect.cpp|20040414082404|18964|246af836b028d810
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLAllocEnv.cpp|20040414082404|21279|eaf36cf2285ec2ac
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLAllocHandle.cpp|20040414082404|23612|c0921921e84d1a10
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLAllocHandleStd.cpp|20040414082404|27069|7d145f6e3640d913
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLAllocStmt.cpp|20040414082404|29405|362331ef456ec879
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLBindCol.cpp|20040414082404|31826|fec3a78088d4951d
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLBindParam.cpp|20040414082404|34178|a50b619a23efaab
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLBindParameter.cpp|20040414082404|36965|533b1992496e2775
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLBrowseConnect.cpp|20040414082404|39327|120b61a1ff6edee3
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLBulkOperations.cpp|20040414082404|41701|7a96be04250a388
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLCancel.cpp|20040414082404|45242|27eab683f6fa6ec6
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLCloseCursor.cpp|20040414082404|47634|6cbf193aadaf1058
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLColAttribute.cpp|20040414082404|51528|f2c858b16a9360d
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLColAttributes.cpp|20040414082404|53928|d4007908ee1309d
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLColumnPrivileges.cpp|20040414082404|56456|39a3020da4c3485b
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLColumns.cpp|20040414082404|58871|1c31107df60bb544
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLConnect.cpp|20040414082404|62974|868e02a519b72743
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLCopyDesc.cpp|20040414082404|64271|286522b25a029761
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLDataSources.cpp|20040414082404|01136|12792108aac5b2ca
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLDescribeCol.cpp|20040414082404|03611|1d1faafbcd3ecb3c
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLDescribeParam.cpp|20040414082404|06014|70b016fa795ed275
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLDisconnect.cpp|20040414082404|08470|9fb4c3d7a84db50a
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLDriverConnect.cpp|20040414082404|10866|8dad42af7d17a9d9
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLDrivers.cpp|20040414082404|13335|400e7453e70f6e99
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLEndTran.cpp|20040414082404|15741|c37cce04cc303c01
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLError.cpp|20040414082404|18143|593b81885c15187b
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLExecDirect.cpp|20040414082404|20664|5e6274e76315339d
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLExecute.cpp|20040414082404|24388|1692a85f8639f71
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLExtendedFetch.cpp|20040414082404|27134|8b9d604580a83cfd
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLFetch.cpp|20040414082404|29534|fa1606aa2dd901db
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLFetchScroll.cpp|20040414082404|31991|cdb16803511963a1
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLForeignKeys.cpp|20040414082405|00096|4b8a9af2f6bf92cb
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLFreeConnect.cpp|20040414082405|02501|92359420501ebc5b
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLFreeEnv.cpp|20040414082405|04956|64f1776817464807
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLFreeHandle.cpp|20040414082405|07349|2dc029edf912c2d
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLFreeStmt.cpp|20040414082405|09791|8f8cb0a43c02a67
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetConnectAttr.cpp|20040414082405|13307|b29ff18aeedd8966
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetConnectOption.cpp|20040414082405|15755|3e0bc4e1af95c682
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetCursorName.cpp|20040414082405|19268|8266b920671b6d01
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetData.cpp|20040414082405|21785|3d837348460c219d
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetDescField.cpp|20040414082405|24186|62828192a7d1d954
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetDescRec.cpp|20040414082405|26589|f54cc69bcd1238ad
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetDiagField.cpp|20040414082405|29075|673e1ea0f9d5121f
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetDiagRec.cpp|20040414082405|31498|bea0f68f5b940ab8
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetEnvAttr.cpp|20040414082405|33972|e742277d8bdf234d
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetFunctions.cpp|20040414082405|36391|72de050fbfb4a9bb
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetInfo.cpp|20040414082405|38935|e4e09d6bedbf02b1
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetStmtAttr.cpp|20040414082405|41363|de7dabc8c2acea7
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetStmtOption.cpp|20040414082405|43806|2ff900ebdd167077
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLGetTypeInfo.cpp|20040414082405|46378|333196b07473dff6
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLMoreResults.cpp|20040414082405|48899|483d94cb57379e81
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLNativeSql.cpp|20040414082405|51374|eeae6067f4a85c
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLNumParams.cpp|20040414082405|57810|8921304c3bcf4835
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLNumResultCols.cpp|20040414082405|59136|4d2b6527ffe81059
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLParamData.cpp|20040414082405|62648|163b046513f1e4ae
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLParamOptions.cpp|20040414082405|64040|bdcbccb961fff044
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLPrepare.cpp|20040414082405|00921|1d339fe24888087
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLPrimaryKeys.cpp|20040414082405|03420|5d7b2a0ae08a267
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLProcedureColumns.cpp|20040414082405|05843|c7a0535e9f50ff39
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLProcedures.cpp|20040414082405|08319|c59d025b22e2d1a6
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLPutData.cpp|20040414082405|11934|9dbf69ea9d369dbd
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLRowCount.cpp|20040414082405|14434|d4ac5b273afdb154
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetConnectAttr.cpp|20040414082405|16860|c2c520c34c41bd88
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetConnectOption.cpp|20040414082405|19298|dadc980d9f9cad1b
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetCursorName.cpp|20040414082405|21855|ccfc33dd2cf6abeb
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetDescField.cpp|20040414082405|24355|c4db694d1b9e8f77
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetDescRec.cpp|20040414082405|26866|f8dd72467d5012ab
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetEnvAttr.cpp|20040414082405|29480|7b50aeae6228c2db
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetParam.cpp|20040414082405|31915|e0dd2d5e8d3ec450
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetPos.cpp|20040414082405|34406|39a3e69960041aa7
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetScrollOptions.cpp|20040414082406|03524|6f8250379bb0cac8
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetStmtAttr.cpp|20040414082406|06008|e99b7e6025a1ae1f
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSetStmtOption.cpp|20040414082406|10068|87af3125a48c27fa
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLSpecialColumns.cpp|20040414082406|12486|1877b4c368825de5
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLStatistics.cpp|20040414082406|14949|87e0359f237aa66a
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLTablePrivileges.cpp|20040414082406|17508|fa16ea0fffa4edeb
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLTables.cpp|20040414082406|20645|c8b201068baec393
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/SQLTransact.cpp|20040414082406|23280|eb33c2f66ee85738
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/driver.cpp|20040414082406|25724|f8f1eeec35b08f18
+magnus@neptunus.(none)|ndb/src/client/odbc/driver/driver.hpp|20040414082406|29359|f108f4eef34ec8ea
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_comp_op.cpp|20040414082406|31800|eacbd7512b32d68b
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_create_index.cpp|20040414082406|35482|c6b8e670198adfa9
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_create_table.cpp|20040414082406|37927|76904d417bc0a59a
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_delete_index.cpp|20040414082406|40489|1ffe5af6eb160a68
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_delete_lookup.cpp|20040414082406|43115|5d24028ce16b6623
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_delete_scan.cpp|20040414082406|46919|810aa4058f73c941
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_drop_index.cpp|20040414082406|49349|3a3871ec6ee48c28
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_drop_table.cpp|20040414082406|51862|639a2faba4da14f4
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_expr_conv.cpp|20040414082406|54314|b5452bd4fbd7c945
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_expr_func.cpp|20040414082406|56759|c78ab0e67d54f38c
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_expr_op.cpp|20040414082406|59381|5e341b2e63495ba4
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_insert.cpp|20040414082406|61884|71dd4bf2fb913f2e
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_pred_op.cpp|20040414082406|64460|ebe7b65ba81e5185
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_query_index.cpp|20040414082406|01584|4cada676fa178001
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_query_lookup.cpp|20040414082406|05431|79dfe29b088d832
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_query_range.cpp|20040414082406|06819|7c4e148e81a292d6
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_query_scan.cpp|20040414082406|09339|7c66194f7f93346f
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_query_sys.cpp|20040414082406|11968|d66abe07cd519163
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_update_index.cpp|20040414082406|14543|86140a945f790890
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_update_lookup.cpp|20040414082406|17085|b7a7387620cf42ab
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Exec_update_scan.cpp|20040414082406|19743|2285c72106cffe0
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Executor.cpp|20040414082406|22273|ccb54cc8ffe18bae
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Executor.hpp|20040414082406|24762|c94d916ae5af2506
+magnus@neptunus.(none)|ndb/src/client/odbc/executor/Makefile|20040414084435|12419|a08f437558c2d3b4
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/AttrDbc.cpp|20040414082406|27307|24a034fbb22cdb23
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/AttrEnv.cpp|20040414082406|30042|7d74bcba78e149d0
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/AttrRoot.cpp|20040414082406|32507|5def5d7e228eedf0
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/AttrStmt.cpp|20040414082407|00551|5363ba63b35ff8f4
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/DescSpec.cpp|20040414082407|03310|cd50c1c855f1905
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/FuncTab.cpp|20040414082407|05927|e77abea11a532708
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleBase.cpp|20040414082407|08362|2ba63dce2dfec07b
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleBase.hpp|20040414082407|10820|8cf9a1e94d272328
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleDbc.cpp|20040414082407|13361|2a79fea6477b2c63
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleDbc.hpp|20040414082407|15852|9abc692ac6b0abb3
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleDesc.cpp|20040414082407|18335|e77eb1d73d171a98
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleDesc.hpp|20040414082407|20794|553aeb842b3da88e
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleEnv.cpp|20040414082407|23207|6b96fc6b188f252b
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleEnv.hpp|20040414082407|25666|572a7b4af6816f8b
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleRoot.cpp|20040414082407|28085|aa5044f74554fa9c
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleRoot.hpp|20040414082407|30587|2fcfca742c13cfb3
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleStmt.cpp|20040414082407|33024|782f96bda9eaf13c
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/HandleStmt.hpp|20040414082407|35570|6508fc97f3c772e1
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/InfoTab.cpp|20040414082407|38088|f89104b9c6fe7489
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/Makefile|20040414084435|15527|3d8d1529ad26ce76
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/PoolNdb.cpp|20040414082407|40567|793fa032699b7d98
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/PoolNdb.hpp|20040414082407|43172|db9e1a04d2fe705d
+magnus@neptunus.(none)|ndb/src/client/odbc/handles/handles.hpp|20040414082407|45564|bfe0b6a7a95ac142
+magnus@neptunus.(none)|ndb/src/ndbbaseclient/Makefile|20040414084439|01640|4b92d5e5b416dd0
+magnus@neptunus.(none)|ndb/src/ndbbaseclient/ndbbaseclient_dummy.cpp|20040414082426|08918|daee9eb6acbc94
+magnus@neptunus.(none)|ndb/src/ndbclient/Makefile|20040414084438|29978|f993f3afae0d4308
+magnus@neptunus.(none)|ndb/src/ndbclient/ndbclient_dummy.cpp|20040414082426|11587|73154070f5d0bfbf
+magnus@neptunus.(none)|ndb/src/newtonapi/Makefile|20040414084438|17704|bcbd9a7282094cc
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_binding.cpp|20040414082426|14355|dcc4fb57f9ab6cba
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_bulkread.cpp|20040414082426|17142|4ddfe02a93d2ba11
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_config.cpp|20040414082426|19935|38acf2ad3a932420
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_dac.cpp|20040414082426|10457|4615e3d0d8a15bff
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_error.cpp|20040414082426|12319|a58b4a1628a2d4b9
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_init.cpp|20040414082426|15064|80da7e3fa0775346
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_internal.hpp|20040414082426|17987|54884404e30c8823
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_process.cpp|20040414082426|22216|509e54294bc7efd2
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_process.hpp|20040414082426|24005|f0ddefb3b2d6a662
+magnus@neptunus.(none)|ndb/src/newtonapi/dba_schema.cpp|20040414082426|26757|1c3b8399853c108
+magnus@neptunus.(none)|ndb/src/rep/ExtSender.cpp|20040414082426|29555|1851d559cfddae43
+magnus@neptunus.(none)|ndb/src/rep/ExtSender.hpp|20040414082426|32345|10ae62ec85ee6692
+magnus@neptunus.(none)|ndb/src/rep/Makefile|20040414084438|44449|954f853c2d812c2c
+magnus@neptunus.(none)|ndb/src/rep/NodeConnectInfo.hpp|20040414082427|00605|9c4318dd55f3f84
+magnus@neptunus.(none)|ndb/src/rep/README|20040414082427|03407|6939b06d192a6b99
+magnus@neptunus.(none)|ndb/src/rep/RepApiInterpreter.cpp|20040414082427|06188|8ba561cb831ae353
+magnus@neptunus.(none)|ndb/src/rep/RepApiInterpreter.hpp|20040414082427|08968|31be5af2ba72d263
+magnus@neptunus.(none)|ndb/src/rep/RepApiService.cpp|20040414082427|11699|93d4005333167a0f
+magnus@neptunus.(none)|ndb/src/rep/RepApiService.hpp|20040414082432|07265|42f5ffb7e3baa54e
+magnus@neptunus.(none)|ndb/src/rep/RepCommandInterpreter.cpp|20040414082432|10009|f661a8ff312213f8
+magnus@neptunus.(none)|ndb/src/rep/RepCommandInterpreter.hpp|20040414082432|12750|fb6f22895e8c8679
+magnus@neptunus.(none)|ndb/src/rep/RepComponents.cpp|20040414082432|16488|fb067aee8e5a4a1f
+magnus@neptunus.(none)|ndb/src/rep/RepComponents.hpp|20040414082432|19179|9e632beac4f8bbf8
+magnus@neptunus.(none)|ndb/src/rep/RepMain.cpp|20040414082432|21936|de79cb7b6f3acd18
+magnus@neptunus.(none)|ndb/src/rep/Requestor.cpp|20040414082432|24636|c653fa987f84ce43
+magnus@neptunus.(none)|ndb/src/rep/Requestor.hpp|20040414082432|27340|a499054c9a128dbd
+magnus@neptunus.(none)|ndb/src/rep/RequestorSubscriptions.cpp|20040414082432|30099|f0643f7cc9aa9654
+magnus@neptunus.(none)|ndb/src/rep/SignalQueue.cpp|20040414082432|32849|6d32d876acc1a598
+magnus@neptunus.(none)|ndb/src/rep/SignalQueue.hpp|20040414082432|35536|b92204ff36f399d1
+magnus@neptunus.(none)|ndb/src/rep/TODO|20040414082432|38233|187896dd2e5dfd02
+magnus@neptunus.(none)|ndb/src/rep/adapters/AppNDB.cpp|20040414082432|46457|1db5eafacdeda3b7
+magnus@neptunus.(none)|ndb/src/rep/adapters/AppNDB.hpp|20040414082432|49233|2c3081224b4ff75f
+magnus@neptunus.(none)|ndb/src/rep/adapters/ExtAPI.cpp|20040414082432|51989|d98f38669b10ca97
+magnus@neptunus.(none)|ndb/src/rep/adapters/ExtAPI.hpp|20040414082432|54656|32bcb96bcd2d60c
+magnus@neptunus.(none)|ndb/src/rep/adapters/ExtNDB.cpp|20040414082432|57410|38cccb80529c02c6
+magnus@neptunus.(none)|ndb/src/rep/adapters/ExtNDB.hpp|20040414082432|60222|ee245e7e2c707685
+magnus@neptunus.(none)|ndb/src/rep/adapters/Makefile|20040414084438|21912|bcb9d87fd69a7911
+magnus@neptunus.(none)|ndb/src/rep/adapters/TableInfoPs.hpp|20040414082432|62988|56b1f8f75fe7cb1c
+magnus@neptunus.(none)|ndb/src/rep/dbug_hack.cpp|20040414082432|40989|f090906a24103f0
+magnus@neptunus.(none)|ndb/src/rep/rep_version.hpp|20040414082432|43779|82a23fe4dbb13cab
+magnus@neptunus.(none)|ndb/src/rep/repapi/Makefile|20040414084438|41386|25c4b35b84d945b4
+magnus@neptunus.(none)|ndb/src/rep/repapi/repapi.cpp|20040414082432|00155|82b9b00c67cfdcf7
+magnus@neptunus.(none)|ndb/src/rep/repapi/repapi.h|20040414082432|02987|6f8cf6b53a86a5ae
+magnus@neptunus.(none)|ndb/src/rep/state/Channel.cpp|20040414082432|05711|1d5f62245962b839
+magnus@neptunus.(none)|ndb/src/rep/state/Channel.hpp|20040414082432|08527|71c1d63ef4b2cbfe
+magnus@neptunus.(none)|ndb/src/rep/state/Interval.cpp|20040414082432|11324|3d079ca9cc21124d
+magnus@neptunus.(none)|ndb/src/rep/state/Interval.hpp|20040414082432|14048|85aa46fc419bb109
+magnus@neptunus.(none)|ndb/src/rep/state/Makefile|20040414084438|33082|6a9cedaeedcc4650
+magnus@neptunus.(none)|ndb/src/rep/state/RepState.cpp|20040414082432|16760|3d60b0a46e9477c1
+magnus@neptunus.(none)|ndb/src/rep/state/RepState.hpp|20040414082432|19671|94d7c472c8a7367
+magnus@neptunus.(none)|ndb/src/rep/state/RepStateEvent.cpp|20040414082432|22494|f51d7eb7b7aca0b
+magnus@neptunus.(none)|ndb/src/rep/state/RepStateRequests.cpp|20040414082432|25234|393882166df6929
+magnus@neptunus.(none)|ndb/src/rep/state/testInterval/Makefile|20040414084438|35164|e33e587a7947ac36
+magnus@neptunus.(none)|ndb/src/rep/state/testInterval/testInterval.cpp|20040414082432|27995|993f4118f616e80
+magnus@neptunus.(none)|ndb/src/rep/state/testRepState/Makefile|20040414084438|28225|f5a6d9415d7e0977
+magnus@neptunus.(none)|ndb/src/rep/state/testRepState/testRequestor.cpp|20040414082432|30850|4a943fae5be63c79
+magnus@neptunus.(none)|ndb/src/rep/state/testRepState/testRequestor.hpp|20040414082432|33580|583208c83ff5b554
+magnus@neptunus.(none)|ndb/src/rep/storage/GCIBuffer.cpp|20040414082433|01915|6e8c6f38ab63d1d6
+magnus@neptunus.(none)|ndb/src/rep/storage/GCIBuffer.hpp|20040414082433|04667|703e2016a7ec616f
+magnus@neptunus.(none)|ndb/src/rep/storage/GCIContainer.cpp|20040414082433|07490|9c53acd16fc5ac74
+magnus@neptunus.(none)|ndb/src/rep/storage/GCIContainer.hpp|20040414082433|10275|ac28cea9114659fd
+magnus@neptunus.(none)|ndb/src/rep/storage/GCIContainerPS.cpp|20040414082433|13103|116168903a2c617a
+magnus@neptunus.(none)|ndb/src/rep/storage/GCIContainerPS.hpp|20040414082433|15896|9a801ffe939e192e
+magnus@neptunus.(none)|ndb/src/rep/storage/GCIPage.cpp|20040414082433|18724|42fa918fbf36828a
+magnus@neptunus.(none)|ndb/src/rep/storage/GCIPage.hpp|20040414082433|22604|4197e2278326515e
+magnus@neptunus.(none)|ndb/src/rep/storage/LogRecord.hpp|20040414082433|25752|11644fe7c5f5d36
+magnus@neptunus.(none)|ndb/src/rep/storage/Makefile|20040414084438|25055|a955d34726662aba
+magnus@neptunus.(none)|ndb/src/rep/storage/NodeConnectInfo.hpp|20040414082433|28517|35a7682fd9dba464
+magnus@neptunus.(none)|ndb/src/rep/storage/NodeGroup.cpp|20040414082433|31343|adebbefb11cd1670
+magnus@neptunus.(none)|ndb/src/rep/storage/NodeGroup.hpp|20040414082433|34127|3fcddc2da5d10e45
+magnus@neptunus.(none)|ndb/src/rep/storage/NodeGroupInfo.cpp|20040414082433|36945|b1130e3c42777658
+magnus@neptunus.(none)|ndb/src/rep/storage/NodeGroupInfo.hpp|20040414082433|39718|7fd3b74f4b59a503
+magnus@neptunus.(none)|ndb/src/rep/transfer/Makefile|20040414084438|38260|6b43df78ea480db1
+magnus@neptunus.(none)|ndb/src/rep/transfer/TransPS.cpp|20040414082433|43592|7a88ca746987ac10
+magnus@neptunus.(none)|ndb/src/rep/transfer/TransPS.hpp|20040414082433|46546|846b26eaa80632a1
+magnus@neptunus.(none)|ndb/src/rep/transfer/TransSS.cpp|20040414082433|49370|8f12a062b240eecf
+magnus@neptunus.(none)|ndb/src/rep/transfer/TransSS.hpp|20040414082433|52255|7718b5e4ce9a4007
+magnus@neptunus.(none)|ndb/src/rep/transfer/TransSSSubscriptions.cpp|20040414082433|55067|6bc55e474f33e023
+magnus@neptunus.(none)|ndb/tools/ndbnet/Makefile.PL|20040414082442|56473|81be90388548652f
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net.pm|20040414082442|02828|425c84165071d5f6
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/Base.pm|20040414082442|11671|50a6f0d38fa1a57c
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/Client.pm|20040414082442|14568|45adb527c5cfdaf6
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/Command.pm|20040414082442|17582|a20dff1bfd06ea7a
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/Config.pm|20040414082442|20612|24456d4beba19604
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/Database.pm|20040414082442|23641|cc02e455b02c557
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/Env.pm|20040414082442|26624|ffeca4ab253818c3
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/Node.pm|20040414082442|29671|276106bf4000fe2b
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/NodeApi.pm|20040414082442|32765|3abf1d7bc947d3d0
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/NodeDb.pm|20040414082443|01346|9e3055381da679ce
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/NodeMgmt.pm|20040414082443|04349|5123fbffcfce73cb
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/Server.pm|20040414082443|07453|70208c964371fd4d
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/ServerINET.pm|20040414082443|10474|fc72d28fedd17795
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Net/ServerUNIX.pm|20040414082443|13573|ad3e25435fceb8d0
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Run.pm|20040414082442|05790|9b414f2b4b76a4da
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Run/Base.pm|20040414082443|16656|dd382c9eec2c38b1
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Run/Database.pm|20040414082443|19701|ec533cd5dd6a54a2
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Run/Env.pm|20040414082443|22716|a343841fae6d0514
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Run/Node.pm|20040414082443|25798|339139ded5fcf795
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util.pm|20040414082442|08694|9be64f1195ec502d
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/Base.pm|20040414082443|28821|f39906f304e8a49
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/Dir.pm|20040414082443|31912|4cbe8dd8c57149a7
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/Event.pm|20040414082443|35023|f445c1c094f57cf
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/File.pm|20040414082443|38178|48da8e977f39bf7
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/IO.pm|20040414082443|41286|6c6a63ce63fe2ee5
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/Lock.pm|20040414082443|44445|366e56786358b3d8
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/Log.pm|20040414082443|47535|e0da9468a6f9213a
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/Socket.pm|20040414082443|50710|371ccd6c5a818fa0
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/SocketINET.pm|20040414082443|53816|db8a45b1360b69f2
+magnus@neptunus.(none)|ndb/tools/ndbnet/lib/NDB/Util/SocketUNIX.pm|20040414082443|56977|9ffab2ada7f61530
+magnus@neptunus.(none)|ndb/tools/ndbnet/ndbnet.pl|20040414082442|59371|8f8f1b18f0458269
+magnus@neptunus.(none)|ndb/tools/ndbnet/ndbnetd.pl|20040414082442|62363|e44f1cfe7e8bbe14
+magnus@neptunus.(none)|ndb/tools/ndbnet/ndbrun|20040414082442|65454|5db549d7436ac81b
miguel@hegel.local|zlib/ChangeLog|20020319032513|28917|5d5425fc84737083
miguel@hegel.local|zlib/Make_vms.com|20020319032513|57151|35050a50ec612bbf
miguel@hegel.local|zlib/Makefile.riscos|20020319032513|63798|8ab53f195fe429af
@@ -748,6 +1184,7 @@ mwagner@evoq.home.mwagner.org|mysql-test/xml/xsl/README|20001013051514|26509|cd4
mwagner@evoq.home.mwagner.org|mysql-test/xml/xsl/mysqltest.xsl|20001013051514|27425|1b8f6ec4f1b5f634
mwagner@work.mysql.com|mysql-test/r/3.23/sel000001.result|20001010091454|28284|383913ae4505ec86
mwagner@work.mysql.com|mysql-test/r/3.23/sel000002.result|20001010091454|29230|d1787e6fd5dbc1cc
+ndb/src/client/Makefile
nick@nick.leippe.com|mysql-test/r/rpl_empty_master_crash.result|20020531235552|47718|615f521be2132141
nick@nick.leippe.com|mysql-test/t/rpl_empty_master_crash.test|20020531235552|52328|99464e737639ccc6
reggie@mdk10.(none)|mysql-test/t/reserved_win_names-master.opt|20050520210356|14878|e56da049a7ce9a5b
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 71cdc892376..e9cc35b4c7e 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -7,11 +7,13 @@ Greg@greg-laptop.
Miguel@light.local
Sinisa@sinisa.nasamreza.org
WAX@sergbook.mysql.com
+acurtis@ltantony.rdg.cyberkinetica.homeunix.net
acurtis@pcgem.rdg.cyberkinetica.com
acurtis@xiphis.org
administrador@light.hegel.local
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
akishkin@work.mysql.com
+anjuta@arthur.local
antony@ltantony.dsl-verizon.net
antony@ltantony.mysql.com
antony@ltantony.rdg.cyberkinetica.com
@@ -25,10 +27,12 @@ bar@bar.intranet.mysql.r18.ru
bar@bar.mysql.r18.ru
bar@bar.udmsearch.izhnet.ru
bar@deer.(none)
+bar@eagle.intranet.mysql.r18.ru
bar@gw.udmsearch.izhnet.ru
bar@mysql.com
bar@noter.intranet.mysql.r18.ru
bell@51.0.168.192.in-addr.arpa
+bell@52.0.168.192.in-addr.arpa
bell@book.sanja.is.com.ua
bell@laptop.sanja.is.com.ua
bell@sanja.is.com.ua
@@ -39,6 +43,7 @@ brian@brian-akers-computer.local
brian@private-client-ip-101.oz.net
brian@zim.(none)
carsten@tsort.bitbybit.dk
+cps@silver_beast.(none)
davida@isil.mysql.com
dean@mysql.com
dellis@goetia.(none)
@@ -54,9 +59,12 @@ gbichot@bk-internal.mysql.com
gbichot@production.mysql.com
gbichot@quadita2.mysql.com
gbichot@quadxeon.mysql.com
+geert@kriem.kemuri.org
georg@beethoven.local
+georg@beethoven.site
georg@lmy002.wdf.sap.corp
gerberb@ou800.zenez.com
+gluh@eagle.intranet.mysql.r18.ru
gluh@gluh.(none)
gluh@gluh.mysql.r18.ru
gluh@mysql.com
@@ -89,12 +97,14 @@ jani@a193-229-222-105.elisa-laajakaista.fi
jani@a193-229-222-2.elisa-laajakaista.fi
jani@a80-186-24-72.elisa-laajakaista.fi
jani@a80-186-41-201.elisa-laajakaista.fi
+jani@a80-186-8-224.elisa-laajakaista.fi
jani@dsl-jkl1657.dial.inet.fi
jani@dsl-kpogw4gb5.dial.inet.fi
jani@hynda.(none)
jani@hynda.mysql.fi
jani@ibmlab.site
jani@janikt.pp.saunalahti.fi
+jani@linux.local
jani@rhols221.adsl.netsonic.fi
jani@rhols221.arenanet.fi
jani@ua126d19.elisa.omakaista.fi
@@ -109,6 +119,10 @@ jcole@sarvik.tfr.cafe.ee
jcole@tetra.spaceapes.com
jimw@mysql.com
joerg@mysql.com
+joerg@trift-lap.fambruehe
+jon@gigan.
+jonas@mysql.com
+joreland@bk-internal.mysql.com
joreland@mysql.com
jorge@linux.jorge.mysql.com
jplindst@t41.(none)
@@ -116,14 +130,17 @@ kaa@polly.local
kaj@work.mysql.com
kent@mysql.com
konstantin@mysql.com
+kosipov@production.mysql.com
kostja@oak.local
lars@mysql.com
lenz@kallisto.mysql.com
lenz@mysql.com
+magnus@msdesk.mysql.com
magnus@neptunus.(none)
magnus@shellback.(none)
marko@hundin.mysql.fi
marty@linux.site
+marty@shark.
mats@mysql.com
matt@booty.(none)
matt@mysql.com
@@ -160,9 +177,11 @@ monty@tramp.mysql.fi
monty@work.mysql.com
mronstrom@build.mysql.com
mronstrom@mysql.com
+mskold@bk-internal.mysql.com
mskold@mysql.com
msvensson@build.mysql.com
msvensson@neptunus.(none)
+msvensson@neptunus.homeip.net
mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
mwagner@here.mwagner.org
@@ -172,6 +191,7 @@ mwagner@work.mysql.com
mydev@mysql.com
mysql@home.(none)
mysql@mc04.(none)
+mysqldev@bk-internal.mysql.com
mysqldev@build.mysql2.com
mysqldev@melody.local
mysqldev@mysql.com
@@ -180,10 +200,16 @@ ndbdev@dl145b.mysql.com
ndbdev@dl145c.mysql.com
ndbdev@eel.hemma.oreland.se
ndbdev@ndbmaster.mysql.com
+ndbdev@shark.
nick@mysql.com
nick@nick.leippe.com
+obarnir@mysql.com
papa@gbichot.local
+patg@krsna.
patg@krsna.patg.net
+patg@patrick-galbraiths-computer.local
+patg@pc248.lfp.kcls.org
+patg@radha.local
paul@central.snake.net
paul@frost.snake.net
paul@ice.local
@@ -193,15 +219,20 @@ paul@snake-hub.snake.net
paul@teton.kitebird.com
pekka@mysql.com
pem@mysql.com
+pem@per-erik-martins-dator.local
peter@linux.local
peter@mysql.com
peterg@mysql.com
petr@mysql.com
pgulutzan@linux.local
+pmartin@build.mysql2.com
+psergey@psergey-rh8.(none)
+psergey@psergey.(none)
ram@deer.(none)
ram@gw.mysql.r18.ru
ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru
+ram@ram-book.(none)
ram@ram.(none)
ramil@mysql.com
ranger@regul.home.lan
@@ -219,8 +250,11 @@ salle@geopard.online.bg
salle@vafla.home
salle@vafla.online.bg
sasha@mysql.sashanet.com
+schwenke@lmy003.wdf.sap.corp
+schwenke@lmy003.xl.local
serg@build.mysql.com
serg@build.mysql2.com
+serg@mysql.com
serg@serg.mylan
serg@serg.mysql.com
serg@sergbook.mylan
@@ -261,6 +295,8 @@ ulli@morbus.(none)
venu@hundin.mysql.fi
venu@myvenu.com
venu@work.mysql.com
+vtkachenko@intelp4d.mysql.com
+vtkachenko@mail.mysql.com
vva@eagle.mysql.r18.ru
vva@genie.(none)
vva@mysql.r18.ru
diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit
index a54086a0d0d..fe263b79325 100755
--- a/BitKeeper/triggers/post-commit
+++ b/BitKeeper/triggers/post-commit
@@ -5,7 +5,7 @@ FROM=$USER@mysql.com
INTERNALS=internals@lists.mysql.com
DOCS=docs-commit@mysql.com
LIMIT=10000
-VERSION="4.1"
+VERSION="5.0"
if [ "$REAL_EMAIL" = "" ]
then
@@ -58,7 +58,7 @@ $BH
EOF
bk changes -v -r+
bk cset -r+ -d
- ) | head -n $LIMIT | /usr/sbin/sendmail -t
+ ) | /usr/sbin/sendmail -t
#++
# internals@ mail
@@ -102,7 +102,7 @@ Subject: bk commit - $VERSION tree (Manual) ($CHANGESET)$BS
EOF
bk changes -v -r+
bk cset -r+ -d
- ) | head -n $LIMIT | /usr/sbin/sendmail -t
+ ) | /usr/sbin/sendmail -t
fi
else
diff --git a/Docs/changelog-5.0.xml b/Docs/changelog-5.0.xml
new file mode 100755
index 00000000000..deb059716ad
--- /dev/null
+++ b/Docs/changelog-5.0.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+<!--
+This is a dummy changelog file. Don't use it yet.
+It merges upward without conflict.
+-->
+<appendix id="news-5.0-x">
+
+ <title>
+ Changes in release 5.0.x
+ </title>
+
+ <para>
+ This is a dummy changelog file. Don't use it yet.
+ </para>
+
+</appendix>
diff --git a/Docs/sp-imp-spec.txt b/Docs/sp-imp-spec.txt
new file mode 100644
index 00000000000..ac17a375926
--- /dev/null
+++ b/Docs/sp-imp-spec.txt
@@ -0,0 +1,1100 @@
+
+ Implementation specification for Stored Procedures
+ ==================================================
+
+
+- How parsing and execution of queries work
+
+ In order to execute a query, the function sql_parse.cc:mysql_parse() is
+ called, which in turn calls the parser (yyparse()) with an updated Lex
+ structure as the result. mysql_parse() then calls mysql_execute_command()
+ which dispatches on the command code (in Lex) to the corresponding code for
+ executing that particular query.
+
+ There are three structures involved in the execution of a query which are of
+ interest to the stored procedure implementation:
+
+ - Lex (mentioned above) is the "compiled" query, that is the output from
+ the parser and what is then interpreted to do the actual work.
+ It constains an enum value (sql_command) which is the query type, and
+ all the data collected by the parser needed for the execution (table
+ names, fields, values, etc).
+ - THD is the "run-time" state of a connection, containing all that is
+ needed for a particular client connection, and, among other things, the
+ Lex structure currently being executed.
+ - Item_*: During parsing, all data is translated into "items", objects of
+ the subclasses of "Item", such as Item_int, Item_real, Item_string, etc,
+ for basic datatypes, and also various more specialized Item types for
+ expressions to be evaluated (Item_func objects).
+
+
+- How to fit Stored Procedure into this scheme
+
+ - An overview of the classes and files for stored procedures
+ (More detailed APIs at the end of this file)
+
+ - class sp_head (sp_head.{cc,h})
+ This contains, among other things, an array of "instructions" and the
+ method for executing the procedure.
+
+ - class sp_pcontext (sp_pcontext.{cc,h}
+ This is the parse context for the procedure. It's primarily used during
+ parsing to keep track of local parameters, variables and labels, but
+ it's also used at CALL time do find parameters mode (IN, OUT or INOUT)
+ and type when setting up the runtime context.
+
+ - class sp_instr (sp_head.{cc,h})
+ This is the base class for "instructions", that is, what is generated
+ by the parser. It turns out that we only need a minimum of 5 different
+ sub classes:
+ - sp_instr_stmt
+ Execute a statement. This is the "call-out" any normal SQL statement,
+ like a SELECT, INSERT etc. It contains the Lex structure for the
+ statement in question.
+ - sp_instr_set
+ Set the value of a local variable (or parameter)
+ - sp_instr_jump
+ An unconditional jump.
+ - sp_instr_jump_if_not
+ Jump if condition is not true. It turns out that the negative test is
+ most convenient when generating the code for the flow control
+ constructs.
+ - sp_instr_freturn
+ Return a value from a FUNCTION and exit.
+ For condition HANDLERs some special instructions are also needed, see
+ that section below.
+
+ - class sp_rcontext (sp_rcontext.h)
+ This is the runtime context in the THD structure.
+ It contains an array of items, the parameters and local variables for
+ the currently executing stored procedure.
+ This means that variable value lookup is in runtime is constant time,
+ a simple index operation.
+
+ - class Item_splocal (Item.{cc,h})
+ This is a subclass of Item. Its sole purpose is to hide the fact that
+ the real Item is actually in the current frame (runtime context).
+ It contains the frame offset and defers all methods to the real Item
+ in the frame. This is what the parser generates for local variables.
+
+ - Utility functions (sp.{cc,h})
+ This contains functions for creating, dropping and finding a stored
+ procedure in the mysql.proc table (or the internal cache).
+
+
+ - Parsing CREATE PROCEDURE ...
+
+ When parsing a CREATE PROCEDURE the parser first initializes the
+ sphead and spcont (runtime context) fields in the Lex.
+ The sql_command code for the result of parsing a is
+ SQLCOM_CREATE_PROCEDURE.
+
+ The parsing of the parameter list and body is relatively
+ straight-forward:
+
+ - Parameters:
+ name, type and mode (IN/OUT/INOUT) is pushed to spcont
+ - Declared local variables:
+ Same as parameters (mode is then IN)
+ - Local Variable references:
+ If an identifier is found in in spcont, an Item_splocal is created
+ with the variable's frame index, otherwise an Item_field or Item_ref
+ is created (as before).
+ - Statements:
+ The Lex in THD is replaced by a new Lex structure and the statement,
+ is parsed as usual. A sp_instr_stmt is created, containing the new
+ Lex, and added to added to the instructions in sphead.
+ Afterwards, the procedure's Lex is restored in THD.
+ - SET var:
+ Setting a local variable generates a sp_instr_set instruction,
+ containing the variable's frame offset, the expression (an Item),
+ and the type.
+ - Flow control:
+ Flow control constructs like, IF, WHILE, etc, generate a conditional
+ and unconditional jumps in the "obvious" way, but a few notes may
+ be required:
+ - Forward jumps: When jumping forward, the exact destination is not
+ known at the time of the creation of the jump instruction. The
+ sphead therefore contains list of instruction-label pairs for
+ each forward reference. When the position later is known, the
+ instructions in the list are updated with the correct location.
+ - Loop constructs have optional labels. If a loop doesn't have a
+ label, an anonymous label is generated to simplify the parsing.
+ - There are two types of CASE. The "simple" case is implemented
+ with an anonymous variable bound to the value to be tested.
+
+
+ - A simple example
+
+ Parsing the procedure:
+
+ create procedure a(s char(16))
+ begin
+ declare x int;
+ set x = 3;
+ while x > 0 do
+ set x = x-1;
+ insert into db.tab values (x, s);
+ end while;
+ end
+
+ would generate the following structures:
+ ______
+ thd: | | _________
+ | lex -+--->| | ___________________
+ |______| | spcont -+------------------->| "s",in,char(16):0 |
+ | sphead -+------ |("x",in,int :1)|
+ |_________| | |___________________|
+ ____V__________________
+ | m_name: "a" |
+ | m_defstr: "create ..."|
+ | m_instr: ... |
+ |_______________________|
+
+ Note that the contents of the spcont is changing during the parsing,
+ at all times reflecting the state of the would-be runtime frame.
+ The m_instr is an array of instructions:
+
+ Pos. Instruction
+ 0 sp_instr_set(1, '3')
+ 1 sp_instr_jump_if_not(5, 'x>0')
+ 2 sp_instr_set(1, 'x-1')
+ 3 sp_instr_stmt('insert into ...')
+ 4 sp_instr_jump(1)
+ 5 <end>
+
+ Here, '3', 'x>0', etc, represent the Items or Lex for the respective
+ expressions or statements.
+
+
+ - Parsing CREATE FUNCTION ...
+
+ Creating a functions is essensially the same thing as for a PROCEDURE,
+ with the addition that a FUNCTION has a return type and a RETURN
+ statement, but no OUT or INOUT parameters.
+
+ The main difference during parsing is that we store the result type
+ in the sp_head. However, there are big differences when it comes to
+ invoking a FUNCTION. (See below.)
+
+
+ - Storing, caching, dropping...
+
+ As seen above, the entired definition string, including the "CREATE
+ PROCEDURE" (or "FUNCTION") is kept. The procedure definition string is
+ stored in the table mysql.proc with the name and type as the key, the
+ type being one of the enum ("procedure","function").
+
+ A PROCEDURE is just stored in the mysql.proc table. A FUNCTION has an
+ additional requirement. They will be called in expressions with the same
+ syntax as UDFs, so UDFs and stored FUNCTIONs share the namespace. Thus,
+ we must make sure that we do not have UDFs and FUNCTIONs with the same
+ name (even if they are storded in different places).
+
+ This means that we can reparse the procedure as many time as we want.
+ The first time, the resulting Lex is used to store the procedure in
+ the database (using the function sp.c:sp_create_procedure()).
+
+ The simplest way would be to just leave it at that, and re-read the
+ procedure from the database each time it is called. (And in fact, that's
+ the way the earliest implementation will work.)
+ However, this is not very efficient, and we can do better. The full
+ implementation should work like this:
+
+ 1) Upon creation time, parse and store the procedure. Note that we still
+ need to parse it to catch syntax errors, but we can't check if called
+ procedures exists for instance.
+ 2) Upon first CALL, read from the database, parse it, and cache the
+ resulting Lex in memory. This time we can do more error checking.
+ 3) Upon subsequent CALLs, use the cached Lex.
+
+ Note that this implies that the Lex structure with its sphead must be
+ reentrant, that is, reusable and shareable between different threads
+ and calls. The runtime state for a procedure is kept in the sp_rcontext
+ in THD.
+
+ The mechanisms of storing, finding, and dropping procedures are
+ encapsulated in the files sp.{cc,h}.
+
+
+ - CALLing a procedure
+
+ A CALL is parsed just like any statement. The resulting Lex has the
+ sql_command SQLCOM_CALL, the procedure's name and the parameters are
+ pushed to the Lex' value_list.
+
+ sql_parse.cc:mysql_execute_command() then uses sp.cc:sp_find() to
+ get the sp_head for the procedure (which may have been read from the
+ database or feetched from the in-memory cache) and calls the sp_head's
+ method execute().
+ Note: It's important that substatements called by the procedure do not
+ do send_ok(). Fortunately, there is a flag in THD->net to disable
+ this during CALLs. If a substatement fails, it will however send
+ an error back to the client, so the CALL mechanism must return
+ immediately and without sending an error.
+
+ The sp_head::execute() method works as follows:
+
+ 1) Keep a pointer to the old runtime context in THD (if any)
+ 2) Create a new runtime context. The information about the required size
+ is in sp_head's parse time context.
+ 3) Push each parameter (from the CALL's Lex->value_list) to the new
+ context. If it's an OUT or INOUT parameter, the parameter's offset
+ in the caller's frame is set in the new context as well.
+ 4) For each instruction, call its execute() method.
+ The result is a pointer to the next instruction to execute (or NULL)
+ if an error occured.
+ 5) On success, set the new values of the OUT and INOUT parameters in
+ the caller's frame.
+
+ - USE database
+
+ Before executing the instruction we also keeps the current default
+ database (if any). If this was changed during execution (i.e. a "USE"
+ statement has been executed), we restore the current database to the
+ original.
+
+ This is the most useful way to handle USE in procedures. If we didn't,
+ the caller would find himself in a different database after calling
+ a function, which can be confusing.
+ Restoring the database also gives full freedom to the procedure writer:
+ - It's possible to write "general" procedures that are independent of
+ the actual database name.
+ - It's possible to write procedures that work on a particular database
+ by calling USE, without having to use fully qualified table names
+ everywhere (which doesn't help if you want to call other, "general",
+ procedures anyway).
+
+ - Evaluating Items
+
+ There are three occasions where we need to evaluate an expression:
+
+ - When SETing a variable
+ - When CALLing a procedure
+ - When testing an expression for a branch (in IF, WHILE, etc)
+
+ The semantics in stored procedures is "call-by-value", so we have to
+ evaluate any "func" Items at the point of the CALL or SET, otherwise
+ we would get a kind of "lazy" evaluation with unexpected results with
+ respect to OUT parameters for instance.
+ For this the support function, sp_head.cc:eval_func_item() is needed.
+
+
+ - Calling a FUNCTION
+
+ Functions don't have an explicit call keyword like procedures. Instead,
+ they appear in expressions with the conventional syntax "fun(arg, ...)".
+ The problem is that we already have User Defined Functions (UDFs) which
+ are called the same way. A UDF is detected by the lexical analyzer (not
+ the parser!), in the find_keyword() function, and returns a UDF_*_FUNC
+ or UDA_*_SUM token with the udf_func object as the yylval.
+
+ So, stored functions must be handled in a simpilar way, and as a
+ consequence, UDFs and functions must not have the same name.
+
+ - Detecting and parsing a FUNCTION invocation
+
+ The existance of UDFs are checked during the lexical analysis (in
+ sql_lex.cc:find_keyword()). This has the drawback that they must
+ exist before they are refered to, which was ok before SPs existed,
+ but then it becomes a problem. The first implementation of SP FUNCTIONs
+ will work the same way, but this should be fixed a.s.a.p. (This will
+ required some reworking of the way UDFs are handled, which is why it's
+ not done from the start.)
+ For the time being, a FUNCTION is detected the same way, and returns
+ the token SP_FUNC. During the parsing we only check for the *existance*
+ of the function, we don't parse it, since wa can't call the parser
+ recursively.
+
+ When encountering a SP_FUNC with parameters in the expression parser,
+ an instance of the new Item_func_sp class is created. Unlike UDFs, we
+ don't have different classes for different return types, since we at
+ this point don't know the type.
+
+ - Collecting FUNCTIONs to invoke
+
+ A FUNCTION differs from a PROCEDURE in one important aspect: Whereas a
+ PROCEDURE is CALLed as statement by itself, a FUNCTION is invoked
+ "on-the-fly" during the execution of *another* statement.
+ This makes things a lot more complicated compared to CALL:
+ - We can't read and parse the FUNCTION from the mysql.proc table at the
+ point of invocation; the server requires that all tables used are
+ opened and locked at the beginning of the query execution.
+ One "obvious" solution would be to simply push "mysql.proc" to the list
+ of tables used by the query, but this implies a "join" with this table
+ if the query is a select, so it doesn't work (and we can't exclude this
+ table easily; since a priviledged used might in fact want to search
+ the proc table).
+ Another solution would of course be to allow the opening and closing
+ of the mysql.proc table during a query execution, but this it not
+ possible at the present.
+
+ So, the solution is to collect the names of the refered FUNCTIONs during
+ parsing in the lex.
+ Then, before doing anything else in mysql_execute_command(), read all
+ functions from the database an keep them in the THD, where the function
+ sp_find_function() can find them during the execution.
+ Note: Even with an in-memory cache, we must still make sure that the
+ functions are indeed read and cached at this point.
+ The code that read and cache functions from the database must also be
+ invoked recursively for each read FUNCTION to make sure we have *all* the
+ functions we need.
+
+
+ - Parsing DROP PROCEDURE/FUNCTION
+
+ The procedure name is pushed to Lex->value_list.
+ The sql_command code for the result of parsing a is
+ SQLCOM_DROP_PROCEDURE/SQLCOM_DROP_FUNCTION.
+
+ Dropping is done by simply getting the procedure with the sp_find()
+ function and calling sp_drop() (both in sp.{cc,h}).
+
+ DROP PROCEDURE/FUNCTION also supports the non-standard "IF EXISTS",
+ analogous to other DROP statements in MySQL.
+
+
+ - Condition and Handlers
+
+ Condition names are lexical entities and are kept in the parser context
+ just like variables. But, condition are just "aliases" for SQLSTATE
+ strings, or mysqld error codes (which is a non-standard extension in
+ MySQL), and are only used during parsing.
+
+ Handlers comes in three types, CONTINUE, EXIT and UNDO. The latter is
+ like an EXIT handler with an implicit rollback, and is currently not
+ implemented.
+ The EXIT handler jumps to the end of its BEGIN-END block when finished.
+ The CONTINUE handler returns to the statement following that which
+ invoked the handler.
+
+ The handlers in effect at any point is part of each thread's runtime
+ state, so we need to push and pop handlers in the sp_rcontext during
+ execution. We use special instructions for this:
+ - sp_instr_hpush_jump
+ Push a handler. The instruction contains the necessary information,
+ like which conditions we handle and the location of the handler.
+ The jump takes us to the location after the handler code.
+ - sp_instr_hpop
+ Pop the handlers of the current frame (which we are just leaving).
+
+ It might seems strange to jump past the handlers like that, but there's
+ no extra cost in doing this, and for technical reasons it's easiest for
+ the parser to generate the handler instructions when they occur in the
+ source.
+
+ When an error occurs, one of the error routines is called and an error
+ message is normally sent back to the client immediately.
+ Catching a condition must be done in these error routines (there are
+ quite a few) to prevent them from doing this. We do this by calling
+ a method in the THD's sp_rcontext (if there is one). If a handler is
+ found, this is recorded in the context and the routine returns without
+ sending the error message.
+ The exectution loop (sp_head::execute()) checks for this after each
+ statement and invokes the handler that has been found. If several
+ errors or warnings occurs during one statement, only the first is
+ caught, the rest are ignored.
+
+ Invoking and returning from a handler is trivial in the EXIT case.
+ We simply jump to it, and it will have an sp_instr_jump as its last
+ instruction.
+
+ Calling and returning from a CONTINUE handler poses some special
+ problems. Since we need to return to the point after its invokation,
+ we push the return location on a stack in the sp_rcontext (this is
+ done by the exectution loop). The handler then ends with a special
+ instruction, sp_instr_hreturn, which returns to this location.
+
+ CONTINUE handlers have one additional problem: They are parsed at
+ the lexical level where they occur, so variable offsets will assume
+ that it's actually called at that level. However, a handler might be
+ invoked from a sub-block where additional local variables have been
+ declared, which will then share the location of any local variables
+ in the handler itself. So, when calling a CONTINUE handler, we need
+ to save any local variables above the handler's frame offset, and
+ restore them upon return. (This is not a problem for EXIT handlers,
+ since they will leave the block anyway.)
+ This is taken care of by the execution loop and the sp_instr_hreturn
+ instruction.
+
+ - Examples:
+
+ - EXIT handler
+ begin
+ declare x int default 0;
+
+ begin
+ declare exit handler for 'XXXXX' set x = 1;
+
+ (statement1);
+ (statement2);
+ end;
+ (statement3);
+ end
+
+ Pos. Instruction
+ 0 sp_instr_set(0, '0')
+ 1 sp_instr_hpush_jump(4, 1) # location and frame size
+ 2 sp_instr_set(0, '1')
+ 3 sp_instr_jump(6)
+ 4 sp_instr_stmt('statement1')
+ 5 sp_instr_stmt('statement2')
+ 6 sp_instr_hpop(1)
+ 7 sp_instr_stmt('statement3')
+
+ - CONTINUE handler
+ create procedure hndlr1(val int)
+ begin
+ declare x int default 0;
+ declare foo condition for 1146;
+ declare continue handler for foo set x = 1;
+
+ insert into t3 values ("hndlr1", val); # Non-existing table?
+ if x>0 then
+ insert into t1 values ("hndlr1", val); # This instead then
+ end if;
+ end|
+
+ Pos. Instruction
+ 0 sp_instr_set(1, '0')
+ 1 sp_instr_hpush_jump(4, 2)
+ 2 sp_instr_set(1, '1')
+ 3 sp_instr_hreturn(2) # frame size
+ 4 sp_instr_stmt('insert ... t3 ...')
+ 5 sp_instr_jump_if_not(7, 'x>0')
+ 6 sp_instr_stmt('insert ... t1 ...')
+ 7 sp_instr_hpop(2)
+
+
+ - Cursors
+
+ For stored procedures to be really useful, you want to have cursors.
+ MySQL doesn't yet have "real" cursor support (with API and ODBC support,
+ allowing updating, arbitrary scrolling, etc), but a simple asensitive,
+ non-scrolling, read-only cursor can be implemented in SPs using the
+ class Protocol_cursor.
+ This class intecepts the creation and sending of results sets and instead
+ stores it in-memory, as MYSQL_FIELDS and MYSQL_ROWS (as in the client API).
+
+ To support this, we need the usual name binding support in sp_pcontext
+ (similar to variables and conditions) to keep track on declared cursor
+ names, and a corresponding run-time mechanism in sp_rcontext.
+ Cursors are lexically scoped like everything with a body or BEGIN/END
+ block, so they are pushed and poped as usual (see conditions and variables
+ above).
+ The basic operations on a cursor are OPEN, FETCH and CLOSE, which will
+ each have a corresponding instruction. In addition, we need instructions
+ to push a new cursor (this will encapsulate the LEX of the SELECT statement
+ of the cursor), and a pop instruction:
+ - sp_instr_cpush
+ Push a cursor to the sp_rcontext. This instruction contains the LEX
+ for the select statement
+ - sp_instr_cpop
+ Pop a number of cursors from the sp_rcontext.
+ - sp_instr_copen
+ Open a cursor: This will execute the select and get the result set
+ in a sepeate memroot.
+ - sp_instr_cfetch
+ Fetch the next row from the in-memory result set. The instruction
+ contains a list of the variables (frame offsets) to set.
+ - sp_instr_cclose
+ Free the result set.
+
+ A cursor is a separate class, sp_cursor (defined in sp_rcontex.h) which
+ encapsulates the basic operations used by the above instructions.
+ This class contains the LEX, Protocol_cursor object, and its memroot,
+ as well as the cursor's current state.
+ Compiling and executing is fairly straight-forward. sp_instr_copen is
+ a subclass of sp_instr_stmt and uses its mechanism to execute a
+ substatement.
+
+ - Example:
+
+ begin
+ declare x int;
+ declare c cursor for select a from t1;
+
+ open c;
+ fetch c into x;
+ close c;
+ end
+
+ Pos. Instruction
+ 0 sp_instr_cpush('select a from ...')
+ 1 sp_instr_copen(0) # The 0'th cursor
+ 2 sp_instr_cfetch(0) # Contains the variable list
+ 3 sp_instr_cclose(0)
+ 4 sp_instr_cpop(1)
+
+
+
+ - The SP cache
+
+ There are two ways to cache SPs:
+
+ 1) one global cache, share by all threads/connections,
+ 2) one cache per thread.
+
+ There are pros and cons with both methods:
+
+ 1) Pros: Save memory, each SP only read from table once,
+ Cons: Needs locking (= serialization at access), requires thread-safe
+ data structures,
+ 2) Pros: Fast, no locking required (almost), limited thread-safe
+ requirement,
+ Cons: Uses more memory, each SP read from table once per thread.
+
+ Unfortunately, we cannot use alternative 1 for the time being, as most
+ of the datastructures to be cached (lex and items) are not reentrant
+ and thread-safe. (Things are modifed at execution, we have THD pointers
+ stored everywhere, etc.)
+ This leaves us with alternative 2, one cache per thread; or actually
+ two, since we keep FUNCTIONs and PROCEDUREs in separate caches.
+ This is not that terrible; the only case when it will perform
+ significantly worse than a global cache is when we have an application
+ where new threads are connecting, calling a procedure, and disconnecting,
+ over and over again.
+
+ The cache implementation itself is simple and straightforward, a hashtable
+ wrapped in a class and a C API (see APIs below).
+
+ There is however one issue with multiple caches: dropping and altering
+ procedures. Normally, this should be a very rare event in a running
+ system; it's typically something you do during development and testing,
+ so it's not unthinkable that we would simply ignore the issue and let
+ any threads running with a cached version of an SP keep doing so until
+ its disconnected.
+ But assuming we want to keep the caches consistent with respect to drop
+ and alter, it can be done:
+
+ 1) A global counter is needed, initialized to 0 at start.
+ 2) At each DROP or ALTER, increase the counter by one.
+ 3) Each cache has its own copy of the counter, copied at the last read.
+ 4) When looking up a name in the cache, first check if the global counter
+ is larger than the local copy.
+ If so, clear the cache and return "not found", and update the local
+ counter; otherwise, lookup as usual.
+
+ This minimizes the cost to a single brief lock for the access of an
+ integer when operating normally. Only in the event of an actual drop or
+ alter, is the cache cleared. This may seem to be drastic, but since we
+ assume that this is a rare event, it's not a problem.
+ It would of course be possible to have a much more fine-grained solution,
+ keeping track of each SP, but the overhead of doing so is not worth the
+ effort.
+
+
+ - Class and function APIs
+ This is an outline of the key types. Some types and other details
+ in the actual files have been omitted for readability.
+
+ - The parser context: sp_pcontext.h
+
+ typedef enum
+ {
+ sp_param_in,
+ sp_param_out,
+ sp_param_inout
+ } sp_param_mode_t;
+
+ typedef struct
+ {
+ LEX_STRING name;
+ enum enum_field_types type;
+ sp_param_mode_t mode;
+ uint offset; // Offset in current frame
+ my_bool isset;
+ } sp_pvar_t;
+
+ typedef struct sp_cond_type
+ {
+ enum { number, state, warning, notfound, exception } type;
+ char sqlstate[6];
+ uint mysqlerr;
+ } sp_cond_type_t;
+
+ class sp_pcontext
+ {
+ sp_pcontext();
+
+ // Return the maximum frame size
+ uint max_framesize();
+
+ // Return the current frame size
+ uint current_framesize();
+
+ // Return the number of parameters
+ uint params();
+
+ // Set the number of parameters to the current frame size
+ void set_params();
+
+ // Set type of the variable at offset 'i' in the frame
+ void set_type(uint i, enum enum_field_types type);
+
+ // Mark the i:th variable to "set" (i.e. having a value) with
+ // 'val' true.
+ void set_isset(uint i, my_bool val);
+
+ // Push the variable 'name' to the frame.
+ void push_var(LEX_STRING *name,
+ enum enum_field_types type, sp_param_mode_t mode);
+
+ // Pop 'num' variables from the frame.
+ void pop_var(uint num = 1);
+
+ // Find variable by name
+ sp_pvar_t *find_pvar(LEX_STRING *name);
+
+ // Find variable by index
+ sp_pvar_t *find_pvar(uint i);
+
+ // Push label 'name' of instruction index 'ip' to the label context
+ sp_label_t *push_label(char *name, uint ip);
+
+ // Find label 'name' in the context
+ sp_label_t *find_label(char *name);
+
+ // Return the last pushed label
+ sp_label_t *last_label();
+
+ // Return and remove the last pushed label.
+ sp_label_t *pop_label();
+
+ // Push a condition to the context
+ void push_cond(LEX_STRING *name, sp_cond_type_t *val);
+
+ // Pop a 'num' condition from the context
+ void pop_cond(uint num);
+
+ // Find a condition in the context
+ sp_cond_type_t *find_cond(LEX_STRING *name);
+
+ // Increase the handler count
+ void add_handler();
+
+ // Returns the handler count
+ uint handlers();
+
+ // Push a cursor
+ void push_cursor(LEX_STRING *name);
+
+ // Find a cursor
+ my_bool find_cursor(LEX_STRING *name, uint *poff);
+
+ // Pop 'num' cursors
+ void pop_cursor(uint num);
+
+ // Return the number of cursors
+ uint cursors();
+ }
+
+
+ - The run-time context (call frame): sp_rcontext.h
+
+ #define SP_HANDLER_NONE 0
+ #define SP_HANDLER_EXIT 1
+ #define SP_HANDLER_CONTINUE 2
+ #define SP_HANDLER_UNDO 3
+
+ typedef struct
+ {
+ struct sp_cond_type *cond;
+ uint handler; // Location of handler
+ int type;
+ uint foffset; // Frame offset for the handlers declare level
+ } sp_handler_t;
+
+ class sp_rcontext
+ {
+ // 'fsize' is the max size of the context, 'hmax' the number of handlers,
+ // 'cmax' the number of cursors
+ sp_rcontext(uint fsize, uint hmax, , uint cmax);
+
+ // Push value (parameter) 'i' to the frame
+ void push_item(Item *i);
+
+ // Set slot 'idx' to value 'i'
+ void set_item(uint idx, Item *i);
+
+ // Return the item in slot 'idx'
+ Item *get_item(uint idx);
+
+ // Set the "out" index 'oidx' for slot 'idx. If it's an IN slot,
+ // use 'oidx' -1.
+ void set_oindex(uint idx, int oidx);
+
+ // Return the "out" index for slot 'idx'
+ int get_oindex(uint idx);
+
+ // Set the FUNCTION result
+ void set_result(Item *i);
+
+ // Get the FUNCTION result
+ Item *get_result();
+
+ // Push handler at location 'h' for condition 'cond'. 'f' is the
+ // current variable frame size.
+ void push_handler(sp_cond_type_t *cond, uint h, int type, uint f);
+
+ // Pop 'count' handlers
+ void pop_handlers(uint count);
+
+ // Find a handler for this error. This sets the state for a found
+ // handler in the context. If called repeatedly without clearing,
+ // only the first call's state is kept.
+ int find_handler(uint sql_errno);
+
+ // Returns 1 if a handler has been found, with '*ip' and '*fp' set
+ // to the handler location and frame size respectively.
+ int found_handler(uint *ip, uint *fp);
+
+ // Clear the found handler state.
+ void clear_handler();
+
+ // Push a return address for a CONTINUE handler
+ void push_hstack(uint ip);
+
+ // Pop the CONTINUE handler return stack
+ uint pop_hstack();
+
+ // Save variables from frame index 'fp' and up.
+ void save_variables(uint fp);
+
+ // Restore saved variables from to frame index 'fp' and up.
+ void restore_variables(uint fp);
+
+ // Push a cursor for the statement (lex)
+ void push_cursor(LEX *lex);
+
+ // Pop 'count' cursors
+ void pop_cursors(uint count);
+
+ // Pop all cursors
+ void pop_all_cursors();
+
+ // Get the 'i'th cursor
+ sp_cursor *get_cursor(uint i);
+
+ }
+
+
+ - The procedure: sp_head.h
+
+ #define TYPE_ENUM_FUNCTION 1
+ #define TYPE_ENUM_PROCEDURE 2
+
+ class sp_head
+ {
+ int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
+
+ sp_head();
+
+ void init(LEX_STRING *name, LEX *lex, LEX_STRING *comment, char suid);
+
+ // Store this procedure in the database. This is a wrapper around
+ // the function sp_create_procedure().
+ int create(THD *);
+
+ // Invoke a FUNCTION
+ int
+ execute_function(THD *thd, Item **args, uint argcount, Item **resp);
+
+ // CALL a PROCEDURE
+ int
+ execute_procedure(THD *thd, List<Item> *args);
+
+ // Add the instruction to this procedure.
+ void add_instr(sp_instr *);
+
+ // Returns the number of instructions.
+ uint instructions();
+
+ // Returns the last instruction
+ sp_instr *last_instruction();
+
+ // Resets lex in 'thd' and keeps a copy of the old one.
+ void reset_lex(THD *);
+
+ // Restores lex in 'thd' from our copy, but keeps some status from the
+ // one in 'thd', like ptr, tables, fields, etc.
+ void restore_lex(THD *);
+
+ // Put the instruction on the backpatch list, associated with
+ // the label.
+ void push_backpatch(sp_instr *, struct sp_label *);
+
+ // Update all instruction with this label in the backpatch list to
+ // the current position.
+ void backpatch(struct sp_label *);
+
+ // Returns the SP name (with optional length in '*lenp').
+ char *name(uint *lenp = 0);
+
+ // Returns the result type for a function
+ Item_result result();
+
+ // Sets various attributes
+ void sp_set_info(char *creator, uint creatorlen,
+ longlong created, longlong modified,
+ bool suid, char *comment, uint commentlen);
+ }
+
+
+ - Instructions
+
+ - The base class:
+ class sp_instr
+ {
+ // 'ip' is the index of this instruction
+ sp_instr(uint ip);
+
+ // Execute this instrution.
+ // '*nextp' will be set to the index of the next instruction
+ // to execute. (For most instruction this will be the
+ // instruction following this one.)
+ // Returns 0 on success, non-zero if some error occured.
+ virtual int execute(THD *, uint *nextp)
+ }
+
+ - Statement instruction:
+ class sp_instr_stmt : public sp_instr
+ {
+ sp_instr_stmt(uint ip);
+
+ int execute(THD *, uint *nextp);
+
+ // Set the statement's Lex
+ void set_lex(LEX *);
+
+ // Return the statement's Lex
+ LEX *get_lex();
+ }
+
+ - SET instruction:
+ class sp_instr_set : public sp_instr
+ {
+ // 'offset' is the variable's frame offset, 'val' the value,
+ // and 'type' the variable type.
+ sp_instr_set(uint ip,
+ uint offset, Item *val, enum enum_field_types type);
+
+ int execute(THD *, uint *nextp);
+ }
+
+ - Unconditional jump
+ class sp_instr_jump : public sp_instr
+ {
+ // No destination, must be set.
+ sp_instr_jump(uint ip);
+
+ // 'dest' is the destination instruction index.
+ sp_instr_jump(uint ip, uint dest);
+
+ int execute(THD *, uint *nextp);
+
+ // Set the destination instruction 'dest'.
+ void set_destination(uint dest);
+ }
+
+ - Conditional jump
+ class sp_instr_jump_if_not : public sp_instr_jump
+ {
+ // Jump if 'i' evaluates to false. Destination not set yet.
+ sp_instr_jump_if_not(uint ip, Item *i);
+
+ // Jump to 'dest' if 'i' evaluates to false.
+ sp_instr_jump_if_not(uint ip, Item *i, uint dest)
+
+ int execute(THD *, uint *nextp);
+ }
+
+ - Return a function value
+ class sp_instr_freturn : public sp_instr
+ {
+ // Return the value 'val'
+ sp_instr_freturn(uint ip, Item *val, enum enum_field_types type);
+
+ int execute(THD *thd, uint *nextp);
+ }
+
+ - Push a handler and jump
+ class sp_instr_hpush_jump : public sp_instr_jump
+ {
+ // Push handler of type 'htype', with current frame size 'fp'
+ sp_instr_hpush_jump(uint ip, int htype, uint fp);
+
+ int execute(THD *thd, uint *nextp);
+
+ // Add condition for this handler
+ void add_condition(struct sp_cond_type *cond);
+ }
+
+ - Pops handlers
+ class sp_instr_hpop : public sp_instr
+ {
+ // Pop 'count' handlers
+ sp_instr_hpop(uint ip, uint count);
+
+ int execute(THD *thd, uint *nextp);
+ }
+
+ - Return from a CONTINUE handler
+ class sp_instr_hreturn : public sp_instr
+ {
+ // Return from handler, and restore variables to 'fp'.
+ sp_instr_hreturn(uint ip, uint fp);
+
+ int execute(THD *thd, uint *nextp);
+ }
+
+ - Push a CURSOR
+ class sp_instr_cpush : public sp_instr_stmt
+ {
+ // Push a cursor for statement 'lex'
+ sp_instr_cpush(uint ip, LEX *lex)
+
+ int execute(THD *thd, uint *nextp);
+ }
+
+ - Pop CURSORs
+ class sp_instr_cpop : public sp_instr_stmt
+ {
+ // Pop 'count' cursors
+ sp_instr_cpop(uint ip, uint count)
+
+ int execute(THD *thd, uint *nextp);
+ }
+
+ - Open a CURSOR
+ class sp_instr_copen : public sp_instr_stmt
+ {
+ // Open the 'c'th cursor
+ sp_instr_copen(uint ip, uint c);
+
+ int execute(THD *thd, uint *nextp);
+ }
+
+ - Close a CURSOR
+ class sp_instr_cclose : public sp_instr
+ {
+ // Close the 'c'th cursor
+ sp_instr_cclose(uint ip, uint c);
+
+ int execute(THD *thd, uint *nextp);
+ }
+
+ - Fetch a row with CURSOR
+ class sp_instr_cfetch : public sp_instr
+ {
+ // Fetch next with the 'c'th cursor
+ sp_instr_cfetch(uint ip, uint c);
+
+ int execute(THD *thd, uint *nextp);
+
+ // Add a target variable for the fetch
+ void add_to_varlist(struct sp_pvar *var);
+ }
+
+
+ - Utility functions: sp.h
+
+ #define SP_OK 0
+ #define SP_KEY_NOT_FOUND -1
+ #define SP_OPEN_TABLE_FAILED -2
+ #define SP_WRITE_ROW_FAILED -3
+ #define SP_DELETE_ROW_FAILED -4
+ #define SP_GET_FIELD_FAILED -5
+ #define SP_PARSE_ERROR -6
+
+ // Finds a stored procedure given its name. Returns NULL if not found.
+ sp_head *sp_find_procedure(THD *, LEX_STRING *name);
+
+ // Store the procedure 'name' in the database. 'def' is the complete
+ // definition string ("create procedure ...").
+ int sp_create_procedure(THD *,
+ char *name, uint namelen,
+ char *def, uint deflen,
+ char *comment, uint commentlen, bool suid);
+
+ // Drop the procedure 'name' from the database.
+ int sp_drop_procedure(THD *, char *name, uint namelen);
+
+ // Finds a stored function given its name. Returns NULL if not found.
+ sp_head *sp_find_function(THD *, LEX_STRING *name);
+
+ // Store the function 'name' in the database. 'def' is the complete
+ // definition string ("create function ...").
+ int sp_create_function(THD *,
+ char *name, uint namelen,
+ char *def, uint deflen,
+ char *comment, uint commentlen, bool suid);
+
+ // Drop the function 'name' from the database.
+ int sp_drop_function(THD *, char *name, uint namelen);
+
+
+ - The cache: sp_cache.h
+
+ /* Initialize the SP caching once at startup */
+ void sp_cache_init();
+
+ /* Clear the cache *cp and set *cp to NULL */
+ void sp_cache_clear(sp_cache **cp);
+
+ /* Insert an SP to cache. If **cp points to NULL, it's set to a
+ new cache */
+ void sp_cache_insert(sp_cache **cp, sp_head *sp);
+
+ /* Lookup an SP in cache */
+ sp_head *sp_cache_lookup(sp_cache **cp, char *name, uint namelen);
+
+ /* Remove an SP from cache */
+ void sp_cache_remove(sp_cache **cp, sp_head *sp);
+
+
+ - The mysql.proc schema:
+
+ CREATE TABLE proc (
+ db char(64) binary DEFAULT '' NOT NULL,
+ name char(64) DEFAULT '' NOT NULL,
+ type enum('FUNCTION','PROCEDURE') NOT NULL,
+ specific_name char(64) DEFAULT '' NOT NULL,
+ language enum('SQL') DEFAULT 'SQL' NOT NULL,
+ sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL,
+ is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,
+ security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL,
+ param_list blob DEFAULT '' NOT NULL,
+ returns char(64) DEFAULT '' NOT NULL,
+ body blob DEFAULT '' NOT NULL,
+ definer char(77) binary DEFAULT '' NOT NULL,
+ created timestamp,
+ modified timestamp,
+ sql_mode set(
+ 'REAL_AS_FLOAT',
+ 'PIPES_AS_CONCAT',
+ 'ANSI_QUOTES',
+ 'IGNORE_SPACE',
+ 'NOT_USED',
+ 'ONLY_FULL_GROUP_BY',
+ 'NO_UNSIGNED_SUBTRACTION',
+ 'NO_DIR_IN_CREATE',
+ 'POSTGRESQL',
+ 'ORACLE',
+ 'MSSQL',
+ 'DB2',
+ 'MAXDB',
+ 'NO_KEY_OPTIONS',
+ 'NO_TABLE_OPTIONS',
+ 'NO_FIELD_OPTIONS',
+ 'MYSQL323',
+ 'MYSQL40',
+ 'ANSI',
+ 'NO_AUTO_VALUE_ON_ZERO'
+ ) DEFAULT 0 NOT NULL,
+ comment char(64) binary DEFAULT '' NOT NULL,
+ PRIMARY KEY (db,name,type)
+ ) comment='Stored Procedures';
+
+ --
+ \ No newline at end of file
diff --git a/Docs/sp-implemented.txt b/Docs/sp-implemented.txt
new file mode 100644
index 00000000000..6f2cf49b3b0
--- /dev/null
+++ b/Docs/sp-implemented.txt
@@ -0,0 +1,112 @@
+Stored Procedures implemented 2004-01-29:
+
+
+Summary of what's implemented:
+
+ - SQL PROCEDUREs/FUNCTIONs (CREATE/DROP)
+ - CALL
+ - DECLARE of local variables
+ - BEGIN/END, SET, CASE, IF, LOOP, WHILE, REPEAT, ITERATE, LEAVE
+ - SELECT INTO local variables
+ - "Non-query" FUNCTIONs only
+ - Prepared SP caching
+ - CONDITIONs and HANDLERs
+ - Simple read-only CURSORs.
+ - SHOW CREATE PROCEDURE/FUNCTION and SHOW PROCEDURE/FUNCTION STATUS
+
+
+Summary of Not Yet Implemented:
+
+ - SQL statements using tables (like SELECT, INSERT, UPDATE etc) in FUNCTIONs
+ - External languages
+ - Access control
+ - SQL-99 COMMIT (related to BEGIN/END)
+ - FOR-loops
+ - CASCADE/RESTRICT for ALTER and DROP
+ - ALTER/DROP METHOD (as it implies User Defined Types)
+ - SIGNAL and RESIGNAL, and UNDO handlers
+
+
+List of what's implemented:
+
+ - CREATE PROCEDURE|FUNCTION name ( args ) characteristics body
+ where characteristics is:
+ LANGUAGE SQL |
+ [NOT] DETERMINISTIC |
+ SQL SECURITY [DEFINER|INVOKER] |
+ COMMENT string
+ However the DETERMINISTIC setting is not currently used.
+
+ - ALTER PROCEDURE|FUNCTION name characteristics
+ CASCADE/RESTRICT is not implemented.
+ characteristics is:
+ COMMENT string |
+ SQL SECURITY [DEFINER|INVOKER] |
+ NAME newname
+
+ - DROP PROCEDURE|FUNCTION [IF EXISTS] name
+ CASCADE/RESTRICT is not implemented.
+
+ - CALL name (args)
+ OUT and INOUT parameters are also works for user variables ("global"
+ variables) - i.e., if a procedure is defined as:
+ CREATE PROCEDURE foo(OUT p INT) ...;
+ a call like:
+ CALL foo(@x);
+ will set @x to the output value.
+
+ - Function/Procedure body:
+ - BEGIN/END
+ Is parsed, but not the real thing with (optional) transaction
+ control, it only serves as block syntax for multiple statements (and
+ local variable binding).
+ Note: Multiple statements requires a client that can send bodies
+ containing ";". This is handled in the CLI clients mysql and
+ mysqltest with the "delimiter" command. Changing the end-of-query
+ delimiter ";" to for instance "|" allows ";" to be used in the
+ routine body.
+ - SET of local variables
+ Implemented as part of the pre-existing SET syntax. This allows an
+ extended syntax of "SET a=x, b=y, ..." where different variable types
+ (SP local and global) can be mixed. This also allows combinations
+ of local variables and some options that only make sense for
+ global/system variables; in that case the options are accepted but
+ ignored.
+ - The flow control constructs: CASE, IF, LOOP, WHILE, ITERATE and LEAVE
+ are fully implemented.
+ - SELECT ... INTO local variables (as well as global session variables)
+ is implemented. (Note: This is not SQL-99 feature, but common in other
+ databases.)
+ - A FUNCTION can have flow control contructs, but must not contain
+ an SQL query/statement, like SELECT, INSERT, UPDATE, etc. The reason
+ is that it's hard to allow this is that a FUNCTION is executed as part
+ of another query (unlike a PROCEDURE, which is called as a statement).
+ The table locking scheme used makes it difficult to allow "subqueries"
+ during FUNCTION invokation.
+ - SPs are cached, but with a separate cache for each thread (THD).
+ There are still quite a few non-reentrant constructs in the lexical
+ context which makes sharing prepared SPs impossible. And, even when
+ this is resolved, it's not necessarily the case that it will be faster
+ than a cache per thread. A global cache requires locks, which might
+ become a bottleneck. (It would save memory though.)
+ - CONDITIONs and HANDLERs are implemented, but not the SIGNAL and
+ RESIGNAL statements. (It's unclear if these can be implemented.)
+ The semantics of CONDITIONs is expanded to allow catching MySQL error
+ codes as well. UNDO handlers are not implemented (since we don't have
+ SQL-99 style transaction control yet).
+ - Simple read-only CURSORs are implemented, but not yet any of the
+ optional arguments to DECLARE (SCROLL, SENSITIVE, etc) or FETCH
+ (NEXT, PRIOR, etc). Cursors are ASENSITIVE, READ-ONLY, non-SCROLLing.
+ (The additional syntax will be added for completeness, but for the
+ most part unsupported with the current underlying cursor mechanism.)
+ N.B. The current implementation is temporary and only works within a
+ stored procedure, and may not perform well for very large result sets.
+ A "real" cursor implementation is under development; this will replace
+ the current one when it's finished.
+
+ - SHOW procedures and functions
+ SHOW CREATE PROCEDURE|FUNCTION <name>
+ returns the definition of a routine.
+ SHOW PROCEDURE|FUNCTION STATUS [LIKE <pattern>]
+ returns characteristics of routines, like the name, type, creator,
+ creation and modification dates, etc.
diff --git a/Makefile.am b/Makefile.am
index ae0d56ba9fd..ee0353349ea 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,19 +20,19 @@ AUTOMAKE_OPTIONS = foreign
# These are built from source in the Docs directory
EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT
-SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
+SUBDIRS = . include @docs_dirs@ @zlib_dir@ @yassl_dir@ \
@readline_topdir@ sql-common \
@thread_dirs@ pstack \
@sql_union_dirs@ scripts @man_dirs@ tests \
netware @libmysqld_dirs@ \
- @bench_dirs@ support-files @fs_dirs@ @tools_dirs@
+ @bench_dirs@ support-files @tools_dirs@
DIST_SUBDIRS = . include @docs_dirs@ zlib \
@readline_topdir@ sql-common \
@thread_dirs@ pstack \
@sql_union_dirs@ scripts @man_dirs@ tests SSL\
BUILD netware os2 @libmysqld_dirs@ \
- @bench_dirs@ support-files @fs_dirs@ @tools_dirs@
+ @bench_dirs@ support-files @tools_dirs@
# Relink after clean
linked_sources = linked_client_sources linked_server_sources \
@@ -103,21 +103,19 @@ MYSQL_TEST_MANAGER_PORT = 9305
MYSQL_TEST_MASTER_PORT = 9306
MYSQL_TEST_SLAVE_PORT = 9308
MYSQL_TEST_NDB_PORT = 9350
-
+MYSQL_TEST_RUN_ARGS = --manager-port=$(MYSQL_TEST_MANAGER_PORT) \
+ --master_port=$(MYSQL_TEST_MASTER_PORT) \
+ --slave_port=$(MYSQL_TEST_SLAVE_PORT) \
+ --ndbcluster_port=$(MYSQL_TEST_NDB_PORT)
test:
cd mysql-test ; \
- ./mysql-test-run.pl \
- --manager-port=$(MYSQL_TEST_MANAGER_PORT) \
- --master_port=$(MYSQL_TEST_MASTER_PORT) \
- --slave_port=$(MYSQL_TEST_SLAVE_PORT) \
- --ndbcluster_port=$(MYSQL_TEST_NDB_PORT) && \
- ./mysql-test-run.pl --ps-protocol \
- --manager-port=$(MYSQL_TEST_MANAGER_PORT) \
- --master_port=$(MYSQL_TEST_MASTER_PORT) \
- --slave_port=$(MYSQL_TEST_SLAVE_PORT) \
- --ndbcluster_port=$(MYSQL_TEST_NDB_PORT)
+ ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) && \
+ ./mysql-test-run.pl --ps-protocol $(MYSQL_TEST_RUN_ARGS)
test-force:
- cd mysql-test; \
- ./mysql-test-run --force ;\
- ./mysql-test-run --ps-protocol --force
+ cd mysql-test ; \
+ ./mysql-test-run --force $(MYSQL_TEST_RUN_ARGS) ; \
+ ./mysql-test-run --ps-protocol --force $(MYSQL_TEST_RUN_ARGS)
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/VC++Files/bdb/bdb.vcproj b/VC++Files/bdb/bdb.vcproj
new file mode 100755
index 00000000000..6258da3cb3a
--- /dev/null
+++ b/VC++Files/bdb/bdb.vcproj
@@ -0,0 +1,3227 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="bdb"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Max|Win32"
+ OutputDirectory=".\max"
+ IntermediateDirectory=".\max"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-max"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../bdb/build_win32,../bdb"
+ PreprocessorDefinitions="NDEBUG;DBUG_OFF;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\max/bdb.pch"
+ AssemblerListingLocation=".\max/"
+ ObjectFile="max/"
+ ProgramDataBaseFileName="max/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\bdb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../bdb/build_win32,../bdb,../bdb/dbinc"
+ PreprocessorDefinitions="__WIN32__;_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/bdb.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\bdb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="btree\bt_compare.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_conv.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_curadj.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_cursor.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_delete.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_open.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_put.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_rec.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_reclaim.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_recno.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_rsearch.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_search.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_split.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_stat.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_upgrade.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\bt_verify.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btree\btree_auto.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\crdel_auto.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\crdel_rec.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_am.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_auto.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="common\db_byteorder.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_cam.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_conv.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_dispatch.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_dup.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="common\db_err.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="common\db_getlong.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="common\db_idspace.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_iface.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_join.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="common\db_log2.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_meta.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_open.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_overflow.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_pr.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_rec.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_reclaim.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_remove.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_rename.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_ret.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="env\db_salloc.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="env\db_shash.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_truncate.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_upg.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_upg_opd.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_vrfy.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="db\db_vrfyutil.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dbm\dbm.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dbreg\dbreg.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dbreg\dbreg_auto.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dbreg\dbreg_rec.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dbreg\dbreg_util.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="env\env_file.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="env\env_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="env\env_open.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="env\env_recover.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="env\env_region.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fileops\fileops_auto.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fileops\fop_basic.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fileops\fop_rec.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fileops\fop_util.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_auto.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_conv.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_dup.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_func.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_meta.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_open.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_page.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_rec.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_reclaim.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_stat.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_upgrade.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash\hash_verify.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hmac\hmac.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hsearch\hsearch.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lock\lock.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lock\lock_deadlock.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lock\lock_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lock\lock_region.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lock\lock_stat.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lock\lock_util.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log\log.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log\log_archive.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log\log_compare.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log\log_get.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log\log_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log\log_put.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_alloc.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_bh.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_fget.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_fopen.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_fput.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_fset.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_region.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_register.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_stat.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_sync.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mp\mp_trickle.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mutex\mut_tas.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mutex\mut_win32.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mutex\mutex.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_abs.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_alloc.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_clock.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_config.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_dir.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_errno.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_fid.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_fsync.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_handle.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_id.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_map.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_oflags.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_open.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_region.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_rename.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_root.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_rpath.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_rw.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_seek.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_sleep.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_spin.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_stat.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_tmpdir.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os_win32\os_type.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os_unlink.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_auto.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_conv.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_files.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_open.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_rec.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_stat.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_upgrade.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qam\qam_verify.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rep\rep_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rep\rep_record.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rep\rep_region.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rep\rep_util.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hmac\sha1.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="clib\strcasecmp.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="txn\txn.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="txn\txn_auto.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="txn\txn_method.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="txn\txn_rec.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="txn\txn_recover.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="txn\txn_region.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="txn\txn_stat.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="txn\txn_util.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="common\util_log.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="common\util_sig.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="xa\xa.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="xa\xa_db.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="xa\xa_map.c">
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/client/mysql.dsp b/VC++Files/client/mysql.dsp
index 8298e62d8ad..ac74515b588 100644
--- a/VC++Files/client/mysql.dsp
+++ b/VC++Files/client/mysql.dsp
@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /I "../extra/yassl/include" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
# SUBTRACT CPP /WX /Fr /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -52,7 +52,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /machine:I386
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\"
# SUBTRACT LINK32 /incremental:yes
!ELSEIF "$(CFG)" == "mysql - Win32 Debug"
@@ -69,7 +69,7 @@ LINK32=xilink6.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../" /I "../extra/yassl/include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
# SUBTRACT CPP /Fr /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
@@ -78,7 +78,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysql.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysql.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
!ELSEIF "$(CFG)" == "mysql - Win32 classic"
@@ -94,9 +94,9 @@ LINK32=xilink6.exe
# PROP Intermediate_Dir "classic"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /G6 /MT /W3 /WX /O2 /I "../include" /I "../" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c
+# ADD BASE CPP /nologo /G6 /MT /W3 /WX /O2 /I "../include" /I "../" /I "../extra/yassl/include" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /WX /O2 /I "../include" /I "../" /D "_CONSOLE" /D "_WINDOWS" /D LICENSE=Commercial /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /WX /O2 /I "../include" /I "../" /I "../extra/yassl/include" /D "_CONSOLE" /D "_WINDOWS" /D LICENSE=Commercial /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -104,9 +104,9 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=xilink6.exe
-# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\"
+# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\"
# SUBTRACT BASE LINK32 /incremental:yes
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_classic/mysql.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_classic/mysql.exe" /libpath:"..\lib_release\\"
# SUBTRACT LINK32 /incremental:yes
!ENDIF
diff --git a/VC++Files/client/mysql.vcproj b/VC++Files/client/mysql.vcproj
new file mode 100755
index 00000000000..72cc4ba6b89
--- /dev/null
+++ b/VC++Files/client/mysql.vcproj
@@ -0,0 +1,318 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysql"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../extra/yassl/include"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysql.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ WarnAsError="TRUE"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_classic/mysql.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\classic/mysql.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysql.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../extra/yassl/include"
+ PreprocessorDefinitions="NDEBUG;DBUG_OFF;_CONSOLE;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysql.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_release/mysql.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\release/mysql.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/mysql.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../extra/yassl/include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysql.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_debug/mysql.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/mysql.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/mysql.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="completion_hash.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mysql.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ DebugInformationFormat="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ DebugInformationFormat="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="readline.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_string.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/client/mysqladmin.dsp b/VC++Files/client/mysqladmin.dsp
index b473d104a76..d0d29cfcaaf 100644
--- a/VC++Files/client/mysqladmin.dsp
+++ b/VC++Files/client/mysqladmin.dsp
@@ -52,7 +52,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /machine:I386
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\"
!ELSEIF "$(CFG)" == "mysqladmin - Win32 Debug"
@@ -77,7 +77,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqladmin.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqladmin.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
!ELSEIF "$(CFG)" == "mysqladmin - Win32 classic"
@@ -104,7 +104,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=xilink6.exe
# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\"
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqladmin.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqladmin.exe" /libpath:"..\lib_release\\"
!ENDIF
diff --git a/VC++Files/client/mysqladmin.vcproj b/VC++Files/client/mysqladmin.vcproj
new file mode 100755
index 00000000000..188bf61dff7
--- /dev/null
+++ b/VC++Files/client/mysqladmin.vcproj
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqladmin"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqladmin.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_classic/mysqladmin.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/mysqladmin.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysqladmin.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqladmin.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_release/mysqladmin.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\release/mysqladmin.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/mysqladmin.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysqladmin.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_debug/mysqladmin.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/mysqladmin.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/mysqladmin.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="mysqladmin.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp
index 9a6fd933041..c14fc31ab8d 100644
--- a/VC++Files/client/mysqlclient.dsp
+++ b/VC++Files/client/mysqlclient.dsp
@@ -42,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 "MYSQL_CLIENT" /D "NDEBUG" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /I "../extra/yassl/include" /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
@@ -66,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" /D "MYSQL_CLIENT" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../" /I "../extra/yassl/include" /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
@@ -91,7 +91,7 @@ LIB32=xilink6.exe -lib
# 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
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /I "../extra/yassl/include" /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
@@ -147,11 +147,11 @@ SOURCE="..\strings\ctype-bin.c"
# End Source File
# Begin Source File
-SOURCE="..\strings\ctype-czech.c"
+SOURCE="..\strings\ctype-cp932.c"
# End Source File
# Begin Source File
-SOURCE="..\strings\ctype-cp932.c"
+SOURCE="..\strings\ctype-czech.c"
# End Source File
# Begin Source File
@@ -159,6 +159,10 @@ SOURCE="..\strings\ctype-euc_kr.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-eucjpms.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-extra.c"
# End Source File
# Begin Source File
@@ -330,6 +334,10 @@ SOURCE=..\mysys\my_alloc.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\my_chsize.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\my_compress.c
# ADD CPP /I "../zlib"
# End Source File
@@ -443,10 +451,6 @@ SOURCE=..\mysys\my_symlink2.c
# End Source File
# Begin Source File
-SOURCE=..\mysys\my_tempnam.c
-# End Source File
-# Begin Source File
-
SOURCE=..\libmysql\my_time.c
# End Source File
# Begin Source File
@@ -479,6 +483,10 @@ SOURCE=..\sql\net_serv.cpp
# End Source File
# Begin Source File
+SOURCE=..\libmysql\manager.c
+# End Source File
+# Begin Source File
+
SOURCE=..\libmysql\pack.c
# End Source File
# Begin Source File
@@ -559,6 +567,10 @@ SOURCE=..\strings\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\thr_mutex.c
# End Source File
# Begin Source File
diff --git a/VC++Files/client/mysqlclient.vcproj b/VC++Files/client/mysqlclient.vcproj
new file mode 100755
index 00000000000..eebba9ebe0e
--- /dev/null
+++ b/VC++Files/client/mysqlclient.vcproj
@@ -0,0 +1,3333 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqlclient"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../extra/yassl/include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;MYSQL_CLIENT;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqlclient.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\mysqlclient.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="authent|Win32"
+ OutputDirectory=".\authent"
+ IntermediateDirectory=".\authent"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../extra/yassl/include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;MYSQL_CLIENT;NDEBUG;CHECK_LICENSE;LICENSE=Commercial"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\authent/mysqlclient.pch"
+ AssemblerListingLocation=".\authent/"
+ ObjectFile=".\authent/"
+ ProgramDataBaseFileName=".\authent/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_authent\mysqlclient.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../extra/yassl/include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;USE_TLS;MYSQL_CLIENT"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysqlclient.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\mysqlclient.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\mysys\array.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\bchange.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\bmove.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\bmove_upp.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\charset-def.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\charset.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\client.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-big5.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-bin.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-cp932.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-czech.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-euc_kr.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-eucjpms.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-extra.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-gb2312.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-gbk.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-latin1.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-mb.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-simple.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-sjis.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-tis620.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-uca.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-ucs2.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-ujis.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-utf8.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-win1250ch.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\dbug\dbug.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\default.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\errmsg.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\errors.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\get_password.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\int2str.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\is_prefix.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\libmysql.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\list.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\llstr.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\longlong2str.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\manager.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_cache.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_dirname.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_fn_ext.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_format.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_iocache.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_iocache2.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_loadpath.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_pack.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_path.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_tempfile.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_unixpath.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_wcomp.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mulalloc.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_access.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_alloc.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_chsize.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_compress.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories="../zlib"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories="../zlib"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../zlib"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_create.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_delete.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_div.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_error.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_file.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_fopen.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_fstream.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_gethostbyname.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_getopt.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_getwd.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_init.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_lib.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_malloc.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_messnc.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_net.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_once.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_open.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_pread.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_pthread.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_read.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_realloc.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_rename.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_seek.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_static.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\my_strtoll10.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_symlink.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_symlink2.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_thr_init.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\my_time.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\my_vsnprintf.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_wincond.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_winthread.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_write.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mysys_priv.h">
+ </File>
+ <File
+ RelativePath="..\sql\net_serv.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\pack.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\password.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\safemalloc.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\sha1.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\str2int.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\str_alloc.c">
+ </File>
+ <File
+ RelativePath="..\strings\strcend.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strcont.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strend.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strfill.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\string.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strinstr.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strmake.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strmov.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strnlen.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strnmov.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strtod.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strtoll.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strtoull.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strxmov.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strxnmov.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\thr_mutex.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\typelib.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\vio.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viosocket.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viossl.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viosslfactories.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\xml.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/client/mysqlclient_ia64.dsp b/VC++Files/client/mysqlclient_ia64.dsp
index ea67e1bf514..1aa6836ca58 100644
--- a/VC++Files/client/mysqlclient_ia64.dsp
+++ b/VC++Files/client/mysqlclient_ia64.dsp
@@ -147,6 +147,10 @@ SOURCE="..\strings\ctype-bin.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-cp932.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-czech.c"
# End Source File
# Begin Source File
@@ -159,6 +163,10 @@ SOURCE="..\strings\ctype-euc_kr.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-eucjpms.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-extra.c"
# End Source File
# Begin Source File
@@ -428,10 +436,6 @@ SOURCE=..\mysys\my_symlink2.c
# End Source File
# Begin Source File
-SOURCE=..\mysys\my_tempnam.c
-# End Source File
-# Begin Source File
-
SOURCE=..\mysys\my_thr_init.c
# End Source File
# Begin Source File
@@ -544,6 +548,10 @@ SOURCE=..\strings\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\thr_mutex.c
# End Source File
# Begin Source File
diff --git a/VC++Files/client/mysqldump.dsp b/VC++Files/client/mysqldump.dsp
index 45d1d8777aa..527d1eb0a74 100644
--- a/VC++Files/client/mysqldump.dsp
+++ b/VC++Files/client/mysqldump.dsp
@@ -52,7 +52,7 @@ BSC32=bscmake.exe
# 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 mysys.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysys.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqldump.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysys.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqldump.exe" /libpath:"..\lib_release\\"
!ELSEIF "$(CFG)" == "mysqldump - Win32 Debug"
@@ -77,7 +77,7 @@ BSC32=bscmake.exe
# 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 mysys.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysys.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqldump.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysys.lib zlib.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqldump.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
!ELSEIF "$(CFG)" == "mysqldump - Win32 classic"
@@ -104,7 +104,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=xilink6.exe
# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysys.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqldump.exe" /libpath:"..\lib_release\\"
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysys.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqldump.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysys.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqldump.exe" /libpath:"..\lib_release\\"
!ENDIF
diff --git a/VC++Files/client/mysqldump.vcproj b/VC++Files/client/mysqldump.vcproj
new file mode 100755
index 00000000000..b6a33596083
--- /dev/null
+++ b/VC++Files/client/mysqldump.vcproj
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqldump"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysqldump.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_debug/mysqldump.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/mysqldump.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/mysqldump.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqldump.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_release/mysqldump.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\release/mysqldump.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/mysqldump.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqldump.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_classic/mysqldump.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/mysqldump.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysqldump.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="mysqldump.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/client/mysqlimport.dsp b/VC++Files/client/mysqlimport.dsp
index 1a9b64a0383..649ba0c0aad 100644
--- a/VC++Files/client/mysqlimport.dsp
+++ b/VC++Files/client/mysqlimport.dsp
@@ -52,7 +52,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /machine:I386
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\"
# SUBTRACT LINK32 /incremental:yes
!ELSEIF "$(CFG)" == "mysqlimport - Win32 Debug"
@@ -78,7 +78,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlimport.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib setargv.obj ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlimport.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
!ELSEIF "$(CFG)" == "mysqlimport - Win32 classic"
@@ -104,9 +104,9 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=xilink6.exe
-# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\"
+# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\"
# SUBTRACT BASE LINK32 /incremental:yes
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlimport.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlimport.exe" /libpath:"..\lib_release\\"
# SUBTRACT LINK32 /incremental:yes
!ENDIF
diff --git a/VC++Files/client/mysqlimport.vcproj b/VC++Files/client/mysqlimport.vcproj
new file mode 100755
index 00000000000..ef440c2fe5a
--- /dev/null
+++ b/VC++Files/client/mysqlimport.vcproj
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqlimport"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysqlimport.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib setargv.obj"
+ OutputFile="../client_debug/mysqlimport.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/mysqlimport.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/mysqlimport.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqlimport.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_release/mysqlimport.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\release/mysqlimport.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/mysqlimport.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqlimport.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_classic/mysqlimport.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/mysqlimport.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysqlimport.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="mysqlimport.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/client/mysqlshow.dsp b/VC++Files/client/mysqlshow.dsp
index 855c2dcdf34..118964671c5 100644
--- a/VC++Files/client/mysqlshow.dsp
+++ b/VC++Files/client/mysqlshow.dsp
@@ -52,7 +52,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /machine:I386
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\"
!ELSEIF "$(CFG)" == "mysqlshow - Win32 Debug"
@@ -77,7 +77,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlshow.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlshow.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
!ELSEIF "$(CFG)" == "mysqlshow - Win32 classic"
@@ -103,8 +103,8 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=xilink6.exe
-# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\"
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlshow.exe" /libpath:"..\lib_release\\"
+# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlshow.exe" /libpath:"..\lib_release\\"
!ENDIF
diff --git a/VC++Files/client/mysqlshow.vcproj b/VC++Files/client/mysqlshow.vcproj
new file mode 100755
index 00000000000..a0707680728
--- /dev/null
+++ b/VC++Files/client/mysqlshow.vcproj
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqlshow"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqlshow.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_release/mysqlshow.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\release/mysqlshow.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/mysqlshow.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqlshow.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_classic/mysqlshow.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/mysqlshow.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysqlshow.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysqlshow.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_debug/mysqlshow.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/mysqlshow.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/mysqlshow.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="mysqlshow.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/client/mysqltest.dsp b/VC++Files/client/mysqltest.dsp
index 1c636c4d078..5b96fbd8a41 100644
--- a/VC++Files/client/mysqltest.dsp
+++ b/VC++Files/client/mysqltest.dsp
@@ -42,8 +42,8 @@ RSC=rc.exe
# PROP Output_Dir ".\debug"
# PROP Intermediate_Dir ".\debug"
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /I "../include" /I "../regex" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /FD /c /GX
-# ADD CPP /nologo /MTd /I "../include" /I "../regex" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /FD /c /GX
+# ADD BASE CPP /nologo /MTd /I "../extra" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /FD /c /GX
+# ADD CPP /nologo /MTd /I "../extra" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /FD /c /GX
# ADD BASE MTL /nologo /tlb".\debug\mysqltest.tlb" /win32
# ADD MTL /nologo /tlb".\debug\mysqltest.tlb" /win32
# ADD BASE RSC /l 1033 /d "_DEBUG"
@@ -52,8 +52,8 @@ 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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_debug\mysqltest.exe" /incremental:no /libpath:"..\lib_debug\" /debug /pdb:".\debug\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_debug\mysqltest.exe" /incremental:no /libpath:"..\lib_debug\" /debug /pdb:".\debug\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib ..\extra\yassl\Debug\yassl.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_debug\mysqltest.exe" /incremental:no /libpath:"..\lib_debug\" /debug /pdb:".\debug\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib ..\extra\yassl\Debug\yassl.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_debug\mysqltest.exe" /incremental:no /libpath:"..\lib_debug\" /debug /pdb:".\debug\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
!ELSEIF "$(CFG)" == "mysqltest - Win32 classic"
@@ -67,8 +67,8 @@ LINK32=link.exe
# PROP Output_Dir ".\classic"
# PROP Intermediate_Dir ".\classic"
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /FD /c /GX
-# ADD CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /FD /c /GX
+# ADD BASE CPP /nologo /MT /I "../extra" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /FD /c /GX
+# ADD CPP /nologo /MT /I "../extra" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /FD /c /GX
# ADD BASE MTL /nologo /tlb".\classic\mysqltest.tlb" /win32
# ADD MTL /nologo /tlb".\classic\mysqltest.tlb" /win32
# ADD BASE RSC /l 1033 /d "NDEBUG"
@@ -77,8 +77,8 @@ 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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_classic\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\classic\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib zlib.lib /nologo /out:"..\client_classic\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\classic\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib ..\extra\yassl\Release\yassl.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_classic\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\classic\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib ..\extra\yassl\Release\yassl.lib wsock32.lib mysys.lib regex.lib zlib.lib /nologo /out:"..\client_classic\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\classic\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
!ELSEIF "$(CFG)" == "mysqltest - Win32 Release"
@@ -92,8 +92,8 @@ LINK32=link.exe
# PROP Output_Dir ".\release"
# PROP Intermediate_Dir ".\release"
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /FD /c /GX
-# ADD CPP /nologo /MT /I "../include" /I "../regex" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /FD /c /GX
+# ADD BASE CPP /nologo /MT /I "../extra" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /FD /c /GX
+# ADD CPP /nologo /MT /I "../extra" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /FD /c /GX
# ADD BASE MTL /nologo /tlb".\release\mysqltest.tlb" /win32
# ADD MTL /nologo /tlb".\release\mysqltest.tlb" /win32
# ADD BASE RSC /l 1033 /d "NDEBUG"
@@ -102,8 +102,8 @@ 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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_release\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\release\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib zlib.lib /nologo /out:"..\client_release\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\release\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib ..\extra\yassl\Release\yassl.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_release\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\release\mysqltest.pdb" /pdbtype:sept /subsystem:console /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 odbc32.lib odbccp32.lib mysqlclient.lib ..\extra\yassl\Release\yassl.lib wsock32.lib mysys.lib regex.lib zlib.lib /nologo /out:"..\client_release\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\release\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
!ENDIF
diff --git a/VC++Files/client/mysqltest.vcproj b/VC++Files/client/mysqltest.vcproj
new file mode 100755
index 00000000000..5c075740fbd
--- /dev/null
+++ b/VC++Files/client/mysqltest.vcproj
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqltest"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../extra,../include,../regex,../extra/yassl/include,../"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqltest.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib wsock32.lib"
+ OutputFile="..\client_release\mysqltest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\release/mysqltest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\release/mysqltest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../extra,../include,../regex,../extra/yassl/include,../"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqltest.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib wsock32.lib"
+ OutputFile="..\client_classic\mysqltest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/mysqltest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\classic/mysqltest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../extra,../include,../regex,../extra/yassl/include,../"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysqltest.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib wsock32.lib"
+ OutputFile="..\client_debug\mysqltest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/mysqltest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\debug/mysqltest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\libmysql\manager.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mysqltest.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/comp_err/comp_err.vcproj b/VC++Files/comp_err/comp_err.vcproj
new file mode 100755
index 00000000000..b12ef8b0af1
--- /dev/null
+++ b/VC++Files/comp_err/comp_err.vcproj
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="comp_err"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_MBCSN;DBUG_OFF;_WINDOWS;__WIN__;_MT"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\release/comp_err.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib wsock32.lib"
+ OutputFile="../client_release/comp-err.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ IgnoreDefaultLibraryNames="LIBC.lib"
+ ProgramDatabaseFile=".\release/comp-err.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/comp_err.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\extra\comp_err.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/dbug/dbug.vcproj b/VC++Files/dbug/dbug.vcproj
new file mode 100755
index 00000000000..57257451aea
--- /dev/null
+++ b/VC++Files/dbug/dbug.vcproj
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="dbug"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="TLS_DEBUG|Win32"
+ OutputDirectory=".\dbug___Win32_TLS_DEBUG"
+ IntermediateDirectory=".\dbug___Win32_TLS_DEBUG"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="__WIN32__;_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\dbug___Win32_TLS_DEBUG/dbug.pch"
+ AssemblerListingLocation=".\dbug___Win32_TLS_DEBUG/"
+ ObjectFile=".\dbug___Win32_TLS_DEBUG/"
+ ProgramDataBaseFileName=".\dbug___Win32_TLS_DEBUG/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\dbug_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/dbug.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\dbug.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="__WIN32__;_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/dbug.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\dbug.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="dbug.c">
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="factorial.c">
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sanity.c">
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/heap/heap.vcproj b/VC++Files/heap/heap.vcproj
new file mode 100755
index 00000000000..b2afd752acf
--- /dev/null
+++ b/VC++Files/heap/heap.vcproj
@@ -0,0 +1,1061 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="heap"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/heap.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\heap.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="TLS_DEBUG|Win32"
+ OutputDirectory=".\heap___Win32_TLS_DEBUG"
+ IntermediateDirectory=".\heap___Win32_TLS_DEBUG"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\heap___Win32_TLS_DEBUG/heap.pch"
+ AssemblerListingLocation=".\heap___Win32_TLS_DEBUG/"
+ ObjectFile=".\heap___Win32_TLS_DEBUG/"
+ ProgramDataBaseFileName=".\heap___Win32_TLS_DEBUG/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\heap_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="TLS|Win32"
+ OutputDirectory=".\heap___Win32_TLS"
+ IntermediateDirectory=".\heap___Win32_TLS"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\heap___Win32_TLS/heap.pch"
+ AssemblerListingLocation=".\heap___Win32_TLS/"
+ ObjectFile=".\heap___Win32_TLS/"
+ ProgramDataBaseFileName=".\heap___Win32_TLS/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\heap_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/heap.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\heap.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="_check.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="_rectest.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="heapdef.h">
+ </File>
+ <File
+ RelativePath="hp_block.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_clear.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_close.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_create.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_delete.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_extra.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_hash.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_info.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_open.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_panic.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_rename.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_rfirst.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_rkey.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_rlast.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_rnext.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_rprev.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_rrnd.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_rsame.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_scan.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_static.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_update.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hp_write.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/innobase/innobase.vcproj b/VC++Files/innobase/innobase.vcproj
new file mode 100755
index 00000000000..9d972366440
--- /dev/null
+++ b/VC++Files/innobase/innobase.vcproj
@@ -0,0 +1,2958 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="innobase"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Max nt|Win32"
+ OutputDirectory=".\max_nt"
+ IntermediateDirectory=".\max_nt"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-nt-max"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../innobase/include,../include"
+ PreprocessorDefinitions="_LIB;_WIN32;WIN32;NDEBUG;MYSQL_SERVER"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\max_nt/innobase.pch"
+ AssemblerListingLocation=".\max_nt/"
+ ObjectFile=".\max_nt/"
+ ProgramDataBaseFileName=".\max_nt/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\innodb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../innobase/include,../include"
+ PreprocessorDefinitions="NDEBUG;_LIB;_WIN32;WIN32;MYSQL_SERVER"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/innobase.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\innodb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../innobase/include,../include"
+ PreprocessorDefinitions="_LIB;_WIN32;WIN32;MYSQL_SERVER;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/innobase.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\innodb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="nt|Win32"
+ OutputDirectory=".\nt"
+ IntermediateDirectory=".\nt"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-nt"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../innobase/include,../include"
+ PreprocessorDefinitions="_LIB;_WIN32;WIN32;NDEBUG;MYSQL_SERVER"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\nt/innobase.pch"
+ AssemblerListingLocation=".\nt/"
+ ObjectFile=".\nt/"
+ ProgramDataBaseFileName=".\nt/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\innodb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="btr\btr0btr.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btr\btr0cur.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btr\btr0pcur.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="btr\btr0sea.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="buf\buf0buf.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="buf\buf0flu.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="buf\buf0lru.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="buf\buf0rea.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="data\data0data.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="data\data0type.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dict\dict0boot.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dict\dict0crea.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dict\dict0dict.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dict\dict0load.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dict\dict0mem.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dyn\dyn0dyn.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="eval\eval0eval.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="eval\eval0proc.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fil\fil0fil.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fsp\fsp0fsp.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fut\fut0fut.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fut\fut0lst.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha\ha0ha.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha\hash0hash.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ibuf\ibuf0ibuf.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pars\lexyy.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lock\lock0lock.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log\log0log.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log\log0recv.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mach\mach0data.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mem\mem0mem.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mem\mem0pool.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mtr\mtr0log.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mtr\mtr0mtr.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os0file.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os0proc.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os0sync.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="os\os0thread.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="page\page0cur.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="page\page0page.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pars\pars0grm.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pars\pars0opt.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pars\pars0pars.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pars\pars0sym.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="que\que0que.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="read\read0read.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rem\rem0cmp.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rem\rem0rec.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0ins.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0mysql.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0purge.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0row.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0sel.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0uins.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0umod.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0undo.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0upd.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="row\row0vers.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="srv\srv0que.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="srv\srv0srv.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="srv\srv0start.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sync\sync0arr.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sync\sync0rw.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sync\sync0sync.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="thr\thr0loc.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trx\trx0purge.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trx\trx0rec.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trx\trx0roll.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trx\trx0rseg.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trx\trx0sys.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trx\trx0trx.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trx\trx0undo.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="usr\usr0sess.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ut\ut0byte.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ut\ut0dbg.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ut\ut0mem.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ut\ut0rnd.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ut\ut0ut.c">
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp
index 9bc7dfb8a1d..e17bee12d1b 100644
--- a/VC++Files/libmysql/libmysql.dsp
+++ b/VC++Files/libmysql/libmysql.dsp
@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "." /I "..\include" /I "../zlib" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_TLS" /D "NDEBUG" /D "MYSQL_CLIENT" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "." /I "..\include" /I "../zlib" /I "../extra/yassl/include" /D "DBUG_OFF" /D "_WINDOWS" /D "USE_TLS" /D "NDEBUG" /D "MYSQL_CLIENT" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
@@ -54,7 +54,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:windows /dll /machine:I386
-# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release"
+# ADD LINK32 mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release"
# SUBTRACT LINK32 /pdb:none
# Begin Special Build Tool
SOURCE="$(InputPath)"
@@ -76,7 +76,7 @@ PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release /y
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "." /I "..\include" /I "../zlib" /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "." /I "..\include" /I "../zlib" /I "../extra/yassl/include" /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
@@ -87,7 +87,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug"
+# ADD LINK32 zlib.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug"
# SUBTRACT LINK32 /pdb:none
# Begin Special Build Tool
SOURCE="$(InputPath)"
@@ -139,11 +139,11 @@ SOURCE="..\strings\ctype-bin.c"
# End Source File
# Begin Source File
-SOURCE="..\strings\ctype-czech.c"
+SOURCE="..\strings\ctype-cp932.c"
# End Source File
# Begin Source File
-SOURCE="..\strings\ctype-cp932.c"
+SOURCE="..\strings\ctype-czech.c"
# End Source File
# Begin Source File
@@ -151,6 +151,10 @@ SOURCE="..\strings\ctype-euc_kr.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-eucjpms.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-extra.c"
# End Source File
# Begin Source File
@@ -215,6 +219,10 @@ SOURCE=..\mysys\default.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\default_modify.c
+# End Source File
+# Begin Source File
+
SOURCE=.\dll.c
# End Source File
# Begin Source File
@@ -303,6 +311,10 @@ SOURCE=..\mysys\my_alloc.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\my_chsize.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\my_compress.c
# End Source File
# Begin Source File
@@ -387,6 +399,10 @@ SOURCE=..\mysys\my_rename.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\my_seek.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\my_static.c
# End Source File
# Begin Source File
@@ -403,10 +419,6 @@ SOURCE=..\mysys\my_symlink2.c
# End Source File
# Begin Source File
-SOURCE=..\mysys\my_tempnam.c
-# End Source File
-# Begin Source File
-
SOURCE=..\mysys\my_thr_init.c
# End Source File
# Begin Source File
@@ -523,6 +535,10 @@ SOURCE=..\strings\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\thr_mutex.c
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysql/libmysql.vcproj b/VC++Files/libmysql/libmysql.vcproj
new file mode 100755
index 00000000000..9ba877e0520
--- /dev/null
+++ b/VC++Files/libmysql/libmysql.vcproj
@@ -0,0 +1,2298 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="libmysql"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories=".,..\include,../zlib,../extra/yassl/include"
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/libmysql.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="..\lib_debug\libmysql.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ModuleDefinitionFile=".\Libmysql.def"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/libmysql.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName=".\debug/libmysql.map"
+ SubSystem="2"
+ ImportLibrary=".\debug/libmysql.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\debug/libmysql.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Move DLL export lib"
+ CommandLine="xcopy ..\lib_debug\libmysql.dll %windir%\system32\ /y
+xcopy debug\libmysql.lib ..\lib_debug\ /y
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories=".,..\include,../zlib,../extra/yassl/include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/libmysql.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="..\lib_release\libmysql.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ModuleDefinitionFile=".\Libmysql.def"
+ ProgramDatabaseFile=".\release/libmysql.pdb"
+ SubSystem="2"
+ ImportLibrary=".\release/libmysql.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\release/libmysql.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Move DLL export lib"
+ CommandLine="xcopy release\libmysql.lib ..\lib_release /y"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\mysys\array.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\bchange.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\bmove.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\bmove_upp.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\charset-def.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\charset.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="client.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-big5.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-bin.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-cp932.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-czech.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-euc_kr.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-eucjpms.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-extra.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-gb2312.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-gbk.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-latin1.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-mb.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-simple.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-sjis.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-tis620.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-uca.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-ucs2.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-ujis.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-utf8.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-win1250ch.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\dbug\dbug.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\default.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\default_modify.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dll.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="errmsg.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\errors.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="get_password.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\int2str.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\is_prefix.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="libmysql.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Libmysql.def">
+ </File>
+ <File
+ RelativePath="..\mysys\list.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\llstr.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\longlong2str.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_dirname.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_fn_ext.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_format.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_loadpath.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_pack.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_path.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_unixpath.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mf_wcomp.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\mulalloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_access.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_alloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_chsize.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_compress.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_create.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_delete.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_div.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_error.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_fopen.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_fstream.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_gethostbyname.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_getopt.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_getwd.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_init.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_lib.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_malloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_messnc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_net.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_once.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_open.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_pthread.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_read.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_realloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_rename.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_seek.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_static.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\my_strtoll10.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_symlink.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_symlink2.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_thr_init.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_time.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\my_vsnprintf.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_wincond.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_winthread.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_write.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\client\mysys_priv.h">
+ </File>
+ <File
+ RelativePath="..\sql\net_serv.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pack.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="password.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\safemalloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\sha1.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\client\sql_string.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\client\sql_string.h">
+ </File>
+ <File
+ RelativePath="..\strings\str2int.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strcend.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strcont.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strend.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strfill.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\string.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strinstr.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strmake.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strmov.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strnlen.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strnmov.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strtod.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strtoll.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strxmov.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strxnmov.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\thr_mutex.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\typelib.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\vio.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viosocket.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viossl.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viosslfactories.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\xml.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;USE_TLS;NDEBUG;MYSQL_CLIENT;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/libmysql/libmysql_ia64.dsp b/VC++Files/libmysql/libmysql_ia64.dsp
index 12932ed3924..dc8778cfe23 100644
--- a/VC++Files/libmysql/libmysql_ia64.dsp
+++ b/VC++Files/libmysql/libmysql_ia64.dsp
@@ -138,6 +138,10 @@ SOURCE="..\strings\ctype-bin.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-cp932.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-czech.c"
# End Source File
# Begin Source File
@@ -150,6 +154,10 @@ SOURCE="..\strings\ctype-euc_kr.c"
# End Source File
# Begin Source File
+SOURCE="..\strings\ctype-eucjpms.c"
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-extra.c"
# End Source File
# Begin Source File
@@ -398,10 +406,6 @@ SOURCE=..\mysys\my_symlink2.c
# End Source File
# Begin Source File
-SOURCE=..\mysys\my_tempnam.c
-# End Source File
-# Begin Source File
-
SOURCE=..\mysys\my_thr_init.c
# End Source File
# Begin Source File
@@ -518,6 +522,10 @@ SOURCE=..\strings\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\thr_mutex.c
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysqld/examples/test_libmysqld.dsp b/VC++Files/libmysqld/examples/test_libmysqld.dsp
index 6707b8cd8ee..f75925f8a86 100644
--- a/VC++Files/libmysqld/examples/test_libmysqld.dsp
+++ b/VC++Files/libmysqld/examples/test_libmysqld.dsp
@@ -38,7 +38,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "DBUG_OFF" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /I "../include" /I "../../extra/yassl/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "DBUG_OFF" /YX /FD /c
# SUBTRACT CPP /WX /Fr
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
@@ -47,7 +47,7 @@ BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 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 /nologo /subsystem:console /machine:I386 /nodefaultlib:"LIBCMTD" /out:"Release/mysql-server.exe"
+# 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 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 ..\..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"LIBCMTD" /out:"..\test_libmysqld.exe"
# Begin Target
# Name "test_libmysqld - Win32 Release"
@@ -71,9 +71,5 @@ SOURCE=..\..\client\readline.cpp
SOURCE=..\..\client\sql_string.cpp
# End Source File
# End Group
-# Begin Source File
-
-SOURCE=..\..\lib_release\libmysqld.lib
-# End Source File
# End Target
# End Project
diff --git a/VC++Files/libmysqld/examples/test_libmysqld.vcproj b/VC++Files/libmysqld/examples/test_libmysqld.vcproj
new file mode 100755
index 00000000000..bf26fbd6588
--- /dev/null
+++ b/VC++Files/libmysqld/examples/test_libmysqld.vcproj
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="test_libmysqld"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\include,../include,../../extra/yassl/include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;DBUG_OFF"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/test_libmysqld.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\..\extra\yassl\Release\yassl.lib"
+ OutputFile="..\test_libmysqld.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ IgnoreDefaultLibraryNames="LIBCMTD"
+ ProgramDatabaseFile=".\Release/test_libmysqld.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/test_libmysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\client\completion_hash.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\client\mysql.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\client\readline.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\client\sql_string.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp
index 0e3e6af03f0..0fb3a645a48 100644
--- a/VC++Files/libmysqld/libmysqld.dsp
+++ b/VC++Files/libmysqld/libmysqld.dsp
@@ -45,7 +45,7 @@ RSC=rc.exe
# 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 "LIBMYSQLD_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../libmysqld" /I "../sql" /I "../regex" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../libmysqld" /I "../sql" /I "../regex" /I "../extra/yassl/include" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FD /c
# SUBTRACT CPP /WX /Fr
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@@ -56,7 +56,7 @@ BSC32=bscmake.exe
# 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 /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 Wsock32.lib ..\lib_release\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /dll /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
+# 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /dll /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "libmysqld - Win32 Debug"
@@ -73,7 +73,7 @@ LINK32=xilink6.exe
# 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 "LIBMYSQLD_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MT /W3 /Z7 /Od /I "../include" /I "../libmysqld" /I "../sql" /I "../regex" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "SAFEMALLOC" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c
+# ADD CPP /nologo /MT /W3 /Z7 /Od /I "../include" /I "../libmysqld" /I "../sql" /I "../regex" /I "../extra/yassl/include" /I "../bdb/build_win32" /I "../zlib" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "SAFEMALLOC" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c
# SUBTRACT CPP /X /Fr
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
@@ -84,7 +84,7 @@ BSC32=bscmake.exe
# 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 /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 Wsock32.lib ..\lib_debug\dbug_tls.lib ..\lib_debug\mysys_tls.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap_tls.lib ..\lib_debug\innodb.lib /nologo /dll /incremental:no /debug /machine:I386 /nodefaultlib:"LIBCMTD" /out:"../lib_debug/libmysqld.dll" /implib:"../lib_debug/libmysqld.lib" /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 Wsock32.lib ..\lib_debug\dbug_tls.lib ..\lib_debug\mysys_tls.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap_tls.lib ..\lib_debug\innodb.lib ..\extra\yassl\Debug\yassl.lib /nologo /dll /incremental:no /debug /machine:I386 /nodefaultlib:"LIBCMTD" /out:"../lib_debug/libmysqld.dll" /implib:"../lib_debug/libmysqld.lib" /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "libmysqld - Win32 classic"
@@ -101,8 +101,8 @@ LINK32=xilink6.exe
# PROP Intermediate_Dir "classic"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /D "NDEBUG" /FR /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../libmysqld" /I "../sql" /I "../zlib" /D "WIN32" /D "_WINDOWS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "USE_TLS" /D "__WIN__" /D LICENSE=Commerical /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /c
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../sql" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /D "NDEBUG" /FR /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../libmysqld" /I "../sql" /I "../zlib" /D "WIN32" /D "_WINDOWS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "USE_TLS" /D "__WIN__" /D LICENSE=Commerical /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /c
# SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@@ -112,9 +112,9 @@ 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\zlib.lib /nologo /dll /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
+# 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /dll /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
# SUBTRACT BASE LINK32 /pdb:none
-# 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\zlib.lib /nologo /dll /machine:I386 /out:"../lib_classic/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
+# 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /dll /machine:I386 /out:"../lib_classic/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "libmysqld - Win32 pro"
@@ -131,8 +131,8 @@ LINK32=xilink6.exe
# PROP Intermediate_Dir "pro"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /D "NDEBUG" /FR /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../libmysqld" /I "../sql" /I "../zlib" /D "WIN32" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "EMBEDDED_LIBRARY" /D "USE_TLS" /D "__WIN__" /D "MYSQL_SERVER" /D LICENSE=Commercial /D "_MBCS" /D "HAVE_DLOPEN" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "NDEBUG" /D "_WINDOWS" /D "_CONSOLE" /FD /D MYSQL_SERVER_SUFFIX=-pro /c
+# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../sql" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /D "NDEBUG" /FR /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../libmysqld" /I "../sql" /I "../zlib" /D "WIN32" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "EMBEDDED_LIBRARY" /D "USE_TLS" /D "__WIN__" /D "MYSQL_SERVER" /D LICENSE=Commercial /D "_MBCS" /D "HAVE_DLOPEN" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "NDEBUG" /D "_WINDOWS" /D "_CONSOLE" /FD /D MYSQL_SERVER_SUFFIX=-pro /c
# SUBTRACT CPP /X /Fr
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@@ -142,9 +142,9 @@ 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib /nologo /dll /machine:I386 /out:"../lib_classic/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
+# 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /dll /machine:I386 /out:"../lib_classic/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
# SUBTRACT BASE LINK32 /pdb:none
-# 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib /nologo /dll /machine:I386 /out:"../lib_pro/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
+# 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\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /dll /machine:I386 /out:"../lib_pro/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
# SUBTRACT LINK32 /pdb:none
!ENDIF
@@ -172,6 +172,10 @@ SOURCE="..\sql-common\client.c"
# End Source File
# Begin Source File
+SOURCE=..\mysys\charset.c
+# End Source File
+# Begin Source File
+
SOURCE="..\strings\ctype-latin1.c"
# End Source File
# Begin Source File
@@ -180,6 +184,10 @@ SOURCE=..\mysys\default.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\default_modify.c
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\derror.cpp
# End Source File
# Begin Source File
@@ -228,10 +236,6 @@ SOURCE=..\sql\ha_innodb.cpp
# End Source File
# Begin Source File
-SOURCE=..\sql\ha_isammrg.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\sql\ha_myisam.cpp
# End Source File
# Begin Source File
@@ -348,9 +352,17 @@ SOURCE=..\mysys\my_alloc.c
# End Source File
# Begin Source File
+SOURCE=..\sql\my_decimal.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\my_getopt.c
# End Source File
# Begin Source File
+
+SOURCE=..\sql-common\my_time.c
+# End Source File
+# Begin Source File
SOURCE=..\sql\net_serv.cpp
# End Source File
@@ -364,11 +376,11 @@ SOURCE=..\sql\opt_sum.cpp
# End Source File
# Begin Source File
-SOURCE="..\sql-common\pack.c"
+SOURCE=..\sql-common\pack.c
# End Source File
# Begin Source File
-SOURCE=..\sql-common\my_time.c
+SOURCE=..\sql\parse_file.cpp
# End Source File
# Begin Source File
@@ -384,6 +396,10 @@ SOURCE=..\sql\protocol.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\protocol_cursor.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\records.cpp
# End Source File
# Begin Source File
@@ -396,6 +412,26 @@ SOURCE=..\sql\set_var.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\sp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\sql\sp_cache.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\sql\sp_head.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\sql\sp_pcontext.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\sql\sp_rcontext.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\spatial.cpp
# End Source File
# Begin Source File
@@ -516,6 +552,10 @@ SOURCE=..\sql\sql_test.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\sql_trigger.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\sql_udf.cpp
# End Source File
# Begin Source File
@@ -525,6 +565,10 @@ SOURCE=..\sql\sql_union.cpp
# Begin Source File
SOURCE=..\sql\sql_update.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\sql\sql_view.cpp
# End Source File
# Begin Source File
@@ -556,6 +600,10 @@ SOURCE=..\strings\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\table.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysqld/libmysqld.vcproj b/VC++Files/libmysqld/libmysqld.vcproj
new file mode 100755
index 00000000000..187a63ece38
--- /dev/null
+++ b/VC++Files/libmysqld/libmysqld.vcproj
@@ -0,0 +1,4500 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="libmysqld"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../include,../libmysqld,../sql,../regex,../extra/yassl/include,../bdb/build_win32,../zlib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\debug/libmysqld.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug_tls.lib ..\lib_debug\mysys_tls.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap_tls.lib ..\lib_debug\innodb.lib ..\extra\yassl\Debug\yassl.lib"
+ OutputFile="../lib_debug/libmysqld.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ IgnoreDefaultLibraryNames="LIBCMTD"
+ ModuleDefinitionFile=".\libmysqld.def"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/libmysqld.pdb"
+ ImportLibrary="../lib_debug/libmysqld.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\debug/libmysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="pro|Win32"
+ OutputDirectory=".\pro"
+ IntermediateDirectory=".\pro"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-pro"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../regex,../extra/yassl/include,../libmysqld,../sql,../zlib"
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\pro/libmysqld.pch"
+ AssemblerListingLocation=".\pro/"
+ ObjectFile=".\pro/"
+ ProgramDataBaseFileName=".\pro/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib"
+ OutputFile="../lib_pro/libmysqld.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ModuleDefinitionFile=".\libmysqld.def"
+ ProgramDatabaseFile=".\pro/libmysqld.pdb"
+ ImportLibrary="../lib_release/libmysqld.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\pro/libmysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../libmysqld,../sql,../regex,../extra/yassl/include,../bdb/build_win32,../zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/libmysqld.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib"
+ OutputFile="../lib_release/libmysqld.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ModuleDefinitionFile=".\libmysqld.def"
+ ProgramDatabaseFile=".\release/libmysqld.pdb"
+ ImportLibrary="../lib_release/libmysqld.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\release/libmysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../regex,../extra/yassl/include,../libmysqld,../sql,../zlib"
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/libmysqld.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib"
+ OutputFile="../lib_classic/libmysqld.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ModuleDefinitionFile=".\libmysqld.def"
+ ProgramDatabaseFile=".\classic/libmysqld.pdb"
+ ImportLibrary="../lib_release/libmysqld.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\classic/libmysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\mysys\charset.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql-common\client.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\ctype-latin1.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\default.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\default_modify.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\derror.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\discover.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="emb_qcache.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\errmsg.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\field.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\field_conv.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\filesort.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\client\get_password.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\gstream.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_berkeley.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_heap.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_innodb.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_myisam.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_myisammrg.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\handler.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\hash_filo.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\hostname.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\init.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\int2str.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_buff.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_cmpfunc.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_create.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_func.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_geofunc.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_row.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_strfunc.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_subselect.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_sum.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_timefunc.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_uniq.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\key.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lib_sql.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\libmysql.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="libmysqld.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="libmysqld.def">
+ </File>
+ <File
+ RelativePath="..\sql\lock.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\log.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\log_event.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\mf_iocache.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_alloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\my_decimal.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\mysys\my_getopt.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql-common\my_time.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\net_serv.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\opt_range.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\opt_sum.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql-common\pack.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\parse_file.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\password.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\procedure.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\protocol.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\protocol_cursor.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\records.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\repl_failsafe.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\set_var.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sp.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sp_cache.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sp_head.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sp_pcontext.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sp_rcontext.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\spatial.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_acl.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_analyse.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_base.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_cache.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_class.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_crypt.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_db.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_delete.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_derived.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_do.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_error.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_handler.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_help.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_insert.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_lex.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_list.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_load.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_manager.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_map.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_parse.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_prepare.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_rename.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_repl.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_select.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_show.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_state.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_string.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_table.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_test.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_trigger.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_udf.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_union.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_update.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_view.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_yacc.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\str2int.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strcend.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strcont.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\strfunc.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strinstr.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\strings\strxnmov.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\table.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\thr_malloc.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\time.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\tztime.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\uniques.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\unireg.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\vio.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viosocket.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viossl.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\vio\viosslfactories.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/libmysqld/libmysqld_ia64.dsp b/VC++Files/libmysqld/libmysqld_ia64.dsp
index fe99ea480c7..b5223e38f2d 100644
--- a/VC++Files/libmysqld/libmysqld_ia64.dsp
+++ b/VC++Files/libmysqld/libmysqld_ia64.dsp
@@ -538,6 +538,10 @@ SOURCE=..\strings\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=..\strings\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\table.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/libmysqltest/myTest.vcproj b/VC++Files/libmysqltest/myTest.vcproj
new file mode 100755
index 00000000000..06ce20bf021
--- /dev/null
+++ b/VC++Files/libmysqltest/myTest.vcproj
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="myTest"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="DBUG_UFF;_CONSOLE;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/myTest.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libmysql.lib odbc32.lib odbccp32.lib"
+ OutputFile=".\release/myTest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\lib_release"
+ ProgramDatabaseFile=".\release/myTest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/myTest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="_DEBUG;_CONSOLE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/myTest.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libmysql.lib odbc32.lib odbccp32.lib"
+ OutputFile=".\debug/myTest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\lib_debug"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/myTest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/myTest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="Mytest.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/libmysqltest/mytest.c b/VC++Files/libmysqltest/mytest.c
index 9af8c486e40..a1dc13db39f 100644
--- a/VC++Files/libmysqltest/mytest.c
+++ b/VC++Files/libmysqltest/mytest.c
@@ -91,6 +91,7 @@ main( int argc, char * argv[] )
mysql_real_connect( myData, NULL, NULL, NULL, NULL, MYSQL_PORT,
NULL, 0 ) )
{
+ myData->reconnect= 1;
if ( mysql_select_db( myData, szDB ) < 0 ) {
printf( "Can't select the %s database !\n", szDB ) ;
mysql_close( myData ) ;
diff --git a/VC++Files/my_print_defaults/my_print_defaults.vcproj b/VC++Files/my_print_defaults/my_print_defaults.vcproj
new file mode 100755
index 00000000000..e49039b6a1e
--- /dev/null
+++ b/VC++Files/my_print_defaults/my_print_defaults.vcproj
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="my_print_defaults"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="WIN32;_CONSOLE;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\release/my_print_defaults.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib wsock32.lib"
+ OutputFile="../client_release/my_print_defaults.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\release/my_print_defaults.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/my_print_defaults.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="WIN32;_CONSOLE;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\classic/my_print_defaults.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib wsock32.lib"
+ OutputFile="../client_classic/my_print_defaults.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/my_print_defaults.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/my_print_defaults.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/my_print_defaults.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib wsock32.lib"
+ OutputFile="../client_debug/my_print_defaults.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ IgnoreDefaultLibraryNames="LIBCMTD.lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/my_print_defaults.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/my_print_defaults.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\extra\my_print_defaults.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/myisam/myisam.vcproj b/VC++Files/myisam/myisam.vcproj
new file mode 100755
index 00000000000..b63b7ffaccc
--- /dev/null
+++ b/VC++Files/myisam/myisam.vcproj
@@ -0,0 +1,2094 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="myisam"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/myisam.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_Debug\myisam.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/myisam.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\myisam.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="TLS|Win32"
+ OutputDirectory=".\myisam___Win32_TLS"
+ IntermediateDirectory=".\myisam___Win32_TLS"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\myisam___Win32_TLS/myisam.pch"
+ AssemblerListingLocation=".\myisam___Win32_TLS/"
+ ObjectFile=".\myisam___Win32_TLS/"
+ ProgramDataBaseFileName=".\myisam___Win32_TLS/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\myisam_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="TLS_DEBUG|Win32"
+ OutputDirectory=".\myisam___Win32_TLS_DEBUG"
+ IntermediateDirectory=".\myisam___Win32_TLS_DEBUG"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\myisam___Win32_TLS_DEBUG/myisam.pch"
+ AssemblerListingLocation=".\myisam___Win32_TLS_DEBUG/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_Debug\myisam_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="ft_boolean_search.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ft_nlq_search.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ft_parser.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ft_static.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ft_stem.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ft_stopwords.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ft_update.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_cache.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_changed.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_check.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_checksum.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_close.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_create.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_dbug.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_delete.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_delete_all.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_delete_table.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_dynrec.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_extra.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_info.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_key.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_keycache.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_locking.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_log.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_open.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_packrec.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_page.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_panic.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_preload.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_range.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rename.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rfirst.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rkey.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rlast.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rnext.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rnext_same.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rprev.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rrnd.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rsame.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_rsamepos.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_scan.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_search.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_static.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_statrec.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_unique.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_update.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mi_write.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rt_index.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rt_key.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rt_mbr.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rt_split.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sort.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sp_key.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="ft_eval.h">
+ </File>
+ <File
+ RelativePath="myisamdef.h">
+ </File>
+ <File
+ RelativePath="rt_index.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/myisam_ftdump/myisam_ftdump.vcproj b/VC++Files/myisam_ftdump/myisam_ftdump.vcproj
new file mode 100755
index 00000000000..4d1013775fa
--- /dev/null
+++ b/VC++Files/myisam_ftdump/myisam_ftdump.vcproj
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="myisam_ftdump"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/myisam_ftdump.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib setargv.obj ..\lib_debug\zlib.lib"
+ OutputFile="../client_debug/myisam_ftdump.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/myisam_ftdump.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/myisam_ftdump.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/myisam_ftdump.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib setargv.obj ..\lib_release\zlib.lib"
+ OutputFile="../client_release/myisam_ftdump.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\release/myisam_ftdump.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/myisam_ftdump.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\myisam\myisam_ftdump.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/myisamchk/myisamchk.vcproj b/VC++Files/myisamchk/myisamchk.vcproj
new file mode 100755
index 00000000000..ce2435bc34a
--- /dev/null
+++ b/VC++Files/myisamchk/myisamchk.vcproj
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="myisamchk"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="NDEBUG;DBUG_OFF;_CONSOLE;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/myisamchk.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib setargv.obj"
+ OutputFile="../client_release/myisamchk.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\release/myisamchk.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/myisamchk.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/myisamchk.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib setargv.obj ..\lib_release\myisam.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\zlib.lib"
+ OutputFile="../client_classic/myisamchk.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\lib_release\"
+ ProgramDatabaseFile=".\classic/myisamchk.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/myisamchk.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/myisamchk.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib setargv.obj"
+ OutputFile="../client_debug/myisamchk.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/myisamchk.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/myisamchk.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\myisam\myisamchk.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/myisamlog/myisamlog.vcproj b/VC++Files/myisamlog/myisamlog.vcproj
new file mode 100755
index 00000000000..6189a54d33b
--- /dev/null
+++ b/VC++Files/myisamlog/myisamlog.vcproj
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="myisamlog"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/myisamlog.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib setargv.obj"
+ OutputFile="../client_debug/myisamlog.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="debug/myisamchk.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/myisamlog.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/myisamlog.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib setargv.obj"
+ OutputFile="../client_classic/myisamlog.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile="release/myisamchk.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/myisamlog.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="NDEBUG;DBUG_OFF;_CONSOLE;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/myisamlog.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib setargv.obj"
+ OutputFile="../client_release/myisamlog.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile="release/myisamchk.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/myisamlog.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\myisam\myisamlog.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/myisammrg/myisammrg.vcproj b/VC++Files/myisammrg/myisammrg.vcproj
new file mode 100755
index 00000000000..3075f8ef9f6
--- /dev/null
+++ b/VC++Files/myisammrg/myisammrg.vcproj
@@ -0,0 +1,968 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="myisammrg"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/myisammrg.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\myisammrg.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="TLS_DEBUG|Win32"
+ OutputDirectory=".\myisammrg___Win32_TLS_DEBUG"
+ IntermediateDirectory=".\myisammrg___Win32_TLS_DEBUG"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\myisammrg___Win32_TLS_DEBUG/myisammrg.pch"
+ AssemblerListingLocation=".\myisammrg___Win32_TLS_DEBUG/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_Debug\myisammrg_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="TLS|Win32"
+ OutputDirectory=".\myisammrg___Win32_TLS"
+ IntermediateDirectory=".\myisammrg___Win32_TLS"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\myisammrg___Win32_TLS/myisammrg.pch"
+ AssemblerListingLocation=".\myisammrg___Win32_TLS/"
+ ObjectFile=".\myisammrg___Win32_TLS/"
+ ProgramDataBaseFileName=".\myisammrg___Win32_TLS/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\myisammrg_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/myisammrg.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_Debug\myisammrg.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="myrg_close.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_create.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_delete.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_extra.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_info.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_locking.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_open.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_panic.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_queue.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_range.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_rfirst.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_rkey.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_rlast.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_rnext.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_rnext_same.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_rprev.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_rrnd.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_rsame.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_static.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_update.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="myrg_write.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="mymrgdef.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/myisampack/myisampack.vcproj b/VC++Files/myisampack/myisampack.vcproj
new file mode 100755
index 00000000000..27a8653cc5a
--- /dev/null
+++ b/VC++Files/myisampack/myisampack.vcproj
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="myisampack"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/myisampack.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib setargv.obj"
+ OutputFile="../client_debug/myisampack.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/myisampack.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/myisampack.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="NDEBUG;DBUG_OFF;_CONSOLE;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/myisampack.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib setargv.obj"
+ OutputFile="../client_release/myisampack.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\release/myisampack.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/myisampack.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../myisam"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/myisampack.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib setargv.obj"
+ OutputFile="../client_classic/myisampack.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/myisampack.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/myisampack.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\myisam\myisampack.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="myisampack.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/mysql-test/mysql_test_run_new.vcproj b/VC++Files/mysql-test/mysql_test_run_new.vcproj
new file mode 100755
index 00000000000..12d502e5768
--- /dev/null
+++ b/VC++Files/mysql-test/mysql_test_run_new.vcproj
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysql_test_run_new"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;__WIN__;_WIN32"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/mysql_test_run_new.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Ws2_32.lib zlib.lib"
+ OutputFile="..\mysql-test\mysql_test_run_new.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\lib_debug\"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/mysql_test_run_new.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName=".\Debug/mysql_test_run_new.map"
+ SubSystem="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/mysql_test_run_new.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;__WIN__;_WIN32"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\Release/mysql_test_run_new.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Ws2_32.lib zlib.lib"
+ OutputFile="..\mysql-test\mysql_test_run_new.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\lib_release\"
+ ProgramDatabaseFile=".\Release/mysql_test_run_new.pdb"
+ SubSystem="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/mysql_test_run_new.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="my_create_tables.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_manage.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_manage.h">
+ </File>
+ <File
+ RelativePath="mysql_test_run_new.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw
index d36cbc7a031..b1d09552705 100644
--- a/VC++Files/mysql.dsw
+++ b/VC++Files/mysql.dsw
@@ -3,21 +3,6 @@ Microsoft Developer Studio Workspace File, Format Version 6.00
###############################################################################
-Project: "MySqlManager"=".\mysqlmanager\MySqlManager.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name mysqlclient
- End Project Dependency
-}}}
-
-###############################################################################
-
Project: "bdb"=".\bdb\bdb.dsp" - Package Owner=<4>
Package=<5>
@@ -84,19 +69,7 @@ Package=<4>
###############################################################################
-Project: "isam"=".\isam\isam.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "isamchk"=".\isamchk\isamchk.dsp" - Package Owner=<4>
+Project: "libmysql"=".\libmysql\libmysql.dsp" - Package Owner=<4>
Package=<5>
{{{
@@ -105,31 +78,13 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
- Project_Dep_Name isam
+ Project_Dep_Name zlib
End Project Dependency
Begin Project Dependency
Project_Dep_Name mysys
End Project Dependency
Begin Project Dependency
- Project_Dep_Name strings
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name dbug
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "libmysql"=".\libmysql\libmysql.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name zlib
+ Project_Dep_Name yassl
End Project Dependency
}}}
@@ -173,18 +128,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name zlib
End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "merge"=".\merge\merge.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
}}}
###############################################################################
@@ -365,6 +311,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name mysqlclient
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
}}}
###############################################################################
@@ -383,6 +332,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name zlib
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
}}}
###############################################################################
@@ -428,6 +380,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name zlib
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
}}}
###############################################################################
@@ -444,12 +399,6 @@ Package=<4>
Project_Dep_Name heap
End Project Dependency
Begin Project Dependency
- Project_Dep_Name isam
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name merge
- End Project Dependency
- Begin Project Dependency
Project_Dep_Name mysys
End Project Dependency
Begin Project Dependency
@@ -474,9 +423,6 @@ Package=<4>
Project_Dep_Name mysqlimport
End Project Dependency
Begin Project Dependency
- Project_Dep_Name MySqlManager
- End Project Dependency
- Begin Project Dependency
Project_Dep_Name mysqlshow
End Project Dependency
Begin Project Dependency
@@ -506,6 +452,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name innobase
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
}}}
###############################################################################
@@ -533,6 +482,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name mysqlclient
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
}}}
###############################################################################
@@ -548,6 +500,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name mysqlclient
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
}}}
###############################################################################
@@ -570,9 +525,6 @@ Package=<4>
Project_Dep_Name innobase
End Project Dependency
Begin Project Dependency
- Project_Dep_Name merge
- End Project Dependency
- Begin Project Dependency
Project_Dep_Name myisam
End Project Dependency
Begin Project Dependency
@@ -608,11 +560,14 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name mysqlclient
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name mysys
+ End Project Dependency
}}}
###############################################################################
-Project: "mysqlshutdown"=".\mysqlshutdown\mysqlshutdown.dsp" - Package Owner=<4>
+Project: "yassl"=".\extra\yassl\yassl.dsp" - Package Owner=<4>
Package=<5>
{{{
@@ -620,11 +575,14 @@ Package=<5>
Package=<4>
{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
}}}
###############################################################################
-Project: "mysqlwatch"=".\mysqlwatch\mysqlwatch.dsp" - Package Owner=<4>
+Project: "taocrypt"=".\extra\yassl\taocrypt\taocrypt.dsp" - Package Owner=<4>
Package=<5>
{{{
@@ -648,30 +606,6 @@ Package=<4>
###############################################################################
-Project: "pack_isam"=".\pack_isam\pack_isam.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name dbug
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name isam
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name mysys
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name strings
- End Project Dependency
-}}}
-
-###############################################################################
-
Project: "perror"=".\perror\perror.dsp" - Package Owner=<4>
Package=<5>
@@ -767,6 +701,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name zlib
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
}}}
###############################################################################
@@ -833,6 +770,9 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name regex
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
}}}
###############################################################################
diff --git a/VC++Files/mysql.sln b/VC++Files/mysql.sln
new file mode 100755
index 00000000000..5b062a31aab
--- /dev/null
+++ b/VC++Files/mysql.sln
@@ -0,0 +1,1249 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bdb", "bdb\bdb.vcproj", "{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "comp_err", "comp_err\comp_err.vcproj", "{1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dbug", "dbug\dbug.vcproj", "{FC369DF4-AEB7-4531-BF34-A638C4363BFE}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "heap", "heap\heap.vcproj", "{C70A6DC7-7D45-4C16-8654-7E57713A4C04}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "innobase", "innobase\innobase.vcproj", "{13D37150-54D0-46C5-9519-03923243C7C7}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmysql", "libmysql\libmysql.vcproj", "{1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmysqld", "libmysqld\libmysqld.vcproj", "{93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113} = {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}
+ {13D37150-54D0-46C5-9519-03923243C7C7} = {13D37150-54D0-46C5-9519-03923243C7C7}
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3} = {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0} = {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}
+ {262280A8-37D5-4037-BDFB-242468DFB3D2} = {262280A8-37D5-4037-BDFB-242468DFB3D2}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04} = {C70A6DC7-7D45-4C16-8654-7E57713A4C04}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "myTest", "libmysqltest\myTest.vcproj", "{2794E434-7CCE-44DB-B2FB-789ABE53D6B9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F} = {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "my_print_defaults", "my_print_defaults\my_print_defaults.vcproj", "{B0EC3594-CD67-4364-826E-BA75EF2050F8}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "myisam", "myisam\myisam.vcproj", "{262280A8-37D5-4037-BDFB-242468DFB3D2}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "myisam_ftdump", "myisam_ftdump\myisam_ftdump.vcproj", "{4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {262280A8-37D5-4037-BDFB-242468DFB3D2} = {262280A8-37D5-4037-BDFB-242468DFB3D2}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "myisamchk", "myisamchk\myisamchk.vcproj", "{87CD9881-D234-4306-BBC6-0668C6168C0F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {262280A8-37D5-4037-BDFB-242468DFB3D2} = {262280A8-37D5-4037-BDFB-242468DFB3D2}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "myisamlog", "myisamlog\myisamlog.vcproj", "{194F5EE6-9440-4298-A6FE-A9B4B480B44C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {262280A8-37D5-4037-BDFB-242468DFB3D2} = {262280A8-37D5-4037-BDFB-242468DFB3D2}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "myisammrg", "myisammrg\myisammrg.vcproj", "{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "myisampack", "myisampack\myisampack.vcproj", "{EF833A1E-E358-4B6C-9C27-9489E85041CC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {262280A8-37D5-4037-BDFB-242468DFB3D2} = {262280A8-37D5-4037-BDFB-242468DFB3D2}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql", "client\mysql.vcproj", "{F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqladmin", "client\mysqladmin.vcproj", "{D2B00DE0-F6E9-40AF-B90D-A257D014F098}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlbinlog", "mysqlbinlog\mysqlbinlog.vcproj", "{DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlcheck", "mysqlcheck\mysqlcheck.vcproj", "{67154F28-D076-419E-B149-819EF548E670}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlclient", "client\mysqlclient.vcproj", "{26383276-4843-494B-8BE0-8936ED3EBAAB}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqld", "sql\mysqld.vcproj", "{62E85884-3ACF-4F4C-873B-60B878147890}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113} = {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}
+ {13D37150-54D0-46C5-9519-03923243C7C7} = {13D37150-54D0-46C5-9519-03923243C7C7}
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3} = {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98} = {DB28DE80-837F-4497-9AA9-CC0A20584C98}
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0} = {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}
+ {262280A8-37D5-4037-BDFB-242468DFB3D2} = {262280A8-37D5-4037-BDFB-242468DFB3D2}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B} = {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04} = {C70A6DC7-7D45-4C16-8654-7E57713A4C04}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqldemb", "mysqldemb\mysqldemb.vcproj", "{37D9BA79-302E-4582-A545-CB5FF7982EA3}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqldump", "client\mysqldump.vcproj", "{89F24ECE-9953-40EF-BDF4-B41F5631E92B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlimport", "client\mysqlimport.vcproj", "{AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlserver", "mysqlserver\mysqlserver.vcproj", "{94B86159-C581-42CD-825D-C69CBC237E5C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113} = {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}
+ {13D37150-54D0-46C5-9519-03923243C7C7} = {13D37150-54D0-46C5-9519-03923243C7C7}
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3} = {37D9BA79-302E-4582-A545-CB5FF7982EA3}
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0} = {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}
+ {262280A8-37D5-4037-BDFB-242468DFB3D2} = {262280A8-37D5-4037-BDFB-242468DFB3D2}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04} = {C70A6DC7-7D45-4C16-8654-7E57713A4C04}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlshow", "client\mysqlshow.vcproj", "{3737BFE2-EF25-464F-994D-BD28A9F84528}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yassl", "extra\yassl\yassl.vcproj", "{BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98} = {DB28DE80-837F-4497-9AA9-CC0A20584C98}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "taocrypt", "extra\yassl\taocrypt\taocrypt.vcproj", "{DB28DE80-837F-4497-9AA9-CC0A20584C98}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysys", "mysys\mysys.vcproj", "{44D9C7DC-6636-4B82-BD01-6876C64017DF}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "perror", "perror\perror.vcproj", "{AC47623D-933C-4A80-83BB-B6AF7CB28B4B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "regex", "regex\regex.vcproj", "{207E9014-C4D1-4F6D-B76F-BC7DD7E31113}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "replace", "replace\replace.vcproj", "{16699B52-ECC6-4A96-A99F-A043059BA2E7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strings", "strings\strings.vcproj", "{EEC1300B-85A5-497C-B3E1-F708021DF859}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test1", "test1\test1.vcproj", "{8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F} = {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_libmysqld", "libmysqld\examples\test_libmysqld.vcproj", "{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9} = {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "thr_test", "thr_test\thr_test.vcproj", "{7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vio", "vio\vio.vcproj", "{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib.vcproj", "{8762A9B8-72A9-462E-A9A2-F3265081F8AF}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqltest", "client\mysqltest.vcproj", "{8961F149-C68A-4154-A499-A2AB39E607E8}"
+ ProjectSection(ProjectDependencies) = postProject
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113} = {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_client_test", "tests\mysql_client_test.vcproj", "{DA224DAB-5006-42BE-BB77-16E8BE5326D5}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_test_run_new", "mysql-test\mysql_test_run_new.vcproj", "{6189F838-21C6-42A1-B2D0-9146316573F7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {8961F149-C68A-4154-A499-A2AB39E607E8} = {8961F149-C68A-4154-A499-A2AB39E607E8}
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5} = {DA224DAB-5006-42BE-BB77-16E8BE5326D5}
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098} = {D2B00DE0-F6E9-40AF-B90D-A257D014F098}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlmanager", "server-tools\instance-manager\mysqlmanager.vcproj", "{6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EEC1300B-85A5-497C-B3E1-F708021DF859} = {EEC1300B-85A5-497C-B3E1-F708021DF859}
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98} = {DB28DE80-837F-4497-9AA9-CC0A20584C98}
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B} = {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE} = {FC369DF4-AEB7-4531-BF34-A638C4363BFE}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ classic = classic
+ classic nt = classic nt
+ Debug = Debug
+ Embedded_Classic = Embedded_Classic
+ Embedded_Debug = Embedded_Debug
+ Embedded_Pro = Embedded_Pro
+ Embedded_Release = Embedded_Release
+ Max = Max
+ Max nt = Max nt
+ nt = nt
+ pro = pro
+ pro nt = pro nt
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.classic.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.classic nt.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Debug.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Debug.Build.0 = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Classic.Build.0 = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Debug.Build.0 = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Release.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Max.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Max.Build.0 = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Max nt.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Max nt.Build.0 = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.nt.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.pro.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.pro nt.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Release.ActiveCfg = Debug|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.classic.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.classic nt.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.classic nt.Build.0 = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Debug.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Embedded_Classic.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Embedded_Debug.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Embedded_Pro.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Embedded_Release.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Max.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Max.Build.0 = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Max nt.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Max nt.Build.0 = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.nt.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.nt.Build.0 = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.pro.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.pro.Build.0 = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.pro nt.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.pro nt.Build.0 = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Release.ActiveCfg = Release|Win32
+ {1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.Release.Build.0 = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.classic.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.classic.Build.0 = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.classic nt.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.classic nt.Build.0 = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Debug.ActiveCfg = Debug|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Debug.Build.0 = Debug|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Debug.ActiveCfg = TLS_DEBUG|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Debug.Build.0 = TLS_DEBUG|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Release.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Max.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Max.Build.0 = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Max nt.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Max nt.Build.0 = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.nt.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.nt.Build.0 = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.pro.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.pro.Build.0 = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.pro nt.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.pro nt.Build.0 = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Release.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Release.Build.0 = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.classic.ActiveCfg = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.classic.Build.0 = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.classic nt.ActiveCfg = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.classic nt.Build.0 = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Debug.ActiveCfg = Debug|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Debug.Build.0 = Debug|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Embedded_Classic.ActiveCfg = TLS|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Embedded_Classic.Build.0 = TLS|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Embedded_Debug.ActiveCfg = TLS_DEBUG|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Embedded_Debug.Build.0 = TLS_DEBUG|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Embedded_Pro.ActiveCfg = TLS|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Embedded_Pro.Build.0 = TLS|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Embedded_Release.ActiveCfg = TLS|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Embedded_Release.Build.0 = TLS|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Max.ActiveCfg = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Max.Build.0 = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Max nt.ActiveCfg = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Max nt.Build.0 = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.nt.ActiveCfg = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.nt.Build.0 = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.pro.ActiveCfg = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.pro.Build.0 = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.pro nt.ActiveCfg = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.pro nt.Build.0 = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Release.ActiveCfg = Release|Win32
+ {C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Release.Build.0 = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.classic.ActiveCfg = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.classic nt.ActiveCfg = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Debug.ActiveCfg = Debug|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Debug.Build.0 = Debug|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Classic.ActiveCfg = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Debug.Build.0 = Debug|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Pro.ActiveCfg = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Pro.Build.0 = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Release.ActiveCfg = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Release.Build.0 = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Max.ActiveCfg = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Max.Build.0 = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Max nt.ActiveCfg = Max nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Max nt.Build.0 = Max nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.nt.ActiveCfg = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.nt.Build.0 = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.pro.ActiveCfg = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.pro.Build.0 = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.pro nt.ActiveCfg = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.pro nt.Build.0 = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Release.ActiveCfg = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Release.Build.0 = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.classic.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.classic.Build.0 = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.classic nt.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.classic nt.Build.0 = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Debug.ActiveCfg = Debug|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Debug.Build.0 = Debug|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Embedded_Classic.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Embedded_Pro.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Embedded_Release.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Max.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Max.Build.0 = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Max nt.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Max nt.Build.0 = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.nt.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.nt.Build.0 = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.pro.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.pro.Build.0 = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.pro nt.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.pro nt.Build.0 = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Release.ActiveCfg = Release|Win32
+ {1FC6EB72-1D0F-4E40-8851-1CC5DEB94F0F}.Release.Build.0 = Release|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.classic.ActiveCfg = classic|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.classic nt.ActiveCfg = classic|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Debug.ActiveCfg = Debug|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Embedded_Classic.ActiveCfg = classic|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Embedded_Classic.Build.0 = classic|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Embedded_Debug.Build.0 = Debug|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Embedded_Pro.ActiveCfg = pro|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Embedded_Pro.Build.0 = pro|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Embedded_Release.ActiveCfg = Release|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Embedded_Release.Build.0 = Release|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Max.ActiveCfg = classic|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Max nt.ActiveCfg = classic|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.nt.ActiveCfg = classic|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.pro.ActiveCfg = pro|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.pro nt.ActiveCfg = pro|Win32
+ {93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Release.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic.ActiveCfg = Debug|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic.Build.0 = Debug|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic nt.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic nt.Build.0 = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Debug.ActiveCfg = Debug|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Debug.Build.0 = Debug|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Embedded_Release.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Max.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Max.Build.0 = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Max nt.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Max nt.Build.0 = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.nt.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.nt.Build.0 = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.pro.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.pro.Build.0 = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.pro nt.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.pro nt.Build.0 = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Release.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Release.Build.0 = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.classic.ActiveCfg = classic|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.classic.Build.0 = classic|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.classic nt.ActiveCfg = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.classic nt.Build.0 = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Debug.ActiveCfg = Debug|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Debug.Build.0 = Debug|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Embedded_Release.ActiveCfg = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Max.ActiveCfg = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Max.Build.0 = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Max nt.ActiveCfg = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Max nt.Build.0 = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.nt.ActiveCfg = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.nt.Build.0 = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.pro.ActiveCfg = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.pro.Build.0 = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.pro nt.ActiveCfg = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.pro nt.Build.0 = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Release.ActiveCfg = Release|Win32
+ {B0EC3594-CD67-4364-826E-BA75EF2050F8}.Release.Build.0 = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.classic.ActiveCfg = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.classic.Build.0 = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.classic nt.ActiveCfg = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.classic nt.Build.0 = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Debug.ActiveCfg = Debug|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Debug.Build.0 = Debug|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Classic.ActiveCfg = TLS|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Classic.Build.0 = TLS|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Pro.ActiveCfg = TLS|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Pro.Build.0 = TLS|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Release.ActiveCfg = TLS|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Release.Build.0 = TLS|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Max.ActiveCfg = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Max.Build.0 = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Max nt.ActiveCfg = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Max nt.Build.0 = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.nt.ActiveCfg = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.nt.Build.0 = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.pro.ActiveCfg = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.pro.Build.0 = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.pro nt.ActiveCfg = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.pro nt.Build.0 = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Release.ActiveCfg = Release|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Release.Build.0 = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.classic.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.classic.Build.0 = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.classic nt.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.classic nt.Build.0 = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Debug.ActiveCfg = Debug|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Debug.Build.0 = Debug|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Embedded_Classic.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Embedded_Pro.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Embedded_Release.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Max.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Max.Build.0 = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Max nt.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Max nt.Build.0 = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.nt.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.nt.Build.0 = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.pro.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.pro.Build.0 = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.pro nt.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.pro nt.Build.0 = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Release.ActiveCfg = Release|Win32
+ {4C5D0EB1-B953-4BE9-A48B-4F3A874E6635}.Release.Build.0 = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.classic.ActiveCfg = classic|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.classic.Build.0 = classic|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.classic nt.ActiveCfg = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.classic nt.Build.0 = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Debug.ActiveCfg = Debug|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Debug.Build.0 = Debug|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Embedded_Release.ActiveCfg = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Max.ActiveCfg = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Max.Build.0 = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Max nt.ActiveCfg = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Max nt.Build.0 = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.nt.ActiveCfg = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.nt.Build.0 = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.pro.ActiveCfg = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.pro.Build.0 = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.pro nt.ActiveCfg = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.pro nt.Build.0 = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Release.ActiveCfg = Release|Win32
+ {87CD9881-D234-4306-BBC6-0668C6168C0F}.Release.Build.0 = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.classic.ActiveCfg = classic|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.classic.Build.0 = classic|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.classic nt.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.classic nt.Build.0 = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Debug.ActiveCfg = Debug|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Debug.Build.0 = Debug|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Embedded_Classic.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Embedded_Pro.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Embedded_Release.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Max.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Max.Build.0 = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Max nt.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Max nt.Build.0 = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.nt.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.nt.Build.0 = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.pro.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.pro.Build.0 = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.pro nt.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.pro nt.Build.0 = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Release.ActiveCfg = Release|Win32
+ {194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Release.Build.0 = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic.ActiveCfg = Debug|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic.Build.0 = Debug|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic nt.ActiveCfg = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic nt.Build.0 = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Debug.ActiveCfg = Debug|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Debug.Build.0 = Debug|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Classic.ActiveCfg = TLS|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Classic.Build.0 = TLS|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Pro.ActiveCfg = TLS|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Pro.Build.0 = TLS|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Release.ActiveCfg = TLS|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Release.Build.0 = TLS|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Max.ActiveCfg = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Max.Build.0 = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Max nt.ActiveCfg = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Max nt.Build.0 = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.nt.ActiveCfg = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.nt.Build.0 = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.pro.ActiveCfg = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.pro.Build.0 = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.pro nt.ActiveCfg = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.pro nt.Build.0 = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Release.ActiveCfg = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Release.Build.0 = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.classic.ActiveCfg = classic|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.classic.Build.0 = classic|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.classic nt.ActiveCfg = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.classic nt.Build.0 = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Debug.ActiveCfg = Debug|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Debug.Build.0 = Debug|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Embedded_Classic.ActiveCfg = classic|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Embedded_Pro.ActiveCfg = classic|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Embedded_Release.ActiveCfg = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Max.ActiveCfg = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Max.Build.0 = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Max nt.ActiveCfg = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Max nt.Build.0 = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.nt.ActiveCfg = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.nt.Build.0 = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.pro.ActiveCfg = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.pro.Build.0 = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.pro nt.ActiveCfg = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.pro nt.Build.0 = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Release.ActiveCfg = Release|Win32
+ {EF833A1E-E358-4B6C-9C27-9489E85041CC}.Release.Build.0 = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.classic.ActiveCfg = classic|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.classic.Build.0 = classic|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.classic nt.ActiveCfg = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.classic nt.Build.0 = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Debug.ActiveCfg = Debug|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Debug.Build.0 = Debug|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Embedded_Release.ActiveCfg = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Max.ActiveCfg = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Max.Build.0 = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Max nt.ActiveCfg = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Max nt.Build.0 = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.nt.ActiveCfg = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.nt.Build.0 = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.pro.ActiveCfg = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.pro.Build.0 = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.pro nt.ActiveCfg = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.pro nt.Build.0 = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Release.ActiveCfg = Release|Win32
+ {F9868FD3-7AE2-486D-BAB3-A299E11F6AC1}.Release.Build.0 = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.classic.ActiveCfg = classic|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.classic.Build.0 = classic|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.classic nt.ActiveCfg = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.classic nt.Build.0 = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Debug.ActiveCfg = Debug|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Debug.Build.0 = Debug|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Embedded_Release.ActiveCfg = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Max.ActiveCfg = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Max.Build.0 = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Max nt.ActiveCfg = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Max nt.Build.0 = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.nt.ActiveCfg = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.nt.Build.0 = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.pro.ActiveCfg = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.pro.Build.0 = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.pro nt.ActiveCfg = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.pro nt.Build.0 = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Release.ActiveCfg = Release|Win32
+ {D2B00DE0-F6E9-40AF-B90D-A257D014F098}.Release.Build.0 = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.classic.ActiveCfg = classic|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.classic.Build.0 = classic|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.classic nt.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.classic nt.Build.0 = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Debug.ActiveCfg = Debug|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Debug.Build.0 = Debug|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Embedded_Classic.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Embedded_Pro.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Embedded_Release.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Max.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Max.Build.0 = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Max nt.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Max nt.Build.0 = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.nt.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.nt.Build.0 = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.pro.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.pro.Build.0 = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.pro nt.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.pro nt.Build.0 = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Release.ActiveCfg = Release|Win32
+ {DC3A4D26-B533-465B-A3C7-9DBBC06DC8BB}.Release.Build.0 = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.classic.ActiveCfg = classic|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.classic.Build.0 = classic|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.classic nt.ActiveCfg = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.classic nt.Build.0 = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Debug.ActiveCfg = Debug|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Debug.Build.0 = Debug|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Embedded_Release.ActiveCfg = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Max.ActiveCfg = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Max.Build.0 = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Max nt.ActiveCfg = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Max nt.Build.0 = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.nt.ActiveCfg = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.nt.Build.0 = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.pro.ActiveCfg = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.pro.Build.0 = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.pro nt.ActiveCfg = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.pro nt.Build.0 = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Release.ActiveCfg = Release|Win32
+ {67154F28-D076-419E-B149-819EF548E670}.Release.Build.0 = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.classic.ActiveCfg = Debug|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.classic.Build.0 = Debug|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.classic nt.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.classic nt.Build.0 = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Debug.ActiveCfg = Debug|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Debug.Build.0 = Debug|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Embedded_Release.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Max.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Max.Build.0 = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Max nt.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Max nt.Build.0 = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.nt.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.nt.Build.0 = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.pro.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.pro.Build.0 = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.pro nt.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.pro nt.Build.0 = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Release.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.Release.Build.0 = Release|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.classic.ActiveCfg = classic|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.classic.Build.0 = classic|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.classic nt.ActiveCfg = classic nt|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.classic nt.Build.0 = classic nt|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Debug.ActiveCfg = Debug|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Debug.Build.0 = Debug|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Embedded_Classic.ActiveCfg = Release|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Embedded_Pro.ActiveCfg = Release|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Embedded_Release.ActiveCfg = Release|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Max.ActiveCfg = Max|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Max.Build.0 = Max|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Max nt.ActiveCfg = Max nt|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Max nt.Build.0 = Max nt|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.nt.ActiveCfg = nt|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.nt.Build.0 = nt|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.pro.ActiveCfg = pro|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.pro.Build.0 = pro|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.pro nt.ActiveCfg = pro nt|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.pro nt.Build.0 = pro nt|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Release.ActiveCfg = Release|Win32
+ {62E85884-3ACF-4F4C-873B-60B878147890}.Release.Build.0 = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic.ActiveCfg = classic|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic.Build.0 = classic|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic nt.ActiveCfg = classic|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic nt.Build.0 = classic|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Debug.ActiveCfg = Debug|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Debug.Build.0 = Debug|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Classic.ActiveCfg = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Pro.ActiveCfg = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Release.ActiveCfg = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max.ActiveCfg = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max.Build.0 = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max nt.ActiveCfg = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max nt.Build.0 = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.nt.ActiveCfg = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.nt.Build.0 = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro.ActiveCfg = pro|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro.Build.0 = pro|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro nt.ActiveCfg = pro|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro nt.Build.0 = pro|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Release.ActiveCfg = Release|Win32
+ {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Release.Build.0 = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.classic.ActiveCfg = classic|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.classic.Build.0 = classic|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.classic nt.ActiveCfg = classic|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.classic nt.Build.0 = classic|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Debug.ActiveCfg = Debug|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Debug.Build.0 = Debug|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Embedded_Classic.ActiveCfg = classic|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Embedded_Pro.ActiveCfg = classic|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Embedded_Release.ActiveCfg = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Max.ActiveCfg = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Max.Build.0 = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Max nt.ActiveCfg = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Max nt.Build.0 = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.nt.ActiveCfg = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.nt.Build.0 = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.pro.ActiveCfg = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.pro.Build.0 = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.pro nt.ActiveCfg = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.pro nt.Build.0 = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Release.ActiveCfg = Release|Win32
+ {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.Release.Build.0 = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.classic.ActiveCfg = classic|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.classic.Build.0 = classic|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.classic nt.ActiveCfg = classic|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.classic nt.Build.0 = classic|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Debug.ActiveCfg = Debug|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Debug.Build.0 = Debug|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Embedded_Classic.ActiveCfg = classic|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Embedded_Pro.ActiveCfg = classic|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Embedded_Release.ActiveCfg = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Max.ActiveCfg = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Max.Build.0 = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Max nt.ActiveCfg = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Max nt.Build.0 = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.nt.ActiveCfg = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.nt.Build.0 = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.pro.ActiveCfg = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.pro.Build.0 = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.pro nt.ActiveCfg = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.pro nt.Build.0 = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Release.ActiveCfg = Release|Win32
+ {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3D}.Release.Build.0 = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.classic.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.classic.Build.0 = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.classic nt.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.classic nt.Build.0 = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Debug.ActiveCfg = Debug|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Debug.Build.0 = Debug|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Classic.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Pro.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Release.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Max.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Max.Build.0 = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Max nt.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Max nt.Build.0 = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.nt.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.nt.Build.0 = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.pro.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.pro.Build.0 = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.pro nt.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.pro nt.Build.0 = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Release.ActiveCfg = Release|Win32
+ {94B86159-C581-42CD-825D-C69CBC237E5C}.Release.Build.0 = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.classic.ActiveCfg = classic|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.classic.Build.0 = classic|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.classic nt.ActiveCfg = classic|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.classic nt.Build.0 = classic|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Debug.ActiveCfg = Debug|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Debug.Build.0 = Debug|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Embedded_Release.ActiveCfg = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Max.ActiveCfg = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Max.Build.0 = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Max nt.ActiveCfg = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Max nt.Build.0 = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.nt.ActiveCfg = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.nt.Build.0 = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.pro.ActiveCfg = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.pro.Build.0 = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.pro nt.ActiveCfg = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.pro nt.Build.0 = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Release.ActiveCfg = Release|Win32
+ {3737BFE2-EF25-464F-994D-BD28A9F84528}.Release.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.classic.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.classic.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.classic nt.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.classic nt.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Debug.ActiveCfg = Debug|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Debug.Build.0 = Debug|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Embedded_Classic.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Embedded_Classic.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Embedded_Debug.Build.0 = Debug|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Embedded_Pro.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Embedded_Pro.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Embedded_Release.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Embedded_Release.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Max.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Max.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Max nt.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Max nt.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.nt.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.nt.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.pro.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.pro.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.pro nt.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.pro nt.Build.0 = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Release.ActiveCfg = Release|Win32
+ {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}.Release.Build.0 = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.classic.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.classic.Build.0 = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.classic nt.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.classic nt.Build.0 = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Debug.ActiveCfg = Debug|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Debug.Build.0 = Debug|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Classic.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Pro.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Release.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Max.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Max.Build.0 = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Max nt.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Max nt.Build.0 = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.nt.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.nt.Build.0 = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.pro.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.pro.Build.0 = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.pro nt.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.pro nt.Build.0 = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Release.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Release.Build.0 = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.classic.ActiveCfg = TLS|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.classic.Build.0 = TLS|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.classic nt.ActiveCfg = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.classic nt.Build.0 = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Debug.ActiveCfg = Debug|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Debug.Build.0 = Debug|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Embedded_Classic.ActiveCfg = TLS|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Embedded_Classic.Build.0 = TLS|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Embedded_Debug.ActiveCfg = TLS_DEBUG|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Embedded_Debug.Build.0 = TLS_DEBUG|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Embedded_Pro.ActiveCfg = TLS|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Embedded_Pro.Build.0 = TLS|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Embedded_Release.ActiveCfg = TLS|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Embedded_Release.Build.0 = TLS|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Max.ActiveCfg = Max|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Max.Build.0 = Max|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Max nt.ActiveCfg = Max|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Max nt.Build.0 = Max|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.nt.ActiveCfg = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.nt.Build.0 = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.pro.ActiveCfg = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.pro.Build.0 = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.pro nt.ActiveCfg = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.pro nt.Build.0 = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Release.ActiveCfg = Release|Win32
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF}.Release.Build.0 = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.classic.ActiveCfg = classic|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.classic.Build.0 = classic|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.classic nt.ActiveCfg = classic|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.classic nt.Build.0 = classic|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Debug.ActiveCfg = Debug|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Debug.Build.0 = Debug|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Embedded_Release.ActiveCfg = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Max.ActiveCfg = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Max.Build.0 = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Max nt.ActiveCfg = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Max nt.Build.0 = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.nt.ActiveCfg = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.nt.Build.0 = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.pro.ActiveCfg = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.pro.Build.0 = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.pro nt.ActiveCfg = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.pro nt.Build.0 = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Release.ActiveCfg = Release|Win32
+ {AC47623D-933C-4A80-83BB-B6AF7CB28B4B}.Release.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.classic.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.classic.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.classic nt.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.classic nt.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Debug.ActiveCfg = Debug|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Debug.Build.0 = Debug|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Embedded_Classic.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Embedded_Classic.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Embedded_Debug.Build.0 = Debug|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Embedded_Pro.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Embedded_Pro.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Embedded_Release.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Embedded_Release.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Max.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Max.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Max nt.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Max nt.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.nt.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.nt.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.pro.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.pro.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.pro nt.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.pro nt.Build.0 = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Release.ActiveCfg = Release|Win32
+ {207E9014-C4D1-4F6D-B76F-BC7DD7E31113}.Release.Build.0 = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.classic.ActiveCfg = classic|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.classic.Build.0 = classic|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.classic nt.ActiveCfg = classic|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.classic nt.Build.0 = classic|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Debug.ActiveCfg = Debug|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Debug.Build.0 = Debug|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Embedded_Classic.ActiveCfg = classic|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Embedded_Pro.ActiveCfg = classic|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Embedded_Release.ActiveCfg = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Max.ActiveCfg = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Max.Build.0 = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Max nt.ActiveCfg = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Max nt.Build.0 = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.nt.ActiveCfg = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.nt.Build.0 = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.pro.ActiveCfg = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.pro.Build.0 = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.pro nt.ActiveCfg = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.pro nt.Build.0 = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Release.ActiveCfg = Release|Win32
+ {16699B52-ECC6-4A96-A99F-A043059BA2E7}.Release.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.classic.ActiveCfg = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.classic.Build.0 = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.classic nt.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.classic nt.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Debug.ActiveCfg = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Debug.Build.0 = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Classic.Build.0 = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Debug.Build.0 = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Pro.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Pro.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Release.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Release.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Max.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Max.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Max nt.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Max nt.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.nt.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.nt.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.pro.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.pro.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.pro nt.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.pro nt.Build.0 = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Release.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Release.Build.0 = Release|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.classic.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.classic.Build.0 = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.classic nt.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Debug.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Debug.Build.0 = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Embedded_Release.ActiveCfg = Release|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Max.ActiveCfg = Release|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Max nt.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.nt.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.pro.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.pro nt.ActiveCfg = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Release.ActiveCfg = Release|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Release.Build.0 = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.classic.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.classic.Build.0 = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.classic nt.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Debug.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Classic.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Debug.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Pro.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Release.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Max.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Max nt.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Max nt.Build.0 = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.nt.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.pro.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.pro nt.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Release.ActiveCfg = Release|Win32
+ {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Release.Build.0 = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.classic.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.classic.Build.0 = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.classic nt.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.classic nt.Build.0 = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Debug.ActiveCfg = Debug|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Debug.Build.0 = Debug|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Embedded_Classic.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Embedded_Pro.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Embedded_Release.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Max.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Max.Build.0 = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Max nt.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Max nt.Build.0 = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.nt.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.nt.Build.0 = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.pro.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.pro.Build.0 = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.pro nt.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.pro nt.Build.0 = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Release.ActiveCfg = Release|Win32
+ {7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Release.Build.0 = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic.ActiveCfg = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic.Build.0 = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic nt.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic nt.Build.0 = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Debug.ActiveCfg = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Debug.Build.0 = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Release.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Max.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Max.Build.0 = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Max nt.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Max nt.Build.0 = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.nt.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.nt.Build.0 = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.pro.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.pro.Build.0 = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.pro nt.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.pro nt.Build.0 = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Release.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Release.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.classic.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.classic.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.classic nt.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.classic nt.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Debug.ActiveCfg = Debug|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Debug.Build.0 = Debug|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Classic.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Classic.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Pro.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Pro.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Release.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Release.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Max.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Max.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Max nt.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Max nt.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.nt.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.nt.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.pro.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.pro.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.pro nt.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.pro nt.Build.0 = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Release.ActiveCfg = Release|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Release.Build.0 = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.classic.ActiveCfg = classic|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.classic.Build.0 = classic|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.classic nt.ActiveCfg = classic|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.classic nt.Build.0 = classic|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Debug.ActiveCfg = Debug|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Debug.Build.0 = Debug|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Embedded_Release.ActiveCfg = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Max.ActiveCfg = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Max.Build.0 = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Max nt.ActiveCfg = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Max nt.Build.0 = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.nt.ActiveCfg = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.nt.Build.0 = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.pro.ActiveCfg = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.pro.Build.0 = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.pro nt.ActiveCfg = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.pro nt.Build.0 = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Release.ActiveCfg = Release|Win32
+ {8961F149-C68A-4154-A499-A2AB39E607E8}.Release.Build.0 = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic.ActiveCfg = Debug|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic.Build.0 = Debug|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic nt.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic nt.Build.0 = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Debug.ActiveCfg = Debug|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Debug.Build.0 = Debug|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Embedded_Release.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Max.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Max.Build.0 = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Max nt.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Max nt.Build.0 = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.nt.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.nt.Build.0 = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.pro.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.pro.Build.0 = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.pro nt.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.pro nt.Build.0 = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Release.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Release.Build.0 = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.classic.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.classic.Build.0 = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.classic nt.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.classic nt.Build.0 = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Debug.ActiveCfg = Debug|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Debug.Build.0 = Debug|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Embedded_Classic.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Embedded_Pro.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Embedded_Release.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Max.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Max.Build.0 = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Max nt.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Max nt.Build.0 = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.nt.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.nt.Build.0 = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.pro.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.pro.Build.0 = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.pro nt.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.pro nt.Build.0 = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Release.ActiveCfg = Release|Win32
+ {6189F838-21C6-42A1-B2D0-9146316573F7}.Release.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.classic.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.classic.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.classic nt.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.classic nt.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Debug.ActiveCfg = Debug|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Debug.Build.0 = Debug|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Embedded_Classic.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Embedded_Classic.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Embedded_Debug.Build.0 = Debug|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Embedded_Pro.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Embedded_Pro.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Embedded_Release.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Embedded_Release.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Max.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Max.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Max nt.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Max nt.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.nt.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.nt.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.pro.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.pro.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.pro nt.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.pro nt.Build.0 = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Release.ActiveCfg = Release|Win32
+ {6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/VC++Files/mysql_ia64.dsw b/VC++Files/mysql_ia64.dsw
index 8af4a7e5c42..3b588deee61 100644
--- a/VC++Files/mysql_ia64.dsw
+++ b/VC++Files/mysql_ia64.dsw
@@ -508,9 +508,6 @@ Package=<4>
Project_Dep_Name mysqlimport
End Project Dependency
Begin Project Dependency
- Project_Dep_Name MySqlManager
- End Project Dependency
- Begin Project Dependency
Project_Dep_Name mysqlshow
End Project Dependency
Begin Project Dependency
@@ -643,30 +640,6 @@ Package=<4>
###############################################################################
-Project: "mysqlshutdown"=".\mysqlshutdown\mysqlshutdown_ia64.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "mysqlwatch"=".\mysqlwatch\mysqlwatch_ia64.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
Project: "pack_isam"=".\pack_isam\pack_isam_ia64.dsp" - Package Owner=<4>
Package=<5>
diff --git a/VC++Files/mysqlbinlog/mysqlbinlog.dsp b/VC++Files/mysqlbinlog/mysqlbinlog.dsp
index 1b129072d8e..bb191944afe 100644
--- a/VC++Files/mysqlbinlog/mysqlbinlog.dsp
+++ b/VC++Files/mysqlbinlog/mysqlbinlog.dsp
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlbinlog.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlbinlog.exe" /libpath:"..\lib_release\\"
# SUBTRACT LINK32 /pdb:none /debug
!ELSEIF "$(CFG)" == "mysqlbinlog - Win32 Debug"
@@ -76,7 +76,7 @@ BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlbinlog.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlbinlog.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
!ELSEIF "$(CFG)" == "mysqlbinlog - Win32 classic"
@@ -102,7 +102,7 @@ BSC32=bscmake.exe
LINK32=xilink6.exe
# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlbinlog.exe" /libpath:"..\lib_release\\"
# SUBTRACT BASE LINK32 /pdb:none /debug
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlbinlog.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlbinlog.exe" /libpath:"..\lib_release\\"
# SUBTRACT LINK32 /pdb:none /debug
!ENDIF
diff --git a/VC++Files/mysqlbinlog/mysqlbinlog.vcproj b/VC++Files/mysqlbinlog/mysqlbinlog.vcproj
new file mode 100755
index 00000000000..9d5d4db2565
--- /dev/null
+++ b/VC++Files/mysqlbinlog/mysqlbinlog.vcproj
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqlbinlog"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../sql"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS;MYSQL_SERVER"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/mysqlbinlog.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_debug/mysqlbinlog.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/mysqlbinlog.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/mysqlbinlog.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../sql"
+ PreprocessorDefinitions="MYSQL_SERVER;_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqlbinlog.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_classic/mysqlbinlog.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/mysqlbinlog.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysqlbinlog.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\eelease"
+ IntermediateDirectory=".\eelease"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../,../sql"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;MYSQL_SERVER;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\eelease/mysqlbinlog.pch"
+ AssemblerListingLocation=".\eelease/"
+ ObjectFile=".\eelease/"
+ ProgramDataBaseFileName=".\eelease/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_release/mysqlbinlog.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\eelease/mysqlbinlog.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\eelease/mysqlbinlog.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\mysys\mf_tempdir.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\client\mysqlbinlog.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/mysqlcheck/mysqlcheck.dsp b/VC++Files/mysqlcheck/mysqlcheck.dsp
index 51a817cc067..1f047e04155 100644
--- a/VC++Files/mysqlcheck/mysqlcheck.dsp
+++ b/VC++Files/mysqlcheck/mysqlcheck.dsp
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlcheck.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlcheck.exe" /libpath:"..\lib_release\\"
!ELSEIF "$(CFG)" == "mysqlcheck - Win32 Debug"
@@ -75,7 +75,7 @@ BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlcheck.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlcheck.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
!ELSEIF "$(CFG)" == "mysqlcheck - Win32 classic"
@@ -100,7 +100,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=xilink6.exe
# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlcheck.exe" /libpath:"..\lib_release\\"
-# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlcheck.exe" /libpath:"..\lib_release\\"
+# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlcheck.exe" /libpath:"..\lib_release\\"
!ENDIF
diff --git a/VC++Files/mysqlcheck/mysqlcheck.vcproj b/VC++Files/mysqlcheck/mysqlcheck.vcproj
new file mode 100755
index 00000000000..f47e171fd65
--- /dev/null
+++ b/VC++Files/mysqlcheck/mysqlcheck.vcproj
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqlcheck"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="MYSQL_SERVER;_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqlcheck.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_classic/mysqlcheck.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/mysqlcheck.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysqlcheck.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;MYSQL_SERVER;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqlcheck.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_release/mysqlcheck.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\Release/mysqlcheck.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/mysqlcheck.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS;MYSQL_SERVER"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/mysqlcheck.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_debug/mysqlcheck.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/mysqlcheck.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/mysqlcheck.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\client\mysqlcheck.c">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/mysqldemb/mysqldemb.dsp b/VC++Files/mysqldemb/mysqldemb.dsp
index a8207d436a0..61a745ff7e8 100644
--- a/VC++Files/mysqldemb/mysqldemb.dsp
+++ b/VC++Files/mysqldemb/mysqldemb.dsp
@@ -169,10 +169,6 @@ SOURCE=..\sql\ha_innodb.cpp
# End Source File
# Begin Source File
-SOURCE=..\sql\ha_isammrg.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\sql\ha_myisam.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/mysqldemb/mysqldemb.vcproj b/VC++Files/mysqldemb/mysqldemb.vcproj
new file mode 100755
index 00000000000..52081adb214
--- /dev/null
+++ b/VC++Files/mysqldemb/mysqldemb.vcproj
@@ -0,0 +1,2960 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqldemb"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../include,../regex,../libmysqld,../sql,../zlib"
+ PreprocessorDefinitions="WIN32;_LIB;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;MYSQL_SERVER;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqldemb.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_classic\mysqldemb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="pro|Win32"
+ OutputDirectory=".\pro"
+ IntermediateDirectory=".\pro"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-pro"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../include,../regex,../libmysqld,../sql,../zlib"
+ PreprocessorDefinitions="WIN32;_LIB;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;USE_SYMDIR;MYSQL_SERVER;LICENSE=Commercial;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\pro/mysqldemb.pch"
+ AssemblerListingLocation=".\pro/"
+ ObjectFile=".\pro/"
+ ProgramDataBaseFileName=".\pro/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_pro\mysqldemb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../zlib,../include,../regex,../libmysqld,../sql,../bdb/build_win32"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;MYSQL_SERVER;HAVE_INNOBASE_DB;USE_TLS;__WIN__"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/mysqldemb.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib_debug/mysqldemb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../include,../regex,../libmysqld,../sql,../bdb/build_win32,../zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;MYSQL_SERVER;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqldemb.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\mysqldemb.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\sql\derror.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\errmsg.c">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\field.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\field_conv.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\filesort.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\get_password.c">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_heap.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_innodb.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_myisam.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\ha_myisammrg.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\handler.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\hash_filo.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\hostname.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\init.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_buff.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_cmpfunc.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_create.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_func.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_row.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_strfunc.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_subselect.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_sum.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_timefunc.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\item_uniq.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\key.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysqld\lib_sql.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysqld\libmysqld.c">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\lock.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\log.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\log_event.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\mf_iocache.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\net_serv.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\opt_range.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\opt_sum.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\password.c">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\procedure.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\protocol.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\records.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\repl_failsafe.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\slave.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_acl.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_analyse.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_base.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_cache.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_class.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_crypt.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_db.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_delete.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_derived.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_do.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_error.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_handler.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_insert.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_lex.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_list.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_manager.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_map.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_parse.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_prepare.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_rename.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_repl.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_select.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_show.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_string.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_table.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_test.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_udf.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_union.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_update.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\sql_yacc.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\table.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\thr_malloc.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\time.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\uniques.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\sql\unireg.cpp">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/mysqlmanager/MySqlManager_ia64.dsp b/VC++Files/mysqlmanager/MySqlManager_ia64.dsp
deleted file mode 100644
index b0ffc9e48c6..00000000000
--- a/VC++Files/mysqlmanager/MySqlManager_ia64.dsp
+++ /dev/null
@@ -1,276 +0,0 @@
-# Microsoft Developer Studio Project File - Name="MySqlManager" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Application" 0x0101
-
-CFG=MYSQLMANAGER - WinIA64 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 "MySqlManager.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 "MySqlManager.mak" CFG="MYSQLMANAGER - WinIA64 DEBUG"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "MySqlManager - WinIA64 Release" (based on "Win32 (x86) Application")
-!MESSAGE "MySqlManager - WinIA64 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "MySqlManager - WinIA64 Release"
-
-# PROP BASE Use_MFC 6
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 6
-# 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 /MD /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /MT /W3 /Zi /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c
-# SUBTRACT CPP /WX /Fr /YX /Yc /Yu
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win64
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win64
-# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
-# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 /nologo /subsystem:windows /machine:IA64
-# ADD LINK32 /nologo /subsystem:windows /out:"../client_release/MySqlManager.exe" /machine:IA64
-# SUBTRACT LINK32 /nodefaultlib
-
-!ELSEIF "$(CFG)" == "MySqlManager - WinIA64 Debug"
-
-# PROP BASE Use_MFC 6
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 6
-# 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 /MDd /W3 /Gm /GX /Zi /Od /D "WIN64" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /MTd /W3 /GR /Zi /Od /I "../include" /D "_DEBUG" /D "_WINDOWS" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c
-# SUBTRACT CPP /Fr /YX /Yc /Yu
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win64
-# ADD MTL /nologo /D "_DEBUG" /o "NUL" /win64
-# SUBTRACT MTL /mktyplib203
-# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:IA64
-# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib /nologo /subsystem:windows /incremental:no /debug /out:"../client_debug/MySqlManager.exe" /libpath:"..\lib_debug\\" /machine:IA64
-
-!ENDIF
-
-# Begin Target
-
-# Name "MySqlManager - WinIA64 Release"
-# Name "MySqlManager - WinIA64 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\ChildFrm.cpp
-# End Source File
-# Begin Source File
-
-SOURCE="..\strings\ctype-extra.c"
-# End Source File
-# Begin Source File
-
-SOURCE="..\strings\ctype-latin1.c"
-# End Source File
-# Begin Source File
-
-SOURCE="..\strings\ctype-mb.c"
-# End Source File
-# Begin Source File
-
-SOURCE=..\strings\is_prefix.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\MainFrm.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\mysys\my_sleep.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\strings\my_vsnprintf.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManager.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManager.rc
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManagerDoc.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManagerView.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\RegisterServer.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\StdAfx.cpp
-# ADD CPP /Yc"stdafx.h"
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSql.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlQuery.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlResults.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlStatus.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\ChildFrm.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\MainFrm.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManager.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManagerDoc.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManagerView.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\RegisterServer.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resource.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\StdAfx.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlQuery.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlResults.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlStatus.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
-# Begin Source File
-
-SOURCE=.\res\bitmap1.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\bitmap3.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\bmp00001.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\bmp00002.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\database.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\fontd.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\fontu.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\MySqlManager.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\MySqlManager.rc2
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\MySqlManagerDoc.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\query_ex.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\Toolbar.bmp
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE=.\ReadMe.txt
-# End Source File
-# End Target
-# End Project
diff --git a/VC++Files/mysqlmanager/README.TXT b/VC++Files/mysqlmanager/README.TXT
deleted file mode 100644
index cdd54c2cba8..00000000000
--- a/VC++Files/mysqlmanager/README.TXT
+++ /dev/null
@@ -1,102 +0,0 @@
-========================================================================
- MICROSOFT FOUNDATION CLASS LIBRARY : MySqlManager
-========================================================================
-
-
-AppWizard has created this MySqlManager application for you. This application
-not only demonstrates the basics of using the Microsoft Foundation classes
-but is also a starting point for writing your application.
-
-This file contains a summary of what you will find in each of the files that
-make up your MySqlManager application.
-
-MySqlManager.h
- This is the main header file for the application. It includes other
- project specific headers (including Resource.h) and declares the
- CMySqlManagerApp application class.
-
-MySqlManager.cpp
- This is the main application source file that contains the application
- class CMySqlManagerApp.
-
-MySqlManager.rc
- This is a listing of all of the Microsoft Windows resources that the
- program uses. It includes the icons, bitmaps, and cursors that are stored
- in the RES subdirectory. This file can be directly edited in Microsoft
- Developer Studio.
-
-res\MySqlManager.ico
- This is an icon file, which is used as the application's icon. This
- icon is included by the main resource file MySqlManager.rc.
-
-res\MySqlManager.rc2
- This file contains resources that are not edited by Microsoft
- Developer Studio. You should place all resources not
- editable by the resource editor in this file.
-
-MySqlManager.clw
- This file contains information used by ClassWizard to edit existing
- classes or add new classes. ClassWizard also uses this file to store
- information needed to create and edit message maps and dialog data
- maps and to create prototype member functions.
-
-/////////////////////////////////////////////////////////////////////////////
-
-For the main frame window:
-
-MainFrm.h, MainFrm.cpp
- These files contain the frame class CMainFrame, which is derived from
- CMDIFrameWnd and controls all MDI frame features.
-
-res\Toolbar.bmp
- This bitmap file is used to create tiled images for the toolbar.
- The initial toolbar and status bar are constructed in the
- CMainFrame class. Edit this toolbar bitmap along with the
- array in MainFrm.cpp to add more toolbar buttons.
-
-/////////////////////////////////////////////////////////////////////////////
-
-AppWizard creates one document type and one view:
-
-MySqlManagerDoc.h, MySqlManagerDoc.cpp - the document
- These files contain your CMySqlManagerDoc class. Edit these files to
- add your special document data and to implement file saving and loading
- (via CMySqlManagerDoc::Serialize).
-
-MySqlManagerView.h, MySqlManagerView.cpp - the view of the document
- These files contain your CMySqlManagerView class.
- CMySqlManagerView objects are used to view CMySqlManagerDoc objects.
-
-res\MySqlManagerDoc.ico
- This is an icon file, which is used as the icon for MDI child windows
- for the CMySqlManagerDoc class. This icon is included by the main
- resource file MySqlManager.rc.
-
-
-/////////////////////////////////////////////////////////////////////////////
-Other standard files:
-
-StdAfx.h, StdAfx.cpp
- These files are used to build a precompiled header (PCH) file
- named MySqlManager.pch and a precompiled types file named StdAfx.obj.
-
-Resource.h
- This is the standard header file, which defines new resource IDs.
- Microsoft Developer Studio reads and updates this file.
-
-/////////////////////////////////////////////////////////////////////////////
-Other notes:
-
-AppWizard uses "TODO:" to indicate parts of the source code you
-should add to or customize.
-
-If your application uses MFC in a shared DLL, and your application is
-in a language other than the operating system's current language, you
-will need to copy the corresponding localized resources MFC40XXX.DLL
-from the Microsoft Visual C++ CD-ROM onto the system or system32 directory,
-and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation.
-For example, MFC40DEU.DLL contains resources translated to German.) If you
-don't do this, some of the UI elements of your application will remain in the
-language of the operating system.
-
-/////////////////////////////////////////////////////////////////////////////
diff --git a/VC++Files/mysqlmanager/RES/bitmap1.bmp b/VC++Files/mysqlmanager/RES/bitmap1.bmp
deleted file mode 100644
index 3751f1a6923..00000000000
--- a/VC++Files/mysqlmanager/RES/bitmap1.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/bitmap3.bmp b/VC++Files/mysqlmanager/RES/bitmap3.bmp
deleted file mode 100644
index 3751f1a6923..00000000000
--- a/VC++Files/mysqlmanager/RES/bitmap3.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/bmp00001.bmp b/VC++Files/mysqlmanager/RES/bmp00001.bmp
deleted file mode 100644
index e98e93d7850..00000000000
--- a/VC++Files/mysqlmanager/RES/bmp00001.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/bmp00002.bmp b/VC++Files/mysqlmanager/RES/bmp00002.bmp
deleted file mode 100644
index 2f2c195a683..00000000000
--- a/VC++Files/mysqlmanager/RES/bmp00002.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/database.bmp b/VC++Files/mysqlmanager/RES/database.bmp
deleted file mode 100644
index 2fc41313541..00000000000
--- a/VC++Files/mysqlmanager/RES/database.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/fontd.bmp b/VC++Files/mysqlmanager/RES/fontd.bmp
deleted file mode 100644
index c77b4f4fdd0..00000000000
--- a/VC++Files/mysqlmanager/RES/fontd.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/fontu.bmp b/VC++Files/mysqlmanager/RES/fontu.bmp
deleted file mode 100644
index c77b4f4fdd0..00000000000
--- a/VC++Files/mysqlmanager/RES/fontu.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/mysqlmanager.ico b/VC++Files/mysqlmanager/RES/mysqlmanager.ico
deleted file mode 100644
index 7eef0bcbe65..00000000000
--- a/VC++Files/mysqlmanager/RES/mysqlmanager.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/mysqlmanager.rc2 b/VC++Files/mysqlmanager/RES/mysqlmanager.rc2
deleted file mode 100644
index 67d4f3f4a85..00000000000
--- a/VC++Files/mysqlmanager/RES/mysqlmanager.rc2
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-// MYSQLMANAGER.RC2 - resources Microsoft Visual C++ does not edit directly
-//
-
-#ifdef APSTUDIO_INVOKED
- #error this file is not editable by Microsoft Visual C++
-#endif //APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-// Add manually edited resources here...
-
-/////////////////////////////////////////////////////////////////////////////
diff --git a/VC++Files/mysqlmanager/RES/mysqlmanagerdoc.ico b/VC++Files/mysqlmanager/RES/mysqlmanagerdoc.ico
deleted file mode 100644
index 2a1f1ae6ef1..00000000000
--- a/VC++Files/mysqlmanager/RES/mysqlmanagerdoc.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/query_ex.bmp b/VC++Files/mysqlmanager/RES/query_ex.bmp
deleted file mode 100644
index cc77222decc..00000000000
--- a/VC++Files/mysqlmanager/RES/query_ex.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/RES/toolbar.bmp b/VC++Files/mysqlmanager/RES/toolbar.bmp
deleted file mode 100644
index d501723c1ce..00000000000
--- a/VC++Files/mysqlmanager/RES/toolbar.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlmanager/childfrm.cpp b/VC++Files/mysqlmanager/childfrm.cpp
deleted file mode 100644
index 08027e068ac..00000000000
--- a/VC++Files/mysqlmanager/childfrm.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// ChildFrm.cpp : implementation of the CChildFrame class
-//
-
-#include "stdafx.h"
-#include "MySqlManager.h"
-
-#include "ChildFrm.h"
-
-#ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// CChildFrame
-
-IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)
-
-BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
-//{{AFX_MSG_MAP(CChildFrame)
-// NOTE - the ClassWizard will add and remove mapping macros here.
-// DO NOT EDIT what you see in these blocks of generated code !
-//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// CChildFrame construction/destruction
-
-CChildFrame::CChildFrame()
-{
- // TODO: add member initialization code here
-
-}
-
-CChildFrame::~CChildFrame()
-{
-}
-
-BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
-{
- // TODO: Modify the Window class or styles here by modifying
- // the CREATESTRUCT cs
-
- return CMDIChildWnd::PreCreateWindow(cs);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// CChildFrame diagnostics
-
-#ifdef _DEBUG
-void CChildFrame::AssertValid() const
-{
- CMDIChildWnd::AssertValid();
-}
-
-void CChildFrame::Dump(CDumpContext& dc) const
-{
- CMDIChildWnd::Dump(dc);
-}
-
-#endif //_DEBUG
-
-/////////////////////////////////////////////////////////////////////////////
-// CChildFrame message handlers
diff --git a/VC++Files/mysqlmanager/childfrm.h b/VC++Files/mysqlmanager/childfrm.h
deleted file mode 100644
index 3075be58a67..00000000000
--- a/VC++Files/mysqlmanager/childfrm.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// ChildFrm.h : interface of the CChildFrame class
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_CHILDFRM_H__826CB2F0_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_CHILDFRM_H__826CB2F0_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-class CChildFrame : public CMDIChildWnd
-{
- DECLARE_DYNCREATE(CChildFrame)
-public:
- CChildFrame();
-
-// Attributes
-public:
-
-// Operations
-public:
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CChildFrame)
- virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
- //}}AFX_VIRTUAL
-
-// Implementation
-public:
- virtual ~CChildFrame();
-#ifdef _DEBUG
- virtual void AssertValid() const;
- virtual void Dump(CDumpContext& dc) const;
-#endif
-
-// Generated message map functions
-protected:
- //{{AFX_MSG(CChildFrame)
- // NOTE - the ClassWizard will add and remove member functions here.
- // DO NOT EDIT what you see in these blocks of generated code!
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_CHILDFRM_H__826CB2F0_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/cresource.h b/VC++Files/mysqlmanager/cresource.h
deleted file mode 100644
index 37c1839d758..00000000000
--- a/VC++Files/mysqlmanager/cresource.h
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef _CRESOURCE_H
-#define _CRESOURCE_H
-
-/////////////////////////////////////////////////////////////////////////////
-
-#define MYSQL_PORT_AS_STRING "3306" /* Can't use # in preprocessor because of bugs in VC++ 5.0 */
-
-class CResource
-{
-public:
- enum eRESOURCETYPE
- {
- eNone
- , eServer
- , eDatabase
- , eTable
- , eField
- , eProcesslist
- , eProcesslistItem
- };
- virtual LPCTSTR GetDisplayName() { return ""; }
- virtual LPCTSTR GetHostName() { return LOCAL_HOST; }
- virtual LPCTSTR GetUserName() { return "root"; }
- virtual LPCTSTR GetPassword() { return ""; }
- virtual LPCTSTR GetPortName() { return MYSQL_PORT_AS_STRING; }
- virtual int GetPortNumber() { return MYSQL_PORT; }
- virtual eRESOURCETYPE GetType() { return eNone; }
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-class CResourceServer : public CResource
-{
-public:
- CResourceServer(LPCTSTR pszName = "",LPCTSTR pszHost = LOCAL_HOST ,LPCTSTR pszUser = "root", LPCTSTR pszPassword = "", LPCTSTR pszPort = MYSQL_PORT_AS_STRING)
- : m_strName(pszName)
- , m_strHost(pszHost)
- , m_strUser(pszUser)
- , m_strPassword(pszPassword)
- , m_strPort(pszPort)
- {
- }
- virtual LPCTSTR GetDisplayName() { return m_strName; }
- virtual LPCTSTR GetHostName() { return m_strHost; }
- virtual LPCTSTR GetUserName() { return m_strUser; }
- virtual LPCTSTR GetPassword() { return m_strPassword; }
- virtual eRESOURCETYPE GetType() { return eServer; }
- virtual LPCTSTR GetPortName() { return m_strPort; }
- virtual int GetPortNumber() { return atoi(m_strPort); }
- CString m_strName;
- CString m_strHost;
- CString m_strUser;
- CString m_strPassword;
- CString m_strPort;
- CStringArray m_rgFields;
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-class CResourceDatabase : public CResource
-{
-public:
- CResourceDatabase(LPCTSTR pszName = "")
- : m_strName(pszName)
- {
- }
- virtual LPCTSTR GetDisplayName() { return m_strName; }
- virtual eRESOURCETYPE GetType() { return eDatabase; }
- CString m_strName;
- CStringArray m_rgFields;
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-class CResourceTable : public CResource
-{
-public:
- CResourceTable(LPCTSTR pszName = "")
- : m_strName(pszName)
- {
- }
- virtual LPCTSTR GetDisplayName() { return m_strName; }
- virtual eRESOURCETYPE GetType() { return eTable; }
- CString m_strName;
- CStringArray m_rgFields;
-};
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-class CResourceField : public CResource
-{
-public:
- CResourceField(LPCTSTR pszName = "")
- : m_strName(pszName)
- {
- }
- virtual LPCTSTR GetDisplayName() { return m_strName; }
- virtual eRESOURCETYPE GetType() { return eField; }
- CString m_strName;
- CStringArray m_rgFields;
-};
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-class CResourceProcesslist : public CResource
-{
-public:
- CResourceProcesslist(LPCTSTR pszName = "Processlist")
- : m_strName(pszName)
- {
- }
- virtual LPCTSTR GetDisplayName() { return m_strName; }
- virtual eRESOURCETYPE GetType() { return eProcesslist; }
- CString m_strName;
- CStringArray m_rgFields;
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-class CResourceProcesslistItem : public CResourceProcesslist
-{
-public:
- CResourceProcesslistItem(LPCTSTR pszName = "ProcesslistItem")
- : CResourceProcesslist(pszName)
- {
- }
- virtual eRESOURCETYPE GetType() { return eProcesslistItem; }
-};
-
-
-#endif
diff --git a/VC++Files/mysqlmanager/mainfrm.cpp b/VC++Files/mysqlmanager/mainfrm.cpp
deleted file mode 100644
index 499704ed2a0..00000000000
--- a/VC++Files/mysqlmanager/mainfrm.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-// MainFrm.cpp : implementation of the CMainFrame class
-//
-
-#include "stdafx.h"
-#include "MySqlManager.h"
-#include "MainFrm.h"
-
-CMainFrame* CMainFrame::g_pMainFrame = NULL;
-
-#ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// CMainFrame
-
-IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
-
-BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
-//{{AFX_MSG_MAP(CMainFrame)
-// NOTE - the ClassWizard will add and remove mapping macros here.
-// DO NOT EDIT what you see in these blocks of generated code !
- ON_WM_CREATE()
-//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-static UINT indicators[] =
-{
- ID_SEPARATOR, // status line indicator
- ID_INDICATOR_CAPS,
- ID_INDICATOR_NUM,
- ID_INDICATOR_SCRL,
-};
-
-/////////////////////////////////////////////////////////////////////////////
-// CMainFrame construction/destruction
-
-CMainFrame::CMainFrame()
-{
- // TODO: add member initialization code here
-
-}
-
-CMainFrame::~CMainFrame()
-{
-}
-
-int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
-{
- if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
- return -1;
-
- if (!m_wndToolBar.Create(this) ||
- !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
- {
- TRACE0("Failed to create toolbar\n");
- return -1; // fail to create
- }
-
- if (!m_wndStatusBar.Create(this) ||
- !m_wndStatusBar.SetIndicators(indicators,
- sizeof(indicators)/sizeof(UINT)))
- {
- TRACE0("Failed to create status bar\n");
- return -1; // fail to create
- }
-
- // TODO: Remove this if you don't want tool tips or a resizeable toolbar
- m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
- CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
-
- // TODO: Delete these three lines if you don't want the toolbar to
- // be dockable
- m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
- EnableDocking(CBRS_ALIGN_ANY);
- DockControlBar(&m_wndToolBar);
-
- return 0;
-}
-
-BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
-{
- // TODO: Modify the Window class or styles here by modifying
- // the CREATESTRUCT cs
-
- return CMDIFrameWnd::PreCreateWindow(cs);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// CMainFrame diagnostics
-
-#ifdef _DEBUG
-void CMainFrame::AssertValid() const
-{
- CMDIFrameWnd::AssertValid();
-}
-
-void CMainFrame::Dump(CDumpContext& dc) const
-{
- CMDIFrameWnd::Dump(dc);
-}
-
-#endif //_DEBUG
-
-/////////////////////////////////////////////////////////////////////////////
-// CMainFrame message handlers
-
-int CMainFrame::StatusMsg ( LPCSTR fmt, ... )
-
-{
-
- char buf [2048];
- va_list args;
- va_start(args, fmt);
- int ret = vsprintf(buf, fmt, args);
-
- if ( this != NULL )
- {
- static char g_StatusMsg_Buffer_TT [ 2048 ];
- memcpy ( g_StatusMsg_Buffer_TT, buf, sizeof(g_StatusMsg_Buffer_TT) );
- m_wndStatusBar.SetPaneText ( 0, buf );
- m_wndStatusBar.UpdateWindow ();
- }
-
- va_end(args);
- return ( ret );
-
-}
-
-
-BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
-{
- g_pMainFrame = this;
- return CMDIFrameWnd::OnCreateClient(lpcs, pContext);
-}
diff --git a/VC++Files/mysqlmanager/mainfrm.h b/VC++Files/mysqlmanager/mainfrm.h
deleted file mode 100644
index 06c51965bb1..00000000000
--- a/VC++Files/mysqlmanager/mainfrm.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// MainFrm.h : interface of the CMainFrame class
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_MAINFRM_H__826CB2EE_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_MAINFRM_H__826CB2EE_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-class CMainFrame : public CMDIFrameWnd
-{
- DECLARE_DYNAMIC(CMainFrame)
-public:
- CMainFrame();
-
-// Attributes
-public:
-
-// Operations
-public:
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CMainFrame)
- public:
- virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
- protected:
- virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
- //}}AFX_VIRTUAL
-
-// Implementation
-public:
- virtual ~CMainFrame();
-#ifdef _DEBUG
- virtual void AssertValid() const;
- virtual void Dump(CDumpContext& dc) const;
-#endif
-
- int StatusMsg ( LPCSTR fmt, ... );
-
-protected: // control bar embedded members
- CStatusBar m_wndStatusBar;
- CToolBar m_wndToolBar;
-
-// Generated message map functions
-protected:
- //{{AFX_MSG(CMainFrame)
- afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
- // NOTE - the ClassWizard will add and remove member functions here.
- // DO NOT EDIT what you see in these blocks of generated code!
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-
-public:
-
-static CMainFrame* g_pMainFrame;
-
-};
-
-#define MainFrame ( CMainFrame::g_pMainFrame ? CMainFrame::g_pMainFrame : (CMainFrame*) AfxGetMainWnd() -> GetTopLevelFrame() )
-
-/////////////////////////////////////////////////////////////////////////////
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_MAINFRM_H__826CB2EE_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/mysqlmanager.cpp b/VC++Files/mysqlmanager/mysqlmanager.cpp
deleted file mode 100644
index 09a19181e22..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanager.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// MySqlManager.cpp : Defines the class behaviors for the application.
-//
-
-#include "stdafx.h"
-#include "MySqlManager.h"
-
-#include "MainFrm.h"
-#include "ChildFrm.h"
-#include "MySqlManagerDoc.h"
-#include "MySqlManagerView.h"
-
-#ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerApp
-
-BEGIN_MESSAGE_MAP(CMySqlManagerApp, CWinApp)
-//{{AFX_MSG_MAP(CMySqlManagerApp)
- ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
-// NOTE - the ClassWizard will add and remove mapping macros here.
-// DO NOT EDIT what you see in these blocks of generated code!
-//}}AFX_MSG_MAP
-// Standard file based document commands
- ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
- ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
-// Standard print setup command
- ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerApp construction
-
-CMySqlManagerApp::CMySqlManagerApp()
-{
- // TODO: add construction code here,
- // Place all significant initialization in InitInstance
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// The one and only CMySqlManagerApp object
-
-CMySqlManagerApp theApp;
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerApp initialization
-
-BOOL CMySqlManagerApp::InitInstance()
-{
-
- WSADATA WsaData;
-
- if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
- {
- AfxMessageBox("WSAStartup Failed\n");
- return FALSE;
- }
-
- AfxEnableControlContainer();
-
- // Standard initialization
- // If you are not using these features and wish to reduce the size
- // of your final executable, you should remove from the following
- // the specific initialization routines you do not need.
-
-#ifdef _AFXDLL
- Enable3dControls(); // Call this when using MFC in a shared DLL
-#else
- Enable3dControlsStatic(); // Call this when linking to MFC statically
-#endif
-
- // Change the registry key under which our settings are stored.
- // You should modify this string to be something appropriate
- // such as the name of your company or organization.
- SetRegistryKey(_T("Local AppWizard-Generated Applications"));
-
- LoadStdProfileSettings(); // Load standard INI file options (including MRU)
-
- // Register the application's document templates. Document templates
- // serve as the connection between documents, frame windows and views.
-
- CMultiDocTemplate* pDocTemplate;
- pDocTemplate = new CMultiDocTemplate(
- IDR_MYSQLMTYPE,
- RUNTIME_CLASS(CMySqlManagerDoc),
- RUNTIME_CLASS(CChildFrame), // custom MDI child frame
- RUNTIME_CLASS(CMySqlManagerView));
- AddDocTemplate(pDocTemplate);
-
- // create main MDI Frame window
- CMainFrame* pMainFrame = new CMainFrame;
- if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
- return FALSE;
- m_pMainWnd = pMainFrame;
-
- // Parse command line for standard shell commands, DDE, file open
- CCommandLineInfo cmdInfo;
- ParseCommandLine(cmdInfo);
-
- // Dispatch commands specified on the command line
- if (!ProcessShellCommand(cmdInfo))
- return FALSE;
-
- // The main window has been initialized, so show and update it.
- pMainFrame->ShowWindow(m_nCmdShow);
- pMainFrame->UpdateWindow();
-
- return TRUE;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// CAboutDlg dialog used for App About
-
-class CAboutDlg : public CDialog
-{
-public:
- CAboutDlg();
-
-// Dialog Data
- //{{AFX_DATA(CAboutDlg)
- enum {IDD = IDD_ABOUTBOX};
- //}}AFX_DATA
-
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CAboutDlg)
-protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
-// Implementation
-protected:
- //{{AFX_MSG(CAboutDlg)
- // No message handlers
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
-{
- //{{AFX_DATA_INIT(CAboutDlg)
- //}}AFX_DATA_INIT
-}
-
-void CAboutDlg::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CAboutDlg)
- //}}AFX_DATA_MAP
-}
-
-BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
-//{{AFX_MSG_MAP(CAboutDlg)
-// No message handlers
-//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-// App command to run the dialog
-void CMySqlManagerApp::OnAppAbout()
-{
- CAboutDlg aboutDlg;
- aboutDlg.DoModal();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerApp commands
diff --git a/VC++Files/mysqlmanager/mysqlmanager.dsp b/VC++Files/mysqlmanager/mysqlmanager.dsp
deleted file mode 100644
index 27aa1a77024..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanager.dsp
+++ /dev/null
@@ -1,277 +0,0 @@
-# Microsoft Developer Studio Project File - Name="MySqlManager" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Application" 0x0101
-
-CFG=MySqlManager - 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 "MySqlManager.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 "MySqlManager.mak" CFG="MySqlManager - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "MySqlManager - Win32 Release" (based on "Win32 (x86) Application")
-!MESSAGE "MySqlManager - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=xicl6.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "MySqlManager - Win32 Release"
-
-# PROP BASE Use_MFC 6
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 6
-# 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 /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /WX /Fr /YX /Yc /Yu
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
-# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=xilink6.exe
-# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
-# ADD LINK32 zlib.lib /nologo /subsystem:windows /machine:I386 /out:"../client_release/MySqlManager.exe" /libpath:"..\lib_release\\"
-# SUBTRACT LINK32 /nodefaultlib
-
-!ELSEIF "$(CFG)" == "MySqlManager - Win32 Debug"
-
-# PROP BASE Use_MFC 6
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 6
-# 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 /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /GR /GX /Z7 /Od /I "../include" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# SUBTRACT CPP /Fr /YX /Yc /Yu
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
-# ADD MTL /nologo /D "_DEBUG" /o "NUL" /win32
-# SUBTRACT MTL /mktyplib203
-# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=xilink6.exe
-# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib zlib.lib /nologo /subsystem:windows /incremental:no /debug /machine:I386 /out:"../client_debug/MySqlManager.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF
-
-# Begin Target
-
-# Name "MySqlManager - Win32 Release"
-# Name "MySqlManager - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\ChildFrm.cpp
-# End Source File
-# Begin Source File
-
-SOURCE="..\strings\ctype-extra.c"
-# End Source File
-# Begin Source File
-
-SOURCE="..\strings\ctype-latin1.c"
-# End Source File
-# Begin Source File
-
-SOURCE="..\strings\ctype-mb.c"
-# End Source File
-# Begin Source File
-
-SOURCE=..\strings\is_prefix.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\MainFrm.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\mysys\my_sleep.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\strings\my_vsnprintf.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManager.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManager.rc
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManagerDoc.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManagerView.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\RegisterServer.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\StdAfx.cpp
-# ADD CPP /Yc"stdafx.h"
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSql.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlQuery.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlResults.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlStatus.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\ChildFrm.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\MainFrm.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManager.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManagerDoc.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\MySqlManagerView.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\RegisterServer.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Resource.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\StdAfx.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlQuery.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlResults.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ToolSqlStatus.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
-# Begin Source File
-
-SOURCE=.\res\bitmap1.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\bitmap3.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\bmp00001.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\bmp00002.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\database.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\fontd.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\fontu.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\MySqlManager.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\MySqlManager.rc2
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\MySqlManagerDoc.ico
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\query_ex.bmp
-# End Source File
-# Begin Source File
-
-SOURCE=.\res\Toolbar.bmp
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE=.\ReadMe.txt
-# End Source File
-# End Target
-# End Project
diff --git a/VC++Files/mysqlmanager/mysqlmanager.h b/VC++Files/mysqlmanager/mysqlmanager.h
deleted file mode 100644
index accb63a908f..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanager.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// MySqlManager.h : main header file for the MYSQLMANAGER application
-//
-
-#if !defined(AFX_MYSQLMANAGER_H__826CB2EA_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_MYSQLMANAGER_H__826CB2EA_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-#ifndef __AFXWIN_H__
- #error include 'stdafx.h' before including this file for PCH
-#endif
-
-#include "resource.h" // main symbols
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerApp:
-// See MySqlManager.cpp for the implementation of this class
-//
-
-class CMySqlManagerApp : public CWinApp
-{
-public:
- CMySqlManagerApp();
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CMySqlManagerApp)
- public:
- virtual BOOL InitInstance();
- //}}AFX_VIRTUAL
-
-// Implementation
-
- //{{AFX_MSG(CMySqlManagerApp)
- afx_msg void OnAppAbout();
- // NOTE - the ClassWizard will add and remove member functions here.
- // DO NOT EDIT what you see in these blocks of generated code !
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_MYSQLMANAGER_H__826CB2EA_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/mysqlmanager.mak b/VC++Files/mysqlmanager/mysqlmanager.mak
deleted file mode 100644
index b372daa52f2..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanager.mak
+++ /dev/null
@@ -1,327 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on MySqlManager.dsp
-!IF "$(CFG)" == ""
-CFG=MySqlManager - Win32 Debug
-!MESSAGE No configuration specified. Defaulting to MySqlManager - Win32 Debug.
-!ENDIF
-
-!IF "$(CFG)" != "MySqlManager - Win32 Release" && "$(CFG)" != "MySqlManager - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!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 "MySqlManager.mak" CFG="MySqlManager - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "MySqlManager - Win32 Release" (based on "Win32 (x86) Application")
-!MESSAGE "MySqlManager - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "MySqlManager - Win32 Release"
-
-OUTDIR=.\release
-INTDIR=.\release
-# Begin Custom Macros
-OutDir=.\release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "..\client_release\MySqlManager.exe" "$(OUTDIR)\MySqlManager.pch"
-
-!ELSE
-
-ALL : "mysqlclient - Win32 Release" "..\client_release\MySqlManager.exe" "$(OUTDIR)\MySqlManager.pch"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"mysqlclient - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\ChildFrm.obj"
- -@erase "$(INTDIR)\MainFrm.obj"
- -@erase "$(INTDIR)\MySqlManager.obj"
- -@erase "$(INTDIR)\MySqlManager.pch"
- -@erase "$(INTDIR)\MySqlManager.res"
- -@erase "$(INTDIR)\MySqlManagerDoc.obj"
- -@erase "$(INTDIR)\MySqlManagerView.obj"
- -@erase "$(INTDIR)\RegisterServer.obj"
- -@erase "$(INTDIR)\StdAfx.obj"
- -@erase "$(INTDIR)\ToolSql.obj"
- -@erase "$(INTDIR)\ToolSqlQuery.obj"
- -@erase "$(INTDIR)\ToolSqlResults.obj"
- -@erase "$(INTDIR)\ToolSqlStatus.obj"
- -@erase "$(INTDIR)\vc60.idb"
- -@erase "..\client_release\MySqlManager.exe"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP_PROJ=/nologo /G6 /MT /W3 /GX /O1 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
-RSC_PROJ=/l 0x409 /fo"$(INTDIR)\MySqlManager.res" /d "NDEBUG" /d "_AFXDLL"
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\MySqlManager.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=/nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)\MySqlManager.pdb" /machine:I386 /out:"../client_release/MySqlManager.exe"
-LINK32_OBJS= \
- "$(INTDIR)\ChildFrm.obj" \
- "$(INTDIR)\MainFrm.obj" \
- "$(INTDIR)\MySqlManager.obj" \
- "$(INTDIR)\MySqlManagerDoc.obj" \
- "$(INTDIR)\MySqlManagerView.obj" \
- "$(INTDIR)\RegisterServer.obj" \
- "$(INTDIR)\StdAfx.obj" \
- "$(INTDIR)\ToolSql.obj" \
- "$(INTDIR)\ToolSqlQuery.obj" \
- "$(INTDIR)\ToolSqlResults.obj" \
- "$(INTDIR)\ToolSqlStatus.obj" \
- "$(INTDIR)\MySqlManager.res" \
- "..\lib_release\mysqlclient.lib"
-
-"..\client_release\MySqlManager.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "MySqlManager - Win32 Debug"
-
-OUTDIR=.\debug
-INTDIR=.\debug
-# Begin Custom Macros
-OutDir=.\debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "..\client_debug\MySqlManager.exe" "$(OUTDIR)\MySqlManager.pch"
-
-!ELSE
-
-ALL : "mysqlclient - Win32 Debug" "..\client_debug\MySqlManager.exe" "$(OUTDIR)\MySqlManager.pch"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"mysqlclient - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\ChildFrm.obj"
- -@erase "$(INTDIR)\MainFrm.obj"
- -@erase "$(INTDIR)\MySqlManager.obj"
- -@erase "$(INTDIR)\MySqlManager.pch"
- -@erase "$(INTDIR)\MySqlManager.res"
- -@erase "$(INTDIR)\MySqlManagerDoc.obj"
- -@erase "$(INTDIR)\MySqlManagerView.obj"
- -@erase "$(INTDIR)\RegisterServer.obj"
- -@erase "$(INTDIR)\StdAfx.obj"
- -@erase "$(INTDIR)\ToolSql.obj"
- -@erase "$(INTDIR)\ToolSqlQuery.obj"
- -@erase "$(INTDIR)\ToolSqlResults.obj"
- -@erase "$(INTDIR)\ToolSqlStatus.obj"
- -@erase "$(INTDIR)\vc60.idb"
- -@erase "$(INTDIR)\vc60.pdb"
- -@erase "$(OUTDIR)\MySqlManager.pdb"
- -@erase "..\client_debug\MySqlManager.exe"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP_PROJ=/nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /I "../include" /D "_DEBUG" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
-MTL_PROJ=/nologo /D "_DEBUG" /o "NUL" /win32
-RSC_PROJ=/l 0x409 /fo"$(INTDIR)\MySqlManager.res" /d "_DEBUG"
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\MySqlManager.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)\MySqlManager.pdb" /debug /machine:I386 /out:"../client_debug/MySqlManager.exe" /pdbtype:sept /libpath:"..\lib_debug\\"
-LINK32_OBJS= \
- "$(INTDIR)\ChildFrm.obj" \
- "$(INTDIR)\MainFrm.obj" \
- "$(INTDIR)\MySqlManager.obj" \
- "$(INTDIR)\MySqlManagerDoc.obj" \
- "$(INTDIR)\MySqlManagerView.obj" \
- "$(INTDIR)\RegisterServer.obj" \
- "$(INTDIR)\StdAfx.obj" \
- "$(INTDIR)\ToolSql.obj" \
- "$(INTDIR)\ToolSqlQuery.obj" \
- "$(INTDIR)\ToolSqlResults.obj" \
- "$(INTDIR)\ToolSqlStatus.obj" \
- "$(INTDIR)\MySqlManager.res" \
- "..\lib_debug\mysqlclient.lib"
-
-"..\client_debug\MySqlManager.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-.c{$(INTDIR)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(INTDIR)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(INTDIR)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(INTDIR)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(INTDIR)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(INTDIR)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-
-!IF "$(NO_EXTERNAL_DEPS)" != "1"
-!IF EXISTS("MySqlManager.dep")
-!INCLUDE "MySqlManager.dep"
-!ELSE
-!MESSAGE Warning: cannot find "MySqlManager.dep"
-!ENDIF
-!ENDIF
-
-
-!IF "$(CFG)" == "MySqlManager - Win32 Release" || "$(CFG)" == "MySqlManager - Win32 Debug"
-SOURCE=.\ChildFrm.cpp
-
-"$(INTDIR)\ChildFrm.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\MainFrm.cpp
-
-"$(INTDIR)\MainFrm.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\MySqlManager.cpp
-
-"$(INTDIR)\MySqlManager.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\MySqlManager.rc
-
-"$(INTDIR)\MySqlManager.res" : $(SOURCE) "$(INTDIR)"
- $(RSC) $(RSC_PROJ) $(SOURCE)
-
-
-SOURCE=.\MySqlManagerDoc.cpp
-
-"$(INTDIR)\MySqlManagerDoc.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\MySqlManagerView.cpp
-
-"$(INTDIR)\MySqlManagerView.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\RegisterServer.cpp
-
-"$(INTDIR)\RegisterServer.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\StdAfx.cpp
-
-!IF "$(CFG)" == "MySqlManager - Win32 Release"
-
-CPP_SWITCHES=/nologo /G6 /MT /W3 /GX /O1 /I "../include" /D "NDEBUG" /D "DBUG_OFF" /D "_WINDOWS" /Fp"$(INTDIR)\MySqlManager.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
-
-"$(INTDIR)\StdAfx.obj" "$(INTDIR)\MySqlManager.pch" : $(SOURCE) "$(INTDIR)"
- $(CPP) @<<
- $(CPP_SWITCHES) $(SOURCE)
-<<
-
-
-!ELSEIF "$(CFG)" == "MySqlManager - Win32 Debug"
-
-CPP_SWITCHES=/nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /I "../include" /D "_DEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\MySqlManager.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
-
-"$(INTDIR)\StdAfx.obj" "$(INTDIR)\MySqlManager.pch" : $(SOURCE) "$(INTDIR)"
- $(CPP) @<<
- $(CPP_SWITCHES) $(SOURCE)
-<<
-
-
-!ENDIF
-
-SOURCE=.\ToolSql.cpp
-
-"$(INTDIR)\ToolSql.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\ToolSqlQuery.cpp
-
-"$(INTDIR)\ToolSqlQuery.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\ToolSqlResults.cpp
-
-"$(INTDIR)\ToolSqlResults.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\ToolSqlStatus.cpp
-
-"$(INTDIR)\ToolSqlStatus.obj" : $(SOURCE) "$(INTDIR)"
-
-
-!IF "$(CFG)" == "MySqlManager - Win32 Release"
-
-"mysqlclient - Win32 Release" :
- cd "\MYSQL-3.23\client"
- $(MAKE) /$(MAKEFLAGS) /F ".\mysqlclient.mak" CFG="mysqlclient - Win32 Release"
- cd "..\mysqlmanager"
-
-"mysqlclient - Win32 ReleaseCLEAN" :
- cd "\MYSQL-3.23\client"
- $(MAKE) /$(MAKEFLAGS) /F ".\mysqlclient.mak" CFG="mysqlclient - Win32 Release" RECURSE=1 CLEAN
- cd "..\mysqlmanager"
-
-!ELSEIF "$(CFG)" == "MySqlManager - Win32 Debug"
-
-"mysqlclient - Win32 Debug" :
- cd "\MYSQL-3.23\client"
- $(MAKE) /$(MAKEFLAGS) /F ".\mysqlclient.mak" CFG="mysqlclient - Win32 Debug"
- cd "..\mysqlmanager"
-
-"mysqlclient - Win32 DebugCLEAN" :
- cd "\MYSQL-3.23\client"
- $(MAKE) /$(MAKEFLAGS) /F ".\mysqlclient.mak" CFG="mysqlclient - Win32 Debug" RECURSE=1 CLEAN
- cd "..\mysqlmanager"
-
-!ENDIF
-
-
-!ENDIF
-
diff --git a/VC++Files/mysqlmanager/mysqlmanager.rc b/VC++Files/mysqlmanager/mysqlmanager.rc
deleted file mode 100644
index 1dd9caeb686..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanager.rc
+++ /dev/null
@@ -1,572 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE
-BEGIN
- "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
- "#define _AFX_NO_OLE_RESOURCES\r\n"
- "#define _AFX_NO_TRACKER_RESOURCES\r\n"
- "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
- "\r\n"
- "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
- "#ifdef _WIN32\r\n"
- "LANGUAGE 9, 1\r\n"
- "#pragma code_page(1252)\r\n"
- "#endif\r\n"
- "#include ""res\\MySqlManager.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
- "#include ""afxres.rc"" // Standard components\r\n"
- "#include ""afxprint.rc"" // printing/print preview resources\r\n"
- "#endif\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDR_MAINFRAME ICON DISCARDABLE "res\\MySqlManager.ico"
-IDR_MYSQLMTYPE ICON DISCARDABLE "res\\MySqlManagerDoc.ico"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Bitmap
-//
-
-IDR_MAINFRAME BITMAP MOVEABLE PURE "res\\Toolbar.bmp"
-IDB_BITMAP1 BITMAP DISCARDABLE "res\\bitmap3.bmp"
-IDB_QUERY_EXECU BITMAP FIXED IMPURE "res\\query_ex.bmp"
-IDB_QUERY_EXECD BITMAP FIXED IMPURE "res\\bmp00001.bmp"
-IDB_FONTU BITMAP FIXED IMPURE "res\\fontu.bmp"
-IDB_FONTD BITMAP FIXED IMPURE "res\\fontd.bmp"
-IDB_DATABASESU BITMAP FIXED IMPURE "res\\database.bmp"
-IDB_DATABASESD BITMAP FIXED IMPURE "res\\bmp00002.bmp"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Toolbar
-//
-
-IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15
-BEGIN
- BUTTON ID_FILE_NEW
- BUTTON ID_FILE_OPEN
- BUTTON ID_FILE_SAVE
- SEPARATOR
- BUTTON ID_EDIT_CUT
- BUTTON ID_EDIT_COPY
- BUTTON ID_EDIT_PASTE
- SEPARATOR
- BUTTON ID_FILE_PRINT
- BUTTON ID_APP_ABOUT
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Menu
-//
-
-IDR_MAINFRAME MENU PRELOAD DISCARDABLE
-BEGIN
- POPUP "&File"
- BEGIN
- MENUITEM "&New\tCtrl+N", ID_FILE_NEW
- MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
- MENUITEM SEPARATOR
- MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP
- MENUITEM SEPARATOR
- MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED
- MENUITEM SEPARATOR
- MENUITEM "E&xit", ID_APP_EXIT
- END
- POPUP "&View"
- BEGIN
- MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
- MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
- END
- POPUP "&Help"
- BEGIN
- MENUITEM "&About MySqlManager...", ID_APP_ABOUT
- END
-END
-
-IDR_MYSQLMTYPE MENU PRELOAD DISCARDABLE
-BEGIN
- POPUP "&File"
- BEGIN
- MENUITEM "&New\tCtrl+N", ID_FILE_NEW
- MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
- MENUITEM "&Close", ID_FILE_CLOSE
- MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
- MENUITEM "Save &As...", ID_FILE_SAVE_AS
- MENUITEM SEPARATOR
- MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT
- MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW
- MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP
- MENUITEM SEPARATOR
- MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED
- MENUITEM SEPARATOR
- MENUITEM "E&xit", ID_APP_EXIT
- END
- POPUP "&Edit"
- BEGIN
- MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO
- MENUITEM SEPARATOR
- MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
- MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
- MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
- END
- POPUP "&Tools"
- BEGIN
- MENUITEM "SQL &Query", IDM_SQL_TOOL_QUERY
- MENUITEM "Register Server", IDM_TOOLS_REGISTER_SERVER
- MENUITEM "Server Properties", IDM_TOOLS_SERVER_PROPERTIES
- END
- POPUP "&View"
- BEGIN
- MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
- MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
- END
- POPUP "&Window"
- BEGIN
- MENUITEM "&New Window", ID_WINDOW_NEW
- MENUITEM "&Cascade", ID_WINDOW_CASCADE
- MENUITEM "&Tile", ID_WINDOW_TILE_HORZ
- MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE
- END
- POPUP "&Help"
- BEGIN
- MENUITEM "&About MySqlManager...", ID_APP_ABOUT
- END
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Accelerator
-//
-
-IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE
-BEGIN
- "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
- "D", IDM_QUERY_DATABASES, VIRTKEY, ALT, NOINVERT
- "E", IDM_QUERY_EXEC, VIRTKEY, CONTROL, NOINVERT
- "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
- "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
- "P", ID_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT
- "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
- "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
- VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
- VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
- VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT
- VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT
- VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
- VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT
- "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
- "X", IDM_QUERY_EXEC, VIRTKEY, ALT, NOINVERT
- "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Dialog
-//
-
-IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 234, 72
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "About MySqlManager"
-FONT 8, "MS Sans Serif"
-BEGIN
- ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
- LTEXT "MySqlManager Version 1.0.2",IDC_STATIC,37,10,119,8,
- SS_NOPREFIX
- LTEXT "By James Pereira (jpereira@iafrica.com)",IDC_STATIC,37,
- 49,146,9
- DEFPUSHBUTTON "OK",IDOK,195,7,32,14,WS_GROUP
- LTEXT "This file is public domain and comes with NO WARRANTY of any kind",
- IDC_STATIC,38,25,136,18,SS_SUNKEN
-END
-
-IDD_TOOL_SQL DIALOGEX 0, 0, 452, 246
-STYLE DS_3DLOOK | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION |
- WS_SYSMENU | WS_THICKFRAME
-EXSTYLE WS_EX_CLIENTEDGE
-CAPTION "mySQL Query Tool"
-FONT 8, "MS Sans Serif", 0, 0, 0x1
-BEGIN
- PUSHBUTTON "OK",IDOK,369,10,12,14,NOT WS_VISIBLE
- DEFPUSHBUTTON "Close",IDCANCEL,391,10,50,14
- CONTROL "Tab1",IDC_TAB1,"SysTabControl32",0x0,11,26,434,213
- CONTROL "IDB_QUERY_EXEC",IDC_QUERY_PB,"Button",BS_OWNERDRAW |
- WS_TABSTOP,106,10,12,14
- CONTROL "IDB_FONT",IDC_FONT_PB,"Button",BS_OWNERDRAW |
- WS_TABSTOP,123,10,12,14
- COMBOBOX IDC_SERVER_CB,12,9,85,128,CBS_DROPDOWN | CBS_SORT |
- WS_VSCROLL | WS_TABSTOP
- CONTROL "IDB_DATABASES",IDC_DATABASES_PB,"Button",BS_OWNERDRAW |
- WS_TABSTOP,142,10,12,14
- DEFPUSHBUTTON "&Start",IDC_START_PB,315,10,23,14
- DEFPUSHBUTTON "S&top",IDC_STOP_PB,343,10,23,14
- EDITTEXT IDC_TIMER_SECS,287,10,22,14,ES_AUTOHSCROLL
- LTEXT "Interval (s)",IDC_STATIC,249,11,34,8
- CONTROL "Clear",IDC_CLEAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
- 215,11,29,10
-END
-
-IDD_TOOL_SQL_QUERY DIALOG DISCARDABLE 0, 0, 452, 247
-STYLE WS_CHILD | WS_BORDER
-FONT 8, "MS Sans Serif"
-BEGIN
- EDITTEXT IDC_EDIT,11,11,434,229,ES_MULTILINE | ES_AUTOVSCROLL |
- ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
-END
-
-IDD_TOOL_SQL_RESULTS DIALOG DISCARDABLE 0, 0, 452, 247
-STYLE WS_CHILD | WS_BORDER
-FONT 8, "MS Sans Serif"
-BEGIN
- EDITTEXT IDC_EDIT,11,11,434,229,ES_MULTILINE | ES_AUTOVSCROLL |
- ES_AUTOHSCROLL | WS_VSCROLL
-END
-
-IDD_REGISTER_SERVER DIALOG FIXED IMPURE 0, 0, 281, 199
-STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Register Server"
-FONT 8, "MS Sans Serif"
-BEGIN
- GROUPBOX "",-1,5,0,270,195
- LTEXT "&Server:",-1,12,14,25,8
- COMBOBOX ID_SERVER_CB,46,12,159,60,CBS_DROPDOWN | CBS_AUTOHSCROLL |
- CBS_SORT | WS_VSCROLL | WS_TABSTOP
- LTEXT "&Host",-1,12,33,25,8
- COMBOBOX ID_HOST_CB,46,31,159,60,CBS_DROPDOWN | CBS_AUTOHSCROLL |
- CBS_SORT | WS_VSCROLL | WS_TABSTOP
- LTEXT "&Port",-1,12,53,25,8
- COMBOBOX ID_PORT_CB,46,50,159,60,CBS_DROPDOWN | CBS_AUTOHSCROLL |
- CBS_SORT | WS_VSCROLL | WS_TABSTOP
- GROUPBOX "Login Information",-1,12,82,194,76
- CONTROL "Use S&tandard Security",ID_USE_STANDARD_CK,"Button",
- BS_AUTORADIOBUTTON | WS_GROUP,19,107,94,11
- CONTROL "Use Tr&usted Connection",ID_USE_TRUSTED_CK,"Button",
- BS_AUTORADIOBUTTON,19,94,99,11
- LTEXT "&Login ID:",1060,37,124,35,8
- EDITTEXT ID_USER,77,122,120,12,ES_AUTOHSCROLL | WS_GROUP
- LTEXT "&Password:",1061,37,140,35,8
- EDITTEXT ID_PASSWORD,77,138,120,12,ES_PASSWORD | ES_AUTOHSCROLL
- LTEXT "S&erver Group:",-1,12,164,24,25
- CONTROL "&Display Server Status in Server Manager",
- ID_DISPLAY_SERVER_STATUS_CK,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,44,168,152,10
- DEFPUSHBUTTON "&Register",IDOK,214,11,53,14
- PUSHBUTTON "Re&move",ID_REMOVE_PB,214,27,53,14
- PUSHBUTTON "&Close",IDCANCEL,214,43,53,14
- PUSHBUTTON "&Help",ID_HELP,214,59,53,14
- PUSHBUTTON "Ser&vers...",ID_SERVERS_PB,214,92,53,14
- PUSHBUTTON "&Groups...",ID_GROUPS_PB,214,108,53,14
-END
-
-IDD_TOOL_SQL_STATUS DIALOG DISCARDABLE 0, 0, 452, 247
-STYLE WS_CHILD | WS_BORDER
-FONT 8, "MS Sans Serif"
-BEGIN
- EDITTEXT IDC_EDIT,11,11,434,229,ES_MULTILINE | ES_AUTOVSCROLL |
- ES_AUTOHSCROLL | WS_VSCROLL
-END
-
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,2
- PRODUCTVERSION 1,0,0,2
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "CompanyName", "\0"
- VALUE "FileDescription", "MySqlManager MFC Application\0"
- VALUE "FileVersion", "1, 0, 0, 2\0"
- VALUE "InternalName", "MySqlManager\0"
- VALUE "LegalCopyright", "Copyright (C) 1998\0"
- VALUE "OriginalFilename", "MySqlManager.EXE\0"
- VALUE "ProductName", "MySqlManager Application\0"
- VALUE "ProductVersion", "1, 0, 0, 2\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // !_MAC
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// DESIGNINFO
-//
-
-#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO DISCARDABLE
-BEGIN
- IDD_ABOUTBOX, DIALOG
- BEGIN
- LEFTMARGIN, 6
- RIGHTMARGIN, 227
- TOPMARGIN, 7
- BOTTOMMARGIN, 65
- END
-
- IDD_TOOL_SQL, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 445
- TOPMARGIN, 7
- BOTTOMMARGIN, 239
- END
-
- IDD_TOOL_SQL_QUERY, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 445
- TOPMARGIN, 7
- BOTTOMMARGIN, 240
- END
-
- IDD_TOOL_SQL_RESULTS, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 445
- TOPMARGIN, 7
- BOTTOMMARGIN, 240
- END
-
- IDD_TOOL_SQL_STATUS, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 445
- TOPMARGIN, 7
- BOTTOMMARGIN, 240
- END
-END
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// String Table
-//
-
-STRINGTABLE PRELOAD DISCARDABLE
-BEGIN
- IDR_MAINFRAME "MySqlManager"
- IDR_MYSQLMTYPE "\nMySqlM\nMySqlM\n\n\nMySqlManager.Document\nMySqlM Document"
-END
-
-STRINGTABLE PRELOAD DISCARDABLE
-BEGIN
- AFX_IDS_APP_TITLE "MySqlManager"
- AFX_IDS_IDLEMESSAGE "Ready"
- IDS_QUERY_DATABASES "Query Database(s)"
- IDS_REFRESH "Refresh"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- ID_INDICATOR_EXT "EXT"
- ID_INDICATOR_CAPS "CAP"
- ID_INDICATOR_NUM "NUM"
- ID_INDICATOR_SCRL "SCRL"
- ID_INDICATOR_OVR "OVR"
- ID_INDICATOR_REC "REC"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- ID_FILE_NEW "Create a new document\nNew"
- ID_FILE_OPEN "Open an existing document\nOpen"
- ID_FILE_CLOSE "Close the active document\nClose"
- ID_FILE_SAVE "Save the active document\nSave"
- ID_FILE_SAVE_AS "Save the active document with a new name\nSave As"
- ID_FILE_PAGE_SETUP "Change the printing options\nPage Setup"
- ID_FILE_PRINT_SETUP "Change the printer and printing options\nPrint Setup"
- ID_FILE_PRINT "Print the active document\nPrint"
- ID_FILE_PRINT_PREVIEW "Display full pages\nPrint Preview"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- ID_APP_ABOUT "Display program information, version number and copyright\nAbout"
- ID_APP_EXIT "Quit the application; prompts to save documents\nExit"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- ID_FILE_MRU_FILE1 "Open this document"
- ID_FILE_MRU_FILE2 "Open this document"
- ID_FILE_MRU_FILE3 "Open this document"
- ID_FILE_MRU_FILE4 "Open this document"
- ID_FILE_MRU_FILE5 "Open this document"
- ID_FILE_MRU_FILE6 "Open this document"
- ID_FILE_MRU_FILE7 "Open this document"
- ID_FILE_MRU_FILE8 "Open this document"
- ID_FILE_MRU_FILE9 "Open this document"
- ID_FILE_MRU_FILE10 "Open this document"
- ID_FILE_MRU_FILE11 "Open this document"
- ID_FILE_MRU_FILE12 "Open this document"
- ID_FILE_MRU_FILE13 "Open this document"
- ID_FILE_MRU_FILE14 "Open this document"
- ID_FILE_MRU_FILE15 "Open this document"
- ID_FILE_MRU_FILE16 "Open this document"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- ID_NEXT_PANE "Switch to the next window pane\nNext Pane"
- ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- ID_WINDOW_NEW "Open another window for the active document\nNew Window"
- ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window\nArrange Icons"
- ID_WINDOW_CASCADE "Arrange windows so they overlap\nCascade Windows"
- ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles\nTile Windows"
- ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles\nTile Windows"
- ID_WINDOW_SPLIT "Split the active window into panes\nSplit"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- ID_EDIT_CLEAR "Erase the selection\nErase"
- ID_EDIT_CLEAR_ALL "Erase everything\nErase All"
- ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy"
- ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut"
- ID_EDIT_FIND "Find the specified text\nFind"
- ID_EDIT_PASTE "Insert Clipboard contents\nPaste"
- ID_EDIT_REPEAT "Repeat the last action\nRepeat"
- ID_EDIT_REPLACE "Replace specific text with different text\nReplace"
- ID_EDIT_SELECT_ALL "Select the entire document\nSelect All"
- ID_EDIT_UNDO "Undo the last action\nUndo"
- ID_EDIT_REDO "Redo the previously undone action\nRedo"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar"
- ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- AFX_IDS_SCSIZE "Change the window size"
- AFX_IDS_SCMOVE "Change the window position"
- AFX_IDS_SCMINIMIZE "Reduce the window to an icon"
- AFX_IDS_SCMAXIMIZE "Enlarge the window to full size"
- AFX_IDS_SCNEXTWINDOW "Switch to the next document window"
- AFX_IDS_SCPREVWINDOW "Switch to the previous document window"
- AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- AFX_IDS_SCRESTORE "Restore the window to normal size"
- AFX_IDS_SCTASKLIST "Activate Task List"
- AFX_IDS_MDICHILD "Activate this window"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- AFX_IDS_PREVIEW_CLOSE "Close print preview mode\nCancel Preview"
-END
-
-STRINGTABLE DISCARDABLE
-BEGIN
- IDC_QUERY_PB "Execute Query"
- IDS_QUERY_EXEC "Execute Query"
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-#define _AFX_NO_SPLITTER_RESOURCES
-#define _AFX_NO_OLE_RESOURCES
-#define _AFX_NO_TRACKER_RESOURCES
-#define _AFX_NO_PROPERTY_RESOURCES
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE 9, 1
-#pragma code_page(1252)
-#endif
-#include "res\MySqlManager.rc2" // non-Microsoft Visual C++ edited resources
-#include "afxres.rc" // Standard components
-#include "afxprint.rc" // printing/print preview resources
-#endif
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
diff --git a/VC++Files/mysqlmanager/mysqlmanagerdoc.cpp b/VC++Files/mysqlmanager/mysqlmanagerdoc.cpp
deleted file mode 100644
index c89ce693a60..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanagerdoc.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-// MySqlManagerDoc.cpp : implementation of the CMySqlManagerDoc class
-//
-
-#include "stdafx.h"
-#include "MySqlManager.h"
-
-#include "MySqlManagerDoc.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerDoc
-
-IMPLEMENT_DYNCREATE(CMySqlManagerDoc, CDocument)
-
-BEGIN_MESSAGE_MAP(CMySqlManagerDoc, CDocument)
- //{{AFX_MSG_MAP(CMySqlManagerDoc)
- // NOTE - the ClassWizard will add and remove mapping macros here.
- // DO NOT EDIT what you see in these blocks of generated code!
- //}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerDoc construction/destruction
-
-CMySqlManagerDoc::CMySqlManagerDoc()
-{
- // TODO: add one-time construction code here
-
-}
-
-CMySqlManagerDoc::~CMySqlManagerDoc()
-{
-}
-
-BOOL CMySqlManagerDoc::OnNewDocument()
-{
- if (!CDocument::OnNewDocument())
- return FALSE;
-
- // TODO: add reinitialization code here
- // (SDI documents will reuse this document)
-
- return TRUE;
-}
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerDoc serialization
-
-void CMySqlManagerDoc::Serialize(CArchive& ar)
-{
- if (ar.IsStoring())
- {
- // TODO: add storing code here
- }
- else
- {
- // TODO: add loading code here
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerDoc diagnostics
-
-#ifdef _DEBUG
-void CMySqlManagerDoc::AssertValid() const
-{
- CDocument::AssertValid();
-}
-
-void CMySqlManagerDoc::Dump(CDumpContext& dc) const
-{
- CDocument::Dump(dc);
-}
-#endif //_DEBUG
-
-/////////////////////////////////////////////////////////////////////////////
-// CMySqlManagerDoc commands
diff --git a/VC++Files/mysqlmanager/mysqlmanagerdoc.h b/VC++Files/mysqlmanager/mysqlmanagerdoc.h
deleted file mode 100644
index f4a4d35cfd5..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanagerdoc.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// MySqlManagerDoc.h : interface of the CMySqlManagerDoc class
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_MYSQLMANAGERDOC_H__826CB2F2_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_MYSQLMANAGERDOC_H__826CB2F2_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-
-class CMySqlManagerDoc : public CDocument
-{
-protected: // create from serialization only
- CMySqlManagerDoc();
- DECLARE_DYNCREATE(CMySqlManagerDoc)
-
-// Attributes
-public:
-
-// Operations
-public:
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CMySqlManagerDoc)
- public:
- virtual BOOL OnNewDocument();
- virtual void Serialize(CArchive& ar);
- //}}AFX_VIRTUAL
-
-// Implementation
-public:
- virtual ~CMySqlManagerDoc();
-#ifdef _DEBUG
- virtual void AssertValid() const;
- virtual void Dump(CDumpContext& dc) const;
-#endif
-
-protected:
-
-// Generated message map functions
-protected:
- //{{AFX_MSG(CMySqlManagerDoc)
- // NOTE - the ClassWizard will add and remove member functions here.
- // DO NOT EDIT what you see in these blocks of generated code !
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_MYSQLMANAGERDOC_H__826CB2F2_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/mysqlmanagerview.cpp b/VC++Files/mysqlmanager/mysqlmanagerview.cpp
deleted file mode 100644
index 1d4756e7d7a..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanagerview.cpp
+++ /dev/null
@@ -1,849 +0,0 @@
-// MySqlManagerView.cpp : implementation of the CMySqlManagerView class
-//
-
-#include "stdafx.h"
-#include "MySqlManager.h"
-#include "MySqlManagerDoc.h"
-#include "MySqlManagerView.h"
-#include "mainfrm.h"
-#include "ToolSql.h"
-#include "RegisterServer.h"
-
-class XStatus
-{
-public:
- XStatus ( LPCSTR fmt, ... )
- {
- char buf [2048];
- va_list args;
- va_start(args, fmt);
- int ret = vsprintf(buf, fmt, args);
- MainFrame->StatusMsg ( "%s", buf );
- va_end(args);
- }
- ~XStatus()
- {
- MainFrame->StatusMsg ( " ");
- }
-private:
- XStatus();
-};
-
-#ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-
-IMPLEMENT_DYNCREATE(CMySqlManagerView, CTreeView)
-
-BEGIN_MESSAGE_MAP(CMySqlManagerView, CTreeView)
-//{{AFX_MSG_MAP(CMySqlManagerView)
-ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
-ON_COMMAND(IDM_SQL_TOOL_QUERY, OnSqlToolQuery)
-ON_COMMAND(IDM_REFRESH, OnRefresh)
-ON_COMMAND(IDM_TOOLS_SERVER_PROPERTIES,OnServerProperties)
-ON_COMMAND(IDM_TOOLS_REGISTER_SERVER, OnRegisterServer)
-ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
-//}}AFX_MSG_MAP
-// Standard printing commands
-ON_COMMAND(ID_FILE_PRINT, CTreeView::OnFilePrint)
-ON_COMMAND(ID_FILE_PRINT_DIRECT, CTreeView::OnFilePrint)
-ON_COMMAND(ID_FILE_PRINT_PREVIEW, CTreeView::OnFilePrintPreview)
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-
-CMySqlManagerView::CMySqlManagerView()
-: m_pTree(0)
-, m_pImages(0)
-, m_pbmBmp(0)
-, m_pTool(0)
-{
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-CMySqlManagerView::~CMySqlManagerView()
-{
- if ( m_pbmBmp ) delete m_pbmBmp;
- if ( m_pImages ) delete m_pImages;
- if ( m_pTool )
- {
- m_pTool->DestroyWindow();
- delete m_pTool;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-BOOL CMySqlManagerView::PreCreateWindow(CREATESTRUCT& cs)
-{
- return CTreeView::PreCreateWindow(cs);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnDraw(CDC* pDC)
-{
- CMySqlManagerDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-BOOL CMySqlManagerView::OnPreparePrinting(CPrintInfo* pInfo)
-{
- return DoPreparePrinting(pInfo);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
-{
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
-{
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-#ifdef _DEBUG
-void CMySqlManagerView::AssertValid() const
-{
- CTreeView::AssertValid();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::Dump(CDumpContext& dc) const
-{
- CTreeView::Dump(dc);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-CMySqlManagerDoc* CMySqlManagerView::GetDocument() // non-debug version is inline
-{
- ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMySqlManagerDoc)));
- return (CMySqlManagerDoc*)m_pDocument;
-}
-#endif //_DEBUG
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnInitialUpdate()
-{
-
- CTreeView::OnInitialUpdate();
-
- m_pTree = & GetTreeCtrl();
- m_pImages = new CImageList;
- m_pImages->Create( 16, 16, FALSE, 0, 10 );
- m_pbmBmp = new CBitmap;
- m_pbmBmp->LoadBitmap( IDB_BITMAP1 );
- m_pImages->Add( m_pbmBmp, (COLORREF)0 );
- m_pTree->SetImageList( m_pImages, TVSIL_NORMAL );
-
- HTREEITEM h = AddResource ( TVI_ROOT, new CResourceServer ( "MySQL", "localhost", "root", "" ) );
-// AddResource ( h, new CResourceProcesslist () );
- h = AddResource ( TVI_ROOT, new CResourceServer ( "Test", "localhost", "test", "" ) );
-// AddResource ( h, new CResourceProcesslist () );
-
- m_pTree->ModifyStyle(0, TVS_HASLINES|TVS_HASBUTTONS);
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-HTREEITEM CMySqlManagerView::AddResource ( HTREEITEM hParent, CResource* pRes, HTREEITEM hLastItem )
-{
-
- TV_INSERTSTRUCT ItemStruct;
- memset( &ItemStruct, 0, sizeof(ItemStruct) );
- ItemStruct.hParent = hParent;
- ItemStruct.hInsertAfter = hLastItem;
- ItemStruct.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_IMAGE;
- ItemStruct.item.hItem = 0;
- ItemStruct.item.state = 0;
- ItemStruct.item.stateMask = 0;
- ItemStruct.item.pszText = (LPSTR) pRes->GetDisplayName();
- ItemStruct.item.cchTextMax = (int) strlen( ItemStruct.item.pszText );
- ItemStruct.item.iImage = 2;
- ItemStruct.item.iSelectedImage = 3;
- ItemStruct.item.cChildren = 0;
- ItemStruct.item.lParam = (long) pRes;
- hLastItem = m_pTree->InsertItem( &ItemStruct );
- return hLastItem;
-}
-
-//int InsertNetResources( LPNETRESOURCE lpNetResource, CTreeCtrl *pTreeCtrl, HTREEITEM hParent, int *pnCount )
-//{
-//
-// DWORD Erc;
-// NETRESOURCE *pNetRes;
-// HANDLE hEnum;
-//
-// if( !pTreeCtrl ) return -1;
-// if( pnCount ) *pnCount = 0;
-// Erc = WNetOpenEnum(
-// RESOURCE_GLOBALNET,//DWORD dwScope, // scope of enumeration
-// RESOURCETYPE_ANY,//DWORD dwType, // resource types to list
-// 0,//DWORD dwUsage, // resource usage to list
-// lpNetResource,//LPNETRESOURCE lpNetResource, // pointer to resource structure
-// &hEnum//LPHANDLE lphEnum // pointer to enumeration handle buffer
-// );
-// if( Erc )
-// {
-// ShowError( Erc );
-// return Erc;
-// }
-//
-//
-// DWORD dwBufferSize = 1024;
-// pNetRes = (NETRESOURCE *)malloc( dwBufferSize );
-//
-// while( TRUE )
-// {
-// DWORD dwCount = 0xFFFFFFFF;
-// Erc = WNetEnumResource(
-// hEnum,//HANDLE hEnum, // handle to enumeration
-// &dwCount,//LPDWORD lpcCount, // pointer to entries to list
-// pNetRes,//LPVOID lpBuffer, // pointer to buffer for results
-// &dwBufferSize//LPDWORD lpBufferSize // pointer to buffer size variable
-// );
-// if( Erc == ERROR_NO_MORE_ITEMS ) return 0;
-// if( Erc )
-// {
-// free( pNetRes );
-// pNetRes = (NETRESOURCE *)malloc( dwBufferSize );
-// Erc = WNetEnumResource(
-// hEnum,//HANDLE hEnum, // handle to enumeration
-// &dwCount,//LPDWORD lpcCount, // pointer to entries to list
-// pNetRes,//LPVOID lpBuffer, // pointer to buffer for results
-// &dwBufferSize//LPDWORD lpBufferSize // pointer to buffer size variable
-// );
-// }
-// if( Erc ){ ShowError( Erc ); return Erc; }
-//
-// TV_INSERTSTRUCT ItemStruct;
-// HTREEITEM hLastItem = TVI_FIRST;
-// DWORD i;
-//
-// if( pnCount ) *pnCount += dwCount;
-// for( i=0; i<dwCount; i++ )
-// {
-// memset( &ItemStruct, 0, sizeof(ItemStruct) );
-// ItemStruct.hParent = hParent;
-// ItemStruct.hInsertAfter = hLastItem;
-// ItemStruct.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_IMAGE;
-// ItemStruct.item.hItem = 0;
-// ItemStruct.item.state = 0;
-// ItemStruct.item.stateMask = 0;
-// ItemStruct.item.pszText = pNetRes[i].lpRemoteName;
-// ItemStruct.item.cchTextMax = strlen( ItemStruct.item.pszText );
-// ItemStruct.item.iImage = 2;
-// ItemStruct.item.iSelectedImage = 3;
-// ItemStruct.item.cChildren = 0;
-// ItemStruct.item.lParam = (long) (new CNetResource( &pNetRes[i] ));
-//
-// hLastItem = pTreeCtrl->InsertItem( &ItemStruct );
-// }
-// }//end while()
-//
-// WNetCloseEnum( hEnum );
-// free( pNetRes );
-// return Erc;
-//}
-
-/////////////////////////////////////////////////////////////////////////////
-
-static void print_top(MYSQL_RES *result)
-{
- uint length;
- MYSQL_FIELD *field;
- mysql_field_seek(result,0);
- while ((field = mysql_fetch_field(result)))
- {
- if ((length= (uint) strlen(field->name)) > field->max_length)
- field->max_length=length;
- else
- length=field->max_length;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-static void print_header(MYSQL_RES *result,CStringArray& rg)
-{
- MYSQL_FIELD *field;
- print_top(result);
- mysql_field_seek(result,0);
- while ((field = mysql_fetch_field(result)))
- {
-// printf(" %-*s|",field->max_length+1,field->name);
- rg.Add(field->name);
- }
- print_top(result);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-static void print_row(MYSQL_RES *result,MYSQL_ROW row,CStringArray& rg)
-{
- uint i,length;
- MYSQL_FIELD *field;
- mysql_field_seek(result,0);
- for (i=0 ; i < mysql_num_fields(result); i++)
- {
- field = mysql_fetch_field(result);
- length=field->max_length;
- rg.Add(row[i] ? (char*) row[i] : "");
-// printf(" %-*s|",length+1,row[i] ? (char*) row[i] : "");
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::ProcessResultSet ( HTREEITEM hItem, LPVOID r, CResource* pResource )
-{
-
- MYSQL_RES* result = (MYSQL_RES *) r;
- MYSQL_ROW row;
-
- switch (pResource->GetType())
- {
- case CResource::eProcesslist:
- {
- CResourceProcesslist* p = (CResourceProcesslist*) pResource;
- CResourceProcesslistItem* pi = new CResourceProcesslistItem ();
- CString strText;
- print_header(result,p->m_rgFields);
- for (int i = 0; i<p->m_rgFields.GetSize(); i++ )
- {
- strText += p->m_rgFields[i];
- strText += " ";
- }
- pi->m_strName = strText;
- AddResource ( hItem, pi );
- for (int index=0;(row=mysql_fetch_row(result));index++)
- {
- pi = new CResourceProcesslistItem ();
- print_row(result,row,pi->m_rgFields);
- strText.Empty();
- for (int i = 0; i<pi->m_rgFields.GetSize(); i++ )
- {
- strText += pi->m_rgFields[i];
- strText += " ";
- }
- pi->m_strName = strText;
- AddResource ( hItem, pi );
- }
- print_top(result);
- break;
- }
- case CResource::eServer:
- {
- CResourceServer* p = (CResourceServer*) pResource;
- CResourceDatabase* pi = new CResourceDatabase ();
- CString strText;
- /* print_header(result,p->m_rgFields); */
- for (int i = 0; i<p->m_rgFields.GetSize(); i++ )
- {
- strText += p->m_rgFields[i];
- strText += " ";
- }
- pi->m_strName = strText;
- /* AddResource ( hItem, pi ); */
- for (int index=0;(row=mysql_fetch_row(result));index++)
- {
- pi = new CResourceDatabase ();
- print_row(result,row,pi->m_rgFields);
- strText.Empty();
- for (int i = 0; i<pi->m_rgFields.GetSize(); i++ )
- {
- strText += pi->m_rgFields[i];
- strText += " ";
- }
- pi->m_strName = strText;
- AddResource ( hItem, pi );
- }
- print_top(result);
- break;
- }
- case CResource::eDatabase:
- {
- CResourceDatabase* p = (CResourceDatabase*) pResource;
- CResourceTable* pi = new CResourceTable ();
- CString strText;
- /* print_header(result,p->m_rgFields); */
- for (int i = 0; i<p->m_rgFields.GetSize(); i++ )
- {
- strText += p->m_rgFields[i];
- strText += " ";
- }
- pi->m_strName = strText;
- /* AddResource ( hItem, pi ); */
- for (int index=0;(row=mysql_fetch_row(result));index++)
- {
- pi = new CResourceTable ();
- print_row(result,row,pi->m_rgFields);
- strText.Empty();
- for (int i = 0; i<pi->m_rgFields.GetSize(); i++ )
- {
- strText += pi->m_rgFields[i];
- strText += " ";
- }
- pi->m_strName = strText;
- AddResource ( hItem, pi );
- }
- print_top(result);
- break;
- }
- case CResource::eTable:
- {
- CResourceTable* p = (CResourceTable*) pResource;
- CResourceField* pi = new CResourceField ();
- CString strText;
- /* print_header(result,p->m_rgFields); */
- for (int i = 0; i<p->m_rgFields.GetSize(); i++ )
- {
- strText += p->m_rgFields[i];
- strText += " ";
- }
- pi->m_strName = strText;
- /* AddResource ( hItem, pi ); */
- for (int index=0;(row=mysql_fetch_row(result));index++)
- {
- pi = new CResourceField ();
- print_row(result,row,pi->m_rgFields);
- strText.Empty();
- for (int i = 0; i<pi->m_rgFields.GetSize(); i++ )
- {
- strText += pi->m_rgFields[i];
- strText += " ";
- }
- pi->m_strName = strText;
- AddResource ( hItem, pi );
- }
- print_top(result);
- break;
- }
- }
-
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-CResource* CMySqlManagerView::GetSelectedResource(HTREEITEM* phItemRet)
-{
- CResource* pResource = NULL;
- HTREEITEM hItem = m_pTree->GetSelectedItem();
- if ( hItem )
- {
- TV_ITEM item;
- memset( &item, 0, sizeof(TV_ITEM) );
- item.hItem = hItem;
- item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN | TVIF_PARAM ;
- m_pTree->GetItem( &item );
- if ( item.lParam )
- {
- pResource = (CResource*) item.lParam;
- }
- }
- if (phItemRet)
- {
- *phItemRet = hItem;
- }
- return pResource;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-CResourceServer* CMySqlManagerView::GetServerResource(HTREEITEM hItem)
-{
-
- TV_ITEM item;
-
- memset( &item, 0, sizeof(TV_ITEM) );
- item.hItem = hItem;
- item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN | TVIF_PARAM ;
- m_pTree->GetItem( &item );
- if ( !item.lParam ) return NULL;
-
- CResource* pResource = (CResource*) item.lParam;
-
- switch (pResource->GetType())
- {
- case CResource::eServer:
- {
- return (CResourceServer*) pResource;
- }
- case CResource::eDatabase:
- {
- HTREEITEM hParent = m_pTree->GetParentItem(hItem);
- memset( &item, 0, sizeof(TV_ITEM) );
- item.hItem = hParent;
- item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN | TVIF_PARAM ;
- m_pTree->GetItem( &item );
- if ( !item.lParam ) return NULL;
- return (CResourceServer*) item.lParam;
- }
- case CResource::eTable:
- {
- HTREEITEM hParent = m_pTree->GetParentItem(m_pTree->GetParentItem(hItem));
- memset( &item, 0, sizeof(TV_ITEM) );
- item.hItem = hParent;
- item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN | TVIF_PARAM ;
- m_pTree->GetItem( &item );
- if ( !item.lParam ) return NULL;
- return (CResourceServer*) item.lParam;
- }
- }
-
- return NULL;
-
-}
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
-{
- HTREEITEM hItem;
- hItem = m_pTree->GetSelectedItem();
- *pResult = 0;
- if ( !hItem ) return;
-
- TV_ITEM item;
- memset( &item, 0, sizeof(TV_ITEM) );
- item.hItem = hItem;
- item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN | TVIF_PARAM ;
- m_pTree->GetItem( &item );
-
- if ( ! item.lParam ) return;
-
- if ( item.cChildren ) return; //if has got children expand only
-
- CWaitCursor x;
-
- CResource* pResource = (CResource*) item.lParam;
-
- MYSQL mysql;
- MYSQL_RES *result;
-
- switch (pResource->GetType())
- {
- case CResource::eProcesslist:
- {
- XStatus x ( "Connecting to server %s on host %s..."
- , (LPCTSTR) pResource->GetDisplayName()
- , (LPCTSTR) pResource->GetHostName()
- );
- mysql_init(&mysql);
- if (!mysql_real_connect(&mysql,pResource->GetHostName(), pResource->GetUserName(),pResource->GetPassword(),0,pResource->GetPortNumber(), NullS,0))
- {
- PostMessage(WM_COMMAND,IDM_TOOLS_SERVER_PROPERTIES);
- return;
- }
- if (!(result=mysql_list_processes(&mysql)))
- {
- return;
- }
- ProcessResultSet ( hItem, result, pResource );
- mysql_free_result(result);
- mysql_close(&mysql);
- break;
- }
- case CResource::eServer:
- {
- MainFrame->StatusMsg ( "Connecting to server %s on host %s..."
- , (LPCTSTR) pResource->GetDisplayName()
- , (LPCTSTR) pResource->GetHostName()
- );
- mysql_init(&mysql);
- if (!mysql_real_connect(&mysql,pResource->GetHostName(), pResource->GetUserName(),pResource->GetPassword(),0,pResource->GetPortNumber(), NullS,0))
- {
- PostMessage(WM_COMMAND,IDM_TOOLS_SERVER_PROPERTIES);
- MainFrame->StatusMsg ( "Error: Connecting to server %s... (%s)"
- , (LPCTSTR) pResource->GetDisplayName()
- , mysql_error(&mysql)
- );
- return;
- }
- if (!(result=mysql_list_dbs(&mysql,0)))
- {
- }
- ProcessResultSet ( hItem, result, pResource );
- mysql_free_result(result);
- mysql_close(&mysql);
- MainFrame->StatusMsg ( " " );
- break;
- }
- case CResource::eDatabase:
- {
- CResourceServer* pServer = GetServerResource(hItem);
- if (!pServer) return;
- MainFrame->StatusMsg ( "Connecting to server %s on host %s..."
- , (LPCTSTR) pServer->GetDisplayName()
- , (LPCTSTR) pServer->GetHostName()
- );
- mysql_init(&mysql);
- if (!mysql_real_connect(&mysql,pServer->GetHostName(), pServer->GetUserName(),pServer->GetPassword(),0,pServer->GetPortNumber(), NullS,0))
- {
- PostMessage(WM_COMMAND,IDM_TOOLS_SERVER_PROPERTIES);
- MainFrame->StatusMsg ( "Error: Connecting to server %s... (%s)"
- , (LPCTSTR) pServer->GetDisplayName()
- , mysql_error(&mysql)
- );
- return;
- }
- CResourceDatabase* pRes = (CResourceDatabase*) pResource;
- CString strDB = pResource->GetDisplayName();
- strDB.TrimRight();
- if (mysql_select_db(&mysql,strDB))
- {
- MainFrame->StatusMsg ( "Error: Selecting database %s... (%s)"
- , (LPCTSTR) strDB
- , mysql_error(&mysql)
- );
- return;
- }
- if (!(result=mysql_list_tables(&mysql,0)))
- {
- }
- ProcessResultSet ( hItem, result, pRes );
- mysql_free_result(result);
- mysql_close(&mysql);
- MainFrame->StatusMsg ( " " );
- break;
- }
- case CResource::eTable:
- {
- CResourceServer* pServer = GetServerResource(hItem);
- if (!pServer) return;
- MainFrame->StatusMsg ( "Connecting to server %s on host %s..."
- , (LPCTSTR) pServer->GetDisplayName()
- , (LPCTSTR) pServer->GetHostName()
- );
- mysql_init(&mysql);
- if (!mysql_real_connect(&mysql,pServer->GetHostName(), pServer->GetUserName(),pServer->GetPassword(),0,pServer->GetPortNumber(), NullS,0))
- {
- PostMessage(WM_COMMAND,IDM_TOOLS_SERVER_PROPERTIES);
- MainFrame->StatusMsg ( "Error: Connecting to server %s... (%s)"
- , (LPCTSTR) pServer->GetDisplayName()
- , mysql_error(&mysql)
- );
- return;
- }
- HTREEITEM hParent = m_pTree->GetParentItem(hItem);
- memset( &item, 0, sizeof(TV_ITEM) );
- item.hItem = hParent;
- item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN | TVIF_PARAM ;
- m_pTree->GetItem( &item );
- if ( item.lParam )
- {
- CResourceDatabase* pResDatabase = (CResourceDatabase*) item.lParam;
- CResourceTable* pRes = (CResourceTable*) pResource;
- CString strDB = pResDatabase->GetDisplayName();
- CString strTable = pResource->GetDisplayName();
- strDB.TrimRight();
- strTable.TrimRight();
- if (mysql_select_db(&mysql,strDB))
- {
- return;
- }
- CString str; str.Format("show fields from %s",(LPCTSTR)strTable);
- if ( mysql_query(&mysql,str)==0 )
- {
- MYSQL_RES *result;
- if ((result=mysql_store_result(&mysql)))
- {
- ProcessResultSet ( hItem, result, pRes );
- mysql_free_result(result);
- }
- }
- }
- mysql_close(&mysql);
- break;
- }
- }
-
-// InsertNetResources( (LPNETRESOURCE)pTvItem->lParam,
-// &m_TreeCtrl,
-// hItem,
-// &pTvItem->cChildren );
-// pTvItem->mask = TVIF_CHILDREN;
-// m_TreeCtrl.SetItem( pTvItem );
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnRefresh()
-{
- HTREEITEM hItem = NULL;
- CResource* pResource = GetSelectedResource(&hItem);
- if (pResource&&hItem)
- {
- switch (pResource->GetType())
- {
- case CResource::eTable:
- {
-
- TV_ITEM item;
- MYSQL mysql;
-// MYSQL_RES *result;
-
- HTREEITEM hParent = m_pTree->GetParentItem(hItem);
-
- HTREEITEM hChild = m_pTree->GetChildItem(hItem);
- while (hChild)
- {
- HTREEITEM h = m_pTree->GetNextSiblingItem(hChild);
- BOOL b = m_pTree->DeleteItem(hChild);
- hChild = h;
- }
- mysql_init(&mysql);
- if (!mysql_real_connect(&mysql,pResource->GetHostName(), pResource->GetUserName(),pResource->GetPassword(),0,pResource->GetPortNumber(), NullS,0))
- {
- return;
- }
- memset( &item, 0, sizeof(TV_ITEM) );
- item.hItem = hParent;
- item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN | TVIF_PARAM ;
- m_pTree->GetItem( &item );
- if ( item.lParam )
- {
- CResourceDatabase* pResDatabase = (CResourceDatabase*) item.lParam;
- CResourceTable* pRes = (CResourceTable*) pResource;
- CString strDB = pResDatabase->GetDisplayName();
- CString strTable = pResource->GetDisplayName();
- strDB.TrimRight();
- strTable.TrimRight();
- if (mysql_select_db(&mysql,strDB))
- {
- return;
- }
- CString str; str.Format("show fields from %s",(LPCTSTR)strTable);
- if ( mysql_query(&mysql,str)==0 )
- {
- MYSQL_RES *result;
- if ((result=mysql_store_result(&mysql)))
- {
- ProcessResultSet ( hItem, result, pRes );
- mysql_free_result(result);
- }
- }
- }
- mysql_close(&mysql);
- break;
- }
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnRegisterServer()
-{
- CRegisterServer dlg;
- if (dlg.DoModal()!=IDOK) return;
- AddResource (
- TVI_ROOT,
- new CResourceServer ( dlg.m_strServer, dlg.m_strHost, dlg.m_strUser, dlg.m_strPassword, dlg.m_strPort )
- );
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnServerProperties()
-{
- HTREEITEM hItem;
- CResource* pRes = GetSelectedResource(&hItem);
- if (!pRes) return;
- if (pRes->GetType()!=CResource::eServer) return;
- CResourceServer* pResource = (CResourceServer*)pRes;
- CRegisterServer dlg;
- dlg.m_strHost = pResource->GetHostName();
- dlg.m_strUser = pResource->GetUserName();
- dlg.m_strPassword = pResource->GetPassword();
- dlg.m_strPort = pResource->GetPortName();
- if (dlg.DoModal()!=IDOK) return;
- pResource->m_strHost = dlg.m_strHost ;
- pResource->m_strUser = dlg.m_strUser ;
- pResource->m_strPassword = dlg.m_strPassword;
- pResource->m_strPort = dlg.m_strPort ;
- TV_ITEM item;
- memset( &item, 0, sizeof(TV_ITEM) );
- item.hItem = hItem;
- item.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_CHILDREN | TVIF_PARAM ;
- m_pTree->GetItem( &item );
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CMySqlManagerView::OnSqlToolQuery()
-{
-
- HTREEITEM hItem;
-
- CResource* pResource = GetSelectedResource(&hItem);
-
- if (!pResource) return;
-
- CResourceServer* pServer = GetServerResource(hItem);
- if (!pServer) return; /* Avoid bug when selecting field */
-
- m_pTool = new CToolSql ( AfxGetMainWnd(), pServer, pResource );
-
- if ( ! m_pTool->Create(IDD_TOOL_SQL,this) )
- {
- delete m_pTool;
- m_pTool = 0;
- PostMessage(WM_COMMAND,IDM_TOOLS_SERVER_PROPERTIES);
- }
- else
- {
- m_pTool->ShowWindow(SW_SHOW);
- }
-
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-BOOL CMySqlManagerView::PreTranslateMessage(MSG* pMsg)
-{
- if (m_pTool && m_pTool->PreTranslateMessage(pMsg))
- return TRUE;
- return CTreeView::PreTranslateMessage(pMsg);
-}
-
-void CMySqlManagerView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
-{
-
- POINT pt;
-
- GetCursorPos ( & pt );
-
- CMenu menu;
-
- menu.CreatePopupMenu ();
-
- menu.AppendMenu ( MF_ENABLED , IDM_SQL_TOOL_QUERY, "SQL Query" );
- menu.AppendMenu ( MF_ENABLED , IDM_REFRESH, "Refresh active item(s)" );
- menu.AppendMenu ( MF_ENABLED , IDM_TOOLS_REGISTER_SERVER, "Register server" );
- menu.AppendMenu ( MF_ENABLED , IDM_TOOLS_SERVER_PROPERTIES, "Properties" );
-
- menu.TrackPopupMenu ( TPM_LEFTALIGN | TPM_RIGHTBUTTON , pt.x, pt.y, CWnd::GetParent(), NULL );
-
- *pResult = 0;
-
-}
diff --git a/VC++Files/mysqlmanager/mysqlmanagerview.h b/VC++Files/mysqlmanager/mysqlmanagerview.h
deleted file mode 100644
index 97f5a2596d1..00000000000
--- a/VC++Files/mysqlmanager/mysqlmanagerview.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// MySqlManagerView.h : interface of the CMySqlManagerView class
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_MYSQLMANAGERVIEW_H__826CB2F4_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_MYSQLMANAGERVIEW_H__826CB2F4_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-#include <afxcview.h>
-#include "cresource.h"
-
-class CToolSql;
-
-class CMySqlManagerView : public CTreeView
-{
-protected: // create from serialization only
- CMySqlManagerView();
- DECLARE_DYNCREATE(CMySqlManagerView)
-
-// Attributes
-public:
- CMySqlManagerDoc* GetDocument();
-
-// Operations
-public:
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CMySqlManagerView)
- public:
- virtual void OnDraw(CDC* pDC); // overridden to draw this view
- virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
- virtual void OnInitialUpdate();
- virtual BOOL PreTranslateMessage(MSG* pMsg);
- protected:
- virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
- virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
- virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
- //}}AFX_VIRTUAL
-
-// Implementation
-
- CResource* GetSelectedResource(HTREEITEM* phItemRet=NULL);
- CResourceServer* GetServerResource(HTREEITEM hItem);
-
- HTREEITEM AddResource ( HTREEITEM hParent, CResource* pRes, HTREEITEM hLastItem = TVI_FIRST ) ;
- void ProcessResultSet ( HTREEITEM hItem, LPVOID result, CResource* pResource );
-
-public:
- virtual ~CMySqlManagerView();
-#ifdef _DEBUG
- virtual void AssertValid() const;
- virtual void Dump(CDumpContext& dc) const;
-#endif
-
-protected:
-
- CTreeCtrl* m_pTree;
- CImageList* m_pImages;
- CBitmap* m_pbmBmp;
- CToolSql* m_pTool;
-
-// Generated message map functions
-protected:
- //{{AFX_MSG(CMySqlManagerView)
- afx_msg void OnDblclk(NMHDR* pNMHDR, LRESULT* pResult);
- afx_msg void OnSqlToolQuery();
- afx_msg void OnRefresh();
- afx_msg void OnRegisterServer();
- afx_msg void OnServerProperties();
- afx_msg void OnRclick(NMHDR* pNMHDR, LRESULT* pResult);
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-#ifndef _DEBUG // debug version in MySqlManagerView.cpp
-inline CMySqlManagerDoc* CMySqlManagerView::GetDocument()
- { return (CMySqlManagerDoc*)m_pDocument; }
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_MYSQLMANAGERVIEW_H__826CB2F4_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/registerserver.cpp b/VC++Files/mysqlmanager/registerserver.cpp
deleted file mode 100644
index a0e9dcca3df..00000000000
--- a/VC++Files/mysqlmanager/registerserver.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// RegisterServer.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "mysqlmanager.h"
-#include "RegisterServer.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// CRegisterServer dialog
-
-
-CRegisterServer::CRegisterServer(CWnd* pParent /*=NULL*/)
- : CDialog(CRegisterServer::IDD, pParent)
- , m_strServer("servername")
- , m_strHost("localhost")
- , m_strUser("root")
- , m_strPassword("")
-{
- //{{AFX_DATA_INIT(CRegisterServer)
- m_strPort = _T("3306");
- //}}AFX_DATA_INIT
-}
-
-
-void CRegisterServer::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CRegisterServer)
- DDX_CBString(pDX, ID_SERVER_CB, m_strServer);
- DDX_CBString(pDX, ID_HOST_CB, m_strHost);
- DDX_Text(pDX, ID_USER, m_strUser);
- DDX_Text(pDX, ID_PASSWORD, m_strPassword);
- DDX_CBString(pDX, ID_PORT_CB, m_strPort);
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(CRegisterServer, CDialog)
- //{{AFX_MSG_MAP(CRegisterServer)
- // NOTE: the ClassWizard will add message map macros here
- //}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// CRegisterServer message handlers
diff --git a/VC++Files/mysqlmanager/registerserver.h b/VC++Files/mysqlmanager/registerserver.h
deleted file mode 100644
index f4ac2356b2c..00000000000
--- a/VC++Files/mysqlmanager/registerserver.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#if !defined(AFX_REGISTERSERVER_H__826CB2FF_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_REGISTERSERVER_H__826CB2FF_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-// RegisterServer.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CRegisterServer dialog
-
-class CRegisterServer : public CDialog
-{
-// Construction
-public:
- CRegisterServer(CWnd* pParent = NULL); // standard constructor
-
-// Dialog Data
- //{{AFX_DATA(CRegisterServer)
- enum { IDD = IDD_REGISTER_SERVER };
- CString m_strServer;
- CString m_strHost;
- CString m_strUser;
- CString m_strPassword;
- CString m_strPort;
- //}}AFX_DATA
-
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CRegisterServer)
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
- // Generated message map functions
- //{{AFX_MSG(CRegisterServer)
- // NOTE: the ClassWizard will add member functions here
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_REGISTERSERVER_H__826CB2FF_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/resource.h b/VC++Files/mysqlmanager/resource.h
deleted file mode 100644
index def26ce6808..00000000000
--- a/VC++Files/mysqlmanager/resource.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by MySqlManager.rc
-//
-#define IDC_START_PB 3
-#define IDC_STOP_PB 4
-#define ID_SERVERS_PB 7
-#define IDD_ABOUTBOX 100
-#define IDM_QUERY_EXEC 101
-#define IDM_QUERY_DATABASES 102
-#define IDM_REFRESH 103
-#define IDD_REGISTER_SERVER 114
-#define IDR_MAINFRAME 128
-#define IDR_MYSQLMTYPE 129
-#define IDD_TOOL_SQL 132
-#define IDB_BITMAP1 133
-#define IDD_TOOL_SQL_QUERY 134
-#define IDD_TOOL_SQL_RESULTS 135
-#define IDD_TOOL_SQL_STATUS 136
-#define IDC_TAB1 1000
-#define IDC_EDIT 1001
-#define IDC_QUERY_PB 1002
-#define IDC_FONT_PB 1003
-#define IDS_QUERY_EXEC 1003
-#define ID_SERVER_CB 1003
-#define ID_USER 1004
-#define IDC_SERVER_CB 1004
-#define IDC_DATABASES_PB 1005
-#define ID_PASSWORD 1005
-#define ID_HOST_CB 1006
-#define IDC_TIMER_SECS 1006
-#define ID_PORT_CB 1007
-#define IDC_CLEAR 1007
-#define ID_GROUPS_PB 1012
-#define ID_REMOVE_PB 1017
-#define ID_DISPLAY_SERVER_STATUS_CK 1057
-#define ID_USE_STANDARD_CK 1058
-#define ID_USE_TRUSTED_CK 1059
-#define IDM_SQL_TOOL_QUERY 32771
-#define IDM_TOOLS_REGISTER_SERVER 32772
-#define IDM_TOOLS_SERVER_PROPERTIES 32773
-#define IDS_QUERY_DATABASES 57346
-#define IDS_REFRESH 57347
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_3D_CONTROLS 1
-#define _APS_NEXT_RESOURCE_VALUE 136
-#define _APS_NEXT_COMMAND_VALUE 32775
-#define _APS_NEXT_CONTROL_VALUE 1008
-#define _APS_NEXT_SYMED_VALUE 104
-#endif
-#endif
diff --git a/VC++Files/mysqlmanager/stdafx.cpp b/VC++Files/mysqlmanager/stdafx.cpp
deleted file mode 100644
index 3e0251dff43..00000000000
--- a/VC++Files/mysqlmanager/stdafx.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-// stdafx.cpp : source file that includes just the standard includes
-// MySqlManager.pch will be the pre-compiled header
-// stdafx.obj will contain the pre-compiled type information
-
-#include "stdafx.h"
diff --git a/VC++Files/mysqlmanager/stdafx.h b/VC++Files/mysqlmanager/stdafx.h
deleted file mode 100644
index 8cd7dfd04f3..00000000000
--- a/VC++Files/mysqlmanager/stdafx.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// stdafx.h : include file for standard system include files,
-// or project specific include files that are used frequently, but
-// are changed infrequently
-//
-
-#if !defined(AFX_STDAFX_H__826CB2EC_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_STDAFX_H__826CB2EC_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
-
-#include <afxwin.h> // MFC core and standard components
-#include <afxext.h> // MFC extensions
-#include <afxdisp.h> // MFC OLE automation classes
-#ifndef _AFX_NO_AFXCMN_SUPPORT
-#include <afxcmn.h> // MFC support for Windows Common Controls
-#endif // _AFX_NO_AFXCMN_SUPPORT
-
-#include <afxsock.h>
-#include "mysql.h"
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_STDAFX_H__826CB2EC_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/toolsql.cpp b/VC++Files/mysqlmanager/toolsql.cpp
deleted file mode 100644
index 1773a3a6dc7..00000000000
--- a/VC++Files/mysqlmanager/toolsql.cpp
+++ /dev/null
@@ -1,687 +0,0 @@
-// ToolSql.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "MySqlManager.h"
-#include "ToolSql.h"
-
-#define WINDOW_COORDS 0
-#define CLIENT_COORDS 1
-
-#define MY_TIMER_ID 0x1234
-
-#ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-
-CToolSql::CToolSql(CWnd* pParent,CResource* pServer,CResource* pResource)
-: CDialog(CToolSql::IDD, pParent)
-, m_pQuery(0)
-, m_pResults(0)
-, m_pStatus(0)
-, m_pServer(pServer)
-, m_pResource(pResource)
-, m_ui_timer(0)
-{
- //{{AFX_DATA_INIT(CToolSql)
- m_nIntervalTimerSeconds = 10;
- m_bClear = FALSE;
- //}}AFX_DATA_INIT
- memset ( & m_lf, 0,sizeof(m_lf) );
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-CToolSql::~CToolSql()
-{
-
- if (m_ui_timer)
- {
- KillTimer(MY_TIMER_ID);
- }
-
- if (m_pdb)
- {
- mysql_close(m_pdb);
- }
- if (m_pQuery)
- {
- m_pQuery->DestroyWindow();
- delete m_pQuery;
- }
- if (m_pResults)
- {
- m_pResults->DestroyWindow();
- delete m_pResults;
- }
- if (m_pStatus)
- {
- m_pStatus->DestroyWindow();
- delete m_pStatus;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CToolSql)
- DDX_Control(pDX, IDC_STOP_PB, m_ctl_Stop);
- DDX_Control(pDX, IDC_START_PB, m_ctl_Start);
- DDX_Control(pDX, IDC_SERVER_CB, m_ctl_Server);
- DDX_Control(pDX, IDC_TAB1, m_tabs);
- DDX_Text(pDX, IDC_TIMER_SECS, m_nIntervalTimerSeconds);
- DDV_MinMaxInt(pDX, m_nIntervalTimerSeconds, 1, 120);
- DDX_Check(pDX, IDC_CLEAR, m_bClear);
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(CToolSql, CDialog)
-//{{AFX_MSG_MAP(CToolSql)
- ON_BN_CLICKED(IDC_QUERY_PB, OnQueryPb)
- ON_BN_CLICKED(IDC_DATABASES_PB, OnQueryDatabases)
- ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnSelchangeTab1)
- ON_BN_CLICKED(IDC_FONT_PB, OnFontPb)
- ON_WM_SIZE()
- ON_BN_CLICKED(IDC_START_PB, OnStartPb)
- ON_BN_CLICKED(IDC_STOP_PB, OnStopPb)
- ON_WM_TIMER()
- ON_WM_DESTROY()
- ON_BN_CLICKED(IDC_CLEAR, OnClear)
- ON_COMMAND(IDM_QUERY_EXEC, OnQueryPb)
- ON_COMMAND(IDM_QUERY_DATABASES, OnQueryDatabases)
- ON_EN_CHANGE(IDC_TIMER_SECS, OnChangeTimerSecs)
- //}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-
-BOOL CToolSql::OnInitDialog()
-{
-
- CDialog::OnInitDialog();
-
- m_ctl_Start . EnableWindow(TRUE);
- m_ctl_Stop . EnableWindow(FALSE);
-
- CString strTitle;
-
- strTitle.Format ("mySql Query to %s on %s",m_pServer->GetDisplayName(),m_pServer->GetHostName());
-
- m_ctl_Server.AddString ( m_pServer->GetDisplayName() );
- m_ctl_Server.SetCurSel (0);
-
- SetWindowText(strTitle);
-
- CWaitCursor x;
-
- m_btn_QueryExec.AutoLoad ( IDC_QUERY_PB, this );
- m_btn_QueryDatabases.AutoLoad ( IDC_DATABASES_PB, this );
- m_btn_Font.AutoLoad ( IDC_FONT_PB, this );
-
- m_tabs.GetWindowRect ( m_rectTab[WINDOW_COORDS] );
- GetWindowRect ( m_rectDlg[WINDOW_COORDS] );
-
- m_tabs.GetClientRect ( m_rectTab[CLIENT_COORDS] );
- GetClientRect ( m_rectDlg[CLIENT_COORDS] );
-
- CMenu* pSysMenu = GetSystemMenu(FALSE);
- if (pSysMenu != NULL)
- {
- CString strText;
- strText.LoadString(IDS_QUERY_EXEC);
- if (!strText.IsEmpty())
- {
- pSysMenu->AppendMenu(MF_SEPARATOR);
- pSysMenu->AppendMenu(MF_STRING, IDM_QUERY_EXEC, strText);
- }
- strText.LoadString(IDS_QUERY_DATABASES);
- if (!strText.IsEmpty())
- {
- pSysMenu->AppendMenu(MF_STRING, IDM_QUERY_DATABASES, strText);
- }
- }
-
-
- m_pdb = new MYSQL;
-
- CString strQuery ( "Query" );
- CString strResults ( "Results" );
- CString strStatus ( "Status" );
-
- TC_ITEM tc1 = { TCIF_TEXT, 0,0, (LPSTR)(LPCTSTR)strQuery, strQuery.GetLength(), 0,0};
- TC_ITEM tc2 = { TCIF_TEXT, 0,0, (LPSTR)(LPCTSTR)strResults, strResults.GetLength(), 0,0};
- TC_ITEM tc3 = { TCIF_TEXT, 0,0, (LPSTR)(LPCTSTR)strStatus, strStatus.GetLength(), 0,0};
-
- m_tabs.InsertItem ( 0,&tc1 );
- m_tabs.InsertItem ( 1,&tc2 );
- m_tabs.InsertItem ( 2,&tc3 );
-
- m_pQuery = new CToolSqlQuery ( NULL );
- m_pResults = new CToolSqlResults ( NULL );
- m_pStatus = new CToolSqlStatus ( NULL );
-
- try
- {
-
-// OpenDatabase();
-//
-// m_pSelection->SetDatabase ( & m_db );
-// m_pScript->SetDatabase ( & m_db );
-// m_pLog->SetDatabase ( & m_db );
-
- m_pQuery -> Create ( (LPCTSTR)IDD_TOOL_SQL_QUERY, &m_tabs );
- m_pResults -> Create ( (LPCTSTR)IDD_TOOL_SQL_RESULTS, &m_tabs );
- m_pStatus -> Create ( (LPCTSTR)IDD_TOOL_SQL_STATUS, &m_tabs );
-
- ActivateTab ( 0 );
-
- m_pQuery -> SetWindowPos(NULL,20,24,0,0,SWP_NOZORDER|SWP_NOSIZE);
- m_pResults -> SetWindowPos(NULL,20,24,0,0,SWP_NOZORDER|SWP_NOSIZE);
- m_pStatus -> SetWindowPos(NULL,20,24,0,0,SWP_NOZORDER|SWP_NOSIZE);
-
- DoOnSize( SIZE_RESTORED, m_rectDlg[CLIENT_COORDS].Width(), m_rectDlg[CLIENT_COORDS].Height() );
-
- }
- catch (...)
- {
- }
-
- mysql_init(m_pdb);
- if (!mysql_real_connect(m_pdb,m_pServer->GetHostName(), m_pServer->GetUserName(),m_pServer->GetPassword(),0,m_pServer->GetPortNumber(), NullS,0))
- {
-// my_printf_error(0,"connect to server at '%s' failed; error: '%s'",
-// MYF(ME_BELL), pResource->GetHostName(), mysql_error(&mysql));
- CString strText;
- strText.Format ( "connect to server at '%s' failed; error: '%s'", m_pServer->GetHostName(), mysql_error(m_pdb));
- AfxMessageBox(strText);
- EndDialog(IDCANCEL);
- return FALSE;
- }
-
- if ( m_pResource && m_pResource->GetType() == CResource::eDatabase )
- {
- CString strDB = m_pResource->GetDisplayName();
- strDB.TrimRight();
- if (mysql_select_db(m_pdb,strDB))
- {
- }
- }
-
- return FALSE; // return TRUE unless you set the focus to a control
- // EXCEPTION: OCX Property Pages should return FALSE
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::ActivateTab ( int tab )
-
-{
- switch (tab)
- {
- case 0: ;
- m_pResults-> ShowWindow(SW_HIDE);
- m_pStatus-> ShowWindow(SW_HIDE);
- m_pQuery-> ShowWindow(SW_SHOW);
- m_pQuery->m_ctl_edit.SetFocus();
- break;
- case 1: ;
- m_pQuery-> ShowWindow(SW_HIDE);
- m_pStatus-> ShowWindow(SW_HIDE);
- m_pResults-> ShowWindow(SW_SHOW);
- m_pResults->m_ctl_edit.SetFocus();
- break;
- case 2: ;
- m_pResults-> ShowWindow(SW_HIDE);
- m_pQuery-> ShowWindow(SW_HIDE);
- m_pStatus-> ShowWindow(SW_SHOW);
- m_pStatus->m_ctl_edit.SetFocus();
- break;
- default:
- break;
- }
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CalculateFontSize ( CEdit& ed, CSize& sizeRet )
-
-{
-
- CDC* pdc = ed.GetDC();
-
- int nAveWidth , nAveHeight;
- int i ;
-
- CSize size ;
-
- static BOOL bFirstTime = TRUE;
- static char rgchAlphabet [54] ;
-
- if ( bFirstTime )
- {
- bFirstTime = false;
- for ( i = 0 ; i <= 25 ; i++)
- {
- rgchAlphabet[i] = (char)(i+(int)'a') ;
- rgchAlphabet[i+26] = (char)(i+(int)'A') ;
- }
- rgchAlphabet[52] = 0x20;
- rgchAlphabet[53] = 0x20;
- }
-
- CFont* pf = ed.GetFont();
- LOGFONT lf;
- pf->GetLogFont(&lf);
- pdc->SelectObject (pf);
- GetTextExtentPoint32 ( pdc->m_hDC, (LPSTR) rgchAlphabet, 54, & size ) ;
-
- nAveWidth = size.cx / 54 ;
-
- if ( size.cx % 54 )
- {
- nAveWidth++;
- }
-
- nAveHeight = size.cy; //6 * size.cy / 4;
-
- sizeRet.cx = nAveWidth;
- sizeRet.cy = nAveHeight; // tm.tmHeight;
-
- ed.ReleaseDC(pdc);
-
-}
-
-///////////////////////////////////////////////////////////////////////////////
-int ProcessYieldMessage ()
-{
-
- CWinApp* pApp = AfxGetApp();
-
- if ( pApp )
- {
- MSG msgx;
- while (::PeekMessage(&msgx, NULL, NULL, NULL, PM_NOREMOVE))
- try
- {
- if (!pApp->PumpMessage())
- {
-// ExitProcess(1);
- }
- }
- catch (...)
- {
- }
- }
-
- return 0;
-
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-void print_table_data(MYSQL_RES *result,CString& str,CEdit& ed,LOGFONT& lf)
-{
- MYSQL_ROW cur;
- uint length;
- MYSQL_FIELD* field;
- bool* num_flag;
- my_ulonglong nRows = mysql_num_rows(result);
- uint nFields = mysql_num_fields(result);
- int* rgi = new int [nFields];
- memset ( rgi, 0, nFields*sizeof(int) );
- num_flag=(bool*) my_alloca(sizeof(bool)*nFields);
-
- ed.SetLimitText(65535*16);
-
- CSize sizeFont;
- CalculateFontSize ( ed, sizeFont );
- uint index = 0;
- rgi[index++]=0;
- CString separator("");
-
- mysql_field_seek(result,0);
-
- for (uint off=0; (field = mysql_fetch_field(result)) ; off++)
- {
- uint length= (uint) strlen(field->name);
- length=max(length,field->max_length);
- if (length < 4 && !IS_NOT_NULL(field->flags))
- length=4; // Room for "NULL"
- field->max_length=length+1;
- int n=length+2;
- for (uint i=lstrlen(field->name); i-- > 0 ; ) separator+="-";
- if ( index!= nFields )
- {
- int o = rgi[index-1];
- rgi[index++]=o+((n+1)*sizeFont.cx)/2;
- }
- separator+='\t';
- str += field->name;
- str += "\t";
- num_flag[off]= IS_NUM(field->type);
- }
- separator += "\r\n";
- str += "\r\n";
- str += separator;
- ed.SetSel(-1,-1);
- ed.ReplaceSel(str);
-
- if ( 1 || nRows > 100 )
- {
- while ((cur = mysql_fetch_row(result)))
- {
- ProcessYieldMessage ();
- mysql_field_seek(result,0);
- str.Empty();
- ed.SetSel(-1,-1);
- for (uint off=0 ; off < mysql_num_fields(result); off++)
- {
- field = mysql_fetch_field(result);
- length=field->max_length;
- CString strText;
- strText.Format ("%s", cur[off] ? (char*) cur[off] : "NULL");
- str += strText;
- str += "\t";
- }
- str += "\r\n";
- ed.SetSel(-1,-1);
- ed.ReplaceSel(str);
- }
- }
- else
- {
- while ((cur = mysql_fetch_row(result)))
- {
- mysql_field_seek(result,0);
- for (uint off=0 ; off < mysql_num_fields(result); off++)
- {
- field = mysql_fetch_field(result);
- length=field->max_length;
- CString strText;
- strText.Format ("%s", cur[off] ? (char*) cur[off] : "NULL");
- str += strText;
- str += "\t";
- }
- str += "\r\n";
- }
- }
- my_afree((gptr) num_flag);
- str += "\r\n";
- ed.SetTabStops(nFields,rgi);
- delete [] rgi;
-}
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnQueryPb()
-{
-
- CWaitCursor x;
-// mysql_select_db(m_pdb,"mysql");
-
- if ( m_pResource && m_pResource->GetType() == CResource::eDatabase )
- {
- CString strDB = m_pResource->GetDisplayName();
- strDB.TrimRight();
- if (mysql_select_db(m_pdb,strDB))
- {
- }
- }
-
- m_pQuery->UpdateData();
- m_pResults->m_edit.Empty();
- CString str = m_pQuery->m_edit;
- if ( mysql_real_query(m_pdb,str,str.GetLength())==0 )
- {
- MYSQL_RES *result;
- if ((result=mysql_store_result(m_pdb)))
- {
- my_ulonglong nRows = mysql_num_rows(result);
- m_pResults->UpdateData(FALSE);
- m_tabs.SetCurSel(1);
- ActivateTab ( 1 );
- print_table_data(result,m_pResults->m_edit,m_pResults->m_ctl_edit,m_lf);
-// m_pResults->UpdateData(FALSE);
- m_pResults->m_ctl_edit.SetSel(-1,-1);
- CString strText;
- strText.Format ( "\r\n(%d row(s) affected)\r\n", nRows );
- m_pResults->m_ctl_edit.ReplaceSel(strText);
- mysql_free_result(result);
- }
- else
- {
- m_pResults->m_edit = mysql_error(m_pdb);
- m_pResults->UpdateData(FALSE);
- }
- }
- else
- {
- m_pResults->m_edit = mysql_error(m_pdb);
- m_pResults->UpdateData(FALSE);
- }
-
- m_tabs.SetCurSel(1);
- ActivateTab ( 1 );
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnQueryDatabases()
-{
- CWaitCursor x;
- MYSQL_RES *result;
- m_pResults->m_edit.Empty();
- if ((result=mysql_list_dbs(m_pdb,0)))
- {
- my_ulonglong nRows = mysql_num_rows(result);
- print_table_data(result,m_pResults->m_edit,m_pResults->m_ctl_edit,m_lf);
- //m_pResults->UpdateData(FALSE);
- mysql_free_result(result);
- }
- else
- {
- m_pResults->m_edit = mysql_error(m_pdb);
- m_pResults->UpdateData(FALSE);
- }
-
- m_tabs.SetCurSel(1);
- ActivateTab ( 1 );
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)
-{
- ActivateTab ( m_tabs.GetCurSel() );
- *pResult = 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnFontPb()
-{
-
- CFontDialog FontDlg ( & m_lf );
-
- if ( FontDlg.DoModal ( ) == IDOK )
- {
- if (m_font.GetSafeHandle())
- m_font.DeleteObject();
- m_lf = *FontDlg.m_cf.lpLogFont;
- m_font.CreateFontIndirect(FontDlg.m_cf.lpLogFont);
- m_pQuery->SetFont(&m_font);
- m_pResults->SetFont(&m_font);
- m_pStatus->SetFont(&m_font);
- }
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::DoOnSize(UINT nType, int cx, int cy)
-{
-
- int nx = cx - ( m_rectDlg[CLIENT_COORDS].Width ( ) - m_rectTab[CLIENT_COORDS].Width ( ) );
- int ny = cy - ( m_rectDlg[CLIENT_COORDS].Height ( ) - m_rectTab[CLIENT_COORDS].Height ( ) );
-
- if (IsWindow(m_tabs.GetSafeHwnd()))
- {
- m_tabs.SetWindowPos ( NULL
- , 0
- , 0
- , nx
- , ny
- , SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW );
-
- if (m_pResults&&IsWindow(m_pResults->GetSafeHwnd()))
- m_pResults -> SetWindowPos(NULL,20,24,nx-40,ny-48,SWP_NOZORDER | SWP_NOMOVE );
- if (m_pQuery&&IsWindow(m_pQuery->GetSafeHwnd()))
- m_pQuery -> SetWindowPos(NULL,20,24,nx-40,ny-48,SWP_NOZORDER | SWP_NOMOVE );
- if (m_pStatus&&IsWindow(m_pStatus->GetSafeHwnd()))
- m_pStatus -> SetWindowPos(NULL,20,24,nx-40,ny-48,SWP_NOZORDER | SWP_NOMOVE );
-// switch ( m_tabs.GetCurSel() )
-// {
-// case 0:
-// {
-// if (m_pResults&&IsWindow(m_pResults->GetSafeHwnd()))
-// m_pResults -> SetWindowPos(NULL,20,24,nx-40,ny-48,SWP_NOZORDER | SWP_NOMOVE | SWP_HIDEWINDOW );
-// if (m_pQuery&&IsWindow(m_pQuery->GetSafeHwnd()))
-// m_pQuery -> SetWindowPos(NULL,20,24,nx-40,ny-48,SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW );
-// break;
-// }
-// case 1:
-// {
-// if (m_pQuery&&IsWindow(m_pQuery->GetSafeHwnd()))
-// m_pQuery -> SetWindowPos(NULL,20,24,nx-40,ny-48,SWP_NOZORDER | SWP_NOMOVE | SWP_HIDEWINDOW );
-// if (m_pResults&&IsWindow(m_pResults->GetSafeHwnd()))
-// m_pResults -> SetWindowPos(NULL,20,24,nx-40,ny-48,SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW );
-// break;
-// }
-// }
- }
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnSize(UINT nType, int cx, int cy)
-{
-
- CDialog::OnSize(nType, cx, cy);
-
- DoOnSize ( nType, cx, cy );
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnOK()
-{
- CDialog::OnOK();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnCancel()
-{
- CDialog::OnCancel();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-BOOL CToolSql::PreTranslateMessage(MSG* pMsg)
-{
- return CDialog::PreTranslateMessage(pMsg);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::DoProcessListQuery()
-{
-
- MYSQL_RES *result;
- if (result=mysql_list_processes(m_pdb))
- {
- if (m_bClear)
- {
- m_pStatus->m_edit.Empty();
- m_pStatus->UpdateData(FALSE);
- }
- print_table_data(result,m_pStatus->m_edit,m_pStatus->m_ctl_edit,m_lf);
- mysql_free_result(result);
- }
- else
- {
-// my_printf_error(0,"process list failed; error: '%s'",MYF(ME_BELL),mysql_error(mysql));
- }
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnStartPb()
-{
- UpdateData();
- if (m_ui_timer) return;
- if (m_nIntervalTimerSeconds<1) return;
- ActivateTab ( 2 );
- m_ui_timer = SetTimer( MY_TIMER_ID, m_nIntervalTimerSeconds*1000, NULL );
- m_ctl_Start . EnableWindow(FALSE);
- m_ctl_Stop . EnableWindow(TRUE);
- DoProcessListQuery();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnStopPb()
-{
- UpdateData();
- if (m_ui_timer)
- {
- KillTimer(MY_TIMER_ID);
- m_ui_timer = 0;
- }
- m_ctl_Start . EnableWindow(TRUE);
- m_ctl_Stop . EnableWindow(FALSE);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSql::OnTimer(UINT nIDEvent)
-{
- DoProcessListQuery();
- CDialog::OnTimer(nIDEvent);
-}
-
-void CToolSql::OnDestroy()
-{
- if (m_ui_timer)
- {
- KillTimer(MY_TIMER_ID);
- m_ui_timer = 0;
- }
- CDialog::OnDestroy();
-}
-
-void CToolSql::OnClear()
-{
- UpdateData();
-}
-
-void CToolSql::OnChangeTimerSecs()
-{
- UpdateData();
-}
diff --git a/VC++Files/mysqlmanager/toolsql.h b/VC++Files/mysqlmanager/toolsql.h
deleted file mode 100644
index 7d608f46cd2..00000000000
--- a/VC++Files/mysqlmanager/toolsql.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#if !defined(AFX_ToolSql_H__826CB2FC_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_ToolSql_H__826CB2FC_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-#include "ToolSqlQuery.h"
-#include "ToolSqlResults.h"
-#include "ToolSqlStatus.h"
-#include "cresource.h"
-#include <my_global.h>
-#include "my_sys.h"
-#include "mysql.h"
-
-
-/////////////////////////////////////////////////////////////////////////////
-// CToolSql dialog
-
-class CToolSql : public CDialog
-{
-// Construction
-public:
- CToolSql(CWnd* pParent = NULL,CResource* pServer=NULL,CResource* pResource=NULL);
- ~CToolSql();
-
-// Dialog Data
- //{{AFX_DATA(CToolSql)
- enum { IDD = IDD_TOOL_SQL };
- CButton m_ctl_Stop;
- CButton m_ctl_Start;
- CComboBox m_ctl_Server;
- CTabCtrl m_tabs;
- int m_nIntervalTimerSeconds;
- BOOL m_bClear;
- //}}AFX_DATA
-
- CBitmapButton m_btn_QueryExec;
- CBitmapButton m_btn_Font;
- CBitmapButton m_btn_QueryDatabases;
-
-#ifdef _WIN64
- __int64 m_ui_timer;
-#else
- UINT m_ui_timer;
-#endif
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CToolSql)
- public:
- virtual BOOL PreTranslateMessage(MSG* pMsg);
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
-// Implementation
-
- void ActivateTab ( int tab );
- void DoProcessListQuery();
-
- CToolSqlQuery* m_pQuery;
- CToolSqlResults* m_pResults;
- CToolSqlStatus* m_pStatus;
-
- CResource* m_pServer;
- CResource* m_pResource;
- MYSQL* m_pdb;
- CFont m_font;
- LOGFONT m_lf;
- CRect m_rectTab[2];
- CRect m_rectDlg[2];
-
-protected:
-
- // Generated message map functions
- //{{AFX_MSG(CToolSql)
- virtual BOOL OnInitDialog();
- afx_msg void OnQueryPb();
- afx_msg void OnQueryDatabases();
- afx_msg void OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult);
- afx_msg void OnFontPb();
- afx_msg void OnSize(UINT nType, int cx, int cy);
- virtual void OnOK();
- virtual void OnCancel();
- afx_msg void OnStartPb();
- afx_msg void OnStopPb();
- afx_msg void OnTimer(UINT nIDEvent);
- afx_msg void OnDestroy();
- afx_msg void OnClear();
- afx_msg void OnChangeTimerSecs();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-
- void DoOnSize(UINT nType, int cx, int cy) ;
-
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_ToolSql_H__826CB2FC_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/toolsqlquery.cpp b/VC++Files/mysqlmanager/toolsqlquery.cpp
deleted file mode 100644
index 1f246f47786..00000000000
--- a/VC++Files/mysqlmanager/toolsqlquery.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-// ToolSqlQuery.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "MySqlManager.h"
-#include "ToolSqlQuery.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-
-CToolSqlQuery::CToolSqlQuery(CWnd* pParent /*=NULL*/)
- : CDialog(CToolSqlQuery::IDD, pParent)
-{
- //{{AFX_DATA_INIT(CToolSqlQuery)
- m_edit = _T("");
- //}}AFX_DATA_INIT
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlQuery::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CToolSqlQuery)
- DDX_Control(pDX, IDC_EDIT, m_ctl_edit);
- DDX_Text(pDX, IDC_EDIT, m_edit);
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(CToolSqlQuery, CDialog)
- //{{AFX_MSG_MAP(CToolSqlQuery)
- ON_WM_SIZE()
- ON_WM_CLOSE()
- ON_COMMAND(IDM_QUERY_EXEC, OnQueryPb)
- ON_COMMAND(IDM_QUERY_DATABASES, OnQueryDatabases)
- //}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlQuery::SetFont(CFont* pFont, BOOL bRedraw)
-{
- m_ctl_edit.SetFont(pFont,bRedraw);
- m_ctl_edit.Invalidate();
- m_ctl_edit.UpdateWindow();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlQuery::OnSize(UINT nType, int cx, int cy)
-{
- CDialog::OnSize(nType, cx, cy);
- if (IsWindow(m_ctl_edit.GetSafeHwnd()))
- m_ctl_edit.SetWindowPos(NULL,20,24,cx-40,cy-48,SWP_NOZORDER | SWP_NOMOVE);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlQuery::OnCancel()
-{
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlQuery::OnClose()
-{
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlQuery::OnQueryPb()
-{
- GetParent()->GetParent()->PostMessage(WM_COMMAND,IDM_QUERY_EXEC);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlQuery::OnQueryDatabases()
-{
- GetParent()->GetParent()->PostMessage(WM_COMMAND,IDM_QUERY_DATABASES);
-}
-/////////////////////////////////////////////////////////////////////////////
-
-BOOL CToolSqlQuery::PreTranslateMessage(MSG* pMsg)
-{
- if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
- {
- if (::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
- return TRUE;
- }
- return CDialog::PreTranslateMessage(pMsg);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-BOOL CToolSqlQuery::OnInitDialog()
-{
-
- CDialog::OnInitDialog();
- m_hAccel = ::LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE ( IDR_MAINFRAME ));
- return TRUE; // return TRUE unless you set the focus to a control
- // EXCEPTION: OCX Property Pages should return FALSE
-}
diff --git a/VC++Files/mysqlmanager/toolsqlquery.h b/VC++Files/mysqlmanager/toolsqlquery.h
deleted file mode 100644
index c5d318c161b..00000000000
--- a/VC++Files/mysqlmanager/toolsqlquery.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#if !defined(AFX_TOOLSQLQUERY_H__826CB2FD_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_TOOLSQLQUERY_H__826CB2FD_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-// ToolSqlQuery.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CToolSqlQuery dialog
-
-class CToolSqlQuery : public CDialog
-{
-// Construction
-public:
- CToolSqlQuery(CWnd* pParent = NULL); // standard constructor
-
-// Dialog Data
- //{{AFX_DATA(CToolSqlQuery)
- enum { IDD = IDD_TOOL_SQL_QUERY };
- CEdit m_ctl_edit;
- CString m_edit;
- //}}AFX_DATA
-
- HACCEL m_hAccel;
-
- void SetFont(CFont* pFont, BOOL bRedraw = TRUE);
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CToolSqlQuery)
- public:
- virtual BOOL PreTranslateMessage(MSG* pMsg);
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
-// Implementation
-
-protected:
-
- // Generated message map functions
- //{{AFX_MSG(CToolSqlQuery)
- afx_msg void OnSize(UINT nType, int cx, int cy);
- afx_msg void OnCancel();
- afx_msg void OnClose();
- virtual BOOL OnInitDialog();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-
- afx_msg void OnQueryPb();
- afx_msg void OnQueryDatabases();
-
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_TOOLSQLQUERY_H__826CB2FD_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/toolsqlresults.cpp b/VC++Files/mysqlmanager/toolsqlresults.cpp
deleted file mode 100644
index b6cfcded18b..00000000000
--- a/VC++Files/mysqlmanager/toolsqlresults.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-// ToolSqlResults.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "MySqlManager.h"
-#include "ToolSqlResults.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-
-CToolSqlResults::CToolSqlResults(CWnd* pParent /*=NULL*/)
- : CDialog(CToolSqlResults::IDD, pParent)
-{
- //{{AFX_DATA_INIT(CToolSqlResults)
- m_edit = _T("");
- //}}AFX_DATA_INIT
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlResults::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CToolSqlResults)
- DDX_Control(pDX, IDC_EDIT, m_ctl_edit);
- DDX_Text(pDX, IDC_EDIT, m_edit);
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(CToolSqlResults, CDialog)
- //{{AFX_MSG_MAP(CToolSqlResults)
- ON_WM_SIZE()
- ON_WM_CLOSE()
- //}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlResults::SetFont(CFont* pFont, BOOL bRedraw)
-{
- m_ctl_edit.SetFont(pFont,bRedraw);
- m_ctl_edit.Invalidate();
- m_ctl_edit.UpdateWindow();
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlResults::OnSize(UINT nType, int cx, int cy)
-{
- CDialog::OnSize(nType, cx, cy);
- if (IsWindow(m_ctl_edit.GetSafeHwnd()))
- m_ctl_edit.SetWindowPos(NULL,20,24,cx-40,cy-48,SWP_NOZORDER | SWP_NOMOVE);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlResults::OnCancel()
-{
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void CToolSqlResults::OnClose()
-{
-}
diff --git a/VC++Files/mysqlmanager/toolsqlresults.h b/VC++Files/mysqlmanager/toolsqlresults.h
deleted file mode 100644
index c4de651cb81..00000000000
--- a/VC++Files/mysqlmanager/toolsqlresults.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#if !defined(AFX_TOOLSQLRESULTS_H__826CB2FE_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
-#define AFX_TOOLSQLRESULTS_H__826CB2FE_8B6D_11D1_AEC1_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-// ToolSqlResults.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CToolSqlResults dialog
-
-class CToolSqlResults : public CDialog
-{
-// Construction
-public:
- CToolSqlResults(CWnd* pParent = NULL); // standard constructor
-
-// Dialog Data
- //{{AFX_DATA(CToolSqlResults)
- enum { IDD = IDD_TOOL_SQL_RESULTS };
- CEdit m_ctl_edit;
- CString m_edit;
- //}}AFX_DATA
-
- void SetFont(CFont* pFont, BOOL bRedraw = TRUE);
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CToolSqlResults)
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
-// Implementation
-
-protected:
-
- // Generated message map functions
- //{{AFX_MSG(CToolSqlResults)
- afx_msg void OnSize(UINT nType, int cx, int cy);
- afx_msg void OnCancel();
- afx_msg void OnClose();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-
-
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_TOOLSQLRESULTS_H__826CB2FE_8B6D_11D1_AEC1_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlmanager/toolsqlstatus.cpp b/VC++Files/mysqlmanager/toolsqlstatus.cpp
deleted file mode 100644
index 81605480783..00000000000
--- a/VC++Files/mysqlmanager/toolsqlstatus.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// ToolSqlStatus.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "mysqlmanager.h"
-#include "ToolSqlStatus.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// CToolSqlStatus dialog
-
-
-CToolSqlStatus::CToolSqlStatus(CWnd* pParent /*=NULL*/)
- : CDialog(CToolSqlStatus::IDD, pParent)
-{
- //{{AFX_DATA_INIT(CToolSqlStatus)
- m_edit = _T("");
- //}}AFX_DATA_INIT
-}
-
-
-void CToolSqlStatus::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CToolSqlStatus)
- DDX_Control(pDX, IDC_EDIT, m_ctl_edit);
- DDX_Text(pDX, IDC_EDIT, m_edit);
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(CToolSqlStatus, CDialog)
- //{{AFX_MSG_MAP(CToolSqlStatus)
- ON_WM_DESTROY()
- //}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// CToolSqlStatus message handlers
-
-void CToolSqlStatus::OnDestroy()
-{
- CDialog::OnDestroy();
-
-}
diff --git a/VC++Files/mysqlmanager/toolsqlstatus.h b/VC++Files/mysqlmanager/toolsqlstatus.h
deleted file mode 100644
index 5e4883b0b30..00000000000
--- a/VC++Files/mysqlmanager/toolsqlstatus.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#if !defined(AFX_TOOLSQLSTATUS_H__40C861B4_9E5A_11D1_AED0_00600806E071__INCLUDED_)
-#define AFX_TOOLSQLSTATUS_H__40C861B4_9E5A_11D1_AED0_00600806E071__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-// ToolSqlStatus.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CToolSqlStatus dialog
-
-class CToolSqlStatus : public CDialog
-{
-// Construction
-public:
- CToolSqlStatus(CWnd* pParent = NULL); // standard constructor
-
-// Dialog Data
- //{{AFX_DATA(CToolSqlStatus)
- enum { IDD = IDD_TOOL_SQL_STATUS };
- CEdit m_ctl_edit;
- CString m_edit;
- //}}AFX_DATA
-
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(CToolSqlStatus)
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
- // Generated message map functions
- //{{AFX_MSG(CToolSqlStatus)
- afx_msg void OnDestroy();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_TOOLSQLSTATUS_H__40C861B4_9E5A_11D1_AED0_00600806E071__INCLUDED_)
diff --git a/VC++Files/mysqlserver/mysqlserver.vcproj b/VC++Files/mysqlserver/mysqlserver.vcproj
new file mode 100755
index 00000000000..2c587e0a2d7
--- /dev/null
+++ b/VC++Files/mysqlserver/mysqlserver.vcproj
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqlserver"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../include,../regex,../sql,../bdb/build_win32,libmysqld"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/mysqlserver.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\mysqlserver.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../include,../regex,../sql,../bdb/build_win32,../libmysqld"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_BERKELEY_DB;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\release/mysqlserver.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\release\mysqlserver.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1046"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/mysqlshutdown/myshutdown.dsp b/VC++Files/mysqlshutdown/myshutdown.dsp
deleted file mode 100644
index 0119df3cd59..00000000000
--- a/VC++Files/mysqlshutdown/myshutdown.dsp
+++ /dev/null
@@ -1,101 +0,0 @@
-# Microsoft Developer Studio Project File - Name="myshutdown" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Application" 0x0101
-
-CFG=myshutdown - 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 "myshutdown.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 "myshutdown.mak" CFG="myshutdown - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "myshutdown - Win32 Release" (based on "Win32 (x86) Application")
-!MESSAGE "myshutdown - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "myshutdown - 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 Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 /subsystem:windows /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 /nologo /subsystem:windows /machine:I386
-
-!ELSEIF "$(CFG)" == "myshutdown - 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 Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /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 /subsystem:windows /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 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
-
-!ENDIF
-
-# Begin Target
-
-# Name "myshutdown - Win32 Release"
-# Name "myshutdown - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# 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/mysqlshutdown/myshutdown_ia64.dsp b/VC++Files/mysqlshutdown/myshutdown_ia64.dsp
deleted file mode 100644
index 1cee7987d5e..00000000000
--- a/VC++Files/mysqlshutdown/myshutdown_ia64.dsp
+++ /dev/null
@@ -1,101 +0,0 @@
-# Microsoft Developer Studio Project File - Name="myshutdown" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Application" 0x0101
-
-CFG=myshutdown - 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 "myshutdown.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 "myshutdown.mak" CFG="myshutdown - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "myshutdown - WinIA64 Release" (based on "Win32 (x86) Application")
-!MESSAGE "myshutdown - WinIA64 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "myshutdown - WinIA64 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 Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /D"WIN64" /D"NDEBUG" /D"_WINDOWS" /D"_MBCS" /YX /FD /c /O2 /G2 /EHsc /D"_IA64_" /Zi /D"WIN64" /D"WIN32" /D"_AFX_NO_DAO_SUPPORT" /Wp64 /Zm600
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win64
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win64
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 /subsystem:windows /machine:IA64
-# 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 /nologo /subsystem:windows /machine:IA64 /incremental:no
-
-!ELSEIF "$(CFG)" == "myshutdown - WinIA64 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 Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN64" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /D"WIN64" /D"_DEBUG" /D"_WINDOWS" /D"_MBCS" /YX /FD /GZ /c /Od /G2 /EHsc /D"_IA64_" /Zi /D"WIN64" /D"WIN32" /D"_AFX_NO_DAO_SUPPORT" /Wp64 /Zm600
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win64
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win64
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /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 /subsystem:windows /debug /machine:IA64
-# 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 /nologo /subsystem:windows /debug /machine:IA64 /incremental:no
-
-!ENDIF
-
-# Begin Target
-
-# Name "myshutdown - WinIA64 Release"
-# Name "myshutdown - WinIA64 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# 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/mysqlshutdown/mysql.ico b/VC++Files/mysqlshutdown/mysql.ico
deleted file mode 100644
index 1fe0b7115bb..00000000000
--- a/VC++Files/mysqlshutdown/mysql.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/mysqlshutdown/mysqlshutdown.c b/VC++Files/mysqlshutdown/mysqlshutdown.c
deleted file mode 100644
index ccaf4a00eda..00000000000
--- a/VC++Files/mysqlshutdown/mysqlshutdown.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/****************************************************************************
- MySqlShutdown - shutdown MySQL on system shutdown (Win95/98)
- ----------------------------------------------------------------------------
- Revision History :
- Version Author Date Description
- 001.00 Irena 21-12-99
-*****************************************************************************/
-#include <windows.h>
-
-//-----------------------------------------------------------------------
-// Local data
-//-----------------------------------------------------------------------
-static char szAppName[] = "MySqlShutdown";
-static HINSTANCE hInstance;
-
-#define MYWM_NOTIFYICON (WM_APP+100)
-
-//-----------------------------------------------------------------------
-// Exported functions
-//-----------------------------------------------------------------------
-LRESULT CALLBACK MainWindowProc (HWND, UINT, WPARAM, LPARAM);
-
-//-----------------------------------------------------------------------
-// Local functions
-//-----------------------------------------------------------------------
-static BOOL InitAppClass (HINSTANCE hInstance);
-
-BOOL TrayMessageAdd(HWND hWnd, DWORD dwMessage)
-{
- BOOL res;
- HICON hIcon =LoadIcon (hInstance, "MySql");
- char *szTip="MySql Shutdown";
- NOTIFYICONDATA tnd;
-
- tnd.cbSize = sizeof(NOTIFYICONDATA);
- tnd.hWnd = hWnd;
- tnd.uID = 101;
-
- tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
- tnd.uCallbackMessage = MYWM_NOTIFYICON;
- tnd.hIcon = hIcon;
- strcpy(tnd.szTip, szTip);
- res = Shell_NotifyIcon(dwMessage, &tnd);
-
- if (hIcon) DestroyIcon(hIcon);
-
- return res;
-}
-
-//-----------------------------------------------------------------------
-// Name: WinMain
-// Purpose: Main application entry point
-//-----------------------------------------------------------------------
-
-int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
-{ HWND hWnd;
- MSG Msg;
-
- hInstance=hInst;
- // Register application class if needed
- if (InitAppClass (hInstance) == FALSE) return (0);
-
-
- hWnd = CreateWindow (szAppName, "MySql",
- WS_OVERLAPPEDWINDOW|WS_MINIMIZE,
- 0, 0,
- GetSystemMetrics(SM_CXSCREEN)/4,
- GetSystemMetrics(SM_CYSCREEN)/4,
- 0, 0, hInstance, NULL);
-
- if(!hWnd)
- {
- return (0);
- }
- ShowWindow (hWnd, SW_HIDE);
- UpdateWindow (hWnd);
- while (GetMessage (&Msg, 0, 0, 0))
- { TranslateMessage (&Msg);
- DispatchMessage (&Msg);
- }
- return ((int) (Msg.wParam));
-}
-
-//-----------------------------------------------------------------------
-// Name: InitAppClass
-// Purpose: Register the main application window class
-//-----------------------------------------------------------------------
-static BOOL InitAppClass (HINSTANCE hInstance)
-{
- WNDCLASS cls;
-
- if (GetClassInfo (hInstance, szAppName, &cls) == 0)
- {
- cls.style = CS_HREDRAW | CS_VREDRAW ;;
- cls.lpfnWndProc = (WNDPROC) MainWindowProc;
- cls.cbClsExtra = 0;
- cls.cbWndExtra = sizeof(HWND);
- cls.hInstance = hInstance;
- cls.hIcon = LoadIcon (hInstance, "MySql");
- cls.hCursor = LoadCursor (NULL, IDC_ARROW);
- cls.hbrBackground = GetStockObject (WHITE_BRUSH) ;
- cls.lpszMenuName = 0; //szAppName;
- cls.lpszClassName = szAppName;
- return RegisterClass (&cls);
- }
- return (TRUE);
-}
-//-----------------------------------------------------------------------
-// Name: MainWindowProc
-// Purpose: Window procedure for main application window.
-//-----------------------------------------------------------------------
-LRESULT CALLBACK MainWindowProc (HWND hWnd, UINT Msg,WPARAM wParam, LPARAM lParam)
-{
- static RECT rect ;
- HDC hdc ;
- PAINTSTRUCT ps ;
- static BOOL bShutdown=FALSE;
-
- switch (Msg)
- {
- case WM_CREATE:
- TrayMessageAdd(hWnd, NIM_ADD);
- return TRUE;
-/***************
- case WM_SYSCOMMAND:
- if(wParam==SC_CLOSE)
- { HANDLE hEventShutdown;
-
- bShutdown=TRUE;
- InvalidateRect(hWnd,NULL,TRUE);
- ShowWindow (hWnd, SW_NORMAL);
- UpdateWindow(hWnd);
- hEventShutdown=OpenEvent(EVENT_MODIFY_STATE, 0, "MySqlShutdown");
- if(hEventShutdown)
- {
- SetEvent(hEventShutdown);
- CloseHandle(hEventShutdown);
- Sleep(1000);
- MessageBox(hWnd,"Shutdown", "MySql", MB_OK);
- }
- TrayMessageAdd(hWnd, NIM_DELETE);
- }
- break;
-**************/
- case WM_DESTROY:
- TrayMessageAdd(hWnd, NIM_DELETE);
- PostQuitMessage (0);
- return 0;
- case WM_SIZE:
- GetClientRect (hWnd, &rect) ;
- return 0 ;
-
- case WM_PAINT:
- hdc = BeginPaint (hWnd, &ps) ;
- if(bShutdown)
- DrawText (hdc, "MySql shutdown in progress...",
- -1, &rect, DT_WORDBREAK) ;
- EndPaint (hWnd, &ps) ;
- return 0 ;
- case WM_QUERYENDSESSION: //Shutdown MySql
- { HANDLE hEventShutdown;
-
- bShutdown=TRUE;
- InvalidateRect(hWnd,NULL,TRUE);
- ShowWindow (hWnd, SW_NORMAL);
- UpdateWindow(hWnd);
- hEventShutdown=OpenEvent(EVENT_MODIFY_STATE, 0, "MySqlShutdown");
- if(hEventShutdown)
- {
- SetEvent(hEventShutdown);
- CloseHandle(hEventShutdown);
- Sleep(1000);
- MessageBox(hWnd,"Shutdown", "MySql", MB_OK);
- }
- }
- return 1;
-
- case MYWM_NOTIFYICON:
- switch (lParam)
- {
- case WM_LBUTTONDOWN:
- case WM_RBUTTONDOWN:
- ShowWindow(hWnd, SW_SHOWNORMAL);
- SetForegroundWindow(hWnd); // make us come to the front
- break;
- default:
- break;
- }
- break;
-
- }
- return DefWindowProc (hWnd, Msg, wParam, lParam);
-}
-
-
-// ----------------------- The end ------------------------------------------
-
-
diff --git a/VC++Files/mysqlshutdown/mysqlshutdown.dsp b/VC++Files/mysqlshutdown/mysqlshutdown.dsp
deleted file mode 100644
index b7802240d42..00000000000
--- a/VC++Files/mysqlshutdown/mysqlshutdown.dsp
+++ /dev/null
@@ -1,119 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mysqlshutdown" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Application" 0x0101
-
-CFG=mysqlshutdown - Win32 Release
-!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 "mysqlshutdown.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 "mysqlshutdown.mak" CFG="mysqlshutdown - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mysqlshutdown - Win32 Release" (based on "Win32 (x86) Application")
-!MESSAGE "mysqlshutdown - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=xicl6.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mysqlshutdown - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /W3 /O2 /D "_WINDOWS" /D "_MBCS" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /WX /Fr /YX
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-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 /nologo /subsystem:windows /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 /nologo /subsystem:windows /machine:I386 /out:"../client_release/mysqlshutdown.exe"
-
-!ELSEIF "$(CFG)" == "mysqlshutdown - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "mysqlshutdown___Win32_Debug"
-# PROP BASE Intermediate_Dir "mysqlshutdown___Win32_Debug"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "debug"
-# PROP Intermediate_Dir "debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /G6 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /W3 /Z7 /Od /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
-# SUBTRACT CPP /Fr /YX
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-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 /nologo /subsystem:windows /machine:I386 /out:"../client_release/mysqlshutdown.exe"
-# 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 /nologo /subsystem:windows /machine:I386 /out:"../client_debug/mysqlshutdown.exe"
-
-!ENDIF
-
-# Begin Target
-
-# Name "mysqlshutdown - Win32 Release"
-# Name "mysqlshutdown - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\mysqlshutdown.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\mysqlshutdown.rc
-# 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"
-# Begin Source File
-
-SOURCE=.\mysql.ico
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/VC++Files/mysqlshutdown/mysqlshutdown.rc b/VC++Files/mysqlshutdown/mysqlshutdown.rc
deleted file mode 100644
index 6837f863a81..00000000000
--- a/VC++Files/mysqlshutdown/mysqlshutdown.rc
+++ /dev/null
@@ -1,2 +0,0 @@
-MySql ICON DISCARDABLE "MYSQL.ICO"
-
diff --git a/VC++Files/mysqlshutdown/mysqlshutdown_ia64.dsp b/VC++Files/mysqlshutdown/mysqlshutdown_ia64.dsp
deleted file mode 100644
index 2549606bf60..00000000000
--- a/VC++Files/mysqlshutdown/mysqlshutdown_ia64.dsp
+++ /dev/null
@@ -1,119 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mysqlshutdown" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Application" 0x0101
-
-CFG=mysqlshutdown - WinIA64 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 "mysqlshutdown_ia64.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 "mysqlshutdown_ia64.mak" CFG="mysqlshutdown - WinIA64 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mysqlshutdown - WinIA64 Release" (based on "Win32 (x86) Application")
-!MESSAGE "mysqlshutdown - WinIA64 Debug" (based on "Win32 (x86) Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mysqlshutdown - WinIA64 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 /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Zi /O2 /D "_WINDOWS" /D "_MBCS" /D "NDEBUG" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c
-# SUBTRACT CPP /WX /Fr /YX
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win64
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win64
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 /subsystem:windows /machine:IA64
-# 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 bufferoverflowU.lib /nologo /subsystem:windows /out:"../client_release/mysqlshutdown.exe" /machine:IA64
-
-!ELSEIF "$(CFG)" == "mysqlshutdown - WinIA64 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "mysqlshutdown___Win64_Debug"
-# PROP BASE Intermediate_Dir "mysqlshutdown___Win64_Debug"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "debug"
-# PROP Intermediate_Dir "debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /G6 /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /W3 /Zi /Od /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c
-# SUBTRACT CPP /Fr /YX
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win64
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win64
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 /subsystem:windows /out:"../client_release/mysqlshutdown.exe" /machine:IA64
-# 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 bufferoverflowU.lib /nologo /subsystem:windows /out:"../client_debug/mysqlshutdown.exe" /machine:IA64
-
-!ENDIF
-
-# Begin Target
-
-# Name "mysqlshutdown - WinIA64 Release"
-# Name "mysqlshutdown - WinIA64 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\mysqlshutdown.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\mysqlshutdown.rc
-# 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"
-# Begin Source File
-
-SOURCE=.\mysql.ico
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/VC++Files/mysqlwatch/mysqlwatch.c b/VC++Files/mysqlwatch/mysqlwatch.c
deleted file mode 100644
index 2a1f62b4394..00000000000
--- a/VC++Files/mysqlwatch/mysqlwatch.c
+++ /dev/null
@@ -1,745 +0,0 @@
-/****************************************************************************
- MySqlWatch - WinNT service program MySQL
- - Re-start MySql server in case of failure
-*****************************************************************************/
-#include <windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <process.h>
-#include <tchar.h>
-
-
-// name of the executable
-#define SZAPPNAME "mysqlwatch"
-// internal name of the service
-#define SZSERVICENAME "MySqlWatch"
-// displayed name of the service
-#define SZSERVICEDISPLAYNAME "MySqlWatch"
-// list of service dependencies - "dep1\0dep2\0\0"
-#define SZDEPENDENCIES ""
-
-
-
-VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
-VOID ServiceStop(void);
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
-void AddToMessageLog(LPTSTR lpszMsg);
-
-// internal variables
-SERVICE_STATUS ssStatus; // current status of the service
-SERVICE_STATUS_HANDLE sshStatusHandle;
-DWORD dwErr = 0;
-BOOL bDebug = FALSE;
-TCHAR szErr[256];
-
-// internal function prototypes
-void WINAPI service_ctrl(DWORD dwCtrlCode);
-void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
-void CmdInstallService(void);
-void CmdRemoveService(void);
-void CmdDebugService(int argc, char **argv);
-BOOL WINAPI ControlHandler ( DWORD dwCtrlType );
-LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
-
-//
-// FUNCTION: main
-//
-// PURPOSE: entrypoint for service
-//
-// PARAMETERS:
-// argc - number of command line arguments
-// argv - array of command line arguments
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-// main() either performs the command line task, or
-// call StartServiceCtrlDispatcher to register the
-// main service thread. When the this call returns,
-// the service has stopped, so exit.
-//
-void main(int argc, char **argv)
-{
- SERVICE_TABLE_ENTRY dispatchTable[] =
- {
- { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main },
- { NULL, NULL }
- };
-
- if ( (argc > 1) &&
- ((*argv[1] == '-') || (*argv[1] == '/')) )
- {
- if ( stricmp( "install", argv[1]+1 ) == 0 )
- {
- CmdInstallService();
- }
- else if ( stricmp( "remove", argv[1]+1 ) == 0 )
- {
- CmdRemoveService();
- }
- else if ( stricmp( "debug", argv[1]+1 ) == 0 )
- {
- bDebug = TRUE;
- CmdDebugService(argc, argv);
- }
- else
- {
- goto dispatch;
- }
- exit(0);
- }
-
- // if it doesn't match any of the above parameters
- // the service control manager may be starting the service
- // so we must call StartServiceCtrlDispatcher
- dispatch:
- // this is just to be friendly
- printf( "%s -install to install the service\n", SZAPPNAME );
- printf( "%s -remove to remove the service\n", SZAPPNAME );
- printf( "%s -debug <params> to run as a console app for debugging\n", SZAPPNAME );
- printf( "\nStartServiceCtrlDispatcher being called.\n" );
- printf( "This may take several seconds. Please wait.\n" );
-
- if (!StartServiceCtrlDispatcher(dispatchTable))
- AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
-}
-
-
-
-//
-// FUNCTION: service_main
-//
-// PURPOSE: To perform actual initialization of the service
-//
-// PARAMETERS:
-// dwArgc - number of command line arguments
-// lpszArgv - array of command line arguments
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-// This routine performs the service initialization and then calls
-// the user defined ServiceStart() routine to perform majority
-// of the work.
-//
-void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
-{
-
- // register our service control handler:
- //
- sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);
-
- if (!sshStatusHandle)
- goto cleanup;
-
- // SERVICE_STATUS members that don't change in example
- //
- ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- ssStatus.dwServiceSpecificExitCode = 0;
-
-
- // report the status to the service control manager.
- //
- if (!ReportStatusToSCMgr(
- SERVICE_START_PENDING, // service state
- NO_ERROR, // exit code
- 3000)) // wait hint
- goto cleanup;
-
-
- ServiceStart( dwArgc, lpszArgv );
-
-cleanup:
-
- // try to report the stopped status to the service control manager.
- //
- if (sshStatusHandle)
- ReportStatusToSCMgr(
- SERVICE_STOPPED,
- dwErr,
- 0);
-
- return;
-}
-
-
-
-//
-// FUNCTION: service_ctrl
-//
-// PURPOSE: This function is called by the SCM whenever
-// ControlService() is called on this service.
-//
-// PARAMETERS:
-// dwCtrlCode - type of control requested
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-//
-void WINAPI service_ctrl(DWORD dwCtrlCode)
-{
- // Handle the requested control code.
- //
- switch(dwCtrlCode)
- {
- // Stop the service.
- //
- case SERVICE_CONTROL_STOP:
- ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
- ServiceStop();
- break;
-
- // Update the service status.
- //
- case SERVICE_CONTROL_INTERROGATE:
- break;
-
- // invalid control code
- //
- default:
- break;
-
- }
-
- ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
-
-}
-
-
-
-//
-// FUNCTION: ReportStatusToSCMgr()
-//
-// PURPOSE: Sets the current status of the service and
-// reports it to the Service Control Manager
-//
-// PARAMETERS:
-// dwCurrentState - the state of the service
-// dwWin32ExitCode - error code to report
-// dwWaitHint - worst case estimate to next checkpoint
-//
-// RETURN VALUE:
-// TRUE - success
-// FALSE - failure
-//
-// COMMENTS:
-//
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
- DWORD dwWin32ExitCode,
- DWORD dwWaitHint)
-{
- static DWORD dwCheckPoint = 1;
- BOOL fResult = TRUE;
-
-
- if ( !bDebug ) // when debugging we don't report to the SCM
- {
- if (dwCurrentState == SERVICE_START_PENDING)
- ssStatus.dwControlsAccepted = 0;
- else
- ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
-
- ssStatus.dwCurrentState = dwCurrentState;
- ssStatus.dwWin32ExitCode = dwWin32ExitCode;
- ssStatus.dwWaitHint = dwWaitHint;
-
- if ( ( dwCurrentState == SERVICE_RUNNING ) ||
- ( dwCurrentState == SERVICE_STOPPED ) )
- ssStatus.dwCheckPoint = 0;
- else
- ssStatus.dwCheckPoint = dwCheckPoint++;
-
-
- // Report the status of the service to the service control manager.
- //
- if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) {
- AddToMessageLog(TEXT("SetServiceStatus"));
- }
- }
- return fResult;
-}
-
-
-
-//
-// FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
-//
-// PURPOSE: Allows any thread to log an error message
-//
-// PARAMETERS:
-// lpszMsg - text for message
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-//
-void AddToMessageLog(LPTSTR lpszMsg)
-{
- TCHAR szMsg[256];
- HANDLE hEventSource;
- LPTSTR lpszStrings[2];
-
-
- if ( !bDebug )
- {
- dwErr = GetLastError();
-
- // Use event logging to log the error.
- //
- hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));
-
- _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
- lpszStrings[0] = szMsg;
- lpszStrings[1] = lpszMsg;
-
- if (hEventSource != NULL) {
- ReportEvent(hEventSource, // handle of event source
- EVENTLOG_ERROR_TYPE, // event type
- 0, // event category
- 0, // event ID
- NULL, // current user's SID
- 2, // strings in lpszStrings
- 0, // no bytes of raw data
- lpszStrings, // array of error strings
- NULL); // no raw data
-
- DeregisterEventSource(hEventSource);
- }
- }
-}
-
-
-
-
-///////////////////////////////////////////////////////////////////
-//
-// The following code handles service installation and removal
-//
-
-
-//
-// FUNCTION: CmdInstallService()
-//
-// PURPOSE: Installs the service
-//
-// PARAMETERS:
-// none
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-//
-void CmdInstallService()
-{
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- TCHAR szPath[512];
-
- if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
- {
- _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
- return;
- }
-
- schSCManager = OpenSCManager(
- NULL, // machine (NULL == local)
- NULL, // database (NULL == default)
- SC_MANAGER_ALL_ACCESS // access required
- );
- if ( schSCManager )
- {
- schService = CreateService(
- schSCManager, // SCManager database
- TEXT(SZSERVICENAME), // name of service
- TEXT(SZSERVICEDISPLAYNAME), // name to display
- SERVICE_ALL_ACCESS, // desired access
- SERVICE_WIN32_OWN_PROCESS, // service type
- SERVICE_DEMAND_START, // start type
- SERVICE_ERROR_NORMAL, // error control type
- szPath, // service's binary
- NULL, // no load ordering group
- NULL, // no tag identifier
- TEXT(SZDEPENDENCIES), // dependencies
- NULL, // LocalSystem account
- NULL); // no password
-
- if ( schService )
- {
- _tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
- CloseServiceHandle(schService);
- }
- else
- {
- _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
- }
-
- CloseServiceHandle(schSCManager);
- }
- else
- _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
-}
-
-
-
-//
-// FUNCTION: CmdRemoveService()
-//
-// PURPOSE: Stops and removes the service
-//
-// PARAMETERS:
-// none
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-//
-void CmdRemoveService()
-{
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- schSCManager = OpenSCManager(
- NULL, // machine (NULL == local)
- NULL, // database (NULL == default)
- SC_MANAGER_ALL_ACCESS // access required
- );
- if ( schSCManager )
- {
- schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);
-
- if (schService)
- {
- // try to stop the service
- if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
- {
- _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
- Sleep( 1000 );
-
- while( QueryServiceStatus( schService, &ssStatus ) )
- {
- if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
- {
- _tprintf(TEXT("."));
- Sleep( 1000 );
- }
- else
- break;
- }
-
- if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
- _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) );
- else
- _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) );
-
- }
-
- // now remove the service
- if( DeleteService(schService) )
- _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
- else
- _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));
-
-
- CloseServiceHandle(schService);
- }
- else
- _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
-
- CloseServiceHandle(schSCManager);
- }
- else
- _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
-}
-
-
-
-
-
-//
-// FUNCTION: CmdRestartService()
-//
-// PURPOSE: Stops and removes the service
-//
-// PARAMETERS:
-// none
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-//
-void CmdRestartService(char *szServiceName)
-{
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
-
- schSCManager = OpenSCManager(
- NULL, // machine (NULL == local)
- NULL, // database (NULL == default)
- SC_MANAGER_ALL_ACCESS // access required
- );
- if ( schSCManager )
- {
- schService = OpenService(schSCManager, TEXT(szServiceName), SERVICE_ALL_ACCESS);
- if (schService)
- {
- if(! ControlService( schService, SERVICE_CONTROL_INTERROGATE, &ssStatus ) )
- //if(QueryServiceStatus( schService, &ssStatus )==0)
- {
- if(GetLastError()==ERROR_SERVICE_NOT_ACTIVE)
- {
-
- //AddToMessageLog(TEXT("Start service..."));
- StartService( schService, 0,NULL);
- }
- else
- { ;
- //AddToMessageLog(TEXT("QueryService..."));
- //AddToMessageLog(TEXT(GetLastErrorText(szErr,256)));
- }
- }
- CloseServiceHandle(schService);
- }
- else
- { _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
- AddToMessageLog(TEXT("OpenService..."));
- AddToMessageLog(TEXT(GetLastErrorText(szErr,256)));
-
- }
- CloseServiceHandle(schSCManager);
- }
- else
- { _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
- AddToMessageLog(TEXT("OpenSCMManager.."));
-
- }
-}
-
-
-
-
-///////////////////////////////////////////////////////////////////
-//
-// The following code is for running the service as a console app
-//
-
-
-//
-// FUNCTION: CmdDebugService(int argc, char ** argv)
-//
-// PURPOSE: Runs the service as a console application
-//
-// PARAMETERS:
-// argc - number of command line arguments
-// argv - array of command line arguments
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-//
-void CmdDebugService(int argc, char ** argv)
-{
- DWORD dwArgc;
- LPTSTR *lpszArgv;
-
-#ifdef UNICODE
- lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
-#else
- dwArgc = (DWORD) argc;
- lpszArgv = argv;
-#endif
-
- _tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
-
- SetConsoleCtrlHandler( ControlHandler, TRUE );
-
- ServiceStart( dwArgc, lpszArgv );
-}
-
-
-//
-// FUNCTION: ControlHandler ( DWORD dwCtrlType )
-//
-// PURPOSE: Handled console control events
-//
-// PARAMETERS:
-// dwCtrlType - type of control event
-//
-// RETURN VALUE:
-// True - handled
-// False - unhandled
-//
-// COMMENTS:
-//
-BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
-{
- switch( dwCtrlType )
- {
- case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
- case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
- _tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
- ServiceStop();
- return TRUE;
- break;
-
- }
- return FALSE;
-}
-
-//
-// FUNCTION: GetLastErrorText
-//
-// PURPOSE: copies error message text to string
-//
-// PARAMETERS:
-// lpszBuf - destination buffer
-// dwSize - size of buffer
-//
-// RETURN VALUE:
-// destination buffer
-//
-// COMMENTS:
-//
-LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
-{
- DWORD dwRet;
- LPTSTR lpszTemp = NULL;
-
- dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
- NULL,
- GetLastError(),
- LANG_NEUTRAL,
- (LPTSTR)&lpszTemp,
- 0,
- NULL );
-
- // supplied buffer is not long enough
- if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
- lpszBuf[0] = TEXT('\0');
- else
- {
- lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character
- _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
- }
-
- if ( lpszTemp )
- LocalFree((HLOCAL) lpszTemp );
-
- return lpszBuf;
-}
-
-//-------------------------------------------------
-// this event is signalled when the
-// service should end
-//-------------------------------------------------
-HANDLE hServerStopEvent = NULL;
-
-
-//-------------------------------------------------
-// FUNCTION: ServiceStart
-//
-// PURPOSE: Actual code of the service
-// that does the work.
-//-------------------------------------------------
-void ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
-{
- DWORD dwWait,dwTimeout=1000*60*1;
-
- if (!ReportStatusToSCMgr(
- SERVICE_START_PENDING, // service state
- NO_ERROR, // exit code
- 3000)) // wait hint
- goto cleanup;
-
- // create the event object. The control handler function signals
- // this event when it receives the "stop" control code.
- //
- hServerStopEvent = CreateEvent(
- NULL, // no security attributes
- TRUE, // manual reset event
- FALSE, // not-signalled
- NULL); // no name
-
- if ( hServerStopEvent == NULL) goto cleanup;
-
-
- // report the status to the service control manager.
- //
- if (!ReportStatusToSCMgr(
- SERVICE_START_PENDING, // service state
- NO_ERROR, // exit code
- 3000)) // wait hint
- goto cleanup;
-
-
-
- // report the status to the service control manager.
- //
- if (!ReportStatusToSCMgr(
- SERVICE_START_PENDING, // service state
- NO_ERROR, // exit code
- 3000)) // wait hint
- goto cleanup;
-
-
-
- // report the status to the service control manager.
- //
- if (!ReportStatusToSCMgr(
- SERVICE_RUNNING, // service state
- NO_ERROR, // exit code
- 0)) // wait hint
- goto cleanup;
-
- //
- // End of initialization
- // Service is now running, perform work until shutdown
- //
-
- while ( 1 )
- {
-
- dwWait = WaitForSingleObject( hServerStopEvent, dwTimeout);
- if(dwWait==WAIT_FAILED)
- {
- AddToMessageLog(TEXT("Error in WaitForSingleObject"));
- break;
- }
- else if(dwWait==WAIT_TIMEOUT)
- {
- CmdRestartService("MySql");
- }
- else
- { break; //shutdown
- }
-
- }
-
- cleanup:
-
- if (hServerStopEvent)
- CloseHandle(hServerStopEvent);
-
-}
-
-
-//-------------------------------------------------
-// FUNCTION: ServiceStop
-//
-// PURPOSE: Stops the service
-//-------------------------------------------------
-void ServiceStop()
-{
- if ( hServerStopEvent )
- SetEvent(hServerStopEvent);
-}
-//-the end ----------------------------------------
diff --git a/VC++Files/mysqlwatch/mysqlwatch.dsp b/VC++Files/mysqlwatch/mysqlwatch.dsp
deleted file mode 100644
index ee683c60351..00000000000
--- a/VC++Files/mysqlwatch/mysqlwatch.dsp
+++ /dev/null
@@ -1,70 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mysqlwatch" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=mysqlwatch - Win32 Release
-!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 "mysqlwatch.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 "mysqlwatch.mak" CFG="mysqlwatch - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mysqlwatch - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=xicl6.exe
-RSC=rc.exe
-# 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /W3 /O2 /D "_WINDOWS" /D "_MBCS" /D "NDEBUG" /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlwatch.exe"
-# Begin Target
-
-# Name "mysqlwatch - Win32 Release"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\mysqlwatch.c
-# 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/mysqlwatch/mysqlwatch_ia64.dsp b/VC++Files/mysqlwatch/mysqlwatch_ia64.dsp
deleted file mode 100644
index eb17b6991f8..00000000000
--- a/VC++Files/mysqlwatch/mysqlwatch_ia64.dsp
+++ /dev/null
@@ -1,71 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mysqlwatch" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=mysqlwatch - WinIA64 Release
-!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 "mysqlwatch_ia64.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 "mysqlwatch_ia64.mak" CFG="mysqlwatch - WinIA64 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mysqlwatch - WinIA64 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-# 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 ""
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /Zi /O2 /D "_WINDOWS" /D "_MBCS" /D "NDEBUG" /D "_IA64_" /D "WIN64" /D "WIN32" /D "_AFX_NO_DAO_SUPPORT" /FD /G2 /EHsc /Wp64 /Zm600 /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:IA64
-# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib bufferoverflowU.lib /nologo /subsystem:console /out:"../client_release/mysqlwatch.exe" /machine:IA64
-# Begin Target
-
-# Name "mysqlwatch - WinIA64 Release"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\mysqlwatch.c
-# 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/mysys/mysys.dsp b/VC++Files/mysys/mysys.dsp
index 2f3d7bb272c..935f1411530 100644
--- a/VC++Files/mysys/mysys.dsp
+++ b/VC++Files/mysys/mysys.dsp
@@ -209,6 +209,10 @@ SOURCE=.\default.c
# End Source File
# Begin Source File
+SOURCE=.\default_modify.c
+# End Source File
+# Begin Source File
+
SOURCE=.\errors.c
# End Source File
# Begin Source File
@@ -313,6 +317,10 @@ SOURCE=.\mf_tempfile.c
# End Source File
# Begin Source File
+SOURCE=.\mf_unixpath.c
+# End Source File
+# Begin Source File
+
SOURCE=.\mf_wcomp.c
# End Source File
# Begin Source File
@@ -457,6 +465,10 @@ SOURCE=.\my_mkdir.c
# End Source File
# Begin Source File
+SOURCE=.\my_mmap.c
+# End Source File
+# Begin Source File
+
SOURCE=.\my_net.c
# End Source File
# Begin Source File
@@ -529,10 +541,6 @@ SOURCE=.\my_sync.c
# End Source File
# Begin Source File
-SOURCE=.\my_tempnam.c
-# End Source File
-# Begin Source File
-
SOURCE=.\my_thr_init.c
# End Source File
# Begin Source File
@@ -545,7 +553,6 @@ SOURCE=.\my_windac.c
# End Source File
# Begin Source File
-
SOURCE=.\my_winsem.c
# End Source File
# Begin Source File
diff --git a/VC++Files/mysys/mysys.vcproj b/VC++Files/mysys/mysys.vcproj
new file mode 100755
index 00000000000..87e9338e811
--- /dev/null
+++ b/VC++Files/mysys/mysys.vcproj
@@ -0,0 +1,4792 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysys"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../zlib"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;USE_SYMDIR"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysys.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\mysys.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Max|Win32"
+ OutputDirectory=".\max"
+ IntermediateDirectory=".\max"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-max"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../zlib"
+ PreprocessorDefinitions="USE_SYMDIR;NDEBUG;DBUG_OFF;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\max/mysys.pch"
+ AssemblerListingLocation=".\max/"
+ ObjectFile=".\max/"
+ ProgramDataBaseFileName=".\max/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\mysys-max.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../zlib"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysys.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\mysys.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="TLS_DEBUG|Win32"
+ OutputDirectory=".\mysys___Win32_TLS_DEBUG"
+ IntermediateDirectory=".\mysys___Win32_TLS_DEBUG"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../zlib"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;USE_SYMDIR;USE_TLS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\mysys___Win32_TLS_DEBUG/mysys.pch"
+ AssemblerListingLocation=".\mysys___Win32_TLS_DEBUG/"
+ ObjectFile=".\mysys___Win32_TLS_DEBUG/"
+ ProgramDataBaseFileName=".\mysys___Win32_TLS_DEBUG/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\mysys_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="TLS|Win32"
+ OutputDirectory=".\mysys___Win32_TLS"
+ IntermediateDirectory=".\mysys___Win32_TLS"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../zlib"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG;USE_TLS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\mysys___Win32_TLS/mysys.pch"
+ AssemblerListingLocation=".\mysys___Win32_TLS/"
+ ObjectFile=".\mysys___Win32_TLS/"
+ ProgramDataBaseFileName=".\mysys___Win32_TLS/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\mysys_tls.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="array.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="charset-def.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="charset.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="checksum.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="default.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="default_modify.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="errors.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="list.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="md5.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_brkhant.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_cache.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_dirname.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_fn_ext.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_format.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_getdate.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_iocache.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_iocache2.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_keycache.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_keycaches.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_loadpath.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_pack.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_path.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_qsort.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_qsort2.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_radix.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_same.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_sort.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_soundex.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_strip.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_tempdir.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_tempfile.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\mf_unixpath.c">
+ </File>
+ <File
+ RelativePath="mf_wcomp.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mf_wfile.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mulalloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_access.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_aes.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_alarm.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_alloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_append.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_bit.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_bitmap.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_chsize.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_clock.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_compress.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_copy.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_crc32.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_create.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_delete.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_div.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_error.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_file.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_fopen.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_fstream.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_gethostbyname.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_gethwaddr.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_getopt.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_getsystime.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_getwd.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_handler.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_init.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_lib.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_lock.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_lockmem.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_lread.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_lwrite.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_malloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_messnc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_mkdir.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_mmap.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_net.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_once.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_open.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_pread.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_pthread.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_quick.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_read.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_realloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_redel.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_rename.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_seek.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_sleep.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_static.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_static.h">
+ </File>
+ <File
+ RelativePath="my_symlink.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_symlink2.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_sync.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_thr_init.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_wincond.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_windac.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_winsem.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_winthread.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_write.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mysys_priv.h">
+ </File>
+ <File
+ RelativePath="ptr_cmp.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="queues.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="raid.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="rijndael.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="safemalloc.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sha1.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="string.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="thr_alarm.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="thr_lock.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="EXTRA_DEBUG"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="EXTRA_DEBUG"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="thr_mutex.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="thr_rwlock.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tree.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="typelib.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS_DEBUG|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="TLS|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/mysys/mysys_ia64.dsp b/VC++Files/mysys/mysys_ia64.dsp
index 622ae1d5bce..10d6ca7960a 100644
--- a/VC++Files/mysys/mysys_ia64.dsp
+++ b/VC++Files/mysys/mysys_ia64.dsp
@@ -530,10 +530,6 @@ SOURCE=.\my_sync.c
# End Source File
# Begin Source File
-SOURCE=.\my_tempnam.c
-# End Source File
-# Begin Source File
-
SOURCE=.\my_thr_init.c
# End Source File
# Begin Source File
diff --git a/VC++Files/perror/perror.vcproj b/VC++Files/perror/perror.vcproj
new file mode 100755
index 00000000000..2a7bb6407c0
--- /dev/null
+++ b/VC++Files/perror/perror.vcproj
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="perror"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="WIN32;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/perror.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_classic/perror.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/perror.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\classic/perror.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/perror.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile="../client_release/perror.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\release/perror.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\release/perror.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/perror.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib"
+ OutputFile=".\Debug/perror.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/perror.pdb"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/perror.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\extra\perror.c">
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/prepare b/VC++Files/prepare
index e0dff9e04c0..f68d0676fc9 100755
--- a/VC++Files/prepare
+++ b/VC++Files/prepare
@@ -67,8 +67,6 @@ link_dir_dirs()
}
link_dir_files 'heap'
-link_dir_files 'isam'
-link_dir_files 'merge'
link_dir_files 'mysys'
link_dir_files 'zlib'
link_dir_files 'regex'
@@ -91,7 +89,6 @@ link_dir_dirs 'innobase'
ln -s $SRCDIR/myisam/myisampack.c $SRCDIR/VC++Files/myisampack/
ln -s $SRCDIR/client/mysqlbinlog.cc $SRCDIR/VC++Files/mysqlbinlog/mysqlbinlog.cpp
-ln -s $SRCDIR/isam/pack_isam.c $SRCDIR/VC++Files/pack_isam/pack_isam.c
echo '/* added for win : */' >> $SRCDIR/config.h
echo '#undef HAVE_SCHED_H' >> $SRCDIR/config.h
@@ -101,4 +98,4 @@ echo '/* added for win : */' >> $SRCDIR/innobase/ib_config.h
echo '#undef HAVE_SCHED_H' >> $SRCDIR/innobase/ib_config.h
cd $SRCDIR/VC++Files
-echo '1' > prepare_done \ No newline at end of file
+echo '1' > prepare_done
diff --git a/VC++Files/regex/regex.vcproj b/VC++Files/regex/regex.vcproj
new file mode 100755
index 00000000000..1b52017ca3b
--- /dev/null
+++ b/VC++Files/regex/regex.vcproj
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="regex"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,./"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/regex.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\regex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,./"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/regex.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\regex.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="debug.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="regcomp.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="regerror.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="regexec.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="regfree.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="reginit.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="split.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/replace/replace.vcproj b/VC++Files/replace/replace.vcproj
new file mode 100755
index 00000000000..270ff494539
--- /dev/null
+++ b/VC++Files/replace/replace.vcproj
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="replace"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/replace.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib setargv.obj"
+ OutputFile="../client_debug/replace.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\debug/replace.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/replace.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1035"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/replace.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib setargv.obj"
+ OutputFile="../client_release/replace.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\release/replace.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/replace.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1035"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;LICENSE=Commercial;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/replace.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib odbc32.lib odbccp32.lib setargv.obj"
+ OutputFile="../client_classic/replace.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ ProgramDatabaseFile=".\classic/replace.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/replace.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1035"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\extra\replace.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp
index 4034ac9f5d0..6db2aca8d1c 100644
--- a/VC++Files/sql/mysqld.dsp
+++ b/VC++Files/sql/mysqld.dsp
@@ -49,7 +49,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../zlib" /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../zlib" /I "../include" /I "../regex" /I "../extra/yassl/include" /D "NDEBUG" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x410 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -58,7 +58,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /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\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld.exe"
+# 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\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld.exe"
# SUBTRACT LINK32 /debug
!ELSEIF "$(CFG)" == "mysqld - Win32 Debug"
@@ -75,7 +75,7 @@ LINK32=xilink6.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_EXAMPLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../zlib" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_FEDERATED_DB" /D "HAVE_EXAMPLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /c
# SUBTRACT CPP /Fr /YX
# ADD BASE RSC /l 0x410 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
@@ -84,7 +84,7 @@ BSC32=bscmake.exe
# 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 /nologo /subsystem:console /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 Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\vio.lib ..\lib_debug\isam.lib ..\lib_debug\merge.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\bdb.lib ..\lib_debug\innodb.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqld-debug.exe" /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 Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\vio.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\bdb.lib ..\lib_debug\innodb.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqld-debug.exe" /pdbtype:sept
!ELSEIF "$(CFG)" == "mysqld - Win32 nt"
@@ -102,7 +102,7 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G5 /MT /W3 /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /D "DBUG_OFF" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-nt /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /I "../extra/yassl/include" /D "__NT__" /D "DBUG_OFF" /D "NDEBUG" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-nt /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x410 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -110,8 +110,8 @@ 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\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"
+# 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\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\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 ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-nt.exe"
# SUBTRACT LINK32 /pdb:none /debug
!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt"
@@ -130,7 +130,7 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_EXAMPLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-nt-max /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../zlib" /D "NDEBUG" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_EXAMPLE_DB" /D "HAVE_FEDERATED_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-nt-max /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -138,9 +138,9 @@ 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\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\zlib.lib /nologo /subsystem:console /map /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\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib /nologo /subsystem:console /map /machine:I386
# SUBTRACT BASE LINK32 /pdb:none /debug
-# 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-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-max-nt.exe"
+# 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\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /map /machine:I386 /out:"../client_release/mysqld-max-nt.exe"
# SUBTRACT LINK32 /pdb:none /debug
!ELSEIF "$(CFG)" == "mysqld - Win32 Max"
@@ -159,7 +159,7 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /D "NDEBUG" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../zlib" /D "NDEBUG" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_EXAMPLE_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-max /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../bdb/build_win32" /I "../include" /I "../regex" /I "../extra/yassl/include" /I "../zlib" /D "NDEBUG" /D "DBUG_OFF" /D "USE_SYMDIR" /D "HAVE_INNOBASE_DB" /D "HAVE_BERKELEY_DB" /D "HAVE_ARCHIVE_DB" /D "HAVE_BLACKHOLE_DB" /D "HAVE_EXAMPLE_DB" /D "HAVE_FEDERATED_DB" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-max /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -167,8 +167,8 @@ 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\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 /pdb:none /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-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-max.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\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /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\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys-max.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_release/mysqld-max.exe"
# SUBTRACT LINK32 /debug
!ELSEIF "$(CFG)" == "mysqld - Win32 classic"
@@ -187,16 +187,16 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D LICENSE=Commercial /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "HAVE_DLOPEN" /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /D MYSQL_SERVER_SUFFIX=-classic /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /I "../extra/yassl/include" /D LICENSE=Commercial /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "HAVE_DLOPEN" /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /D MYSQL_SERVER_SUFFIX=-classic /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
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\vio.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 /pdb:none /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\vio.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386
# SUBTRACT BASE LINK32 /debug
-# 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\zlib.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_classic/mysqld.exe" /libpath:"..\lib_release"
+# 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\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_classic/mysqld.exe" /libpath:"..\lib_release"
# SUBTRACT LINK32 /debug
!ELSEIF "$(CFG)" == "mysqld - Win32 pro"
@@ -215,16 +215,16 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "MYSQL_SERVER" /D LICENSE=Commercial /D "_MBCS" /D "HAVE_DLOPEN" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "DBUG_OFF" /D "NDEBUG" /D "_WINDOWS" /D "_CONSOLE" /D MYSQL_SERVER_SUFFIX=-pro /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /I "../extra/yassl/include" /D "MYSQL_SERVER" /D LICENSE=Commercial /D "_MBCS" /D "HAVE_DLOPEN" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "DBUG_OFF" /D "NDEBUG" /D "_WINDOWS" /D "_CONSOLE" /D MYSQL_SERVER_SUFFIX=-pro /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
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\vio.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 /pdb:none /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\vio.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386
# SUBTRACT BASE LINK32 /debug
-# 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 /pdb:none /machine:I386 /out:"../client_pro/mysqld.exe" /libpath:"..\lib_release"
+# 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\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 ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_pro/mysqld.exe" /libpath:"..\lib_release"
# SUBTRACT LINK32 /debug
!ELSEIF "$(CFG)" == "mysqld - Win32 classic nt"
@@ -243,7 +243,7 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /D LICENSE=Commercial /D MYSQL_SERVER_SUFFIX=-classic-nt /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /I "../extra/yassl/include" /D "__NT__" /D "DBUG_OFF" /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /D LICENSE=Commercial /D MYSQL_SERVER_SUFFIX=-classic-nt /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -251,9 +251,9 @@ 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\vio.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 /pdb:none /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\vio.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386
# SUBTRACT BASE LINK32 /debug
-# 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\zlib.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_classic/mysqld-nt.exe" /libpath:"..\lib_release"
+# 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\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_classic/mysqld-nt.exe" /libpath:"..\lib_release"
# SUBTRACT LINK32 /debug
!ELSEIF "$(CFG)" == "mysqld - Win32 pro nt"
@@ -272,16 +272,17 @@ LINK32=xilink6.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D LICENSE=Commercial /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-pro-nt /FD
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /I "../extra/yassl/include" /D "__NT__" /D "DBUG_OFF" /D "NDEBUG" /D "HAVE_INNOBASE_DB" /D "HAVE_ARCHIVE_DB" /D "MYSQL_SERVER" /D LICENSE=Commercial /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-pro-nt /FD /c
+# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
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\vio.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 /pdb:none /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\vio.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib /nologo /subsystem:console /pdb:none /machine:I386
# SUBTRACT BASE LINK32 /debug
-# 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 /pdb:none /machine:I386 /out:"../client_pro/mysqld-nt.exe" /libpath:"..\lib_release"
+# 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\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 ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../client_pro/mysqld-nt.exe" /libpath:"..\lib_release"
# SUBTRACT LINK32 /debug
!ENDIF
@@ -355,6 +356,10 @@ SOURCE=.\derror.cpp
# End Source File
# Begin Source File
+SOURCE=.\des_key_file.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\discover.cpp
# End Source File
# Begin Source File
@@ -463,23 +468,19 @@ SOURCE=.\ha_blackhole.cpp
# End Source File
# Begin Source File
-SOURCE=.\ha_berkeley.cpp
+SOURCE=.\ha_federated.cpp
# End Source File
# Begin Source File
-SOURCE=.\ha_heap.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ha_innodb.cpp
+SOURCE=.\ha_berkeley.cpp
# End Source File
# Begin Source File
-SOURCE=.\ha_isam.cpp
+SOURCE=.\ha_heap.cpp
# End Source File
# Begin Source File
-SOURCE=.\ha_isammrg.cpp
+SOURCE=.\ha_innodb.cpp
# End Source File
# Begin Source File
@@ -1100,8 +1101,16 @@ SOURCE=.\mf_iocache.cpp
!ELSEIF "$(CFG)" == "mysqld - Win32 pro nt"
-!ENDIF
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\my_decimal.cpp
+# End Source File
+# Begin Source File
+SOURCE=.\my_time.c
# End Source File
# Begin Source File
@@ -1211,7 +1220,7 @@ SOURCE=.\pack.c
# End Source File
# Begin Source File
-SOURCE=.\my_time.c
+SOURCE=.\parse_file.cpp
# End Source File
# Begin Source File
@@ -1274,6 +1283,10 @@ SOURCE=.\protocol.cpp
# End Source File
# Begin Source File
+SOURCE=.\protocol_cursor.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\records.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
@@ -1314,6 +1327,26 @@ SOURCE=.\slave.cpp
# End Source File
# Begin Source File
+SOURCE=.\sp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sp_cache.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sp_head.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sp_pcontext.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sp_rcontext.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\spatial.cpp
# End Source File
# Begin Source File
@@ -1826,6 +1859,10 @@ SOURCE=.\sql_test.cpp
# End Source File
# Begin Source File
+SOURCE=.\sql_trigger.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_udf.cpp
# End Source File
# Begin Source File
@@ -1857,8 +1894,12 @@ SOURCE=.\sql_update.cpp
!ELSEIF "$(CFG)" == "mysqld - Win32 pro nt"
-!ENDIF
+!ENDIF
+
+# End Source File
+# Begin Source File
+SOURCE=.\sql_view.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/sql/mysqld.vcproj b/VC++Files/sql/mysqld.vcproj
new file mode 100755
index 00000000000..db84f081ac8
--- /dev/null
+++ b/VC++Files/sql/mysqld.vcproj
@@ -0,0 +1,8659 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqld"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="classic nt|Win32"
+ OutputDirectory=".\classic_nt"
+ IntermediateDirectory=".\classic_nt"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-classic-nt"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../regex,../zlib,../extra/yassl/include"
+ PreprocessorDefinitions="__NT__;DBUG_OFF;NDEBUG;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN;LICENSE=Commercial"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic_nt/mysqld.pch"
+ AssemblerListingLocation=".\classic_nt/"
+ ObjectFile=".\classic_nt/"
+ ProgramDataBaseFileName=".\classic_nt/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_classic/mysqld-nt.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic_nt/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Max|Win32"
+ OutputDirectory=".\max"
+ IntermediateDirectory=".\max"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-max"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../bdb/build_win32,../include,../regex,../extra/yassl/include,../zlib"
+ PreprocessorDefinitions="NDEBUG;DBUG_OFF;USE_SYMDIR;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\max/mysqld.pch"
+ AssemblerListingLocation=".\max/"
+ ObjectFile=".\max/"
+ ProgramDataBaseFileName=".\max/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_release/mysqld-max.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\max/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Max nt|Win32"
+ OutputDirectory=".\max_nt"
+ IntermediateDirectory=".\max_nt"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-nt-max"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../bdb/build_win32,../include,../regex,../extra/yassl/include,../zlib"
+ PreprocessorDefinitions="NDEBUG;__NT__;DBUG_OFF;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\max_nt/mysqld.pch"
+ AssemblerListingLocation=".\max_nt/"
+ ObjectFile=".\max_nt/"
+ ProgramDataBaseFileName=".\max_nt/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_release/mysqld-max-nt.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\max_nt/mysqld-max-nt.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName=".\max_nt/mysqld-max-nt.map"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\max_nt/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="nt|Win32"
+ OutputDirectory=".\nt"
+ IntermediateDirectory=".\nt"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-nt"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../regex,../zlib,../extra/yassl/include"
+ PreprocessorDefinitions="__NT__;DBUG_OFF;NDEBUG;HAVE_INNOBASE_DB;HAVE_ARCHIVE_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\nt/mysqld.pch"
+ AssemblerListingLocation=".\nt/"
+ ObjectFile=".\nt/"
+ ProgramDataBaseFileName=".\nt/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_release/mysqld-nt.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\nt/mysqld-nt.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName=".\nt/mysqld-nt.map"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\nt/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="pro nt|Win32"
+ OutputDirectory=".\pro_nt"
+ IntermediateDirectory=".\pro_nt"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-pro-nt"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../regex,../zlib,../extra/yassl/include"
+ PreprocessorDefinitions="__NT__;DBUG_OFF;NDEBUG;HAVE_INNOBASE_DB;HAVE_ARCHIVE_DB;MYSQL_SERVER;LICENSE=Commercial;_WINDOWS;_CONSOLE;HAVE_DLOPEN"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\pro_nt/mysqld.pch"
+ AssemblerListingLocation=".\pro_nt/"
+ ObjectFile=".\pro_nt/"
+ ProgramDataBaseFileName=".\pro_nt/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_pro/mysqld-nt.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\pro_nt/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../bdb/build_win32,../include,../regex,../extra/yassl/include,../zlib"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/mysqld.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_debug/mysqld-debug.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/mysqld-debug.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="pro|Win32"
+ OutputDirectory=".\pro"
+ IntermediateDirectory=".\pro"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-pro"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../regex,../zlib,../extra/yassl/include"
+ PreprocessorDefinitions="MYSQL_SERVER;LICENSE=Commercial;HAVE_DLOPEN;HAVE_INNOBASE_DB;HAVE_ARCHIVE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\pro/mysqld.pch"
+ AssemblerListingLocation=".\pro/"
+ ObjectFile=".\pro/"
+ ProgramDataBaseFileName=".\pro/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_pro/mysqld.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\pro/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="classic|Win32"
+ OutputDirectory=".\classic"
+ IntermediateDirectory=".\classic"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D MYSQL_SERVER_SUFFIX=-classic"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../regex,../zlib,../extra/yassl/include"
+ PreprocessorDefinitions="LICENSE=Commercial;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN;DBUG_OFF;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\classic/mysqld.pch"
+ AssemblerListingLocation=".\classic/"
+ ObjectFile=".\classic/"
+ ProgramDataBaseFileName=".\classic/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_classic/mysqld.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories=""
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\classic/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../zlib,../include,../regex,../extra/yassl/include"
+ PreprocessorDefinitions="NDEBUG;DBUG_OFF;HAVE_INNOBASE_DB;HAVE_ARCHIVE_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/mysqld.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
+ OutputFile="../client_release/mysqld.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/mysqld.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="client.c">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="derror.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="des_key_file.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="discover.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\libmysql\errmsg.c">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="field.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="field_conv.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="filesort.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="gstream.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="examples\ha_archive.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="examples\ha_example.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha_berkeley.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha_blackhole.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha_federated.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha_heap.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha_innodb.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha_myisam.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ha_myisammrg.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="handler.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash_filo.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="hash_filo.h">
+ </File>
+ <File
+ RelativePath="hostname.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="init.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_buff.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_cmpfunc.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_create.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_func.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_geofunc.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_row.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_strfunc.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_subselect.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_sum.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_timefunc.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="item_uniq.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="key.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lock.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="log_event.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="message.mc">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="mc message.mc
+"
+ Outputs="message.rc;message.h"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="message.rc">
+ </File>
+ <File
+ RelativePath="mf_iocache.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_decimal.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_time.c">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\myisammrg\myrg_rnext_same.c">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mysqld.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="net_serv.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="nt_servc.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="nt_servc.h">
+ </File>
+ <File
+ RelativePath="opt_range.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="opt_range.h">
+ </File>
+ <File
+ RelativePath="OPT_SUM.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pack.c">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="parse_file.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="password.c">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="procedure.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="protocol.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="protocol_cursor.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="records.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="repl_failsafe.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="set_var.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="slave.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sp.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sp_cache.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sp_head.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sp_pcontext.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sp_rcontext.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="spatial.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_acl.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_analyse.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_base.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_cache.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_class.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_client.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_crypt.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_crypt.h">
+ </File>
+ <File
+ RelativePath="sql_db.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_delete.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_derived.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_do.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_error.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_handler.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_help.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_insert.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_lex.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_list.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_load.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_manager.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_map.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_parse.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_prepare.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_rename.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_repl.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_select.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_show.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_state.c">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_string.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_table.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_test.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_trigger.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_udf.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_union.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_update.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_view.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="sql_yacc.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strfunc.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="table.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="thr_malloc.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="time.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tztime.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="uniques.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="unireg.cpp">
+ <FileConfiguration
+ Name="classic nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Max nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro nt|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="pro|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="classic|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/sql/mysqldmax.dsp b/VC++Files/sql/mysqldmax.dsp
index a7ed1b918c7..2711b274da0 100644
--- a/VC++Files/sql/mysqldmax.dsp
+++ b/VC++Files/sql/mysqldmax.dsp
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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\isam.lib ..\lib_release\merge.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innobase-opt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../client_release/mysqld-max-opt.exe"
+# 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\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innobase-opt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../client_release/mysqld-max-opt.exe"
!ELSEIF "$(CFG)" == "mysqldmax - Win32 Debug"
@@ -75,7 +75,7 @@ BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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 Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\isam.lib ..\lib_debug\merge.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_release\innobase-opt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /incremental:no /pdb:"debug/mysqld.pdb" /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../client_debug/mysqld-max.exe" /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 Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_release\innobase-opt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /incremental:no /pdb:"debug/mysqld.pdb" /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../client_debug/mysqld-max.exe" /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "mysqldmax - Win32 nt"
@@ -100,7 +100,7 @@ BSC32=bscmake.exe
# 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /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\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\zlib.lib ..\lib_release\innobase-nt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /pdb:"NT/mysqld-nt.pdb" /map:"NT/mysqld-nt.map" /machine:I386 /nodefaultlib:"LIBC" /out:"../client_release/mysqld-max-nt.exe"
+# 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\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\zlib.lib ..\lib_release\innobase-nt.lib ..\lib_release\libdb32s.lib /nologo /subsystem:console /pdb:"NT/mysqld-nt.pdb" /map:"NT/mysqld-nt.map" /machine:I386 /nodefaultlib:"LIBC" /out:"../client_release/mysqld-max-nt.exe"
# SUBTRACT LINK32 /pdb:none
!ENDIF
@@ -204,14 +204,6 @@ SOURCE=.\ha_innobase.cpp
# End Source File
# Begin Source File
-SOURCE=.\ha_isam.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ha_isammrg.cpp
-# End Source File
-# Begin Source File
-
SOURCE=.\ha_myisam.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/strings/backup/strings.dsp b/VC++Files/strings/backup/strings.dsp
index a6be39b40ab..dcff9915f13 100644
--- a/VC++Files/strings/backup/strings.dsp
+++ b/VC++Files/strings/backup/strings.dsp
@@ -238,7 +238,12 @@ InputName=Strxmov
# End Source File
# Begin Source File
-SOURCE=.\strxnmov.c
+SOURCE=.\strxnmov.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\str_alloc.c
# End Source File
+
# End Target
# End Project
diff --git a/VC++Files/strings/noMASM/strings.dsp b/VC++Files/strings/noMASM/strings.dsp
index ffec20f3a59..e7a0395c3df 100644
--- a/VC++Files/strings/noMASM/strings.dsp
+++ b/VC++Files/strings/noMASM/strings.dsp
@@ -256,6 +256,10 @@ SOURCE=.\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=.\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=.\xml.c
# End Source File
# End Target
diff --git a/VC++Files/strings/strings.dsp b/VC++Files/strings/strings.dsp
index d1156702956..714359c5570 100644
--- a/VC++Files/strings/strings.dsp
+++ b/VC++Files/strings/strings.dsp
@@ -121,6 +121,10 @@ SOURCE=".\ctype-czech.c"
# End Source File
# Begin Source File
+SOURCE=".\ctype-eucjpms.c"
+# End Source File
+# Begin Source File
+
SOURCE=".\ctype-euc_kr.c"
# End Source File
# Begin Source File
@@ -181,6 +185,10 @@ SOURCE=.\ctype.c
# End Source File
# Begin Source File
+SOURCE=.\decimal.c
+# End Source File
+# Begin Source File
+
SOURCE=.\int2str.c
# End Source File
# Begin Source File
@@ -265,6 +273,10 @@ SOURCE=.\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=.\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=.\xml.c
# End Source File
# End Target
diff --git a/VC++Files/strings/strings.vcproj b/VC++Files/strings/strings.vcproj
new file mode 100755
index 00000000000..8e16a0c7221
--- /dev/null
+++ b/VC++Files/strings/strings.vcproj
@@ -0,0 +1,1034 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="strings"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/strings.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\strings.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/strings.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\strings.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="bchange.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="bcmp.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="bfill.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="bmove512.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="bmove_upp.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-big5.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-bin.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-cp932.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-czech.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-euc_kr.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-eucjpms.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-extra.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-gb2312.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-gbk.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-latin1.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-mb.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-simple.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-sjis.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-tis620.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-uca.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-ucs2.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-ujis.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-utf8.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype-win1250ch.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ctype.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="decimal.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="int2str.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="is_prefix.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="llstr.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="longlong2str.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_strtoll10.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="my_vsnprintf.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="r_strinstr.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="str2int.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\str_alloc.c">
+ </File>
+ <File
+ RelativePath="strcend.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strend.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strfill.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strmake.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strmov.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strnmov.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strtod.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strtol.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strtoll.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strtoul.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strtoull.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strxmov.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="strxnmov.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="xml.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/strings/strings_ia64.dsp b/VC++Files/strings/strings_ia64.dsp
index edbcdee2f11..0ccb4f62928 100644
--- a/VC++Files/strings/strings_ia64.dsp
+++ b/VC++Files/strings/strings_ia64.dsp
@@ -112,6 +112,10 @@ SOURCE=".\ctype-bin.c"
# End Source File
# Begin Source File
+SOURCE=".\ctype-cp932.c"
+# End Source File
+# Begin Source File
+
SOURCE=".\ctype-czech.c"
# End Source File
# Begin Source File
@@ -124,6 +128,10 @@ SOURCE=".\ctype-euc_kr.c"
# End Source File
# Begin Source File
+SOURCE=".\ctype-eucjpms.c"
+# End Source File
+# Begin Source File
+
SOURCE=".\ctype-extra.c"
# End Source File
# Begin Source File
@@ -264,6 +272,10 @@ SOURCE=.\strxnmov.c
# End Source File
# Begin Source File
+SOURCE=.\str_alloc.c
+# End Source File
+# Begin Source File
+
SOURCE=.\xml.c
# End Source File
# End Target
diff --git a/VC++Files/test1/mysql_thr.c b/VC++Files/test1/mysql_thr.c
index fac5c37a9af..c2743cb8e4c 100644
--- a/VC++Files/test1/mysql_thr.c
+++ b/VC++Files/test1/mysql_thr.c
@@ -167,6 +167,7 @@ pthread_handler_decl(test_thread,arg)
perror("");
goto end;
}
+ mysql.reconnect= 1;
if (mysql_query(&mysql,"select 1") < 0)
{
fprintf(stderr,"Query failed (%s)\n",mysql_error(&mysql));
diff --git a/VC++Files/test1/test1.vcproj b/VC++Files/test1/test1.vcproj
new file mode 100755
index 00000000000..6a850f7b2e3
--- /dev/null
+++ b/VC++Files/test1/test1.vcproj
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="test1"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/test1.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\release/test1.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\release/test1.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/test1.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="_DEBUG;_CONSOLE;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/test1.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libmysql.lib odbc32.lib odbccp32.lib"
+ OutputFile=".\debug/test1.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\lib_debug"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/test1.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/test1.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="mysql_thr.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ RuntimeLibrary="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/tests/mysql_client_test.dsp b/VC++Files/tests/mysql_client_test.dsp
index 012129a208b..7d821b45f2b 100644
--- a/VC++Files/tests/mysql_client_test.dsp
+++ b/VC++Files/tests/mysql_client_test.dsp
@@ -51,8 +51,8 @@ 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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_debug\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console
-# 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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_debug\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console
+# 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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib ..\extra\yassl\Debug\yassl.lib /nologo /out:"..\client_debug\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console
+# 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 odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib ..\extra\yassl\Debug\yassl.lib /nologo /out:"..\client_debug\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console
!ELSEIF "$(CFG)" == "mysql_client_test - Win32 Release"
@@ -76,8 +76,8 @@ 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 odbc32.lib odbccp32.lib Ws2_32.lib mysqlclient.lib mysys.lib regex.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console
-# 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 odbc32.lib odbccp32.lib Ws2_32.lib mysqlclient.lib mysys.lib regex.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console
+# 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 odbc32.lib odbccp32.lib Ws2_32.lib mysqlclient.lib mysys.lib regex.lib ..\extra\yassl\Release\yassl.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console
+# 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 odbc32.lib odbccp32.lib Ws2_32.lib mysqlclient.lib mysys.lib regex.lib ..\extra\yassl\Release\yassl.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console
!ENDIF
diff --git a/VC++Files/tests/mysql_client_test.vcproj b/VC++Files/tests/mysql_client_test.vcproj
new file mode 100755
index 00000000000..adcc680b6e7
--- /dev/null
+++ b/VC++Files/tests/mysql_client_test.vcproj
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysql_client_test"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;__WIN__;_WIN32"
+ StringPooling="TRUE"
+ RuntimeLibrary="1"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\Release/mysql_client_test.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Ws2_32.lib mysqlclient.lib mysys.lib regex.lib ..\extra\yassl\Release\yassl.lib"
+ OutputFile="..\client_release\mysql_client_test.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\lib_release\"
+ ProgramDatabaseFile=".\Release/mysql_client_test.pdb"
+ SubSystem="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/mysql_client_test.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../"
+ PreprocessorDefinitions="_DEBUG;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;__WIN__;_WIN32"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/mysql_client_test.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib ..\extra\yassl\Debug\yassl.lib"
+ OutputFile="..\client_debug\mysql_client_test.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\lib_debug\"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/mysql_client_test.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName=".\Debug/mysql_client_test.map"
+ SubSystem="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/mysql_client_test.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="mysql_client_test.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/thr_test/thr_test.vcproj b/VC++Files/thr_test/thr_test.vcproj
new file mode 100755
index 00000000000..ede9bd04de8
--- /dev/null
+++ b/VC++Files/thr_test/thr_test.vcproj
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="thr_test"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="__WIN32__;_DEBUG;SAFEMALLOC;SAFE_MUTEX;_CONSOLE;_WINDOWS"
+ ExceptionHandling="FALSE"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/thr_test.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\debug/thr_test.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\debug/thr_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\debug/thr_test.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1035"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include"
+ PreprocessorDefinitions="DBUG_OFF;_CONSOLE;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ ExceptionHandling="FALSE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/thr_test.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\release/thr_test.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\release/thr_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\release/thr_test.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1035"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="thr_test.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ AssemblerOutput="2"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ OptimizeForProcessor="1"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/vio/vio.dsp b/VC++Files/vio/vio.dsp
index 5daa5800dbd..f7971823937 100644
--- a/VC++Files/vio/vio.dsp
+++ b/VC++Files/vio/vio.dsp
@@ -41,7 +41,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../extra/yassl/include" /D "DBUG_OFF" /D "_WINDOWS" /D "NDEBUG" /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -64,7 +64,7 @@ LIB32=xilink6.exe -lib
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_SYMDIR" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Z7 /Od /I "../include" /I "../extra/yassl/include" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_WINDOWS" /D "USE_SYMDIR" /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
diff --git a/VC++Files/vio/vio.vcproj b/VC++Files/vio/vio.vcproj
new file mode 100755
index 00000000000..3f50c1546fb
--- /dev/null
+++ b/VC++Files/vio/vio.vcproj
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="vio"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../extra/yassl/include"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/vio.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\vio.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ AdditionalIncludeDirectories="../include,../extra/yassl/include"
+ PreprocessorDefinitions="_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;USE_SYMDIR"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/vio.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\vio.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="vio.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="viosocket.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="viossl.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="viosslfactories.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/VC++Files/winmysqladmin/db.cpp b/VC++Files/winmysqladmin/db.cpp
deleted file mode 100644
index 6e796856a7e..00000000000
--- a/VC++Files/winmysqladmin/db.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-//---------------------------------------------------------------------------
-#include <vcl.h>
-#pragma hdrstop
-
-#include "db.h"
-#include "main.h"
-//---------------------------------------------------------------------------
-#pragma package(smart_init)
-#pragma resource "*.dfm"
-Tdbfrm *dbfrm;
-//---------------------------------------------------------------------------
-__fastcall Tdbfrm::Tdbfrm(TComponent* Owner)
- : TForm(Owner)
-{
-}
-//---------------------------------------------------------------------------
-void __fastcall Tdbfrm::SpeedButton2Click(TObject *Sender)
-{
- Close();
-}
-//---------------------------------------------------------------------------
-void __fastcall Tdbfrm::SpeedButton1Click(TObject *Sender)
-{
- if (VerDBName())
- {
- if (!Form1->CreatingDB())
- {
- Form1->OutRefresh();
- Edit1->Text = "";
- Application->MessageBox("The database was created", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- }
- }
-
-
-
-
-
-}
-//---------------------------------------------------------------------------
-bool __fastcall Tdbfrm::VerDBName()
-{
- String temp = Edit1->Text;
- if (Edit1->Text.IsEmpty())
- {
- Application->MessageBox("The name of the Database is Empty", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- return false;
- }
-
- if (temp.Length() > 64)
- {
- Application->MessageBox("The name of the Database can't have more than 64 characters ", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- return false;
- }
-
- for (int j = 1; j <= temp.Length(); j++)
- {
- if (temp[j] == ' ')
- {
- Application->MessageBox("The name of the Database can't have blank spaces ", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- return false;
- }
- else if (temp[j] == '/')
- {
- Application->MessageBox("The name of the Database can't have frontslash (/)", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- return false;
- }
- else if (temp[j] == '\\')
- {
- Application->MessageBox("The name of the Database can't have backslash (\\)", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- return false;
- }
- else if (temp[j] == '.')
- {
- Application->MessageBox("The name of the Database can't have periods", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- return false;
- }
- }
- return true;
-}
-//---------------------------------------------------------------------------
diff --git a/VC++Files/winmysqladmin/db.h b/VC++Files/winmysqladmin/db.h
deleted file mode 100644
index f7ab87351ea..00000000000
--- a/VC++Files/winmysqladmin/db.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//---------------------------------------------------------------------------
-#ifndef dbH
-#define dbH
-//---------------------------------------------------------------------------
-#include <Classes.hpp>
-#include <Controls.hpp>
-#include <StdCtrls.hpp>
-#include <Forms.hpp>
-#include <ExtCtrls.hpp>
-#include <Graphics.hpp>
-#include <Buttons.hpp>
-//---------------------------------------------------------------------------
-class Tdbfrm : public TForm
-{
-__published: // IDE-managed Components
- TImage *Image1;
- TLabel *Label1;
- TLabel *Label2;
- TEdit *Edit1;
- TSpeedButton *SpeedButton1;
- TSpeedButton *SpeedButton2;
- void __fastcall SpeedButton2Click(TObject *Sender);
- void __fastcall SpeedButton1Click(TObject *Sender);
-private: // User declarations
- bool __fastcall VerDBName();
-public: // User declarations
- __fastcall Tdbfrm(TComponent* Owner);
-};
-//---------------------------------------------------------------------------
-extern PACKAGE Tdbfrm *dbfrm;
-//---------------------------------------------------------------------------
-#endif
diff --git a/VC++Files/winmysqladmin/images/Goahead.ico b/VC++Files/winmysqladmin/images/Goahead.ico
deleted file mode 100644
index 8241c90e2a2..00000000000
--- a/VC++Files/winmysqladmin/images/Goahead.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/HELP.ICO b/VC++Files/winmysqladmin/images/HELP.ICO
deleted file mode 100644
index d0cd6d68cce..00000000000
--- a/VC++Files/winmysqladmin/images/HELP.ICO
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/INFO.ICO b/VC++Files/winmysqladmin/images/INFO.ICO
deleted file mode 100644
index e3afa8cf52c..00000000000
--- a/VC++Files/winmysqladmin/images/INFO.ICO
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/Info.bmp b/VC++Files/winmysqladmin/images/Info.bmp
deleted file mode 100644
index 58f729fb1fd..00000000000
--- a/VC++Files/winmysqladmin/images/Info.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/MYINI.ICO b/VC++Files/winmysqladmin/images/MYINI.ICO
deleted file mode 100644
index 428ed8e92b0..00000000000
--- a/VC++Files/winmysqladmin/images/MYINI.ICO
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/Myini.bmp b/VC++Files/winmysqladmin/images/Myini.bmp
deleted file mode 100644
index e743a1b9b32..00000000000
--- a/VC++Files/winmysqladmin/images/Myini.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/Noentry.ico b/VC++Files/winmysqladmin/images/Noentry.ico
deleted file mode 100644
index 27f2211f56c..00000000000
--- a/VC++Files/winmysqladmin/images/Noentry.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/SETUP.BMP b/VC++Files/winmysqladmin/images/SETUP.BMP
deleted file mode 100644
index c5794e5ac00..00000000000
--- a/VC++Files/winmysqladmin/images/SETUP.BMP
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/Setup 16.bmp b/VC++Files/winmysqladmin/images/Setup 16.bmp
deleted file mode 100644
index e17b06155fb..00000000000
--- a/VC++Files/winmysqladmin/images/Setup 16.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/Table.ico b/VC++Files/winmysqladmin/images/Table.ico
deleted file mode 100644
index 4469a915b7f..00000000000
--- a/VC++Files/winmysqladmin/images/Table.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/Working.ico b/VC++Files/winmysqladmin/images/Working.ico
deleted file mode 100644
index 72faedbbfc5..00000000000
--- a/VC++Files/winmysqladmin/images/Working.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/database.ico b/VC++Files/winmysqladmin/images/database.ico
deleted file mode 100644
index 9689aa88361..00000000000
--- a/VC++Files/winmysqladmin/images/database.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/find.ico b/VC++Files/winmysqladmin/images/find.ico
deleted file mode 100644
index 2e0f96c52f9..00000000000
--- a/VC++Files/winmysqladmin/images/find.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/green.ico b/VC++Files/winmysqladmin/images/green.ico
deleted file mode 100644
index ef53cd87994..00000000000
--- a/VC++Files/winmysqladmin/images/green.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/help.bmp b/VC++Files/winmysqladmin/images/help.bmp
deleted file mode 100644
index 76c6a90d2d8..00000000000
--- a/VC++Files/winmysqladmin/images/help.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/initsetup.cpp b/VC++Files/winmysqladmin/images/initsetup.cpp
deleted file mode 100644
index d0dd15b059c..00000000000
--- a/VC++Files/winmysqladmin/images/initsetup.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//---------------------------------------------------------------------------
-#include <vcl.h>
-#pragma hdrstop
-
-#include "initsetup.h"
-#include "main.h"
-//---------------------------------------------------------------------------
-#pragma package(smart_init)
-#pragma resource "*.dfm"
-TForm2 *Form2;
-//---------------------------------------------------------------------------
-__fastcall TForm2::TForm2(TComponent* Owner)
- : TForm(Owner)
-{
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm2::BitBtn1Click(TObject *Sender)
-{
-if ((Edit1->Text).IsEmpty() || (Edit2->Text).IsEmpty())
- Application->MessageBox("Fill the User name and Password text boxs ", "Winmysqladmin 1.0", MB_OK |MB_ICONINFORMATION);
- else
- {
- if(Form1->ForceConnection())
- if(Form1->ForceMySQLInit())
- {
- Form1->CreateMyIniFile();
- Form1->CreatingShortCut();
- }
- Close();
- }
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm2::BitBtn2Click(TObject *Sender)
-{
- Close();
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm2::SpeedButton1Click(TObject *Sender)
-{
- Application->HelpCommand(HELP_FINDER,0);
-}
-//---------------------------------------------------------------------------
diff --git a/VC++Files/winmysqladmin/images/killdb.ico b/VC++Files/winmysqladmin/images/killdb.ico
deleted file mode 100644
index 9689aa88361..00000000000
--- a/VC++Files/winmysqladmin/images/killdb.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/logo.ico b/VC++Files/winmysqladmin/images/logo.ico
deleted file mode 100644
index 9409cad72b6..00000000000
--- a/VC++Files/winmysqladmin/images/logo.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/multitrg.ico b/VC++Files/winmysqladmin/images/multitrg.ico
deleted file mode 100644
index 76ffbe29c77..00000000000
--- a/VC++Files/winmysqladmin/images/multitrg.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/mysql-07.bmp b/VC++Files/winmysqladmin/images/mysql-07.bmp
deleted file mode 100644
index dcae23b8813..00000000000
--- a/VC++Files/winmysqladmin/images/mysql-07.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/mysql-17.bmp b/VC++Files/winmysqladmin/images/mysql-17.bmp
deleted file mode 100644
index 0291c804006..00000000000
--- a/VC++Files/winmysqladmin/images/mysql-17.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/mysql.BMP b/VC++Files/winmysqladmin/images/mysql.BMP
deleted file mode 100644
index ed5c7f9051f..00000000000
--- a/VC++Files/winmysqladmin/images/mysql.BMP
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/red.ico b/VC++Files/winmysqladmin/images/red.ico
deleted file mode 100644
index b28288d576e..00000000000
--- a/VC++Files/winmysqladmin/images/red.ico
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/red22.BMP b/VC++Files/winmysqladmin/images/red22.BMP
deleted file mode 100644
index a35052afa01..00000000000
--- a/VC++Files/winmysqladmin/images/red22.BMP
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/images/see.bmp b/VC++Files/winmysqladmin/images/see.bmp
deleted file mode 100644
index 72fb2c50ec6..00000000000
--- a/VC++Files/winmysqladmin/images/see.bmp
+++ /dev/null
Binary files differ
diff --git a/VC++Files/winmysqladmin/initsetup.cpp b/VC++Files/winmysqladmin/initsetup.cpp
deleted file mode 100644
index 0a25b8cb79c..00000000000
--- a/VC++Files/winmysqladmin/initsetup.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//---------------------------------------------------------------------------
-#include <vcl.h>
-#pragma hdrstop
-
-#include "initsetup.h"
-#include "main.h"
-//---------------------------------------------------------------------------
-#pragma package(smart_init)
-#pragma resource "*.dfm"
-TForm2 *Form2;
-//---------------------------------------------------------------------------
-__fastcall TForm2::TForm2(TComponent* Owner)
- : TForm(Owner)
-{
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm2::BitBtn1Click(TObject *Sender)
-{
- if ((Edit1->Text).IsEmpty() || (Edit2->Text).IsEmpty())
- Application->MessageBox("Fill the User name and Password text boxs ", "Winmysqladmin 1.0", MB_OK |MB_ICONINFORMATION);
- else
- {
- Form1->GetServerFile();
- Form1->CreateMyIniFile();
- Form1->CreatingShortCut();
-
- Close();
- }
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm2::BitBtn2Click(TObject *Sender)
-{
- Close();
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm2::SpeedButton1Click(TObject *Sender)
-{
- Application->HelpCommand(HELP_FINDER,0);
-}
-//---------------------------------------------------------------------------
diff --git a/VC++Files/winmysqladmin/initsetup.h b/VC++Files/winmysqladmin/initsetup.h
deleted file mode 100644
index 28f575198e3..00000000000
--- a/VC++Files/winmysqladmin/initsetup.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//---------------------------------------------------------------------------
-#ifndef initsetupH
-#define initsetupH
-//---------------------------------------------------------------------------
-#include <Classes.hpp>
-#include <Controls.hpp>
-#include <StdCtrls.hpp>
-#include <Forms.hpp>
-#include <Buttons.hpp>
-#include <ExtCtrls.hpp>
-#include <Graphics.hpp>
-//---------------------------------------------------------------------------
-class TForm2 : public TForm
-{
-__published: // IDE-managed Components
- TImage *Image1;
- TLabel *Label1;
- TLabel *Label4;
- TPanel *Panel1;
- TLabel *Label5;
- TLabel *Label6;
- TLabel *Label2;
- TEdit *Edit1;
- TEdit *Edit2;
- TBitBtn *BitBtn1;
- TSpeedButton *SpeedButton1;
- TBitBtn *BitBtn2;
- void __fastcall BitBtn1Click(TObject *Sender);
- void __fastcall BitBtn2Click(TObject *Sender);
- void __fastcall SpeedButton1Click(TObject *Sender);
-private: // User declarations
-public: // User declarations
- __fastcall TForm2(TComponent* Owner);
-};
-//---------------------------------------------------------------------------
-extern PACKAGE TForm2 *Form2;
-//---------------------------------------------------------------------------
-#endif
diff --git a/VC++Files/winmysqladmin/main.cpp b/VC++Files/winmysqladmin/main.cpp
deleted file mode 100644
index dfb2004a780..00000000000
--- a/VC++Files/winmysqladmin/main.cpp
+++ /dev/null
@@ -1,2529 +0,0 @@
-//---------------------------------------------------------------------------
-#include <vcl.h>
-#pragma hdrstop
-
-#include "main.h"
-#include "initsetup.h"
-#include "db.h"
-
-//---------------------------------------------------------------------------
-#pragma package(smart_init)
-#pragma resource "*.dfm"
-#include <shellapi.h>
-#include <registry.hpp>
-#include <winsvc.h>
-#include <winsock.h>
-#include <shlobj.h>
-#include <IniFiles.hpp>
-#include <dir.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <deque.h>
-#include <vector.h>
-#include <fstream.h>
-#include <iostream.h>
-#include <iterator.h>
-#include <sstream.h>
-#include "mysql.h"
-#include <Printers.hpp>
-
-TForm1 *Form1;
-bool i_start, NT;
-bool IsForce = false;
-bool IsVariables = false;
-bool IsProcess = false ;
-bool IsDatabases = false;
-bool new_line = 0;
-bool ya = true;
-bool yy = true;
-bool rinit = false;
-AnsiString vpath;
-AnsiString vip;
-MYSQL_RES *res_1;
-static unsigned long q = 0;
-bool preport = false;
-bool treport = false;
-bool ereport = false;
-AnsiString mainroot;
-bool IsMySQLNode = false;
-MYSQL *MySQL;
-//---------------------------------------------------------------------------
-__fastcall TForm1::TForm1(TComponent* Owner)
- : TForm(Owner)
-{
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::FormCreate(TObject *Sender)
-{
- i_start = true;
- IsConnect = false;
- if (ParamCount() > 0){
- if (ParamStr(1) == "-h" || ParamStr(1) == "h" ) {
- ShowHelp(); Application->Terminate(); }
- else if (ParamStr(1) == "-w" || ParamStr(1) == "w") {
- i_start = false; ContinueLoad(); }
- }
- else {
- ContinueLoad(); Hide(); GetServerOptions(); }
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::DrawItem(TMessage& Msg)
-{
- IconDrawItem((LPDRAWITEMSTRUCT)Msg.LParam);
- TForm::Dispatch(&Msg);
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::MyNotify(TMessage& Msg)
-{
- POINT MousePos;
-
- switch(Msg.LParam) {
- case WM_RBUTTONUP:
- if (GetCursorPos(&MousePos)){
- PopupMenu1->PopupComponent = Form1; SetForegroundWindow(Handle);
- PopupMenu1->Popup(MousePos.x, MousePos.y);}
- else Show();
- break;
- case WM_LBUTTONUP:
- if (GetCursorPos(&MousePos)){
- PopupMenu1->PopupComponent = Form1; SetForegroundWindow(Handle);
- PopupMenu1->Popup(MousePos.x, MousePos.y); }
-
- ToggleState();
- break;
- default:
- break; }
-
- TForm::Dispatch(&Msg);
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::TrayMessage(DWORD dwMessage)
-{
- NOTIFYICONDATA tnd;
- PSTR pszTip;
-
- pszTip = TipText();
-
- tnd.cbSize = sizeof(NOTIFYICONDATA);
- tnd.hWnd = Handle;
- tnd.uID = IDC_MYICON;
- tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
- tnd.uCallbackMessage = MYWM_NOTIFY;
-
- if (dwMessage == NIM_MODIFY){
- tnd.hIcon = IconHandle();
- if (pszTip)lstrcpyn(tnd.szTip, pszTip, sizeof(tnd.szTip));
- else tnd.szTip[0] = '\0'; }
- else { tnd.hIcon = NULL; tnd.szTip[0] = '\0'; }
-
- return (Shell_NotifyIcon(dwMessage, &tnd));
-}
-//---------------------------------------------------------------------------
-HANDLE __fastcall TForm1::IconHandle(void)
-{
-
- if (!NT){
- if (MySQLSignal()){Image3->Visible = false; Image2->Visible = true;
- return (Image2->Picture->Icon->Handle); }
- else {Image2->Visible = false; Image3->Visible = true;
- return (Image3->Picture->Icon->Handle); }
- }
- else {
- if (TheServiceStatus()){Image3->Visible = false; Image2->Visible = true;
- return (Image2->Picture->Icon->Handle); }
-
- else if (MySQLSignal()){Image3->Visible = false; Image2->Visible = true;
- return (Image2->Picture->Icon->Handle); }
- else {Image2->Visible = false; Image3->Visible = true;
- return (Image3->Picture->Icon->Handle); }
- }
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::ToggleState(void)
-{
-
- TrayMessage(NIM_MODIFY);
- if (!NT){
- if (MySQLSignal()){SSW9->Caption = "ShutDown the Server";
- Image3->Visible = false; Image2->Visible = true; }
- else {SSW9->Caption = "Start the Server";
- Image2->Visible = false; Image3->Visible = true; }
- }
- else {
- if (TheServiceStart()) {
- Standa->Enabled = false;
- if (TheServiceStatus()) {RService->Enabled = false;
- StopS->Enabled = true;
- StopS->Caption = "Stop the Service";
- Image3->Visible = false;
- Image2->Visible = true; }
- else {RService->Enabled = true;
- StopS->Enabled = true;
- RService->Caption = "Remove the Service";
- StopS->Caption = "Start the Service";
- Image2->Visible = false;
- Image3->Visible = true; }
- }
- else {
- Standa->Enabled = true;
- StopS->Enabled = false;
- if (MySQLSignal()) {
- RService->Enabled = false;
- Standa->Caption = "ShutDown the Server Standalone";
- Image3->Visible = false;
- Image2->Visible = true; }
-
- else {
- RService->Enabled = true;
- RService->Caption = "Install the Service";
- Standa->Caption = "Start the Server Standalone";
- Image2->Visible = false;
- Image3->Visible = true; }
-
- }
-
-
- }
-
-}
-//---------------------------------------------------------------------------
-PSTR __fastcall TForm1::TipText(void)
-{
- char* status = StatusLine->SimpleText.c_str();
- return status;
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::WMQueryEndSession(TWMQueryEndSession &msg)
-{
-
-
- if (!NT) {
-
- if (MySQLSignal()){
- StatusLine->SimpleText = "Shutdown in progress.....";
- Show(); Shutd(); msg.Result = 1; }
- else {
- StatusLine->SimpleText = "The Server already is down......";
- Show(); msg.Result = 1; Close(); }
- }
- else {
-
- Show();
- if (!TheServiceStart()) { if (MySQLSignal()) Shutd(); }
- msg.Result = 1;
- }
-
-}
-
-//---------------------------------------------------------------------------
-LRESULT IconDrawItem(LPDRAWITEMSTRUCT lpdi)
-{
- HICON hIcon;
-
- hIcon = (HICON)LoadImage(g_hinst, MAKEINTRESOURCE(lpdi->CtlID), IMAGE_ICON,
- 16, 16, 0);
- if (!hIcon)
- return(false);
-
- DrawIconEx(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top, hIcon,
- 16, 16, 0, NULL, DI_NORMAL);
-
- return(true);
-}
-//---------------------------------------------------------------------------
-AnsiString __fastcall TForm1::TheComputer()
-{
- AnsiString theword;
- DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
- char szBuf[MAX_COMPUTERNAME_LENGTH + 1];
- szBuf[0] = '\0';
-
- GetComputerName(szBuf, &dwSize);
- theword = (AnsiString) szBuf;
- delete [] szBuf;
- return theword;
-
-}
-//---------------------------------------------------------------------------
-AnsiString __fastcall TForm1::TheOS()
-{
- AnsiString theword;
- OSVERSIONINFO info;
- info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&info);
-
- switch (info.dwPlatformId)
- {
- case VER_PLATFORM_WIN32s:
- NT = false;
- theword = "Win32s detected";
- break;
- case VER_PLATFORM_WIN32_WINDOWS:
- NT = false;
- theword = "Win 95 or Win 98 detected";
- break;
- case VER_PLATFORM_WIN32_NT:
- NT = true;
- theword = "Windows NT detected";
- break;
- }
- return theword;
-}
-///---------------------------------------------------------------------------
-AnsiString __fastcall TForm1::TheUser()
-{
- AnsiString theword;
- DWORD dwSize = 0;
-
- GetUserName(NULL, &dwSize);
-
- char *szBuf = new char[dwSize];
- szBuf[0] = '\0';
-
- GetUserName(szBuf, &dwSize);
- theword = (AnsiString) szBuf;
- delete [] szBuf;
- return theword;
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::TakeIP(void)
-{
- WORD wVersionRequested;
- WSADATA WSAData;
- wVersionRequested = MAKEWORD(1,1);
- WSAStartup(wVersionRequested,&WSAData);
-
- hostent *P;
- char s[128];
- in_addr in;
- char *P2;
- gethostname(s, 128);
- P = gethostbyname(s);
-
- Memo2->Lines->Clear();
- Memo2->Lines->Add((AnsiString)P->h_name);
- mainroot = P->h_name;
- in.S_un.S_un_b.s_b1 = P->h_addr_list[0][0];
- in.S_un.S_un_b.s_b2 = P->h_addr_list[0][1];
- in.S_un.S_un_b.s_b3 = P->h_addr_list[0][2];
- in.S_un.S_un_b.s_b4 = P->h_addr_list[0][3];
- P2 = inet_ntoa(in);
- vip = P2;
- mainroot += " ( " + (AnsiString)P2 + " )";
- Memo2->Lines->Add(P2);
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::GetmemStatus(void)
-{
- MEMORYSTATUS ms;
- ms.dwLength = sizeof(MEMORYSTATUS);
- GlobalMemoryStatus(&ms);
-
- Edit2->Text = AnsiString((double)ms.dwTotalPhys / 1024000.0) + " MB RAM";
-}
-
-//---------------------------------------------------------------------------
-void __fastcall TForm1::ShowHelp(void)
-{
- Application->MessageBox("Usage: WinMySQLadmin.EXE [OPTIONS]\n\n-w Run the tool without start the Server.\n-h Shows this message and exit ", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::ContinueLoad(void)
-{
- OS->Text = TheOS();
- Localhost->Text = TheComputer();
- Localuser->Text = TheUser();
- GetmemStatus();
- ClearBox();
- TakeIP();
- MyODBC();
-
-
- IsMyIniUp();
-
- if (!NT) { WinNT->Enabled = false; NtVer->Enabled = false; Win9->Enabled = true; }
- else { WinNT->Enabled = true; Win9->Enabled = false; }
-
- if (i_start)
- {
- // NT never is started from the prompt
- if ((!NT) && (!MySQLSignal())) mysqldstart();
- {
- TrayMessage(NIM_MODIFY);
- SeekErrFile();
- }
- }
- Hide();
-
-}
-
-//---------------------------------------------------------------------------
-void __fastcall TForm1::MyODBC(void)
-{
-
- TRegistry *Registry = new TRegistry();
- Memo3->Lines->Clear();
-
- try
- {
- Registry->RootKey = HKEY_LOCAL_MACHINE;
- // the basic data of myodbc
- if (Registry->OpenKey("Software\\ODBC\\ODBCINST.INI\\MySQL", false))
- {
- Memo3->Lines->Add("Driver Version\t" + Registry->ReadString("DriverODBCVer"));
- Memo3->Lines->Add("Driver\t\t" + Registry->ReadString("Driver"));
- Memo3->Lines->Add("API Level\t\t" + Registry->ReadString("APILevel"));
- Memo3->Lines->Add("Setup\t\t" + Registry->ReadString("Setup"));
- Memo3->Lines->Add("SQL Level\t" + Registry->ReadString("SQLLevel"));
- }
- else
- Memo3->Lines->Add("Not Found");
-
- }
- catch (...)
- {
- delete Registry;
- }
- Memo3->Enabled = false;
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::IsMyIniUp(void)
-{
- // we see if the my.ini is Up
- AnsiString asFileName = FileSearch("my.ini", TheWinDir());
- if (asFileName.IsEmpty())
- {
- IsForce = true;
- i_start = false;
- QuickSearch();
- }
- else
- {
- Memo1->Enabled = true;
- Memo1->Lines->Clear();
- FillMyIni();
- GetBaseDir();
- }
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::QuickSearch(void)
-{
- AnsiString asFileName = FileSearch("mysql.exe", "c:/mysql/bin");
- if (!asFileName.IsEmpty())
- BaseDir->Text = "c:/mysql";
-}
-//---------------------------------------------------------------------------
-AnsiString __fastcall TForm1::TheWinDir()
-{
- AnsiString WinDir;
- UINT BufferSize = GetWindowsDirectory(NULL,0);
- WinDir.SetLength(BufferSize+1);
- GetWindowsDirectory(WinDir.c_str(),BufferSize);
- char* dirw = WinDir.c_str();
- return dirw ;
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::FillMyIni(void)
-{
- Memo1->Lines->LoadFromFile(TheWinDir() + "\\my.ini");
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::GetBaseDir(void)
-{
-
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char file[_MAX_FNAME];
- char ext[_MAX_EXT];
-
-
- TIniFile *pIniFile = new
- TIniFile(TheWinDir() + "\\my.ini");
-
- BaseDir->Text = pIniFile->ReadString("mysqld","basedir","") ;
- AnsiString lx = pIniFile->ReadString("WinMySQLadmin","Server","") ;
- _splitpath((lx).c_str(),drive,dir,file,ext);
- AnsiString lw = (AnsiString) file + ext;
-
- if ( lw == "mysqld-shareware.exe") {ShareVer->Checked = true;}
- if ( lw == "mysqld.exe") {MysqldVer->Checked = true;}
- if ( lw == "mysqld-opt.exe") {OptVer->Checked = true;}
- if ( lw == "mysqld-nt.exe") {NtVer->Checked = true;}
-
- delete pIniFile;
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::Showme1Click(TObject *Sender)
-{
- if(Showme1->Caption == "Show me") { TrayMessage(NIM_DELETE);
- Showme1->Caption = "Hide me"; Show(); }
- else { TrayMessage(NIM_ADD); TrayMessage(NIM_MODIFY);
- Showme1->Caption = "Show me"; Hide(); }
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::MySQLSignal()
-{
- HANDLE hEventShutdown;
- hEventShutdown=OpenEvent(EVENT_MODIFY_STATE, 0, "MySqlShutdown");
-
- if(hEventShutdown)
- {
- CloseHandle(hEventShutdown);
- return true;
- }
- else
- {
- CloseHandle(hEventShutdown);
- return false;
- }
-
-}
-
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::mysqldstart()
-{
- memset(&pi, 0, sizeof(pi));
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
- si.dwFlags |= STARTF_USESHOWWINDOW;
- si.wShowWindow |= SW_SHOWNORMAL;
-
-
- TIniFile *pIniFile = new
- TIniFile(TheWinDir() + "\\my.ini");
-
- if (NT)
- vpath = pIniFile->ReadString("WinMySQLadmin","Server","") + " --standalone\0" ;
- else
- vpath = pIniFile->ReadString("WinMySQLadmin","Server","") + "\0" ;
-
- if ( ! CreateProcess(0,vpath.c_str(), 0, 0, 0, 0, 0, 0, &si,&pi))
- {
- TrayMessage(NIM_MODIFY);
- return false;
- }
- else
- {
- TrayMessage(NIM_MODIFY);
- return true;
-
- }
-
-}
-
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::SeekErrFile()
-{
- Memo4->Enabled = true;
- Memo4->Lines->Clear();
- AnsiString asFileName = FileSearch("mysql.err", BaseDir->Text + "/data");
- if (!asFileName.IsEmpty())
- {
- FName = BaseDir->Text + "/data/mysql.err";
- ifstream in((FName).c_str());
- in.seekg(0, ios::end);
- string s, line;
- deque<string> v;
- deque<string> lines;
- streampos sp = in.tellg();
- if (sp <= 1000)
- in.seekg(0, ios::beg);
- else
- {
- in.seekg(0, ios::beg);
- in.seekg((sp - 1000));
- }
-
- do {
- lines.push_back(line);
- }while (getline(in, line));
-
-
- if( lines.size() <= 15)
- {
- deque<string>::reverse_iterator r;
- for(r = lines.rbegin(); r != lines.rend() ; r++)
- {
- if (ereport)
- Memo5->Lines->Add((*r).c_str());
- Memo4->Lines->Add((*r).c_str());
-
- }
- }
- else
- {
- int k = 0;
- deque<string>::reverse_iterator r;
- for(r = lines.rbegin(); r != lines.rend(); r++)
- {
- if (ereport)
- Memo5->Lines->Add((*r).c_str());
- Memo4->Lines->Add((*r).c_str());
- if (++k >= 15) { break;}
- }
- }
- in.close();
- return true;
- }
- else
- return false;
-
-}
-
-//---------------------------------------------------------------------------
-void __fastcall TForm1::Timer1Timer(TObject *Sender)
-{
- Showme1->Caption = "Show me";
- TrayMessage(NIM_ADD);
- TrayMessage(NIM_MODIFY);
- Hide();
- if (IsForce) {Form2->Show();}
- Timer1->Enabled = false;
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::GetServerFile()
-{
-
- AnsiString FileName;
-
- if(!NT) {
- FileName = FileSearch("mysqld-opt.exe", ExtractFilePath(Application->ExeName));
- if (FileName.IsEmpty()) FileName = FileSearch("mysqld.exe", ExtractFilePath(Application->ExeName));
- if (FileName.IsEmpty()) FileName = FileSearch("mysqld-shareware.exe", ExtractFilePath(Application->ExeName));
-
- if (!FileName.IsEmpty()){
- if ( FileName == "mysqld-opt.exe") {OptVer->Checked = true;}
- if ( FileName == "mysqld.exe") {MysqldVer->Checked= true;}
- if ( FileName == "mysqld-shareware.exe") {ShareVer->Checked= true;} }
-
- }
- else {
-
- FileName = FileSearch("mysqld-nt.exe", ExtractFilePath(Application->ExeName));
- if (FileName.IsEmpty()) FileName = FileSearch("mysqld.exe", ExtractFilePath(Application->ExeName));
- if (FileName.IsEmpty()) FileName = FileSearch("mysqld-shareware.exe", ExtractFilePath(Application->ExeName));
-
- if (!FileName.IsEmpty()) {
- if ( FileName == "mysqld-nt.exe") {NtVer->Checked = true;}
- if ( FileName == "mysqld.exe") {MysqldVer->Checked= true;}
- if ( FileName == "mysqld-shareware.exe") {ShareVer->Checked= true;} }
-
- }
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::CreateMyIniFile(void)
-{
- char szFileName[6];
- int iFileHandle;
- AnsiString jk;
-
- Memo1->Enabled = true;
- Memo1->Lines->Clear();
- strcpy(szFileName,"\\my.ini");
- iFileHandle = FileCreate(TheWinDir() + szFileName );
-
- jk = "#This File was made using the WinMySQLadmin 1.0 Tool\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#" + Now() + "\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#Uncomment or Add only the keys that you know how works.\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#Read the MySQL Manual for instructions\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
-
- jk = "[mysqld]\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "basedir=" + TheDir() + "\n";
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#bind-address=" + vip + "\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#datadir=" + TheDir() + "/data\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#language=" + TheDir() + "/share/your language directory\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#delay-key-write-for-all-tables\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#log-long-format\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#slow query log=#\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#tmpdir=#\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#ansi\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#new\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#port=3306\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#safe\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#skip-name-resolve\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#skip-networking\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#skip-new\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#skip-host-cache\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#set-variable = key_buffer=16M\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#set-variable = max_allowed_packet=1M\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#set-variable = thread_stack=128K\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#set-variable = flush_time=1800\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "[mysqldump]\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#quick\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#set-variable = max_allowed_packet=16M\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "[mysql]\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#no-auto-rehash\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "[isamchk]\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "#set-variable= key=16M\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "[WinMySQLadmin]\n\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
-
- if (ShareVer->Checked) { jk = "Server=" + TheDir() + "/bin/mysqld-shareware.exe\n\n";}
- if (MysqldVer->Checked) {jk = "Server=" + TheDir() + "/bin/mysqld.exe\n\n";}
- if (OptVer->Checked) {jk = "Server=" + TheDir() + "/bin/mysqld-opt.exe\n\n";}
- if (NtVer->Checked) {jk = "Server=" + TheDir() + "/bin/mysqld-nt.exe\n\n";}
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "user=" + Form2->Edit1->Text + "\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- jk = "password=" + Form2->Edit2->Text + "\n" ;
- FileWrite(iFileHandle, (jk).c_str(), (jk).Length());
-
- FileClose(iFileHandle);
- FillMyIni();
-
-}
-
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::CreatingShortCut()
-{
- // Where is The Start Menu in this Machine ?
- LPITEMIDLIST pidl;
- LPMALLOC pShellMalloc;
- char szDir[MAX_PATH + 16];
- AnsiString file;
- AnsiString jk = "\\WinMySQLadmin.lnk" ;
-
- if(SUCCEEDED(SHGetMalloc(&pShellMalloc)))
- {
- if(SUCCEEDED(SHGetSpecialFolderLocation(NULL,
- CSIDL_STARTUP, &pidl)))
- {
- if(!SHGetPathFromIDList(pidl, szDir))
- {
- pShellMalloc->Release();
- pShellMalloc->Free(pidl);
- return false;
- }
-
- pShellMalloc->Free(pidl);
- }
-
- pShellMalloc->Release();
- StrCat(szDir, jk.c_str());
- }
-
- // the create
-
- IShellLink* pLink;
- IPersistFile* pPersistFile;
-
- if(SUCCEEDED(CoInitialize(NULL)))
- {
- if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL,
- CLSCTX_INPROC_SERVER,
- IID_IShellLink, (void **) &pLink)))
- {
-
- pLink->SetPath((ExtractFilePath(Application->ExeName) + "WinMySQLadmin.exe").c_str());
- pLink->SetDescription("WinMySQLadmin Tool");
- pLink->SetShowCmd(SW_SHOW);
-
- if(SUCCEEDED(pLink->QueryInterface(IID_IPersistFile,
- (void **)&pPersistFile)))
- {
-
- WideString strShortCutLocation(szDir);
- pPersistFile->Save(strShortCutLocation.c_bstr(), TRUE);
- pPersistFile->Release();
- }
- pLink->Release();
- }
-
- CoUninitialize();
- }
-
-
- return true;
-}
-
-//---------------------------------------------------------------------------
-AnsiString __fastcall TForm1::TheDir()
-{
- AnsiString buffer;
- char s[_MAX_PATH + 1];
-
- StrCopy(s, ( BaseDir->Text).c_str()) ;
-
- for (int i = 0; s[i] != NULL; i++)
- if (s[i] != '\\')
- buffer += s[i];
- else
- buffer += "/";
-
- return buffer;
-
-}
-
-//---------------------------------------------------------------------------
-void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
-{
- Application->HelpCommand(HELP_FINDER,0);
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Timer2Timer(TObject *Sender)
-{
- ToggleState();
-
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::TheServiceStart()
-{
- bool thatok;
- char *SERVICE_NAME = "MySql";
- SC_HANDLE myService, scm;
- scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS | GENERIC_WRITE);
- if (scm)
- {
- myService = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
- if (myService)
- thatok = true;
- else
- thatok = false;
- }
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- return thatok;
-}
-
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::TheServicePause()
-{
-
- bool thatok;
- char *SERVICE_NAME = "MySql";
- SC_HANDLE myService, scm;
- scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
-
- if (scm)
- {
- myService = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
- if (myService)
- {
- // stop the service
- if (IsConnect)
- {
- mysql_kill(MySQL,mysql_thread_id(MySQL));
- StatusLine->SimpleText = "";
- q = 0;
- }
-
-
- SERVICE_STATUS ss;
- thatok = ControlService(myService,
- SERVICE_CONTROL_STOP,
- &ss);
-
- }
- else
- thatok = false;
- }
- else
- thatok = false;
-
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- return thatok;
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::TheServiceResume()
-{
-
- bool thatok;
- char *SERVICE_NAME = "MySql";
- SC_HANDLE myService, scm;
- scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
-
- if (scm)
- {
- myService = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
- if (myService)
- {
- // start the service
-
- thatok = StartService(myService, 0, NULL);
- }
- else
- thatok = false;
- }
- else
- thatok = false;
-
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- return thatok;
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::TheServiceStatus()
-{
- bool thatok;
- bool k;
- char *SERVICE_NAME = "MySql";
- SC_HANDLE myService, scm;
- SERVICE_STATUS ss;
- DWORD dwState = 0xFFFFFFFF;
- scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
-
- if (scm)
- {
- myService = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
- if (myService)
- {
- memset(&ss, 0, sizeof(ss));
- k = QueryServiceStatus(myService,&ss);
- if (k)
- {
- dwState = ss.dwCurrentState;
- if (dwState == SERVICE_RUNNING)
- thatok = true;
- }
- else
- thatok = false;
- }
- else
- thatok = false;
- }
- else
- thatok = false;
-
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- return thatok;
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::TheServiceCreate()
-
-{
- bool thatok;
- char *SERVICE_NAME = "MySql";
- char *szFullPath = vpath.c_str();
- SC_HANDLE myService, scm;
- scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
-
- if (scm)
- { myService = CreateService(
- scm,
- SERVICE_NAME,
- SERVICE_NAME,
- SERVICE_ALL_ACCESS,
- SERVICE_WIN32_OWN_PROCESS,
- SERVICE_AUTO_START ,
- SERVICE_ERROR_NORMAL,
- szFullPath,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL);
-
- if (myService)
- thatok = true;
- else
- thatok = false;
-
- }
-
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- return thatok;
-
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Swin9Click(TObject *Sender)
-{
- if(Application->MessageBox("Shutdown this tool", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- Close();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SSW9Click(TObject *Sender)
-{
- if (MySQLSignal())
- {
- if(Application->MessageBox("Shutdown the MySQL Server ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
-
- if (Shutd())
- {
- IsConnect = false;
- IsVariables = false;
- IsProcess = false;
- IsDatabases = false;
- ya = false;
- ClearBox();
- Sleep(500);
- TrayMessage(NIM_MODIFY);
-
- }
- else
- Application->MessageBox("Fails to Shutdown the Server", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- }
- }
- else
- {
- if(Application->MessageBox("Start the MySQL Server ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- if (mysqldstart())
- {
- TrayMessage(NIM_MODIFY);
- ya = true;
- }
- else
- Application->MessageBox("Fails to Start the Server", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
-
- }
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::ShutDownBoth1Click(TObject *Sender)
-{
- if (MySQLSignal())
- {
- if(Application->MessageBox("Shutdown the MySQL Server and this tool ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
-
- if (Shutd())
- Close();
- else
- {
- Application->MessageBox("Fails to Shutdown the Server", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
-
- }
- }
- }
- else
- if(Application->MessageBox("Shutdown this tool ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- Close();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::ShutDownthisTool1Click(TObject *Sender)
-{
- if(Application->MessageBox("Shutdown this tool ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- Close();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::StopSClick(TObject *Sender)
-{
- AnsiString theWarning;
- theWarning = "Are you sure to stop the Service ?\n\nAll the connections will be loss !" ;
- if (TheServiceStatus())
- {
- if(Application->MessageBox(theWarning.c_str(), "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- if (TheServicePause())
- {
- TrayMessage(NIM_MODIFY);
- IsConnect = false;
- IsVariables = false;
- IsProcess = false;
- IsDatabases = false;
- ya = false;
- ClearBox();
-
- }
- else
- Application->MessageBox("Fails to stop the Service", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
-
- }
- }
- else
- {
- if(Application->MessageBox("Start the Service Manager for the MySQL Server ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- if (TheServiceResume())
- {
- ya = true;
- TrayMessage(NIM_MODIFY);
- }
- else
- Application->MessageBox("Fails to start the Service", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- }
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::RServiceClick(TObject *Sender)
-{
- if (TheServiceStart())
- {
- if(Application->MessageBox("Remove the MySQL Server service ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- if (!TheServiceRemove())
- Application->MessageBox("Fails to Remove The MySQL Server Service", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- }
- }
- else
- {
- if(Application->MessageBox("Install the MySQL Server service ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- if (!TheServerPath())
- Application->MessageBox("Please create first the my.ini setup", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- else
- {
- if (!TheServiceCreate())
- Application->MessageBox("Fails to Install The MySQL Server Service", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- }
-
- }
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::StandaClick(TObject *Sender)
-{
- if (MySQLSignal())
- {
- if(Application->MessageBox("Shutdown the MySQL Server ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- if (Shutd())
- {
- IsConnect = false;
- IsVariables = false;
- IsProcess = false;
- IsDatabases = false;
- ya = false;
- ClearBox();
- Sleep(500);
- TrayMessage(NIM_MODIFY);
-
- }
- else
- Application->MessageBox("Fails to Shutdown the Server", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- }
- }
- else
- {
- if(Application->MessageBox("Start the MySQL Server ", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- if (mysqldstart())
- {
- StatusLine->SimpleText = "";
- TrayMessage(NIM_MODIFY);
-
- }
- else
- Application->MessageBox("Fails to Start the Server", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- }
- }
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::Shutd()
-{
- // from Irena
- HANDLE hEventShutdown;
- hEventShutdown=OpenEvent(EVENT_MODIFY_STATE, 0, "MySqlShutdown");
-
- if (IsConnect)
- {
- mysql_kill(MySQL,mysql_thread_id(MySQL));
- mysql_shutdown(MySQL, SHUTDOWN_DEFAULT);
- StatusLine->SimpleText = "";
-
- }
-
- q = 0;
-
-
- if(hEventShutdown)
- {
- SetEvent(hEventShutdown);
- CloseHandle(hEventShutdown);
- TrayMessage(NIM_MODIFY);
- IsConnect = false;
- return true;
- }
- else
- {
- TrayMessage(NIM_MODIFY);
- return false;
- }
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::ClearBox(void)
-{
-
- st22->Text = "";
- st23->Text = "";
- st24->Text = "";
- st25->Text = "";
- st26->Text = "";
- st27->Text = "";
- st28->Text = "";
- st29->Text = "";
- Edit3->Text = "";
- Edit4->Text = "";
- Edit5->Text = "";
- Edit6->Text = "";
-
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::TheServiceRemove()
-{
- bool thatok;
- char *SERVICE_NAME = "MySql";
- SC_HANDLE myService, scm;
- scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
- if (scm)
- {
- myService = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
- if (myService)
- {
- if(DeleteService(myService))
- {
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- thatok = true;
- }
- else
- {
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- thatok = false;
- }
-
- }
- else
- {
- CloseServiceHandle(myService);
- CloseServiceHandle(scm);
- thatok = false;
- }
- }
- else
- {
- thatok = false;
- CloseServiceHandle(scm);
- }
-
- return thatok;
-
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::TheServerPath()
-{
-
- TIniFile *pIniFile = new
- TIniFile(TheWinDir() + "\\my.ini");
-
- vpath = pIniFile->ReadString("WinMySQLadmin","Server","") ;
- delete pIniFile;
- if (vpath.IsEmpty())
- return false;
- else
- return true;
-
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button5Click(TObject *Sender)
-{
- if (!SeekErrFile())
- Application->MessageBox("Fails to find mysql.err", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::IsMySQLInit(void)
-{
- AnsiString theCommand;
- char *host = NULL,*password=0,*user=0 ;
- TIniFile *pIniFile = new
- TIniFile(TheWinDir() + "\\my.ini");
-
- AnsiString MyUser = pIniFile->ReadString("WinMySQLadmin","user","") ;
- AnsiString MyPass = pIniFile->ReadString("WinMySQLadmin","password","") ;
-
- delete pIniFile;
-
-
- if (!MyUser.IsEmpty() && MyUser.Length() && !MyPass.IsEmpty() && MyPass.Length())
- {
- if (!IsConnect)
- {
-
- MySQL = mysql_init(MySQL);
- if (mysql_real_connect(MySQL, "localhost",(MyUser).c_str(), (MyPass).c_str() , 0, 0, NULL, 0))
- IsConnect = true;
- else
- {
- if(mysql_real_connect(MySQL,host,user,password , 0, 0, NULL, 0))
- {
- IsConnect = true;
- theCommand = "GRANT ALL PRIVILEGES ON *.* TO ";
- theCommand += "'" + MyUser + "' @localhost IDENTIFIED BY ";
- theCommand += "'" + MyPass + "' with GRANT OPTION";
- char* los = theCommand.c_str();
- if(!mysql_query(MySQL, los ))
- StatusLine->SimpleText = " ";
- }
-
- }
-
- }
-
- }
- else
- {
- if (!IsConnect)
- {
- MySQL = mysql_init(MySQL);
- if(mysql_real_connect(MySQL,host,user,password , 0, 0, NULL, 0))
- IsConnect = true;
- }
- }
-}
-
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Timer3Timer(TObject *Sender)
-{
- if ((NT) && TheServiceStatus()) {IsMySQLInit(); }
-
- if ((NT) && !TheServiceStatus() && MySQLSignal()) {IsMySQLInit(); }
-
- if (!(NT) && MySQLSignal()) {IsMySQLInit(); }
-
- if (IsConnect)
- {
- GetServerStatus();
- if (!IsMySQLNode)
- GetMainRoot();
- Extended->Enabled = true;
- if (!IsProcess && !GetProcess())
- StatusLine->SimpleText = "";
- if (!IsVariables && !GetVariables())
- StatusLine->SimpleText = "";
- Timer3->Interval = 10000;
- }
- else
- Extended->Enabled = false;
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::GetServerStatus(void)
-{
-
- GetExtendedStatus();
- Edit3->Text = mysql_get_server_info(MySQL);
- Edit4->Text = mysql_get_host_info(MySQL);
- Edit5->Text = mysql_get_client_info();
- Edit6->Text = mysql_get_proto_info(MySQL);
-
-
-}
-
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::GetProcess()
-{
- MYSQL_RES *res;
- MYSQL_ROW row;
- unsigned int i;
- int k = 0;
- int therow = 1;
- new_line=1;
-
- StringGrid2->RowCount= 2;
-
- if (!(res=mysql_list_processes(MySQL)))
- {
- return false;
- }
-
- while ((row=mysql_fetch_row(res)) != 0)
- {
- mysql_field_seek(res,0);
- StringGrid2->Cells[0][0] = "PID";
- StringGrid2->Cells[1][0] = "User";
- StringGrid2->Cells[2][0] = "Host";
- StringGrid2->Cells[3][0] = "DB";
- StringGrid2->Cells[4][0] = "Command";
- StringGrid2->Cells[5][0] = "Time";
- StringGrid2->Cells[6][0] = "State";
- StringGrid2->Cells[7][0] = "Info";
- for (i=0 ; i < mysql_num_fields(res); i++)
- {
-
- if (k <= 6 )
- {
- StringGrid2->Cells[k][therow] = row[i];
- k++;
- }
- else
- {
-
- StringGrid2->Cells[(k)][therow] = row[i];
- k = 0;
- therow++ ;
- StringGrid2->RowCount++;
-
- }
-
- }
-
- }
-
- StringGrid2->RowCount--;
- mysql_free_result(res);
- StringGrid5->RowCount--;
- IsProcess = true;
- return true;
-
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::GetVariables()
-{
- MYSQL_RES *res;
- MYSQL_ROW row;
- unsigned int i;
- int k = 1;
- new_line=1;
- bool left = true;
- AnsiString report;
- StringGrid1->RowCount = 2;
- if (mysql_query(MySQL,"show variables") ||
- !(res=mysql_store_result(MySQL)))
- {
- return false;
- }
-
- while ((row=mysql_fetch_row(res)) != 0)
- {
- mysql_field_seek(res,0);
-
- StringGrid1->Cells[0][0] = "Variable Name";
- StringGrid1->Cells[1][0] = "Value";
-
-
- for (i=0 ; i < mysql_num_fields(res); i++)
- {
-
- if (left)
- {
- if (treport)
- report = GetString(row[i]);
- StringGrid1->Cells[0][k++] = row[i];
- left = false;
- }
- else
- {
- if (treport)
- Memo5->Lines->Add(report + row[i]);
- StringGrid1->RowCount++;
- StringGrid1->Cells[1][--k] = row[i];
- k++;
- left = true;
- }
-
- }
-
- }
-
- StringGrid1->RowCount--;
- mysql_free_result(res);
- IsVariables = true;
- return true;
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::nice_time(AnsiString buff)
-{
-
- unsigned long sec;
- unsigned long tmp;
- AnsiString mytime;
-
- sec = StrToInt(buff);
-
- if (sec >= 3600L*24)
- {
- tmp=sec/(3600L*24);
- sec-=3600L*24*tmp;
-
- mytime = IntToStr(tmp);
- if (tmp > 1)
- mytime+= " days ";
- else
- mytime+= " day ";
-
- }
-
- if (sec >= 3600L)
- {
- tmp=sec/3600L;
- sec-=3600L*tmp;
- mytime += IntToStr(tmp);
- if (tmp > 1)
- mytime+= " hours ";
- else
- mytime+= " hour ";
- }
- if (sec >= 60)
- {
- tmp=sec/60;
- sec-=60*tmp;
- mytime += IntToStr(tmp);
- mytime+= " min ";
-
- }
- mytime += IntToStr(sec);
- mytime+= " sec ";
- st29->Text = mytime ;
- return true;
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::Button11Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (GetVariables())
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button10Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (GetProcess())
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button6Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (mysql_refresh(MySQL,REFRESH_HOSTS))
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button7Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (mysql_refresh(MySQL,REFRESH_LOG))
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button8Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (mysql_refresh(MySQL,REFRESH_TABLES))
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button2Click(TObject *Sender)
-{
- Memo1->Enabled = true;
- Memo1->Lines->Clear();
- AnsiString asFileName = FileSearch("my.ini", TheWinDir());
- if (asFileName.IsEmpty())
- Application->MessageBox("Don't found my.ini file on the Win Directory", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- else
- FillMyIni();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button3Click(TObject *Sender)
-{
- TIniFile *pIniFile = new
- TIniFile(TheWinDir() + "\\my.ini");
-
- if (!Memo1->GetTextLen())
- Application->MessageBox("The Memo Box is Empty", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- else
- {
- if(Application->MessageBox("Are you sure to write the modifications into My.ini file.", "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- Memo1->Lines->SaveToFile(TheWinDir() + "\\my.ini");
-
- Memo1->Lines->Clear();
- Memo1->Enabled = true;
- Memo1->Lines->Clear();
- if (NtVer->Checked)
- pIniFile->WriteString("WinMySQLadmin","Server",TheDir() + "/bin/mysqld-nt.exe");
- if (MysqldVer->Checked == true)
- pIniFile->WriteString("WinMySQLadmin","Server", TheDir() + "/bin/mysqld.exe");
- if (ShareVer->Checked)
- pIniFile->WriteString("WinMySQLadmin","Server",TheDir() + "/bin/mysqld-shareware.exe");
- if (OptVer->Checked)
- pIniFile->WriteString("WinMySQLadmin","Server", TheDir() + "/bin/mysqld-opt.exe");
- FillMyIni();
- Application->MessageBox("My.ini was modificated", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- }
-
- }
- delete pIniFile;
- Memo1->Lines->Clear();
- FillMyIni();
-
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button1Click(TObject *Sender)
-{
- if(CreatingShortCut())
- Application->MessageBox("The ShortCut on Start Menu was created", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
- else
- Application->MessageBox("Fails the Operation of Create the ShortCut", "WinMySQLadmin 1.0", MB_OK |MB_ICONINFORMATION);
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
-{
- BROWSEINFO info;
- char szDir[MAX_PATH];
- char szDisplayName[MAX_PATH];
- LPITEMIDLIST pidl;
- LPMALLOC pShellMalloc;
-
-
- if(SHGetMalloc(&pShellMalloc) == NO_ERROR)
- {
-
- memset(&info, 0x00,sizeof(info));
- info.hwndOwner = Handle;
- info.pidlRoot = 0;
- info.pszDisplayName = szDisplayName;
- info.lpszTitle = "Search MySQL Base Directory";
- info.ulFlags = BIF_RETURNONLYFSDIRS;
- info.lpfn = 0;
-
- pidl = SHBrowseForFolder(&info);
-
- if(pidl)
- {
-
- if(SHGetPathFromIDList(pidl, szDir)) {BaseDir->Text = szDir; }
-
- pShellMalloc->Free(pidl);
- }
- pShellMalloc->Release();
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::Button4Click(TObject *Sender)
-{
- if (IsConnect)
- {
- Memo3->Lines->Add(mysql_stat(MySQL));
- }
-}
-//---------------------------------------------------------------------------
-
-
-void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
-{
- if(Showme1->Caption == "Show me") { TrayMessage(NIM_DELETE);
- Showme1->Caption = "Hide me"; Show(); }
- else { TrayMessage(NIM_ADD); TrayMessage(NIM_MODIFY);
- Showme1->Caption = "Show me"; Hide(); }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::ExtendedClick(TObject *Sender)
-{
-if (ya)
- {
- Extended->Caption = "Start Extended Server Status";
- ya = false;
- ClearBox();
- }
-else
- {
- Extended->Caption = "Stop Extended Server Status";
- ya = true;
- }
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::GetServerOptions(void)
-{
-AnsiString FileName;
-FileName = FileSearch("mysqld-opt.exe", ExtractFilePath(Application->ExeName));
-if (FileName.IsEmpty()) {OptVer->Enabled = false; }
-
-FileName = FileSearch("mysqld-shareware.exe", ExtractFilePath(Application->ExeName));
-if (FileName.IsEmpty()) {ShareVer->Enabled = false; }
-
-FileName = FileSearch("mysqld.exe", ExtractFilePath(Application->ExeName));
-if (FileName.IsEmpty()) {MysqldVer->Enabled = false; }
-
-FileName = FileSearch("mysqld-nt.exe", ExtractFilePath(Application->ExeName));
-if (FileName.IsEmpty()) {NtVer->Enabled = false; }
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::GetReportServer(void)
-{
-
- AnsiString strspace;
- Memo5->Lines->Clear();
- Memo5->Lines->Add("This Report was made using the WinMySQLadmin 1.0 Tool");
- Memo5->Lines->Add("");
- Memo5->Lines->Add(Now());
- Memo5->Lines->Add("");
-
- preport = true;
- Memo5->Lines->Add("");
- Memo5->Lines->Add("Server Status Values");
- Memo5->Lines->Add("");
- Memo5->Lines->Add(GetString("Server Info") + mysql_get_server_info(MySQL));
- Memo5->Lines->Add(GetString("Host Info") + mysql_get_host_info(MySQL));
- Memo5->Lines->Add(GetString("Client Info") + mysql_get_client_info());
- Memo5->Lines->Add(GetString("Proto Info") + mysql_get_proto_info(MySQL));
- GetExtendedStatus();
- preport = false;
- treport = true;
- Memo5->Lines->Add("");
- Memo5->Lines->Add("Variables Values");
- Memo5->Lines->Add("");
- GetVariables();
- treport = false;
- ereport = true;
- Memo5->Lines->Add("");
- Memo5->Lines->Add("Last Lines from Err File");
- Memo5->Lines->Add("");
- SeekErrFile();
- ereport = false;
-
-}
-
-void __fastcall TForm1::SpeedButton4Click(TObject *Sender)
-{
- if(IsConnect)
- GetReportServer();
- else
- Application->MessageBox("The Server must be connected", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SpeedButton5Click(TObject *Sender)
-{
- AnsiString PathName;
- SaveFileDialog->FileName = PathName;
- if (SaveFileDialog->Execute() ){
- PathName= SaveFileDialog->FileName;
- Caption = ExtractFileName(PathName);
- Memo5->Lines->SaveToFile(PathName);
- Memo5->Modified = false;
- }
-}
-//---------------------------------------------------------------------------
-String __fastcall TForm1::GetString(String k)
-{
- int i = 35 - k.Length();
- for (int y = 1 ; y <= i ;y++ )
- k+= " ";
- return k ;
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::SpeedButton6Click(TObject *Sender)
-{
- PrinterSetupDialog1->Execute();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SpeedButton7Click(TObject *Sender)
-{
- AnsiString PathName;
- if (PrintDialog1->Execute()){
- try {
- Memo5->Print(PathName);
- }
- catch(...){
- Printer()->EndDoc();
- throw;
- }
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SpeedButton8Click(TObject *Sender)
-{
- Memo5->CutToClipboard();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SpeedButton9Click(TObject *Sender)
-{
- Memo5->CopyToClipboard();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SpeedButton10Click(TObject *Sender)
-{
-
- Memo5->PasteFromClipboard();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SpeedButton11Click(TObject *Sender)
-{
- Memo5->ClearSelection();
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::SpeedButton12Click(TObject *Sender)
-{
- Memo5->SelectAll();
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::GetMainRoot()
-{
-
- MYSQL_RES *res;
- MYSQL_ROW row;
- unsigned int i;
- AnsiString command;
-
- CleanGrid();
- CleanGridI();
- TakeIP();
-
- MySQLNode = DBView->Items->Add(NULL, mainroot.UpperCase());
- MySQLNode->ImageIndex = 0;
-
- if (!(res=mysql_list_dbs(MySQL,"%"))) { return false; }
- while ((row=mysql_fetch_row(res)) != 0) {
- mysql_field_seek(res,0);
-
- for (i=0 ; i < mysql_num_fields(res); i++)
- {
- MySQLDbs = DBView->Items->AddChild(MySQLNode, row[i]);
- MySQLDbs->ImageIndex = 1;
- MySQLDbs->SelectedIndex = 1;
-
-
- }
-
- }
-
- mysql_free_result(res);
- MySQLNode->Expanded = true;
-
-
-
-
- IsMySQLNode = true;
- return true;
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::DeleteDatabaseSClick(TObject *Sender)
-{
- AnsiString alert;
- if (IsConnect)
- {
- if(DBView->Selected == MySQLNode )
- Application->MessageBox("Invalid database row selected.", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- else if ( DBView->Selected == NULL )
- Application->MessageBox("Invalid database row selected.", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- else
- {
- if (DBView->Selected->Text.UpperCase() == "MYSQL")
- Application->MessageBox("You cann't use this tool to drop the MySQL Database.", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- else {
- alert = "Are you sure to drop the < ";
- alert+= DBView->Selected->Text.c_str();
- alert+= " > database.";
- if(Application->MessageBox(alert.c_str(), "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- char* lese = DBView->Selected->Text.c_str();
- if (!mysql_drop_db(MySQL, lese ))
- {
- DBView->Items->Clear();
- GetMainRoot();
- }
- else
- Application->MessageBox("Fails to drop the Database.", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- }
- }
- }
- }
- else
- Application->MessageBox("The Server must be connected", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
-}
-//---------------------------------------------------------------------------
- bool __fastcall TForm1::IsDatabase(String Name)
-{
- MYSQL_RES *res;
- MYSQL_ROW row;
- unsigned int i;
- AnsiString command;
-
-
- CleanTree();
- command = "use ";
- command+= Name.c_str();
- char* das = command.c_str();
- char* lis = Name.c_str();
- if (mysql_query(MySQL, das ) ||
- !(res=mysql_list_tables(MySQL,"%")))
- return false;
-
- MySQLNodeT = TableView->Items->Add(NULL, lis);
- MySQLNodeT->ImageIndex = 1;
- MySQLNodeT->SelectedIndex = 1;
- while ((row=mysql_fetch_row(res)) != 0) {
- mysql_field_seek(res,0);
-
- for (i=0 ; i < mysql_num_fields(res); i++)
- {
-
- MySQLTbs = TableView->Items->AddChild(MySQLNodeT, row[i]);
- MySQLTbs->ImageIndex = 2;
- MySQLTbs->SelectedIndex = 2;
- }
- MySQLNodeT->Expanded = true;
- }
- mysql_free_result(res);
- return true;
-}
-//---------------------------------------------------------------------------
-
-
-void __fastcall TForm1::DBViewClick(TObject *Sender)
-{
-
- if (IsConnect)
- {
- if (DBView->Selected != MySQLNode && DBView->Selected != NULL )
- {
- IsDatabase(DBView->Selected->Text);
-
- }
- else
- {
- CleanTree();
- }
- }
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::TableViewClick(TObject *Sender)
-{
- if (IsConnect)
- {
- if (DBView->Selected != MySQLNodeT )
- {
- IsTable(TableView->Selected->Text);
- IsIndex(TableView->Selected->Text);
-
- }
- else
- {
- CleanGrid();
- CleanGridI();
-
- }
- }
-}
-//---------------------------------------------------------------------------
- bool __fastcall TForm1::IsTable(String Name)
-{
- MYSQL_RES *res;
- MYSQL_ROW row;
- unsigned int i;
- int k = 0;
- int therow = 1;
- new_line=1;
- AnsiString command;
- AnsiString commandt;
-
- CleanGrid();
- CleanGridI();
- command = "use ";
- command+= DBView->Selected->Text.c_str();
- char* las = command.c_str();
-
- commandt = "desc ";
- commandt+= Name.c_str();
- char* les = commandt.c_str();
-
- if (mysql_query(MySQL, las ))
- return false;
-
- if (mysql_query(MySQL, les ) ||
- !(res=mysql_store_result(MySQL)))
- return false ;
-
- StringGrid4->Cells[0][0] = "Field";
- StringGrid4->Cells[1][0] = "Type";
- StringGrid4->Cells[2][0] = "Null";
- StringGrid4->Cells[3][0] = "Key";
- StringGrid4->Cells[4][0] = "Default";
- StringGrid4->Cells[5][0] = "Extra";
- StringGrid4->Cells[6][0] = "Previleges";
-
-
- int thecounter;
- String u = GetNumberServer();
- if ( u == "3.22")
- {
- StringGrid3->ColCount = 7;
- thecounter = 4;
- }
- else
- thecounter = 5;
-
- while ((row=mysql_fetch_row(res)) != 0)
- {
- mysql_field_seek(res,0);
-
- for (i=0 ; i < mysql_num_fields(res); i++)
- {
- if (k <= thecounter )
- {
- StringGrid4->Cells[k][therow] = row[i];
- k++;
- }
- else
- {
- StringGrid4->Cells[(k)][therow] = row[i];
- k = 0;
- therow++ ;
- StringGrid4->RowCount++;
- }
- }
-
- }
- StringGrid4->RowCount--;
- mysql_free_result(res);
- return true;
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::TableViewChange(TObject *Sender, TTreeNode *Node)
-{
-if (IsConnect)
- {
- if (DBView->Selected != MySQLNodeT )
- {
- IsTable(TableView->Selected->Text);
- IsIndex(TableView->Selected->Text);
-
- }
- else
- {
- CleanGrid();
- CleanGridI();
-
- }
- }
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::DBViewChange(TObject *Sender, TTreeNode *Node)
-{
- if (IsConnect)
- {
- if (DBView->Selected != MySQLNode )
- {
- IsDatabase(DBView->Selected->Text);
-
- }
- else
- {
- CleanTree();
- }
- }
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::RefreshSClick(TObject *Sender)
-{
- MYSQL_RES *res;
- MYSQL_ROW row;
- unsigned int i;
- AnsiString command;
-
- if (IsConnect)
- {
- IsMySQLNode = false;
- CleanTree();
- DBView->Items->Clear();
-
- TakeIP();
-
- MySQLNode = DBView->Items->Add(NULL, mainroot.UpperCase());
- MySQLNode->ImageIndex = 0;
-
- if (!(res=mysql_list_dbs(MySQL,"%"))) { /*do nothing;*/ }
- while ((row=mysql_fetch_row(res)) != 0) {
- mysql_field_seek(res,0);
-
- for (i=0 ; i < mysql_num_fields(res); i++)
- {
- MySQLDbs = DBView->Items->AddChild(MySQLNode, row[i]);
- MySQLDbs->ImageIndex = 1;
- MySQLDbs->SelectedIndex = 1;
-
- }
-
- }
-
- mysql_free_result(res);
-
- IsMySQLNode = true;
-
- MySQLNode->Expanded = true;
-
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::CreateDatabaseSClick(TObject *Sender)
-{
-
- if (IsConnect)
- {
- dbfrm->Show();
-
- }
- else
- ShowMessage("Precisa estar conectado");
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::CleanTree(void)
-{
- StringGrid4->RowCount= 2;
- StringGrid4->Cells[0][1] = "";
- StringGrid4->Cells[1][1] = "";
- StringGrid4->Cells[2][1] = "";
- StringGrid4->Cells[3][1] = "";
- StringGrid4->Cells[4][1] = "";
- StringGrid4->Cells[5][1] = "";
- TableView->Items->Clear();
-
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::CleanGrid(void)
-{
- StringGrid4->RowCount= 2;
- StringGrid4->Cells[0][1] = "";
- StringGrid4->Cells[1][1] = "";
- StringGrid4->Cells[2][1] = "";
- StringGrid4->Cells[3][1] = "";
- StringGrid4->Cells[4][1] = "";
- StringGrid4->Cells[5][1] = "";
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::CreatingDB()
-{
-
- if (mysql_create_db(MySQL, dbfrm->Edit1->Text.c_str()))
- return true;
- else
- return false;
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::OutRefresh(void)
-{
- RefreshSClick(dbfrm->SpeedButton1);
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::FlushHosts1Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (mysql_refresh(MySQL,REFRESH_HOSTS))
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::FlushLogs1Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (mysql_refresh(MySQL,REFRESH_LOG))
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-
-void __fastcall TForm1::FlushTables1Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (mysql_refresh(MySQL,REFRESH_TABLES))
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-//---------------------------------------------------------------------------
- bool __fastcall TForm1::IsIndex(String Name)
-{
- MYSQL_RES *res;
- MYSQL_ROW row;
- unsigned int i;
- int k = 0;
- int therow = 1;
- new_line=1;
- AnsiString command;
- AnsiString commandt;
- i = 0;
- CleanGridI();
- command = "use ";
- command+= DBView->Selected->Text.c_str();
- char* las = command.c_str();
-
- commandt = "show index from ";
- commandt+= Name.c_str();
- char* les = commandt.c_str();
-
- if (mysql_query(MySQL, las ))
- return false;
-
- if (mysql_query(MySQL, les ) ||
- !(res=mysql_store_result(MySQL)))
- return false ;
-
- StringGrid3->RowCount= 2;
- StringGrid3->Cells[0][0] = "Table";
- StringGrid3->Cells[1][0] = "Non_unique";
- StringGrid3->Cells[2][0] = "Key_name";
- StringGrid3->Cells[3][0] = "Seq_in_index";
- StringGrid3->Cells[4][0] = "Col_name";
- StringGrid3->Cells[5][0] = "Collation";
- StringGrid3->Cells[6][0] = "Card.";
- StringGrid3->Cells[7][0] = "Sub_part";
- StringGrid3->Cells[8][0] = "Packed";
- StringGrid3->Cells[9][0] = "Comment";
-
- int thecounter;
- String u = GetNumberServer();
-
- if ( u == "3.22")
- {
- StringGrid3->ColCount = 8;
- thecounter = 6;
- }
- else
- thecounter = 8;
- while ((row=mysql_fetch_row(res)) != 0)
- {
- mysql_field_seek(res,0);
-
- for (i=0 ; i < mysql_num_fields(res); i++)
- {
- if (k <= thecounter )
- {
- StringGrid3->Cells[k][therow] = row[i];
- k++;
- }
- else
- {
- StringGrid3->Cells[(k)][therow] = row[i];
- k = 0;
- therow++ ;
- StringGrid3->RowCount++;
- }
- }
-
- }
- if (i)
- StringGrid3->RowCount--;
- mysql_free_result(res);
- return true;
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::CleanGridI(void)
-{
- StringGrid3->RowCount= 2;
- StringGrid3->Cells[0][1] = "";
- StringGrid3->Cells[1][1] = "";
- StringGrid3->Cells[2][1] = "";
- StringGrid3->Cells[3][1] = "";
- StringGrid3->Cells[4][1] = "";
- StringGrid3->Cells[5][1] = "";
- StringGrid3->Cells[6][1] = "";
- StringGrid3->Cells[7][1] = "";
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::CreatingTable(String TheTable)
-{
-
- if (!mysql_query(MySQL, TheTable.c_str()))
- return true;
- else
- return false;
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::GetExtendedStatus()
-{
- if (!ya && !preport)
- return true;
-
- MYSQL_RES *res;
- MYSQL_ROW row;
- unsigned int i;
- int k = 1;
- new_line=1;
- bool left = true;
- bool open_tables = false;
- bool open_files = false;
- bool uptime = false;
- bool running_threads = false;
- bool open_streams = false;
- bool slow_queries = false;
- bool opened_tables = false;
- bool questions = false;
-
- AnsiString report;
- if (yy)
- StringGrid5->RowCount = 2;
-
- if (mysql_query(MySQL,"show status") ||
- !(res=mysql_store_result(MySQL)))
- {
- return false;
- }
-
- while ((row=mysql_fetch_row(res)) != 0)
- {
- mysql_field_seek(res,0);
-
- StringGrid5->Cells[0][0] = "Variable Name";
- StringGrid5->Cells[1][0] = "Value";
-
-
- for (i=0 ; i < mysql_num_fields(res); i++)
- {
-
- if (left)
- {
- if (preport)
- report = GetString(row[i]);
- if ( (String) row[i] == "Open_tables")
- open_tables = true;
- else
- open_tables = false;
- if ( (String) row[i] == "Open_files")
- open_files = true;
- else
- open_files = false;
- if ((String) row[i] == "Uptime")
- uptime = true;
- else
- uptime = false;
-
- if ( (String) row[i] == "Opened_tables")
- opened_tables = true;
- else
- opened_tables = false;
-
- if ( (String) row[i] == "Threads_running" || (String) row[i] == "Running_threads")
- running_threads = true;
- else
- running_threads = false;
-
- if ( (String) row[i] == "Open_streams")
- open_streams = true;
- else
- open_streams = false;
-
- if ( (String) row[i] == "Slow_queries")
- slow_queries = true;
- else
- slow_queries = false;
-
- if ( (String) row[i] == "Questions")
- questions = true;
- else
- questions = false;
-
- if (yy)
- StringGrid5->Cells[0][k++] = row[i];
-
- left = false;
- }
- else
- {
- if (preport)
- Memo5->Lines->Add(report + row[i]);
- if (open_tables)
- st22->Text = row[i];
- if (open_files)
- st23->Text = row[i];
- if (uptime)
- nice_time(row[i]);
- if (running_threads)
- st27->Text = row[i];
- if (open_streams)
- st24->Text = row[i];
- if (slow_queries)
- st28->Text = row[i];
- if (opened_tables)
- st25->Text = row[i];
- if (questions){
- q++;
- st26->Text = StrToInt64(row[i]) - q; }
-
- if (yy){
- StringGrid5->RowCount++;
- StringGrid5->Cells[1][--k] = row[i];
- k++; }
-
- left = true;
- }
-
- }
-
- }
-
-
- if (rinit)
- StringGrid5->RowCount--;
- mysql_free_result(res);
- yy = false;
- return true;
-}
-//---------------------------------------------------------------------------
-void __fastcall TForm1::SpeedButton13Click(TObject *Sender)
-{
- yy = true;
- // rinit = true;
-}
-//---------------------------------------------------------------------------
-String __fastcall TForm1::GetNumberServer()
-{
- String TheVersion;
-
- TheVersion = mysql_get_server_info(MySQL) ;
- TheVersion.SetLength(4);
- return TheVersion;
-
-
-}
-
-//---------------------------------------------------------------------------
-void __fastcall TForm1::KillProcess1Click(TObject *Sender)
-{
-
- if (IsConnect)
- KillPID();
- else
- Application->MessageBox("The Server must be connected", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
-}
-//---------------------------------------------------------------------------
-bool __fastcall TForm1::KillPID()
-{
- String s = "Are you sure to kill the process PID no. ";
- s+= StringGrid2->Cells[0][StringGrid2->Row];
- s+= " of the USER ";
- s+= StringGrid2->Cells[1][StringGrid2->Row];
- unsigned long xx = mysql_thread_id(MySQL);
- unsigned long yy = StrToInt(StringGrid2->Cells[0][StringGrid2->Row]);
- if ( xx != yy)
- {
- if(Application->MessageBox(s.c_str(), "WinMySQLadmin 1.0", MB_YESNOCANCEL | MB_ICONQUESTION ) == IDYES)
- {
- if (!mysql_kill(MySQL,yy))
- {
- GetProcess();
- return true;
- }
- }
- }
- else
- {
- Application->MessageBox("From here you can't kill the PID of this tool", "WinMySQLadmin 1.0", MB_OK | MB_ICONEXCLAMATION);
- return true;
- }
- return true;
-}
-void __fastcall TForm1::FlushThreads1Click(TObject *Sender)
-{
- if (IsConnect)
- {
- if (mysql_refresh(MySQL,REFRESH_THREADS))
- StatusLine->SimpleText = "";
- }
-}
-//---------------------------------------------------------------------------
-
diff --git a/VC++Files/winmysqladmin/main.h b/VC++Files/winmysqladmin/main.h
deleted file mode 100644
index dcb8ad60d7b..00000000000
--- a/VC++Files/winmysqladmin/main.h
+++ /dev/null
@@ -1,314 +0,0 @@
-//---------------------------------------------------------------------------
-#ifndef mainH
-#define mainH
-//---------------------------------------------------------------------------
-#include <Classes.hpp>
-#include <Controls.hpp>
-#include <StdCtrls.hpp>
-#include <Forms.hpp>
-#include <Buttons.hpp>
-#include <ComCtrls.hpp>
-#include <ExtCtrls.hpp>
-#include <Graphics.hpp>
-#include <Grids.hpp>
-#include <ImgList.hpp>
-#include <Menus.hpp>
-#include <Dialogs.hpp>
-#include <string.h>
-
-#define MYWM_NOTIFY (WM_APP+100)
-#define IDC_MYICON 1006
-extern HINSTANCE g_hinst;
-LRESULT IconDrawItem(LPDRAWITEMSTRUCT lpdi);
-//---------------------------------------------------------------------------
-class TForm1 : public TForm
-{
-__published: // IDE-managed Components
- TStatusBar *StatusLine;
- TPanel *Panel1;
- TImage *Image1;
- TLabel *Label1;
- TLabel *Label2;
- TLabel *Label3;
- TLabel *Label8;
- TImage *Image3;
- TImage *Image2;
- TPageControl *PageControl1;
- TTabSheet *TabSheet1;
- TSpeedButton *SpeedButton1;
- TGroupBox *GroupBox1;
- TLabel *Label4;
- TLabel *Label5;
- TLabel *Label6;
- TLabel *Label14;
- TLabel *Label17;
- TEdit *Localhost;
- TEdit *Localuser;
- TEdit *OS;
- TMemo *Memo2;
- TEdit *Edit2;
- TGroupBox *GroupBox2;
- TMemo *Memo3;
- TGroupBox *GroupBox3;
- TLabel *Label13;
- TLabel *Label15;
- TLabel *Label16;
- TLabel *Label7;
- TLabel *Label47;
- TLabel *Label44;
- TLabel *Label42;
- TLabel *Label45;
- TEdit *Edit3;
- TEdit *Edit4;
- TEdit *Edit5;
- TEdit *Edit6;
- TEdit *st29;
- TEdit *st27;
- TEdit *st25;
- TEdit *st28;
- TTabSheet *TabSheet2;
- TTabSheet *TabSheet3;
- TLabel *Label18;
- TSpeedButton *SpeedButton2;
- TEdit *BaseDir;
- TMemo *Memo1;
- TRadioGroup *RadioGroup1;
- TRadioButton *ShareVer;
- TRadioButton *MysqldVer;
- TRadioButton *OptVer;
- TRadioButton *NtVer;
- TButton *Button2;
- TButton *Button3;
- TButton *Button1;
- TTabSheet *TabSheet4;
- TMemo *Memo4;
- TButton *Button5;
- TTabSheet *TabSheet5;
- TStringGrid *StringGrid1;
- TButton *Button11;
- TTabSheet *TabSheet6;
- TStringGrid *StringGrid2;
- TButton *Button10;
- TPopupMenu *PopupMenu1;
- TMenuItem *Showme1;
- TMenuItem *N1;
- TMenuItem *Win9;
- TMenuItem *Swin9;
- TMenuItem *N3;
- TMenuItem *SSW9;
- TMenuItem *N4;
- TMenuItem *ShutDownBoth1;
- TMenuItem *N2;
- TMenuItem *WinNT;
- TMenuItem *ShutDownthisTool1;
- TMenuItem *N5;
- TMenuItem *StopS;
- TMenuItem *N6;
- TMenuItem *RService;
- TMenuItem *N7;
- TMenuItem *Standa;
- TImageList *ImageList1;
- TTimer *Timer1;
- TTimer *Timer2;
- TTimer *Timer3;
- TSpeedButton *SpeedButton3;
- TSpeedButton *Extended;
- TLabel *Label9;
- TEdit *st26;
- TLabel *Label43;
- TEdit *st24;
- TLabel *Label41;
- TEdit *st23;
- TLabel *Label40;
- TEdit *st22;
- TLabel *Label39;
- TTabSheet *TabSheet8;
- TSaveDialog *SaveFileDialog;
- TPrinterSetupDialog *PrinterSetupDialog1;
- TPrintDialog *PrintDialog1;
- TRichEdit *Memo5;
- TGroupBox *GroupBox5;
- TSpeedButton *SpeedButton4;
- TSpeedButton *SpeedButton5;
- TSpeedButton *SpeedButton7;
- TSpeedButton *SpeedButton6;
- TGroupBox *GroupBox6;
- TSpeedButton *SpeedButton8;
- TSpeedButton *SpeedButton9;
- TSpeedButton *SpeedButton10;
- TSpeedButton *SpeedButton11;
- TSpeedButton *SpeedButton12;
- TTabSheet *TabSheet9;
- TImageList *ImageList2;
- TPopupMenu *PopupMenu2;
- TMenuItem *CreateDatabaseS;
- TMenuItem *DeleteDatabaseS;
- TMenuItem *RefreshS;
- TMenuItem *N8;
- TMenuItem *N9;
- TMenuItem *N10;
- TGroupBox *GroupBox7;
- TTreeView *DBView;
- TGroupBox *GroupBox8;
- TTreeView *TableView;
- TGroupBox *GroupBox9;
- TStringGrid *StringGrid4;
- TMenuItem *FlushHosts1;
- TMenuItem *N11;
- TMenuItem *FlushLogs1;
- TMenuItem *N12;
- TMenuItem *FlushTables1;
- TGroupBox *GroupBox10;
- TStringGrid *StringGrid3;
- TImage *Image5;
- TStringGrid *StringGrid5;
- TSpeedButton *SpeedButton13;
- TPopupMenu *PopupMenu4;
- TMenuItem *KillProcess1;
- TMenuItem *N13;
- TMenuItem *FlushThreads1;
- void __fastcall FormCreate(TObject *Sender);
- void __fastcall Showme1Click(TObject *Sender);
- void __fastcall Timer1Timer(TObject *Sender);
- void __fastcall SpeedButton1Click(TObject *Sender);
- void __fastcall Timer2Timer(TObject *Sender);
- void __fastcall Swin9Click(TObject *Sender);
- void __fastcall SSW9Click(TObject *Sender);
- void __fastcall ShutDownBoth1Click(TObject *Sender);
- void __fastcall ShutDownthisTool1Click(TObject *Sender);
- void __fastcall StopSClick(TObject *Sender);
- void __fastcall RServiceClick(TObject *Sender);
- void __fastcall StandaClick(TObject *Sender);
- void __fastcall Button5Click(TObject *Sender);
- void __fastcall Timer3Timer(TObject *Sender);
- void __fastcall Button11Click(TObject *Sender);
- void __fastcall Button10Click(TObject *Sender);
- void __fastcall Button6Click(TObject *Sender);
- void __fastcall Button7Click(TObject *Sender);
- void __fastcall Button8Click(TObject *Sender);
-
- void __fastcall Button2Click(TObject *Sender);
- void __fastcall Button3Click(TObject *Sender);
- void __fastcall Button1Click(TObject *Sender);
- void __fastcall SpeedButton2Click(TObject *Sender);
- void __fastcall Button4Click(TObject *Sender);
- void __fastcall SpeedButton3Click(TObject *Sender);
- void __fastcall ExtendedClick(TObject *Sender);
- void __fastcall SpeedButton4Click(TObject *Sender);
- void __fastcall SpeedButton5Click(TObject *Sender);
- void __fastcall SpeedButton6Click(TObject *Sender);
- void __fastcall SpeedButton7Click(TObject *Sender);
- void __fastcall SpeedButton8Click(TObject *Sender);
- void __fastcall SpeedButton9Click(TObject *Sender);
- void __fastcall SpeedButton10Click(TObject *Sender);
- void __fastcall SpeedButton11Click(TObject *Sender);
- void __fastcall SpeedButton12Click(TObject *Sender);
- void __fastcall DeleteDatabaseSClick(TObject *Sender);
- void __fastcall DBViewClick(TObject *Sender);
- void __fastcall TableViewClick(TObject *Sender);
- void __fastcall TableViewChange(TObject *Sender, TTreeNode *Node);
- void __fastcall DBViewChange(TObject *Sender, TTreeNode *Node);
-
- void __fastcall RefreshSClick(TObject *Sender);
- void __fastcall CreateDatabaseSClick(TObject *Sender);
- void __fastcall FlushHosts1Click(TObject *Sender);
- void __fastcall FlushLogs1Click(TObject *Sender);
- void __fastcall FlushTables1Click(TObject *Sender);
- void __fastcall SpeedButton13Click(TObject *Sender);
- void __fastcall KillProcess1Click(TObject *Sender);
- void __fastcall FlushThreads1Click(TObject *Sender);
-
-
-
-
-
-
-
-private: // User declarations
- void __fastcall DrawItem(TMessage& Msg);
- void __fastcall MyNotify(TMessage& Msg);
- bool __fastcall TrayMessage(DWORD dwMessage);
- HANDLE __fastcall IconHandle(void);
- void __fastcall ToggleState(void);
- PSTR __fastcall TipText(void);
- void __fastcall WMQueryEndSession(TWMQueryEndSession &msg);
- AnsiString __fastcall TheComputer();
- AnsiString __fastcall TheUser();
- AnsiString __fastcall TheOS();
- void __fastcall TakeIP(void);
- void __fastcall GetmemStatus(void);
- void __fastcall ShowHelp(void);
- void __fastcall ContinueLoad(void);
- void __fastcall MyODBC(void);
- void __fastcall IsMyIniUp(void);
- void __fastcall QuickSearch(void);
- AnsiString __fastcall TheWinDir();
- void __fastcall FillMyIni(void);
- void __fastcall GetBaseDir(void);
- bool __fastcall MySQLSignal();
- bool __fastcall mysqldstart();
- bool __fastcall SeekErrFile();
- AnsiString __fastcall TheDir();
- bool __fastcall TheServiceStart();
- bool __fastcall TheServicePause();
- bool __fastcall TheServiceResume();
- bool __fastcall TheServiceStatus();
- bool __fastcall TheServiceCreate();
- bool __fastcall TheServiceRemove();
- bool __fastcall Shutd();
- void __fastcall ClearBox(void);
- bool __fastcall TheServerPath();
- void __fastcall GetServerOptions(void);
- void __fastcall GetReportServer(void);
-
-
- TFileStream *MyFile;
- String FName;
-
- void __fastcall IsMySQLInit(void);
- void __fastcall GetServerStatus(void);
- bool __fastcall GetExtendedStatus();
- bool __fastcall GetProcess();
- bool __fastcall GetVariables();
- bool __fastcall nice_time(AnsiString buff);
- String __fastcall GetString(String k);
- String __fastcall GetNumberServer();
- // pointers for database screen
- TTreeNode *MySQLNode, *MySQLDbs, *MySQLNodeT, *MySQLTbs;
-
- bool __fastcall GetMainRoot();
- bool __fastcall IsDatabase(String Name);
- bool __fastcall IsTable(String Name);
- void __fastcall CleanTree(void);
- void __fastcall CleanGrid(void);
- bool __fastcall IsIndex(String Name);
- void __fastcall CleanGridI(void);
- bool __fastcall KillPID();
-
-
-
-public: // User declarations
- __fastcall TForm1(TComponent* Owner);
- void __fastcall GetServerFile(void);
- void __fastcall CreateMyIniFile(void);
- bool __fastcall CreatingShortCut();
- bool __fastcall CreatingDB();
- void __fastcall OutRefresh(void);
- bool __fastcall CreatingTable(String TheTable);
-
- bool IsConnect ;
-
-
-
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- BEGIN_MESSAGE_MAP
- MESSAGE_HANDLER(WM_DRAWITEM,TMessage,DrawItem)
- MESSAGE_HANDLER(MYWM_NOTIFY,TMessage,MyNotify)
- MESSAGE_HANDLER(WM_QUERYENDSESSION,TWMQueryEndSession,WMQueryEndSession)
- END_MESSAGE_MAP(TForm)
-};
-//---------------------------------------------------------------------------
-extern PACKAGE TForm1 *Form1;
-//---------------------------------------------------------------------------
-#endif
diff --git a/VC++Files/winmysqladmin/mysql.h b/VC++Files/winmysqladmin/mysql.h
deleted file mode 100644
index f01b55f5d3f..00000000000
--- a/VC++Files/winmysqladmin/mysql.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-/* defines for the libmysql library */
-
-#ifndef _mysql_h
-#define _mysql_h
-
-#ifndef MYSQL_SERVER
-#ifdef __cplusplus
-extern "C" {
-#endif
-#endif
-
-#ifndef _global_h /* If not standard header */
-#include <sys/types.h>
-typedef char my_bool;
-#if (defined(_WIN32) || defined(_WIN64)) && !defined(__WIN__)
-#define __WIN__
-#endif
-#if !defined(__WIN__)
-#define STDCALL
-#else
-#define STDCALL __stdcall
-#endif
-typedef char * gptr;
-
-#ifndef ST_USED_MEM_DEFINED
-#define ST_USED_MEM_DEFINED
-typedef struct st_used_mem { /* struct for once_alloc */
- struct st_used_mem *next; /* Next block in use */
- unsigned int left; /* memory left in block */
- unsigned int size; /* size of block */
-} USED_MEM;
-typedef struct st_mem_root {
- USED_MEM *free;
- USED_MEM *used;
- unsigned int min_malloc;
- unsigned int block_size;
- void (*error_handler)(void);
-} MEM_ROOT;
-#endif
-
-#ifndef my_socket_defined
-#ifdef __WIN__
-#define my_socket SOCKET
-#else
-typedef int my_socket;
-#endif
-#endif
-#endif
-#include "mysql_com.h"
-#include "mysql_version.h"
-
-extern unsigned int mysql_port;
-extern char *mysql_unix_port;
-
-#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
-#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
-#define IS_BLOB(n) ((n) & BLOB_FLAG)
-#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR)
-
-typedef struct st_mysql_field {
- char *name; /* Name of column */
- char *table; /* Table of column if column was a field */
- char *def; /* Default value (set by mysql_list_fields) */
- enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
- unsigned int length; /* Width of column */
- unsigned int max_length; /* Max width of selected set */
- unsigned int flags; /* Div flags */
- unsigned int decimals; /* Number of decimals in field */
-} MYSQL_FIELD;
-
-typedef char **MYSQL_ROW; /* return data as array of strings */
-typedef unsigned int MYSQL_FIELD_OFFSET; /* offset to current field */
-
-#if defined(NO_CLIENT_LONG_LONG)
-typedef unsigned long my_ulonglong;
-#elif defined (__WIN__)
-typedef unsigned __int64 my_ulonglong;
-#else
-typedef unsigned long long my_ulonglong;
-#endif
-
-#define MYSQL_COUNT_ERROR (~(my_ulonglong) 0)
-
-typedef struct st_mysql_rows {
- struct st_mysql_rows *next; /* list of rows */
- MYSQL_ROW data;
-} MYSQL_ROWS;
-
-typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
-
-typedef struct st_mysql_data {
- my_ulonglong rows;
- unsigned int fields;
- MYSQL_ROWS *data;
- MEM_ROOT alloc;
-} MYSQL_DATA;
-
-struct st_mysql_options {
- unsigned int connect_timeout,client_flag;
- my_bool compress,named_pipe;
- unsigned int port;
- char *host,*init_command,*user,*password,*unix_socket,*db;
- char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
- my_bool use_ssl; /* if to use SSL or not */
- char *ssl_key; /* PEM key file */
- char *ssl_cert; /* PEM cert file */
- char *ssl_ca; /* PEM CA file */
- char *ssl_capath; /* PEM directory of CA-s? */
-};
-
-enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
- MYSQL_OPT_NAMED_PIPE, MYSQL_INIT_COMMAND,
- MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
- MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME};
-
-enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,
- MYSQL_STATUS_USE_RESULT};
-
-typedef struct st_mysql {
- NET net; /* Communication parameters */
- gptr connector_fd; /* ConnectorFd for SSL */
- char *host,*user,*passwd,*unix_socket,*server_version,*host_info,
- *info,*db;
- unsigned int port,client_flag,server_capabilities;
- unsigned int protocol_version;
- unsigned int field_count;
- unsigned int server_status;
- unsigned long thread_id; /* Id for connection in server */
- my_ulonglong affected_rows;
- my_ulonglong insert_id; /* id if insert on table with NEXTNR */
- my_ulonglong extra_info; /* Used by mysqlshow */
- unsigned long packet_length;
- enum mysql_status status;
- MYSQL_FIELD *fields;
- MEM_ROOT field_alloc;
- my_bool free_me; /* If free in mysql_close */
- my_bool reconnect; /* set to 1 if automatic reconnect */
- struct st_mysql_options options;
- char scramble_buff[9];
- struct charset_info_st *charset;
- unsigned int server_language;
-} MYSQL;
-
-
-typedef struct st_mysql_res {
- my_ulonglong row_count;
- unsigned int field_count, current_field;
- MYSQL_FIELD *fields;
- MYSQL_DATA *data;
- MYSQL_ROWS *data_cursor;
- MEM_ROOT field_alloc;
- MYSQL_ROW row; /* If unbuffered read */
- MYSQL_ROW current_row; /* buffer to current row */
- unsigned long *lengths; /* column lengths of current row */
- MYSQL *handle; /* for unbuffered reads */
- my_bool eof; /* Used my mysql_fetch_row */
-} MYSQL_RES;
-
-/* Functions to get information from the MYSQL and MYSQL_RES structures */
-/* Should definitely be used if one uses shared libraries */
-
-my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);
-unsigned int STDCALL mysql_num_fields(MYSQL_RES *res);
-my_bool STDCALL mysql_eof(MYSQL_RES *res);
-MYSQL_FIELD *STDCALL mysql_fetch_field_direct(MYSQL_RES *res,
- unsigned int fieldnr);
-MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res);
-MYSQL_ROWS * STDCALL mysql_row_tell(MYSQL_RES *res);
-unsigned int STDCALL mysql_field_tell(MYSQL_RES *res);
-
-unsigned int STDCALL mysql_field_count(MYSQL *mysql);
-my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
-my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql);
-unsigned int STDCALL mysql_errno(MYSQL *mysql);
-char * STDCALL mysql_error(MYSQL *mysql);
-char * STDCALL mysql_info(MYSQL *mysql);
-unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
-const char * STDCALL mysql_character_set_name(MYSQL *mysql);
-
-MYSQL * STDCALL mysql_init(MYSQL *mysql);
-#ifdef HAVE_OPENSSL
-int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
- const char *cert, const char *ca,
- const char *capath);
-char * STDCALL mysql_ssl_cipher(MYSQL *mysql);
-int STDCALL mysql_ssl_clear(MYSQL *mysql);
-#endif /* HAVE_OPENSSL */
-MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host,
- const char *user, const char *passwd);
-my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
- const char *passwd, const char *db);
-#if MYSQL_VERSION_ID >= 32200
-MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
- const char *user,
- const char *passwd,
- const char *db,
- unsigned int port,
- const char *unix_socket,
- unsigned int clientflag);
-#else
-MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
- const char *user,
- const char *passwd,
- unsigned int port,
- const char *unix_socket,
- unsigned int clientflag);
-#endif
-void STDCALL mysql_close(MYSQL *sock);
-int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
-int STDCALL mysql_query(MYSQL *mysql, const char *q);
-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,
- enum enum_shutdown_level
- shutdown_level);
-int STDCALL mysql_dump_debug_info(MYSQL *mysql);
-int STDCALL mysql_refresh(MYSQL *mysql,
- unsigned int refresh_options);
-int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
-int STDCALL mysql_ping(MYSQL *mysql);
-char * STDCALL mysql_stat(MYSQL *mysql);
-char * STDCALL mysql_get_server_info(MYSQL *mysql);
-char * STDCALL mysql_get_client_info(void);
-char * STDCALL mysql_get_host_info(MYSQL *mysql);
-unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql);
-MYSQL_RES * STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild);
-MYSQL_RES * STDCALL mysql_list_tables(MYSQL *mysql,const char *wild);
-MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table,
- const char *wild);
-MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql);
-MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql);
-MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql);
-int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
- const char *arg);
-void STDCALL mysql_free_result(MYSQL_RES *result);
-void STDCALL mysql_data_seek(MYSQL_RES *result,
- my_ulonglong offset);
-MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET);
-MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result,
- MYSQL_FIELD_OFFSET offset);
-MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result);
-unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result);
-MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result);
-unsigned long STDCALL mysql_escape_string(char *to,const char *from,
- unsigned long from_length);
-unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
- char *to,const char *from,
- unsigned long length);
-void STDCALL mysql_debug(const char *debug);
-char * STDCALL mysql_odbc_escape_string(MYSQL *mysql,
- char *to,
- unsigned long to_length,
- const char *from,
- unsigned long from_length,
- void *param,
- char *
- (*extend_buffer)
- (void *, char *to,
- unsigned long *length));
-void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
-unsigned int STDCALL mysql_thread_safe(void);
-
-
-#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
-
-/* new api functions */
-
-#define HAVE_MYSQL_REAL_CONNECT
-
-#ifndef MYSQL_SERVER
-#ifdef __cplusplus
-}
-#endif
-#endif
-
-#endif
diff --git a/VC++Files/winmysqladmin/mysql_com.h b/VC++Files/winmysqladmin/mysql_com.h
deleted file mode 100644
index 2a7eb57d745..00000000000
--- a/VC++Files/winmysqladmin/mysql_com.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-/*
-** Common definition between mysql server & client
-*/
-
-#ifndef _mysql_com_h
-#define _mysql_com_h
-
-
-#define NAME_LEN 64 /* Field/table name length */
-#define HOSTNAME_LENGTH 60
-#define USERNAME_LENGTH 16
-
-#define LOCAL_HOST "localhost"
-#define LOCAL_HOST_NAMEDPIPE "."
-
-#if defined(__EMX__) || defined(__OS2__)
-#undef MYSQL_UNIX_ADDR
-#define MYSQL_OS2_ADDR "\\socket\\MySQL"
-#define MYSQL_UNIX_ADDR MYSQL_OS2_ADDR
-#endif
-#if defined(__WIN__) && !defined( _CUSTOMCONFIG_)
-#define MYSQL_NAMEDPIPE "MySQL"
-#define MYSQL_SERVICENAME "MySql"
-#endif /* __WIN__ */
-
-enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
- COM_FIELD_LIST,COM_CREATE_DB,COM_DROP_DB,COM_REFRESH,
- COM_SHUTDOWN,COM_STATISTICS,
- COM_PROCESS_INFO,COM_CONNECT,COM_PROCESS_KILL,
- COM_DEBUG,COM_PING,COM_TIME,COM_DELAYED_INSERT,
- COM_CHANGE_USER, COM_BINLOG_DUMP,
- COM_TABLE_DUMP};
-
-#define NOT_NULL_FLAG 1 /* Field can't be NULL */
-#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
-#define UNIQUE_KEY_FLAG 4 /* Field is part of a unique key */
-#define MULTIPLE_KEY_FLAG 8 /* Field is part of a key */
-#define BLOB_FLAG 16 /* Field is a blob */
-#define UNSIGNED_FLAG 32 /* Field is unsigned */
-#define ZEROFILL_FLAG 64 /* Field is zerofill */
-#define BINARY_FLAG 128
-/* The following are only sent to new clients */
-#define ENUM_FLAG 256 /* field is an enum */
-#define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */
-#define TIMESTAMP_FLAG 1024 /* Field is a timestamp */
-#define SET_FLAG 2048 /* field is a set */
-#define PART_KEY_FLAG 16384 /* Intern; Part of some key */
-#define GROUP_FLAG 32768 /* Intern: Group field */
-#define UNIQUE_FLAG 65536 /* Intern: Used by sql_yacc */
-
-#define REFRESH_GRANT 1 /* Refresh grant tables */
-#define REFRESH_LOG 2 /* Start on new log file */
-#define REFRESH_TABLES 4 /* close all tables */
-#define REFRESH_HOSTS 8 /* Flush host cache */
-#define REFRESH_STATUS 16 /* Flush status variables */
-#define REFRESH_THREADS 32 /* Flush status variables */
-#define REFRESH_SLAVE 64 /* Reset master info and restart slave
- thread */
-#define REFRESH_MASTER 128 /* Remove all bin logs in the index
- and truncate the index */
-
-/* The following can't be set with mysql_refresh() */
-#define REFRESH_READ_LOCK 16384 /* Lock tables for read */
-#define REFRESH_FAST 32768 /* Intern flag */
-
-#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
-#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
-#define CLIENT_LONG_FLAG 4 /* Get all column flags */
-#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
-#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */
-#define CLIENT_COMPRESS 32 /* Can use compression protocol */
-#define CLIENT_ODBC 64 /* Odbc client */
-#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */
-#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */
-#define CLIENT_CHANGE_USER 512 /* Support the mysql_change_user() */
-#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */
-#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
-#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
-#define CLIENT_TRANSACTIONS 8196 /* Client knows about transactions */
-
-#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
-#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
-
-#define MYSQL_ERRMSG_SIZE 200
-#define NET_READ_TIMEOUT 30 /* Timeout on read */
-#define NET_WRITE_TIMEOUT 60 /* Timeout on write */
-#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */
-
-#ifndef Vio_defined
-#define Vio_defined
-#ifdef HAVE_VIO
-class Vio; /* Fill Vio class in C++ */
-#else
-struct st_vio; /* Only C */
-typedef struct st_vio Vio;
-#endif
-#endif
-
-typedef struct st_net {
- Vio* vio;
- my_socket fd; /* For Perl DBI/dbd */
- int fcntl;
- unsigned char *buff,*buff_end,*write_pos,*read_pos;
- char last_error[MYSQL_ERRMSG_SIZE];
- unsigned int last_errno,max_packet,timeout,pkt_nr;
- unsigned char error;
- my_bool return_errno,compress;
- my_bool no_send_ok; /* needed if we are doing several
- queries in one command ( as in LOAD TABLE ... FROM MASTER ),
- and do not want to confuse the client with OK at the wrong time
- */
- unsigned long remain_in_buf,length, buf_length, where_b;
- unsigned int *return_status;
- unsigned char reading_or_writing;
- char save_char;
-} NET;
-
-#define packet_error ((unsigned int) -1)
-
-enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY,
- FIELD_TYPE_SHORT, FIELD_TYPE_LONG,
- FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE,
- FIELD_TYPE_NULL, FIELD_TYPE_TIMESTAMP,
- FIELD_TYPE_LONGLONG,FIELD_TYPE_INT24,
- FIELD_TYPE_DATE, FIELD_TYPE_TIME,
- FIELD_TYPE_DATETIME, FIELD_TYPE_YEAR,
- FIELD_TYPE_NEWDATE,
- FIELD_TYPE_ENUM=247,
- FIELD_TYPE_SET=248,
- FIELD_TYPE_TINY_BLOB=249,
- FIELD_TYPE_MEDIUM_BLOB=250,
- FIELD_TYPE_LONG_BLOB=251,
- FIELD_TYPE_BLOB=252,
- FIELD_TYPE_VAR_STRING=253,
- FIELD_TYPE_STRING=254
-};
-
-#define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compability */
-#define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compability */
-
-
-/* Shutdown/kill enums and constants */
-
-/* Bits for THD::killable. */
-#define MYSQL_SHUTDOWN_KILLABLE_CONNECT (unsigned char)(1 << 0)
-#define MYSQL_SHUTDOWN_KILLABLE_TRANS (unsigned char)(1 << 1)
-#define MYSQL_SHUTDOWN_KILLABLE_LOCK_TABLE (unsigned char)(1 << 2)
-#define MYSQL_SHUTDOWN_KILLABLE_UPDATE (unsigned char)(1 << 3)
-
-enum mysql_enum_shutdown_level {
- /*
- We want levels to be in growing order of hardness (because we use number
- comparisons). Note that DEFAULT does not respect the growing property, but
- it's ok.
- */
- DEFAULT= 0,
- /* wait for existing connections to finish */
- WAIT_CONNECTIONS= MYSQL_SHUTDOWN_KILLABLE_CONNECT,
- /* wait for existing trans to finish */
- WAIT_TRANSACTIONS= MYSQL_SHUTDOWN_KILLABLE_TRANS,
- /* wait for existing updates to finish (=> no partial MyISAM update) */
- WAIT_UPDATES= MYSQL_SHUTDOWN_KILLABLE_UPDATE,
- /* flush InnoDB buffers and other storage engines' buffers*/
- WAIT_ALL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1),
- /* don't flush InnoDB buffers, flush other storage engines' buffers*/
- WAIT_CRITICAL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1) + 1,
- /* 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;
-
-#define net_new_transaction(net) ((net)->pkt_nr=0)
-
-int my_net_init(NET *net, Vio* vio);
-void net_end(NET *net);
-void net_clear(NET *net);
-int net_flush(NET *net);
-int my_net_write(NET *net,const char *packet,unsigned long len);
-int net_write_command(NET *net,unsigned char command,const char *packet,
- unsigned long len);
-int net_real_write(NET *net,const char *packet,unsigned long len);
-unsigned int my_net_read(NET *net);
-
-struct rand_struct {
- unsigned long seed1,seed2,max_value;
- double max_value_dbl;
-};
-
- /* The following is for user defined functions */
-
-enum Item_result {STRING_RESULT,REAL_RESULT,INT_RESULT};
-
-typedef struct st_udf_args
-{
- unsigned int arg_count; /* Number of arguments */
- enum Item_result *arg_type; /* Pointer to item_results */
- char **args; /* Pointer to argument */
- unsigned long *lengths; /* Length of string arguments */
- char *maybe_null; /* Set to 1 for all maybe_null args */
-} UDF_ARGS;
-
- /* This holds information about the result */
-
-typedef struct st_udf_init
-{
- my_bool maybe_null; /* 1 if function can return NULL */
- unsigned int decimals; /* for real functions */
- unsigned int max_length; /* For string functions */
- char *ptr; /* free pointer for function data */
- my_bool const_item; /* 0 if result is independent of arguments */
-} UDF_INIT;
-
- /* Constants when using compression */
-#define NET_HEADER_SIZE 4 /* standard header size */
-#define COMP_HEADER_SIZE 3 /* compression header extra size */
-
- /* Prototypes to password functions */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void randominit(struct rand_struct *,unsigned long seed1,
- unsigned long seed2);
-double rnd(struct rand_struct *);
-void make_scrambled_password(char *to,const char *password);
-void get_salt_from_password(unsigned long *res,const char *password);
-void make_password_from_salt(char *to, unsigned long *hash_res);
-char *scramble(char *to,const char *message,const char *password,
- my_bool old_ver);
-my_bool check_scramble(const char *, const char *message,
- unsigned long *salt,my_bool old_ver);
-char *get_tty_password(char *opt_message);
-void hash_password(unsigned long *result, const char *password);
-#ifdef __cplusplus
-}
-#endif
-
-/* Some other useful functions */
-
-void my_init(void);
-void load_defaults(const char *conf_file, const char **groups,
- int *argc, char ***argv);
-
-#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
-
-#ifdef __WIN__
-#define socket_errno WSAGetLastError()
-#else
-#define socket_errno errno
-#endif
-
-#endif
diff --git a/VC++Files/winmysqladmin/mysql_version.h b/VC++Files/winmysqladmin/mysql_version.h
deleted file mode 100644
index 1f868704fe8..00000000000
--- a/VC++Files/winmysqladmin/mysql_version.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright Abandoned 1996,1999 TCX DataKonsult AB & Monty Program KB & Detron HB
- This file is public domain and comes with NO WARRANTY of any kind */
-
-/* Version numbers for protocol & mysqld */
-
-#ifdef _CUSTOMCONFIG_
- #include <custom_conf.h>
-#else
-#define PROTOCOL_VERSION 10
-#define MYSQL_SERVER_VERSION "3.23.22-beta"
-#define FRM_VER 6
-#define MYSQL_VERSION_ID 32322
-#define MYSQL_PORT 3306
-#define MYSQL_UNIX_ADDR "/tmp/mysql.sock"
-
-/* mysqld compile time options */
-#ifndef MYSQL_CHARSET
-#define MYSQL_CHARSET "latin1"
-#endif
-#endif
diff --git a/VC++Files/winmysqladmin/winmysqladmin.cpp b/VC++Files/winmysqladmin/winmysqladmin.cpp
deleted file mode 100644
index 591b7518fa3..00000000000
--- a/VC++Files/winmysqladmin/winmysqladmin.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//---------------------------------------------------------------------------
-#include <vcl.h>
-#pragma hdrstop
-HINSTANCE g_hinst;
-USERES("winmysqladmin.res");
-USEFORM("main.cpp", Form1);
-USEFORM("initsetup.cpp", Form2);
-USEFORM("db.cpp", dbfrm);
-USELIB("lib\mysqlclient.lib");
-USELIB("lib\myisammrg.lib");
-USELIB("lib\heap.lib");
-USELIB("lib\isam.lib");
-USELIB("lib\merge.lib");
-USELIB("lib\myisam.lib");
-USELIB("lib\mysys.lib");
-USELIB("lib\regex.lib");
-USELIB("lib\strings.lib");
-USELIB("lib\zlib.lib");
-//---------------------------------------------------------------------------
-WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
-{
- try
- {
- Application->Initialize();
- Application->HelpFile = "C:\\mysql\\bin\\WINMYSQLADMIN.HLP";
- Application->Title = "WinMySQLadmin 1.0";
- Application->CreateForm(__classid(TForm1), &Form1);
- Application->CreateForm(__classid(TForm2), &Form2);
- Application->CreateForm(__classid(Tdbfrm), &dbfrm);
- Application->Run();
- }
- catch (Exception &exception)
- {
- Application->ShowException(&exception);
- }
- return 0;
-}
-//---------------------------------------------------------------------------
diff --git a/VC++Files/zlib/zlib.vcproj b/VC++Files/zlib/zlib.vcproj
new file mode 100755
index 00000000000..ee17d915a1a
--- /dev/null
+++ b/VC++Files/zlib/zlib.vcproj
@@ -0,0 +1,483 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="zlib"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\debug"
+ IntermediateDirectory=".\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ OptimizeForProcessor="2"
+ PreprocessorDefinitions="_DEBUG;__WIN32__;_WINDOWS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\debug/zlib.pch"
+ AssemblerListingLocation=".\debug/"
+ ObjectFile=".\debug/"
+ ProgramDataBaseFileName=".\debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="1"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_debug\zlib.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="authent|Win32"
+ OutputDirectory=".\zlib___Win32_authent"
+ IntermediateDirectory=".\zlib___Win32_authent"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\zlib___Win32_authent/zlib.pch"
+ AssemblerListingLocation=".\zlib___Win32_authent/"
+ ObjectFile=".\zlib___Win32_authent/"
+ ProgramDataBaseFileName=".\zlib___Win32_authent/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\zlib.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\release"
+ IntermediateDirectory=".\release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OptimizeForProcessor="2"
+ PreprocessorDefinitions="DBUG_OFF;_WINDOWS;NDEBUG"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\release/zlib.pch"
+ AssemblerListingLocation=".\release/"
+ ObjectFile=".\release/"
+ ProgramDataBaseFileName=".\release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\lib_release\zlib.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="adler32.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="compress.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="crc32.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="crc32.h">
+ </File>
+ <File
+ RelativePath="deflate.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="deflate.h">
+ </File>
+ <File
+ RelativePath="gzio.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="infback.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="inffast.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="inffast.h">
+ </File>
+ <File
+ RelativePath="inffixed.h">
+ </File>
+ <File
+ RelativePath="inflate.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="inflate.h">
+ </File>
+ <File
+ RelativePath="inftrees.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="inftrees.h">
+ </File>
+ <File
+ RelativePath="inftrees.h">
+ </File>
+ <File
+ RelativePath="trees.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="trees.h">
+ </File>
+ <File
+ RelativePath="uncompr.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="zconf.h">
+ </File>
+ <File
+ RelativePath="zlib.h">
+ </File>
+ <File
+ RelativePath="zutil.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="authent|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="zutil.h">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/acinclude.m4 b/acinclude.m4
deleted file mode 100644
index 9c7271f7cc9..00000000000
--- a/acinclude.m4
+++ /dev/null
@@ -1,1999 +0,0 @@
-# Local macros for automake & autoconf
-
-
-AC_DEFUN([MYSQL_CHECK_READLINE_DECLARES_HIST_ENTRY], [
- AC_CACHE_CHECK([HIST_ENTRY is declared in readline/readline.h], mysql_cv_hist_entry_declared,
- AC_TRY_COMPILE(
- [
- #include "stdio.h"
- #include "readline/readline.h"
- ],
- [
- HIST_ENTRY entry;
- ],
- [
- mysql_cv_hist_entry_declared=yes
- AC_DEFINE_UNQUOTED(HAVE_HIST_ENTRY, [1],
- [HIST_ENTRY is defined in the outer libeditreadline])
- ],
- [mysql_cv_libedit_interface=no]
- )
- )
-])
-
-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], [1],
- [used libedit interface (can we dereference result of rl_completion_entry_function)])
- ],
- [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], [1],
- [used new readline interface (are rl_completion_func_t and rl_compentry_func_t defined)])
- ],
- [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_PUSH(C++)
-if test "$ac_cv_prog_gxx" = "yes"
-then
- # Add -Werror, remove -fbranch-probabilities (Bug #268)
- 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_POP(C++)
-AC_DEFINE_UNQUOTED([SOCKET_SIZE_TYPE], [$mysql_cv_btype_last_arg_accept],
- [The base type of the last arg to 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],
- [The return type of qsort (int or void).])
-if test "$mysql_cv_type_qsort" = "void"
-then
- AC_DEFINE_UNQUOTED([QSORT_TYPE_IS_VOID], [1], [qsort returns void])
-fi
-])
-
-#---START: Figure out whether to use 'struct rlimit' or 'struct rlimit64'
-AC_DEFUN([MYSQL_TYPE_STRUCT_RLIMIT],
-[ac_save_CXXFLAGS="$CXXFLAGS"
-AC_CACHE_CHECK([struct type to use with setrlimit], mysql_cv_btype_struct_rlimit,
-AC_LANG_PUSH(C++)
-if test "$ac_cv_prog_gxx" = "yes"
-then
- # Add -Werror, remove -fbranch-probabilities (Bug #268)
- CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'`
-fi
-mysql_cv_btype_struct_rlimit=none
-[AC_TRY_COMPILE([#if defined(inline)
-#undef inline
-#endif
-#include <stdlib.h>
-#include <sys/resource.h>
-],
-[struct rlimit64 rl; setrlimit(RLIMIT_CORE, &rl);],
-mysql_cv_btype_struct_rlimit="struct rlimit64")]
-if test "$mysql_cv_btype_struct_rlimit" = "none"; then
-mysql_cv_btype_struct_rlimit="struct rlimit"
-fi)
-AC_LANG_POP(C++)
-AC_DEFINE_UNQUOTED([STRUCT_RLIMIT], [$mysql_cv_btype_struct_rlimit],
- [The struct rlimit type to use with setrlimit])
-CXXFLAGS="$ac_save_CXXFLAGS"
-])
-#---END:
-
-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], [1],
- [Timespec has a ts_sec instead of tv_sev])
-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], [1], [Have the tzname variable])
-fi
-])
-
-
-dnl Define zlib paths to point at bundled zlib
-
-AC_DEFUN([MYSQL_USE_BUNDLED_ZLIB], [
-ZLIB_INCLUDES="-I\$(top_srcdir)/zlib"
-ZLIB_LIBS="\$(top_builddir)/zlib/libz.la"
-dnl Omit -L$pkglibdir as it's always in the list of mysql_config deps.
-ZLIB_DEPS="-lz"
-zlib_dir="zlib"
-AC_SUBST([zlib_dir])
-mysql_cv_compress="yes"
-])
-
-dnl Auxiliary macro to check for zlib at given path
-
-AC_DEFUN([MYSQL_CHECK_ZLIB_DIR], [
-save_INCLUDES="$INCLUDES"
-save_LIBS="$LIBS"
-INCLUDES="$INCLUDES $ZLIB_INCLUDES"
-LIBS="$LIBS $ZLIB_LIBS"
-AC_CACHE_VAL([mysql_cv_compress],
- [AC_TRY_LINK([#include <zlib.h>],
- [return compress(0, (unsigned long*) 0, "", 0);],
- [mysql_cv_compress="yes"
- AC_MSG_RESULT([ok])],
- [mysql_cv_compress="no"])
- ])
-INCLUDES="$save_INCLUDES"
-LIBS="$save_LIBS"
-])
-
-dnl MYSQL_CHECK_ZLIB_WITH_COMPRESS
-dnl ------------------------------------------------------------------------
-dnl @synopsis MYSQL_CHECK_ZLIB_WITH_COMPRESS
-dnl
-dnl Provides the following configure options:
-dnl --with-zlib-dir=DIR
-dnl Possible DIR values are:
-dnl - "no" - the macro will disable use of compression functions
-dnl - "bundled" - means use zlib bundled along with MySQL sources
-dnl - empty, or not specified - the macro will try default system
-dnl library (if present), and in case of error will fall back to
-dnl bundled zlib
-dnl - zlib location prefix - given location prefix, the macro expects
-dnl to find the library headers in $prefix/include, and binaries in
-dnl $prefix/lib. If zlib headers or binaries weren't found at $prefix, the
-dnl macro bails out with error.
-dnl
-dnl If the library was found, this function #defines HAVE_COMPRESS
-dnl and configure variables ZLIB_INCLUDES (i.e. -I/path/to/zlib/include),
-dnl ZLIB_LIBS (i. e. -L/path/to/zlib/lib -lz) and ZLIB_DEPS which is
-dnl used in mysql_config and is always the same as ZLIB_LIBS except to
-dnl when we use the bundled zlib. In the latter case ZLIB_LIBS points to the
-dnl build dir ($top_builddir/zlib), while mysql_config must point to the
-dnl installation dir ($pkglibdir), so ZLIB_DEPS is set to point to
-dnl $pkglibdir.
-
-AC_DEFUN([MYSQL_CHECK_ZLIB_WITH_COMPRESS], [
-AC_MSG_CHECKING([for zlib compression library])
-case $SYSTEM_TYPE in
-*netware* | *modesto*)
- AC_MSG_RESULT(ok)
- AC_DEFINE([HAVE_COMPRESS], [1], [Define to enable compression support])
- ;;
- *)
- AC_ARG_WITH([zlib-dir],
- AC_HELP_STRING([--with-zlib-dir=DIR],
- [Provide MySQL with a custom location of
- compression library. Given DIR, zlib library is
- assumed to be in $DIR/lib and header files
- in $DIR/include. Specify "bundled" to use
- bundled zlib.]),
- [mysql_zlib_dir=${withval}],
- [mysql_zlib_dir=""])
- case "$mysql_zlib_dir" in
- "no")
- mysql_cv_compress="no"
- AC_MSG_RESULT([disabled])
- ;;
- "bundled")
- MYSQL_USE_BUNDLED_ZLIB
- AC_MSG_RESULT([using bundled zlib])
- ;;
- "")
- ZLIB_INCLUDES=""
- ZLIB_LIBS="-lz"
- MYSQL_CHECK_ZLIB_DIR
- if test "$mysql_cv_compress" = "no"; then
- MYSQL_USE_BUNDLED_ZLIB
- AC_MSG_RESULT([system-wide zlib not found, using one bundled with MySQL])
- fi
- ;;
- *)
- if test -f "$mysql_zlib_dir/lib/libz.a" -a \
- -f "$mysql_zlib_dir/include/zlib.h"; then
- ZLIB_INCLUDES="-I$mysql_zlib_dir/include"
- ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz"
- MYSQL_CHECK_ZLIB_DIR
- fi
- if test "x$mysql_cv_compress" != "xyes"; then
- AC_MSG_ERROR([headers or binaries were not found in $mysql_zlib_dir/{include,lib}])
- fi
- ;;
- esac
- if test "$mysql_cv_compress" = "yes"; then
- if test "x$ZLIB_DEPS" = "x"; then
- ZLIB_DEPS="$ZLIB_LIBS"
- fi
- AC_SUBST([ZLIB_LIBS])
- AC_SUBST([ZLIB_DEPS])
- AC_SUBST([ZLIB_INCLUDES])
- AC_DEFINE([HAVE_COMPRESS], [1], [Define to enable compression support])
- fi
- ;;
-esac
-])
-
-dnl ------------------------------------------------------------------------
-
-#---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], [1], [system headers define 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], [1], [system headers define 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], [1], [system headers define 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], [1], [system headers define 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], [1],
- [pthread_yield that doesn't take any arguments])
-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], [1],
- [pthread_yield function with one argument])
-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], [1], [fp_except from ieeefp.h])
-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, [1],
- [Signal handling is POSIX (sigset/sighold, etc)])
-elif test "$mysql_cv_signal_vintage" = "4.2bsd"; then
-AC_DEFINE([HAVE_BSD_SIGNALS], [1], [BSD style signals])
-elif test "$mysql_cv_signal_vintage" = svr3; then
-AC_DEFINE(HAVE_USG_SIGHOLD, [1], [sighold() is present and usable])
-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, [1], [getpwent() declaration present])
-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], [1],
- [READLINE: your system defines TIOCGWINSZ in sys/ioctl.h.])
-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], [1], [Do we have FIONREAD])
-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, [1],
- [declaration of TIOCSTAT in sys/ioctl.h])
-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, [1],
- [d_ino member present in struct dirent])
-fi
-])
-
-AC_DEFUN([MYSQL_STRUCT_DIRENT_D_NAMLEN],
-[AC_REQUIRE([AC_HEADER_DIRENT])
-AC_MSG_CHECKING(if struct dirent has a d_namlen member)
-AC_CACHE_VAL(mysql_cv_dirent_has_dnamlen,
-[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 = (int)d.d_namlen;
-], mysql_cv_dirent_has_dnamlen=yes, mysql_cv_dirent_has_dnamlen=no)])
-AC_MSG_RESULT($mysql_cv_dirent_has_dnamlen)
-if test "$mysql_cv_dirent_has_dnamlen" = "yes"; then
-AC_DEFINE(STRUCT_DIRENT_HAS_D_NAMLEN, [1],
- [d_namlen member present in struct dirent])
-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, [1], [sighandler type is void (*signal ()) ();])
-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], [1], [bool is not defined by all C++ compilators])
-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, 1)
- 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], [1], [If we have a working alloca() implementation])
- 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, 1)
-
- 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, 1)
- 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 /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/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
- 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 "$TARGET_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[=DIR] 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" != "no"
- then
- if test "$openssl" != "yes"
- then
- if test -z "$openssl_includes"
- then
- openssl_includes="$openssl/include"
- fi
- if test -z "$openssl_libs"
- then
- openssl_libs="$openssl/lib"
- fi
- fi
- MYSQL_FIND_OPENSSL([$openssl_includes], [$openssl_libs])
- #force VIO use
- vio_dir="vio"
- vio_libs="../vio/libvio.la"
- AC_DEFINE([HAVE_VIO], [1], [Virtual IO])
- 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], [1], [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
- else
- AC_MSG_RESULT(no)
- if test ! -z "$openssl_includes"
- then
- AC_MSG_ERROR(Can't have --with-openssl-includes without --with-openssl);
- fi
- if test ! -z "$openssl_libs"
- then
- AC_MSG_ERROR(Can't have --with-openssl-libs without --with-openssl);
- fi
- fi
- AC_SUBST(openssl_libs)
- AC_SUBST(openssl_includes)
-])
-
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_BIG_TABLES
-dnl Sets BIG_TABLES if --with-big-tables is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_BIG_TABLES], [
- AC_ARG_WITH([big-tables],
- [
- --with-big-tables Support tables with more than 4 G rows even on 32 bit platforms],
- [bigtables="$withval"],
- [bigtables=no])
- AC_MSG_CHECKING([for big tables support])
-
- case "$bigtables" in
- yes )
- AC_DEFINE([BIG_TABLES], [1], [Support big tables])
- AC_MSG_RESULT([yes])
- ;;
- * )
- AC_MSG_RESULT([no])
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_BIG_TABLES SECTION
-dnl ---------------------------------------------------------------------------
-
-
-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], [1], [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], [1], [Using old ISAM tables])
- 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], [1], [Using 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_EXAMPLEDB
-dnl Sets HAVE_EXAMPLE_DB if --with-example-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_EXAMPLEDB], [
- AC_ARG_WITH([example-storage-engine],
- [
- --with-example-storage-engine
- Enable the Example Storage Engine],
- [exampledb="$withval"],
- [exampledb=no])
- AC_MSG_CHECKING([for example storage engine])
-
- case "$exampledb" in
- yes )
- AC_DEFINE([HAVE_EXAMPLE_DB], [1], [Builds Example DB])
- AC_MSG_RESULT([yes])
- [exampledb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [exampledb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_EXAMPLE SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_BLACKHOLEDB
-dnl Sets HAVE_BLACKHOLE_DB if --with-blackhole-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_BLACKHOLEDB], [
- AC_ARG_WITH([blackhole-storage-engine],
- [
- --with-blackhole-storage-engine
- Enable the Blackhole Storage Engine],
- [blackholedb="$withval"],
- [blackholedb=no])
- AC_MSG_CHECKING([for blackhole storage engine])
-
- case "$blackholedb" in
- yes )
- AC_DEFINE([HAVE_BLACKHOLE_DB], [1], [Builds Blackhole Storage Engine])
- AC_MSG_RESULT([yes])
- [blackholedb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [blackholedb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_BLACKHOLE 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], [1], [Builds Archive Storage Engine])
- 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_CSVDB
-dnl Sets HAVE_CSV_DB if --with-csv-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_CSVDB], [
- AC_ARG_WITH([csv-storage-engine],
- [
- --with-csv-storage-engine
- Enable the CSV Storage Engine],
- [csvdb="$withval"],
- [csvdb=no])
- AC_MSG_CHECKING([for csv storage engine])
-
- case "$csvdb" in
- yes )
- AC_DEFINE([HAVE_CSV_DB], [1], [Builds the CSV Storage Engine])
- AC_MSG_RESULT([yes])
- [csvdb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [csvdb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_CSV 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-sci],
- AC_HELP_STRING([--with-ndb-sci=DIR],
- [Provide MySQL with a custom location of
- sci library. Given DIR, sci library is
- assumed to be in $DIR/lib and header files
- in $DIR/include.]),
- [mysql_sci_dir=${withval}],
- [mysql_sci_dir=""])
-
- case "$mysql_sci_dir" in
- "no" )
- have_ndb_sci=no
- AC_MSG_RESULT([-- not including sci transporter])
- ;;
- * )
- if test -f "$mysql_sci_dir/lib/libsisci.a" -a \
- -f "$mysql_sci_dir/include/sisci_api.h"; then
- NDB_SCI_INCLUDES="-I$mysql_sci_dir/include"
- NDB_SCI_LIBS="-L$mysql_sci_dir/lib -lsisci"
- AC_MSG_RESULT([-- including sci transporter])
- AC_DEFINE([NDB_SCI_TRANSPORTER], [1],
- [Including Ndb Cluster DB sci transporter])
- AC_SUBST(NDB_SCI_INCLUDES)
- AC_SUBST(NDB_SCI_LIBS)
- have_ndb_sci="yes"
- AC_MSG_RESULT([found sci transporter in $mysql_sci_dir/{include, lib}])
- else
- AC_MSG_RESULT([could not find sci transporter in $mysql_sci_dir/{include, lib}])
- fi
- ;;
- esac
-
- 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_ARG_WITH([ndb-port],
- [
- --with-ndb-port Port for NDB Cluster management server],
- [ndb_port="$withval"],
- [ndb_port="default"])
- AC_ARG_WITH([ndb-port-base],
- [
- --with-ndb-port-base Base port for NDB Cluster transporters],
- [ndb_port_base="$withval"],
- [ndb_port_base="default"])
- AC_ARG_WITH([ndb-debug],
- [
- --without-ndb-debug Disable special ndb debug features],
- [ndb_debug="$withval"],
- [ndb_debug="default"])
- AC_ARG_WITH([ndb-ccflags],
- AC_HELP_STRING([--with-ndb-ccflags=CFLAGS],
- [Extra CFLAGS for ndb compile]),
- [ndb_ccflags=${withval}],
- [ndb_ccflags=""])
-
- case "$ndb_ccflags" in
- "yes")
- AC_MSG_RESULT([The --ndb-ccflags option requires a parameter (passed to CC for ndb compilation)])
- ;;
- *)
- ndb_cxxflags_fix="$ndb_cxxflags_fix $ndb_ccflags"
- ;;
- esac
-
- AC_MSG_CHECKING([for NDB Cluster options])
- AC_MSG_RESULT([])
-
- 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
-
- case "$ndb_debug" in
- yes )
- AC_MSG_RESULT([-- including ndb extra debug options])
- have_ndb_debug="yes"
- ;;
- full )
- AC_MSG_RESULT([-- including ndb extra extra debug options])
- have_ndb_debug="full"
- ;;
- no )
- AC_MSG_RESULT([-- not including ndb extra debug options])
- have_ndb_debug="no"
- ;;
- * )
- have_ndb_debug="default"
- ;;
- esac
-
- AC_MSG_RESULT([done.])
-])
-
-AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
- AC_ARG_WITH([ndbcluster],
- [
- --with-ndbcluster Include the NDB Cluster table handler],
- [ndbcluster="$withval"],
- [ndbcluster=no])
-
- AC_MSG_CHECKING([for NDB Cluster])
-
- have_ndbcluster=no
- ndbcluster_includes=
- ndbcluster_libs=
- ndb_mgmclient_libs=
- case "$ndbcluster" in
- yes )
- AC_MSG_RESULT([Using NDB Cluster])
- AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB])
- have_ndbcluster="yes"
- ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi"
- ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a"
- ndbcluster_system_libs=""
- ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la"
- 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)
- AC_SUBST(ndb_mgmclient_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,
- [makes 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,
- [Large files support 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([$ac_declaration
-@%:@include <stdlib.h>],
- [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/bdb/dist/configure.ac b/bdb/dist/configure.ac
index 98cf0f63b39..0bf53972f54 100644
--- a/bdb/dist/configure.ac
+++ b/bdb/dist/configure.ac
@@ -161,7 +161,8 @@ bsdi*) optimize_def="-O2";;
freebsd*)
optimize_def="-O2"
CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE"
- LDFLAGS="$LDFLAGS -pthread";;
+ #LDFLAGS="$LDFLAGS -pthread"
+ ;;
hpux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT";;
irix*) optimize_def="-O2"
CPPFLAGS="$CPPFLAGS -D_SGI_MP_SOURCE";;
diff --git a/client/Makefile.am b/client/Makefile.am
index 1e8851fb3b9..d47e9f98f5e 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -16,6 +16,11 @@
# This file is public domain and comes with NO WARRANTY of any kind
+if HAVE_YASSL
+ yassl_dummy_link_fix= $(top_srcdir)/extra/yassl/src/dummy.cpp
+else
+ yassl_dummy_link_fix=
+endif
#AUTOMAKE_OPTIONS = nostdinc
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_srcdir)/regex $(openssl_includes)
@@ -23,18 +28,26 @@ LIBS = @CLIENT_LIBS@
LDADD= @CLIENT_EXTRA_LDFLAGS@ \
$(top_builddir)/libmysql/libmysqlclient.la
bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \
- mysqldump mysqlimport mysqltest mysqlbinlog mysqlmanagerc mysqlmanager-pwgen
+ mysqldump mysqlimport mysqltest mysqlbinlog \
+ mysqltestmanagerc mysqltestmanager-pwgen
noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
client_priv.h
mysql_SOURCES = mysql.cc readline.cc sql_string.cc completion_hash.cc
mysqladmin_SOURCES = mysqladmin.cc
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
-mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
-mysqltest_SOURCES= mysqltest.c $(top_srcdir)/mysys/my_getsystime.c
+mysqltest_SOURCES= mysqltest.c $(top_srcdir)/mysys/my_getsystime.c \
+ $(yassl_dummy_link_fix)
mysqltest_LDADD = $(top_builddir)/regex/libregex.a $(LDADD)
-mysqlbinlog_SOURCES = mysqlbinlog.cc ../mysys/mf_tempdir.c
-mysqlmanagerc_SOURCES = mysqlmanagerc.c
-sql_src=log_event.h log_event.cc
+mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c $(top_srcdir)/mysys/my_new.cc
+mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
+mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c
+mysqltestmanagerc_SOURCES= mysqlmanagerc.c $(yassl_dummy_link_fix)
+mysqlcheck_SOURCES= mysqlcheck.c $(yassl_dummy_link_fix)
+mysqlshow_SOURCES= mysqlshow.c $(yassl_dummy_link_fix)
+mysqldump_SOURCES= mysqldump.c $(yassl_dummy_link_fix)
+mysqlimport_SOURCES= mysqlimport.c $(yassl_dummy_link_fix)
+sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc
+strings_src=decimal.c
# Fix for mit-threads
DEFS = -DUNDEF_THREADS_HACK
@@ -43,7 +56,11 @@ link_sources:
for f in $(sql_src) ; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(top_srcdir)/sql/$$f $(srcdir)/$$f; \
- done;
+ done; \
+ for f in $(strings_src) ; do \
+ rm -f $(srcdir)/$$f; \
+ @LN_CP_F@ $(top_srcdir)/strings/$$f $(srcdir)/$$f; \
+ done;
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/client/client_priv.h b/client/client_priv.h
index 37ed407de68..18102fa8b16 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -45,10 +45,11 @@ enum options_client
OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS,
OPT_START_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
- OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY
+ OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY, OPT_COUNT,
#ifdef HAVE_NDBCLUSTER_DB
- ,OPT_NDBCLUSTER,OPT_NDB_CONNECTSTRING
+ OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING,
#endif
- ,OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_DROP_DATABASE,
+ OPT_TRIGGERS,
+ OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
OPT_AUTO_CLOSE
};
diff --git a/client/mysql.cc b/client/mysql.cc
index be1541faaf5..05dfcbeccba 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -44,7 +44,7 @@
#include <locale.h>
#endif
-const char *VER= "14.7";
+const char *VER= "14.12";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -135,7 +135,8 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1,
default_charset_used= 0, opt_secure_auth= 0,
- default_pager_set= 0, opt_sigint_ignore= 0;
+ default_pager_set= 0, opt_sigint_ignore= 0,
+ show_warnings = 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;
@@ -144,6 +145,7 @@ static char *current_host,*current_db,*current_user=0,*opt_password=0,
*current_prompt=0, *delimiter_str= 0,
*default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
static char *histfile;
+static char *histfile_tmp;
static String glob_buffer,old_buffer;
static String processed_prompt;
static char *full_username=0,*part_username=0,*default_prompt=0;
@@ -154,6 +156,8 @@ static char mysql_charsets_dir[FN_REFLEN+1];
static const char *xmlmeta[] = {
"&", "&amp;",
"<", "&lt;",
+ ">", "&gt;",
+ "\"", "&quot;",
0, 0
};
static const char *day_names[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
@@ -191,14 +195,15 @@ static int com_quit(String *str,char*),
com_use(String *str,char*), com_source(String *str, char*),
com_rehash(String *str, char*), com_tee(String *str, char*),
com_notee(String *str, char*),
- com_prompt(String *str, char*), com_delimiter(String *str, char*);
+ com_prompt(String *str, char*), com_delimiter(String *str, char*),
+ com_warnings(String *str, char*), com_nowarnings(String *str, char*);
#ifdef USE_POPEN
static int com_nopager(String *str, char*), com_pager(String *str, char*),
com_edit(String *str,char*), com_shell(String *str, char *);
#endif
-static int read_lines(bool execute_commands);
+static int read_and_execute(bool interactive);
static int sql_connect(char *host,char *database,char *user,char *password,
uint silent);
static int put_info(const char *str,INFO_TYPE info,uint error=0,
@@ -232,7 +237,7 @@ static COMMANDS commands[] = {
{ "connect",'r', com_connect,1,
"Reconnect to the server. Optional arguments are db and host." },
{ "delimiter", 'd', com_delimiter, 1,
- "Set query delimiter. " },
+ "Set statement delimiter. NOTE: Takes the rest of the line as new delimiter." },
#ifdef USE_POPEN
{ "edit", 'e', com_edit, 0, "Edit command with $EDITOR."},
#endif
@@ -263,6 +268,10 @@ static COMMANDS commands[] = {
"Set outfile [to_outfile]. Append everything into given outfile." },
{ "use", 'u', com_use, 1,
"Use another database. Takes database name as argument." },
+ { "warnings", 'W', com_warnings, 0,
+ "Show warnings after every statement." },
+ { "nowarning", 'w', com_nowarnings, 0,
+ "Don't show warnings after every statement." },
/* Get bash-like expansion for some commands */
{ "create table", 0, 0, 0, ""},
{ "create database", 0, 0, 0, ""},
@@ -320,6 +329,7 @@ static void print_table_data_html(MYSQL_RES *result);
static void print_table_data_xml(MYSQL_RES *result);
static void print_tab_data(MYSQL_RES *result);
static void print_table_data_vertically(MYSQL_RES *result);
+static void print_warnings(void);
static ulong start_timer(void);
static void end_timer(ulong start_time,char *buff);
static void mysql_end_timer(ulong start_time,char *buff);
@@ -330,16 +340,15 @@ static sig_handler mysql_end(int sig);
int main(int argc,char *argv[])
{
char buff[80];
- char *defaults, *extra_defaults;
- char *emb_argv[3];
- int emb_argc= 1;
+ char *defaults, *extra_defaults, *group_suffix;
+ char *emb_argv[4];
+ int emb_argc;
- emb_argv[0]= argv[0];
- get_defaults_files(argc, argv, &defaults, &extra_defaults);
- if (defaults)
- emb_argv[emb_argc++]= defaults;
- if (extra_defaults)
- emb_argv[emb_argc++]= extra_defaults;
+ /* Get --defaults-xxx args for mysql_server_init() */
+ emb_argc= get_defaults_options(argc, argv, &defaults, &extra_defaults,
+ &group_suffix)+1;
+ memcpy((char*) emb_argv, (char*) argv, emb_argc * sizeof(*argv));
+ emb_argv[emb_argc]= 0;
MY_INIT(argv[0]);
DBUG_ENTER("main");
@@ -423,7 +432,7 @@ int main(int argc,char *argv[])
put_info((char*) glob_buffer.ptr(),INFO_INFO);
#ifdef HAVE_READLINE
- initialize_readline(my_progname);
+ initialize_readline((char*) my_progname);
if (!status.batch && !quick && !opt_html && !opt_xml)
{
/* read-history from file, default ~/.mysql_history*/
@@ -442,6 +451,13 @@ int main(int argc,char *argv[])
if (verbose)
tee_fprintf(stdout, "Reading history-file %s\n",histfile);
read_history(histfile);
+ if (!(histfile_tmp= (char*) my_malloc((uint) strlen(histfile) + 5,
+ MYF(MY_WME))))
+ {
+ fprintf(stderr, "Couldn't allocate memory for temp histfile!\n");
+ exit(1);
+ }
+ sprintf(histfile_tmp, "%s.TMP", histfile);
}
}
#endif
@@ -452,7 +468,7 @@ int main(int argc,char *argv[])
"Type 'help [[%]function name[%]]' to get help on usage of function.\n");
#endif
put_info(buff,INFO_INFO);
- status.exit_status=read_lines(1); // read lines and execute them
+ status.exit_status= read_and_execute(!status.batch);
if (opt_outfile)
end_tee();
mysql_end(0);
@@ -470,7 +486,8 @@ sig_handler mysql_end(int sig)
/* write-history */
if (verbose)
tee_fprintf(stdout, "Writing history-file %s\n",histfile);
- write_history(histfile);
+ if (!write_history(histfile_tmp))
+ my_rename(histfile_tmp, histfile, MYF(MY_WME));
}
batch_readline_end(status.line_buff);
completion_hash_free(&ht);
@@ -485,6 +502,7 @@ sig_handler mysql_end(int sig)
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
my_free(opt_mysql_unix_port,MYF(MY_ALLOW_ZERO_PTR));
my_free(histfile,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(histfile_tmp,MYF(MY_ALLOW_ZERO_PTR));
my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
my_free(current_user,MYF(MY_ALLOW_ZERO_PTR));
@@ -610,7 +628,7 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
- (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
+ (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
0},
{"prompt", OPT_PROMPT, "Set the mysql prompt to this value.",
(gptr*) &current_prompt, (gptr*) &current_prompt, 0, GET_STR_ALLOC,
@@ -685,6 +703,9 @@ static struct my_option my_long_options[] =
{"secure-auth", OPT_SECURE_AUTH, "Refuse client connecting to server if it"
" uses old (pre-4.1.1) protocol", (gptr*) &opt_secure_auth,
(gptr*) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
+ (gptr*) &show_warnings, (gptr*) &show_warnings, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -936,7 +957,7 @@ static int get_options(int argc, char **argv)
return(0);
}
-static int read_lines(bool execute_commands)
+static int read_and_execute(bool interactive)
{
#if defined(OS2) || defined(__NETWARE__)
char linebuffer[254];
@@ -956,7 +977,7 @@ static int read_lines(bool execute_commands)
for (;;)
{
- if (status.batch || !execute_commands)
+ if (!interactive)
{
line=batch_readline(status.line_buff);
line_number++;
@@ -1049,7 +1070,7 @@ static int read_lines(bool execute_commands)
Check if line is a mysql command line
(We want to allow help, print and clear anywhere at line start
*/
- if (execute_commands && (named_cmds || glob_buffer.is_empty())
+ if ((named_cmds || glob_buffer.is_empty())
&& !in_string && (com=find_command(line,0)))
{
if ((*com->func)(&glob_buffer,line) > 0)
@@ -1057,7 +1078,7 @@ static int read_lines(bool execute_commands)
if (glob_buffer.is_empty()) // If buffer was emptied
in_string=0;
#ifdef HAVE_READLINE
- if (status.add_to_history && not_in_history(line))
+ if (interactive && status.add_to_history && not_in_history(line))
add_history(line);
#endif
continue;
@@ -1067,7 +1088,7 @@ static int read_lines(bool execute_commands)
}
/* if in batch mode, send last query even if it doesn't end with \g or go */
- if ((status.batch || !execute_commands) && !status.exit_status)
+ if (!interactive && !status.exit_status)
{
remove_cntrl(glob_buffer);
if (!glob_buffer.is_empty())
@@ -1103,7 +1124,12 @@ static COMMANDS *find_command (char *name,char cmd_char)
{
while (my_isspace(charset_info,*name))
name++;
- if (strstr(name, delimiter) || strstr(name, "\\g"))
+ /*
+ As special case we allow row that starts with word delimiter
+ to be able to change delimiter if someone has delimiter 'delimiter'.
+ */
+ if (strstr(name, "\\g") || (strstr(name, delimiter) &&
+ strncmp(name, "delimiter", 9)))
return ((COMMANDS *) 0);
if ((end=strcont(name," \t")))
{
@@ -1138,6 +1164,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
uchar inchar;
char buff[80], *pos, *out;
COMMANDS *com;
+ bool need_space= 0;
if (!line[0] && buffer.is_empty())
return 0;
@@ -1246,6 +1273,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
{
pos++;
*ml_comment= 0;
+ need_space= 1;
}
else
{ // Add found char to buffer
@@ -1255,7 +1283,14 @@ static bool add_line(String &buffer,char *line,char *in_string,
(inchar == '\'' || inchar == '"' || inchar == '`'))
*in_string= (char) inchar;
if (!*ml_comment)
+ {
+ if (need_space && !my_isspace(charset_info, (char)inchar))
+ {
+ *out++= ' ';
+ need_space= 0;
+ }
*out++= (char) inchar;
+ }
}
}
if (out != line || !buffer.is_empty())
@@ -1673,11 +1708,12 @@ int mysql_real_query_for_lazy(const char *buf, int length)
{
for (uint retry=0;; retry++)
{
+ int error;
if (!mysql_real_query(&mysql,buf,length))
return 0;
- int error= put_error(&mysql);
+ error= put_error(&mysql);
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
- !opt_reconnect)
+ !opt_reconnect)
return error;
if (reconnect())
return error;
@@ -1933,7 +1969,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
time_buff[0]=0;
if (result)
{
- if (!mysql_num_rows(result) && ! quick)
+ if (!mysql_num_rows(result) && ! quick && !info_flag)
{
strmov(buff, "Empty set");
}
@@ -1988,6 +2024,13 @@ com_go(String *buffer,char *line __attribute__((unused)))
if (err >= 1)
error= put_error(&mysql);
+ if (show_warnings == 1 && warnings >= 1) /* Show warnings if any */
+ {
+ init_pager();
+ print_warnings();
+ end_pager();
+ }
+
if (!error && !status.batch &&
(mysql.server_status & SERVER_STATUS_DB_DROPPED))
get_current_db();
@@ -2047,6 +2090,7 @@ static void end_tee()
return;
}
+
static int
com_ego(String *buffer,char *line)
{
@@ -2058,18 +2102,95 @@ com_ego(String *buffer,char *line)
return result;
}
+
+static const char *fieldtype2str(enum enum_field_types type)
+{
+ switch (type) {
+ case FIELD_TYPE_BIT: return "BIT";
+ case FIELD_TYPE_BLOB: return "BLOB";
+ case FIELD_TYPE_DATE: return "DATE";
+ case FIELD_TYPE_DATETIME: return "DATETIME";
+ case FIELD_TYPE_NEWDECIMAL: return "NEWDECIMAL";
+ case FIELD_TYPE_DECIMAL: return "DECIMAL";
+ case FIELD_TYPE_DOUBLE: return "DOUBLE";
+ case FIELD_TYPE_ENUM: return "ENUM";
+ case FIELD_TYPE_FLOAT: return "FLOAT";
+ case FIELD_TYPE_GEOMETRY: return "GEOMETRY";
+ case FIELD_TYPE_INT24: return "INT24";
+ case FIELD_TYPE_LONG: return "LONG";
+ case FIELD_TYPE_LONGLONG: return "LONGLONG";
+ case FIELD_TYPE_LONG_BLOB: return "LONG_BLOB";
+ case FIELD_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB";
+ case FIELD_TYPE_NEWDATE: return "NEWDATE";
+ case FIELD_TYPE_NULL: return "NULL";
+ case FIELD_TYPE_SET: return "SET";
+ case FIELD_TYPE_SHORT: return "SHORT";
+ case FIELD_TYPE_STRING: return "STRING";
+ case FIELD_TYPE_TIME: return "TIME";
+ case FIELD_TYPE_TIMESTAMP: return "TIMESTAMP";
+ case FIELD_TYPE_TINY: return "TINY";
+ case FIELD_TYPE_TINY_BLOB: return "TINY_BLOB";
+ case FIELD_TYPE_VAR_STRING: return "VAR_STRING";
+ case FIELD_TYPE_YEAR: return "YEAR";
+ default: return "?-unknown-?";
+ }
+}
+
+static char *fieldflags2str(uint f) {
+ static char buf[1024];
+ char *s=buf;
+ *s=0;
+#define ff2s_check_flag(X) \
+ if (f & X ## _FLAG) { s=strmov(s, # X " "); f &= ~ X ## _FLAG; }
+ ff2s_check_flag(NOT_NULL);
+ ff2s_check_flag(PRI_KEY);
+ ff2s_check_flag(UNIQUE_KEY);
+ ff2s_check_flag(MULTIPLE_KEY);
+ ff2s_check_flag(BLOB);
+ ff2s_check_flag(UNSIGNED);
+ ff2s_check_flag(ZEROFILL);
+ ff2s_check_flag(BINARY);
+ ff2s_check_flag(ENUM);
+ ff2s_check_flag(AUTO_INCREMENT);
+ ff2s_check_flag(TIMESTAMP);
+ ff2s_check_flag(SET);
+ ff2s_check_flag(NO_DEFAULT_VALUE);
+ ff2s_check_flag(NUM);
+ ff2s_check_flag(PART_KEY);
+ ff2s_check_flag(GROUP);
+ ff2s_check_flag(UNIQUE);
+ ff2s_check_flag(BINCMP);
+#undef ff2s_check_flag
+ if (f)
+ sprintf(s, " unknows=0x%04x", f);
+ return buf;
+}
+
static void
print_field_types(MYSQL_RES *result)
{
- MYSQL_FIELD *field;
+ MYSQL_FIELD *field;
+ uint i=0;
+
while ((field = mysql_fetch_field(result)))
{
- tee_fprintf(PAGER,"Catalog: '%s'\nDatabase: '%s'\nTable: '%s'\nName: '%s'\nType: %d\nLength: %ld\nMax length: %ld\nIs_null: %d\nFlags: %u\nDecimals: %u\n\n",
- field->catalog, field->db, field->table, field->name,
- (int) field->type,
- field->length, field->max_length,
- !IS_NOT_NULL(field->flags),
- field->flags, field->decimals);
+ tee_fprintf(PAGER, "Field %3u: `%s`\n"
+ "Catalog: `%s`\n"
+ "Database: `%s`\n"
+ "Table: `%s`\n"
+ "Org_table: `%s`\n"
+ "Type: %s\n"
+ "Collation: %s (%u)\n"
+ "Length: %lu\n"
+ "Max_length: %lu\n"
+ "Decimals: %u\n"
+ "Flags: %s\n\n",
+ ++i,
+ field->name, field->catalog, field->db, field->table,
+ field->org_table, fieldtype2str(field->type),
+ get_charset_name(field->charsetnr), field->charsetnr,
+ field->length, field->max_length, field->decimals,
+ fieldflags2str(field->flags));
}
tee_puts("", PAGER);
}
@@ -2087,6 +2208,8 @@ print_table_data(MYSQL_RES *result)
if (info_flag)
{
print_field_types(result);
+ if (!mysql_num_rows(result))
+ return;
mysql_field_seek(result,0);
}
separator.copy("+",1,charset_info);
@@ -2204,13 +2327,11 @@ print_table_data_xml(MYSQL_RES *result)
(void) tee_fputs("\n <row>\n", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
{
- tee_fprintf(PAGER, "\t<%s>", (fields[i].name ?
- (fields[i].name[0] ? fields[i].name :
- " &nbsp; ") : "NULL"));
+ tee_fprintf(PAGER, "\t<field name=\"");
+ xmlencode_print(fields[i].name, (uint) strlen(fields[i].name));
+ tee_fprintf(PAGER, "\">");
xmlencode_print(cur[i], lengths[i]);
- tee_fprintf(PAGER, "</%s>\n", (fields[i].name ?
- (fields[i].name[0] ? fields[i].name :
- " &nbsp; ") : "NULL"));
+ tee_fprintf(PAGER, "</field>\n");
}
(void) tee_fputs(" </row>\n", PAGER);
}
@@ -2249,13 +2370,41 @@ print_table_data_vertically(MYSQL_RES *result)
}
-static const char
-*array_value(const char **array, char key)
+/* print_warnings should be called right after executing a statement */
+
+static void print_warnings()
{
- int x;
- for (x= 0; array[x]; x+= 2)
- if (*array[x] == key)
- return array[x + 1];
+ const char *query;
+ MYSQL_RES *result;
+ MYSQL_ROW cur;
+ my_ulonglong num_rows;
+
+ /* Get the warnings */
+ query= "show warnings";
+ mysql_real_query_for_lazy(query, strlen(query));
+ mysql_store_result_for_lazy(&result);
+
+ /* Bail out when no warnings */
+ if (!(num_rows= mysql_num_rows(result)))
+ {
+ mysql_free_result(result);
+ return;
+ }
+
+ /* Print the warnings */
+ while ((cur= mysql_fetch_row(result)))
+ {
+ tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]);
+ }
+ mysql_free_result(result);
+}
+
+
+static const char *array_value(const char **array, char key)
+{
+ for (; *array; array+= 2)
+ if (**array == key)
+ return array[1];
return 0;
}
@@ -2659,7 +2808,7 @@ static int com_source(String *buffer, char *line)
status.line_buff=line_buff;
status.file_name=source_name;
glob_buffer.length(0); // Empty command buffer
- error=read_lines(0); // Read lines from file
+ error= read_and_execute(false);
status=old_status; // Continue as before
my_fclose(sql_file,MYF(0));
batch_readline_end(line_buff);
@@ -2744,6 +2893,23 @@ com_use(String *buffer __attribute__((unused)), char *line)
return 0;
}
+static int
+com_warnings(String *buffer __attribute__((unused)),
+ char *line __attribute__((unused)))
+{
+ show_warnings = 1;
+ put_info("Show warnings enabled.",INFO_INFO);
+ return 0;
+}
+
+static int
+com_nowarnings(String *buffer __attribute__((unused)),
+ char *line __attribute__((unused)))
+{
+ show_warnings = 0;
+ put_info("Show warnings disabled.",INFO_INFO);
+ return 0;
+}
/*
Gets argument from a command on the command line. If get_next_arg is
@@ -2867,6 +3033,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
connected=1;
#ifndef EMBEDDED_LIBRARY
mysql.reconnect=info_flag ? 1 : 0; // We want to know if this happens
+#else
+ mysql.reconnect= 1;
#endif
#ifdef HAVE_READLINE
build_completion_hash(rehash, 1);
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index da790bce375..ec136402bd8 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -431,6 +431,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port,
unix_port, 0))
{
+ mysql->reconnect= 1;
if (info)
{
fputs("\n",stderr);
@@ -726,7 +727,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
void (*func) (MYSQL_RES*, MYSQL_ROW, uint);
new_line = 1;
- if (mysql_query(mysql, "show status") ||
+ if (mysql_query(mysql, "show /*!50002 GLOBAL */ status") ||
!(res = mysql_store_result(mysql)))
{
my_printf_error(0, "unable to show status; error: '%s'", MYF(ME_BELL),
@@ -1345,6 +1346,3 @@ static my_bool wait_pidfile(char *pidfile, time_t last_modified,
}
DBUG_RETURN(error);
}
-#ifdef __GNUC__
-FIX_GCC_LINKING_PROBLEM
-#endif
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 802d5081ad6..fb9ed3af70c 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -14,10 +14,27 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/*
+
+ TODO: print the catalog (some USE catalog.db ????).
+
+ Standalone program to read a MySQL binary log (or relay log);
+ can read files produced by 3.23, 4.x, 5.0 servers.
+
+ Can read binlogs from 3.23/4.x/5.0 and relay logs from 4.x/5.0.
+ Should be able to read any file of these categories, even with
+ --start-position.
+ An important fact: the Format_desc event of the log is at most the 3rd event
+ of the log; if it is the 3rd then there is this combination:
+ Format_desc_of_slave, Rotate_of_master, Format_desc_of_master.
+*/
+
#define MYSQL_CLIENT
#undef MYSQL_SERVER
#include "client_priv.h"
#include <my_time.h>
+/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
+#include "mysql_priv.h"
#include "log_event.h"
#define BIN_LOG_HEADER_SIZE 4
@@ -66,6 +83,14 @@ static MYSQL* mysql = NULL;
static const char* dirname_for_local_load= 0;
static bool stop_passed= 0;
+/*
+ check_header() will set the pointer below.
+ Why do we need here a pointer on an event instead of an event ?
+ This is because the event will be created (alloced) in read_log_event()
+ (which returns a pointer) in check_header().
+*/
+Format_description_log_event* description_event;
+
static int dump_local_log_entries(const char* logname);
static int dump_remote_log_entries(const char* logname);
static int dump_log_entries(const char* logname);
@@ -78,6 +103,22 @@ class Load_log_processor
{
char target_dir_name[FN_REFLEN];
int target_dir_name_len;
+
+ /*
+ When we see first event corresponding to some LOAD DATA statement in
+ binlog, we create temporary file to store data to be loaded.
+ We add name of this file to file_names array using its file_id as index.
+ If we have Create_file event (i.e. we have binary log in pre-5.0.3
+ format) we also store save event object to be able which is needed to
+ emit LOAD DATA statement when we will meet Exec_load_data event.
+ If we have Begin_load_query event we simply store 0 in
+ File_name_record::event field.
+ */
+ struct File_name_record
+ {
+ char *fname;
+ Create_file_log_event *event;
+ };
DYNAMIC_ARRAY file_names;
/*
@@ -119,7 +160,7 @@ public:
int init()
{
- return init_dynamic_array(&file_names,sizeof(Create_file_log_event*),
+ return init_dynamic_array(&file_names, sizeof(File_name_record),
100,100 CALLER_INFO);
}
@@ -136,33 +177,91 @@ public:
}
void destroy()
{
- Create_file_log_event **ptr= (Create_file_log_event**)file_names.buffer;
- Create_file_log_event **end= ptr + file_names.elements;
+ File_name_record *ptr= (File_name_record *)file_names.buffer;
+ File_name_record *end= ptr + file_names.elements;
for (; ptr<end; ptr++)
{
- if (*ptr)
+ if (ptr->fname)
{
- my_free((char*)(*ptr)->fname,MYF(MY_WME));
- delete *ptr;
- *ptr= 0;
+ my_free(ptr->fname, MYF(MY_WME));
+ delete ptr->event;
+ bzero((char *)ptr, sizeof(File_name_record));
}
}
}
+
+ /*
+ Obtain Create_file event for LOAD DATA statement by its file_id.
+
+ SYNOPSIS
+ grab_event()
+ file_id - file_id identifiying LOAD DATA statement
+
+ DESCRIPTION
+ Checks whenever we have already seen Create_file event for this file_id.
+ If yes then returns pointer to it and removes it from array describing
+ active temporary files. Since this moment caller is responsible for
+ freeing memory occupied by this event and associated file name.
+
+ RETURN VALUES
+ Pointer to Create_file event or 0 if there was no such event
+ with this file_id.
+ */
Create_file_log_event *grab_event(uint file_id)
{
+ File_name_record *ptr;
+ Create_file_log_event *res;
+
if (file_id >= file_names.elements)
return 0;
- Create_file_log_event **ptr=
- (Create_file_log_event**)file_names.buffer + file_id;
- Create_file_log_event *res= *ptr;
- *ptr= 0;
+ ptr= dynamic_element(&file_names, file_id, File_name_record*);
+ if ((res= ptr->event))
+ bzero((char *)ptr, sizeof(File_name_record));
+ return res;
+ }
+
+ /*
+ Obtain file name of temporary file for LOAD DATA statement by its file_id.
+
+ SYNOPSIS
+ grab_fname()
+ file_id - file_id identifiying LOAD DATA statement
+
+ DESCRIPTION
+ Checks whenever we have already seen Begin_load_query event for this
+ file_id. If yes then returns file name of corresponding temporary file.
+ Removes record about this file from the array of active temporary files.
+ Since this moment caller is responsible for freeing memory occupied by
+ this name.
+
+ RETURN VALUES
+ String with name of temporary file or 0 if we have not seen Begin_load_query
+ event with this file_id.
+ */
+ char *grab_fname(uint file_id)
+ {
+ File_name_record *ptr;
+ char *res= 0;
+
+ if (file_id >= file_names.elements)
+ return 0;
+ ptr= dynamic_element(&file_names, file_id, File_name_record*);
+ if (!ptr->event)
+ {
+ res= ptr->fname;
+ bzero((char *)ptr, sizeof(File_name_record));
+ }
return res;
}
int process(Create_file_log_event *ce);
+ int process(Begin_load_query_log_event *ce);
int process(Append_block_log_event *ae);
File prepare_new_file_for_old_format(Load_log_event *le, char *filename);
int load_old_format_file(NET* net, const char *server_fname,
uint server_fname_len, File file);
+ int process_first_event(const char *bname, uint blen, const char *block,
+ uint block_len, uint file_id,
+ Create_file_log_event *ce);
};
@@ -240,22 +339,42 @@ int Load_log_processor::load_old_format_file(NET* net, const char*server_fname,
}
-int Load_log_processor::process(Create_file_log_event *ce)
+/*
+ Process first event in the sequence of events representing LOAD DATA
+ statement.
+
+ SYNOPSIS
+ process_first_event()
+ bname - base name for temporary file to be created
+ blen - base name length
+ block - first block of data to be loaded
+ block_len - first block length
+ file_id - identifies LOAD DATA statement
+ ce - pointer to Create_file event object if we are processing
+ this type of event.
+
+ DESCRIPTION
+ Creates temporary file to be used in LOAD DATA and writes first block of
+ data to it. Registers its file name (and optional Create_file event)
+ in the array of active temporary files.
+
+ RETURN VALUES
+ 0 - success
+ non-0 - error
+*/
+
+int Load_log_processor::process_first_event(const char *bname, uint blen,
+ const char *block, uint block_len,
+ uint file_id,
+ Create_file_log_event *ce)
{
- const char *bname= ce->fname+dirname_length(ce->fname);
- uint blen= ce->fname_len - (bname-ce->fname);
uint full_len= target_dir_name_len + blen + 9 + 9 + 1;
int error= 0;
char *fname, *ptr;
File file;
- DBUG_ENTER("Load_log_processor::process");
+ File_name_record rec;
+ DBUG_ENTER("Load_log_processor::process_first_event");
- if (set_dynamic(&file_names,(gptr)&ce,ce->file_id))
- {
- sql_print_error("Could not construct local filename %s%s",
- target_dir_name,bname);
- DBUG_RETURN(-1);
- }
if (!(fname= my_malloc(full_len,MYF(MY_WME))))
DBUG_RETURN(-1);
@@ -263,7 +382,7 @@ int Load_log_processor::process(Create_file_log_event *ce)
ptr= fname + target_dir_name_len;
memcpy(ptr,bname,blen);
ptr+= blen;
- ptr+= my_sprintf(ptr,(ptr,"-%x",ce->file_id));
+ ptr+= my_sprintf(ptr, (ptr, "-%x", file_id));
if ((file= create_unique_file(fname,ptr)) < 0)
{
@@ -271,9 +390,21 @@ int Load_log_processor::process(Create_file_log_event *ce)
target_dir_name,bname);
DBUG_RETURN(-1);
}
- ce->set_fname_outside_temp_buf(fname,strlen(fname));
- if (my_write(file,(byte*) ce->block,ce->block_len,MYF(MY_WME|MY_NABP)))
+ rec.fname= fname;
+ rec.event= ce;
+
+ if (set_dynamic(&file_names, (gptr)&rec, file_id))
+ {
+ sql_print_error("Could not construct local filename %s%s",
+ target_dir_name, bname);
+ DBUG_RETURN(-1);
+ }
+
+ if (ce)
+ ce->set_fname_outside_temp_buf(fname, strlen(fname));
+
+ if (my_write(file, (byte*)block, block_len, MYF(MY_WME|MY_NABP)))
error= -1;
if (my_close(file, MYF(MY_WME)))
error= -1;
@@ -281,19 +412,35 @@ int Load_log_processor::process(Create_file_log_event *ce)
}
+int Load_log_processor::process(Create_file_log_event *ce)
+{
+ const char *bname= ce->fname + dirname_length(ce->fname);
+ uint blen= ce->fname_len - (bname-ce->fname);
+
+ return process_first_event(bname, blen, ce->block, ce->block_len,
+ ce->file_id, ce);
+}
+
+
+int Load_log_processor::process(Begin_load_query_log_event *blqe)
+{
+ return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len,
+ blqe->file_id, 0);
+}
+
+
int Load_log_processor::process(Append_block_log_event *ae)
{
DBUG_ENTER("Load_log_processor::process");
- Create_file_log_event* ce= ((ae->file_id < file_names.elements) ?
- *((Create_file_log_event**)file_names.buffer +
- ae->file_id) :
- 0);
+ const char* fname= ((ae->file_id < file_names.elements) ?
+ dynamic_element(&file_names, ae->file_id,
+ File_name_record*)->fname : 0);
- if (ce)
+ if (fname)
{
File file;
int error= 0;
- if (((file= my_open(ce->fname,
+ if (((file= my_open(fname,
O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0))
DBUG_RETURN(-1);
if (my_write(file,(byte*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP)))
@@ -305,8 +452,8 @@ int Load_log_processor::process(Append_block_log_event *ae)
/*
There is no Create_file event (a bad binlog or a big
- --position). Assuming it's a big --position, we just do nothing and
- print a warning.
+ --start-position). Assuming it's a big --start-position, we just do
+ nothing and print a warning.
*/
fprintf(stderr,"Warning: ignoring Append_block as there is no \
Create_file event for file_id: %u\n",ae->file_id);
@@ -316,30 +463,57 @@ Create_file event for file_id: %u\n",ae->file_id);
Load_log_processor load_processor;
+
+static bool check_database(const char *log_dbname)
+{
+ return one_database &&
+ (log_dbname != NULL) &&
+ strcmp(log_dbname, database);
+}
+
+
/*
+ Process an event
+
+ SYNOPSIS
+ process_event()
+
RETURN
0 ok and continue
1 error and terminate
-1 ok and terminate
-
+
TODO
This function returns 0 even in some error cases. This should be changed.
*/
-int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
+
+
+
+int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev,
+ my_off_t pos)
{
char ll_buff[21];
+ Log_event_type ev_type= ev->get_type_code();
DBUG_ENTER("process_event");
+ /*
+ Format events are not concerned by --offset and such, we always need to
+ read them to be able to process the wanted events.
+ */
if ((rec_count >= offset) &&
- ((my_time_t)(ev->when) >= start_datetime))
+ ((my_time_t)(ev->when) >= start_datetime) ||
+ (ev_type == FORMAT_DESCRIPTION_EVENT))
{
- /*
- We have found an event after start_datetime, from now on print
- everything (in case the binlog has timestamps increasing and decreasing,
- we do this to avoid cutting the middle).
- */
- start_datetime= 0;
- offset= 0; // print everything and protect against cycling rec_count
+ if (ev_type != FORMAT_DESCRIPTION_EVENT)
+ {
+ /*
+ We have found an event after start_datetime, from now on print
+ everything (in case the binlog has timestamps increasing and
+ decreasing, we do this to avoid cutting the middle).
+ */
+ start_datetime= 0;
+ offset= 0; // print everything and protect against cycling rec_count
+ }
if (((my_time_t)(ev->when) >= stop_datetime)
|| (pos >= stop_position_mot))
{
@@ -349,31 +523,23 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
if (!short_form)
fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
- switch (ev->get_type_code()) {
+ switch (ev_type) {
case QUERY_EVENT:
- if (one_database)
- {
- const char * log_dbname = ((Query_log_event*)ev)->db;
- if ((log_dbname != NULL) && (strcmp(log_dbname, database)))
- goto end;
- }
- ev->print(result_file, short_form, last_db);
+ if (check_database(((Query_log_event*)ev)->db))
+ goto end;
+ ev->print(result_file, short_form, last_event_info);
break;
case CREATE_FILE_EVENT:
{
Create_file_log_event* ce= (Create_file_log_event*)ev;
- if (one_database)
- {
- /*
- We test if this event has to be ignored. If yes, we don't save
- this event; this will have the good side-effect of ignoring all
- related Append_block and Exec_load.
- Note that Load event from 3.23 is not tested.
- */
- const char * log_dbname = ce->db;
- if ((log_dbname != NULL) && (strcmp(log_dbname, database)))
- goto end; // Next event
- }
+ /*
+ We test if this event has to be ignored. If yes, we don't save
+ this event; this will have the good side-effect of ignoring all
+ related Append_block and Exec_load.
+ Note that Load event from 3.23 is not tested.
+ */
+ if (check_database(ce->db))
+ goto end; // Next event
/*
We print the event, but with a leading '#': this is just to inform
the user of the original command; the command we want to execute
@@ -381,8 +547,9 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT'
below.
*/
- ce->print(result_file, short_form, last_db, TRUE);
- if (!old_format)
+ ce->print(result_file, short_form, last_event_info, TRUE);
+ // If this binlog is not 3.23 ; why this test??
+ if (description_event->binlog_version >= 3)
{
if (load_processor.process(ce))
break; // Error
@@ -391,23 +558,23 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
break;
}
case APPEND_BLOCK_EVENT:
- ev->print(result_file, short_form, last_db);
+ ev->print(result_file, short_form, last_event_info);
if (load_processor.process((Append_block_log_event*) ev))
break; // Error
break;
case EXEC_LOAD_EVENT:
{
- ev->print(result_file, short_form, last_db);
+ ev->print(result_file, short_form, last_event_info);
Execute_load_log_event *exv= (Execute_load_log_event*)ev;
Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
/*
if ce is 0, it probably means that we have not seen the Create_file
- event (a bad binlog, or most probably --position is after the
+ event (a bad binlog, or most probably --start-position is after the
Create_file event). Print a warning comment.
*/
if (ce)
{
- ce->print(result_file, short_form, last_db, TRUE);
+ ce->print(result_file, short_form, last_event_info, TRUE);
my_free((char*)ce->fname,MYF(MY_WME));
delete ce;
}
@@ -416,8 +583,46 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
Create_file event for file_id: %u\n",exv->file_id);
break;
}
+ case FORMAT_DESCRIPTION_EVENT:
+ delete description_event;
+ description_event= (Format_description_log_event*) ev;
+ ev->print(result_file, short_form, last_event_info);
+ /*
+ We don't want this event to be deleted now, so let's hide it (I
+ (Guilhem) should later see if this triggers a non-serious Valgrind
+ error). Not serious error, because we will free description_event
+ later.
+ */
+ ev= 0;
+ break;
+ case BEGIN_LOAD_QUERY_EVENT:
+ ev->print(result_file, short_form, last_event_info);
+ load_processor.process((Begin_load_query_log_event*) ev);
+ break;
+ case EXECUTE_LOAD_QUERY_EVENT:
+ {
+ Execute_load_query_log_event *exlq= (Execute_load_query_log_event*)ev;
+ char *fname= load_processor.grab_fname(exlq->file_id);
+
+ if (check_database(exlq->db))
+ {
+ if (fname)
+ my_free(fname, MYF(MY_WME));
+ goto end;
+ }
+
+ if (fname)
+ {
+ exlq->print(result_file, short_form, last_event_info, fname);
+ my_free(fname, MYF(MY_WME));
+ }
+ else
+ fprintf(stderr,"Warning: ignoring Execute_load_query as there is no \
+Begin_load_query event for file_id: %u\n", exlq->file_id);
+ break;
+ }
default:
- ev->print(result_file, short_form, last_db);
+ ev->print(result_file, short_form, last_event_info);
}
}
@@ -436,6 +641,15 @@ static struct my_option my_long_options[] =
{"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ /*
+ mysqlbinlog needs charsets knowledge, to be able to convert a charset
+ number found in binlog to a charset name (to be able to print things
+ like this:
+ SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`;
+ */
+ {"character-sets-dir", OPT_CHARSETS_DIR,
+ "Directory where character sets are.", (gptr*) &charsets_dir,
+ (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifndef DBUG_OFF
{"debug", '#', "Output debug log.", (gptr*) &default_dbug_option,
(gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
@@ -570,7 +784,7 @@ static void die(const char* fmt, ...)
static void print_version()
{
- printf("%s Ver 3.0 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
+ printf("%s Ver 3.1 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
NETWARE_SET_SCREEN_MODE(1);
}
@@ -596,7 +810,7 @@ static my_time_t convert_str_to_timestamp(const char* str)
int was_cut;
MYSQL_TIME l_time;
long dummy_my_timezone;
- bool dummy_in_dst_time_gap;
+ my_bool dummy_in_dst_time_gap;
/* We require a total specification (date AND time) */
if (str_to_datetime(str, strlen(str), &l_time, 0, &was_cut) !=
MYSQL_TIMESTAMP_DATETIME || was_cut)
@@ -711,6 +925,7 @@ static MYSQL* safe_connect()
mysql_close(local_mysql);
die("failed on connect: %s", errmsg);
}
+ local_mysql->reconnect= 1;
return local_mysql;
}
@@ -722,12 +937,17 @@ static int dump_log_entries(const char* logname)
}
-static int check_master_version(MYSQL* mysql)
+/*
+ This is not as smart as check_header() (used for local log); it will not work
+ for a binlog which mixes format. TODO: fix this.
+*/
+static int check_master_version(MYSQL* mysql,
+ Format_description_log_event
+ **description_event)
{
MYSQL_RES* res = 0;
MYSQL_ROW row;
const char* version;
- int old_format = 0;
if (mysql_query(mysql, "SELECT VERSION()") ||
!(res = mysql_store_result(mysql)))
@@ -753,11 +973,18 @@ static int check_master_version(MYSQL* mysql)
switch (*version) {
case '3':
- old_format = 1;
+ *description_event= new Format_description_log_event(1);
break;
case '4':
+ *description_event= new Format_description_log_event(3);
case '5':
- old_format = 0;
+ /*
+ The server is soon going to send us its Format_description log
+ event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
+ So we first assume that this is 4.0 (which is enough to read the
+ Format_desc event if one comes).
+ */
+ *description_event= new Format_description_log_event(3);
break;
default:
sql_print_error("Master reported unrecognized MySQL version '%s'",
@@ -767,18 +994,17 @@ static int check_master_version(MYSQL* mysql)
return 1;
}
mysql_free_result(res);
- return old_format;
+ return 0;
}
static int dump_remote_log_entries(const char* logname)
+
{
char buf[128];
- char last_db[FN_REFLEN+1] = "";
- ulong len;
- uint logname_len;
+ LAST_EVENT_INFO last_event_info;
+ uint len, logname_len;
NET* net;
- int old_format;
int error= 0;
my_off_t old_off= start_position_mot;
char fname[FN_REFLEN+1];
@@ -791,7 +1017,18 @@ static int dump_remote_log_entries(const char* logname)
*/
mysql= safe_connect();
net= &mysql->net;
- old_format = check_master_version(mysql);
+
+ if (check_master_version(mysql, &description_event))
+ {
+ fprintf(stderr, "Could not find server version");
+ DBUG_RETURN(1);
+ }
+ if (!description_event || !description_event->is_valid())
+ {
+ fprintf(stderr, "Invalid Format_description log event; \
+could be out of memory");
+ DBUG_RETURN(1);
+ }
/*
COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
@@ -820,6 +1057,8 @@ static int dump_remote_log_entries(const char* logname)
for (;;)
{
const char *error_msg;
+ Log_event *ev;
+
len = net_safe_read(mysql);
if (len == packet_error)
{
@@ -832,9 +1071,9 @@ static int dump_remote_log_entries(const char* logname)
break; // end of data
DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n",
len, net->read_pos[5]));
- Log_event *ev = Log_event::read_log_event((const char*) net->read_pos + 1 ,
- len - 1, &error_msg, old_format);
- if (!ev)
+ if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
+ len - 1, &error_msg,
+ description_event)))
{
fprintf(stderr, "Could not construct log event object\n");
error= 1;
@@ -842,25 +1081,27 @@ static int dump_remote_log_entries(const char* logname)
}
Log_event_type type= ev->get_type_code();
- if (!old_format || ( type != LOAD_EVENT && type != CREATE_FILE_EVENT))
+ if (description_event->binlog_version >= 3 ||
+ (type != LOAD_EVENT && type != CREATE_FILE_EVENT))
{
- if (ev->get_type_code() == ROTATE_EVENT)
+ /*
+ If this is a Rotate event, maybe it's the end of the requested binlog;
+ in this case we are done (stop transfer).
+ This is suitable for binlogs, not relay logs (but for now we don't read
+ relay logs remotely because the server is not able to do that). If one
+ day we read relay logs remotely, then we will have a problem with the
+ detection below: relay logs contain Rotate events which are about the
+ binlogs, so which would trigger the end-detection below.
+ */
+ if (type == ROTATE_EVENT)
{
Rotate_log_event *rev= (Rotate_log_event *)ev;
/*
- mysqld is sending us all its binlogs after the requested one, but we
- don't want them.
If this is a fake Rotate event, and not about our log, we can stop
transfer. If this a real Rotate event (so it's not about our log,
it's in our log describing the next log), we print it (because it's
part of our log) and then we will stop when we receive the fake one
soon.
- This is suitable for binlogs, not relay logs (but for now we don't
- read relay logs remotely because the server is not able to do
- that). If one day we read relay logs remotely, then we will have a
- problem with the detection below: relay logs contain Rotate events
- which are about the binlogs, so which would trigger the end-detection
- below.
*/
if (rev->when == 0)
{
@@ -883,7 +1124,7 @@ static int dump_remote_log_entries(const char* logname)
len= 1; // fake Rotate, so don't increment old_off
}
}
- if ((error= process_event(last_db,ev,old_off,old_format)))
+ if ((error= process_event(&last_event_info,ev,old_off)))
{
error= ((error < 0) ? 0 : 1);
goto err;
@@ -895,64 +1136,135 @@ static int dump_remote_log_entries(const char* logname)
const char *old_fname= le->fname;
uint old_len= le->fname_len;
File file;
-
+
if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
{
error= 1;
goto err;
}
-
- if ((error= process_event(last_db,ev,old_off,old_format)))
+
+ if ((error= process_event(&last_event_info,ev,old_off)))
{
- my_close(file,MYF(MY_WME));
+ my_close(file,MYF(MY_WME));
error= ((error < 0) ? 0 : 1);
goto err;
}
- if (load_processor.load_old_format_file(net,old_fname,old_len,file))
+ error= load_processor.load_old_format_file(net,old_fname,old_len,file);
+ my_close(file,MYF(MY_WME));
+ if (error)
{
- my_close(file,MYF(MY_WME));
error= 1;
goto err;
}
- my_close(file,MYF(MY_WME));
}
-
/*
Let's adjust offset for remote log as for local log to produce
similar text.
*/
old_off+= len-1;
}
+
err:
mysql_close(mysql);
DBUG_RETURN(error);
}
-static int check_header(IO_CACHE* file)
+static void check_header(IO_CACHE* file,
+ Format_description_log_event **description_event)
{
byte header[BIN_LOG_HEADER_SIZE];
byte buf[PROBE_HEADER_LEN];
- int old_format=0;
- DBUG_ENTER("check_header");
+ my_off_t tmp_pos, pos;
- my_off_t pos = my_b_tell(file);
+ *description_event= new Format_description_log_event(3);
+ pos= my_b_tell(file);
my_b_seek(file, (my_off_t)0);
if (my_b_read(file, header, sizeof(header)))
die("Failed reading header; Probably an empty file");
if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
die("File is not a binary log file");
- if (!my_b_read(file, buf, sizeof(buf)))
+
+ /*
+ Imagine we are running with --start-position=1000. We still need
+ to know the binlog format's. So we still need to find, if there is
+ one, the Format_desc event, or to know if this is a 3.23
+ binlog. So we need to first read the first events of the log,
+ those around offset 4. Even if we are reading a 3.23 binlog from
+ the start (no --start-position): we need to know the header length
+ (which is 13 in 3.23, 19 in 4.x) to be able to successfully print
+ the first event (Start_log_event_v3). So even in this case, we
+ need to "probe" the first bytes of the log *before* we do a real
+ read_log_event(). Because read_log_event() needs to know the
+ header's length to work fine.
+ */
+ for(;;)
{
- if (buf[4] == START_EVENT)
+ tmp_pos= my_b_tell(file); /* should be 4 the first time */
+ if (my_b_read(file, buf, sizeof(buf)))
{
- uint event_len;
- event_len = uint4korr(buf + EVENT_LEN_OFFSET);
- old_format = (event_len < (LOG_EVENT_HEADER_LEN + START_HEADER_LEN));
+ if (file->error)
+ die("\
+Could not read entry at offset %lu : Error in log format or read error",
+ tmp_pos);
+ /*
+ Otherwise this is just EOF : this log currently contains 0-2
+ events. Maybe it's going to be filled in the next
+ milliseconds; then we are going to have a problem if this a
+ 3.23 log (imagine we are locally reading a 3.23 binlog which
+ is being written presently): we won't know it in
+ read_log_event() and will fail(). Similar problems could
+ happen with hot relay logs if --start-position is used (but a
+ --start-position which is posterior to the current size of the log).
+ These are rare problems anyway (reading a hot log + when we
+ read the first events there are not all there yet + when we
+ read a bit later there are more events + using a strange
+ --start-position).
+ */
+ break;
+ }
+ else
+ {
+ DBUG_PRINT("info",("buf[4]=%d", buf[4]));
+ /* always test for a Start_v3, even if no --start-position */
+ if (buf[4] == START_EVENT_V3) /* This is 3.23 or 4.x */
+ {
+ if (uint4korr(buf + EVENT_LEN_OFFSET) <
+ (LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN))
+ {
+ /* This is 3.23 (format 1) */
+ delete *description_event;
+ *description_event= new Format_description_log_event(1);
+ }
+ break;
+ }
+ else if (tmp_pos >= start_position)
+ break;
+ else if (buf[4] == FORMAT_DESCRIPTION_EVENT) /* This is 5.0 */
+ {
+ my_b_seek(file, tmp_pos); /* seek back to event's start */
+ if (!(*description_event= (Format_description_log_event*)
+ Log_event::read_log_event(file, *description_event)))
+ /* EOF can't be hit here normally, so it's a real error */
+ die("Could not read a Format_description_log_event event \
+at offset %lu ; this could be a log format error or read error",
+ tmp_pos);
+ DBUG_PRINT("info",("Setting description_event"));
+ }
+ else if (buf[4] == ROTATE_EVENT)
+ {
+ my_b_seek(file, tmp_pos); /* seek back to event's start */
+ if (!Log_event::read_log_event(file, *description_event))
+ /* EOF can't be hit here normally, so it's a real error */
+ die("Could not read a Rotate_log_event event \
+at offset %lu ; this could be a log format error or read error",
+ tmp_pos);
+ }
+ else
+ break;
}
}
my_b_seek(file, pos);
- DBUG_RETURN(old_format);
}
@@ -960,13 +1272,10 @@ static int dump_local_log_entries(const char* logname)
{
File fd = -1;
IO_CACHE cache,*file= &cache;
- char last_db[FN_REFLEN+1];
+ LAST_EVENT_INFO last_event_info;
byte tmp_buff[BIN_LOG_HEADER_SIZE];
- bool old_format = 0;
int error= 0;
- last_db[0]= 0;
-
if (logname && logname[0] != '-')
{
if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
@@ -975,65 +1284,67 @@ static int dump_local_log_entries(const char* logname)
MYF(MY_WME | MY_NABP)))
{
my_close(fd, MYF(MY_WME));
- exit(1);
+ return 1;
}
- old_format = check_header(file);
+ check_header(file, &description_event);
}
- else
+ else // reading from stdin;
{
- if (init_io_cache(file, fileno(result_file), 0, READ_CACHE, (my_off_t) 0,
+ if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
return 1;
- old_format = check_header(file);
+ check_header(file, &description_event);
if (start_position)
{
- /* skip 'start_position' characters from stdout */
+ /* skip 'start_position' characters from stdin */
byte buff[IO_SIZE];
my_off_t length,tmp;
for (length= start_position_mot ; length > 0 ; length-=tmp)
{
tmp=min(length,sizeof(buff));
if (my_b_read(file, buff, (uint) tmp))
- {
- error= 1;
- goto end;
- }
+ {
+ error= 1;
+ goto end;
+ }
}
}
- file->pos_in_file= start_position_mot;
- file->seek_not_done=0;
}
- if (!start_position)
+ if (!description_event || !description_event->is_valid())
+ die("Invalid Format_description log event; could be out of memory");
+
+ if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
{
- // Skip header
- if (my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
- {
- error= 1;
- goto end;
- }
+ error= 1;
+ goto end;
}
-
for (;;)
{
char llbuff[21];
my_off_t old_off = my_b_tell(file);
- Log_event* ev = Log_event::read_log_event(file, old_format);
+ Log_event* ev = Log_event::read_log_event(file, description_event);
if (!ev)
{
- if (file->error)
+ /*
+ if binlog wasn't closed properly ("in use" flag is set) don't complain
+ about a corruption, but treat it as EOF and move to the next binlog.
+ */
+ if (description_event->flags & LOG_EVENT_BINLOG_IN_USE_F)
+ file->error= 0;
+ else if (file->error)
{
- fprintf(stderr,
- "Could not read entry at offset %s:"
- "Error in log format or read error\n",
- llstr(old_off,llbuff));
- error= 1;
+ fprintf(stderr,
+ "Could not read entry at offset %s:"
+ "Error in log format or read error\n",
+ llstr(old_off,llbuff));
+ error= 1;
}
// file->error == 0 means EOF, that's OK, we break in this case
break;
}
- if ((error= process_event(last_db,ev,old_off,false)))
+ if ((error= process_event(&last_event_info,ev,old_off)))
{
if (error < 0)
error= 0;
@@ -1045,6 +1356,7 @@ end:
if (fd >= 0)
my_close(fd, MYF(MY_WME));
end_io_cache(file);
+ delete description_event;
return error;
}
@@ -1095,6 +1407,14 @@ int main(int argc, char** argv)
fprintf(result_file,
"/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
+ /*
+ In mysqlbinlog|mysql, don't want mysql to be disconnected after each
+ transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
+ */
+ fprintf(result_file,
+ "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
+ "COMPLETION_TYPE=0*/;\n");
+
for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
(--argc >= 0) && !stop_passed ; )
{
@@ -1109,6 +1429,13 @@ int main(int argc, char** argv)
start_position= BIN_LOG_HEADER_SIZE;
}
+ /*
+ Issue a ROLLBACK in case the last printed binlog was crashed and had half
+ of transaction.
+ */
+ fprintf(result_file,
+ "ROLLBACK;\n"
+ "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
if (disable_log_bin)
fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
@@ -1130,9 +1457,14 @@ int main(int argc, char** argv)
*/
#ifdef __WIN__
+#include "my_decimal.h"
+#include "decimal.c"
+#include "my_decimal.cpp"
#include "log_event.cpp"
#else
+#include "my_decimal.h"
+#include "decimal.c"
+#include "my_decimal.cc"
#include "log_event.cc"
#endif
-FIX_GCC_LINKING_PROBLEM
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 2a2ae1311c9..35d57e0394e 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -643,6 +643,7 @@ static int dbConnect(char *host, char *user, char *passwd)
DBerror(&mysql_connection, "when trying to connect");
return 1;
}
+ mysql_connection.reconnect= 1;
return 0;
} /* dbConnect */
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 3458f74d8a2..322acbd26c0 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -37,7 +37,7 @@
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
*/
-#define DUMP_VERSION "10.9"
+#define DUMP_VERSION "10.10"
#include <my_global.h>
#include <my_sys.h>
@@ -86,7 +86,8 @@ static my_bool verbose=0,tFlag=0,dFlag=0,quick= 1, extended_insert= 1,
opt_delete_master_logs=0, tty_password=0,
opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
- opt_complete_insert= 0, opt_drop_database= 0;
+ opt_complete_insert= 0, opt_drop_database= 0,
+ opt_dump_triggers= 0, opt_routines=0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*sock=0;
static my_bool insert_pat_inited=0;
@@ -121,6 +122,8 @@ static const char *mysql_universal_client_charset=
static char *default_charset;
static CHARSET_INFO *charset_info= &my_charset_latin1;
const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace";
+/* do we met VIEWs during tables scaning */
+my_bool was_views= 0;
const char *compatible_mode_names[]=
{
@@ -206,7 +209,9 @@ static struct my_option my_long_options[] =
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", (gptr*) &default_charset,
(gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED.",
+ {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED; "
+ "currently ignored because of http://bugs.mysql.com/bug.php?id=7815 "
+ "but will be re-enabled later",
(gptr*) &opt_delayed, (gptr*) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"delete-master-logs", OPT_DELETE_MASTER_LOGS,
@@ -334,6 +339,9 @@ static struct my_option my_long_options[] =
{"result-file", 'r',
"Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"routines", 'R', "Dump routines FUNCTIONS and PROCEDURES.",
+ (gptr*) &opt_routines, (gptr*) &opt_routines, 0, GET_BOOL,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
{"set-charset", OPT_SET_CHARSET,
"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,
@@ -371,6 +379,9 @@ static struct my_option my_long_options[] =
(gptr*) &path, (gptr*) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"tables", OPT_TABLES, "Overrides option --databases (-B).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"triggers", OPT_TRIGGERS, "Dump triggers for each dumped table",
+ (gptr*) &opt_dump_triggers, (gptr*) &opt_dump_triggers, 0, GET_BOOL,
+ NO_ARG, 1, 0, 0, 0, 0, 0},
#ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user.",
(gptr*) &current_user, (gptr*) &current_user, 0, GET_STR, REQUIRED_ARG,
@@ -384,7 +395,7 @@ static struct my_option my_long_options[] =
(gptr*) &where, (gptr*) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
- { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+ {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
static const char *load_default_groups[]= { "mysqldump","client",0 };
@@ -402,6 +413,8 @@ static int dump_all_databases();
static char *quote_name(const char *name, char *buff, my_bool force);
static const char *check_if_ignore_table(const char *table_name);
static char *primary_key_fields(const char *table_name);
+static my_bool get_view_structure(char *table, char* db);
+static my_bool dump_all_views_in_db(char *database);
#include <help_start.h>
@@ -418,6 +431,7 @@ void check_io(FILE *file)
if (ferror(file))
{
fprintf(stderr, "%s: Got errno %d on write\n", my_progname, errno);
+ ignore_errors= 0; /* We can't ignore this error */
safe_exit(EX_EOF);
}
}
@@ -706,6 +720,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
break;
}
+#ifndef REMOVE_THIS_CODE_WHEN_FIX_BUG_7815
+ case (int) OPT_DELAYED:
+ /*
+ Because of http://bugs.mysql.com/bug.php?id=7815, we disable
+ --delayed-insert; when the bug gets fixed by checking the storage engine
+ (using the table definition cache) before printing INSERT DELAYED, we
+ can correct the option's description and re-enable it again (scheduled
+ for later 5.0 or 5.1 versions).
+ It's ok to do the if() below as get_one_option is called after
+ opt_delayed is set.
+ */
+ if (opt_delayed)
+ {
+ fprintf(stderr, "Warning: ignoring --delayed-insert (as explained "
+ "in the output of 'mysqldump --help').\n");
+ opt_delayed= 0;
+ }
+ break;
+#endif
}
return 0;
}
@@ -778,16 +811,16 @@ static int get_options(int *argc, char ***argv)
/*
-** DBerror -- prints mysql error message and exits the program.
+** DB_error -- prints mysql error message and exits the program.
*/
-static void DBerror(MYSQL *mysql, const char *when)
+static void DB_error(MYSQL *mysql, const char *when)
{
- DBUG_ENTER("DBerror");
+ DBUG_ENTER("DB_error");
my_printf_error(0,"Got error: %d: %s %s", MYF(0),
mysql_errno(mysql), mysql_error(mysql), when);
safe_exit(EX_MYSQLERR);
DBUG_VOID_RETURN;
-} /* DBerror */
+} /* DB_error */
/*
@@ -797,7 +830,8 @@ static void DBerror(MYSQL *mysql, const char *when)
SYNOPSIS
mysql_query_with_error_report()
mysql_con connection to use
- res if non zero, result will be put there with mysql_store_result
+ res if non zero, result will be put there with
+ mysql_store_result()
query query to send to server
RETURN VALUES
@@ -863,7 +897,7 @@ static int dbConnect(char *host, char *user,char *passwd)
NULL,opt_mysql_port,opt_mysql_unix_port,
0)))
{
- DBerror(&mysql_connection, "when trying to connect");
+ DB_error(&mysql_connection, "when trying to connect");
return 1;
}
/*
@@ -1126,7 +1160,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name,
uint i;
MYSQL_FIELD *field;
ulong *lengths= mysql_fetch_lengths(tableRes);
-
+
fprintf(xml_file, "\t\t<%s", row_name);
check_io(xml_file);
mysql_field_seek(tableRes, 0);
@@ -1146,6 +1180,104 @@ static void print_xml_row(FILE *xml_file, const char *row_name,
check_io(xml_file);
}
+/*
+ dump_routines_for_db
+ -- retrievs list of routines for a given db, and prints out
+ the CREATE PROCEDURE definition into the output (the dump).
+
+ This function has logic to print the appropriate syntax depending on whether
+ this is a procedure or functions
+
+ RETURN 0 succes, 1 if error
+*/
+
+static uint dump_routines_for_db (char *db)
+{
+ char query_buff[512];
+ const char *routine_type[]={"FUNCTION", "PROCEDURE"};
+ char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3], *routine_name;
+ int i;
+ FILE *sql_file = md_result_file;
+ MYSQL_RES *routine_res, *routine_list_res;
+ MYSQL_ROW row, routine_list_row;
+
+ DBUG_ENTER("dump_routines_for_db");
+
+ mysql_real_escape_string(sock, db_name_buff, db, strlen(db));
+ DBUG_PRINT("enter", ("db: '%s'", db_name_buff));
+
+ /* nice comments */
+ if (opt_comments)
+ fprintf(sql_file, "\n--\n-- Dumping routines for database '%s'\n--\n", db);
+
+ /*
+ not using "mysql_query_with_error_report" because we may have not
+ enough privileges to lock mysql.proc.
+ */
+ if (lock_tables)
+ mysql_query(sock, "LOCK TABLES mysql.proc READ");
+
+ fprintf(sql_file, "DELIMITER //\n");
+
+ /* 0, retrieve and dump functions, 1, procedures */
+ for (i=0; i <= 1; i++)
+ {
+ my_snprintf(query_buff, sizeof(query_buff),
+ "SHOW %s STATUS WHERE Db = '%s'",
+ routine_type[i], db_name_buff);
+
+ if (mysql_query_with_error_report(sock, &routine_list_res, query_buff))
+ DBUG_RETURN(1);
+
+ if (mysql_num_rows(routine_list_res))
+ {
+
+ while((routine_list_row= mysql_fetch_row(routine_list_res)))
+ {
+ DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i],
+ name_buff));
+ routine_name=quote_name(routine_list_row[1], name_buff, 0);
+ my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s",
+ routine_type[i], routine_name);
+
+ if (mysql_query_with_error_report(sock, &routine_res, query_buff))
+ DBUG_RETURN(1);
+
+ while ((row=mysql_fetch_row(routine_res)))
+ {
+ /*
+ if the user has EXECUTE privilege he see routine names, but NOT the
+ routine body of other routines that are not the creator of!
+ */
+ DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d",
+ routine_name, row[2], strlen(row[2])));
+ if (strlen(row[2]))
+ {
+ if (opt_drop)
+ fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */ //\n",
+ routine_type[i], routine_name);
+ /*
+ we need to change sql_mode only for the CREATE PROCEDURE/FUNCTION
+ otherwise we may need to re-quote routine_name
+ */;
+ fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/ //\n",
+ row[1] /* sql_mode */);
+ fprintf(sql_file, "/*!50003 %s */ //\n", row[2]);
+ fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/ //\n");
+ }
+ } /* end of routine printing */
+ } /* end of list of routines */
+ mysql_free_result(routine_res);
+ }
+ mysql_free_result(routine_list_res);
+ } /* end of for i (0 .. 1) */
+ /* set the delimiter back to ';' */
+ fprintf(sql_file, "DELIMITER ;\n");
+
+ if (lock_tables)
+ mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
+ DBUG_RETURN(0);
+}
/*
getTableStructure -- retrievs database structure, prints out corresponding
@@ -1155,7 +1287,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name,
number of fields in table, 0 if error
*/
-static uint getTableStructure(char *table, char* db)
+static uint get_table_structure(char *table, char *db)
{
MYSQL_RES *tableRes;
MYSQL_ROW row;
@@ -1168,7 +1300,7 @@ static uint getTableStructure(char *table, char* db)
char query_buff[512];
FILE *sql_file = md_result_file;
int len;
- DBUG_ENTER("getTableStructure");
+ DBUG_ENTER("get_table_structure");
DBUG_PRINT("enter", ("db: %s, table: %s", db, table));
if (!insert_pat_inited)
@@ -1195,7 +1327,7 @@ static uint getTableStructure(char *table, char* db)
opt_quoted_table= quote_name(table, table_buff2, 0);
if (opt_order_by_primary)
- order_by = primary_key_fields(opt_quoted_table);
+ order_by = primary_key_fields(result_table);
if (!opt_xml && !mysql_query_with_error_report(sock, 0, query_buff))
{
@@ -1204,6 +1336,7 @@ static uint getTableStructure(char *table, char* db)
{
/* Make an sql-file, if path was given iow. option -T was given */
char buff[20+FN_REFLEN];
+ MYSQL_FIELD *field;
my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
if (mysql_query_with_error_report(sock, 0, buff))
@@ -1237,8 +1370,64 @@ static uint getTableStructure(char *table, char* db)
check_io(sql_file);
}
- tableRes=mysql_store_result(sock);
- row=mysql_fetch_row(tableRes);
+ tableRes= mysql_store_result(sock);
+ field= mysql_fetch_field_direct(tableRes, 0);
+ if (strcmp(field->name, "View") == 0)
+ {
+ if (verbose)
+ fprintf(stderr, "-- It's a view, create dummy table for view\n");
+
+ mysql_free_result(tableRes);
+
+ /* Create a dummy table for the view. ie. a table which has the
+ same columns as the view should have. This table is dropped
+ just before the view is created. The table is used to handle the
+ case where a view references another view, which hasn't yet been
+ created(during the load of the dump). BUG#10927 */
+
+ /* Create temp table by selecting from the view */
+ my_snprintf(query_buff, sizeof(query_buff),
+ "CREATE TEMPORARY TABLE %s SELECT * FROM %s WHERE 0",
+ result_table, result_table);
+ if (mysql_query_with_error_report(sock, 0, query_buff))
+ {
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
+
+ /* Get CREATE statement for the temp table */
+ my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE TABLE %s",
+ result_table);
+ if (mysql_query_with_error_report(sock, 0, query_buff))
+ {
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
+ tableRes= mysql_store_result(sock);
+ row= mysql_fetch_row(tableRes);
+
+ if (opt_drop)
+ fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
+ opt_quoted_table);
+
+ /* Print CREATE statement but remove TEMPORARY */
+ fprintf(sql_file, "/*!50001 CREATE %s*/;\n", row[1]+17);
+ check_io(sql_file);
+
+ mysql_free_result(tableRes);
+
+ /* Drop the temp table */
+ my_snprintf(buff, sizeof(buff),
+ "DROP TEMPORARY TABLE %s", result_table);
+ if (mysql_query_with_error_report(sock, 0, buff))
+ {
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
+ was_views= 1;
+ DBUG_RETURN(0);
+ }
+ row= mysql_fetch_row(tableRes);
fprintf(sql_file, "%s;\n", row[1]);
check_io(sql_file);
mysql_free_result(tableRes);
@@ -1318,7 +1507,7 @@ static uint getTableStructure(char *table, char* db)
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
result_table);
if (opt_drop)
- fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",result_table);
+ fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", result_table);
if (!opt_xml)
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
else
@@ -1396,6 +1585,14 @@ static uint getTableStructure(char *table, char* db)
my_snprintf(buff, sizeof(buff), "show keys from %s", result_table);
if (mysql_query_with_error_report(sock, &tableRes, buff))
{
+ if (mysql_errno(sock) == ER_WRONG_OBJECT)
+ {
+ /* it is VIEW */
+ fputs("\t\t<options Comment=\"view\" />\n", sql_file);
+ goto continue_xml;
+ }
+ fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
+ my_progname, result_table, mysql_error(sock));
if (path)
my_fclose(sql_file, MYF(MY_WME));
safe_exit(EX_MYSQLERR);
@@ -1462,10 +1659,9 @@ static uint getTableStructure(char *table, char* db)
/* Get MySQL specific create options */
if (create_options)
{
- char show_name_buff[FN_REFLEN];
+ char show_name_buff[NAME_LEN*2+2+24];
/* Check memory for quote_for_like() */
- DBUG_ASSERT(2*sizeof(table) < sizeof(show_name_buff));
my_snprintf(buff, sizeof(buff), "show table status like %s",
quote_for_like(table, show_name_buff));
@@ -1503,6 +1699,7 @@ static uint getTableStructure(char *table, char* db)
}
mysql_free_result(tableRes); /* Is always safe to free */
}
+continue_xml:
if (!opt_xml)
fputs(";\n", sql_file);
else
@@ -1523,8 +1720,64 @@ static uint getTableStructure(char *table, char* db)
my_fclose(sql_file, MYF(MY_WME));
}
DBUG_RETURN(numFields);
-} /* getTableStructure */
+} /* get_table_structure */
+
+/*
+
+ dump_triggers_for_table
+
+ Dumps the triggers given a table/db name. This should be called after
+ the tables have been dumped in case a trigger depends on the existence
+ of a table
+
+*/
+
+static void dump_triggers_for_table (char *table, char *db)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ char *result_table;
+ char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
+ char query_buff[512];
+ FILE *sql_file = md_result_file;
+
+ DBUG_ENTER("dump_triggers_for_table");
+ DBUG_PRINT("enter", ("db: %s, table: %s", db, table));
+ result_table= quote_name(table, table_buff, 1);
+
+ my_snprintf(query_buff, sizeof(query_buff),
+ "SHOW TRIGGERS LIKE %s",
+ quote_for_like(table, name_buff));
+
+ if (mysql_query_with_error_report(sock, &result, query_buff))
+ {
+ if (path)
+ my_fclose(sql_file, MYF(MY_WME));
+ safe_exit(EX_MYSQLERR);
+ DBUG_VOID_RETURN;
+ }
+ if (mysql_num_rows(result))
+ fprintf(sql_file, "\n/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n\
+DELIMITER //;\n");
+ while ((row=mysql_fetch_row(result)))
+ {
+ fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\" */ //\n\
+/*!50003 CREATE TRIGGER %s %s %s ON %s FOR EACH ROW%s */ //\n\n",
+ row[6], /* sql_mode */
+ quote_name(row[0], name_buff, 0), /* Trigger */
+ row[4], /* Timing */
+ row[1], /* Event */
+ result_table,
+ row[3] /* Statement */);
+ }
+ if (mysql_num_rows(result))
+ fprintf(sql_file,
+ "DELIMITER ;//\n\
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;");
+ mysql_free_result(result);
+ DBUG_VOID_RETURN;
+}
static char *add_load_option(char *ptr,const char *object,
const char *statement)
@@ -1589,10 +1842,12 @@ static char *alloc_query_str(ulong size)
return query;
}
+
/*
-** dumpTable saves database contents as a series of INSERT statements.
+** dump_table saves database contents as a series of INSERT statements.
*/
-static void dumpTable(uint numFields, char *table)
+
+static void dump_table(uint numFields, char *table)
{
char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3];
char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
@@ -1604,6 +1859,26 @@ static void dumpTable(uint numFields, char *table)
const char *table_type;
int error= 0;
+ /* Check --no-data flag */
+ if (dFlag)
+ {
+ if (verbose)
+ fprintf(stderr,
+ "-- Skipping dump data for table '%s', --no-data was used\n",
+ table);
+ return;
+ }
+
+ /* Check that there are any fields in the table */
+ if (numFields == 0)
+ {
+ if (verbose)
+ fprintf(stderr,
+ "-- Skipping dump data for table '%s', it has no fields\n",
+ table);
+ return;
+ }
+
result_table= quote_name(table,table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
@@ -1658,7 +1933,7 @@ static void dumpTable(uint numFields, char *table)
}
if (mysql_real_query(sock, query, (uint) (end - query)))
{
- DBerror(sock, "when executing 'SELECT INTO OUTFILE'");
+ DB_error(sock, "when executing 'SELECT INTO OUTFILE'");
return;
}
}
@@ -1705,13 +1980,13 @@ static void dumpTable(uint numFields, char *table)
check_io(md_result_file);
}
if (mysql_query_with_error_report(sock, 0, query))
- DBerror(sock, "when retrieving data from server");
+ DB_error(sock, "when retrieving data from server");
if (quick)
res=mysql_use_result(sock);
else
res=mysql_store_result(sock);
if (!res)
- DBerror(sock, "when retrieving data from server");
+ DB_error(sock, "when retrieving data from server");
if (verbose)
fprintf(stderr, "-- Retrieving rows...\n");
if (mysql_num_fields(res) != numFields)
@@ -1784,12 +2059,14 @@ static void dumpTable(uint numFields, char *table)
we'll dump in hex only BLOB columns.
*/
is_blob= (opt_hex_blob && field->charsetnr == 63 &&
- (field->type == FIELD_TYPE_STRING ||
- field->type == FIELD_TYPE_VAR_STRING ||
- field->type == FIELD_TYPE_BLOB ||
- field->type == FIELD_TYPE_LONG_BLOB ||
- field->type == FIELD_TYPE_MEDIUM_BLOB ||
- field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0;
+ (field->type == MYSQL_TYPE_BIT ||
+ field->type == MYSQL_TYPE_STRING ||
+ field->type == MYSQL_TYPE_VAR_STRING ||
+ field->type == MYSQL_TYPE_VARCHAR ||
+ field->type == MYSQL_TYPE_BLOB ||
+ field->type == MYSQL_TYPE_LONG_BLOB ||
+ field->type == MYSQL_TYPE_MEDIUM_BLOB ||
+ field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0;
if (extended_insert)
{
ulong length = lengths[i];
@@ -2018,7 +2295,7 @@ err:
my_free(query, MYF(MY_ALLOW_ZERO_PTR));
safe_exit(error);
return;
-} /* dumpTable */
+} /* dump_table */
static char *getTableName(int reset)
@@ -2058,6 +2335,21 @@ static int dump_all_databases()
if (dump_all_tables_in_db(row[0]))
result=1;
}
+ if (was_views)
+ {
+ if (mysql_query(sock, "SHOW DATABASES") ||
+ !(tableres = mysql_store_result(sock)))
+ {
+ my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
+ MYF(0), mysql_error(sock));
+ return 1;
+ }
+ while ((row = mysql_fetch_row(tableres)))
+ {
+ if (dump_all_views_in_db(row[0]))
+ result=1;
+ }
+ }
return result;
}
/* dump_all_databases */
@@ -2066,20 +2358,33 @@ static int dump_all_databases()
static int dump_databases(char **db_names)
{
int result=0;
- for ( ; *db_names ; db_names++)
+ char **db;
+ for (db= db_names ; *db ; db++)
{
- if (dump_all_tables_in_db(*db_names))
+ if (dump_all_tables_in_db(*db))
result=1;
}
+ if (!result && was_views)
+ {
+ for (db= db_names ; *db ; db++)
+ {
+ if (dump_all_views_in_db(*db))
+ result=1;
+ }
+ }
return result;
} /* dump_databases */
static int init_dumping(char *database)
{
+ if (mysql_get_server_version(sock) >= 50003 &&
+ !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
+ return 1;
+
if (mysql_select_db(sock, database))
{
- DBerror(sock, "when selecting the database");
+ DB_error(sock, "when selecting the database");
return 1; /* If --force */
}
if (!path && !opt_xml)
@@ -2175,14 +2480,14 @@ static int dump_all_tables_in_db(char *database)
dynstr_append(&query, " READ /*!32311 LOCAL */,");
}
if (numrows && mysql_real_query(sock, query.str, query.length-1))
- DBerror(sock, "when using LOCK TABLES");
+ DB_error(sock, "when using LOCK TABLES");
/* We shall continue here, if --force was given */
dynstr_free(&query);
}
if (flush_logs)
{
if (mysql_refresh(sock, REFRESH_LOG))
- DBerror(sock, "when doing refresh");
+ DB_error(sock, "when doing refresh");
/* We shall continue here, if --force was given */
}
while ((table= getTableName(0)))
@@ -2190,13 +2495,21 @@ static int dump_all_tables_in_db(char *database)
char *end= strmov(afterdot, table);
if (include_table(hash_key, end - hash_key))
{
- numrows = getTableStructure(table, database);
- if (!dFlag && numrows > 0)
- dumpTable(numrows,table);
+ numrows = get_table_structure(table, database);
+ dump_table(numrows,table);
my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
order_by= 0;
+ if (opt_dump_triggers && ! opt_xml &&
+ mysql_get_server_version(sock) >= 50009)
+ dump_triggers_for_table(table, database);
}
}
+ if (opt_routines && !opt_xml &&
+ mysql_get_server_version(sock) >= 50009)
+ {
+ DBUG_PRINT("info", ("Dumping routines for database %s", database));
+ dump_routines_for_db(database);
+ }
if (opt_xml)
{
fputs("</database>\n", md_result_file);
@@ -2209,6 +2522,61 @@ static int dump_all_tables_in_db(char *database)
/*
+ dump structure of views of database
+
+ SYNOPSIS
+ dump_all_views_in_db()
+ database database name
+
+ RETURN
+ 0 OK
+ 1 ERROR
+*/
+
+static my_bool dump_all_views_in_db(char *database)
+{
+ char *table;
+ uint numrows;
+ char table_buff[NAME_LEN*2+3];
+
+ if (init_dumping(database))
+ return 1;
+ if (opt_xml)
+ print_xml_tag1(md_result_file, "", "database name=", database, "\n");
+ if (lock_tables)
+ {
+ DYNAMIC_STRING query;
+ init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
+ for (numrows= 0 ; (table= getTableName(1)); numrows++)
+ {
+ dynstr_append(&query, quote_name(table, table_buff, 1));
+ dynstr_append(&query, " READ /*!32311 LOCAL */,");
+ }
+ if (numrows && mysql_real_query(sock, query.str, query.length-1))
+ DB_error(sock, "when using LOCK TABLES");
+ /* We shall continue here, if --force was given */
+ dynstr_free(&query);
+ }
+ if (flush_logs)
+ {
+ if (mysql_refresh(sock, REFRESH_LOG))
+ DB_error(sock, "when doing refresh");
+ /* We shall continue here, if --force was given */
+ }
+ while ((table= getTableName(0)))
+ get_view_structure(table, database);
+ if (opt_xml)
+ {
+ fputs("</database>\n", md_result_file);
+ check_io(md_result_file);
+ }
+ if (lock_tables)
+ mysql_query(sock,"UNLOCK TABLES");
+ return 0;
+} /* dump_all_tables_in_db */
+
+
+/*
get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
table name from the server for the table name given on the command line.
we do this because the table name given on the command line may be a
@@ -2223,12 +2591,11 @@ static int get_actual_table_name(const char *old_table_name,
int buf_size)
{
int retval;
- MYSQL_RES *tableRes;
+ MYSQL_RES *table_res;
MYSQL_ROW row;
char query[50 + 2*NAME_LEN];
char show_name_buff[FN_REFLEN];
DBUG_ENTER("get_actual_table_name");
- DBUG_PRINT("enter", ("old_table_name: %s", old_table_name));
/* Check memory for quote_for_like() */
DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
@@ -2240,22 +2607,24 @@ static int get_actual_table_name(const char *old_table_name,
safe_exit(EX_MYSQLERR);
}
- tableRes= mysql_store_result( sock );
retval = 1;
- if (tableRes != NULL)
+
+ if ((table_res= mysql_store_result(sock)))
{
- my_ulonglong numRows= mysql_num_rows(tableRes);
- if (numRows > 0)
+ my_ulonglong num_rows= mysql_num_rows(table_res);
+ if (num_rows > 0)
{
- row= mysql_fetch_row( tableRes );
+ /*
+ Return first row
+ TODO: Return all matching rows
+ */
+ row= mysql_fetch_row(table_res);
strmake(new_table_name, row[0], buf_size-1);
retval= 0;
- DBUG_PRINT("info", ("new_table_name: %s", new_table_name));
}
- mysql_free_result(tableRes);
+ mysql_free_result(table_res);
}
- DBUG_PRINT("exit", ("retval: %d", retval));
- DBUG_RETURN(retval);
+ return retval;
}
@@ -2266,6 +2635,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
char new_table_name[NAME_LEN];
DYNAMIC_STRING lock_tables_query;
HASH dump_tables;
+ char *table_name;
DBUG_ENTER("dump_selected_tables");
if (init_dumping(db))
@@ -2273,17 +2643,16 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
/* Init hash table for storing the actual name of tables to dump */
if (hash_init(&dump_tables, charset_info, 16, 0, 0,
- (hash_get_key) get_table_key, (hash_free_key) free_table_ent,
+ (hash_get_key) get_table_key, (hash_free_key) free_table_ent,
0))
exit(EX_EOM);
init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024);
for (; tables > 0 ; tables-- , table_names++)
{
-
/* the table name passed on commandline may be wrong case */
if (!get_actual_table_name(*table_names,
- new_table_name, sizeof(new_table_name) ))
+ new_table_name, sizeof(new_table_name)))
{
/* Add found table name to lock_tables_query */
if (lock_tables)
@@ -2312,27 +2681,46 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
{
if (mysql_real_query(sock, lock_tables_query.str,
lock_tables_query.length-1))
- DBerror(sock, "when doing LOCK TABLES");
+ DB_error(sock, "when doing LOCK TABLES");
/* We shall countinue here, if --force was given */
}
dynstr_free(&lock_tables_query);
if (flush_logs)
{
if (mysql_refresh(sock, REFRESH_LOG))
- DBerror(sock, "when doing refresh");
+ DB_error(sock, "when doing refresh");
/* We shall countinue here, if --force was given */
}
if (opt_xml)
print_xml_tag1(md_result_file, "", "database name=", db, "\n");
/* Dump each selected table */
- for (i= 0 ; i < dump_tables.records ; i++)
+ for (i= 0; i < dump_tables.records; i++)
{
- const char *table_name= hash_element(&dump_tables, i);
+ table_name= hash_element(&dump_tables, i);
DBUG_PRINT("info",("Dumping table %s", table_name));
- numrows= getTableStructure((char*) table_name, db);
- if (!dFlag && numrows > 0)
- dumpTable(numrows, (char*) table_name);
+ numrows= get_table_structure(table_name, db);
+ dump_table(numrows, table_name);
+ if (opt_dump_triggers &&
+ mysql_get_server_version(sock) >= 50009)
+ dump_triggers_for_table(table_name, db);
+ }
+
+ /* Dump each selected view */
+ if (was_views)
+ {
+ for(i=0; i < dump_tables.records; i++)
+ {
+ table_name= hash_element(&dump_tables, i);
+ get_view_structure(table_name, db);
+ }
+ }
+ /* obtain dump of routines (procs/functions) */
+ if (opt_routines && !opt_xml &&
+ mysql_get_server_version(sock) >= 50009)
+ {
+ DBUG_PRINT("info", ("Dumping routines for database %s", db));
+ dump_routines_for_db(db);
}
hash_free(&dump_tables);
my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
@@ -2557,9 +2945,14 @@ static const char *check_if_ignore_table(const char *table_name)
mysql_free_result(res);
return 0; /* assume table is ok */
}
- if (strcmp(row[1], (result= "MRG_MyISAM")) &&
- strcmp(row[1], (result= "MRG_ISAM")))
- result= 0;
+ if (!(row[1]))
+ result= "VIEW";
+ else
+ {
+ if (strcmp(row[1], (result= "MRG_MyISAM")) &&
+ strcmp(row[1], (result= "MRG_ISAM")))
+ result= 0;
+ }
mysql_free_result(res);
return result;
}
@@ -2581,6 +2974,7 @@ static const char *check_if_ignore_table(const char *table_name)
or if there is some failure. It is better to continue to dump
the table unsorted, rather than exit without dumping the data.
*/
+
static char *primary_key_fields(const char *table_name)
{
MYSQL_RES *res = NULL;
@@ -2617,11 +3011,13 @@ static char *primary_key_fields(const char *table_name)
}
/* Build the ORDER BY clause result */
- if (result_length) {
+ if (result_length)
+ {
char *end;
/* result (terminating \0 is already in result_length) */
result = my_malloc(result_length + 10, MYF(MY_WME));
- if (!result) {
+ if (!result)
+ {
fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n");
goto cleanup;
}
@@ -2640,13 +3036,114 @@ cleanup:
}
+/*
+ Getting VIEW structure
+
+ SYNOPSIS
+ get_view_structure()
+ table view name
+ db db name
+
+ RETURN
+ 0 OK
+ 1 ERROR
+*/
+
+static my_bool get_view_structure(char *table, char* db)
+{
+ MYSQL_RES *table_res;
+ MYSQL_ROW row;
+ MYSQL_FIELD *field;
+ char *result_table, *opt_quoted_table;
+ char table_buff[NAME_LEN*2+3];
+ char table_buff2[NAME_LEN*2+3];
+ char buff[20+FN_REFLEN];
+ FILE *sql_file = md_result_file;
+ DBUG_ENTER("get_view_structure");
+
+ if (tFlag)
+ DBUG_RETURN(0);
+
+ if (verbose)
+ fprintf(stderr, "-- Retrieving view structure for table %s...\n", table);
+
+#ifdef NOT_REALLY_USED_YET
+ sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
+ (opt_quoted || opt_keywords));
+#endif
+
+ result_table= quote_name(table, table_buff, 1);
+ opt_quoted_table= quote_name(table, table_buff2, 0);
+
+ sprintf(buff,"show create table %s", result_table);
+ if (mysql_query(sock, buff))
+ {
+ fprintf(stderr, "%s: Can't get CREATE TABLE for view %s (%s)\n",
+ my_progname, result_table, mysql_error(sock));
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
+
+ if (path)
+ {
+ char filename[FN_REFLEN], tmp_path[FN_REFLEN];
+ convert_dirname(tmp_path,path,NullS);
+ sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
+ O_WRONLY, MYF(MY_WME));
+ if (!sql_file) /* If file couldn't be opened */
+ {
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(1);
+ }
+ write_header(sql_file, db);
+ }
+ table_res= mysql_store_result(sock);
+ field= mysql_fetch_field_direct(table_res, 0);
+ if (strcmp(field->name, "View") != 0)
+ {
+ if (verbose)
+ fprintf(stderr, "-- It's base table, skipped\n");
+ DBUG_RETURN(0);
+ }
+
+ if (!opt_xml && opt_comments)
+ {
+ fprintf(sql_file, "\n--\n-- View structure for view %s\n--\n\n",
+ result_table);
+ check_io(sql_file);
+ }
+ if (opt_drop)
+ {
+ fprintf(sql_file, "/*!50001 DROP TABLE IF EXISTS %s*/;\n",
+ opt_quoted_table);
+ fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n",
+ opt_quoted_table);
+ check_io(sql_file);
+ }
+
+ row= mysql_fetch_row(table_res);
+ fprintf(sql_file, "/*!50001 %s*/;\n", row[1]);
+ check_io(sql_file);
+ mysql_free_result(table_res);
+
+ if (sql_file != md_result_file)
+ {
+ fputs("\n", sql_file);
+ write_footer(sql_file);
+ my_fclose(sql_file, MYF(MY_WME));
+ }
+ DBUG_RETURN(0);
+}
+
+
int main(int argc, char **argv)
{
+ MY_INIT("mysqldump");
+
compatible_mode_normal_str[0]= 0;
default_charset= (char *)mysql_universal_client_charset;
bzero((char*) &ignore_table, sizeof(ignore_table));
- MY_INIT("mysqldump");
if (get_options(&argc, &argv))
{
my_end(0);
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index ca4acd82db6..ca0a751e963 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -398,6 +398,7 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *passwd)
ignore_errors=0; /* NO RETURN FROM db_error */
db_error(&mysql_connection);
}
+ mysql_connection.reconnect= 0;
if (verbose)
fprintf(stdout, "Selecting database %s\n", database);
if (mysql_select_db(sock, database))
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 44fc9448782..8f6be6cf70b 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -28,7 +28,8 @@
#include <sslopt-vars.h>
static my_string host=0,opt_password=0,user=0;
-static my_bool opt_show_keys=0,opt_compress=0,opt_status=0, tty_password=0;
+static my_bool opt_show_keys= 0, opt_compress= 0, opt_count=0, opt_status= 0,
+ tty_password= 0, opt_table_type= 0;
static uint opt_verbose=0;
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
@@ -70,8 +71,7 @@ int main(int argc, char **argv)
char *pos= argv[argc-1], *to;
for (to= pos ; *pos ; pos++, to++)
{
- switch (*pos)
- {
+ switch (*pos) {
case '*':
*pos= '%';
first_argument_uses_wildcards= 1;
@@ -125,6 +125,7 @@ int main(int argc, char **argv)
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
exit(1);
}
+ mysql.reconnect= 1;
switch (argc)
{
@@ -165,6 +166,10 @@ static struct my_option my_long_options[] =
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", (gptr*) &default_charset,
(gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"count", OPT_COUNT,
+ "Show number of rows per table (may be slow for not MyISAM tables)",
+ (gptr*) &opt_count, (gptr*) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ 0, 0, 0},
{"compress", 'C', "Use compression in server/client protocol.",
(gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
@@ -196,6 +201,9 @@ static struct my_option my_long_options[] =
"Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"show-table-type", 't', "Show table type column.",
+ (gptr*) &opt_table_type, (gptr*) &opt_table_type, 0, GET_BOOL,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -312,6 +320,14 @@ get_options(int *argc,char ***argv)
if (tty_password)
opt_password=get_tty_password(NullS);
+ if (opt_count)
+ {
+ /*
+ We need to set verbose to 2 as we need to change the output to include
+ the number-of-rows column
+ */
+ opt_verbose= 2;
+ }
return;
}
@@ -326,7 +342,7 @@ list_dbs(MYSQL *mysql,const char *wild)
char query[255];
MYSQL_FIELD *field;
MYSQL_RES *result;
- MYSQL_ROW row, trow, rrow;
+ MYSQL_ROW row, rrow;
if (!(result=mysql_list_dbs(mysql,wild)))
{
@@ -356,11 +372,6 @@ list_dbs(MYSQL *mysql,const char *wild)
if (opt_verbose)
{
- /*
- * Original code by MG16373; Slightly modified by Monty.
- * Print now the count of tables and rows for each database.
- */
-
if (!(mysql_select_db(mysql,row[0])))
{
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
@@ -370,6 +381,8 @@ list_dbs(MYSQL *mysql,const char *wild)
rowcount = 0;
if (opt_verbose > 1)
{
+ /* Print the count of tables and rows for each database */
+ MYSQL_ROW trow;
while ((trow = mysql_fetch_row(tresult)))
{
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
@@ -426,7 +439,7 @@ list_tables(MYSQL *mysql,const char *db,const char *table)
{
const char *header;
uint head_length, counter = 0;
- char query[255], rows[64], fields[16];
+ char query[255], rows[NAME_LEN], fields[16];
MYSQL_FIELD *field;
MYSQL_RES *result;
MYSQL_ROW row, rrow;
@@ -437,7 +450,20 @@ list_tables(MYSQL *mysql,const char *db,const char *table)
mysql_error(mysql));
return 1;
}
- if (!(result=mysql_list_tables(mysql,table)))
+ if (table)
+ {
+ /*
+ We just hijack the 'rows' variable for a bit to store the escaped
+ table name
+ */
+ mysql_real_escape_string(mysql, rows, table, (unsigned long)strlen(table));
+ my_snprintf(query, sizeof(query), "show%s tables like '%s'",
+ opt_table_type ? " full" : "", rows);
+ }
+ else
+ my_snprintf(query, sizeof(query), "show%s tables",
+ opt_table_type ? " full" : "");
+ if (mysql_query(mysql, query) || !(result= mysql_store_result(mysql)))
{
fprintf(stderr,"%s: Cannot list tables in %s: %s\n",my_progname,db,
mysql_error(mysql));
@@ -454,19 +480,30 @@ list_tables(MYSQL *mysql,const char *db,const char *table)
if (head_length < field->max_length)
head_length=field->max_length;
- if (!opt_verbose)
- print_header(header,head_length,NullS);
- else if (opt_verbose == 1)
- print_header(header,head_length,"Columns",8,NullS);
+ if (opt_table_type)
+ {
+ if (!opt_verbose)
+ print_header(header,head_length,"table_type",10,NullS);
+ else if (opt_verbose == 1)
+ print_header(header,head_length,"table_type",10,"Columns",8,NullS);
+ else
+ {
+ print_header(header,head_length,"table_type",10,"Columns",8,
+ "Total Rows",10,NullS);
+ }
+ }
else
- print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
+ {
+ if (!opt_verbose)
+ print_header(header,head_length,NullS);
+ else if (opt_verbose == 1)
+ print_header(header,head_length,"Columns",8,NullS);
+ else
+ print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
+ }
while ((row = mysql_fetch_row(result)))
{
- /*
- * Modified by MG16373
- * Print now the count of rows for each table.
- */
counter++;
if (opt_verbose > 0)
{
@@ -486,6 +523,7 @@ list_tables(MYSQL *mysql,const char *db,const char *table)
if (opt_verbose > 1)
{
+ /* Print the count of rows for each table */
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
if (!(mysql_query(mysql,query)))
{
@@ -508,17 +546,31 @@ list_tables(MYSQL *mysql,const char *db,const char *table)
strmov(rows,"N/A");
}
}
- if (!opt_verbose)
- print_row(row[0],head_length,NullS);
- else if (opt_verbose == 1)
- print_row(row[0],head_length, fields,8, NullS);
- else
- print_row(row[0],head_length, fields,8, rows,10, NullS);
+ if (opt_table_type)
+ {
+ if (!opt_verbose)
+ print_row(row[0],head_length,row[1],10,NullS);
+ else if (opt_verbose == 1)
+ print_row(row[0],head_length,row[1],10,fields,8,NullS);
+ else
+ print_row(row[0],head_length,row[1],10,fields,8,rows,10,NullS);
+ }
+ else
+ {
+ if (!opt_verbose)
+ print_row(row[0],head_length,NullS);
+ else if (opt_verbose == 1)
+ print_row(row[0],head_length, fields,8, NullS);
+ else
+ print_row(row[0],head_length, fields,8, rows,10, NullS);
+ }
}
print_trailer(head_length,
- (opt_verbose > 0 ? 8 : 0),
- (opt_verbose > 1 ? 10 :0),
+ (opt_table_type ? 10 : opt_verbose > 0 ? 8 : 0),
+ (opt_table_type ? (opt_verbose > 0 ? 8 : 0)
+ : (opt_verbose > 1 ? 10 :0)),
+ !opt_table_type ? 0 : opt_verbose > 1 ? 10 :0,
0);
if (counter && opt_verbose)
@@ -536,7 +588,7 @@ list_table_status(MYSQL *mysql,const char *db,const char *wild)
MYSQL_RES *result;
MYSQL_ROW row;
- end=strxmov(query,"show table status from ",db,NullS);
+ end=strxmov(query,"show table status from `",db,"`",NullS);
if (wild && wild[0])
strxmov(end," like '",wild,"'",NullS);
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
@@ -562,8 +614,8 @@ list_table_status(MYSQL *mysql,const char *db,const char *wild)
}
/*
-** list fields uses field interface as an example of how to parse
-** a MYSQL FIELD
+ list fields uses field interface as an example of how to parse
+ a MYSQL FIELD
*/
static int
@@ -573,6 +625,8 @@ list_fields(MYSQL *mysql,const char *db,const char *table,
char query[1024],*end;
MYSQL_RES *result;
MYSQL_ROW row;
+ ulong rows;
+ LINT_INIT(rows);
if (mysql_select_db(mysql,db))
{
@@ -580,6 +634,21 @@ list_fields(MYSQL *mysql,const char *db,const char *table,
mysql_error(mysql));
return 1;
}
+
+ if (opt_count)
+ {
+ sprintf(query,"select count(*) from `%s`", table);
+ if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
+ {
+ fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
+ my_progname,db,table,mysql_error(mysql));
+ return 1;
+ }
+ row= mysql_fetch_row(result);
+ rows= (ulong) strtoull(row[0], (char**) 0, 10);
+ mysql_free_result(result);
+ }
+
end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
if (wild && wild[0])
strxmov(end," like '",wild,"'",NullS);
@@ -590,8 +659,9 @@ list_fields(MYSQL *mysql,const char *db,const char *table,
return 1;
}
- printf("Database: %s Table: %s Rows: %lu", db,table,
- (ulong) mysql->extra_info);
+ printf("Database: %s Table: %s", db, table);
+ if (opt_count)
+ printf(" Rows: %lu", rows);
if (wild && wild[0])
printf(" Wildcard: %s",wild);
putchar('\n');
@@ -625,7 +695,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table,
/*****************************************************************************
-** General functions to print a nice ascii-table from data
+ General functions to print a nice ascii-table from data
*****************************************************************************/
static void
diff --git a/client/mysqltest.c b/client/mysqltest.c
index f5facccee3a..287fa012b7d 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -66,7 +66,8 @@
#ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
-#define MAX_QUERY 131072
+/* MAX_QUERY is 256K -- there is a test in sp-big that is >128K */
+#define MAX_QUERY (256*1024)
#define MAX_VAR_NAME 256
#define MAX_COLUMNS 256
#define PAD_SIZE 128
@@ -132,6 +133,17 @@ typedef struct
} code;
} match_err;
+typedef struct
+{
+ const char *name;
+ long code;
+} st_error;
+
+static st_error global_error[] = {
+#include <mysqld_ername.h>
+ { 0, 0 }
+};
+
static match_err global_expected_errno[MAX_EXPECTED_ERRORS];
static uint global_expected_errors;
@@ -143,6 +155,7 @@ const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
static int port = 0;
static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0;
static my_bool tty_password= 0, ps_protocol= 0, ps_protocol_enabled= 0;
+static int parsing_disabled= 0;
static uint start_lineno, *lineno;
const char *manager_user="root",*manager_host=0;
char *manager_pass=0;
@@ -169,6 +182,17 @@ static char TMPDIR[FN_REFLEN];
static char delimiter[MAX_DELIMITER]= DEFAULT_DELIMITER;
static uint delimiter_length= 1;
+/* Block stack */
+enum block_cmd { cmd_none, cmd_if, cmd_while };
+typedef struct
+{
+ int line; /* Start line of block */
+ my_bool ok; /* Should block be executed */
+ enum block_cmd cmd; /* Command owning the block */
+} BLOCK;
+static BLOCK block_stack[BLOCK_STACK_DEPTH];
+static BLOCK *cur_block, *block_stack_end;
+
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
static const char *charset_name= "latin1"; /* Default character set name */
@@ -245,6 +269,7 @@ typedef struct
static char *subst_env_var(const char *cmd);
static FILE *my_popen(const char *cmd, const char *mode);
+#undef popen
#define popen(A,B) my_popen((A),(B))
#endif /* __NETWARE__ */
@@ -252,6 +277,7 @@ VAR var_reg[10];
/*Perl/shell-like variable registers */
HASH var_hash;
my_bool disable_query_log=0, disable_result_log=0, disable_warnings=0;
+my_bool disable_ps_warnings= 0;
my_bool disable_info= 1; /* By default off */
my_bool abort_on_error= 1;
@@ -282,6 +308,7 @@ Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
Q_WAIT_FOR_SLAVE_TO_STOP,
Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
+Q_ENABLE_PS_WARNINGS, Q_DISABLE_PS_WARNINGS,
Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_ENABLE_METADATA, Q_DISABLE_METADATA,
Q_EXEC, Q_DELIMITER,
@@ -290,8 +317,10 @@ Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
Q_START_TIMER, Q_END_TIMER,
Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
+Q_EXIT,
Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
Q_IF,
+Q_DISABLE_PARSING, Q_ENABLE_PARSING,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
@@ -360,6 +389,8 @@ const char *command_names[]=
"wait_for_slave_to_stop",
"enable_warnings",
"disable_warnings",
+ "enable_ps_warnings",
+ "disable_ps_warnings",
"enable_info",
"disable_info",
"enable_metadata",
@@ -377,22 +408,15 @@ const char *command_names[]=
"character_set",
"disable_ps_protocol",
"enable_ps_protocol",
+ "exit",
"disable_reconnect",
"enable_reconnect",
"if",
+ "disable_parsing",
+ "enable_parsing",
0
};
-/* Block stack */
-typedef struct
-{
- int line; /* Start line of block */
- my_bool ok; /* Should block be executed */
- enum enum_commands cmd; /* Command owning the block */
-} BLOCK;
-static BLOCK block_stack[BLOCK_STACK_DEPTH];
-static BLOCK *cur_block, *block_stack_end;
-
TYPELIB command_typelib= {array_elements(command_names),"",
command_names, 0};
@@ -460,6 +484,10 @@ my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int len);
+static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
+static int handle_error(const char *query, struct st_query *q,
+ unsigned int err_errno, const char *err_error,
+ const char *err_sqlstate, DYNAMIC_STRING *ds);
static int handle_no_error(struct st_query *q);
static void do_eval(DYNAMIC_STRING* query_eval, const char *query)
@@ -654,6 +682,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
{
DBUG_PRINT("info",("Size differs: result size: %u file size: %u",
ds->length, stat_info.st_size));
+ DBUG_PRINT("info",("result: '%s'", ds->str));
DBUG_RETURN(RESULT_LENGTH_MISMATCH);
}
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
@@ -702,6 +731,8 @@ static int check_result(DYNAMIC_STRING* ds, const char *fname,
int error= RESULT_OK;
int res= dyn_string_cmp(ds, fname);
+ DBUG_ENTER("check_result");
+
if (res && require_option)
abort_not_supported_test();
switch (res) {
@@ -720,7 +751,7 @@ static int check_result(DYNAMIC_STRING* ds, const char *fname,
}
if (error)
reject_dump(fname, ds->str, ds->length);
- return error;
+ DBUG_RETURN(error);
}
@@ -1043,7 +1074,7 @@ static void do_exec(struct st_query *query)
ds= &ds_res;
while (fgets(buf, sizeof(buf), res_file))
- replace_dynstr_append_mem(ds, buf, strlen(buf));
+ replace_dynstr_append(ds, buf);
}
error= pclose(res_file);
if (error != 0)
@@ -1058,6 +1089,8 @@ static void do_exec(struct st_query *query)
("error: %d, status: %d", error, status));
for (i= 0; i < query->expected_errors; i++)
{
+ DBUG_PRINT("info",
+ ("error: %d, status: %d", error, status));
DBUG_PRINT("info", ("expected error: %d",
query->expected_errno[i].code.errnum));
if ((query->expected_errno[i].type == ERR_ERRNO) &&
@@ -1606,6 +1639,7 @@ static uint get_errcodes(match_err *to,struct st_query *q)
{
char *p= q->first_argument;
uint count= 0;
+
DBUG_ENTER("get_errcodes");
if (!*p)
@@ -1616,19 +1650,41 @@ static uint get_errcodes(match_err *to,struct st_query *q)
if (*p == 'S')
{
/* SQLSTATE string */
- int i;
- p++;
- for (i = 0; my_isalnum(charset_info, *p) && i < SQLSTATE_LENGTH; p++, i++)
- to[count].code.sqlstate[i]= *p;
- to[count].code.sqlstate[i]= '\0';
+ char *end= ++p + SQLSTATE_LENGTH;
+ char *to_ptr= to[count].code.sqlstate;
+
+ for (; my_isalnum(charset_info, *p) && p != end; p++)
+ *to_ptr++= *p;
+ *to_ptr= 0;
+
to[count].type= ERR_SQLSTATE;
}
+ else if (*p == 'E')
+ {
+ /* SQL error as string */
+ st_error *e= global_error;
+ char *start= p++;
+
+ for (; *p == '_' || my_isalnum(charset_info, *p); p++)
+ ;
+ for (; e->name; e++)
+ {
+ if (!strncmp(start, e->name, (int) (p - start)))
+ {
+ to[count].code.errnum= (uint) e->code;
+ to[count].type= ERR_ERRNO;
+ break;
+ }
+ }
+ if (!e->name)
+ die("Unknown SQL error '%s'", start);
+ }
else
{
long val;
- p=str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val);
- if (p == NULL)
- die("Invalid argument in %s", q->query);
+
+ if (!(p= str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val)))
+ die("Invalid argument in %s", q->query);
to[count].code.errnum= (uint) val;
to[count].type= ERR_ERRNO;
}
@@ -1898,26 +1954,171 @@ void init_manager()
}
#endif
+
+/*
+ Connect to a server doing several retries if needed.
+
+ SYNOPSIS
+ safe_connect()
+ con - connection structure to be used
+ host, user, pass, - connection parameters
+ db, port, sock
+
+ NOTE
+ This function will try to connect to the given server MAX_CON_TRIES
+ times and sleep CON_RETRY_SLEEP seconds between attempts before
+ finally giving up. This helps in situation when the client starts
+ before the server (which happens sometimes).
+ It will ignore any errors during these retries. One should use
+ connect_n_handle_errors() if he expects a connection error and wants
+ handle as if it was an error from a usual statement.
+
+ RETURN VALUE
+ 0 - success, non-0 - failure
+*/
+
int safe_connect(MYSQL* con, const char *host, const char *user,
const char *pass,
const char *db, int port, const char *sock)
{
- int con_error = 1;
+ int con_error= 1;
+ my_bool reconnect= 1;
int i;
- for (i = 0; i < MAX_CON_TRIES; ++i)
+ for (i= 0; i < MAX_CON_TRIES; ++i)
{
if (mysql_real_connect(con, host,user, pass, db, port, sock,
- CLIENT_MULTI_STATEMENTS))
+ CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
{
- con_error = 0;
+ con_error= 0;
break;
}
sleep(CON_RETRY_SLEEP);
}
+ /*
+ TODO: change this to 0 in future versions, but the 'kill' test relies on
+ existing behavior
+ */
+ mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect);
return con_error;
}
+/*
+ Connect to a server and handle connection errors in case when they occur.
+
+ SYNOPSIS
+ connect_n_handle_errors()
+ q - context of connect "query" (command)
+ con - connection structure to be used
+ host, user, pass, - connection parameters
+ db, port, sock
+ create_conn - out parameter, set to zero if connection was
+ not established and is not touched otherwise
+
+ DESCRIPTION
+ This function will try to establish a connection to server and handle
+ possible errors in the same manner as if "connect" was usual SQL-statement
+ (If error is expected it will ignore it once it occurs and log the
+ "statement" to the query log).
+ Unlike safe_connect() it won't do several attempts.
+
+ RETURN VALUE
+ 0 - success, non-0 - failure
+*/
+
+int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
+ const char* user, const char* pass,
+ const char* db, int port, const char* sock,
+ int* create_conn)
+{
+ DYNAMIC_STRING ds_tmp, *ds;
+ my_bool reconnect= 1;
+ int error= 0;
+
+ /*
+ Altough we ignore --require or --result before connect() command we still
+ need to handle record_file because of "@result_file sql-command" syntax.
+ */
+ if (q->record_file[0])
+ {
+ init_dynamic_string(&ds_tmp, "", 16384, 65536);
+ ds= &ds_tmp;
+ }
+ else
+ ds= &ds_res;
+
+ if (!disable_query_log)
+ {
+ /*
+ It is nice to have connect() statement logged in result file
+ in this case.
+ QQ: Should we do this only if we are expecting an error ?
+ */
+ char port_buff[22]; /* This should be enough for any int */
+ char *port_end;
+ dynstr_append_mem(ds, "connect(", 8);
+ replace_dynstr_append(ds, host);
+ dynstr_append_mem(ds, ",", 1);
+ replace_dynstr_append(ds, user);
+ dynstr_append_mem(ds, ",", 1);
+ replace_dynstr_append(ds, pass);
+ dynstr_append_mem(ds, ",", 1);
+ if (db)
+ replace_dynstr_append(ds, db);
+ dynstr_append_mem(ds, ",", 1);
+ port_end= int10_to_str(port, port_buff, 10);
+ replace_dynstr_append_mem(ds, port_buff, port_end - port_buff);
+ dynstr_append_mem(ds, ",", 1);
+ if (sock)
+ replace_dynstr_append(ds, sock);
+ dynstr_append_mem(ds, ")", 1);
+ dynstr_append_mem(ds, delimiter, delimiter_length);
+ dynstr_append_mem(ds, "\n", 1);
+ }
+ if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
+ CLIENT_MULTI_STATEMENTS))
+ {
+ error= handle_error("connect", q, mysql_errno(con), mysql_error(con),
+ mysql_sqlstate(con), ds);
+ *create_conn= 0;
+ goto err;
+ }
+ else if (handle_no_error(q))
+ {
+ /*
+ Fail if there was no error but we expected it.
+ We also don't want to have connection in this case.
+ */
+ mysql_close(con);
+ *create_conn= 0;
+ error= 1;
+ goto err;
+ }
+
+ /*
+ TODO: change this to 0 in future versions, but the 'kill' test relies on
+ existing behavior
+ */
+ mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect);
+
+ if (record)
+ {
+ if (!q->record_file[0] && !result_file)
+ die("Missing result file");
+ if (!result_file)
+ str_to_file(q->record_file, ds->str, ds->length);
+ }
+ else if (q->record_file[0])
+ error|= check_result(ds, q->record_file, q->require_file);
+
+err:
+ free_replace();
+ if (ds == &ds_tmp)
+ dynstr_free(&ds_tmp);
+ return error;
+}
+
+
int do_connect(struct st_query *q)
{
char *con_name, *con_user,*con_pass, *con_host, *con_port_str,
@@ -1926,6 +2127,8 @@ int do_connect(struct st_query *q)
char buff[FN_REFLEN];
int con_port;
int free_con_sock= 0;
+ int error= 0;
+ int create_conn= 1;
DBUG_ENTER("do_connect");
DBUG_PRINT("enter",("connect: %s",p));
@@ -1991,18 +2194,27 @@ int do_connect(struct st_query *q)
/* Special database to allow one to connect without a database name */
if (con_db && !strcmp(con_db,"*NO-ONE*"))
con_db= 0;
- if ((safe_connect(&next_con->mysql, con_host,
- con_user, con_pass,
- con_db, con_port, con_sock ? con_sock: 0)))
- die("Could not open connection '%s': %s", con_name,
- mysql_error(&next_con->mysql));
+ if (q->abort_on_error)
+ {
+ if ((safe_connect(&next_con->mysql, con_host, con_user, con_pass,
+ con_db, con_port, con_sock ? con_sock: 0)))
+ die("Could not open connection '%s': %s", con_name,
+ mysql_error(&next_con->mysql));
+ }
+ else
+ error= connect_n_handle_errors(q, &next_con->mysql, con_host, con_user,
+ con_pass, con_db, con_port, con_sock,
+ &create_conn);
- if (!(next_con->name= my_strdup(con_name, MYF(MY_WME))))
- die(NullS);
- cur_con= next_con++;
+ if (create_conn)
+ {
+ if (!(next_con->name= my_strdup(con_name, MYF(MY_WME))))
+ die(NullS);
+ cur_con= next_con++;
+ }
if (free_con_sock)
my_free(con_sock, MYF(MY_WME));
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
@@ -2017,7 +2229,7 @@ int do_done(struct st_query *q)
}
/* Test if inner block has been executed */
- if (cur_block->ok && cur_block->cmd == Q_WHILE)
+ if (cur_block->ok && cur_block->cmd == cmd_while)
{
/* Pop block from stack, re-execute outer block */
cur_block--;
@@ -2033,12 +2245,12 @@ int do_done(struct st_query *q)
}
-int do_block(enum enum_commands cmd, struct st_query *q)
+int do_block(enum block_cmd cmd, struct st_query* q)
{
char *p= q->first_argument;
const char *expr_start, *expr_end;
VAR v;
- const char *cmd_name= (cmd == Q_WHILE ? "while" : "if");
+ const char *cmd_name= (cmd == cmd_while ? "while" : "if");
/* Check stack overflow */
if (cur_block == block_stack_end)
@@ -2160,12 +2372,13 @@ my_bool end_of_query(int c)
int read_line(char *buf, int size)
{
int c;
+ char quote;
char *p= buf, *buf_end= buf + size - 1;
int no_save= 0;
- 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;
+ enum {R_NORMAL, R_Q, R_Q_IN_Q, R_SLASH_IN_Q,
+ R_COMMENT, R_LINE_START} state= R_LINE_START;
DBUG_ENTER("read_line");
+ LINT_INIT(quote);
start_lineno= *lineno;
for (; p < buf_end ;)
@@ -2194,6 +2407,7 @@ int read_line(char *buf, int size)
start_lineno= *(lineno+1);
die("Missing end of block");
}
+ DBUG_PRINT("info", ("end of file"));
DBUG_RETURN(1);
}
cur_file--;
@@ -2212,10 +2426,11 @@ int read_line(char *buf, int size)
*p= 0;
DBUG_RETURN(0);
}
- else if (c == '\'')
- state = R_Q1;
- else if (c == '"')
- state = R_Q2;
+ else if (c == '\'' || c == '"' || c == '`')
+ {
+ quote= c;
+ state= R_Q;
+ }
else if (c == '\n')
{
state = R_LINE_START;
@@ -2230,7 +2445,7 @@ int read_line(char *buf, int size)
break;
case R_LINE_START:
/* Only accept start of comment if this is the first line in query */
- if ((*lineno == start_lineno) && (c == '#' || c == '-'))
+ if ((*lineno == start_lineno) && (c == '#' || c == '-' || parsing_disabled))
{
state = R_COMMENT;
}
@@ -2251,55 +2466,36 @@ int read_line(char *buf, int size)
*p= 0;
DBUG_RETURN(0);
}
- else if (c == '\'')
- state= R_Q1;
- else if (c == '"')
- state= R_Q2;
- else
- state= R_NORMAL;
- break;
-
- case R_Q1:
- if (c == '\'')
- state= R_ESC_Q_Q1;
- else if (c == '\\')
- state= R_ESC_SLASH_Q1;
- break;
- case R_ESC_Q_Q1:
- if (end_of_query(c))
+ else if (c == '\'' || c == '"' || c == '`')
{
- *p= 0;
- DBUG_RETURN(0);
+ quote= c;
+ state= R_Q;
}
- if (c != '\'')
- state= R_NORMAL;
else
- state= R_Q1;
- break;
- case R_ESC_SLASH_Q1:
- state= R_Q1;
+ state= R_NORMAL;
break;
- case R_Q2:
- if (c == '"')
- state= R_ESC_Q_Q2;
+ case R_Q:
+ if (c == quote)
+ state= R_Q_IN_Q;
else if (c == '\\')
- state= R_ESC_SLASH_Q2;
+ state= R_SLASH_IN_Q;
break;
- case R_ESC_Q_Q2:
+ case R_Q_IN_Q:
if (end_of_query(c))
{
*p= 0;
DBUG_RETURN(0);
}
- if (c != '"')
+ if (c != quote)
state= R_NORMAL;
else
- state= R_Q2;
+ state= R_Q;
break;
- case R_ESC_SLASH_Q2:
- state= R_Q2;
+ case R_SLASH_IN_Q:
+ state= R_Q;
break;
+
}
if (!no_save)
@@ -2386,7 +2582,6 @@ int read_query(struct st_query** q_ptr)
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));
@@ -2396,16 +2591,20 @@ int read_query(struct st_query** q_ptr)
/* This goto is to avoid losing the "expected error" info. */
goto end;
}
- memcpy((gptr) q->expected_errno, (gptr) global_expected_errno,
- sizeof(global_expected_errno));
- q->expected_errors= global_expected_errors;
- q->abort_on_error= (global_expected_errors == 0 && abort_on_error);
+ if (!parsing_disabled)
+ {
+ memcpy((gptr) q->expected_errno, (gptr) global_expected_errno,
+ sizeof(global_expected_errno));
+ q->expected_errors= global_expected_errors;
+ q->abort_on_error= (global_expected_errors == 0 && abort_on_error);
+ }
+
if (p[0] == '-' && p[1] == '-')
{
q->type= Q_COMMENT_WITH_COMMAND;
p+= 2; /* To calculate first word */
}
- else
+ else if (!parsing_disabled)
{
while (*p && my_isspace(charset_info, *p))
p++ ;
@@ -2537,6 +2736,8 @@ void usage()
#include <help_end.h>
+#include <help_end.h>
+
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
@@ -2704,6 +2905,13 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
dynstr_append_mem(ds, val, len);
}
+/* Append zero-terminated string to ds, with optional replace */
+
+static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
+{
+ replace_dynstr_append_mem(ds, val, strlen(val));
+}
+
/*
Append all results to the dynamic string separated with '\t'
@@ -2739,13 +2947,13 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
{
if (i)
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, val, len);
+ replace_dynstr_append_mem(ds, val, (int)len);
}
else
{
dynstr_append(ds, fields[i].name);
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, val, len);
+ replace_dynstr_append_mem(ds, val, (int)len);
dynstr_append_mem(ds, "\n", 1);
}
}
@@ -2765,8 +2973,6 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
static int run_query_normal(MYSQL *mysql, struct st_query *q, int flags);
static int run_query_stmt (MYSQL *mysql, struct st_query *q, int flags);
static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds);
-static int run_query_stmt_handle_error(char *query, struct st_query *q,
- MYSQL_STMT *stmt, DYNAMIC_STRING *ds);
static void run_query_display_metadata(MYSQL_FIELD *field, uint num_fields,
DYNAMIC_STRING *ds);
@@ -2850,68 +3056,10 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
(!(last_result= res= mysql_store_result(mysql)) &&
mysql_field_count(mysql)))
{
- if (q->require_file)
- {
- abort_not_supported_test();
- }
- if (q->abort_on_error)
- die("query '%s' failed: %d: %s", query,
- mysql_errno(mysql), mysql_error(mysql));
-
- for (i=0 ; (uint) i < q->expected_errors ; i++)
- {
- if (((q->expected_errno[i].type == ERR_ERRNO) &&
- (q->expected_errno[i].code.errnum == mysql_errno(mysql))) ||
- ((q->expected_errno[i].type == ERR_SQLSTATE) &&
- (strcmp(q->expected_errno[i].code.sqlstate,mysql_sqlstate(mysql)) == 0)))
- {
- if (i == 0 && q->expected_errors == 1)
- {
- /* Only log error if there is one possible error */
- dynstr_append_mem(ds,"ERROR ",6);
- replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
- strlen(mysql_sqlstate(mysql)));
- dynstr_append_mem(ds, ": ", 2);
- replace_dynstr_append_mem(ds,mysql_error(mysql),
- strlen(mysql_error(mysql)));
- dynstr_append_mem(ds,"\n",1);
- }
- /* Don't log error if we may not get an error */
- else if (q->expected_errno[0].type == ERR_SQLSTATE ||
- (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0))
- dynstr_append(ds,"Got one of the listed errors\n");
- goto end; /* Ok */
- }
- }
- DBUG_PRINT("info",("i: %d expected_errors: %d", i,
- q->expected_errors));
- dynstr_append_mem(ds, "ERROR ",6);
- replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
- strlen(mysql_sqlstate(mysql)));
- dynstr_append_mem(ds,": ",2);
- replace_dynstr_append_mem(ds, mysql_error(mysql),
- strlen(mysql_error(mysql)));
- dynstr_append_mem(ds,"\n",1);
- if (i)
- {
- if (q->expected_errno[0].type == ERR_ERRNO)
- verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
- q->query, mysql_errno(mysql), q->expected_errno[0].code.errnum);
- else
- verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...",
- q->query, mysql_sqlstate(mysql), q->expected_errno[0].code.sqlstate);
+ if (handle_error(query, q, mysql_errno(mysql), mysql_error(mysql),
+ mysql_sqlstate(mysql), ds))
error= 1;
- goto end;
- }
- verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
- mysql_error(mysql));
- /*
- if we do not abort on error, failure to run the query does
- not fail the whole test case
- */
goto end;
-
}
if (handle_no_error(q))
@@ -2939,8 +3087,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
{
if (i)
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, field[i].name,
- strlen(field[i].name));
+ replace_dynstr_append(ds, field[i].name);
}
dynstr_append_mem(ds, "\n", 1);
}
@@ -2954,8 +3101,13 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
if (!disable_info)
affected_rows= (ulong)mysql_affected_rows(mysql);
- /* Add all warnings to the result */
- if (!disable_warnings && mysql_warning_count(mysql))
+ /*
+ Add all warnings to the result. We can't do this if we are in
+ the middle of processing results from multi-statement, because
+ this will break protocol.
+ */
+ if (!disable_warnings && !mysql_more_results(mysql) &&
+ mysql_warning_count(mysql))
{
MYSQL_RES *warn_res=0;
uint count= mysql_warning_count(mysql);
@@ -2964,7 +3116,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
warn_res= mysql_store_result(mysql);
}
if (!warn_res)
- verbose_msg("Warning count is %u but didn't get any warnings\n",
+ verbose_msg("Warning count is %u but didn't get any warnings",
count);
else
{
@@ -3024,6 +3176,135 @@ end:
}
+/*
+ Handle errors which occurred after execution
+
+ SYNOPSIS
+ handle_error()
+ query - query string
+ q - query context
+ err_errno - error number
+ err_error - error message
+ err_sqlstate - sql state
+ ds - dynamic string which is used for output buffer
+
+ NOTE
+ If there is an unexpected error this function will abort mysqltest
+ immediately.
+
+ RETURN VALUE
+ 0 - OK
+ 1 - Some other error was expected.
+*/
+
+static int handle_error(const char *query, struct st_query *q,
+ unsigned int err_errno, const char *err_error,
+ const char* err_sqlstate, DYNAMIC_STRING *ds)
+{
+ uint i;
+
+ DBUG_ENTER("handle_error");
+
+ if (q->require_file)
+ abort_not_supported_test();
+
+ if (q->abort_on_error)
+ die("query '%s' failed: %d: %s", query,
+ err_errno, err_error);
+
+ for (i= 0 ; (uint) i < q->expected_errors ; i++)
+ {
+ if (((q->expected_errno[i].type == ERR_ERRNO) &&
+ (q->expected_errno[i].code.errnum == err_errno)) ||
+ ((q->expected_errno[i].type == ERR_SQLSTATE) &&
+ (strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0)))
+ {
+ if (q->expected_errors == 1)
+ {
+ /* Only log error if there is one possible error */
+ dynstr_append_mem(ds, "ERROR ", 6);
+ replace_dynstr_append(ds, err_sqlstate);
+ dynstr_append_mem(ds, ": ", 2);
+ replace_dynstr_append(ds, err_error);
+ dynstr_append_mem(ds,"\n",1);
+ }
+ /* Don't log error if we may not get an error */
+ else if (q->expected_errno[0].type == ERR_SQLSTATE ||
+ (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0))
+ dynstr_append(ds,"Got one of the listed errors\n");
+ /* OK */
+ DBUG_RETURN(0);
+ }
+ }
+
+ DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors));
+
+ dynstr_append_mem(ds, "ERROR ",6);
+ replace_dynstr_append(ds, err_sqlstate);
+ dynstr_append_mem(ds, ": ", 2);
+ replace_dynstr_append(ds, err_error);
+ dynstr_append_mem(ds, "\n", 1);
+
+ if (i)
+ {
+ if (q->expected_errno[0].type == ERR_ERRNO)
+ verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
+ q->query, err_errno,
+ q->expected_errno[0].code.errnum);
+ else
+ verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...",
+ q->query, err_sqlstate,
+ q->expected_errno[0].code.sqlstate);
+ DBUG_RETURN(1);
+ }
+
+ /*
+ If we do not abort on error, failure to run the query does not fail the
+ whole test case.
+ */
+ verbose_msg("query '%s' failed: %d: %s", q->query, err_errno,
+ err_error);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Handle absence of errors after execution
+
+ SYNOPSIS
+ handle_no_error()
+ q - context of query
+
+ RETURN VALUE
+ 0 - OK
+ 1 - Some error was expected from this query.
+*/
+
+static int handle_no_error(struct st_query *q)
+{
+ DBUG_ENTER("handle_no_error");
+
+ if (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0)
+ {
+ /* Error code we wanted was != 0, i.e. not an expected success */
+ verbose_msg("query '%s' succeeded - should have failed with errno %d...",
+ q->query, q->expected_errno[0].code.errnum);
+ DBUG_RETURN(1);
+ }
+ else if (q->expected_errno[0].type == ERR_SQLSTATE &&
+ strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
+ {
+ /* SQLSTATE we wanted was != "00000", i.e. not an expected success */
+ verbose_msg("query '%s' succeeded - should have failed with sqlstate %s...",
+ q->query, q->expected_errno[0].code.sqlstate);
+ DBUG_RETURN(1);
+ }
+
+ DBUG_RETURN(0);
+}
+
/****************************************************************************\
* If --ps-protocol run ordinary statements using prepared statemnt C API
\****************************************************************************/
@@ -3038,7 +3319,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
int error= 0; /* Function return code if "goto end;" */
int err; /* Temporary storage of return code from calls */
int query_len, got_error_on_execute;
- uint num_rows;
+ ulonglong num_rows;
char *query;
MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */
DYNAMIC_STRING *ds;
@@ -3096,22 +3377,25 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
{
if (q->abort_on_error)
{
- die("query '%s' failed: %d: %s", query,
- mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
+ die("query '%s' failed: %d: %s", query,
+ mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
}
else
{
/*
Preparing is part of normal execution and some errors may be expected
*/
- error= run_query_stmt_handle_error(query, q, stmt, ds);
+ error= handle_error(query, q, mysql_stmt_errno(stmt),
+ mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt),
+ ds);
goto end;
}
}
/* We may have got warnings already, collect them if any */
/* FIXME we only want this if the statement succeeds I think */
- run_query_stmt_handle_warnings(mysql, ds);
+ if (!disable_ps_warnings)
+ run_query_stmt_handle_warnings(mysql, ds);
/*
No need to call mysql_stmt_bind_param() because we have no
@@ -3136,7 +3420,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
else
{
/* We got an error, maybe expected */
- error= run_query_stmt_handle_error(query, q, stmt, ds);
+ error= handle_error(query, q, mysql_stmt_errno(stmt),
+ mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt),
+ ds);
goto end;
}
}
@@ -3172,7 +3458,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
else
{
/* We got an error, maybe expected */
- error= run_query_stmt_handle_error(query, q, stmt, ds);
+ error= handle_error(query, q, mysql_stmt_errno(stmt),
+ mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt),
+ ds);
goto end;
}
}
@@ -3211,8 +3499,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
{
if (col_idx)
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, field[col_idx].name,
- strlen(field[col_idx].name));
+ replace_dynstr_append(ds, field[col_idx].name);
}
dynstr_append_mem(ds, "\n", 1);
}
@@ -3228,7 +3515,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
/* Allocate array with bind structs, lengths and NULL flags */
bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND),
- MYF(MY_WME | MY_FAE));
+ MYF(MY_WME | MY_FAE | MY_ZEROFILL));
length= (unsigned long*) my_malloc(num_fields * sizeof(unsigned long),
MYF(MY_WME | MY_FAE));
is_null= (my_bool*) my_malloc(num_fields * sizeof(my_bool),
@@ -3287,13 +3574,13 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
{
if (col_idx) /* No tab before first col */
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, val, len);
+ replace_dynstr_append_mem(ds, val, (int)len);
}
else
{
dynstr_append(ds, field[col_idx].name);
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, val, len);
+ replace_dynstr_append_mem(ds, val, (int)len);
dynstr_append_mem(ds, "\n", 1);
}
}
@@ -3435,11 +3722,18 @@ static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds)
if (!disable_warnings && (count= mysql_warning_count(mysql)))
{
+ /*
+ If one day we will support execution of multi-statements
+ through PS API we should not issue SHOW WARNINGS until
+ we have not read all results...
+ */
+ DBUG_ASSERT(!mysql_more_results(mysql));
+
if (mysql_real_query(mysql, "SHOW WARNINGS", 13) == 0)
{
MYSQL_RES *warn_res= mysql_store_result(mysql);
if (!warn_res)
- verbose_msg("Warning count is %u but didn't get any warnings\n",
+ verbose_msg("Warning count is %u but didn't get any warnings",
count);
else
{
@@ -3453,118 +3747,6 @@ static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds)
}
-static int run_query_stmt_handle_error(char *query, struct st_query *q,
- MYSQL_STMT *stmt, DYNAMIC_STRING *ds)
-{
- if (q->require_file) /* FIXME don't understand this one */
- {
- abort_not_supported_test();
- }
-
- if (q->abort_on_error)
- die("query '%s' failed: %d: %s", query,
- mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
- else
- {
- int i;
-
- for (i=0 ; (uint) i < q->expected_errors ; i++)
- {
- if (((q->expected_errno[i].type == ERR_ERRNO) &&
- (q->expected_errno[i].code.errnum == mysql_stmt_errno(stmt))) ||
- ((q->expected_errno[i].type == ERR_SQLSTATE) &&
- (strcmp(q->expected_errno[i].code.sqlstate,
- mysql_stmt_sqlstate(stmt)) == 0)))
- {
- if (i == 0 && q->expected_errors == 1)
- {
- /* Only log error if there is one possible error */
- dynstr_append_mem(ds,"ERROR ",6);
- replace_dynstr_append_mem(ds, mysql_stmt_sqlstate(stmt),
- strlen(mysql_stmt_sqlstate(stmt)));
- dynstr_append_mem(ds, ": ", 2);
- replace_dynstr_append_mem(ds,mysql_stmt_error(stmt),
- strlen(mysql_stmt_error(stmt)));
- dynstr_append_mem(ds,"\n",1);
- }
- /* Don't log error if we may not get an error */
- else if (q->expected_errno[0].type == ERR_SQLSTATE ||
- (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0))
- dynstr_append(ds,"Got one of the listed errors\n");
- return 0; /* Ok */
- }
- }
- DBUG_PRINT("info",("i: %d expected_errors: %d", i,
- q->expected_errors));
- dynstr_append_mem(ds, "ERROR ",6);
- replace_dynstr_append_mem(ds, mysql_stmt_sqlstate(stmt),
- strlen(mysql_stmt_sqlstate(stmt)));
- dynstr_append_mem(ds,": ",2);
- replace_dynstr_append_mem(ds, mysql_stmt_error(stmt),
- strlen(mysql_stmt_error(stmt)));
- dynstr_append_mem(ds,"\n",1);
- if (i)
- {
- if (q->expected_errno[0].type == ERR_ERRNO)
- verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
- q->query, mysql_stmt_errno(stmt),
- q->expected_errno[0].code.errnum);
- else
- verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...",
- q->query, mysql_stmt_sqlstate(stmt),
- q->expected_errno[0].code.sqlstate);
- return 1; /* Error */
- }
- verbose_msg("query '%s' failed: %d: %s", q->query, mysql_stmt_errno(stmt),
- mysql_stmt_error(stmt));
- /*
- if we do not abort on error, failure to run the query does
- not fail the whole test case
- */
- return 0;
- }
-
- return 0;
-}
-
-
-/*
- Handle absence of errors after execution
-
- SYNOPSIS
- handle_no_error()
- q - context of query
-
- RETURN VALUE
- 0 - OK
- 1 - Some error was expected from this query.
-*/
-
-static int handle_no_error(struct st_query *q)
-{
- DBUG_ENTER("handle_no_error");
-
- if (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0)
- {
- /* Error code we wanted was != 0, i.e. not an expected success */
- verbose_msg("query '%s' succeeded - should have failed with errno %d...",
- q->query, q->expected_errno[0].code.errnum);
- DBUG_RETURN(1);
- }
- else if (q->expected_errno[0].type == ERR_SQLSTATE &&
- strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
- {
- /* SQLSTATE we wanted was != "00000", i.e. not an expected success */
- verbose_msg("query '%s' succeeded - should have failed with sqlstate %s...",
- q->query, q->expected_errno[0].code.sqlstate);
- DBUG_RETURN(1);
- }
-
- DBUG_RETURN(0);
-}
-
/****************************************************************************\
* Functions to match SQL statements that can be prepared
\****************************************************************************/
@@ -3638,20 +3820,45 @@ void get_query_type(struct st_query* q)
uint type;
DBUG_ENTER("get_query_type");
- if (*q->query == '}')
+ if (!parsing_disabled && *q->query == '}')
{
q->type = Q_END_BLOCK;
DBUG_VOID_RETURN;
}
if (q->type != Q_COMMENT_WITH_COMMAND)
- q->type = Q_QUERY;
+ q->type= parsing_disabled ? Q_COMMENT : Q_QUERY;
save=q->query[q->first_word_len];
q->query[q->first_word_len]=0;
type=find_type(q->query, &command_typelib, 1+2);
q->query[q->first_word_len]=save;
if (type > 0)
+ {
q->type=(enum enum_commands) type; /* Found command */
+ /*
+ If queries are disabled, only recognize
+ --enable-queries and --disable-queries
+ */
+ if (parsing_disabled && q->type != Q_ENABLE_PARSING &&
+ q->type != Q_DISABLE_PARSING)
+ q->type= Q_COMMENT;
+ }
+ else if (q->type == Q_COMMENT_WITH_COMMAND &&
+ q->query[q->first_word_len-1] == ';')
+ {
+ /*
+ Detect comment with command using extra delimiter
+ Ex --disable_query_log;
+ ^ Extra delimiter causing the command
+ to be skipped
+ */
+ save= q->query[q->first_word_len-1];
+ q->query[q->first_word_len-1]= 0;
+ type= find_type(q->query, &command_typelib, 1+2);
+ q->query[q->first_word_len-1]= save;
+ if (type > 0)
+ die("Extra delimiter \";\" found");
+ }
DBUG_VOID_RETURN;
}
@@ -3727,8 +3934,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");
- if (opt_big_test)
- my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0, "1",0));
+ my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0,
+ (opt_big_test) ? "1" : "0", 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);
@@ -3743,13 +3950,11 @@ int main(int argc, char **argv)
{
int error = 0;
struct st_query *q;
- my_bool require_file=0, q_send_flag=0, query_executed= 0;
+ my_bool require_file=0, q_send_flag=0, abort_flag= 0,
+ query_executed= 0;
char save_file[FN_REFLEN];
MY_STAT res_info;
MY_INIT(argv[0]);
- {
- DBUG_ENTER("main");
- DBUG_PROCESS(argv[0]);
/* Use all time until exit if no explicit 'start_timer' */
timer_start= timer_now();
@@ -3773,10 +3978,12 @@ int main(int argc, char **argv)
block_stack_end= block_stack + BLOCK_STACK_DEPTH - 1;
cur_block= block_stack;
cur_block->ok= TRUE; /* Outer block should always be executed */
- cur_block->cmd= Q_UNKNOWN;
+ cur_block->cmd= cmd_none;
init_dynamic_string(&ds_res, "", 0, 65536);
parse_args(argc, argv);
+
+ DBUG_PRINT("info",("result_file: '%s'", result_file ? result_file : ""));
if (mysql_server_init(embedded_server_arg_count,
embedded_server_args,
(char**) embedded_server_groups))
@@ -3824,7 +4031,7 @@ int main(int argc, char **argv)
*/
var_set_errno(-1);
- while (!read_query(&q))
+ while (!abort_flag && !read_query(&q))
{
int current_line_inc = 1, processed = 0;
if (q->type == Q_UNKNOWN || q->type == Q_COMMENT_WITH_COMMAND)
@@ -3834,7 +4041,9 @@ int main(int argc, char **argv)
q->last_argument= q->first_argument;
processed = 1;
switch (q->type) {
- case Q_CONNECT: do_connect(q); break;
+ case Q_CONNECT:
+ error|= do_connect(q);
+ break;
case Q_CONNECTION: select_connection(q); break;
case Q_DISCONNECT:
case Q_DIRTY_CLOSE:
@@ -3850,6 +4059,8 @@ int main(int argc, char **argv)
case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
case Q_ENABLE_WARNINGS: disable_warnings=0; break;
case Q_DISABLE_WARNINGS: disable_warnings=1; break;
+ case Q_ENABLE_PS_WARNINGS: disable_ps_warnings=0; break;
+ case Q_DISABLE_PS_WARNINGS: disable_ps_warnings=1; break;
case Q_ENABLE_INFO: disable_info=0; break;
case Q_DISABLE_INFO: disable_info=1; break;
case Q_ENABLE_METADATA: display_metadata=1; break;
@@ -4021,22 +4232,45 @@ int main(int argc, char **argv)
ps_protocol_enabled= ps_protocol;
break;
case Q_DISABLE_RECONNECT:
- cur_con->mysql.reconnect= 0;
+ {
+ my_bool reconnect= 0;
+ mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
break;
+ }
case Q_ENABLE_RECONNECT:
- cur_con->mysql.reconnect= 1;
+ {
+ my_bool reconnect= 1;
+ mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
+ break;
+ }
+ case Q_DISABLE_PARSING:
+ parsing_disabled++;
+ break;
+ case Q_ENABLE_PARSING:
+ /*
+ Ensure we don't get parsing_disabled < 0 as this would accidently
+ disable code we don't want to have disabled
+ */
+ if (parsing_disabled > 0)
+ parsing_disabled--;
break;
- default: processed = 0; break;
+ case Q_EXIT:
+ abort_flag= 1;
+ break;
+
+ default:
+ processed= 0;
+ break;
}
}
if (!processed)
{
- current_line_inc = 0;
+ current_line_inc= 0;
switch (q->type) {
- case Q_WHILE: do_block(Q_WHILE, q); break;
- case Q_IF: do_block(Q_IF, q); break;
+ case Q_WHILE: do_block(cmd_while, q); break;
+ case Q_IF: do_block(cmd_if, q); break;
case Q_END_BLOCK: do_done(q); break;
default: current_line_inc = 1; break;
}
@@ -4092,7 +4326,6 @@ int main(int argc, char **argv)
my_end(MY_CHECK_ERROR);
exit(error ? 1 : 0);
return error ? 1 : 0; /* Keep compiler happy */
- }
}
diff --git a/client/sql_string.cc b/client/sql_string.cc
index 690997152f1..51f802e7465 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -28,6 +28,11 @@
#include <floatingpoint.h>
#endif
+/*
+ The following extern declarations are ok as these are interface functions
+ required by the string function
+*/
+
extern gptr sql_alloc(unsigned size);
extern void sql_element_free(void *ptr);
@@ -97,14 +102,7 @@ bool String::set(longlong num, CHARSET_INFO *cs)
if (alloc(l))
return TRUE;
- if (cs->cset->snprintf == my_snprintf_8bit)
- {
- str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr);
- }
- else
- {
- str_length=cs->cset->snprintf(cs,Ptr,l,"%d",num);
- }
+ str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,-10,num);
str_charset=cs;
return FALSE;
}
@@ -115,14 +113,7 @@ bool String::set(ulonglong num, CHARSET_INFO *cs)
if (alloc(l))
return TRUE;
- if (cs->cset->snprintf == my_snprintf_8bit)
- {
- str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr);
- }
- else
- {
- str_length=cs->cset->snprintf(cs,Ptr,l,"%d",num);
- }
+ str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,10,num);
str_charset=cs;
return FALSE;
}
@@ -130,12 +121,13 @@ bool String::set(ulonglong num, CHARSET_INFO *cs)
bool String::set(double num,uint decimals, CHARSET_INFO *cs)
{
char buff[331];
+ uint dummy_errors;
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
- sprintf(buff,"%.14g",num); // Enough for a DATETIME
- return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs);
+ uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
+ return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
}
#ifdef HAVE_FCONVERT
int decpt,sign;
@@ -150,7 +142,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
buff[0]='-';
pos=buff;
}
- return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs);
+ uint dummy_errors;
+ return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors);
}
if (alloc((uint32) ((uint32) decpt+3+decimals)))
return TRUE;
@@ -200,7 +193,8 @@ end:
#else
sprintf(buff,"%.*f",(int) decimals,num);
#endif
- return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs);
+ return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs,
+ &dummy_errors);
#endif
}
@@ -237,55 +231,163 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
return FALSE;
}
-/* Copy with charset convertion */
-bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET_INFO *to)
+
+/*
+ Checks that the source string can be just copied to the destination string
+ without conversion.
+
+ SYNPOSIS
+
+ needs_conversion()
+ arg_length Length of string to copy.
+ from_cs Character set to copy from
+ to_cs Character set to copy to
+ uint32 *offset Returns number of unaligned characters.
+
+ RETURN
+ 0 No conversion needed
+ 1 Either character set conversion or adding leading zeros
+ (e.g. for UCS-2) must be done
+*/
+
+bool String::needs_conversion(uint32 arg_length,
+ CHARSET_INFO *from_cs,
+ CHARSET_INFO *to_cs,
+ uint32 *offset)
+{
+ *offset= 0;
+ if ((to_cs == &my_charset_bin) ||
+ (to_cs == from_cs) ||
+ my_charset_same(from_cs, to_cs) ||
+ ((from_cs == &my_charset_bin) &&
+ (!(*offset=(arg_length % to_cs->mbminlen)))))
+ return FALSE;
+ return TRUE;
+}
+
+
+/*
+ Copy a multi-byte character sets with adding leading zeros.
+
+ SYNOPSIS
+
+ copy_aligned()
+ str String to copy
+ arg_length Length of string. This should NOT be dividable with
+ cs->mbminlen.
+ offset arg_length % cs->mb_minlength
+ cs Character set for 'str'
+
+ NOTES
+ For real multi-byte, ascii incompatible charactser sets,
+ like UCS-2, add leading zeros if we have an incomplete character.
+ Thus,
+ SELECT _ucs2 0xAA
+ will automatically be converted into
+ SELECT _ucs2 0x00AA
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset,
+ CHARSET_INFO *cs)
{
- uint32 new_length=to->mbmaxlen*arg_length;
- int cnvres;
- my_wc_t wc;
- const uchar *s=(const uchar *)str;
- const uchar *se=s+arg_length;
- uchar *d, *de;
+ /* How many bytes are in incomplete character */
+ offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */
+ DBUG_ASSERT(offset && offset != cs->mbmaxlen);
- if (alloc(new_length))
+ uint32 aligned_length= arg_length + offset;
+ if (alloc(aligned_length))
return TRUE;
+
+ /*
+ Note, this is only safe for little-endian UCS-2.
+ If we add big-endian UCS-2 sometimes, this code
+ will be more complicated. But it's OK for now.
+ */
+ bzero((char*) Ptr, offset);
+ memcpy(Ptr + offset, str, arg_length);
+ Ptr[aligned_length]=0;
+ /* str_length is always >= 0 as arg_length is != 0 */
+ str_length= aligned_length;
+ str_charset= cs;
+ return FALSE;
+}
+
- d=(uchar *)Ptr;
- de=d+new_length;
+bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
+ CHARSET_INFO *cs)
+{
+ /* How many bytes are in incomplete character */
+ uint32 offset= (arg_length % cs->mbminlen);
- for (str_length=new_length ; s < se && d < de ; )
+ if (!offset) /* All characters are complete, just copy */
{
- if ((cnvres=from->cset->mb_wc(from,&wc,s,se)) > 0 )
- {
- s+=cnvres;
- }
- else if (cnvres==MY_CS_ILSEQ)
- {
- s++;
- wc='?';
- }
- else
- break;
+ set(str, arg_length, cs);
+ return FALSE;
+ }
+ return copy_aligned(str, arg_length, offset, cs);
+}
-outp:
- if((cnvres=to->cset->wc_mb(to,wc,d,de)) >0 )
- {
- d+=cnvres;
- }
- else if (cnvres==MY_CS_ILUNI && wc!='?')
- {
- wc='?';
- goto outp;
- }
- else
- break;
+ /* Copy with charset convertion */
+
+bool String::copy(const char *str, uint32 arg_length,
+ CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
+{
+ uint32 offset;
+ if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
+ {
+ *errors= 0;
+ return copy(str, arg_length, to_cs);
+ }
+ if ((from_cs == &my_charset_bin) && offset)
+ {
+ *errors= 0;
+ return copy_aligned(str, arg_length, offset, to_cs);
}
- Ptr[new_length]=0;
- length((uint32) (d-(uchar *)Ptr));
- str_charset=to;
+ uint32 new_length= to_cs->mbmaxlen*arg_length;
+ if (alloc(new_length))
+ return TRUE;
+ str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
+ str, arg_length, from_cs, errors);
+ str_charset=to_cs;
return FALSE;
}
+
+/*
+ Set a string to the value of a latin1-string, keeping the original charset
+
+ SYNOPSIS
+ copy_or_set()
+ str String of a simple charset (latin1)
+ arg_length Length of string
+
+ IMPLEMENTATION
+ If string object is of a simple character set, set it to point to the
+ given string.
+ If not, make a copy and convert it to the new character set.
+
+ RETURN
+ 0 ok
+ 1 Could not allocate result buffer
+
+*/
+
+bool String::set_ascii(const char *str, uint32 arg_length)
+{
+ if (str_charset->mbminlen == 1)
+ {
+ set(str, arg_length, str_charset);
+ return 0;
+ }
+ uint dummy_errors;
+ return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
+}
+
+
/* This is used by mysql.cc */
bool String::fill(uint32 max_length,char fill_char)
@@ -320,11 +422,34 @@ bool String::append(const String &s)
return FALSE;
}
+
+/*
+ Append an ASCII string to the a string of the current character set
+*/
+
bool String::append(const char *s,uint32 arg_length)
{
- if (!arg_length) // Default argument
- if (!(arg_length= (uint32) strlen(s)))
- return FALSE;
+ if (!arg_length)
+ return FALSE;
+
+ /*
+ For an ASCII incompatible string, e.g. UCS-2, we need to convert
+ */
+ if (str_charset->mbminlen > 1)
+ {
+ uint32 add_length=arg_length * str_charset->mbmaxlen;
+ uint dummy_errors;
+ if (realloc(str_length+ add_length))
+ return TRUE;
+ str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
+ s, arg_length, &my_charset_latin1,
+ &dummy_errors);
+ return FALSE;
+ }
+
+ /*
+ For an ASCII compatinble string we can just append.
+ */
if (realloc(str_length+arg_length))
return TRUE;
memcpy(Ptr+str_length,s,arg_length);
@@ -332,6 +457,46 @@ bool String::append(const char *s,uint32 arg_length)
return FALSE;
}
+
+/*
+ Append a 0-terminated ASCII string
+*/
+
+bool String::append(const char *s)
+{
+ return append(s, strlen(s));
+}
+
+
+/*
+ Append a string in the given charset to the string
+ with character set recoding
+*/
+
+bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs)
+{
+ uint32 dummy_offset;
+
+ if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
+ {
+ uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
+ uint dummy_errors;
+ if (realloc(str_length + add_length))
+ return TRUE;
+ str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
+ s, arg_length, cs, &dummy_errors);
+ }
+ else
+ {
+ if (realloc(str_length + arg_length))
+ return TRUE;
+ memcpy(Ptr + str_length, s, arg_length);
+ str_length+= arg_length;
+ }
+ return FALSE;
+}
+
+
#ifdef TO_BE_REMOVED
bool String::append(FILE* file, uint32 arg_length, myf my_flags)
{
@@ -360,48 +525,33 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
return FALSE;
}
-uint32 String::numchars()
+bool String::append_with_prefill(const char *s,uint32 arg_length,
+ uint32 full_length, char fill_char)
{
-#ifdef USE_MB
- register uint32 n=0,mblen;
- register const char *mbstr=Ptr;
- register const char *end=mbstr+str_length;
- if (use_mb(str_charset))
+ int t_length= arg_length > full_length ? arg_length : full_length;
+
+ if (realloc(str_length + t_length))
+ return TRUE;
+ t_length= full_length - arg_length;
+ if (t_length > 0)
{
- while (mbstr < end) {
- if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
- else ++mbstr;
- ++n;
- }
- return n;
+ bfill(Ptr+str_length, t_length, fill_char);
+ str_length=str_length + t_length;
}
- else
-#endif
- return str_length;
+ append(s, arg_length);
+ return FALSE;
+}
+
+uint32 String::numchars()
+{
+ return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
}
int String::charpos(int i,uint32 offset)
{
-#ifdef USE_MB
- register uint32 mblen;
- register const char *mbstr=Ptr+offset;
- register const char *end=Ptr+str_length;
- if (use_mb(str_charset))
- {
- if (i<=0) return i;
- while (i && mbstr < end) {
- if ((mblen=my_ismbchar(str_charset, mbstr,end))) mbstr+=mblen;
- else ++mbstr;
- --i;
- }
- if ( INT_MAX32-i <= (int) (mbstr-Ptr-offset))
- return INT_MAX32;
- else
- return (int) ((mbstr-Ptr-offset)+i);
- }
- else
-#endif
+ if (i <= 0)
return i;
+ return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
}
int String::strstr(const String &s,uint32 offset)
@@ -432,40 +582,6 @@ skip:
}
/*
- Search after a string without regarding to case
- This needs to be replaced when we have character sets per string
-*/
-
-int String::strstr_case(const String &s,uint32 offset)
-{
- if (s.length()+offset <= str_length)
- {
- if (!s.length())
- return ((int) offset); // Empty string is always found
-
- register const char *str = Ptr+offset;
- register const char *search=s.ptr();
- const char *end=Ptr+str_length-s.length()+1;
- const char *search_end=s.ptr()+s.length();
-skip:
- while (str != end)
- {
- if (str_charset->sort_order[*str++] == str_charset->sort_order[*search])
- {
- register char *i,*j;
- i=(char*) str; j=(char*) search+1;
- while (j != search_end)
- if (str_charset->sort_order[*i++] !=
- str_charset->sort_order[*j++])
- goto skip;
- return (int) (str-Ptr) -1;
- }
- }
- }
- return -1;
-}
-
-/*
** Search string from end. Offset is offset to the end of string
*/
@@ -504,14 +620,20 @@ skip:
bool String::replace(uint32 offset,uint32 arg_length,const String &to)
{
- long diff = (long) to.length()-(long) arg_length;
+ return replace(offset,arg_length,to.ptr(),to.length());
+}
+
+bool String::replace(uint32 offset,uint32 arg_length,
+ const char *to,uint32 length)
+{
+ long diff = (long) length-(long) arg_length;
if (offset+arg_length <= str_length)
{
if (diff < 0)
{
- if (to.length())
- memcpy(Ptr+offset,to.ptr(),to.length());
- bmove(Ptr+offset+to.length(),Ptr+offset+arg_length,
+ if (length)
+ memcpy(Ptr+offset,to,length);
+ bmove(Ptr+offset+length,Ptr+offset+arg_length,
str_length-offset-arg_length);
}
else
@@ -523,14 +645,15 @@ bool String::replace(uint32 offset,uint32 arg_length,const String &to)
bmove_upp(Ptr+str_length+diff,Ptr+str_length,
str_length-offset-arg_length);
}
- if (to.length())
- memcpy(Ptr+offset,to.ptr(),to.length());
+ if (length)
+ memcpy(Ptr+offset,to,length);
}
str_length+=(uint32) diff;
}
return FALSE;
}
+
// added by Holyfoot for "geometry" needs
int String::reserve(uint32 space_needed, uint32 grow_by)
{
@@ -542,9 +665,8 @@ int String::reserve(uint32 space_needed, uint32 grow_by)
return FALSE;
}
-void String::qs_append(const char *str)
+void String::qs_append(const char *str, uint32 len)
{
- int len = (int)strlen(str);
memcpy(Ptr + str_length, str, len + 1);
str_length += len;
}
@@ -552,8 +674,7 @@ void String::qs_append(const char *str)
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
- sprintf(buff,"%.14g", d);
- str_length += (int)strlen(buff);
+ str_length+= my_sprintf(buff, (buff, "%.14g", d));
}
void String::qs_append(double *d)
@@ -563,90 +684,70 @@ void String::qs_append(double *d)
qs_append(ld);
}
-void String::qs_append(const char &c)
+void String::qs_append(int i)
{
- Ptr[str_length] = c;
- str_length += sizeof(c);
+ char *buff= Ptr + str_length;
+ char *end= int10_to_str(i, buff, -10);
+ str_length+= (int) (end-buff);
}
-
-int sortcmp(const String *x,const String *y)
+void String::qs_append(uint i)
{
- const char *s= x->ptr();
- const char *t= y->ptr();
- uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
-
- if (use_strnxfrm(x->str_charset))
- {
-#ifndef CMP_ENDSPACE
- while (x_len && my_isspace(x->str_charset,s[x_len-1]))
- x_len--;
- while (y_len && my_isspace(x->str_charset,t[y_len-1]))
- y_len--;
-#endif
- return my_strnncoll(x->str_charset,
- (unsigned char *)s,x_len,(unsigned char *)t,y_len);
- }
- else
- {
- x_len-=len; // For easy end space test
- y_len-=len;
- if (x->str_charset->sort_order)
- {
- while (len--)
- {
- if (x->str_charset->sort_order[(uchar) *s++] !=
- x->str_charset->sort_order[(uchar) *t++])
- return ((int) x->str_charset->sort_order[(uchar) s[-1]] -
- (int) x->str_charset->sort_order[(uchar) t[-1]]);
- }
- }
- else
- {
- while (len--)
- {
- if (*s++ != *t++)
- return ((int) s[-1] - (int) t[-1]);
- }
- }
-#ifndef CMP_ENDSPACE
- /* Don't compare end space in strings */
- {
- if (y_len)
- {
- const char *end=t+y_len;
- for (; t != end ; t++)
- if (!my_isspace(x->str_charset,*t))
- return -1;
- }
- else
- {
- const char *end=s+x_len;
- for (; s != end ; s++)
- if (!my_isspace(x->str_charset,*s))
- return 1;
- }
- return 0;
- }
-#else
- return (int) (x_len-y_len);
-#endif /* CMP_ENDSPACE */
- }
+ char *buff= Ptr + str_length;
+ char *end= int10_to_str(i, buff, 10);
+ str_length+= (int) (end-buff);
}
+/*
+ Compare strings according to collation, without end space.
+
+ SYNOPSIS
+ sortcmp()
+ s First string
+ t Second string
+ cs Collation
+
+ NOTE:
+ Normally this is case sensitive comparison
-int stringcmp(const String *x,const String *y)
+ RETURN
+ < 0 s < t
+ 0 s == t
+ > 0 s > t
+*/
+
+
+int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
{
- const char *s= x->ptr();
- const char *t= y->ptr();
- uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
+ return cs->coll->strnncollsp(cs,
+ (unsigned char *) s->ptr(),s->length(),
+ (unsigned char *) t->ptr(),t->length(), 0);
+}
- while (len--)
- {
- if (*s++ != *t++)
- return ((int) (uchar) s[-1] - (int) (uchar) t[-1]);
- }
- return (int) (x_len-y_len);
+
+/*
+ Compare strings byte by byte. End spaces are also compared.
+
+ SYNOPSIS
+ stringcmp()
+ s First string
+ t Second string
+
+ NOTE:
+ Strings are compared as a stream of unsigned chars
+
+ RETURN
+ < 0 s < t
+ 0 s == t
+ > 0 s > t
+*/
+
+
+int stringcmp(const String *s,const String *t)
+{
+ uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
+ int cmp= memcmp(s->ptr(), t->ptr(), len);
+ return (cmp) ? cmp : (int) (s_len - t_len);
}
@@ -668,4 +769,124 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
}
+/****************************************************************************
+ Help functions
+****************************************************************************/
+/*
+ copy a string from one character set to another
+
+ SYNOPSIS
+ copy_and_convert()
+ to Store result here
+ to_cs Character set of result string
+ from Copy from here
+ from_length Length of from string
+ from_cs From character set
+
+ NOTES
+ 'to' must be big enough as form_length * to_cs->mbmaxlen
+
+ RETURN
+ length of bytes copied to 'to'
+*/
+
+
+uint32
+copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length, CHARSET_INFO *from_cs,
+ uint *errors)
+{
+ int cnvres;
+ my_wc_t wc;
+ const uchar *from_end= (const uchar*) from+from_length;
+ char *to_start= to;
+ uchar *to_end= (uchar*) to+to_length;
+ int (*mb_wc)(struct charset_info_st *, my_wc_t *, const uchar *,
+ const uchar *) = from_cs->cset->mb_wc;
+ int (*wc_mb)(struct charset_info_st *, my_wc_t, uchar *s, uchar *e)=
+ to_cs->cset->wc_mb;
+ uint error_count= 0;
+
+ while (1)
+ {
+ if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
+ from_end)) > 0)
+ from+= cnvres;
+ else if (cnvres == MY_CS_ILSEQ)
+ {
+ error_count++;
+ from++;
+ wc= '?';
+ }
+ else
+ break; // Impossible char.
+
+outp:
+ if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
+ to+= cnvres;
+ else if (cnvres == MY_CS_ILUNI && wc != '?')
+ {
+ error_count++;
+ wc= '?';
+ goto outp;
+ }
+ else
+ break;
+ }
+ *errors= error_count;
+ return (uint32) (to - to_start);
+}
+
+
+void String::print(String *str)
+{
+ char *st= (char*)Ptr, *end= st+str_length;
+ for (; st < end; st++)
+ {
+ uchar c= *st;
+ switch (c)
+ {
+ case '\\':
+ str->append("\\\\", 2);
+ break;
+ case '\0':
+ str->append("\\0", 2);
+ break;
+ case '\'':
+ str->append("\\'", 2);
+ break;
+ case '\n':
+ str->append("\\n", 2);
+ break;
+ case '\r':
+ str->append("\\r", 2);
+ break;
+ case 26: //Ctrl-Z
+ str->append("\\z", 2);
+ break;
+ default:
+ str->append(c);
+ }
+ }
+}
+
+
+/*
+ Exchange state of this object and argument.
+
+ SYNOPSIS
+ String::swap()
+
+ RETURN
+ Target string will contain state of this object and vice versa.
+*/
+
+void String::swap(String &s)
+{
+ swap_variables(char *, Ptr, s.Ptr);
+ swap_variables(uint32, str_length, s.str_length);
+ swap_variables(uint32, Alloced_length, s.Alloced_length);
+ swap_variables(bool, alloced, s.alloced);
+ swap_variables(CHARSET_INFO*, str_charset, s.str_charset);
+}
diff --git a/client/sql_string.h b/client/sql_string.h
index fd6d3ef59d9..e284301b214 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h
@@ -25,9 +25,11 @@
#endif
class String;
-int sortcmp(const String *a,const String *b);
-int stringcmp(const String *a,const String *b);
+int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
+uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length,
+ CHARSET_INFO *from_cs, uint *errors);
class String
{
@@ -39,12 +41,12 @@ public:
String()
{
Ptr=0; str_length=Alloced_length=0; alloced=0;
- str_charset= &my_charset_latin1;
+ str_charset= &my_charset_bin;
}
String(uint32 length_arg)
{
alloced=0; Alloced_length=0; (void) real_alloc(length_arg);
- str_charset= &my_charset_latin1;
+ str_charset= &my_charset_bin;
}
String(const char *str, CHARSET_INFO *cs)
{
@@ -67,12 +69,15 @@ public:
Alloced_length=str.Alloced_length; alloced=0;
str_charset=str.str_charset;
}
- static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); }
- static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */
- { sql_element_free(ptr_arg); }
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
+ static void operator delete(void *ptr_arg,size_t size)
+ { TRASH(ptr_arg, size); }
+ static void operator delete(void *ptr_arg, MEM_ROOT *mem_root)
+ { /* never called */ }
~String() { free(); }
- inline void set_charset(CHARSET_INFO *charset) { str_charset=charset; }
+ inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; }
inline CHARSET_INFO *charset() const { return str_charset; }
inline uint32 length() const { return str_length;}
inline uint32 alloced_length() const { return Alloced_length;}
@@ -103,6 +108,7 @@ public:
void set(String &str,uint32 offset,uint32 arg_length)
{
+ DBUG_ASSERT(&str != this);
free();
Ptr=(char*) str.ptr()+offset; str_length=arg_length; alloced=0;
if (str.Alloced_length)
@@ -123,6 +129,7 @@ public:
Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0;
str_charset=cs;
}
+ bool set_ascii(const char *str, uint32 arg_length);
inline void set_quick(char *str,uint32 arg_length, CHARSET_INFO *cs)
{
if (!alloced)
@@ -134,6 +141,34 @@ public:
bool set(longlong num, CHARSET_INFO *cs);
bool set(ulonglong num, CHARSET_INFO *cs);
bool set(double num,uint decimals, CHARSET_INFO *cs);
+
+ /*
+ PMG 2004.11.12
+ This is a method that works the same as perl's "chop". It simply
+ drops the last character of a string. This is useful in the case
+ of the federated storage handler where I'm building a unknown
+ number, list of values and fields to be used in a sql insert
+ statement to be run on the remote server, and have a comma after each.
+ When the list is complete, I "chop" off the trailing comma
+
+ ex.
+ String stringobj;
+ stringobj.append("VALUES ('foo', 'fi', 'fo',");
+ stringobj.chop();
+ stringobj.append(")");
+
+ In this case, the value of string was:
+
+ VALUES ('foo', 'fi', 'fo',
+ VALUES ('foo', 'fi', 'fo'
+ VALUES ('foo', 'fi', 'fo')
+
+ */
+ inline void chop()
+ {
+ Ptr[str_length--]= '\0';
+ }
+
inline void free()
{
if (alloced)
@@ -175,6 +210,11 @@ public:
{
if (&s != this)
{
+ /*
+ It is forbidden to do assignments like
+ some_string = substring_of_that_string
+ */
+ DBUG_ASSERT(!s.uses_buffer_owned_by(this));
free();
Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length;
alloced=0;
@@ -185,13 +225,24 @@ public:
bool copy(); // Alloc string if not alloced
bool copy(const String &s); // Allocate new string
bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string
- bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto);
+ static bool needs_conversion(uint32 arg_length,
+ CHARSET_INFO *cs_from, CHARSET_INFO *cs_to,
+ uint32 *offset);
+ bool copy_aligned(const char *s, uint32 arg_length, uint32 offset,
+ CHARSET_INFO *cs);
+ bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
+ bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
+ CHARSET_INFO *csto, uint *errors);
bool append(const String &s);
- bool append(const char *s,uint32 arg_length=0);
+ bool append(const char *s);
+ bool append(const char *s,uint32 arg_length);
+ bool append(const char *s,uint32 arg_length, CHARSET_INFO *cs);
bool append(IO_CACHE* file, uint32 arg_length);
+ bool append_with_prefill(const char *s, uint32 arg_length,
+ uint32 full_length, char fill_char);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
- int strstr_case(const String &s,uint32 offset=0);
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
+ bool replace(uint32 offset,uint32 arg_length,const char *to,uint32 length);
bool replace(uint32 offset,uint32 arg_length,const String &to);
inline bool append(char chr)
{
@@ -209,9 +260,7 @@ public:
}
bool fill(uint32 max_length,char fill);
void strip_sp();
- inline void caseup() { my_caseup(str_charset,Ptr,str_length); }
- inline void casedn() { my_casedn(str_charset,Ptr,str_length); }
- friend int sortcmp(const String *a,const String *b);
+ friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
friend int stringcmp(const String *a,const String *b);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
uint32 numchars();
@@ -228,11 +277,11 @@ public:
q_*** methods writes values of parameters itself
qs_*** methods writes string representation of value
*/
- void q_append(const char &c)
+ void q_append(const char c)
{
Ptr[str_length++] = c;
}
- void q_append(const uint32 &n)
+ void q_append(const uint32 n)
{
int4store(Ptr + str_length, n);
str_length += 4;
@@ -253,13 +302,53 @@ public:
str_length += data_len;
}
- void WriteAtPosition(int position, uint32 value)
+ void write_at_position(int position, uint32 value)
{
int4store(Ptr + position,value);
}
- void qs_append(const char *str);
+ void qs_append(const char *str, uint32 len);
void qs_append(double d);
void qs_append(double *d);
- void qs_append(const char &c);
+ inline void qs_append(const char c)
+ {
+ Ptr[str_length]= c;
+ str_length++;
+ }
+ void qs_append(int i);
+ void qs_append(uint i);
+
+ /* Inline (general) functions used by the protocol functions */
+
+ inline char *prep_append(uint32 arg_length, uint32 step_alloc)
+ {
+ uint32 new_length= arg_length + str_length;
+ if (new_length > Alloced_length)
+ {
+ if (realloc(new_length + step_alloc))
+ return 0;
+ }
+ uint32 old_length= str_length;
+ str_length+= arg_length;
+ return Ptr+ old_length; /* Area to use */
+ }
+
+ inline bool append(const char *s, uint32 arg_length, uint32 step_alloc)
+ {
+ uint32 new_length= arg_length + str_length;
+ if (new_length > Alloced_length && realloc(new_length + step_alloc))
+ return TRUE;
+ memcpy(Ptr+str_length, s, arg_length);
+ str_length+= arg_length;
+ return FALSE;
+ }
+ void print(String *print);
+
+ /* Swap two string objects. Efficient way to exchange data without memcpy. */
+ void swap(String &s);
+
+ inline bool uses_buffer_owned_by(const String *s) const
+ {
+ return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length);
+ }
};
diff --git a/cmd-line-utils/readline/INSTALL b/cmd-line-utils/readline/INSTALL
index adb27a9f222..cb4a06fb701 100644
--- a/cmd-line-utils/readline/INSTALL
+++ b/cmd-line-utils/readline/INSTALL
@@ -1,7 +1,7 @@
Basic Installation
==================
-These are installation instructions for Readline-4.3.
+These are installation instructions for Readline-5.0.
The simplest way to compile readline is:
diff --git a/cmd-line-utils/readline/Makefile.am b/cmd-line-utils/readline/Makefile.am
index 14d25ff62c0..f5e41b7e2e9 100644
--- a/cmd-line-utils/readline/Makefile.am
+++ b/cmd-line-utils/readline/Makefile.am
@@ -17,7 +17,8 @@ libreadline_a_SOURCES = readline.c funmap.c keymaps.c \
callback.c terminal.c xmalloc.c \
history.c histsearch.c histexpand.c \
histfile.c nls.c search.c \
- shell.c tilde.c misc.c text.c mbutil.c
+ shell.c tilde.c misc.c text.c mbutil.c \
+ compat.c savestring.c
pkginclude_HEADERS = readline.h chardefs.h keymaps.h \
history.h tilde.h rlmbutil.h rltypedefs.h rlprivate.h \
diff --git a/cmd-line-utils/readline/README b/cmd-line-utils/readline/README
index 7aa939452fb..ac4e3a767f9 100644
--- a/cmd-line-utils/readline/README
+++ b/cmd-line-utils/readline/README
@@ -1,7 +1,7 @@
Introduction
============
-This is the Gnu Readline library, version 4.3.
+This is the Gnu Readline library, version 5.0.
The Readline library provides a set of functions for use by applications
that allow users to edit command lines as they are typed in. Both
diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c
index 0e8efc5c636..17f61d1df08 100644
--- a/cmd-line-utils/readline/bind.c
+++ b/cmd-line-utils/readline/bind.c
@@ -19,8 +19,13 @@
is generally kept in a file called COPYING or LICENSE. If you do not
have a copy of the license, write to the Free Software Foundation,
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
#define READLINE_LIBRARY
+#if defined (__TANDEM)
+# include <floss.h>
+#endif
+
#include "config_readline.h"
#include <stdio.h>
@@ -146,6 +151,34 @@ rl_bind_key_in_map (key, function, map)
return (result);
}
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
+ now, this is always used to attempt to bind the arrow keys, hence the
+ check for rl_vi_movement_mode. */
+int
+rl_bind_key_if_unbound_in_map (key, default_func, kmap)
+ int key;
+ rl_command_func_t *default_func;
+ Keymap kmap;
+{
+ char keyseq[2];
+
+ keyseq[0] = (unsigned char)key;
+ keyseq[1] = '\0';
+ return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap));
+}
+
+int
+rl_bind_key_if_unbound (key, default_func)
+ int key;
+ rl_command_func_t *default_func;
+{
+ char keyseq[2];
+
+ keyseq[0] = (unsigned char)key;
+ keyseq[1] = '\0';
+ return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
+}
+
/* Make KEY do nothing in the currently selected keymap.
Returns non-zero in case of error. */
int
@@ -198,9 +231,30 @@ rl_unbind_command_in_map (command, map)
}
/* Bind the key sequence represented by the string KEYSEQ to
+ FUNCTION, starting in the current keymap. This makes new
+ keymaps as necessary. */
+int
+rl_bind_keyseq (keyseq, function)
+ const char *keyseq;
+ rl_command_func_t *function;
+{
+ return (rl_generic_bind (ISFUNC, keyseq, (char *)function, _rl_keymap));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
FUNCTION. This makes new keymaps as necessary. The initial
place to do bindings is in MAP. */
int
+rl_bind_keyseq_in_map (keyseq, function, map)
+ const char *keyseq;
+ rl_command_func_t *function;
+ Keymap map;
+{
+ return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
+}
+
+/* Backwards compatibility; equivalent to rl_bind_keyseq_in_map() */
+int
rl_set_key (keyseq, function, map)
const char *keyseq;
rl_command_func_t *function;
@@ -209,6 +263,40 @@ rl_set_key (keyseq, function, map)
return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
}
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
+ now, this is always used to attempt to bind the arrow keys, hence the
+ check for rl_vi_movement_mode. */
+int
+rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap)
+ const char *keyseq;
+ rl_command_func_t *default_func;
+ Keymap kmap;
+{
+ rl_command_func_t *func;
+
+ if (keyseq)
+ {
+ func = rl_function_of_keyseq (keyseq, kmap, (int *)NULL);
+#if defined (VI_MODE)
+ if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
+#else
+ if (!func || func == rl_do_lowercase_version)
+#endif
+ return (rl_bind_keyseq_in_map (keyseq, default_func, kmap));
+ else
+ return 1;
+ }
+ return 0;
+}
+
+int
+rl_bind_keyseq_if_unbound (keyseq, default_func)
+ const char *keyseq;
+ rl_command_func_t *default_func;
+{
+ return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
+}
+
/* Bind the key sequence represented by the string KEYSEQ to
the string of characters MACRO. This makes new keymaps as
necessary. The initial place to do bindings is in MAP. */
@@ -346,7 +434,7 @@ rl_translate_keyseq (seq, array, len)
{
register int i, c, l, temp;
- for (i = l = 0; (c = seq[i]); i++)
+ for (i = l = 0; c = seq[i]; i++)
{
if (c == '\\')
{
@@ -678,7 +766,7 @@ _rl_read_file (filename, sizep)
/* Re-read the current keybindings file. */
int
rl_re_read_init_file (count, ignore)
- int count __attribute__((unused)), ignore __attribute__((unused));
+ int count, ignore;
{
int r;
r = rl_read_init_file ((const char *)NULL);
@@ -900,7 +988,7 @@ parser_if (args)
/* Invert the current parser state if there is anything on the stack. */
static int
parser_else (args)
- char *args __attribute__((unused));
+ char *args;
{
register int i;
@@ -910,9 +998,15 @@ parser_else (args)
return 0;
}
+#if 0
/* Check the previous (n - 1) levels of the stack to make sure that
we haven't previously turned off parsing. */
for (i = 0; i < if_stack_depth - 1; i++)
+#else
+ /* Check the previous (n) levels of the stack to make sure that
+ we haven't previously turned off parsing. */
+ for (i = 0; i < if_stack_depth; i++)
+#endif
if (if_stack[i] == 1)
return 0;
@@ -925,7 +1019,7 @@ parser_else (args)
_rl_parsing_conditionalized_out from the stack. */
static int
parser_endif (args)
- char *args __attribute__((unused));
+ char *args;
{
if (if_stack_depth)
_rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
@@ -1048,7 +1142,7 @@ rl_parse_and_bind (string)
{
int passc = 0;
- for (i = 1; (c = string[i]); i++)
+ for (i = 1; c = string[i]; i++)
{
if (passc)
{
@@ -1124,7 +1218,7 @@ rl_parse_and_bind (string)
{
int delimiter = string[i++], passc;
- for (passc = 0; (c = string[i]); i++)
+ for (passc = 0; c = string[i]; i++)
{
if (passc)
{
@@ -1159,7 +1253,7 @@ rl_parse_and_bind (string)
}
/* If this is a new-style key-binding, then do the binding with
- rl_set_key (). Otherwise, let the older code deal with it. */
+ rl_bind_keyseq (). Otherwise, let the older code deal with it. */
if (*string == '"')
{
char *seq;
@@ -1198,7 +1292,7 @@ rl_parse_and_bind (string)
rl_macro_bind (seq, &funname[1], _rl_keymap);
}
else
- rl_set_key (seq, rl_named_function (funname), _rl_keymap);
+ rl_bind_keyseq (seq, rl_named_function (funname));
free (seq);
return 0;
@@ -1279,10 +1373,11 @@ static struct {
{ "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL },
{ "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
{ "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
+ { "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 },
#if defined (VISIBLE_STATS)
{ "visible-stats", &rl_visible_stats, 0 },
#endif /* VISIBLE_STATS */
- { (char *)NULL, (int *)NULL, 0 }
+ { (char *)NULL, (int *)NULL }
};
static int
@@ -1351,7 +1446,7 @@ static struct {
{ "editing-mode", V_STRING, sv_editmode },
{ "isearch-terminators", V_STRING, sv_isrchterm },
{ "keymap", V_STRING, sv_keymap },
- { (char *)NULL, 0, 0 }
+ { (char *)NULL, 0 }
};
static int
@@ -1626,8 +1721,7 @@ rl_set_keymap_from_edit_mode ()
#endif /* VI_MODE */
}
-
-const char *
+char *
rl_get_keymap_name_from_edit_mode ()
{
if (rl_editing_mode == emacs_mode)
@@ -1637,7 +1731,7 @@ rl_get_keymap_name_from_edit_mode ()
return "vi";
#endif /* VI_MODE */
else
- return "nope";
+ return "none";
}
/* **************************************************************** */
@@ -1649,7 +1743,7 @@ rl_get_keymap_name_from_edit_mode ()
/* Each of the following functions produces information about the
state of keybindings and functions known to Readline. The info
is always printed to rl_outstream, and in such a way that it can
- be read back in (i.e., passed to rl_parse_and_bind (). */
+ be read back in (i.e., passed to rl_parse_and_bind ()). */
/* Print the names of functions known to Readline. */
void
@@ -1872,7 +1966,7 @@ rl_function_dumper (print_readably)
fprintf (rl_outstream, "\n");
- for (i = 0; (name = names[i]); i++)
+ for (i = 0; name = names[i]; i++)
{
rl_command_func_t *function;
char **invokers;
@@ -1932,7 +2026,7 @@ rl_function_dumper (print_readably)
the output in such a way that it can be read back in. */
int
rl_dump_functions (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
@@ -2012,7 +2106,7 @@ rl_macro_dumper (print_readably)
int
rl_dump_macros (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
@@ -2102,7 +2196,7 @@ rl_variable_dumper (print_readably)
the output in such a way that it can be read back in. */
int
rl_dump_variables (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
@@ -2111,28 +2205,6 @@ rl_dump_variables (count, key)
return (0);
}
-/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
- now, this is always used to attempt to bind the arrow keys, hence the
- check for rl_vi_movement_mode. */
-void
-_rl_bind_if_unbound (keyseq, default_func)
- const char *keyseq;
- rl_command_func_t *default_func;
-{
- rl_command_func_t *func;
-
- if (keyseq)
- {
- func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL);
-#if defined (VI_MODE)
- if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
-#else
- if (!func || func == rl_do_lowercase_version)
-#endif
- rl_set_key (keyseq, default_func, _rl_keymap);
- }
-}
-
/* Return non-zero if any members of ARRAY are a substring in STRING. */
static int
substring_member_of_array (string, array)
diff --git a/cmd-line-utils/readline/callback.c b/cmd-line-utils/readline/callback.c
index 737f483eed0..0807f137b92 100644
--- a/cmd-line-utils/readline/callback.c
+++ b/cmd-line-utils/readline/callback.c
@@ -129,7 +129,7 @@ rl_callback_read_char ()
if (in_handler == 0 && rl_linefunc)
_rl_callback_newline ();
}
- if (rl_pending_input)
+ if (rl_pending_input || _rl_pushed_input_available ())
eof = readline_internal_char ();
else
break;
diff --git a/cmd-line-utils/readline/chardefs.h b/cmd-line-utils/readline/chardefs.h
index a537be220b0..cb04c982343 100644
--- a/cmd-line-utils/readline/chardefs.h
+++ b/cmd-line-utils/readline/chardefs.h
@@ -77,7 +77,11 @@
# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
#endif
-#define NON_NEGATIVE(c) ((unsigned char)(c) == (c))
+#if defined (CTYPE_NON_ASCII)
+# define NON_NEGATIVE(c) 1
+#else
+# define NON_NEGATIVE(c) ((unsigned char)(c) == (c))
+#endif
/* Some systems define these; we want our definitions. */
#undef ISPRINT
diff --git a/cmd-line-utils/readline/compat.c b/cmd-line-utils/readline/compat.c
new file mode 100644
index 00000000000..e4fbc322cee
--- /dev/null
+++ b/cmd-line-utils/readline/compat.c
@@ -0,0 +1,111 @@
+/* compat.c -- backwards compatibility functions. */
+
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline Library 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, or
+ (at your option) any later version.
+
+ The GNU Readline Library 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#include "config_readline.h"
+
+#include <stdio.h>
+
+#include "rlstdc.h"
+#include "rltypedefs.h"
+
+extern void rl_free_undo_list PARAMS((void));
+extern int rl_maybe_save_line PARAMS((void));
+extern int rl_maybe_unsave_line PARAMS((void));
+extern int rl_maybe_replace_line PARAMS((void));
+
+extern int rl_crlf PARAMS((void));
+extern int rl_ding PARAMS((void));
+extern int rl_alphabetic PARAMS((int));
+
+extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *));
+extern char *rl_username_completion_function PARAMS((const char *, int));
+extern char *rl_filename_completion_function PARAMS((const char *, int));
+
+/* Provide backwards-compatible entry points for old function names. */
+
+void
+free_undo_list ()
+{
+ rl_free_undo_list ();
+}
+
+int
+maybe_replace_line ()
+{
+ return rl_maybe_replace_line ();
+}
+
+int
+maybe_save_line ()
+{
+ return rl_maybe_save_line ();
+}
+
+int
+maybe_unsave_line ()
+{
+ return rl_maybe_unsave_line ();
+}
+
+int
+ding ()
+{
+ return rl_ding ();
+}
+
+int
+crlf ()
+{
+ return rl_crlf ();
+}
+
+int
+alphabetic (c)
+ int c;
+{
+ return rl_alphabetic (c);
+}
+
+char **
+completion_matches (s, f)
+ const char *s;
+ rl_compentry_func_t *f;
+{
+ return rl_completion_matches (s, f);
+}
+
+char *
+username_completion_function (s, i)
+ const char *s;
+ int i;
+{
+ return rl_username_completion_function (s, i);
+}
+
+char *
+filename_completion_function (s, i)
+ const char *s;
+ int i;
+{
+ return rl_filename_completion_function (s, i);
+}
diff --git a/cmd-line-utils/readline/complete.c b/cmd-line-utils/readline/complete.c
index 749875e0e5e..2196c66a54c 100644
--- a/cmd-line-utils/readline/complete.c
+++ b/cmd-line-utils/readline/complete.c
@@ -1,6 +1,6 @@
/* complete.c -- filename completion for readline. */
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -26,7 +26,7 @@
#include <sys/types.h>
#include <fcntl.h>
#if defined (HAVE_SYS_FILE_H)
-#include <sys/file.h>
+# include <sys/file.h>
#endif
#if defined (HAVE_UNISTD_H)
@@ -97,12 +97,16 @@ rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)N
static int stat_char PARAMS((char *));
#endif
+static int path_isdir PARAMS((const char *));
+
static char *rl_quote_filename PARAMS((char *, int, char *));
static void set_completion_defaults PARAMS((int));
static int get_y_or_n PARAMS((int));
static int _rl_internal_pager PARAMS((int));
static char *printable_part PARAMS((char *));
+static int fnwidth PARAMS((const char *));
+static int fnprint PARAMS((const char *));
static int print_filename PARAMS((char *, char *));
static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
@@ -128,6 +132,10 @@ static char *make_quoted_replacement PARAMS((char *, int, char *));
/* If non-zero, non-unique completions always show the list of matches. */
int _rl_complete_show_all = 0;
+/* If non-zero, non-unique completions show the list of matches, unless it
+ is not possible to do partial completion and modify the line. */
+int _rl_complete_show_unmodified = 0;
+
/* If non-zero, completed directory names have a slash appended. */
int _rl_complete_mark_directories = 1;
@@ -212,7 +220,12 @@ const char *rl_basic_quote_characters = "\"'";
/* The list of characters that signal a break between words for
rl_complete_internal. The default list is the contents of
rl_basic_word_break_characters. */
-const char *rl_completer_word_break_characters = (const char *)NULL;
+/*const*/ char *rl_completer_word_break_characters = (/*const*/ char *)NULL;
+
+/* Hook function to allow an application to set the completion word
+ break characters before readline breaks up the line. Allows
+ position-dependent word break characters. */
+rl_cpvfunc_t *rl_completion_word_break_hook = (rl_cpvfunc_t *)NULL;
/* List of characters which can be used to quote a substring of the line.
Completion occurs on the entire substring, and within the substring
@@ -280,6 +293,19 @@ int rl_completion_suppress_append = 0;
default is a space. */
int rl_completion_append_character = ' ';
+/* If non-zero, the completion functions don't append any closing quote.
+ This is set to 0 by rl_complete_internal and may be changed by an
+ application-specific completion function. */
+int rl_completion_suppress_quote = 0;
+
+/* Set to any quote character readline thinks it finds before any application
+ completion function is called. */
+int rl_completion_quote_character;
+
+/* Set to a non-zero value if readline found quoting anywhere in the word to
+ be completed; set before any application completion function is called. */
+int rl_completion_found_quote;
+
/* If non-zero, a slash will be appended to completed filenames that are
symbolic links to directory names, subject to the value of the
mark-directories variable (which is user-settable). This exists so
@@ -318,6 +344,8 @@ rl_complete (ignore, invoking_key)
return (rl_complete_internal ('?'));
else if (_rl_complete_show_all)
return (rl_complete_internal ('!'));
+ else if (_rl_complete_show_unmodified)
+ return (rl_complete_internal ('@'));
else
return (rl_complete_internal (TAB));
}
@@ -325,14 +353,14 @@ rl_complete (ignore, invoking_key)
/* List the possible completions. See description of rl_complete (). */
int
rl_possible_completions (ignore, invoking_key)
- int ignore __attribute__((unused)), invoking_key __attribute__((unused));
+ int ignore, invoking_key;
{
return (rl_complete_internal ('?'));
}
int
rl_insert_completions (ignore, invoking_key)
- int ignore __attribute__((unused)), invoking_key __attribute__((unused));
+ int ignore, invoking_key;
{
return (rl_complete_internal ('*'));
}
@@ -350,6 +378,8 @@ rl_completion_mode (cfunc)
return '?';
else if (_rl_complete_show_all)
return '!';
+ else if (_rl_complete_show_unmodified)
+ return '@';
else
return TAB;
}
@@ -370,7 +400,7 @@ set_completion_defaults (what_to_do)
rl_filename_completion_desired = 0;
rl_filename_quoting_desired = 1;
rl_completion_type = what_to_do;
- rl_completion_suppress_append = 0;
+ rl_completion_suppress_append = rl_completion_suppress_quote = 0;
/* The completion entry function may optionally change this. */
rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;
@@ -421,6 +451,15 @@ _rl_internal_pager (lines)
return 0;
}
+static int
+path_isdir (filename)
+ const char *filename;
+{
+ struct stat finfo;
+
+ return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode));
+}
+
#if defined (VISIBLE_STATS)
/* Return the character which best describes FILENAME.
`@' for symbolic links
@@ -518,53 +557,140 @@ printable_part (pathname)
return ++temp;
}
+/* Compute width of STRING when displayed on screen by print_filename */
+static int
+fnwidth (string)
+ const char *string;
+{
+ int width, pos;
+#if defined (HANDLE_MULTIBYTE)
+ mbstate_t ps;
+ int left, w;
+ size_t clen;
+ wchar_t wc;
+
+ left = strlen (string) + 1;
+ memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
+ width = pos = 0;
+ while (string[pos])
+ {
+ if (CTRL_CHAR (*string) || *string == RUBOUT)
+ {
+ width += 2;
+ pos++;
+ }
+ else
+ {
+#if defined (HANDLE_MULTIBYTE)
+ clen = mbrtowc (&wc, string + pos, left - pos, &ps);
+ if (MB_INVALIDCH (clen))
+ {
+ width++;
+ pos++;
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else if (MB_NULLWCH (clen))
+ break;
+ else
+ {
+ pos += clen;
+ w = wcwidth (wc);
+ width += (w >= 0) ? w : 1;
+ }
+#else
+ width++;
+ pos++;
+#endif
+ }
+ }
+
+ return width;
+}
+
+static int
+fnprint (to_print)
+ const char *to_print;
+{
+ int printed_len;
+ const char *s;
+#if defined (HANDLE_MULTIBYTE)
+ mbstate_t ps;
+ const char *end;
+ size_t tlen;
+
+ end = to_print + strlen (to_print) + 1;
+ memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
+ printed_len = 0;
+ s = to_print;
+ while (*s)
+ {
+ if (CTRL_CHAR (*s))
+ {
+ putc ('^', rl_outstream);
+ putc (UNCTRL (*s), rl_outstream);
+ printed_len += 2;
+ s++;
+#if defined (HANDLE_MULTIBYTE)
+ memset (&ps, 0, sizeof (mbstate_t));
+#endif
+ }
+ else if (*s == RUBOUT)
+ {
+ putc ('^', rl_outstream);
+ putc ('?', rl_outstream);
+ printed_len += 2;
+ s++;
+#if defined (HANDLE_MULTIBYTE)
+ memset (&ps, 0, sizeof (mbstate_t));
+#endif
+ }
+ else
+ {
+#if defined (HANDLE_MULTIBYTE)
+ tlen = mbrlen (s, end - s, &ps);
+ if (MB_INVALIDCH (tlen))
+ {
+ tlen = 1;
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else if (MB_NULLWCH (tlen))
+ break;
+ fwrite (s, 1, tlen, rl_outstream);
+ s += tlen;
+#else
+ putc (*s, rl_outstream);
+ s++;
+#endif
+ printed_len++;
+ }
+ }
+
+ return printed_len;
+}
+
/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
are using it, check for and output a single character for `special'
filenames. Return the number of characters we output. */
-#define PUTX(c) \
- do { \
- if (CTRL_CHAR (c)) \
- { \
- putc ('^', rl_outstream); \
- putc (UNCTRL (c), rl_outstream); \
- printed_len += 2; \
- } \
- else if (c == RUBOUT) \
- { \
- putc ('^', rl_outstream); \
- putc ('?', rl_outstream); \
- printed_len += 2; \
- } \
- else \
- { \
- putc (c, rl_outstream); \
- printed_len++; \
- } \
- } while (0)
-
static int
print_filename (to_print, full_pathname)
char *to_print, *full_pathname;
{
- int printed_len = 0;
-#if !defined (VISIBLE_STATS)
- char *s;
-
- for (s = to_print; *s; s++)
- {
- PUTX (*s);
- }
-#else
+ int printed_len, extension_char, slen, tlen;
char *s, c, *new_full_pathname;
- int extension_char, slen, tlen;
- for (s = to_print; *s; s++)
- {
- PUTX (*s);
- }
+ extension_char = 0;
+ printed_len = fnprint (to_print);
- if (rl_filename_completion_desired && rl_visible_stats)
+#if defined (VISIBLE_STATS)
+ if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories))
+#else
+ if (rl_filename_completion_desired && _rl_complete_mark_directories)
+#endif
{
/* If to_print != full_pathname, to_print is the basename of the
path passed. In this case, we try to expand the directory
@@ -591,7 +717,13 @@ print_filename (to_print, full_pathname)
new_full_pathname[slen] = '/';
strcpy (new_full_pathname + slen + 1, to_print);
- extension_char = stat_char (new_full_pathname);
+#if defined (VISIBLE_STATS)
+ if (rl_visible_stats)
+ extension_char = stat_char (new_full_pathname);
+ else
+#endif
+ if (path_isdir (new_full_pathname))
+ extension_char = '/';
free (new_full_pathname);
to_print[-1] = c;
@@ -599,7 +731,13 @@ print_filename (to_print, full_pathname)
else
{
s = tilde_expand (full_pathname);
- extension_char = stat_char (s);
+#if defined (VISIBLE_STATS)
+ if (rl_visible_stats)
+ extension_char = stat_char (s);
+ else
+#endif
+ if (path_isdir (s))
+ extension_char = '/';
}
free (s);
@@ -609,14 +747,14 @@ print_filename (to_print, full_pathname)
printed_len++;
}
}
-#endif /* VISIBLE_STATS */
+
return printed_len;
}
static char *
rl_quote_filename (s, rtype, qcp)
char *s;
- int rtype __attribute__((unused));
+ int rtype;
char *qcp;
{
char *r;
@@ -649,19 +787,32 @@ _rl_find_completion_word (fp, dp)
int *fp, *dp;
{
int scan, end, found_quote, delimiter, pass_next, isbrk;
- char quote_char;
+ char quote_char, *brkchars;
end = rl_point;
found_quote = delimiter = 0;
quote_char = '\0';
+ brkchars = 0;
+ if (rl_completion_word_break_hook)
+ brkchars = (*rl_completion_word_break_hook) ();
+ if (brkchars == 0)
+ brkchars = rl_completer_word_break_characters;
+
if (rl_completer_quote_characters)
{
/* We have a list of characters which can be used in pairs to
quote substrings for the completer. Try to find the start
of an unclosed quoted substring. */
/* FOUND_QUOTE is set so we know what kind of quotes we found. */
+#if defined (HANDLE_MULTIBYTE)
+ for (scan = pass_next = 0; scan < end;
+ scan = ((MB_CUR_MAX == 1 || rl_byte_oriented)
+ ? (scan + 1)
+ : _rl_find_next_mbchar (rl_line_buffer, scan, 1, MB_FIND_ANY)))
+#else
for (scan = pass_next = 0; scan < end; scan++)
+#endif
{
if (pass_next)
{
@@ -719,7 +870,7 @@ _rl_find_completion_word (fp, dp)
{
scan = rl_line_buffer[rl_point];
- if (strchr (rl_completer_word_break_characters, scan) == 0)
+ if (strchr (brkchars, scan) == 0)
continue;
/* Call the application-specific function to tell us whether
@@ -747,9 +898,9 @@ _rl_find_completion_word (fp, dp)
if (rl_char_is_quoted_p)
isbrk = (found_quote == 0 ||
(*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) &&
- strchr (rl_completer_word_break_characters, scan) != 0;
+ strchr (brkchars, scan) != 0;
else
- isbrk = strchr (rl_completer_word_break_characters, scan) != 0;
+ isbrk = strchr (brkchars, scan) != 0;
if (isbrk)
{
@@ -784,6 +935,9 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
{
char **matches, *temp;
+ rl_completion_found_quote = found_quote;
+ rl_completion_quote_character = quote_char;
+
/* If the user wants to TRY to complete, but then wants to give
up and use the default completion function, they set the
variable rl_attempted_completion_function. */
@@ -887,6 +1041,7 @@ compute_lcd_of_matches (match_list, matches, text)
{
register int i, c1, c2, si;
int low; /* Count of max-matched characters. */
+ char *dtext; /* dequoted TEXT, if needed */
#if defined (HANDLE_MULTIBYTE)
int v;
mbstate_t ps1, ps2;
@@ -978,6 +1133,26 @@ compute_lcd_of_matches (match_list, matches, text)
the user typed in the face of multiple matches differing in case. */
if (_rl_completion_case_fold)
{
+ /* We're making an assumption here:
+ IF we're completing filenames AND
+ the application has defined a filename dequoting function AND
+ we found a quote character AND
+ the application has requested filename quoting
+ THEN
+ we assume that TEXT was dequoted before checking against
+ the file system and needs to be dequoted here before we
+ check against the list of matches
+ FI */
+ dtext = (char *)NULL;
+ if (rl_filename_completion_desired &&
+ rl_filename_dequoting_function &&
+ rl_completion_found_quote &&
+ rl_filename_quoting_desired)
+ {
+ dtext = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
+ text = dtext;
+ }
+
/* sort the list to get consistent answers. */
qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
@@ -997,6 +1172,8 @@ compute_lcd_of_matches (match_list, matches, text)
else
/* otherwise, just use the text the user typed. */
strncpy (match_list[0], text, low);
+
+ FREE (dtext);
}
else
strncpy (match_list[0], match_list[1], low);
@@ -1201,7 +1378,7 @@ display_matches (matches)
for (max = 0, i = 1; matches[i]; i++)
{
temp = printable_part (matches[i]);
- len = strlen (temp);
+ len = fnwidth (temp);
if (len > max)
max = len;
@@ -1336,7 +1513,8 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
struct stat finfo;
temp_string_index = 0;
- if (quote_char && rl_point && rl_line_buffer[rl_point - 1] != quote_char)
+ if (quote_char && rl_point && rl_completion_suppress_quote == 0 &&
+ rl_line_buffer[rl_point - 1] != quote_char)
temp_string[temp_string_index++] = quote_char;
if (delimiter)
@@ -1447,7 +1625,9 @@ _rl_free_match_list (matches)
TAB means do standard completion.
`*' means insert all of the possible completions.
`!' means to do standard completion, and list all possible completions if
- there is more than one. */
+ there is more than one.
+ `@' means to do standard completion, and list all possible completions if
+ there is more than one and partial completion is not possible. */
int
rl_complete_internal (what_to_do)
int what_to_do;
@@ -1466,7 +1646,6 @@ rl_complete_internal (what_to_do)
our_func = rl_completion_entry_function
? rl_completion_entry_function
: rl_filename_completion_function;
-
/* We now look backwards for the start of a filename/variable word. */
end = rl_point;
found_quote = delimiter = 0;
@@ -1514,6 +1693,7 @@ rl_complete_internal (what_to_do)
{
case TAB:
case '!':
+ case '@':
/* Insert the first match with proper quoting. */
if (*matches[0])
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
@@ -1533,6 +1713,12 @@ rl_complete_internal (what_to_do)
display_matches (matches);
break;
}
+ else if (what_to_do == '@')
+ {
+ if (nontrivial_lcd == 0)
+ display_matches (matches);
+ break;
+ }
else if (rl_editing_mode != vi_mode)
rl_ding (); /* There are other matches remaining. */
}
@@ -1610,7 +1796,7 @@ rl_completion_matches (text, entry_function)
match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
match_list[1] = (char *)NULL;
- while ((string = (*entry_function) (text, matches)))
+ while (string = (*entry_function) (text, matches))
{
if (matches + 1 == match_list_size)
match_list = (char **)xrealloc
@@ -1660,7 +1846,7 @@ rl_username_completion_function (text, state)
setpwent ();
}
- while ((entry = getpwent ()))
+ while (entry = getpwent ())
{
/* Null usernames should result in all users as possible completions. */
if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
@@ -1897,7 +2083,7 @@ rl_filename_completion_function (text, state)
ring the bell, and reset the counter to zero. */
int
rl_menu_complete (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
rl_compentry_func_t *our_func;
int matching_filenames, found_quote;
diff --git a/cmd-line-utils/readline/configure.in b/cmd-line-utils/readline/configure.in
index bc78f8a0f60..31e17606024 100644
--- a/cmd-line-utils/readline/configure.in
+++ b/cmd-line-utils/readline/configure.in
@@ -4,9 +4,9 @@ dnl
dnl report bugs to chet@po.cwru.edu
dnl
dnl Process this file with autoconf to produce a configure script.
-AC_REVISION([for Readline 4.3, version 2.45, from autoconf version] AC_ACVERSION)
+AC_REVISION([for Readline 5.0, version 2.52, from autoconf version] AC_ACVERSION)
-AC_INIT(readline, 4.3, bug-readline@gnu.org)
+AC_INIT(readline, 5.0-rc1, bug-readline@gnu.org)
dnl make sure we are using a recent autoconf version
AC_PREREQ(2.50)
@@ -16,7 +16,7 @@ AC_CONFIG_AUX_DIR(./support)
AC_CONFIG_HEADERS(config.h)
dnl update the value of RL_READLINE_VERSION in readline.h when this changes
-LIBVERSION=4.3
+LIBVERSION=5.0
AC_CANONICAL_HOST
@@ -31,12 +31,18 @@ if test "$opt_curses" = "yes"; then
fi
dnl option parsing for optional features
+opt_multibyte=yes
opt_static_libs=yes
opt_shared_libs=yes
+AC_ARG_ENABLE(multibyte, AC_HELP_STRING([--enable-multibyte], [enable multibyte characters if OS supports them]), opt_multibyte=$enableval)
AC_ARG_ENABLE(shared, AC_HELP_STRING([--enable-shared], [build shared libraries [[default=YES]]]), opt_shared_libs=$enableval)
AC_ARG_ENABLE(static, AC_HELP_STRING([--enable-static], [build static libraries [[default=YES]]]), opt_static_libs=$enableval)
+if test $opt_multibyte = no; then
+AC_DEFINE(NO_MULTIBYTE_SUPPORT)
+fi
+
echo ""
echo "Beginning configuration for readline-$LIBVERSION for ${host_cpu}-${host_vendor}-${host_os}"
echo ""
@@ -72,6 +78,8 @@ AC_TYPE_SIGNAL
AC_TYPE_SIZE_T
AC_CHECK_TYPE(ssize_t, int)
+AC_HEADER_STDC
+
AC_HEADER_STAT
AC_HEADER_DIRENT
@@ -90,6 +98,7 @@ BASH_SYS_REINSTALL_SIGHANDLERS
BASH_FUNC_POSIX_SETJMP
BASH_FUNC_LSTAT
BASH_FUNC_STRCOLL
+BASH_FUNC_CTYPE_NONASCII
BASH_CHECK_GETPW_FUNCS
diff --git a/cmd-line-utils/readline/display.c b/cmd-line-utils/readline/display.c
index 7c393f1c8a5..cab76c0da81 100644
--- a/cmd-line-utils/readline/display.c
+++ b/cmd-line-utils/readline/display.c
@@ -1,6 +1,6 @@
/* display.c -- readline redisplay facility. */
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -119,7 +119,7 @@ int _rl_suppress_redisplay = 0;
/* The stuff that gets printed out before the actual text of the line.
This is usually pointing to rl_prompt. */
-const char *rl_display_prompt = (char *)NULL;
+char *rl_display_prompt = (char *)NULL;
/* Pseudo-global variables declared here. */
/* The visible cursor position. If you print some text, adjust this. */
@@ -176,12 +176,15 @@ static int prompt_invis_chars_first_line;
static int prompt_last_screen_line;
+static int prompt_physical_chars;
+
/* Expand the prompt string S and return the number of visible
characters in *LP, if LP is not null. This is currently more-or-less
a placeholder for expansion. LIP, if non-null is a place to store the
index of the last invisible character in the returned string. NIFLP,
if non-zero, is a place to store the number of invisible characters in
- the first prompt line. */
+ the first prompt line. The previous are used as byte counts -- indexes
+ into a character buffer. */
/* Current implementation:
\001 (^A) start non-visible characters
@@ -191,19 +194,25 @@ static int prompt_last_screen_line;
\002 are assumed to be `visible'. */
static char *
-expand_prompt (pmt, lp, lip, niflp)
+expand_prompt (pmt, lp, lip, niflp, vlp)
char *pmt;
- int *lp, *lip, *niflp;
+ int *lp, *lip, *niflp, *vlp;
{
char *r, *ret, *p;
- int l, rl, last, ignoring, ninvis, invfl;
+ int l, rl, last, ignoring, ninvis, invfl, ind, pind, physchars;
/* Short-circuit if we can. */
- if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
+ if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
{
r = savestring (pmt);
if (lp)
*lp = strlen (r);
+ if (lip)
+ *lip = 0;
+ if (niflp)
+ *niflp = 0;
+ if (vlp)
+ *vlp = lp ? *lp : strlen (r);
return r;
}
@@ -212,7 +221,7 @@ expand_prompt (pmt, lp, lip, niflp)
invfl = 0; /* invisible chars in first line of prompt */
- for (rl = ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
+ for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
{
/* This code strips the invisible character string markers
RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
@@ -229,13 +238,35 @@ expand_prompt (pmt, lp, lip, niflp)
}
else
{
- *r++ = *p;
- if (!ignoring)
- rl++;
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ pind = p - pmt;
+ ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
+ l = ind - pind;
+ while (l--)
+ *r++ = *p++;
+ if (!ignoring)
+ rl += ind - pind;
+ else
+ ninvis += ind - pind;
+ p--; /* compensate for later increment */
+ }
else
- ninvis++;
- if (rl == _rl_screenwidth)
+#endif
+ {
+ *r++ = *p;
+ if (!ignoring)
+ rl++; /* visible length byte counter */
+ else
+ ninvis++; /* invisible chars byte counter */
+ }
+
+ if (rl >= _rl_screenwidth)
invfl = ninvis;
+
+ if (ignoring == 0)
+ physchars++;
}
}
@@ -249,6 +280,8 @@ expand_prompt (pmt, lp, lip, niflp)
*lip = last;
if (niflp)
*niflp = invfl;
+ if (vlp)
+ *vlp = physchars;
return ret;
}
@@ -260,7 +293,7 @@ _rl_strip_prompt (pmt)
{
char *ret;
- ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL);
+ ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
return ret;
}
@@ -304,7 +337,8 @@ rl_expand_prompt (prompt)
/* The prompt is only one logical line, though it might wrap. */
local_prompt = expand_prompt (prompt, &prompt_visible_length,
&prompt_last_invisible,
- &prompt_invis_chars_first_line);
+ &prompt_invis_chars_first_line,
+ &prompt_physical_chars);
local_prompt_prefix = (char *)0;
return (prompt_visible_length);
}
@@ -314,13 +348,15 @@ rl_expand_prompt (prompt)
t = ++p;
local_prompt = expand_prompt (p, &prompt_visible_length,
&prompt_last_invisible,
- &prompt_invis_chars_first_line);
+ (int *)NULL,
+ (int *)NULL);
c = *t; *t = '\0';
/* The portion of the prompt string up to and including the
final newline is now null-terminated. */
local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
(int *)NULL,
- &prompt_invis_chars_first_line);
+ &prompt_invis_chars_first_line,
+ &prompt_physical_chars);
*t = c;
return (prompt_prefix_length);
}
@@ -379,8 +415,8 @@ rl_redisplay ()
register int in, out, c, linenum, cursor_linenum;
register char *line;
int c_pos, inv_botlin, lb_botlin, lb_linenum;
- int newlines, lpos, temp;
- const char *prompt_this_line;
+ int newlines, lpos, temp, modmark;
+ char *prompt_this_line;
#if defined (HANDLE_MULTIBYTE)
wchar_t wc;
size_t wc_bytes;
@@ -409,10 +445,12 @@ rl_redisplay ()
/* Mark the line as modified or not. We only do this for history
lines. */
+ modmark = 0;
if (_rl_mark_modified_lines && current_history () && rl_undo_list)
{
line[out++] = '*';
line[out] = '\0';
+ modmark = 1;
}
/* If someone thought that the redisplay was handled, but the currently
@@ -466,7 +504,7 @@ rl_redisplay ()
}
}
- pmtlen = strlen (prompt_this_line);
+ prompt_physical_chars = pmtlen = strlen (prompt_this_line);
temp = pmtlen + out + 2;
if (temp >= line_size)
{
@@ -525,7 +563,12 @@ rl_redisplay ()
/* inv_lbreaks[i] is where line i starts in the buffer. */
inv_lbreaks[newlines = 0] = 0;
+#if 0
lpos = out - wrap_offset;
+#else
+ lpos = prompt_physical_chars + modmark;
+#endif
+
#if defined (HANDLE_MULTIBYTE)
memset (_rl_wrapped_line, 0, vis_lbsize);
#endif
@@ -544,15 +587,13 @@ rl_redisplay ()
prompt_invis_chars_first_line variable could be made into an array
saying how many invisible characters there are per line, but that's
probably too much work for the benefit gained. How many people have
- prompts that exceed two physical lines? */
+ prompts that exceed two physical lines?
+ Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
temp = ((newlines + 1) * _rl_screenwidth) +
-#if 0
- ((newlines == 0) ? prompt_invis_chars_first_line : 0) +
-#else
- ((newlines == 0 && local_prompt_prefix == 0) ? prompt_invis_chars_first_line : 0) +
-#endif
- ((newlines == 1) ? wrap_offset : 0);
-
+ ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
+ : ((newlines == 1) ? wrap_offset : 0))
+ : ((newlines == 0) ? wrap_offset :0));
+
inv_lbreaks[++newlines] = temp;
lpos -= _rl_screenwidth;
}
@@ -584,7 +625,7 @@ rl_redisplay ()
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
- if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2)
+ if (MB_INVALIDCH (wc_bytes))
{
/* Byte sequence is invalid or shortened. Assume that the
first byte represents a character. */
@@ -593,12 +634,12 @@ rl_redisplay ()
wc_width = 1;
memset (&ps, 0, sizeof (mbstate_t));
}
- else if (wc_bytes == (size_t)0)
+ else if (MB_NULLWCH (wc_bytes))
break; /* Found '\0' */
else
{
temp = wcwidth (wc);
- wc_width = (temp < 0) ? 1 : temp;
+ wc_width = (temp >= 0) ? temp : 1;
}
}
#endif
@@ -788,7 +829,7 @@ rl_redisplay ()
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
-#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? (char*)"" : VIS_CHARS(line)
+#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
/* For each line in the buffer, do the updating display. */
@@ -829,7 +870,7 @@ rl_redisplay ()
_rl_move_vert (linenum);
_rl_move_cursor_relative (0, tt);
_rl_clear_to_eol
- ((linenum == _rl_vis_botlin) ? (int)strlen (tt) : _rl_screenwidth);
+ ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
}
}
_rl_vis_botlin = inv_botlin;
@@ -865,7 +906,7 @@ rl_redisplay ()
#endif
_rl_output_some_chars (local_prompt, nleft);
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- _rl_last_c_pos = _rl_col_width(local_prompt, 0, nleft);
+ _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft);
else
_rl_last_c_pos = nleft;
}
@@ -1067,12 +1108,12 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
memset (&ps, 0, sizeof (mbstate_t));
ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
- if (ret == (size_t)-1 || ret == (size_t)-2)
+ if (MB_INVALIDCH (ret))
{
tempwidth = 1;
ret = 1;
}
- else if (ret == 0)
+ else if (MB_NULLWCH (ret))
tempwidth = 0;
else
tempwidth = wcwidth (wc);
@@ -1089,7 +1130,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
if (ret != 0 && bytes != 0)
{
- if (ret == (size_t)-1 || ret == (size_t)-2)
+ if (MB_INVALIDCH (ret))
memmove (old+bytes, old+1, strlen (old+1));
else
memmove (old+bytes, old+ret, strlen (old+ret));
@@ -1124,18 +1165,37 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
- memset (&ps_new, 0, sizeof(mbstate_t));
- memset (&ps_old, 0, sizeof(mbstate_t));
-
- new_offset = old_offset = 0;
- for (ofd = old, nfd = new;
- (ofd - old < omax) && *ofd &&
- _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
+ /* See if the old line is a subset of the new line, so that the
+ only change is adding characters. */
+ temp = (omax < nmax) ? omax : nmax;
+ if (memcmp (old, new, temp) == 0)
{
- old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
- new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
- ofd = old + old_offset;
- nfd = new + new_offset;
+ ofd = old + temp;
+ nfd = new + temp;
+ }
+ else
+ {
+ memset (&ps_new, 0, sizeof(mbstate_t));
+ memset (&ps_old, 0, sizeof(mbstate_t));
+
+ if (omax == nmax && STREQN (new, old, omax))
+ {
+ ofd = old + omax;
+ nfd = new + nmax;
+ }
+ else
+ {
+ new_offset = old_offset = 0;
+ for (ofd = old, nfd = new;
+ (ofd - old < omax) && *ofd &&
+ _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
+ {
+ old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
+ new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
+ ofd = old + old_offset;
+ nfd = new + new_offset;
+ }
+ }
}
}
else
@@ -1167,8 +1227,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
memset (&ps_old, 0, sizeof (mbstate_t));
memset (&ps_new, 0, sizeof (mbstate_t));
+#if 0
+ /* On advice from jir@yamato.ibm.com */
_rl_adjust_point (old, ols - old, &ps_old);
_rl_adjust_point (new, nls - new, &ps_new);
+#endif
if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
break;
@@ -1322,7 +1385,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
insert_some_chars (nfd, lendiff, col_lendiff);
_rl_last_c_pos += col_lendiff;
}
- else if (*ols == 0)
+ else if (*ols == 0 && lendiff > 0)
{
/* At the end of a line the characters do not have to
be "inserted". They can just be placed on the screen. */
@@ -1345,10 +1408,14 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
if ((temp - lendiff) > 0)
{
_rl_output_some_chars (nfd + lendiff, temp - lendiff);
-#if 0
- _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff) - col_lendiff;
-#else
+#if 1
+ /* XXX -- this bears closer inspection. Fixes a redisplay bug
+ reported against bash-3.0-alpha by Andreas Schwab involving
+ multibyte characters and prompt strings with invisible
+ characters, but was previously disabled. */
_rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
+#else
+ _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
#endif
}
}
@@ -1424,12 +1491,13 @@ rl_on_new_line ()
/* Tell the update routines that we have moved onto a new line with the
prompt already displayed. Code originally from the version of readline
- distributed with CLISP. */
+ distributed with CLISP. rl_expand_prompt must have already been called
+ (explicitly or implicitly). This still doesn't work exactly right. */
int
rl_on_new_line_with_prompt ()
{
int prompt_size, i, l, real_screenwidth, newlines;
- char *prompt_last_line;
+ char *prompt_last_line, *lprompt;
/* Initialize visible_line and invisible_line to ensure that they can hold
the already-displayed prompt. */
@@ -1438,8 +1506,9 @@ rl_on_new_line_with_prompt ()
/* Make sure the line structures hold the already-displayed prompt for
redisplay. */
- strcpy (visible_line, rl_prompt);
- strcpy (invisible_line, rl_prompt);
+ lprompt = local_prompt ? local_prompt : rl_prompt;
+ strcpy (visible_line, lprompt);
+ strcpy (invisible_line, lprompt);
/* If the prompt contains newlines, take the last tail. */
prompt_last_line = strrchr (rl_prompt, '\n');
@@ -1474,6 +1543,8 @@ rl_on_new_line_with_prompt ()
vis_lbreaks[newlines] = l;
visible_wrap_offset = 0;
+ rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
+
return 0;
}
@@ -1508,8 +1579,15 @@ _rl_move_cursor_relative (new, data)
#if defined (HANDLE_MULTIBYTE)
/* If we have multibyte characters, NEW is indexed by the buffer point in
a multibyte string, but _rl_last_c_pos is the display position. In
- this case, NEW's display position is not obvious. */
- if ((MB_CUR_MAX == 1 || rl_byte_oriented ) && _rl_last_c_pos == new) return;
+ this case, NEW's display position is not obvious and must be
+ calculated. */
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ {
+ if (_rl_last_c_pos == new)
+ return;
+ }
+ else if (_rl_last_c_pos == _rl_col_width (data, 0, new))
+ return;
#else
if (_rl_last_c_pos == new) return;
#endif
@@ -1592,11 +1670,7 @@ _rl_move_cursor_relative (new, data)
#endif
{
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- tputs (_rl_term_cr, 1, _rl_output_character_function);
- for (i = 0; i < new; i++)
- putc (data[i], rl_outstream);
- }
+ _rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new));
else
_rl_backspace (_rl_last_c_pos - new);
}
@@ -1734,7 +1808,6 @@ rl_message (va_alist)
int
rl_message (format, arg1, arg2)
char *format;
- int arg1, arg2;
{
sprintf (msg_buf, format, arg1, arg2);
msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
@@ -1763,10 +1836,14 @@ rl_reset_line_state ()
return 0;
}
+/* These are getting numerous enough that it's time to create a struct. */
+
static char *saved_local_prompt;
static char *saved_local_prefix;
static int saved_last_invisible;
static int saved_visible_length;
+static int saved_invis_chars_first_line;
+static int saved_physical_chars;
void
rl_save_prompt ()
@@ -1775,9 +1852,12 @@ rl_save_prompt ()
saved_local_prefix = local_prompt_prefix;
saved_last_invisible = prompt_last_invisible;
saved_visible_length = prompt_visible_length;
+ saved_invis_chars_first_line = prompt_invis_chars_first_line;
+ saved_physical_chars = prompt_physical_chars;
local_prompt = local_prompt_prefix = (char *)0;
prompt_last_invisible = prompt_visible_length = 0;
+ prompt_invis_chars_first_line = prompt_physical_chars = 0;
}
void
@@ -1790,6 +1870,8 @@ rl_restore_prompt ()
local_prompt_prefix = saved_local_prefix;
prompt_last_invisible = saved_last_invisible;
prompt_visible_length = saved_visible_length;
+ prompt_invis_chars_first_line = saved_invis_chars_first_line;
+ prompt_physical_chars = saved_physical_chars;
}
char *
@@ -1822,6 +1904,7 @@ _rl_make_prompt_for_search (pchar)
prompt_last_invisible = saved_last_invisible;
prompt_visible_length = saved_visible_length + 1;
}
+
return pmt;
}
@@ -1997,9 +2080,8 @@ static void
redraw_prompt (t)
char *t;
{
- const char *oldp;
- char *oldl, *oldlprefix;
- int oldlen, oldlast, oldplen, oldninvis;
+ char *oldp, *oldl, *oldlprefix;
+ int oldlen, oldlast, oldplen, oldninvis, oldphyschars;
/* Geez, I should make this a struct. */
oldp = rl_display_prompt;
@@ -2009,11 +2091,13 @@ redraw_prompt (t)
oldplen = prompt_prefix_length;
oldlast = prompt_last_invisible;
oldninvis = prompt_invis_chars_first_line;
+ oldphyschars = prompt_physical_chars;
rl_display_prompt = t;
local_prompt = expand_prompt (t, &prompt_visible_length,
&prompt_last_invisible,
- &prompt_invis_chars_first_line);
+ &prompt_invis_chars_first_line,
+ &prompt_physical_chars);
local_prompt_prefix = (char *)NULL;
rl_forced_update_display ();
@@ -2024,6 +2108,7 @@ redraw_prompt (t)
prompt_prefix_length = oldplen;
prompt_last_invisible = oldlast;
prompt_invis_chars_first_line = oldninvis;
+ prompt_physical_chars = oldphyschars;
}
/* Redisplay the current line after a SIGWINCH is received. */
@@ -2133,7 +2218,7 @@ _rl_col_width (str, start, end)
while (point < start)
{
tmp = mbrlen (str + point, max, &ps);
- if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
+ if (MB_INVALIDCH ((size_t)tmp))
{
/* In this case, the bytes are invalid or too short to compose a
multibyte character, so we assume that the first byte represents
@@ -2145,8 +2230,8 @@ _rl_col_width (str, start, end)
effect of mbstate is undefined. */
memset (&ps, 0, sizeof (mbstate_t));
}
- else if (tmp == 0)
- break; /* Found '\0' */
+ else if (MB_NULLWCH (tmp))
+ break; /* Found '\0' */
else
{
point += tmp;
@@ -2162,7 +2247,7 @@ _rl_col_width (str, start, end)
while (point < end)
{
tmp = mbrtowc (&wc, str + point, max, &ps);
- if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
+ if (MB_INVALIDCH ((size_t)tmp))
{
/* In this case, the bytes are invalid or too short to compose a
multibyte character, so we assume that the first byte represents
@@ -2177,8 +2262,8 @@ _rl_col_width (str, start, end)
effect of mbstate is undefined. */
memset (&ps, 0, sizeof (mbstate_t));
}
- else if (tmp == 0)
- break; /* Found '\0' */
+ else if (MB_NULLWCH (tmp))
+ break; /* Found '\0' */
else
{
point += tmp;
@@ -2193,4 +2278,3 @@ _rl_col_width (str, start, end)
return width;
}
#endif /* HANDLE_MULTIBYTE */
-
diff --git a/cmd-line-utils/readline/funmap.c b/cmd-line-utils/readline/funmap.c
index 53fd22754ab..d56ffb9fadc 100644
--- a/cmd-line-utils/readline/funmap.c
+++ b/cmd-line-utils/readline/funmap.c
@@ -129,6 +129,7 @@ static FUNMAP default_funmap[] = {
{ "tty-status", rl_tty_status },
{ "undo", rl_undo_command },
{ "universal-argument", rl_universal_argument },
+ { "unix-filename-rubout", rl_unix_filename_rubout },
{ "unix-line-discard", rl_unix_line_discard },
{ "unix-word-rubout", rl_unix_word_rubout },
{ "upcase-word", rl_upcase_word },
diff --git a/cmd-line-utils/readline/histexpand.c b/cmd-line-utils/readline/histexpand.c
index eed8d5a365e..47f97e9a6f7 100644
--- a/cmd-line-utils/readline/histexpand.c
+++ b/cmd-line-utils/readline/histexpand.c
@@ -1,6 +1,6 @@
/* histexpand.c -- history expansion. */
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2004 Free Software Foundation, Inc.
This file contains the GNU History Library (the Library), a set of
routines for managing the text of previously typed lines.
@@ -50,6 +50,8 @@
#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
#define HISTORY_QUOTE_CHARACTERS "\"'`"
+#define slashify_in_quotes "\\`\"$"
+
typedef int _hist_search_func_t PARAMS((const char *, int));
extern int rl_byte_oriented; /* declared in mbutil.c */
@@ -63,6 +65,8 @@ static int subst_rhs_len;
static char *get_history_word_specifier PARAMS((char *, char *, int *));
static char *history_find_word PARAMS((char *, int));
+static int history_tokenize_word PARAMS((const char *, int));
+static char *history_substring PARAMS((const char *, int, int));
static char *quote_breaks PARAMS((char *));
@@ -83,14 +87,14 @@ char history_comment_char = '\0';
/* The list of characters which inhibit the expansion of text if found
immediately following history_expansion_char. */
-const char *history_no_expand_chars = " \t\n\r=";
+char *history_no_expand_chars = " \t\n\r=";
/* If set to a non-zero value, single quotes inhibit history expansion.
The default is 0. */
int history_quotes_inhibit_expansion = 0;
/* Used to split words by history_tokenize_internal. */
-const char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
+char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
/* If set, this points to a function that is called to verify that a
particular history expansion should be performed. */
@@ -199,7 +203,7 @@ get_history_event (string, caller_index, delimiting_quote)
}
/* Only a closing `?' or a newline delimit a substring search string. */
- for (local_index = i; (c = string[i]); i++)
+ for (local_index = i; c = string[i]; i++)
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
@@ -209,8 +213,8 @@ get_history_event (string, caller_index, delimiting_quote)
memset (&ps, 0, sizeof (mbstate_t));
/* These produce warnings because we're passing a const string to a
function that takes a non-const string. */
- _rl_adjust_point (string, i, &ps);
- if ((v = _rl_get_char_len (string + i, &ps)) > 1)
+ _rl_adjust_point ((char *)string, i, &ps);
+ if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1)
{
i += v - 1;
continue;
@@ -515,7 +519,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
char *current_line; /* for !# */
{
int i, n, starting_index;
- int substitute_globally, want_quotes, print_only;
+ int substitute_globally, subst_bywords, want_quotes, print_only;
char *event, *temp, *result, *tstr, *t, c, *word_spec;
int result_len;
#if defined (HANDLE_MULTIBYTE)
@@ -597,19 +601,25 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
FREE (word_spec);
/* Perhaps there are other modifiers involved. Do what they say. */
- want_quotes = substitute_globally = print_only = 0;
+ want_quotes = substitute_globally = subst_bywords = print_only = 0;
starting_index = i;
while (string[i] == ':')
{
c = string[i + 1];
- if (c == 'g')
+ if (c == 'g' || c == 'a')
{
substitute_globally = 1;
i++;
c = string[i + 1];
}
+ else if (c == 'G')
+ {
+ subst_bywords = 1;
+ i++;
+ c = string[i + 1];
+ }
switch (c)
{
@@ -681,7 +691,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
case 's':
{
char *new_event;
- int delimiter, failed, si, l_temp;
+ int delimiter, failed, si, l_temp, ws, we;
if (c == 's')
{
@@ -758,33 +768,67 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
}
/* Find the first occurrence of THIS in TEMP. */
- si = 0;
+ /* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three
+ cases to consider:
+
+ 1. substitute_globally == subst_bywords == 0
+ 2. substitute_globally == 1 && subst_bywords == 0
+ 3. substitute_globally == 0 && subst_bywords == 1
+
+ In the first case, we substitute for the first occurrence only.
+ In the second case, we substitute for every occurrence.
+ In the third case, we tokenize into words and substitute the
+ first occurrence of each word. */
+
+ si = we = 0;
for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
- if (STREQN (temp+si, subst_lhs, subst_lhs_len))
- {
- int len = subst_rhs_len - subst_lhs_len + l_temp;
- new_event = (char *)xmalloc (1 + len);
- strncpy (new_event, temp, si);
- strncpy (new_event + si, subst_rhs, subst_rhs_len);
- strncpy (new_event + si + subst_rhs_len,
- temp + si + subst_lhs_len,
- l_temp - (si + subst_lhs_len));
- new_event[len] = '\0';
- free (temp);
- temp = new_event;
-
- failed = 0;
-
- if (substitute_globally)
- {
- si += subst_rhs_len;
- l_temp = strlen (temp);
- substitute_globally++;
- continue;
- }
- else
- break;
- }
+ {
+ /* First skip whitespace and find word boundaries if
+ we're past the end of the word boundary we found
+ the last time. */
+ if (subst_bywords && si > we)
+ {
+ for (; temp[si] && whitespace (temp[si]); si++)
+ ;
+ ws = si;
+ we = history_tokenize_word (temp, si);
+ }
+
+ if (STREQN (temp+si, subst_lhs, subst_lhs_len))
+ {
+ int len = subst_rhs_len - subst_lhs_len + l_temp;
+ new_event = (char *)xmalloc (1 + len);
+ strncpy (new_event, temp, si);
+ strncpy (new_event + si, subst_rhs, subst_rhs_len);
+ strncpy (new_event + si + subst_rhs_len,
+ temp + si + subst_lhs_len,
+ l_temp - (si + subst_lhs_len));
+ new_event[len] = '\0';
+ free (temp);
+ temp = new_event;
+
+ failed = 0;
+
+ if (substitute_globally)
+ {
+ /* Reported to fix a bug that causes it to skip every
+ other match when matching a single character. Was
+ si += subst_rhs_len previously. */
+ si += subst_rhs_len - 1;
+ l_temp = strlen (temp);
+ substitute_globally++;
+ continue;
+ }
+ else if (subst_bywords)
+ {
+ si = we;
+ l_temp = strlen (temp);
+ continue;
+ }
+ else
+ break;
+ }
+ }
if (substitute_globally > 1)
{
@@ -877,7 +921,7 @@ history_expand (hstring, output)
char **output;
{
register int j;
- int i, r, l, passc, cc, modified, eindex, only_printing;
+ int i, r, l, passc, cc, modified, eindex, only_printing, dquote;
char *string;
/* The output string, and its length. */
@@ -940,7 +984,7 @@ history_expand (hstring, output)
/* `!' followed by one of the characters in history_no_expand_chars
is NOT an expansion. */
- for (i = 0; string[i]; i++)
+ for (i = dquote = 0; string[i]; i++)
{
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -982,9 +1026,19 @@ history_expand (hstring, output)
else
break;
}
- /* XXX - at some point, might want to extend this to handle
- double quotes as well. */
- else if (history_quotes_inhibit_expansion && string[i] == '\'')
+ /* Shell-like quoting: allow backslashes to quote double quotes
+ inside a double-quoted string. */
+ else if (dquote && string[i] == '\\' && cc == '"')
+ i++;
+ /* More shell-like quoting: if we're paying attention to single
+ quotes and letting them quote the history expansion character,
+ then we need to pay attention to double quotes, because single
+ quotes are not special inside double-quoted strings. */
+ else if (history_quotes_inhibit_expansion && string[i] == '"')
+ {
+ dquote = 1 - dquote;
+ }
+ else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'')
{
/* If this is bash, single quotes inhibit history expansion. */
i++;
@@ -997,6 +1051,7 @@ history_expand (hstring, output)
if (cc == '\'' || cc == history_expansion_char)
i++;
}
+
}
if (string[i] != history_expansion_char)
@@ -1008,7 +1063,7 @@ history_expand (hstring, output)
}
/* Extract and perform the substitution. */
- for (passc = i = j = 0; i < l; i++)
+ for (passc = dquote = i = j = 0; i < l; i++)
{
int tchar = string[i];
@@ -1059,11 +1114,16 @@ history_expand (hstring, output)
ADD_CHAR (tchar);
break;
+ case '"':
+ dquote = 1 - dquote;
+ ADD_CHAR (tchar);
+ break;
+
case '\'':
{
/* If history_quotes_inhibit_expansion is set, single quotes
inhibit history expansion. */
- if (history_quotes_inhibit_expansion)
+ if (dquote == 0 && history_quotes_inhibit_expansion)
{
int quote, slen;
@@ -1158,7 +1218,9 @@ history_expand (hstring, output)
if (only_printing)
{
+#if 0
add_history (result);
+#endif
return (2);
}
@@ -1221,7 +1283,10 @@ get_history_word_specifier (spec, from, caller_index)
if (spec[i] == '-')
first = 0;
else if (spec[i] == '^')
- first = 1;
+ {
+ first = 1;
+ i++;
+ }
else if (_rl_digit_p (spec[i]) && expecting_word_spec)
{
for (first = 0; _rl_digit_p (spec[i]); i++)
@@ -1336,7 +1401,103 @@ history_arg_extract (first, last, string)
return (result);
}
-#define slashify_in_quotes "\\`\"$"
+static int
+history_tokenize_word (string, ind)
+ const char *string;
+ int ind;
+{
+ register int i;
+ int delimiter;
+
+ i = ind;
+ delimiter = 0;
+
+ if (member (string[i], "()\n"))
+ {
+ i++;
+ return i;
+ }
+
+ if (member (string[i], "<>;&|$"))
+ {
+ int peek = string[i + 1];
+
+ if (peek == string[i] && peek != '$')
+ {
+ if (peek == '<' && string[i + 2] == '-')
+ i++;
+ i += 2;
+ return i;
+ }
+ else
+ {
+ if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
+ (peek == '>' && string[i] == '&') ||
+ (peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
+ (peek == '(' && string[i] == '$')) /* ) */
+ {
+ i += 2;
+ return i;
+ }
+ }
+
+ if (string[i] != '$')
+ {
+ i++;
+ return i;
+ }
+ }
+
+ /* Get word from string + i; */
+
+ if (member (string[i], HISTORY_QUOTE_CHARACTERS))
+ delimiter = string[i++];
+
+ for (; string[i]; i++)
+ {
+ if (string[i] == '\\' && string[i + 1] == '\n')
+ {
+ i++;
+ continue;
+ }
+
+ if (string[i] == '\\' && delimiter != '\'' &&
+ (delimiter != '"' || member (string[i], slashify_in_quotes)))
+ {
+ i++;
+ continue;
+ }
+
+ if (delimiter && string[i] == delimiter)
+ {
+ delimiter = 0;
+ continue;
+ }
+
+ if (!delimiter && (member (string[i], history_word_delimiters)))
+ break;
+
+ if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
+ delimiter = string[i];
+ }
+
+ return i;
+}
+
+static char *
+history_substring (string, start, end)
+ const char *string;
+ int start, end;
+{
+ register int len;
+ register char *result;
+
+ len = end - start;
+ result = (char *)xmalloc (len + 1);
+ strncpy (result, string + start, len);
+ result[len] = '\0';
+ return result;
+}
/* Parse STRING into tokens and return an array of strings. If WIND is
not -1 and INDP is not null, we also want the word surrounding index
@@ -1349,7 +1510,6 @@ history_tokenize_internal (string, wind, indp)
{
char **result;
register int i, start, result_index, size;
- int len, delimiter;
/* If we're searching for a string that's not part of a word (e.g., " "),
make sure we set *INDP to a reasonable value. */
@@ -1360,8 +1520,6 @@ history_tokenize_internal (string, wind, indp)
exactly where the shell would split them. */
for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
{
- delimiter = 0;
-
/* Skip leading whitespace. */
for (; string[i] && whitespace (string[i]); i++)
;
@@ -1369,88 +1527,30 @@ history_tokenize_internal (string, wind, indp)
return (result);
start = i;
-
- if (member (string[i], "()\n"))
- {
- i++;
- goto got_token;
- }
- if (member (string[i], "<>;&|$"))
- {
- int peek = string[i + 1];
+ i = history_tokenize_word (string, start);
- if (peek == string[i] && peek != '$')
- {
- if (peek == '<' && string[i + 2] == '-')
- i++;
- i += 2;
- goto got_token;
- }
- else
- {
- if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
- ((peek == '>') && (string[i] == '&')) ||
- ((peek == '(') && (string[i] == '$')))
- {
- i += 2;
- goto got_token;
- }
- }
- if (string[i] != '$')
- {
- i++;
- goto got_token;
- }
- }
-
- /* Get word from string + i; */
-
- if (member (string[i], HISTORY_QUOTE_CHARACTERS))
- delimiter = string[i++];
-
- for (; string[i]; i++)
+ /* If we have a non-whitespace delimiter character (which would not be
+ skipped by the loop above), use it and any adjacent delimiters to
+ make a separate field. Any adjacent white space will be skipped the
+ next time through the loop. */
+ if (i == start && history_word_delimiters)
{
- if (string[i] == '\\' && string[i + 1] == '\n')
- {
- i++;
- continue;
- }
-
- if (string[i] == '\\' && delimiter != '\'' &&
- (delimiter != '"' || member (string[i], slashify_in_quotes)))
- {
- i++;
- continue;
- }
-
- if (delimiter && string[i] == delimiter)
- {
- delimiter = 0;
- continue;
- }
-
- if (!delimiter && (member (string[i], history_word_delimiters)))
- break;
-
- if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
- delimiter = string[i];
+ i++;
+ while (string[i] && member (string[i], history_word_delimiters))
+ i++;
}
- got_token:
-
/* If we are looking for the word in which the character at a
particular index falls, remember it. */
if (indp && wind != -1 && wind >= start && wind < i)
*indp = result_index;
- len = i - start;
if (result_index + 2 >= size)
result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
- result[result_index] = (char *)xmalloc (1 + len);
- strncpy (result[result_index], string + start, len);
- result[result_index][len] = '\0';
- result[++result_index] = (char *)NULL;
+
+ result[result_index++] = history_substring (string, start, i);
+ result[result_index] = (char *)NULL;
}
return (result);
diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c
index 77f757eac1d..7d340b346d4 100644
--- a/cmd-line-utils/readline/histfile.c
+++ b/cmd-line-utils/readline/histfile.c
@@ -1,6 +1,6 @@
/* histfile.c - functions to manipulate the history file. */
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
This file contains the GNU History Library (the Library), a set of
routines for managing the text of previously typed lines.
@@ -23,14 +23,19 @@
/* The goal is to make the implementation transparent, so that you
don't have to know what data types are used, just what functions
you can call. I think I have done that. */
+
#define READLINE_LIBRARY
+#if defined (__TANDEM)
+# include <floss.h>
+#endif
+
#include "config_readline.h"
#include <stdio.h>
#include <sys/types.h>
-#ifndef _MINIX
+#if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif
#include "posixstat.h"
@@ -50,7 +55,7 @@
# undef HAVE_MMAP
#endif
-#ifdef HAVE_MMAP
+#ifdef HISTORY_USE_MMAP
# include <sys/mman.h>
# ifdef MAP_FILE
@@ -65,7 +70,7 @@
# define MAP_FAILED ((void *)-1)
# endif
-#endif /* HAVE_MMAP */
+#endif /* HISTORY_USE_MMAP */
/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
on win 95/98/nt), we want to open files with O_BINARY mode so that there
@@ -91,6 +96,13 @@ extern int errno;
#include "rlshell.h"
#include "xmalloc.h"
+/* If non-zero, we write timestamps to the history file in history_do_write() */
+int history_write_timestamps = 0;
+
+/* Does S look like the beginning of a history timestamp entry? Placeholder
+ for more extensive tests. */
+#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char)
+
/* Return the string that should be used in the place of this
filename. This only matters when you don't specify the
filename to read_history (), or write_history (). */
@@ -149,13 +161,20 @@ read_history_range (filename, from, to)
const char *filename;
int from, to;
{
- register char *line_start, *line_end;
- char *input, *buffer, *bufend;
+ register char *line_start, *line_end, *p;
+ char *input, *buffer, *bufend, *last_ts;
int file, current_line, chars_read;
struct stat finfo;
size_t file_size;
+#if defined (EFBIG)
+ int overflow_errno = EFBIG;
+#elif defined (EOVERFLOW)
+ int overflow_errno = EOVERFLOW;
+#else
+ int overflow_errno = EIO;
+#endif
- buffer = (char *)NULL;
+ buffer = last_ts = (char *)NULL;
input = history_filename (filename);
file = open (input, O_RDONLY|O_BINARY, 0666);
@@ -167,37 +186,42 @@ read_history_range (filename, from, to)
/* check for overflow on very large files */
if (file_size != finfo.st_size || file_size + 1 < file_size)
{
-#if defined (EFBIG)
- errno = EFBIG;
-#elif defined (EOVERFLOW)
- errno = EOVERFLOW;
-#endif
+ errno = overflow_errno;
goto error_and_exit;
}
-#ifdef HAVE_MMAP
+#ifdef HISTORY_USE_MMAP
/* We map read/write and private so we can change newlines to NULs without
affecting the underlying object. */
buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
if ((void *)buffer == MAP_FAILED)
- goto error_and_exit;
+ {
+ errno = overflow_errno;
+ goto error_and_exit;
+ }
chars_read = file_size;
#else
buffer = (char *)malloc (file_size + 1);
if (buffer == 0)
- goto error_and_exit;
+ {
+ errno = overflow_errno;
+ goto error_and_exit;
+ }
chars_read = read (file, buffer, file_size);
#endif
if (chars_read < 0)
{
error_and_exit:
- chars_read = errno;
+ if (errno != 0)
+ chars_read = errno;
+ else
+ chars_read = EIO;
if (file >= 0)
close (file);
FREE (input);
-#ifndef HAVE_MMAP
+#ifndef HISTORY_USE_MMAP
FREE (buffer);
#endif
@@ -218,8 +242,12 @@ read_history_range (filename, from, to)
for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
if (*line_end == '\n')
{
- current_line++;
- line_start = line_end + 1;
+ p = line_end + 1;
+ /* If we see something we think is a timestamp, continue with this
+ line. We should check more extensively here... */
+ if (HIST_TIMESTAMP_START(p) == 0)
+ current_line++;
+ line_start = p;
}
/* If there are lines left to gobble, then gobble them now. */
@@ -229,7 +257,22 @@ read_history_range (filename, from, to)
*line_end = '\0';
if (*line_start)
- add_history (line_start);
+ {
+ if (HIST_TIMESTAMP_START(line_start) == 0)
+ {
+ add_history (line_start);
+ if (last_ts)
+ {
+ add_history_time (last_ts);
+ last_ts = NULL;
+ }
+ }
+ else
+ {
+ last_ts = line_start;
+ current_line--;
+ }
+ }
current_line++;
@@ -240,7 +283,7 @@ read_history_range (filename, from, to)
}
FREE (input);
-#ifndef HAVE_MMAP
+#ifndef HISTORY_USE_MMAP
FREE (buffer);
#else
munmap (buffer, file_size);
@@ -257,7 +300,7 @@ history_truncate_file (fname, lines)
const char *fname;
int lines;
{
- char *buffer, *filename, *bp;
+ char *buffer, *filename, *bp, *bp1; /* bp1 == bp+1 */
int file, chars_read, rv;
struct stat finfo;
size_t file_size;
@@ -320,11 +363,14 @@ history_truncate_file (fname, lines)
}
/* Count backwards from the end of buffer until we have passed
- LINES lines. */
- for (bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
+ LINES lines. bp1 is set funny initially. But since bp[1] can't
+ be a comment character (since it's off the end) and *bp can't be
+ both a newline and the history comment character, it should be OK. */
+ for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
{
- if (*bp == '\n')
+ if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
lines--;
+ bp1 = bp;
}
/* If this is the first line, then the file contains exactly the
@@ -333,11 +379,14 @@ history_truncate_file (fname, lines)
the current value of i and 0. Otherwise, write from the start of
this line until the end of the buffer. */
for ( ; bp > buffer; bp--)
- if (*bp == '\n')
- {
- bp++;
- break;
- }
+ {
+ if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
+ {
+ bp++;
+ break;
+ }
+ bp1 = bp;
+ }
/* Write only if there are more lines in the file than we want to
truncate to. */
@@ -372,9 +421,9 @@ history_do_write (filename, nelements, overwrite)
register int i;
char *output;
int file, mode, rv;
+#ifdef HISTORY_USE_MMAP
size_t cursize;
-#ifdef HAVE_MMAP
mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
#else
mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
@@ -388,7 +437,7 @@ history_do_write (filename, nelements, overwrite)
return (errno);
}
-#ifdef HAVE_MMAP
+#ifdef HISTORY_USE_MMAP
cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
#endif
@@ -406,10 +455,18 @@ history_do_write (filename, nelements, overwrite)
the_history = history_list ();
/* Calculate the total number of bytes to write. */
for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
- buffer_size += 1 + strlen (the_history[i]->line);
+#if 0
+ buffer_size += 2 + HISTENT_BYTES (the_history[i]);
+#else
+ {
+ if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
+ buffer_size += strlen (the_history[i]->timestamp) + 1;
+ buffer_size += strlen (the_history[i]->line) + 1;
+ }
+#endif
/* Allocate the buffer, and fill it. */
-#ifdef HAVE_MMAP
+#ifdef HISTORY_USE_MMAP
if (ftruncate (file, buffer_size+cursize) == -1)
goto mmap_error;
buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
@@ -434,12 +491,18 @@ mmap_error:
for (j = 0, i = history_length - nelements; i < history_length; i++)
{
+ if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
+ {
+ strcpy (buffer + j, the_history[i]->timestamp);
+ j += strlen (the_history[i]->timestamp);
+ buffer[j++] = '\n';
+ }
strcpy (buffer + j, the_history[i]->line);
j += strlen (the_history[i]->line);
buffer[j++] = '\n';
}
-#ifdef HAVE_MMAP
+#ifdef HISTORY_USE_MMAP
if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
rv = errno;
#else
diff --git a/cmd-line-utils/readline/history.c b/cmd-line-utils/readline/history.c
index 759ff9e0de9..bb1960d8d99 100644
--- a/cmd-line-utils/readline/history.c
+++ b/cmd-line-utils/readline/history.c
@@ -1,6 +1,6 @@
-/* History.c -- standalone history library */
+/* history.c -- standalone history library */
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
This file contains the GNU History Library (the Library), a set of
routines for managing the text of previously typed lines.
@@ -50,6 +50,8 @@
/* The number of slots to increase the_history by. */
#define DEFAULT_HISTORY_GROW_SIZE 50
+static char *hist_inittime PARAMS((void));
+
/* **************************************************************** */
/* */
/* History Functions */
@@ -121,14 +123,15 @@ using_history ()
}
/* Return the number of bytes that the primary history entries are using.
- This just adds up the lengths of the_history->lines. */
+ This just adds up the lengths of the_history->lines and the associated
+ timestamps. */
int
history_total_bytes ()
{
register int i, result;
for (i = result = 0; the_history && the_history[i]; i++)
- result += strlen (the_history[i]->line);
+ result += HISTENT_BYTES (the_history[i]);
return (result);
}
@@ -204,6 +207,40 @@ history_get (offset)
: the_history[local_index];
}
+time_t
+history_get_time (hist)
+ HIST_ENTRY *hist;
+{
+ char *ts;
+ time_t t;
+
+ if (hist == 0 || hist->timestamp == 0)
+ return 0;
+ ts = hist->timestamp;
+ if (ts[0] != history_comment_char)
+ return 0;
+ t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */
+ return t;
+}
+
+static char *
+hist_inittime ()
+{
+ time_t t;
+ char ts[64], *ret;
+
+ t = (time_t) time ((time_t *)0);
+#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
+ snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
+#else
+ sprintf (ts, "X%lu", (unsigned long) t);
+#endif
+ ret = savestring (ts);
+ ret[0] = history_comment_char;
+
+ return ret;
+}
+
/* Place STRING at the end of the history list. The data field
is set to NULL. */
void
@@ -223,10 +260,7 @@ add_history (string)
/* If there is something in the slot, then remove it. */
if (the_history[0])
- {
- free (the_history[0]->line);
- free (the_history[0]);
- }
+ (void) free_history_entry (the_history[0]);
/* Copy the rest of the entries, moving down one slot. */
for (i = 0; i < history_length; i++)
@@ -258,10 +292,41 @@ add_history (string)
temp->line = savestring (string);
temp->data = (char *)NULL;
+ temp->timestamp = hist_inittime ();
+
the_history[history_length] = (HIST_ENTRY *)NULL;
the_history[history_length - 1] = temp;
}
+/* Change the time stamp of the most recent history entry to STRING. */
+void
+add_history_time (string)
+ const char *string;
+{
+ HIST_ENTRY *hs;
+
+ hs = the_history[history_length - 1];
+ FREE (hs->timestamp);
+ hs->timestamp = savestring (string);
+}
+
+/* Free HIST and return the data so the calling application can free it
+ if necessary and desired. */
+histdata_t
+free_history_entry (hist)
+ HIST_ENTRY *hist;
+{
+ histdata_t x;
+
+ if (hist == 0)
+ return ((histdata_t) 0);
+ FREE (hist->line);
+ FREE (hist->timestamp);
+ x = hist->data;
+ free (hist);
+ return (x);
+}
+
/* Make the history entry at WHICH have LINE and DATA. This returns
the old entry so you can dispose of the data. In the case of an
invalid WHICH, a NULL pointer is returned. */
@@ -281,6 +346,7 @@ replace_history_entry (which, line, data)
temp->line = savestring (line);
temp->data = data;
+ temp->timestamp = savestring (old_value->timestamp);
the_history[which] = temp;
return (old_value);
@@ -325,10 +391,7 @@ stifle_history (max)
{
/* This loses because we cannot free the data. */
for (i = 0, j = history_length - max; i < j; i++)
- {
- free (the_history[i]->line);
- free (the_history[i]);
- }
+ free_history_entry (the_history[i]);
history_base = i;
for (j = 0, i = history_length - max; j < max; i++, j++)
@@ -370,8 +433,7 @@ clear_history ()
/* This loses because we cannot free the data. */
for (i = 0; i < history_length; i++)
{
- free (the_history[i]->line);
- free (the_history[i]);
+ free_history_entry (the_history[i]);
the_history[i] = (HIST_ENTRY *)NULL;
}
diff --git a/cmd-line-utils/readline/history.h b/cmd-line-utils/readline/history.h
index afd85104554..14ca2a996c7 100644
--- a/cmd-line-utils/readline/history.h
+++ b/cmd-line-utils/readline/history.h
@@ -1,5 +1,5 @@
-/* History.h -- the names of functions that you can call in history. */
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+/* history.h -- the names of functions that you can call in history. */
+/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
This file contains the GNU History Library (the Library), a set of
routines for managing the text of previously typed lines.
@@ -26,6 +26,8 @@
extern "C" {
#endif
+#include <time.h> /* XXX - for history timestamp code */
+
#if defined READLINE_LIBRARY
# include "rlstdc.h"
# include "rltypedefs.h"
@@ -43,9 +45,13 @@ typedef char *histdata_t;
/* The structure used to store a history entry. */
typedef struct _hist_entry {
char *line;
+ char *timestamp; /* char * rather than time_t for read/write */
histdata_t data;
} HIST_ENTRY;
+/* Size of the history-library-managed space in history entry HS. */
+#define HISTENT_BYTES(hs) (strlen ((hs)->line) + strlen ((hs)->timestamp))
+
/* A structure used to pass the current state of the history stuff around. */
typedef struct _hist_state {
HIST_ENTRY **entries; /* Pointer to the entries themselves. */
@@ -76,11 +82,19 @@ extern void history_set_history_state PARAMS((HISTORY_STATE *));
The associated data field (if any) is set to NULL. */
extern void add_history PARAMS((const char *));
+/* Change the timestamp associated with the most recent history entry to
+ STRING. */
+extern void add_history_time PARAMS((const char *));
+
/* A reasonably useless function, only here for completeness. WHICH
is the magic number that tells us which element to delete. The
elements are numbered from 0. */
extern HIST_ENTRY *remove_history PARAMS((int));
+/* Free the history entry H and return any application-specific data
+ associated with it. */
+extern histdata_t free_history_entry PARAMS((HIST_ENTRY *));
+
/* Make the history entry at WHICH have LINE and DATA. This returns
the old entry so you can dispose of the data. In the case of an
invalid WHICH, a NULL pointer is returned. */
@@ -119,6 +133,10 @@ extern HIST_ENTRY *current_history PARAMS((void));
array. OFFSET is relative to history_base. */
extern HIST_ENTRY *history_get PARAMS((int));
+/* Return the timestamp associated with the HIST_ENTRY * passed as an
+ argument */
+extern time_t history_get_time PARAMS((HIST_ENTRY *));
+
/* Return the number of bytes that the primary history entries are using.
This just adds up the lengths of the_history->lines. */
extern int history_total_bytes PARAMS((void));
@@ -225,12 +243,14 @@ extern int history_length;
extern int history_max_entries;
extern char history_expansion_char;
extern char history_subst_char;
-extern const char *history_word_delimiters;
+extern char *history_word_delimiters;
extern char history_comment_char;
-extern const char *history_no_expand_chars;
+extern char *history_no_expand_chars;
extern char *history_search_delimiter_chars;
extern int history_quotes_inhibit_expansion;
+extern int history_write_timestamps;
+
/* Backwards compatibility */
extern int max_input_history;
diff --git a/cmd-line-utils/readline/histsearch.c b/cmd-line-utils/readline/histsearch.c
index ffc97d720db..778b323afdc 100644
--- a/cmd-line-utils/readline/histsearch.c
+++ b/cmd-line-utils/readline/histsearch.c
@@ -75,11 +75,11 @@ history_search_internal (string, direction, anchored)
if (string == 0 || *string == '\0')
return (-1);
- if (!history_length || ((i == history_length) && !reverse))
+ if (!history_length || ((i >= history_length) && !reverse))
return (-1);
- if (reverse && (i == history_length))
- i--;
+ if (reverse && (i >= history_length))
+ i = history_length - 1;
#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
diff --git a/cmd-line-utils/readline/input.c b/cmd-line-utils/readline/input.c
index d9c52dfcec8..1981061eac6 100644
--- a/cmd-line-utils/readline/input.c
+++ b/cmd-line-utils/readline/input.c
@@ -21,6 +21,10 @@
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#define READLINE_LIBRARY
+#if defined (__TANDEM)
+# include <floss.h>
+#endif
+
#include "config_readline.h"
#include <sys/types.h>
@@ -152,6 +156,12 @@ _rl_unget_char (key)
return (0);
}
+int
+_rl_pushed_input_available ()
+{
+ return (push_index != pop_index);
+}
+
/* If a character is available to be read, then read it and stuff it into
IBUFFER. Otherwise, just return. Returns number of characters read
(0 if none available) and -1 on error (EIO). */
@@ -160,7 +170,7 @@ rl_gather_tyi ()
{
int tty;
register int tem, result;
- int chars_avail;
+ int chars_avail, k;
char input;
#if defined(HAVE_SELECT)
fd_set readfds, exceptfds;
@@ -200,6 +210,11 @@ rl_gather_tyi ()
fcntl (tty, F_SETFL, tem);
if (chars_avail == -1 && errno == EAGAIN)
return 0;
+ if (chars_avail == 0) /* EOF */
+ {
+ rl_stuff_char (EOF);
+ return (0);
+ }
}
#endif /* O_NDELAY */
@@ -223,7 +238,12 @@ rl_gather_tyi ()
if (result != -1)
{
while (chars_avail--)
- rl_stuff_char ((*rl_getc_function) (rl_instream));
+ {
+ k = (*rl_getc_function) (rl_instream);
+ rl_stuff_char (k);
+ if (k == NEWLINE || k == RETURN)
+ break;
+ }
}
else
{
@@ -385,7 +405,7 @@ rl_read_key ()
else
{
/* If input is coming from a macro, then use that. */
- if ((c = _rl_next_macro_key ()))
+ if (c = _rl_next_macro_key ())
return (c);
/* If the user has an event function, then call it periodically. */
diff --git a/cmd-line-utils/readline/isearch.c b/cmd-line-utils/readline/isearch.c
index 1de16c6a56c..f7b0f1404e9 100644
--- a/cmd-line-utils/readline/isearch.c
+++ b/cmd-line-utils/readline/isearch.c
@@ -68,7 +68,7 @@ static char *prev_line_found;
static char *last_isearch_string;
static int last_isearch_string_len;
-static const char *default_isearch_terminators = "\033\012";
+static char *default_isearch_terminators = "\033\012";
/* Search backwards through the history looking for a string which is typed
interactively. Start with the current line. */
@@ -96,7 +96,7 @@ rl_forward_search_history (sign, key)
static void
rl_display_search (search_string, reverse_p, where)
char *search_string;
- int reverse_p, where __attribute__((unused));
+ int reverse_p, where;
{
char *message;
int msglen, searchlen;
@@ -144,7 +144,7 @@ rl_display_search (search_string, reverse_p, where)
backwards. */
static int
rl_search_history (direction, invoking_key)
- int direction, invoking_key __attribute__((unused));
+ int direction, invoking_key;
{
/* The string that the user types in to search for. */
char *search_string;
@@ -184,7 +184,7 @@ rl_search_history (direction, invoking_key)
/* The list of characters which terminate the search, but are not
subsequently executed. If the variable isearch-terminators has
been set, we use that value, otherwise we use ESC and C-J. */
- const char *isearch_terminators;
+ char *isearch_terminators;
RL_SETSTATE(RL_STATE_ISEARCH);
orig_point = rl_point;
diff --git a/cmd-line-utils/readline/keymaps.c b/cmd-line-utils/readline/keymaps.c
index 9972d83e4f1..2be03f7086f 100644
--- a/cmd-line-utils/readline/keymaps.c
+++ b/cmd-line-utils/readline/keymaps.c
@@ -62,11 +62,13 @@ rl_make_bare_keymap ()
keymap[i].function = (rl_command_func_t *)NULL;
}
+#if 0
for (i = 'A'; i < ('Z' + 1); i++)
{
keymap[i].type = ISFUNC;
keymap[i].function = rl_do_lowercase_version;
}
+#endif
return (keymap);
}
@@ -77,8 +79,9 @@ rl_copy_keymap (map)
Keymap map;
{
register int i;
- Keymap temp = rl_make_bare_keymap ();
+ Keymap temp;
+ temp = rl_make_bare_keymap ();
for (i = 0; i < KEYMAP_SIZE; i++)
{
temp[i].type = map[i].type;
@@ -107,12 +110,8 @@ rl_make_keymap ()
newmap[CTRL('H')].function = rl_rubout;
#if KEYMAP_SIZE > 128
- /* Printing characters in some 8-bit character sets. */
- for (i = 128; i < 160; i++)
- newmap[i].function = rl_insert;
-
- /* ISO Latin-1 printing characters should self-insert. */
- for (i = 160; i < 256; i++)
+ /* Printing characters in ISO Latin-1 and some 8-bit character sets. */
+ for (i = 128; i < 256; i++)
newmap[i].function = rl_insert;
#endif /* KEYMAP_SIZE > 128 */
diff --git a/cmd-line-utils/readline/kill.c b/cmd-line-utils/readline/kill.c
index 32a661f076f..061bdafcf9a 100644
--- a/cmd-line-utils/readline/kill.c
+++ b/cmd-line-utils/readline/kill.c
@@ -77,7 +77,7 @@ static int rl_yank_nth_arg_internal PARAMS((int, int, int));
of kill material. */
int
rl_set_retained_kills (num)
- int num __attribute__((unused));
+ int num;
{
return 0;
}
@@ -294,7 +294,7 @@ rl_backward_kill_line (direction, ignore)
/* Kill the whole line, no matter where point is. */
int
rl_kill_full_line (count, ignore)
- int count __attribute__((unused)), ignore __attribute__((unused));
+ int count, ignore;
{
rl_begin_undo_group ();
rl_point = 0;
@@ -312,7 +312,7 @@ rl_kill_full_line (count, ignore)
using behaviour that they expect. */
int
rl_unix_word_rubout (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
int orig_point;
@@ -337,6 +337,47 @@ rl_unix_word_rubout (count, key)
if (rl_editing_mode == emacs_mode)
rl_mark = rl_point;
}
+
+ return 0;
+}
+
+/* This deletes one filename component in a Unix pathname. That is, it
+ deletes backward to directory separator (`/') or whitespace. */
+int
+rl_unix_filename_rubout (count, key)
+ int count, key;
+{
+ int orig_point, c;
+
+ if (rl_point == 0)
+ rl_ding ();
+ else
+ {
+ orig_point = rl_point;
+ if (count <= 0)
+ count = 1;
+
+ while (count--)
+ {
+ c = rl_line_buffer[rl_point - 1];
+ while (rl_point && (whitespace (c) || c == '/'))
+ {
+ rl_point--;
+ c = rl_line_buffer[rl_point - 1];
+ }
+
+ while (rl_point && (whitespace (c) == 0) && c != '/')
+ {
+ rl_point--;
+ c = rl_line_buffer[rl_point - 1];
+ }
+ }
+
+ rl_kill_text (orig_point, rl_point);
+ if (rl_editing_mode == emacs_mode)
+ rl_mark = rl_point;
+ }
+
return 0;
}
@@ -348,7 +389,7 @@ rl_unix_word_rubout (count, key)
doing. */
int
rl_unix_line_discard (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
if (rl_point == 0)
rl_ding ();
@@ -385,7 +426,7 @@ region_kill_internal (delete)
/* Copy the text in the region to the kill ring. */
int
rl_copy_region_to_kill (count, ignore)
- int count __attribute__((unused)), ignore __attribute__((unused));
+ int count, ignore;
{
return (region_kill_internal (0));
}
@@ -393,7 +434,7 @@ rl_copy_region_to_kill (count, ignore)
/* Kill the text between the point and mark. */
int
rl_kill_region (count, ignore)
- int count __attribute__((unused)), ignore __attribute__((unused));
+ int count, ignore;
{
int r, npoint;
@@ -458,7 +499,7 @@ rl_copy_backward_word (count, key)
/* Yank back the last killed text. This ignores arguments. */
int
rl_yank (count, ignore)
- int count __attribute__((unused)), ignore __attribute__((unused));
+ int count, ignore;
{
if (rl_kill_ring == 0)
{
@@ -477,7 +518,7 @@ rl_yank (count, ignore)
yank back some other text. */
int
rl_yank_pop (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
int l, n;
diff --git a/cmd-line-utils/readline/macro.c b/cmd-line-utils/readline/macro.c
index 7f5c39f7d86..f7b77a831b8 100644
--- a/cmd-line-utils/readline/macro.c
+++ b/cmd-line-utils/readline/macro.c
@@ -190,7 +190,7 @@ _rl_kill_kbd_macro ()
re-executing the existing macro. */
int
rl_start_kbd_macro (ignore1, ignore2)
- int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
+ int ignore1, ignore2;
{
if (RL_ISSTATE (RL_STATE_MACRODEF))
{
@@ -215,7 +215,7 @@ rl_start_kbd_macro (ignore1, ignore2)
that many times, counting the definition as the first time. */
int
rl_end_kbd_macro (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
if (RL_ISSTATE (RL_STATE_MACRODEF) == 0)
{
@@ -235,7 +235,7 @@ rl_end_kbd_macro (count, ignore)
COUNT says how many times to execute it. */
int
rl_call_last_kbd_macro (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
if (current_macro == 0)
_rl_abort_internal ();
diff --git a/cmd-line-utils/readline/mbutil.c b/cmd-line-utils/readline/mbutil.c
index 3113b7b0538..c88e9485f39 100644
--- a/cmd-line-utils/readline/mbutil.c
+++ b/cmd-line-utils/readline/mbutil.c
@@ -1,6 +1,6 @@
/* mbutil.c -- readline multibyte character utility functions */
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -90,12 +90,12 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
/* if this is true, means that seed was not pointed character
started byte. So correct the point and consume count */
if (seed < point)
- count --;
+ count--;
while (count > 0)
{
tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps);
- if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+ if (MB_INVALIDCH ((size_t)tmp))
{
/* invalid bytes. asume a byte represents a character */
point++;
@@ -103,9 +103,8 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
/* reset states. */
memset(&ps, 0, sizeof(mbstate_t));
}
- else if (tmp == (size_t)0)
- /* found '\0' char */
- break;
+ else if (MB_NULLWCH (tmp))
+ break; /* found wide '\0' */
else
{
/* valid bytes */
@@ -158,7 +157,7 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero)
while (point < seed)
{
tmp = mbrtowc (&wc, string + point, length - point, &ps);
- if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+ if (MB_INVALIDCH ((size_t)tmp))
{
/* in this case, bytes are invalid or shorted to compose
multibyte char, so assume that the first byte represents
@@ -167,8 +166,12 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero)
/* clear the state of the byte sequence, because
in this case effect of mbstate is undefined */
memset(&ps, 0, sizeof (mbstate_t));
+
+ /* Since we're assuming that this byte represents a single
+ non-zero-width character, don't forget about it. */
+ prev = point;
}
- else if (tmp == 0)
+ else if (MB_NULLWCH (tmp))
break; /* Found '\0' char. Can this happen? */
else
{
@@ -194,7 +197,7 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero)
if it couldn't parse a complete multibyte character. */
int
_rl_get_char_len (src, ps)
- const char *src;
+ char *src;
mbstate_t *ps;
{
size_t tmp;
@@ -203,14 +206,16 @@ _rl_get_char_len (src, ps)
if (tmp == (size_t)(-2))
{
/* shorted to compose multibyte char */
- memset (ps, 0, sizeof(mbstate_t));
+ if (ps)
+ memset (ps, 0, sizeof(mbstate_t));
return -2;
}
else if (tmp == (size_t)(-1))
{
/* invalid to compose multibyte char */
/* initialize the conversion state */
- memset (ps, 0, sizeof(mbstate_t));
+ if (ps)
+ memset (ps, 0, sizeof(mbstate_t));
return -1;
}
else if (tmp == (size_t)0)
@@ -223,9 +228,12 @@ _rl_get_char_len (src, ps)
return 1. Otherwise return 0. */
int
_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
- char *buf1, *buf2;
- mbstate_t *ps1, *ps2;
- int pos1, pos2;
+ char *buf1;
+ int pos1;
+ mbstate_t *ps1;
+ char *buf2;
+ int pos2;
+ mbstate_t *ps2;
{
int i, w1, w2;
@@ -249,7 +257,7 @@ _rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
it returns -1 */
int
_rl_adjust_point(string, point, ps)
- const char *string;
+ char *string;
int point;
mbstate_t *ps;
{
@@ -266,7 +274,7 @@ _rl_adjust_point(string, point, ps)
while (pos < point)
{
tmp = mbrlen (string + pos, length - pos, ps);
- if((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+ if (MB_INVALIDCH ((size_t)tmp))
{
/* in this case, bytes are invalid or shorted to compose
multibyte char, so assume that the first byte represents
@@ -274,8 +282,11 @@ _rl_adjust_point(string, point, ps)
pos++;
/* clear the state of the byte sequence, because
in this case effect of mbstate is undefined */
- memset (ps, 0, sizeof (mbstate_t));
+ if (ps)
+ memset (ps, 0, sizeof (mbstate_t));
}
+ else if (MB_NULLWCH (tmp))
+ pos++;
else
pos += tmp;
}
@@ -308,8 +319,8 @@ _rl_is_mbchar_matched (string, seed, end, mbchar, length)
#undef _rl_find_next_mbchar
int
_rl_find_next_mbchar (string, seed, count, flags)
- char *string __attribute__((unused));
- int seed, count, flags __attribute__((unused));
+ char *string;
+ int seed, count, flags;
{
#if defined (HANDLE_MULTIBYTE)
return _rl_find_next_mbchar_internal (string, seed, count, flags);
@@ -324,8 +335,8 @@ _rl_find_next_mbchar (string, seed, count, flags)
#undef _rl_find_prev_mbchar
int
_rl_find_prev_mbchar (string, seed, flags)
- char *string __attribute__((unused));
- int seed, flags __attribute__((unused));
+ char *string;
+ int seed, flags;
{
#if defined (HANDLE_MULTIBYTE)
return _rl_find_prev_mbchar_internal (string, seed, flags);
diff --git a/cmd-line-utils/readline/misc.c b/cmd-line-utils/readline/misc.c
index 858d09dbe90..810b940edab 100644
--- a/cmd-line-utils/readline/misc.c
+++ b/cmd-line-utils/readline/misc.c
@@ -1,6 +1,6 @@
/* misc.c -- miscellaneous bindable readline functions. */
-/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -155,7 +155,7 @@ rl_digit_loop ()
/* Add the current digit to the argument in progress. */
int
rl_digit_argument (ignore, key)
- int ignore __attribute__((unused)), key;
+ int ignore, key;
{
rl_execute_next (key);
return (rl_digit_loop ());
@@ -185,7 +185,7 @@ _rl_init_argument ()
dispatch on it. If the key is the abort character then abort. */
int
rl_universal_argument (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
rl_numeric_arg *= 4;
return (rl_digit_loop ());
@@ -251,6 +251,8 @@ rl_maybe_unsave_line ()
{
if (_rl_saved_line_for_history)
{
+ /* Can't call with `1' because rl_undo_list might point to an undo
+ list from a history entry, as in rl_replace_from_history() below. */
rl_replace_line (_rl_saved_line_for_history->line, 0);
rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
_rl_free_history_entry (_rl_saved_line_for_history);
@@ -272,6 +274,13 @@ rl_maybe_save_line ()
_rl_saved_line_for_history->line = savestring (rl_line_buffer);
_rl_saved_line_for_history->data = (char *)rl_undo_list;
}
+ else if (STREQ (rl_line_buffer, _rl_saved_line_for_history->line) == 0)
+ {
+ free (_rl_saved_line_for_history->line);
+ _rl_saved_line_for_history->line = savestring (rl_line_buffer);
+ _rl_saved_line_for_history->data = (char *)rl_undo_list; /* XXX possible memleak */
+ }
+
return 0;
}
@@ -296,7 +305,7 @@ _rl_history_set_point ()
rl_point = rl_end;
#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
+ if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
rl_point = 0;
#endif /* VI_MODE */
@@ -307,8 +316,10 @@ _rl_history_set_point ()
void
rl_replace_from_history (entry, flags)
HIST_ENTRY *entry;
- int flags __attribute__((unused)); /* currently unused */
+ int flags; /* currently unused */
{
+ /* Can't call with `1' because rl_undo_list might point to an undo list
+ from a history entry, just like we're setting up here. */
rl_replace_line (entry->line, 0);
rl_undo_list = (UNDO_LIST *)entry->data;
rl_point = rl_end;
@@ -332,7 +343,7 @@ rl_replace_from_history (entry, flags)
/* Meta-< goes to the start of the history. */
int
rl_beginning_of_history (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
return (rl_get_previous_history (1 + where_history (), key));
}
@@ -340,7 +351,7 @@ rl_beginning_of_history (count, key)
/* Meta-> goes to the end of the history. (The current line). */
int
rl_end_of_history (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
rl_maybe_replace_line ();
using_history ();
@@ -433,6 +444,7 @@ rl_get_previous_history (count, key)
rl_replace_from_history (temp, 0);
_rl_history_set_point ();
}
+
return 0;
}
@@ -444,7 +456,7 @@ rl_get_previous_history (count, key)
/* How to toggle back and forth between editing modes. */
int
rl_vi_editing_mode (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
#if defined (VI_MODE)
_rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
@@ -457,7 +469,7 @@ rl_vi_editing_mode (count, key)
int
rl_emacs_editing_mode (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
rl_editing_mode = emacs_mode;
_rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
@@ -468,7 +480,7 @@ rl_emacs_editing_mode (count, key)
/* Function for the rest of the library to use to set insert/overwrite mode. */
void
_rl_set_insert_mode (im, force)
- int im, force __attribute__((unused));
+ int im, force;
{
#ifdef CURSOR_MODE
_rl_set_cursor (im, force);
@@ -481,7 +493,7 @@ _rl_set_insert_mode (im, force)
mode. A negative or zero explicit argument selects insert mode. */
int
rl_overwrite_mode (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
if (rl_explicit_arg == 0)
_rl_set_insert_mode (rl_insert_mode ^ 1, 0);
diff --git a/cmd-line-utils/readline/nls.c b/cmd-line-utils/readline/nls.c
index 6555c50c22b..4f28152f316 100644
--- a/cmd-line-utils/readline/nls.c
+++ b/cmd-line-utils/readline/nls.c
@@ -73,6 +73,23 @@ static char *normalize_codeset PARAMS((char *));
static char *find_codeset PARAMS((char *, size_t *));
#endif /* !HAVE_SETLOCALE */
+static char *_rl_get_locale_var PARAMS((const char *));
+
+static char *
+_rl_get_locale_var (v)
+ const char *v;
+{
+ char *lspec;
+
+ lspec = sh_get_env_value ("LC_ALL");
+ if (lspec == 0 || *lspec == 0)
+ lspec = sh_get_env_value (v);
+ if (lspec == 0 || *lspec == 0)
+ lspec = sh_get_env_value ("LANG");
+
+ return lspec;
+}
+
/* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
to decide the defaults for 8-bit character input and output. Returns
1 if we set eight-bit mode. */
@@ -82,10 +99,21 @@ _rl_init_eightbit ()
/* If we have setlocale(3), just check the current LC_CTYPE category
value, and go into eight-bit mode if it's not C or POSIX. */
#if defined (HAVE_SETLOCALE)
- char *t;
+ char *lspec, *t;
/* Set the LC_CTYPE locale category from environment variables. */
- t = setlocale (LC_CTYPE, "");
+ lspec = _rl_get_locale_var ("LC_CTYPE");
+ /* Since _rl_get_locale_var queries the right environment variables,
+ we query the current locale settings with setlocale(), and, if
+ that doesn't return anything, we set lspec to the empty string to
+ force the subsequent call to setlocale() to define the `native'
+ environment. */
+ if (lspec == 0 || *lspec == 0)
+ lspec = setlocale (LC_CTYPE, (char *)NULL);
+ if (lspec == 0)
+ lspec = "";
+ t = setlocale (LC_CTYPE, lspec);
+
if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
{
_rl_meta_flag = 1;
@@ -103,9 +131,8 @@ _rl_init_eightbit ()
/* We don't have setlocale. Finesse it. Check the environment for the
appropriate variables and set eight-bit mode if they have the right
values. */
- lspec = sh_get_env_value ("LC_ALL");
- if (lspec == 0) lspec = sh_get_env_value ("LC_CTYPE");
- if (lspec == 0) lspec = sh_get_env_value ("LANG");
+ lspec = _rl_get_locale_var ("LC_CTYPE");
+
if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
return (0);
for (i = 0; t && legal_lang_values[i]; i++)
diff --git a/cmd-line-utils/readline/parens.c b/cmd-line-utils/readline/parens.c
index 5d4a08a0ce8..bb893ac1bfb 100644
--- a/cmd-line-utils/readline/parens.c
+++ b/cmd-line-utils/readline/parens.c
@@ -21,6 +21,10 @@
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#define READLINE_LIBRARY
+#if defined (__TANDEM)
+# include <floss.h>
+#endif
+
#include "rlconf.h"
#include "config_readline.h"
diff --git a/cmd-line-utils/readline/posixdir.h b/cmd-line-utils/readline/posixdir.h
index 505e27954f1..91f6d96111d 100644
--- a/cmd-line-utils/readline/posixdir.h
+++ b/cmd-line-utils/readline/posixdir.h
@@ -25,7 +25,11 @@
#if defined (HAVE_DIRENT_H)
# include <dirent.h>
-# define D_NAMLEN(d) (strlen ((d)->d_name))
+# if defined (HAVE_STRUCT_DIRENT_D_NAMLEN)
+# define D_NAMLEN(d) ((d)->d_namlen)
+# else
+# define D_NAMLEN(d) (strlen ((d)->d_name))
+# endif /* !HAVE_STRUCT_DIRENT_D_NAMLEN */
#else
# if defined (HAVE_SYS_NDIR_H)
# include <sys/ndir.h>
@@ -42,11 +46,11 @@
# define D_NAMLEN(d) ((d)->d_namlen)
#endif /* !HAVE_DIRENT_H */
-#if defined (STRUCT_DIRENT_HAS_D_INO) && !defined (STRUCT_DIRENT_HAS_D_FILENO)
+#if defined (HAVE_STRUCT_DIRENT_D_INO) && !defined (HAVE_STRUCT_DIRENT_D_FILENO)
# define d_fileno d_ino
#endif
-#if defined (_POSIX_SOURCE) && (!defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO))
+#if defined (_POSIX_SOURCE) && (!defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO))
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
# define REAL_DIR_ENTRY(dp) 1
diff --git a/cmd-line-utils/readline/readline.c b/cmd-line-utils/readline/readline.c
index 2c0bb499b7b..e82db84c9dc 100644
--- a/cmd-line-utils/readline/readline.c
+++ b/cmd-line-utils/readline/readline.c
@@ -66,11 +66,11 @@
#include "xmalloc.h"
#ifndef RL_LIBRARY_VERSION
-# define RL_LIBRARY_VERSION "4.3"
+# define RL_LIBRARY_VERSION "5.0"
#endif
#ifndef RL_READLINE_VERSION
-# define RL_READLINE_VERSION 0x0403
+# define RL_READLINE_VERSION 0x0500
#endif
extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
@@ -83,6 +83,7 @@ static void bind_arrow_keys_internal PARAMS((Keymap));
static void bind_arrow_keys PARAMS((void));
static void readline_default_bindings PARAMS((void));
+static void reset_default_bindings PARAMS((void));
/* **************************************************************** */
/* */
@@ -345,7 +346,7 @@ readline_internal_setup ()
#if defined (VI_MODE)
if (rl_editing_mode == vi_mode)
- rl_vi_insertion_mode (1, 0);
+ rl_vi_insertion_mode (1, 'i');
#endif /* VI_MODE */
if (rl_pre_input_hook)
@@ -648,7 +649,21 @@ _rl_dispatch_subseq (key, map, got_subseq)
the function. The recursive call to _rl_dispatch_subseq has
already taken care of pushing any necessary input back onto
the input queue with _rl_unget_char. */
- r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
+ {
+#if 0
+ r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
+#else
+ /* XXX - experimental code -- might never be executed. Save
+ for later. */
+ Keymap m = FUNCTION_TO_KEYMAP (map, key);
+ int type = m[ANYOTHERKEY].type;
+ func = m[ANYOTHERKEY].function;
+ if (type == ISFUNC && func == rl_do_lowercase_version)
+ r = _rl_dispatch (_rl_to_lower (key), map);
+ else
+ r = _rl_dispatch (ANYOTHERKEY, m);
+#endif
+ }
else if (r && map[ANYOTHERKEY].function)
{
/* We didn't match (r is probably -1), so return something to
@@ -682,6 +697,7 @@ _rl_dispatch_subseq (key, map, got_subseq)
}
#if defined (VI_MODE)
if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
+ key != ANYOTHERKEY &&
_rl_vi_textmod_command (key))
_rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
#endif
@@ -836,7 +852,7 @@ readline_initialize_everything ()
/* If the completion parser's default word break characters haven't
been set yet, then do so now. */
if (rl_completer_word_break_characters == (char *)NULL)
- rl_completer_word_break_characters = rl_basic_word_break_characters;
+ rl_completer_word_break_characters = (char *)rl_basic_word_break_characters;
}
/* If this system allows us to look at the values of the regular
@@ -848,6 +864,15 @@ readline_default_bindings ()
rl_tty_set_default_bindings (_rl_keymap);
}
+/* Reset the default bindings for the terminal special characters we're
+ interested in back to rl_insert and read the new ones. */
+static void
+reset_default_bindings ()
+{
+ rl_tty_unset_default_bindings (_rl_keymap);
+ rl_tty_set_default_bindings (_rl_keymap);
+}
+
/* Bind some common arrow key sequences in MAP. */
static void
bind_arrow_keys_internal (map)
@@ -859,25 +884,25 @@ bind_arrow_keys_internal (map)
_rl_keymap = map;
#if defined (__MSDOS__)
- _rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
- _rl_bind_if_unbound ("\033[0B", rl_backward_char);
- _rl_bind_if_unbound ("\033[0C", rl_forward_char);
- _rl_bind_if_unbound ("\033[0D", rl_get_next_history);
+ rl_bind_keyseq_if_unbound ("\033[0A", rl_get_previous_history);
+ rl_bind_keyseq_if_unbound ("\033[0B", rl_backward_char);
+ rl_bind_keyseq_if_unbound ("\033[0C", rl_forward_char);
+ rl_bind_keyseq_if_unbound ("\033[0D", rl_get_next_history);
#endif
- _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
- _rl_bind_if_unbound ("\033[B", rl_get_next_history);
- _rl_bind_if_unbound ("\033[C", rl_forward_char);
- _rl_bind_if_unbound ("\033[D", rl_backward_char);
- _rl_bind_if_unbound ("\033[H", rl_beg_of_line);
- _rl_bind_if_unbound ("\033[F", rl_end_of_line);
-
- _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
- _rl_bind_if_unbound ("\033OB", rl_get_next_history);
- _rl_bind_if_unbound ("\033OC", rl_forward_char);
- _rl_bind_if_unbound ("\033OD", rl_backward_char);
- _rl_bind_if_unbound ("\033OH", rl_beg_of_line);
- _rl_bind_if_unbound ("\033OF", rl_end_of_line);
+ rl_bind_keyseq_if_unbound ("\033[A", rl_get_previous_history);
+ rl_bind_keyseq_if_unbound ("\033[B", rl_get_next_history);
+ rl_bind_keyseq_if_unbound ("\033[C", rl_forward_char);
+ rl_bind_keyseq_if_unbound ("\033[D", rl_backward_char);
+ rl_bind_keyseq_if_unbound ("\033[H", rl_beg_of_line);
+ rl_bind_keyseq_if_unbound ("\033[F", rl_end_of_line);
+
+ rl_bind_keyseq_if_unbound ("\033OA", rl_get_previous_history);
+ rl_bind_keyseq_if_unbound ("\033OB", rl_get_next_history);
+ rl_bind_keyseq_if_unbound ("\033OC", rl_forward_char);
+ rl_bind_keyseq_if_unbound ("\033OD", rl_backward_char);
+ rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line);
+ rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line);
_rl_keymap = xkeymap;
}
diff --git a/cmd-line-utils/readline/readline.h b/cmd-line-utils/readline/readline.h
index 9425de50aef..222b317c4a8 100644
--- a/cmd-line-utils/readline/readline.h
+++ b/cmd-line-utils/readline/readline.h
@@ -1,6 +1,6 @@
/* Readline.h -- the names of functions callable from within readline. */
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -40,9 +40,9 @@ extern "C" {
#endif
/* Hex-encoded Readline version number. */
-#define RL_READLINE_VERSION 0x0403 /* Readline 4.3 */
-#define RL_VERSION_MAJOR 4
-#define RL_VERSION_MINOR 3
+#define RL_READLINE_VERSION 0x0500 /* Readline 5.0 */
+#define RL_VERSION_MAJOR 5
+#define RL_VERSION_MINOR 0
/* Readline data structures. */
@@ -160,6 +160,7 @@ extern int rl_kill_line PARAMS((int, int));
extern int rl_backward_kill_line PARAMS((int, int));
extern int rl_kill_full_line PARAMS((int, int));
extern int rl_unix_word_rubout PARAMS((int, int));
+extern int rl_unix_filename_rubout PARAMS((int, int));
extern int rl_unix_line_discard PARAMS((int, int));
extern int rl_copy_region_to_kill PARAMS((int, int));
extern int rl_kill_region PARAMS((int, int));
@@ -258,6 +259,8 @@ extern int rl_vi_check PARAMS((void));
extern int rl_vi_domove PARAMS((int, int *));
extern int rl_vi_bracktype PARAMS((int));
+extern void rl_vi_start_inserting PARAMS((int, int, int));
+
/* VI-mode pseudo-bindable commands, used as utility functions. */
extern int rl_vi_fWord PARAMS((int, int));
extern int rl_vi_bWord PARAMS((int, int));
@@ -290,12 +293,20 @@ extern int rl_bind_key PARAMS((int, rl_command_func_t *));
extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap));
extern int rl_unbind_key PARAMS((int));
extern int rl_unbind_key_in_map PARAMS((int, Keymap));
+extern int rl_bind_key_if_unbound PARAMS((int, rl_command_func_t *));
+extern int rl_bind_key_if_unbound_in_map PARAMS((int, rl_command_func_t *, Keymap));
extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap));
extern int rl_unbind_command_in_map PARAMS((const char *, Keymap));
-extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap));
+extern int rl_bind_keyseq PARAMS((const char *, rl_command_func_t *));
+extern int rl_bind_keyseq_in_map PARAMS((const char *, rl_command_func_t *, Keymap));
+extern int rl_bind_keyseq_if_unbound PARAMS((const char *, rl_command_func_t *));
+extern int rl_bind_keyseq_if_unbound_in_map PARAMS((const char *, rl_command_func_t *, Keymap));
extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap));
extern int rl_variable_bind PARAMS((const char *, const char *));
+/* Backwards compatibility, use rl_bind_keyseq_in_map instead. */
+extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap));
+
/* Backwards compatibility, use rl_generic_bind instead. */
extern int rl_macro_bind PARAMS((const char *, const char *, Keymap));
@@ -329,7 +340,7 @@ extern void rl_set_keymap PARAMS((Keymap));
extern Keymap rl_get_keymap PARAMS((void));
/* Undocumented; used internally only. */
extern void rl_set_keymap_from_edit_mode PARAMS((void));
-extern const char *rl_get_keymap_name_from_edit_mode PARAMS((void));
+extern char *rl_get_keymap_name_from_edit_mode PARAMS((void));
/* Functions for manipulating the funmap, which maps command names to functions. */
extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *));
@@ -358,7 +369,7 @@ extern int rl_clear_message PARAMS((void));
extern int rl_reset_line_state PARAMS((void));
extern int rl_crlf PARAMS((void));
-#if (defined (__STDC__) || defined (__cplusplus)) && defined (USE_VARARGS) && defined (PREFER_STDARG)
+#if defined (USE_VARARGS) && defined (PREFER_STDARG)
extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
#else
extern int rl_message ();
@@ -384,13 +395,14 @@ extern char *rl_copy_text PARAMS((int, int));
extern void rl_prep_terminal PARAMS((int));
extern void rl_deprep_terminal PARAMS((void));
extern void rl_tty_set_default_bindings PARAMS((Keymap));
+extern void rl_tty_unset_default_bindings PARAMS((Keymap));
extern int rl_reset_terminal PARAMS((const char *));
extern void rl_resize_terminal PARAMS((void));
extern void rl_set_screen_size PARAMS((int, int));
extern void rl_get_screen_size PARAMS((int *, int *));
-extern const char *rl_get_termcap PARAMS((const char *));
+extern char *rl_get_termcap PARAMS((const char *));
/* Functions for character input. */
extern int rl_stuff_char PARAMS((int));
@@ -603,7 +615,12 @@ extern const char *rl_basic_word_break_characters;
/* The list of characters that signal a break between words for
rl_complete_internal. The default list is the contents of
rl_basic_word_break_characters. */
-extern const char *rl_completer_word_break_characters;
+extern /*const*/ char *rl_completer_word_break_characters;
+
+/* Hook function to allow an application to set the completion word
+ break characters before readline breaks up the line. Allows
+ position-dependent word break characters. */
+extern rl_cpvfunc_t *rl_completion_word_break_hook;
/* List of characters which can be used to quote a substring of the line.
Completion occurs on the entire substring, and within the substring
@@ -687,6 +704,11 @@ extern int rl_attempted_completion_over;
functions. */
extern int rl_completion_type;
+/* Up to this many items will be displayed in response to a
+ possible-completions call. After that, we ask the user if she
+ is sure she wants to see them all. The default value is 100. */
+extern int rl_completion_query_items;
+
/* Character appended to completed words when at the end of the line. The
default is a space. Nothing is added if this is '\0'. */
extern int rl_completion_append_character;
@@ -695,10 +717,18 @@ extern int rl_completion_append_character;
rl_completion_append_character will not be appended. */
extern int rl_completion_suppress_append;
-/* Up to this many items will be displayed in response to a
- possible-completions call. After that, we ask the user if she
- is sure she wants to see them all. The default value is 100. */
-extern int rl_completion_query_items;
+/* Set to any quote character readline thinks it finds before any application
+ completion function is called. */
+extern int rl_completion_quote_character;
+
+/* Set to a non-zero value if readline found quoting anywhere in the word to
+ be completed; set before any application completion function is called. */
+extern int rl_completion_found_quote;
+
+/* If non-zero, the completion functions don't append any closing quote.
+ This is set to 0 by rl_complete_internal and may be changed by an
+ application-specific completion function. */
+extern int rl_completion_suppress_quote;
/* If non-zero, a slash will be appended to completed filenames that are
symbolic links to directory names, subject to the value of the
@@ -749,6 +779,7 @@ extern int rl_inhibit_completion;
#define RL_STATE_SIGHANDLER 0x08000 /* in readline sighandler */
#define RL_STATE_UNDOING 0x10000 /* doing an undo */
#define RL_STATE_INPUTPENDING 0x20000 /* rl_execute_next called */
+#define RL_STATE_TTYCSAVED 0x40000 /* tty special chars saved */
#define RL_STATE_DONE 0x80000 /* done; accepted line */
@@ -785,6 +816,12 @@ struct readline_state {
int catchsigs;
int catchsigwinch;
+ /* search state */
+
+ /* completion state */
+
+ /* options state */
+
/* reserved for future expansion, so the struct size doesn't change */
char reserved[64];
};
diff --git a/cmd-line-utils/readline/rldefs.h b/cmd-line-utils/readline/rldefs.h
index 5cba9a5ac32..0d600407b5f 100644
--- a/cmd-line-utils/readline/rldefs.h
+++ b/cmd-line-utils/readline/rldefs.h
@@ -32,10 +32,6 @@
#include "rlstdc.h"
-#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ <8)
-#define __attribute__(A)
-#endif
-
#if defined (_POSIX_VERSION) && !defined (TERMIOS_MISSING)
# define TERMIOS_TTY_DRIVER
#else
@@ -81,7 +77,7 @@ extern int _rl_stricmp PARAMS((char *, char *));
extern int _rl_strnicmp PARAMS((char *, char *, int));
#endif
-#if defined (HAVE_STRPBRK)
+#if defined (HAVE_STRPBRK) && !defined (HAVE_MULTIBYTE)
# define _rl_strpbrk(a,b) strpbrk((a),(b))
#else
extern char *_rl_strpbrk PARAMS((const char *, const char *));
diff --git a/cmd-line-utils/readline/rlmbutil.h b/cmd-line-utils/readline/rlmbutil.h
index 4660a72fce5..77cc026e3e8 100644
--- a/cmd-line-utils/readline/rlmbutil.h
+++ b/cmd-line-utils/readline/rlmbutil.h
@@ -35,11 +35,18 @@
#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
# include <wchar.h>
# include <wctype.h>
-# if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
+# if defined (HAVE_MBSRTOWCS) && defined (HAVE_MBRTOWC) && defined (HAVE_MBRLEN) && defined (HAVE_WCWIDTH)
+ /* system is supposed to support XPG5 */
# define HANDLE_MULTIBYTE 1
# endif
#endif
+/* If we don't want multibyte chars even on a system that supports them, let
+ the configuring user turn multibyte support off. */
+#if defined (NO_MULTIBYTE_SUPPORT)
+# undef HANDLE_MULTIBYTE
+#endif
+
/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
# define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
@@ -82,14 +89,17 @@ extern int _rl_find_next_mbchar PARAMS((char *, int, int, int));
#ifdef HANDLE_MULTIBYTE
extern int _rl_compare_chars PARAMS((char *, int, mbstate_t *, char *, int, mbstate_t *));
-extern int _rl_get_char_len PARAMS((const char *, mbstate_t *));
-extern int _rl_adjust_point PARAMS((const char *, int, mbstate_t *));
+extern int _rl_get_char_len PARAMS((char *, mbstate_t *));
+extern int _rl_adjust_point PARAMS((char *, int, mbstate_t *));
extern int _rl_read_mbchar PARAMS((char *, int));
extern int _rl_read_mbstring PARAMS((int, char *, int));
extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
+#define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
+#define MB_NULLWCH(x) ((x) == 0)
+
#else /* !HANDLE_MULTIBYTE */
#undef MB_LEN_MAX
@@ -101,6 +111,9 @@ extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
#define _rl_find_prev_mbchar(b, i, f) (((i) == 0) ? (i) : ((i) - 1))
#define _rl_find_next_mbchar(b, i1, i2, f) ((i1) + (i2))
+#define MB_INVALIDCH(x) (0)
+#define MB_NULLWCH(x) (0)
+
#endif /* !HANDLE_MULTIBYTE */
extern int rl_byte_oriented;
diff --git a/cmd-line-utils/readline/rlprivate.h b/cmd-line-utils/readline/rlprivate.h
index 36645fb4a65..c3cee917b76 100644
--- a/cmd-line-utils/readline/rlprivate.h
+++ b/cmd-line-utils/readline/rlprivate.h
@@ -1,7 +1,7 @@
/* rlprivate.h -- functions and variables global to the readline library,
but not intended for use by applications. */
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -73,7 +73,7 @@ extern int rl_set_retained_kills PARAMS((int));
extern void _rl_set_screen_size PARAMS((int, int));
/* undo.c */
-extern int _rl_fix_last_undo_of_type PARAMS((unsigned int, int, int));
+extern int _rl_fix_last_undo_of_type PARAMS((int, int, int));
/* util.c */
extern char *_rl_savestring PARAMS((const char *));
@@ -103,7 +103,6 @@ extern int readline_internal_char PARAMS((void));
#endif /* READLINE_CALLBACKS */
/* bind.c */
-extern void _rl_bind_if_unbound PARAMS((const char *, rl_command_func_t *));
/* complete.c */
extern char _rl_find_completion_word PARAMS((int *, int *));
@@ -131,6 +130,7 @@ extern int _rl_input_available PARAMS((void));
extern int _rl_input_queued PARAMS((int));
extern void _rl_insert_typein PARAMS((int));
extern int _rl_unget_char PARAMS((int));
+extern int _rl_pushed_input_available PARAMS((void));
/* macro.c */
extern void _rl_with_macro_input PARAMS((char *));
@@ -219,6 +219,7 @@ extern const char *_rl_possible_meta_prefixes[];
/* complete.c */
extern int _rl_complete_show_all;
+extern int _rl_complete_show_unmodified;
extern int _rl_complete_mark_directories;
extern int _rl_complete_mark_symlink_dirs;
extern int _rl_print_completions_horizontally;
@@ -230,7 +231,7 @@ extern int _rl_page_completions;
extern int _rl_vis_botlin;
extern int _rl_last_c_pos;
extern int _rl_suppress_redisplay;
-extern const char *rl_display_prompt;
+extern char *rl_display_prompt;
/* isearch.c */
extern char *_rl_isearch_terminators;
@@ -261,16 +262,16 @@ extern procenv_t readline_top_level;
/* terminal.c */
extern int _rl_enable_keypad;
extern int _rl_enable_meta;
-extern const char *_rl_term_clreol;
-extern const char *_rl_term_clrpag;
-extern const char *_rl_term_im;
-extern const char *_rl_term_ic;
-extern const char *_rl_term_ei;
-extern const char *_rl_term_DC;
-extern const char *_rl_term_up;
-extern const char *_rl_term_dc;
-extern const char *_rl_term_cr;
-extern const char *_rl_term_IC;
+extern char *_rl_term_clreol;
+extern char *_rl_term_clrpag;
+extern char *_rl_term_im;
+extern char *_rl_term_ic;
+extern char *_rl_term_ei;
+extern char *_rl_term_DC;
+extern char *_rl_term_up;
+extern char *_rl_term_dc;
+extern char *_rl_term_cr;
+extern char *_rl_term_IC;
extern int _rl_screenheight;
extern int _rl_screenwidth;
extern int _rl_screenchars;
@@ -281,4 +282,7 @@ extern int _rl_term_autowrap;
extern int _rl_doing_an_undo;
extern int _rl_undo_group_level;
+/* vi_mode.c */
+extern int _rl_vi_last_command;
+
#endif /* _RL_PRIVATE_H_ */
diff --git a/cmd-line-utils/readline/rlstdc.h b/cmd-line-utils/readline/rlstdc.h
index d6a22b3742c..847fa9c26f4 100644
--- a/cmd-line-utils/readline/rlstdc.h
+++ b/cmd-line-utils/readline/rlstdc.h
@@ -37,7 +37,7 @@
#endif
#ifndef __attribute__
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
# define __attribute__(x)
# endif
#endif
diff --git a/cmd-line-utils/readline/rltty.c b/cmd-line-utils/readline/rltty.c
index 9a2cef4b279..3e9c71c8df1 100644
--- a/cmd-line-utils/readline/rltty.c
+++ b/cmd-line-utils/readline/rltty.c
@@ -184,6 +184,8 @@ static int set_tty_settings PARAMS((int, TIOTYPE *));
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+
static void
save_tty_chars (tiop)
TIOTYPE *tiop;
@@ -398,6 +400,9 @@ static int set_tty_settings PARAMS((int, TIOTYPE *));
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
+
#if defined (FLUSHO)
# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
#else
@@ -650,7 +655,10 @@ rl_prep_terminal (meta_flag)
otio = tio;
+ rl_tty_unset_default_bindings (_rl_keymap);
save_tty_chars (&otio);
+ RL_SETSTATE(RL_STATE_TTYCSAVED);
+ _rl_bind_tty_special_chars (_rl_keymap, tio);
prepare_terminal_settings (meta_flag, otio, &tio);
@@ -709,7 +717,7 @@ rl_deprep_terminal ()
int
rl_restart_output (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
int fildes = fileno (rl_outstream);
#if defined (TIOCSTART)
@@ -742,7 +750,7 @@ rl_restart_output (count, key)
int
rl_stop_output (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
int fildes = fileno (rl_instream);
@@ -774,70 +782,97 @@ rl_stop_output (count, key)
/* */
/* **************************************************************** */
-/* Set the system's default editing characters to their readline equivalents
- in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */
-void
-rltty_set_default_bindings (kmap)
- Keymap kmap;
-{
- TIOTYPE ttybuff;
- int tty = fileno (rl_instream);
+#define SET_SPECIAL(sc, func) set_special_char(kmap, &ttybuff, sc, func)
#if defined (NEW_TTY_DRIVER)
+static void
+set_special_char (kmap, tiop, sc, func)
+ Keymap kmap;
+ TIOTYPE *tiop;
+ int sc;
+ rl_command_func_t *func;
+{
+ if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC)
+ kmap[(unsigned char)sc].function = func;
+}
-#define SET_SPECIAL(sc, func) \
- do \
- { \
- int ic; \
- ic = sc; \
- if (ic != -1 && kmap[(unsigned char)ic].type == ISFUNC) \
- kmap[(unsigned char)ic].function = func; \
- } \
- while (0)
+#define RESET_SPECIAL(c) \
+ if (c != -1 && kmap[(unsigned char)c].type == ISFUNC)
+ kmap[(unsigned char)c].function = rl_insert;
- if (get_tty_settings (tty, &ttybuff) == 0)
+static void
+_rl_bind_tty_special_chars (kmap, ttybuff)
+ Keymap kmap;
+ TIOTYPE ttybuff;
+{
+ if (ttybuff.flags & SGTTY_SET)
{
- if (ttybuff.flags & SGTTY_SET)
- {
- SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
- SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
- }
+ SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
+ SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
+ }
# if defined (TIOCGLTC)
- if (ttybuff.flags & LTCHARS_SET)
- {
- SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
- SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
- }
-# endif /* TIOCGLTC */
+ if (ttybuff.flags & LTCHARS_SET)
+ {
+ SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
+ SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
}
+# endif /* TIOCGLTC */
+}
#else /* !NEW_TTY_DRIVER */
+static void
+set_special_char (kmap, tiop, sc, func)
+ Keymap kmap;
+ TIOTYPE *tiop;
+ int sc;
+ rl_command_func_t *func;
+{
+ unsigned char uc;
-#define SET_SPECIAL(sc, func) \
- do \
- { \
- unsigned char uc; \
- uc = ttybuff.c_cc[sc]; \
- if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
- kmap[uc].function = func; \
- } \
- while (0)
+ uc = tiop->c_cc[sc];
+ if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC)
+ kmap[uc].function = func;
+}
- if (get_tty_settings (tty, &ttybuff) == 0)
- {
- SET_SPECIAL (VERASE, rl_rubout);
- SET_SPECIAL (VKILL, rl_unix_line_discard);
+/* used later */
+#define RESET_SPECIAL(uc) \
+ if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
+ kmap[uc].function = rl_insert;
+
+static void
+_rl_bind_tty_special_chars (kmap, ttybuff)
+ Keymap kmap;
+ TIOTYPE ttybuff;
+{
+ SET_SPECIAL (VERASE, rl_rubout);
+ SET_SPECIAL (VKILL, rl_unix_line_discard);
# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
- SET_SPECIAL (VLNEXT, rl_quoted_insert);
+ SET_SPECIAL (VLNEXT, rl_quoted_insert);
# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
- SET_SPECIAL (VWERASE, rl_unix_word_rubout);
+ SET_SPECIAL (VWERASE, rl_unix_word_rubout);
# endif /* VWERASE && TERMIOS_TTY_DRIVER */
- }
+}
+
#endif /* !NEW_TTY_DRIVER */
+
+/* Set the system's default editing characters to their readline equivalents
+ in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */
+void
+rltty_set_default_bindings (kmap)
+ Keymap kmap;
+{
+ TIOTYPE ttybuff;
+ int tty;
+ static int called = 0;
+
+ tty = fileno (rl_instream);
+
+ if (get_tty_settings (tty, &ttybuff) == 0)
+ _rl_bind_tty_special_chars (kmap, ttybuff);
}
/* New public way to set the system default editing chars to their readline
@@ -849,6 +884,30 @@ rl_tty_set_default_bindings (kmap)
rltty_set_default_bindings (kmap);
}
+/* Rebind all of the tty special chars that readline worries about back
+ to self-insert. Call this before saving the current terminal special
+ chars with save_tty_chars(). This only works on POSIX termios or termio
+ systems. */
+void
+rl_tty_unset_default_bindings (kmap)
+ Keymap kmap;
+{
+ /* Don't bother before we've saved the tty special chars at least once. */
+ if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0)
+ return;
+
+ RESET_SPECIAL (_rl_tty_chars.t_erase);
+ RESET_SPECIAL (_rl_tty_chars.t_kill);
+
+# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+ RESET_SPECIAL (_rl_tty_chars.t_lnext);
+# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+ RESET_SPECIAL (_rl_tty_chars.t_werase);
+# endif /* VWERASE && TERMIOS_TTY_DRIVER */
+}
+
#if defined (HANDLE_SIGNALS)
#if defined (NEW_TTY_DRIVER)
diff --git a/cmd-line-utils/readline/rltty.h b/cmd-line-utils/readline/rltty.h
index 029a3fbc0e1..142e96b6a64 100644
--- a/cmd-line-utils/readline/rltty.h
+++ b/cmd-line-utils/readline/rltty.h
@@ -61,22 +61,22 @@
#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
typedef struct _rl_tty_chars {
- char t_eof;
- char t_eol;
- char t_eol2;
- char t_erase;
- char t_werase;
- char t_kill;
- char t_reprint;
- char t_intr;
- char t_quit;
- char t_susp;
- char t_dsusp;
- char t_start;
- char t_stop;
- char t_lnext;
- char t_flush;
- char t_status;
+ unsigned char t_eof;
+ unsigned char t_eol;
+ unsigned char t_eol2;
+ unsigned char t_erase;
+ unsigned char t_werase;
+ unsigned char t_kill;
+ unsigned char t_reprint;
+ unsigned char t_intr;
+ unsigned char t_quit;
+ unsigned char t_susp;
+ unsigned char t_dsusp;
+ unsigned char t_start;
+ unsigned char t_stop;
+ unsigned char t_lnext;
+ unsigned char t_flush;
+ unsigned char t_status;
} _RL_TTY_CHARS;
#endif /* _RLTTY_H_ */
diff --git a/cmd-line-utils/readline/rltypedefs.h b/cmd-line-utils/readline/rltypedefs.h
index f3280e9fce0..862bdb8e4d9 100644
--- a/cmd-line-utils/readline/rltypedefs.h
+++ b/cmd-line-utils/readline/rltypedefs.h
@@ -1,6 +1,6 @@
/* rltypedefs.h -- Type declarations for readline functions. */
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -79,6 +79,12 @@ typedef void rl_voidfunc_t PARAMS((void));
typedef void rl_vintfunc_t PARAMS((int));
typedef void rl_vcpfunc_t PARAMS((char *));
typedef void rl_vcppfunc_t PARAMS((char **));
+
+typedef char *rl_cpvfunc_t PARAMS((void));
+typedef char *rl_cpifunc_t PARAMS((int));
+typedef char *rl_cpcpfunc_t PARAMS((char *));
+typedef char *rl_cpcppfunc_t PARAMS((char **));
+
#endif /* _RL_FUNCTION_TYPEDEF */
#ifdef __cplusplus
diff --git a/cmd-line-utils/readline/savestring.c b/cmd-line-utils/readline/savestring.c
new file mode 100644
index 00000000000..ae605374d13
--- /dev/null
+++ b/cmd-line-utils/readline/savestring.c
@@ -0,0 +1,38 @@
+/* savestring.c */
+
+/* Copyright (C) 1998,2003 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library, a library for
+ reading lines of text with interactive input and history editing.
+
+ The GNU Readline Library 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, or
+ (at your option) any later version.
+
+ The GNU Readline Library 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.
+
+ The GNU General Public License is often shipped with GNU software, and
+ is generally kept in a file called COPYING or LICENSE. If you do not
+ have a copy of the license, write to the Free Software Foundation,
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#include "config_readline.h"
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#include "xmalloc.h"
+
+/* Backwards compatibility, now that savestring has been removed from
+ all `public' readline header files. */
+char *
+savestring (s)
+ const char *s;
+{
+ return ((char *)strcpy ((char *)xmalloc (1 + strlen (s)), (s)));
+}
diff --git a/cmd-line-utils/readline/search.c b/cmd-line-utils/readline/search.c
index 637534924f1..1878d2bf031 100644
--- a/cmd-line-utils/readline/search.c
+++ b/cmd-line-utils/readline/search.c
@@ -80,8 +80,13 @@ static void
make_history_line_current (entry)
HIST_ENTRY *entry;
{
- rl_replace_line (entry->line, 0);
+#if 0
+ rl_replace_line (entry->line, 1);
rl_undo_list = (UNDO_LIST *)entry->data;
+#else
+ _rl_replace_text (entry->line, 0, rl_end);
+ _rl_fix_point (1);
+#endif
if (_rl_saved_line_for_history)
_rl_free_history_entry (_rl_saved_line_for_history);
@@ -187,6 +192,11 @@ noninc_search (dir, pchar)
saved_point = rl_point;
saved_mark = rl_mark;
+ /* Clear the undo list, since reading the search string should create its
+ own undo list, and the whole list will end up being freed when we
+ finish reading the search string. */
+ rl_undo_list = 0;
+
/* Use the line buffer to read the search string. */
rl_line_buffer[0] = 0;
rl_end = rl_point = 0;
@@ -294,7 +304,7 @@ noninc_search (dir, pchar)
code calls this, KEY will be `?'. */
int
rl_noninc_forward_search (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
noninc_search (1, (key == '?') ? '?' : 0);
return 0;
@@ -304,7 +314,7 @@ rl_noninc_forward_search (count, key)
calls this, KEY will be `/'. */
int
rl_noninc_reverse_search (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
noninc_search (-1, (key == '/') ? '/' : 0);
return 0;
@@ -314,7 +324,7 @@ rl_noninc_reverse_search (count, key)
for. If there is no saved search string, abort. */
int
rl_noninc_forward_search_again (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
if (!noninc_search_string)
{
@@ -329,7 +339,7 @@ rl_noninc_forward_search_again (count, key)
for. If there is no saved search string, abort. */
int
rl_noninc_reverse_search_again (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
if (!noninc_search_string)
{
diff --git a/cmd-line-utils/readline/shell.c b/cmd-line-utils/readline/shell.c
index fd6a2816309..41668d70ab5 100644
--- a/cmd-line-utils/readline/shell.c
+++ b/cmd-line-utils/readline/shell.c
@@ -124,6 +124,7 @@ sh_set_lines_and_columns (lines, cols)
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1);
sprintf (b, "LINES=%d", lines);
putenv (b);
+
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1);
sprintf (b, "COLUMNS=%d", cols);
putenv (b);
@@ -132,9 +133,12 @@ sh_set_lines_and_columns (lines, cols)
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
sprintf (b, "%d", lines);
setenv ("LINES", b, 1);
+ free (b);
+
b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1);
sprintf (b, "%d", cols);
setenv ("COLUMNS", b, 1);
+ free (b);
# endif /* HAVE_SETENV */
#endif /* !HAVE_PUTENV */
}
diff --git a/cmd-line-utils/readline/signals.c b/cmd-line-utils/readline/signals.c
index 4609598ff98..be1150f6c54 100644
--- a/cmd-line-utils/readline/signals.c
+++ b/cmd-line-utils/readline/signals.c
@@ -71,6 +71,10 @@ typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt
# define sigemptyset(m)
#endif /* !HAVE_POSIX_SIGNALS */
+#ifndef SA_RESTART
+# define SA_RESTART 0
+#endif
+
static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
@@ -83,6 +87,8 @@ int rl_catch_signals = 1;
/* If non-zero, readline will install a signal handler for SIGWINCH. */
#ifdef SIGWINCH
int rl_catch_sigwinch = 1;
+#else
+int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
#endif
static int signals_set_flag;
@@ -231,7 +237,7 @@ rl_set_sighandler (sig, handler, ohandler)
struct sigaction act;
act.sa_handler = handler;
- act.sa_flags = 0; /* XXX - should we set SA_RESTART for SIGWINCH? */
+ act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
sigemptyset (&act.sa_mask);
sigemptyset (&ohandler->sa_mask);
sigaction (sig, &act, &old_handler);
diff --git a/cmd-line-utils/readline/terminal.c b/cmd-line-utils/readline/terminal.c
index b2bcf5f146c..3545fce5b85 100644
--- a/cmd-line-utils/readline/terminal.c
+++ b/cmd-line-utils/readline/terminal.c
@@ -82,41 +82,40 @@ static int tcap_initialized;
# if defined (__EMX__) || defined (NEED_EXTERN_PC)
extern
# endif /* __EMX__ || NEED_EXTERN_PC */
-char PC;
-char *BC, *UP;
+char PC, *BC, *UP;
#endif /* __linux__ */
/* Some strings to control terminal actions. These are output by tputs (). */
-const char *_rl_term_clreol;
-const char *_rl_term_clrpag;
-const char *_rl_term_cr;
-const char *_rl_term_backspace;
-const char *_rl_term_goto;
-const char *_rl_term_pc;
+char *_rl_term_clreol;
+char *_rl_term_clrpag;
+char *_rl_term_cr;
+char *_rl_term_backspace;
+char *_rl_term_goto;
+char *_rl_term_pc;
/* Non-zero if we determine that the terminal can do character insertion. */
int _rl_terminal_can_insert = 0;
/* How to insert characters. */
-const char *_rl_term_im;
-const char *_rl_term_ei;
-const char *_rl_term_ic;
-const char *_rl_term_ip;
-const char *_rl_term_IC;
+char *_rl_term_im;
+char *_rl_term_ei;
+char *_rl_term_ic;
+char *_rl_term_ip;
+char *_rl_term_IC;
/* How to delete characters. */
-const char *_rl_term_dc;
-const char *_rl_term_DC;
+char *_rl_term_dc;
+char *_rl_term_DC;
#if defined (HACK_TERMCAP_MOTION)
char *_rl_term_forward_char;
#endif /* HACK_TERMCAP_MOTION */
/* How to go up a line. */
-const char *_rl_term_up;
+char *_rl_term_up;
/* A visible bell; char if the terminal can be made to flash the screen. */
-static const char *_rl_visible_bell;
+static char *_rl_visible_bell;
/* Non-zero means the terminal can auto-wrap lines. */
int _rl_term_autowrap;
@@ -126,30 +125,30 @@ static int term_has_meta;
/* The sequences to write to turn on and off the meta key, if this
terminal has one. */
-static const char *_rl_term_mm;
-static const char *_rl_term_mo;
+static char *_rl_term_mm;
+static char *_rl_term_mo;
/* The key sequences output by the arrow keys, if this terminal has any. */
-static const char *_rl_term_ku;
-static const char *_rl_term_kd;
-static const char *_rl_term_kr;
-static const char *_rl_term_kl;
+static char *_rl_term_ku;
+static char *_rl_term_kd;
+static char *_rl_term_kr;
+static char *_rl_term_kl;
/* How to initialize and reset the arrow keys, if this terminal has any. */
-static const char *_rl_term_ks;
-static const char *_rl_term_ke;
+static char *_rl_term_ks;
+static char *_rl_term_ke;
/* The key sequences sent by the Home and End keys, if any. */
-static const char *_rl_term_kh;
-static const char *_rl_term_kH;
-static const char *_rl_term_at7; /* @7 */
+static char *_rl_term_kh;
+static char *_rl_term_kH;
+static char *_rl_term_at7; /* @7 */
/* Insert key */
-static const char *_rl_term_kI;
+static char *_rl_term_kI;
/* Cursor control */
-static const char *_rl_term_vs; /* very visible */
-static const char *_rl_term_ve; /* normal */
+static char *_rl_term_vs; /* very visible */
+static char *_rl_term_ve; /* normal */
static void bind_termcap_arrow_keys PARAMS((Keymap));
@@ -295,7 +294,7 @@ rl_resize_terminal ()
struct _tc_string {
const char *tc_var;
- const char **tc_value;
+ char **tc_value;
};
/* This should be kept sorted, just in case we decide to change the
@@ -343,14 +342,10 @@ get_term_capabilities (bp)
char **bp;
{
#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
- register unsigned int i;
+ register int i;
for (i = 0; i < NUM_TC_STRINGS; i++)
-# if defined(__LCC__) || defined(__MWERKS__)
*(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
-# else
- *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
-# endif
#endif
tcap_initialized = 1;
}
@@ -432,8 +427,8 @@ _rl_init_terminal_io (terminal_name)
tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
change that later... */
PC = '\0';
- BC = (char*)(_rl_term_backspace = "\b");
- UP = (char*)_rl_term_up;
+ BC = _rl_term_backspace = "\b";
+ UP = _rl_term_up;
return 0;
}
@@ -443,8 +438,8 @@ _rl_init_terminal_io (terminal_name)
/* Set up the variables that the termcap library expects the application
to provide. */
PC = _rl_term_pc ? *_rl_term_pc : 0;
- BC = (char*)_rl_term_backspace;
- UP = (char*)_rl_term_up;
+ BC = _rl_term_backspace;
+ UP = _rl_term_up;
if (!_rl_term_cr)
_rl_term_cr = "\r";
@@ -488,22 +483,22 @@ bind_termcap_arrow_keys (map)
xkeymap = _rl_keymap;
_rl_keymap = map;
- _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
- _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
- _rl_bind_if_unbound (_rl_term_kr, rl_forward);
- _rl_bind_if_unbound (_rl_term_kl, rl_backward);
+ rl_bind_keyseq_if_unbound (_rl_term_ku, rl_get_previous_history);
+ rl_bind_keyseq_if_unbound (_rl_term_kd, rl_get_next_history);
+ rl_bind_keyseq_if_unbound (_rl_term_kr, rl_forward_char);
+ rl_bind_keyseq_if_unbound (_rl_term_kl, rl_backward_char);
- _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
- _rl_bind_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
+ rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
+ rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
_rl_keymap = xkeymap;
}
-const char *
+char *
rl_get_termcap (cap)
const char *cap;
{
- register unsigned int i;
+ register int i;
if (tcap_initialized == 0)
return ((char *)NULL);
diff --git a/cmd-line-utils/readline/text.c b/cmd-line-utils/readline/text.c
index d98b266edfe..ad7b53ec422 100644
--- a/cmd-line-utils/readline/text.c
+++ b/cmd-line-utils/readline/text.c
@@ -1,6 +1,6 @@
/* text.c -- text handling commands for readline. */
-/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -168,6 +168,9 @@ _rl_fix_point (fix_mark_too)
}
#undef _RL_FIX_POINT
+/* Replace the contents of the line buffer between START and END with
+ TEXT. The operation is undoable. To replace the entire line in an
+ undoable mode, use _rl_replace_text(text, 0, rl_end); */
int
_rl_replace_text (text, start, end)
const char *text;
@@ -400,7 +403,7 @@ rl_backward (count, key)
/* Move to the beginning of the line. */
int
rl_beg_of_line (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
rl_point = 0;
return 0;
@@ -409,7 +412,7 @@ rl_beg_of_line (count, key)
/* Move to the end of the line. */
int
rl_end_of_line (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
rl_point = rl_end;
return 0;
@@ -506,7 +509,7 @@ rl_backward_word (count, key)
/* Clear the current line. Numeric argument to C-l does this. */
int
rl_refresh_line (ignore1, ignore2)
- int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
+ int ignore1, ignore2;
{
int curr_line;
@@ -545,7 +548,7 @@ rl_clear_screen (count, key)
int
rl_arrow_keys (count, c)
- int count, c __attribute__((unused));
+ int count, c;
{
int ch;
@@ -799,13 +802,10 @@ _rl_overwrite_char (count, c)
k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
#endif
+ rl_begin_undo_group ();
+
for (i = 0; i < count; i++)
{
- rl_begin_undo_group ();
-
- if (rl_point < rl_end)
- rl_delete (1, c);
-
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
rl_insert_text (mbkey);
@@ -813,9 +813,12 @@ _rl_overwrite_char (count, c)
#endif
_rl_insert_char (1, c);
- rl_end_undo_group ();
+ if (rl_point < rl_end)
+ rl_delete (1, c);
}
+ rl_end_undo_group ();
+
return 0;
}
@@ -830,7 +833,7 @@ rl_insert (count, c)
/* Insert the next typed character verbatim. */
int
rl_quoted_insert (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
int c;
@@ -852,7 +855,7 @@ rl_quoted_insert (count, key)
/* Insert a tab character. */
int
rl_tab_insert (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
return (_rl_insert_char (count, '\t'));
}
@@ -862,7 +865,7 @@ rl_tab_insert (count, key)
meaning in the future. */
int
rl_newline (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
rl_done = 1;
@@ -875,7 +878,8 @@ rl_newline (count, key)
if (rl_editing_mode == vi_mode)
{
_rl_vi_done_inserting ();
- _rl_vi_reset_last ();
+ if (_rl_vi_textmod_command (_rl_vi_last_command) == 0) /* XXX */
+ _rl_vi_reset_last ();
}
#endif /* VI_MODE */
@@ -895,7 +899,7 @@ rl_newline (count, key)
is special cased. */
int
rl_do_lowercase_version (ignore1, ignore2)
- int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
+ int ignore1, ignore2;
{
return 0;
}
@@ -933,9 +937,12 @@ _rl_overwrite_rubout (count, key)
rl_delete_text (opoint, rl_point);
/* Emacs puts point at the beginning of the sequence of spaces. */
- opoint = rl_point;
- _rl_insert_char (l, ' ');
- rl_point = opoint;
+ if (rl_point < rl_end)
+ {
+ opoint = rl_point;
+ _rl_insert_char (l, ' ');
+ rl_point = opoint;
+ }
rl_end_undo_group ();
@@ -1087,7 +1094,7 @@ rl_rubout_or_delete (count, key)
/* Delete all spaces and tabs around point. */
int
rl_delete_horizontal_space (count, ignore)
- int count __attribute__((unused)), ignore __attribute__((unused));
+ int count, ignore;
{
int start = rl_point;
@@ -1128,9 +1135,9 @@ rl_delete_or_show_completions (count, key)
A K*rn shell style function. */
int
rl_insert_comment (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
- const char *rl_comment_text;
+ char *rl_comment_text;
int rl_comment_len;
rl_beg_of_line (1, key);
@@ -1167,7 +1174,7 @@ rl_insert_comment (count, key)
/* Uppercase the word at point. */
int
rl_upcase_word (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
return (rl_change_case (count, UpCase));
}
@@ -1175,7 +1182,7 @@ rl_upcase_word (count, key)
/* Lowercase the word at point. */
int
rl_downcase_word (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
return (rl_change_case (count, DownCase));
}
@@ -1183,7 +1190,7 @@ rl_downcase_word (count, key)
/* Upcase the first letter, downcase the rest. */
int
rl_capitalize_word (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
return (rl_change_case (count, CapCase));
}
@@ -1308,7 +1315,7 @@ rl_transpose_words (count, key)
then transpose the characters before point. */
int
rl_transpose_chars (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
#if defined (HANDLE_MULTIBYTE)
char *dummy;
@@ -1480,14 +1487,14 @@ _rl_char_search (count, fdir, bdir)
int
rl_char_search (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
return (_rl_char_search (count, FFIND, BFIND));
}
int
rl_backward_char_search (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
return (_rl_char_search (count, BFIND, FFIND));
}
@@ -1513,7 +1520,7 @@ _rl_set_mark_at_pos (position)
/* A bindable command to set the mark. */
int
rl_set_mark (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
}
@@ -1521,7 +1528,7 @@ rl_set_mark (count, key)
/* Exchange the position of mark and point. */
int
rl_exchange_point_and_mark (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
if (rl_mark > rl_end)
rl_mark = -1;
diff --git a/cmd-line-utils/readline/tilde.c b/cmd-line-utils/readline/tilde.c
index 456a6bcb357..c44357ffbea 100644
--- a/cmd-line-utils/readline/tilde.c
+++ b/cmd-line-utils/readline/tilde.c
@@ -19,6 +19,8 @@
along with Readline; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
#include "config_readline.h"
#if defined (HAVE_UNISTD_H)
@@ -188,7 +190,7 @@ tilde_expand (string)
int result_size, result_index;
result_index = result_size = 0;
- if ((result = strchr(string, '~')))
+ if (result = strchr (string, '~'))
result = (char *)xmalloc (result_size = (strlen (string) + 16));
else
result = (char *)xmalloc (result_size = (strlen (string) + 1));
diff --git a/cmd-line-utils/readline/undo.c b/cmd-line-utils/readline/undo.c
index 947da3d00d0..48baded332a 100644
--- a/cmd-line-utils/readline/undo.c
+++ b/cmd-line-utils/readline/undo.c
@@ -169,8 +169,7 @@ rl_do_undo ()
int
_rl_fix_last_undo_of_type (type, start, end)
- unsigned int type;
- int start, end;
+ int type, start, end;
{
UNDO_LIST *rl;
@@ -228,7 +227,7 @@ rl_modifying (start, end)
/* Revert the current line to its previous state. */
int
rl_revert_line (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
if (!rl_undo_list)
rl_ding ();
@@ -243,7 +242,7 @@ rl_revert_line (count, key)
/* Do some undoing of things that were done. */
int
rl_undo_command (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
if (count < 0)
return 0; /* Nothing to do. */
diff --git a/cmd-line-utils/readline/util.c b/cmd-line-utils/readline/util.c
index 403b3d544d9..43478aaf1ac 100644
--- a/cmd-line-utils/readline/util.c
+++ b/cmd-line-utils/readline/util.c
@@ -96,14 +96,14 @@ _rl_abort_internal ()
int
rl_abort (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
return (_rl_abort_internal ());
}
int
rl_tty_status (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
#if defined (TIOCSTAT)
ioctl (1, TIOCSTAT, (char *)0);
@@ -153,7 +153,7 @@ rl_extend_line_buffer (len)
/* A function for simple tilde expansion. */
int
rl_tilde_expand (ignore, key)
- int ignore __attribute__((unused)), key __attribute__((unused));
+ int ignore, key;
{
register int start, end;
char *homedir, *temp;
@@ -248,7 +248,7 @@ _rl_strpbrk (string1, string2)
{
v = _rl_get_char_len (string1, &ps);
if (v > 1)
- string += v - 1; /* -1 to account for auto-increment in loop */
+ string1 += v - 1; /* -1 to account for auto-increment in loop */
}
#endif
}
diff --git a/cmd-line-utils/readline/vi_mode.c b/cmd-line-utils/readline/vi_mode.c
index e8ad05d866f..9a8cfdd7200 100644
--- a/cmd-line-utils/readline/vi_mode.c
+++ b/cmd-line-utils/readline/vi_mode.c
@@ -1,7 +1,7 @@
/* vi_mode.c -- A vi emulation mode for Bash.
Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -61,6 +61,8 @@
#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
#endif
+int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
+
/* Non-zero means enter insertion mode. */
static int _rl_vi_doing_insert;
@@ -81,7 +83,6 @@ static int vi_continued_command;
static char *vi_insert_buffer;
static int vi_insert_buffer_size;
-static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
static int _rl_vi_last_repeat = 1;
static int _rl_vi_last_arg_sign = 1;
static int _rl_vi_last_motion;
@@ -109,7 +110,7 @@ static int rl_digit_loop1 PARAMS((void));
void
_rl_vi_initialize_line ()
{
- register unsigned int i;
+ register int i;
for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
vi_mark_chars[i] = -1;
@@ -133,6 +134,16 @@ _rl_vi_set_last (key, repeat, sign)
_rl_vi_last_arg_sign = sign;
}
+/* A convenience function that calls _rl_vi_set_last to save the last command
+ information and enters insertion mode. */
+void
+rl_vi_start_inserting (key, repeat, sign)
+ int key, repeat, sign;
+{
+ _rl_vi_set_last (key, repeat, sign);
+ rl_vi_insertion_mode (1, key);
+}
+
/* Is the command C a VI mode text modification command? */
int
_rl_vi_textmod_command (c)
@@ -156,7 +167,7 @@ _rl_vi_stuff_insert (count)
puts you back into insert mode. */
int
rl_vi_redo (count, c)
- int count, c __attribute__((unused));
+ int count, c;
{
int r;
@@ -195,7 +206,7 @@ rl_vi_undo (count, key)
/* Yank the nth arg from the previous line into this line at point. */
int
rl_vi_yank_arg (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
/* Readline thinks that the first word on a line is the 0th, while vi
thinks the first word on a line is the 1st. Compensate. */
@@ -276,7 +287,7 @@ rl_vi_search (count, key)
/* Completion, from vi's point of view. */
int
rl_vi_complete (ignore, key)
- int ignore __attribute__((unused)), key;
+ int ignore, key;
{
if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
{
@@ -295,21 +306,18 @@ rl_vi_complete (ignore, key)
rl_complete (0, key);
if (key == '*' || key == '\\')
- {
- _rl_vi_set_last (key, 1, rl_arg_sign);
- rl_vi_insertion_mode (1, key);
- }
+ rl_vi_start_inserting (key, 1, rl_arg_sign);
+
return (0);
}
/* Tilde expansion for vi mode. */
int
rl_vi_tilde_expand (ignore, key)
- int ignore __attribute__((unused)), key;
+ int ignore, key;
{
rl_tilde_expand (0, key);
- _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */
- rl_vi_insertion_mode (1, key);
+ rl_vi_start_inserting (key, 1, rl_arg_sign);
return (0);
}
@@ -377,7 +385,7 @@ rl_vi_end_word (count, key)
/* Move forward a word the way that 'W' does. */
int
rl_vi_fWord (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -394,7 +402,7 @@ rl_vi_fWord (count, ignore)
int
rl_vi_bWord (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
while (count-- && rl_point > 0)
{
@@ -418,7 +426,7 @@ rl_vi_bWord (count, ignore)
int
rl_vi_eWord (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -427,7 +435,8 @@ rl_vi_eWord (count, ignore)
/* Move to the next non-whitespace character (to the start of the
next word). */
- while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
if (rl_point && rl_point < rl_end)
{
@@ -448,7 +457,7 @@ rl_vi_eWord (count, ignore)
int
rl_vi_fword (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -474,7 +483,7 @@ rl_vi_fword (count, ignore)
int
rl_vi_bword (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
while (count-- && rl_point > 0)
{
@@ -513,7 +522,7 @@ rl_vi_bword (count, ignore)
int
rl_vi_eword (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
while (count-- && rl_point < rl_end - 1)
{
@@ -538,7 +547,7 @@ rl_vi_eword (count, ignore)
int
rl_vi_insert_beg (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
rl_beg_of_line (1, key);
rl_vi_insertion_mode (1, key);
@@ -547,7 +556,7 @@ rl_vi_insert_beg (count, key)
int
rl_vi_append_mode (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
if (rl_point < rl_end)
{
@@ -567,7 +576,7 @@ rl_vi_append_mode (count, key)
int
rl_vi_append_eol (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
rl_end_of_line (1, key);
rl_vi_append_mode (1, key);
@@ -577,7 +586,7 @@ rl_vi_append_eol (count, key)
/* What to do in the case of C-d. */
int
rl_vi_eof_maybe (count, c)
- int count __attribute__((unused)), c __attribute__((unused));
+ int count, c;
{
return (rl_newline (1, '\n'));
}
@@ -588,7 +597,7 @@ rl_vi_eof_maybe (count, c)
switching keymaps. */
int
rl_vi_insertion_mode (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
_rl_keymap = vi_insertion_keymap;
_rl_vi_last_key_before_insert = key;
@@ -638,7 +647,7 @@ _rl_vi_done_inserting ()
}
else
{
- if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
+ if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list)
_rl_vi_save_insert (rl_undo_list);
/* XXX - Other keys probably need to be checked. */
else if (_rl_vi_last_key_before_insert == 'C')
@@ -651,7 +660,7 @@ _rl_vi_done_inserting ()
int
rl_vi_movement_mode (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
if (rl_point > 0)
rl_backward_char (1, key);
@@ -678,7 +687,8 @@ _rl_vi_change_mbchar_case (count)
int count;
{
wchar_t wc;
- char mb[MB_LEN_MAX];
+ char mb[MB_LEN_MAX+1];
+ int mblen;
mbstate_t ps;
memset (&ps, 0, sizeof (mbstate_t));
@@ -701,7 +711,9 @@ _rl_vi_change_mbchar_case (count)
/* Vi is kind of strange here. */
if (wc)
{
- wctomb (mb, wc);
+ mblen = wcrtomb (mb, wc, &ps);
+ if (mblen >= 0)
+ mb[mblen] = '\0';
rl_begin_undo_group ();
rl_delete (1, 0);
rl_insert_text (mb);
@@ -718,14 +730,15 @@ _rl_vi_change_mbchar_case (count)
int
rl_vi_change_case (count, ignore)
- int count, ignore __attribute__((unused));
+ int count, ignore;
{
- char c = 0;
+ int c, p;
/* Don't try this on an empty line. */
if (rl_point >= rl_end)
return (0);
+ c = 0;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
return (_rl_vi_change_mbchar_case (count));
@@ -747,8 +760,11 @@ rl_vi_change_case (count, ignore)
/* Vi is kind of strange here. */
if (c)
{
+ p = rl_point;
rl_begin_undo_group ();
- rl_delete (1, c);
+ rl_vi_delete (1, c);
+ if (rl_point < p) /* Did we retreat at EOL? */
+ rl_point++;
_rl_insert_char (1, c);
rl_end_undo_group ();
rl_vi_check ();
@@ -761,12 +777,14 @@ rl_vi_change_case (count, ignore)
int
rl_vi_put (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
- rl_yank (1, key);
+ while (count--)
+ rl_yank (1, key);
+
rl_backward_char (1, key);
return (0);
}
@@ -814,6 +832,7 @@ rl_vi_domove (key, nextkey)
{
save = rl_numeric_arg;
rl_numeric_arg = _rl_digit_value (c);
+ rl_explicit_arg = 1;
rl_digit_loop1 ();
rl_numeric_arg *= save;
RL_SETSTATE(RL_STATE_MOREINPUT);
@@ -941,7 +960,7 @@ rl_digit_loop1 ()
int
rl_vi_delete_to (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
int c;
@@ -1012,8 +1031,7 @@ rl_vi_change_to (count, key)
/* `C' does not save the text inserted for undoing or redoing. */
if (_rl_uppercase_p (key) == 0)
_rl_vi_doing_insert = 1;
- _rl_vi_set_last (key, count, rl_arg_sign);
- rl_vi_insertion_mode (1, key);
+ rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign);
}
return (0);
@@ -1021,7 +1039,7 @@ rl_vi_change_to (count, key)
int
rl_vi_yank_to (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
int c, save = rl_point;
@@ -1077,7 +1095,7 @@ rl_vi_delete (count, key)
int
rl_vi_back_to_indent (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
rl_beg_of_line (1, key);
while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
@@ -1087,7 +1105,7 @@ rl_vi_back_to_indent (count, key)
int
rl_vi_first_print (count, key)
- int count __attribute__((unused)), key;
+ int count, key;
{
return (rl_vi_back_to_indent (1, key));
}
@@ -1156,7 +1174,7 @@ rl_vi_char_search (count, key)
/* Match brackets */
int
rl_vi_match (ignore, key)
- int ignore __attribute__((unused)), key;
+ int ignore, key;
{
int count = 1, brack, pos, tmp, pre;
@@ -1262,14 +1280,14 @@ rl_vi_bracktype (c)
/* XXX - think about reading an entire mbchar with _rl_read_mbchar and
inserting it in one bunch instead of the loop below (like in
- rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0]
+ rl_vi_char_search or _rl_vi_change_mbchar_case). Set c to mbchar[0]
for test against 033 or ^C. Make sure that _rl_read_mbchar does
this right. */
int
rl_vi_change_char (count, key)
- int count, key __attribute__((unused));
+ int count, key;
{
- int c;
+ int c, p;
if (vi_redoing)
c = _rl_vi_last_replacement;
@@ -1283,11 +1301,11 @@ rl_vi_change_char (count, key)
if (c == '\033' || c == CTRL ('C'))
return -1;
+ rl_begin_undo_group ();
while (count-- && rl_point < rl_end)
{
- rl_begin_undo_group ();
-
- rl_delete (1, c);
+ p = rl_point;
+ rl_vi_delete (1, c);
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
while (_rl_insert_char (1, c))
@@ -1298,12 +1316,14 @@ rl_vi_change_char (count, key)
}
else
#endif
- _rl_insert_char (1, c);
- if (count == 0)
- rl_backward_char (1, c);
-
- rl_end_undo_group ();
+ {
+ if (rl_point < p) /* Did we retreat at EOL? */
+ rl_point++;
+ _rl_insert_char (1, c);
+ }
}
+ rl_end_undo_group ();
+
return (0);
}
@@ -1313,7 +1333,7 @@ rl_vi_subst (count, key)
{
/* If we are redoing, rl_vi_change_to will stuff the last motion char */
if (vi_redoing == 0)
- rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */
+ rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
return (rl_vi_change_to (count, 'c'));
}
@@ -1370,7 +1390,7 @@ rl_vi_overstrike_delete (count, key)
int
rl_vi_replace (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
int i;
@@ -1431,7 +1451,7 @@ rl_vi_possible_completions()
/* Functions to save and restore marks. */
int
rl_vi_set_mark (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
int ch;
@@ -1451,7 +1471,7 @@ rl_vi_set_mark (count, key)
int
rl_vi_goto_mark (count, key)
- int count __attribute__((unused)), key __attribute__((unused));
+ int count, key;
{
int ch;
diff --git a/config.guess b/config.guess
deleted file mode 100755
index ef65f9b4ea9..00000000000
--- a/config.guess
+++ /dev/null
@@ -1,1416 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-
-timestamp='2003-07-02'
-
-# This file 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.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Originally written by Per Bothner <per@bothner.com>.
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
-#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit build system type.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit 0 ;;
- --version | -v )
- echo "$version" ; exit 0 ;;
- --help | --h* | -h )
- echo "$usage"; exit 0 ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help" >&2
- exit 1 ;;
- * )
- break ;;
- esac
-done
-
-if test $# != 0; then
- echo "$me: too many arguments$help" >&2
- exit 1
-fi
-
-trap 'exit 1' 1 2 15
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ;'
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
- PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-case "${UNAME_MACHINE}" in
- i?86)
- test -z "$VENDOR" && VENDOR=pc
- ;;
- *)
- test -z "$VENDOR" && VENDOR=unknown
- ;;
-esac
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- *:NetBSD:*:*)
- # NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
- # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
- # switched to ELF, *-*-netbsd* would select the old
- # object file format. This provides both forward
- # compatibility and a consistent mechanism for selecting the
- # object file format.
- #
- # Note: NetBSD doesn't particularly care about the vendor
- # portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
- armeb) machine=armeb-unknown ;;
- arm*) machine=arm-unknown ;;
- sh3el) machine=shl-unknown ;;
- sh3eb) machine=sh-unknown ;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
- esac
- # The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
- case "${UNAME_MACHINE_ARCH}" in
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep __ELF__ >/dev/null
- then
- # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
- # Return netbsd for either. FIX?
- os=netbsd
- else
- os=netbsdelf
- fi
- ;;
- *)
- os=netbsd
- ;;
- esac
- # The OS release
- # Debian GNU/NetBSD machines have a different userland, and
- # thus, need a distinct triplet. However, they do not need
- # kernel version information, so it can be replaced with a
- # suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
- Debian*)
- release='-gnu'
- ;;
- *)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
- ;;
- esac
- # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
- # contains redundant information, the shorter form:
- # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
- exit 0 ;;
- amiga:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- arc:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- hp300:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mac68k:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- macppc:OpenBSD:*:*)
- echo powerpc-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvme68k:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvme88k:OpenBSD:*:*)
- echo m88k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvmeppc:OpenBSD:*:*)
- echo powerpc-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- pmax:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- sgi:OpenBSD:*:*)
- echo mipseb-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- sun3:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- wgrisc:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- *:OpenBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- alpha:OSF1:*:*)
- if test $UNAME_RELEASE = "V4.0"; then
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- fi
- # According to Compaq, /usr/sbin/psrinfo has been available on
- # OSF/1 and Tru64 systems produced since 1995. I hope that
- # covers most systems running today. This code pipes the CPU
- # types through head -n 1, so we only detect the type of CPU 0.
- ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
- case "$ALPHA_CPU_TYPE" in
- "EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
- "EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
- "LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
- "EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
- "EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
- "EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
- "EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
- "EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
- "EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
- "EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
- "EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
- "EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
- esac
- # A Vn.n version is a released version.
- # A Tn.n version is a released field test version.
- # A Xn.n version is an unreleased experimental baselevel.
- # 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit 0 ;;
- Alpha*:OpenVMS:*:*)
- echo alpha-hp-vms
- exit 0 ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit 0 ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit 0 ;;
- Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit 0;;
- *:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
- exit 0 ;;
- *:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
- exit 0 ;;
- *:OS/390:*:*)
- echo i370-ibm-openedition
- exit 0 ;;
- arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
- exit 0;;
- SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit 0;;
- Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
- # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "`(/bin/universe) 2>/dev/null`" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit 0 ;;
- NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit 0 ;;
- DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit 0 ;;
- DRS?6000:UNIX_SV:4.2*:7*)
- case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7 && exit 0 ;;
- esac ;;
- sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- i86pc:SunOS:5.*:*)
- echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- sun4*:SunOS:6*:*)
- # According to config.sub, this is the proper way to canonicalize
- # SunOS6. Hard to guess exactly what SunOS6 will be like, but
- # it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- sun4*:SunOS:*:*)
- case "`/usr/bin/arch -k`" in
- Series*|S4*)
- UNAME_RELEASE=`uname -v`
- ;;
- esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit 0 ;;
- sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
- exit 0 ;;
- sun*:*:4.2BSD:*)
- UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
- case "`/bin/arch`" in
- sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
- ;;
- sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
- ;;
- esac
- exit 0 ;;
- aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
- exit 0 ;;
- # The situation for MiNT is a little confusing. The machine name
- # can be virtually everything (everything which is not
- # "atarist" or "atariste" at least should have a processor
- # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
- # to the lowercase version "mint" (or "freemint"). Finally
- # the system name "TOS" denotes a system which is actually not
- # MiNT. But MiNT is downward compatible to TOS, so this should
- # be no problem.
- atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
- atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
- *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
- milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit 0 ;;
- hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit 0 ;;
- *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit 0 ;;
- powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
- exit 0 ;;
- RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit 0 ;;
- RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
- exit 0 ;;
- VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
- exit 0 ;;
- 2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
- exit 0 ;;
- mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-#ifdef __cplusplus
-#include <stdio.h> /* for printf() prototype */
- int main (int argc, char *argv[]) {
-#else
- int main (argc, argv) int argc; char *argv[]; {
-#endif
- #if defined (host_mips) && defined (MIPSEB)
- #if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
- #endif
- #endif
- exit (-1);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c \
- && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
- && exit 0
- echo mips-mips-riscos${UNAME_RELEASE}
- exit 0 ;;
- Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit 0 ;;
- Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit 0 ;;
- Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit 0 ;;
- Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit 0 ;;
- m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit 0 ;;
- m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit 0 ;;
- m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit 0 ;;
- AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
- then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
- then
- echo m88k-dg-dgux${UNAME_RELEASE}
- else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
- fi
- else
- echo i586-dg-dgux${UNAME_RELEASE}
- fi
- exit 0 ;;
- M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit 0 ;;
- M88*:*:R3*:*)
- # Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit 0 ;;
- XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit 0 ;;
- Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit 0 ;;
- *:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit 0 ;;
- ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
- i*86:AIX:*:*)
- echo i386-ibm-aix
- exit 0 ;;
- ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit 0 ;;
- *:AIX:2:3)
- if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <sys/systemcfg.h>
-
- main()
- {
- if (!__power_pc())
- exit(1);
- puts("powerpc-ibm-aix3.2.5");
- exit(0);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
- echo rs6000-ibm-aix3.2.5
- elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
- else
- echo rs6000-ibm-aix3.2
- fi
- exit 0 ;;
- *:AIX:*:[45])
- IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
- IBM_ARCH=rs6000
- else
- IBM_ARCH=powerpc
- fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit 0 ;;
- *:AIX:*:*)
- echo rs6000-ibm-aix
- exit 0 ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
- echo romp-ibm-bsd4.4
- exit 0 ;;
- ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit 0 ;; # report: romp-ibm BSD 4.3
- *:BOSX:*:*)
- echo rs6000-bull-bosx
- exit 0 ;;
- DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit 0 ;;
- 9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit 0 ;;
- hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit 0 ;;
- 9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
- sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
- fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-
- #define _HPUX_SOURCE
- #include <stdlib.h>
- #include <unistd.h>
-
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
-
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
-EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
- test -z "$HP_ARCH" && HP_ARCH=hppa
- fi ;;
- esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
- then
- # avoid double evaluation of $set_cc_for_build
- test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
- then
- HP_ARCH="hppa2.0w"
- else
- HP_ARCH="hppa64"
- fi
- fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit 0 ;;
- ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
- exit 0 ;;
- 3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <unistd.h>
- int
- main ()
- {
- long cpu = sysconf (_SC_CPU_VERSION);
- /* The order matters, because CPU_IS_HP_MC68K erroneously returns
- true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
- results, however. */
- if (CPU_IS_PA_RISC (cpu))
- {
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
- default: puts ("hppa-hitachi-hiuxwe2"); break;
- }
- }
- else if (CPU_IS_HP_MC68K (cpu))
- puts ("m68k-hitachi-hiuxwe2");
- else puts ("unknown-hitachi-hiuxwe2");
- exit (0);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
- echo unknown-hitachi-hiuxwe2
- exit 0 ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
- echo hppa1.1-hp-bsd
- exit 0 ;;
- 9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit 0 ;;
- *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit 0 ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
- echo hppa1.1-hp-osf
- exit 0 ;;
- hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit 0 ;;
- i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
- else
- echo ${UNAME_MACHINE}-unknown-osf1
- fi
- exit 0 ;;
- parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit 0 ;;
- C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit 0 ;;
- C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit 0 ;;
- C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit 0 ;;
- C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit 0 ;;
- C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit 0 ;;
- CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
- | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
- -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
- -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- *:UNICOS/mp:*:*)
- echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit 0 ;;
- i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit 0 ;;
- sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit 0 ;;
- *:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit 0 ;;
- *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
- # Determine whether the default compiler uses glibc.
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <features.h>
- #if __GLIBC__ >= 2
- LIBC=gnu
- #else
- LIBC=
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
- # GNU/FreeBSD systems have a "k" prefix to indicate we are using
- # FreeBSD's kernel, but not the complete OS.
- case ${LIBC} in gnu) kernel_only='k' ;; esac
- echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
- exit 0 ;;
- i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
- exit 0 ;;
- i*:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit 0 ;;
- i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
- exit 0 ;;
- x86:Interix*:[34]*)
- echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
- exit 0 ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit 0 ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit 0 ;;
- i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
- exit 0 ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
- exit 0 ;;
- prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- *:GNU:*:*)
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit 0 ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
- exit 0 ;;
- arm*:Linux:*:*)
- echo ${UNAME_MACHINE}-${VENDOR}-linux
- exit 0 ;;
- cris:Linux:*:*)
- echo cris-axis-linux
- exit 0 ;;
- ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-${VENDOR}-linux
- exit 0 ;;
- m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-${VENDOR}-linux
- exit 0 ;;
- mips:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips
- #undef mipsel
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mipsel
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips
- #else
- CPU=
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && echo "${CPU}-${VENDOR}-linux" && exit 0
- ;;
- mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips64
- #undef mips64el
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mips64el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips64
- #else
- CPU=
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && echo "${CPU}-${VENDOR}-linux" && exit 0
- ;;
- ppc:Linux:*:*)
- echo powerpc-${VENDOR}-linux
- exit 0 ;;
- ppc64:Linux:*:*)
- echo powerpc64-${VENDOR}-linux
- exit 0 ;;
- alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- EV5) UNAME_MACHINE=alphaev5 ;;
- EV56) UNAME_MACHINE=alphaev56 ;;
- PCA56) UNAME_MACHINE=alphapca56 ;;
- PCA57) UNAME_MACHINE=alphapca56 ;;
- EV6) UNAME_MACHINE=alphaev6 ;;
- EV67) UNAME_MACHINE=alphaev67 ;;
- EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
- objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
- if test "$?" = 0 ; then LIBC="-libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-${VENDOR}-linux${LIBC}
- exit 0 ;;
- parisc:Linux:*:* | hppa:Linux:*:*)
- # Look for CPU level
- case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-${VENDOR}-linux ;;
- PA8*) echo hppa2.0-${VENDOR}-linux ;;
- *) echo hppa-${VENDOR}-linux ;;
- esac
- exit 0 ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-${VENDOR}-linux
- exit 0 ;;
- s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
- exit 0 ;;
- sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-${VENDOR}-linux
- exit 0 ;;
- sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-${VENDOR}-linux
- exit 0 ;;
- sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-${VENDOR}-linux
- exit 0 ;;
- x86_64:Linux:*:*)
- echo x86_64-${VENDOR}-linux
- exit 0 ;;
- i*86:Linux:*:*)
- # The BFD linker knows what the default object file format is, so
- # first see if it will tell us. cd to the root directory to prevent
- # problems with other programs or directories called `ld' in the path.
- # Set LC_ALL=C to ensure ld outputs messages in English.
- ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
- | sed -ne '/supported targets:/!d
- s/[ ][ ]*/ /g
- s/.*supported targets: *//
- s/ .*//
- p'`
- case "$ld_supported_targets" in
- elf32-i386)
- TENTATIVE="${UNAME_MACHINE}-${VENDOR}-linux"
- ;;
- a.out-i386-linux)
- echo "${UNAME_MACHINE}-${VENDOR}-linuxaout"
- exit 0 ;;
- coff-i386)
- echo "${UNAME_MACHINE}-${VENDOR}-linuxcoff"
- exit 0 ;;
- "")
- # Either a pre-BFD a.out linker (linuxoldld) or
- # one that does not give us useful --help.
- echo "${UNAME_MACHINE}-${VENDOR}-linuxoldld"
- exit 0 ;;
- esac
- # Determine whether the default compiler is a.out or elf
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <features.h>
- #ifdef __ELF__
- # ifdef __GLIBC__
- # if __GLIBC__ >= 2
- LIBC=gnu
- # else
- LIBC=gnulibc1
- # endif
- # else
- LIBC=gnulibc1
- # endif
- #else
- #ifdef __INTEL_COMPILER
- LIBC=gnu
- #else
- LIBC=gnuaout
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
- test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}" | sed 's/linux-gnu/linux/' && exit 0
- test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
- ;;
- i*86:DYNIX/ptx:4*:*)
- # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
- # earlier versions are messed up and put the nodename in both
- # sysname and nodename.
- echo i386-sequent-sysv4
- exit 0 ;;
- i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
- # I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit 0 ;;
- i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
- # is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
- exit 0 ;;
- i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
- exit 0 ;;
- i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
- exit 0 ;;
- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit 0 ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
- if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
- else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
- fi
- exit 0 ;;
- i*86:*:5:[78]*)
- case `/bin/uname -X | grep "^Machine"` in
- *486*) UNAME_MACHINE=i486 ;;
- *Pentium) UNAME_MACHINE=i586 ;;
- *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
- esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit 0 ;;
- i*86:*:3.2:*)
- if test -f /usr/options/cb.name; then
- UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
- elif /bin/uname -X 2>/dev/null >/dev/null ; then
- UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
- (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
- (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
- && UNAME_MACHINE=i586
- (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
- && UNAME_MACHINE=i686
- (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
- && UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
- else
- echo ${UNAME_MACHINE}-pc-sysv32
- fi
- exit 0 ;;
- pc:*:*:*)
- # Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i386.
- echo i386-pc-msdosdjgpp
- exit 0 ;;
- Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit 0 ;;
- paragon:*:*:*)
- echo i860-intel-osf1
- exit 0 ;;
- i860:*:4.*:*) # i860-SVR4
- if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
- else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
- fi
- exit 0 ;;
- mini*:CTIX:SYS*5:*)
- # "miniframe"
- echo m68010-convergent-sysv
- exit 0 ;;
- mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit 0 ;;
- M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit 0 ;;
- M68*:*:R3V[567]*:*)
- test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
- 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
- OS_REL=''
- test -r /etc/.relid \
- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && echo i486-ncr-sysv4.3${OS_REL} && exit 0
- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
- 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && echo i486-ncr-sysv4 && exit 0 ;;
- m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit 0 ;;
- TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
- exit 0 ;;
- RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit 0 ;;
- RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit 0 ;;
- *:SINIX-*:*:*)
- if uname -p 2>/dev/null >/dev/null ; then
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
- else
- echo ns32k-sni-sysv
- fi
- exit 0 ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit 0 ;;
- *:UNIX_System_V:4*:FTX*)
- # From Gerald Hewes <hewes@openmarket.com>.
- # How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit 0 ;;
- *:*:*:FTX*)
- # From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit 0 ;;
- *:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit 0 ;;
- mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
- exit 0 ;;
- news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit 0 ;;
- R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
- else
- echo mips-unknown-sysv${UNAME_RELEASE}
- fi
- exit 0 ;;
- BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit 0 ;;
- BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit 0 ;;
- BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit 0 ;;
- SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
- exit 0 ;;
- SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
- exit 0 ;;
- SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
- exit 0 ;;
- Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit 0 ;;
- *:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit 0 ;;
- *:Darwin:*:*)
- case `uname -p` in
- *86) UNAME_PROCESSOR=i686 ;;
- powerpc) UNAME_PROCESSOR=powerpc ;;
- esac
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit 0 ;;
- *:procnto*:*:* | *:QNX:[0123456789]*:*)
- UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
- UNAME_PROCESSOR=i386
- UNAME_MACHINE=pc
- fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit 0 ;;
- *:QNX:*:4*)
- echo i386-pc-qnx
- exit 0 ;;
- NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
- exit 0 ;;
- *:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit 0 ;;
- BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit 0 ;;
- DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit 0 ;;
- *:Plan9:*:*)
- # "uname -m" is not consistent, so use $cputype instead. 386
- # is converted to i386 for consistency with other x86
- # operating systems.
- if test "$cputype" = "386"; then
- UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
- fi
- echo ${UNAME_MACHINE}-unknown-plan9
- exit 0 ;;
- *:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit 0 ;;
- *:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit 0 ;;
- KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit 0 ;;
- XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit 0 ;;
- *:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit 0 ;;
- *:ITS:*:*)
- echo pdp10-unknown-its
- exit 0 ;;
- SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit 0 ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
- I don't know.... */
- printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
- printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
- "4"
-#else
- ""
-#endif
- ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
- int version;
- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- if (version < 4)
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
- else
- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
- exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
- printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
- printf ("ns32k-encore-mach\n"); exit (0);
-#else
- printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
- printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
- printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
- printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-# include <sys/param.h>
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
- printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
- exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit 0 ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit 0 ;;
- c34*)
- echo c34-convex-bsd
- exit 0 ;;
- c38*)
- echo c38-convex-bsd
- exit 0 ;;
- c4*)
- echo c4-convex-bsd
- exit 0 ;;
- esac
-fi
-
-cat >&2 <<EOF
-$0: unable to guess system type
-
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
-
- ftp://ftp.gnu.org/pub/gnu/config/
-
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
-
-hostinfo = `(hostinfo) 2>/dev/null`
-/bin/universe = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
-EOF
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/config.sub b/config.sub
deleted file mode 100755
index 9952c14c714..00000000000
--- a/config.sub
+++ /dev/null
@@ -1,1501 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-
-timestamp='2003-07-04'
-
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file 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.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
-#
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support. The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
-
-Canonicalize a configuration name.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit 0 ;;
- --version | -v )
- echo "$version" ; exit 0 ;;
- --help | --h* | -h )
- echo "$usage"; exit 0 ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help"
- exit 1 ;;
-
- *local*)
- # First pass through any local machine types.
- echo $1
- exit 0;;
-
- * )
- break ;;
- esac
-done
-
-case $# in
- 0) echo "$me: missing argument$help" >&2
- exit 1;;
- 1) ;;
- *) echo "$me: too many arguments$help" >&2
- exit 1;;
-esac
-
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
-
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis)
- os=
- basic_machine=$1
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*)
- os=-lynxos
- ;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
- ;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
- ;;
- -psos*)
- os=-psos
- ;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
-esac
-
-# Decode aliases for certain CPU-COMPANY combinations.
-case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
- | c4x | clipper \
- | d10v | d30v | dlx | dsp16xx \
- | fr30 | frv \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | i370 | i860 | i960 | ia64 \
- | ip2k \
- | m32r | m68000 | m68k | m88k | mcore \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64el \
- | mips64vr | mips64vrel \
- | mips64orion | mips64orionel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipstx39 | mipstx39el \
- | mn10200 | mn10300 \
- | msp430 \
- | ns16k | ns32k \
- | openrisc | or32 \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
- | pyramid \
- | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
- | sh64 | sh64le \
- | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
- | strongarm \
- | tahoe | thumb | tic4x | tic80 | tron \
- | v850 | v850e \
- | we32k \
- | x86 | xscale | xstormy16 | xtensa \
- | z8k)
- basic_machine=$basic_machine-unknown
- ;;
- m6811 | m68hc11 | m6812 | m68hc12)
- # Motorola 68HC11/12.
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
- ;;
-
- # We use `pc' rather than `unknown'
- # because (1) that's what they normally are, and
- # (2) the word "unknown" tends to confuse beginning users.
- i*86 | x86_64)
- basic_machine=$basic_machine-pc
- ;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* \
- | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
- | clipper-* | cydra-* \
- | d10v-* | d30v-* | dlx-* \
- | elxsi-* \
- | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* \
- | m32r-* \
- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | mcore-* \
- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- | mips16-* \
- | mips64-* | mips64el-* \
- | mips64vr-* | mips64vrel-* \
- | mips64orion-* | mips64orionel-* \
- | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* \
- | mips64vr5000-* | mips64vr5000el-* \
- | mipsisa32-* | mipsisa32el-* \
- | mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa64-* | mipsisa64el-* \
- | mipsisa64sb1-* | mipsisa64sb1el-* \
- | mipsisa64sr71k-* | mipsisa64sr71kel-* \
- | mipstx39-* | mipstx39el-* \
- | msp430-* \
- | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
- | pyramid-* \
- | romp-* | rs6000-* \
- | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
- | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
- | tron-* \
- | v850-* | v850e-* | vax-* \
- | we32k-* \
- | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
- | xtensa-* \
- | ymp-* \
- | z8k-*)
- ;;
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
- ;;
- 3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amd64)
- basic_machine=x86_64-pc
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- c90)
- basic_machine=c90-cray
- os=-unicos
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
- ;;
- decsystem10* | dec10*)
- basic_machine=pdp10-dec
- os=-tops10
- ;;
- decsystem20* | dec20*)
- basic_machine=pdp10-dec
- os=-tops20
- ;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
- ;;
- encore | umax | mmax)
- basic_machine=ns32k-encore
- ;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
- ;;
- fx2800)
- basic_machine=i860-alliant
- ;;
- genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
- ;;
- h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
- ;;
- hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
- ;;
- hp9k3[2-9][0-9])
- basic_machine=m68k-hp
- ;;
- hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
- ;;
- hp9k78[0-9] | hp78[0-9])
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
- ;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
- i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
- ;;
- i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
- ;;
- i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
- ;;
- i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
- ;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
- ;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
- ;;
- iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- -irix*)
- ;;
- *)
- os=-irix4
- ;;
- esac
- ;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- mingw32)
- basic_machine=i386-pc
- os=-mingw32
- ;;
- miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
- ;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- mmix*)
- basic_machine=mmix-knuth
- os=-mmixware
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
- ;;
- news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
- ;;
- next | m*-next )
- basic_machine=m68k-next
- case $os in
- -nextstep* )
- ;;
- -ns2*)
- os=-nextstep2
- ;;
- *)
- os=-nextstep3
- ;;
- esac
- ;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
- np1)
- basic_machine=np1-gould
- ;;
- nv1)
- basic_machine=nv1-cray
- os=-unicosmp
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
- ;;
- op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- or32 | or32-*)
- basic_machine=or32-unknown
- os=-coff
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
- ;;
- pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- pbd)
- basic_machine=sparc-tti
- ;;
- pbb)
- basic_machine=m68k-tti
- ;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
- ;;
- pentium | p5 | k5 | k6 | nexgen | viac3)
- basic_machine=i586-pc
- ;;
- pentiumpro | p6 | 6x86 | athlon | athlon_*)
- basic_machine=i686-pc
- ;;
- pentiumii | pentium2 | pentiumiii | pentium3)
- basic_machine=i686-pc
- ;;
- pentium4)
- basic_machine=i786-pc
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium4-*)
- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pn)
- basic_machine=pn-gould
- ;;
- power) basic_machine=power-ibm
- ;;
- ppc) basic_machine=powerpc-unknown
- ;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppcle | powerpclittle | ppc-le | powerpc-little)
- basic_machine=powerpcle-unknown
- ;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little | ppc64-le | powerpc64-little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- rm[46]00)
- basic_machine=mips-siemens
- ;;
- rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- s390 | s390-*)
- basic_machine=s390-ibm
- ;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
- ;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
- ;;
- sb1)
- basic_machine=mipsisa64sb1-unknown
- ;;
- sb1el)
- basic_machine=mipsisa64sb1el-unknown
- ;;
- sei)
- basic_machine=mips-sei
- os=-seiux
- ;;
- sequent)
- basic_machine=i386-sequent
- ;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
- ;;
- sh64)
- basic_machine=sh64-unknown
- ;;
- sparclite-wrs | simso-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
- ;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
- ;;
- spur)
- basic_machine=spur-unknown
- ;;
- st2000)
- basic_machine=m68k-tandem
- ;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
- ;;
- sun2)
- basic_machine=m68000-sun
- ;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
- ;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
- ;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
- ;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
- ;;
- sun4)
- basic_machine=sparc-sun
- ;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
- ;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
- ;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
- ;;
- t90)
- basic_machine=t90-cray
- os=-unicos
- ;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tic55x | c55x*)
- basic_machine=tic55x-unknown
- os=-coff
- ;;
- tic6x | c6x*)
- basic_machine=tic6x-unknown
- os=-coff
- ;;
- tx39)
- basic_machine=mipstx39-unknown
- ;;
- tx39el)
- basic_machine=mipstx39el-unknown
- ;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
- ;;
- tower | tower-32)
- basic_machine=m68k-ncr
- ;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
- ;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
- ;;
- vms)
- basic_machine=vax-dec
- os=-vms
- ;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
- ;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
- ;;
- w65*)
- basic_machine=w65-wdc
- os=-none
- ;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
- ;;
- xps | xps100)
- basic_machine=xps100-honeywell
- ;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
- ;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
- ;;
- none)
- basic_machine=none-none
- os=-none
- ;;
-
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
- ;;
- op50n)
- basic_machine=hppa1.1-oki
- ;;
- op60c)
- basic_machine=hppa1.1-oki
- ;;
- romp)
- basic_machine=romp-ibm
- ;;
- rs6000)
- basic_machine=rs6000-ibm
- ;;
- vax)
- basic_machine=vax-dec
- ;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
- ;;
- pdp11)
- basic_machine=pdp11-dec
- ;;
- we32k)
- basic_machine=we32k-att
- ;;
- sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
- basic_machine=sh-unknown
- ;;
- sh64)
- basic_machine=sh64-unknown
- ;;
- sparc | sparcv9 | sparcv9b)
- basic_machine=sparc-sun
- ;;
- cydra)
- basic_machine=cydra-cydrome
- ;;
- orion)
- basic_machine=orion-highlevel
- ;;
- orion105)
- basic_machine=clipper-highlevel
- ;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
- ;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
- ;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
- ;;
- *)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
- ;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
- ;;
- *)
- ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if [ x"$os" != x"" ]
-then
-case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
- ;;
- -solaris)
- os=-solaris2
- ;;
- -svr4*)
- os=-sysv4
- ;;
- -unixware*)
- os=-sysv4.2uw
- ;;
- -gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
- ;;
- # First accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST END IN A *, to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
- | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux* | -uxpv* | -beos* | -mpeix* | -udk* \
- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
- | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
- # Remember, each alternative MUST END IN *, to match a version number.
- ;;
- -qnx*)
- case $basic_machine in
- x86-* | i*86-*)
- ;;
- *)
- os=-nto$os
- ;;
- esac
- ;;
- -nto-qnx*)
- ;;
- -nto*)
- os=`echo $os | sed -e 's|nto|nto-qnx|'`
- ;;
- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
- ;;
- -mac*)
- os=`echo $os | sed -e 's|mac|macos|'`
- ;;
- -sunos5*)
- os=`echo $os | sed -e 's|sunos5|solaris2|'`
- ;;
- -sunos6*)
- os=`echo $os | sed -e 's|sunos6|solaris3|'`
- ;;
- -opened*)
- os=-openedition
- ;;
- -wince*)
- os=-wince
- ;;
- -osfrose*)
- os=-osfrose
- ;;
- -osf*)
- os=-osf
- ;;
- -utek*)
- os=-bsd
- ;;
- -dynix*)
- os=-bsd
- ;;
- -acis*)
- os=-aos
- ;;
- -atheos*)
- os=-atheos
- ;;
- -386bsd)
- os=-bsd
- ;;
- -ctix* | -uts*)
- os=-sysv
- ;;
- -nova*)
- os=-rtmk-nova
- ;;
- -ns2 )
- os=-nextstep2
- ;;
- -nsk*)
- os=-nsk
- ;;
- # Preserve the version number of sinix5.
- -sinix5.*)
- os=`echo $os | sed -e 's|sinix|sysv|'`
- ;;
- -sinix*)
- os=-sysv4
- ;;
- -triton*)
- os=-sysv3
- ;;
- -oss*)
- os=-sysv3
- ;;
- -svr4)
- os=-sysv4
- ;;
- -svr3)
- os=-sysv3
- ;;
- -sysvr4)
- os=-sysv4
- ;;
- # This must come after -sysvr4.
- -sysv*)
- ;;
- -ose*)
- os=-ose
- ;;
- -es1800*)
- os=-ose
- ;;
- -xenix)
- os=-xenix
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
- ;;
- -aros*)
- os=-aros
- ;;
- -kaos*)
- os=-kaos
- ;;
- -none)
- ;;
- *)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
- exit 1
- ;;
-esac
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system. Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-case $basic_machine in
- *-acorn)
- os=-riscix1.2
- ;;
- arm*-rebel)
- os=-linux
- ;;
- arm*-semi)
- os=-aout
- ;;
- c4x-* | tic4x-*)
- os=-coff
- ;;
- # This must come before the *-dec entry.
- pdp10-*)
- os=-tops20
- ;;
- pdp11-*)
- os=-none
- ;;
- *-dec | vax-*)
- os=-ultrix4.2
- ;;
- m68*-apollo)
- os=-domain
- ;;
- i386-sun)
- os=-sunos4.0.2
- ;;
- m68000-sun)
- os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
- ;;
- m68*-cisco)
- os=-aout
- ;;
- mips*-cisco)
- os=-elf
- ;;
- mips*-*)
- os=-elf
- ;;
- or32-*)
- os=-coff
- ;;
- *-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
- ;;
- sparc-* | *-sun)
- os=-sunos4.1.1
- ;;
- *-be)
- os=-beos
- ;;
- *-ibm)
- os=-aix
- ;;
- *-wec)
- os=-proelf
- ;;
- *-winbond)
- os=-proelf
- ;;
- *-oki)
- os=-proelf
- ;;
- *-hp)
- os=-hpux
- ;;
- *-hitachi)
- os=-hiux
- ;;
- i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
- ;;
- *-cbm)
- os=-amigaos
- ;;
- *-dg)
- os=-dgux
- ;;
- *-dolphin)
- os=-sysv3
- ;;
- m68k-ccur)
- os=-rtu
- ;;
- m88k-omron*)
- os=-luna
- ;;
- *-next )
- os=-nextstep
- ;;
- *-sequent)
- os=-ptx
- ;;
- *-crds)
- os=-unos
- ;;
- *-ns)
- os=-genix
- ;;
- i370-*)
- os=-mvs
- ;;
- *-next)
- os=-nextstep3
- ;;
- *-gould)
- os=-sysv
- ;;
- *-highlevel)
- os=-bsd
- ;;
- *-encore)
- os=-bsd
- ;;
- *-sgi)
- os=-irix
- ;;
- *-siemens)
- os=-sysv4
- ;;
- *-masscomp)
- os=-rtu
- ;;
- f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
- ;;
- *-rom68k)
- os=-coff
- ;;
- *-*bug)
- os=-coff
- ;;
- *-apple)
- os=-macos
- ;;
- *-atari*)
- os=-mint
- ;;
- *)
- os=-none
- ;;
-esac
-fi
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
- case $os in
- -riscix*)
- vendor=acorn
- ;;
- -sunos*)
- vendor=sun
- ;;
- -aix*)
- vendor=ibm
- ;;
- -beos*)
- vendor=be
- ;;
- -hpux*)
- vendor=hp
- ;;
- -mpeix*)
- vendor=hp
- ;;
- -hiux*)
- vendor=hitachi
- ;;
- -unos*)
- vendor=crds
- ;;
- -dgux*)
- vendor=dg
- ;;
- -luna*)
- vendor=omron
- ;;
- -genix*)
- vendor=ns
- ;;
- -mvs* | -opened*)
- vendor=ibm
- ;;
- -ptx*)
- vendor=sequent
- ;;
- -vxsim* | -vxworks* | -windiss*)
- vendor=wrs
- ;;
- -aux*)
- vendor=apple
- ;;
- -hms*)
- vendor=hitachi
- ;;
- -mpw* | -macos*)
- vendor=apple
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- vendor=atari
- ;;
- -vos*)
- vendor=stratus
- ;;
- esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
- ;;
-esac
-
-echo $basic_machine$os
-exit 0
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/config/ac-macros/alloca.m4 b/config/ac-macros/alloca.m4
new file mode 100644
index 00000000000..8c730dd671f
--- /dev/null
+++ b/config/ac-macros/alloca.m4
@@ -0,0 +1,68 @@
+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, 1)
+ 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], [1], [If we have a working alloca() implementation])
+ 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, 1)
+
+ 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
+])
diff --git a/config/ac-macros/character_sets.m4 b/config/ac-macros/character_sets.m4
new file mode 100644
index 00000000000..1ab6e7dd780
--- /dev/null
+++ b/config/ac-macros/character_sets.m4
@@ -0,0 +1,431 @@
+dnl In order to add new charset, you must add charset name to
+dnl this CHARSETS_AVAILABLE list and sql/share/charsets/Index.xml.
+dnl If the character set uses strcoll or other special handling,
+dnl you must also create strings/ctype-$charset_name.c
+
+AC_DIVERT_PUSH(0)
+
+define(CHARSETS_AVAILABLE0,binary)
+define(CHARSETS_AVAILABLE1,armscii8 ascii big5 cp1250 cp1251 cp1256 cp1257)
+define(CHARSETS_AVAILABLE2,cp850 cp852 cp866 cp932 dec8 eucjpms 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_AVAILABLE0 CHARSETS_AVAILABLE1 CHARSETS_AVAILABLE2 CHARSETS_AVAILABLE3 CHARSETS_AVAILABLE4 CHARSETS_AVAILABLE5"
+CHARSETS_COMPLEX="big5 cp1250 cp932 eucjpms euckr gb2312 gbk latin1 latin2 sjis tis620 ucs2 ujis utf8"
+
+AC_DIVERT_POP
+
+AC_ARG_WITH(charset,
+ [ --with-charset=CHARSET
+ Default character set, use one of:
+ CHARSETS_AVAILABLE0
+ CHARSETS_AVAILABLE1
+ CHARSETS_AVAILABLE2
+ CHARSETS_AVAILABLE3
+ CHARSETS_AVAILABLE4
+ CHARSETS_AVAILABLE5],
+ [default_charset="$withval"],
+ [default_charset="$DEFAULT_CHARSET"])
+
+AC_ARG_WITH(collation,
+ [ --with-collation=COLLATION
+ Default collation],
+ [default_collation="$withval"],
+ [default_collation="default"])
+
+
+AC_ARG_WITH(extra-charsets,
+ [ --with-extra-charsets=CHARSET[,CHARSET,...]
+ Use charsets in addition to default (none, complex,
+ all, or a list selected from the above sets)],
+ [extra_charsets="$withval"],
+ [extra_charsets="none"])
+
+
+AC_MSG_CHECKING("character sets")
+
+CHARSETS="$default_charset latin1 utf8"
+
+if test "$extra_charsets" = no; then
+ CHARSETS="$CHARSETS"
+elif test "$extra_charsets" = none; then
+ CHARSETS="$CHARSETS"
+elif test "$extra_charsets" = complex; then
+ CHARSETS="$CHARSETS $CHARSETS_COMPLEX"
+ AC_DEFINE([DEFINE_ALL_CHARACTER_SETS],1,[all charsets are available])
+elif test "$extra_charsets" = all; then
+ CHARSETS="$CHARSETS $CHARSETS_AVAILABLE"
+ AC_DEFINE([DEFINE_ALL_CHARACTER_SETS],1,[all charsets are available])
+else
+ EXTRA_CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
+ CHARSETS="$CHARSETS $EXTRA_CHARSETS"
+fi
+
+for cs in $CHARSETS
+do
+ case $cs in
+ armscii8)
+ AC_DEFINE(HAVE_CHARSET_armscii8, 1,
+ [Define to enable charset armscii8])
+ ;;
+ ascii)
+ AC_DEFINE(HAVE_CHARSET_ascii, 1,
+ [Define to enable ascii character set])
+ ;;
+ big5)
+ AC_DEFINE(HAVE_CHARSET_big5, 1, [Define to enable charset big5])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, [1], [ ])
+ ;;
+ binary)
+ ;;
+ cp1250)
+ AC_DEFINE(HAVE_CHARSET_cp1250, 1, [Define to enable cp1250])
+ ;;
+ cp1251)
+ AC_DEFINE(HAVE_CHARSET_cp1251, 1, [Define to enable charset cp1251])
+ ;;
+ cp1256)
+ AC_DEFINE(HAVE_CHARSET_cp1256, 1, [Define to enable charset cp1256])
+ ;;
+ cp1257)
+ AC_DEFINE(HAVE_CHARSET_cp1257, 1, [Define to enable charset cp1257])
+ ;;
+ cp850)
+ AC_DEFINE(HAVE_CHARSET_cp850, 1, [Define to enable charset cp850])
+ ;;
+ cp852)
+ AC_DEFINE(HAVE_CHARSET_cp852, 1, [Define to enable charset cp852])
+ ;;
+ cp866)
+ AC_DEFINE(HAVE_CHARSET_cp866, 1, [Define to enable charset cp866])
+ ;;
+ cp932)
+ AC_DEFINE(HAVE_CHARSET_cp932, 1, [Define to enable charset cp932])
+ AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ dec8)
+ AC_DEFINE(HAVE_CHARSET_dec8, 1, [Define to enable charset dec8])
+ ;;
+ eucjpms)
+ AC_DEFINE(HAVE_CHARSET_eucjpms, 1, [Define to enable charset eucjpms])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ euckr)
+ AC_DEFINE(HAVE_CHARSET_euckr, 1, [Define to enable charset euckr])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ gb2312)
+ AC_DEFINE(HAVE_CHARSET_gb2312, 1, [Define to enable charset gb2312])
+ AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ gbk)
+ AC_DEFINE(HAVE_CHARSET_gbk, 1, [Define to enable charset gbk])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ geostd8)
+ AC_DEFINE(HAVE_CHARSET_geostd8, 1, [Define to enable charset geostd8])
+ ;;
+ greek)
+ AC_DEFINE(HAVE_CHARSET_greek, 1, [Define to enable charset greek])
+ ;;
+ hebrew)
+ AC_DEFINE(HAVE_CHARSET_hebrew, 1, [Define to enable charset hebrew])
+ ;;
+ hp8)
+ AC_DEFINE(HAVE_CHARSET_hp8, 1, [Define to enable charset hp8])
+ ;;
+ keybcs2)
+ AC_DEFINE(HAVE_CHARSET_keybcs2, 1, [Define to enable charset keybcs2])
+ ;;
+ koi8r)
+ AC_DEFINE(HAVE_CHARSET_koi8r, 1, [Define to enable charset koi8r])
+ ;;
+ koi8u)
+ AC_DEFINE(HAVE_CHARSET_koi8u, 1, [Define to enable charset koi8u])
+ ;;
+ latin1)
+ AC_DEFINE(HAVE_CHARSET_latin1, 1, [Define to enable charset latin1])
+ ;;
+ latin2)
+ AC_DEFINE(HAVE_CHARSET_latin2, 1, [Define to enable charset latin2])
+ ;;
+ latin5)
+ AC_DEFINE(HAVE_CHARSET_latin5, 1, [Define to enable charset latin5])
+ ;;
+ latin7)
+ AC_DEFINE(HAVE_CHARSET_latin7, 1, [Define to enable charset latin7])
+ ;;
+ macce)
+ AC_DEFINE(HAVE_CHARSET_macce, 1, [Define to enable charset macce])
+ ;;
+ macroman)
+ AC_DEFINE(HAVE_CHARSET_macroman, 1,
+ [Define to enable charset macroman])
+ ;;
+ sjis)
+ AC_DEFINE(HAVE_CHARSET_sjis, 1, [Define to enable charset sjis])
+ AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ swe7)
+ AC_DEFINE(HAVE_CHARSET_swe7, 1, [Define to enable charset swe7])
+ ;;
+ tis620)
+ AC_DEFINE(HAVE_CHARSET_tis620, 1, [Define to enable charset tis620])
+ ;;
+ ucs2)
+ AC_DEFINE(HAVE_CHARSET_ucs2, 1, [Define to enable charset ucs2])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ ujis)
+ AC_DEFINE(HAVE_CHARSET_ujis, 1, [Define to enable charset ujis])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ utf8)
+ AC_DEFINE(HAVE_CHARSET_utf8, 1, [Define to enable ut8])
+ AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ *)
+ AC_MSG_ERROR([Charset '$cs' not available. (Available are: $CHARSETS_AVAILABLE).
+ See the Installation chapter in the Reference Manual.]);
+ esac
+done
+
+
+ default_charset_collations=""
+
+case $default_charset in
+ armscii8)
+ default_charset_default_collation="armscii8_general_ci"
+ default_charset_collations="armscii8_general_ci armscii8_bin"
+ ;;
+ ascii)
+ default_charset_default_collation="ascii_general_ci"
+ default_charset_collations="ascii_general_ci ascii_bin"
+ ;;
+ big5)
+ 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_cs cp1250_bin"
+ ;;
+ cp1251)
+ default_charset_default_collation="cp1251_general_ci"
+ default_charset_collations="cp1251_general_ci cp1251_general_cs cp1251_bin cp1251_bulgarian_ci cp1251_ukrainian_ci"
+ ;;
+ cp1256)
+ default_charset_default_collation="cp1256_general_ci"
+ default_charset_collations="cp1256_general_ci cp1256_bin"
+ ;;
+ cp1257)
+ default_charset_default_collation="cp1257_general_ci"
+ default_charset_collations="cp1257_general_ci cp1257_lithuanian_ci cp1257_bin"
+ ;;
+ cp850)
+ default_charset_default_collation="cp850_general_ci"
+ default_charset_collations="cp850_general_ci cp850_bin"
+ ;;
+ cp852)
+ default_charset_default_collation="cp852_general_ci"
+ default_charset_collations="cp852_general_ci cp852_bin"
+ ;;
+ cp866)
+ default_charset_default_collation="cp866_general_ci"
+ default_charset_collations="cp866_general_ci cp866_bin"
+ ;;
+ cp932)
+ default_charset_default_collation="cp932_japanese_ci"
+ default_charset_collations="cp932_japanese_ci cp932_bin"
+ ;;
+ dec8)
+ default_charset_default_collation="dec8_swedish_ci"
+ default_charset_collations="dec8_swedish_ci dec8_bin"
+ ;;
+ eucjpms)
+ default_charset_default_collation="eucjpms_japanese_ci"
+ default_charset_collations="eucjpms_japanese_ci ujis_bin"
+ ;;
+ euckr)
+ default_charset_default_collation="euckr_korean_ci"
+ default_charset_collations="euckr_korean_ci euckr_bin"
+ ;;
+ gb2312)
+ default_charset_default_collation="gb2312_chinese_ci"
+ default_charset_collations="gb2312_chinese_ci gb2312_bin"
+ ;;
+ gbk)
+ 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"
+ ;;
+ hebrew)
+ default_charset_default_collation="hebrew_general_ci"
+ default_charset_collations="hebrew_general_ci hebrew_bin"
+ ;;
+ hp8)
+ default_charset_default_collation="hp8_english_ci"
+ default_charset_collations="hp8_english_ci hp8_bin"
+ ;;
+ keybcs2)
+ default_charset_default_collation="keybcs2_general_ci"
+ default_charset_collations="keybcs2_general_ci keybcs2_bin"
+ ;;
+ koi8r)
+ default_charset_default_collation="koi8r_general_ci"
+ default_charset_collations="koi8r_general_ci koi8r_bin"
+ ;;
+ koi8u)
+ default_charset_default_collation="koi8u_general_ci"
+ default_charset_collations="koi8u_general_ci koi8u_bin"
+ ;;
+ latin1)
+ default_charset_default_collation="latin1_swedish_ci"
+ default_charset_collations="latin1_general_ci latin1_general_cs latin1_bin latin1_german1_ci latin1_german2_ci latin1_danish_ci latin1_spanish_ci latin1_swedish_ci"
+ ;;
+ latin2)
+ default_charset_default_collation="latin2_general_ci"
+ default_charset_collations="latin2_general_ci latin2_bin latin2_czech_cs latin2_hungarian_ci latin2_croatian_ci"
+ ;;
+ latin5)
+ default_charset_default_collation="latin5_turkish_ci"
+ default_charset_collations="latin5_turkish_ci latin5_bin"
+ ;;
+ latin7)
+ default_charset_default_collation="latin7_general_ci"
+ default_charset_collations="latin7_general_ci latin7_general_cs latin7_bin latin7_estonian_cs"
+ ;;
+ macce)
+ default_charset_default_collation="macce_general_ci"
+ default_charset_collations="macce_general_ci macce_bin"
+ ;;
+ macroman)
+ default_charset_default_collation="macroman_general_ci"
+ default_charset_collations="macroman_general_ci macroman_bin"
+ ;;
+ sjis)
+ default_charset_default_collation="sjis_japanese_ci"
+ default_charset_collations="sjis_japanese_ci sjis_bin"
+ ;;
+ swe7)
+ default_charset_default_collation="swe7_swedish_ci"
+ default_charset_collations="swe7_swedish_ci swe7_bin"
+ ;;
+ tis620)
+ default_charset_default_collation="tis620_thai_ci"
+ default_charset_collations="tis620_thai_ci tis620_bin"
+ ;;
+ ucs2)
+ default_charset_default_collation="ucs2_general_ci"
+ define(UCSC1, ucs2_general_ci ucs2_bin)
+ define(UCSC2, ucs2_czech_ci ucs2_danish_ci)
+ define(UCSC3, ucs2_esperanto_ci ucs2_estonian_ci ucs2_icelandic_ci)
+ define(UCSC4, ucs2_latvian_ci ucs2_lithuanian_ci)
+ define(UCSC5, ucs2_persian_ci 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"
+ default_charset_collations="ujis_japanese_ci ujis_bin"
+ ;;
+ utf8)
+ default_charset_default_collation="utf8_general_ci"
+ if test "$default_collation" = "utf8_general_cs"; then
+ # For those who explicitly desire "utf8_general_cs", support it,
+ # and then also set the CPP switch enabling that code.
+ UTFC="utf8_general_cs"
+ AC_DEFINE([HAVE_UTF8_GENERAL_CS], [1], [certain Japanese customer])
+ else
+ define(UTFC1, utf8_general_ci utf8_bin)
+ define(UTFC2, utf8_czech_ci utf8_danish_ci)
+ define(UTFC3, utf8_esperanto_ci utf8_estonian_ci utf8_icelandic_ci)
+ define(UTFC4, utf8_latvian_ci utf8_lithuanian_ci)
+ define(UTFC5, utf8_persian_ci 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"
+ fi
+ default_charset_collations="$UTFC"
+ ;;
+ *)
+ AC_MSG_ERROR([Charset $cs not available. (Available are: $CHARSETS_AVAILABLE).
+ See the Installation chapter in the Reference Manual.]);
+esac
+
+if test "$default_collation" = default; then
+ default_collation=$default_charset_default_collation
+fi
+
+valid_default_collation=no
+for cl in $default_charset_collations
+do
+ if test x"$cl" = x"$default_collation"
+ then
+ valid_default_collation=yes
+ break
+ fi
+done
+
+if test x$valid_default_collation = xyes
+then
+ AC_MSG_RESULT([default: $default_charset, collation: $default_collation; compiled in: $CHARSETS])
+else
+ AC_MSG_ERROR([
+ Collation $default_collation is not valid for character set $default_charset.
+ Valid collations are: $default_charset_collations.
+ See the Installation chapter in the Reference Manual.
+ ]);
+fi
+
+AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_CHARSET_NAME], ["$default_charset"],
+ [Define the default charset name])
+AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_COLLATION_NAME], ["$default_collation"],
+ [Define the default charset name])
+
+# Shall we build the UCA-based Unicode collations
+AC_ARG_WITH(uca,
+ [ --without-uca Skip building of the national Unicode collations.],
+ [with_uca=$withval],
+ [with_uca=yes]
+)
+
+AC_MSG_CHECKING([whether to compile national Unicode collations])
+
+if test "$with_uca" = "yes"
+then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([HAVE_UCA_COLLATIONS], [1], [national Unicode collations])
+else
+ AC_MSG_RESULT(no)
+fi
diff --git a/config/ac-macros/check_cpu.m4 b/config/ac-macros/check_cpu.m4
new file mode 100644
index 00000000000..d551f47769e
--- /dev/null
+++ b/config/ac-macros/check_cpu.m4
@@ -0,0 +1,47 @@
+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
+])])
+
diff --git a/config/ac-macros/compiler_flag.m4 b/config/ac-macros/compiler_flag.m4
new file mode 100644
index 00000000000..a236f61a198
--- /dev/null
+++ b/config/ac-macros/compiler_flag.m4
@@ -0,0 +1,40 @@
+# 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
+])
+
diff --git a/config/ac-macros/ha_archive.m4 b/config/ac-macros/ha_archive.m4
new file mode 100644
index 00000000000..2d2558ea600
--- /dev/null
+++ b/config/ac-macros/ha_archive.m4
@@ -0,0 +1,29 @@
+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], [1], [Builds Archive Storage Engine])
+ AC_MSG_RESULT([yes])
+ [archivedb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [archivedb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_ARCHIVE SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_berkeley.m4 b/config/ac-macros/ha_berkeley.m4
new file mode 100644
index 00000000000..732c7730816
--- /dev/null
+++ b/config/ac-macros/ha_berkeley.m4
@@ -0,0 +1,267 @@
+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 ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_blackhole.m4 b/config/ac-macros/ha_blackhole.m4
new file mode 100644
index 00000000000..cc4d360f5a8
--- /dev/null
+++ b/config/ac-macros/ha_blackhole.m4
@@ -0,0 +1,29 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_BLACKHOLEDB
+dnl Sets HAVE_BLACKHOLE_DB if --with-blackhole-storage-engine is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_BLACKHOLEDB], [
+ AC_ARG_WITH([blackhole-storage-engine],
+ [
+ --with-blackhole-storage-engine
+ Enable the Blackhole Storage Engine],
+ [blackholedb="$withval"],
+ [blackholedb=no])
+ AC_MSG_CHECKING([for blackhole storage engine])
+
+ case "$blackholedb" in
+ yes )
+ AC_DEFINE([HAVE_BLACKHOLE_DB], [1], [Builds Blackhole Storage Engine])
+ AC_MSG_RESULT([yes])
+ [blackholedb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [blackholedb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_BLACKHOLE SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_example.m4 b/config/ac-macros/ha_example.m4
new file mode 100644
index 00000000000..f8067931ce6
--- /dev/null
+++ b/config/ac-macros/ha_example.m4
@@ -0,0 +1,30 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_EXAMPLEDB
+dnl Sets HAVE_EXAMPLE_DB if --with-example-storage-engine is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_EXAMPLEDB], [
+ AC_ARG_WITH([example-storage-engine],
+ [
+ --with-example-storage-engine
+ Enable the Example Storage Engine],
+ [exampledb="$withval"],
+ [exampledb=no])
+ AC_MSG_CHECKING([for example storage engine])
+
+ case "$exampledb" in
+ yes )
+ AC_DEFINE([HAVE_EXAMPLE_DB], [1], [Builds Example DB])
+ AC_MSG_RESULT([yes])
+ [exampledb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [exampledb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_EXAMPLE SECTION
+dnl ---------------------------------------------------------------------------
+
diff --git a/config/ac-macros/ha_federated.m4 b/config/ac-macros/ha_federated.m4
new file mode 100644
index 00000000000..5c991f31666
--- /dev/null
+++ b/config/ac-macros/ha_federated.m4
@@ -0,0 +1,29 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_FEDERATED
+dnl Sets HAVE_FEDERATED if --with-federated-storage-engine is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_FEDERATED], [
+ AC_ARG_WITH([federated-storage-engine],
+ [
+ --with-federated-storage-engine
+ Enable the MySQL Federated Storage Engine],
+ [federateddb="$withval"],
+ [federateddb=no])
+ AC_MSG_CHECKING([for MySQL federated storage engine])
+
+ case "$federateddb" in
+ yes )
+ AC_DEFINE([HAVE_FEDERATED_DB], [1], [Define to enable Federated Handler])
+ AC_MSG_RESULT([yes])
+ [federateddb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [federateddb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_FEDERATED SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_innodb.m4 b/config/ac-macros/ha_innodb.m4
new file mode 100644
index 00000000000..17f0fab3e90
--- /dev/null
+++ b/config/ac-macros/ha_innodb.m4
@@ -0,0 +1,77 @@
+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], [1], [Using 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 ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_ndbcluster.m4 b/config/ac-macros/ha_ndbcluster.m4
new file mode 100644
index 00000000000..509cd868909
--- /dev/null
+++ b/config/ac-macros/ha_ndbcluster.m4
@@ -0,0 +1,163 @@
+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-sci],
+ AC_HELP_STRING([--with-ndb-sci=DIR],
+ [Provide MySQL with a custom location of
+ sci library. Given DIR, sci library is
+ assumed to be in $DIR/lib and header files
+ in $DIR/include.]),
+ [mysql_sci_dir=${withval}],
+ [mysql_sci_dir=""])
+
+ case "$mysql_sci_dir" in
+ "no" )
+ have_ndb_sci=no
+ AC_MSG_RESULT([-- not including sci transporter])
+ ;;
+ * )
+ if test -f "$mysql_sci_dir/lib/libsisci.a" -a \
+ -f "$mysql_sci_dir/include/sisci_api.h"; then
+ NDB_SCI_INCLUDES="-I$mysql_sci_dir/include"
+ NDB_SCI_LIBS="-L$mysql_sci_dir/lib -lsisci"
+ AC_MSG_RESULT([-- including sci transporter])
+ AC_DEFINE([NDB_SCI_TRANSPORTER], [1],
+ [Including Ndb Cluster DB sci transporter])
+ AC_SUBST(NDB_SCI_INCLUDES)
+ AC_SUBST(NDB_SCI_LIBS)
+ have_ndb_sci="yes"
+ AC_MSG_RESULT([found sci transporter in $mysql_sci_dir/{include, lib}])
+ else
+ AC_MSG_RESULT([could not find sci transporter in $mysql_sci_dir/{include, lib}])
+ fi
+ ;;
+ esac
+
+ 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_ARG_WITH([ndb-port],
+ [
+ --with-ndb-port Port for NDB Cluster management server],
+ [ndb_port="$withval"],
+ [ndb_port="default"])
+ AC_ARG_WITH([ndb-port-base],
+ [
+ --with-ndb-port-base Base port for NDB Cluster transporters],
+ [ndb_port_base="$withval"],
+ [ndb_port_base="default"])
+ AC_ARG_WITH([ndb-debug],
+ [
+ --without-ndb-debug Disable special ndb debug features],
+ [ndb_debug="$withval"],
+ [ndb_debug="default"])
+ AC_ARG_WITH([ndb-ccflags],
+ AC_HELP_STRING([--with-ndb-ccflags=CFLAGS],
+ [Extra CFLAGS for ndb compile]),
+ [ndb_ccflags=${withval}],
+ [ndb_ccflags=""])
+
+ case "$ndb_ccflags" in
+ "yes")
+ AC_MSG_RESULT([The --ndb-ccflags option requires a parameter (passed to CC for ndb compilation)])
+ ;;
+ *)
+ ndb_cxxflags_fix="$ndb_cxxflags_fix $ndb_ccflags"
+ ;;
+ esac
+
+ AC_MSG_CHECKING([for NDB Cluster options])
+ AC_MSG_RESULT([])
+
+ 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
+
+ case "$ndb_debug" in
+ yes )
+ AC_MSG_RESULT([-- including ndb extra debug options])
+ have_ndb_debug="yes"
+ ;;
+ full )
+ AC_MSG_RESULT([-- including ndb extra extra debug options])
+ have_ndb_debug="full"
+ ;;
+ no )
+ AC_MSG_RESULT([-- not including ndb extra debug options])
+ have_ndb_debug="no"
+ ;;
+ * )
+ have_ndb_debug="default"
+ ;;
+ esac
+
+ AC_MSG_RESULT([done.])
+])
+
+AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
+ AC_ARG_WITH([ndbcluster],
+ [
+ --with-ndbcluster Include the NDB Cluster table handler],
+ [ndbcluster="$withval"],
+ [ndbcluster=no])
+
+ AC_MSG_CHECKING([for NDB Cluster])
+
+ have_ndbcluster=no
+ ndbcluster_includes=
+ ndbcluster_libs=
+ ndb_mgmclient_libs=
+ case "$ndbcluster" in
+ yes )
+ AC_MSG_RESULT([Using NDB Cluster])
+ AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB])
+ have_ndbcluster="yes"
+ ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi"
+ ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a"
+ ndbcluster_system_libs=""
+ ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la"
+ 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)
+ AC_SUBST(ndb_mgmclient_libs)
+])
+
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_NDBCLUSTER SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_tina.m4 b/config/ac-macros/ha_tina.m4
new file mode 100644
index 00000000000..fe6e382ce20
--- /dev/null
+++ b/config/ac-macros/ha_tina.m4
@@ -0,0 +1,29 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_CSVDB
+dnl Sets HAVE_CSV_DB if --with-csv-storage-engine is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_CSVDB], [
+ AC_ARG_WITH([csv-storage-engine],
+ [
+ --with-csv-storage-engine
+ Enable the CSV Storage Engine],
+ [csvdb="$withval"],
+ [csvdb=no])
+ AC_MSG_CHECKING([for csv storage engine])
+
+ case "$csvdb" in
+ yes )
+ AC_DEFINE([HAVE_CSV_DB], [1], [Builds the CSV Storage Engine])
+ AC_MSG_RESULT([yes])
+ [csvdb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [csvdb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_CSV SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/large_file.m4 b/config/ac-macros/large_file.m4
new file mode 100644
index 00000000000..00c2fdf614e
--- /dev/null
+++ b/config/ac-macros/large_file.m4
@@ -0,0 +1,140 @@
+
+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,
+ [makes 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,
+ [Large files support 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
+ ])
+
diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4
new file mode 100644
index 00000000000..6f93f38f119
--- /dev/null
+++ b/config/ac-macros/misc.m4
@@ -0,0 +1,768 @@
+# Local macros for automake & autoconf
+
+# 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_PUSH(C++)
+if test "$ac_cv_prog_gxx" = "yes"
+then
+ # Add -Werror, remove -fbranch-probabilities (Bug #268)
+ CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-Wcheck//'`
+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_POP(C++)
+AC_DEFINE_UNQUOTED([SOCKET_SIZE_TYPE], [$mysql_cv_btype_last_arg_accept],
+ [The base type of the last arg to 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],
+ [The return type of qsort (int or void).])
+if test "$mysql_cv_type_qsort" = "void"
+then
+ AC_DEFINE_UNQUOTED([QSORT_TYPE_IS_VOID], [1], [qsort returns void])
+fi
+])
+
+#---START: Figure out whether to use 'struct rlimit' or 'struct rlimit64'
+AC_DEFUN([MYSQL_TYPE_STRUCT_RLIMIT],
+[ac_save_CXXFLAGS="$CXXFLAGS"
+AC_CACHE_CHECK([struct type to use with setrlimit], mysql_cv_btype_struct_rlimit,
+AC_LANG_PUSH(C++)
+if test "$ac_cv_prog_gxx" = "yes"
+then
+ # Add -Werror, remove -fbranch-probabilities (Bug #268)
+ CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-Wcheck//'`
+fi
+mysql_cv_btype_struct_rlimit=none
+[AC_TRY_COMPILE([#if defined(inline)
+#undef inline
+#endif
+#include <stdlib.h>
+#include <sys/resource.h>
+],
+[struct rlimit64 rl; setrlimit(RLIMIT_CORE, &rl);],
+mysql_cv_btype_struct_rlimit="struct rlimit64")]
+if test "$mysql_cv_btype_struct_rlimit" = "none"; then
+mysql_cv_btype_struct_rlimit="struct rlimit"
+fi)
+AC_LANG_POP(C++)
+AC_DEFINE_UNQUOTED([STRUCT_RLIMIT], [$mysql_cv_btype_struct_rlimit],
+ [The struct rlimit type to use with setrlimit])
+CXXFLAGS="$ac_save_CXXFLAGS"
+])
+#---END:
+
+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], [1],
+ [Timespec has a ts_sec instead of tv_sev])
+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], [1], [Have the tzname variable])
+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], [1], [system headers define 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], [1], [system headers define 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], [1], [system headers define 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], [1], [system headers define 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], [1],
+ [pthread_yield that doesn't take any arguments])
+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], [1],
+ [pthread_yield function with one argument])
+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], [1], [fp_except from ieeefp.h])
+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
+])
+
+# 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, [1],
+ [Signal handling is POSIX (sigset/sighold, etc)])
+elif test "$mysql_cv_signal_vintage" = "4.2bsd"; then
+AC_DEFINE([HAVE_BSD_SIGNALS], [1], [BSD style signals])
+elif test "$mysql_cv_signal_vintage" = svr3; then
+AC_DEFINE(HAVE_USG_SIGHOLD, [1], [sighold() is present and usable])
+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, [1], [getpwent() declaration present])
+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], [1],
+ [READLINE: your system defines TIOCGWINSZ in sys/ioctl.h.])
+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], [1], [Do we have FIONREAD])
+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, [1],
+ [declaration of TIOCSTAT in sys/ioctl.h])
+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, [1],
+ [d_ino member present in struct dirent])
+fi
+])
+
+AC_DEFUN([MYSQL_STRUCT_DIRENT_D_NAMLEN],
+[AC_REQUIRE([AC_HEADER_DIRENT])
+AC_MSG_CHECKING(if struct dirent has a d_namlen member)
+AC_CACHE_VAL(mysql_cv_dirent_has_dnamlen,
+[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 = (int)d.d_namlen;
+], mysql_cv_dirent_has_dnamlen=yes, mysql_cv_dirent_has_dnamlen=no)])
+AC_MSG_RESULT($mysql_cv_dirent_has_dnamlen)
+if test "$mysql_cv_dirent_has_dnamlen" = "yes"; then
+AC_DEFINE(STRUCT_DIRENT_HAS_D_NAMLEN, [1],
+ [d_namlen member present in struct dirent])
+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, [1], [sighandler type is void (*signal ()) ();])
+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], [1], [bool is not defined by all C++ compilators])
+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_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_VIO], [
+dnl
+dnl we always use vio: no need for special defines
+dnl
+ AC_DEFINE([HAVE_VIO_READ_BUFF], [1],
+ [Define to enable buffered read. This works only if syscalls
+ read/recv return as soon as there is some data in the kernel
+ buffer, no matter how big the given buffer is.])
+])
+
+# 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([$ac_declaration
+@%:@include <stdlib.h>],
+ [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 ---------------------------------------------------------------------------
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_BIG_TABLES
+dnl Sets BIG_TABLES if --with-big-tables is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_BIG_TABLES], [
+ AC_ARG_WITH([big-tables],
+ [
+ --with-big-tables Support tables with more than 4 G rows even on 32 bit platforms],
+ [bigtables="$withval"],
+ [bigtables=no])
+ AC_MSG_CHECKING([for big tables support])
+
+ case "$bigtables" in
+ yes )
+ AC_DEFINE([BIG_TABLES], [1], [Support big tables])
+ AC_MSG_RESULT([yes])
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_BIG_TABLES SECTION
+dnl ---------------------------------------------------------------------------
+
+dnl MYSQL_NEEDS_MYSYS_NEW
+AC_DEFUN([MYSQL_NEEDS_MYSYS_NEW],
+[AC_CACHE_CHECK([needs mysys_new helpers], mysql_use_mysys_new,
+[
+AC_LANG_PUSH(C++)
+AC_TRY_LINK([], [
+class A { public: int b; }; A *a=new A; a->b=10; delete a;
+], mysql_use_mysys_new=no, mysql_use_mysys_new=yes)
+AC_LANG_POP(C++)
+])
+if test "$mysql_use_mysys_new" = "yes"
+then
+ AC_DEFINE([USE_MYSYS_NEW], [1], [Needs to use mysys_new helpers])
+fi
+])
+
+
+AC_DEFUN([MYSQL_CHECK_CXX_VERSION], [
+case $SYSTEM_TYPE in
+ *netware*)
+ CXX_VERSION=`$CXX -version | grep -i version`
+ ;;
+ *)
+ CXX_VERSION=`$CXX --version | sed 1q`
+ if test $? -ne "0" -o -z "$CXX_VERSION"
+ then
+ CXX_VERSION=`$CXX -V 2>&1|sed 1q` # trying harder for Sun and SGI
+ fi
+ if test $? -ne "0" -o -z "$CXX_VERSION"
+ then
+ CXX_VERSION=`$CXX -v 2>&1|sed 1q` # even harder for Alpha
+ fi
+ if test $? -ne "0" -o -z "$CXX_VERSION"
+ then
+ CXX_VERSION=""
+ fi
+esac
+if test "$CXX_VERSION"
+then
+ AC_MSG_CHECKING("C++ compiler version");
+ AC_MSG_RESULT("$CXX $CXX_VERSION")
+fi
+AC_SUBST(CXX_VERSION)
+])
+
+AC_DEFUN([MYSQL_PROG_AR], [
+AC_REQUIRE([MYSQL_CHECK_CXX_VERSION])
+case $CXX_VERSION in
+ MIPSpro*)
+ AR=$CXX
+ ARFLAGS="-ar -o"
+ ;;
+ *Forte*)
+ AR=$CXX
+ ARFLAGS="-xar -o"
+ ;;
+ *)
+ if test -z "$AR"
+ then
+ AC_CHECK_PROG([AR], [ar], [ar])
+ fi
+ if test -z "$AR"
+ then
+ AC_MSG_ERROR([You need ar to build the library])
+ fi
+ if test -z "$ARFLAGS"
+ then
+ ARFLAGS="cru"
+ fi
+esac
+AC_SUBST(AR)
+AC_SUBST(ARFLAGS)
+])
diff --git a/config/ac-macros/openssl.m4 b/config/ac-macros/openssl.m4
new file mode 100644
index 00000000000..aa46dd45360
--- /dev/null
+++ b/config/ac-macros/openssl.m4
@@ -0,0 +1,133 @@
+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 /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/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
+ 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 "$TARGET_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[=DIR] 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" != "no"
+ then
+ if test "$openssl" != "yes"
+ then
+ if test -z "$openssl_includes"
+ then
+ openssl_includes="$openssl/include"
+ fi
+ if test -z "$openssl_libs"
+ then
+ openssl_libs="$openssl/lib"
+ fi
+ fi
+ MYSQL_FIND_OPENSSL([$openssl_includes], [$openssl_libs])
+ #force VIO use
+ 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], [1], [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)
+ if test ! -z "$openssl_includes"
+ then
+ AC_MSG_ERROR(Can't have --with-openssl-includes without --with-openssl);
+ fi
+ if test ! -z "$openssl_libs"
+ then
+ AC_MSG_ERROR(Can't have --with-openssl-libs without --with-openssl);
+ fi
+ fi
+ AC_SUBST(openssl_libs)
+ AC_SUBST(openssl_includes)
+])
diff --git a/config/ac-macros/readline.m4 b/config/ac-macros/readline.m4
new file mode 100644
index 00000000000..79c6479d15d
--- /dev/null
+++ b/config/ac-macros/readline.m4
@@ -0,0 +1,61 @@
+AC_DEFUN([MYSQL_CHECK_READLINE_DECLARES_HIST_ENTRY], [
+ AC_CACHE_CHECK([HIST_ENTRY is declared in readline/readline.h], mysql_cv_hist_entry_declared,
+ AC_TRY_COMPILE(
+ [
+ #include "stdio.h"
+ #include "readline/readline.h"
+ ],
+ [
+ HIST_ENTRY entry;
+ ],
+ [
+ mysql_cv_hist_entry_declared=yes
+ AC_DEFINE_UNQUOTED(HAVE_HIST_ENTRY, [1],
+ [HIST_ENTRY is defined in the outer libeditreadline])
+ ],
+ [mysql_cv_libedit_interface=no]
+ )
+ )
+])
+
+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], [1],
+ [used libedit interface (can we dereference result of rl_completion_entry_function)])
+ ],
+ [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], [1],
+ [used new readline interface (are rl_completion_func_t and rl_compentry_func_t defined)])
+ ],
+ [mysql_cv_new_rl_interface=no]
+ )
+ )
+])
diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4
new file mode 100644
index 00000000000..7af39db48be
--- /dev/null
+++ b/config/ac-macros/yassl.m4
@@ -0,0 +1,42 @@
+AC_CONFIG_FILES(extra/yassl/Makefile dnl
+extra/yassl/taocrypt/Makefile dnl
+extra/yassl/taocrypt/src/Makefile dnl
+extra/yassl/src/Makefile)
+
+AC_DEFUN([MYSQL_CHECK_YASSL], [
+ AC_MSG_CHECKING(for yaSSL)
+ AC_ARG_WITH([yassl], [ --with-yassl Include the yaSSL support],,)
+
+ if test "$with_yassl" = "yes"
+ then
+ if test "$openssl" != "no"
+ then
+ AC_MSG_ERROR([Cannot configure MySQL to use yaSSL and OpenSSL simultaneously.])
+ fi
+ AC_MSG_RESULT([using bundled yaSSL])
+ yassl_dir="extra/yassl"
+ openssl_libs="\
+ -L\$(top_builddir)/extra/yassl/src -lyassl\
+ -L\$(top_builddir)/extra/yassl/taocrypt/src -ltaocrypt"
+ openssl_includes="-I\$(top_srcdir)/extra/yassl/include"
+ AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.])
+
+ # System specific checks
+ yassl_integer_extra_cxxflags=""
+ case $SYSTEM_TYPE--$CXX_VERSION in
+ sparc*solaris*--*Sun*C++*5.6*)
+ # Disable inlining when compiling taocrypt/src/integer.cpp
+ yassl_integer_extra_cxxflags="+d"
+ ;;
+ esac
+ AC_SUBST([yassl_integer_extra_cxxflags])
+
+ else
+ yassl_dir=""
+ AC_MSG_RESULT(no)
+ fi
+ AC_SUBST(openssl_libs)
+ AC_SUBST(openssl_includes)
+ AC_SUBST(yassl_dir)
+ AM_CONDITIONAL([HAVE_YASSL], [ test "with_yassl" = "yes" ])
+])
diff --git a/config/ac-macros/zlib.m4 b/config/ac-macros/zlib.m4
new file mode 100644
index 00000000000..94a26f33dd3
--- /dev/null
+++ b/config/ac-macros/zlib.m4
@@ -0,0 +1,116 @@
+dnl Define zlib paths to point at bundled zlib
+
+AC_DEFUN([MYSQL_USE_BUNDLED_ZLIB], [
+ZLIB_INCLUDES="-I\$(top_srcdir)/zlib"
+ZLIB_LIBS="\$(top_builddir)/zlib/libz.la"
+dnl Omit -L$pkglibdir as it's always in the list of mysql_config deps.
+ZLIB_DEPS="-lz"
+zlib_dir="zlib"
+AC_SUBST([zlib_dir])
+mysql_cv_compress="yes"
+])
+
+dnl Auxiliary macro to check for zlib at given path
+
+AC_DEFUN([MYSQL_CHECK_ZLIB_DIR], [
+save_INCLUDES="$INCLUDES"
+save_LIBS="$LIBS"
+INCLUDES="$INCLUDES $ZLIB_INCLUDES"
+LIBS="$LIBS $ZLIB_LIBS"
+AC_CACHE_VAL([mysql_cv_compress],
+ [AC_TRY_LINK([#include <zlib.h>],
+ [return compress(0, (unsigned long*) 0, "", 0);],
+ [mysql_cv_compress="yes"
+ AC_MSG_RESULT([ok])],
+ [mysql_cv_compress="no"])
+ ])
+INCLUDES="$save_INCLUDES"
+LIBS="$save_LIBS"
+])
+
+dnl MYSQL_CHECK_ZLIB_WITH_COMPRESS
+dnl ------------------------------------------------------------------------
+dnl @synopsis MYSQL_CHECK_ZLIB_WITH_COMPRESS
+dnl
+dnl Provides the following configure options:
+dnl --with-zlib-dir=DIR
+dnl Possible DIR values are:
+dnl - "no" - the macro will disable use of compression functions
+dnl - "bundled" - means use zlib bundled along with MySQL sources
+dnl - empty, or not specified - the macro will try default system
+dnl library (if present), and in case of error will fall back to
+dnl bundled zlib
+dnl - zlib location prefix - given location prefix, the macro expects
+dnl to find the library headers in $prefix/include, and binaries in
+dnl $prefix/lib. If zlib headers or binaries weren't found at $prefix, the
+dnl macro bails out with error.
+dnl
+dnl If the library was found, this function #defines HAVE_COMPRESS
+dnl and configure variables ZLIB_INCLUDES (i.e. -I/path/to/zlib/include),
+dnl ZLIB_LIBS (i. e. -L/path/to/zlib/lib -lz) and ZLIB_DEPS which is
+dnl used in mysql_config and is always the same as ZLIB_LIBS except to
+dnl when we use the bundled zlib. In the latter case ZLIB_LIBS points to the
+dnl build dir ($top_builddir/zlib), while mysql_config must point to the
+dnl installation dir ($pkglibdir), so ZLIB_DEPS is set to point to
+dnl $pkglibdir.
+
+AC_DEFUN([MYSQL_CHECK_ZLIB_WITH_COMPRESS], [
+AC_MSG_CHECKING([for zlib compression library])
+case $SYSTEM_TYPE in
+*netware* | *modesto*)
+ AC_MSG_RESULT(ok)
+ AC_DEFINE([HAVE_COMPRESS], [1], [Define to enable compression support])
+ ;;
+ *)
+ AC_ARG_WITH([zlib-dir],
+ AC_HELP_STRING([--with-zlib-dir=DIR],
+ [Provide MySQL with a custom location of
+ compression library. Given DIR, zlib binary is
+ assumed to be in $DIR/lib and header files
+ in $DIR/include.]),
+ [mysql_zlib_dir=${withval}],
+ [mysql_zlib_dir=""])
+ case "$mysql_zlib_dir" in
+ "no")
+ mysql_cv_compress="no"
+ AC_MSG_RESULT([disabled])
+ ;;
+ "bundled")
+ MYSQL_USE_BUNDLED_ZLIB
+ AC_MSG_RESULT([using bundled zlib])
+ ;;
+ "")
+ ZLIB_INCLUDES=""
+ ZLIB_LIBS="-lz"
+ MYSQL_CHECK_ZLIB_DIR
+ if test "$mysql_cv_compress" = "no"; then
+ MYSQL_USE_BUNDLED_ZLIB
+ AC_MSG_RESULT([system-wide zlib not found, using one bundled with MySQL])
+ fi
+ ;;
+ *)
+ if test -f "$mysql_zlib_dir/lib/libz.a" -a \
+ -f "$mysql_zlib_dir/include/zlib.h"; then
+ ZLIB_INCLUDES="-I$mysql_zlib_dir/include"
+ ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz"
+ MYSQL_CHECK_ZLIB_DIR
+ fi
+ if test "x$mysql_cv_compress" != "xyes"; then
+ AC_MSG_ERROR([headers or binaries were not found in $mysql_zlib_dir/{include,lib}])
+ fi
+ ;;
+ esac
+ if test "$mysql_cv_compress" = "yes"; then
+ if test "x$ZLIB_DEPS" = "x"; then
+ ZLIB_DEPS="$ZLIB_LIBS"
+ fi
+ AC_SUBST([ZLIB_LIBS])
+ AC_SUBST([ZLIB_DEPS])
+ AC_SUBST([ZLIB_INCLUDES])
+ AC_DEFINE([HAVE_COMPRESS], [1], [Define to enable compression support])
+ fi
+ ;;
+esac
+])
+
+dnl ------------------------------------------------------------------------
diff --git a/configure.in b/configure.in
index 97eb0cb0edf..6ef98da33fb 100644
--- a/configure.in
+++ b/configure.in
@@ -1,23 +1,25 @@
dnl -*- ksh -*-
dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.52)dnl Minimum Autoconf version required.
+
AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line!
# remember to also change ndb version below and update version.c in ndb
-AM_INIT_AUTOMAKE(mysql, 4.1.15)
+AM_INIT_AUTOMAKE(mysql, 5.0.14-rc)
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
+SHARED_LIB_VERSION=15:0:0
# ndb version
-NDB_VERSION_MAJOR=4
-NDB_VERSION_MINOR=1
-NDB_VERSION_BUILD=15
-NDB_VERSION_STATUS=""
+NDB_VERSION_MAJOR=5
+NDB_VERSION_MINOR=0
+NDB_VERSION_BUILD=14
+NDB_VERSION_STATUS="rc"
# 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
@@ -29,33 +31,32 @@ MYSQL_VERSION_ID=`echo $MYSQL_NO_DASH_VERSION. | sed -e 's/[[^0-9.]]//g; s/\./
MYSQL_TCP_PORT_DEFAULT=3306
MYSQL_UNIX_ADDR_DEFAULT="/tmp/mysql.sock"
+dnl Include m4
+sinclude(config/ac-macros/alloca.m4)
+sinclude(config/ac-macros/check_cpu.m4)
+sinclude(config/ac-macros/character_sets.m4)
+sinclude(config/ac-macros/compiler_flag.m4)
+sinclude(config/ac-macros/ha_archive.m4)
+sinclude(config/ac-macros/ha_berkeley.m4)
+sinclude(config/ac-macros/ha_blackhole.m4)
+sinclude(config/ac-macros/ha_example.m4)
+sinclude(config/ac-macros/ha_federated.m4)
+sinclude(config/ac-macros/ha_innodb.m4)
+sinclude(config/ac-macros/ha_ndbcluster.m4)
+sinclude(config/ac-macros/ha_tina.m4)
+sinclude(config/ac-macros/large_file.m4)
+sinclude(config/ac-macros/misc.m4)
+sinclude(config/ac-macros/openssl.m4)
+sinclude(config/ac-macros/readline.m4)
+sinclude(config/ac-macros/yassl.m4)
+sinclude(config/ac-macros/zlib.m4)
+
# Remember to add a directory sql/share/LANGUAGE
AVAILABLE_LANGUAGES="\
czech danish dutch english estonian french german greek hungarian \
-italian japanese japanese-sjis korean norwegian norwegian-ny polish portuguese \
+italian japanese korean norwegian norwegian-ny polish portuguese \
romanian russian serbian slovak spanish swedish ukrainian"
-# Generate make rules for all error messages
-AVAILABLE_LANGUAGES_ERRORS=
-AVAILABLE_LANGUAGES_ERRORS_RULES=$srcdir/ac_available_languages_fragment
-rm -f $AVAILABLE_LANGUAGES_ERRORS_RULES
-for i in $AVAILABLE_LANGUAGES
-do
- AVAILABLE_LANGUAGES_ERRORS="$AVAILABLE_LANGUAGES_ERRORS $i/errmsg.sys"
- case $host_os in
- netware* | modesto*)
- echo "$i/errmsg.sys: $i/errmsg.txt
- \$(top_builddir)/extra/comp_err.linux -C\$(srcdir)/charsets/ $i/errmsg.txt $i/errmsg.sys" \
- >> $AVAILABLE_LANGUAGES_ERRORS_RULES
- ;;
- *)
- echo "$i/errmsg.sys: $i/errmsg.txt
- \$(top_builddir)/extra/comp_err -C\$(srcdir)/charsets/ $i/errmsg.txt $i/errmsg.sys" \
- >> $AVAILABLE_LANGUAGES_ERRORS_RULES
- ;;
- esac
-done
-
#####
#####
@@ -71,7 +72,6 @@ AC_DEFINE_UNQUOTED([DOT_FRM_VERSION], [$DOT_FRM_VERSION],
AC_SUBST(SHARED_LIB_VERSION)
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])
@@ -118,14 +118,11 @@ AC_SUBST(SAVE_LDFLAGS)
AC_SUBST(SAVE_CXXLDFLAGS)
AC_SUBST(CXXLDFLAGS)
-AC_PREREQ(2.52)dnl Minimum Autoconf version required.
-
#AC_ARG_PROGRAM # Automaticly invoked by AM_INIT_AUTOMAKE
+
AM_SANITY_CHECK
# This is needed is SUBDIRS is set
AC_PROG_MAKE_SET
-# This generates rules for webpage generation for the MySQL homepage.
-AM_CONDITIONAL(LOCAL, test -d ../web/SitePages)
##############################################################################
# The below section needs to be done before AC_PROG_CC
@@ -134,6 +131,7 @@ AM_CONDITIONAL(LOCAL, test -d ../web/SitePages)
# Hack for OS X/Darwin and Metrowerks CodeWarrior
AC_ARG_WITH(darwin-mwcc,
[ --with-darwin-mwcc Use Metrowerks CodeWarrior wrappers on OS X/Darwin],[
+ if [ "with_darwin_mwcc" = yes ] ; then
builddir=`pwd`
ccwrapper="$builddir/support-files/MacOSX/mwcc-wrapper"
arwrapper="$builddir/support-files/MacOSX/mwar-wrapper"
@@ -145,7 +143,7 @@ AC_ARG_WITH(darwin-mwcc,
export CC CXX LD AR RANLIB
AC_SUBST(AR)
AC_SUBST(RANLIB)
- with_darwin_mwcc=yes
+ fi
])
AM_CONDITIONAL(DARWIN_MWCC, test x$with_darwin_mwcc = xyes)
@@ -199,23 +197,8 @@ then
else
CC_VERSION=""
fi
-case $SYSTEM_TYPE in
- *netware*)
-CXX_VERSION=`$CXX -version | grep -i version`
- ;;
- *)
-CXX_VERSION=`$CXX --version | sed 1q`
- ;;
-esac
-if test $? -eq "0"
-then
- AC_MSG_CHECKING("C++ compiler version");
- AC_MSG_RESULT("$CXX $CXX_VERSION")
-else
-CXX_VERSION=""
-fi
-AC_SUBST(CXX_VERSION)
AC_SUBST(CC_VERSION)
+MYSQL_CHECK_CXX_VERSION
# Fix for sgi gcc / sgiCC which tries to emulate gcc
if test "$CC" = "sgicc"
@@ -294,48 +277,6 @@ AC_TRY_RUN([
;;
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
@@ -362,7 +303,7 @@ case "$target_os" in
AC_SYS_COMPILER_FLAG(-belf,sco_belf_option,CFLAGS,[],[
case "$LDFLAGS" in
*-belf*) ;;
- *) echo "Adding -belf option to ldflags."
+ *) AC_MSG_WARN([Adding -belf option to ldflags.])
LDFLAGS="$LDFLAGS -belf"
;;
esac
@@ -373,7 +314,7 @@ case "$target_os" in
case "$LDFLAGS" in
*-belf*) ;;
*)
- echo "Adding -belf option to ldflags."
+ AC_MSG_WARN([Adding -belf option to ldflags.])
LDFLAGS="$LDFLAGS -belf"
;;
esac
@@ -403,37 +344,23 @@ AC_SUBST(CXXFLAGS)
AC_SUBST(LD)
AC_SUBST(INSTALL_SCRIPT)
-export CC CXX CFLAGS LD LDFLAGS AR
+export CC CXX CFLAGS LD LDFLAGS AR ARFLAGS
-ndb_cxxflags_fix=
-if test "$GXX" = "yes"
+if test "$GCC" = "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 echo $CXX | grep gcc > /dev/null 2>&1
- then
- AC_MSG_CHECKING([if CXX is gcc 3 or 4])
- if $CXX -v 2>&1 | grep 'version [[34]]' > /dev/null 2>&1
- then
- AC_MSG_RESULT([yes])
- AC_MSG_NOTICE([using MySQL tricks to avoid linking C++ code with C++ libraries])
- CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL"
- else
- AC_MSG_RESULT([no])
- fi
- fi
+ AC_DEFINE([HAVE_EXPLICIT_TEMPLATE_INSTANTIATION],
+ [1], [Defined by configure. Use explicit template instantiation.])
fi
+MYSQL_PROG_AR
+
# Avoid bug in fcntl on some versions of linux
AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os")
-# Any wariation of Linux
+# Any variation of Linux
if expr "$target_os" : "[[Ll]]inux.*" > /dev/null
then
MYSQLD_DEFAULT_SWITCHES="--skip-locking"
@@ -506,35 +433,35 @@ PS=$ac_cv_path_PS
# Linux style
if $PS p $$ 2> /dev/null | grep $0 > /dev/null
then
- FIND_PROC="$PS p \$\$PID | grep -v grep | grep mysqld > /dev/null"
+ FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null"
# Solaris
elif $PS -fp $$ 2> /dev/null | grep $0 > /dev/null
then
- FIND_PROC="$PS -p \$\$PID | grep -v grep | grep mysqld > /dev/null"
+ FIND_PROC="$PS -p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null"
# BSD style
elif $PS -uaxww 2> /dev/null | grep $0 > /dev/null
then
- FIND_PROC="$PS -uaxww | grep -v grep | grep mysqld | grep \" \$\$PID \" > /dev/null"
+ FIND_PROC="$PS -uaxww | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null"
# SysV style
elif $PS -ef 2> /dev/null | grep $0 > /dev/null
then
- FIND_PROC="$PS -ef | grep -v grep | grep mysqld | grep \" \$\$PID \" > /dev/null"
+ FIND_PROC="$PS -ef | grep -v grep | 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 -v grep | grep mysqld > /dev/null"
+ FIND_PROC="$PS \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null"
else
case $SYSTEM_TYPE in
*freebsd*)
- FIND_PROC="$PS p \$\$PID | grep -v grep | grep mysqld > /dev/null"
+ FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null"
;;
*darwin*)
- FIND_PROC="$PS -uaxww | grep -v grep | grep mysqld | grep \" \$\$PID \" > /dev/null"
+ FIND_PROC="$PS -uaxww | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null"
;;
*cygwin*)
- FIND_PROC="$PS -e | grep -v grep | grep mysqld | grep \" \$\$PID \" > /dev/null"
+ FIND_PROC="$PS -e | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null"
;;
- *netware* | *modesto*)
+ *netware*)
FIND_PROC=
;;
*)
@@ -654,18 +581,6 @@ AC_ARG_WITH(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.],
@@ -722,20 +637,6 @@ else
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], [1], [Use MySQL 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
@@ -799,7 +700,8 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.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 sys/resource.h sys/param.h)
+ sys/ioctl.h malloc.h sys/malloc.h sys/ipc.h sys/shm.h linux/config.h \
+ sys/resource.h sys/param.h)
#--------------------------------------------------------------------
# Check for system libraries. Adds the library to $LIBS
@@ -826,6 +728,22 @@ AC_CHECK_FUNC(crypt, AC_DEFINE([HAVE_CRYPT], [1], [crypt]))
AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4, sem_init))
MYSQL_CHECK_ZLIB_WITH_COMPRESS
+# For large pages support
+if test "$TARGET_LINUX" = "true"
+then
+ # For SHM_HUGETLB on Linux
+ AC_CHECK_DECLS(SHM_HUGETLB,
+ AC_DEFINE([HAVE_LARGE_PAGES], [1],
+ [Define if you have large pages support])
+ AC_DEFINE([HUGETLB_USE_PROC_MEMINFO], [1],
+ [Define if /proc/meminfo shows the huge page size (Linux only)])
+ , ,
+ [
+#include <sys/shm.h>
+ ]
+ )
+fi
+
#--------------------------------------------------------------------
# Check for TCP wrapper support
#--------------------------------------------------------------------
@@ -913,7 +831,7 @@ int main()
[ USE_PSTACK=no ])
pstack_libs=
pstack_dirs=
- if test "$USE_PSTACK" = yes -a "$TARGET_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no"
+ if test "$USE_PSTACK" = yes -a "$TARGET_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386"
then
have_libiberty= have_libbfd=
my_save_LIBS="$LIBS"
@@ -998,6 +916,7 @@ esac
MAX_C_OPTIMIZE="-O3"
MAX_CXX_OPTIMIZE="-O3"
+ndb_cxxflags_fix=
case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in
# workaround for Sun Forte/x86 see BUG#4681
*solaris*-i?86-no)
@@ -1019,7 +938,7 @@ 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"
+ AC_MSG_WARN([Fixing broken include files for $SYSTEM_TYPE])
echo " - Creating local copy of widec.h"
if test ! -d include
then
@@ -1033,7 +952,7 @@ case $SYSTEM_TYPE in
*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"
+ AC_MSG_WARN([Fixing broken include files for $SYSTEM_TYPE])
echo " - Creating local copy of widec.h"
if test ! -d include
then
@@ -1045,7 +964,7 @@ case $SYSTEM_TYPE in
CXXFLAGS="$CXXFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
;;
*solaris2.5.1*)
- echo "Enabling getpass() workaround for Solaris 2.5.1"
+ AC_MSG_WARN([Enabling getpass() workaround for Solaris 2.5.1])
CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS -DHAVE_RWLOCK_T";
CXXFLAGS="$CXXFLAGS -DHAVE_RWLOCK_T -DSOLARIS"
;;
@@ -1054,26 +973,26 @@ case $SYSTEM_TYPE in
CXXFLAGS="$CXXFLAGS -DHAVE_RWLOCK_T"
;;
*SunOS*)
- echo "Enabling getpass() workaround for SunOS"
+ AC_MSG_WARN([Enabling getpass() workaround for SunOS])
CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS";
;;
*hpux10.20*)
- echo "Enabling workarounds for hpux 10.20"
+ AC_MSG_WARN([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"
+ AC_MSG_WARN([Using --with-named-thread=-lpthread])
with_named_thread="-lcma"
fi
;;
*hpux11.*)
- echo "Enabling workarounds for hpux 11"
+ AC_MSG_WARN([Enabling workarounds for hpux 11])
CFLAGS="$CFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -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 -DSNPRINTF_RETURN_TRUNC -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"
+ AC_MSG_WARN([Using --with-named-thread=-lpthread])
with_named_thread="-lpthread"
fi
# Fixes for HPUX 11.0 compiler
@@ -1138,7 +1057,7 @@ case $SYSTEM_TYPE in
fi
;;
*freebsd*)
- echo "Adding fix for interrupted reads"
+ AC_MSG_WARN([Adding fix for interrupted reads])
OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
if test "$OSVERSION" -gt "480100" && \
test "$OSVERSION" -lt "500000" || \
@@ -1151,13 +1070,13 @@ case $SYSTEM_TYPE in
fi
;;
*netbsd*)
- echo "Adding flag -Dunix"
+ AC_MSG_WARN([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"
+ AC_MSG_WARN([Adding fix for BSDI])
CFLAGS="$CFLAGS -D__BSD__ -DHAVE_BROKEN_REALPATH"
AC_DEFINE_UNQUOTED([SOCKOPT_OPTLEN_TYPE], [size_t],
[Last argument to get/setsockopt])
@@ -1165,13 +1084,13 @@ case $SYSTEM_TYPE in
*sgi-irix6*)
if test "$with_named_thread" = "no"
then
- echo "Using --with-named-thread=-lpthread"
+ AC_MSG_WARN([Using --with-named-thread=-lpthread])
with_named_thread="-lpthread"
fi
CXXFLAGS="$CXXFLAGS -D_BOOL"
;;
*aix4.3*)
- echo "Adding defines for AIX"
+ AC_MSG_WARN([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"
;;
@@ -1179,11 +1098,11 @@ 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"
+ AC_MSG_WARN([Adding defines for DEC OSF on alpha])
CFLAGS="$CFLAGS -mieee"
CXXFLAGS="$CXXFLAGS -mieee"
fi
- echo "Adding defines for OSF1"
+ AC_MSG_WARN([Adding defines for OSF1])
# gethostbyname_r is deprecated and doesn't work ok on OSF1
CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC"
CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC"
@@ -1298,7 +1217,7 @@ esac
with_posix_threads="no"
# Search thread lib on Linux
-if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
+if test "$with_named_thread" = "no"
then
AC_MSG_CHECKING("Linux threads")
if test "$TARGET_LINUX" = "true"
@@ -1455,20 +1374,20 @@ then
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";
+ 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";
+ 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; };
+ AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.])
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.]);
+ 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")
@@ -1504,8 +1423,7 @@ then
fi
AC_MSG_RESULT(yes)
else
- AC_MSG_RESULT(failed)
- { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
+ AC_MSG_ERROR([configure: error: Can't find thread library on SCO/Caldera system. See the Installation chapter in the Reference Manual.])
fi
else
AC_MSG_RESULT(no)
@@ -1513,7 +1431,7 @@ then
fi
# Hack for Siemens UNIX
-if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
+if test "$with_named_thread" = "no"
then
AC_MSG_CHECKING("Siemens threads")
if test -f /usr/lib/libxnet.so -a "$SYSTEM_TYPE" = "sni-sysv4"
@@ -1541,7 +1459,7 @@ fi
# 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"
+if test "$with_named_thread" = "no"
then
AC_MSG_CHECKING("Solaris threads")
if test -f /usr/lib/libpthread.so -a -f /usr/lib/libthread.so
@@ -1559,14 +1477,21 @@ if test "$with_named_thread" != "no"
then
LIBS="$with_named_thread $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"
+ # 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
- # pthread_create is in standard libraries (As in BSDI 3.0)
- AC_MSG_CHECKING("for pthread_create in -libc");
+ AC_MSG_CHECKING("for pthread_create in -lpthread");
+ ac_save_LIBS="$LIBS"
+ LIBS="$LIBS -lpthread"
AC_TRY_LINK(
[#include <pthread.h>],
[ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
@@ -1574,39 +1499,23 @@ else
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"
- LIBS="$LIBS -lpthread"
+ LIBS=" $ac_save_LIBS -lpthreads"
+ AC_MSG_CHECKING("for pthread_create in -lpthreads");
AC_TRY_LINK(
[#include <pthread.h>],
- [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
+ [ 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"
- AC_MSG_CHECKING("for pthread_create in -lpthreads");
+ # This is for FreeBSD
+ LIBS="$ac_save_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
- # This is for FreeBSD
- LIBS="$ac_save_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"
- fi
- fi
fi
fi
fi
@@ -1646,7 +1555,7 @@ AC_SUBST(LIBDL)
# System characteristics
case $SYSTEM_TYPE in
- *netware* | *modesto*) ;;
+ *netware*) ;;
*)
AC_SYS_RESTARTABLE_SYSCALLS
;;
@@ -1676,10 +1585,12 @@ else
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"
+ DEBUG_CFLAGS="-g -DDEBUG -sym internal,codeview4"
+ DEBUG_CXXFLAGS="-g -DDEBUG -sym internal,codeview4"
+ DEBUG_OPTIMIZE_CC="-DDEBUG"
+ DEBUG_OPTIMIZE_CXX="-DDEBUG"
+ OPTIMIZE_CFLAGS="-O3 -DNDEBUG"
+ OPTIMIZE_CXXFLAGS="-O3 -DNDEBUG"
fi
AC_ARG_WITH(debug,
@@ -1694,8 +1605,8 @@ then
elif test "$with_debug" = "full"
then
# Full debug. Very slow in some cases
- CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC -DUNIV_DEBUG $CFLAGS"
- CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC -DUNIV_DEBUG $CXXFLAGS"
+ CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS"
+ CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS"
else
# Optimized version. No debug
CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS"
@@ -1768,6 +1679,7 @@ AC_TYPE_OFF_T
AC_STRUCT_ST_RDEV
AC_HEADER_TIME
AC_STRUCT_TM
+MYSQL_NEEDS_MYSYS_NEW
# 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)
@@ -1782,6 +1694,7 @@ 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(short, 2)
AC_CHECK_SIZEOF(int, 4)
if test "$ac_cv_sizeof_int" -eq 0
then
@@ -1939,7 +1852,7 @@ if test "$GCC" != "yes"; then
AC_SYS_COMPILER_FLAG(-nolib_inline,nolib_inline,CFLAGS,[],[])
fi
-AC_FUNC_MMAP
+#AC_FUNC_MMAP
AC_TYPE_SIGNAL
MYSQL_TYPE_QSORT
AC_FUNC_UTIME_NULL
@@ -1950,7 +1863,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
- mkstemp mlockall perror poll pread pthread_attr_create \
+ mkstemp mlockall perror poll pread pthread_attr_create mmap getpagesize \
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 \
@@ -2016,9 +1929,12 @@ AC_CHECK_DECLS(madvise, [], [], [#if HAVE_SYS_MMAN_H
# with respect to ANSI C++
# We also remove the -fbranch-probabilities option as this will give warnings
# about not profiled code, which confuses configure
+# We also must remove -W and -Wcheck which on icc produces warnings that
+# we don't want to catch with -Werror
+
if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
then
- CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'`
+ CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-ansi//; s/-pedantic//; s/-Wcheck//'`
fi
AC_TRY_COMPILE(
@@ -2053,7 +1969,7 @@ 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//'`
+ CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-ansi//; s/-pedantic//; s/-Wcheck//'`
fi
AC_TRY_COMPILE(
[#undef inline
@@ -2086,7 +2002,7 @@ 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//'`
+ CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-ansi//; s/-pedantic//; s/-Wcheck//'`
fi
AC_TRY_COMPILE(
[#undef inline
@@ -2112,11 +2028,9 @@ then
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(
+# 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
@@ -2149,7 +2063,6 @@ mysql_cv_mutex_init_args=POSIX, mysql_cv_mutex_init_args=other))
AC_DEFINE([HAVE_NONPOSIX_PTHREAD_MUTEX_INIT], [1],
[For some non posix threads])
fi
-fi
#---END:
#---START: Used in for client configure
@@ -2307,17 +2220,28 @@ if test "$with_tools" = "yes"
then
if test "$THREAD_SAFE_CLIENT" = "no"
then
- echo "Warning: extra-tools disabled because --enable-thread-safe-client wasn't used"
+ AC_MSG_WARN([extra-tools disabled because --enable-thread-safe-client wasn't used])
else
tools_dirs="tools"
fi
fi
+
+AC_ARG_WITH([mysqlmanager],
+ AC_HELP_STRING([--with-mysqlmanager], [Build the mysqlmanager binary: yes/no (default: build if server is built.)]),
+ [if test "x${withval}" != "xno"; then
+ tools_dirs="$tools_dirs server-tools"
+ fi],
+ [if test "x${with_server}" = "xyes"; then
+ tools_dirs="$tools_dirs server-tools"
+ fi]
+)
+
AC_SUBST(tools_dirs)
#MYSQL_CHECK_CPU
-MYSQL_CHECK_MYSQLFS
MYSQL_CHECK_VIO
MYSQL_CHECK_OPENSSL
+MYSQL_CHECK_YASSL
libmysqld_dirs=
if test "$with_embedded_server" = "yes"
@@ -2472,433 +2396,7 @@ AC_SUBST(readline_basedir)
AC_SUBST(readline_link)
AC_SUBST(readline_h_ln_cmd)
-
-dnl In order to add new charset, you must add charset name to
-dnl this CHARSETS_AVAILABLE list and sql/share/charsets/Index.xml.
-dnl If the character set uses strcoll or other special handling,
-dnl you must also create strings/ctype-$charset_name.c
-
-AC_DIVERT_PUSH(0)
-
-define(CHARSETS_AVAILABLE0,binary)
-define(CHARSETS_AVAILABLE1,armscii8 ascii big5 cp1250 cp1251 cp1256 cp1257)
-define(CHARSETS_AVAILABLE2,cp850 cp852 cp866 cp932 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_AVAILABLE0 CHARSETS_AVAILABLE1 CHARSETS_AVAILABLE2 CHARSETS_AVAILABLE3 CHARSETS_AVAILABLE4 CHARSETS_AVAILABLE5"
-CHARSETS_COMPLEX="big5 cp1250 cp932 euckr gb2312 gbk latin1 latin2 sjis tis620 ucs2 ujis utf8"
-
-AC_DIVERT_POP
-
-AC_ARG_WITH(charset,
- [ --with-charset=CHARSET
- Default character set, use one of:
- CHARSETS_AVAILABLE0
- CHARSETS_AVAILABLE1
- CHARSETS_AVAILABLE2
- CHARSETS_AVAILABLE3
- CHARSETS_AVAILABLE4
- CHARSETS_AVAILABLE5],
- [default_charset="$withval"],
- [default_charset="$DEFAULT_CHARSET"])
-
-AC_ARG_WITH(collation,
- [ --with-collation=COLLATION
- Default collation],
- [default_collation="$withval"],
- [default_collation="default"])
-
-
-AC_ARG_WITH(extra-charsets,
- [ --with-extra-charsets=CHARSET[,CHARSET,...]
- Use charsets in addition to default (none, complex,
- all, or a list selected from the above sets)],
- [extra_charsets="$withval"],
- [extra_charsets="none"])
-
-
-AC_MSG_CHECKING("character sets")
-
-CHARSETS="$default_charset latin1 utf8"
-
-if test "$extra_charsets" = no; then
- CHARSETS="$CHARSETS"
-elif test "$extra_charsets" = none; then
- CHARSETS="$CHARSETS"
-elif test "$extra_charsets" = complex; then
- CHARSETS="$CHARSETS $CHARSETS_COMPLEX"
- AC_DEFINE([DEFINE_ALL_CHARACTER_SETS],1,[all charsets are available])
-elif test "$extra_charsets" = all; then
- CHARSETS="$CHARSETS $CHARSETS_AVAILABLE"
- AC_DEFINE([DEFINE_ALL_CHARACTER_SETS],1,[all charsets are available])
-else
- EXTRA_CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
- CHARSETS="$CHARSETS $EXTRA_CHARSETS"
-fi
-
-for cs in $CHARSETS
-do
- case $cs in
- armscii8)
- AC_DEFINE(HAVE_CHARSET_armscii8, 1,
- [Define to enable charset armscii8])
- ;;
- ascii)
- AC_DEFINE(HAVE_CHARSET_ascii, 1,
- [Define to enable ascii character set])
- ;;
- big5)
- AC_DEFINE(HAVE_CHARSET_big5, 1, [Define to enable charset big5])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, [1], [ ])
- ;;
- binary)
- ;;
- cp1250)
- AC_DEFINE(HAVE_CHARSET_cp1250, 1, [Define to enable cp1250])
- ;;
- cp1251)
- AC_DEFINE(HAVE_CHARSET_cp1251, 1, [Define to enable charset cp1251])
- ;;
- cp1256)
- AC_DEFINE(HAVE_CHARSET_cp1256, 1, [Define to enable charset cp1256])
- ;;
- cp1257)
- AC_DEFINE(HAVE_CHARSET_cp1257, 1, [Define to enable charset cp1257])
- ;;
- cp850)
- AC_DEFINE(HAVE_CHARSET_cp850, 1, [Define to enable charset cp850])
- ;;
- cp852)
- AC_DEFINE(HAVE_CHARSET_cp852, 1, [Define to enable charset cp852])
- ;;
- cp866)
- AC_DEFINE(HAVE_CHARSET_cp866, 1, [Define to enable charset cp866])
- ;;
- cp932)
- AC_DEFINE(HAVE_CHARSET_cp932, 1, [Define to enable charset cp932])
- AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- dec8)
- AC_DEFINE(HAVE_CHARSET_dec8, 1, [Define to enable charset dec8])
- ;;
- euckr)
- AC_DEFINE(HAVE_CHARSET_euckr, 1, [Define to enable charset euckr])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- gb2312)
- AC_DEFINE(HAVE_CHARSET_gb2312, 1, [Define to enable charset gb2312])
- AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- gbk)
- AC_DEFINE(HAVE_CHARSET_gbk, 1, [Define to enable charset gbk])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- geostd8)
- AC_DEFINE(HAVE_CHARSET_geostd8, 1, [Define to enable charset geostd8])
- ;;
- greek)
- AC_DEFINE(HAVE_CHARSET_greek, 1, [Define to enable charset greek])
- ;;
- hebrew)
- AC_DEFINE(HAVE_CHARSET_hebrew, 1, [Define to enable charset hebrew])
- ;;
- hp8)
- AC_DEFINE(HAVE_CHARSET_hp8, 1, [Define to enable charset hp8])
- ;;
- keybcs2)
- AC_DEFINE(HAVE_CHARSET_keybcs2, 1, [Define to enable charset keybcs2])
- ;;
- koi8r)
- AC_DEFINE(HAVE_CHARSET_koi8r, 1, [Define to enable charset koi8r])
- ;;
- koi8u)
- AC_DEFINE(HAVE_CHARSET_koi8u, 1, [Define to enable charset koi8u])
- ;;
- latin1)
- AC_DEFINE(HAVE_CHARSET_latin1, 1, [Define to enable charset latin1])
- ;;
- latin2)
- AC_DEFINE(HAVE_CHARSET_latin2, 1, [Define to enable charset latin2])
- ;;
- latin5)
- AC_DEFINE(HAVE_CHARSET_latin5, 1, [Define to enable charset latin5])
- ;;
- latin7)
- AC_DEFINE(HAVE_CHARSET_latin7, 1, [Define to enable charset latin7])
- ;;
- macce)
- AC_DEFINE(HAVE_CHARSET_macce, 1, [Define to enable charset macce])
- ;;
- macroman)
- AC_DEFINE(HAVE_CHARSET_macroman, 1,
- [Define to enable charset macroman])
- ;;
- sjis)
- AC_DEFINE(HAVE_CHARSET_sjis, 1, [Define to enable charset sjis])
- AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- swe7)
- AC_DEFINE(HAVE_CHARSET_swe7, 1, [Define to enable charset swe7])
- ;;
- tis620)
- AC_DEFINE(HAVE_CHARSET_tis620, 1, [Define to enable charset tis620])
- ;;
- ucs2)
- AC_DEFINE(HAVE_CHARSET_ucs2, 1, [Define to enable charset ucs2])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- ujis)
- AC_DEFINE(HAVE_CHARSET_ujis, 1, [Define to enable charset ujis])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- utf8)
- AC_DEFINE(HAVE_CHARSET_utf8, 1, [Define to enable ut8])
- AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- *)
- AC_MSG_ERROR([Charset '$cs' not available. (Available are: $CHARSETS_AVAILABLE).
- See the Installation chapter in the Reference Manual.]);
- esac
-done
-
-
- default_charset_collations=""
-
-case $default_charset in
- armscii8)
- default_charset_default_collation="armscii8_general_ci"
- default_charset_collations="armscii8_general_ci armscii8_bin"
- ;;
- ascii)
- default_charset_default_collation="ascii_general_ci"
- default_charset_collations="ascii_general_ci ascii_bin"
- ;;
- big5)
- 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_cs cp1250_bin"
- ;;
- cp1251)
- default_charset_default_collation="cp1251_general_ci"
- default_charset_collations="cp1251_general_ci cp1251_general_cs cp1251_bin cp1251_bulgarian_ci cp1251_ukrainian_ci"
- ;;
- cp1256)
- default_charset_default_collation="cp1256_general_ci"
- default_charset_collations="cp1256_general_ci cp1256_bin"
- ;;
- cp1257)
- default_charset_default_collation="cp1257_general_ci"
- default_charset_collations="cp1257_general_ci cp1257_lithuanian_ci cp1257_bin"
- ;;
- cp850)
- default_charset_default_collation="cp850_general_ci"
- default_charset_collations="cp850_general_ci cp850_bin"
- ;;
- cp852)
- default_charset_default_collation="cp852_general_ci"
- default_charset_collations="cp852_general_ci cp852_bin"
- ;;
- cp866)
- default_charset_default_collation="cp866_general_ci"
- default_charset_collations="cp866_general_ci cp866_bin"
- ;;
- cp932)
- default_charset_default_collation="cp932_japanese_ci"
- default_charset_collations="cp932_japanese_ci cp932_bin"
- ;;
- dec8)
- default_charset_default_collation="dec8_swedish_ci"
- default_charset_collations="dec8_swedish_ci dec8_bin"
- ;;
- euckr)
- default_charset_default_collation="euckr_korean_ci"
- default_charset_collations="euckr_korean_ci euckr_bin"
- ;;
- gb2312)
- default_charset_default_collation="gb2312_chinese_ci"
- default_charset_collations="gb2312_chinese_ci gb2312_bin"
- ;;
- gbk)
- 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"
- ;;
- hebrew)
- default_charset_default_collation="hebrew_general_ci"
- default_charset_collations="hebrew_general_ci hebrew_bin"
- ;;
- hp8)
- default_charset_default_collation="hp8_english_ci"
- default_charset_collations="hp8_english_ci hp8_bin"
- ;;
- keybcs2)
- default_charset_default_collation="keybcs2_general_ci"
- default_charset_collations="keybcs2_general_ci keybcs2_bin"
- ;;
- koi8r)
- default_charset_default_collation="koi8r_general_ci"
- default_charset_collations="koi8r_general_ci koi8r_bin"
- ;;
- koi8u)
- default_charset_default_collation="koi8u_general_ci"
- default_charset_collations="koi8u_general_ci koi8u_bin"
- ;;
- latin1)
- default_charset_default_collation="latin1_swedish_ci"
- default_charset_collations="latin1_general_ci latin1_general_cs latin1_bin latin1_german1_ci latin1_german2_ci latin1_danish_ci latin1_spanish_ci latin1_swedish_ci"
- ;;
- latin2)
- default_charset_default_collation="latin2_general_ci"
- default_charset_collations="latin2_general_ci latin2_bin latin2_czech_cs latin2_hungarian_ci latin2_croatian_ci"
- ;;
- latin5)
- default_charset_default_collation="latin5_turkish_ci"
- default_charset_collations="latin5_turkish_ci latin5_bin"
- ;;
- latin7)
- default_charset_default_collation="latin7_general_ci"
- default_charset_collations="latin7_general_ci latin7_general_cs latin7_bin latin7_estonian_cs"
- ;;
- macce)
- default_charset_default_collation="macce_general_ci"
- default_charset_collations="macce_general_ci macce_bin"
- ;;
- macroman)
- default_charset_default_collation="macroman_general_ci"
- default_charset_collations="macroman_general_ci macroman_bin"
- ;;
- sjis)
- default_charset_default_collation="sjis_japanese_ci"
- default_charset_collations="sjis_japanese_ci sjis_bin"
- ;;
- swe7)
- default_charset_default_collation="swe7_swedish_ci"
- default_charset_collations="swe7_swedish_ci swe7_bin"
- ;;
- tis620)
- default_charset_default_collation="tis620_thai_ci"
- default_charset_collations="tis620_thai_ci tis620_bin"
- ;;
- ucs2)
- default_charset_default_collation="ucs2_general_ci"
- 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_persian_ci 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"
- default_charset_collations="ujis_japanese_ci ujis_bin"
- ;;
- utf8)
- default_charset_default_collation="utf8_general_ci"
- if test "$default_collation" = "utf8_general_cs"; then
- # For those who explicitly desire "utf8_general_cs", support it,
- # and then also set the CPP switch enabling that code.
- UTFC="utf8_general_cs"
- AC_DEFINE([HAVE_UTF8_GENERAL_CS], [1], [certain Japanese customer])
- else
- 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_persian_ci 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"
- fi
- default_charset_collations="$UTFC"
- ;;
- *)
- AC_MSG_ERROR([Charset $cs not available. (Available are: $CHARSETS_AVAILABLE).
- See the Installation chapter in the Reference Manual.]);
-esac
-
-if test "$default_collation" = default; then
- default_collation=$default_charset_default_collation
-fi
-
-valid_default_collation=no
-for cl in $default_charset_collations
-do
- if test x"$cl" = x"$default_collation"
- then
- valid_default_collation=yes
- break
- fi
-done
-
-if test x$valid_default_collation = xyes
-then
- AC_MSG_RESULT([default: $default_charset, collation: $default_collation; compiled in: $CHARSETS])
-else
- AC_MSG_ERROR([
- Collation $default_collation is not valid for character set $default_charset.
- Valid collations are: $default_charset_collations.
- See the Installation chapter in the Reference Manual.
- ]);
-fi
-
-AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_CHARSET_NAME], ["$default_charset"],
- [Define the default charset name])
-AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_COLLATION_NAME], ["$default_collation"],
- [Define the default charset name])
-
-
-# Shall we build the UCA-based Unicode collations
-AC_ARG_WITH(uca,
- [ --without-uca Skip building of the national Unicode collations.],
- [with_uca=$withval],
- [with_uca=yes]
-)
-
-AC_MSG_CHECKING([whether to compile national Unicode collations])
-
-if test "$with_uca" = "yes"
-then
- AC_MSG_RESULT(yes)
- AC_DEFINE([HAVE_UCA_COLLATIONS], [1], [national Unicode collations])
-else
- AC_MSG_RESULT(no)
-fi
-
MYSQL_CHECK_BIG_TABLES
-MYSQL_CHECK_ISAM
MYSQL_CHECK_BDB
MYSQL_CHECK_INNODB
MYSQL_CHECK_EXAMPLEDB
@@ -2906,6 +2404,7 @@ MYSQL_CHECK_ARCHIVEDB
MYSQL_CHECK_CSVDB
MYSQL_CHECK_BLACKHOLEDB
MYSQL_CHECK_NDBCLUSTER
+MYSQL_CHECK_FEDERATED
# If we have threads generate some library functions and test programs
sql_server_dirs=
@@ -2914,7 +2413,7 @@ thread_dirs=
dnl This probably should be cleaned up more - for now the threaded
dnl client is just using plain-old libs.
-sql_client_dirs="libmysql strings regex client"
+sql_client_dirs="strings regex mysys libmysql client"
linked_client_targets="linked_libmysql_sources"
if test "$THREAD_SAFE_CLIENT" != "no"
@@ -2952,24 +2451,16 @@ then
AC_DEFINE([THREAD], [1],
[Define if you want to have threaded code. This may be undef on client code])
# Avoid _PROGRAMS names
- THREAD_LPROGRAMS="test_thr_alarm\$(EXEEXT) test_thr_lock\$(EXEEXT)"
- AC_SUBST(THREAD_LPROGRAMS)
- THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o"
+ THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o"
AC_SUBST(THREAD_LOBJECTS)
server_scripts="mysqld_safe mysql_install_db"
- sql_server_dirs="strings dbug mysys extra regex"
+ sql_server_dirs="strings mysys dbug extra regex"
#
# Configuration for optional table handlers
#
- 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
@@ -3071,29 +2562,6 @@ esac
# END of configuration for optional table handlers
#
sql_server_dirs="$sql_server_dirs myisam myisammrg heap vio sql"
-
- if test "$with_posix_threads" = "no" -o "$with_mit_threads" = "yes"
- then
- # MIT user level threads
- thread_dirs="mit-pthreads"
- AC_DEFINE([HAVE_mit_thread], [1], [Do we use user level threads])
- MT_INCLUDES="-I\$(top_srcdir)/mit-pthreads/include"
- AC_SUBST(MT_INCLUDES)
- if test -n "$OVERRIDE_MT_LD_ADD"
- then
- MT_LD_ADD="$OVERRIDE_MT_LD_ADD"
- else
- MT_LD_ADD="-L \$(top_srcdir)/mit-pthreads/obj/ -lpthread"
- fi
- AC_SUBST(MT_LD_ADD)
- echo ""
- echo "Configuring MIT Pthreads"
- # We will never install so installation paths are not needed.
- (cd mit-pthreads && sh ./configure) || exit 1
- echo "End of MIT Pthreads configuration"
- echo ""
- LIBS="$MT_LD_ADD $LIBS"
- fi
fi
# IMPORTANT - do not modify LIBS past this line - this hack is the only way
@@ -3121,12 +2589,6 @@ do
done
AC_SUBST(sql_union_dirs)
-#if test "$with_posix_threads" = "no" -o "$with_mit_threads" = "yes"
-#then
- # MIT pthreads does now support connecting with unix sockets
- # AC_DEFINE([HAVE_THREADS_WITHOUT_SOCKETS], [], [MIT pthreads does not support connecting with unix sockets])
-#fi
-
# Some usefull subst
AC_SUBST(CC)
AC_SUBST(GXX)
@@ -3141,6 +2603,7 @@ case $SYSTEM_TYPE in
;;
esac
+
if test X"$have_ndbcluster" = Xyes
then
MAKE_BINARY_DISTRIBUTION_OPTIONS="$MAKE_BINARY_DISTRIBUTION_OPTIONS --with-ndbcluster"
@@ -3178,12 +2641,6 @@ then
fi
AC_SUBST([ndb_port])
-if test X"$ndb_port_base" = Xdefault
-then
- ndb_port_base="2202"
-fi
-AC_SUBST([ndb_port_base])
-
ndb_transporter_opt_objs=""
if test "$ac_cv_func_shmget" = "yes" &&
test "$ac_cv_func_shmat" = "yes" &&
@@ -3222,11 +2679,26 @@ then
fi
AC_SUBST([ndb_bin_am_ldflags])
AC_SUBST([ndb_opt_subdirs])
+
+NDB_SIZEOF_CHARP="$ac_cv_sizeof_charp"
+NDB_SIZEOF_CHAR="$ac_cv_sizeof_char"
+NDB_SIZEOF_SHORT="$ac_cv_sizeof_short"
+NDB_SIZEOF_INT="$ac_cv_sizeof_int"
+NDB_SIZEOF_LONG="$ac_cv_sizeof_long"
+NDB_SIZEOF_LONG_LONG="$ac_cv_sizeof_long_long"
+AC_SUBST([NDB_SIZEOF_CHARP])
+AC_SUBST([NDB_SIZEOF_CHAR])
+AC_SUBST([NDB_SIZEOF_SHORT])
+AC_SUBST([NDB_SIZEOF_INT])
+AC_SUBST([NDB_SIZEOF_LONG])
+AC_SUBST([NDB_SIZEOF_LONG_LONG])
+
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/debugger/Makefile dnl
+ 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
@@ -3264,6 +2736,7 @@ AC_CONFIG_FILES(ndb/Makefile ndb/include/Makefile dnl
ndb/test/tools/Makefile dnl
ndb/test/run-test/Makefile mysql-test/ndb/Makefile dnl
ndb/include/ndb_version.h ndb/include/ndb_global.h dnl
+ ndb/include/ndb_types.h dnl
)
fi
@@ -3281,6 +2754,7 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
sql-common/Makefile SSL/Makefile dnl
dbug/Makefile scripts/Makefile dnl
include/Makefile sql-bench/Makefile tools/Makefile dnl
+ server-tools/Makefile server-tools/instance-manager/Makefile dnl
tests/Makefile Docs/Makefile support-files/Makefile dnl
support-files/MacOSX/Makefile mysql-test/Makefile dnl
netware/Makefile dnl
diff --git a/dbug/Makefile.am b/dbug/Makefile.am
index 3ddb5bc17e1..38705e63847 100644
--- a/dbug/Makefile.am
+++ b/dbug/Makefile.am
@@ -15,44 +15,50 @@
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include
-LDADD = libdbug.a ../strings/libmystrings.a
-pkglib_LIBRARIES = libdbug.a
-noinst_HEADERS = dbug_long.h
-libdbug_a_SOURCES = dbug.c sanity.c
-EXTRA_DIST = example1.c example2.c example3.c \
- user.r monty.doc readme.prof \
- main.c factorial.c dbug_analyze.c
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
+LDADD = libdbug.a ../mysys/libmysys.a ../strings/libmystrings.a
+pkglib_LIBRARIES = libdbug.a
+noinst_HEADERS = dbug_long.h
+libdbug_a_SOURCES = dbug.c sanity.c
+EXTRA_DIST = example1.c example2.c example3.c \
+ user.r monty.doc readme.prof dbug_add_tags.pl \
+ my_main.c main.c factorial.c dbug_analyze.c
+NROFF_INC = example1.r example2.r example3.r main.r \
+ factorial.r output1.r output2.r output3.r \
+ output4.r output5.r
+CLEANFILES = $(NROFF_INC) user.t user.ps
+
# Must be linked with libs that are not compiled yet
-extra_progs: factorial dbug_analyze
+noinst_PROGRAMS = factorial dbug_analyze
+factorial_SOURCES = my_main.c factorial.c
+dbug_analyze_SOURCES = dbug_analyze.c
-factorial: main.o factorial.o
- @rm -f factorial
- $(LINK) main.o factorial.o -lmysys
+all: user.t user.ps
-dbug_analyze: dbug_analyze.o
- @rm -f dbug_analyze
- $(LINK) dbug_analyze.o -lmysys
+user.t: user.r $(NROFF_INC)
+ -nroff -mm user.r > $@
-user.t: user.r $(NROFF_INC)
- nroff -cm user.r > $@
+user.ps: user.r $(NROFF_INC)
+ -groff -mm user.r > $@
-output1.r: $(PROGRAM)
- factorial 1 2 3 4 5 | cat > $@
+output1.r: factorial
+ ./factorial 1 2 3 4 5 | cat > $@
-output2.r: $(PROGRAM)
- factorial -\#t:o 2 3 | cat >$@
+output2.r: factorial
+ ./factorial -\#t:o 2 3 | cat >$@
-output3.r: $(PROGRAM)
- factorial -\#d:t:o 3 | cat >$@
+output3.r: factorial
+ ./factorial -\#d:t:o 3 | cat >$@
-output4.r: $(PROGRAM)
- factorial -\#d,result:o 4 | cat >$@
+output4.r: factorial
+ ./factorial -\#d,result:o 4 | cat >$@
-output5.r: $(PROGRAM)
- factorial -\#d:f,factorial:F:L:o 3 | cat >$@
+output5.r: factorial
+ ./factorial -\#d:f,factorial:F:L:o 3 | cat >$@
+.c.r:
+ @RM@ -f $@
+ @SED@ -e 's!\\!\\\\!g' $< > $@
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/dbug/dbug.c b/dbug/dbug.c
index 02175f8b091..91b7e7b6c4c 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -21,8 +21,7 @@
* all copies and derivative works. Thank you. *
* *
* The author makes no warranty of any kind with respect to this *
- * product and explicitly disclaims any implied warranties of mer- *ct_lex.table_list.first=0;
- thd->lex.selec
+ * product and explicitly disclaims any implied warranties of mer- *
* chantability or fitness for any particular purpose. *
* *
******************************************************************************
@@ -60,8 +59,8 @@
*
* Michael Widenius:
* DBUG_DUMP - To dump a block of memory.
- * PUSH_FLAG "O" - To be used insted of "o" if we don't
- * want flushing (for slow systems)
+ * PUSH_FLAG "O" - To be used insted of "o" if we
+ * want flushing after each write
* PUSH_FLAG "A" - as 'O', but we will append to the out file instead
* of creating a new one.
* Check of malloc on entry/exit (option "S")
@@ -938,7 +937,7 @@ void _db_doprnt_ (const char *format,...)
/*
* FUNCTION
*
- * _db_dump_ dump a string until '\0' is found
+ * _db_dump_ dump a string in hex
*
* SYNOPSIS
*
@@ -979,7 +978,7 @@ uint length)
{
fprintf(_db_fp_, "%s: ", state->func);
}
- sprintf(dbuff,"%s: Memory: %lx Bytes: (%d)\n",
+ sprintf(dbuff,"%s: Memory: 0x%lx Bytes: (%d)\n",
keyword,(ulong) memory, length);
(void) fputs(dbuff,_db_fp_);
@@ -1230,6 +1229,33 @@ static BOOLEAN DoProfile ()
}
#endif
+/*
+ * FUNCTION
+ *
+ * _db_strict_keyword_ test keyword for member of keyword list
+ *
+ * SYNOPSIS
+ *
+ * BOOLEAN _db_strict_keyword_ (keyword)
+ * char *keyword;
+ *
+ * DESCRIPTION
+ *
+ * Similar to _db_keyword_, but keyword is NOT accepted if keyword list
+ * is empty. Used in DBUG_EXECUTE_IF() - for actions that must not be
+ * executed by default.
+ *
+ * Returns TRUE if keyword accepted, FALSE otherwise.
+ *
+ */
+
+BOOLEAN _db_strict_keyword_ (
+const char *keyword)
+{
+ if (stack -> keywords == NULL)
+ return FALSE;
+ return _db_keyword_ (keyword);
+}
/*
* FUNCTION
diff --git a/dbug/dbug_analyze.c b/dbug/dbug_analyze.c
index de228c64aa5..1db056d549c 100644
--- a/dbug/dbug_analyze.c
+++ b/dbug/dbug_analyze.c
@@ -51,6 +51,7 @@
#include <my_global.h>
#include <m_string.h>
+#include <my_pthread.h>
static char *my_name;
static int verbose;
@@ -246,7 +247,7 @@ char *m_name;
modules[n_items].m_stkuse = 0;
DBUG_RETURN (n_items++);
}
- while (cmp = strcmp (m_name,modules[ind].name)) {
+ while ((cmp = strcmp (m_name,modules[ind].name))) {
if (cmp < 0) { /* In left subtree */
if (s_table[ind].lchild == MAXPROCS) {
/* Add as left child */
@@ -392,7 +393,7 @@ FILE *inf;
}
break;
default:
- fprintf (stderr, "unknown record type '%s'\n", buf[0]);
+ fprintf (stderr, "unknown record type '%c'\n", buf[0]);
break;
}
next_line:;
@@ -450,10 +451,11 @@ FILE *outf;
unsigned long int sum_calls, sum_time;
{
DBUG_ENTER ("out_trailer");
- if (verbose) {
- fprintf (outf, "======\t==========\t===========\t==========\t========\n");
- fprintf (outf, "%6d\t%10.2f\t%11d\t%10.2f\t\t%-15s\n",
- sum_calls, 100.0, sum_time, 100.0, "Totals");
+ if (verbose)
+ {
+ fprintf(outf, "======\t==========\t===========\t==========\t========\n");
+ fprintf(outf, "%6ld\t%10.2f\t%11ld\t%10.2f\t\t%-15s\n",
+ sum_calls, 100.0, sum_time, 100.0, "Totals");
}
DBUG_VOID_RETURN;
}
@@ -488,16 +490,16 @@ unsigned long int *called, *timed;
import = (unsigned int) (per_time * per_calls);
if (verbose) {
- fprintf (outf, "%6d\t%10.2f\t%11d\t%10.2f %10d\t%-15s\n",
+ fprintf (outf, "%6d\t%10.2f\t%11ld\t%10.2f %10d\t%-15s\n",
calls, per_calls, time, per_time, import, name);
} else {
ms_per_call = time;
ms_per_call /= calls;
ftime = time;
ftime /= 1000;
- fprintf (outf, "%8.2f%8.3f%8u%8.3f%8.2f%8u%8u %-s\n",
- per_time, ftime, calls, ms_per_call, per_calls, import,
- stkuse, name);
+ fprintf(outf, "%8.2f%8.3f%8u%8.3f%8.2f%8u%8lu %-s\n",
+ per_time, ftime, calls, ms_per_call, per_calls, import,
+ stkuse, name);
}
*called = calls;
*timed = time;
@@ -572,6 +574,11 @@ int main (int argc, char **argv)
FILE *infile;
FILE *outfile = {stdout};
+#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
+ pthread_init(); /* Must be called before DBUG_ENTER */
+#endif
+ my_thread_global_init();
+ {
DBUG_ENTER ("main");
DBUG_PROCESS (argv[0]);
my_name = argv[0];
@@ -601,6 +608,7 @@ int main (int argc, char **argv)
output (outfile);
DBUG_RETURN (EX_OK);
}
+}
#ifdef MSDOS
diff --git a/dbug/dbug_long.h b/dbug/dbug_long.h
index 07266b51553..829df181ef1 100644
--- a/dbug/dbug_long.h
+++ b/dbug/dbug_long.h
@@ -1,3 +1,4 @@
+#error This file is not used in MySQL - see ../include/my_dbug.h instead
/******************************************************************************
* *
* N O T I C E *
diff --git a/dbug/example1.c b/dbug/example1.c
index e468f065796..7b3c3fcd63d 100644
--- a/dbug/example1.c
+++ b/dbug/example1.c
@@ -1,6 +1,3 @@
-
-#include <my_global.h>
-
main (argc, argv)
int argc;
char *argv[];
diff --git a/dbug/example2.c b/dbug/example2.c
index 5e5f14f0e7e..75fc1321b13 100644
--- a/dbug/example2.c
+++ b/dbug/example2.c
@@ -1,6 +1,3 @@
-
-#include <my_global.h>
-
int debug = 0;
main (argc, argv)
diff --git a/dbug/example3.c b/dbug/example3.c
index f177c07425d..c035cdfffa0 100644
--- a/dbug/example3.c
+++ b/dbug/example3.c
@@ -1,6 +1,3 @@
-
-#include <my_global.h>
-
main (argc, argv)
int argc;
char *argv[];
diff --git a/dbug/main.c b/dbug/main.c
index da56c00feb3..00e80c8ba31 100644
--- a/dbug/main.c
+++ b/dbug/main.c
@@ -1,33 +1,24 @@
-#ifdef DBUG_OFF /* We are testing dbug */
-#undef DBUG_OFF
-#endif
-
-#include <my_global.h> /* This includes dbug.h */
+#include <dbug.h>
int main (argc, argv)
int argc;
char *argv[];
{
- register int result, ix;
+ int result, ix;
extern int factorial(int);
-#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
- pthread_init(); /* Must be called before DBUG_ENTER */
-#endif
- {
- DBUG_ENTER ("main");
- DBUG_PROCESS (argv[0]);
- for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
- switch (argv[ix][1]) {
- case '#':
- DBUG_PUSH (&(argv[ix][2]));
- break;
- }
- }
- for (; ix < argc; ix++) {
- DBUG_PRINT ("args", ("argv[%d] = %s", ix, argv[ix]));
- result = factorial (atoi(argv[ix]));
- printf ("%d\n", result);
+ DBUG_ENTER ("main");
+ DBUG_PROCESS (argv[0]);
+ for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
+ switch (argv[ix][1]) {
+ case '#':
+ DBUG_PUSH (&(argv[ix][2]));
+ break;
}
- DBUG_RETURN (0);
}
+ for (; ix < argc; ix++) {
+ DBUG_PRINT ("args", ("argv[%d] = %s", ix, argv[ix]));
+ result = factorial (atoi(argv[ix]));
+ printf ("%d\n", result);
+ }
+ DBUG_RETURN (0);
}
diff --git a/dbug/monty.doc b/dbug/monty.doc
index 1c102e1c31e..bd4096951d2 100644
--- a/dbug/monty.doc
+++ b/dbug/monty.doc
@@ -15,6 +15,6 @@ All changes that I or other people at MySQL AB have done to all files
in the dbug library (Mainly in dbug.c, dbug_analyze.c, dbug_long.h,
dbug.h) are put in public domain, as the rest of the dbug.c library)
-To my knowledge, all code in dbug library are in public domain.
+To my knowledge, all code in dbug library is in public domain.
Michael Widenius
diff --git a/dbug/my_main.c b/dbug/my_main.c
new file mode 100644
index 00000000000..ed1c9329235
--- /dev/null
+++ b/dbug/my_main.c
@@ -0,0 +1,41 @@
+/*
+ this is modified version of the original example main.c
+ fixed so that it could compile and run in MySQL source tree
+*/
+
+#ifdef DBUG_OFF /* We are testing dbug */
+#undef DBUG_OFF
+#endif
+
+#include <my_global.h> /* This includes dbug.h */
+
+int main (argc, argv)
+int argc;
+char *argv[];
+{
+ register int result, ix;
+ extern int factorial(int);
+#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
+ pthread_init(); /* Must be called before DBUG_ENTER */
+#endif
+#ifdef THREAD
+ my_thread_global_init();
+#endif
+ {
+ DBUG_ENTER ("main");
+ DBUG_PROCESS (argv[0]);
+ for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
+ switch (argv[ix][1]) {
+ case '#':
+ DBUG_PUSH (&(argv[ix][2]));
+ break;
+ }
+ }
+ for (; ix < argc; ix++) {
+ DBUG_PRINT ("args", ("argv[%d] = %s", ix, argv[ix]));
+ result = factorial (atoi(argv[ix]));
+ printf ("%d\n", result);
+ }
+ DBUG_RETURN (0);
+ }
+}
diff --git a/dbug/user.r b/dbug/user.r
index e8321243962..198f88cf272 100644
--- a/dbug/user.r
+++ b/dbug/user.r
@@ -1,8 +1,13 @@
.\" @(#)user.r 1.13 10/29/86
.\"
+.\" 2004-10-29: documented features implemented since 10/29/86
+.\" formatting cleanup
+.\" - Sergei Golubchik
+.\"
.\" DBUG (Macro Debugger Package) nroff source
.\"
.\" nroff -mm user.r >user.t
+.\" groff -mm user.r >user.ps
.\"
.\" ===================================================
.\"
@@ -196,7 +201,9 @@ Figure 1 is an example of this type of primitive debugging
technique.
.DS I N
.SP 2
+\fC
.so example1.r
+\fR
.SP 2
.ll -5
.ce
@@ -222,7 +229,9 @@ C preprocessor.
Figure 2 is an example of all three techniques.
.DS I N
.SP 2
+\fC
.so example2.r
+\fR
.SP 2
.ll -5
.ce
@@ -255,7 +264,9 @@ like an arbitrary and unreasonable restriction.
Figure 3 is an example of this usage.
.DS I N
.SP 2
+\fC
.so example3.r
+\fR
.SP 2
.ll -5
.ce
@@ -281,7 +292,9 @@ program is implemented recursively.
Figure 4 is the main function for this factorial program.
.DS I N
.SP 2
+\fC
.so main.r
+\fR
.SP 2
.ll -5
.ce
@@ -346,7 +359,7 @@ All of these macros will be fully explained in subsequent sections.
To use the debugger, the factorial program is invoked with a command
line of the form:
.DS CB N
-factorial -#d:t 1 2 3
+\fCfactorial -#d:t 1 2 3
.DE
The
.B main
@@ -364,7 +377,7 @@ The factorial function is then called three times, with the arguments
Note that the DBUG_PRINT takes exactly
.B two
arguments, with the second argument (a format string and list
-of printable values) enclosed in parenthesis.
+of printable values) enclosed in parentheses.
.P
Debug control strings consist of a header, the "-#", followed
by a colon separated list of debugger arguments.
@@ -373,6 +386,7 @@ by an optional comma separated list of arguments specific
to the given flag.
Some examples are:
.DS CB N
+\fC
-#d:t:o
-#d,in,out:f,main:F:L
.DE
@@ -391,7 +405,9 @@ Note that this is not necessarily the best way to do factorials
and error conditions are ignored completely.
.DS I N
.SP 2
+\fC
.so factorial.r
+\fR
.SP 2
.ll -5
.ce
@@ -421,7 +437,7 @@ To build the factorial program on a
system, compile and
link with the command:
.DS CB N
-cc -o factorial main.c factorial.c -ldbug
+\fCcc -o factorial main.c factorial.c -ldbug
.DE
The "-ldbug" argument tells the loader to link in the
runtime support modules for the
@@ -429,18 +445,20 @@ runtime support modules for the
package.
Executing the factorial program with a command of the form:
.DS CB N
-factorial 1 2 3 4 5
+\fCfactorial 1 2 3 4 5
.DE
generates the output shown in figure 6.
.DS I N
.SP 2
+\fC
.so output1.r
+\fR
.SP 2
.ll -5
.ce
Figure 6
.ce
-factorial 1 2 3 4 5
+\fCfactorial 1 2 3 4 5
.ll +5
.SP 2
.DE
@@ -449,16 +467,18 @@ factorial 1 2 3 4 5
Function level tracing is enabled by passing the debugger
the 't' flag in the debug control string.
Figure 7 is the output resulting from the command
-"factorial\ -#t:o\ 3\ 2".
+"factorial\ -#t:o\ 2\ 3".
.DS I N
.SP 2
+\fC
.so output2.r
+\fR
.SP 2
.ll -5
.ce
Figure 7
.ce
-factorial -#t:o 3 2
+\fCfactorial -#t:o 2 3
.ll +5
.SP 2
.DE
@@ -510,7 +530,7 @@ output instead, via the 'o' flag character.
Note that no 'o' implies the default (standard error), a 'o'
with no arguments means standard output, and a 'o'
with an argument means used the named file.
-I.E, "factorial\ -#t:o,logfile\ 3\ 2" would write the trace
+i.e, "factorial\ -#t:o,logfile\ 3\ 2" would write the trace
output in "logfile".
Because of
.B UNIX
@@ -555,7 +575,7 @@ The second argument to a
.B DBUG_PRINT
macro is a standard printf style
format string and one or more arguments to print, all
-enclosed in parenthesis so that they collectively become a single macro
+enclosed in parentheses so that they collectively become a single macro
argument.
This is how variable numbers of printf arguments are supported.
Also note that no explicit newline is required at the end of the format string.
@@ -566,13 +586,15 @@ to a single macro with a huge format string.
Figure 8 shows the output for default tracing and debug.
.DS I N
.SP 2
+\fC
.so output3.r
+\fR
.SP 2
.ll -5
.ce
Figure 8
.ce
-factorial -#d:t:o 3
+\fCfactorial -#d:t:o 3
.ll +5
.SP 2
.DE
@@ -591,13 +613,15 @@ To demonstrate selection of specific macros for output, figure
the debug control string "-#d,result:o".
.DS I N
.SP 2
+\fC
.so output4.r
+\fR
.SP 2
.ll -5
.ce
Figure 9
.ce
-factorial -#d,result:o 4
+\fCfactorial -#d,result:o 4
.ll +5
.SP 2
.DE
@@ -613,13 +637,15 @@ The 'F' flag enables printing of the source file name and the 'L'
flag enables printing of the source file line number.
.DS I N
.SP 2
+\fC
.so output5.r
+\fR
.SP 2
.ll -5
.ce
Figure 10
.ce
-factorial -#d:f,factorial:F:L:o 3
+\fCfactorial -#d:f,factorial:F:L:o 3
.ll +5
.SP 2
.DE
@@ -671,7 +697,7 @@ will cause warning messages from the
.I dbug
package runtime support module.
.SP 1
-EX:\ DBUG_ENTER\ ("main");
+EX:\ \fCDBUG_ENTER\ ("main");\fR
.SP 1
.LI DBUG_RETURN\
Used at each exit point of a function containing a
@@ -693,16 +719,16 @@ DBUG_ENTER
macro, and the compiler will complain
if the macros are actually used (expanded).
.SP 1
-EX:\ DBUG_RETURN\ (value);
+EX:\ \fCDBUG_RETURN\ (value);\fR
.br
-EX:\ DBUG_VOID_RETURN;
+EX:\ \fCDBUG_VOID_RETURN;\fR
.SP 1
.LI DBUG_PROCESS\
Used to name the current process being executed.
A typical argument for this macro is "argv[0]", though
it will be perfectly happy with any other string.
.SP 1
-EX:\ DBUG_PROCESS\ (argv[0]);
+EX:\ \fCDBUG_PROCESS\ (argv[0]);\fR
.SP 1
.LI DBUG_PUSH\
Sets a new debugger state by pushing the current
@@ -720,11 +746,11 @@ The proper usage is to pass a pointer to the first character
.B after
the "-#" string.
.SP 1
-EX:\ DBUG_PUSH\ (\&(argv[i][2]));
+EX:\ \fCDBUG_PUSH\ (\&(argv[i][2]));\fR
.br
-EX:\ DBUG_PUSH\ ("d:t");
+EX:\ \fCDBUG_PUSH\ ("d:t");\fR
.br
-EX:\ DBUG_PUSH\ ("");
+EX:\ \fCDBUG_PUSH\ ("");\fR
.SP 1
.LI DBUG_POP\
Restores the previous debugger state by popping the state stack.
@@ -734,7 +760,7 @@ The
DBUG_POP
macro has no arguments.
.SP 1
-EX:\ DBUG_POP\ ();
+EX:\ \fCDBUG_POP\ ();\fR
.SP 1
.LI DBUG_FILE\
The
@@ -744,7 +770,7 @@ stream.
It is used in the same manner as the symbols "stdout" and "stderr"
in the standard I/O package.
.SP 1
-EX:\ fprintf\ (DBUG_FILE,\ "Doing my own I/O!\n");
+EX:\ \fCfprintf\ (DBUG_FILE,\ "Doing\ my\ own\ I/O!\\n");\fR
.SP 1
.LI DBUG_EXECUTE\
The DBUG_EXECUTE macro is used to execute any arbitrary C code.
@@ -754,9 +780,19 @@ This macro must be used cautiously because, like the
DBUG_PRINT
macro,
it is automatically selected by default whenever the 'd' flag has
-no argument list (I.E., a "-#d:t" control string).
+no argument list (i.e., a "-#d:t" control string).
+.SP 1
+EX:\ \fCDBUG_EXECUTE\ ("status",\ print_status\ ());\fR
+.SP 1
+.LI DBUG_EXECUTE_IF\
+Works like DBUG_EXECUTE macro, but the code is
+.B not
+executed "by default", if the keyword is not explicitly listed in
+the 'd' flag. Used to conditionally execute "dangerous" actions, e.g
+to crash the program testing how recovery works, or to introduce an
+artificial delay checking for race conditions.
.SP 1
-EX:\ DBUG_EXECUTE\ ("abort",\ abort\ ());
+EX:\ \fCDBUG_EXECUTE_IF\ ("crashme",\ abort\ ());\fR
.SP 1
.LI DBUG_N\
These macros, where N is in the range 2-5, are currently obsolete
@@ -771,22 +807,32 @@ and the corresponding argument list.
Note that the format string and argument list are all one macro argument
and
.B must
-be enclosed in parenthesis.
+be enclosed in parentheses.
.SP 1
-EX:\ DBUG_PRINT\ ("eof",\ ("end\ of\ file\ found"));
+EX:\ \fCDBUG_PRINT\ ("eof",\ ("end\ of\ file\ found"));\fR
.br
-EX:\ DBUG_PRINT\ ("type",\ ("type\ is\ %x", type));
+EX:\ \fCDBUG_PRINT\ ("type",\ ("type\ is\ %x", type));\fR
.br
-EX:\ DBUG_PRINT\ ("stp",\ ("%x\ ->\ %s", stp, stp\ ->\ name));
+EX:\ \fCDBUG_PRINT\ ("stp",\ ("%x\ ->\ %s", stp, stp\ ->\ name));\fR
+.SP 1
+.LI DBUG_DUMP\
+Used to dump a memory block in hex via the "fprintf" library function on the
+current debug stream, DBUG_FILE.
+The first argument is a debug keyword, the second is a pointer to
+a memory to dump, the third is a number of bytes to dump.
+.SP 1
+EX: \fCDBUG_DBUG\ ("net",\ packet,\ len);\fR
+.SP 1
.LI DBUG_SETJMP\
Used in place of the setjmp() function to first save the current
debugger state and then execute the standard setjmp call.
-This allows to the debugger to restore it's state when the
+This allows to the debugger to restore its state when the
DBUG_LONGJMP macro is used to invoke the standard longjmp() call.
Currently all instances of DBUG_SETJMP must occur within the
same function and at the same function nesting level.
.SP 1
-EX:\ DBUG_SETJMP\ (env);
+EX: \fCDBUG_SETJMP\ (env);\fR
+.SP 1
.LI DBUG_LONGJMP\
Used in place of the longjmp() function to first restore the
previous debugger state at the time of the last DBUG_SETJMP
@@ -797,7 +843,45 @@ It would be possible to maintain separate DBUG_SETJMP and DBUG_LONGJMP
pairs by having the debugger runtime support module use the first
argument to differentiate the pairs.
.SP 1
-EX:\ DBUG_LONGJMP\ (env,val);
+EX: \fCDBUG_LONGJMP\ (env,val);\fR
+.SP 1
+.LI DBUG_LOCK_FILE\
+Used in multi-threaded environment to lock DBUG_FILE stream.
+It can be used, for example, in functions that need to write something to a
+debug stream more than in one fprintf() call and want to ensure that no other
+thread will write something in between.
+.SP 1
+EX:\fC
+.br
+ DBUG_LOCK_FILE;
+.br
+ fprintf (DBUG_FILE, "a=[");
+.br
+ for (int i=0; i < a_length; i++)
+.br
+ fprintf (DBUG_FILE, "0x%03x ", a[i]);
+.br
+ fprintf (DBUG_FILE, "]");
+.br
+ DBUG_UNLOCK_FILE;\fR
+.SP 1
+.LI DBUG_UNLOCK_FILE\
+Unlocks DBUG_FILE stream, that was locked with a DBUG_LOCK_FILE.
+.LI DBUG_ASSERT\
+This macro just does a regular assert(). The difference is that it will be
+disabled by DBUG_OFF togeher with the
+.I dbug
+library. So there will be no need to disable asserts separately with NDEBUG.
+.SP 1
+EX:\ \fCDBUG_ASSERT(\ a\ >\ 0\ );\fR
+.SP 1
+.LI DBUG_OUTPUT\
+In multi-threaded environment disables (or enables) any
+.I dbug
+output from the current thread.
+.SP 1
+EX:\ \fCDBUG_OUTPUT(\ 0\ );\fR
+.SP 1
.LE
.SK
@@ -815,6 +899,18 @@ and the flag characters which enable or disable them.
Argument lists enclosed in '[' and ']' are optional.
.SP 2
.BL 22
+.LI a[,file]
+Redirect the debugger output stream and append it to the specified file.
+The default output stream is stderr.
+A null argument list causes output to be redirected to stdout.
+Double the colon, if you want it in the path
+.SP 1
+EX: \fCa,C::\\tmp\\log\fR
+.LI A[,file]
+Like 'a[,file]' but ensure that data are written after each write
+(this typically implies flush or close/reopen). It helps to get
+a complete log file in case of crashes. This mode is implied in
+multi-threaded environment.
.LI d[,keywords]
Enable output from macros with specified keywords.
A null list of keywords implies that all keywords are selected.
@@ -828,6 +924,14 @@ A null list of functions implies that all functions are selected.
.LI F
Mark each debugger output line with the name of the source file
containing the macro causing the output.
+.LI i
+Mark each debugger output line with the PID of the current process.
+.LI g,[functions]
+Enable profiling for the specified list of functions.
+By default profiling is enabled for all functions.
+See
+.B PROFILING\ WITH\ DBUG
+below.
.LI L
Mark each debugger output line with the source file line number of
the macro causing the output.
@@ -838,9 +942,9 @@ Sequentially number each debugger output line starting at 1.
This is useful for reference purposes when debugger output is
interspersed with program output.
.LI o[,file]
-Redirect the debugger output stream to the specified file.
-The default output stream is stderr.
-A null argument list causes output to be redirected to stdout.
+Like 'a[,file]' but overwrite old file, do not append.
+.LI O[,file]
+Like 'A[,file]' but overwrite old file, do not append.
.LI p[,processes]
Limit debugger actions to the specified processes.
A null list implies all processes.
@@ -865,6 +969,14 @@ Most useful with
.B DBUG_PUSH
macros used to temporarily alter the
debugger state.
+.LI S
+When compiled with
+.I safemalloc
+this flag forces "sanity" memory checks (for overwrites/underwrites)
+on each
+.B DBUG_ENTER
+and
+.B DBUG_RETURN.
.LI t[,N]
Enable function control flow tracing.
The maximum nesting depth is specified by N, and defaults to
@@ -872,6 +984,76 @@ The maximum nesting depth is specified by N, and defaults to
.LE
.SK
.B
+PROFILING WITH DBUG
+.R
+
+.P
+With
+.I dbug
+one can do profiling in a machine independent fashion,
+without a need for profiled version of system libraries.
+For this,
+.I dbug
+can write out a file
+called
+.B dbugmon.out
+(by default). This is an ascii file containing lines of the form:
+.DS CB N
+\fC<function-name> E <time-entered>
+<function-name> X <time-exited>
+.DE
+
+.P
+A second program (\fBanalyze\fR) reads this file, and produces a report on
+standard output.
+
+.P
+Profiling is enabled through the
+.B g
+flag. It can take a list of
+function names for which profiling is enabled. By default, it
+profiles all functions.
+
+.P
+The profile file is opened for appending. This
+is in order that one can run a program several times, and get the
+sum total of all the times, etc.
+
+.P
+An example of the report generated follows:
+.DS CB N
+\fC
+ Profile of Execution
+ Execution times are in milliseconds
+
+ Calls Time
+ ----- ----
+ Times Percentage Time Spent Percentage
+Function Called of total in Function of total Importance
+======== ====== ========== =========== ========== ==========
+factorial 5 83.33 30 100.00 8333
+main 1 16.67 0 0.00 0
+======== ====== ========== =========== ==========
+Totals 6 100.00 30 100.00
+.DE
+.P
+As you can see, it's quite self-evident. The
+.B Importance
+column is a
+metric obtained by multiplying the percentage of the calls and the percentage
+of the time. Functions with higher 'importance' benefit the most from
+being sped up.
+
+.P
+As a limitation - setjmp/longjmp, or child processes, are ignored
+for the time being. Also, profiling does not work
+in a multi-threaded environment.
+
+.P
+Profiling code is (c) Binayak Banerjee.
+
+.SK
+.B
HINTS AND MISCELLANEOUS
.R
@@ -934,4 +1116,4 @@ The most common problem is multiply allocated memory.
.\" .DE nroff dident like this. davida 900108
.CS
-
+.\" vim:filetype=nroff
diff --git a/depcomp b/depcomp
deleted file mode 100755
index 65899658ee7..00000000000
--- a/depcomp
+++ /dev/null
@@ -1,411 +0,0 @@
-#! /bin/sh
-
-# depcomp - compile a program generating dependencies as side-effects
-# Copyright 1999, 2000 Free Software Foundation, Inc.
-
-# 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, 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.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
-
-if test -z "$depmode" || test -z "$source" || test -z "$object"; then
- echo "depcomp: Variables source, object and depmode must be set" 1>&2
- exit 1
-fi
-# `libtool' can also be set to `yes' or `no'.
-
-depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`}
-tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
-
-rm -f "$tmpdepfile"
-
-# Some modes work just like other modes, but use different flags. We
-# parameterize here, but still list the modes in the big case below,
-# to make depend.m4 easier to write. Note that we *cannot* use a case
-# here, because this file can only contain one case statement.
-if test "$depmode" = hp; then
- # HP compiler uses -M and no extra arg.
- gccflag=-M
- depmode=gcc
-fi
-
-if test "$depmode" = dashXmstdout; then
- # This is just like dashmstdout with a different argument.
- dashmflag=-xM
- depmode=dashmstdout
-fi
-
-case "$depmode" in
-gcc3)
-## gcc 3 implements dependency tracking that does exactly what
-## we want. Yay! Note: for some reason libtool 1.4 doesn't like
-## it if -MD -MP comes after the -MF stuff. Hmm.
- "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
- mv "$tmpdepfile" "$depfile"
- ;;
-
-gcc)
-## There are various ways to get dependency output from gcc. Here's
-## why we pick this rather obscure method:
-## - Don't want to use -MD because we'd like the dependencies to end
-## up in a subdir. Having to rename by hand is ugly.
-## (We might end up doing this anyway to support other compilers.)
-## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
-## -MM, not -M (despite what the docs say).
-## - Using -M directly means running the compiler twice (even worse
-## than renaming).
- if test -z "$gccflag"; then
- gccflag=-MD,
- fi
- "$@" -Wp,"$gccflag$tmpdepfile"
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
- rm -f "$depfile"
- echo "$object : \\" > "$depfile"
- alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
-## The second -e expression handles DOS-style file names with drive letters.
- sed -e 's/^[^:]*: / /' \
- -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
-## The problem is that when a header file which appears in a .P file
-## is deleted, the dependency causes make to die (because there is
-## typically no way to rebuild the header). We avoid this by adding
-## dummy dependencies for each header file. Too bad gcc doesn't do
-## this for us directly.
- tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'. On the theory
-## that the space means something, we add a space to the output as
-## well.
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-hp)
- # This case exists only to let depend.m4 do its work. It works by
- # looking at the text of this script. This case will never be run,
- # since it is checked for above.
- exit 1
- ;;
-
-sgi)
- if test "$libtool" = yes; then
- "$@" "-Wp,-MDupdate,$tmpdepfile"
- else
- "$@" -MDupdate "$tmpdepfile"
- fi
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
- rm -f "$depfile"
-
- if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
- echo "$object : \\" > "$depfile"
-
- # Clip off the initial element (the dependent). Don't try to be
- # clever and replace this with sed code, as IRIX sed won't handle
- # lines with more than a fixed number of characters (4096 in
- # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
- # the IRIX cc adds comments like `#:fec' to the end of the
- # dependency line.
- tr ' ' '
-' < "$tmpdepfile" \
- | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
- tr '
-' ' ' >> $depfile
- echo >> $depfile
-
- # The second pass generates a dummy entry for each header file.
- tr ' ' '
-' < "$tmpdepfile" \
- | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
- >> $depfile
- else
- # The sourcefile does not contain any dependencies, so just
- # store a dummy comment line, to avoid errors with the Makefile
- # "include basename.Plo" scheme.
- echo "#dummy" > "$depfile"
- fi
- rm -f "$tmpdepfile"
- ;;
-
-aix)
- # The C for AIX Compiler uses -M and outputs the dependencies
- # in a .u file. This file always lives in the current directory.
- # Also, the AIX compiler puts `$object:' at the start of each line;
- # $object doesn't have directory information.
- stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
- tmpdepfile="$stripped.u"
- outname="$stripped.o"
- if test "$libtool" = yes; then
- "$@" -Wc,-M
- else
- "$@" -M
- fi
-
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
-
- if test -f "$tmpdepfile"; then
- # Each line is of the form `foo.o: dependent.h'.
- # Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
- sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
- sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
- else
- # The sourcefile does not contain any dependencies, so just
- # store a dummy comment line, to avoid errors with the Makefile
- # "include basename.Plo" scheme.
- echo "#dummy" > "$depfile"
- fi
- rm -f "$tmpdepfile"
- ;;
-
-tru64)
- # The Tru64 AIX compiler uses -MD to generate dependencies as a side
- # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
- # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
- # dependencies in `foo.d' instead, so we check for that too.
- # Subdirectories are respected.
-
- tmpdepfile1="$object.d"
- tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'`
- if test "$libtool" = yes; then
- "$@" -Wc,-MD
- else
- "$@" -MD
- fi
-
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile1" "$tmpdepfile2"
- exit $stat
- fi
-
- if test -f "$tmpdepfile1"; then
- tmpdepfile="$tmpdepfile1"
- else
- tmpdepfile="$tmpdepfile2"
- fi
- if test -f "$tmpdepfile"; then
- sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
- # That's a space and a tab in the [].
- sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
- else
- echo "#dummy" > "$depfile"
- fi
- rm -f "$tmpdepfile"
- ;;
-
-#nosideeffect)
- # This comment above is used by automake to tell side-effect
- # dependency tracking mechanisms from slower ones.
-
-dashmstdout)
- # Important note: in order to support this mode, a compiler *must*
- # always write the proprocessed file to stdout, regardless of -o,
- # because we must use -o when running libtool.
- test -z "$dashmflag" && dashmflag=-M
- ( IFS=" "
- case " $* " in
- *" --mode=compile "*) # this is libtool, let us make it quiet
- for arg
- do # cycle over the arguments
- case "$arg" in
- "--mode=compile")
- # insert --quiet before "--mode=compile"
- set fnord "$@" --quiet
- shift # fnord
- ;;
- esac
- set fnord "$@" "$arg"
- shift # fnord
- shift # "$arg"
- done
- ;;
- esac
- "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
- ) &
- proc=$!
- "$@"
- stat=$?
- wait "$proc"
- if test "$stat" != 0; then exit $stat; fi
- rm -f "$depfile"
- cat < "$tmpdepfile" > "$depfile"
- tr ' ' '
-' < "$tmpdepfile" | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-dashXmstdout)
- # This case only exists to satisfy depend.m4. It is never actually
- # run, as this mode is specially recognized in the preamble.
- exit 1
- ;;
-
-makedepend)
- # X makedepend
- (
- shift
- cleared=no
- for arg in "$@"; do
- case $cleared in no)
- set ""; shift
- cleared=yes
- esac
- case "$arg" in
- -D*|-I*)
- set fnord "$@" "$arg"; shift;;
- -*)
- ;;
- *)
- set fnord "$@" "$arg"; shift;;
- esac
- done
- obj_suffix="`echo $object | sed 's/^.*\././'`"
- touch "$tmpdepfile"
- ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@"
- ) &
- proc=$!
- "$@"
- stat=$?
- wait "$proc"
- if test "$stat" != 0; then exit $stat; fi
- rm -f "$depfile"
- cat < "$tmpdepfile" > "$depfile"
- tail +3 "$tmpdepfile" | tr ' ' '
-' | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile" "$tmpdepfile".bak
- ;;
-
-cpp)
- # Important note: in order to support this mode, a compiler *must*
- # always write the proprocessed file to stdout, regardless of -o,
- # because we must use -o when running libtool.
- ( IFS=" "
- case " $* " in
- *" --mode=compile "*)
- for arg
- do # cycle over the arguments
- case $arg in
- "--mode=compile")
- # insert --quiet before "--mode=compile"
- set fnord "$@" --quiet
- shift # fnord
- ;;
- esac
- set fnord "$@" "$arg"
- shift # fnord
- shift # "$arg"
- done
- ;;
- esac
- "$@" -E |
- sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
- sed '$ s: \\$::' > "$tmpdepfile"
- ) &
- proc=$!
- "$@"
- stat=$?
- wait "$proc"
- if test "$stat" != 0; then exit $stat; fi
- rm -f "$depfile"
- echo "$object : \\" > "$depfile"
- cat < "$tmpdepfile" >> "$depfile"
- sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-msvisualcpp)
- # Important note: in order to support this mode, a compiler *must*
- # always write the proprocessed file to stdout, regardless of -o,
- # because we must use -o when running libtool.
- ( IFS=" "
- case " $* " in
- *" --mode=compile "*)
- for arg
- do # cycle over the arguments
- case $arg in
- "--mode=compile")
- # insert --quiet before "--mode=compile"
- set fnord "$@" --quiet
- shift # fnord
- ;;
- esac
- set fnord "$@" "$arg"
- shift # fnord
- shift # "$arg"
- done
- ;;
- esac
- "$@" -E |
- sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
- ) &
- proc=$!
- "$@"
- stat=$?
- wait "$proc"
- if test "$stat" != 0; then exit $stat; fi
- rm -f "$depfile"
- echo "$object : \\" > "$depfile"
- . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
- echo " " >> "$depfile"
- . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-none)
- exec "$@"
- ;;
-
-*)
- echo "Unknown depmode $depmode" 1>&2
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/extra/Makefile.am b/extra/Makefile.am
index 467f426f1a5..457fddce673 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -14,13 +14,32 @@
# 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_builddir)/include -I$(top_srcdir)/include \
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
@ndbcluster_includes@ -I$(top_srcdir)/sql
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
+BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \
+ $(top_builddir)/include/sql_state.h \
+ $(top_builddir)/include/mysqld_ername.h
+pkginclude_HEADERS= $(BUILT_SOURCES)
+CLEANFILES = $(BUILT_SOURCES)
+DIST_SUBDIRS= yassl
+
+# This will build mysqld_error.h and sql_state.h
+$(top_builddir)/include/mysqld_error.h: comp_err
+ $(top_builddir)/extra/comp_err \
+ --charset=$(top_srcdir)/sql/share/charsets \
+ --out-dir=$(top_builddir)/sql/share/ \
+ --header_file=$(top_builddir)/include/mysqld_error.h \
+ --name_file=$(top_builddir)/include/mysqld_ername.h \
+ --state_file=$(top_builddir)/include/sql_state.h \
+ --in_file=$(top_srcdir)/sql/share/errmsg.txt
+$(top_builddir)/include/mysqld_ername.h: $(top_builddir)/include/mysqld_error.h
+$(top_builddir)/include/sql_state.h: $(top_builddir)/include/mysqld_error.h
+
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
- resolve_stack_dump mysql_waitpid
+ resolve_stack_dump mysql_waitpid innochecksum
+noinst_PROGRAMS = charset2html
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/mysys/charset2html.c b/extra/charset2html.c
index 96862ff16a1..96862ff16a1 100644
--- a/mysys/charset2html.c
+++ b/extra/charset2html.c
diff --git a/extra/comp_err.c b/extra/comp_err.c
index 6c7fad6a270..b322be2b8ed 100644
--- a/extra/comp_err.c
+++ b/extra/comp_err.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* 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
@@ -14,287 +14,932 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Saves all errmesg in a header file, updated by me, in a compact file */
+/*
+ Written by Anjuta Widenius
+*/
+
+/*
+ Creates one include file and multiple language-error message files from one
+ multi-language text file.
+*/
#include <my_global.h>
#include <m_ctype.h>
#include <my_sys.h>
#include <m_string.h>
+#include <my_getopt.h>
+#include <assert.h>
+#include <my_dir.h>
-#define MAXLENGTH 1000
#define MAX_ROWS 1000
-#define MAX_FILES 10
-#define MAX_CHARSET_NAME 64
+#define HEADER_LENGTH 32 /* Length of header in errmsg.sys */
+#define DEFAULT_CHARSET_DIR "../sql/share/charsets"
+#define ER_PREFIX "ER_"
+#define WARN_PREFIX "WARN_"
+static char *OUTFILE= (char*) "errmsg.sys";
+static char *HEADERFILE= (char*) "mysqld_error.h";
+static char *NAMEFILE= (char*) "mysqld_ername.h";
+static char *STATEFILE= (char*) "sql_state.h";
+static char *TXTFILE= (char*) "../sql/share/errmsg.txt";
+static char *DATADIRECTORY= (char*) "../sql/share/";
+static char *default_dbug_option= (char*) "d:t:O,/tmp/comp_err.trace";
+
+/* Header for errmsg.sys files */
+uchar file_head[]= { 254, 254, 2, 1 };
+/* Store positions to each error message row to store in errmsg.sys header */
+uint file_pos[MAX_ROWS];
+
+const char *empty_string= ""; /* For empty states */
+/*
+ Default values for command line options. See getopt structure for definitions
+ for these.
+*/
+
+const char *default_language= "eng";
+int er_offset= 1000;
+my_bool info_flag= 0;
+
+/* Storage of one error message row (for one language) */
+
+struct message
+{
+ char *lang_short_name;
+ char *text;
+};
-int row_count;
-uint file_pos[MAX_ROWS],file_row_pos[MAX_FILES];
-my_string saved_row[MAX_ROWS];
-uchar file_head[]= { 254,254,2,1 };
-char charset_name[MAX_CHARSET_NAME];
-static void get_options(int *argc,char **argv[]);
-static int count_rows(FILE *from,pchar c, pchar c2);
-static int remember_rows(FILE *from,pchar c);
-static int copy_rows(FILE *to);
+/* Storage for languages and charsets (from start of error text file) */
+
+struct languages
+{
+ char *lang_long_name; /* full name of the language */
+ char *lang_short_name; /* abbreviation of the lang. */
+ char *charset; /* Character set name */
+ struct languages *next_lang; /* Pointer to next language */
+};
- /* Functions defined in this file */
+/* Name, code and texts (for all lang) for one error message */
-int main(int argc,char *argv[])
+struct errors
{
- uint csnum= 0;
- int i,error,files,length;
- uchar head[32];
- FILE *from,*to;
- MY_INIT(argv[0]);
-
- get_options(&argc,&argv);
- error=1;
- row_count=files=0;
+ const char *er_name; /* Name of the error (ER_HASHCK) */
+ int d_code; /* Error code number */
+ const char *sql_code1; /* sql state */
+ const char *sql_code2; /* ODBC state */
+ struct errors *next_error; /* Pointer to next error */
+ DYNAMIC_ARRAY msg; /* All language texts for this error */
+};
+
- to=0;
- for ( ; argc-- > 1 ; argv++)
+static struct my_option my_long_options[]=
+{
+#ifdef DBUG_OFF
+ {"debug", '#', "This is a non-debug version. Catch this and exit",
+ 0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#else
+ {"debug", '#', "Output debug log", (gptr *) & default_dbug_option,
+ (gptr *) & default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+ {"debug-info", 'T', "Print some debug info at exit.", (gptr *) & info_flag,
+ (gptr *) & info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"version", 'V', "Prints version", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"charset", 'C', "Charset dir", (gptr *) & charsets_dir,
+ (gptr *) & charsets_dir,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"in_file", 'F', "Input file", (gptr *) & TXTFILE, (gptr *) & TXTFILE,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"out_dir", 'D', "Output base directory", (gptr *) & DATADIRECTORY,
+ (gptr *) & DATADIRECTORY,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"out_file", 'O', "Output filename (errmsg.sys)", (gptr *) & OUTFILE,
+ (gptr *) & OUTFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"header_file", 'H', "mysqld_error.h file ", (gptr *) & HEADERFILE,
+ (gptr *) & HEADERFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"name_file", 'N', "mysqld_ername.h file ", (gptr *) & NAMEFILE,
+ (gptr *) & NAMEFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"state_file", 'S', "sql_state.h file", (gptr *) & STATEFILE,
+ (gptr *) & STATEFILE, 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}
+};
+
+
+static struct languages *parse_charset_string(char *str);
+static struct errors *parse_error_string(char *ptr, int er_count);
+static struct message *parse_message_string(struct message *new_message,
+ char *str);
+static struct message *find_message(struct errors *err, const char *lang);
+static int parse_input_file(const char *file_name, struct errors **top_error,
+ struct languages **top_language);
+static int get_options(int *argc, char ***argv);
+static void print_version(void);
+static void usage(void);
+static my_bool get_one_option(int optid, const struct my_option *opt,
+ char *argument);
+static char *parse_text_line(char *pos);
+static int copy_rows(FILE * to, char *row, int row_nr, long start_pos);
+static char *parse_default_language(char *str);
+static uint parse_error_offset(char *str);
+
+static char *skip_delimiters(char *str);
+static char *get_word(char **str);
+static char *find_end_of_word(char *str);
+static void clean_up(struct languages *lang_head, struct errors *error_head);
+static int create_header_files(struct errors *error_head);
+static int create_sys_files(struct languages *lang_head,
+ struct errors *error_head, uint row_count);
+
+
+int main(int argc, char *argv[])
+{
+ MY_INIT(argv[0]);
{
- file_row_pos[files++] = row_count;
+ uint row_count;
+ struct errors *error_head;
+ struct languages *lang_head;
+ DBUG_ENTER("main");
- if ((from = fopen(*argv,"r")) == NULL)
+ charsets_dir= DEFAULT_CHARSET_DIR;
+ if (get_options(&argc, &argv))
+ DBUG_RETURN(1);
+ if (!(row_count= parse_input_file(TXTFILE, &error_head, &lang_head)))
{
- fprintf(stderr,"Can't open file '%s'\n",*argv);
- return(1);
+ fprintf(stderr, "Failed to parse input file %s\n", TXTFILE);
+ DBUG_RETURN(1);
}
-
- VOID(count_rows(from,'"','{')); /* Calculate start-info */
- if (!charset_name[0])
+ if (lang_head == NULL || error_head == NULL)
{
- fprintf(stderr,"Character set is not specified in '%s'\n",*argv);
- fclose(from);
- goto end;
+ fprintf(stderr, "Failed to parse input file %s\n", TXTFILE);
+ DBUG_RETURN(1);
}
- if (!(csnum= get_charset_number(charset_name, MY_CS_PRIMARY)))
+ if (create_header_files(error_head))
{
- fprintf(stderr,"Unknown character '%s' in '%s'\n",charset_name, *argv);
- fclose(from);
- goto end;
+ fprintf(stderr, "Failed to create header files\n");
+ DBUG_RETURN(1);
}
-
- if (remember_rows(from,'}') < 0) /* Remember rows */
+ if (create_sys_files(lang_head, error_head, row_count))
{
- fprintf(stderr,"Can't find textrows in '%s'\n",*argv);
- fclose(from);
- goto end;
+ fprintf(stderr, "Failed to create sys files\n");
+ DBUG_RETURN(1);
}
- fclose(from);
+ clean_up(lang_head, error_head);
+ my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
+ DBUG_RETURN(0);
}
+}
- if ((to=my_fopen(*argv,O_WRONLY | FILE_BINARY,MYF(0))) == NULL)
+
+static int create_header_files(struct errors *error_head)
+{
+ uint er_last;
+ FILE *er_definef, *sql_statef, *er_namef;
+ struct errors *tmp_error;
+ DBUG_ENTER("create_header_files");
+ LINT_INIT(er_last);
+
+ if (!(er_definef= my_fopen(HEADERFILE, O_WRONLY, MYF(MY_WME))))
+ {
+ DBUG_RETURN(1);
+ }
+ if (!(sql_statef= my_fopen(STATEFILE, O_WRONLY, MYF(MY_WME))))
{
- fprintf(stderr,"Can't create file '%s'\n",*argv);
- return(1);
+ my_fclose(er_definef, MYF(0));
+ DBUG_RETURN(1);
+ }
+ if (!(er_namef= my_fopen(NAMEFILE, O_WRONLY, MYF(MY_WME))))
+ {
+ my_fclose(er_definef, MYF(0));
+ my_fclose(sql_statef, MYF(0));
+ DBUG_RETURN(1);
}
- fseek(to,(long) (32+row_count*2),0);
- if (copy_rows(to))
- goto end;
+ fprintf(er_definef, "/* Autogenerated file, please don't edit */\n\n");
+ fprintf(sql_statef, "/* Autogenerated file, please don't edit */\n\n");
+ fprintf(er_namef, "/* Autogenerated file, please don't edit */\n\n");
- length=ftell(to)-32-row_count*2;
+ fprintf(er_definef, "#define ER_ERROR_FIRST %d\n", error_head->d_code);
- bzero((gptr) head,32); /* Save Header & pointers */
- bmove((byte*) head,(byte*) file_head,4);
- head[4]=files;
- int2store(head+6,length);
- int2store(head+8,row_count);
- for (i=0 ; i<files ; i++)
+ for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error)
{
- int2store(head+10+i+i,file_row_pos[i]);
+ /*
+ generating mysqld_error.h
+ fprintf() will automatically add \r on windows
+ */
+ fprintf(er_definef, "#define %s %d\n", tmp_error->er_name,
+ tmp_error->d_code);
+ er_last= tmp_error->d_code;
+
+ /* generating sql_state.h file */
+ if (tmp_error->sql_code1[0] || tmp_error->sql_code2[0])
+ fprintf(sql_statef,
+ "%-40s,\"%s\", \"%s\",\n", tmp_error->er_name,
+ tmp_error->sql_code1, tmp_error->sql_code2);
+ /*generating er_name file */
+ fprintf(er_namef, "{ \"%s\", %d },\n", tmp_error->er_name,
+ tmp_error->d_code);
+
}
- head[30]= csnum;
-
- fseek(to,0l,0);
- if (fwrite(head,1,32,to) != 32)
- goto end;
+ /* finishing off with mysqld_error.h */
+ fprintf(er_definef, "#define ER_ERROR_LAST %d\n", er_last);
+ my_fclose(er_definef, MYF(0));
+ my_fclose(sql_statef, MYF(0));
+ my_fclose(er_namef, MYF(0));
+ DBUG_RETURN(0);
+}
+
- for (i=0 ; i<row_count ; i++)
+static int create_sys_files(struct languages *lang_head,
+ struct errors *error_head, uint row_count)
+{
+ FILE *to;
+ uint csnum= 0, length, i, row_nr;
+ uchar head[32];
+ char outfile[FN_REFLEN], *outfile_end;
+ long start_pos;
+ struct message *tmp;
+ struct languages *tmp_lang;
+ struct errors *tmp_error;
+
+ MY_STAT stat_info;
+ DBUG_ENTER("create_sys_files");
+
+ /*
+ going over all languages and assembling corresponding error messages
+ */
+ for (tmp_lang= lang_head; tmp_lang; tmp_lang= tmp_lang->next_lang)
{
- int2store(head,file_pos[i]);
- if (fwrite(head,1,2,to) != 2)
- goto end;
- }
- error=0;
- printf("Found %d messages in language file %s\n",row_count,*argv);
- end:
- if (to)
- fclose(to);
- if (error)
- fprintf(stderr,"Can't update messagefile %s, errno: %d\n",*argv,errno);
+ /* setting charset name */
+ if (!(csnum= get_charset_number(tmp_lang->charset, MY_CS_PRIMARY)))
+ {
+ fprintf(stderr, "Unknown charset '%s' in '%s'\n", tmp_lang->charset,
+ TXTFILE);
+ DBUG_RETURN(1);
+ }
+
+ outfile_end= strxmov(outfile, DATADIRECTORY,
+ tmp_lang->lang_long_name, NullS);
+ if (!my_stat(outfile, &stat_info,MYF(0)))
+ {
+ if (my_mkdir(outfile, 0777,MYF(0)) < 0)
+ {
+ fprintf(stderr, "Can't create output directory for %s\n",
+ outfile);
+ DBUG_RETURN(1);
+ }
+ }
+
+ strxmov(outfile_end, FN_ROOTDIR, OUTFILE, NullS);
- exit(error);
- return(0);
-} /* main */
+ if (!(to= my_fopen(outfile, O_WRONLY | FILE_BINARY, MYF(MY_WME))))
+ DBUG_RETURN(1);
+ /* 2 is for 2 bytes to store row position / error message */
+ start_pos= (long) (HEADER_LENGTH + row_count * 2);
+ fseek(to, start_pos, 0);
+ row_nr= 0;
+ for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error)
+ {
+ /* dealing with messages */
+ tmp= find_message(tmp_error, tmp_lang->lang_short_name);
- /* Read options */
+ if (!tmp)
+ {
+ fprintf(stderr,
+ "Did not find message for %s neither in %s nor in default "
+ "language\n", tmp_error->er_name, tmp_lang->lang_short_name);
+ goto err;
+ }
+ if (copy_rows(to, tmp->text, row_nr, start_pos))
+ {
+ fprintf(stderr, "Failed to copy rows to %s\n", outfile);
+ goto err;
+ }
+ row_nr++;
+ }
-static void get_options(register int *argc,register char **argv[])
-{
- int help=0;
- char *pos,*progname;
-
- progname= (*argv)[0];
- while (--*argc >0 && *(pos = *(++*argv)) == '-' ) {
- while (*++pos)
- switch(*pos) {
- case '#':
- DBUG_PUSH (++pos);
- *(pos--) = '\0'; /* Skippa argument */
- break;
- case 'V':
- printf("%s (Compile errormessage) Ver 1.3\n",progname);
- break;
- case 'C':
- charsets_dir= pos+1;
- *(pos--)= '\0';
- break;
- case 'I':
- case '?':
- printf(" %s (Compile errormessage) Ver 1.3\n",progname);
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
- printf("Usage: %s [-?] [-I] [-V] fromfile[s] tofile\n",progname);
- puts("Options: -Info -Version\n");
- help=1;
- break;
- default:
- fprintf(stderr,"illegal option: -%c\n",*pos);
- fprintf(stderr,"legal options: -?IV\n");
- break;
+ /* continue with header of the errmsg.sys file */
+ length= ftell(to) - HEADER_LENGTH - row_count * 2;
+ bzero((gptr) head, HEADER_LENGTH);
+ bmove((byte *) head, (byte *) file_head, 4);
+ head[4]= 1;
+ int2store(head + 6, length);
+ int2store(head + 8, row_count);
+ head[30]= csnum;
+
+ my_fseek(to, 0l, MY_SEEK_SET, MYF(0));
+ if (my_fwrite(to, (byte*) head, HEADER_LENGTH, MYF(MY_WME | MY_FNABP)))
+ goto err;
+
+ for (i= 0; i < row_count; i++)
+ {
+ int2store(head, file_pos[i]);
+ if (my_fwrite(to, (byte*) head, 2, MYF(MY_WME | MY_FNABP)))
+ goto err;
}
+ my_fclose(to, MYF(0));
}
- if (*argc < 2)
+ DBUG_RETURN(0);
+
+err:
+ my_fclose(to, MYF(0));
+ DBUG_RETURN(1);
+}
+
+
+static void clean_up(struct languages *lang_head, struct errors *error_head)
+{
+ struct languages *tmp_lang, *next_language;
+ struct errors *tmp_error, *next_error;
+ uint count, i;
+
+ my_free((gptr) default_language, MYF(0));
+
+ for (tmp_lang= lang_head; tmp_lang; tmp_lang= next_language)
{
- if (!help)
- printf("Usage: %s [-?] [-I] [-V] fromfile[s] tofile\n",progname);
- exit(-1);
+ next_language= tmp_lang->next_lang;
+ my_free(tmp_lang->lang_short_name, MYF(0));
+ my_free(tmp_lang->lang_long_name, MYF(0));
+ my_free(tmp_lang->charset, MYF(0));
+ my_free((gptr) tmp_lang, MYF(0));
}
- return;
-} /* get_options */
+ for (tmp_error= error_head; tmp_error; tmp_error= next_error)
+ {
+ next_error= tmp_error->next_error;
+ count= (tmp_error->msg).elements;
+ for (i= 0; i < count; i++)
+ {
+ struct message *tmp;
+ tmp= dynamic_element(&tmp_error->msg, i, struct message*);
+ my_free((gptr) tmp->lang_short_name, MYF(0));
+ my_free((gptr) tmp->text, MYF(0));
+ }
+
+ delete_dynamic(&tmp_error->msg);
+ if (tmp_error->sql_code1[0])
+ my_free((gptr) tmp_error->sql_code1, MYF(0));
+ if (tmp_error->sql_code2[0])
+ my_free((gptr) tmp_error->sql_code2, MYF(0));
+ my_free((gptr) tmp_error->er_name, MYF(0));
+ my_free((gptr) tmp_error, MYF(0));
+ }
+}
- /* Count rows in from-file until row that start with char is found */
-static int count_rows(FILE *from, pchar c, pchar c2)
+static int parse_input_file(const char *file_name, struct errors **top_error,
+ struct languages **top_lang)
{
- int count;
- long pos;
- char rad[MAXLENGTH];
- DBUG_ENTER("count_rows");
-
- pos=ftell(from); count=0;
-
- charset_name[0]= '\0';
- while (fgets(rad,MAXLENGTH,from) != NULL)
+ FILE *file;
+ char *str, buff[1000];
+ struct errors *current_error= 0, **tail_error= top_error;
+ struct message current_message;
+ int rcount= 0;
+ DBUG_ENTER("parse_input_file");
+
+ if (!(file= my_fopen(file_name, O_RDONLY | O_SHARE, MYF(MY_WME))))
+ DBUG_RETURN(0);
+
+ while ((str= fgets(buff, sizeof(buff), file)))
{
- if (!strncmp(rad,"character-set=",14))
+ if (is_prefix(str, "language"))
+ {
+ if (!(*top_lang= parse_charset_string(str)))
+ {
+ fprintf(stderr, "Failed to parse the charset string!\n");
+ DBUG_RETURN(0);
+ }
+ continue;
+ }
+ if (is_prefix(str, "start-error-number"))
+ {
+ if (!(er_offset= parse_error_offset(str)))
+ {
+ fprintf(stderr, "Failed to parse the error offset string!\n");
+ DBUG_RETURN(0);
+ }
+ continue;
+ }
+ if (is_prefix(str, "default-language"))
+ {
+ if (!(default_language= parse_default_language(str)))
+ {
+ DBUG_PRINT("info", ("default_slang: %s", default_language));
+ fprintf(stderr,
+ "Failed to parse the default language line. Aborting\n");
+ DBUG_RETURN(0);
+ }
+ continue;
+ }
+
+ if (*str == '\t' || *str == ' ')
{
- char *b= rad+14, *e;
- for (e=b ; e[0] && e-b < MAX_CHARSET_NAME &&
- e[0] != ' ' && e[0] != '\r' &&
- e[0] != '\n' && e[0] != '\t' ; e++);
- e[0]= '\0';
- strcpy(charset_name, b);
+ /* New error message in another language for previous error */
+ if (!current_error)
+ {
+ fprintf(stderr, "Error in the input file format\n");
+ DBUG_RETURN(0);
+ }
+ if (!parse_message_string(&current_message, str))
+ {
+ fprintf(stderr, "Failed to parse message string for error '%s'",
+ current_error->er_name);
+ DBUG_RETURN(0);
+ }
+ if (insert_dynamic(&current_error->msg, (byte *) & current_message))
+ DBUG_RETURN(0);
+ continue;
}
- if (rad[0] == c || rad[0] == c2)
- break;
- count++;
- pos=ftell(from);
+ if (is_prefix(str, ER_PREFIX) || is_prefix(str, WARN_PREFIX))
+ {
+ if (!(current_error= parse_error_string(str, rcount)))
+ {
+ fprintf(stderr, "Failed to parse the error name string\n");
+ DBUG_RETURN(0);
+ }
+ rcount++; /* Count number of unique errors */
+
+ /* add error to the list */
+ *tail_error= current_error;
+ tail_error= &current_error->next_error;
+ continue;
+ }
+ if (*str == '#' || *str == '\n')
+ continue; /* skip comment or empty lines */
+
+ fprintf(stderr, "Wrong input file format. Stop!\nLine: %s\n", str);
+ DBUG_RETURN(0);
+ }
+ *tail_error= 0; /* Mark end of list */
+
+ my_fclose(file, MYF(0));
+ DBUG_RETURN(rcount);
+}
+
+
+static uint parse_error_offset(char *str)
+{
+ char *soffset, *end;
+ int error;
+ uint ioffset;
+
+ DBUG_ENTER("parse_error_offset");
+ /* skipping the "start-error-number" keyword and spaces after it */
+ str= find_end_of_word(str);
+ str= skip_delimiters(str);
+
+ if (!*str)
+ DBUG_RETURN(0); /* Unexpected EOL: No error number after the keyword */
+
+ /* reading the error offset */
+ if (!(soffset= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+ DBUG_PRINT("info", ("default_error_offset: %s", soffset));
+
+ /* skipping space(s) and/or tabs after the error offset */
+ str= skip_delimiters(str);
+ DBUG_PRINT("info", ("str: %s", str));
+ if (*str)
+ {
+ /* The line does not end with the error offset -> error! */
+ fprintf(stderr, "The error offset line does not end with an error offset");
+ DBUG_RETURN(0);
}
- fseek(from,pos,0); /* Position to beginning of last row */
- DBUG_PRINT("exit",("count: %d",count));
- DBUG_RETURN(count);
-} /* count_rows */
+ DBUG_PRINT("info", ("str: %s", str));
+
+ end= 0;
+ ioffset= (uint) my_strtoll10(soffset, &end, &error);
+ my_free((gptr) soffset, MYF(0));
+ DBUG_RETURN(ioffset);
+}
- /* Read rows and remember them until row that start with char */
- /* Converts row as a C-compiler would convert a textstring */
+/* Parsing of the default language line. e.g. "default-language eng" */
-static int remember_rows(FILE* from, pchar c)
+static char *parse_default_language(char *str)
{
- int i,nr,start_count,found_end;
- char row[MAXLENGTH],*pos;
- DBUG_ENTER("remember_rows");
+ char *slang;
+
+ DBUG_ENTER("parse_default_language");
+ /* skipping the "default-language" keyword */
+ str= find_end_of_word(str);
+ /* skipping space(s) and/or tabs after the keyword */
+ str= skip_delimiters(str);
+ if (!*str)
+ {
+ fprintf(stderr,
+ "Unexpected EOL: No short language name after the keyword\n");
+ DBUG_RETURN(0);
+ }
+
+ /* reading the short language tag */
+ if (!(slang= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+ DBUG_PRINT("info", ("default_slang: %s", slang));
- start_count=row_count; found_end=0;
- while (fgets(row,MAXLENGTH,from) != NULL)
+ str= skip_delimiters(str);
+ DBUG_PRINT("info", ("str: %s", str));
+ if (*str)
{
- if (row[0] == c)
+ fprintf(stderr,
+ "The default language line does not end with short language "
+ "name\n");
+ DBUG_RETURN(0);
+ }
+ DBUG_PRINT("info", ("str: %s", str));
+ DBUG_RETURN(slang);
+}
+
+
+/*
+ For given error, finds message in given language; if does not exist,
+ returns english.
+*/
+
+static struct message *find_message(struct errors *err, const char *lang)
+{
+ struct message *tmp, *return_val= 0;
+ uint i, count;
+ DBUG_ENTER("find_message");
+
+ count= (err->msg).elements;
+ for (i= 0; i < count; i++)
+ {
+ tmp= dynamic_element(&err->msg, i, struct message*);
+
+ if (!strcmp(tmp->lang_short_name, lang))
+ DBUG_RETURN(tmp);
+ if (!strcmp(tmp->lang_short_name, default_language))
{
- found_end=1;
- break;
+ DBUG_ASSERT(tmp->text[0] != 0);
+ return_val= tmp;
}
- for (pos=row ; *pos ;)
+ }
+ DBUG_RETURN(return_val);
+}
+
+
+/*
+ Skips spaces and or tabs till the beginning of the next word
+ Returns pointer to the beginning of the first character of the word
+*/
+
+static char *skip_delimiters(char *str)
+{
+ DBUG_ENTER("skip_delimiters");
+ for (;
+ *str == ' ' || *str == ',' || *str == '\t' || *str == '\r' ||
+ *str == '\n' || *str == '='; str++)
+ ;
+ DBUG_RETURN(str);
+}
+
+
+/*
+ Skips all characters till meets with space, or tab, or EOL
+*/
+
+static char *find_end_of_word(char *str)
+{
+ DBUG_ENTER("find_end_of_word");
+ for (;
+ *str != ' ' && *str != '\t' && *str != '\n' && *str != '\r' && *str &&
+ *str != ',' && *str != ';' && *str != '='; str++)
+ ;
+ DBUG_RETURN(str);
+}
+
+
+/* Read the word starting from *str */
+
+static char *get_word(char **str)
+{
+ char *start= *str;
+ DBUG_ENTER("get_word");
+
+ *str= find_end_of_word(start);
+ DBUG_RETURN(my_strdup_with_length(start, (uint) (*str - start),
+ MYF(MY_WME | MY_FAE)));
+}
+
+
+/*
+ Parsing the string with short_lang - message text. Code - to
+ remember to which error does the text belong
+*/
+
+static struct message *parse_message_string(struct message *new_message,
+ char *str)
+{
+ char *start;
+
+ DBUG_ENTER("parse_message_string");
+ DBUG_PRINT("enter", ("str: %s", str));
+
+ /*skip space(s) and/or tabs in the beginning */
+ while (*str == ' ' || *str == '\t' || *str == '\n')
+ str++;
+
+ if (!*str)
+ {
+ /* It was not a message line, but an empty line. */
+ DBUG_PRINT("info", ("str: %s", str));
+ DBUG_RETURN(0);
+ }
+
+ /* reading the short lang */
+ start= str;
+ while (*str != ' ' && *str != '\t' && *str)
+ str++;
+ if (!(new_message->lang_short_name=
+ my_strdup_with_length(start, (uint) (str - start),
+ MYF(MY_WME | MY_FAE))))
+ DBUG_RETURN(0); /* Fatal error */
+ DBUG_PRINT("info", ("msg_slang: %s", new_message->lang_short_name));
+
+ /*skip space(s) and/or tabs after the lang */
+ while (*str == ' ' || *str == '\t' || *str == '\n')
+ str++;
+
+ if (*str != '"')
+ {
+ fprintf(stderr, "Unexpected EOL");
+ DBUG_PRINT("info", ("str: %s", str));
+ DBUG_RETURN(0);
+ }
+
+ /* reading the text */
+ start= str + 1;
+ str= parse_text_line(start);
+
+ if (!(new_message->text= my_strdup_with_length(start, (uint) (str - start),
+ MYF(MY_WME | MY_FAE))))
+ DBUG_RETURN(0); /* Fatal error */
+ DBUG_PRINT("info", ("msg_text: %s", new_message->text));
+
+ DBUG_RETURN(new_message);
+}
+
+
+/*
+ Parsing the string with error name and codes; returns the pointer to
+ the errors struct
+*/
+
+static struct errors *parse_error_string(char *str, int er_count)
+{
+ struct errors *new_error;
+ char *start;
+ DBUG_ENTER("parse_error_string");
+ DBUG_PRINT("enter", ("str: %s", str));
+
+ /* create a new element */
+ new_error= (struct errors *) my_malloc(sizeof(*new_error), MYF(MY_WME));
+
+ if (my_init_dynamic_array(&new_error->msg, sizeof(struct message), 0, 0))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+
+ /* getting the error name */
+ start= str;
+ str= skip_delimiters(str);
+
+ if (!(new_error->er_name= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+ DBUG_PRINT("info", ("er_name: %s", new_error->er_name));
+
+ str= skip_delimiters(str);
+
+ /* getting the code1 */
+
+ new_error->d_code= er_offset + er_count;
+ DBUG_PRINT("info", ("d_code: %d", new_error->d_code));
+
+ str= skip_delimiters(str);
+
+ /* if we reached EOL => no more codes, but this can happen */
+ if (!*str)
+ {
+ new_error->sql_code1= empty_string;
+ new_error->sql_code2= empty_string;
+ DBUG_PRINT("info", ("str: %s", str));
+ DBUG_RETURN(new_error);
+ }
+
+ /* getting the sql_code 1 */
+
+ if (!(new_error->sql_code1= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+ DBUG_PRINT("info", ("sql_code1: %s", new_error->sql_code1));
+
+ str= skip_delimiters(str);
+
+ /* if we reached EOL => no more codes, but this can happen */
+ if (!*str)
+ {
+ new_error->sql_code2= empty_string;
+ DBUG_PRINT("info", ("str: %s", str));
+ DBUG_RETURN(new_error);
+ }
+
+ /* getting the sql_code 2 */
+ if (!(new_error->sql_code2= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+ DBUG_PRINT("info", ("sql_code2: %s", new_error->sql_code2));
+
+ str= skip_delimiters(str);
+ if (*str)
+ {
+ fprintf(stderr, "The error line did not end with sql/odbc code!");
+ DBUG_RETURN(0);
+ }
+
+ DBUG_RETURN(new_error);
+}
+
+
+/*
+ Parsing the string with full lang name/short lang name/charset;
+ returns pointer to the language structure
+*/
+
+static struct languages *parse_charset_string(char *str)
+{
+ struct languages *head=0, *new_lang;
+ DBUG_ENTER("parse_charset_string");
+ DBUG_PRINT("enter", ("str: %s", str));
+
+ /* skip over keyword */
+ str= find_end_of_word(str);
+ if (!*str)
+ {
+ /* unexpected EOL */
+ DBUG_PRINT("info", ("str: %s", str));
+ DBUG_RETURN(0);
+ }
+
+ str= skip_delimiters(str);
+ if (!(*str != ';' && *str))
+ DBUG_RETURN(0);
+
+ do
+ {
+ /*creating new element of the linked list */
+ new_lang= (struct languages *) my_malloc(sizeof(*new_lang), MYF(MY_WME));
+ new_lang->next_lang= head;
+ head= new_lang;
+
+ /* get the full language name */
+
+ if (!(new_lang->lang_long_name= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+
+ DBUG_PRINT("info", ("long_name: %s", new_lang->lang_long_name));
+
+ /* getting the short name for language */
+ str= skip_delimiters(str);
+ if (!*str)
+ DBUG_RETURN(0); /* Error: No space or tab */
+
+ if (!(new_lang->lang_short_name= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+ DBUG_PRINT("info", ("short_name: %s", new_lang->lang_short_name));
+
+ /* getting the charset name */
+ str= skip_delimiters(str);
+ if (!(new_lang->charset= get_word(&str)))
+ DBUG_RETURN(0); /* Fatal error */
+ DBUG_PRINT("info", ("charset: %s", new_lang->charset));
+
+ /* skipping space, tab or "," */
+ str= skip_delimiters(str);
+ }
+ while (*str != ';' && *str);
+
+ DBUG_PRINT("info", ("long name: %s", new_lang->lang_long_name));
+ DBUG_RETURN(head);
+}
+
+
+/* Read options */
+
+static void print_version(void)
+{
+ DBUG_ENTER("print_version");
+ printf("%s (Compile errormessage) Ver %s\n", my_progname, "2.0");
+ DBUG_VOID_RETURN;
+}
+
+
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)),
+ char *argument __attribute__ ((unused)))
+{
+ DBUG_ENTER("get_one_option");
+ switch (optid) {
+ case 'V':
+ print_version();
+ exit(0);
+ break;
+ case '?':
+ usage();
+ exit(0);
+ break;
+ case '#':
+ DBUG_PUSH(argument ? argument : default_dbug_option);
+ break;
+ }
+ DBUG_RETURN(0);
+}
+
+
+static void usage(void)
+{
+ DBUG_ENTER("usage");
+ print_version();
+ printf("This software comes with ABSOLUTELY NO WARRANTY. This is free "
+ "software,\nand you are welcome to modify and redistribute it under "
+ "the GPL license\nUsage:\n");
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+ DBUG_VOID_RETURN;
+}
+
+
+static int get_options(int *argc, char ***argv)
+{
+ int ho_error;
+ DBUG_ENTER("get_options");
+
+ if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
+ DBUG_RETURN(ho_error);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Read rows and remember them until row that start with char Converts
+ row as a C-compiler would convert a textstring
+*/
+
+static char *parse_text_line(char *pos)
+{
+ int i, nr;
+ char *row= pos;
+ DBUG_ENTER("parse_text_line");
+
+ while (*pos)
+ {
+ if (*pos == '\\')
{
- if (*pos == '\\')
- {
- switch (*++pos) {
- case '\\':
- case '"':
- VOID(strmov(pos-1,pos));
- break;
- case 'n':
- pos[-1]='\n';
- VOID(strmov(pos,pos+1));
- break;
- default:
- if (*pos >= '0' && *pos <'8')
- {
- nr=0;
- for (i=0 ; i<3 && (*pos >= '0' && *pos <'8' ) ; i++)
- nr=nr*8+ (*(pos++) -'0');
- pos-=i;
- pos[-1]=nr;
- VOID(strmov(pos,pos+i));
- }
- else if (*pos)
- VOID(strmov(pos-1,pos)); /* Remove '\' */
+ switch (*++pos) {
+ case '\\':
+ case '"':
+ VOID(strmov(pos - 1, pos));
+ break;
+ case 'n':
+ pos[-1]= '\n';
+ VOID(strmov(pos, pos + 1));
+ break;
+ default:
+ if (*pos >= '0' && *pos < '8')
+ {
+ nr= 0;
+ for (i= 0; i < 3 && (*pos >= '0' && *pos < '8'); i++)
+ nr= nr * 8 + (*(pos++) - '0');
+ pos -= i;
+ pos[-1]= nr;
+ VOID(strmov(pos, pos + i));
}
+ else if (*pos)
+ VOID(strmov(pos - 1, pos)); /* Remove '\' */
}
- else pos++;
}
- while (pos >row+1 && *pos != '"')
- pos--;
-
- if (!(saved_row[row_count] = (my_string) my_malloc((uint) (pos-row),
- MYF(MY_WME))))
- DBUG_RETURN(-1);
- *pos=0;
- VOID(strmov(saved_row[row_count],row+1));
- row_count++;
+ else
+ pos++;
}
- if (row_count-start_count == 0 && ! found_end)
- DBUG_RETURN(-1); /* Found nothing */
- DBUG_RETURN(row_count-start_count);
-} /* remember_rows */
+ while (pos > row + 1 && *pos != '"')
+ pos--;
+ *pos= 0;
+ DBUG_RETURN(pos);
+}
- /* Copy rows from memory to file and remember position */
+/* Copy rows from memory to file and remember position */
-
-static int copy_rows(FILE *to)
+static int copy_rows(FILE *to, char *row, int row_nr, long start_pos)
{
- int row_nr;
- long start_pos;
DBUG_ENTER("copy_rows");
- start_pos=ftell(to);
- for (row_nr =0 ; row_nr < row_count; row_nr++)
+ file_pos[row_nr]= (int) (ftell(to) - start_pos);
+ if (fputs(row, to) == EOF || fputc('\0', to) == EOF)
{
- file_pos[row_nr]= (int) (ftell(to)-start_pos);
- if (fputs(saved_row[row_nr],to) == EOF || fputc('\0',to) == EOF)
- {
- fprintf(stderr,"Can't write to outputfile\n");
- DBUG_RETURN(1);
- }
- my_free((gptr) saved_row[row_nr],MYF(0));
+ fprintf(stderr, "Can't write to outputfile\n");
+ DBUG_RETURN(1);
}
+
DBUG_RETURN(0);
-} /* copy_rows */
+}
diff --git a/extra/innochecksum.c b/extra/innochecksum.c
new file mode 100644
index 00000000000..739953298af
--- /dev/null
+++ b/extra/innochecksum.c
@@ -0,0 +1,328 @@
+/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ InnoDB offline file checksum utility. 85% of the code in this file
+ was taken wholesale fron the InnoDB codebase.
+
+ The final 15% was originally written by Mark Smith of Danga
+ Interactive, Inc. <junior@danga.com>
+
+ Published with a permission.
+*/
+
+/* needed to have access to 64 bit file functions */
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* all of these ripped from InnoDB code from MySQL 4.0.22 */
+#define UT_HASH_RANDOM_MASK 1463735687
+#define UT_HASH_RANDOM_MASK2 1653893711
+#define FIL_PAGE_LSN 16
+#define FIL_PAGE_FILE_FLUSH_LSN 26
+#define FIL_PAGE_OFFSET 4
+#define FIL_PAGE_DATA 38
+#define FIL_PAGE_END_LSN_OLD_CHKSUM 8
+#define FIL_PAGE_SPACE_OR_CHKSUM 0
+#define UNIV_PAGE_SIZE (2 * 8192)
+
+/* command line argument to do page checks (that's it) */
+/* another argument to specify page ranges... seek to right spot and go from there */
+
+typedef unsigned long int ulint;
+typedef unsigned char byte;
+
+/* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */
+ulint mach_read_from_4(byte *b)
+{
+ return( ((ulint)(b[0]) << 24)
+ + ((ulint)(b[1]) << 16)
+ + ((ulint)(b[2]) << 8)
+ + (ulint)(b[3])
+ );
+}
+
+ulint
+ut_fold_ulint_pair(
+/*===============*/
+ /* out: folded value */
+ ulint n1, /* in: ulint */
+ ulint n2) /* in: ulint */
+{
+ return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1)
+ ^ UT_HASH_RANDOM_MASK) + n2);
+}
+
+ulint
+ut_fold_binary(
+/*===========*/
+ /* out: folded value */
+ byte* str, /* in: string of bytes */
+ ulint len) /* in: length */
+{
+ ulint i;
+ ulint fold= 0;
+
+ for (i= 0; i < len; i++)
+ {
+ fold= ut_fold_ulint_pair(fold, (ulint)(*str));
+
+ str++;
+ }
+
+ return(fold);
+}
+
+ulint
+buf_calc_page_new_checksum(
+/*=======================*/
+ /* out: checksum */
+ byte* page) /* in: buffer page */
+{
+ ulint checksum;
+
+ /* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO
+ are written outside the buffer pool to the first pages of data
+ files, we have to skip them in the page checksum calculation.
+ We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
+ checksum is stored, and also the last 8 bytes of page because
+ there we store the old formula checksum. */
+
+ checksum= ut_fold_binary(page + FIL_PAGE_OFFSET,
+ FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
+ + ut_fold_binary(page + FIL_PAGE_DATA,
+ UNIV_PAGE_SIZE - FIL_PAGE_DATA
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+ checksum= checksum & 0xFFFFFFFF;
+
+ return(checksum);
+}
+
+ulint
+buf_calc_page_old_checksum(
+/*=======================*/
+ /* out: checksum */
+ byte* page) /* in: buffer page */
+{
+ ulint checksum;
+
+ checksum= ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
+
+ checksum= checksum & 0xFFFFFFFF;
+
+ return(checksum);
+}
+
+
+int main(int argc, char **argv)
+{
+ FILE *f; /* our input file */
+ byte *p; /* storage of pages read */
+ int bytes; /* bytes read count */
+ ulint ct; /* current page number (0 based) */
+ int now; /* current time */
+ int lastt; /* last time */
+ ulint oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; /* ulints for checksum storage */
+ struct stat st; /* for stat, if you couldn't guess */
+ unsigned long long int size; /* size of file (has to be 64 bits) */
+ ulint pages; /* number of pages in file */
+ ulint start_page= 0, end_page= 0, use_end_page= 0; /* for starting and ending at certain pages */
+ off_t offset= 0;
+ int just_count= 0; /* if true, just print page count */
+ int verbose= 0;
+ int debug= 0;
+ int c;
+ int fd;
+
+ /* remove arguments */
+ while ((c= getopt(argc, argv, "cvds:e:p:")) != -1)
+ {
+ switch (c)
+ {
+ case 'v':
+ verbose= 1;
+ break;
+ case 'c':
+ just_count= 1;
+ break;
+ case 's':
+ start_page= atoi(optarg);
+ break;
+ case 'e':
+ end_page= atoi(optarg);
+ use_end_page= 1;
+ break;
+ case 'p':
+ start_page= atoi(optarg);
+ end_page= atoi(optarg);
+ use_end_page= 1;
+ break;
+ case 'd':
+ debug= 1;
+ break;
+ case ':':
+ fprintf(stderr, "option -%c requires an argument\n", optopt);
+ return 1;
+ break;
+ case '?':
+ fprintf(stderr, "unrecognized option: -%c\n", optopt);
+ return 1;
+ break;
+ }
+ }
+
+ /* debug implies verbose... */
+ if (debug) verbose= 1;
+
+ /* make sure we have the right arguments */
+ if (optind >= argc)
+ {
+ printf("InnoDB offline file checksum utility.\n");
+ printf("usage: %s [-c] [-s <start page>] [-e <end page>] [-p <page>] [-v] [-d] <filename>\n", argv[0]);
+ printf("\t-c\tprint the count of pages in the file\n");
+ printf("\t-s n\tstart on this page number (0 based)\n");
+ printf("\t-e n\tend at this page number (0 based)\n");
+ printf("\t-p n\tcheck only this page (0 based)\n");
+ printf("\t-v\tverbose (prints progress every 5 seconds)\n");
+ printf("\t-d\tdebug mode (prints checksums for each page)\n");
+ return 1;
+ }
+
+ /* stat the file to get size and page count */
+ if (stat(argv[optind], &st))
+ {
+ perror("error statting file");
+ return 1;
+ }
+ size= st.st_size;
+ pages= size / UNIV_PAGE_SIZE;
+ if (just_count)
+ {
+ printf("%lu\n", pages);
+ return 0;
+ }
+ else if (verbose)
+ {
+ printf("file %s= %llu bytes (%lu pages)...\n", argv[1], size, pages);
+ printf("checking pages in range %lu to %lu\n", start_page, use_end_page ? end_page : (pages - 1));
+ }
+
+ /* open the file for reading */
+ f= fopen(argv[optind], "r");
+ if (!f)
+ {
+ perror("error opening file");
+ return 1;
+ }
+
+ /* seek to the necessary position */
+ if (start_page)
+ {
+ fd= fileno(f);
+ if (!fd)
+ {
+ perror("unable to obtain file descriptor number");
+ return 1;
+ }
+
+ offset= (off_t)start_page * (off_t)UNIV_PAGE_SIZE;
+
+ if (lseek(fd, offset, SEEK_SET) != offset)
+ {
+ perror("unable to seek to necessary offset");
+ return 1;
+ }
+ }
+
+ /* allocate buffer for reading (so we don't realloc every time) */
+ p= (byte *)malloc(UNIV_PAGE_SIZE);
+
+ /* main checksumming loop */
+ ct= start_page;
+ lastt= 0;
+ while (!feof(f))
+ {
+ bytes= fread(p, 1, UNIV_PAGE_SIZE, f);
+ if (!bytes && feof(f)) return 0;
+ if (bytes != UNIV_PAGE_SIZE)
+ {
+ fprintf(stderr, "bytes read (%d) doesn't match universal page size (%d)\n", bytes, UNIV_PAGE_SIZE);
+ return 1;
+ }
+
+ /* check the "stored log sequence numbers" */
+ logseq= mach_read_from_4(p + FIL_PAGE_LSN + 4);
+ logseqfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4);
+ if (debug)
+ printf("page %lu: log sequence number: first = %lu; second = %lu\n", ct, logseq, logseqfield);
+ if (logseq != logseqfield)
+ {
+ fprintf(stderr, "page %lu invalid (fails log sequence number check)\n", ct);
+ return 1;
+ }
+
+ /* check old method of checksumming */
+ oldcsum= buf_calc_page_old_checksum(p);
+ oldcsumfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
+ if (debug)
+ printf("page %lu: old style: calculated = %lu; recorded = %lu\n", ct, oldcsum, oldcsumfield);
+ if (oldcsumfield != mach_read_from_4(p + FIL_PAGE_LSN) && oldcsumfield != oldcsum)
+ {
+ fprintf(stderr, "page %lu invalid (fails old style checksum)\n", ct);
+ return 1;
+ }
+
+ /* now check the new method */
+ csum= buf_calc_page_new_checksum(p);
+ csumfield= mach_read_from_4(p + FIL_PAGE_SPACE_OR_CHKSUM);
+ if (debug)
+ printf("page %lu: new style: calculated = %lu; recorded = %lu\n", ct, csum, csumfield);
+ if (csumfield != 0 && csum != csumfield)
+ {
+ fprintf(stderr, "page %lu invalid (fails new style checksum)\n", ct);
+ return 1;
+ }
+
+ /* end if this was the last page we were supposed to check */
+ if (use_end_page && (ct >= end_page))
+ return 0;
+
+ /* do counter increase and progress printing */
+ ct++;
+ if (verbose)
+ {
+ if (ct % 64 == 0)
+ {
+ now= time(0);
+ if (!lastt) lastt= now;
+ if (now - lastt >= 1)
+ {
+ printf("page %lu okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100);
+ lastt= now;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c
index 794ce8dee07..bcf8c7aed7c 100644
--- a/extra/my_print_defaults.c
+++ b/extra/my_print_defaults.c
@@ -1,3 +1,4 @@
+
/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
@@ -23,8 +24,10 @@
#include <my_global.h>
#include <my_sys.h>
+#include <m_string.h>
#include <my_getopt.h>
+
const char *config_file="my"; /* Default config file */
uint verbose= 0, opt_defaults_file_used= 0;
const char *default_dbug_option="d:t:o,/tmp/my_print_defaults.trace";
@@ -48,6 +51,10 @@ static struct my_option my_long_options[] =
"Read this file after the global /etc config file and before the config file in the users home directory.",
(gptr*) &defaults_extra_file, (gptr*) &defaults_extra_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"defaults-group-suffix", 'g',
+ "In addition to the given groups, read also groups with this suffix",
+ (gptr*) &defaults_group_suffix, (gptr*) &defaults_group_suffix,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"extra-file", 'e',
"Synonym for --defaults-extra-file.",
(gptr*) &defaults_extra_file, (gptr*) &defaults_extra_file, 0, GET_STR,
@@ -77,6 +84,7 @@ static void usage(my_bool version)
puts("Prints all arguments that is give to some program using the default files");
printf("Usage: %s [OPTIONS] groups\n", my_progname);
my_print_help(my_long_options);
+ my_print_default_files(config_file);
my_print_variables(my_long_options);
printf("\nExample usage:\n%s --config-file=my client mysql\n", my_progname);
}
@@ -127,37 +135,32 @@ static int get_options(int *argc,char ***argv)
return 0;
}
+
int main(int argc, char **argv)
{
- int count, error;
- char **load_default_groups, *tmp_arguments[3],
- **argument, **arguments;
- char *defaults, *extra_defaults;
+ int count, error, args_used;
+ char **load_default_groups, *tmp_arguments[6];
+ char **argument, **arguments, **org_argv;
+ char *defaults, *extra_defaults, *group_suffix;
MY_INIT(argv[0]);
- get_defaults_files(argc, argv, &defaults, &extra_defaults);
+ org_argv= argv;
+ args_used= get_defaults_options(argc, argv, &defaults, &extra_defaults,
+ &group_suffix);
- /*
- ** Check out the args
- */
- if (!(load_default_groups=(char**) my_malloc((argc+2)*sizeof(char*),
+ /* Copy defaults-xxx arguments & program name */
+ count=args_used+1;
+ arguments= tmp_arguments;
+ memcpy((char*) arguments, (char*) org_argv, count * sizeof(*org_argv));
+ arguments[count]= 0;
+
+ /* Check out the args */
+ if (!(load_default_groups=(char**) my_malloc((argc+1)*sizeof(char*),
MYF(MY_WME))))
exit(1);
if (get_options(&argc,&argv))
exit(1);
-
- for (count=0; *argv ; argv++,count++)
- load_default_groups[count]= *argv;
- load_default_groups[count]=0;
-
- count=0;
- arguments=tmp_arguments;
- arguments[count++]=my_progname;
- if (extra_defaults)
- arguments[count++]= extra_defaults;
- if (defaults)
- arguments[count++]= defaults;
- arguments[count]= 0;
+ memcpy((char*) load_default_groups, (char*) argv, (argc + 1) * sizeof(*argv));
if ((error= load_defaults(config_file, (const char **) load_default_groups,
&count, &arguments)))
diff --git a/extra/perror.c b/extra/perror.c
index 69cd6f87aab..dedd558e4cf 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -250,7 +250,8 @@ int main(int argc,char *argv[])
'Unknown Error' (without regard to case).
*/
if (msg &&
- my_strnncoll(&my_charset_latin1, msg, 13, "Unknown Error", 13) &&
+ my_strnncoll(&my_charset_latin1, (const uchar*) msg, 13,
+ (const uchar*) "Unknown Error", 13) &&
(!unknown_error || strcmp(msg, unknown_error)))
{
found=1;
diff --git a/extra/replace.c b/extra/replace.c
index 98945ed35b3..9acf1620d49 100644
--- a/extra/replace.c
+++ b/extra/replace.c
@@ -63,7 +63,7 @@ typedef struct st_pointer_array { /* when using array-strings */
#define LAST_CHAR_CODE 259
typedef struct st_replace {
- bool found;
+ my_bool found;
struct st_replace *next[256];
} REPLACE;
@@ -80,19 +80,18 @@ typedef struct st_replace_found {
/* functions defined in this file */
-extern int main(int argc,char * *argv);
static int static_get_options(int *argc,char * * *argv);
static int get_replace_strings(int *argc,char * * *argv,
POINTER_ARRAY *from_array,
POINTER_ARRAY *to_array);
-int insert_pointer_name(POINTER_ARRAY *pa, my_string name);
-void free_pointer_array(POINTER_ARRAY *pa);
+static int insert_pointer_name(POINTER_ARRAY *pa, my_string name);
+static void free_pointer_array(POINTER_ARRAY *pa);
static int convert_pipe(REPLACE *,FILE *,FILE *);
static int convert_file(REPLACE *, my_string);
-REPLACE *init_replace(my_string *from, my_string *to,uint count, my_string
- word_end_chars);
-uint replace_strings(REPLACE *rep, my_string *start,uint *max_length,
- my_string from);
+static REPLACE *init_replace(my_string *from, my_string *to,uint count,
+ my_string word_end_chars);
+static uint replace_strings(REPLACE *rep, my_string *start,uint *max_length,
+ my_string from);
static int initialize_buffer(void);
static void reset_buffer(void);
static void free_buffer(void);
@@ -101,9 +100,7 @@ static int silent=0,verbose=0,updated=0;
/* The main program */
-int main(argc,argv)
-int argc;
-char *argv[];
+int main(int argc, char *argv[])
{
int i,error;
char word_end_chars[256],*pos;
@@ -118,7 +115,7 @@ char *argv[];
for (i=1,pos=word_end_chars ; i < 256 ; i++)
if (my_isspace(&my_charset_latin1,i))
- *pos++=i;
+ *pos++= (char) i;
*pos=0;
if (!(replace=init_replace((char**) from.typelib.type_names,
(char**) to.typelib.type_names,
@@ -153,7 +150,7 @@ static int static_get_options(argc,argv)
register int *argc;
register char **argv[];
{
- int help,version,opt;
+ int help,version;
char *pos;
silent=verbose=help=0;
@@ -162,7 +159,7 @@ register char **argv[];
while (*++pos)
{
version=0;
- switch((opt= *pos)) {
+ switch((*pos)) {
case 's':
silent=1;
break;
@@ -178,7 +175,7 @@ register char **argv[];
case 'I':
case '?':
help=1; /* Help text written */
- printf("%s Ver 1.3 for %s at %s\n",my_progname,SYSTEM_TYPE,
+ printf("%s Ver 1.4 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE);
if (version)
break;
@@ -249,7 +246,7 @@ POINTER_ARRAY *from_array,*to_array;
return 0;
}
-int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name)
+static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name)
{
uint i,length,old_count;
byte *new_pos;
@@ -323,8 +320,7 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name)
/* free pointer array */
-void free_pointer_array(pa)
-reg1 POINTER_ARRAY *pa;
+static void free_pointer_array(reg1 POINTER_ARRAY *pa)
{
if (pa->typelib.count)
{
@@ -382,9 +378,9 @@ static void or_bits(REP_SET *to,REP_SET *from);
static void copy_bits(REP_SET *to,REP_SET *from);
static int cmp_bits(REP_SET *set1,REP_SET *set2);
static int get_next_bit(REP_SET *set,uint lastpos);
-static int find_set(REP_SETS *sets,REP_SET *find);
-static int find_found(FOUND_SET *found_set,uint table_offset,
- int found_offset);
+static short find_set(REP_SETS *sets,REP_SET *find);
+static short find_found(FOUND_SET *found_set,uint table_offset,
+ int found_offset);
static uint start_at_word(my_string pos);
static uint end_of_word(my_string pos);
static uint replace_len(my_string pos);
@@ -394,11 +390,12 @@ static uint found_sets=0;
/* Init a replace structure for further calls */
-REPLACE *init_replace(my_string *from, my_string *to,uint count,
- my_string word_end_chars)
+static REPLACE *init_replace(my_string *from, my_string *to,uint count,
+ my_string word_end_chars)
{
uint i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
- int used_sets,chr,default_state;
+ int used_sets,chr;
+ short default_state;
char used_chars[LAST_CHAR_CODE],is_word_end[256];
my_string pos,to_pos,*to_array;
REP_SETS sets;
@@ -561,7 +558,7 @@ REPLACE *init_replace(my_string *from, my_string *to,uint count,
for (chr= 0 ; chr < 256 ; chr++)
{
if (! used_chars[chr])
- set->next[chr]= chr ? default_state : -1;
+ set->next[chr]= (short) (chr ? default_state : -1);
else
{
new_set=make_new_set(&sets);
@@ -652,7 +649,7 @@ REPLACE *init_replace(my_string *from, my_string *to,uint count,
for (i=1 ; i <= found_sets ; i++)
{
pos=from[found_set[i-1].table_offset];
- rep_str[i].found= !bcmp(pos,"\\^",3) ? 2 : 1;
+ rep_str[i].found= (my_bool) (!bcmp(pos,"\\^",3) ? 2 : 1);
rep_str[i].replace_string=to_array[found_set[i-1].table_offset];
rep_str[i].to_offset=found_set[i-1].found_offset-start_at_word(pos);
rep_str[i].from_offset=found_set[i-1].found_offset-replace_len(pos)+
@@ -812,7 +809,7 @@ static int get_next_bit(REP_SET *set,uint lastpos)
free given set, else put in given set in sets and return it's
position */
-static int find_set(REP_SETS *sets,REP_SET *find)
+static short find_set(REP_SETS *sets,REP_SET *find)
{
uint i;
for (i=0 ; i < sets->count-1 ; i++)
@@ -820,30 +817,33 @@ static int find_set(REP_SETS *sets,REP_SET *find)
if (!cmp_bits(sets->set+i,find))
{
free_last_set(sets);
- return i;
+ return (short) i;
}
}
- return i; /* return new postion */
+ return (short) i; /* return new postion */
}
- /* find if there is a found_set with same table_offset & found_offset
- If there is return offset to it, else add new offset and return pos.
- Pos returned is -offset-2 in found_set_structure because it's is
- saved in set->next and set->next[] >= 0 points to next set and
- set->next[] == -1 is reserved for end without replaces.
- */
-static int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
+/*
+ find if there is a found_set with same table_offset & found_offset
+ If there is return offset to it, else add new offset and return pos.
+ Pos returned is -offset-2 in found_set_structure because it's is
+ saved in set->next and set->next[] >= 0 points to next set and
+ set->next[] == -1 is reserved for end without replaces.
+*/
+
+static short find_found(FOUND_SET *found_set,uint table_offset,
+ int found_offset)
{
int i;
for (i=0 ; (uint) i < found_sets ; i++)
if (found_set[i].table_offset == table_offset &&
found_set[i].found_offset == found_offset)
- return -i-2;
+ return (short) (-i-2);
found_set[i].table_offset=table_offset;
found_set[i].found_offset=found_offset;
found_sets++;
- return -i-2; /* return new postion */
+ return (short) (-i-2); /* return new postion */
}
/* Return 1 if regexp starts with \b or ends with \b*/
@@ -878,7 +878,8 @@ static uint replace_len(my_string str)
/* The actual loop */
-uint replace_strings(REPLACE *rep, my_string *start,uint *max_length, my_string from)
+static uint replace_strings(REPLACE *rep, my_string *start,uint *max_length,
+ my_string from)
{
reg1 REPLACE *rep_pos;
reg2 REPLACE_STRING *rep_str;
@@ -1047,23 +1048,31 @@ FILE *in,*out;
}
-static int convert_file(rep,name)
-REPLACE *rep;
-my_string name;
+static int convert_file(REPLACE *rep, my_string name)
{
int error;
FILE *in,*out;
- char dir_buff[FN_REFLEN],*tempname;
+ char dir_buff[FN_REFLEN], tempname[FN_REFLEN];
+ char link_name[FN_REFLEN], *org_name = name;
+ File temp_file;
DBUG_ENTER("convert_file");
- if (!(in=my_fopen(name,O_RDONLY,MYF(MY_WME))))
+ /* check if name is a symlink */
+#ifdef HAVE_READLINK
+ org_name= (!my_disable_symlinks &&
+ !my_readlink(link_name, name, MYF(0))) ? link_name : name;
+#endif
+ if (!(in= my_fopen(org_name,O_RDONLY,MYF(MY_WME))))
+ DBUG_RETURN(1);
+ dirname_part(dir_buff,org_name);
+ if ((temp_file= create_temp_file(tempname, dir_buff, "PR", O_WRONLY,
+ MYF(MY_WME))) < 0)
+ {
+ my_fclose(in,MYF(0));
DBUG_RETURN(1);
- dirname_part(dir_buff,name);
- tempname=my_tempnam(dir_buff,"PR",MYF(MY_WME));
- if (!(out=my_fopen(tempname,(int) (O_WRONLY | O_CREAT),
- MYF(MY_WME))))
+ }
+ if (!(out= my_fdopen(temp_file, tempname, O_WRONLY, MYF(MY_WME))))
{
- (*free)(tempname);
my_fclose(in,MYF(0));
DBUG_RETURN(1);
}
@@ -1072,10 +1081,9 @@ my_string name;
my_fclose(in,MYF(0)); my_fclose(out,MYF(0));
if (updated && ! error)
- my_redel(name,tempname,MYF(MY_WME | MY_LINK_WARNING));
+ my_redel(org_name,tempname,MYF(MY_WME | MY_LINK_WARNING));
else
my_delete(tempname,MYF(MY_WME));
- (*free)(tempname);
if (!silent && ! error)
{
if (updated)
diff --git a/extra/yassl/AUTHORS b/extra/yassl/AUTHORS
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/AUTHORS
diff --git a/extra/yassl/ChangeLog b/extra/yassl/ChangeLog
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/ChangeLog
diff --git a/extra/yassl/INSTALL b/extra/yassl/INSTALL
new file mode 100644
index 00000000000..54caf7c190f
--- /dev/null
+++ b/extra/yassl/INSTALL
@@ -0,0 +1,229 @@
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am
new file mode 100644
index 00000000000..7c1f2ea5acb
--- /dev/null
+++ b/extra/yassl/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = taocrypt src
+EXTRA_DIST = yassl.dsp yassl.dsw mySTL/*.hpp
diff --git a/extra/yassl/NEWS b/extra/yassl/NEWS
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/NEWS
diff --git a/extra/yassl/README b/extra/yassl/README
new file mode 100644
index 00000000000..198a1031cb7
--- /dev/null
+++ b/extra/yassl/README
@@ -0,0 +1,263 @@
+yaSSL Release notes, version 0.9.6
+
+This release of yaSSL contains minor bug fixes, removal of STL support, and
+removal of exceptions and rtti so that the library can be linked without the
+std c++ library.
+
+--To build on Linux, Solaris, FreeBSD, Mac OS X, or Cygwin
+
+./configure
+make
+
+run testsuite from yaSSL-Home/testsuite to test the build
+
+
+--To build on Win32
+
+Choose (Re)Build All from the project workspace
+
+run Debug\testsuite.exe from yaSSL-Home\testsuite to test the build
+
+
+
+******************yaSSL Release notes, version 0.9.2
+
+This release of yaSSL contains minor bug fixes, expanded certificate
+verification and chaining, and improved documentation.
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.9.0
+
+This release of yaSSL contains minor bug fixes, client verification handling,
+hex and base64 encoing/decoding, and an improved test suite.
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.8.0
+
+This release of yaSSL contains minor bug fixes, and initial porting effort to
+64bit, BigEndian, and more UNIX systems.
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.6.0
+
+This release of yaSSL contains minor bug fixes, source cleanup, and binary beta
+(1) of the yaSSL libraries.
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.5.0
+
+This release of yaSSL contains minor bug fixes, full session resumption
+support, and initial testing suite support.
+
+
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.4.0
+
+This release of yaSSL contains minor bug fixes, an optional memory tracker,
+an echo client and server with input/output redirection for load testing,
+and initial session caching support.
+
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.3.5
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library including a full test suite.
+
+
+*******************yaSSL Release notes, version 0.3.0
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library including AES and an improved random number generator. GNU autoconf
+and automake are now used to simplify the build process on Linux.
+
+*** Linux Build process
+
+./configure
+make
+
+*** Windows Build process
+
+open the yassl workspace and build the project
+
+
+*******************yaSSL Release notes, version 0.2.9
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library.
+
+See the notes at the bottom of this page for build instructions.
+
+
+*******************yaSSL Release notes, version 0.2.5
+
+This release of yaSSL contains minor bug fixes and a beta binary of the yaSSL
+libraries for win32 and linux.
+
+See the notes at the bottom of this page for build instructions.
+
+
+
+*******************yaSSL Release notes, version 0.2.0
+
+This release of yaSSL contains minor bug fixes and initial alternate crypto
+functionality.
+
+*** Complete Build ***
+
+See the notes in Readme.txt for build instructions.
+
+*** Update Build ***
+
+If you have already done a complete build of yaSSL as described in the release
+0.0.1 - 0.1.0 notes and downloaded the update to 0.2.0, place the update file
+yassl-update-0.2.0.tar.gz in the yaSSL home directory and issue the command:
+
+gzip -cd yassl-update-0.2.0.tar.gz | tar xvf -
+
+to update the previous release.
+
+Then issue the make command on linux or rebuild the yaSSL project on Windows.
+
+*******************yaSSL Release notes, version 0.1.0
+
+This release of yaSSL contains minor bug fixes, full client and server TLSv1
+support including full ephemeral Diffie-Hellman support, SSL type RSA and DSS
+signing and verification, and initial stunnel 4.05 build support.
+
+
+
+*********************yaSSL Release notes, version 0.0.3
+
+The third release of yaSSL contains minor bug fixes, client certificate
+enhancements, and initial ephemeral Diffie-Hellman integration:
+
+
+
+*********************
+
+yaSSL Release notes, version 0.0.2
+
+The second release of yaSSL contains minor bug fixes, client certificate
+enhancements, session resumption, and improved TLS support including:
+
+- HMAC for MD5 and SHA-1
+- PRF (pseudo random function)
+- Master Secret and Key derivation routines
+- Record Authentication codes
+- Finish verify data check
+
+Once ephemeral RSA and DH are added yaSSL will be fully complaint with TLS.
+
+
+
+**********************
+
+yassl Release notes, version 0.0.1
+
+The first release of yassl supports normal RSA mode SSLv3 connections with
+support for SHA-1 and MD5 digests. Ciphers include DES, 3DES, and RC4.
+
+yassl uses the CryptoPP library for cryptography, the source is available at
+www.cryptopp.com .
+
+yassl uses CML (the Certificate Management Library) for x509 support. More
+features will be in future versions. The CML source is available for download
+from www.digitalnet.com/knowledge/cml_home.htm .
+
+The next release of yassl will support the 3 lesser-used SSL connection modes;
+HandShake resumption, Ephemeral RSA (or DH), and Client Authentication as well
+as full support for TLS. Backwards support for SSLv2 is not planned at this
+time.
+
+
+**********************
+
+Building yassl on linux:
+
+use the ./buildall script to build everything.
+
+buildall will configure and build CML, CryptoPP, and yassl. Testing was
+preformed with gcc version 3.3.2 on kernel 2.4.22.
+
+
+**********************
+
+Building yassl on Windows:
+
+Testing was preformed on Windows 2000 with Visual C++ 6 sp5.
+
+1) decompress esnacc_r16.tgz in place, see buildall for syntax if unsure
+
+2) decompress smp_r23.tgz in place
+
+3) unzip cryptopp51/crypto51.zip in place
+
+4) Build SNACC (part of CML) using snacc_builds.dsw in the SNACC directory
+
+5) Build SMP (part of CMP) using smp.dsw in the smp directory
+
+6) Build yassl using yassl.dsw
+
+
+**********************
+
+examples, server and client:
+
+Please see the server and client examples in both versions to see how to link
+to yassl and the support libraries. On linux do 'make server' and 'make
+client' to build them. On Windows you will find the example projects in the
+main workspace, yassl.dsw.
+
+The example server and client are compatible with openssl.
+
+
+**********************
+
+Building yassl into mysql on linux:
+
+Testing was done using mysql version 4.0.17.
+
+alter openssl_libs in the configure file, line 21056. Change '-lssl -lcrypto'
+to '-lyassl -lcryptopp -lcmapi -lcmlasn -lctil -lc++asn1'.
+
+see build/config_command for the configure command used to configure mysql
+please change /home/touska/ to the relevant directory of course.
+
+add yassl/lib to the LD_LIBRARY_PATH because libmysql/conf_to_src does not
+use the ssl lib directory though it does use the ssl libraries.
+
+make
+
+make install
+
+
+*********************
+
+License: yassl is currently under the GPL, please see license information
+in the source and include files.
+
+
+*********************
+
+Contact: please send comments or questions to Todd A Ouska at todd@yassl.com
+and/or Larry Stefonic at larry@yassl.com or 425-741-6858.
+
+
+
diff --git a/extra/yassl/include/buffer.hpp b/extra/yassl/include/buffer.hpp
new file mode 100644
index 00000000000..6b0e9e65389
--- /dev/null
+++ b/extra/yassl/include/buffer.hpp
@@ -0,0 +1,207 @@
+/* buffer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* yaSSL buffer header defines input and output buffers to simulate streaming
+ * with SSL types and sockets
+ */
+
+#ifndef yaSSL_BUFFER_HPP
+#define yaSSL_BUFFER_HPP
+
+#include <assert.h> // assert
+#include "yassl_types.hpp" // ysDelete
+#include "memory.hpp" // mySTL::auto_ptr
+#include "algorithm.hpp" // mySTL::swap
+
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+
+namespace yaSSL {
+
+typedef unsigned char byte;
+typedef unsigned int uint;
+const uint AUTO = 0xFEEDBEEF;
+
+
+// Checking Policy should implement a check function that tests whether the
+// index is within the size limit of the array
+struct Check {
+ void check(uint i, uint limit);
+};
+
+
+struct NoCheck {
+ void check(uint, uint);
+};
+
+/* input_buffer operates like a smart c style array with a checking option,
+ * meant to be read from through [] with AUTO index or read().
+ * Should only write to at/near construction with assign() or raw (e.g., recv)
+ * followed by add_size with the number of elements added by raw write.
+ *
+ * Not using vector because need checked []access, offset, and the ability to
+ * write to the buffer bulk wise and have the correct size
+ */
+
+class input_buffer : public Check {
+ uint size_; // number of elements in buffer
+ uint current_; // current offset position in buffer
+ byte* buffer_; // storage for buffer
+ byte* end_; // end of storage marker
+public:
+ input_buffer();
+
+ explicit input_buffer(uint s);
+
+ // with assign
+ input_buffer(uint s, const byte* t, uint len);
+
+ ~input_buffer();
+
+ // users can pass defualt zero length buffer and then allocate
+ void allocate(uint s);
+
+ // for passing to raw writing functions at beginning, then use add_size
+ byte* get_buffer() const;
+
+ // after a raw write user can set new size
+ // if you know the size before the write use assign()
+ void add_size(uint i);
+
+ uint get_capacity() const;
+
+ uint get_current() const;
+
+ uint get_size() const;
+
+ uint get_remaining() const;
+
+ void set_current(uint i);
+
+ // read only access through [], advance current
+ // user passes in AUTO index for ease of use
+ const byte& operator[](uint i);
+
+ // end of input test
+ bool eof();
+
+ // peek ahead
+ byte peek() const;
+
+ // write function, should use at/near construction
+ void assign(const byte* t, uint s);
+
+ // use read to query input, adjusts current
+ void read(byte* dst, uint length);
+
+private:
+ input_buffer(const input_buffer&); // hide copy
+ input_buffer& operator=(const input_buffer&); // and assign
+};
+
+
+/* output_buffer operates like a smart c style array with a checking option.
+ * Meant to be written to through [] with AUTO index or write().
+ * Size (current) counter increases when written to. Can be constructed with
+ * zero length buffer but be sure to allocate before first use.
+ * Don't use add write for a couple bytes, use [] instead, way less overhead.
+ *
+ * Not using vector because need checked []access and the ability to
+ * write to the buffer bulk wise and retain correct size
+ */
+class output_buffer : public Check {
+ uint current_; // current offset and elements in buffer
+ byte* buffer_; // storage for buffer
+ byte* end_; // end of storage marker
+public:
+ // default
+ output_buffer();
+
+ // with allocate
+ explicit output_buffer(uint s);
+
+ // with assign
+ output_buffer(uint s, const byte* t, uint len);
+
+ ~output_buffer();
+
+ uint get_size() const;
+
+ uint get_capacity() const;
+
+ void set_current(uint c);
+
+ // users can pass defualt zero length buffer and then allocate
+ void allocate(uint s);
+
+ // for passing to reading functions when finished
+ const byte* get_buffer() const;
+
+ // allow write access through [], update current
+ // user passes in AUTO as index for ease of use
+ byte& operator[](uint i);
+
+ // end of output test
+ bool eof();
+
+ void write(const byte* t, uint s);
+
+private:
+ output_buffer(const output_buffer&); // hide copy
+ output_buffer& operator=(const output_buffer&); // and assign
+};
+
+
+
+
+// turn delete an incomplete type into comipler error instead of warning
+template <typename T>
+inline void checked_delete(T* p)
+{
+ typedef char complete_type[sizeof(T) ? 1 : -1];
+ (void)sizeof(complete_type);
+ ysDelete(p);
+}
+
+
+// checked delete functor increases effeciency, no indirection on function call
+// sets pointer to zero so safe for std conatiners
+struct del_ptr_zero
+{
+ template <typename T>
+ void operator()(T*& p) const
+ {
+ T* tmp = 0;
+ mySTL::swap(tmp, p);
+ checked_delete(tmp);
+ }
+};
+
+
+
+} // naemspace
+
+#endif // yaSSL_BUUFER_HPP
diff --git a/extra/yassl/include/cert_wrapper.hpp b/extra/yassl/include/cert_wrapper.hpp
new file mode 100644
index 00000000000..2381347c27e
--- /dev/null
+++ b/extra/yassl/include/cert_wrapper.hpp
@@ -0,0 +1,124 @@
+/* cert_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* The certificate wrapper header defines certificate management functions
+ *
+ */
+
+
+#ifndef yaSSL_CERT_WRAPPER_HPP
+#define yaSSL_CERT_WRAPPER_HPP
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+
+#include "yassl_types.hpp" // SignatureAlgorithm
+#include "buffer.hpp" // input_buffer
+#include "asn.hpp" // SignerList
+#include "list.hpp" // mySTL::list
+#include "algorithm.hpp" // mySTL::for_each
+
+namespace yaSSL {
+
+typedef unsigned char opaque;
+class X509; // forward openSSL type
+
+using TaoCrypt::SignerList;
+
+// an x509 version 3 certificate
+class x509 {
+ uint length_;
+ opaque* buffer_;
+public:
+ explicit x509(uint sz);
+ ~x509();
+
+ uint get_length() const;
+ const opaque* get_buffer() const;
+ opaque* use_buffer();
+
+ x509(const x509&);
+ x509& operator=(const x509&);
+private:
+ void Swap(x509&);
+};
+
+
+// Certificate Manager keeps a list of the cert chain and public key
+class CertManager {
+ typedef mySTL::list<x509*> CertList;
+
+ CertList list_; // self
+ input_buffer privateKey_;
+
+ CertList peerList_; // peer
+ input_buffer peerPublicKey_;
+ X509* peerX509_; // peer's openSSL X509
+
+ SignatureAlgorithm keyType_; // self key type
+ SignatureAlgorithm peerKeyType_; // peer's key type
+
+ SignerList signers_; // decoded CA keys and names
+ // plus verified chained certs
+ bool verifyPeer_;
+ bool failNoCert_;
+ bool sendVerify_;
+public:
+ CertManager();
+ ~CertManager();
+
+ void AddPeerCert(x509* x); // take ownership
+ void CopySelfCert(const x509* x);
+ int CopyCaCert(const x509* x);
+ int Validate();
+
+ int SetPrivateKey(const x509&);
+
+ const x509* get_cert() const;
+ const opaque* get_peerKey() const;
+ const opaque* get_privateKey() const;
+ X509* get_peerX509() const;
+ SignatureAlgorithm get_keyType() const;
+ SignatureAlgorithm get_peerKeyType() const;
+
+ uint get_peerKeyLength() const;
+ uint get_privateKeyLength() const;
+
+ bool verifyPeer() const;
+ bool failNoCert() const;
+ bool sendVerify() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+ void setSendVerify();
+private:
+ CertManager(const CertManager&); // hide copy
+ CertManager& operator=(const CertManager&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_CERT_WRAPPER_HPP
diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp
new file mode 100644
index 00000000000..ca9d870677e
--- /dev/null
+++ b/extra/yassl/include/crypto_wrapper.hpp
@@ -0,0 +1,418 @@
+/* crypto_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* The crypto wrapper header is used to define policies for the cipher
+ * components used by SSL. There are 3 policies to consider:
+ *
+ * 1) MAC, the Message Authentication Code used for each Message
+ * 2) Bulk Cipher, the Cipher used to encrypt/decrypt each Message
+ * 3) Atuhentication, the Digitial Signing/Verifiaction scheme used
+ *
+ * This header doesn't rely on a specific crypto libraries internals,
+ * only the implementation should.
+ */
+
+
+#ifndef yaSSL_CRYPTO_WRAPPER_HPP
+#define yaSSL_CRYPTO_WRAPPER_HPP
+
+#include "yassl_types.hpp"
+
+
+namespace yaSSL {
+
+
+// Digest policy should implement a get_digest, update, and get sizes for pad and
+// digest
+struct Digest : public virtual_base {
+ virtual void get_digest(byte*) = 0;
+ virtual void get_digest(byte*, const byte*, unsigned int) = 0;
+ virtual void update(const byte*, unsigned int) = 0;
+ virtual uint get_digestSize() const = 0;
+ virtual uint get_padSize() const = 0;
+ virtual ~Digest() {}
+};
+
+
+// For use with NULL Digests
+struct NO_MAC : public Digest {
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+};
+
+
+// MD5 Digest
+class MD5 : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ MD5();
+ ~MD5();
+ MD5(const MD5&);
+ MD5& operator=(const MD5&);
+private:
+ struct MD5Impl;
+ MD5Impl* pimpl_;
+};
+
+
+// SHA-1 Digest
+class SHA : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ SHA();
+ ~SHA();
+ SHA(const SHA&);
+ SHA& operator=(const SHA&);
+private:
+ struct SHAImpl;
+ SHAImpl* pimpl_;
+
+};
+
+
+// RIPEMD-160 Digest
+class RMD : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ RMD();
+ ~RMD();
+ RMD(const RMD&);
+ RMD& operator=(const RMD&);
+private:
+ struct RMDImpl;
+ RMDImpl* pimpl_;
+
+};
+
+
+// HMAC_MD5
+class HMAC_MD5 : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_MD5(const byte*, unsigned int);
+ ~HMAC_MD5();
+private:
+ struct HMAC_MD5Impl;
+ HMAC_MD5Impl* pimpl_;
+
+ HMAC_MD5(const HMAC_MD5&);
+ HMAC_MD5& operator=(const HMAC_MD5&);
+};
+
+
+// HMAC_SHA-1
+class HMAC_SHA : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_SHA(const byte*, unsigned int);
+ ~HMAC_SHA();
+private:
+ struct HMAC_SHAImpl;
+ HMAC_SHAImpl* pimpl_;
+
+ HMAC_SHA(const HMAC_SHA&);
+ HMAC_SHA& operator=(const HMAC_SHA&);
+};
+
+
+// HMAC_RMD
+class HMAC_RMD : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_RMD(const byte*, unsigned int);
+ ~HMAC_RMD();
+private:
+ struct HMAC_RMDImpl;
+ HMAC_RMDImpl* pimpl_;
+
+ HMAC_RMD(const HMAC_RMD&);
+ HMAC_RMD& operator=(const HMAC_RMD&);
+};
+
+
+// BulkCipher policy should implement encrypt, decrypt, get block size,
+// and set keys for encrypt and decrypt
+struct BulkCipher : public virtual_base {
+ virtual void encrypt(byte*, const byte*, unsigned int) = 0;
+ virtual void decrypt(byte*, const byte*, unsigned int) = 0;
+ virtual void set_encryptKey(const byte*, const byte* = 0) = 0;
+ virtual void set_decryptKey(const byte*, const byte* = 0) = 0;
+ virtual uint get_blockSize() const = 0;
+ virtual int get_keySize() const = 0;
+ virtual int get_ivSize() const = 0;
+ virtual ~BulkCipher() {}
+};
+
+
+// For use with NULL Ciphers
+struct NO_Cipher : public BulkCipher {
+ void encrypt(byte*, const byte*, unsigned int) {}
+ void decrypt(byte*, const byte*, unsigned int) {}
+ void set_encryptKey(const byte*, const byte*) {}
+ void set_decryptKey(const byte*, const byte*) {}
+ uint get_blockSize() const { return 0; }
+ int get_keySize() const { return 0; }
+ int get_ivSize() const { return 0; }
+};
+
+
+// SSLv3 and TLSv1 always use DES in CBC mode so IV is required
+class DES : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return DES_BLOCK; }
+ int get_keySize() const { return DES_KEY_SZ; }
+ int get_ivSize() const { return DES_IV_SZ; }
+ DES();
+ ~DES();
+private:
+ struct DESImpl;
+ DESImpl* pimpl_;
+
+ DES(const DES&); // hide copy
+ DES& operator=(const DES&); // & assign
+};
+
+
+// 3DES Encrypt-Decrypt-Encrypt in CBC mode
+class DES_EDE : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return DES_BLOCK; }
+ int get_keySize() const { return DES_EDE_KEY_SZ; }
+ int get_ivSize() const { return DES_IV_SZ; }
+ DES_EDE();
+ ~DES_EDE();
+private:
+ struct DES_EDEImpl;
+ DES_EDEImpl* pimpl_;
+
+ DES_EDE(const DES_EDE&); // hide copy
+ DES_EDE& operator=(const DES_EDE&); // & assign
+};
+
+
+// Alledged RC4
+class RC4 : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return 0; }
+ int get_keySize() const { return RC4_KEY_SZ; }
+ int get_ivSize() const { return 0; }
+ RC4();
+ ~RC4();
+private:
+ struct RC4Impl;
+ RC4Impl* pimpl_;
+
+ RC4(const RC4&); // hide copy
+ RC4& operator=(const RC4&); // & assign
+};
+
+
+// AES
+class AES : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return AES_BLOCK_SZ; }
+ int get_keySize() const;
+ int get_ivSize() const { return AES_IV_SZ; }
+ explicit AES(unsigned int = AES_128_KEY_SZ);
+ ~AES();
+private:
+ struct AESImpl;
+ AESImpl* pimpl_;
+
+ AES(const AES&); // hide copy
+ AES& operator=(const AES&); // & assign
+};
+
+
+// Random number generator
+class RandomPool {
+public:
+ void Fill(opaque* dst, uint sz) const;
+ RandomPool();
+ ~RandomPool();
+
+ int GetError() const;
+
+ friend class RSA;
+ friend class DSS;
+ friend class DiffieHellman;
+private:
+ struct RandomImpl;
+ RandomImpl* pimpl_;
+
+ RandomPool(const RandomPool&); // hide copy
+ RandomPool& operator=(const RandomPool&); // & assign
+};
+
+
+// Authentication policy should implement sign, and verify
+struct Auth : public virtual_base {
+ virtual void sign(byte*, const byte*, unsigned int, const RandomPool&) = 0;
+ virtual bool verify(const byte*, unsigned int, const byte*,
+ unsigned int) = 0;
+ virtual uint get_signatureLength() const = 0;
+ virtual ~Auth() {}
+};
+
+
+// For use with NULL Authentication schemes
+struct NO_Auth : public Auth {
+ void sign(byte*, const byte*, unsigned int, const RandomPool&) {}
+ bool verify(const byte*, unsigned int, const byte*, unsigned int)
+ { return true; }
+};
+
+
+// Digitial Signature Standard scheme
+class DSS : public Auth {
+public:
+ void sign(byte*, const byte*, unsigned int, const RandomPool&);
+ bool verify(const byte*, unsigned int, const byte*, unsigned int);
+ uint get_signatureLength() const;
+ DSS(const byte*, unsigned int, bool publicKey = true);
+ ~DSS();
+private:
+ struct DSSImpl;
+ DSSImpl* pimpl_;
+
+ DSS(const DSS&);
+ DSS& operator=(const DSS&);
+};
+
+
+// RSA Authentication and exchange
+class RSA : public Auth {
+public:
+ void sign(byte*, const byte*, unsigned int, const RandomPool&);
+ bool verify(const byte*, unsigned int, const byte*, unsigned int);
+ void encrypt(byte*, const byte*, unsigned int, const RandomPool&);
+ void decrypt(byte*, const byte*, unsigned int, const RandomPool&);
+ uint get_signatureLength() const;
+ uint get_cipherLength() const;
+ RSA(const byte*, unsigned int, bool publicKey = true);
+ ~RSA();
+private:
+ struct RSAImpl;
+ RSAImpl* pimpl_;
+
+ RSA(const RSA&); // hide copy
+ RSA& operator=(const RSA&); // & assing
+};
+
+
+class Integer;
+
+// Diffie-Hellman agreement
+// hide for now TODO: figure out a way to give access to C clients p and g args
+class DiffieHellman {
+public:
+ DiffieHellman(const byte*, unsigned int, const byte*, unsigned int,
+ const byte*, unsigned int, const RandomPool& random);
+ //DiffieHellman(const char*, const RandomPool&);
+ DiffieHellman(const Integer&, const Integer&, const RandomPool&);
+ ~DiffieHellman();
+
+ DiffieHellman(const DiffieHellman&);
+ DiffieHellman& operator=(const DiffieHellman&);
+
+ uint get_agreedKeyLength() const;
+ const byte* get_agreedKey() const;
+ const byte* get_publicKey() const;
+ void makeAgreement(const byte*);
+
+ void set_sizes(int&, int&, int&) const;
+ void get_parms(byte*, byte*, byte*) const;
+private:
+ struct DHImpl;
+ DHImpl* pimpl_;
+};
+
+
+// Lagrge Integer
+class Integer {
+public:
+ Integer();
+ ~Integer();
+
+ Integer(const Integer&);
+ Integer& operator=(const Integer&);
+
+ void assign(const byte*, unsigned int);
+
+ friend class DiffieHellman;
+private:
+ struct IntegerImpl;
+ IntegerImpl* pimpl_;
+};
+
+
+class x509;
+
+x509* PemToDer(const char*, CertType);
+
+
+} // naemspace
+
+#endif // yaSSL_CRYPTO_WRAPPER_HPP
diff --git a/extra/yassl/include/factory.hpp b/extra/yassl/include/factory.hpp
new file mode 100644
index 00000000000..f457188f587
--- /dev/null
+++ b/extra/yassl/include/factory.hpp
@@ -0,0 +1,105 @@
+/* factory.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* The factory header defines an Object Factory, used by SSL message and
+ * handshake types.
+ *
+ * See Desgin Pattern in GoF and Alexandrescu's chapter in Modern C++ Design,
+ * page 208
+ */
+
+
+
+#ifndef yaSSL_FACTORY_HPP
+#define yaSSL_FACTORY_HPP
+
+#include "vector.hpp"
+#include "pair.hpp"
+
+
+
+// VC60 workaround: it doesn't allow typename in some places
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ #define CPP_TYPENAME
+#else
+ #define CPP_TYPENAME typename
+#endif
+
+
+namespace yaSSL {
+
+
+// Factory uses its callback map to create objects by id,
+// returning an abstract base pointer
+template<class AbstractProduct,
+ typename IdentifierType = int,
+ typename ProductCreator = AbstractProduct* (*)()
+ >
+class Factory {
+ typedef mySTL::pair<IdentifierType, ProductCreator> CallBack;
+ typedef mySTL::vector<CallBack> CallBackVector;
+
+ CallBackVector callbacks_;
+public:
+ // pass function pointer to register all callbacks upon creation
+ explicit Factory(void (*init)(Factory<AbstractProduct, IdentifierType,
+ ProductCreator>&))
+ {
+ init(*this);
+ }
+
+ // reserve place in vector before registering, used by init funcion
+ void Reserve(size_t sz)
+ {
+ callbacks_.reserve(sz);
+ }
+
+ // register callback
+ void Register(const IdentifierType& id, ProductCreator pc)
+ {
+ callbacks_.push_back(mySTL::make_pair(id, pc));
+ }
+
+ // THE Creator, returns a new object of the proper type or 0
+ AbstractProduct* CreateObject(const IdentifierType& id) const
+ {
+ const CallBack* first = callbacks_.begin();
+ const CallBack* last = callbacks_.end();
+
+ while (first != last) {
+ if (first->first == id)
+ break;
+ ++first;
+ }
+
+ if (first == callbacks_.end())
+ return 0;
+ return (first->second)();
+ }
+private:
+ Factory(const Factory&); // hide copy
+ Factory& operator=(const Factory&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_FACTORY_HPP
diff --git a/extra/yassl/include/handshake.hpp b/extra/yassl/include/handshake.hpp
new file mode 100644
index 00000000000..6261359cd58
--- /dev/null
+++ b/extra/yassl/include/handshake.hpp
@@ -0,0 +1,72 @@
+/* handshake.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* The handshake header declares function prototypes for creating and reading
+ * the various handshake messages.
+ */
+
+
+
+#ifndef yaSSL_HANDSHAKE_HPP
+#define yaSSL_HANDSHAKE_HPP
+
+#include "yassl_types.hpp"
+
+
+namespace yaSSL {
+
+// forward decls
+class SSL;
+class Finished;
+class Data;
+class Alert;
+struct Hashes;
+
+enum BufferOutput { buffered, unbuffered };
+
+void sendClientHello(SSL&);
+void sendServerHello(SSL&, BufferOutput = buffered);
+void sendServerHelloDone(SSL&, BufferOutput = buffered);
+void sendClientKeyExchange(SSL&, BufferOutput = buffered);
+void sendServerKeyExchange(SSL&, BufferOutput = buffered);
+void sendChangeCipher(SSL&, BufferOutput = buffered);
+void sendFinished(SSL&, ConnectionEnd, BufferOutput = buffered);
+void sendCertificate(SSL&, BufferOutput = buffered);
+void sendCertificateRequest(SSL&, BufferOutput = buffered);
+void sendCertificateVerify(SSL&, BufferOutput = buffered);
+int sendData(SSL&, const void*, int);
+int sendAlert(SSL& ssl, const Alert& alert);
+
+int receiveData(SSL&, Data&);
+void processReply(SSL&);
+
+void buildFinished(SSL&, Finished&, const opaque*);
+void build_certHashes(SSL&, Hashes&);
+
+void hmac(SSL&, byte*, const byte*, uint, ContentType, bool verify = false);
+void TLS_hmac(SSL&, byte*, const byte*, uint, ContentType,
+ bool verify = false);
+void PRF(byte* digest, uint digLen, const byte* secret, uint secLen,
+ const byte* label, uint labLen, const byte* seed, uint seedLen);
+
+} // naemspace
+
+#endif // yaSSL_HANDSHAKE_HPP
diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp
new file mode 100644
index 00000000000..f5231528821
--- /dev/null
+++ b/extra/yassl/include/lock.hpp
@@ -0,0 +1,90 @@
+/* lock.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* lock.hpp provides an os specific Lock, locks mutex on entry and unlocks
+ * automatically upon exit, no-ops provided for Single Threaded
+*/
+
+#ifndef yaSSL_LOCK_HPP
+#define yaSSL_LOCK_HPP
+
+
+namespace yaSSL {
+
+
+#ifdef MULTI_THREADED
+ #ifdef _WIN32
+ #include <windows.h>
+
+ class Mutex {
+ CRITICAL_SECTION cs_;
+ public:
+ Mutex();
+ ~Mutex();
+
+ class Lock;
+ friend class Lock;
+
+ class Lock {
+ Mutex& mutex_;
+ public:
+ explicit Lock(Mutex& lm);
+ ~Lock();
+ };
+ };
+ #else // _WIN32
+ #include <pthread.h>
+
+ class Mutex {
+ pthread_mutex_t mutex_;
+ public:
+
+ Mutex();
+ ~Mutex();
+
+ class Lock;
+ friend class Lock;
+
+ class Lock {
+ Mutex& mutex_;
+ public:
+ explicit Lock(Mutex& lm);
+ ~Lock();
+ };
+ };
+
+ #endif // _WIN32
+#else // MULTI_THREADED (WE'RE SINGLE)
+
+ class Mutex {
+ public:
+ class Lock {
+ public:
+ explicit Lock(Mutex&) {}
+ };
+ };
+
+#endif // MULTI_THREADED
+
+
+
+} // namespace
+#endif // yaSSL_LOCK_HPP
diff --git a/extra/yassl/include/log.hpp b/extra/yassl/include/log.hpp
new file mode 100644
index 00000000000..c20116901ad
--- /dev/null
+++ b/extra/yassl/include/log.hpp
@@ -0,0 +1,58 @@
+/* log.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* yaSSL log interface
+ *
+ */
+
+#ifndef yaSSL_LOG_HPP
+#define yaSSL_LOG_HPP
+
+#include "socket_wrapper.hpp"
+
+#ifdef YASSL_LOG
+#include <stdio.h>
+#endif
+
+namespace yaSSL {
+
+typedef unsigned int uint;
+
+
+// Debug logger
+class Log {
+#ifdef YASSL_LOG
+ FILE* log_;
+#endif
+public:
+ explicit Log(const char* str = "yaSSL.log");
+ ~Log();
+
+ void Trace(const char*);
+ void ShowTCP(socket_t, bool ended = false);
+ void ShowData(uint, bool sent = false);
+};
+
+
+} // naemspace
+
+#endif // yaSSL_LOG_HPP
diff --git a/extra/yassl/include/openssl/crypto.h b/extra/yassl/include/openssl/crypto.h
new file mode 100644
index 00000000000..4a0c1db0df1
--- /dev/null
+++ b/extra/yassl/include/openssl/crypto.h
@@ -0,0 +1,13 @@
+/* crypto.h for openSSL */
+
+#ifndef ysSSL_crypto_h__
+#define yaSSL_crypto_h__
+
+const char* SSLeay_version(int type);
+
+#define SSLEAY_VERSION 0x0900L
+#define SSLEAY_VERSION_NUMBER SSLEAY_VERSION
+
+
+#endif /* yaSSL_crypto_h__ */
+
diff --git a/extra/yassl/include/openssl/des.h b/extra/yassl/include/openssl/des.h
new file mode 100644
index 00000000000..67be7eecfb9
--- /dev/null
+++ b/extra/yassl/include/openssl/des.h
@@ -0,0 +1 @@
+/* des.h for openssl */
diff --git a/extra/yassl/include/openssl/err.h b/extra/yassl/include/openssl/err.h
new file mode 100644
index 00000000000..054d0940509
--- /dev/null
+++ b/extra/yassl/include/openssl/err.h
@@ -0,0 +1,8 @@
+/* err.h for openssl */
+
+#ifndef ysSSL_err_h__
+#define yaSSL_err_h__
+
+
+
+#endif /* yaSSL_err_h__ */
diff --git a/extra/yassl/include/openssl/lhash.h b/extra/yassl/include/openssl/lhash.h
new file mode 100644
index 00000000000..01f8535f869
--- /dev/null
+++ b/extra/yassl/include/openssl/lhash.h
@@ -0,0 +1,2 @@
+/* lhash.h for openSSL */
+
diff --git a/extra/yassl/include/openssl/md5.h b/extra/yassl/include/openssl/md5.h
new file mode 100644
index 00000000000..a1025b92782
--- /dev/null
+++ b/extra/yassl/include/openssl/md5.h
@@ -0,0 +1 @@
+/* md5.h for openssl */
diff --git a/extra/yassl/include/openssl/opensslv.h b/extra/yassl/include/openssl/opensslv.h
new file mode 100644
index 00000000000..d932130684f
--- /dev/null
+++ b/extra/yassl/include/openssl/opensslv.h
@@ -0,0 +1,12 @@
+/* opensslv.h compatibility */
+
+#ifndef yaSSL_opensslv_h__
+#define yaSSL_opensslv_h__
+
+
+/* api version compatibility */
+#define OPENSSL_VERSION_NUMBER 0x0090700f
+
+
+#endif /* yaSSLopensslv_h__ */
+
diff --git a/extra/yassl/include/openssl/rand.h b/extra/yassl/include/openssl/rand.h
new file mode 100644
index 00000000000..df9c9020346
--- /dev/null
+++ b/extra/yassl/include/openssl/rand.h
@@ -0,0 +1,2 @@
+/* rand.h for openSSL */
+
diff --git a/extra/yassl/include/openssl/rsa.h b/extra/yassl/include/openssl/rsa.h
new file mode 100644
index 00000000000..1ab9d13b89f
--- /dev/null
+++ b/extra/yassl/include/openssl/rsa.h
@@ -0,0 +1,10 @@
+/* rsa.h for openSSL */
+
+
+#ifndef ysSSL_rsa_h__
+#define yaSSL_rsa_h__
+
+enum { RSA_F4 = 1 };
+
+
+#endif /* yaSSL_rsa_h__ */
diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h
new file mode 100644
index 00000000000..45e26fb56ee
--- /dev/null
+++ b/extra/yassl/include/openssl/ssl.h
@@ -0,0 +1,401 @@
+/* ssl.h
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* ssl.h defines openssl compatibility layer
+ *
+ */
+
+#ifndef ysSSL_openssl_h__
+#define yaSSL_openssl_h__
+
+#include <stdio.h> /* ERR_print fp */
+#include "rsa.h"
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+namespace yaSSL {
+extern "C" {
+#endif
+
+#undef X509_NAME /* wincrypt.h clash */
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+ class SSL;
+ class SSL_SESSION;
+ class SSL_METHOD;
+ class SSL_CTX;
+ class SSL_CIPHER;
+
+ class RSA;
+
+ class X509;
+ class X509_NAME;
+#else
+ typedef struct SSL SSL;
+ typedef struct SSL_SESION SSL_SESSION;
+ typedef struct SSL_METHOD SSL_METHOD;
+ typedef struct SSL_CTX SSL_CTX;
+ typedef struct SSL_CIPHER SSL_CIPHER;
+
+ typedef struct RSA RSA;
+
+ typedef struct X509 X509;
+ typedef struct X509_NAME X509_NAME;
+#endif
+
+
+/* Big Number stuff, different file? */
+typedef struct BIGNUM BIGNUM;
+
+BIGNUM *BN_bin2bn(const unsigned char*, int, BIGNUM*);
+
+
+/* Diffie-Hellman stuff, different file? */
+/* mySQL deferences to set group parameters */
+typedef struct DH {
+ BIGNUM* p;
+ BIGNUM* g;
+} DH;
+
+DH* DH_new(void);
+void DH_free(DH*);
+
+/* RSA stuff */
+
+void RSA_free(RSA*);
+RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*);
+
+
+/* X509 stuff, different file? */
+
+typedef struct X509_STORE X509_STORE;
+typedef struct X509_LOOKUP X509_LOOKUP;
+typedef struct X509_OBJECT { char c; } X509_OBJECT;
+typedef struct X509_CRL X509_CRL;
+typedef struct X509_REVOKED X509_REVOKED;
+typedef struct X509_LOOKUP_METHOD X509_LOOKUP_METHOD;
+
+
+void X509_free(X509*);
+
+
+/* bio stuff */
+typedef struct BIO BIO;
+
+/* ASN stuff */
+typedef struct ASN1_TIME ASN1_TIME;
+
+
+
+/* because mySQL dereferences to use error and current_cert, even after calling
+ * get functions for local references */
+typedef struct X509_STORE_CTX {
+ int error;
+ int error_depth;
+ X509* current_cert;
+} X509_STORE_CTX;
+
+
+
+X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX*);
+int X509_STORE_CTX_get_error(X509_STORE_CTX*);
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX*);
+
+char* X509_NAME_oneline(X509_NAME*, char*, int);
+X509_NAME* X509_get_issuer_name(X509*);
+X509_NAME* X509_get_subject_name(X509*);
+const char* X509_verify_cert_error_string(long);
+
+int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long);
+int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long);
+X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void);
+X509_LOOKUP_METHOD* X509_LOOKUP_file(void);
+
+X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*);
+X509_STORE* X509_STORE_new(void);
+int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*,
+ X509_OBJECT*);
+
+
+
+
+enum { /* X509 Constants */
+ X509_V_OK = 0,
+ X509_V_ERR_CERT_CHAIN_TOO_LONG = 1,
+ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2,
+ X509_V_ERR_CERT_NOT_YET_VALID = 3,
+ X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 4,
+ X509_V_ERR_CERT_HAS_EXPIRED = 5,
+ X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 6,
+ X509_FILETYPE_PEM = 7,
+ X509_LU_X509 = 8,
+ X509_LU_CRL = 9,
+ X509_V_ERR_CRL_SIGNATURE_FAILURE = 10,
+ X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 11,
+ X509_V_ERR_CRL_HAS_EXPIRED = 12,
+ X509_V_ERR_CERT_REVOKED = 13
+
+};
+
+
+/* Error stuff, could move to yassl_error */
+unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *);
+void ERR_print_errors_fp(FILE*);
+char* ERR_error_string(unsigned long,char*);
+void ERR_remove_state(unsigned long);
+unsigned long ERR_get_error(void);
+unsigned long ERR_peek_error(void);
+int ERR_GET_REASON(int);
+
+
+enum { /* ERR Constants */
+ ERR_TXT_STRING = 1,
+ EVP_R_BAD_DECRYPT = 2
+};
+
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD*);
+SSL* SSL_new(SSL_CTX*);
+int SSL_set_fd (SSL*, int);
+int SSL_connect(SSL*);
+int SSL_write(SSL*, const void*, int);
+int SSL_read(SSL*, void*, int);
+int SSL_accept(SSL*);
+void SSL_CTX_free(SSL_CTX*);
+void SSL_free(SSL*);
+int SSL_clear(SSL*);
+int SSL_shutdown(SSL*);
+
+void SSL_set_connect_state(SSL*);
+void SSL_set_accept_state(SSL*);
+int SSL_do_handshake(SSL*);
+
+const char* SSL_get_cipher(SSL*);
+const char* SSL_get_cipher_name(SSL*); /* uses SSL_get_cipher */
+char* SSL_get_shared_ciphers(SSL*, char*, int);
+const char* SSL_get_cipher_list(SSL*, int);
+const char* SSL_get_version(SSL*);
+const char* SSLeay_version(int);
+
+int SSL_get_error(SSL*, int);
+void SSL_load_error_strings(void);
+
+int SSL_set_session(SSL *ssl, SSL_SESSION *session);
+SSL_SESSION* SSL_get_session(SSL* ssl);
+long SSL_SESSION_set_timeout(SSL_SESSION*, long);
+X509* SSL_get_peer_certificate(SSL*);
+long SSL_get_verify_result(SSL*);
+
+
+typedef int (*VerifyCallback)(int, X509_STORE_CTX*);
+typedef int (*pem_password_cb)(char*, int, int, void*);
+
+void SSL_CTX_set_verify(SSL_CTX*, int, VerifyCallback verify_callback);
+int SSL_CTX_load_verify_locations(SSL_CTX*, const char*, const char*);
+int SSL_CTX_set_default_verify_paths(SSL_CTX*);
+int SSL_CTX_check_private_key(SSL_CTX*);
+int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
+ unsigned int);
+
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int));
+long SSL_CTX_set_options(SSL_CTX*, long);
+long SSL_CTX_set_session_cache_mode(SSL_CTX*, long);
+long SSL_CTX_set_timeout(SSL_CTX*, long);
+int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*);
+void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb);
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int);
+void SSL_CTX_set_info_callback(SSL_CTX*, void (*)());
+
+long SSL_CTX_sess_accept(SSL_CTX*);
+long SSL_CTX_sess_connect(SSL_CTX*);
+long SSL_CTX_sess_accept_good(SSL_CTX*);
+long SSL_CTX_sess_connect_good(SSL_CTX*);
+long SSL_CTX_sess_accept_renegotiate(SSL_CTX*);
+long SSL_CTX_sess_connect_renegotiate(SSL_CTX*);
+long SSL_CTX_sess_hits(SSL_CTX*);
+long SSL_CTX_sess_cb_hits(SSL_CTX*);
+long SSL_CTX_sess_cache_full(SSL_CTX*);
+long SSL_CTX_sess_misses(SSL_CTX*);
+long SSL_CTX_sess_timeouts(SSL_CTX*);
+long SSL_CTX_sess_number(SSL_CTX*);
+long SSL_CTX_sess_get_cache_size(SSL_CTX*);
+
+int SSL_CTX_get_verify_mode(SSL_CTX*);
+int SSL_get_verify_mode(SSL*);
+int SSL_CTX_get_verify_depth(SSL_CTX*);
+int SSL_get_verify_depth(SSL*);
+
+long SSL_get_default_timeout(SSL*);
+long SSL_CTX_get_session_cache_mode(SSL_CTX*);
+int SSL_session_reused(SSL*);
+
+int SSL_set_rfd(SSL*, int);
+int SSL_set_wfd(SSL*, int);
+void SSL_set_shutdown(SSL*, int);
+
+int SSL_want_read(SSL*);
+int SSL_want_write(SSL*);
+
+int SSL_pending(SSL*);
+
+
+enum { /* ssl Constants */
+ SSL_BAD_FILETYPE = -5,
+ SSL_BAD_FILE = -4,
+ SSL_NOT_IMPLEMENTED = -3,
+ SSL_UNKNOWN = -2,
+ SSL_FATAL_ERROR = -1,
+ SSL_NORMAL_SHUTDOWN = 0,
+ SSL_ERROR_NONE = 0, /* for most functions */
+ SSL_FAILURE = 0, /* for some functions */
+ SSL_SUCCESS = 1,
+
+ SSL_FILETYPE_ASN1 = 10,
+ SSL_FILETYPE_PEM = 11,
+ SSL_FILETYPE_DEFAULT = 10, /* ASN1 */
+
+ SSL_VERIFY_NONE = 0,
+ SSL_VERIFY_PEER = 1,
+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2,
+ SSL_VERIFY_CLIENT_ONCE = 4,
+
+ SSL_SESS_CACHE_OFF = 30,
+ SSL_SESS_CACHE_CLIENT = 31,
+ SSL_SESS_CACHE_SERVER = 32,
+ SSL_SESS_CACHE_BOTH = 33,
+ SSL_SESS_CACHE_NO_AUTO_CLEAR = 34,
+ SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35,
+
+ SSL_OP_MICROSOFT_SESS_ID_BUG = 50,
+ SSL_OP_NETSCAPE_CHALLENGE_BUG = 51,
+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 52,
+ SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 53,
+ SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 54,
+ SSL_OP_MSIE_SSLV2_RSA_PADDING = 55,
+ SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 56,
+ SSL_OP_TLS_D5_BUG = 57,
+ SSL_OP_TLS_BLOCK_PADDING_BUG = 58,
+ SSL_OP_TLS_ROLLBACK_BUG = 59,
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 60,
+ SSL_OP_ALL = 61,
+ SSL_OP_SINGLE_DH_USE = 62,
+ SSL_OP_EPHEMERAL_RSA = 63,
+ SSL_OP_NO_SSLv2 = 64,
+ SSL_OP_NO_SSLv3 = 65,
+ SSL_OP_NO_TLSv1 = 66,
+ SSL_OP_PKCS1_CHECK_1 = 67,
+ SSL_OP_PKCS1_CHECK_2 = 68,
+ SSL_OP_NETSCAPE_CA_DN_BUG = 69,
+ SSL_OP_NON_EXPORT_FIRST = 70,
+ SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 71,
+
+ SSL_ERROR_WANT_READ = 80,
+ SSL_ERROR_WANT_WRITE = 81,
+ SSL_ERROR_SYSCALL = 82,
+ SSL_ERROR_WANT_X509_LOOKUP = 83,
+ SSL_ERROR_ZERO_RETURN = 84,
+ SSL_ERROR_SSL = 85,
+
+ SSL_SENT_SHUTDOWN = 90,
+ SSL_RECEIVED_SHUTDOWN = 91,
+ SSL_CB_LOOP = 92,
+ SSL_ST_CONNECT = 93,
+ SSL_ST_ACCEPT = 94,
+ SSL_CB_ALERT = 95,
+ SSL_CB_READ = 96,
+ SSL_CB_HANDSHAKE_DONE = 97
+
+};
+
+
+SSL_METHOD *SSLv3_method(void);
+SSL_METHOD *SSLv3_server_method(void);
+SSL_METHOD *SSLv3_client_method(void);
+SSL_METHOD *TLSv1_server_method(void);
+SSL_METHOD *TLSv1_client_method(void);
+SSL_METHOD *SSLv23_server_method(void);
+
+int SSL_CTX_use_certificate_file(SSL_CTX*, const char*, int);
+int SSL_CTX_use_PrivateKey_file(SSL_CTX*, const char*, int);
+int SSL_CTX_set_cipher_list(SSL_CTX*, const char*);
+
+long SSL_CTX_sess_set_cache_size(SSL_CTX*, long);
+long SSL_CTX_set_tmp_dh(SSL_CTX*, DH*);
+
+void OpenSSL_add_all_algorithms(void);
+void SSLeay_add_ssl_algorithms(void);
+
+
+SSL_CIPHER* SSL_get_current_cipher(SSL*);
+char* SSL_CIPHER_description(SSL_CIPHER*, char*, int);
+
+
+char* SSL_alert_type_string_long(int);
+char* SSL_alert_desc_string_long(int);
+char* SSL_state_string_long(SSL*);
+
+
+/* EVP stuff, des and md5, different file? */
+typedef struct Digest Digest;
+typedef Digest EVP_MD;
+
+typedef struct BulkCipher BulkCipher;
+typedef BulkCipher EVP_CIPHER;
+
+typedef struct EVP_PKEY EVP_PKEY;
+
+typedef unsigned char DES_cblock[8];
+typedef const DES_cblock const_DES_cblock;
+typedef DES_cblock DES_key_schedule;
+
+
+const EVP_MD* EVP_md5(void);
+const EVP_CIPHER* EVP_des_ede3_cbc(void);
+
+typedef unsigned char opaque;
+
+int EVP_BytesToKey(const EVP_CIPHER*, const EVP_MD*, const opaque*,
+ const opaque*, int, int, opaque*, opaque*);
+
+void DES_set_key_unchecked(const_DES_cblock*, DES_key_schedule*);
+void DES_ede3_cbc_encrypt(const opaque*, opaque*, long, DES_key_schedule*,
+ DES_key_schedule*, DES_key_schedule*, DES_cblock*, int);
+
+
+/* RAND stuff */
+void RAND_screen(void);
+const char* RAND_file_name(char*, size_t);
+int RAND_write_file(const char*);
+int RAND_load_file(const char*, long);
+
+
+#define SSL_DEFAULT_CIPHER_LIST "" /* default all */
+
+
+
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+} /* namespace */
+} /* extern "C" */
+#endif
+
+
+#endif /* yaSSL_openssl_h__ */
diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp
new file mode 100644
index 00000000000..38a9ce3bd25
--- /dev/null
+++ b/extra/yassl/include/socket_wrapper.hpp
@@ -0,0 +1,95 @@
+/* socket_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* The socket wrapper header defines a Socket class that hides the differences
+ * between Berkely style sockets and Windows sockets, allowing transparent TCP
+ * access.
+ */
+
+
+#ifndef yaSSL_SOCKET_WRAPPER_HPP
+#define yaSSL_SOCKET_WRAPPER_HPP
+
+#include <assert.h>
+
+#ifdef _WIN32
+ #include <winsock2.h>
+#else
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+#endif
+
+
+namespace yaSSL {
+
+typedef unsigned int uint;
+
+#ifdef _WIN32
+ typedef SOCKET socket_t;
+#else
+ typedef int socket_t;
+ const socket_t INVALID_SOCKET = -1;
+ const int SD_RECEIVE = 0;
+ const int SD_SEND = 1;
+ const int SD_BOTH = 2;
+ const int SOCKET_ERROR = -1;
+#endif
+
+
+
+typedef unsigned char byte;
+
+
+// Wraps Windows Sockets and BSD Sockets
+class Socket {
+ socket_t socket_; // underlying socket descriptor
+public:
+ explicit Socket(socket_t s = INVALID_SOCKET);
+ ~Socket();
+
+ void set_fd(socket_t s);
+ uint get_ready() const;
+ socket_t get_fd() const;
+
+ uint send(const byte* buf, unsigned int len, int flags = 0) const;
+ uint receive(byte* buf, unsigned int len, int flags = 0) const;
+
+ void wait() const;
+
+ void closeSocket();
+ void shutDown(int how = SD_SEND);
+
+ static int get_lastError();
+ static void set_lastError(int error);
+private:
+ Socket(const Socket&); // hide copy
+ Socket& operator= (const Socket&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_SOCKET_WRAPPER_HPP
diff --git a/extra/yassl/include/timer.hpp b/extra/yassl/include/timer.hpp
new file mode 100644
index 00000000000..3025b7a0bd9
--- /dev/null
+++ b/extra/yassl/include/timer.hpp
@@ -0,0 +1,43 @@
+/* timer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* timer.hpp provides a high res and low res timers
+ *
+*/
+
+
+#ifndef yaSSL_TIMER_HPP
+#define yaSSL_TIMER_HPP
+
+namespace yaSSL {
+
+typedef double timer_d;
+typedef unsigned int uint;
+
+
+
+timer_d timer();
+uint lowResTimer();
+
+
+
+} // namespace
+#endif // yaSSL_TIMER_HPP
diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp
new file mode 100644
index 00000000000..0b06a37a635
--- /dev/null
+++ b/extra/yassl/include/yassl_error.hpp
@@ -0,0 +1,78 @@
+/* yassl_error.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* yaSSL error header defines error codes and an exception class
+ */
+
+#ifndef yaSSL_ERROR_HPP
+#define yaSSL_ERROR_HPP
+
+#include "stdexcept.hpp"
+
+
+namespace yaSSL {
+
+
+enum YasslError {
+ no_error = 0,
+
+ // 10 - 47 from AlertDescription, 0 also close_notify
+
+ range_error = 101,
+ realloc_error = 102,
+ factory_error = 103,
+ unknown_cipher = 104,
+ prefix_error = 105,
+ record_layer = 106,
+ handshake_layer = 107,
+ out_of_order = 108,
+ bad_input = 109,
+ match_error = 110,
+ no_key_file = 111,
+ verify_error = 112,
+ send_error = 113,
+ receive_error = 114,
+ certificate_error = 115
+
+ // 1000+ from TaoCrypt error.hpp
+
+};
+
+
+enum Library { yaSSL_Lib = 0, CryptoLib, SocketLib };
+
+// Base class for all yaSSL exceptions
+class Error : public mySTL::runtime_error {
+ YasslError error_;
+ Library lib_;
+public:
+ explicit Error(const char* s = "", YasslError e = no_error,
+ Library l = yaSSL_Lib);
+
+ YasslError get_number() const;
+ Library get_lib() const;
+};
+
+
+} // naemspace
+
+#endif // yaSSL_ERROR_HPP
diff --git a/extra/yassl/include/yassl_imp.hpp b/extra/yassl/include/yassl_imp.hpp
new file mode 100644
index 00000000000..3de58901f8e
--- /dev/null
+++ b/extra/yassl/include/yassl_imp.hpp
@@ -0,0 +1,742 @@
+/* yassl_imp.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* yaSSL implementation header defines all strucutres from the SSL.v3
+ * specification "draft-freier-ssl-version3-02.txt"
+ * all page citations refer to this document unless otherwise noted.
+ */
+
+
+#ifndef yaSSL_IMP_HPP
+#define yaSSL_IMP_HPP
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+#include "yassl_types.hpp"
+#include "factory.hpp"
+#include "list.hpp" // mySTL::list
+
+
+namespace yaSSL {
+
+
+class SSL; // forward decls
+class input_buffer;
+class output_buffer;
+
+
+struct ProtocolVersion {
+ uint8 major_;
+ uint8 minor_; // major and minor SSL/TLS version numbers
+
+ ProtocolVersion(uint8 maj = 3, uint8 min = 0);
+};
+
+
+// Record Layer Header for PlainText, Compressed, and CipherText
+struct RecordLayerHeader {
+ ContentType type_;
+ ProtocolVersion version_;
+ uint16 length_; // should not exceed 2^14
+};
+
+
+// base for all messages
+struct Message : public virtual_base {
+ virtual input_buffer& set(input_buffer&) =0;
+ virtual output_buffer& get(output_buffer&) const =0;
+
+ virtual void Process(input_buffer&, SSL&) =0;
+ virtual ContentType get_type() const =0;
+ virtual uint16 get_length() const =0;
+
+ virtual ~Message() {}
+};
+
+
+class ChangeCipherSpec : public Message {
+ CipherChoice type_;
+public:
+ ChangeCipherSpec();
+
+ friend input_buffer& operator>>(input_buffer&, ChangeCipherSpec&);
+ friend output_buffer& operator<<(output_buffer&, const ChangeCipherSpec&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ void Process(input_buffer&, SSL&);
+private:
+ ChangeCipherSpec(const ChangeCipherSpec&); // hide copy
+ ChangeCipherSpec& operator=(const ChangeCipherSpec&); // and assign
+};
+
+
+
+class Alert : public Message {
+ AlertLevel level_;
+ AlertDescription description_;
+public:
+ Alert() {}
+ Alert(AlertLevel al, AlertDescription ad);
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ void Process(input_buffer&, SSL&);
+
+ friend input_buffer& operator>>(input_buffer&, Alert&);
+ friend output_buffer& operator<<(output_buffer&, const Alert&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+private:
+ Alert(const Alert&); // hide copy
+ Alert& operator=(const Alert&); // and assign
+};
+
+
+class Data : public Message {
+ uint16 length_;
+ opaque* buffer_; // read buffer used by fillData input
+ const opaque* write_buffer_; // write buffer used by output operator
+public:
+ Data();
+ Data(uint16 len, opaque* b);
+ Data(uint16 len, const opaque* w);
+
+ friend output_buffer& operator<<(output_buffer&, const Data&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ const opaque* get_buffer() const;
+ void set_length(uint16 l);
+ opaque* set_buffer();
+ void Process(input_buffer&, SSL&);
+private:
+ Data(const Data&); // hide copy
+ Data& operator=(const Data&); // and assign
+};
+
+
+uint32 c24to32(const uint24); // forward form internal header
+void c32to24(uint32, uint24&);
+
+
+// HandShake header, same for each message type from page 20/21
+class HandShakeHeader : public Message {
+ HandShakeType type_;
+ uint24 length_; // length of message
+public:
+ HandShakeHeader() {}
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ HandShakeType get_handshakeType() const;
+ void Process(input_buffer&, SSL&);
+
+ void set_type(HandShakeType hst);
+ void set_length(uint32 u32);
+
+ friend input_buffer& operator>>(input_buffer&, HandShakeHeader&);
+ friend output_buffer& operator<<(output_buffer&, const HandShakeHeader&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+private:
+ HandShakeHeader(const HandShakeHeader&); // hide copy
+ HandShakeHeader& operator=(const HandShakeHeader&); // and assign
+};
+
+
+// Base Class for all handshake messages
+class HandShakeBase : public virtual_base {
+ int length_;
+public:
+ int get_length() const;
+ void set_length(int);
+
+ // for building buffer's type field
+ virtual HandShakeType get_type() const =0;
+
+ // handles dispactch of proper >>
+ virtual input_buffer& set(input_buffer& in) =0;
+ virtual output_buffer& get(output_buffer& out) const =0;
+
+ virtual void Process(input_buffer&, SSL&) =0;
+
+ virtual ~HandShakeBase() {}
+};
+
+
+struct HelloRequest : public HandShakeBase {
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer&, SSL&);
+
+ HandShakeType get_type() const;
+};
+
+
+// The Client's Hello Message from page 23
+class ClientHello : public HandShakeBase {
+ ProtocolVersion client_version_;
+ Random random_;
+ uint8 id_len_; // session id length
+ opaque session_id_[ID_LEN];
+ uint16 suite_len_; // cipher suite length
+ opaque cipher_suites_[MAX_SUITE_SZ];
+ uint8 comp_len_; // compression length
+ CompressionMethod compression_methods_;
+public:
+ friend input_buffer& operator>>(input_buffer&, ClientHello&);
+ friend output_buffer& operator<<(output_buffer&, const ClientHello&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+
+ const opaque* get_random() const;
+ friend void buildClientHello(SSL&, ClientHello&, CompressionMethod);
+ friend void ProcessOldClientHello(input_buffer& input, SSL& ssl);
+
+ ClientHello();
+ explicit ClientHello(ProtocolVersion pv);
+private:
+ ClientHello(const ClientHello&); // hide copy
+ ClientHello& operator=(const ClientHello&); // and assign
+};
+
+
+
+// The Server's Hello Message from page 24
+class ServerHello : public HandShakeBase {
+ ProtocolVersion server_version_;
+ Random random_;
+ uint8 id_len_; // session id length
+ opaque session_id_[ID_LEN];
+ opaque cipher_suite_[SUITE_LEN];
+ CompressionMethod compression_method_;
+public:
+ explicit ServerHello(ProtocolVersion pv);
+ ServerHello();
+
+ friend input_buffer& operator>>(input_buffer&, ServerHello&);
+ friend output_buffer& operator<<(output_buffer&, const ServerHello&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+
+ const opaque* get_random() const;
+ friend void buildServerHello(SSL&, ServerHello&);
+private:
+ ServerHello(const ServerHello&); // hide copy
+ ServerHello& operator=(const ServerHello&); // and assign
+};
+
+
+class x509;
+
+// Certificate could be a chain
+class Certificate : public HandShakeBase {
+ const x509* cert_;
+public:
+ Certificate();
+ explicit Certificate(const x509* cert);
+ friend output_buffer& operator<<(output_buffer&, const Certificate&);
+
+ const opaque* get_buffer() const;
+
+ // Process handles input, needs SSL
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+private:
+ Certificate(const Certificate&); // hide copy
+ Certificate& operator=(const Certificate&); // and assign
+};
+
+
+
+// RSA Public Key
+struct ServerRSAParams {
+ opaque* rsa_modulus_;
+ opaque* rsa_exponent_;
+};
+
+
+// Ephemeral Diffie-Hellman Parameters
+class ServerDHParams {
+ int pSz_;
+ int gSz_;
+ int pubSz_;
+ opaque* p_;
+ opaque* g_;
+ opaque* Ys_;
+public:
+ ServerDHParams();
+ ~ServerDHParams();
+
+ int get_pSize() const;
+ int get_gSize() const;
+ int get_pubSize() const;
+
+ const opaque* get_p() const;
+ const opaque* get_g() const;
+ const opaque* get_pub() const;
+
+ opaque* alloc_p(int sz);
+ opaque* alloc_g(int sz);
+ opaque* alloc_pub(int sz);
+private:
+ ServerDHParams(const ServerDHParams&); // hide copy
+ ServerDHParams& operator=(const ServerDHParams&); // and assign
+};
+
+
+struct ServerKeyBase : public virtual_base {
+ virtual ~ServerKeyBase() {}
+ virtual void build(SSL&) {}
+ virtual void read(SSL&, input_buffer&) {}
+ virtual int get_length() const;
+ virtual opaque* get_serverKey() const;
+};
+
+
+// Server random number for FORTEZZA KEA
+struct Fortezza_Server : public ServerKeyBase {
+ opaque r_s_[FORTEZZA_MAX];
+};
+
+
+struct SignatureBase : public virtual_base {
+ virtual ~SignatureBase() {}
+};
+
+struct anonymous_sa : public SignatureBase {};
+
+
+struct Hashes {
+ uint8 md5_[MD5_LEN];
+ uint8 sha_[SHA_LEN];
+};
+
+
+struct rsa_sa : public SignatureBase {
+ Hashes hashes_;
+};
+
+
+struct dsa_sa : public SignatureBase {
+ uint8 sha_[SHA_LEN];
+};
+
+
+// Server's Diffie-Hellman exchange
+class DH_Server : public ServerKeyBase {
+ ServerDHParams parms_;
+ opaque* signature_;
+
+ int length_; // total length of message
+ opaque* keyMessage_; // total exchange message
+public:
+ DH_Server();
+ ~DH_Server();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_serverKey() const;
+private:
+ DH_Server(const DH_Server&); // hide copy
+ DH_Server& operator=(const DH_Server&); // and assign
+};
+
+
+// Server's RSA exchange
+struct RSA_Server : public ServerKeyBase {
+ ServerRSAParams params_;
+ opaque* signature_; // signed rsa_sa hashes
+};
+
+
+class ServerKeyExchange : public HandShakeBase {
+ ServerKeyBase* server_key_;
+public:
+ explicit ServerKeyExchange(SSL&);
+ ServerKeyExchange();
+ ~ServerKeyExchange();
+
+ void createKey(SSL&);
+ void build(SSL& ssl);
+
+ const opaque* getKey() const;
+ int getKeyLength() const;
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend output_buffer& operator<<(output_buffer&, const ServerKeyExchange&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+private:
+ ServerKeyExchange(const ServerKeyExchange&); // hide copy
+ ServerKeyExchange& operator=(const ServerKeyExchange&); // and assign
+};
+
+
+
+class CertificateRequest : public HandShakeBase {
+ ClientCertificateType certificate_types_[CERT_TYPES];
+ int typeTotal_;
+ mySTL::list<DistinguishedName> certificate_authorities_;
+public:
+ CertificateRequest();
+ ~CertificateRequest();
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend input_buffer& operator>>(input_buffer&, CertificateRequest&);
+ friend output_buffer& operator<<(output_buffer&,
+ const CertificateRequest&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+
+ void Build();
+private:
+ CertificateRequest(const CertificateRequest&); // hide copy
+ CertificateRequest& operator=(const CertificateRequest&); // and assign
+};
+
+
+struct ServerHelloDone : public HandShakeBase {
+ ServerHelloDone();
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer& input, SSL& ssl);
+
+ HandShakeType get_type() const;
+};
+
+
+struct PreMasterSecret {
+ opaque random_[SECRET_LEN]; // first two bytes Protocol Version
+};
+
+
+struct ClientKeyBase : public virtual_base {
+ virtual ~ClientKeyBase() {}
+ virtual void build(SSL&) {}
+ virtual void read(SSL&, input_buffer&) {}
+ virtual int get_length() const;
+ virtual opaque* get_clientKey() const;
+};
+
+
+class EncryptedPreMasterSecret : public ClientKeyBase {
+ opaque* secret_;
+ int length_;
+public:
+ EncryptedPreMasterSecret();
+ ~EncryptedPreMasterSecret();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_clientKey() const;
+ void alloc(int sz);
+private:
+ // hide copy and assign
+ EncryptedPreMasterSecret(const EncryptedPreMasterSecret&);
+ EncryptedPreMasterSecret& operator=(const EncryptedPreMasterSecret&);
+};
+
+
+// Fortezza Key Parameters from page 29
+// hard code lengths cause only used here
+struct FortezzaKeys : public ClientKeyBase {
+ opaque y_c_ [128]; // client's Yc, public value
+ opaque r_c_ [128]; // client's Rc
+ opaque y_signature_ [40]; // DSS signed public key
+ opaque wrapped_client_write_key_ [12]; // wrapped by the TEK
+ opaque wrapped_server_write_key_ [12]; // wrapped by the TEK
+ opaque client_write_iv_ [24];
+ opaque server_write_iv_ [24];
+ opaque master_secret_iv_ [24]; // IV used to encrypt preMaster
+ opaque encrypted_preMasterSecret_[48]; // random & crypted by the TEK
+};
+
+
+
+// Diffie-Hellman public key from page 40/41
+class ClientDiffieHellmanPublic : public ClientKeyBase {
+ PublicValueEncoding public_value_encoding_;
+ int length_; // includes two byte length for message
+ opaque* Yc_; // length + Yc_
+ // dh_Yc only if explicit, otherwise sent in certificate
+ enum { KEY_OFFSET = 2 };
+public:
+ ClientDiffieHellmanPublic();
+ ~ClientDiffieHellmanPublic();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_clientKey() const;
+ void alloc(int sz, bool offset = false);
+private:
+ // hide copy and assign
+ ClientDiffieHellmanPublic(const ClientDiffieHellmanPublic&);
+ ClientDiffieHellmanPublic& operator=(const ClientDiffieHellmanPublic&);
+};
+
+
+class ClientKeyExchange : public HandShakeBase {
+ ClientKeyBase* client_key_;
+public:
+ explicit ClientKeyExchange(SSL& ssl);
+ ClientKeyExchange();
+ ~ClientKeyExchange();
+
+ void createKey(SSL&);
+ void build(SSL& ssl);
+
+ const opaque* getKey() const;
+ int getKeyLength() const;
+
+ friend output_buffer& operator<<(output_buffer&, const ClientKeyExchange&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+private:
+ ClientKeyExchange(const ClientKeyExchange&); // hide copy
+ ClientKeyExchange& operator=(const ClientKeyExchange&); // and assign
+};
+
+
+class CertificateVerify : public HandShakeBase {
+ Hashes hashes_;
+ byte* signature_; // owns
+public:
+ CertificateVerify();
+ ~CertificateVerify();
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend input_buffer& operator>>(input_buffer&, CertificateVerify&);
+ friend output_buffer& operator<<(output_buffer&, const CertificateVerify&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+
+ void Build(SSL&);
+private:
+ CertificateVerify(const CertificateVerify&); // hide copy
+ CertificateVerify& operator=(const CertificateVerify&); // and assign
+};
+
+
+class Finished : public HandShakeBase {
+ Hashes hashes_;
+public:
+ Finished();
+
+ uint8* set_md5();
+ uint8* set_sha();
+
+ friend input_buffer& operator>>(input_buffer&, Finished&);
+ friend output_buffer& operator<<(output_buffer&, const Finished&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer&, SSL&);
+
+ HandShakeType get_type() const;
+private:
+ Finished(const Finished&); // hide copy
+ Finished& operator=(const Finished&); // and assign
+};
+
+
+class RandomPool; // forward for connection
+
+
+// SSL Connection defined on page 11
+struct Connection {
+ opaque *pre_master_secret_;
+ opaque master_secret_[SECRET_LEN];
+ opaque client_random_[RAN_LEN];
+ opaque server_random_[RAN_LEN];
+ opaque sessionID_[ID_LEN];
+ opaque client_write_MAC_secret_[SHA_LEN]; // sha is max size
+ opaque server_write_MAC_secret_[SHA_LEN];
+ opaque client_write_key_[AES_256_KEY_SZ]; // aes 256bit is max sz
+ opaque server_write_key_[AES_256_KEY_SZ];
+ opaque client_write_IV_[AES_IV_SZ]; // aes is max size
+ opaque server_write_IV_[AES_IV_SZ];
+ uint32 sequence_number_;
+ uint32 peer_sequence_number_;
+ uint32 pre_secret_len_; // pre master length
+ bool send_server_key_; // server key exchange?
+ bool master_clean_; // master secret clean?
+ bool TLS_; // TLSv1 or greater
+ ProtocolVersion version_;
+ RandomPool& random_;
+
+ Connection(ProtocolVersion v, RandomPool& ran);
+ ~Connection();
+
+ void AllocPreSecret(uint sz);
+ void CleanPreMaster();
+ void CleanMaster();
+ void TurnOffTLS();
+private:
+ Connection(const Connection&); // hide copy
+ Connection& operator=(const Connection&); // and assign
+};
+
+
+struct Ciphers; // forward
+
+
+// TLSv1 Security Spec, defined on page 56 of RFC 2246
+struct Parameters {
+ ConnectionEnd entity_;
+ BulkCipherAlgorithm bulk_cipher_algorithm_;
+ CipherType cipher_type_;
+ uint8 key_size_;
+ uint8 iv_size_;
+ IsExportable is_exportable_;
+ MACAlgorithm mac_algorithm_;
+ uint8 hash_size_;
+ CompressionMethod compression_algorithm_;
+ KeyExchangeAlgorithm kea_; // yassl additions
+ SignatureAlgorithm sig_algo_; // signature auth type
+ SignatureAlgorithm verify_algo_; // cert verify auth type
+ bool pending_;
+ bool resumable_; // new conns by session
+ uint16 encrypt_size_; // current msg encrypt sz
+ Cipher suite_[SUITE_LEN]; // choosen suite
+ uint8 suites_size_;
+ Cipher suites_[MAX_SUITE_SZ];
+ char cipher_name_[MAX_SUITE_NAME];
+ char cipher_list_[MAX_CIPHER_LIST];
+
+ Parameters(ConnectionEnd, const Ciphers&, ProtocolVersion);
+
+ void SetSuites(ProtocolVersion pv);
+ void SetCipherNames();
+private:
+ Parameters(const Parameters&); // hide copy
+ Parameters& operator=(const Parameters&); // and assing
+};
+
+
+input_buffer& operator>>(input_buffer&, RecordLayerHeader&);
+output_buffer& operator<<(output_buffer&, const RecordLayerHeader&);
+
+input_buffer& operator>>(input_buffer&, Message&);
+output_buffer& operator<<(output_buffer&, const Message&);
+
+input_buffer& operator>>(input_buffer&, HandShakeBase&);
+output_buffer& operator<<(output_buffer&, const HandShakeBase&);
+
+
+// Message Factory definition
+// uses the ContentType enumeration for unique id
+typedef Factory<Message> MessageFactory;
+void InitMessageFactory(MessageFactory&); // registers derived classes
+
+// HandShake Factory definition
+// uses the HandShakeType enumeration for unique id
+typedef Factory<HandShakeBase> HandShakeFactory;
+void InitHandShakeFactory(HandShakeFactory&); // registers derived classes
+
+// ServerKey Factory definition
+// uses KeyExchangeAlgorithm enumeration for unique id
+typedef Factory<ServerKeyBase> ServerKeyFactory;
+void InitServerKeyFactory(ServerKeyFactory&);
+
+// ClientKey Factory definition
+// uses KeyExchangeAlgorithm enumeration for unique id
+typedef Factory<ClientKeyBase> ClientKeyFactory;
+void InitClientKeyFactory(ClientKeyFactory&);
+
+
+// Message Creators
+Message* CreateHandShake();
+Message* CreateCipherSpec();
+Message* CreateAlert();
+Message* CreateData();
+
+
+// HandShake Creators
+HandShakeBase* CreateCertificate();
+HandShakeBase* CreateHelloRequest();
+HandShakeBase* CreateClientHello();
+HandShakeBase* CreateServerHello();
+HandShakeBase* CreateServerKeyExchange();
+HandShakeBase* CreateCertificateRequest();
+HandShakeBase* CreateServerHelloDone();
+HandShakeBase* CreateClientKeyExchange();
+HandShakeBase* CreateCertificateVerify();
+HandShakeBase* CreateFinished();
+
+
+// ServerKey Exchange Creators
+ServerKeyBase* CreateRSAServerKEA();
+ServerKeyBase* CreateDHServerKEA();
+ServerKeyBase* CreateFortezzaServerKEA();
+
+// ClientKey Exchange Creators
+ClientKeyBase* CreateRSAClient();
+ClientKeyBase* CreateDHClient();
+ClientKeyBase* CreateFortezzaClient();
+
+
+
+} // naemspace
+
+#endif // yaSSL_IMP_HPP
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
new file mode 100644
index 00000000000..60a78a3970e
--- /dev/null
+++ b/extra/yassl/include/yassl_int.hpp
@@ -0,0 +1,550 @@
+/* yassl_int.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* yaSSL internal header defines SSL supporting types not specified in the
+ * draft along with type conversion functions and openssl compatibility
+ */
+
+
+#ifndef yaSSL_INT_HPP
+#define yaSSL_INT_HPP
+
+#include "yassl_imp.hpp"
+#include "yassl_error.hpp"
+#include "crypto_wrapper.hpp"
+#include "cert_wrapper.hpp"
+#include "log.hpp"
+#include "lock.hpp"
+
+
+namespace yaSSL {
+
+
+// State Machine for Record Layer Protocol
+enum RecordLayerState {
+ recordNotReady = 0, // fatal error, no more processing
+ recordReady
+};
+
+
+// State Machine for HandShake Protocol
+enum HandShakeState {
+ handShakeNotReady = 0, // fatal error, no more processing
+ preHandshake, // initial state
+ inHandshake, // handshake started
+ handShakeReady // handshake done
+};
+
+
+// client input HandShake state, use if HandShakeState == inHandShake
+enum ClientState {
+ serverNull = 0,
+ serverHelloComplete,
+ serverCertComplete,
+ serverKeyExchangeComplete,
+ serverHelloDoneComplete,
+ serverFinishedComplete
+};
+
+
+// server input HandShake state, use if HandShakeState == inHandShake
+enum ServerState {
+ clientNull = 0,
+ clientHelloComplete,
+ clientKeyExchangeComplete,
+ clientFinishedComplete
+};
+
+
+// combines all states
+class States {
+ enum {MAX_ERROR_SZ = 80 };
+
+ RecordLayerState recordLayer_;
+ HandShakeState handshakeLayer_;
+ ClientState clientState_;
+ ServerState serverState_;
+ char errorString_[MAX_ERROR_SZ];
+ YasslError what_;
+public:
+ States();
+
+ const RecordLayerState& getRecord() const;
+ const HandShakeState& getHandShake() const;
+ const ClientState& getClient() const;
+ const ServerState& getServer() const;
+ const char* getString() const;
+ YasslError What() const;
+
+ RecordLayerState& useRecord();
+ HandShakeState& useHandShake();
+ ClientState& useClient();
+ ServerState& useServer();
+ char* useString();
+ void SetError(YasslError);
+private:
+ States(const States&); // hide copy
+ States& operator=(const States&); // and assign
+};
+
+
+// holds all factories
+class sslFactory {
+ MessageFactory messageFactory_; // creates new messages by type
+ HandShakeFactory handShakeFactory_; // creates new handshake types
+ ServerKeyFactory serverKeyFactory_; // creates new server key types
+ ClientKeyFactory clientKeyFactory_; // creates new client key types
+
+ sslFactory(); // only GetSSL_Factory creates
+public:
+ const MessageFactory& getMessage() const;
+ const HandShakeFactory& getHandShake() const;
+ const ServerKeyFactory& getServerKey() const;
+ const ClientKeyFactory& getClientKey() const;
+
+ friend sslFactory& GetSSL_Factory(); // singleton creator
+private:
+ static sslFactory instance_;
+
+ sslFactory(const sslFactory&); // hide copy
+ sslFactory& operator=(const sslFactory&); // and assign
+};
+
+
+#undef X509_NAME // wincrypt.h clash
+
+// openSSL X509 names
+class X509_NAME {
+ char* name_;
+public:
+ X509_NAME(const char*, size_t sz);
+ ~X509_NAME();
+
+ char* GetName();
+private:
+ X509_NAME(const X509_NAME&); // hide copy
+ X509_NAME& operator=(const X509_NAME&); // and assign
+};
+
+
+// openSSL X509
+class X509 {
+ X509_NAME issuer_;
+ X509_NAME subject_;
+public:
+ X509(const char* i, size_t, const char* s, size_t);
+ ~X509() {}
+
+ X509_NAME* GetIssuer();
+ X509_NAME* GetSubject();
+private:
+ X509(const X509&); // hide copy
+ X509& operator=(const X509&); // and assign
+};
+
+
+// openSSL bignum
+struct BIGNUM {
+ /*
+ gcc 2.96 fix: because of two Integer classes (yaSSL::Integer and
+ TaoCrypt::Integer), we need to explicitly state the namespace
+ here to let gcc 2.96 deduce the correct type.
+ */
+ yaSSL::Integer int_;
+ void assign(const byte* b, uint s) { int_.assign(b,s); }
+};
+
+
+// openSSL session
+class SSL_SESSION {
+ opaque sessionID_[ID_LEN];
+ opaque master_secret_[SECRET_LEN];
+ Cipher suite_[SUITE_LEN];
+ uint bornOn_; // create time in seconds
+ uint timeout_; // timeout in seconds
+ RandomPool& random_; // will clean master secret
+public:
+ explicit SSL_SESSION(RandomPool&);
+ SSL_SESSION(const SSL&, RandomPool&);
+ ~SSL_SESSION();
+
+ const opaque* GetID() const;
+ const opaque* GetSecret() const;
+ const Cipher* GetSuite() const;
+ uint GetBornOn() const;
+ uint GetTimeOut() const;
+ void SetTimeOut(uint);
+
+ SSL_SESSION& operator=(const SSL_SESSION&); // allow assign for resumption
+private:
+ SSL_SESSION(const SSL_SESSION&); // hide copy
+};
+
+
+// holds all sessions
+class Sessions {
+ mySTL::list<SSL_SESSION*> list_;
+ RandomPool random_; // for session cleaning
+ Mutex mutex_; // no-op for single threaded
+
+ Sessions() {} // only GetSessions can create
+public:
+ SSL_SESSION* lookup(const opaque*, SSL_SESSION* copy = 0);
+ void add(const SSL&);
+ void remove(const opaque*);
+
+ ~Sessions();
+
+ friend Sessions& GetSessions(); // singleton creator
+private:
+ static Sessions instance_;
+
+ Sessions(const Sessions&); // hide copy
+ Sessions& operator=(const Sessions&); // and assign
+};
+
+
+Sessions& GetSessions(); // forward singletons
+sslFactory& GetSSL_Factory();
+
+
+// openSSL method and context types
+class SSL_METHOD {
+ ProtocolVersion version_;
+ ConnectionEnd side_;
+ bool verifyPeer_;
+ bool failNoCert_;
+public:
+ explicit SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv);
+
+ ProtocolVersion getVersion() const;
+ ConnectionEnd getSide() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+
+ bool verifyPeer() const;
+ bool failNoCert() const;
+private:
+ SSL_METHOD(const SSL_METHOD&); // hide copy
+ SSL_METHOD& operator=(const SSL_METHOD&); // and assign
+};
+
+
+struct Ciphers {
+ bool setSuites_; // user set suites from default
+ byte suites_[MAX_SUITE_SZ]; // new suites
+ int suiteSz_; // suite length in bytes
+
+ Ciphers() : setSuites_(false), suiteSz_(0) {}
+};
+
+
+struct DH; // forward
+
+
+// save for SSL construction
+struct DH_Parms {
+ Integer p_;
+ Integer g_;
+ bool set_; // if set by user
+
+ DH_Parms() : set_(false) {}
+};
+
+
+enum StatsField {
+ Accept, Connect, AcceptGood, ConnectGood, AcceptRenegotiate,
+ ConnectRenegotiate, Hits, CbHits, CacheFull, Misses, Timeouts, Number,
+ GetCacheSize, VerifyMode, VerifyDepth
+};
+
+
+// SSL stats
+struct Stats {
+ long accept_;
+ long connect_;
+ long acceptGood_;
+ long connectGood_;
+ long acceptRenegotiate_;
+ long connectRenegotiate_;
+
+ long hits_;
+ long cbHits_;
+ long cacheFull_;
+ long misses_;
+ long timeouts_;
+ long number_;
+ long getCacheSize_;
+
+ int verifyMode_;
+ int verifyDepth_;
+public:
+ Stats() : accept_(0), connect_(0), acceptGood_(0), connectGood_(0),
+ acceptRenegotiate_(0), connectRenegotiate_(0), hits_(0), cbHits_(0),
+ cacheFull_(0), misses_(0), timeouts_(0), number_(0), getCacheSize_(0),
+ verifyMode_(0), verifyDepth_(0)
+ {}
+private:
+ Stats(const Stats&); // hide copy
+ Stats& operator=(const Stats&); // and assign
+};
+
+
+// the SSL context
+class SSL_CTX {
+public:
+ typedef mySTL::list<x509*> CertList;
+private:
+ SSL_METHOD* method_;
+ x509* certificate_;
+ x509* privateKey_;
+ CertList caList_;
+ Ciphers ciphers_;
+ DH_Parms dhParms_;
+ Stats stats_;
+ Mutex mutex_; // for Stats
+public:
+ explicit SSL_CTX(SSL_METHOD* meth);
+ ~SSL_CTX();
+
+ const x509* getCert() const;
+ const x509* getKey() const;
+ const SSL_METHOD* getMethod() const;
+ const Ciphers& GetCiphers() const;
+ const DH_Parms& GetDH_Parms() const;
+ const Stats& GetStats() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+ bool SetCipherList(const char*);
+ bool SetDH(const DH&);
+
+ void IncrementStats(StatsField);
+ void AddCA(x509* ca);
+ const CertList& GetCA_List() const;
+
+ friend int read_file(SSL_CTX*, const char*, int, CertType);
+private:
+ SSL_CTX(const SSL_CTX&); // hide copy
+ SSL_CTX& operator=(const SSL_CTX&); // and assign
+};
+
+
+// holds all cryptographic types
+class Crypto {
+ Digest* digest_; // agreed upon digest
+ BulkCipher* cipher_; // agreed upon cipher
+ DiffieHellman* dh_; // dh parms
+ RandomPool random_; // random number generator
+ CertManager cert_; // manages certificates
+public:
+ explicit Crypto();
+ ~Crypto();
+
+ const Digest& get_digest() const;
+ const BulkCipher& get_cipher() const;
+ const DiffieHellman& get_dh() const;
+ const RandomPool& get_random() const;
+ const CertManager& get_certManager() const;
+
+ Digest& use_digest();
+ BulkCipher& use_cipher();
+ DiffieHellman& use_dh();
+ RandomPool& use_random();
+ CertManager& use_certManager();
+
+ void SetDH(DiffieHellman*);
+ void SetDH(const DH_Parms&);
+ void setDigest(Digest*);
+ void setCipher(BulkCipher*);
+
+ bool DhSet();
+private:
+ Crypto(const Crypto&); // hide copy
+ Crypto& operator=(const Crypto&); // and assign
+};
+
+
+// holds all handshake and verify hashes
+class sslHashes {
+ MD5 md5HandShake_; // md5 handshake hash
+ SHA shaHandShake_; // sha handshake hash
+ Finished verify_; // peer's verify hash
+ Hashes certVerify_; // peer's cert verify hash
+public:
+ sslHashes() {}
+
+ const MD5& get_MD5() const;
+ const SHA& get_SHA() const;
+ const Finished& get_verify() const;
+ const Hashes& get_certVerify() const;
+
+ MD5& use_MD5();
+ SHA& use_SHA();
+ Finished& use_verify();
+ Hashes& use_certVerify();
+private:
+ sslHashes(const sslHashes&); // hide copy
+ sslHashes& operator=(const sslHashes&); // and assign
+};
+
+
+// holds input and output buffers
+class Buffers {
+ typedef mySTL::list<input_buffer*> inputList;
+ typedef mySTL::list<output_buffer*> outputList;
+
+ inputList dataList_; // list of users app data / handshake
+ outputList handShakeList_; // buffered handshake msgs
+public:
+ Buffers() {}
+ ~Buffers();
+
+ const inputList& getData() const;
+ const outputList& getHandShake() const;
+
+ inputList& useData();
+ outputList& useHandShake();
+private:
+ Buffers(const Buffers&); // hide copy
+ Buffers& operator=(const Buffers&); // and assign
+};
+
+
+// wraps security parameters
+class Security {
+ Connection conn_; // connection information
+ Parameters parms_; // may be pending
+ SSL_SESSION resumeSession_; // if resuming
+ SSL_CTX* ctx_; // context used to init
+ bool resuming_; // trying to resume
+public:
+ Security(ProtocolVersion, RandomPool&, ConnectionEnd, const Ciphers&,
+ SSL_CTX*);
+
+ const SSL_CTX* GetContext() const;
+ const Connection& get_connection() const;
+ const Parameters& get_parms() const;
+ const SSL_SESSION& get_resume() const;
+ bool get_resuming() const;
+
+ Connection& use_connection();
+ Parameters& use_parms();
+ SSL_SESSION& use_resume();
+
+ void set_resuming(bool b);
+private:
+ Security(const Security&); // hide copy
+ Security& operator=(const Security&); // and assign
+};
+
+
+// THE SSL type
+class SSL {
+ Crypto crypto_; // agreed crypto agents
+ Security secure_; // Connection and Session parms
+ States states_; // Record and HandShake states
+ sslHashes hashes_; // handshake, finished hashes
+ Socket socket_; // socket wrapper
+ Buffers buffers_; // buffered handshakes and data
+ Log log_; // logger
+public:
+ SSL(SSL_CTX* ctx);
+
+ // gets and uses
+ const Crypto& getCrypto() const;
+ const Security& getSecurity() const;
+ const States& getStates() const;
+ const sslHashes& getHashes() const;
+ const sslFactory& getFactory() const;
+ const Socket& getSocket() const;
+ YasslError GetError() const;
+
+ Crypto& useCrypto();
+ Security& useSecurity();
+ States& useStates();
+ sslHashes& useHashes();
+ Socket& useSocket();
+ Log& useLog();
+
+ // sets
+ void set_pending(Cipher suite);
+ void set_random(const opaque*, ConnectionEnd);
+ void set_sessionID(const opaque*);
+ void set_session(SSL_SESSION*);
+ void set_preMaster(const opaque*, uint);
+ void set_masterSecret(const opaque*);
+ void SetError(YasslError);
+
+ // helpers
+ bool isTLS() const;
+ void order_error();
+ void makeMasterSecret();
+ void makeTLSMasterSecret();
+ void addData(input_buffer* data);
+ void fillData(Data&);
+ void addBuffer(output_buffer* b);
+ void flushBuffer();
+ void verifyState(const RecordLayerHeader&);
+ void verifyState(const HandShakeHeader&);
+ void verifyState(ClientState);
+ void verifyState(ServerState);
+ void verfiyHandShakeComplete();
+ void matchSuite(const opaque*, uint length);
+ void deriveKeys();
+ void deriveTLSKeys();
+ void Send(const byte*, uint);
+
+ uint bufferedData();
+ uint get_SEQIncrement(bool);
+
+ const byte* get_macSecret(bool);
+private:
+ void storeKeys(const opaque*);
+ void setKeys();
+ void verifyClientState(HandShakeType);
+ void verifyServerState(HandShakeType);
+
+ SSL(const SSL&); // hide copy
+ const SSL& operator=(const SSL&); // and assign
+};
+
+
+
+// conversion functions
+void c32to24(uint32, uint24&);
+void c24to32(const uint24, uint32&);
+
+uint32 c24to32(const uint24);
+
+void ato16(const opaque*, uint16&);
+void ato24(const opaque*, uint24&);
+
+void c16toa(uint16, opaque*);
+void c24toa(const uint24, opaque*);
+void c32toa(uint32 u32, opaque*);
+
+
+} // naemspace
+
+#endif // yaSSL_INT_HPP
diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp
new file mode 100644
index 00000000000..ec9e6fb7ceb
--- /dev/null
+++ b/extra/yassl/include/yassl_types.hpp
@@ -0,0 +1,460 @@
+/* yassl_types.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* yaSSL types header defines all constants, enums, and typedefs
+ * from the SSL.v3 specification "draft-freier-ssl-version3-02.txt"
+ */
+
+
+#ifndef yaSSL_TYPES_HPP
+#define yaSSL_TYPES_HPP
+
+#include <stddef.h>
+#include <assert.h>
+#include "type_traits.hpp"
+
+
+namespace yaSSL {
+
+// library allocation
+struct new_t {}; // yaSSL New type
+extern new_t ys; // pass in parameter
+
+} // namespace yaSSL
+
+void* operator new (size_t, yaSSL::new_t);
+void* operator new[](size_t, yaSSL::new_t);
+
+void operator delete (void*, yaSSL::new_t);
+void operator delete[](void*, yaSSL::new_t);
+
+
+namespace yaSSL {
+
+
+template<typename T>
+void ysDelete(T* ptr)
+{
+ if (ptr) ptr->~T();
+ ::operator delete(ptr, yaSSL::ys);
+}
+
+template<typename T>
+void ysArrayDelete(T* ptr)
+{
+ // can't do array placement destruction since not tracking size in
+ // allocation, only allow builtins to use array placement since they
+ // don't need destructors called
+ typedef char builtin[TaoCrypt::IsFundamentalType<T>::Yes ? 1 : -1];
+ (void)sizeof(builtin);
+
+ ::operator delete[](ptr, yaSSL::ys);
+}
+
+
+// to resolve compiler generated operator delete on base classes with
+// virtual destructors (when on stack), make sure doesn't get called
+class virtual_base {
+public:
+ static void operator delete(void*) { assert(0); }
+};
+
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef uint8 uint24[3];
+typedef uint32 uint64[2];
+
+typedef uint8 opaque;
+typedef opaque byte;
+
+typedef unsigned int uint;
+
+
+// all length constants in bytes
+const int ID_LEN = 32; // session id length
+const int SUITE_LEN = 2; // cipher suite length
+const int SECRET_LEN = 48; // pre RSA and all master secret length
+const int MASTER_ROUNDS = 3; // master secret derivation rounds
+const int RAN_LEN = 32; // client and server random length
+const int MAC_BLOCK_SZ = 64; // MAC block size, & padding
+const int MD5_LEN = 16; // MD5 digest length
+const int SHA_LEN = 20; // SHA digest length
+const int RMD_LEN = 20; // RIPEMD-160 digest length
+const int PREFIX = 3; // up to 3 prefix letters for secret rounds
+const int KEY_PREFIX = 7; // up to 7 prefix letters for key rounds
+const int FORTEZZA_MAX = 128; // Maximum Fortezza Key length
+const int MAX_SUITE_SZ = 64; // 32 max suites * sizeof(suite)
+const int MAX_SUITE_NAME = 48; // max length of suite name
+const int MAX_CIPHER_LIST = 512; // max length of cipher list names
+const int SIZEOF_ENUM = 1; // SSL considers an enum 1 byte, not 4
+const int SIZEOF_SENDER = 4; // Sender constant, for finished generation
+const int PAD_MD5 = 48; // pad length 1 and 2 for md5 finished
+const int PAD_SHA = 40; // should be 44, specd wrong by netscape
+const int PAD_RMD = 44; // pad length for RIPEMD-160, some use 40??
+const int CERT_HEADER = 3; // always use 3 bytes for certificate
+const int CERT_TYPES = 7; // certificate request types
+const int REQUEST_HEADER = 2; // request uses 2 bytes
+const int VERIFY_HEADER = 2; // verify length field
+const int MIN_CERT_TYPES = 1; // minimum certificate request types
+const int MIN_DIS_NAMES = 3; // minimum distinguished names
+const int MIN_DIS_SIZE = 1; // minimum distinguished name size
+const int RECORD_HEADER = 5; // type + version + length(2)
+const int HANDSHAKE_HEADER = 4; // type + length(3)
+const int FINISHED_SZ = MD5_LEN + SHA_LEN; // sizeof finished data
+const int TLS_FINISHED_SZ = 12; // TLS verify data size
+const int SEQ_SZ = 8; // 64 bit sequence number
+const int LENGTH_SZ = 2; // length field for HMAC, data only
+const int VERSION_SZ = SIZEOF_ENUM * 2; // SSL/TLS length of version
+const int DES_KEY_SZ = 8; // DES Key length
+const int DES_EDE_KEY_SZ = 24; // DES EDE Key length
+const int DES_BLOCK = 8; // DES is always fixed block size 8
+const int DES_IV_SZ = DES_BLOCK; // Init Vector length for DES
+const int RC4_KEY_SZ = 16; // RC4 Key length
+const int AES_128_KEY_SZ = 16; // AES 128bit Key length
+const int AES_256_KEY_SZ = 32; // AES 256bit Key length
+const int AES_BLOCK_SZ = 16; // AES 128bit block size, rfc 3268
+const int AES_IV_SZ = AES_BLOCK_SZ; // AES Init Vector length
+const int DSS_SIG_SZ = 40; // two 20 byte high byte first Integers
+const int DSS_ENCODED_EXTRA = 6; // seqID + len(1) + (intID + len(1)) * 2
+const int EVP_SALT_SZ = 8;
+const int MASTER_LABEL_SZ = 13; // TLS master secret label size
+const int KEY_LABEL_SZ = 13; // TLS key block expansion size
+const int FINISHED_LABEL_SZ = 15; // TLS finished lable length
+const int SEED_LEN = RAN_LEN * 2; // TLS seed, client + server random
+const int DEFAULT_TIMEOUT = 500; // Default Session timeout in seconds
+const int MAX_RECORD_SIZE = 16384; // 2^14, max size by standard
+
+
+typedef uint8 Cipher; // first byte is always 0x00 for SSLv3 & TLS
+
+typedef opaque Random[RAN_LEN];
+
+typedef opaque* DistinguishedName;
+
+typedef bool IsExportable;
+
+
+enum CompressionMethod { no_compression = 0 };
+
+enum CipherType { stream, block };
+
+enum CipherChoice { change_cipher_spec_choice = 1 };
+
+enum PublicValueEncoding { implicit_encoding, explicit_encoding };
+
+enum ConnectionEnd { server_end, client_end };
+
+enum AlertLevel { warning = 1, fatal = 2 };
+
+
+
+// Record Layer Header identifier from page 12
+enum ContentType {
+ no_type = 0,
+ change_cipher_spec = 20,
+ alert = 21,
+ handshake = 22,
+ application_data = 23
+};
+
+
+// HandShake Layer Header identifier from page 20
+enum HandShakeType {
+ no_shake = -1,
+ hello_request = 0,
+ client_hello = 1,
+ server_hello = 2,
+ certificate = 11,
+ server_key_exchange = 12,
+ certificate_request = 13,
+ server_hello_done = 14,
+ certificate_verify = 15,
+ client_key_exchange = 16,
+ finished = 20
+};
+
+
+// Valid Alert types from page 16/17
+enum AlertDescription {
+ close_notify = 0,
+ unexpected_message = 10,
+ bad_record_mac = 20,
+ decompression_failure = 30,
+ handshake_failure = 40,
+ no_certificate = 41,
+ bad_certificate = 42,
+ unsupported_certificate = 43,
+ certificate_revoked = 44,
+ certificate_expired = 45,
+ certificate_unknown = 46,
+ illegal_parameter = 47
+};
+
+
+// Supported Key Exchange Protocols
+enum KeyExchangeAlgorithm {
+ no_kea = 0,
+ rsa_kea,
+ diffie_hellman_kea,
+ fortezza_kea
+};
+
+
+// Supported Authentication Schemes
+enum SignatureAlgorithm {
+ anonymous_sa_algo = 0,
+ rsa_sa_algo,
+ dsa_sa_algo
+};
+
+
+// Valid client certificate request types from page 27
+enum ClientCertificateType {
+ rsa_sign = 1,
+ dss_sign = 2,
+ rsa_fixed_dh = 3,
+ dss_fixed_dh = 4,
+ rsa_ephemeral_dh = 5,
+ dss_ephemeral_dh = 6,
+ fortezza_kea_cert = 20
+};
+
+
+// Supported Ciphers from page 43
+enum BulkCipherAlgorithm {
+ cipher_null,
+ rc4,
+ rc2,
+ des,
+ triple_des, // leading 3 (3des) not valid identifier
+ des40,
+ idea,
+ aes
+};
+
+
+// Supported Message Authentication Codes from page 43
+enum MACAlgorithm {
+ no_mac,
+ md5,
+ sha,
+ rmd
+};
+
+
+// Certificate file Type
+enum CertType { Cert = 0, PrivateKey, CA };
+
+
+// all Cipher Suites from pages 41/42
+const Cipher SSL_NULL_WITH_NULL_NULL = 0; // { 0x00, 0x00 }
+const Cipher SSL_RSA_WITH_NULL_MD5 = 1; // { 0x00, 0x01 }
+const Cipher SSL_RSA_WITH_NULL_SHA = 2; // { 0x00, 0x02 }
+const Cipher SSL_RSA_EXPORT_WITH_RC4_40_MD5 = 3; // { 0x00, 0x03 }
+const Cipher SSL_RSA_WITH_RC4_128_MD5 = 4; // { 0x00, 0x04 }
+const Cipher SSL_RSA_WITH_RC4_128_SHA = 5; // { 0x00, 0x05 }
+const Cipher SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6; // { 0x00, 0x06 }
+const Cipher SSL_RSA_WITH_IDEA_CBC_SHA = 7; // { 0x00, 0x07 }
+const Cipher SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = 8; // { 0x00, 0x08 }
+const Cipher SSL_RSA_WITH_DES_CBC_SHA = 9; // { 0x00, 0x09 }
+const Cipher SSL_RSA_WITH_3DES_EDE_CBC_SHA = 10; // { 0x00, 0x0A }
+const Cipher SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11; // { 0x00, 0x0B }
+const Cipher SSL_DH_DSS_WITH_DES_CBC_SHA = 12; // { 0x00, 0x0C }
+const Cipher SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13; // { 0x00, 0x0D }
+const Cipher SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14; // { 0x00, 0x0E }
+const Cipher SSL_DH_RSA_WITH_DES_CBC_SHA = 15; // { 0x00, 0x0F }
+const Cipher SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16; // { 0x00, 0x10 }
+const Cipher SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17; // { 0x00, 0x11 }
+const Cipher SSL_DHE_DSS_WITH_DES_CBC_SHA = 18; // { 0x00, 0x12 }
+const Cipher SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19; // { 0x00, 0x13 }
+const Cipher SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20; // { 0x00, 0x14 }
+const Cipher SSL_DHE_RSA_WITH_DES_CBC_SHA = 21; // { 0x00, 0x15 }
+const Cipher SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22; // { 0x00, 0x16 }
+const Cipher SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23; // { 0x00, 0x17 }
+const Cipher SSL_DH_anon_WITH_RC4_128_MD5 = 24; // { 0x00, 0x18 }
+const Cipher SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25; // { 0x00, 0x19 }
+const Cipher SSL_DH_anon_WITH_DES_CBC_SHA = 26; // { 0x00, 0x1A }
+const Cipher SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = 27; // { 0x00, 0x1B }
+const Cipher SSL_FORTEZZA_KEA_WITH_NULL_SHA = 28; // { 0x00, 0x1C }
+const Cipher SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 29; // { 0x00, 0x1D }
+const Cipher SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 30; // { 0x00, 0x1E }
+
+// .. to 0x2B uses Kerberos Authentication
+
+
+// TLS AES extensions
+const Cipher TLS_RSA_WITH_AES_128_CBC_SHA = 47; // { 0x00, 0x2F }
+const Cipher TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48; // { 0x00, 0x30 }
+const Cipher TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49; // { 0x00, 0x31 }
+const Cipher TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50; // { 0x00, 0x32 }
+const Cipher TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51; // { 0x00, 0x33 }
+const Cipher TLS_DH_anon_WITH_AES_128_CBC_SHA = 52; // { 0x00, 0x34 }
+
+const Cipher TLS_RSA_WITH_AES_256_CBC_SHA = 53; // { 0x00, 0x35 }
+const Cipher TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54; // { 0x00, 0x36 }
+const Cipher TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55; // { 0x00, 0x37 }
+const Cipher TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56; // { 0x00, 0x38 }
+const Cipher TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57; // { 0x00, 0x39 }
+const Cipher TLS_DH_anon_WITH_AES_256_CBC_SHA = 58; // { 0x00, 0x3A }
+
+
+// OpenPGP extensions
+
+const Cipher TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160 = 114; // { 0x00, 0x72 };
+const Cipher TLS_DHE_DSS_WITH_AES_128_CBC_RMD160 = 115; // { 0x00, 0x73 };
+const Cipher TLS_DHE_DSS_WITH_AES_256_CBC_RMD160 = 116; // { 0x00, 0x74 };
+const Cipher TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160 = 119; // { 0x00, 0x77 };
+const Cipher TLS_DHE_RSA_WITH_AES_128_CBC_RMD160 = 120; // { 0x00, 0x78 };
+const Cipher TLS_DHE_RSA_WITH_AES_256_CBC_RMD160 = 121; // { 0x00, 0x79 };
+const Cipher TLS_RSA_WITH_3DES_EDE_CBC_RMD160 = 124; // { 0x00, 0x7C };
+const Cipher TLS_RSA_WITH_AES_128_CBC_RMD160 = 125; // { 0x00, 0x7D };
+const Cipher TLS_RSA_WITH_AES_256_CBC_RMD160 = 126; // { 0x00, 0x7E };
+
+
+const char* const null_str = "";
+
+const char* const cipher_names[128] =
+{
+ null_str, // SSL_NULL_WITH_NULL_NULL = 0
+ null_str, // SSL_RSA_WITH_NULL_MD5 = 1
+ null_str, // SSL_RSA_WITH_NULL_SHA = 2
+ null_str, // SSL_RSA_EXPORT_WITH_RC4_40_MD5 = 3
+ "RC4-MD5", // SSL_RSA_WITH_RC4_128_MD5 = 4
+ "RC4-SHA", // SSL_RSA_WITH_RC4_128_SHA = 5
+ null_str, // SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6
+ null_str, // SSL_RSA_WITH_IDEA_CBC_SHA = 7
+ null_str, // SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = 8
+ "DES-CBC-SHA", // SSL_RSA_WITH_DES_CBC_SHA = 9
+ "DES-CBC3-SHA", // SSL_RSA_WITH_3DES_EDE_CBC_SHA = 10
+
+ null_str, // SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11
+ null_str, // SSL_DH_DSS_WITH_DES_CBC_SHA = 12
+ null_str, // SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13
+ null_str, // SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14
+ null_str, // SSL_DH_RSA_WITH_DES_CBC_SHA = 15
+ null_str, // SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16
+ null_str, // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17
+ "EDH-DSS-DES-CBC-SHA", // SSL_DHE_DSS_WITH_DES_CBC_SHA = 18
+ "EDH-DSS-DES-CBC3-SHA", // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19
+ null_str, // SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20
+
+ "EDH-RSA-DES-CBC-SHA", // SSL_DHE_RSA_WITH_DES_CBC_SHA = 21
+ "EDH-RSA-DES-CBC3-SHA", // SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22
+ null_str, // SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23
+ null_str, // SSL_DH_anon_WITH_RC4_128_MD5 = 24
+ null_str, // SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25
+ null_str, // SSL_DH_anon_WITH_DES_CBC_SHA = 26
+ null_str, // SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = 27
+ null_str, // SSL_FORTEZZA_KEA_WITH_NULL_SHA = 28
+ null_str, // SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 29
+ null_str, // SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 30
+
+ null_str, null_str, null_str, null_str, null_str, // 31 - 35
+ null_str, null_str, null_str, null_str, null_str, // 36 - 40
+ null_str, null_str, null_str, null_str, null_str, // 41 - 45
+ null_str, // 46
+
+ // TLS AES extensions
+ "AES128-SHA", // TLS_RSA_WITH_AES_128_CBC_SHA = 47
+ null_str, // TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48
+ null_str, // TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49
+ "DHE-DSS-AES128-SHA", // TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50
+ "DHE-RSA-AES128-SHA", // TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51
+ null_str, // TLS_DH_anon_WITH_AES_128_CBC_SHA = 52
+
+ "AES256-SHA", // TLS_RSA_WITH_AES_256_CBC_SHA = 53
+ null_str, // TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54
+ null_str, // TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55
+ "DHE-DSS-AES256-SHA", // TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56
+ "DHE-RSA-AES256-SHA", // TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57
+ null_str, // TLS_DH_anon_WITH_AES_256_CBC_SHA = 58
+
+ null_str, // 59
+ null_str, // 60
+ null_str, null_str, null_str, null_str, null_str, // 61 - 65
+ null_str, null_str, null_str, null_str, null_str, // 66 - 70
+ null_str, null_str, null_str, null_str, null_str, // 71 - 75
+ null_str, null_str, null_str, null_str, null_str, // 76 - 80
+ null_str, null_str, null_str, null_str, null_str, // 81 - 85
+ null_str, null_str, null_str, null_str, null_str, // 86 - 90
+ null_str, null_str, null_str, null_str, null_str, // 91 - 95
+ null_str, null_str, null_str, null_str, null_str, // 96 - 100
+ null_str, null_str, null_str, null_str, null_str, // 101 - 105
+ null_str, null_str, null_str, null_str, null_str, // 106 - 110
+ null_str, null_str, null_str, // 111 - 113
+
+ "DHE-DSS-DES-CBC3-RMD", // TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160 = 114
+ "DHE-DSS-AES128-RMD", // TLS_DHE_DSS_WITH_AES_128_CBC_RMD160 = 115
+ "DHE-DSS-AES256-RMD", // TLS_DHE_DSS_WITH_AES_256_CBC_RMD160 = 116
+ null_str, // 117
+ null_str, // 118
+ "DHE-RSA-DES-CBC3-RMD", // TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160 = 119
+ "DHE-RSA-AES128-RMD", // TLS_DHE_RSA_WITH_AES_128_CBC_RMD160 = 120
+ "DHE-RSA-AES256-RMD", // TLS_DHE_RSA_WITH_AES_256_CBC_RMD160 = 121
+ null_str, // 122
+ null_str, // 123
+ "DES-CBC3-RMD", // TLS_RSA_WITH_3DES_EDE_CBC_RMD160 = 124
+ "AES128-RMD", // TLS_RSA_WITH_AES_128_CBC_RMD160 = 125
+ "AES256-RMD", // TLS_RSA_WITH_AES_256_CBC_RMD160 = 126
+ null_str // 127
+};
+
+// fill with MD5 pad size since biggest required
+const opaque PAD1[PAD_MD5] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+ };
+const opaque PAD2[PAD_MD5] = { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+ };
+
+const opaque client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 };
+const opaque server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 };
+
+const opaque tls_client[FINISHED_LABEL_SZ + 1] = "client finished";
+const opaque tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
+
+const opaque master_label[MASTER_LABEL_SZ + 1] = "master secret";
+const opaque key_label [KEY_LABEL_SZ + 1] = "key expansion";
+
+
+} // naemspace
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
+/*
+ gcc 2.96 bails out because of two declarations of byte: yaSSL::byte and
+ TaoCrypt::byte. TODO: define global types.hpp and move the declaration of
+ 'byte' there.
+*/
+using yaSSL::byte;
+#endif
+
+
+#endif // yaSSL_TYPES_HPP
diff --git a/extra/yassl/mySTL/algorithm.hpp b/extra/yassl/mySTL/algorithm.hpp
new file mode 100644
index 00000000000..3ceb0ca5fdc
--- /dev/null
+++ b/extra/yassl/mySTL/algorithm.hpp
@@ -0,0 +1,111 @@
+/* mySTL algorithm.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* mySTL algorithm implements max, min, for_each, swap, find_if, copy,
+ * copy_backward, fill
+ */
+
+#ifndef mySTL_ALGORITHM_HPP
+#define mySTL_ALGORITHM_HPP
+
+
+namespace mySTL {
+
+
+template<typename T>
+inline const T& max(const T& a, const T&b)
+{
+ return a < b ? b : a;
+}
+
+
+template<typename T>
+inline const T& min(const T& a, const T&b)
+{
+ return b < a ? b : a;
+}
+
+
+template<typename InIter, typename Func>
+Func for_each(InIter first, InIter last, Func op)
+{
+ while (first != last) {
+ op(*first);
+ ++first;
+ }
+ return op;
+}
+
+
+template<typename T>
+inline void swap(T& a, T& b)
+{
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+
+template<typename InIter, typename Pred>
+InIter find_if(InIter first, InIter last, Pred pred)
+{
+ while (first != last && !pred(*first))
+ ++first;
+ return first;
+}
+
+
+template<typename InputIter, typename OutputIter>
+inline OutputIter copy(InputIter first, InputIter last, OutputIter place)
+{
+ while (first != last) {
+ *place = *first;
+ ++first;
+ ++place;
+ }
+ return place;
+}
+
+
+template<typename InputIter, typename OutputIter>
+inline OutputIter
+copy_backward(InputIter first, InputIter last, OutputIter place)
+{
+ while (first != last)
+ *--place = *--last;
+ return place;
+}
+
+
+template<typename InputIter, typename T>
+void fill(InputIter first, InputIter last, const T& v)
+{
+ while (first != last) {
+ *first = v;
+ ++first;
+ }
+}
+
+
+} // namespace mySTL
+
+#endif // mySTL_ALGORITHM_HPP
diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/mySTL/helpers.hpp
new file mode 100644
index 00000000000..de825c23fec
--- /dev/null
+++ b/extra/yassl/mySTL/helpers.hpp
@@ -0,0 +1,108 @@
+/* mySTL helpers.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* mySTL helpers implements misc constructs for vector and list
+ *
+ */
+
+#ifndef mySTL_HELPERS_HPP
+#define mySTL_HELPERS_HPP
+
+#include <stdlib.h>
+
+/*
+ Workaround for the lack of operator new(size_t, void*)
+ in IBM VA C++ 6.0
+ Also used as a workaround to avoid including <new>
+*/
+ struct Dummy {};
+
+ inline void* operator new(size_t size, Dummy* d)
+ {
+ return static_cast<void*>(d);
+ }
+
+ typedef Dummy* yassl_pointer;
+
+
+namespace mySTL {
+
+
+template <typename T, typename T2>
+inline void construct(T* p, const T2& value)
+{
+ new (reinterpret_cast<yassl_pointer>(p)) T(value);
+}
+
+
+template <typename T>
+inline void construct(T* p)
+{
+ new (reinterpret_cast<yassl_pointer>(p)) T();
+}
+
+
+template <typename T>
+inline void destroy(T* p)
+{
+ p->~T();
+}
+
+
+template <typename Iter>
+void destroy(Iter first, Iter last)
+{
+ while (first != last) {
+ destroy(&*first);
+ ++first;
+ }
+}
+
+
+template <typename Iter, typename PlaceIter>
+PlaceIter uninit_copy(Iter first, Iter last, PlaceIter place)
+{
+ while (first != last) {
+ construct(&*place, *first);
+ ++first;
+ ++place;
+ }
+ return place;
+}
+
+
+template <typename PlaceIter, typename Size, typename T>
+PlaceIter uninit_fill_n(PlaceIter place, Size n, const T& value)
+{
+ while (n) {
+ construct(&*place, value);
+ --n;
+ ++place;
+ }
+ return place;
+}
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_HELPERS_HPP
diff --git a/extra/yassl/mySTL/list.hpp b/extra/yassl/mySTL/list.hpp
new file mode 100644
index 00000000000..dd8485f48a7
--- /dev/null
+++ b/extra/yassl/mySTL/list.hpp
@@ -0,0 +1,383 @@
+/* mySTL list.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* mySTL list implements a simple list
+ *
+ */
+
+#ifndef mySTL_LIST_HPP
+#define mySTL_LIST_HPP
+
+
+#include "helpers.hpp"
+#include <stdlib.h>
+
+
+namespace mySTL {
+
+
+
+template<typename T>
+class list {
+
+#ifdef __SUNPRO_CC
+/*
+ Sun Forte 7 C++ v. 5.4 needs class 'node' public to be visible to
+ the nested class 'iterator' (a non-standard behaviour).
+*/
+public:
+#endif
+
+ struct node {
+ node(T t) : prev_(0), next_(0), value_(t) {}
+
+ node* prev_;
+ node* next_;
+ T value_;
+ };
+public:
+ list() : head_(0), tail_(0), sz_(0) {}
+ ~list();
+
+ void push_front(T);
+ void pop_front();
+ T front() const;
+ void push_back(T);
+ void pop_back();
+ T back() const;
+ bool remove(T);
+ size_t size() const { return sz_; }
+ bool empty() const { return sz_ == 0; }
+
+ class iterator {
+ node* current_;
+ public:
+ iterator() : current_(0) {}
+ explicit iterator(node* p) : current_(p) {}
+
+ T& operator*() const
+ {
+ return current_->value_;
+ }
+
+ T* operator->() const
+ {
+ return &(operator*());
+ }
+
+ iterator& operator++()
+ {
+ current_ = current_->next_;
+ return *this;
+ }
+
+ iterator& operator--()
+ {
+ current_ = current_->prev_;
+ return *this;
+ }
+
+ iterator operator++(int)
+ {
+ iterator tmp = *this;
+ current_ = current_->next_;
+ return tmp;
+ }
+
+ iterator operator--(int)
+ {
+ iterator tmp = *this;
+ current_ = current_->prev_;
+ return tmp;
+ }
+
+ bool operator==(const iterator& other) const
+ {
+ return current_ == other.current_;
+ }
+
+ bool operator!=(const iterator& other) const
+ {
+ return current_ != other.current_;
+ }
+
+ friend class list<T>;
+ };
+
+ bool erase(iterator);
+
+ iterator begin() const { return iterator(head_); }
+ iterator rbegin() const { return iterator(tail_); }
+ iterator end() const { return iterator(); }
+
+ typedef iterator const_iterator; // for now
+
+ class underflow {};
+ class overflow {};
+private:
+ node* head_;
+ node* tail_;
+ size_t sz_;
+
+ node* look_up(T);
+
+ list(const list&); // hide copy
+ list& operator=(const list&); // and assign
+};
+
+
+template<typename T>
+list<T>::~list()
+{
+ node* start = head_;
+ node* next_;
+
+ for (; start; start = next_) {
+ next_ = start->next_;
+ destroy(start);
+ free(start);
+ }
+}
+
+
+template<typename T>
+void list<T>::push_front(T t)
+{
+ void* mem = malloc(sizeof(node));
+ if (!mem) abort();
+ node* add = new (reinterpret_cast<yassl_pointer>(mem)) node(t);
+
+ if (head_) {
+ add->next_ = head_;
+ head_->prev_ = add;
+ }
+ else
+ tail_ = add;
+
+ head_ = add;
+ ++sz_;
+}
+
+
+template<typename T>
+void list<T>::pop_front()
+{
+ node* front = head_;
+
+ if (head_ == 0)
+ return;
+ else if (head_ == tail_)
+ head_ = tail_ = 0;
+ else {
+ head_ = head_->next_;
+ head_->prev_ = 0;
+ }
+ destroy(front);
+ free(front);
+ --sz_;
+}
+
+
+template<typename T>
+T list<T>::front() const
+{
+ if (head_ == 0) return 0;
+ return head_->value_;
+}
+
+
+template<typename T>
+void list<T>::push_back(T t)
+{
+ void* mem = malloc(sizeof(node));
+ if (!mem) abort();
+ node* add = new (reinterpret_cast<yassl_pointer>(mem)) node(t);
+
+ if (tail_) {
+ tail_->next_ = add;
+ add->prev_ = tail_;
+ }
+ else
+ head_ = add;
+
+ tail_ = add;
+ ++sz_;
+}
+
+
+template<typename T>
+void list<T>::pop_back()
+{
+ node* rear = tail_;
+
+ if (tail_ == 0)
+ return;
+ else if (tail_ == head_)
+ tail_ = head_ = 0;
+ else {
+ tail_ = tail_->prev_;
+ tail_->next_ = 0;
+ }
+ destroy(rear);
+ free(rear);
+ --sz_;
+}
+
+
+template<typename T>
+T list<T>::back() const
+{
+ if (tail_ == 0) return 0;
+ return tail_->value_;
+}
+
+
+template<typename T>
+typename list<T>::node* list<T>::look_up(T t)
+{
+ node* list = head_;
+
+ if (list == 0) return 0;
+
+ for (; list; list = list->next_)
+ if (list->value_ == t)
+ return list;
+
+ return 0;
+}
+
+
+template<typename T>
+bool list<T>::remove(T t)
+{
+ node* del = look_up(t);
+
+ if (del == 0)
+ return false;
+ else if (del == head_)
+ pop_front();
+ else if (del == tail_)
+ pop_back();
+ else {
+ del->prev_->next_ = del->next_;
+ del->next_->prev_ = del->prev_;
+
+ destroy(del);
+ free(del);
+ --sz_;
+ }
+ return true;
+}
+
+
+template<typename T>
+bool list<T>::erase(iterator iter)
+{
+ node* del = iter.current_;
+
+ if (del == 0)
+ return false;
+ else if (del == head_)
+ pop_front();
+ else if (del == tail_)
+ pop_back();
+ else {
+ del->prev_->next_ = del->next_;
+ del->next_->prev_ = del->prev_;
+
+ destroy(del);
+ free(del);
+ --sz_;
+ }
+ return true;
+}
+
+
+/* MSVC can't handle ??
+
+template<typename T>
+T& list<T>::iterator::operator*() const
+{
+ return current_->value_;
+}
+
+
+template<typename T>
+T* list<T>::iterator::operator->() const
+{
+ return &(operator*());
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator++()
+{
+ current_ = current_->next_;
+ return *this;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator--()
+{
+ current_ = current_->prev_;
+ return *this;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator++(int)
+{
+ iterator tmp = *this;
+ current_ = current_->next_;
+ return tmp;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator--(int)
+{
+ iterator tmp = *this;
+ current_ = current_->prev_;
+ return tmp;
+}
+
+
+template<typename T>
+bool list<T>::iterator::operator==(const iterator& other) const
+{
+ return current_ == other.current_;
+}
+
+
+template<typename T>
+bool list<T>::iterator::operator!=(const iterator& other) const
+{
+ return current_ != other.current_;
+}
+*/ // end MSVC 6 can't handle
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_LIST_HPP
diff --git a/extra/yassl/mySTL/memory.hpp b/extra/yassl/mySTL/memory.hpp
new file mode 100644
index 00000000000..cc70fbf60d8
--- /dev/null
+++ b/extra/yassl/mySTL/memory.hpp
@@ -0,0 +1,142 @@
+/* mySTL memory.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* mySTL memory implements auto_ptr
+ *
+ */
+
+#ifndef mySTL_MEMORY_HPP
+#define mySTL_MEMORY_HPP
+
+
+#ifdef _MSC_VER
+ // disable operator-> warning for builtins
+ #pragma warning(disable:4284)
+#endif
+
+
+namespace mySTL {
+
+
+template<typename T>
+struct auto_ptr_ref {
+ typedef void (*Deletor)(T*);
+ T* ptr_;
+ Deletor del_;
+ auto_ptr_ref(T* p, Deletor d) : ptr_(p), del_(d) {}
+};
+
+
+template<typename T>
+class auto_ptr {
+ typedef void (*Deletor)(T*);
+ T* ptr_;
+ Deletor del_;
+
+ void Destroy()
+ {
+ del_(ptr_);
+ }
+public:
+ auto_ptr(T* p, Deletor d) : ptr_(p), del_(d) {}
+
+ explicit auto_ptr(Deletor d) : ptr_(0), del_(d) {}
+
+ ~auto_ptr()
+ {
+ Destroy();
+ }
+
+
+ auto_ptr(auto_ptr& other) : ptr_(other.release()), del_(other.del_) {}
+
+ auto_ptr& operator=(auto_ptr& that)
+ {
+ if (this != &that) {
+ Destroy();
+ ptr_ = that.release();
+ del_ = that.del_;
+ }
+ return *this;
+ }
+
+
+ T* operator->() const
+ {
+ return ptr_;
+ }
+
+ T& operator*() const
+ {
+ return *ptr_;
+ }
+
+ T* get() const
+ {
+ return ptr_;
+ }
+
+ T* release()
+ {
+ T* tmp = ptr_;
+ ptr_ = 0;
+ return tmp;
+ }
+
+ void reset(T* p = 0)
+ {
+ if (ptr_ != p) {
+ Destroy();
+ ptr_ = p;
+ }
+ }
+
+ // auto_ptr_ref conversions
+ auto_ptr(auto_ptr_ref<T> ref) : ptr_(ref.ptr_), del_(ref.del_) {}
+
+ auto_ptr& operator=(auto_ptr_ref<T> ref)
+ {
+ if (this->ptr_ != ref.ptr_) {
+ Destroy();
+ ptr_ = ref.ptr_;
+ del_ = ref.del_;
+ }
+ return *this;
+ }
+
+ template<typename T2>
+ operator auto_ptr<T2>()
+ {
+ return auto_ptr<T2>(this->release(), this->del_);
+ }
+
+ template<typename T2>
+ operator auto_ptr_ref<T2>()
+ {
+ return auto_ptr_ref<T2>(this->release(), this->del_);
+ }
+};
+
+
+} // namespace mySTL
+
+#endif // mySTL_MEMORY_HPP
diff --git a/extra/yassl/mySTL/pair.hpp b/extra/yassl/mySTL/pair.hpp
new file mode 100644
index 00000000000..c9bb03b5953
--- /dev/null
+++ b/extra/yassl/mySTL/pair.hpp
@@ -0,0 +1,61 @@
+/* mySTL pair.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* mySTL pair implements pair
+ *
+ */
+
+#ifndef mySTL_PAIR_HPP
+#define mySTL_PAIR_HPP
+
+
+
+namespace mySTL {
+
+
+template<typename T1, typename T2>
+struct pair {
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ first_type first;
+ second_type second;
+
+ pair() {}
+ pair(const T1& t1, const T2& t2) : first(t1), second(t2) {}
+
+ template<typename U1, typename U2>
+ pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}
+};
+
+
+template<typename T1, typename T2>
+inline pair<T1, T2> make_pair(const T1& a, const T2& b)
+{
+ return pair<T1, T2>(a, b);
+}
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_PAIR_HPP
diff --git a/extra/yassl/mySTL/stdexcept.hpp b/extra/yassl/mySTL/stdexcept.hpp
new file mode 100644
index 00000000000..33ea43bf0e0
--- /dev/null
+++ b/extra/yassl/mySTL/stdexcept.hpp
@@ -0,0 +1,80 @@
+/* mySTL stdexcept.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* mySTL memory implements exception, runtime_error
+ *
+ */
+
+#ifndef mySTL_STDEXCEPT_HPP
+#define mySTL_STDEXCEPT_HPP
+
+
+#include <string.h> // strncpy
+#include <assert.h> // assert
+#include <stdlib.h> // size_t
+
+
+namespace mySTL {
+
+
+class exception {
+public:
+ exception() {}
+ virtual ~exception() {} // to shut up compiler warnings
+
+ virtual const char* what() const { return ""; }
+
+ // for compiler generated call, never used
+ static void operator delete(void*) { assert(0); }
+private:
+ // don't allow dynamic creation of exceptions
+ static void* operator new(size_t);
+};
+
+
+class named_exception : public exception {
+public:
+ enum { NAME_SIZE = 80 };
+
+ explicit named_exception(const char* str)
+ {
+ strncpy(name_, str, NAME_SIZE);
+ name_[NAME_SIZE - 1] = 0;
+ }
+
+ virtual const char* what() const { return name_; }
+private:
+ char name_[NAME_SIZE];
+};
+
+
+class runtime_error : public named_exception {
+public:
+ explicit runtime_error(const char* str) : named_exception(str) {}
+};
+
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_STDEXCEPT_HPP
diff --git a/extra/yassl/mySTL/vector.hpp b/extra/yassl/mySTL/vector.hpp
new file mode 100644
index 00000000000..e7f63c37c7c
--- /dev/null
+++ b/extra/yassl/mySTL/vector.hpp
@@ -0,0 +1,153 @@
+/* mySTL vector.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* mySTL vector implements simple vector, w/ swap
+ *
+ */
+
+#ifndef mySTL_VECTOR_HPP
+#define mySTL_VECTOR_HPP
+
+#include "helpers.hpp" // construct, destory, fill, etc.
+#include "algorithm.hpp" // swap
+#include <assert.h> // assert
+#include <stdlib.h> // malloc
+
+
+namespace mySTL {
+
+
+template <typename T>
+struct vector_base {
+ T* start_;
+ T* finish_;
+ T* end_of_storage_;
+
+ vector_base() : start_(0), finish_(0), end_of_storage_(0) {}
+ vector_base(size_t n)
+ {
+ start_ = static_cast<T*>(malloc(n * sizeof(T)));
+ if (!start_) abort();
+ finish_ = start_;
+ end_of_storage_ = start_ + n;
+ }
+
+ ~vector_base() { if (start_) free(start_); }
+
+ void Swap(vector_base& that)
+ {
+ swap(start_, that.start_);
+ swap(finish_, that.finish_);
+ swap(end_of_storage_, that.end_of_storage_);
+ }
+};
+
+
+
+template <typename T>
+class vector {
+public:
+ vector() {}
+ explicit vector(size_t n) : vec_(n)
+ {
+ vec_.finish_ = uninit_fill_n(vec_.start_, n, T());
+ }
+
+ ~vector() { destroy(vec_.start_, vec_.finish_); }
+
+ vector(const vector& other) : vec_(other.size())
+ {
+ vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_,
+ vec_.start_);
+ }
+
+ size_t capacity() const { return vec_.end_of_storage_ - vec_.start_; }
+
+ size_t size() const { return vec_.finish_ - vec_.start_; }
+
+ T& operator[](size_t idx) { return *(vec_.start_ + idx); }
+ const T& operator[](size_t idx) const { return *(vec_.start_ + idx); }
+
+ const T* begin() const { return vec_.start_; }
+ const T* end() const { return vec_.finish_; }
+
+ void push_back(const T& v)
+ {
+ if (vec_.finish_ != vec_.end_of_storage_) {
+ construct(vec_.finish_, v);
+ ++vec_.finish_;
+ }
+ else {
+ vector tmp(size() * 2 + 1, *this);
+ construct(tmp.vec_.finish_, v);
+ ++tmp.vec_.finish_;
+ Swap(tmp);
+ }
+ }
+
+ void resize(size_t n, const T& v)
+ {
+ if (n == size()) return;
+
+ if (n < size()) {
+ T* first = vec_.start_ + n;
+ destroy(first, vec_.finish_);
+ vec_.finish_ -= vec_.finish_ - first;
+ }
+ else {
+ vector tmp(n, *this);
+ tmp.vec_.finish_ = uninit_fill_n(tmp.vec_.finish_, n - size(), v);
+ Swap(tmp);
+ }
+ }
+
+ void reserve(size_t n)
+ {
+ if (capacity() < n) {
+ vector tmp(n, *this);
+ Swap(tmp);
+ }
+ }
+
+ void Swap(vector& that)
+ {
+ vec_.Swap(that.vec_);
+ }
+private:
+ vector_base<T> vec_;
+
+ vector& operator=(const vector&); // hide assign
+
+ // for growing, n must be bigger than other size
+ vector(size_t n, const vector& other) : vec_(n)
+ {
+ assert(n > other.size());
+ vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_,
+ vec_.start_);
+ }
+};
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_VECTOR_HPP
diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am
new file mode 100644
index 00000000000..83397e24168
--- /dev/null
+++ b/extra/yassl/src/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES = -I../include -I../taocrypt/include -I../mySTL
+
+noinst_LTLIBRARIES = libyassl.la
+libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \
+ handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \
+ template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp
+EXTRA_DIST = ../include/*.hpp ../include/openssl/*.h
+AM_CXXFLAGS = -DYASSL_PURE_C
diff --git a/extra/yassl/src/buffer.cpp b/extra/yassl/src/buffer.cpp
new file mode 100644
index 00000000000..56d355bea80
--- /dev/null
+++ b/extra/yassl/src/buffer.cpp
@@ -0,0 +1,281 @@
+/* buffer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* yaSSL buffer header implements input/output buffers to simulate streaming
+ * with SSL types and sockets
+ */
+
+#include <string.h> // memcpy
+#include "runtime.hpp"
+#include "buffer.hpp"
+#include "yassl_types.hpp"
+
+namespace yaSSL {
+
+
+
+// Checking Policy should implement a check function that tests whether the
+// index is within the size limit of the array
+
+void Check::check(uint i, uint limit)
+{
+ assert(i < limit);
+}
+
+
+void NoCheck::check(uint, uint)
+{
+}
+
+
+/* input_buffer operates like a smart c style array with a checking option,
+ * meant to be read from through [] with AUTO index or read().
+ * Should only write to at/near construction with assign() or raw (e.g., recv)
+ * followed by add_size with the number of elements added by raw write.
+ *
+ * Not using vector because need checked []access, offset, and the ability to
+ * write to the buffer bulk wise and have the correct size
+ */
+
+
+input_buffer::input_buffer()
+ : size_(0), current_(0), buffer_(0), end_(0)
+{}
+
+
+input_buffer::input_buffer(uint s)
+ : size_(0), current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{}
+
+
+// with assign
+input_buffer::input_buffer(uint s, const byte* t, uint len)
+ : size_(0), current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{
+ assign(t, len);
+}
+
+
+input_buffer::~input_buffer()
+{
+ ysArrayDelete(buffer_);
+}
+
+
+// users can pass defualt zero length buffer and then allocate
+void input_buffer::allocate(uint s)
+{
+ assert(!buffer_); // find realloc error
+ buffer_ = new (ys) byte[s];
+ end_ = buffer_ + s;
+}
+
+
+// for passing to raw writing functions at beginning, then use add_size
+byte* input_buffer::get_buffer() const
+{
+ return buffer_;
+}
+
+
+// after a raw write user can set new (ys) size
+// if you know the size before the write use assign()
+void input_buffer::add_size(uint i)
+{
+ check(size_ + i-1, get_capacity());
+ size_ += i;
+}
+
+
+uint input_buffer::get_capacity() const
+{
+ return end_ - buffer_;
+}
+
+
+uint input_buffer::get_current() const
+{
+ return current_;
+}
+
+
+uint input_buffer::get_size() const
+{
+ return size_;
+}
+
+
+uint input_buffer::get_remaining() const
+{
+ return size_ - current_;
+}
+
+
+void input_buffer::set_current(uint i)
+{
+ if (i)
+ check(i - 1, size_);
+ current_ = i;
+}
+
+
+// read only access through [], advance current
+// user passes in AUTO index for ease of use
+const byte& input_buffer::operator[](uint i)
+{
+ assert (i == AUTO);
+ check(current_, size_);
+ return buffer_[current_++];
+}
+
+
+// end of input test
+bool input_buffer::eof()
+{
+ return current_ >= size_;
+}
+
+
+// peek ahead
+byte input_buffer::peek() const
+{
+ return buffer_[current_];
+}
+
+
+// write function, should use at/near construction
+void input_buffer::assign(const byte* t, uint s)
+{
+ check(current_, get_capacity());
+ add_size(s);
+ memcpy(&buffer_[current_], t, s);
+}
+
+
+// use read to query input, adjusts current
+void input_buffer::read(byte* dst, uint length)
+{
+ check(current_ + length - 1, size_);
+ memcpy(dst, &buffer_[current_], length);
+ current_ += length;
+}
+
+
+
+/* output_buffer operates like a smart c style array with a checking option.
+ * Meant to be written to through [] with AUTO index or write().
+ * Size (current) counter increases when written to. Can be constructed with
+ * zero length buffer but be sure to allocate before first use.
+ * Don't use add write for a couple bytes, use [] instead, way less overhead.
+ *
+ * Not using vector because need checked []access and the ability to
+ * write to the buffer bulk wise and retain correct size
+ */
+
+
+output_buffer::output_buffer()
+ : current_(0), buffer_(0), end_(0)
+{}
+
+
+// with allocate
+output_buffer::output_buffer(uint s)
+ : current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{}
+
+
+// with assign
+output_buffer::output_buffer(uint s, const byte* t, uint len)
+ : current_(0), buffer_(new (ys) byte[s]), end_(buffer_+ s)
+{
+ write(t, len);
+}
+
+
+output_buffer::~output_buffer()
+{
+ ysArrayDelete(buffer_);
+}
+
+
+uint output_buffer::get_size() const
+{
+ return current_;
+}
+
+
+uint output_buffer::get_capacity() const
+{
+ return end_ - buffer_;
+}
+
+
+void output_buffer::set_current(uint c)
+{
+ check(c, get_capacity());
+ current_ = c;
+}
+
+
+// users can pass defualt zero length buffer and then allocate
+void output_buffer::allocate(uint s)
+{
+ assert(!buffer_); // find realloc error
+ buffer_ = new (ys) byte[s]; end_ = buffer_ + s;
+}
+
+
+// for passing to reading functions when finished
+const byte* output_buffer::get_buffer() const
+{
+ return buffer_;
+}
+
+
+// allow write access through [], update current
+// user passes in AUTO as index for ease of use
+byte& output_buffer::operator[](uint i)
+{
+ assert(i == AUTO);
+ check(current_, get_capacity());
+ return buffer_[current_++];
+}
+
+
+// end of output test
+bool output_buffer::eof()
+{
+ return current_ >= get_capacity();
+}
+
+
+void output_buffer::write(const byte* t, uint s)
+{
+ check(current_ + s - 1, get_capacity());
+ memcpy(&buffer_[current_], t, s);
+ current_ += s;
+}
+
+
+
+} // naemspace
+
diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp
new file mode 100644
index 00000000000..a775c366a92
--- /dev/null
+++ b/extra/yassl/src/cert_wrapper.cpp
@@ -0,0 +1,318 @@
+/* cert_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* The certificate wrapper source implements certificate management functions
+ *
+ */
+
+#include "runtime.hpp"
+#include "cert_wrapper.hpp"
+#include "yassl_int.hpp"
+
+#if defined(USE_CML_LIB)
+ #include "cmapi_cpp.h"
+#else
+ #include "asn.hpp"
+ #include "file.hpp"
+#endif // USE_CML_LIB
+
+
+namespace yaSSL {
+
+
+x509::x509(uint sz) : length_(sz), buffer_(new (ys) opaque[sz])
+{
+}
+
+
+x509::~x509()
+{
+ ysArrayDelete(buffer_);
+}
+
+
+x509::x509(const x509& that) : length_(that.length_),
+ buffer_(new (ys) opaque[length_])
+{
+ memcpy(buffer_, that.buffer_, length_);
+}
+
+
+void x509::Swap(x509& that)
+{
+ mySTL::swap(length_, that.length_);
+ mySTL::swap(buffer_, that.buffer_);
+}
+
+
+x509& x509::operator=(const x509& that)
+{
+ x509 temp(that);
+ Swap(temp);
+ return *this;
+}
+
+
+uint x509::get_length() const
+{
+ return length_;
+}
+
+
+const opaque* x509::get_buffer() const
+{
+ return buffer_;
+}
+
+
+opaque* x509::use_buffer()
+{
+ return buffer_;
+}
+
+
+//CertManager
+CertManager::CertManager()
+ : peerX509_(0), verifyPeer_(false), failNoCert_(false), sendVerify_(false)
+{}
+
+
+CertManager::~CertManager()
+{
+ ysDelete(peerX509_);
+
+ mySTL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ;
+
+ mySTL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ;
+
+ mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ;
+}
+
+
+bool CertManager::verifyPeer() const
+{
+ return verifyPeer_;
+}
+
+
+bool CertManager::failNoCert() const
+{
+ return failNoCert_;
+}
+
+
+bool CertManager::sendVerify() const
+{
+ return sendVerify_;
+}
+
+
+void CertManager::setVerifyPeer()
+{
+ verifyPeer_ = true;
+}
+
+
+void CertManager::setFailNoCert()
+{
+ failNoCert_ = true;
+}
+
+
+void CertManager::setSendVerify()
+{
+ sendVerify_ = true;
+}
+
+
+void CertManager::AddPeerCert(x509* x)
+{
+ peerList_.push_back(x); // take ownership
+}
+
+
+void CertManager::CopySelfCert(const x509* x)
+{
+ if (x)
+ list_.push_back(new (ys) x509(*x));
+}
+
+
+// add to signers
+int CertManager::CopyCaCert(const x509* x)
+{
+ TaoCrypt::Source source(x->get_buffer(), x->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (!cert.GetError().What()) {
+ const TaoCrypt::PublicKey& key = cert.GetPublicKey();
+ signers_.push_back(new (ys) TaoCrypt::Signer(key.GetKey(), key.size(),
+ cert.GetCommonName(), cert.GetHash()));
+ }
+ return cert.GetError().What();
+}
+
+
+const x509* CertManager::get_cert() const
+{
+ return list_.front();
+}
+
+
+const opaque* CertManager::get_peerKey() const
+{
+ return peerPublicKey_.get_buffer();
+}
+
+
+X509* CertManager::get_peerX509() const
+{
+ return peerX509_;
+}
+
+
+SignatureAlgorithm CertManager::get_peerKeyType() const
+{
+ return peerKeyType_;
+}
+
+
+SignatureAlgorithm CertManager::get_keyType() const
+{
+ return keyType_;
+}
+
+
+uint CertManager::get_peerKeyLength() const
+{
+ return peerPublicKey_.get_size();
+}
+
+
+const opaque* CertManager::get_privateKey() const
+{
+ return privateKey_.get_buffer();
+}
+
+
+uint CertManager::get_privateKeyLength() const
+{
+ return privateKey_.get_size();
+}
+
+
+// Validate the peer's certificate list, from root to peer (last to first)
+int CertManager::Validate()
+{
+ CertList::iterator last = peerList_.rbegin(); // fix this
+ int count = peerList_.size();
+
+ while ( count > 1 ) {
+ TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (int err = cert.GetError().What())
+ return err;
+
+ const TaoCrypt::PublicKey& key = cert.GetPublicKey();
+ signers_.push_back(new (ys) TaoCrypt::Signer(key.GetKey(), key.size(),
+ cert.GetCommonName(), cert.GetHash()));
+ --last;
+ --count;
+ }
+
+ if (count) {
+ // peer's is at the front
+ TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (int err = cert.GetError().What())
+ return err;
+
+ uint sz = cert.GetPublicKey().size();
+ peerPublicKey_.allocate(sz);
+ peerPublicKey_.assign(cert.GetPublicKey().GetKey(), sz);
+
+ if (cert.GetKeyType() == TaoCrypt::RSAk)
+ peerKeyType_ = rsa_sa_algo;
+ else
+ peerKeyType_ = dsa_sa_algo;
+
+ int iSz = cert.GetIssuer() ? strlen(cert.GetIssuer()) + 1 : 0;
+ int sSz = cert.GetCommonName() ? strlen(cert.GetCommonName()) + 1 : 0;
+ peerX509_ = new (ys) X509(cert.GetIssuer(), iSz, cert.GetCommonName(),
+ sSz);
+ }
+ return 0;
+}
+
+
+// Set the private key
+int CertManager::SetPrivateKey(const x509& key)
+{
+ privateKey_.allocate(key.get_length());
+ privateKey_.assign(key.get_buffer(), key.get_length());
+
+ // set key type
+ if (x509* cert = list_.front()) {
+ TaoCrypt::Source source(cert->get_buffer(), cert->get_length());
+ TaoCrypt::CertDecoder cd(source, false);
+ cd.DecodeToKey();
+ if (int err = cd.GetError().What())
+ return err;
+ if (cd.GetKeyType() == TaoCrypt::RSAk)
+ keyType_ = rsa_sa_algo;
+ else
+ keyType_ = dsa_sa_algo;
+ }
+ return 0;
+}
+
+
+#if defined(USE_CML_LIB)
+
+// Get the peer's certificate, extract and save public key
+void CertManager::SetPeerKey()
+{
+ // first cert is the peer's
+ x509* main = peerList_.front();
+
+ Bytes_struct cert;
+ cert.num = main->get_length();
+ cert.data = main->set_buffer();
+
+ CML::Certificate cm(cert);
+ const CML::ASN::Cert& raw = cm.base();
+ CTIL::CSM_Buffer key = raw.pubKeyInfo.key;
+
+ uint sz;
+ opaque* key_buffer = reinterpret_cast<opaque*>(key.Get(sz));
+ peerPublicKey_.allocate(sz);
+ peerPublicKey_.assign(key_buffer, sz);
+}
+
+
+#endif // USE_CML_LIB
+
+
+
+} // namespace
diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp
new file mode 100644
index 00000000000..80cadd3d722
--- /dev/null
+++ b/extra/yassl/src/crypto_wrapper.cpp
@@ -0,0 +1,994 @@
+/* crypto_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* The crypto wrapper source implements the policies for the cipher
+ * components used by SSL.
+ *
+ * The implementation relies on a specfic library, taoCrypt.
+ */
+
+#if !defined(USE_CRYPTOPP_LIB)
+
+#include "runtime.hpp"
+#include "crypto_wrapper.hpp"
+#include "cert_wrapper.hpp"
+
+#include "md5.hpp"
+#include "sha.hpp"
+#include "ripemd.hpp"
+#include "hmac.hpp"
+#include "modes.hpp"
+#include "des.hpp"
+#include "arc4.hpp"
+#include "aes.hpp"
+#include "rsa.hpp"
+#include "dsa.hpp"
+#include "dh.hpp"
+#include "random.hpp"
+#include "file.hpp"
+#include "coding.hpp"
+
+
+namespace yaSSL {
+
+
+// MD5 Implementation
+struct MD5::MD5Impl {
+ TaoCrypt::MD5 md5_;
+ MD5Impl() {}
+ explicit MD5Impl(const TaoCrypt::MD5& md5) : md5_(md5) {}
+};
+
+
+MD5::MD5() : pimpl_(new (ys) MD5Impl) {}
+
+
+MD5::~MD5() { ysDelete(pimpl_); }
+
+
+MD5::MD5(const MD5& that) : Digest(), pimpl_(new (ys)
+ MD5Impl(that.pimpl_->md5_)) {}
+
+
+MD5& MD5::operator=(const MD5& that)
+{
+ pimpl_->md5_ = that.pimpl_->md5_;
+ return *this;
+}
+
+
+uint MD5::get_digestSize() const
+{
+ return MD5_LEN;
+}
+
+
+uint MD5::get_padSize() const
+{
+ return PAD_MD5;
+}
+
+
+// Fill out with MD5 digest from in that is sz bytes, out must be >= digest sz
+void MD5::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->md5_.Update(in, sz);
+ pimpl_->md5_.Final(out);
+}
+
+// Fill out with MD5 digest from previous updates
+void MD5::get_digest(byte* out)
+{
+ pimpl_->md5_.Final(out);
+}
+
+
+// Update the current digest
+void MD5::update(const byte* in, unsigned int sz)
+{
+ pimpl_->md5_.Update(in, sz);
+}
+
+
+// SHA Implementation
+struct SHA::SHAImpl {
+ TaoCrypt::SHA sha_;
+ SHAImpl() {}
+ explicit SHAImpl(const TaoCrypt::SHA& sha) : sha_(sha) {}
+};
+
+
+SHA::SHA() : pimpl_(new (ys) SHAImpl) {}
+
+
+SHA::~SHA() { ysDelete(pimpl_); }
+
+
+SHA::SHA(const SHA& that) : Digest(), pimpl_(new (ys) SHAImpl(that.pimpl_->sha_)) {}
+
+SHA& SHA::operator=(const SHA& that)
+{
+ pimpl_->sha_ = that.pimpl_->sha_;
+ return *this;
+}
+
+
+uint SHA::get_digestSize() const
+{
+ return SHA_LEN;
+}
+
+
+uint SHA::get_padSize() const
+{
+ return PAD_SHA;
+}
+
+
+// Fill out with SHA digest from in that is sz bytes, out must be >= digest sz
+void SHA::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->sha_.Update(in, sz);
+ pimpl_->sha_.Final(out);
+}
+
+
+// Fill out with SHA digest from previous updates
+void SHA::get_digest(byte* out)
+{
+ pimpl_->sha_.Final(out);
+}
+
+
+// Update the current digest
+void SHA::update(const byte* in, unsigned int sz)
+{
+ pimpl_->sha_.Update(in, sz);
+}
+
+
+// RMD-160 Implementation
+struct RMD::RMDImpl {
+ TaoCrypt::RIPEMD160 rmd_;
+ RMDImpl() {}
+ explicit RMDImpl(const TaoCrypt::RIPEMD160& rmd) : rmd_(rmd) {}
+};
+
+
+RMD::RMD() : pimpl_(new (ys) RMDImpl) {}
+
+
+RMD::~RMD() { ysDelete(pimpl_); }
+
+
+RMD::RMD(const RMD& that) : Digest(), pimpl_(new (ys) RMDImpl(that.pimpl_->rmd_)) {}
+
+RMD& RMD::operator=(const RMD& that)
+{
+ pimpl_->rmd_ = that.pimpl_->rmd_;
+ return *this;
+}
+
+
+uint RMD::get_digestSize() const
+{
+ return RMD_LEN;
+}
+
+
+uint RMD::get_padSize() const
+{
+ return PAD_RMD;
+}
+
+
+// Fill out with RMD digest from in that is sz bytes, out must be >= digest sz
+void RMD::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->rmd_.Update(in, sz);
+ pimpl_->rmd_.Final(out);
+}
+
+
+// Fill out with RMD digest from previous updates
+void RMD::get_digest(byte* out)
+{
+ pimpl_->rmd_.Final(out);
+}
+
+
+// Update the current digest
+void RMD::update(const byte* in, unsigned int sz)
+{
+ pimpl_->rmd_.Update(in, sz);
+}
+
+
+// HMAC_MD5 Implementation
+struct HMAC_MD5::HMAC_MD5Impl {
+ TaoCrypt::HMAC<TaoCrypt::MD5> mac_;
+ HMAC_MD5Impl() {}
+};
+
+
+HMAC_MD5::HMAC_MD5(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_MD5Impl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_MD5::~HMAC_MD5() { ysDelete(pimpl_); }
+
+
+uint HMAC_MD5::get_digestSize() const
+{
+ return MD5_LEN;
+}
+
+
+uint HMAC_MD5::get_padSize() const
+{
+ return PAD_MD5;
+}
+
+
+// Fill out with MD5 digest from in that is sz bytes, out must be >= digest sz
+void HMAC_MD5::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with MD5 digest from previous updates
+void HMAC_MD5::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_MD5::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+// HMAC_SHA Implementation
+struct HMAC_SHA::HMAC_SHAImpl {
+ TaoCrypt::HMAC<TaoCrypt::SHA> mac_;
+ HMAC_SHAImpl() {}
+};
+
+
+HMAC_SHA::HMAC_SHA(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_SHAImpl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_SHA::~HMAC_SHA() { ysDelete(pimpl_); }
+
+
+uint HMAC_SHA::get_digestSize() const
+{
+ return SHA_LEN;
+}
+
+
+uint HMAC_SHA::get_padSize() const
+{
+ return PAD_SHA;
+}
+
+
+// Fill out with SHA digest from in that is sz bytes, out must be >= digest sz
+void HMAC_SHA::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with SHA digest from previous updates
+void HMAC_SHA::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_SHA::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+
+// HMAC_RMD Implementation
+struct HMAC_RMD::HMAC_RMDImpl {
+ TaoCrypt::HMAC<TaoCrypt::RIPEMD160> mac_;
+ HMAC_RMDImpl() {}
+};
+
+
+HMAC_RMD::HMAC_RMD(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_RMDImpl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_RMD::~HMAC_RMD() { ysDelete(pimpl_); }
+
+
+uint HMAC_RMD::get_digestSize() const
+{
+ return RMD_LEN;
+}
+
+
+uint HMAC_RMD::get_padSize() const
+{
+ return PAD_RMD;
+}
+
+
+// Fill out with RMD digest from in that is sz bytes, out must be >= digest sz
+void HMAC_RMD::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with RMD digest from previous updates
+void HMAC_RMD::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_RMD::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+struct DES::DESImpl {
+ TaoCrypt::DES_CBC_Encryption encryption;
+ TaoCrypt::DES_CBC_Decryption decryption;
+};
+
+
+DES::DES() : pimpl_(new (ys) DESImpl) {}
+
+DES::~DES() { ysDelete(pimpl_); }
+
+
+void DES::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, DES_KEY_SZ, iv);
+}
+
+
+void DES::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, DES_KEY_SZ, iv);
+}
+
+// DES encrypt plain of length sz into cipher
+void DES::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// DES decrypt cipher of length sz into plain
+void DES::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+struct DES_EDE::DES_EDEImpl {
+ TaoCrypt::DES_EDE3_CBC_Encryption encryption;
+ TaoCrypt::DES_EDE3_CBC_Decryption decryption;
+};
+
+
+DES_EDE::DES_EDE() : pimpl_(new (ys) DES_EDEImpl) {}
+
+DES_EDE::~DES_EDE() { ysDelete(pimpl_); }
+
+
+void DES_EDE::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, DES_EDE_KEY_SZ, iv);
+}
+
+
+void DES_EDE::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, DES_EDE_KEY_SZ, iv);
+}
+
+
+// 3DES encrypt plain of length sz into cipher
+void DES_EDE::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// 3DES decrypt cipher of length sz into plain
+void DES_EDE::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+// Implementation of alledged RC4
+struct RC4::RC4Impl {
+ TaoCrypt::ARC4::Encryption encryption;
+ TaoCrypt::ARC4::Decryption decryption;
+};
+
+
+RC4::RC4() : pimpl_(new (ys) RC4Impl) {}
+
+RC4::~RC4() { ysDelete(pimpl_); }
+
+
+void RC4::set_encryptKey(const byte* k, const byte*)
+{
+ pimpl_->encryption.SetKey(k, RC4_KEY_SZ);
+}
+
+
+void RC4::set_decryptKey(const byte* k, const byte*)
+{
+ pimpl_->decryption.SetKey(k, RC4_KEY_SZ);
+}
+
+
+// RC4 encrypt plain of length sz into cipher
+void RC4::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// RC4 decrypt cipher of length sz into plain
+void RC4::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+
+// Implementation of AES
+struct AES::AESImpl {
+ TaoCrypt::AES_CBC_Encryption encryption;
+ TaoCrypt::AES_CBC_Decryption decryption;
+ unsigned int keySz_;
+
+ AESImpl(unsigned int ks) : keySz_(ks) {}
+};
+
+
+AES::AES(unsigned int ks) : pimpl_(new (ys) AESImpl(ks)) {}
+
+AES::~AES() { ysDelete(pimpl_); }
+
+
+int AES::get_keySize() const
+{
+ return pimpl_->keySz_;
+}
+
+
+void AES::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, pimpl_->keySz_, iv);
+}
+
+
+void AES::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, pimpl_->keySz_, iv);
+}
+
+
+// AES encrypt plain of length sz into cipher
+void AES::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// AES decrypt cipher of length sz into plain
+void AES::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+struct RandomPool::RandomImpl {
+ TaoCrypt::RandomNumberGenerator RNG_;
+};
+
+RandomPool::RandomPool() : pimpl_(new (ys) RandomImpl) {}
+
+RandomPool::~RandomPool() { ysDelete(pimpl_); }
+
+int RandomPool::GetError() const
+{
+ return pimpl_->RNG_.GetError();
+}
+
+void RandomPool::Fill(opaque* dst, uint sz) const
+{
+ pimpl_->RNG_.GenerateBlock(dst, sz);
+}
+
+
+// Implementation of DSS Authentication
+struct DSS::DSSImpl {
+ void SetPublic (const byte*, unsigned int);
+ void SetPrivate(const byte*, unsigned int);
+ TaoCrypt::DSA_PublicKey publicKey_;
+ TaoCrypt::DSA_PrivateKey privateKey_;
+};
+
+
+// Decode and store the public key
+void DSS::DSSImpl::SetPublic(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ publicKey_.Initialize(source);
+}
+
+
+// Decode and store the public key
+void DSS::DSSImpl::SetPrivate(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ privateKey_.Initialize(source);
+ publicKey_ = TaoCrypt::DSA_PublicKey(privateKey_);
+
+}
+
+
+// Set public or private key
+DSS::DSS(const byte* key, unsigned int sz, bool publicKey)
+ : pimpl_(new (ys) DSSImpl)
+{
+ if (publicKey)
+ pimpl_->SetPublic(key, sz);
+ else
+ pimpl_->SetPrivate(key, sz);
+}
+
+
+DSS::~DSS()
+{
+ ysDelete(pimpl_);
+}
+
+
+uint DSS::get_signatureLength() const
+{
+ return pimpl_->publicKey_.SignatureLength();
+}
+
+
+// DSS Sign message of length sz into sig
+void DSS::sign(byte* sig, const byte* sha_digest, unsigned int /* shaSz */,
+ const RandomPool& random)
+{
+ using namespace TaoCrypt;
+
+ DSA_Signer signer(pimpl_->privateKey_);
+ signer.Sign(sha_digest, sig, random.pimpl_->RNG_);
+}
+
+
+// DSS Verify message of length sz against sig, is it correct?
+bool DSS::verify(const byte* sha_digest, unsigned int /* shaSz */,
+ const byte* sig, unsigned int /* sigSz */)
+{
+ using namespace TaoCrypt;
+
+ DSA_Verifier ver(pimpl_->publicKey_);
+ return ver.Verify(sha_digest, sig);
+}
+
+
+// Implementation of RSA key interface
+struct RSA::RSAImpl {
+ void SetPublic (const byte*, unsigned int);
+ void SetPrivate(const byte*, unsigned int);
+ TaoCrypt::RSA_PublicKey publicKey_;
+ TaoCrypt::RSA_PrivateKey privateKey_;
+};
+
+
+// Decode and store the public key
+void RSA::RSAImpl::SetPublic(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ publicKey_.Initialize(source);
+}
+
+
+// Decode and store the private key
+void RSA::RSAImpl::SetPrivate(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ privateKey_.Initialize(source);
+ publicKey_ = TaoCrypt::RSA_PublicKey(privateKey_);
+}
+
+
+// Set public or private key
+RSA::RSA(const byte* key, unsigned int sz, bool publicKey)
+ : pimpl_(new (ys) RSAImpl)
+{
+ if (publicKey)
+ pimpl_->SetPublic(key, sz);
+ else
+ pimpl_->SetPrivate(key, sz);
+}
+
+RSA::~RSA()
+{
+ ysDelete(pimpl_);
+}
+
+
+// get cipher text length, varies on key size
+unsigned int RSA::get_cipherLength() const
+{
+ return pimpl_->publicKey_.FixedCiphertextLength();
+}
+
+
+// get signautre length, varies on key size
+unsigned int RSA::get_signatureLength() const
+{
+ return get_cipherLength();
+}
+
+
+// RSA Sign message of length sz into sig
+void RSA::sign(byte* sig, const byte* message, unsigned int sz,
+ const RandomPool& random)
+{
+ TaoCrypt::RSAES_Decryptor dec(pimpl_->privateKey_);
+ dec.SSL_Sign(message, sz, sig, random.pimpl_->RNG_);
+}
+
+
+// RSA Verify message of length sz against sig
+bool RSA::verify(const byte* message, unsigned int sz, const byte* sig,
+ unsigned int)
+{
+ TaoCrypt::RSAES_Encryptor enc(pimpl_->publicKey_);
+ return enc.SSL_Verify(message, sz, sig);
+}
+
+
+// RSA public encrypt plain of length sz into cipher
+void RSA::encrypt(byte* cipher, const byte* plain, unsigned int sz,
+ const RandomPool& random)
+{
+
+ TaoCrypt::RSAES_Encryptor enc(pimpl_->publicKey_);
+ enc.Encrypt(plain, sz, cipher, random.pimpl_->RNG_);
+}
+
+
+// RSA private decrypt cipher of length sz into plain
+void RSA::decrypt(byte* plain, const byte* cipher, unsigned int sz,
+ const RandomPool& random)
+{
+ TaoCrypt::RSAES_Decryptor dec(pimpl_->privateKey_);
+ dec.Decrypt(cipher, sz, plain, random.pimpl_->RNG_);
+}
+
+
+struct Integer::IntegerImpl {
+ TaoCrypt::Integer int_;
+
+ IntegerImpl() {}
+ explicit IntegerImpl(const TaoCrypt::Integer& i) : int_(i) {}
+};
+
+Integer::Integer() : pimpl_(new (ys) IntegerImpl) {}
+
+Integer::~Integer() { ysDelete(pimpl_); }
+
+
+
+Integer::Integer(const Integer& other) : pimpl_(new (ys)
+ IntegerImpl(other.pimpl_->int_))
+{}
+
+
+Integer& Integer::operator=(const Integer& that)
+{
+ pimpl_->int_ = that.pimpl_->int_;
+
+ return *this;
+}
+
+
+void Integer::assign(const byte* num, unsigned int sz)
+{
+ pimpl_->int_ = TaoCrypt::Integer(num, sz);
+}
+
+
+struct DiffieHellman::DHImpl {
+ TaoCrypt::DH dh_;
+ TaoCrypt::RandomNumberGenerator& ranPool_;
+ byte* publicKey_;
+ byte* privateKey_;
+ byte* agreedKey_;
+
+ DHImpl(TaoCrypt::RandomNumberGenerator& r) : ranPool_(r), publicKey_(0),
+ privateKey_(0), agreedKey_(0) {}
+ ~DHImpl()
+ {
+ ysArrayDelete(agreedKey_);
+ ysArrayDelete(privateKey_);
+ ysArrayDelete(publicKey_);
+ }
+
+ DHImpl(const DHImpl& that) : dh_(that.dh_), ranPool_(that.ranPool_),
+ publicKey_(0), privateKey_(0), agreedKey_(0)
+ {
+ uint length = dh_.GetByteLength();
+ AllocKeys(length, length, length);
+ }
+
+ void AllocKeys(unsigned int pubSz, unsigned int privSz, unsigned int agrSz)
+ {
+ publicKey_ = new (ys) byte[pubSz];
+ privateKey_ = new (ys) byte[privSz];
+ agreedKey_ = new (ys) byte[agrSz];
+ }
+};
+
+
+
+/*
+// server Side DH, server's view
+DiffieHellman::DiffieHellman(const char* file, const RandomPool& random)
+ : pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using namespace TaoCrypt;
+ Source source;
+ FileSource(file, source);
+ if (source.size() == 0)
+ return; // TODO add error state, and force check
+ HexDecoder hd(source);
+
+ pimpl_->dh_.Initialize(source);
+
+ uint length = pimpl_->dh_.GetByteLength();
+
+ pimpl_->AllocKeys(length, length, length);
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+*/
+
+
+// server Side DH, client's view
+DiffieHellman::DiffieHellman(const byte* p, unsigned int pSz, const byte* g,
+ unsigned int gSz, const byte* pub,
+ unsigned int pubSz, const RandomPool& random)
+ : pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using TaoCrypt::Integer;
+
+ pimpl_->dh_.Initialize(Integer(p, pSz).Ref(), Integer(g, gSz).Ref());
+ pimpl_->publicKey_ = new (ys) opaque[pubSz];
+ memcpy(pimpl_->publicKey_, pub, pubSz);
+}
+
+
+// Server Side DH, server's view
+DiffieHellman::DiffieHellman(const Integer& p, const Integer& g,
+ const RandomPool& random)
+: pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using TaoCrypt::Integer;
+
+ pimpl_->dh_.Initialize(p.pimpl_->int_, g.pimpl_->int_);
+
+ uint length = pimpl_->dh_.GetByteLength();
+
+ pimpl_->AllocKeys(length, length, length);
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+
+DiffieHellman::~DiffieHellman() { ysDelete(pimpl_); }
+
+
+// Client side and view, use server that for p and g
+DiffieHellman::DiffieHellman(const DiffieHellman& that)
+ : pimpl_(new (ys) DHImpl(*that.pimpl_))
+{
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+
+
+DiffieHellman& DiffieHellman::operator=(const DiffieHellman& that)
+{
+ pimpl_->dh_ = that.pimpl_->dh_;
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+ return *this;
+}
+
+
+void DiffieHellman::makeAgreement(const byte* other)
+{
+ pimpl_->dh_.Agree(pimpl_->agreedKey_, pimpl_->privateKey_, other);
+}
+
+
+uint DiffieHellman::get_agreedKeyLength() const
+{
+ return pimpl_->dh_.GetByteLength();
+}
+
+
+const byte* DiffieHellman::get_agreedKey() const
+{
+ return pimpl_->agreedKey_;
+}
+
+
+const byte* DiffieHellman::get_publicKey() const
+{
+ return pimpl_->publicKey_;
+}
+
+
+void DiffieHellman::set_sizes(int& pSz, int& gSz, int& pubSz) const
+{
+ using TaoCrypt::Integer;
+ Integer p = pimpl_->dh_.GetP();
+ Integer g = pimpl_->dh_.GetG();
+
+ pSz = p.ByteCount();
+ gSz = g.ByteCount();
+ pubSz = pimpl_->dh_.GetByteLength();
+}
+
+
+void DiffieHellman::get_parms(byte* bp, byte* bg, byte* bpub) const
+{
+ using TaoCrypt::Integer;
+ Integer p = pimpl_->dh_.GetP();
+ Integer g = pimpl_->dh_.GetG();
+
+ p.Encode(bp, p.ByteCount());
+ g.Encode(bg, g.ByteCount());
+ memcpy(bpub, pimpl_->publicKey_, pimpl_->dh_.GetByteLength());
+}
+
+
+// convert PEM file to DER x509 type
+x509* PemToDer(const char* fname, CertType type)
+{
+ using namespace TaoCrypt;
+
+ char header[80];
+ char footer[80];
+
+ if (type == Cert) {
+ strncpy(header, "-----BEGIN CERTIFICATE-----", sizeof(header));
+ strncpy(footer, "-----END CERTIFICATE-----", sizeof(footer));
+ } else {
+ strncpy(header, "-----BEGIN RSA PRIVATE KEY-----", sizeof(header));
+ strncpy(footer, "-----END RSA PRIVATE KEY-----", sizeof(header));
+ }
+
+ FILE* file = fopen(fname, "rb");
+ if (!file)
+ return 0;
+
+ long begin = -1;
+ long end = 0;
+ bool foundEnd = false;
+
+ char line[80];
+
+ while(fgets(line, sizeof(line), file))
+ if (strncmp(header, line, strlen(header)) == 0) {
+ begin = ftell(file);
+ break;
+ }
+
+ while(fgets(line, sizeof(line), file))
+ if (strncmp(footer, line, strlen(footer)) == 0) {
+ foundEnd = true;
+ break;
+ }
+ else
+ end = ftell(file);
+
+ if (begin == -1 || !foundEnd) {
+ fclose(file);
+ return 0;
+ }
+
+ input_buffer tmp(end - begin);
+ fseek(file, begin, SEEK_SET);
+ size_t bytes = fread(tmp.get_buffer(), end - begin, 1, file);
+ if (bytes != 1) {
+ fclose(file);
+ return 0;
+ }
+
+ Source der(tmp.get_buffer(), end - begin);
+ Base64Decoder b64Dec(der);
+
+ uint sz = der.size();
+ mySTL::auto_ptr<x509> x(new (ys) x509(sz), ysDelete);
+ memcpy(x->use_buffer(), der.get_buffer(), sz);
+
+ fclose(file);
+ return x.release();
+}
+
+
+} // namespace
+
+
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+namespace yaSSL {
+template void ysDelete<DiffieHellman::DHImpl>(DiffieHellman::DHImpl*);
+template void ysDelete<Integer::IntegerImpl>(Integer::IntegerImpl*);
+template void ysDelete<RSA::RSAImpl>(RSA::RSAImpl*);
+template void ysDelete<DSS::DSSImpl>(DSS::DSSImpl*);
+template void ysDelete<RandomPool::RandomImpl>(RandomPool::RandomImpl*);
+template void ysDelete<AES::AESImpl>(AES::AESImpl*);
+template void ysDelete<RC4::RC4Impl>(RC4::RC4Impl*);
+template void ysDelete<DES_EDE::DES_EDEImpl>(DES_EDE::DES_EDEImpl*);
+template void ysDelete<DES::DESImpl>(DES::DESImpl*);
+template void ysDelete<HMAC_RMD::HMAC_RMDImpl>(HMAC_RMD::HMAC_RMDImpl*);
+template void ysDelete<HMAC_SHA::HMAC_SHAImpl>(HMAC_SHA::HMAC_SHAImpl*);
+template void ysDelete<HMAC_MD5::HMAC_MD5Impl>(HMAC_MD5::HMAC_MD5Impl*);
+template void ysDelete<RMD::RMDImpl>(RMD::RMDImpl*);
+template void ysDelete<SHA::SHAImpl>(SHA::SHAImpl*);
+template void ysDelete<MD5::MD5Impl>(MD5::MD5Impl*);
+}
+#endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+
+#endif // !USE_CRYPTOPP_LIB
diff --git a/extra/yassl/src/dummy.cpp b/extra/yassl/src/dummy.cpp
new file mode 100644
index 00000000000..19b7fe887cd
--- /dev/null
+++ b/extra/yassl/src/dummy.cpp
@@ -0,0 +1,4 @@
+/*
+ To make libtool always use a C++ linker when compiling with yaSSL we need
+ to add a dummy C++ file to the source list.
+*/
diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp
new file mode 100644
index 00000000000..45dfb6fa032
--- /dev/null
+++ b/extra/yassl/src/handshake.cpp
@@ -0,0 +1,1011 @@
+/* handshake.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* The handshake source implements functions for creating and reading
+ * the various handshake messages.
+ */
+
+#include "runtime.hpp"
+#include "handshake.hpp"
+#include "yassl_int.hpp"
+
+
+namespace yaSSL {
+
+using mySTL::min;
+
+
+// Build a client hello message from cipher suites and compression method
+void buildClientHello(SSL& ssl, ClientHello& hello,
+ CompressionMethod compression = no_compression)
+{
+ ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
+ if (ssl.getSecurity().get_resuming()) {
+ hello.id_len_ = ID_LEN;
+ memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN);
+ }
+ else
+ hello.id_len_ = 0;
+ hello.suite_len_ = ssl.getSecurity().get_parms().suites_size_;
+ memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_,
+ hello.suite_len_);
+ hello.comp_len_ = 1;
+ hello.compression_methods_ = compression;
+
+ hello.set_length(sizeof(ProtocolVersion) +
+ RAN_LEN +
+ hello.id_len_ + sizeof(hello.id_len_) +
+ hello.suite_len_ + sizeof(hello.suite_len_) +
+ hello.comp_len_ + sizeof(hello.comp_len_));
+}
+
+
+// Build a server hello message
+void buildServerHello(SSL& ssl, ServerHello& hello)
+{
+ if (ssl.getSecurity().get_resuming()) {
+ memcpy(hello.random_,ssl.getSecurity().get_connection().server_random_,
+ RAN_LEN);
+ memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN);
+ }
+ else {
+ ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
+ ssl.getCrypto().get_random().Fill(hello.session_id_, ID_LEN);
+ }
+ hello.id_len_ = ID_LEN;
+ ssl.set_sessionID(hello.session_id_);
+
+ hello.cipher_suite_[0] = ssl.getSecurity().get_parms().suite_[0];
+ hello.cipher_suite_[1] = ssl.getSecurity().get_parms().suite_[1];
+ hello.compression_method_ = no_compression;
+
+ hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + ID_LEN +
+ sizeof(hello.id_len_) + SUITE_LEN + SIZEOF_ENUM);
+}
+
+
+// add handshake from buffer into md5 and sha hashes, use handshake header
+void hashHandShake(SSL& ssl, const input_buffer& input, uint sz)
+{
+ const opaque* buffer = input.get_buffer() + input.get_current() -
+ HANDSHAKE_HEADER;
+ sz += HANDSHAKE_HEADER;
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+}
+
+
+// locals
+namespace {
+
+// Write a plaintext record to buffer
+void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr,
+ const Message& msg)
+{
+ buffer.allocate(RECORD_HEADER + rlHdr.length_);
+ buffer << rlHdr << msg;
+}
+
+
+// Write a plaintext record to buffer
+void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr,
+ const HandShakeHeader& hsHdr, const HandShakeBase& shake)
+{
+ buffer.allocate(RECORD_HEADER + rlHdr.length_);
+ buffer << rlHdr << hsHdr << shake;
+}
+
+
+// Build Record Layer header for Message without handshake header
+void buildHeader(SSL& ssl, RecordLayerHeader& rlHeader, const Message& msg)
+{
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ rlHeader.type_ = msg.get_type();
+ rlHeader.version_.major_ = pv.major_;
+ rlHeader.version_.minor_ = pv.minor_;
+ rlHeader.length_ = msg.get_length();
+}
+
+
+// Build HandShake and RecordLayer Headers for handshake output
+void buildHeaders(SSL& ssl, HandShakeHeader& hsHeader,
+ RecordLayerHeader& rlHeader, const HandShakeBase& shake)
+{
+ int sz = shake.get_length();
+
+ hsHeader.set_type(shake.get_type());
+ hsHeader.set_length(sz);
+
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ rlHeader.type_ = handshake;
+ rlHeader.version_.major_ = pv.major_;
+ rlHeader.version_.minor_ = pv.minor_;
+ rlHeader.length_ = sz + HANDSHAKE_HEADER;
+}
+
+
+// add handshake from buffer into md5 and sha hashes, exclude record header
+void hashHandShake(SSL& ssl, const output_buffer& output)
+{
+ uint sz = output.get_size() - RECORD_HEADER;
+
+ const opaque* buffer = output.get_buffer() + RECORD_HEADER;
+
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+}
+
+
+// calculate MD5 hash for finished
+void buildMD5(SSL& ssl, Finished& fin, const opaque* sender)
+{
+
+ opaque md5_result[MD5_LEN];
+ opaque md5_inner[SIZEOF_SENDER + SECRET_LEN + PAD_MD5];
+ opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make md5 inner
+ memcpy(md5_inner, sender, SIZEOF_SENDER);
+ memcpy(&md5_inner[SIZEOF_SENDER], master_secret, SECRET_LEN);
+ memcpy(&md5_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_MD5);
+
+ ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
+ sizeof(md5_inner));
+
+ // make md5 outer
+ memcpy(md5_outer, master_secret, SECRET_LEN);
+ memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
+ memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
+
+ ssl.useHashes().use_MD5().get_digest(fin.set_md5(), md5_outer,
+ sizeof(md5_outer));
+}
+
+
+// calculate SHA hash for finished
+void buildSHA(SSL& ssl, Finished& fin, const opaque* sender)
+{
+
+ opaque sha_result[SHA_LEN];
+ opaque sha_inner[SIZEOF_SENDER + SECRET_LEN + PAD_SHA];
+ opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make sha inner
+ memcpy(sha_inner, sender, SIZEOF_SENDER);
+ memcpy(&sha_inner[SIZEOF_SENDER], master_secret, SECRET_LEN);
+ memcpy(&sha_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_SHA);
+
+ ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
+ sizeof(sha_inner));
+
+ // make sha outer
+ memcpy(sha_outer, master_secret, SECRET_LEN);
+ memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
+ memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
+
+ ssl.useHashes().use_SHA().get_digest(fin.set_sha(), sha_outer,
+ sizeof(sha_outer));
+}
+
+
+// decrypt input message in place, store size in case needed later
+void decrypt_message(SSL& ssl, input_buffer& input, uint sz)
+{
+ input_buffer plain(sz);
+ opaque* cipher = input.get_buffer() + input.get_current();
+
+ ssl.useCrypto().use_cipher().decrypt(plain.get_buffer(), cipher, sz);
+ memcpy(cipher, plain.get_buffer(), sz);
+ ssl.useSecurity().use_parms().encrypt_size_ = sz;
+}
+
+
+// write headers, handshake hash, mac, pad, and encrypt
+void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output)
+{
+ uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ;
+ uint sz = RECORD_HEADER + HANDSHAKE_HEADER + finishedSz + digestSz;
+ uint pad = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ sz += 1; // pad byte
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+ pad = (sz - RECORD_HEADER) % blockSz;
+ pad = blockSz - pad;
+ sz += pad;
+ }
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ buildHeaders(ssl, hsHeader, rlHeader, fin);
+ rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
+ // and pad, hanshake doesn't
+ output.allocate(sz);
+ output << rlHeader << hsHeader << fin;
+
+ hashHandShake(ssl, output);
+ opaque digest[SHA_LEN]; // max size
+ if (ssl.isTLS())
+ TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, handshake);
+ else
+ hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, handshake);
+ output.write(digest, digestSz);
+
+ if (ssl.getSecurity().get_parms().cipher_type_ == block)
+ for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets
+ // pad value too
+ input_buffer cipher(rlHeader.length_);
+ ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(),
+ output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER);
+ output.set_current(RECORD_HEADER);
+ output.write(cipher.get_buffer(), cipher.get_capacity());
+}
+
+
+// build an encrypted data or alert message for output
+void buildMessage(SSL& ssl, output_buffer& output, const Message& msg)
+{
+ uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ uint sz = RECORD_HEADER + msg.get_length() + digestSz;
+ uint pad = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ sz += 1; // pad byte
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+ pad = (sz - RECORD_HEADER) % blockSz;
+ pad = blockSz - pad;
+ sz += pad;
+ }
+
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, msg);
+ rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
+ // and pad, hanshake doesn't
+ output.allocate(sz);
+ output << rlHeader << msg;
+
+ opaque digest[SHA_LEN]; // max size
+ if (ssl.isTLS())
+ TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, msg.get_type());
+ else
+ hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, msg.get_type());
+ output.write(digest, digestSz);
+
+ if (ssl.getSecurity().get_parms().cipher_type_ == block)
+ for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets
+ // pad value too
+ input_buffer cipher(rlHeader.length_);
+ ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(),
+ output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER);
+ output.set_current(RECORD_HEADER);
+ output.write(cipher.get_buffer(), cipher.get_capacity());
+}
+
+
+// build alert message
+void buildAlert(SSL& ssl, output_buffer& output, const Alert& alert)
+{
+ if (ssl.getSecurity().get_parms().pending_ == false) // encrypted
+ buildMessage(ssl, output, alert);
+ else {
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, alert);
+ buildOutput(output, rlHeader, alert);
+ }
+}
+
+
+// build TLS finished message
+void buildFinishedTLS(SSL& ssl, Finished& fin, const opaque* sender)
+{
+ opaque handshake_hash[FINISHED_SZ];
+
+ ssl.useHashes().use_MD5().get_digest(handshake_hash);
+ ssl.useHashes().use_SHA().get_digest(&handshake_hash[MD5_LEN]);
+
+ const opaque* side;
+ if ( strncmp((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
+ side = tls_client;
+ else
+ side = tls_server;
+
+ PRF(fin.set_md5(), TLS_FINISHED_SZ,
+ ssl.getSecurity().get_connection().master_secret_, SECRET_LEN,
+ side, FINISHED_LABEL_SZ,
+ handshake_hash, FINISHED_SZ);
+
+ fin.set_length(TLS_FINISHED_SZ); // shorter length for TLS
+}
+
+
+// compute p_hash for MD5 or SHA-1 for TLSv1 PRF
+void p_hash(output_buffer& result, const output_buffer& secret,
+ const output_buffer& seed, MACAlgorithm hash)
+{
+ uint len = hash == md5 ? MD5_LEN : SHA_LEN;
+ uint times = result.get_capacity() / len;
+ uint lastLen = result.get_capacity() % len;
+ opaque previous[SHA_LEN]; // max size
+ opaque current[SHA_LEN]; // max size
+ mySTL::auto_ptr<Digest> hmac(ysDelete);
+
+ if (lastLen) times += 1;
+
+ if (hash == md5)
+ hmac.reset(new (ys) HMAC_MD5(secret.get_buffer(), secret.get_size()));
+ else
+ hmac.reset(new (ys) HMAC_SHA(secret.get_buffer(), secret.get_size()));
+ // A0 = seed
+ hmac->get_digest(previous, seed.get_buffer(), seed.get_size());// A1
+ uint lastTime = times - 1;
+
+ for (uint i = 0; i < times; i++) {
+ hmac->update(previous, len);
+ hmac->get_digest(current, seed.get_buffer(), seed.get_size());
+
+ if (lastLen && (i == lastTime))
+ result.write(current, lastLen);
+ else {
+ result.write(current, len);
+ //memcpy(previous, current, len);
+ hmac->get_digest(previous, previous, len);
+ }
+ }
+}
+
+
+// calculate XOR for TLSv1 PRF
+void get_xor(byte *digest, uint digLen, output_buffer& md5,
+ output_buffer& sha)
+{
+ for (uint i = 0; i < digLen; i++)
+ digest[i] = md5[AUTO] ^ sha[AUTO];
+}
+
+
+// build MD5 part of certificate verify
+void buildMD5_CertVerify(SSL& ssl, byte* digest)
+{
+ opaque md5_result[MD5_LEN];
+ opaque md5_inner[SECRET_LEN + PAD_MD5];
+ opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make md5 inner
+ memcpy(md5_inner, master_secret, SECRET_LEN);
+ memcpy(&md5_inner[SECRET_LEN], PAD1, PAD_MD5);
+
+ ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
+ sizeof(md5_inner));
+
+ // make md5 outer
+ memcpy(md5_outer, master_secret, SECRET_LEN);
+ memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
+ memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
+
+ ssl.useHashes().use_MD5().get_digest(digest, md5_outer, sizeof(md5_outer));
+}
+
+
+// build SHA part of certificate verify
+void buildSHA_CertVerify(SSL& ssl, byte* digest)
+{
+ opaque sha_result[SHA_LEN];
+ opaque sha_inner[SECRET_LEN + PAD_SHA];
+ opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make sha inner
+ memcpy(sha_inner, master_secret, SECRET_LEN);
+ memcpy(&sha_inner[SECRET_LEN], PAD1, PAD_SHA);
+
+ ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
+ sizeof(sha_inner));
+
+ // make sha outer
+ memcpy(sha_outer, master_secret, SECRET_LEN);
+ memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
+ memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
+
+ ssl.useHashes().use_SHA().get_digest(digest, sha_outer, sizeof(sha_outer));
+}
+
+
+} // namespace for locals
+
+
+// some clients still send sslv2 client hello
+void ProcessOldClientHello(input_buffer& input, SSL& ssl)
+{
+ byte b0 = input[AUTO];
+ byte b1 = input[AUTO];
+
+ uint16 sz = ((b0 & 0x7f) << 8) | b1;
+
+ // hashHandShake manually
+ const opaque* buffer = input.get_buffer() + input.get_current();
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+
+ b1 = input[AUTO]; // does this value mean client_hello?
+
+ ClientHello ch;
+ ch.client_version_.major_ = input[AUTO];
+ ch.client_version_.minor_ = input[AUTO];
+
+ byte len[2];
+
+ input.read(len, sizeof(len));
+ ato16(len, ch.suite_len_);
+
+ input.read(len, sizeof(len));
+ uint16 sessionLen;
+ ato16(len, sessionLen);
+ ch.id_len_ = sessionLen;
+
+ input.read(len, sizeof(len));
+ uint16 randomLen;
+ ato16(len, randomLen);
+
+ int j = 0;
+ for (uint16 i = 0; i < ch.suite_len_; i += 3) {
+ byte first = input[AUTO];
+ if (first) // sslv2 type
+ input.read(len, SUITE_LEN); // skip
+ else {
+ input.read(&ch.cipher_suites_[j], SUITE_LEN);
+ j += SUITE_LEN;
+ }
+ }
+ ch.suite_len_ = j;
+
+ if (ch.id_len_)
+ input.read(ch.session_id_, ch.id_len_);
+
+ if (randomLen < RAN_LEN)
+ memset(ch.random_, 0, RAN_LEN - randomLen);
+ input.read(&ch.random_[RAN_LEN - randomLen], randomLen);
+
+
+ ch.Process(input, ssl);
+}
+
+
+// Build a finished message, see 7.6.9
+void buildFinished(SSL& ssl, Finished& fin, const opaque* sender)
+{
+ // store current states, building requires get_digest which resets state
+ MD5 md5(ssl.getHashes().get_MD5());
+ SHA sha(ssl.getHashes().get_SHA());
+
+ if (ssl.isTLS())
+ buildFinishedTLS(ssl, fin, sender);
+ else {
+ buildMD5(ssl, fin, sender);
+ buildSHA(ssl, fin, sender);
+ }
+
+ // restore
+ ssl.useHashes().use_MD5() = md5;
+ ssl.useHashes().use_SHA() = sha;
+}
+
+
+/* compute SSLv3 HMAC into digest see
+ * buffer is of sz size and includes HandShake Header but not a Record Header
+ * verify means to check peers hmac
+*/
+void hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
+ ContentType content, bool verify)
+{
+ Digest& mac = ssl.useCrypto().use_digest();
+ opaque inner[SHA_LEN + PAD_MD5 + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ];
+ opaque outer[SHA_LEN + PAD_MD5 + SHA_LEN];
+ opaque result[SHA_LEN]; // max possible sizes
+ uint digestSz = mac.get_digestSize(); // actual sizes
+ uint padSz = mac.get_padSize();
+ uint innerSz = digestSz + padSz + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ;
+ uint outerSz = digestSz + padSz + digestSz;
+
+ // data
+ const opaque* mac_secret = ssl.get_macSecret(verify);
+ opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ opaque length[LENGTH_SZ];
+ c16toa(sz, length);
+ c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
+
+ // make inner
+ memcpy(inner, mac_secret, digestSz);
+ memcpy(&inner[digestSz], PAD1, padSz);
+ memcpy(&inner[digestSz + padSz], seq, SEQ_SZ);
+ inner[digestSz + padSz + SEQ_SZ] = content;
+ memcpy(&inner[digestSz + padSz + SEQ_SZ + SIZEOF_ENUM], length, LENGTH_SZ);
+
+ mac.update(inner, innerSz);
+ mac.get_digest(result, buffer, sz); // append content buffer
+
+ // make outer
+ memcpy(outer, mac_secret, digestSz);
+ memcpy(&outer[digestSz], PAD2, padSz);
+ memcpy(&outer[digestSz + padSz], result, digestSz);
+
+ mac.get_digest(digest, outer, outerSz);
+}
+
+
+// TLS type HAMC
+void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
+ ContentType content, bool verify)
+{
+ mySTL::auto_ptr<Digest> hmac(ysDelete);
+ opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ opaque length[LENGTH_SZ];
+ opaque inner[SIZEOF_ENUM + VERSION_SZ + LENGTH_SZ]; // type + version + len
+
+ c16toa(sz, length);
+ c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
+
+ MACAlgorithm algo = ssl.getSecurity().get_parms().mac_algorithm_;
+
+ if (algo == sha)
+ hmac.reset(new (ys) HMAC_SHA(ssl.get_macSecret(verify), SHA_LEN));
+ else if (algo == rmd)
+ hmac.reset(new (ys) HMAC_RMD(ssl.get_macSecret(verify), RMD_LEN));
+ else
+ hmac.reset(new (ys) HMAC_MD5(ssl.get_macSecret(verify), MD5_LEN));
+
+ hmac->update(seq, SEQ_SZ); // seq_num
+ inner[0] = content; // type
+ inner[SIZEOF_ENUM] = ssl.getSecurity().get_connection().version_.major_;
+ inner[SIZEOF_ENUM + SIZEOF_ENUM] =
+ ssl.getSecurity().get_connection().version_.minor_; // version
+ memcpy(&inner[SIZEOF_ENUM + VERSION_SZ], length, LENGTH_SZ); // length
+ hmac->update(inner, sizeof(inner));
+ hmac->get_digest(digest, buffer, sz); // content
+}
+
+
+// compute TLSv1 PRF (pseudo random function using HMAC)
+void PRF(byte* digest, uint digLen, const byte* secret, uint secLen,
+ const byte* label, uint labLen, const byte* seed, uint seedLen)
+{
+ uint half = secLen / 2 + secLen % 2;
+
+ output_buffer md5_half(half);
+ output_buffer sha_half(half);
+ output_buffer labelSeed(labLen + seedLen);
+
+ md5_half.write(secret, half);
+ sha_half.write(secret + half - secLen % 2, half);
+ labelSeed.write(label, labLen);
+ labelSeed.write(seed, seedLen);
+
+ output_buffer md5_result(digLen);
+ output_buffer sha_result(digLen);
+
+ p_hash(md5_result, md5_half, labelSeed, md5);
+ p_hash(sha_result, sha_half, labelSeed, sha);
+
+ md5_result.set_current(0);
+ sha_result.set_current(0);
+ get_xor(digest, digLen, md5_result, sha_result);
+}
+
+
+// build certificate hashes
+void build_certHashes(SSL& ssl, Hashes& hashes)
+{
+ // store current states, building requires get_digest which resets state
+ MD5 md5(ssl.getHashes().get_MD5());
+ SHA sha(ssl.getHashes().get_SHA());
+
+ if (ssl.isTLS()) {
+ ssl.useHashes().use_MD5().get_digest(hashes.md5_);
+ ssl.useHashes().use_SHA().get_digest(hashes.sha_);
+ }
+ else {
+ buildMD5_CertVerify(ssl, hashes.md5_);
+ buildSHA_CertVerify(ssl, hashes.sha_);
+ }
+
+ // restore
+ ssl.useHashes().use_MD5() = md5;
+ ssl.useHashes().use_SHA() = sha;
+}
+
+
+mySTL::auto_ptr<input_buffer> null_buffer(ysDelete);
+
+// do process input requests
+mySTL::auto_ptr<input_buffer>
+DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
+{
+ ssl.getSocket().wait(); // wait for input if blocking
+ uint ready = ssl.getSocket().get_ready();
+ if (!ready) return buffered;
+
+ // add buffered data if its there
+ uint buffSz = buffered.get() ? buffered.get()->get_size() : 0;
+ input_buffer buffer(buffSz + ready);
+ if (buffSz) {
+ buffer.assign(buffered.get()->get_buffer(), buffSz);
+ buffered = null_buffer;
+ }
+
+ // add new (ys) data
+ uint read = ssl.getSocket().receive(buffer.get_buffer() + buffSz, ready);
+ buffer.add_size(read);
+ uint offset = 0;
+ const MessageFactory& mf = ssl.getFactory().getMessage();
+
+ // old style sslv2 client hello?
+ if (ssl.getSecurity().get_parms().entity_ == server_end &&
+ ssl.getStates().getServer() == clientNull)
+ if (buffer.peek() != handshake)
+ ProcessOldClientHello(buffer, ssl);
+
+ while(!buffer.eof()) {
+ // each record
+ RecordLayerHeader hdr;
+ buffer >> hdr;
+ ssl.verifyState(hdr);
+
+ // make sure we have enough input in buffer to process this record
+ if (hdr.length_ > buffer.get_remaining()) {
+ uint sz = buffer.get_remaining() + RECORD_HEADER;
+ buffered.reset(new (ys) input_buffer(sz, buffer.get_buffer() +
+ buffer.get_current() - RECORD_HEADER, sz));
+ break;
+ }
+
+ while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) {
+ // each message in record
+ if (ssl.getSecurity().get_parms().pending_ == false) // cipher on
+ decrypt_message(ssl, buffer, hdr.length_);
+ mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_), ysDelete);
+ if (!msg.get()) {
+ ssl.SetError(factory_error);
+ return buffered = null_buffer;
+ }
+ buffer >> *msg;
+ msg->Process(buffer, ssl);
+ if (ssl.GetError()) return buffered = null_buffer;
+ }
+ offset += hdr.length_ + RECORD_HEADER;
+ }
+ return buffered; // done, don't call again
+}
+
+
+// process input requests
+void processReply(SSL& ssl)
+{
+ if (ssl.GetError()) return;
+ mySTL::auto_ptr<input_buffer> buffered(ysDelete);
+
+ for (;;) {
+ mySTL::auto_ptr<input_buffer> tmp(DoProcessReply(ssl, buffered));
+ if (tmp.get()) // had only part of a record's data, call again
+ buffered = tmp;
+ else
+ break;
+ }
+}
+
+
+// send client_hello, no buffering
+void sendClientHello(SSL& ssl)
+{
+ ssl.verifyState(serverNull);
+ if (ssl.GetError()) return;
+
+ ClientHello ch(ssl.getSecurity().get_connection().version_);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ output_buffer out;
+
+ buildClientHello(ssl, ch);
+ ssl.set_random(ch.get_random(), client_end);
+ buildHeaders(ssl, hsHeader, rlHeader, ch);
+ buildOutput(out, rlHeader, hsHeader, ch);
+ hashHandShake(ssl, out);
+
+ ssl.Send(out.get_buffer(), out.get_size());
+}
+
+
+// send client key exchange
+void sendClientKeyExchange(SSL& ssl, BufferOutput buffer)
+{
+ ssl.verifyState(serverHelloDoneComplete);
+ if (ssl.GetError()) return;
+
+ ClientKeyExchange ck(ssl);
+ ck.build(ssl);
+ ssl.makeMasterSecret();
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ buildHeaders(ssl, hsHeader, rlHeader, ck);
+ buildOutput(*out.get(), rlHeader, hsHeader, ck);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send server key exchange
+void sendServerKeyExchange(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+ ServerKeyExchange sk(ssl);
+ sk.build(ssl);
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ buildHeaders(ssl, hsHeader, rlHeader, sk);
+ buildOutput(*out.get(), rlHeader, hsHeader, sk);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send change cipher
+void sendChangeCipher(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.getSecurity().get_parms().entity_ == server_end)
+ if (ssl.getSecurity().get_resuming())
+ ssl.verifyState(clientKeyExchangeComplete);
+ else
+ ssl.verifyState(clientFinishedComplete);
+ if (ssl.GetError()) return;
+
+ ChangeCipherSpec ccs;
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, ccs);
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ buildOutput(*out.get(), rlHeader, ccs);
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send finished
+void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ Finished fin;
+ buildFinished(ssl, fin, side == client_end ? client : server);
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+ cipherFinished(ssl, fin, *out.get()); // hashes handshake
+
+ if (ssl.getSecurity().get_resuming()) {
+ if (side == server_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), client); // client
+ }
+ else {
+ GetSessions().add(ssl); // store session
+ if (side == client_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), server); // server
+ }
+ ssl.useSecurity().use_connection().CleanMaster();
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send data
+int sendData(SSL& ssl, const void* buffer, int sz)
+{
+ ssl.verfiyHandShakeComplete();
+ if (ssl.GetError()) return 0;
+ int sent = 0;
+
+ for (;;) {
+ int len = min(sz - sent, MAX_RECORD_SIZE);
+ output_buffer out;
+ const Data data(len, static_cast<const opaque*>(buffer) + sent);
+
+ buildMessage(ssl, out, data);
+ ssl.Send(out.get_buffer(), out.get_size());
+
+ if (ssl.GetError()) return 0;
+ sent += len;
+ if (sent == sz) break;
+ }
+ ssl.useLog().ShowData(sent, true);
+ return sent;
+}
+
+
+// send alert
+int sendAlert(SSL& ssl, const Alert& alert)
+{
+ output_buffer out;
+ buildAlert(ssl, out, alert);
+ ssl.Send(out.get_buffer(), out.get_size());
+
+ return alert.get_length();
+}
+
+
+// process input data
+int receiveData(SSL& ssl, Data& data)
+{
+ ssl.verfiyHandShakeComplete();
+ if (ssl.GetError()) return 0;
+
+ if (!ssl.bufferedData())
+ processReply(ssl);
+ ssl.fillData(data);
+ ssl.useLog().ShowData(data.get_length());
+
+ if (ssl.GetError()) return 0;
+ return data.get_length();
+}
+
+
+// send server hello
+void sendServerHello(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.getSecurity().get_resuming())
+ ssl.verifyState(clientKeyExchangeComplete);
+ else
+ ssl.verifyState(clientHelloComplete);
+ if (ssl.GetError()) return;
+
+ ServerHello sh(ssl.getSecurity().get_connection().version_);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+
+ buildServerHello(ssl, sh);
+ ssl.set_random(sh.get_random(), server_end);
+ buildHeaders(ssl, hsHeader, rlHeader, sh);
+ buildOutput(*out.get(), rlHeader, hsHeader, sh);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send server hello done
+void sendServerHelloDone(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ ServerHelloDone shd;
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+
+ buildHeaders(ssl, hsHeader, rlHeader, shd);
+ buildOutput(*out.get(), rlHeader, hsHeader, shd);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate
+void sendCertificate(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ Certificate cert(ssl.getCrypto().get_certManager().get_cert());
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+
+ buildHeaders(ssl, hsHeader, rlHeader, cert);
+ buildOutput(*out.get(), rlHeader, hsHeader, cert);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate request
+void sendCertificateRequest(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ CertificateRequest request;
+ request.Build();
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+
+ buildHeaders(ssl, hsHeader, rlHeader, request);
+ buildOutput(*out.get(), rlHeader, hsHeader, request);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate verify
+void sendCertificateVerify(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ CertificateVerify verify;
+ verify.Build(ssl);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer, ysDelete);
+
+ buildHeaders(ssl, hsHeader, rlHeader, verify);
+ buildOutput(*out.get(), rlHeader, hsHeader, verify);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+} // namespace
diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp
new file mode 100644
index 00000000000..4827d396e81
--- /dev/null
+++ b/extra/yassl/src/lock.cpp
@@ -0,0 +1,90 @@
+/* lock.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* Locking functions
+ */
+
+#include "runtime.hpp"
+#include "lock.hpp"
+
+
+namespace yaSSL {
+
+
+#ifdef MULTI_THREADED
+ #ifdef _WIN32
+
+ Mutex::Mutex()
+ {
+ InitializeCriticalSection(&cs_);
+ }
+
+
+ Mutex::~Mutex()
+ {
+ DeleteCriticalSection(&cs_);
+ }
+
+
+ Mutex::Lock::Lock(Mutex& lm) : mutex_(lm)
+ {
+ EnterCriticalSection(&mutex_.cs_);
+ }
+
+
+ Mutex::Lock::~Lock()
+ {
+ LeaveCriticalSection(&mutex_.cs_);
+ }
+
+ #else // _WIN32
+
+ Mutex::Mutex()
+ {
+ pthread_mutex_init(&mutex_, 0);
+ }
+
+
+ Mutex::~Mutex()
+ {
+ pthread_mutex_destroy(&mutex_);
+ }
+
+
+ Mutex::Lock::Lock(Mutex& lm) : mutex_(lm)
+ {
+ pthread_mutex_lock(&mutex_.mutex_);
+ }
+
+
+ Mutex::Lock::~Lock()
+ {
+ pthread_mutex_unlock(&mutex_.mutex_);
+ }
+
+
+ #endif // _WIN32
+#endif // MULTI_THREADED
+
+
+
+} // namespace yaSSL
+
diff --git a/extra/yassl/src/log.cpp b/extra/yassl/src/log.cpp
new file mode 100644
index 00000000000..8ab351ee2b1
--- /dev/null
+++ b/extra/yassl/src/log.cpp
@@ -0,0 +1,149 @@
+/* log.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* Debug logging functions
+ */
+
+
+#include "runtime.hpp"
+#include "log.hpp"
+
+#ifdef YASSL_LOG
+ #include <time.h>
+ #include <stdio.h>
+ #include <string.h>
+#endif
+
+
+
+namespace yaSSL {
+
+
+#ifdef YASSL_LOG
+
+ enum { MAX_MSG = 81 };
+
+ Log::Log(const char* str)
+ {
+ log_ = fopen(str, "w");
+ Trace("********** Logger Attached **********");
+ }
+
+
+ Log::~Log()
+ {
+ Trace("********** Logger Detached **********");
+ fclose(log_);
+ }
+
+
+ // Trace a message
+ void Log::Trace(const char* str)
+ {
+ if (!log_) return;
+
+ time_t clicks = time(0);
+ char timeStr[32];
+
+ // get rid of newline
+ strncpy(timeStr, ctime(&clicks), sizeof(timeStr));
+ unsigned int len = strlen(timeStr);
+ timeStr[len - 1] = 0;
+
+ char msg[MAX_MSG];
+
+ strncpy(msg, timeStr, sizeof(timeStr));
+ strncat(msg, ":", 1);
+ strncat(msg, str, MAX_MSG - sizeof(timeStr) - 2);
+ strncat(msg, "\n", 1);
+ msg[MAX_MSG - 1] = 0;
+
+ fputs(msg, log_);
+ }
+
+
+ #if defined(_WIN32) || defined(__MACH__) || defined(__hpux__)
+ typedef int socklen_t;
+ #endif
+
+
+ // write tcp address
+ void Log::ShowTCP(socket_t fd, bool ended)
+ {
+ sockaddr_in peeraddr;
+ socklen_t len = sizeof(peeraddr);
+ if (getpeername(fd, (sockaddr*)&peeraddr, &len) != 0)
+ return;
+
+ const char* p = reinterpret_cast<const char*>(&peeraddr.sin_addr);
+ char msg[MAX_MSG];
+ char number[16];
+
+ if (ended)
+ strncpy(msg, "yaSSL conn DONE w/ peer ", 26);
+ else
+ strncpy(msg, "yaSSL conn BEGUN w/ peer ", 26);
+ for (int i = 0; i < 4; ++i) {
+ sprintf(number, "%u", static_cast<unsigned short>(p[i]));
+ strncat(msg, number, 8);
+ if (i < 3)
+ strncat(msg, ".", 1);
+ }
+ strncat(msg, " port ", 8);
+ sprintf(number, "%d", htons(peeraddr.sin_port));
+ strncat(msg, number, 8);
+
+ msg[MAX_MSG - 1] = 0;
+ Trace(msg);
+ }
+
+
+ // log processed data
+ void Log::ShowData(uint bytes, bool sent)
+ {
+ char msg[MAX_MSG];
+ char number[16];
+
+ if (sent)
+ strncpy(msg, "Sent ", 10);
+ else
+ strncpy(msg, "Received ", 10);
+ sprintf(number, "%u", bytes);
+ strncat(msg, number, 8);
+ strncat(msg, " bytes of application data", 27);
+
+ msg[MAX_MSG - 1] = 0;
+ Trace(msg);
+ }
+
+
+#else // no YASSL_LOG
+
+
+ Log::Log(const char*) {}
+ Log::~Log() {}
+ void Log::Trace(const char*) {}
+ void Log::ShowTCP(socket_t, bool) {}
+ void Log::ShowData(uint, bool) {}
+
+
+#endif // YASSL_LOG
+} // namespace
diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp
new file mode 100644
index 00000000000..91cea1f9753
--- /dev/null
+++ b/extra/yassl/src/socket_wrapper.cpp
@@ -0,0 +1,171 @@
+/* socket_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* The socket wrapper source implements a Socket class that hides the
+ * differences between Berkely style sockets and Windows sockets, allowing
+ * transparent TCP access.
+ */
+
+
+#include "runtime.hpp"
+#include "socket_wrapper.hpp"
+
+#ifndef _WIN32
+ #include <errno.h>
+ #include <netdb.h>
+ #include <unistd.h>
+ #include <arpa/inet.h>
+ #include <netinet/in.h>
+ #include <sys/ioctl.h>
+ #include <string.h>
+#endif // _WIN32
+
+#ifdef __sun
+ #include <sys/filio.h>
+#endif
+
+#ifdef _WIN32
+ const int SOCKET_EINVAL = WSAEINVAL;
+ const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
+#else
+ const int SOCKET_EINVAL = EINVAL;
+ const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
+#endif // _WIN32
+
+
+namespace yaSSL {
+
+
+Socket::Socket(socket_t s)
+ : socket_(s)
+{}
+
+
+void Socket::set_fd(socket_t s)
+{
+ socket_ = s;
+}
+
+
+socket_t Socket::get_fd() const
+{
+ return socket_;
+}
+
+
+Socket::~Socket()
+{
+ closeSocket();
+}
+
+
+void Socket::closeSocket()
+{
+ if (socket_ != INVALID_SOCKET) {
+#ifdef _WIN32
+ closesocket(socket_);
+#else
+ close(socket_);
+#endif
+ socket_ = INVALID_SOCKET;
+ }
+}
+
+
+uint Socket::get_ready() const
+{
+#ifdef _WIN32
+ unsigned long ready = 0;
+ ioctlsocket(socket_, FIONREAD, &ready);
+#else
+ /*
+ 64-bit Solaris requires the variable passed to
+ FIONREAD be a 32-bit value.
+ */
+ int ready = 0;
+ ioctl(socket_, FIONREAD, &ready);
+#endif
+
+ return ready;
+}
+
+
+uint Socket::send(const byte* buf, unsigned int sz, int flags) const
+{
+ assert(socket_ != INVALID_SOCKET);
+ int sent = ::send(socket_, reinterpret_cast<const char *>(buf), sz, flags);
+
+ if (sent == -1)
+ return 0;
+
+ return sent;
+}
+
+
+uint Socket::receive(byte* buf, unsigned int sz, int flags) const
+{
+ assert(socket_ != INVALID_SOCKET);
+ int recvd = ::recv(socket_, reinterpret_cast<char *>(buf), sz, flags);
+
+ if (recvd == -1)
+ return 0;
+
+ return recvd;
+}
+
+
+// wait if blocking for input, or error
+void Socket::wait() const
+{
+ byte b;
+ receive(&b, 1, MSG_PEEK);
+}
+
+
+void Socket::shutDown(int how)
+{
+ assert(socket_ != INVALID_SOCKET);
+ shutdown(socket_, how);
+}
+
+
+int Socket::get_lastError()
+{
+#ifdef _WIN32
+ return WSAGetLastError();
+#else
+ return errno;
+#endif
+}
+
+
+void Socket::set_lastError(int errorCode)
+{
+#ifdef _WIN32
+ WSASetLastError(errorCode);
+#else
+ errno = errorCode;
+#endif
+}
+
+
+} // namespace
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
new file mode 100644
index 00000000000..8cea205377e
--- /dev/null
+++ b/extra/yassl/src/ssl.cpp
@@ -0,0 +1,1051 @@
+/* ssl.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* SSL source implements all openssl compatibility API functions
+ *
+ * TODO: notes are mostly api additions to allow compilation with mysql
+ * they don't affect normal modes but should be provided for completeness
+
+ * stunnel functions at end of file
+ */
+
+
+
+
+/* see man pages for function descriptions */
+
+#include "runtime.hpp"
+#include "openssl/ssl.h"
+#include "handshake.hpp"
+#include "yassl_int.hpp"
+#include <stdio.h>
+
+
+namespace yaSSL {
+
+using mySTL::min;
+
+
+SSL_METHOD* SSLv3_method()
+{
+ return SSLv3_client_method();
+}
+
+
+SSL_METHOD* SSLv3_server_method()
+{
+ return new (ys) SSL_METHOD(server_end, ProtocolVersion(3,0));
+}
+
+
+SSL_METHOD* SSLv3_client_method()
+{
+ return new (ys) SSL_METHOD(client_end, ProtocolVersion(3,0));
+}
+
+
+SSL_METHOD* TLSv1_server_method()
+{
+ return new (ys) SSL_METHOD(server_end, ProtocolVersion(3,1));
+}
+
+
+SSL_METHOD* TLSv1_client_method()
+{
+ return new (ys) SSL_METHOD(client_end, ProtocolVersion(3,1));
+}
+
+
+SSL_METHOD* SSLv23_server_method()
+{
+ // compatibility only, no version 2 support
+ return SSLv3_server_method();
+}
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD* method)
+{
+ return new (ys) SSL_CTX(method);
+}
+
+
+void SSL_CTX_free(SSL_CTX* ctx)
+{
+ ysDelete(ctx);
+}
+
+
+SSL* SSL_new(SSL_CTX* ctx)
+{
+ return new (ys) SSL(ctx);
+}
+
+
+void SSL_free(SSL* ssl)
+{
+ ysDelete(ssl);
+}
+
+
+int SSL_set_fd(SSL* ssl, int fd)
+{
+ ssl->useSocket().set_fd(fd);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_connect(SSL* ssl)
+{
+ sendClientHello(*ssl);
+ processReply(*ssl);
+
+ if(ssl->getCrypto().get_certManager().sendVerify())
+ sendCertificate(*ssl);
+
+ if (!ssl->getSecurity().get_resuming())
+ sendClientKeyExchange(*ssl);
+
+ if(ssl->getCrypto().get_certManager().sendVerify())
+ sendCertificateVerify(*ssl);
+
+ sendChangeCipher(*ssl);
+ sendFinished(*ssl, client_end);
+ ssl->flushBuffer();
+ if (!ssl->getSecurity().get_resuming())
+ processReply(*ssl);
+
+ ssl->verifyState(serverFinishedComplete);
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
+
+ if (ssl->GetError())
+ return SSL_FATAL_ERROR;
+ return SSL_SUCCESS;
+}
+
+
+int SSL_write(SSL* ssl, const void* buffer, int sz)
+{
+ return sendData(*ssl, buffer, sz);
+}
+
+
+int SSL_read(SSL* ssl, void* buffer, int sz)
+{
+ Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
+ return receiveData(*ssl, data);
+}
+
+
+int SSL_accept(SSL* ssl)
+{
+ processReply(*ssl);
+ sendServerHello(*ssl);
+
+ if (!ssl->getSecurity().get_resuming()) {
+ sendCertificate(*ssl);
+
+ if (ssl->getSecurity().get_connection().send_server_key_)
+ sendServerKeyExchange(*ssl);
+
+ if(ssl->getCrypto().get_certManager().verifyPeer())
+ sendCertificateRequest(*ssl);
+
+ sendServerHelloDone(*ssl);
+ ssl->flushBuffer();
+
+ // Java Client sends fragmented response
+ while (ssl->getStates().getServer() <
+ clientFinishedComplete) {
+ if (ssl->GetError()) break;
+ processReply(*ssl);
+ }
+ }
+ sendChangeCipher(*ssl);
+ sendFinished(*ssl, server_end);
+ ssl->flushBuffer();
+ if (ssl->getSecurity().get_resuming()) {
+
+ // Java Client sends fragmented response
+ while (ssl->getStates().getServer() <
+ clientFinishedComplete) {
+ if (ssl->GetError()) break;
+ processReply(*ssl);
+ }
+ }
+
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
+
+ if (ssl->GetError())
+ return SSL_FATAL_ERROR;
+ return SSL_SUCCESS;
+}
+
+
+int SSL_do_handshake(SSL* ssl)
+{
+ if (ssl->getSecurity().get_parms().entity_ == client_end)
+ return SSL_connect(ssl);
+ else
+ return SSL_accept(ssl);
+}
+
+
+int SSL_clear(SSL* ssl)
+{
+ ssl->useSocket().closeSocket();
+ return SSL_SUCCESS;
+}
+
+
+int SSL_shutdown(SSL* ssl)
+{
+ Alert alert(warning, close_notify);
+ sendAlert(*ssl, alert);
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true);
+ ssl->useSocket().closeSocket();
+
+ return SSL_SUCCESS;
+}
+
+
+SSL_SESSION* SSL_get_session(SSL* ssl)
+{
+ return GetSessions().lookup(
+ ssl->getSecurity().get_connection().sessionID_);
+}
+
+
+int SSL_set_session(SSL* ssl, SSL_SESSION* session)
+{
+ ssl->set_session(session);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_session_reused(SSL* ssl)
+{
+ return ssl->getSecurity().get_resuming();
+}
+
+
+long SSL_SESSION_set_timeout(SSL_SESSION* sess, long t)
+{
+ if (!sess)
+ return SSL_ERROR_NONE;
+
+ sess->SetTimeOut(t);
+ return SSL_SUCCESS;
+}
+
+
+long SSL_get_default_timeout(SSL* /*ssl*/)
+{
+ return DEFAULT_TIMEOUT;
+}
+
+
+const char* SSL_get_cipher_name(SSL* ssl)
+{
+ return SSL_get_cipher(ssl);
+}
+
+
+const char* SSL_get_cipher(SSL* ssl)
+{
+ return ssl->getSecurity().get_parms().cipher_name_;
+}
+
+
+// SSLv2 only, not implemented
+char* SSL_get_shared_ciphers(SSL* /*ssl*/, char* buf, int len)
+{
+ return strncpy(buf, "Not Implemented, SSLv2 only", len);
+}
+
+
+const char* SSL_get_cipher_list(SSL* ssl, int /*priority */)
+{
+ return ssl->getSecurity().get_parms().cipher_list_;
+}
+
+
+int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
+{
+ if (ctx->SetCipherList(list))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+const char* SSL_get_version(SSL* ssl)
+{
+ static const char* version3 = "SSLv3";
+ static const char* version31 = "TLSv1";
+
+ return ssl->isTLS() ? version31 : version3;
+}
+
+const char* SSLeay_version(int)
+{
+ static const char* version = "SSLeay yaSSL compatibility";
+ return version;
+}
+
+
+int SSL_get_error(SSL* ssl, int /*previous*/)
+{
+ return ssl->getStates().What();
+}
+
+
+X509* SSL_get_peer_certificate(SSL* ssl)
+{
+ return ssl->getCrypto().get_certManager().get_peerX509();
+}
+
+
+void X509_free(X509* /*x*/)
+{
+ // peer cert set for deletion during destruction
+ // no need to delete now
+}
+
+
+X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX* ctx)
+{
+ return ctx->current_cert;
+}
+
+
+int X509_STORE_CTX_get_error(X509_STORE_CTX* ctx)
+{
+ return ctx->error;
+}
+
+
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX* ctx)
+{
+ return ctx->error_depth;
+}
+
+
+// copy name into buffer, at most sz bytes, if buffer is null
+// will malloc buffer, caller responsible for freeing
+char* X509_NAME_oneline(X509_NAME* name, char* buffer, int sz)
+{
+ if (!name->GetName()) return buffer;
+
+ int len = strlen(name->GetName()) + 1;
+ int copySz = min(len, sz);
+
+ if (!buffer) {
+ buffer = (char*)malloc(len);
+ if (!buffer) return buffer;
+ copySz = len;
+ }
+
+ if (copySz == 0)
+ return buffer;
+
+ memcpy(buffer, name->GetName(), copySz - 1);
+ buffer[copySz - 1] = 0;
+
+ return buffer;
+}
+
+
+X509_NAME* X509_get_issuer_name(X509* x)
+{
+ return x->GetIssuer();
+}
+
+
+X509_NAME* X509_get_subject_name(X509* x)
+{
+ return x->GetSubject();
+}
+
+
+void SSL_load_error_strings() // compatibility only
+{}
+
+
+void SSL_set_connect_state(SSL*)
+{
+ // already a client by default
+}
+
+
+void SSL_set_accept_state(SSL* ssl)
+{
+ ssl->useSecurity().use_parms().entity_ = server_end;
+}
+
+
+long SSL_get_verify_result(SSL*)
+{
+ // won't get here if not OK
+ return X509_V_OK;
+}
+
+
+long SSL_CTX_sess_set_cache_size(SSL_CTX* /*ctx*/, long /*sz*/)
+{
+ // unlimited size, can't set for now
+ return 0;
+}
+
+
+long SSL_CTX_get_session_cache_mode(SSL_CTX*)
+{
+ // always 0, unlimited size for now
+ return 0;
+}
+
+
+long SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH* dh)
+{
+ if (ctx->SetDH(*dh))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+int read_file(SSL_CTX* ctx, const char* file, int format, CertType type)
+{
+ if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)
+ return SSL_BAD_FILETYPE;
+
+ FILE* input = fopen(file, "rb");
+ if (!input)
+ return SSL_BAD_FILE;
+
+ if (type == CA) {
+ x509* ptr = PemToDer(file, Cert);
+ if (!ptr) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ ctx->AddCA(ptr); // takes ownership
+ }
+ else {
+ x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_;
+
+ if (format == SSL_FILETYPE_ASN1) {
+ fseek(input, 0, SEEK_END);
+ long sz = ftell(input);
+ rewind(input);
+ x = new (ys) x509(sz); // takes ownership
+ size_t bytes = fread(x->use_buffer(), sz, 1, input);
+ if (bytes != 1) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ }
+ else {
+ x = PemToDer(file, type);
+ if (!x) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ }
+ }
+ fclose(input);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format)
+{
+ return read_file(ctx, file, format, Cert);
+}
+
+
+int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx, const char* file, int format)
+{
+ return read_file(ctx, file, format, PrivateKey);
+}
+
+
+void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback /*vc*/)
+{
+ if (mode & SSL_VERIFY_PEER)
+ ctx->setVerifyPeer();
+
+ if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+ ctx->setFailNoCert();
+}
+
+
+int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
+ const char* /*path*/)
+{
+ // just files for now
+ return read_file(ctx, file, SSL_FILETYPE_PEM, CA);
+}
+
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX* /*ctx*/)
+{
+ // TODO: figure out way to set/store default path, then call load_verify
+ return SSL_NOT_IMPLEMENTED;
+}
+
+
+int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
+ unsigned int)
+{
+ // No application specific context needed for yaSSL
+ return SSL_SUCCESS;
+}
+
+
+int SSL_CTX_check_private_key(SSL_CTX* /*ctx*/)
+{
+ // TODO: check private against public for RSA match
+ return SSL_NOT_IMPLEMENTED;
+}
+
+
+// TODO: all session stats
+long SSL_CTX_sess_accept(SSL_CTX* ctx)
+{
+ return ctx->GetStats().accept_;
+}
+
+
+long SSL_CTX_sess_connect(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connect_;
+}
+
+
+long SSL_CTX_sess_accept_good(SSL_CTX* ctx)
+{
+ return ctx->GetStats().acceptGood_;
+}
+
+
+long SSL_CTX_sess_connect_good(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connectGood_;
+}
+
+
+long SSL_CTX_sess_accept_renegotiate(SSL_CTX* ctx)
+{
+ return ctx->GetStats().acceptRenegotiate_;
+}
+
+
+long SSL_CTX_sess_connect_renegotiate(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connectRenegotiate_;
+}
+
+
+long SSL_CTX_sess_hits(SSL_CTX* ctx)
+{
+ return ctx->GetStats().hits_;
+}
+
+
+long SSL_CTX_sess_cb_hits(SSL_CTX* ctx)
+{
+ return ctx->GetStats().cbHits_;
+}
+
+
+long SSL_CTX_sess_cache_full(SSL_CTX* ctx)
+{
+ return ctx->GetStats().cacheFull_;
+}
+
+
+long SSL_CTX_sess_misses(SSL_CTX* ctx)
+{
+ return ctx->GetStats().misses_;
+}
+
+
+long SSL_CTX_sess_timeouts(SSL_CTX* ctx)
+{
+ return ctx->GetStats().timeouts_;
+}
+
+
+long SSL_CTX_sess_number(SSL_CTX* ctx)
+{
+ return ctx->GetStats().number_;
+}
+
+
+long SSL_CTX_sess_get_cache_size(SSL_CTX* ctx)
+{
+ return ctx->GetStats().getCacheSize_;
+}
+// end session stats TODO:
+
+
+int SSL_CTX_get_verify_mode(SSL_CTX* ctx)
+{
+ return ctx->GetStats().verifyMode_;
+}
+
+
+int SSL_get_verify_mode(SSL* ssl)
+{
+ return ssl->getSecurity().GetContext()->GetStats().verifyMode_;
+}
+
+
+int SSL_CTX_get_verify_depth(SSL_CTX* ctx)
+{
+ return ctx->GetStats().verifyDepth_;
+}
+
+
+int SSL_get_verify_depth(SSL* ssl)
+{
+ return ssl->getSecurity().GetContext()->GetStats().verifyDepth_;
+}
+
+
+long SSL_CTX_set_options(SSL_CTX*, long)
+{
+ // TDOD:
+ return SSL_SUCCESS;
+}
+
+
+void SSL_CTX_set_info_callback(SSL_CTX*, void (*)())
+{
+ // TDOD:
+}
+
+
+void OpenSSL_add_all_algorithms() // compatibility only
+{}
+
+
+DH* DH_new(void)
+{
+ DH* dh = new (ys) DH;
+ if (dh)
+ dh->p = dh->g = 0;
+ return dh;
+}
+
+
+void DH_free(DH* dh)
+{
+ ysDelete(dh->g);
+ ysDelete(dh->p);
+ ysDelete(dh);
+}
+
+
+// convert positive big-endian num of length sz into retVal, which may need to
+// be created
+BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal)
+{
+ using mySTL::auto_ptr;
+ bool created = false;
+ auto_ptr<BIGNUM> bn(ysDelete);
+
+ if (!retVal) {
+ created = true;
+ bn.reset(new (ys) BIGNUM);
+ retVal = bn.get();
+ }
+
+ retVal->assign(num, sz);
+
+ if (created)
+ return bn.release();
+ else
+ return retVal;
+}
+
+
+unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *)
+{
+ //return SSL_NOT_IMPLEMENTED;
+ return 0;
+}
+
+
+void ERR_print_errors_fp(FILE* /*fp*/)
+{
+ // need ssl access to implement TODO:
+ //fprintf(fp, "%s", ssl.get_states().errorString_.c_str());
+}
+
+
+char* ERR_error_string(unsigned long /*err*/, char* buffer)
+{
+ // TODO:
+ static char* msg = "Not Implemented";
+ if (buffer)
+ return strncpy(buffer, msg, strlen(msg));
+
+ return msg;
+}
+
+
+const char* X509_verify_cert_error_string(long /* error */)
+{
+ // TODO:
+ static const char* msg = "Not Implemented";
+ return msg;
+}
+
+
+const EVP_MD* EVP_md5(void)
+{
+ // TODO: FIX add to some list for destruction
+ return new (ys) MD5;
+}
+
+
+const EVP_CIPHER* EVP_des_ede3_cbc(void)
+{
+ // TODO: FIX add to some list for destruction
+ return new (ys) DES_EDE;
+}
+
+
+int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt,
+ const byte* data, int sz, int count, byte* key, byte* iv)
+{
+ EVP_MD* myMD = const_cast<EVP_MD*>(md);
+ uint digestSz = myMD->get_digestSize();
+ byte digest[SHA_LEN]; // max size
+
+ int keyLen = type->get_keySize();
+ int ivLen = type->get_ivSize();
+ int keyLeft = keyLen;
+ int ivLeft = ivLen;
+ int keyOutput = 0;
+
+ while (keyOutput < (keyLen + ivLen)) {
+ int digestLeft = digestSz;
+ // D_(i - 1)
+ if (keyOutput) // first time D_0 is empty
+ myMD->update(digest, digestSz);
+ // data
+ myMD->update(data, sz);
+ // salt
+ if (salt)
+ myMD->update(salt, EVP_SALT_SZ);
+ myMD->get_digest(digest);
+ // count
+ for (int j = 1; j < count; j++) {
+ myMD->update(digest, digestSz);
+ myMD->get_digest(digest);
+ }
+
+ if (keyLeft) {
+ int store = min(keyLeft, static_cast<int>(digestSz));
+ memcpy(&key[keyLen - keyLeft], digest, store);
+
+ keyOutput += store;
+ keyLeft -= store;
+ digestLeft -= store;
+ }
+
+ if (ivLeft && digestLeft) {
+ int store = min(ivLeft, digestLeft);
+ memcpy(&iv[ivLen - ivLeft], digest, store);
+
+ keyOutput += store;
+ ivLeft -= store;
+ }
+ }
+ assert(keyOutput == (keyLen + ivLen));
+ return keyOutput;
+}
+
+
+
+void DES_set_key_unchecked(const_DES_cblock* key, DES_key_schedule* schedule)
+{
+ memcpy(schedule, key, sizeof(const_DES_cblock));
+}
+
+
+void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz,
+ DES_key_schedule* ks1, DES_key_schedule* ks2,
+ DES_key_schedule* ks3, DES_cblock* ivec, int enc)
+{
+ DES_EDE des;
+ byte key[DES_EDE_KEY_SZ];
+
+ memcpy(key, *ks1, DES_BLOCK);
+ memcpy(&key[DES_BLOCK], *ks2, DES_BLOCK);
+ memcpy(&key[DES_BLOCK * 2], *ks3, DES_BLOCK);
+
+ if (enc) {
+ des.set_encryptKey(key, *ivec);
+ des.encrypt(output, input, sz);
+ }
+ else {
+ des.set_decryptKey(key, *ivec);
+ des.decrypt(output, input, sz);
+ }
+}
+
+
+ // functions for stunnel
+
+ void RAND_screen()
+ {
+ // TODO:
+ }
+
+
+ const char* RAND_file_name(char*, size_t)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int RAND_write_file(const char*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int RAND_load_file(const char*, long)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void RSA_free(RSA*)
+ {
+ // TODO:
+ }
+
+
+ RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_file(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*, X509_OBJECT*)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ X509_STORE* X509_STORE_new(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+ char* SSL_alert_type_string_long(int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_alert_desc_string_long(int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_state_string_long(SSL*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int))
+ {
+ // TDOD:
+ }
+
+
+ long SSL_CTX_set_session_cache_mode(SSL_CTX*, long)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ long SSL_CTX_set_timeout(SSL_CTX*, long)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb)
+ {
+ // TDOD:
+ }
+
+
+ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_set_rfd(SSL*, int)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_set_wfd(SSL*, int)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_pending(SSL*)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_want_read(SSL*)
+ {
+ return 0; // TODO:
+ }
+
+
+ int SSL_want_write(SSL*)
+ {
+ return 0; // TODO:
+ }
+
+
+ void SSL_set_shutdown(SSL*, int)
+ {
+ // TODO:
+ }
+
+
+ SSL_CIPHER* SSL_get_current_cipher(SSL*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_CIPHER_description(SSL_CIPHER*, char*, int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void SSLeay_add_ssl_algorithms() // compatibility only
+ {}
+
+
+ void ERR_remove_state(unsigned long)
+ {
+ // TODO:
+ }
+
+
+ int ERR_GET_REASON(int l)
+ {
+ return l & 0xfff;
+ }
+
+
+ unsigned long ERR_peek_error()
+ {
+ return 0; // TODO:
+ }
+
+
+ unsigned long ERR_get_error()
+ {
+ return ERR_peek_error();
+ }
+
+
+ // end stunnel needs
+
+
+} // namespace
diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp
new file mode 100644
index 00000000000..5ee57e76aed
--- /dev/null
+++ b/extra/yassl/src/template_instnt.cpp
@@ -0,0 +1,95 @@
+/* template_instnt.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* Explicit template instantiation requests
+ */
+
+
+#include "runtime.hpp"
+#include "handshake.hpp"
+#include "yassl_int.hpp"
+#include "crypto_wrapper.hpp"
+#include "hmac.hpp"
+#include "md5.hpp"
+#include "sha.hpp"
+#include "ripemd.hpp"
+#include "openssl/ssl.h"
+
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+#if !defined(USE_CRYPTOPP_LIB)
+namespace TaoCrypt {
+template class HMAC<MD5>;
+template class HMAC<SHA>;
+template class HMAC<RIPEMD160>;
+}
+#endif // USE_CRYPTOPP_LIB
+
+namespace mySTL {
+template class list<unsigned char*>;
+template yaSSL::del_ptr_zero for_each(mySTL::list<unsigned char*>::iterator, mySTL::list<unsigned char*>::iterator, yaSSL::del_ptr_zero);
+template pair<int, yaSSL::Message* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
+template pair<int, yaSSL::HandShakeBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
+template void destroy<mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
+template void destroy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
+template pair<int, yaSSL::ServerKeyBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
+template void destroy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
+template pair<int, yaSSL::ClientKeyBase* (*)()>* uninit_copy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
+template class list<TaoCrypt::Signer*>;
+template class list<yaSSL::SSL_SESSION*>;
+template class list<yaSSL::input_buffer*>;
+template class list<yaSSL::output_buffer*>;
+template class list<yaSSL::x509*>;
+template void destroy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
+template yaSSL::del_ptr_zero for_each<mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<TaoCrypt::Signer*>::iterator, mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::x509*>::iterator, mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero);
+}
+
+namespace yaSSL {
+template void ysDelete<SSL_CTX>(yaSSL::SSL_CTX*);
+template void ysDelete<SSL>(yaSSL::SSL*);
+template void ysDelete<BIGNUM>(yaSSL::BIGNUM*);
+template void ysDelete<unsigned char>(unsigned char*);
+template void ysDelete<DH>(yaSSL::DH*);
+template void ysDelete<TaoCrypt::Signer>(TaoCrypt::Signer*);
+template void ysDelete<SSL_SESSION>(yaSSL::SSL_SESSION*);
+template void ysDelete<input_buffer>(input_buffer*);
+template void ysDelete<output_buffer>(output_buffer*);
+template void ysDelete<x509>(x509*);
+template void ysDelete<Auth>(Auth*);
+template void ysDelete<HandShakeBase>(HandShakeBase*);
+template void ysDelete<ServerKeyBase>(ServerKeyBase*);
+template void ysDelete<ClientKeyBase>(ClientKeyBase*);
+template void ysDelete<SSL_METHOD>(SSL_METHOD*);
+template void ysDelete<DiffieHellman>(DiffieHellman*);
+template void ysDelete<BulkCipher>(BulkCipher*);
+template void ysDelete<Digest>(Digest*);
+template void ysDelete<X509>(X509*);
+template void ysDelete<Message>(Message*);
+template void ysArrayDelete<unsigned char>(unsigned char*);
+template void ysArrayDelete<char>(char*);
+}
+
+#endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+
diff --git a/extra/yassl/src/timer.cpp b/extra/yassl/src/timer.cpp
new file mode 100644
index 00000000000..4fe0d3aa4f9
--- /dev/null
+++ b/extra/yassl/src/timer.cpp
@@ -0,0 +1,82 @@
+ /* timer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* timer.cpp implements a high res and low res timer
+ *
+*/
+
+#include "runtime.hpp"
+#include "timer.hpp"
+
+namespace yaSSL {
+
+#ifdef _WIN32
+
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+
+ timer_d timer()
+ {
+ static bool init(false);
+ static LARGE_INTEGER freq;
+
+ if (!init) {
+ QueryPerformanceFrequency(&freq);
+ init = true;
+ }
+
+ LARGE_INTEGER count;
+ QueryPerformanceCounter(&count);
+
+ return static_cast<double>(count.QuadPart) / freq.QuadPart;
+ }
+
+
+ uint lowResTimer()
+ {
+ return static_cast<uint>(timer());
+ }
+
+#else // _WIN32
+
+ #include <sys/time.h>
+
+ timer_d timer()
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ return static_cast<double>(tv.tv_sec)
+ + static_cast<double>(tv.tv_usec) / 1000000;
+ }
+
+
+ uint lowResTimer()
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ return tv.tv_sec;
+ }
+
+
+#endif // _WIN32
+} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp
new file mode 100644
index 00000000000..c53aef2068d
--- /dev/null
+++ b/extra/yassl/src/yassl_error.cpp
@@ -0,0 +1,53 @@
+/* yassl_error.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* yaSSL error implements and an exception class
+ */
+
+#include "runtime.hpp"
+#include "yassl_error.hpp"
+
+namespace yaSSL {
+
+
+Error::Error(const char* s, YasslError e, Library l)
+ : mySTL::runtime_error(s), error_(e), lib_(l)
+{
+}
+
+
+YasslError Error::get_number() const
+{
+ return error_;
+}
+
+
+Library Error::get_lib() const
+{
+
+ return lib_;
+}
+
+
+
+
+} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp
new file mode 100644
index 00000000000..1d9db46816b
--- /dev/null
+++ b/extra/yassl/src/yassl_imp.cpp
@@ -0,0 +1,2093 @@
+/* yassl_imp.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* yaSSL source implements all SSL.v3 secification structures.
+ */
+
+#include "runtime.hpp"
+#include "yassl_int.hpp"
+#include "handshake.hpp"
+
+#include "asn.hpp" // provide crypto wrapper??
+
+
+namespace yaSSL {
+
+
+namespace { // locals
+
+bool isTLS(ProtocolVersion pv)
+{
+ if (pv.major_ >= 3 && pv.minor_ >= 1)
+ return true;
+
+ return false;
+}
+
+
+} // namespace (locals)
+
+
+void hashHandShake(SSL&, const input_buffer&, uint);
+
+
+ProtocolVersion::ProtocolVersion(uint8 maj, uint8 min)
+ : major_(maj), minor_(min)
+{}
+
+
+// construct key exchange with known ssl parms
+void ClientKeyExchange::createKey(SSL& ssl)
+{
+ const ClientKeyFactory& ckf = ssl.getFactory().getClientKey();
+ client_key_ = ckf.CreateObject(ssl.getSecurity().get_parms().kea_);
+
+ if (!client_key_)
+ ssl.SetError(factory_error);
+}
+
+
+// construct key exchange with known ssl parms
+void ServerKeyExchange::createKey(SSL& ssl)
+{
+ const ServerKeyFactory& skf = ssl.getFactory().getServerKey();
+ server_key_ = skf.CreateObject(ssl.getSecurity().get_parms().kea_);
+
+ if (!server_key_)
+ ssl.SetError(factory_error);
+}
+
+
+// build/set PreMaster secret and encrypt, client side
+void EncryptedPreMasterSecret::build(SSL& ssl)
+{
+ opaque tmp[SECRET_LEN];
+ memset(tmp, 0, sizeof(tmp));
+ ssl.getCrypto().get_random().Fill(tmp, SECRET_LEN);
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ tmp[0] = pv.major_;
+ tmp[1] = pv.minor_;
+ ssl.set_preMaster(tmp, SECRET_LEN);
+
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+ bool tls = ssl.isTLS(); // if TLS, put length for encrypted data
+ alloc(rsa.get_cipherLength() + (tls ? 2 : 0));
+ byte* holder = secret_;
+ if (tls) {
+ byte len[2];
+ c16toa(rsa.get_cipherLength(), len);
+ memcpy(secret_, len, sizeof(len));
+ holder += 2;
+ }
+ rsa.encrypt(holder, tmp, SECRET_LEN, ssl.getCrypto().get_random());
+}
+
+
+// build/set premaster and Client Public key, client side
+void ClientDiffieHellmanPublic::build(SSL& ssl)
+{
+ DiffieHellman& dhServer = ssl.useCrypto().use_dh();
+ DiffieHellman dhClient(dhServer);
+
+ uint keyLength = dhClient.get_agreedKeyLength(); // pub and agree same
+
+ alloc(keyLength, true);
+ dhClient.makeAgreement(dhServer.get_publicKey());
+ c16toa(keyLength, Yc_);
+ memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength);
+
+ ssl.set_preMaster(dhClient.get_agreedKey(), keyLength);
+}
+
+
+// build server exhange, server side
+void DH_Server::build(SSL& ssl)
+{
+ DiffieHellman& dhServer = ssl.useCrypto().use_dh();
+
+ int pSz, gSz, pubSz;
+ dhServer.set_sizes(pSz, gSz, pubSz);
+ dhServer.get_parms(parms_.alloc_p(pSz), parms_.alloc_g(gSz),
+ parms_.alloc_pub(pubSz));
+
+ short sigSz = 0;
+ mySTL::auto_ptr<Auth> auth(ysDelete);
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo)
+ auth.reset(new (ys) RSA(cert.get_privateKey(),
+ cert.get_privateKeyLength(), false));
+ else {
+ auth.reset(new (ys) DSS(cert.get_privateKey(),
+ cert.get_privateKeyLength(), false));
+ sigSz += DSS_ENCODED_EXTRA;
+ }
+
+
+ sigSz += auth->get_signatureLength();
+
+
+ length_ = 8; // pLen + gLen + YsLen + SigLen
+ length_ += pSz + gSz + pubSz + sigSz;
+
+ output_buffer tmp(length_);
+ byte len[2];
+ // P
+ c16toa(pSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_p(), pSz);
+ // G
+ c16toa(gSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_g(), gSz);
+ // Ys
+ c16toa(pubSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_pub(), pubSz);
+
+ // Sig
+ byte hash[FINISHED_SZ];
+ MD5 md5;
+ SHA sha;
+ signature_ = new (ys) byte[sigSz];
+
+ const Connection& conn = ssl.getSecurity().get_connection();
+ // md5
+ md5.update(conn.client_random_, RAN_LEN);
+ md5.update(conn.server_random_, RAN_LEN);
+ md5.update(tmp.get_buffer(), tmp.get_size());
+ md5.get_digest(hash);
+
+ // sha
+ sha.update(conn.client_random_, RAN_LEN);
+ sha.update(conn.server_random_, RAN_LEN);
+ sha.update(tmp.get_buffer(), tmp.get_size());
+ sha.get_digest(&hash[MD5_LEN]);
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo)
+ auth->sign(signature_, hash, sizeof(hash),
+ ssl.getCrypto().get_random());
+ else {
+ auth->sign(signature_, &hash[MD5_LEN], SHA_LEN,
+ ssl.getCrypto().get_random());
+ byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA];
+ TaoCrypt::EncodeDSA_Signature(signature_, encoded);
+ memcpy(signature_, encoded, sizeof(encoded));
+ }
+
+ c16toa(sigSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(signature_, sigSz);
+
+ // key message
+ keyMessage_ = new (ys) opaque[length_];
+ memcpy(keyMessage_, tmp.get_buffer(), tmp.get_size());
+}
+
+
+// read PreMaster secret and decrypt, server side
+void EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input)
+{
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+ uint16 cipherLen = rsa.get_cipherLength();
+ if (ssl.isTLS()) {
+ byte len[2];
+ input.read(len, sizeof(len));
+ ato16(len, cipherLen);
+ }
+ alloc(cipherLen);
+ input.read(secret_, length_);
+
+ opaque preMasterSecret[SECRET_LEN];
+ rsa.decrypt(preMasterSecret, secret_, length_,
+ ssl.getCrypto().get_random());
+
+ ssl.set_preMaster(preMasterSecret, SECRET_LEN);
+ ssl.makeMasterSecret();
+}
+
+
+EncryptedPreMasterSecret::EncryptedPreMasterSecret()
+ : secret_(0), length_(0)
+{}
+
+
+EncryptedPreMasterSecret::~EncryptedPreMasterSecret()
+{
+ ysArrayDelete(secret_);
+}
+
+
+int EncryptedPreMasterSecret::get_length() const
+{
+ return length_;
+}
+
+
+opaque* EncryptedPreMasterSecret::get_clientKey() const
+{
+ return secret_;
+}
+
+
+void EncryptedPreMasterSecret::alloc(int sz)
+{
+ length_ = sz;
+ secret_ = new (ys) opaque[sz];
+}
+
+
+// read client's public key, server side
+void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input)
+{
+ DiffieHellman& dh = ssl.useCrypto().use_dh();
+
+ uint16 keyLength;
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, keyLength);
+
+ alloc(keyLength);
+ input.read(Yc_, length_);
+ dh.makeAgreement(Yc_);
+
+ ssl.set_preMaster(dh.get_agreedKey(), keyLength);
+ ssl.makeMasterSecret();
+}
+
+
+ClientDiffieHellmanPublic::ClientDiffieHellmanPublic()
+ : length_(0), Yc_(0)
+{}
+
+
+ClientDiffieHellmanPublic::~ClientDiffieHellmanPublic()
+{
+ ysArrayDelete(Yc_);
+}
+
+
+int ClientDiffieHellmanPublic::get_length() const
+{
+ return length_;
+}
+
+
+opaque* ClientDiffieHellmanPublic::get_clientKey() const
+{
+ return Yc_;
+}
+
+
+void ClientDiffieHellmanPublic::alloc(int sz, bool offset)
+{
+ length_ = sz + (offset ? KEY_OFFSET : 0);
+ Yc_ = new (ys) opaque[length_];
+}
+
+
+// read server's p, g, public key and sig, client side
+void DH_Server::read(SSL& ssl, input_buffer& input)
+{
+ uint16 length, messageTotal = 6; // pSz + gSz + pubSz
+ byte tmp[2];
+
+ // p
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_p(length), length);
+
+ // g
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_g(length), length);
+
+ // pub
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_pub(length), length);
+
+ // save message for hash verify
+ input_buffer message(messageTotal);
+ input.set_current(input.get_current() - messageTotal);
+ input.read(message.get_buffer(), messageTotal);
+ message.add_size(messageTotal);
+
+ // signature
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+
+ signature_ = new (ys) byte[length];
+ input.read(signature_, length);
+
+ // verify signature
+ byte hash[FINISHED_SZ];
+ MD5 md5;
+ SHA sha;
+
+ const Connection& conn = ssl.getSecurity().get_connection();
+ // md5
+ md5.update(conn.client_random_, RAN_LEN);
+ md5.update(conn.server_random_, RAN_LEN);
+ md5.update(message.get_buffer(), message.get_size());
+ md5.get_digest(hash);
+
+ // sha
+ sha.update(conn.client_random_, RAN_LEN);
+ sha.update(conn.server_random_, RAN_LEN);
+ sha.update(message.get_buffer(), message.get_size());
+ sha.get_digest(&hash[MD5_LEN]);
+
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) {
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!rsa.verify(hash, sizeof(hash), signature_, length))
+ ssl.SetError(verify_error);
+ }
+ else {
+ byte decodedSig[DSS_SIG_SZ];
+ length = TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, length);
+
+ DSS dss(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!dss.verify(&hash[MD5_LEN], SHA_LEN, decodedSig, length))
+ ssl.SetError(verify_error);
+ }
+
+ // save input
+ ssl.useCrypto().SetDH(new (ys) DiffieHellman(parms_.get_p(),
+ parms_.get_pSize(), parms_.get_g(), parms_.get_gSize(),
+ parms_.get_pub(), parms_.get_pubSize(),
+ ssl.getCrypto().get_random()));
+}
+
+
+DH_Server::DH_Server()
+ : signature_(0), length_(0), keyMessage_(0)
+{}
+
+
+DH_Server::~DH_Server()
+{
+ ysArrayDelete(keyMessage_);
+ ysArrayDelete(signature_);
+}
+
+
+int DH_Server::get_length() const
+{
+ return length_;
+}
+
+
+opaque* DH_Server::get_serverKey() const
+{
+ return keyMessage_;
+}
+
+
+// set available suites
+Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers,
+ ProtocolVersion pv) : entity_(ce)
+{
+ pending_ = true; // suite not set yet
+
+ if (ciphers.setSuites_) { // use user set list
+ suites_size_ = ciphers.suiteSz_;
+ memcpy(suites_, ciphers.suites_, ciphers.suiteSz_);
+ SetCipherNames();
+ }
+ else
+ SetSuites(pv); // defaults
+}
+
+
+void Parameters::SetSuites(ProtocolVersion pv)
+{
+ int i = 0;
+ // available suites, best first
+ // when adding more, make sure cipher_names is updated and
+ // MAX_CIPHER_LIST is big enough
+
+ if (isTLS(pv)) {
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_256_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_128_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_3DES_EDE_CBC_RMD160;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160;
+ }
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_RC4_128_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_RC4_128_MD5;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_DES_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_RSA_WITH_DES_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_DSS_WITH_DES_CBC_SHA;
+
+ suites_size_ = i;
+
+ SetCipherNames();
+}
+
+
+void Parameters::SetCipherNames()
+{
+ const int suites = suites_size_ / 2;
+ int pos = 0;
+
+ for (int j = 0; j < suites; j++) {
+ int index = suites_[j*2 + 1]; // every other suite is suite id
+ int len = strlen(cipher_names[index]);
+ memcpy(&cipher_list_[pos], cipher_names[index], len);
+ pos += len;
+ cipher_list_[pos++] = ':';
+ }
+ if (suites)
+ cipher_list_[--pos] = 0;
+}
+
+
+// input operator for RecordLayerHeader, adjust stream
+input_buffer& operator>>(input_buffer& input, RecordLayerHeader& hdr)
+{
+ hdr.type_ = ContentType(input[AUTO]);
+ hdr.version_.major_ = input[AUTO];
+ hdr.version_.minor_ = input[AUTO];
+
+ // length
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, hdr.length_);
+
+ return input;
+}
+
+
+// output operator for RecordLayerHeader
+output_buffer& operator<<(output_buffer& output, const RecordLayerHeader& hdr)
+{
+ output[AUTO] = hdr.type_;
+ output[AUTO] = hdr.version_.major_;
+ output[AUTO] = hdr.version_.minor_;
+
+ // length
+ byte tmp[2];
+ c16toa(hdr.length_, tmp);
+ output[AUTO] = tmp[0];
+ output[AUTO] = tmp[1];
+
+ return output;
+}
+
+
+// virtual input operator for Messages
+input_buffer& operator>>(input_buffer& input, Message& msg)
+{
+ return msg.set(input);
+}
+
+// virtual output operator for Messages
+output_buffer& operator<<(output_buffer& output, const Message& msg)
+{
+ return msg.get(output);
+}
+
+
+// input operator for HandShakeHeader
+input_buffer& operator>>(input_buffer& input, HandShakeHeader& hs)
+{
+ hs.type_ = HandShakeType(input[AUTO]);
+
+ hs.length_[0] = input[AUTO];
+ hs.length_[1] = input[AUTO];
+ hs.length_[2] = input[AUTO];
+
+ return input;
+}
+
+
+// output operator for HandShakeHeader
+output_buffer& operator<<(output_buffer& output, const HandShakeHeader& hdr)
+{
+ output[AUTO] = hdr.type_;
+ output.write(hdr.length_, sizeof(hdr.length_));
+ return output;
+}
+
+
+// HandShake Header Processing function
+void HandShakeHeader::Process(input_buffer& input, SSL& ssl)
+{
+ ssl.verifyState(*this);
+ const HandShakeFactory& hsf = ssl.getFactory().getHandShake();
+ mySTL::auto_ptr<HandShakeBase> hs(hsf.CreateObject(type_), ysDelete);
+ if (!hs.get()) {
+ ssl.SetError(factory_error);
+ return;
+ }
+ hashHandShake(ssl, input, c24to32(length_));
+
+ input >> *hs;
+ hs->Process(input, ssl);
+}
+
+
+ContentType HandShakeHeader::get_type() const
+{
+ return handshake;
+}
+
+
+uint16 HandShakeHeader::get_length() const
+{
+ return c24to32(length_);
+}
+
+
+HandShakeType HandShakeHeader::get_handshakeType() const
+{
+ return type_;
+}
+
+
+void HandShakeHeader::set_type(HandShakeType hst)
+{
+ type_ = hst;
+}
+
+
+void HandShakeHeader::set_length(uint32 u32)
+{
+ c32to24(u32, length_);
+}
+
+
+input_buffer& HandShakeHeader::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& HandShakeHeader::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+
+int HandShakeBase::get_length() const
+{
+ return length_;
+}
+
+
+void HandShakeBase::set_length(int l)
+{
+ length_ = l;
+}
+
+
+// for building buffer's type field
+HandShakeType HandShakeBase::get_type() const
+{
+ return no_shake;
+}
+
+
+input_buffer& HandShakeBase::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& HandShakeBase::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+void HandShakeBase::Process(input_buffer&, SSL&)
+{}
+
+
+input_buffer& HelloRequest::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& HelloRequest::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+void HelloRequest::Process(input_buffer&, SSL&)
+{}
+
+
+HandShakeType HelloRequest::get_type() const
+{
+ return hello_request;
+}
+
+
+// input operator for CipherSpec
+input_buffer& operator>>(input_buffer& input, ChangeCipherSpec& cs)
+{
+ cs.type_ = CipherChoice(input[AUTO]);
+ return input;
+}
+
+// output operator for CipherSpec
+output_buffer& operator<<(output_buffer& output, const ChangeCipherSpec& cs)
+{
+ output[AUTO] = cs.type_;
+ return output;
+}
+
+
+ChangeCipherSpec::ChangeCipherSpec()
+ : type_(change_cipher_spec_choice)
+{}
+
+
+input_buffer& ChangeCipherSpec::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ChangeCipherSpec::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+ContentType ChangeCipherSpec::get_type() const
+{
+ return change_cipher_spec;
+}
+
+
+uint16 ChangeCipherSpec::get_length() const
+{
+ return SIZEOF_ENUM;
+}
+
+
+// CipherSpec processing handler
+void ChangeCipherSpec::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useSecurity().use_parms().pending_ = false;
+ if (ssl.getSecurity().get_resuming()) {
+ if (ssl.getSecurity().get_parms().entity_ == client_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), server); // server
+ }
+ else if (ssl.getSecurity().get_parms().entity_ == server_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), client); // client
+}
+
+
+Alert::Alert(AlertLevel al, AlertDescription ad)
+ : level_(al), description_(ad)
+{}
+
+
+ContentType Alert::get_type() const
+{
+ return alert;
+}
+
+
+uint16 Alert::get_length() const
+{
+ return SIZEOF_ENUM * 2;
+}
+
+
+input_buffer& Alert::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& Alert::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for Alert
+input_buffer& operator>>(input_buffer& input, Alert& a)
+{
+ a.level_ = AlertLevel(input[AUTO]);
+ a.description_ = AlertDescription(input[AUTO]);
+
+ return input;
+}
+
+
+// output operator for Alert
+output_buffer& operator<<(output_buffer& output, const Alert& a)
+{
+ output[AUTO] = a.level_;
+ output[AUTO] = a.description_;
+ return output;
+}
+
+
+// Alert processing handler
+void Alert::Process(input_buffer& input, SSL& ssl)
+{
+ if (ssl.getSecurity().get_parms().pending_ == false) { // encrypted alert
+ int aSz = get_length(); // alert size already read on input
+ opaque verify[SHA_LEN];
+ const opaque* data = input.get_buffer() + input.get_current() - aSz;
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verify, data, aSz, alert, true);
+ else
+ hmac(ssl, verify, data, aSz, alert, true);
+
+ // read mac and fill
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ opaque mac[SHA_LEN];
+ input.read(mac, digestSz);
+
+ opaque fill;
+ int padSz = ssl.getSecurity().get_parms().encrypt_size_ - aSz -
+ digestSz;
+ for (int i = 0; i < padSz; i++)
+ fill = input[AUTO];
+
+ // verify
+ if (memcmp(mac, verify, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+ }
+ if (level_ == fatal) {
+ ssl.useStates().useRecord() = recordNotReady;
+ ssl.useStates().useHandShake() = handShakeNotReady;
+ ssl.SetError(YasslError(description_));
+ }
+}
+
+
+Data::Data()
+ : length_(0), buffer_(0), write_buffer_(0)
+{}
+
+
+Data::Data(uint16 len, opaque* b)
+ : length_(len), buffer_(b), write_buffer_(0)
+{}
+
+
+Data::Data(uint16 len, const opaque* w)
+ : length_(len), buffer_(0), write_buffer_(w)
+{}
+
+input_buffer& Data::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& Data::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+ContentType Data::get_type() const
+{
+ return application_data;
+}
+
+
+uint16 Data::get_length() const
+{
+ return length_;
+}
+
+
+const opaque* Data::get_buffer() const
+{
+ return write_buffer_;
+}
+
+
+void Data::set_length(uint16 l)
+{
+ length_ = l;
+}
+
+opaque* Data::set_buffer()
+{
+ return buffer_;
+}
+
+
+// output operator for Data
+output_buffer& operator<<(output_buffer& output, const Data& data)
+{
+ output.write(data.write_buffer_, data.length_);
+ return output;
+}
+
+
+// Process handler for Data
+void Data::Process(input_buffer& input, SSL& ssl)
+{
+ int msgSz = ssl.getSecurity().get_parms().encrypt_size_;
+ int pad = 0, padByte = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ pad = *(input.get_buffer() + input.get_current() + msgSz - 1);
+ padByte = 1;
+ }
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ int dataSz = msgSz - digestSz - pad - padByte;
+ opaque verify[SHA_LEN];
+
+ // read data
+ if (dataSz) {
+ input_buffer* data;
+ ssl.addData(data = new (ys) input_buffer(dataSz));
+ input.read(data->get_buffer(), dataSz);
+ data->add_size(dataSz);
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verify, data->get_buffer(), dataSz, application_data,
+ true);
+ else
+ hmac(ssl, verify, data->get_buffer(), dataSz, application_data,
+ true);
+ }
+
+ // read mac and fill
+ opaque mac[SHA_LEN];
+ opaque fill;
+ input.read(mac, digestSz);
+ for (int i = 0; i < pad; i++)
+ fill = input[AUTO];
+ if (padByte)
+ fill = input[AUTO];
+
+ // verify
+ if (dataSz) {
+ if (memcmp(mac, verify, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+ }
+ else
+ ssl.get_SEQIncrement(true); // even though no data, increment verify
+}
+
+
+// virtual input operator for HandShakes
+input_buffer& operator>>(input_buffer& input, HandShakeBase& hs)
+{
+ return hs.set(input);
+}
+
+
+// virtual output operator for HandShakes
+output_buffer& operator<<(output_buffer& output, const HandShakeBase& hs)
+{
+ return hs.get(output);
+}
+
+
+Certificate::Certificate(const x509* cert) : cert_(cert)
+{
+ set_length(cert_->get_length() + 2 * CERT_HEADER); // list and cert size
+}
+
+
+const opaque* Certificate::get_buffer() const
+{
+ return cert_->get_buffer();
+}
+
+
+// output operator for Certificate
+output_buffer& operator<<(output_buffer& output, const Certificate& cert)
+{
+ uint sz = cert.get_length() - 2 * CERT_HEADER;
+ opaque tmp[CERT_HEADER];
+
+ c32to24(sz + CERT_HEADER, tmp);
+ output.write(tmp, CERT_HEADER);
+ c32to24(sz, tmp);
+ output.write(tmp, CERT_HEADER);
+ output.write(cert.get_buffer(), sz);
+
+ return output;
+}
+
+
+// certificate processing handler
+void Certificate::Process(input_buffer& input, SSL& ssl)
+{
+ CertManager& cm = ssl.useCrypto().use_certManager();
+
+ uint32 list_sz;
+ byte tmp[3];
+
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ tmp[2] = input[AUTO];
+ c24to32(tmp, list_sz);
+
+ while (list_sz) {
+ // cert size
+ uint32 cert_sz;
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ tmp[2] = input[AUTO];
+ c24to32(tmp, cert_sz);
+
+ x509* myCert;
+ cm.AddPeerCert(myCert = new (ys) x509(cert_sz));
+ input.read(myCert->use_buffer(), myCert->get_length());
+
+ list_sz -= cert_sz + CERT_HEADER;
+ }
+ if (int err = cm.Validate())
+ ssl.SetError(YasslError(err));
+ else if (ssl.getSecurity().get_parms().entity_ == client_end)
+ ssl.useStates().useClient() = serverCertComplete;
+}
+
+
+Certificate::Certificate()
+ : cert_(0)
+{}
+
+
+input_buffer& Certificate::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& Certificate::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType Certificate::get_type() const
+{
+ return certificate;
+}
+
+
+ServerDHParams::ServerDHParams()
+ : pSz_(0), gSz_(0), pubSz_(0), p_(0), g_(0), Ys_(0)
+{}
+
+
+ServerDHParams::~ServerDHParams()
+{
+ ysArrayDelete(Ys_);
+ ysArrayDelete(g_);
+ ysArrayDelete(p_);
+}
+
+
+int ServerDHParams::get_pSize() const
+{
+ return pSz_;
+}
+
+
+int ServerDHParams::get_gSize() const
+{
+ return gSz_;
+}
+
+
+int ServerDHParams::get_pubSize() const
+{
+ return pubSz_;
+}
+
+
+const opaque* ServerDHParams::get_p() const
+{
+ return p_;
+}
+
+
+const opaque* ServerDHParams::get_g() const
+{
+ return g_;
+}
+
+
+const opaque* ServerDHParams::get_pub() const
+{
+ return Ys_;
+}
+
+
+opaque* ServerDHParams::alloc_p(int sz)
+{
+ p_ = new (ys) opaque[pSz_ = sz];
+ return p_;
+}
+
+
+opaque* ServerDHParams::alloc_g(int sz)
+{
+ g_ = new (ys) opaque[gSz_ = sz];
+ return g_;
+}
+
+
+opaque* ServerDHParams::alloc_pub(int sz)
+{
+ Ys_ = new (ys) opaque[pubSz_ = sz];
+ return Ys_;
+}
+
+
+int ServerKeyBase::get_length() const
+{
+ return 0;
+}
+
+
+opaque* ServerKeyBase::get_serverKey() const
+{
+ return 0;
+}
+
+
+// input operator for ServerHello
+input_buffer& operator>>(input_buffer& input, ServerHello& hello)
+{
+ // Protocol
+ hello.server_version_.major_ = input[AUTO];
+ hello.server_version_.minor_ = input[AUTO];
+
+ // Random
+ input.read(hello.random_, RAN_LEN);
+
+ // Session
+ hello.id_len_ = input[AUTO];
+ input.read(hello.session_id_, ID_LEN);
+
+ // Suites
+ hello.cipher_suite_[0] = input[AUTO];
+ hello.cipher_suite_[1] = input[AUTO];
+
+ // Compression
+ hello.compression_method_ = CompressionMethod(input[AUTO]);
+
+ return input;
+}
+
+
+// output operator for ServerHello
+output_buffer& operator<<(output_buffer& output, const ServerHello& hello)
+{
+ // Protocol
+ output[AUTO] = hello.server_version_.major_;
+ output[AUTO] = hello.server_version_.minor_;
+
+ // Random
+ output.write(hello.random_, RAN_LEN);
+
+ // Session
+ output[AUTO] = hello.id_len_;
+ output.write(hello.session_id_, ID_LEN);
+
+ // Suites
+ output[AUTO] = hello.cipher_suite_[0];
+ output[AUTO] = hello.cipher_suite_[1];
+
+ // Compression
+ output[AUTO] = hello.compression_method_;
+
+ return output;
+}
+
+
+// Server Hello processing handler
+void ServerHello::Process(input_buffer&, SSL& ssl)
+{
+ ssl.set_pending(cipher_suite_[1]);
+ ssl.set_random(random_, server_end);
+ ssl.set_sessionID(session_id_);
+
+ if (ssl.getSecurity().get_resuming())
+ if (memcmp(session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN) == 0) {
+ ssl.set_masterSecret(ssl.getSecurity().get_resume().GetSecret());
+ if (ssl.isTLS())
+ ssl.deriveTLSKeys();
+ else
+ ssl.deriveKeys();
+ ssl.useStates().useClient() = serverHelloDoneComplete;
+ return;
+ }
+ else {
+ ssl.useSecurity().set_resuming(false);
+ ssl.useLog().Trace("server denied resumption");
+ }
+ ssl.useStates().useClient() = serverHelloComplete;
+}
+
+
+ServerHello::ServerHello()
+{
+ memset(random_, 0, RAN_LEN);
+ memset(session_id_, 0, ID_LEN);
+}
+
+
+ServerHello::ServerHello(ProtocolVersion pv)
+ : server_version_(pv)
+{
+ memset(random_, 0, RAN_LEN);
+ memset(session_id_, 0, ID_LEN);
+}
+
+
+input_buffer& ServerHello::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ServerHello::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ServerHello::get_type() const
+{
+ return server_hello;
+}
+
+
+const opaque* ServerHello::get_random() const
+{
+ return random_;
+}
+
+
+// Server Hello Done processing handler
+void ServerHelloDone::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useStates().useClient() = serverHelloDoneComplete;
+}
+
+
+ServerHelloDone::ServerHelloDone()
+{
+ set_length(0);
+}
+
+
+input_buffer& ServerHelloDone::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& ServerHelloDone::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+HandShakeType ServerHelloDone::get_type() const
+{
+ return server_hello_done;
+}
+
+
+int ClientKeyBase::get_length() const
+{
+ return 0;
+}
+
+
+opaque* ClientKeyBase::get_clientKey() const
+{
+ return 0;
+}
+
+
+// input operator for Client Hello
+input_buffer& operator>>(input_buffer& input, ClientHello& hello)
+{
+ // Protocol
+ hello.client_version_.major_ = input[AUTO];
+ hello.client_version_.minor_ = input[AUTO];
+
+ // Random
+ input.read(hello.random_, RAN_LEN);
+
+ // Session
+ hello.id_len_ = input[AUTO];
+ if (hello.id_len_) input.read(hello.session_id_, ID_LEN);
+
+ // Suites
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, hello.suite_len_);
+ input.read(hello.cipher_suites_, hello.suite_len_);
+
+ // Compression
+ hello.comp_len_ = input[AUTO];
+ hello.compression_methods_ = CompressionMethod(input[AUTO]);
+
+ return input;
+}
+
+
+// output operaotr for Client Hello
+output_buffer& operator<<(output_buffer& output, const ClientHello& hello)
+{
+ // Protocol
+ output[AUTO] = hello.client_version_.major_;
+ output[AUTO] = hello.client_version_.minor_;
+
+ // Random
+ output.write(hello.random_, RAN_LEN);
+
+ // Session
+ output[AUTO] = hello.id_len_;
+ if (hello.id_len_) output.write(hello.session_id_, ID_LEN);
+
+ // Suites
+ byte tmp[2];
+ c16toa(hello.suite_len_, tmp);
+ output[AUTO] = tmp[0];
+ output[AUTO] = tmp[1];
+ output.write(hello.cipher_suites_, hello.suite_len_);
+
+ // Compression
+ output[AUTO] = hello.comp_len_;
+ output[AUTO] = hello.compression_methods_;
+
+ return output;
+}
+
+
+// Client Hello processing handler
+void ClientHello::Process(input_buffer&, SSL& ssl)
+{
+ if (ssl.isTLS() && client_version_.minor_ == 0) {
+ ssl.useSecurity().use_connection().TurnOffTLS();
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ ssl.useSecurity().use_parms().SetSuites(pv); // reset w/ SSL suites
+ }
+ ssl.set_random(random_, client_end);
+
+ while (id_len_) { // trying to resume
+ SSL_SESSION* session = GetSessions().lookup(session_id_);
+ if (!session) {
+ ssl.useLog().Trace("session lookup failed");
+ break;
+ }
+ ssl.set_session(session);
+ ssl.useSecurity().set_resuming(true);
+ ssl.matchSuite(session->GetSuite(), SUITE_LEN);
+ ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]);
+ ssl.set_masterSecret(session->GetSecret());
+
+ opaque serverRandom[RAN_LEN];
+ ssl.getCrypto().get_random().Fill(serverRandom, sizeof(serverRandom));
+ ssl.set_random(serverRandom, server_end);
+ if (ssl.isTLS())
+ ssl.deriveTLSKeys();
+ else
+ ssl.deriveKeys();
+ ssl.useStates().useServer() = clientKeyExchangeComplete;
+ return;
+ }
+ ssl.matchSuite(cipher_suites_, suite_len_);
+ ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]);
+
+ ssl.useStates().useServer() = clientHelloComplete;
+}
+
+
+input_buffer& ClientHello::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ClientHello::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ClientHello::get_type() const
+{
+ return client_hello;
+}
+
+
+const opaque* ClientHello::get_random() const
+{
+ return random_;
+}
+
+
+ClientHello::ClientHello()
+{
+ memset(random_, 0, RAN_LEN);
+}
+
+
+ClientHello::ClientHello(ProtocolVersion pv)
+ : client_version_(pv)
+{
+ memset(random_, 0, RAN_LEN);
+}
+
+
+// output operator for ServerKeyExchange
+output_buffer& operator<<(output_buffer& output, const ServerKeyExchange& sk)
+{
+ output.write(sk.getKey(), sk.getKeyLength());
+ return output;
+}
+
+
+// Server Key Exchange processing handler
+void ServerKeyExchange::Process(input_buffer& input, SSL& ssl)
+{
+ createKey(ssl);
+ if (ssl.GetError()) return;
+ server_key_->read(ssl, input);
+
+ ssl.useStates().useClient() = serverKeyExchangeComplete;
+}
+
+
+ServerKeyExchange::ServerKeyExchange(SSL& ssl)
+{
+ createKey(ssl);
+}
+
+
+ServerKeyExchange::ServerKeyExchange()
+ : server_key_(0)
+{}
+
+
+ServerKeyExchange::~ServerKeyExchange()
+{
+ ysDelete(server_key_);
+}
+
+
+void ServerKeyExchange::build(SSL& ssl)
+{
+ server_key_->build(ssl);
+ set_length(server_key_->get_length());
+}
+
+
+const opaque* ServerKeyExchange::getKey() const
+{
+ return server_key_->get_serverKey();
+}
+
+
+int ServerKeyExchange::getKeyLength() const
+{
+ return server_key_->get_length();
+}
+
+
+input_buffer& ServerKeyExchange::set(input_buffer& in)
+{
+ return in; // process does
+}
+
+
+output_buffer& ServerKeyExchange::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ServerKeyExchange::get_type() const
+{
+ return server_key_exchange;
+}
+
+
+// CertificateRequest
+CertificateRequest::CertificateRequest()
+ : typeTotal_(0)
+{
+ memset(certificate_types_, 0, sizeof(certificate_types_));
+}
+
+
+CertificateRequest::~CertificateRequest()
+{
+
+ mySTL::for_each(certificate_authorities_.begin(),
+ certificate_authorities_.end(),
+ del_ptr_zero()) ;
+}
+
+
+void CertificateRequest::Build()
+{
+ certificate_types_[0] = rsa_sign;
+ certificate_types_[1] = dss_sign;
+
+ typeTotal_ = 2;
+
+ uint16 authCount = 0;
+ uint16 authSz = 0;
+
+ for (int j = 0; j < authCount; j++) {
+ int sz = REQUEST_HEADER + MIN_DIS_SIZE;
+ DistinguishedName dn;
+ certificate_authorities_.push_back(dn = new (ys) byte[sz]);
+
+ opaque tmp[REQUEST_HEADER];
+ c16toa(MIN_DIS_SIZE, tmp);
+ memcpy(dn, tmp, sizeof(tmp));
+
+ // fill w/ junk for now
+ memcpy(dn, tmp, MIN_DIS_SIZE);
+ authSz += sz;
+ }
+
+ set_length(SIZEOF_ENUM + typeTotal_ + REQUEST_HEADER + authSz);
+}
+
+
+input_buffer& CertificateRequest::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& CertificateRequest::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for CertificateRequest
+input_buffer& operator>>(input_buffer& input, CertificateRequest& request)
+{
+ // types
+ request.typeTotal_ = input[AUTO];
+ for (int i = 0; i < request.typeTotal_; i++)
+ request.certificate_types_[i] = ClientCertificateType(input[AUTO]);
+
+ byte tmp[REQUEST_HEADER];
+ input.read(tmp, sizeof(tmp));
+ uint16 sz;
+ ato16(tmp, sz);
+
+ // authorities
+ while (sz) {
+ uint16 dnSz;
+ input.read(tmp, sizeof(tmp));
+ ato16(tmp, dnSz);
+
+ DistinguishedName dn;
+ request.certificate_authorities_.push_back(dn = new (ys)
+ byte[REQUEST_HEADER + dnSz]);
+ memcpy(dn, tmp, REQUEST_HEADER);
+ input.read(&dn[REQUEST_HEADER], dnSz);
+
+ sz -= dnSz + REQUEST_HEADER;
+ }
+
+ return input;
+}
+
+
+// output operator for CertificateRequest
+output_buffer& operator<<(output_buffer& output,
+ const CertificateRequest& request)
+{
+ // types
+ output[AUTO] = request.typeTotal_;
+ for (int i = 0; i < request.typeTotal_; i++)
+ output[AUTO] = request.certificate_types_[i];
+
+ // authorities
+ opaque tmp[REQUEST_HEADER];
+ c16toa(request.get_length() - SIZEOF_ENUM -
+ request.typeTotal_ - REQUEST_HEADER, tmp);
+ output.write(tmp, sizeof(tmp));
+
+ mySTL::list<DistinguishedName>::const_iterator first =
+ request.certificate_authorities_.begin();
+ mySTL::list<DistinguishedName>::const_iterator last =
+ request.certificate_authorities_.end();
+ while (first != last) {
+ uint16 sz;
+ ato16(*first, sz);
+ output.write(*first, sz + REQUEST_HEADER);
+
+ ++first;
+ }
+
+ return output;
+}
+
+
+// CertificateRequest processing handler
+void CertificateRequest::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useCrypto().use_certManager().setSendVerify();
+}
+
+
+HandShakeType CertificateRequest::get_type() const
+{
+ return certificate_request;
+}
+
+
+// CertificateVerify
+CertificateVerify::CertificateVerify() : signature_(0)
+{}
+
+
+CertificateVerify::~CertificateVerify()
+{
+ ysArrayDelete(signature_);
+}
+
+
+void CertificateVerify::Build(SSL& ssl)
+{
+ build_certHashes(ssl, hashes_);
+
+ uint16 sz = 0;
+ byte len[VERIFY_HEADER];
+ mySTL::auto_ptr<byte> sig(ysArrayDelete);
+
+ // sign
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ if (cert.get_keyType() == rsa_sa_algo) {
+ RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+
+ sz = rsa.get_cipherLength() + VERIFY_HEADER;
+ sig.reset(new (ys) byte[sz]);
+
+ c16toa(sz - VERIFY_HEADER, len);
+ memcpy(sig.get(), len, VERIFY_HEADER);
+ rsa.sign(sig.get() + VERIFY_HEADER, hashes_.md5_, sizeof(Hashes),
+ ssl.getCrypto().get_random());
+ }
+ else { // DSA
+ DSS dss(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+
+ sz = DSS_SIG_SZ + DSS_ENCODED_EXTRA + VERIFY_HEADER;
+ sig.reset(new (ys) byte[sz]);
+
+ c16toa(sz - VERIFY_HEADER, len);
+ memcpy(sig.get(), len, VERIFY_HEADER);
+ dss.sign(sig.get() + VERIFY_HEADER, hashes_.sha_, SHA_LEN,
+ ssl.getCrypto().get_random());
+
+ byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA];
+ TaoCrypt::EncodeDSA_Signature(sig.get() + VERIFY_HEADER, encoded);
+ memcpy(sig.get() + VERIFY_HEADER, encoded, sizeof(encoded));
+ }
+ set_length(sz);
+ signature_ = sig.release();
+}
+
+
+input_buffer& CertificateVerify::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& CertificateVerify::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for CertificateVerify
+input_buffer& operator>>(input_buffer& input, CertificateVerify& request)
+{
+ byte tmp[VERIFY_HEADER];
+ input.read(tmp, sizeof(tmp));
+
+ uint16 sz = 0;
+ ato16(tmp, sz);
+ request.set_length(sz);
+
+ request.signature_ = new (ys) byte[sz];
+ input.read(request.signature_, sz);
+
+ return input;
+}
+
+
+// output operator for CertificateVerify
+output_buffer& operator<<(output_buffer& output,
+ const CertificateVerify& verify)
+{
+ output.write(verify.signature_, verify.get_length());
+
+ return output;
+}
+
+
+// CertificateVerify processing handler
+void CertificateVerify::Process(input_buffer&, SSL& ssl)
+{
+ const Hashes& hashVerify = ssl.getHashes().get_certVerify();
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (cert.get_peerKeyType() == rsa_sa_algo) {
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+
+ if (!rsa.verify(hashVerify.md5_, sizeof(hashVerify), signature_,
+ get_length()))
+ ssl.SetError(verify_error);
+ }
+ else { // DSA
+ byte decodedSig[DSS_SIG_SZ];
+ TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, get_length());
+
+ DSS dss(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!dss.verify(hashVerify.sha_, SHA_LEN, decodedSig, get_length()))
+ ssl.SetError(verify_error);
+ }
+}
+
+
+HandShakeType CertificateVerify::get_type() const
+{
+ return certificate_verify;
+}
+
+
+// output operator for ClientKeyExchange
+output_buffer& operator<<(output_buffer& output, const ClientKeyExchange& ck)
+{
+ output.write(ck.getKey(), ck.getKeyLength());
+ return output;
+}
+
+
+// Client Key Exchange processing handler
+void ClientKeyExchange::Process(input_buffer& input, SSL& ssl)
+{
+ createKey(ssl);
+ if (ssl.GetError()) return;
+ client_key_->read(ssl, input);
+
+ if (ssl.getCrypto().get_certManager().verifyPeer())
+ build_certHashes(ssl, ssl.useHashes().use_certVerify());
+
+ ssl.useStates().useServer() = clientKeyExchangeComplete;
+}
+
+
+ClientKeyExchange::ClientKeyExchange(SSL& ssl)
+{
+ createKey(ssl);
+}
+
+
+ClientKeyExchange::ClientKeyExchange()
+ : client_key_(0)
+{}
+
+
+ClientKeyExchange::~ClientKeyExchange()
+{
+ ysDelete(client_key_);
+}
+
+
+void ClientKeyExchange::build(SSL& ssl)
+{
+ client_key_->build(ssl);
+ set_length(client_key_->get_length());
+}
+
+const opaque* ClientKeyExchange::getKey() const
+{
+ return client_key_->get_clientKey();
+}
+
+
+int ClientKeyExchange::getKeyLength() const
+{
+ return client_key_->get_length();
+}
+
+
+input_buffer& ClientKeyExchange::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& ClientKeyExchange::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ClientKeyExchange::get_type() const
+{
+ return client_key_exchange;
+}
+
+
+// input operator for Finished
+input_buffer& operator>>(input_buffer& input, Finished&)
+{
+ /* do in process */
+
+ return input;
+}
+
+// output operator for Finished
+output_buffer& operator<<(output_buffer& output, const Finished& fin)
+{
+ if (fin.get_length() == FINISHED_SZ) {
+ output.write(fin.hashes_.md5_, MD5_LEN);
+ output.write(fin.hashes_.sha_, SHA_LEN);
+ }
+ else // TLS_FINISHED_SZ
+ output.write(fin.hashes_.md5_, TLS_FINISHED_SZ);
+
+ return output;
+}
+
+
+// Finished processing handler
+void Finished::Process(input_buffer& input, SSL& ssl)
+{
+ // verify hashes
+ const Finished& verify = ssl.getHashes().get_verify();
+ uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ;
+
+ input.read(hashes_.md5_, finishedSz);
+
+ if (memcmp(&hashes_, &verify.hashes_, finishedSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+
+ // read verify mac
+ opaque verifyMAC[SHA_LEN];
+ uint macSz = finishedSz + HANDSHAKE_HEADER;
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verifyMAC, input.get_buffer() + input.get_current()
+ - macSz, macSz, handshake, true);
+ else
+ hmac(ssl, verifyMAC, input.get_buffer() + input.get_current() - macSz,
+ macSz, handshake, true);
+
+ // read mac and fill
+ opaque mac[SHA_LEN]; // max size
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ input.read(mac, digestSz);
+
+ opaque fill;
+ int padSz = ssl.getSecurity().get_parms().encrypt_size_ -
+ HANDSHAKE_HEADER - finishedSz - digestSz;
+ for (int i = 0; i < padSz; i++)
+ fill = input[AUTO];
+
+ // verify mac
+ if (memcmp(mac, verifyMAC, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+
+ // update states
+ ssl.useStates().useHandShake() = handShakeReady;
+ if (ssl.getSecurity().get_parms().entity_ == client_end)
+ ssl.useStates().useClient() = serverFinishedComplete;
+ else
+ ssl.useStates().useServer() = clientFinishedComplete;
+}
+
+
+Finished::Finished()
+{
+ set_length(FINISHED_SZ);
+}
+
+
+uint8* Finished::set_md5()
+{
+ return hashes_.md5_;
+}
+
+
+uint8* Finished::set_sha()
+{
+ return hashes_.sha_;
+}
+
+
+input_buffer& Finished::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& Finished::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType Finished::get_type() const
+{
+ return finished;
+}
+
+
+void clean(volatile opaque* p, uint sz, RandomPool& ran)
+{
+ uint i(0);
+
+ for (i = 0; i < sz; ++i)
+ p[i] = 0;
+
+ ran.Fill(const_cast<opaque*>(p), sz);
+
+ for (i = 0; i < sz; ++i)
+ p[i] = 0;
+}
+
+
+
+Connection::Connection(ProtocolVersion v, RandomPool& ran)
+ : pre_master_secret_(0), sequence_number_(0), peer_sequence_number_(0),
+ pre_secret_len_(0), send_server_key_(false), master_clean_(false),
+ TLS_(v.major_ >= 3 && v.minor_ >= 1), version_(v), random_(ran)
+{}
+
+
+Connection::~Connection()
+{
+ CleanMaster(); CleanPreMaster(); ysArrayDelete(pre_master_secret_);
+}
+
+
+void Connection::AllocPreSecret(uint sz)
+{
+ pre_master_secret_ = new (ys) opaque[pre_secret_len_ = sz];
+}
+
+
+void Connection::TurnOffTLS()
+{
+ TLS_ = false;
+ version_.minor_ = 0;
+}
+
+
+// wipeout master secret
+void Connection::CleanMaster()
+{
+ if (!master_clean_) {
+ volatile opaque* p = master_secret_;
+ clean(p, SECRET_LEN, random_);
+ master_clean_ = true;
+ }
+}
+
+
+// wipeout pre master secret
+void Connection::CleanPreMaster()
+{
+ if (pre_master_secret_) {
+ volatile opaque* p = pre_master_secret_;
+ clean(p, pre_secret_len_, random_);
+
+ ysArrayDelete(pre_master_secret_);
+ pre_master_secret_ = 0;
+ }
+}
+
+
+// Create functions for message factory
+Message* CreateCipherSpec() { return new (ys) ChangeCipherSpec; }
+Message* CreateAlert() { return new (ys) Alert; }
+Message* CreateHandShake() { return new (ys) HandShakeHeader; }
+Message* CreateData() { return new (ys) Data; }
+
+// Create functions for handshake factory
+HandShakeBase* CreateHelloRequest() { return new (ys) HelloRequest; }
+HandShakeBase* CreateClientHello() { return new (ys) ClientHello; }
+HandShakeBase* CreateServerHello() { return new (ys) ServerHello; }
+HandShakeBase* CreateCertificate() { return new (ys) Certificate; }
+HandShakeBase* CreateServerKeyExchange() { return new (ys) ServerKeyExchange;}
+HandShakeBase* CreateCertificateRequest() { return new (ys)
+ CertificateRequest; }
+HandShakeBase* CreateServerHelloDone() { return new (ys) ServerHelloDone; }
+HandShakeBase* CreateCertificateVerify() { return new (ys) CertificateVerify;}
+HandShakeBase* CreateClientKeyExchange() { return new (ys) ClientKeyExchange;}
+HandShakeBase* CreateFinished() { return new (ys) Finished; }
+
+// Create functions for server key exchange factory
+ServerKeyBase* CreateRSAServerKEA() { return new (ys) RSA_Server; }
+ServerKeyBase* CreateDHServerKEA() { return new (ys) DH_Server; }
+ServerKeyBase* CreateFortezzaServerKEA() { return new (ys) Fortezza_Server; }
+
+// Create functions for client key exchange factory
+ClientKeyBase* CreateRSAClient() { return new (ys)
+ EncryptedPreMasterSecret; }
+ClientKeyBase* CreateDHClient() { return new (ys)
+ ClientDiffieHellmanPublic; }
+ClientKeyBase* CreateFortezzaClient() { return new (ys) FortezzaKeys; }
+
+
+// Constructor calls this to Register compile time callbacks
+void InitMessageFactory(MessageFactory& mf)
+{
+ mf.Reserve(4);
+ mf.Register(alert, CreateAlert);
+ mf.Register(change_cipher_spec, CreateCipherSpec);
+ mf.Register(handshake, CreateHandShake);
+ mf.Register(application_data, CreateData);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitHandShakeFactory(HandShakeFactory& hsf)
+{
+ hsf.Reserve(10);
+ hsf.Register(hello_request, CreateHelloRequest);
+ hsf.Register(client_hello, CreateClientHello);
+ hsf.Register(server_hello, CreateServerHello);
+ hsf.Register(certificate, CreateCertificate);
+ hsf.Register(server_key_exchange, CreateServerKeyExchange);
+ hsf.Register(certificate_request, CreateCertificateRequest);
+ hsf.Register(server_hello_done, CreateServerHelloDone);
+ hsf.Register(certificate_verify, CreateCertificateVerify);
+ hsf.Register(client_key_exchange, CreateClientKeyExchange);
+ hsf.Register(finished, CreateFinished);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitServerKeyFactory(ServerKeyFactory& skf)
+{
+ skf.Reserve(3);
+ skf.Register(rsa_kea, CreateRSAServerKEA);
+ skf.Register(diffie_hellman_kea, CreateDHServerKEA);
+ skf.Register(fortezza_kea, CreateFortezzaServerKEA);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitClientKeyFactory(ClientKeyFactory& ckf)
+{
+ ckf.Reserve(3);
+ ckf.Register(rsa_kea, CreateRSAClient);
+ ckf.Register(diffie_hellman_kea, CreateDHClient);
+ ckf.Register(fortezza_kea, CreateFortezzaClient);
+}
+
+
+} // namespace
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
new file mode 100644
index 00000000000..740618ce701
--- /dev/null
+++ b/extra/yassl/src/yassl_int.cpp
@@ -0,0 +1,1997 @@
+/* yassl_int.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* yaSSL internal source implements SSL supporting types not specified in the
+ * draft along with type conversion functions.
+ */
+
+#include "runtime.hpp"
+#include "yassl_int.hpp"
+#include "handshake.hpp"
+#include "timer.hpp"
+#include "openssl/ssl.h" // for DH
+
+
+void* operator new(size_t sz, yaSSL::new_t)
+{
+#ifdef YASSL_PURE_C
+ void* ptr = malloc(sz ? sz : 1);
+ if (!ptr) abort();
+
+ return ptr;
+#else
+ return ::operator new(sz);
+#endif
+}
+
+
+void operator delete(void* ptr, yaSSL::new_t)
+{
+#ifdef YASSL_PURE_C
+ if (ptr) free(ptr);
+#else
+ ::operator delete(ptr);
+#endif
+}
+
+
+void* operator new[](size_t sz, yaSSL::new_t nt)
+{
+ return ::operator new(sz, nt);
+}
+
+
+void operator delete[](void* ptr, yaSSL::new_t nt)
+{
+ ::operator delete(ptr, nt);
+}
+
+
+
+namespace yaSSL {
+
+
+using mySTL::min;
+
+new_t ys; // for yaSSL library new
+
+
+
+// convert a 32 bit integer into a 24 bit one
+void c32to24(uint32 u32, uint24& u24)
+{
+ u24[0] = (u32 >> 16) & 0xff;
+ u24[1] = (u32 >> 8) & 0xff;
+ u24[2] = u32 & 0xff;
+}
+
+
+// convert a 24 bit integer into a 32 bit one
+void c24to32(const uint24 u24, uint32& u32)
+{
+ u32 = 0;
+ u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
+}
+
+
+// convert with return for ease of use
+uint32 c24to32(const uint24 u24)
+{
+ uint32 ret;
+ c24to32(u24, ret);
+
+ return ret;
+}
+
+
+// using a for opaque since underlying type is unsgined char and o is not a
+// good leading identifier
+
+// convert opaque to 16 bit integer
+void ato16(const opaque* c, uint16& u16)
+{
+ u16 = 0;
+ u16 = (c[0] << 8) | (c[1]);
+}
+
+
+// convert (copy) opaque to 24 bit integer
+void ato24(const opaque* c, uint24& u24)
+{
+ u24[0] = c[0];
+ u24[1] = c[1];
+ u24[2] = c[2];
+}
+
+
+// convert 16 bit integer to opaque
+void c16toa(uint16 u16, opaque* c)
+{
+ c[0] = (u16 >> 8) & 0xff;
+ c[1] = u16 & 0xff;
+}
+
+
+// convert 24 bit integer to opaque
+void c24toa(const uint24 u24, opaque* c)
+{
+ c[0] = u24[0];
+ c[1] = u24[1];
+ c[2] = u24[2];
+}
+
+
+// convert 32 bit integer to opaque
+void c32toa(uint32 u32, opaque* c)
+{
+ c[0] = (u32 >> 24) & 0xff;
+ c[1] = (u32 >> 16) & 0xff;
+ c[2] = (u32 >> 8) & 0xff;
+ c[3] = u32 & 0xff;
+}
+
+
+States::States() : recordLayer_(recordReady), handshakeLayer_(preHandshake),
+ clientState_(serverNull), serverState_(clientNull),
+ what_(no_error) {}
+
+const RecordLayerState& States::getRecord() const
+{
+ return recordLayer_;
+}
+
+
+const HandShakeState& States::getHandShake() const
+{
+ return handshakeLayer_;
+}
+
+
+const ClientState& States::getClient() const
+{
+ return clientState_;
+}
+
+
+const ServerState& States::getServer() const
+{
+ return serverState_;
+}
+
+
+const char* States::getString() const
+{
+ return errorString_;
+}
+
+
+YasslError States::What() const
+{
+ return what_;
+}
+
+
+RecordLayerState& States::useRecord()
+{
+ return recordLayer_;
+}
+
+
+HandShakeState& States::useHandShake()
+{
+ return handshakeLayer_;
+}
+
+
+ClientState& States::useClient()
+{
+ return clientState_;
+}
+
+
+ServerState& States::useServer()
+{
+ return serverState_;
+}
+
+
+char* States::useString()
+{
+ return errorString_;
+}
+
+
+void States::SetError(YasslError ye)
+{
+ what_ = ye;
+}
+
+
+sslFactory::sslFactory() :
+ messageFactory_(InitMessageFactory),
+ handShakeFactory_(InitHandShakeFactory),
+ serverKeyFactory_(InitServerKeyFactory),
+ clientKeyFactory_(InitClientKeyFactory)
+{}
+
+
+const MessageFactory& sslFactory::getMessage() const
+{
+ return messageFactory_;
+}
+
+
+const HandShakeFactory& sslFactory::getHandShake() const
+{
+ return handShakeFactory_;
+}
+
+
+const ServerKeyFactory& sslFactory::getServerKey() const
+{
+ return serverKeyFactory_;
+}
+
+
+const ClientKeyFactory& sslFactory::getClientKey() const
+{
+ return clientKeyFactory_;
+}
+
+
+// extract context parameters and store
+SSL::SSL(SSL_CTX* ctx)
+ : secure_(ctx->getMethod()->getVersion(), crypto_.use_random(),
+ ctx->getMethod()->getSide(), ctx->GetCiphers(), ctx)
+{
+ if (int err = crypto_.get_random().GetError()) {
+ SetError(YasslError(err));
+ return;
+ }
+
+ CertManager& cm = crypto_.use_certManager();
+ cm.CopySelfCert(ctx->getCert());
+
+ bool serverSide = secure_.use_parms().entity_ == server_end;
+
+ if (ctx->getKey()) {
+ if (int err = cm.SetPrivateKey(*ctx->getKey())) {
+ SetError(YasslError(err));
+ return;
+ }
+ }
+ else if (serverSide) {
+ SetError(no_key_file);
+ return;
+ }
+
+ if (ctx->getMethod()->verifyPeer())
+ cm.setVerifyPeer();
+ if (ctx->getMethod()->failNoCert())
+ cm.setFailNoCert();
+
+ if (serverSide)
+ crypto_.SetDH(ctx->GetDH_Parms());
+
+ const SSL_CTX::CertList& ca = ctx->GetCA_List();
+ SSL_CTX::CertList::const_iterator first(ca.begin());
+ SSL_CTX::CertList::const_iterator last(ca.end());
+
+ while (first != last) {
+ if (int err = cm.CopyCaCert(*first)) {
+ SetError(YasslError(err));
+ return;
+ }
+ ++first;
+ }
+}
+
+
+// store pending security parameters from Server Hello
+void SSL::set_pending(Cipher suite)
+{
+ Parameters& parms = secure_.use_parms();
+
+ switch (suite) {
+
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_, cipher_names[TLS_RSA_WITH_AES_256_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_, cipher_names[TLS_RSA_WITH_AES_128_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_3DES_EDE_CBC_SHA]
+ , MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_RC4_128_SHA:
+ parms.bulk_cipher_algorithm_ = rc4;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = RC4_KEY_SZ;
+ parms.iv_size_ = 0;
+ parms.cipher_type_ = stream;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) RC4);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_RC4_128_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_RC4_128_MD5:
+ parms.bulk_cipher_algorithm_ = rc4;
+ parms.mac_algorithm_ = md5;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = MD5_LEN;
+ parms.key_size_ = RC4_KEY_SZ;
+ parms.iv_size_ = 0;
+ parms.cipher_type_ = stream;
+ crypto_.setDigest(new (ys) MD5);
+ crypto_.setCipher(new (ys) RC4);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_RC4_128_MD5],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_DHE_RSA_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_256_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_128_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_DHE_DSS_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_256_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_128_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_AES_256_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_AES_128_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_3DES_EDE_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_256_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_128_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_256_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_128_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ default:
+ SetError(unknown_cipher);
+ }
+}
+
+
+// store peer's random
+void SSL::set_random(const opaque* random, ConnectionEnd sender)
+{
+ if (sender == client_end)
+ memcpy(secure_.use_connection().client_random_, random, RAN_LEN);
+ else
+ memcpy(secure_.use_connection().server_random_, random, RAN_LEN);
+}
+
+
+// store client pre master secret
+void SSL::set_preMaster(const opaque* pre, uint sz)
+{
+ secure_.use_connection().AllocPreSecret(sz);
+ memcpy(secure_.use_connection().pre_master_secret_, pre, sz);
+}
+
+
+// store master secret
+void SSL::set_masterSecret(const opaque* sec)
+{
+ memcpy(secure_.use_connection().master_secret_, sec, SECRET_LEN);
+}
+
+// store server issued id
+void SSL::set_sessionID(const opaque* sessionID)
+{
+ memcpy(secure_.use_connection().sessionID_, sessionID, ID_LEN);
+}
+
+
+// store error
+void SSL::SetError(YasslError ye)
+{
+ states_.SetError(ye);
+ //strncpy(states_.useString(), e.what(), mySTL::named_exception::NAME_SIZE);
+ // TODO: add string here
+}
+
+
+// locals
+namespace {
+
+// DeriveKeys and MasterSecret helper sets prefix letters
+static bool setPrefix(opaque* sha_input, int i)
+{
+ switch (i) {
+ case 0:
+ memcpy(sha_input, "A", 1);
+ break;
+ case 1:
+ memcpy(sha_input, "BB", 2);
+ break;
+ case 2:
+ memcpy(sha_input, "CCC", 3);
+ break;
+ case 3:
+ memcpy(sha_input, "DDDD", 4);
+ break;
+ case 4:
+ memcpy(sha_input, "EEEEE", 5);
+ break;
+ case 5:
+ memcpy(sha_input, "FFFFFF", 6);
+ break;
+ case 6:
+ memcpy(sha_input, "GGGGGGG", 7);
+ break;
+ default:
+ return false; // prefix_error
+ }
+ return true;
+}
+
+
+const char handshake_order[] = "Out of order HandShake Message!";
+
+
+} // namespcae for locals
+
+
+void SSL::order_error()
+{
+ SetError(out_of_order);
+}
+
+
+// Create and store the master secret see page 32, 6.1
+void SSL::makeMasterSecret()
+{
+ if (isTLS())
+ makeTLSMasterSecret();
+ else {
+ opaque sha_output[SHA_LEN];
+
+ const uint& preSz = secure_.get_connection().pre_secret_len_;
+ output_buffer md5_input(preSz + SHA_LEN);
+ output_buffer sha_input(PREFIX + preSz + 2 * RAN_LEN);
+
+ MD5 md5;
+ SHA sha;
+
+ md5_input.write(secure_.get_connection().pre_master_secret_, preSz);
+
+ for (int i = 0; i < MASTER_ROUNDS; ++i) {
+ opaque prefix[PREFIX];
+ if (!setPrefix(prefix, i)) {
+ SetError(prefix_error);
+ return;
+ }
+
+ sha_input.set_current(0);
+ sha_input.write(prefix, i + 1);
+
+ sha_input.write(secure_.get_connection().pre_master_secret_,preSz);
+ sha_input.write(secure_.get_connection().client_random_, RAN_LEN);
+ sha_input.write(secure_.get_connection().server_random_, RAN_LEN);
+ sha.get_digest(sha_output, sha_input.get_buffer(),
+ sha_input.get_size());
+
+ md5_input.set_current(preSz);
+ md5_input.write(sha_output, SHA_LEN);
+ md5.get_digest(&secure_.use_connection().master_secret_[i*MD5_LEN],
+ md5_input.get_buffer(), md5_input.get_size());
+ }
+ deriveKeys();
+ }
+ secure_.use_connection().CleanPreMaster();
+}
+
+
+// create TLSv1 master secret
+void SSL::makeTLSMasterSecret()
+{
+ opaque seed[SEED_LEN];
+
+ memcpy(seed, secure_.get_connection().client_random_, RAN_LEN);
+ memcpy(&seed[RAN_LEN], secure_.get_connection().server_random_, RAN_LEN);
+
+ PRF(secure_.use_connection().master_secret_, SECRET_LEN,
+ secure_.get_connection().pre_master_secret_,
+ secure_.get_connection().pre_secret_len_,
+ master_label, MASTER_LABEL_SZ,
+ seed, SEED_LEN);
+
+ deriveTLSKeys();
+}
+
+
+// derive mac, write, and iv keys for server and client, see page 34, 6.2.2
+void SSL::deriveKeys()
+{
+ int length = 2 * secure_.get_parms().hash_size_ +
+ 2 * secure_.get_parms().key_size_ +
+ 2 * secure_.get_parms().iv_size_;
+ int rounds = length / MD5_LEN + ((length % MD5_LEN) ? 1 : 0);
+ input_buffer key_data(rounds * MD5_LEN);
+
+ opaque sha_output[SHA_LEN];
+ opaque md5_input[SECRET_LEN + SHA_LEN];
+ opaque sha_input[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
+
+ MD5 md5;
+ SHA sha;
+
+ memcpy(md5_input, secure_.get_connection().master_secret_, SECRET_LEN);
+
+ for (int i = 0; i < rounds; ++i) {
+ int j = i + 1;
+ if (!setPrefix(sha_input, i)) {
+ SetError(prefix_error);
+ return;
+ }
+
+ memcpy(&sha_input[j], secure_.get_connection().master_secret_,
+ SECRET_LEN);
+ memcpy(&sha_input[j+SECRET_LEN],
+ secure_.get_connection().server_random_, RAN_LEN);
+ memcpy(&sha_input[j + SECRET_LEN + RAN_LEN],
+ secure_.get_connection().client_random_, RAN_LEN);
+ sha.get_digest(sha_output, sha_input,
+ sizeof(sha_input) - KEY_PREFIX + j);
+
+ memcpy(&md5_input[SECRET_LEN], sha_output, SHA_LEN);
+ md5.get_digest(key_data.get_buffer() + i * MD5_LEN,
+ md5_input, sizeof(md5_input));
+ }
+ storeKeys(key_data.get_buffer());
+}
+
+
+// derive mac, write, and iv keys for server and client
+void SSL::deriveTLSKeys()
+{
+ int length = 2 * secure_.get_parms().hash_size_ +
+ 2 * secure_.get_parms().key_size_ +
+ 2 * secure_.get_parms().iv_size_;
+ opaque seed[SEED_LEN];
+ input_buffer key_data(length);
+
+ memcpy(seed, secure_.get_connection().server_random_, RAN_LEN);
+ memcpy(&seed[RAN_LEN], secure_.get_connection().client_random_, RAN_LEN);
+
+ PRF(key_data.get_buffer(), length, secure_.get_connection().master_secret_,
+ SECRET_LEN, key_label, KEY_LABEL_SZ, seed, SEED_LEN);
+
+ storeKeys(key_data.get_buffer());
+}
+
+
+// store mac, write, and iv keys for client and server
+void SSL::storeKeys(const opaque* key_data)
+{
+ int sz = secure_.get_parms().hash_size_;
+ memcpy(secure_.use_connection().client_write_MAC_secret_, key_data, sz);
+ int i = sz;
+ memcpy(secure_.use_connection().server_write_MAC_secret_,&key_data[i], sz);
+ i += sz;
+
+ sz = secure_.get_parms().key_size_;
+ memcpy(secure_.use_connection().client_write_key_, &key_data[i], sz);
+ i += sz;
+ memcpy(secure_.use_connection().server_write_key_, &key_data[i], sz);
+ i += sz;
+
+ sz = secure_.get_parms().iv_size_;
+ memcpy(secure_.use_connection().client_write_IV_, &key_data[i], sz);
+ i += sz;
+ memcpy(secure_.use_connection().server_write_IV_, &key_data[i], sz);
+
+ setKeys();
+}
+
+
+// set encrypt/decrypt keys and ivs
+void SSL::setKeys()
+{
+ Connection& conn = secure_.use_connection();
+
+ if (secure_.get_parms().entity_ == client_end) {
+ crypto_.use_cipher().set_encryptKey(conn.client_write_key_,
+ conn.client_write_IV_);
+ crypto_.use_cipher().set_decryptKey(conn.server_write_key_,
+ conn.server_write_IV_);
+ }
+ else {
+ crypto_.use_cipher().set_encryptKey(conn.server_write_key_,
+ conn.server_write_IV_);
+ crypto_.use_cipher().set_decryptKey(conn.client_write_key_,
+ conn.client_write_IV_);
+ }
+}
+
+
+
+// local functors
+namespace yassl_int_cpp_local1 { // for explicit templates
+
+struct SumData {
+ uint total_;
+ SumData() : total_(0) {}
+ void operator()(input_buffer* data) { total_ += data->get_remaining(); }
+};
+
+
+struct SumBuffer {
+ uint total_;
+ SumBuffer() : total_(0) {}
+ void operator()(output_buffer* buffer) { total_ += buffer->get_size(); }
+};
+
+} // namespace for locals
+using namespace yassl_int_cpp_local1;
+
+
+uint SSL::bufferedData()
+{
+ return mySTL::for_each(buffers_.getData().begin(),buffers_.getData().end(),
+ SumData()).total_;
+}
+
+
+// use input buffer to fill data
+void SSL::fillData(Data& data)
+{
+ if (GetError()) return;
+ uint dataSz = data.get_length(); // input, data size to fill
+ uint elements = buffers_.getData().size();
+
+ data.set_length(0); // output, actual data filled
+ dataSz = min(dataSz, bufferedData());
+
+ for (uint i = 0; i < elements; i++) {
+ input_buffer* front = buffers_.getData().front();
+ uint frontSz = front->get_remaining();
+ uint readSz = min(dataSz - data.get_length(), frontSz);
+
+ front->read(data.set_buffer() + data.get_length(), readSz);
+ data.set_length(data.get_length() + readSz);
+
+ if (readSz == frontSz) {
+ buffers_.useData().pop_front();
+ ysDelete(front);
+ }
+ if (data.get_length() == dataSz)
+ break;
+ }
+}
+
+
+// flush output buffer
+void SSL::flushBuffer()
+{
+ if (GetError()) return;
+
+ uint sz = mySTL::for_each(buffers_.getHandShake().begin(),
+ buffers_.getHandShake().end(),
+ SumBuffer()).total_;
+ output_buffer out(sz);
+ uint elements = buffers_.getHandShake().size();
+
+ for (uint i = 0; i < elements; i++) {
+ output_buffer* front = buffers_.getHandShake().front();
+ out.write(front->get_buffer(), front->get_size());
+
+ buffers_.useHandShake().pop_front();
+ ysDelete(front);
+ }
+ Send(out.get_buffer(), out.get_size());
+}
+
+
+void SSL::Send(const byte* buffer, uint sz)
+{
+ if (socket_.send(buffer, sz) != sz)
+ SetError(send_error);
+}
+
+
+// get sequence number, if verify get peer's
+uint SSL::get_SEQIncrement(bool verify)
+{
+ if (verify)
+ return secure_.use_connection().peer_sequence_number_++;
+ else
+ return secure_.use_connection().sequence_number_++;
+}
+
+
+const byte* SSL::get_macSecret(bool verify)
+{
+ if ( (secure_.get_parms().entity_ == client_end && !verify) ||
+ (secure_.get_parms().entity_ == server_end && verify) )
+ return secure_.get_connection().client_write_MAC_secret_;
+ else
+ return secure_.get_connection().server_write_MAC_secret_;
+}
+
+
+void SSL::verifyState(const RecordLayerHeader& rlHeader)
+{
+ if (GetError()) return;
+
+ if (states_.getRecord() == recordNotReady ||
+ (rlHeader.type_ == application_data && // data and handshake
+ states_.getHandShake() != handShakeReady) ) // isn't complete yet
+ SetError(record_layer);
+}
+
+
+void SSL::verifyState(const HandShakeHeader& hsHeader)
+{
+ if (GetError()) return;
+
+ if (states_.getHandShake() == handShakeNotReady) {
+ SetError(handshake_layer);
+ return;
+ }
+
+ if (secure_.get_parms().entity_ == client_end)
+ verifyClientState(hsHeader.get_handshakeType());
+ else
+ verifyServerState(hsHeader.get_handshakeType());
+}
+
+
+void SSL::verifyState(ClientState cs)
+{
+ if (GetError()) return;
+ if (states_.getClient() != cs) order_error();
+}
+
+
+void SSL::verifyState(ServerState ss)
+{
+ if (GetError()) return;
+ if (states_.getServer() != ss) order_error();
+}
+
+
+void SSL::verfiyHandShakeComplete()
+{
+ if (GetError()) return;
+ if (states_.getHandShake() != handShakeReady) order_error();
+}
+
+
+void SSL::verifyClientState(HandShakeType hsType)
+{
+ if (GetError()) return;
+
+ switch(hsType) {
+ case server_hello :
+ if (states_.getClient() != serverNull)
+ order_error();
+ break;
+ case certificate :
+ if (states_.getClient() != serverHelloComplete)
+ order_error();
+ break;
+ case server_key_exchange :
+ if (states_.getClient() != serverCertComplete)
+ order_error();
+ break;
+ case certificate_request :
+ if (states_.getClient() != serverCertComplete &&
+ states_.getClient() != serverKeyExchangeComplete)
+ order_error();
+ break;
+ case server_hello_done :
+ if (states_.getClient() != serverCertComplete &&
+ states_.getClient() != serverKeyExchangeComplete)
+ order_error();
+ break;
+ case finished :
+ if (states_.getClient() != serverHelloDoneComplete ||
+ secure_.get_parms().pending_) // no change
+ order_error(); // cipher yet
+ break;
+ default :
+ order_error();
+ };
+}
+
+
+void SSL::verifyServerState(HandShakeType hsType)
+{
+ if (GetError()) return;
+
+ switch(hsType) {
+ case client_hello :
+ if (states_.getServer() != clientNull)
+ order_error();
+ break;
+ case certificate :
+ if (states_.getServer() != clientHelloComplete)
+ order_error();
+ break;
+ case client_key_exchange :
+ if (states_.getServer() != clientHelloComplete)
+ order_error();
+ break;
+ case certificate_verify :
+ if (states_.getServer() != clientKeyExchangeComplete)
+ order_error();
+ break;
+ case finished :
+ if (states_.getServer() != clientKeyExchangeComplete ||
+ secure_.get_parms().pending_) // no change
+ order_error(); // cipher yet
+ break;
+ default :
+ order_error();
+ };
+}
+
+
+// try to find a suite match
+void SSL::matchSuite(const opaque* peer, uint length)
+{
+ if (length == 0 || (length % 2) != 0) {
+ SetError(bad_input);
+ return;
+ }
+
+ // start with best, if a match we are good, Ciphers are at odd index
+ // since all SSL and TLS ciphers have 0x00 first byte
+ for (uint i = 1; i < secure_.get_parms().suites_size_; i += 2)
+ for (uint j = 1; j < length; j+= 2)
+ if (secure_.use_parms().suites_[i] == peer[j]) {
+ secure_.use_parms().suite_[0] = 0x00;
+ secure_.use_parms().suite_[1] = peer[j];
+ return;
+ }
+
+ SetError(match_error);
+}
+
+
+void SSL::set_session(SSL_SESSION* s)
+{
+ if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume()))
+ secure_.set_resuming(true);
+}
+
+
+const Crypto& SSL::getCrypto() const
+{
+ return crypto_;
+}
+
+
+const Security& SSL::getSecurity() const
+{
+ return secure_;
+}
+
+
+const States& SSL::getStates() const
+{
+ return states_;
+}
+
+
+const sslHashes& SSL::getHashes() const
+{
+ return hashes_;
+}
+
+
+const sslFactory& SSL::getFactory() const
+{
+ return GetSSL_Factory();
+}
+
+
+const Socket& SSL::getSocket() const
+{
+ return socket_;
+}
+
+
+YasslError SSL::GetError() const
+{
+ return states_.What();
+}
+
+
+Crypto& SSL::useCrypto()
+{
+ return crypto_;
+}
+
+
+Security& SSL::useSecurity()
+{
+ return secure_;
+}
+
+
+States& SSL::useStates()
+{
+ return states_;
+}
+
+
+sslHashes& SSL::useHashes()
+{
+ return hashes_;
+}
+
+
+Socket& SSL::useSocket()
+{
+ return socket_;
+}
+
+
+Log& SSL::useLog()
+{
+ return log_;
+}
+
+
+bool SSL::isTLS() const
+{
+ return secure_.get_connection().TLS_;
+}
+
+
+void SSL::addData(input_buffer* data)
+{
+ buffers_.useData().push_back(data);
+}
+
+
+void SSL::addBuffer(output_buffer* b)
+{
+ buffers_.useHandShake().push_back(b);
+}
+
+
+// store connection parameters
+SSL_SESSION::SSL_SESSION(const SSL& ssl, RandomPool& ran)
+ : timeout_(DEFAULT_TIMEOUT), random_(ran)
+{
+ const Connection& conn = ssl.getSecurity().get_connection();
+
+ memcpy(sessionID_, conn.sessionID_, ID_LEN);
+ memcpy(master_secret_, conn.master_secret_, SECRET_LEN);
+ memcpy(suite_, ssl.getSecurity().get_parms().suite_, SUITE_LEN);
+
+ bornOn_ = lowResTimer();
+}
+
+
+// for resumption copy in ssl::parameters
+SSL_SESSION::SSL_SESSION(RandomPool& ran)
+ : bornOn_(0), timeout_(0), random_(ran)
+{
+ memset(sessionID_, 0, ID_LEN);
+ memset(master_secret_, 0, SECRET_LEN);
+ memset(suite_, 0, SUITE_LEN);
+}
+
+
+SSL_SESSION& SSL_SESSION::operator=(const SSL_SESSION& that)
+{
+ memcpy(sessionID_, that.sessionID_, ID_LEN);
+ memcpy(master_secret_, that.master_secret_, SECRET_LEN);
+ memcpy(suite_, that.suite_, SUITE_LEN);
+
+ bornOn_ = that.bornOn_;
+ timeout_ = that.timeout_;
+
+ return *this;
+}
+
+
+const opaque* SSL_SESSION::GetID() const
+{
+ return sessionID_;
+}
+
+
+const opaque* SSL_SESSION::GetSecret() const
+{
+ return master_secret_;
+}
+
+
+const Cipher* SSL_SESSION::GetSuite() const
+{
+ return suite_;
+}
+
+
+uint SSL_SESSION::GetBornOn() const
+{
+ return bornOn_;
+}
+
+
+uint SSL_SESSION::GetTimeOut() const
+{
+ return timeout_;
+}
+
+
+void SSL_SESSION::SetTimeOut(uint t)
+{
+ timeout_ = t;
+}
+
+
+extern void clean(volatile opaque*, uint, RandomPool&);
+
+
+// clean up secret data
+SSL_SESSION::~SSL_SESSION()
+{
+ volatile opaque* p = master_secret_;
+ clean(p, SECRET_LEN, random_);
+}
+
+
+Sessions Sessions::instance_; // simple singleton
+
+Sessions& GetSessions()
+{
+ return Sessions::instance_;
+}
+
+
+sslFactory sslFactory::instance_; // simple singleton
+
+sslFactory& GetSSL_Factory()
+{
+ return sslFactory::instance_;
+}
+
+
+typedef Mutex::Lock Lock;
+
+
+void Sessions::add(const SSL& ssl)
+{
+ Lock guard(mutex_);
+ list_.push_back(new (ys) SSL_SESSION(ssl, random_));
+}
+
+
+Sessions::~Sessions()
+{
+ mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero());
+}
+
+
+// locals
+namespace yassl_int_cpp_local2 { // for explicit templates
+
+typedef mySTL::list<SSL_SESSION*>::iterator iterator;
+
+struct sess_match {
+ const opaque* id_;
+ explicit sess_match(const opaque* p) : id_(p) {}
+
+ bool operator()(SSL_SESSION* sess)
+ {
+ if ( memcmp(sess->GetID(), id_, ID_LEN) == 0)
+ return true;
+ return false;
+ }
+};
+
+
+} // local namespace
+using namespace yassl_int_cpp_local2;
+
+
+// lookup session by id, return a copy if space provided
+SSL_SESSION* Sessions::lookup(const opaque* id, SSL_SESSION* copy)
+{
+ Lock guard(mutex_);
+ iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id));
+
+ if (find != list_.end()) {
+ uint current = lowResTimer();
+ if ( ((*find)->GetBornOn() + (*find)->GetTimeOut()) < current) {
+ del_ptr_zero()(*find);
+ list_.erase(find);
+ return 0;
+ }
+ if (copy)
+ *copy = *(*find);
+ return *find;
+ }
+ return 0;
+}
+
+
+// remove a session by id
+void Sessions::remove(const opaque* id)
+{
+ Lock guard(mutex_);
+ iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id));
+
+ if (find != list_.end()) {
+ del_ptr_zero()(*find);
+ list_.erase(find);
+ }
+}
+
+
+SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv)
+ : version_(pv), side_(ce), verifyPeer_(false), failNoCert_(false)
+{}
+
+
+ProtocolVersion SSL_METHOD::getVersion() const
+{
+ return version_;
+}
+
+
+ConnectionEnd SSL_METHOD::getSide() const
+{
+ return side_;
+}
+
+
+void SSL_METHOD::setVerifyPeer()
+{
+ verifyPeer_ = true;
+}
+
+
+void SSL_METHOD::setFailNoCert()
+{
+ failNoCert_ = true;
+}
+
+
+bool SSL_METHOD::verifyPeer() const
+{
+ return verifyPeer_;
+}
+
+
+bool SSL_METHOD::failNoCert() const
+{
+ return failNoCert_;
+}
+
+
+SSL_CTX::SSL_CTX(SSL_METHOD* meth)
+ : method_(meth), certificate_(0), privateKey_(0)
+{}
+
+
+SSL_CTX::~SSL_CTX()
+{
+ ysDelete(method_);
+ ysDelete(certificate_);
+ ysDelete(privateKey_);
+
+ mySTL::for_each(caList_.begin(), caList_.end(), del_ptr_zero());
+}
+
+
+void SSL_CTX::AddCA(x509* ca)
+{
+ caList_.push_back(ca);
+}
+
+
+const SSL_CTX::CertList&
+SSL_CTX::GetCA_List() const
+{
+ return caList_;
+}
+
+
+const x509* SSL_CTX::getCert() const
+{
+ return certificate_;
+}
+
+
+const x509* SSL_CTX::getKey() const
+{
+ return privateKey_;
+}
+
+
+const SSL_METHOD* SSL_CTX::getMethod() const
+{
+ return method_;
+}
+
+
+const Ciphers& SSL_CTX::GetCiphers() const
+{
+ return ciphers_;
+}
+
+
+const DH_Parms& SSL_CTX::GetDH_Parms() const
+{
+ return dhParms_;
+}
+
+
+const Stats& SSL_CTX::GetStats() const
+{
+ return stats_;
+}
+
+
+void SSL_CTX::setVerifyPeer()
+{
+ method_->setVerifyPeer();
+}
+
+
+void SSL_CTX::setFailNoCert()
+{
+ method_->setFailNoCert();
+}
+
+
+bool SSL_CTX::SetDH(const DH& dh)
+{
+ dhParms_.p_ = dh.p->int_;
+ dhParms_.g_ = dh.g->int_;
+
+ return dhParms_.set_ = true;
+}
+
+
+bool SSL_CTX::SetCipherList(const char* list)
+{
+ if (!list)
+ return false;
+
+ bool ret = false;
+ char name[MAX_SUITE_NAME];
+
+ char needle[] = ":";
+ char* haystack = const_cast<char*>(list);
+ char* prev;
+
+ const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]);
+ int idx = 0;
+
+ for(;;) {
+ int len;
+ prev = haystack;
+ haystack = strstr(haystack, needle);
+
+ if (!haystack) // last cipher
+ len = min(sizeof(name), strlen(prev));
+ else
+ len = min(sizeof(name), (size_t)(haystack - prev));
+
+ strncpy(name, prev, len);
+ name[(len == sizeof(name)) ? len - 1 : len] = 0;
+
+ for (int i = 0; i < suiteSz; i++)
+ if (strncmp(name, cipher_names[i], sizeof(name)) == 0) {
+
+ ciphers_.suites_[idx++] = 0x00; // first byte always zero
+ ciphers_.suites_[idx++] = i;
+
+ if (!ret) ret = true; // found at least one
+ break;
+ }
+ if (!haystack) break;
+ haystack++;
+ }
+
+ if (ret) {
+ ciphers_.setSuites_ = true;
+ ciphers_.suiteSz_ = idx;
+ }
+
+ return ret;
+}
+
+
+void SSL_CTX::IncrementStats(StatsField fd)
+{
+
+ Lock guard(mutex_);
+
+ switch (fd) {
+
+ case Accept:
+ ++stats_.accept_;
+ break;
+
+ case Connect:
+ ++stats_.connect_;
+ break;
+
+ case AcceptGood:
+ ++stats_.acceptGood_;
+ break;
+
+ case ConnectGood:
+ ++stats_.connectGood_;
+ break;
+
+ case AcceptRenegotiate:
+ ++stats_.acceptRenegotiate_;
+ break;
+
+ case ConnectRenegotiate:
+ ++stats_.connectRenegotiate_;
+ break;
+
+ case Hits:
+ ++stats_.hits_;
+ break;
+
+ case CbHits:
+ ++stats_.cbHits_;
+ break;
+
+ case CacheFull:
+ ++stats_.cacheFull_;
+ break;
+
+ case Misses:
+ ++stats_.misses_;
+ break;
+
+ case Timeouts:
+ ++stats_.timeouts_;
+ break;
+
+ case Number:
+ ++stats_.number_;
+ break;
+
+ case GetCacheSize:
+ ++stats_.getCacheSize_;
+ break;
+
+ case VerifyMode:
+ ++stats_.verifyMode_;
+ break;
+
+ case VerifyDepth:
+ ++stats_.verifyDepth_;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+Crypto::Crypto()
+ : digest_(0), cipher_(0), dh_(0)
+{}
+
+
+Crypto::~Crypto()
+{
+ ysDelete(dh_);
+ ysDelete(cipher_);
+ ysDelete(digest_);
+}
+
+
+const Digest& Crypto::get_digest() const
+{
+ return *digest_;
+}
+
+
+const BulkCipher& Crypto::get_cipher() const
+{
+ return *cipher_;
+}
+
+
+const DiffieHellman& Crypto::get_dh() const
+{
+ return *dh_;
+}
+
+
+const RandomPool& Crypto::get_random() const
+{
+ return random_;
+}
+
+
+const CertManager& Crypto::get_certManager() const
+{
+ return cert_;
+}
+
+
+
+Digest& Crypto::use_digest()
+{
+ return *digest_;
+}
+
+
+BulkCipher& Crypto::use_cipher()
+{
+ return *cipher_;
+}
+
+
+DiffieHellman& Crypto::use_dh()
+{
+ return *dh_;
+}
+
+
+RandomPool& Crypto::use_random()
+{
+ return random_;
+}
+
+
+CertManager& Crypto::use_certManager()
+{
+ return cert_;
+}
+
+
+
+void Crypto::SetDH(DiffieHellman* dh)
+{
+ dh_ = dh;
+}
+
+
+void Crypto::SetDH(const DH_Parms& dh)
+{
+ if (dh.set_)
+ dh_ = new (ys) DiffieHellman(dh.p_, dh.g_, random_);
+}
+
+
+bool Crypto::DhSet()
+{
+ return dh_ != 0;
+}
+
+
+void Crypto::setDigest(Digest* digest)
+{
+ digest_ = digest;
+}
+
+
+void Crypto::setCipher(BulkCipher* c)
+{
+ cipher_ = c;
+}
+
+
+const MD5& sslHashes::get_MD5() const
+{
+ return md5HandShake_;
+}
+
+
+const SHA& sslHashes::get_SHA() const
+{
+ return shaHandShake_;
+}
+
+
+const Finished& sslHashes::get_verify() const
+{
+ return verify_;
+}
+
+
+const Hashes& sslHashes::get_certVerify() const
+{
+ return certVerify_;
+}
+
+
+MD5& sslHashes::use_MD5(){
+ return md5HandShake_;
+}
+
+
+SHA& sslHashes::use_SHA()
+{
+ return shaHandShake_;
+}
+
+
+Finished& sslHashes::use_verify()
+{
+ return verify_;
+}
+
+
+Hashes& sslHashes::use_certVerify()
+{
+ return certVerify_;
+}
+
+
+Buffers::~Buffers()
+{
+ mySTL::for_each(handShakeList_.begin(), handShakeList_.end(),
+ del_ptr_zero()) ;
+ mySTL::for_each(dataList_.begin(), dataList_.end(),
+ del_ptr_zero()) ;
+}
+
+
+const Buffers::inputList& Buffers::getData() const
+{
+ return dataList_;
+}
+
+
+const Buffers::outputList& Buffers::getHandShake() const
+{
+ return handShakeList_;
+}
+
+
+Buffers::inputList& Buffers::useData()
+{
+ return dataList_;
+}
+
+
+Buffers::outputList& Buffers::useHandShake()
+{
+ return handShakeList_;
+}
+
+
+Security::Security(ProtocolVersion pv, RandomPool& ran, ConnectionEnd ce,
+ const Ciphers& ciphers, SSL_CTX* ctx)
+ : conn_(pv, ran), parms_(ce, ciphers, pv), resumeSession_(ran), ctx_(ctx),
+ resuming_(false)
+{}
+
+
+const Connection& Security::get_connection() const
+{
+ return conn_;
+}
+
+
+const SSL_CTX* Security::GetContext() const
+{
+ return ctx_;
+}
+
+
+const Parameters& Security::get_parms() const
+{
+ return parms_;
+}
+
+
+const SSL_SESSION& Security::get_resume() const
+{
+ return resumeSession_;
+}
+
+
+bool Security::get_resuming() const
+{
+ return resuming_;
+}
+
+
+Connection& Security::use_connection()
+{
+ return conn_;
+}
+
+
+Parameters& Security::use_parms()
+{
+ return parms_;
+}
+
+
+SSL_SESSION& Security::use_resume()
+{
+ return resumeSession_;
+}
+
+
+void Security::set_resuming(bool b)
+{
+ resuming_ = b;
+}
+
+
+X509_NAME::X509_NAME(const char* n, size_t sz)
+ : name_(0)
+{
+ if (sz) {
+ name_ = new (ys) char[sz];
+ memcpy(name_, n, sz);
+ }
+}
+
+
+X509_NAME::~X509_NAME()
+{
+ ysArrayDelete(name_);
+}
+
+
+char* X509_NAME::GetName()
+{
+ return name_;
+}
+
+
+X509::X509(const char* i, size_t iSz, const char* s, size_t sSz)
+ : issuer_(i, iSz), subject_(s, sSz)
+{}
+
+
+X509_NAME* X509::GetIssuer()
+{
+ return &issuer_;
+}
+
+
+X509_NAME* X509::GetSubject()
+{
+ return &subject_;
+}
+
+
+
+} // namespace
+
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+namespace mySTL {
+template yaSSL::yassl_int_cpp_local1::SumData for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData);
+template yaSSL::yassl_int_cpp_local1::SumBuffer for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer);
+template mySTL::list<yaSSL::SSL_SESSION*>::iterator find_if<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match);
+}
+#endif
+
diff --git a/extra/yassl/taocrypt/Makefile.am b/extra/yassl/taocrypt/Makefile.am
new file mode 100644
index 00000000000..af3ded7abfd
--- /dev/null
+++ b/extra/yassl/taocrypt/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = src
+EXTRA_DIST = taocrypt.dsw taocrypt.dsp
diff --git a/extra/yassl/taocrypt/include/aes.hpp b/extra/yassl/taocrypt/include/aes.hpp
new file mode 100644
index 00000000000..b8436d35c5f
--- /dev/null
+++ b/extra/yassl/taocrypt/include/aes.hpp
@@ -0,0 +1,90 @@
+/* aes.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* aes.hpp defines AES
+*/
+
+
+#ifndef TAO_CRYPT_AES_HPP
+#define TAO_CRYPT_AES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+#include "modes.hpp"
+#include "block.hpp"
+
+namespace TaoCrypt {
+
+enum { AES_BLOCK_SIZE = 16 };
+
+
+// AES encryption and decryption, see FIPS-197
+class AES : public Mode_BASE {
+public:
+ enum { BLOCK_SIZE = AES_BLOCK_SIZE };
+
+ AES(CipherDir DIR, Mode MODE)
+ : Mode_BASE(BLOCK_SIZE), dir_(DIR), mode_(MODE) {}
+
+ void Process(byte*, const byte*, word32);
+ void SetKey(const byte* iv, word32 sz, CipherDir fake = ENCRYPTION);
+
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ CipherDir dir_;
+ Mode mode_;
+
+ static const word32 Te0[256];
+ static const word32 Te1[256];
+ static const word32 Te2[256];
+ static const word32 Te3[256];
+ static const word32 Te4[256];
+
+ static const word32 Td0[256];
+ static const word32 Td1[256];
+ static const word32 Td2[256];
+ static const word32 Td3[256];
+ static const word32 Td4[256];
+
+ static const word32 rcon_[];
+
+ word32 rounds_;
+ Word32Block key_;
+
+ void encrypt(const byte*, const byte*, byte*) const;
+ void decrypt(const byte*, const byte*, byte*) const;
+
+ AES(const AES&); // hide copy
+ AES& operator=(const AES&); // and assign
+};
+
+
+typedef BlockCipher<ENCRYPTION, AES, ECB> AES_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, AES, ECB> AES_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, AES, CBC> AES_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, AES, CBC> AES_CBC_Decryption;
+
+
+
+} // naemspace
+
+#endif // TAO_CRYPT_AES_HPP
diff --git a/extra/yassl/taocrypt/include/algebra.hpp b/extra/yassl/taocrypt/include/algebra.hpp
new file mode 100644
index 00000000000..a09ac8dce16
--- /dev/null
+++ b/extra/yassl/taocrypt/include/algebra.hpp
@@ -0,0 +1,228 @@
+/* algebra.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's algebra.h from CryptoPP */
+
+#ifndef TAO_CRYPT_ALGEBRA_HPP
+#define TAO_CRYPT_ALGEBRA_HPP
+
+#include "integer.hpp"
+
+namespace TaoCrypt {
+
+
+// "const Element&" returned by member functions are references
+// to internal data members. Since each object may have only
+// one such data member for holding results, the following code
+// will produce incorrect results:
+// abcd = group.Add(group.Add(a,b), group.Add(c,d));
+// But this should be fine:
+// abcd = group.Add(a, group.Add(b, group.Add(c,d));
+
+// Abstract Group
+class TAOCRYPT_NO_VTABLE AbstractGroup : public virtual_base
+{
+public:
+ typedef Integer Element;
+
+ virtual ~AbstractGroup() {}
+
+ virtual bool Equal(const Element &a, const Element &b) const =0;
+ virtual const Element& Identity() const =0;
+ virtual const Element& Add(const Element &a, const Element &b) const =0;
+ virtual const Element& Inverse(const Element &a) const =0;
+ virtual bool InversionIsFast() const {return false;}
+
+ virtual const Element& Double(const Element &a) const;
+ virtual const Element& Subtract(const Element &a, const Element &b) const;
+ virtual Element& Accumulate(Element &a, const Element &b) const;
+ virtual Element& Reduce(Element &a, const Element &b) const;
+
+ virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
+ virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const;
+
+ virtual void SimultaneousMultiply(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const;
+};
+
+// Abstract Ring
+class TAOCRYPT_NO_VTABLE AbstractRing : public AbstractGroup
+{
+public:
+ typedef Integer Element;
+
+ AbstractRing() : AbstractGroup() {m_mg.m_pRing = this;}
+ AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
+ AbstractRing& operator=(const AbstractRing &source) {return *this;}
+
+ virtual bool IsUnit(const Element &a) const =0;
+ virtual const Element& MultiplicativeIdentity() const =0;
+ virtual const Element& Multiply(const Element&, const Element&) const =0;
+ virtual const Element& MultiplicativeInverse(const Element &a) const =0;
+
+ virtual const Element& Square(const Element &a) const;
+ virtual const Element& Divide(const Element &a, const Element &b) const;
+
+ virtual Element Exponentiate(const Element &a, const Integer &e) const;
+ virtual Element CascadeExponentiate(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const;
+
+ virtual void SimultaneousExponentiate(Element *results, const Element&,
+ const Integer *exponents, unsigned int exponentsCount) const;
+
+ virtual const AbstractGroup& MultiplicativeGroup() const
+ {return m_mg;}
+
+private:
+ class MultiplicativeGroupT : public AbstractGroup
+ {
+ public:
+ const AbstractRing& GetRing() const
+ {return *m_pRing;}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return GetRing().Equal(a, b);}
+
+ const Element& Identity() const
+ {return GetRing().MultiplicativeIdentity();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return GetRing().Multiply(a, b);}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return a = GetRing().Multiply(a, b);}
+
+ const Element& Inverse(const Element &a) const
+ {return GetRing().MultiplicativeInverse(a);}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return GetRing().Divide(a, b);}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a = GetRing().Divide(a, b);}
+
+ const Element& Double(const Element &a) const
+ {return GetRing().Square(a);}
+
+ Element ScalarMultiply(const Element &a, const Integer &e) const
+ {return GetRing().Exponentiate(a, e);}
+
+ Element CascadeScalarMultiply(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const
+ {return GetRing().CascadeExponentiate(x, e1, y, e2);}
+
+ void SimultaneousMultiply(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const
+ {GetRing().SimultaneousExponentiate(results, base, exponents,
+ exponentsCount);}
+
+ const AbstractRing* m_pRing;
+ };
+
+ MultiplicativeGroupT m_mg;
+};
+
+
+// Abstract Euclidean Domain
+class TAOCRYPT_NO_VTABLE AbstractEuclideanDomain
+ : public AbstractRing
+{
+public:
+ typedef Integer Element;
+
+ virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a,
+ const Element &d) const =0;
+
+ virtual const Element& Mod(const Element &a, const Element &b) const =0;
+ virtual const Element& Gcd(const Element &a, const Element &b) const;
+
+protected:
+ mutable Element result;
+};
+
+
+// EuclideanDomainOf
+class EuclideanDomainOf : public AbstractEuclideanDomain
+{
+public:
+ typedef Integer Element;
+
+ EuclideanDomainOf() {}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return a==b;}
+
+ const Element& Identity() const
+ {return Element::Zero();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return result = a+b;}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return a+=b;}
+
+ const Element& Inverse(const Element &a) const
+ {return result = -a;}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return result = a-b;}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a-=b;}
+
+ const Element& Double(const Element &a) const
+ {return result = a.Doubled();}
+
+ const Element& MultiplicativeIdentity() const
+ {return Element::One();}
+
+ const Element& Multiply(const Element &a, const Element &b) const
+ {return result = a*b;}
+
+ const Element& Square(const Element &a) const
+ {return result = a.Squared();}
+
+ bool IsUnit(const Element &a) const
+ {return a.IsUnit();}
+
+ const Element& MultiplicativeInverse(const Element &a) const
+ {return result = a.MultiplicativeInverse();}
+
+ const Element& Divide(const Element &a, const Element &b) const
+ {return result = a/b;}
+
+ const Element& Mod(const Element &a, const Element &b) const
+ {return result = a%b;}
+
+ void DivisionAlgorithm(Element &r, Element &q, const Element &a,
+ const Element &d) const
+ {Element::Divide(r, q, a, d);}
+
+private:
+ mutable Element result;
+};
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_ALGEBRA_HPP
diff --git a/extra/yassl/taocrypt/include/arc4.hpp b/extra/yassl/taocrypt/include/arc4.hpp
new file mode 100644
index 00000000000..c919c8ea2ae
--- /dev/null
+++ b/extra/yassl/taocrypt/include/arc4.hpp
@@ -0,0 +1,59 @@
+/* arc4.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* arc4.hpp defines ARC4
+*/
+
+
+#ifndef TAO_CRYPT_ARC4_HPP
+#define TAO_CRYPT_ARC4_HPP
+
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+// ARC4 encryption and decryption
+class ARC4 {
+public:
+ enum { STATE_SIZE = 256 };
+
+ typedef ARC4 Encryption;
+ typedef ARC4 Decryption;
+
+ ARC4() {}
+
+ void Process(byte*, const byte*, word32);
+ void SetKey(const byte*, word32);
+private:
+ byte x_;
+ byte y_;
+ byte state_[STATE_SIZE];
+
+ ARC4(const ARC4&); // hide copy
+ const ARC4 operator=(const ARC4&); // and assign
+};
+
+} // namespace
+
+
+#endif // TAO_CRYPT_ARC4_HPP
+
diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp
new file mode 100644
index 00000000000..14fcf22d843
--- /dev/null
+++ b/extra/yassl/taocrypt/include/asn.hpp
@@ -0,0 +1,327 @@
+/* asn.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* asn.hpp provides ASN1 BER, PublicKey, and x509v3 decoding
+*/
+
+
+#ifndef TAO_CRYPT_ASN_HPP
+#define TAO_CRYPT_ASN_HPP
+
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "list.hpp"
+#include "error.hpp"
+
+
+
+namespace TaoCrypt {
+
+// these tags and flags are not complete
+enum ASNTag
+{
+ BOOLEAN = 0x01,
+ INTEGER = 0x02,
+ BIT_STRING = 0x03,
+ OCTET_STRING = 0x04,
+ TAG_NULL = 0x05,
+ OBJECT_IDENTIFIER = 0x06,
+ OBJECT_DESCRIPTOR = 0x07,
+ EXTERNAL = 0x08,
+ REAL = 0x09,
+ ENUMERATED = 0x0a,
+ UTF8_STRING = 0x0c,
+ SEQUENCE = 0x10,
+ SET = 0x11,
+ NUMERIC_STRING = 0x12,
+ PRINTABLE_STRING = 0x13,
+ T61_STRING = 0x14,
+ VIDEOTEXT_STRING = 0x15,
+ IA5_STRING = 0x16,
+ UTC_TIME = 0x17,
+ GENERALIZED_TIME = 0x18,
+ GRAPHIC_STRING = 0x19,
+ VISIBLE_STRING = 0x1a,
+ GENERAL_STRING = 0x1b,
+ LONG_LENGTH = 0x80
+};
+
+enum ASNIdFlag
+{
+ UNIVERSAL = 0x00,
+ DATA = 0x01,
+ HEADER = 0x02,
+ CONSTRUCTED = 0x20,
+ APPLICATION = 0x40,
+ CONTEXT_SPECIFIC = 0x80,
+ PRIVATE = 0xc0
+};
+
+
+enum DNTags
+{
+ COMMON_NAME = 0x03
+};
+
+
+enum Constants
+{
+ MIN_DATE_SZ = 13,
+ MAX_DATE_SZ = 15,
+ MAX_ALGO_SZ = 16,
+ MAX_LENGTH_SZ = 5,
+ MAX_SEQ_SZ = 5, // enum(seq|con) + length(4)
+ MAX_ALGO_SIZE = 9,
+ MAX_DIGEST_SZ = 25, // SHA + enum(Bit or Octet) + length(4)
+ DSA_SIG_SZ = 40
+};
+
+
+class Source;
+class RSA_PublicKey;
+class RSA_PrivateKey;
+class DSA_PublicKey;
+class DSA_PrivateKey;
+class Integer;
+class DH;
+
+
+// General BER decoding
+class BER_Decoder : public virtual_base {
+protected:
+ Source& source_;
+public:
+ explicit BER_Decoder(Source& s) : source_(s) {}
+ virtual ~BER_Decoder() {}
+
+ Integer& GetInteger(Integer&);
+ word32 GetSequence();
+ word32 GetSet();
+ word32 GetVersion();
+ word32 GetExplicitVersion();
+
+ Error GetError();
+private:
+ virtual void ReadHeader() = 0;
+
+ BER_Decoder(const BER_Decoder&); // hide copy
+ BER_Decoder& operator=(const BER_Decoder&); // and assign
+};
+
+
+// RSA Private Key BER Decoder
+class RSA_Private_Decoder : public BER_Decoder {
+public:
+ explicit RSA_Private_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(RSA_PrivateKey&);
+private:
+ void ReadHeader();
+};
+
+
+// RSA Public Key BER Decoder
+class RSA_Public_Decoder : public BER_Decoder {
+public:
+ explicit RSA_Public_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(RSA_PublicKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DSA Private Key BER Decoder
+class DSA_Private_Decoder : public BER_Decoder {
+public:
+ explicit DSA_Private_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DSA_PrivateKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DSA Public Key BER Decoder
+class DSA_Public_Decoder : public BER_Decoder {
+public:
+ explicit DSA_Public_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DSA_PublicKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DH Key BER Decoder
+class DH_Decoder : public BER_Decoder {
+public:
+ explicit DH_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DH&);
+private:
+ void ReadHeader();
+};
+
+
+// General PublicKey
+class PublicKey {
+ byte* key_;
+ word32 sz_;
+public:
+ explicit PublicKey(const byte* k = 0, word32 s = 0);
+ ~PublicKey() { tcArrayDelete(key_); }
+
+ const byte* GetKey() const { return key_; }
+ word32 size() const { return sz_; }
+
+ void SetKey(const byte*);
+ void SetSize(word32 s);
+
+ void AddToEnd(const byte*, word32);
+private:
+ PublicKey(const PublicKey&); // hide copy
+ PublicKey& operator=(const PublicKey&); // and assign
+};
+
+
+enum { SHA_SIZE = 20 };
+
+
+// A Signing Authority
+class Signer {
+ PublicKey key_;
+ char* name_;
+ byte hash_[SHA_SIZE];
+public:
+ Signer(const byte* k, word32 kSz, const char* n, const byte* h);
+ ~Signer();
+
+ const PublicKey& GetPublicKey() const { return key_; }
+ const char* GetCommonName() const { return name_; }
+ const byte* GetHash() const { return hash_; }
+
+private:
+ Signer(const Signer&); // hide copy
+ Signer& operator=(const Signer&); // and assign
+};
+
+
+typedef mySTL::list<Signer*> SignerList;
+
+
+enum SigType { SHAwDSA = 517, MD2wRSA = 646, MD5wRSA = 648, SHAwRSA =649};
+enum HashType { MD2h = 646, MD5h = 649, SHAh = 88 };
+enum KeyType { DSAk = 515, RSAk = 645 }; // sums of algo OID
+
+
+// an x509v Certificate BER Decoder
+class CertDecoder : public BER_Decoder {
+public:
+ explicit CertDecoder(Source&, bool decode = true, SignerList* = 0);
+ ~CertDecoder();
+
+ const PublicKey& GetPublicKey() const { return key_; }
+ KeyType GetKeyType() const { return KeyType(keyOID_); }
+ const char* GetIssuer() const { return issuer_; }
+ const char* GetCommonName() const { return subject_; }
+ const byte* GetHash() const { return subjectHash_; }
+
+ void DecodeToKey();
+
+ enum DateType { BEFORE, AFTER };
+ enum NameType { ISSUER, SUBJECT };
+private:
+ PublicKey key_;
+ word32 certBegin_; // offset to start of cert
+ word32 sigIndex_; // offset to start of signature
+ word32 sigLength_; // length of signature
+ word32 signatureOID_; // sum of algorithm object id
+ word32 keyOID_; // sum of key algo object id
+ byte subjectHash_[SHA_SIZE]; // hash of all Names
+ byte issuerHash_[SHA_SIZE]; // hash of all Names
+ byte* signature_;
+ char* issuer_; // CommonName
+ char* subject_; // CommonName
+
+ void ReadHeader();
+ void Decode(SignerList*);
+ void StoreKey();
+ void AddDSA();
+ bool ValidateSelfSignature();
+ bool ValidateSignature(SignerList*);
+ bool ConfirmSignature(Source&);
+ void GetKey();
+ void GetName(NameType);
+ void GetValidity();
+ void GetDate(DateType);
+ void GetCompareHash(const byte*, word32, byte*, word32);
+ word32 GetAlgoId();
+ word32 GetSignature();
+ word32 GetDigest();
+};
+
+
+word32 GetLength(Source&);
+
+word32 SetLength(word32, byte*);
+word32 SetSequence(word32, byte*);
+
+word32 EncodeDSA_Signature(const byte* signature, byte* output);
+word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output);
+word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz);
+
+
+// General DER encoding
+class DER_Encoder : public virtual_base {
+public:
+ DER_Encoder() {}
+ virtual ~DER_Encoder() {}
+
+ word32 SetAlgoID(HashType, byte*);
+
+ Error GetError() const { return error_; }
+private:
+ //virtual void WriteHeader() = 0;
+ Error error_;
+
+ DER_Encoder(const DER_Encoder&); // hide copy
+ DER_Encoder& operator=(const DER_Encoder&); // and assign
+};
+
+
+
+class Signature_Encoder : public DER_Encoder {
+ const byte* digest_;
+ word32 digestSz_;
+ SigType digestOID_;
+public:
+ explicit Signature_Encoder(const byte*, word32, HashType, Source&);
+
+private:
+ void WriteHeader();
+ word32 SetDigest(const byte*, word32, byte*);
+
+ Signature_Encoder(const Signature_Encoder&); // hide copy
+ Signature_Encoder& operator=(const Signature_Encoder&); // and assign
+};
+
+
+} // namespace
+
+
+#endif // TAO_CRYPT_ASN_HPP
diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp
new file mode 100644
index 00000000000..ee00ad7487f
--- /dev/null
+++ b/extra/yassl/taocrypt/include/block.hpp
@@ -0,0 +1,202 @@
+/* block.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* block.hpp provides word and byte blocks with configurable allocators
+*/
+
+
+#ifndef TAO_CRYPT_BLOCK_HPP
+#define TAO_CRYPT_BLOCK_HPP
+
+#include "algorithm.hpp" // mySTL::swap
+#include "misc.hpp"
+#include <string.h> // memcpy
+#include <stddef.h> // ptrdiff_t
+
+
+
+namespace TaoCrypt {
+
+
+// a Base class for Allocators
+template<class T>
+class AllocatorBase
+{
+public:
+ typedef T value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+
+ pointer address(reference r) const {return (&r);}
+ const_pointer address(const_reference r) const {return (&r); }
+ void construct(pointer p, const T& val) {new (p) T(val);}
+ void destroy(pointer p) {p->~T();}
+ size_type max_size() const {return ~size_type(0)/sizeof(T);}
+protected:
+ static void CheckSize(size_t n)
+ {
+ assert(n <= ~size_t(0) / sizeof(T));
+ }
+};
+
+
+// General purpose realloc
+template<typename T, class A>
+typename A::pointer StdReallocate(A& a, T* p, typename A::size_type oldSize,
+ typename A::size_type newSize, bool preserve)
+{
+ if (oldSize == newSize)
+ return p;
+
+ if (preserve) {
+ A b = A();
+ typename A::pointer newPointer = b.allocate(newSize, 0);
+ memcpy(newPointer, p, sizeof(T) * min(oldSize, newSize));
+ a.deallocate(p, oldSize);
+ mySTL::swap(a, b);
+ return newPointer;
+ }
+ else {
+ a.deallocate(p, oldSize);
+ return a.allocate(newSize, 0);
+ }
+}
+
+
+// Allocator that zeros out memory on deletion
+template <class T>
+class AllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+ typedef typename AllocatorBase<T>::pointer pointer;
+ typedef typename AllocatorBase<T>::size_type size_type;
+
+ pointer allocate(size_type n, const void* = 0)
+ {
+ CheckSize(n);
+ if (n == 0)
+ return 0;
+ return new (tc) T[n];
+ }
+
+ void deallocate(void* p, size_type n)
+ {
+ memset(p, 0, n * sizeof(T));
+ tcArrayDelete((T*)p);
+ }
+
+ pointer reallocate(T* p, size_type oldSize, size_type newSize,
+ bool preserve)
+ {
+ return StdReallocate(*this, p, oldSize, newSize, preserve);
+ }
+
+ // VS.NET STL enforces the policy of "All STL-compliant allocators have to
+ // provide a template class member called rebind".
+ template <class U> struct rebind { typedef AllocatorWithCleanup<U> other;};
+};
+
+
+// Block class template
+template<typename T, class A = AllocatorWithCleanup<T> >
+class Block {
+public:
+ explicit Block(word32 s = 0) : sz_(s), buffer_(allocator_.allocate(sz_))
+ { CleanNew(sz_); }
+
+ Block(const T* buff, word32 s) : sz_(s), buffer_(allocator_.allocate(sz_))
+ { memcpy(buffer_, buff, sz_ * sizeof(T)); }
+
+ Block(const Block& that) : sz_(that.sz_), buffer_(allocator_.allocate(sz_))
+ { memcpy(buffer_, that.buffer_, sz_ * sizeof(T)); }
+
+ Block& operator=(const Block& that) {
+ Block tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ T& operator[] (word32 i) { assert(i < sz_); return buffer_[i]; }
+ const T& operator[] (word32 i) const
+ { assert(i < sz_); return buffer_[i]; }
+
+ T* operator+ (word32 i) { return buffer_ + i; }
+ const T* operator+ (word32 i) const { return buffer_ + i; }
+
+ word32 size() const { return sz_; }
+
+ T* get_buffer() const { return buffer_; }
+ T* begin() const { return get_buffer(); }
+
+ void CleanGrow(word32 newSize)
+ {
+ if (newSize > sz_) {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true);
+ memset(buffer_ + sz_, 0, (newSize - sz_) * sizeof(T));
+ sz_ = newSize;
+ }
+ }
+
+ void CleanNew(word32 newSize)
+ {
+ New(newSize);
+ memset(buffer_, 0, sz_ * sizeof(T));
+ }
+
+ void New(word32 newSize)
+ {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, false);
+ sz_ = newSize;
+ }
+
+ void resize(word32 newSize)
+ {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true);
+ sz_ = newSize;
+ }
+
+ void Swap(Block& other) {
+ mySTL::swap(sz_, other.sz_);
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(allocator_, other.allocator_);
+ }
+
+ ~Block() { allocator_.deallocate(buffer_, sz_); }
+private:
+ word32 sz_; // size in Ts
+ T* buffer_;
+ A allocator_;
+};
+
+
+typedef Block<byte> ByteBlock;
+typedef Block<word> WordBlock;
+typedef Block<word32> Word32Block;
+
+
+} // namespace
+
+#endif // TAO_CRYPT_BLOCK_HPP
diff --git a/extra/yassl/taocrypt/include/coding.hpp b/extra/yassl/taocrypt/include/coding.hpp
new file mode 100644
index 00000000000..9aab2a30c7e
--- /dev/null
+++ b/extra/yassl/taocrypt/include/coding.hpp
@@ -0,0 +1,94 @@
+/* coding.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* coding.hpp defines hex and base64 encoding/decoing
+*/
+
+#ifndef TAO_CRYPT_CODING_HPP
+#define TAO_CRYPT_CODING_HPP
+
+#include "misc.hpp"
+#include "block.hpp"
+
+namespace TaoCrypt {
+
+class Source;
+
+
+// Hex Encoding, see RFC 3548
+class HexEncoder {
+ ByteBlock encoded_;
+ Source& plain_;
+public:
+ explicit HexEncoder(Source& s) : plain_(s) { Encode(); }
+private:
+ void Encode();
+
+ HexEncoder(const HexEncoder&); // hide copy
+ HexEncoder& operator=(const HexEncoder&); // and assign
+};
+
+
+// Hex Decoding, see RFC 3548
+class HexDecoder {
+ ByteBlock decoded_;
+ Source& coded_;
+public:
+ explicit HexDecoder(Source& s) : coded_(s) { Decode(); }
+private:
+ void Decode();
+
+ HexDecoder(const HexDecoder&); // hide copy
+ HexDecoder& operator=(const HexDecoder&); // and assign
+};
+
+
+// Base 64 encoding, see RFC 3548
+class Base64Encoder {
+ ByteBlock encoded_;
+ Source& plain_;
+public:
+ explicit Base64Encoder(Source& s) : plain_(s) { Encode(); }
+private:
+ void Encode();
+
+ Base64Encoder(const Base64Encoder&); // hide copy
+ Base64Encoder& operator=(const Base64Encoder&); // and assign
+};
+
+
+// Base 64 decoding, see RFC 3548
+class Base64Decoder {
+ ByteBlock decoded_;
+ Source& coded_;
+public:
+ explicit Base64Decoder(Source& s) : coded_(s) { Decode(); }
+private:
+ void Decode();
+
+ Base64Decoder(const Base64Decoder&); // hide copy
+ Base64Decoder& operator=(const Base64Decoder&); // and assign
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_CODING_HPP
diff --git a/extra/yassl/taocrypt/include/des.hpp b/extra/yassl/taocrypt/include/des.hpp
new file mode 100644
index 00000000000..127b8ddc6d5
--- /dev/null
+++ b/extra/yassl/taocrypt/include/des.hpp
@@ -0,0 +1,122 @@
+/* des.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* des.hpp defines DES, DES_EDE2, and DES_EDE3
+ see FIPS 46-2 and FIPS 81
+*/
+
+
+#ifndef TAO_CRYPT_DES_HPP
+#define TAO_CRYPT_DES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+#include "modes.hpp"
+
+namespace TaoCrypt {
+
+enum { DES_BLOCK_SIZE = 8 };
+
+// Base for all DES types
+class DES_BASE : public Mode_BASE {
+public:
+ enum { BLOCK_SIZE = DES_BLOCK_SIZE, KEY_SIZE = 32, BOXES = 8,
+ BOX_SIZE = 64 };
+
+ DES_BASE(CipherDir DIR, Mode MODE)
+ : Mode_BASE(BLOCK_SIZE), dir_(DIR), mode_(MODE) {}
+
+ void Process(byte*, const byte*, word32);
+protected:
+ CipherDir dir_;
+ Mode mode_;
+private:
+ DES_BASE(const DES_BASE&); // hide copy
+ DES_BASE& operator=(const DES_BASE&); // and assign
+};
+
+
+// DES
+class DES : public DES_BASE {
+public:
+ DES(CipherDir DIR, Mode MODE) : DES_BASE(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void RawProcessBlock(word32&, word32&) const;
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ word32 k_[KEY_SIZE];
+};
+
+
+// DES_EDE2
+class DES_EDE2 : public DES_BASE {
+public:
+ DES_EDE2(CipherDir DIR, Mode MODE)
+ : DES_BASE(DIR, MODE), des1_(DIR, MODE), des2_(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ DES des1_;
+ DES des2_;
+};
+
+
+// DES_EDE3
+class DES_EDE3 : public DES_BASE {
+public:
+ DES_EDE3(CipherDir DIR, Mode MODE)
+ : DES_BASE(DIR, MODE), des1_(DIR, MODE), des2_(DIR, MODE),
+ des3_(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ DES des1_;
+ DES des2_;
+ DES des3_;
+};
+
+
+typedef BlockCipher<ENCRYPTION, DES, ECB> DES_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES, ECB> DES_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES, CBC> DES_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES, CBC> DES_CBC_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE2, ECB> DES_EDE2_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE2, ECB> DES_EDE2_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE2, CBC> DES_EDE2_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE2, CBC> DES_EDE2_CBC_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE3, ECB> DES_EDE3_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE3, ECB> DES_EDE3_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE3, CBC> DES_EDE3_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE3, CBC> DES_EDE3_CBC_Decryption;
+
+
+} // namespace
+
+
+#endif // TAO_CRYPT_DES_HPP
diff --git a/extra/yassl/taocrypt/include/dh.hpp b/extra/yassl/taocrypt/include/dh.hpp
new file mode 100644
index 00000000000..54a1705546b
--- /dev/null
+++ b/extra/yassl/taocrypt/include/dh.hpp
@@ -0,0 +1,89 @@
+/* dh.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* dh.hpp provides Diffie-Hellman support
+*/
+
+
+#ifndef TAO_CRYPT_DH_HPP
+#define TAO_CRYPT_DH_HPP
+
+#include "misc.hpp"
+#include "integer.hpp"
+
+namespace TaoCrypt {
+
+
+class Source;
+
+
+// Diffie-Hellman
+class DH {
+public:
+ DH() {}
+ DH(Integer& p, Integer& g) : p_(p), g_(g) {}
+ explicit DH(Source&);
+
+ DH(const DH& that) : p_(that.p_), g_(that.g_) {}
+ DH& operator=(const DH& that)
+ {
+ DH tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(DH& other)
+ {
+ p_.Swap(other.p_);
+ g_.Swap(other.g_);
+ }
+
+ void Initialize(Source&);
+ void Initialize(Integer& p, Integer& g)
+ {
+ SetP(p);
+ SetG(g);
+ }
+
+ void GenerateKeyPair(RandomNumberGenerator&, byte*, byte*);
+ void Agree(byte*, const byte*, const byte*);
+
+ void SetP(const Integer& p) { p_ = p; }
+ void SetG(const Integer& g) { g_ = g; }
+
+ Integer& GetP() { return p_; }
+ Integer& GetG() { return g_; }
+
+ // for p and agree
+ word32 GetByteLength() const { return p_.ByteCount(); }
+private:
+ // group parms
+ Integer p_;
+ Integer g_;
+
+ void GeneratePrivate(RandomNumberGenerator&, byte*);
+ void GeneratePublic(const byte*, byte*);
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_DH_HPP
diff --git a/extra/yassl/taocrypt/include/dsa.hpp b/extra/yassl/taocrypt/include/dsa.hpp
new file mode 100644
index 00000000000..f1fdd2dfa25
--- /dev/null
+++ b/extra/yassl/taocrypt/include/dsa.hpp
@@ -0,0 +1,129 @@
+/* dsa.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* dsa.hpp provides Digitial Signautre Algorithm see FIPS 186-2
+*/
+
+#ifndef TAO_CRYPT_DSA_HPP
+#define TAO_CRYPT_DSA_HPP
+
+#include "integer.hpp"
+
+
+namespace TaoCrypt {
+
+class Source;
+
+
+class DSA_PublicKey {
+protected:
+ Integer p_;
+ Integer q_;
+ Integer g_;
+ Integer y_;
+public:
+ DSA_PublicKey() {}
+ explicit DSA_PublicKey(Source&);
+
+ void Initialize(Source&);
+ void Initialize(const Integer& p, const Integer& q, const Integer& g,
+ const Integer& y);
+
+ const Integer& GetModulus() const;
+ const Integer& GetSubGroupOrder() const;
+ const Integer& GetSubGroupGenerator() const;
+ const Integer& GetPublicPart() const;
+
+ void SetModulus(const Integer&);
+ void SetSubGroupOrder(const Integer&);
+ void SetSubGroupGenerator(const Integer&);
+ void SetPublicPart(const Integer&);
+
+ word32 SignatureLength() const;
+
+ DSA_PublicKey(const DSA_PublicKey&);
+ DSA_PublicKey& operator=(const DSA_PublicKey&);
+
+ void Swap(DSA_PublicKey& other);
+};
+
+
+
+class DSA_PrivateKey : public DSA_PublicKey {
+ Integer x_;
+public:
+ DSA_PrivateKey() {}
+ explicit DSA_PrivateKey(Source&);
+
+ void Initialize(Source&);
+ void Initialize(const Integer& p, const Integer& q, const Integer& g,
+ const Integer& y, const Integer& x);
+
+ const Integer& GetPrivatePart() const;
+
+ void SetPrivatePart(const Integer&);
+private:
+ DSA_PrivateKey(const DSA_PrivateKey&); // hide copy
+ DSA_PrivateKey& operator=(const DSA_PrivateKey&); // and assign
+};
+
+
+
+class DSA_Signer {
+ const DSA_PrivateKey& key_;
+ Integer r_;
+ Integer s_;
+public:
+ explicit DSA_Signer(const DSA_PrivateKey&);
+
+ word32 Sign(const byte* sha_digest, byte* sig, RandomNumberGenerator&);
+
+ const Integer& GetR() const;
+ const Integer& GetS() const;
+private:
+ DSA_Signer(const DSA_Signer&); // hide copy
+ DSA_Signer& operator=(DSA_Signer&); // and assign
+};
+
+
+class DSA_Verifier {
+ const DSA_PublicKey& key_;
+ Integer r_;
+ Integer s_;
+public:
+ explicit DSA_Verifier(const DSA_PublicKey&);
+
+ bool Verify(const byte* sha_digest, const byte* sig);
+
+ const Integer& GetR() const;
+ const Integer& GetS() const;
+private:
+ DSA_Verifier(const DSA_Verifier&); // hide copy
+ DSA_Verifier& operator=(const DSA_Verifier&); // and assign
+};
+
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_DSA_HPP
diff --git a/extra/yassl/taocrypt/include/error.hpp b/extra/yassl/taocrypt/include/error.hpp
new file mode 100644
index 00000000000..55ab39313f5
--- /dev/null
+++ b/extra/yassl/taocrypt/include/error.hpp
@@ -0,0 +1,87 @@
+/* error.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* error.hpp provides a taocrypt error numbers
+ *
+ */
+
+
+#ifndef TAO_CRYPT_ERROR_HPP
+#define TAO_CRYPT_ERROR_HPP
+
+
+namespace TaoCrypt {
+
+
+enum ErrorNumber {
+
+NO_ERROR = 0, // "not in error state"
+
+// RandomNumberGenerator
+WINCRYPT_E = 1001, // "bad wincrypt acquire"
+CRYPTGEN_E = 1002, // "CryptGenRandom error"
+OPEN_RAN_E = 1003, // "open /dev/urandom error"
+READ_RAN_E = 1004, // "read /dev/urandom error"
+
+// Integer
+INTEGER_E = 1010, // "bad DER Integer Header"
+
+
+// ASN.1
+SEQUENCE_E = 1020, // "bad Sequence Header"
+SET_E = 1021, // "bad Set Header"
+VERSION_E = 1022, // "version length not 1"
+SIG_OID_E = 1023, // "signature OID mismatch"
+BIT_STR_E = 1024, // "bad BitString Header"
+UNKNOWN_OID_E = 1025, // "unknown key OID type"
+OBJECT_ID_E = 1026, // "bad Ojbect ID Header"
+TAG_NULL_E = 1027, // "expected TAG NULL"
+EXPECT_0_E = 1028, // "expected 0"
+OCTET_STR_E = 1029, // "bad Octet String Header"
+TIME_E = 1030, // "bad TIME"
+
+DATE_SZ_E = 1031, // "bad Date Size"
+SIG_LEN_E = 1032, // "bad Signature Length"
+UNKOWN_SIG_E = 1033, // "unknown signature OID"
+UNKOWN_HASH_E = 1034, // "unknown hash OID"
+DSA_SZ_E = 1035, // "bad DSA r or s size"
+BEFORE_DATE_E = 1036, // "before date in the future"
+AFTER_DATE_E = 1037, // "after date in the past"
+SIG_CONFIRM_E = 1038, // "bad self signature confirmation"
+SIG_OTHER_E = 1039 // "bad other signature confirmation"
+
+};
+
+
+struct Error {
+ ErrorNumber what_; // description number, 0 for no error
+
+ explicit Error(ErrorNumber w = NO_ERROR) : what_(w) {}
+
+ ErrorNumber What() const { return what_; }
+ void SetError(ErrorNumber w) { what_ = w; }
+};
+
+
+
+} // namespace TaoCrypt
+
+#endif // TAO_CRYPT_ERROR_HPP
diff --git a/extra/yassl/taocrypt/include/file.hpp b/extra/yassl/taocrypt/include/file.hpp
new file mode 100644
index 00000000000..fe7e1073c99
--- /dev/null
+++ b/extra/yassl/taocrypt/include/file.hpp
@@ -0,0 +1,124 @@
+/* file.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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.hpp provies File Sources and Sinks
+*/
+
+
+#ifndef TAO_CRYPT_FILE_HPP
+#define TAO_CRYPT_FILE_HPP
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "error.hpp"
+#include <stdio.h>
+
+namespace TaoCrypt {
+
+
+class Source {
+ ByteBlock buffer_;
+ word32 current_;
+ Error error_;
+public:
+ explicit Source(word32 sz = 0) : buffer_(sz), current_(0) {}
+ Source(const byte* b, word32 sz) : buffer_(b, sz), current_(0) {}
+
+ word32 size() const { return buffer_.size(); }
+ void grow(word32 sz) { buffer_.CleanGrow(sz); }
+
+ const byte* get_buffer() const { return buffer_.get_buffer(); }
+ const byte* get_current() const { return &buffer_[current_]; }
+ word32 get_index() const { return current_; }
+ void set_index(word32 i) { current_ = i; }
+
+ byte operator[] (word32 i) { current_ = i; return next(); }
+ byte next() { return buffer_[current_++]; }
+ byte prev() { return buffer_[--current_]; }
+
+ void add(const byte* data, word32 len)
+ {
+ memcpy(buffer_.get_buffer() + current_, data, len);
+ current_ += len;
+ }
+
+ void advance(word32 i) { current_ += i; }
+ void reset(ByteBlock&);
+
+ Error GetError() { return error_; }
+ void SetError(ErrorNumber w) { error_.SetError(w); }
+
+ friend class FileSource; // for get()
+private:
+ Source(const Source& that) : buffer_(that.buffer_), current_(that.current_) {}
+ Source& operator=(const Source& that)
+ {
+ Source tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(Source& other)
+ {
+ buffer_.Swap(other.buffer_);
+ mySTL::swap(current_, other.current_);
+ }
+
+};
+
+
+// File Source
+class FileSource {
+ FILE* file_;
+public:
+ FileSource(const char* fname, Source& source);
+ ~FileSource();
+
+ word32 size(bool use_current = false);
+private:
+ word32 get(Source&);
+ word32 size_left();
+
+ FileSource(const FileSource&); // hide
+ FileSource& operator=(const FileSource&); // hide
+};
+
+
+// File Sink
+class FileSink {
+ FILE* file_;
+public:
+ FileSink(const char* fname, Source& source);
+ ~FileSink();
+
+ word32 size(bool use_current = false);
+private:
+ void put(Source&);
+
+ FileSink(const FileSink&); // hide
+ FileSink& operator=(const FileSink&); // hide
+};
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_FILE_HPP
diff --git a/extra/yassl/taocrypt/include/hash.hpp b/extra/yassl/taocrypt/include/hash.hpp
new file mode 100644
index 00000000000..5c90d01aefe
--- /dev/null
+++ b/extra/yassl/taocrypt/include/hash.hpp
@@ -0,0 +1,73 @@
+/* hash.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* hash.hpp provides a base for digest types
+*/
+
+
+#ifndef TAO_CRYPT_HASH_HPP
+#define TAO_CRYPT_HASH_HPP
+
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+// HASH
+class HASH : public virtual_base {
+public:
+ virtual ~HASH() {}
+
+ virtual void Update(const byte*, word32) = 0;
+ virtual void Final(byte*) = 0;
+
+ virtual void Init() = 0;
+
+ virtual word32 getBlockSize() const = 0;
+ virtual word32 getDigestSize() const = 0;
+};
+
+
+// HASH with Transform
+class HASHwithTransform : public HASH {
+public:
+ HASHwithTransform(word32 digSz, word32 buffSz);
+ virtual ~HASHwithTransform() {}
+ virtual ByteOrder getByteOrder() const = 0;
+ virtual word32 getPadSize() const = 0;
+
+ virtual void Update(const byte*, word32);
+ virtual void Final(byte*);
+
+ enum { MaxDigestSz = 5, MaxBufferSz = 64 };
+protected:
+ word32 buffLen_;
+ word32 length_; // in Bits
+ word32 digest_[MaxDigestSz];
+ word32 buffer_[MaxBufferSz / sizeof(word32)];
+
+ virtual void Transform() = 0;
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_HASH_HPP
diff --git a/extra/yassl/taocrypt/include/hmac.hpp b/extra/yassl/taocrypt/include/hmac.hpp
new file mode 100644
index 00000000000..543366afc3a
--- /dev/null
+++ b/extra/yassl/taocrypt/include/hmac.hpp
@@ -0,0 +1,141 @@
+/* hmac.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* hamc.hpp implements HMAC, see RFC 2104
+*/
+
+
+#ifndef TAO_CRYPT_HMAC_HPP
+#define TAO_CRYPT_HMAC_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// HMAC class template
+template <class T>
+class HMAC {
+public:
+ enum { IPAD = 0x36, OPAD = 0x5C };
+
+ HMAC() : ipad_(reinterpret_cast<byte*>(&ip_)),
+ opad_(reinterpret_cast<byte*>(&op_)),
+ innerHash_(reinterpret_cast<byte*>(&innerH_))
+ {
+ Init();
+ }
+ void Update(const byte*, word32);
+ void Final(byte*);
+ void Init();
+
+ void SetKey(const byte*, word32);
+private:
+ byte* ipad_;
+ byte* opad_;
+ byte* innerHash_;
+ bool innerHashKeyed_;
+ T mac_;
+
+ // MSVC 6 HACK, gives compiler error if calculated in array
+ enum { BSIZE = T::BLOCK_SIZE / sizeof(word32),
+ DSIZE = T::DIGEST_SIZE / sizeof(word32) };
+
+ word32 ip_[BSIZE]; // align ipad_ on word32
+ word32 op_[BSIZE]; // align opad_ on word32
+ word32 innerH_[DSIZE]; // align innerHash_ on word32
+
+ void KeyInnerHash();
+
+ HMAC(const HMAC&);
+ HMAC& operator= (const HMAC&);
+};
+
+
+// Setup
+template <class T>
+void HMAC<T>::Init()
+{
+ mac_.Init();
+ innerHashKeyed_ = false;
+}
+
+
+// Key generation
+template <class T>
+void HMAC<T>::SetKey(const byte* key, word32 length)
+{
+ Init();
+
+ if (length <= T::BLOCK_SIZE)
+ memcpy(ipad_, key, length);
+ else {
+ mac_.Update(key, length);
+ mac_.Final(ipad_);
+ length = T::DIGEST_SIZE;
+ }
+ memset(ipad_ + length, 0, T::BLOCK_SIZE - length);
+
+ for (word32 i = 0; i < T::BLOCK_SIZE; i++) {
+ opad_[i] = ipad_[i] ^ OPAD;
+ ipad_[i] ^= IPAD;
+ }
+}
+
+
+// Inner Key Hash
+template <class T>
+void HMAC<T>::KeyInnerHash()
+{
+ mac_.Update(ipad_, T::BLOCK_SIZE);
+ innerHashKeyed_ = true;
+}
+
+
+// Update
+template <class T>
+void HMAC<T>::Update(const byte* msg, word32 length)
+{
+ if (!innerHashKeyed_)
+ KeyInnerHash();
+ mac_.Update(msg, length);
+}
+
+
+// Final
+template <class T>
+void HMAC<T>::Final(byte* hash)
+{
+ if (!innerHashKeyed_)
+ KeyInnerHash();
+ mac_.Final(innerHash_);
+
+ mac_.Update(opad_, T::BLOCK_SIZE);
+ mac_.Update(innerHash_, T::DIGEST_SIZE);
+ mac_.Final(hash);
+
+ innerHashKeyed_ = false;
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_HMAC_HPP
diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp
new file mode 100644
index 00000000000..76034c3ae8f
--- /dev/null
+++ b/extra/yassl/taocrypt/include/integer.hpp
@@ -0,0 +1,330 @@
+/* integer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's integer.h from CryptoPP */
+
+
+#ifndef TAO_CRYPT_INTEGER_HPP
+#define TAO_CRYPT_INTEGER_HPP
+
+
+#ifdef _MSC_VER
+ // 4250: dominance
+ // 4660: explicitly instantiating a class already implicitly instantiated
+ // 4661: no suitable definition provided for explicit template request
+ // 4786: identifer was truncated in debug information
+ // 4355: 'this' : used in base member initializer list
+# pragma warning(disable: 4250 4660 4661 4786 4355)
+#endif
+
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "random.hpp"
+#include "file.hpp"
+#include "algorithm.hpp" // mySTL::swap
+#include <string.h>
+
+
+#ifdef TAOCRYPT_X86ASM_AVAILABLE
+
+#ifdef _M_IX86
+ #if (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 500)) || \
+ (defined(__ICL) && (__ICL >= 500))
+ #define SSE2_INTRINSICS_AVAILABLE
+ #define TAOCRYPT_MM_MALLOC_AVAILABLE
+ #elif defined(_MSC_VER)
+ // _mm_free seems to be the only way to tell if the Processor Pack is
+ //installed or not
+ #include <malloc.h>
+ #if defined(_mm_free)
+ #define SSE2_INTRINSICS_AVAILABLE
+ #define TAOCRYPT_MM_MALLOC_AVAILABLE
+ #endif
+ #endif
+#endif
+
+// SSE2 intrinsics work in GCC 3.3 or later
+#if defined(__SSE2__) && (__GNUC_MAJOR__ > 3 || __GNUC_MINOR__ > 2)
+ #define SSE2_INTRINSICS_AVAILABLE
+#endif
+
+#endif // X86ASM
+
+
+
+
+namespace TaoCrypt {
+
+#if defined(SSE2_INTRINSICS_AVAILABLE)
+
+ // Allocator handling proper alignment
+ template <class T>
+ class AlignedAllocator : public AllocatorBase<T>
+ {
+ public:
+ typedef typename AllocatorBase<T>::pointer pointer;
+ typedef typename AllocatorBase<T>::size_type size_type;
+
+ pointer allocate(size_type n, const void* = 0);
+ void deallocate(void* p, size_type n);
+ pointer reallocate(T* p, size_type oldSize, size_type newSize,
+ bool preserve)
+ {
+ return StdReallocate(*this, p, oldSize, newSize, preserve);
+ }
+
+ #if !(defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16) || \
+ defined(TAOCRYPT_MEMALIGN_AVAILABLE) || \
+ defined(TAOCRYPT_MM_MALLOC_AVAILABLE))
+ #define TAOCRYPT_NO_ALIGNED_ALLOC
+ AlignedAllocator() : m_pBlock(0) {}
+ protected:
+ void *m_pBlock;
+ #endif
+ };
+
+ template class TAOCRYPT_DLL AlignedAllocator<word>;
+ typedef Block<word, AlignedAllocator<word> > AlignedWordBlock;
+#else
+ typedef WordBlock AlignedWordBlock;
+#endif
+
+
+// general MIN
+template<typename T> inline
+const T& min(const T& a, const T& b)
+{
+ return a < b ? a : b;
+}
+
+
+// general MAX
+template<typename T> inline
+const T& max(const T& a, const T& b)
+{
+ return a > b ? a : b;
+}
+
+
+// Large Integer class
+class Integer {
+public:
+ enum Sign {POSITIVE = 0, NEGATIVE = 1 };
+ enum Signedness { UNSIGNED, SIGNED };
+ enum RandomNumberType { ANY, PRIME };
+
+ class DivideByZero {};
+
+ Integer();
+ Integer(const Integer& t);
+ Integer(signed long value);
+ Integer(Sign s, word highWord, word lowWord);
+
+ // BER Decode Source
+ explicit Integer(Source&);
+
+ Integer(const byte* encodedInteger, unsigned int byteCount,
+ Signedness s = UNSIGNED);
+
+ ~Integer() {}
+
+ static const Integer& Zero();
+ static const Integer& One();
+
+ Integer& Ref() { return *this; }
+
+ Integer(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max);
+
+ static Integer Power2(unsigned int e);
+
+ unsigned int MinEncodedSize(Signedness = UNSIGNED) const;
+ unsigned int Encode(byte* output, unsigned int outputLen,
+ Signedness = UNSIGNED) const;
+
+ void Decode(const byte* input, unsigned int inputLen,
+ Signedness = UNSIGNED);
+ void Decode(Source&);
+
+ bool IsConvertableToLong() const;
+ signed long ConvertToLong() const;
+
+ unsigned int BitCount() const;
+ unsigned int ByteCount() const;
+ unsigned int WordCount() const;
+
+ bool GetBit(unsigned int i) const;
+ byte GetByte(unsigned int i) const;
+ unsigned long GetBits(unsigned int i, unsigned int n) const;
+
+ bool IsZero() const { return !*this; }
+ bool NotZero() const { return !IsZero(); }
+ bool IsNegative() const { return sign_ == NEGATIVE; }
+ bool NotNegative() const { return !IsNegative(); }
+ bool IsPositive() const { return NotNegative() && NotZero(); }
+ bool NotPositive() const { return !IsPositive(); }
+ bool IsEven() const { return GetBit(0) == 0; }
+ bool IsOdd() const { return GetBit(0) == 1; }
+
+ Integer& operator=(const Integer& t);
+ Integer& operator+=(const Integer& t);
+ Integer& operator-=(const Integer& t);
+ Integer& operator*=(const Integer& t) { return *this = Times(t); }
+ Integer& operator/=(const Integer& t)
+ { return *this = DividedBy(t);}
+ Integer& operator%=(const Integer& t) { return *this = Modulo(t); }
+ Integer& operator/=(word t) { return *this = DividedBy(t); }
+ Integer& operator%=(word t) { return *this = Modulo(t); }
+ Integer& operator<<=(unsigned int);
+ Integer& operator>>=(unsigned int);
+
+
+ void Randomize(RandomNumberGenerator &rng, unsigned int bitcount);
+ void Randomize(RandomNumberGenerator &rng, const Integer &min,
+ const Integer &max);
+
+ void SetBit(unsigned int n, bool value = 1);
+ void SetByte(unsigned int n, byte value);
+
+ void Negate();
+ void SetPositive() { sign_ = POSITIVE; }
+ void SetNegative() { if (!!(*this)) sign_ = NEGATIVE; }
+ void Swap(Integer& a);
+
+ bool operator!() const;
+ Integer operator+() const {return *this;}
+ Integer operator-() const;
+ Integer& operator++();
+ Integer& operator--();
+ Integer operator++(int)
+ { Integer temp = *this; ++*this; return temp; }
+ Integer operator--(int)
+ { Integer temp = *this; --*this; return temp; }
+
+ int Compare(const Integer& a) const;
+
+ Integer Plus(const Integer &b) const;
+ Integer Minus(const Integer &b) const;
+ Integer Times(const Integer &b) const;
+ Integer DividedBy(const Integer &b) const;
+ Integer Modulo(const Integer &b) const;
+ Integer DividedBy(word b) const;
+ word Modulo(word b) const;
+
+ Integer operator>>(unsigned int n) const { return Integer(*this)>>=n; }
+ Integer operator<<(unsigned int n) const { return Integer(*this)<<=n; }
+
+ Integer AbsoluteValue() const;
+ Integer Doubled() const { return Plus(*this); }
+ Integer Squared() const { return Times(*this); }
+ Integer SquareRoot() const;
+
+ bool IsSquare() const;
+ bool IsUnit() const;
+
+ Integer MultiplicativeInverse() const;
+
+ friend Integer a_times_b_mod_c(const Integer& x, const Integer& y,
+ const Integer& m);
+ friend Integer a_exp_b_mod_c(const Integer& x, const Integer& e,
+ const Integer& m);
+
+ static void Divide(Integer& r, Integer& q, const Integer& a,
+ const Integer& d);
+ static void Divide(word& r, Integer& q, const Integer& a, word d);
+ static void DivideByPowerOf2(Integer& r, Integer& q, const Integer& a,
+ unsigned int n);
+ static Integer Gcd(const Integer& a, const Integer& n);
+
+ Integer InverseMod(const Integer& n) const;
+ word InverseMod(word n) const;
+
+private:
+ friend class ModularArithmetic;
+ friend class MontgomeryRepresentation;
+
+ Integer(word value, unsigned int length);
+ int PositiveCompare(const Integer& t) const;
+
+ friend void PositiveAdd(Integer& sum, const Integer& a, const Integer& b);
+ friend void PositiveSubtract(Integer& diff, const Integer& a,
+ const Integer& b);
+ friend void PositiveMultiply(Integer& product, const Integer& a,
+ const Integer& b);
+ friend void PositiveDivide(Integer& remainder, Integer& quotient, const
+ Integer& dividend, const Integer& divisor);
+ AlignedWordBlock reg_;
+ Sign sign_;
+
+ static const Integer zero_;
+ static const Integer one_;
+};
+
+inline bool operator==(const Integer& a, const Integer& b)
+ {return a.Compare(b)==0;}
+inline bool operator!=(const Integer& a, const Integer& b)
+ {return a.Compare(b)!=0;}
+inline bool operator> (const Integer& a, const Integer& b)
+ {return a.Compare(b)> 0;}
+inline bool operator>=(const Integer& a, const Integer& b)
+ {return a.Compare(b)>=0;}
+inline bool operator< (const Integer& a, const Integer& b)
+ {return a.Compare(b)< 0;}
+inline bool operator<=(const Integer& a, const Integer& b)
+ {return a.Compare(b)<=0;}
+
+inline Integer operator+(const Integer &a, const Integer &b)
+ {return a.Plus(b);}
+inline Integer operator-(const Integer &a, const Integer &b)
+ {return a.Minus(b);}
+inline Integer operator*(const Integer &a, const Integer &b)
+ {return a.Times(b);}
+inline Integer operator/(const Integer &a, const Integer &b)
+ {return a.DividedBy(b);}
+inline Integer operator%(const Integer &a, const Integer &b)
+ {return a.Modulo(b);}
+inline Integer operator/(const Integer &a, word b) {return a.DividedBy(b);}
+inline word operator%(const Integer &a, word b) {return a.Modulo(b);}
+
+inline void swap(Integer &a, Integer &b)
+{
+ a.Swap(b);
+}
+
+
+Integer CRT(const Integer& xp, const Integer& p, const Integer& xq,
+ const Integer& q, const Integer& u);
+
+inline Integer ModularExponentiation(const Integer& a, const Integer& e,
+ const Integer& m)
+{
+ return a_exp_b_mod_c(a, e, m);
+}
+
+Integer ModularRoot(const Integer& a, const Integer& dp, const Integer& dq,
+ const Integer& p, const Integer& q, const Integer& u);
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_INTEGER_HPP
diff --git a/extra/yassl/taocrypt/include/md2.hpp b/extra/yassl/taocrypt/include/md2.hpp
new file mode 100644
index 00000000000..1e1c17e9cbe
--- /dev/null
+++ b/extra/yassl/taocrypt/include/md2.hpp
@@ -0,0 +1,67 @@
+/* md5.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* md2.hpp provides MD2 digest support, see RFC 1319
+*/
+
+#ifndef TAO_CRYPT_MD2_HPP
+#define TAO_CRYPT_MD2_HPP
+
+
+#include "hash.hpp"
+#include "block.hpp"
+
+
+namespace TaoCrypt {
+
+
+// MD2 digest
+class MD2 : public HASH {
+public:
+ enum { BLOCK_SIZE = 16, DIGEST_SIZE = 16, PAD_SIZE = 16, X_SIZE = 48 };
+ MD2();
+
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+
+ void Update(const byte*, word32);
+ void Final(byte*);
+
+ void Init();
+ void Swap(MD2&);
+private:
+ ByteBlock X_, C_, buffer_;
+ word32 count_; // bytes % PAD_SIZE
+
+ MD2(const MD2&);
+ MD2& operator=(const MD2&);
+};
+
+inline void swap(MD2& a, MD2& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MD2_HPP
+
diff --git a/extra/yassl/taocrypt/include/md5.hpp b/extra/yassl/taocrypt/include/md5.hpp
new file mode 100644
index 00000000000..0198daa466e
--- /dev/null
+++ b/extra/yassl/taocrypt/include/md5.hpp
@@ -0,0 +1,63 @@
+/* md5.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* md5.hpp provides MD5 digest support, see RFC 1321
+*/
+
+#ifndef TAO_CRYPT_MD5_HPP
+#define TAO_CRYPT_MD5_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// MD5 digest
+class MD5 : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 16, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes
+ MD5() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ MD5(const MD5&);
+ MD5& operator= (const MD5&);
+
+ void Init();
+ void Swap(MD5&);
+private:
+ void Transform();
+};
+
+inline void swap(MD5& a, MD5& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MD5_HPP
+
diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp
new file mode 100644
index 00000000000..f705cc99970
--- /dev/null
+++ b/extra/yassl/taocrypt/include/misc.hpp
@@ -0,0 +1,751 @@
+/* misc.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's misc.h from CryptoPP */
+
+#ifndef TAO_CRYPT_MISC_HPP
+#define TAO_CRYPT_MISC_HPP
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "types.hpp"
+#include "type_traits.hpp"
+
+
+
+namespace TaoCrypt {
+
+// library allocation
+struct new_t {}; // TaoCrypt New type
+extern new_t tc; // pass in parameter
+
+} // namespace TaoCrypt
+
+void* operator new (size_t, TaoCrypt::new_t);
+void* operator new[](size_t, TaoCrypt::new_t);
+
+void operator delete (void*, TaoCrypt::new_t);
+void operator delete[](void*, TaoCrypt::new_t);
+
+
+namespace TaoCrypt {
+
+template<typename T>
+void tcDelete(T* ptr)
+{
+ if (ptr) ptr->~T();
+ ::operator delete(ptr, TaoCrypt::tc);
+}
+
+template<typename T>
+void tcArrayDelete(T* ptr)
+{
+ // can't do array placement destruction since not tracking size in
+ // allocation, only allow builtins to use array placement since they
+ // don't need destructors called
+ typedef char builtin[IsFundamentalType<T>::Yes ? 1 : -1];
+ (void)sizeof(builtin);
+
+ ::operator delete[](ptr, TaoCrypt::tc);
+}
+
+
+// to resolve compiler generated operator delete on base classes with
+// virtual destructors (when on stack), make sure doesn't get called
+class virtual_base {
+public:
+ static void operator delete(void*) { assert(0); }
+};
+
+
+#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+ #define INTEL_INTRINSICS
+ #define FAST_ROTATE
+#elif defined(__MWERKS__) && TARGET_CPU_PPC
+ #define PPC_INTRINSICS
+ #define FAST_ROTATE
+#elif defined(__GNUC__) && defined(__i386__)
+ // GCC does peephole optimizations which should result in using rotate
+ // instructions
+ #define FAST_ROTATE
+#endif
+
+
+// no gas on these systems ?, disable for now
+#if defined(__sun__) || defined (__QNX__) || defined (__APPLE__)
+ #define TAOCRYPT_DISABLE_X86ASM
+#endif
+
+
+// Disable assmebler when compiling with icc
+// Temporary workaround for bug12717
+#if defined(__INTEL_COMPILER)
+ #define TAOCRYPT_DISABLE_X86ASM
+#endif
+
+
+
+// CodeWarrior defines _MSC_VER
+#if !defined(TAOCRYPT_DISABLE_X86ASM) && ((defined(_MSC_VER) && \
+ !defined(__MWERKS__) && defined(_M_IX86)) || \
+ (defined(__GNUC__) && defined(__i386__)))
+ #define TAOCRYPT_X86ASM_AVAILABLE
+#endif
+
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# define TAOCRYPT_MALLOC_ALIGNMENT_IS_16
+#endif
+
+#if defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
+# define TAOCRYPT_MEMALIGN_AVAILABLE
+#endif
+
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ #define TAOCRYPT_WIN32_AVAILABLE
+#endif
+
+#if defined(__unix__) || defined(__MACH__)
+ #define TAOCRYPT_UNIX_AVAILABLE
+#endif
+
+
+// VC60 workaround: it doesn't allow typename in some places
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ #define CPP_TYPENAME
+#else
+ #define CPP_TYPENAME typename
+#endif
+
+
+#ifdef _MSC_VER
+ #define TAOCRYPT_NO_VTABLE __declspec(novtable)
+#else
+ #define TAOCRYPT_NO_VTABLE
+#endif
+
+
+// ***************** DLL related ********************
+
+#ifdef TAOCRYPT_WIN32_AVAILABLE
+
+#ifdef TAOCRYPT_EXPORTS
+ #define TAOCRYPT_IS_DLL
+ #define TAOCRYPT_DLL __declspec(dllexport)
+#elif defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_IS_DLL
+ #define TAOCRYPT_DLL __declspec(dllimport)
+#else
+ #define TAOCRYPT_DLL
+#endif // EXPORTS
+
+#define TAOCRYPT_API __stdcall
+#define TAOCRYPT_CDECL __cdecl
+
+#else // TAOCRYPT_WIN32_AVAILABLE
+
+#define TAOCRYPT_DLL
+#define TAOCRYPT_API
+#define TAOCRYPT_CDECL
+
+#endif // TAOCRYPT_WIN32_AVAILABLE
+
+
+// ****************** tempalte stuff *******************
+
+
+#if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \
+ !defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS template class TAOCRYPT_DLL
+#elif defined(__MWERKS__)
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS extern class TAOCRYPT_DLL
+#else
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS extern template class TAOCRYPT_DLL
+#endif
+
+
+#if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \
+ !defined(TAOCRYPT_EXPORTS)
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS template class
+#elif defined(__MWERKS__)
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern class
+#else
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern template class
+#endif
+
+
+// ************** compile-time assertion ***************
+
+template <bool b>
+struct CompileAssert
+{
+ static char dummy[2*b-1];
+};
+
+#define TAOCRYPT_COMPILE_ASSERT(assertion) \
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
+
+#if defined(TAOCRYPT_EXPORTS) || defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance)
+#else
+ #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance) \
+ (void)sizeof(CompileAssert<(assertion)>)
+#endif
+
+#define TAOCRYPT_ASSERT_JOIN(X, Y) TAOCRYPT_DO_ASSERT_JOIN(X, Y)
+
+#define TAOCRYPT_DO_ASSERT_JOIN(X, Y) X##Y
+
+
+/*************** helpers *****************************/
+
+inline unsigned int BitsToBytes(unsigned int bitCount)
+{
+ return ((bitCount+7)/(8));
+}
+
+inline unsigned int BytesToWords(unsigned int byteCount)
+{
+ return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
+}
+
+inline unsigned int BitsToWords(unsigned int bitCount)
+{
+ return ((bitCount+WORD_BITS-1)/(WORD_BITS));
+}
+
+inline void CopyWords(word* r, const word* a, word32 n)
+{
+ for (word32 i = 0; i < n; i++)
+ r[i] = a[i];
+}
+
+inline unsigned int CountWords(const word* X, unsigned int N)
+{
+ while (N && X[N-1]==0)
+ N--;
+ return N;
+}
+
+inline void SetWords(word* r, word a, unsigned int n)
+{
+ for (unsigned int i=0; i<n; i++)
+ r[i] = a;
+}
+
+enum ByteOrder { LittleEndianOrder = 0, BigEndianOrder = 1 };
+enum CipherDir {ENCRYPTION, DECRYPTION};
+
+inline CipherDir ReverseDir(CipherDir dir)
+{
+ return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION;
+}
+
+template <typename ENUM_TYPE, int VALUE>
+struct EnumToType
+{
+ static ENUM_TYPE ToEnum() { return (ENUM_TYPE)VALUE; }
+};
+
+typedef EnumToType<ByteOrder, LittleEndianOrder> LittleEndian;
+typedef EnumToType<ByteOrder, BigEndianOrder> BigEndian;
+
+
+#ifndef BIG_ENDIAN_ORDER
+ typedef LittleEndian HostByteOrder;
+#else
+ typedef BigEndian HostByteOrder;
+#endif
+
+inline ByteOrder GetHostByteOrder()
+{
+ return HostByteOrder::ToEnum();
+}
+
+inline bool HostByteOrderIs(ByteOrder order)
+{
+ return order == GetHostByteOrder();
+}
+
+
+void xorbuf(byte*, const byte*, unsigned int);
+
+
+template <class T>
+inline bool IsPowerOf2(T n)
+{
+ return n > 0 && (n & (n-1)) == 0;
+}
+
+template <class T1, class T2>
+inline T2 ModPowerOf2(T1 a, T2 b)
+{
+ assert(IsPowerOf2(b));
+ return T2(a) & (b-1);
+}
+
+template <class T>
+inline T RoundDownToMultipleOf(T n, T m)
+{
+ return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m));
+}
+
+template <class T>
+inline T RoundUpToMultipleOf(T n, T m)
+{
+ return RoundDownToMultipleOf(n+m-1, m);
+}
+
+template <class T>
+inline unsigned int GetAlignment(T* dummy = 0) // VC60 workaround
+{
+#if (_MSC_VER >= 1300)
+ return __alignof(T);
+#elif defined(__GNUC__)
+ return __alignof__(T);
+#else
+ return sizeof(T);
+#endif
+}
+
+inline bool IsAlignedOn(const void* p, unsigned int alignment)
+{
+ return IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0
+ : (size_t)p % alignment == 0;
+}
+
+template <class T>
+inline bool IsAligned(const void* p, T* dummy = 0) // VC60 workaround
+{
+ return IsAlignedOn(p, GetAlignment<T>());
+}
+
+
+template <class T> inline T rotlFixed(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return (x<<y) | (x>>(sizeof(T)*8-y));
+}
+
+template <class T> inline T rotrFixed(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return (x>>y) | (x<<(sizeof(T)*8-y));
+}
+
+#ifdef INTEL_INTRINSICS
+
+#pragma intrinsic(_lrotl, _lrotr)
+
+template<> inline word32 rotlFixed(word32 x, word32 y)
+{
+ assert(y < 32);
+ return y ? _lrotl(x, y) : x;
+}
+
+template<> inline word32 rotrFixed(word32 x, word32 y)
+{
+ assert(y < 32);
+ return y ? _lrotr(x, y) : x;
+}
+
+#endif // INTEL_INTRINSICS
+
+#ifdef min
+#undef min
+#endif
+
+inline word32 min(word32 a, word32 b)
+{
+ return a < b ? a : b;
+}
+
+
+inline word32 ByteReverse(word32 value)
+{
+#ifdef PPC_INTRINSICS
+ // PPC: load reverse indexed instruction
+ return (word32)__lwbrx(&value,0);
+#elif defined(FAST_ROTATE)
+ // 5 instructions with rotate instruction, 9 without
+ return (rotrFixed(value, 8U) & 0xff00ff00) |
+ (rotlFixed(value, 8U) & 0x00ff00ff);
+#else
+ // 6 instructions with rotate instruction, 8 without
+ value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+ return rotlFixed(value, 16U);
+#endif
+}
+
+
+template <typename T>
+inline void ByteReverse(T* out, const T* in, word32 byteCount)
+{
+ assert(byteCount % sizeof(T) == 0);
+ word32 count = byteCount/sizeof(T);
+ for (word32 i=0; i<count; i++)
+ out[i] = ByteReverse(in[i]);
+}
+
+inline void ByteReverse(byte* out, const byte* in, word32 byteCount)
+{
+ word32* o = reinterpret_cast<word32*>(out);
+ const word32* i = reinterpret_cast<const word32*>(in);
+ ByteReverse(o, i, byteCount);
+}
+
+
+template <class T>
+inline T ByteReverseIf(T value, ByteOrder order)
+{
+ return HostByteOrderIs(order) ? value : ByteReverse(value);
+}
+
+
+template <typename T>
+inline void ByteReverseIf(T* out, const T* in, word32 bc, ByteOrder order)
+{
+ if (!HostByteOrderIs(order))
+ ByteReverse(out, in, bc);
+ else if (out != in)
+ memcpy(out, in, bc);
+}
+
+
+template <class T>
+inline void GetUserKey(ByteOrder order, T* out, word32 outlen, const byte* in,
+ word32 inlen)
+{
+ const unsigned int U = sizeof(T);
+ assert(inlen <= outlen*U);
+ memcpy(out, in, inlen);
+ memset((byte *)out+inlen, 0, outlen*U-inlen);
+ ByteReverseIf(out, out, RoundUpToMultipleOf(inlen, U), order);
+}
+
+
+#ifdef _MSC_VER
+ // disable conversion warning
+ #pragma warning(disable:4244)
+#endif
+
+
+inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block,
+ byte*)
+{
+ return block[0];
+}
+
+inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block,
+ word16*)
+{
+ return (order == BigEndianOrder)
+ ? block[1] | (block[0] << 8)
+ : block[0] | (block[1] << 8);
+}
+
+inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block,
+ word32*)
+{
+ return (order == BigEndianOrder)
+ ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16)
+ | (word32(block[0]) << 24)
+ : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16)
+ | (word32(block[3]) << 24);
+}
+
+template <class T>
+inline T UnalignedGetWord(ByteOrder order, const byte *block, T* dummy = 0)
+{
+ return UnalignedGetWordNonTemplate(order, block, dummy);
+}
+
+inline void UnalignedPutWord(ByteOrder order, byte *block, byte value,
+ const byte *xorBlock = 0)
+{
+ block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
+}
+
+#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
+
+inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value,
+ const byte *xorBlock = 0)
+{
+ if (order == BigEndianOrder)
+ {
+ block[0] = GETBYTE(value, 1);
+ block[1] = GETBYTE(value, 0);
+ }
+ else
+ {
+ block[0] = GETBYTE(value, 0);
+ block[1] = GETBYTE(value, 1);
+ }
+
+ if (xorBlock)
+ {
+ block[0] ^= xorBlock[0];
+ block[1] ^= xorBlock[1];
+ }
+}
+
+inline void UnalignedPutWord(ByteOrder order, byte* block, word32 value,
+ const byte* xorBlock = 0)
+{
+ if (order == BigEndianOrder)
+ {
+ block[0] = GETBYTE(value, 3);
+ block[1] = GETBYTE(value, 2);
+ block[2] = GETBYTE(value, 1);
+ block[3] = GETBYTE(value, 0);
+ }
+ else
+ {
+ block[0] = GETBYTE(value, 0);
+ block[1] = GETBYTE(value, 1);
+ block[2] = GETBYTE(value, 2);
+ block[3] = GETBYTE(value, 3);
+ }
+
+ if (xorBlock)
+ {
+ block[0] ^= xorBlock[0];
+ block[1] ^= xorBlock[1];
+ block[2] ^= xorBlock[2];
+ block[3] ^= xorBlock[3];
+ }
+}
+
+
+template <class T>
+inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
+{
+ if (assumeAligned)
+ {
+ assert(IsAligned<T>(block));
+ return ByteReverseIf(*reinterpret_cast<const T *>(block), order);
+ }
+ else
+ return UnalignedGetWord<T>(order, block);
+}
+
+template <class T>
+inline void GetWord(bool assumeAligned, ByteOrder order, T &result,
+ const byte *block)
+{
+ result = GetWord<T>(assumeAligned, order, block);
+}
+
+template <class T>
+inline void PutWord(bool assumeAligned, ByteOrder order, byte* block, T value,
+ const byte *xorBlock = 0)
+{
+ if (assumeAligned)
+ {
+ assert(IsAligned<T>(block));
+ if (xorBlock)
+ *reinterpret_cast<T *>(block) = ByteReverseIf(value, order)
+ ^ *reinterpret_cast<const T *>(xorBlock);
+ else
+ *reinterpret_cast<T *>(block) = ByteReverseIf(value, order);
+ }
+ else
+ UnalignedPutWord(order, block, value, xorBlock);
+}
+
+template <class T, class B, bool A=true>
+class GetBlock
+{
+public:
+ GetBlock(const void *block)
+ : m_block((const byte *)block) {}
+
+ template <class U>
+ inline GetBlock<T, B, A> & operator()(U &x)
+ {
+ TAOCRYPT_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
+ x = GetWord<T>(A, B::ToEnum(), m_block);
+ m_block += sizeof(T);
+ return *this;
+ }
+
+private:
+ const byte *m_block;
+};
+
+template <class T, class B, bool A = true>
+class PutBlock
+{
+public:
+ PutBlock(const void *xorBlock, void *block)
+ : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
+
+ template <class U>
+ inline PutBlock<T, B, A> & operator()(U x)
+ {
+ PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
+ m_block += sizeof(T);
+ if (m_xorBlock)
+ m_xorBlock += sizeof(T);
+ return *this;
+ }
+
+private:
+ const byte *m_xorBlock;
+ byte *m_block;
+};
+
+template <class T, class B, bool A=true>
+struct BlockGetAndPut
+{
+ // function needed because of C++ grammatical ambiguity between
+ // expression-statements and declarations
+ static inline GetBlock<T, B, A> Get(const void *block)
+ {return GetBlock<T, B, A>(block);}
+ typedef PutBlock<T, B, A> Put;
+};
+
+
+
+template <bool overflow> struct SafeShifter;
+
+template<> struct SafeShifter<true>
+{
+ template <class T>
+ static inline T RightShift(T value, unsigned int bits)
+ {
+ return 0;
+ }
+
+ template <class T>
+ static inline T LeftShift(T value, unsigned int bits)
+ {
+ return 0;
+ }
+};
+
+template<> struct SafeShifter<false>
+{
+ template <class T>
+ static inline T RightShift(T value, unsigned int bits)
+ {
+ return value >> bits;
+ }
+
+ template <class T>
+ static inline T LeftShift(T value, unsigned int bits)
+ {
+ return value << bits;
+ }
+};
+
+template <unsigned int bits, class T>
+inline T SafeRightShift(T value)
+{
+ return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
+}
+
+template <unsigned int bits, class T>
+inline T SafeLeftShift(T value)
+{
+ return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
+}
+
+
+inline
+word ShiftWordsLeftByBits(word* r, unsigned int n, unsigned int shiftBits)
+{
+ assert (shiftBits<WORD_BITS);
+ word u, carry=0;
+ if (shiftBits)
+ for (unsigned int i=0; i<n; i++)
+ {
+ u = r[i];
+ r[i] = (u << shiftBits) | carry;
+ carry = u >> (WORD_BITS-shiftBits);
+ }
+ return carry;
+}
+
+
+inline
+word ShiftWordsRightByBits(word* r, unsigned int n, unsigned int shiftBits)
+{
+ assert (shiftBits<WORD_BITS);
+ word u, carry=0;
+ if (shiftBits)
+ for (int i=n-1; i>=0; i--)
+ {
+ u = r[i];
+ r[i] = (u >> shiftBits) | carry;
+ carry = u << (WORD_BITS-shiftBits);
+ }
+ return carry;
+}
+
+
+inline
+void ShiftWordsLeftByWords(word* r, unsigned int n, unsigned int shiftWords)
+{
+ shiftWords = min(shiftWords, n);
+ if (shiftWords)
+ {
+ for (unsigned int i=n-1; i>=shiftWords; i--)
+ r[i] = r[i-shiftWords];
+ SetWords(r, 0, shiftWords);
+ }
+}
+
+
+inline
+void ShiftWordsRightByWords(word* r, unsigned int n, unsigned int shiftWords)
+{
+ shiftWords = min(shiftWords, n);
+ if (shiftWords)
+ {
+ for (unsigned int i=0; i+shiftWords<n; i++)
+ r[i] = r[i+shiftWords];
+ SetWords(r+n-shiftWords, 0, shiftWords);
+ }
+}
+
+
+template <class T1, class T2>
+inline T1 SaturatingSubtract(T1 a, T2 b)
+{
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0); // T1 is unsigned type
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1); // T2 is unsigned type
+ return T1((a > b) ? (a - b) : 0);
+}
+
+
+// declares
+unsigned int BytePrecision(unsigned long value);
+unsigned int BitPrecision(unsigned long);
+unsigned long Crop(unsigned long value, unsigned int size);
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MISC_HPP
diff --git a/extra/yassl/taocrypt/include/modarith.hpp b/extra/yassl/taocrypt/include/modarith.hpp
new file mode 100644
index 00000000000..66a841b05c3
--- /dev/null
+++ b/extra/yassl/taocrypt/include/modarith.hpp
@@ -0,0 +1,168 @@
+/* modarith.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* based on Wei Dai's modarith.h from CryptoPP */
+
+
+#ifndef TAO_CRYPT_MODARITH_HPP
+#define TAO_CRYPT_MODARITH_HPP
+
+#include "misc.hpp"
+#include "algebra.hpp"
+
+namespace TaoCrypt {
+
+
+// ModularArithmetic
+class ModularArithmetic : public AbstractRing
+{
+public:
+
+ typedef int RandomizationParameter;
+ typedef Integer Element;
+
+ ModularArithmetic(const Integer &modulus = Integer::One())
+ : modulus(modulus), result((word)0, modulus.reg_.size()) {}
+
+ ModularArithmetic(const ModularArithmetic &ma)
+ : AbstractRing(),
+ modulus(ma.modulus), result((word)0, modulus.reg_.size()) {}
+
+ const Integer& GetModulus() const {return modulus;}
+ void SetModulus(const Integer &newModulus)
+ {
+ modulus = newModulus;
+ result.reg_.resize(modulus.reg_.size());
+ }
+
+ virtual bool IsMontgomeryRepresentation() const {return false;}
+
+ virtual Integer ConvertIn(const Integer &a) const
+ {return a%modulus;}
+
+ virtual Integer ConvertOut(const Integer &a) const
+ {return a;}
+
+ const Integer& Half(const Integer &a) const;
+
+ bool Equal(const Integer &a, const Integer &b) const
+ {return a==b;}
+
+ const Integer& Identity() const
+ {return Integer::Zero();}
+
+ const Integer& Add(const Integer &a, const Integer &b) const;
+
+ Integer& Accumulate(Integer &a, const Integer &b) const;
+
+ const Integer& Inverse(const Integer &a) const;
+
+ const Integer& Subtract(const Integer &a, const Integer &b) const;
+
+ Integer& Reduce(Integer &a, const Integer &b) const;
+
+ const Integer& Double(const Integer &a) const
+ {return Add(a, a);}
+
+ const Integer& MultiplicativeIdentity() const
+ {return Integer::One();}
+
+ const Integer& Multiply(const Integer &a, const Integer &b) const
+ {return result1 = a*b%modulus;}
+
+ const Integer& Square(const Integer &a) const
+ {return result1 = a.Squared()%modulus;}
+
+ bool IsUnit(const Integer &a) const
+ {return Integer::Gcd(a, modulus).IsUnit();}
+
+ const Integer& MultiplicativeInverse(const Integer &a) const
+ {return result1 = a.InverseMod(modulus);}
+
+ const Integer& Divide(const Integer &a, const Integer &b) const
+ {return Multiply(a, MultiplicativeInverse(b));}
+
+ Integer CascadeExponentiate(const Integer &x, const Integer &e1,
+ const Integer &y, const Integer &e2) const;
+
+ void SimultaneousExponentiate(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const;
+
+ unsigned int MaxElementBitLength() const
+ {return (modulus-1).BitCount();}
+
+ unsigned int MaxElementByteLength() const
+ {return (modulus-1).ByteCount();}
+
+
+ static const RandomizationParameter DefaultRandomizationParameter;
+
+protected:
+ Integer modulus;
+ mutable Integer result, result1;
+
+};
+
+
+
+//! do modular arithmetics in Montgomery representation for increased speed
+class MontgomeryRepresentation : public ModularArithmetic
+{
+public:
+ MontgomeryRepresentation(const Integer &modulus); // modulus must be odd
+
+ bool IsMontgomeryRepresentation() const {return true;}
+
+ Integer ConvertIn(const Integer &a) const
+ {return (a<<(WORD_BITS*modulus.reg_.size()))%modulus;}
+
+ Integer ConvertOut(const Integer &a) const;
+
+ const Integer& MultiplicativeIdentity() const
+ {return result1 = Integer::Power2(WORD_BITS*modulus.reg_.size())%modulus;}
+
+ const Integer& Multiply(const Integer &a, const Integer &b) const;
+
+ const Integer& Square(const Integer &a) const;
+
+ const Integer& MultiplicativeInverse(const Integer &a) const;
+
+ Integer CascadeExponentiate(const Integer &x, const Integer &e1,
+ const Integer &y, const Integer &e2) const
+ {return AbstractRing::CascadeExponentiate(x, e1, y, e2);}
+
+ void SimultaneousExponentiate(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const
+ {AbstractRing::SimultaneousExponentiate(results, base,
+ exponents, exponentsCount);}
+
+private:
+ Integer u;
+ mutable AlignedWordBlock workspace;
+};
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MODARITH_HPP
diff --git a/extra/yassl/taocrypt/include/modes.hpp b/extra/yassl/taocrypt/include/modes.hpp
new file mode 100644
index 00000000000..a23d14db7da
--- /dev/null
+++ b/extra/yassl/taocrypt/include/modes.hpp
@@ -0,0 +1,141 @@
+/* modes.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* modes.hpp provides ECB and CBC modes for block cipher encryption/decryption
+*/
+
+
+#ifndef TAO_CRYPT_MODES_HPP
+#define TAO_CRYPT_MODES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+enum Mode { ECB, CBC };
+
+
+// BlockCipher abstraction
+template<CipherDir DIR, class T, Mode MODE>
+class BlockCipher {
+public:
+ BlockCipher() : cipher_(DIR, MODE) {}
+
+ void Process(byte* c, const byte* p, word32 sz)
+ { cipher_.Process(c, p, sz); }
+ void SetKey(const byte* k, word32 sz)
+ { cipher_.SetKey(k, sz, DIR); }
+ void SetKey(const byte* k, word32 sz, const byte* iv)
+ { cipher_.SetKey(k, sz, DIR); cipher_.SetIV(iv); }
+private:
+ T cipher_;
+
+ BlockCipher(const BlockCipher&); // hide copy
+ BlockCipher& operator=(const BlockCipher&); // and assign
+};
+
+
+// Mode Base for block ciphers, static size
+class Mode_BASE : public virtual_base {
+public:
+ enum { MaxBlockSz = 16 };
+
+ explicit Mode_BASE(int sz)
+ : blockSz_(sz), reg_(reinterpret_cast<byte*>(r_)),
+ tmp_(reinterpret_cast<byte*>(t_))
+ {
+ assert(sz <= MaxBlockSz);
+ }
+ virtual ~Mode_BASE() {}
+
+ virtual void ProcessAndXorBlock(const byte*, const byte*, byte*) const = 0;
+
+ void ECB_Process(byte*, const byte*, word32);
+ void CBC_Encrypt(byte*, const byte*, word32);
+ void CBC_Decrypt(byte*, const byte*, word32);
+
+ void SetIV(const byte* iv) { memcpy(reg_, iv, blockSz_); }
+private:
+ int blockSz_;
+ byte* reg_;
+ byte* tmp_;
+
+ word32 r_[MaxBlockSz / sizeof(word32)]; // align reg_ on word32
+ word32 t_[MaxBlockSz / sizeof(word32)]; // align tmp_ on word32
+
+
+ Mode_BASE(const Mode_BASE&); // hide copy
+ Mode_BASE& operator=(const Mode_BASE&); // and assign
+};
+
+
+// ECB Process blocks
+inline void Mode_BASE::ECB_Process(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / blockSz_;
+
+ while (blocks--) {
+ ProcessAndXorBlock(in, 0, out);
+ out += blockSz_;
+ in += blockSz_;
+ }
+}
+
+
+// CBC Encrypt
+inline void Mode_BASE::CBC_Encrypt(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / blockSz_;
+
+ while (blocks--) {
+ xorbuf(reg_, in, blockSz_);
+ ProcessAndXorBlock(reg_, 0, reg_);
+ memcpy(out, reg_, blockSz_);
+ out += blockSz_;
+ in += blockSz_;
+ }
+}
+
+
+// CBC Decrypt
+inline void Mode_BASE::CBC_Decrypt(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / blockSz_;
+ byte hold[MaxBlockSz];
+
+ while (blocks--) {
+ memcpy(tmp_, in, blockSz_);
+ ProcessAndXorBlock(tmp_, 0, out);
+ xorbuf(out, reg_, blockSz_);
+ memcpy(hold, reg_, blockSz_); // swap reg_ and tmp_
+ memcpy(reg_, tmp_, blockSz_);
+ memcpy(tmp_, hold, blockSz_);
+ out += blockSz_;
+ in += blockSz_;
+ }
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MODES_HPP
diff --git a/extra/yassl/taocrypt/include/random.hpp b/extra/yassl/taocrypt/include/random.hpp
new file mode 100644
index 00000000000..62f49a8716f
--- /dev/null
+++ b/extra/yassl/taocrypt/include/random.hpp
@@ -0,0 +1,87 @@
+/* random.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* random.hpp provides a crypto secure Random Number Generator using an OS
+ specific seed
+*/
+
+
+#ifndef TAO_CRYPT_RANDOM_HPP
+#define TAO_CRYPT_RANDOM_HPP
+
+#include "arc4.hpp"
+#include "error.hpp"
+
+namespace TaoCrypt {
+
+
+// OS specific seeder
+class OS_Seed {
+public:
+ OS_Seed();
+ ~OS_Seed();
+
+ void GenerateSeed(byte*, word32 sz);
+ Error GetError() const { return error_; }
+private:
+#if defined(_WIN32)
+ #if defined(_WIN64)
+ typedef unsigned __int64 ProviderHandle;
+ // type HCRYPTPROV, avoid #include <windows.h>
+ #else
+ typedef unsigned long ProviderHandle;
+ #endif
+ ProviderHandle handle_;
+#else
+ int fd_;
+#endif
+ Error error_;
+
+ OS_Seed(const OS_Seed&); // hide copy
+ OS_Seed& operator=(const OS_Seed&); // hide assign
+};
+
+
+// secure Random Nnumber Generator
+class RandomNumberGenerator {
+public:
+ RandomNumberGenerator();
+ ~RandomNumberGenerator() {}
+
+ void GenerateBlock(byte*, word32 sz);
+ byte GenerateByte();
+
+ ErrorNumber GetError() const { return seed_.GetError().What(); }
+private:
+ OS_Seed seed_;
+ ARC4 cipher_;
+
+ RandomNumberGenerator(const RandomNumberGenerator&); // hide copy
+ RandomNumberGenerator operator=(const RandomNumberGenerator&); // && assign
+};
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RANDOM_HPP
+
diff --git a/extra/yassl/taocrypt/include/ripemd.hpp b/extra/yassl/taocrypt/include/ripemd.hpp
new file mode 100644
index 00000000000..4f8e1fd0386
--- /dev/null
+++ b/extra/yassl/taocrypt/include/ripemd.hpp
@@ -0,0 +1,63 @@
+/* ripemd.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* ripemd.hpp provides RIPEMD digest support
+*/
+
+#ifndef TAO_CRYPT_RIPEMD_HPP
+#define TAO_CRYPT_RIPEMD_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// RIPEMD160 digest
+class RIPEMD160 : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 20, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes
+ RIPEMD160() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ RIPEMD160(const RIPEMD160&);
+ RIPEMD160& operator= (const RIPEMD160&);
+
+ void Init();
+ void Swap(RIPEMD160&);
+private:
+ void Transform();
+};
+
+inline void swap(RIPEMD160& a, RIPEMD160& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RIPEMD_HPP
+
diff --git a/extra/yassl/taocrypt/include/rsa.hpp b/extra/yassl/taocrypt/include/rsa.hpp
new file mode 100644
index 00000000000..e327fdd20ad
--- /dev/null
+++ b/extra/yassl/taocrypt/include/rsa.hpp
@@ -0,0 +1,252 @@
+/* rsa.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* rsa.hpp provides RSA ES encrypt/decrypt, SSL (block type 1) sign and verify
+*/
+
+#ifndef TAO_CRYPT_RSA_HPP
+#define TAO_CRYPT_RSA_HPP
+
+#include "integer.hpp"
+#include "random.hpp"
+
+
+namespace TaoCrypt {
+
+class Source;
+
+
+// Public Key Length helper
+class PK_Lengths {
+ const Integer& image_;
+public:
+ explicit PK_Lengths(const Integer& i) : image_(i) {}
+
+ word32 PaddedBlockBitLength() const {return image_.BitCount() - 1;}
+ word32 PaddedBlockByteLength() const
+ {return BitsToBytes(PaddedBlockBitLength());}
+
+ word32 FixedCiphertextLength() const {return image_.ByteCount();}
+ word32 FixedMaxPlaintextLength() const
+ {return SaturatingSubtract(PaddedBlockBitLength() / 8, 10U); }
+};
+
+
+// RSA Public Key
+class RSA_PublicKey {
+protected:
+ Integer n_;
+ Integer e_;
+public:
+ RSA_PublicKey() {}
+ explicit RSA_PublicKey(Source&);
+
+ void Initialize(const Integer& n, const Integer& e) {n_ = n; e_ = e;}
+ void Initialize(Source&);
+
+ Integer ApplyFunction(const Integer& x) const;
+
+ const Integer& GetModulus() const {return n_;}
+ const Integer& GetPublicExponent() const {return e_;}
+
+ void SetModulus(const Integer& n) {n_ = n;}
+ void SetPublicExponent(const Integer& e) {e_ = e;}
+
+ word32 FixedCiphertextLength()
+ {
+ return PK_Lengths(n_).FixedCiphertextLength();
+ }
+
+ RSA_PublicKey(const RSA_PublicKey& other) : n_(other.n_), e_(other.e_) {}
+ RSA_PublicKey& operator=(const RSA_PublicKey& that)
+ {
+ RSA_PublicKey tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(RSA_PublicKey& other)
+ {
+ n_.Swap(other.n_);
+ e_.Swap(other.e_);
+ }
+};
+
+
+// RSA Private Key
+class RSA_PrivateKey : public RSA_PublicKey {
+ Integer d_;
+ Integer p_;
+ Integer q_;
+ Integer dp_;
+ Integer dq_;
+ Integer u_;
+public:
+ RSA_PrivateKey() {}
+ explicit RSA_PrivateKey(Source&);
+
+ void Initialize(const Integer& n, const Integer& e, const Integer& d,
+ const Integer& p, const Integer& q, const Integer& dp,
+ const Integer& dq, const Integer& u)
+ {n_ = n; e_ = e; d_ = d; p_ = p; q_ = q; dp_ = dp; dq_ = dq; u_ = u;}
+ void Initialize(Source&);
+
+ Integer CalculateInverse(RandomNumberGenerator&, const Integer&) const;
+
+ const Integer& GetPrime1() const {return p_;}
+ const Integer& GetPrime2() const {return q_;}
+ const Integer& GetPrivateExponent() const {return d_;}
+ const Integer& GetModPrime1PrivateExponent() const {return dp_;}
+ const Integer& GetModPrime2PrivateExponent() const {return dq_;}
+ const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const
+ {return u_;}
+
+ void SetPrime1(const Integer& p) {p_ = p;}
+ void SetPrime2(const Integer& q) {q_ = q;}
+ void SetPrivateExponent(const Integer& d) {d_ = d;}
+ void SetModPrime1PrivateExponent(const Integer& dp) {dp_ = dp;}
+ void SetModPrime2PrivateExponent(const Integer& dq) {dq_ = dq;}
+ void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer& u) {u_ = u;}
+private:
+ RSA_PrivateKey(const RSA_PrivateKey&); // hide copy
+ RSA_PrivateKey& operator=(const RSA_PrivateKey&); // and assign
+};
+
+
+// block type 2 padding
+class RSA_BlockType2 {
+public:
+ void Pad(const byte*, word32, byte*, word32,
+ RandomNumberGenerator&) const;
+ word32 UnPad(const byte*, word32, byte*) const;
+};
+
+
+// block type 1 padding
+class RSA_BlockType1 {
+public:
+ void Pad(const byte*, word32, byte*, word32,
+ RandomNumberGenerator&) const;
+ word32 UnPad(const byte*, word32, byte*) const;
+};
+
+
+// RSA Encryptor, can use any padding
+template<class Pad = RSA_BlockType2>
+class RSA_Encryptor {
+ const RSA_PublicKey& key_;
+ Pad padding_;
+public:
+ explicit RSA_Encryptor(const RSA_PublicKey& k) : key_(k) {}
+
+ void Encrypt(const byte*, word32, byte*, RandomNumberGenerator&);
+ bool SSL_Verify(const byte* msg, word32 sz, const byte* sig);
+};
+
+
+// RSA Decryptor, can use any padding
+template<class Pad = RSA_BlockType2>
+class RSA_Decryptor {
+ const RSA_PrivateKey& key_;
+ Pad padding_;
+public:
+ explicit RSA_Decryptor(const RSA_PrivateKey& k) : key_(k) {}
+
+ word32 Decrypt(const byte*, word32, byte*, RandomNumberGenerator&);
+ void SSL_Sign(const byte*, word32, byte*, RandomNumberGenerator&);
+};
+
+
+// Public Encrypt
+template<class Pad>
+void RSA_Encryptor<Pad>::Encrypt(const byte* plain, word32 sz, byte* cipher,
+ RandomNumberGenerator& rng)
+{
+ PK_Lengths lengths(key_.GetModulus());
+ assert(sz <= lengths.FixedMaxPlaintextLength());
+
+ ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
+ padding_.Pad(plain, sz, paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), rng);
+
+ key_.ApplyFunction(Integer(paddedBlock.get_buffer(), paddedBlock.size())).
+ Encode(cipher, lengths.FixedCiphertextLength());
+}
+
+
+// Private Decrypt
+template<class Pad>
+word32 RSA_Decryptor<Pad>::Decrypt(const byte* cipher, word32 sz, byte* plain,
+ RandomNumberGenerator& rng)
+{
+ PK_Lengths lengths(key_.GetModulus());
+ assert(sz == lengths.FixedCiphertextLength());
+
+ if (sz != lengths.FixedCiphertextLength())
+ return 0;
+
+ ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
+ Integer x = key_.CalculateInverse(rng, Integer(cipher,
+ lengths.FixedCiphertextLength()).Ref());
+ if (x.ByteCount() > paddedBlock.size())
+ x = Integer::Zero(); // don't return false, prevents timing attack
+ x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
+ return padding_.UnPad(paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), plain);
+}
+
+
+// Private SSL type (block 1) Encrypt
+template<class Pad>
+void RSA_Decryptor<Pad>::SSL_Sign(const byte* message, word32 sz, byte* sig,
+ RandomNumberGenerator& rng)
+{
+ RSA_PublicKey inverse;
+ inverse.Initialize(key_.GetModulus(), key_.GetPrivateExponent());
+ RSA_Encryptor<RSA_BlockType1> enc(inverse); // SSL Type
+ enc.Encrypt(message, sz, sig, rng);
+}
+
+
+word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain);
+
+
+// Public SSL type (block 1) Decrypt
+template<class Pad>
+bool RSA_Encryptor<Pad>::SSL_Verify(const byte* message, word32 sz,
+ const byte* sig)
+{
+ ByteBlock plain(PK_Lengths(key_.GetModulus()).FixedMaxPlaintextLength());
+ SSL_Decrypt(key_, sig, plain.get_buffer());
+
+ if ( (memcmp(plain.get_buffer(), message, sz)) == 0)
+ return true;
+ return false;
+}
+
+
+typedef RSA_Encryptor<> RSAES_Encryptor;
+typedef RSA_Decryptor<> RSAES_Decryptor;
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RSA_HPP
diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp
new file mode 100644
index 00000000000..254e67a7f64
--- /dev/null
+++ b/extra/yassl/taocrypt/include/runtime.hpp
@@ -0,0 +1,52 @@
+/* runtime.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* runtime.hpp provides C++ runtime support functions when building a pure C
+ * version of yaSSL, user must define YASSL_PURE_C
+*/
+
+
+
+#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__)
+#if !(defined(__ICC) || defined(__INTEL_COMPILER))
+
+#define yaSSL_NEW_HPP
+
+#if __GNUC__ > 2
+
+extern "C" {
+#include <assert.h>
+
+/* Disallow inline __cxa_pure_virtual() */
+static int __cxa_pure_virtual() __attribute__((noinline, used));
+static int __cxa_pure_virtual()
+{
+ // oops, pure virtual called!
+ assert("Pure virtual method called." == "Aborted");
+ return 0;
+}
+
+} // extern "C"
+
+#endif // __GNUC__ > 2
+#endif // ! _ICC
+#endif // yaSSL_NEW_HPP && __GNUC__
+
diff --git a/extra/yassl/taocrypt/include/sha.hpp b/extra/yassl/taocrypt/include/sha.hpp
new file mode 100644
index 00000000000..b75d9e3f670
--- /dev/null
+++ b/extra/yassl/taocrypt/include/sha.hpp
@@ -0,0 +1,65 @@
+/* sha.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* sha.hpp provides SHA-1 digests, see RFC 3174
+*/
+
+#ifndef TAO_CRYPT_SHA_HPP
+#define TAO_CRYPT_SHA_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// SHA-1 digest
+class SHA : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 20, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = BigEndianOrder}; // in Bytes
+ SHA() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ void Init();
+
+ SHA(const SHA&);
+ SHA& operator= (const SHA&);
+
+ void Swap(SHA&);
+private:
+ void Transform();
+};
+
+
+inline void swap(SHA& a, SHA& b)
+{
+ a.Swap(b);
+}
+
+} // namespace
+
+
+#endif // TAO_CRYPT_SHA_HPP
+
diff --git a/extra/yassl/taocrypt/include/type_traits.hpp b/extra/yassl/taocrypt/include/type_traits.hpp
new file mode 100644
index 00000000000..d03ccae64ed
--- /dev/null
+++ b/extra/yassl/taocrypt/include/type_traits.hpp
@@ -0,0 +1,80 @@
+/* type_traits.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* type_traits defines fundamental types
+ * see discussion in C++ Templates, $19.1
+*/
+
+
+#ifndef TAO_CRYPT_TYPE_TRAITS_HPP
+#define TAO_CRYPT_TYPE_TRAITS_HPP
+
+#include "types.hpp"
+
+namespace TaoCrypt {
+
+
+// primary template: in general T is not a fundamental type
+
+template <typename T>
+class IsFundamentalType {
+ public:
+ enum { Yes = 0, No = 1 };
+};
+
+
+// macro to specialize for fundamental types
+#define MK_FUNDAMENTAL_TYPE(T) \
+ template<> class IsFundamentalType<T> { \
+ public: \
+ enum { Yes = 1, No = 0 }; \
+ };
+
+
+MK_FUNDAMENTAL_TYPE(void)
+
+MK_FUNDAMENTAL_TYPE(bool)
+MK_FUNDAMENTAL_TYPE( char)
+MK_FUNDAMENTAL_TYPE(signed char)
+MK_FUNDAMENTAL_TYPE(unsigned char)
+
+MK_FUNDAMENTAL_TYPE(signed short)
+MK_FUNDAMENTAL_TYPE(unsigned short)
+MK_FUNDAMENTAL_TYPE(signed int)
+MK_FUNDAMENTAL_TYPE(unsigned int)
+MK_FUNDAMENTAL_TYPE(signed long)
+MK_FUNDAMENTAL_TYPE(unsigned long)
+
+MK_FUNDAMENTAL_TYPE(float)
+MK_FUNDAMENTAL_TYPE( double)
+MK_FUNDAMENTAL_TYPE(long double)
+
+#if defined(WORD64_AVAILABLE) && defined(WORD64_IS_DISTINCT_TYPE)
+ MK_FUNDAMENTAL_TYPE(word64)
+#endif
+
+
+#undef MK_FUNDAMENTAL_TYPE
+
+
+} // namespace
+
+#endif // TAO_CRYPT_TYPE_TRAITS_HPP
diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp
new file mode 100644
index 00000000000..db9c3792bbd
--- /dev/null
+++ b/extra/yassl/taocrypt/include/types.hpp
@@ -0,0 +1,97 @@
+/* types.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's misc.h from CryptoPP, basic crypt types */
+
+
+#ifndef TAO_CRYPT_TYPES_HPP
+#define TAO_CRYPT_TYPES_HPP
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+namespace TaoCrypt {
+
+
+#if defined(WORDS_BIGENDIAN) || (defined(__MWERKS__) && !defined(__INTEL__))
+ #define BIG_ENDIAN_ORDER
+#endif
+
+#ifndef BIG_ENDIAN_ORDER
+ #define LITTLE_ENDIAN_ORDER
+#endif
+
+
+typedef unsigned char byte;
+typedef unsigned short word16;
+typedef unsigned int word32;
+
+#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+ #define WORD64_AVAILABLE
+ #define WORD64_IS_DISTINCT_TYPE
+ typedef unsigned __int64 word64;
+#elif SIZEOF_LONG == 8
+ #define WORD64_AVAILABLE
+ typedef unsigned long word64;
+#elif SIZEOF_LONG_LONG == 8
+ #define WORD64_AVAILABLE
+ #define WORD64_IS_DISTINCT_TYPE
+ typedef unsigned long long word64;
+#endif
+
+
+// compilers we've found 64-bit multiply insructions for
+#if defined(__GNUC__) || defined(_MSC_VER) || defined(__DECCXX)
+#if !(defined(__ICC) || defined(__INTEL_COMPILER))
+ #define HAVE_64_MULTIPLY
+#endif
+#endif
+
+#if defined(HAVE_64_MULTIPLY) && (defined(__alpha__) || defined(__ia64__) \
+ || defined(_ARCH_PPC64) || defined(__mips64) || defined(__x86_64__))
+// These platforms have 64-bit CPU registers. Unfortunately most C++ compilers
+// don't allow any way to access the 64-bit by 64-bit multiply instruction
+// without using assembly, so in order to use word64 as word, the assembly
+// instruction must be defined in Dword::Multiply().
+ typedef word32 hword;
+ typedef word64 word;
+#else
+ #define TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ #ifdef WORD64_AVAILABLE
+ #define TAOCRYPT_SLOW_WORD64
+ typedef word16 hword;
+ typedef word32 word;
+ typedef word64 dword;
+ #else
+ typedef byte hword;
+ typedef word16 word;
+ typedef word32 dword;
+ #endif
+#endif
+
+const word32 WORD_SIZE = sizeof(word);
+const word32 WORD_BITS = WORD_SIZE * 8;
+
+
+} // namespace
+
+#endif // TAO_CRYPT_TYPES_HPP
diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am
new file mode 100644
index 00000000000..c4fc4607622
--- /dev/null
+++ b/extra/yassl/taocrypt/src/Makefile.am
@@ -0,0 +1,12 @@
+INCLUDES = -I../include -I../../mySTL
+
+noinst_LTLIBRARIES = libtaocrypt.la libtaoint.la
+libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \
+ coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp \
+ md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp \
+ template_instnt.cpp
+libtaocrypt_la_LIBADD = libtaoint.la
+libtaoint_la_SOURCES = integer.cpp
+libtaoint_la_CXXFLAGS = @yassl_integer_extra_cxxflags@
+EXTRA_DIST = ../include/*.hpp
+AM_CXXFLAGS = -DYASSL_PURE_C
diff --git a/extra/yassl/taocrypt/src/aes.cpp b/extra/yassl/taocrypt/src/aes.cpp
new file mode 100644
index 00000000000..09cf28a40b0
--- /dev/null
+++ b/extra/yassl/taocrypt/src/aes.cpp
@@ -0,0 +1,400 @@
+/* aes.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's aes.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "aes.hpp"
+
+
+namespace TaoCrypt {
+
+
+void AES::Process(byte* out, const byte* in, word32 sz)
+{
+ if (mode_ == ECB)
+ ECB_Process(out, in, sz);
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ CBC_Encrypt(out, in, sz);
+ else
+ CBC_Decrypt(out, in, sz);
+}
+
+
+
+void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/)
+{
+ assert( (keylen == 16) || (keylen == 24) || (keylen == 32) );
+
+ rounds_ = keylen/4 + 6;
+ key_.New(4*(rounds_+1));
+
+ word32 temp, *rk = key_.get_buffer();
+ unsigned int i=0;
+
+ GetUserKey(BigEndianOrder, rk, keylen/4, userKey, keylen);
+
+ switch(keylen)
+ {
+ case 16:
+ while (true)
+ {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10)
+ break;
+ rk += 4;
+ }
+ break;
+
+ case 24:
+ while (true) // for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack
+ {
+ temp = rk[ 5];
+ rk[ 6] = rk[ 0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8)
+ break;
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ break;
+
+ case 32:
+ while (true)
+ {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7)
+ break;
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
+ (Te4[GETBYTE(temp, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 0)] & 0x000000ff);
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+
+ rk += 8;
+ }
+ break;
+ }
+
+ if (dir_ == DECRYPTION)
+ {
+ unsigned int i, j;
+ rk = key_.get_buffer();
+
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4*rounds_; i < j; i += 4, j -= 4) {
+ temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
+ temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+ temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+ temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+ }
+ // apply the inverse MixColumn transform to all round keys but the
+ // first and the last:
+ for (i = 1; i < rounds_; i++) {
+ rk += 4;
+ rk[0] =
+ Td0[Te4[GETBYTE(rk[0], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[0], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[0], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[0], 0)] & 0xff];
+ rk[1] =
+ Td0[Te4[GETBYTE(rk[1], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[1], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[1], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[1], 0)] & 0xff];
+ rk[2] =
+ Td0[Te4[GETBYTE(rk[2], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[2], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[2], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[2], 0)] & 0xff];
+ rk[3] =
+ Td0[Te4[GETBYTE(rk[3], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[3], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[3], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[3], 0)] & 0xff];
+ }
+ }
+}
+
+
+typedef BlockGetAndPut<word32, BigEndian> gpBlock;
+
+void AES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
+{
+ if (dir_ == ENCRYPTION)
+ encrypt(in, xOr, out);
+ else
+ decrypt(in, xOr, out);
+}
+
+
+void AES::encrypt(const byte* inBlock, const byte* xorBlock,
+ byte* outBlock) const
+{
+ word32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const word32 *rk = key_.get_buffer();
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ gpBlock::Get(inBlock)(s0)(s1)(s2)(s3);
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+ /*
+ * Nr - 1 full rounds:
+ */
+ unsigned int r = rounds_ >> 1;
+ for (;;) {
+ t0 =
+ Te0[GETBYTE(s0, 3)] ^
+ Te1[GETBYTE(s1, 2)] ^
+ Te2[GETBYTE(s2, 1)] ^
+ Te3[GETBYTE(s3, 0)] ^
+ rk[4];
+ t1 =
+ Te0[GETBYTE(s1, 3)] ^
+ Te1[GETBYTE(s2, 2)] ^
+ Te2[GETBYTE(s3, 1)] ^
+ Te3[GETBYTE(s0, 0)] ^
+ rk[5];
+ t2 =
+ Te0[GETBYTE(s2, 3)] ^
+ Te1[GETBYTE(s3, 2)] ^
+ Te2[GETBYTE(s0, 1)] ^
+ Te3[GETBYTE(s1, 0)] ^
+ rk[6];
+ t3 =
+ Te0[GETBYTE(s3, 3)] ^
+ Te1[GETBYTE(s0, 2)] ^
+ Te2[GETBYTE(s1, 1)] ^
+ Te3[GETBYTE(s2, 0)] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Te0[GETBYTE(t0, 3)] ^
+ Te1[GETBYTE(t1, 2)] ^
+ Te2[GETBYTE(t2, 1)] ^
+ Te3[GETBYTE(t3, 0)] ^
+ rk[0];
+ s1 =
+ Te0[GETBYTE(t1, 3)] ^
+ Te1[GETBYTE(t2, 2)] ^
+ Te2[GETBYTE(t3, 1)] ^
+ Te3[GETBYTE(t0, 0)] ^
+ rk[1];
+ s2 =
+ Te0[GETBYTE(t2, 3)] ^
+ Te1[GETBYTE(t3, 2)] ^
+ Te2[GETBYTE(t0, 1)] ^
+ Te3[GETBYTE(t1, 0)] ^
+ rk[2];
+ s3 =
+ Te0[GETBYTE(t3, 3)] ^
+ Te1[GETBYTE(t0, 2)] ^
+ Te2[GETBYTE(t1, 1)] ^
+ Te3[GETBYTE(t2, 0)] ^
+ rk[3];
+ }
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+
+ s0 =
+ (Te4[GETBYTE(t0, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t1, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t2, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t3, 0)] & 0x000000ff) ^
+ rk[0];
+ s1 =
+ (Te4[GETBYTE(t1, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t2, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t3, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t0, 0)] & 0x000000ff) ^
+ rk[1];
+ s2 =
+ (Te4[GETBYTE(t2, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t3, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t0, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t1, 0)] & 0x000000ff) ^
+ rk[2];
+ s3 =
+ (Te4[GETBYTE(t3, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t0, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t1, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t2, 0)] & 0x000000ff) ^
+ rk[3];
+
+ gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
+
+}
+
+
+void AES::decrypt(const byte* inBlock, const byte* xorBlock,
+ byte* outBlock) const
+{
+ word32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const word32* rk = key_.get_buffer();
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ gpBlock::Get(inBlock)(s0)(s1)(s2)(s3);
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+ /*
+ * Nr - 1 full rounds:
+ */
+ unsigned int r = rounds_ >> 1;
+ for (;;) {
+ t0 =
+ Td0[GETBYTE(s0, 3)] ^
+ Td1[GETBYTE(s3, 2)] ^
+ Td2[GETBYTE(s2, 1)] ^
+ Td3[GETBYTE(s1, 0)] ^
+ rk[4];
+ t1 =
+ Td0[GETBYTE(s1, 3)] ^
+ Td1[GETBYTE(s0, 2)] ^
+ Td2[GETBYTE(s3, 1)] ^
+ Td3[GETBYTE(s2, 0)] ^
+ rk[5];
+ t2 =
+ Td0[GETBYTE(s2, 3)] ^
+ Td1[GETBYTE(s1, 2)] ^
+ Td2[GETBYTE(s0, 1)] ^
+ Td3[GETBYTE(s3, 0)] ^
+ rk[6];
+ t3 =
+ Td0[GETBYTE(s3, 3)] ^
+ Td1[GETBYTE(s2, 2)] ^
+ Td2[GETBYTE(s1, 1)] ^
+ Td3[GETBYTE(s0, 0)] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Td0[GETBYTE(t0, 3)] ^
+ Td1[GETBYTE(t3, 2)] ^
+ Td2[GETBYTE(t2, 1)] ^
+ Td3[GETBYTE(t1, 0)] ^
+ rk[0];
+ s1 =
+ Td0[GETBYTE(t1, 3)] ^
+ Td1[GETBYTE(t0, 2)] ^
+ Td2[GETBYTE(t3, 1)] ^
+ Td3[GETBYTE(t2, 0)] ^
+ rk[1];
+ s2 =
+ Td0[GETBYTE(t2, 3)] ^
+ Td1[GETBYTE(t1, 2)] ^
+ Td2[GETBYTE(t0, 1)] ^
+ Td3[GETBYTE(t3, 0)] ^
+ rk[2];
+ s3 =
+ Td0[GETBYTE(t3, 3)] ^
+ Td1[GETBYTE(t2, 2)] ^
+ Td2[GETBYTE(t1, 1)] ^
+ Td3[GETBYTE(t0, 0)] ^
+ rk[3];
+ }
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Td4[GETBYTE(t0, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t3, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t2, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t1, 0)] & 0x000000ff) ^
+ rk[0];
+ s1 =
+ (Td4[GETBYTE(t1, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t0, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t3, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t2, 0)] & 0x000000ff) ^
+ rk[1];
+ s2 =
+ (Td4[GETBYTE(t2, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t1, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t0, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t3, 0)] & 0x000000ff) ^
+ rk[2];
+ s3 =
+ (Td4[GETBYTE(t3, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t2, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t1, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t0, 0)] & 0x000000ff) ^
+ rk[3];
+
+ gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
+}
+
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/aestables.cpp b/extra/yassl/taocrypt/src/aestables.cpp
new file mode 100644
index 00000000000..7ba25bc9ffb
--- /dev/null
+++ b/extra/yassl/taocrypt/src/aestables.cpp
@@ -0,0 +1,724 @@
+/* aestables.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's aestables.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "aes.hpp"
+
+
+namespace TaoCrypt {
+
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+const word32 AES::Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+const word32 AES::Te1[256] = {
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+const word32 AES::Te2[256] = {
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+
+const word32 AES::Te3[256] = {
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+
+const word32 AES::Te4[256] = {
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+ 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+ 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+ 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+ 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+ 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+ 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+ 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+ 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+ 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+ 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+ 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+ 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+ 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+ 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+ 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+ 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+ 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+ 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+ 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+ 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+ 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+ 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+ 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+ 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+ 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+ 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+ 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+ 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+ 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+ 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+ 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+ 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+ 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+
+const word32 AES::Td0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+
+const word32 AES::Td1[256] = {
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+
+const word32 AES::Td2[256] = {
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+
+const word32 AES::Td3[256] = {
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+
+const word32 AES::Td4[256] = {
+ 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+ 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+ 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+ 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+ 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+ 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+ 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+ 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+ 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+ 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+ 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+ 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+ 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+ 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+ 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+ 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+ 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+ 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+ 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+ 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+ 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+ 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+ 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+ 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+ 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+ 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+ 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+ 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+ 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+ 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+ 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+ 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+ 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+ 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+ 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+ 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+ 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+ 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+ 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+ 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+ 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+ 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+ 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+ 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+ 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+ 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+ 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+ 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+ 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+ 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+ 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+ 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+ 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+ 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+ 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+ 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+ 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+ 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+ 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+ 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+ 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+ 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+ 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+ 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+
+const word32 AES::rcon_[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000,
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp
new file mode 100644
index 00000000000..45bbcfa662a
--- /dev/null
+++ b/extra/yassl/taocrypt/src/algebra.cpp
@@ -0,0 +1,329 @@
+/* algebra.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's algebra.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "algebra.hpp"
+#include "vector.hpp" // mySTL::vector (simple)
+
+
+namespace TaoCrypt {
+
+
+const Integer& AbstractGroup::Double(const Element &a) const
+{
+ return Add(a, a);
+}
+
+const Integer& AbstractGroup::Subtract(const Element &a, const Element &b) const
+{
+ // make copy of a in case Inverse() overwrites it
+ Element a1(a);
+ return Add(a1, Inverse(b));
+}
+
+Integer& AbstractGroup::Accumulate(Element &a, const Element &b) const
+{
+ return a = Add(a, b);
+}
+
+Integer& AbstractGroup::Reduce(Element &a, const Element &b) const
+{
+ return a = Subtract(a, b);
+}
+
+const Integer& AbstractRing::Square(const Element &a) const
+{
+ return Multiply(a, a);
+}
+
+
+const Integer& AbstractRing::Divide(const Element &a, const Element &b) const
+{
+ // make copy of a in case MultiplicativeInverse() overwrites it
+ Element a1(a);
+ return Multiply(a1, MultiplicativeInverse(b));
+}
+
+
+const Integer& AbstractEuclideanDomain::Mod(const Element &a,
+ const Element &b) const
+{
+ Element q;
+ DivisionAlgorithm(result, q, a, b);
+ return result;
+}
+
+const Integer& AbstractEuclideanDomain::Gcd(const Element &a,
+ const Element &b) const
+{
+ Element g[3]={b, a};
+ unsigned int i0=0, i1=1, i2=2;
+
+ while (!Equal(g[i1], this->Identity()))
+ {
+ g[i2] = Mod(g[i0], g[i1]);
+ unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
+ }
+
+ return result = g[i0];
+}
+
+
+Integer AbstractGroup::ScalarMultiply(const Element &base,
+ const Integer &exponent) const
+{
+ Element result;
+ SimultaneousMultiply(&result, base, &exponent, 1);
+ return result;
+}
+
+
+Integer AbstractGroup::CascadeScalarMultiply(const Element &x,
+ const Integer &e1, const Element &y, const Integer &e2) const
+{
+ const unsigned expLen = max(e1.BitCount(), e2.BitCount());
+ if (expLen==0)
+ return Identity();
+
+ const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
+ const unsigned tableSize = 1<<w;
+ mySTL::vector<Element> powerTable(tableSize << w);
+
+ powerTable[1] = x;
+ powerTable[tableSize] = y;
+ if (w==1)
+ powerTable[3] = Add(x,y);
+ else
+ {
+ powerTable[2] = Double(x);
+ powerTable[2*tableSize] = Double(y);
+
+ unsigned i, j;
+
+ for (i=3; i<tableSize; i+=2)
+ powerTable[i] = Add(powerTable[i-2], powerTable[2]);
+ for (i=1; i<tableSize; i+=2)
+ for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
+ powerTable[j] = Add(powerTable[j-tableSize], y);
+
+ for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
+ powerTable[i] = Add(powerTable[i-2*tableSize],
+ powerTable[2*tableSize]);
+ for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
+ for (j=i+2; j<i+tableSize; j+=2)
+ powerTable[j] = Add(powerTable[j-1], x);
+ }
+
+ Element result;
+ unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
+ bool firstTime = true;
+
+ for (int i = expLen-1; i>=0; i--)
+ {
+ power1 = 2*power1 + e1.GetBit(i);
+ power2 = 2*power2 + e2.GetBit(i);
+
+ if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
+ {
+ unsigned squaresBefore = prevPosition-i;
+ unsigned squaresAfter = 0;
+ prevPosition = i;
+ while ((power1 || power2) && power1%2 == 0 && power2%2==0)
+ {
+ power1 /= 2;
+ power2 /= 2;
+ squaresBefore--;
+ squaresAfter++;
+ }
+ if (firstTime)
+ {
+ result = powerTable[(power2<<w) + power1];
+ firstTime = false;
+ }
+ else
+ {
+ while (squaresBefore--)
+ result = Double(result);
+ if (power1 || power2)
+ Accumulate(result, powerTable[(power2<<w) + power1]);
+ }
+ while (squaresAfter--)
+ result = Double(result);
+ power1 = power2 = 0;
+ }
+ }
+ return result;
+}
+
+
+struct WindowSlider
+{
+ WindowSlider(const Integer &exp, bool fastNegate,
+ unsigned int windowSizeIn=0)
+ : exp(exp), windowModulus(Integer::One()), windowSize(windowSizeIn),
+ windowBegin(0), fastNegate(fastNegate), firstTime(true),
+ finished(false)
+ {
+ if (windowSize == 0)
+ {
+ unsigned int expLen = exp.BitCount();
+ windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 :
+ (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 :
+ (expLen <= 1434 ? 6 : 7)))));
+ }
+ windowModulus <<= windowSize;
+ }
+
+ void FindNextWindow()
+ {
+ unsigned int expLen = exp.WordCount() * WORD_BITS;
+ unsigned int skipCount = firstTime ? 0 : windowSize;
+ firstTime = false;
+ while (!exp.GetBit(skipCount))
+ {
+ if (skipCount >= expLen)
+ {
+ finished = true;
+ return;
+ }
+ skipCount++;
+ }
+
+ exp >>= skipCount;
+ windowBegin += skipCount;
+ expWindow = exp % (1 << windowSize);
+
+ if (fastNegate && exp.GetBit(windowSize))
+ {
+ negateNext = true;
+ expWindow = (1 << windowSize) - expWindow;
+ exp += windowModulus;
+ }
+ else
+ negateNext = false;
+ }
+
+ Integer exp, windowModulus;
+ unsigned int windowSize, windowBegin, expWindow;
+ bool fastNegate, negateNext, firstTime, finished;
+};
+
+
+void AbstractGroup::SimultaneousMultiply(Integer *results, const Integer &base,
+ const Integer *expBegin, unsigned int expCount) const
+{
+ mySTL::vector<mySTL::vector<Element> > buckets(expCount);
+ mySTL::vector<WindowSlider> exponents;
+ exponents.reserve(expCount);
+ unsigned int i;
+
+ for (i=0; i<expCount; i++)
+ {
+ assert(expBegin->NotNegative());
+ exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
+ exponents[i].FindNextWindow();
+ buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
+ }
+
+ unsigned int expBitPosition = 0;
+ Element g = base;
+ bool notDone = true;
+
+ while (notDone)
+ {
+ notDone = false;
+ for (i=0; i<expCount; i++)
+ {
+ if (!exponents[i].finished && expBitPosition ==
+ exponents[i].windowBegin)
+ {
+ Element &bucket = buckets[i][exponents[i].expWindow/2];
+ if (exponents[i].negateNext)
+ Accumulate(bucket, Inverse(g));
+ else
+ Accumulate(bucket, g);
+ exponents[i].FindNextWindow();
+ }
+ notDone = notDone || !exponents[i].finished;
+ }
+
+ if (notDone)
+ {
+ g = Double(g);
+ expBitPosition++;
+ }
+ }
+
+ for (i=0; i<expCount; i++)
+ {
+ Element &r = *results++;
+ r = buckets[i][buckets[i].size()-1];
+ if (buckets[i].size() > 1)
+ {
+ for (int j = buckets[i].size()-2; j >= 1; j--)
+ {
+ Accumulate(buckets[i][j], buckets[i][j+1]);
+ Accumulate(r, buckets[i][j]);
+ }
+ Accumulate(buckets[i][0], buckets[i][1]);
+ r = Add(Double(r), buckets[i][0]);
+ }
+ }
+}
+
+Integer AbstractRing::Exponentiate(const Element &base,
+ const Integer &exponent) const
+{
+ Element result;
+ SimultaneousExponentiate(&result, base, &exponent, 1);
+ return result;
+}
+
+
+Integer AbstractRing::CascadeExponentiate(const Element &x,
+ const Integer &e1, const Element &y, const Integer &e2) const
+{
+ return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply(
+ x, e1, y, e2);
+}
+
+
+void AbstractRing::SimultaneousExponentiate(Integer *results,
+ const Integer &base,
+ const Integer *exponents, unsigned int expCount) const
+{
+ MultiplicativeGroup().AbstractGroup::SimultaneousMultiply(results, base,
+ exponents, expCount);
+}
+
+
+} // namespace
+
+
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+namespace mySTL {
+template TaoCrypt::WindowSlider* uninit_copy<TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
+template void destroy<TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
+}
+#endif
+
diff --git a/extra/yassl/taocrypt/src/arc4.cpp b/extra/yassl/taocrypt/src/arc4.cpp
new file mode 100644
index 00000000000..1e521b48f0c
--- /dev/null
+++ b/extra/yassl/taocrypt/src/arc4.cpp
@@ -0,0 +1,93 @@
+/* arc4.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's arc4.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "arc4.hpp"
+
+
+namespace TaoCrypt {
+
+void ARC4::SetKey(const byte* key, word32 length)
+{
+ x_ = 1;
+ y_ = 0;
+
+ word32 i;
+
+ for (i = 0; i < STATE_SIZE; i++)
+ state_[i] = i;
+
+ word32 keyIndex = 0, stateIndex = 0;
+
+ for (i = 0; i < STATE_SIZE; i++) {
+ word32 a = state_[i];
+ stateIndex += key[keyIndex] + a;
+ stateIndex &= 0xFF;
+ state_[i] = state_[stateIndex];
+ state_[stateIndex] = a;
+
+ if (++keyIndex >= length)
+ keyIndex = 0;
+ }
+}
+
+
+// local
+namespace {
+
+inline unsigned int MakeByte(word32& x, word32& y, byte* s)
+{
+ word32 a = s[x];
+ y = (y+a) & 0xff;
+
+ word32 b = s[y];
+ s[x] = b;
+ s[y] = a;
+ x = (x+1) & 0xff;
+
+ return s[(a+b) & 0xff];
+}
+
+} // namespace
+
+
+void ARC4::Process(byte* out, const byte* in, word32 length)
+{
+ if (length == 0) return;
+
+ byte *const s = state_;
+ word32 x = x_;
+ word32 y = y_;
+
+ if (in == out)
+ while (length--)
+ *out++ ^= MakeByte(x, y, s);
+ else
+ while(length--)
+ *out++ = *in++ ^ MakeByte(x, y, s);
+ x_ = x;
+ y_ = y;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
new file mode 100644
index 00000000000..8f8d2ba52da
--- /dev/null
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -0,0 +1,1050 @@
+ /* asn.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* asn.cpp implements ASN1 BER, PublicKey, and x509v3 decoding
+*/
+
+#include "runtime.hpp"
+#include "asn.hpp"
+#include "file.hpp"
+#include "integer.hpp"
+#include "rsa.hpp"
+#include "dsa.hpp"
+#include "dh.hpp"
+#include "md5.hpp"
+#include "md2.hpp"
+#include "sha.hpp"
+#include "coding.hpp"
+#include <time.h> // gmtime();
+#include "memory.hpp" // mySTL::auto_ptr
+
+namespace TaoCrypt {
+
+namespace { // locals
+
+
+// to the minute
+bool operator>(tm& a, tm& b)
+{
+ if (a.tm_year > b.tm_year)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon > b.tm_mon)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && a.tm_mday >b.tm_mday)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon &&
+ a.tm_mday == b.tm_mday && a.tm_hour > b.tm_hour)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon &&
+ a.tm_mday == b.tm_mday && a.tm_hour == b.tm_hour &&
+ a.tm_min > b.tm_min)
+ return true;
+
+ return false;
+}
+
+
+bool operator<(tm& a, tm&b)
+{
+ return !(a>b);
+}
+
+
+// like atoi but only use first byte
+word32 btoi(byte b)
+{
+ return b - 0x30;
+}
+
+
+// two byte date/time, add to value
+void GetTime(int& value, const byte* date, int& i)
+{
+ value += btoi(date[i++]) * 10;
+ value += btoi(date[i++]);
+}
+
+
+// Make sure before and after dates are valid
+bool ValidateDate(const byte* date, byte format, CertDecoder::DateType dt)
+{
+ tm certTime;
+ memset(&certTime, 0, sizeof(certTime));
+ int i = 0;
+
+ if (format == UTC_TIME) {
+ if (btoi(date[0]) >= 5)
+ certTime.tm_year = 1900;
+ else
+ certTime.tm_year = 2000;
+ }
+ else { // format == GENERALIZED_TIME
+ certTime.tm_year += btoi(date[i++]) * 1000;
+ certTime.tm_year += btoi(date[i++]) * 100;
+ }
+
+ GetTime(certTime.tm_year, date, i); certTime.tm_year -= 1900; // adjust
+ GetTime(certTime.tm_mon, date, i); certTime.tm_mon -= 1; // adjust
+ GetTime(certTime.tm_mday, date, i);
+ GetTime(certTime.tm_hour, date, i);
+ GetTime(certTime.tm_min, date, i);
+ GetTime(certTime.tm_sec, date, i);
+
+ assert(date[i] == 'Z'); // only Zulu supported for this profile
+
+ time_t ltime = time(0);
+ tm* localTime = gmtime(&ltime);
+
+ if (dt == CertDecoder::BEFORE) {
+ if (*localTime < certTime)
+ return false;
+ }
+ else
+ if (*localTime > certTime)
+ return false;
+
+ return true;
+}
+
+
+class BadCertificate {};
+
+} // local namespace
+
+
+
+// used by Integer as well
+word32 GetLength(Source& source)
+{
+ word32 length = 0;
+
+ byte b = source.next();
+ if (b >= LONG_LENGTH) {
+ word32 bytes = b & 0x7F;
+
+ while (bytes--) {
+ b = source.next();
+ length = (length << 8) | b;
+ }
+ }
+ else
+ length = b;
+
+ return length;
+}
+
+
+word32 SetLength(word32 length, byte* output)
+{
+ word32 i = 0;
+
+ if (length < LONG_LENGTH)
+ output[i++] = length;
+ else {
+ output[i++] = BytePrecision(length) | 0x80;
+
+ for (int j = BytePrecision(length); j; --j) {
+ output[i] = length >> (j - 1) * 8;
+ i++;
+ }
+ }
+ return i;
+}
+
+
+PublicKey::PublicKey(const byte* k, word32 s) : key_(0), sz_(0)
+{
+ if (s) {
+ SetSize(s);
+ SetKey(k);
+ }
+}
+
+
+void PublicKey::SetSize(word32 s)
+{
+ sz_ = s;
+ key_ = new (tc) byte[sz_];
+}
+
+
+void PublicKey::SetKey(const byte* k)
+{
+ memcpy(key_, k, sz_);
+}
+
+
+void PublicKey::AddToEnd(const byte* data, word32 len)
+{
+ mySTL::auto_ptr<byte> tmp(new (tc) byte[sz_ + len], tcArrayDelete);
+
+ memcpy(tmp.get(), key_, sz_);
+ memcpy(tmp.get() + sz_, data, len);
+
+ byte* del = 0;
+ mySTL::swap(del, key_);
+ tcArrayDelete(del);
+
+ key_ = tmp.release();
+ sz_ += len;
+}
+
+
+Signer::Signer(const byte* k, word32 kSz, const char* n, const byte* h)
+ : key_(k, kSz), name_(0)
+{
+ if (n) {
+ int sz = strlen(n);
+ name_ = new (tc) char[sz + 1];
+ memcpy(name_, n, sz);
+ name_[sz] = 0;
+ }
+
+ memcpy(hash_, h, SHA::DIGEST_SIZE);
+}
+
+Signer::~Signer()
+{
+ tcArrayDelete(name_);
+}
+
+
+Error BER_Decoder::GetError()
+{
+ return source_.GetError();
+}
+
+
+Integer& BER_Decoder::GetInteger(Integer& integer)
+{
+ if (!source_.GetError().What())
+ integer.Decode(source_);
+ return integer;
+}
+
+
+// Read a Sequence, return length
+word32 BER_Decoder::GetSequence()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != (SEQUENCE | CONSTRUCTED)) {
+ source_.SetError(SEQUENCE_E);
+ return 0;
+ }
+
+ return GetLength(source_);
+}
+
+
+// Read a Sequence, return length
+word32 BER_Decoder::GetSet()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != (SET | CONSTRUCTED)) {
+ source_.SetError(SET_E);
+ return 0;
+ }
+
+ return GetLength(source_);
+}
+
+
+// Read Version, return it
+word32 BER_Decoder::GetVersion()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != INTEGER) {
+ source_.SetError(INTEGER_E);
+ return 0;
+ }
+
+ b = source_.next();
+ if (b != 0x01) {
+ source_.SetError(VERSION_E);
+ return 0;
+ }
+
+ return source_.next();
+}
+
+
+// Read ExplicitVersion, return it or 0 if not there (not an error)
+word32 BER_Decoder::GetExplicitVersion()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+
+ if (b == (CONTEXT_SPECIFIC | CONSTRUCTED)) { // not an error if not here
+ source_.next();
+ return GetVersion();
+ }
+ else
+ source_.prev(); // put back
+
+ return 0;
+}
+
+
+// Decode a BER encoded RSA Private Key
+void RSA_Private_Decoder::Decode(RSA_PrivateKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+ // public
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetPublicExponent(GetInteger(Integer().Ref()));
+
+ // private
+ key.SetPrivateExponent(GetInteger(Integer().Ref()));
+ key.SetPrime1(GetInteger(Integer().Ref()));
+ key.SetPrime2(GetInteger(Integer().Ref()));
+ key.SetModPrime1PrivateExponent(GetInteger(Integer().Ref()));
+ key.SetModPrime2PrivateExponent(GetInteger(Integer().Ref()));
+ key.SetMultiplicativeInverseOfPrime2ModPrime1(GetInteger(Integer().Ref()));
+}
+
+
+void RSA_Private_Decoder::ReadHeader()
+{
+ GetSequence();
+ GetVersion();
+}
+
+
+// Decode a BER encoded DSA Private Key
+void DSA_Private_Decoder::Decode(DSA_PrivateKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+ // group parameters
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetSubGroupOrder(GetInteger(Integer().Ref()));
+ key.SetSubGroupGenerator(GetInteger(Integer().Ref()));
+
+ // key
+ key.SetPublicPart(GetInteger(Integer().Ref()));
+ key.SetPrivatePart(GetInteger(Integer().Ref()));
+}
+
+
+void DSA_Private_Decoder::ReadHeader()
+{
+ GetSequence();
+ GetVersion();
+}
+
+
+// Decode a BER encoded RSA Public Key
+void RSA_Public_Decoder::Decode(RSA_PublicKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // public key
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetPublicExponent(GetInteger(Integer().Ref()));
+}
+
+
+void RSA_Public_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+// Decode a BER encoded DSA Public Key
+void DSA_Public_Decoder::Decode(DSA_PublicKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // group parameters
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetSubGroupOrder(GetInteger(Integer().Ref()));
+ key.SetSubGroupGenerator(GetInteger(Integer().Ref()));
+
+ // key
+ key.SetPublicPart(GetInteger(Integer().Ref()));
+}
+
+
+void DSA_Public_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+void DH_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+// Decode a BER encoded Diffie-Hellman Key
+void DH_Decoder::Decode(DH& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // group parms
+ key.SetP(GetInteger(Integer().Ref()));
+ key.SetG(GetInteger(Integer().Ref()));
+}
+
+
+CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers)
+ : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0),
+ signature_(0), issuer_(0), subject_(0)
+{
+ if (decode)
+ Decode(signers);
+}
+
+
+CertDecoder::~CertDecoder()
+{
+ tcArrayDelete(subject_);
+ tcArrayDelete(issuer_);
+ tcArrayDelete(signature_);
+}
+
+
+// process certificate header, set signature offset
+void CertDecoder::ReadHeader()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence(); // total
+ certBegin_ = source_.get_index();
+
+ sigIndex_ = GetSequence(); // this cert
+ sigIndex_ += source_.get_index();
+
+ GetExplicitVersion(); // version
+ GetInteger(Integer().Ref()); // serial number
+}
+
+
+// Decode a x509v3 Certificate
+void CertDecoder::Decode(SignerList* signers)
+{
+ if (source_.GetError().What()) return;
+ DecodeToKey();
+ if (source_.GetError().What()) return;
+
+ if (source_.get_index() != sigIndex_)
+ source_.set_index(sigIndex_);
+
+ word32 confirmOID = GetAlgoId();
+ GetSignature();
+ if (source_.GetError().What()) return;
+
+ if ( confirmOID != signatureOID_ ) {
+ source_.SetError(SIG_OID_E);
+ return;
+ }
+
+ if ( memcmp(issuerHash_, subjectHash_, SHA::DIGEST_SIZE) == 0 ) {
+ if (!ValidateSelfSignature())
+ source_.SetError(SIG_CONFIRM_E);
+ }
+ else
+ if (!ValidateSignature(signers))
+ source_.SetError(SIG_OTHER_E);
+}
+
+
+void CertDecoder::DecodeToKey()
+{
+ ReadHeader();
+ signatureOID_ = GetAlgoId();
+ GetName(ISSUER);
+ GetValidity();
+ GetName(SUBJECT);
+ GetKey();
+}
+
+
+// Read public key
+void CertDecoder::GetKey()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence();
+ keyOID_ = GetAlgoId();
+
+ if (keyOID_ == RSAk) {
+ byte b = source_.next();
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return;
+ }
+ b = source_.next(); // length, future
+ b = source_.next();
+ while(b != 0)
+ b = source_.next();
+ }
+ else if (keyOID_ == DSAk)
+ ; // do nothing
+ else {
+ source_.SetError(UNKNOWN_OID_E);
+ return;
+ }
+
+ StoreKey();
+ if (keyOID_ == DSAk)
+ AddDSA();
+}
+
+
+// Save public key
+void CertDecoder::StoreKey()
+{
+ if (source_.GetError().What()) return;
+
+ word32 read = source_.get_index();
+ word32 length = GetSequence();
+
+ read = source_.get_index() - read;
+ length += read;
+
+ while (read--) source_.prev();
+
+ key_.SetSize(length);
+ key_.SetKey(source_.get_current());
+ source_.advance(length);
+}
+
+
+// DSA has public key after group
+void CertDecoder::AddDSA()
+{
+ if (source_.GetError().What()) return;
+
+ byte b = source_.next();
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return;
+ }
+ b = source_.next(); // length, future
+ b = source_.next();
+ while(b != 0)
+ b = source_.next();
+
+ word32 idx = source_.get_index();
+ b = source_.next();
+ if (b != INTEGER) {
+ source_.SetError(INTEGER_E);
+ return;
+ }
+
+ word32 length = GetLength(source_);
+ length += source_.get_index() - idx;
+
+ key_.AddToEnd(source_.get_buffer() + idx, length);
+}
+
+
+// process algo OID by summing, return it
+word32 CertDecoder::GetAlgoId()
+{
+ if (source_.GetError().What()) return 0;
+ word32 length = GetSequence();
+
+ byte b = source_.next();
+ if (b != OBJECT_IDENTIFIER) {
+ source_.SetError(OBJECT_ID_E);
+ return 0;
+ }
+
+ length = GetLength(source_);
+ word32 oid = 0;
+
+ while(length--)
+ oid += source_.next(); // just sum it up for now
+
+ if (oid != SHAwDSA && oid != DSAk) {
+ b = source_.next(); // should have NULL tag and 0
+
+ if (b != TAG_NULL) {
+ source_.SetError(TAG_NULL_E);
+ return 0;
+ }
+
+ b = source_.next();
+ if (b != 0) {
+ source_.SetError(EXPECT_0_E);
+ return 0;
+ }
+ }
+
+ return oid;
+}
+
+
+// read cert signature, store in signature_
+word32 CertDecoder::GetSignature()
+{
+ if (source_.GetError().What()) return 0;
+ byte b = source_.next();
+
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return 0;
+ }
+
+ sigLength_ = GetLength(source_);
+
+ b = source_.next();
+ if (b != 0) {
+ source_.SetError(EXPECT_0_E);
+ return 0;
+ }
+ sigLength_--;
+
+ signature_ = new (tc) byte[sigLength_];
+ memcpy(signature_, source_.get_current(), sigLength_);
+ source_.advance(sigLength_);
+
+ return sigLength_;
+}
+
+
+// read cert digest, store in signature_
+word32 CertDecoder::GetDigest()
+{
+ if (source_.GetError().What()) return 0;
+ byte b = source_.next();
+
+ if (b != OCTET_STRING) {
+ source_.SetError(OCTET_STR_E);
+ return 0;
+ }
+
+ sigLength_ = GetLength(source_);
+
+ signature_ = new (tc) byte[sigLength_];
+ memcpy(signature_, source_.get_current(), sigLength_);
+ source_.advance(sigLength_);
+
+ return sigLength_;
+}
+
+
+// process NAME, either issuer or subject
+void CertDecoder::GetName(NameType nt)
+{
+ if (source_.GetError().What()) return;
+
+ SHA sha;
+ word32 length = GetSequence(); // length of all distinguished names
+ length += source_.get_index();
+
+ while (source_.get_index() < length) {
+ GetSet();
+ GetSequence();
+
+ byte b = source_.next();
+ if (b != OBJECT_IDENTIFIER) {
+ source_.SetError(OBJECT_ID_E);
+ return;
+ }
+
+ word32 oidSz = GetLength(source_);
+ byte joint[2];
+ memcpy(joint, source_.get_current(), sizeof(joint));
+
+ // v1 name types
+ if (joint[0] == 0x55 && joint[1] == 0x04) {
+ source_.advance(2);
+ byte id = source_.next();
+ b = source_.next(); // strType
+ word32 strLen = GetLength(source_);
+
+ if (id == COMMON_NAME) {
+ char*& ptr = (nt == ISSUER) ? issuer_ : subject_;
+ ptr = new (tc) char[strLen + 1];
+ memcpy(ptr, source_.get_current(), strLen);
+ ptr[strLen] = 0;
+ }
+ sha.Update(source_.get_current(), strLen);
+ source_.advance(strLen);
+ }
+ else {
+ // skip
+ source_.advance(oidSz + 1);
+ word32 length = GetLength(source_);
+ source_.advance(length);
+ }
+ }
+ if (nt == ISSUER)
+ sha.Final(issuerHash_);
+ else
+ sha.Final(subjectHash_);
+}
+
+
+// process a Date, either BEFORE or AFTER
+void CertDecoder::GetDate(DateType dt)
+{
+ if (source_.GetError().What()) return;
+
+ byte b = source_.next();
+ if (b != UTC_TIME && b != GENERALIZED_TIME) {
+ source_.SetError(TIME_E);
+ return;
+ }
+
+ word32 length = GetLength(source_);
+ byte date[MAX_DATE_SZ];
+ if (length > MAX_DATE_SZ || length < MIN_DATE_SZ) {
+ source_.SetError(DATE_SZ_E);
+ return;
+ }
+
+ memcpy(date, source_.get_current(), length);
+ source_.advance(length);
+
+ if (!ValidateDate(date, b, dt))
+ if (dt == BEFORE)
+ source_.SetError(BEFORE_DATE_E);
+ else
+ source_.SetError(AFTER_DATE_E);
+}
+
+
+void CertDecoder::GetValidity()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence();
+ GetDate(BEFORE);
+ GetDate(AFTER);
+}
+
+
+bool CertDecoder::ValidateSelfSignature()
+{
+ Source pub(key_.GetKey(), key_.size());
+ return ConfirmSignature(pub);
+}
+
+
+// extract compare signature hash from plain and place into digest
+void CertDecoder::GetCompareHash(const byte* plain, word32 sz, byte* digest,
+ word32 digSz)
+{
+ if (source_.GetError().What()) return;
+
+ Source s(plain, sz);
+ CertDecoder dec(s, false);
+
+ dec.GetSequence();
+ dec.GetAlgoId();
+ dec.GetDigest();
+
+ if (dec.sigLength_ > digSz) {
+ source_.SetError(SIG_LEN_E);
+ return;
+ }
+
+ memcpy(digest, dec.signature_, dec.sigLength_);
+}
+
+
+// validate signature signed by someone else
+bool CertDecoder::ValidateSignature(SignerList* signers)
+{
+ assert(signers);
+
+ SignerList::iterator first = signers->begin();
+ SignerList::iterator last = signers->end();
+
+ while (first != last) {
+ if ( memcmp(issuerHash_, (*first)->GetHash(), SHA::DIGEST_SIZE) == 0) {
+
+ const PublicKey& iKey = (*first)->GetPublicKey();
+ Source pub(iKey.GetKey(), iKey.size());
+ return ConfirmSignature(pub);
+ }
+ ++first;
+ }
+ return false;
+}
+
+
+// RSA confirm
+bool CertDecoder::ConfirmSignature(Source& pub)
+{
+ HashType ht;
+ mySTL::auto_ptr<HASH> hasher(tcDelete);
+
+ if (signatureOID_ == MD5wRSA) {
+ hasher.reset(new (tc) MD5);
+ ht = MD5h;
+ }
+ else if (signatureOID_ == MD2wRSA) {
+ hasher.reset(new (tc) MD2);
+ ht = MD2h;
+ }
+ else if (signatureOID_ == SHAwRSA || signatureOID_ == SHAwDSA) {
+ hasher.reset(new (tc) SHA);
+ ht = SHAh;
+ }
+ else {
+ source_.SetError(UNKOWN_SIG_E);
+ return false;
+ }
+
+ byte digest[SHA::DIGEST_SIZE]; // largest size
+
+ hasher->Update(source_.get_buffer() + certBegin_, sigIndex_ - certBegin_);
+ hasher->Final(digest);
+
+ if (keyOID_ == RSAk) {
+ // put in ASN.1 signature format
+ Source build;
+ Signature_Encoder(digest, hasher->getDigestSize(), ht, build);
+
+ RSA_PublicKey pubKey(pub);
+ RSAES_Encryptor enc(pubKey);
+
+ return enc.SSL_Verify(build.get_buffer(), build.size(), signature_);
+ }
+ else { // DSA
+ // extract r and s from sequence
+ byte seqDecoded[DSA_SIG_SZ];
+ DecodeDSA_Signature(seqDecoded, signature_, sigLength_);
+
+ DSA_PublicKey pubKey(pub);
+ DSA_Verifier ver(pubKey);
+
+ return ver.Verify(digest, seqDecoded);
+ }
+}
+
+
+Signature_Encoder::Signature_Encoder(const byte* dig, word32 digSz,
+ HashType digOID, Source& source)
+{
+ // build bottom up
+
+ // Digest
+ byte digArray[MAX_DIGEST_SZ];
+ word32 digestSz = SetDigest(dig, digSz, digArray);
+
+ // AlgoID
+ byte algoArray[MAX_ALGO_SZ];
+ word32 algoSz = SetAlgoID(digOID, algoArray);
+
+ // Sequence
+ byte seqArray[MAX_SEQ_SZ];
+ word32 seqSz = SetSequence(digestSz + algoSz, seqArray);
+
+ source.grow(seqSz + algoSz + digestSz); // make sure enough room
+ source.add(seqArray, seqSz);
+ source.add(algoArray, algoSz);
+ source.add(digArray, digestSz);
+}
+
+
+
+word32 Signature_Encoder::SetDigest(const byte* d, word32 dSz, byte* output)
+{
+ output[0] = OCTET_STRING;
+ output[1] = dSz;
+ memcpy(&output[2], d, dSz);
+
+ return dSz + 2;
+}
+
+
+
+word32 DER_Encoder::SetAlgoID(HashType aOID, byte* output)
+{
+ // adding TAG_NULL and 0 to end
+ static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00 };
+ static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x05, 0x05, 0x00 };
+ static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x02, 0x05, 0x00};
+
+ int algoSz = 0;
+ const byte* algoName = 0;
+
+ switch (aOID) {
+ case SHAh:
+ algoSz = sizeof(shaAlgoID);
+ algoName = shaAlgoID;
+ break;
+
+ case MD2h:
+ algoSz = sizeof(md2AlgoID);
+ algoName = md2AlgoID;
+ break;
+
+ case MD5h:
+ algoSz = sizeof(md5AlgoID);
+ algoName = md5AlgoID;
+ break;
+
+ default:
+ error_.SetError(UNKOWN_HASH_E);
+ return 0;
+ }
+
+
+ byte ID_Length[MAX_LENGTH_SZ];
+ word32 idSz = SetLength(algoSz - 2, ID_Length); // don't include TAG_NULL/0
+
+ byte seqArray[MAX_SEQ_SZ + 1]; // add object_id to end
+ word32 seqSz = SetSequence(idSz + algoSz + 1, seqArray);
+ seqArray[seqSz++] = OBJECT_IDENTIFIER;
+
+ memcpy(output, seqArray, seqSz);
+ memcpy(output + seqSz, ID_Length, idSz);
+ memcpy(output + seqSz + idSz, algoName, algoSz);
+
+ return seqSz + idSz + algoSz;
+}
+
+
+word32 SetSequence(word32 len, byte* output)
+{
+
+ output[0] = SEQUENCE | CONSTRUCTED;
+ return SetLength(len, output + 1) + 1;
+}
+
+
+word32 EncodeDSA_Signature(const byte* signature, byte* output)
+{
+ Integer r(signature, 20);
+ Integer s(signature + 20, 20);
+
+ return EncodeDSA_Signature(r, s, output);
+}
+
+
+word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output)
+{
+ word32 rSz = r.ByteCount();
+ word32 sSz = s.ByteCount();
+
+ byte rLen[MAX_LENGTH_SZ + 1];
+ byte sLen[MAX_LENGTH_SZ + 1];
+
+ rLen[0] = INTEGER;
+ sLen[0] = INTEGER;
+
+ word32 rLenSz = SetLength(rSz, &rLen[1]) + 1;
+ word32 sLenSz = SetLength(sSz, &sLen[1]) + 1;
+
+ byte seqArray[MAX_SEQ_SZ];
+
+ word32 seqSz = SetSequence(rLenSz + rSz + sLenSz + sSz, seqArray);
+
+ // seq
+ memcpy(output, seqArray, seqSz);
+ // r
+ memcpy(output + seqSz, rLen, rLenSz);
+ r.Encode(output + seqSz + rLenSz, rSz);
+ // s
+ memcpy(output + seqSz + rLenSz + rSz, sLen, sLenSz);
+ s.Encode(output + seqSz + rLenSz + rSz + sLenSz, sSz);
+
+ return seqSz + rLenSz + rSz + sLenSz + sSz;
+}
+
+
+// put sequence encoded dsa signature into decoded in 2 20 byte integers
+word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz)
+{
+ Source source(encoded, sz);
+
+ if (source.next() != (SEQUENCE | CONSTRUCTED)) {
+ source.SetError(SEQUENCE_E);
+ return 0;
+ }
+
+ GetLength(source); // total
+
+ // r
+ if (source.next() != INTEGER) {
+ source.SetError(INTEGER_E);
+ return 0;
+ }
+ word32 rLen = GetLength(source);
+ if (rLen != 20)
+ if (rLen == 21) { // zero at front, eat
+ source.next();
+ --rLen;
+ }
+ else if (rLen == 19) { // add zero to front so 20 bytes
+ decoded[0] = 0;
+ decoded++;
+ }
+ else {
+ source.SetError(DSA_SZ_E);
+ return 0;
+ }
+ memcpy(decoded, source.get_buffer() + source.get_index(), rLen);
+ source.advance(rLen);
+
+ // s
+ if (source.next() != INTEGER) {
+ source.SetError(INTEGER_E);
+ return 0;
+ }
+ word32 sLen = GetLength(source);
+ if (sLen != 20)
+ if (sLen == 21) {
+ source.next(); // zero at front, eat
+ --sLen;
+ }
+ else if (sLen == 19) {
+ decoded[rLen] = 0; // add zero to front so 20 bytes
+ decoded++;
+ }
+ else {
+ source.SetError(DSA_SZ_E);
+ return 0;
+ }
+ memcpy(decoded + rLen, source.get_buffer() + source.get_index(), sLen);
+ source.advance(sLen);
+
+ return 40;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp
new file mode 100644
index 00000000000..944a47c288e
--- /dev/null
+++ b/extra/yassl/taocrypt/src/coding.cpp
@@ -0,0 +1,250 @@
+/* coding.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* coding.cpp implements hex and base64 encoding/decoing
+*/
+
+#include "runtime.hpp"
+#include "coding.hpp"
+#include "file.hpp"
+
+
+namespace TaoCrypt {
+
+
+namespace { // locals
+
+const byte bad = 0xFF; // invalid encoding
+
+const byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ bad, bad, bad, bad, bad, bad, bad,
+ 10, 11, 12, 13, 14, 15
+ }; // A starts at 0x41 not 0x3A
+
+
+const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '+', '/'
+ };
+
+const byte base64Decode[] = { 62, bad, bad, bad, 63, // + starts at 0x2B
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ bad, bad, bad, bad, bad, bad, bad,
+ 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,
+ bad, bad, bad, bad, bad, bad,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51
+ };
+
+const byte pad = '=';
+const int pemLineSz = 64;
+
+} // local namespace
+
+
+// Hex Encode
+void HexEncoder::Encode()
+{
+ word32 bytes = plain_.size();
+ encoded_.New(bytes * 2);
+
+ word32 i = 0;
+
+ while (bytes--) {
+ byte p = plain_.next();
+
+ byte b = p >> 4;
+ byte b2 = p & 0xF;
+
+ encoded_[i++] = hexEncode[b];
+ encoded_[i++] = hexEncode[b2];
+ }
+
+ plain_.reset(encoded_);
+}
+
+
+// Hex Decode
+void HexDecoder::Decode()
+{
+ word32 bytes = coded_.size();
+ assert((bytes % 2) == 0);
+ decoded_.New(bytes / 2);
+
+ word32 i(0);
+
+ while (bytes) {
+ byte b = coded_.next() - 0x30; // 0 starts at 0x30
+ byte b2 = coded_.next() - 0x30;
+
+ // sanity checks
+ assert( b < sizeof(hexDecode)/sizeof(hexDecode[0]) );
+ assert( b2 < sizeof(hexDecode)/sizeof(hexDecode[0]) );
+ assert( b != bad && b2 != bad );
+
+ b = hexDecode[b];
+ b2 = hexDecode[b2];
+
+ decoded_[i++] = (b << 4) | b2;
+ bytes -= 2;
+ }
+
+ coded_.reset(decoded_);
+}
+
+
+// Base 64 Encode
+void Base64Encoder::Encode()
+{
+ word32 bytes = plain_.size();
+ word32 outSz = bytes * 4 / 3;
+ outSz += (outSz % 4); // 4 byte integrals
+
+ outSz += outSz / pemLineSz + ( (outSz % pemLineSz) ? 1 : 0); // new lines
+ encoded_.New(outSz);
+
+ word32 i = 0;
+ word32 j = 0;
+
+ while (bytes > 2) {
+ byte b1 = plain_.next();
+ byte b2 = plain_.next();
+ byte b3 = plain_.next();
+
+ // encoded idx
+ byte e1 = b1 >> 2;
+ byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
+ byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
+ byte e4 = b3 & 0x3F;
+
+ // store
+ encoded_[i++] = base64Encode[e1];
+ encoded_[i++] = base64Encode[e2];
+ encoded_[i++] = base64Encode[e3];
+ encoded_[i++] = base64Encode[e4];
+
+ bytes -= 3;
+
+ if ((++j % 16) == 0)
+ encoded_[i++] = '\n';
+ }
+
+ // last integral
+ if (bytes) {
+ bool twoBytes = (bytes == 2);
+
+ byte b1 = plain_.next();
+ byte b2 = (twoBytes) ? plain_.next() : 0;
+
+ byte e1 = b1 >> 2;
+ byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
+ byte e3 = (b2 & 0xF) << 2;
+
+ encoded_[i++] = base64Encode[e1];
+ encoded_[i++] = base64Encode[e2];
+ encoded_[i++] = (twoBytes) ? base64Encode[e3] : pad;
+ encoded_[i++] = pad;
+ }
+
+ encoded_[i++] = '\n';
+ assert(i == outSz);
+
+ plain_.reset(encoded_);
+}
+
+
+// Base 64 Decode
+void Base64Decoder::Decode()
+{
+ word32 bytes = coded_.size();
+ word32 plainSz = bytes - (bytes / pemLineSz + ( (bytes % pemLineSz) ?
+ 1 : 0));
+ plainSz = plainSz * 3 / 4 + (( (plainSz * 3) % 4) ? 1 : 0);
+ decoded_.New(plainSz);
+
+ word32 i = 0;
+ word32 j = 0;
+
+ while (bytes > 3) {
+ byte e1 = coded_.next();
+ byte e2 = coded_.next();
+ byte e3 = coded_.next();
+ byte e4 = coded_.next();
+
+ // do asserts first
+ if (e1 == 0) // end file 0's
+ break;
+
+ bool pad3 = false;
+ bool pad4 = false;
+ if (e3 == pad)
+ pad3 = true;
+ if (e4 == pad)
+ pad4 = true;
+
+ e1 = base64Decode[e1 - 0x2B];
+ e2 = base64Decode[e2 - 0x2B];
+ e3 = (e3 == pad) ? 0 : base64Decode[e3 - 0x2B];
+ e4 = (e4 == pad) ? 0 : base64Decode[e4 - 0x2B];
+
+ byte b1 = (e1 << 2) | (e2 >> 4);
+ byte b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
+ byte b3 = ((e3 & 0x3) << 6) | e4;
+
+ decoded_[i++] = b1;
+ if (!pad3)
+ decoded_[i++] = b2;
+ if (!pad4)
+ decoded_[i++] = b3;
+ else
+ break;
+
+ bytes -= 4;
+ if ((++j % 16) == 0) {
+ byte endLine = coded_.next();
+ bytes--;
+ if (endLine == '\r') {
+ endLine = coded_.next();
+ bytes--;
+ }
+ assert(endLine == '\n');
+ }
+ }
+
+ if (i != decoded_.size())
+ decoded_.resize(i);
+ coded_.reset(decoded_);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/des.cpp b/extra/yassl/taocrypt/src/des.cpp
new file mode 100644
index 00000000000..e5d3331500c
--- /dev/null
+++ b/extra/yassl/taocrypt/src/des.cpp
@@ -0,0 +1,435 @@
+/* des.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's des.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "des.hpp"
+#include <string.h>
+#include "algorithm.hpp" // mySTL::swap
+
+
+namespace TaoCrypt {
+
+
+/* permuted choice table (key) */
+static const byte pc1[] = {
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4
+};
+
+/* number left rotations of pc1 */
+static const byte totrot[] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
+};
+
+/* permuted choice key (table) */
+static const byte pc2[] = {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+};
+
+/* End of DES-defined tables */
+
+/* bit 0 is left-most in byte */
+static const int bytebit[] = {
+ 0200,0100,040,020,010,04,02,01
+};
+
+
+void DES::SetKey(const byte* key, word32 /*length*/, CipherDir dir)
+{
+ byte buffer[56+56+8];
+ byte *const pc1m = buffer; /* place to modify pc1 into */
+ byte *const pcr = pc1m + 56; /* place to rotate pc1 into */
+ byte *const ks = pcr + 56;
+ register int i,j,l;
+ int m;
+
+ for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */
+ l = pc1[j] - 1; /* integer bit location */
+ m = l & 07; /* find bit */
+ pc1m[j] = (key[l >> 3] & /* find which key byte l is in */
+ bytebit[m]) /* and which bit of that byte */
+ ? 1 : 0; /* and store 1-bit result */
+ }
+ for (i = 0; i < 16; i++) { /* key chunk for each iteration */
+ memset(ks, 0, 8); /* Clear key schedule */
+ for (j = 0; j < 56; j++) /* rotate pc1 the right amount */
+ pcr[j] = pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l: l-28];
+ /* rotate left and right halves independently */
+ for (j = 0; j < 48; j++){ /* select bits individually */
+ /* check bit that goes to ks[j] */
+ if (pcr[pc2[j] - 1]){
+ /* mask it in if it's there */
+ l= j % 6;
+ ks[j/6] |= bytebit[l] >> 2;
+ }
+ }
+ /* Now convert to odd/even interleaved form for use in F */
+ k_[2*i] = ((word32)ks[0] << 24)
+ | ((word32)ks[2] << 16)
+ | ((word32)ks[4] << 8)
+ | ((word32)ks[6]);
+ k_[2*i + 1] = ((word32)ks[1] << 24)
+ | ((word32)ks[3] << 16)
+ | ((word32)ks[5] << 8)
+ | ((word32)ks[7]);
+ }
+
+ // reverse key schedule order
+ if (dir == DECRYPTION)
+ for (i = 0; i < 16; i += 2) {
+ mySTL::swap(k_[i], k_[32 - 2 - i]);
+ mySTL::swap(k_[i+1], k_[32 - 1 - i]);
+ }
+
+}
+
+static inline void IPERM(word32& left, word32& right)
+{
+ word32 work;
+
+ right = rotlFixed(right, 4U);
+ work = (left ^ right) & 0xf0f0f0f0;
+ left ^= work;
+ right = rotrFixed(right^work, 20U);
+ work = (left ^ right) & 0xffff0000;
+ left ^= work;
+ right = rotrFixed(right^work, 18U);
+ work = (left ^ right) & 0x33333333;
+ left ^= work;
+ right = rotrFixed(right^work, 6U);
+ work = (left ^ right) & 0x00ff00ff;
+ left ^= work;
+ right = rotlFixed(right^work, 9U);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left = rotlFixed(left^work, 1U);
+ right ^= work;
+}
+
+static inline void FPERM(word32& left, word32& right)
+{
+ word32 work;
+
+ right = rotrFixed(right, 1U);
+ work = (left ^ right) & 0xaaaaaaaa;
+ right ^= work;
+ left = rotrFixed(left^work, 9U);
+ work = (left ^ right) & 0x00ff00ff;
+ right ^= work;
+ left = rotlFixed(left^work, 6U);
+ work = (left ^ right) & 0x33333333;
+ right ^= work;
+ left = rotlFixed(left^work, 18U);
+ work = (left ^ right) & 0xffff0000;
+ right ^= work;
+ left = rotlFixed(left^work, 20U);
+ work = (left ^ right) & 0xf0f0f0f0;
+ right ^= work;
+ left = rotrFixed(left^work, 4U);
+}
+
+const word32 Spbox[DES::BOXES][DES::BOX_SIZE] = {
+{
+0x01010400,0x00000000,0x00010000,0x01010404,
+0x01010004,0x00010404,0x00000004,0x00010000,
+0x00000400,0x01010400,0x01010404,0x00000400,
+0x01000404,0x01010004,0x01000000,0x00000004,
+0x00000404,0x01000400,0x01000400,0x00010400,
+0x00010400,0x01010000,0x01010000,0x01000404,
+0x00010004,0x01000004,0x01000004,0x00010004,
+0x00000000,0x00000404,0x00010404,0x01000000,
+0x00010000,0x01010404,0x00000004,0x01010000,
+0x01010400,0x01000000,0x01000000,0x00000400,
+0x01010004,0x00010000,0x00010400,0x01000004,
+0x00000400,0x00000004,0x01000404,0x00010404,
+0x01010404,0x00010004,0x01010000,0x01000404,
+0x01000004,0x00000404,0x00010404,0x01010400,
+0x00000404,0x01000400,0x01000400,0x00000000,
+0x00010004,0x00010400,0x00000000,0x01010004},
+{
+0x80108020,0x80008000,0x00008000,0x00108020,
+0x00100000,0x00000020,0x80100020,0x80008020,
+0x80000020,0x80108020,0x80108000,0x80000000,
+0x80008000,0x00100000,0x00000020,0x80100020,
+0x00108000,0x00100020,0x80008020,0x00000000,
+0x80000000,0x00008000,0x00108020,0x80100000,
+0x00100020,0x80000020,0x00000000,0x00108000,
+0x00008020,0x80108000,0x80100000,0x00008020,
+0x00000000,0x00108020,0x80100020,0x00100000,
+0x80008020,0x80100000,0x80108000,0x00008000,
+0x80100000,0x80008000,0x00000020,0x80108020,
+0x00108020,0x00000020,0x00008000,0x80000000,
+0x00008020,0x80108000,0x00100000,0x80000020,
+0x00100020,0x80008020,0x80000020,0x00100020,
+0x00108000,0x00000000,0x80008000,0x00008020,
+0x80000000,0x80100020,0x80108020,0x00108000},
+{
+0x00000208,0x08020200,0x00000000,0x08020008,
+0x08000200,0x00000000,0x00020208,0x08000200,
+0x00020008,0x08000008,0x08000008,0x00020000,
+0x08020208,0x00020008,0x08020000,0x00000208,
+0x08000000,0x00000008,0x08020200,0x00000200,
+0x00020200,0x08020000,0x08020008,0x00020208,
+0x08000208,0x00020200,0x00020000,0x08000208,
+0x00000008,0x08020208,0x00000200,0x08000000,
+0x08020200,0x08000000,0x00020008,0x00000208,
+0x00020000,0x08020200,0x08000200,0x00000000,
+0x00000200,0x00020008,0x08020208,0x08000200,
+0x08000008,0x00000200,0x00000000,0x08020008,
+0x08000208,0x00020000,0x08000000,0x08020208,
+0x00000008,0x00020208,0x00020200,0x08000008,
+0x08020000,0x08000208,0x00000208,0x08020000,
+0x00020208,0x00000008,0x08020008,0x00020200},
+{
+0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802080,0x00800081,0x00800001,0x00002001,
+0x00000000,0x00802000,0x00802000,0x00802081,
+0x00000081,0x00000000,0x00800080,0x00800001,
+0x00000001,0x00002000,0x00800000,0x00802001,
+0x00000080,0x00800000,0x00002001,0x00002080,
+0x00800081,0x00000001,0x00002080,0x00800080,
+0x00002000,0x00802080,0x00802081,0x00000081,
+0x00800080,0x00800001,0x00802000,0x00802081,
+0x00000081,0x00000000,0x00000000,0x00802000,
+0x00002080,0x00800080,0x00800081,0x00000001,
+0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802081,0x00000081,0x00000001,0x00002000,
+0x00800001,0x00002001,0x00802080,0x00800081,
+0x00002001,0x00002080,0x00800000,0x00802001,
+0x00000080,0x00800000,0x00002000,0x00802080},
+{
+0x00000100,0x02080100,0x02080000,0x42000100,
+0x00080000,0x00000100,0x40000000,0x02080000,
+0x40080100,0x00080000,0x02000100,0x40080100,
+0x42000100,0x42080000,0x00080100,0x40000000,
+0x02000000,0x40080000,0x40080000,0x00000000,
+0x40000100,0x42080100,0x42080100,0x02000100,
+0x42080000,0x40000100,0x00000000,0x42000000,
+0x02080100,0x02000000,0x42000000,0x00080100,
+0x00080000,0x42000100,0x00000100,0x02000000,
+0x40000000,0x02080000,0x42000100,0x40080100,
+0x02000100,0x40000000,0x42080000,0x02080100,
+0x40080100,0x00000100,0x02000000,0x42080000,
+0x42080100,0x00080100,0x42000000,0x42080100,
+0x02080000,0x00000000,0x40080000,0x42000000,
+0x00080100,0x02000100,0x40000100,0x00080000,
+0x00000000,0x40080000,0x02080100,0x40000100},
+{
+0x20000010,0x20400000,0x00004000,0x20404010,
+0x20400000,0x00000010,0x20404010,0x00400000,
+0x20004000,0x00404010,0x00400000,0x20000010,
+0x00400010,0x20004000,0x20000000,0x00004010,
+0x00000000,0x00400010,0x20004010,0x00004000,
+0x00404000,0x20004010,0x00000010,0x20400010,
+0x20400010,0x00000000,0x00404010,0x20404000,
+0x00004010,0x00404000,0x20404000,0x20000000,
+0x20004000,0x00000010,0x20400010,0x00404000,
+0x20404010,0x00400000,0x00004010,0x20000010,
+0x00400000,0x20004000,0x20000000,0x00004010,
+0x20000010,0x20404010,0x00404000,0x20400000,
+0x00404010,0x20404000,0x00000000,0x20400010,
+0x00000010,0x00004000,0x20400000,0x00404010,
+0x00004000,0x00400010,0x20004010,0x00000000,
+0x20404000,0x20000000,0x00400010,0x20004010},
+{
+0x00200000,0x04200002,0x04000802,0x00000000,
+0x00000800,0x04000802,0x00200802,0x04200800,
+0x04200802,0x00200000,0x00000000,0x04000002,
+0x00000002,0x04000000,0x04200002,0x00000802,
+0x04000800,0x00200802,0x00200002,0x04000800,
+0x04000002,0x04200000,0x04200800,0x00200002,
+0x04200000,0x00000800,0x00000802,0x04200802,
+0x00200800,0x00000002,0x04000000,0x00200800,
+0x04000000,0x00200800,0x00200000,0x04000802,
+0x04000802,0x04200002,0x04200002,0x00000002,
+0x00200002,0x04000000,0x04000800,0x00200000,
+0x04200800,0x00000802,0x00200802,0x04200800,
+0x00000802,0x04000002,0x04200802,0x04200000,
+0x00200800,0x00000000,0x00000002,0x04200802,
+0x00000000,0x00200802,0x04200000,0x00000800,
+0x04000002,0x04000800,0x00000800,0x00200002},
+{
+0x10001040,0x00001000,0x00040000,0x10041040,
+0x10000000,0x10001040,0x00000040,0x10000000,
+0x00040040,0x10040000,0x10041040,0x00041000,
+0x10041000,0x00041040,0x00001000,0x00000040,
+0x10040000,0x10000040,0x10001000,0x00001040,
+0x00041000,0x00040040,0x10040040,0x10041000,
+0x00001040,0x00000000,0x00000000,0x10040040,
+0x10000040,0x10001000,0x00041040,0x00040000,
+0x00041040,0x00040000,0x10041000,0x00001000,
+0x00000040,0x10040040,0x00001000,0x00041040,
+0x10001000,0x00000040,0x10000040,0x10040000,
+0x10040040,0x10000000,0x00040000,0x10001040,
+0x00000000,0x10041040,0x00040040,0x10000040,
+0x10040000,0x10001000,0x10001040,0x00000000,
+0x10041040,0x00041000,0x00041000,0x00001040,
+0x00001040,0x00040040,0x10000000,0x10041000}
+};
+
+
+
+void DES::RawProcessBlock(word32& lIn, word32& rIn) const
+{
+ word32 l = lIn, r = rIn;
+ const word32* kptr = k_;
+
+ for (unsigned i=0; i<8; i++)
+ {
+ word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ kptr[4*i+1];
+ l ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ kptr[4*i+3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+ }
+
+ lIn = l; rIn = r;
+}
+
+
+void DES_BASE::Process(byte* out, const byte* in, word32 sz)
+{
+ if (mode_ == ECB)
+ ECB_Process(out, in, sz);
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ CBC_Encrypt(out, in, sz);
+ else
+ CBC_Decrypt(out, in, sz);
+}
+
+
+
+typedef BlockGetAndPut<word32, BigEndian> Block;
+
+
+void DES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+
+ const word32* kptr = k_;
+
+ for (unsigned i = 0; i < 8; i++)
+ {
+ word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ kptr[4*i+1];
+ l ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ kptr[4*i+3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+ }
+
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+void DES_EDE2::SetKey(const byte* key, word32 sz, CipherDir dir)
+{
+ des1_.SetKey(key, sz, dir);
+ des2_.SetKey(key + 8, sz, ReverseDir(dir));
+}
+
+
+void DES_EDE2::ProcessAndXorBlock(const byte* in, const byte* xOr,
+ byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+ des1_.RawProcessBlock(l, r);
+ des2_.RawProcessBlock(r, l);
+ des1_.RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+void DES_EDE3::SetKey(const byte* key, word32 sz, CipherDir dir)
+{
+ des1_.SetKey(key+(dir==ENCRYPTION?0:2*8), sz, dir);
+ des2_.SetKey(key+8, sz, ReverseDir(dir));
+ des3_.SetKey(key+(dir==DECRYPTION?0:2*8), sz, dir);
+}
+
+void DES_EDE3::ProcessAndXorBlock(const byte* in, const byte* xOr,
+ byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+ des1_.RawProcessBlock(l, r);
+ des2_.RawProcessBlock(r, l);
+ des3_.RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/dh.cpp b/extra/yassl/taocrypt/src/dh.cpp
new file mode 100644
index 00000000000..ea1b5846f7d
--- /dev/null
+++ b/extra/yassl/taocrypt/src/dh.cpp
@@ -0,0 +1,84 @@
+/* dh.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* dh.cpp implements Diffie-Hellman support
+*/
+
+#include "runtime.hpp"
+#include "dh.hpp"
+#include "asn.hpp"
+
+namespace TaoCrypt {
+
+
+// Generate a DH Key Pair
+void DH::GenerateKeyPair(RandomNumberGenerator& rng, byte* priv, byte* pub)
+{
+ GeneratePrivate(rng, priv);
+ GeneratePublic(priv, pub);
+}
+
+
+// Generate private value
+void DH::GeneratePrivate(RandomNumberGenerator& rng, byte* priv)
+{
+ Integer x(rng, Integer::One(), p_ - 1);
+ x.Encode(priv, p_.ByteCount());
+}
+
+
+// Generate public value
+void DH::GeneratePublic(const byte* priv, byte* pub)
+{
+ const word32 bc(p_.ByteCount());
+ Integer x(priv, bc);
+ Integer y(a_exp_b_mod_c(g_, x, p_));
+ y.Encode(pub, bc);
+}
+
+
+// Generate Agreement
+void DH::Agree(byte* agree, const byte* priv, const byte* otherPub)
+{
+ const word32 bc(p_.ByteCount());
+ Integer x(priv, bc);
+ Integer y(otherPub, bc);
+
+ Integer z(a_exp_b_mod_c(y, x, p_));
+ z.Encode(agree, bc);
+}
+
+
+DH::DH(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DH::Initialize(Source& source)
+{
+ DH_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/dsa.cpp b/extra/yassl/taocrypt/src/dsa.cpp
new file mode 100644
index 00000000000..4574fe5ebd8
--- /dev/null
+++ b/extra/yassl/taocrypt/src/dsa.cpp
@@ -0,0 +1,274 @@
+/* dsa.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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 "runtime.hpp"
+#include "dsa.hpp"
+#include "sha.hpp"
+#include "asn.hpp"
+#include "modarith.hpp"
+
+
+namespace TaoCrypt {
+
+
+void DSA_PublicKey::Swap(DSA_PublicKey& other)
+{
+ p_.Swap(other.p_);
+ q_.Swap(other.q_);
+ g_.Swap(other.g_);
+ y_.Swap(other.y_);
+}
+
+
+DSA_PublicKey::DSA_PublicKey(const DSA_PublicKey& other)
+ : p_(other.p_), q_(other.q_), g_(other.g_), y_(other.y_)
+{}
+
+
+DSA_PublicKey& DSA_PublicKey::operator=(const DSA_PublicKey& that)
+{
+ DSA_PublicKey tmp(that);
+ Swap(tmp);
+ return *this;
+}
+
+
+DSA_PublicKey::DSA_PublicKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DSA_PublicKey::Initialize(Source& source)
+{
+ DSA_Public_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void DSA_PublicKey::Initialize(const Integer& p, const Integer& q,
+ const Integer& g, const Integer& y)
+{
+ p_ = p;
+ q_ = q;
+ g_ = g;
+ y_ = y;
+}
+
+
+const Integer& DSA_PublicKey::GetModulus() const
+{
+ return p_;
+}
+
+const Integer& DSA_PublicKey::GetSubGroupOrder() const
+{
+ return q_;
+}
+
+
+const Integer& DSA_PublicKey::GetSubGroupGenerator() const
+{
+ return g_;
+}
+
+
+const Integer& DSA_PublicKey::GetPublicPart() const
+{
+ return y_;
+}
+
+
+void DSA_PublicKey::SetModulus(const Integer& p)
+{
+ p_ = p;
+}
+
+
+void DSA_PublicKey::SetSubGroupOrder(const Integer& q)
+{
+ q_ = q;
+}
+
+
+void DSA_PublicKey::SetSubGroupGenerator(const Integer& g)
+{
+ g_ = g;
+}
+
+
+void DSA_PublicKey::SetPublicPart(const Integer& y)
+{
+ y_ = y;
+}
+
+
+word32 DSA_PublicKey::SignatureLength() const
+{
+ return GetSubGroupOrder().ByteCount() * 2; // r and s
+}
+
+
+
+DSA_PrivateKey::DSA_PrivateKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DSA_PrivateKey::Initialize(Source& source)
+{
+ DSA_Private_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void DSA_PrivateKey::Initialize(const Integer& p, const Integer& q,
+ const Integer& g, const Integer& y,
+ const Integer& x)
+{
+ DSA_PublicKey::Initialize(p, q, g, y);
+ x_ = x;
+}
+
+
+const Integer& DSA_PrivateKey::GetPrivatePart() const
+{
+ return x_;
+}
+
+
+void DSA_PrivateKey::SetPrivatePart(const Integer& x)
+{
+ x_ = x;
+}
+
+
+DSA_Signer::DSA_Signer(const DSA_PrivateKey& key)
+ : key_(key)
+{}
+
+
+word32 DSA_Signer::Sign(const byte* sha_digest, byte* sig,
+ RandomNumberGenerator& rng)
+{
+ const Integer& p = key_.GetModulus();
+ const Integer& q = key_.GetSubGroupOrder();
+ const Integer& g = key_.GetSubGroupGenerator();
+ const Integer& x = key_.GetPrivatePart();
+
+ Integer k(rng, 1, q - 1);
+
+ r_ = a_exp_b_mod_c(g, k, p);
+ r_ %= q;
+
+ Integer H(sha_digest, SHA::DIGEST_SIZE); // sha Hash(m)
+
+ Integer kInv = k.InverseMod(q);
+ s_ = (kInv * (H + x*r_)) % q;
+
+ assert(!!r_ && !!s_);
+
+ int rSz = r_.ByteCount();
+
+ if (rSz == 19) {
+ sig[0] = 0;
+ sig++;
+ }
+
+ r_.Encode(sig, rSz);
+
+ int sSz = s_.ByteCount();
+
+ if (sSz == 19) {
+ sig[rSz] = 0;
+ sig++;
+ }
+
+ s_.Encode(sig + rSz, sSz);
+
+ return 40;
+}
+
+
+DSA_Verifier::DSA_Verifier(const DSA_PublicKey& key)
+ : key_(key)
+{}
+
+
+bool DSA_Verifier::Verify(const byte* sha_digest, const byte* sig)
+{
+ const Integer& p = key_.GetModulus();
+ const Integer& q = key_.GetSubGroupOrder();
+ const Integer& g = key_.GetSubGroupGenerator();
+ const Integer& y = key_.GetPublicPart();
+
+ int sz = q.ByteCount();
+
+ r_.Decode(sig, sz);
+ s_.Decode(sig + sz, sz);
+
+ if (r_ >= q || r_ < 1 || s_ >= q || s_ < 1)
+ return false;
+
+ Integer H(sha_digest, SHA::DIGEST_SIZE); // sha Hash(m)
+
+ Integer w = s_.InverseMod(q);
+ Integer u1 = (H * w) % q;
+ Integer u2 = (r_ * w) % q;
+
+ // verify r == ((g^u1 * y^u2) mod p) mod q
+ ModularArithmetic ma(p);
+ Integer v = ma.CascadeExponentiate(g, u1, y, u2);
+ v %= q;
+
+ return r_ == v;
+}
+
+
+
+
+const Integer& DSA_Signer::GetR() const
+{
+ return r_;
+}
+
+
+const Integer& DSA_Signer::GetS() const
+{
+ return s_;
+}
+
+
+const Integer& DSA_Verifier::GetR() const
+{
+ return r_;
+}
+
+
+const Integer& DSA_Verifier::GetS() const
+{
+ return s_;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/file.cpp b/extra/yassl/taocrypt/src/file.cpp
new file mode 100644
index 00000000000..4d48b9e7bca
--- /dev/null
+++ b/extra/yassl/taocrypt/src/file.cpp
@@ -0,0 +1,118 @@
+/* file.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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.cpp implements File Sources and Sinks
+*/
+
+#include "runtime.hpp"
+#include "file.hpp"
+
+
+namespace TaoCrypt {
+
+
+FileSource::FileSource(const char* fname, Source& source)
+{
+ file_ = fopen(fname, "rb");
+ if (file_) get(source);
+}
+
+
+FileSource::~FileSource()
+{
+ if (file_)
+ fclose(file_);
+}
+
+
+
+// return size of source from beginning or current position
+word32 FileSource::size(bool use_current)
+{
+ long current = ftell(file_);
+ long begin = current;
+
+ if (!use_current) {
+ fseek(file_, 0, SEEK_SET);
+ begin = ftell(file_);
+ }
+
+ fseek(file_, 0, SEEK_END);
+ long end = ftell(file_);
+
+ fseek(file_, current, SEEK_SET);
+
+ return end - begin;
+}
+
+
+word32 FileSource::size_left()
+{
+ return size(true);
+}
+
+
+// fill file source from source
+word32 FileSource::get(Source& source)
+{
+ word32 sz(size());
+ if (source.size() < sz)
+ source.grow(sz);
+
+ size_t bytes = fread(source.buffer_.get_buffer(), 1, sz, file_);
+
+ if (bytes == 1)
+ return sz;
+ else
+ return 0;
+}
+
+
+FileSink::FileSink(const char* fname, Source& source)
+{
+ file_ = fopen(fname, "wb");
+ if (file_) put(source);
+}
+
+
+FileSink::~FileSink()
+{
+ if (file_)
+ fclose(file_);
+}
+
+
+// fill source from file sink
+void FileSink::put(Source& source)
+{
+ fwrite(source.get_buffer(), 1, source.size(), file_);
+}
+
+
+// swap with other and reset to beginning
+void Source::reset(ByteBlock& otherBlock)
+{
+ buffer_.Swap(otherBlock);
+ current_ = 0;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/hash.cpp b/extra/yassl/taocrypt/src/hash.cpp
new file mode 100644
index 00000000000..53b1b489b14
--- /dev/null
+++ b/extra/yassl/taocrypt/src/hash.cpp
@@ -0,0 +1,99 @@
+/* hash.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* hash.cpp implements a base for digest types
+*/
+
+#include "runtime.hpp"
+#include <string.h>
+#include <assert.h>
+
+#include "hash.hpp"
+
+
+namespace TaoCrypt {
+
+
+HASHwithTransform::HASHwithTransform(word32 digSz, word32 buffSz)
+{
+ assert(digSz <= MaxDigestSz);
+ assert(buffSz <= MaxBufferSz);
+}
+
+
+// Update digest with data of size len, do in blocks
+void HASHwithTransform::Update(const byte* data, word32 len)
+{
+ // do block size increments
+ word32 blockSz = getBlockSize();
+ byte* local = reinterpret_cast<byte*>(buffer_);
+
+ while (len) {
+ word32 add = min(len, blockSz - buffLen_);
+ memcpy(&local[buffLen_], data, add);
+
+ buffLen_ += add;
+ data += add;
+ len -= add;
+
+ if (buffLen_ == blockSz) {
+ ByteReverseIf(local, local, blockSz, getByteOrder());
+ Transform();
+ }
+ }
+}
+
+
+// Final process, place digest in hash
+void HASHwithTransform::Final(byte* hash)
+{
+ word32 blockSz = getBlockSize();
+ word32 digestSz = getDigestSize();
+ word32 padSz = getPadSize();
+ ByteOrder order = getByteOrder();
+ word32 prePadLen = length_ + buffLen_ * 8; // in bits
+ byte* local = reinterpret_cast<byte*>(buffer_);
+
+ local[buffLen_++] = 0x80; // add 1
+
+ // pad with zeros
+ if (buffLen_ > padSz) {
+ while (buffLen_ < blockSz) local[buffLen_++] = 0;
+ ByteReverseIf(local, local, blockSz, order);
+ Transform();
+ }
+ while (buffLen_ < padSz) local[buffLen_++] = 0;
+
+ ByteReverseIf(local, local, blockSz, order);
+
+ word32 hiSize = 0; // for future 64 bit length TODO:
+ memcpy(&local[padSz], order ? &hiSize : &prePadLen, sizeof(prePadLen));
+ memcpy(&local[padSz+4], order ? &prePadLen : &hiSize, sizeof(prePadLen));
+
+
+ Transform();
+ ByteReverseIf(digest_, digest_, digestSz, order);
+ memcpy(hash, digest_, digestSz);
+
+ Init(); // reset state
+}
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp
new file mode 100644
index 00000000000..71324b04b92
--- /dev/null
+++ b/extra/yassl/taocrypt/src/integer.cpp
@@ -0,0 +1,3971 @@
+/* integer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+
+/* based on Wei Dai's integer.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "integer.hpp"
+#include "modarith.hpp"
+#include "asn.hpp"
+
+
+
+#ifdef __DECCXX
+ #include <c_asm.h> // for asm overflow assembly
+#endif
+
+
+// 64bit multiply overflow intrinsic
+#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && \
+ !defined(TAOCRYPT_NATIVE_DWORD_AVAILABLE)
+ #ifdef __ia64__
+ #define myUMULH __UMULH
+ #elif __x86_64__
+ #define myUMULH __umulh
+ #else
+ #error unknown 64bit windows
+ #endif
+
+extern "C" word myUMULH(word, word);
+
+#pragma intrinsic (myUMULH)
+#endif
+
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ #ifdef __GNUC__
+ #include <xmmintrin.h>
+ #include <signal.h>
+ #include <setjmp.h>
+ #ifdef TAOCRYPT_MEMALIGN_AVAILABLE
+ #include <malloc.h>
+ #else
+ #include <stdlib.h>
+ #endif
+ #else
+ #include <emmintrin.h>
+ #endif
+#elif defined(_MSC_VER) && defined(_M_IX86)
+ #pragma message("You do not seem to have the Visual C++ Processor Pack ")
+ #pragma message("installed, so use of SSE2 intrinsics will be disabled.")
+#elif defined(__GNUC__) && defined(__i386__)
+/* #warning You do not have GCC 3.3 or later, or did not specify the -msse2 \
+ compiler option. Use of SSE2 intrinsics will be disabled.
+*/
+#endif
+
+
+namespace TaoCrypt {
+
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+
+template <class T>
+CPP_TYPENAME AllocatorBase<T>::pointer AlignedAllocator<T>::allocate(
+ size_type n, const void *)
+{
+ CheckSize(n);
+ if (n == 0)
+ return 0;
+ if (n >= 4)
+ {
+ void* p;
+ #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE
+ p = _mm_malloc(sizeof(T)*n, 16);
+ #elif defined(TAOCRYPT_MEMALIGN_AVAILABLE)
+ p = memalign(16, sizeof(T)*n);
+ #elif defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16)
+ p = malloc(sizeof(T)*n);
+ #else
+ p = (byte *)malloc(sizeof(T)*n + 8);
+ // assume malloc alignment is at least 8
+ #endif
+
+ #ifdef TAOCRYPT_NO_ALIGNED_ALLOC
+ assert(m_pBlock == 0);
+ m_pBlock = p;
+ if (!IsAlignedOn(p, 16))
+ {
+ assert(IsAlignedOn(p, 8));
+ p = (byte *)p + 8;
+ }
+ #endif
+
+ assert(IsAlignedOn(p, 16));
+ return (T*)p;
+ }
+ return new (tc) T[n];
+}
+
+
+template <class T>
+void AlignedAllocator<T>::deallocate(void* p, size_type n)
+{
+ memset(p, 0, n*sizeof(T));
+ if (n >= 4)
+ {
+ #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE
+ _mm_free(p);
+ #elif defined(TAOCRYPT_NO_ALIGNED_ALLOC)
+ assert(m_pBlock == p || (byte*)m_pBlock+8 == p);
+ free(m_pBlock);
+ m_pBlock = 0;
+ #else
+ free(p);
+ #endif
+ }
+ else
+ tcArrayDelete((T *)p);
+}
+
+#endif // SSE2
+
+
+// ******** start of integer needs
+
+// start 5.2.1 adds DWord and Word ********
+
+// ********************************************************
+
+class DWord {
+public:
+DWord() {}
+
+#ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ explicit DWord(word low)
+ {
+ whole_ = low;
+ }
+#else
+ explicit DWord(word low)
+ {
+ halfs_.low = low;
+ halfs_.high = 0;
+ }
+#endif
+
+ DWord(word low, word high)
+ {
+ halfs_.low = low;
+ halfs_.high = high;
+ }
+
+ static DWord Multiply(word a, word b)
+ {
+ DWord r;
+
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = (dword)a * b;
+
+ #elif defined(_MSC_VER)
+ r.halfs_.low = a*b;
+ r.halfs_.high = myUMULH(a,b);
+
+ #elif defined(__alpha__)
+ r.halfs_.low = a*b;
+ #ifdef __GNUC__
+ __asm__("umulh %1,%2,%0" : "=r" (r.halfs_.high)
+ : "r" (a), "r" (b));
+ #elif defined(__DECCXX)
+ r.halfs_.high = asm("umulh %a0, %a1, %v0", a, b);
+ #else
+ #error unknown alpha compiler
+ #endif
+
+ #elif defined(__ia64__)
+ r.halfs_.low = a*b;
+ __asm__("xmpy.hu %0=%1,%2" : "=f" (r.halfs_.high)
+ : "f" (a), "f" (b));
+
+ #elif defined(_ARCH_PPC64)
+ r.halfs_.low = a*b;
+ __asm__("mulhdu %0,%1,%2" : "=r" (r.halfs_.high)
+ : "r" (a), "r" (b) : "cc");
+
+ #elif defined(__x86_64__)
+ __asm__("mulq %3" : "=d" (r.halfs_.high), "=a" (r.halfs_.low) :
+ "a" (a), "rm" (b) : "cc");
+
+ #elif defined(__mips64)
+ __asm__("dmultu %2,%3" : "=h" (r.halfs_.high), "=l" (r.halfs_.low)
+ : "r" (a), "r" (b));
+
+ #elif defined(_M_IX86)
+ // for testing
+ word64 t = (word64)a * b;
+ r.halfs_.high = ((word32 *)(&t))[1];
+ r.halfs_.low = (word32)t;
+ #else
+ #error can not implement DWord
+ #endif
+
+ return r;
+ }
+
+ static DWord MultiplyAndAdd(word a, word b, word c)
+ {
+ DWord r = Multiply(a, b);
+ return r += c;
+ }
+
+ DWord & operator+=(word a)
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ whole_ = whole_ + a;
+ #else
+ halfs_.low += a;
+ halfs_.high += (halfs_.low < a);
+ #endif
+ return *this;
+ }
+
+ DWord operator+(word a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ + a;
+ #else
+ r.halfs_.low = halfs_.low + a;
+ r.halfs_.high = halfs_.high + (r.halfs_.low < a);
+ #endif
+ return r;
+ }
+
+ DWord operator-(DWord a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ - a.whole_;
+ #else
+ r.halfs_.low = halfs_.low - a.halfs_.low;
+ r.halfs_.high = halfs_.high - a.halfs_.high -
+ (r.halfs_.low > halfs_.low);
+ #endif
+ return r;
+ }
+
+ DWord operator-(word a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ - a;
+ #else
+ r.halfs_.low = halfs_.low - a;
+ r.halfs_.high = halfs_.high - (r.halfs_.low > halfs_.low);
+ #endif
+ return r;
+ }
+
+ // returns quotient, which must fit in a word
+ word operator/(word divisor);
+
+ word operator%(word a);
+
+ bool operator!() const
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return !whole_;
+ #else
+ return !halfs_.high && !halfs_.low;
+ #endif
+ }
+
+ word GetLowHalf() const {return halfs_.low;}
+ word GetHighHalf() const {return halfs_.high;}
+ word GetHighHalfAsBorrow() const {return 0-halfs_.high;}
+
+private:
+ union
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ dword whole_;
+ #endif
+ struct
+ {
+ #ifdef LITTLE_ENDIAN_ORDER
+ word low;
+ word high;
+ #else
+ word high;
+ word low;
+ #endif
+ } halfs_;
+ };
+};
+
+
+class Word {
+public:
+ Word() {}
+
+ Word(word value)
+ {
+ whole_ = value;
+ }
+
+ Word(hword low, hword high)
+ {
+ whole_ = low | (word(high) << (WORD_BITS/2));
+ }
+
+ static Word Multiply(hword a, hword b)
+ {
+ Word r;
+ r.whole_ = (word)a * b;
+ return r;
+ }
+
+ Word operator-(Word a)
+ {
+ Word r;
+ r.whole_ = whole_ - a.whole_;
+ return r;
+ }
+
+ Word operator-(hword a)
+ {
+ Word r;
+ r.whole_ = whole_ - a;
+ return r;
+ }
+
+ // returns quotient, which must fit in a word
+ hword operator/(hword divisor)
+ {
+ return hword(whole_ / divisor);
+ }
+
+ bool operator!() const
+ {
+ return !whole_;
+ }
+
+ word GetWhole() const {return whole_;}
+ hword GetLowHalf() const {return hword(whole_);}
+ hword GetHighHalf() const {return hword(whole_>>(WORD_BITS/2));}
+ hword GetHighHalfAsBorrow() const {return 0-hword(whole_>>(WORD_BITS/2));}
+
+private:
+ word whole_;
+};
+
+
+// dummy is VC60 compiler bug workaround
+// do a 3 word by 2 word divide, returns quotient and leaves remainder in A
+template <class S, class D>
+S DivideThreeWordsByTwo(S* A, S B0, S B1, D* dummy_VC6_WorkAround = 0)
+{
+ // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S
+ assert(A[2] < B1 || (A[2]==B1 && A[1] < B0));
+
+ // estimate the quotient: do a 2 S by 1 S divide
+ S Q;
+ if (S(B1+1) == 0)
+ Q = A[2];
+ else
+ Q = D(A[1], A[2]) / S(B1+1);
+
+ // now subtract Q*B from A
+ D p = D::Multiply(B0, Q);
+ D u = (D) A[0] - p.GetLowHalf();
+ A[0] = u.GetLowHalf();
+ u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() -
+ D::Multiply(B1, Q);
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+
+ // Q <= actual quotient, so fix it
+ while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0))
+ {
+ u = (D) A[0] - B0;
+ A[0] = u.GetLowHalf();
+ u = (D) A[1] - B1 - u.GetHighHalfAsBorrow();
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+ Q++;
+ assert(Q); // shouldn't overflow
+ }
+
+ return Q;
+}
+
+
+// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1
+template <class S, class D>
+inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B)
+{
+ if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS)
+ return D(Ah.GetLowHalf(), Ah.GetHighHalf());
+ else
+ {
+ S Q[2];
+ T[0] = Al.GetLowHalf();
+ T[1] = Al.GetHighHalf();
+ T[2] = Ah.GetLowHalf();
+ T[3] = Ah.GetHighHalf();
+ Q[1] = DivideThreeWordsByTwo<S, D>(T+1, B.GetLowHalf(),
+ B.GetHighHalf());
+ Q[0] = DivideThreeWordsByTwo<S, D>(T, B.GetLowHalf(), B.GetHighHalf());
+ return D(Q[0], Q[1]);
+ }
+}
+
+
+// returns quotient, which must fit in a word
+inline word DWord::operator/(word a)
+{
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return word(whole_ / a);
+ #else
+ hword r[4];
+ return DivideFourWordsByTwo<hword, Word>(r, halfs_.low,
+ halfs_.high, a).GetWhole();
+ #endif
+}
+
+inline word DWord::operator%(word a)
+{
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return word(whole_ % a);
+ #else
+ if (a < (word(1) << (WORD_BITS/2)))
+ {
+ hword h = hword(a);
+ word r = halfs_.high % h;
+ r = ((halfs_.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h;
+ return hword((hword(halfs_.low) + (r << (WORD_BITS/2))) % h);
+ }
+ else
+ {
+ hword r[4];
+ DivideFourWordsByTwo<hword, Word>(r, halfs_.low, halfs_.high, a);
+ return Word(r[0], r[1]).GetWhole();
+ }
+ #endif
+}
+
+
+
+// end 5.2.1 DWord and Word adds
+
+
+
+
+
+static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8};
+
+static inline unsigned int RoundupSize(unsigned int n)
+{
+ if (n<=8)
+ return RoundupSizeTable[n];
+ else if (n<=16)
+ return 16;
+ else if (n<=32)
+ return 32;
+ else if (n<=64)
+ return 64;
+ else return 1U << BitPrecision(n-1);
+}
+
+
+static int Compare(const word *A, const word *B, unsigned int N)
+{
+ while (N--)
+ if (A[N] > B[N])
+ return 1;
+ else if (A[N] < B[N])
+ return -1;
+
+ return 0;
+}
+
+static word Increment(word *A, unsigned int N, word B=1)
+{
+ assert(N);
+ word t = A[0];
+ A[0] = t+B;
+ if (A[0] >= t)
+ return 0;
+ for (unsigned i=1; i<N; i++)
+ if (++A[i])
+ return 0;
+ return 1;
+}
+
+static word Decrement(word *A, unsigned int N, word B=1)
+{
+ assert(N);
+ word t = A[0];
+ A[0] = t-B;
+ if (A[0] <= t)
+ return 0;
+ for (unsigned i=1; i<N; i++)
+ if (A[i]--)
+ return 0;
+ return 1;
+}
+
+static void TwosComplement(word *A, unsigned int N)
+{
+ Decrement(A, N);
+ for (unsigned i=0; i<N; i++)
+ A[i] = ~A[i];
+}
+
+
+static word LinearMultiply(word *C, const word *A, word B, unsigned int N)
+{
+ word carry=0;
+ for(unsigned i=0; i<N; i++)
+ {
+ DWord p = DWord::MultiplyAndAdd(A[i], B, carry);
+ C[i] = p.GetLowHalf();
+ carry = p.GetHighHalf();
+ }
+ return carry;
+}
+
+
+static word AtomicInverseModPower2(word A)
+{
+ assert(A%2==1);
+
+ word R=A%8;
+
+ for (unsigned i=3; i<WORD_BITS; i*=2)
+ R = R*(2-R*A);
+
+ assert(R*A==1);
+ return R;
+}
+
+
+// ********************************************************
+
+class Portable
+{
+public:
+ static word Add(word *C, const word *A, const word *B, unsigned int N);
+ static word Subtract(word *C, const word *A, const word*B, unsigned int N);
+
+ static inline void Multiply2(word *C, const word *A, const word *B);
+ static inline word Multiply2Add(word *C, const word *A, const word *B);
+ static void Multiply4(word *C, const word *A, const word *B);
+ static void Multiply8(word *C, const word *A, const word *B);
+ static inline unsigned int MultiplyRecursionLimit() {return 8;}
+
+ static inline void Multiply2Bottom(word *C, const word *A, const word *B);
+ static void Multiply4Bottom(word *C, const word *A, const word *B);
+ static void Multiply8Bottom(word *C, const word *A, const word *B);
+ static inline unsigned int MultiplyBottomRecursionLimit() {return 8;}
+
+ static void Square2(word *R, const word *A);
+ static void Square4(word *R, const word *A);
+ static void Square8(word *R, const word *A) {assert(false);}
+ static inline unsigned int SquareRecursionLimit() {return 4;}
+};
+
+word Portable::Add(word *C, const word *A, const word *B, unsigned int N)
+{
+ assert (N%2 == 0);
+
+ DWord u(0, 0);
+ for (unsigned int i = 0; i < N; i+=2)
+ {
+ u = DWord(A[i]) + B[i] + u.GetHighHalf();
+ C[i] = u.GetLowHalf();
+ u = DWord(A[i+1]) + B[i+1] + u.GetHighHalf();
+ C[i+1] = u.GetLowHalf();
+ }
+ return u.GetHighHalf();
+}
+
+word Portable::Subtract(word *C, const word *A, const word *B, unsigned int N)
+{
+ assert (N%2 == 0);
+
+ DWord u(0, 0);
+ for (unsigned int i = 0; i < N; i+=2)
+ {
+ u = (DWord) A[i] - B[i] - u.GetHighHalfAsBorrow();
+ C[i] = u.GetLowHalf();
+ u = (DWord) A[i+1] - B[i+1] - u.GetHighHalfAsBorrow();
+ C[i+1] = u.GetLowHalf();
+ }
+ return 0-u.GetHighHalf();
+}
+
+void Portable::Multiply2(word *C, const word *A, const word *B)
+{
+/*
+ word s;
+ dword d;
+
+ if (A1 >= A0)
+ if (B0 >= B1)
+ {
+ s = 0;
+ d = (dword)(A1-A0)*(B0-B1);
+ }
+ else
+ {
+ s = (A1-A0);
+ d = (dword)s*(word)(B0-B1);
+ }
+ else
+ if (B0 > B1)
+ {
+ s = (B0-B1);
+ d = (word)(A1-A0)*(dword)s;
+ }
+ else
+ {
+ s = 0;
+ d = (dword)(A0-A1)*(B1-B0);
+ }
+*/
+ // this segment is the branchless equivalent of above
+ word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]};
+ unsigned int ai = A[1] < A[0];
+ unsigned int bi = B[0] < B[1];
+ unsigned int di = ai & bi;
+ DWord d = DWord::Multiply(D[di], D[di+2]);
+ D[1] = D[3] = 0;
+ unsigned int si = ai + !bi;
+ word s = D[si];
+
+ DWord A0B0 = DWord::Multiply(A[0], B[0]);
+ C[0] = A0B0.GetLowHalf();
+
+ DWord A1B1 = DWord::Multiply(A[1], B[1]);
+ DWord t = (DWord) A0B0.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf()
+ + A1B1.GetLowHalf();
+ C[1] = t.GetLowHalf();
+
+ t = A1B1 + t.GetHighHalf() + A0B0.GetHighHalf() + d.GetHighHalf()
+ + A1B1.GetHighHalf() - s;
+ C[2] = t.GetLowHalf();
+ C[3] = t.GetHighHalf();
+}
+
+inline void Portable::Multiply2Bottom(word *C, const word *A, const word *B)
+{
+ DWord t = DWord::Multiply(A[0], B[0]);
+ C[0] = t.GetLowHalf();
+ C[1] = t.GetHighHalf() + A[0]*B[1] + A[1]*B[0];
+}
+
+word Portable::Multiply2Add(word *C, const word *A, const word *B)
+{
+ word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]};
+ unsigned int ai = A[1] < A[0];
+ unsigned int bi = B[0] < B[1];
+ unsigned int di = ai & bi;
+ DWord d = DWord::Multiply(D[di], D[di+2]);
+ D[1] = D[3] = 0;
+ unsigned int si = ai + !bi;
+ word s = D[si];
+
+ DWord A0B0 = DWord::Multiply(A[0], B[0]);
+ DWord t = A0B0 + C[0];
+ C[0] = t.GetLowHalf();
+
+ DWord A1B1 = DWord::Multiply(A[1], B[1]);
+ t = (DWord) t.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf() +
+ A1B1.GetLowHalf() + C[1];
+ C[1] = t.GetLowHalf();
+
+ t = (DWord) t.GetHighHalf() + A1B1.GetLowHalf() + A0B0.GetHighHalf() +
+ d.GetHighHalf() + A1B1.GetHighHalf() - s + C[2];
+ C[2] = t.GetLowHalf();
+
+ t = (DWord) t.GetHighHalf() + A1B1.GetHighHalf() + C[3];
+ C[3] = t.GetLowHalf();
+ return t.GetHighHalf();
+}
+
+
+#define MulAcc(x, y) \
+ p = DWord::MultiplyAndAdd(A[x], B[y], c); \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+#define SaveMulAcc(s, x, y) \
+ R[s] = c; \
+ p = DWord::MultiplyAndAdd(A[x], B[y], d); \
+ c = p.GetLowHalf(); \
+ p = (DWord) e + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e = p.GetHighHalf();
+
+#define SquAcc(x, y) \
+ q = DWord::Multiply(A[x], A[y]); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf(); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+#define SaveSquAcc(s, x, y) \
+ R[s] = c; \
+ q = DWord::Multiply(A[x], A[y]); \
+ p = q + d; \
+ c = p.GetLowHalf(); \
+ p = (DWord) e + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e = p.GetHighHalf(); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+
+void Portable::Multiply4(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 3, 1);
+ MulAcc(2, 2);
+ MulAcc(1, 3);
+
+ SaveMulAcc(4, 2, 3);
+ MulAcc(3, 2);
+
+ R[5] = c;
+ p = DWord::MultiplyAndAdd(A[3], B[3], d);
+ R[6] = p.GetLowHalf();
+ R[7] = e + p.GetHighHalf();
+}
+
+void Portable::Square2(word *R, const word *A)
+{
+ DWord p, q;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], A[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ SquAcc(0, 1);
+
+ R[1] = c;
+ p = DWord::MultiplyAndAdd(A[1], A[1], d);
+ R[2] = p.GetLowHalf();
+ R[3] = e + p.GetHighHalf();
+}
+
+void Portable::Square4(word *R, const word *A)
+{
+#ifdef _MSC_VER
+ // VC60 workaround: MSVC 6.0 has an optimization bug that makes
+ // (dword)A*B where either A or B has been cast to a dword before
+ // very expensive. Revisit this function when this
+ // bug is fixed.
+ Multiply4(R, A, A);
+#else
+ const word *B = A;
+ DWord p, q;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], A[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ SquAcc(0, 1);
+
+ SaveSquAcc(1, 2, 0);
+ MulAcc(1, 1);
+
+ SaveSquAcc(2, 0, 3);
+ SquAcc(1, 2);
+
+ SaveSquAcc(3, 3, 1);
+ MulAcc(2, 2);
+
+ SaveSquAcc(4, 2, 3);
+
+ R[5] = c;
+ p = DWord::MultiplyAndAdd(A[3], A[3], d);
+ R[6] = p.GetLowHalf();
+ R[7] = e + p.GetHighHalf();
+#endif
+}
+
+void Portable::Multiply8(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 0, 4);
+ MulAcc(1, 3);
+ MulAcc(2, 2);
+ MulAcc(3, 1);
+ MulAcc(4, 0);
+
+ SaveMulAcc(4, 0, 5);
+ MulAcc(1, 4);
+ MulAcc(2, 3);
+ MulAcc(3, 2);
+ MulAcc(4, 1);
+ MulAcc(5, 0);
+
+ SaveMulAcc(5, 0, 6);
+ MulAcc(1, 5);
+ MulAcc(2, 4);
+ MulAcc(3, 3);
+ MulAcc(4, 2);
+ MulAcc(5, 1);
+ MulAcc(6, 0);
+
+ SaveMulAcc(6, 0, 7);
+ MulAcc(1, 6);
+ MulAcc(2, 5);
+ MulAcc(3, 4);
+ MulAcc(4, 3);
+ MulAcc(5, 2);
+ MulAcc(6, 1);
+ MulAcc(7, 0);
+
+ SaveMulAcc(7, 1, 7);
+ MulAcc(2, 6);
+ MulAcc(3, 5);
+ MulAcc(4, 4);
+ MulAcc(5, 3);
+ MulAcc(6, 2);
+ MulAcc(7, 1);
+
+ SaveMulAcc(8, 2, 7);
+ MulAcc(3, 6);
+ MulAcc(4, 5);
+ MulAcc(5, 4);
+ MulAcc(6, 3);
+ MulAcc(7, 2);
+
+ SaveMulAcc(9, 3, 7);
+ MulAcc(4, 6);
+ MulAcc(5, 5);
+ MulAcc(6, 4);
+ MulAcc(7, 3);
+
+ SaveMulAcc(10, 4, 7);
+ MulAcc(5, 6);
+ MulAcc(6, 5);
+ MulAcc(7, 4);
+
+ SaveMulAcc(11, 5, 7);
+ MulAcc(6, 6);
+ MulAcc(7, 5);
+
+ SaveMulAcc(12, 6, 7);
+ MulAcc(7, 6);
+
+ R[13] = c;
+ p = DWord::MultiplyAndAdd(A[7], B[7], d);
+ R[14] = p.GetLowHalf();
+ R[15] = e + p.GetHighHalf();
+}
+
+void Portable::Multiply4Bottom(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ R[2] = c;
+ R[3] = d + A[0] * B[3] + A[1] * B[2] + A[2] * B[1] + A[3] * B[0];
+}
+
+void Portable::Multiply8Bottom(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 0, 4);
+ MulAcc(1, 3);
+ MulAcc(2, 2);
+ MulAcc(3, 1);
+ MulAcc(4, 0);
+
+ SaveMulAcc(4, 0, 5);
+ MulAcc(1, 4);
+ MulAcc(2, 3);
+ MulAcc(3, 2);
+ MulAcc(4, 1);
+ MulAcc(5, 0);
+
+ SaveMulAcc(5, 0, 6);
+ MulAcc(1, 5);
+ MulAcc(2, 4);
+ MulAcc(3, 3);
+ MulAcc(4, 2);
+ MulAcc(5, 1);
+ MulAcc(6, 0);
+
+ R[6] = c;
+ R[7] = d + A[0] * B[7] + A[1] * B[6] + A[2] * B[5] + A[3] * B[4] +
+ A[4] * B[3] + A[5] * B[2] + A[6] * B[1] + A[7] * B[0];
+}
+
+
+#undef MulAcc
+#undef SaveMulAcc
+#undef SquAcc
+#undef SaveSquAcc
+
+// optimized
+
+#ifdef TAOCRYPT_X86ASM_AVAILABLE
+
+// ************** x86 feature detection ***************
+
+static bool s_sse2Enabled = true;
+
+static void CpuId(word32 input, word32 *output)
+{
+#ifdef __GNUC__
+ __asm__
+ (
+ // save ebx in case -fPIC is being used
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+ : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d"(output[3])
+ : "a" (input)
+ );
+#else
+ __asm
+ {
+ mov eax, input
+ cpuid
+ mov edi, output
+ mov [edi], eax
+ mov [edi+4], ebx
+ mov [edi+8], ecx
+ mov [edi+12], edx
+ }
+#endif
+}
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+#ifndef _MSC_VER
+static jmp_buf s_env;
+static void SigIllHandler(int)
+{
+ longjmp(s_env, 1);
+}
+#endif
+
+static bool HasSSE2()
+{
+ if (!s_sse2Enabled)
+ return false;
+
+ word32 cpuid[4];
+ CpuId(1, cpuid);
+ if ((cpuid[3] & (1 << 26)) == 0)
+ return false;
+
+#ifdef _MSC_VER
+ __try
+ {
+ __asm xorpd xmm0, xmm0 // executing SSE2 instruction
+ }
+ __except (1)
+ {
+ return false;
+ }
+ return true;
+#else
+ typedef void (*SigHandler)(int);
+
+ SigHandler oldHandler = signal(SIGILL, SigIllHandler);
+ if (oldHandler == SIG_ERR)
+ return false;
+
+ bool result = true;
+ if (setjmp(s_env))
+ result = false;
+ else
+ __asm __volatile ("xorps %xmm0, %xmm0");
+
+ signal(SIGILL, oldHandler);
+ return result;
+#endif
+}
+#endif
+
+static bool IsP4()
+{
+ word32 cpuid[4];
+
+ CpuId(0, cpuid);
+ mySTL::swap(cpuid[2], cpuid[3]);
+ if (memcmp(cpuid+1, "GenuineIntel", 12) != 0)
+ return false;
+
+ CpuId(1, cpuid);
+ return ((cpuid[0] >> 8) & 0xf) == 0xf;
+}
+
+// ************** Pentium/P4 optimizations ***************
+
+class PentiumOptimized : public Portable
+{
+public:
+ static word TAOCRYPT_CDECL Add(word *C, const word *A, const word *B,
+ unsigned int N);
+ static word TAOCRYPT_CDECL Subtract(word *C, const word *A, const word *B,
+ unsigned int N);
+ static void TAOCRYPT_CDECL Multiply4(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8Bottom(word *C, const word *A,
+ const word *B);
+};
+
+class P4Optimized
+{
+public:
+ static word TAOCRYPT_CDECL Add(word *C, const word *A, const word *B,
+ unsigned int N);
+ static word TAOCRYPT_CDECL Subtract(word *C, const word *A, const word *B,
+ unsigned int N);
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ static void TAOCRYPT_CDECL Multiply4(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8Bottom(word *C, const word *A,
+ const word *B);
+#endif
+};
+
+typedef word (TAOCRYPT_CDECL * PAddSub)(word *C, const word *A, const word *B,
+ unsigned int N);
+typedef void (TAOCRYPT_CDECL * PMul)(word *C, const word *A, const word *B);
+
+static PAddSub s_pAdd, s_pSub;
+#ifdef SSE2_INTRINSICS_AVAILABLE
+static PMul s_pMul4, s_pMul8, s_pMul8B;
+#endif
+
+static void SetPentiumFunctionPointers()
+{
+ if (IsP4())
+ {
+ s_pAdd = &P4Optimized::Add;
+ s_pSub = &P4Optimized::Subtract;
+ }
+ else
+ {
+ s_pAdd = &PentiumOptimized::Add;
+ s_pSub = &PentiumOptimized::Subtract;
+ }
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ if (HasSSE2())
+ {
+ s_pMul4 = &P4Optimized::Multiply4;
+ s_pMul8 = &P4Optimized::Multiply8;
+ s_pMul8B = &P4Optimized::Multiply8Bottom;
+ }
+ else
+ {
+ s_pMul4 = &PentiumOptimized::Multiply4;
+ s_pMul8 = &PentiumOptimized::Multiply8;
+ s_pMul8B = &PentiumOptimized::Multiply8Bottom;
+ }
+#endif
+}
+
+static const char s_RunAtStartupSetPentiumFunctionPointers =
+ (SetPentiumFunctionPointers(), 0);
+
+void DisableSSE2()
+{
+ s_sse2Enabled = false;
+ SetPentiumFunctionPointers();
+}
+
+class LowLevel : public PentiumOptimized
+{
+public:
+ inline static word Add(word *C, const word *A, const word *B,
+ unsigned int N)
+ {return s_pAdd(C, A, B, N);}
+ inline static word Subtract(word *C, const word *A, const word *B,
+ unsigned int N)
+ {return s_pSub(C, A, B, N);}
+ inline static void Square4(word *R, const word *A)
+ {Multiply4(R, A, A);}
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ inline static void Multiply4(word *C, const word *A, const word *B)
+ {s_pMul4(C, A, B);}
+ inline static void Multiply8(word *C, const word *A, const word *B)
+ {s_pMul8(C, A, B);}
+ inline static void Multiply8Bottom(word *C, const word *A, const word *B)
+ {s_pMul8B(C, A, B);}
+#endif
+};
+
+// use some tricks to share assembly code between MSVC and GCC
+#ifdef _MSC_VER
+ #define TAOCRYPT_NAKED __declspec(naked)
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+ #define AddPrologue \
+ __asm push ebp \
+ __asm push ebx \
+ __asm push esi \
+ __asm push edi \
+ __asm mov ecx, [esp+20] \
+ __asm mov edx, [esp+24] \
+ __asm mov ebx, [esp+28] \
+ __asm mov esi, [esp+32]
+ #define AddEpilogue \
+ __asm pop edi \
+ __asm pop esi \
+ __asm pop ebx \
+ __asm pop ebp \
+ __asm ret
+ #define MulPrologue \
+ __asm push ebp \
+ __asm push ebx \
+ __asm push esi \
+ __asm push edi \
+ __asm mov ecx, [esp+28] \
+ __asm mov esi, [esp+24] \
+ __asm push [esp+20]
+ #define MulEpilogue \
+ __asm add esp, 4 \
+ __asm pop edi \
+ __asm pop esi \
+ __asm pop ebx \
+ __asm pop ebp \
+ __asm ret
+#else
+ #define TAOCRYPT_NAKED
+ #define AS1(x) #x ";"
+ #define AS2(x, y) #x ", " #y ";"
+ #define AddPrologue \
+ __asm__ __volatile__ \
+ ( \
+ "push %%ebx;" /* save this manually, in case of -fPIC */ \
+ "mov %2, %%ebx;" \
+ ".intel_syntax noprefix;" \
+ "push ebp;"
+ #define AddEpilogue \
+ "pop ebp;" \
+ ".att_syntax prefix;" \
+ "pop %%ebx;" \
+ : \
+ : "c" (C), "d" (A), "m" (B), "S" (N) \
+ : "%edi", "memory", "cc" \
+ );
+ #define MulPrologue \
+ __asm__ __volatile__ \
+ ( \
+ "push %%ebx;" /* save this manually, in case of -fPIC */ \
+ "push %%ebp;" \
+ "push %0;" \
+ ".intel_syntax noprefix;"
+ #define MulEpilogue \
+ "add esp, 4;" \
+ "pop ebp;" \
+ "pop ebx;" \
+ ".att_syntax prefix;" \
+ : \
+ : "rm" (Z), "S" (X), "c" (Y) \
+ : "%eax", "%edx", "%edi", "memory", "cc" \
+ );
+#endif
+
+TAOCRYPT_NAKED word PentiumOptimized::Add(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( sub ecx, edx) // hold the distance between C & A so we
+ // can add this to A to get C
+ AS2( xor eax, eax) // clear eax
+
+ AS2( sub eax, esi) // eax is a negative index from end of B
+ AS2( lea ebx, [ebx+4*esi]) // ebx is end of B
+
+ AS2( sar eax, 1) // unit of eax is now dwords; this also
+ // clears the carry flag
+ AS1( jz loopendAdd) // if no dwords then nothing to do
+
+ AS1(loopstartAdd:)
+ AS2( mov esi,[edx]) // load lower word of A
+ AS2( mov ebp,[edx+4]) // load higher word of A
+
+ AS2( mov edi,[ebx+8*eax]) // load lower word of B
+ AS2( lea edx,[edx+8]) // advance A and C
+
+ AS2( adc esi,edi) // add lower words
+ AS2( mov edi,[ebx+8*eax+4]) // load higher word of B
+
+ AS2( adc ebp,edi) // add higher words
+ AS1( inc eax) // advance B
+
+ AS2( mov [edx+ecx-8],esi) // store lower word result
+ AS2( mov [edx+ecx-4],ebp) // store higher word result
+
+ AS1( jnz loopstartAdd) // loop until eax overflows and becomes zero
+
+ AS1(loopendAdd:)
+ AS2( adc eax, 0) // store carry into eax (return result register)
+
+ AddEpilogue
+}
+
+TAOCRYPT_NAKED word PentiumOptimized::Subtract(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( sub ecx, edx) // hold the distance between C & A so we
+ // can add this to A to get C
+ AS2( xor eax, eax) // clear eax
+
+ AS2( sub eax, esi) // eax is a negative index from end of B
+ AS2( lea ebx, [ebx+4*esi]) // ebx is end of B
+
+ AS2( sar eax, 1) // unit of eax is now dwords; this also
+ // clears the carry flag
+ AS1( jz loopendSub) // if no dwords then nothing to do
+
+ AS1(loopstartSub:)
+ AS2( mov esi,[edx]) // load lower word of A
+ AS2( mov ebp,[edx+4]) // load higher word of A
+
+ AS2( mov edi,[ebx+8*eax]) // load lower word of B
+ AS2( lea edx,[edx+8]) // advance A and C
+
+ AS2( sbb esi,edi) // subtract lower words
+ AS2( mov edi,[ebx+8*eax+4]) // load higher word of B
+
+ AS2( sbb ebp,edi) // subtract higher words
+ AS1( inc eax) // advance B
+
+ AS2( mov [edx+ecx-8],esi) // store lower word result
+ AS2( mov [edx+ecx-4],ebp) // store higher word result
+
+ AS1( jnz loopstartSub) // loop until eax overflows and becomes zero
+
+ AS1(loopendSub:)
+ AS2( adc eax, 0) // store carry into eax (return result register)
+
+ AddEpilogue
+}
+
+// On Pentium 4, the adc and sbb instructions are very expensive, so avoid them.
+
+TAOCRYPT_NAKED word P4Optimized::Add(word *C, const word *A, const word *B,
+ unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( xor eax, eax)
+ AS1( neg esi)
+ AS1( jz loopendAddP4) // if no dwords then nothing to do
+
+ AS2( mov edi, [edx])
+ AS2( mov ebp, [ebx])
+ AS1( jmp carry1AddP4)
+
+ AS1(loopstartAddP4:)
+ AS2( mov edi, [edx+8])
+ AS2( add ecx, 8)
+ AS2( add edx, 8)
+ AS2( mov ebp, [ebx])
+ AS2( add edi, eax)
+ AS1( jc carry1AddP4)
+ AS2( xor eax, eax)
+
+ AS1(carry1AddP4:)
+ AS2( add edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( mov [ecx], edi)
+ AS2( mov edi, [edx+4])
+ AS2( cmovc eax, ebp)
+ AS2( mov ebp, [ebx+4])
+ AS2( add ebx, 8)
+ AS2( add edi, eax)
+ AS1( jc carry2AddP4)
+ AS2( xor eax, eax)
+
+ AS1(carry2AddP4:)
+ AS2( add edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( cmovc eax, ebp)
+ AS2( mov [ecx+4], edi)
+ AS2( add esi, 2)
+ AS1( jnz loopstartAddP4)
+
+ AS1(loopendAddP4:)
+
+ AddEpilogue
+}
+
+TAOCRYPT_NAKED word P4Optimized::Subtract(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( xor eax, eax)
+ AS1( neg esi)
+ AS1( jz loopendSubP4) // if no dwords then nothing to do
+
+ AS2( mov edi, [edx])
+ AS2( mov ebp, [ebx])
+ AS1( jmp carry1SubP4)
+
+ AS1(loopstartSubP4:)
+ AS2( mov edi, [edx+8])
+ AS2( add edx, 8)
+ AS2( add ecx, 8)
+ AS2( mov ebp, [ebx])
+ AS2( sub edi, eax)
+ AS1( jc carry1SubP4)
+ AS2( xor eax, eax)
+
+ AS1(carry1SubP4:)
+ AS2( sub edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( mov [ecx], edi)
+ AS2( mov edi, [edx+4])
+ AS2( cmovc eax, ebp)
+ AS2( mov ebp, [ebx+4])
+ AS2( add ebx, 8)
+ AS2( sub edi, eax)
+ AS1( jc carry2SubP4)
+ AS2( xor eax, eax)
+
+ AS1(carry2SubP4:)
+ AS2( sub edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( cmovc eax, ebp)
+ AS2( mov [ecx+4], edi)
+ AS2( add esi, 2)
+ AS1( jnz loopstartSubP4)
+
+ AS1(loopendSubP4:)
+
+ AddEpilogue
+}
+
+// multiply assembly code originally contributed by Leonard Janke
+
+#define MulStartup \
+ AS2(xor ebp, ebp) \
+ AS2(xor edi, edi) \
+ AS2(xor ebx, ebx)
+
+#define MulShiftCarry \
+ AS2(mov ebp, edx) \
+ AS2(mov edi, ebx) \
+ AS2(xor ebx, ebx)
+
+#define MulAccumulateBottom(i,j) \
+ AS2(mov eax, [ecx+4*j]) \
+ AS2(imul eax, dword ptr [esi+4*i]) \
+ AS2(add ebp, eax)
+
+#define MulAccumulate(i,j) \
+ AS2(mov eax, [ecx+4*j]) \
+ AS1(mul dword ptr [esi+4*i]) \
+ AS2(add ebp, eax) \
+ AS2(adc edi, edx) \
+ AS2(adc bl, bh)
+
+#define MulStoreDigit(i) \
+ AS2(mov edx, edi) \
+ AS2(mov edi, [esp]) \
+ AS2(mov [edi+4*i], ebp)
+
+#define MulLastDiagonal(digits) \
+ AS2(mov eax, [ecx+4*(digits-1)]) \
+ AS1(mul dword ptr [esi+4*(digits-1)]) \
+ AS2(add ebp, eax) \
+ AS2(adc edx, edi) \
+ AS2(mov edi, [esp]) \
+ AS2(mov [edi+4*(2*digits-2)], ebp) \
+ AS2(mov [edi+4*(2*digits-1)], edx)
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply4(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulLastDiagonal(4)
+ MulEpilogue
+}
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply8(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(4,0)
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulAccumulate(0,4)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(5,0)
+ MulAccumulate(4,1)
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulAccumulate(1,4)
+ MulAccumulate(0,5)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulAccumulate(6,0)
+ MulAccumulate(5,1)
+ MulAccumulate(4,2)
+ MulAccumulate(3,3)
+ MulAccumulate(2,4)
+ MulAccumulate(1,5)
+ MulAccumulate(0,6)
+ MulStoreDigit(6)
+ MulShiftCarry
+
+ MulAccumulate(7,0)
+ MulAccumulate(6,1)
+ MulAccumulate(5,2)
+ MulAccumulate(4,3)
+ MulAccumulate(3,4)
+ MulAccumulate(2,5)
+ MulAccumulate(1,6)
+ MulAccumulate(0,7)
+ MulStoreDigit(7)
+ MulShiftCarry
+
+ MulAccumulate(7,1)
+ MulAccumulate(6,2)
+ MulAccumulate(5,3)
+ MulAccumulate(4,4)
+ MulAccumulate(3,5)
+ MulAccumulate(2,6)
+ MulAccumulate(1,7)
+ MulStoreDigit(8)
+ MulShiftCarry
+
+ MulAccumulate(7,2)
+ MulAccumulate(6,3)
+ MulAccumulate(5,4)
+ MulAccumulate(4,5)
+ MulAccumulate(3,6)
+ MulAccumulate(2,7)
+ MulStoreDigit(9)
+ MulShiftCarry
+
+ MulAccumulate(7,3)
+ MulAccumulate(6,4)
+ MulAccumulate(5,5)
+ MulAccumulate(4,6)
+ MulAccumulate(3,7)
+ MulStoreDigit(10)
+ MulShiftCarry
+
+ MulAccumulate(7,4)
+ MulAccumulate(6,5)
+ MulAccumulate(5,6)
+ MulAccumulate(4,7)
+ MulStoreDigit(11)
+ MulShiftCarry
+
+ MulAccumulate(7,5)
+ MulAccumulate(6,6)
+ MulAccumulate(5,7)
+ MulStoreDigit(12)
+ MulShiftCarry
+
+ MulAccumulate(7,6)
+ MulAccumulate(6,7)
+ MulStoreDigit(13)
+ MulShiftCarry
+
+ MulLastDiagonal(8)
+ MulEpilogue
+}
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply8Bottom(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(4,0)
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulAccumulate(0,4)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(5,0)
+ MulAccumulate(4,1)
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulAccumulate(1,4)
+ MulAccumulate(0,5)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulAccumulate(6,0)
+ MulAccumulate(5,1)
+ MulAccumulate(4,2)
+ MulAccumulate(3,3)
+ MulAccumulate(2,4)
+ MulAccumulate(1,5)
+ MulAccumulate(0,6)
+ MulStoreDigit(6)
+ MulShiftCarry
+
+ MulAccumulateBottom(7,0)
+ MulAccumulateBottom(6,1)
+ MulAccumulateBottom(5,2)
+ MulAccumulateBottom(4,3)
+ MulAccumulateBottom(3,4)
+ MulAccumulateBottom(2,5)
+ MulAccumulateBottom(1,6)
+ MulAccumulateBottom(0,7)
+ MulStoreDigit(7)
+ MulEpilogue
+}
+
+#undef AS1
+#undef AS2
+
+#else // not x86 - no processor specific code at this layer
+
+typedef Portable LowLevel;
+
+#endif
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+
+#ifdef __GNUC__
+#define TAOCRYPT_FASTCALL
+#else
+#define TAOCRYPT_FASTCALL __fastcall
+#endif
+
+static void TAOCRYPT_FASTCALL P4_Mul(__m128i *C, const __m128i *A,
+ const __m128i *B)
+{
+ __m128i a3210 = _mm_load_si128(A);
+ __m128i b3210 = _mm_load_si128(B);
+
+ __m128i sum;
+
+ __m128i z = _mm_setzero_si128();
+ __m128i a2b2_a0b0 = _mm_mul_epu32(a3210, b3210);
+ C[0] = a2b2_a0b0;
+
+ __m128i a3120 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(3, 1, 2, 0));
+ __m128i b3021 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 2, 1));
+ __m128i a1b0_a0b1 = _mm_mul_epu32(a3120, b3021);
+ __m128i a1b0 = _mm_unpackhi_epi32(a1b0_a0b1, z);
+ __m128i a0b1 = _mm_unpacklo_epi32(a1b0_a0b1, z);
+ C[1] = _mm_add_epi64(a1b0, a0b1);
+
+ __m128i a31 = _mm_srli_epi64(a3210, 32);
+ __m128i b31 = _mm_srli_epi64(b3210, 32);
+ __m128i a3b3_a1b1 = _mm_mul_epu32(a31, b31);
+ C[6] = a3b3_a1b1;
+
+ __m128i a1b1 = _mm_unpacklo_epi32(a3b3_a1b1, z);
+ __m128i b3012 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 1, 2));
+ __m128i a2b0_a0b2 = _mm_mul_epu32(a3210, b3012);
+ __m128i a0b2 = _mm_unpacklo_epi32(a2b0_a0b2, z);
+ __m128i a2b0 = _mm_unpackhi_epi32(a2b0_a0b2, z);
+ sum = _mm_add_epi64(a1b1, a0b2);
+ C[2] = _mm_add_epi64(sum, a2b0);
+
+ __m128i a2301 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i b2103 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(2, 1, 0, 3));
+ __m128i a3b0_a1b2 = _mm_mul_epu32(a2301, b3012);
+ __m128i a2b1_a0b3 = _mm_mul_epu32(a3210, b2103);
+ __m128i a3b0 = _mm_unpackhi_epi32(a3b0_a1b2, z);
+ __m128i a1b2 = _mm_unpacklo_epi32(a3b0_a1b2, z);
+ __m128i a2b1 = _mm_unpackhi_epi32(a2b1_a0b3, z);
+ __m128i a0b3 = _mm_unpacklo_epi32(a2b1_a0b3, z);
+ __m128i sum1 = _mm_add_epi64(a3b0, a1b2);
+ sum = _mm_add_epi64(a2b1, a0b3);
+ C[3] = _mm_add_epi64(sum, sum1);
+
+ __m128i a3b1_a1b3 = _mm_mul_epu32(a2301, b2103);
+ __m128i a2b2 = _mm_unpackhi_epi32(a2b2_a0b0, z);
+ __m128i a3b1 = _mm_unpackhi_epi32(a3b1_a1b3, z);
+ __m128i a1b3 = _mm_unpacklo_epi32(a3b1_a1b3, z);
+ sum = _mm_add_epi64(a2b2, a3b1);
+ C[4] = _mm_add_epi64(sum, a1b3);
+
+ __m128i a1302 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(1, 3, 0, 2));
+ __m128i b1203 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(1, 2, 0, 3));
+ __m128i a3b2_a2b3 = _mm_mul_epu32(a1302, b1203);
+ __m128i a3b2 = _mm_unpackhi_epi32(a3b2_a2b3, z);
+ __m128i a2b3 = _mm_unpacklo_epi32(a3b2_a2b3, z);
+ C[5] = _mm_add_epi64(a3b2, a2b3);
+}
+
+void P4Optimized::Multiply4(word *C, const word *A, const word *B)
+{
+ __m128i temp[7];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ C[0] = w[0];
+
+ __m64 s1, s2;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w18, w20);
+ s1 = _mm_add_si64(s1, s2);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w22, w26);
+ s1 = _mm_add_si64(s1, s2);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[7] = _mm_cvtsi64_si32(s1) + w[27];
+ _mm_empty();
+}
+
+void P4Optimized::Multiply8(word *C, const word *A, const word *B)
+{
+ __m128i temp[28];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+ const word *x = (word *)temp+7*4;
+ const __m64 *mx = (__m64 *)x;
+ const word *y = (word *)temp+7*4*2;
+ const __m64 *my = (__m64 *)y;
+ const word *z = (word *)temp+7*4*3;
+ const __m64 *mz = (__m64 *)z;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ P4_Mul(temp+7, (__m128i *)A+1, (__m128i *)B);
+
+ P4_Mul(temp+14, (__m128i *)A, (__m128i *)B+1);
+
+ P4_Mul(temp+21, (__m128i *)A+1, (__m128i *)B+1);
+
+ C[0] = w[0];
+
+ __m64 s1, s2, s3, s4;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+ __m64 w27 = _mm_cvtsi32_si64(w[27]);
+
+ __m64 x0 = _mm_cvtsi32_si64(x[0]);
+ __m64 x1 = _mm_cvtsi32_si64(x[1]);
+ __m64 x4 = mx[2];
+ __m64 x6 = mx[3];
+ __m64 x8 = mx[4];
+ __m64 x10 = mx[5];
+ __m64 x12 = mx[6];
+ __m64 x14 = mx[7];
+ __m64 x16 = mx[8];
+ __m64 x18 = mx[9];
+ __m64 x20 = mx[10];
+ __m64 x22 = mx[11];
+ __m64 x26 = _mm_cvtsi32_si64(x[26]);
+ __m64 x27 = _mm_cvtsi32_si64(x[27]);
+
+ __m64 y0 = _mm_cvtsi32_si64(y[0]);
+ __m64 y1 = _mm_cvtsi32_si64(y[1]);
+ __m64 y4 = my[2];
+ __m64 y6 = my[3];
+ __m64 y8 = my[4];
+ __m64 y10 = my[5];
+ __m64 y12 = my[6];
+ __m64 y14 = my[7];
+ __m64 y16 = my[8];
+ __m64 y18 = my[9];
+ __m64 y20 = my[10];
+ __m64 y22 = my[11];
+ __m64 y26 = _mm_cvtsi32_si64(y[26]);
+ __m64 y27 = _mm_cvtsi32_si64(y[27]);
+
+ __m64 z0 = _mm_cvtsi32_si64(z[0]);
+ __m64 z1 = _mm_cvtsi32_si64(z[1]);
+ __m64 z4 = mz[2];
+ __m64 z6 = mz[3];
+ __m64 z8 = mz[4];
+ __m64 z10 = mz[5];
+ __m64 z12 = mz[6];
+ __m64 z14 = mz[7];
+ __m64 z16 = mz[8];
+ __m64 z18 = mz[9];
+ __m64 z20 = mz[10];
+ __m64 z22 = mz[11];
+ __m64 z26 = _mm_cvtsi32_si64(z[26]);
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x0, y0);
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s3);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x1, y1);
+ s4 = _mm_add_si64(x4, y4);
+ s1 = _mm_add_si64(s1, w18);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w20);
+ s1 = _mm_add_si64(s1, s3);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x6, y6);
+ s4 = _mm_add_si64(x8, y8);
+ s1 = _mm_add_si64(s1, w22);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w26);
+ s1 = _mm_add_si64(s1, s3);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x10, y10);
+ s4 = _mm_add_si64(x12, y12);
+ s1 = _mm_add_si64(s1, w27);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, s3);
+ C[7] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x14, y14);
+ s4 = _mm_add_si64(x16, y16);
+ s1 = _mm_add_si64(s1, z0);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, s3);
+ C[8] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x18, y18);
+ s4 = _mm_add_si64(x20, y20);
+ s1 = _mm_add_si64(s1, z1);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, z4);
+ s1 = _mm_add_si64(s1, s3);
+ C[9] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x22, y22);
+ s4 = _mm_add_si64(x26, y26);
+ s1 = _mm_add_si64(s1, z6);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, z8);
+ s1 = _mm_add_si64(s1, s3);
+ C[10] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x27, y27);
+ s1 = _mm_add_si64(s1, z10);
+ s1 = _mm_add_si64(s1, z12);
+ s1 = _mm_add_si64(s1, s3);
+ C[11] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z14, z16);
+ s1 = _mm_add_si64(s1, s3);
+ C[12] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z18, z20);
+ s1 = _mm_add_si64(s1, s3);
+ C[13] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z22, z26);
+ s1 = _mm_add_si64(s1, s3);
+ C[14] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[15] = z[27] + _mm_cvtsi64_si32(s1);
+ _mm_empty();
+}
+
+void P4Optimized::Multiply8Bottom(word *C, const word *A, const word *B)
+{
+ __m128i temp[21];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+ const word *x = (word *)temp+7*4;
+ const __m64 *mx = (__m64 *)x;
+ const word *y = (word *)temp+7*4*2;
+ const __m64 *my = (__m64 *)y;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ P4_Mul(temp+7, (__m128i *)A+1, (__m128i *)B);
+
+ P4_Mul(temp+14, (__m128i *)A, (__m128i *)B+1);
+
+ C[0] = w[0];
+
+ __m64 s1, s2, s3, s4;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+
+ __m64 x0 = _mm_cvtsi32_si64(x[0]);
+ __m64 x1 = _mm_cvtsi32_si64(x[1]);
+ __m64 x4 = mx[2];
+ __m64 x6 = mx[3];
+ __m64 x8 = mx[4];
+
+ __m64 y0 = _mm_cvtsi32_si64(y[0]);
+ __m64 y1 = _mm_cvtsi32_si64(y[1]);
+ __m64 y4 = my[2];
+ __m64 y6 = my[3];
+ __m64 y8 = my[4];
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x0, y0);
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s3);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x1, y1);
+ s4 = _mm_add_si64(x4, y4);
+ s1 = _mm_add_si64(s1, w18);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w20);
+ s1 = _mm_add_si64(s1, s3);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x6, y6);
+ s4 = _mm_add_si64(x8, y8);
+ s1 = _mm_add_si64(s1, w22);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w26);
+ s1 = _mm_add_si64(s1, s3);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[7] = _mm_cvtsi64_si32(s1) + w[27] + x[10] + y[10] + x[12] + y[12];
+ _mm_empty();
+}
+
+#endif // #ifdef SSE2_INTRINSICS_AVAILABLE
+
+// end optimized
+
+// ********************************************************
+
+#define A0 A
+#define A1 (A+N2)
+#define B0 B
+#define B1 (B+N2)
+
+#define T0 T
+#define T1 (T+N2)
+#define T2 (T+N)
+#define T3 (T+N+N2)
+
+#define R0 R
+#define R1 (R+N2)
+#define R2 (R+N)
+#define R3 (R+N+N2)
+
+//VC60 workaround: compiler bug triggered without the extra dummy parameters
+
+// R[2*N] - result = A*B
+// T[2*N] - temporary work space
+// A[N] --- multiplier
+// B[N] --- multiplicant
+
+
+void RecursiveMultiply(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (LowLevel::MultiplyRecursionLimit() >= 8 && N==8)
+ LowLevel::Multiply8(R, A, B);
+ else if (LowLevel::MultiplyRecursionLimit() >= 4 && N==4)
+ LowLevel::Multiply4(R, A, B);
+ else if (N==2)
+ LowLevel::Multiply2(R, A, B);
+ else
+ {
+ const unsigned int N2 = N/2;
+ int carry;
+
+ int aComp = Compare(A0, A1, N2);
+ int bComp = Compare(B0, B1, N2);
+
+ switch (2*aComp + aComp + bComp)
+ {
+ case -4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R0, N2);
+ carry = -1;
+ break;
+ case -2:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 2:
+ LowLevel::Subtract(R0, A0, A1, N2);
+ LowLevel::Subtract(R1, B1, B0, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R1, N2);
+ carry = -1;
+ break;
+ default:
+ SetWords(T0, 0, N);
+ carry = 0;
+ }
+
+ RecursiveMultiply(R0, T2, A0, B0, N2);
+ RecursiveMultiply(R2, T2, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1),R[01] holds A0*B0, R[23] holds A1*B1
+
+ carry += LowLevel::Add(T0, T0, R0, N);
+ carry += LowLevel::Add(T0, T0, R2, N);
+ carry += LowLevel::Add(R1, R1, T0, N);
+
+ assert (carry >= 0 && carry <= 2);
+ Increment(R3, N2, carry);
+ }
+}
+
+
+void RecursiveSquare(word *R, word *T, const word *A, unsigned int N)
+{
+ assert(N && N%2==0);
+ if (LowLevel::SquareRecursionLimit() >= 8 && N==8)
+ LowLevel::Square8(R, A);
+ if (LowLevel::SquareRecursionLimit() >= 4 && N==4)
+ LowLevel::Square4(R, A);
+ else if (N==2)
+ LowLevel::Square2(R, A);
+ else
+ {
+ const unsigned int N2 = N/2;
+
+ RecursiveSquare(R0, T2, A0, N2);
+ RecursiveSquare(R2, T2, A1, N2);
+ RecursiveMultiply(T0, T2, A0, A1, N2);
+
+ word carry = LowLevel::Add(R1, R1, T0, N);
+ carry += LowLevel::Add(R1, R1, T0, N);
+ Increment(R3, N2, carry);
+ }
+}
+
+
+// R[N] - bottom half of A*B
+// T[N] - temporary work space
+// A[N] - multiplier
+// B[N] - multiplicant
+
+
+void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+ if (LowLevel::MultiplyBottomRecursionLimit() >= 8 && N==8)
+ LowLevel::Multiply8Bottom(R, A, B);
+ else if (LowLevel::MultiplyBottomRecursionLimit() >= 4 && N==4)
+ LowLevel::Multiply4Bottom(R, A, B);
+ else if (N==2)
+ LowLevel::Multiply2Bottom(R, A, B);
+ else
+ {
+ const unsigned int N2 = N/2;
+
+ RecursiveMultiply(R, T, A0, B0, N2);
+ RecursiveMultiplyBottom(T0, T1, A1, B0, N2);
+ LowLevel::Add(R1, R1, T0, N2);
+ RecursiveMultiplyBottom(T0, T1, A0, B1, N2);
+ LowLevel::Add(R1, R1, T0, N2);
+ }
+}
+
+
+void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A,
+ const word *B, unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (N==4)
+ {
+ LowLevel::Multiply4(T, A, B);
+ memcpy(R, T+4, 4*WORD_SIZE);
+ }
+ else if (N==2)
+ {
+ LowLevel::Multiply2(T, A, B);
+ memcpy(R, T+2, 2*WORD_SIZE);
+ }
+ else
+ {
+ const unsigned int N2 = N/2;
+ int carry;
+
+ int aComp = Compare(A0, A1, N2);
+ int bComp = Compare(B0, B1, N2);
+
+ switch (2*aComp + aComp + bComp)
+ {
+ case -4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R0, N2);
+ carry = -1;
+ break;
+ case -2:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 2:
+ LowLevel::Subtract(R0, A0, A1, N2);
+ LowLevel::Subtract(R1, B1, B0, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R1, N2);
+ carry = -1;
+ break;
+ default:
+ SetWords(T0, 0, N);
+ carry = 0;
+ }
+
+ RecursiveMultiply(T2, R0, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1), T[23] holds A1*B1
+
+ word c2 = LowLevel::Subtract(R0, L+N2, L, N2);
+ c2 += LowLevel::Subtract(R0, R0, T0, N2);
+ word t = (Compare(R0, T2, N2) == -1);
+
+ carry += t;
+ carry += Increment(R0, N2, c2+t);
+ carry += LowLevel::Add(R0, R0, T1, N2);
+ carry += LowLevel::Add(R0, R0, T3, N2);
+ assert (carry >= 0 && carry <= 2);
+
+ CopyWords(R1, T3, N2);
+ Increment(R1, N2, carry);
+ }
+}
+
+
+inline word Add(word *C, const word *A, const word *B, unsigned int N)
+{
+ return LowLevel::Add(C, A, B, N);
+}
+
+inline word Subtract(word *C, const word *A, const word *B, unsigned int N)
+{
+ return LowLevel::Subtract(C, A, B, N);
+}
+
+inline void Multiply(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ RecursiveMultiply(R, T, A, B, N);
+}
+
+inline void Square(word *R, word *T, const word *A, unsigned int N)
+{
+ RecursiveSquare(R, T, A, N);
+}
+
+
+void AsymmetricMultiply(word *R, word *T, const word *A, unsigned int NA,
+ const word *B, unsigned int NB)
+{
+ if (NA == NB)
+ {
+ if (A == B)
+ Square(R, T, A, NA);
+ else
+ Multiply(R, T, A, B, NA);
+
+ return;
+ }
+
+ if (NA > NB)
+ {
+ mySTL::swap(A, B);
+ mySTL::swap(NA, NB);
+ }
+
+ assert(NB % NA == 0);
+ assert((NB/NA)%2 == 0); // NB is an even multiple of NA
+
+ if (NA==2 && !A[1])
+ {
+ switch (A[0])
+ {
+ case 0:
+ SetWords(R, 0, NB+2);
+ return;
+ case 1:
+ CopyWords(R, B, NB);
+ R[NB] = R[NB+1] = 0;
+ return;
+ default:
+ R[NB] = LinearMultiply(R, B, A[0], NB);
+ R[NB+1] = 0;
+ return;
+ }
+ }
+
+ Multiply(R, T, A, B, NA);
+ CopyWords(T+2*NA, R+NA, NA);
+
+ unsigned i;
+
+ for (i=2*NA; i<NB; i+=2*NA)
+ Multiply(T+NA+i, T, A, B+i, NA);
+ for (i=NA; i<NB; i+=2*NA)
+ Multiply(R+i, T, A, B+i, NA);
+
+ if (Add(R+NA, R+NA, T+2*NA, NB-NA))
+ Increment(R+NB, NA);
+}
+
+
+void PositiveMultiply(Integer& product, const Integer& a, const Integer& b)
+{
+ unsigned int aSize = RoundupSize(a.WordCount());
+ unsigned int bSize = RoundupSize(b.WordCount());
+
+ product.reg_.CleanNew(RoundupSize(aSize + bSize));
+ product.sign_ = Integer::POSITIVE;
+
+ WordBlock workspace(aSize + bSize);
+ AsymmetricMultiply(product.reg_.get_buffer(), workspace.get_buffer(),
+ a.reg_.get_buffer(), aSize, b.reg_.get_buffer(), bSize);
+}
+
+void Multiply(Integer &product, const Integer &a, const Integer &b)
+{
+ PositiveMultiply(product, a, b);
+
+ if (a.NotNegative() != b.NotNegative())
+ product.Negate();
+}
+
+
+static inline unsigned int EvenWordCount(const word *X, unsigned int N)
+{
+ while (N && X[N-2]==0 && X[N-1]==0)
+ N-=2;
+ return N;
+}
+
+
+unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA,
+ const word *M, unsigned int N)
+{
+ assert(NA<=N && N && N%2==0);
+
+ word *b = T;
+ word *c = T+N;
+ word *f = T+2*N;
+ word *g = T+3*N;
+ unsigned int bcLen=2, fgLen=EvenWordCount(M, N);
+ unsigned int k=0, s=0;
+
+ SetWords(T, 0, 3*N);
+ b[0]=1;
+ CopyWords(f, A, NA);
+ CopyWords(g, M, N);
+
+ while (1)
+ {
+ word t=f[0];
+ while (!t)
+ {
+ if (EvenWordCount(f, fgLen)==0)
+ {
+ SetWords(R, 0, N);
+ return 0;
+ }
+
+ ShiftWordsRightByWords(f, fgLen, 1);
+ if (c[bcLen-1]) bcLen+=2;
+ assert(bcLen <= N);
+ ShiftWordsLeftByWords(c, bcLen, 1);
+ k+=WORD_BITS;
+ t=f[0];
+ }
+
+ unsigned int i=0;
+ while (t%2 == 0)
+ {
+ t>>=1;
+ i++;
+ }
+ k+=i;
+
+ if (t==1 && f[1]==0 && EvenWordCount(f, fgLen)==2)
+ {
+ if (s%2==0)
+ CopyWords(R, b, N);
+ else
+ Subtract(R, M, b, N);
+ return k;
+ }
+
+ ShiftWordsRightByBits(f, fgLen, i);
+ t=ShiftWordsLeftByBits(c, bcLen, i);
+ if (t)
+ {
+ c[bcLen] = t;
+ bcLen+=2;
+ assert(bcLen <= N);
+ }
+
+ if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0)
+ fgLen-=2;
+
+ if (Compare(f, g, fgLen)==-1)
+ {
+ mySTL::swap(f, g);
+ mySTL::swap(b, c);
+ s++;
+ }
+
+ Subtract(f, f, g, fgLen);
+
+ if (Add(b, b, c, bcLen))
+ {
+ b[bcLen] = 1;
+ bcLen+=2;
+ assert(bcLen <= N);
+ }
+ }
+}
+
+// R[N] - result = A/(2^k) mod M
+// A[N] - input
+// M[N] - modulus
+
+void DivideByPower2Mod(word *R, const word *A, unsigned int k, const word *M,
+ unsigned int N)
+{
+ CopyWords(R, A, N);
+
+ while (k--)
+ {
+ if (R[0]%2==0)
+ ShiftWordsRightByBits(R, N, 1);
+ else
+ {
+ word carry = Add(R, R, M, N);
+ ShiftWordsRightByBits(R, N, 1);
+ R[N-1] += carry<<(WORD_BITS-1);
+ }
+ }
+}
+
+// R[N] - result = A*(2^k) mod M
+// A[N] - input
+// M[N] - modulus
+
+void MultiplyByPower2Mod(word *R, const word *A, unsigned int k, const word *M,
+ unsigned int N)
+{
+ CopyWords(R, A, N);
+
+ while (k--)
+ if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0)
+ Subtract(R, R, M, N);
+}
+
+
+// ********** end of integer needs
+
+
+Integer::Integer()
+ : reg_(2), sign_(POSITIVE)
+{
+ reg_[0] = reg_[1] = 0;
+}
+
+
+Integer::Integer(const Integer& t)
+ : reg_(RoundupSize(t.WordCount())), sign_(t.sign_)
+{
+ CopyWords(reg_.get_buffer(), t.reg_.get_buffer(), reg_.size());
+}
+
+
+Integer::Integer(signed long value)
+ : reg_(2)
+{
+ if (value >= 0)
+ sign_ = POSITIVE;
+ else
+ {
+ sign_ = NEGATIVE;
+ value = -value;
+ }
+ reg_[0] = word(value);
+ reg_[1] = word(SafeRightShift<WORD_BITS, unsigned long>(value));
+}
+
+
+Integer::Integer(Sign s, word high, word low)
+ : reg_(2), sign_(s)
+{
+ reg_[0] = low;
+ reg_[1] = high;
+}
+
+
+Integer::Integer(word value, unsigned int length)
+ : reg_(RoundupSize(length)), sign_(POSITIVE)
+{
+ reg_[0] = value;
+ SetWords(reg_ + 1, 0, reg_.size() - 1);
+}
+
+
+Integer::Integer(const byte *encodedInteger, unsigned int byteCount,
+ Signedness s)
+{
+ Decode(encodedInteger, byteCount, s);
+}
+
+class BadBER {};
+
+// BER Decode Source
+Integer::Integer(Source& source)
+ : reg_(2), sign_(POSITIVE)
+{
+ Decode(source);
+}
+
+void Integer::Decode(Source& source)
+{
+ byte b = source.next();
+ if (b != INTEGER) {
+ source.SetError(INTEGER_E);
+ return;
+ }
+
+ word32 length = GetLength(source);
+
+ if ( (b = source.next()) == 0x00)
+ length--;
+ else
+ source.prev();
+
+ unsigned int words = (length + WORD_SIZE - 1) / WORD_SIZE;
+ words = RoundupSize(words);
+ if (words > reg_.size()) reg_.CleanNew(words);
+
+ for (int j = length; j > 0; j--) {
+ b = source.next();
+ reg_ [(j-1) / WORD_SIZE] |= (word)b << ((j-1) % WORD_SIZE) * 8;
+ }
+}
+
+
+void Integer::Decode(const byte* input, unsigned int inputLen, Signedness s)
+{
+ unsigned int idx(0);
+ byte b = input[idx++];
+ sign_ = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE;
+
+ while (inputLen>0 && (sign_==POSITIVE ? b==0 : b==0xff))
+ {
+ inputLen--;
+ b = input[idx++];
+ }
+
+ reg_.CleanNew(RoundupSize(BytesToWords(inputLen)));
+
+ --idx;
+ for (unsigned int i=inputLen; i > 0; i--)
+ {
+ b = input[idx++];
+ reg_[(i-1)/WORD_SIZE] |= (word)b << ((i-1)%WORD_SIZE)*8;
+ }
+
+ if (sign_ == NEGATIVE)
+ {
+ for (unsigned i=inputLen; i<reg_.size()*WORD_SIZE; i++)
+ reg_[i/WORD_SIZE] |= (word)0xff << (i%WORD_SIZE)*8;
+ TwosComplement(reg_.get_buffer(), reg_.size());
+ }
+}
+
+
+unsigned int Integer::Encode(byte* output, unsigned int outputLen,
+ Signedness signedness) const
+{
+ unsigned int idx(0);
+ if (signedness == UNSIGNED || NotNegative())
+ {
+ for (unsigned int i=outputLen; i > 0; i--)
+ output[idx++] = GetByte(i-1);
+ }
+ else
+ {
+ // take two's complement of *this
+ Integer temp = Integer::Power2(8*max(ByteCount(), outputLen)) + *this;
+ for (unsigned i=0; i<outputLen; i++)
+ output[idx++] = temp.GetByte(outputLen-i-1);
+ }
+ return outputLen;
+}
+
+
+const Integer Integer::zero_;
+
+const Integer &Integer::Zero()
+{
+ return zero_;
+}
+
+
+const Integer Integer::one_(1,2);
+
+const Integer &Integer::One()
+{
+ return one_;
+}
+
+
+Integer::Integer(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max)
+{
+ Randomize(rng, min, max);
+}
+
+
+void Integer::Randomize(RandomNumberGenerator& rng, unsigned int nbits)
+{
+ const unsigned int nbytes = nbits/8 + 1;
+ ByteBlock buf(nbytes);
+ rng.GenerateBlock(buf.get_buffer(), nbytes);
+ if (nbytes)
+ buf[0] = (byte)Crop(buf[0], nbits % 8);
+ Decode(buf.get_buffer(), nbytes, UNSIGNED);
+}
+
+void Integer::Randomize(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max)
+{
+ assert(min <= max);
+
+ Integer range = max - min;
+ const unsigned int nbits = range.BitCount();
+
+ do
+ {
+ Randomize(rng, nbits);
+ }
+ while (*this > range);
+
+ *this += min;
+}
+
+
+Integer Integer::Power2(unsigned int e)
+{
+ Integer r((word)0, BitsToWords(e + 1));
+ r.SetBit(e);
+ return r;
+}
+
+
+void Integer::SetBit(unsigned int n, bool value)
+{
+ if (value)
+ {
+ reg_.CleanGrow(RoundupSize(BitsToWords(n + 1)));
+ reg_[n / WORD_BITS] |= (word(1) << (n % WORD_BITS));
+ }
+ else
+ {
+ if (n / WORD_BITS < reg_.size())
+ reg_[n / WORD_BITS] &= ~(word(1) << (n % WORD_BITS));
+ }
+}
+
+
+void Integer::SetByte(unsigned int n, byte value)
+{
+ reg_.CleanGrow(RoundupSize(BytesToWords(n+1)));
+ reg_[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
+ reg_[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
+}
+
+
+void Integer::Negate()
+{
+ if (!!(*this)) // don't flip sign if *this==0
+ sign_ = Sign(1 - sign_);
+}
+
+
+bool Integer::operator!() const
+{
+ return IsNegative() ? false : (reg_[0]==0 && WordCount()==0);
+}
+
+
+Integer& Integer::operator=(const Integer& t)
+{
+ if (this != &t)
+ {
+ reg_.New(RoundupSize(t.WordCount()));
+ CopyWords(reg_.get_buffer(), t.reg_.get_buffer(), reg_.size());
+ sign_ = t.sign_;
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator+=(const Integer& t)
+{
+ reg_.CleanGrow(t.reg_.size());
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ PositiveAdd(*this, *this, t);
+ else
+ PositiveSubtract(*this, *this, t);
+ }
+ else
+ {
+ if (t.NotNegative())
+ PositiveSubtract(*this, t, *this);
+ else
+ {
+ PositiveAdd(*this, *this, t);
+ sign_ = Integer::NEGATIVE;
+ }
+ }
+ return *this;
+}
+
+
+Integer Integer::operator-() const
+{
+ Integer result(*this);
+ result.Negate();
+ return result;
+}
+
+
+Integer& Integer::operator-=(const Integer& t)
+{
+ reg_.CleanGrow(t.reg_.size());
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ PositiveSubtract(*this, *this, t);
+ else
+ PositiveAdd(*this, *this, t);
+ }
+ else
+ {
+ if (t.NotNegative())
+ {
+ PositiveAdd(*this, *this, t);
+ sign_ = Integer::NEGATIVE;
+ }
+ else
+ PositiveSubtract(*this, t, *this);
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator++()
+{
+ if (NotNegative())
+ {
+ if (Increment(reg_.get_buffer(), reg_.size()))
+ {
+ reg_.CleanGrow(2*reg_.size());
+ reg_[reg_.size()/2]=1;
+ }
+ }
+ else
+ {
+ word borrow = Decrement(reg_.get_buffer(), reg_.size());
+ assert(!borrow);
+ if (WordCount()==0)
+ *this = Zero();
+ }
+ return *this;
+}
+
+Integer& Integer::operator--()
+{
+ if (IsNegative())
+ {
+ if (Increment(reg_.get_buffer(), reg_.size()))
+ {
+ reg_.CleanGrow(2*reg_.size());
+ reg_[reg_.size()/2]=1;
+ }
+ }
+ else
+ {
+ if (Decrement(reg_.get_buffer(), reg_.size()))
+ *this = -One();
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator<<=(unsigned int n)
+{
+ const unsigned int wordCount = WordCount();
+ const unsigned int shiftWords = n / WORD_BITS;
+ const unsigned int shiftBits = n % WORD_BITS;
+
+ reg_.CleanGrow(RoundupSize(wordCount+BitsToWords(n)));
+ ShiftWordsLeftByWords(reg_.get_buffer(), wordCount + shiftWords,
+ shiftWords);
+ ShiftWordsLeftByBits(reg_+shiftWords, wordCount+BitsToWords(shiftBits),
+ shiftBits);
+ return *this;
+}
+
+Integer& Integer::operator>>=(unsigned int n)
+{
+ const unsigned int wordCount = WordCount();
+ const unsigned int shiftWords = n / WORD_BITS;
+ const unsigned int shiftBits = n % WORD_BITS;
+
+ ShiftWordsRightByWords(reg_.get_buffer(), wordCount, shiftWords);
+ if (wordCount > shiftWords)
+ ShiftWordsRightByBits(reg_.get_buffer(), wordCount-shiftWords,
+ shiftBits);
+ if (IsNegative() && WordCount()==0) // avoid -0
+ *this = Zero();
+ return *this;
+}
+
+
+void PositiveAdd(Integer& sum, const Integer& a, const Integer& b)
+{
+ word carry;
+ if (a.reg_.size() == b.reg_.size())
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size());
+ else if (a.reg_.size() > b.reg_.size())
+ {
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), b.reg_.size());
+ CopyWords(sum.reg_+b.reg_.size(), a.reg_+b.reg_.size(),
+ a.reg_.size()-b.reg_.size());
+ carry = Increment(sum.reg_+b.reg_.size(), a.reg_.size()-b.reg_.size(),
+ carry);
+ }
+ else
+ {
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size());
+ CopyWords(sum.reg_+a.reg_.size(), b.reg_+a.reg_.size(),
+ b.reg_.size()-a.reg_.size());
+ carry = Increment(sum.reg_+a.reg_.size(), b.reg_.size()-a.reg_.size(),
+ carry);
+ }
+
+ if (carry)
+ {
+ sum.reg_.CleanGrow(2*sum.reg_.size());
+ sum.reg_[sum.reg_.size()/2] = 1;
+ }
+ sum.sign_ = Integer::POSITIVE;
+}
+
+void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b)
+{
+ unsigned aSize = a.WordCount();
+ aSize += aSize%2;
+ unsigned bSize = b.WordCount();
+ bSize += bSize%2;
+
+ if (aSize == bSize)
+ {
+ if (Compare(a.reg_.get_buffer(), b.reg_.get_buffer(), aSize) >= 0)
+ {
+ Subtract(diff.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), aSize);
+ diff.sign_ = Integer::POSITIVE;
+ }
+ else
+ {
+ Subtract(diff.reg_.get_buffer(), b.reg_.get_buffer(),
+ a.reg_.get_buffer(), aSize);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+ }
+ else if (aSize > bSize)
+ {
+ word borrow = Subtract(diff.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), bSize);
+ CopyWords(diff.reg_+bSize, a.reg_+bSize, aSize-bSize);
+ borrow = Decrement(diff.reg_+bSize, aSize-bSize, borrow);
+ assert(!borrow);
+ diff.sign_ = Integer::POSITIVE;
+ }
+ else
+ {
+ word borrow = Subtract(diff.reg_.get_buffer(), b.reg_.get_buffer(),
+ a.reg_.get_buffer(), aSize);
+ CopyWords(diff.reg_+aSize, b.reg_+aSize, bSize-aSize);
+ borrow = Decrement(diff.reg_+aSize, bSize-aSize, borrow);
+ assert(!borrow);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+}
+
+
+unsigned int Integer::MinEncodedSize(Signedness signedness) const
+{
+ unsigned int outputLen = max(1U, ByteCount());
+ if (signedness == UNSIGNED)
+ return outputLen;
+ if (NotNegative() && (GetByte(outputLen-1) & 0x80))
+ outputLen++;
+ if (IsNegative() && *this < -Power2(outputLen*8-1))
+ outputLen++;
+ return outputLen;
+}
+
+
+int Integer::Compare(const Integer& t) const
+{
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ return PositiveCompare(t);
+ else
+ return 1;
+ }
+ else
+ {
+ if (t.NotNegative())
+ return -1;
+ else
+ return -PositiveCompare(t);
+ }
+}
+
+
+int Integer::PositiveCompare(const Integer& t) const
+{
+ unsigned size = WordCount(), tSize = t.WordCount();
+
+ if (size == tSize)
+ return TaoCrypt::Compare(reg_.get_buffer(), t.reg_.get_buffer(), size);
+ else
+ return size > tSize ? 1 : -1;
+}
+
+
+bool Integer::GetBit(unsigned int n) const
+{
+ if (n/WORD_BITS >= reg_.size())
+ return 0;
+ else
+ return bool((reg_[n/WORD_BITS] >> (n % WORD_BITS)) & 1);
+}
+
+
+unsigned long Integer::GetBits(unsigned int i, unsigned int n) const
+{
+ assert(n <= sizeof(unsigned long)*8);
+ unsigned long v = 0;
+ for (unsigned int j=0; j<n; j++)
+ v |= GetBit(i+j) << j;
+ return v;
+}
+
+
+byte Integer::GetByte(unsigned int n) const
+{
+ if (n/WORD_SIZE >= reg_.size())
+ return 0;
+ else
+ return byte(reg_[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
+}
+
+
+unsigned int Integer::BitCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_BITS + BitPrecision(reg_[wordCount-1]);
+ else
+ return 0;
+}
+
+
+unsigned int Integer::ByteCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_SIZE + BytePrecision(reg_[wordCount-1]);
+ else
+ return 0;
+}
+
+
+unsigned int Integer::WordCount() const
+{
+ return CountWords(reg_.get_buffer(), reg_.size());
+}
+
+
+bool Integer::IsConvertableToLong() const
+{
+ if (ByteCount() > sizeof(long))
+ return false;
+
+ unsigned long value = reg_[0];
+ value += SafeLeftShift<WORD_BITS, unsigned long>(reg_[1]);
+
+ if (sign_ == POSITIVE)
+ return (signed long)value >= 0;
+ else
+ return -(signed long)value < 0;
+}
+
+
+signed long Integer::ConvertToLong() const
+{
+ assert(IsConvertableToLong());
+
+ unsigned long value = reg_[0];
+ value += SafeLeftShift<WORD_BITS, unsigned long>(reg_[1]);
+ return sign_ == POSITIVE ? value : -(signed long)value;
+}
+
+
+void Integer::Swap(Integer& a)
+{
+ reg_.Swap(a.reg_);
+ mySTL::swap(sign_, a.sign_);
+}
+
+
+Integer Integer::Plus(const Integer& b) const
+{
+ Integer sum((word)0, max(reg_.size(), b.reg_.size()));
+ if (NotNegative())
+ {
+ if (b.NotNegative())
+ PositiveAdd(sum, *this, b);
+ else
+ PositiveSubtract(sum, *this, b);
+ }
+ else
+ {
+ if (b.NotNegative())
+ PositiveSubtract(sum, b, *this);
+ else
+ {
+ PositiveAdd(sum, *this, b);
+ sum.sign_ = Integer::NEGATIVE;
+ }
+ }
+ return sum;
+}
+
+
+Integer Integer::Minus(const Integer& b) const
+{
+ Integer diff((word)0, max(reg_.size(), b.reg_.size()));
+ if (NotNegative())
+ {
+ if (b.NotNegative())
+ PositiveSubtract(diff, *this, b);
+ else
+ PositiveAdd(diff, *this, b);
+ }
+ else
+ {
+ if (b.NotNegative())
+ {
+ PositiveAdd(diff, *this, b);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+ else
+ PositiveSubtract(diff, b, *this);
+ }
+ return diff;
+}
+
+
+Integer Integer::Times(const Integer &b) const
+{
+ Integer product;
+ Multiply(product, *this, b);
+ return product;
+}
+
+
+#undef A0
+#undef A1
+#undef B0
+#undef B1
+
+#undef T0
+#undef T1
+#undef T2
+#undef T3
+
+#undef R0
+#undef R1
+#undef R2
+#undef R3
+
+
+static inline void AtomicDivide(word *Q, const word *A, const word *B)
+{
+ word T[4];
+ DWord q = DivideFourWordsByTwo<word, DWord>(T, DWord(A[0], A[1]),
+ DWord(A[2], A[3]), DWord(B[0], B[1]));
+ Q[0] = q.GetLowHalf();
+ Q[1] = q.GetHighHalf();
+
+#ifndef NDEBUG
+ if (B[0] || B[1])
+ {
+ // multiply quotient and divisor and add remainder, make sure it
+ // equals dividend
+ assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0])));
+ word P[4];
+ Portable::Multiply2(P, Q, B);
+ Add(P, P, T, 4);
+ assert(memcmp(P, A, 4*WORD_SIZE)==0);
+ }
+#endif
+}
+
+
+// for use by Divide(), corrects the underestimated quotient {Q1,Q0}
+static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B,
+ unsigned int N)
+{
+ assert(N && N%2==0);
+
+ if (Q[1])
+ {
+ T[N] = T[N+1] = 0;
+ unsigned i;
+ for (i=0; i<N; i+=4)
+ LowLevel::Multiply2(T+i, Q, B+i);
+ for (i=2; i<N; i+=4)
+ if (LowLevel::Multiply2Add(T+i, Q, B+i))
+ T[i+5] += (++T[i+4]==0);
+ }
+ else
+ {
+ T[N] = LinearMultiply(T, B, Q[0], N);
+ T[N+1] = 0;
+ }
+
+ word borrow = Subtract(R, R, T, N+2);
+ assert(!borrow && !R[N+1]);
+
+ while (R[N] || Compare(R, B, N) >= 0)
+ {
+ R[N] -= Subtract(R, R, B, N);
+ Q[1] += (++Q[0]==0);
+ assert(Q[0] || Q[1]); // no overflow
+ }
+}
+
+// R[NB] -------- remainder = A%B
+// Q[NA-NB+2] --- quotient = A/B
+// T[NA+2*NB+4] - temp work space
+// A[NA] -------- dividend
+// B[NB] -------- divisor
+
+
+void Divide(word* R, word* Q, word* T, const word* A, unsigned int NA,
+ const word* B, unsigned int NB)
+{
+ assert(NA && NB && NA%2==0 && NB%2==0);
+ assert(B[NB-1] || B[NB-2]);
+ assert(NB <= NA);
+
+ // set up temporary work space
+ word *const TA=T;
+ word *const TB=T+NA+2;
+ word *const TP=T+NA+2+NB;
+
+ // copy B into TB and normalize it so that TB has highest bit set to 1
+ unsigned shiftWords = (B[NB-1]==0);
+ TB[0] = TB[NB-1] = 0;
+ CopyWords(TB+shiftWords, B, NB-shiftWords);
+ unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]);
+ assert(shiftBits < WORD_BITS);
+ ShiftWordsLeftByBits(TB, NB, shiftBits);
+
+ // copy A into TA and normalize it
+ TA[0] = TA[NA] = TA[NA+1] = 0;
+ CopyWords(TA+shiftWords, A, NA);
+ ShiftWordsLeftByBits(TA, NA+2, shiftBits);
+
+ if (TA[NA+1]==0 && TA[NA] <= 1)
+ {
+ Q[NA-NB+1] = Q[NA-NB] = 0;
+ while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0)
+ {
+ TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB);
+ ++Q[NA-NB];
+ }
+ }
+ else
+ {
+ NA+=2;
+ assert(Compare(TA+NA-NB, TB, NB) < 0);
+ }
+
+ word BT[2];
+ BT[0] = TB[NB-2] + 1;
+ BT[1] = TB[NB-1] + (BT[0]==0);
+
+ // start reducing TA mod TB, 2 words at a time
+ for (unsigned i=NA-2; i>=NB; i-=2)
+ {
+ AtomicDivide(Q+i-NB, TA+i-2, BT);
+ CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB);
+ }
+
+ // copy TA into R, and denormalize it
+ CopyWords(R, TA+shiftWords, NB);
+ ShiftWordsRightByBits(R, NB, shiftBits);
+}
+
+
+void PositiveDivide(Integer& remainder, Integer& quotient,
+ const Integer& a, const Integer& b)
+{
+ unsigned aSize = a.WordCount();
+ unsigned bSize = b.WordCount();
+
+ assert(bSize);
+
+ if (a.PositiveCompare(b) == -1)
+ {
+ remainder = a;
+ remainder.sign_ = Integer::POSITIVE;
+ quotient = Integer::Zero();
+ return;
+ }
+
+ aSize += aSize%2; // round up to next even number
+ bSize += bSize%2;
+
+ remainder.reg_.CleanNew(RoundupSize(bSize));
+ remainder.sign_ = Integer::POSITIVE;
+ quotient.reg_.CleanNew(RoundupSize(aSize-bSize+2));
+ quotient.sign_ = Integer::POSITIVE;
+
+ WordBlock T(aSize+2*bSize+4);
+ Divide(remainder.reg_.get_buffer(), quotient.reg_.get_buffer(),
+ T.get_buffer(), a.reg_.get_buffer(), aSize, b.reg_.get_buffer(),
+ bSize);
+}
+
+void Integer::Divide(Integer &remainder, Integer &quotient,
+ const Integer &dividend, const Integer &divisor)
+{
+ PositiveDivide(remainder, quotient, dividend, divisor);
+
+ if (dividend.IsNegative())
+ {
+ quotient.Negate();
+ if (remainder.NotZero())
+ {
+ --quotient;
+ remainder = divisor.AbsoluteValue() - remainder;
+ }
+ }
+
+ if (divisor.IsNegative())
+ quotient.Negate();
+}
+
+void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a,
+ unsigned int n)
+{
+ q = a;
+ q >>= n;
+
+ const unsigned int wordCount = BitsToWords(n);
+ if (wordCount <= a.WordCount())
+ {
+ r.reg_.resize(RoundupSize(wordCount));
+ CopyWords(r.reg_.get_buffer(), a.reg_.get_buffer(), wordCount);
+ SetWords(r.reg_+wordCount, 0, r.reg_.size()-wordCount);
+ if (n % WORD_BITS != 0)
+ r.reg_[wordCount-1] %= (1 << (n % WORD_BITS));
+ }
+ else
+ {
+ r.reg_.resize(RoundupSize(a.WordCount()));
+ CopyWords(r.reg_.get_buffer(), a.reg_.get_buffer(), r.reg_.size());
+ }
+ r.sign_ = POSITIVE;
+
+ if (a.IsNegative() && r.NotZero())
+ {
+ --q;
+ r = Power2(n) - r;
+ }
+}
+
+Integer Integer::DividedBy(const Integer &b) const
+{
+ Integer remainder, quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+Integer Integer::Modulo(const Integer &b) const
+{
+ Integer remainder, quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return remainder;
+}
+
+void Integer::Divide(word &remainder, Integer &quotient,
+ const Integer &dividend, word divisor)
+{
+ assert(divisor);
+
+ if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
+ {
+ quotient = dividend >> (BitPrecision(divisor)-1);
+ remainder = dividend.reg_[0] & (divisor-1);
+ return;
+ }
+
+ unsigned int i = dividend.WordCount();
+ quotient.reg_.CleanNew(RoundupSize(i));
+ remainder = 0;
+ while (i--)
+ {
+ quotient.reg_[i] = DWord(dividend.reg_[i], remainder) / divisor;
+ remainder = DWord(dividend.reg_[i], remainder) % divisor;
+ }
+
+ if (dividend.NotNegative())
+ quotient.sign_ = POSITIVE;
+ else
+ {
+ quotient.sign_ = NEGATIVE;
+ if (remainder)
+ {
+ --quotient;
+ remainder = divisor - remainder;
+ }
+ }
+}
+
+Integer Integer::DividedBy(word b) const
+{
+ word remainder;
+ Integer quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+word Integer::Modulo(word divisor) const
+{
+ assert(divisor);
+
+ word remainder;
+
+ if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
+ remainder = reg_[0] & (divisor-1);
+ else
+ {
+ unsigned int i = WordCount();
+
+ if (divisor <= 5)
+ {
+ DWord sum(0, 0);
+ while (i--)
+ sum += reg_[i];
+ remainder = sum % divisor;
+ }
+ else
+ {
+ remainder = 0;
+ while (i--)
+ remainder = DWord(reg_[i], remainder) % divisor;
+ }
+ }
+
+ if (IsNegative() && remainder)
+ remainder = divisor - remainder;
+
+ return remainder;
+}
+
+
+Integer Integer::AbsoluteValue() const
+{
+ Integer result(*this);
+ result.sign_ = POSITIVE;
+ return result;
+}
+
+
+Integer Integer::SquareRoot() const
+{
+ if (!IsPositive())
+ return Zero();
+
+ // overestimate square root
+ Integer x, y = Power2((BitCount()+1)/2);
+ assert(y*y >= *this);
+
+ do
+ {
+ x = y;
+ y = (x + *this/x) >> 1;
+ } while (y<x);
+
+ return x;
+}
+
+bool Integer::IsSquare() const
+{
+ Integer r = SquareRoot();
+ return *this == r.Squared();
+}
+
+bool Integer::IsUnit() const
+{
+ return (WordCount() == 1) && (reg_[0] == 1);
+}
+
+Integer Integer::MultiplicativeInverse() const
+{
+ return IsUnit() ? *this : Zero();
+}
+
+Integer a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m)
+{
+ return x*y%m;
+}
+
+Integer a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m)
+{
+ ModularArithmetic mr(m);
+ return mr.Exponentiate(x, e);
+}
+
+Integer Integer::Gcd(const Integer &a, const Integer &b)
+{
+ return EuclideanDomainOf().Gcd(a, b);
+}
+
+Integer Integer::InverseMod(const Integer &m) const
+{
+ assert(m.NotNegative());
+
+ if (IsNegative() || *this>=m)
+ return (*this%m).InverseMod(m);
+
+ if (m.IsEven())
+ {
+ if (!m || IsEven())
+ return Zero(); // no inverse
+ if (*this == One())
+ return One();
+
+ Integer u = m.InverseMod(*this);
+ return !u ? Zero() : (m*(*this-u)+1)/(*this);
+ }
+
+ WordBlock T(m.reg_.size() * 4);
+ Integer r((word)0, m.reg_.size());
+ unsigned k = AlmostInverse(r.reg_.get_buffer(), T.get_buffer(),
+ reg_.get_buffer(), reg_.size(),
+ m.reg_.get_buffer(), m.reg_.size());
+ DivideByPower2Mod(r.reg_.get_buffer(), r.reg_.get_buffer(), k,
+ m.reg_.get_buffer(), m.reg_.size());
+ return r;
+}
+
+word Integer::InverseMod(const word mod) const
+{
+ word g0 = mod, g1 = *this % mod;
+ word v0 = 0, v1 = 1;
+ word y;
+
+ while (g1)
+ {
+ if (g1 == 1)
+ return v1;
+ y = g0 / g1;
+ g0 = g0 % g1;
+ v0 += y * v1;
+
+ if (!g0)
+ break;
+ if (g0 == 1)
+ return mod-v0;
+ y = g1 / g0;
+ g1 = g1 % g0;
+ v1 += y * v0;
+ }
+ return 0;
+}
+
+// ********* ModArith stuff
+
+const Integer& ModularArithmetic::Half(const Integer &a) const
+{
+ if (a.reg_.size()==modulus.reg_.size())
+ {
+ TaoCrypt::DivideByPower2Mod(result.reg_.begin(), a.reg_.begin(), 1,
+ modulus.reg_.begin(), a.reg_.size());
+ return result;
+ }
+ else
+ return result1 = (a.IsEven() ? (a >> 1) : ((a+modulus) >> 1));
+}
+
+const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Add(result.reg_.begin(), a.reg_.begin(), b.reg_.begin(),
+ a.reg_.size())
+ || Compare(result.reg_.get_buffer(), modulus.reg_.get_buffer(),
+ a.reg_.size()) >= 0)
+ {
+ TaoCrypt::Subtract(result.reg_.begin(), result.reg_.begin(),
+ modulus.reg_.begin(), a.reg_.size());
+ }
+ return result;
+ }
+ else
+ {
+ result1 = a+b;
+ if (result1 >= modulus)
+ result1 -= modulus;
+ return result1;
+ }
+}
+
+Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Add(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size())
+ || Compare(a.reg_.get_buffer(), modulus.reg_.get_buffer(),
+ a.reg_.size()) >= 0)
+ {
+ TaoCrypt::Subtract(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ modulus.reg_.get_buffer(), a.reg_.size());
+ }
+ }
+ else
+ {
+ a+=b;
+ if (a>=modulus)
+ a-=modulus;
+ }
+
+ return a;
+}
+
+const Integer& ModularArithmetic::Subtract(const Integer &a,
+ const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Subtract(result.reg_.begin(), a.reg_.begin(),
+ b.reg_.begin(), a.reg_.size()))
+ TaoCrypt::Add(result.reg_.begin(), result.reg_.begin(),
+ modulus.reg_.begin(), a.reg_.size());
+ return result;
+ }
+ else
+ {
+ result1 = a-b;
+ if (result1.IsNegative())
+ result1 += modulus;
+ return result1;
+ }
+}
+
+Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Subtract(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size()))
+ TaoCrypt::Add(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ modulus.reg_.get_buffer(), a.reg_.size());
+ }
+ else
+ {
+ a-=b;
+ if (a.IsNegative())
+ a+=modulus;
+ }
+
+ return a;
+}
+
+const Integer& ModularArithmetic::Inverse(const Integer &a) const
+{
+ if (!a)
+ return a;
+
+ CopyWords(result.reg_.begin(), modulus.reg_.begin(), modulus.reg_.size());
+ if (TaoCrypt::Subtract(result.reg_.begin(), result.reg_.begin(),
+ a.reg_.begin(), a.reg_.size()))
+ Decrement(result.reg_.begin()+a.reg_.size(), 1,
+ modulus.reg_.size()-a.reg_.size());
+
+ return result;
+}
+
+Integer ModularArithmetic::CascadeExponentiate(const Integer &x,
+ const Integer &e1, const Integer &y, const Integer &e2) const
+{
+ if (modulus.IsOdd())
+ {
+ MontgomeryRepresentation dr(modulus);
+ return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1,
+ dr.ConvertIn(y), e2));
+ }
+ else
+ return AbstractRing::CascadeExponentiate(x, e1, y, e2);
+}
+
+void ModularArithmetic::SimultaneousExponentiate(Integer *results,
+ const Integer &base, const Integer *exponents,
+ unsigned int exponentsCount) const
+{
+ if (modulus.IsOdd())
+ {
+ MontgomeryRepresentation dr(modulus);
+ dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents,
+ exponentsCount);
+ for (unsigned int i=0; i<exponentsCount; i++)
+ results[i] = dr.ConvertOut(results[i]);
+ }
+ else
+ AbstractRing::SimultaneousExponentiate(results, base,
+ exponents, exponentsCount);
+}
+
+
+// ********************************************************
+
+#define A0 A
+#define A1 (A+N2)
+#define B0 B
+#define B1 (B+N2)
+
+#define T0 T
+#define T1 (T+N2)
+#define T2 (T+N)
+#define T3 (T+N+N2)
+
+#define R0 R
+#define R1 (R+N2)
+#define R2 (R+N)
+#define R3 (R+N+N2)
+
+
+inline void MultiplyBottom(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ RecursiveMultiplyBottom(R, T, A, B, N);
+}
+
+inline void MultiplyTop(word *R, word *T, const word *L, const word *A,
+ const word *B, unsigned int N)
+{
+ RecursiveMultiplyTop(R, T, L, A, B, N);
+}
+
+
+// R[N] --- result = X/(2**(WORD_BITS*N)) mod M
+// T[3*N] - temporary work space
+// X[2*N] - number to be reduced
+// M[N] --- modulus
+// U[N] --- multiplicative inverse of M mod 2**(WORD_BITS*N)
+
+void MontgomeryReduce(word *R, word *T, const word *X, const word *M,
+ const word *U, unsigned int N)
+{
+ MultiplyBottom(R, T, X, U, N);
+ MultiplyTop(T, T+N, X, R, M, N);
+ word borrow = Subtract(T, X+N, T, N);
+ // defend against timing attack by doing this Add even when not needed
+ word carry = Add(T+N, T, M, N);
+ assert(carry || !borrow);
+ CopyWords(R, T + (borrow ? N : 0), N);
+}
+
+// R[N] ----- result = A inverse mod 2**(WORD_BITS*N)
+// T[3*N/2] - temporary work space
+// A[N] ----- an odd number as input
+
+void RecursiveInverseModPower2(word *R, word *T, const word *A, unsigned int N)
+{
+ if (N==2)
+ {
+ T[0] = AtomicInverseModPower2(A[0]);
+ T[1] = 0;
+ LowLevel::Multiply2Bottom(T+2, T, A);
+ TwosComplement(T+2, 2);
+ Increment(T+2, 2, 2);
+ LowLevel::Multiply2Bottom(R, T, T+2);
+ }
+ else
+ {
+ const unsigned int N2 = N/2;
+ RecursiveInverseModPower2(R0, T0, A0, N2);
+ T0[0] = 1;
+ SetWords(T0+1, 0, N2-1);
+ MultiplyTop(R1, T1, T0, R0, A0, N2);
+ MultiplyBottom(T0, T1, R0, A1, N2);
+ Add(T0, R1, T0, N2);
+ TwosComplement(T0, N2);
+ MultiplyBottom(R1, T1, R0, T0, N2);
+ }
+}
+
+
+#undef A0
+#undef A1
+#undef B0
+#undef B1
+
+#undef T0
+#undef T1
+#undef T2
+#undef T3
+
+#undef R0
+#undef R1
+#undef R2
+#undef R3
+
+
+// modulus must be odd
+MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m)
+ : ModularArithmetic(m),
+ u((word)0, modulus.reg_.size()),
+ workspace(5*modulus.reg_.size())
+{
+ assert(modulus.IsOdd());
+ RecursiveInverseModPower2(u.reg_.get_buffer(), workspace.get_buffer(),
+ modulus.reg_.get_buffer(), modulus.reg_.size());
+}
+
+const Integer& MontgomeryRepresentation::Multiply(const Integer &a,
+ const Integer &b) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N && b.reg_.size()<=N);
+
+ AsymmetricMultiply(T, T+2*N, a.reg_.get_buffer(), a.reg_.size(),
+ b.reg_.get_buffer(), b.reg_.size());
+ SetWords(T+a.reg_.size()+b.reg_.size(),0, 2*N-a.reg_.size()-b.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+const Integer& MontgomeryRepresentation::Square(const Integer &a) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ TaoCrypt::Square(T, T+2*N, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+2*a.reg_.size(), 0, 2*N-2*a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ CopyWords(T, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+a.reg_.size(), 0, 2*N-a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+const Integer& MontgomeryRepresentation::MultiplicativeInverse(
+ const Integer &a) const
+{
+// return (EuclideanMultiplicativeInverse(a, modulus)<<
+// (2*WORD_BITS*modulus.reg_.size()))%modulus;
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ CopyWords(T, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+a.reg_.size(), 0, 2*N-a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ unsigned k = AlmostInverse(R, T, R, N, modulus.reg_.get_buffer(), N);
+
+// cout << "k=" << k << " N*32=" << 32*N << endl;
+
+ if (k>N*WORD_BITS)
+ DivideByPower2Mod(R, R, k-N*WORD_BITS, modulus.reg_.get_buffer(), N);
+ else
+ MultiplyByPower2Mod(R, R, N*WORD_BITS-k, modulus.reg_.get_buffer(), N);
+
+ return result;
+}
+
+
+// mod Root stuff
+Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
+ const Integer &p, const Integer &q, const Integer &u)
+{
+ Integer p2 = ModularExponentiation((a % p), dp, p);
+ Integer q2 = ModularExponentiation((a % q), dq, q);
+ return CRT(p2, p, q2, q, u);
+}
+
+Integer CRT(const Integer &xp, const Integer &p, const Integer &xq,
+ const Integer &q, const Integer &u)
+{
+ // isn't operator overloading great?
+ return p * (u * (xq-xp) % q) + xp;
+}
+
+
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+#ifndef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+template hword DivideThreeWordsByTwo<hword, Word>(hword*, hword, hword, Word*);
+#endif
+template word DivideThreeWordsByTwo<word, DWord>(word*, word, word, DWord*);
+#endif
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/md2.cpp b/extra/yassl/taocrypt/src/md2.cpp
new file mode 100644
index 00000000000..16834b6bc89
--- /dev/null
+++ b/extra/yassl/taocrypt/src/md2.cpp
@@ -0,0 +1,128 @@
+/* md2.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* based on Wei Dai's md2.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "md2.hpp"
+#include <string.h>
+
+namespace TaoCrypt {
+
+
+MD2::MD2()
+ : X_(X_SIZE), C_(BLOCK_SIZE), buffer_(BLOCK_SIZE)
+{
+ Init();
+}
+
+void MD2::Init()
+{
+ memset(X_.get_buffer(), 0, X_SIZE);
+ memset(C_.get_buffer(), 0, BLOCK_SIZE);
+ memset(buffer_.get_buffer(), 0, BLOCK_SIZE);
+ count_ = 0;
+}
+
+
+void MD2::Update(const byte* data, word32 len)
+{
+
+ static const byte S[256] =
+ {
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+ };
+
+ while (len) {
+ word32 L = (PAD_SIZE - count_) < len ? (PAD_SIZE - count_) : len;
+ memcpy(buffer_.get_buffer() + count_, data, L);
+ count_ += L;
+ data += L;
+ len -= L;
+
+ if (count_==PAD_SIZE) {
+ count_ = 0;
+ memcpy(X_.get_buffer() + PAD_SIZE, buffer_.get_buffer(), PAD_SIZE);
+ byte t = C_[15];
+
+ int i;
+ for(i = 0; i < PAD_SIZE; i++) {
+ X_[32 + i] = X_[PAD_SIZE + i] ^ X_[i];
+ t = C_[i] ^= S[buffer_[i] ^ t];
+ }
+
+ t=0;
+ for(i = 0; i < 18; i++) {
+ for(int j = 0; j < X_SIZE; j += 8) {
+ t = X_[j+0] ^= S[t];
+ t = X_[j+1] ^= S[t];
+ t = X_[j+2] ^= S[t];
+ t = X_[j+3] ^= S[t];
+ t = X_[j+4] ^= S[t];
+ t = X_[j+5] ^= S[t];
+ t = X_[j+6] ^= S[t];
+ t = X_[j+7] ^= S[t];
+ }
+ t = (t + i) & 0xFF;
+ }
+ }
+ }
+}
+
+
+void MD2::Final(byte *hash)
+{
+ byte padding[BLOCK_SIZE];
+ word32 padLen = PAD_SIZE - count_;
+
+ for (word32 i = 0; i < padLen; i++)
+ padding[i] = static_cast<byte>(padLen);
+
+ Update(padding, padLen);
+ Update(C_.get_buffer(), BLOCK_SIZE);
+
+ memcpy(hash, X_.get_buffer(), DIGEST_SIZE);
+
+ Init();
+}
+
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp
new file mode 100644
index 00000000000..1c240b43adf
--- /dev/null
+++ b/extra/yassl/taocrypt/src/md5.cpp
@@ -0,0 +1,170 @@
+/* md5.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* based on Wei Dai's md5.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "md5.hpp"
+#include "algorithm.hpp" // mySTL::swap
+
+namespace TaoCrypt {
+
+void MD5::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xefcdab89L;
+ digest_[2] = 0x98badcfeL;
+ digest_[3] = 0x10325476L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+MD5::MD5(const MD5& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
+ BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+MD5& MD5::operator= (const MD5& that)
+{
+ MD5 tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void MD5::Swap(MD5& other)
+{
+ mySTL::swap(length_, other.length_);
+ mySTL::swap(buffLen_, other.buffLen_);
+
+ memcpy(digest_, other.digest_, DIGEST_SIZE);
+ memcpy(buffer_, other.buffer_, BLOCK_SIZE);
+}
+
+
+void MD5::Transform()
+{
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) \
+ w = rotlFixed(w + f(x, y, z) + data, s) + x
+
+ // Copy context->state[] to working vars
+ word32 a = digest_[0];
+ word32 b = digest_[1];
+ word32 c = digest_[2];
+ word32 d = digest_[3];
+
+ MD5STEP(F1, a, b, c, d, buffer_[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, buffer_[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, buffer_[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, buffer_[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, buffer_[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, buffer_[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, buffer_[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, buffer_[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, buffer_[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, buffer_[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, buffer_[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, buffer_[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, buffer_[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, buffer_[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, buffer_[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, buffer_[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, buffer_[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, buffer_[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, buffer_[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, buffer_[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, buffer_[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, buffer_[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, buffer_[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, buffer_[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, buffer_[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, buffer_[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, buffer_[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, buffer_[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, buffer_[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, buffer_[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, buffer_[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, buffer_[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, buffer_[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, buffer_[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, buffer_[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, buffer_[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, buffer_[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, buffer_[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, buffer_[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, buffer_[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, buffer_[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, buffer_[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, buffer_[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, buffer_[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, buffer_[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, buffer_[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, buffer_[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, buffer_[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, buffer_[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, buffer_[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, buffer_[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, buffer_[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, buffer_[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, buffer_[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, buffer_[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, buffer_[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, buffer_[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, buffer_[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, buffer_[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, buffer_[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, buffer_[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, buffer_[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, buffer_[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, buffer_[9] + 0xeb86d391, 21);
+
+ // Add the working vars back into digest state[]
+ digest_[0] += a;
+ digest_[1] += b;
+ digest_[2] += c;
+ digest_[3] += d;
+
+ // Wipe variables
+ a = b = c = d = 0;
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp
new file mode 100644
index 00000000000..0b33bb38aea
--- /dev/null
+++ b/extra/yassl/taocrypt/src/misc.cpp
@@ -0,0 +1,143 @@
+/* misc.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's misc.cpp from CryptoPP */
+
+
+#include "runtime.hpp"
+#include "misc.hpp"
+
+
+void* operator new(size_t sz, TaoCrypt::new_t)
+{
+#ifdef YASSL_PURE_C
+ void* ptr = malloc(sz ? sz : 1);
+ if (!ptr) abort();
+
+ return ptr;
+#else
+ return ::operator new(sz);
+#endif
+}
+
+
+void operator delete(void* ptr, TaoCrypt::new_t)
+{
+#ifdef YASSL_PURE_C
+ if (ptr) free(ptr);
+#else
+ ::operator delete(ptr);
+#endif
+}
+
+
+void* operator new[](size_t sz, TaoCrypt::new_t nt)
+{
+ return ::operator new(sz, nt);
+}
+
+
+void operator delete[](void* ptr, TaoCrypt::new_t nt)
+{
+ ::operator delete(ptr, nt);
+}
+
+
+/* uncomment to test
+// make sure not using globals anywhere by forgetting to use overloaded
+void* operator new(size_t sz);
+
+void operator delete(void* ptr);
+
+void* operator new[](size_t sz);
+
+void operator delete[](void* ptr);
+*/
+
+
+namespace TaoCrypt {
+
+
+new_t tc; // for library new
+
+
+inline void XorWords(word* r, const word* a, unsigned int n)
+{
+ for (unsigned int i=0; i<n; i++)
+ r[i] ^= a[i];
+}
+
+
+void xorbuf(byte* buf, const byte* mask, unsigned int count)
+{
+ if (((size_t)buf | (size_t)mask | count) % WORD_SIZE == 0)
+ XorWords((word *)buf, (const word *)mask, count/WORD_SIZE);
+ else
+ {
+ for (unsigned int i=0; i<count; i++)
+ buf[i] ^= mask[i];
+ }
+}
+
+
+unsigned int BytePrecision(unsigned long value)
+{
+ unsigned int i;
+ for (i=sizeof(value); i; --i)
+ if (value >> (i-1)*8)
+ break;
+
+ return i;
+}
+
+
+unsigned int BitPrecision(unsigned long value)
+{
+ if (!value)
+ return 0;
+
+ unsigned int l = 0,
+ h = 8 * sizeof(value);
+
+ while (h-l > 1)
+ {
+ unsigned int t = (l+h)/2;
+ if (value >> t)
+ l = t;
+ else
+ h = t;
+ }
+
+ return h;
+}
+
+
+unsigned long Crop(unsigned long value, unsigned int size)
+{
+ if (size < 8*sizeof(value))
+ return (value & ((1L << size) - 1));
+ else
+ return value;
+}
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp
new file mode 100644
index 00000000000..e1e6416eb00
--- /dev/null
+++ b/extra/yassl/taocrypt/src/random.cpp
@@ -0,0 +1,130 @@
+/* random.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* random.cpp implements a crypto secure Random Number Generator using an OS
+ specific seed, switch to /dev/random for more security but may block
+*/
+
+#include "runtime.hpp"
+#include "random.hpp"
+
+#if defined(_WIN32)
+ #define _WIN32_WINNT 0x0400
+ #include <windows.h>
+ #include <wincrypt.h>
+#else
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+#endif // _WIN32
+
+namespace TaoCrypt {
+
+
+// Get seed and key cipher
+RandomNumberGenerator::RandomNumberGenerator()
+{
+ byte key[32];
+ seed_.GenerateSeed(key, sizeof(key));
+ cipher_.SetKey(key, sizeof(key));
+}
+
+
+// place a generated block in output
+void RandomNumberGenerator::GenerateBlock(byte* output, word32 sz)
+{
+ cipher_.Process(output, output, sz);
+}
+
+
+byte RandomNumberGenerator::GenerateByte()
+{
+ byte b;
+ GenerateBlock(&b, 1);
+
+ return b;
+}
+
+
+#if defined(_WIN32)
+
+OS_Seed::OS_Seed()
+{
+ if(!CryptAcquireContext(&handle_, 0, 0, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ error_.SetError(WINCRYPT_E);
+}
+
+
+OS_Seed::~OS_Seed()
+{
+ CryptReleaseContext(handle_, 0);
+}
+
+
+void OS_Seed::GenerateSeed(byte* output, word32 sz)
+{
+ if (!CryptGenRandom(handle_, sz, output))
+ error_.SetError(CRYPTGEN_E);
+}
+
+
+#else // _WIN32
+
+
+OS_Seed::OS_Seed()
+{
+ fd_ = open("/dev/urandom",O_RDONLY);
+ if (fd_ == -1)
+ error_.SetError(OPEN_RAN_E);
+}
+
+
+OS_Seed::~OS_Seed()
+{
+ close(fd_);
+}
+
+
+// may block
+void OS_Seed::GenerateSeed(byte* output, word32 sz)
+{
+ while (sz) {
+ int len = read(fd_, output, sz);
+ if (len == -1) {
+ error_.SetError(READ_RAN_E);
+ return;
+ }
+
+ sz -= len;
+ output += len;
+
+ if (sz)
+ sleep(1);
+ }
+}
+
+#endif // _WIN32
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp
new file mode 100644
index 00000000000..0534a0d572d
--- /dev/null
+++ b/extra/yassl/taocrypt/src/ripemd.cpp
@@ -0,0 +1,290 @@
+/* ripemd.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* based on Wei Dai's ripemd.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "ripemd.hpp"
+#include "algorithm.hpp" // mySTL::swap
+
+namespace TaoCrypt {
+
+void RIPEMD160::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xefcdab89L;
+ digest_[2] = 0x98badcfeL;
+ digest_[3] = 0x10325476L;
+ digest_[4] = 0xc3d2e1f0L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+RIPEMD160::RIPEMD160(const RIPEMD160& that)
+ : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+
+RIPEMD160& RIPEMD160::operator= (const RIPEMD160& that)
+{
+ RIPEMD160 tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void RIPEMD160::Swap(RIPEMD160& other)
+{
+ mySTL::swap(length_, other.length_);
+ mySTL::swap(buffLen_, other.buffLen_);
+
+ memcpy(digest_, other.digest_, DIGEST_SIZE);
+ memcpy(buffer_, other.buffer_, BLOCK_SIZE);
+}
+
+
+// for all
+#define F(x, y, z) (x ^ y ^ z)
+#define G(x, y, z) (z ^ (x & (y^z)))
+#define H(x, y, z) (z ^ (x | ~y))
+#define I(x, y, z) (y ^ (z & (x^y)))
+#define J(x, y, z) (x ^ (y | ~z))
+
+#define k0 0
+#define k1 0x5a827999UL
+#define k2 0x6ed9eba1UL
+#define k3 0x8f1bbcdcUL
+#define k4 0xa953fd4eUL
+#define k5 0x50a28be6UL
+#define k6 0x5c4dd124UL
+#define k7 0x6d703ef3UL
+#define k8 0x7a6d76e9UL
+#define k9 0
+
+// for 160 and 320
+#define Subround(f, a, b, c, d, e, x, s, k) \
+ a += f(b, c, d) + x + k;\
+ a = rotlFixed((word32)a, s) + e;\
+ c = rotlFixed((word32)c, 10U)
+
+
+void RIPEMD160::Transform()
+{
+ unsigned long a1, b1, c1, d1, e1, a2, b2, c2, d2, e2;
+ a1 = a2 = digest_[0];
+ b1 = b2 = digest_[1];
+ c1 = c2 = digest_[2];
+ d1 = d2 = digest_[3];
+ e1 = e2 = digest_[4];
+
+ Subround(F, a1, b1, c1, d1, e1, buffer_[ 0], 11, k0);
+ Subround(F, e1, a1, b1, c1, d1, buffer_[ 1], 14, k0);
+ Subround(F, d1, e1, a1, b1, c1, buffer_[ 2], 15, k0);
+ Subround(F, c1, d1, e1, a1, b1, buffer_[ 3], 12, k0);
+ Subround(F, b1, c1, d1, e1, a1, buffer_[ 4], 5, k0);
+ Subround(F, a1, b1, c1, d1, e1, buffer_[ 5], 8, k0);
+ Subround(F, e1, a1, b1, c1, d1, buffer_[ 6], 7, k0);
+ Subround(F, d1, e1, a1, b1, c1, buffer_[ 7], 9, k0);
+ Subround(F, c1, d1, e1, a1, b1, buffer_[ 8], 11, k0);
+ Subround(F, b1, c1, d1, e1, a1, buffer_[ 9], 13, k0);
+ Subround(F, a1, b1, c1, d1, e1, buffer_[10], 14, k0);
+ Subround(F, e1, a1, b1, c1, d1, buffer_[11], 15, k0);
+ Subround(F, d1, e1, a1, b1, c1, buffer_[12], 6, k0);
+ Subround(F, c1, d1, e1, a1, b1, buffer_[13], 7, k0);
+ Subround(F, b1, c1, d1, e1, a1, buffer_[14], 9, k0);
+ Subround(F, a1, b1, c1, d1, e1, buffer_[15], 8, k0);
+
+ Subround(G, e1, a1, b1, c1, d1, buffer_[ 7], 7, k1);
+ Subround(G, d1, e1, a1, b1, c1, buffer_[ 4], 6, k1);
+ Subround(G, c1, d1, e1, a1, b1, buffer_[13], 8, k1);
+ Subround(G, b1, c1, d1, e1, a1, buffer_[ 1], 13, k1);
+ Subround(G, a1, b1, c1, d1, e1, buffer_[10], 11, k1);
+ Subround(G, e1, a1, b1, c1, d1, buffer_[ 6], 9, k1);
+ Subround(G, d1, e1, a1, b1, c1, buffer_[15], 7, k1);
+ Subround(G, c1, d1, e1, a1, b1, buffer_[ 3], 15, k1);
+ Subround(G, b1, c1, d1, e1, a1, buffer_[12], 7, k1);
+ Subround(G, a1, b1, c1, d1, e1, buffer_[ 0], 12, k1);
+ Subround(G, e1, a1, b1, c1, d1, buffer_[ 9], 15, k1);
+ Subround(G, d1, e1, a1, b1, c1, buffer_[ 5], 9, k1);
+ Subround(G, c1, d1, e1, a1, b1, buffer_[ 2], 11, k1);
+ Subround(G, b1, c1, d1, e1, a1, buffer_[14], 7, k1);
+ Subround(G, a1, b1, c1, d1, e1, buffer_[11], 13, k1);
+ Subround(G, e1, a1, b1, c1, d1, buffer_[ 8], 12, k1);
+
+ Subround(H, d1, e1, a1, b1, c1, buffer_[ 3], 11, k2);
+ Subround(H, c1, d1, e1, a1, b1, buffer_[10], 13, k2);
+ Subround(H, b1, c1, d1, e1, a1, buffer_[14], 6, k2);
+ Subround(H, a1, b1, c1, d1, e1, buffer_[ 4], 7, k2);
+ Subround(H, e1, a1, b1, c1, d1, buffer_[ 9], 14, k2);
+ Subround(H, d1, e1, a1, b1, c1, buffer_[15], 9, k2);
+ Subround(H, c1, d1, e1, a1, b1, buffer_[ 8], 13, k2);
+ Subround(H, b1, c1, d1, e1, a1, buffer_[ 1], 15, k2);
+ Subround(H, a1, b1, c1, d1, e1, buffer_[ 2], 14, k2);
+ Subround(H, e1, a1, b1, c1, d1, buffer_[ 7], 8, k2);
+ Subround(H, d1, e1, a1, b1, c1, buffer_[ 0], 13, k2);
+ Subround(H, c1, d1, e1, a1, b1, buffer_[ 6], 6, k2);
+ Subround(H, b1, c1, d1, e1, a1, buffer_[13], 5, k2);
+ Subround(H, a1, b1, c1, d1, e1, buffer_[11], 12, k2);
+ Subround(H, e1, a1, b1, c1, d1, buffer_[ 5], 7, k2);
+ Subround(H, d1, e1, a1, b1, c1, buffer_[12], 5, k2);
+
+ Subround(I, c1, d1, e1, a1, b1, buffer_[ 1], 11, k3);
+ Subround(I, b1, c1, d1, e1, a1, buffer_[ 9], 12, k3);
+ Subround(I, a1, b1, c1, d1, e1, buffer_[11], 14, k3);
+ Subround(I, e1, a1, b1, c1, d1, buffer_[10], 15, k3);
+ Subround(I, d1, e1, a1, b1, c1, buffer_[ 0], 14, k3);
+ Subround(I, c1, d1, e1, a1, b1, buffer_[ 8], 15, k3);
+ Subround(I, b1, c1, d1, e1, a1, buffer_[12], 9, k3);
+ Subround(I, a1, b1, c1, d1, e1, buffer_[ 4], 8, k3);
+ Subround(I, e1, a1, b1, c1, d1, buffer_[13], 9, k3);
+ Subround(I, d1, e1, a1, b1, c1, buffer_[ 3], 14, k3);
+ Subround(I, c1, d1, e1, a1, b1, buffer_[ 7], 5, k3);
+ Subround(I, b1, c1, d1, e1, a1, buffer_[15], 6, k3);
+ Subround(I, a1, b1, c1, d1, e1, buffer_[14], 8, k3);
+ Subround(I, e1, a1, b1, c1, d1, buffer_[ 5], 6, k3);
+ Subround(I, d1, e1, a1, b1, c1, buffer_[ 6], 5, k3);
+ Subround(I, c1, d1, e1, a1, b1, buffer_[ 2], 12, k3);
+
+ Subround(J, b1, c1, d1, e1, a1, buffer_[ 4], 9, k4);
+ Subround(J, a1, b1, c1, d1, e1, buffer_[ 0], 15, k4);
+ Subround(J, e1, a1, b1, c1, d1, buffer_[ 5], 5, k4);
+ Subround(J, d1, e1, a1, b1, c1, buffer_[ 9], 11, k4);
+ Subround(J, c1, d1, e1, a1, b1, buffer_[ 7], 6, k4);
+ Subround(J, b1, c1, d1, e1, a1, buffer_[12], 8, k4);
+ Subround(J, a1, b1, c1, d1, e1, buffer_[ 2], 13, k4);
+ Subround(J, e1, a1, b1, c1, d1, buffer_[10], 12, k4);
+ Subround(J, d1, e1, a1, b1, c1, buffer_[14], 5, k4);
+ Subround(J, c1, d1, e1, a1, b1, buffer_[ 1], 12, k4);
+ Subround(J, b1, c1, d1, e1, a1, buffer_[ 3], 13, k4);
+ Subround(J, a1, b1, c1, d1, e1, buffer_[ 8], 14, k4);
+ Subround(J, e1, a1, b1, c1, d1, buffer_[11], 11, k4);
+ Subround(J, d1, e1, a1, b1, c1, buffer_[ 6], 8, k4);
+ Subround(J, c1, d1, e1, a1, b1, buffer_[15], 5, k4);
+ Subround(J, b1, c1, d1, e1, a1, buffer_[13], 6, k4);
+
+ Subround(J, a2, b2, c2, d2, e2, buffer_[ 5], 8, k5);
+ Subround(J, e2, a2, b2, c2, d2, buffer_[14], 9, k5);
+ Subround(J, d2, e2, a2, b2, c2, buffer_[ 7], 9, k5);
+ Subround(J, c2, d2, e2, a2, b2, buffer_[ 0], 11, k5);
+ Subround(J, b2, c2, d2, e2, a2, buffer_[ 9], 13, k5);
+ Subround(J, a2, b2, c2, d2, e2, buffer_[ 2], 15, k5);
+ Subround(J, e2, a2, b2, c2, d2, buffer_[11], 15, k5);
+ Subround(J, d2, e2, a2, b2, c2, buffer_[ 4], 5, k5);
+ Subround(J, c2, d2, e2, a2, b2, buffer_[13], 7, k5);
+ Subround(J, b2, c2, d2, e2, a2, buffer_[ 6], 7, k5);
+ Subround(J, a2, b2, c2, d2, e2, buffer_[15], 8, k5);
+ Subround(J, e2, a2, b2, c2, d2, buffer_[ 8], 11, k5);
+ Subround(J, d2, e2, a2, b2, c2, buffer_[ 1], 14, k5);
+ Subround(J, c2, d2, e2, a2, b2, buffer_[10], 14, k5);
+ Subround(J, b2, c2, d2, e2, a2, buffer_[ 3], 12, k5);
+ Subround(J, a2, b2, c2, d2, e2, buffer_[12], 6, k5);
+
+ Subround(I, e2, a2, b2, c2, d2, buffer_[ 6], 9, k6);
+ Subround(I, d2, e2, a2, b2, c2, buffer_[11], 13, k6);
+ Subround(I, c2, d2, e2, a2, b2, buffer_[ 3], 15, k6);
+ Subround(I, b2, c2, d2, e2, a2, buffer_[ 7], 7, k6);
+ Subround(I, a2, b2, c2, d2, e2, buffer_[ 0], 12, k6);
+ Subround(I, e2, a2, b2, c2, d2, buffer_[13], 8, k6);
+ Subround(I, d2, e2, a2, b2, c2, buffer_[ 5], 9, k6);
+ Subround(I, c2, d2, e2, a2, b2, buffer_[10], 11, k6);
+ Subround(I, b2, c2, d2, e2, a2, buffer_[14], 7, k6);
+ Subround(I, a2, b2, c2, d2, e2, buffer_[15], 7, k6);
+ Subround(I, e2, a2, b2, c2, d2, buffer_[ 8], 12, k6);
+ Subround(I, d2, e2, a2, b2, c2, buffer_[12], 7, k6);
+ Subround(I, c2, d2, e2, a2, b2, buffer_[ 4], 6, k6);
+ Subround(I, b2, c2, d2, e2, a2, buffer_[ 9], 15, k6);
+ Subround(I, a2, b2, c2, d2, e2, buffer_[ 1], 13, k6);
+ Subround(I, e2, a2, b2, c2, d2, buffer_[ 2], 11, k6);
+
+ Subround(H, d2, e2, a2, b2, c2, buffer_[15], 9, k7);
+ Subround(H, c2, d2, e2, a2, b2, buffer_[ 5], 7, k7);
+ Subround(H, b2, c2, d2, e2, a2, buffer_[ 1], 15, k7);
+ Subround(H, a2, b2, c2, d2, e2, buffer_[ 3], 11, k7);
+ Subround(H, e2, a2, b2, c2, d2, buffer_[ 7], 8, k7);
+ Subround(H, d2, e2, a2, b2, c2, buffer_[14], 6, k7);
+ Subround(H, c2, d2, e2, a2, b2, buffer_[ 6], 6, k7);
+ Subround(H, b2, c2, d2, e2, a2, buffer_[ 9], 14, k7);
+ Subround(H, a2, b2, c2, d2, e2, buffer_[11], 12, k7);
+ Subround(H, e2, a2, b2, c2, d2, buffer_[ 8], 13, k7);
+ Subround(H, d2, e2, a2, b2, c2, buffer_[12], 5, k7);
+ Subround(H, c2, d2, e2, a2, b2, buffer_[ 2], 14, k7);
+ Subround(H, b2, c2, d2, e2, a2, buffer_[10], 13, k7);
+ Subround(H, a2, b2, c2, d2, e2, buffer_[ 0], 13, k7);
+ Subround(H, e2, a2, b2, c2, d2, buffer_[ 4], 7, k7);
+ Subround(H, d2, e2, a2, b2, c2, buffer_[13], 5, k7);
+
+ Subround(G, c2, d2, e2, a2, b2, buffer_[ 8], 15, k8);
+ Subround(G, b2, c2, d2, e2, a2, buffer_[ 6], 5, k8);
+ Subround(G, a2, b2, c2, d2, e2, buffer_[ 4], 8, k8);
+ Subround(G, e2, a2, b2, c2, d2, buffer_[ 1], 11, k8);
+ Subround(G, d2, e2, a2, b2, c2, buffer_[ 3], 14, k8);
+ Subround(G, c2, d2, e2, a2, b2, buffer_[11], 14, k8);
+ Subround(G, b2, c2, d2, e2, a2, buffer_[15], 6, k8);
+ Subround(G, a2, b2, c2, d2, e2, buffer_[ 0], 14, k8);
+ Subround(G, e2, a2, b2, c2, d2, buffer_[ 5], 6, k8);
+ Subround(G, d2, e2, a2, b2, c2, buffer_[12], 9, k8);
+ Subround(G, c2, d2, e2, a2, b2, buffer_[ 2], 12, k8);
+ Subround(G, b2, c2, d2, e2, a2, buffer_[13], 9, k8);
+ Subround(G, a2, b2, c2, d2, e2, buffer_[ 9], 12, k8);
+ Subround(G, e2, a2, b2, c2, d2, buffer_[ 7], 5, k8);
+ Subround(G, d2, e2, a2, b2, c2, buffer_[10], 15, k8);
+ Subround(G, c2, d2, e2, a2, b2, buffer_[14], 8, k8);
+
+ Subround(F, b2, c2, d2, e2, a2, buffer_[12], 8, k9);
+ Subround(F, a2, b2, c2, d2, e2, buffer_[15], 5, k9);
+ Subround(F, e2, a2, b2, c2, d2, buffer_[10], 12, k9);
+ Subround(F, d2, e2, a2, b2, c2, buffer_[ 4], 9, k9);
+ Subround(F, c2, d2, e2, a2, b2, buffer_[ 1], 12, k9);
+ Subround(F, b2, c2, d2, e2, a2, buffer_[ 5], 5, k9);
+ Subround(F, a2, b2, c2, d2, e2, buffer_[ 8], 14, k9);
+ Subround(F, e2, a2, b2, c2, d2, buffer_[ 7], 6, k9);
+ Subround(F, d2, e2, a2, b2, c2, buffer_[ 6], 8, k9);
+ Subround(F, c2, d2, e2, a2, b2, buffer_[ 2], 13, k9);
+ Subround(F, b2, c2, d2, e2, a2, buffer_[13], 6, k9);
+ Subround(F, a2, b2, c2, d2, e2, buffer_[14], 5, k9);
+ Subround(F, e2, a2, b2, c2, d2, buffer_[ 0], 15, k9);
+ Subround(F, d2, e2, a2, b2, c2, buffer_[ 3], 13, k9);
+ Subround(F, c2, d2, e2, a2, b2, buffer_[ 9], 11, k9);
+ Subround(F, b2, c2, d2, e2, a2, buffer_[11], 11, k9);
+
+ c1 = digest_[1] + c1 + d2;
+ digest_[1] = digest_[2] + d1 + e2;
+ digest_[2] = digest_[3] + e1 + a2;
+ digest_[3] = digest_[4] + a1 + b2;
+ digest_[4] = digest_[0] + b1 + c2;
+ digest_[0] = c1;
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+
+} // namespace TaoCrypt
diff --git a/extra/yassl/taocrypt/src/rsa.cpp b/extra/yassl/taocrypt/src/rsa.cpp
new file mode 100644
index 00000000000..021fd992b5c
--- /dev/null
+++ b/extra/yassl/taocrypt/src/rsa.cpp
@@ -0,0 +1,213 @@
+/* rsa.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's rsa.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "rsa.hpp"
+#include "asn.hpp"
+#include "modarith.hpp"
+
+
+
+namespace TaoCrypt {
+
+
+Integer RSA_PublicKey::ApplyFunction(const Integer& x) const
+{
+ return a_exp_b_mod_c(x, e_, n_);
+}
+
+
+RSA_PublicKey::RSA_PublicKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void RSA_PublicKey::Initialize(Source& source)
+{
+ RSA_Public_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+Integer RSA_PrivateKey::CalculateInverse(RandomNumberGenerator& rng,
+ const Integer& x) const
+{
+ ModularArithmetic modn(n_);
+
+ Integer r(rng, Integer::One(), n_ - Integer::One());
+ Integer re = modn.Exponentiate(r, e_);
+ re = modn.Multiply(re, x); // blind
+
+ // here we follow the notation of PKCS #1 and let u=q inverse mod p
+ // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q
+
+ Integer y = ModularRoot(re, dq_, dp_, q_, p_, u_);
+ y = modn.Divide(y, r); // unblind
+ assert(modn.Exponentiate(y, e_) == x); // check
+
+ return y;
+}
+
+
+RSA_PrivateKey::RSA_PrivateKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void RSA_PrivateKey::Initialize(Source& source)
+{
+ RSA_Private_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void RSA_BlockType2::Pad(const byte *input, word32 inputLen, byte *pkcsBlock,
+ word32 pkcsBlockLen, RandomNumberGenerator& rng) const
+{
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ pkcsBlock[0] = 0;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ pkcsBlock[0] = 2; // block type 2
+
+ // pad with non-zero random bytes
+ word32 padLen = pkcsBlockLen - inputLen - 1;
+ rng.GenerateBlock(&pkcsBlock[1], padLen);
+ for (word32 i = 1; i < padLen; i++)
+ if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
+ memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+}
+
+word32 RSA_BlockType2::UnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
+ byte *output) const
+{
+ bool invalid = false;
+ unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U);
+
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ invalid = (pkcsBlock[0] != 0) || invalid;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ // Require block type 2.
+ invalid = (pkcsBlock[0] != 2) || invalid;
+
+ // skip past the padding until we find the separator
+ unsigned i=1;
+ while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
+ }
+ assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
+
+ unsigned int outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid)
+ return 0;
+
+ memcpy (output, pkcsBlock+i, outputLen);
+ return outputLen;
+}
+
+
+void RSA_BlockType1::Pad(const byte* input, word32 inputLen, byte* pkcsBlock,
+ word32 pkcsBlockLen, RandomNumberGenerator&) const
+{
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ pkcsBlock[0] = 0;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ pkcsBlock[0] = 1; // block type 1 for SSL
+
+ // pad with 0xff bytes
+ memset(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
+ memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+}
+
+
+word32 RSA_BlockType1::UnPad(const byte* pkcsBlock, word32 pkcsBlockLen,
+ byte* output) const
+{
+ bool invalid = false;
+ unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U);
+
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ invalid = (pkcsBlock[0] != 0) || invalid;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ // Require block type 1 for SSL.
+ invalid = (pkcsBlock[0] != 1) || invalid;
+
+ // skip past the padding until we find the separator
+ unsigned i=1;
+ while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
+ }
+ assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
+
+ unsigned int outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid)
+ return 0;
+
+ memcpy(output, pkcsBlock+i, outputLen);
+ return outputLen;
+}
+
+
+word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain)
+{
+ PK_Lengths lengths(key.GetModulus());
+
+ ByteBlock paddedBlock(BitsToBytes(lengths.PaddedBlockBitLength()));
+ Integer x = key.ApplyFunction(Integer(sig,
+ lengths.FixedCiphertextLength()));
+ if (x.ByteCount() > paddedBlock.size())
+ x = Integer::Zero();
+ x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
+ return RSA_BlockType1().UnPad(paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), plain);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp
new file mode 100644
index 00000000000..13a4cfc22d3
--- /dev/null
+++ b/extra/yassl/taocrypt/src/sha.cpp
@@ -0,0 +1,145 @@
+/* sha.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+/* based on Wei Dai's sha.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include <string.h>
+#include "algorithm.hpp" // mySTL::swap
+#include "sha.hpp"
+
+
+namespace TaoCrypt {
+
+#define blk0(i) (W[i] = buffer_[i])
+#define blk1(i) (W[i&15] = \
+ rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
+
+#define f1(x,y,z) (z^(x &(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+
+// (R0+R1), R2, R3, R4 are the different operations used in SHA1
+#define R0(v,w,x,y,z,i) z+= f1(w,x,y) + blk0(i) + 0x5A827999+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R1(v,w,x,y,z,i) z+= f1(w,x,y) + blk1(i) + 0x5A827999+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R2(v,w,x,y,z,i) z+= f2(w,x,y) + blk1(i) + 0x6ED9EBA1+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R3(v,w,x,y,z,i) z+= f3(w,x,y) + blk1(i) + 0x8F1BBCDC+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R4(v,w,x,y,z,i) z+= f4(w,x,y) + blk1(i) + 0xCA62C1D6+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+
+
+void SHA::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xEFCDAB89L;
+ digest_[2] = 0x98BADCFEL;
+ digest_[3] = 0x10325476L;
+ digest_[4] = 0xC3D2E1F0L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+SHA::SHA(const SHA& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
+ BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+SHA& SHA::operator= (const SHA& that)
+{
+ SHA tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void SHA::Swap(SHA& other)
+{
+ mySTL::swap(length_, other.length_);
+ mySTL::swap(buffLen_, other.buffLen_);
+
+ memcpy(digest_, other.digest_, DIGEST_SIZE);
+ memcpy(buffer_, other.buffer_, BLOCK_SIZE);
+}
+
+
+void SHA::Transform()
+{
+ word32 W[BLOCK_SIZE / sizeof(word32)];
+
+ // Copy context->state[] to working vars
+ word32 a = digest_[0];
+ word32 b = digest_[1];
+ word32 c = digest_[2];
+ word32 d = digest_[3];
+ word32 e = digest_[4];
+
+ // 4 rounds of 20 operations each. Loop unrolled.
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ // Add the working vars back into digest state[]
+ digest_[0] += a;
+ digest_[1] += b;
+ digest_[2] += c;
+ digest_[3] += d;
+ digest_[4] += e;
+
+ // Wipe variables
+ a = b = c = d = e = 0;
+ memset(W, 0, sizeof(W));
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp
new file mode 100644
index 00000000000..9a3c12badfc
--- /dev/null
+++ b/extra/yassl/taocrypt/src/template_instnt.cpp
@@ -0,0 +1,65 @@
+/* template_instnt.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL 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.
+ *
+ * yaSSL 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
+ */
+
+
+/* Explicit template instantiation requests
+ */
+
+
+#include "integer.hpp"
+#include "rsa.hpp"
+#include "algebra.hpp"
+#include "vector.hpp"
+#include "hash.hpp"
+
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+namespace TaoCrypt {
+
+#if defined(SSE2_INTRINSICS_AVAILABLE)
+template AlignedAllocator<unsigned int>::pointer StdReallocate<unsigned int, AlignedAllocator<unsigned int> >(AlignedAllocator<unsigned int>&, unsigned int*, AlignedAllocator<unsigned int>::size_type, AlignedAllocator<unsigned int>::size_type, bool);
+#endif
+
+template class RSA_Decryptor<RSA_BlockType2>;
+template class RSA_Encryptor<RSA_BlockType1>;
+template class RSA_Encryptor<RSA_BlockType2>;
+template void tcDelete<HASH>(HASH*);
+template void tcArrayDelete<byte>(byte*);
+template AllocatorWithCleanup<byte>::pointer StdReallocate<byte, AllocatorWithCleanup<byte> >(AllocatorWithCleanup<byte>&, byte*, AllocatorWithCleanup<byte>::size_type, AllocatorWithCleanup<byte>::size_type, bool);
+template void tcArrayDelete<word>(word*);
+template AllocatorWithCleanup<word>::pointer StdReallocate<word, AllocatorWithCleanup<word> >(AllocatorWithCleanup<word>&, word*, AllocatorWithCleanup<word>::size_type, AllocatorWithCleanup<word>::size_type, bool);
+
+#ifndef TAOCRYPT_SLOW_WORD64 // defined when word != word32
+template void tcArrayDelete<word32>(word32*);
+template AllocatorWithCleanup<word32>::pointer StdReallocate<word32, AllocatorWithCleanup<word32> >(AllocatorWithCleanup<word32>&, word32*, AllocatorWithCleanup<word32>::size_type, AllocatorWithCleanup<word32>::size_type, bool);
+#endif
+
+template void tcArrayDelete<char>(char*);
+}
+
+namespace mySTL {
+template vector<TaoCrypt::Integer>* uninit_fill_n<vector<TaoCrypt::Integer>*, size_t, vector<TaoCrypt::Integer> >(vector<TaoCrypt::Integer>*, size_t, vector<TaoCrypt::Integer> const&);
+template void destroy<vector<TaoCrypt::Integer>*>(vector<TaoCrypt::Integer>*, vector<TaoCrypt::Integer>*);
+template TaoCrypt::Integer* uninit_copy<TaoCrypt::Integer*, TaoCrypt::Integer*>(TaoCrypt::Integer*, TaoCrypt::Integer*, TaoCrypt::Integer*);
+template TaoCrypt::Integer* uninit_fill_n<TaoCrypt::Integer*, size_t, TaoCrypt::Integer>(TaoCrypt::Integer*, size_t, TaoCrypt::Integer const&);
+template void destroy<TaoCrypt::Integer*>(TaoCrypt::Integer*, TaoCrypt::Integer*);
+}
+
+#endif
diff --git a/extra/yassl/taocrypt/taocrypt.dsp b/extra/yassl/taocrypt/taocrypt.dsp
new file mode 100644
index 00000000000..115ad0cb272
--- /dev/null
+++ b/extra/yassl/taocrypt/taocrypt.dsp
@@ -0,0 +1,260 @@
+# Microsoft Developer Studio Project File - Name="taocrypt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=taocrypt - 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 "taocrypt.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 "taocrypt.mak" CFG="taocrypt - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "taocrypt - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "taocrypt - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "taocrypt - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "taocrypt___Win32_Release"
+# PROP BASE Intermediate_Dir "taocrypt___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX- /O2 /I "include" /I "..\mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "taocrypt - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "taocrypt___Win32_Debug"
+# PROP BASE Intermediate_Dir "taocrypt___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX- /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "taocrypt - Win32 Release"
+# Name "taocrypt - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\aes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aestables.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\algebra.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\arc4.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\asn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\coding.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\des.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\dh.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\dsa.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\file.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\hash.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\integer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\md2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\md5.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\random.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ripemd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\rsa.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sha.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\include\aes.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\algebra.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arc4.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\asn.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\block.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\coding.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\des.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\dh.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\dsa.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\error.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\file.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\hash.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\hmac.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\integer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\md2.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\md5.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\misc.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\modarith.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\modes.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\random.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\ripemd.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\rsa.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\sha.hpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/VC++Files/mysqlmanager/mysqlmanager.dsw b/extra/yassl/taocrypt/taocrypt.dsw
index 013873b113b..d10d7534c3d 100644
--- a/VC++Files/mysqlmanager/mysqlmanager.dsw
+++ b/extra/yassl/taocrypt/taocrypt.dsw
@@ -1,9 +1,9 @@
-Microsoft Developer Studio Workspace File, Format Version 5.00
+Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
-Project: "MySqlManager"=.\MySqlManager.dsp - Package Owner=<4>
+Project: "taocrypt"=.\taocrypt.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -15,6 +15,21 @@ Package=<4>
###############################################################################
+Project: "test"=.\test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
Global:
Package=<5>
@@ -26,3 +41,4 @@ Package=<3>
}}}
###############################################################################
+
diff --git a/extra/yassl/taocrypt/taocrypt.vcproj b/extra/yassl/taocrypt/taocrypt.vcproj
new file mode 100755
index 00000000000..603fafd4090
--- /dev/null
+++ b/extra/yassl/taocrypt/taocrypt.vcproj
@@ -0,0 +1,602 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="taocrypt"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="include,..\mySTL"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ ExceptionHandling="FALSE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/taocrypt.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\taocrypt.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="include,..\mySTL"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ ExceptionHandling="FALSE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/taocrypt.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\taocrypt.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="src\aes.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\aestables.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\algebra.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\arc4.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\asn.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\coding.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\des.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\dh.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\dsa.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\file.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\hash.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\integer.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\md2.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\md5.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\misc.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\random.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\ripemd.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\rsa.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\sha.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="include\aes.hpp">
+ </File>
+ <File
+ RelativePath="include\algebra.hpp">
+ </File>
+ <File
+ RelativePath="include\arc4.hpp">
+ </File>
+ <File
+ RelativePath="include\asn.hpp">
+ </File>
+ <File
+ RelativePath="include\block.hpp">
+ </File>
+ <File
+ RelativePath="include\coding.hpp">
+ </File>
+ <File
+ RelativePath="include\des.hpp">
+ </File>
+ <File
+ RelativePath="include\dh.hpp">
+ </File>
+ <File
+ RelativePath="include\dsa.hpp">
+ </File>
+ <File
+ RelativePath="include\error.hpp">
+ </File>
+ <File
+ RelativePath="include\file.hpp">
+ </File>
+ <File
+ RelativePath="include\hash.hpp">
+ </File>
+ <File
+ RelativePath="include\hmac.hpp">
+ </File>
+ <File
+ RelativePath="include\integer.hpp">
+ </File>
+ <File
+ RelativePath="include\md2.hpp">
+ </File>
+ <File
+ RelativePath="include\md5.hpp">
+ </File>
+ <File
+ RelativePath="include\misc.hpp">
+ </File>
+ <File
+ RelativePath="include\modarith.hpp">
+ </File>
+ <File
+ RelativePath="include\modes.hpp">
+ </File>
+ <File
+ RelativePath="include\random.hpp">
+ </File>
+ <File
+ RelativePath="include\ripemd.hpp">
+ </File>
+ <File
+ RelativePath="include\rsa.hpp">
+ </File>
+ <File
+ RelativePath="include\sha.hpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/extra/yassl/yassl.dsp b/extra/yassl/yassl.dsp
new file mode 100644
index 00000000000..f51c19eebbf
--- /dev/null
+++ b/extra/yassl/yassl.dsp
@@ -0,0 +1,192 @@
+# Microsoft Developer Studio Project File - Name="yassl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=yassl - 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 "yassl.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 "yassl.mak" CFG="yassl - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "yassl - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "yassl - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "yassl - 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 Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX- /O2 /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "yassl - 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 Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX- /ZI /Od /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "yassl - Win32 Release"
+# Name "yassl - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\buffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\cert_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\crypto_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\handshake.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\lock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\log.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\socket_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ssl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\timer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_imp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_int.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\include\buffer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\cert_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\crypto_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\factory.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\handshake.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\lock.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\log.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\socket_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\timer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_error.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_imp.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_int.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_types.hpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extra/yassl/yassl.dsw b/extra/yassl/yassl.dsw
new file mode 100644
index 00000000000..c0bba9acdce
--- /dev/null
+++ b/extra/yassl/yassl.dsw
@@ -0,0 +1,137 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "client"=.\examples\client\client.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "echoclient"=.\examples\echoclient\echoclient.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "echoserver"=.\examples\echoserver\echoserver.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "server"=.\examples\server\server.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "taocrypt"=.\taocrypt\taocrypt.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "test"=.\taocrypt\test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "testsuite"=.\testsuite\testsuite.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "yassl"=.\yassl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/extra/yassl/yassl.vcproj b/extra/yassl/yassl.vcproj
new file mode 100755
index 00000000000..e2915e3f575
--- /dev/null
+++ b/extra/yassl/yassl.vcproj
@@ -0,0 +1,425 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="yassl"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="include,taocrypt\include,mySTL"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ ExceptionHandling="FALSE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/yassl.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\yassl.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="include,taocrypt\include,mySTL"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ ExceptionHandling="FALSE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/yassl.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\yassl.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="src\buffer.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\cert_wrapper.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\crypto_wrapper.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\handshake.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\lock.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\log.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\socket_wrapper.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\ssl.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\timer.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\yassl_error.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\yassl_imp.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="src\yassl_int.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="include\buffer.hpp">
+ </File>
+ <File
+ RelativePath="include\cert_wrapper.hpp">
+ </File>
+ <File
+ RelativePath="include\crypto_wrapper.hpp">
+ </File>
+ <File
+ RelativePath="include\factory.hpp">
+ </File>
+ <File
+ RelativePath="include\handshake.hpp">
+ </File>
+ <File
+ RelativePath="include\lock.hpp">
+ </File>
+ <File
+ RelativePath="include\log.hpp">
+ </File>
+ <File
+ RelativePath="include\socket_wrapper.hpp">
+ </File>
+ <File
+ RelativePath="include\timer.hpp">
+ </File>
+ <File
+ RelativePath="include\yassl_error.hpp">
+ </File>
+ <File
+ RelativePath="include\yassl_imp.hpp">
+ </File>
+ <File
+ RelativePath="include\yassl_int.hpp">
+ </File>
+ <File
+ RelativePath="include\yassl_types.hpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/heap/Makefile.am b/heap/Makefile.am
index 9ce09757802..567c7774751 100644
--- a/heap/Makefile.am
+++ b/heap/Makefile.am
@@ -14,8 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
LDADD = libheap.a ../mysys/libmysys.a ../dbug/libdbug.a \
../strings/libmystrings.a
pkglib_LIBRARIES = libheap.a
diff --git a/heap/_check.c b/heap/_check.c
index a745aee48bf..4316a9926f7 100644
--- a/heap/_check.c
+++ b/heap/_check.c
@@ -123,7 +123,7 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
blength, records))
!= i)
{
- DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
+ DBUG_PRINT("error",("Record in wrong link: Link %d Record: 0x%lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
error=1;
}
else
@@ -180,7 +180,7 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
key_length, SEARCH_FIND | SEARCH_SAME, &not_used))
{
error= 1;
- DBUG_PRINT("error",("Record in wrong link: key: %d Record: %lx\n",
+ DBUG_PRINT("error",("Record in wrong link: key: %d Record: 0x%lx\n",
keynr, recpos));
}
else
diff --git a/heap/heapdef.h b/heap/heapdef.h
index 083765334ab..68d9405138f 100644
--- a/heap/heapdef.h
+++ b/heap/heapdef.h
@@ -86,7 +86,8 @@ extern ulong hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
HASH_INFO *newlink);
extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
- const byte *rec2);
+ const byte *rec2,
+ my_bool diff_if_only_endspace_difference);
extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key);
extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
@@ -94,6 +95,7 @@ extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos);
extern uint hp_rb_key_length(HP_KEYDEF *keydef, const byte *key);
extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key);
+extern uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key);
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
extern int hp_close(register HP_INFO *info);
extern void hp_clear(HP_SHARE *info);
diff --git a/heap/hp_create.c b/heap/hp_create.c
index af32fefea1b..8fcf7dde000 100644
--- a/heap/hp_create.c
+++ b/heap/hp_create.c
@@ -76,9 +76,38 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
case HA_KEYTYPE_UINT24:
case HA_KEYTYPE_INT8:
keyinfo->seg[j].flag|= HA_SWAP_KEY;
+ break;
+ case HA_KEYTYPE_VARBINARY1:
+ /* Case-insensitiveness is handled in coll->hash_sort */
+ keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
+ /* fall_through */
+ case HA_KEYTYPE_VARTEXT1:
+ if (!my_binary_compare(keyinfo->seg[j].charset))
+ keyinfo->flag|= HA_END_SPACE_KEY;
+ keyinfo->flag|= HA_VAR_LENGTH_KEY;
+ /* Save number of bytes used to store length */
+ keyinfo->seg[j].bit_start= 1;
+ break;
+ case HA_KEYTYPE_VARBINARY2:
+ /* Case-insensitiveness is handled in coll->hash_sort */
+ /* fall_through */
+ case HA_KEYTYPE_VARTEXT2:
+ if (!my_binary_compare(keyinfo->seg[j].charset))
+ keyinfo->flag|= HA_END_SPACE_KEY;
+ keyinfo->flag|= HA_VAR_LENGTH_KEY;
+ /* Save number of bytes used to store length */
+ keyinfo->seg[j].bit_start= 2;
+ /*
+ Make future comparison simpler by only having to check for
+ one type
+ */
+ keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
+ break;
default:
break;
}
+ if (keyinfo->seg[j].flag & HA_END_SPACE_ARE_EQUAL)
+ keyinfo->flag|= HA_END_SPACE_KEY;
}
keyinfo->length= length;
length+= keyinfo->rb_tree.size_of_element +
@@ -89,7 +118,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
key_segs++; /* additional HA_KEYTYPE_END segment */
- if (keyinfo->flag & HA_NULL_PART_KEY)
+ if (keyinfo->flag & HA_VAR_LENGTH_KEY)
+ keyinfo->get_key_length= hp_rb_var_key_length;
+ else if (keyinfo->flag & HA_NULL_PART_KEY)
keyinfo->get_key_length= hp_rb_null_key_length;
else
keyinfo->get_key_length= hp_rb_key_length;
@@ -137,6 +168,8 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
keyinfo->write_key= hp_write_key;
keyinfo->hash_buckets= 0;
}
+ if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
+ share->auto_key= i + 1;
}
share->min_records= min_records;
share->max_records= max_records;
diff --git a/heap/hp_delete.c b/heap/hp_delete.c
index 90e537081d3..2d94418a1bf 100644
--- a/heap/hp_delete.c
+++ b/heap/hp_delete.c
@@ -24,7 +24,7 @@ int heap_delete(HP_INFO *info, const byte *record)
HP_SHARE *share=info->s;
HP_KEYDEF *keydef, *end, *p_lastinx;
DBUG_ENTER("heap_delete");
- DBUG_PRINT("enter",("info: %lx record: %lx",info,record));
+ DBUG_PRINT("enter",("info: %lx record: 0x%lx",info,record));
test_active(info);
@@ -123,7 +123,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
while (pos->ptr_to_rec != recpos)
{
- if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
+ if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
last_ptr=pos; /* Previous same key */
gpos=pos;
if (!(pos=pos->next_key))
@@ -139,7 +139,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
/* Save for heap_rnext/heap_rprev */
info->current_hash_ptr=last_ptr;
info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
- DBUG_PRINT("info",("Corrected current_ptr to point at: %lx",
+ DBUG_PRINT("info",("Corrected current_ptr to point at: 0x%lx",
info->current_ptr));
}
empty=pos;
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index ee5b4958e62..77f3cf6d80b 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -255,6 +255,9 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
if (*pos) /* Found null */
{
nr^= (nr << 1) | 1;
+ /* Add key pack length (2) to key for VARCHAR segments */
+ if (seg->type == HA_KEYTYPE_VARTEXT1)
+ key+= 2;
continue;
}
pos++;
@@ -262,14 +265,30 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
if (seg->type == HA_KEYTYPE_TEXT)
{
CHARSET_INFO *cs= seg->charset;
- uint char_length= (uint) ((uchar*) key - pos);
+ uint length= seg->length;
if (cs->mbmaxlen > 1)
{
- uint length= char_length;
+ uint char_length;
char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
- set_if_smaller(char_length, length); /* QQ: ok to remove? */
+ set_if_smaller(length, char_length);
}
- cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
+ cs->coll->hash_sort(cs, pos, length, &nr, &nr2);
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
+ {
+ CHARSET_INFO *cs= seg->charset;
+ uint pack_length= 2; /* Key packing is constant */
+ uint length= uint2korr(pos);
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length;
+ char_length= my_charpos(cs, pos +pack_length,
+ pos +pack_length + length,
+ seg->length/cs->mbmaxlen);
+ set_if_smaller(length, char_length);
+ }
+ cs->coll->hash_sort(cs, pos+pack_length, length, &nr, &nr2);
+ key+= pack_length;
}
else
{
@@ -280,6 +299,7 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
}
}
}
+ DBUG_PRINT("exit", ("hash: 0x%lx", nr));
return((ulong) nr);
}
@@ -287,7 +307,6 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
- /*register*/
ulong nr=1, nr2=4;
HA_KEYSEG *seg,*endseg;
@@ -314,6 +333,21 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
+ {
+ CHARSET_INFO *cs= seg->charset;
+ uint pack_length= seg->bit_start;
+ uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length;
+ char_length= my_charpos(cs, pos + pack_length,
+ pos + pack_length + length,
+ seg->length/cs->mbmaxlen);
+ set_if_smaller(length, char_length);
+ }
+ cs->coll->hash_sort(cs, pos+pack_length, length, &nr, &nr2);
+ }
else
{
for (; pos < end ; pos++)
@@ -323,7 +357,8 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
}
}
- return((ulong) nr);
+ DBUG_PRINT("exit", ("hash: 0x%lx", nr));
+ return(nr);
}
#else
@@ -358,6 +393,9 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
if (*pos)
{
nr^= (nr << 1) | 1;
+ /* Add key pack length (2) to key for VARCHAR segments */
+ if (seg->type == HA_KEYTYPE_VARTEXT1)
+ key+= 2;
continue;
}
pos++;
@@ -366,6 +404,14 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
+ {
+ uint pack_length= 2; /* Key packing is constant */
+ uint length= uint2korr(pos);
+ seg->charset->hash_sort(seg->charset, pos+pack_length, length, &nr,
+ NULL);
+ key+= pack_length;
+ }
else
{
for ( ; pos < (uchar*) key ; pos++)
@@ -375,7 +421,8 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
}
}
}
- return((ulong) nr);
+ DBUG_PRINT("exit", ("hash: 0x%lx", nr));
+ return(nr);
}
/* Calc hashvalue for a key in a record */
@@ -387,7 +434,7 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
- uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
+ uchar *pos=(uchar*) rec+seg->start;
if (seg->null_bit)
{
if (rec[seg->null_pos] & seg->null_bit)
@@ -400,8 +447,16 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
+ {
+ uint pack_length= seg->bit_start;
+ uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
+ seg->charset->hash_sort(seg->charset, pos+pack_length,
+ length, &nr, NULL);
+ }
else
{
+ uchar *end= pos+seg->length;
for ( ; pos < end ; pos++)
{
nr *=16777619;
@@ -409,15 +464,35 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
}
}
- return((ulong) nr);
+ DBUG_PRINT("exit", ("hash: 0x%lx", nr));
+ return(nr);
}
#endif
- /* Compare keys for two records. Returns 0 if they are identical */
+/*
+ Compare keys for two records. Returns 0 if they are identical
+
+ SYNOPSIS
+ hp_rec_key_cmp()
+ keydef Key definition
+ rec1 Record to compare
+ rec2 Other record to compare
+ diff_if_only_endspace_difference
+ Different number of end space is significant
+
+ NOTES
+ diff_if_only_endspace_difference is used to allow us to insert
+ 'a' and 'a ' when there is an an unique key.
-int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
+ RETURN
+ 0 Key is identical
+ <> 0 Key differes
+*/
+
+int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2,
+ my_bool diff_if_only_endspace_difference)
{
HA_KEYSEG *seg,*endseg;
@@ -442,9 +517,9 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
{
uint char_length= seg->length / cs->mbmaxlen;
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
- set_if_smaller(char_length1, seg->length); /* QQ: ok to remove? */
+ set_if_smaller(char_length1, seg->length);
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
- set_if_smaller(char_length2, seg->length); /* QQ: ok to remove? */
+ set_if_smaller(char_length2, seg->length);
}
else
{
@@ -452,7 +527,44 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
}
if (seg->charset->coll->strnncollsp(seg->charset,
pos1,char_length1,
- pos2,char_length2))
+ pos2,char_length2, 0))
+ return 1;
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
+ {
+ uchar *pos1= (uchar*) rec1 + seg->start;
+ uchar *pos2= (uchar*) rec2 + seg->start;
+ uint char_length1, char_length2;
+ uint pack_length= seg->bit_start;
+ CHARSET_INFO *cs= seg->charset;
+ if (pack_length == 1)
+ {
+ char_length1= (uint) *(uchar*) pos1++;
+ char_length2= (uint) *(uchar*) pos2++;
+ }
+ else
+ {
+ char_length1= uint2korr(pos1);
+ char_length2= uint2korr(pos2);
+ pos1+= 2;
+ pos2+= 2;
+ }
+ if (cs->mbmaxlen > 1)
+ {
+ uint safe_length1= char_length1;
+ uint safe_length2= char_length2;
+ uint char_length= seg->length / cs->mbmaxlen;
+ char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
+ set_if_smaller(char_length1, safe_length1);
+ char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
+ set_if_smaller(char_length2, safe_length2);
+ }
+
+ if (cs->coll->strnncollsp(seg->charset,
+ pos1, char_length1,
+ pos2, char_length2,
+ seg->flag & HA_END_SPACE_ARE_EQUAL ?
+ 0 : diff_if_only_endspace_difference))
return 1;
}
else
@@ -480,7 +592,12 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (found_null != (int) *key++)
return 1;
if (found_null)
+ {
+ /* Add key pack length (2) to key for VARCHAR segments */
+ if (seg->type == HA_KEYTYPE_VARTEXT1)
+ key+= 2;
continue;
+ }
}
if (seg->type == HA_KEYTYPE_TEXT)
{
@@ -504,7 +621,33 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (seg->charset->coll->strnncollsp(seg->charset,
(uchar*) pos, char_length_rec,
- (uchar*) key, char_length_key))
+ (uchar*) key, char_length_key, 0))
+ return 1;
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
+ {
+ uchar *pos= (uchar*) rec + seg->start;
+ CHARSET_INFO *cs= seg->charset;
+ uint pack_length= seg->bit_start;
+ uint char_length_rec= (pack_length == 1 ? (uint) *(uchar*) pos :
+ uint2korr(pos));
+ /* Key segments are always packed with 2 bytes */
+ uint char_length_key= uint2korr(key);
+ pos+= pack_length;
+ key+= 2; /* skip key pack length */
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length1, char_length2;
+ char_length1= char_length2= seg->length / cs->mbmaxlen;
+ char_length1= my_charpos(cs, key, key + char_length_key, char_length1);
+ set_if_smaller(char_length_key, char_length1);
+ char_length2= my_charpos(cs, pos, pos + char_length_rec, char_length2);
+ set_if_smaller(char_length_rec, char_length2);
+ }
+
+ if (cs->coll->strnncollsp(seg->charset,
+ (uchar*) pos, char_length_rec,
+ (uchar*) key, char_length_key, 0))
return 1;
}
else
@@ -536,11 +679,20 @@ void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
char_length / cs->mbmaxlen);
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
}
+ if (seg->type == HA_KEYTYPE_VARTEXT1)
+ char_length+= seg->bit_start; /* Copy also length */
memcpy(key,rec+seg->start,(size_t) char_length);
key+= char_length;
}
}
+#define FIX_LENGTH(cs, pos, length, char_length) \
+ do { \
+ if (length > char_length) \
+ char_length= my_charpos(cs, pos, pos+length, char_length); \
+ set_if_smaller(char_length,length); \
+ } while(0)
+
uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos)
@@ -593,6 +745,26 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
}
continue;
}
+
+ if (seg->flag & HA_VAR_LENGTH_PART)
+ {
+ uchar *pos= (uchar*) rec + seg->start;
+ uint length= seg->length;
+ uint pack_length= seg->bit_start;
+ uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
+ uint2korr(pos));
+ CHARSET_INFO *cs= seg->charset;
+ char_length= length/cs->mbmaxlen;
+
+ pos+= pack_length; /* Skip VARCHAR length */
+ set_if_smaller(length,tmp_length);
+ FIX_LENGTH(cs, pos, length, char_length);
+ store_key_length_inc(key,char_length);
+ memcpy((byte*) key,(byte*) pos,(size_t) char_length);
+ key+= char_length;
+ continue;
+ }
+
char_length= seg->length;
if (seg->charset->mbmaxlen > 1)
{
@@ -608,7 +780,7 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
key+= seg->length;
}
memcpy(key, &recpos, sizeof(byte*));
- return key - start_key;
+ return (uint) (key - start_key);
}
@@ -643,6 +815,23 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
}
continue;
}
+ if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+ {
+ /* Length of key-part used with heap_rkey() always 2 */
+ uint tmp_length=uint2korr(old);
+ uint length= seg->length;
+ CHARSET_INFO *cs= seg->charset;
+ char_length= length/cs->mbmaxlen;
+
+ k_len-= 2+length;
+ old+= 2;
+ set_if_smaller(length,tmp_length); /* Safety */
+ FIX_LENGTH(cs, old, length, char_length);
+ store_key_length_inc(key,char_length);
+ memcpy((byte*) key, old,(size_t) char_length);
+ key+= char_length;
+ continue;
+ }
char_length= seg->length;
if (seg->charset->mbmaxlen > 1)
{
@@ -657,7 +846,7 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
key+= seg->length;
k_len-= seg->length;
}
- return key - start_key;
+ return (uint) (key - start_key);
}
@@ -679,9 +868,30 @@ uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
continue;
key+= seg->length;
}
- return key - start_key;
+ return (uint) (key - start_key);
}
+
+uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key)
+{
+ const byte *start_key= key;
+ HA_KEYSEG *seg, *endseg;
+
+ for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
+ {
+ uint length= seg->length;
+ if (seg->null_bit && !*key++)
+ continue;
+ if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+ {
+ get_key_length(length, key);
+ }
+ key+= length;
+ }
+ return (uint) (key - start_key);
+}
+
+
/*
Test if any of the key parts are NULL.
Return:
diff --git a/heap/hp_open.c b/heap/hp_open.c
index 1fa832208fb..fd937229b0d 100644
--- a/heap/hp_open.c
+++ b/heap/hp_open.c
@@ -63,7 +63,7 @@ HP_INFO *heap_open(const char *name, int mode)
#ifndef DBUG_OFF
info->opt_flag= READ_CHECK_USED; /* Check when changing */
#endif
- DBUG_PRINT("exit",("heap: %lx reclength: %d records_in_block: %d",
+ DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %d",
info,share->reclength,share->block.records_in_block));
DBUG_RETURN(info);
}
@@ -82,7 +82,7 @@ HP_SHARE *hp_find_named_heap(const char *name)
info= (HP_SHARE*) pos->data;
if (!strcmp(name, info->name))
{
- DBUG_PRINT("exit", ("Old heap_database: %lx",info));
+ DBUG_PRINT("exit", ("Old heap_database: 0x%lx",info));
DBUG_RETURN(info);
}
}
diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c
index 2c23d9d721e..f5f22a877a1 100644
--- a/heap/hp_rkey.c
+++ b/heap/hp_rkey.c
@@ -23,7 +23,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
HP_SHARE *share= info->s;
HP_KEYDEF *keyinfo= share->keydef + inx;
DBUG_ENTER("heap_rkey");
- DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
+ DBUG_PRINT("enter",("base: 0x%lx inx: %d",info,inx));
if ((uint) inx >= share->keys)
{
@@ -64,7 +64,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
info->update= 0;
DBUG_RETURN(my_errno);
}
- if (!(keyinfo->flag & HA_NOSAME))
+ if (!(keyinfo->flag & HA_NOSAME) || (keyinfo->flag & HA_END_SPACE_KEY))
memcpy(info->lastkey, key, (size_t) keyinfo->length);
}
memcpy(record, pos, (size_t) share->reclength);
diff --git a/heap/hp_rrnd.c b/heap/hp_rrnd.c
index cce3ce24e51..4daa3a06377 100644
--- a/heap/hp_rrnd.c
+++ b/heap/hp_rrnd.c
@@ -29,7 +29,7 @@ int heap_rrnd(register HP_INFO *info, byte *record, byte *pos)
{
HP_SHARE *share=info->s;
DBUG_ENTER("heap_rrnd");
- DBUG_PRINT("enter",("info: %lx pos: %lx",info,pos));
+ DBUG_PRINT("enter",("info: 0x%lx pos: %lx",info,pos));
info->lastinx= -1;
if (!(info->current_ptr= pos))
@@ -44,7 +44,7 @@ int heap_rrnd(register HP_INFO *info, byte *record, byte *pos)
}
info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
memcpy(record,info->current_ptr,(size_t) share->reclength);
- DBUG_PRINT("exit",("found record at %lx",info->current_ptr));
+ DBUG_PRINT("exit",("found record at 0x%lx",info->current_ptr));
info->current_hash_ptr=0; /* Can't use rnext */
DBUG_RETURN(0);
} /* heap_rrnd */
@@ -64,7 +64,7 @@ int heap_rrnd_old(register HP_INFO *info, byte *record, ulong pos)
{
HP_SHARE *share=info->s;
DBUG_ENTER("heap_rrnd");
- DBUG_PRINT("enter",("info: %lx pos: %ld",info,pos));
+ DBUG_PRINT("enter",("info: 0x%lx pos: %ld",info,pos));
info->lastinx= -1;
if (pos == (ulong) -1)
@@ -98,7 +98,7 @@ end:
}
info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
memcpy(record,info->current_ptr,(size_t) share->reclength);
- DBUG_PRINT("exit",("found record at %lx",info->current_ptr));
+ DBUG_PRINT("exit",("found record at 0x%lx",info->current_ptr));
info->current_hash_ptr=0; /* Can't use rnext */
DBUG_RETURN(0);
} /* heap_rrnd */
diff --git a/heap/hp_update.c b/heap/hp_update.c
index 2ed0edf08de..63ada225f06 100644
--- a/heap/hp_update.c
+++ b/heap/hp_update.c
@@ -37,7 +37,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
p_lastinx= share->keydef + info->lastinx;
for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++)
{
- if (hp_rec_key_cmp(keydef, old, heap_new))
+ if (hp_rec_key_cmp(keydef, old, heap_new, 0))
{
if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
(*keydef->write_key)(info, keydef, heap_new, pos))
@@ -60,7 +60,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
err:
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
{
- info->errkey = keydef - share->keydef;
+ info->errkey = (int) (keydef - share->keydef);
if (keydef->algorithm == HA_KEY_ALG_BTREE)
{
/* we don't need to delete non-inserted key from rb-tree */
@@ -74,7 +74,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
}
while (keydef >= share->keydef)
{
- if (hp_rec_key_cmp(keydef, old, heap_new))
+ if (hp_rec_key_cmp(keydef, old, heap_new, 0))
{
if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
(*keydef->write_key)(info, keydef, old, pos))
diff --git a/heap/hp_write.c b/heap/hp_write.c
index 808fe6608b1..a60d32eecb6 100644
--- a/heap/hp_write.c
+++ b/heap/hp_write.c
@@ -105,7 +105,7 @@ int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
if (keyinfo->flag & HA_NOSAME)
{
- custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
+ custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME | SEARCH_UPDATE;
keyinfo->rb_tree.flag= TREE_NO_DUPS;
}
else
@@ -138,7 +138,7 @@ static byte *next_free_record_pos(HP_SHARE *info)
pos=info->del_link;
info->del_link= *((byte**) pos);
info->deleted--;
- DBUG_PRINT("exit",("Used old position: %lx",pos));
+ DBUG_PRINT("exit",("Used old position: 0x%lx",pos));
DBUG_RETURN(pos);
}
if (!(block_pos=(info->records % info->block.records_in_block)))
@@ -370,7 +370,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
pos=empty;
do
{
- if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
+ if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
{
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
}
diff --git a/include/Makefile.am b/include/Makefile.am
index 0c845900a4f..5f426843950 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -17,31 +17,26 @@
BUILT_SOURCES = mysql_version.h m_ctype.h my_config.h
pkginclude_HEADERS = my_dbug.h m_string.h my_sys.h my_list.h my_xml.h \
- mysql.h mysql_com.h mysqld_error.h mysql_embed.h \
+ mysql.h mysql_com.h mysql_embed.h \
my_semaphore.h my_pthread.h my_no_pthread.h raid.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 mysql_time.h $(BUILT_SOURCES)
+ 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\
+ heap.h my_bitmap.h\
myisam.h myisampack.h myisammrg.h ft_global.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 my_time.h
+ mysql_version.h.in my_handler.h my_time.h decimal.h
# mysql_version.h are generated
-SUPERCLEANFILES = mysql_version.h my_config.h
+CLEANFILES = mysql_version.h my_config.h readline
# Some include files that may be moved and patched by configure
-DISTCLEANFILES = sched.h $(SUPERCLEANFILES)
-
-clean:
- $(RM) -fr readline
-distclean:
- $(RM) -fr readline
+DISTCLEANFILES = sched.h $(CLEANFILES)
all-local: my_config.h
diff --git a/include/config-netware.h b/include/config-netware.h
index 1b24655ee89..4c46ccd3ec7 100644
--- a/include/config-netware.h
+++ b/include/config-netware.h
@@ -45,7 +45,9 @@ extern "C" {
#undef HAVE_SCHED_H
#undef HAVE_SYS_MMAN_H
#undef HAVE_SYNCH_H
+#undef HAVE_MMAP
#undef HAVE_RINT
+
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
#define HAVE_PTHREAD_SIGMASK 1
#define HAVE_PTHREAD_YIELD_ZERO_ARG 1
diff --git a/include/config-win.h b/include/config-win.h
index 0899d961d14..4eaf97cd4f5 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -76,6 +76,7 @@ functions */
#define F_EXCLUSIVE 1 /* We have only exclusive locking */
#define F_TO_EOF (INT_MAX32/2) /* size for lock of all file */
#define F_OK 0 /* parameter to access() */
+#define W_OK 2
#define S_IROTH S_IREAD /* for my_lib */
@@ -283,8 +284,8 @@ inline double ulonglong2double(ulonglong value)
#define doublestore(T,V) { *((long *) T) = *((long*) &V); \
*(((long *) T)+1) = *(((long*) &V)+1); }
#define float4get(V,M) { *((long *) &(V)) = *((long*) (M)); }
-#define floatget(V,M) memcpy((byte*) &V,(byte*) (M),sizeof(float))
#define floatstore(T,V) memcpy((byte*)(T), (byte*)(&V), sizeof(float))
+#define floatget(V,M) memcpy((byte*)(&V), (byte*)(M), sizeof(float))
#define float8get(V,M) doubleget((V),(M))
#define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float))
#define float8store(V,M) doublestore((V),(M))
@@ -322,7 +323,7 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_QUERY_CACHE
#define SPRINTF_RETURNS_INT
#define HAVE_SETFILEPOINTER
-#define HAVE_VIO
+#define HAVE_VIO_READ_BUFF
#ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */
@@ -350,6 +351,12 @@ inline double ulonglong2double(ulonglong value)
#define SHAREDIR "share"
#define DEFAULT_CHARSET_HOME "C:/mysql/"
#endif
+#ifndef DEFAULT_HOME_ENV
+#define DEFAULT_HOME_ENV MYSQL_HOME
+#endif
+#ifndef DEFAULT_GROUP_SUFFIX_ENV
+#define DEFAULT_GROUP_SUFFIX_ENV MYSQL_GROUP_SUFFIX
+#endif
/* File name handling */
@@ -361,6 +368,7 @@ inline double ulonglong2double(ulonglong value)
#define DO_NOT_REMOVE_THREAD_WRAPPERS
#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V))
+#define thread_safe_decrement(V,L) InterlockedDecrement((long*) &(V))
/* The following is only used for statistics, so it should be good enough */
#ifdef __NT__ /* This should also work on Win98 but .. */
#define thread_safe_add(V,C,L) InterlockedExchangeAdd((long*) &(V),(C))
@@ -374,6 +382,7 @@ inline double ulonglong2double(ulonglong value)
#define statistic_add(V,C,L) (V)+=(C)
#endif
#define statistic_increment(V,L) thread_safe_increment((V),(L))
+#define statistic_decrement(V,L) thread_safe_decrement((V),(L))
#define shared_memory_buffer_length 16000
#define default_shared_memory_base_name "MYSQL"
@@ -383,6 +392,9 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_SPATIAL 1
#define HAVE_RTREE_KEYS 1
+#define HAVE_OPENSSL 1
+#define HAVE_YASSL 1
+
/* Define charsets you want */
/* #undef HAVE_CHARSET_armscii8 */
/* #undef HAVE_CHARSET_ascii */
@@ -396,6 +408,7 @@ inline double ulonglong2double(ulonglong value)
/* #undef HAVE_CHARSET_cp866 */
#define HAVE_CHARSET_cp932 1
/* #undef HAVE_CHARSET_dec8 */
+#define HAVE_CHARSET_eucjpms 1
#define HAVE_CHARSET_euckr 1
#define HAVE_CHARSET_gb2312 1
#define HAVE_CHARSET_gbk 1
diff --git a/include/decimal.h b/include/decimal.h
new file mode 100644
index 00000000000..2648e04c1cf
--- /dev/null
+++ b/include/decimal.h
@@ -0,0 +1,107 @@
+/* Copyright (C) 2000 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 _decimal_h
+#define _decimal_h
+
+typedef enum
+{TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR}
+ decimal_round_mode;
+typedef int32 decimal_digit_t;
+
+typedef struct st_decimal_t {
+ int intg, frac, len;
+ my_bool sign;
+ decimal_digit_t *buf;
+} decimal_t;
+
+int internal_str2dec(const char *from, decimal_t *to, char **end,
+ my_bool fixed);
+int decimal2string(decimal_t *from, char *to, int *to_len,
+ int fixed_precision, int fixed_decimals,
+ char filler);
+int decimal2ulonglong(decimal_t *from, ulonglong *to);
+int ulonglong2decimal(ulonglong from, decimal_t *to);
+int decimal2longlong(decimal_t *from, longlong *to);
+int longlong2decimal(longlong from, decimal_t *to);
+int decimal2double(decimal_t *from, double *to);
+int double2decimal(double from, decimal_t *to);
+int decimal_actual_fraction(decimal_t *from);
+int decimal2bin(decimal_t *from, char *to, int precision, int scale);
+int bin2decimal(char *from, decimal_t *to, int precision, int scale);
+
+int decimal_size(int precision, int scale);
+int decimal_bin_size(int precision, int scale);
+int decimal_result_size(decimal_t *from1, decimal_t *from2, char op,
+ int param);
+
+int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to);
+int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to);
+int decimal_cmp(decimal_t *from1, decimal_t *from2);
+int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to);
+int decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to,
+ int scale_incr);
+int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to);
+int decimal_round(decimal_t *from, decimal_t *to, int new_scale,
+ decimal_round_mode mode);
+int decimal_is_zero(decimal_t *from);
+void max_decimal(int precision, int frac, decimal_t *to);
+
+#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0)
+#define string2decimal_fixed(A,B,C) internal_str2dec((A), (B), (C), 1)
+
+/* set a decimal_t to zero */
+
+#define decimal_make_zero(dec) do { \
+ (dec)->buf[0]=0; \
+ (dec)->intg=1; \
+ (dec)->frac=0; \
+ (dec)->sign=0; \
+ } while(0)
+
+/*
+ returns the length of the buffer to hold string representation
+ of the decimal (including decimal dot, possible sign and \0)
+*/
+
+#define decimal_string_size(dec) (((dec)->intg ? (dec)->intg : 1) + \
+ (dec)->frac + ((dec)->frac > 0) + 2)
+
+/* negate a decimal */
+#define decimal_neg(dec) do { (dec)->sign^=1; } while(0)
+
+/*
+ conventions:
+
+ decimal_smth() == 0 -- everything's ok
+ decimal_smth() <= 1 -- result is usable, but precision loss is possible
+ decimal_smth() <= 2 -- result can be unusable, most significant digits
+ could've been lost
+ decimal_smth() > 2 -- no result was generated
+*/
+
+#define E_DEC_OK 0
+#define E_DEC_TRUNCATED 1
+#define E_DEC_OVERFLOW 2
+#define E_DEC_DIV_ZERO 4
+#define E_DEC_BAD_NUM 8
+#define E_DEC_OOM 16
+
+#define E_DEC_ERROR 31
+#define E_DEC_FATAL_ERROR 30
+
+#endif
+
diff --git a/include/errmsg.h b/include/errmsg.h
index 96977227666..1dd5759c104 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -21,6 +21,7 @@
extern "C" {
#endif
void init_client_errs(void);
+void finish_client_errs(void);
extern const char *client_errors[]; /* Error messages */
#ifdef __cplusplus
}
@@ -35,6 +36,9 @@ extern const char *client_errors[]; /* Error messages */
#endif
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
+/* Do not add error numbers before CR_ERROR_FIRST. */
+/* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */
+#define CR_ERROR_FIRST 2000 /*Copy first error nr.*/
#define CR_UNKNOWN_ERROR 2000
#define CR_SOCKET_CREATE_ERROR 2001
#define CR_CONNECTION_ERROR 2002
@@ -91,3 +95,8 @@ extern const char *client_errors[]; /* Error messages */
#define CR_FETCH_CANCELED 2050
#define CR_NO_DATA 2051
#define CR_NO_STMT_METADATA 2052
+#define CR_NO_RESULT_SET 2053
+#define CR_NOT_IMPLEMENTED 2054
+#define CR_ERROR_LAST /*Copy last error nr:*/ 2054
+/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
+
diff --git a/include/m_ctype.h b/include/m_ctype.h
index a5dc7cc00c6..e0a26c4ce56 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -44,6 +44,9 @@ typedef struct unicase_info_st
uint16 sort;
} MY_UNICASE_INFO;
+extern MY_UNICASE_INFO *my_unicase_default[256];
+extern MY_UNICASE_INFO *my_unicase_turkish[256];
+
#define MY_CS_ILSEQ 0
#define MY_CS_ILUNI 0
#define MY_CS_TOOSMALL -1
@@ -85,7 +88,7 @@ enum my_lex_states
{
MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT,
MY_LEX_IDENT_SEP, MY_LEX_IDENT_START,
- MY_LEX_REAL, MY_LEX_HEX_NUMBER,
+ MY_LEX_REAL, MY_LEX_HEX_NUMBER, MY_LEX_BIN_NUMBER,
MY_LEX_CMP_OP, MY_LEX_LONG_CMP_OP, MY_LEX_STRING, MY_LEX_COMMENT, MY_LEX_END,
MY_LEX_OPERATOR_OR_IDENT, MY_LEX_NUMBER_IDENT, MY_LEX_INT_OR_REAL,
MY_LEX_REAL_OR_POINT, MY_LEX_BOOL, MY_LEX_EOL, MY_LEX_ESCAPE,
@@ -106,9 +109,11 @@ typedef struct my_collation_handler_st
int (*strnncoll)(struct charset_info_st *,
const uchar *, uint, const uchar *, uint, my_bool);
int (*strnncollsp)(struct charset_info_st *,
- const uchar *, uint, const uchar *, uint);
+ const uchar *, uint, const uchar *, uint,
+ my_bool diff_if_only_endspace_difference);
int (*strnxfrm)(struct charset_info_st *,
uchar *, uint, const uchar *, uint);
+ uint (*strnxfrmlen)(struct charset_info_st *, uint);
my_bool (*like_range)(struct charset_info_st *,
const char *s, uint s_length,
pchar w_prefix, pchar w_one, pchar w_many,
@@ -130,6 +135,7 @@ typedef struct my_collation_handler_st
/* Hash calculation */
void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len,
ulong *nr1, ulong *nr2);
+ my_bool (*propagate)(struct charset_info_st *cs, const uchar *str, uint len);
} MY_COLLATION_HANDLER;
extern MY_COLLATION_HANDLER my_collation_mb_bin_handler;
@@ -161,8 +167,10 @@ typedef struct my_charset_handler_st
/* Functions for case and sort convertion */
void (*caseup_str)(struct charset_info_st *, char *);
void (*casedn_str)(struct charset_info_st *, char *);
- void (*caseup)(struct charset_info_st *, char *, uint);
- void (*casedn)(struct charset_info_st *, char *, uint);
+ uint (*caseup)(struct charset_info_st *, char *src, uint srclen,
+ char *dst, uint dstlen);
+ uint (*casedn)(struct charset_info_st *, char *src, uint srclen,
+ char *dst, uint dstlen);
/* Charset dependant snprintf() */
int (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt,
@@ -185,7 +193,7 @@ typedef struct my_charset_handler_st
int base, char **e, int *err);
double (*strntod)(struct charset_info_st *, char *s, uint l, char **e,
int *err);
- longlong (*my_strtoll10)(struct charset_info_st *cs,
+ longlong (*strtoll10)(struct charset_info_st *cs,
const char *nptr, char **endptr, int *error);
ulong (*scan)(struct charset_info_st *, const char *b, const char *e,
int sq);
@@ -213,9 +221,12 @@ typedef struct charset_info_st
uint16 **sort_order_big;
uint16 *tab_to_uni;
MY_UNI_IDX *tab_from_uni;
+ MY_UNICASE_INFO **caseinfo;
uchar *state_map;
uchar *ident_map;
uint strxfrm_multiply;
+ uchar caseup_multiply;
+ uchar casedn_multiply;
uint mbminlen;
uint mbmaxlen;
uint16 min_sort_char;
@@ -233,6 +244,8 @@ extern CHARSET_INFO my_charset_big5_chinese_ci;
extern CHARSET_INFO my_charset_big5_bin;
extern CHARSET_INFO my_charset_cp932_japanese_ci;
extern CHARSET_INFO my_charset_cp932_bin;
+extern CHARSET_INFO my_charset_eucjpms_japanese_ci;
+extern CHARSET_INFO my_charset_eucjpms_bin;
extern CHARSET_INFO my_charset_euckr_korean_ci;
extern CHARSET_INFO my_charset_euckr_bin;
extern CHARSET_INFO my_charset_gb2312_chinese_ci;
@@ -258,12 +271,14 @@ extern CHARSET_INFO my_charset_cp1250_czech_ci;
/* declarations for simple charsets */
extern int my_strnxfrm_simple(CHARSET_INFO *, uchar *, uint, const uchar *,
- uint);
+ uint);
+uint my_strnxfrmlen_simple(CHARSET_INFO *, uint);
extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, uint,
const uchar *, uint, my_bool);
extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, uint,
- const uchar *, uint);
+ const uchar *, uint,
+ my_bool diff_if_only_endspace_difference);
extern void my_hash_sort_simple(CHARSET_INFO *cs,
const uchar *key, uint len,
@@ -280,8 +295,10 @@ extern uint my_instr_simple(struct charset_info_st *,
/* Functions for 8bit */
extern void my_caseup_str_8bit(CHARSET_INFO *, char *);
extern void my_casedn_str_8bit(CHARSET_INFO *, char *);
-extern void my_caseup_8bit(CHARSET_INFO *, char *, uint);
-extern void my_casedn_8bit(CHARSET_INFO *, char *, uint);
+extern uint my_caseup_8bit(CHARSET_INFO *, char *src, uint srclen,
+ char *dst, uint dstlen);
+extern uint my_casedn_8bit(CHARSET_INFO *, char *src, uint srclen,
+ char *dst, uint dstlen);
extern int my_strcasecmp_8bit(CHARSET_INFO * cs, const char *, const char *);
@@ -353,8 +370,10 @@ int my_mbcharlen_8bit(CHARSET_INFO *, uint c);
/* Functions for multibyte charsets */
extern void my_caseup_str_mb(CHARSET_INFO *, char *);
extern void my_casedn_str_mb(CHARSET_INFO *, char *);
-extern void my_caseup_mb(CHARSET_INFO *, char *, uint);
-extern void my_casedn_mb(CHARSET_INFO *, char *, uint);
+extern uint my_caseup_mb(CHARSET_INFO *, char *src, uint srclen,
+ char *dst, uint dstlen);
+extern uint my_casedn_mb(CHARSET_INFO *, char *src, uint srclen,
+ char *dst, uint dstlen);
extern int my_strcasecmp_mb(CHARSET_INFO * cs,const char *, const char *);
int my_wildcmp_mb(CHARSET_INFO *,
@@ -380,6 +399,10 @@ int my_wildcmp_unicode(CHARSET_INFO *cs,
extern my_bool my_parse_charset_xml(const char *bug, uint len,
int (*add)(CHARSET_INFO *cs));
+my_bool my_propagate_simple(CHARSET_INFO *cs, const uchar *str, uint len);
+my_bool my_propagate_complex(CHARSET_INFO *cs, const uchar *str, uint len);
+
+
#define _MY_U 01 /* Upper case */
#define _MY_L 02 /* Lower case */
#define _MY_NMR 04 /* Numeral (digit) */
@@ -431,8 +454,6 @@ extern my_bool my_parse_charset_xml(const char *bug, uint len,
#define my_mbcharlen(s, a) 1
#endif
-#define my_caseup(s, a, l) ((s)->cset->caseup((s), (a), (l)))
-#define my_casedn(s, a, l) ((s)->cset->casedn((s), (a), (l)))
#define my_caseup_str(s, a) ((s)->cset->caseup_str((s), (a)))
#define my_casedn_str(s, a) ((s)->cset->casedn_str((s), (a)))
#define my_strntol(s, a, b, c, d, e) ((s)->cset->strntol((s),(a),(b),(c),(d),(e)))
diff --git a/include/m_string.h b/include/m_string.h
index d3465363beb..33ba9c155c2 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -88,6 +88,13 @@
extern "C" {
#endif
+/*
+ my_str_malloc() and my_str_free() are assigned to implementations in
+ strings/alloc.c, but can be overridden in the calling program.
+ */
+extern void *(*my_str_malloc)(size_t);
+extern void (*my_str_free)(void *);
+
#if defined(HAVE_STPCPY) && !defined(HAVE_mit_thread)
#define strmov(A,B) stpcpy((A),(B))
#ifndef stpcpy
diff --git a/include/merge.h b/include/merge.h
deleted file mode 100644
index 97cea5fabb1..00000000000
--- a/include/merge.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Copyright (C) 2000 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 should be included when using merge_isam_funktions */
-/* Author: Michael Widenius */
-
-#ifndef _merge_h
-#define _merge_h
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _my_base_h
-#include <my_base.h>
-#endif
-#ifndef _nisam_h
-#include <nisam.h>
-#endif
-
-#define MRG_NAME_EXT ".MRG"
-
- /* Param to/from mrg_info */
-
-typedef struct st_mrg_info /* Struct from h_info */
-{
- ulonglong records; /* Records in database */
- ulonglong deleted; /* Deleted records in database */
- ulonglong recpos; /* Pos for last used record */
- ulonglong data_file_length;
- uint reclength; /* Recordlength */
- int errkey; /* With key was dupplicated on err */
- uint options; /* HA_OPTION_... used */
-} MERGE_INFO;
-
-typedef struct st_mrg_table_info
-{
- N_INFO *table;
- ulonglong file_offset;
-} MRG_TABLE;
-
-typedef struct st_merge
-{
- MRG_TABLE *open_tables,*current_table,*end_table,*last_used_table;
- ulonglong records; /* records in tables */
- ulonglong del; /* Removed records */
- ulonglong data_file_length;
- uint tables,options,reclength;
- my_bool cache_in_use;
- LIST open_list;
-} MRG_INFO;
-
-typedef ulong mrg_off_t;
-
- /* Prototypes for merge-functions */
-
-extern int mrg_close(MRG_INFO *file);
-extern int mrg_delete(MRG_INFO *file,const byte *buff);
-extern MRG_INFO *mrg_open(const char *name,int mode,int wait_if_locked);
-extern int mrg_panic(enum ha_panic_function function);
-extern int mrg_rfirst(MRG_INFO *file,byte *buf,int inx);
-extern int mrg_rkey(MRG_INFO *file,byte *buf,int inx,const byte *key,
- uint key_len, enum ha_rkey_function search_flag);
-extern int mrg_rrnd(MRG_INFO *file,byte *buf, mrg_off_t pos);
-extern int mrg_rsame(MRG_INFO *file,byte *record,int inx);
-extern int mrg_update(MRG_INFO *file,const byte *old,const byte *new_rec);
-extern int mrg_info(MRG_INFO *file,MERGE_INFO *x,int flag);
-extern int mrg_lock_database(MRG_INFO *file,int lock_type);
-extern int mrg_create(const char *name,const char **table_names);
-extern int mrg_extra(MRG_INFO *file,enum ha_extra_function function);
-extern ha_rows mrg_records_in_range(MRG_INFO *info,int inx,
- const byte *start_key,uint start_key_len,
- enum ha_rkey_function start_search_flag,
- const byte *end_key,uint end_key_len,
- enum ha_rkey_function end_search_flag);
-
-extern mrg_off_t mrg_position(MRG_INFO *info);
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/include/my_base.h b/include/my_base.h
index d702ec45140..c76cf8c604e 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -146,7 +146,13 @@ enum ha_extra_function {
On-the-fly switching between unique and non-unique key inserting.
*/
HA_EXTRA_CHANGE_KEY_TO_UNIQUE,
- HA_EXTRA_CHANGE_KEY_TO_DUP
+ HA_EXTRA_CHANGE_KEY_TO_DUP,
+ /*
+ When using HA_EXTRA_KEYREAD, overwrite only key member fields and keep
+ other fields intact. When this is off (by default) InnoDB will use memcpy
+ to overwrite entire row.
+ */
+ HA_EXTRA_KEYREAD_PRESERVE_FIELDS
};
/* The following is parameter to ha_panic() */
@@ -175,8 +181,13 @@ enum ha_base_keytype {
HA_KEYTYPE_INT24=12,
HA_KEYTYPE_UINT24=13,
HA_KEYTYPE_INT8=14,
- HA_KEYTYPE_VARTEXT=15, /* Key is sorted as letters */
- HA_KEYTYPE_VARBINARY=16 /* Key is sorted as unsigned chars */
+ /* Varchar (0-255 bytes) with length packed with 1 byte */
+ HA_KEYTYPE_VARTEXT1=15, /* Key is sorted as letters */
+ HA_KEYTYPE_VARBINARY1=16, /* Key is sorted as unsigned chars */
+ /* Varchar (0-65535 bytes) with length packed with 2 bytes */
+ HA_KEYTYPE_VARTEXT2=17, /* Key is sorted as letters */
+ HA_KEYTYPE_VARBINARY2=18, /* Key is sorted as unsigned chars */
+ HA_KEYTYPE_BIT=19
};
#define HA_MAX_KEYTYPE 31 /* Must be log2-1 */
@@ -207,7 +218,7 @@ enum ha_base_keytype {
/*
Key has a part that can have end space. If this is an unique key
we have to handle it differently from other unique keys as we can find
- many matching rows for one key (becaue end space are not compared)
+ many matching rows for one key (because end space are not compared)
*/
#define HA_END_SPACE_KEY 4096
@@ -215,12 +226,18 @@ enum ha_base_keytype {
#define HA_SPACE_PACK 1 /* Pack space in key-seg */
#define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */
-#define HA_VAR_LENGTH 8
+#define HA_VAR_LENGTH_PART 8
#define HA_NULL_PART 16
#define HA_BLOB_PART 32
#define HA_SWAP_KEY 64
#define HA_REVERSE_SORT 128 /* Sort key in reverse order */
#define HA_NO_SORT 256 /* do not bother sorting on this keyseg */
+/*
+ End space in unique/varchar are considered equal. (Like 'a' and 'a ')
+ Only needed for internal temporary tables.
+*/
+#define HA_END_SPACE_ARE_EQUAL 512
+#define HA_BIT_PART 1024
/* optionbits for database */
#define HA_OPTION_PACK_RECORD 1
@@ -256,6 +273,9 @@ enum ha_base_keytype {
/* Errorcodes given by functions */
/* opt_sum_query() assumes these codes are > 1 */
+/* Do not add error numbers before HA_ERR_FIRST. */
+/* If necessary to add lower numbers, change HA_ERR_FIRST accordingly. */
+#define HA_ERR_FIRST 120 /*Copy first error nr.*/
#define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */
#define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */
#define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */
@@ -292,6 +312,11 @@ enum ha_base_keytype {
#define HA_ERR_TABLE_EXIST 156 /* The table existed in storage engine */
#define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */
#define HA_ERR_NULL_IN_SPATIAL 158 /* NULLs are not supported in spatial index */
+#define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */
+
+#define HA_ERR_LAST 159 /*Copy last error nr.*/
+/* Add error numbers before HA_ERR_LAST and change it accordingly. */
+#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
/* Other constants */
@@ -342,6 +367,7 @@ enum ha_base_keytype {
#define HA_STATE_EXTEND_BLOCK 2048
#define HA_STATE_RNEXT_SAME 4096 /* rnext_same was called */
+/* myisampack expects no more than 32 field types. */
enum en_fieldtype {
FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE,
FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO,
@@ -354,6 +380,15 @@ enum data_file_type {
/* For key ranges */
+#define NO_MIN_RANGE 1
+#define NO_MAX_RANGE 2
+#define NEAR_MIN 4
+#define NEAR_MAX 8
+#define UNIQUE_RANGE 16
+#define EQ_RANGE 32
+#define NULL_RANGE 64
+#define GEOM_FLAG 128
+
typedef struct st_key_range
{
const byte *key;
@@ -361,6 +396,14 @@ typedef struct st_key_range
enum ha_rkey_function flag;
} key_range;
+typedef struct st_key_multi_range
+{
+ key_range start_key;
+ key_range end_key;
+ char *ptr; /* Free to use by caller (ptr to row etc) */
+ uint range_flag; /* key range flags see above */
+} KEY_MULTI_RANGE;
+
/* For number of records */
#ifdef BIG_TABLES
@@ -380,4 +423,6 @@ typedef ulong ha_rows;
#define MAX_FILE_SIZE LONGLONG_MAX
#endif
+#define HA_VARCHAR_PACKLENGTH(field_length) ((field_length) < 256 ? 1 :2)
+
#endif /* _my_base_h */
diff --git a/include/my_bitmap.h b/include/my_bitmap.h
index a4511bf3414..f4fe28266e4 100644
--- a/include/my_bitmap.h
+++ b/include/my_bitmap.h
@@ -24,7 +24,7 @@
typedef struct st_bitmap
{
uchar *bitmap;
- uint bitmap_size;
+ uint bitmap_size; /* number of bytes occupied by the above */
/*
mutex will be acquired for the duration of each bitmap operation if
thread_safe flag in bitmap_init was set. Otherwise, we optimize by not
@@ -45,11 +45,16 @@ extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size);
extern my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit);
extern my_bool bitmap_is_set_all(const MY_BITMAP *map);
extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2);
+extern my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit);
+extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit);
extern uint bitmap_set_next(MY_BITMAP *map);
+extern uint bitmap_get_first(const MY_BITMAP *map);
+extern uint bitmap_bits_set(const MY_BITMAP *map);
extern void bitmap_clear_all(MY_BITMAP *map);
extern void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_free(MY_BITMAP *map);
extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2);
+extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit);
extern void bitmap_set_all(MY_BITMAP *map);
extern void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size);
diff --git a/include/my_dbug.h b/include/my_dbug.h
index 711ece4335c..b76a3fcc8c9 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -25,6 +25,7 @@ extern int _db_on_,_no_db_;
extern FILE *_db_fp_;
extern char *_db_process_;
extern int _db_keyword_(const char *keyword);
+extern int _db_strict_keyword_(const char *keyword);
extern void _db_setjmp_(void);
extern void _db_longjmp_(void);
extern void _db_push_(const char *control);
@@ -38,9 +39,9 @@ extern void _db_pargs_(uint _line_,const char *keyword);
extern void _db_doprnt_ _VARARGS((const char *format,...));
extern void _db_dump_(uint _line_,const char *keyword,const char *memory,
uint length);
-extern void _db_output_();
-extern void _db_lock_file();
-extern void _db_unlock_file();
+extern void _db_output_(uint flag);
+extern void _db_lock_file(void);
+extern void _db_unlock_file(void);
#define DBUG_ENTER(a) const char *_db_func_, *_db_file_; uint _db_level_; \
char **_db_framep_; \
@@ -69,12 +70,15 @@ extern void _db_unlock_file();
#define DBUG_UNLOCK_FILE { _db_unlock_file(); }
#define DBUG_OUTPUT(A) { _db_output_(A); }
#define DBUG_ASSERT(A) assert(A)
+#define DBUG_EXECUTE_IF(keyword,a1) \
+ {if (_db_on_) {if (_db_strict_keyword_ (keyword)) { a1 }}}
#else /* No debugger */
#define DBUG_ENTER(a1)
#define DBUG_RETURN(a1) return(a1)
#define DBUG_VOID_RETURN return
#define DBUG_EXECUTE(keyword,a1) {}
+#define DBUG_EXECUTE_IF(keyword,a1) {}
#define DBUG_PRINT(keyword,arglist) {}
#define DBUG_PUSH(a1) {}
#define DBUG_POP() {}
diff --git a/include/my_global.h b/include/my_global.h
index 0f99aacd079..48dd165dba1 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -107,6 +107,14 @@
#define _GNU_SOURCE 1
#endif
+/*
+ Temporary solution to solve bug#7156. Include "sys/types.h" before
+ the thread headers, else the function madvise() will not be defined
+*/
+#if defined(HAVE_SYS_TYPES_H) && ( defined(sun) || defined(__sun) )
+#include <sys/types.h>
+#endif
+
/* The client defines this to avoid all thread code */
#if defined(UNDEF_THREADS_HACK)
#undef THREAD
@@ -126,6 +134,38 @@
#define __STDC_EXT__ 1 /* To get large file support on hpux */
#endif
+/*
+ Solaris 9 include file <sys/feature_tests.h> refers to X/Open document
+
+ System Interfaces and Headers, Issue 5
+
+ saying we should define _XOPEN_SOURCE=500 to get POSIX.1c prototypes,
+ but apparently other systems (namely FreeBSD) don't agree.
+
+ On a newer Solaris 10, the above file recognizes also _XOPEN_SOURCE=600.
+ Furthermore, it tests that if a program requires older standard
+ (_XOPEN_SOURCE<600 or _POSIX_C_SOURCE<200112L) it cannot be
+ run on a new compiler (that defines _STDC_C99) and issues an #error.
+ It's also an #error if a program requires new standard (_XOPEN_SOURCE=600
+ or _POSIX_C_SOURCE=200112L) and a compiler does not define _STDC_C99.
+
+ To add more to this mess, Sun Studio C compiler defines _STDC_C99 while
+ C++ compiler does not!
+
+ So, in a desperate attempt to get correct prototypes for both
+ C and C++ code, we define either _XOPEN_SOURCE=600 or _XOPEN_SOURCE=500
+ depending on the compiler's announced C standard support.
+
+ Cleaner solutions are welcome.
+*/
+#ifdef __sun
+#if __STDC_VERSION__ - 0 >= 199901L
+#define _XOPEN_SOURCE 600
+#else
+#define _XOPEN_SOURCE 500
+#endif
+#endif
+
#if defined(THREAD) && !defined(__WIN__) && !defined(OS2)
#ifndef _POSIX_PTHREAD_SEMANTICS
#define _POSIX_PTHREAD_SEMANTICS /* We want posix threads */
@@ -203,17 +243,6 @@ C_MODE_END
#define __LONG_MAX__ 2147483647
#endif
-/* Fix problem when linking c++ programs with gcc 3.x */
-#ifdef DEFINE_CXA_PURE_VIRTUAL
-#define FIX_GCC_LINKING_PROBLEM \
-C_MODE_START int __cxa_pure_virtual() {\
- DBUG_ASSERT("Pure virtual method called." == "Aborted");\
- return 0;\
-} C_MODE_END
-#else
-#define FIX_GCC_LINKING_PROBLEM
-#endif
-
/* egcs 1.1.2 has a problem with memcpy on Alpha */
#if defined(__GNUC__) && defined(__alpha__) && ! (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
#define BAD_MEMCPY
@@ -323,7 +352,9 @@ extern "C" int madvise(void *addr, size_t len, int behav);
#undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */
#undef LONGLONG_MAX /* standard system library 'limits.h' */
#ifdef __cplusplus
-#define HAVE_RINT /* rint() and isnan() functions are not */
+#ifndef HAVE_RINT
+#define HAVE_RINT
+#endif /* rint() and isnan() functions are not */
#define rint(a) std::rint(a) /* visible in C++ scope due to an error */
#define isnan(a) std::isnan(a) /* in the usr/include/math.h on QNX */
#endif
@@ -669,6 +700,7 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define UINT_MAX16 0xFFFF
#define INT_MIN8 (~0x7F)
#define INT_MAX8 0x7F
+#define UINT_MAX8 0xFF
/* From limits.h instead */
#ifndef DBL_MIN
@@ -684,6 +716,17 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define isinf(X) 0
#endif
+/* Define missing math constants. */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_E
+#define M_E 2.7182818284590452354
+#endif
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942
+#endif
+
/*
Max size that must be added to a so that we know Size to make
adressable obj.
@@ -747,7 +790,7 @@ typedef long int32;
#endif
typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */
#else
-error "Neither int or long is of 4 bytes width"
+#error "Neither int or long is of 4 bytes width"
#endif
#if !defined(HAVE_ULONG) && !defined(TARGET_OS_LINUX) && !defined(__USE_MISC)
@@ -899,10 +942,24 @@ typedef char bool; /* Ordinary boolean values 0 1 */
#define MY_HOW_OFTEN_TO_ALARM 2 /* How often we want info on screen */
#define MY_HOW_OFTEN_TO_WRITE 1000 /* How often we want info on screen */
-#ifndef set_timespec
#ifdef HAVE_TIMESPEC_TS_SEC
-#define set_timespec(ABSTIME,SEC) { (ABSTIME).ts_sec=time(0) + (time_t) (SEC); (ABSTIME).ts_nsec=0; }
+#ifndef set_timespec
+#define set_timespec(ABSTIME,SEC) \
+{ \
+ (ABSTIME).ts_sec=time(0) + (time_t) (SEC); \
+ (ABSTIME).ts_nsec=0; \
+}
+#endif /* !set_timespec */
+#ifndef set_timespec_nsec
+#define set_timespec_nsec(ABSTIME,NSEC) \
+{ \
+ ulonglong now= my_getsystime() + (NSEC/100); \
+ (ABSTIME).ts_sec= (now / ULL(10000000)); \
+ (ABSTIME).ts_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
+}
+#endif /* !set_timespec_nsec */
#else
+#ifndef set_timespec
#define set_timespec(ABSTIME,SEC) \
{\
struct timeval tv;\
@@ -910,8 +967,16 @@ typedef char bool; /* Ordinary boolean values 0 1 */
(ABSTIME).tv_sec=tv.tv_sec+(time_t) (SEC);\
(ABSTIME).tv_nsec=tv.tv_usec*1000;\
}
+#endif /* !set_timespec */
+#ifndef set_timespec_nsec
+#define set_timespec_nsec(ABSTIME,NSEC) \
+{\
+ ulonglong now= my_getsystime() + (NSEC/100); \
+ (ABSTIME).tv_sec= (now / ULL(10000000)); \
+ (ABSTIME).tv_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
+}
+#endif /* !set_timespec_nsec */
#endif /* HAVE_TIMESPEC_TS_SEC */
-#endif /* set_timespec */
/*
Define-funktions for reading and storing in machine independent format
diff --git a/include/my_handler.h b/include/my_handler.h
index 18a6234d3f6..c076ba0c2c9 100644
--- a/include/my_handler.h
+++ b/include/my_handler.h
@@ -25,15 +25,17 @@
typedef struct st_HA_KEYSEG /* Key-portion */
{
+ CHARSET_INFO *charset;
+ uint32 start; /* Start of key in record */
+ uint32 null_pos; /* position to NULL indicator */
+ uint16 bit_pos; /* Position to bit part */
+ uint16 flag;
+ uint16 length; /* Keylength */
uint8 type; /* Type of key (for sort) */
uint8 language;
uint8 null_bit; /* bitmask to test for NULL */
uint8 bit_start,bit_end; /* if bit field */
- uint16 flag;
- uint16 length; /* Keylength */
- uint32 start; /* Start of key in record */
- uint32 null_pos; /* position to NULL indicator */
- CHARSET_INFO *charset;
+ uint8 bit_length; /* Length of bit part */
} HA_KEYSEG;
#define get_key_length(length,key) \
@@ -57,6 +59,29 @@ typedef struct st_HA_KEYSEG /* Key-portion */
{ length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
}
+#define store_key_length_inc(key,length) \
+{ if ((length) < 255) \
+ { *(key)++=(length); } \
+ else \
+ { *(key)=255; mi_int2store((key)+1,(length)); (key)+=3; } \
+}
+
+#define get_rec_bits(bit_ptr, bit_ofs, bit_len) \
+ (((((uint16) (bit_ptr)[1] << 8) | (uint16) (bit_ptr)[0]) >> (bit_ofs)) & \
+ ((1 << (bit_len)) - 1))
+
+#define set_rec_bits(bits, bit_ptr, bit_ofs, bit_len) \
+{ \
+ (bit_ptr)[0]= ((bit_ptr)[0] & ~(((1 << (bit_len)) - 1) << (bit_ofs))) | \
+ ((bits) << (bit_ofs)); \
+ if ((bit_ofs) + (bit_len) > 8) \
+ (bit_ptr)[1]= ((bit_ptr)[1] & ~((1 << ((bit_len) - 8 + (bit_ofs))) - 1)) | \
+ ((bits) >> (8 - (bit_ofs))); \
+}
+
+#define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \
+ set_rec_bits(0, bit_ptr, bit_ofs, bit_len)
+
extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
my_bool, my_bool);
extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
diff --git a/include/my_net.h b/include/my_net.h
index 7b42afa1f3a..71914964e46 100644
--- a/include/my_net.h
+++ b/include/my_net.h
@@ -72,6 +72,11 @@ C_MODE_START
#define in_addr_t uint32
#endif
+/* On some operating systems (e.g. Solaris) INADDR_NONE is not defined */
+#ifndef INADDR_NONE
+#define INADDR_NONE -1 /* Error value from inet_addr */
+#endif
+
/* Thread safe or portable version of some functions */
void my_inet_ntoa(struct in_addr in, char *buf);
diff --git a/include/my_pthread.h b/include/my_pthread.h
index d83ddf62a80..132a298bc69 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -671,21 +671,25 @@ extern pthread_t shutdown_th, main_th, signal_th;
#ifndef thread_safe_increment
#ifdef HAVE_ATOMIC_ADD
-#define thread_safe_increment(V,L) atomic_add(1,(atomic_t*) &V);
-#define thread_safe_add(V,C,L) atomic_add((C),(atomic_t*) &V);
-#define thread_safe_sub(V,C,L) atomic_sub((C),(atomic_t*) &V);
+#define thread_safe_increment(V,L) atomic_inc((atomic_t*) &V)
+#define thread_safe_decrement(V,L) atomic_dec((atomic_t*) &V)
+#define thread_safe_add(V,C,L) atomic_add((C),(atomic_t*) &V)
+#define thread_safe_sub(V,C,L) atomic_sub((C),(atomic_t*) &V)
#else
#define thread_safe_increment(V,L) \
- pthread_mutex_lock((L)); (V)++; pthread_mutex_unlock((L));
-#define thread_safe_add(V,C,L) \
- pthread_mutex_lock((L)); (V)+=(C); pthread_mutex_unlock((L));
+ (pthread_mutex_lock((L)), (V)++, pthread_mutex_unlock((L)))
+#define thread_safe_decrement(V,L) \
+ (pthread_mutex_lock((L)), (V)--, pthread_mutex_unlock((L)))
+#define thread_safe_add(V,C,L) (pthread_mutex_lock((L)), (V)+=(C), pthread_mutex_unlock((L)))
#define thread_safe_sub(V,C,L) \
- pthread_mutex_lock((L)); (V)-=(C); pthread_mutex_unlock((L));
+ (pthread_mutex_lock((L)), (V)-=(C), pthread_mutex_unlock((L)))
#endif /* HAVE_ATOMIC_ADD */
#ifdef SAFE_STATISTICS
#define statistic_increment(V,L) thread_safe_increment((V),(L))
+#define statistic_decrement(V,L) thread_safe_decrement((V),(L))
#define statistic_add(V,C,L) thread_safe_add((V),(C),(L))
#else
+#define statistic_decrement(V,L) (V)--
#define statistic_increment(V,L) (V)++
#define statistic_add(V,C,L) (V)+=(C)
#endif /* SAFE_STATISTICS */
diff --git a/include/my_sys.h b/include/my_sys.h
index 02ea188a18e..2970f68805b 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -43,8 +43,6 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MYSYS_PROGRAM_DONT_USE_CURSES() { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;}
#define MY_INIT(name); { my_progname= name; my_init(); }
-#define MAXMAPS (4) /* Number of error message maps */
-#define ERRMOD (1000) /* Max number of errors in a map */
#define ERRMSGSIZE (SC_MAXWIDTH) /* Max length of a error message */
#define NRERRBUFFS (2) /* Buffers for parameters */
#define MY_FILE_ERROR ((uint) ~0)
@@ -56,11 +54,10 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_FAE 8 /* Fatal if any error */
#define MY_WME 16 /* Write message on error */
#define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */
-#define MY_RAID 64 /* Support for RAID (not the "Johnson&Johnson"-s one ;) */
-#define MY_FULL_IO 512 /* For my_read - loop intil I/O
- is complete
- */
-#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
+#define MY_IGNORE_BADFD 32 /* my_sync: ignore 'bad descriptor' errors */
+#define MY_RAID 64 /* Support for RAID */
+#define MY_FULL_IO 512 /* For my_read - loop intil I/O is complete */
+#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
#define MY_LINK_WARNING 32 /* my_redel() gives warning if links */
#define MY_COPYTIME 64 /* my_redel() copys time */
#define MY_DELETE_OLD 256 /* my_create_with_symlink() */
@@ -74,7 +71,7 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_FREE_ON_ERROR 128 /* my_realloc() ; Free old ptr on error */
#define MY_HOLD_ON_ERROR 256 /* my_realloc() ; Return old ptr on error */
#define MY_THREADSAFE 128 /* pread/pwrite: Don't allow interrupts */
-#define MY_DONT_OVERWRITE_FILE 1024 /* my_copy; Don't overwrite file */
+#define MY_DONT_OVERWRITE_FILE 1024 /* my_copy: Don't overwrite file */
#define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */
#define MY_GIVE_INFO 2 /* Give time info about process*/
@@ -101,6 +98,7 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_RETURN_REAL_PATH 32 /* return full path for file */
#define MY_SAFE_PATH 64 /* Return NULL if too long path */
#define MY_RELATIVE_PATH 128 /* name is relative to 'dir' */
+#define MY_UNIX_PATH 256 /* convert path to UNIX format */
/* My seek flags */
#define MY_SEEK_SET 0
@@ -121,6 +119,13 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_ERRNO_EDOM 33
#define MY_ERRNO_ERANGE 34
+ /* Bits for get_date timeflag */
+#define GETDATE_DATE_TIME 1
+#define GETDATE_SHORT_DATE 2
+#define GETDATE_HHMMSSTIME 4
+#define GETDATE_GMT 8
+#define GETDATE_FIXEDLENGTH 16
+
/* defines when allocating data */
#ifdef SAFEMALLOC
#define my_malloc(SZ,FLAG) _mymalloc((SZ), __FILE__, __LINE__, FLAG )
@@ -131,6 +136,7 @@ extern int NEAR my_errno; /* Last error in mysys */
#define my_memdup(A,B,C) _my_memdup((A),(B), __FILE__,__LINE__,C)
#define my_strdup(A,C) _my_strdup((A), __FILE__,__LINE__,C)
#define my_strdup_with_length(A,B,C) _my_strdup_with_length((A),(B),__FILE__,__LINE__,C)
+#define TRASH(A,B) bfill(A, B, 0x8F)
#define QUICK_SAFEMALLOC sf_malloc_quick=1
#define NORMAL_SAFEMALLOC sf_malloc_quick=0
extern uint sf_malloc_prehunc,sf_malloc_endhunc,sf_malloc_quick;
@@ -157,8 +163,19 @@ extern char *my_strdup_with_length(const byte *from, uint length,
#define CALLER_INFO_PROTO /* nothing */
#define CALLER_INFO /* nothing */
#define ORIG_CALLER_INFO /* nothing */
+#define TRASH(A,B) /* nothing */
#endif
+#ifdef HAVE_LARGE_PAGES
+extern uint my_get_large_page_size(void);
+extern gptr my_large_malloc(uint size, myf my_flags);
+extern void my_large_free(gptr ptr, myf my_flags);
+#else
+#define my_get_large_page_size() (0)
+#define my_large_malloc(A,B) my_malloc_lock((A),(B))
+#define my_large_free(A,B) my_free_lock((A),(B))
+#endif /* HAVE_LARGE_PAGES */
+
#ifdef HAVE_ALLOCA
#if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43)
#pragma alloca
@@ -200,16 +217,20 @@ void __CDECL hfree(void *ptr);
extern int errno; /* declare errno */
#endif
#endif /* #ifndef errno */
-extern const char ** NEAR my_errmsg[];
extern char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
extern char *home_dir; /* Home directory for user */
-extern char *my_progname; /* program-name (printed in errors) */
+extern const char *my_progname; /* program-name (printed in errors) */
extern char NEAR curr_dir[]; /* Current directory for user */
extern int (*error_handler_hook)(uint my_err, const char *str,myf MyFlags);
extern int (*fatal_error_handler_hook)(uint my_err, const char *str,
myf MyFlags);
extern uint my_file_limit;
+#ifdef HAVE_LARGE_PAGES
+extern my_bool my_use_large_pages;
+extern uint my_large_page_size;
+#endif
+
/* charsets */
extern CHARSET_INFO *default_charset_info;
extern CHARSET_INFO *all_charsets[256];
@@ -240,6 +261,9 @@ extern my_bool NEAR my_disable_locking,NEAR my_disable_async_io,
extern char wild_many,wild_one,wild_prefix;
extern const char *charsets_dir;
extern char *defaults_extra_file;
+extern const char *defaults_group_suffix;
+
+extern my_bool timed_mutexes;
typedef struct wild_file_pack /* Struct to hold info when selecting files */
{
@@ -502,12 +526,17 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *);
/* tell write offset in the SEQ_APPEND cache */
my_off_t my_b_append_tell(IO_CACHE* info);
+my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */
#define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \
*(info)->current_pos)
typedef uint32 ha_checksum;
+/* Define the type of function to be passed to process_default_option_files */
+typedef int (*Process_option_func)(void *ctx, const char *group_name,
+ const char *option);
+
#include <my_alloc.h>
/* Prototypes for mysys and my_func functions */
@@ -522,7 +551,6 @@ extern gptr my_once_alloc(uint Size,myf MyFlags);
extern void my_once_free(void);
extern char *my_once_strdup(const char *src,myf myflags);
extern char *my_once_memdup(const char *src, uint len, myf myflags);
-extern my_string my_tempnam(const char *dir,const char *pfx,myf MyFlags);
extern File my_open(const char *FileName,int Flags,myf MyFlags);
extern File my_register_filename(File fd, const char *FileName,
enum file_type type_of_file,
@@ -590,6 +618,8 @@ extern int my_error _VARARGS((int nr,myf MyFlags, ...));
extern int my_printf_error _VARARGS((uint my_err, const char *format,
myf MyFlags, ...)
__attribute__ ((format (printf, 2, 4))));
+extern int my_error_register(const char **errmsgs, int first, int last);
+extern const char **my_error_unregister(int first, int last);
extern int my_message(uint my_err, const char *str,myf MyFlags);
extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags);
extern int my_message_curses(uint my_err, const char *str,myf MyFlags);
@@ -662,6 +692,8 @@ extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements,
extern qsort_t qsort2(void *base_ptr, size_t total_elems, size_t size,
qsort2_cmp cmp, void *cmp_argument);
extern qsort2_cmp get_ptr_compare(uint);
+void my_store_ptr(byte *buff, uint pack_length, my_off_t pos);
+my_off_t my_get_ptr(byte *ptr, uint pack_length);
extern int init_io_cache(IO_CACHE *info,File file,uint cachesize,
enum cache_type type,my_off_t seek_offset,
pbool use_async_io, myf cache_myflags);
@@ -707,7 +739,8 @@ File create_temp_file(char *to, const char *dir, const char *pfx,
#define my_init_dynamic_array(A,B,C,D) init_dynamic_array(A,B,C,D CALLER_INFO)
#define my_init_dynamic_array_ci(A,B,C,D) init_dynamic_array(A,B,C,D ORIG_CALLER_INFO)
extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size,
- uint init_alloc,uint alloc_increment CALLER_INFO_PROTO);
+ uint init_alloc,uint alloc_increment
+ CALLER_INFO_PROTO);
extern my_bool insert_dynamic(DYNAMIC_ARRAY *array,gptr element);
extern byte *alloc_dynamic(DYNAMIC_ARRAY *array);
extern byte *pop_dynamic(DYNAMIC_ARRAY*);
@@ -749,11 +782,19 @@ extern void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
extern char *strdup_root(MEM_ROOT *root,const char *str);
extern char *strmake_root(MEM_ROOT *root,const char *str,uint len);
extern char *memdup_root(MEM_ROOT *root,const char *str,uint len);
-extern void get_defaults_files(int argc, char **argv,
- char **defaults, char **extra_defaults);
+extern int get_defaults_options(int argc, char **argv,
+ char **defaults, char **extra_defaults,
+ char **group_suffix);
extern int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
+extern int modify_defaults_file(const char *file_location, const char *option,
+ const char *option_value,
+ const char *section_name, int remove_option);
+extern int my_search_option_files(const char *conf_file, int *argc,
+ char ***argv, uint *args_used,
+ Process_option_func func, void *func_ctx);
extern void free_defaults(char **argv);
+extern void my_print_default_files(const char *conf_file);
extern void print_defaults(const char *conf_file, const char **groups);
extern my_bool my_compress(byte *, ulong *, ulong *);
extern my_bool my_uncompress(byte *, ulong *, ulong *);
@@ -761,6 +802,7 @@ extern byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen);
extern ha_checksum my_checksum(ha_checksum crc, const byte *mem, uint count);
extern uint my_bit_log2(ulong value);
extern uint my_count_bits(ulonglong v);
+extern uint my_count_bits_ushort(ushort v);
extern void my_sleep(ulong m_seconds);
extern ulong crc32(ulong crc, const uchar *buf, uint len);
extern uint my_set_max_open_files(uint files);
@@ -769,6 +811,42 @@ void my_free_open_file_info(void);
ulonglong my_getsystime(void);
my_bool my_gethwaddr(uchar *to);
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+
+#ifndef MAP_NOSYNC
+#define MAP_NOSYNC 0
+#endif
+
+#define my_mmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f)
+#ifdef HAVE_GETPAGESIZE
+#define my_getpagesize() getpagesize()
+#else
+/* qnx ? */
+#define my_getpagesize() 8192
+#endif
+#define my_munmap(a,b) munmap((a),(b))
+
+#else
+/* not a complete set of mmap() flags, but only those that nesessary */
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define MAP_SHARED 0x0001
+#define MAP_NOSYNC 0x0800
+#define MAP_FAILED ((void *)-1)
+#define MS_SYNC 0x0000
+
+#ifndef __NETWARE__
+#define HAVE_MMAP
+#endif
+
+int my_getpagesize(void);
+void *my_mmap(void *, size_t, int, int, int, my_off_t);
+int my_munmap(void *, size_t);
+#endif
+
+int my_msync(int, void *, size_t, int);
+
/* character sets */
extern uint get_charset_number(const char *cs_name, uint cs_flags);
extern uint get_collation_number(const char *name);
@@ -783,13 +861,21 @@ extern char *get_charsets_dir(char *buf);
extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
extern my_bool init_compiled_charsets(myf flags);
extern void add_compiled_collation(CHARSET_INFO *cs);
-extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
+extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
const char *from, ulong length);
#ifdef __WIN__
#define BACKSLASH_MBTAIL
/* File system character set */
extern CHARSET_INFO *fs_character_set(void);
#endif
+extern ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
+ const char *from, ulong length);
+
+extern void thd_increment_bytes_sent(ulong length);
+extern void thd_increment_bytes_received(ulong length);
+extern void thd_increment_net_big_packet_count(ulong length);
#ifdef __WIN__
extern my_bool have_tcpip; /* Is set if tcpip is used */
diff --git a/include/my_time.h b/include/my_time.h
index 94701e159c4..e52ef69475d 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -41,22 +41,36 @@ typedef long my_time_t;
#define YY_PART_YEAR 70
/* Flags to str_to_datetime */
-#define TIME_FUZZY_DATE 1
-#define TIME_DATETIME_ONLY 2
+#define TIME_FUZZY_DATE 1
+#define TIME_DATETIME_ONLY 2
+/* Must be same as MODE_NO_ZERO_IN_DATE */
+#define TIME_NO_ZERO_IN_DATE (65536L*2*2*2*2*2*2*2)
+/* Must be same as MODE_NO_ZERO_DATE */
+#define TIME_NO_ZERO_DATE (TIME_NO_ZERO_IN_DATE*2)
+#define TIME_INVALID_DATES (TIME_NO_ZERO_DATE*2)
enum enum_mysql_timestamp_type
str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
uint flags, int *was_cut);
+longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
+ uint flags, int *was_cut);
+ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *time);
+ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *time);
+ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *time);
+ulonglong TIME_to_ulonglong(const MYSQL_TIME *time);
-bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
- int *was_cut);
+
+my_bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
+ int *was_cut);
long calc_daynr(uint year,uint month,uint day);
+uint calc_days_in_year(uint year);
void init_time(void);
my_time_t
-my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap);
+my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone,
+ my_bool *in_dst_time_gap);
void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type);
diff --git a/include/myisam.h b/include/myisam.h
index e276d4efdff..6cc219de6e8 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -35,14 +35,26 @@ extern "C" {
/* defines used by myisam-funktions */
-/* The following defines can be increased if necessary */
-#define MI_MAX_KEY 64 /* Max allowed keys */
-#define MI_MAX_KEY_SEG 16 /* Max segments for key */
-#define MI_MAX_KEY_LENGTH 1000
+/*
+ There is a hard limit for the maximum number of keys as there are only
+ 8 bits in the index file header for the number of keys in a table.
+ This means that 0..255 keys can exist for a table. The idea of
+ MI_MAX_POSSIBLE_KEY is to ensure that one can use myisamchk & tools on
+ a MyISAM table for which one has more keys than MyISAM is normally
+ compiled for. If you don't have this, you will get a core dump when
+ running myisamchk compiled for 128 keys on a table with 255 keys.
+*/
+#define MI_MAX_POSSIBLE_KEY 255 /* For myisam_chk */
+#define MI_MAX_POSSIBLE_KEY_BUFF (1024+6+6) /* For myisam_chk */
+/*
+ The following defines can be increased if necessary.
+ BUT: MI_MAX_KEY must be <= MI_MAX_POSSIBLE_KEY.
+*/
+#define MI_MAX_KEY 64 /* Max allowed keys */
+#define MI_MAX_KEY_SEG 16 /* Max segments for key */
+#define MI_MAX_KEY_LENGTH 1000
#define MI_MAX_KEY_BUFF (MI_MAX_KEY_LENGTH+MI_MAX_KEY_SEG*6+8+8)
-#define MI_MAX_POSSIBLE_KEY_BUFF (1024+6+6) /* For myisam_chk */
-#define MI_MAX_POSSIBLE_KEY 64 /* For myisam_chk */
#define MI_MAX_MSG_BUF 1024 /* used in CHECK TABLE, REPAIR TABLE */
#define MI_NAME_IEXT ".MYI"
#define MI_NAME_DEXT ".MYD"
@@ -56,6 +68,63 @@ extern "C" {
#define mi_portable_sizeof_char_ptr 8
+/*
+ In the following macros '_keyno_' is 0 .. keys-1.
+ If there can be more keys than bits in the key_map, the highest bit
+ is for all upper keys. They cannot be switched individually.
+ This means that clearing of high keys is ignored, setting one high key
+ sets all high keys.
+*/
+#define MI_KEYMAP_BITS (8 * SIZEOF_LONG_LONG)
+#define MI_KEYMAP_HIGH_MASK (ULL(1) << (MI_KEYMAP_BITS - 1))
+#define mi_get_mask_all_keys_active(_keys_) \
+ (((_keys_) < MI_KEYMAP_BITS) ? \
+ ((ULL(1) << (_keys_)) - ULL(1)) : \
+ (~ ULL(0)))
+
+#if MI_MAX_KEY > MI_KEYMAP_BITS
+
+#define mi_is_key_active(_keymap_,_keyno_) \
+ (((_keyno_) < MI_KEYMAP_BITS) ? \
+ test((_keymap_) & (ULL(1) << (_keyno_))) : \
+ test((_keymap_) & MI_KEYMAP_HIGH_MASK))
+#define mi_set_key_active(_keymap_,_keyno_) \
+ (_keymap_)|= (((_keyno_) < MI_KEYMAP_BITS) ? \
+ (ULL(1) << (_keyno_)) : \
+ MI_KEYMAP_HIGH_MASK)
+#define mi_clear_key_active(_keymap_,_keyno_) \
+ (_keymap_)&= (((_keyno_) < MI_KEYMAP_BITS) ? \
+ (~ (ULL(1) << (_keyno_))) : \
+ (~ (ULL(0))) /*ignore*/ )
+
+#else
+
+#define mi_is_key_active(_keymap_,_keyno_) \
+ test((_keymap_) & (ULL(1) << (_keyno_)))
+#define mi_set_key_active(_keymap_,_keyno_) \
+ (_keymap_)|= (ULL(1) << (_keyno_))
+#define mi_clear_key_active(_keymap_,_keyno_) \
+ (_keymap_)&= (~ (ULL(1) << (_keyno_)))
+
+#endif
+
+#define mi_is_any_key_active(_keymap_) \
+ test((_keymap_))
+#define mi_is_all_keys_active(_keymap_,_keys_) \
+ ((_keymap_) == mi_get_mask_all_keys_active(_keys_))
+#define mi_set_all_keys_active(_keymap_,_keys_) \
+ (_keymap_)= mi_get_mask_all_keys_active(_keys_)
+#define mi_clear_all_keys_active(_keymap_) \
+ (_keymap_)= 0
+#define mi_intersect_keys_active(_to_,_from_) \
+ (_to_)&= (_from_)
+#define mi_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \
+ ((_keymap1_) & (_keymap2_) & \
+ mi_get_mask_all_keys_active(_keys_))
+#define mi_copy_keys_active(_to_,_maxkeys_,_from_) \
+ (_to_)= (mi_get_mask_all_keys_active(_maxkeys_) & \
+ (_from_))
+
/* Param to/from mi_info */
typedef struct st_mi_isaminfo /* Struct from h_info */
@@ -107,12 +176,13 @@ typedef struct st_mi_create_info
} MI_CREATE_INFO;
struct st_myisam_info; /* For referense */
+struct st_mi_isam_share;
typedef struct st_myisam_info MI_INFO;
-
struct st_mi_s_param;
typedef struct st_mi_keydef /* Key definition with open & info */
{
+ struct st_mi_isam_share *share; /* Pointer to base (set in mi_open) */
uint16 keysegs; /* Number of key-segment */
uint16 flag; /* NOSAME, PACK_USED */
@@ -189,10 +259,10 @@ typedef struct st_columndef /* column information */
typedef void (* invalidator_by_filename)(const char * filename);
extern my_string myisam_log_filename; /* Name of logfile */
-extern uint myisam_block_size;
+extern ulong myisam_block_size;
+extern ulong myisam_concurrent_insert;
extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user;
-extern my_bool myisam_concurrent_insert;
-extern my_off_t myisam_max_temp_length,myisam_max_extra_temp_length;
+extern my_off_t myisam_max_temp_length;
extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size;
/* Prototypes for myisam-functions */
@@ -320,7 +390,7 @@ typedef struct st_sort_key_blocks /* Used when sorting */
typedef enum
{
/* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */
- MI_STATS_METHOD_NULLS_NOT_EQUAL,
+ MI_STATS_METHOD_NULLS_NOT_EQUAL=1,
/* Treat NULLs as equal when collecting statistics (like 4.0 did) */
MI_STATS_METHOD_NULLS_EQUAL
} enum_mi_stats_method;
@@ -353,8 +423,8 @@ typedef struct st_mi_check_param
ha_checksum key_crc[MI_MAX_POSSIBLE_KEY];
ulong rec_per_key_part[MI_MAX_KEY_SEG*MI_MAX_POSSIBLE_KEY];
void *thd;
- char *db_name,*table_name;
- char *op_name;
+ const char *db_name, *table_name;
+ const char *op_name;
enum_mi_stats_method stats_method;
} MI_CHECK;
diff --git a/include/mysql.h b/include/mysql.h
index 0949937814c..c4b4e026e5b 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -74,14 +74,14 @@ extern char *mysql_unix_port;
#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
#define IS_BLOB(n) ((n) & BLOB_FLAG)
-#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR)
+#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL)
#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)
typedef struct st_mysql_field {
char *name; /* Name of column */
- char *org_name; /* Original column name, if an alias */
+ char *org_name; /* Original column name, if an alias */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */
@@ -145,7 +145,8 @@ enum mysql_option
MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT,
MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
- MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH
+ MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
+ MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT
};
struct st_mysql_options {
@@ -186,6 +187,8 @@ struct st_mysql_options {
char *client_ip;
/* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */
my_bool secure_auth;
+ /* 0 - never report, 1 - always report (default) */
+ my_bool report_data_truncation;
/* function pointers for local infile support */
int (*local_infile_init)(void **, const char *, void *);
@@ -215,6 +218,18 @@ enum mysql_rpl_type
MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, MYSQL_RPL_ADMIN
};
+typedef struct character_set
+{
+ unsigned int number; /* character set number */
+ unsigned int state; /* character set state */
+ const char *csname; /* collation name */
+ const char *name; /* character set name */
+ const char *comment; /* comment */
+ const char *dir; /* character set directory */
+ unsigned int mbminlen; /* min. length for multibyte strings */
+ unsigned int mbmaxlen; /* max. length for multibyte strings */
+} MY_CHARSET_INFO;
+
struct st_mysql_methods;
typedef struct st_mysql
@@ -228,7 +243,7 @@ typedef struct st_mysql
MEM_ROOT field_alloc;
my_ulonglong affected_rows;
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
- my_ulonglong extra_info; /* Used by mysqlshow */
+ my_ulonglong extra_info; /* Not used */
unsigned long thread_id; /* Id for connection in server */
unsigned long packet_length;
unsigned int port;
@@ -381,7 +396,7 @@ unsigned int STDCALL mysql_warning_count(MYSQL *mysql);
const char * STDCALL mysql_info(MYSQL *mysql);
unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
const char * STDCALL mysql_character_set_name(MYSQL *mysql);
-int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname);
+int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname);
MYSQL * STDCALL mysql_init(MYSQL *mysql);
my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
@@ -415,6 +430,8 @@ my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
unsigned long length);
my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
unsigned long length);
+void STDCALL mysql_get_character_set_info(MYSQL *mysql,
+ MY_CHARSET_INFO *charset);
/* local infile support */
@@ -549,26 +566,91 @@ enum enum_mysql_stmt_state
};
-/* bind structure */
+/*
+ This structure is used to define bind information, and
+ internally by the client library.
+ Public members with their descriptions are listed below
+ (conventionally `On input' refers to the binds given to
+ mysql_stmt_bind_param, `On output' refers to the binds given
+ to mysql_stmt_bind_result):
+
+ buffer_type - One of the MYSQL_* types, used to describe
+ the host language type of buffer.
+ On output: if column type is different from
+ buffer_type, column value is automatically converted
+ to buffer_type before it is stored in the buffer.
+ buffer - On input: points to the buffer with input data.
+ On output: points to the buffer capable to store
+ output data.
+ The type of memory pointed by buffer must correspond
+ to buffer_type. See the correspondence table in
+ the comment to mysql_stmt_bind_param.
+
+ The two above members are mandatory for any kind of bind.
+
+ buffer_length - the length of the buffer. You don't have to set
+ it for any fixed length buffer: float, double,
+ int, etc. It must be set however for variable-length
+ types, such as BLOBs or STRINGs.
+
+ length - On input: in case when lengths of input values
+ are different for each execute, you can set this to
+ point at a variable containining value length. This
+ way the value length can be different in each execute.
+ If length is not NULL, buffer_length is not used.
+ Note, length can even point at buffer_length if
+ you keep bind structures around while fetching:
+ this way you can change buffer_length before
+ each execution, everything will work ok.
+ On output: if length is set, mysql_stmt_fetch will
+ write column length into it.
+
+ is_null - On input: points to a boolean variable that should
+ be set to TRUE for NULL values.
+ This member is useful only if your data may be
+ NULL in some but not all cases.
+ If your data is never NULL, is_null should be set to 0.
+ If your data is always NULL, set buffer_type
+ to MYSQL_TYPE_NULL, and is_null will not be used.
+
+ is_unsigned - On input: used to signify that values provided for one
+ of numeric types are unsigned.
+ On output describes signedness of the output buffer.
+ If, taking into account is_unsigned flag, column data
+ is out of range of the output buffer, data for this column
+ is regarded truncated. Note that this has no correspondence
+ to the sign of result set column, if you need to find it out
+ use mysql_stmt_result_metadata.
+ error - where to write a truncation error if it is present.
+ possible error value is:
+ 0 no truncation
+ 1 value is out of range or buffer is too small
+
+ Please note that MYSQL_BIND also has internals members.
+*/
+
typedef struct st_mysql_bind
{
unsigned long *length; /* output length pointer */
my_bool *is_null; /* Pointer to null indicator */
void *buffer; /* buffer to get/put data */
+ /* set this if you want to track data truncations happened during fetch */
+ my_bool *error;
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_stmt_bind_param */
- unsigned char *inter_buffer; /* for the current data position */
+ /* output buffer length, must be set when fetching str/binary */
+ unsigned long buffer_length;
+ unsigned char *row_ptr; /* for the current data position */
unsigned long offset; /* offset position for char/binary fetch */
- unsigned long internal_length; /* Used if length is 0 */
+ unsigned long length_value; /* Used if length is 0 */
unsigned int param_number; /* For null count and error messages */
unsigned int pack_length; /* Internal length for packed data */
+ my_bool error_value; /* used if error is 0 */
my_bool is_unsigned; /* set if integer type is unsigned */
my_bool long_data_used; /* If used with mysql_send_long_data */
- my_bool internal_is_null; /* Used if is_null is 0 */
+ my_bool is_null_value; /* Used if is_null is 0 */
void (*store_param_func)(NET *net, struct st_mysql_bind *param);
- void (*fetch_result)(struct st_mysql_bind *, unsigned char **row);
+ void (*fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *,
+ unsigned char **row);
void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *,
unsigned char **row);
} MYSQL_BIND;
@@ -595,6 +677,13 @@ typedef struct st_mysql_stmt
int (*read_row_func)(struct st_mysql_stmt *stmt,
unsigned char **row);
unsigned long stmt_id; /* Id for prepared statement */
+ unsigned long flags; /* i.e. type of cursor to open */
+ unsigned long prefetch_rows; /* number of rows per one COM_FETCH */
+ /*
+ Copied from mysql->server_status after execute/fetch to know
+ server-side cursor status for this statement.
+ */
+ unsigned int server_status;
unsigned int last_errno; /* error code */
unsigned int param_count; /* input parameter count */
unsigned int field_count; /* number of columns in result set */
@@ -604,7 +693,7 @@ typedef struct st_mysql_stmt
/* Types of input parameters should be sent to server */
my_bool send_types_to_server;
my_bool bind_param_done; /* input buffers were supplied */
- my_bool bind_result_done; /* output buffers were supplied */
+ unsigned char bind_result_done; /* output buffers were supplied */
/* mysql_stmt_close() had to cancel this result */
my_bool unbuffered_fetch_cancelled;
/*
@@ -623,7 +712,17 @@ enum enum_stmt_attr_type
In the new API we do that only by request because it slows down
mysql_stmt_store_result sufficiently.
*/
- STMT_ATTR_UPDATE_MAX_LENGTH
+ STMT_ATTR_UPDATE_MAX_LENGTH,
+ /*
+ unsigned long with combination of cursor flags (read only, for update,
+ etc)
+ */
+ STMT_ATTR_CURSOR_TYPE,
+ /*
+ Amount of rows to retrieve from server per one fetch if using cursors.
+ Accepts unsigned long attribute in the range 1 - ulong_max
+ */
+ STMT_ATTR_PREFETCH_ROWS
};
@@ -705,7 +804,8 @@ void STDCALL mysql_close(MYSQL *sock);
/* status return codes */
-#define MYSQL_NO_DATA 100
+#define MYSQL_NO_DATA 100
+#define MYSQL_DATA_TRUNCATED 101
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 56c7f7d2ab5..c4eb33a6c9a 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -36,6 +36,11 @@
#define MYSQL_SERVICENAME "MySQL"
#endif /* __WIN__ */
+/*
+ You should add new commands to the end of this list, otherwise old
+ servers won't be able to handle them as 'unsupported'.
+*/
+
enum enum_server_command
{
COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
@@ -43,8 +48,8 @@ enum enum_server_command
COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING,
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
- COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT,
- COM_RESET_STMT, COM_SET_OPTION,
+ COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE,
+ COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH,
/* don't forget to update const char *command_name[] in sql_parse.cc */
/* Must be last */
@@ -77,6 +82,7 @@ enum enum_server_command
#define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */
#define TIMESTAMP_FLAG 1024 /* Field is a timestamp */
#define SET_FLAG 2048 /* field is a set */
+#define NO_DEFAULT_VALUE_FLAG 4096 /* Field doesn't have default value */
#define NUM_FLAG 32768 /* Field is num (for clients) */
#define PART_KEY_FLAG 16384 /* Intern; Part of some key */
#define GROUP_FLAG 32768 /* Intern: Group field */
@@ -130,13 +136,27 @@ enum enum_server_command
#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
#define SERVER_QUERY_NO_GOOD_INDEX_USED 16
#define SERVER_QUERY_NO_INDEX_USED 32
+/*
+ The server was able to fulfill the clients request and opened a
+ read-only non-scrollable cursor for a query. This flag comes
+ in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
+*/
+#define SERVER_STATUS_CURSOR_EXISTS 64
+/*
+ This flag is sent when a read-only cursor is exhausted, in reply to
+ COM_STMT_FETCH command.
+*/
+#define SERVER_STATUS_LAST_ROW_SENT 128
#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */
+#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
#define MYSQL_ERRMSG_SIZE 512
#define NET_READ_TIMEOUT 30 /* Timeout on read */
#define NET_WRITE_TIMEOUT 60 /* Timeout on write */
#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */
+#define ONLY_KILL_QUERY 1
+
struct st_vio; /* Only C */
typedef struct st_vio Vio;
@@ -167,7 +187,13 @@ typedef struct st_net {
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
- my_bool no_send_ok;
+ my_bool no_send_ok; /* For SPs and other things that do multiple stmts */
+ my_bool no_send_eof; /* For SPs' first version read-only cursors */
+ /*
+ Set if OK packet is already sent, and we do not need to send error
+ messages
+ */
+ my_bool no_send_error;
/*
Pointer to query object in query cache, do not equal NULL (0) for
queries in cache that have not stored its results yet
@@ -190,7 +216,9 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
- MYSQL_TYPE_NEWDATE,
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ MYSQL_TYPE_BIT,
+ MYSQL_TYPE_NEWDECIMAL=246,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
@@ -206,6 +234,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
/* For backward compatibility */
#define CLIENT_MULTI_QUERIES CLIENT_MULTI_STATEMENTS
#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
+#define FIELD_TYPE_NEWDECIMAL MYSQL_TYPE_NEWDECIMAL
#define FIELD_TYPE_TINY MYSQL_TYPE_TINY
#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT
#define FIELD_TYPE_LONG MYSQL_TYPE_LONG
@@ -231,6 +260,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
+#define FIELD_TYPE_BIT MYSQL_TYPE_BIT
/* Shutdown/kill enums and constants */
@@ -265,6 +295,16 @@ enum mysql_enum_shutdown_level {
KILL_CONNECTION= 255
};
+
+enum enum_cursor_type
+{
+ CURSOR_TYPE_NO_CURSOR= 0,
+ CURSOR_TYPE_READ_ONLY= 1,
+ CURSOR_TYPE_FOR_UPDATE= 2,
+ CURSOR_TYPE_SCROLLABLE= 4
+};
+
+
/* options for mysql_set_option */
enum enum_mysql_set_option
{
@@ -310,7 +350,8 @@ struct rand_struct {
/* The following is for user defined functions */
-enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT};
+enum Item_result {STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT,
+ DECIMAL_RESULT};
typedef struct st_udf_args
{
@@ -319,6 +360,8 @@ typedef struct st_udf_args
char **args; /* Pointer to argument */
unsigned long *lengths; /* Length of string arguments */
char *maybe_null; /* Set to 1 for all maybe_null args */
+ char **attributes; /* Pointer to attribute name */
+ unsigned long *attribute_lengths; /* Length of attribute arguments */
} UDF_ARGS;
/* This holds information about the result */
@@ -366,6 +409,7 @@ my_bool check_scramble(const char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
+void octet2hex(char *to, const unsigned char *str, unsigned int len);
/* end of password.c */
@@ -375,6 +419,9 @@ const char *mysql_errno_to_sqlstate(unsigned int mysql_errno);
/* Some other useful functions */
my_bool my_init(void);
+extern int modify_defaults_file(const char *file_location, const char *option,
+ const char *option_value,
+ const char *section_name, int remove_option);
int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
my_bool my_thread_init(void);
diff --git a/include/mysql_embed.h b/include/mysql_embed.h
index 603af8e83b8..311d95eda73 100644
--- a/include/mysql_embed.h
+++ b/include/mysql_embed.h
@@ -24,7 +24,6 @@
#undef HAVE_PSTACK /* No stacktrace */
#undef HAVE_DLOPEN /* No udf functions */
#undef HAVE_OPENSSL
-#undef HAVE_ISAM
#undef HAVE_SMEM /* No shared memory */
#undef HAVE_NDBCLUSTER_DB /* No NDB cluster */
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
deleted file mode 100644
index 776869ff045..00000000000
--- a/include/mysqld_error.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/* Copyright (C) 2000 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 */
-
-/* Definefile for error messagenumbers */
-
-#define ER_HASHCHK 1000
-#define ER_NISAMCHK 1001
-#define ER_NO 1002
-#define ER_YES 1003
-#define ER_CANT_CREATE_FILE 1004
-#define ER_CANT_CREATE_TABLE 1005
-#define ER_CANT_CREATE_DB 1006
-#define ER_DB_CREATE_EXISTS 1007
-#define ER_DB_DROP_EXISTS 1008
-#define ER_DB_DROP_DELETE 1009
-#define ER_DB_DROP_RMDIR 1010
-#define ER_CANT_DELETE_FILE 1011
-#define ER_CANT_FIND_SYSTEM_REC 1012
-#define ER_CANT_GET_STAT 1013
-#define ER_CANT_GET_WD 1014
-#define ER_CANT_LOCK 1015
-#define ER_CANT_OPEN_FILE 1016
-#define ER_FILE_NOT_FOUND 1017
-#define ER_CANT_READ_DIR 1018
-#define ER_CANT_SET_WD 1019
-#define ER_CHECKREAD 1020
-#define ER_DISK_FULL 1021
-#define ER_DUP_KEY 1022
-#define ER_ERROR_ON_CLOSE 1023
-#define ER_ERROR_ON_READ 1024
-#define ER_ERROR_ON_RENAME 1025
-#define ER_ERROR_ON_WRITE 1026
-#define ER_FILE_USED 1027
-#define ER_FILSORT_ABORT 1028
-#define ER_FORM_NOT_FOUND 1029
-#define ER_GET_ERRNO 1030
-#define ER_ILLEGAL_HA 1031
-#define ER_KEY_NOT_FOUND 1032
-#define ER_NOT_FORM_FILE 1033
-#define ER_NOT_KEYFILE 1034
-#define ER_OLD_KEYFILE 1035
-#define ER_OPEN_AS_READONLY 1036
-#define ER_OUTOFMEMORY 1037
-#define ER_OUT_OF_SORTMEMORY 1038
-#define ER_UNEXPECTED_EOF 1039
-#define ER_CON_COUNT_ERROR 1040
-#define ER_OUT_OF_RESOURCES 1041
-#define ER_BAD_HOST_ERROR 1042
-#define ER_HANDSHAKE_ERROR 1043
-#define ER_DBACCESS_DENIED_ERROR 1044
-#define ER_ACCESS_DENIED_ERROR 1045
-#define ER_NO_DB_ERROR 1046
-#define ER_UNKNOWN_COM_ERROR 1047
-#define ER_BAD_NULL_ERROR 1048
-#define ER_BAD_DB_ERROR 1049
-#define ER_TABLE_EXISTS_ERROR 1050
-#define ER_BAD_TABLE_ERROR 1051
-#define ER_NON_UNIQ_ERROR 1052
-#define ER_SERVER_SHUTDOWN 1053
-#define ER_BAD_FIELD_ERROR 1054
-#define ER_WRONG_FIELD_WITH_GROUP 1055
-#define ER_WRONG_GROUP_FIELD 1056
-#define ER_WRONG_SUM_SELECT 1057
-#define ER_WRONG_VALUE_COUNT 1058
-#define ER_TOO_LONG_IDENT 1059
-#define ER_DUP_FIELDNAME 1060
-#define ER_DUP_KEYNAME 1061
-#define ER_DUP_ENTRY 1062
-#define ER_WRONG_FIELD_SPEC 1063
-#define ER_PARSE_ERROR 1064
-#define ER_EMPTY_QUERY 1065
-#define ER_NONUNIQ_TABLE 1066
-#define ER_INVALID_DEFAULT 1067
-#define ER_MULTIPLE_PRI_KEY 1068
-#define ER_TOO_MANY_KEYS 1069
-#define ER_TOO_MANY_KEY_PARTS 1070
-#define ER_TOO_LONG_KEY 1071
-#define ER_KEY_COLUMN_DOES_NOT_EXITS 1072
-#define ER_BLOB_USED_AS_KEY 1073
-#define ER_TOO_BIG_FIELDLENGTH 1074
-#define ER_WRONG_AUTO_KEY 1075
-#define ER_READY 1076
-#define ER_NORMAL_SHUTDOWN 1077
-#define ER_GOT_SIGNAL 1078
-#define ER_SHUTDOWN_COMPLETE 1079
-#define ER_FORCING_CLOSE 1080
-#define ER_IPSOCK_ERROR 1081
-#define ER_NO_SUCH_INDEX 1082
-#define ER_WRONG_FIELD_TERMINATORS 1083
-#define ER_BLOBS_AND_NO_TERMINATED 1084
-#define ER_TEXTFILE_NOT_READABLE 1085
-#define ER_FILE_EXISTS_ERROR 1086
-#define ER_LOAD_INFO 1087
-#define ER_ALTER_INFO 1088
-#define ER_WRONG_SUB_KEY 1089
-#define ER_CANT_REMOVE_ALL_FIELDS 1090
-#define ER_CANT_DROP_FIELD_OR_KEY 1091
-#define ER_INSERT_INFO 1092
-#define ER_UPDATE_TABLE_USED 1093
-#define ER_NO_SUCH_THREAD 1094
-#define ER_KILL_DENIED_ERROR 1095
-#define ER_NO_TABLES_USED 1096
-#define ER_TOO_BIG_SET 1097
-#define ER_NO_UNIQUE_LOGFILE 1098
-#define ER_TABLE_NOT_LOCKED_FOR_WRITE 1099
-#define ER_TABLE_NOT_LOCKED 1100
-#define ER_BLOB_CANT_HAVE_DEFAULT 1101
-#define ER_WRONG_DB_NAME 1102
-#define ER_WRONG_TABLE_NAME 1103
-#define ER_TOO_BIG_SELECT 1104
-#define ER_UNKNOWN_ERROR 1105
-#define ER_UNKNOWN_PROCEDURE 1106
-#define ER_WRONG_PARAMCOUNT_TO_PROCEDURE 1107
-#define ER_WRONG_PARAMETERS_TO_PROCEDURE 1108
-#define ER_UNKNOWN_TABLE 1109
-#define ER_FIELD_SPECIFIED_TWICE 1110
-#define ER_INVALID_GROUP_FUNC_USE 1111
-#define ER_UNSUPPORTED_EXTENSION 1112
-#define ER_TABLE_MUST_HAVE_COLUMNS 1113
-#define ER_RECORD_FILE_FULL 1114
-#define ER_UNKNOWN_CHARACTER_SET 1115
-#define ER_TOO_MANY_TABLES 1116
-#define ER_TOO_MANY_FIELDS 1117
-#define ER_TOO_BIG_ROWSIZE 1118
-#define ER_STACK_OVERRUN 1119
-#define ER_WRONG_OUTER_JOIN 1120
-#define ER_NULL_COLUMN_IN_INDEX 1121
-#define ER_CANT_FIND_UDF 1122
-#define ER_CANT_INITIALIZE_UDF 1123
-#define ER_UDF_NO_PATHS 1124
-#define ER_UDF_EXISTS 1125
-#define ER_CANT_OPEN_LIBRARY 1126
-#define ER_CANT_FIND_DL_ENTRY 1127
-#define ER_FUNCTION_NOT_DEFINED 1128
-#define ER_HOST_IS_BLOCKED 1129
-#define ER_HOST_NOT_PRIVILEGED 1130
-#define ER_PASSWORD_ANONYMOUS_USER 1131
-#define ER_PASSWORD_NOT_ALLOWED 1132
-#define ER_PASSWORD_NO_MATCH 1133
-#define ER_UPDATE_INFO 1134
-#define ER_CANT_CREATE_THREAD 1135
-#define ER_WRONG_VALUE_COUNT_ON_ROW 1136
-#define ER_CANT_REOPEN_TABLE 1137
-#define ER_INVALID_USE_OF_NULL 1138
-#define ER_REGEXP_ERROR 1139
-#define ER_MIX_OF_GROUP_FUNC_AND_FIELDS 1140
-#define ER_NONEXISTING_GRANT 1141
-#define ER_TABLEACCESS_DENIED_ERROR 1142
-#define ER_COLUMNACCESS_DENIED_ERROR 1143
-#define ER_ILLEGAL_GRANT_FOR_TABLE 1144
-#define ER_GRANT_WRONG_HOST_OR_USER 1145
-#define ER_NO_SUCH_TABLE 1146
-#define ER_NONEXISTING_TABLE_GRANT 1147
-#define ER_NOT_ALLOWED_COMMAND 1148
-#define ER_SYNTAX_ERROR 1149
-#define ER_DELAYED_CANT_CHANGE_LOCK 1150
-#define ER_TOO_MANY_DELAYED_THREADS 1151
-#define ER_ABORTING_CONNECTION 1152
-#define ER_NET_PACKET_TOO_LARGE 1153
-#define ER_NET_READ_ERROR_FROM_PIPE 1154
-#define ER_NET_FCNTL_ERROR 1155
-#define ER_NET_PACKETS_OUT_OF_ORDER 1156
-#define ER_NET_UNCOMPRESS_ERROR 1157
-#define ER_NET_READ_ERROR 1158
-#define ER_NET_READ_INTERRUPTED 1159
-#define ER_NET_ERROR_ON_WRITE 1160
-#define ER_NET_WRITE_INTERRUPTED 1161
-#define ER_TOO_LONG_STRING 1162
-#define ER_TABLE_CANT_HANDLE_BLOB 1163
-#define ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164
-#define ER_DELAYED_INSERT_TABLE_LOCKED 1165
-#define ER_WRONG_COLUMN_NAME 1166
-#define ER_WRONG_KEY_COLUMN 1167
-#define ER_WRONG_MRG_TABLE 1168
-#define ER_DUP_UNIQUE 1169
-#define ER_BLOB_KEY_WITHOUT_LENGTH 1170
-#define ER_PRIMARY_CANT_HAVE_NULL 1171
-#define ER_TOO_MANY_ROWS 1172
-#define ER_REQUIRES_PRIMARY_KEY 1173
-#define ER_NO_RAID_COMPILED 1174
-#define ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175
-#define ER_KEY_DOES_NOT_EXITS 1176
-#define ER_CHECK_NO_SUCH_TABLE 1177
-#define ER_CHECK_NOT_IMPLEMENTED 1178
-#define ER_CANT_DO_THIS_DURING_AN_TRANSACTION 1179
-#define ER_ERROR_DURING_COMMIT 1180
-#define ER_ERROR_DURING_ROLLBACK 1181
-#define ER_ERROR_DURING_FLUSH_LOGS 1182
-#define ER_ERROR_DURING_CHECKPOINT 1183
-#define ER_NEW_ABORTING_CONNECTION 1184
-#define ER_DUMP_NOT_IMPLEMENTED 1185
-#define ER_FLUSH_MASTER_BINLOG_CLOSED 1186
-#define ER_INDEX_REBUILD 1187
-#define ER_MASTER 1188
-#define ER_MASTER_NET_READ 1189
-#define ER_MASTER_NET_WRITE 1190
-#define ER_FT_MATCHING_KEY_NOT_FOUND 1191
-#define ER_LOCK_OR_ACTIVE_TRANSACTION 1192
-#define ER_UNKNOWN_SYSTEM_VARIABLE 1193
-#define ER_CRASHED_ON_USAGE 1194
-#define ER_CRASHED_ON_REPAIR 1195
-#define ER_WARNING_NOT_COMPLETE_ROLLBACK 1196
-#define ER_TRANS_CACHE_FULL 1197
-#define ER_SLAVE_MUST_STOP 1198
-#define ER_SLAVE_NOT_RUNNING 1199
-#define ER_BAD_SLAVE 1200
-#define ER_MASTER_INFO 1201
-#define ER_SLAVE_THREAD 1202
-#define ER_TOO_MANY_USER_CONNECTIONS 1203
-#define ER_SET_CONSTANTS_ONLY 1204
-#define ER_LOCK_WAIT_TIMEOUT 1205
-#define ER_LOCK_TABLE_FULL 1206
-#define ER_READ_ONLY_TRANSACTION 1207
-#define ER_DROP_DB_WITH_READ_LOCK 1208
-#define ER_CREATE_DB_WITH_READ_LOCK 1209
-#define ER_WRONG_ARGUMENTS 1210
-#define ER_NO_PERMISSION_TO_CREATE_USER 1211
-#define ER_UNION_TABLES_IN_DIFFERENT_DIR 1212
-#define ER_LOCK_DEADLOCK 1213
-#define ER_TABLE_CANT_HANDLE_FT 1214
-#define ER_CANNOT_ADD_FOREIGN 1215
-#define ER_NO_REFERENCED_ROW 1216
-#define ER_ROW_IS_REFERENCED 1217
-#define ER_CONNECT_TO_MASTER 1218
-#define ER_QUERY_ON_MASTER 1219
-#define ER_ERROR_WHEN_EXECUTING_COMMAND 1220
-#define ER_WRONG_USAGE 1221
-#define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1222
-#define ER_CANT_UPDATE_WITH_READLOCK 1223
-#define ER_MIXING_NOT_ALLOWED 1224
-#define ER_DUP_ARGUMENT 1225
-#define ER_USER_LIMIT_REACHED 1226
-#define ER_SPECIFIC_ACCESS_DENIED_ERROR 1227
-#define ER_LOCAL_VARIABLE 1228
-#define ER_GLOBAL_VARIABLE 1229
-#define ER_NO_DEFAULT 1230
-#define ER_WRONG_VALUE_FOR_VAR 1231
-#define ER_WRONG_TYPE_FOR_VAR 1232
-#define ER_VAR_CANT_BE_READ 1233
-#define ER_CANT_USE_OPTION_HERE 1234
-#define ER_NOT_SUPPORTED_YET 1235
-#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236
-#define ER_SLAVE_IGNORED_TABLE 1237
-#define ER_INCORRECT_GLOBAL_LOCAL_VAR 1238
-#define ER_WRONG_FK_DEF 1239
-#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1240
-#define ER_OPERAND_COLUMNS 1241
-#define ER_SUBQUERY_NO_1_ROW 1242
-#define ER_UNKNOWN_STMT_HANDLER 1243
-#define ER_CORRUPT_HELP_DB 1244
-#define ER_CYCLIC_REFERENCE 1245
-#define ER_AUTO_CONVERT 1246
-#define ER_ILLEGAL_REFERENCE 1247
-#define ER_DERIVED_MUST_HAVE_ALIAS 1248
-#define ER_SELECT_REDUCED 1249
-#define ER_TABLENAME_NOT_ALLOWED_HERE 1250
-#define ER_NOT_SUPPORTED_AUTH_MODE 1251
-#define ER_SPATIAL_CANT_HAVE_NULL 1252
-#define ER_COLLATION_CHARSET_MISMATCH 1253
-#define ER_SLAVE_WAS_RUNNING 1254
-#define ER_SLAVE_WAS_NOT_RUNNING 1255
-#define ER_TOO_BIG_FOR_UNCOMPRESS 1256
-#define ER_ZLIB_Z_MEM_ERROR 1257
-#define ER_ZLIB_Z_BUF_ERROR 1258
-#define ER_ZLIB_Z_DATA_ERROR 1259
-#define ER_CUT_VALUE_GROUP_CONCAT 1260
-#define ER_WARN_TOO_FEW_RECORDS 1261
-#define ER_WARN_TOO_MANY_RECORDS 1262
-#define ER_WARN_NULL_TO_NOTNULL 1263
-#define ER_WARN_DATA_OUT_OF_RANGE 1264
-#define ER_WARN_DATA_TRUNCATED 1265
-#define ER_WARN_USING_OTHER_HANDLER 1266
-#define ER_CANT_AGGREGATE_2COLLATIONS 1267
-#define ER_DROP_USER 1268
-#define ER_REVOKE_GRANTS 1269
-#define ER_CANT_AGGREGATE_3COLLATIONS 1270
-#define ER_CANT_AGGREGATE_NCOLLATIONS 1271
-#define ER_VARIABLE_IS_NOT_STRUCT 1272
-#define ER_UNKNOWN_COLLATION 1273
-#define ER_SLAVE_IGNORED_SSL_PARAMS 1274
-#define ER_SERVER_IS_IN_SECURE_AUTH_MODE 1275
-#define ER_WARN_FIELD_RESOLVED 1276
-#define ER_BAD_SLAVE_UNTIL_COND 1277
-#define ER_MISSING_SKIP_SLAVE 1278
-#define ER_UNTIL_COND_IGNORED 1279
-#define ER_WRONG_NAME_FOR_INDEX 1280
-#define ER_WRONG_NAME_FOR_CATALOG 1281
-#define ER_WARN_QC_RESIZE 1282
-#define ER_BAD_FT_COLUMN 1283
-#define ER_UNKNOWN_KEY_CACHE 1284
-#define ER_WARN_HOSTNAME_WONT_WORK 1285
-#define ER_UNKNOWN_STORAGE_ENGINE 1286
-#define ER_WARN_DEPRECATED_SYNTAX 1287
-#define ER_NON_UPDATABLE_TABLE 1288
-#define ER_FEATURE_DISABLED 1289
-#define ER_OPTION_PREVENTS_STATEMENT 1290
-#define ER_DUPLICATED_VALUE_IN_TYPE 1291
-#define ER_TRUNCATED_WRONG_VALUE 1292
-#define ER_TOO_MUCH_AUTO_TIMESTAMP_COLS 1293
-#define ER_INVALID_ON_UPDATE 1294
-#define ER_UNSUPPORTED_PS 1295
-#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_INVALID_CHARACTER_STRING 1300
-#define ER_WARN_ALLOWED_PACKET_OVERFLOWED 1301
-#define ER_CONFLICTING_DECLARATIONS 1302
-#define ER_ERROR_MESSAGES 303
diff --git a/include/mysys_err.h b/include/mysys_err.h
index 19106dc3553..341e6950792 100644
--- a/include/mysys_err.h
+++ b/include/mysys_err.h
@@ -20,14 +20,20 @@
extern "C" {
#endif
-#define GLOB 0 /* Error maps */
-#define GLOBERRS 29 /* Max number of error messages in map's */
-#define EE(X) globerrs[ X ] /* Defines to add error to right map */
+#define GLOBERRS (EE_ERROR_LAST - EE_ERROR_FIRST + 1) /* Nr of global errors */
+#define EE(X) (globerrs[(X) - EE_ERROR_FIRST])
extern const char * NEAR globerrs[]; /* my_error_messages is here */
/* Error message numbers in global map */
-#define EE_FILENOTFOUND 0
+/*
+ Do not add error numbers before EE_ERROR_FIRST.
+ If necessary to add lower numbers, change EE_ERROR_FIRST accordingly.
+
+ We start with error 1 to not confuse peoples with 'error 0'
+*/
+
+#define EE_ERROR_FIRST 1 /*Copy first error nr.*/
#define EE_CANTCREATEFILE 1
#define EE_READ 2
#define EE_WRITE 3
@@ -55,6 +61,9 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */
#define EE_REALPATH 26
#define EE_SYNC 27
#define EE_UNKNOWN_COLLATION 28
+#define EE_FILENOTFOUND 29
+#define EE_ERROR_LAST 29 /*Copy last error nr.*/
+/* Add error numbers before EE_ERROR_LAST and change it accordingly. */
/* exit codes for all MySQL programs */
diff --git a/include/nisam.h b/include/nisam.h
deleted file mode 100644
index e8f29991a4e..00000000000
--- a/include/nisam.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* Copyright (C) 2000 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 should be included when using nisam_funktions */
-/* Author: Michael Widenius */
-
-#ifndef _nisam_h
-#define _nisam_h
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _my_base_h
-#include <my_base.h>
-#endif
- /* defines used by nisam-funktions */
-
-#define N_MAXKEY 16 /* Max allowed keys */
-#define N_MAXKEY_SEG 16 /* Max segments for key */
-#define N_MAX_KEY_LENGTH 256 /* May be increased up to 500 */
-#define N_MAX_KEY_BUFF (N_MAX_KEY_LENGTH+N_MAXKEY_SEG+sizeof(double)-1)
-#define N_MAX_POSSIBLE_KEY_BUFF 500+9
-
-#define N_NAME_IEXT ".ISM"
-#define N_NAME_DEXT ".ISD"
-#define NI_POS_ERROR (~ (ulong) 0)
-
-
- /* Param to/from nisam_info */
-
-typedef struct st_n_isaminfo /* Struct from h_info */
-{
- ulong records; /* Records in database */
- ulong deleted; /* Deleted records in database */
- ulong recpos; /* Pos for last used record */
- ulong newrecpos; /* Pos if we write new record */
- ulong dupp_key_pos; /* Position to record with dupp key */
- ulong data_file_length, /* Length of data file */
- max_data_file_length,
- index_file_length,
- max_index_file_length,
- delete_length;
- uint reclength; /* Recordlength */
- uint mean_reclength; /* Mean recordlength (if packed) */
- uint keys; /* How many keys used */
- uint options; /* HA_OPTION_... used */
- int errkey, /* With key was dupplicated on err */
- sortkey; /* clustered by this key */
- File filenr; /* (uniq) filenr for datafile */
- time_t create_time; /* When table was created */
- time_t isamchk_time;
- time_t update_time;
- ulong *rec_per_key; /* for sql optimizing */
-} N_ISAMINFO;
-
-
- /* Info saved on file for each info-part */
-
-#ifdef __WATCOMC__
-#pragma pack(2)
-#define uint uint16 /* Same format as in MSDOS */
-#endif
-
-#ifdef __ZTC__
-#pragma ZTC align 2
-#define uint uint16 /* Same format as in MSDOS */
-#endif
-
-typedef struct st_n_save_keyseg /* Key-portion */
-{
- uint8 type; /* Typ av nyckel (f|r sort) */
- uint8 flag; /* HA_DIFF_LENGTH */
- uint16 start; /* Start of key in record */
- uint16 length; /* Keylength */
-} N_SAVE_KEYSEG;
-
-typedef struct st_n_save_keydef /* Key definition with create & info */
-{
- uint8 flag; /* NOSAME, PACK_USED */
- uint8 keysegs; /* Number of key-segment */
- uint16 block_length; /* Length of keyblock (auto) */
- uint16 keylength; /* Tot length of keyparts (auto) */
- uint16 minlength; /* min length of (packed) key (auto) */
- uint16 maxlength; /* max length of (packed) key (auto) */
-} N_SAVE_KEYDEF;
-
-typedef struct st_n_save_recinfo /* Info of record */
-{
- int16 type; /* en_fieldtype */
- uint16 length; /* length of field */
-} N_SAVE_RECINFO;
-
-
-#ifdef __ZTC__
-#pragma ZTC align
-#undef uint
-#endif
-
-#ifdef __WATCOMC__
-#pragma pack()
-#undef uint
-#endif
-
-
-struct st_isam_info; /* For referense */
-
-#ifndef ISAM_LIBRARY
-typedef struct st_isam_info N_INFO;
-#endif
-
-typedef struct st_n_keyseg /* Key-portion */
-{
- N_SAVE_KEYSEG base;
-} N_KEYSEG;
-
-
-typedef struct st_n_keydef /* Key definition with open & info */
-{
- N_SAVE_KEYDEF base;
- N_KEYSEG seg[N_MAXKEY_SEG+1];
- int (*bin_search)(struct st_isam_info *info,struct st_n_keydef *keyinfo,
- uchar *page,uchar *key,
- uint key_len,uint comp_flag,uchar * *ret_pos,
- uchar *buff);
- uint (*get_key)(struct st_n_keydef *keyinfo,uint nod_flag,uchar * *page,
- uchar *key);
-} N_KEYDEF;
-
-
-typedef struct st_decode_tree /* Decode huff-table */
-{
- uint16 *table;
- uint quick_table_bits;
- byte *intervalls;
-} DECODE_TREE;
-
-
-struct st_bit_buff;
-
-typedef struct st_n_recinfo /* Info of record */
-{
- N_SAVE_RECINFO base;
-#ifndef NOT_PACKED_DATABASES
- void (*unpack)(struct st_n_recinfo *rec,struct st_bit_buff *buff,
- uchar *start,uchar *end);
- enum en_fieldtype base_type;
- uint space_length_bits,pack_type;
- DECODE_TREE *huff_tree;
-#endif
-} N_RECINFO;
-
-
-extern my_string nisam_log_filename; /* Name of logfile */
-extern uint nisam_block_size;
-extern my_bool nisam_flush;
-
- /* Prototypes for nisam-functions */
-
-extern int nisam_close(struct st_isam_info *file);
-extern int nisam_delete(struct st_isam_info *file,const byte *buff);
-extern struct st_isam_info *nisam_open(const char *name,int mode,
- uint wait_if_locked);
-extern int nisam_panic(enum ha_panic_function function);
-extern int nisam_rfirst(struct st_isam_info *file,byte *buf,int inx);
-extern int nisam_rkey(struct st_isam_info *file,byte *buf,int inx,
- const byte *key,
- uint key_len, enum ha_rkey_function search_flag);
-extern int nisam_rlast(struct st_isam_info *file,byte *buf,int inx);
-extern int nisam_rnext(struct st_isam_info *file,byte *buf,int inx);
-extern int nisam_rprev(struct st_isam_info *file,byte *buf,int inx);
-extern int nisam_rrnd(struct st_isam_info *file,byte *buf,ulong pos);
-extern int nisam_rsame(struct st_isam_info *file,byte *record,int inx);
-extern int nisam_rsame_with_pos(struct st_isam_info *file,byte *record,
- int inx,ulong pos);
-extern int nisam_update(struct st_isam_info *file,const byte *old,
- const byte *new_record);
-extern int nisam_write(struct st_isam_info *file,const byte *buff);
-extern int nisam_info(struct st_isam_info *file,N_ISAMINFO *x,int flag);
-extern ulong nisam_position(struct st_isam_info *info);
-extern int nisam_lock_database(struct st_isam_info *file,int lock_type);
-extern int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
- N_RECINFO *recinfo,ulong records,
- ulong reloc,uint flags,uint options,
- ulong data_file_length);
-extern int nisam_extra(struct st_isam_info *file,
- enum ha_extra_function function);
-extern ulong nisam_records_in_range(struct st_isam_info *info,int inx,
- const byte *start_key,uint start_key_len,
- enum ha_rkey_function start_search_flag,
- const byte *end_key,uint end_key_len,
- enum ha_rkey_function end_search_flag);
-extern int nisam_log(int activate_log);
-extern int nisam_is_changed(struct st_isam_info *info);
-extern uint _calc_blob_length(uint length , const byte *pos);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/include/queues.h b/include/queues.h
index ac15b09719b..02ab768198e 100644
--- a/include/queues.h
+++ b/include/queues.h
@@ -53,6 +53,7 @@ int resize_queue(QUEUE *queue, uint max_elements);
void delete_queue(QUEUE *queue);
void queue_insert(QUEUE *queue,byte *element);
byte *queue_remove(QUEUE *queue,uint idx);
+#define queue_remove_all(queue) { (queue)->elements= 0; }
void _downheap(QUEUE *queue,uint idx);
void queue_fix(QUEUE *queue);
#define is_queue_inited(queue) ((queue)->root != 0)
diff --git a/include/sql_state.h b/include/sql_state.h
deleted file mode 100644
index 52a359405e1..00000000000
--- a/include/sql_state.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Copyright (C) 2000-2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 includes a mapping from mysql_errno.h to sql_state (as used by
- MyODBC) and jdbc_state.
- It's suitable to include into a C struct for further processing
-
- The first column is the mysqld server error (declared in mysqld_error.h),
- 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.
-
- 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", "",
-ER_OUTOFMEMORY, "HY001", "S1001",
-ER_OUT_OF_SORTMEMORY, "HY001", "S1001",
-ER_CON_COUNT_ERROR, "08004", "",
-ER_BAD_HOST_ERROR, "08S01", "",
-ER_HANDSHAKE_ERROR, "08S01", "",
-ER_DBACCESS_DENIED_ERROR, "42000", "",
-ER_ACCESS_DENIED_ERROR, "28000", "",
-ER_NO_DB_ERROR, "3D000", "",
-ER_UNKNOWN_COM_ERROR, "08S01", "",
-ER_BAD_NULL_ERROR, "23000", "",
-ER_BAD_DB_ERROR, "42000", "",
-ER_TABLE_EXISTS_ERROR, "42S01", "",
-ER_BAD_TABLE_ERROR, "42S02", "",
-ER_NON_UNIQ_ERROR, "23000", "",
-ER_SERVER_SHUTDOWN, "08S01", "",
-ER_BAD_FIELD_ERROR, "42S22", "S0022",
-ER_WRONG_FIELD_WITH_GROUP, "42000", "S1009",
-ER_WRONG_GROUP_FIELD, "42000", "S1009",
-ER_WRONG_SUM_SELECT, "42000", "S1009",
-ER_WRONG_VALUE_COUNT, "21S01", "",
-ER_TOO_LONG_IDENT, "42000", "S1009",
-ER_DUP_FIELDNAME, "42S21", "S1009",
-ER_DUP_KEYNAME, "42000", "S1009",
-ER_DUP_ENTRY, "23000", "S1009",
-ER_WRONG_FIELD_SPEC, "42000", "S1009",
-ER_PARSE_ERROR, "42000", "",
-ER_EMPTY_QUERY, "42000" , "",
-ER_NONUNIQ_TABLE, "42000", "S1009",
-ER_INVALID_DEFAULT, "42000", "S1009",
-ER_MULTIPLE_PRI_KEY, "42000", "S1009",
-ER_TOO_MANY_KEYS, "42000", "S1009",
-ER_TOO_MANY_KEY_PARTS, "42000", "S1009",
-ER_TOO_LONG_KEY, "42000", "S1009",
-ER_KEY_COLUMN_DOES_NOT_EXITS, "42000", "S1009",
-ER_BLOB_USED_AS_KEY, "42000", "S1009",
-ER_TOO_BIG_FIELDLENGTH, "42000", "S1009",
-ER_WRONG_AUTO_KEY, "42000", "S1009",
-ER_FORCING_CLOSE, "08S01", "",
-ER_IPSOCK_ERROR, "08S01", "",
-ER_NO_SUCH_INDEX, "42S12", "S1009",
-ER_WRONG_FIELD_TERMINATORS, "42000", "S1009",
-ER_BLOBS_AND_NO_TERMINATED, "42000", "S1009",
-ER_CANT_REMOVE_ALL_FIELDS, "42000", "",
-ER_CANT_DROP_FIELD_OR_KEY, "42000", "",
-ER_BLOB_CANT_HAVE_DEFAULT, "42000", "",
-ER_WRONG_DB_NAME, "42000", "",
-ER_WRONG_TABLE_NAME, "42000", "",
-ER_TOO_BIG_SELECT, "42000", "",
-ER_UNKNOWN_PROCEDURE, "42000", "",
-ER_WRONG_PARAMCOUNT_TO_PROCEDURE, "42000", "",
-ER_UNKNOWN_TABLE, "42S02", "",
-ER_FIELD_SPECIFIED_TWICE, "42000", "",
-ER_UNSUPPORTED_EXTENSION, "42000", "",
-ER_TABLE_MUST_HAVE_COLUMNS, "42000", "",
-ER_UNKNOWN_CHARACTER_SET, "42000", "",
-ER_TOO_BIG_ROWSIZE, "42000", "",
-ER_WRONG_OUTER_JOIN, "42000", "",
-ER_NULL_COLUMN_IN_INDEX, "42000", "",
-ER_PASSWORD_ANONYMOUS_USER, "42000", "",
-ER_PASSWORD_NOT_ALLOWED, "42000", "",
-ER_PASSWORD_NO_MATCH, "42000", "",
-ER_WRONG_VALUE_COUNT_ON_ROW, "21S01", "",
-ER_INVALID_USE_OF_NULL, "42000", "",
-ER_REGEXP_ERROR, "42000", "",
-ER_MIX_OF_GROUP_FUNC_AND_FIELDS,"42000", "",
-ER_NONEXISTING_GRANT, "42000", "",
-ER_TABLEACCESS_DENIED_ERROR, "42000", "",
-ER_COLUMNACCESS_DENIED_ERROR, "42000", "",
-ER_ILLEGAL_GRANT_FOR_TABLE, "42000", "",
-ER_GRANT_WRONG_HOST_OR_USER, "42000", "",
-ER_NO_SUCH_TABLE, "42S02", "",
-ER_NONEXISTING_TABLE_GRANT, "42000", "",
-ER_NOT_ALLOWED_COMMAND, "42000", "",
-ER_SYNTAX_ERROR, "42000", "",
-ER_ABORTING_CONNECTION, "08S01", "",
-ER_NET_PACKET_TOO_LARGE, "08S01", "",
-ER_NET_READ_ERROR_FROM_PIPE, "08S01", "",
-ER_NET_FCNTL_ERROR, "08S01", "",
-ER_NET_PACKETS_OUT_OF_ORDER, "08S01", "",
-ER_NET_UNCOMPRESS_ERROR, "08S01", "",
-ER_NET_READ_ERROR, "08S01", "",
-ER_NET_READ_INTERRUPTED, "08S01", "",
-ER_NET_ERROR_ON_WRITE, "08S01", "",
-ER_NET_WRITE_INTERRUPTED, "08S01", "",
-ER_TOO_LONG_STRING, "42000", "",
-ER_TABLE_CANT_HANDLE_BLOB, "42000", "",
-ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, "42000", "",
-ER_WRONG_COLUMN_NAME, "42000", "",
-ER_WRONG_KEY_COLUMN, "42000", "",
-ER_DUP_UNIQUE, "23000", "",
-ER_BLOB_KEY_WITHOUT_LENGTH, "42000", "",
-ER_PRIMARY_CANT_HAVE_NULL, "42000", "",
-ER_TOO_MANY_ROWS, "42000", "",
-ER_REQUIRES_PRIMARY_KEY, "42000", "",
-ER_CHECK_NO_SUCH_TABLE, "42000", "",
-ER_CHECK_NOT_IMPLEMENTED, "42000", "",
-ER_CANT_DO_THIS_DURING_AN_TRANSACTION, "25000", "",
-ER_NEW_ABORTING_CONNECTION, "08S01", "",
-ER_MASTER_NET_READ, "08S01", "",
-ER_MASTER_NET_WRITE, "08S01", "",
-ER_TOO_MANY_USER_CONNECTIONS, "42000", "",
-ER_READ_ONLY_TRANSACTION, "25000", "",
-ER_NO_PERMISSION_TO_CREATE_USER,"42000", "",
-ER_LOCK_DEADLOCK, "40001", "",
-ER_NO_REFERENCED_ROW, "23000", "",
-ER_ROW_IS_REFERENCED, "23000", "",
-ER_CONNECT_TO_MASTER, "08S01", "",
-ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,"21000", "",
-ER_USER_LIMIT_REACHED, "42000", "",
-ER_NO_DEFAULT, "42000", "",
-ER_WRONG_VALUE_FOR_VAR, "42000", "",
-ER_WRONG_TYPE_FOR_VAR, "42000", "",
-ER_CANT_USE_OPTION_HERE, "42000", "",
-ER_NOT_SUPPORTED_YET, "42000", "",
-ER_WRONG_FK_DEF, "42000", "",
-ER_OPERAND_COLUMNS, "21000", "",
-ER_SUBQUERY_NO_1_ROW, "21000", "",
-ER_ILLEGAL_REFERENCE, "42S22", "",
-ER_DERIVED_MUST_HAVE_ALIAS, "42000", "",
-ER_SELECT_REDUCED, "01000", "",
-ER_TABLENAME_NOT_ALLOWED_HERE, "42000", "",
-ER_NOT_SUPPORTED_AUTH_MODE, "08004", "",
-ER_SPATIAL_CANT_HAVE_NULL, "42000", "",
-ER_COLLATION_CHARSET_MISMATCH, "42000", "",
-ER_WARN_TOO_FEW_RECORDS, "01000", "",
-ER_WARN_TOO_MANY_RECORDS, "01000", "",
-ER_WARN_NULL_TO_NOTNULL, "01000", "",
-ER_WARN_DATA_OUT_OF_RANGE, "01000", "",
-ER_WARN_DATA_TRUNCATED, "01000", "",
-ER_WRONG_NAME_FOR_INDEX, "42000", "",
-ER_WRONG_NAME_FOR_CATALOG, "42000", "",
-ER_UNKNOWN_STORAGE_ENGINE, "42000", "",
diff --git a/include/thr_lock.h b/include/thr_lock.h
index 7459ab7aefc..251d8e7c9cf 100644
--- a/include/thr_lock.h
+++ b/include/thr_lock.h
@@ -62,17 +62,45 @@ enum thr_lock_type { TL_IGNORE=-1,
/* Abort new lock request with an error */
TL_WRITE_ONLY};
+enum enum_thr_lock_result { THR_LOCK_SUCCESS= 0, THR_LOCK_ABORTED= 1,
+ THR_LOCK_WAIT_TIMEOUT= 2, THR_LOCK_DEADLOCK= 3 };
+
+
extern ulong max_write_lock_count;
+extern ulong table_lock_wait_timeout;
extern my_bool thr_lock_inited;
extern enum thr_lock_type thr_upgraded_concurrent_insert_lock;
-typedef struct st_thr_lock_data {
+/*
+ A description of the thread which owns the lock. The address
+ of an instance of this structure is used to uniquely identify the thread.
+*/
+
+typedef struct st_thr_lock_info
+{
pthread_t thread;
+ ulong thread_id;
+ ulong n_cursors;
+} THR_LOCK_INFO;
+
+/*
+ Lock owner identifier. Globally identifies the lock owner within the
+ thread and among all the threads. The address of an instance of this
+ structure is used as id.
+*/
+
+typedef struct st_thr_lock_owner
+{
+ THR_LOCK_INFO *info;
+} THR_LOCK_OWNER;
+
+
+typedef struct st_thr_lock_data {
+ THR_LOCK_OWNER *owner;
struct st_thr_lock_data *next,**prev;
struct st_thr_lock *lock;
pthread_cond_t *cond;
enum thr_lock_type type;
- ulong thread_id;
void *status_param; /* Param to status functions */
void *debug_print_param;
} THR_LOCK_DATA;
@@ -88,10 +116,10 @@ typedef struct st_thr_lock {
struct st_lock_list read;
struct st_lock_list write_wait;
struct st_lock_list write;
-/* write_lock_count is incremented for write locks and reset on read locks */
+ /* write_lock_count is incremented for write locks and reset on read locks */
ulong write_lock_count;
uint read_no_write_count;
- void (*get_status)(void*); /* When one gets a lock */
+ void (*get_status)(void*, int); /* When one gets a lock */
void (*copy_status)(void*,void*);
void (*update_status)(void*); /* Before release of write */
my_bool (*check_status)(void *);
@@ -102,13 +130,18 @@ extern LIST *thr_lock_thread_list;
extern pthread_mutex_t THR_LOCK_lock;
my_bool init_thr_lock(void); /* Must be called once/thread */
+#define thr_lock_owner_init(owner, info_arg) (owner)->info= (info_arg)
+void thr_lock_info_init(THR_LOCK_INFO *info);
void thr_lock_init(THR_LOCK *lock);
void thr_lock_delete(THR_LOCK *lock);
void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data,
void *status_param);
-int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type);
+enum enum_thr_lock_result thr_lock(THR_LOCK_DATA *data,
+ THR_LOCK_OWNER *owner,
+ enum thr_lock_type lock_type);
void thr_unlock(THR_LOCK_DATA *data);
-int thr_multi_lock(THR_LOCK_DATA **data,uint count);
+enum enum_thr_lock_result thr_multi_lock(THR_LOCK_DATA **data,
+ uint count, THR_LOCK_OWNER *owner);
void thr_multi_unlock(THR_LOCK_DATA **data,uint count);
void thr_abort_locks(THR_LOCK *lock);
my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread);
diff --git a/include/violite.h b/include/violite.h
index fbc6a546cc5..b48f3724f5b 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -37,7 +37,12 @@ enum enum_vio_type
VIO_TYPE_SSL, VIO_TYPE_SHARED_MEMORY
};
-Vio* vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost);
+
+#define VIO_LOCALHOST 1 /* a localhost connection */
+#define VIO_BUFFERED_READ 2 /* use buffered read */
+#define VIO_READ_BUFFER_SIZE 16384 /* size of read buffer */
+
+Vio* vio_new(my_socket sd, enum enum_vio_type type, uint flags);
#ifdef __WIN__
Vio* vio_new_win32pipe(HANDLE hPipe);
Vio* vio_new_win32shared_memory(NET *net,HANDLE handle_file_map,
@@ -57,8 +62,9 @@ int vio_close_pipe(Vio * vio);
void vio_delete(Vio* vio);
int vio_close(Vio* vio);
void vio_reset(Vio* vio, enum enum_vio_type type,
- my_socket sd, HANDLE hPipe, my_bool localhost);
+ my_socket sd, HANDLE hPipe, uint flags);
int vio_read(Vio *vio, gptr buf, int size);
+int vio_read_buff(Vio *vio, gptr buf, int size);
int vio_write(Vio *vio, const gptr buf, int size);
int vio_blocking(Vio *vio, my_bool onoff, my_bool *old_mode);
my_bool vio_is_blocking(Vio *vio);
@@ -95,6 +101,7 @@ void vio_timeout(Vio *vio,uint which, uint timeout);
#endif
#define HEADER_DES_LOCL_H dummy_something
+#define YASSL_MYSQL_COMPATIBLE
#include <openssl/ssl.h>
#include <openssl/err.h>
@@ -137,7 +144,7 @@ int vio_close_shared_memory(Vio * vio);
}
#endif
-#if defined(HAVE_VIO) && !defined(DONT_MAP_VIO)
+#if !defined(DONT_MAP_VIO)
#define vio_delete(vio) (vio)->viodelete(vio)
#define vio_errno(vio) (vio)->vioerrno(vio)
#define vio_read(vio, buf, size) ((vio)->read)(vio,buf,size)
@@ -153,7 +160,7 @@ int vio_close_shared_memory(Vio * vio);
#define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
#define vio_timeout(vio, which, seconds) (vio)->timeout(vio, which, seconds)
-#endif /* defined(HAVE_VIO) && !defined(DONT_MAP_VIO) */
+#endif /* !defined(DONT_MAP_VIO) */
/* This enumerator is used in parser - should be always visible */
enum SSL_type
@@ -178,7 +185,10 @@ struct st_vio
struct sockaddr_in remote; /* Remote internet address */
enum enum_vio_type type; /* Type of connection */
char desc[30]; /* String description */
-#ifdef HAVE_VIO
+ char *read_buffer; /* buffer for vio_read_buff */
+ char *read_pos; /* start of unfetched data in the
+ read buffer */
+ char *read_end; /* end of unfetched data */
/* function pointers. They are similar for socket/SSL/whatever */
void (*viodelete)(Vio*);
int (*vioerrno)(Vio*);
@@ -207,6 +217,5 @@ struct st_vio
char *shared_memory_pos;
NET *net;
#endif /* HAVE_SMEM */
-#endif /* HAVE_VIO */
};
#endif /* vio_violite_h_ */
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index ae967e0525e..c27fb73ff8d 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -20,6 +20,7 @@ Created 6/2/1994 Heikki Tuuri
#include "rem0cmp.h"
#include "lock0lock.h"
#include "ibuf0ibuf.h"
+#include "trx0trx.h"
/*
Latching strategy of the InnoDB B-tree
@@ -86,15 +87,6 @@ btr_page_create(
page_t* page, /* in: page to be created */
dict_tree_t* tree, /* in: index tree */
mtr_t* mtr); /* in: mtr */
-/******************************************************************
-Sets the child node file address in a node pointer. */
-UNIV_INLINE
-void
-btr_node_ptr_set_child_page_no(
-/*===========================*/
- rec_t* rec, /* in: node pointer record */
- ulint page_no, /* in: child node address */
- mtr_t* mtr); /* in: mtr */
/****************************************************************
Returns the upper level node pointer to a page. It is assumed that
mtr holds an x-latch on the tree. */
@@ -128,7 +120,10 @@ btr_page_insert_fits(
rec_t* split_rec, /* in: suggestion for first record
on upper half-page, or NULL if
tuple should be first */
- dtuple_t* tuple); /* in: tuple to insert */
+ const ulint* offsets, /* in: rec_get_offsets(
+ split_rec, cursor->index) */
+ dtuple_t* tuple, /* in: tuple to insert */
+ mem_heap_t* heap); /* in: temporary memory heap */
/******************************************************************
Gets the root node of a tree and x-latches it. */
@@ -148,6 +143,8 @@ btr_root_get(
root_page_no = dict_tree_get_page(tree);
root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
+ ut_a((ibool)!!page_is_comp(root) ==
+ UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
return(root);
}
@@ -167,21 +164,19 @@ btr_get_prev_user_rec(
page_t* page;
page_t* prev_page;
ulint prev_page_no;
- rec_t* prev_rec;
ulint space;
- page = buf_frame_align(rec);
-
- if (page_get_infimum_rec(page) != rec) {
+ if (!page_rec_is_infimum(rec)) {
- prev_rec = page_rec_get_prev(rec);
+ rec_t* prev_rec = page_rec_get_prev(rec);
- if (page_get_infimum_rec(page) != prev_rec) {
+ if (!page_rec_is_infimum(prev_rec)) {
return(prev_rec);
}
}
+ page = buf_frame_align(rec);
prev_page_no = btr_page_get_prev(page, mtr);
space = buf_frame_get_space_id(page);
@@ -194,10 +189,9 @@ btr_get_prev_user_rec(
MTR_MEMO_PAGE_S_FIX))
|| (mtr_memo_contains(mtr, buf_block_align(prev_page),
MTR_MEMO_PAGE_X_FIX)));
+ ut_a(page_is_comp(prev_page) == page_is_comp(page));
- prev_rec = page_rec_get_prev(page_get_supremum_rec(prev_page));
-
- return(prev_rec);
+ return(page_rec_get_prev(page_get_supremum_rec(prev_page)));
}
return(NULL);
@@ -218,21 +212,19 @@ btr_get_next_user_rec(
page_t* page;
page_t* next_page;
ulint next_page_no;
- rec_t* next_rec;
ulint space;
- page = buf_frame_align(rec);
-
- if (page_get_supremum_rec(page) != rec) {
+ if (!page_rec_is_supremum(rec)) {
- next_rec = page_rec_get_next(rec);
+ rec_t* next_rec = page_rec_get_next(rec);
- if (page_get_supremum_rec(page) != next_rec) {
+ if (!page_rec_is_supremum(next_rec)) {
return(next_rec);
}
}
+ page = buf_frame_align(rec);
next_page_no = btr_page_get_next(page, mtr);
space = buf_frame_get_space_id(page);
@@ -246,9 +238,8 @@ btr_get_next_user_rec(
|| (mtr_memo_contains(mtr, buf_block_align(next_page),
MTR_MEMO_PAGE_X_FIX)));
- next_rec = page_rec_get_next(page_get_infimum_rec(next_page));
-
- return(next_rec);
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
+ return(page_rec_get_next(page_get_infimum_rec(next_page)));
}
return(NULL);
@@ -267,7 +258,8 @@ btr_page_create(
{
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
- page_create(page, mtr);
+ page_create(page, mtr,
+ UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
buf_block_align(page)->check_index_page_at_flush = TRUE;
btr_page_set_index_id(page, tree->id, mtr);
@@ -503,20 +495,21 @@ UNIV_INLINE
void
btr_node_ptr_set_child_page_no(
/*===========================*/
- rec_t* rec, /* in: node pointer record */
- ulint page_no, /* in: child node address */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: node pointer record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint page_no,/* in: child node address */
+ mtr_t* mtr) /* in: mtr */
{
- ulint n_fields;
byte* field;
ulint len;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(0 < btr_page_get_level(buf_frame_align(rec), mtr));
-
- n_fields = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
/* The child address is in the last field */
- field = rec_get_nth_field(rec, n_fields - 1, &len);
+ field = rec_get_nth_field(rec, offsets,
+ rec_offs_n_fields(offsets) - 1, &len);
ut_ad(len == 4);
@@ -529,16 +522,18 @@ static
page_t*
btr_node_ptr_get_child(
/*===================*/
- /* out: child page, x-latched */
- rec_t* node_ptr, /* in: node pointer */
- mtr_t* mtr) /* in: mtr */
+ /* out: child page, x-latched */
+ rec_t* node_ptr,/* in: node pointer */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ mtr_t* mtr) /* in: mtr */
{
ulint page_no;
ulint space;
page_t* page;
-
+
+ ut_ad(rec_offs_validate(node_ptr, NULL, offsets));
space = buf_frame_get_space_id(node_ptr);
- page_no = btr_node_ptr_get_child_page_no(node_ptr);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
@@ -564,11 +559,14 @@ btr_page_get_father_for_rec(
dtuple_t* tuple;
btr_cur_t cursor;
rec_t* node_ptr;
+ dict_index_t* index;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
- ut_a(user_rec != page_get_supremum_rec(page));
- ut_a(user_rec != page_get_infimum_rec(page));
+ ut_a(page_rec_is_user_rec(user_rec));
ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page));
@@ -576,36 +574,44 @@ btr_page_get_father_for_rec(
tuple = dict_tree_build_node_ptr(tree, user_rec, 0, heap,
btr_page_get_level(page, mtr));
+ index = UT_LIST_GET_FIRST(tree->tree_indexes);
/* In the following, we choose just any index from the tree as the
first parameter for btr_cur_search_to_nth_level. */
-
- btr_cur_search_to_nth_level(UT_LIST_GET_FIRST(tree->tree_indexes),
+
+ btr_cur_search_to_nth_level(index,
btr_page_get_level(page, mtr) + 1,
tuple, PAGE_CUR_LE,
BTR_CONT_MODIFY_TREE, &cursor, 0, mtr);
node_ptr = btr_cur_get_rec(&cursor);
+ offsets = rec_get_offsets(node_ptr, index, offsets,
+ ULINT_UNDEFINED, &heap);
- if (btr_node_ptr_get_child_page_no(node_ptr) !=
+ if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
buf_frame_get_page_no(page)) {
+ rec_t* print_rec;
fputs("InnoDB: Dump of the child page:\n", stderr);
buf_page_print(buf_frame_align(page));
fputs("InnoDB: Dump of the parent page:\n", stderr);
buf_page_print(buf_frame_align(node_ptr));
fputs("InnoDB: Corruption of an index tree: table ", stderr);
- ut_print_name(stderr, NULL,
- UT_LIST_GET_FIRST(tree->tree_indexes)->table_name);
+ ut_print_name(stderr, NULL, index->table_name);
fputs(", index ", stderr);
- ut_print_name(stderr, NULL,
- UT_LIST_GET_FIRST(tree->tree_indexes)->name);
+ ut_print_name(stderr, NULL, index->name);
fprintf(stderr, ",\n"
"InnoDB: father ptr page no %lu, child page no %lu\n",
- (ulong) btr_node_ptr_get_child_page_no(node_ptr),
+ (ulong)
+ btr_node_ptr_get_child_page_no(node_ptr, offsets),
(ulong) buf_frame_get_page_no(page));
- page_rec_print(page_rec_get_next(page_get_infimum_rec(page)));
- page_rec_print(node_ptr);
+ print_rec = page_rec_get_next(page_get_infimum_rec(page));
+ offsets = rec_get_offsets(print_rec, index,
+ offsets, ULINT_UNDEFINED, &heap);
+ page_rec_print(print_rec, offsets);
+ offsets = rec_get_offsets(node_ptr, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ page_rec_print(node_ptr, offsets);
fputs(
"InnoDB: You should dump + drop + reimport the table to fix the\n"
@@ -614,7 +620,7 @@ btr_page_get_father_for_rec(
"InnoDB: forcing recovery. Then dump + drop + reimport.\n", stderr);
}
- ut_a(btr_node_ptr_get_child_page_no(node_ptr) ==
+ ut_a(btr_node_ptr_get_child_page_no(node_ptr, offsets) ==
buf_frame_get_page_no(page));
mem_heap_free(heap);
@@ -649,6 +655,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
+ ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr) /* in: mini-transaction handle */
{
ulint page_no;
@@ -716,7 +723,7 @@ btr_create(
}
/* Create a new index page on the the allocated segment page */
- page = page_create(frame, mtr);
+ page = page_create(frame, mtr, comp);
buf_block_align(page)->check_index_page_at_flush = TRUE;
/* Set the index id of the page */
@@ -821,12 +828,14 @@ static
void
btr_page_reorganize_low(
/*====================*/
- ibool recovery,/* in: TRUE if called in recovery: locks should not
- be updated, i.e., there cannot exist locks on the
- page, and a hash index should not be dropped: it
- cannot exist */
- page_t* page, /* in: page to be reorganized */
- mtr_t* mtr) /* in: mtr */
+ ibool recovery,/* in: TRUE if called in recovery:
+ locks should not be updated, i.e.,
+ there cannot exist locks on the
+ page, and a hash index should not be
+ dropped: it cannot exist */
+ page_t* page, /* in: page to be reorganized */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_t* new_page;
ulint log_mode;
@@ -837,11 +846,14 @@ btr_page_reorganize_low(
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
+ ut_ad(!!page_is_comp(page) == index->table->comp);
data_size1 = page_get_data_size(page);
max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);
/* Write the log record */
- mlog_write_initial_log_record(page, MLOG_PAGE_REORGANIZE, mtr);
+ mlog_open_and_write_index(mtr, page, index, page_is_comp(page)
+ ? MLOG_COMP_PAGE_REORGANIZE
+ : MLOG_PAGE_REORGANIZE, 0);
/* Turn logging off */
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
@@ -858,14 +870,14 @@ btr_page_reorganize_low(
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
- page_create(page, mtr);
+ page_create(page, mtr, page_is_comp(page));
buf_block_align(page)->check_index_page_at_flush = TRUE;
/* Copy the records from the temporary space to the recreated page;
do not copy the lock bits yet */
page_copy_rec_list_end_no_locks(page, new_page,
- page_get_infimum_rec(new_page), mtr);
+ page_get_infimum_rec(new_page), index, mtr);
/* Copy max trx id to recreated page */
page_set_max_trx_id(page, page_get_max_trx_id(new_page));
@@ -901,10 +913,11 @@ Reorganizes an index page. */
void
btr_page_reorganize(
/*================*/
- page_t* page, /* in: page to be reorganized */
- mtr_t* mtr) /* in: mtr */
+ page_t* page, /* in: page to be reorganized */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
- btr_page_reorganize_low(FALSE, page, mtr);
+ btr_page_reorganize_low(FALSE, page, index, mtr);
}
/***************************************************************
@@ -913,18 +926,20 @@ Parses a redo log record of reorganizing a page. */
byte*
btr_parse_page_reorganize(
/*======================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr __attribute__((unused)), /* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr __attribute__((unused)),
+ /* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
ut_ad(ptr && end_ptr);
/* The record is empty, except for the record initial part */
if (page) {
- btr_page_reorganize_low(TRUE, page, mtr);
+ btr_page_reorganize_low(TRUE, page, index, mtr);
}
return(ptr);
@@ -946,7 +961,7 @@ btr_page_empty(
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
- page_create(page, mtr);
+ page_create(page, mtr, page_is_comp(page));
buf_block_align(page)->check_index_page_at_flush = TRUE;
}
@@ -1011,7 +1026,7 @@ btr_root_raise_and_insert(
/* Move the records from root to the new page */
page_move_rec_list_end(new_page, root, page_get_infimum_rec(root),
- mtr);
+ cursor->index, mtr);
/* If this is a pessimistic insert which is actually done to
perform a pessimistic update then we have stored the lock
information of the record to be inserted on the infimum of the
@@ -1031,7 +1046,7 @@ btr_root_raise_and_insert(
node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap,
level);
/* Reorganize the root to get free space */
- btr_page_reorganize(root, mtr);
+ btr_page_reorganize(root, cursor->index, mtr);
page_cursor = btr_cur_get_page_cur(cursor);
@@ -1039,7 +1054,8 @@ btr_root_raise_and_insert(
page_cur_set_before_first(root, page_cursor);
- node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr, mtr);
+ node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr,
+ cursor->index, mtr);
ut_ad(node_ptr_rec);
@@ -1047,7 +1063,7 @@ btr_root_raise_and_insert(
as there is no lower alphabetical limit to records in the leftmost
node of a level: */
- btr_set_min_rec_mark(node_ptr_rec, mtr);
+ btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr);
/* Free the memory heap */
mem_heap_free(heap);
@@ -1060,7 +1076,8 @@ btr_root_raise_and_insert(
ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
new_page);
/* Reposition the cursor to the child node */
- page_cur_search(new_page, tuple, PAGE_CUR_LE, page_cursor);
+ page_cur_search(new_page, cursor->index, tuple,
+ PAGE_CUR_LE, page_cursor);
/* Split the child and insert tuple */
return(btr_page_split_and_insert(cursor, tuple, mtr));
@@ -1127,7 +1144,6 @@ btr_page_get_split_rec_to_right(
{
page_t* page;
rec_t* insert_point;
- rec_t* supremum;
page = btr_cur_get_page(cursor);
insert_point = btr_cur_get_rec(cursor);
@@ -1136,13 +1152,23 @@ btr_page_get_split_rec_to_right(
the previous insert on the same page, we assume that there is a
pattern of sequential inserts here. */
- if (page_header_get_ptr(page, PAGE_LAST_INSERT) == insert_point) {
+ if (UNIV_LIKELY(page_header_get_ptr(page, PAGE_LAST_INSERT)
+ == insert_point)) {
+
+ rec_t* next_rec;
- supremum = page_get_supremum_rec(page);
-
- if (page_rec_get_next(insert_point) != supremum
- && page_rec_get_next(page_rec_get_next(insert_point))
- != supremum) {
+ next_rec = page_rec_get_next(insert_point);
+
+ if (page_rec_is_supremum(next_rec)) {
+split_at_new:
+ /* Split at the new record to insert */
+ *split_rec = NULL;
+ } else {
+ rec_t* next_next_rec = page_rec_get_next(next_rec);
+ if (page_rec_is_supremum(next_next_rec)) {
+
+ goto split_at_new;
+ }
/* If there are >= 2 user records up from the insert
point, split all but 1 off. We want to keep one because
@@ -1151,12 +1177,8 @@ btr_page_get_split_rec_to_right(
search position just by looking at the records on this
page. */
- *split_rec = page_rec_get_next(
- page_rec_get_next(insert_point));
- } else {
- /* Else split at the new record to insert */
- *split_rec = NULL;
- }
+ *split_rec = next_next_rec;
+ }
return(TRUE);
}
@@ -1190,11 +1212,13 @@ btr_page_get_sure_split_rec(
rec_t* rec;
rec_t* next_rec;
ulint n;
-
+ mem_heap_t* heap;
+ ulint* offsets;
+
page = btr_cur_get_page(cursor);
- insert_size = rec_get_converted_size(tuple);
- free_space = page_get_free_space_of_empty();
+ insert_size = rec_get_converted_size(cursor->index, tuple);
+ free_space = page_get_free_space_of_empty(page_is_comp(page));
/* free_space is now the free space of a created new page */
@@ -1208,6 +1232,9 @@ btr_page_get_sure_split_rec(
ins_rec = btr_cur_get_rec(cursor);
rec = page_get_infimum_rec(page);
+ heap = NULL;
+ offsets = NULL;
+
/* We start to include records to the left half, and when the
space reserved by them exceeds half of total_space, then if
the included records fit on the left page, they will be put there
@@ -1230,7 +1257,9 @@ btr_page_get_sure_split_rec(
/* Include tuple */
incl_data += insert_size;
} else {
- incl_data += rec_get_size(rec);
+ offsets = rec_get_offsets(rec, cursor->index,
+ offsets, ULINT_UNDEFINED, &heap);
+ incl_data += rec_offs_size(offsets);
}
n++;
@@ -1245,18 +1274,24 @@ btr_page_get_sure_split_rec(
supremum record of page */
if (rec == ins_rec) {
- next_rec = NULL;
+ rec = NULL;
+
+ goto func_exit;
} else if (rec == NULL) {
next_rec = page_rec_get_next(ins_rec);
} else {
next_rec = page_rec_get_next(rec);
}
- if (next_rec != page_get_supremum_rec(page)) {
-
- return(next_rec);
+ ut_ad(next_rec);
+ if (!page_rec_is_supremum(next_rec)) {
+ rec = next_rec;
}
}
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(rec);
}
}
@@ -1275,7 +1310,10 @@ btr_page_insert_fits(
rec_t* split_rec, /* in: suggestion for first record
on upper half-page, or NULL if
tuple to be inserted should be first */
- dtuple_t* tuple) /* in: tuple to insert */
+ const ulint* offsets, /* in: rec_get_offsets(
+ split_rec, cursor->index) */
+ dtuple_t* tuple, /* in: tuple to insert */
+ mem_heap_t* heap) /* in: temporary memory heap */
{
page_t* page;
ulint insert_size;
@@ -1284,11 +1322,18 @@ btr_page_insert_fits(
ulint total_n_recs;
rec_t* rec;
rec_t* end_rec;
+ ulint* offs;
page = btr_cur_get_page(cursor);
-
- insert_size = rec_get_converted_size(tuple);
- free_space = page_get_free_space_of_empty();
+
+ ut_ad(!split_rec == !offsets);
+ ut_ad(!offsets
+ || !page_is_comp(page) == !rec_offs_comp(offsets));
+ ut_ad(!offsets
+ || rec_offs_validate(split_rec, cursor->index, offsets));
+
+ insert_size = rec_get_converted_size(cursor->index, tuple);
+ free_space = page_get_free_space_of_empty(page_is_comp(page));
/* free_space is now the free space of a created new page */
@@ -1303,7 +1348,7 @@ btr_page_insert_fits(
rec = page_rec_get_next(page_get_infimum_rec(page));
end_rec = page_rec_get_next(btr_cur_get_rec(cursor));
- } else if (cmp_dtuple_rec(tuple, split_rec) >= 0) {
+ } else if (cmp_dtuple_rec(tuple, split_rec, offsets) >= 0) {
rec = page_rec_get_next(page_get_infimum_rec(page));
end_rec = split_rec;
@@ -1321,11 +1366,16 @@ btr_page_insert_fits(
return(TRUE);
}
+ offs = NULL;
+
while (rec != end_rec) {
/* In this loop we calculate the amount of reserved
space after rec is removed from page. */
- total_data -= rec_get_size(rec);
+ offs = rec_get_offsets(rec, cursor->index, offs,
+ ULINT_UNDEFINED, &heap);
+
+ total_data -= rec_offs_size(offs);
total_n_recs--;
if (total_data + page_dir_calc_reserved_space(total_n_recs)
@@ -1411,6 +1461,10 @@ btr_attach_half_pages(
MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr_memo_contains(mtr, buf_block_align(new_page),
MTR_MEMO_PAGE_X_FIX));
+ ut_a(page_is_comp(page) == page_is_comp(new_page));
+
+ /* Create a memory heap where the data tuple is stored */
+ heap = mem_heap_create(1024);
/* Based on split direction, decide upper and lower pages */
if (direction == FSP_DOWN) {
@@ -1426,7 +1480,12 @@ btr_attach_half_pages(
/* Replace the address of the old child node (= page) with the
address of the new lower half */
- btr_node_ptr_set_child_page_no(node_ptr, lower_page_no, mtr);
+ btr_node_ptr_set_child_page_no(node_ptr,
+ rec_get_offsets(node_ptr,
+ UT_LIST_GET_FIRST(tree->tree_indexes),
+ NULL, ULINT_UNDEFINED, &heap),
+ lower_page_no, mtr);
+ mem_heap_empty(heap);
} else {
lower_page_no = buf_frame_get_page_no(page);
upper_page_no = buf_frame_get_page_no(new_page);
@@ -1434,9 +1493,6 @@ btr_attach_half_pages(
upper_page = new_page;
}
- /* Create a memory heap where the data tuple is stored */
- heap = mem_heap_create(100);
-
/* Get the level of the split pages */
level = btr_page_get_level(page, mtr);
@@ -1465,6 +1521,7 @@ btr_attach_half_pages(
if (prev_page_no != FIL_NULL) {
prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(prev_page) == page_is_comp(page));
btr_page_set_next(prev_page, lower_page_no, mtr);
}
@@ -1472,6 +1529,7 @@ btr_attach_half_pages(
if (next_page_no != FIL_NULL) {
next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
btr_page_set_prev(next_page, upper_page_no, mtr);
}
@@ -1522,7 +1580,15 @@ btr_page_split_and_insert(
ibool insert_will_fit;
ulint n_iterations = 0;
rec_t* rec;
+ mem_heap_t* heap;
+ ulint n_uniq;
+ ulint* offsets;
+
+ heap = mem_heap_create(1024);
+ n_uniq = dict_index_get_n_unique_in_tree(cursor->index);
func_start:
+ mem_heap_empty(heap);
+ offsets = NULL;
tree = btr_cur_get_tree(cursor);
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
@@ -1574,9 +1640,10 @@ func_start:
first_rec = split_rec;
move_limit = split_rec;
} else {
- buf = mem_alloc(rec_get_converted_size(tuple));
+ buf = mem_alloc(rec_get_converted_size(cursor->index, tuple));
- first_rec = rec_convert_dtuple_to_rec(buf, tuple);
+ first_rec = rec_convert_dtuple_to_rec(buf,
+ cursor->index, tuple);
move_limit = page_rec_get_next(btr_cur_get_rec(cursor));
}
@@ -1593,7 +1660,16 @@ func_start:
We can then move the records after releasing the tree latch,
thus reducing the tree latch contention. */
- insert_will_fit = btr_page_insert_fits(cursor, split_rec, tuple);
+ if (split_rec) {
+ offsets = rec_get_offsets(split_rec, cursor->index, offsets,
+ n_uniq, &heap);
+
+ insert_will_fit = btr_page_insert_fits(cursor,
+ split_rec, offsets, tuple, heap);
+ } else {
+ insert_will_fit = btr_page_insert_fits(cursor,
+ NULL, NULL, tuple, heap);
+ }
if (insert_will_fit && (btr_page_get_level(page, mtr) == 0)) {
@@ -1605,7 +1681,8 @@ func_start:
if (direction == FSP_DOWN) {
/* fputs("Split left\n", stderr); */
- page_move_rec_list_start(new_page, page, move_limit, mtr);
+ page_move_rec_list_start(new_page, page, move_limit,
+ cursor->index, mtr);
left_page = new_page;
right_page = page;
@@ -1613,7 +1690,8 @@ func_start:
} else {
/* fputs("Split right\n", stderr); */
- page_move_rec_list_end(new_page, page, move_limit, mtr);
+ page_move_rec_list_end(new_page, page, move_limit,
+ cursor->index, mtr);
left_page = page;
right_page = new_page;
@@ -1626,19 +1704,25 @@ func_start:
if (split_rec == NULL) {
insert_page = right_page;
- } else if (cmp_dtuple_rec(tuple, first_rec) >= 0) {
-
- insert_page = right_page;
} else {
- insert_page = left_page;
+ offsets = rec_get_offsets(first_rec, cursor->index,
+ offsets, n_uniq, &heap);
+
+ if (cmp_dtuple_rec(tuple, first_rec, offsets) >= 0) {
+
+ insert_page = right_page;
+ } else {
+ insert_page = left_page;
+ }
}
/* 7. Reposition the cursor for insert and try insertion */
page_cursor = btr_cur_get_page_cur(cursor);
- page_cur_search(insert_page, tuple, PAGE_CUR_LE, page_cursor);
+ page_cur_search(insert_page, cursor->index, tuple,
+ PAGE_CUR_LE, page_cursor);
- rec = page_cur_tuple_insert(page_cursor, tuple, mtr);
+ rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr);
if (rec != NULL) {
/* Insert fit on the page: update the free bits for the
@@ -1650,15 +1734,17 @@ func_start:
/* fprintf(stderr, "Split and insert done %lu %lu\n",
buf_frame_get_page_no(left_page),
buf_frame_get_page_no(right_page)); */
+ mem_heap_free(heap);
return(rec);
}
/* 8. If insert did not fit, try page reorganization */
- btr_page_reorganize(insert_page, mtr);
+ btr_page_reorganize(insert_page, cursor->index, mtr);
- page_cur_search(insert_page, tuple, PAGE_CUR_LE, page_cursor);
- rec = page_cur_tuple_insert(page_cursor, tuple, mtr);
+ page_cur_search(insert_page, cursor->index, tuple,
+ PAGE_CUR_LE, page_cursor);
+ rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr);
if (rec == NULL) {
/* The insert did not fit on the page: loop back to the
@@ -1688,6 +1774,7 @@ func_start:
ut_ad(page_validate(left_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
ut_ad(page_validate(right_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
+ mem_heap_free(heap);
return(rec);
}
@@ -1721,6 +1808,7 @@ btr_level_list_remove(
if (prev_page_no != FIL_NULL) {
prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(prev_page) == page_is_comp(page));
btr_page_set_next(prev_page, next_page_no, mtr);
}
@@ -1728,6 +1816,7 @@ btr_level_list_remove(
if (next_page_no != FIL_NULL) {
next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
btr_page_set_prev(next_page, prev_page_no, mtr);
}
@@ -1741,12 +1830,15 @@ void
btr_set_min_rec_mark_log(
/*=====================*/
rec_t* rec, /* in: record */
+ ulint comp, /* nonzero=compact record format */
mtr_t* mtr) /* in: mtr */
{
- mlog_write_initial_log_record(rec, MLOG_REC_MIN_MARK, mtr);
+ mlog_write_initial_log_record(rec,
+ comp ? MLOG_COMP_REC_MIN_MARK : MLOG_REC_MIN_MARK, mtr);
/* Write rec offset as a 2-byte ulint */
- mlog_catenate_ulint(mtr, rec - buf_frame_align(rec), MLOG_2BYTES);
+ mlog_catenate_ulint(mtr, ut_align_offset(rec, UNIV_PAGE_SIZE),
+ MLOG_2BYTES);
}
/********************************************************************
@@ -1759,6 +1851,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
+ ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -1770,9 +1863,11 @@ btr_parse_set_min_rec_mark(
}
if (page) {
+ ut_a(!page_is_comp(page) == !comp);
+
rec = page + mach_read_from_2(ptr);
- btr_set_min_rec_mark(rec, mtr);
+ btr_set_min_rec_mark(rec, comp, mtr);
}
return(ptr + 2);
@@ -1785,15 +1880,16 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
+ ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr) /* in: mtr */
{
ulint info_bits;
- info_bits = rec_get_info_bits(rec);
+ info_bits = rec_get_info_bits(rec, comp);
- rec_set_info_bits(rec, info_bits | REC_INFO_MIN_REC_FLAG);
+ rec_set_info_bits(rec, comp, info_bits | REC_INFO_MIN_REC_FLAG);
- btr_set_min_rec_mark_log(rec, mtr);
+ btr_set_min_rec_mark_log(rec, comp, mtr);
}
/*****************************************************************
@@ -1842,18 +1938,19 @@ btr_lift_page_up(
record from the page should be removed */
mtr_t* mtr) /* in: mtr */
{
- rec_t* node_ptr;
- page_t* father_page;
- ulint page_level;
-
+ page_t* father_page;
+ ulint page_level;
+ dict_index_t* index;
+
ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL);
ut_ad(btr_page_get_next(page, mtr) == FIL_NULL);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
- node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
- father_page = buf_frame_align(node_ptr);
+ father_page = buf_frame_align(
+ btr_page_get_father_node_ptr(tree, page, mtr));
page_level = btr_page_get_level(page, mtr);
+ index = UT_LIST_GET_FIRST(tree->tree_indexes);
btr_search_drop_page_hash_index(page);
@@ -1862,7 +1959,7 @@ btr_lift_page_up(
/* Move records to the father */
page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page),
- mtr);
+ index, mtr);
lock_update_copy_and_discard(father_page, page);
btr_page_set_level(father_page, page_level, mtr);
@@ -1871,10 +1968,8 @@ btr_lift_page_up(
btr_page_free(tree, page, mtr);
/* We play safe and reset the free bits for the father */
- ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
- father_page);
- ut_ad(page_validate(father_page,
- UT_LIST_GET_FIRST(tree->tree_indexes)));
+ ibuf_reset_free_bits(index, father_page);
+ ut_ad(page_validate(father_page, index));
ut_ad(btr_check_node_ptr(tree, father_page, mtr));
}
@@ -1914,9 +2009,12 @@ btr_compress(
ulint max_ins_size;
ulint max_ins_size_reorg;
ulint level;
-
+ ulint comp;
+
page = btr_cur_get_page(cursor);
tree = btr_cur_get_tree(cursor);
+ comp = page_is_comp(page);
+ ut_a((ibool)!!comp == cursor->index->table->comp);
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
@@ -1932,7 +2030,9 @@ btr_compress(
right_page_no); */
node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
+ ut_ad(!comp || rec_get_status(node_ptr) == REC_STATUS_NODE_PTR);
father_page = buf_frame_align(node_ptr);
+ ut_a(comp == page_is_comp(father_page));
/* Decide the page to which we try to merge and which will inherit
the locks */
@@ -1957,6 +2057,7 @@ btr_compress(
n_recs = page_get_n_recs(page);
data_size = page_get_data_size(page);
+ ut_a(page_is_comp(merge_page) == comp);
max_ins_size_reorg = page_get_max_insert_size_after_reorganize(
merge_page, n_recs);
@@ -1975,7 +2076,7 @@ btr_compress(
/* We have to reorganize merge_page */
- btr_page_reorganize(merge_page, mtr);
+ btr_page_reorganize(merge_page, cursor->index, mtr);
max_ins_size = page_get_max_insert_size(merge_page, n_recs);
@@ -1999,11 +2100,19 @@ btr_compress(
if (is_left) {
btr_node_ptr_delete(tree, page, mtr);
} else {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
/* Replace the address of the old child node (= page) with the
address of the merge page to the right */
- btr_node_ptr_set_child_page_no(node_ptr, right_page_no, mtr);
-
+ btr_node_ptr_set_child_page_no(node_ptr,
+ rec_get_offsets(node_ptr, cursor->index,
+ offsets_, ULINT_UNDEFINED, &heap),
+ right_page_no, mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
btr_node_ptr_delete(tree, merge_page, mtr);
}
@@ -2012,14 +2121,14 @@ btr_compress(
orig_pred = page_rec_get_prev(
page_get_supremum_rec(merge_page));
page_copy_rec_list_start(merge_page, page,
- page_get_supremum_rec(page), mtr);
+ page_get_supremum_rec(page), cursor->index, mtr);
lock_update_merge_left(merge_page, orig_pred, page);
} else {
orig_succ = page_rec_get_next(
page_get_infimum_rec(merge_page));
page_copy_rec_list_end(merge_page, page,
- page_get_infimum_rec(page), mtr);
+ page_get_infimum_rec(page), cursor->index, mtr);
lock_update_merge_right(orig_succ, page);
}
@@ -2133,6 +2242,7 @@ btr_discard_page(
return;
}
+ ut_a(page_is_comp(merge_page) == page_is_comp(page));
btr_search_drop_page_hash_index(page);
if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) {
@@ -2142,9 +2252,9 @@ btr_discard_page(
node_ptr = page_rec_get_next(page_get_infimum_rec(merge_page));
- ut_ad(node_ptr != page_get_supremum_rec(merge_page));
+ ut_ad(page_rec_is_user_rec(node_ptr));
- btr_set_min_rec_mark(node_ptr, mtr);
+ btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr);
}
btr_node_ptr_delete(tree, page, mtr);
@@ -2165,6 +2275,7 @@ btr_discard_page(
ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
}
+#ifdef UNIV_BTR_PRINT
/*****************************************************************
Prints size info of a B-tree. */
@@ -2215,6 +2326,8 @@ btr_print_recursive(
page_t* page, /* in: index page */
ulint width, /* in: print this many entries from start
and end */
+ mem_heap_t** heap, /* in/out: heap for rec_get_offsets() */
+ ulint** offsets,/* in/out: buffer for rec_get_offsets() */
mtr_t* mtr) /* in: mtr */
{
page_cur_t cursor;
@@ -2223,14 +2336,16 @@ btr_print_recursive(
mtr_t mtr2;
rec_t* node_ptr;
page_t* child;
-
+ dict_index_t* index;
+
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
fprintf(stderr, "NODE ON LEVEL %lu page number %lu\n",
(ulong) btr_page_get_level(page, mtr),
(ulong) buf_frame_get_page_no(page));
- page_print(page, width, width);
+ index = UT_LIST_GET_FIRST(tree->tree_indexes);
+ page_print(page, index, width, width);
n_recs = page_get_n_recs(page);
@@ -2249,9 +2364,12 @@ btr_print_recursive(
node_ptr = page_cur_get_rec(&cursor);
- child = btr_node_ptr_get_child(node_ptr, &mtr2);
-
- btr_print_recursive(tree, child, width, &mtr2);
+ *offsets = rec_get_offsets(node_ptr, index, *offsets,
+ ULINT_UNDEFINED, heap);
+ child = btr_node_ptr_get_child(node_ptr,
+ *offsets, &mtr2);
+ btr_print_recursive(tree, child, width,
+ heap, offsets, &mtr2);
mtr_commit(&mtr2);
}
@@ -2270,8 +2388,12 @@ btr_print_tree(
ulint width) /* in: print this many entries from start
and end */
{
- mtr_t mtr;
- page_t* root;
+ mtr_t mtr;
+ page_t* root;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
fputs("--------------------------\n"
"INDEX TREE PRINT\n", stderr);
@@ -2280,12 +2402,16 @@ btr_print_tree(
root = btr_root_get(tree, &mtr);
- btr_print_recursive(tree, root, width, &mtr);
+ btr_print_recursive(tree, root, width, &heap, &offsets, &mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
mtr_commit(&mtr);
- btr_validate_tree(tree);
+ btr_validate_tree(tree, NULL);
}
+#endif /* UNIV_BTR_PRINT */
/****************************************************************
Checks that the node pointer to a page is appropriate. */
@@ -2323,7 +2449,10 @@ btr_check_node_ptr(
page_rec_get_next(page_get_infimum_rec(page)),
0, heap, btr_page_get_level(page, mtr));
- ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr) == 0);
+ ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr,
+ rec_get_offsets(node_ptr,
+ dict_tree_find_index(tree, node_ptr),
+ NULL, ULINT_UNDEFINED, &heap)) == 0);
mem_heap_free(heap);
@@ -2360,14 +2489,18 @@ btr_index_rec_validate(
should print hex dump of record
and page on error */
{
- ulint len;
- ulint n;
- ulint i;
- page_t* page;
+ ulint len;
+ ulint n;
+ ulint i;
+ page_t* page;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
page = buf_frame_align(rec);
-
- if (index->type & DICT_UNIVERSAL) {
+
+ if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
/* The insert buffer index tree can contain records from any
other index: we cannot check the number of fields or
their length */
@@ -2375,38 +2508,46 @@ btr_index_rec_validate(
return(TRUE);
}
+ if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) != index->table->comp)) {
+ btr_index_rec_validate_report(page, rec, index);
+ fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n",
+ (ulong) !!page_is_comp(page),
+ (ulong) index->table->comp);
+ return(FALSE);
+ }
+
n = dict_index_get_n_fields(index);
- if (rec_get_n_fields(rec) != n) {
+ if (!page_is_comp(page)
+ && UNIV_UNLIKELY(rec_get_n_fields_old(rec) != n)) {
btr_index_rec_validate_report(page, rec, index);
fprintf(stderr, "InnoDB: has %lu fields, should have %lu\n",
- (ulong) rec_get_n_fields(rec), (ulong) n);
+ (ulong) rec_get_n_fields_old(rec), (ulong) n);
- if (!dump_on_error) {
+ if (dump_on_error) {
+ buf_page_print(page);
- return(FALSE);
+ fputs("InnoDB: corrupt record ", stderr);
+ rec_print_old(stderr, rec);
+ putc('\n', stderr);
}
-
- buf_page_print(page);
-
- fputs("InnoDB: corrupt record ", stderr);
- rec_print(stderr, rec);
- putc('\n', stderr);
-
return(FALSE);
}
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+
for (i = 0; i < n; i++) {
dtype_t* type = dict_index_get_nth_type(index, i);
+ ulint fixed_size = dtype_get_fixed_size(type);
- rec_get_nth_field(rec, i, &len);
+ rec_get_nth_field(rec, offsets, i, &len);
/* Note that prefix indexes are not fixed size even when
their type is CHAR. */
if ((dict_index_get_nth_field(index, i)->prefix_len == 0
- && len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
- && len != dtype_get_fixed_size(type))
+ && len != UNIV_SQL_NULL && fixed_size
+ && len != fixed_size)
||
(dict_index_get_nth_field(index, i)->prefix_len > 0
&& len != UNIV_SQL_NULL
@@ -2418,21 +2559,23 @@ btr_index_rec_validate(
"InnoDB: field %lu len is %lu, should be %lu\n",
(ulong) i, (ulong) len, (ulong) dtype_get_fixed_size(type));
- if (!dump_on_error) {
-
- return(FALSE);
- }
-
- buf_page_print(page);
-
- fputs("InnoDB: corrupt record ", stderr);
- rec_print(stderr, rec);
- putc('\n', stderr);
+ if (dump_on_error) {
+ buf_page_print(page);
+ fputs("InnoDB: corrupt record ", stderr);
+ rec_print_new(stderr, rec, offsets);
+ putc('\n', stderr);
+ }
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(FALSE);
}
}
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(TRUE);
}
@@ -2518,6 +2661,7 @@ btr_validate_level(
/*===============*/
/* out: TRUE if ok */
dict_tree_t* tree, /* in: index tree */
+ trx_t* trx, /* in: transaction or NULL */
ulint level) /* in: level number */
{
ulint space;
@@ -2527,15 +2671,18 @@ btr_validate_level(
page_t* right_father_page;
rec_t* node_ptr;
rec_t* right_node_ptr;
+ rec_t* rec;
ulint right_page_no;
ulint left_page_no;
page_cur_t cursor;
- mem_heap_t* heap;
dtuple_t* node_ptr_tuple;
ibool ret = TRUE;
dict_index_t* index;
mtr_t mtr;
-
+ mem_heap_t* heap = mem_heap_create(256);
+ ulint* offsets = NULL;
+ ulint* offsets2= NULL;
+
mtr_start(&mtr);
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
@@ -2544,6 +2691,8 @@ btr_validate_level(
space = buf_frame_get_space_id(page);
+ index = UT_LIST_GET_FIRST(tree->tree_indexes);
+
while (level != btr_page_get_level(page, &mtr)) {
ut_a(btr_page_get_level(page, &mtr) > 0);
@@ -2552,14 +2701,21 @@ btr_validate_level(
page_cur_move_to_next(&cursor);
node_ptr = page_cur_get_rec(&cursor);
- page = btr_node_ptr_get_child(node_ptr, &mtr);
+ offsets = rec_get_offsets(node_ptr, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ page = btr_node_ptr_get_child(node_ptr, offsets, &mtr);
}
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
-
/* Now we are on the desired level. Loop through the pages on that
level. */
loop:
+ if (trx_is_interrupted(trx)) {
+ mtr_commit(&mtr);
+ mem_heap_free(heap);
+ return(ret);
+ }
+ mem_heap_empty(heap);
+ offsets = offsets2 = NULL;
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
/* Check ordering etc. of records */
@@ -2588,12 +2744,19 @@ loop:
(buf_frame_get_page_no(page) == dict_tree_get_page(tree))));
if (right_page_no != FIL_NULL) {
-
+ rec_t* right_rec;
right_page = btr_page_get(space, right_page_no, RW_X_LATCH,
&mtr);
- if (cmp_rec_rec(page_rec_get_prev(page_get_supremum_rec(page)),
- page_rec_get_next(page_get_infimum_rec(right_page)),
- UT_LIST_GET_FIRST(tree->tree_indexes)) >= 0) {
+ ut_a(page_is_comp(right_page) == page_is_comp(page));
+ rec = page_rec_get_prev(page_get_supremum_rec(page));
+ right_rec = page_rec_get_next(
+ page_get_infimum_rec(right_page));
+ offsets = rec_get_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, &heap);
+ offsets2 = rec_get_offsets(right_rec, index,
+ offsets2, ULINT_UNDEFINED, &heap);
+ if (cmp_rec_rec(rec, right_rec, offsets, offsets2, index)
+ >= 0) {
btr_validate_report2(index, level, page, right_page);
@@ -2604,12 +2767,13 @@ loop:
buf_page_print(right_page);
fputs("InnoDB: record ", stderr);
- rec_print(stderr, page_rec_get_prev(
- page_get_supremum_rec(page)));
+ rec = page_rec_get_prev(page_get_supremum_rec(page));
+ rec_print(stderr, rec, index);
putc('\n', stderr);
fputs("InnoDB: record ", stderr);
- rec_print(stderr, page_rec_get_next(
- page_get_infimum_rec(right_page)));
+ rec = page_rec_get_next(page_get_infimum_rec(
+ right_page));
+ rec_print(stderr, rec, index);
putc('\n', stderr);
ret = FALSE;
@@ -2618,7 +2782,8 @@ loop:
if (level > 0 && left_page_no == FIL_NULL) {
ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
- page_rec_get_next(page_get_infimum_rec(page))));
+ page_rec_get_next(page_get_infimum_rec(page)),
+ page_is_comp(page)));
}
if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) {
@@ -2627,12 +2792,14 @@ loop:
node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr);
father_page = buf_frame_align(node_ptr);
+ offsets = rec_get_offsets(node_ptr, index,
+ offsets, ULINT_UNDEFINED, &heap);
- if (btr_node_ptr_get_child_page_no(node_ptr) !=
+ if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
buf_frame_get_page_no(page)
|| node_ptr != btr_page_get_father_for_rec(tree, page,
- page_rec_get_prev(page_get_supremum_rec(page)),
- &mtr)) {
+ page_rec_get_prev(page_get_supremum_rec(page)),
+ &mtr)) {
btr_validate_report1(index, level, page);
fputs("InnoDB: node pointer to the page is wrong\n",
@@ -2642,17 +2809,18 @@ loop:
buf_page_print(page);
fputs("InnoDB: node ptr ", stderr);
- rec_print(stderr, node_ptr);
+ rec_print_new(stderr, node_ptr, offsets);
fprintf(stderr, "\n"
"InnoDB: node ptr child page n:o %lu\n",
- (unsigned long) btr_node_ptr_get_child_page_no(node_ptr));
+ (unsigned long) btr_node_ptr_get_child_page_no(
+ node_ptr, offsets));
fputs("InnoDB: record on page ", stderr);
- rec_print(stderr,
- btr_page_get_father_for_rec(tree, page,
- page_rec_get_prev(page_get_supremum_rec(page)),
- &mtr));
+ rec = btr_page_get_father_for_rec(tree, page,
+ page_rec_get_prev(page_get_supremum_rec(page)),
+ &mtr);
+ rec_print(stderr, rec, index);
putc('\n', stderr);
ret = FALSE;
@@ -2660,7 +2828,8 @@ loop:
}
if (btr_page_get_level(page, &mtr) > 0) {
- heap = mem_heap_create(256);
+ offsets = rec_get_offsets(node_ptr, index,
+ offsets, ULINT_UNDEFINED, &heap);
node_ptr_tuple = dict_tree_build_node_ptr(
tree,
@@ -2669,7 +2838,10 @@ loop:
0, heap,
btr_page_get_level(page, &mtr));
- if (cmp_dtuple_rec(node_ptr_tuple, node_ptr) != 0) {
+ if (cmp_dtuple_rec(node_ptr_tuple, node_ptr,
+ offsets)) {
+ rec_t* first_rec = page_rec_get_next(
+ page_get_infimum_rec(page));
btr_validate_report1(index, level, page);
@@ -2679,18 +2851,14 @@ loop:
fputs("InnoDB: Error: node ptrs differ"
" on levels > 0\n"
"InnoDB: node ptr ", stderr);
- rec_print(stderr, node_ptr);
+ rec_print_new(stderr, node_ptr, offsets);
fputs("InnoDB: first rec ", stderr);
- rec_print(stderr, page_rec_get_next(
- page_get_infimum_rec(page)));
+ rec_print(stderr, first_rec, index);
putc('\n', stderr);
ret = FALSE;
- mem_heap_free(heap);
goto node_ptr_fails;
}
-
- mem_heap_free(heap);
}
if (left_page_no == FIL_NULL) {
@@ -2701,7 +2869,7 @@ loop:
if (right_page_no == FIL_NULL) {
ut_a(node_ptr == page_rec_get_prev(
- page_get_supremum_rec(father_page)));
+ page_get_supremum_rec(father_page)));
ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL);
}
@@ -2771,13 +2939,16 @@ node_ptr_fails:
mtr_commit(&mtr);
if (right_page_no != FIL_NULL) {
+ ulint comp = page_is_comp(page);
mtr_start(&mtr);
page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
+ ut_a(page_is_comp(page) == comp);
goto loop;
}
+ mem_heap_free(heap);
return(ret);
}
@@ -2788,7 +2959,8 @@ ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
- dict_tree_t* tree) /* in: tree */
+ dict_tree_t* tree, /* in: tree */
+ trx_t* trx) /* in: transaction or NULL */
{
mtr_t mtr;
page_t* root;
@@ -2801,9 +2973,8 @@ btr_validate_tree(
root = btr_root_get(tree, &mtr);
n = btr_page_get_level(root, &mtr);
- for (i = 0; i <= n; i++) {
-
- if (!btr_validate_level(tree, n - i)) {
+ for (i = 0; i <= n && !trx_is_interrupted(trx); i++) {
+ if (!btr_validate_level(tree, trx, n - i)) {
mtr_commit(&mtr);
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 48de5644908..f81cce5b8e9 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -36,11 +36,11 @@ Created 10/16/1994 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "lock0lock.h"
+#ifdef UNIV_DEBUG
/* If the following is set to TRUE, this module prints a lot of
trace information of individual record operations */
ibool btr_cur_print_record_ops = FALSE;
-
-ulint btr_cur_rnd = 0;
+#endif /* UNIV_DEBUG */
ulint btr_cur_n_non_sea = 0;
ulint btr_cur_n_sea = 0;
@@ -73,8 +73,9 @@ static
void
btr_cur_unmark_extern_fields(
/*=========================*/
- rec_t* rec, /* in: record in a clustered index */
- mtr_t* mtr); /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ mtr_t* mtr, /* in: mtr */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/***********************************************************************
Adds path information to the cursor for the current page, for which
the binary search has been performed. */
@@ -96,6 +97,7 @@ btr_rec_free_updated_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree MUST be
X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update, /* in: update vector */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
@@ -108,9 +110,10 @@ static
ulint
btr_rec_get_externally_stored_len(
/*==============================*/
- /* out: externally stored part, in units of a
- database page */
- rec_t* rec); /* in: record */
+ /* out: externally stored part,
+ in units of a database page */
+ rec_t* rec, /* in: record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*==================== B-TREE SEARCH =========================*/
@@ -137,11 +140,13 @@ btr_cur_latch_leaves(
if (latch_mode == BTR_SEARCH_LEAF) {
get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_LEAF) {
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_TREE) {
@@ -152,11 +157,13 @@ btr_cur_latch_leaves(
if (left_page_no != FIL_NULL) {
get_page = btr_page_get(space, left_page_no,
RW_X_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush =
TRUE;
}
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
right_page_no = btr_page_get_next(page, mtr);
@@ -176,11 +183,14 @@ btr_cur_latch_leaves(
if (left_page_no != FIL_NULL) {
cursor->left_page = btr_page_get(space, left_page_no,
RW_S_LATCH, mtr);
+ ut_a(page_is_comp(cursor->left_page) ==
+ page_is_comp(page));
buf_block_align(
cursor->left_page)->check_index_page_at_flush = TRUE;
}
get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_PREV) {
@@ -191,11 +201,14 @@ btr_cur_latch_leaves(
if (left_page_no != FIL_NULL) {
cursor->left_page = btr_page_get(space, left_page_no,
RW_X_LATCH, mtr);
+ ut_a(page_is_comp(cursor->left_page) ==
+ page_is_comp(page));
buf_block_align(
cursor->left_page)->check_index_page_at_flush = TRUE;
}
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else {
ut_error;
@@ -261,6 +274,10 @@ btr_cur_search_to_nth_level(
#ifdef BTR_CUR_ADAPT
btr_search_t* info;
#endif
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
/* Currently, PAGE_CUR_LE is the only search mode used for searches
ending to upper levels */
@@ -299,7 +316,9 @@ btr_cur_search_to_nth_level(
if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED
&& latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ
&& !estimate
+#ifdef PAGE_CUR_LE_OR_EXTENDS
&& mode != PAGE_CUR_LE_OR_EXTENDS
+#endif /* PAGE_CUR_LE_OR_EXTENDS */
&& srv_use_adaptive_hash_indexes
&& btr_search_guess_on_hash(index, info, tuple, mode,
latch_mode, cursor,
@@ -373,13 +392,16 @@ btr_cur_search_to_nth_level(
page_mode = PAGE_CUR_LE;
break;
default:
- ut_ad(mode == PAGE_CUR_L
- || mode == PAGE_CUR_LE
+#ifdef PAGE_CUR_LE_OR_EXTENDS
+ ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE
|| mode == PAGE_CUR_LE_OR_EXTENDS);
+#else /* PAGE_CUR_LE_OR_EXTENDS */
+ ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE);
+#endif /* PAGE_CUR_LE_OR_EXTENDS */
page_mode = mode;
break;
}
-
+
/* Loop and search until we arrive at the desired level */
for (;;) {
@@ -414,7 +436,9 @@ retry_page_get:
cursor->thr)) {
/* Insertion to the insert buffer succeeded */
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
-
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return;
}
@@ -470,9 +494,9 @@ retry_page_get:
page_mode = mode;
}
- page_cur_search_with_match(page, tuple, page_mode, &up_match,
- &up_bytes, &low_match, &low_bytes,
- page_cursor);
+ page_cur_search_with_match(page, index, tuple, page_mode,
+ &up_match, &up_bytes,
+ &low_match, &low_bytes, page_cursor);
if (estimate) {
btr_cur_add_path_info(cursor, height, root_height);
}
@@ -486,7 +510,10 @@ retry_page_get:
if (level > 0) {
/* x-latch the page */
- btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ page = btr_page_get(space,
+ page_no, RW_X_LATCH, mtr);
+ ut_a((ibool)!!page_is_comp(page)
+ == index->table->comp);
}
break;
@@ -498,9 +525,14 @@ retry_page_get:
guess = NULL;
node_ptr = page_cur_get_rec(page_cursor);
-
+ offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
+ ULINT_UNDEFINED, &heap);
/* Go to the child node */
- page_no = btr_node_ptr_get_child_page_no(node_ptr);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
+ }
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
if (level == 0) {
@@ -552,6 +584,10 @@ btr_cur_open_at_index_side(
rec_t* node_ptr;
ulint estimate;
ulint savepoint;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
estimate = latch_mode & BTR_ESTIMATE;
latch_mode = latch_mode & ~BTR_ESTIMATE;
@@ -576,7 +612,7 @@ btr_cur_open_at_index_side(
page_no = dict_tree_get_page(tree);
height = ULINT_UNDEFINED;
-
+
for (;;) {
page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL,
BUF_GET,
@@ -645,9 +681,14 @@ btr_cur_open_at_index_side(
height--;
node_ptr = page_cur_get_rec(page_cursor);
-
+ offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
+ ULINT_UNDEFINED, &heap);
/* Go to the child node */
- page_no = btr_node_ptr_get_child_page_no(node_ptr);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
+ }
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
}
@@ -669,6 +710,10 @@ btr_cur_open_at_rnd_pos(
ulint space;
ulint height;
rec_t* node_ptr;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
tree = index->tree;
@@ -717,9 +762,14 @@ btr_cur_open_at_rnd_pos(
height--;
node_ptr = page_cur_get_rec(page_cursor);
-
+ offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
+ ULINT_UNDEFINED, &heap);
/* Go to the child node */
- page_no = btr_node_ptr_get_child_page_no(node_ptr);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
+ }
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
}
@@ -758,18 +808,20 @@ btr_cur_insert_if_possible(
page_cursor = btr_cur_get_page_cur(cursor);
/* Now, try the insert */
- rec = page_cur_tuple_insert(page_cursor, tuple, mtr);
+ rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr);
if (!rec) {
/* If record did not fit, reorganize */
- btr_page_reorganize(page, mtr);
+ btr_page_reorganize(page, cursor->index, mtr);
*reorg = TRUE;
- page_cur_search(page, tuple, PAGE_CUR_LE, page_cursor);
+ page_cur_search(page, cursor->index, tuple,
+ PAGE_CUR_LE, page_cursor);
- rec = page_cur_tuple_insert(page_cursor, tuple, mtr);
+ rec = page_cur_tuple_insert(page_cursor, tuple,
+ cursor->index, mtr);
}
return(rec);
@@ -833,6 +885,7 @@ btr_cur_ins_lock_and_undo(
return(DB_SUCCESS);
}
+#ifdef UNIV_DEBUG
/*****************************************************************
Report information about a transaction. */
static
@@ -850,6 +903,7 @@ btr_cur_trx_report(
dict_index_name_print(stderr, trx, index);
putc('\n', stderr);
}
+#endif /* UNIV_DEBUG */
/*****************************************************************
Tries to perform an insert to a page in an index tree, next to cursor.
@@ -887,8 +941,6 @@ btr_cur_optimistic_insert(
ibool reorg;
ibool inherit;
ulint rec_size;
- ulint data_size;
- ulint extra_size;
ulint type;
ulint err;
@@ -901,12 +953,13 @@ btr_cur_optimistic_insert(
fputs("InnoDB: Error in a tuple to insert into ", stderr);
dict_index_name_print(stderr, thr_get_trx(thr), index);
}
-
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "insert into ");
dtuple_print(stderr, entry);
}
-
+#endif /* UNIV_DEBUG */
+
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
max_size = page_get_max_insert_size_after_reorganize(page, 1);
@@ -914,13 +967,11 @@ btr_cur_optimistic_insert(
calculate_sizes_again:
/* Calculate the record size when entry is converted to a record */
- data_size = dtuple_get_data_size(entry);
- extra_size = rec_get_converted_extra_size(data_size,
- dtuple_get_n_fields(entry));
- rec_size = data_size + extra_size;
+ rec_size = rec_get_converted_size(index, entry);
- if ((rec_size >= page_get_free_space_of_empty() / 2)
- || (rec_size >= REC_MAX_DATA_SIZE)) {
+ if (rec_size >=
+ ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
+ REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields
externally on separate database pages */
@@ -983,21 +1034,21 @@ calculate_sizes_again:
/* Now, try the insert */
- *rec = page_cur_insert_rec_low(page_cursor, entry, data_size,
- NULL, mtr);
- if (!(*rec)) {
+ *rec = page_cur_insert_rec_low(page_cursor, entry, index,
+ NULL, NULL, mtr);
+ if (UNIV_UNLIKELY(!(*rec))) {
/* If the record did not fit, reorganize */
- btr_page_reorganize(page, mtr);
+ btr_page_reorganize(page, index, mtr);
ut_ad(page_get_max_insert_size(page, 1) == max_size);
reorg = TRUE;
- page_cur_search(page, entry, PAGE_CUR_LE, page_cursor);
+ page_cur_search(page, index, entry, PAGE_CUR_LE, page_cursor);
- *rec = page_cur_tuple_insert(page_cursor, entry, mtr);
+ *rec = page_cur_tuple_insert(page_cursor, entry, index, mtr);
- if (!*rec) {
+ if (UNIV_UNLIKELY(!*rec)) {
fputs("InnoDB: Error: cannot insert tuple ", stderr);
dtuple_print(stderr, entry);
fputs(" into ", stderr);
@@ -1123,9 +1174,9 @@ btr_cur_pessimistic_insert(
}
}
- if ((rec_get_converted_size(entry)
- >= page_get_free_space_of_empty() / 2)
- || (rec_get_converted_size(entry) >= REC_MAX_DATA_SIZE)) {
+ if (rec_get_converted_size(index, entry) >=
+ ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
+ REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields
externally on separate database pages */
@@ -1212,8 +1263,16 @@ btr_cur_upd_lock_and_undo(
err = DB_SUCCESS;
if (!(flags & BTR_NO_LOCKING_FLAG)) {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
err = lock_clust_rec_modify_check_and_lock(flags, rec, index,
- thr);
+ rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap), thr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
if (err != DB_SUCCESS) {
return(err);
@@ -1243,14 +1302,19 @@ btr_cur_update_in_place_log(
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
+ page_t* page = ut_align_down(rec, UNIV_PAGE_SIZE);
+ ut_ad(flags < 256);
+ ut_ad(!!page_is_comp(page) == index->table->comp);
- log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
+ log_ptr = mlog_open_and_write_index(mtr, rec, index, page_is_comp(page)
+ ? MLOG_COMP_REC_UPDATE_IN_PLACE
+ : MLOG_REC_UPDATE_IN_PLACE,
+ 1 + DATA_ROLL_PTR_LEN + 14 + 2 + MLOG_BUF_MARGIN);
- log_ptr = mlog_write_initial_log_record_fast(rec,
- MLOG_REC_UPDATE_IN_PLACE, log_ptr, mtr);
-
- mach_write_to_1(log_ptr, flags);
- log_ptr++;
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery */
+ return;
+ }
/* The code below assumes index is a clustered index: change index to
the clustered index if we are updating a secondary index record (or we
@@ -1259,9 +1323,12 @@ btr_cur_update_in_place_log(
index = dict_table_get_first_index(index->table);
+ mach_write_to_1(log_ptr, flags);
+ log_ptr++;
+
log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
mtr);
- mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
row_upd_index_write_log(update, log_ptr, mtr);
@@ -1273,10 +1340,11 @@ Parses a redo log record of updating a record in-place. */
byte*
btr_cur_parse_update_in_place(
/*==========================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page) /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ page_t* page, /* in: page or NULL */
+ dict_index_t* index) /* in: index corresponding to page */
{
ulint flags;
rec_t* rec;
@@ -1286,6 +1354,7 @@ btr_cur_parse_update_in_place(
dulint roll_ptr;
ulint rec_offset;
mem_heap_t* heap;
+ ulint* offsets;
if (end_ptr < ptr + 1) {
@@ -1316,29 +1385,27 @@ btr_cur_parse_update_in_place(
ptr = row_upd_index_parse(ptr, end_ptr, heap, &update);
- if (ptr == NULL) {
- mem_heap_free(heap);
-
- return(NULL);
- }
-
- if (!page) {
- mem_heap_free(heap);
+ if (!ptr || !page) {
- return(ptr);
+ goto func_exit;
}
-
+
+ ut_a((ibool)!!page_is_comp(page) == index->table->comp);
rec = page + rec_offset;
/* We do not need to reserve btr_search_latch, as the page is only
being recovered, and there cannot be a hash index to it. */
+ offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
+
if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields_in_recovery(rec, pos, trx_id, roll_ptr);
+ row_upd_rec_sys_fields_in_recovery(rec, offsets,
+ pos, trx_id, roll_ptr);
}
- row_upd_rec_in_place(rec, update);
+ row_upd_rec_in_place(rec, offsets, update);
+func_exit:
mem_heap_free(heap);
return(ptr);
@@ -1368,26 +1435,38 @@ btr_cur_update_in_place(
rec_t* rec;
dulint roll_ptr = ut_dulint_zero;
trx_t* trx;
- ibool was_delete_marked;
+ ulint was_delete_marked;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
rec = btr_cur_get_rec(cursor);
index = cursor->index;
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
trx = thr_get_trx(thr);
-
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(trx, index, "update ");
- rec_print(stderr, rec);
+ rec_print_new(stderr, rec, offsets);
}
+#endif /* UNIV_DEBUG */
/* Do lock checking and undo logging */
err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info,
thr, &roll_ptr);
- if (err != DB_SUCCESS) {
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(err);
}
block = buf_block_align(rec);
+ ut_ad(!!page_is_comp(buf_block_get_frame(block))
+ == index->table->comp);
if (block->is_hashed) {
/* The function row_upd_changes_ord_field_binary works only
@@ -1405,15 +1484,16 @@ btr_cur_update_in_place(
}
if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields(rec, index, trx, roll_ptr);
+ row_upd_rec_sys_fields(rec, index, offsets, trx, roll_ptr);
}
/* FIXME: in a mixed tree, all records may not have enough ordering
fields for btr search: */
- was_delete_marked = rec_get_deleted_flag(rec);
-
- row_upd_rec_in_place(rec, update);
+ was_delete_marked = rec_get_deleted_flag(rec,
+ page_is_comp(buf_block_get_frame(block)));
+
+ row_upd_rec_in_place(rec, offsets, update);
if (block->is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
@@ -1421,13 +1501,17 @@ btr_cur_update_in_place(
btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr,
mtr);
- if (was_delete_marked && !rec_get_deleted_flag(rec)) {
+ if (was_delete_marked && !rec_get_deleted_flag(rec,
+ page_is_comp(buf_block_get_frame(block)))) {
/* The new updated record owns its possible externally
stored fields */
- btr_cur_unmark_extern_fields(rec, mtr);
+ btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(DB_SUCCESS);
}
@@ -1469,24 +1553,31 @@ btr_cur_optimistic_update(
mem_heap_t* heap;
ibool reorganized = FALSE;
ulint i;
-
+ ulint* offsets;
+
page = btr_cur_get_page(cursor);
rec = btr_cur_get_rec(cursor);
index = cursor->index;
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
+ heap = mem_heap_create(1024);
+ offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
+
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "update ");
- rec_print(stderr, rec);
+ rec_print_new(stderr, rec, offsets);
}
+#endif /* UNIV_DEBUG */
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
- if (!row_upd_changes_field_size_or_external(rec, index, update)) {
+ if (!row_upd_changes_field_size_or_external(index, offsets, update)) {
/* The simplest and the most common case: the update does not
change the size of any field and none of the updated fields is
externally stored in rec or update */
-
+ mem_heap_free(heap);
return(btr_cur_update_in_place(flags, cursor, update,
cmpl_info, thr, mtr));
}
@@ -1497,29 +1588,30 @@ btr_cur_optimistic_update(
/* Externally stored fields are treated in pessimistic
update */
+ mem_heap_free(heap);
return(DB_OVERFLOW);
}
}
- if (rec_contains_externally_stored_field(btr_cur_get_rec(cursor))) {
+ if (rec_offs_any_extern(offsets)) {
/* Externally stored fields are treated in pessimistic
update */
+ mem_heap_free(heap);
return(DB_OVERFLOW);
}
page_cursor = btr_cur_get_page_cur(cursor);
- heap = mem_heap_create(1024);
-
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
NULL);
- old_rec_size = rec_get_size(rec);
- new_rec_size = rec_get_converted_size(new_entry);
+ old_rec_size = rec_offs_size(offsets);
+ new_rec_size = rec_get_converted_size(index, new_entry);
- if (new_rec_size >= page_get_free_space_of_empty() / 2) {
+ if (UNIV_UNLIKELY(new_rec_size >= page_get_free_space_of_empty(
+ page_is_comp(page)) / 2)) {
mem_heap_free(heap);
@@ -1529,8 +1621,9 @@ btr_cur_optimistic_update(
max_size = old_rec_size
+ page_get_max_insert_size_after_reorganize(page, 1);
- if (page_get_data_size(page) - old_rec_size + new_rec_size
- < BTR_CUR_PAGE_COMPRESS_LIMIT) {
+ if (UNIV_UNLIKELY(page_get_data_size(page)
+ - old_rec_size + new_rec_size
+ < BTR_CUR_PAGE_COMPRESS_LIMIT)) {
/* The page would become too empty */
@@ -1566,11 +1659,11 @@ btr_cur_optimistic_update(
explicit locks on rec, before deleting rec (see the comment in
.._pessimistic_update). */
- lock_rec_store_on_page_infimum(rec);
+ lock_rec_store_on_page_infimum(page, rec);
btr_search_update_hash_on_delete(cursor);
- page_cur_delete_rec(page_cursor, mtr);
+ page_cur_delete_rec(page_cursor, index, offsets, mtr);
page_cur_move_to_prev(page_cursor);
@@ -1587,11 +1680,13 @@ btr_cur_optimistic_update(
ut_a(rec); /* <- We calculated above the insert would fit */
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, page_is_comp(page))) {
/* The new inserted record owns its possible externally
stored fields */
- btr_cur_unmark_extern_fields(rec, mtr);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
/* Restore the old explicit lock state on the record */
@@ -1690,6 +1785,7 @@ btr_cur_pessimistic_update(
ulint* ext_vect;
ulint n_ext_vect;
ulint reserve_flag;
+ ulint* offsets = NULL;
*big_rec = NULL;
@@ -1733,7 +1829,7 @@ btr_cur_pessimistic_update(
}
success = fsp_reserve_free_extents(&n_reserved,
- cursor->index->space,
+ index->space,
n_extents, reserve_flag, mtr);
if (!success) {
err = DB_OUT_OF_FILE_SPACE;
@@ -1743,6 +1839,7 @@ btr_cur_pessimistic_update(
}
heap = mem_heap_create(1024);
+ offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
trx = thr_get_trx(thr);
@@ -1767,28 +1864,29 @@ btr_cur_pessimistic_update(
ut_a(big_rec_vec == NULL);
- btr_rec_free_updated_extern_fields(index, rec, update,
- TRUE, mtr);
+ btr_rec_free_updated_extern_fields(index, rec, offsets,
+ update, TRUE, mtr);
}
/* We have to set appropriate extern storage bits in the new
record to be inserted: we have to remember which fields were such */
- ext_vect = mem_heap_alloc(heap, sizeof(ulint) * rec_get_n_fields(rec));
- n_ext_vect = btr_push_update_extern_fields(ext_vect, rec, update);
-
- if ((rec_get_converted_size(new_entry) >=
- page_get_free_space_of_empty() / 2)
- || (rec_get_converted_size(new_entry) >= REC_MAX_DATA_SIZE)) {
+ ext_vect = mem_heap_alloc(heap, sizeof(ulint)
+ * dict_index_get_n_fields(index));
+ ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update);
+
+ if (UNIV_UNLIKELY(rec_get_converted_size(index, new_entry) >=
+ ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
+ REC_MAX_DATA_SIZE))) {
big_rec_vec = dtuple_convert_big_rec(index, new_entry,
ext_vect, n_ext_vect);
if (big_rec_vec == NULL) {
- mem_heap_free(heap);
-
err = DB_TOO_BIG_RECORD;
-
goto return_after_reservations;
}
}
@@ -1804,11 +1902,11 @@ btr_cur_pessimistic_update(
delete the lock structs set on the root page even if the root
page carries just node pointers. */
- lock_rec_store_on_page_infimum(rec);
+ lock_rec_store_on_page_infimum(buf_frame_align(rec), rec);
btr_search_update_hash_on_delete(cursor);
- page_cur_delete_rec(page_cursor, mtr);
+ page_cur_delete_rec(page_cursor, index, offsets, mtr);
page_cur_move_to_prev(page_cursor);
@@ -1817,21 +1915,22 @@ btr_cur_pessimistic_update(
ut_a(rec || optim_err != DB_UNDERFLOW);
if (rec) {
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+
lock_rec_restore_from_page_infimum(rec, page);
- rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
+ rec_set_field_extern_bits(rec, index,
+ ext_vect, n_ext_vect, mtr);
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
/* The new inserted record owns its possible externally
stored fields */
-
- btr_cur_unmark_extern_fields(rec, mtr);
+ btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
btr_cur_compress_if_useful(cursor, mtr);
err = DB_SUCCESS;
- mem_heap_free(heap);
-
goto return_after_reservations;
}
@@ -1856,13 +1955,14 @@ btr_cur_pessimistic_update(
ut_a(err == DB_SUCCESS);
ut_a(dummy_big_rec == NULL);
- rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
+ rec_set_field_extern_bits(rec, index, ext_vect, n_ext_vect, mtr);
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
/* The new inserted record owns its possible externally
stored fields */
- btr_cur_unmark_extern_fields(rec, mtr);
+ btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
lock_rec_restore_from_page_infimum(rec, page);
@@ -1876,13 +1976,11 @@ btr_cur_pessimistic_update(
btr_cur_pess_upd_restore_supremum(rec, mtr);
}
- mem_heap_free(heap);
-
return_after_reservations:
+ mem_heap_free(heap);
if (n_extents > 0) {
- fil_space_release_free_extents(cursor->index->space,
- n_reserved);
+ fil_space_release_free_extents(index->space, n_reserved);
}
*big_rec = big_rec_vec;
@@ -1908,11 +2006,21 @@ btr_cur_del_mark_set_clust_rec_log(
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
+ ut_ad(flags < 256);
+ ut_ad(val <= 1);
- log_ptr = mlog_open(mtr, 30);
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
- log_ptr = mlog_write_initial_log_record_fast(rec,
- MLOG_REC_CLUST_DELETE_MARK, log_ptr, mtr);
+ log_ptr = mlog_open_and_write_index(mtr, rec, index,
+ page_rec_is_comp(rec)
+ ? MLOG_COMP_REC_CLUST_DELETE_MARK
+ : MLOG_REC_CLUST_DELETE_MARK,
+ 1 + 1 + DATA_ROLL_PTR_LEN + 14 + 2);
+
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery */
+ return;
+ }
mach_write_to_1(log_ptr, flags);
log_ptr++;
@@ -1921,7 +2029,7 @@ btr_cur_del_mark_set_clust_rec_log(
log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
mtr);
- mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
mlog_close(mtr, log_ptr);
@@ -1934,19 +2042,22 @@ index record. */
byte*
btr_cur_parse_del_mark_set_clust_rec(
/*=================================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page) /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: index corresponding to page */
+ page_t* page) /* in: page or NULL */
{
ulint flags;
- ibool val;
+ ulint val;
ulint pos;
dulint trx_id;
dulint roll_ptr;
ulint offset;
rec_t* rec;
+ ut_ad(!page || !!page_is_comp(page) == index->table->comp);
+
if (end_ptr < ptr + 2) {
return(NULL);
@@ -1978,15 +2089,24 @@ btr_cur_parse_del_mark_set_clust_rec(
rec = page + offset;
if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields_in_recovery(rec, pos, trx_id,
- roll_ptr);
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ row_upd_rec_sys_fields_in_recovery(rec,
+ rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap),
+ pos, trx_id, roll_ptr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
it. */
- rec_set_deleted_flag(rec, val);
+ rec_set_deleted_flag(rec, page_is_comp(page), val);
}
return(ptr);
@@ -2015,22 +2135,34 @@ btr_cur_del_mark_set_clust_rec(
ulint err;
rec_t* rec;
trx_t* trx;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
rec = btr_cur_get_rec(cursor);
index = cursor->index;
-
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "del mark ");
- rec_print(stderr, rec);
+ rec_print_new(stderr, rec, offsets);
}
+#endif /* UNIV_DEBUG */
ut_ad(index->type & DICT_CLUSTERED);
- ut_ad(rec_get_deleted_flag(rec) == FALSE);
+ ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
- err = lock_clust_rec_modify_check_and_lock(flags, rec, index, thr);
+ err = lock_clust_rec_modify_check_and_lock(flags,
+ rec, index, offsets, thr);
if (err != DB_SUCCESS) {
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(err);
}
@@ -2039,6 +2171,9 @@ btr_cur_del_mark_set_clust_rec(
&roll_ptr);
if (err != DB_SUCCESS) {
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(err);
}
@@ -2048,13 +2183,12 @@ btr_cur_del_mark_set_clust_rec(
rw_lock_x_lock(&btr_search_latch);
}
- rec_set_deleted_flag(rec, val);
+ rec_set_deleted_flag(rec, rec_offs_comp(offsets), val);
trx = thr_get_trx(thr);
if (!(flags & BTR_KEEP_SYS_FLAG)) {
-
- row_upd_rec_sys_fields(rec, index, trx, roll_ptr);
+ row_upd_rec_sys_fields(rec, index, offsets, trx, roll_ptr);
}
if (block->is_hashed) {
@@ -2063,6 +2197,9 @@ btr_cur_del_mark_set_clust_rec(
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(DB_SUCCESS);
}
@@ -2073,21 +2210,27 @@ UNIV_INLINE
void
btr_cur_del_mark_set_sec_rec_log(
/*=============================*/
- rec_t* rec, /* in: record */
- ibool val, /* in: value to set */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
+ ut_ad(val <= 1);
- log_ptr = mlog_open(mtr, 30);
+ log_ptr = mlog_open(mtr, 11 + 1 + 2);
- log_ptr = mlog_write_initial_log_record_fast(rec,
- MLOG_REC_SEC_DELETE_MARK, log_ptr, mtr);
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery:
+ in that case mlog_open returns NULL */
+ return;
+ }
+ log_ptr = mlog_write_initial_log_record_fast(
+ rec, MLOG_REC_SEC_DELETE_MARK, log_ptr, mtr);
mach_write_to_1(log_ptr, val);
log_ptr++;
- mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
mlog_close(mtr, log_ptr);
@@ -2100,12 +2243,12 @@ index record. */
byte*
btr_cur_parse_del_mark_set_sec_rec(
/*===============================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page) /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ page_t* page) /* in: page or NULL */
{
- ibool val;
+ ulint val;
ulint offset;
rec_t* rec;
@@ -2129,7 +2272,7 @@ btr_cur_parse_del_mark_set_sec_rec(
is only being recovered, and there cannot be a hash index to
it. */
- rec_set_deleted_flag(rec, val);
+ rec_set_deleted_flag(rec, page_is_comp(page), val);
}
return(ptr);
@@ -2155,11 +2298,13 @@ btr_cur_del_mark_set_sec_rec(
rec = btr_cur_get_rec(cursor);
+#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), cursor->index,
"del mark ");
- rec_print(stderr, rec);
+ rec_print(stderr, rec, cursor->index);
}
+#endif /* UNIV_DEBUG */
err = lock_sec_rec_modify_check_and_lock(flags, rec, cursor->index,
thr);
@@ -2169,12 +2314,15 @@ btr_cur_del_mark_set_sec_rec(
}
block = buf_block_align(rec);
+ ut_ad(!!page_is_comp(buf_block_get_frame(block))
+ == cursor->index->table->comp);
if (block->is_hashed) {
rw_lock_x_lock(&btr_search_latch);
}
- rec_set_deleted_flag(rec, val);
+ rec_set_deleted_flag(rec, page_is_comp(buf_block_get_frame(block)),
+ val);
if (block->is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
@@ -2192,13 +2340,13 @@ used by the insert buffer insert merge mechanism. */
void
btr_cur_del_unmark_for_ibuf(
/*========================*/
- rec_t* rec, /* in: record to delete unmark */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record to delete unmark */
+ mtr_t* mtr) /* in: mtr */
{
/* We do not need to reserve btr_search_latch, as the page has just
been read to the buffer pool and there cannot be a hash index to it. */
- rec_set_deleted_flag(rec, FALSE);
+ rec_set_deleted_flag(rec, page_is_comp(buf_frame_align(rec)), FALSE);
btr_cur_del_mark_set_sec_rec_log(rec, FALSE, mtr);
}
@@ -2279,8 +2427,14 @@ btr_cur_optimistic_delete(
successor of the deleted record */
mtr_t* mtr) /* in: mtr */
{
- page_t* page;
- ulint max_ins_size;
+ page_t* page;
+ ulint max_ins_size;
+ rec_t* rec;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ ibool no_compress_needed;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_page(cursor)),
MTR_MEMO_PAGE_X_FIX));
@@ -2290,27 +2444,34 @@ btr_cur_optimistic_delete(
ut_ad(btr_page_get_level(page, mtr) == 0);
- if (rec_contains_externally_stored_field(btr_cur_get_rec(cursor))) {
+ rec = btr_cur_get_rec(cursor);
+ offsets = rec_get_offsets(rec, cursor->index, offsets,
+ ULINT_UNDEFINED, &heap);
- return(FALSE);
- }
+ no_compress_needed = !rec_offs_any_extern(offsets)
+ && btr_cur_can_delete_without_compress(
+ cursor, rec_offs_size(offsets), mtr);
- if (btr_cur_can_delete_without_compress(cursor, mtr)) {
+ if (no_compress_needed) {
- lock_update_delete(btr_cur_get_rec(cursor));
+ lock_update_delete(rec);
btr_search_update_hash_on_delete(cursor);
max_ins_size = page_get_max_insert_size_after_reorganize(page,
1);
- page_cur_delete_rec(btr_cur_get_page_cur(cursor), mtr);
+ page_cur_delete_rec(btr_cur_get_page_cur(cursor),
+ cursor->index, offsets, mtr);
ibuf_update_free_bits_low(cursor->index, page, max_ins_size,
mtr);
- return(TRUE);
}
- return(FALSE);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
+ return(no_compress_needed);
}
/*****************************************************************
@@ -2349,7 +2510,9 @@ btr_cur_pessimistic_delete(
ulint n_reserved;
ibool success;
ibool ret = FALSE;
+ ulint level;
mem_heap_t* heap;
+ ulint* offsets;
page = btr_cur_get_page(cursor);
tree = btr_cur_get_tree(cursor);
@@ -2375,11 +2538,24 @@ btr_cur_pessimistic_delete(
}
}
- btr_rec_free_externally_stored_fields(cursor->index,
- btr_cur_get_rec(cursor), in_rollback, mtr);
+ heap = mem_heap_create(1024);
+ rec = btr_cur_get_rec(cursor);
+
+ offsets = rec_get_offsets(rec, cursor->index,
+ NULL, ULINT_UNDEFINED, &heap);
+
+ /* Free externally stored fields if the record is neither
+ a node pointer nor in two-byte format.
+ This avoids an unnecessary loop. */
+ if (page_is_comp(page)
+ ? !rec_get_node_ptr_flag(rec)
+ : !rec_get_1byte_offs_flag(rec)) {
+ btr_rec_free_externally_stored_fields(cursor->index,
+ rec, offsets, in_rollback, mtr);
+ }
- if ((page_get_n_recs(page) < 2)
- && (dict_tree_get_page(btr_cur_get_tree(cursor))
+ if (UNIV_UNLIKELY(page_get_n_recs(page) < 2)
+ && UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor))
!= buf_frame_get_page_no(page))) {
/* If there is only one record, drop the whole page in
@@ -2393,12 +2569,14 @@ btr_cur_pessimistic_delete(
goto return_after_reservations;
}
- rec = btr_cur_get_rec(cursor);
-
lock_update_delete(rec);
+ level = btr_page_get_level(page, mtr);
- if ((btr_page_get_level(page, mtr) > 0)
- && (page_rec_get_next(page_get_infimum_rec(page)) == rec)) {
+ if (level > 0
+ && UNIV_UNLIKELY(rec == page_rec_get_next(
+ page_get_infimum_rec(page)))) {
+
+ rec_t* next_rec = page_rec_get_next(rec);
if (btr_page_get_prev(page, mtr) == FIL_NULL) {
@@ -2406,7 +2584,8 @@ btr_cur_pessimistic_delete(
non-leaf level, we must mark the new leftmost node
pointer as the predefined minimum record */
- btr_set_min_rec_mark(page_rec_get_next(rec), mtr);
+ btr_set_min_rec_mark(next_rec, page_is_comp(page),
+ mtr);
} else {
/* Otherwise, if we delete the leftmost node pointer
on a page, we have to change the father node pointer
@@ -2415,30 +2594,27 @@ btr_cur_pessimistic_delete(
btr_node_ptr_delete(tree, page, mtr);
- heap = mem_heap_create(256);
-
node_ptr = dict_tree_build_node_ptr(
- tree, page_rec_get_next(rec),
+ tree, next_rec,
buf_frame_get_page_no(page),
- heap, btr_page_get_level(page, mtr));
+ heap, level);
btr_insert_on_non_leaf_level(tree,
- btr_page_get_level(page, mtr) + 1,
- node_ptr, mtr);
-
- mem_heap_free(heap);
+ level + 1, node_ptr, mtr);
}
}
btr_search_update_hash_on_delete(cursor);
- page_cur_delete_rec(btr_cur_get_page_cur(cursor), mtr);
+ page_cur_delete_rec(btr_cur_get_page_cur(cursor), cursor->index,
+ offsets, mtr);
ut_ad(btr_check_node_ptr(tree, page, mtr));
*err = DB_SUCCESS;
return_after_reservations:
+ mem_heap_free(heap);
if (ret == FALSE) {
ret = btr_cur_compress_if_useful(cursor, mtr);
@@ -2663,18 +2839,25 @@ btr_estimate_number_of_different_key_vals(
ulint j;
ulint add_on;
mtr_t mtr;
+ mem_heap_t* heap = NULL;
+ ulint offsets_rec_[REC_OFFS_NORMAL_SIZE];
+ ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets_rec = offsets_rec_;
+ ulint* offsets_next_rec= offsets_next_rec_;
+ *offsets_rec_ = (sizeof offsets_rec_) / sizeof *offsets_rec_;
+ *offsets_next_rec_ =
+ (sizeof offsets_next_rec_) / sizeof *offsets_next_rec_;
n_cols = dict_index_get_n_unique(index);
n_diff = mem_alloc((n_cols + 1) * sizeof(ib_longlong));
- for (j = 0; j <= n_cols; j++) {
- n_diff[j] = 0;
- }
+ memset(n_diff, 0, (n_cols + 1) * sizeof(ib_longlong));
/* We sample some pages in the index to get an estimate */
for (i = 0; i < BTR_KEY_VAL_ESTIMATE_N_PAGES; i++) {
+ rec_t* supremum;
mtr_start(&mtr);
btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
@@ -2687,20 +2870,29 @@ btr_estimate_number_of_different_key_vals(
page = btr_cur_get_page(&cursor);
- rec = page_get_infimum_rec(page);
- rec = page_rec_get_next(rec);
+ supremum = page_get_supremum_rec(page);
+ rec = page_rec_get_next(page_get_infimum_rec(page));
- if (rec != page_get_supremum_rec(page)) {
+ if (rec != supremum) {
not_empty_flag = 1;
+ offsets_rec = rec_get_offsets(rec, index, offsets_rec,
+ ULINT_UNDEFINED, &heap);
}
-
- while (rec != page_get_supremum_rec(page)
- && page_rec_get_next(rec)
- != page_get_supremum_rec(page)) {
+
+ while (rec != supremum) {
+ rec_t* next_rec = page_rec_get_next(rec);
+ if (next_rec == supremum) {
+ break;
+ }
+
matched_fields = 0;
matched_bytes = 0;
+ offsets_next_rec = rec_get_offsets(next_rec, index,
+ offsets_next_rec,
+ n_cols, &heap);
- cmp_rec_rec_with_match(rec, page_rec_get_next(rec),
+ cmp_rec_rec_with_match(rec, next_rec,
+ offsets_rec, offsets_next_rec,
index, &matched_fields,
&matched_bytes);
@@ -2712,9 +2904,18 @@ btr_estimate_number_of_different_key_vals(
}
total_external_size +=
- btr_rec_get_externally_stored_len(rec);
+ btr_rec_get_externally_stored_len(
+ rec, offsets_rec);
- rec = page_rec_get_next(rec);
+ rec = next_rec;
+ /* Initialize offsets_rec for the next round
+ and assign the old offsets_rec buffer to
+ offsets_next_rec. */
+ {
+ ulint* offsets_tmp = offsets_rec;
+ offsets_rec = offsets_next_rec;
+ offsets_next_rec = offsets_tmp;
+ }
}
@@ -2736,8 +2937,11 @@ btr_estimate_number_of_different_key_vals(
}
}
+ offsets_rec = rec_get_offsets(rec, index, offsets_rec,
+ ULINT_UNDEFINED, &heap);
total_external_size +=
- btr_rec_get_externally_stored_len(rec);
+ btr_rec_get_externally_stored_len(rec,
+ offsets_rec);
mtr_commit(&mtr);
}
@@ -2778,6 +2982,9 @@ btr_estimate_number_of_different_key_vals(
}
mem_free(n_diff);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
@@ -2788,9 +2995,10 @@ static
ulint
btr_rec_get_externally_stored_len(
/*==============================*/
- /* out: externally stored part, in units of a
- database page */
- rec_t* rec) /* in: record */
+ /* out: externally stored part,
+ in units of a database page */
+ rec_t* rec, /* in: record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_fields;
byte* data;
@@ -2799,17 +3007,13 @@ btr_rec_get_externally_stored_len(
ulint total_extern_len = 0;
ulint i;
- if (rec_get_data_size(rec) <= REC_1BYTE_OFFS_LIMIT) {
-
- return(0);
- }
-
- n_fields = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+ n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+ if (rec_offs_nth_extern(offsets, i)) {
- data = rec_get_nth_field(rec, i, &local_len);
+ data = rec_get_nth_field(rec, offsets, i, &local_len);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
@@ -2830,16 +3034,17 @@ static
void
btr_cur_set_ownership_of_extern_field(
/*==================================*/
- rec_t* rec, /* in: clustered index record */
- ulint i, /* in: field number */
- ibool val, /* in: value to set */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: clustered index record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint i, /* in: field number */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr */
{
byte* data;
ulint local_len;
ulint byte_val;
- data = rec_get_nth_field(rec, i, &local_len);
+ data = rec_get_nth_field(rec, offsets, i, &local_len);
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
@@ -2866,19 +3071,22 @@ to free the field. */
void
btr_cur_mark_extern_inherited_fields(
/*=================================*/
- rec_t* rec, /* in: record in a clustered index */
- upd_t* update, /* in: update vector */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update, /* in: update vector */
+ mtr_t* mtr) /* in: mtr */
{
ibool is_updated;
ulint n;
ulint j;
ulint i;
-
- n = rec_get_n_fields(rec);
+
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+ n = rec_offs_n_fields(offsets);
for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+ if (rec_offs_nth_extern(offsets, i)) {
/* Check it is not in updated fields */
is_updated = FALSE;
@@ -2894,8 +3102,8 @@ btr_cur_mark_extern_inherited_fields(
}
if (!is_updated) {
- btr_cur_set_ownership_of_extern_field(rec, i,
- FALSE, mtr);
+ btr_cur_set_ownership_of_extern_field(rec,
+ offsets, i, FALSE, mtr);
}
}
}
@@ -2967,18 +3175,20 @@ static
void
btr_cur_unmark_extern_fields(
/*=========================*/
- rec_t* rec, /* in: record in a clustered index */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ mtr_t* mtr, /* in: mtr */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n;
ulint i;
- n = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+ n = rec_offs_n_fields(offsets);
for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
-
- btr_cur_set_ownership_of_extern_field(rec, i,
+ if (rec_offs_nth_extern(offsets, i)) {
+
+ btr_cur_set_ownership_of_extern_field(rec, offsets, i,
TRUE, mtr);
}
}
@@ -3028,10 +3238,10 @@ ulint
btr_push_update_extern_fields(
/*==========================*/
/* out: number of values stored in ext_vect */
- ulint* ext_vect, /* in: array of ulints, must be preallocated
+ ulint* ext_vect,/* in: array of ulints, must be preallocated
to have space for all fields in rec */
- rec_t* rec, /* in: record */
- upd_t* update) /* in: update vector or NULL */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update) /* in: update vector or NULL */
{
ulint n_pushed = 0;
ibool is_updated;
@@ -3054,10 +3264,10 @@ btr_push_update_extern_fields(
}
}
- n = rec_get_n_fields(rec);
+ n = rec_offs_n_fields(offsets);
for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+ if (rec_offs_nth_extern(offsets, i)) {
/* Check it is not in updated fields */
is_updated = FALSE;
@@ -3119,6 +3329,7 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
mtr_t* local_mtr __attribute__((unused))) /* in: mtr
@@ -3139,6 +3350,7 @@ btr_store_big_rec_extern_fields(
ulint i;
mtr_t mtr;
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, buf_block_align(rec),
@@ -3152,8 +3364,8 @@ btr_store_big_rec_extern_fields(
for (i = 0; i < big_rec_vec->n_fields; i++) {
- data = rec_get_nth_field(rec, big_rec_vec->fields[i].field_no,
- &local_len);
+ data = rec_get_nth_field(rec, offsets,
+ big_rec_vec->fields[i].field_no, &local_len);
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
extern_len = big_rec_vec->fields[i].len;
@@ -3254,7 +3466,7 @@ btr_store_big_rec_extern_fields(
/* Set the bit denoting that this field
in rec is stored externally */
- rec_set_nth_field_extern_bit(rec,
+ rec_set_nth_field_extern_bit(rec, index,
big_rec_vec->fields[i].field_no,
TRUE, &mtr);
}
@@ -3407,6 +3619,7 @@ btr_rec_free_externally_stored_fields(
dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
inherited fields */
@@ -3419,21 +3632,18 @@ btr_rec_free_externally_stored_fields(
ulint len;
ulint i;
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_X_FIX));
- if (rec_get_data_size(rec) <= REC_1BYTE_OFFS_LIMIT) {
-
- return;
- }
-
/* Free possible externally stored fields in the record */
- n_fields = rec_get_n_fields(rec);
+ ut_ad(index->table->comp == !!rec_offs_comp(offsets));
+ n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+ if (rec_offs_nth_extern(offsets, i)) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
btr_free_externally_stored_field(index, data, len,
do_not_free_inherited, mtr);
}
@@ -3450,6 +3660,7 @@ btr_rec_free_updated_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree MUST be
X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update, /* in: update vector */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
@@ -3463,13 +3674,10 @@ btr_rec_free_updated_extern_fields(
ulint len;
ulint i;
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_X_FIX));
- if (rec_get_data_size(rec) <= REC_1BYTE_OFFS_LIMIT) {
- return;
- }
-
/* Free possible externally stored fields in the record */
n_fields = upd_get_n_fields(update);
@@ -3477,9 +3685,10 @@ btr_rec_free_updated_extern_fields(
for (i = 0; i < n_fields; i++) {
ufield = upd_get_nth_field(update, i);
- if (rec_get_nth_field_extern_bit(rec, ufield->field_no)) {
+ if (rec_offs_nth_extern(offsets, ufield->field_no)) {
- data = rec_get_nth_field(rec, ufield->field_no, &len);
+ data = rec_get_nth_field(rec, offsets,
+ ufield->field_no, &len);
btr_free_externally_stored_field(index, data, len,
do_not_free_inherited, mtr);
}
@@ -3583,7 +3792,8 @@ byte*
btr_rec_copy_externally_stored_field(
/*=================================*/
/* out: the field copied to heap */
- rec_t* rec, /* in: record */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint no, /* in: field number */
ulint* len, /* out: length of the field */
mem_heap_t* heap) /* in: mem heap */
@@ -3591,7 +3801,8 @@ btr_rec_copy_externally_stored_field(
ulint local_len;
byte* data;
- ut_a(rec_get_nth_field_extern_bit(rec, no));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_a(rec_offs_nth_extern(offsets, no));
/* An externally stored field can contain some initial
data from the field, and in the last 20 bytes it has the
@@ -3602,7 +3813,7 @@ btr_rec_copy_externally_stored_field(
limit so that field offsets are stored in two bytes, and
the extern bit is available in those two bytes. */
- data = rec_get_nth_field(rec, no, &local_len);
+ data = rec_get_nth_field(rec, offsets, no, &local_len);
return(btr_copy_externally_stored_field(len, data, local_len, heap));
}
diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c
index 0dcf6c2f3fc..5dbbca0b17d 100644
--- a/innobase/btr/btr0pcur.c
+++ b/innobase/btr/btr0pcur.c
@@ -46,12 +46,12 @@ btr_pcur_free_for_mysql(
mem_free(cursor->old_rec_buf);
- cursor->old_rec = NULL;
cursor->old_rec_buf = NULL;
}
cursor->btr_cur.page_cur.rec = NULL;
cursor->old_rec = NULL;
+ cursor->old_n_fields = 0;
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
cursor->latch_mode = BTR_NO_LATCHES;
@@ -78,6 +78,7 @@ btr_pcur_store_position(
rec_t* rec;
dict_tree_t* tree;
page_t* page;
+ ulint offs;
ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
@@ -87,7 +88,8 @@ btr_pcur_store_position(
page_cursor = btr_pcur_get_page_cur(cursor);
rec = page_cur_get_rec(page_cursor);
- page = buf_frame_align(rec);
+ page = ut_align_down(rec, UNIV_PAGE_SIZE);
+ offs = ut_align_offset(rec, UNIV_PAGE_SIZE);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_S_FIX)
@@ -95,35 +97,33 @@ btr_pcur_store_position(
MTR_MEMO_PAGE_X_FIX));
ut_a(cursor->latch_mode != BTR_NO_LATCHES);
- if (page_get_n_recs(page) == 0) {
+ if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) {
/* It must be an empty index tree; NOTE that in this case
we do not store the modify_clock, but always do a search
if we restore the cursor position */
- ut_a(btr_page_get_next(page, mtr) == FIL_NULL
- && btr_page_get_prev(page, mtr) == FIL_NULL);
+ ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
+ ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
- if (rec == page_get_supremum_rec(page)) {
+ cursor->old_stored = BTR_PCUR_OLD_STORED;
- cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
- cursor->old_stored = BTR_PCUR_OLD_STORED;
+ if (page_rec_is_supremum_low(offs)) {
- return;
+ cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
+ } else {
+ cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
}
- cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
- cursor->old_stored = BTR_PCUR_OLD_STORED;
-
return;
}
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum_low(offs)) {
rec = page_rec_get_prev(rec);
cursor->rel_pos = BTR_PCUR_AFTER;
- } else if (rec == page_get_infimum_rec(page)) {
+ } else if (page_rec_is_infimum_low(offs)) {
rec = page_rec_get_next(rec);
@@ -134,11 +134,13 @@ btr_pcur_store_position(
cursor->old_stored = BTR_PCUR_OLD_STORED;
cursor->old_rec = dict_tree_copy_rec_order_prefix(tree, rec,
- &(cursor->old_rec_buf),
- &(cursor->buf_size));
-
+ &cursor->old_n_fields,
+ &cursor->old_rec_buf,
+ &cursor->buf_size);
+
cursor->block_when_stored = buf_block_align(page);
- cursor->modify_clock = buf_frame_get_modify_clock(page);
+ cursor->modify_clock = buf_block_get_modify_clock(
+ cursor->block_when_stored);
}
/******************************************************************
@@ -167,6 +169,8 @@ btr_pcur_copy_stored_position(
pcur_receive->old_rec = pcur_receive->old_rec_buf
+ (pcur_donate->old_rec - pcur_donate->old_rec_buf);
}
+
+ pcur_receive->old_n_fields = pcur_donate->old_n_fields;
}
/******************************************************************
@@ -199,33 +203,27 @@ btr_pcur_restore_position(
dtuple_t* tuple;
ulint mode;
ulint old_mode;
- ibool from_left;
mem_heap_t* heap;
- ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
- || cursor->pos_state == BTR_PCUR_IS_POSITIONED);
- if (cursor->old_stored != BTR_PCUR_OLD_STORED) {
+ if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED)
+ || UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED
+ && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) {
ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t));
if (cursor->trx_if_known) {
- trx_print(stderr, cursor->trx_if_known);
+ trx_print(stderr, cursor->trx_if_known, 0);
}
- ut_a(0);
+ ut_error;
}
- if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
- || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
+ if (UNIV_UNLIKELY(cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
+ || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
/* In these cases we do not try an optimistic restoration,
but always do a search */
- if (cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
- from_left = TRUE;
- } else {
- from_left = FALSE;
- }
-
- btr_cur_open_at_index_side(from_left,
+ btr_cur_open_at_index_side(
+ cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
btr_pcur_get_btr_cur(cursor)->index, latch_mode,
btr_pcur_get_btr_cur(cursor), mtr);
@@ -236,31 +234,47 @@ btr_pcur_restore_position(
}
ut_a(cursor->old_rec);
+ ut_a(cursor->old_n_fields);
page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
- if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) {
+ if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF)
+ || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) {
/* Try optimistic restoration */
- if (buf_page_optimistic_get(latch_mode,
+ if (UNIV_LIKELY(buf_page_optimistic_get(latch_mode,
cursor->block_when_stored, page,
- cursor->modify_clock, mtr)) {
+ cursor->modify_clock, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
#endif /* UNIV_SYNC_DEBUG */
if (cursor->rel_pos == BTR_PCUR_ON) {
-
+#ifdef UNIV_DEBUG
+ rec_t* rec;
+ ulint* offsets1;
+ ulint* offsets2;
+ dict_index_t* index;
+#endif /* UNIV_DEBUG */
cursor->latch_mode = latch_mode;
-
- ut_ad(cmp_rec_rec(cursor->old_rec,
- btr_pcur_get_rec(cursor),
- dict_tree_find_index(
- btr_cur_get_tree(
+#ifdef UNIV_DEBUG
+ rec = btr_pcur_get_rec(cursor);
+ index = dict_tree_find_index(
+ btr_cur_get_tree(
btr_pcur_get_btr_cur(cursor)),
- btr_pcur_get_rec(cursor)))
- == 0);
+ rec);
+ heap = mem_heap_create(256);
+ offsets1 = rec_get_offsets(cursor->old_rec,
+ index, NULL,
+ cursor->old_n_fields, &heap);
+ offsets2 = rec_get_offsets(rec, index, NULL,
+ cursor->old_n_fields, &heap);
+
+ ut_ad(cmp_rec_rec(cursor->old_rec,
+ rec, offsets1, offsets2, index) == 0);
+ mem_heap_free(heap);
+#endif /* UNIV_DEBUG */
return(TRUE);
}
@@ -273,12 +287,13 @@ btr_pcur_restore_position(
heap = mem_heap_create(256);
tree = btr_cur_get_tree(btr_pcur_get_btr_cur(cursor));
- tuple = dict_tree_build_data_tuple(tree, cursor->old_rec, heap);
+ tuple = dict_tree_build_data_tuple(tree, cursor->old_rec,
+ cursor->old_n_fields, heap);
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
- if (cursor->rel_pos == BTR_PCUR_ON) {
+ if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
mode = PAGE_CUR_LE;
} else if (cursor->rel_pos == BTR_PCUR_AFTER) {
mode = PAGE_CUR_G;
@@ -295,18 +310,19 @@ btr_pcur_restore_position(
if (cursor->rel_pos == BTR_PCUR_ON
&& btr_pcur_is_on_user_rec(cursor, mtr)
- && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor))) {
+ && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
+ rec_get_offsets(btr_pcur_get_rec(cursor),
+ btr_pcur_get_btr_cur(cursor)->index,
+ NULL, ULINT_UNDEFINED, &heap))) {
/* We have to store the NEW value for the modify clock, since
the cursor can now be on a different page! But we can retain
the value of old_rec */
- cursor->modify_clock =
- buf_frame_get_modify_clock(btr_pcur_get_page(cursor));
-
cursor->block_when_stored =
buf_block_align(btr_pcur_get_page(cursor));
-
+ cursor->modify_clock =
+ buf_block_get_modify_clock(cursor->block_when_stored);
cursor->old_stored = BTR_PCUR_OLD_STORED;
mem_heap_free(heap);
@@ -384,6 +400,7 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr);
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
buf_block_align(next_page)->check_index_page_at_flush = TRUE;
btr_leaf_page_release(page, cursor->latch_mode, mtr);
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index 9384168df88..7a4e92a672a 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -411,11 +411,17 @@ btr_search_update_hash_ref(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(buf_block_align(btr_cur_get_rec(cursor)) == block);
+ ut_a(!block->is_hashed || block->index == cursor->index);
+
if (block->is_hashed
&& (info->n_hash_potential > 0)
&& (block->curr_n_fields == info->n_fields)
&& (block->curr_n_bytes == info->n_bytes)
&& (block->curr_side == info->side)) {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
rec = btr_cur_get_rec(cursor);
@@ -425,10 +431,13 @@ btr_search_update_hash_ref(
}
tree_id = ((cursor->index)->tree)->id;
-
- fold = rec_fold(rec, block->curr_n_fields,
- block->curr_n_bytes, tree_id);
-
+ fold = rec_fold(rec, rec_get_offsets(rec, cursor->index,
+ offsets_, ULINT_UNDEFINED, &heap),
+ block->curr_n_fields,
+ block->curr_n_bytes, tree_id);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
@@ -535,135 +544,127 @@ btr_search_check_guess(
or PAGE_CUR_GE */
mtr_t* mtr) /* in: mtr */
{
- page_t* page;
- rec_t* rec;
- rec_t* prev_rec;
- rec_t* next_rec;
- ulint n_unique;
- ulint match;
- ulint bytes;
- int cmp;
-
+ rec_t* rec;
+ ulint n_unique;
+ ulint match;
+ ulint bytes;
+ int cmp;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ ibool success = FALSE;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
n_unique = dict_index_get_n_unique_in_tree(cursor->index);
rec = btr_cur_get_rec(cursor);
- page = buf_frame_align(rec);
ut_ad(page_rec_is_user_rec(rec));
match = 0;
bytes = 0;
- cmp = page_cmp_dtuple_rec_with_match(tuple, rec, &match, &bytes);
+ offsets = rec_get_offsets(rec, cursor->index, offsets,
+ n_unique, &heap);
+ cmp = page_cmp_dtuple_rec_with_match(tuple, rec,
+ offsets, &match, &bytes);
if (mode == PAGE_CUR_GE) {
if (cmp == 1) {
-
- return(FALSE);
+ goto exit_func;
}
cursor->up_match = match;
if (match >= n_unique) {
-
- return(TRUE);
+ success = TRUE;
+ goto exit_func;
}
} else if (mode == PAGE_CUR_LE) {
if (cmp == -1) {
-
- return(FALSE);
+ goto exit_func;
}
cursor->low_match = match;
} else if (mode == PAGE_CUR_G) {
if (cmp != -1) {
-
- return(FALSE);
+ goto exit_func;
}
} else if (mode == PAGE_CUR_L) {
if (cmp != 1) {
-
- return(FALSE);
+ goto exit_func;
}
}
if (can_only_compare_to_cursor_rec) {
/* Since we could not determine if our guess is right just by
looking at the record under the cursor, return FALSE */
-
- return(FALSE);
+ goto exit_func;
}
match = 0;
bytes = 0;
if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) {
+ rec_t* prev_rec;
- ut_ad(rec != page_get_infimum_rec(page));
+ ut_ad(!page_rec_is_infimum(rec));
prev_rec = page_rec_get_prev(rec);
- if (prev_rec == page_get_infimum_rec(page)) {
-
- if (btr_page_get_prev(page, mtr) != FIL_NULL) {
+ if (page_rec_is_infimum(prev_rec)) {
+ success = btr_page_get_prev(
+ buf_frame_align(prev_rec), mtr) == FIL_NULL;
- return(FALSE);
- }
-
- return(TRUE);
+ goto exit_func;
}
+ offsets = rec_get_offsets(prev_rec, cursor->index, offsets,
+ n_unique, &heap);
cmp = page_cmp_dtuple_rec_with_match(tuple, prev_rec,
- &match, &bytes);
+ offsets, &match, &bytes);
if (mode == PAGE_CUR_GE) {
- if (cmp != 1) {
-
- return(FALSE);
- }
+ success = cmp == 1;
} else {
- if (cmp == -1) {
-
- return(FALSE);
- }
+ success = cmp != -1;
}
- return(TRUE);
- }
-
- ut_ad(rec != page_get_supremum_rec(page));
-
- next_rec = page_rec_get_next(rec);
-
- if (next_rec == page_get_supremum_rec(page)) {
-
- if (btr_page_get_next(page, mtr) == FIL_NULL) {
-
- cursor->up_match = 0;
+ goto exit_func;
+ } else {
+ rec_t* next_rec;
- return(TRUE);
- }
+ ut_ad(!page_rec_is_supremum(rec));
+
+ next_rec = page_rec_get_next(rec);
- return(FALSE);
- }
+ if (page_rec_is_supremum(next_rec)) {
+ if (btr_page_get_next(
+ buf_frame_align(next_rec), mtr) == FIL_NULL) {
- cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, &match, &bytes);
-
- if (mode == PAGE_CUR_LE) {
- if (cmp != -1) {
+ cursor->up_match = 0;
+ success = TRUE;
+ }
- return(FALSE);
+ goto exit_func;
}
- cursor->up_match = match;
- } else {
- if (cmp == 1) {
-
- return(FALSE);
+ offsets = rec_get_offsets(next_rec, cursor->index, offsets,
+ n_unique, &heap);
+ cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec,
+ offsets, &match, &bytes);
+ if (mode == PAGE_CUR_LE) {
+ success = cmp == -1;
+ cursor->up_match = match;
+ } else {
+ success = cmp != 1;
}
}
-
- return(TRUE);
+exit_func:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(success);
}
/**********************************************************************
@@ -695,7 +696,6 @@ btr_search_guess_on_hash(
buf_block_t* block;
rec_t* rec;
page_t* page;
- ibool success;
ulint fold;
ulint tuple_n_fields;
dulint tree_id;
@@ -711,7 +711,7 @@ btr_search_guess_on_hash(
/* Note that, for efficiency, the struct info may not be protected by
any latch here! */
- if (info->n_hash_potential == 0) {
+ if (UNIV_UNLIKELY(info->n_hash_potential == 0)) {
return(FALSE);
}
@@ -721,12 +721,13 @@ btr_search_guess_on_hash(
tuple_n_fields = dtuple_get_n_fields(tuple);
- if (tuple_n_fields < cursor->n_fields) {
+ if (UNIV_UNLIKELY(tuple_n_fields < cursor->n_fields)) {
return(FALSE);
}
- if ((cursor->n_bytes > 0) && (tuple_n_fields <= cursor->n_fields)) {
+ if (UNIV_UNLIKELY(tuple_n_fields == cursor->n_fields)
+ && (cursor->n_bytes > 0)) {
return(FALSE);
}
@@ -741,39 +742,31 @@ btr_search_guess_on_hash(
cursor->fold = fold;
cursor->flag = BTR_CUR_HASH;
- if (!has_search_latch) {
+ if (UNIV_LIKELY(!has_search_latch)) {
rw_lock_s_lock(&btr_search_latch);
}
- ut_a(btr_search_latch.writer != RW_LOCK_EX);
- ut_a(btr_search_latch.reader_count > 0);
+ ut_ad(btr_search_latch.writer != RW_LOCK_EX);
+ ut_ad(btr_search_latch.reader_count > 0);
rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
- if (!rec) {
- if (!has_search_latch) {
- rw_lock_s_unlock(&btr_search_latch);
- }
-
- goto failure;
+ if (UNIV_UNLIKELY(!rec)) {
+ goto failure_unlock;
}
page = buf_frame_align(rec);
- if (!has_search_latch) {
+ if (UNIV_LIKELY(!has_search_latch)) {
- success = buf_page_get_known_nowait(latch_mode, page,
+ if (UNIV_UNLIKELY(!buf_page_get_known_nowait(latch_mode, page,
BUF_MAKE_YOUNG,
__FILE__, __LINE__,
- mtr);
-
- rw_lock_s_unlock(&btr_search_latch);
-
- if (!success) {
-
- goto failure;
+ mtr))) {
+ goto failure_unlock;
}
+ rw_lock_s_unlock(&btr_search_latch);
can_only_compare_to_cursor_rec = FALSE;
#ifdef UNIV_SYNC_DEBUG
@@ -783,8 +776,8 @@ btr_search_guess_on_hash(
block = buf_block_align(page);
- if (block->state == BUF_BLOCK_REMOVE_HASH) {
- if (!has_search_latch) {
+ if (UNIV_UNLIKELY(block->state == BUF_BLOCK_REMOVE_HASH)) {
+ if (UNIV_LIKELY(!has_search_latch)) {
btr_leaf_page_release(page, latch_mode, mtr);
}
@@ -792,51 +785,33 @@ btr_search_guess_on_hash(
goto failure;
}
- ut_a(block->state == BUF_BLOCK_FILE_PAGE);
- ut_a(page_rec_is_user_rec(rec));
+ ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
+ ut_ad(page_rec_is_user_rec(rec));
btr_cur_position(index, rec, cursor);
/* Check the validity of the guess within the page */
- if (0 != ut_dulint_cmp(tree_id, btr_page_get_index_id(page))) {
-
- success = FALSE;
-/*
- fprintf(stderr, "Tree id %lu, page index id %lu fold %lu\n",
- ut_dulint_get_low(tree_id),
- ut_dulint_get_low(btr_page_get_index_id(page)),
- fold);
-*/
- } else {
- /* If we only have the latch on btr_search_latch, not on the
- page, it only protects the columns of the record the cursor
- is positioned on. We cannot look at the next of the previous
- record to determine if our guess for the cursor position is
- right. */
-
- success = btr_search_check_guess(cursor,
- can_only_compare_to_cursor_rec,
- tuple, mode, mtr);
- }
-
- if (!success) {
- if (!has_search_latch) {
+ /* If we only have the latch on btr_search_latch, not on the
+ page, it only protects the columns of the record the cursor
+ is positioned on. We cannot look at the next of the previous
+ record to determine if our guess for the cursor position is
+ right. */
+ if (UNIV_EXPECT(ut_dulint_cmp(tree_id, btr_page_get_index_id(page)), 0)
+ || !btr_search_check_guess(cursor, can_only_compare_to_cursor_rec,
+ tuple, mode, mtr)) {
+ if (UNIV_LIKELY(!has_search_latch)) {
btr_leaf_page_release(page, latch_mode, mtr);
}
goto failure;
}
- if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) {
+ if (UNIV_LIKELY(info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5)) {
info->n_hash_potential++;
}
- if (info->last_hash_succ != TRUE) {
- info->last_hash_succ = TRUE;
- }
-
#ifdef notdefined
/* These lines of code can be used in a debug version to check
the correctness of the searched cursor position: */
@@ -844,15 +819,14 @@ btr_search_guess_on_hash(
info->last_hash_succ = FALSE;
/* Currently, does not work if the following fails: */
- ut_a(!has_search_latch);
+ ut_ad(!has_search_latch);
btr_leaf_page_release(page, latch_mode, mtr);
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
&cursor2, 0, mtr);
if (mode == PAGE_CUR_GE
- && btr_cur_get_rec(&cursor2) == page_get_supremum_rec(
- buf_frame_align(btr_cur_get_rec(&cursor2)))) {
+ && page_rec_is_supremum(btr_cur_get_rec(&cursor2))) {
/* If mode is PAGE_CUR_GE, then the binary search
in the index tree may actually take us to the supremum
@@ -862,22 +836,22 @@ btr_search_guess_on_hash(
btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode,
&pcur, mtr);
- ut_a(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
+ ut_ad(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
} else {
- ut_a(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
+ ut_ad(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
}
/* NOTE that it is theoretically possible that the above assertions
fail if the page of the cursor gets removed from the buffer pool
meanwhile! Thus it might not be a bug. */
-
- info->last_hash_succ = TRUE;
#endif
+ info->last_hash_succ = TRUE;
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_succ++;
#endif
- if (!has_search_latch && buf_block_peek_if_too_old(block)) {
+ if (UNIV_LIKELY(!has_search_latch)
+ && buf_block_peek_if_too_old(block)) {
buf_page_make_young(page);
}
@@ -890,6 +864,10 @@ btr_search_guess_on_hash(
return(TRUE);
/*-------------------------------------------*/
+failure_unlock:
+ if (UNIV_LIKELY(!has_search_latch)) {
+ rw_lock_s_unlock(&btr_search_latch);
+ }
failure:
info->n_hash_fail++;
@@ -918,7 +896,6 @@ btr_search_drop_page_hash_index(
ulint n_fields;
ulint n_bytes;
rec_t* rec;
- rec_t* sup;
ulint fold;
ulint prev_fold;
dulint tree_id;
@@ -926,6 +903,8 @@ btr_search_drop_page_hash_index(
ulint n_recs;
ulint* folds;
ulint i;
+ mem_heap_t* heap;
+ ulint* offsets;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
@@ -967,16 +946,14 @@ btr_search_drop_page_hash_index(
n_cached = 0;
- sup = page_get_supremum_rec(page);
-
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
- if (rec != sup) {
- ut_a(n_fields <= rec_get_n_fields(rec));
+ if (!page_rec_is_supremum(rec)) {
+ ut_a(n_fields <= rec_get_n_fields(rec, block->index));
if (n_bytes > 0) {
- ut_a(n_fields < rec_get_n_fields(rec));
+ ut_a(n_fields < rec_get_n_fields(rec, block->index));
}
}
@@ -984,11 +961,22 @@ btr_search_drop_page_hash_index(
prev_fold = 0;
- while (rec != sup) {
+ heap = NULL;
+ offsets = NULL;
+
+ if (block->index == NULL) {
+
+ mem_analyze_corruption((byte*)block);
+
+ ut_a(block->index != NULL);
+ }
+
+ while (!page_rec_is_supremum(rec)) {
/* FIXME: in a mixed tree, not all records may have enough
ordering fields: */
-
- fold = rec_fold(rec, n_fields, n_bytes, tree_id);
+ offsets = rec_get_offsets(rec, block->index,
+ offsets, n_fields + (n_bytes > 0), &heap);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
if (fold == prev_fold && prev_fold != 0) {
@@ -1005,6 +993,10 @@ next_rec:
prev_fold = fold;
}
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
rw_lock_x_lock(&btr_search_latch);
for (i = 0; i < n_cached; i++) {
@@ -1013,6 +1005,7 @@ next_rec:
}
block->is_hashed = FALSE;
+ block->index = NULL;
rw_lock_x_unlock(&btr_search_latch);
@@ -1069,8 +1062,7 @@ static
void
btr_search_build_page_hash_index(
/*=============================*/
- dict_index_t* index, /* in: index for which to build, or NULL if
- not known */
+ dict_index_t* index, /* in: index for which to build */
page_t* page, /* in: index page, s- or x-latched */
ulint n_fields,/* in: hash this many full fields */
ulint n_bytes,/* in: hash this many bytes from the next
@@ -1081,7 +1073,6 @@ btr_search_build_page_hash_index(
buf_block_t* block;
rec_t* rec;
rec_t* next_rec;
- rec_t* sup;
ulint fold;
ulint next_fold;
dulint tree_id;
@@ -1090,7 +1081,13 @@ btr_search_build_page_hash_index(
ulint* folds;
rec_t** recs;
ulint i;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ ut_ad(index);
+
block = buf_block_align(page);
table = btr_search_sys->hash_index;
@@ -1127,9 +1124,9 @@ btr_search_build_page_hash_index(
return;
}
- if (index && (dict_index_get_n_unique_in_tree(index) < n_fields
+ if (dict_index_get_n_unique_in_tree(index) < n_fields
|| (dict_index_get_n_unique_in_tree(index) == n_fields
- && n_bytes > 0))) {
+ && n_bytes > 0)) {
return;
}
@@ -1143,23 +1140,23 @@ btr_search_build_page_hash_index(
tree_id = btr_page_get_index_id(page);
- sup = page_get_supremum_rec(page);
-
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
- if (rec != sup) {
- ut_a(n_fields <= rec_get_n_fields(rec));
+ offsets = rec_get_offsets(rec, index, offsets,
+ n_fields + (n_bytes > 0), &heap);
+
+ if (!page_rec_is_supremum(rec)) {
+ ut_a(n_fields <= rec_offs_n_fields(offsets));
if (n_bytes > 0) {
- ut_a(n_fields < rec_get_n_fields(rec));
+ ut_a(n_fields < rec_offs_n_fields(offsets));
}
}
/* FIXME: in a mixed tree, all records may not have enough ordering
fields: */
-
- fold = rec_fold(rec, n_fields, n_bytes, tree_id);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
if (side == BTR_SEARCH_LEFT_SIDE) {
@@ -1171,7 +1168,7 @@ btr_search_build_page_hash_index(
for (;;) {
next_rec = page_rec_get_next(rec);
- if (next_rec == sup) {
+ if (page_rec_is_supremum(next_rec)) {
if (side == BTR_SEARCH_RIGHT_SIDE) {
@@ -1183,7 +1180,10 @@ btr_search_build_page_hash_index(
break;
}
- next_fold = rec_fold(next_rec, n_fields, n_bytes, tree_id);
+ offsets = rec_get_offsets(next_rec, index, offsets,
+ n_fields + (n_bytes > 0), &heap);
+ next_fold = rec_fold(next_rec, offsets, n_fields,
+ n_bytes, tree_id);
if (fold != next_fold) {
/* Insert an entry into the hash index */
@@ -1211,13 +1211,7 @@ btr_search_build_page_hash_index(
if (block->is_hashed && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_side != side))) {
-
- rw_lock_x_unlock(&btr_search_latch);
-
- mem_free(folds);
- mem_free(recs);
-
- return;
+ goto exit_func;
}
block->is_hashed = TRUE;
@@ -1226,16 +1220,21 @@ btr_search_build_page_hash_index(
block->curr_n_fields = n_fields;
block->curr_n_bytes = n_bytes;
block->curr_side = side;
+ block->index = index;
for (i = 0; i < n_cached; i++) {
ha_insert_for_fold(table, folds[i], recs[i]);
}
+exit_func:
rw_lock_x_unlock(&btr_search_latch);
mem_free(folds);
mem_free(recs);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
/************************************************************************
@@ -1247,10 +1246,13 @@ parameters as page (this often happens when a page is split). */
void
btr_search_move_or_delete_hash_entries(
/*===================================*/
- page_t* new_page, /* in: records are copied to this page */
- page_t* page) /* in: index page from which records were
- copied, and the copied records will be deleted
- from this page */
+ page_t* new_page, /* in: records are copied
+ to this page */
+ page_t* page, /* in: index page from which
+ records were copied, and the
+ copied records will be deleted
+ from this page */
+ dict_index_t* index) /* in: record descriptor */
{
buf_block_t* block;
buf_block_t* new_block;
@@ -1260,11 +1262,14 @@ btr_search_move_or_delete_hash_entries(
block = buf_block_align(page);
new_block = buf_block_align(new_page);
+ ut_a(page_is_comp(page) == page_is_comp(new_page));
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
+ ut_a(!new_block->is_hashed || new_block->index == index);
+ ut_a(!block->is_hashed || block->index == index);
rw_lock_s_lock(&btr_search_latch);
@@ -1290,8 +1295,8 @@ btr_search_move_or_delete_hash_entries(
rw_lock_s_unlock(&btr_search_latch);
ut_a(n_fields + n_bytes > 0);
-
- btr_search_build_page_hash_index(NULL, new_page, n_fields,
+
+ btr_search_build_page_hash_index(index, new_page, n_fields,
n_bytes, side);
ut_a(n_fields == block->curr_n_fields);
ut_a(n_bytes == block->curr_n_bytes);
@@ -1319,6 +1324,9 @@ btr_search_update_hash_on_delete(
ulint fold;
dulint tree_id;
ibool found;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ mem_heap_t* heap = NULL;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
rec = btr_cur_get_rec(cursor);
@@ -1333,14 +1341,18 @@ btr_search_update_hash_on_delete(
return;
}
+ ut_a(block->index == cursor->index);
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
table = btr_search_sys->hash_index;
tree_id = cursor->index->tree->id;
-
- fold = rec_fold(rec, block->curr_n_fields, block->curr_n_bytes,
- tree_id);
+ fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
+ ULINT_UNDEFINED, &heap), block->curr_n_fields,
+ block->curr_n_bytes, tree_id);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
rw_lock_x_lock(&btr_search_latch);
found = ha_search_and_delete_if_found(table, fold, rec);
@@ -1376,6 +1388,8 @@ btr_search_update_hash_node_on_insert(
return;
}
+ ut_a(block->index == cursor->index);
+
rw_lock_x_lock(&btr_search_latch);
if ((cursor->flag == BTR_CUR_HASH)
@@ -1409,7 +1423,6 @@ btr_search_update_hash_on_insert(
{
hash_table_t* table;
buf_block_t* block;
- page_t* page;
rec_t* rec;
rec_t* ins_rec;
rec_t* next_rec;
@@ -1420,7 +1433,11 @@ btr_search_update_hash_on_insert(
ulint n_fields;
ulint n_bytes;
ulint side;
- ibool locked = FALSE;
+ ibool locked = FALSE;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
table = btr_search_sys->hash_index;
@@ -1439,6 +1456,8 @@ btr_search_update_hash_on_insert(
return;
}
+ ut_a(block->index == cursor->index);
+
tree_id = ((cursor->index)->tree)->id;
n_fields = block->curr_n_fields;
@@ -1448,16 +1467,21 @@ btr_search_update_hash_on_insert(
ins_rec = page_rec_get_next(rec);
next_rec = page_rec_get_next(ins_rec);
- page = buf_frame_align(rec);
-
- ins_fold = rec_fold(ins_rec, n_fields, n_bytes, tree_id);
+ offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
+ ULINT_UNDEFINED, &heap);
+ ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, tree_id);
- if (next_rec != page_get_supremum_rec(page)) {
- next_fold = rec_fold(next_rec, n_fields, n_bytes, tree_id);
+ if (!page_rec_is_supremum(next_rec)) {
+ offsets = rec_get_offsets(next_rec, cursor->index, offsets,
+ n_fields + (n_bytes > 0), &heap);
+ next_fold = rec_fold(next_rec, offsets, n_fields,
+ n_bytes, tree_id);
}
- if (rec != page_get_infimum_rec(page)) {
- fold = rec_fold(rec, n_fields, n_bytes, tree_id);
+ if (!page_rec_is_infimum(rec)) {
+ offsets = rec_get_offsets(rec, cursor->index, offsets,
+ n_fields + (n_bytes > 0), &heap);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
} else {
if (side == BTR_SEARCH_LEFT_SIDE) {
@@ -1488,7 +1512,7 @@ btr_search_update_hash_on_insert(
}
check_next_rec:
- if (next_rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(next_rec)) {
if (side == BTR_SEARCH_RIGHT_SIDE) {
@@ -1527,6 +1551,9 @@ check_next_rec:
}
function_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
if (locked) {
rw_lock_x_unlock(&btr_search_latch);
}
@@ -1546,6 +1573,10 @@ btr_search_validate(void)
ulint n_page_dumps = 0;
ibool ok = TRUE;
ulint i;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
rw_lock_x_lock(&btr_search_latch);
@@ -1555,9 +1586,14 @@ btr_search_validate(void)
while (node != NULL) {
block = buf_block_align(node->data);
page = buf_frame_align(node->data);
+ offsets = rec_get_offsets((rec_t*) node->data,
+ block->index, offsets,
+ block->curr_n_fields
+ + (block->curr_n_bytes > 0), &heap);
if (!block->is_hashed
|| node->fold != rec_fold((rec_t*)(node->data),
+ offsets,
block->curr_n_fields,
block->curr_n_bytes,
btr_page_get_index_id(page))) {
@@ -1573,12 +1609,14 @@ btr_search_validate(void)
(ulong) ut_dulint_get_low(btr_page_get_index_id(page)),
(ulong) node->fold,
(ulong) rec_fold((rec_t*)(node->data),
+ offsets,
block->curr_n_fields,
block->curr_n_bytes,
btr_page_get_index_id(page)));
fputs("InnoDB: Record ", stderr);
- rec_print(stderr, (rec_t*)(node->data));
+ rec_print_new(stderr, (rec_t*)node->data,
+ offsets);
fprintf(stderr, "\nInnoDB: on that page."
"Page mem address %p, is hashed %lu, n fields %lu, n bytes %lu\n"
"side %lu\n",
@@ -1602,6 +1640,9 @@ btr_search_validate(void)
}
rw_lock_x_unlock(&btr_search_latch);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(ok);
}
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 31a581d2ba8..aa3aef7f97c 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -223,13 +223,14 @@ in the free list to the frames.
buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */
+#ifdef UNIV_DEBUG
ulint buf_dbg_counter = 0; /* This is used to insert validation
operations in excution in the
debug version */
ibool buf_debug_prints = FALSE; /* If this is set TRUE,
the program prints info whenever
read-ahead or flush occurs */
-
+#endif /* UNIV_DEBUG */
/************************************************************************
Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value on
@@ -331,33 +332,43 @@ buf_page_is_corrupted(
}
}
#endif
- old_checksum = buf_calc_page_old_checksum(read_buf);
-
- old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE
+
+ /* If we use checksums validation, make additional check before returning
+ TRUE to ensure that the checksum is not equal to BUF_NO_CHECKSUM_MAGIC which
+ might be stored by InnoDB with checksums disabled.
+ Otherwise, skip checksum calculation and return FALSE */
+
+ if (srv_use_checksums) {
+ old_checksum = buf_calc_page_old_checksum(read_buf);
+
+ old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM);
- /* There are 2 valid formulas for old_checksum_field:
- 1. Very old versions of InnoDB only stored 8 byte lsn to the start
- and the end of the page.
- 2. Newer InnoDB versions store the old formula checksum there. */
+ /* There are 2 valid formulas for old_checksum_field:
+ 1. Very old versions of InnoDB only stored 8 byte lsn to the start
+ and the end of the page.
+ 2. Newer InnoDB versions store the old formula checksum there. */
- if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN)
- && old_checksum_field != old_checksum) {
-
- return(TRUE);
- }
+ if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN)
+ && old_checksum_field != old_checksum
+ && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) {
- checksum = buf_calc_page_new_checksum(read_buf);
- checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM);
+ return(TRUE);
+ }
- /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
- (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
+ checksum = buf_calc_page_new_checksum(read_buf);
+ checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM);
- if (checksum_field != 0 && checksum_field != checksum) {
+ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+ (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
- return(TRUE);
- }
+ if (checksum_field != 0 && checksum_field != checksum
+ && checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+ return(TRUE);
+ }
+ }
+
return(FALSE);
}
@@ -379,8 +390,10 @@ buf_page_print(
ut_print_buf(stderr, read_buf, UNIV_PAGE_SIZE);
fputs("InnoDB: End of page dump\n", stderr);
- checksum = buf_calc_page_new_checksum(read_buf);
- old_checksum = buf_calc_page_old_checksum(read_buf);
+ checksum = srv_use_checksums ?
+ buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+ old_checksum = srv_use_checksums ?
+ buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -460,6 +473,7 @@ buf_block_init(
block->file_page_was_freed = FALSE;
block->check_index_page_at_flush = FALSE;
+ block->index = NULL;
block->in_free_list = FALSE;
block->in_LRU_list = FALSE;
@@ -547,7 +561,7 @@ buf_pool_init(
}
/*----------------------------------------*/
} else {
- buf_pool->frame_mem = ut_malloc_low(
+ buf_pool->frame_mem = os_mem_alloc_large(
UNIV_PAGE_SIZE * (n_frames + 1),
TRUE, FALSE);
}
@@ -1273,8 +1287,9 @@ buf_page_optimistic_get_func(
/* If AWE is used, block may have a different frame now, e.g., NULL */
- if (block->state != BUF_BLOCK_FILE_PAGE || block->frame != guess) {
-
+ if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE)
+ || UNIV_UNLIKELY(block->frame != guess)) {
+ exit_func:
mutex_exit(&(buf_pool->mutex));
return(FALSE);
@@ -1307,19 +1322,17 @@ buf_page_optimistic_get_func(
fix_type = MTR_MEMO_PAGE_X_FIX;
}
- if (!success) {
+ if (UNIV_UNLIKELY(!success)) {
mutex_enter(&(buf_pool->mutex));
block->buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
-#endif
- mutex_exit(&(buf_pool->mutex));
-
- return(FALSE);
+#endif
+ goto exit_func;
}
- if (!UT_DULINT_EQ(modify_clock, block->modify_clock)) {
+ if (UNIV_UNLIKELY(!UT_DULINT_EQ(modify_clock, block->modify_clock))) {
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(block->frame, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
@@ -1334,10 +1347,8 @@ buf_page_optimistic_get_func(
block->buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
-#endif
- mutex_exit(&(buf_pool->mutex));
-
- return(FALSE);
+#endif
+ goto exit_func;
}
mtr_memo_push(mtr, block, fix_type);
@@ -1355,7 +1366,7 @@ buf_page_optimistic_get_func(
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->file_page_was_freed == FALSE);
#endif
- if (!accessed) {
+ if (UNIV_UNLIKELY(!accessed)) {
/* In the case of a first access, try to apply linear
read-ahead */
@@ -1535,6 +1546,7 @@ buf_page_init(
block->offset = offset;
block->check_index_page_at_flush = FALSE;
+ block->index = NULL;
block->lock_hash_val = lock_rec_hash(space, offset);
block->lock_mutex = NULL;
@@ -1728,10 +1740,12 @@ buf_page_create(
/* If we get here, the page was not in buf_pool: init it there */
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr, "Creating space %lu page %lu to buffer\n",
(ulong) space, (ulong) offset);
}
+#endif /* UNIV_DEBUG */
block = free_block;
@@ -1891,9 +1905,11 @@ buf_page_io_complete(
rw_lock_x_unlock_gen(&(block->lock), BUF_IO_READ);
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fputs("Has read ", stderr);
}
+#endif /* UNIV_DEBUG */
} else {
ut_ad(io_type == BUF_IO_WRITE);
@@ -1906,17 +1922,21 @@ buf_page_io_complete(
buf_pool->n_pages_written++;
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fputs("Has written ", stderr);
}
+#endif /* UNIV_DEBUG */
}
mutex_exit(&(buf_pool->mutex));
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr, "page space %lu page no %lu\n",
(ulong) block->space, (ulong) block->offset);
}
+#endif /* UNIV_DEBUG */
}
/*************************************************************************
@@ -1945,6 +1965,7 @@ buf_pool_invalidate(void)
mutex_exit(&(buf_pool->mutex));
}
+#ifdef UNIV_DEBUG
/*************************************************************************
Validates the buffer buf_pool data structure. */
@@ -2089,10 +2110,6 @@ buf_print(void)
n_found = 0;
- for (i = 0 ; i < size; i++) {
- counts[i] = 0;
- }
-
for (i = 0; i < size; i++) {
frame = buf_pool_get_nth_block(buf_pool, i)->frame;
@@ -2144,6 +2161,32 @@ buf_print(void)
ut_a(buf_validate());
}
+#endif /* UNIV_DEBUG */
+
+/*************************************************************************
+Returns the number of latched pages in the buffer pool. */
+
+ulint
+buf_get_latched_pages_number(void)
+{
+ buf_block_t* block;
+ ulint i;
+ ulint fixed_pages_number = 0;
+
+ mutex_enter(&(buf_pool->mutex));
+
+ for (i = 0; i < buf_pool->curr_size; i++) {
+
+ block = buf_pool_get_nth_block(buf_pool, i);
+
+ if (((block->buf_fix_count != 0) || (block->io_fix != 0)) &&
+ block->magic_n == BUF_BLOCK_MAGIC_N )
+ fixed_pages_number++;
+ }
+
+ mutex_exit(&(buf_pool->mutex));
+ return fixed_pages_number;
+}
/*************************************************************************
Returns the number of pending buf pool ios. */
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index 4df0e9962fb..ffb16790b2d 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -281,6 +281,10 @@ buf_flush_buffered_writes(void)
}
}
+ /* increment the doublewrite flushed pages counter */
+ srv_dblwr_pages_written+= trx_doublewrite->first_free;
+ srv_dblwr_writes++;
+
if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
len = TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
} else {
@@ -452,7 +456,8 @@ buf_flush_init_for_writing(
/* Store the new formula checksum */
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
- buf_calc_page_new_checksum(page));
+ srv_use_checksums ?
+ buf_calc_page_new_checksum(page) : BUF_NO_CHECKSUM_MAGIC);
/* We overwrite the first 4 bytes of the end lsn field to store
the old formula checksum. Since it depends also on the field
@@ -460,7 +465,8 @@ buf_flush_init_for_writing(
new formula checksum. */
mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
- buf_calc_page_old_checksum(page));
+ srv_use_checksums ?
+ buf_calc_page_old_checksum(page) : BUF_NO_CHECKSUM_MAGIC);
}
/************************************************************************
@@ -580,11 +586,13 @@ buf_flush_try_page(
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
}
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Flushing page space %lu, page no %lu \n",
(ulong) block->space, (ulong) block->offset);
}
+#endif /* UNIV_DEBUG */
buf_flush_write_block_low(block);
@@ -668,12 +676,14 @@ buf_flush_try_page(
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Flushing single page space %lu, page no %lu \n",
(ulong) block->space,
(ulong) block->offset);
}
+#endif /* UNIV_DEBUG */
buf_flush_write_block_low(block);
@@ -900,6 +910,7 @@ buf_flush_batch(
buf_flush_buffered_writes();
+#ifdef UNIV_DEBUG
if (buf_debug_prints && page_count > 0) {
ut_a(flush_type == BUF_FLUSH_LRU
|| flush_type == BUF_FLUSH_LIST);
@@ -908,7 +919,11 @@ buf_flush_batch(
: "Flushed %lu pages in flush list flush\n",
(ulong) page_count);
}
+#endif /* UNIV_DEBUG */
+ if (page_count != ULINT_UNDEFINED)
+ srv_buf_pool_flushed+= page_count;
+
return(page_count);
}
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 05e92933edf..a0157da2d42 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -213,12 +213,14 @@ buf_LRU_search_and_free_block(
ut_a(block->in_LRU_list);
if (buf_flush_ready_for_replace(block)) {
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Putting space %lu page %lu to free list\n",
(ulong) block->space,
(ulong) block->offset);
}
+#endif /* UNIV_DEBUG */
buf_LRU_block_remove_hashed_page(block);
@@ -465,6 +467,7 @@ loop:
/* No free block was found: try to flush the LRU list */
buf_flush_free_margin();
+ ++srv_buf_pool_wait_free;
os_aio_simulated_wake_handler_threads();
@@ -918,7 +921,8 @@ buf_LRU_block_free_hashed_page(
buf_LRU_block_free_non_file_page(block);
}
-
+
+#ifdef UNIV_DEBUG
/**************************************************************************
Validates the LRU list. */
@@ -1049,3 +1053,4 @@ buf_LRU_print(void)
mutex_exit(&(buf_pool->mutex));
}
+#endif /* UNIV_DEBUG */
diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c
index 055eede5c1a..813ca589907 100644
--- a/innobase/buf/buf0rea.c
+++ b/innobase/buf/buf0rea.c
@@ -20,6 +20,10 @@ Created 11/5/1995 Heikki Tuuri
#include "os0file.h"
#include "srv0start.h"
+extern ulint srv_read_ahead_rnd;
+extern ulint srv_read_ahead_seq;
+extern ulint srv_buf_pool_reads;
+
/* The size in blocks of the area where the random read-ahead algorithm counts
the accessed pages when deciding whether to read-ahead */
#define BUF_READ_AHEAD_RANDOM_AREA BUF_READ_AHEAD_AREA
@@ -284,13 +288,16 @@ buf_read_ahead_random(
os_aio_simulated_wake_handler_threads();
+#ifdef UNIV_DEBUG
if (buf_debug_prints && (count > 0)) {
fprintf(stderr,
"Random read-ahead space %lu offset %lu pages %lu\n",
(ulong) space, (ulong) offset,
(ulong) count);
}
+#endif /* UNIV_DEBUG */
+ ++srv_read_ahead_rnd;
return(count);
}
@@ -323,6 +330,7 @@ buf_read_page(
count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
tablespace_version, offset);
+ srv_buf_pool_reads+= count2;
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -569,12 +577,15 @@ buf_read_ahead_linear(
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
+#ifdef UNIV_DEBUG
if (buf_debug_prints && (count > 0)) {
fprintf(stderr,
"LINEAR read-ahead space %lu offset %lu pages %lu\n",
(ulong) space, (ulong) offset, (ulong) count);
}
+#endif /* UNIV_DEBUG */
+ ++srv_read_ahead_seq;
return(count);
}
@@ -634,11 +645,13 @@ buf_read_ibuf_merge_pages(
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Ibuf merge read-ahead space %lu pages %lu\n",
(ulong) space_ids[0], (ulong) n_stored);
}
+#endif /* UNIV_DEBUG */
}
/************************************************************************
@@ -704,8 +717,10 @@ buf_read_recv_pages(
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
+#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Recovery applies read-ahead pages %lu\n", (ulong) n_stored);
}
+#endif /* UNIV_DEBUG */
}
diff --git a/innobase/configure.in b/innobase/configure.in
index baf11272ab9..c56bd8274c4 100644
--- a/innobase/configure.in
+++ b/innobase/configure.in
@@ -117,6 +117,13 @@ case "$target" in
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
esac
+# must go in pair with AR as set by MYSQL_CHECK_AR
+if test -z "$ARFLAGS"
+then
+ ARFLAGS="cru"
+fi
+AC_SUBST(ARFLAGS)
+
AC_OUTPUT(Makefile os/Makefile ut/Makefile btr/Makefile dnl
buf/Makefile data/Makefile dnl
dict/Makefile dyn/Makefile dnl
diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c
index 97ec1a1acd9..194213a04e1 100644
--- a/innobase/data/data0data.c
+++ b/innobase/data/data0data.c
@@ -500,9 +500,9 @@ dtuple_convert_big_rec(
ut_a(dtuple_check_typed_no_assert(entry));
- size = rec_get_converted_size(entry);
+ size = rec_get_converted_size(index, entry);
- if (size > 1000000000) {
+ if (UNIV_UNLIKELY(size > 1000000000)) {
fprintf(stderr,
"InnoDB: Warning: tuple size very big: %lu\n", (ulong) size);
fputs("InnoDB: Tuple contents: ", stderr);
@@ -524,9 +524,10 @@ dtuple_convert_big_rec(
n_fields = 0;
- while ((rec_get_converted_size(entry)
- >= page_get_free_space_of_empty() / 2)
- || rec_get_converted_size(entry) >= REC_MAX_DATA_SIZE) {
+ while (rec_get_converted_size(index, entry)
+ >= ut_min(page_get_free_space_of_empty(
+ index->table->comp) / 2,
+ REC_MAX_DATA_SIZE)) {
longest = 0;
for (i = dict_index_get_n_unique_in_tree(index);
@@ -545,9 +546,7 @@ dtuple_convert_big_rec(
}
}
- if (!is_externally_stored
- && dict_index_get_nth_type(index, i)->mtype
- == DATA_BLOB) {
+ if (!is_externally_stored) {
dfield = dtuple_get_nth_field(entry, i);
diff --git a/innobase/data/data0type.c b/innobase/data/data0type.c
index dab14df4240..d4264ad2926 100644
--- a/innobase/data/data0type.c
+++ b/innobase/data/data0type.c
@@ -39,59 +39,39 @@ column definitions, or records in the insert buffer, we use this
charset-collation code for them. */
ulint data_mysql_default_charset_coll = 99999999;
-ulint data_mysql_latin1_swedish_charset_coll = 99999999;
-dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0};
+dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0, 0, 0};
dtype_t* dtype_binary = &dtype_binary_val;
/*************************************************************************
-Checks if a string type has to be compared by the MySQL comparison functions.
-InnoDB internally only handles binary byte string comparisons, as well as
-latin1_swedish_ci strings. For example, UTF-8 strings have to be compared
-by MySQL. */
-
-ibool
-dtype_str_needs_mysql_cmp(
-/*======================*/
- /* out: TRUE if a string type that requires
- comparison with MySQL functions */
- dtype_t* dtype) /* in: type struct */
-{
- if (dtype->mtype == DATA_MYSQL
- || dtype->mtype == DATA_VARMYSQL
- || (dtype->mtype == DATA_BLOB
- && 0 == (dtype->prtype & DATA_BINARY_TYPE)
- && dtype_get_charset_coll(dtype->prtype) !=
- data_mysql_latin1_swedish_charset_coll)) {
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*************************************************************************
-For the documentation of this function, see innobase_get_at_most_n_mbchars()
-in ha_innodb.cc. */
+Determine how many bytes the first n characters of the given string occupy.
+If the string is shorter than n characters, returns the number of bytes
+the characters in the string occupy. */
ulint
dtype_get_at_most_n_mbchars(
/*========================*/
- dtype_t* dtype,
- ulint prefix_len,
- ulint data_len,
- const char* str)
+ /* out: length of the prefix,
+ in bytes */
+ const dtype_t* dtype, /* in: data type */
+ ulint prefix_len, /* in: length of the requested
+ prefix, in characters, multiplied by
+ dtype_get_mbmaxlen(dtype) */
+ ulint data_len, /* in: length of str (in bytes) */
+ const char* str) /* in: the string whose prefix
+ length is being determined */
{
+#ifndef UNIV_HOTBACKUP
ut_a(data_len != UNIV_SQL_NULL);
+ ut_ad(!dtype->mbmaxlen || !(prefix_len % dtype->mbmaxlen));
- if (dtype_str_needs_mysql_cmp(dtype)) {
+ if (dtype->mbminlen != dtype->mbmaxlen) {
+ ut_a(!(prefix_len % dtype->mbmaxlen));
return(innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(dtype->prtype),
prefix_len, data_len, str));
}
- /* We assume here that the string types that InnoDB itself can compare
- are single-byte charsets! */
-
if (prefix_len < data_len) {
return(prefix_len);
@@ -99,6 +79,12 @@ dtype_get_at_most_n_mbchars(
}
return(data_len);
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/*************************************************************************
@@ -206,9 +192,11 @@ dtype_validate(
ut_a((type->mtype >= DATA_VARCHAR) && (type->mtype <= DATA_MYSQL));
if (type->mtype == DATA_SYS) {
- ut_a(type->prtype <= DATA_MIX_ID);
+ ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS);
}
+ ut_a(type->mbminlen <= type->mbmaxlen);
+
return(TRUE);
}
diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c
index f156cf67a18..18a707a1b93 100644
--- a/innobase/dict/dict0boot.c
+++ b/innobase/dict/dict0boot.c
@@ -66,15 +66,6 @@ dict_hdr_get_new_id(
dict_hdr = dict_hdr_get(&mtr);
id = mtr_read_dulint(dict_hdr + type, &mtr);
-
- /* Add some dummy code here because otherwise pgcc seems to
- compile wrong */
-
- if (0 == ut_dulint_cmp(id, ut_dulint_max)) {
- /* TO DO: remove this code, or make it conditional */
- ut_dbg_null_ptr = 0;
- }
-
id = ut_dulint_add(id, 1);
mlog_write_dulint(dict_hdr + type, id, &mtr);
@@ -158,7 +149,7 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_TABLES_ID, mtr);
+ DICT_HDR_SPACE, DICT_TABLES_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -168,7 +159,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE,
- DICT_TABLE_IDS_ID, mtr);
+ DICT_TABLE_IDS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -178,7 +169,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_COLUMNS_ID, mtr);
+ DICT_HDR_SPACE, DICT_COLUMNS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -188,7 +179,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_INDEXES_ID, mtr);
+ DICT_HDR_SPACE, DICT_INDEXES_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -198,7 +189,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_FIELDS_ID, mtr);
+ DICT_HDR_SPACE, DICT_FIELDS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -223,6 +214,7 @@ dict_boot(void)
dict_index_t* index;
dict_hdr_t* dict_hdr;
mtr_t mtr;
+ ibool success;
mtr_start(&mtr);
@@ -254,7 +246,7 @@ dict_boot(void)
/* Insert into the dictionary cache the descriptions of the basic
system tables */
/*-------------------------*/
- table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE,8);
+ table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, FALSE);
dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
@@ -275,22 +267,22 @@ dict_boot(void)
dict_mem_index_add_field(index, "NAME", 0, 0);
- index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLES,
- MLOG_4BYTES, &mtr);
index->id = DICT_TABLES_ID;
- ut_a(dict_index_add_to_cache(table, index));
+ success = dict_index_add_to_cache(table, index, mtr_read_ulint(
+ dict_hdr + DICT_HDR_TABLES, MLOG_4BYTES, &mtr));
+ ut_a(success);
/*-------------------------*/
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));
+ success = dict_index_add_to_cache(table, index, mtr_read_ulint(
+ dict_hdr + DICT_HDR_TABLE_IDS, MLOG_4BYTES, &mtr));
+ ut_a(success);
/*-------------------------*/
- table = dict_mem_table_create("SYS_COLUMNS",DICT_HDR_SPACE,7);
+ table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, FALSE);
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);
@@ -311,12 +303,12 @@ dict_boot(void)
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));
+ success = dict_index_add_to_cache(table, index, mtr_read_ulint(
+ dict_hdr + DICT_HDR_COLUMNS, MLOG_4BYTES, &mtr));
+ ut_a(success);
/*-------------------------*/
- table = dict_mem_table_create("SYS_INDEXES",DICT_HDR_SPACE,7);
+ table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, FALSE);
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);
@@ -333,6 +325,9 @@ dict_boot(void)
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
#endif
+#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
+#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
+#endif
table->id = DICT_INDEXES_ID;
dict_table_add_to_cache(table);
@@ -344,12 +339,12 @@ dict_boot(void)
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));
+ success = dict_index_add_to_cache(table, index, mtr_read_ulint(
+ dict_hdr + DICT_HDR_INDEXES, MLOG_4BYTES, &mtr));
+ ut_a(success);
/*-------------------------*/
- table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE,3);
+ table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, FALSE);
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);
@@ -365,10 +360,10 @@ dict_boot(void)
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);
index->id = DICT_FIELDS_ID;
- ut_a(dict_index_add_to_cache(table, index));
+ success = dict_index_add_to_cache(table, index, mtr_read_ulint(
+ dict_hdr + DICT_HDR_FIELDS, MLOG_4BYTES, &mtr));
+ ut_a(success);
mtr_commit(&mtr);
/*-------------------------*/
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index d9e89316613..c7d6ffd2c22 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -63,8 +63,8 @@ dict_create_sys_tables_tuple(
dfield = dtuple_get_nth_field(entry, 2);
ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, table->n_def);
-
+ mach_write_to_4(ptr, table->n_def
+ | ((ulint) table->comp << 31));
dfield_set_data(dfield, ptr, 4);
/* 5: TYPE -----------------------------*/
dfield = dtuple_get_nth_field(entry, 3);
@@ -82,16 +82,6 @@ dict_create_sys_tables_tuple(
dfield_set_data(dfield, ptr, 8);
/* 7: MIX_LEN --------------------------*/
- /* Track corruption reported on mailing list Jan 14, 2005 */
- if (table->mix_len != 0 && table->mix_len != 0x80000000) {
- fprintf(stderr,
-"InnoDB: Error: mix_len is %lu in table %s\n", (ulong)table->mix_len,
- table->name);
- mem_analyze_corruption((byte*)&(table->mix_len));
-
- ut_error;
- }
-
dfield = dtuple_get_nth_field(entry, 5);
ptr = mem_heap_alloc(heap, 4);
@@ -219,6 +209,8 @@ dict_build_table_def_step(
const char* path_or_name;
ibool is_path;
mtr_t mtr;
+ ulint i;
+ ulint row_len;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -230,6 +222,15 @@ dict_build_table_def_step(
thr_get_trx(thr)->table_id = table->id;
+ row_len = 0;
+ for (i = 0; i < table->n_def; i++) {
+ row_len += dtype_get_min_size(dict_col_get_type(
+ &table->cols[i]));
+ }
+ if (row_len > BTR_PAGE_MAX_REC_SIZE) {
+ return(DB_TOO_BIG_RECORD);
+ }
+
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
cluster_table = dict_table_get_low(table->cluster_name);
@@ -554,9 +555,7 @@ dict_build_index_def_step(
table in the same tablespace */
index->space = table->space;
-
- index->page_no = FIL_NULL;
-
+ node->page_no = FIL_NULL;
row = dict_create_sys_indexes_tuple(index, node->heap);
node->ind_row = row;
@@ -634,18 +633,18 @@ dict_create_index_tree_step(
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
- index->page_no = btr_create(index->type, index->space, index->id,
- &mtr);
+ node->page_no = btr_create(index->type, index->space, index->id,
+ table->comp, &mtr);
/* printf("Created a new index tree in space %lu root page %lu\n",
index->space, index->page_no); */
page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
DICT_SYS_INDEXES_PAGE_NO_FIELD,
- index->page_no, &mtr);
+ node->page_no, &mtr);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
- if (index->page_no == FIL_NULL) {
+ if (node->page_no == FIL_NULL) {
return(DB_OUT_OF_FILE_SPACE);
}
@@ -671,8 +670,9 @@ dict_drop_index_tree(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
-
- ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
+
+ ut_a(!dict_sys->sys_indexes->comp);
+ ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
ut_ad(len == 4);
@@ -684,8 +684,9 @@ dict_drop_index_tree(
return;
}
- ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
-
+ ptr = rec_get_nth_field_old(rec,
+ DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
+
ut_ad(len == 4);
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
@@ -710,8 +711,132 @@ dict_drop_index_tree(
root_page_no); */
btr_free_root(space, root_page_no, mtr);
+ page_rec_write_index_page_no(rec,
+ DICT_SYS_INDEXES_PAGE_NO_FIELD, FIL_NULL, mtr);
+}
+
+/***********************************************************************
+Truncates the index tree associated with a row in SYS_INDEXES table. */
+
+ulint
+dict_truncate_index_tree(
+/*=====================*/
+ /* out: new root page number, or
+ FIL_NULL on failure */
+ dict_table_t* table, /* in: the table the index belongs to */
+ rec_t* rec, /* in: record in the clustered index of
+ SYS_INDEXES table */
+ mtr_t* mtr) /* in: mtr having the latch
+ on the record page. The mtr may be
+ committed and restarted in this call. */
+{
+ ulint root_page_no;
+ ulint space;
+ ulint type;
+ dulint index_id;
+ byte* ptr;
+ ulint len;
+ ulint comp;
+ dict_index_t* index;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
+
+ ut_a(!dict_sys->sys_indexes->comp);
+ ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
+
+ ut_ad(len == 4);
+
+ root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
+
+ if (root_page_no == FIL_NULL) {
+ /* The tree has been freed. */
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Trying to TRUNCATE"
+ " a missing index of table %s!\n", table->name);
+ return(FIL_NULL);
+ }
+
+ ptr = rec_get_nth_field_old(rec,
+ DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
+
+ ut_ad(len == 4);
+
+ space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
+
+ if (!fil_tablespace_exists_in_mem(space)) {
+ /* It is a single table tablespace and the .ibd file is
+ missing: do nothing */
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Trying to TRUNCATE"
+ " a missing .ibd file of table %s!\n", table->name);
+ return(FIL_NULL);
+ }
+
+ ptr = rec_get_nth_field_old(rec,
+ DICT_SYS_INDEXES_TYPE_FIELD, &len);
+ ut_ad(len == 4);
+ type = mach_read_from_4(ptr);
+
+ ptr = rec_get_nth_field_old(rec, 1, &len);
+ ut_ad(len == 8);
+ index_id = mach_read_from_8(ptr);
+
+ /* We free all the pages but the root page first; this operation
+ may span several mini-transactions */
+
+ btr_free_but_not_root(space, root_page_no);
+
+ /* Then we free the root page in the same mini-transaction where
+ we create the b-tree and write its new root page number to the
+ appropriate field in the SYS_INDEXES record: this mini-transaction
+ marks the B-tree totally truncated */
+
+ comp = page_is_comp(btr_page_get(
+ space, root_page_no, RW_X_LATCH, mtr));
+
+ btr_free_root(space, root_page_no, mtr);
+ /* We will temporarily write FIL_NULL to the PAGE_NO field
+ in SYS_INDEXES, so that the database will not get into an
+ inconsistent state in case it crashes between the mtr_commit()
+ below and the following mtr_commit() call. */
page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
FIL_NULL, mtr);
+
+ /* We will need to commit the mini-transaction in order to avoid
+ deadlocks in the btr_create() call, because otherwise we would
+ be freeing and allocating pages in the same mini-transaction. */
+ mtr_commit(mtr);
+ /* mtr_commit() will invalidate rec. */
+ rec = NULL;
+ mtr_start(mtr);
+
+ /* Find the index corresponding to this SYS_INDEXES record. */
+ for (index = UT_LIST_GET_FIRST(table->indexes);
+ index;
+ index = UT_LIST_GET_NEXT(indexes, index)) {
+ if (!ut_dulint_cmp(index->id, index_id)) {
+ break;
+ }
+ }
+
+ root_page_no = btr_create(type, space, index_id, comp, mtr);
+ if (index) {
+ index->tree->page = root_page_no;
+ } else {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Index %lu %lu of table %s is missing\n"
+ "InnoDB: from the data dictionary during TRUNCATE!\n",
+ ut_dulint_get_high(index_id),
+ ut_dulint_get_low(index_id),
+ table->name);
+ }
+
+ return(root_page_no);
}
/*************************************************************************
@@ -770,6 +895,7 @@ ind_create_graph_create(
node->index = index;
node->state = INDEX_BUILD_INDEX_DEF;
+ node->page_no = FIL_NULL;
node->heap = mem_heap_create(256);
node->ind_def = ins_node_create(INS_DIRECT,
@@ -989,7 +1115,8 @@ dict_create_index_step(
if (node->state == INDEX_ADD_TO_CACHE) {
- success = dict_index_add_to_cache(node->table, node->index);
+ success = dict_index_add_to_cache(node->table, node->index,
+ node->page_no);
ut_a(success);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index b0327f77fd3..5eee57c250b 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -53,6 +53,7 @@ rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
/* Identifies generated InnoDB foreign key names */
static char dict_ibfk[] = "_ibfk_";
+#ifndef UNIV_HOTBACKUP
/**********************************************************************
Compares NUL-terminated UTF-8 strings case insensitively.
@@ -76,6 +77,7 @@ void
innobase_casedn_str(
/*================*/
char* a); /* in/out: string to put in lower case */
+#endif /* !UNIV_HOTBACKUP */
/**************************************************************************
Adds a column to the data dictionary hash table. */
@@ -824,23 +826,22 @@ dict_table_add_to_cache(
system columns. */
dict_mem_table_add_col(table, "DB_ROW_ID", DATA_SYS,
- DATA_ROW_ID, 0, 0);
+ DATA_ROW_ID | DATA_NOT_NULL, DATA_ROW_ID_LEN, 0);
#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);
+ DATA_TRX_ID | DATA_NOT_NULL, DATA_TRX_ID_LEN, 0);
#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);
+ DATA_ROLL_PTR | DATA_NOT_NULL, DATA_ROLL_PTR_LEN, 0);
#if DATA_ROLL_PTR != 2
#error "DATA_ROLL_PTR != 2"
#endif
-
dict_mem_table_add_col(table, "DB_MIX_ID", DATA_SYS,
- DATA_MIX_ID, 0, 0);
+ DATA_MIX_ID | DATA_NOT_NULL, DATA_MIX_ID_LEN, 0);
#if DATA_MIX_ID != 3
#error "DATA_MIX_ID != 3"
#endif
@@ -1385,8 +1386,9 @@ dict_index_add_to_cache(
/*====================*/
/* out: TRUE if success */
dict_table_t* table, /* in: table on which the index is */
- dict_index_t* index) /* in, own: index; NOTE! The index memory
+ dict_index_t* index, /* in, own: index; NOTE! The index memory
object is freed in this function! */
+ ulint page_no)/* in: root page number of the index */
{
dict_index_t* new_index;
dict_tree_t* tree;
@@ -1451,7 +1453,7 @@ dict_index_add_to_cache(
/* Increment the ord_part counts in columns which are ordering */
- if (index->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
n_ord = new_index->n_fields;
} else {
n_ord = dict_index_get_n_unique(new_index);
@@ -1472,16 +1474,15 @@ dict_index_add_to_cache(
tree = dict_index_get_tree(
UT_LIST_GET_FIRST(cluster->indexes));
new_index->tree = tree;
- new_index->page_no = tree->page;
} else {
/* Create an index tree memory object for the index */
- tree = dict_tree_create(new_index);
+ tree = dict_tree_create(new_index, page_no);
ut_ad(tree);
new_index->tree = tree;
}
- if (!(new_index->type & DICT_UNIVERSAL)) {
+ if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
new_index->stat_n_diff_key_vals =
mem_heap_alloc(new_index->heap,
@@ -1598,7 +1599,7 @@ dict_index_find_cols(
/***********************************************************************
Adds a column to index. */
-UNIV_INLINE
+
void
dict_index_add_col(
/*===============*/
@@ -1614,6 +1615,34 @@ dict_index_add_col(
field = dict_index_get_nth_field(index, index->n_def - 1);
field->col = col;
+ field->fixed_len = dtype_get_fixed_size(&col->type);
+
+ if (prefix_len && field->fixed_len > prefix_len) {
+ field->fixed_len = prefix_len;
+ }
+
+ /* Long fixed-length fields that need external storage are treated as
+ variable-length fields, so that the extern flag can be embedded in
+ the length word. */
+
+ if (field->fixed_len > DICT_MAX_COL_PREFIX_LEN) {
+ field->fixed_len = 0;
+ }
+
+ if (!(dtype_get_prtype(&col->type) & DATA_NOT_NULL)) {
+ index->n_nullable++;
+ }
+
+ if (index->n_def > 1) {
+ const dict_field_t* field2 =
+ dict_index_get_nth_field(index, index->n_def - 2);
+ field->fixed_offs = (!field2->fixed_len ||
+ field2->fixed_offs == ULINT_UNDEFINED)
+ ? ULINT_UNDEFINED
+ : field2->fixed_len + field2->fixed_offs;
+ } else {
+ field->fixed_offs = 0;
+ }
}
/***********************************************************************
@@ -1654,7 +1683,7 @@ dict_index_copy_types(
dtype_t* type;
ulint i;
- if (index->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
dtuple_set_types_binary(tuple, n_fields);
return;
@@ -1732,7 +1761,6 @@ dict_index_build_internal_clust(
new_index->n_user_defined_cols = index->n_fields;
new_index->id = index->id;
- new_index->page_no = index->page_no;
if (table->type != DICT_TABLE_ORDINARY) {
/* The index is mixed: copy common key prefix fields */
@@ -1751,7 +1779,7 @@ dict_index_build_internal_clust(
dict_index_copy(new_index, index, 0, index->n_fields);
}
- if (index->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
/* No fixed number of fields determines an entry uniquely */
new_index->n_uniq = ULINT_MAX;
@@ -1911,7 +1939,6 @@ dict_index_build_internal_non_clust(
new_index->n_user_defined_cols = index->n_fields;
new_index->id = index->id;
- new_index->page_no = index->page_no;
/* Copy fields from index to new_index */
dict_index_copy(new_index, index, 0, index->n_fields);
@@ -2080,6 +2107,7 @@ dict_foreign_find_index(
dict_index_t* types_idx)/* in: NULL or an index to whose types the
column types must match */
{
+#ifndef UNIV_HOTBACKUP
dict_index_t* index;
const char* col_name;
ulint i;
@@ -2124,6 +2152,12 @@ dict_foreign_find_index(
}
return(NULL);
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/**************************************************************************
@@ -2462,7 +2496,7 @@ dict_scan_id(
my_isspace(). Only after that, convert id names to UTF-8. */
b = (byte*)(*id);
- id_len = strlen(b);
+ id_len = strlen((char*) b);
if (id_len >= 3 && b[id_len - 1] == 0xA0
&& b[id_len - 2] == 0xC2) {
@@ -2491,6 +2525,7 @@ dict_scan_col(
const char** name) /* out,own: the column name; NULL if no name
was scannable */
{
+#ifndef UNIV_HOTBACKUP
dict_col_t* col;
ulint i;
@@ -2524,6 +2559,12 @@ dict_scan_col(
}
return(ptr);
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/*************************************************************************
@@ -2541,6 +2582,7 @@ dict_scan_table_name(
const char** ref_name)/* out,own: the table name;
NULL if no name was scannable */
{
+#ifndef UNIV_HOTBACKUP
const char* database_name = NULL;
ulint database_name_len = 0;
const char* table_name = NULL;
@@ -2622,6 +2664,12 @@ dict_scan_table_name(
*table = dict_table_get_low(ref);
return(ptr);
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/*************************************************************************
@@ -2823,8 +2871,12 @@ dict_create_foreign_constraints_low(
table2 can be written also with the database
name before it: test.table2; the default
database is the database of parameter name */
- const char* name) /* in: table full name in the normalized form
+ const char* name, /* in: table full name in the normalized form
database_name/table_name */
+ ibool reject_fks)
+ /* in: if TRUE, fail with error code
+ DB_CANNOT_ADD_CONSTRAINT if any foreign
+ keys are found. */
{
dict_table_t* table;
dict_table_t* referenced_table;
@@ -2946,6 +2998,18 @@ loop:
}
if (*ptr == '\0') {
+ /* The proper way to reject foreign keys for temporary
+ tables would be to split the lexing and syntactical
+ analysis of foreign key clauses from the actual adding
+ of them, so that ha_innodb.cc could first parse the SQL
+ command, determine if there are any foreign keys, and
+ if so, immediately reject the command if the table is a
+ temporary one. For now, this kludge will work. */
+ if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0))
+ {
+ return DB_CANNOT_ADD_CONSTRAINT;
+ }
+
/**********************************************************/
/* The following call adds the foreign key constraints
to the data dictionary system tables on disk */
@@ -3369,9 +3433,12 @@ dict_create_foreign_constraints(
name before it: test.table2; the
default database id the database of
parameter name */
- const char* name) /* in: table full name in the
+ const char* name, /* in: table full name in the
normalized form
database_name/table_name */
+ ibool reject_fks) /* in: if TRUE, fail with error
+ code DB_CANNOT_ADD_CONSTRAINT if
+ any foreign keys are found. */
{
char* str;
ulint err;
@@ -3380,7 +3447,8 @@ dict_create_foreign_constraints(
str = dict_strip_comments(sql_string);
heap = mem_heap_create(10000);
- err = dict_create_foreign_constraints_low(trx, heap, str, name);
+ err = dict_create_foreign_constraints_low(trx, heap, str, name,
+ reject_fks);
mem_heap_free(heap);
mem_free(str);
@@ -3570,9 +3638,10 @@ dict_tree_t*
dict_tree_create(
/*=============*/
/* out, own: created tree */
- dict_index_t* index) /* in: the index for which to create: in the
+ dict_index_t* index, /* in: the index for which to create: in the
case of a mixed tree, this should be the
index of the cluster object */
+ ulint page_no)/* in: root page number of the index */
{
dict_tree_t* tree;
@@ -3582,7 +3651,7 @@ dict_tree_create(
tree->type = index->type;
tree->space = index->space;
- tree->page = index->page_no;
+ tree->page = page_no;
tree->id = index->id;
@@ -3633,12 +3702,13 @@ dict_tree_find_index_low(
table = index->table;
if ((index->type & DICT_CLUSTERED)
- && (table->type != DICT_TABLE_ORDINARY)) {
+ && UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) {
/* Get the mix id of the record */
+ ut_a(!table->comp);
mix_id = mach_dulint_read_compressed(
- rec_get_nth_field(rec, table->mix_len, &len));
+ rec_get_nth_field_old(rec, table->mix_len, &len));
while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
@@ -3717,6 +3787,29 @@ dict_tree_find_index_for_tuple(
return(index);
}
+/***********************************************************************
+Checks if a table which is a mixed cluster member owns a record. */
+
+ibool
+dict_is_mixed_table_rec(
+/*====================*/
+ /* out: TRUE if the record belongs to this
+ table */
+ dict_table_t* table, /* in: table in a mixed cluster */
+ rec_t* rec) /* in: user record in the clustered index */
+{
+ byte* mix_id_field;
+ ulint len;
+
+ ut_ad(!table->comp);
+
+ mix_id_field = rec_get_nth_field_old(rec,
+ table->mix_len, &len);
+
+ return(len == table->mix_id_len
+ && !ut_memcmp(table->mix_id_buf, mix_id_field, len));
+}
+
/**************************************************************************
Checks that a tuple has n_fields_cmp value in a sensible range, so that
no comparison can occur with the page number field in a node pointer. */
@@ -3765,13 +3858,14 @@ dict_tree_build_node_ptr(
ind = dict_tree_find_index_low(tree, rec);
- if (tree->type & DICT_UNIVERSAL) {
+ if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
/* In a universal index tree, we take the whole record as
the node pointer if the reord is on the leaf level,
on non-leaf levels we remove the last field, which
contains the page number of the child page */
- n_unique = rec_get_n_fields(rec);
+ ut_a(!ind->table->comp);
+ n_unique = rec_get_n_fields_old(rec);
if (level > 0) {
ut_a(n_unique > 1);
@@ -3800,9 +3894,11 @@ dict_tree_build_node_ptr(
field = dtuple_get_nth_field(tuple, n_unique);
dfield_set_data(field, buf, 4);
- dtype_set(dfield_get_type(field), DATA_SYS_CHILD, 0, 0, 0);
+ dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4, 0);
- rec_copy_prefix_to_dtuple(tuple, rec, n_unique, heap);
+ rec_copy_prefix_to_dtuple(tuple, rec, ind, n_unique, heap);
+ dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple) |
+ REC_STATUS_NODE_PTR);
ut_ad(dtuple_check_typed(tuple));
@@ -3819,27 +3915,27 @@ dict_tree_copy_rec_order_prefix(
/* out: pointer to the prefix record */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to copy prefix */
+ ulint* n_fields,/* out: number of fields copied */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size)/* in/out: buffer size */
{
- dict_index_t* ind;
- rec_t* order_rec;
- ulint n_fields;
-
- ind = dict_tree_find_index_low(tree, rec);
+ dict_index_t* index;
+ ulint n;
- n_fields = dict_index_get_n_unique_in_tree(ind);
-
- if (tree->type & DICT_UNIVERSAL) {
+ UNIV_PREFETCH_R(rec);
+ index = dict_tree_find_index_low(tree, rec);
- n_fields = rec_get_n_fields(rec);
+ if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
+ ut_a(!index->table->comp);
+ n = rec_get_n_fields_old(rec);
+ } else {
+ n = dict_index_get_n_unique_in_tree(index);
}
- order_rec = rec_copy_prefix_to_buf(rec, n_fields, buf, buf_size);
-
- return(order_rec);
-}
+ *n_fields = n;
+ return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
+}
/**************************************************************************
Builds a typed data tuple out of a physical record. */
@@ -3850,21 +3946,21 @@ dict_tree_build_data_tuple(
/* out, own: data tuple */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build data tuple */
+ ulint n_fields,/* in: number of data fields */
mem_heap_t* heap) /* in: memory heap where tuple created */
{
dtuple_t* tuple;
dict_index_t* ind;
- ulint n_fields;
ind = dict_tree_find_index_low(tree, rec);
- n_fields = rec_get_n_fields(rec);
+ ut_ad(ind->table->comp || n_fields <= rec_get_n_fields_old(rec));
tuple = dtuple_create(heap, n_fields);
dict_index_copy_types(tuple, ind, n_fields);
- rec_copy_prefix_to_dtuple(tuple, rec, n_fields, heap);
+ rec_copy_prefix_to_dtuple(tuple, rec, ind, n_fields, heap);
ut_ad(dtuple_check_typed(tuple));
@@ -3882,6 +3978,27 @@ dict_index_calc_min_rec_len(
ulint sum = 0;
ulint i;
+ if (UNIV_LIKELY(index->table->comp)) {
+ ulint nullable = 0;
+ sum = REC_N_NEW_EXTRA_BYTES;
+ for (i = 0; i < dict_index_get_n_fields(index); i++) {
+ dtype_t*t = dict_index_get_nth_type(index, i);
+ ulint size = dtype_get_fixed_size(t);
+ sum += size;
+ if (!size) {
+ size = dtype_get_len(t);
+ sum += size < 128 ? 1 : 2;
+ }
+ if (!(dtype_get_prtype(t) & DATA_NOT_NULL))
+ nullable++;
+ }
+
+ /* round the NULL flags up to full bytes */
+ sum += (nullable + 7) / 8;
+
+ return(sum);
+ }
+
for (i = 0; i < dict_index_get_n_fields(index); i++) {
sum += dtype_get_fixed_size(dict_index_get_nth_type(index, i));
}
@@ -3892,7 +4009,7 @@ dict_index_calc_min_rec_len(
sum += dict_index_get_n_fields(index);
}
- sum += REC_N_EXTRA_BYTES;
+ sum += REC_N_OLD_EXTRA_BYTES;
return(sum);
}
@@ -4181,9 +4298,11 @@ dict_index_print_low(
putc('\n', stderr);
-/* btr_print_size(tree); */
+#ifdef UNIV_BTR_PRINT
+ btr_print_size(tree);
-/* btr_print_tree(tree, 7); */
+ btr_print_tree(tree, 7);
+#endif /* UNIV_BTR_PRINT */
}
/**************************************************************************
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index 0d58823a2ea..9bafcf33553 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -8,6 +8,9 @@ Created 4/24/1996 Heikki Tuuri
*******************************************************/
#include "dict0load.h"
+#ifndef UNIV_HOTBACKUP
+#include "mysql_version.h"
+#endif /* !UNIV_HOTBACKUP */
#ifdef UNIV_NONINL
#include "dict0load.ic"
@@ -55,6 +58,7 @@ dict_get_first_table_name_in_db(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
+ ut_a(!sys_tables->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -77,7 +81,7 @@ loop:
return(NULL);
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
if (len < strlen(name)
|| ut_memcmp(name, field, strlen(name)) != 0) {
@@ -90,7 +94,7 @@ loop:
return(NULL);
}
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
@@ -163,9 +167,9 @@ loop:
return;
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
@@ -180,7 +184,7 @@ loop:
if (table == NULL) {
fputs("InnoDB: Failed to load table ", stderr);
- ut_print_namel(stderr, NULL, field, len);
+ ut_print_namel(stderr, NULL, (char*) field, len);
putc('\n', stderr);
} else {
/* The table definition was corrupt if there
@@ -231,6 +235,7 @@ dict_check_tablespaces_and_store_max_id(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
+ ut_a(!sys_tables->comp);
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
TRUE, &mtr);
@@ -257,15 +262,15 @@ loop:
return;
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
char* name = mem_strdupl((char*) field, len);
- field = rec_get_nth_field(rec, 9, &len);
+ field = rec_get_nth_field_old(rec, 9, &len);
ut_a(len == 4);
space_id = mach_read_from_4(field);
@@ -338,6 +343,7 @@ dict_load_columns(
sys_columns = dict_table_get_low("SYS_COLUMNS");
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
+ ut_a(!sys_columns->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -356,28 +362,27 @@ dict_load_columns(
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
- ut_a(!rec_get_deleted_flag(rec));
-
- field = rec_get_nth_field(rec, 0, &len);
+ ut_a(!rec_get_deleted_flag(rec, sys_columns->comp));
+
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
ut_ad(len == 4);
ut_a(i == mach_read_from_4(field));
ut_a(0 == ut_strcmp("NAME",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_columns), 4))->name));
+ dict_index_get_nth_field(sys_index, 4))->name));
- field = rec_get_nth_field(rec, 4, &len);
+ field = rec_get_nth_field_old(rec, 4, &len);
name = mem_heap_strdupl(heap, (char*) field, len);
- field = rec_get_nth_field(rec, 5, &len);
+ field = rec_get_nth_field_old(rec, 5, &len);
mtype = mach_read_from_4(field);
- field = rec_get_nth_field(rec, 6, &len);
+ field = rec_get_nth_field_old(rec, 6, &len);
prtype = mach_read_from_4(field);
if (dtype_is_non_binary_string_type(mtype, prtype)
@@ -389,15 +394,14 @@ dict_load_columns(
data_mysql_default_charset_coll);
}
- field = rec_get_nth_field(rec, 7, &len);
+ field = rec_get_nth_field_old(rec, 7, &len);
col_len = mach_read_from_4(field);
ut_a(0 == ut_strcmp("PREC",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_columns), 8))->name));
+ dict_index_get_nth_field(sys_index, 8))->name));
- field = rec_get_nth_field(rec, 8, &len);
+ field = rec_get_nth_field_old(rec, 8, &len);
prec = mach_read_from_4(field);
dict_mem_table_add_col(table, name, mtype, prtype, col_len,
@@ -462,6 +466,7 @@ dict_load_fields(
sys_fields = dict_table_get_low("SYS_FIELDS");
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
+ ut_a(!sys_fields->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -479,15 +484,15 @@ dict_load_fields(
rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, sys_fields->comp)) {
dict_load_report_deleted_index(table->name, i);
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
ut_a(ut_memcmp(buf, field, len) == 0);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
ut_a(len == 4);
/* The next field stores the field position in the index
@@ -513,10 +518,9 @@ dict_load_fields(
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));
+ dict_index_get_nth_field(sys_index, 4))->name));
- field = rec_get_nth_field(rec, 4, &len);
+ field = rec_get_nth_field_old(rec, 4, &len);
dict_mem_index_add_field(index,
mem_heap_strdupl(heap, (char*) field, len), 0, prefix_len);
@@ -575,6 +579,7 @@ dict_load_indexes(
sys_indexes = dict_table_get_low("SYS_INDEXES");
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
+ ut_a(!sys_indexes->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -595,14 +600,14 @@ dict_load_indexes(
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
if (ut_memcmp(buf, field, len) != 0) {
break;
}
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, table->comp)) {
dict_load_report_deleted_index(table->name,
ULINT_UNDEFINED);
@@ -612,33 +617,31 @@ dict_load_indexes(
return(FALSE);
}
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
ut_ad(len == 8);
id = mach_read_from_8(field);
ut_a(0 == ut_strcmp("NAME",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_indexes), 4))->name));
-
- field = rec_get_nth_field(rec, 4, &name_len);
+ dict_index_get_nth_field(sys_index, 4))->name));
+
+ field = rec_get_nth_field_old(rec, 4, &name_len);
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
- field = rec_get_nth_field(rec, 5, &len);
+ field = rec_get_nth_field_old(rec, 5, &len);
n_fields = mach_read_from_4(field);
- field = rec_get_nth_field(rec, 6, &len);
+ field = rec_get_nth_field_old(rec, 6, &len);
type = mach_read_from_4(field);
- field = rec_get_nth_field(rec, 7, &len);
+ field = rec_get_nth_field_old(rec, 7, &len);
space = mach_read_from_4(field);
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));
+ dict_index_get_nth_field(sys_index, 8))->name));
- field = rec_get_nth_field(rec, 8, &len);
+ field = rec_get_nth_field_old(rec, 8, &len);
page_no = mach_read_from_4(field);
if (page_no == FIL_NULL) {
@@ -680,12 +683,10 @@ dict_load_indexes(
} else {
index = dict_mem_index_create(table->name, name_buf,
space, type, n_fields);
- index->page_no = page_no;
index->id = id;
dict_load_fields(table, index, heap);
-
- dict_index_add_to_cache(table, index);
+ dict_index_add_to_cache(table, index, page_no);
}
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
@@ -741,6 +742,7 @@ dict_load_table(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
+ ut_a(!sys_tables->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -753,7 +755,7 @@ dict_load_table(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec)) {
+ || rec_get_deleted_flag(rec, sys_tables->comp)) {
/* Not found */
btr_pcur_close(&pcur);
@@ -763,11 +765,10 @@ dict_load_table(
return(NULL);
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the table name in record is the searched one */
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
- err_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
mem_heap_free(heap);
@@ -777,10 +778,9 @@ dict_load_table(
ut_a(0 == ut_strcmp("SPACE",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_tables), 9))->name));
+ dict_index_get_nth_field(sys_index, 9))->name));
- field = rec_get_nth_field(rec, 9, &len);
+ field = rec_get_nth_field_old(rec, 9, &len);
space = mach_read_from_4(field);
/* Check if the tablespace exists and has the right name */
@@ -812,49 +812,44 @@ dict_load_table(
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));
+ dict_index_get_nth_field(sys_index, 4))->name));
- field = rec_get_nth_field(rec, 4, &len);
+ field = rec_get_nth_field_old(rec, 4, &len);
n_cols = mach_read_from_4(field);
- if (n_cols & 0x80000000UL) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: table %s is in the new compact format\n"
- "InnoDB: of MySQL 5.0.3 or later\n", name);
- goto err_exit;
- }
- table = dict_mem_table_create(name, space, n_cols);
+ /* The high-order bit of N_COLS is the "compact format" flag. */
+ table = dict_mem_table_create(name, space,
+ n_cols & ~0x80000000UL,
+ !!(n_cols & 0x80000000UL));
table->ibd_file_missing = ibd_file_missing;
ut_a(0 == ut_strcmp("ID",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_tables), 3))->name));
+ dict_index_get_nth_field(sys_index, 3))->name));
- field = rec_get_nth_field(rec, 3, &len);
+ field = rec_get_nth_field_old(rec, 3, &len);
table->id = mach_read_from_8(field);
- field = rec_get_nth_field(rec, 5, &len);
+ field = rec_get_nth_field_old(rec, 5, &len);
table->type = mach_read_from_4(field);
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
ut_error;
#if 0 /* clustered tables have not been implemented yet */
- field = rec_get_nth_field(rec, 6, &len);
+ field = rec_get_nth_field_old(rec, 6, &len);
table->mix_id = mach_read_from_8(field);
- field = rec_get_nth_field(rec, 8, &len);
+ field = rec_get_nth_field_old(rec, 8, &len);
table->cluster_name = mem_heap_strdupl(heap, (char*) field, len);
#endif
}
if ((table->type == DICT_TABLE_CLUSTER)
|| (table->type == DICT_TABLE_CLUSTER_MEMBER)) {
-
- field = rec_get_nth_field(rec, 7, &len);
+
+ field = rec_get_nth_field_old(rec, 7, &len);
+ ut_a(len == 4);
table->mix_len = mach_read_from_4(field);
}
@@ -933,6 +928,7 @@ dict_load_table_on_id(
sys_tables = dict_sys->sys_tables;
sys_table_ids = dict_table_get_next_index(
dict_table_get_first_index(sys_tables));
+ ut_a(!sys_tables->comp);
heap = mem_heap_create(256);
tuple = dtuple_create(heap, 1);
@@ -949,7 +945,7 @@ dict_load_table_on_id(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec)) {
+ || rec_get_deleted_flag(rec, sys_tables->comp)) {
/* Not found */
btr_pcur_close(&pcur);
@@ -964,7 +960,7 @@ dict_load_table_on_id(
table ID and NAME */
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
/* Check if the table id in record is the one searched for */
@@ -978,7 +974,7 @@ dict_load_table_on_id(
}
/* Now we get the table name from the record */
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
/* Load the table definition to memory */
table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
@@ -1046,6 +1042,7 @@ dict_load_foreign_cols(
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
+ ut_a(!sys_foreign_cols->comp);
tuple = dtuple_create(foreign->heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -1060,21 +1057,21 @@ dict_load_foreign_cols(
rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
- ut_a(!rec_get_deleted_flag(rec));
-
- field = rec_get_nth_field(rec, 0, &len);
+ ut_a(!rec_get_deleted_flag(rec, sys_foreign_cols->comp));
+
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == ut_strlen(id));
ut_a(ut_memcmp(id, field, len) == 0);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
ut_a(len == 4);
ut_a(i == mach_read_from_4(field));
- field = rec_get_nth_field(rec, 4, &len);
+ field = rec_get_nth_field_old(rec, 4, &len);
foreign->foreign_col_names[i] =
mem_heap_strdupl(foreign->heap, (char*) field, len);
- field = rec_get_nth_field(rec, 5, &len);
+ field = rec_get_nth_field_old(rec, 5, &len);
foreign->referenced_col_names[i] =
mem_heap_strdupl(foreign->heap, (char*) field, len);
@@ -1118,6 +1115,7 @@ dict_load_foreign(
sys_foreign = dict_table_get_low("SYS_FOREIGN");
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
+ ut_a(!sys_foreign->comp);
tuple = dtuple_create(heap2, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -1130,7 +1128,7 @@ dict_load_foreign(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec)) {
+ || rec_get_deleted_flag(rec, sys_foreign->comp)) {
/* Not found */
fprintf(stderr,
@@ -1144,7 +1142,7 @@ dict_load_foreign(
return(DB_ERROR);
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the id in record is the searched one */
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
@@ -1167,7 +1165,8 @@ dict_load_foreign(
foreign = dict_mem_foreign_create();
- foreign->n_fields = mach_read_from_4(rec_get_nth_field(rec, 5, &len));
+ foreign->n_fields =
+ mach_read_from_4(rec_get_nth_field_old(rec, 5, &len));
ut_a(len == 4);
@@ -1178,11 +1177,11 @@ dict_load_foreign(
foreign->id = mem_heap_strdup(foreign->heap, id);
- field = rec_get_nth_field(rec, 3, &len);
+ field = rec_get_nth_field_old(rec, 3, &len);
foreign->foreign_table_name =
mem_heap_strdupl(foreign->heap, (char*) field, len);
-
- field = rec_get_nth_field(rec, 4, &len);
+
+ field = rec_get_nth_field_old(rec, 4, &len);
foreign->referenced_table_name =
mem_heap_strdupl(foreign->heap, (char*) field, len);
@@ -1250,6 +1249,7 @@ dict_load_foreigns(
return(DB_ERROR);
}
+ ut_a(!sys_foreign->comp);
mtr_start(&mtr);
/* Get the secondary index based on FOR_NAME from table
@@ -1281,7 +1281,7 @@ loop:
name and a foreign constraint ID */
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the table name in the record is the one searched for; the
following call does the comparison in the latin1_swedish_ci
@@ -1304,13 +1304,13 @@ loop:
goto next_rec;
}
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, sys_foreign->comp)) {
goto next_rec;
}
/* Now we get a foreign key constraint id */
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
id = mem_heap_strdupl(heap, (char*) field, len);
btr_pcur_store_position(&pcur, &mtr);
diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c
index 1d45585aac1..eec35310039 100644
--- a/innobase/dict/dict0mem.c
+++ b/innobase/dict/dict0mem.c
@@ -35,12 +35,14 @@ dict_mem_table_create(
the table is placed; this parameter is
ignored if the table is made a member of
a cluster */
- ulint n_cols) /* in: number of columns */
+ ulint n_cols, /* in: number of columns */
+ ibool comp) /* in: TRUE=compact page format */
{
dict_table_t* table;
mem_heap_t* heap;
ut_ad(name);
+ ut_ad(comp == FALSE || comp == TRUE);
heap = mem_heap_create(DICT_HEAP_SIZE);
@@ -54,6 +56,7 @@ dict_mem_table_create(
table->space = space;
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
+ table->comp = comp;
table->n_def = 0;
table->n_cols = n_cols + DATA_N_SYS_COLS;
table->mem_fix = 0;
@@ -110,7 +113,8 @@ dict_mem_cluster_create(
{
dict_table_t* cluster;
- cluster = dict_mem_table_create(name, space, n_cols);
+ /* Clustered tables cannot work with the compact record format. */
+ cluster = dict_mem_table_create(name, space, n_cols, FALSE);
cluster->type = DICT_TABLE_CLUSTER;
cluster->mix_len = mix_len;
@@ -197,7 +201,7 @@ dict_mem_index_create(
index->name = mem_heap_strdup(heap, index_name);
index->table_name = table_name;
index->table = NULL;
- index->n_def = 0;
+ index->n_def = index->n_nullable = 0;
index->n_fields = n_fields;
index->fields = mem_heap_alloc(heap, 1 + n_fields
* sizeof(dict_field_t));
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index e83d2fcde32..20f522c1a60 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -89,6 +89,9 @@ but in the MySQL Embedded Server Library and ibbackup it is not the default
directory, and we must set the base file path explicitly */
const char* fil_path_to_mysql_datadir = ".";
+/* The number of fsyncs done to the log */
+ulint fil_n_log_flushes = 0;
+
ulint fil_n_pending_log_flushes = 0;
ulint fil_n_pending_tablespace_flushes = 0;
@@ -96,7 +99,6 @@ ulint fil_n_pending_tablespace_flushes = 0;
fil_addr_t fil_addr_null = {FIL_NULL, 0};
/* File node of a tablespace or the log data space */
-typedef struct fil_node_struct fil_node_t;
struct fil_node_struct {
fil_space_t* space; /* backpointer to the space where this node
belongs */
@@ -517,7 +519,7 @@ fil_node_open_file(
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Error: the size of single-table tablespace file %s\n"
-"InnoDB: is only %lu %lu, should be at least %lu!", node->name,
+"InnoDB: is only %lu %lu, should be at least %lu!\n", node->name,
(ulong) size_high,
(ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE));
@@ -687,8 +689,8 @@ fil_try_to_close_file_in_LRU(
ut_print_filename(stderr, node->name);
fprintf(stderr,
", because mod_count %ld != fl_count %ld\n",
- (ulong) node->modification_counter,
- (ulong) node->flush_counter);
+ (long) node->modification_counter,
+ (long) node->flush_counter);
}
node = UT_LIST_GET_PREV(LRU, node);
@@ -1652,30 +1654,38 @@ fil_op_write_log(
mtr_t* mtr) /* in: mini-transaction handle */
{
byte* log_ptr;
+ ulint len;
+
+ log_ptr = mlog_open(mtr, 11 + 2);
+
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery:
+ in that case mlog_open returns NULL */
+ return;
+ }
- log_ptr = mlog_open(mtr, 30);
-
log_ptr = mlog_write_initial_log_record_for_file_op(type, space_id, 0,
log_ptr, mtr);
/* Let us store the strings as null-terminated for easier readability
and handling */
- mach_write_to_2(log_ptr, ut_strlen(name) + 1);
+ len = strlen(name) + 1;
+
+ mach_write_to_2(log_ptr, len);
log_ptr += 2;
-
mlog_close(mtr, log_ptr);
- mlog_catenate_string(mtr, (byte*) name, ut_strlen(name) + 1);
+ mlog_catenate_string(mtr, (byte*) name, len);
if (type == MLOG_FILE_RENAME) {
- log_ptr = mlog_open(mtr, 30);
- mach_write_to_2(log_ptr, ut_strlen(new_name) + 1);
+ ulint len = strlen(new_name) + 1;
+ log_ptr = mlog_open(mtr, 2 + len);
+ ut_a(log_ptr);
+ mach_write_to_2(log_ptr, len);
log_ptr += 2;
-
mlog_close(mtr, log_ptr);
- mlog_catenate_string(mtr, (byte*) new_name,
- ut_strlen(new_name) + 1);
+ mlog_catenate_string(mtr, (byte*) new_name, len);
}
}
#endif
@@ -2612,12 +2622,12 @@ fil_open_single_table_tablespace(
fputs("!\n"
"InnoDB: Have you moved InnoDB .ibd files around without using the\n"
"InnoDB: commands DISCARD TABLESPACE and IMPORT TABLESPACE?\n"
-"InnoDB: It is also possible that this is a table created with\n"
-"InnoDB: CREATE TEMPORARY TABLE, and MySQL removed the .ibd file for this.\n"
+"InnoDB: It is also possible that this is a temporary table #sql...,\n"
+"InnoDB: and MySQL removed the .ibd file for this.\n"
"InnoDB: Please refer to\n"
"InnoDB:"
" http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
-"InnoDB: how to resolve the issue.\n", stderr);
+"InnoDB: for how to resolve the issue.\n", stderr);
mem_free(filepath);
@@ -2657,7 +2667,7 @@ fil_open_single_table_tablespace(
"InnoDB: Please refer to\n"
"InnoDB:"
" http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
-"InnoDB: how to resolve the issue.\n", (ulong) space_id, (ulong) id);
+"InnoDB: for how to resolve the issue.\n", (ulong) space_id, (ulong) id);
ret = FALSE;
@@ -3292,7 +3302,7 @@ fil_space_for_table_exists_in_mem(
ut_print_filename(stderr, name);
fprintf(stderr, "\n"
"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
-"InnoDB: but tablespace with that id does not exist. There is\n"
+"InnoDB: but a tablespace with that id does not exist. There is\n"
"InnoDB: a tablespace of name %s and id %lu, though. Have\n"
"InnoDB: you deleted or moved .ibd files?\n",
(ulong) id, namespace->name,
@@ -3303,7 +3313,7 @@ fil_space_for_table_exists_in_mem(
"InnoDB: Please refer to\n"
"InnoDB:"
" http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
-"InnoDB: how to resolve the issue.\n", stderr);
+"InnoDB: for how to resolve the issue.\n", stderr);
mem_free(path);
mutex_exit(&(system->mutex));
@@ -3317,7 +3327,7 @@ fil_space_for_table_exists_in_mem(
ut_print_filename(stderr, name);
fprintf(stderr, "\n"
"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
-"InnoDB: but tablespace with that id has name %s.\n"
+"InnoDB: but the tablespace with that id has name %s.\n"
"InnoDB: Have you deleted or moved .ibd files?\n", (ulong) id, space->name);
if (namespace != NULL) {
@@ -3815,6 +3825,12 @@ fil_io(
mode = OS_AIO_NORMAL;
}
+ if (type == OS_FILE_READ) {
+ srv_data_read+= len;
+ } else if (type == OS_FILE_WRITE) {
+ srv_data_written+= len;
+ }
+
/* Reserve the fil_system mutex and make sure that we can open at
least one file while holding it, if the file is not already open */
@@ -4016,7 +4032,7 @@ fil_aio_wait(
if (os_aio_use_native_aio) {
srv_set_io_thread_op_info(segment, "native aio handle");
#ifdef WIN_ASYNC_IO
- ret = os_aio_windows_handle(segment, 0, (void**) &fil_node,
+ ret = os_aio_windows_handle(segment, 0, &fil_node,
&message, &type);
#elif defined(POSIX_ASYNC_IO)
ret = os_aio_posix_handle(segment, &fil_node, &message);
@@ -4027,7 +4043,7 @@ fil_aio_wait(
} else {
srv_set_io_thread_op_info(segment, "simulated aio handle");
- ret = os_aio_simulated_handle(segment, (void**) &fil_node,
+ ret = os_aio_simulated_handle(segment, &fil_node,
&message, &type);
}
@@ -4100,6 +4116,7 @@ fil_flush(
fil_n_pending_tablespace_flushes++;
} else {
fil_n_pending_log_flushes++;
+ fil_n_log_flushes++;
}
#ifdef __WIN__
if (node->is_raw_disk) {
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index e1621cc2765..ad4228f6797 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -910,7 +910,7 @@ fsp_header_init(
if (space == 0) {
fsp_fill_free_list(FALSE, space, header, mtr);
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, space,
- ut_dulint_add(DICT_IBUF_ID_MIN, space), mtr);
+ ut_dulint_add(DICT_IBUF_ID_MIN, space), FALSE, mtr);
} else {
fsp_fill_free_list(TRUE, space, header, mtr);
}
@@ -2325,7 +2325,6 @@ fseg_alloc_free_page_low(
dulint seg_id;
ulint used;
ulint reserved;
- fil_addr_t first;
xdes_t* descr; /* extent of the hinted page */
ulint ret_page; /* the allocated page offset, FIL_NULL
if could not be allocated */
@@ -2428,6 +2427,8 @@ fseg_alloc_free_page_low(
} else if (reserved - used > 0) {
/* 5. We take any unused page from the segment
==============================================*/
+ fil_addr_t first;
+
if (flst_get_len(seg_inode + FSEG_NOT_FULL, mtr) > 0) {
first = flst_get_first(seg_inode + FSEG_NOT_FULL,
mtr);
@@ -2435,6 +2436,7 @@ fseg_alloc_free_page_low(
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
} else {
ut_error;
+ return(FIL_NULL);
}
ret_descr = xdes_lst_get_descriptor(space, first, mtr);
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index 2191cdc0ee6..d7fa48b6e66 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -46,7 +46,7 @@ Note that contary to what we planned in the 1990's, there will only be one
insert buffer tree, and that is in the system tablespace of InnoDB.
1. The first field is the space id.
-2. The second field is a one-byte marker which differentiates records from
+2. The second field is a one-byte marker (0) which differentiates records from
the < 4.1.x storage format.
3. The third field is the page number.
4. The fourth field contains the type info, where we have also added 2 bytes to
@@ -55,7 +55,14 @@ insert buffer tree, and that is in the system tablespace of InnoDB.
can use in the binary search on the index page in the ibuf merge phase.
5. The rest of the fields contain the fields of the actual index record.
-*/
+In versions >= 5.0.3:
+
+The first byte of the fourth field is an additional marker (0) if the record
+is in the compact format. The presence of this marker can be detected by
+looking at the length of the field modulo DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE.
+
+The high-order bit of the character set field in the type info is the
+"nullable" flag for the field. */
/* PREVENTING DEADLOCKS IN THE INSERT BUFFER SYSTEM
@@ -525,8 +532,8 @@ ibuf_data_init_for_space(
ibuf_exit();
sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space);
-
- table = dict_mem_table_create(buf, space, 2);
+ /* use old-style record format for the insert buffer */
+ table = dict_mem_table_create(buf, space, 2, FALSE);
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);
@@ -541,11 +548,9 @@ ibuf_data_init_for_space(
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;
-
index->id = ut_dulint_add(DICT_IBUF_ID_MIN, space);
- dict_index_add_to_cache(table, index);
+ dict_index_add_to_cache(table, index, FSP_IBUF_TREE_ROOT_PAGE_NO);
data->index = dict_table_get_first_index(table);
@@ -1049,20 +1054,20 @@ ibuf_rec_get_page_no(
ulint len;
ut_ad(ibuf_inside());
- ut_ad(rec_get_n_fields(rec) > 2);
+ ut_ad(rec_get_n_fields_old(rec) > 2);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
- field = rec_get_nth_field(rec, 2, &len);
+ field = rec_get_nth_field_old(rec, 2, &len);
} else {
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
}
ut_a(len == 4);
@@ -1084,15 +1089,15 @@ ibuf_rec_get_space(
ulint len;
ut_ad(ibuf_inside());
- ut_ad(rec_get_n_fields(rec) > 2);
+ ut_ad(rec_get_n_fields_old(rec) > 2);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == 4);
return(mach_read_from_4(field));
@@ -1105,6 +1110,162 @@ ibuf_rec_get_space(
}
/************************************************************************
+Creates a dummy index for inserting a record to a non-clustered index.
+*/
+static
+dict_index_t*
+ibuf_dummy_index_create(
+/*====================*/
+ /* out: dummy index */
+ ulint n, /* in: number of fields */
+ ibool comp) /* in: TRUE=use compact record format */
+{
+ dict_table_t* table;
+ dict_index_t* index;
+ table = dict_mem_table_create("IBUF_DUMMY",
+ DICT_HDR_SPACE, n, comp);
+ index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY",
+ DICT_HDR_SPACE, 0, n);
+ index->table = table;
+ /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
+ index->cached = TRUE;
+ return(index);
+}
+/************************************************************************
+Add a column to the dummy index */
+static
+void
+ibuf_dummy_index_add_col(
+/*====================*/
+ dict_index_t* index, /* in: dummy index */
+ dtype_t* type, /* in: the data type of the column */
+ ulint len) /* in: length of the column */
+{
+ ulint i = index->table->n_def;
+ dict_mem_table_add_col(index->table, "DUMMY",
+ dtype_get_mtype(type),
+ dtype_get_prtype(type),
+ dtype_get_len(type),
+ dtype_get_prec(type));
+ dict_index_add_col(index,
+ dict_table_get_nth_col(index->table, i), 0, len);
+}
+/************************************************************************
+Deallocates a dummy index for inserting a record to a non-clustered index.
+*/
+static
+void
+ibuf_dummy_index_free(
+/*====================*/
+ dict_index_t* index) /* in: dummy index */
+{
+ dict_table_t* table = index->table;
+ mem_heap_free(index->heap);
+ mutex_free(&(table->autoinc_mutex));
+ mem_heap_free(table->heap);
+}
+
+/*************************************************************************
+Builds the entry to insert into a non-clustered index when we have the
+corresponding record in an ibuf index. */
+static
+dtuple_t*
+ibuf_build_entry_from_ibuf_rec(
+/*===========================*/
+ /* out, own: entry to insert to
+ a non-clustered index; NOTE that
+ as we copy pointers to fields in
+ ibuf_rec, the caller must hold a
+ latch to the ibuf_rec page as long
+ as the entry is used! */
+ rec_t* ibuf_rec, /* in: record in an insert buffer */
+ mem_heap_t* heap, /* in: heap where built */
+ dict_index_t** pindex) /* out, own: dummy index that
+ describes the entry */
+{
+ dtuple_t* tuple;
+ dfield_t* field;
+ ulint n_fields;
+ byte* types;
+ const byte* data;
+ ulint len;
+ ulint i;
+ dict_index_t* index;
+
+ data = rec_get_nth_field_old(ibuf_rec, 1, &len);
+
+ if (len > 1) {
+ /* This a < 4.1.x format record */
+
+ ut_a(trx_doublewrite_must_reset_space_ids);
+ ut_a(!trx_sys_multiple_tablespace_format);
+
+ n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
+ tuple = dtuple_create(heap, n_fields);
+ types = rec_get_nth_field_old(ibuf_rec, 1, &len);
+
+ ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
+
+ for (i = 0; i < n_fields; i++) {
+ field = dtuple_get_nth_field(tuple, i);
+
+ data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
+
+ dfield_set_data(field, data, len);
+
+ dtype_read_for_order_and_null_size(
+ dfield_get_type(field),
+ types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
+ }
+
+ *pindex = ibuf_dummy_index_create(n_fields, FALSE);
+ return(tuple);
+ }
+
+ /* This a >= 4.1.x format record */
+
+ ut_a(trx_sys_multiple_tablespace_format);
+ ut_a(*data == 0);
+ ut_a(rec_get_n_fields_old(ibuf_rec) > 4);
+
+ n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
+
+ tuple = dtuple_create(heap, n_fields);
+
+ types = rec_get_nth_field_old(ibuf_rec, 3, &len);
+
+ ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1);
+ index = ibuf_dummy_index_create(n_fields,
+ len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+
+ if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
+ /* compact record format */
+ len--;
+ ut_a(*types == 0);
+ types++;
+ }
+
+ ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+
+ for (i = 0; i < n_fields; i++) {
+ field = dtuple_get_nth_field(tuple, i);
+
+ data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
+
+ dfield_set_data(field, data, len);
+
+ dtype_new_read_for_order_and_null_size(
+ dfield_get_type(field),
+ types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+
+ ibuf_dummy_index_add_col(index, dfield_get_type(field), len);
+ }
+
+ *pindex = index;
+ return(tuple);
+}
+
+/************************************************************************
Returns the space taken by a stored non-clustered index entry if converted to
an index record. */
static
@@ -1125,43 +1286,60 @@ ibuf_rec_get_volume(
ulint i;
ut_ad(ibuf_inside());
- ut_ad(rec_get_n_fields(ibuf_rec) > 2);
-
- data = rec_get_nth_field(ibuf_rec, 1, &len);
+ ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
+
+ data = rec_get_nth_field_old(ibuf_rec, 1, &len);
if (len > 1) {
- /* < 4.1.x format record */
+ /* < 4.1.x format record */
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
- n_fields = rec_get_n_fields(ibuf_rec) - 2;
+ n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
- types = rec_get_nth_field(ibuf_rec, 1, &len);
+ types = rec_get_nth_field_old(ibuf_rec, 1, &len);
ut_ad(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
} else {
- /* >= 4.1.x format record */
+ /* >= 4.1.x format record */
ut_a(trx_sys_multiple_tablespace_format);
- new_format = TRUE;
+ ut_a(*data == 0);
+
+ types = rec_get_nth_field_old(ibuf_rec, 3, &len);
+
+ ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1);
+ if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
+ /* compact record format */
+ ulint volume;
+ dict_index_t* dummy_index;
+ mem_heap_t* heap = mem_heap_create(500);
+ dtuple_t* entry =
+ ibuf_build_entry_from_ibuf_rec(
+ ibuf_rec, heap, &dummy_index);
+ volume = rec_get_converted_size(dummy_index, entry);
+ ibuf_dummy_index_free(dummy_index);
+ mem_heap_free(heap);
+ return(volume + page_dir_calc_reserved_space(1));
+ }
- n_fields = rec_get_n_fields(ibuf_rec) - 4;
+ n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
- types = rec_get_nth_field(ibuf_rec, 3, &len);
+ new_format = TRUE;
}
for (i = 0; i < n_fields; i++) {
if (new_format) {
- data = rec_get_nth_field(ibuf_rec, i + 4, &len);
+ data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
dtype_new_read_for_order_and_null_size(&dtype,
- types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+ types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
} else {
- data = rec_get_nth_field(ibuf_rec, i + 2, &len);
+ data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
dtype_read_for_order_and_null_size(&dtype,
- types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
+ types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
}
if (len == UNIV_SQL_NULL) {
@@ -1187,6 +1365,7 @@ ibuf_entry_build(
must be kept because we copy pointers to its
fields */
dtuple_t* entry, /* in: entry for a non-clustered index */
+ ibool comp, /* in: flag: TRUE=compact record format */
ulint space, /* in: space id */
ulint page_no,/* in: index page number where entry should
be inserted */
@@ -1202,11 +1381,14 @@ ibuf_entry_build(
/* Starting from 4.1.x, we have to build a tuple whose
(1) first field is the space id,
- (2) the second field a single marker byte to tell that this
+ (2) the second field a single marker byte (0) to tell that this
is a new format record,
(3) the third contains the page number, and
(4) the fourth contains the relevent type information of each data
- field,
+ field; the length of this field % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE is
+ (a) 0 for b-trees in the old format, and
+ (b) 1 for b-trees in the compact format, the first byte of the field
+ being the marker (0);
(5) and the rest of the fields are copied from entry. All fields
in the tuple are ordered like the type binary in our insert buffer
tree. */
@@ -1247,10 +1429,15 @@ ibuf_entry_build(
dfield_set_data(field, buf, 4);
+ ut_ad(comp == 0 || comp == 1);
/* Store the type info in buf2, and add the fields from entry to
tuple */
buf2 = mem_heap_alloc(heap, n_fields
- * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+ * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+ + comp);
+ if (comp) {
+ *buf2++ = 0; /* write the compact format indicator */
+ }
for (i = 0; i < n_fields; i++) {
/* We add 4 below because we have the 4 extra fields at the
start of an ibuf record */
@@ -1268,8 +1455,13 @@ ibuf_entry_build(
field = dtuple_get_nth_field(tuple, 3);
+ if (comp) {
+ buf2--;
+ }
+
dfield_set_data(field, buf2, n_fields
- * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+ * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+ + comp);
/* Set all the types in the new tuple binary */
dtuple_set_types_binary(tuple, n_fields + 4);
@@ -1278,88 +1470,6 @@ ibuf_entry_build(
}
/*************************************************************************
-Builds the entry to insert into a non-clustered index when we have the
-corresponding record in an ibuf index. */
-static
-dtuple_t*
-ibuf_build_entry_from_ibuf_rec(
-/*===========================*/
- /* out, own: entry to insert to
- a non-clustered index; NOTE that
- as we copy pointers to fields in
- ibuf_rec, the caller must hold a
- latch to the ibuf_rec page as long
- as the entry is used! */
- rec_t* ibuf_rec, /* in: record in an insert buffer */
- mem_heap_t* heap) /* in: heap where built */
-{
- dtuple_t* tuple;
- dfield_t* field;
- ulint n_fields;
- byte* types;
- byte* data;
- ulint len;
- ulint i;
-
- data = rec_get_nth_field(ibuf_rec, 1, &len);
-
- if (len > 1) {
- /* This a < 4.1.x format record */
-
- ut_a(trx_doublewrite_must_reset_space_ids);
- ut_a(!trx_sys_multiple_tablespace_format);
-
- n_fields = rec_get_n_fields(ibuf_rec) - 2;
- tuple = dtuple_create(heap, n_fields);
- types = rec_get_nth_field(ibuf_rec, 1, &len);
-
- ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
-
- for (i = 0; i < n_fields; i++) {
- field = dtuple_get_nth_field(tuple, i);
-
- data = rec_get_nth_field(ibuf_rec, i + 2, &len);
-
- dfield_set_data(field, data, len);
-
- dtype_read_for_order_and_null_size(
- dfield_get_type(field),
- types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
- }
-
- return(tuple);
- }
-
- /* This a >= 4.1.x format record */
-
- ut_a(trx_sys_multiple_tablespace_format);
-
- ut_a(rec_get_n_fields(ibuf_rec) > 4);
-
- n_fields = rec_get_n_fields(ibuf_rec) - 4;
-
- tuple = dtuple_create(heap, n_fields);
-
- types = rec_get_nth_field(ibuf_rec, 3, &len);
-
- ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
-
- for (i = 0; i < n_fields; i++) {
- field = dtuple_get_nth_field(tuple, i);
-
- data = rec_get_nth_field(ibuf_rec, i + 4, &len);
-
- dfield_set_data(field, data, len);
-
- dtype_new_read_for_order_and_null_size(
- dfield_get_type(field),
- types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
- }
-
- return(tuple);
-}
-
-/*************************************************************************
Builds a search tuple used to search buffered inserts for an index page.
This is for < 4.1.x format records */
static
@@ -1779,7 +1889,7 @@ ibuf_get_merge_page_nos(
contract the tree, FALSE if this is called
when a single page becomes full and we look
if it pays to read also nearby pages */
- rec_t* first_rec,/* in: record from which we read up and down
+ rec_t* rec, /* in: record from which we read up and down
in the chain of records */
ulint* space_ids,/* in/out: space id's of the pages */
ib_longlong* space_versions,/* in/out: tablespace version
@@ -1797,47 +1907,42 @@ ibuf_get_merge_page_nos(
ulint first_space_id;
ulint rec_page_no;
ulint rec_space_id;
- rec_t* rec;
ulint sum_volumes;
ulint volume_for_page;
ulint rec_volume;
ulint limit;
- page_t* page;
ulint n_pages;
*n_stored = 0;
limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool->curr_size / 4);
- page = buf_frame_align(first_rec);
-
- if (first_rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
- first_rec = page_rec_get_prev(first_rec);
+ rec = page_rec_get_prev(rec);
}
- if (first_rec == page_get_infimum_rec(page)) {
+ if (page_rec_is_infimum(rec)) {
- first_rec = page_rec_get_next(first_rec);
+ rec = page_rec_get_next(rec);
}
- if (first_rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
return(0);
}
- rec = first_rec;
- first_page_no = ibuf_rec_get_page_no(first_rec);
- first_space_id = ibuf_rec_get_space(first_rec);
+ first_page_no = ibuf_rec_get_page_no(rec);
+ first_space_id = ibuf_rec_get_space(rec);
n_pages = 0;
prev_page_no = 0;
prev_space_id = 0;
- /* Go backwards from the first_rec until we reach the border of the
+ /* Go backwards from the first rec until we reach the border of the
'merge area', or the page start or the limit of storeable pages is
reached */
- while ((rec != page_get_infimum_rec(page)) && (n_pages < limit)) {
+ while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
rec_page_no = ibuf_rec_get_page_no(rec);
rec_space_id = ibuf_rec_get_space(rec);
@@ -1872,7 +1977,7 @@ ibuf_get_merge_page_nos(
volume_for_page = 0;
while (*n_stored < limit) {
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
/* When no more records available, mark this with
another 'impossible' pair of space id, page no */
rec_page_no = 1;
@@ -2047,8 +2152,7 @@ loop:
mutex_exit(&ibuf_mutex);
sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
- space_ids, space_versions, page_nos,
- &n_stored);
+ space_ids, space_versions, page_nos, &n_stored);
#ifdef UNIV_IBUF_DEBUG
/* fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
sync, n_stored, sum_sizes); */
@@ -2202,12 +2306,12 @@ ibuf_get_volume_buffered(
page = buf_frame_align(rec);
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
rec = page_rec_get_prev(rec);
}
for (;;) {
- if (rec == page_get_infimum_rec(page)) {
+ if (page_rec_is_infimum(rec)) {
break;
}
@@ -2242,7 +2346,7 @@ ibuf_get_volume_buffered(
rec = page_rec_get_prev(rec);
for (;;) {
- if (rec == page_get_infimum_rec(prev_page)) {
+ if (page_rec_is_infimum(rec)) {
/* We cannot go to yet a previous page, because we
do not have the x-latch on it, and cannot acquire one
@@ -2265,12 +2369,12 @@ ibuf_get_volume_buffered(
count_later:
rec = btr_pcur_get_rec(pcur);
- if (rec != page_get_supremum_rec(page)) {
+ if (!page_rec_is_supremum(rec)) {
rec = page_rec_get_next(rec);
}
for (;;) {
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
break;
}
@@ -2305,7 +2409,7 @@ count_later:
rec = page_rec_get_next(rec);
for (;;) {
- if (rec == page_get_supremum_rec(next_page)) {
+ if (page_rec_is_supremum(rec)) {
/* We give up */
@@ -2344,6 +2448,7 @@ ibuf_update_max_tablespace_id(void)
ibuf_data = fil_space_get_ibuf_data(0);
ibuf_index = ibuf_data->index;
+ ut_a(!ibuf_index->table->comp);
ibuf_enter();
@@ -2360,7 +2465,7 @@ ibuf_update_max_tablespace_id(void)
} else {
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == 4);
@@ -2479,7 +2584,7 @@ ibuf_insert_low(
ibuf_enter();
}
- entry_size = rec_get_converted_size(entry);
+ entry_size = rec_get_converted_size(index, entry);
heap = mem_heap_create(512);
@@ -2487,7 +2592,8 @@ ibuf_insert_low(
the first fields and the type information for other fields, and which
will be inserted to the insert buffer. */
- ibuf_entry = ibuf_entry_build(entry, space, page_no, heap);
+ ibuf_entry = ibuf_entry_build(entry, index->table->comp,
+ space, page_no, heap);
/* Open a cursor to the insert buffer tree to calculate if we can add
the new entry to it without exceeding the free space limit for the
@@ -2532,8 +2638,8 @@ ibuf_insert_low(
do_merge = TRUE;
ibuf_get_merge_page_nos(FALSE, btr_pcur_get_rec(&pcur),
- space_ids, space_versions, page_nos,
- &n_stored);
+ space_ids, space_versions,
+ page_nos, &n_stored);
goto function_exit;
}
@@ -2656,8 +2762,8 @@ ibuf_insert(
ut_a(!(index->type & DICT_CLUSTERED));
- if (rec_get_converted_size(entry)
- >= page_get_free_space_of_empty() / 2) {
+ if (rec_get_converted_size(index, entry)
+ >= page_get_free_space_of_empty(index->table->comp) / 2) {
return(FALSE);
}
@@ -2692,6 +2798,7 @@ ibuf_insert_to_index_page(
dtuple_t* entry, /* in: buffered entry to insert */
page_t* page, /* in: index page where the buffered entry
should be placed */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mtr */
{
page_cur_t page_cur;
@@ -2703,13 +2810,21 @@ ibuf_insert_to_index_page(
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
- if (rec_get_n_fields(page_rec_get_next(page_get_infimum_rec(page)))
- != dtuple_get_n_fields(entry)) {
-
- fprintf(stderr,
+ if (UNIV_UNLIKELY(index->table->comp != (ibool)!!page_is_comp(page))) {
+ fputs(
"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
-"InnoDB: but the number of fields does not match!\n");
+"InnoDB: but the 'compact' flag does not match!\n", stderr);
+ goto dump;
+ }
+ rec = page_rec_get_next(page_get_infimum_rec(page));
+
+ if (UNIV_UNLIKELY(rec_get_n_fields(rec, index)
+ != dtuple_get_n_fields(entry))) {
+ fputs(
+"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
+"InnoDB: but the number of fields does not match!\n", stderr);
+ dump:
buf_page_print(page);
dtuple_print(stderr, entry);
@@ -2723,31 +2838,34 @@ ibuf_insert_to_index_page(
return;
}
- low_match = page_cur_search(page, entry, PAGE_CUR_LE, &page_cur);
+ low_match = page_cur_search(page, index, entry,
+ PAGE_CUR_LE, &page_cur);
if (low_match == dtuple_get_n_fields(entry)) {
rec = page_cur_get_rec(&page_cur);
btr_cur_del_unmark_for_ibuf(rec, mtr);
} else {
- rec = page_cur_tuple_insert(&page_cur, entry, mtr);
+ rec = page_cur_tuple_insert(&page_cur, entry, index, mtr);
if (rec == NULL) {
/* If the record did not fit, reorganize */
- btr_page_reorganize(page, mtr);
+ btr_page_reorganize(page, index, mtr);
- page_cur_search(page, entry, PAGE_CUR_LE, &page_cur);
+ page_cur_search(page, index, entry,
+ PAGE_CUR_LE, &page_cur);
/* This time the record must fit */
- if (!page_cur_tuple_insert(&page_cur, entry, mtr)) {
+ if (UNIV_UNLIKELY(!page_cur_tuple_insert(
+ &page_cur, entry, index, mtr))) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: Insert buffer insert fails; page free %lu, dtuple size %lu\n",
(ulong) page_get_max_insert_size(page, 1),
- (ulong) rec_get_converted_size(entry));
+ (ulong) rec_get_converted_size(index, entry));
fputs("InnoDB: Cannot insert index record ",
stderr);
dtuple_print(stderr, entry);
@@ -2836,17 +2954,20 @@ ibuf_delete_rec(
"InnoDB: ibuf record inserted to page %lu\n", (ulong) page_no);
fflush(stderr);
- rec_print(stderr, btr_pcur_get_rec(pcur));
- rec_print(stderr, pcur->old_rec);
+ rec_print_old(stderr, btr_pcur_get_rec(pcur));
+ rec_print_old(stderr, pcur->old_rec);
dtuple_print(stderr, search_tuple);
- rec_print(stderr, page_rec_get_next(btr_pcur_get_rec(pcur)));
+ rec_print_old(stderr,
+ page_rec_get_next(btr_pcur_get_rec(pcur)));
fflush(stderr);
btr_pcur_commit_specify_mtr(pcur, mtr);
fputs("InnoDB: Validating insert buffer tree:\n", stderr);
- ut_a(btr_validate_tree(ibuf_data->index->tree));
+ if (!btr_validate_tree(ibuf_data->index->tree, NULL)) {
+ ut_error;
+ }
fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr);
@@ -3075,7 +3196,7 @@ loop:
if (corruption_noticed) {
fputs("InnoDB: Discarding record\n ", stderr);
- rec_print(stderr, ibuf_rec);
+ rec_print_old(stderr, ibuf_rec);
fputs("\n from the insert buffer!\n\n", stderr);
} else if (page) {
/* Now we have at pcur a record which should be
@@ -3083,19 +3204,22 @@ loop:
copies pointers to fields in ibuf_rec, and we must
keep the latch to the ibuf_rec page until the
insertion is finished! */
-
- dulint max_trx_id = page_get_max_trx_id(
+ dict_index_t* dummy_index;
+ dulint max_trx_id = page_get_max_trx_id(
buf_frame_align(ibuf_rec));
page_update_max_trx_id(page, max_trx_id);
- entry = ibuf_build_entry_from_ibuf_rec(ibuf_rec, heap);
+ entry = ibuf_build_entry_from_ibuf_rec(ibuf_rec,
+ heap, &dummy_index);
#ifdef UNIV_IBUF_DEBUG
- volume += rec_get_converted_size(entry)
+ volume += rec_get_converted_size(dummy_index, entry)
+ page_dir_calc_reserved_space(1);
ut_a(volume <= 4 * UNIV_PAGE_SIZE
/ IBUF_PAGE_SIZE_PER_FREE_SPACE);
#endif
- ibuf_insert_to_index_page(entry, page, &mtr);
+ ibuf_insert_to_index_page(entry, page,
+ dummy_index, &mtr);
+ ibuf_dummy_index_free(dummy_index);
}
n_inserts++;
diff --git a/innobase/include/Makefile.am b/innobase/include/Makefile.am
index 102d25566da..eb1e3b72877 100644
--- a/innobase/include/Makefile.am
+++ b/innobase/include/Makefile.am
@@ -49,7 +49,7 @@ noinst_HEADERS = btr0btr.h btr0btr.ic btr0cur.h btr0cur.ic \
thr0loc.h thr0loc.ic trx0purge.h trx0purge.ic trx0rec.h \
trx0rec.ic trx0roll.h trx0roll.ic trx0rseg.h trx0rseg.ic \
trx0sys.h trx0sys.ic trx0trx.h trx0trx.ic trx0types.h \
- trx0undo.h trx0undo.ic univ.i \
+ trx0undo.h trx0undo.ic trx0xa.h univ.i \
usr0sess.h usr0sess.ic usr0types.h ut0byte.h ut0byte.ic \
ut0dbg.h ut0lst.h ut0mem.h ut0mem.ic ut0rnd.h ut0rnd.ic \
ut0sort.h ut0ut.h ut0ut.ic
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index 8606fcd2a5c..d28b0b129a1 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -23,16 +23,6 @@ special big record storage structure */
#define BTR_PAGE_MAX_REC_SIZE (UNIV_PAGE_SIZE / 2 - 200)
-/* Maximum key size in a B-tree: the records on non-leaf levels must be
-shorter than this */
-
-#define BTR_PAGE_MAX_KEY_SIZE 1024
-
-/* If data in page drops below this limit, we try to compress it.
-NOTE! The value has to be > 2 * BTR_MAX_KEY_SIZE */
-
-#define BTR_COMPRESS_LIMIT (UNIV_PAGE_SIZE / 4 + 1);
-
/* Latching modes for the search function (in btr0cur.*) */
#define BTR_SEARCH_LEAF RW_S_LATCH
#define BTR_MODIFY_LEAF RW_X_LATCH
@@ -155,7 +145,8 @@ ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
/* out: child node address */
- rec_t* rec); /* in: node pointer record */
+ rec_t* rec, /* in: node pointer record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/****************************************************************
Creates the root node for a new index tree. */
@@ -167,6 +158,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
+ ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr); /* in: mini-transaction handle */
/****************************************************************
Frees a B-tree except the root page, which MUST be freed after this
@@ -210,8 +202,9 @@ Reorganizes an index page. */
void
btr_page_reorganize(
/*================*/
- page_t* page, /* in: page to be reorganized */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: page to be reorganized */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Decides if the page should be split at the convergence point of
inserts converging to left. */
@@ -273,6 +266,7 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
+ ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes on the upper level the node pointer to a page. */
@@ -332,6 +326,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
+ ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
@@ -340,11 +335,12 @@ Parses a redo log record of reorganizing a page. */
byte*
btr_parse_page_reorganize(
/*======================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/******************************************************************
Gets the number of pages in a B-tree. */
@@ -392,6 +388,7 @@ btr_page_free_low(
page_t* page, /* in: page to be freed, x-latched */
ulint level, /* in: page level */
mtr_t* mtr); /* in: mtr */
+#ifdef UNIV_BTR_PRINT
/*****************************************************************
Prints size info of a B-tree. */
@@ -408,6 +405,7 @@ btr_print_tree(
dict_tree_t* tree, /* in: tree */
ulint width); /* in: print this many entries from start
and end */
+#endif /* UNIV_BTR_PRINT */
/****************************************************************
Checks the size and number of fields in a record based on the definition of
the index. */
@@ -428,7 +426,8 @@ ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
- dict_tree_t* tree); /* in: tree */
+ dict_tree_t* tree, /* in: tree */
+ trx_t* trx); /* in: transaction or NULL */
#define BTR_N_LEAF_PAGES 1
#define BTR_TOTAL_SIZE 2
diff --git a/innobase/include/btr0btr.ic b/innobase/include/btr0btr.ic
index b0aa0756307..a0860b1c3a7 100644
--- a/innobase/include/btr0btr.ic
+++ b/innobase/include/btr0btr.ic
@@ -183,26 +183,27 @@ ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
/* out: child node address */
- rec_t* rec) /* in: node pointer record */
+ rec_t* rec, /* in: node pointer record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n_fields;
byte* field;
ulint len;
ulint page_no;
- n_fields = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
/* The child address is in the last field */
- field = rec_get_nth_field(rec, n_fields - 1, &len);
+ field = rec_get_nth_field(rec, offsets,
+ rec_offs_n_fields(offsets) - 1, &len);
ut_ad(len == 4);
page_no = mach_read_from_4(field);
- if (page_no == 0) {
+ if (UNIV_UNLIKELY(page_no == 0)) {
fprintf(stderr,
"InnoDB: a nonsensical page number 0 in a node ptr record at offset %lu\n",
- (unsigned long)(rec - buf_frame_align(rec)));
+ (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE));
buf_page_print(buf_frame_align(rec));
}
diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h
index f1334656d53..352d1739b6a 100644
--- a/innobase/include/btr0cur.h
+++ b/innobase/include/btr0cur.h
@@ -34,7 +34,7 @@ page_cur_t*
btr_cur_get_page_cur(
/*=================*/
/* out: pointer to page cursor component */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the record pointer of a tree cursor. */
UNIV_INLINE
@@ -42,14 +42,14 @@ rec_t*
btr_cur_get_rec(
/*============*/
/* out: pointer to record */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Invalidates a tree cursor by setting record pointer to NULL. */
UNIV_INLINE
void
btr_cur_invalidate(
/*===============*/
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the page of a tree cursor. */
UNIV_INLINE
@@ -57,7 +57,7 @@ page_t*
btr_cur_get_page(
/*=============*/
/* out: pointer to page */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the tree of a cursor. */
UNIV_INLINE
@@ -65,7 +65,7 @@ dict_tree_t*
btr_cur_get_tree(
/*=============*/
/* out: tree */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Positions a tree cursor at a given record. */
UNIV_INLINE
@@ -283,8 +283,8 @@ only used by the insert buffer insert merge mechanism. */
void
btr_cur_del_unmark_for_ibuf(
/*========================*/
- rec_t* rec, /* in: record to delete unmark */
- mtr_t* mtr); /* in: mtr */
+ rec_t* rec, /* in: record to delete unmark */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Tries to compress a page of the tree on the leaf level. It is assumed
that mtr holds an x-latch on the tree and on the cursor page. To avoid
@@ -361,10 +361,11 @@ Parses a redo log record of updating a record in-place. */
byte*
btr_cur_parse_update_in_place(
/*==========================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ page_t* page, /* in: page or NULL */
+ dict_index_t* index); /* in: index corresponding to page */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a clustered
index record. */
@@ -372,10 +373,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_clust_rec(
/*=================================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: index corresponding to page */
+ page_t* page); /* in: page or NULL */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a secondary
index record. */
@@ -383,10 +385,10 @@ index record. */
byte*
btr_cur_parse_del_mark_set_sec_rec(
/*===============================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ page_t* page); /* in: page or NULL */
/***********************************************************************
Estimates the number of rows in a given index range. */
@@ -417,9 +419,10 @@ to free the field. */
void
btr_cur_mark_extern_inherited_fields(
/*=================================*/
- rec_t* rec, /* in: record in a clustered index */
- upd_t* update, /* in: update vector */
- mtr_t* mtr); /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update, /* in: update vector */
+ mtr_t* mtr); /* in: mtr */
/***********************************************************************
The complement of the previous function: in an update entry may inherit
some externally stored fields from a record. We must mark them as inherited
@@ -456,6 +459,7 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
mtr_t* local_mtr); /* in: mtr containing the latch to
@@ -496,6 +500,7 @@ btr_rec_free_externally_stored_fields(
dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
inherited fields */
@@ -510,6 +515,7 @@ btr_rec_copy_externally_stored_field(
/*=================================*/
/* out: the field copied to heap */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint no, /* in: field number */
ulint* len, /* out: length of the field */
mem_heap_t* heap); /* in: mem heap */
@@ -540,10 +546,10 @@ ulint
btr_push_update_extern_fields(
/*==========================*/
/* out: number of values stored in ext_vect */
- ulint* ext_vect, /* in: array of ulints, must be preallocated
- to have place for all fields in rec */
- rec_t* rec, /* in: record */
- upd_t* update); /* in: update vector */
+ ulint* ext_vect,/* in: array of ulints, must be preallocated
+ to have space for all fields in rec */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update);/* in: update vector or NULL */
/*######################################################################*/
diff --git a/innobase/include/btr0cur.ic b/innobase/include/btr0cur.ic
index a3a04b60c45..bf8a6efb68d 100644
--- a/innobase/include/btr0cur.ic
+++ b/innobase/include/btr0cur.ic
@@ -52,7 +52,9 @@ btr_cur_get_page(
/* out: pointer to page */
btr_cur_t* cursor) /* in: tree cursor */
{
- return(buf_frame_align(page_cur_get_rec(&(cursor->page_cur))));
+ page_t* page = buf_frame_align(page_cur_get_rec(&(cursor->page_cur)));
+ ut_ad(!!page_is_comp(page) == cursor->index->table->comp);
+ return(page);
}
/*************************************************************
@@ -134,17 +136,15 @@ btr_cur_can_delete_without_compress(
/* out: TRUE if can be deleted without
recommended compression */
btr_cur_t* cursor, /* in: btr cursor */
+ ulint rec_size,/* in: rec_get_size(btr_cur_get_rec(cursor))*/
mtr_t* mtr) /* in: mtr */
{
- ulint rec_size;
page_t* page;
ut_ad(mtr_memo_contains(mtr, buf_block_align(
btr_cur_get_page(cursor)),
MTR_MEMO_PAGE_X_FIX));
- rec_size = rec_get_size(btr_cur_get_rec(cursor));
-
page = btr_cur_get_page(cursor);
if ((page_get_data_size(page) - rec_size < BTR_CUR_PAGE_COMPRESS_LIMIT)
diff --git a/innobase/include/btr0pcur.h b/innobase/include/btr0pcur.h
index 9339eb5d0ee..eb3822aab7a 100644
--- a/innobase/include/btr0pcur.h
+++ b/innobase/include/btr0pcur.h
@@ -462,6 +462,7 @@ struct btr_pcur_struct{
contains an initial segment of the
latest record cursor was positioned
either on, before, or after */
+ ulint old_n_fields; /* number of fields in old_rec */
ulint rel_pos; /* BTR_PCUR_ON, BTR_PCUR_BEFORE, or
BTR_PCUR_AFTER, depending on whether
cursor was on, before, or after the
diff --git a/innobase/include/btr0sea.h b/innobase/include/btr0sea.h
index ce4140ecf92..78e88a24083 100644
--- a/innobase/include/btr0sea.h
+++ b/innobase/include/btr0sea.h
@@ -77,8 +77,10 @@ parameters as page (this often happens when a page is split). */
void
btr_search_move_or_delete_hash_entries(
/*===================================*/
- page_t* new_page, /* in: records are copied to this page */
- page_t* page); /* in: index page */
+ page_t* new_page, /* in: records are copied
+ to this page */
+ page_t* page, /* in: index page */
+ dict_index_t* index); /* in: record descriptor */
/************************************************************************
Drops a page hash index. */
@@ -129,8 +131,8 @@ Validates the search system. */
ibool
btr_search_validate(void);
-/*=====================*/
-
+/*======================*/
+ /* out: TRUE if ok */
/* Search info directions */
#define BTR_SEA_NO_DIRECTION 1
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index 53599d03c73..ae8d0411c12 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -52,11 +52,17 @@ Created 11/5/1995 Heikki Tuuri
/* Modes for buf_page_get_known_nowait */
#define BUF_MAKE_YOUNG 51
#define BUF_KEEP_OLD 52
+/* Magic value to use instead of checksums when they are disabled */
+#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
extern buf_pool_t* buf_pool; /* The buffer pool of the database */
+#ifdef UNIV_DEBUG
extern ibool buf_debug_prints;/* If this is set TRUE, the program
prints info whenever read or flush
occurs */
+#endif /* UNIV_DEBUG */
+extern ulint srv_buf_pool_write_requests; /* variable to count write request
+ issued */
/************************************************************************
Creates the buffer pool. */
@@ -378,10 +384,10 @@ Returns the value of the modify clock. The caller must have an s-lock
or x-lock on the block. */
UNIV_INLINE
dulint
-buf_frame_get_modify_clock(
+buf_block_get_modify_clock(
/*=======================*/
/* out: value */
- buf_frame_t* frame); /* in: pointer to a frame */
+ buf_block_t* block); /* in: block */
/************************************************************************
Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value
@@ -476,12 +482,20 @@ buf_pool_is_block(
/*==============*/
/* out: TRUE if pointer to block */
void* ptr); /* in: pointer to memory */
+#ifdef UNIV_DEBUG
/*************************************************************************
Validates the buffer pool data structure. */
ibool
buf_validate(void);
/*==============*/
+/*************************************************************************
+Prints info of the buffer pool data structure. */
+
+void
+buf_print(void);
+/*============*/
+#endif /* UNIV_DEBUG */
/************************************************************************
Prints a page to stderr. */
@@ -490,11 +504,11 @@ buf_page_print(
/*===========*/
byte* read_buf); /* in: a database page */
/*************************************************************************
-Prints info of the buffer pool data structure. */
+Returns the number of latched pages in the buffer pool. */
-void
-buf_print(void);
-/*============*/
+ulint
+buf_get_latched_pages_number(void);
+/*==============================*/
/*************************************************************************
Returns the number of pending buf pool ios. */
@@ -731,6 +745,8 @@ struct buf_block_struct{
buffer pool which are index pages,
but this flag is not set because
we do not keep track of all pages */
+ dict_index_t* index; /* index for which the adaptive
+ hash index has been created */
/* 2. Page flushing fields */
UT_LIST_NODE_T(buf_block_t) flush_list;
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index 681a0ef000a..d949254d47d 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -11,10 +11,11 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0rea.h"
#include "mtr0mtr.h"
+#ifdef UNIV_DEBUG
extern ulint buf_dbg_counter; /* This is used to insert validation
operations in execution in the
debug version */
-
+#endif /* UNIV_DEBUG */
/************************************************************************
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
@@ -26,12 +27,8 @@ buf_block_peek_if_too_old(
/* out: TRUE if should be made younger */
buf_block_t* block) /* in: block to make younger */
{
- if (buf_pool->freed_page_clock >= block->freed_page_clock
- + 1 + (buf_pool->curr_size / 1024)) {
- return(TRUE);
- }
-
- return(FALSE);
+ return(buf_pool->freed_page_clock >= block->freed_page_clock
+ + 1 + (buf_pool->curr_size / 1024));
}
/*************************************************************************
@@ -210,8 +207,8 @@ buf_block_align(
frame_zero = buf_pool->frame_zero;
- if ((ulint)ptr < (ulint)frame_zero
- || (ulint)ptr > (ulint)(buf_pool->high_end)) {
+ if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero)
+ || UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -246,8 +243,8 @@ buf_frame_align(
frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
- if (((ulint)frame < (ulint)(buf_pool->frame_zero))
- || (ulint)frame >= (ulint)(buf_pool->high_end)) {
+ if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero))
+ || UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -485,17 +482,11 @@ Returns the value of the modify clock. The caller must have an s-lock
or x-lock on the block. */
UNIV_INLINE
dulint
-buf_frame_get_modify_clock(
+buf_block_get_modify_clock(
/*=======================*/
/* out: value */
- buf_frame_t* frame) /* in: pointer to a frame */
+ buf_block_t* block) /* in: block */
{
- buf_block_t* block;
-
- ut_ad(frame);
-
- block = buf_block_align(frame);
-
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
diff --git a/innobase/include/buf0flu.ic b/innobase/include/buf0flu.ic
index d6dbdcc0865..9a8a021e029 100644
--- a/innobase/include/buf0flu.ic
+++ b/innobase/include/buf0flu.ic
@@ -61,6 +61,8 @@ buf_flush_note_modification(
ut_ad(ut_dulint_cmp(block->oldest_modification,
mtr->start_lsn) <= 0);
}
+
+ ++srv_buf_pool_write_requests;
}
/************************************************************************
diff --git a/innobase/include/buf0lru.h b/innobase/include/buf0lru.h
index 45164dd561e..fb29b44ba98 100644
--- a/innobase/include/buf0lru.h
+++ b/innobase/include/buf0lru.h
@@ -122,6 +122,7 @@ void
buf_LRU_make_block_old(
/*===================*/
buf_block_t* block); /* in: control block */
+#ifdef UNIV_DEBUG
/**************************************************************************
Validates the LRU list. */
@@ -134,6 +135,7 @@ Prints the LRU list. */
void
buf_LRU_print(void);
/*===============*/
+#endif /* UNIV_DEBUG */
#ifndef UNIV_NONINL
#include "buf0lru.ic"
diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h
index 02c874836fd..7e9692eca5a 100644
--- a/innobase/include/data0type.h
+++ b/innobase/include/data0type.h
@@ -12,7 +12,7 @@ Created 1/16/1996 Heikki Tuuri
#include "univ.i"
extern ulint data_mysql_default_charset_coll;
-extern ulint data_mysql_latin1_swedish_charset_coll;
+#define DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL 8
/* SQL data type struct */
typedef struct dtype_struct dtype_t;
@@ -24,7 +24,11 @@ extern dtype_t* dtype_binary;
/*-------------------------------------------*/
/* The 'MAIN TYPE' of a column */
#define DATA_VARCHAR 1 /* character varying of the
- latin1_swedish_ci charset-collation */
+ latin1_swedish_ci charset-collation; note
+ that the MySQL format for this, DATA_BINARY,
+ DATA_VARMYSQL, is also affected by whether the
+ 'precise type' contains
+ DATA_MYSQL_TRUE_VARCHAR */
#define DATA_CHAR 2 /* fixed length character of the
latin1_swedish_ci charset-collation */
#define DATA_FIXBINARY 3 /* binary string of fixed length */
@@ -32,7 +36,9 @@ extern dtype_t* dtype_binary;
#define DATA_BLOB 5 /* binary large object, or a TEXT type;
if prtype & DATA_BINARY_TYPE == 0, then this is
actually a TEXT column (or a BLOB created
- with < 4.0.14) */
+ with < 4.0.14; since column prefix indexes
+ came only in 4.0.14, the missing flag in BLOBs
+ created before that does not cause any harm) */
#define DATA_INT 6 /* integer: can be any size 1 - 8 bytes */
#define DATA_SYS_CHILD 7 /* address of the child page in node pointer */
#define DATA_SYS 8 /* system column */
@@ -102,6 +108,8 @@ columns, and for them the precise type is usually not used at all.
#define DATA_MYSQL_TYPE_MASK 255 /* AND with this mask to extract the MySQL
type from the precise type */
+#define DATA_MYSQL_TRUE_VARCHAR 15 /* MySQL type code for the >= 5.0.3
+ format true VARCHAR */
/* Precise data types for system columns and the length of those columns;
NOTE: the values must run from 0 up in the order given! All codes must
@@ -134,6 +142,10 @@ be less than 256 */
In earlier versions this was set for some
BLOB columns.
*/
+#define DATA_LONG_TRUE_VARCHAR 4096 /* this is ORed to the precise data
+ type when the column is true VARCHAR where
+ MySQL uses 2 bytes to store the data len;
+ for shorter VARCHARs MySQL uses only 1 byte */
/*-------------------------------------------*/
/* This many bytes we need to store the type information affecting the
@@ -145,28 +157,31 @@ store the charset-collation number; one byte is left unused, though */
#define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6
/*************************************************************************
-Checks if a string type has to be compared by the MySQL comparison functions.
-InnoDB internally only handles binary byte string comparisons, as well as
-latin1_swedish_ci strings. For example, UTF-8 strings have to be compared
-by MySQL. */
-
-ibool
-dtype_str_needs_mysql_cmp(
-/*======================*/
- /* out: TRUE if a string type that requires
- comparison with MySQL functions */
- dtype_t* dtype); /* in: type struct */
+Gets the MySQL type code from a dtype. */
+UNIV_INLINE
+ulint
+dtype_get_mysql_type(
+/*=================*/
+ /* out: MySQL type code; this is NOT an InnoDB
+ type code! */
+ dtype_t* type); /* in: type struct */
/*************************************************************************
-For the documentation of this function, see innobase_get_at_most_n_mbchars()
-in ha_innodb.cc. */
+Determine how many bytes the first n characters of the given string occupy.
+If the string is shorter than n characters, returns the number of bytes
+the characters in the string occupy. */
ulint
dtype_get_at_most_n_mbchars(
/*========================*/
- dtype_t* dtype,
- ulint prefix_len,
- ulint data_len,
- const char* str);
+ /* out: length of the prefix,
+ in bytes */
+ const dtype_t* dtype, /* in: data type */
+ ulint prefix_len, /* in: length of the requested
+ prefix, in characters, multiplied by
+ dtype_get_mbmaxlen(dtype) */
+ ulint data_len, /* in: length of str (in bytes) */
+ const char* str); /* in: the string whose prefix
+ length is being determined */
/*************************************************************************
Checks if a data main type is a string type. Also a BLOB is considered a
string type. */
@@ -271,6 +286,24 @@ dtype_get_prec(
/*===========*/
dtype_t* type);
/*************************************************************************
+Gets the minimum length of a character, in bytes. */
+UNIV_INLINE
+ulint
+dtype_get_mbminlen(
+/*===============*/
+ /* out: minimum length of a char, in bytes,
+ or 0 if this is not a character type */
+ const dtype_t* type); /* in: type */
+/*************************************************************************
+Gets the maximum length of a character, in bytes. */
+UNIV_INLINE
+ulint
+dtype_get_mbmaxlen(
+/*===============*/
+ /* out: maximum length of a char, in bytes,
+ or 0 if this is not a character type */
+ const dtype_t* type); /* in: type */
+/*************************************************************************
Gets the padding character code for the type. */
UNIV_INLINE
ulint
@@ -288,6 +321,14 @@ dtype_get_fixed_size(
/* out: fixed size, or 0 */
dtype_t* type); /* in: type */
/***************************************************************************
+Returns the minimum size of a data type. */
+UNIV_INLINE
+ulint
+dtype_get_min_size(
+/*===============*/
+ /* out: minimum size */
+ const dtype_t* type); /* in: type */
+/***************************************************************************
Returns a stored SQL NULL size for a type. For fixed length types it is
the fixed length of the type, otherwise 0. */
UNIV_INLINE
@@ -352,16 +393,34 @@ dtype_print(
/*========*/
dtype_t* type); /* in: type */
-/* Structure for an SQL data type */
+/* Structure for an SQL data type.
+If you add fields to this structure, be sure to initialize them everywhere.
+This structure is initialized in the following functions:
+dtype_set()
+dtype_read_for_order_and_null_size()
+dtype_new_read_for_order_and_null_size()
+sym_tab_add_null_lit() */
struct dtype_struct{
ulint mtype; /* main data type */
- ulint prtype; /* precise type; MySQL data type */
-
- /* the remaining two fields do not affect alphabetical ordering: */
-
- ulint len; /* length */
+ ulint prtype; /* precise type; MySQL data type, charset code,
+ flags to indicate nullability, signedness,
+ whether this is a binary string, whether this
+ is a true VARCHAR where MySQL uses 2 bytes to
+ store the length */
+
+ /* the remaining fields do not affect alphabetical ordering: */
+
+ ulint len; /* length; for MySQL data this is
+ field->pack_length(), except that for a
+ >= 5.0.3 type true VARCHAR this is the
+ maximum byte length of the string data
+ (in addition to the string, MySQL uses 1 or
+ 2 bytes to store the string length) */
ulint prec; /* precision */
+
+ ulint mbminlen; /* minimum length of a character, in bytes */
+ ulint mbmaxlen; /* maximum length of a character, in bytes */
};
#ifndef UNIV_NONINL
diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic
index 946b646ffbf..06d45dd5501 100644
--- a/innobase/include/data0type.ic
+++ b/innobase/include/data0type.ic
@@ -8,6 +8,61 @@ Created 1/16/1996 Heikki Tuuri
#include "mach0data.h"
+/**********************************************************************
+Get the variable length bounds of the given character set.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+void
+innobase_get_cset_width(
+/*====================*/
+ ulint cset, /* in: MySQL charset-collation code */
+ ulint* mbminlen, /* out: minimum length of a char (in bytes) */
+ ulint* mbmaxlen); /* out: maximum length of a char (in bytes) */
+
+/*************************************************************************
+Gets the MySQL charset-collation code for MySQL string types. */
+UNIV_INLINE
+ulint
+dtype_get_charset_coll(
+/*===================*/
+ ulint prtype) /* in: precise data type */
+{
+ return((prtype >> 16) & 0xFFUL);
+}
+
+/*************************************************************************
+Gets the MySQL type code from a dtype. */
+UNIV_INLINE
+ulint
+dtype_get_mysql_type(
+/*=================*/
+ /* out: MySQL type code; this is NOT an InnoDB
+ type code! */
+ dtype_t* type) /* in: type struct */
+{
+ return(type->prtype & 0xFFUL);
+}
+
+/*************************************************************************
+Sets the mbminlen and mbmaxlen members of a data type structure. */
+UNIV_INLINE
+void
+dtype_set_mblen(
+/*============*/
+ dtype_t* type) /* in/out: type struct */
+{
+ ut_ad(type);
+ if (dtype_is_string_type(type->mtype)) {
+ innobase_get_cset_width(dtype_get_charset_coll(type->prtype),
+ &type->mbminlen, &type->mbmaxlen);
+ ut_ad(type->mbminlen <= type->mbmaxlen);
+ } else {
+ type->mbminlen = type->mbmaxlen = 0;
+ }
+}
+
/*************************************************************************
Sets a data type structure. */
UNIV_INLINE
@@ -28,6 +83,7 @@ dtype_set(
type->len = len;
type->prec = prec;
+ dtype_set_mblen(type);
ut_ad(dtype_validate(type));
}
@@ -72,17 +128,6 @@ dtype_get_prtype(
}
/*************************************************************************
-Gets the MySQL charset-collation code for MySQL string types. */
-UNIV_INLINE
-ulint
-dtype_get_charset_coll(
-/*===================*/
- ulint prtype) /* in: precise data type */
-{
- return((prtype >> 16) & 0xFFUL);
-}
-
-/*************************************************************************
Gets the type length. */
UNIV_INLINE
ulint
@@ -109,6 +154,33 @@ dtype_get_prec(
}
/*************************************************************************
+Gets the minimum length of a character, in bytes. */
+UNIV_INLINE
+ulint
+dtype_get_mbminlen(
+/*===============*/
+ /* out: minimum length of a char, in bytes,
+ or 0 if this is not a character type */
+ const dtype_t* type) /* in: type */
+{
+ ut_ad(type);
+ return(type->mbminlen);
+}
+/*************************************************************************
+Gets the maximum length of a character, in bytes. */
+UNIV_INLINE
+ulint
+dtype_get_mbmaxlen(
+/*===============*/
+ /* out: maximum length of a char, in bytes,
+ or 0 if this is not a character type */
+ const dtype_t* type) /* in: type */
+{
+ ut_ad(type);
+ return(type->mbmaxlen);
+}
+
+/*************************************************************************
Gets the padding character code for the type. */
UNIV_INLINE
ulint
@@ -123,10 +195,12 @@ dtype_get_pad_char(
|| type->mtype == DATA_BINARY
|| type->mtype == DATA_FIXBINARY
|| type->mtype == DATA_MYSQL
- || type->mtype == DATA_VARMYSQL) {
+ || type->mtype == DATA_VARMYSQL
+ || (type->mtype == DATA_BLOB
+ && (type->prtype & DATA_BINARY_TYPE) == 0)) {
/* Space is the padding character for all char and binary
- strings */
+ strings, and starting from 5.0.3, also for TEXT strings. */
return((ulint)' ');
}
@@ -149,8 +223,10 @@ dtype_new_store_for_order_and_null_size(
bytes where we store the info */
dtype_t* type) /* in: type struct */
{
- ut_ad(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
-
+#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
+#endif
+
buf[0] = (byte)(type->mtype & 0xFFUL);
if (type->prtype & DATA_BINARY_TYPE) {
@@ -166,10 +242,12 @@ dtype_new_store_for_order_and_null_size(
mach_write_to_2(buf + 2, type->len & 0xFFFFUL);
+ ut_ad(dtype_get_charset_coll(type->prtype) < 256);
mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype));
- /* Note that the second last byte is left unused, because the
- charset-collation code is always < 256 */
+ if (type->prtype & DATA_NOT_NULL) {
+ buf[4] |= 128;
+ }
}
/**************************************************************************
@@ -196,6 +274,7 @@ dtype_read_for_order_and_null_size(
type->prtype = dtype_form_prtype(type->prtype,
data_mysql_default_charset_coll);
+ dtype_set_mblen(type);
}
/**************************************************************************
@@ -211,20 +290,26 @@ dtype_new_read_for_order_and_null_size(
{
ulint charset_coll;
- ut_ad(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
+#endif
type->mtype = buf[0] & 63;
type->prtype = buf[1];
if (buf[0] & 128) {
- type->prtype = type->prtype | DATA_BINARY_TYPE;
+ type->prtype |= DATA_BINARY_TYPE;
+ }
+
+ if (buf[4] & 128) {
+ type->prtype |= DATA_NOT_NULL;
}
type->len = mach_read_from_2(buf + 2);
mach_read_from_2(buf + 4);
- charset_coll = mach_read_from_2(buf + 4);
+ charset_coll = mach_read_from_2(buf + 4) & 0x7fff;
if (dtype_is_string_type(type->mtype)) {
ut_a(charset_coll < 256);
@@ -241,8 +326,10 @@ dtype_new_read_for_order_and_null_size(
type->prtype = dtype_form_prtype(type->prtype, charset_coll);
}
+ dtype_set_mblen(type);
}
+#ifndef UNIV_HOTBACKUP
/***************************************************************************
Returns the size of a fixed size data type, 0 if not a fixed size type. */
UNIV_INLINE
@@ -257,23 +344,127 @@ dtype_get_fixed_size(
mtype = dtype_get_mtype(type);
switch (mtype) {
+ case DATA_SYS:
+#ifdef UNIV_DEBUG
+ switch (type->prtype & DATA_MYSQL_TYPE_MASK) {
+ default:
+ ut_ad(0);
+ return(0);
+ case DATA_ROW_ID:
+ ut_ad(type->len == DATA_ROW_ID_LEN);
+ break;
+ case DATA_TRX_ID:
+ ut_ad(type->len == DATA_TRX_ID_LEN);
+ break;
+ case DATA_ROLL_PTR:
+ ut_ad(type->len == DATA_ROLL_PTR_LEN);
+ break;
+ case DATA_MIX_ID:
+ ut_ad(type->len == DATA_MIX_ID_LEN);
+ break;
+ }
+#endif /* UNIV_DEBUG */
case DATA_CHAR:
case DATA_FIXBINARY:
case DATA_INT:
case DATA_FLOAT:
case DATA_DOUBLE:
- case DATA_MYSQL:
return(dtype_get_len(type));
-
- case DATA_SYS: if (type->prtype == DATA_ROW_ID) {
- return(DATA_ROW_ID_LEN);
- } else if (type->prtype == DATA_TRX_ID) {
- return(DATA_TRX_ID_LEN);
- } else if (type->prtype == DATA_ROLL_PTR) {
- return(DATA_ROLL_PTR_LEN);
+ case DATA_MYSQL:
+ if (type->prtype & DATA_BINARY_TYPE) {
+ return(dtype_get_len(type));
} else {
+ /* We play it safe here and ask MySQL for
+ mbminlen and mbmaxlen. Although
+ type->mbminlen and type->mbmaxlen are
+ initialized if and only if type->prtype
+ is (in one of the 3 functions in this file),
+ it could be that none of these functions
+ has been called. */
+
+ ulint mbminlen, mbmaxlen;
+
+ innobase_get_cset_width(
+ dtype_get_charset_coll(type->prtype),
+ &mbminlen, &mbmaxlen);
+
+ if (UNIV_UNLIKELY(type->mbminlen != mbminlen)
+ || UNIV_UNLIKELY(type->mbmaxlen != mbmaxlen)) {
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: "
+ "mbminlen=%lu, "
+ "mbmaxlen=%lu, "
+ "type->mbminlen=%lu, "
+ "type->mbmaxlen=%lu\n",
+ (ulong) mbminlen,
+ (ulong) mbmaxlen,
+ (ulong) type->mbminlen,
+ (ulong) type->mbmaxlen);
+ }
+ if (mbminlen == mbmaxlen) {
+ return(dtype_get_len(type));
+ }
+ }
+ /* fall through for variable-length charsets */
+ case DATA_VARCHAR:
+ case DATA_BINARY:
+ case DATA_DECIMAL:
+ case DATA_VARMYSQL:
+ case DATA_BLOB:
+ return(0);
+ default: ut_error;
+ }
+
+ return(0);
+}
+
+/***************************************************************************
+Returns the size of a fixed size data type, 0 if not a fixed size type. */
+UNIV_INLINE
+ulint
+dtype_get_min_size(
+/*===============*/
+ /* out: minimum size */
+ const dtype_t* type) /* in: type */
+{
+ switch (type->mtype) {
+ case DATA_SYS:
+#ifdef UNIV_DEBUG
+ switch (type->prtype & DATA_MYSQL_TYPE_MASK) {
+ default:
+ ut_ad(0);
return(0);
+ case DATA_ROW_ID:
+ ut_ad(type->len == DATA_ROW_ID_LEN);
+ break;
+ case DATA_TRX_ID:
+ ut_ad(type->len == DATA_TRX_ID_LEN);
+ break;
+ case DATA_ROLL_PTR:
+ ut_ad(type->len == DATA_ROLL_PTR_LEN);
+ break;
+ case DATA_MIX_ID:
+ ut_ad(type->len == DATA_MIX_ID_LEN);
+ break;
+ }
+#endif /* UNIV_DEBUG */
+ case DATA_CHAR:
+ case DATA_FIXBINARY:
+ case DATA_INT:
+ case DATA_FLOAT:
+ case DATA_DOUBLE:
+ return(type->len);
+ case DATA_MYSQL:
+ if ((type->prtype & DATA_BINARY_TYPE)
+ || type->mbminlen == type->mbmaxlen) {
+ return(type->len);
}
+ /* this is a variable-length character set */
+ ut_a(type->mbminlen > 0);
+ ut_a(type->mbmaxlen > type->mbminlen);
+ ut_a(type->len % type->mbmaxlen == 0);
+ return(type->len * type->mbminlen / type->mbmaxlen);
case DATA_VARCHAR:
case DATA_BINARY:
case DATA_DECIMAL:
@@ -285,6 +476,7 @@ dtype_get_fixed_size(
return(0);
}
+#endif /* !UNIV_HOTBACKUP */
/***************************************************************************
Returns a stored SQL NULL size for a type. For fixed length types it is
diff --git a/innobase/include/dict0boot.h b/innobase/include/dict0boot.h
index 35eff5af29a..86702cbca05 100644
--- a/innobase/include/dict0boot.h
+++ b/innobase/include/dict0boot.h
@@ -119,6 +119,7 @@ dict_create(void);
clustered index */
#define DICT_SYS_INDEXES_PAGE_NO_FIELD 8
#define DICT_SYS_INDEXES_SPACE_NO_FIELD 7
+#define DICT_SYS_INDEXES_TYPE_FIELD 6
/* When a row id which is zero modulo this number (which must be a power of
two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
diff --git a/innobase/include/dict0crea.h b/innobase/include/dict0crea.h
index 8b6944fc605..5dd571be59c 100644
--- a/innobase/include/dict0crea.h
+++ b/innobase/include/dict0crea.h
@@ -54,6 +54,20 @@ dict_create_index_step(
/* out: query thread to run next or NULL */
que_thr_t* thr); /* in: query thread */
/***********************************************************************
+Truncates the index tree associated with a row in SYS_INDEXES table. */
+
+ulint
+dict_truncate_index_tree(
+/*=====================*/
+ /* out: new root page number, or
+ FIL_NULL on failure */
+ dict_table_t* table, /* in: the table the index belongs to */
+ rec_t* rec, /* in: record in the clustered index of
+ SYS_INDEXES table */
+ mtr_t* mtr); /* in: mtr having the latch
+ on the record page. The mtr may be
+ committed and restarted in this call. */
+/***********************************************************************
Drops the index tree associated with a row in SYS_INDEXES table. */
void
@@ -142,6 +156,7 @@ struct ind_node_struct{
/*----------------------*/
/* Local storage for this graph node */
ulint state; /* node execution state */
+ ulint page_no;/* root page number of the index */
dict_table_t* table; /* table which owns the index */
dtuple_t* ind_row;/* index definition row built */
ulint field_no;/* next field definition to insert */
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index 3333385ec56..a1232acdca7 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -228,9 +228,12 @@ dict_create_foreign_constraints(
name before it: test.table2; the
default database id the database of
parameter name */
- const char* name); /* in: table full name in the
+ const char* name, /* in: table full name in the
normalized form
database_name/table_name */
+ ibool reject_fks); /* in: if TRUE, fail with error
+ code DB_CANNOT_ADD_CONSTRAINT if
+ any foreign keys are found. */
/**************************************************************************
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
@@ -516,8 +519,9 @@ dict_index_add_to_cache(
/*====================*/
/* out: TRUE if success */
dict_table_t* table, /* in: table on which the index is */
- dict_index_t* index); /* in, own: index; NOTE! The index memory
+ dict_index_t* index, /* in, own: index; NOTE! The index memory
object is freed in this function! */
+ ulint page_no);/* in: root page number of the index */
/************************************************************************
Gets the number of fields in the internal representation of an index,
including fields added by the dictionary system. */
@@ -647,6 +651,16 @@ dict_index_get_sys_col_pos(
dict_index_t* index, /* in: index */
ulint type); /* in: DATA_ROW_ID, ... */
/***********************************************************************
+Adds a column to index. */
+
+void
+dict_index_add_col(
+/*===============*/
+ dict_index_t* index, /* in: index */
+ dict_col_t* col, /* in: column */
+ ulint order, /* in: order criterion */
+ ulint prefix_len); /* in: column prefix length */
+/***********************************************************************
Copies types of fields contained in index to tuple. */
void
@@ -655,18 +669,6 @@ dict_index_copy_types(
dtuple_t* tuple, /* in: data tuple */
dict_index_t* index, /* in: index */
ulint n_fields); /* in: number of field types to copy */
-/************************************************************************
-Gets the value of a system column in a clustered index record. The clustered
-index must contain the system column: if the index is unique, row id is
-not contained there! */
-UNIV_INLINE
-dulint
-dict_index_rec_get_sys_col(
-/*=======================*/
- /* out: system column value */
- dict_index_t* index, /* in: clustered index describing the record */
- ulint type, /* in: column type: DATA_ROLL_PTR, ... */
- rec_t* rec); /* in: record */
/*************************************************************************
Gets the index tree where the index is stored. */
UNIV_INLINE
@@ -696,9 +698,10 @@ dict_tree_t*
dict_tree_create(
/*=============*/
/* out, own: created tree */
- dict_index_t* index); /* in: the index for which to create: in the
+ dict_index_t* index, /* in: the index for which to create: in the
case of a mixed tree, this should be the
index of the cluster object */
+ ulint page_no);/* in: root page number of the index */
/**************************************************************************
Frees an index tree struct. */
@@ -728,7 +731,7 @@ dict_tree_find_index_for_tuple(
dtuple_t* tuple); /* in: tuple for which to find index */
/***********************************************************************
Checks if a table which is a mixed cluster member owns a record. */
-UNIV_INLINE
+
ibool
dict_is_mixed_table_rec(
/*====================*/
@@ -778,6 +781,7 @@ dict_tree_copy_rec_order_prefix(
/* out: pointer to the prefix record */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to copy prefix */
+ ulint* n_fields,/* out: number of fields copied */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size);/* in/out: buffer size */
@@ -790,6 +794,7 @@ dict_tree_build_data_tuple(
/* out, own: data tuple */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build data tuple */
+ ulint n_fields,/* in: number of data fields */
mem_heap_t* heap); /* in: memory heap where tuple created */
/*************************************************************************
Gets the space id of the root of the index tree. */
diff --git a/innobase/include/dict0dict.ic b/innobase/include/dict0dict.ic
index 85e4aaf1a05..928a693f860 100644
--- a/innobase/include/dict0dict.ic
+++ b/innobase/include/dict0dict.ic
@@ -9,7 +9,6 @@ Created 1/8/1996 Heikki Tuuri
#include "dict0load.h"
#include "trx0undo.h"
#include "trx0sys.h"
-#include "rem0rec.h"
/*************************************************************************
Gets the column data type. */
@@ -168,7 +167,7 @@ dict_table_get_sys_col(
col = dict_table_get_nth_col(table, table->n_cols
- DATA_N_SYS_COLS + sys);
ut_ad(col->type.mtype == DATA_SYS);
- ut_ad(col->type.prtype == sys);
+ ut_ad(col->type.prtype == (sys | DATA_NOT_NULL));
return(col);
}
@@ -312,49 +311,6 @@ dict_index_get_sys_col_pos(
dict_table_get_sys_col_no(index->table, type)));
}
-/************************************************************************
-Gets the value of a system column in a clustered index record. The clustered
-index must contain the system column: if the index is unique, row id is
-not contained there! */
-UNIV_INLINE
-dulint
-dict_index_rec_get_sys_col(
-/*=======================*/
- /* out: system column value */
- dict_index_t* index, /* in: clustered index describing the record */
- ulint type, /* in: column type: DATA_ROLL_PTR, ... */
- rec_t* rec) /* in: record */
-{
- ulint pos;
- byte* field;
- ulint len;
-
- ut_ad(index);
- ut_ad(index->type & DICT_CLUSTERED);
-
- pos = dict_index_get_sys_col_pos(index, type);
-
- ut_ad(pos != ULINT_UNDEFINED);
-
- field = rec_get_nth_field(rec, pos, &len);
-
- if (type == DATA_ROLL_PTR) {
- ut_ad(len == 7);
-
- return(trx_read_roll_ptr(field));
- } else if (type == DATA_TRX_ID) {
-
- return(trx_read_trx_id(field));
- } else if (type == DATA_MIX_ID) {
-
- return(mach_dulint_read_compressed(field));
- } else {
- ut_a(type == DATA_ROW_ID);
-
- return(mach_read_from_6(field));
- }
-}
-
/*************************************************************************
Gets the index tree where the index is stored. */
UNIV_INLINE
@@ -662,28 +618,3 @@ dict_table_get_index(
return(index);
}
-
-/***********************************************************************
-Checks if a table which is a mixed cluster member owns a record. */
-UNIV_INLINE
-ibool
-dict_is_mixed_table_rec(
-/*====================*/
- /* out: TRUE if the record belongs to this
- table */
- dict_table_t* table, /* in: table in a mixed cluster */
- rec_t* rec) /* in: user record in the clustered index */
-{
- byte* mix_id_field;
- ulint len;
-
- mix_id_field = rec_get_nth_field(rec, table->mix_len, &len);
-
- if ((len != table->mix_id_len)
- || (0 != ut_memcmp(table->mix_id_buf, mix_id_field, len))) {
-
- return(FALSE);
- }
-
- return(TRUE);
-}
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index 1e496a25477..ff6c4ec9b28 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -54,7 +54,8 @@ dict_mem_table_create(
of the table is placed; this parameter
is ignored if the table is made
a member of a cluster */
- ulint n_cols); /* in: number of columns */
+ ulint n_cols, /* in: number of columns */
+ ibool comp); /* in: TRUE=compact page format */
/**************************************************************************
Creates a cluster memory object. */
@@ -171,6 +172,13 @@ struct dict_field_struct{
DICT_MAX_COL_PREFIX_LEN; NOTE that
in the UTF-8 charset, MySQL sets this
to 3 * the prefix len in UTF-8 chars */
+ ulint fixed_len; /* 0 or the fixed length of the
+ column if smaller than
+ DICT_MAX_COL_PREFIX_LEN */
+ ulint fixed_offs; /* offset to the field, or
+ ULINT_UNDEFINED if it is not fixed
+ within the record (due to preceding
+ variable-length fields) */
};
/* Data structure for an index tree */
@@ -210,7 +218,6 @@ struct dict_index_struct{
const char* table_name; /* table name */
dict_table_t* table; /* back pointer to table */
ulint space; /* space where the index tree is placed */
- ulint page_no;/* page number of the index tree root */
ulint trx_id_offset;/* position of the the trx id column
in a clustered index record, if the fields
before it are known to be of a fixed size,
@@ -225,6 +232,7 @@ struct dict_index_struct{
ulint n_def; /* number of fields defined so far */
ulint n_fields;/* number of fields in the index */
dict_field_t* fields; /* array of field descriptions */
+ ulint n_nullable;/* number of nullable fields */
UT_LIST_NODE_T(dict_index_t)
indexes;/* list of indexes of the table */
dict_tree_t* tree; /* index tree struct */
@@ -320,6 +328,7 @@ struct dict_table_struct{
ibool tablespace_discarded;/* this flag is set TRUE when the
user calls DISCARD TABLESPACE on this table,
and reset to FALSE in IMPORT TABLESPACE */
+ ibool comp; /* flag: TRUE=compact page format */
hash_node_t name_hash; /* hash chain node */
hash_node_t id_hash; /* hash chain node */
ulint n_def; /* number of columns defined so far */
diff --git a/innobase/include/dyn0dyn.h b/innobase/include/dyn0dyn.h
index abee62300e3..1df976a5301 100644
--- a/innobase/include/dyn0dyn.h
+++ b/innobase/include/dyn0dyn.h
@@ -132,7 +132,7 @@ void
dyn_push_string(
/*============*/
dyn_array_t* arr, /* in: dyn array */
- byte* str, /* in: string to write */
+ const byte* str, /* in: string to write */
ulint len); /* in: string length */
/*#################################################################*/
diff --git a/innobase/include/dyn0dyn.ic b/innobase/include/dyn0dyn.ic
index b6c4808398b..c1b8f2cb8ce 100644
--- a/innobase/include/dyn0dyn.ic
+++ b/innobase/include/dyn0dyn.ic
@@ -324,10 +324,9 @@ void
dyn_push_string(
/*============*/
dyn_array_t* arr, /* in: dyn array */
- byte* str, /* in: string to write */
+ const byte* str, /* in: string to write */
ulint len) /* in: string length */
{
- byte* ptr;
ulint n_copied;
while (len > 0) {
@@ -337,9 +336,7 @@ dyn_push_string(
n_copied = len;
}
- ptr = (byte*) dyn_array_push(arr, n_copied);
-
- ut_memcpy(ptr, str, n_copied);
+ memcpy(dyn_array_push(arr, n_copied), str, n_copied);
str += n_copied;
len -= n_copied;
diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h
index c1a127aadca..aa1ec5c25a5 100644
--- a/innobase/include/fil0fil.h
+++ b/innobase/include/fil0fil.h
@@ -89,6 +89,8 @@ extern fil_addr_t fil_addr_null;
#define FIL_TABLESPACE 501
#define FIL_LOG 502
+extern ulint fil_n_log_flushes;
+
extern ulint fil_n_pending_log_flushes;
extern ulint fil_n_pending_tablespace_flushes;
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 74288d57285..20b1f1d7145 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -19,7 +19,9 @@ Created 5/7/1996 Heikki Tuuri
#include "read0types.h"
#include "hash0hash.h"
+#ifdef UNIV_DEBUG
extern ibool lock_print_waits;
+#endif /* UNIV_DEBUG */
/* Buffer for storing information about the most recent deadlock error */
extern FILE* lock_latest_err_file;
@@ -47,7 +49,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index); /* in: secondary index */
+ dict_index_t* index, /* in: secondary index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Checks if some transaction has an implicit x-lock on a record in a clustered
index. */
@@ -58,7 +61,8 @@ lock_clust_rec_some_has_impl(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*****************************************************************
Resets the lock bits for a single record. Releases transactions
waiting for lock requests here. */
@@ -214,6 +218,7 @@ actual record is being moved. */
void
lock_rec_store_on_page_infimum(
/*===========================*/
+ page_t* page, /* in: page containing the record */
rec_t* rec); /* in: record whose lock state is stored
on the infimum record of the same page; lock
bits are reset on the record */
@@ -275,6 +280,7 @@ lock_clust_rec_modify_check_and_lock(
does nothing */
rec_t* rec, /* in: record which should be modified */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
Checks if locks of other transactions prevent an immediate modify
@@ -308,6 +314,7 @@ lock_sec_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: secondary index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -333,6 +340,34 @@ lock_clust_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
+ ulint mode, /* in: mode of the lock which the read cursor
+ should set on records: LOCK_S or LOCK_X; the
+ latter is possible in SELECT FOR UPDATE */
+ ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
+ LOCK_REC_NOT_GAP */
+ que_thr_t* thr); /* in: query thread */
+/*************************************************************************
+Checks if locks of other transactions prevent an immediate read, or passing
+over by a read cursor, of a clustered index record. If they do, first tests
+if the query thread should anyway be suspended for some reason; if not, then
+puts the transaction and the query thread to the lock wait state and inserts a
+waiting request for a record lock to the lock queue. Sets the requested mode
+lock on the record. This is an alternative version of
+lock_clust_rec_read_check_and_lock() that does not require the parameter
+"offsets". */
+
+ulint
+lock_clust_rec_read_check_and_lock_alt(
+/*===================================*/
+ /* out: DB_SUCCESS, DB_LOCK_WAIT,
+ DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
+ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
+ does nothing */
+ rec_t* rec, /* in: user record or page supremum record
+ which should be read or passed over by a read
+ cursor */
+ dict_index_t* index, /* in: clustered index */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -350,6 +385,7 @@ lock_clust_rec_cons_read_sees(
rec_t* rec, /* in: user record which should be read or
passed over by a read cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
read_view_t* view); /* in: consistent read view */
/*************************************************************************
Checks that a non-clustered index record is seen in a consistent read. */
@@ -379,9 +415,7 @@ lock_table(
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
- does nothing;
- if LOCK_TABLE_EXP bits are set,
- creates an explicit table lock */
+ does nothing */
dict_table_t* table, /* in: database table in dictionary cache */
ulint mode, /* in: lock mode */
que_thr_t* thr); /* in: query thread */
@@ -418,15 +452,6 @@ lock_release_off_kernel(
/*====================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
-Releases table locks explicitly requested with LOCK TABLES (indicated by
-lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
-because of these locks. */
-
-void
-lock_release_tables_off_kernel(
-/*===========================*/
- trx_t* trx); /* in: transaction */
-/*************************************************************************
Cancels a waiting lock request and releases possible other transactions
waiting behind it. */
@@ -499,6 +524,7 @@ lock_check_trx_id_sanity(
dulint trx_id, /* in: trx id */
rec_t* rec, /* in: user record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
ibool has_kernel_mutex);/* in: TRUE if the caller owns the
kernel mutex */
/*************************************************************************
@@ -509,7 +535,8 @@ 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 */
+ dict_index_t* index, /* in: index, or NULL if not known */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Prints info of a table lock. */
@@ -583,7 +610,6 @@ extern lock_sys_t* lock_sys;
/* Lock types */
#define LOCK_TABLE 16 /* these type values should be so high that */
#define LOCK_REC 32 /* they can be ORed to the lock mode */
-#define LOCK_TABLE_EXP 80 /* explicit table lock (80 = 16 + 64) */
#define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the
type_mode field in a lock */
/* Waiting lock flag */
diff --git a/innobase/include/lock0lock.ic b/innobase/include/lock0lock.ic
index fabc9256401..c7a71bb45d8 100644
--- a/innobase/include/lock0lock.ic
+++ b/innobase/include/lock0lock.ic
@@ -60,7 +60,8 @@ lock_clust_rec_some_has_impl(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
dulint trx_id;
@@ -70,7 +71,7 @@ lock_clust_rec_some_has_impl(
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec));
- trx_id = row_get_rec_trx_id(rec, index);
+ trx_id = row_get_rec_trx_id(rec, index, offsets);
if (trx_is_active(trx_id)) {
/* The modifying or inserting transaction is active */
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index d14a116072d..7f3f10438b4 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -17,8 +17,12 @@ Created 12/9/1995 Heikki Tuuri
typedef struct log_struct log_t;
typedef struct log_group_struct log_group_t;
+#ifdef UNIV_DEBUG
extern ibool log_do_write;
extern ibool log_debug_writes;
+#else /* UNIV_DEBUG */
+# define log_do_write TRUE
+#endif /* UNIV_DEBUG */
/* Wait modes for log_write_up_to */
#define LOG_NO_WAIT 91
diff --git a/innobase/include/mach0data.h b/innobase/include/mach0data.h
index 7ad760cd60f..f9a3ff521d5 100644
--- a/innobase/include/mach0data.h
+++ b/innobase/include/mach0data.h
@@ -52,6 +52,27 @@ mach_read_from_2(
/*=============*/
/* out: ulint integer, >= 0, < 64k */
byte* b); /* in: pointer to two bytes */
+
+/************************************************************
+The following function is used to convert a 16-bit data item
+to the canonical format, for fast bytewise equality test
+against memory. */
+UNIV_INLINE
+uint16
+mach_encode_2(
+/*==========*/
+ /* out: 16-bit integer in canonical format */
+ ulint n); /* in: integer in machine-dependent format */
+/************************************************************
+The following function is used to convert a 16-bit data item
+from the canonical format, for fast bytewise equality test
+against memory. */
+UNIV_INLINE
+ulint
+mach_decode_2(
+/*==========*/
+ /* out: integer in machine-dependent format */
+ uint16 n); /* in: 16-bit integer in canonical format */
/***********************************************************
The following function is used to store data in 3 consecutive
bytes. We store the most significant byte to the lowest address. */
diff --git a/innobase/include/mach0data.ic b/innobase/include/mach0data.ic
index 3ffb9baa344..888f3f743e4 100644
--- a/innobase/include/mach0data.ic
+++ b/innobase/include/mach0data.ic
@@ -68,6 +68,37 @@ mach_read_from_2(
);
}
+/************************************************************
+The following function is used to convert a 16-bit data item
+to the canonical format, for fast bytewise equality test
+against memory. */
+UNIV_INLINE
+uint16
+mach_encode_2(
+/*==========*/
+ /* out: 16-bit integer in canonical format */
+ ulint n) /* in: integer in machine-dependent format */
+{
+ uint16 ret;
+ ut_ad(2 == sizeof ret);
+ mach_write_to_2((byte*) &ret, n);
+ return(ret);
+}
+/************************************************************
+The following function is used to convert a 16-bit data item
+from the canonical format, for fast bytewise equality test
+against memory. */
+UNIV_INLINE
+ulint
+mach_decode_2(
+/*==========*/
+ /* out: integer in machine-dependent format */
+ uint16 n) /* in: 16-bit integer in canonical format */
+{
+ ut_ad(2 == sizeof n);
+ return(mach_read_from_2((byte*) &n));
+}
+
/***********************************************************
The following function is used to store data in 3 consecutive
bytes. We store the most significant byte to the lowest address. */
diff --git a/innobase/include/mem0mem.ic b/innobase/include/mem0mem.ic
index 82d88099c3f..8c87c884d78 100644
--- a/innobase/include/mem0mem.ic
+++ b/innobase/include/mem0mem.ic
@@ -623,7 +623,7 @@ mem_strdupq(
}
*d++ = q;
*d++ = '\0';
- ut_ad(len == d - dst);
+ ut_ad((ssize_t) len == d - dst);
return(dst);
}
diff --git a/innobase/include/mtr0log.h b/innobase/include/mtr0log.h
index 9c9c6f696e8..6a3920aa8a1 100644
--- a/innobase/include/mtr0log.h
+++ b/innobase/include/mtr0log.h
@@ -11,6 +11,7 @@ Created 12/7/1995 Heikki Tuuri
#include "univ.i"
#include "mtr0mtr.h"
+#include "dict0types.h"
/************************************************************
Writes 1 - 4 bytes to a file page buffered in the buffer pool.
@@ -40,10 +41,10 @@ corresponding log record to the mini-transaction log. */
void
mlog_write_string(
/*==============*/
- byte* ptr, /* in: pointer where to write */
- byte* str, /* in: string to write */
- ulint len, /* in: string length */
- mtr_t* mtr); /* in: mini-transaction handle */
+ byte* ptr, /* in: pointer where to write */
+ const byte* str, /* in: string to write */
+ ulint len, /* in: string length */
+ mtr_t* mtr); /* in: mini-transaction handle */
/************************************************************
Writes initial part of a log record consisting of one-byte item
type and four-byte space and page numbers. */
@@ -84,9 +85,9 @@ Catenates n bytes to the mtr log. */
void
mlog_catenate_string(
/*=================*/
- mtr_t* mtr, /* in: mtr */
- byte* str, /* in: string to write */
- ulint len); /* in: string length */
+ mtr_t* mtr, /* in: mtr */
+ const byte* str, /* in: string to write */
+ ulint len); /* in: string length */
/************************************************************
Catenates a compressed ulint to mlog. */
UNIV_INLINE
@@ -173,6 +174,38 @@ mlog_parse_string(
byte* page); /* in: page where to apply the log record, or NULL */
+/************************************************************
+Opens a buffer for mlog, writes the initial log record and,
+if needed, the field lengths of an index. Reserves space
+for further log entries. The log entry must be closed with
+mtr_close(). */
+
+byte*
+mlog_open_and_write_index(
+/*======================*/
+ /* out: buffer, NULL if log mode
+ MTR_LOG_NONE */
+ mtr_t* mtr, /* in: mtr */
+ byte* rec, /* in: index record or page */
+ dict_index_t* index, /* in: record descriptor */
+ byte type, /* in: log item type */
+ ulint size); /* in: requested buffer size in bytes
+ (if 0, calls mlog_close() and returns NULL) */
+
+/************************************************************
+Parses a log record written by mlog_open_and_write_index. */
+
+byte*
+mlog_parse_index(
+/*=============*/
+ /* out: parsed record end,
+ NULL if not a complete record */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ /* out: new value of log_ptr */
+ ibool comp, /* in: TRUE=compact record format */
+ dict_index_t** index); /* out, own: dummy index */
+
/* Insert, update, and maybe other functions may use this value to define an
extra mlog buffer size for variable size data */
#define MLOG_BUF_MARGIN 256
diff --git a/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h
index e8c68a91dad..f44e813cf6b 100644
--- a/innobase/include/mtr0mtr.h
+++ b/innobase/include/mtr0mtr.h
@@ -102,7 +102,35 @@ flag value must give the length also! */
file rename */
#define MLOG_FILE_DELETE ((byte)35) /* log record about an .ibd
file deletion */
-#define MLOG_BIGGEST_TYPE ((byte)35) /* biggest value (used in
+#define MLOG_COMP_REC_MIN_MARK ((byte)36) /* mark a compact index record
+ as the predefined minimum
+ record */
+#define MLOG_COMP_PAGE_CREATE ((byte)37) /* create a compact
+ index page */
+#define MLOG_COMP_REC_INSERT ((byte)38) /* compact record insert */
+#define MLOG_COMP_REC_CLUST_DELETE_MARK ((byte)39)
+ /* mark compact clustered index
+ record deleted */
+#define MLOG_COMP_REC_SEC_DELETE_MARK ((byte)40)/* mark compact secondary index
+ record deleted; this log
+ record type is redundant, as
+ MLOG_REC_SEC_DELETE_MARK is
+ independent of the record
+ format. */
+#define MLOG_COMP_REC_UPDATE_IN_PLACE ((byte)41)/* update of a compact record,
+ preserves record field sizes */
+#define MLOG_COMP_REC_DELETE ((byte)42) /* delete a compact record
+ from a page */
+#define MLOG_COMP_LIST_END_DELETE ((byte)43) /* delete compact record list
+ end on index page */
+#define MLOG_COMP_LIST_START_DELETE ((byte)44) /* delete compact record list
+ start on index page */
+#define MLOG_COMP_LIST_END_COPY_CREATED ((byte)45)
+ /* copy compact record list end
+ to a new created index page */
+#define MLOG_COMP_PAGE_REORGANIZE ((byte)46) /* reorganize an index page */
+
+#define MLOG_BIGGEST_TYPE ((byte)46) /* biggest value (used in
asserts) */
/*******************************************************************
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index 280a949c1c5..adbc4afafd2 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -17,6 +17,8 @@ Created 10/21/1995 Heikki Tuuri
#include <time.h>
#endif
+typedef struct fil_node_struct fil_node_t;
+
#ifdef UNIV_DO_FLUSH
extern ibool os_do_not_call_flush_at_each_write;
#endif /* UNIV_DO_FLUSH */
@@ -26,6 +28,9 @@ extern ibool os_aio_print_debug;
extern ulint os_file_n_pending_preads;
extern ulint os_file_n_pending_pwrites;
+extern ulint os_n_pending_reads;
+extern ulint os_n_pending_writes;
+
#ifdef __WIN__
/* We define always WIN_ASYNC_IO, and check at run-time whether
@@ -562,7 +567,7 @@ os_aio(
ulint offset_high, /* in: most significant 32 bits of
offset */
ulint n, /* in: number of bytes to read or write */
- void* message1,/* in: messages for the aio handler (these
+ fil_node_t* message1,/* in: messages for the aio handler (these
can be used to identify a completed aio
operation); if mode is OS_AIO_SYNC, these
are ignored */
@@ -620,7 +625,7 @@ os_aio_windows_handle(
ignored */
ulint pos, /* this parameter is used only in sync aio:
wait for the aio slot at this position */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -640,7 +645,7 @@ os_aio_posix_handle(
/*================*/
/* out: TRUE if the aio operation succeeded */
ulint array_no, /* in: array number 0 - 3 */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -660,7 +665,7 @@ os_aio_simulated_handle(
i/o thread, segment 1 the log i/o thread,
then follow the non-ibuf read threads, and as
the last are the non-ibuf write threads */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -687,6 +692,8 @@ Refreshes the statistics used to print per-second averages. */
void
os_aio_refresh_stats(void);
/*======================*/
+
+#ifdef UNIV_DEBUG
/**************************************************************************
Checks that all slots in the system have been freed, that is, there are
no pending io operations. */
@@ -694,6 +701,7 @@ no pending io operations. */
ibool
os_aio_all_slots_free(void);
/*=======================*/
+#endif /* UNIV_DEBUG */
/***********************************************************************
This function returns information about the specified file */
diff --git a/innobase/include/os0proc.h b/innobase/include/os0proc.h
index d0d3cf82e38..b0b72e18675 100644
--- a/innobase/include/os0proc.h
+++ b/innobase/include/os0proc.h
@@ -12,6 +12,11 @@ Created 9/30/1995 Heikki Tuuri
#include "univ.i"
+#ifdef UNIV_LINUX
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
typedef void* os_process_t;
typedef unsigned long int os_process_id_t;
@@ -27,6 +32,10 @@ page size of an Intel x86 processor. We cannot use AWE with 2 MB or 4 MB
pages. */
#define OS_AWE_X86_PAGE_SIZE 4096
+extern ibool os_use_large_pages;
+/* Large page size. This may be a boot-time option on some platforms */
+extern ulint os_large_page_size;
+
/********************************************************************
Windows AWE support. Tries to enable the "lock pages in memory" privilege for
the current process so that the current process can allocate memory-locked
@@ -103,6 +112,25 @@ os_mem_alloc_nocache(
/* out: allocated memory */
ulint n); /* in: number of bytes */
/********************************************************************
+Allocates large pages memory. */
+
+void*
+os_mem_alloc_large(
+/*=================*/
+ /* out: allocated memory */
+ ulint n, /* in: number of bytes */
+ ibool set_to_zero, /* in: TRUE if allocated memory should be set
+ to zero if UNIV_SET_MEM_TO_ZERO is defined */
+ ibool assert_on_error); /* in: if TRUE, we crash mysqld if the memory
+ cannot be allocated */
+/********************************************************************
+Frees large pages memory. */
+
+void
+os_mem_free_large(
+/*=================*/
+void *ptr); /* in: number of bytes */
+/********************************************************************
Sets the priority boost for threads released from waiting within the current
process. */
diff --git a/innobase/include/page0cur.h b/innobase/include/page0cur.h
index c85669ed4df..b03302b0e77 100644
--- a/innobase/include/page0cur.h
+++ b/innobase/include/page0cur.h
@@ -26,11 +26,13 @@ Created 10/4/1994 Heikki Tuuri
#define PAGE_CUR_GE 2
#define PAGE_CUR_L 3
#define PAGE_CUR_LE 4
-#define PAGE_CUR_LE_OR_EXTENDS 5 /* This is a search mode used in
+/*#define PAGE_CUR_LE_OR_EXTENDS 5*/ /* This is a search mode used in
"column LIKE 'abc%' ORDER BY column DESC";
we have to find strings which are <= 'abc' or
which extend it */
-#define PAGE_CUR_DBG 6
+#ifdef UNIV_SEARCH_DEBUG
+# define PAGE_CUR_DBG 6 /* As PAGE_CUR_LE, but skips search shortcut */
+#endif /* UNIV_SEARCH_DEBUG */
#ifdef PAGE_CUR_ADAPT
# ifdef UNIV_SEARCH_PERF_STAT
@@ -78,16 +80,16 @@ UNIV_INLINE
ibool
page_cur_is_before_first(
/*=====================*/
- /* out: TRUE if at start */
- page_cur_t* cur); /* in: cursor */
+ /* out: TRUE if at start */
+ const page_cur_t* cur); /* in: cursor */
/*************************************************************
Returns TRUE if the cursor is after last user record. */
UNIV_INLINE
ibool
page_cur_is_after_last(
/*===================*/
- /* out: TRUE if at end */
- page_cur_t* cur); /* in: cursor */
+ /* out: TRUE if at end */
+ const page_cur_t* cur); /* in: cursor */
/**************************************************************
Positions the cursor on the given record. */
UNIV_INLINE
@@ -128,7 +130,8 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple */
+ dtuple_t* tuple, /* in: pointer to a data tuple */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if
@@ -142,6 +145,8 @@ page_cur_rec_insert(
otherwise */
page_cur_t* cursor, /* in: a page cursor */
rec_t* rec, /* in: record to insert */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) */
mtr_t* mtr); /* in: mini-transaction handle */
/***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if
@@ -155,9 +160,10 @@ page_cur_insert_rec_low(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
- ulint data_size,/* in: data size of tuple */
- rec_t* rec, /* in: pointer to a physical record or NULL */
+ dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
+ dict_index_t* index, /* in: record descriptor */
+ rec_t* rec, /* in: pointer to a physical record or NULL */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) or NULL */
mtr_t* mtr); /* in: mini-transaction handle */
/*****************************************************************
Copies records from page to a newly created page, from a given record onward,
@@ -166,10 +172,11 @@ including that record. Infimum and supremum records are not copied. */
void
page_copy_rec_list_end_to_created_page(
/*===================================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: first record to copy */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: first record to copy */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/***************************************************************
Deletes a record at the page cursor. The cursor is moved to the
next record after the deleted one. */
@@ -177,8 +184,10 @@ next record after the deleted one. */
void
page_cur_delete_rec(
/*================*/
- page_cur_t* cursor, /* in: a page cursor */
- mtr_t* mtr); /* in: mini-transaction handle */
+ page_cur_t* cursor, /* in: a page cursor */
+ dict_index_t* index, /* in: record descriptor */
+ const ulint* offsets,/* in: rec_get_offsets(cursor->rec, index) */
+ mtr_t* mtr); /* in: mini-transaction handle */
/********************************************************************
Searches the right position for a page cursor. */
UNIV_INLINE
@@ -187,6 +196,7 @@ page_cur_search(
/*============*/
/* out: number of matched fields on the left */
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -198,6 +208,7 @@ void
page_cur_search_with_match(
/*=======================*/
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -229,34 +240,37 @@ Parses a log record of a record insert on a page. */
byte*
page_cur_parse_insert_rec(
/*======================*/
- /* out: end of log record or NULL */
- ibool is_short,/* in: TRUE if short inserts */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ ibool is_short,/* in: TRUE if short inserts */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/**************************************************************
Parses a log record of copying a record list end to a new created page. */
byte*
page_parse_copy_rec_list_to_created_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 */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses log record of a record delete on a page. */
byte*
page_cur_parse_delete_rec(
/*======================*/
- /* out: pointer to record end or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: pointer to record end or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/* Index page cursor */
diff --git a/innobase/include/page0cur.ic b/innobase/include/page0cur.ic
index 39f8ab11513..f8346819e84 100644
--- a/innobase/include/page0cur.ic
+++ b/innobase/include/page0cur.ic
@@ -69,15 +69,10 @@ UNIV_INLINE
ibool
page_cur_is_before_first(
/*=====================*/
- /* out: TRUE if at start */
- page_cur_t* cur) /* in: cursor */
+ /* out: TRUE if at start */
+ const page_cur_t* cur) /* in: cursor */
{
- if (page_get_infimum_rec(page_cur_get_page(cur)) == cur->rec) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(page_rec_is_infimum(cur->rec));
}
/*************************************************************
@@ -86,15 +81,10 @@ UNIV_INLINE
ibool
page_cur_is_after_last(
/*===================*/
- /* out: TRUE if at end */
- page_cur_t* cur) /* in: cursor */
+ /* out: TRUE if at end */
+ const page_cur_t* cur) /* in: cursor */
{
- if (page_get_supremum_rec(page_cur_get_page(cur)) == cur->rec) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(page_rec_is_supremum(cur->rec));
}
/**************************************************************
@@ -143,7 +133,7 @@ UNIV_INLINE
void
page_cur_move_to_prev(
/*==================*/
- page_cur_t* cur) /* in: cursor; must not before first */
+ page_cur_t* cur) /* in: page cursor, not before first */
{
ut_ad(!page_cur_is_before_first(cur));
@@ -158,6 +148,7 @@ page_cur_search(
/*============*/
/* out: number of matched fields on the left */
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -170,7 +161,7 @@ page_cur_search(
ut_ad(dtuple_check_typed(tuple));
- page_cur_search_with_match(page, tuple, mode,
+ page_cur_search_with_match(page, index, tuple, mode,
&up_matched_fields,
&up_matched_bytes,
&low_matched_fields,
@@ -190,16 +181,11 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple */
+ dtuple_t* tuple, /* in: pointer to a data tuple */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
- ulint data_size;
-
- ut_ad(dtuple_check_typed(tuple));
-
- data_size = dtuple_get_data_size(tuple);
-
- return(page_cur_insert_rec_low(cursor, tuple, data_size, NULL, mtr));
+ return(page_cur_insert_rec_low(cursor, tuple, index, NULL, NULL, mtr));
}
/***************************************************************
@@ -214,8 +200,11 @@ page_cur_rec_insert(
otherwise */
page_cur_t* cursor, /* in: a page cursor */
rec_t* rec, /* in: record to insert */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) */
mtr_t* mtr) /* in: mini-transaction handle */
{
- return(page_cur_insert_rec_low(cursor, NULL, 0, rec, mtr));
+ return(page_cur_insert_rec_low(cursor, NULL, index, rec,
+ offsets, mtr));
}
diff --git a/innobase/include/page0page.h b/innobase/include/page0page.h
index 969313614e3..c4ffa39d3ac 100644
--- a/innobase/include/page0page.h
+++ b/innobase/include/page0page.h
@@ -37,7 +37,8 @@ typedef byte page_header_t;
/*-----------------------------*/
#define PAGE_N_DIR_SLOTS 0 /* number of slots in page directory */
#define PAGE_HEAP_TOP 2 /* pointer to record heap top */
-#define PAGE_N_HEAP 4 /* number of records in the heap */
+#define PAGE_N_HEAP 4 /* number of records in the heap,
+ bit 15=flag: new-style compact page format */
#define PAGE_FREE 6 /* pointer to start of page free record list */
#define PAGE_GARBAGE 8 /* number of bytes in deleted records */
#define PAGE_LAST_INSERT 10 /* pointer to the last inserted record, or
@@ -79,15 +80,24 @@ typedef byte page_header_t;
#define PAGE_DATA (PAGE_HEADER + 36 + 2 * FSEG_HEADER_SIZE)
/* start of data on the page */
-#define PAGE_INFIMUM (PAGE_DATA + 1 + REC_N_EXTRA_BYTES)
- /* offset of the page infimum record on the
- page */
-#define PAGE_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_EXTRA_BYTES + 8)
- /* offset of the page supremum record on the
- page */
-#define PAGE_SUPREMUM_END (PAGE_SUPREMUM + 9)
+#define PAGE_OLD_INFIMUM (PAGE_DATA + 1 + REC_N_OLD_EXTRA_BYTES)
+ /* offset of the page infimum record on an
+ old-style page */
+#define PAGE_OLD_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_OLD_EXTRA_BYTES + 8)
+ /* offset of the page supremum record on an
+ old-style page */
+#define PAGE_OLD_SUPREMUM_END (PAGE_OLD_SUPREMUM + 9)
/* offset of the page supremum record end on
- the page */
+ an old-style page */
+#define PAGE_NEW_INFIMUM (PAGE_DATA + REC_N_NEW_EXTRA_BYTES)
+ /* offset of the page infimum record on a
+ new-style compact page */
+#define PAGE_NEW_SUPREMUM (PAGE_DATA + 2 * REC_N_NEW_EXTRA_BYTES + 8)
+ /* offset of the page supremum record on a
+ new-style compact page */
+#define PAGE_NEW_SUPREMUM_END (PAGE_NEW_SUPREMUM + 8)
+ /* offset of the page supremum record end on
+ a new-style compact page */
/*-----------------------------*/
/* Directions of cursor movement */
@@ -233,6 +243,7 @@ page_cmp_dtuple_rec_with_match(
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
@@ -259,6 +270,22 @@ page_rec_get_n_recs_before(
/* out: number of records */
rec_t* rec); /* in: the physical record */
/*****************************************************************
+Gets the number of records in the heap. */
+UNIV_INLINE
+ulint
+page_dir_get_n_heap(
+/*================*/
+ /* out: number of user records */
+ page_t* page); /* in: index page */
+/*****************************************************************
+Sets the number of records in the heap. */
+UNIV_INLINE
+void
+page_dir_set_n_heap(
+/*================*/
+ page_t* page, /* in: index page */
+ ulint n_heap);/* in: number of records */
+/*****************************************************************
Gets the number of dir slots in directory. */
UNIV_INLINE
ulint
@@ -267,6 +294,15 @@ page_dir_get_n_slots(
/* out: number of slots */
page_t* page); /* in: index page */
/*****************************************************************
+Sets the number of dir slots in directory. */
+UNIV_INLINE
+void
+page_dir_set_n_slots(
+/*=================*/
+ /* out: number of slots */
+ page_t* page, /* in: index page */
+ ulint n_slots);/* in: number of slots */
+/*****************************************************************
Gets pointer to nth directory slot. */
UNIV_INLINE
page_dir_slot_t*
@@ -333,7 +369,24 @@ ulint
page_dir_find_owner_slot(
/*=====================*/
/* out: the directory slot number */
- rec_t* rec); /* in: the physical record */
+ rec_t* rec); /* in: the physical record */
+/****************************************************************
+Determine whether the page is in new-style compact format. */
+UNIV_INLINE
+ulint
+page_is_comp(
+/*=========*/
+ /* out: nonzero if the page is in compact
+ format, zero if it is in old-style format */
+ page_t* page); /* in: index page */
+/****************************************************************
+TRUE if the record is on a page in compact format. */
+UNIV_INLINE
+ulint
+page_rec_is_comp(
+/*=============*/
+ /* out: nonzero if in compact format */
+ const rec_t* rec); /* in: record */
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
@@ -359,49 +412,58 @@ UNIV_INLINE
rec_t*
page_rec_get_prev(
/*==============*/
- /* out: pointer to previous record */
- rec_t* rec); /* in: pointer to record, must not be page
- infimum */
+ /* out: pointer to previous record */
+ rec_t* rec); /* in: pointer to record,
+ must not be page infimum */
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
-page_rec_is_user_rec(
-/*=================*/
+page_rec_is_user_rec_low(
+/*=====================*/
/* out: TRUE if a user record */
- rec_t* rec); /* in: record */
+ ulint offset);/* in: record offset on page */
/****************************************************************
TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_supremum(
-/*=================*/
+page_rec_is_supremum_low(
+/*=====================*/
/* out: TRUE if the supremum record */
- rec_t* rec); /* in: record */
+ ulint offset);/* in: record offset on page */
/****************************************************************
TRUE if the record is the infimum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_infimum(
-/*================*/
+page_rec_is_infimum_low(
+/*=====================*/
/* out: TRUE if the infimum record */
- rec_t* rec); /* in: record */
+ ulint offset);/* in: record offset on page */
+
/****************************************************************
-TRUE if the record is the first user record on the page. */
+TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
-page_rec_is_first_user_rec(
-/*=======================*/
- /* out: TRUE if first user record */
- rec_t* rec); /* in: record */
+page_rec_is_user_rec(
+/*=================*/
+ /* out: TRUE if a user record */
+ const rec_t* rec); /* in: record */
/****************************************************************
-TRUE if the record is the last user record on the page. */
+TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_last_user_rec(
-/*======================*/
- /* out: TRUE if last user record */
- rec_t* rec); /* in: record */
+page_rec_is_supremum(
+/*=================*/
+ /* out: TRUE if the supremum record */
+ const rec_t* rec); /* in: record */
+/****************************************************************
+TRUE if the record is the infimum record on a page. */
+UNIV_INLINE
+ibool
+page_rec_is_infimum(
+/*================*/
+ /* out: TRUE if the infimum record */
+ const rec_t* rec); /* in: record */
/*******************************************************************
Looks for the record which owns the given record. */
UNIV_INLINE
@@ -446,9 +508,11 @@ page_get_max_insert_size_after_reorganize(
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
-page_get_free_space_of_empty(void);
-/*==============================*/
- /* out: free space */
+page_get_free_space_of_empty(
+/*=========================*/
+ /* out: free space */
+ ulint comp) /* in: nonzero=compact page format */
+ __attribute__((const));
/****************************************************************
Returns the sum of the sizes of the records in the record list
excluding the infimum and supremum records. */
@@ -464,20 +528,23 @@ Allocates a block of memory from an index page. */
byte*
page_mem_alloc(
/*===========*/
- /* out: pointer to start of allocated
- buffer, or NULL if allocation fails */
- page_t* page, /* in: index page */
- ulint need, /* in: number of bytes needed */
- ulint* heap_no);/* out: this contains the heap number
- of the allocated record if allocation succeeds */
+ /* out: pointer to start of allocated
+ buffer, or NULL if allocation fails */
+ page_t* page, /* in: index page */
+ ulint need, /* in: number of bytes needed */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* heap_no);/* out: this contains the heap number
+ of the allocated record
+ if allocation succeeds */
/****************************************************************
Puts a record to free list. */
UNIV_INLINE
void
page_mem_free(
/*==========*/
- page_t* page, /* in: index page */
- rec_t* rec); /* in: pointer to the (origin of) record */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: pointer to the (origin of) record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
The index page creation function. */
@@ -487,7 +554,8 @@ page_create(
/* out: pointer to the page */
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
- mtr_t* mtr); /* in: mini-transaction handle */
+ mtr_t* mtr, /* in: mini-transaction handle */
+ ulint comp); /* in: nonzero=compact page format */
/*****************************************************************
Differs from page_copy_rec_list_end, because this function does not
touch the lock table and max trx id on page. */
@@ -495,10 +563,11 @@ touch the lock table and max trx id on page. */
void
page_copy_rec_list_end_no_locks(
/*============================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Copies records from page to new_page, from the given record onward,
including that record. Infimum and supremum records are not copied.
@@ -507,10 +576,11 @@ The records are copied to the start of the record list on new_page. */
void
page_copy_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Copies records from page to new_page, up to the given record, NOT
including that record. Infimum and supremum records are not copied.
@@ -519,10 +589,11 @@ The records are copied to the end of the record list on new_page. */
void
page_copy_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes records from a page from a given record onward, including that record.
The infimum and supremum records are not deleted. */
@@ -530,14 +601,15 @@ The infimum and supremum records are not deleted. */
void
page_delete_rec_list_end(
/*=====================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- ulint n_recs, /* in: number of records to delete, or ULINT_UNDEFINED
- if not known */
- ulint size, /* in: the sum of the sizes of the records in the end
- of the chain to delete, or ULINT_UNDEFINED if not
- known */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_recs, /* in: number of records to delete,
+ or ULINT_UNDEFINED if not known */
+ ulint size, /* in: the sum of the sizes of the
+ records in the end of the chain to
+ delete, or ULINT_UNDEFINED if not known */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes records from page, up to the given record, NOT including
that record. Infimum and supremum records are not deleted. */
@@ -545,9 +617,10 @@ that record. Infimum and supremum records are not deleted. */
void
page_delete_rec_list_start(
/*=======================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Moves record list end to another page. Moved records include
split_rec. */
@@ -555,10 +628,11 @@ split_rec. */
void
page_move_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record to move */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Moves record list start to another page. Moved records do not include
split_rec. */
@@ -566,10 +640,11 @@ split_rec. */
void
page_move_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record not to move */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record not to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/********************************************************************
Splits a directory slot which owns too many records. */
@@ -595,13 +670,16 @@ Parses a log record of a record list end or start deletion. */
byte*
page_parse_delete_rec_list(
/*=======================*/
- /* out: end of log record or NULL */
- byte type, /* in: MLOG_LIST_END_DELETE or
- MLOG_LIST_START_DELETE */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte type, /* in: MLOG_LIST_END_DELETE,
+ MLOG_LIST_START_DELETE,
+ MLOG_COMP_LIST_END_DELETE or
+ MLOG_COMP_LIST_START_DELETE */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses a redo log record of creating a page. */
@@ -611,6 +689,7 @@ page_parse_create(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
+ ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/****************************************************************
@@ -620,7 +699,8 @@ the index page context. */
void
page_rec_print(
/*===========*/
- rec_t* rec);
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: record descriptor */
/*******************************************************************
This is used to print the contents of the directory for
debugging purposes. */
@@ -637,8 +717,9 @@ debugging purposes. */
void
page_print_list(
/*============*/
- page_t* page, /* in: index page */
- ulint pr_n); /* in: print n first and n last entries */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint pr_n); /* in: print n first and n last entries */
/*******************************************************************
Prints the info in a page header. */
@@ -653,9 +734,12 @@ debugging purposes. */
void
page_print(
/*======*/
- page_t* page, /* in: index page */
- ulint dn, /* in: print dn first and last entries in directory */
- ulint rn); /* in: print rn first and last records on page */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint dn, /* in: print dn first and last entries
+ in directory */
+ ulint rn); /* in: print rn first and last records
+ in directory */
/*******************************************************************
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and
@@ -664,8 +748,9 @@ the heap_no field. */
ibool
page_rec_validate(
/*==============*/
- /* out: TRUE if ok */
- rec_t* rec); /* in: record on the page */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Checks that the first directory slot points to the infimum record and
the last to the supremum. This function is intended to track if the
diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic
index c7bf78040e9..655ff245aa8 100644
--- a/innobase/include/page0page.ic
+++ b/innobase/include/page0page.ic
@@ -73,7 +73,8 @@ page_header_set_field(
{
ut_ad(page);
ut_ad(field <= PAGE_N_RECS);
- ut_ad(val < UNIV_PAGE_SIZE);
+ ut_ad(field == PAGE_N_HEAP || val < UNIV_PAGE_SIZE);
+ ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < UNIV_PAGE_SIZE);
mach_write_to_2(page + PAGE_HEADER + field, val);
}
@@ -152,6 +153,45 @@ page_header_reset_last_insert(
}
/****************************************************************
+Determine whether the page is in new-style compact format. */
+UNIV_INLINE
+ulint
+page_is_comp(
+/*=========*/
+ /* out: nonzero if the page is in compact
+ format, zero if it is in old-style format */
+ page_t* page) /* in: index page */
+{
+ return(UNIV_EXPECT(page_header_get_field(page, PAGE_N_HEAP) & 0x8000,
+ 0x8000));
+}
+
+/****************************************************************
+TRUE if the record is on a page in compact format. */
+UNIV_INLINE
+ulint
+page_rec_is_comp(
+/*=============*/
+ /* out: nonzero if in compact format */
+ const rec_t* rec) /* in: record */
+{
+#ifdef UNIV_RELEASE_NOT_YET_STABLE
+ if (UNIV_UNLIKELY((ulint)rec < (ulint)(buf_pool->frame_zero))
+ || UNIV_UNLIKELY((ulint)rec >= (ulint)(buf_pool->high_end))) {
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+"InnoDB: Error: trying to read a stray page rec %p\n"
+"InnoDB: buf pool start is at %p, end at %p\n",
+ rec, buf_pool->frame_zero,
+ buf_pool->high_end);
+ ut_error;
+ }
+#endif
+ return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE)));
+}
+
+/****************************************************************
Gets the first record on the page. */
UNIV_INLINE
rec_t*
@@ -162,7 +202,11 @@ page_get_infimum_rec(
{
ut_ad(page);
- return(page + PAGE_INFIMUM);
+ if (page_is_comp(page)) {
+ return(page + PAGE_NEW_INFIMUM);
+ } else {
+ return(page + PAGE_OLD_INFIMUM);
+ }
}
/****************************************************************
@@ -176,119 +220,118 @@ page_get_supremum_rec(
{
ut_ad(page);
- return(page + PAGE_SUPREMUM);
+ if (page_is_comp(page)) {
+ return(page + PAGE_NEW_SUPREMUM);
+ } else {
+ return(page + PAGE_OLD_SUPREMUM);
+ }
}
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
-page_rec_is_user_rec(
-/*=================*/
+page_rec_is_user_rec_low(
+/*=====================*/
/* out: TRUE if a user record */
- rec_t* rec) /* in: record */
+ ulint offset) /* in: record offset on page */
{
- ut_ad(rec);
-
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(FALSE);
- }
-
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
-
- return(FALSE);
- }
+ ut_ad(offset >= PAGE_NEW_INFIMUM);
+#if PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM
+# error "PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM"
+#endif
+#if PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM
+# error "PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM"
+#endif
+#if PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM
+# error "PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM"
+#endif
+#if PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM
+# error "PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM"
+#endif
+#if PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END
+# error "PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END"
+#endif
+#if PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END
+# error "PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END"
+#endif
+ ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
- return(TRUE);
+ return(UNIV_LIKELY(offset != PAGE_NEW_SUPREMUM)
+ && UNIV_LIKELY(offset != PAGE_NEW_INFIMUM)
+ && UNIV_LIKELY(offset != PAGE_OLD_INFIMUM)
+ && UNIV_LIKELY(offset != PAGE_OLD_SUPREMUM));
}
/****************************************************************
TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_supremum(
-/*=================*/
+page_rec_is_supremum_low(
+/*=====================*/
/* out: TRUE if the supremum record */
- rec_t* rec) /* in: record */
+ ulint offset) /* in: record offset on page */
{
- ut_ad(rec);
-
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(TRUE);
- }
+ ut_ad(offset >= PAGE_NEW_INFIMUM);
+ ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
- return(FALSE);
+ return(UNIV_UNLIKELY(offset == PAGE_NEW_SUPREMUM)
+ || UNIV_UNLIKELY(offset == PAGE_OLD_SUPREMUM));
}
/****************************************************************
TRUE if the record is the infimum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_infimum(
-/*================*/
+page_rec_is_infimum_low(
+/*=====================*/
/* out: TRUE if the infimum record */
- rec_t* rec) /* in: record */
+ ulint offset) /* in: record offset on page */
{
- ut_ad(rec);
+ ut_ad(offset >= PAGE_NEW_INFIMUM);
+ ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(UNIV_UNLIKELY(offset == PAGE_NEW_INFIMUM)
+ || UNIV_UNLIKELY(offset == PAGE_OLD_INFIMUM));
}
/****************************************************************
-TRUE if the record is the first user record on the page. */
+TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
-page_rec_is_first_user_rec(
-/*=======================*/
- /* out: TRUE if first user record */
- rec_t* rec) /* in: record */
+page_rec_is_user_rec(
+/*=================*/
+ /* out: TRUE if a user record */
+ const rec_t* rec) /* in: record */
{
- ut_ad(rec);
-
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(FALSE);
- }
-
- if (rec == page_rec_get_next(
- page_get_infimum_rec(buf_frame_align(rec)))) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(page_rec_is_user_rec_low(
+ ut_align_offset(rec, UNIV_PAGE_SIZE)));
}
/****************************************************************
-TRUE if the record is the last user record on the page. */
+TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
-page_rec_is_last_user_rec(
-/*======================*/
- /* out: TRUE if last user record */
- rec_t* rec) /* in: record */
+page_rec_is_supremum(
+/*=================*/
+ /* out: TRUE if the supremum record */
+ const rec_t* rec) /* in: record */
{
- ut_ad(rec);
-
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(FALSE);
- }
-
- if (page_rec_get_next(rec)
- == page_get_supremum_rec(buf_frame_align(rec))) {
-
- return(TRUE);
- }
+ return(page_rec_is_supremum_low(
+ ut_align_offset(rec, UNIV_PAGE_SIZE)));
+}
- return(FALSE);
+/****************************************************************
+TRUE if the record is the infimum record on a page. */
+UNIV_INLINE
+ibool
+page_rec_is_infimum(
+/*================*/
+ /* out: TRUE if the infimum record */
+ const rec_t* rec) /* in: record */
+{
+ return(page_rec_is_infimum_low(
+ ut_align_offset(rec, UNIV_PAGE_SIZE)));
}
/*****************************************************************
@@ -309,6 +352,7 @@ page_cmp_dtuple_rec_with_match(
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
@@ -317,21 +361,26 @@ page_cmp_dtuple_rec_with_match(
matched; when function returns contains the
value for current comparison */
{
- page_t* page;
+ ulint rec_offset;
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec));
- page = buf_frame_align(rec);
+ rec_offset = ut_align_offset(rec, UNIV_PAGE_SIZE);
- if (rec == page_get_infimum_rec(page)) {
+ if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_INFIMUM)
+ || UNIV_UNLIKELY(rec_offset == PAGE_OLD_INFIMUM)) {
return(1);
- } else if (rec == page_get_supremum_rec(page)) {
+ }
+ if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_SUPREMUM)
+ || UNIV_UNLIKELY(rec_offset == PAGE_OLD_SUPREMUM)) {
return(-1);
- } else {
- return(cmp_dtuple_rec_with_match(dtuple, rec,
+ }
+
+ return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields,
matched_bytes));
- }
}
/*****************************************************************
@@ -358,6 +407,45 @@ page_dir_get_n_slots(
{
return(page_header_get_field(page, PAGE_N_DIR_SLOTS));
}
+/*****************************************************************
+Sets the number of dir slots in directory. */
+UNIV_INLINE
+void
+page_dir_set_n_slots(
+/*=================*/
+ /* out: number of slots */
+ page_t* page, /* in: index page */
+ ulint n_slots)/* in: number of slots */
+{
+ page_header_set_field(page, PAGE_N_DIR_SLOTS, n_slots);
+}
+
+/*****************************************************************
+Gets the number of records in the heap. */
+UNIV_INLINE
+ulint
+page_dir_get_n_heap(
+/*================*/
+ /* out: number of user records */
+ page_t* page) /* in: index page */
+{
+ return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff);
+}
+
+/*****************************************************************
+Sets the number of records in the heap. */
+UNIV_INLINE
+void
+page_dir_set_n_heap(
+/*================*/
+ page_t* page, /* in: index page */
+ ulint n_heap) /* in: number of records */
+{
+ ut_ad(n_heap < 0x8000);
+
+ page_header_set_field(page, PAGE_N_HEAP, n_heap | (0x8000 &
+ page_header_get_field(page, PAGE_N_HEAP)));
+}
/*****************************************************************
Gets pointer to nth directory slot. */
@@ -369,7 +457,7 @@ page_dir_get_nth_slot(
page_t* page, /* in: index page */
ulint n) /* in: position */
{
- ut_ad(page_header_get_field(page, PAGE_N_DIR_SLOTS) > n);
+ ut_ad(page_dir_get_n_slots(page) > n);
return(page + UNIV_PAGE_SIZE - PAGE_DIR
- (n + 1) * PAGE_DIR_SLOT_SIZE);
@@ -419,7 +507,7 @@ page_dir_slot_set_rec(
{
ut_ad(page_rec_check(rec));
- mach_write_to_2(slot, rec - buf_frame_align(rec));
+ mach_write_to_2(slot, ut_align_offset(rec, UNIV_PAGE_SIZE));
}
/*******************************************************************
@@ -431,7 +519,8 @@ page_dir_slot_get_n_owned(
/* out: number of records */
page_dir_slot_t* slot) /* in: page directory slot */
{
- return(rec_get_n_owned(page_dir_slot_get_rec(slot)));
+ rec_t* rec = page_dir_slot_get_rec(slot);
+ return(rec_get_n_owned(rec, page_rec_is_comp(rec)));
}
/*******************************************************************
@@ -444,7 +533,8 @@ page_dir_slot_set_n_owned(
ulint n) /* in: number of records owned
by the slot */
{
- rec_set_n_owned(page_dir_slot_get_rec(slot), n);
+ rec_t* rec = page_dir_slot_get_rec(slot);
+ rec_set_n_owned(rec, page_rec_is_comp(rec), n);
}
/****************************************************************
@@ -475,26 +565,25 @@ page_rec_get_next(
ut_ad(page_rec_check(rec));
- page = buf_frame_align(rec);
+ page = ut_align_down(rec, UNIV_PAGE_SIZE);
- offs = rec_get_next_offs(rec);
+ offs = rec_get_next_offs(rec, page_is_comp(page));
- if (offs >= UNIV_PAGE_SIZE) {
- fprintf(stderr,
-"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n",
- (ulong)offs, (ulong)(rec - page));
+ if (UNIV_UNLIKELY(offs >= UNIV_PAGE_SIZE)) {
fprintf(stderr,
-"\nInnoDB: rec address %p, first buffer frame %p\n"
+"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n"
+"InnoDB: rec address %p, first buffer frame %p\n"
"InnoDB: buffer pool high end %p, buf fix count %lu\n",
+ (ulong)offs, (ulong)(rec - page),
rec, buf_pool->frame_zero,
buf_pool->high_end,
(ulong)buf_block_align(rec)->buf_fix_count);
buf_page_print(page);
- ut_a(0);
+ ut_error;
}
- if (offs == 0) {
+ if (UNIV_UNLIKELY(offs == 0)) {
return(NULL);
}
@@ -513,21 +602,21 @@ page_rec_set_next(
infimum */
{
page_t* page;
+ ulint offs;
ut_ad(page_rec_check(rec));
- ut_a((next == NULL)
- || (buf_frame_align(rec) == buf_frame_align(next)));
+ ut_ad(!page_rec_is_supremum(rec));
+ page = ut_align_down(rec, UNIV_PAGE_SIZE);
- page = buf_frame_align(rec);
-
- ut_ad(rec != page_get_supremum_rec(page));
- ut_ad(next != page_get_infimum_rec(page));
-
- if (next == NULL) {
- rec_set_next_offs(rec, 0);
+ if (next) {
+ ut_ad(!page_rec_is_infimum(next));
+ ut_ad(page == ut_align_down(next, UNIV_PAGE_SIZE));
+ offs = (ulint) (next - page);
} else {
- rec_set_next_offs(rec, (ulint)(next - page));
+ offs = 0;
}
+
+ rec_set_next_offs(rec, page_is_comp(page), offs);
}
/****************************************************************
@@ -548,9 +637,9 @@ page_rec_get_prev(
ut_ad(page_rec_check(rec));
- page = buf_frame_align(rec);
+ page = ut_align_down(rec, UNIV_PAGE_SIZE);
- ut_ad(rec != page_get_infimum_rec(page));
+ ut_ad(!page_rec_is_infimum(rec));
slot_no = page_dir_find_owner_slot(rec);
@@ -581,8 +670,14 @@ page_rec_find_owner_rec(
{
ut_ad(page_rec_check(rec));
- while (rec_get_n_owned(rec) == 0) {
- rec = page_rec_get_next(rec);
+ if (page_rec_is_comp(rec)) {
+ while (rec_get_n_owned(rec, TRUE) == 0) {
+ rec = page_rec_get_next(rec);
+ }
+ } else {
+ while (rec_get_n_owned(rec, FALSE) == 0) {
+ rec = page_rec_get_next(rec);
+ }
}
return(rec);
@@ -601,7 +696,9 @@ page_get_data_size(
ulint ret;
ret = (ulint)(page_header_get_field(page, PAGE_HEAP_TOP)
- - PAGE_SUPREMUM_END
+ - (page_is_comp(page)
+ ? PAGE_NEW_SUPREMUM_END
+ : PAGE_OLD_SUPREMUM_END)
- page_header_get_field(page, PAGE_GARBAGE));
ut_ad(ret < UNIV_PAGE_SIZE);
@@ -613,12 +710,20 @@ page_get_data_size(
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
-page_get_free_space_of_empty(void)
-/*==============================*/
+page_get_free_space_of_empty(
+/*=========================*/
/* out: free space */
+ ulint comp) /* in: nonzero=compact page layout */
{
+ if (UNIV_LIKELY(comp)) {
+ return((ulint)(UNIV_PAGE_SIZE
+ - PAGE_NEW_SUPREMUM_END
+ - PAGE_DIR
+ - 2 * PAGE_DIR_SLOT_SIZE));
+ }
+
return((ulint)(UNIV_PAGE_SIZE
- - PAGE_SUPREMUM_END
+ - PAGE_OLD_SUPREMUM_END
- PAGE_DIR
- 2 * PAGE_DIR_SLOT_SIZE));
}
@@ -641,13 +746,20 @@ page_get_max_insert_size(
ulint occupied;
ulint free_space;
- occupied = page_header_get_field(page, PAGE_HEAP_TOP)
- - PAGE_SUPREMUM_END
- + page_dir_calc_reserved_space(
- n_recs + (page_header_get_field(page, PAGE_N_HEAP) - 2));
+ if (page_is_comp(page)) {
+ occupied = page_header_get_field(page, PAGE_HEAP_TOP)
+ - PAGE_NEW_SUPREMUM_END + page_dir_calc_reserved_space(
+ n_recs + page_dir_get_n_heap(page) - 2);
+
+ free_space = page_get_free_space_of_empty(TRUE);
+ } else {
+ occupied = page_header_get_field(page, PAGE_HEAP_TOP)
+ - PAGE_OLD_SUPREMUM_END + page_dir_calc_reserved_space(
+ n_recs + page_dir_get_n_heap(page) - 2);
+
+ free_space = page_get_free_space_of_empty(FALSE);
+ }
- free_space = page_get_free_space_of_empty();
-
/* Above the 'n_recs +' part reserves directory space for the new
inserted records; the '- 2' excludes page infimum and supremum
records */
@@ -673,11 +785,11 @@ page_get_max_insert_size_after_reorganize(
{
ulint occupied;
ulint free_space;
-
+
occupied = page_get_data_size(page)
+ page_dir_calc_reserved_space(n_recs + page_get_n_recs(page));
- free_space = page_get_free_space_of_empty();
+ free_space = page_get_free_space_of_empty(page_is_comp(page));
if (occupied > free_space) {
@@ -693,21 +805,34 @@ UNIV_INLINE
void
page_mem_free(
/*==========*/
- page_t* page, /* in: index page */
- rec_t* rec) /* in: pointer to the (origin of) record */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: pointer to the (origin of) record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- rec_t* free;
- ulint garbage;
+ rec_t* free;
+ ulint garbage;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec));
free = page_header_get_ptr(page, PAGE_FREE);
page_rec_set_next(rec, free);
page_header_set_ptr(page, PAGE_FREE, rec);
+#if 0 /* It's better not to destroy the user's data. */
+
+ /* Clear the data bytes of the deleted record in order to improve
+ the compression ratio of the page and to make it easier to read
+ page dumps in corruption reports. The extra bytes of the record
+ cannot be cleared, because page_mem_alloc() needs them in order
+ to determine the size of the deleted record. */
+ memset(rec, 0, rec_offs_data_size(offsets));
+#endif
+
garbage = page_header_get_field(page, PAGE_GARBAGE);
page_header_set_field(page, PAGE_GARBAGE,
- garbage + rec_get_size(rec));
+ garbage + rec_offs_size(offsets));
}
#ifdef UNIV_MATERIALIZE
diff --git a/innobase/include/que0que.h b/innobase/include/que0que.h
index e1874edcaf2..4113e52d425 100644
--- a/innobase/include/que0que.h
+++ b/innobase/include/que0que.h
@@ -359,6 +359,8 @@ struct que_thr_struct{
the control came */
ulint resource; /* resource usage of the query thread
thus far */
+ ulint lock_state; /* lock state of thread (table or
+ row) */
};
#define QUE_THR_MAGIC_N 8476583
@@ -482,6 +484,11 @@ struct que_fork_struct{
#define QUE_THR_SUSPENDED 7
#define QUE_THR_ERROR 8
+/* Query thread lock states */
+#define QUE_THR_LOCK_NOLOCK 0
+#define QUE_THR_LOCK_ROW 1
+#define QUE_THR_LOCK_TABLE 2
+
/* From where the cursor position is counted */
#define QUE_CUR_NOT_DEFINED 1
#define QUE_CUR_START 2
diff --git a/innobase/include/read0read.h b/innobase/include/read0read.h
index db6bf888095..7a91248cf7f 100644
--- a/innobase/include/read0read.h
+++ b/innobase/include/read0read.h
@@ -68,7 +68,34 @@ void
read_view_print(
/*============*/
read_view_t* view); /* in: read view */
+/*************************************************************************
+Create a consistent cursor view for mysql to be used in cursors. In this
+consistent read view modifications done by the creating transaction or future
+transactions are not visible. */
+
+cursor_view_t*
+read_cursor_view_create_for_mysql(
+/*==============================*/
+ trx_t* cr_trx);/* in: trx where cursor view is created */
+/*************************************************************************
+Close a given consistent cursor view for mysql and restore global read view
+back to a transaction read view. */
+
+void
+read_cursor_view_close_for_mysql(
+/*=============================*/
+ trx_t* trx, /* in: trx */
+ cursor_view_t* curview); /* in: cursor view to be closed */
+/*************************************************************************
+This function sets a given consistent cursor view to a transaction
+read view if given consistent cursor view is not NULL. Otherwise, function
+restores a global read view to a transaction read view. */
+void
+read_cursor_set_for_mysql(
+/*======================*/
+ trx_t* trx, /* in: transaction where cursor is set */
+ cursor_view_t* curview);/* in: consistent cursor view to be set */
/* Read view lists the trx ids of those transactions for which a consistent
read should not see the modifications to the database. */
@@ -100,6 +127,20 @@ struct read_view_struct{
/* List of read views in trx_sys */
};
+/* Implement InnoDB framework to support consistent read views in
+cursors. This struct holds both heap where consistent read view
+is allocated and pointer to a read view. */
+
+struct cursor_view_struct{
+ mem_heap_t* heap;
+ /* Memory heap for the cursor view */
+ read_view_t* read_view;
+ /* Consistent read view of the cursor*/
+ ulint n_mysql_tables_in_use;
+ /* number of Innobase tables used in the
+ processing of this cursor */
+};
+
#ifndef UNIV_NONINL
#include "read0read.ic"
#endif
diff --git a/innobase/include/read0read.ic b/innobase/include/read0read.ic
index 03d84ee0c51..ec9ef5814bb 100644
--- a/innobase/include/read0read.ic
+++ b/innobase/include/read0read.ic
@@ -71,13 +71,8 @@ read_view_sees_trx_id(
cmp = ut_dulint_cmp(trx_id,
read_view_get_nth_trx_id(view, n_ids - i - 1));
- if (0 == cmp) {
-
- return(FALSE);
-
- } else if (cmp < 0) {
-
- return(TRUE);
+ if (cmp <= 0) {
+ return(cmp < 0);
}
}
diff --git a/innobase/include/read0types.h b/innobase/include/read0types.h
index 5eb3e533f89..7d42728523e 100644
--- a/innobase/include/read0types.h
+++ b/innobase/include/read0types.h
@@ -10,5 +10,6 @@ Created 2/16/1997 Heikki Tuuri
#define read0types_h
typedef struct read_view_struct read_view_t;
+typedef struct cursor_view_struct cursor_view_t;
#endif
diff --git a/innobase/include/rem0cmp.h b/innobase/include/rem0cmp.h
index 712e263350e..1b1ee26b809 100644
--- a/innobase/include/rem0cmp.h
+++ b/innobase/include/rem0cmp.h
@@ -90,6 +90,7 @@ cmp_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns,
contains the value for current comparison */
@@ -107,7 +108,8 @@ cmp_dtuple_rec(
less than rec, respectively; see the comments
for cmp_dtuple_rec_with_match */
dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/******************************************************************
Checks if a dtuple is a prefix of a record. The last field in dtuple
is allowed to be a prefix of the corresponding field in the record. */
@@ -116,23 +118,9 @@ ibool
cmp_dtuple_is_prefix_of_rec(
/*========================*/
/* out: TRUE if prefix */
- dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec); /* in: physical record */
-/******************************************************************
-Compares a prefix of a data tuple to a prefix of a physical record for
-equality. If there are less fields in rec than parameter n_fields, FALSE
-is returned. NOTE that n_fields_cmp of dtuple does not affect this
-comparison. */
-
-ibool
-cmp_dtuple_rec_prefix_equal(
-/*========================*/
- /* out: TRUE if equal */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
- ulint n_fields); /* in: number of fields which should be
- compared; must not exceed the number of
- fields in dtuple */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*****************************************************************
This function is used to compare two physical records. Only the common
first fields are compared, and if an externally stored field is
@@ -146,6 +134,8 @@ cmp_rec_rec_with_match(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index, /* in: data dictionary index */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when the function returns,
@@ -167,6 +157,8 @@ cmp_rec_rec(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index); /* in: data dictionary index */
diff --git a/innobase/include/rem0cmp.ic b/innobase/include/rem0cmp.ic
index 75cb3ef04e8..b86534e0a6a 100644
--- a/innobase/include/rem0cmp.ic
+++ b/innobase/include/rem0cmp.ic
@@ -57,10 +57,13 @@ cmp_rec_rec(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index) /* in: data dictionary index */
{
ulint match_f = 0;
ulint match_b = 0;
- return(cmp_rec_rec_with_match(rec1, rec2, index, &match_f, &match_b));
+ return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index,
+ &match_f, &match_b));
}
diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h
index 86bf263170f..1d15b8d1c77 100644
--- a/innobase/include/rem0rec.h
+++ b/innobase/include/rem0rec.h
@@ -23,9 +23,23 @@ Created 5/30/1994 Heikki Tuuri
info bits of a record */
#define REC_INFO_MIN_REC_FLAG 0x10UL
-/* Number of extra bytes in a record, in addition to the data and the
-offsets */
-#define REC_N_EXTRA_BYTES 6
+/* Number of extra bytes in an old-style record,
+in addition to the data and the offsets */
+#define REC_N_OLD_EXTRA_BYTES 6
+/* Number of extra bytes in a new-style record,
+in addition to the data and the offsets */
+#define REC_N_NEW_EXTRA_BYTES 5
+
+/* Record status values */
+#define REC_STATUS_ORDINARY 0
+#define REC_STATUS_NODE_PTR 1
+#define REC_STATUS_INFIMUM 2
+#define REC_STATUS_SUPREMUM 3
+
+/* Number of elements that should be initially allocated for the
+offsets[] array, first passed to rec_get_offsets() */
+#define REC_OFFS_NORMAL_SIZE 100
+#define REC_OFFS_SMALL_SIZE 10
/**********************************************************
The following function is used to get the offset of the
@@ -36,7 +50,8 @@ rec_get_next_offs(
/*==============*/
/* out: the page offset of the next
chained record */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the next record offset field
of the record. */
@@ -45,17 +60,28 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
ulint next); /* in: offset of the next record */
/**********************************************************
The following function is used to get the number of fields
-in the record. */
+in an old-style record. */
UNIV_INLINE
ulint
-rec_get_n_fields(
-/*=============*/
+rec_get_n_fields_old(
+/*=================*/
/* out: number of data fields */
rec_t* rec); /* in: physical record */
/**********************************************************
+The following function is used to get the number of fields
+in a record. */
+UNIV_INLINE
+ulint
+rec_get_n_fields(
+/*=============*/
+ /* out: number of data fields */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index); /* in: record descriptor */
+/**********************************************************
The following function is used to get the number of records
owned by the previous directory record. */
UNIV_INLINE
@@ -63,7 +89,8 @@ ulint
rec_get_n_owned(
/*============*/
/* out: number of owned records */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the number of owned
records. */
@@ -72,6 +99,7 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
ulint n_owned); /* in: the number of owned */
/**********************************************************
The following function is used to retrieve the info bits of
@@ -81,7 +109,8 @@ ulint
rec_get_info_bits(
/*==============*/
/* out: info bits */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the info bits of a record. */
UNIV_INLINE
@@ -89,23 +118,56 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
ulint bits); /* in: info bits */
/**********************************************************
-Gets the value of the deleted falg in info bits. */
+The following function retrieves the status bits of a new-style record. */
UNIV_INLINE
-ibool
-rec_info_bits_get_deleted_flag(
-/*===========================*/
- /* out: TRUE if deleted flag set */
- ulint info_bits); /* in: info bits from a record */
+ulint
+rec_get_status(
+/*===========*/
+ /* out: status bits */
+ rec_t* rec); /* in: physical record */
+
+/**********************************************************
+The following function is used to set the status bits of a new-style record. */
+UNIV_INLINE
+void
+rec_set_status(
+/*===========*/
+ rec_t* rec, /* in: physical record */
+ ulint bits); /* in: info bits */
+
+/**********************************************************
+The following function is used to retrieve the info and status
+bits of a record. (Only compact records have status bits.) */
+UNIV_INLINE
+ulint
+rec_get_info_and_status_bits(
+/*=========================*/
+ /* out: info bits */
+ rec_t* rec, /* in: physical record */
+ ulint comp); /* in: nonzero=compact page format */
+/**********************************************************
+The following function is used to set the info and status
+bits of a record. (Only compact records have status bits.) */
+UNIV_INLINE
+void
+rec_set_info_and_status_bits(
+/*=========================*/
+ rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
+ ulint bits); /* in: info bits */
+
/**********************************************************
The following function tells if record is delete marked. */
UNIV_INLINE
-ibool
+ulint
rec_get_deleted_flag(
/*=================*/
- /* out: TRUE if delete marked */
- rec_t* rec); /* in: physical record */
+ /* out: nonzero if delete marked */
+ rec_t* rec, /* in: physical record */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the deleted bit. */
UNIV_INLINE
@@ -113,7 +175,16 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
- ibool flag); /* in: TRUE if delete marked */
+ ulint comp, /* in: nonzero=compact page format */
+ ulint flag); /* in: nonzero if delete marked */
+/**********************************************************
+The following function tells if a new-style record is a node pointer. */
+UNIV_INLINE
+ibool
+rec_get_node_ptr_flag(
+/*=================*/
+ /* out: TRUE if node pointer */
+ rec_t* rec); /* in: physical record */
/**********************************************************
The following function is used to get the order number
of the record in the heap of the index page. */
@@ -122,7 +193,8 @@ ulint
rec_get_heap_no(
/*=============*/
/* out: heap order number */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the heap number
field in the record. */
@@ -131,6 +203,7 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
ulint heap_no);/* in: the heap number */
/**********************************************************
The following function is used to test whether the data offsets
@@ -141,31 +214,65 @@ rec_get_1byte_offs_flag(
/*====================*/
/* out: TRUE if 1-byte form */
rec_t* rec); /* in: physical record */
+/**********************************************************
+The following function determines the offsets to each field
+in the record. It can reuse a previously allocated array. */
+
+ulint*
+rec_get_offsets_func(
+/*=================*/
+ /* out: the new offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets,/* in: array consisting of offsets[0]
+ allocated elements, or an array from
+ rec_get_offsets(), or NULL */
+ ulint n_fields,/* in: maximum number of initialized fields
+ (ULINT_UNDEFINED if all fields) */
+ mem_heap_t** heap, /* in/out: memory heap */
+ const char* file, /* in: file name where called */
+ ulint line); /* in: line number where called */
+
+#define rec_get_offsets(rec,index,offsets,n,heap) \
+ rec_get_offsets_func(rec,index,offsets,n,heap,__FILE__,__LINE__)
+
+/****************************************************************
+Validates offsets returned by rec_get_offsets(). */
+UNIV_INLINE
+ibool
+rec_offs_validate(
+/*==============*/
+ /* out: TRUE if valid */
+ rec_t* rec, /* in: record or NULL */
+ dict_index_t* index, /* in: record descriptor or NULL */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/****************************************************************
+Updates debug data in offsets, in order to avoid bogus
+rec_offs_validate() failures. */
+UNIV_INLINE
+void
+rec_offs_make_valid(
+/*================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index,/* in: record descriptor */
+ ulint* offsets);/* in: array returned by rec_get_offsets() */
+
/****************************************************************
The following function is used to get a pointer to the nth
-data field in the record. */
+data field in an old-style record. */
byte*
-rec_get_nth_field(
-/*==============*/
+rec_get_nth_field_old(
+/*==================*/
/* out: pointer to the field */
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
ulint* len); /* out: length of the field; UNIV_SQL_NULL
if SQL null */
/****************************************************************
-Return field length or UNIV_SQL_NULL. */
-UNIV_INLINE
-ulint
-rec_get_nth_field_len(
-/*==================*/
- /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
- rec_t* rec, /* in: record */
- ulint n); /* in: index of the field */
-/****************************************************************
-Gets the physical size of a field. Also an SQL null may have a field of
-size > 0, if the data type is of a fixed size. */
+Gets the physical size of an old-style field.
+Also an SQL null may have a field of size > 0,
+if the data type is of a fixed size. */
UNIV_INLINE
ulint
rec_get_nth_field_size(
@@ -173,131 +280,176 @@ rec_get_nth_field_size(
/* out: field size in bytes */
rec_t* rec, /* in: record */
ulint n); /* in: index of the field */
-/***************************************************************
-Gets the value of the ith field extern storage bit. If it is TRUE
-it means that the field is stored on another page. */
+/****************************************************************
+The following function is used to get a pointer to the nth
+data field in a record. */
UNIV_INLINE
-ibool
-rec_get_nth_field_extern_bit(
-/*=========================*/
- /* in: TRUE or FALSE */
- rec_t* rec, /* in: record */
- ulint i); /* in: ith field */
+byte*
+rec_get_nth_field(
+/*==============*/
+ /* out: pointer to the field */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index of the field */
+ ulint* len); /* out: length of the field; UNIV_SQL_NULL
+ if SQL null */
+/**********************************************************
+Determine if the offsets are for a record in the new
+compact format. */
+UNIV_INLINE
+ulint
+rec_offs_comp(
+/*==========*/
+ /* out: nonzero if compact format */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**********************************************************
+Returns nonzero if the extern bit is set in nth field of rec. */
+UNIV_INLINE
+ulint
+rec_offs_nth_extern(
+/*================*/
+ /* out: nonzero if externally stored */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n); /* in: nth field */
+/**********************************************************
+Gets the physical size of a field. */
+UNIV_INLINE
+ulint
+rec_offs_nth_size(
+/*==============*/
+ /* out: length of field */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n); /* in: nth field */
+
/**********************************************************
Returns TRUE if the extern bit is set in any of the fields
of rec. */
UNIV_INLINE
ibool
-rec_contains_externally_stored_field(
-/*=================================*/
- /* out: TRUE if a field is stored externally */
- rec_t* rec); /* in: record */
+rec_offs_any_extern(
+/*================*/
+ /* out: TRUE if a field is stored externally */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/***************************************************************
Sets the value of the ith field extern storage bit. */
-
+UNIV_INLINE
void
rec_set_nth_field_extern_bit(
/*=========================*/
- rec_t* rec, /* in: record */
- ulint i, /* in: ith field */
- ibool val, /* in: value to set */
- mtr_t* mtr); /* in: mtr holding an X-latch to the page where
- rec is, or NULL; in the NULL case we do not
- write to log about the change */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
/***************************************************************
Sets TRUE the extern storage bits of fields mentioned in an array. */
void
rec_set_field_extern_bits(
/*======================*/
- rec_t* rec, /* in: record */
- ulint* vec, /* in: array of field numbers */
- ulint n_fields, /* in: number of fields numbers */
- mtr_t* mtr); /* in: mtr holding an X-latch to the page
- where rec is, or NULL; in the NULL case we
- do not write to log about the change */
-/****************************************************************
-The following function is used to get a copy of the nth
-data field in the record to a buffer. */
-UNIV_INLINE
-void
-rec_copy_nth_field(
-/*===============*/
- void* buf, /* in: pointer to the buffer */
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- ulint* len); /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ const ulint* vec, /* in: array of field numbers */
+ ulint n_fields,/* in: number of fields numbers */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
/***************************************************************
-This is used to modify the value of an already existing field in
-a physical record. The previous value must have exactly the same
-size as the new value. If len is UNIV_SQL_NULL then the field is
-treated as SQL null. */
+This is used to modify the value of an already existing field in a record.
+The previous value must have exactly the same size as the new value. If len
+is UNIV_SQL_NULL then the field is treated as an SQL null for old-style
+records. For new-style records, len must not be UNIV_SQL_NULL. */
UNIV_INLINE
void
rec_set_nth_field(
/*==============*/
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- void* data, /* in: pointer to the data if not SQL null */
- ulint len); /* in: length of the data or UNIV_SQL_NULL.
- If not SQL null, must have the same length as the
- previous value. If SQL null, previous value must be
- SQL null. */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index number of the field */
+ const void* data, /* in: pointer to the data if not SQL null */
+ ulint len); /* in: length of the data or UNIV_SQL_NULL.
+ If not SQL null, must have the same
+ length as the previous value.
+ If SQL null, previous value must be
+ SQL null. */
/**************************************************************
-The following function returns the data size of a physical
+The following function returns the data size of an old-style physical
record, that is the sum of field lengths. SQL null fields
are counted as length 0 fields. The value returned by the function
is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
-rec_get_data_size(
-/*==============*/
- /* out: size */
+rec_get_data_size_old(
+/*==================*/
+ /* out: size */
rec_t* rec); /* in: physical record */
/**************************************************************
+The following function returns the number of fields in a record. */
+UNIV_INLINE
+ulint
+rec_offs_n_fields(
+/*===============*/
+ /* out: number of fields */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
+The following function returns the data size of a physical
+record, that is the sum of field lengths. SQL null fields
+are counted as length 0 fields. The value returned by the function
+is the distance from record origin to record end in bytes. */
+UNIV_INLINE
+ulint
+rec_offs_data_size(
+/*===============*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
Returns the total size of record minus data size of record.
The value returned by the function is the distance from record
start to record origin in bytes. */
UNIV_INLINE
ulint
-rec_get_extra_size(
-/*===============*/
- /* out: size */
- rec_t* rec); /* in: physical record */
-/**************************************************************
+rec_offs_extra_size(
+/*================*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
Returns the total size of a physical record. */
UNIV_INLINE
ulint
-rec_get_size(
-/*=========*/
- /* out: size */
- rec_t* rec); /* in: physical record */
+rec_offs_size(
+/*==========*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
Returns a pointer to the start of the record. */
UNIV_INLINE
byte*
rec_get_start(
/*==========*/
- /* out: pointer to start */
- rec_t* rec); /* in: pointer to record */
+ /* out: pointer to start */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
Returns a pointer to the end of the record. */
UNIV_INLINE
byte*
rec_get_end(
/*========*/
- /* out: pointer to end */
- rec_t* rec); /* in: pointer to record */
+ /* out: pointer to end */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Copies a physical record to a buffer. */
UNIV_INLINE
rec_t*
rec_copy(
/*=====*/
- /* out: pointer to the origin of the copied record */
- void* buf, /* in: buffer */
- rec_t* rec); /* in: physical record */
+ /* out: pointer to the origin of the copy */
+ void* buf, /* in: buffer */
+ const rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/******************************************************************
Copies the first n fields of a physical record to a new physical record in
a buffer. */
@@ -305,49 +457,43 @@ a buffer. */
rec_t*
rec_copy_prefix_to_buf(
/*===================*/
- /* out, own: copied record */
- rec_t* rec, /* in: physical record */
- ulint n_fields, /* in: number of fields to copy */
- byte** buf, /* in/out: memory buffer for the copied prefix,
- or NULL */
- ulint* buf_size); /* in/out: buffer size */
+ /* out, own: copied record */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_fields, /* in: number of fields to copy */
+ byte** buf, /* in/out: memory buffer
+ for the copied prefix, or NULL */
+ ulint* buf_size); /* in/out: buffer size */
/****************************************************************
Folds a prefix of a physical record to a ulint. */
UNIV_INLINE
ulint
rec_fold(
/*=====*/
- /* out: the folded value */
- rec_t* rec, /* in: the physical record */
- ulint n_fields, /* in: number of complete fields to fold */
- ulint n_bytes, /* in: number of bytes to fold in an
- incomplete last field */
- dulint tree_id); /* in: index tree id */
+ /* out: the folded value */
+ rec_t* rec, /* in: the physical record */
+ const ulint* offsets, /* in: array returned by
+ rec_get_offsets() */
+ ulint n_fields, /* in: number of complete
+ fields to fold */
+ ulint n_bytes, /* in: number of bytes to fold
+ in an incomplete last field */
+ dulint tree_id); /* in: index tree id */
/*************************************************************
Builds a physical record out of a data tuple and stores it beginning from
address destination. */
-UNIV_INLINE
+
rec_t*
rec_convert_dtuple_to_rec(
/*======================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple); /* in: data tuple */
-/*************************************************************
-Builds a physical record out of a data tuple and stores it beginning from
-address destination. */
-
-rec_t*
-rec_convert_dtuple_to_rec_low(
-/*==========================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple, /* in: data tuple */
- ulint data_size); /* in: data size of dtuple */
+ /* out: pointer to the origin
+ of physical record */
+ byte* buf, /* in: start address of the
+ physical record */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple);/* in: data tuple */
/**************************************************************
-Returns the extra size of a physical record if we know its
+Returns the extra size of an old-style physical record if we know its
data size and number of fields. */
UNIV_INLINE
ulint
@@ -355,7 +501,8 @@ rec_get_converted_extra_size(
/*=========================*/
/* out: extra size */
ulint data_size, /* in: data size */
- ulint n_fields); /* in: number of fields */
+ ulint n_fields) /* in: number of fields */
+ __attribute__((const));
/**************************************************************
The following function returns the size of a data tuple when converted to
a physical record. */
@@ -364,6 +511,7 @@ ulint
rec_get_converted_size(
/*===================*/
/* out: size */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* dtuple);/* in: data tuple */
/******************************************************************
Copies the first n fields of a physical record to a data tuple.
@@ -374,6 +522,7 @@ rec_copy_prefix_to_dtuple(
/*======================*/
dtuple_t* tuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
ulint n_fields, /* in: number of fields to copy */
mem_heap_t* heap); /* in: memory heap */
/*******************************************************************
@@ -382,16 +531,35 @@ Validates the consistency of a physical record. */
ibool
rec_validate(
/*=========*/
- /* out: TRUE if ok */
- rec_t* rec); /* in: physical record */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/*******************************************************************
+Prints an old-style physical record. */
+
+void
+rec_print_old(
+/*==========*/
+ FILE* file, /* in: file where to print */
+ rec_t* rec); /* in: physical record */
+/*******************************************************************
+Prints a physical record. */
+
+void
+rec_print_new(
+/*==========*/
+ FILE* file, /* in: file where to print */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Prints a physical record. */
void
rec_print(
/*======*/
- FILE* file, /* in: file where to print */
- rec_t* rec); /* in: physical record */
+ FILE* file, /* in: file where to print */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index); /* in: record descriptor */
#define REC_INFO_BITS 6 /* This is single byte bit-field */
diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic
index c36bf8f6d6e..e2dceb6bae5 100644
--- a/innobase/include/rem0rec.ic
+++ b/innobase/include/rem0rec.ic
@@ -8,9 +8,19 @@ Created 5/30/1994 Heikki Tuuri
#include "mach0data.h"
#include "ut0byte.h"
+#include "dict0dict.h"
-/* Offsets of the bit-fields in the record. NOTE! In the table the most
-significant bytes and bits are written below less significant.
+/* Compact flag ORed to the extra size returned by rec_get_offsets() */
+#define REC_OFFS_COMPACT ((ulint) 1 << 31)
+/* SQL NULL flag in offsets returned by rec_get_offsets() */
+#define REC_OFFS_SQL_NULL ((ulint) 1 << 31)
+/* External flag in offsets returned by rec_get_offsets() */
+#define REC_OFFS_EXTERNAL ((ulint) 1 << 30)
+/* Mask for offsets returned by rec_get_offsets() */
+#define REC_OFFS_MASK (REC_OFFS_EXTERNAL - 1)
+
+/* Offsets of the bit-fields in an old-style record. NOTE! In the table the
+most significant bytes and bits are written below less significant.
(1) byte offset (2) bit usage within byte
downward from
@@ -25,6 +35,35 @@ significant bytes and bits are written below less significant.
4 bits info bits
*/
+/* Offsets of the bit-fields in a new-style record. NOTE! In the table the
+most significant bytes and bits are written below less significant.
+
+ (1) byte offset (2) bit usage within byte
+ downward from
+ origin -> 1 8 bits relative offset of next record
+ 2 8 bits relative offset of next record
+ the relative offset is an unsigned 16-bit
+ integer:
+ (offset_of_next_record
+ - offset_of_this_record) mod 64Ki,
+ where mod is the modulo as a non-negative
+ number;
+ we can calculate the the offset of the next
+ record with the formula:
+ relative_offset + offset_of_this_record
+ mod UNIV_PAGE_SIZE
+ 3 3 bits status:
+ 000=conventional record
+ 001=node pointer record (inside B-tree)
+ 010=infimum record
+ 011=supremum record
+ 1xx=reserved
+ 5 bits heap number
+ 4 8 bits heap number
+ 5 4 bits n_owned
+ 4 bits info bits
+*/
+
/* We list the byte offsets from the origin of the record, the mask,
and the shift needed to obtain each bit-field of the record. */
@@ -32,22 +71,30 @@ and the shift needed to obtain each bit-field of the record. */
#define REC_NEXT_MASK 0xFFFFUL
#define REC_NEXT_SHIFT 0
-#define REC_SHORT 3 /* This is single byte bit-field */
-#define REC_SHORT_MASK 0x1UL
-#define REC_SHORT_SHIFT 0
+#define REC_OLD_SHORT 3 /* This is single byte bit-field */
+#define REC_OLD_SHORT_MASK 0x1UL
+#define REC_OLD_SHORT_SHIFT 0
+
+#define REC_OLD_N_FIELDS 4
+#define REC_OLD_N_FIELDS_MASK 0x7FEUL
+#define REC_OLD_N_FIELDS_SHIFT 1
-#define REC_N_FIELDS 4
-#define REC_N_FIELDS_MASK 0x7FEUL
-#define REC_N_FIELDS_SHIFT 1
+#define REC_NEW_STATUS 3 /* This is single byte bit-field */
+#define REC_NEW_STATUS_MASK 0x7UL
+#define REC_NEW_STATUS_SHIFT 0
-#define REC_HEAP_NO 5
+#define REC_OLD_HEAP_NO 5
+#define REC_NEW_HEAP_NO 4
#define REC_HEAP_NO_MASK 0xFFF8UL
#define REC_HEAP_NO_SHIFT 3
-#define REC_N_OWNED 6 /* This is single byte bit-field */
+#define REC_OLD_N_OWNED 6 /* This is single byte bit-field */
+#define REC_NEW_N_OWNED 5 /* This is single byte bit-field */
#define REC_N_OWNED_MASK 0xFUL
#define REC_N_OWNED_SHIFT 0
+#define REC_OLD_INFO_BITS 6 /* This is single byte bit-field */
+#define REC_NEW_INFO_BITS 5 /* This is single byte bit-field */
#define REC_INFO_BITS_MASK 0xF0UL
#define REC_INFO_BITS_SHIFT 0
@@ -65,26 +112,24 @@ a field stored to another page: */
#define REC_2BYTE_EXTERN_MASK 0x4000UL
-/****************************************************************
-Return field length or UNIV_SQL_NULL. */
-UNIV_INLINE
-ulint
-rec_get_nth_field_len(
-/*==================*/
- /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
- rec_t* rec, /* in: record */
- ulint n) /* in: index of the field */
-{
- ulint len;
-
- rec_get_nth_field(rec, n, &len);
-
- return(len);
-}
+#if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) \
+ ^ REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) \
+ ^ REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) \
+ ^ REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) \
+ ^ REC_INFO_BITS_MASK << (8 * (REC_OLD_INFO_BITS - 3)) \
+ ^ 0xFFFFFFFFUL
+# error "sum of old-style masks != 0xFFFFFFFFUL"
+#endif
+#if REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) \
+ ^ REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) \
+ ^ REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) \
+ ^ REC_INFO_BITS_MASK << (8 * (REC_NEW_INFO_BITS - 3)) \
+ ^ 0xFFFFFFUL
+# error "sum of new-style masks != 0xFFFFFFUL"
+#endif
/***************************************************************
-Sets the value of the ith field SQL null bit. */
+Sets the value of the ith field SQL null bit of an old-style record. */
void
rec_set_nth_field_null_bit(
@@ -93,8 +138,8 @@ rec_set_nth_field_null_bit(
ulint i, /* in: ith field */
ibool val); /* in: value to set */
/***************************************************************
-Sets a record field to SQL null. The physical size of the field is not
-changed. */
+Sets an old-style record field to SQL null.
+The physical size of the field is not changed. */
void
rec_set_nth_field_sql_null(
@@ -102,6 +147,32 @@ rec_set_nth_field_sql_null(
rec_t* rec, /* in: record */
ulint n); /* in: index of the field */
+/***************************************************************
+Sets the value of the ith field extern storage bit of an old-style record. */
+
+void
+rec_set_nth_field_extern_bit_old(
+/*=============================*/
+ rec_t* rec, /* in: old-style record */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page where
+ rec is, or NULL; in the NULL case we do not
+ write to log about the change */
+/***************************************************************
+Sets the value of the ith field extern storage bit of a new-style record. */
+
+void
+rec_set_nth_field_extern_bit_new(
+/*=============================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint ith, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
+
/**********************************************************
Gets a bit field from within 1 byte. */
UNIV_INLINE
@@ -131,7 +202,7 @@ rec_set_bit_field_1(
ulint shift) /* in: shift right applied after masking */
{
ut_ad(rec);
- ut_ad(offs <= REC_N_EXTRA_BYTES);
+ ut_ad(offs <= REC_N_OLD_EXTRA_BYTES);
ut_ad(mask);
ut_ad(mask <= 0xFFUL);
ut_ad(((mask >> shift) << shift) == mask);
@@ -171,30 +242,14 @@ rec_set_bit_field_2(
ulint shift) /* in: shift right applied after masking */
{
ut_ad(rec);
- ut_ad(offs <= REC_N_EXTRA_BYTES);
+ ut_ad(offs <= REC_N_OLD_EXTRA_BYTES);
ut_ad(mask > 0xFFUL);
ut_ad(mask <= 0xFFFFUL);
ut_ad((mask >> shift) & 1);
ut_ad(0 == ((mask >> shift) & ((mask >> shift) + 1)));
ut_ad(((mask >> shift) << shift) == mask);
ut_ad(((val << shift) & mask) == (val << shift));
-#ifdef UNIV_DEBUG
- {
- ulint m;
-
- /* The following assertion checks that the masks of currently
- defined bit-fields in bytes 3-6 do not overlap. */
- m = (ulint)((REC_SHORT_MASK << (8 * (REC_SHORT - 3)))
- + (REC_N_FIELDS_MASK << (8 * (REC_N_FIELDS - 4)))
- + (REC_HEAP_NO_MASK << (8 * (REC_HEAP_NO - 4)))
- + (REC_N_OWNED_MASK << (8 * (REC_N_OWNED - 3)))
- + (REC_INFO_BITS_MASK << (8 * (REC_INFO_BITS - 3))));
- if (m != ut_dbg_zero + 0xFFFFFFFFUL) {
- fprintf(stderr, "Sum of masks %lx\n", m);
- ut_error;
- }
- }
-#endif
+
mach_write_to_2(rec - offs,
(mach_read_from_2(rec - offs) & ~mask)
| (val << shift));
@@ -207,18 +262,46 @@ UNIV_INLINE
ulint
rec_get_next_offs(
/*==============*/
- /* out: the page offset of the next chained record */
- rec_t* rec) /* in: physical record */
+ /* out: the page offset of the next chained record, or
+ 0 if none */
+ rec_t* rec, /* in: physical record */
+ ulint comp) /* in: nonzero=compact page format */
{
- ulint ret;
-
- ut_ad(rec);
-
- ret = rec_get_bit_field_2(rec, REC_NEXT, REC_NEXT_MASK,
- REC_NEXT_SHIFT);
- ut_ad(ret < UNIV_PAGE_SIZE);
+ ulint field_value;
+
+ ut_ad(REC_NEXT_MASK == 0xFFFFUL);
+ ut_ad(REC_NEXT_SHIFT == 0);
+
+ field_value = mach_read_from_2(rec - REC_NEXT);
+
+ if (comp) {
+#if UNIV_PAGE_SIZE <= 32768
+ /* Note that for 64 KiB pages, field_value can 'wrap around'
+ and the debug assertion is not valid */
+
+ /* In the following assertion, field_value is interpreted
+ as signed 16-bit integer in 2's complement arithmetics.
+ If all platforms defined int16_t in the standard headers,
+ the expression could be written simpler as
+ (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE
+ */
+ ut_ad((field_value >= 32768
+ ? field_value - 65536
+ : field_value)
+ + ut_align_offset(rec, UNIV_PAGE_SIZE)
+ < UNIV_PAGE_SIZE);
+#endif
+ if (field_value == 0) {
+
+ return(0);
+ }
+
+ return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE));
+ } else {
+ ut_ad(field_value < UNIV_PAGE_SIZE);
- return(ret);
+ return(field_value);
+ }
}
/**********************************************************
@@ -229,21 +312,42 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
- ulint next) /* in: offset of the next record */
+ ulint comp, /* in: nonzero=compact page format */
+ ulint next) /* in: offset of the next record, or 0 if none */
{
ut_ad(rec);
ut_ad(UNIV_PAGE_SIZE > next);
+ ut_ad(REC_NEXT_MASK == 0xFFFFUL);
+ ut_ad(REC_NEXT_SHIFT == 0);
+
+ if (comp) {
+ ulint field_value;
+
+ if (next) {
+ /* The following two statements calculate
+ next - offset_of_rec mod 64Ki, where mod is the modulo
+ as a non-negative number */
+
+ field_value = (ulint)((lint)next
+ - (lint)ut_align_offset(rec, UNIV_PAGE_SIZE));
+ field_value &= REC_NEXT_MASK;
+ } else {
+ field_value = 0;
+ }
- rec_set_bit_field_2(rec, next, REC_NEXT, REC_NEXT_MASK,
- REC_NEXT_SHIFT);
+ mach_write_to_2(rec - REC_NEXT, field_value);
+ } else {
+ mach_write_to_2(rec - REC_NEXT, next);
+ }
}
/**********************************************************
-The following function is used to get the number of fields in the record. */
+The following function is used to get the number of fields
+in an old-style record. */
UNIV_INLINE
ulint
-rec_get_n_fields(
-/*=============*/
+rec_get_n_fields_old(
+/*=================*/
/* out: number of data fields */
rec_t* rec) /* in: physical record */
{
@@ -251,8 +355,8 @@ rec_get_n_fields(
ut_ad(rec);
- ret = rec_get_bit_field_2(rec, REC_N_FIELDS, REC_N_FIELDS_MASK,
- REC_N_FIELDS_SHIFT);
+ ret = rec_get_bit_field_2(rec, REC_OLD_N_FIELDS,
+ REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT);
ut_ad(ret <= REC_MAX_N_FIELDS);
ut_ad(ret > 0);
@@ -260,12 +364,12 @@ rec_get_n_fields(
}
/**********************************************************
-The following function is used to set the number of fields field in the
-record. */
+The following function is used to set the number of fields
+in an old-style record. */
UNIV_INLINE
void
-rec_set_n_fields(
-/*=============*/
+rec_set_n_fields_old(
+/*=================*/
rec_t* rec, /* in: physical record */
ulint n_fields) /* in: the number of fields */
{
@@ -273,8 +377,58 @@ rec_set_n_fields(
ut_ad(n_fields <= REC_MAX_N_FIELDS);
ut_ad(n_fields > 0);
- rec_set_bit_field_2(rec, n_fields, REC_N_FIELDS, REC_N_FIELDS_MASK,
- REC_N_FIELDS_SHIFT);
+ rec_set_bit_field_2(rec, n_fields, REC_OLD_N_FIELDS,
+ REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT);
+}
+
+/**********************************************************
+The following function retrieves the status bits of a new-style record. */
+UNIV_INLINE
+ulint
+rec_get_status(
+/*===========*/
+ /* out: status bits */
+ rec_t* rec) /* in: physical record */
+{
+ ulint ret;
+
+ ut_ad(rec);
+
+ ret = rec_get_bit_field_1(rec, REC_NEW_STATUS,
+ REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT);
+ ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0);
+
+ return(ret);
+}
+
+/**********************************************************
+The following function is used to get the number of fields
+in a record. */
+UNIV_INLINE
+ulint
+rec_get_n_fields(
+/*=============*/
+ /* out: number of data fields */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index) /* in: record descriptor */
+{
+ ut_ad(rec);
+ ut_ad(index);
+ if (UNIV_UNLIKELY(!index->table->comp)) {
+ return(rec_get_n_fields_old(rec));
+ }
+ switch (rec_get_status(rec)) {
+ case REC_STATUS_ORDINARY:
+ return(dict_index_get_n_fields(index));
+ case REC_STATUS_NODE_PTR:
+ return(dict_index_get_n_unique_in_tree(index) + 1);
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ return(1);
+ default:
+ ut_error;
+ return(ULINT_UNDEFINED);
+ }
}
/**********************************************************
@@ -285,14 +439,16 @@ ulint
rec_get_n_owned(
/*============*/
/* out: number of owned records */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ulint comp) /* in: nonzero=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_1(rec, REC_N_OWNED, REC_N_OWNED_MASK,
- REC_N_OWNED_SHIFT);
+ ret = rec_get_bit_field_1(rec,
+ comp ? REC_NEW_N_OWNED : REC_OLD_N_OWNED,
+ REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
ut_ad(ret <= REC_MAX_N_OWNED);
return(ret);
@@ -305,13 +461,15 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
ulint n_owned) /* in: the number of owned */
{
ut_ad(rec);
ut_ad(n_owned <= REC_MAX_N_OWNED);
- rec_set_bit_field_1(rec, n_owned, REC_N_OWNED, REC_N_OWNED_MASK,
- REC_N_OWNED_SHIFT);
+ rec_set_bit_field_1(rec, n_owned,
+ comp ? REC_NEW_N_OWNED : REC_OLD_N_OWNED,
+ REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
}
/**********************************************************
@@ -321,14 +479,16 @@ ulint
rec_get_info_bits(
/*==============*/
/* out: info bits */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ulint comp) /* in: nonzero=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_1(rec, REC_INFO_BITS, REC_INFO_BITS_MASK,
- REC_INFO_BITS_SHIFT);
+ ret = rec_get_bit_field_1(rec,
+ comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS,
+ REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
ut_ad((ret & ~REC_INFO_BITS_MASK) == 0);
return(ret);
@@ -341,47 +501,99 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
ulint bits) /* in: info bits */
{
ut_ad(rec);
ut_ad((bits & ~REC_INFO_BITS_MASK) == 0);
- rec_set_bit_field_1(rec, bits, REC_INFO_BITS, REC_INFO_BITS_MASK,
- REC_INFO_BITS_SHIFT);
+ rec_set_bit_field_1(rec, bits,
+ comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS,
+ REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
}
/**********************************************************
-Gets the value of the deleted flag in info bits. */
+The following function is used to set the status bits of a new-style record. */
UNIV_INLINE
-ibool
-rec_info_bits_get_deleted_flag(
-/*===========================*/
- /* out: TRUE if deleted flag set */
- ulint info_bits) /* in: info bits from a record */
+void
+rec_set_status(
+/*===========*/
+ rec_t* rec, /* in: physical record */
+ ulint bits) /* in: info bits */
{
- if (info_bits & REC_INFO_DELETED_FLAG) {
+ ut_ad(rec);
+ ut_ad((bits & ~REC_NEW_STATUS_MASK) == 0);
- return(TRUE);
- }
+ rec_set_bit_field_1(rec, bits, REC_NEW_STATUS,
+ REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT);
+}
- return(FALSE);
+/**********************************************************
+The following function is used to retrieve the info and status
+bits of a record. (Only compact records have status bits.) */
+UNIV_INLINE
+ulint
+rec_get_info_and_status_bits(
+/*=========================*/
+ /* out: info bits */
+ rec_t* rec, /* in: physical record */
+ ulint comp) /* in: nonzero=compact page format */
+{
+ ulint bits;
+#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
+& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)
+# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap"
+#endif
+ if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
+ bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec);
+ } else {
+ bits = rec_get_info_bits(rec, FALSE);
+ ut_ad(!(bits & ~(REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)));
+ }
+ return(bits);
+}
+/**********************************************************
+The following function is used to set the info and status
+bits of a record. (Only compact records have status bits.) */
+UNIV_INLINE
+void
+rec_set_info_and_status_bits(
+/*=========================*/
+ rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
+ ulint bits) /* in: info bits */
+{
+#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
+& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)
+# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap"
+#endif
+ if (comp) {
+ rec_set_status(rec, bits & REC_NEW_STATUS_MASK);
+ } else {
+ ut_ad(!(bits & ~(REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)));
+ }
+ rec_set_info_bits(rec, comp, bits & ~REC_NEW_STATUS_MASK);
}
/**********************************************************
The following function tells if record is delete marked. */
UNIV_INLINE
-ibool
+ulint
rec_get_deleted_flag(
/*=================*/
- /* out: TRUE if delete marked */
- rec_t* rec) /* in: physical record */
+ /* out: nonzero if delete marked */
+ rec_t* rec, /* in: physical record */
+ ulint comp) /* in: nonzero=compact page format */
{
- if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec)) {
-
- return(TRUE);
+ if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
+ return(UNIV_UNLIKELY(rec_get_bit_field_1(rec,
+ REC_NEW_INFO_BITS, REC_INFO_DELETED_FLAG,
+ REC_INFO_BITS_SHIFT)));
+ } else {
+ return(UNIV_UNLIKELY(rec_get_bit_field_1(rec,
+ REC_OLD_INFO_BITS, REC_INFO_DELETED_FLAG,
+ REC_INFO_BITS_SHIFT)));
}
-
- return(FALSE);
}
/**********************************************************
@@ -391,23 +603,32 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
- ibool flag) /* in: TRUE if delete marked */
+ ulint comp, /* in: nonzero=compact page format */
+ ulint flag) /* in: nonzero if delete marked */
{
- ulint old_val;
- ulint new_val;
-
- ut_ad(TRUE == 1);
- ut_ad(flag <= TRUE);
+ ulint val;
- old_val = rec_get_info_bits(rec);
+ val = rec_get_info_bits(rec, comp);
if (flag) {
- new_val = REC_INFO_DELETED_FLAG | old_val;
+ val |= REC_INFO_DELETED_FLAG;
} else {
- new_val = ~REC_INFO_DELETED_FLAG & old_val;
+ val &= ~REC_INFO_DELETED_FLAG;
}
- rec_set_info_bits(rec, new_val);
+ rec_set_info_bits(rec, comp, val);
+}
+
+/**********************************************************
+The following function tells if a new-style record is a node pointer. */
+UNIV_INLINE
+ibool
+rec_get_node_ptr_flag(
+/*=================*/
+ /* out: TRUE if node pointer */
+ rec_t* rec) /* in: physical record */
+{
+ return(REC_STATUS_NODE_PTR == rec_get_status(rec));
}
/**********************************************************
@@ -418,14 +639,16 @@ ulint
rec_get_heap_no(
/*=============*/
/* out: heap order number */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ulint comp) /* in: nonzero=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_2(rec, REC_HEAP_NO, REC_HEAP_NO_MASK,
- REC_HEAP_NO_SHIFT);
+ ret = rec_get_bit_field_2(rec,
+ comp ? REC_NEW_HEAP_NO : REC_OLD_HEAP_NO,
+ REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
ut_ad(ret <= REC_MAX_HEAP_NO);
return(ret);
@@ -438,12 +661,14 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
+ ulint comp, /* in: nonzero=compact page format */
ulint heap_no)/* in: the heap number */
{
ut_ad(heap_no <= REC_MAX_HEAP_NO);
- rec_set_bit_field_2(rec, heap_no, REC_HEAP_NO, REC_HEAP_NO_MASK,
- REC_HEAP_NO_SHIFT);
+ rec_set_bit_field_2(rec, heap_no,
+ comp ? REC_NEW_HEAP_NO : REC_OLD_HEAP_NO,
+ REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
}
/**********************************************************
@@ -456,10 +681,12 @@ rec_get_1byte_offs_flag(
/* out: TRUE if 1-byte form */
rec_t* rec) /* in: physical record */
{
- ut_ad(TRUE == 1);
+#if TRUE != 1
+#error "TRUE != 1"
+#endif
- return(rec_get_bit_field_1(rec, REC_SHORT, REC_SHORT_MASK,
- REC_SHORT_SHIFT));
+ return(rec_get_bit_field_1(rec, REC_OLD_SHORT, REC_OLD_SHORT_MASK,
+ REC_OLD_SHORT_SHIFT));
}
/**********************************************************
@@ -471,11 +698,13 @@ rec_set_1byte_offs_flag(
rec_t* rec, /* in: physical record */
ibool flag) /* in: TRUE if 1byte form */
{
- ut_ad(TRUE == 1);
+#if TRUE != 1
+#error "TRUE != 1"
+#endif
ut_ad(flag <= TRUE);
- rec_set_bit_field_1(rec, flag, REC_SHORT, REC_SHORT_MASK,
- REC_SHORT_SHIFT);
+ rec_set_bit_field_1(rec, flag, REC_OLD_SHORT, REC_OLD_SHORT_MASK,
+ REC_OLD_SHORT_SHIFT);
}
/**********************************************************
@@ -492,9 +721,9 @@ rec_1_get_field_end_info(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- return(mach_read_from_1(rec - (REC_N_EXTRA_BYTES + n + 1)));
+ return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1)));
}
/**********************************************************
@@ -511,73 +740,281 @@ rec_2_get_field_end_info(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- return(mach_read_from_2(rec - (REC_N_EXTRA_BYTES + 2 * n + 2)));
+ return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2)));
}
-/***************************************************************
-Gets the value of the ith field extern storage bit. If it is TRUE
-it means that the field is stored on another page. */
+#ifdef UNIV_DEBUG
+/* Length of the rec_get_offsets() header */
+# define REC_OFFS_HEADER_SIZE 4
+#else /* UNIV_DEBUG */
+/* Length of the rec_get_offsets() header */
+# define REC_OFFS_HEADER_SIZE 2
+#endif /* UNIV_DEBUG */
+
+/* Get the base address of offsets. The extra_size is stored at
+this position, and following positions hold the end offsets of
+the fields. */
+#define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE)
+
+/**************************************************************
+The following function returns the number of allocated elements
+for an array of offsets. */
+UNIV_INLINE
+ulint
+rec_offs_get_n_alloc(
+/*=================*/
+ /* out: number of elements */
+ const ulint* offsets)/* in: array for rec_get_offsets() */
+{
+ ulint n_alloc;
+ ut_ad(offsets);
+ n_alloc = offsets[0];
+ ut_ad(n_alloc > 0);
+ return(n_alloc);
+}
+
+/**************************************************************
+The following function sets the number of allocated elements
+for an array of offsets. */
+UNIV_INLINE
+void
+rec_offs_set_n_alloc(
+/*=================*/
+ ulint* offsets, /* in: array for rec_get_offsets() */
+ ulint n_alloc) /* in: number of elements */
+{
+ ut_ad(offsets);
+ ut_ad(n_alloc > 0);
+ offsets[0] = n_alloc;
+}
+
+/**************************************************************
+The following function returns the number of fields in a record. */
+UNIV_INLINE
+ulint
+rec_offs_n_fields(
+/*===============*/
+ /* out: number of fields */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint n_fields;
+ ut_ad(offsets);
+ n_fields = offsets[1];
+ ut_ad(n_fields > 0);
+ ut_ad(n_fields <= REC_MAX_N_FIELDS);
+ ut_ad(n_fields + REC_OFFS_HEADER_SIZE
+ <= rec_offs_get_n_alloc(offsets));
+ return(n_fields);
+}
+
+/****************************************************************
+Validates offsets returned by rec_get_offsets(). */
UNIV_INLINE
ibool
-rec_get_nth_field_extern_bit(
-/*=========================*/
- /* in: TRUE or FALSE */
- rec_t* rec, /* in: record */
- ulint i) /* in: ith field */
+rec_offs_validate(
+/*==============*/
+ /* out: TRUE if valid */
+ rec_t* rec, /* in: record or NULL */
+ dict_index_t* index, /* in: record descriptor or NULL */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint info;
+ ulint i = rec_offs_n_fields(offsets);
+ ulint last = ULINT_MAX;
+ ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT;
+
+ if (rec) {
+ ut_ad((ulint) rec == offsets[2]);
+ if (!comp) {
+ ut_a(rec_get_n_fields_old(rec) >= i);
+ }
+ }
+ if (index) {
+ ulint max_n_fields;
+ ut_ad((ulint) index == offsets[3]);
+ max_n_fields = ut_max(
+ dict_index_get_n_fields(index),
+ dict_index_get_n_unique_in_tree(index) + 1);
+ if (comp && rec) {
+ switch (rec_get_status(rec)) {
+ case REC_STATUS_ORDINARY:
+ break;
+ case REC_STATUS_NODE_PTR:
+ max_n_fields =
+ dict_index_get_n_unique_in_tree(index) + 1;
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ max_n_fields = 1;
+ break;
+ default:
+ ut_error;
+ }
+ }
+ /* index->n_def == 0 for dummy indexes if !comp */
+ ut_a(!comp || index->n_def);
+ ut_a(!index->n_def || i <= max_n_fields);
+ }
+ while (i--) {
+ ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK;
+ ut_a(curr <= last);
+ last = curr;
+ }
+ return(TRUE);
+}
+/****************************************************************
+Updates debug data in offsets, in order to avoid bogus
+rec_offs_validate() failures. */
+UNIV_INLINE
+void
+rec_offs_make_valid(
+/*================*/
+ rec_t* rec __attribute__((unused)),
+ /* in: record */
+ dict_index_t* index __attribute__((unused)),
+ /* in: record descriptor */
+ ulint* offsets __attribute__((unused)))
+ /* in: array returned by rec_get_offsets() */
+{
+#ifdef UNIV_DEBUG
+ ut_ad(rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets));
+ offsets[2] = (ulint) rec;
+ offsets[3] = (ulint) index;
+#endif /* UNIV_DEBUG */
+}
- if (rec_get_1byte_offs_flag(rec)) {
+/****************************************************************
+The following function is used to get a pointer to the nth
+data field in a record. */
+UNIV_INLINE
+byte*
+rec_get_nth_field(
+/*==============*/
+ /* out: pointer to the field */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index of the field */
+ ulint* len) /* out: length of the field; UNIV_SQL_NULL
+ if SQL null */
+{
+ byte* field;
+ ulint length;
+ ut_ad(rec);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ ut_ad(len);
- return(FALSE);
+ if (UNIV_UNLIKELY(n == 0)) {
+ field = rec;
+ } else {
+ field = rec + (rec_offs_base(offsets)[n] & REC_OFFS_MASK);
}
- info = rec_2_get_field_end_info(rec, i);
+ length = rec_offs_base(offsets)[1 + n];
- if (info & REC_2BYTE_EXTERN_MASK) {
- return(TRUE);
+ if (length & REC_OFFS_SQL_NULL) {
+ length = UNIV_SQL_NULL;
+ } else {
+ length &= REC_OFFS_MASK;
+ length -= field - rec;
}
- return(FALSE);
+ *len = length;
+ return(field);
}
/**********************************************************
-Returns TRUE if the extern bit is set in any of the fields
-of rec. */
+Determine if the offsets are for a record in the new
+compact format. */
UNIV_INLINE
-ibool
-rec_contains_externally_stored_field(
-/*=================================*/
- /* out: TRUE if a field is stored externally */
- rec_t* rec) /* in: record */
+ulint
+rec_offs_comp(
+/*==========*/
+ /* out: nonzero if compact format */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n;
- ulint i;
-
- if (rec_get_1byte_offs_flag(rec)) {
-
- return(FALSE);
- }
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ return(*rec_offs_base(offsets) & REC_OFFS_COMPACT);
+}
- n = rec_get_n_fields(rec);
+/**********************************************************
+Returns nonzero if the extern bit is set in nth field of rec. */
+UNIV_INLINE
+ulint
+rec_offs_nth_extern(
+/*================*/
+ /* out: nonzero if externally stored */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: nth field */
+{
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ return(UNIV_UNLIKELY(rec_offs_base(offsets)[1 + n]
+ & REC_OFFS_EXTERNAL));
+}
- for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+/**********************************************************
+Gets the physical size of a field. */
+UNIV_INLINE
+ulint
+rec_offs_nth_size(
+/*==============*/
+ /* out: length of field */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: nth field */
+{
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ return((rec_offs_base(offsets)[1 + n] - rec_offs_base(offsets)[n])
+ & REC_OFFS_MASK);
+}
+/**********************************************************
+Returns TRUE if the extern bit is set in any of the fields
+of an old-style record. */
+UNIV_INLINE
+ibool
+rec_offs_any_extern(
+/*================*/
+ /* out: TRUE if a field is stored externally */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint i;
+ for (i = rec_offs_n_fields(offsets); i--; ) {
+ if (rec_offs_nth_extern(offsets, i)) {
return(TRUE);
}
}
-
return(FALSE);
}
+/***************************************************************
+Sets the value of the ith field extern storage bit. */
+UNIV_INLINE
+void
+rec_set_nth_field_extern_bit(
+/*=========================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
+{
+ if (UNIV_LIKELY(index->table->comp)) {
+ rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr);
+ } else {
+ rec_set_nth_field_extern_bit_old(rec, i, val, mtr);
+ }
+}
+
/**********************************************************
Returns the offset of n - 1th field end if the record is stored in the 1-byte
offsets form. If the field is SQL null, the flag is ORed in the returned
value. This function and the 2-byte counterpart are defined here because the
-C-compilerwas not able to sum negative and positive constant offsets, and
+C-compiler was not able to sum negative and positive constant offsets, and
warned of constant arithmetic overflow within the compiler. */
UNIV_INLINE
ulint
@@ -589,9 +1026,9 @@ rec_1_get_prev_field_end_info(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
- return(mach_read_from_1(rec - (REC_N_EXTRA_BYTES + n)));
+ return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n)));
}
/**********************************************************
@@ -608,9 +1045,9 @@ rec_2_get_prev_field_end_info(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
- return(mach_read_from_2(rec - (REC_N_EXTRA_BYTES + 2 * n)));
+ return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n)));
}
/**********************************************************
@@ -625,9 +1062,9 @@ rec_1_set_field_end_info(
ulint info) /* in: value to set */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- mach_write_to_1(rec - (REC_N_EXTRA_BYTES + n + 1), info);
+ mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1), info);
}
/**********************************************************
@@ -642,9 +1079,9 @@ rec_2_set_field_end_info(
ulint info) /* in: value to set */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- mach_write_to_2(rec - (REC_N_EXTRA_BYTES + 2 * n + 2), info);
+ mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2), info);
}
/**********************************************************
@@ -659,7 +1096,7 @@ rec_1_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -682,7 +1119,7 @@ rec_2_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -707,7 +1144,7 @@ rec_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(rec);
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -723,8 +1160,9 @@ rec_get_field_start_offs(
}
/****************************************************************
-Gets the physical size of a field. Also an SQL null may have a field of
-size > 0, if the data type is of a fixed size. */
+Gets the physical size of an old-style field.
+Also an SQL null may have a field of size > 0,
+if the data type is of a fixed size. */
UNIV_INLINE
ulint
rec_get_nth_field_size(
@@ -744,133 +1182,134 @@ rec_get_nth_field_size(
return(next_os - os);
}
-/****************************************************************
-The following function is used to get a copy of the nth data field in a
-record to a buffer. */
-UNIV_INLINE
-void
-rec_copy_nth_field(
-/*===============*/
- void* buf, /* in: pointer to the buffer */
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- ulint* len) /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
-{
- byte* ptr;
-
- ut_ad(buf && rec && len);
-
- ptr = rec_get_nth_field(rec, n, len);
-
- if (*len == UNIV_SQL_NULL) {
-
- return;
- }
-
- ut_memcpy(buf, ptr, *len);
-}
-
/***************************************************************
This is used to modify the value of an already existing field in a record.
The previous value must have exactly the same size as the new value. If len
-is UNIV_SQL_NULL then the field is treated as an SQL null. */
+is UNIV_SQL_NULL then the field is treated as an SQL null for old-style
+records. For new-style records, len must not be UNIV_SQL_NULL. */
UNIV_INLINE
void
rec_set_nth_field(
/*==============*/
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- void* data, /* in: pointer to the data if not SQL null */
- ulint len) /* in: length of the data or UNIV_SQL_NULL */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index number of the field */
+ const void* data, /* in: pointer to the data
+ if not SQL null */
+ ulint len) /* in: length of the data or UNIV_SQL_NULL.
+ If not SQL null, must have the same
+ length as the previous value.
+ If SQL null, previous value must be
+ SQL null. */
{
byte* data2;
ulint len2;
- ut_ad((len == UNIV_SQL_NULL)
- || (rec_get_nth_field_size(rec, n) == len));
-
+ ut_ad(rec);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
if (len == UNIV_SQL_NULL) {
+ ut_ad(!rec_offs_comp(offsets));
rec_set_nth_field_sql_null(rec, n);
return;
}
- data2 = rec_get_nth_field(rec, n, &len2);
-
- ut_memcpy(data2, data, len);
-
+ data2 = rec_get_nth_field(rec, offsets, n, &len2);
if (len2 == UNIV_SQL_NULL) {
-
+ ut_ad(!rec_offs_comp(offsets));
rec_set_nth_field_null_bit(rec, n, FALSE);
+ ut_ad(len == rec_get_nth_field_size(rec, n));
+ } else {
+ ut_ad(len2 == len);
}
+
+ ut_memcpy(data2, data, len);
}
/**************************************************************
-The following function returns the data size of a physical
+The following function returns the data size of an old-style physical
record, that is the sum of field lengths. SQL null fields
are counted as length 0 fields. The value returned by the function
is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
-rec_get_data_size(
-/*==============*/
- /* out: size */
+rec_get_data_size_old(
+/*==================*/
+ /* out: size */
rec_t* rec) /* in: physical record */
{
ut_ad(rec);
- return(rec_get_field_start_offs(rec, rec_get_n_fields(rec)));
+ return(rec_get_field_start_offs(rec, rec_get_n_fields_old(rec)));
}
/**************************************************************
-Returns the total size of record minus data size of record. The value
-returned by the function is the distance from record start to record origin
-in bytes. */
+The following function sets the number of fields in offsets. */
+UNIV_INLINE
+void
+rec_offs_set_n_fields(
+/*==================*/
+ ulint* offsets, /* in: array returned by rec_get_offsets() */
+ ulint n_fields) /* in: number of fields */
+{
+ ut_ad(offsets);
+ ut_ad(n_fields > 0);
+ ut_ad(n_fields <= REC_MAX_N_FIELDS);
+ ut_ad(n_fields + REC_OFFS_HEADER_SIZE
+ <= rec_offs_get_n_alloc(offsets));
+ offsets[1] = n_fields;
+}
+
+/**************************************************************
+The following function returns the data size of a physical
+record, that is the sum of field lengths. SQL null fields
+are counted as length 0 fields. The value returned by the function
+is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
-rec_get_extra_size(
+rec_offs_data_size(
/*===============*/
- /* out: size */
- rec_t* rec) /* in: physical record */
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n_fields;
-
- ut_ad(rec);
-
- n_fields = rec_get_n_fields(rec);
+ ulint size;
- if (rec_get_1byte_offs_flag(rec)) {
-
- return(REC_N_EXTRA_BYTES + n_fields);
- }
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ size = rec_offs_base(offsets)[rec_offs_n_fields(offsets)]
+ & REC_OFFS_MASK;
+ ut_ad(size < UNIV_PAGE_SIZE);
+ return(size);
+}
- return(REC_N_EXTRA_BYTES + 2 * n_fields);
+/**************************************************************
+Returns the total size of record minus data size of record. The value
+returned by the function is the distance from record start to record origin
+in bytes. */
+UNIV_INLINE
+ulint
+rec_offs_extra_size(
+/*================*/
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint size;
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ size = *rec_offs_base(offsets) & ~REC_OFFS_COMPACT;
+ ut_ad(size < UNIV_PAGE_SIZE);
+ return(size);
}
-/**************************************************************
+/**************************************************************
Returns the total size of a physical record. */
UNIV_INLINE
ulint
-rec_get_size(
-/*=========*/
- /* out: size */
- rec_t* rec) /* in: physical record */
+rec_offs_size(
+/*==========*/
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n_fields;
-
- ut_ad(rec);
-
- n_fields = rec_get_n_fields(rec);
-
- if (rec_get_1byte_offs_flag(rec)) {
-
- return(REC_N_EXTRA_BYTES + n_fields
- + rec_1_get_field_start_offs(rec, n_fields));
- }
-
- return(REC_N_EXTRA_BYTES + 2 * n_fields
- + rec_2_get_field_start_offs(rec, n_fields));
+ return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets));
}
/**************************************************************
@@ -879,10 +1318,11 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
- /* out: pointer to end */
- rec_t* rec) /* in: pointer to record */
+ /* out: pointer to end */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- return(rec + rec_get_data_size(rec));
+ return(rec + rec_offs_data_size(offsets));
}
/**************************************************************
@@ -891,10 +1331,11 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
- /* out: pointer to start */
- rec_t* rec) /* in: pointer to record */
+ /* out: pointer to start */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- return(rec - rec_get_extra_size(rec));
+ return(rec - rec_offs_extra_size(offsets));
}
/*******************************************************************
@@ -903,18 +1344,20 @@ UNIV_INLINE
rec_t*
rec_copy(
/*=====*/
- /* out: pointer to the origin of the copied record */
- void* buf, /* in: buffer */
- rec_t* rec) /* in: physical record */
+ /* out: pointer to the origin of the copy */
+ void* buf, /* in: buffer */
+ const rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint extra_len;
ulint data_len;
ut_ad(rec && buf);
- ut_ad(rec_validate(rec));
+ ut_ad(rec_offs_validate((rec_t*) rec, NULL, offsets));
+ ut_ad(rec_validate((rec_t*) rec, offsets));
- extra_len = rec_get_extra_size(rec);
- data_len = rec_get_data_size(rec);
+ extra_len = rec_offs_extra_size(offsets);
+ data_len = rec_offs_data_size(offsets);
ut_memcpy(buf, rec - extra_len, extra_len + data_len);
@@ -922,8 +1365,8 @@ rec_copy(
}
/**************************************************************
-Returns the extra size of a physical record if we know its data size and
-the number of fields. */
+Returns the extra size of an old-style physical record if we know its
+data size and number of fields. */
UNIV_INLINE
ulint
rec_get_converted_extra_size(
@@ -934,28 +1377,51 @@ rec_get_converted_extra_size(
{
if (data_size <= REC_1BYTE_OFFS_LIMIT) {
- return(REC_N_EXTRA_BYTES + n_fields);
+ return(REC_N_OLD_EXTRA_BYTES + n_fields);
}
- return(REC_N_EXTRA_BYTES + 2 * n_fields);
+ return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields);
}
/**************************************************************
The following function returns the size of a data tuple when converted to
+a new-style physical record. */
+
+ulint
+rec_get_converted_size_new(
+/*=======================*/
+ /* out: size */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple);/* in: data tuple */
+/**************************************************************
+The following function returns the size of a data tuple when converted to
a physical record. */
UNIV_INLINE
ulint
rec_get_converted_size(
/*===================*/
/* out: size */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* dtuple) /* in: data tuple */
{
ulint data_size;
ulint extra_size;
-
+
+ ut_ad(index);
ut_ad(dtuple);
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(index->type & DICT_UNIVERSAL
+ || dtuple_get_n_fields(dtuple) ==
+ (((dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK)
+ == REC_STATUS_NODE_PTR)
+ ? dict_index_get_n_unique_in_tree(index) + 1
+ : dict_index_get_n_fields(index)));
+
+ if (UNIV_LIKELY(index->table->comp)) {
+ return(rec_get_converted_size_new(index, dtuple));
+ }
+
data_size = dtuple_get_data_size(dtuple);
extra_size = rec_get_converted_extra_size(
@@ -971,12 +1437,15 @@ UNIV_INLINE
ulint
rec_fold(
/*=====*/
- /* out: the folded value */
- rec_t* rec, /* in: the physical record */
- ulint n_fields, /* in: number of complete fields to fold */
- ulint n_bytes, /* in: number of bytes to fold in an
- incomplete last field */
- dulint tree_id) /* in: index tree id */
+ /* out: the folded value */
+ rec_t* rec, /* in: the physical record */
+ const ulint* offsets, /* in: array returned by
+ rec_get_offsets() */
+ ulint n_fields, /* in: number of complete
+ fields to fold */
+ ulint n_bytes, /* in: number of bytes to fold
+ in an incomplete last field */
+ dulint tree_id) /* in: index tree id */
{
ulint i;
byte* data;
@@ -984,12 +1453,13 @@ rec_fold(
ulint fold;
ulint n_fields_rec;
- ut_ad(rec_validate(rec));
- ut_ad(n_fields <= rec_get_n_fields(rec));
- ut_ad((n_fields < rec_get_n_fields(rec)) || (n_bytes == 0));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(rec_validate((rec_t*) rec, offsets));
ut_ad(n_fields + n_bytes > 0);
-
- n_fields_rec = rec_get_n_fields(rec);
+
+ n_fields_rec = rec_offs_n_fields(offsets);
+ ut_ad(n_fields <= n_fields_rec);
+ ut_ad(n_fields < n_fields_rec || n_bytes == 0);
if (n_fields > n_fields_rec) {
n_fields = n_fields_rec;
@@ -1002,7 +1472,7 @@ rec_fold(
fold = ut_fold_dulint(tree_id);
for (i = 0; i < n_fields; i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) {
fold = ut_fold_ulint_pair(fold,
@@ -1011,7 +1481,7 @@ rec_fold(
}
if (n_bytes > 0) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) {
if (len > n_bytes) {
@@ -1025,19 +1495,3 @@ rec_fold(
return(fold);
}
-
-/*************************************************************
-Builds a physical record out of a data tuple and stores it beginning from
-the address destination. */
-UNIV_INLINE
-rec_t*
-rec_convert_dtuple_to_rec(
-/*======================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple) /* in: data tuple */
-{
- return(rec_convert_dtuple_to_rec_low(destination, dtuple,
- dtuple_get_data_size(dtuple)));
-}
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 13773ed380d..a61705b90be 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -22,36 +22,6 @@ Created 9/17/2000 Heikki Tuuri
typedef struct row_prebuilt_struct row_prebuilt_t;
/***********************************************************************
-Stores a variable-length field (like VARCHAR) length to dest, in the
-MySQL format. */
-UNIV_INLINE
-byte*
-row_mysql_store_var_len(
-/*====================*/
- /* out: dest + 2 */
- byte* dest, /* in: where to store */
- ulint len); /* in: length, must fit in two bytes */
-/***********************************************************************
-Reads a MySQL format variable-length field (like VARCHAR) length and
-returns pointer to the field data. */
-UNIV_INLINE
-byte*
-row_mysql_read_var_ref(
-/*===================*/
- /* out: field + 2 */
- ulint* len, /* out: variable-length field length */
- byte* field); /* in: field */
-/***********************************************************************
-Reads a MySQL format variable-length field (like VARCHAR) length and
-returns pointer to the field data. */
-
-byte*
-row_mysql_read_var_ref_noninline(
-/*=============================*/
- /* out: field + 2 */
- ulint* len, /* out: variable-length field length */
- byte* field); /* in: field */
-/***********************************************************************
Frees the blob heap in prebuilt when no longer needed. */
void
@@ -60,6 +30,30 @@ row_mysql_prebuilt_free_blob_heap(
row_prebuilt_t* prebuilt); /* in: prebuilt struct of a
ha_innobase:: table handle */
/***********************************************************************
+Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
+format. */
+
+byte*
+row_mysql_store_true_var_len(
+/*=========================*/
+ /* out: pointer to the data, we skip the 1 or 2 bytes
+ at the start that are used to store the len */
+ byte* dest, /* in: where to store */
+ ulint len, /* in: length, must fit in two bytes */
+ ulint lenlen);/* in: storage length of len: either 1 or 2 bytes */
+/***********************************************************************
+Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
+returns a pointer to the data. */
+
+byte*
+row_mysql_read_true_varchar(
+/*========================*/
+ /* out: pointer to the data, we skip the 1 or 2 bytes
+ at the start that are used to store the len */
+ ulint* len, /* out: variable-length field length */
+ byte* field, /* in: field in the MySQL format */
+ ulint lenlen);/* in: storage length of len: either 1 or 2 bytes */
+/***********************************************************************
Stores a reference to a BLOB in the MySQL format. */
void
@@ -83,23 +77,40 @@ row_mysql_read_blob_ref(
ulint col_len); /* in: BLOB reference length (not BLOB
length) */
/******************************************************************
-Stores a non-SQL-NULL field given in the MySQL format in the Innobase
-format. */
-UNIV_INLINE
-void
+Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
+The counterpart of this function is row_sel_field_store_in_mysql_format() in
+row0sel.c. */
+
+byte*
row_mysql_store_col_in_innobase_format(
/*===================================*/
- dfield_t* dfield, /* in/out: dfield */
- byte* buf, /* in/out: buffer for the converted
- value */
+ /* out: up to which byte we used
+ buf in the conversion */
+ dfield_t* dfield, /* in/out: dfield where dtype
+ information must be already set when
+ this function is called! */
+ byte* buf, /* in/out: buffer for a converted
+ integer value; this must be at least
+ col_len long then! */
+ ibool row_format_col, /* TRUE if the mysql_data is from
+ a MySQL row, FALSE if from a MySQL
+ key value;
+ in MySQL, a true VARCHAR storage
+ format differs in a row and in a
+ key value: in a key value the length
+ is always stored in 2 bytes! */
byte* mysql_data, /* in: MySQL column value, not
SQL NULL; NOTE that dfield may also
get a pointer to mysql_data,
therefore do not discard this as long
as dfield is used! */
- ulint col_len, /* in: MySQL column length */
- ulint type, /* in: data type */
- ulint is_unsigned); /* in: != 0 if unsigned integer type */
+ ulint col_len, /* in: MySQL column length; NOTE that
+ this is the storage length of the
+ column in the MySQL format row, not
+ necessarily the length of the actual
+ payload data; if the column is a true
+ VARCHAR then this is irrelevant */
+ ulint comp); /* in: nonzero=compact format */
/********************************************************************
Handles user errors and lock waits detected by the database engine. */
@@ -161,14 +172,6 @@ row_lock_table_autoinc_for_mysql(
row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL
table handle */
/*************************************************************************
-Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
-lock type LOCK_TABLE_EXP). */
-
-void
-row_unlock_tables_for_mysql(
-/*========================*/
- trx_t* trx); /* in: transaction */
-/*************************************************************************
Sets a table lock on the table mentioned in prebuilt. */
int
@@ -179,9 +182,10 @@ row_lock_table_for_mysql(
table handle */
dict_table_t* table, /* in: table to lock, or NULL
if prebuilt->table should be
- locked as LOCK_TABLE_EXP |
+ locked as
prebuilt->select_lock_type */
- ulint mode); /* in: lock mode of table */
+ ulint mode); /* in: lock mode of table
+ (ignored if table==NULL) */
/*************************************************************************
Does an insert for MySQL. */
@@ -240,6 +244,27 @@ row_update_for_mysql(
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
handle */
/*************************************************************************
+This can only be used when srv_locks_unsafe_for_binlog is TRUE. Before
+calling this function we must use trx_reset_new_rec_lock_info() and
+trx_register_new_rec_lock() to store the information which new record locks
+really were set. This function removes a newly set lock under prebuilt->pcur,
+and also under prebuilt->clust_pcur. Currently, this is only used and tested
+in the case of an UPDATE or a DELETE statement, where the row lock is of the
+LOCK_X type.
+Thus, this implements a 'mini-rollback' that releases the latest record
+locks we set. */
+
+int
+row_unlock_for_mysql(
+/*=================*/
+ /* out: error code or DB_SUCCESS */
+ row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL
+ handle */
+ ibool has_latches_on_recs);/* TRUE if called so that we have
+ the latches on the records under pcur
+ and clust_pcur, and we do not need to
+ reposition the cursors. */
+/*************************************************************************
Creates an query graph node of 'update' type to be used in the MySQL
interface. */
@@ -330,9 +355,13 @@ row_table_add_foreign_constraints(
FOREIGN KEY (a, b) REFERENCES table2(c, d),
table2 can be written also with the
database name before it: test.table2 */
- const char* name); /* in: table full name in the
+ const char* name, /* in: table full name in the
normalized form
database_name/table_name */
+ ibool reject_fks); /* in: if TRUE, fail with error
+ code DB_CANNOT_ADD_CONSTRAINT if
+ any foreign keys are found. */
+
/*************************************************************************
The master thread in srv0srv.c calls this regularly to drop tables which
we must drop in background after queries to them have ended. Such lazy
@@ -352,6 +381,15 @@ row_get_background_drop_list_len_low(void);
/*======================================*/
/* out: how many tables in list */
/*************************************************************************
+Truncates a table for MySQL. */
+
+int
+row_truncate_table_for_mysql(
+/*=========================*/
+ /* out: error code or DB_SUCCESS */
+ dict_table_t* table, /* in: table handle */
+ trx_t* trx); /* in: transaction handle */
+/*************************************************************************
Drops a table for MySQL. If the name of the dropped table ends to
characters INNODB_MONITOR, then this also stops printing of monitor
output by the master thread. */
@@ -436,8 +474,22 @@ struct mysql_row_templ_struct {
zero if column cannot be NULL */
ulint type; /* column type in Innobase mtype
numbers DATA_CHAR... */
+ ulint mysql_type; /* MySQL type code; this is always
+ < 256 */
+ ulint mysql_length_bytes; /* if mysql_type
+ == DATA_MYSQL_TRUE_VARCHAR, this tells
+ whether we should use 1 or 2 bytes to
+ store the MySQL true VARCHAR data
+ length at the start of row in the MySQL
+ format (NOTE that the MySQL key value
+ format always uses 2 bytes for the data
+ len) */
ulint charset; /* MySQL charset-collation code
of the column, or zero */
+ ulint mbminlen; /* minimum length of a char, in bytes,
+ or zero if not a char type */
+ ulint mbmaxlen; /* maximum length of a char, in bytes,
+ or zero if not a char type */
ulint is_unsigned; /* if a column type is an integer
type and this field is != 0, then
it is an unsigned integer type */
@@ -554,6 +606,8 @@ struct row_prebuilt_struct {
that was decided in ha_innodb.cc,
::store_lock(), ::external_lock(),
etc. */
+ ulint mysql_prefix_len;/* byte offset of the end of
+ the last requested column */
ulint mysql_row_len; /* length in bytes of a row in the
MySQL format */
ulint n_rows_fetched; /* number of rows fetched after
@@ -569,6 +623,10 @@ struct row_prebuilt_struct {
allocated mem buf start, because
there is a 4 byte magic number at the
start and at the end */
+ ibool keep_other_fields_on_keyread; /* when using fetch
+ cache with HA_EXTRA_KEYREAD, don't
+ overwrite other fields in mysql row
+ row buffer.*/
ulint fetch_cache_first;/* position of the first not yet
fetched row in fetch_cache */
ulint n_fetch_cached; /* number of not yet fetched rows
diff --git a/innobase/include/row0mysql.ic b/innobase/include/row0mysql.ic
index fc922b52d0a..aa8a70d8761 100644
--- a/innobase/include/row0mysql.ic
+++ b/innobase/include/row0mysql.ic
@@ -5,122 +5,3 @@ MySQL interface for Innobase
Created 1/23/2001 Heikki Tuuri
*******************************************************/
-
-/***********************************************************************
-Stores a variable-length field (like VARCHAR) length to dest, in the
-MySQL format. No real var implemented in MySQL yet! */
-UNIV_INLINE
-byte*
-row_mysql_store_var_len(
-/*====================*/
- /* out: dest + 2 */
- byte* dest, /* in: where to store */
- ulint len __attribute__((unused))) /* in: length, must fit in two
- bytes */
-{
- ut_ad(len < 256 * 256);
-/*
- mach_write_to_2_little_endian(dest, len);
-
- return(dest + 2);
-*/
- return(dest); /* No real var implemented in MySQL yet! */
-}
-
-/***********************************************************************
-Reads a MySQL format variable-length field (like VARCHAR) length and
-returns pointer to the field data. No real var implemented in MySQL yet! */
-UNIV_INLINE
-byte*
-row_mysql_read_var_ref(
-/*===================*/
- /* out: field + 2 */
- ulint* len, /* out: variable-length field length; does not work
- yet! */
- byte* field) /* in: field */
-{
-/*
- *len = mach_read_from_2_little_endian(field);
-
- return(field + 2);
-*/
- UT_NOT_USED(len);
-
- return(field); /* No real var implemented in MySQL yet! */
-}
-
-/******************************************************************
-Stores a non-SQL-NULL field given in the MySQL format in the Innobase
-format. */
-UNIV_INLINE
-void
-row_mysql_store_col_in_innobase_format(
-/*===================================*/
- dfield_t* dfield, /* in/out: dfield */
- byte* buf, /* in/out: buffer for the converted
- value; this must be at least col_len
- long! */
- byte* mysql_data, /* in: MySQL column value, not
- SQL NULL; NOTE that dfield may also
- get a pointer to mysql_data,
- therefore do not discard this as long
- as dfield is used! */
- ulint col_len, /* in: MySQL column length */
- ulint type, /* in: data type */
- ulint is_unsigned) /* in: != 0 if unsigned integer type */
-{
- byte* ptr = mysql_data;
-
- if (type == DATA_INT) {
- /* Store integer data in Innobase in a big-endian format,
- sign bit negated */
-
- ptr = buf + col_len;
-
- for (;;) {
- ptr--;
- *ptr = *mysql_data;
- if (ptr == buf) {
- break;
- }
- mysql_data++;
- }
-
- if (!is_unsigned) {
- *ptr = (byte) (*ptr ^ 128);
- }
- } else if (type == DATA_VARCHAR || type == DATA_VARMYSQL
- || type == DATA_BINARY) {
- /* Remove trailing spaces. */
-
- /* Handle UCS2 strings differently. As no new
- collations will be introduced in 4.1, we hardcode the
- charset-collation codes here. In 5.0, the logic will
- be based on mbminlen. */
- ulint cset = dtype_get_charset_coll(
- dtype_get_prtype(dfield_get_type(dfield)));
- ptr = row_mysql_read_var_ref(&col_len, mysql_data);
- if (cset == 35/*ucs2_general_ci*/
- || cset == 90/*ucs2_bin*/
- || (cset >= 128/*ucs2_unicode_ci*/
- && cset <= 144/*ucs2_persian_ci*/)) {
- /* space=0x0020 */
- /* Trim "half-chars", just in case. */
- col_len &= ~1;
-
- while (col_len >= 2 && ptr[col_len - 2] == 0x00
- && ptr[col_len - 1] == 0x20) {
- col_len -= 2;
- }
- } else {
- /* space=0x20 */
- while (col_len > 0 && ptr[col_len - 1] == 0x20) {
- col_len--;
- }
- }
- } else if (type == DATA_BLOB) {
- ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len);
- }
-
- dfield_set_data(dfield, ptr, col_len);
-}
diff --git a/innobase/include/row0row.h b/innobase/include/row0row.h
index 951e211fb37..782973d8f5d 100644
--- a/innobase/include/row0row.h
+++ b/innobase/include/row0row.h
@@ -27,7 +27,8 @@ row_get_rec_trx_id(
/*===============*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Reads the roll pointer field from a clustered index record. */
UNIV_INLINE
@@ -36,7 +37,8 @@ row_get_rec_roll_ptr(
/*=================*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Writes the trx id field to a clustered index record. */
UNIV_INLINE
@@ -45,7 +47,8 @@ row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
- dulint trx_id); /* in: value of the field */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
+ dulint trx_id);/* in: value of the field */
/*************************************************************************
Sets the roll pointer field in a clustered index record. */
UNIV_INLINE
@@ -54,6 +57,7 @@ row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr);/* in: value of the field */
/*********************************************************************
When an insert to a table is performed, this function builds the entry which
@@ -90,6 +94,9 @@ row_build(
the buffer page of this record must be
at least s-latched and the latch held
as long as the row dtuple is used! */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index)
+ or NULL, in which case this function
+ will invoke rec_get_offsets() */
mem_heap_t* heap); /* in: memory heap from which the memory
needed is allocated */
/***********************************************************************
@@ -175,14 +182,15 @@ UNIV_INLINE
void
row_build_row_ref_fast(
/*===================*/
- dtuple_t* ref, /* in: typed data tuple where the reference
- is built */
- ulint* map, /* in: array of field numbers in rec telling
- how ref should be built from the fields of
- rec */
- rec_t* rec); /* in: record in the index; must be preserved
- while ref is used, as we do not copy field
- values to heap */
+ dtuple_t* ref, /* in: typed data tuple where the
+ reference is built */
+ const ulint* map, /* in: array of field numbers in rec
+ telling how ref should be built from
+ the fields of rec */
+ rec_t* rec, /* in: record in the index; must be
+ preserved while ref is used, as we do
+ not copy field values to heap */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Searches the clustered index record for a row, if we have the row
reference. */
diff --git a/innobase/include/row0row.ic b/innobase/include/row0row.ic
index 8e5121f5a96..85410beacf0 100644
--- a/innobase/include/row0row.ic
+++ b/innobase/include/row0row.ic
@@ -20,7 +20,8 @@ row_get_rec_sys_field(
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Sets the trx id or roll ptr field in a clustered index record: this function
is slower than the specialized inline functions. */
@@ -32,6 +33,7 @@ row_set_rec_sys_field(
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val); /* in: value to set */
/*************************************************************************
@@ -42,18 +44,21 @@ row_get_rec_trx_id(
/*===============*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
return(trx_read_trx_id(rec + offset));
} else {
- return(row_get_rec_sys_field(DATA_TRX_ID, rec, index));
+ return(row_get_rec_sys_field(DATA_TRX_ID,
+ rec, index, offsets));
}
}
@@ -65,18 +70,21 @@ row_get_rec_roll_ptr(
/*=================*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
} else {
- return(row_get_rec_sys_field(DATA_ROLL_PTR, rec, index));
+ return(row_get_rec_sys_field(DATA_ROLL_PTR,
+ rec, index, offsets));
}
}
@@ -88,18 +96,21 @@ row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint trx_id) /* in: value of the field */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
trx_write_trx_id(rec + offset, trx_id);
} else {
- row_set_rec_sys_field(DATA_TRX_ID, rec, index, trx_id);
+ row_set_rec_sys_field(DATA_TRX_ID,
+ rec, index, offsets, trx_id);
}
}
@@ -111,18 +122,21 @@ row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr)/* in: value of the field */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr);
} else {
- row_set_rec_sys_field(DATA_ROLL_PTR, rec, index, roll_ptr);
+ row_set_rec_sys_field(DATA_ROLL_PTR,
+ rec, index, offsets, roll_ptr);
}
}
@@ -133,14 +147,15 @@ UNIV_INLINE
void
row_build_row_ref_fast(
/*===================*/
- dtuple_t* ref, /* in: typed data tuple where the reference
- is built */
- ulint* map, /* in: array of field numbers in rec telling
- how ref should be built from the fields of
- rec */
- rec_t* rec) /* in: record in the index; must be preserved
- while ref is used, as we do not copy field
- values to heap */
+ dtuple_t* ref, /* in: typed data tuple where the
+ reference is built */
+ const ulint* map, /* in: array of field numbers in rec
+ telling how ref should be built from
+ the fields of rec */
+ rec_t* rec, /* in: record in the index; must be
+ preserved while ref is used, as we do
+ not copy field values to heap */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
dfield_t* dfield;
byte* field;
@@ -149,6 +164,7 @@ row_build_row_ref_fast(
ulint field_no;
ulint i;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ref_len = dtuple_get_n_fields(ref);
for (i = 0; i < ref_len; i++) {
@@ -158,7 +174,8 @@ row_build_row_ref_fast(
if (field_no != ULINT_UNDEFINED) {
- field = rec_get_nth_field(rec, field_no, &len);
+ field = rec_get_nth_field(rec, offsets,
+ field_no, &len);
dfield_set_data(dfield, field, len);
}
}
diff --git a/innobase/include/row0sel.ic b/innobase/include/row0sel.ic
index 595cea1138b..600c6204571 100644
--- a/innobase/include/row0sel.ic
+++ b/innobase/include/row0sel.ic
@@ -75,7 +75,7 @@ open_step(
}
}
- if (err != DB_SUCCESS) {
+ if (UNIV_EXPECT(err, DB_SUCCESS) != DB_SUCCESS) {
/* SQL error detected */
fprintf(stderr, "SQL error %lu\n", (ulong) err);
diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h
index 28210364833..673e0511153 100644
--- a/innobase/include/row0upd.h
+++ b/innobase/include/row0upd.h
@@ -80,6 +80,7 @@ row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
dulint roll_ptr);/* in: roll ptr of the undo log record */
/*************************************************************************
@@ -124,8 +125,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
- rec_t* rec, /* in: record in index */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update);/* in: update vector */
/***************************************************************
Replaces the new column values stored in the update vector to the record
@@ -135,8 +136,9 @@ a clustered index */
void
row_upd_rec_in_place(
/*=================*/
- rec_t* rec, /* in/out: record where replaced */
- upd_t* update);/* in: update vector */
+ rec_t* rec, /* in/out: record where replaced */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update);/* in: update vector */
/*******************************************************************
Builds an update vector from those fields which in a secondary index entry
differ from a record that has the equal ordering fields. NOTE: we compare
@@ -274,10 +276,11 @@ recovery. */
void
row_upd_rec_sys_fields_in_recovery(
/*===============================*/
- rec_t* rec, /* in: record */
- ulint pos, /* in: TRX_ID position in rec */
- dulint trx_id, /* in: transaction id */
- dulint roll_ptr);/* in: roll ptr of the undo log record */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint pos, /* in: TRX_ID position in rec */
+ dulint trx_id, /* in: transaction id */
+ dulint roll_ptr);/* in: roll ptr of the undo log record */
/*************************************************************************
Parses the log data written by row_upd_index_write_log. */
diff --git a/innobase/include/row0upd.ic b/innobase/include/row0upd.ic
index a124228a0de..acbb11aa1c7 100644
--- a/innobase/include/row0upd.ic
+++ b/innobase/include/row0upd.ic
@@ -83,7 +83,7 @@ upd_field_set_field_no(
{
upd_field->field_no = field_no;
- if (field_no >= dict_index_get_n_fields(index)) {
+ if (UNIV_UNLIKELY(field_no >= dict_index_get_n_fields(index))) {
fprintf(stderr,
"InnoDB: Error: trying to access field %lu in ",
(ulong) field_no);
@@ -106,15 +106,17 @@ row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
dulint roll_ptr)/* in: roll ptr of the undo log record */
{
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
#ifdef UNIV_SYNC_DEBUG
ut_ad(!buf_block_align(rec)->is_hashed
|| rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- row_set_rec_trx_id(rec, index, trx->id);
- row_set_rec_roll_ptr(rec, index, roll_ptr);
+ row_set_rec_trx_id(rec, index, offsets, trx->id);
+ row_set_rec_roll_ptr(rec, index, offsets, roll_ptr);
}
diff --git a/innobase/include/row0vers.h b/innobase/include/row0vers.h
index 30cf82144e9..079d841f7f3 100644
--- a/innobase/include/row0vers.h
+++ b/innobase/include/row0vers.h
@@ -30,7 +30,8 @@ row_vers_impl_x_locked_off_kernel(
transaction; NOTE that the kernel mutex is
temporarily released! */
rec_t* rec, /* in: record in a secondary index */
- dict_index_t* index); /* in: the secondary index */
+ dict_index_t* index, /* in: the secondary index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*********************************************************************
Finds out if we must preserve a delete marked earlier version of a clustered
index record, because it is >= the purge view. */
@@ -78,7 +79,11 @@ row_vers_build_for_consistent_read(
mtr_t* mtr, /* in: mtr holding the latch on rec; it will
also hold the latch on purge_view */
dict_index_t* index, /* in: the clustered index */
+ ulint** offsets,/* in/out: offsets returned by
+ rec_get_offsets(rec, index) */
read_view_t* view, /* in: the consistent read view */
+ mem_heap_t** offset_heap,/* in/out: memory heap from which
+ the offsets are allocated */
mem_heap_t* in_heap,/* in: memory heap from which the memory for
old_vers is allocated; memory for possible
intermediate versions is allocated and freed
diff --git a/innobase/include/row0vers.ic b/innobase/include/row0vers.ic
index 5ece47c35d1..ab1e264635b 100644
--- a/innobase/include/row0vers.ic
+++ b/innobase/include/row0vers.ic
@@ -11,73 +11,3 @@ Created 2/6/1997 Heikki Tuuri
#include "read0read.h"
#include "page0page.h"
#include "log0recv.h"
-
-/*************************************************************************
-Fetches the trx id of a clustered index record or version. */
-UNIV_INLINE
-dulint
-row_vers_get_trx_id(
-/*================*/
- /* out: trx id or ut_dulint_zero if the
- clustered index record not found */
- rec_t* rec, /* in: clustered index record, or an old
- version of it */
- dict_table_t* table) /* in: table */
-{
- return(row_get_rec_trx_id(rec, dict_table_get_first_index(table)));
-}
-
-/*************************************************************************
-Checks if a consistent read can be performed immediately on the index
-record, or if an older version is needed. */
-UNIV_INLINE
-ibool
-row_vers_clust_rec_sees_older(
-/*==========================*/
- /* out: FALSE if can read immediately */
- rec_t* rec, /* in: record which should be read or passed
- over by a read cursor */
- dict_index_t* index, /* in: clustered index */
- read_view_t* view) /* in: read view */
-{
- ut_ad(index->type & DICT_CLUSTERED);
-
- if (read_view_sees_trx_id(view, row_get_rec_trx_id(rec, index))) {
-
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-/*************************************************************************
-Checks if a secondary index record can be read immediately by a consistent
-read, or if an older version may be needed. To be sure, we will have to
-look in the clustered index. */
-UNIV_INLINE
-ibool
-row_vers_sec_rec_may_see_older(
-/*===========================*/
- /* out: FALSE if can be read immediately */
- rec_t* rec, /* in: record which should be read or passed */
- dict_index_t* index __attribute__((unused)),/* in: secondary index */
- read_view_t* view) /* in: read view */
-{
- page_t* page;
-
- ut_ad(!(index->type & DICT_CLUSTERED));
-
- page = buf_frame_align(rec);
-
- if ((ut_dulint_cmp(page_get_max_trx_id(page), view->up_limit_id) >= 0)
- || recv_recovery_is_on()) {
-
- /* It may be that the record was inserted or modified by a
- transaction the view should not see: we have to look in the
- clustered index */
-
- return(TRUE);
- }
-
- return(FALSE);
-}
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 4352083b21f..11347f430d4 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -93,20 +93,24 @@ extern ulint srv_max_n_open_files;
extern ulint srv_max_dirty_pages_pct;
extern ulint srv_force_recovery;
-extern ulint srv_thread_concurrency;
+extern ulong srv_thread_concurrency;
+extern ulong srv_commit_concurrency;
extern ulint srv_max_n_threads;
extern lint srv_conc_n_threads;
-extern ibool srv_fast_shutdown;
-extern ibool srv_very_fast_shutdown; /* if this TRUE, do not flush the
+extern ulint srv_fast_shutdown; /* If this is 1, do not do a
+ purge and index buffer merge.
+ If this 2, do not even flush the
buffer pool to data files at the
- shutdown; we effectively 'crash'
- InnoDB */
+ shutdown: we effectively 'crash'
+ InnoDB (but lose no committed
+ transactions). */
extern ibool srv_innodb_status;
extern ibool srv_use_doublewrite_buf;
+extern ibool srv_use_checksums;
extern ibool srv_set_thread_priorities;
extern int srv_query_thread_priority;
@@ -131,7 +135,9 @@ extern ibool srv_print_innodb_table_monitor;
extern ibool srv_lock_timeout_and_monitor_active;
extern ibool srv_error_monitor_active;
-extern ulint srv_n_spin_wait_rounds;
+extern ulong srv_n_spin_wait_rounds;
+extern ulong srv_n_free_tickets_to_enter;
+extern ulong srv_thread_sleep_delay;
extern ulint srv_spin_wait_delay;
extern ibool srv_priority_boost;
@@ -177,12 +183,70 @@ extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
#define kernel_mutex (*kernel_mutex_temp)
#define SRV_MAX_N_IO_THREADS 100
+#define SRV_CONCURRENCY_THRESHOLD 20
/* Array of English strings describing the current state of an
i/o handler thread */
extern const char* srv_io_thread_op_info[];
extern const char* srv_io_thread_function[];
+/* the number of the log write requests done */
+extern ulint srv_log_write_requests;
+
+/* the number of physical writes to the log performed */
+extern ulint srv_log_writes;
+
+/* amount of data written to the log files in bytes */
+extern ulint srv_os_log_written;
+
+/* amount of writes being done to the log files */
+extern ulint srv_os_log_pending_writes;
+
+/* we increase this counter, when there we don't have enough space in the
+log buffer and have to flush it */
+extern ulint srv_log_waits;
+
+/* variable that counts amount of data read in total (in bytes) */
+extern ulint srv_data_read;
+
+/* here we count the amount of data written in total (in bytes) */
+extern ulint srv_data_written;
+
+/* this variable counts the amount of times, when the doublewrite buffer
+was flushed */
+extern ulint srv_dblwr_writes;
+
+/* here we store the number of pages that have been flushed to the
+doublewrite buffer */
+extern ulint srv_dblwr_pages_written;
+
+/* in this variable we store the number of write requests issued */
+extern ulint srv_buf_pool_write_requests;
+
+/* here we store the number of times when we had to wait for a free page
+in the buffer pool. It happens when the buffer pool is full and we need
+to make a flush, in order to be able to read or create a page. */
+extern ulint srv_buf_pool_wait_free;
+
+/* variable to count the number of pages that were written from the
+buffer pool to disk */
+extern ulint srv_buf_pool_flushed;
+
+/* variable to count the number of buffer pool reads that led to the
+reading of a disk page */
+extern ulint srv_buf_pool_reads;
+
+/* variable to count the number of sequential read-aheads were done */
+extern ulint srv_read_ahead_seq;
+
+/* variable to count the number of random read-aheads were done */
+extern ulint srv_read_ahead_rnd;
+
+/* In this structure we store status variables to be passed to MySQL */
+typedef struct export_var_struct export_struc;
+
+extern export_struc export_vars;
+
typedef struct srv_sys_struct srv_sys_t;
/* The server system */
@@ -233,6 +297,12 @@ srv_boot(void);
/*==========*/
/* out: DB_SUCCESS or error code */
/*************************************************************************
+Initializes the server. */
+
+void
+srv_init(void);
+/*==========*/
+/*************************************************************************
Frees the OS fast mutex created in srv_boot(). */
void
@@ -404,6 +474,12 @@ srv_printf_innodb_monitor(
ulint* trx_end); /* out: file position of the end of
the list of active transactions */
+/**********************************************************************
+Function to pass InnoDB status variables to MySQL */
+
+void
+srv_export_innodb_status(void);
+/*=====================*/
/* Types for the threads existing in the system. Threads of types 4 - 9
are called utility threads. Note that utility threads are mainly disk
@@ -429,6 +505,53 @@ typedef struct srv_slot_struct srv_slot_t;
/* Thread table is an array of slots */
typedef srv_slot_t srv_table_t;
+/* In this structure we store status variables to be passed to MySQL */
+struct export_var_struct{
+ ulint innodb_data_pending_reads;
+ ulint innodb_data_pending_writes;
+ ulint innodb_data_pending_fsyncs;
+ ulint innodb_data_fsyncs;
+ ulint innodb_data_read;
+ ulint innodb_data_writes;
+ ulint innodb_data_written;
+ ulint innodb_data_reads;
+ ulint innodb_buffer_pool_pages_total;
+ ulint innodb_buffer_pool_pages_data;
+ ulint innodb_buffer_pool_pages_dirty;
+ ulint innodb_buffer_pool_pages_misc;
+ ulint innodb_buffer_pool_pages_free;
+ ulint innodb_buffer_pool_pages_latched;
+ ulint innodb_buffer_pool_read_requests;
+ ulint innodb_buffer_pool_reads;
+ ulint innodb_buffer_pool_wait_free;
+ ulint innodb_buffer_pool_pages_flushed;
+ ulint innodb_buffer_pool_write_requests;
+ ulint innodb_buffer_pool_read_ahead_seq;
+ ulint innodb_buffer_pool_read_ahead_rnd;
+ ulint innodb_dblwr_pages_written;
+ ulint innodb_dblwr_writes;
+ ulint innodb_log_waits;
+ ulint innodb_log_write_requests;
+ ulint innodb_log_writes;
+ ulint innodb_os_log_written;
+ ulint innodb_os_log_fsyncs;
+ ulint innodb_os_log_pending_writes;
+ ulint innodb_os_log_pending_fsyncs;
+ ulint innodb_page_size;
+ ulint innodb_pages_created;
+ ulint innodb_pages_read;
+ ulint innodb_pages_written;
+ ulint innodb_row_lock_waits;
+ ulint innodb_row_lock_current_waits;
+ ib_longlong innodb_row_lock_time;
+ ulint innodb_row_lock_time_avg;
+ ulint innodb_row_lock_time_max;
+ ulint innodb_rows_read;
+ ulint innodb_rows_inserted;
+ ulint innodb_rows_updated;
+ ulint innodb_rows_deleted;
+};
+
/* The server system struct */
struct srv_sys_struct{
os_event_t operational; /* created threads must wait for the
@@ -437,6 +560,10 @@ struct srv_sys_struct{
srv_table_t* threads; /* server thread table */
UT_LIST_BASE_NODE_T(que_thr_t)
tasks; /* task queue */
+ dict_index_t* dummy_ind1; /* dummy index for old-style
+ supremum and infimum records */
+ dict_index_t* dummy_ind2; /* dummy index for new-style
+ supremum and infimum records */
};
extern ulint srv_n_threads_active[];
diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h
index 8df0f97c4ff..d24f119c0b0 100644
--- a/innobase/include/srv0start.h
+++ b/innobase/include/srv0start.h
@@ -53,6 +53,16 @@ srv_parse_log_group_home_dirs(
error */
char* str, /* in: character string */
char*** log_group_home_dirs); /* out, own: log group home dirs */
+/*************************************************************************
+Adds a slash or a backslash to the end of a string if it is missing
+and the string is not empty. */
+
+char*
+srv_add_path_separator_if_needed(
+/*=============================*/
+ /* out: string which has the separator if the
+ string is not empty */
+ char* str); /* in: null-terminated character string */
/********************************************************************
Starts Innobase and creates a new database if database files
are not found and the user wants. Server parameters are
diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h
index 9a988a03e92..911c8ac3f4a 100644
--- a/innobase/include/sync0rw.h
+++ b/innobase/include/sync0rw.h
@@ -61,8 +61,8 @@ Creates, or rather, initializes an rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
is necessary only if the memory block containing it is freed. */
-
-#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__)
+#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__, #L)
+
/*=====================*/
/**********************************************************************
Creates, or rather, initializes an rw-lock object in a specified memory
@@ -75,7 +75,8 @@ rw_lock_create_func(
/*================*/
rw_lock_t* lock, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */
- ulint cline); /* in: file line where created */
+ ulint cline, /* in: file line where created */
+ const char* cmutex_name); /* in: mutex name */
/**********************************************************************
Calling this function is obligatory only if the memory buffer containing
the rw-lock is freed. Removes an rw-lock object from the global list. The
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index 3a92100ba01..b1ae636010a 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -138,7 +138,7 @@ rw_lock_s_lock_low(
#endif /* UNIV_SYNC_DEBUG */
/* Check if the writer field is free */
- if (lock->writer == RW_LOCK_NOT_LOCKED) {
+ if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
/* Set the shared lock by incrementing the reader count */
lock->reader_count++;
@@ -243,7 +243,7 @@ rw_lock_s_lock_func(
mutex_enter(rw_lock_get_mutex(lock));
- if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
+ if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) {
mutex_exit(rw_lock_get_mutex(lock));
return; /* Success */
@@ -307,21 +307,18 @@ rw_lock_x_lock_func_nowait(
const char* file_name,/* in: file name where lock requested */
ulint line) /* in: line where requested */
{
- ibool success = FALSE;
-
+ ibool success = FALSE;
+ os_thread_id_t curr_thread = os_thread_get_curr_id();
mutex_enter(rw_lock_get_mutex(lock));
- if ((rw_lock_get_reader_count(lock) == 0)
- && ((rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)
- || ((rw_lock_get_writer(lock) == RW_LOCK_EX)
- && (lock->pass == 0)
- && os_thread_eq(lock->writer_thread,
- os_thread_get_curr_id())))) {
-
+ if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
+ } else if (UNIV_LIKELY(rw_lock_get_writer(lock)
+ == RW_LOCK_NOT_LOCKED)) {
rw_lock_set_writer(lock, RW_LOCK_EX);
- lock->writer_thread = os_thread_get_curr_id();
- lock->writer_count++;
+ lock->writer_thread = curr_thread;
lock->pass = 0;
+ relock:
+ lock->writer_count++;
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
@@ -331,6 +328,10 @@ rw_lock_x_lock_func_nowait(
lock->last_x_line = line;
success = TRUE;
+ } else if (rw_lock_get_writer(lock) == RW_LOCK_EX
+ && lock->pass == 0
+ && os_thread_eq(lock->writer_thread, curr_thread)) {
+ goto relock;
}
mutex_exit(rw_lock_get_mutex(lock));
@@ -361,7 +362,7 @@ rw_lock_s_unlock_func(
/* Reset the shared lock by decrementing the reader count */
- ut_a(lock->reader_count > 0);
+ ut_ad(lock->reader_count > 0);
lock->reader_count--;
#ifdef UNIV_SYNC_DEBUG
@@ -371,7 +372,8 @@ rw_lock_s_unlock_func(
/* If there may be waiters and this was the last s-lock,
signal the object */
- if (lock->waiters && (lock->reader_count == 0)) {
+ if (UNIV_UNLIKELY(lock->waiters)
+ && lock->reader_count == 0) {
sg = TRUE;
rw_lock_set_waiters(lock, 0);
@@ -379,7 +381,7 @@ rw_lock_s_unlock_func(
mutex_exit(mutex);
- if (sg == TRUE) {
+ if (UNIV_UNLIKELY(sg)) {
sync_array_signal_object(sync_primary_wait_array, lock);
}
@@ -450,7 +452,8 @@ rw_lock_x_unlock_func(
#endif
/* If there may be waiters, signal the lock */
- if (lock->waiters && (lock->writer_count == 0)) {
+ if (UNIV_UNLIKELY(lock->waiters)
+ && lock->writer_count == 0) {
sg = TRUE;
rw_lock_set_waiters(lock, 0);
@@ -458,7 +461,7 @@ rw_lock_x_unlock_func(
mutex_exit(&(lock->mutex));
- if (sg == TRUE) {
+ if (UNIV_UNLIKELY(sg)) {
sync_array_signal_object(sync_primary_wait_array, lock);
}
diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h
index 8e0ec715b12..5955ab9a06a 100644
--- a/innobase/include/sync0sync.h
+++ b/innobase/include/sync0sync.h
@@ -17,6 +17,10 @@ Created 9/5/1995 Heikki Tuuri
#include "os0sync.h"
#include "sync0arr.h"
+#ifndef UNIV_HOTBACKUP
+extern my_bool timed_mutexes;
+#endif /* UNIV_HOTBACKUP */
+
/**********************************************************************
Initializes the synchronization data structures. */
@@ -35,8 +39,7 @@ location (which must be appropriately aligned). The mutex is initialized
in the reset state. Explicit freeing of the mutex with mutex_free is
necessary only if the memory block containing it is freed. */
-
-#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__)
+#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__, #M)
/*===================*/
/**********************************************************************
Creates, or rather, initializes a mutex object in a specified memory
@@ -49,7 +52,8 @@ mutex_create_func(
/*==============*/
mutex_t* mutex, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */
- ulint cline); /* in: file line where created */
+ ulint cline, /* in: file line where created */
+ const char* cmutex_name); /* in: mutex name */
/**********************************************************************
Calling this function is obligatory only if the memory buffer containing
the mutex is freed. Removes a mutex object from the mutex list. The mutex
@@ -413,6 +417,8 @@ or row lock! */
/*------------------------------------- Insert buffer tree */
#define SYNC_IBUF_BITMAP_MUTEX 351
#define SYNC_IBUF_BITMAP 350
+/*------------------------------------- MySQL query cache mutex */
+/*------------------------------------- MySQL binlog mutex */
/*-------------------------------*/
#define SYNC_KERNEL 300
#define SYNC_REC_LOCK 299
@@ -471,6 +477,17 @@ struct mutex_struct {
const char* cfile_name;/* File name where mutex created */
ulint cline; /* Line where created */
ulint magic_n;
+#ifndef UNIV_HOTBACKUP
+ ulong count_using; /* count of times mutex used */
+ ulong count_spin_loop; /* count of spin loops */
+ ulong count_spin_rounds; /* count of spin rounds */
+ ulong count_os_wait; /* count of os_wait */
+ ulong count_os_yield; /* count of os_wait */
+ ulonglong lspent_time; /* mutex os_wait timer msec */
+ ulonglong lmax_spent_time; /* mutex os_wait timer msec */
+ const char* cmutex_name;/* mutex name */
+ ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */
+#endif /* !UNIV_HOTBACKUP */
};
#define MUTEX_MAGIC_N (ulint)979585
@@ -504,6 +521,14 @@ extern ibool sync_order_checks_on;
/* This variable is set to TRUE when sync_init is called */
extern ibool sync_initialized;
+/* Global list of database mutexes (not OS mutexes) created. */
+typedef UT_LIST_BASE_NODE_T(mutex_t) ut_list_base_node_t;
+extern ut_list_base_node_t mutex_list;
+
+/* Mutex protecting the mutex_list variable */
+extern mutex_t mutex_list_mutex;
+
+
#ifndef UNIV_NONINL
#include "sync0sync.ic"
#endif
diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic
index aaf5e1fd9e9..b3fde61db5e 100644
--- a/innobase/include/sync0sync.ic
+++ b/innobase/include/sync0sync.ic
@@ -249,8 +249,13 @@ mutex_enter_func(
/* Note that we do not peek at the value of lock_word before trying
the atomic test_and_set; we could peek, and possibly save time. */
+
+#ifndef UNIV_HOTBACKUP
+ mutex->count_using++;
+#endif /* UNIV_HOTBACKUP */
- if (!mutex_test_and_set(mutex)) {
+ if (!mutex_test_and_set(mutex))
+ {
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
@@ -258,4 +263,5 @@ mutex_enter_func(
}
mutex_spin_wait(mutex, file_name, line);
+
}
diff --git a/innobase/include/trx0rec.h b/innobase/include/trx0rec.h
index 9d7f41cd94e..4387ce1a61e 100644
--- a/innobase/include/trx0rec.h
+++ b/innobase/include/trx0rec.h
@@ -246,6 +246,7 @@ trx_undo_prev_version_build(
index_rec page and purge_view */
rec_t* rec, /* in: version of a clustered index record */
dict_index_t* index, /* in: clustered index */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) */
mem_heap_t* heap, /* in: memory heap from which the memory
needed is allocated */
rec_t** old_vers);/* out, own: previous version, or NULL if
diff --git a/innobase/include/trx0roll.h b/innobase/include/trx0roll.h
index 6004551f456..944142a299d 100644
--- a/innobase/include/trx0roll.h
+++ b/innobase/include/trx0roll.h
@@ -104,11 +104,20 @@ trx_rollback(
/***********************************************************************
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
-undo log. If the transaction was not yet committed, then we roll it back. */
+undo log. If the transaction was not yet committed, then we roll it back.
+Note: this is done in a background thread. */
-void
-trx_rollback_or_clean_all_without_sess(void);
-/*========================================*/
+#ifndef __WIN__
+void*
+#else
+ulint
+#endif
+trx_rollback_or_clean_all_without_sess(
+/*===================================*/
+ /* out: a dummy parameter */
+ void* arg __attribute__((unused)));
+ /* in: a dummy parameter required by
+ os_thread_create */
/********************************************************************
Finishes a transaction rollback. */
@@ -216,6 +225,21 @@ trx_savepoint_for_mysql(
position corresponding to this
connection at the time of the
savepoint */
+
+/***********************************************************************
+Releases a named savepoint. Savepoints which
+were set after this savepoint are deleted. */
+
+ulint
+trx_release_savepoint_for_mysql(
+/*================================*/
+ /* out: if no savepoint
+ of the name found then
+ DB_NO_SAVEPOINT,
+ otherwise DB_SUCCESS */
+ trx_t* trx, /* in: transaction handle */
+ const char* savepoint_name); /* in: savepoint name */
+
/***********************************************************************
Frees savepoint structs. */
diff --git a/innobase/include/trx0rseg.ic b/innobase/include/trx0rseg.ic
index 35e927f5e79..c9ac50ebf16 100644
--- a/innobase/include/trx0rseg.ic
+++ b/innobase/include/trx0rseg.ic
@@ -65,7 +65,7 @@ trx_rsegf_get_nth_undo(
ulint n, /* in: index of slot */
mtr_t* mtr) /* in: mtr */
{
- if (n >= TRX_RSEG_N_SLOTS) {
+ if (UNIV_UNLIKELY(n >= TRX_RSEG_N_SLOTS)) {
fprintf(stderr,
"InnoDB: Error: trying to get slot %lu of rseg\n", (unsigned long) n);
ut_error;
@@ -86,7 +86,7 @@ trx_rsegf_set_nth_undo(
ulint page_no,/* in: page number of the undo log segment */
mtr_t* mtr) /* in: mtr */
{
- if (n >= TRX_RSEG_N_SLOTS) {
+ if (UNIV_UNLIKELY(n >= TRX_RSEG_N_SLOTS)) {
fprintf(stderr,
"InnoDB: Error: trying to set slot %lu of rseg\n", (unsigned long) n);
ut_error;
diff --git a/innobase/include/trx0sys.ic b/innobase/include/trx0sys.ic
index 8f455e554ea..24610bef827 100644
--- a/innobase/include/trx0sys.ic
+++ b/innobase/include/trx0sys.ic
@@ -315,7 +315,7 @@ trx_is_active(
}
if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) {
-
+
/* There must be corruption: we return TRUE because this
function is only called by lock_clust_rec_some_has_impl()
and row_vers_impl_x_locked_off_kernel() and they have
@@ -325,8 +325,9 @@ trx_is_active(
}
trx = trx_get_on_id(trx_id);
- if (trx && (trx->conc_state == TRX_ACTIVE)) {
-
+ if (trx && (trx->conc_state == TRX_ACTIVE ||
+ trx->conc_state == TRX_PREPARED)) {
+
return(TRUE);
}
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 905b25447a8..5dbf003594f 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -16,9 +16,39 @@ Created 3/26/1996 Heikki Tuuri
#include "que0types.h"
#include "mem0mem.h"
#include "read0types.h"
+#include "dict0types.h"
+#include "trx0xa.h"
extern ulint trx_n_mysql_transactions;
+/*****************************************************************
+Resets the new record lock info in a transaction struct. */
+UNIV_INLINE
+void
+trx_reset_new_rec_lock_info(
+/*========================*/
+ trx_t* trx); /* in: transaction struct */
+/*****************************************************************
+Registers that we have set a new record lock on an index. We only have space
+to store 2 indexes! If this is called to store more than 2 indexes after
+trx_reset_new_rec_lock_info(), then this function does nothing. */
+UNIV_INLINE
+void
+trx_register_new_rec_lock(
+/*======================*/
+ trx_t* trx, /* in: transaction struct */
+ dict_index_t* index); /* in: trx sets a new record lock on this
+ index */
+/*****************************************************************
+Checks if trx has set a new record lock on an index. */
+UNIV_INLINE
+ibool
+trx_new_rec_locks_contain(
+/*======================*/
+ /* out: TRUE if trx has set a new record lock
+ on index */
+ trx_t* trx, /* in: transaction struct */
+ dict_index_t* index); /* in: index */
/************************************************************************
Releases the search latch if trx has reserved it. */
@@ -157,6 +187,32 @@ trx_commit_for_mysql(
/* out: 0 or error number */
trx_t* trx); /* in: trx handle */
/**************************************************************************
+Does the transaction prepare for MySQL. */
+
+ulint
+trx_prepare_for_mysql(
+/*=================*/
+ /* out: 0 or error number */
+ trx_t* trx); /* in: trx handle */
+/**************************************************************************
+This function is used to find number of prepared transactions and
+their transaction objects for a recovery. */
+
+int
+trx_recover_for_mysql(
+/*==================*/
+ /* out: number of prepared transactions */
+ XID* xid_list, /* in/out: prepared transactions */
+ ulint len); /* in: number of slots in xid_list */
+/***********************************************************************
+This function is used to commit one X/Open XA distributed transaction
+which is in the prepared state */
+trx_t *
+trx_get_trx_by_xid(
+/*===============*/
+ /* out: trx or NULL */
+ XID* xid); /* in: X/Open XA transaction identification */
+/**************************************************************************
If required, flushes the log to disk if we called trx_commit_for_mysql()
with trx->flush_log_later == TRUE. */
@@ -273,17 +329,33 @@ trx_commit_step(
/*============*/
/* out: query thread to run next, or NULL */
que_thr_t* thr); /* in: query thread */
+
/**************************************************************************
-Prints info about a transaction to the standard output. The caller must
-own the kernel mutex and must have called
-innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL or
-InnoDB cannot meanwhile change the info printed here. */
+Prints info about a transaction to the given file. The caller must own the
+kernel mutex and must have called
+innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
+or InnoDB cannot meanwhile change the info printed here. */
void
trx_print(
/*======*/
- FILE* f, /* in: output stream */
+ FILE* f, /* in: output stream */
+ trx_t* trx, /* in: transaction */
+ uint max_query_len); /* in: max query length to print, or 0 to
+ use the default max length */
+
+#ifndef UNIV_HOTBACKUP
+/**************************************************************************
+Determines if the currently running transaction has been interrupted. */
+
+ibool
+trx_is_interrupted(
+/*===============*/
+ /* out: TRUE if interrupted */
trx_t* trx); /* in: transaction */
+#else /* !UNIV_HOTBACKUP */
+#define trx_is_interrupted(trx) FALSE
+#endif /* !UNIV_HOTBACKUP */
/* Signal to a transaction */
@@ -339,6 +411,14 @@ struct trx_struct{
if we can use the insert buffer for
them, we set this FALSE */
dulint id; /* transaction id */
+ XID xid; /* X/Open XA transaction
+ identification to identify a
+ transaction branch */
+ ibool support_xa; /* normally we do the XA two-phase
+ commit steps, but by setting this to
+ FALSE, one can save CPU time and about
+ 150 bytes in the undo log size as then
+ we skip XA steps */
dulint no; /* transaction serialization number ==
max trx id when the transaction is
moved to COMMITTED_IN_MEMORY state */
@@ -355,12 +435,17 @@ struct trx_struct{
dulint commit_lsn; /* lsn at the time of the commit */
ibool dict_operation; /* TRUE if the trx is used to create
a table, create an index, or drop a
- table */
+ table. This is a hint that the table
+ may need to be dropped in crash
+ recovery. */
dulint table_id; /* table id if the preceding field is
TRUE */
/*------------------------------*/
- void* mysql_thd; /* MySQL thread handle corresponding
- to this trx, or NULL */
+ int active_trans; /* 1 - if a transaction in MySQL
+ is active. 2 - if prepare_commit_mutex
+ was taken */
+ void* mysql_thd; /* MySQL thread handle corresponding
+ to this trx, or NULL */
char** mysql_query_str;/* pointer to the field in mysqld_thd
which contains the pointer to the
current SQL query string */
@@ -442,9 +527,18 @@ struct trx_struct{
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
the transaction; note that it is also
in the lock list trx_locks */
- ulint n_lock_table_exp;/* number of explicit table locks
- (LOCK TABLES) reserved by the
- transaction, stored in trx_locks */
+ dict_index_t* new_rec_locks[2];/* these are normally NULL; if
+ srv_locks_unsafe_for_binlog is TRUE,
+ in a cursor search, if we set a new
+ record lock on an index, this is set
+ to point to the index; this is
+ used in releasing the locks under the
+ cursors if we are performing an UPDATE
+ and we determine after retrieving
+ the row that it does not need to be
+ locked; thus, these can be used to
+ implement a 'mini-rollback' that
+ releases the latest record locks */
UT_LIST_NODE_T(trx_t)
trx_list; /* list of transactions */
UT_LIST_NODE_T(trx_t)
@@ -511,8 +605,18 @@ struct trx_struct{
UT_LIST_BASE_NODE_T(lock_t)
trx_locks; /* locks reserved by the transaction */
/*------------------------------*/
- mem_heap_t* read_view_heap; /* memory heap for the read view */
- read_view_t* read_view; /* consistent read view or NULL */
+ mem_heap_t* global_read_view_heap;
+ /* memory heap for the global read
+ view */
+ read_view_t* global_read_view;
+ /* consistent read view associated
+ to a transaction or NULL */
+ read_view_t* read_view; /* consistent read view used in the
+ transaction or NULL, this read view
+ if defined can be normal read view
+ associated to a transaction (i.e.
+ same as global_read_view) or read view
+ associated to a cursor */
/*------------------------------*/
UT_LIST_BASE_NODE_T(trx_named_savept_t)
trx_savepoints; /* savepoints set with SAVEPOINT ...,
@@ -560,6 +664,7 @@ struct trx_struct{
#define TRX_NOT_STARTED 1
#define TRX_ACTIVE 2
#define TRX_COMMITTED_IN_MEMORY 3
+#define TRX_PREPARED 4 /* Support for 2PC/XA */
/* Transaction execution states when trx state is TRX_ACTIVE */
#define TRX_QUE_RUNNING 1 /* transaction is running */
diff --git a/innobase/include/trx0trx.ic b/innobase/include/trx0trx.ic
index 78e5acda148..54cf2ff331f 100644
--- a/innobase/include/trx0trx.ic
+++ b/innobase/include/trx0trx.ic
@@ -39,4 +39,60 @@ trx_start_if_not_started_low(
}
}
+/*****************************************************************
+Resets the new record lock info in a transaction struct. */
+UNIV_INLINE
+void
+trx_reset_new_rec_lock_info(
+/*========================*/
+ trx_t* trx) /* in: transaction struct */
+{
+ trx->new_rec_locks[0] = NULL;
+ trx->new_rec_locks[1] = NULL;
+}
+
+/*****************************************************************
+Registers that we have set a new record lock on an index. We only have space
+to store 2 indexes! If this is called to store more than 2 indexes after
+trx_reset_new_rec_lock_info(), then this function does nothing. */
+UNIV_INLINE
+void
+trx_register_new_rec_lock(
+/*======================*/
+ trx_t* trx, /* in: transaction struct */
+ dict_index_t* index) /* in: trx sets a new record lock on this
+ index */
+{
+ if (trx->new_rec_locks[0] == NULL) {
+ trx->new_rec_locks[0] = index;
+
+ return;
+ }
+
+ if (trx->new_rec_locks[0] == index) {
+ return;
+ }
+
+ if (trx->new_rec_locks[1] != NULL) {
+
+ return;
+ }
+
+ trx->new_rec_locks[1] = index;
+}
+
+/*****************************************************************
+Checks if trx has set a new record lock on an index. */
+UNIV_INLINE
+ibool
+trx_new_rec_locks_contain(
+/*======================*/
+ /* out: TRUE if trx has set a new record lock
+ on index */
+ trx_t* trx, /* in: transaction struct */
+ dict_index_t* index) /* in: index */
+{
+ return(trx->new_rec_locks[0] == index
+ || trx->new_rec_locks[1] == index);
+}
diff --git a/innobase/include/trx0undo.h b/innobase/include/trx0undo.h
index 20002076cc3..bd7337e4f90 100644
--- a/innobase/include/trx0undo.h
+++ b/innobase/include/trx0undo.h
@@ -14,6 +14,7 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.h"
#include "trx0sys.h"
#include "page0types.h"
+#include "trx0xa.h"
/***************************************************************************
Builds a roll pointer dulint. */
@@ -36,7 +37,7 @@ trx_undo_decode_roll_ptr(
ibool* is_insert, /* out: TRUE if insert undo log */
ulint* rseg_id, /* out: rollback segment id */
ulint* page_no, /* out: page number */
- ulint* offset); /* out: offset of the undo entry within page */
+ ulint* offset); /* out: offset of the undo entry within page */
/***************************************************************************
Returns TRUE if the roll pointer is of the insert type. */
UNIV_INLINE
@@ -239,6 +240,18 @@ trx_undo_set_state_at_finish(
trx_t* trx, /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr); /* in: mtr */
+/**********************************************************************
+Sets the state of the undo log segment at a transaction prepare. */
+
+page_t*
+trx_undo_set_state_at_prepare(
+/*==========================*/
+ /* out: undo log segment header page,
+ x-latched */
+ trx_t* trx, /* in: transaction */
+ trx_undo_t* undo, /* in: undo log memory copy */
+ mtr_t* mtr); /* in: mtr */
+
/**************************************************************************
Adds the update undo log header as the first in the history list, and
frees the memory object, or puts it to the list of cached update undo log
@@ -295,7 +308,6 @@ trx_undo_parse_discard_latest(
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
-
/* Types of an undo log segment */
#define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */
#define TRX_UNDO_UPDATE 2 /* contains undo entries for updates
@@ -310,6 +322,8 @@ trx_undo_parse_discard_latest(
#define TRX_UNDO_TO_PURGE 4 /* update undo segment will not be
reused: it can be freed in purge when
all undo data in it is removed */
+#define TRX_UNDO_PREPARED 5 /* contains an undo log of an
+ prepared transaction */
/* Transaction undo log memory object; this is protected by the undo_mutex
in the corresponding transaction object */
@@ -332,6 +346,8 @@ struct trx_undo_struct{
field */
dulint trx_id; /* id of the trx assigned to the undo
log */
+ XID xid; /* X/Open XA transaction
+ identification */
ibool dict_operation; /* TRUE if a dict operation trx */
dulint table_id; /* if a dict operation, then the table
id */
@@ -386,7 +402,8 @@ struct trx_undo_struct{
#define TRX_UNDO_PAGE_HDR_SIZE (6 + FLST_NODE_SIZE)
/* An update undo segment with just one page can be reused if it has
-< this number bytes used */
+< this number bytes used; we must leave space at least for one new undo
+log header on the page */
#define TRX_UNDO_PAGE_REUSE_LIMIT (3 * UNIV_PAGE_SIZE / 4)
@@ -436,7 +453,10 @@ page of an update undo log segment. */
log start, and therefore this is not
necessarily the same as this log
header end offset */
-#define TRX_UNDO_DICT_OPERATION 20 /* TRUE if the transaction is a table
+#define TRX_UNDO_XID_EXISTS 20 /* TRUE if undo log header includes
+ X/Open XA transaction identification
+ XID */
+#define TRX_UNDO_DICT_TRANS 21 /* TRUE if the transaction is a table
create, index create, or drop
transaction: in recovery
the transaction cannot be rolled back
@@ -452,7 +472,25 @@ page of an update undo log segment. */
#define TRX_UNDO_HISTORY_NODE 34 /* If the log is put to the history
list, the file list node is here */
/*-------------------------------------------------------------*/
-#define TRX_UNDO_LOG_HDR_SIZE (34 + FLST_NODE_SIZE)
+#define TRX_UNDO_LOG_OLD_HDR_SIZE (34 + FLST_NODE_SIZE)
+
+/* Note: the writing of the undo log old header is coded by a log record
+MLOG_UNDO_HDR_CREATE or MLOG_UNDO_HDR_REUSE. The appending of an XID to the
+header is logged separately. In this sense, the XID is not really a member
+of the undo log header. TODO: do not append the XID to the log header if XA
+is not needed by the user. The XID wastes about 150 bytes of space in every
+undo log. In the history list we may have millions of undo logs, which means
+quite a large overhead. */
+
+/* X/Open XA Transaction Identification (XID) */
+
+#define TRX_UNDO_XA_FORMAT (TRX_UNDO_LOG_OLD_HDR_SIZE)
+#define TRX_UNDO_XA_TRID_LEN (TRX_UNDO_XA_FORMAT + 4)
+#define TRX_UNDO_XA_BQUAL_LEN (TRX_UNDO_XA_TRID_LEN + 4)
+#define TRX_UNDO_XA_XID (TRX_UNDO_XA_BQUAL_LEN + 4)
+/*--------------------------------------------------------------*/
+#define TRX_UNDO_LOG_XA_HDR_SIZE (TRX_UNDO_XA_XID + XIDDATASIZE)
+ /* Total size of the header with the XA XID */
#ifndef UNIV_NONINL
#include "trx0undo.ic"
diff --git a/innobase/include/trx0xa.h b/innobase/include/trx0xa.h
new file mode 100644
index 00000000000..34b7a2f95a8
--- /dev/null
+++ b/innobase/include/trx0xa.h
@@ -0,0 +1,182 @@
+/*
+ * Start of xa.h header
+ *
+ * Define a symbol to prevent multiple inclusions of this header file
+ */
+#ifndef XA_H
+#define XA_H
+
+/*
+ * Transaction branch identification: XID and NULLXID:
+ */
+#ifndef XIDDATASIZE
+
+#define XIDDATASIZE 128 /* size in bytes */
+#define MAXGTRIDSIZE 64 /* maximum size in bytes of gtrid */
+#define MAXBQUALSIZE 64 /* maximum size in bytes of bqual */
+
+struct xid_t {
+ long formatID; /* format identifier */
+ long gtrid_length; /* value from 1 through 64 */
+ long bqual_length; /* value from 1 through 64 */
+ char data[XIDDATASIZE];
+};
+typedef struct xid_t XID;
+#endif
+/*
+ * A value of -1 in formatID means that the XID is null.
+ */
+
+
+#ifdef NOTDEFINED
+/* Let us comment this out to remove compiler errors!!!!!!!!!!!! */
+
+/*
+ * Declarations of routines by which RMs call TMs:
+ */
+extern int ax_reg __P((int, XID *, long));
+extern int ax_unreg __P((int, long));
+
+/*
+ * XA Switch Data Structure
+ */
+#define RMNAMESZ 32 /* length of resource manager name, */
+ /* including the null terminator */
+#define MAXINFOSIZE 256 /* maximum size in bytes of xa_info */
+ /* strings, including the null
+ terminator */
+
+
+struct xa_switch_t {
+ char name[RMNAMESZ]; /* name of resource manager */
+ long flags; /* resource manager specific options */
+ long version; /* must be 0 */
+ int (*xa_open_entry) /* xa_open function pointer */
+ __P((char *, int, long));
+ int (*xa_close_entry) /* xa_close function pointer */
+ __P((char *, int, long));
+ int (*xa_start_entry) /* xa_start function pointer */
+ __P((XID *, int, long));
+ int (*xa_end_entry) /* xa_end function pointer */
+ __P((XID *, int, long));
+ int (*xa_rollback_entry) /* xa_rollback function pointer */
+ __P((XID *, int, long));
+ int (*xa_prepare_entry) /* xa_prepare function pointer */
+ __P((XID *, int, long));
+ int (*xa_commit_entry) /* xa_commit function pointer */
+ __P((XID *, int, long));
+ int (*xa_recover_entry) /* xa_recover function pointer */
+ __P((XID *, long, int, long));
+ int (*xa_forget_entry) /* xa_forget function pointer */
+ __P((XID *, int, long));
+ int (*xa_complete_entry) /* xa_complete function pointer */
+ __P((int *, int *, int, long));
+};
+#endif /* NOTDEFINED */
+
+
+/*
+ * Flag definitions for the RM switch
+ */
+#define TMNOFLAGS 0x00000000L /* no resource manager features
+ selected */
+#define TMREGISTER 0x00000001L /* resource manager dynamically
+ registers */
+#define TMNOMIGRATE 0x00000002L /* resource manager does not support
+ association migration */
+#define TMUSEASYNC 0x00000004L /* resource manager supports
+ asynchronous operations */
+/*
+ * Flag definitions for xa_ and ax_ routines
+ */
+/* use TMNOFLAGGS, defined above, when not specifying other flags */
+#define TMASYNC 0x80000000L /* perform routine asynchronously */
+#define TMONEPHASE 0x40000000L /* caller is using one-phase commit
+ optimisation */
+#define TMFAIL 0x20000000L /* dissociates caller and marks
+ transaction branch rollback-only */
+#define TMNOWAIT 0x10000000L /* return if blocking condition
+ exists */
+#define TMRESUME 0x08000000L /* caller is resuming association with
+ suspended transaction branch */
+#define TMSUCCESS 0x04000000L /* dissociate caller from transaction
+ branch */
+#define TMSUSPEND 0x02000000L /* caller is suspending, not ending,
+ association */
+#define TMSTARTRSCAN 0x01000000L /* start a recovery scan */
+#define TMENDRSCAN 0x00800000L /* end a recovery scan */
+#define TMMULTIPLE 0x00400000L /* wait for any asynchronous
+ operation */
+#define TMJOIN 0x00200000L /* caller is joining existing
+ transaction branch */
+#define TMMIGRATE 0x00100000L /* caller intends to perform
+ migration */
+
+/*
+ * ax_() return codes (transaction manager reports to resource manager)
+ */
+#define TM_JOIN 2 /* caller is joining existing
+ transaction branch */
+#define TM_RESUME 1 /* caller is resuming association with
+ suspended transaction branch */
+#define TM_OK 0 /* normal execution */
+#define TMER_TMERR -1 /* an error occurred in the transaction
+ manager */
+#define TMER_INVAL -2 /* invalid arguments were given */
+#define TMER_PROTO -3 /* routine invoked in an improper
+ context */
+
+/*
+ * xa_() return codes (resource manager reports to transaction manager)
+ */
+#define XA_RBBASE 100 /* The inclusive lower bound of the
+ rollback codes */
+#define XA_RBROLLBACK XA_RBBASE /* The rollback was caused by an
+ unspecified reason */
+#define XA_RBCOMMFAIL XA_RBBASE+1 /* The rollback was caused by a
+ communication failure */
+#define XA_RBDEADLOCK XA_RBBASE+2 /* A deadlock was detected */
+#define XA_RBINTEGRITY XA_RBBASE+3 /* A condition that violates the
+ integrity of the resources was
+ detected */
+#define XA_RBOTHER XA_RBBASE+4 /* The resource manager rolled back the
+ transaction branch for a reason not
+ on this list */
+#define XA_RBPROTO XA_RBBASE+5 /* A protocol error occurred in the
+ resource manager */
+#define XA_RBTIMEOUT XA_RBBASE+6 /* A transaction branch took too long */
+#define XA_RBTRANSIENT XA_RBBASE+7 /* May retry the transaction branch */
+#define XA_RBEND XA_RBTRANSIENT /* The inclusive upper bound of the
+ rollback codes */
+#define XA_NOMIGRATE 9 /* resumption must occur where
+ suspension occurred */
+#define XA_HEURHAZ 8 /* the transaction branch may have
+ been heuristically completed */
+#define XA_HEURCOM 7 /* the transaction branch has been
+ heuristically committed */
+#define XA_HEURRB 6 /* the transaction branch has been
+ heuristically rolled back */
+#define XA_HEURMIX 5 /* the transaction branch has been
+ heuristically committed and rolled
+ back */
+#define XA_RETRY 4 /* routine returned with no effect and
+ may be re-issued */
+#define XA_RDONLY 3 /* the transaction branch was read-only
+ and has been committed */
+#define XA_OK 0 /* normal execution */
+#define XAER_ASYNC -2 /* asynchronous operation already
+ outstanding */
+#define XAER_RMERR -3 /* a resource manager error occurred in
+ the transaction branch */
+#define XAER_NOTA -4 /* the XID is not valid */
+#define XAER_INVAL -5 /* invalid arguments were given */
+#define XAER_PROTO -6 /* routine invoked in an improper
+ context */
+#define XAER_RMFAIL -7 /* resource manager unavailable */
+#define XAER_DUPID -8 /* the XID already exists */
+#define XAER_OUTSIDE -9 /* resource manager doing work outside
+ transaction */
+#endif /* ifndef XA_H */
+/*
+ * End of xa.h header
+ */
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index 625978ffc38..15650f22ed8 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -80,6 +80,10 @@ memory is read outside the allocated blocks. */
/* Make a non-inline debug version */
+/* You can remove this define when the release is stable. This define adds
+some consistency checks to code. They use a little CPU time. */
+#define UNIV_RELEASE_NOT_YET_STABLE
+
/*
#define UNIV_DEBUG
#define UNIV_MEM_DEBUG
@@ -88,6 +92,7 @@ memory is read outside the allocated blocks. */
#define UNIV_SEARCH_DEBUG
#define UNIV_SYNC_PERF_STAT
#define UNIV_SEARCH_PERF_STAT
+#define UNIV_SRV_PRINT_LATCH_WAITS;
*/
#define UNIV_LIGHT_MEM_DEBUG
@@ -180,7 +185,7 @@ management to ensure correct alignment for doubles etc. */
/* Another basic type we use is unsigned long integer which should be equal to
the word size of the machine, that is on a 32-bit platform 32 bits, and on a
64-bit platform 64 bits. We also give the printf format for the type as a
-macro PRULINT. */
+macro ULINTPF. */
#ifdef _WIN64
typedef unsigned __int64 ulint;
@@ -242,6 +247,30 @@ contains the sum of the following flag and the locally stored len. */
#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE)
+/* Some macros to improve branch prediction and reduce cache misses */
+#if defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER)
+/* Tell the compiler that 'expr' probably evaluates to 'constant'. */
+# define UNIV_EXPECT(expr,constant) __builtin_expect(expr, constant)
+/* Tell the compiler that a pointer is likely to be NULL */
+# define UNIV_LIKELY_NULL(ptr) __builtin_expect((ulint) ptr, 0)
+/* Minimize cache-miss latency by moving data at addr into a cache before
+it is read. */
+# define UNIV_PREFETCH_R(addr) __builtin_prefetch(addr, 0, 3)
+/* Minimize cache-miss latency by moving data at addr into a cache before
+it is read or written. */
+# define UNIV_PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 3)
+#else
+/* Dummy versions of the macros */
+# define UNIV_EXPECT(expr,value) (expr)
+# define UNIV_LIKELY_NULL(expr) (expr)
+# define UNIV_PREFETCH_R(addr) ((void) 0)
+# define UNIV_PREFETCH_RW(addr) ((void) 0)
+#endif
+/* Tell the compiler that cond is likely to hold */
+#define UNIV_LIKELY(cond) UNIV_EXPECT(cond, TRUE)
+/* Tell the compiler that cond is unlikely to hold */
+#define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE)
+
#include <stdio.h>
#include "ut0dbg.h"
#include "ut0ut.h"
diff --git a/innobase/include/ut0byte.h b/innobase/include/ut0byte.h
index a62c2e2e318..22d488abeaf 100644
--- a/innobase/include/ut0byte.h
+++ b/innobase/include/ut0byte.h
@@ -208,7 +208,20 @@ ut_align_down(
/*==========*/
/* out: aligned pointer */
void* ptr, /* in: pointer */
- ulint align_no); /* in: align by this number */
+ ulint align_no) /* in: align by this number */
+ __attribute__((const));
+/*************************************************************
+The following function computes the offset of a pointer from the nearest
+aligned address. */
+UNIV_INLINE
+ulint
+ut_align_offset(
+/*==========*/
+ /* out: distance from aligned
+ pointer */
+ const void* ptr, /* in: pointer */
+ ulint align_no) /* in: align by this number */
+ __attribute__((const));
/*********************************************************************
Gets the nth bit of a ulint. */
UNIV_INLINE
diff --git a/innobase/include/ut0byte.ic b/innobase/include/ut0byte.ic
index 5a70dcf12a8..e141de3aa3f 100644
--- a/innobase/include/ut0byte.ic
+++ b/innobase/include/ut0byte.ic
@@ -335,6 +335,27 @@ ut_align_down(
return((void*)((((ulint)ptr)) & ~(align_no - 1)));
}
+/*************************************************************
+The following function computes the offset of a pointer from the nearest
+aligned address. */
+UNIV_INLINE
+ulint
+ut_align_offset(
+/*============*/
+ /* out: distance from
+ aligned pointer */
+ const void* ptr, /* in: pointer */
+ ulint align_no) /* in: align by this number */
+{
+ ut_ad(align_no > 0);
+ ut_ad(((align_no - 1) & align_no) == 0);
+ ut_ad(ptr);
+
+ ut_ad(sizeof(void*) == sizeof(ulint));
+
+ return(((ulint)ptr) & (align_no - 1));
+}
+
/*********************************************************************
Gets the nth bit of a ulint. */
UNIV_INLINE
diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h
index 5f30a894874..bc3f852626a 100644
--- a/innobase/include/ut0dbg.h
+++ b/innobase/include/ut0dbg.h
@@ -13,74 +13,75 @@ Created 1/30/1994 Heikki Tuuri
#include <stdlib.h>
#include "os0thread.h"
+#if defined(__GNUC__) && (__GNUC__ > 2)
+# define UT_DBG_FAIL(EXPR) UNIV_UNLIKELY(!((ulint)(EXPR)))
+#else
extern ulint ut_dbg_zero; /* This is used to eliminate
compiler warnings */
+# define UT_DBG_FAIL(EXPR) !((ulint)(EXPR) + ut_dbg_zero)
+#endif
+
+/*****************************************************************
+Report a failed assertion. */
+
+void
+ut_dbg_assertion_failed(
+/*====================*/
+ const char* expr, /* in: the failed assertion */
+ const char* file, /* in: source file containing the assertion */
+ ulint line); /* in: line number of the assertion */
+
+#ifdef __NETWARE__
+/* Flag for ignoring further assertion failures.
+On NetWare, have a graceful exit rather than a segfault to avoid abends. */
+extern ibool panic_shutdown;
+/* Abort the execution. */
+void ut_dbg_panic(void);
+# define UT_DBG_PANIC ut_dbg_panic()
+/* Stop threads in ut_a(). */
+# define UT_DBG_STOP while (0) /* We do not do this on NetWare */
+#else /* __NETWARE__ */
+/* Flag for indicating that all threads should stop. This will be set
+by ut_dbg_assertion_failed(). */
extern ibool ut_dbg_stop_threads;
+/* A null pointer that will be dereferenced to trigger a memory trap */
extern ulint* ut_dbg_null_ptr;
-extern const char* ut_dbg_msg_assert_fail;
-extern const char* ut_dbg_msg_trap;
-extern const char* ut_dbg_msg_stop;
-/* Have a graceful exit on NetWare rather than a segfault to avoid abends */
-#ifdef __NETWARE__
-extern ibool panic_shutdown;
-#define ut_a(EXPR) do {\
- if (!((ulint)(EXPR) + ut_dbg_zero)) {\
- ut_print_timestamp(stderr);\
- fprintf(stderr, ut_dbg_msg_assert_fail,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__,\
- (ulint)__LINE__);\
- fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\
- fputs(ut_dbg_msg_trap, stderr);\
- ut_dbg_stop_threads = TRUE;\
- if (ut_dbg_stop_threads) {\
- fprintf(stderr, ut_dbg_msg_stop,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
- }\
- if(!panic_shutdown){\
- panic_shutdown = TRUE;\
- innobase_shutdown_for_mysql();}\
- exit(1);\
- }\
-} while (0)
-#define ut_error do {\
- ut_print_timestamp(stderr);\
- fprintf(stderr, ut_dbg_msg_assert_fail,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
- fprintf(stderr, ut_dbg_msg_trap);\
- ut_dbg_stop_threads = TRUE;\
- if(!panic_shutdown){panic_shutdown = TRUE;\
- innobase_shutdown_for_mysql();}\
-} while (0)
-#else
-#define ut_a(EXPR) do {\
- if (!((ulint)(EXPR) + ut_dbg_zero)) {\
- ut_print_timestamp(stderr);\
- fprintf(stderr, ut_dbg_msg_assert_fail,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__,\
- (ulint)__LINE__);\
- fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\
- fputs(ut_dbg_msg_trap, stderr);\
- ut_dbg_stop_threads = TRUE;\
- if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
- }\
- if (ut_dbg_stop_threads) {\
- fprintf(stderr, ut_dbg_msg_stop,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
- os_thread_sleep(1000000000);\
- }\
+/*****************************************************************
+Stop a thread after assertion failure. */
+
+void
+ut_dbg_stop_thread(
+/*===============*/
+ const char* file,
+ ulint line);
+
+/* Abort the execution. */
+# define UT_DBG_PANIC \
+ if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL
+/* Stop threads in ut_a(). */
+# define UT_DBG_STOP do \
+ if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \
+ ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \
+ } while (0)
+#endif /* __NETWARE__ */
+
+/* Abort execution if EXPR does not evaluate to nonzero. */
+#define ut_a(EXPR) do { \
+ if (UT_DBG_FAIL(EXPR)) { \
+ ut_dbg_assertion_failed(#EXPR, \
+ __FILE__, (ulint) __LINE__); \
+ UT_DBG_PANIC; \
+ } \
+ UT_DBG_STOP; \
} while (0)
-#define ut_error do {\
- ut_print_timestamp(stderr);\
- fprintf(stderr, ut_dbg_msg_assert_fail,\
- os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
- fprintf(stderr, ut_dbg_msg_trap);\
- ut_dbg_stop_threads = TRUE;\
- if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
+/* Abort execution. */
+#define ut_error do { \
+ ut_dbg_assertion_failed(0, __FILE__, (ulint) __LINE__); \
+ UT_DBG_PANIC; \
} while (0)
-#endif
#ifdef UNIV_DEBUG
#define ut_ad(EXPR) ut_a(EXPR)
diff --git a/innobase/include/ut0rnd.ic b/innobase/include/ut0rnd.ic
index 06d7012f60b..d2ab087d491 100644
--- a/innobase/include/ut0rnd.ic
+++ b/innobase/include/ut0rnd.ic
@@ -207,12 +207,12 @@ ut_fold_binary(
const byte* str, /* in: string of bytes */
ulint len) /* in: length */
{
- ulint i;
- ulint fold = 0;
+ const byte* str_end = str + len;
+ ulint fold = 0;
ut_ad(str);
- for (i = 0; i < len; i++) {
+ while (str < str_end) {
fold = ut_fold_ulint_pair(fold, (ulint)(*str));
str++;
diff --git a/innobase/include/ut0ut.h b/innobase/include/ut0ut.h
index dee8785c9e7..8938957cd12 100644
--- a/innobase/include/ut0ut.h
+++ b/innobase/include/ut0ut.h
@@ -139,6 +139,14 @@ ib_time_t
ut_time(void);
/*=========*/
/**************************************************************
+Returns system time. */
+
+void
+ut_usectime(
+/*========*/
+ ulint* sec, /* out: seconds since the Epoch */
+ ulint* ms); /* out: microseconds since the Epoch+*sec */
+/**************************************************************
Returns the difference of two times in seconds. */
double
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 1c08d3defaa..7844991613f 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -47,6 +47,10 @@ innobase_mysql_end_print_arbitrary_thd(void);
graph of transactions */
#define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
+/* Restricts the recursion depth of the search we will do in the waits-for
+graph of transactions */
+#define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200
+
/* When releasing transaction locks, this specifies how often we release
the kernel mutex for a moment to give also others access to it */
@@ -292,7 +296,25 @@ waiting, in its lock queue. Solution: We can copy the locks as gap type
locks, so that also the waiting locks are transformed to granted gap type
locks on the inserted record. */
+/* LOCK COMPATIBILITY MATRIX
+ * IS IX S X AI
+ * IS + + + - +
+ * IX + + - - +
+ * S + - + - -
+ * X - - - - -
+ * AI + + - - -
+ *
+ * Note that for rows, InnoDB only acquires S or X locks.
+ * For tables, InnoDB normally acquires IS or IX locks.
+ * S or X table locks are only acquired for LOCK TABLES.
+ * Auto-increment (AI) locks are needed because of
+ * statement-level MySQL binlog.
+ * See also lock_mode_compatible().
+ */
+
+#ifdef UNIV_DEBUG
ibool lock_print_waits = FALSE;
+#endif /* UNIV_DEBUG */
/* The lock system */
lock_sys_t* lock_sys = NULL;
@@ -348,23 +370,35 @@ static
ibool
lock_deadlock_occurs(
/*=================*/
- /* out: TRUE if a deadlock was detected */
+ /* out: TRUE if a deadlock was detected and we
+ chose trx as a victim; FALSE if no deadlock, or
+ there was a deadlock, but we chose other
+ transaction(s) as victim(s) */
lock_t* lock, /* in: lock the transaction is requesting */
trx_t* trx); /* in: transaction */
/************************************************************************
Looks recursively for a deadlock. */
static
-ibool
+ulint
lock_deadlock_recursive(
/*====================*/
- /* out: TRUE if a deadlock was detected
- or the calculation took too long */
+ /* out: 0 if no deadlock found,
+ LOCK_VICTIM_IS_START if there was a deadlock
+ and we chose 'start' as the victim,
+ LOCK_VICTIM_IS_OTHER if a deadlock
+ was found and we chose some other trx as a
+ victim: we must do the search again in this
+ last case because there may be another
+ deadlock! */
trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
- ulint* cost); /* in/out: number of calculation steps thus
+ ulint* cost, /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
- we return TRUE */
+ we return LOCK_VICTIM_IS_START */
+ uint depth); /* in: recursion depth: if this exceeds
+ LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
+ return LOCK_VICTIM_IS_START */
/*************************************************************************
Gets the type of a lock. */
@@ -424,12 +458,15 @@ lock_check_trx_id_sanity(
/* out: TRUE if ok */
dulint trx_id, /* in: trx id */
rec_t* rec, /* in: user record */
- dict_index_t* index, /* in: clustered index */
+ dict_index_t* index, /* in: index */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
ibool has_kernel_mutex)/* in: TRUE if the caller owns the
kernel mutex */
{
ibool is_ok = TRUE;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (!has_kernel_mutex) {
mutex_enter(&kernel_mutex);
}
@@ -442,7 +479,7 @@ lock_check_trx_id_sanity(
fputs(" InnoDB: Error: transaction id associated"
" with record\n",
stderr);
- rec_print(stderr, rec);
+ rec_print_new(stderr, rec, offsets);
fputs("InnoDB: in ", stderr);
dict_index_name_print(stderr, NULL, index);
fprintf(stderr, "\n"
@@ -474,25 +511,22 @@ lock_clust_rec_cons_read_sees(
rec_t* rec, /* in: user record which should be read or
passed over by a read cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
read_view_t* view) /* in: consistent read view */
{
dulint trx_id;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec));
+ ut_ad(rec_offs_validate(rec, index, offsets));
/* NOTE that we call this function while holding the search
system latch. To obey the latching order we must NOT reserve the
kernel mutex here! */
- trx_id = row_get_rec_trx_id(rec, index);
+ trx_id = row_get_rec_trx_id(rec, index, offsets);
- if (read_view_sees_trx_id(view, trx_id)) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(read_view_sees_trx_id(view, trx_id));
}
/*************************************************************************
@@ -689,7 +723,7 @@ lock_is_table_exclusive(
trx_t* trx) /* in: transaction */
{
lock_t* lock;
- bool ok = FALSE;
+ ibool ok = FALSE;
ut_ad(table && trx);
@@ -929,7 +963,7 @@ lock_rec_has_to_wait(
cause waits */
if ((lock_is_on_supremum || (type_mode & LOCK_GAP))
- && !(type_mode & LOCK_INSERT_INTENTION)) {
+ && !(type_mode & LOCK_INSERT_INTENTION)) {
/* Gap type locks without LOCK_INSERT_INTENTION flag
do not need to wait for anything. This is because
@@ -1263,19 +1297,19 @@ lock_rec_get_next(
#endif /* UNIV_SYNC_DEBUG */
ut_ad(lock_get_type(lock) == LOCK_REC);
- for (;;) {
- lock = lock_rec_get_next_on_page(lock);
-
- if (lock == NULL) {
-
- return(NULL);
- }
-
- if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec))) {
-
- return(lock);
- }
+ if (page_rec_is_comp(rec)) {
+ do {
+ lock = lock_rec_get_next_on_page(lock);
+ } while (lock && !lock_rec_get_nth_bit(lock,
+ rec_get_heap_no(rec, TRUE)));
+ } else {
+ do {
+ lock = lock_rec_get_next_on_page(lock);
+ } while (lock && !lock_rec_get_nth_bit(lock,
+ rec_get_heap_no(rec, FALSE)));
}
+
+ return(lock);
}
/*************************************************************************
@@ -1294,14 +1328,12 @@ lock_rec_get_first(
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first_on_page(rec);
+ if (UNIV_LIKELY_NULL(lock)) {
+ ulint heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
- while (lock) {
- if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec))) {
-
- break;
+ while (lock && !lock_rec_get_nth_bit(lock, heap_no)) {
+ lock = lock_rec_get_next_on_page(lock);
}
-
- lock = lock_rec_get_next_on_page(lock);
}
return(lock);
@@ -1556,7 +1588,6 @@ lock_rec_other_has_conflicting(
trx_t* trx) /* in: our transaction */
{
lock_t* lock;
-
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
@@ -1596,8 +1627,7 @@ lock_rec_find_similar_on_page(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- heap_no = rec_get_heap_no(rec);
-
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
lock = lock_rec_get_first_on_page(rec);
while (lock != NULL) {
@@ -1624,7 +1654,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index) /* in: secondary index */
+ dict_index_t* index, /* in: secondary index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
page_t* page;
@@ -1633,6 +1664,7 @@ lock_sec_rec_some_has_impl_off_kernel(
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!(index->type & DICT_CLUSTERED));
ut_ad(page_rec_is_user_rec(rec));
+ ut_ad(rec_offs_validate(rec, index, offsets));
page = buf_frame_align(rec);
@@ -1652,8 +1684,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* Ok, in this case it is possible that some transaction has an
implicit x-lock. We have to look in the clustered index. */
- if (!lock_check_trx_id_sanity(page_get_max_trx_id(page), rec, index,
- TRUE)) {
+ if (!lock_check_trx_id_sanity(page_get_max_trx_id(page),
+ rec, index, offsets, TRUE)) {
buf_page_print(page);
/* The page is corrupt: try to avoid a crash by returning
@@ -1661,7 +1693,7 @@ lock_sec_rec_some_has_impl_off_kernel(
return(NULL);
}
- return(row_vers_impl_x_locked_off_kernel(rec, index));
+ return(row_vers_impl_x_locked_off_kernel(rec, index, offsets));
}
/*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
@@ -1695,7 +1727,9 @@ lock_rec_create(
page = buf_frame_align(rec);
space = buf_frame_get_space_id(page);
page_no = buf_frame_get_page_no(page);
- heap_no = rec_get_heap_no(rec);
+ heap_no = rec_get_heap_no(rec, page_is_comp(page));
+
+ ut_ad(!!page_is_comp(page) == index->table->comp);
/* If rec is the supremum record, then we reset the gap and
LOCK_REC_NOT_GAP bits, as all locks on the supremum are
@@ -1708,13 +1742,12 @@ lock_rec_create(
}
/* Make lock bitmap bigger by a safety margin */
- n_bits = page_header_get_field(page, PAGE_N_HEAP)
- + LOCK_PAGE_BITMAP_MARGIN;
+ n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
n_bytes = 1 + n_bits / 8;
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
- if (lock == NULL) {
+ if (UNIV_UNLIKELY(lock == NULL)) {
return(NULL);
}
@@ -1739,7 +1772,7 @@ lock_rec_create(
lock_rec_set_nth_bit(lock, heap_no);
HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
- lock_rec_fold(space, page_no), lock);
+ lock_rec_fold(space, page_no), lock);
if (type_mode & LOCK_WAIT) {
lock_set_lock_and_trx_wait(lock, trx);
@@ -1811,7 +1844,8 @@ lock_rec_enqueue_waiting(
if (lock_deadlock_occurs(lock, trx)) {
lock_reset_lock_and_trx_wait(lock);
- lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec));
+ lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec,
+ page_rec_is_comp(rec)));
return(DB_DEADLOCK);
}
@@ -1830,11 +1864,13 @@ lock_rec_enqueue_waiting(
ut_a(que_thr_stop(thr));
+#ifdef UNIV_DEBUG
if (lock_print_waits) {
fprintf(stderr, "Lock wait for trx %lu in index ",
(ulong) ut_dulint_get_low(trx->id));
ut_print_name(stderr, trx, index->name);
}
+#endif /* UNIV_DEBUG */
return(DB_LOCK_WAIT);
}
@@ -1861,7 +1897,6 @@ lock_rec_add_to_queue(
lock_t* lock;
lock_t* similar_lock = NULL;
ulint heap_no;
- page_t* page;
ibool somebody_waits = FALSE;
#ifdef UNIV_SYNC_DEBUG
@@ -1869,21 +1904,21 @@ lock_rec_add_to_queue(
#endif /* UNIV_SYNC_DEBUG */
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_S)
- || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, rec, trx));
+ || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,
+ rec, trx));
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_X)
- || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, rec, trx));
+ || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
+ rec, trx));
type_mode = type_mode | LOCK_REC;
- page = buf_frame_align(rec);
-
/* If rec is the supremum record, then we can reset the gap bit, as
all locks on the supremum are automatically of the gap type, and we
try to avoid unnecessary memory consumption of a new record lock
struct for a gap type lock */
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
/* There should never be LOCK_REC_NOT_GAP on a supremum
@@ -1894,7 +1929,7 @@ lock_rec_add_to_queue(
/* Look for a waiting lock request on the same record or on a gap */
- heap_no = rec_get_heap_no(rec);
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
lock = lock_rec_get_first_on_page(rec);
while (lock != NULL) {
@@ -1945,6 +1980,7 @@ lock_rec_lock_fast(
{
lock_t* lock;
ulint heap_no;
+ trx_t* trx;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -1959,13 +1995,19 @@ lock_rec_lock_fast(
|| mode - (LOCK_MODE_MASK & mode) == 0
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
- heap_no = rec_get_heap_no(rec);
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
lock = lock_rec_get_first_on_page(rec);
+ trx = thr_get_trx(thr);
+
if (lock == NULL) {
if (!impl) {
- lock_rec_create(mode, rec, index, thr_get_trx(thr));
+ lock_rec_create(mode, rec, index, trx);
+
+ if (srv_locks_unsafe_for_binlog) {
+ trx_register_new_rec_lock(trx, index);
+ }
}
return(TRUE);
@@ -1976,14 +2018,23 @@ lock_rec_lock_fast(
return(FALSE);
}
- if (lock->trx != thr_get_trx(thr)
- || lock->type_mode != (mode | LOCK_REC)
- || lock_rec_get_n_bits(lock) <= heap_no) {
+ if (lock->trx != trx
+ || lock->type_mode != (mode | LOCK_REC)
+ || lock_rec_get_n_bits(lock) <= heap_no) {
+
return(FALSE);
}
if (!impl) {
- lock_rec_set_nth_bit(lock, heap_no);
+ /* If the nth bit of the record lock is already set then we
+ do not set a new lock bit, otherwise we do set */
+
+ if (!lock_rec_get_nth_bit(lock, heap_no)) {
+ lock_rec_set_nth_bit(lock, heap_no);
+ if (srv_locks_unsafe_for_binlog) {
+ trx_register_new_rec_lock(trx, index);
+ }
+ }
}
return(TRUE);
@@ -2039,12 +2090,19 @@ lock_rec_lock_slow(
enough already granted on the record, we have to wait. */
err = lock_rec_enqueue_waiting(mode, rec, index, thr);
+
+ if (srv_locks_unsafe_for_binlog) {
+ trx_register_new_rec_lock(trx, index);
+ }
} else {
if (!impl) {
/* Set the requested lock on the record */
lock_rec_add_to_queue(LOCK_REC | mode, rec, index,
trx);
+ if (srv_locks_unsafe_for_binlog) {
+ trx_register_new_rec_lock(trx, index);
+ }
}
err = DB_SUCCESS;
@@ -2168,15 +2226,14 @@ lock_grant(
release it at the end of the SQL statement */
lock->trx->auto_inc_lock = lock;
- } else if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_a(lock_get_mode(lock) == LOCK_S
- || lock_get_mode(lock) == LOCK_X);
- }
+ }
+#ifdef UNIV_DEBUG
if (lock_print_waits) {
fprintf(stderr, "Lock wait for trx %lu ends\n",
(ulong) ut_dulint_get_low(lock->trx->id));
}
+#endif /* UNIV_DEBUG */
/* If we are resolving a deadlock by choosing another transaction
as a victim, then our original transaction may not be in the
@@ -2343,12 +2400,12 @@ lock_rec_reset_and_release_wait(
{
lock_t* lock;
ulint heap_no;
-
+
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- heap_no = rec_get_heap_no(rec);
+ heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
lock = lock_rec_get_first(rec);
@@ -2377,15 +2434,21 @@ lock_rec_inherit_to_gap(
the locks on this record */
{
lock_t* lock;
-
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
+ /* If srv_locks_unsafe_for_binlog is TRUE, we do not want locks set
+ by an UPDATE or a DELETE to be inherited as gap type locks. But we
+ DO want S-locks set by a consistency constraint to be inherited also
+ then. */
+
while (lock != NULL) {
- if (!lock_rec_get_insert_intention(lock)) {
+ if (!lock_rec_get_insert_intention(lock)
+ && !(srv_locks_unsafe_for_binlog
+ && lock_get_mode(lock) == LOCK_X)) {
lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
| LOCK_GAP,
@@ -2409,7 +2472,6 @@ lock_rec_inherit_to_gap_if_gap_lock(
the locks on this record */
{
lock_t* lock;
-
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
@@ -2439,7 +2501,8 @@ lock_rec_move(
/*==========*/
rec_t* receiver, /* in: record which gets locks; this record
must have no lock requests on it! */
- rec_t* donator) /* in: record which gives locks */
+ rec_t* donator, /* in: record which gives locks */
+ ulint comp) /* in: nonzero=compact page format */
{
lock_t* lock;
ulint heap_no;
@@ -2449,7 +2512,7 @@ lock_rec_move(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- heap_no = rec_get_heap_no(donator);
+ heap_no = rec_get_heap_no(donator, comp);
lock = lock_rec_get_first(donator);
@@ -2495,6 +2558,7 @@ lock_move_reorganize_page(
UT_LIST_BASE_NODE_T(lock_t) old_locks;
mem_heap_t* heap = NULL;
rec_t* sup;
+ ulint comp;
lock_mutex_enter_kernel();
@@ -2535,6 +2599,9 @@ lock_move_reorganize_page(
lock = UT_LIST_GET_FIRST(old_locks);
+ comp = page_is_comp(page);
+ ut_ad(comp == page_is_comp(old_page));
+
while (lock) {
/* NOTE: we copy also the locks set on the infimum and
supremum of the page; the infimum may carry locks if an
@@ -2546,12 +2613,12 @@ lock_move_reorganize_page(
/* Set locks according to old locks */
for (;;) {
- ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
+ ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
- rec_get_data_size(
+ rec_get_data_size_old(
page_cur_get_rec(&cur2))));
-
- old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2));
+ old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2),
+ comp);
if (lock_rec_get_nth_bit(lock, old_heap_no)) {
@@ -2610,7 +2677,9 @@ lock_move_rec_list_end(
ulint heap_no;
rec_t* sup;
ulint type_mode;
-
+ ulint comp;
+ ut_ad(page == buf_frame_align(rec));
+
lock_mutex_enter_kernel();
/* Note: when we move locks from record to record, waiting locks
@@ -2623,6 +2692,8 @@ lock_move_rec_list_end(
lock = lock_rec_get_first_on_page(page);
+ comp = page_is_comp(page);
+
while (lock != NULL) {
page_cur_position(rec, &cur1);
@@ -2638,13 +2709,12 @@ lock_move_rec_list_end(
reset the lock bits on the old */
while (page_cur_get_rec(&cur1) != sup) {
-
- ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
+ ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
- rec_get_data_size(
+ rec_get_data_size_old(
page_cur_get_rec(&cur2))));
-
- heap_no = rec_get_heap_no(page_cur_get_rec(&cur1));
+ heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
+ comp);
if (lock_rec_get_nth_bit(lock, heap_no)) {
type_mode = lock->type_mode;
@@ -2694,12 +2764,16 @@ lock_move_rec_list_start(
page_cur_t cur2;
ulint heap_no;
ulint type_mode;
+ ulint comp;
ut_a(new_page);
lock_mutex_enter_kernel();
lock = lock_rec_get_first_on_page(page);
+ comp = page_is_comp(page);
+ ut_ad(comp == page_is_comp(new_page));
+ ut_ad(page == buf_frame_align(rec));
while (lock != NULL) {
@@ -2713,13 +2787,12 @@ lock_move_rec_list_start(
reset the lock bits on the old */
while (page_cur_get_rec(&cur1) != rec) {
-
- ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
+ ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
- rec_get_data_size(
+ rec_get_data_size_old(
page_cur_get_rec(&cur2))));
-
- heap_no = rec_get_heap_no(page_cur_get_rec(&cur1));
+ heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
+ comp);
if (lock_rec_get_nth_bit(lock, heap_no)) {
type_mode = lock->type_mode;
@@ -2759,13 +2832,16 @@ lock_update_split_right(
page_t* right_page, /* in: right page */
page_t* left_page) /* in: left page */
{
+ ulint comp;
lock_mutex_enter_kernel();
-
+ comp = page_is_comp(left_page);
+ ut_ad(comp == page_is_comp(right_page));
+
/* Move the locks on the supremum of the left page to the supremum
of the right page */
lock_rec_move(page_get_supremum_rec(right_page),
- page_get_supremum_rec(left_page));
+ page_get_supremum_rec(left_page), comp);
/* Inherit the locks to the supremum of left page from the successor
of the infimum on right page */
@@ -2819,13 +2895,16 @@ lock_update_root_raise(
page_t* new_page, /* in: index page to which copied */
page_t* root) /* in: root page */
{
+ ulint comp;
lock_mutex_enter_kernel();
-
+ comp = page_is_comp(root);
+ ut_ad(comp == page_is_comp(new_page));
+
/* Move the locks on the supremum of the root to the supremum
of new_page */
lock_rec_move(page_get_supremum_rec(new_page),
- page_get_supremum_rec(root));
+ page_get_supremum_rec(root), comp);
lock_mutex_exit_kernel();
}
@@ -2839,13 +2918,16 @@ lock_update_copy_and_discard(
page_t* new_page, /* in: index page to which copied */
page_t* page) /* in: index page; NOT the root! */
{
+ ulint comp;
lock_mutex_enter_kernel();
-
+ comp = page_is_comp(page);
+ ut_ad(comp == page_is_comp(new_page));
+
/* Move the locks on the supremum of the old page to the supremum
of new_page */
lock_rec_move(page_get_supremum_rec(new_page),
- page_get_supremum_rec(page));
+ page_get_supremum_rec(page), comp);
lock_rec_free_all_from_discard_page(page);
lock_mutex_exit_kernel();
@@ -2883,28 +2965,34 @@ lock_update_merge_left(
page_t* right_page) /* in: merged index page which will be
discarded */
{
+ rec_t* left_next_rec;
+ rec_t* left_supremum;
+ ulint comp;
lock_mutex_enter_kernel();
-
- if (page_rec_get_next(orig_pred) != page_get_supremum_rec(left_page)) {
+ comp = page_is_comp(left_page);
+ ut_ad(comp == page_is_comp(right_page));
+ ut_ad(left_page == buf_frame_align(orig_pred));
+
+ left_next_rec = page_rec_get_next(orig_pred);
+ left_supremum = page_get_supremum_rec(left_page);
+
+ if (UNIV_LIKELY(left_next_rec != left_supremum)) {
/* Inherit the locks on the supremum of the left page to the
first record which was moved from the right page */
- lock_rec_inherit_to_gap(page_rec_get_next(orig_pred),
- page_get_supremum_rec(left_page));
+ lock_rec_inherit_to_gap(left_next_rec, left_supremum);
/* Reset the locks on the supremum of the left page,
releasing waiting transactions */
- lock_rec_reset_and_release_wait(page_get_supremum_rec(
- left_page));
+ lock_rec_reset_and_release_wait(left_supremum);
}
/* Move the locks from the supremum of right page to the supremum
of the left page */
- lock_rec_move(page_get_supremum_rec(left_page),
- page_get_supremum_rec(right_page));
+ lock_rec_move(left_supremum, page_get_supremum_rec(right_page), comp);
lock_rec_free_all_from_discard_page(right_page);
@@ -2963,7 +3051,7 @@ lock_update_discard(
lock_rec_reset_and_release_wait(rec);
- if (rec == page_get_supremum_rec(page)) {
+ if (page_rec_is_supremum(rec)) {
break;
}
@@ -2992,7 +3080,7 @@ lock_update_insert(
lock_rec_inherit_to_gap_if_gap_lock(rec, page_rec_get_next(rec));
lock_mutex_exit_kernel();
-}
+}
/*****************************************************************
Updates the lock table when a record is removed. */
@@ -3026,17 +3114,16 @@ actual record is being moved. */
void
lock_rec_store_on_page_infimum(
/*===========================*/
+ page_t* page, /* in: page containing the record */
rec_t* rec) /* in: record whose lock state is stored
on the infimum record of the same page; lock
bits are reset on the record */
{
- page_t* page;
-
- page = buf_frame_align(rec);
+ ut_ad(page == buf_frame_align(rec));
lock_mutex_enter_kernel();
- lock_rec_move(page_get_infimum_rec(page), rec);
+ lock_rec_move(page_get_infimum_rec(page), rec, page_is_comp(page));
lock_mutex_exit_kernel();
}
@@ -3053,9 +3140,12 @@ lock_rec_restore_from_page_infimum(
whose infimum stored the lock state; lock bits are
reset on the infimum */
{
+ ulint comp;
lock_mutex_enter_kernel();
-
- lock_rec_move(rec, page_get_infimum_rec(page));
+ comp = page_is_comp(page);
+ ut_ad(!comp == !page_rec_is_comp(rec));
+
+ lock_rec_move(rec, page_get_infimum_rec(page), comp);
lock_mutex_exit_kernel();
}
@@ -3097,7 +3187,7 @@ retry:
mark_trx = UT_LIST_GET_NEXT(trx_list, mark_trx);
}
- ret = lock_deadlock_recursive(trx, trx, lock, &cost);
+ ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
if (ret == LOCK_VICTIM_IS_OTHER) {
/* We chose some other trx as a victim: retry if there still
@@ -3143,9 +3233,12 @@ lock_deadlock_recursive(
trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
- ulint* cost) /* in/out: number of calculation steps thus
+ ulint* cost, /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */
+ uint depth) /* in: recursion depth: if this exceeds
+ LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
+ return LOCK_VICTIM_IS_START */
{
lock_t* lock;
ulint bit_no = ULINT_UNDEFINED;
@@ -3166,7 +3259,8 @@ lock_deadlock_recursive(
*cost = *cost + 1;
- if (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK) {
+ if ((depth > LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK)
+ || (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK)) {
return(LOCK_VICTIM_IS_START);
}
@@ -3214,7 +3308,7 @@ lock_deadlock_recursive(
fputs("\n*** (1) TRANSACTION:\n", ef);
- trx_print(ef, wait_lock->trx);
+ trx_print(ef, wait_lock->trx, 3000);
fputs(
"*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n", ef);
@@ -3227,7 +3321,7 @@ lock_deadlock_recursive(
fputs("*** (2) TRANSACTION:\n", ef);
- trx_print(ef, lock->trx);
+ trx_print(ef, lock->trx, 3000);
fputs("*** (2) HOLDS THE LOCK(S):\n", ef);
@@ -3246,11 +3340,11 @@ lock_deadlock_recursive(
} else {
lock_table_print(ef, start->wait_lock);
}
-
+#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock detected\n", stderr);
}
-
+#endif /* UNIV_DEBUG */
if (ut_dulint_cmp(wait_lock->trx->undo_no,
start->undo_no) >= 0) {
/* Our recursion starting point
@@ -3292,7 +3386,7 @@ lock_deadlock_recursive(
a lock */
ret = lock_deadlock_recursive(start, lock_trx,
- lock_trx->wait_lock, cost);
+ lock_trx->wait_lock, cost, depth + 1);
if (ret != 0) {
return(ret);
@@ -3348,10 +3442,6 @@ lock_table_create(
lock->type_mode = type_mode | LOCK_TABLE;
lock->trx = trx;
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- lock->trx->n_lock_table_exp++;
- }
-
lock->un_member.tab_lock.table = table;
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
@@ -3388,10 +3478,6 @@ lock_table_remove_low(
trx->auto_inc_lock = NULL;
}
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- lock->trx->n_lock_table_exp--;
- }
-
UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock);
UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock);
}
@@ -3522,9 +3608,7 @@ lock_table(
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
- does nothing;
- if LOCK_TABLE_EXP bits are set,
- creates an explicit table lock */
+ does nothing */
dict_table_t* table, /* in: database table in dictionary cache */
ulint mode, /* in: lock mode */
que_thr_t* thr) /* in: query thread */
@@ -3539,7 +3623,7 @@ lock_table(
return(DB_SUCCESS);
}
- ut_a(flags == 0 || flags == LOCK_TABLE_EXP);
+ ut_a(flags == 0);
trx = thr_get_trx(thr);
@@ -3562,7 +3646,7 @@ lock_table(
/* Another trx has a request on the table in an incompatible
mode: this trx may have to wait */
- err = lock_table_enqueue_waiting(mode, table, thr);
+ err = lock_table_enqueue_waiting(mode | flags, table, thr);
lock_mutex_exit_kernel();
@@ -3652,8 +3736,7 @@ lock_table_dequeue(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(lock_get_type(in_lock) == LOCK_TABLE ||
- lock_get_type(in_lock) == LOCK_TABLE_EXP);
+ ut_a(lock_get_type(in_lock) == LOCK_TABLE);
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
@@ -3757,10 +3840,6 @@ lock_release_off_kernel(
}
lock_table_dequeue(lock);
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_a(lock_get_mode(lock) == LOCK_S
- || lock_get_mode(lock) == LOCK_X);
- }
}
if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
@@ -3780,72 +3859,6 @@ lock_release_off_kernel(
mem_heap_empty(trx->lock_heap);
ut_a(trx->auto_inc_lock == NULL);
- ut_a(trx->n_lock_table_exp == 0);
-}
-
-/*************************************************************************
-Releases table locks explicitly requested with LOCK TABLES (indicated by
-lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
-because of these locks. */
-
-void
-lock_release_tables_off_kernel(
-/*===========================*/
- trx_t* trx) /* in: transaction */
-{
- dict_table_t* table;
- ulint count;
- lock_t* lock;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&kernel_mutex));
-#endif /* UNIV_SYNC_DEBUG */
-
- lock = UT_LIST_GET_LAST(trx->trx_locks);
-
- count = 0;
-
- while (lock != NULL) {
-
- count++;
-
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_a(lock_get_mode(lock) == LOCK_S
- || lock_get_mode(lock) == LOCK_X);
- if (trx->insert_undo || trx->update_undo) {
-
- /* The trx may have modified the table.
- We block the use of the MySQL query
- cache for all currently active
- transactions. */
-
- table = lock->un_member.tab_lock.table;
-
- table->query_cache_inv_trx_id =
- trx_sys->max_trx_id;
- }
-
- lock_table_dequeue(lock);
-
- lock = UT_LIST_GET_LAST(trx->trx_locks);
- continue;
- }
-
- if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
- /* Release the kernel mutex for a while, so that we
- do not monopolize it */
-
- lock_mutex_exit_kernel();
-
- lock_mutex_enter_kernel();
-
- count = 0;
- }
-
- lock = UT_LIST_GET_PREV(trx_locks, lock);
- }
-
- ut_a(trx->n_lock_table_exp == 0);
}
/*************************************************************************
@@ -3958,12 +3971,8 @@ lock_table_print(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(lock_get_type(lock) == LOCK_TABLE ||
- lock_get_type(lock) == LOCK_TABLE_EXP);
+ ut_a(lock_get_type(lock) == LOCK_TABLE);
- if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- fputs("EXPLICIT ", file);
- }
fputs("TABLE LOCK table ", file);
ut_print_name(file, lock->trx, lock->un_member.tab_lock.table->name);
fprintf(file, " trx id %lu %lu",
@@ -3999,11 +4008,15 @@ lock_rec_print(
FILE* file, /* in: file where to print */
lock_t* lock) /* in: record type lock */
{
- page_t* page;
- ulint space;
- ulint page_no;
- ulint i;
- mtr_t mtr;
+ page_t* page;
+ ulint space;
+ ulint page_no;
+ ulint i;
+ mtr_t mtr;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -4082,8 +4095,11 @@ lock_rec_print(
fprintf(file, "Record lock, heap no %lu ", (ulong) i);
if (page) {
- rec_print(file,
- page_find_rec_with_heap_no(page, i));
+ rec_t* rec
+ = page_find_rec_with_heap_no(page, i);
+ offsets = rec_get_offsets(rec, lock->index,
+ offsets, ULINT_UNDEFINED, &heap);
+ rec_print_new(file, rec, offsets);
}
putc('\n', file);
@@ -4091,8 +4107,11 @@ lock_rec_print(
}
mtr_commit(&mtr);
-}
-
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+}
+
/*************************************************************************
Calculates the number of record lock structs in the record lock hash table. */
static
@@ -4121,7 +4140,8 @@ lock_get_n_rec_locks(void)
return(n_locks);
}
-
+
+#ifndef UNIV_HOTBACKUP
/*************************************************************************
Prints info of locks for all transactions. */
@@ -4198,7 +4218,7 @@ lock_print_info_all_transactions(
while (trx) {
if (trx->conc_state == TRX_NOT_STARTED) {
fputs("---", file);
- trx_print(file, trx);
+ trx_print(file, trx, 600);
}
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
@@ -4230,7 +4250,7 @@ loop:
if (nth_lock == 0) {
fputs("---", file);
- trx_print(file, trx);
+ trx_print(file, trx, 600);
if (trx->read_view) {
fprintf(file,
@@ -4349,6 +4369,7 @@ lock_table_queue_validate(
while (lock) {
ut_a(((lock->trx)->conc_state == TRX_ACTIVE)
+ || ((lock->trx)->conc_state == TRX_PREPARED)
|| ((lock->trx)->conc_state == TRX_COMMITTED_IN_MEMORY));
if (!lock_get_wait(lock)) {
@@ -4377,21 +4398,25 @@ 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 */
+ dict_index_t* index, /* in: index, or NULL if not known */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
trx_t* impl_trx;
lock_t* lock;
-
+
ut_a(rec);
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
lock_mutex_enter_kernel();
- if (page_rec_is_supremum(rec) || page_rec_is_infimum(rec)) {
+ if (!page_rec_is_user_rec(rec)) {
lock = lock_rec_get_first(rec);
while (lock) {
ut_a(lock->trx->conc_state == TRX_ACTIVE
+ || lock->trx->conc_state == TRX_PREPARED
|| lock->trx->conc_state
== TRX_COMMITTED_IN_MEMORY);
@@ -4415,13 +4440,13 @@ lock_rec_queue_validate(
if (index && (index->type & DICT_CLUSTERED)) {
- impl_trx = lock_clust_rec_some_has_impl(rec, index);
+ impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
LOCK_WAIT, rec, impl_trx)) {
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
- impl_trx));
+ impl_trx));
}
}
@@ -4431,13 +4456,14 @@ lock_rec_queue_validate(
next function call: we have to release lock table mutex
to obey the latching order */
- impl_trx = lock_sec_rec_some_has_impl_off_kernel(rec, index);
+ impl_trx = lock_sec_rec_some_has_impl_off_kernel(
+ rec, index, offsets);
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
LOCK_WAIT, rec, impl_trx)) {
- ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
- impl_trx));
+ ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
+ rec, impl_trx));
}
}
@@ -4445,6 +4471,7 @@ lock_rec_queue_validate(
while (lock) {
ut_a(lock->trx->conc_state == TRX_ACTIVE
+ || lock->trx->conc_state == TRX_PREPARED
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
ut_a(trx_in_trx_list(lock->trx));
@@ -4453,14 +4480,16 @@ lock_rec_queue_validate(
}
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
+
+ ulint mode;
if (lock_get_mode(lock) == LOCK_S) {
- ut_a(!lock_rec_other_has_expl_req(LOCK_X,
- 0, 0, rec, lock->trx));
+ mode = LOCK_X;
} else {
- ut_a(!lock_rec_other_has_expl_req(LOCK_S,
- 0, 0, rec, lock->trx));
+ mode = LOCK_S;
}
+ ut_a(!lock_rec_other_has_expl_req(mode,
+ 0, 0, rec, lock->trx));
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
@@ -4489,10 +4518,14 @@ lock_rec_validate_page(
page_t* page;
lock_t* lock;
rec_t* rec;
- ulint nth_lock = 0;
- ulint nth_bit = 0;
+ ulint nth_lock = 0;
+ ulint nth_bit = 0;
ulint i;
mtr_t mtr;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
@@ -4524,6 +4557,7 @@ loop:
ut_a(trx_in_trx_list(lock->trx));
ut_a(lock->trx->conc_state == TRX_ACTIVE
+ || lock->trx->conc_state == TRX_PREPARED
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
@@ -4532,13 +4566,15 @@ loop:
index = lock->index;
rec = page_find_rec_with_heap_no(page, i);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
fprintf(stderr,
"Validating %lu %lu\n", (ulong) space, (ulong) page_no);
lock_mutex_exit_kernel();
- lock_rec_queue_validate(rec, index);
+ lock_rec_queue_validate(rec, index, offsets);
lock_mutex_enter_kernel();
@@ -4558,6 +4594,9 @@ function_exit:
mtr_commit(&mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(TRUE);
}
@@ -4637,7 +4676,7 @@ lock_validate(void)
return(TRUE);
}
-
+#endif /* !UNIV_HOTBACKUP */
/*============ RECORD LOCK CHECKS FOR ROW OPERATIONS ====================*/
/*************************************************************************
@@ -4730,8 +4769,22 @@ lock_rec_insert_check_and_lock(
page_update_max_trx_id(buf_frame_align(rec),
thr_get_trx(thr)->id);
}
-
- ut_ad(lock_rec_queue_validate(next_rec, index));
+
+#ifdef UNIV_DEBUG
+ {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ const ulint* offsets;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ offsets = rec_get_offsets(next_rec, index, offsets_,
+ ULINT_UNDEFINED, &heap);
+ ut_ad(lock_rec_queue_validate(next_rec, index, offsets));
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ }
+#endif /* UNIV_DEBUG */
return(err);
}
@@ -4745,7 +4798,8 @@ void
lock_rec_convert_impl_to_expl(
/*==========================*/
rec_t* rec, /* in: user record on page */
- dict_index_t* index) /* in: index of record */
+ dict_index_t* index, /* in: index of record */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
trx_t* impl_trx;
@@ -4753,11 +4807,14 @@ lock_rec_convert_impl_to_expl(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(page_rec_is_user_rec(rec));
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
if (index->type & DICT_CLUSTERED) {
- impl_trx = lock_clust_rec_some_has_impl(rec, index);
+ impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
} else {
- impl_trx = lock_sec_rec_some_has_impl_off_kernel(rec, index);
+ impl_trx = lock_sec_rec_some_has_impl_off_kernel(
+ rec, index, offsets);
}
if (impl_trx) {
@@ -4765,7 +4822,7 @@ lock_rec_convert_impl_to_expl(
record, set one for it */
if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
- impl_trx)) {
+ impl_trx)) {
lock_rec_add_to_queue(LOCK_REC | LOCK_X
| LOCK_REC_NOT_GAP, rec, index,
@@ -4791,17 +4848,19 @@ lock_clust_rec_modify_check_and_lock(
does nothing */
rec_t* rec, /* in: record which should be modified */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
-
+
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_ad(index->type & DICT_CLUSTERED);
+
if (flags & BTR_NO_LOCKING_FLAG) {
return(DB_SUCCESS);
}
- ut_ad(index->type & DICT_CLUSTERED);
-
lock_mutex_enter_kernel();
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
@@ -4809,13 +4868,13 @@ lock_clust_rec_modify_check_and_lock(
/* If a transaction has no explicit x-lock set on the record, set one
for it */
- lock_rec_convert_impl_to_expl(rec, index);
+ lock_rec_convert_impl_to_expl(rec, index, offsets);
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
lock_mutex_exit_kernel();
- ut_ad(lock_rec_queue_validate(rec, index));
+ ut_ad(lock_rec_queue_validate(rec, index, offsets));
return(err);
}
@@ -4859,8 +4918,22 @@ lock_sec_rec_modify_check_and_lock(
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
lock_mutex_exit_kernel();
-
- ut_ad(lock_rec_queue_validate(rec, index));
+
+#ifdef UNIV_DEBUG
+ {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ const ulint* offsets;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ offsets = rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap);
+ ut_ad(lock_rec_queue_validate(rec, index, offsets));
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ }
+#endif /* UNIV_DEBUG */
if (err == DB_SUCCESS) {
/* Update the page max trx id field */
@@ -4887,6 +4960,7 @@ lock_sec_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: secondary index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -4898,6 +4972,7 @@ lock_sec_rec_read_check_and_lock(
ut_ad(!(index->type & DICT_CLUSTERED));
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
+ ut_ad(rec_offs_validate(rec, index, offsets));
if (flags & BTR_NO_LOCKING_FLAG) {
@@ -4920,14 +4995,14 @@ lock_sec_rec_read_check_and_lock(
|| recv_recovery_is_on())
&& !page_rec_is_supremum(rec)) {
- lock_rec_convert_impl_to_expl(rec, index);
+ lock_rec_convert_impl_to_expl(rec, index, offsets);
}
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
lock_mutex_exit_kernel();
- ut_ad(lock_rec_queue_validate(rec, index));
+ ut_ad(lock_rec_queue_validate(rec, index, offsets));
return(err);
}
@@ -4951,6 +5026,7 @@ lock_clust_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -4964,6 +5040,8 @@ lock_clust_rec_read_check_and_lock(
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
|| gap_mode == LOCK_REC_NOT_GAP);
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (flags & BTR_NO_LOCKING_FLAG) {
return(DB_SUCCESS);
@@ -4978,14 +5056,57 @@ lock_clust_rec_read_check_and_lock(
if (!page_rec_is_supremum(rec)) {
- lock_rec_convert_impl_to_expl(rec, index);
+ lock_rec_convert_impl_to_expl(rec, index, offsets);
}
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
lock_mutex_exit_kernel();
- ut_ad(lock_rec_queue_validate(rec, index));
-
+ ut_ad(lock_rec_queue_validate(rec, index, offsets));
+
return(err);
}
+/*************************************************************************
+Checks if locks of other transactions prevent an immediate read, or passing
+over by a read cursor, of a clustered index record. If they do, first tests
+if the query thread should anyway be suspended for some reason; if not, then
+puts the transaction and the query thread to the lock wait state and inserts a
+waiting request for a record lock to the lock queue. Sets the requested mode
+lock on the record. This is an alternative version of
+lock_clust_rec_read_check_and_lock() that does not require the parameter
+"offsets". */
+
+ulint
+lock_clust_rec_read_check_and_lock_alt(
+/*===================================*/
+ /* out: DB_SUCCESS, DB_LOCK_WAIT,
+ DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
+ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
+ does nothing */
+ rec_t* rec, /* in: user record or page supremum record
+ which should be read or passed over by a read
+ cursor */
+ dict_index_t* index, /* in: clustered index */
+ ulint mode, /* in: mode of the lock which the read cursor
+ should set on records: LOCK_S or LOCK_X; the
+ latter is possible in SELECT FOR UPDATE */
+ ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
+ LOCK_REC_NOT_GAP */
+ que_thr_t* thr) /* in: query thread */
+{
+ mem_heap_t* tmp_heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ ulint ret;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &tmp_heap);
+ ret = lock_clust_rec_read_check_and_lock(flags, rec, index,
+ offsets, mode, gap_mode, thr);
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
+ return(ret);
+}
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index e08adb013b5..2f76bf450db 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -24,6 +24,32 @@ Created 12/9/1995 Heikki Tuuri
#include "trx0sys.h"
#include "trx0trx.h"
+/*
+General philosophy of InnoDB redo-logs:
+
+1) Every change to a contents of a data page must be done
+through mtr, which in mtr_commit() writes log records
+to the InnoDB redo log.
+
+2) Normally these changes are performed using a mlog_write_ulint()
+or similar function.
+
+3) In some page level operations only a code number of a
+c-function and its parameters are written to the log to
+reduce the size of the log.
+
+ 3a) You should not add parameters to these kind of functions
+ (e.g. trx_undo_header_create(), trx_undo_insert_header_reuse())
+
+ 3b) You should not add such functionality which either change
+ working when compared with the old or are dependent on data
+ outside of the page. These kind of functions should implement
+ self-contained page transformation and it should be unchanged
+ if you don't have very essential reasons to change log
+ semantics or format.
+
+*/
+
/* Current free limit of space 0; protected by the log sys mutex; 0 means
uninitialized */
ulint log_fsp_current_free_limit = 0;
@@ -31,10 +57,11 @@ ulint log_fsp_current_free_limit = 0;
/* Global log system variable */
log_t* log_sys = NULL;
+#ifdef UNIV_DEBUG
ibool log_do_write = TRUE;
ibool log_debug_writes = FALSE;
-
+#endif /* UNIV_DEBUG */
/* These control how often we print warnings if the last checkpoint is too
old */
@@ -190,6 +217,8 @@ loop:
log_buffer_flush_to_disk();
+ srv_log_waits++;
+
ut_ad(++count < 50);
goto loop;
@@ -292,6 +321,8 @@ part_loop:
if (str_len > 0) {
goto part_loop;
}
+
+ srv_log_write_requests++;
}
/****************************************************************
@@ -944,22 +975,24 @@ log_group_check_flush_completion(
#endif /* UNIV_SYNC_DEBUG */
if (!log_sys->one_flushed && group->n_pending_writes == 0) {
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Log flushed first to group %lu\n", (ulong) group->id);
}
-
+#endif /* UNIV_DEBUG */
log_sys->written_to_some_lsn = log_sys->write_lsn;
log_sys->one_flushed = TRUE;
return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
}
+#ifdef UNIV_DEBUG
if (log_debug_writes && (group->n_pending_writes == 0)) {
fprintf(stderr, "Log flushed to group %lu\n", (ulong) group->id);
}
-
+#endif /* UNIV_DEBUG */
return(0);
}
@@ -1036,12 +1069,13 @@ log_io_complete(
fil_flush(group->space_id);
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Checkpoint info written to group %lu\n",
group->id);
}
-
+#endif /* UNIV_DEBUG */
log_io_complete_checkpoint();
return;
@@ -1103,20 +1137,25 @@ log_group_file_header_flush(
dest_offset = nth_file * group->file_size;
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Writing log file header to group %lu file %lu\n",
(ulong) group->id, (ulong) nth_file);
}
-
+#endif /* UNIV_DEBUG */
if (log_do_write) {
log_sys->n_log_ios++;
+ srv_os_log_pending_writes++;
+
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id,
dest_offset / UNIV_PAGE_SIZE,
dest_offset % UNIV_PAGE_SIZE,
OS_FILE_LOG_BLOCK_SIZE,
buf, group);
+
+ srv_os_log_pending_writes--;
}
}
@@ -1181,6 +1220,8 @@ loop:
log_group_file_header_flush(group,
next_offset / group->file_size, start_lsn);
+ srv_os_log_written+= OS_FILE_LOG_BLOCK_SIZE;
+ srv_log_writes++;
}
if ((next_offset % group->file_size) + len > group->file_size) {
@@ -1190,7 +1231,8 @@ loop:
} else {
write_len = len;
}
-
+
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
@@ -1214,7 +1256,7 @@ loop:
+ i * OS_FILE_LOG_BLOCK_SIZE));
}
}
-
+#endif /* UNIV_DEBUG */
/* Calculate the checksums for each log block and write them to
the trailer fields of the log blocks */
@@ -1225,9 +1267,16 @@ loop:
if (log_do_write) {
log_sys->n_log_ios++;
+ srv_os_log_pending_writes++;
+
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id,
next_offset / UNIV_PAGE_SIZE,
next_offset % UNIV_PAGE_SIZE, write_len, buf, group);
+
+ srv_os_log_pending_writes--;
+
+ srv_os_log_written+= write_len;
+ srv_log_writes++;
}
if (write_len < len) {
@@ -1341,6 +1390,7 @@ loop:
return;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Writing log from %lu %lu up to lsn %lu %lu\n",
@@ -1349,7 +1399,7 @@ loop:
(ulong) ut_dulint_get_high(log_sys->lsn),
(ulong) ut_dulint_get_low(log_sys->lsn));
}
-
+#endif /* UNIV_DEBUG */
log_sys->n_pending_writes++;
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -1918,12 +1968,14 @@ log_checkpoint(
log_sys->next_checkpoint_lsn = oldest_lsn;
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr, "Making checkpoint no %lu at lsn %lu %lu\n",
(ulong) ut_dulint_get_low(log_sys->next_checkpoint_no),
(ulong) ut_dulint_get_high(oldest_lsn),
(ulong) ut_dulint_get_low(oldest_lsn));
}
+#endif /* UNIV_DEBUG */
log_groups_write_checkpoint_info();
@@ -1986,8 +2038,6 @@ log_checkpoint_margin(void)
ulint checkpoint_age;
ulint advance;
dulint oldest_lsn;
- dulint new_oldest;
- ibool do_preflush;
ibool sync;
ibool checkpoint_sync;
ibool do_checkpoint;
@@ -1995,7 +2045,6 @@ log_checkpoint_margin(void)
loop:
sync = FALSE;
checkpoint_sync = FALSE;
- do_preflush = FALSE;
do_checkpoint = FALSE;
mutex_enter(&(log->mutex));
@@ -2015,21 +2064,13 @@ loop:
/* A flush is urgent: we have to do a synchronous preflush */
sync = TRUE;
-
advance = 2 * (age - log->max_modified_age_sync);
-
- new_oldest = ut_dulint_add(oldest_lsn, advance);
-
- do_preflush = TRUE;
-
} else if (age > log->max_modified_age_async) {
/* A flush is not urgent: we do an asynchronous preflush */
advance = age - log->max_modified_age_async;
-
- new_oldest = ut_dulint_add(oldest_lsn, advance);
-
- do_preflush = TRUE;
+ } else {
+ advance = 0;
}
checkpoint_age = ut_dulint_minus(log->lsn, log->last_checkpoint_lsn);
@@ -2053,7 +2094,9 @@ loop:
mutex_exit(&(log->mutex));
- if (do_preflush) {
+ if (advance) {
+ dulint new_oldest = ut_dulint_add(oldest_lsn, advance);
+
success = log_preflush_pool_modified_pages(new_oldest, sync);
/* If the flush succeeded, this thread has done its part
@@ -2304,9 +2347,11 @@ loop:
exit(1);
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr, "Created archive file %s\n", name);
}
+#endif /* UNIV_DEBUG */
ret = os_file_close(file_handle);
@@ -2332,7 +2377,8 @@ loop:
len = group->file_size - (next_offset % group->file_size);
}
-
+
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Archiving starting at lsn %lu %lu, len %lu to group %lu\n",
@@ -2340,6 +2386,7 @@ loop:
(ulong) ut_dulint_get_low(start_lsn),
(ulong) len, (ulong) group->id);
}
+#endif /* UNIV_DEBUG */
log_sys->n_pending_archive_ios++;
@@ -2430,11 +2477,13 @@ log_archive_write_complete_groups(void)
trunc_files = n_files - 1;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes && trunc_files) {
fprintf(stderr,
"Complete file(s) archived to group %lu\n",
(ulong) group->id);
}
+#endif /* UNIV_DEBUG */
/* Calculate the archive file space start lsn */
start_lsn = ut_dulint_subtract(log_sys->next_archived_lsn,
@@ -2457,9 +2506,11 @@ log_archive_write_complete_groups(void)
fil_space_truncate_start(group->archive_space_id,
trunc_files * group->file_size);
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fputs("Archiving writes completed\n", stderr);
}
+#endif /* UNIV_DEBUG */
}
/**********************************************************
@@ -2476,9 +2527,11 @@ log_archive_check_completion_low(void)
if (log_sys->n_pending_archive_ios == 0
&& log_sys->archiving_phase == LOG_ARCHIVE_READ) {
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fputs("Archiving read completed\n", stderr);
}
+#endif /* UNIV_DEBUG */
/* Archive buffer has now been read in: start archive writes */
@@ -2622,6 +2675,7 @@ loop:
log_sys->next_archived_lsn = limit_lsn;
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Archiving from lsn %lu %lu to lsn %lu %lu\n",
@@ -2630,6 +2684,7 @@ loop:
(ulong) ut_dulint_get_high(limit_lsn),
(ulong) ut_dulint_get_low(limit_lsn));
}
+#endif /* UNIV_DEBUG */
/* Read the log segment to the archive buffer */
@@ -2732,12 +2787,14 @@ log_archive_close_groups(
group->archived_file_no += 2;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"Incrementing arch file no to %lu in log group %lu\n",
(ulong) group->archived_file_no + 2,
(ulong) group->id);
}
+#endif /* UNIV_DEBUG */
}
}
@@ -3004,7 +3061,10 @@ loop:
mutex_enter(&kernel_mutex);
- /* Check that there are no longer transactions */
+ /* Check that there are no longer transactions. We need this wait even
+ for the 'very fast' shutdown, because the InnoDB layer may have
+ committed or prepared transactions and we don't want to lose them. */
+
if (trx_n_mysql_transactions > 0
|| UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
@@ -3013,6 +3073,21 @@ loop:
goto loop;
}
+ if (srv_fast_shutdown == 2) {
+ /* In this fastest shutdown we do not flush the buffer pool:
+ it is essentially a 'crash' of the InnoDB server.
+ Make sure that the log is all flushed to disk, so that
+ we can recover all committed transactions in a crash
+ recovery.
+ We must not write the lsn stamps to the data files, since at a
+ startup InnoDB deduces from the stamps if the previous
+ shutdown was clean. */
+
+ log_buffer_flush_to_disk();
+ return; /* We SKIP ALL THE REST !! */
+ }
+
+
/* Check that the master thread is suspended */
if (srv_n_threads_active[SRV_MASTER] != 0) {
@@ -3049,24 +3124,13 @@ loop:
log_archive_all();
#endif /* UNIV_LOG_ARCHIVE */
- if (!srv_very_fast_shutdown) {
- /* In a 'very fast' shutdown we do not flush the buffer pool:
- it is essentially a 'crash' of the InnoDB server. */
-
log_make_checkpoint_at(ut_dulint_max, TRUE);
- } else {
- /* Make sure that the log is all flushed to disk, so that
- we can recover all committed transactions in a crash
- recovery */
- log_buffer_flush_to_disk();
- }
mutex_enter(&(log_sys->mutex));
lsn = log_sys->lsn;
- if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0
- && !srv_very_fast_shutdown)
+ if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0)
#ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on
&& ut_dulint_cmp(lsn,
@@ -3115,7 +3179,7 @@ loop:
completely flushed to disk! (We do not call fil_write... if the
'very fast' shutdown is enabled.) */
- if (!srv_very_fast_shutdown && !buf_all_freed()) {
+ if (!buf_all_freed()) {
goto loop;
}
@@ -3138,7 +3202,7 @@ loop:
/* Make some checks that the server really is quiet */
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
- ut_a(srv_very_fast_shutdown || buf_all_freed());
+ ut_a(buf_all_freed());
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) {
@@ -3153,15 +3217,7 @@ loop:
srv_shutdown_lsn = lsn;
- if (!srv_very_fast_shutdown) {
- /* In a 'very fast' shutdown we do not flush the buffer pool:
- it is essentially a 'crash' of the InnoDB server. Then we must
- not write the lsn stamps to the data files, since at a
- startup InnoDB deduces from the stamps if the previous
- shutdown was clean. */
-
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
- }
fil_flush_file_spaces(FIL_TABLESPACE);
@@ -3169,7 +3225,7 @@ loop:
/* Make some checks that the server really is quiet */
ut_a(srv_n_threads_active[SRV_MASTER] == 0);
- ut_a(srv_very_fast_shutdown || buf_all_freed());
+ ut_a(buf_all_freed());
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
}
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index ddb33de6fa6..42e854398ba 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -477,6 +477,7 @@ recv_find_max_checkpoint(
max_no = ut_dulint_zero;
*max_group = NULL;
+ *max_field = 0;
buf = log_sys->checkpoint_buf;
@@ -489,6 +490,7 @@ recv_find_max_checkpoint(
log_group_read_checkpoint_info(group, field);
if (!recv_check_cp_is_consistent(buf)) {
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n",
@@ -498,7 +500,7 @@ recv_find_max_checkpoint(
+ LOG_CHECKPOINT_CHECKSUM_1));
}
-
+#endif /* UNIV_DEBUG */
goto not_consistent;
}
@@ -511,13 +513,15 @@ recv_find_max_checkpoint(
checkpoint_no =
mach_read_from_8(buf + LOG_CHECKPOINT_NO);
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Checkpoint number %lu found in group %lu\n",
(ulong) ut_dulint_get_low(checkpoint_no),
(ulong) group->id);
}
-
+#endif /* UNIV_DEBUG */
+
if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
*max_group = group;
*max_field = field;
@@ -540,7 +544,6 @@ recv_find_max_checkpoint(
"InnoDB: to create the InnoDB data files, but log file creation failed.\n"
"InnoDB: If that is the case, please refer to\n"
"InnoDB: http://dev.mysql.com/doc/mysql/en/Error_creating_InnoDB.html\n");
-
return(DB_ERROR);
}
@@ -756,81 +759,143 @@ recv_parse_or_apply_log_rec_body(
mtr_t* mtr) /* in: mtr or NULL; should be non-NULL if and only if
page is non-NULL */
{
- byte* new_ptr;
-
- if (type <= MLOG_8BYTES) {
- new_ptr = mlog_parse_nbytes(type, ptr, end_ptr, page);
-
- } else if (type == MLOG_REC_INSERT) {
- new_ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr, page,
- mtr);
- } else if (type == MLOG_REC_CLUST_DELETE_MARK) {
- new_ptr = btr_cur_parse_del_mark_set_clust_rec(ptr, end_ptr,
- page);
- } else if (type == MLOG_REC_SEC_DELETE_MARK) {
- new_ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
- page);
- } else if (type == MLOG_REC_UPDATE_IN_PLACE) {
- new_ptr = btr_cur_parse_update_in_place(ptr, end_ptr, page);
-
- } else if ((type == MLOG_LIST_END_DELETE)
- || (type == MLOG_LIST_START_DELETE)) {
- new_ptr = page_parse_delete_rec_list(type, ptr, end_ptr, page,
- mtr);
- } else if (type == MLOG_LIST_END_COPY_CREATED) {
- new_ptr = page_parse_copy_rec_list_to_created_page(ptr,
- end_ptr, page, mtr);
- } else if (type == MLOG_PAGE_REORGANIZE) {
- new_ptr = btr_parse_page_reorganize(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_PAGE_CREATE) {
- new_ptr = page_parse_create(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_UNDO_INSERT) {
- new_ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page);
-
- } else if (type == MLOG_UNDO_ERASE_END) {
- new_ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page,
- mtr);
- } else if (type == MLOG_UNDO_INIT) {
- new_ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_UNDO_HDR_DISCARD) {
- new_ptr = trx_undo_parse_discard_latest(ptr, end_ptr, page,
- mtr);
- } else if ((type == MLOG_UNDO_HDR_CREATE)
- || (type == MLOG_UNDO_HDR_REUSE)) {
- new_ptr = trx_undo_parse_page_header(type, ptr, end_ptr, page,
- mtr);
- } else if (type == MLOG_REC_MIN_MARK) {
- new_ptr = btr_parse_set_min_rec_mark(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_REC_DELETE) {
- new_ptr = page_cur_parse_delete_rec(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_IBUF_BITMAP_INIT) {
- new_ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_INIT_FILE_PAGE) {
- new_ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
-
- } else if (type == MLOG_WRITE_STRING) {
- new_ptr = mlog_parse_string(ptr, end_ptr, page);
-
- } else if (type == MLOG_FILE_CREATE
- || type == MLOG_FILE_RENAME
- || type == MLOG_FILE_DELETE) {
- new_ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
+ dict_index_t* index = NULL;
+
+ switch (type) {
+ case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES:
+ ptr = mlog_parse_nbytes(type, ptr, end_ptr, page);
+ break;
+ case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_INSERT, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
+ ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr,
+ index, page, mtr);
+ }
+ break;
+ case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
+ ptr = btr_cur_parse_del_mark_set_clust_rec(ptr,
+ end_ptr, index, page);
+ }
+ break;
+ case MLOG_COMP_REC_SEC_DELETE_MARK:
+ /* This log record type is obsolete, but we process it for
+ backward compatibility with MySQL 5.0.3 and 5.0.4. */
+ ut_a(!page || page_is_comp(page));
+ ptr = mlog_parse_index(ptr, end_ptr, TRUE, &index);
+ if (!ptr) {
+ break;
+ }
+ /* Fall through */
+ case MLOG_REC_SEC_DELETE_MARK:
+ ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, page);
+ break;
+ case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
+ ptr = btr_cur_parse_update_in_place(ptr, end_ptr,
+ page, index);
+ }
+ break;
+ case MLOG_LIST_END_DELETE: case MLOG_COMP_LIST_END_DELETE:
+ case MLOG_LIST_START_DELETE: case MLOG_COMP_LIST_START_DELETE:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_LIST_END_DELETE
+ || type == MLOG_COMP_LIST_START_DELETE, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
+ ptr = page_parse_delete_rec_list(type, ptr, end_ptr,
+ index, page, mtr);
+ }
+ break;
+ case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
+ ptr = page_parse_copy_rec_list_to_created_page(ptr,
+ end_ptr, index, page, mtr);
+ }
+ break;
+ case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_PAGE_REORGANIZE, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
+ ptr = btr_parse_page_reorganize(ptr, end_ptr, index,
+ page, mtr);
+ }
+ break;
+ case MLOG_PAGE_CREATE: case MLOG_COMP_PAGE_CREATE:
+ ptr = page_parse_create(ptr, end_ptr,
+ type == MLOG_COMP_PAGE_CREATE, page, mtr);
+ break;
+ case MLOG_UNDO_INSERT:
+ ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page);
+ break;
+ case MLOG_UNDO_ERASE_END:
+ ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_UNDO_INIT:
+ ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_UNDO_HDR_DISCARD:
+ ptr = trx_undo_parse_discard_latest(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_UNDO_HDR_CREATE:
+ case MLOG_UNDO_HDR_REUSE:
+ ptr = trx_undo_parse_page_header(type, ptr, end_ptr,
+ page, mtr);
+ break;
+ case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK:
+ ptr = btr_parse_set_min_rec_mark(ptr, end_ptr,
+ type == MLOG_COMP_REC_MIN_MARK, page, mtr);
+ break;
+ case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_DELETE, &index))) {
+ ut_a(!page
+ || (ibool)!!page_is_comp(page)==index->table->comp);
+ ptr = page_cur_parse_delete_rec(ptr, end_ptr,
+ index, page, mtr);
+ }
+ break;
+ case MLOG_IBUF_BITMAP_INIT:
+ ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_INIT_FILE_PAGE:
+ ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
+ break;
+ case MLOG_WRITE_STRING:
+ ptr = mlog_parse_string(ptr, end_ptr, page);
+ break;
+ case MLOG_FILE_CREATE:
+ case MLOG_FILE_RENAME:
+ case MLOG_FILE_DELETE:
+ ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
ULINT_UNDEFINED);
- } else {
- new_ptr = NULL;
-
+ break;
+ default:
+ ptr = NULL;
recv_sys->found_corrupt_log = TRUE;
}
- ut_ad(!page || new_ptr);
+ ut_ad(!page || ptr);
+ if (index) {
+ dict_table_t* table = index->table;
+ mem_heap_free(index->heap);
+ mutex_free(&(table->autoinc_mutex));
+ mem_heap_free(table->heap);
+ }
- return(new_ptr);
+ return(ptr);
}
/*************************************************************************
@@ -1110,6 +1175,7 @@ recv_recover_page(
}
modification_to_page = FALSE;
+ start_lsn = end_lsn = ut_dulint_zero;
recv = UT_LIST_GET_FIRST(recv_addr->rec_list);
@@ -1143,6 +1209,7 @@ recv_recover_page(
start_lsn = recv->start_lsn;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n",
@@ -1150,6 +1217,7 @@ recv_recover_page(
(ulong) recv_addr->space,
(ulong) recv_addr->page_no);
}
+#endif /* UNIV_DEBUG */
recv_parse_or_apply_log_rec_body(recv->type, buf,
buf + recv->len, page, &mtr);
@@ -1394,7 +1462,7 @@ loop:
/* This page is allocated from the buffer pool and used in the function
below */
-page_t* recv_backup_application_page = NULL;
+static page_t* recv_backup_application_page = NULL;
/***********************************************************************
Applies log records in the hash table to a backup. */
@@ -1736,6 +1804,8 @@ recv_parse_log_rec(
{
byte* new_ptr;
+ *body = NULL;
+
if (ptr == end_ptr) {
return(0);
@@ -1758,25 +1828,25 @@ recv_parse_log_rec(
new_ptr = mlog_parse_initial_log_record(ptr, end_ptr, type, space,
page_no);
- if (!new_ptr) {
+ *body = new_ptr;
+
+ if (UNIV_UNLIKELY(!new_ptr)) {
return(0);
}
/* Check that page_no is sensible */
- if (*page_no > 0x8FFFFFFFUL) {
+ if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) {
recv_sys->found_corrupt_log = TRUE;
return(0);
}
- *body = new_ptr;
-
new_ptr = recv_parse_or_apply_log_rec_body(*type, new_ptr, end_ptr,
NULL, NULL);
- if (new_ptr == NULL) {
+ if (UNIV_UNLIKELY(new_ptr == NULL)) {
return(0);
}
@@ -1970,12 +2040,14 @@ loop:
recv_sys->recovered_offset += len;
recv_sys->recovered_lsn = new_recovered_lsn;
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Parsed a single log rec type %lu len %lu space %lu page no %lu\n",
(ulong) type, (ulong) len, (ulong) space,
(ulong) page_no);
}
+#endif /* UNIV_DEBUG */
if (type == MLOG_DUMMY_RECORD) {
/* Do nothing */
@@ -2058,13 +2130,15 @@ loop:
body, ptr + len);
#endif /* UNIV_LOG_REPLICATE */
}
-
+
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Parsed a multi log rec type %lu len %lu space %lu page no %lu\n",
(ulong) type, (ulong) len, (ulong) space,
(ulong) page_no);
}
+#endif /* UNIV_DEBUG */
total_len += len;
n_recs++;
@@ -2471,6 +2545,7 @@ recv_group_scan_log_recs(
start_lsn = end_lsn;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Scanned group %lu up to log sequence number %lu %lu\n",
@@ -2478,6 +2553,7 @@ recv_group_scan_log_recs(
(ulong) ut_dulint_get_high(*group_scanned_lsn),
(ulong) ut_dulint_get_low(*group_scanned_lsn));
}
+#endif /* UNIV_DEBUG */
}
/************************************************************
@@ -2853,11 +2929,8 @@ void
recv_recovery_from_checkpoint_finish(void)
/*======================================*/
{
- /* Rollback the uncommitted transactions which have no user session */
-
- if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
- trx_rollback_or_clean_all_without_sess();
- }
+ int i;
+ os_thread_id_t recovery_thread_id;
/* Apply the hashed log records to the respective file pages */
@@ -2866,10 +2939,12 @@ recv_recovery_from_checkpoint_finish(void)
recv_apply_hashed_log_recs(TRUE);
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Log records applied to the database\n");
}
+#endif /* UNIV_DEBUG */
if (recv_needed_recovery) {
trx_sys_print_mysql_master_log_pos();
@@ -2890,9 +2965,17 @@ recv_recovery_from_checkpoint_finish(void)
/* Free the resources of the recovery system */
recv_recovery_on = FALSE;
+
#ifndef UNIV_LOG_DEBUG
recv_sys_free();
#endif
+ if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
+ /* Rollback the uncommitted transactions which have no user
+ session */
+
+ os_thread_create(trx_rollback_or_clean_all_without_sess,
+ (void *)&i, &recovery_thread_id);
+ }
}
/**********************************************************
@@ -3198,6 +3281,7 @@ ask_again:
break;
}
+#ifdef UNIV_DEBUG
if (log_debug_writes) {
fprintf(stderr,
"InnoDB: Archive read starting at lsn %lu %lu, len %lu from file %s\n",
@@ -3205,6 +3289,7 @@ ask_again:
(ulong) ut_dulint_get_low(start_lsn),
(ulong) len, name);
}
+#endif /* UNIV_DEBUG */
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE,
group->archive_space_id, read_offset / UNIV_PAGE_SIZE,
diff --git a/innobase/mtr/mtr0log.c b/innobase/mtr/mtr0log.c
index 82baa8905ba..0308619073a 100644
--- a/innobase/mtr/mtr0log.c
+++ b/innobase/mtr/mtr0log.c
@@ -15,6 +15,7 @@ Created 12/7/1995 Heikki Tuuri
#include "buf0buf.h"
#include "dict0boot.h"
#include "log0recv.h"
+#include "page0page.h"
/************************************************************
Catenates n bytes to the mtr log. */
@@ -22,9 +23,9 @@ Catenates n bytes to the mtr log. */
void
mlog_catenate_string(
/*=================*/
- mtr_t* mtr, /* in: mtr */
- byte* str, /* in: string to write */
- ulint len) /* in: string length */
+ mtr_t* mtr, /* in: mtr */
+ const byte* str, /* in: string to write */
+ ulint len) /* in: string length */
{
dyn_array_t* mlog;
@@ -301,14 +302,15 @@ corresponding log record to the mini-transaction log. */
void
mlog_write_string(
/*==============*/
- byte* ptr, /* in: pointer where to write */
- byte* str, /* in: string to write */
- ulint len, /* in: string length */
- mtr_t* mtr) /* in: mini-transaction handle */
+ byte* ptr, /* in: pointer where to write */
+ const byte* str, /* in: string to write */
+ ulint len, /* in: string length */
+ mtr_t* mtr) /* in: mini-transaction handle */
{
byte* log_ptr;
- if (ptr < buf_pool->frame_zero || ptr >= buf_pool->high_end) {
+ if (UNIV_UNLIKELY(ptr < buf_pool->frame_zero)
+ || UNIV_UNLIKELY(ptr >= buf_pool->high_end)) {
fprintf(stderr,
"InnoDB: Error: trying to write to a stray memory location %p\n", ptr);
ut_error;
@@ -384,3 +386,165 @@ mlog_parse_string(
return(ptr + len);
}
+
+/************************************************************
+Opens a buffer for mlog, writes the initial log record and,
+if needed, the field lengths of an index. */
+
+byte*
+mlog_open_and_write_index(
+/*======================*/
+ /* out: buffer, NULL if log mode
+ MTR_LOG_NONE */
+ mtr_t* mtr, /* in: mtr */
+ byte* rec, /* in: index record or page */
+ dict_index_t* index, /* in: record descriptor */
+ byte type, /* in: log item type */
+ ulint size) /* in: requested buffer size in bytes
+ (if 0, calls mlog_close() and returns NULL) */
+{
+ byte* log_ptr;
+ const byte* log_start;
+ const byte* log_end;
+
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
+
+ if (!page_rec_is_comp(rec)) {
+ log_start = log_ptr = mlog_open(mtr, 11 + size);
+ if (!log_ptr) {
+ return(NULL); /* logging is disabled */
+ }
+ log_ptr = mlog_write_initial_log_record_fast(rec, type,
+ log_ptr, mtr);
+ log_end = log_ptr + 11 + size;
+ } else {
+ ulint i;
+ ulint n = dict_index_get_n_fields(index);
+ /* total size needed */
+ ulint total = 11 + size + (n + 2) * 2;
+ ulint alloc = total;
+ /* allocate at most DYN_ARRAY_DATA_SIZE at a time */
+ if (alloc > DYN_ARRAY_DATA_SIZE) {
+ alloc = DYN_ARRAY_DATA_SIZE;
+ }
+ log_start = log_ptr = mlog_open(mtr, alloc);
+ if (!log_ptr) {
+ return(NULL); /* logging is disabled */
+ }
+ log_end = log_ptr + alloc;
+ log_ptr = mlog_write_initial_log_record_fast(rec, type,
+ log_ptr, mtr);
+ mach_write_to_2(log_ptr, n);
+ log_ptr += 2;
+ mach_write_to_2(log_ptr,
+ dict_index_get_n_unique_in_tree(index));
+ log_ptr += 2;
+ for (i = 0; i < n; i++) {
+ dict_field_t* field;
+ dtype_t* type;
+ ulint len;
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ len = field->fixed_len;
+ ut_ad(len < 0x7fff);
+ if (len == 0 && (dtype_get_len(type) > 255
+ || dtype_get_mtype(type) == DATA_BLOB)) {
+ /* variable-length field
+ with maximum length > 255 */
+ len = 0x7fff;
+ }
+ if (dtype_get_prtype(type) & DATA_NOT_NULL) {
+ len |= 0x8000;
+ }
+ if (log_ptr + 2 > log_end) {
+ mlog_close(mtr, log_ptr);
+ ut_a(total > (ulint) (log_ptr - log_start));
+ total -= log_ptr - log_start;
+ alloc = total;
+ if (alloc > DYN_ARRAY_DATA_SIZE) {
+ alloc = DYN_ARRAY_DATA_SIZE;
+ }
+ log_start = log_ptr = mlog_open(mtr, alloc);
+ if (!log_ptr) {
+ return(NULL); /* logging is disabled */
+ }
+ log_end = log_ptr + alloc;
+ }
+ mach_write_to_2(log_ptr, len);
+ log_ptr += 2;
+ }
+ }
+ if (size == 0) {
+ mlog_close(mtr, log_ptr);
+ log_ptr = NULL;
+ } else if (log_ptr + size > log_end) {
+ mlog_close(mtr, log_ptr);
+ log_ptr = mlog_open(mtr, size);
+ }
+ return(log_ptr);
+}
+
+/************************************************************
+Parses a log record written by mlog_open_and_write_index. */
+
+byte*
+mlog_parse_index(
+/*=============*/
+ /* out: parsed record end,
+ NULL if not a complete record */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ /* out: new value of log_ptr */
+ ibool comp, /* in: TRUE=compact record format */
+ dict_index_t** index) /* out, own: dummy index */
+{
+ ulint i, n, n_uniq;
+ dict_table_t* table;
+ dict_index_t* ind;
+
+ ut_ad(comp == FALSE || comp == TRUE);
+
+ if (comp) {
+ if (end_ptr < ptr + 4) {
+ return(NULL);
+ }
+ n = mach_read_from_2(ptr);
+ ptr += 2;
+ n_uniq = mach_read_from_2(ptr);
+ ut_ad(n_uniq <= n);
+ if (end_ptr < ptr + (n + 1) * 2) {
+ return(NULL);
+ }
+ } else {
+ n = n_uniq = 1;
+ }
+ table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, comp);
+ ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY",
+ DICT_HDR_SPACE, 0, n);
+ ind->table = table;
+ ind->n_uniq = n_uniq;
+ if (n_uniq != n) {
+ ind->type = DICT_CLUSTERED;
+ }
+ /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
+ ind->cached = TRUE;
+ if (comp) {
+ for (i = 0; i < n; i++) {
+ ulint len = mach_read_from_2(ptr += 2);
+ /* The high-order bit of len is the NOT NULL flag;
+ the rest is 0 or 0x7fff for variable-length fields,
+ and 1..0x7ffe for fixed-length fields. */
+ dict_mem_table_add_col(table, "DUMMY",
+ ((len + 1) & 0x7fff) <= 1
+ ? DATA_BINARY
+ : DATA_FIXBINARY,
+ len & 0x8000 ? DATA_NOT_NULL : 0,
+ len & 0x7fff, 0);
+ dict_index_add_col(ind,
+ dict_table_get_nth_col(table, i), 0, 0);
+ }
+ ptr += 2;
+ }
+ *index = ind;
+ return(ptr);
+}
diff --git a/innobase/mtr/mtr0mtr.c b/innobase/mtr/mtr0mtr.c
index 6e918806eb1..da045be1f62 100644
--- a/innobase/mtr/mtr0mtr.c
+++ b/innobase/mtr/mtr0mtr.c
@@ -48,16 +48,11 @@ mtr_memo_slot_release(
object = slot->object;
type = slot->type;
- if (object != NULL) {
+ if (UNIV_LIKELY(object != NULL)) {
if (type <= MTR_MEMO_BUF_FIX) {
buf_page_release((buf_block_t*)object, type, mtr);
} else if (type == MTR_MEMO_S_LOCK) {
rw_lock_s_unlock((rw_lock_t*)object);
-#ifndef UNIV_DEBUG
- } else {
- rw_lock_x_unlock((rw_lock_t*)object);
- }
-#endif
#ifdef UNIV_DEBUG
} else if (type == MTR_MEMO_X_LOCK) {
rw_lock_x_unlock((rw_lock_t*)object);
@@ -65,8 +60,11 @@ mtr_memo_slot_release(
ut_ad(type == MTR_MEMO_MODIFY);
ut_ad(mtr_memo_contains(mtr, object,
MTR_MEMO_PAGE_X_FIX));
- }
+#else
+ } else {
+ rw_lock_x_unlock((rw_lock_t*)object);
#endif
+ }
}
slot->object = NULL;
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 49f88c0d62a..9c87b59f018 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -15,6 +15,13 @@ Created 10/21/1995 Heikki Tuuri
#include "fil0fil.h"
#include "buf0buf.h"
+#if defined(UNIV_HOTBACKUP) && defined(__WIN__)
+/* Add includes for the _stat() call to compile on Windows */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#endif /* UNIV_HOTBACKUP */
+
#undef HAVE_FDATASYNC
#ifdef POSIX_ASYNC_IO
@@ -80,7 +87,7 @@ struct os_aio_slot_struct{
made and only the slot message
needs to be passed to the caller
of os_aio_simulated_handle */
- void* message1; /* message which is given by the */
+ fil_node_t* message1; /* message which is given by the */
void* message2; /* the requester of an aio operation
and which can be used to identify
which pending aio operation was
@@ -130,17 +137,17 @@ os_event_t* os_aio_segment_wait_events = NULL;
/* The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
are NULL when the module has not yet been initialized. */
-os_aio_array_t* os_aio_read_array = NULL;
-os_aio_array_t* os_aio_write_array = NULL;
-os_aio_array_t* os_aio_ibuf_array = NULL;
-os_aio_array_t* os_aio_log_array = NULL;
-os_aio_array_t* os_aio_sync_array = NULL;
+static os_aio_array_t* os_aio_read_array = NULL;
+static os_aio_array_t* os_aio_write_array = NULL;
+static os_aio_array_t* os_aio_ibuf_array = NULL;
+static os_aio_array_t* os_aio_log_array = NULL;
+static os_aio_array_t* os_aio_sync_array = NULL;
-ulint os_aio_n_segments = ULINT_UNDEFINED;
+static ulint os_aio_n_segments = ULINT_UNDEFINED;
/* If the following is TRUE, read i/o handler threads try to
wait until a batch of new read requests have been posted */
-ibool os_aio_recommend_sleep_for_read_threads = FALSE;
+static ibool os_aio_recommend_sleep_for_read_threads = FALSE;
ulint os_n_file_reads = 0;
ulint os_bytes_read_since_printout = 0;
@@ -155,10 +162,14 @@ ibool os_has_said_disk_full = FALSE;
/* The mutex protecting the following counts of pending pread and pwrite
operations */
-os_mutex_t os_file_count_mutex;
+static os_mutex_t os_file_count_mutex;
ulint os_file_n_pending_preads = 0;
ulint os_file_n_pending_pwrites = 0;
+/* These are not protected by any mutex */
+ulint os_n_pending_writes = 0;
+ulint os_n_pending_reads = 0;
+
/***************************************************************************
Gets the operating system version. Currently works only on Windows. */
@@ -598,7 +609,7 @@ os_file_opendir(
lpFindFileData = ut_malloc(sizeof(WIN32_FIND_DATA));
- dir = FindFirstFile(path, lpFindFileData);
+ dir = FindFirstFile((LPCTSTR) path, lpFindFileData);
ut_free(lpFindFileData);
@@ -679,15 +690,15 @@ next_file:
ret = FindNextFile(dir, lpFindFileData);
if (ret) {
- ut_a(strlen(lpFindFileData->cFileName) < OS_FILE_MAX_PATH);
+ ut_a(strlen((char *) lpFindFileData->cFileName) < OS_FILE_MAX_PATH);
- if (strcmp(lpFindFileData->cFileName, ".") == 0
- || strcmp(lpFindFileData->cFileName, "..") == 0) {
+ if (strcmp((char *) lpFindFileData->cFileName, ".") == 0
+ || strcmp((char *) lpFindFileData->cFileName, "..") == 0) {
goto next_file;
}
- strcpy(info->name, lpFindFileData->cFileName);
+ strcpy(info->name, (char *) lpFindFileData->cFileName);
info->size = (ib_longlong)(lpFindFileData->nFileSizeLow)
+ (((ib_longlong)(lpFindFileData->nFileSizeHigh)) << 32);
@@ -823,7 +834,7 @@ os_file_create_directory(
#ifdef __WIN__
BOOL rcode;
- rcode = CreateDirectory(pathname, NULL);
+ rcode = CreateDirectory((LPCTSTR) pathname, NULL);
if (!(rcode != 0 ||
(GetLastError() == ERROR_ALREADY_EXISTS && !fail_if_exists))) {
/* failure */
@@ -907,7 +918,7 @@ try_again:
ut_error;
}
- file = CreateFile(name,
+ file = CreateFile((LPCTSTR) name,
access,
FILE_SHARE_READ | FILE_SHARE_WRITE,
/* file can be read ansd written also
@@ -1046,7 +1057,7 @@ os_file_create_simple_no_error_handling(
ut_error;
}
- file = CreateFile(name,
+ file = CreateFile((LPCTSTR) name,
access,
share_mode,
NULL, /* default security attributes */
@@ -1193,7 +1204,7 @@ try_again:
ut_error;
}
- file = CreateFile(name,
+ file = CreateFile((LPCTSTR) name,
GENERIC_READ | GENERIC_WRITE, /* read and write
access */
share_mode, /* File can be read also by other
@@ -2085,8 +2096,12 @@ try_again:
goto error_handling;
}
+ os_n_pending_reads++;
+
ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
+ os_n_pending_reads--;
+
os_mutex_exit(os_file_seek_mutexes[i]);
if (ret && len == n) {
@@ -2099,8 +2114,12 @@ try_again:
os_bytes_read_since_printout += n;
try_again:
+ os_n_pending_reads++;
+
ret = os_file_pread(file, buf, n, offset, offset_high);
+ os_n_pending_reads--;
+
if ((ulint)ret == n) {
return(TRUE);
@@ -2188,8 +2207,12 @@ try_again:
goto error_handling;
}
+ os_n_pending_reads++;
+
ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
+ os_n_pending_reads--;
+
os_mutex_exit(os_file_seek_mutexes[i]);
if (ret && len == n) {
@@ -2202,8 +2225,12 @@ try_again:
os_bytes_read_since_printout += n;
try_again:
+ os_n_pending_reads++;
+
ret = os_file_pread(file, buf, n, offset, offset_high);
+ os_n_pending_reads--;
+
if ((ulint)ret == n) {
return(TRUE);
@@ -2285,7 +2312,11 @@ retry:
return(FALSE);
}
+ os_n_pending_writes++;
+
ret = WriteFile(file, buf, (DWORD) n, &len, NULL);
+
+ os_n_pending_writes--;
/* Always do fsync to reduce the probability that when the OS crashes,
a database page is only partially physically written to disk. */
@@ -2348,8 +2379,12 @@ retry:
#else
ssize_t ret;
+ os_n_pending_writes++;
+
ret = os_file_pwrite(file, buf, n, offset, offset_high);
+ os_n_pending_writes--;
+
if ((ulint)ret == n) {
return(TRUE);
@@ -2999,7 +3034,7 @@ os_aio_array_reserve_slot(
/* out: pointer to slot */
ulint type, /* in: OS_FILE_READ or OS_FILE_WRITE */
os_aio_array_t* array, /* in: aio array */
- void* message1,/* in: message to be passed along with
+ fil_node_t* message1,/* in: message to be passed along with
the aio operation */
void* message2,/* in: message to be passed along with
the aio operation */
@@ -3261,7 +3296,7 @@ os_aio(
ulint offset_high, /* in: most significant 32 bits of
offset */
ulint n, /* in: number of bytes to read or write */
- void* message1,/* in: messages for the aio handler (these
+ fil_node_t* message1,/* in: messages for the aio handler (these
can be used to identify a completed aio
operation); if mode is OS_AIO_SYNC, these
are ignored */
@@ -3273,7 +3308,7 @@ os_aio(
ibool retval;
BOOL ret = TRUE;
DWORD len = (DWORD) n;
- void* dummy_mess1;
+ struct fil_node_struct * dummy_mess1;
void* dummy_mess2;
ulint dummy_type;
#endif
@@ -3446,7 +3481,7 @@ os_aio_windows_handle(
ignored */
ulint pos, /* this parameter is used only in sync aio:
wait for the aio slot at this position */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -3539,7 +3574,7 @@ os_aio_posix_handle(
/*================*/
/* out: TRUE if the aio operation succeeded */
ulint array_no, /* in: array number 0 - 3 */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -3622,7 +3657,7 @@ os_aio_simulated_handle(
i/o thread, segment 1 the log i/o thread,
then follow the non-ibuf read threads, and as
the last are the non-ibuf write threads */
- void** message1, /* out: the messages passed with the aio
+ fil_node_t**message1, /* out: the messages passed with the aio
request; note that also in the case where
the aio operation failed, these output
parameters are valid and can be used to
@@ -4160,6 +4195,7 @@ os_aio_refresh_stats(void)
os_last_printout = time(NULL);
}
+#ifdef UNIV_DEBUG
/**************************************************************************
Checks that all slots in the system have been freed, that is, there are
no pending io operations. */
@@ -4219,3 +4255,4 @@ os_aio_all_slots_free(void)
return(FALSE);
}
+#endif /* UNIV_DEBUG */
diff --git a/innobase/os/os0proc.c b/innobase/os/os0proc.c
index 2f155788420..167aed93de7 100644
--- a/innobase/os/os0proc.c
+++ b/innobase/os/os0proc.c
@@ -69,6 +69,10 @@ byte* os_awe_window;
ulint os_awe_window_size;
#endif
+ibool os_use_large_pages;
+/* Large page size. This may be a boot-time option on some platforms */
+ulint os_large_page_size;
+
/********************************************************************
Windows AWE support. Tries to enable the "lock pages in memory" privilege for
the current process so that the current process can allocate memory-locked
@@ -516,6 +520,89 @@ os_mem_alloc_nocache(
}
/********************************************************************
+Allocates large pages memory. */
+
+void*
+os_mem_alloc_large(
+/*=================*/
+ /* out: allocated memory */
+ ulint n, /* in: number of bytes */
+ ibool set_to_zero, /* in: TRUE if allocated memory should be set
+ to zero if UNIV_SET_MEM_TO_ZERO is defined */
+ ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory
+ cannot be allocated */
+{
+#ifdef HAVE_LARGE_PAGES
+ ulint size;
+ int shmid;
+ void *ptr = NULL;
+ struct shmid_ds buf;
+
+ if (!os_use_large_pages || !os_large_page_size) {
+ goto skip;
+ }
+
+#ifdef UNIV_LINUX
+ /* Align block size to os_large_page_size */
+ size = ((n - 1) & ~(os_large_page_size - 1)) + os_large_page_size;
+
+ shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
+ if (shmid < 0) {
+ fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. "
+ "errno %d\n", n, errno);
+ } else {
+ ptr = shmat(shmid, NULL, 0);
+ if (ptr == (void *)-1) {
+ fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to attach shared memory "
+ "segment, errno %d\n", errno);
+ }
+ /*
+ Remove the shared memory segment so that it will be automatically freed
+ after memory is detached or process exits
+ */
+ shmctl(shmid, IPC_RMID, &buf);
+ }
+#endif
+
+ if (ptr) {
+ if (set_to_zero) {
+#ifdef UNIV_SET_MEM_TO_ZERO
+ memset(ptr, '\0', size);
+#endif
+ }
+
+ return(ptr);
+ }
+
+ fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional memory pool\n");
+skip:
+#endif /* HAVE_LARGE_PAGES */
+
+ return(ut_malloc_low(n, set_to_zero, assert_on_error));
+}
+
+/********************************************************************
+Frees large pages memory. */
+
+void
+os_mem_free_large(
+/*=================*/
+ void *ptr) /* in: number of bytes */
+{
+#ifdef HAVE_LARGE_PAGES
+ if (os_use_large_pages && os_large_page_size
+#ifdef UNIV_LINUX
+ && !shmdt(ptr)
+#endif
+ ) {
+ return;
+ }
+#endif
+
+ ut_free(ptr);
+}
+
+/********************************************************************
Sets the priority boost for threads released from waiting within the current
process. */
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index 18d92af5054..356d7c8c163 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -121,7 +121,7 @@ os_event_create(
event->handle = CreateEvent(NULL,/* No security attributes */
TRUE, /* Manual reset */
FALSE, /* Initial state nonsignaled */
- name);
+ (LPCTSTR) name);
if (!event->handle) {
fprintf(stderr,
"InnoDB: Could not create a Windows event semaphore; Windows error %lu\n",
@@ -177,7 +177,7 @@ os_event_create_auto(
event->handle = CreateEvent(NULL,/* No security attributes */
FALSE, /* Auto-reset */
FALSE, /* Initial state nonsignaled */
- name);
+ (LPCTSTR) name);
if (!event->handle) {
fprintf(stderr,
@@ -440,7 +440,7 @@ os_mutex_create(
mutex = CreateMutex(NULL, /* No security attributes */
FALSE, /* Initial state: no owner */
- name);
+ (LPCTSTR) name);
ut_a(mutex);
#else
os_fast_mutex_t* mutex;
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index 0278e3b2b66..847d0ee1cc7 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -88,7 +88,7 @@ os_thread_create(
/*=============*/
/* out: handle to the thread */
#ifndef __WIN__
- os_posix_f_t start_f,
+ os_posix_f_t start_f,
#else
ulint (*start_f)(void*), /* in: pointer to function
from which to start */
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 459ab986610..d0b89e81787 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -29,7 +29,9 @@ UNIV_INLINE
ibool
page_cur_try_search_shortcut(
/*=========================*/
+ /* out: TRUE on success */
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint* iup_matched_fields,
/* in/out: already matched fields in upper
@@ -45,7 +47,6 @@ page_cur_try_search_shortcut(
not yet completely matched */
page_cur_t* cursor) /* out: page cursor */
{
- int cmp;
rec_t* rec;
rec_t* next_rec;
ulint low_match;
@@ -55,9 +56,17 @@ page_cur_try_search_shortcut(
#ifdef UNIV_SEARCH_DEBUG
page_cur_t cursor2;
#endif
+ ibool success = FALSE;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_ad(dtuple_check_typed(tuple));
rec = page_header_get_ptr(page, PAGE_LAST_INSERT);
+ offsets = rec_get_offsets(rec, index, offsets,
+ dtuple_get_n_fields(tuple), &heap);
ut_ad(rec);
ut_ad(page_rec_is_user_rec(rec));
@@ -69,26 +78,24 @@ page_cur_try_search_shortcut(
up_match = low_match;
up_bytes = low_bytes;
- cmp = page_cmp_dtuple_rec_with_match(tuple, rec, &low_match,
- &low_bytes);
- if (cmp == -1) {
-
- return(FALSE);
+ if (page_cmp_dtuple_rec_with_match(tuple, rec, offsets,
+ &low_match, &low_bytes) < 0) {
+ goto exit_func;
}
next_rec = page_rec_get_next(rec);
+ offsets = rec_get_offsets(next_rec, index, offsets,
+ dtuple_get_n_fields(tuple), &heap);
- cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, &up_match,
- &up_bytes);
- if (cmp != -1) {
-
- return(FALSE);
+ if (page_cmp_dtuple_rec_with_match(tuple, next_rec, offsets,
+ &up_match, &up_bytes) >= 0) {
+ goto exit_func;
}
cursor->rec = rec;
#ifdef UNIV_SEARCH_DEBUG
- page_cur_search_with_match(page, tuple, PAGE_CUR_DBG,
+ page_cur_search_with_match(page, index, tuple, PAGE_CUR_DBG,
iup_matched_fields,
iup_matched_bytes,
ilow_matched_fields,
@@ -105,7 +112,7 @@ page_cur_try_search_shortcut(
ut_a(*ilow_matched_fields == low_match);
ut_a(*ilow_matched_bytes == low_bytes);
#endif
- if (next_rec != page_get_supremum_rec(page)) {
+ if (!page_rec_is_supremum(next_rec)) {
*iup_matched_fields = up_match;
*iup_matched_bytes = up_bytes;
@@ -117,11 +124,17 @@ page_cur_try_search_shortcut(
#ifdef UNIV_SEARCH_PERF_STAT
page_cur_short_succ++;
#endif
- return(TRUE);
+ success = TRUE;
+exit_func:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(success);
}
#endif
+#ifdef PAGE_CUR_LE_OR_EXTENDS
/********************************************************************
Checks if the nth field in a record is a character type field which extends
the nth field in tuple, i.e., the field is longer or equal in length and has
@@ -130,22 +143,24 @@ static
ibool
page_cur_rec_field_extends(
/*=======================*/
- /* out: TRUE if rec field extends tuple
- field */
- dtuple_t* tuple, /* in: data tuple */
- rec_t* rec, /* in: record */
- ulint n) /* in: compare nth field */
+ /* out: TRUE if rec field
+ extends tuple field */
+ dtuple_t* tuple, /* in: data tuple */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: compare nth field */
{
dtype_t* type;
dfield_t* dfield;
byte* rec_f;
ulint rec_f_len;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
dfield = dtuple_get_nth_field(tuple, n);
type = dfield_get_type(dfield);
- rec_f = rec_get_nth_field(rec, n, &rec_f_len);
+ rec_f = rec_get_nth_field(rec, offsets, n, &rec_f_len);
if (type->mtype == DATA_VARCHAR
|| type->mtype == DATA_CHAR
@@ -168,6 +183,7 @@ page_cur_rec_field_extends(
return(FALSE);
}
+#endif /* PAGE_CUR_LE_OR_EXTENDS */
/********************************************************************
Searches the right position for a page cursor. */
@@ -176,6 +192,7 @@ void
page_cur_search_with_match(
/*=======================*/
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -212,14 +229,26 @@ page_cur_search_with_match(
ulint dbg_matched_fields;
ulint dbg_matched_bytes;
#endif
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_ad(page && tuple && iup_matched_fields && iup_matched_bytes
&& ilow_matched_fields && ilow_matched_bytes && cursor);
ut_ad(dtuple_validate(tuple));
ut_ad(dtuple_check_typed(tuple));
+#ifdef UNIV_DEBUG
+# ifdef PAGE_CUR_DBG
+ if (mode != PAGE_CUR_DBG)
+# endif /* PAGE_CUR_DBG */
+# ifdef PAGE_CUR_LE_OR_EXTENDS
+ if (mode != PAGE_CUR_LE_OR_EXTENDS)
+# endif /* PAGE_CUR_LE_OR_EXTENDS */
ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE)
- || (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)
- || (mode == PAGE_CUR_LE_OR_EXTENDS) || (mode == PAGE_CUR_DBG));
-
+ || (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE));
+#endif /* UNIV_DEBUG */
+
page_check_dir(page);
#ifdef PAGE_CUR_ADAPT
@@ -229,7 +258,7 @@ page_cur_search_with_match(
&& (page_header_get_ptr(page, PAGE_LAST_INSERT))
&& (page_header_get_field(page, PAGE_DIRECTION) == PAGE_RIGHT)) {
- if (page_cur_try_search_shortcut(page, tuple,
+ if (page_cur_try_search_shortcut(page, index, tuple,
iup_matched_fields,
iup_matched_bytes,
ilow_matched_fields,
@@ -238,16 +267,18 @@ page_cur_search_with_match(
return;
}
}
-/*#ifdef UNIV_SEARCH_DEBUG */
+# ifdef PAGE_CUR_DBG
if (mode == PAGE_CUR_DBG) {
mode = PAGE_CUR_LE;
}
-/*#endif */
+# endif
#endif
/* The following flag does not work for non-latin1 char sets because
cmp_full_field does not tell how many bytes matched */
+#ifdef PAGE_CUR_LE_OR_EXTENDS
ut_a(mode != PAGE_CUR_LE_OR_EXTENDS);
+#endif /* PAGE_CUR_LE_OR_EXTENDS */
/* If mode PAGE_CUR_G is specified, we are trying to position the
cursor to answer a query of the form "tuple < X", where tuple is
@@ -279,37 +310,42 @@ page_cur_search_with_match(
low_matched_fields, low_matched_bytes,
up_matched_fields, up_matched_bytes);
- cmp = cmp_dtuple_rec_with_match(tuple, mid_rec,
+ offsets = rec_get_offsets(mid_rec, index, offsets,
+ dtuple_get_n_fields_cmp(tuple), &heap);
+
+ cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
&cur_matched_fields,
&cur_matched_bytes);
- if (cmp == 1) {
+ if (UNIV_LIKELY(cmp > 0)) {
+low_slot_match:
low = mid;
low_matched_fields = cur_matched_fields;
low_matched_bytes = cur_matched_bytes;
- } else if (cmp == -1) {
-
+ } else if (UNIV_LIKELY(cmp /* == -1 */)) {
+#ifdef PAGE_CUR_LE_OR_EXTENDS
if (mode == PAGE_CUR_LE_OR_EXTENDS
&& page_cur_rec_field_extends(tuple, mid_rec,
- cur_matched_fields)) {
- low = mid;
- low_matched_fields = cur_matched_fields;
- low_matched_bytes = cur_matched_bytes;
- } else {
- up = mid;
- up_matched_fields = cur_matched_fields;
- up_matched_bytes = cur_matched_bytes;
- }
+ offsets, cur_matched_fields)) {
- } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
- || mode == PAGE_CUR_LE_OR_EXTENDS) {
- low = mid;
- low_matched_fields = cur_matched_fields;
- low_matched_bytes = cur_matched_bytes;
- } else {
+ goto low_slot_match;
+ }
+#endif /* PAGE_CUR_LE_OR_EXTENDS */
+up_slot_match:
up = mid;
up_matched_fields = cur_matched_fields;
up_matched_bytes = cur_matched_bytes;
+
+ } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
+#ifdef PAGE_CUR_LE_OR_EXTENDS
+ || mode == PAGE_CUR_LE_OR_EXTENDS
+#endif /* PAGE_CUR_LE_OR_EXTENDS */
+ ) {
+
+ goto low_slot_match;
+ } else {
+
+ goto up_slot_match;
}
}
@@ -329,35 +365,41 @@ page_cur_search_with_match(
low_matched_fields, low_matched_bytes,
up_matched_fields, up_matched_bytes);
- cmp = cmp_dtuple_rec_with_match(tuple, mid_rec,
+ offsets = rec_get_offsets(mid_rec, index, offsets,
+ dtuple_get_n_fields_cmp(tuple), &heap);
+
+ cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
&cur_matched_fields,
&cur_matched_bytes);
- if (cmp == 1) {
+ if (UNIV_LIKELY(cmp > 0)) {
+low_rec_match:
low_rec = mid_rec;
low_matched_fields = cur_matched_fields;
low_matched_bytes = cur_matched_bytes;
- } else if (cmp == -1) {
+ } else if (UNIV_LIKELY(cmp /* == -1 */)) {
+#ifdef PAGE_CUR_LE_OR_EXTENDS
if (mode == PAGE_CUR_LE_OR_EXTENDS
&& page_cur_rec_field_extends(tuple, mid_rec,
- cur_matched_fields)) {
- low_rec = mid_rec;
- low_matched_fields = cur_matched_fields;
- low_matched_bytes = cur_matched_bytes;
- } else {
- up_rec = mid_rec;
- up_matched_fields = cur_matched_fields;
- up_matched_bytes = cur_matched_bytes;
+ offsets, cur_matched_fields)) {
+
+ goto low_rec_match;
}
- } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
- || mode == PAGE_CUR_LE_OR_EXTENDS) {
- low_rec = mid_rec;
- low_matched_fields = cur_matched_fields;
- low_matched_bytes = cur_matched_bytes;
- } else {
+#endif /* PAGE_CUR_LE_OR_EXTENDS */
+up_rec_match:
up_rec = mid_rec;
up_matched_fields = cur_matched_fields;
up_matched_bytes = cur_matched_bytes;
+ } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
+#ifdef PAGE_CUR_LE_OR_EXTENDS
+ || mode == PAGE_CUR_LE_OR_EXTENDS
+#endif /* PAGE_CUR_LE_OR_EXTENDS */
+ ) {
+
+ goto low_rec_match;
+ } else {
+
+ goto up_rec_match;
}
}
@@ -368,7 +410,9 @@ page_cur_search_with_match(
dbg_matched_fields = 0;
dbg_matched_bytes = 0;
- dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, low_rec,
+ offsets = rec_get_offsets(low_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, low_rec, offsets,
&dbg_matched_fields,
&dbg_matched_bytes);
if (mode == PAGE_CUR_G) {
@@ -390,7 +434,9 @@ page_cur_search_with_match(
dbg_matched_fields = 0;
dbg_matched_bytes = 0;
- dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, up_rec,
+ offsets = rec_get_offsets(up_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, up_rec, offsets,
&dbg_matched_fields,
&dbg_matched_bytes);
if (mode == PAGE_CUR_G) {
@@ -419,6 +465,9 @@ page_cur_search_with_match(
*iup_matched_bytes = up_matched_bytes;
*ilow_matched_fields = low_matched_fields;
*ilow_matched_bytes = low_matched_bytes;
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
/***************************************************************
@@ -463,10 +512,12 @@ static
void
page_cur_insert_rec_write_log(
/*==========================*/
- rec_t* insert_rec, /* in: inserted physical record */
- ulint rec_size, /* in: insert_rec size */
- rec_t* cursor_rec, /* in: record the cursor is pointing to */
- mtr_t* mtr) /* in: mini-transaction handle */
+ rec_t* insert_rec, /* in: inserted physical record */
+ ulint rec_size, /* in: insert_rec size */
+ rec_t* cursor_rec, /* in: record the
+ cursor is pointing to */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mini-transaction handle */
{
ulint cur_rec_size;
ulint extra_size;
@@ -476,22 +527,40 @@ page_cur_insert_rec_write_log(
byte* cur_ptr;
ulint extra_info_yes;
byte* log_ptr;
+ byte* log_end;
ulint i;
+ ulint comp;
ut_a(rec_size < UNIV_PAGE_SIZE);
- ut_ad(rec_size == rec_get_size(insert_rec));
+ ut_ad(buf_frame_align(insert_rec) == buf_frame_align(cursor_rec));
+ ut_ad(!page_rec_is_comp(insert_rec) == !index->table->comp);
+ comp = page_rec_is_comp(insert_rec);
- log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
+ {
+ mem_heap_t* heap = NULL;
+ ulint cur_offs_[REC_OFFS_NORMAL_SIZE];
+ ulint ins_offs_[REC_OFFS_NORMAL_SIZE];
- if (log_ptr == NULL) {
+ ulint* cur_offs;
+ ulint* ins_offs;
- return;
- }
+ *cur_offs_ = (sizeof cur_offs_) / sizeof *cur_offs_;
+ *ins_offs_ = (sizeof ins_offs_) / sizeof *ins_offs_;
+
+ cur_offs = rec_get_offsets(cursor_rec, index, cur_offs_,
+ ULINT_UNDEFINED, &heap);
+ ins_offs = rec_get_offsets(insert_rec, index, ins_offs_,
+ ULINT_UNDEFINED, &heap);
- extra_size = rec_get_extra_size(insert_rec);
+ extra_size = rec_offs_extra_size(ins_offs);
+ cur_extra_size = rec_offs_extra_size(cur_offs);
+ ut_ad(rec_size == rec_offs_size(ins_offs));
+ cur_rec_size = rec_offs_size(cur_offs);
- cur_extra_size = rec_get_extra_size(cursor_rec);
- cur_rec_size = rec_get_size(cursor_rec);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ }
ins_ptr = insert_rec - extra_size;
@@ -514,7 +583,9 @@ page_cur_insert_rec_write_log(
ins_ptr++;
cur_ptr++;
} else if ((i < extra_size)
- && (i >= extra_size - REC_N_EXTRA_BYTES)) {
+ && (i >= extra_size - (comp
+ ? REC_N_NEW_EXTRA_BYTES
+ : REC_N_OLD_EXTRA_BYTES))) {
i = extra_size;
ins_ptr = insert_rec;
cur_ptr = cursor_rec;
@@ -525,16 +596,35 @@ page_cur_insert_rec_write_log(
}
if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) {
-
- log_ptr = mlog_write_initial_log_record_fast(insert_rec,
- MLOG_REC_INSERT, log_ptr, mtr);
+
+ log_ptr = mlog_open_and_write_index(mtr, insert_rec, index,
+ comp
+ ? MLOG_COMP_REC_INSERT : MLOG_REC_INSERT,
+ 2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
+
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash
+ recovery: in that case mlog_open returns NULL */
+ return;
+ }
+
+ log_end = &log_ptr[2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
/* Write the cursor rec offset as a 2-byte ulint */
mach_write_to_2(log_ptr, cursor_rec
- buf_frame_align(cursor_rec));
log_ptr += 2;
+ } else {
+ log_ptr = mlog_open(mtr, 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash
+ recovery: in that case mlog_open returns NULL */
+ return;
+ }
+ log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
}
- if ((rec_get_info_bits(insert_rec) != rec_get_info_bits(cursor_rec))
+ if ((rec_get_info_and_status_bits(insert_rec, comp) !=
+ rec_get_info_and_status_bits(cursor_rec, comp))
|| (extra_size != cur_extra_size)
|| (rec_size != cur_rec_size)) {
@@ -549,7 +639,8 @@ page_cur_insert_rec_write_log(
+ extra_info_yes);
if (extra_info_yes) {
/* Write the info bits */
- mach_write_to_1(log_ptr, rec_get_info_bits(insert_rec));
+ mach_write_to_1(log_ptr,
+ rec_get_info_and_status_bits(insert_rec, comp));
log_ptr++;
/* Write the record origin offset */
@@ -565,17 +656,15 @@ page_cur_insert_rec_write_log(
/* Write to the log the inserted index record end segment which
differs from the cursor record */
- if (rec_size - i < MLOG_BUF_MARGIN) {
- ut_memcpy(log_ptr, ins_ptr, rec_size - i);
- log_ptr += rec_size - i;
- }
-
- mlog_close(mtr, log_ptr);
+ rec_size -= i;
- ut_a(rec_size - i < UNIV_PAGE_SIZE);
-
- if (rec_size - i >= MLOG_BUF_MARGIN) {
- mlog_catenate_string(mtr, ins_ptr, rec_size - i);
+ if (log_ptr + rec_size <= log_end) {
+ memcpy(log_ptr, ins_ptr, rec_size);
+ mlog_close(mtr, log_ptr + rec_size);
+ } else {
+ mlog_close(mtr, log_ptr);
+ ut_a(rec_size < UNIV_PAGE_SIZE);
+ mlog_catenate_string(mtr, ins_ptr, rec_size);
}
}
@@ -585,12 +674,13 @@ Parses a log record of a record insert on a page. */
byte*
page_cur_parse_insert_rec(
/*======================*/
- /* out: end of log record or NULL */
- ibool is_short,/* in: TRUE if short inserts */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ ibool is_short,/* in: TRUE if short inserts */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
ulint extra_info_yes;
ulint offset = 0; /* remove warning */
@@ -601,8 +691,12 @@ page_cur_parse_insert_rec(
byte buf1[1024];
byte* buf;
byte* ptr2 = ptr;
- ulint info_bits = 0; /* remove warning */
+ ulint info_and_status_bits = 0; /* remove warning */
page_cur_t cursor;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
if (!is_short) {
/* Read the cursor rec offset as a 2-byte ulint */
@@ -648,7 +742,7 @@ page_cur_parse_insert_rec(
return(NULL);
}
- info_bits = mach_read_from_1(ptr);
+ info_and_status_bits = mach_read_from_1(ptr);
ptr++;
ptr = mach_parse_compressed(ptr, end_ptr, &origin_offset);
@@ -680,6 +774,8 @@ page_cur_parse_insert_rec(
return(ptr + end_seg_len);
}
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+
/* Read from the log the inserted index record end segment which
differs from the cursor record */
@@ -689,11 +785,15 @@ page_cur_parse_insert_rec(
cursor_rec = page + offset;
}
+ offsets = rec_get_offsets(cursor_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+
if (extra_info_yes == 0) {
- info_bits = rec_get_info_bits(cursor_rec);
- origin_offset = rec_get_extra_size(cursor_rec);
- mismatch_index = rec_get_size(cursor_rec) - end_seg_len;
- }
+ info_and_status_bits = rec_get_info_and_status_bits(
+ cursor_rec, page_is_comp(page));
+ origin_offset = rec_offs_extra_size(offsets);
+ mismatch_index = rec_offs_size(offsets) - end_seg_len;
+ }
if (mismatch_index + end_seg_len < sizeof buf1) {
buf = buf1;
@@ -705,11 +805,12 @@ page_cur_parse_insert_rec(
if (mismatch_index >= UNIV_PAGE_SIZE) {
fprintf(stderr,
- "Is short %lu, info_bits %lu, offset %lu, "
+ "Is short %lu, info_and_status_bits %lu, offset %lu, "
"o_offset %lu\n"
"mismatch index %lu, end_seg_len %lu\n"
"parsed len %lu\n",
- (ulong) is_short, (ulong) info_bits, (ulong) offset,
+ (ulong) is_short, (ulong) info_and_status_bits,
+ (ulong) offset,
(ulong) origin_offset,
(ulong) mismatch_index, (ulong) end_seg_len,
(ulong) (ptr - ptr2));
@@ -722,20 +823,27 @@ page_cur_parse_insert_rec(
ut_error;
}
- ut_memcpy(buf, rec_get_start(cursor_rec), mismatch_index);
+ ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index);
ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
- rec_set_info_bits(buf + origin_offset, info_bits);
+ rec_set_info_and_status_bits(buf + origin_offset, page_is_comp(page),
+ info_and_status_bits);
page_cur_position(cursor_rec, &cursor);
- page_cur_rec_insert(&cursor, buf + origin_offset, mtr);
+ offsets = rec_get_offsets(buf + origin_offset, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ page_cur_rec_insert(&cursor, buf + origin_offset, index, offsets, mtr);
if (buf != buf1) {
mem_free(buf);
}
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
return(ptr + end_seg_len);
}
@@ -751,68 +859,85 @@ page_cur_insert_rec_low(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
- ulint data_size,/* in: data size of tuple */
- rec_t* rec, /* in: pointer to a physical record or NULL */
+ dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
+ dict_index_t* index, /* in: record descriptor */
+ rec_t* rec, /* in: pointer to a physical record or NULL */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) or NULL */
mtr_t* mtr) /* in: mini-transaction handle */
{
- byte* insert_buf = NULL;
- ulint rec_size;
- byte* page; /* the relevant page */
- rec_t* last_insert; /* cursor position at previous insert */
- rec_t* insert_rec; /* inserted record */
- ulint heap_no; /* heap number of the inserted record */
- rec_t* current_rec; /* current record after which the
- new record is inserted */
- rec_t* next_rec; /* next record after current before
- the insertion */
- ulint owner_slot; /* the slot which owns the inserted record */
- rec_t* owner_rec;
- ulint n_owned;
-
+ byte* insert_buf = NULL;
+ ulint rec_size;
+ byte* page; /* the relevant page */
+ rec_t* last_insert; /* cursor position at previous insert */
+ rec_t* insert_rec; /* inserted record */
+ ulint heap_no; /* heap number of the inserted record */
+ rec_t* current_rec; /* current record after which the
+ new record is inserted */
+ rec_t* next_rec; /* next record after current before
+ the insertion */
+ ulint owner_slot; /* the slot which owns the
+ inserted record */
+ rec_t* owner_rec;
+ ulint n_owned;
+ mem_heap_t* heap = NULL;
+ ulint comp;
+
ut_ad(cursor && mtr);
ut_ad(tuple || rec);
ut_ad(!(tuple && rec));
ut_ad(rec || dtuple_check_typed(tuple));
- ut_ad(rec || (dtuple_get_data_size(tuple) == data_size));
page = page_cur_get_page(cursor);
+ comp = page_is_comp(page);
+ ut_ad(index->table->comp == !!comp);
ut_ad(cursor->rec != page_get_supremum_rec(page));
/* 1. Get the size of the physical record in the page */
if (tuple != NULL) {
- rec_size = data_size + rec_get_converted_extra_size(
- data_size,
- dtuple_get_n_fields(tuple));
+ rec_size = rec_get_converted_size(index, tuple);
} else {
- rec_size = rec_get_size(rec);
+ if (!offsets) {
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ }
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ rec_size = rec_offs_size(offsets);
}
/* 2. Try to find suitable space from page memory management */
- insert_buf = page_mem_alloc(page, rec_size, &heap_no);
+ insert_buf = page_mem_alloc(page, rec_size, index, &heap_no);
if (insert_buf == NULL) {
-
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(NULL);
}
/* 3. Create the record */
if (tuple != NULL) {
- insert_rec = rec_convert_dtuple_to_rec_low(insert_buf, tuple,
- data_size);
+ insert_rec = rec_convert_dtuple_to_rec(insert_buf,
+ index, tuple);
+ offsets = rec_get_offsets(insert_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
} else {
- insert_rec = rec_copy(insert_buf, rec);
+ insert_rec = rec_copy(insert_buf, rec, offsets);
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ rec_offs_make_valid(insert_rec, index, offsets);
}
ut_ad(insert_rec);
- ut_ad(rec_size == rec_get_size(insert_rec));
+ ut_ad(rec_size == rec_offs_size(offsets));
/* 4. Insert the record in the linked list of records */
-
current_rec = cursor->rec;
+ ut_ad(!comp || rec_get_status(current_rec) <= REC_STATUS_INFIMUM);
+ ut_ad(!comp || rec_get_status(insert_rec) < REC_STATUS_INFIMUM);
+
next_rec = page_rec_get_next(current_rec);
+ ut_ad(!comp || rec_get_status(next_rec) != REC_STATUS_INFIMUM);
page_rec_set_next(insert_rec, next_rec);
page_rec_set_next(current_rec, insert_rec);
@@ -821,12 +946,15 @@ page_cur_insert_rec_low(
/* 5. Set the n_owned field in the inserted record to zero,
and set the heap_no field */
- rec_set_n_owned(insert_rec, 0);
- rec_set_heap_no(insert_rec, heap_no);
+ rec_set_n_owned(insert_rec, comp, 0);
+ rec_set_heap_no(insert_rec, comp, heap_no);
/* 6. Update the last insertion info in page header */
last_insert = page_header_get_ptr(page, PAGE_LAST_INSERT);
+ ut_ad(!last_insert || !comp
+ || rec_get_node_ptr_flag(last_insert)
+ == rec_get_node_ptr_flag(insert_rec));
if (last_insert == NULL) {
page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
@@ -855,8 +983,8 @@ page_cur_insert_rec_low(
/* 7. It remains to update the owner record. */
owner_rec = page_rec_find_owner_rec(insert_rec);
- n_owned = rec_get_n_owned(owner_rec);
- rec_set_n_owned(owner_rec, n_owned + 1);
+ n_owned = rec_get_n_owned(owner_rec, comp);
+ rec_set_n_owned(owner_rec, comp, n_owned + 1);
/* 8. Now we have incremented the n_owned field of the owner
record. If the number exceeds PAGE_DIR_SLOT_MAX_N_OWNED,
@@ -868,8 +996,12 @@ page_cur_insert_rec_low(
}
/* 9. Write log record of the insert */
- page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec, mtr);
+ page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec,
+ index, mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(insert_rec);
}
@@ -879,17 +1011,21 @@ UNIV_INLINE
byte*
page_copy_rec_list_to_created_page_write_log(
/*=========================================*/
- /* out: 4-byte field where to write the log data
- length */
- page_t* page, /* in: index page */
- mtr_t* mtr) /* in: mtr */
+ /* out: 4-byte field where to
+ write the log data length */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
-
- mlog_write_initial_log_record(page, MLOG_LIST_END_COPY_CREATED, mtr);
- log_ptr = mlog_open(mtr, 4);
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+ log_ptr = mlog_open_and_write_index(mtr, page, index,
+ page_is_comp(page)
+ ? MLOG_COMP_LIST_END_COPY_CREATED
+ : MLOG_LIST_END_COPY_CREATED, 4);
+ ut_a(log_ptr);
mlog_close(mtr, log_ptr + 4);
return(log_ptr);
@@ -901,11 +1037,12 @@ Parses a log record of copying a record list end to a new created page. */
byte*
page_parse_copy_rec_list_to_created_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 */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
byte* rec_end;
ulint log_data_len;
@@ -931,7 +1068,8 @@ page_parse_copy_rec_list_to_created_page(
}
while (ptr < rec_end) {
- ptr = page_cur_parse_insert_rec(TRUE, ptr, end_ptr, page, mtr);
+ ptr = page_cur_parse_insert_rec(TRUE, ptr, end_ptr,
+ index, page, mtr);
}
ut_a(ptr == rec_end);
@@ -950,10 +1088,11 @@ including that record. Infimum and supremum records are not copied. */
void
page_copy_rec_list_end_to_created_page(
/*===================================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: first record to copy */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: first record to copy */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_dir_slot_t* slot = 0; /* remove warning */
byte* heap_top;
@@ -966,9 +1105,15 @@ page_copy_rec_list_end_to_created_page(
ulint log_mode;
byte* log_ptr;
ulint log_data_len;
+ ulint comp = page_is_comp(page);
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
- ut_ad(page_header_get_field(new_page, PAGE_N_HEAP) == 2);
+ ut_ad(page_dir_get_n_heap(new_page) == 2);
ut_ad(page != new_page);
+ ut_ad(comp == page_is_comp(new_page));
if (rec == page_get_infimum_rec(page)) {
@@ -983,12 +1128,13 @@ page_copy_rec_list_end_to_created_page(
#ifdef UNIV_DEBUG
/* To pass the debug tests we have to set these dummy values
in the debug version */
- page_header_set_field(new_page, PAGE_N_DIR_SLOTS, UNIV_PAGE_SIZE / 2);
+ page_dir_set_n_slots(new_page, UNIV_PAGE_SIZE / 2);
page_header_set_ptr(new_page, PAGE_HEAP_TOP,
new_page + UNIV_PAGE_SIZE - 1);
#endif
- log_ptr = page_copy_rec_list_to_created_page_write_log(new_page, mtr);
+ log_ptr = page_copy_rec_list_to_created_page_write_log(new_page,
+ index, mtr);
log_data_len = dyn_array_get_data_size(&(mtr->log));
@@ -997,22 +1143,27 @@ page_copy_rec_list_end_to_created_page(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_SHORT_INSERTS);
prev_rec = page_get_infimum_rec(new_page);
- heap_top = new_page + PAGE_SUPREMUM_END;
+ if (comp) {
+ heap_top = new_page + PAGE_NEW_SUPREMUM_END;
+ } else {
+ heap_top = new_page + PAGE_OLD_SUPREMUM_END;
+ }
count = 0;
slot_index = 0;
n_recs = 0;
/* should be do ... until, comment by Jani */
while (rec != page_get_supremum_rec(page)) {
-
- insert_rec = rec_copy(heap_top, rec);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ insert_rec = rec_copy(heap_top, rec, offsets);
- rec_set_next_offs(prev_rec, insert_rec - new_page);
+ rec_set_next_offs(prev_rec, comp, insert_rec - new_page);
- rec_set_n_owned(insert_rec, 0);
- rec_set_heap_no(insert_rec, 2 + n_recs);
+ rec_set_n_owned(insert_rec, comp, 0);
+ rec_set_heap_no(insert_rec, comp, 2 + n_recs);
- rec_size = rec_get_size(insert_rec);
+ rec_size = rec_offs_size(offsets);
heap_top = heap_top + rec_size;
@@ -1034,7 +1185,7 @@ page_copy_rec_list_end_to_created_page(
}
page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
- mtr);
+ index, mtr);
prev_rec = insert_rec;
rec = page_rec_get_next(rec);
}
@@ -1056,22 +1207,27 @@ page_copy_rec_list_end_to_created_page(
slot_index--;
}
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
log_data_len = dyn_array_get_data_size(&(mtr->log)) - log_data_len;
ut_a(log_data_len < 100 * UNIV_PAGE_SIZE);
mach_write_to_4(log_ptr, log_data_len);
- rec_set_next_offs(insert_rec, PAGE_SUPREMUM);
+ rec_set_next_offs(insert_rec, comp,
+ comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM);
slot = page_dir_get_nth_slot(new_page, 1 + slot_index);
page_dir_slot_set_rec(slot, page_get_supremum_rec(new_page));
page_dir_slot_set_n_owned(slot, count + 1);
- page_header_set_field(new_page, PAGE_N_DIR_SLOTS, 2 + slot_index);
+ page_dir_set_n_slots(new_page, 2 + slot_index);
page_header_set_ptr(new_page, PAGE_HEAP_TOP, heap_top);
- page_header_set_field(new_page, PAGE_N_HEAP, 2 + n_recs);
+ page_dir_set_n_heap(new_page, 2 + n_recs);
page_header_set_field(new_page, PAGE_N_RECS, n_recs);
page_header_set_ptr(new_page, PAGE_LAST_INSERT, NULL);
@@ -1089,14 +1245,29 @@ UNIV_INLINE
void
page_cur_delete_rec_write_log(
/*==========================*/
- rec_t* cursor_rec, /* in: record to be deleted */
- mtr_t* mtr) /* in: mini-transaction handle */
+ rec_t* rec, /* in: record to be deleted */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mini-transaction handle */
{
- mlog_write_initial_log_record(cursor_rec, MLOG_REC_DELETE, mtr);
+ byte* log_ptr;
+
+ ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
+
+ log_ptr = mlog_open_and_write_index(mtr, rec, index,
+ page_rec_is_comp(rec)
+ ? MLOG_COMP_REC_DELETE
+ : MLOG_REC_DELETE, 2);
+
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery:
+ in that case mlog_open returns NULL */
+ return;
+ }
/* Write the cursor rec offset as a 2-byte ulint */
- mlog_catenate_ulint(mtr, cursor_rec - buf_frame_align(cursor_rec),
- MLOG_2BYTES);
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
+
+ mlog_close(mtr, log_ptr + 2);
}
/***************************************************************
@@ -1105,11 +1276,12 @@ Parses log record of a record delete on a page. */
byte*
page_cur_parse_delete_rec(
/*======================*/
- /* out: pointer to record end or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: pointer to record end or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
ulint offset;
page_cur_t cursor;
@@ -1126,9 +1298,19 @@ page_cur_parse_delete_rec(
ut_a(offset <= UNIV_PAGE_SIZE);
if (page) {
- page_cur_position(page + offset, &cursor);
-
- page_cur_delete_rec(&cursor, mtr);
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ rec_t* rec = page + offset;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ page_cur_position(rec, &cursor);
+
+ page_cur_delete_rec(&cursor, index,
+ rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap), mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
return(ptr);
@@ -1142,6 +1324,8 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /* in: a page cursor */
+ dict_index_t* index, /* in: record descriptor */
+ const ulint* offsets,/* in: rec_get_offsets(cursor->rec, index) */
mtr_t* mtr) /* in: mini-transaction handle */
{
page_dir_slot_t* cur_dir_slot;
@@ -1158,6 +1342,8 @@ page_cur_delete_rec(
page = page_cur_get_page(cursor);
current_rec = cursor->rec;
+ ut_ad(rec_offs_validate(current_rec, index, offsets));
+ ut_ad(!!page_is_comp(page) == index->table->comp);
/* The record must not be the supremum or infimum record. */
ut_ad(current_rec != page_get_supremum_rec(page));
@@ -1169,7 +1355,7 @@ page_cur_delete_rec(
cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot);
/* 0. Write the log record */
- page_cur_delete_rec_write_log(current_rec, mtr);
+ page_cur_delete_rec_write_log(current_rec, index, mtr);
/* 1. Reset the last insert info in the page header and increment
the modify clock for the frame */
@@ -1223,7 +1409,7 @@ page_cur_delete_rec(
page_dir_slot_set_n_owned(cur_dir_slot, cur_n_owned - 1);
/* 6. Free the memory occupied by the record */
- page_mem_free(page, current_rec);
+ page_mem_free(page, current_rec, offsets);
/* 7. Now we have decremented the number of owned records of the slot.
If the number drops below PAGE_DIR_SLOT_MIN_N_OWNED, we balance the
diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c
index 343f300fc77..7e09cdf073e 100644
--- a/innobase/page/page0page.c
+++ b/innobase/page/page0page.c
@@ -18,6 +18,8 @@ Created 2/2/1994 Heikki Tuuri
#include "fut0lst.h"
#include "btr0sea.h"
#include "buf0buf.h"
+#include "srv0srv.h"
+#include "btr0btr.h"
/* THE INDEX PAGE
==============
@@ -70,53 +72,70 @@ page_dir_find_owner_slot(
/* out: the directory slot number */
rec_t* rec) /* in: the physical record */
{
- ulint i;
- ulint steps = 0;
- page_t* page;
- page_dir_slot_t* slot;
- rec_t* original_rec = rec;
-
+ page_t* page;
+ register uint16 rec_offs_bytes;
+ register page_dir_slot_t* slot;
+ register const page_dir_slot_t* first_slot;
+ register rec_t* r = rec;
+
ut_ad(page_rec_check(rec));
- while (rec_get_n_owned(rec) == 0) {
- steps++;
- rec = page_rec_get_next(rec);
- }
-
page = buf_frame_align(rec);
+ first_slot = page_dir_get_nth_slot(page, 0);
+ slot = page_dir_get_nth_slot(page, page_dir_get_n_slots(page) - 1);
+
+ if (page_is_comp(page)) {
+ while (rec_get_n_owned(r, TRUE) == 0) {
+ r = page + rec_get_next_offs(r, TRUE);
+ ut_ad(r >= page + PAGE_NEW_SUPREMUM);
+ ut_ad(r < page + (UNIV_PAGE_SIZE - PAGE_DIR));
+ }
+ } else {
+ while (rec_get_n_owned(r, FALSE) == 0) {
+ r = page + rec_get_next_offs(r, FALSE);
+ ut_ad(r >= page + PAGE_OLD_SUPREMUM);
+ ut_ad(r < page + (UNIV_PAGE_SIZE - PAGE_DIR));
+ }
+ }
- i = page_dir_get_n_slots(page) - 1;
- slot = page_dir_get_nth_slot(page, i);
+ rec_offs_bytes = mach_encode_2(r - page);
- while (page_dir_slot_get_rec(slot) != rec) {
+ while (UNIV_LIKELY(*(uint16*) slot != rec_offs_bytes)) {
- if (i == 0) {
+ if (UNIV_UNLIKELY(slot == first_slot)) {
fprintf(stderr,
"InnoDB: Probable data corruption on page %lu\n"
"InnoDB: Original record ",
(ulong) buf_frame_get_page_no(page));
- rec_print(stderr, original_rec);
+ if (page_is_comp(page)) {
+ fputs("(compact record)", stderr);
+ } else {
+ rec_print_old(stderr, rec);
+ }
- fprintf(stderr, "\n"
- "InnoDB: on that page. Steps %lu.\n", (ulong) steps);
- fputs(
+ fputs("\n"
+ "InnoDB: on that page.\n"
"InnoDB: Cannot find the dir slot for record ",
stderr);
- rec_print(stderr, rec);
+ if (page_is_comp(page)) {
+ fputs("(compact record)", stderr);
+ } else {
+ rec_print_old(stderr, page
+ + mach_decode_2(rec_offs_bytes));
+ }
fputs("\n"
"InnoDB: on that page!\n", stderr);
buf_page_print(page);
- ut_error;
- }
+ ut_error;
+ }
- i--;
- slot = page_dir_get_nth_slot(page, i);
+ slot += PAGE_DIR_SLOT_SIZE;
}
- return(i);
+ return(((ulint) (first_slot - slot)) / PAGE_DIR_SLOT_SIZE);
}
/******************************************************************
@@ -136,14 +155,15 @@ page_dir_slot_check(
page = buf_frame_align(slot);
- n_slots = page_header_get_field(page, PAGE_N_DIR_SLOTS);
+ n_slots = page_dir_get_n_slots(page);
ut_a(slot <= page_dir_get_nth_slot(page, 0));
ut_a(slot >= page_dir_get_nth_slot(page, n_slots - 1));
- ut_a(page_rec_check(page + mach_read_from_2(slot)));
+ ut_a(page_rec_check(page_dir_slot_get_rec(slot)));
- n_owned = rec_get_n_owned(page + mach_read_from_2(slot));
+ n_owned = rec_get_n_owned(page_dir_slot_get_rec(slot),
+ page_is_comp(page));
if (slot == page_dir_get_nth_slot(page, 0)) {
ut_a(n_owned == 1);
@@ -194,12 +214,14 @@ Allocates a block of memory from an index page. */
byte*
page_mem_alloc(
/*===========*/
- /* out: pointer to start of allocated
- buffer, or NULL if allocation fails */
- page_t* page, /* in: index page */
- ulint need, /* in: number of bytes needed */
- ulint* heap_no)/* out: this contains the heap number
- of the allocated record if allocation succeeds */
+ /* out: pointer to start of allocated
+ buffer, or NULL if allocation fails */
+ page_t* page, /* in: index page */
+ ulint need, /* in: number of bytes needed */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* heap_no)/* out: this contains the heap number
+ of the allocated record
+ if allocation succeeds */
{
rec_t* rec;
byte* block;
@@ -213,18 +235,37 @@ page_mem_alloc(
rec = page_header_get_ptr(page, PAGE_FREE);
- if (rec && (rec_get_size(rec) >= need)) {
+ if (rec) {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
- page_header_set_ptr(page, PAGE_FREE, page_rec_get_next(rec));
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
- garbage = page_header_get_field(page, PAGE_GARBAGE);
- ut_ad(garbage >= need);
+ if (rec_offs_size(offsets) >= need) {
+ page_header_set_ptr(page, PAGE_FREE,
+ page_rec_get_next(rec));
- page_header_set_field(page, PAGE_GARBAGE, garbage - need);
+ garbage = page_header_get_field(page, PAGE_GARBAGE);
+ ut_ad(garbage >= need);
- *heap_no = rec_get_heap_no(rec);
+ page_header_set_field(page, PAGE_GARBAGE,
+ garbage - need);
- return(rec_get_start(rec));
+ *heap_no = rec_get_heap_no(rec, page_is_comp(page));
+
+ block = rec_get_start(rec, offsets);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(block);
+ }
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
/* Could not find space from the free list, try top of heap */
@@ -235,9 +276,9 @@ page_mem_alloc(
block = page_header_get_ptr(page, PAGE_HEAP_TOP);
page_header_set_ptr(page, PAGE_HEAP_TOP, block + need);
- *heap_no = page_header_get_field(page, PAGE_N_HEAP);
+ *heap_no = page_dir_get_n_heap(page);
- page_header_set_field(page, PAGE_N_HEAP, 1 + *heap_no);
+ page_dir_set_n_heap(page, 1 + *heap_no);
return(block);
}
@@ -253,9 +294,11 @@ page_create_write_log(
/*==================*/
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr, /* in: mini-transaction handle */
+ ulint comp) /* in: nonzero=compact page format */
{
- mlog_write_initial_log_record(frame, MLOG_PAGE_CREATE, mtr);
+ mlog_write_initial_log_record(frame,
+ comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE, mtr);
}
/***************************************************************
@@ -267,6 +310,7 @@ page_parse_create(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr __attribute__((unused)), /* in: buffer end */
+ ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -275,7 +319,7 @@ page_parse_create(
/* The record is empty, except for the record initial part */
if (page) {
- page_create(page, mtr);
+ page_create(page, mtr, comp);
}
return(ptr);
@@ -290,7 +334,8 @@ page_create(
/* out: pointer to the page */
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr, /* in: mini-transaction handle */
+ ulint comp) /* in: nonzero=compact page format */
{
page_dir_slot_t* slot;
mem_heap_t* heap;
@@ -300,6 +345,10 @@ page_create(
rec_t* infimum_rec;
rec_t* supremum_rec;
page_t* page;
+ dict_index_t* index;
+ ulint* offsets;
+
+ index = comp ? srv_sys->dummy_ind2 : srv_sys->dummy_ind1;
ut_ad(frame && mtr);
ut_ad(PAGE_BTR_IBUF_FREE_LIST + FLST_BASE_NODE_SIZE
@@ -311,7 +360,7 @@ page_create(
buf_frame_modify_clock_inc(frame);
/* 2. WRITE LOG INFORMATION */
- page_create_write_log(frame, mtr);
+ page_create_write_log(frame, mtr, comp);
page = frame;
@@ -323,51 +372,61 @@ page_create(
/* Create first a data tuple for infimum record */
tuple = dtuple_create(heap, 1);
+ dtuple_set_info_bits(tuple, REC_STATUS_INFIMUM);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field, "infimum", sizeof "infimum");
- dtype_set(dfield_get_type(field), DATA_VARCHAR, DATA_ENGLISH, 20, 0);
-
+ dfield_set_data(field, "infimum", 8);
+ dtype_set(dfield_get_type(field),
+ DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, 8, 0);
/* Set the corresponding physical record to its place in the page
record heap */
heap_top = page + PAGE_DATA;
- infimum_rec = rec_convert_dtuple_to_rec(heap_top, tuple);
+ infimum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple);
+
+ ut_a(infimum_rec ==
+ page + (comp ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
+
+ rec_set_n_owned(infimum_rec, comp, 1);
+ rec_set_heap_no(infimum_rec, comp, 0);
+ offsets = rec_get_offsets(infimum_rec, index, NULL,
+ ULINT_UNDEFINED, &heap);
+
+ heap_top = rec_get_end(infimum_rec, offsets);
- ut_a(infimum_rec == page + PAGE_INFIMUM);
-
- rec_set_n_owned(infimum_rec, 1);
- rec_set_heap_no(infimum_rec, 0);
-
- heap_top = rec_get_end(infimum_rec);
-
/* Create then a tuple for supremum */
tuple = dtuple_create(heap, 1);
+ dtuple_set_info_bits(tuple, REC_STATUS_SUPREMUM);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field, "supremum", sizeof "supremum");
- dtype_set(dfield_get_type(field), DATA_VARCHAR, DATA_ENGLISH, 20, 0);
+ dfield_set_data(field, "supremum", comp ? 8 : 9);
+ dtype_set(dfield_get_type(field),
+ DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, comp ? 8 : 9, 0);
- supremum_rec = rec_convert_dtuple_to_rec(heap_top, tuple);
+ supremum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple);
- ut_a(supremum_rec == page + PAGE_SUPREMUM);
+ ut_a(supremum_rec ==
+ page + (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM));
- rec_set_n_owned(supremum_rec, 1);
- rec_set_heap_no(supremum_rec, 1);
-
- heap_top = rec_get_end(supremum_rec);
+ rec_set_n_owned(supremum_rec, comp, 1);
+ rec_set_heap_no(supremum_rec, comp, 1);
+
+ offsets = rec_get_offsets(supremum_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ heap_top = rec_get_end(supremum_rec, offsets);
- ut_ad(heap_top == page + PAGE_SUPREMUM_END);
+ ut_ad(heap_top ==
+ page + (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END));
mem_heap_free(heap);
- /* 4. INITIALIZE THE PAGE HEADER */
+ /* 4. INITIALIZE THE PAGE */
page_header_set_field(page, PAGE_N_DIR_SLOTS, 2);
page_header_set_ptr(page, PAGE_HEAP_TOP, heap_top);
- page_header_set_field(page, PAGE_N_HEAP, 2);
+ page_header_set_field(page, PAGE_N_HEAP, comp ? 0x8002 : 2);
page_header_set_ptr(page, PAGE_FREE, NULL);
page_header_set_field(page, PAGE_GARBAGE, 0);
page_header_set_ptr(page, PAGE_LAST_INSERT, NULL);
@@ -375,7 +434,9 @@ page_create(
page_header_set_field(page, PAGE_N_DIRECTION, 0);
page_header_set_field(page, PAGE_N_RECS, 0);
page_set_max_trx_id(page, ut_dulint_zero);
-
+ memset(heap_top, 0, UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START
+ - (heap_top - page));
+
/* 5. SET POINTERS IN RECORDS AND DIR SLOTS */
/* Set the slots to point to infimum and supremum. */
@@ -388,8 +449,8 @@ page_create(
/* Set the next pointers in infimum and supremum */
- rec_set_next_offs(infimum_rec, (ulint)(supremum_rec - page));
- rec_set_next_offs(supremum_rec, 0);
+ rec_set_next_offs(infimum_rec, comp, (ulint)(supremum_rec - page));
+ rec_set_next_offs(supremum_rec, comp, 0);
return(page);
}
@@ -401,14 +462,19 @@ touch the lock table and max trx id on page. */
void
page_copy_rec_list_end_no_locks(
/*============================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_cur_t cur1;
page_cur_t cur2;
rec_t* sup;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
page_cur_position(rec, &cur1);
@@ -416,8 +482,12 @@ page_copy_rec_list_end_no_locks(
page_cur_move_to_next(&cur1);
}
-
- ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == PAGE_INFIMUM);
+
+ ut_a((ibool)!!page_is_comp(new_page) == index->table->comp);
+ ut_a(page_is_comp(new_page) == page_is_comp(page));
+ ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint)
+ (page_is_comp(new_page)
+ ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
page_cur_set_before_first(new_page, &cur2);
@@ -425,9 +495,15 @@ page_copy_rec_list_end_no_locks(
sup = page_get_supremum_rec(page);
- while (sup != page_cur_get_rec(&cur1)) {
- if (!page_cur_rec_insert(&cur2,
- page_cur_get_rec(&cur1), mtr)) {
+ for (;;) {
+ rec_t* cur1_rec = page_cur_get_rec(&cur1);
+ if (cur1_rec == sup) {
+ break;
+ }
+ offsets = rec_get_offsets(cur1_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ if (UNIV_UNLIKELY(!page_cur_rec_insert(&cur2, cur1_rec, index,
+ offsets, mtr))) {
/* Track an assertion failure reported on the mailing
list on June 18th, 2003 */
@@ -446,7 +522,11 @@ page_copy_rec_list_end_no_locks(
page_cur_move_to_next(&cur1);
page_cur_move_to_next(&cur2);
}
-}
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+}
/*****************************************************************
Copies records from page to new_page, from a given record onward,
@@ -456,16 +536,18 @@ The records are copied to the start of the record list on new_page. */
void
page_copy_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
- if (page_header_get_field(new_page, PAGE_N_HEAP) == 2) {
+ if (page_dir_get_n_heap(new_page) == 2) {
page_copy_rec_list_end_to_created_page(new_page, page, rec,
- mtr);
+ index, mtr);
} else {
- page_copy_rec_list_end_no_locks(new_page, page, rec, mtr);
+ page_copy_rec_list_end_no_locks(new_page, page, rec,
+ index, mtr);
}
/* Update the lock table, MAX_TRX_ID, and possible hash index */
@@ -474,7 +556,7 @@ page_copy_rec_list_end(
page_update_max_trx_id(new_page, page_get_max_trx_id(page));
- btr_search_move_or_delete_hash_entries(new_page, page);
+ btr_search_move_or_delete_hash_entries(new_page, page, index);
}
/*****************************************************************
@@ -485,14 +567,19 @@ The records are copied to the end of the record list on new_page. */
void
page_copy_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_cur_t cur1;
page_cur_t cur2;
rec_t* old_end;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
page_cur_set_before_first(page, &cur1);
@@ -510,8 +597,13 @@ page_copy_rec_list_start(
/* Copy records from the original page to the new page */
while (page_cur_get_rec(&cur1) != rec) {
- ut_a(
- page_cur_rec_insert(&cur2, page_cur_get_rec(&cur1), mtr));
+ rec_t* ins_rec;
+ rec_t* cur1_rec = page_cur_get_rec(&cur1);
+ offsets = rec_get_offsets(cur1_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ ins_rec = page_cur_rec_insert(&cur2, cur1_rec, index,
+ offsets, mtr);
+ ut_a(ins_rec);
page_cur_move_to_next(&cur1);
page_cur_move_to_next(&cur2);
@@ -523,8 +615,12 @@ page_copy_rec_list_start(
page_update_max_trx_id(new_page, page_get_max_trx_id(page));
- btr_search_move_or_delete_hash_entries(new_page, page);
-}
+ btr_search_move_or_delete_hash_entries(new_page, page, index);
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+}
/**************************************************************
Writes a log record of a record list end or start deletion. */
@@ -532,18 +628,24 @@ UNIV_INLINE
void
page_delete_rec_list_write_log(
/*===========================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- byte type, /* in: operation type: MLOG_LIST_END_DELETE, ... */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ byte type, /* in: operation type:
+ MLOG_LIST_END_DELETE, ... */
+ mtr_t* mtr) /* in: mtr */
{
- ut_ad((type == MLOG_LIST_END_DELETE)
- || (type == MLOG_LIST_START_DELETE));
-
- mlog_write_initial_log_record(page, type, mtr);
-
- /* Write the parameter as a 2-byte ulint */
- mlog_catenate_ulint(mtr, rec - page, MLOG_2BYTES);
+ byte* log_ptr;
+ ut_ad(type == MLOG_LIST_END_DELETE
+ || type == MLOG_LIST_START_DELETE
+ || type == MLOG_COMP_LIST_END_DELETE
+ || type == MLOG_COMP_LIST_START_DELETE);
+
+ log_ptr = mlog_open_and_write_index(mtr, rec, index, type, 2);
+ if (log_ptr) {
+ /* Write the parameter as a 2-byte ulint */
+ mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
+ mlog_close(mtr, log_ptr + 2);
+ }
}
/**************************************************************
@@ -552,18 +654,23 @@ Parses a log record of a record list end or start deletion. */
byte*
page_parse_delete_rec_list(
/*=======================*/
- /* out: end of log record or NULL */
- byte type, /* in: MLOG_LIST_END_DELETE or
- MLOG_LIST_START_DELETE */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte type, /* in: MLOG_LIST_END_DELETE,
+ MLOG_LIST_START_DELETE,
+ MLOG_COMP_LIST_END_DELETE or
+ MLOG_COMP_LIST_START_DELETE */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
ulint offset;
- ut_ad((type == MLOG_LIST_END_DELETE)
- || (type == MLOG_LIST_START_DELETE));
+ ut_ad(type == MLOG_LIST_END_DELETE
+ || type == MLOG_LIST_START_DELETE
+ || type == MLOG_COMP_LIST_END_DELETE
+ || type == MLOG_COMP_LIST_START_DELETE);
/* Read the record offset as a 2-byte ulint */
@@ -580,11 +687,14 @@ page_parse_delete_rec_list(
return(ptr);
}
- if (type == MLOG_LIST_END_DELETE) {
- page_delete_rec_list_end(page, page + offset, ULINT_UNDEFINED,
- ULINT_UNDEFINED, mtr);
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+
+ if (type == MLOG_LIST_END_DELETE
+ || type == MLOG_COMP_LIST_END_DELETE) {
+ page_delete_rec_list_end(page, page + offset, index,
+ ULINT_UNDEFINED, ULINT_UNDEFINED, mtr);
} else {
- page_delete_rec_list_start(page, page + offset, mtr);
+ page_delete_rec_list_start(page, page + offset, index, mtr);
}
return(ptr);
@@ -597,14 +707,15 @@ The infimum and supremum records are not deleted. */
void
page_delete_rec_list_end(
/*=====================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- ulint n_recs, /* in: number of records to delete, or ULINT_UNDEFINED
- if not known */
- ulint size, /* in: the sum of the sizes of the records in the end
- of the chain to delete, or ULINT_UNDEFINED if not
- known */
- mtr_t* mtr) /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_recs, /* in: number of records to delete,
+ or ULINT_UNDEFINED if not known */
+ ulint size, /* in: the sum of the sizes of the
+ records in the end of the chain to
+ delete, or ULINT_UNDEFINED if not known */
+ mtr_t* mtr) /* in: mtr */
{
page_dir_slot_t* slot;
ulint slot_index;
@@ -615,10 +726,12 @@ page_delete_rec_list_end(
ulint count;
ulint n_owned;
rec_t* sup;
+ ulint comp;
/* Reset the last insert info in the page header and increment
the modify clock for the frame */
+ ut_ad(size == ULINT_UNDEFINED || size < UNIV_PAGE_SIZE);
page_header_set_ptr(page, PAGE_LAST_INSERT, NULL);
/* The page gets invalid for optimistic searches: increment the
@@ -628,11 +741,13 @@ page_delete_rec_list_end(
sup = page_get_supremum_rec(page);
- if (rec == page_get_infimum_rec(page)) {
+ comp = page_is_comp(page);
+ if (page_rec_is_infimum_low(rec - page)) {
rec = page_rec_get_next(rec);
}
- page_delete_rec_list_write_log(page, rec, MLOG_LIST_END_DELETE, mtr);
+ page_delete_rec_list_write_log(rec, index,
+ comp ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr);
if (rec == sup) {
@@ -644,19 +759,36 @@ page_delete_rec_list_end(
last_rec = page_rec_get_prev(sup);
if ((size == ULINT_UNDEFINED) || (n_recs == ULINT_UNDEFINED)) {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
/* Calculate the sum of sizes and the number of records */
size = 0;
n_recs = 0;
rec2 = rec;
while (rec2 != sup) {
- size += rec_get_size(rec2);
+ ulint s;
+ offsets = rec_get_offsets(rec2, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ s = rec_offs_size(offsets);
+ ut_ad(rec2 - page + s - rec_offs_extra_size(offsets)
+ < UNIV_PAGE_SIZE);
+ ut_ad(size + s < UNIV_PAGE_SIZE);
+ size += s;
n_recs++;
rec2 = page_rec_get_next(rec2);
}
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
+ ut_ad(size < UNIV_PAGE_SIZE);
+
/* Update the page directory; there is no need to balance the number
of the records owned by the supremum record, as it is allowed to be
less than PAGE_DIR_SLOT_MIN_N_OWNED */
@@ -664,15 +796,15 @@ page_delete_rec_list_end(
rec2 = rec;
count = 0;
- while (rec_get_n_owned(rec2) == 0) {
+ while (rec_get_n_owned(rec2, comp) == 0) {
count++;
rec2 = page_rec_get_next(rec2);
}
- ut_ad(rec_get_n_owned(rec2) - count > 0);
+ ut_ad(rec_get_n_owned(rec2, comp) - count > 0);
- n_owned = rec_get_n_owned(rec2) - count;
+ n_owned = rec_get_n_owned(rec2, comp) - count;
slot_index = page_dir_find_owner_slot(rec2);
slot = page_dir_get_nth_slot(page, slot_index);
@@ -680,7 +812,7 @@ page_delete_rec_list_end(
page_dir_slot_set_rec(slot, sup);
page_dir_slot_set_n_owned(slot, n_owned);
- page_header_set_field(page, PAGE_N_DIR_SLOTS, slot_index + 1);
+ page_dir_set_n_slots(page, slot_index + 1);
/* Remove the record chain segment from the record chain */
page_rec_set_next(prev_rec, page_get_supremum_rec(page));
@@ -706,14 +838,28 @@ that record. Infimum and supremum records are not deleted. */
void
page_delete_rec_list_start(
/*=======================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr) /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_cur_t cur1;
ulint log_mode;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ mem_heap_t* heap = NULL;
+ byte type;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ ut_ad(!!page_is_comp(page) == index->table->comp);
+
+ if (page_is_comp(page)) {
+ type = MLOG_COMP_LIST_START_DELETE;
+ } else {
+ type = MLOG_LIST_START_DELETE;
+ }
- page_delete_rec_list_write_log(page, rec, MLOG_LIST_START_DELETE, mtr);
+ page_delete_rec_list_write_log(rec, index, type, mtr);
page_cur_set_before_first(page, &cur1);
@@ -729,8 +875,13 @@ page_delete_rec_list_start(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
while (page_cur_get_rec(&cur1) != rec) {
+ offsets = rec_get_offsets(page_cur_get_rec(&cur1), index,
+ offsets, ULINT_UNDEFINED, &heap);
+ page_cur_delete_rec(&cur1, index, offsets, mtr);
+ }
- page_cur_delete_rec(&cur1, mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
/* Restore log mode */
@@ -745,10 +896,11 @@ split_rec. */
void
page_move_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record to move */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
ulint old_data_size;
ulint new_data_size;
@@ -758,15 +910,15 @@ page_move_rec_list_end(
old_data_size = page_get_data_size(new_page);
old_n_recs = page_get_n_recs(new_page);
- page_copy_rec_list_end(new_page, page, split_rec, mtr);
+ page_copy_rec_list_end(new_page, page, split_rec, index, mtr);
new_data_size = page_get_data_size(new_page);
new_n_recs = page_get_n_recs(new_page);
ut_ad(new_data_size >= old_data_size);
- page_delete_rec_list_end(page, split_rec, new_n_recs - old_n_recs,
- new_data_size - old_data_size, mtr);
+ page_delete_rec_list_end(page, split_rec, index,
+ new_n_recs - old_n_recs, new_data_size - old_data_size, mtr);
}
/*****************************************************************
@@ -776,14 +928,15 @@ split_rec. */
void
page_move_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record not to move */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record not to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
- page_copy_rec_list_start(new_page, page, split_rec, mtr);
+ page_copy_rec_list_start(new_page, page, split_rec, index, mtr);
- page_delete_rec_list_start(page, split_rec, mtr);
+ page_delete_rec_list_start(page, split_rec, index, mtr);
}
/***************************************************************************
@@ -801,7 +954,7 @@ page_rec_write_index_page_no(
byte* data;
ulint len;
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field_old(rec, i, &len);
ut_ad(len == 4);
@@ -885,7 +1038,7 @@ page_dir_add_slots(
ut_ad(start < n_slots - 1);
/* Update the page header */
- page_header_set_field(page, PAGE_N_DIR_SLOTS, n_slots + n);
+ page_dir_set_n_slots(page, n_slots + n);
/* Move slots up */
@@ -1006,8 +1159,8 @@ page_dir_balance_slot(
old_rec = page_dir_slot_get_rec(slot);
new_rec = page_rec_get_next(old_rec);
- rec_set_n_owned(old_rec, 0);
- rec_set_n_owned(new_rec, n_owned + 1);
+ rec_set_n_owned(old_rec, page_is_comp(page), 0);
+ rec_set_n_owned(new_rec, page_is_comp(page), n_owned + 1);
page_dir_slot_set_rec(slot, new_rec);
@@ -1080,13 +1233,15 @@ page_rec_get_n_recs_before(
rec_t* slot_rec;
page_t* page;
ulint i;
+ ulint comp;
lint n = 0;
ut_ad(page_rec_check(rec));
page = buf_frame_align(rec);
-
- while (rec_get_n_owned(rec) == 0) {
+ comp = page_is_comp(page);
+
+ while (rec_get_n_owned(rec, comp) == 0) {
rec = page_rec_get_next(rec);
n--;
@@ -1096,7 +1251,7 @@ page_rec_get_n_recs_before(
slot = page_dir_get_nth_slot(page, i);
slot_rec = page_dir_slot_get_rec(slot);
- n += rec_get_n_owned(slot_rec);
+ n += rec_get_n_owned(slot_rec, comp);
if (rec == slot_rec) {
@@ -1118,17 +1273,21 @@ the index page context. */
void
page_rec_print(
/*===========*/
- rec_t* rec)
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: record descriptor */
{
- rec_print(stderr, rec);
+ ulint comp = page_is_comp(buf_frame_align(rec));
+
+ ut_a(!comp == !rec_offs_comp(offsets));
+ rec_print_new(stderr, rec, offsets);
fprintf(stderr,
" n_owned: %lu; heap_no: %lu; next rec: %lu\n",
- (ulong) rec_get_n_owned(rec),
- (ulong) rec_get_heap_no(rec),
- (ulong) rec_get_next_offs(rec));
+ (ulong) rec_get_n_owned(rec, comp),
+ (ulong) rec_get_heap_no(rec, comp),
+ (ulong) rec_get_next_offs(rec, comp));
page_rec_check(rec);
- rec_validate(rec);
+ rec_validate(rec, offsets);
}
/*******************************************************************
@@ -1176,12 +1335,19 @@ debugging purposes. */
void
page_print_list(
/*============*/
- page_t* page, /* in: index page */
- ulint pr_n) /* in: print n first and n last entries */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint pr_n) /* in: print n first and n last entries */
{
page_cur_t cur;
ulint count;
ulint n_recs;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ ut_a((ibool)!!page_is_comp(page) == index->table->comp);
fprintf(stderr,
"--------------------------------\n"
@@ -1193,7 +1359,9 @@ page_print_list(
page_cur_set_before_first(page, &cur);
count = 0;
for (;;) {
- page_rec_print(cur.rec);
+ offsets = rec_get_offsets(cur.rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ page_rec_print(cur.rec, offsets);
if (count == pr_n) {
break;
@@ -1213,7 +1381,9 @@ page_print_list(
page_cur_move_to_next(&cur);
if (count + pr_n >= n_recs) {
- page_rec_print(cur.rec);
+ offsets = rec_get_offsets(cur.rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ page_rec_print(cur.rec, offsets);
}
count++;
}
@@ -1222,6 +1392,10 @@ page_print_list(
"Total of %lu records \n"
"--------------------------------\n",
(ulong) (count + 1));
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
/*******************************************************************
@@ -1235,14 +1409,15 @@ page_header_print(
fprintf(stderr,
"--------------------------------\n"
"PAGE HEADER INFO\n"
- "Page address %p, n records %lu\n"
+ "Page address %p, n records %lu (%s)\n"
"n dir slots %lu, heap top %lu\n"
"Page n heap %lu, free %lu, garbage %lu\n"
"Page last insert %lu, direction %lu, n direction %lu\n",
page, (ulong) page_header_get_field(page, PAGE_N_RECS),
+ page_is_comp(page) ? "compact format" : "original format",
(ulong) page_header_get_field(page, PAGE_N_DIR_SLOTS),
(ulong) page_header_get_field(page, PAGE_HEAP_TOP),
- (ulong) page_header_get_field(page, PAGE_N_HEAP),
+ (ulong) page_dir_get_n_heap(page),
(ulong) page_header_get_field(page, PAGE_FREE),
(ulong) page_header_get_field(page, PAGE_GARBAGE),
(ulong) page_header_get_field(page, PAGE_LAST_INSERT),
@@ -1257,13 +1432,16 @@ debugging purposes. */
void
page_print(
/*======*/
- page_t* page, /* in: index page */
- ulint dn, /* in: print dn first and last entries in directory */
- ulint rn) /* in: print rn first and last records on page */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint dn, /* in: print dn first and last entries
+ in directory */
+ ulint rn) /* in: print rn first and last records
+ in directory */
{
page_header_print(page);
page_dir_print(page, dn);
- page_print_list(page, rn);
+ page_print_list(page, index, rn);
}
/*******************************************************************
@@ -1274,20 +1452,24 @@ the heap_no field. */
ibool
page_rec_validate(
/*==============*/
- /* out: TRUE if ok */
- rec_t* rec) /* in: record on the page */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_owned;
ulint heap_no;
- page_t* page;
+ page_t* page;
+ ulint comp;
page = buf_frame_align(rec);
+ comp = page_is_comp(page);
+ ut_a(!comp == !rec_offs_comp(offsets));
page_rec_check(rec);
- rec_validate(rec);
+ rec_validate(rec, offsets);
- n_owned = rec_get_n_owned(rec);
- heap_no = rec_get_heap_no(rec);
+ n_owned = rec_get_n_owned(rec, comp);
+ heap_no = rec_get_heap_no(rec, comp);
if (!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED)) {
fprintf(stderr,
@@ -1296,11 +1478,11 @@ page_rec_validate(
return(FALSE);
}
- if (!(heap_no < page_header_get_field(page, PAGE_N_HEAP))) {
+ if (!(heap_no < page_dir_get_n_heap(page))) {
fprintf(stderr,
"InnoDB: Heap no of rec %lu too big %lu %lu\n",
(ulong)(rec - page), (ulong) heap_no,
- (ulong) page_header_get_field(page, PAGE_N_HEAP));
+ (ulong) page_dir_get_n_heap(page));
return(FALSE);
}
@@ -1358,6 +1540,7 @@ page_simple_validate(
ulint count;
ulint own_count;
ibool ret = FALSE;
+ ulint comp = page_is_comp(page);
/* Check first that the record heap and the directory do not
overlap. */
@@ -1404,13 +1587,13 @@ page_simple_validate(
goto func_exit;
}
- if (rec_get_n_owned(rec) != 0) {
+ if (rec_get_n_owned(rec, comp) != 0) {
/* This is a record pointed to by a dir slot */
- if (rec_get_n_owned(rec) != own_count) {
+ if (rec_get_n_owned(rec, comp) != own_count) {
fprintf(stderr,
"InnoDB: Wrong owned count %lu, %lu, rec %lu\n",
- (ulong) rec_get_n_owned(rec),
+ (ulong) rec_get_n_owned(rec, comp),
(ulong) own_count,
(ulong)(rec - page));
@@ -1438,11 +1621,11 @@ page_simple_validate(
break;
}
- if (rec_get_next_offs(rec) < FIL_PAGE_DATA
- || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
+ if (rec_get_next_offs(rec, comp) < FIL_PAGE_DATA
+ || rec_get_next_offs(rec, comp) >= UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Next record offset nonsensical %lu for rec %lu\n",
- (ulong) rec_get_next_offs(rec),
+ (ulong) rec_get_next_offs(rec, comp),
(ulong)(rec - page));
goto func_exit;
@@ -1461,7 +1644,7 @@ page_simple_validate(
own_count++;
}
- if (rec_get_n_owned(rec) == 0) {
+ if (rec_get_n_owned(rec, comp) == 0) {
fprintf(stderr, "InnoDB: n owned is zero in a supremum rec\n");
goto func_exit;
@@ -1514,10 +1697,10 @@ page_simple_validate(
rec = page_rec_get_next(rec);
}
- if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
+ if (page_dir_get_n_heap(page) != count + 1) {
fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n",
- (ulong) page_header_get_field(page, PAGE_N_HEAP),
+ (ulong) page_dir_get_n_heap(page),
(ulong) (count + 1));
goto func_exit;
@@ -1549,25 +1732,30 @@ page_validate(
ulint slot_no;
ulint data_size;
rec_t* rec;
- rec_t* old_rec = NULL;
+ rec_t* old_rec = NULL;
ulint offs;
ulint n_slots;
- ibool ret = FALSE;
+ ibool ret = FALSE;
ulint i;
-
+ ulint comp = page_is_comp(page);
+ ulint* offsets = NULL;
+ ulint* old_offsets = NULL;
+
+ if ((ibool)!!comp != index->table->comp) {
+ fputs("InnoDB: 'compact format' flag mismatch\n", stderr);
+ goto func_exit2;
+ }
if (!page_simple_validate(page)) {
goto func_exit2;
}
- heap = mem_heap_create(UNIV_PAGE_SIZE);
+ heap = mem_heap_create(UNIV_PAGE_SIZE + 200);
/* The following buffer is used to check that the
records in the page record heap do not overlap */
buf = mem_heap_alloc(heap, UNIV_PAGE_SIZE);
- for (i = 0; i < UNIV_PAGE_SIZE; i++) {
- buf[i] = 0;
- }
+ memset(buf, 0, UNIV_PAGE_SIZE);
/* Check first that the record heap and the directory do not
overlap. */
@@ -1599,37 +1787,47 @@ page_validate(
for (;;) {
rec = cur.rec;
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+
+ if (comp && page_rec_is_user_rec(rec)
+ && rec_get_node_ptr_flag(rec)
+ != (ibool)
+ (btr_page_get_level_low(page) != 0)) {
+ fputs("InnoDB: node_ptr flag mismatch\n", stderr);
+ goto func_exit;
+ }
- if (!page_rec_validate(rec)) {
+ if (!page_rec_validate(rec, offsets)) {
goto func_exit;
}
/* Check that the records are in the ascending order */
if ((count >= 2) && (!page_cur_is_after_last(&cur))) {
- if (!(1 == cmp_rec_rec(rec, old_rec, index))) {
+ if (!(1 == cmp_rec_rec(rec, old_rec,
+ offsets, old_offsets, index))) {
fprintf(stderr,
"InnoDB: Records in wrong order on page %lu",
(ulong) buf_frame_get_page_no(page));
dict_index_name_print(stderr, NULL, index);
fputs("\nInnoDB: previous record ", stderr);
- rec_print(stderr, old_rec);
+ rec_print_new(stderr, old_rec, old_offsets);
fputs("\nInnoDB: record ", stderr);
- rec_print(stderr, rec);
+ rec_print_new(stderr, rec, offsets);
putc('\n', stderr);
goto func_exit;
}
}
- if ((rec != page_get_supremum_rec(page))
- && (rec != page_get_infimum_rec(page))) {
+ if (page_rec_is_user_rec(rec)) {
- data_size += rec_get_size(rec);
+ data_size += rec_offs_size(offsets);
}
- offs = rec_get_start(rec) - page;
+ offs = rec_get_start(rec, offsets) - page;
- for (i = 0; i < rec_get_size(rec); i++) {
+ for (i = 0; i < rec_offs_size(offsets); i++) {
if (!buf[offs + i] == 0) {
/* No other record may overlap this */
@@ -1641,12 +1839,12 @@ page_validate(
buf[offs + i] = 1;
}
- if (rec_get_n_owned(rec) != 0) {
+ if (rec_get_n_owned(rec, comp) != 0) {
/* This is a record pointed to by a dir slot */
- if (rec_get_n_owned(rec) != own_count) {
+ if (rec_get_n_owned(rec, comp) != own_count) {
fprintf(stderr,
"InnoDB: Wrong owned count %lu, %lu\n",
- (ulong) rec_get_n_owned(rec),
+ (ulong) rec_get_n_owned(rec, comp),
(ulong) own_count);
goto func_exit;
}
@@ -1671,11 +1869,11 @@ page_validate(
break;
}
- if (rec_get_next_offs(rec) < FIL_PAGE_DATA
- || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
+ if (rec_get_next_offs(rec, comp) < FIL_PAGE_DATA
+ || rec_get_next_offs(rec, comp) >= UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Next record offset wrong %lu\n",
- (ulong) rec_get_next_offs(rec));
+ (ulong) rec_get_next_offs(rec, comp));
goto func_exit;
}
@@ -1683,9 +1881,15 @@ page_validate(
page_cur_move_to_next(&cur);
own_count++;
old_rec = rec;
+ /* set old_offsets to offsets; recycle offsets */
+ {
+ ulint* offs = old_offsets;
+ old_offsets = offsets;
+ offsets = offs;
+ }
}
- if (rec_get_n_owned(rec) == 0) {
+ if (rec_get_n_owned(rec, comp) == 0) {
fputs("InnoDB: n owned is zero\n", stderr);
goto func_exit;
}
@@ -1714,15 +1918,17 @@ page_validate(
rec = page_header_get_ptr(page, PAGE_FREE);
while (rec != NULL) {
- if (!page_rec_validate(rec)) {
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ if (!page_rec_validate(rec, offsets)) {
goto func_exit;
}
count++;
- offs = rec_get_start(rec) - page;
+ offs = rec_get_start(rec, offsets) - page;
- for (i = 0; i < rec_get_size(rec); i++) {
+ for (i = 0; i < rec_offs_size(offsets); i++) {
if (buf[offs + i] != 0) {
fputs(
@@ -1736,9 +1942,9 @@ page_validate(
rec = page_rec_get_next(rec);
}
- if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
+ if (page_dir_get_n_heap(page) != count + 1) {
fprintf(stderr, "InnoDB: N heap is wrong %lu %lu\n",
- (ulong) page_header_get_field(page, PAGE_N_HEAP),
+ (ulong) page_dir_get_n_heap(page),
(ulong) count + 1);
goto func_exit;
}
@@ -1775,7 +1981,7 @@ page_find_rec_with_heap_no(
page_cur_set_before_first(page, &cur);
for (;;) {
- if (rec_get_heap_no(cur.rec) == heap_no) {
+ if (rec_get_heap_no(cur.rec, page_is_comp(page)) == heap_no) {
return(cur.rec);
}
diff --git a/innobase/pars/lexyy.c b/innobase/pars/lexyy.c
index 0112f618533..1145ca295e7 100644
--- a/innobase/pars/lexyy.c
+++ b/innobase/pars/lexyy.c
@@ -616,6 +616,9 @@ How to make the InnoDB parser and lexer C files:
7. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c
(Needed for AIX)
+8. Add a type cast to int to the assignment below the comment
+ 'need more input.' (Removes a warning on Win64)
+
These instructions seem to work at least with bison-1.28 and flex-2.5.4 on
Linux.
*******************************************************/
@@ -2114,7 +2117,7 @@ static int input()
else
{ /* need more input */
- int offset = yy_c_buf_p - yytext_ptr;
+ int offset = (int) (yy_c_buf_p - yytext_ptr);
++yy_c_buf_p;
switch ( yy_get_next_buffer() )
diff --git a/innobase/pars/pars0lex.l b/innobase/pars/pars0lex.l
index 811057d48a1..e481634f77e 100644
--- a/innobase/pars/pars0lex.l
+++ b/innobase/pars/pars0lex.l
@@ -31,6 +31,9 @@ How to make the InnoDB parser and lexer C files:
7. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c
(Needed for AIX)
+8. Add a type cast to int to the assignment below the comment
+ 'need more input.' (Removes a warning on Win64)
+
These instructions seem to work at least with bison-1.28 and flex-2.5.4 on
Linux.
*******************************************************/
diff --git a/innobase/pars/pars0pars.c b/innobase/pars/pars0pars.c
index 16d630dd318..c62184abd85 100644
--- a/innobase/pars/pars0pars.c
+++ b/innobase/pars/pars0pars.c
@@ -1514,8 +1514,11 @@ pars_create_table(
n_cols = que_node_list_get_len(column_defs);
- table = dict_mem_table_create(table_sym->name, 0, n_cols);
-
+ /* As the InnoDB SQL parser is for internal use only,
+ for creating some system tables, this function will only
+ create tables in the old (not compact) record format. */
+ table = dict_mem_table_create(table_sym->name, 0, n_cols, FALSE);
+
if (not_fit_in_memory != NULL) {
table->does_not_fit_in_memory = TRUE;
}
diff --git a/innobase/pars/pars0sym.c b/innobase/pars/pars0sym.c
index 194e6677183..8ade5579e47 100644
--- a/innobase/pars/pars0sym.c
+++ b/innobase/pars/pars0sym.c
@@ -220,7 +220,7 @@ sym_tab_add_id(
node->resolved = FALSE;
node->indirection = NULL;
- node->name = mem_heap_strdupl(sym_tab->heap, name, len + 1);
+ node->name = mem_heap_strdupl(sym_tab->heap, (char*) name, len + 1);
node->name_len = len;
UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);
diff --git a/innobase/que/que0que.c b/innobase/que/que0que.c
index 22878dec27f..a0a6adf9b83 100644
--- a/innobase/que/que0que.c
+++ b/innobase/que/que0que.c
@@ -163,6 +163,7 @@ que_thr_create(
thr->run_node = NULL;
thr->resource = 0;
+ thr->lock_state = QUE_THR_LOCK_NOLOCK;
UT_LIST_ADD_LAST(thrs, parent->thrs, thr);
diff --git a/innobase/read/read0read.c b/innobase/read/read0read.c
index 889612deef4..06349c1fd39 100644
--- a/innobase/read/read0read.c
+++ b/innobase/read/read0read.c
@@ -153,10 +153,11 @@ read_view_open_now(
/* No active transaction should be visible, except cr_trx */
while (trx) {
- if (trx != cr_trx && trx->conc_state == TRX_ACTIVE) {
+ if (trx != cr_trx && (trx->conc_state == TRX_ACTIVE ||
+ trx->conc_state == TRX_PREPARED)) {
read_view_set_nth_trx_id(view, n, trx->id);
-
+
n++;
/* NOTE that a transaction whose trx number is <
@@ -164,7 +165,7 @@ read_view_open_now(
in the middle of its commit! Note that when a
transaction starts, we initialize trx->no to
ut_dulint_max. */
-
+
if (ut_dulint_cmp(view->low_limit_no, trx->no) > 0) {
view->low_limit_no = trx->no;
@@ -211,15 +212,16 @@ read_view_close_for_mysql(
/*======================*/
trx_t* trx) /* in: trx which has a read view */
{
- ut_a(trx->read_view);
+ ut_a(trx->global_read_view);
mutex_enter(&kernel_mutex);
- read_view_close(trx->read_view);
+ read_view_close(trx->global_read_view);
- mem_heap_empty(trx->read_view_heap);
+ mem_heap_empty(trx->global_read_view_heap);
trx->read_view = NULL;
+ trx->global_read_view = NULL;
mutex_exit(&kernel_mutex);
}
@@ -257,3 +259,148 @@ read_view_print(
(ulong) ut_dulint_get_low(read_view_get_nth_trx_id(view, i)));
}
}
+
+/*************************************************************************
+Create a consistent cursor view for mysql to be used in cursors. In this
+consistent read view modifications done by the creating transaction or future
+transactions are not visible. */
+
+cursor_view_t*
+read_cursor_view_create_for_mysql(
+/*==============================*/
+ trx_t* cr_trx) /* in: trx where cursor view is created */
+{
+ cursor_view_t* curview;
+ read_view_t* view;
+ mem_heap_t* heap;
+ trx_t* trx;
+ ulint n;
+
+ ut_a(cr_trx);
+
+ /* Use larger heap than in trx_create when creating a read_view
+ because cursors are quite long. */
+
+ heap = mem_heap_create(512);
+
+ curview = (cursor_view_t*) mem_heap_alloc(heap, sizeof(cursor_view_t));
+ curview->heap = heap;
+
+ /* Drop cursor tables from consideration when evaluating the need of
+ auto-commit */
+ curview->n_mysql_tables_in_use = cr_trx->n_mysql_tables_in_use;
+ cr_trx->n_mysql_tables_in_use = 0;
+
+ mutex_enter(&kernel_mutex);
+
+ curview->read_view = read_view_create_low(
+ UT_LIST_GET_LEN(trx_sys->trx_list),
+ curview->heap);
+
+ view = curview->read_view;
+ view->creator = cr_trx;
+
+ /* No future transactions should be visible in the view */
+
+ view->low_limit_no = trx_sys->max_trx_id;
+ view->low_limit_id = view->low_limit_no;
+
+ view->can_be_too_old = FALSE;
+
+ n = 0;
+ trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
+
+ /* No active transaction should be visible, except cr_trx.
+ This is quick fix for a bug 12456 and needs to be fixed when
+ semi-consistent high-granularity read view is implemented. */
+
+ while (trx) {
+ if (trx != cr_trx && (trx->conc_state == TRX_ACTIVE ||
+ trx->conc_state == TRX_PREPARED)) {
+
+ read_view_set_nth_trx_id(view, n, trx->id);
+
+ n++;
+
+ /* NOTE that a transaction whose trx number is <
+ trx_sys->max_trx_id can still be active, if it is
+ in the middle of its commit! Note that when a
+ transaction starts, we initialize trx->no to
+ ut_dulint_max. */
+
+ if (ut_dulint_cmp(view->low_limit_no, trx->no) > 0) {
+
+ view->low_limit_no = trx->no;
+ }
+ }
+
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ }
+
+ view->n_trx_ids = n;
+
+ if (n > 0) {
+ /* The last active transaction has the smallest id: */
+ view->up_limit_id = read_view_get_nth_trx_id(view, n - 1);
+ } else {
+ view->up_limit_id = view->low_limit_id;
+ }
+
+ UT_LIST_ADD_FIRST(view_list, trx_sys->view_list, view);
+
+ mutex_exit(&kernel_mutex);
+
+ return(curview);
+}
+
+/*************************************************************************
+Close a given consistent cursor view for mysql and restore global read view
+back to a transaction read view. */
+
+void
+read_cursor_view_close_for_mysql(
+/*=============================*/
+ trx_t* trx, /* in: trx */
+ cursor_view_t* curview)/* in: cursor view to be closed */
+{
+ ut_a(curview);
+ ut_a(curview->read_view);
+ ut_a(curview->heap);
+
+ /* Add cursor's tables to the global count of active tables that
+ belong to this transaction */
+ trx->n_mysql_tables_in_use += curview->n_mysql_tables_in_use;
+
+ mutex_enter(&kernel_mutex);
+
+ read_view_close(curview->read_view);
+ trx->read_view = trx->global_read_view;
+
+ mutex_exit(&kernel_mutex);
+
+ mem_heap_free(curview->heap);
+}
+
+/*************************************************************************
+This function sets a given consistent cursor view to a transaction
+read view if given consistent cursor view is not NULL. Otherwise, function
+restores a global read view to a transaction read view. */
+
+void
+read_cursor_set_for_mysql(
+/*======================*/
+ trx_t* trx, /* in: transaction where cursor is set */
+ cursor_view_t* curview)/* in: consistent cursor view to be set */
+{
+ ut_a(trx);
+
+ mutex_enter(&kernel_mutex);
+
+ if (UNIV_LIKELY(curview != NULL)) {
+ trx->read_view = curview->read_view;
+ } else {
+ trx->read_view = trx->global_read_view;
+ }
+
+ mutex_exit(&kernel_mutex);
+}
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index f2dc8a7021a..7c33476fb9e 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -51,6 +51,7 @@ cmp_debug_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields);/* in/out: number of already
completely matched fields; when function
returns, contains the value for current
@@ -319,7 +320,7 @@ cmp_data_data_slow(
|| (cur_type->mtype == DATA_BLOB
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
&& dtype_get_charset_coll(cur_type->prtype) !=
- data_mysql_latin1_swedish_charset_coll)) {
+ DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
return(cmp_whole_field(cur_type,
data1, (unsigned) len1,
@@ -412,6 +413,7 @@ cmp_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns,
contains the value for current comparison */
@@ -441,12 +443,27 @@ cmp_dtuple_rec_with_match(
ut_ad(dtuple && rec && matched_fields && matched_bytes);
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
cur_field = *matched_fields;
cur_bytes = *matched_bytes;
ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
- ut_ad(cur_field <= rec_get_n_fields(rec));
+ ut_ad(cur_field <= rec_offs_n_fields(offsets));
+
+ if (cur_bytes == 0 && cur_field == 0) {
+ ulint rec_info = rec_get_info_bits(rec,
+ rec_offs_comp(offsets));
+ ulint tup_info = dtuple_get_info_bits(dtuple);
+
+ if (rec_info & REC_INFO_MIN_REC_FLAG) {
+ ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
+ goto order_resolved;
+ } else if (tup_info & REC_INFO_MIN_REC_FLAG) {
+ ret = -1;
+ goto order_resolved;
+ }
+ }
/* Match fields in a loop; stop if we run out of fields in dtuple
or find an externally stored field */
@@ -458,39 +475,16 @@ cmp_dtuple_rec_with_match(
dtuple_f_len = dfield_get_len(dtuple_field);
- rec_b_ptr = rec_get_nth_field(rec, cur_field, &rec_f_len);
+ rec_b_ptr = rec_get_nth_field(rec, offsets,
+ cur_field, &rec_f_len);
/* If we have matched yet 0 bytes, it may be that one or
both the fields are SQL null, or the record or dtuple may be
the predefined minimum record, or the field is externally
stored */
- if (cur_bytes == 0) {
- if (cur_field == 0) {
-
- if (rec_get_info_bits(rec)
- & REC_INFO_MIN_REC_FLAG) {
-
- if (dtuple_get_info_bits(dtuple)
- & REC_INFO_MIN_REC_FLAG) {
-
- ret = 0;
- } else {
- ret = 1;
- }
-
- goto order_resolved;
- }
-
- if (dtuple_get_info_bits(dtuple)
- & REC_INFO_MIN_REC_FLAG) {
- ret = -1;
-
- goto order_resolved;
- }
- }
-
- if (rec_get_nth_field_extern_bit(rec, cur_field)) {
+ if (UNIV_LIKELY(cur_bytes == 0)) {
+ if (rec_offs_nth_extern(offsets, cur_field)) {
/* We do not compare to an externally
stored field */
@@ -499,24 +493,20 @@ cmp_dtuple_rec_with_match(
goto order_resolved;
}
- if (dtuple_f_len == UNIV_SQL_NULL
- || rec_f_len == UNIV_SQL_NULL) {
-
- if (dtuple_f_len == rec_f_len) {
+ if (dtuple_f_len == UNIV_SQL_NULL) {
+ if (rec_f_len == UNIV_SQL_NULL) {
goto next_field;
}
- if (rec_f_len == UNIV_SQL_NULL) {
- /* We define the SQL null to be the
- smallest possible value of a field
- in the alphabetical order */
-
- ret = 1;
- } else {
- ret = -1;
- }
+ ret = -1;
+ goto order_resolved;
+ } else if (rec_f_len == UNIV_SQL_NULL) {
+ /* We define the SQL null to be the
+ smallest possible value of a field
+ in the alphabetical order */
+ ret = 1;
goto order_resolved;
}
}
@@ -525,7 +515,7 @@ cmp_dtuple_rec_with_match(
|| (cur_type->mtype == DATA_BLOB
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
&& dtype_get_charset_coll(cur_type->prtype) !=
- data_mysql_latin1_swedish_charset_coll)) {
+ DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
ret = cmp_whole_field(
cur_type,
@@ -550,7 +540,7 @@ cmp_dtuple_rec_with_match(
/* Compare then the fields */
for (;;) {
- if (rec_f_len <= cur_bytes) {
+ if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
if (dtuple_f_len <= cur_bytes) {
goto next_field;
@@ -567,7 +557,7 @@ cmp_dtuple_rec_with_match(
rec_byte = *rec_b_ptr;
}
- if (dtuple_f_len <= cur_bytes) {
+ if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
dtuple_byte = dtype_get_pad_char(cur_type);
if (dtuple_byte == ULINT_UNDEFINED) {
@@ -595,14 +585,16 @@ cmp_dtuple_rec_with_match(
rec_byte = cmp_collate(rec_byte);
dtuple_byte = cmp_collate(dtuple_byte);
}
-
- if (dtuple_byte > rec_byte) {
- ret = 1;
- goto order_resolved;
- } else if (dtuple_byte < rec_byte) {
- ret = -1;
- goto order_resolved;
+ ret = dtuple_byte - rec_byte;
+ if (UNIV_UNLIKELY(ret)) {
+ if (ret < 0) {
+ ret = -1;
+ goto order_resolved;
+ } else {
+ ret = 1;
+ goto order_resolved;
+ }
}
next_byte:
/* Next byte */
@@ -622,7 +614,7 @@ cmp_dtuple_rec_with_match(
up to the common fields */
order_resolved:
ut_ad((ret >= - 1) && (ret <= 1));
- ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec,
+ ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields));
ut_ad(*matched_fields == cur_field); /* In the debug version, the
above cmp_debug_... sets
@@ -643,13 +635,15 @@ cmp_dtuple_rec(
less than rec, respectively; see the comments
for cmp_dtuple_rec_with_match */
dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint matched_fields = 0;
ulint matched_bytes = 0;
- return(cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
- &matched_bytes));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
+ &matched_fields, &matched_bytes));
}
/******************************************************************
@@ -660,22 +654,24 @@ ibool
cmp_dtuple_is_prefix_of_rec(
/*========================*/
/* out: TRUE if prefix */
- dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec) /* in: physical record */
+ dtuple_t* dtuple, /* in: data tuple */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_fields;
ulint matched_fields = 0;
ulint matched_bytes = 0;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
n_fields = dtuple_get_n_fields(dtuple);
- if (n_fields > rec_get_n_fields(rec)) {
+ if (n_fields > rec_offs_n_fields(offsets)) {
return(FALSE);
}
- cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
- &matched_bytes);
+ cmp_dtuple_rec_with_match(dtuple, rec, offsets,
+ &matched_fields, &matched_bytes);
if (matched_fields == n_fields) {
return(TRUE);
@@ -690,42 +686,6 @@ cmp_dtuple_is_prefix_of_rec(
return(FALSE);
}
-/******************************************************************
-Compares a prefix of a data tuple to a prefix of a physical record for
-equality. If there are less fields in rec than parameter n_fields, FALSE
-is returned. NOTE that n_fields_cmp of dtuple does not affect this
-comparison. */
-
-ibool
-cmp_dtuple_rec_prefix_equal(
-/*========================*/
- /* out: TRUE if equal */
- dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec, /* in: physical record */
- ulint n_fields) /* in: number of fields which should be
- compared; must not exceed the number of
- fields in dtuple */
-{
- ulint matched_fields = 0;
- ulint matched_bytes = 0;
-
- ut_ad(n_fields <= dtuple_get_n_fields(dtuple));
-
- if (rec_get_n_fields(rec) < n_fields) {
-
- return(FALSE);
- }
-
- cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
- &matched_bytes);
- if (matched_fields >= n_fields) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
/*****************************************************************
This function is used to compare two physical records. Only the common
first fields are compared, and if an externally stored field is
@@ -739,6 +699,8 @@ cmp_rec_rec_with_match(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index, /* in: data dictionary index */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when the function returns,
@@ -765,17 +727,21 @@ cmp_rec_rec_with_match(
ulint cur_bytes; /* number of already matched bytes in current
field */
int ret = 3333; /* return value */
+ ulint comp;
ut_ad(rec1 && rec2 && index);
+ ut_ad(rec_offs_validate(rec1, index, offsets1));
+ ut_ad(rec_offs_validate(rec2, index, offsets2));
+ ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
- rec1_n_fields = rec_get_n_fields(rec1);
- rec2_n_fields = rec_get_n_fields(rec2);
+ comp = rec_offs_comp(offsets1);
+ rec1_n_fields = rec_offs_n_fields(offsets1);
+ rec2_n_fields = rec_offs_n_fields(offsets2);
cur_field = *matched_fields;
cur_bytes = *matched_bytes;
- /* Match fields in a loop; stop if we run out of fields in either
- record */
+ /* Match fields in a loop */
while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
@@ -787,17 +753,19 @@ cmp_rec_rec_with_match(
dict_index_get_nth_field(index, cur_field)));
}
- rec1_b_ptr = rec_get_nth_field(rec1, cur_field, &rec1_f_len);
- rec2_b_ptr = rec_get_nth_field(rec2, cur_field, &rec2_f_len);
-
+ rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
+ cur_field, &rec1_f_len);
+ rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
+ cur_field, &rec2_f_len);
+
if (cur_bytes == 0) {
if (cur_field == 0) {
/* Test if rec is the predefined minimum
record */
- if (rec_get_info_bits(rec1)
+ if (rec_get_info_bits(rec1, comp)
& REC_INFO_MIN_REC_FLAG) {
- if (rec_get_info_bits(rec2)
+ if (rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG) {
ret = 0;
} else {
@@ -806,7 +774,7 @@ cmp_rec_rec_with_match(
goto order_resolved;
- } else if (rec_get_info_bits(rec2)
+ } else if (rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG) {
ret = 1;
@@ -815,8 +783,8 @@ cmp_rec_rec_with_match(
}
}
- if (rec_get_nth_field_extern_bit(rec1, cur_field)
- || rec_get_nth_field_extern_bit(rec2, cur_field)) {
+ if (rec_offs_nth_extern(offsets1, cur_field)
+ || rec_offs_nth_extern(offsets2, cur_field)) {
/* We do not compare to an externally
stored field */
@@ -851,7 +819,7 @@ cmp_rec_rec_with_match(
|| (cur_type->mtype == DATA_BLOB
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
&& dtype_get_charset_coll(cur_type->prtype) !=
- data_mysql_latin1_swedish_charset_coll)) {
+ DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
ret = cmp_whole_field(cur_type,
rec1_b_ptr, (unsigned) rec1_f_len,
@@ -971,6 +939,7 @@ cmp_debug_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields) /* in/out: number of already
completely matched fields; when function
returns, contains the value for current
@@ -990,21 +959,19 @@ cmp_debug_dtuple_rec_with_match(
ut_ad(dtuple && rec && matched_fields);
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
- ut_ad(*matched_fields <= rec_get_n_fields(rec));
+ ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
cur_field = *matched_fields;
if (cur_field == 0) {
- if (rec_get_info_bits(rec) & REC_INFO_MIN_REC_FLAG) {
+ if (rec_get_info_bits(rec, rec_offs_comp(offsets))
+ & REC_INFO_MIN_REC_FLAG) {
- if (dtuple_get_info_bits(dtuple)
- & REC_INFO_MIN_REC_FLAG) {
- ret = 0;
- } else {
- ret = 1;
- }
+ ret = !(dtuple_get_info_bits(dtuple)
+ & REC_INFO_MIN_REC_FLAG);
goto order_resolved;
}
@@ -1027,9 +994,10 @@ cmp_debug_dtuple_rec_with_match(
dtuple_f_data = dfield_get_data(dtuple_field);
dtuple_f_len = dfield_get_len(dtuple_field);
- rec_f_data = rec_get_nth_field(rec, cur_field, &rec_f_len);
+ rec_f_data = rec_get_nth_field(rec, offsets,
+ cur_field, &rec_f_len);
- if (rec_get_nth_field_extern_bit(rec, cur_field)) {
+ if (rec_offs_nth_extern(offsets, cur_field)) {
/* We do not compare to an externally stored field */
ret = 0;
diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c
index 1db89241dff..fbc33aea669 100644
--- a/innobase/rem/rem0rec.c
+++ b/innobase/rem/rem0rec.c
@@ -15,8 +15,8 @@ Created 5/30/1994 Heikki Tuuri
#include "mtr0mtr.h"
#include "mtr0log.h"
-/* PHYSICAL RECORD
- ===============
+/* PHYSICAL RECORD (OLD STYLE)
+ ===========================
The physical record, which is the data type of all the records
found in index pages of the database, has the following format
@@ -39,7 +39,7 @@ represented on a higher text line):
| 10 bits giving the number of fields in this record |
| 1 bit which is set to 1 if the offsets above are given in
one byte format, 0 if in two byte format |
-| two bytes giving the pointer to the next record in the page |
+| two bytes giving an absolute pointer to the next record in the page |
ORIGIN of the record
| first field of data |
...
@@ -55,9 +55,50 @@ The offsets of the data fields are given as one-byte
(if there are less than 127 bytes of data in the record)
or two-byte unsigned integers. The most significant bit
is not part of the offset, instead it indicates the SQL-null
-if the bit is set to 1.
+if the bit is set to 1. */
-CANONICAL COORDINATES. A record can be seen as a single
+/* PHYSICAL RECORD (NEW STYLE)
+ ===========================
+
+The physical record, which is the data type of all the records
+found in index pages of the database, has the following format
+(lower addresses and more significant bits inside a byte are below
+represented on a higher text line):
+
+| length of the last non-null variable-length field of data:
+ if the maximum length is 255, one byte; otherwise,
+ 0xxxxxxx (one byte, length=0..127), or 1exxxxxxxxxxxxxx (two bytes,
+ length=128..16383, extern storage flag) |
+...
+| length of first variable-length field of data |
+| SQL-null flags (1 bit per nullable field), padded to full bytes |
+| 4 bits used to delete mark a record, and mark a predefined
+ minimum record in alphabetical order |
+| 4 bits giving the number of records owned by this record
+ (this term is explained in page0page.h) |
+| 13 bits giving the order number of this record in the
+ heap of the index page |
+| 3 bits record type: 000=conventional, 001=node pointer (inside B-tree),
+ 010=infimum, 011=supremum, 1xx=reserved |
+| two bytes giving a relative pointer to the next record in the page |
+ORIGIN of the record
+| first field of data |
+...
+| last field of data |
+
+The origin of the record is the start address of the first field
+of data. The offsets are given relative to the origin.
+The offsets of the data fields are stored in an inverted
+order because then the offset of the first fields are near the
+origin, giving maybe a better processor cache hit rate in searches.
+
+The offsets of the data fields are given as one-byte
+(if there are less than 127 bytes of data in the record)
+or two-byte unsigned integers. The most significant bit
+is not part of the offset, instead it indicates the SQL-null
+if the bit is set to 1. */
+
+/* CANONICAL COORDINATES. A record can be seen as a single
string of 'characters' in the following way: catenate the bytes
in each field, in the order of fields. An SQL-null field
is taken to be an empty sequence of bytes. Then after
@@ -86,13 +127,250 @@ the corresponding canonical strings have the same property. */
ulint rec_dummy; /* this is used to fool compiler in
rec_validate */
+/*******************************************************************
+Validates the consistency of an old-style physical record. */
+static
+ibool
+rec_validate_old(
+/*=============*/
+ /* out: TRUE if ok */
+ rec_t* rec); /* in: physical record */
+
+/**********************************************************
+The following function determines the offsets to each field in the
+record. The offsets are written to a previously allocated array of
+ulint, where rec_offs_n_fields(offsets) has been initialized to the
+number of fields in the record. The rest of the array will be
+initialized by this function. rec_offs_base(offsets)[0] will be set
+to the extra size (if REC_OFFS_COMPACT is set, the record is in the
+new format), and rec_offs_base(offsets)[1..n_fields] will be set to
+offsets past the end of fields 0..n_fields, or to the beginning of
+fields 1..n_fields+1. When the high-order bit of the offset at [i+1]
+is set (REC_OFFS_SQL_NULL), the field i is NULL. When the second
+high-order bit of the offset at [i+1] is set (REC_OFFS_EXTERNAL), the
+field i is being stored externally. */
+static
+void
+rec_init_offsets(
+/*=============*/
+ /* out: the offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets)/* in/out: array of offsets;
+ in: n=rec_offs_n_fields(offsets) */
+{
+ ulint i = 0;
+ ulint offs;
+
+ rec_offs_make_valid(rec, index, offsets);
+
+ if (UNIV_LIKELY(index->table->comp)) {
+ const byte* nulls;
+ const byte* lens;
+ dict_field_t* field;
+ ulint null_mask;
+ ulint status = rec_get_status(rec);
+ ulint n_node_ptr_field = ULINT_UNDEFINED;
+
+ switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* the field is 8 bytes long */
+ rec_offs_base(offsets)[0] =
+ REC_N_NEW_EXTRA_BYTES | REC_OFFS_COMPACT;
+ rec_offs_base(offsets)[1] = 8;
+ return;
+ case REC_STATUS_NODE_PTR:
+ n_node_ptr_field =
+ dict_index_get_n_unique_in_tree(index);
+ break;
+ case REC_STATUS_ORDINARY:
+ break;
+ }
+
+ nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ lens = nulls - (index->n_nullable + 7) / 8;
+ offs = 0;
+ null_mask = 1;
+
+ /* read the lengths of fields 0..n */
+ do {
+ ulint len;
+ if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
+ len = offs += 4;
+ goto resolved;
+ }
+
+ field = dict_index_get_nth_field(index, i);
+ if (!(dtype_get_prtype(dict_col_get_type(
+ dict_field_get_col(field)))
+ & DATA_NOT_NULL)) {
+ /* nullable field => read the null flag */
+
+ if (UNIV_UNLIKELY(!(byte) null_mask)) {
+ nulls--;
+ null_mask = 1;
+ }
+
+ if (*nulls & null_mask) {
+ null_mask <<= 1;
+ /* No length is stored for NULL fields.
+ We do not advance offs, and we set
+ the length to zero and enable the
+ SQL NULL flag in offsets[]. */
+ len = offs | REC_OFFS_SQL_NULL;
+ goto resolved;
+ }
+ null_mask <<= 1;
+ }
+
+ if (UNIV_UNLIKELY(!field->fixed_len)) {
+ /* Variable-length field: read the length */
+ dtype_t* type = dict_col_get_type(
+ dict_field_get_col(field));
+ len = *lens--;
+ if (UNIV_UNLIKELY(dtype_get_len(type) > 255)
+ || UNIV_UNLIKELY(dtype_get_mtype(type)
+ == DATA_BLOB)) {
+ if (len & 0x80) {
+ /* 1exxxxxxx xxxxxxxx */
+ len <<= 8;
+ len |= *lens--;
+
+ offs += len & 0x3fff;
+ if (UNIV_UNLIKELY(len
+ & 0x4000)) {
+ len = offs
+ | REC_OFFS_EXTERNAL;
+ } else {
+ len = offs;
+ }
+
+ goto resolved;
+ }
+ }
+
+ len = offs += len;
+ } else {
+ len = offs += field->fixed_len;
+ }
+ resolved:
+ rec_offs_base(offsets)[i + 1] = len;
+ } while (++i < rec_offs_n_fields(offsets));
+
+ *rec_offs_base(offsets) =
+ (rec - (lens + 1)) | REC_OFFS_COMPACT;
+ } else {
+ /* Old-style record: determine extra size and end offsets */
+ offs = REC_N_OLD_EXTRA_BYTES;
+ if (rec_get_1byte_offs_flag(rec)) {
+ offs += rec_offs_n_fields(offsets);
+ *rec_offs_base(offsets) = offs;
+ /* Determine offsets to fields */
+ do {
+ offs = rec_1_get_field_end_info(rec, i);
+ if (offs & REC_1BYTE_SQL_NULL_MASK) {
+ offs &= ~REC_1BYTE_SQL_NULL_MASK;
+ offs |= REC_OFFS_SQL_NULL;
+ }
+ rec_offs_base(offsets)[1 + i] = offs;
+ } while (++i < rec_offs_n_fields(offsets));
+ } else {
+ offs += 2 * rec_offs_n_fields(offsets);
+ *rec_offs_base(offsets) = offs;
+ /* Determine offsets to fields */
+ do {
+ offs = rec_2_get_field_end_info(rec, i);
+ if (offs & REC_2BYTE_SQL_NULL_MASK) {
+ offs &= ~REC_2BYTE_SQL_NULL_MASK;
+ offs |= REC_OFFS_SQL_NULL;
+ }
+ if (offs & REC_2BYTE_EXTERN_MASK) {
+ offs &= ~REC_2BYTE_EXTERN_MASK;
+ offs |= REC_OFFS_EXTERNAL;
+ }
+ rec_offs_base(offsets)[1 + i] = offs;
+ } while (++i < rec_offs_n_fields(offsets));
+ }
+ }
+}
+
+/**********************************************************
+The following function determines the offsets to each field
+in the record. It can reuse a previously returned array. */
+
+ulint*
+rec_get_offsets_func(
+/*=================*/
+ /* out: the new offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets,/* in: array consisting of offsets[0]
+ allocated elements, or an array from
+ rec_get_offsets(), or NULL */
+ ulint n_fields,/* in: maximum number of initialized fields
+ (ULINT_UNDEFINED if all fields) */
+ mem_heap_t** heap, /* in/out: memory heap */
+ const char* file, /* in: file name where called */
+ ulint line) /* in: line number where called */
+{
+ ulint n;
+ ulint size;
+
+ ut_ad(rec);
+ ut_ad(index);
+ ut_ad(heap);
+
+ if (UNIV_LIKELY(index->table->comp)) {
+ switch (UNIV_EXPECT(rec_get_status(rec),
+ REC_STATUS_ORDINARY)) {
+ case REC_STATUS_ORDINARY:
+ n = dict_index_get_n_fields(index);
+ break;
+ case REC_STATUS_NODE_PTR:
+ n = dict_index_get_n_unique_in_tree(index) + 1;
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* infimum or supremum record */
+ n = 1;
+ break;
+ default:
+ ut_error;
+ return(NULL);
+ }
+ } else {
+ n = rec_get_n_fields_old(rec);
+ }
+
+ if (UNIV_UNLIKELY(n_fields < n)) {
+ n = n_fields;
+ }
+
+ size = n + (1 + REC_OFFS_HEADER_SIZE);
+
+ if (UNIV_UNLIKELY(!offsets) ||
+ UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) {
+ if (!*heap) {
+ *heap = mem_heap_create_func(size * sizeof(ulint),
+ NULL, MEM_HEAP_DYNAMIC, file, line);
+ }
+ offsets = mem_heap_alloc(*heap, size * sizeof(ulint));
+ rec_offs_set_n_alloc(offsets, size);
+ }
+
+ rec_offs_set_n_fields(offsets, n);
+ rec_init_offsets(rec, index, offsets);
+ return(offsets);
+}
+
/****************************************************************
-The following function is used to get a pointer to the nth data field in a
-record. */
+The following function is used to get a pointer to the nth
+data field in an old-style record. */
byte*
-rec_get_nth_field(
-/*==============*/
+rec_get_nth_field_old(
+/*==================*/
/* out: pointer to the field */
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
@@ -103,9 +381,9 @@ rec_get_nth_field(
ulint next_os;
ut_ad(rec && len);
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- if (n > 1024) {
+ if (n > REC_MAX_N_FIELDS) {
fprintf(stderr, "Error: trying to access field %lu in rec\n",
(ulong) n);
ut_error;
@@ -150,8 +428,78 @@ rec_get_nth_field(
return(rec + os);
}
+/**************************************************************
+The following function returns the size of a data tuple when converted to
+a new-style physical record. */
+
+ulint
+rec_get_converted_size_new(
+/*=======================*/
+ /* out: size */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple) /* in: data tuple */
+{
+ ulint size = REC_N_NEW_EXTRA_BYTES
+ + (index->n_nullable + 7) / 8;
+ dict_field_t* field;
+ dtype_t* type;
+ ulint i;
+ ulint n_fields;
+ ut_ad(index && dtuple);
+ ut_ad(index->table->comp);
+
+ switch (dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) {
+ case REC_STATUS_ORDINARY:
+ n_fields = dict_index_get_n_fields(index);
+ ut_ad(n_fields == dtuple_get_n_fields(dtuple));
+ break;
+ case REC_STATUS_NODE_PTR:
+ n_fields = dict_index_get_n_unique_in_tree(index);
+ ut_ad(n_fields + 1 == dtuple_get_n_fields(dtuple));
+ ut_ad(dtuple_get_nth_field(dtuple, n_fields)->len == 4);
+ size += 4; /* child page number */
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* infimum or supremum record, 8 bytes */
+ return(size + 8); /* no extra data needed */
+ default:
+ ut_a(0);
+ return(ULINT_UNDEFINED);
+ }
+
+ /* read the lengths of fields 0..n */
+ for (i = 0; i < n_fields; i++) {
+ ulint len = dtuple_get_nth_field(dtuple, i)->len;
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ ut_ad(len != UNIV_SQL_NULL ||
+ !(dtype_get_prtype(type) & DATA_NOT_NULL));
+
+ if (len == UNIV_SQL_NULL) {
+ /* No length is stored for NULL fields. */
+ continue;
+ }
+
+ ut_ad(len <= dtype_get_len(type)
+ || dtype_get_mtype(type) == DATA_BLOB);
+ ut_ad(!field->fixed_len || len == field->fixed_len);
+
+ if (field->fixed_len) {
+ } else if (len < 128 || (dtype_get_len(type) < 256
+ && dtype_get_mtype(type) != DATA_BLOB)) {
+ size++;
+ } else {
+ size += 2;
+ }
+ size += len;
+ }
+
+ return(size);
+}
+
/***************************************************************
-Sets the value of the ith field SQL null bit. */
+Sets the value of the ith field SQL null bit of an old-style record. */
void
rec_set_nth_field_null_bit(
@@ -189,12 +537,12 @@ rec_set_nth_field_null_bit(
}
/***************************************************************
-Sets the value of the ith field extern storage bit. */
+Sets the value of the ith field extern storage bit of an old-style record. */
void
-rec_set_nth_field_extern_bit(
-/*=========================*/
- rec_t* rec, /* in: record */
+rec_set_nth_field_extern_bit_old(
+/*=============================*/
+ rec_t* rec, /* in: old-style record */
ulint i, /* in: ith field */
ibool val, /* in: value to set */
mtr_t* mtr) /* in: mtr holding an X-latch to the page where
@@ -204,7 +552,7 @@ rec_set_nth_field_extern_bit(
ulint info;
ut_a(!rec_get_1byte_offs_flag(rec));
- ut_a(i < rec_get_n_fields(rec));
+ ut_a(i < rec_get_n_fields_old(rec));
info = rec_2_get_field_end_info(rec, i);
@@ -215,36 +563,133 @@ rec_set_nth_field_extern_bit(
}
if (mtr) {
- mlog_write_ulint(rec - REC_N_EXTRA_BYTES - 2 * (i + 1), info,
- MLOG_2BYTES, mtr);
+ mlog_write_ulint(rec - REC_N_OLD_EXTRA_BYTES - 2 * (i + 1),
+ info, MLOG_2BYTES, mtr);
} else {
rec_2_set_field_end_info(rec, i, info);
}
}
/***************************************************************
+Sets the value of the ith field extern storage bit of a new-style record. */
+
+void
+rec_set_nth_field_extern_bit_new(
+/*=============================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint ith, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
+{
+ byte* nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ byte* lens = nulls - (index->n_nullable + 7) / 8;
+ dict_field_t* field;
+ dtype_t* type;
+ ulint i;
+ ulint n_fields;
+ ulint null_mask = 1;
+ ut_ad(rec && index);
+ ut_ad(index->table->comp);
+ ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY);
+
+ n_fields = dict_index_get_n_fields(index);
+
+ ut_ad(ith < n_fields);
+
+ /* read the lengths of fields 0..n */
+ for (i = 0; i < n_fields; i++) {
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ if (UNIV_UNLIKELY(!(byte) null_mask)) {
+ nulls--;
+ null_mask = 1;
+ }
+
+ if (*nulls & null_mask) {
+ null_mask <<= 1;
+ /* NULL fields cannot be external. */
+ ut_ad(i != ith);
+ continue;
+ }
+
+ null_mask <<= 1;
+ }
+ if (field->fixed_len) {
+ /* fixed-length fields cannot be external
+ (Fixed-length fields longer than
+ DICT_MAX_COL_PREFIX_LEN will be treated as
+ variable-length ones in dict_index_add_col().) */
+ ut_ad(i != ith);
+ continue;
+ }
+ lens--;
+ if (dtype_get_len(type) > 255
+ || dtype_get_mtype(type) == DATA_BLOB) {
+ ulint len = lens[1];
+ if (len & 0x80) { /* 1exxxxxx: 2-byte length */
+ if (i == ith) {
+ if (!val == !(len & 0x40)) {
+ return; /* no change */
+ }
+ /* toggle the extern bit */
+ len ^= 0x40;
+ if (mtr) {
+ mlog_write_ulint(lens + 1, len,
+ MLOG_1BYTE, mtr);
+ } else {
+ lens[1] = (byte) len;
+ }
+ return;
+ }
+ lens--;
+ } else {
+ /* short fields cannot be external */
+ ut_ad(i != ith);
+ }
+ } else {
+ /* short fields cannot be external */
+ ut_ad(i != ith);
+ }
+ }
+}
+
+/***************************************************************
Sets TRUE the extern storage bits of fields mentioned in an array. */
void
rec_set_field_extern_bits(
/*======================*/
- rec_t* rec, /* in: record */
- ulint* vec, /* in: array of field numbers */
- ulint n_fields, /* in: number of fields numbers */
- mtr_t* mtr) /* in: mtr holding an X-latch to the page
- where rec is, or NULL; in the NULL case we
- do not write to log about the change */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ const ulint* vec, /* in: array of field numbers */
+ ulint n_fields,/* in: number of fields numbers */
+ mtr_t* mtr) /* in: mtr holding an X-latch to the
+ page where rec is, or NULL;
+ in the NULL case we do not write
+ to log about the change */
{
ulint i;
-
- for (i = 0; i < n_fields; i++) {
- rec_set_nth_field_extern_bit(rec, vec[i], TRUE, mtr);
+
+ if (UNIV_LIKELY(index->table->comp)) {
+ for (i = 0; i < n_fields; i++) {
+ rec_set_nth_field_extern_bit_new(rec, index, vec[i],
+ TRUE, mtr);
+ }
+ } else {
+ for (i = 0; i < n_fields; i++) {
+ rec_set_nth_field_extern_bit_old(rec, vec[i],
+ TRUE, mtr);
+ }
}
}
/***************************************************************
-Sets a record field to SQL null. The physical size of the field is not
-changed. */
+Sets an old-style record field to SQL null.
+The physical size of the field is not changed. */
void
rec_set_nth_field_sql_null(
@@ -262,20 +707,20 @@ rec_set_nth_field_sql_null(
}
/*************************************************************
-Builds a physical record out of a data tuple and stores it beginning from
-address destination. */
-
-rec_t*
-rec_convert_dtuple_to_rec_low(
+Builds an old-style physical record out of a data tuple and
+stores it beginning from the start of the given buffer. */
+static
+rec_t*
+rec_convert_dtuple_to_rec_old(
/*==========================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple, /* in: data tuple */
- ulint data_size) /* in: data size of dtuple */
+ /* out: pointer to the origin of
+ physical record */
+ byte* buf, /* in: start address of the physical record */
+ dtuple_t* dtuple)/* in: data tuple */
{
dfield_t* field;
ulint n_fields;
+ ulint data_size;
rec_t* rec;
ulint end_offset;
ulint ored_offset;
@@ -283,24 +728,25 @@ rec_convert_dtuple_to_rec_low(
ulint len;
ulint i;
- ut_ad(destination && dtuple);
+ ut_ad(buf && dtuple);
ut_ad(dtuple_validate(dtuple));
ut_ad(dtuple_check_typed(dtuple));
- ut_ad(dtuple_get_data_size(dtuple) == data_size);
n_fields = dtuple_get_n_fields(dtuple);
+ data_size = dtuple_get_data_size(dtuple);
ut_ad(n_fields > 0);
/* Calculate the offset of the origin in the physical record */
- rec = destination + rec_get_converted_extra_size(data_size, n_fields);
+ rec = buf + rec_get_converted_extra_size(data_size, n_fields);
/* Store the number of fields */
- rec_set_n_fields(rec, n_fields);
+ rec_set_n_fields_old(rec, n_fields);
/* Set the info bits of the record */
- rec_set_info_bits(rec, dtuple_get_info_bits(dtuple));
+ rec_set_info_bits(rec, FALSE,
+ dtuple_get_info_bits(dtuple) & REC_INFO_BITS_MASK);
/* Store the data and the offsets */
@@ -361,8 +807,218 @@ rec_convert_dtuple_to_rec_low(
}
}
- ut_ad(rec_validate(rec));
+ return(rec);
+}
+
+/*************************************************************
+Builds a new-style physical record out of a data tuple and
+stores it beginning from the start of the given buffer. */
+static
+rec_t*
+rec_convert_dtuple_to_rec_new(
+/*==========================*/
+ /* out: pointer to the origin
+ of physical record */
+ byte* buf, /* in: start address of the physical record */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple) /* in: data tuple */
+{
+ dfield_t* field;
+ dtype_t* type;
+ rec_t* rec = buf + REC_N_NEW_EXTRA_BYTES;
+ byte* end;
+ byte* nulls;
+ byte* lens;
+ ulint len;
+ ulint i;
+ ulint n_node_ptr_field;
+ ulint fixed_len;
+ ulint null_mask = 1;
+ const ulint n_fields = dtuple_get_n_fields(dtuple);
+ const ulint status = dtuple_get_info_bits(dtuple)
+ & REC_NEW_STATUS_MASK;
+ ut_ad(index->table->comp);
+
+ ut_ad(n_fields > 0);
+
+ /* Try to ensure that the memset() between the for() loops
+ completes fast. The address is not exact, but UNIV_PREFETCH
+ should never generate a memory fault. */
+ UNIV_PREFETCH_RW(rec - REC_N_NEW_EXTRA_BYTES - n_fields);
+ UNIV_PREFETCH_RW(rec);
+
+ switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
+ case REC_STATUS_ORDINARY:
+ ut_ad(n_fields <= dict_index_get_n_fields(index));
+ n_node_ptr_field = ULINT_UNDEFINED;
+ break;
+ case REC_STATUS_NODE_PTR:
+ ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1);
+ n_node_ptr_field = n_fields - 1;
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ ut_ad(n_fields == 1);
+ n_node_ptr_field = ULINT_UNDEFINED;
+ goto init;
+ default:
+ ut_a(0);
+ return(0);
+ }
+
+ /* Calculate the offset of the origin in the physical record.
+ We must loop over all fields to do this. */
+ rec += (index->n_nullable + 7) / 8;
+
+ for (i = 0; i < n_fields; i++) {
+ if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
+#ifdef UNIV_DEBUG
+ field = dtuple_get_nth_field(dtuple, i);
+ type = dfield_get_type(field);
+ ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
+ ut_ad(dfield_get_len(field) == 4);
+#endif /* UNIV_DEBUG */
+ goto init;
+ }
+ field = dtuple_get_nth_field(dtuple, i);
+ type = dfield_get_type(field);
+ len = dfield_get_len(field);
+ fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
+
+ if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ if (len == UNIV_SQL_NULL)
+ continue;
+ }
+ /* only nullable fields can be null */
+ ut_ad(len != UNIV_SQL_NULL);
+ if (fixed_len) {
+ ut_ad(len == fixed_len);
+ } else {
+ ut_ad(len <= dtype_get_len(type)
+ || dtype_get_mtype(type) == DATA_BLOB);
+ rec++;
+ if (len >= 128 && (dtype_get_len(type) >= 256
+ || dtype_get_mtype(type) == DATA_BLOB)) {
+ rec++;
+ }
+ }
+ }
+
+init:
+ end = rec;
+ nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ lens = nulls - (index->n_nullable + 7) / 8;
+ /* clear the SQL-null flags */
+ memset (lens + 1, 0, nulls - lens);
+
+ /* Set the info bits of the record */
+ rec_set_status(rec, status);
+
+ rec_set_info_bits(rec, TRUE,
+ dtuple_get_info_bits(dtuple) & REC_INFO_BITS_MASK);
+
+ /* Store the data and the offsets */
+
+ for (i = 0; i < n_fields; i++) {
+ field = dtuple_get_nth_field(dtuple, i);
+ type = dfield_get_type(field);
+ len = dfield_get_len(field);
+
+ if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
+ ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
+ ut_ad(len == 4);
+ memcpy(end, dfield_get_data(field), len);
+ break;
+ }
+ fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
+
+ if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ /* nullable field */
+ ut_ad(index->n_nullable > 0);
+
+ if (UNIV_UNLIKELY(!(byte) null_mask)) {
+ nulls--;
+ null_mask = 1;
+ }
+
+ ut_ad(*nulls < null_mask);
+
+ /* set the null flag if necessary */
+ if (len == UNIV_SQL_NULL) {
+ *nulls |= null_mask;
+ null_mask <<= 1;
+ continue;
+ }
+
+ null_mask <<= 1;
+ }
+ /* only nullable fields can be null */
+ ut_ad(len != UNIV_SQL_NULL);
+ if (fixed_len) {
+ ut_ad(len == fixed_len);
+ } else {
+ ut_ad(len <= dtype_get_len(type)
+ || dtype_get_mtype(type) == DATA_BLOB);
+ if (len < 128 || (dtype_get_len(type) < 256
+ && dtype_get_mtype(type) != DATA_BLOB)) {
+ *lens-- = (byte) len;
+ }
+ else {
+ /* the extern bits will be set later */
+ ut_ad(len < 16384);
+ *lens-- = (byte) (len >> 8) | 0x80;
+ *lens-- = (byte) len;
+ }
+ }
+
+ memcpy(end, dfield_get_data(field), len);
+ end += len;
+ }
+
+ return(rec);
+}
+
+/*************************************************************
+Builds a physical record out of a data tuple and
+stores it beginning from the start of the given buffer. */
+
+rec_t*
+rec_convert_dtuple_to_rec(
+/*======================*/
+ /* out: pointer to the origin
+ of physical record */
+ byte* buf, /* in: start address of the
+ physical record */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple) /* in: data tuple */
+{
+ rec_t* rec;
+
+ ut_ad(buf && index && dtuple);
+ ut_ad(dtuple_validate(dtuple));
+ ut_ad(dtuple_check_typed(dtuple));
+ if (UNIV_LIKELY(index->table->comp)) {
+ rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple);
+ } else {
+ rec = rec_convert_dtuple_to_rec_old(buf, dtuple);
+ }
+
+#ifdef UNIV_DEBUG
+ {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ const ulint* offsets;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ offsets = rec_get_offsets(rec, index,
+ offsets_, ULINT_UNDEFINED, &heap);
+ ut_ad(rec_validate(rec, offsets));
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ }
+#endif /* UNIV_DEBUG */
return(rec);
}
@@ -375,6 +1031,7 @@ rec_copy_prefix_to_dtuple(
/*======================*/
dtuple_t* tuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
ulint n_fields, /* in: number of fields to copy */
mem_heap_t* heap) /* in: memory heap */
{
@@ -383,16 +1040,22 @@ rec_copy_prefix_to_dtuple(
ulint len;
byte* buf = NULL;
ulint i;
-
- ut_ad(rec_validate(rec));
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ offsets = rec_get_offsets(rec, index, offsets, n_fields, &heap);
+
+ ut_ad(rec_validate(rec, offsets));
ut_ad(dtuple_check_typed(tuple));
- dtuple_set_info_bits(tuple, rec_get_info_bits(rec));
+ dtuple_set_info_bits(tuple,
+ rec_get_info_bits(rec, index->table->comp));
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) {
buf = mem_heap_alloc(heap, len);
@@ -405,32 +1068,28 @@ rec_copy_prefix_to_dtuple(
}
/******************************************************************
-Copies the first n fields of a physical record to a new physical record in
-a buffer. */
-
+Copies the first n fields of an old-style physical record
+to a new physical record in a buffer. */
+static
rec_t*
-rec_copy_prefix_to_buf(
-/*===================*/
+rec_copy_prefix_to_buf_old(
+/*=======================*/
/* out, own: copied record */
rec_t* rec, /* in: physical record */
ulint n_fields, /* in: number of fields to copy */
+ ulint area_end, /* in: end of the prefix data */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size) /* in/out: buffer size */
{
rec_t* copy_rec;
ulint area_start;
- ulint area_end;
ulint prefix_len;
- ut_ad(rec_validate(rec));
-
- area_end = rec_get_field_start_offs(rec, n_fields);
-
if (rec_get_1byte_offs_flag(rec)) {
- area_start = REC_N_EXTRA_BYTES + n_fields;
+ area_start = REC_N_OLD_EXTRA_BYTES + n_fields;
} else {
- area_start = REC_N_EXTRA_BYTES + 2 * n_fields;
+ area_start = REC_N_OLD_EXTRA_BYTES + 2 * n_fields;
}
prefix_len = area_start + area_end;
@@ -448,17 +1107,129 @@ rec_copy_prefix_to_buf(
copy_rec = *buf + area_start;
- rec_set_n_fields(copy_rec, n_fields);
+ rec_set_n_fields_old(copy_rec, n_fields);
return(copy_rec);
}
-/*******************************************************************
-Validates the consistency of a physical record. */
+/******************************************************************
+Copies the first n fields of a physical record to a new physical record in
+a buffer. */
+
+rec_t*
+rec_copy_prefix_to_buf(
+/*===================*/
+ /* out, own: copied record */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_fields, /* in: number of fields to copy */
+ byte** buf, /* in/out: memory buffer
+ for the copied prefix, or NULL */
+ ulint* buf_size) /* in/out: buffer size */
+{
+ byte* nulls;
+ byte* lens;
+ dict_field_t* field;
+ dtype_t* type;
+ ulint i;
+ ulint prefix_len;
+ ulint null_mask;
+ ulint status;
+ UNIV_PREFETCH_RW(*buf);
+
+ if (UNIV_UNLIKELY(!index->table->comp)) {
+ ut_ad(rec_validate_old(rec));
+ return(rec_copy_prefix_to_buf_old(rec, n_fields,
+ rec_get_field_start_offs(rec, n_fields),
+ buf, buf_size));
+ }
+
+ status = rec_get_status(rec);
+
+ switch (status) {
+ case REC_STATUS_ORDINARY:
+ ut_ad(n_fields <= dict_index_get_n_fields(index));
+ break;
+ case REC_STATUS_NODE_PTR:
+ /* it doesn't make sense to copy the child page number field */
+ ut_ad(n_fields <= dict_index_get_n_unique_in_tree(index));
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* infimum or supremum record: no sense to copy anything */
+ default:
+ ut_error;
+ return(NULL);
+ }
+
+ nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ lens = nulls - (index->n_nullable + 7) / 8;
+ UNIV_PREFETCH_R(lens);
+ prefix_len = 0;
+ null_mask = 1;
+
+ /* read the lengths of fields 0..n */
+ for (i = 0; i < n_fields; i++) {
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ /* nullable field => read the null flag */
+ if (UNIV_UNLIKELY(!(byte) null_mask)) {
+ nulls--;
+ null_mask = 1;
+ }
+
+ if (*nulls & null_mask) {
+ null_mask <<= 1;
+ continue;
+ }
+
+ null_mask <<= 1;
+ }
+
+ if (field->fixed_len) {
+ prefix_len += field->fixed_len;
+ } else {
+ ulint len = *lens--;
+ if (dtype_get_len(type) > 255
+ || dtype_get_mtype(type) == DATA_BLOB) {
+ if (len & 0x80) {
+ /* 1exxxxxx */
+ len &= 0x3f;
+ len <<= 8;
+ len |= *lens--;
+ UNIV_PREFETCH_R(lens);
+ }
+ }
+ prefix_len += len;
+ }
+ }
+
+ UNIV_PREFETCH_R(rec + prefix_len);
+
+ prefix_len += rec - (lens + 1);
+
+ if ((*buf == NULL) || (*buf_size < prefix_len)) {
+ if (*buf != NULL) {
+ mem_free(*buf);
+ }
+
+ *buf = mem_alloc(prefix_len);
+ *buf_size = prefix_len;
+ }
+
+ memcpy(*buf, lens + 1, prefix_len);
+
+ return(*buf + (rec - (lens + 1)));
+}
+
+/*******************************************************************
+Validates the consistency of an old-style physical record. */
+static
ibool
-rec_validate(
-/*=========*/
+rec_validate_old(
+/*=============*/
/* out: TRUE if ok */
rec_t* rec) /* in: physical record */
{
@@ -470,7 +1241,7 @@ rec_validate(
ulint i;
ut_a(rec);
- n_fields = rec_get_n_fields(rec);
+ n_fields = rec_get_n_fields_old(rec);
if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) {
fprintf(stderr, "InnoDB: Error: record has %lu fields\n",
@@ -479,7 +1250,7 @@ rec_validate(
}
for (i = 0; i < n_fields; i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field_old(rec, i, &len);
if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) {
fprintf(stderr,
@@ -499,45 +1270,167 @@ rec_validate(
}
}
- if (len_sum != (ulint)(rec_get_end(rec) - rec)) {
+ if (len_sum != rec_get_data_size_old(rec)) {
fprintf(stderr,
"InnoDB: Error: record len should be %lu, len %lu\n",
(ulong) len_sum,
- (ulong) (rec_get_end(rec) - rec));
+ rec_get_data_size_old(rec));
+ return(FALSE);
+ }
+
+ rec_dummy = sum; /* This is here only to fool the compiler */
+
+ return(TRUE);
+}
+
+/*******************************************************************
+Validates the consistency of a physical record. */
+
+ibool
+rec_validate(
+/*=========*/
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ const byte* data;
+ ulint len;
+ ulint n_fields;
+ ulint len_sum = 0;
+ ulint sum = 0;
+ ulint i;
+
+ ut_a(rec);
+ n_fields = rec_offs_n_fields(offsets);
+
+ if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) {
+ fprintf(stderr, "InnoDB: Error: record has %lu fields\n",
+ (ulong) n_fields);
+ return(FALSE);
+ }
+
+ ut_a(rec_offs_comp(offsets) || n_fields <= rec_get_n_fields_old(rec));
+
+ for (i = 0; i < n_fields; i++) {
+ data = rec_get_nth_field(rec, offsets, i, &len);
+
+ if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) {
+ fprintf(stderr,
+ "InnoDB: Error: record field %lu len %lu\n", (ulong) i,
+ (ulong) len);
+ return(FALSE);
+ }
+
+ if (len != UNIV_SQL_NULL) {
+ len_sum += len;
+ sum += *(data + len -1); /* dereference the
+ end of the field to
+ cause a memory trap
+ if possible */
+ } else if (!rec_offs_comp(offsets)) {
+ len_sum += rec_get_nth_field_size(rec, i);
+ }
+ }
+
+ if (len_sum != (ulint)(rec_get_end(rec, offsets) - rec)) {
+ fprintf(stderr,
+ "InnoDB: Error: record len should be %lu, len %lu\n",
+ (ulong) len_sum,
+ (ulong) (rec_get_end(rec, offsets) - rec));
return(FALSE);
}
rec_dummy = sum; /* This is here only to fool the compiler */
+ if (!rec_offs_comp(offsets)) {
+ ut_a(rec_validate_old(rec));
+ }
+
return(TRUE);
}
/*******************************************************************
+Prints an old-style physical record. */
+
+void
+rec_print_old(
+/*==========*/
+ FILE* file, /* in: file where to print */
+ rec_t* rec) /* in: physical record */
+{
+ const byte* data;
+ ulint len;
+ ulint n;
+ ulint i;
+
+ ut_ad(rec);
+
+ n = rec_get_n_fields_old(rec);
+
+ fprintf(file, "PHYSICAL RECORD: n_fields %lu;"
+ " %u-byte offsets; info bits %lu\n",
+ (ulong) n,
+ rec_get_1byte_offs_flag(rec) ? 1 : 2,
+ (ulong) rec_get_info_bits(rec, FALSE));
+
+ for (i = 0; i < n; i++) {
+
+ data = rec_get_nth_field_old(rec, i, &len);
+
+ fprintf(file, " %lu:", (ulong) i);
+
+ if (len != UNIV_SQL_NULL) {
+ if (len <= 30) {
+
+ ut_print_buf(file, data, len);
+ } else {
+ ut_print_buf(file, data, 30);
+
+ fputs("...(truncated)", file);
+ }
+ } else {
+ fprintf(file, " SQL NULL, size %lu ",
+ rec_get_nth_field_size(rec, i));
+ }
+ putc(';', file);
+ }
+
+ putc('\n', file);
+
+ rec_validate_old(rec);
+}
+
+/*******************************************************************
Prints a physical record. */
void
-rec_print(
-/*======*/
- FILE* file, /* in: file where to print */
- rec_t* rec) /* in: physical record */
+rec_print_new(
+/*==========*/
+ FILE* file, /* in: file where to print */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- byte* data;
- ulint len;
- ulint n;
- ulint i;
+ const byte* data;
+ ulint len;
+ ulint i;
+
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
+ if (!rec_offs_comp(offsets)) {
+ rec_print_old(file, rec);
+ return;
+ }
ut_ad(rec);
-
- n = rec_get_n_fields(rec);
fprintf(file, "PHYSICAL RECORD: n_fields %lu;"
- " 1-byte offs %s; info bits %lu\n",
- (ulong) n, rec_get_1byte_offs_flag(rec) ? "TRUE" : "FALSE",
- (ulong) rec_get_info_bits(rec));
+ " compact format; info bits %lu\n",
+ (ulong) rec_offs_n_fields(offsets),
+ (ulong) rec_get_info_bits(rec, TRUE));
- for (i = 0; i < n; i++) {
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
fprintf(file, " %lu:", (ulong) i);
@@ -551,14 +1444,40 @@ rec_print(
fputs("...(truncated)", file);
}
} else {
- fprintf(file, " SQL NULL, size %lu ",
- (ulong) rec_get_nth_field_size(rec, i));
-
+ fputs(" SQL NULL", file);
}
putc(';', file);
}
putc('\n', file);
- rec_validate(rec);
+ rec_validate(rec, offsets);
+}
+
+/*******************************************************************
+Prints a physical record. */
+
+void
+rec_print(
+/*======*/
+ FILE* file, /* in: file where to print */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index) /* in: record descriptor */
+{
+ ut_ad(index);
+
+ if (!index->table->comp) {
+ rec_print_old(file, rec);
+ return;
+ } else {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ rec_print_new(file, rec, rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap));
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ }
}
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 5ca1ee51cbd..75d8117a73e 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -256,7 +256,7 @@ row_ins_sec_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
ut_ad((cursor->index->type & DICT_CLUSTERED) == 0);
- ut_ad(rec_get_deleted_flag(rec));
+ ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp));
/* We know that in the alphabetical ordering, entry and rec are
identified. But in their binary form there may be differences if
@@ -321,7 +321,7 @@ row_ins_clust_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
- ut_ad(rec_get_deleted_flag(rec));
+ ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp));
heap = mem_heap_create(1024);
@@ -478,6 +478,8 @@ row_ins_cascade_calc_update_vec(
if (parent_ufield->field_no == parent_field_no) {
+ ulint min_size;
+
/* A field in the parent index record is
updated. Let us make the update vector
field for the child table. */
@@ -506,10 +508,13 @@ row_ins_cascade_calc_update_vec(
column, do not allow the update */
if (ufield->new_val.len != UNIV_SQL_NULL
- && ufield->new_val.len
- > dtype_get_len(type)) {
+ && dtype_get_at_most_n_mbchars(
+ type, dtype_get_len(type),
+ ufield->new_val.len,
+ ufield->new_val.data)
+ < ufield->new_val.len) {
- return(ULINT_UNDEFINED);
+ return(ULINT_UNDEFINED);
}
/* If the parent column type has a different
@@ -517,25 +522,48 @@ row_ins_cascade_calc_update_vec(
need to pad with spaces the new value of the
child column */
- if (dtype_is_fixed_size(type)
+ min_size = dtype_get_min_size(type);
+
+ if (min_size
&& ufield->new_val.len != UNIV_SQL_NULL
- && ufield->new_val.len
- < dtype_get_fixed_size(type)) {
+ && ufield->new_val.len < min_size) {
+ char* pad_start;
+ const char* pad_end;
ufield->new_val.data =
mem_heap_alloc(heap,
- dtype_get_fixed_size(type));
- ufield->new_val.len =
- dtype_get_fixed_size(type);
- ut_a(dtype_get_pad_char(type)
- != ULINT_UNDEFINED);
-
- memset(ufield->new_val.data,
- (byte)dtype_get_pad_char(type),
- dtype_get_fixed_size(type));
+ min_size);
+ pad_start =
+ ((char*) ufield->new_val.data)
+ + ufield->new_val.len;
+ pad_end =
+ ((char*) ufield->new_val.data)
+ + min_size;
+ ufield->new_val.len = min_size;
ut_memcpy(ufield->new_val.data,
parent_ufield->new_val.data,
parent_ufield->new_val.len);
+
+ switch (UNIV_EXPECT(
+ dtype_get_mbminlen(type), 1)) {
+ default:
+ ut_error;
+ case 1:
+ /* space=0x20 */
+ memset(pad_start, 0x20,
+ pad_end - pad_start);
+ break;
+ case 2:
+ /* space=0x0020 */
+ ut_a(!(ufield->new_val.len
+ % 2));
+ ut_a(!(min_size % 2));
+ do {
+ *pad_start++ = 0x00;
+ *pad_start++ = 0x20;
+ } while (pad_start < pad_end);
+ break;
+ }
}
ufield->extern_storage = FALSE;
@@ -574,7 +602,7 @@ row_ins_foreign_report_err(
rewind(ef);
ut_print_timestamp(ef);
fputs(" Transaction:\n", ef);
- trx_print(ef, trx);
+ trx_print(ef, trx, 600);
fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name);
@@ -594,7 +622,7 @@ row_ins_foreign_report_err(
ut_print_name(ef, trx, foreign->foreign_index->name);
if (rec) {
fputs(", there is a record:\n", ef);
- rec_print(ef, rec);
+ rec_print(ef, rec, foreign->foreign_index);
} else {
fputs(", the record is not available\n", ef);
}
@@ -625,7 +653,7 @@ row_ins_foreign_report_add_err(
rewind(ef);
ut_print_timestamp(ef);
fputs(" Transaction:\n", ef);
- trx_print(ef, trx);
+ trx_print(ef, trx, 600);
fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef);
@@ -649,7 +677,7 @@ row_ins_foreign_report_add_err(
}
if (rec) {
- rec_print(ef, rec);
+ rec_print(ef, rec, foreign->foreign_index);
}
putc('\n', ef);
@@ -711,7 +739,6 @@ row_ins_foreign_check_on_constraint(
dict_index_t* index;
dict_index_t* clust_index;
dtuple_t* ref;
- mem_heap_t* tmp_heap;
mem_heap_t* upd_vec_heap = NULL;
rec_t* rec;
rec_t* clust_rec;
@@ -720,14 +747,17 @@ row_ins_foreign_check_on_constraint(
ulint err;
ulint i;
trx_t* trx;
+ mem_heap_t* tmp_heap = NULL;
-
ut_a(thr && foreign && pcur && mtr);
trx = thr_get_trx(thr);
/* Since we are going to delete or update a row, we have to invalidate
- the MySQL query cache for table */
+ the MySQL query cache for table. A deadlock of threads is not possible
+ here because the caller of this function does not hold any latches with
+ the sync0sync.h rank above the kernel mutex. The query cache mutex has
+ a rank just above the kernel mutex. */
row_ins_invalidate_query_cache(thr, table->name);
@@ -821,7 +851,7 @@ row_ins_foreign_check_on_constraint(
err = DB_ROW_IS_REFERENCED;
row_ins_foreign_report_err(
-(char*)"Trying a too deep cascaded delete or update\n",
+"Trying a too deep cascaded delete or update\n",
thr, foreign, btr_pcur_get_rec(pcur), entry);
goto nonstandard_exit_func;
@@ -853,8 +883,6 @@ row_ins_foreign_check_on_constraint(
PAGE_CUR_LE, BTR_SEARCH_LEAF,
cascade->pcur, 0, mtr);
- mem_heap_free(tmp_heap);
-
clust_rec = btr_pcur_get_rec(cascade->pcur);
if (!page_rec_is_user_rec(clust_rec)
@@ -868,10 +896,10 @@ row_ins_foreign_check_on_constraint(
fputs("\n"
"InnoDB: record ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, index);
fputs("\n"
"InnoDB: clustered record ", stderr);
- rec_print(stderr, clust_rec);
+ rec_print(stderr, clust_rec, clust_index);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
@@ -889,9 +917,9 @@ row_ins_foreign_check_on_constraint(
/* Here it suffices to use a LOCK_REC_NOT_GAP type lock;
we already have a normal shared lock on the appropriate
gap if the search criterion was not unique */
-
- err = lock_clust_rec_read_check_and_lock(0, clust_rec,
- clust_index, LOCK_X, LOCK_REC_NOT_GAP, thr);
+
+ err = lock_clust_rec_read_check_and_lock_alt(0, clust_rec,
+ clust_index, LOCK_X, LOCK_REC_NOT_GAP, thr);
}
if (err != DB_SUCCESS) {
@@ -899,7 +927,7 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
- if (rec_get_deleted_flag(clust_rec)) {
+ if (rec_get_deleted_flag(clust_rec, table->comp)) {
/* This can happen if there is a circular reference of
rows such that cascading delete comes to delete a row
already in the process of being delete marked */
@@ -1008,6 +1036,10 @@ row_ins_foreign_check_on_constraint(
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
+
if (upd_vec_heap) {
mem_heap_free(upd_vec_heap);
}
@@ -1015,6 +1047,9 @@ row_ins_foreign_check_on_constraint(
return(err);
nonstandard_exit_func:
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
if (upd_vec_heap) {
mem_heap_free(upd_vec_heap);
@@ -1042,16 +1077,19 @@ row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (index->type & DICT_CLUSTERED) {
- err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_S,
- type, thr);
+ err = lock_clust_rec_read_check_and_lock(0,
+ rec, index, offsets, LOCK_S, type, thr);
} else {
- err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_S,
- type, thr);
+ err = lock_sec_rec_read_check_and_lock(0,
+ rec, index, offsets, LOCK_S, type, thr);
}
return(err);
@@ -1069,16 +1107,19 @@ row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (index->type & DICT_CLUSTERED) {
- err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_X,
- type, thr);
+ err = lock_clust_rec_read_check_and_lock(0,
+ rec, index, offsets, LOCK_X, type, thr);
} else {
- err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_X,
- type, thr);
+ err = lock_sec_rec_read_check_and_lock(0,
+ rec, index, offsets, LOCK_X, type, thr);
}
return(err);
@@ -1117,7 +1158,11 @@ row_ins_check_foreign_constraint(
ulint err;
ulint i;
mtr_t mtr;
- trx_t* trx = thr_get_trx(thr);
+ trx_t* trx = thr_get_trx(thr);
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
run_again:
#ifdef UNIV_SYNC_DEBUG
@@ -1129,8 +1174,7 @@ run_again:
if (trx->check_foreigns == FALSE) {
/* The user has suppressed foreign key checks currently for
this session */
-
- return(DB_SUCCESS);
+ goto exit_func;
}
/* If any of the foreign key fields in entry is SQL NULL, we
@@ -1141,7 +1185,7 @@ run_again:
if (UNIV_SQL_NULL == dfield_get_len(
dtuple_get_nth_field(entry, i))) {
- return(DB_SUCCESS);
+ goto exit_func;
}
}
@@ -1164,8 +1208,8 @@ run_again:
with each foreign key constraint, one after
another, and the user has problems predicting in
which order they are performed. */
-
- return(DB_SUCCESS);
+
+ goto exit_func;
}
}
@@ -1184,7 +1228,7 @@ run_again:
rewind(ef);
ut_print_timestamp(ef);
fputs(" Transaction:\n", ef);
- trx_print(ef, trx);
+ trx_print(ef, trx, 600);
fputs("Foreign key constraint fails for table ", ef);
ut_print_name(ef, trx, foreign->foreign_table_name);
fputs(":\n", ef);
@@ -1199,10 +1243,10 @@ run_again:
fputs("\nor its .ibd file does not currently exist!\n", ef);
mutex_exit(&dict_foreign_err_mutex);
- return(DB_NO_REFERENCED_ROW);
+ err = DB_NO_REFERENCED_ROW;
}
- return(DB_SUCCESS);
+ goto exit_func;
}
ut_a(check_table && check_index);
@@ -1233,17 +1277,22 @@ run_again:
/* Scan index records and check if there is a matching record */
for (;;) {
+ page_t* page;
rec = btr_pcur_get_rec(&pcur);
+ page = buf_frame_align(rec);
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
+ if (rec == page_get_infimum_rec(page)) {
goto next_rec;
}
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
+ offsets = rec_get_offsets(rec, check_index,
+ offsets, ULINT_UNDEFINED, &heap);
+
+ if (rec == page_get_supremum_rec(page)) {
+
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec,
- check_index, thr);
+ check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
@@ -1252,13 +1301,14 @@ run_again:
goto next_rec;
}
- cmp = cmp_dtuple_rec(entry, rec);
+ cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec,
+ rec_offs_comp(offsets))) {
err = row_ins_set_shared_rec_lock(
- LOCK_ORDINARY,
- rec, check_index, thr);
+ LOCK_ORDINARY, rec,
+ check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
@@ -1269,9 +1319,9 @@ run_again:
into gaps */
err = row_ins_set_shared_rec_lock(
- LOCK_REC_NOT_GAP,
- rec, check_index, thr);
-
+ LOCK_REC_NOT_GAP, rec,
+ check_index, offsets, thr);
+
if (err != DB_SUCCESS) {
break;
@@ -1307,7 +1357,7 @@ run_again:
if (cmp < 0) {
err = row_ins_set_shared_rec_lock(LOCK_GAP,
- rec, check_index, thr);
+ rec, check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
@@ -1365,6 +1415,10 @@ do_possible_lock_wait:
err = trx->error_state;
}
+exit_func:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(err);
}
@@ -1462,19 +1516,23 @@ row_ins_dupl_error_with_rec(
that the caller already has a record lock on
the record! */
dtuple_t* entry, /* in: entry to insert */
- dict_index_t* index) /* in: index */
+ dict_index_t* index, /* in: index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint matched_fields;
ulint matched_bytes;
ulint n_unique;
ulint i;
-
+
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
n_unique = dict_index_get_n_unique(index);
matched_fields = 0;
matched_bytes = 0;
- cmp_dtuple_rec_with_match(entry, rec, &matched_fields, &matched_bytes);
+ cmp_dtuple_rec_with_match(entry, rec, offsets,
+ &matched_fields, &matched_bytes);
if (matched_fields < n_unique) {
@@ -1495,12 +1553,7 @@ row_ins_dupl_error_with_rec(
}
}
- if (!rec_get_deleted_flag(rec)) {
-
- return(TRUE);
- }
-
- return(FALSE);
+ return(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
}
/*******************************************************************
@@ -1517,6 +1570,7 @@ row_ins_scan_sec_index_for_duplicate(
dtuple_t* entry, /* in: index entry */
que_thr_t* thr) /* in: query thread */
{
+#ifndef UNIV_HOTBACKUP
ulint n_unique;
ulint i;
int cmp;
@@ -1526,8 +1580,11 @@ row_ins_scan_sec_index_for_duplicate(
ulint err = DB_SUCCESS;
ibool moved;
mtr_t mtr;
- trx_t* trx;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
n_unique = dict_index_get_n_unique(index);
/* If the secondary index is unique, but one of the fields in the
@@ -1562,10 +1619,8 @@ row_ins_scan_sec_index_for_duplicate(
goto next_rec;
}
- /* Try to place a lock on the index record */
-
- trx = thr_get_trx(thr);
- ut_ad(trx);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
if (innobase_query_is_update()) {
@@ -1574,12 +1629,12 @@ row_ins_scan_sec_index_for_duplicate(
duplicates ( REPLACE, LOAD DATAFILE REPLACE,
INSERT ON DUPLICATE KEY UPDATE). */
- err = row_ins_set_exclusive_rec_lock(
- LOCK_ORDINARY,rec,index,thr);
+ err = row_ins_set_exclusive_rec_lock(LOCK_ORDINARY,
+ rec, index, offsets, thr);
} else {
- err = row_ins_set_shared_rec_lock(
- LOCK_ORDINARY, rec, index,thr);
+ err = row_ins_set_shared_rec_lock(LOCK_ORDINARY,
+ rec, index, offsets, thr);
}
if (err != DB_SUCCESS) {
@@ -1587,15 +1642,16 @@ row_ins_scan_sec_index_for_duplicate(
break;
}
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ if (page_rec_is_supremum(rec)) {
goto next_rec;
}
- cmp = cmp_dtuple_rec(entry, rec);
+ cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
- if (row_ins_dupl_error_with_rec(rec, entry, index)) {
+ if (row_ins_dupl_error_with_rec(rec, entry,
+ index, offsets)) {
err = DB_DUPLICATE_KEY;
thr_get_trx(thr)->error_info = index;
@@ -1617,12 +1673,21 @@ next_rec:
}
}
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
mtr_commit(&mtr);
/* Restore old value */
dtuple_set_n_fields_cmp(entry, n_fields_cmp);
return(err);
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/*******************************************************************
@@ -1642,11 +1707,15 @@ row_ins_duplicate_error_in_clust(
que_thr_t* thr, /* in: query thread */
mtr_t* mtr) /* in: mtr */
{
+#ifndef UNIV_HOTBACKUP
ulint err;
rec_t* rec;
- page_t* page;
ulint n_unique;
- trx_t* trx = thr_get_trx(thr);
+ trx_t* trx = thr_get_trx(thr);
+ mem_heap_t*heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
UT_NOT_USED(mtr);
@@ -1671,9 +1740,10 @@ row_ins_duplicate_error_in_clust(
if (cursor->low_match >= n_unique) {
rec = btr_cur_get_rec(cursor);
- page = buf_frame_align(rec);
- if (rec != page_get_infimum_rec(page)) {
+ if (!page_rec_is_infimum(rec)) {
+ offsets = rec_get_offsets(rec, cursor->index, offsets,
+ ULINT_UNDEFINED, &heap);
/* We set a lock on the possible duplicate: this
is needed in logical logging of MySQL to make
@@ -1689,23 +1759,23 @@ row_ins_duplicate_error_in_clust(
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,rec,cursor->index,
- thr);
+ offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,rec, cursor->index,
- thr);
+ offsets, thr);
}
if (err != DB_SUCCESS) {
-
- return(err);
+ goto func_exit;
}
if (row_ins_dupl_error_with_rec(rec, entry,
- cursor->index)) {
+ cursor->index, offsets)) {
trx->error_info = cursor->index;
- return(DB_DUPLICATE_KEY);
+ err = DB_DUPLICATE_KEY;
+ goto func_exit;
}
}
}
@@ -1713,10 +1783,10 @@ row_ins_duplicate_error_in_clust(
if (cursor->up_match >= n_unique) {
rec = page_rec_get_next(btr_cur_get_rec(cursor));
- page = buf_frame_align(rec);
-
- if (rec != page_get_supremum_rec(page)) {
+ if (!page_rec_is_supremum(rec)) {
+ offsets = rec_get_offsets(rec, cursor->index, offsets,
+ ULINT_UNDEFINED, &heap);
if (innobase_query_is_update()) {
@@ -1726,32 +1796,41 @@ row_ins_duplicate_error_in_clust(
INSERT ON DUPLICATE KEY UPDATE). */
err = row_ins_set_exclusive_rec_lock(
- LOCK_REC_NOT_GAP,
- rec,cursor->index,thr);
+ LOCK_REC_NOT_GAP, rec,
+ cursor->index, offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
- LOCK_REC_NOT_GAP,rec,
- cursor->index, thr);
+ LOCK_REC_NOT_GAP, rec,
+ cursor->index, offsets, thr);
}
if (err != DB_SUCCESS) {
-
- return(err);
+ goto func_exit;
}
if (row_ins_dupl_error_with_rec(rec, entry,
- cursor->index)) {
+ cursor->index, offsets)) {
trx->error_info = cursor->index;
- return(DB_DUPLICATE_KEY);
+ err = DB_DUPLICATE_KEY;
+ goto func_exit;
}
+ mem_heap_free(heap);
}
ut_a(!(cursor->index->type & DICT_CLUSTERED));
/* This should never happen */
}
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+func_exit:
+ return(err);
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/*******************************************************************
@@ -1773,7 +1852,6 @@ row_ins_must_modify(
{
ulint enough_match;
rec_t* rec;
- page_t* page;
/* NOTE: (compare to the note in row_ins_duplicate_error) Because node
pointers on upper levels of the B-tree may match more to entry than
@@ -1787,9 +1865,8 @@ row_ins_must_modify(
if (cursor->low_match >= enough_match) {
rec = btr_cur_get_rec(cursor);
- page = buf_frame_align(rec);
- if (rec != page_get_infimum_rec(page)) {
+ if (!page_rec_is_infimum(rec)) {
return(ROW_INS_PREV);
}
@@ -1828,12 +1905,15 @@ row_ins_index_entry_low(
ulint modify = 0; /* remove warning */
rec_t* insert_rec;
rec_t* rec;
- rec_t* first_rec;
ulint err;
ulint n_unique;
big_rec_t* big_rec = NULL;
mtr_t mtr;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
log_free_check();
mtr_start(&mtr);
@@ -1859,15 +1939,20 @@ row_ins_index_entry_low(
err = DB_SUCCESS;
goto function_exit;
- }
-
- first_rec = page_rec_get_next(page_get_infimum_rec(
- buf_frame_align(btr_cur_get_rec(&cursor))));
+ }
+
+#ifdef UNIV_DEBUG
+ {
+ page_t* page = btr_cur_get_page(&cursor);
+ rec_t* first_rec = page_rec_get_next(
+ page_get_infimum_rec(page));
- if (!page_rec_is_supremum(first_rec)) {
- ut_a((rec_get_n_fields(first_rec))
- == dtuple_get_n_fields(entry));
+ if (UNIV_LIKELY(first_rec != page_get_supremum_rec(page))) {
+ ut_a(rec_get_n_fields(first_rec, index)
+ == dtuple_get_n_fields(entry));
+ }
}
+#endif
n_unique = dict_index_get_n_unique(index);
@@ -1944,7 +2029,7 @@ row_ins_index_entry_low(
if (err == DB_SUCCESS) {
if (ext_vec) {
- rec_set_field_extern_bits(insert_rec,
+ rec_set_field_extern_bits(insert_rec, index,
ext_vec, n_ext_vec, &mtr);
}
}
@@ -1954,14 +2039,18 @@ function_exit:
mtr_commit(&mtr);
if (big_rec) {
+ rec_t* rec;
mtr_start(&mtr);
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0, &mtr);
+ rec = btr_cur_get_rec(&cursor);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+
+ err = btr_store_big_rec_extern_fields(index, rec,
+ offsets, big_rec, &mtr);
- err = btr_store_big_rec_extern_fields(index,
- btr_cur_get_rec(&cursor),
- big_rec, &mtr);
if (modify) {
dtuple_big_rec_free(big_rec);
} else {
@@ -1971,6 +2060,9 @@ function_exit:
mtr_commit(&mtr);
}
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(err);
}
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 7ce5c766e06..26aae117d1d 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -106,20 +106,6 @@ row_mysql_delay_if_needed(void)
}
/***********************************************************************
-Reads a MySQL format variable-length field (like VARCHAR) length and
-returns pointer to the field data. */
-
-byte*
-row_mysql_read_var_ref_noninline(
-/*=============================*/
- /* out: field + 2 */
- ulint* len, /* out: variable-length field length */
- byte* field) /* in: field */
-{
- return(row_mysql_read_var_ref(len, field));
-}
-
-/***********************************************************************
Frees the blob heap in prebuilt when no longer needed. */
void
@@ -133,6 +119,61 @@ row_mysql_prebuilt_free_blob_heap(
}
/***********************************************************************
+Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
+format. */
+
+byte*
+row_mysql_store_true_var_len(
+/*=========================*/
+ /* out: pointer to the data, we skip the 1 or 2 bytes
+ at the start that are used to store the len */
+ byte* dest, /* in: where to store */
+ ulint len, /* in: length, must fit in two bytes */
+ ulint lenlen) /* in: storage length of len: either 1 or 2 bytes */
+{
+ if (lenlen == 2) {
+ ut_a(len < 256 * 256);
+
+ mach_write_to_2_little_endian(dest, len);
+
+ return(dest + 2);
+ }
+
+ ut_a(lenlen == 1);
+ ut_a(len < 256);
+
+ mach_write_to_1(dest, len);
+
+ return(dest + 1);
+}
+
+/***********************************************************************
+Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
+returns a pointer to the data. */
+
+byte*
+row_mysql_read_true_varchar(
+/*========================*/
+ /* out: pointer to the data, we skip the 1 or 2 bytes
+ at the start that are used to store the len */
+ ulint* len, /* out: variable-length field length */
+ byte* field, /* in: field in the MySQL format */
+ ulint lenlen) /* in: storage length of len: either 1 or 2 bytes */
+{
+ if (lenlen == 2) {
+ *len = mach_read_from_2_little_endian(field);
+
+ return(field + 2);
+ }
+
+ ut_a(lenlen == 1);
+
+ *len = mach_read_from_1(field);
+
+ return(field + 1);
+}
+
+/***********************************************************************
Stores a reference to a BLOB in the MySQL format. */
void
@@ -191,15 +232,177 @@ row_mysql_read_blob_ref(
}
/******************************************************************
-Convert a row in the MySQL format to a row in the Innobase format. */
+Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
+The counterpart of this function is row_sel_field_store_in_mysql_format() in
+row0sel.c. */
+
+byte*
+row_mysql_store_col_in_innobase_format(
+/*===================================*/
+ /* out: up to which byte we used
+ buf in the conversion */
+ dfield_t* dfield, /* in/out: dfield where dtype
+ information must be already set when
+ this function is called! */
+ byte* buf, /* in/out: buffer for a converted
+ integer value; this must be at least
+ col_len long then! */
+ ibool row_format_col, /* TRUE if the mysql_data is from
+ a MySQL row, FALSE if from a MySQL
+ key value;
+ in MySQL, a true VARCHAR storage
+ format differs in a row and in a
+ key value: in a key value the length
+ is always stored in 2 bytes! */
+ byte* mysql_data, /* in: MySQL column value, not
+ SQL NULL; NOTE that dfield may also
+ get a pointer to mysql_data,
+ therefore do not discard this as long
+ as dfield is used! */
+ ulint col_len, /* in: MySQL column length; NOTE that
+ this is the storage length of the
+ column in the MySQL format row, not
+ necessarily the length of the actual
+ payload data; if the column is a true
+ VARCHAR then this is irrelevant */
+ ulint comp) /* in: nonzero=compact format */
+{
+ byte* ptr = mysql_data;
+ dtype_t* dtype;
+ ulint type;
+ ulint lenlen;
+
+ dtype = dfield_get_type(dfield);
+
+ type = dtype->mtype;
+
+ if (type == DATA_INT) {
+ /* Store integer data in Innobase in a big-endian format,
+ sign bit negated if the data is a signed integer. In MySQL,
+ integers are stored in a little-endian format. */
+
+ ptr = buf + col_len;
+
+ for (;;) {
+ ptr--;
+ *ptr = *mysql_data;
+ if (ptr == buf) {
+ break;
+ }
+ mysql_data++;
+ }
+
+ if (!(dtype->prtype & DATA_UNSIGNED)) {
+
+ *ptr = (byte) (*ptr ^ 128);
+ }
+
+ buf += col_len;
+ } else if ((type == DATA_VARCHAR
+ || type == DATA_VARMYSQL
+ || type == DATA_BINARY)) {
+
+ if (dtype_get_mysql_type(dtype) == DATA_MYSQL_TRUE_VARCHAR) {
+ /* The length of the actual data is stored to 1 or 2
+ bytes at the start of the field */
+
+ if (row_format_col) {
+ if (dtype->prtype & DATA_LONG_TRUE_VARCHAR) {
+ lenlen = 2;
+ } else {
+ lenlen = 1;
+ }
+ } else {
+ /* In a MySQL key value, lenlen is always 2 */
+ lenlen = 2;
+ }
+
+ ptr = row_mysql_read_true_varchar(&col_len, mysql_data,
+ lenlen);
+ } else {
+ /* Remove trailing spaces from old style VARCHAR
+ columns. */
+
+ /* Handle UCS2 strings differently. */
+ ulint mbminlen = dtype_get_mbminlen(dtype);
+
+ ptr = mysql_data;
+
+ if (mbminlen == 2) {
+ /* space=0x0020 */
+ /* Trim "half-chars", just in case. */
+ col_len &= ~1;
+
+ while (col_len >= 2 && ptr[col_len - 2] == 0x00
+ && ptr[col_len - 1] == 0x20) {
+ col_len -= 2;
+ }
+ } else {
+ ut_a(mbminlen == 1);
+ /* space=0x20 */
+ while (col_len > 0
+ && ptr[col_len - 1] == 0x20) {
+ col_len--;
+ }
+ }
+ }
+ } else if (comp && type == DATA_MYSQL
+ && dtype_get_mbminlen(dtype) == 1
+ && dtype_get_mbmaxlen(dtype) > 1) {
+ /* In some cases we strip trailing spaces from UTF-8 and other
+ multibyte charsets, from FIXED-length CHAR columns, to save
+ space. UTF-8 would otherwise normally use 3 * the string length
+ bytes to store a latin1 string! */
+
+ /* We assume that this CHAR field is encoded in a
+ variable-length character set where spaces have
+ 1:1 correspondence to 0x20 bytes, such as UTF-8.
+
+ Consider a CHAR(n) field, a field of n characters.
+ It will contain between n * mbminlen and n * mbmaxlen bytes.
+ We will try to truncate it to n bytes by stripping
+ space padding. If the field contains single-byte
+ characters only, it will be truncated to n characters.
+ Consider a CHAR(5) field containing the string ".a "
+ where "." denotes a 3-byte character represented by
+ the bytes "$%&". After our stripping, the string will
+ be stored as "$%&a " (5 bytes). The string ".abc "
+ will be stored as "$%&abc" (6 bytes).
+
+ The space padding will be restored in row0sel.c, function
+ row_sel_field_store_in_mysql_format(). */
+
+ ulint n_chars;
+
+ ut_a(!(dtype_get_len(dtype) % dtype_get_mbmaxlen(dtype)));
+
+ n_chars = dtype_get_len(dtype) / dtype_get_mbmaxlen(dtype);
+
+ /* Strip space padding. */
+ while (col_len > n_chars && ptr[col_len - 1] == 0x20) {
+ col_len--;
+ }
+ } else if (type == DATA_BLOB && row_format_col) {
+
+ ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len);
+ }
+
+ dfield_set_data(dfield, ptr, col_len);
+
+ return(buf);
+}
+
+/******************************************************************
+Convert a row in the MySQL format to a row in the Innobase format. Note that
+the function to convert a MySQL format key value to an InnoDB dtuple is
+row_sel_convert_mysql_key_to_innobase() in row0sel.c. */
static
void
row_mysql_convert_row_to_innobase(
/*==============================*/
dtuple_t* row, /* in/out: Innobase row where the
field type information is already
- copied there, or will be copied
- later */
+ copied there! */
row_prebuilt_t* prebuilt, /* in: prebuilt struct where template
must be of type ROW_MYSQL_WHOLE_ROW */
byte* mysql_rec) /* in: row in the MySQL format;
@@ -236,9 +439,10 @@ row_mysql_convert_row_to_innobase(
row_mysql_store_col_in_innobase_format(dfield,
prebuilt->ins_upd_rec_buff
+ templ->mysql_col_offset,
+ TRUE, /* MySQL row format data */
mysql_rec + templ->mysql_col_offset,
templ->mysql_col_len,
- templ->type, templ->is_unsigned);
+ prebuilt->table->comp);
next_column:
;
}
@@ -260,6 +464,7 @@ row_mysql_handle_errors(
que_thr_t* thr, /* in: query thread */
trx_savept_t* savept) /* in: savepoint or NULL */
{
+#ifndef UNIV_HOTBACKUP
ulint err;
handle_new_error:
@@ -308,14 +513,15 @@ handle_new_error:
return(TRUE);
- } else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT
+ } else if (err == DB_DEADLOCK
|| err == DB_LOCK_TABLE_FULL) {
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */
trx_general_rollback_for_mysql(trx, FALSE, NULL);
- } else if (err == DB_OUT_OF_FILE_SPACE) {
+ } else if (err == DB_OUT_OF_FILE_SPACE
+ || err == DB_LOCK_WAIT_TIMEOUT) {
if (savept) {
/* Roll back the latest, possibly incomplete
insertion or update */
@@ -359,6 +565,12 @@ handle_new_error:
trx->error_state = DB_SUCCESS;
return(FALSE);
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/************************************************************************
@@ -421,6 +633,9 @@ row_create_prebuilt(
clust_index = dict_table_get_first_index(table);
+ /* Make sure that search_tuple is long enough for clustered index */
+ ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields);
+
ref_len = dict_index_get_n_unique(clust_index);
ref = dtuple_create(heap, ref_len);
@@ -583,7 +798,8 @@ static
dtuple_t*
row_get_prebuilt_insert_row(
/*========================*/
- /* out: prebuilt dtuple */
+ /* out: prebuilt dtuple; the column
+ type information is also set in it */
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
handle */
{
@@ -756,24 +972,6 @@ run_again:
}
/*************************************************************************
-Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
-lock type LOCK_TABLE_EXP). */
-
-void
-row_unlock_tables_for_mysql(
-/*========================*/
- trx_t* trx) /* in: transaction */
-{
- if (!trx->n_lock_table_exp) {
-
- return;
- }
-
- mutex_enter(&kernel_mutex);
- lock_release_tables_off_kernel(trx);
- mutex_exit(&kernel_mutex);
-}
-/*************************************************************************
Sets a table lock on the table mentioned in prebuilt. */
int
@@ -784,9 +982,10 @@ row_lock_table_for_mysql(
table handle */
dict_table_t* table, /* in: table to lock, or NULL
if prebuilt->table should be
- locked as LOCK_TABLE_EXP |
+ locked as
prebuilt->select_lock_type */
- ulint mode) /* in: lock mode of table */
+ ulint mode) /* in: lock mode of table
+ (ignored if table==NULL) */
{
trx_t* trx = prebuilt->trx;
que_thr_t* thr;
@@ -822,8 +1021,8 @@ run_again:
if (table) {
err = lock_table(0, table, mode, thr);
} else {
- err = lock_table(LOCK_TABLE_EXP, prebuilt->table,
- prebuilt->select_lock_type, thr);
+ err = lock_table(0, prebuilt->table,
+ prebuilt->select_lock_type, thr);
}
trx->error_state = err;
@@ -946,8 +1145,12 @@ run_again:
if (err != DB_SUCCESS) {
que_thr_stop_for_mysql(thr);
+/* TODO: what is this? */ thr->lock_state= QUE_THR_LOCK_ROW;
+
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
&savept);
+ thr->lock_state= QUE_THR_LOCK_NOLOCK;
+
if (was_lock_wait) {
goto run_again;
}
@@ -1193,9 +1396,11 @@ run_again:
return((int) err);
}
-
+
+ thr->lock_state= QUE_THR_LOCK_ROW;
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
&savept);
+ thr->lock_state= QUE_THR_LOCK_NOLOCK;;
if (was_lock_wait) {
goto run_again;
}
@@ -1224,6 +1429,112 @@ run_again:
return((int) err);
}
+/*************************************************************************
+This can only be used when srv_locks_unsafe_for_binlog is TRUE. Before
+calling this function we must use trx_reset_new_rec_lock_info() and
+trx_register_new_rec_lock() to store the information which new record locks
+really were set. This function removes a newly set lock under prebuilt->pcur,
+and also under prebuilt->clust_pcur. Currently, this is only used and tested
+in the case of an UPDATE or a DELETE statement, where the row lock is of the
+LOCK_X type.
+Thus, this implements a 'mini-rollback' that releases the latest record
+locks we set. */
+
+int
+row_unlock_for_mysql(
+/*=================*/
+ /* out: error code or DB_SUCCESS */
+ row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL
+ handle */
+ ibool has_latches_on_recs)/* TRUE if called so that we have
+ the latches on the records under pcur
+ and clust_pcur, and we do not need to
+ reposition the cursors. */
+{
+ dict_index_t* index;
+ btr_pcur_t* pcur = prebuilt->pcur;
+ btr_pcur_t* clust_pcur = prebuilt->clust_pcur;
+ trx_t* trx = prebuilt->trx;
+ rec_t* rec;
+ mtr_t mtr;
+
+ ut_ad(prebuilt && trx);
+ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+
+ if (!srv_locks_unsafe_for_binlog) {
+
+ fprintf(stderr,
+"InnoDB: Error: calling row_unlock_for_mysql though\n"
+"InnoDB: srv_locks_unsafe_for_binlog is FALSE.\n");
+
+ return(DB_SUCCESS);
+ }
+
+ trx->op_info = "unlock_row";
+
+ index = btr_pcur_get_btr_cur(pcur)->index;
+
+ if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
+
+ mtr_start(&mtr);
+
+ /* Restore the cursor position and find the record */
+
+ if (!has_latches_on_recs) {
+ btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr);
+ }
+
+ rec = btr_pcur_get_rec(pcur);
+
+ mutex_enter(&kernel_mutex);
+
+ lock_rec_reset_and_release_wait(rec);
+
+ mutex_exit(&kernel_mutex);
+
+ mtr_commit(&mtr);
+
+ /* If the search was done through the clustered index, then
+ we have not used clust_pcur at all, and we must NOT try to
+ reset locks on clust_pcur. The values in clust_pcur may be
+ garbage! */
+
+ if (index->type & DICT_CLUSTERED) {
+
+ goto func_exit;
+ }
+ }
+
+ index = btr_pcur_get_btr_cur(clust_pcur)->index;
+
+ if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
+
+ mtr_start(&mtr);
+
+ /* Restore the cursor position and find the record */
+
+ if (!has_latches_on_recs) {
+ btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur,
+ &mtr);
+ }
+
+ rec = btr_pcur_get_rec(clust_pcur);
+
+ mutex_enter(&kernel_mutex);
+
+ lock_rec_reset_and_release_wait(rec);
+
+ mutex_exit(&kernel_mutex);
+
+ mtr_commit(&mtr);
+ }
+
+func_exit:
+ trx->op_info = "";
+
+ return(DB_SUCCESS);
+}
+
/**************************************************************************
Does a cascaded delete or set null in a foreign key operation. */
@@ -1777,9 +2088,12 @@ row_table_add_foreign_constraints(
FOREIGN KEY (a, b) REFERENCES table2(c, d),
table2 can be written also with the
database name before it: test.table2 */
- const char* name) /* in: table full name in the
+ const char* name, /* in: table full name in the
normalized form
database_name/table_name */
+ ibool reject_fks) /* in: if TRUE, fail with error
+ code DB_CANNOT_ADD_CONSTRAINT if
+ any foreign keys are found. */
{
ulint err;
@@ -1800,7 +2114,8 @@ row_table_add_foreign_constraints(
trx->dict_operation = TRUE;
- err = dict_create_foreign_constraints(trx, sql_string, name);
+ err = dict_create_foreign_constraints(trx, sql_string, name,
+ reject_fks);
if (err == DB_SUCCESS) {
/* Check that also referencing constraints are ok */
@@ -2020,6 +2335,7 @@ row_add_table_to_background_drop_list(
return(TRUE);
}
+#ifndef UNIV_HOTBACKUP
/*************************************************************************
Discards the tablespace of a table which stored in an .ibd file. Discarding
means that this function deletes the .ibd file and assigns a new table id for
@@ -2370,6 +2686,302 @@ funct_exit:
}
/*************************************************************************
+Truncates a table for MySQL. */
+
+int
+row_truncate_table_for_mysql(
+/*=========================*/
+ /* out: error code or DB_SUCCESS */
+ dict_table_t* table, /* in: table handle */
+ trx_t* trx) /* in: transaction handle */
+{
+ dict_foreign_t* foreign;
+ ulint err;
+ mem_heap_t* heap;
+ byte* buf;
+ dtuple_t* tuple;
+ dfield_t* dfield;
+ dict_index_t* sys_index;
+ btr_pcur_t pcur;
+ mtr_t mtr;
+ dulint new_id;
+ char* sql;
+ que_thr_t* thr;
+ que_t* graph = NULL;
+
+/* How do we prevent crashes caused by ongoing operations on the table? Old
+operations could try to access non-existent pages.
+
+1) SQL queries, INSERT, SELECT, ...: we must get an exclusive MySQL table lock
+on the table before we can do TRUNCATE TABLE. Then there are no running
+queries on the table. This is guaranteed, because in
+ha_innobase::store_lock(), we do not weaken the TL_WRITE lock requested
+by MySQL when executing SQLCOM_TRUNCATE.
+2) Purge and rollback: we assign a new table id for the table. Since purge and
+rollback look for the table based on the table id, they see the table as
+'dropped' and discard their operations.
+3) Insert buffer: TRUNCATE TABLE is analogous to DROP TABLE, so we do not
+have to remove insert buffer records, as the insert buffer works at a low
+level. If a freed page is later reallocated, the allocator will remove
+the ibuf entries for it.
+
+TODO: when we truncate *.ibd files (analogous to DISCARD TABLESPACE), we
+will have to remove we remove all entries for the table in the insert
+buffer tree!
+
+4) Linear readahead and random readahead: we use the same method as in 3) to
+discard ongoing operations. (This will only be relevant for TRUNCATE TABLE
+by DISCARD TABLESPACE.)
+5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we
+do not allow the TRUNCATE. We also reserve the data dictionary latch. */
+
+ static const char renumber_tablespace_proc[] =
+ "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
+ "old_id CHAR;\n"
+ "new_id CHAR;\n"
+ "old_id_low INT;\n"
+ "old_id_high INT;\n"
+ "new_id_low INT;\n"
+ "new_id_high INT;\n"
+ "BEGIN\n"
+ "old_id_high := %lu;\n"
+ "old_id_low := %lu;\n"
+ "new_id_high := %lu;\n"
+ "new_id_low := %lu;\n"
+ "old_id := CONCAT(TO_BINARY(old_id_high, 4), TO_BINARY(old_id_low, 4));\n"
+ "new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\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());
+ ut_ad(table);
+
+ if (srv_created_new_raw) {
+ fputs(
+ "InnoDB: A new raw disk partition was initialized or\n"
+ "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ "InnoDB: database modifications by the user. Shut down\n"
+ "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
+ "InnoDB: with raw, and innodb_force_... is removed.\n",
+ stderr);
+
+ return(DB_ERROR);
+ }
+
+ trx->op_info = "truncating table";
+
+ trx_start_if_not_started(trx);
+
+ /* Serialize data dictionary operations with dictionary mutex:
+ no deadlocks can occur then in these operations */
+
+ ut_a(trx->dict_operation_lock_mode == 0);
+ /* Prevent foreign key checks etc. while we are truncating the
+ table */
+
+ row_mysql_lock_data_dictionary(trx);
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+ ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ /* Check if the table is referenced by foreign key constraints from
+ some other table (not the table itself) */
+
+ foreign = UT_LIST_GET_FIRST(table->referenced_list);
+
+ while (foreign && foreign->foreign_table == table) {
+ foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
+ }
+
+ if (foreign && trx->check_foreigns) {
+ FILE* ef = dict_foreign_err_file;
+
+ /* We only allow truncating a referenced table if
+ FOREIGN_KEY_CHECKS is set to 0 */
+
+ mutex_enter(&dict_foreign_err_mutex);
+ rewind(ef);
+ ut_print_timestamp(ef);
+
+ fputs(" Cannot truncate table ", ef);
+ ut_print_name(ef, trx, table->name);
+ fputs(" by DROP+CREATE\n"
+ "InnoDB: because it is referenced by ", ef);
+ ut_print_name(ef, trx, foreign->foreign_table_name);
+ putc('\n', ef);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ err = DB_ERROR;
+ goto funct_exit;
+ }
+
+ /* TODO: could we replace the counter n_foreign_key_checks_running
+ with lock checks on the table? Acquire here an exclusive lock on the
+ table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that
+ they can cope with the table having been truncated here? Foreign key
+ checks take an IS or IX lock on the table. */
+
+ if (table->n_foreign_key_checks_running > 0) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Cannot truncate table ", stderr);
+ ut_print_name(stderr, trx, table->name);
+ fputs(" by DROP+CREATE\n"
+"InnoDB: because there is a foreign key check running on it.\n",
+ stderr);
+ err = DB_ERROR;
+
+ goto funct_exit;
+ }
+
+ /* Remove any locks there are on the table or its records */
+
+ lock_reset_all_on_table(table);
+
+ trx->table_id = table->id;
+
+ /* scan SYS_INDEXES for all indexes of the table */
+ heap = mem_heap_create(800);
+
+ tuple = dtuple_create(heap, 1);
+ dfield = dtuple_get_nth_field(tuple, 0);
+
+ buf = mem_heap_alloc(heap, 8);
+ mach_write_to_8(buf, table->id);
+
+ dfield_set_data(dfield, buf, 8);
+ sys_index = dict_table_get_first_index(dict_sys->sys_indexes);
+ dict_index_copy_types(tuple, sys_index, 1);
+
+ mtr_start(&mtr);
+ btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
+ BTR_MODIFY_LEAF, &pcur, &mtr);
+ for (;;) {
+ rec_t* rec;
+ const byte* field;
+ ulint len;
+ ulint root_page_no;
+
+ if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
+ /* The end of SYS_INDEXES has been reached. */
+ break;
+ }
+
+ rec = btr_pcur_get_rec(&pcur);
+
+ field = rec_get_nth_field_old(rec, 0, &len);
+ ut_ad(len == 8);
+
+ if (memcmp(buf, field, len) != 0) {
+ /* End of indexes for the table (TABLE_ID mismatch). */
+ break;
+ }
+
+ if (rec_get_deleted_flag(rec, FALSE)) {
+ /* The index has been dropped. */
+ goto next_rec;
+ }
+
+ btr_pcur_store_position(&pcur, &mtr);
+
+ /* This call may commit and restart mtr. */
+ root_page_no = dict_truncate_index_tree(table, rec, &mtr);
+
+ btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr);
+ rec = btr_pcur_get_rec(&pcur);
+
+ if (root_page_no != FIL_NULL) {
+ page_rec_write_index_page_no(rec,
+ DICT_SYS_INDEXES_PAGE_NO_FIELD,
+ root_page_no, &mtr);
+ /* We will need to commit and restart the
+ mini-transaction in order to avoid deadlocks.
+ The dict_truncate_index_tree() call has allocated
+ a page in this mini-transaction, and the rest of
+ this loop could latch another index page. */
+ mtr_commit(&mtr);
+ mtr_start(&mtr);
+ btr_pcur_restore_position(BTR_MODIFY_LEAF,
+ &pcur, &mtr);
+ }
+
+ next_rec:
+ btr_pcur_move_to_next_user_rec(&pcur, &mtr);
+ }
+
+ btr_pcur_close(&pcur);
+ mtr_commit(&mtr);
+
+ new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
+
+ mem_heap_empty(heap);
+ sql = mem_heap_alloc(heap, (sizeof renumber_tablespace_proc) + 40);
+ sprintf(sql, renumber_tablespace_proc,
+ (ulong) ut_dulint_get_high(table->id),
+ (ulong) ut_dulint_get_low(table->id),
+ (ulong) ut_dulint_get_high(new_id),
+ (ulong) ut_dulint_get_low(new_id));
+
+ graph = pars_sql(sql);
+
+ ut_a(graph);
+
+ mem_heap_free(heap);
+
+ graph->trx = trx;
+ trx->graph = NULL;
+
+ graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
+
+ thr = que_fork_start_command(graph);
+ ut_a(thr);
+
+ que_run_threads(thr);
+
+ que_graph_free(graph);
+
+ err = trx->error_state;
+
+ if (err != DB_SUCCESS) {
+ trx->error_state = DB_SUCCESS;
+ trx_general_rollback_for_mysql(trx, FALSE, NULL);
+ trx->error_state = DB_SUCCESS;
+ ut_print_timestamp(stderr);
+fputs(" InnoDB: Unable to assign a new identifier to table ", stderr);
+ ut_print_name(stderr, trx, table->name);
+ fputs("\n"
+"InnoDB: after truncating it. Background processes may corrupt the table!\n",
+ stderr);
+ err = DB_ERROR;
+ } else {
+ dict_table_change_id_in_cache(table, new_id);
+ }
+
+ dict_table_autoinc_initialize(table, 0);
+ dict_update_statistics(table);
+
+ trx_commit_for_mysql(trx);
+
+funct_exit:
+
+ row_mysql_unlock_data_dictionary(trx);
+
+ trx->op_info = "";
+
+ srv_wake_master_thread();
+
+ return((int) err);
+}
+#endif /* !UNIV_HOTBACKUP */
+
+/*************************************************************************
Drops a table for MySQL. If the name of the table to be dropped is equal
with one of the predefined magic table names, then this also stops printing
the corresponding monitor output by the master thread. */
@@ -2769,7 +3381,9 @@ funct_exit:
trx->op_info = "";
+#ifndef UNIV_HOTBACKUP
srv_wake_master_thread();
+#endif /* !UNIV_HOTBACKUP */
return((int) err);
}
@@ -3025,8 +3639,9 @@ row_rename_table_for_mysql(
"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.php\n", stderr);
+ "InnoDB: You can look for further help from\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/"
+ "InnoDB_troubleshooting_datadict.html\n", stderr);
goto funct_exit;
}
@@ -3038,8 +3653,9 @@ row_rename_table_for_mysql(
ut_print_name(stderr, trx, 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.php\n", stderr);
+ "InnoDB: You can look for further help from\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/"
+ "InnoDB_troubleshooting_datadict.html\n", stderr);
goto funct_exit;
}
@@ -3278,7 +3894,7 @@ funct_exit:
que_graph_free(graph);
}
- if (heap) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -3303,18 +3919,22 @@ row_scan_and_check_index(
ulint* n_rows) /* out: number of entries seen in the
current consistent read */
{
- mem_heap_t* heap;
- dtuple_t* prev_entry = NULL;
+ dtuple_t* prev_entry = NULL;
ulint matched_fields;
ulint matched_bytes;
byte* buf;
ulint ret;
rec_t* rec;
- ibool is_ok = TRUE;
+ ibool is_ok = TRUE;
int cmp;
ibool contains_null;
ulint i;
-
+ ulint cnt;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
*n_rows = 0;
buf = mem_alloc(UNIV_PAGE_SIZE);
@@ -3332,11 +3952,19 @@ row_scan_and_check_index(
dtuple_set_n_fields(prebuilt->search_tuple, 0);
prebuilt->select_lock_type = LOCK_NONE;
+ cnt = 1000;
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
loop:
+ /* Check thd->killed every 1,000 scanned rows */
+ if (--cnt == 0) {
+ if (trx_is_interrupted(prebuilt->trx)) {
+ goto func_exit;
+ }
+ cnt = 1000;
+ }
if (ret != DB_SUCCESS) {
-
+ func_exit:
mem_free(buf);
mem_heap_free(heap);
@@ -3354,8 +3982,10 @@ loop:
if (prev_entry != NULL) {
matched_fields = 0;
matched_bytes = 0;
-
- cmp = cmp_dtuple_rec_with_match(prev_entry, rec,
+
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ cmp = cmp_dtuple_rec_with_match(prev_entry, rec, offsets,
&matched_fields,
&matched_bytes);
contains_null = FALSE;
@@ -3384,7 +4014,7 @@ loop:
dtuple_print(stderr, prev_entry);
fputs("\n"
"InnoDB: record ", stderr);
- rec_print(stderr, rec);
+ rec_print_new(stderr, rec, offsets);
putc('\n', stderr);
is_ok = FALSE;
} else if ((index->type & DICT_UNIQUE)
@@ -3398,6 +4028,7 @@ loop:
}
mem_heap_empty(heap);
+ offsets = offsets_;
prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
@@ -3460,7 +4091,7 @@ row_check_table_for_mysql(
ut_print_name(stderr, index->name);
putc('\n', stderr); */
- if (!btr_validate_tree(index->tree)) {
+ if (!btr_validate_tree(index->tree, prebuilt->trx)) {
ret = DB_ERROR;
} else {
if (!row_scan_and_check_index(prebuilt,
@@ -3468,6 +4099,10 @@ row_check_table_for_mysql(
ret = DB_ERROR;
}
+ if (trx_is_interrupted(prebuilt->trx)) {
+ break;
+ }
+
/* fprintf(stderr, "%lu entries in index %s\n", n_rows,
index->name); */
diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c
index f7e01169b9d..abcf97110d9 100644
--- a/innobase/row/row0purge.c
+++ b/innobase/row/row0purge.c
@@ -99,6 +99,10 @@ row_purge_remove_clust_if_poss_low(
ibool success;
ulint err;
mtr_t mtr;
+ rec_t* rec;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
index = dict_table_get_first_index(node->table);
@@ -117,15 +121,24 @@ row_purge_remove_clust_if_poss_low(
return(TRUE);
}
+ rec = btr_pcur_get_rec(pcur);
+
if (0 != ut_dulint_cmp(node->roll_ptr,
- row_get_rec_roll_ptr(btr_pcur_get_rec(pcur), index))) {
-
+ row_get_rec_roll_ptr(rec, index, rec_get_offsets(
+ rec, index, offsets_, ULINT_UNDEFINED, &heap)))) {
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
/* Someone else has modified the record later: do not remove */
btr_pcur_commit_specify_mtr(pcur, &mtr);
return(TRUE);
}
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
if (mode == BTR_MODIFY_LEAF) {
success = btr_cur_optimistic_delete(btr_cur, &mtr);
} else {
diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c
index 38714b0c49b..9a74397dc08 100644
--- a/innobase/row/row0row.c
+++ b/innobase/row/row0row.c
@@ -37,17 +37,18 @@ row_get_rec_sys_field(
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
- ulint pos;
- byte* field;
- ulint len;
+ ulint pos;
+ byte* field;
+ ulint len;
ut_ad(index->type & DICT_CLUSTERED);
pos = dict_index_get_sys_col_pos(index, type);
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_TRX_ID) {
@@ -70,6 +71,7 @@ row_set_rec_sys_field(
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val) /* in: value to set */
{
ulint pos;
@@ -77,10 +79,11 @@ row_set_rec_sys_field(
ulint len;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
pos = dict_index_get_sys_col_pos(index, type);
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_TRX_ID) {
@@ -182,6 +185,9 @@ row_build(
the buffer page of this record must be
at least s-latched and the latch held
as long as the row dtuple is used! */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index)
+ or NULL, in which case this function
+ will invoke rec_get_offsets() */
mem_heap_t* heap) /* in: memory heap from which the memory
needed is allocated */
{
@@ -196,14 +202,26 @@ row_build(
ulint row_len;
byte* buf;
ulint i;
-
+ mem_heap_t* tmp_heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_ad(index && rec && heap);
ut_ad(index->type & DICT_CLUSTERED);
+ if (!offsets) {
+ offsets = rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &tmp_heap);
+ } else {
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ }
+
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
- buf = mem_heap_alloc(heap, rec_get_size(rec));
- rec = rec_copy(buf, rec);
+ buf = mem_heap_alloc(heap, rec_offs_size(offsets));
+ rec = rec_copy(buf, rec, offsets);
+ /* Avoid a debug assertion in rec_offs_validate(). */
+ rec_offs_make_valid(rec, index, (ulint*) offsets);
}
table = index->table;
@@ -211,11 +229,9 @@ row_build(
row = dtuple_create(heap, row_len);
- dtuple_set_info_bits(row, rec_get_info_bits(rec));
-
- n_fields = dict_index_get_n_fields(index);
+ dtuple_set_info_bits(row, rec_get_info_bits(rec, table->comp));
- ut_ad(n_fields == rec_get_n_fields(rec));
+ n_fields = rec_offs_n_fields(offsets);
dict_table_copy_types(row, table);
@@ -227,13 +243,13 @@ row_build(
col = dict_field_get_col(ind_field);
dfield = dtuple_get_nth_field(row,
dict_col_get_no(col));
- field = rec_get_nth_field(rec, i, &len);
+ field = rec_get_nth_field(rec, offsets, i, &len);
if (type == ROW_COPY_ALSO_EXTERNALS
- && rec_get_nth_field_extern_bit(rec, i)) {
+ && rec_offs_nth_extern(offsets, i)) {
field = btr_rec_copy_externally_stored_field(
- rec, i, &len, heap);
+ rec, offsets, i, &len, heap);
}
dfield_set_data(dfield, field, len);
@@ -242,6 +258,10 @@ row_build(
ut_ad(dtuple_check_typed(row));
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
+
return(row);
}
@@ -276,16 +296,25 @@ row_rec_to_index_entry(
ulint len;
ulint rec_len;
byte* buf;
-
+ mem_heap_t* tmp_heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_ad(rec && heap && index);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &tmp_heap);
+
if (type == ROW_COPY_DATA) {
/* Take a copy of rec to heap */
- buf = mem_heap_alloc(heap, rec_get_size(rec));
- rec = rec_copy(buf, rec);
+ buf = mem_heap_alloc(heap, rec_offs_size(offsets));
+ rec = rec_copy(buf, rec, offsets);
+ /* Avoid a debug assertion in rec_offs_validate(). */
+ rec_offs_make_valid(rec, index, offsets);
}
- rec_len = rec_get_n_fields(rec);
+ rec_len = rec_offs_n_fields(offsets);
entry = dtuple_create(heap, rec_len);
@@ -295,17 +324,21 @@ row_rec_to_index_entry(
dict_index_copy_types(entry, index, rec_len);
- dtuple_set_info_bits(entry, rec_get_info_bits(rec));
+ dtuple_set_info_bits(entry,
+ rec_get_info_bits(rec, rec_offs_comp(offsets)));
for (i = 0; i < rec_len; i++) {
dfield = dtuple_get_nth_field(entry, i);
- field = rec_get_nth_field(rec, i, &len);
+ field = rec_get_nth_field(rec, offsets, i, &len);
dfield_set_data(dfield, field, len);
}
ut_ad(dtuple_check_typed(entry));
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
return(entry);
}
@@ -345,15 +378,24 @@ row_build_row_ref(
byte* buf;
ulint clust_col_prefix_len;
ulint i;
-
+ mem_heap_t* tmp_heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_ad(index && rec && heap);
-
+
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &tmp_heap);
+
if (type == ROW_COPY_DATA) {
/* Take a copy of rec to heap */
- buf = mem_heap_alloc(heap, rec_get_size(rec));
+ buf = mem_heap_alloc(heap, rec_offs_size(offsets));
- rec = rec_copy(buf, rec);
+ rec = rec_copy(buf, rec, offsets);
+ /* Avoid a debug assertion in rec_offs_validate(). */
+ rec_offs_make_valid(rec, index, offsets);
}
table = index->table;
@@ -373,7 +415,7 @@ row_build_row_ref(
ut_a(pos != ULINT_UNDEFINED);
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
dfield_set_data(dfield, field, len);
@@ -391,12 +433,15 @@ row_build_row_ref(
dfield_set_len(dfield,
dtype_get_at_most_n_mbchars(
dfield_get_type(dfield),
- clust_col_prefix_len, len, field));
+ clust_col_prefix_len, len, (char*) field));
}
}
}
ut_ad(dtuple_check_typed(ref));
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
return(ref);
}
@@ -427,7 +472,11 @@ row_build_row_ref_in_tuple(
ulint pos;
ulint clust_col_prefix_len;
ulint i;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_a(ref && index && rec);
if (!index->table) {
@@ -446,7 +495,9 @@ row_build_row_ref_in_tuple(
fputs("InnoDB: clust index for table ", stderr);
goto notfound;
}
-
+
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+
ref_len = dict_index_get_n_unique(clust_index);
ut_ad(ref_len == dtuple_get_n_fields(ref));
@@ -459,8 +510,8 @@ row_build_row_ref_in_tuple(
pos = dict_index_get_nth_field_pos(index, clust_index, i);
ut_a(pos != ULINT_UNDEFINED);
-
- field = rec_get_nth_field(rec, pos, &len);
+
+ field = rec_get_nth_field(rec, offsets, pos, &len);
dfield_set_data(dfield, field, len);
@@ -478,12 +529,15 @@ row_build_row_ref_in_tuple(
dfield_set_len(dfield,
dtype_get_at_most_n_mbchars(
dfield_get_type(dfield),
- clust_col_prefix_len, len, field));
+ clust_col_prefix_len, len, (char*) field));
}
}
}
ut_ad(dtuple_check_typed(ref));
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
/***********************************************************************
@@ -562,7 +616,6 @@ row_search_on_row_ref(
ulint low_match;
rec_t* rec;
dict_index_t* index;
- page_t* page;
ut_ad(dtuple_check_typed(ref));
@@ -575,9 +628,8 @@ row_search_on_row_ref(
low_match = btr_pcur_get_low_match(pcur);
rec = btr_pcur_get_rec(pcur);
- page = buf_frame_align(rec);
- if (rec == page_get_infimum_rec(page)) {
+ if (page_rec_is_infimum(rec)) {
return(FALSE);
}
@@ -648,7 +700,6 @@ row_search_index_entry(
{
ulint n_fields;
ulint low_match;
- page_t* page;
rec_t* rec;
ut_ad(dtuple_check_typed(entry));
@@ -657,11 +708,10 @@ row_search_index_entry(
low_match = btr_pcur_get_low_match(pcur);
rec = btr_pcur_get_rec(pcur);
- page = buf_frame_align(rec);
n_fields = dtuple_get_n_fields(entry);
- if (rec == page_get_infimum_rec(page)) {
+ if (page_rec_is_infimum(rec)) {
return(FALSE);
}
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index f8218e08297..1b66f14f5d7 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -78,8 +78,20 @@ row_sel_sec_rec_is_for_clust_rec(
ulint n;
ulint i;
dtype_t* cur_type;
+ mem_heap_t* heap = NULL;
+ ulint clust_offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint sec_offsets_[REC_OFFS_SMALL_SIZE];
+ ulint* clust_offs = clust_offsets_;
+ ulint* sec_offs = sec_offsets_;
+ ibool is_equal = TRUE;
- UT_NOT_USED(clust_index);
+ *clust_offsets_ = (sizeof clust_offsets_) / sizeof *clust_offsets_;
+ *sec_offsets_ = (sizeof sec_offsets_) / sizeof *sec_offsets_;
+
+ clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs,
+ ULINT_UNDEFINED, &heap);
+ sec_offs = rec_get_offsets(sec_rec, sec_index, sec_offs,
+ ULINT_UNDEFINED, &heap);
n = dict_index_get_n_ordering_defined_by_user(sec_index);
@@ -87,10 +99,10 @@ row_sel_sec_rec_is_for_clust_rec(
ifield = dict_index_get_nth_field(sec_index, i);
col = dict_field_get_col(ifield);
- clust_field = rec_get_nth_field(clust_rec,
+ clust_field = rec_get_nth_field(clust_rec, clust_offs,
dict_col_get_clust_pos(col),
&clust_len);
- sec_field = rec_get_nth_field(sec_rec, i, &sec_len);
+ sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len);
if (ifield->prefix_len > 0
&& clust_len != UNIV_SQL_NULL) {
@@ -101,17 +113,22 @@ row_sel_sec_rec_is_for_clust_rec(
clust_len = dtype_get_at_most_n_mbchars(
cur_type,
ifield->prefix_len,
- clust_len, clust_field);
+ clust_len, (char*) clust_field);
}
if (0 != cmp_data_data(dict_col_get_type(col),
clust_field, clust_len,
sec_field, sec_len)) {
- return(FALSE);
+ is_equal = FALSE;
+ goto func_exit;
}
}
- return(TRUE);
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(is_equal);
}
/*************************************************************************
@@ -266,6 +283,7 @@ row_sel_fetch_columns(
dict_index_t* index, /* in: record index */
rec_t* rec, /* in: record in a clustered or non-clustered
index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
sym_node_t* column) /* in: first column in a column list, or
NULL */
{
@@ -275,6 +293,8 @@ row_sel_fetch_columns(
byte* data;
ulint len;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (index->type & DICT_CLUSTERED) {
index_type = SYM_CLUST_FIELD_NO;
} else {
@@ -286,7 +306,7 @@ row_sel_fetch_columns(
if (field_no != ULINT_UNDEFINED) {
- data = rec_get_nth_field(rec, field_no, &len);
+ data = rec_get_nth_field(rec, offsets, field_no, &len);
if (column->copy_val) {
eval_node_copy_and_alloc_val(column, data,
@@ -491,6 +511,10 @@ row_sel_build_prev_vers(
read_view_t* read_view, /* in: read view */
plan_t* plan, /* in: plan node for table */
rec_t* rec, /* in: record in a clustered index */
+ ulint** offsets, /* in/out: offsets returned by
+ rec_get_offsets(rec, plan->index) */
+ mem_heap_t** offset_heap, /* in/out: memory heap from which
+ the offsets are allocated */
rec_t** old_vers, /* out: old version, or NULL if the
record does not exist in the view:
i.e., it was freshly inserted
@@ -506,8 +530,8 @@ row_sel_build_prev_vers(
}
err = row_vers_build_for_consistent_read(rec, mtr, plan->index,
- read_view, plan->old_vers_heap,
- old_vers);
+ offsets, read_view, offset_heap,
+ plan->old_vers_heap, old_vers);
return(err);
}
@@ -601,8 +625,18 @@ row_sel_get_clust_rec(
rec_t* clust_rec;
rec_t* old_vers;
ulint err;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
+ *out_rec = NULL;
+
+ offsets = rec_get_offsets(rec,
+ btr_pcur_get_btr_cur(&plan->pcur)->index,
+ offsets, ULINT_UNDEFINED, &heap);
- row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec);
+ row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets);
index = dict_table_get_first_index(plan->table);
@@ -619,7 +653,7 @@ row_sel_get_clust_rec(
|| btr_pcur_get_low_match(&(plan->clust_pcur))
< dict_index_get_n_unique(index)) {
- ut_a(rec_get_deleted_flag(rec));
+ ut_a(rec_get_deleted_flag(rec, plan->table->comp));
ut_a(node->read_view);
/* In a rare case it is possible that no clust rec is found
@@ -631,34 +665,33 @@ row_sel_get_clust_rec(
clustered index record did not exist in the read view of
trx. */
- clust_rec = NULL;
-
goto func_exit;
}
+ offsets = rec_get_offsets(clust_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+
if (!node->read_view) {
/* Try to place a lock on the index record */
/* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
+ we lock only the record, i.e., next-key locking is
+ not used. */
+ ulint lock_type;
if (srv_locks_unsafe_for_binlog) {
- err = lock_clust_rec_read_check_and_lock(0,
- clust_rec,
- index, node->row_lock_mode,
- LOCK_REC_NOT_GAP, thr);
+ lock_type = LOCK_REC_NOT_GAP;
} else {
- err = lock_clust_rec_read_check_and_lock(0,
- clust_rec,
- index, node->row_lock_mode,
- LOCK_ORDINARY, thr);
+ lock_type = LOCK_ORDINARY;
}
+ err = lock_clust_rec_read_check_and_lock(0,
+ clust_rec, index, offsets,
+ node->row_lock_mode, lock_type, thr);
+
if (err != DB_SUCCESS) {
- return(err);
+ goto err_exit;
}
} else {
/* This is a non-locking consistent read: if necessary, fetch
@@ -666,22 +699,21 @@ row_sel_get_clust_rec(
old_vers = NULL;
- if (!lock_clust_rec_cons_read_sees(clust_rec, index,
+ if (!lock_clust_rec_cons_read_sees(clust_rec, index, offsets,
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view, plan,
- clust_rec, &old_vers, mtr);
+ clust_rec, &offsets, &heap,
+ &old_vers, mtr);
if (err != DB_SUCCESS) {
- return(err);
+ goto err_exit;
}
clust_rec = old_vers;
if (clust_rec == NULL) {
- *out_rec = clust_rec;
-
- return(DB_SUCCESS);
+ goto func_exit;
}
}
@@ -698,24 +730,25 @@ row_sel_get_clust_rec(
visit through secondary index records that would not really
exist in our snapshot. */
- if ((old_vers || rec_get_deleted_flag(rec))
+ if ((old_vers || rec_get_deleted_flag(rec, plan->table->comp))
&& !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,
clust_rec, index)) {
- clust_rec = NULL;
- *out_rec = clust_rec;
-
- return(DB_SUCCESS);
+ goto func_exit;
}
}
/* Fetch the columns needed in test conditions */
-
- row_sel_fetch_columns(index, clust_rec,
+
+ row_sel_fetch_columns(index, clust_rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
-func_exit:
*out_rec = clust_rec;
-
- return(DB_SUCCESS);
+func_exit:
+ err = DB_SUCCESS;
+err_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(err);
}
/*************************************************************************
@@ -727,6 +760,7 @@ sel_set_rec_lock(
/* out: DB_SUCCESS or error code */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: lock mode */
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */
que_thr_t* thr) /* in: query thread */
@@ -744,11 +778,11 @@ sel_set_rec_lock(
}
if (index->type & DICT_CLUSTERED) {
- err = lock_clust_rec_read_check_and_lock(0, rec, index, mode,
- type, thr);
+ err = lock_clust_rec_read_check_and_lock(0,
+ rec, index, offsets, mode, type, thr);
} else {
- err = lock_sec_rec_read_check_and_lock(0, rec, index, mode,
- type, thr);
+ err = lock_sec_rec_read_check_and_lock(0,
+ rec, index, offsets, mode, type, thr);
}
return(err);
@@ -956,6 +990,11 @@ row_sel_try_search_shortcut(
{
dict_index_t* index;
rec_t* rec;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ ulint ret;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
index = plan->index;
@@ -989,36 +1028,46 @@ row_sel_try_search_shortcut(
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+
if (index->type & DICT_CLUSTERED) {
- if (!lock_clust_rec_cons_read_sees(rec, index,
+ if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
node->read_view)) {
- return(SEL_RETRY);
+ ret = SEL_RETRY;
+ goto func_exit;
}
} else if (!lock_sec_rec_cons_read_sees(rec, index, node->read_view)) {
- return(SEL_RETRY);
+ ret = SEL_RETRY;
+ goto func_exit;
}
/* Test deleted flag. Fetch the columns needed in test conditions. */
-
- row_sel_fetch_columns(index, rec, UT_LIST_GET_FIRST(plan->columns));
- if (rec_get_deleted_flag(rec)) {
+ row_sel_fetch_columns(index, rec, offsets,
+ UT_LIST_GET_FIRST(plan->columns));
- return(SEL_EXHAUSTED);
+ if (rec_get_deleted_flag(rec, plan->table->comp)) {
+
+ ret = SEL_EXHAUSTED;
+ goto func_exit;
}
/* Test the rest of search conditions */
if (!row_sel_test_other_conds(plan)) {
- return(SEL_EXHAUSTED);
+ ret = SEL_EXHAUSTED;
+ goto func_exit;
}
ut_ad(plan->pcur.latch_mode == node->latch_mode);
plan->n_rows_fetched++;
-
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(SEL_FOUND);
}
@@ -1067,7 +1116,11 @@ row_sel(
to the next non-clustered record */
ulint found_flag;
ulint err;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_ad(thr->run_node == node);
search_latch_locked = FALSE;
@@ -1207,7 +1260,7 @@ rec_loop:
/* PHASE 1: Set a lock if specified */
if (!node->asc && cursor_just_opened
- && (rec != page_get_supremum_rec(buf_frame_align(rec)))) {
+ && !page_rec_is_supremum(rec)) {
/* When we open a cursor for a descending search, we must set
a next-key lock on the successor record: otherwise it would
@@ -1218,22 +1271,23 @@ rec_loop:
if (!consistent_read) {
/* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
+ we lock only the record, i.e., next-key locking is
+ not used. */
+
+ rec_t* next_rec = page_rec_get_next(rec);
+ ulint lock_type;
+ offsets = rec_get_offsets(next_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
if (srv_locks_unsafe_for_binlog) {
- err = sel_set_rec_lock(page_rec_get_next(rec),
- index,
- node->row_lock_mode,
- LOCK_REC_NOT_GAP, thr);
+ lock_type = LOCK_REC_NOT_GAP;
} else {
- err = sel_set_rec_lock(page_rec_get_next(rec),
- index,
- node->row_lock_mode,
- LOCK_ORDINARY, thr);
+ lock_type = LOCK_ORDINARY;
}
+ err = sel_set_rec_lock(next_rec, index, offsets,
+ node->row_lock_mode, lock_type, thr);
+
if (err != DB_SUCCESS) {
/* Note that in this case we will store in pcur
the PREDECESSOR of the record we are waiting
@@ -1244,7 +1298,7 @@ rec_loop:
}
}
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
+ if (page_rec_is_infimum(rec)) {
/* The infimum record on a page cannot be in the result set,
and neither can a record lock be placed on it: we skip such
@@ -1260,25 +1314,29 @@ rec_loop:
/* Try to place a lock on the index record */
/* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
+ we lock only the record, i.e., next-key locking is
+ not used. */
+
+ ulint lock_type;
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
if (srv_locks_unsafe_for_binlog) {
- err = sel_set_rec_lock(rec, index, node->row_lock_mode,
- LOCK_REC_NOT_GAP, thr);
+ lock_type = LOCK_REC_NOT_GAP;
} else {
- err = sel_set_rec_lock(rec, index, node->row_lock_mode,
- LOCK_ORDINARY, thr);
+ lock_type = LOCK_ORDINARY;
}
+ err = sel_set_rec_lock(rec, index, offsets,
+ node->row_lock_mode, lock_type, thr);
+
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
}
}
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ if (page_rec_is_supremum(rec)) {
/* A page supremum record cannot be in the result set: skip
it now when we have placed a possible lock on it */
@@ -1334,6 +1392,7 @@ rec_loop:
/* PHASE 3: Get previous version in a consistent read */
cons_read_requires_clust_rec = FALSE;
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
if (consistent_read) {
/* This is a non-locking consistent read: if necessary, fetch
@@ -1341,19 +1400,24 @@ rec_loop:
if (index->type & DICT_CLUSTERED) {
- if (!lock_clust_rec_cons_read_sees(rec, index,
+ if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view,
- plan, rec, &old_vers,
- &mtr);
+ plan, rec,
+ &offsets, &heap,
+ &old_vers, &mtr);
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
}
if (old_vers == NULL) {
+ offsets = rec_get_offsets(
+ rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
row_sel_fetch_columns(index, rec,
+ offsets,
UT_LIST_GET_FIRST(plan->columns));
if (!row_sel_test_end_conds(plan)) {
@@ -1376,7 +1440,8 @@ rec_loop:
/* Fetch the columns needed in test conditions */
- row_sel_fetch_columns(index, rec, UT_LIST_GET_FIRST(plan->columns));
+ row_sel_fetch_columns(index, rec, offsets,
+ UT_LIST_GET_FIRST(plan->columns));
/* Test the selection end conditions: these can only contain columns
which already are found in the index, even though the index might be
@@ -1391,7 +1456,8 @@ rec_loop:
goto table_exhausted;
}
- if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) {
+ if (rec_get_deleted_flag(rec, plan->table->comp)
+ && !cons_read_requires_clust_rec) {
/* The record is delete marked: we can skip it if this is
not a consistent read which might see an earlier version
@@ -1434,7 +1500,7 @@ rec_loop:
goto next_rec;
}
- if (rec_get_deleted_flag(clust_rec)) {
+ if (rec_get_deleted_flag(clust_rec, plan->table->comp)) {
/* The record is delete marked: we can skip it */
@@ -1592,8 +1658,9 @@ next_table_no_mtr:
if (search_latch_locked) {
rw_lock_s_unlock(&btr_search_latch);
}
-
- return(DB_SUCCESS);
+
+ err = DB_SUCCESS;
+ goto func_exit;
}
node->fetch_table++;
@@ -1626,6 +1693,7 @@ table_exhausted:
table_exhausted_no_mtr:
if (node->fetch_table == 0) {
+ err = DB_SUCCESS;
if (node->is_aggregate && !node->aggregate_already_fetched) {
@@ -1639,7 +1707,7 @@ table_exhausted_no_mtr:
rw_lock_s_unlock(&btr_search_latch);
}
- return(DB_SUCCESS);
+ goto func_exit;
}
node->state = SEL_NODE_NO_MORE_ROWS;
@@ -1650,7 +1718,7 @@ table_exhausted_no_mtr:
rw_lock_s_unlock(&btr_search_latch);
}
- return(DB_SUCCESS);
+ goto func_exit;
}
node->fetch_table--;
@@ -1674,8 +1742,8 @@ stop_for_a_while:
mtr_commit(&mtr);
ut_ad(sync_thread_levels_empty_gen(TRUE));
-
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+ goto func_exit;
commit_mtr_for_a_while:
/* Stores the cursor position and commits &mtr; this is used if
@@ -1710,6 +1778,10 @@ lock_wait_or_error:
ut_ad(sync_thread_levels_empty_gen(TRUE));
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(err);
}
@@ -1945,7 +2017,8 @@ Converts a key value stored in MySQL format to an Innobase dtuple. The last
field of the key value may be just a prefix of a fixed length field: hence
the parameter key_len. But currently we do not allow search keys where the
last field is only a prefix of the full key field len and print a warning if
-such appears. */
+such appears. A counterpart of this function is
+ha_innobase::store_key_val_for_row() in ha_innodb.cc. */
void
row_sel_convert_mysql_key_to_innobase(
@@ -2026,10 +2099,10 @@ row_sel_convert_mysql_key_to_innobase(
type = dfield_get_type(dfield)->mtype;
/* Calculate data length and data field total length */
-
+
if (type == DATA_BLOB) {
/* The key field is a column prefix of a BLOB or
- TEXT type column */
+ TEXT */
ut_a(field->prefix_len > 0);
@@ -2045,11 +2118,12 @@ row_sel_convert_mysql_key_to_innobase(
data_len = key_ptr[data_offset]
+ 256 * key_ptr[data_offset + 1];
data_field_len = data_offset + 2 + field->prefix_len;
+
data_offset += 2;
-
- type = DATA_CHAR; /* now that we know the length, we
- store the column value like it would
- be a fixed char field */
+
+ /* Now that we know the length, we store the column
+ value like it would be a fixed char field */
+
} else if (field->prefix_len > 0) {
/* Looks like MySQL pads unused end bytes in the
prefix with space. Therefore, also in UTF-8, it is ok
@@ -2069,14 +2143,32 @@ row_sel_convert_mysql_key_to_innobase(
data_field_len = data_offset + data_len;
}
+ if (dtype_get_mysql_type(dfield_get_type(dfield))
+ == DATA_MYSQL_TRUE_VARCHAR
+ && dfield_get_type(dfield)->mtype != DATA_INT) {
+ /* In a MySQL key value format, a true VARCHAR is
+ always preceded by 2 bytes of a length field.
+ dfield_get_type(dfield)->len returns the maximum
+ 'payload' len in bytes. That does not include the
+ 2 bytes that tell the actual data length.
+
+ We added the check != DATA_INT to make sure we do
+ not treat MySQL ENUM or SET as a true VARCHAR! */
+
+ data_len += 2;
+ data_field_len += 2;
+ }
+
/* Storing may use at most data_len bytes of buf */
if (!is_null) {
row_mysql_store_col_in_innobase_format(
- dfield, buf, key_ptr + data_offset,
- data_len, type,
- dfield_get_type(dfield)->prtype
- & DATA_UNSIGNED);
+ dfield,
+ buf,
+ FALSE, /* MySQL key value format col */
+ key_ptr + data_offset,
+ data_len,
+ index->table->comp);
buf += data_len;
}
@@ -2133,11 +2225,16 @@ row_sel_store_row_id_to_prebuilt(
/*=============================*/
row_prebuilt_t* prebuilt, /* in: prebuilt */
rec_t* index_rec, /* in: record */
- dict_index_t* index) /* in: index of the record */
+ dict_index_t* index, /* in: index of the record */
+ const ulint* offsets) /* in: rec_get_offsets
+ (index_rec, index) */
{
byte* data;
ulint len;
- data = rec_get_nth_field(index_rec,
+
+ ut_ad(rec_offs_validate(index_rec, index, offsets));
+
+ data = rec_get_nth_field(index_rec, offsets,
dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len);
if (len != DATA_ROW_ID_LEN) {
@@ -2146,8 +2243,8 @@ row_sel_store_row_id_to_prebuilt(
dict_index_name_print(stderr, prebuilt->trx, index);
fprintf(stderr, "\n"
"InnoDB: Field number %lu, record:\n",
- (ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID));
- rec_print(stderr, index_rec);
+ (ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID));
+ rec_print_new(stderr, index_rec, offsets);
putc('\n', stderr);
ut_error;
}
@@ -2156,8 +2253,9 @@ row_sel_store_row_id_to_prebuilt(
}
/******************************************************************
-Stores a non-SQL-NULL field in the MySQL format. */
-UNIV_INLINE
+Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
+function is row_mysql_store_col_in_innobase_format() in row0mysql.c. */
+static
void
row_sel_field_store_in_mysql_format(
/*================================*/
@@ -2165,17 +2263,19 @@ row_sel_field_store_in_mysql_format(
are not in themselves stored here: the caller must
allocate and copy the BLOB into buffer before, and pass
the pointer to the BLOB in 'data' */
- ulint col_len,/* in: MySQL column length */
+ const mysql_row_templ_t* templ, /* in: MySQL column template.
+ Its following fields are referenced:
+ type, is_unsigned, mysql_col_len, mbminlen, mbmaxlen */
byte* data, /* in: data to store */
- ulint len, /* in: length of the data */
- ulint type, /* in: data type */
- ulint is_unsigned)/* in: != 0 if an unsigned integer type */
+ ulint len) /* in: length of the data */
{
byte* ptr;
+ byte* field_end;
+ byte* pad_ptr;
ut_ad(len != UNIV_SQL_NULL);
- if (type == DATA_INT) {
+ if (templ->type == DATA_INT) {
/* Convert integer data from Innobase to a little-endian
format, sign bit restored to normal */
@@ -2190,31 +2290,103 @@ row_sel_field_store_in_mysql_format(
data++;
}
- if (!is_unsigned) {
+ if (!templ->is_unsigned) {
dest[len - 1] = (byte) (dest[len - 1] ^ 128);
}
- ut_ad(col_len == len);
- } else if (type == DATA_VARCHAR || type == DATA_VARMYSQL
- || type == DATA_BINARY) {
- /* Store the length of the data to the first two bytes of
- dest; does not do anything yet because MySQL has
- no real vars! */
+ ut_ad(templ->mysql_col_len == len);
+ } else if (templ->type == DATA_VARCHAR
+ || templ->type == DATA_VARMYSQL
+ || templ->type == DATA_BINARY) {
+
+ field_end = dest + templ->mysql_col_len;
+
+ if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
+ /* This is a >= 5.0.3 type true VARCHAR. Store the
+ length of the data to the first byte or the first
+ two bytes of dest. */
- dest = row_mysql_store_var_len(dest, len);
- ut_memcpy(dest, data, len);
+ dest = row_mysql_store_true_var_len(dest, len,
+ templ->mysql_length_bytes);
+ }
- /* ut_ad(col_len >= len + 2); No real var implemented in
- MySQL yet! */
+ /* Copy the actual data */
+ ut_memcpy(dest, data, len);
- } else if (type == DATA_BLOB) {
+ /* Pad with trailing spaces. We pad with spaces also the
+ unused end of a >= 5.0.3 true VARCHAR column, just in case
+ MySQL expects its contents to be deterministic. */
+
+ pad_ptr = dest + len;
+
+ ut_ad(templ->mbminlen <= templ->mbmaxlen);
+
+ /* We handle UCS2 charset strings differently. */
+ if (templ->mbminlen == 2) {
+ /* A space char is two bytes, 0x0020 in UCS2 */
+
+ if (len & 1) {
+ /* A 0x20 has been stripped from the column.
+ Pad it back. */
+
+ if (pad_ptr < field_end) {
+ *pad_ptr = 0x20;
+ pad_ptr++;
+ }
+ }
+
+ /* Pad the rest of the string with 0x0020 */
+
+ while (pad_ptr < field_end) {
+ *pad_ptr = 0x00;
+ pad_ptr++;
+ *pad_ptr = 0x20;
+ pad_ptr++;
+ }
+ } else {
+ ut_ad(templ->mbminlen == 1);
+ /* space=0x20 */
+
+ memset(pad_ptr, 0x20, field_end - pad_ptr);
+ }
+ } else if (templ->type == DATA_BLOB) {
/* Store a pointer to the BLOB buffer to dest: the BLOB was
already copied to the buffer in row_sel_store_mysql_rec */
- row_mysql_store_blob_ref(dest, col_len, data, len);
+ row_mysql_store_blob_ref(dest, templ->mysql_col_len, data,
+ len);
+ } else if (templ->type == DATA_MYSQL) {
+ memcpy(dest, data, len);
+
+ ut_a(templ->mysql_col_len >= len);
+ ut_a(templ->mbmaxlen >= templ->mbminlen);
+
+ ut_a(templ->mbmaxlen > templ->mbminlen
+ || templ->mysql_col_len == len);
+ /* The following assertion would fail for old tables
+ containing UTF-8 ENUM columns due to Bug #9526. */
+ ut_ad(!templ->mbmaxlen
+ || !(templ->mysql_col_len % templ->mbmaxlen));
+ ut_a(len * templ->mbmaxlen >= templ->mysql_col_len);
+
+ if (templ->mbminlen != templ->mbmaxlen) {
+ /* Pad with spaces. This undoes the stripping
+ done in row0mysql.ic, function
+ row_mysql_store_col_in_innobase_format(). */
+
+ memset(dest + len, 0x20, templ->mysql_col_len - len);
+ }
} else {
- ut_memcpy(dest, data, len);
- ut_ad(col_len == len);
+ ut_a(templ->type == DATA_CHAR
+ || templ->type == DATA_FIXBINARY
+ /*|| templ->type == DATA_SYS_CHILD
+ || templ->type == DATA_SYS*/
+ || templ->type == DATA_FLOAT
+ || templ->type == DATA_DOUBLE
+ || templ->type == DATA_DECIMAL);
+ ut_ad(templ->mysql_col_len == len);
+
+ memcpy(dest, data, len);
}
}
@@ -2233,37 +2405,35 @@ row_sel_store_mysql_rec(
case) */
byte* mysql_rec, /* out: row in the MySQL format */
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
- rec_t* rec) /* in: Innobase record in the index
+ rec_t* rec, /* in: Innobase record in the index
which was described in prebuilt's
template */
+ const ulint* offsets) /* in: array returned by
+ rec_get_offsets() */
{
mysql_row_templ_t* templ;
mem_heap_t* extern_field_heap = NULL;
byte* data;
ulint len;
- byte* blob_buf;
- int pad_char;
ulint i;
ut_ad(prebuilt->mysql_template);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
- if (prebuilt->blob_heap != NULL) {
+ if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
mem_heap_free(prebuilt->blob_heap);
prebuilt->blob_heap = NULL;
}
- /* MySQL assumes that all columns have the SQL NULL bit set unless it
- is a nullable column with a non-NULL value */
-
- memset(mysql_rec, 0xFF, prebuilt->null_bitmap_len);
-
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
- data = rec_get_nth_field(rec, templ->rec_field_no, &len);
+ data = rec_get_nth_field(rec, offsets,
+ templ->rec_field_no, &len);
- if (rec_get_nth_field_extern_bit(rec, templ->rec_field_no)) {
+ if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
+ templ->rec_field_no))) {
/* Copy an externally stored field to the temporary
heap */
@@ -2277,14 +2447,14 @@ row_sel_store_mysql_rec(
causes an assert */
data = btr_rec_copy_externally_stored_field(rec,
- templ->rec_field_no, &len,
+ offsets, templ->rec_field_no, &len,
extern_field_heap);
ut_a(len != UNIV_SQL_NULL);
}
if (len != UNIV_SQL_NULL) {
- if (templ->type == DATA_BLOB) {
+ if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
ut_a(prebuilt->templ_contains_blob);
@@ -2293,8 +2463,9 @@ row_sel_store_mysql_rec(
of 1000000 bytes. Since the test takes some
CPU time, we do not use it for small BLOBs. */
- if (len > 2000000
- && !ut_test_malloc(len + 1000000)) {
+ if (UNIV_UNLIKELY(len > 2000000)
+ && UNIV_UNLIKELY(!ut_test_malloc(
+ len + 1000000))) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -2320,55 +2491,14 @@ row_sel_store_mysql_rec(
mem_heap_create(len);
}
- blob_buf = mem_heap_alloc(prebuilt->blob_heap,
- len);
- ut_memcpy(blob_buf, data, len);
-
- data = blob_buf;
+ data = memcpy(mem_heap_alloc(
+ prebuilt->blob_heap, len),
+ data, len);
}
row_sel_field_store_in_mysql_format(
mysql_rec + templ->mysql_col_offset,
- templ->mysql_col_len, data, len,
- templ->type, templ->is_unsigned);
-
- if (templ->type == DATA_VARCHAR
- || templ->type == DATA_VARMYSQL
- || templ->type == DATA_BINARY) {
- /* Pad with trailing spaces */
- data = mysql_rec + templ->mysql_col_offset;
-
- /* Handle UCS2 strings differently. As no new
- collations will be introduced in 4.1, we
- hardcode the charset-collation codes here.
- 5.0 will use a different approach. */
- if (templ->charset == 35
- || templ->charset == 90
- || (templ->charset >= 128
- && templ->charset <= 144)) {
- /* space=0x0020 */
- ulint col_len = templ->mysql_col_len;
-
- ut_a(!(col_len & 1));
- if (len & 1) {
- /* A 0x20 has been stripped
- from the column.
- Pad it back. */
- goto pad_0x20;
- }
- /* Pad the rest of the string
- with 0x0020 */
- while (len < col_len) {
- data[len++] = 0x00;
- pad_0x20:
- data[len++] = 0x20;
- }
- } else {
- /* space=0x20 */
- memset(data + len, 0x20,
- templ->mysql_col_len - len);
- }
- }
+ templ, data, len);
/* Cleanup */
if (extern_field_heap) {
@@ -2388,45 +2518,53 @@ row_sel_store_mysql_rec(
account caused seg faults with NULL BLOB fields, and
bug number 154 in the MySQL bug database: GROUP BY
and DISTINCT could treat NULL values inequal. */
-
- if (templ->type == DATA_VARCHAR
- || templ->type == DATA_CHAR
- || templ->type == DATA_BINARY
- || templ->type == DATA_FIXBINARY
- || templ->type == DATA_MYSQL
- || templ->type == DATA_VARMYSQL) {
- /* MySQL pads all non-BLOB and non-TEXT
- string types with space ' ' */
-
- pad_char = ' ';
- } else {
- pad_char = '\0';
+ int pad_char;
+
+ mysql_rec[templ->mysql_null_byte_offset] |=
+ (byte) (templ->mysql_null_bit_mask);
+ switch (templ->type) {
+ case DATA_VARCHAR:
+ case DATA_BINARY:
+ case DATA_VARMYSQL:
+ if (templ->mysql_type
+ == DATA_MYSQL_TRUE_VARCHAR) {
+ /* This is a >= 5.0.3 type
+ true VARCHAR. Zero the field. */
+ pad_char = 0x00;
+ break;
+ }
+ /* Fall through */
+ case DATA_CHAR:
+ case DATA_FIXBINARY:
+ case DATA_MYSQL:
+ /* MySQL pads all string types (except
+ BLOB, TEXT and true VARCHAR) with space. */
+ if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
+ /* Treat UCS2 as a special case. */
+ data = mysql_rec
+ + templ->mysql_col_offset;
+ len = templ->mysql_col_len;
+ /* There are two UCS2 bytes per char,
+ so the length has to be even. */
+ ut_a(!(len & 1));
+ /* Pad with 0x0020. */
+ while (len) {
+ *data++ = 0x00;
+ *data++ = 0x20;
+ len -= 2;
+ }
+ continue;
+ }
+ pad_char = 0x20;
+ break;
+ default:
+ pad_char = 0x00;
+ break;
}
- /* Handle UCS2 strings differently. As no new
- collations will be introduced in 4.1,
- we hardcode the charset-collation codes here.
- 5.0 will use a different approach. */
- if (pad_char != '\0'
- && (templ->charset == 35
- || templ->charset == 90
- || (templ->charset >= 128
- && templ->charset <= 144))) {
- /* There are two bytes per char, so the length
- has to be an even number. */
- ut_a(!(templ->mysql_col_len & 1));
- data = mysql_rec + templ->mysql_col_offset;
- len = templ->mysql_col_len;
- /* Pad with 0x0020. */
- while (len >= 2) {
- *data++ = 0x00;
- *data++ = 0x20;
- len -= 2;
- }
- } else {
- memset(mysql_rec + templ->mysql_col_offset,
+ ut_ad(!pad_char || templ->mbminlen == 1);
+ memset(mysql_rec + templ->mysql_col_offset,
pad_char, templ->mysql_col_len);
- }
}
}
@@ -2444,6 +2582,10 @@ row_sel_build_prev_vers_for_mysql(
dict_index_t* clust_index, /* in: clustered index */
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
rec_t* rec, /* in: record in a clustered index */
+ ulint** offsets, /* in/out: offsets returned by
+ rec_get_offsets(rec, clust_index) */
+ mem_heap_t** offset_heap, /* in/out: memory heap from which
+ the offsets are allocated */
rec_t** old_vers, /* out: old version, or NULL if the
record does not exist in the view:
i.e., it was freshly inserted
@@ -2459,8 +2601,8 @@ row_sel_build_prev_vers_for_mysql(
}
err = row_vers_build_for_consistent_read(rec, mtr, clust_index,
- read_view, prebuilt->old_vers_heap,
- old_vers);
+ offsets, read_view, offset_heap,
+ prebuilt->old_vers_heap, old_vers);
return(err);
}
@@ -2484,6 +2626,10 @@ row_sel_get_clust_rec_for_mysql(
it, NULL if the old version did not exist
in the read view, i.e., it was a fresh
inserted version */
+ ulint** offsets,/* out: offsets returned by
+ rec_get_offsets(out_rec, clust_index) */
+ mem_heap_t** offset_heap,/* in/out: memory heap from which
+ the offsets are allocated */
mtr_t* mtr) /* in: mtr used to get access to the
non-clustered record; the same mtr is used to
access the clustered index */
@@ -2525,9 +2671,8 @@ row_sel_get_clust_rec_for_mysql(
clustered index record did not exist in the read view of
trx. */
- if (!rec_get_deleted_flag(rec)
+ if (!rec_get_deleted_flag(rec, sec_index->table->comp)
|| prebuilt->select_lock_type != LOCK_NONE) {
-
ut_print_timestamp(stderr);
fputs(" InnoDB: error clustered record"
" for sec rec not found\n"
@@ -2535,12 +2680,12 @@ row_sel_get_clust_rec_for_mysql(
dict_index_name_print(stderr, trx, sec_index);
fputs("\n"
"InnoDB: sec index record ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, sec_index);
fputs("\n"
"InnoDB: clust index record ", stderr);
- rec_print(stderr, clust_rec);
+ rec_print(stderr, clust_rec, clust_index);
putc('\n', stderr);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 600);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
@@ -2551,18 +2696,21 @@ row_sel_get_clust_rec_for_mysql(
goto func_exit;
}
+ *offsets = rec_get_offsets(clust_rec, clust_index, *offsets,
+ ULINT_UNDEFINED, offset_heap);
+
if (prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record; we are searching
the clust rec with a unique condition, hence
we set a LOCK_REC_NOT_GAP type lock */
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
- clust_index,
+ clust_index, *offsets,
prebuilt->select_lock_type,
LOCK_REC_NOT_GAP, thr);
if (err != DB_SUCCESS) {
- return(err);
+ goto err_exit;
}
} else {
/* This is a non-locking consistent read: if necessary, fetch
@@ -2575,16 +2723,19 @@ row_sel_get_clust_rec_for_mysql(
if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
&& !lock_clust_rec_cons_read_sees(clust_rec, clust_index,
- trx->read_view)) {
-
+ *offsets, trx->read_view)) {
+
+ /* The following call returns 'offsets' associated with
+ 'old_vers' */
err = row_sel_build_prev_vers_for_mysql(
trx->read_view, clust_index,
prebuilt, clust_rec,
+ offsets, offset_heap,
&old_vers, mtr);
if (err != DB_SUCCESS) {
- return(err);
+ goto err_exit;
}
clust_rec = old_vers;
@@ -2603,7 +2754,8 @@ row_sel_get_clust_rec_for_mysql(
visit through secondary index records that would not really
exist in our snapshot. */
- if (clust_rec && (old_vers || rec_get_deleted_flag(rec))
+ if (clust_rec && (old_vers
+ || rec_get_deleted_flag(rec, sec_index->table->comp))
&& !row_sel_sec_rec_is_for_clust_rec(rec, sec_index,
clust_rec, clust_index)) {
clust_rec = NULL;
@@ -2625,7 +2777,9 @@ func_exit:
btr_pcur_store_position(prebuilt->clust_pcur, mtr);
}
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+err_exit:
+ return(err);
}
/************************************************************************
@@ -2640,6 +2794,10 @@ sel_restore_position_for_mysql(
process the record the cursor is
now positioned on (i.e. we should
not go to the next record yet) */
+ ibool* same_user_rec, /* out: TRUE if we were able to restore
+ the cursor on a user record with the
+ same ordering prefix in in the
+ B-tree index */
ulint latch_mode, /* in: latch mode wished in
restoration */
btr_pcur_t* pcur, /* in: cursor whose position
@@ -2656,6 +2814,8 @@ sel_restore_position_for_mysql(
success = btr_pcur_restore_position(latch_mode, pcur, mtr);
+ *same_user_rec = success;
+
if (relative_position == BTR_PCUR_ON) {
if (success) {
return(FALSE);
@@ -2702,10 +2862,41 @@ row_sel_pop_cached_row_for_mysql(
row */
row_prebuilt_t* prebuilt) /* in: prebuilt struct */
{
- ut_ad(prebuilt->n_fetch_cached > 0);
-
- ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first],
- prebuilt->mysql_row_len);
+ ulint i;
+ mysql_row_templ_t* templ;
+ byte* cached_rec;
+ ut_ad(prebuilt->n_fetch_cached > 0);
+ ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
+
+ if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread))
+ {
+ /* Copy cache record field by field, don't touch fields that
+ are not covered by current key */
+ cached_rec =
+ prebuilt->fetch_cache[prebuilt->fetch_cache_first];
+
+ for (i = 0; i < prebuilt->n_template; i++) {
+ templ = prebuilt->mysql_template + i;
+ ut_memcpy(
+ buf + templ->mysql_col_offset,
+ cached_rec + templ->mysql_col_offset,
+ templ->mysql_col_len);
+ /* Copy NULL bit of the current field from cached_rec
+ to buf */
+ if (templ->mysql_null_bit_mask)
+ {
+ buf[templ->mysql_null_byte_offset] ^=
+ (buf[templ->mysql_null_byte_offset] ^
+ cached_rec[templ->mysql_null_byte_offset]) &
+ (byte)templ->mysql_null_bit_mask;
+ }
+ }
+ }
+ else
+ {
+ ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first],
+ prebuilt->mysql_prefix_len);
+ }
prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++;
@@ -2721,12 +2912,14 @@ void
row_sel_push_cache_row_for_mysql(
/*=============================*/
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
- rec_t* rec) /* in: record to push */
+ rec_t* rec, /* in: record to push */
+ const ulint* offsets) /* in: rec_get_offsets() */
{
byte* buf;
ulint i;
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_a(!prebuilt->templ_contains_blob);
if (prebuilt->fetch_cache[0] == NULL) {
@@ -2750,9 +2943,11 @@ row_sel_push_cache_row_for_mysql(
ut_ad(prebuilt->fetch_cache_first == 0);
- ut_a(row_sel_store_mysql_rec(
+ if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
prebuilt->fetch_cache[prebuilt->n_fetch_cached],
- prebuilt, rec));
+ prebuilt, rec, offsets))) {
+ ut_error;
+ }
prebuilt->n_fetch_cached++;
}
@@ -2769,6 +2964,8 @@ row_sel_try_search_shortcut_for_mysql(
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
rec_t** out_rec,/* out: record if found */
row_prebuilt_t* prebuilt,/* in: prebuilt struct */
+ ulint** offsets,/* in/out: for rec_get_offsets(*out_rec) */
+ mem_heap_t** heap, /* in/out: heap for rec_get_offsets() */
mtr_t* mtr) /* in: started mtr */
{
dict_index_t* index = prebuilt->index;
@@ -2806,13 +3003,17 @@ row_sel_try_search_shortcut_for_mysql(
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
-
- if (!lock_clust_rec_cons_read_sees(rec, index, trx->read_view)) {
+
+ *offsets = rec_get_offsets(rec, index, *offsets,
+ ULINT_UNDEFINED, heap);
+
+ if (!lock_clust_rec_cons_read_sees(rec, index,
+ *offsets, trx->read_view)) {
return(SEL_RETRY);
}
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, index->table->comp)) {
return(SEL_EXHAUSTED);
}
@@ -2856,21 +3057,17 @@ row_search_for_mysql(
cursor 'direction' should be 0. */
{
dict_index_t* index = prebuilt->index;
+ ibool comp = index->table->comp;
dtuple_t* search_tuple = prebuilt->search_tuple;
btr_pcur_t* pcur = prebuilt->pcur;
trx_t* trx = prebuilt->trx;
dict_index_t* clust_index;
que_thr_t* thr;
rec_t* rec;
- rec_t* index_rec;
+ rec_t* result_rec;
rec_t* clust_rec;
rec_t* old_vers;
- ulint err = DB_SUCCESS;
- ibool moved;
- ibool cons_read_requires_clust_rec;
- ibool was_lock_wait;
- ulint ret;
- ulint shortcut;
+ ulint err = DB_SUCCESS;
ibool unique_search = FALSE;
ibool unique_search_from_clust_index = FALSE;
ibool mtr_has_extra_clust_latch = FALSE;
@@ -2880,15 +3077,22 @@ row_search_for_mysql(
locking SELECT, and the isolation
level is <= TRX_ISO_READ_COMMITTED,
then this is set to FALSE */
- ibool success;
+#ifdef UNIV_SEARCH_DEBUG
ulint cnt = 0;
+#endif /* UNIV_SEARCH_DEBUG */
ulint next_offs;
+ ibool same_user_rec;
mtr_t mtr;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_ad(index && pcur && search_tuple);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- if (prebuilt->table->ibd_file_missing) {
+ if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error:\n"
"InnoDB: MySQL is trying to use a table handle but the .ibd file for\n"
@@ -2899,10 +3103,11 @@ row_search_for_mysql(
"http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
"InnoDB: how you can resolve the problem.\n",
prebuilt->table->name);
+
return(DB_ERROR);
}
- if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
+ if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
"InnoDB: table handle. Magic n %lu, table name ",
@@ -2916,18 +3121,23 @@ row_search_for_mysql(
}
if (trx->n_mysql_tables_in_use == 0
- && prebuilt->select_lock_type == LOCK_NONE) {
+ && UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) {
/* Note that if MySQL uses an InnoDB temp table that it
created inside LOCK TABLES, then n_mysql_tables_in_use can
be zero; in that case select_lock_type is set to LOCK_X in
::start_stmt. */
+/* August 19, 2005 by Heikki: temporarily disable this error print until the
+cursor lock count is done correctly. See bugs #12263 and #12456!
+
fputs(
"InnoDB: Error: MySQL is trying to perform a SELECT\n"
"InnoDB: but it has not locked any tables in ::external_lock()!\n",
stderr);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 600);
fputc('\n', stderr);
+*/
+
}
/* fprintf(stderr, "Match mode %lu\n search tuple ", (ulong) match_mode);
@@ -2939,8 +3149,8 @@ row_search_for_mysql(
/* PHASE 0: Release a possible s-latch we are holding on the
adaptive hash index latch if there is someone waiting behind */
- if (trx->has_search_latch
- && btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
+ if (UNIV_UNLIKELY(btr_search_latch.writer != RW_LOCK_NOT_LOCKED)
+ && trx->has_search_latch) {
/* There is an x-latch request on the adaptive hash index:
release the s-latch to reduce starvation and wait for
@@ -2953,10 +3163,20 @@ row_search_for_mysql(
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
}
+ /* Reset the new record lock info if we srv_locks_unsafe_for_binlog
+ is set. Then we are able to remove the record locks set here on an
+ individual row. */
+
+ if (srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
+
+ trx_reset_new_rec_lock_info(trx);
+ }
+
/*-------------------------------------------------------------*/
/* PHASE 1: Try to pop the row from the prefetch cache */
- if (direction == 0) {
+ if (UNIV_UNLIKELY(direction == 0)) {
trx->op_info = "starting index read";
prebuilt->n_rows_fetched = 0;
@@ -2974,8 +3194,8 @@ row_search_for_mysql(
prebuilt->fetch_direction = direction;
}
- if (direction != prebuilt->fetch_direction) {
- if (prebuilt->n_fetch_cached > 0) {
+ if (UNIV_UNLIKELY(direction != prebuilt->fetch_direction)) {
+ if (UNIV_UNLIKELY(prebuilt->n_fetch_cached > 0)) {
ut_error;
/* TODO: scrollable cursor: restore cursor to
the place of the latest returned row,
@@ -2987,15 +3207,14 @@ row_search_for_mysql(
prebuilt->n_fetch_cached = 0;
prebuilt->fetch_cache_first = 0;
- } else if (prebuilt->n_fetch_cached > 0) {
+ } else if (UNIV_LIKELY(prebuilt->n_fetch_cached > 0)) {
row_sel_pop_cached_row_for_mysql(buf, prebuilt);
prebuilt->n_rows_fetched++;
srv_n_rows_read++;
- trx->op_info = "";
-
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+ goto func_exit;
}
if (prebuilt->fetch_cache_first > 0
@@ -3004,9 +3223,9 @@ row_search_for_mysql(
/* The previous returned row was popped from the fetch
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 = "";
- return(DB_RECORD_NOT_FOUND);
+
+ err = DB_RECORD_NOT_FOUND;
+ goto func_exit;
}
prebuilt->n_rows_fetched++;
@@ -3048,10 +3267,11 @@ row_search_for_mysql(
1 column. Return immediately if this is not a HANDLER
command. */
- if (direction != 0 && !prebuilt->used_in_HANDLER) {
+ if (UNIV_UNLIKELY(direction != 0 &&
+ !prebuilt->used_in_HANDLER)) {
- trx->op_info = "";
- return(DB_RECORD_NOT_FOUND);
+ err = DB_RECORD_NOT_FOUND;
+ goto func_exit;
}
}
@@ -3066,9 +3286,9 @@ row_search_for_mysql(
cannot use the adaptive hash index in a search in the case the row
may be long and there may be externally stored fields */
- if (unique_search
+ if (UNIV_UNLIKELY(direction == 0)
+ && unique_search
&& index->type & DICT_CLUSTERED
- && direction == 0
&& !prebuilt->templ_contains_blob
&& !prebuilt->used_in_HANDLER
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
@@ -3100,14 +3320,15 @@ row_search_for_mysql(
trx->has_search_latch = TRUE;
}
#endif
- shortcut = row_sel_try_search_shortcut_for_mysql(&rec,
- prebuilt, &mtr);
- if (shortcut == SEL_FOUND) {
+ switch (row_sel_try_search_shortcut_for_mysql(&rec,
+ prebuilt, &offsets, &heap, &mtr)) {
+ case SEL_FOUND:
#ifdef UNIV_SEARCH_DEBUG
- ut_a(0 == cmp_dtuple_rec(search_tuple, rec));
+ ut_a(0 == cmp_dtuple_rec(search_tuple,
+ rec, offsets));
#endif
if (!row_sel_store_mysql_rec(buf, prebuilt,
- rec)) {
+ rec, offsets)) {
err = DB_TOO_BIG_RECORD;
/* We let the main loop to do the
@@ -3131,15 +3352,12 @@ row_search_for_mysql(
trx->has_search_latch = FALSE;
}
- trx->op_info = "";
-
/* NOTE that we do NOT store the cursor
position */
+ err = DB_SUCCESS;
+ goto func_exit;
- return(DB_SUCCESS);
-
- } else if (shortcut == SEL_EXHAUSTED) {
-
+ case SEL_EXHAUSTED:
mtr_commit(&mtr);
/* ut_print_name(stderr, index->name);
@@ -3154,12 +3372,11 @@ row_search_for_mysql(
trx->has_search_latch = FALSE;
}
- trx->op_info = "";
-
/* NOTE that we do NOT store the cursor
position */
- return(DB_RECORD_NOT_FOUND);
+ err = DB_RECORD_NOT_FOUND;
+ goto func_exit;
}
shortcut_fails_too_big_rec:
mtr_commit(&mtr);
@@ -3183,6 +3400,7 @@ shortcut_fails_too_big_rec:
/* Scan the MySQL query string; check if SELECT is the first
word there */
+ ibool success;
dict_accept(*trx->mysql_query_str, "SELECT", &success);
@@ -3198,7 +3416,7 @@ shortcut_fails_too_big_rec:
naturally moves upward (in fetch next) in alphabetical order,
otherwise downward */
- if (direction == 0) {
+ if (UNIV_UNLIKELY(direction == 0)) {
if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G) {
moves_up = TRUE;
}
@@ -3212,10 +3430,10 @@ shortcut_fails_too_big_rec:
clust_index = dict_table_get_first_index(index->table);
- if (direction != 0) {
- moved = sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
- moves_up, &mtr);
- if (!moved) {
+ if (UNIV_LIKELY(direction != 0)) {
+ if (!sel_restore_position_for_mysql(&same_user_rec,
+ BTR_SEARCH_LEAF,
+ pcur, moves_up, &mtr)) {
goto next_rec;
}
@@ -3245,7 +3463,7 @@ shortcut_fails_too_big_rec:
fputs(
"InnoDB: Error: MySQL is trying to perform a consistent read\n"
"InnoDB: but the read view is not assigned!\n", stderr);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 600);
fputc('\n', stderr);
ut_a(0);
}
@@ -3256,11 +3474,13 @@ shortcut_fails_too_big_rec:
trx_assign_read_view(trx);
prebuilt->sql_stat_start = FALSE;
} else {
+ ulint lock_mode;
if (prebuilt->select_lock_type == LOCK_S) {
- err = lock_table(0, index->table, LOCK_IS, thr);
+ lock_mode = LOCK_IS;
} else {
- err = lock_table(0, index->table, LOCK_IX, thr);
+ lock_mode = LOCK_IX;
}
+ err = lock_table(0, index->table, lock_mode, thr);
if (err != DB_SUCCESS) {
@@ -3274,6 +3494,8 @@ rec_loop:
/* PHASE 4: Look for matching records in a loop */
rec = btr_pcur_get_rec(pcur);
+ ut_ad(!!page_rec_is_comp(rec) == comp);
+#ifdef UNIV_SEARCH_DEBUG
/*
fputs("Using ", stderr);
dict_index_name_print(stderr, index);
@@ -3281,7 +3503,9 @@ rec_loop:
buf_frame_get_page_no(buf_frame_align(rec)));
rec_print(rec);
*/
- if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
+#endif /* UNIV_SEARCH_DEBUG */
+
+ if (page_rec_is_infimum(rec)) {
/* The infimum record on a page cannot be in the result set,
and neither can a record lock be placed on it: we skip such
@@ -3290,10 +3514,11 @@ rec_loop:
goto next_rec;
}
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ if (page_rec_is_supremum(rec)) {
- if (prebuilt->select_lock_type != LOCK_NONE
- && set_also_gap_locks) {
+ if (set_also_gap_locks
+ && !srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record */
@@ -3301,16 +3526,16 @@ rec_loop:
we do not lock gaps. Supremum record is really
a gap and therefore we do not set locks there. */
- if (srv_locks_unsafe_for_binlog == FALSE) {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_ORDINARY, thr);
- if (err != DB_SUCCESS) {
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ err = sel_set_rec_lock(rec, index, offsets,
+ prebuilt->select_lock_type,
+ LOCK_ORDINARY, thr);
- goto lock_wait_or_error;
- }
- }
+ if (err != DB_SUCCESS) {
+ goto lock_wait_or_error;
+ }
}
/* A page supremum record cannot be in the result set: skip
it now that we have placed a possible lock on it */
@@ -3322,10 +3547,23 @@ rec_loop:
/* Do sanity checks in case our cursor has bumped into page
corruption */
- next_offs = rec_get_next_offs(rec);
+ if (comp) {
+ next_offs = rec_get_next_offs(rec, TRUE);
+ if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) {
+
+ goto wrong_offs;
+ }
+ } else {
+ next_offs = rec_get_next_offs(rec, FALSE);
+ if (UNIV_UNLIKELY(next_offs < PAGE_OLD_SUPREMUM)) {
+
+ goto wrong_offs;
+ }
+ }
- if (next_offs >= UNIV_PAGE_SIZE || next_offs < PAGE_SUPREMUM) {
+ if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
+wrong_offs:
if (srv_force_recovery == 0 || moves_up == FALSE) {
ut_print_timestamp(stderr);
buf_page_print(buf_frame_align(rec));
@@ -3338,7 +3576,7 @@ rec_loop:
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: ",
- (ulong) (rec - buf_frame_align(rec)),
+ (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
dict_index_name_print(stderr, trx, index);
@@ -3356,7 +3594,7 @@ rec_loop:
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: ",
- (ulong) (rec - buf_frame_align(rec)),
+ (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
dict_index_name_print(stderr, trx, index);
@@ -3368,14 +3606,19 @@ rec_loop:
goto next_rec;
}
}
+ /*-------------------------------------------------------------*/
+
+ /* Calculate the 'offsets' associated with 'rec' */
- if (srv_force_recovery > 0) {
- if (!rec_validate(rec) || !btr_index_rec_validate(rec, index,
- FALSE)) {
+ offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+
+ if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
+ if (!rec_validate(rec, offsets)
+ || !btr_index_rec_validate(rec, index, FALSE)) {
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: ",
- (ulong) (rec - buf_frame_align(rec)),
+ (ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
dict_index_name_print(stderr, trx, index);
@@ -3386,8 +3629,6 @@ rec_loop:
}
}
- /*-------------------------------------------------------------*/
-
/* Note that we cannot trust the up_match value in the cursor at this
place because we can arrive here after moving the cursor! Thus
we have to recompare rec and search_tuple to determine if they
@@ -3399,31 +3640,29 @@ rec_loop:
/* fputs("Comparing rec and search tuple\n", stderr); */
- if (0 != cmp_dtuple_rec(search_tuple, rec)) {
+ if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
- if (prebuilt->select_lock_type != LOCK_NONE
- && set_also_gap_locks) {
+ if (set_also_gap_locks
+ && !srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a gap lock on the index
record only if innodb_locks_unsafe_for_binlog
option is not set */
- if (srv_locks_unsafe_for_binlog == FALSE) {
-
- err = sel_set_rec_lock(rec, index,
+ err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
LOCK_GAP, thr);
- if (err != DB_SUCCESS) {
- goto lock_wait_or_error;
- }
- }
+ if (err != DB_SUCCESS) {
+ goto lock_wait_or_error;
+ }
}
btr_pcur_store_position(pcur, &mtr);
- ret = DB_RECORD_NOT_FOUND;
+ err = DB_RECORD_NOT_FOUND;
/* ut_print_name(stderr, index->name);
fputs(" record not found 3\n", stderr); */
@@ -3432,70 +3671,86 @@ rec_loop:
} else if (match_mode == ROW_SEL_EXACT_PREFIX) {
- if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec)) {
+ if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
- if (prebuilt->select_lock_type != LOCK_NONE
- && set_also_gap_locks) {
+ if (set_also_gap_locks
+ && !srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a gap lock on the index
record only if innodb_locks_unsafe_for_binlog
option is not set */
- if (srv_locks_unsafe_for_binlog == FALSE) {
-
- err = sel_set_rec_lock(rec, index,
+ err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
LOCK_GAP, thr);
- if (err != DB_SUCCESS) {
- goto lock_wait_or_error;
- }
- }
+ if (err != DB_SUCCESS) {
+ goto lock_wait_or_error;
+ }
}
btr_pcur_store_position(pcur, &mtr);
- ret = DB_RECORD_NOT_FOUND;
+ err = DB_RECORD_NOT_FOUND;
/* ut_print_name(stderr, index->name);
fputs(" record not found 4\n", stderr); */
goto normal_return;
}
}
-
+
/* We are ready to look at a possible new index entry in the result
set: the cursor is now placed on a user record */
- cons_read_requires_clust_rec = FALSE;
-
if (prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record; note that delete
marked records are a special case in a unique search. If there
is a non-delete marked record, then it is enough to lock its
existence with LOCK_REC_NOT_GAP. */
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we lock only the record, i.e., next-key locking is
+ not used. */
+
+ ulint lock_type;
+
if (!set_also_gap_locks
- || (unique_search && !rec_get_deleted_flag(rec))) {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_REC_NOT_GAP, thr);
+ || srv_locks_unsafe_for_binlog
+ || (unique_search && !UNIV_UNLIKELY(rec_get_deleted_flag(
+ rec, comp)))) {
+
+ goto no_gap_lock;
} else {
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used. */
+ lock_type = LOCK_ORDINARY;
+ }
- if (srv_locks_unsafe_for_binlog) {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_REC_NOT_GAP, thr);
- } else {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_ORDINARY, thr);
- }
+ /* If we are doing a 'greater or equal than a primary key
+ value' search from a clustered index, and we find a record
+ that has that exact primary key value, then there is no need
+ to lock the gap before the record, because no insert in the
+ gap can be in our search range. That is, no phantom row can
+ appear that way.
+
+ An example: if col1 is the primary key, the search is WHERE
+ col1 >= 100, and we find a record where col1 = 100, then no
+ need to lock the gap before that record. */
+
+ if (index == clust_index
+ && mode == PAGE_CUR_GE
+ && direction == 0
+ && dtuple_get_n_fields_cmp(search_tuple)
+ == dict_index_get_n_unique(index)
+ && 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) {
+no_gap_lock:
+ lock_type = LOCK_REC_NOT_GAP;
}
-
+
+ err = sel_set_rec_lock(rec, index, offsets,
+ prebuilt->select_lock_type,
+ lock_type, thr);
+
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
@@ -3516,13 +3771,16 @@ rec_loop:
high force recovery level set, we try to avoid crashes
by skipping this lookup */
- if (srv_force_recovery < 5
+ if (UNIV_LIKELY(srv_force_recovery < 5)
&& !lock_clust_rec_cons_read_sees(rec, index,
- trx->read_view)) {
+ offsets, trx->read_view)) {
+ /* The following call returns 'offsets'
+ associated with 'old_vers' */
err = row_sel_build_prev_vers_for_mysql(
trx->read_view, clust_index,
prebuilt, rec,
+ &offsets, &heap,
&old_vers, &mtr);
if (err != DB_SUCCESS) {
@@ -3546,35 +3804,60 @@ rec_loop:
have to look also into the clustered index: this
is necessary, because we can only get the undo
information via the clustered index record. */
-
- cons_read_requires_clust_rec = TRUE;
+
+ ut_ad(index != clust_index);
+
+ goto requires_clust_rec;
}
}
- if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) {
+ /* NOTE that at this point rec can be an old version of a clustered
+ index record built for a consistent read. We cannot assume after this
+ point that rec is on a buffer pool page. Functions like
+ page_rec_is_comp() cannot be used! */
- /* The record is delete-marked: we can skip it if this is
- not a consistent read which might see an earlier version
- of a non-clustered index record */
+ if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp))) {
+
+ /* The record is delete-marked: we can skip it */
+
+ if (srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
+
+ /* No need to keep a lock on a delete-marked record
+ if we do not want to use next-key locking. */
+
+ row_unlock_for_mysql(prebuilt, TRUE);
+
+ trx_reset_new_rec_lock_info(trx);
+ }
goto next_rec;
}
- /* Get the clustered index record if needed and if we did
- not do the search using the clustered index */
+ /* Get the clustered index record if needed, if we did not do the
+ search using the clustered index. */
+
+ if (index != clust_index && prebuilt->need_to_access_clustered) {
- index_rec = rec;
+requires_clust_rec:
+ /* We use a 'goto' to the preceding label if a consistent
+ read of a secondary index record requires us to look up old
+ versions of the associated clustered index record. */
- if (index != clust_index && (cons_read_requires_clust_rec
- || prebuilt->need_to_access_clustered)) {
+ ut_ad(rec_offs_validate(rec, index, offsets));
/* It was a non-clustered index and we must fetch also the
clustered index record */
mtr_has_extra_clust_latch = TRUE;
+
+ /* The following call returns 'offsets' associated with
+ 'clust_rec'. Note that 'clust_rec' can be an old version
+ built for a consistent read. */
err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
- thr, &clust_rec, &mtr);
+ thr, &clust_rec,
+ &offsets, &heap, &mtr);
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
@@ -3587,21 +3870,51 @@ rec_loop:
goto next_rec;
}
- if (rec_get_deleted_flag(clust_rec)) {
+ if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
/* The record is delete marked: we can skip it */
+ if (srv_locks_unsafe_for_binlog
+ && prebuilt->select_lock_type != LOCK_NONE) {
+
+ /* No need to keep a lock on a delete-marked
+ record if we do not want to use next-key
+ locking. */
+
+ row_unlock_for_mysql(prebuilt, TRUE);
+
+ trx_reset_new_rec_lock_info(trx);
+ }
+
goto next_rec;
}
if (prebuilt->need_to_access_clustered) {
- rec = clust_rec;
+
+ result_rec = clust_rec;
+
+ ut_ad(rec_offs_validate(result_rec, clust_index,
+ offsets));
+ } else {
+ /* We used 'offsets' for the clust rec, recalculate
+ them for 'rec' */
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ result_rec = rec;
}
+ } else {
+ result_rec = rec;
}
- /* We found a qualifying row */
-
- if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD
+ /* We found a qualifying record 'result_rec'. At this point,
+ 'offsets' are associated with 'result_rec'. */
+
+ ut_ad(rec_offs_validate(result_rec,
+ result_rec != rec ? clust_index : index,
+ offsets));
+
+ if ((match_mode == ROW_SEL_EXACT
+ || prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD)
&& prebuilt->select_lock_type == LOCK_NONE
&& !prebuilt->templ_contains_blob
&& !prebuilt->clust_index_was_generated
@@ -3618,8 +3931,8 @@ rec_loop:
not cache rows because there the cursor is a scrollable
cursor. */
- row_sel_push_cache_row_for_mysql(prebuilt, rec);
-
+ row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
+ offsets);
if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
goto got_row;
@@ -3628,11 +3941,14 @@ rec_loop:
goto next_rec;
} else {
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
- ut_memcpy(buf + 4, rec - rec_get_extra_size(rec),
- rec_get_size(rec));
- mach_write_to_4(buf, rec_get_extra_size(rec) + 4);
+ memcpy(buf + 4, result_rec
+ - rec_offs_extra_size(offsets),
+ rec_offs_size(offsets));
+ mach_write_to_4(buf,
+ rec_offs_extra_size(offsets) + 4);
} else {
- if (!row_sel_store_mysql_rec(buf, prebuilt, rec)) {
+ if (!row_sel_store_mysql_rec(buf, prebuilt,
+ result_rec, offsets)) {
err = DB_TOO_BIG_RECORD;
goto lock_wait_or_error;
@@ -3640,10 +3956,18 @@ rec_loop:
}
if (prebuilt->clust_index_was_generated) {
- row_sel_store_row_id_to_prebuilt(prebuilt, index_rec,
- index);
+ if (result_rec != rec) {
+ offsets = rec_get_offsets(
+ rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ }
+ row_sel_store_row_id_to_prebuilt(prebuilt, rec,
+ index, offsets);
}
}
+
+ /* From this point on, 'offsets' are invalid. */
+
got_row:
/* We have an optimization to save CPU time: if this is a consistent
read on a unique condition on the clustered index, then we do not
@@ -3661,15 +3985,15 @@ got_row:
btr_pcur_store_position(pcur, &mtr);
}
- ret = DB_SUCCESS;
+ err = DB_SUCCESS;
goto normal_return;
next_rec:
/*-------------------------------------------------------------*/
/* PHASE 5: Move the cursor to the next index record */
-
- if (mtr_has_extra_clust_latch) {
+
+ if (UNIV_UNLIKELY(mtr_has_extra_clust_latch)) {
/* We must commit mtr if we are moving to the next
non-clustered index record, because we could break the
latching order if we would access a different clustered
@@ -3681,34 +4005,39 @@ next_rec:
mtr_has_extra_clust_latch = FALSE;
mtr_start(&mtr);
- moved = sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
- moves_up, &mtr);
- if (moved) {
+ if (sel_restore_position_for_mysql(&same_user_rec,
+ BTR_SEARCH_LEAF,
+ pcur, moves_up, &mtr)) {
+#ifdef UNIV_SEARCH_DEBUG
cnt++;
+#endif /* UNIV_SEARCH_DEBUG */
goto rec_loop;
}
}
if (moves_up) {
- moved = btr_pcur_move_to_next(pcur, &mtr);
- } else {
- moved = btr_pcur_move_to_prev(pcur, &mtr);
- }
+ if (UNIV_UNLIKELY(!btr_pcur_move_to_next(pcur, &mtr))) {
+not_moved:
+ btr_pcur_store_position(pcur, &mtr);
- if (!moved) {
- btr_pcur_store_position(pcur, &mtr);
+ if (match_mode != 0) {
+ err = DB_RECORD_NOT_FOUND;
+ } else {
+ err = DB_END_OF_INDEX;
+ }
- if (match_mode != 0) {
- ret = DB_RECORD_NOT_FOUND;
- } else {
- ret = DB_END_OF_INDEX;
+ goto normal_return;
+ }
+ } else {
+ if (UNIV_UNLIKELY(!btr_pcur_move_to_prev(pcur, &mtr))) {
+ goto not_moved;
}
-
- goto normal_return;
}
+#ifdef UNIV_SEARCH_DEBUG
cnt++;
+#endif /* UNIV_SEARCH_DEBUG */
goto rec_loop;
@@ -3726,24 +4055,50 @@ lock_wait_or_error:
que_thr_stop_for_mysql(thr);
- was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
-
- if (was_lock_wait) {
+ thr->lock_state = QUE_THR_LOCK_ROW;
+
+ if (row_mysql_handle_errors(&err, trx, thr, NULL)) {
+ /* It was a lock wait, and it ended */
+
+ thr->lock_state = QUE_THR_LOCK_NOLOCK;
mtr_start(&mtr);
- sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
- moves_up, &mtr);
+ sel_restore_position_for_mysql(&same_user_rec,
+ BTR_SEARCH_LEAF, pcur,
+ moves_up, &mtr);
+ if (srv_locks_unsafe_for_binlog && !same_user_rec) {
+ /* Since we were not able to restore the cursor
+ on the same user record, we cannot use
+ row_unlock_for_mysql() to unlock any records, and
+ we must thus reset the new rec lock info. Since
+ in lock0lock.c we have blocked the inheriting of gap
+ X-locks, we actually do not have any new record locks
+ set in this case.
+
+ Note that if we were able to restore on the 'same'
+ user record, it is still possible that we were actually
+ waiting on a delete-marked record, and meanwhile
+ it was removed by purge and inserted again by some
+ other user. But that is no problem, because in
+ rec_loop we will again try to set a lock, and
+ new_rec_lock_info in trx will be right at the end. */
+
+ trx_reset_new_rec_lock_info(trx);
+ }
+
mode = pcur->search_mode;
goto rec_loop;
}
+ thr->lock_state = QUE_THR_LOCK_NOLOCK;
+
+#ifdef UNIV_SEARCH_DEBUG
/* fputs("Using ", stderr);
dict_index_name_print(stderr, index);
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
- trx->op_info = "";
-
- return(err);
+#endif /* UNIV_SEARCH_DEBUG */
+ goto func_exit;
normal_return:
/*-------------------------------------------------------------*/
@@ -3754,19 +4109,24 @@ normal_return:
if (prebuilt->n_fetch_cached > 0) {
row_sel_pop_cached_row_for_mysql(buf, prebuilt);
- ret = DB_SUCCESS;
+ err = DB_SUCCESS;
}
+#ifdef UNIV_SEARCH_DEBUG
/* fputs("Using ", stderr);
dict_index_name_print(stderr, index);
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
- if (ret == DB_SUCCESS) {
+#endif /* UNIV_SEARCH_DEBUG */
+ if (err == DB_SUCCESS) {
srv_n_rows_read++;
}
+func_exit:
trx->op_info = "";
-
- return(ret);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(err);
}
/***********************************************************************
@@ -3815,7 +4175,8 @@ row_search_check_if_query_cache_permitted(
&& !trx->read_view) {
trx->read_view = read_view_open_now(trx,
- trx->read_view_heap);
+ trx->global_read_view_heap);
+ trx->global_read_view = trx->read_view;
}
}
diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c
index e16d696314b..f906027033f 100644
--- a/innobase/row/row0umod.c
+++ b/innobase/row/row0umod.c
@@ -52,19 +52,16 @@ row_undo_mod_undo_also_prev_vers(
/* out: TRUE if also previous modify or
insert of this row should be undone */
undo_node_t* node, /* in: row undo node */
- que_thr_t* thr, /* in: query thread */
dulint* undo_no)/* out: the undo number */
{
trx_undo_rec_t* undo_rec;
- ibool ret;
trx_t* trx;
- UT_NOT_USED(thr);
-
trx = node->trx;
if (0 != ut_dulint_cmp(node->new_trx_id, trx->id)) {
+ *undo_no = ut_dulint_zero;
return(FALSE);
}
@@ -72,13 +69,7 @@ row_undo_mod_undo_also_prev_vers(
*undo_no = trx_undo_rec_get_undo_no(undo_rec);
- if (ut_dulint_cmp(trx->roll_limit, *undo_no) <= 0) {
- ret = TRUE;
- } else {
- ret = FALSE;
- }
-
- return(ret);
+ return(ut_dulint_cmp(trx->roll_limit, *undo_no) <= 0);
}
/***************************************************************
@@ -214,7 +205,7 @@ row_undo_mod_clust(
/* Check if also the previous version of the clustered index record
should be undone in this same rollback operation */
- more_vers = row_undo_mod_undo_also_prev_vers(node, thr, &new_undo_no);
+ more_vers = row_undo_mod_undo_also_prev_vers(node, &new_undo_no);
pcur = &(node->pcur);
@@ -438,9 +429,9 @@ row_undo_mod_del_unmark_sec_and_undo_update(
dtuple_print(stderr, entry);
fputs("\n"
"InnoDB: record ", stderr);
- rec_print(stderr, btr_pcur_get_rec(&pcur));
+ rec_print(stderr, btr_pcur_get_rec(&pcur), index);
putc('\n', stderr);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 0);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
} else {
diff --git a/innobase/row/row0undo.c b/innobase/row/row0undo.c
index bc3cc8ea9f3..435c0279dbb 100644
--- a/innobase/row/row0undo.c
+++ b/innobase/row/row0undo.c
@@ -151,6 +151,10 @@ row_undo_search_clust_to_pcur(
mtr_t mtr;
ibool ret;
rec_t* rec;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
mtr_start(&mtr);
@@ -161,8 +165,11 @@ row_undo_search_clust_to_pcur(
rec = btr_pcur_get_rec(&(node->pcur));
+ offsets = rec_get_offsets(rec, clust_index, offsets,
+ ULINT_UNDEFINED, &heap);
+
if (!found || 0 != ut_dulint_cmp(node->roll_ptr,
- row_get_rec_roll_ptr(rec, clust_index))) {
+ row_get_rec_roll_ptr(rec, clust_index, offsets))) {
/* We must remove the reservation on the undo log record
BEFORE releasing the latch on the clustered index page: this
@@ -175,7 +182,7 @@ row_undo_search_clust_to_pcur(
ret = FALSE;
} else {
node->row = row_build(ROW_COPY_DATA, clust_index, rec,
- node->heap);
+ offsets, node->heap);
btr_pcur_store_position(&(node->pcur), &mtr);
ret = TRUE;
@@ -183,6 +190,9 @@ row_undo_search_clust_to_pcur(
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(ret);
}
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 9192f6dc692..4f44dbeae67 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -301,19 +301,20 @@ recovery. */
void
row_upd_rec_sys_fields_in_recovery(
/*===============================*/
- rec_t* rec, /* in: record */
- ulint pos, /* in: TRX_ID position in rec */
- dulint trx_id, /* in: transaction id */
- dulint roll_ptr)/* in: roll ptr of the undo log record */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint pos, /* in: TRX_ID position in rec */
+ dulint trx_id, /* in: transaction id */
+ dulint roll_ptr)/* in: roll ptr of the undo log record */
{
byte* field;
ulint len;
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
ut_ad(len == DATA_TRX_ID_LEN);
trx_write_trx_id(field, trx_id);
- field = rec_get_nth_field(rec, pos + 1, &len);
+ field = rec_get_nth_field(rec, offsets, pos + 1, &len);
ut_ad(len == DATA_ROLL_PTR_LEN);
trx_write_roll_ptr(field, roll_ptr);
}
@@ -361,8 +362,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
- rec_t* rec, /* in: record in index */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update) /* in: update vector */
{
upd_field_t* upd_field;
@@ -372,6 +373,7 @@ row_upd_changes_field_size_or_external(
ulint n_fields;
ulint i;
+ ut_ad(rec_offs_validate(NULL, index, offsets));
n_fields = upd_get_n_fields(update);
for (i = 0; i < n_fields; i++) {
@@ -380,7 +382,7 @@ row_upd_changes_field_size_or_external(
new_val = &(upd_field->new_val);
new_len = new_val->len;
- if (new_len == UNIV_SQL_NULL) {
+ if (new_len == UNIV_SQL_NULL && !rec_offs_comp(offsets)) {
/* A bug fixed on Dec 31st, 2004: we looked at the
SQL NULL size from the wrong field! We may backport
this fix also to 4.0. The merge to 5.0 will be made
@@ -391,14 +393,14 @@ row_upd_changes_field_size_or_external(
upd_field->field_no));
}
- old_len = rec_get_nth_field_size(rec, upd_field->field_no);
-
+ old_len = rec_offs_nth_size(offsets, upd_field->field_no);
+
if (old_len != new_len) {
return(TRUE);
}
- if (rec_get_nth_field_extern_bit(rec, upd_field->field_no)) {
+ if (rec_offs_nth_extern(offsets, upd_field->field_no)) {
return(TRUE);
}
@@ -420,15 +422,18 @@ a clustered index */
void
row_upd_rec_in_place(
/*=================*/
- rec_t* rec, /* in/out: record where replaced */
- upd_t* update) /* in: update vector */
+ rec_t* rec, /* in/out: record where replaced */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update) /* in: update vector */
{
upd_field_t* upd_field;
dfield_t* new_val;
ulint n_fields;
ulint i;
- rec_set_info_bits(rec, update->info_bits);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
+ rec_set_info_bits(rec, rec_offs_comp(offsets), update->info_bits);
n_fields = upd_get_n_fields(update);
@@ -436,7 +441,7 @@ row_upd_rec_in_place(
upd_field = upd_get_nth_field(update, i);
new_val = &(upd_field->new_val);
- rec_set_nth_field(rec, upd_field->field_no,
+ rec_set_nth_field(rec, offsets, upd_field->field_no,
dfield_get_data(new_val),
dfield_get_len(new_val));
}
@@ -701,6 +706,9 @@ row_upd_build_sec_rec_difference_binary(
upd_t* update;
ulint n_diff;
ulint i;
+ ulint offsets_[REC_OFFS_SMALL_SIZE];
+ const ulint* offsets;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
/* This function is used only for a secondary index */
ut_a(0 == (index->type & DICT_CLUSTERED));
@@ -708,10 +716,12 @@ row_upd_build_sec_rec_difference_binary(
update = upd_create(dtuple_get_n_fields(entry), heap);
n_diff = 0;
+ offsets = rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap);
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
dfield = dtuple_get_nth_field(entry, i);
@@ -774,6 +784,9 @@ row_upd_build_difference_binary(
ulint trx_id_pos;
ibool extern_bit;
ulint i;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ const ulint* offsets;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
/* This function is used only for a clustered index */
ut_a(index->type & DICT_CLUSTERED);
@@ -785,9 +798,12 @@ row_upd_build_difference_binary(
roll_ptr_pos = dict_index_get_sys_col_pos(index, DATA_ROLL_PTR);
trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
+ offsets = rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap);
+
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
dfield = dtuple_get_nth_field(entry, i);
@@ -799,9 +815,10 @@ row_upd_build_difference_binary(
goto skip_compare;
}
- extern_bit = rec_get_nth_field_extern_bit(rec, i);
+ extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i);
- if (extern_bit != upd_ext_vec_contains(ext_vec, n_ext_vec, i)
+ if (UNIV_UNLIKELY(extern_bit ==
+ (ibool)!rec_offs_nth_extern(offsets, i))
|| !dfield_data_is_binary_equal(dfield, len, data)) {
upd_field = upd_get_nth_field(update, n_diff);
@@ -810,12 +827,8 @@ row_upd_build_difference_binary(
upd_field_set_field_no(upd_field, i, index, trx);
- if (upd_ext_vec_contains(ext_vec, n_ext_vec, i)) {
- upd_field->extern_storage = TRUE;
- } else {
- upd_field->extern_storage = FALSE;
- }
-
+ upd_field->extern_storage = extern_bit;
+
n_diff++;
}
skip_compare:
@@ -1123,6 +1136,7 @@ void
row_upd_copy_columns(
/*=================*/
rec_t* rec, /* in: record in a clustered index */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
sym_node_t* column) /* in: first column in a column list, or
NULL */
{
@@ -1130,7 +1144,7 @@ row_upd_copy_columns(
ulint len;
while (column) {
- data = rec_get_nth_field(rec,
+ data = rec_get_nth_field(rec, offsets,
column->field_nos[SYM_CLUST_FIELD_NO],
&len);
eval_node_copy_and_alloc_val(column, data, len);
@@ -1177,7 +1191,11 @@ row_upd_store_row(
dict_index_t* clust_index;
upd_t* update;
rec_t* rec;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ const ulint* offsets;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_ad(node->pcur->latch_mode != BTR_NO_LATCHES);
if (node->row != NULL) {
@@ -1189,10 +1207,12 @@ row_upd_store_row(
rec = btr_pcur_get_rec(node->pcur);
- node->row = row_build(ROW_COPY_DATA, clust_index, rec, node->heap);
-
+ offsets = rec_get_offsets(rec, clust_index, offsets_,
+ ULINT_UNDEFINED, &heap);
+ node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
+ node->heap);
node->ext_vec = mem_heap_alloc(node->heap, sizeof(ulint)
- * rec_get_n_fields(rec));
+ * rec_offs_n_fields(offsets));
if (node->is_delete) {
update = NULL;
} else {
@@ -1200,7 +1220,10 @@ row_upd_store_row(
}
node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec,
- rec, update);
+ offsets, update);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
}
/***************************************************************
@@ -1244,7 +1267,7 @@ row_upd_sec_index_entry(
rec = btr_cur_get_rec(btr_cur);
- if (!found) {
+ if (UNIV_UNLIKELY(!found)) {
fputs("InnoDB: error in sec index entry update in\n"
"InnoDB: ", stderr);
dict_index_name_print(stderr, trx, index);
@@ -1253,10 +1276,10 @@ row_upd_sec_index_entry(
dtuple_print(stderr, entry);
fputs("\n"
"InnoDB: record ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, index);
putc('\n', stderr);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 0);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
@@ -1265,7 +1288,7 @@ row_upd_sec_index_entry(
delete marked if we return after a lock wait in
row_ins_index_entry below */
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, index->table->comp)) {
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
thr, &mtr);
if (err == DB_SUCCESS && check_ref) {
@@ -1353,7 +1376,7 @@ row_upd_clust_rec_by_insert(
a foreign key constraint */
mtr_t* mtr) /* in: mtr; gets committed here */
{
- mem_heap_t* heap;
+ mem_heap_t* heap = NULL;
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
trx_t* trx;
@@ -1370,12 +1393,13 @@ row_upd_clust_rec_by_insert(
btr_cur = btr_pcur_get_btr_cur(pcur);
if (node->state != UPD_NODE_INSERT_CLUSTERED) {
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
btr_cur, TRUE, thr, mtr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
-
return(err);
}
@@ -1385,7 +1409,9 @@ row_upd_clust_rec_by_insert(
record is removed from the index tree, or updated. */
btr_cur_mark_extern_inherited_fields(btr_cur_get_rec(btr_cur),
- node->update, mtr);
+ rec_get_offsets(btr_cur_get_rec(btr_cur),
+ dict_table_get_first_index(table), offsets_,
+ ULINT_UNDEFINED, &heap), node->update, mtr);
if (check_ref) {
/* NOTE that the following call loses
the position of pcur ! */
@@ -1394,7 +1420,9 @@ row_upd_clust_rec_by_insert(
index, thr, mtr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
-
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(err);
}
}
@@ -1403,10 +1431,11 @@ row_upd_clust_rec_by_insert(
mtr_commit(mtr);
+ if (!heap) {
+ heap = mem_heap_create(500);
+ }
node->state = UPD_NODE_INSERT_CLUSTERED;
- heap = mem_heap_create(500);
-
entry = row_build_index_entry(node->row, index, heap);
row_upd_index_replace_new_col_vals(entry, index, node->update, NULL);
@@ -1458,7 +1487,8 @@ row_upd_clust_rec(
pcur = node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
- ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
+ ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
+ index->table->comp));
/* Try optimistic updating of the record, keeping changes within
the page; we do not check locks because we assume the x-lock on the
@@ -1494,7 +1524,8 @@ row_upd_clust_rec(
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
- ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
+ ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
+ index->table->comp));
err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
&big_rec, node->update,
@@ -1502,12 +1533,22 @@ row_upd_clust_rec(
mtr_commit(mtr);
if (err == DB_SUCCESS && big_rec) {
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ rec_t* rec;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
mtr_start(mtr);
+
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
-
- err = btr_store_big_rec_extern_fields(index,
- btr_cur_get_rec(btr_cur),
- big_rec, mtr);
+ rec = btr_cur_get_rec(btr_cur);
+ err = btr_store_big_rec_extern_fields(index, rec,
+ rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap),
+ big_rec, mtr);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
mtr_commit(mtr);
}
@@ -1591,7 +1632,12 @@ row_upd_clust_step(
ulint err;
mtr_t* mtr;
mtr_t mtr_buf;
-
+ rec_t* rec;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ const ulint* offsets;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
index = dict_table_get_first_index(node->table);
check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr));
@@ -1647,14 +1693,16 @@ row_upd_clust_step(
}
}
+ rec = btr_pcur_get_rec(pcur);
+ offsets = rec_get_offsets(rec, index, offsets_,
+ ULINT_UNDEFINED, &heap);
+
if (!node->has_clust_rec_x_lock) {
err = lock_clust_rec_modify_check_and_lock(0,
- btr_pcur_get_rec(pcur),
- index, thr);
+ rec, index, offsets, thr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
-
- return(err);
+ goto exit_func;
}
}
@@ -1663,14 +1711,14 @@ row_upd_clust_step(
if (node->is_delete) {
err = row_upd_del_mark_clust_rec(node, index, thr, check_ref,
mtr);
- if (err != DB_SUCCESS) {
-
- return(err);
+ if (err == DB_SUCCESS) {
+ node->state = UPD_NODE_UPDATE_ALL_SEC;
+ node->index = dict_table_get_next_index(index);
+ }
+ exit_func:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
-
- node->state = UPD_NODE_UPDATE_ALL_SEC;
- node->index = dict_table_get_next_index(index);
-
return(err);
}
@@ -1680,16 +1728,18 @@ row_upd_clust_step(
if (!node->in_mysql_interface) {
/* Copy the necessary columns from clust_rec and calculate the
new values to set */
-
- row_upd_copy_columns(btr_pcur_get_rec(pcur),
+ row_upd_copy_columns(rec, offsets,
UT_LIST_GET_FIRST(node->columns));
row_upd_eval_new_vals(node->update);
}
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) {
err = row_upd_clust_rec(node, index, thr, mtr);
-
return(err);
}
@@ -1941,6 +1991,9 @@ row_upd_in_place_in_select(
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
ulint err;
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
ut_ad(sel_node->select_will_do_update);
ut_ad(sel_node->latch_mode == BTR_MODIFY_LEAF);
@@ -1956,11 +2009,17 @@ row_upd_in_place_in_select(
/* Copy the necessary columns from clust_rec and calculate the new
values to set */
- row_upd_copy_columns(btr_pcur_get_rec(pcur),
- UT_LIST_GET_FIRST(node->columns));
+ row_upd_copy_columns(btr_pcur_get_rec(pcur), rec_get_offsets(
+ btr_pcur_get_rec(pcur), btr_cur->index, offsets_,
+ ULINT_UNDEFINED, &heap),
+ UT_LIST_GET_FIRST(node->columns));
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
row_upd_eval_new_vals(node->update);
- ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
+ ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
+ btr_cur->index->table->comp));
ut_ad(node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE);
ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE);
diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c
index bc17ede89e3..8e747423047 100644
--- a/innobase/row/row0vers.c
+++ b/innobase/row/row0vers.c
@@ -41,10 +41,12 @@ row_vers_impl_x_locked_off_kernel(
transaction; NOTE that the kernel mutex is
temporarily released! */
rec_t* rec, /* in: record in a secondary index */
- dict_index_t* index) /* in: the secondary index */
+ dict_index_t* index, /* in: the secondary index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
dict_index_t* clust_index;
rec_t* clust_rec;
+ ulint* clust_offsets;
rec_t* version;
rec_t* prev_version;
dulint trx_id;
@@ -55,10 +57,11 @@ row_vers_impl_x_locked_off_kernel(
dtuple_t* entry = NULL; /* assignment to eliminate compiler
warning */
trx_t* trx;
- ibool vers_del;
- ibool rec_del;
+ ulint vers_del;
+ ulint rec_del;
ulint err;
mtr_t mtr;
+ ulint comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -96,29 +99,33 @@ row_vers_impl_x_locked_off_kernel(
return(NULL);
}
- trx_id = row_get_rec_trx_id(clust_rec, clust_index);
+ heap = mem_heap_create(1024);
+ clust_offsets = rec_get_offsets(clust_rec, clust_index, NULL,
+ ULINT_UNDEFINED, &heap);
+ trx_id = row_get_rec_trx_id(clust_rec, clust_index, clust_offsets);
mtr_s_lock(&(purge_sys->latch), &mtr);
mutex_enter(&kernel_mutex);
+ trx = NULL;
if (!trx_is_active(trx_id)) {
/* The transaction that modified or inserted clust_rec is no
longer active: no implicit lock on rec */
-
- mtr_commit(&mtr);
-
- return(NULL);
+ goto exit_func;
}
- if (!lock_check_trx_id_sanity(trx_id, clust_rec, clust_index, TRUE)) {
+ if (!lock_check_trx_id_sanity(trx_id, clust_rec, clust_index,
+ clust_offsets, TRUE)) {
/* Corruption noticed: try to avoid a crash by returning */
-
- mtr_commit(&mtr);
-
- return(NULL);
+ goto exit_func;
}
+ comp = page_rec_is_comp(rec);
+ ut_ad(index->table == clust_index->table);
+ ut_ad(!!comp == index->table->comp);
+ ut_ad(!comp == !page_rec_is_comp(clust_rec));
+
/* We look up if some earlier version, which was modified by the trx_id
transaction, of the clustered index record would require rec to be in
a different state (delete marked or unmarked, or have different field
@@ -128,11 +135,10 @@ row_vers_impl_x_locked_off_kernel(
different state, then the trx_id transaction has not yet had time to
modify rec, and does not necessarily have an implicit x-lock on rec. */
- rec_del = rec_get_deleted_flag(rec);
+ rec_del = rec_get_deleted_flag(rec, comp);
trx = NULL;
version = clust_rec;
- heap = NULL;
for (;;) {
mutex_exit(&kernel_mutex);
@@ -146,18 +152,17 @@ row_vers_impl_x_locked_off_kernel(
heap2 = heap;
heap = mem_heap_create(1024);
-
err = trx_undo_prev_version_build(clust_rec, &mtr, version,
- clust_index, heap,
- &prev_version);
- if (heap2) {
- mem_heap_free(heap2); /* version was stored in heap2,
- if heap2 != NULL */
- }
+ clust_index, clust_offsets, heap,
+ &prev_version);
+ mem_heap_free(heap2); /* free version and clust_offsets */
if (prev_version) {
+ clust_offsets = rec_get_offsets(prev_version,
+ clust_index, NULL,
+ ULINT_UNDEFINED, &heap);
row = row_build(ROW_COPY_POINTERS, clust_index,
- prev_version, heap);
+ prev_version, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
}
@@ -189,11 +194,11 @@ row_vers_impl_x_locked_off_kernel(
if prev_version would require rec to be in a different
state. */
- vers_del = rec_get_deleted_flag(prev_version);
+ vers_del = rec_get_deleted_flag(prev_version, comp);
/* We check if entry and rec are identified in the alphabetical
ordering */
- if (0 == cmp_dtuple_rec(entry, rec)) {
+ if (0 == cmp_dtuple_rec(entry, rec, offsets)) {
/* The delete marks of rec and prev_version should be
equal for rec to be in the state required by
prev_version */
@@ -211,7 +216,7 @@ row_vers_impl_x_locked_off_kernel(
dtuple_set_types_binary(entry,
dtuple_get_n_fields(entry));
- if (0 != cmp_dtuple_rec(entry, rec)) {
+ if (0 != cmp_dtuple_rec(entry, rec, offsets)) {
trx = trx_get_on_id(trx_id);
@@ -226,7 +231,8 @@ row_vers_impl_x_locked_off_kernel(
break;
}
- prev_trx_id = row_get_rec_trx_id(prev_version, clust_index);
+ prev_trx_id = row_get_rec_trx_id(prev_version, clust_index,
+ clust_offsets);
if (0 != ut_dulint_cmp(trx_id, prev_trx_id)) {
/* The versions modified by the trx_id transaction end
@@ -238,6 +244,7 @@ row_vers_impl_x_locked_off_kernel(
version = prev_version;
}/* for (;;) */
+exit_func:
mtr_commit(&mtr);
mem_heap_free(heap);
@@ -297,12 +304,14 @@ row_vers_old_has_index_entry(
rec_t* version;
rec_t* prev_version;
dict_index_t* clust_index;
+ ulint* clust_offsets;
mem_heap_t* heap;
mem_heap_t* heap2;
dtuple_t* row;
dtuple_t* entry;
ulint err;
-
+ ulint comp;
+
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_S_FIX));
@@ -313,10 +322,15 @@ row_vers_old_has_index_entry(
clust_index = dict_table_get_first_index(index->table);
- if (also_curr && !rec_get_deleted_flag(rec)) {
+ comp = page_rec_is_comp(rec);
+ ut_ad(!index->table->comp == !comp);
+ heap = mem_heap_create(1024);
+ clust_offsets = rec_get_offsets(rec, clust_index, NULL,
+ ULINT_UNDEFINED, &heap);
- heap = mem_heap_create(1024);
- row = row_build(ROW_COPY_POINTERS, clust_index, rec, heap);
+ if (also_curr && !rec_get_deleted_flag(rec, comp)) {
+ row = row_build(ROW_COPY_POINTERS, clust_index,
+ rec, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
/* NOTE that we cannot do the comparison as binary
@@ -331,24 +345,17 @@ row_vers_old_has_index_entry(
return(TRUE);
}
-
- mem_heap_free(heap);
}
version = rec;
- heap = NULL;
for (;;) {
heap2 = heap;
heap = mem_heap_create(1024);
-
err = trx_undo_prev_version_build(rec, mtr, version,
- clust_index, heap,
- &prev_version);
- if (heap2) {
- mem_heap_free(heap2); /* version was stored in heap2,
- if heap2 != NULL */
- }
+ clust_index, clust_offsets, heap,
+ &prev_version);
+ mem_heap_free(heap2); /* free version and clust_offsets */
if (err != DB_SUCCESS || !prev_version) {
/* Versions end here */
@@ -358,9 +365,12 @@ row_vers_old_has_index_entry(
return(FALSE);
}
- if (!rec_get_deleted_flag(prev_version)) {
+ clust_offsets = rec_get_offsets(prev_version, clust_index,
+ NULL, ULINT_UNDEFINED, &heap);
+
+ if (!rec_get_deleted_flag(prev_version, comp)) {
row = row_build(ROW_COPY_POINTERS, clust_index,
- prev_version, heap);
+ prev_version, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
/* NOTE that we cannot do the comparison as binary
@@ -396,7 +406,11 @@ row_vers_build_for_consistent_read(
of this records */
mtr_t* mtr, /* in: mtr holding the latch on rec */
dict_index_t* index, /* in: the clustered index */
+ ulint** offsets,/* in/out: offsets returned by
+ rec_get_offsets(rec, index) */
read_view_t* view, /* in: the consistent read view */
+ mem_heap_t** offset_heap,/* in/out: memory heap from which
+ the offsets are allocated */
mem_heap_t* in_heap,/* in: memory heap from which the memory for
old_vers is allocated; memory for possible
intermediate versions is allocated and freed
@@ -408,8 +422,7 @@ row_vers_build_for_consistent_read(
rec_t* version;
rec_t* prev_version;
dulint prev_trx_id;
- mem_heap_t* heap;
- mem_heap_t* heap2;
+ mem_heap_t* heap = NULL;
byte* buf;
ulint err;
@@ -420,21 +433,23 @@ row_vers_build_for_consistent_read(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
- ut_ad(!read_view_sees_trx_id(view, row_get_rec_trx_id(rec, index)));
+
+ ut_ad(rec_offs_validate(rec, index, *offsets));
+
+ ut_ad(!read_view_sees_trx_id(view,
+ row_get_rec_trx_id(rec, index, *offsets)));
rw_lock_s_lock(&(purge_sys->latch));
version = rec;
- heap = NULL;
for (;;) {
- heap2 = heap;
+ mem_heap_t* heap2 = heap;
heap = mem_heap_create(1024);
err = trx_undo_prev_version_build(rec, mtr, version, index,
- heap, &prev_version);
+ *offsets, heap, &prev_version);
if (heap2) {
- mem_heap_free(heap2); /* version was stored in heap2,
- if heap2 != NULL */
+ mem_heap_free(heap2); /* free version */
}
if (err != DB_SUCCESS) {
@@ -449,16 +464,19 @@ row_vers_build_for_consistent_read(
break;
}
- prev_trx_id = row_get_rec_trx_id(prev_version, index);
+ *offsets = rec_get_offsets(prev_version, index, *offsets,
+ ULINT_UNDEFINED, offset_heap);
+ prev_trx_id = row_get_rec_trx_id(prev_version, index,
+ *offsets);
if (read_view_sees_trx_id(view, prev_trx_id)) {
/* The view already sees this version: we can copy
it to in_heap and return */
- buf = mem_heap_alloc(in_heap, rec_get_size(
- prev_version));
- *old_vers = rec_copy(buf, prev_version);
+ buf = mem_heap_alloc(in_heap, rec_offs_size(*offsets));
+ *old_vers = rec_copy(buf, prev_version, *offsets);
+ rec_offs_make_valid(*old_vers, index, *offsets);
err = DB_SUCCESS;
break;
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index e56389a8541..c585536baee 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -44,6 +44,7 @@ Created 10/8/1995 Heikki Tuuri
#include "buf0flu.h"
#include "btr0sea.h"
#include "dict0load.h"
+#include "dict0boot.h"
#include "srv0start.h"
#include "row0mysql.h"
@@ -186,6 +187,61 @@ that during a time of heavy update/insert activity. */
ulong srv_max_buf_pool_modified_pct = 90;
+/* variable counts amount of data read in total (in bytes) */
+ulint srv_data_read = 0;
+
+/* here we count the amount of data written in total (in bytes) */
+ulint srv_data_written = 0;
+
+/* the number of the log write requests done */
+ulint srv_log_write_requests = 0;
+
+/* the number of physical writes to the log performed */
+ulint srv_log_writes = 0;
+
+/* amount of data written to the log files in bytes */
+ulint srv_os_log_written = 0;
+
+/* amount of writes being done to the log files */
+ulint srv_os_log_pending_writes = 0;
+
+/* we increase this counter, when there we don't have enough space in the
+log buffer and have to flush it */
+ulint srv_log_waits = 0;
+
+/* this variable counts the amount of times, when the doublewrite buffer
+was flushed */
+ulint srv_dblwr_writes = 0;
+
+/* here we store the number of pages that have been flushed to the
+doublewrite buffer */
+ulint srv_dblwr_pages_written = 0;
+
+/* in this variable we store the number of write requests issued */
+ulint srv_buf_pool_write_requests = 0;
+
+/* here we store the number of times when we had to wait for a free page
+in the buffer pool. It happens when the buffer pool is full and we need
+to make a flush, in order to be able to read or create a page. */
+ulint srv_buf_pool_wait_free = 0;
+
+/* variable to count the number of pages that were written from buffer
+pool to the disk */
+ulint srv_buf_pool_flushed = 0;
+
+/* variable to count the number of buffer pool reads that led to the
+reading of a disk page */
+ulint srv_buf_pool_reads = 0;
+
+/* variable to count the number of sequential read-aheads */
+ulint srv_read_ahead_seq = 0;
+
+/* variable to count the number of random read-aheads */
+ulint srv_read_ahead_rnd = 0;
+
+/* structure to pass status variables to MySQL */
+export_struc export_vars;
+
/* If the following is != 0 we do not allow inserts etc. This protects
the user from forgetting the innodb_force_recovery keyword to my.cnf */
@@ -204,7 +260,8 @@ semaphore contention and convoy problems can occur withput this restriction.
Value 10 should be good if there are less than 4 processors + 4 disks in the
computer. Bigger computers need bigger values. */
-ulint srv_thread_concurrency = 8;
+ulong srv_thread_concurrency = SRV_CONCURRENCY_THRESHOLD;
+ulong srv_commit_concurrency = 0;
os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data
structures */
@@ -241,22 +298,20 @@ srv_conc_slot_t* srv_conc_slots; /* array of wait
/* Number of times a thread is allowed to enter InnoDB within the same
SQL query after it has once got the ticket at srv_conc_enter_innodb */
-#define SRV_FREE_TICKETS_TO_ENTER 500
-
+#define SRV_FREE_TICKETS_TO_ENTER srv_n_free_tickets_to_enter
+#define SRV_THREAD_SLEEP_DELAY srv_thread_sleep_delay
/*-----------------------*/
-/* If the following is set TRUE then we do not run purge and insert buffer
-merge to completion before shutdown */
-
-ibool srv_fast_shutdown = FALSE;
+/* If the following is set to 1 then we do not run purge and insert buffer
+merge to completion before shutdown. If it is set to 2, do not even flush the
+buffer pool to data files at the shutdown: we effectively 'crash'
+InnoDB (but lose no committed transactions). */
+ulint srv_fast_shutdown = 0;
-ibool srv_very_fast_shutdown = FALSE; /* if this TRUE, do not flush the
- buffer pool to data files at the
- shutdown; we effectively 'crash'
- InnoDB */
/* Generate a innodb_status.<pid> file */
ibool srv_innodb_status = FALSE;
ibool srv_use_doublewrite_buf = TRUE;
+ibool srv_use_checksums = TRUE;
ibool srv_set_thread_priorities = TRUE;
int srv_query_thread_priority = 0;
@@ -267,7 +322,9 @@ ibool srv_use_awe = FALSE;
ibool srv_use_adaptive_hash_indexes = TRUE;
/*-------------------------------------------*/
-ulint srv_n_spin_wait_rounds = 20;
+ulong srv_n_spin_wait_rounds = 20;
+ulong srv_n_free_tickets_to_enter = 500;
+ulong srv_thread_sleep_delay = 10000;
ulint srv_spin_wait_delay = 5;
ibool srv_priority_boost = TRUE;
@@ -286,6 +343,12 @@ static ulint srv_n_rows_updated_old = 0;
static ulint srv_n_rows_deleted_old = 0;
static ulint srv_n_rows_read_old = 0;
+ulint srv_n_lock_wait_count = 0;
+ulint srv_n_lock_wait_current_count = 0;
+ib_longlong srv_n_lock_wait_time = 0;
+ulint srv_n_lock_max_wait_time = 0;
+
+
/*
Set the following to 0 if you want InnoDB to write messages on
stderr on startup/shutdown
@@ -780,13 +843,14 @@ srv_get_thread_type(void)
/*************************************************************************
Initializes the server. */
-static
+
void
srv_init(void)
/*==========*/
{
srv_conc_slot_t* conc_slot;
srv_slot_t* slot;
+ dict_table_t* table;
ulint i;
srv_sys = mem_alloc(sizeof(srv_sys_t));
@@ -836,6 +900,31 @@ srv_init(void)
UT_LIST_INIT(srv_sys->tasks);
+ /* create dummy table and index for old-style infimum and supremum */
+ table = dict_mem_table_create("SYS_DUMMY1",
+ DICT_HDR_SPACE, 1, FALSE);
+ dict_mem_table_add_col(table, "DUMMY", DATA_CHAR,
+ DATA_ENGLISH | DATA_NOT_NULL, 8, 0);
+
+ srv_sys->dummy_ind1 = dict_mem_index_create("SYS_DUMMY1",
+ "SYS_DUMMY1", DICT_HDR_SPACE, 0, 1);
+ dict_index_add_col(srv_sys->dummy_ind1,
+ dict_table_get_nth_col(table, 0), 0, 0);
+ srv_sys->dummy_ind1->table = table;
+ /* create dummy table and index for new-style infimum and supremum */
+ table = dict_mem_table_create("SYS_DUMMY2",
+ DICT_HDR_SPACE, 1, TRUE);
+ dict_mem_table_add_col(table, "DUMMY", DATA_CHAR,
+ DATA_ENGLISH | DATA_NOT_NULL, 8, 0);
+ srv_sys->dummy_ind2 = dict_mem_index_create("SYS_DUMMY2",
+ "SYS_DUMMY2", DICT_HDR_SPACE, 0, 1);
+ dict_index_add_col(srv_sys->dummy_ind2,
+ dict_table_get_nth_col(table, 0), 0, 0);
+ srv_sys->dummy_ind2->table = table;
+
+ /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
+ srv_sys->dummy_ind1->cached = srv_sys->dummy_ind2->cached = TRUE;
+
/* Init the server concurrency restriction data structures */
os_fast_mutex_init(&srv_conc_mutex);
@@ -895,12 +984,6 @@ srv_conc_enter_innodb(
srv_conc_slot_t* slot = NULL;
ulint i;
- if (srv_thread_concurrency >= 500) {
- /* Disable the concurrency check */
-
- return;
- }
-
/* If trx has 'free tickets' to enter the engine left, then use one
such ticket */
@@ -917,7 +1000,7 @@ retry:
fputs(
" InnoDB: Error: trying to declare trx to enter InnoDB, but\n"
"InnoDB: it already is declared.\n", stderr);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 0);
putc('\n', stderr);
os_fast_mutex_unlock(&srv_conc_mutex);
@@ -935,8 +1018,8 @@ retry:
return;
}
- /* If the transaction is not holding resources, let it sleep for 50
- milliseconds, and try again then */
+ /* If the transaction is not holding resources,
+ let it sleep for SRV_THREAD_SLEEP_DELAY microseconds, and try again then */
if (!has_slept && !trx->has_search_latch
&& NULL == UT_LIST_GET_FIRST(trx->trx_locks)) {
@@ -955,8 +1038,10 @@ retry:
situations of lots of thread switches. Simply put some
threads aside for a while to reduce the number of thread
switches. */
-
- os_thread_sleep(10000);
+ if (SRV_THREAD_SLEEP_DELAY > 0)
+ {
+ os_thread_sleep(SRV_THREAD_SLEEP_DELAY);
+ }
trx->op_info = "";
@@ -1044,7 +1129,7 @@ srv_conc_force_enter_innodb(
trx_t* trx) /* in: transaction object associated with the
thread */
{
- if (srv_thread_concurrency >= 500) {
+ if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) {
return;
}
@@ -1070,7 +1155,7 @@ srv_conc_force_exit_innodb(
{
srv_conc_slot_t* slot = NULL;
- if (srv_thread_concurrency >= 500) {
+ if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) {
return;
}
@@ -1122,11 +1207,6 @@ srv_conc_exit_innodb(
trx_t* trx) /* in: transaction object associated with the
thread */
{
- if (srv_thread_concurrency >= 500) {
-
- return;
- }
-
if (trx->n_tickets_to_enter_innodb > 0) {
/* We will pretend the thread is still inside InnoDB though it
now leaves the InnoDB engine. In this way we save
@@ -1216,6 +1296,7 @@ srv_boot(void)
return(DB_SUCCESS);
}
+#ifndef UNIV_HOTBACKUP
/*************************************************************************
Reserves a slot in the thread table for the current MySQL OS thread.
NOTE! The kernel mutex has to be reserved by the caller! */
@@ -1274,6 +1355,7 @@ srv_table_reserve_slot_for_mysql(void)
return(slot);
}
+#endif /* !UNIV_HOTBACKUP */
/*******************************************************************
Puts a MySQL OS thread to wait for a lock to be released. If an error
@@ -1288,13 +1370,19 @@ srv_suspend_mysql_thread(
que_thr_t* thr) /* in: query thread associated with the MySQL
OS thread */
{
+#ifndef UNIV_HOTBACKUP
srv_slot_t* slot;
os_event_t event;
double wait_time;
trx_t* trx;
ibool had_dict_lock = FALSE;
ibool was_declared_inside_innodb = FALSE;
-
+ ib_longlong start_time = 0;
+ ib_longlong finish_time;
+ ulint diff_time;
+ ulint sec;
+ ulint ms;
+
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
@@ -1337,6 +1425,13 @@ srv_suspend_mysql_thread(
slot->suspend_time = ut_time();
+ if (thr->lock_state == QUE_THR_LOCK_ROW) {
+ srv_n_lock_wait_count++;
+ srv_n_lock_wait_current_count++;
+
+ ut_usectime(&sec, &ms);
+ start_time = (ib_longlong)sec * 1000000 + ms;
+ }
/* Wake the lock timeout monitor thread, if it is suspended */
os_event_set(srv_lock_timeout_thread_event);
@@ -1387,7 +1482,20 @@ srv_suspend_mysql_thread(
slot->in_use = FALSE;
wait_time = ut_difftime(ut_time(), slot->suspend_time);
-
+
+ if (thr->lock_state == QUE_THR_LOCK_ROW) {
+ ut_usectime(&sec, &ms);
+ finish_time = (ib_longlong)sec * 1000000 + ms;
+
+ diff_time = (ulint) (finish_time - start_time);
+
+ srv_n_lock_wait_current_count--;
+ srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time;
+ if (diff_time > srv_n_lock_max_wait_time) {
+ srv_n_lock_max_wait_time = diff_time;
+ }
+ }
+
if (trx->was_chosen_as_deadlock_victim) {
trx->error_state = DB_DEADLOCK;
@@ -1401,6 +1509,12 @@ srv_suspend_mysql_thread(
trx->error_state = DB_LOCK_WAIT_TIMEOUT;
}
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/************************************************************************
@@ -1413,6 +1527,7 @@ srv_release_mysql_thread_if_suspended(
que_thr_t* thr) /* in: query thread associated with the
MySQL OS thread */
{
+#ifndef UNIV_HOTBACKUP
srv_slot_t* slot;
ulint i;
@@ -1434,8 +1549,15 @@ srv_release_mysql_thread_if_suspended(
}
/* not found */
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
+#ifndef UNIV_HOTBACKUP
/**********************************************************************
Refreshes the values used to calculate per-second averages. */
static
@@ -1590,6 +1712,10 @@ srv_printf_innodb_monitor(
fprintf(file, "%ld queries inside InnoDB, %lu queries in queue\n",
(long) srv_conc_n_threads,
(ulong) srv_conc_n_waiting_threads);
+
+ fprintf(file, "%lu read views open inside InnoDB\n",
+ UT_LIST_GET_LEN(trx_sys->view_list));
+
n_reserved = fil_space_get_n_reserved_extents(0);
if (n_reserved > 0) {
fprintf(file,
@@ -1625,19 +1751,80 @@ srv_printf_innodb_monitor(
(srv_n_rows_read - srv_n_rows_read_old)
/ time_elapsed);
- srv_n_rows_inserted_old = srv_n_rows_inserted;
+ srv_n_rows_inserted_old = srv_n_rows_inserted;
srv_n_rows_updated_old = srv_n_rows_updated;
srv_n_rows_deleted_old = srv_n_rows_deleted;
srv_n_rows_read_old = srv_n_rows_read;
- fputs("----------------------------\n"
+ fputs("----------------------------\n"
"END OF INNODB MONITOR OUTPUT\n"
"============================\n", file);
-
mutex_exit(&srv_innodb_monitor_mutex);
fflush(file);
}
+/**********************************************************************
+Function to pass InnoDB status variables to MySQL */
+
+void
+srv_export_innodb_status(void)
+{
+
+ mutex_enter(&srv_innodb_monitor_mutex);
+ export_vars.innodb_data_pending_reads= os_n_pending_reads;
+ export_vars.innodb_data_pending_writes= os_n_pending_writes;
+ export_vars.innodb_data_pending_fsyncs=
+ fil_n_pending_log_flushes + fil_n_pending_tablespace_flushes;
+ export_vars.innodb_data_fsyncs= os_n_fsyncs;
+ export_vars.innodb_data_read= srv_data_read;
+ export_vars.innodb_data_reads= os_n_file_reads;
+ export_vars.innodb_data_writes= os_n_file_writes;
+ export_vars.innodb_data_written= srv_data_written;
+ export_vars.innodb_buffer_pool_read_requests= buf_pool->n_page_gets;
+ export_vars.innodb_buffer_pool_write_requests= srv_buf_pool_write_requests;
+ export_vars.innodb_buffer_pool_wait_free= srv_buf_pool_wait_free;
+ export_vars.innodb_buffer_pool_pages_flushed= srv_buf_pool_flushed;
+ export_vars.innodb_buffer_pool_reads= srv_buf_pool_reads;
+ export_vars.innodb_buffer_pool_read_ahead_rnd= srv_read_ahead_rnd;
+ export_vars.innodb_buffer_pool_read_ahead_seq= srv_read_ahead_seq;
+ export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU);
+ export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list);
+ export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free);
+ export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number();
+ export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size;
+ export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size -
+ UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free);
+ export_vars.innodb_page_size= UNIV_PAGE_SIZE;
+ export_vars.innodb_log_waits= srv_log_waits;
+ export_vars.innodb_os_log_written= srv_os_log_written;
+ export_vars.innodb_os_log_fsyncs= fil_n_log_flushes;
+ export_vars.innodb_os_log_pending_fsyncs= fil_n_pending_log_flushes;
+ export_vars.innodb_os_log_pending_writes= srv_os_log_pending_writes;
+ export_vars.innodb_log_write_requests= srv_log_write_requests;
+ export_vars.innodb_log_writes= srv_log_writes;
+ export_vars.innodb_dblwr_pages_written= srv_dblwr_pages_written;
+ export_vars.innodb_dblwr_writes= srv_dblwr_writes;
+ export_vars.innodb_pages_created= buf_pool->n_pages_created;
+ export_vars.innodb_pages_read= buf_pool->n_pages_read;
+ export_vars.innodb_pages_written= buf_pool->n_pages_written;
+ export_vars.innodb_row_lock_waits= srv_n_lock_wait_count;
+ export_vars.innodb_row_lock_current_waits= srv_n_lock_wait_current_count;
+ export_vars.innodb_row_lock_time= srv_n_lock_wait_time / 10000;
+ if (srv_n_lock_wait_count > 0) {
+ export_vars.innodb_row_lock_time_avg = (ulint)
+ (srv_n_lock_wait_time / 10000 / srv_n_lock_wait_count);
+ } else {
+ export_vars.innodb_row_lock_time_avg = 0;
+ }
+ export_vars.innodb_row_lock_time_max= srv_n_lock_max_wait_time / 10000;
+ export_vars.innodb_rows_read= srv_n_rows_read;
+ export_vars.innodb_rows_inserted= srv_n_rows_inserted;
+ export_vars.innodb_rows_updated= srv_n_rows_updated;
+ export_vars.innodb_rows_deleted= srv_n_rows_deleted;
+ mutex_exit(&srv_innodb_monitor_mutex);
+
+}
+
/*************************************************************************
A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors. */
@@ -2296,11 +2483,11 @@ background_loop:
flush_loop:
srv_main_thread_op_info = "flushing buffer pool pages";
- if (!srv_very_fast_shutdown) {
+ if (srv_fast_shutdown < 2) {
n_pages_flushed =
buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
} else {
- /* In a 'very fast' shutdown we do not flush the buffer pool
+ /* In the fastest shutdown we do not flush the buffer pool
to data files: we set n_pages_flushed to 0 artificially. */
n_pages_flushed = 0;
@@ -2420,3 +2607,4 @@ suspend_thread:
return(0);
#endif
}
+#endif /* !UNIV_HOTBACKUP */
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 87f4c31257a..325b0a109cf 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -479,7 +479,6 @@ srv_normalize_path_for_win(
Adds a slash or a backslash to the end of a string if it is missing
and the string is not empty. */
-static
char*
srv_add_path_separator_if_needed(
/*=============================*/
@@ -531,6 +530,7 @@ srv_calc_high32(
return(file_size >> (32 - UNIV_PAGE_SIZE_SHIFT));
}
+#ifndef UNIV_HOTBACKUP
/*************************************************************************
Creates or opens the log files and closes them. */
static
@@ -1040,7 +1040,9 @@ innobase_start_or_create_for_mysql(void)
srv_start_has_been_called = TRUE;
+#ifdef UNIV_DEBUG
log_do_write = TRUE;
+#endif /* UNIV_DEBUG */
/* yydebug = TRUE; */
srv_is_being_started = TRUE;
@@ -1478,15 +1480,13 @@ NetWare. */
fsp_header_inc_size(0, sum_of_new_sizes, &mtr);
mtr_commit(&mtr);
- }
- if (recv_needed_recovery) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Flushing modified pages from the buffer pool...\n");
- }
+ /* Immediately write the log record about increased tablespace
+ size to disk, so that it is durable even if mysqld would crash
+ quickly */
- log_make_checkpoint_at(ut_dulint_max, TRUE);
+ log_buffer_flush_to_disk();
+ }
#ifdef UNIV_LOG_ARCHIVE
/* Archiving is always off under MySQL */
@@ -1557,8 +1557,9 @@ NetWare. */
os_thread_create(&srv_master_thread, NULL, thread_ids + 1 +
SRV_MAX_N_IO_THREADS);
+#ifdef UNIV_DEBUG
/* buf_debug_prints = TRUE; */
-
+#endif /* UNIV_DEBUG */
sum_of_data_file_sizes = 0;
for (i = 0; i < srv_n_data_files; i++) {
@@ -1732,6 +1733,15 @@ innobase_shutdown_for_mysql(void)
The step 1 is the real InnoDB shutdown. The remaining steps 2 - ...
just free data structures after the shutdown. */
+
+ if (srv_fast_shutdown == 2) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: MySQL has requested a very fast shutdown without flushing "
+"the InnoDB buffer pool to data files. At the next mysqld startup "
+"InnoDB will do a crash recovery!\n");
+ }
+
#ifdef __NETWARE__
if(!panic_shutdown)
#endif
@@ -1748,6 +1758,14 @@ innobase_shutdown_for_mysql(void)
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
+ /* In a 'very fast' shutdown, we do not need to wait for these threads
+ to die; all which counts is that we flushed the log; a 'very fast'
+ shutdown is essentially a crash. */
+
+ if (srv_fast_shutdown == 2) {
+ return(DB_SUCCESS);
+ }
+
/* All threads end up waiting for certain events. Put those events
to the signaled state. Then the threads will exit themselves in
os_thread_event_wait(). */
@@ -1816,6 +1834,16 @@ innobase_shutdown_for_mysql(void)
srv_free();
os_sync_free();
+ /* Check that all read views are closed except read view owned
+ by a purge. */
+
+ if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) {
+ fprintf(stderr,
+"InnoDB: Error: all read views were not closed before shutdown:\n"
+"InnoDB: %lu read views open \n",
+ UT_LIST_GET_LEN(trx_sys->view_list) - 1);
+ }
+
/* 5. Free all allocated memory and the os_fast_mutex created in
ut0mem.c */
@@ -1856,4 +1884,5 @@ void set_panic_flag_for_netware()
extern ibool panic_shutdown;
panic_shutdown = TRUE;
}
-#endif
+#endif /* __NETWARE__ */
+#endif /* !UNIV_HOTBACKUP */
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index 77757685208..973b46fdd50 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -90,7 +90,8 @@ rw_lock_create_func(
/*================*/
rw_lock_t* lock, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */
- ulint cline) /* in: file line where created */
+ ulint cline, /* in: file line where created */
+ const char* cmutex_name) /* in: mutex name */
{
/* If this is the very first time a synchronization
object is created, then the following call initializes
@@ -101,7 +102,11 @@ rw_lock_create_func(
lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline;
-
+#ifndef UNIV_HOTBACKUP
+ lock->mutex.cmutex_name = cmutex_name;
+ lock->mutex.mutex_type = 1;
+#endif /* !UNIV_HOTBACKUP */
+
rw_lock_set_waiters(lock, 0);
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
lock->writer_count = 0;
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 86306e49cac..43249f4b96f 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -129,11 +129,6 @@ sync_array_t* sync_primary_wait_array;
/* This variable is set to TRUE when sync_init is called */
ibool sync_initialized = FALSE;
-/* Global list of database mutexes (not OS mutexes) created. */
-UT_LIST_BASE_NODE_T(mutex_t) mutex_list;
-
-/* Mutex protecting the mutex_list variable */
-mutex_t mutex_list_mutex;
typedef struct sync_level_struct sync_level_t;
typedef struct sync_thread_struct sync_thread_t;
@@ -146,6 +141,12 @@ sync_thread_t* sync_thread_level_arrays;
/* Mutex protecting sync_thread_level_arrays */
mutex_t sync_thread_mutex;
+/* Global list of database mutexes (not OS mutexes) created. */
+ut_list_base_node_t mutex_list;
+
+/* Mutex protecting the mutex_list variable */
+mutex_t mutex_list_mutex;
+
/* Latching order checks start when this is set TRUE */
ibool sync_order_checks_on = FALSE;
@@ -202,7 +203,8 @@ mutex_create_func(
/*==============*/
mutex_t* mutex, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */
- ulint cline) /* in: file line where created */
+ ulint cline, /* in: file line where created */
+ const char* cmutex_name) /* in: mutex name */
{
#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
mutex_reset_lock_word(mutex);
@@ -219,6 +221,17 @@ mutex_create_func(
mutex->level = SYNC_LEVEL_NONE;
mutex->cfile_name = cfile_name;
mutex->cline = cline;
+#ifndef UNIV_HOTBACKUP
+ mutex->cmutex_name= cmutex_name;
+ mutex->count_using= 0;
+ mutex->mutex_type= 0;
+ mutex->lspent_time= 0;
+ mutex->lmax_spent_time= 0;
+ mutex->count_spin_loop= 0;
+ mutex->count_spin_rounds= 0;
+ mutex->count_os_wait= 0;
+ mutex->count_os_yield= 0;
+#endif /* !UNIV_HOTBACKUP */
/* Check that lock_word is aligned; this is important on Intel */
ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
@@ -355,135 +368,188 @@ for the mutex before suspending the thread. */
void
mutex_spin_wait(
/*============*/
- mutex_t* mutex, /* in: pointer to mutex */
- const char* file_name, /* in: file name where
- mutex requested */
- ulint line) /* in: line where requested */
+ mutex_t* mutex, /* in: pointer to mutex */
+ const char* file_name, /* in: file name where
+ mutex requested */
+ ulint line) /* in: line where requested */
{
- ulint index; /* index of the reserved wait cell */
- ulint i; /* spin round count */
-
- ut_ad(mutex);
+ ulint index; /* index of the reserved wait cell */
+ ulint i; /* spin round count */
+#ifndef UNIV_HOTBACKUP
+ ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */
+ ulint ltime_diff;
+ ulint sec;
+ ulint ms;
+ uint timer_started = 0;
+#endif /* !UNIV_HOTBACKUP */
+ ut_ad(mutex);
mutex_loop:
- i = 0;
-
- /* Spin waiting for the lock word to become zero. Note that we do not
- have to assume that the read access to the lock word is atomic, as the
- actual locking is always committed with atomic test-and-set. In
- reality, however, all processors probably have an atomic read of a
- memory word. */
-
-spin_loop:
- mutex_spin_wait_count++;
-
- while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) {
+ i = 0;
- if (srv_spin_wait_delay) {
- ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
- }
-
- i++;
- }
+/* Spin waiting for the lock word to become zero. Note that we do not
+ have to assume that the read access to the lock word is atomic, as the
+ actual locking is always committed with atomic test-and-set. In
+ reality, however, all processors probably have an atomic read of a
+ memory word. */
- if (i == SYNC_SPIN_ROUNDS) {
- os_thread_yield();
- }
+spin_loop:
+#ifndef UNIV_HOTBACKUP
+ mutex_spin_wait_count++;
+ mutex->count_spin_loop++;
+#endif /* !UNIV_HOTBACKUP */
+
+ while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS)
+ {
+ if (srv_spin_wait_delay)
+ {
+ ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
+ }
+
+ i++;
+ }
+
+ if (i == SYNC_SPIN_ROUNDS)
+ {
+#ifndef UNIV_HOTBACKUP
+ mutex->count_os_yield++;
+ if (timed_mutexes == 1 && timer_started==0)
+ {
+ ut_usectime(&sec, &ms);
+ lstart_time= (ib_longlong)sec * 1000000 + ms;
+ timer_started = 1;
+ }
+#endif /* !UNIV_HOTBACKUP */
+ os_thread_yield();
+ }
+
+#ifdef UNIV_SRV_PRINT_LATCH_WAITS
+ fprintf(stderr,
+ "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n",
+ (ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
+ mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
+#endif
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
- mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
- }
+ mutex_spin_round_count += i;
- mutex_spin_round_count += i;
+#ifndef UNIV_HOTBACKUP
+ mutex->count_spin_rounds += i;
+#endif /* !UNIV_HOTBACKUP */
- if (mutex_test_and_set(mutex) == 0) {
- /* Succeeded! */
+ if (mutex_test_and_set(mutex) == 0)
+ {
+ /* Succeeded! */
#ifdef UNIV_SYNC_DEBUG
- mutex_set_debug_info(mutex, file_name, line);
+ mutex_set_debug_info(mutex, file_name, line);
#endif
- return;
- }
+ goto finish_timing;
+ }
- /* We may end up with a situation where lock_word is
- 0 but the OS fast mutex is still reserved. On FreeBSD
- the OS does not seem to schedule a thread which is constantly
- calling pthread_mutex_trylock (in mutex_test_and_set
- implementation). Then we could end up spinning here indefinitely.
- The following 'i++' stops this infinite spin. */
+ /* We may end up with a situation where lock_word is
+ 0 but the OS fast mutex is still reserved. On FreeBSD
+ the OS does not seem to schedule a thread which is constantly
+ calling pthread_mutex_trylock (in mutex_test_and_set
+ implementation). Then we could end up spinning here indefinitely.
+ The following 'i++' stops this infinite spin. */
- i++;
-
- if (i < SYNC_SPIN_ROUNDS) {
+ i++;
- goto spin_loop;
- }
+ if (i < SYNC_SPIN_ROUNDS)
+ {
+ goto spin_loop;
+ }
- sync_array_reserve_cell(sync_primary_wait_array, mutex,
- SYNC_MUTEX,
- file_name, line,
- &index);
+ sync_array_reserve_cell(sync_primary_wait_array, mutex,
+ SYNC_MUTEX, file_name, line, &index);
- mutex_system_call_count++;
+ mutex_system_call_count++;
- /* The memory order of the array reservation and the change in the
- waiters field is important: when we suspend a thread, we first
- reserve the cell and then set waiters field to 1. When threads are
- released in mutex_exit, the waiters field is first set to zero and
- then the event is set to the signaled state. */
-
- mutex_set_waiters(mutex, 1);
+ /* The memory order of the array reservation and the change in the
+ waiters field is important: when we suspend a thread, we first
+ reserve the cell and then set waiters field to 1. When threads are
+ released in mutex_exit, the waiters field is first set to zero and
+ then the event is set to the signaled state. */
+
+ mutex_set_waiters(mutex, 1);
- /* Try to reserve still a few times */
- for (i = 0; i < 4; i++) {
- if (mutex_test_and_set(mutex) == 0) {
+ /* Try to reserve still a few times */
+ for (i = 0; i < 4; i++)
+ {
+ if (mutex_test_and_set(mutex) == 0)
+ {
+ /* Succeeded! Free the reserved wait cell */
- /* Succeeded! Free the reserved wait cell */
+ sync_array_free_cell(sync_primary_wait_array, index);
- sync_array_free_cell(sync_primary_wait_array, index);
-
#ifdef UNIV_SYNC_DEBUG
- mutex_set_debug_info(mutex, file_name, line);
+ mutex_set_debug_info(mutex, file_name, line);
#endif
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu spin wait succeeds at 2:"
- " mutex at %p\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()),
- mutex);
- }
-
- return;
+#ifdef UNIV_SRV_PRINT_LATCH_WAITS
+ fprintf(stderr, "Thread %lu spin wait succeeds at 2:"
+ " mutex at %p\n",
+ (ulong) os_thread_pf(os_thread_get_curr_id()),
+ mutex);
+#endif
- /* Note that in this case we leave the waiters field
- set to 1. We cannot reset it to zero, as we do not know
- if there are other waiters. */
- }
- }
+ goto finish_timing;
- /* Now we know that there has been some thread holding the mutex
- after the change in the wait array and the waiters field was made.
- Now there is no risk of infinite wait on the event. */
+ /* Note that in this case we leave the waiters field
+ set to 1. We cannot reset it to zero, as we do not know
+ if there are other waiters. */
+ }
+ }
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
- mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
- }
-
- mutex_system_call_count++;
- mutex_os_wait_count++;
+ /* Now we know that there has been some thread holding the mutex
+ after the change in the wait array and the waiters field was made.
+Now there is no risk of infinite wait on the event. */
- sync_array_wait_event(sync_primary_wait_array, index);
+#ifdef UNIV_SRV_PRINT_LATCH_WAITS
+ fprintf(stderr,
+ "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
+ (ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
+ mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
+#endif
- goto mutex_loop;
+ mutex_system_call_count++;
+ mutex_os_wait_count++;
+
+#ifndef UNIV_HOTBACKUP
+ mutex->count_os_wait++;
+ /*
+ !!!!! Sometimes os_wait can be called without os_thread_yield
+ */
+
+ if (timed_mutexes == 1 && timer_started==0)
+ {
+ ut_usectime(&sec, &ms);
+ lstart_time= (ib_longlong)sec * 1000000 + ms;
+ timer_started = 1;
+ }
+#endif /* !UNIV_HOTBACKUP */
+
+ sync_array_wait_event(sync_primary_wait_array, index);
+ goto mutex_loop;
+
+finish_timing:
+#ifndef UNIV_HOTBACKUP
+ if (timed_mutexes == 1 && timer_started==1)
+ {
+ ut_usectime(&sec, &ms);
+ lfinish_time= (ib_longlong)sec * 1000000 + ms;
+
+ ltime_diff= (ulint) (lfinish_time - lstart_time);
+ mutex->lspent_time += ltime_diff;
+ if (mutex->lmax_spent_time < ltime_diff)
+ {
+ mutex->lmax_spent_time= ltime_diff;
+ }
+ }
+#endif /* !UNIV_HOTBACKUP */
+ return;
}
/**********************************************************************
@@ -555,6 +621,7 @@ mutex_set_level(
mutex->level = level;
}
+
#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Checks that the current thread owns the mutex. Works only in the debug
@@ -1075,8 +1142,12 @@ sync_thread_add_level(
} else if (level == SYNC_DICT_HEADER) {
ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER));
} else if (level == SYNC_DICT) {
+#ifdef UNIV_DEBUG
ut_a(buf_debug_prints
|| sync_thread_levels_g(array, SYNC_DICT));
+#else /* UNIV_DEBUG */
+ ut_a(sync_thread_levels_g(array, SYNC_DICT));
+#endif /* UNIV_DEBUG */
} else {
ut_error;
}
diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c
index fe429d1cc62..3b7171e6038 100644
--- a/innobase/trx/trx0rec.c
+++ b/innobase/trx/trx0rec.c
@@ -38,16 +38,18 @@ trx_undof_page_add_undo_rec_log(
ulint new_free, /* in: end offset of the entry */
mtr_t* mtr) /* in: mtr */
{
- byte* log_ptr;
- ulint len;
+ byte* log_ptr;
+ const byte* log_end;
+ ulint len;
- log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
+ log_ptr = mlog_open(mtr, 11 + 13 + MLOG_BUF_MARGIN);
if (log_ptr == NULL) {
return;
}
+ log_end = &log_ptr[11 + 13 + MLOG_BUF_MARGIN];
log_ptr = mlog_write_initial_log_record_fast(undo_page,
MLOG_UNDO_INSERT, log_ptr, mtr);
len = new_free - old_free - 4;
@@ -55,14 +57,11 @@ trx_undof_page_add_undo_rec_log(
mach_write_to_2(log_ptr, len);
log_ptr += 2;
- if (len < 256) {
- ut_memcpy(log_ptr, undo_page + old_free + 2, len);
- log_ptr += len;
- }
-
- mlog_close(mtr, log_ptr);
-
- if (len >= MLOG_BUF_MARGIN) {
+ if (log_ptr + len <= log_end) {
+ memcpy(log_ptr, undo_page + old_free + 2, len);
+ mlog_close(mtr, log_ptr + len);
+ } else {
+ mlog_close(mtr, log_ptr);
mlog_catenate_string(mtr, undo_page + old_free + 2, len);
}
}
@@ -404,6 +403,7 @@ trx_undo_page_report_modify(
delete marking is done */
rec_t* rec, /* in: clustered index record which
has NOT yet been modified */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
upd_t* update, /* in: update vector which tells the
columns to be updated; in the case of
a delete, this should be set to NULL */
@@ -430,6 +430,7 @@ trx_undo_page_report_modify(
ulint i;
ut_a(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE);
table = index->table;
@@ -454,7 +455,7 @@ trx_undo_page_report_modify(
/* Store first some general parameters to the undo log */
if (update) {
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, table->comp)) {
type_cmpl = TRX_UNDO_UPD_DEL_REC;
} else {
type_cmpl = TRX_UNDO_UPD_EXIST_REC;
@@ -479,14 +480,20 @@ trx_undo_page_report_modify(
/*----------------------------------------*/
/* Store the state of the info bits */
- bits = rec_get_info_bits(rec);
+ bits = rec_get_info_bits(rec, table->comp);
mach_write_to_1(ptr, bits);
ptr += 1;
/* Store the values of the system columns */
- trx_id = dict_index_rec_get_sys_col(index, DATA_TRX_ID, rec);
+ field = rec_get_nth_field(rec, offsets,
+ dict_index_get_sys_col_pos(index, DATA_TRX_ID), &len);
+ ut_ad(len == DATA_TRX_ID_LEN);
+ trx_id = trx_read_trx_id(field);
+ field = rec_get_nth_field(rec, offsets,
+ dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), &len);
+ ut_ad(len == DATA_ROLL_PTR_LEN);
+ roll_ptr = trx_read_roll_ptr(field);
- roll_ptr = dict_index_rec_get_sys_col(index, DATA_ROLL_PTR, rec);
len = mach_dulint_write_compressed(ptr, trx_id);
ptr += len;
@@ -499,7 +506,7 @@ trx_undo_page_report_modify(
for (i = 0; i < dict_index_get_n_unique(index); i++) {
- field = rec_get_nth_field(rec, i, &flen);
+ field = rec_get_nth_field(rec, offsets, i, &flen);
if (trx_undo_left(undo_page, ptr) < 4) {
@@ -547,14 +554,14 @@ trx_undo_page_report_modify(
ptr += len;
/* Save the old value of field */
- field = rec_get_nth_field(rec, pos, &flen);
+ field = rec_get_nth_field(rec, offsets, pos, &flen);
if (trx_undo_left(undo_page, ptr) < 5) {
return(0);
}
- if (rec_get_nth_field_extern_bit(rec, pos)) {
+ if (rec_offs_nth_extern(offsets, pos)) {
/* If a field has external storage, we add to
flen the flag */
@@ -631,7 +638,7 @@ trx_undo_page_report_modify(
ptr += len;
/* Save the old value of field */
- field = rec_get_nth_field(rec, pos, &flen);
+ field = rec_get_nth_field(rec, offsets, pos, &flen);
if (trx_undo_left(undo_page, ptr) < 5) {
@@ -934,13 +941,11 @@ trx_undo_erase_page_end(
mtr_t* mtr) /* in: mtr */
{
ulint first_free;
- ulint i;
-
+
first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_FREE);
- for (i = first_free; i < UNIV_PAGE_SIZE - FIL_PAGE_DATA_END; i++) {
- undo_page[i] = 0xFF;
- }
+ memset(undo_page + first_free, 0xff,
+ (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free);
mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr);
}
@@ -1008,7 +1013,11 @@ trx_undo_report_row_operation(
ibool is_insert;
trx_rseg_t* rseg;
mtr_t mtr;
-
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ *offsets_ = (sizeof offsets_) / sizeof *offsets_;
+
ut_a(index->type & DICT_CLUSTERED);
if (flags & BTR_NO_UNDO_LOG_FLAG) {
@@ -1019,7 +1028,6 @@ trx_undo_report_row_operation(
}
ut_ad(thr);
- ut_a(index->type & DICT_CLUSTERED);
ut_ad((op_type != TRX_UNDO_INSERT_OP)
|| (clust_entry && !update && !rec));
@@ -1079,9 +1087,10 @@ trx_undo_report_row_operation(
index, clust_entry,
&mtr);
} else {
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
offset = trx_undo_page_report_modify(undo_page, trx,
- index, rec, update,
- cmpl_info, &mtr);
+ index, rec, offsets, update, cmpl_info, &mtr);
}
if (offset == 0) {
@@ -1123,7 +1132,9 @@ trx_undo_report_row_operation(
mutex_exit(&(trx->undo_mutex));
mtr_commit(&mtr);
-
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(DB_OUT_OF_FILE_SPACE);
}
}
@@ -1140,6 +1151,9 @@ trx_undo_report_row_operation(
*roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no,
offset);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
return(DB_SUCCESS);
}
@@ -1236,6 +1250,7 @@ trx_undo_prev_version_build(
index_rec page and purge_view */
rec_t* rec, /* in: version of a clustered index record */
dict_index_t* index, /* in: clustered index */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) */
mem_heap_t* heap, /* in: memory heap from which the memory
needed is allocated */
rec_t** old_vers)/* out, own: previous version, or NULL if
@@ -1258,7 +1273,6 @@ trx_undo_prev_version_build(
ibool dummy_extern;
byte* buf;
ulint err;
-
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
@@ -1266,21 +1280,23 @@ trx_undo_prev_version_build(
MTR_MEMO_PAGE_S_FIX) ||
mtr_memo_contains(index_mtr, buf_block_align(index_rec),
MTR_MEMO_PAGE_X_FIX));
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (!(index->type & DICT_CLUSTERED)) {
fprintf(stderr, "InnoDB: Error: trying to access"
" update undo rec for non-clustered index %s\n"
"InnoDB: Submit a detailed bug report to"
" http://bugs.mysql.com\n"
"InnoDB: index record ", index->name);
- rec_print(stderr, index_rec);
+ rec_print(stderr, index_rec, index);
fputs("\n"
"InnoDB: record version ", stderr);
- rec_print(stderr, rec);
+ rec_print_new(stderr, rec, offsets);
putc('\n', stderr);
return(DB_ERROR);
}
- roll_ptr = row_get_rec_roll_ptr(rec, index);
+ roll_ptr = row_get_rec_roll_ptr(rec, index, offsets);
old_roll_ptr = roll_ptr;
*old_vers = NULL;
@@ -1292,7 +1308,7 @@ trx_undo_prev_version_build(
return(DB_SUCCESS);
}
- rec_trx_id = row_get_rec_trx_id(rec, index);
+ rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
err = trx_undo_get_undo_rec(roll_ptr, rec_trx_id, &undo_rec, heap);
@@ -1341,10 +1357,10 @@ trx_undo_prev_version_build(
ut_print_buf(stderr, undo_rec, 150);
fputs("\n"
"InnoDB: index record ", stderr);
- rec_print(stderr, index_rec);
+ rec_print(stderr, index_rec, index);
fputs("\n"
"InnoDB: record version ", stderr);
- rec_print(stderr, rec);
+ rec_print_new(stderr, rec, offsets);
fprintf(stderr, "\n"
"InnoDB: Record trx id %lu %lu, update rec trx id %lu %lu\n"
"InnoDB: Roll ptr in rec %lu %lu, in update rec %lu %lu\n",
@@ -1358,11 +1374,10 @@ trx_undo_prev_version_build(
(ulong) ut_dulint_get_low(roll_ptr));
trx_purge_sys_print();
-
return(DB_ERROR);
}
- if (row_upd_changes_field_size_or_external(rec, index, update)) {
+ if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint* ext_vect;
ulint n_ext_vect;
@@ -1372,27 +1387,28 @@ trx_undo_prev_version_build(
those fields that update updates to become externally stored
fields. Store the info to ext_vect: */
- ext_vect = mem_alloc(sizeof(ulint) * rec_get_n_fields(rec));
- n_ext_vect = btr_push_update_extern_fields(ext_vect, rec,
+ ext_vect = mem_alloc(sizeof(ulint)
+ * rec_offs_n_fields(offsets));
+ n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets,
update);
entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec,
heap);
row_upd_index_replace_new_col_vals(entry, index, update, heap);
- buf = mem_heap_alloc(heap, rec_get_converted_size(entry));
+ buf = mem_heap_alloc(heap,
+ rec_get_converted_size(index, entry));
- *old_vers = rec_convert_dtuple_to_rec(buf, entry);
+ *old_vers = rec_convert_dtuple_to_rec(buf, index, entry);
/* Now set the extern bits in the old version of the record */
- rec_set_field_extern_bits(*old_vers, ext_vect, n_ext_vect,
- NULL);
+ rec_set_field_extern_bits(*old_vers, index,
+ ext_vect, n_ext_vect, NULL);
mem_free(ext_vect);
} else {
- buf = mem_heap_alloc(heap, rec_get_size(rec));
-
- *old_vers = rec_copy(buf, rec);
-
- row_upd_rec_in_place(*old_vers, update);
+ buf = mem_heap_alloc(heap, rec_offs_size(offsets));
+ *old_vers = rec_copy(buf, rec, offsets);
+ rec_offs_make_valid(*old_vers, index, offsets);
+ row_upd_rec_in_place(*old_vers, offsets, update);
}
return(DB_SUCCESS);
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index eb7c7f43f03..fdfb7428129 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -30,9 +30,13 @@ Created 3/26/1996 Heikki Tuuri
/* This many pages must be undone before a truncate is tried within rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1
+/* In crash recovery, the current trx to be rolled back */
+trx_t* trx_roll_crash_recv_trx = NULL;
+
/* In crash recovery we set this to the undo n:o of the current trx to be
rolled back. Then we can print how many % the rollback has progressed. */
ib_longlong trx_roll_max_undo_no;
+
/* Auxiliary variable which tells the previous progress % we printed */
ulint trx_roll_progress_printed_pct;
@@ -48,6 +52,7 @@ trx_general_rollback_for_mysql(
trx_savept_t* savept) /* in: pointer to savepoint undo number, if
partial rollback requested */
{
+#ifndef UNIV_HOTBACKUP
mem_heap_t* heap;
que_thr_t* thr;
roll_node_t* roll_node;
@@ -99,6 +104,12 @@ trx_general_rollback_for_mysql(
srv_active_wake_master_thread();
return((int) trx->error_state);
+#else /* UNIV_HOTBACKUP */
+ /* This function depends on MySQL code that is not included in
+ InnoDB Hot Backup builds. Besides, this function should never
+ be called in InnoDB Hot Backup. */
+ ut_error;
+#endif /* UNIV_HOTBACKUP */
}
/***********************************************************************
@@ -313,6 +324,51 @@ trx_savepoint_for_mysql(
}
/***********************************************************************
+Releases a named savepoint. Savepoints which
+were set after this savepoint are deleted. */
+
+ulint
+trx_release_savepoint_for_mysql(
+/*============================*/
+ /* out: if no savepoint
+ of the name found then
+ DB_NO_SAVEPOINT,
+ otherwise DB_SUCCESS */
+ trx_t* trx, /* in: transaction handle */
+ const char* savepoint_name) /* in: savepoint name */
+{
+ trx_named_savept_t* savep;
+
+ savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
+
+ while (savep != NULL) {
+ if (0 == ut_strcmp(savep->name, savepoint_name)) {
+ /* Found */
+ break;
+ }
+ savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
+ }
+
+ if (savep == NULL) {
+
+ return(DB_NO_SAVEPOINT);
+ }
+
+ /* We can now free all savepoints strictly later than this one */
+
+ trx_roll_savepoints_free(trx, savep);
+
+ /* Now we can free this savepoint too */
+
+ UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);
+
+ mem_free(savep->name);
+ mem_free(savep);
+
+ return(DB_SUCCESS);
+}
+
+/***********************************************************************
Returns a transaction savepoint taken at this point in time. */
trx_savept_t
@@ -331,11 +387,20 @@ trx_savept_take(
/***********************************************************************
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
-undo log. If the transaction was not yet committed, then we roll it back. */
+undo log. If the transaction was not yet committed, then we roll it back.
+Note: this is done in a background thread. */
-void
-trx_rollback_or_clean_all_without_sess(void)
-/*========================================*/
+#ifndef __WIN__
+void*
+#else
+ulint
+#endif
+trx_rollback_or_clean_all_without_sess(
+/*===================================*/
+ /* out: a dummy parameter */
+ void* arg __attribute__((unused)))
+ /* in: a dummy parameter required by
+ os_thread_create */
{
mem_heap_t* heap;
que_fork_t* fork;
@@ -360,9 +425,9 @@ trx_rollback_or_clean_all_without_sess(void)
if (UT_LIST_GET_FIRST(trx_sys->trx_list)) {
fprintf(stderr,
- "InnoDB: Starting rollback of uncommitted transactions\n");
+"InnoDB: Starting in background the rollback of uncommitted transactions\n");
} else {
- return;
+ goto leave_function;
}
loop:
heap = mem_heap_create(512);
@@ -371,24 +436,32 @@ loop:
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
- while (trx && (trx->sess || (trx->conc_state == TRX_NOT_STARTED))) {
+ while (trx) {
+ if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) {
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ } else if (trx->conc_state == TRX_PREPARED) {
- trx = UT_LIST_GET_NEXT(trx_list, trx);
+ trx->sess = trx_dummy_sess;
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ } else {
+ break;
+ }
}
mutex_exit(&kernel_mutex);
if (trx == NULL) {
+ ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Rollback of uncommitted transactions completed\n");
+ " InnoDB: Rollback of non-prepared transactions completed\n");
mem_heap_free(heap);
-
- return;
+
+ goto leave_function;
}
trx->sess = trx_dummy_sess;
-
+
if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n",
(ulong) ut_dulint_get_high(trx->id),
@@ -417,21 +490,28 @@ loop:
ut_a(thr == que_fork_start_command(fork));
+ trx_roll_crash_recv_trx = trx;
trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no);
trx_roll_progress_printed_pct = 0;
rows_to_undo = trx_roll_max_undo_no;
+
if (rows_to_undo > 1000000000) {
rows_to_undo = rows_to_undo / 1000000;
unit = "M";
}
+ ut_print_timestamp(stderr);
fprintf(stderr,
-"InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo",
+" InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo\n",
(ulong) ut_dulint_get_high(trx->id),
(ulong) ut_dulint_get_low(trx->id),
(ulong) rows_to_undo, unit);
mutex_exit(&kernel_mutex);
+ trx->mysql_thread_id = os_thread_get_curr_id();
+
+ trx->mysql_process_no = os_proc_get_number();
+
if (trx->dict_operation) {
row_mysql_lock_data_dictionary(trx);
}
@@ -446,7 +526,7 @@ loop:
fprintf(stderr,
"InnoDB: Waiting for rollback of trx id %lu to end\n",
- (ulong) ut_dulint_get_low(trx->id));
+ (ulong) ut_dulint_get_low(trx->id));
os_thread_sleep(100000);
mutex_enter(&kernel_mutex);
@@ -485,7 +565,23 @@ loop:
(ulong) ut_dulint_get_low(trx->id));
mem_heap_free(heap);
+ trx_roll_crash_recv_trx = NULL;
+
goto loop;
+
+leave_function:
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit. */
+
+ os_thread_exit(NULL);
+
+ /* The following is dummy code to keep the compiler happy: */
+
+#ifndef __WIN__
+ return(NULL);
+#else
+ return(0);
+#endif
}
/***********************************************************************
@@ -846,16 +942,17 @@ try_again:
ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0);
/* We print rollback progress info if we are in a crash recovery
- and the transaction has at least 1000 row operations to undo */
+ and the transaction has at least 1000 row operations to undo. */
+
+ if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) {
- if (srv_is_being_started && trx_roll_max_undo_no > 1000) {
- progress_pct = 100 - (ulint)
+ progress_pct = 100 - (ulint)
((ut_conv_dulint_to_longlong(undo_no) * 100)
/ trx_roll_max_undo_no);
if (progress_pct != trx_roll_progress_printed_pct) {
if (trx_roll_progress_printed_pct == 0) {
fprintf(stderr,
- "\nInnoDB: Progress in percents: %lu", (ulong) progress_pct);
+"\nInnoDB: Progress in percents: %lu", (ulong) progress_pct);
} else {
fprintf(stderr,
" %lu", (ulong) progress_pct);
@@ -1140,10 +1237,12 @@ trx_finish_rollback_off_kernel(
return;
}
+#ifdef UNIV_DEBUG
if (lock_print_waits) {
fprintf(stderr, "Trx %lu rollback finished\n",
(ulong) ut_dulint_get_low(trx->id));
}
+#endif /* UNIV_DEBUG */
trx_commit_off_kernel(trx);
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index c7292fb7650..bf48c30e942 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -126,6 +126,22 @@ trx_doublewrite_init(
}
/********************************************************************
+Frees the doublewrite buffer. */
+static
+void
+trx_doublewrite_free(void)
+/*======================*/
+{
+ mutex_free(&(trx_doublewrite->mutex));
+
+ mem_free(trx_doublewrite->buf_block_arr);
+ ut_free(trx_doublewrite->write_buf_unaligned);
+
+ mem_free(trx_doublewrite);
+ trx_doublewrite = NULL;
+}
+
+/********************************************************************
Marks the trx sys header when we have successfully upgraded to the >= 4.1.x
multiple tablespace format. */
@@ -513,6 +529,9 @@ trx_sys_doublewrite_init_or_restore_pages(
fil_flush_file_spaces(FIL_TABLESPACE);
+ if (!srv_use_doublewrite_buf)
+ trx_doublewrite_free();
+
leave_func:
ut_free(unaligned_read_buf);
}
@@ -889,8 +908,12 @@ trx_sys_init_at_db_start(void)
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
for (;;) {
- rows_to_undo +=
+
+ if ( trx->conc_state != TRX_PREPARED) {
+ rows_to_undo +=
ut_conv_dulint_to_longlong(trx->undo_no);
+ }
+
trx = UT_LIST_GET_NEXT(trx_list, trx);
if (!trx) {
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 13575a3cedd..078befb81d2 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -24,13 +24,15 @@ Created 3/26/1996 Heikki Tuuri
#include "thr0loc.h"
#include "btr0sea.h"
#include "os0proc.h"
+#include "trx0xa.h"
/* Copy of the prototype for innobase_mysql_print_thd: this
copy MUST be equal to the one in mysql/sql/ha_innodb.cc ! */
void innobase_mysql_print_thd(
- FILE* f,
- void* thd);
+ FILE* f,
+ void* thd,
+ uint max_query_len);
/* Dummy session used currently in MySQL interface */
sess_t* trx_dummy_sess = NULL;
@@ -92,6 +94,8 @@ trx_create(
trx->id = ut_dulint_zero;
trx->no = ut_dulint_max;
+ trx->support_xa = TRUE;
+
trx->check_foreigns = TRUE;
trx->check_unique_secondary = TRUE;
@@ -155,11 +159,17 @@ trx_create(
trx->n_tickets_to_enter_innodb = 0;
trx->auto_inc_lock = NULL;
- trx->n_lock_table_exp = 0;
- trx->read_view_heap = mem_heap_create(256);
+ trx->global_read_view_heap = mem_heap_create(256);
+ trx->global_read_view = NULL;
trx->read_view = NULL;
+ /* Set X/Open XA transaction identification to NULL */
+ memset(&trx->xid, 0, sizeof(trx->xid));
+ trx->xid.formatID = -1;
+
+ trx_reset_new_rec_lock_info(trx);
+
return(trx);
}
@@ -253,7 +263,7 @@ trx_free(
fputs(
" InnoDB: Error: Freeing a trx which is declared to be processing\n"
"InnoDB: inside InnoDB.\n", stderr);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 600);
putc('\n', stderr);
}
@@ -268,7 +278,7 @@ trx_free(
(ulong)trx->n_mysql_tables_in_use,
(ulong)trx->mysql_n_tables_locked);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 600);
ut_print_buf(stderr, (byte*)trx, sizeof(trx_t));
}
@@ -301,7 +311,6 @@ trx_free(
ut_a(!trx->has_search_latch);
ut_a(!trx->auto_inc_lock);
- ut_a(!trx->n_lock_table_exp);
ut_a(trx->dict_operation_lock_mode == 0);
@@ -311,10 +320,12 @@ trx_free(
ut_a(UT_LIST_GET_LEN(trx->trx_locks) == 0);
- if (trx->read_view_heap) {
- mem_heap_free(trx->read_view_heap);
+ if (trx->global_read_view_heap) {
+ mem_heap_free(trx->global_read_view_heap);
}
+ trx->global_read_view = NULL;
+
ut_a(trx->read_view == NULL);
mem_free(trx);
@@ -430,13 +441,36 @@ trx_lists_init_at_db_start(void)
trx = trx_create(NULL);
trx->id = undo->trx_id;
-
+ trx->xid = undo->xid;
trx->insert_undo = undo;
trx->rseg = rseg;
if (undo->state != TRX_UNDO_ACTIVE) {
- trx->conc_state = TRX_COMMITTED_IN_MEMORY;
+ /* Prepared transactions are left in
+ the prepared state waiting for a
+ commit or abort decision from MySQL */
+
+ if (undo->state == TRX_UNDO_PREPARED) {
+
+ fprintf(stderr,
+"InnoDB: Transaction %lu %lu was in the XA prepared state.\n",
+ ut_dulint_get_high(trx->id),
+ ut_dulint_get_low(trx->id));
+
+ if (srv_force_recovery == 0) {
+
+ trx->conc_state = TRX_PREPARED;
+ } else {
+ fprintf(stderr,
+"InnoDB: Since innodb_force_recovery > 0, we will rollback it anyway.\n");
+
+ trx->conc_state = TRX_ACTIVE;
+ }
+ } else {
+ trx->conc_state =
+ TRX_COMMITTED_IN_MEMORY;
+ }
/* We give a dummy value for the trx no;
this should have no relevance since purge
@@ -479,10 +513,34 @@ trx_lists_init_at_db_start(void)
trx = trx_create(NULL);
trx->id = undo->trx_id;
+ trx->xid = undo->xid;
if (undo->state != TRX_UNDO_ACTIVE) {
- trx->conc_state =
- TRX_COMMITTED_IN_MEMORY;
+
+ /* Prepared transactions are left in
+ the prepared state waiting for a
+ commit or abort decision from MySQL */
+
+ if (undo->state == TRX_UNDO_PREPARED) {
+ fprintf(stderr,
+"InnoDB: Transaction %lu %lu was in the XA prepared state.\n",
+ ut_dulint_get_high(trx->id),
+ ut_dulint_get_low(trx->id));
+
+ if (srv_force_recovery == 0) {
+
+ trx->conc_state = TRX_PREPARED;
+ } else {
+ fprintf(stderr,
+"InnoDB: Since innodb_force_recovery > 0, we will rollback it anyway.\n");
+
+ trx->conc_state = TRX_ACTIVE;
+ }
+ } else {
+ trx->conc_state =
+ TRX_COMMITTED_IN_MEMORY;
+ }
+
/* We give a dummy value for the trx
number */
@@ -750,7 +808,8 @@ trx_commit_off_kernel(
mutex_enter(&kernel_mutex);
}
- ut_ad(trx->conc_state == TRX_ACTIVE);
+ ut_ad(trx->conc_state == TRX_ACTIVE
+ || trx->conc_state == TRX_PREPARED);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
@@ -775,15 +834,13 @@ trx_commit_off_kernel(
lock_release_off_kernel(trx);
- if (trx->read_view) {
- read_view_close(trx->read_view);
-
- mem_heap_empty(trx->read_view_heap);
- trx->read_view = NULL;
+ if (trx->global_read_view) {
+ read_view_close(trx->global_read_view);
+ mem_heap_empty(trx->global_read_view_heap);
+ trx->global_read_view = NULL;
}
-/* fprintf(stderr, "Trx %lu commit finished\n",
- ut_dulint_get_low(trx->id)); */
+ trx->read_view = NULL;
if (must_flush_log) {
@@ -829,14 +886,15 @@ trx_commit_off_kernel(
/* Do nothing */
} else if (srv_flush_log_at_trx_commit == 1) {
if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) {
- /* Write the log but do not flush it to disk */
+ /* Write the log but do not flush it to disk */
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP,
+ FALSE);
} else {
- /* Write the log to the log files AND flush
- them to disk */
+ /* Write the log to the log files AND flush
+ them to disk */
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
}
} else if (srv_flush_log_at_trx_commit == 2) {
@@ -911,7 +969,9 @@ trx_assign_read_view(
mutex_enter(&kernel_mutex);
if (!trx->read_view) {
- trx->read_view = read_view_open_now(trx, trx->read_view_heap);
+ trx->read_view = read_view_open_now(trx,
+ trx->global_read_view_heap);
+ trx->global_read_view = trx->read_view;
}
mutex_exit(&kernel_mutex);
@@ -1592,16 +1652,18 @@ trx_mark_sql_stat_end(
}
/**************************************************************************
-Prints info about a transaction to the standard output. The caller must
-own the kernel mutex and must have called
-innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL or
-InnoDB cannot meanwhile change the info printed here. */
+Prints info about a transaction to the given file. The caller must own the
+kernel mutex and must have called
+innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
+or InnoDB cannot meanwhile change the info printed here. */
void
trx_print(
/*======*/
- FILE* f, /* in: output stream */
- trx_t* trx) /* in: transaction */
+ FILE* f, /* in: output stream */
+ trx_t* trx, /* in: transaction */
+ uint max_query_len) /* in: max query length to print, or 0 to
+ use the default max length */
{
ibool newline;
@@ -1609,20 +1671,24 @@ trx_print(
(ulong) ut_dulint_get_high(trx->id),
(ulong) ut_dulint_get_low(trx->id));
- switch (trx->conc_state) {
+ switch (trx->conc_state) {
case TRX_NOT_STARTED:
fputs(", not started", f);
break;
case TRX_ACTIVE:
fprintf(f, ", ACTIVE %lu sec",
(ulong)difftime(time(NULL), trx->start_time));
- break;
+ break;
+ case TRX_PREPARED:
+ fprintf(f, ", ACTIVE (PREPARED) %lu sec",
+ (ulong)difftime(time(NULL), trx->start_time));
+ break;
case TRX_COMMITTED_IN_MEMORY:
fputs(", COMMITTED IN MEMORY", f);
break;
default:
fprintf(f, " state %lu", (ulong) trx->conc_state);
- }
+ }
#ifdef UNIV_LINUX
fprintf(f, ", process no %lu", trx->mysql_process_no);
@@ -1647,11 +1713,10 @@ trx_print(
putc('\n', f);
if (trx->n_mysql_tables_in_use > 0 || trx->mysql_n_tables_locked > 0) {
-
- fprintf(f, "mysql tables in use %lu, locked %lu\n",
- (ulong) trx->n_mysql_tables_in_use,
- (ulong) trx->mysql_n_tables_locked);
- }
+ fprintf(f, "mysql tables in use %lu, locked %lu\n",
+ (ulong) trx->n_mysql_tables_in_use,
+ (ulong) trx->mysql_n_tables_locked);
+ }
newline = TRUE;
@@ -1693,6 +1758,273 @@ trx_print(
}
if (trx->mysql_thd != NULL) {
- innobase_mysql_print_thd(f, trx->mysql_thd);
+ innobase_mysql_print_thd(f, trx->mysql_thd, max_query_len);
}
}
+
+/********************************************************************
+Prepares a transaction. */
+
+void
+trx_prepare_off_kernel(
+/*===================*/
+ trx_t* trx) /* in: transaction */
+{
+ page_t* update_hdr_page;
+ trx_rseg_t* rseg;
+ ibool must_flush_log = FALSE;
+ dulint lsn;
+ mtr_t mtr;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+
+ rseg = trx->rseg;
+
+ if (trx->insert_undo != NULL || trx->update_undo != NULL) {
+
+ mutex_exit(&kernel_mutex);
+
+ mtr_start(&mtr);
+
+ must_flush_log = TRUE;
+
+ /* Change the undo log segment states from TRX_UNDO_ACTIVE
+ to TRX_UNDO_PREPARED: these modifications to the file data
+ structure define the transaction as prepared in the
+ file-based world, at the serialization point of lsn. */
+
+ mutex_enter(&(rseg->mutex));
+
+ if (trx->insert_undo != NULL) {
+
+ /* It is not necessary to obtain trx->undo_mutex here
+ because only a single OS thread is allowed to do the
+ transaction prepare for this transaction. */
+
+ trx_undo_set_state_at_prepare(trx, trx->insert_undo,
+ &mtr);
+ }
+
+ if (trx->update_undo) {
+ update_hdr_page = trx_undo_set_state_at_prepare(trx,
+ trx->update_undo, &mtr);
+ }
+
+ mutex_exit(&(rseg->mutex));
+
+ /*--------------*/
+ mtr_commit(&mtr); /* This mtr commit makes the
+ transaction prepared in the file-based
+ world */
+ /*--------------*/
+ lsn = mtr.end_lsn;
+
+ mutex_enter(&kernel_mutex);
+ }
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+
+ /*--------------------------------------*/
+ trx->conc_state = TRX_PREPARED;
+ /*--------------------------------------*/
+
+ if (must_flush_log) {
+ /* Depending on the my.cnf options, we may now write the log
+ buffer to the log files, making the prepared state of the
+ transaction durable if the OS does not crash. We may also
+ flush the log files to disk, making the prepared state of the
+ transaction durable also at an OS crash or a power outage.
+
+ The idea in InnoDB's group prepare is that a group of
+ transactions gather behind a trx doing a physical disk write
+ to log files, and when that physical write has been completed,
+ one of those transactions does a write which prepares the whole
+ group. Note that this group prepare will only bring benefit if
+ there are > 2 users in the database. Then at least 2 users can
+ gather behind one doing the physical log write to disk.
+
+ TODO: find out if MySQL holds some mutex when calling this.
+ That would spoil our group prepare algorithm. */
+
+ mutex_exit(&kernel_mutex);
+
+ if (srv_flush_log_at_trx_commit == 0) {
+ /* Do nothing */
+ } else if (srv_flush_log_at_trx_commit == 1) {
+ if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) {
+ /* Write the log but do not flush it to disk */
+
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP,
+ FALSE);
+ } else {
+ /* Write the log to the log files AND flush
+ them to disk */
+
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
+ }
+ } else if (srv_flush_log_at_trx_commit == 2) {
+
+ /* Write the log but do not flush it to disk */
+
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
+ } else {
+ ut_error;
+ }
+
+ mutex_enter(&kernel_mutex);
+ }
+}
+
+/**************************************************************************
+Does the transaction prepare for MySQL. */
+
+ulint
+trx_prepare_for_mysql(
+/*====-=============*/
+ /* out: 0 or error number */
+ trx_t* trx) /* in: trx handle */
+{
+ /* Because we do not do the prepare by sending an Innobase
+ sig to the transaction, we must here make sure that trx has been
+ started. */
+
+ ut_a(trx);
+
+ trx->op_info = "preparing";
+
+ trx_start_if_not_started(trx);
+
+ mutex_enter(&kernel_mutex);
+
+ trx_prepare_off_kernel(trx);
+
+ mutex_exit(&kernel_mutex);
+
+ trx->op_info = "";
+
+ return(0);
+}
+
+/**************************************************************************
+This function is used to find number of prepared transactions and
+their transaction objects for a recovery. */
+
+int
+trx_recover_for_mysql(
+/*==================*/
+ /* out: number of prepared transactions
+ stored in xid_list */
+ XID* xid_list, /* in/out: prepared transactions */
+ ulint len) /* in: number of slots in xid_list */
+{
+ trx_t* trx;
+ int count = 0;
+
+ ut_ad(xid_list);
+ ut_ad(len);
+
+ /* We should set those transactions which are in the prepared state
+ to the xid_list */
+
+ mutex_enter(&kernel_mutex);
+
+ trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
+
+ while (trx) {
+ if (trx->conc_state == TRX_PREPARED) {
+ xid_list[count] = trx->xid;
+
+ if (count == 0) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Starting recovery for XA transactions...\n");
+ }
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Transaction %lu %lu in prepared state after recovery\n",
+ (ulong) ut_dulint_get_high(trx->id),
+ (ulong) ut_dulint_get_low(trx->id));
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Transaction contains changes to %lu rows\n",
+ (ulong)ut_conv_dulint_to_longlong(trx->undo_no));
+
+ count++;
+
+ if ((uint)count == len ) {
+ break;
+ }
+ }
+
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ }
+
+ mutex_exit(&kernel_mutex);
+
+ if (count > 0){
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: %d transactions in prepared state after recovery\n",
+ count);
+ }
+
+ return (count);
+}
+
+/***********************************************************************
+This function is used to find one X/Open XA distributed transaction
+which is in the prepared state */
+
+trx_t*
+trx_get_trx_by_xid(
+/*===============*/
+ /* out: trx or NULL */
+ XID* xid) /* in: X/Open XA transaction identification */
+{
+ trx_t* trx;
+
+ if (xid == NULL) {
+
+ return (NULL);
+ }
+
+ mutex_enter(&kernel_mutex);
+
+ trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
+
+ while (trx) {
+ /* Compare two X/Open XA transaction id's: their
+ length should be the same and binary comparison
+ of gtrid_lenght+bqual_length bytes should be
+ the same */
+
+ if (xid->gtrid_length == trx->xid.gtrid_length &&
+ xid->bqual_length == trx->xid.bqual_length &&
+ memcmp(xid->data, trx->xid.data,
+ xid->gtrid_length +
+ xid->bqual_length) == 0) {
+ break;
+ }
+
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ }
+
+ mutex_exit(&kernel_mutex);
+
+ if (trx) {
+ if (trx->conc_state != TRX_PREPARED) {
+
+ return(NULL);
+ }
+
+ return(trx);
+ } else {
+ return(NULL);
+ }
+}
diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c
index 8d1518753dd..7441dd3f152 100644
--- a/innobase/trx/trx0undo.c
+++ b/innobase/trx/trx0undo.c
@@ -19,6 +19,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "trx0rec.h"
#include "trx0purge.h"
+#include "trx0xa.h"
/* How should the old versions in the history list be managed?
----------------------------------------------------------
@@ -97,10 +98,13 @@ trx_undo_mem_create(
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open XA transaction identification*/
ulint page_no,/* in: undo log header page number */
- ulint offset); /* in: undo log header byte offset on page */
+ ulint offset);/* in: undo log header byte offset on page */
/*******************************************************************
-Initializes a cached insert undo log header page for new use. */
+Initializes a cached insert undo log header page for new use. NOTE that this
+function has its own log record type MLOG_UNDO_HDR_REUSE. You must NOT change
+the operation of this function! */
static
ulint
trx_undo_insert_header_reuse(
@@ -181,7 +185,8 @@ trx_undo_get_prev_rec(
/* We have to go to the previous undo log page to look for the
previous record */
- return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset, mtr));
+ return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset,
+ mtr));
}
/***************************************************************************
@@ -473,15 +478,17 @@ trx_undo_header_create_log(
}
/*******************************************************************
-Creates a new undo log header in file. */
+Creates a new undo log header in file. NOTE that this function has its own
+log record type MLOG_UNDO_HDR_CREATE. You must NOT change the operation of
+this function! */
static
ulint
trx_undo_header_create(
/*===================*/
/* out: header byte offset on page */
page_t* undo_page, /* in: undo log segment header page,
- x-latched; it is assumed that there is
- TRX_UNDO_LOG_HDR_SIZE bytes free space
+ x-latched; it is assumed that there are
+ TRX_UNDO_LOG_XA_HDR_SIZE bytes free space
on it */
dulint trx_id, /* in: transaction id */
mtr_t* mtr) /* in: mtr */
@@ -503,9 +510,9 @@ trx_undo_header_create(
log_hdr = undo_page + free;
- new_free = free + TRX_UNDO_LOG_HDR_SIZE;
+ new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
- ut_ad(new_free <= UNIV_PAGE_SIZE);
+ ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100);
mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free);
@@ -530,16 +537,98 @@ trx_undo_header_create(
mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
- mach_write_to_2(log_hdr + TRX_UNDO_DICT_OPERATION, FALSE);
-
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
+ mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
+
mach_write_to_2(log_hdr + TRX_UNDO_NEXT_LOG, 0);
mach_write_to_2(log_hdr + TRX_UNDO_PREV_LOG, prev_log);
-
+
+ /* Write the log record about the header creation */
trx_undo_header_create_log(undo_page, trx_id, mtr);
return(free);
}
+/************************************************************************
+Write X/Open XA Transaction Identification (XID) to undo log header */
+static
+void
+trx_undo_write_xid(
+/*===============*/
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ const XID* xid, /* in: X/Open XA Transaction Identification */
+ mtr_t* mtr) /* in: mtr */
+{
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT,
+ (ulint)xid->formatID, MLOG_4BYTES, mtr);
+
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_TRID_LEN,
+ (ulint)xid->gtrid_length, MLOG_4BYTES, mtr);
+
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN,
+ (ulint)xid->bqual_length, MLOG_4BYTES, mtr);
+
+ mlog_write_string(log_hdr + TRX_UNDO_XA_XID, (const byte*) xid->data,
+ XIDDATASIZE, mtr);
+}
+
+/************************************************************************
+Read X/Open XA Transaction Identification (XID) from undo log header */
+static
+void
+trx_undo_read_xid(
+/*==============*/
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ XID* xid) /* out: X/Open XA Transaction Identification */
+{
+ xid->formatID = (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT);
+
+ xid->gtrid_length =
+ (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN);
+ xid->bqual_length =
+ (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN);
+
+ memcpy(xid->data, log_hdr + TRX_UNDO_XA_XID, XIDDATASIZE);
+}
+
+/*******************************************************************
+Adds space for the XA XID after an undo log old-style header. */
+static
+void
+trx_undo_header_add_space_for_xid(
+/*==============================*/
+ page_t* undo_page,/* in: undo log segment header page */
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ mtr_t* mtr) /* in: mtr */
+{
+ trx_upagef_t* page_hdr;
+ ulint free;
+ ulint new_free;
+
+ page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
+
+ free = mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE);
+
+ /* free is now the end offset of the old style undo log header */
+
+ ut_a(free == (ulint)(log_hdr - undo_page) + TRX_UNDO_LOG_OLD_HDR_SIZE);
+
+ new_free = free + (TRX_UNDO_LOG_XA_HDR_SIZE
+ - TRX_UNDO_LOG_OLD_HDR_SIZE);
+
+ /* Add space for a XID after the header, update the free offset
+ fields on the undo log page and in the undo log header */
+
+ mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_START, new_free,
+ MLOG_2BYTES, mtr);
+
+ mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_FREE, new_free,
+ MLOG_2BYTES, mtr);
+
+ mlog_write_ulint(log_hdr + TRX_UNDO_LOG_START, new_free,
+ MLOG_2BYTES, mtr);
+}
+
/**************************************************************************
Writes the mtr log entry of an undo log header reuse. */
UNIV_INLINE
@@ -590,7 +679,9 @@ trx_undo_parse_page_header(
}
/*******************************************************************
-Initializes a cached insert undo log header page for new use. */
+Initializes a cached insert undo log header page for new use. NOTE that this
+function has its own log record type MLOG_UNDO_HDR_REUSE. You must NOT change
+the operation of this function! */
static
ulint
trx_undo_insert_header_reuse(
@@ -614,9 +705,11 @@ trx_undo_insert_header_reuse(
free = TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE;
+ ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100);
+
log_hdr = undo_page + free;
- new_free = free + TRX_UNDO_LOG_HDR_SIZE;
+ new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
/* Insert undo data is not needed after commit: we may free all
the space on the page */
@@ -636,8 +729,10 @@ trx_undo_insert_header_reuse(
mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
- mach_write_to_2(log_hdr + TRX_UNDO_DICT_OPERATION, FALSE);
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
+ mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
+ /* Write the log record MLOG_UNDO_HDR_REUSE */
trx_undo_insert_header_reuse_log(undo_page, trx_id, mtr);
return(free);
@@ -800,7 +895,6 @@ trx_undo_free_page(
list */
ulint space, /* in: space */
ulint hdr_page_no, /* in: header page number */
- ulint hdr_offset, /* in: header offset */
ulint page_no, /* in: page number to free: must not be the
header page */
mtr_t* mtr) /* in: mtr which does not have a latch to any
@@ -813,7 +907,6 @@ trx_undo_free_page(
trx_rsegf_t* rseg_header;
ulint hist_size;
- UT_NOT_USED(hdr_offset);
ut_a(hdr_page_no != page_no);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
@@ -870,8 +963,7 @@ trx_undo_free_page_in_rollback(
#endif /* UNIV_SYNC_DEBUG */
last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
- undo->hdr_page_no, undo->hdr_offset,
- page_no, mtr);
+ undo->hdr_page_no, page_no, mtr);
undo->last_page_no = last_page_no;
undo->size--;
@@ -1039,7 +1131,7 @@ loop:
trx_undo_empty_header_page(space, hdr_page_no, hdr_offset,
&mtr);
} else {
- trx_undo_free_page(rseg, TRUE, space, hdr_page_no, hdr_offset,
+ trx_undo_free_page(rseg, TRUE, space, hdr_page_no,
page_no, &mtr);
}
@@ -1123,7 +1215,9 @@ trx_undo_mem_create_at_db_start(
fil_addr_t last_addr;
page_t* last_page;
trx_undo_rec_t* rec;
-
+ XID xid;
+ ibool xid_exists = FALSE;
+
if (id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n", (ulong) id);
@@ -1145,15 +1239,30 @@ trx_undo_mem_create_at_db_start(
undo_header = undo_page + offset;
trx_id = mtr_read_dulint(undo_header + TRX_UNDO_TRX_ID, mtr);
+
+ xid_exists = mtr_read_ulint(undo_header + TRX_UNDO_XID_EXISTS,
+ MLOG_1BYTE, mtr);
+
+ /* Read X/Open XA transaction identification if it exists, or
+ set it to NULL. */
+
+ memset(&xid, 0, sizeof(xid));
+ xid.formatID = -1;
+
+ if (xid_exists == TRUE) {
+ trx_undo_read_xid(undo_header, &xid);
+ }
+
mutex_enter(&(rseg->mutex));
- undo = trx_undo_mem_create(rseg, id, type, trx_id, page_no, offset);
-
+ undo = trx_undo_mem_create(rseg, id, type, trx_id, &xid,
+ page_no, offset);
mutex_exit(&(rseg->mutex));
- undo->dict_operation = mtr_read_ulint(
- undo_header + TRX_UNDO_DICT_OPERATION,
- MLOG_2BYTES, mtr);
+ undo->dict_operation = mtr_read_ulint(
+ undo_header + TRX_UNDO_DICT_TRANS,
+ MLOG_1BYTE, mtr);
+
undo->table_id = mtr_read_dulint(undo_header + TRX_UNDO_TABLE_ID, mtr);
undo->state = state;
undo->size = flst_get_len(seg_header + TRX_UNDO_PAGE_LIST, mtr);
@@ -1272,7 +1381,8 @@ trx_undo_mem_create(
ulint type, /* in: type of the log: TRX_UNDO_INSERT or
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
- is created */
+ is created */
+ XID* xid, /* in: X/Open transaction identification */
ulint page_no,/* in: undo log header page number */
ulint offset) /* in: undo log header byte offset on page */
{
@@ -1295,6 +1405,7 @@ trx_undo_mem_create(
undo->state = TRX_UNDO_ACTIVE;
undo->del_marks = FALSE;
undo->trx_id = trx_id;
+ undo->xid = *xid;
undo->dict_operation = FALSE;
@@ -1322,6 +1433,7 @@ trx_undo_mem_init_for_reuse(
trx_undo_t* undo, /* in: undo log to init */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open XA transaction identification*/
ulint offset) /* in: undo log header byte offset on page */
{
#ifdef UNIV_SYNC_DEBUG
@@ -1339,6 +1451,7 @@ trx_undo_mem_init_for_reuse(
undo->state = TRX_UNDO_ACTIVE;
undo->del_marks = FALSE;
undo->trx_id = trx_id;
+ undo->xid = *xid;
undo->dict_operation = FALSE;
@@ -1371,11 +1484,13 @@ trx_undo_create(
/*============*/
/* out: undo log object, NULL if did not
succeed: out of space */
+ trx_t* trx, /* in: transaction */
trx_rseg_t* rseg, /* in: rollback segment memory copy */
ulint type, /* in: type of the log: TRX_UNDO_INSERT or
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open transaction identification*/
mtr_t* mtr) /* in: mtr */
{
trx_rsegf_t* rseg_header;
@@ -1410,10 +1525,15 @@ trx_undo_create(
page_no = buf_frame_get_page_no(undo_page);
- offset = trx_undo_header_create(undo_page, trx_id, mtr);
+ offset = trx_undo_header_create(undo_page, trx_id, mtr);
- undo = trx_undo_mem_create(rseg, id, type, trx_id, page_no, offset);
-
+ if (trx->support_xa) {
+ trx_undo_header_add_space_for_xid(undo_page,
+ undo_page + offset, mtr);
+ }
+
+ undo = trx_undo_mem_create(rseg, id, type, trx_id, xid,
+ page_no, offset);
return(undo);
}
@@ -1427,11 +1547,13 @@ trx_undo_reuse_cached(
/*==================*/
/* out: the undo log memory object, NULL if
none cached */
+ trx_t* trx, /* in: transaction */
trx_rseg_t* rseg, /* in: rollback segment memory object */
ulint type, /* in: type of the log: TRX_UNDO_INSERT or
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is used */
+ XID* xid, /* in: X/Open XA transaction identification */
mtr_t* mtr) /* in: mtr */
{
trx_undo_t* undo;
@@ -1476,15 +1598,25 @@ trx_undo_reuse_cached(
if (type == TRX_UNDO_INSERT) {
offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr);
+
+ if (trx->support_xa) {
+ trx_undo_header_add_space_for_xid(undo_page,
+ undo_page + offset, mtr);
+ }
} else {
ut_a(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_TYPE)
== TRX_UNDO_UPDATE);
offset = trx_undo_header_create(undo_page, trx_id, mtr);
+
+ if (trx->support_xa) {
+ trx_undo_header_add_space_for_xid(undo_page,
+ undo_page + offset, mtr);
+ }
}
- trx_undo_mem_init_for_reuse(undo, trx_id, offset);
+ trx_undo_mem_init_for_reuse(undo, trx_id, xid, offset);
return(undo);
}
@@ -1506,9 +1638,10 @@ trx_undo_mark_as_dict_operation(
hdr_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
- mlog_write_ulint(hdr_page + undo->hdr_offset + TRX_UNDO_DICT_OPERATION,
- trx->dict_operation, MLOG_2BYTES, mtr);
-
+ mlog_write_ulint(hdr_page + undo->hdr_offset +
+ TRX_UNDO_DICT_TRANS,
+ trx->dict_operation, MLOG_1BYTE, mtr);
+
mlog_write_dulint(hdr_page + undo->hdr_offset + TRX_UNDO_TABLE_ID,
trx->table_id, mtr);
@@ -1548,11 +1681,11 @@ trx_undo_assign_undo(
#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(rseg->mutex));
- undo = trx_undo_reuse_cached(rseg, type, trx->id, &mtr);
-
+ undo = trx_undo_reuse_cached(trx, rseg, type, trx->id, &trx->xid,
+ &mtr);
if (undo == NULL) {
- undo = trx_undo_create(rseg, type, trx->id, &mtr);
-
+ undo = trx_undo_create(trx, rseg, type, trx->id, &trx->xid,
+ &mtr);
if (undo == NULL) {
/* Did not succeed */
@@ -1632,6 +1765,57 @@ trx_undo_set_state_at_finish(
return(undo_page);
}
+/**********************************************************************
+Sets the state of the undo log segment at a transaction prepare. */
+
+page_t*
+trx_undo_set_state_at_prepare(
+/*==========================*/
+ /* out: undo log segment header page,
+ x-latched */
+ trx_t* trx, /* in: transaction */
+ trx_undo_t* undo, /* in: undo log memory copy */
+ mtr_t* mtr) /* in: mtr */
+{
+ trx_usegf_t* seg_hdr;
+ trx_upagef_t* page_hdr;
+ trx_ulogf_t* undo_header;
+ page_t* undo_page;
+ ulint offset;
+
+ ut_ad(trx && undo && mtr);
+
+ if (undo->id >= TRX_RSEG_N_SLOTS) {
+ fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
+ (ulong) undo->id);
+ mem_analyze_corruption((byte*)undo);
+ ut_error;
+ }
+
+ undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
+
+ seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
+ page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
+
+ /*------------------------------*/
+ undo->state = TRX_UNDO_PREPARED;
+ undo->xid = trx->xid;
+ /*------------------------------*/
+
+ mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, undo->state,
+ MLOG_2BYTES, mtr);
+
+ offset = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG);
+ undo_header = undo_page + offset;
+
+ mlog_write_ulint(undo_header + TRX_UNDO_XID_EXISTS,
+ TRUE, MLOG_1BYTE, mtr);
+
+ trx_undo_write_xid(undo_header, &undo->xid, mtr);
+
+ return(undo_page);
+}
+
/**************************************************************************
Adds the update undo log header as the first in the history list, and
frees the memory object, or puts it to the list of cached update undo log
diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c
index 0f6a27d35d9..e810d8dead7 100644
--- a/innobase/ut/ut0dbg.c
+++ b/innobase/ut/ut0dbg.c
@@ -8,8 +8,11 @@ Created 1/30/1994 Heikki Tuuri
#include "univ.i"
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#else
/* This is used to eliminate compiler warnings */
ulint ut_dbg_zero = 0;
+#endif
/* If this is set to TRUE all threads will stop into the next assertion
and assert */
@@ -19,21 +22,69 @@ ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there
happens an InnoDB assertion failure or other
fatal error condition that requires an
immediate shutdown. */
-#endif
+#else /* __NETWARE__ */
/* Null pointer used to generate memory trap */
ulint* ut_dbg_null_ptr = NULL;
+#endif /* __NETWARE__ */
+
+/*****************************************************************
+Report a failed assertion. */
-const char* ut_dbg_msg_assert_fail =
-"InnoDB: Assertion failure in thread %lu in file %s line %lu\n";
-const char* ut_dbg_msg_trap =
+void
+ut_dbg_assertion_failed(
+/*====================*/
+ const char* expr, /* in: the failed assertion (optional) */
+ const char* file, /* in: source file containing the assertion */
+ ulint line) /* in: line number of the assertion */
+{
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ "InnoDB: Assertion failure in thread %lu"
+ " in file %s line %lu\n",
+ os_thread_pf(os_thread_get_curr_id()), file, line);
+ if (expr) {
+ fprintf(stderr,
+ "InnoDB: Failing assertion: %s\n", expr);
+ }
+
+ fputs(
"InnoDB: We intentionally generate a memory trap.\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com.\n"
"InnoDB: If you get repeated assertion failures or crashes, even\n"
"InnoDB: immediately after the mysqld startup, there may be\n"
"InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
-"InnoDB: about forcing recovery.\n";
+"InnoDB: about forcing recovery.\n", stderr);
+ ut_dbg_stop_threads = TRUE;
+}
+
+#ifdef __NETWARE__
+/*****************************************************************
+Shut down MySQL/InnoDB after assertion failure. */
+
+void
+ut_dbg_panic(void)
+/*==============*/
+{
+ if (!panic_shutdown) {
+ panic_shutdown = TRUE;
+ innobase_shutdown_for_mysql();
+ }
+ exit(1);
+}
+#else /* __NETWARE__ */
+/*****************************************************************
+Stop a thread after assertion failure. */
-const char* ut_dbg_msg_stop =
-"InnoDB: Thread %lu stopped in file %s line %lu\n";
+void
+ut_dbg_stop_thread(
+/*===============*/
+ const char* file,
+ ulint line)
+{
+ fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n",
+ os_thread_pf(os_thread_get_curr_id()), file, line);
+ os_thread_sleep(1000000000);
+}
+#endif /* __NETWARE__ */
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index 18ee53a354c..3e8fd79a739 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -92,6 +92,8 @@ retry:
"InnoDB: ulimits of your operating system.\n"
"InnoDB: On FreeBSD check you have compiled the OS with\n"
"InnoDB: a big enough maximum process size.\n"
+ "InnoDB: Note that in most 32-bit computers the process\n"
+ "InnoDB: memory space is limited to 2 GB or 4 GB.\n"
"InnoDB: We keep retrying the allocation for 60 seconds...\n",
(ulong) n, (ulong) ut_total_allocated_memory,
#ifdef __WIN__
diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c
index 2a2db9442b3..1be5939303a 100644
--- a/innobase/ut/ut0ut.c
+++ b/innobase/ut/ut0ut.c
@@ -74,6 +74,28 @@ ut_time(void)
}
/**************************************************************
+Returns system time. */
+
+void
+ut_usectime(
+/*========*/
+ ulint* sec, /* out: seconds since the Epoch */
+ ulint* ms) /* out: microseconds since the Epoch+*sec */
+{
+#ifdef __WIN__
+ SYSTEMTIME st;
+ GetLocalTime(&st);
+ *sec = (ulint) st.wSecond;
+ *ms = (ulint) st.wMilliseconds;
+#else
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ *sec = (ulint) tv.tv_sec;
+ *ms = (ulint) tv.tv_usec;
+#endif
+}
+
+/**************************************************************
Returns the difference of two times in seconds. */
double
@@ -394,7 +416,11 @@ ut_print_namel(
{
const char* s = name;
const char* e = s + namelen;
+#ifdef UNIV_HOTBACKUP
+ int q = '"';
+#else
int q = mysql_get_identifier_quote_char(trx, name, namelen);
+#endif
if (q == EOF) {
fwrite(name, 1, namelen, f);
return;
diff --git a/install-sh b/install-sh
deleted file mode 100755
index c1666c37407..00000000000
--- a/install-sh
+++ /dev/null
@@ -1,251 +0,0 @@
-#!/bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
-#
-# Copyright 1991 by the Massachusetts Institute of Technology
-#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission. M.I.T. makes no representations about the
-# suitability of this software for any purpose. It is provided "as is"
-# without express or implied warranty.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch. It can only install one file at a time, a restriction
-# shared with many OS's install programs.
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=""
-transform_arg=""
-instcmd="$cpprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
-
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
-else
- true
-fi
-
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
-
- if [ -d $dst ]; then
- instcmd=:
- chmodcmd=""
- else
- instcmd=mkdir
- fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
-
- if [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
-
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-'
-IFS="${IFS-${defaultIFS}}"
-
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
-
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
-
- pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
-
-# don't allow the sed command to completely eliminate the filename
-
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
-
-# Make a temp file name in the proper directory.
-
- dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
- $doit $instcmd $src $dsttmp &&
-
- trap "rm -f ${dsttmp}" 0 &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing. If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
-
-fi &&
-
-
-exit 0
diff --git a/isam/.cvsignore b/isam/.cvsignore
deleted file mode 100644
index dc55807a96b..00000000000
--- a/isam/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-isamchk
-isamlog
-pack_isam
-test1
-test2
-test3
diff --git a/isam/ChangeLog b/isam/ChangeLog
deleted file mode 100644
index 4a9e3e03954..00000000000
--- a/isam/ChangeLog
+++ /dev/null
@@ -1,186 +0,0 @@
-2000-04-26 Michael Widenius <monty@mysql.com>
-
-* Fixed bug when doing read_next after a delete/insert which balanced key
- pages (In this case one internal buffer was wrongly reused)
-
-1999-11-23 Michael Widenius <monty@monty.pp.sci.fi>
-
-* Changed prefix from ni_ to nisam_ to avoid problems on MacOS X.
-
-1999-08-17 Michael Widenius <monty@tik.pp.sci.fi>
-
-* Changed last parameter to mi_open() to be a bit flag instead of an int.
-
-1998-10-01 Michael Widenius <monty@monty.pp.sci.fi>
-
-* Fixed bug in key packing when using some USE_STRCOLL character sets.
-
-Thu Aug 20 23:17:41 1998 Michael Widenius <monty@bitch.pp.sci.fi>
-
-* isamchk.c: Sometimes isamchk --sort-table caused isamchk to die.
-
-1998-06-28 Michael Widenius <monty@monty.pp.sci.fi>
-
-* Fixed some possible race conditions when using with MySQL and
- many reopen/close of the same tables under heavy load!
-* Changed isamchk to re-pack records when doing a repair to make it more safer.
-
-Thu Mar 12 21:44:08 1998 Michael Widenius <monty@monty.pp.sci.fi>
-
-* Added a safty test to _ni_rec_unpack.
-
-Wed Nov 26 01:52:55 1997 <monty@monty.pp.sci.fi>
-
-* Fixed small problem when reading delete-marked records with rkey, rnext and
- rprev. In normal applications this should never happen.
-
-Thu Nov 20 14:01:21 1997 <monty@monty.pp.sci.fi>
-
-* Fixed range key bug when using compressed key where the first part wasn't
- compressed.
-* Converted everything to use prototypes.
-
-Mon Sep 29 13:16:27 1997 <monty@monty.pp.sci.fi>
-
-* Fixed problem with isamchk and compressed records files with record_reflength
- < 4 (Gave wrong key when using isamchk -rq).
-
-Fri Sep 26 16:06:37 1997 <monty@monty.pp.sci.fi>
-
-* Fixed bug in range calculation.
-
-Thu Aug 14 14:44:33 1997 <monty@monty.pp.sci.fi>
-
-* Removed a couple of unnecessary seeks from 'delete static record'
-
-Tue Jul 1 22:04:16 1997 <monty@monty.pp.sci.fi>
-
-* Added checking of 'wrong packed records' when using 'isamchk -e' or
- isamchk -ro.
-
-Fri Feb 7 22:22:28 1997 Michael Widenius <monty@bitch.sci.fi>
-
-* Fixed use of packed tables with threads (One static variable left)
-
-Thu Jan 23 09:05:22 1997 Michael Widenius <monty@bitch.sci.fi>
-
-* Changed create to detect keys > 127 and not pack them. Now one can
- define keys with a length of up to (nisam_block_size-18)/2
- by changeing N_MAX_KEY_LENGTH.
-
-Fri Jan 10 21:01:44 1997 Michael Widenius <monty@bitch.sci.fi>
-
-* added signed chars as key type.
-
-Fri Apr 26 14:31:05 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* create.c: All keyfile blocks are now IO_SIZE big (for better keycashing).
-
-Tue Mar 12 22:42:52 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* isamchk.c: Changed to print info if system table
-* write.c: Don't allow more than 1 record in system table.
-
-Fri Feb 2 16:40:32 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* isamchk.c; Check that delete-link-chain is ok before trying to delete with 'q'.
-
-Thu Jan 11 13:21:23 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* All same isam files now shares a structure to allow many opens off the same
- file
-
-Sat Nov 25 12:33:53 1995 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* All functions now used my_errno instead of errno
-
-Mon Oct 23 12:32:02 1995 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* isamchk.c: Don't print that database should be fixed on automatic rep.
-
-Sun Aug 27 20:13:56 1995 Michael Widenius <monty@bitch.analytikerna.se (Michael Widenius)>
-
-* _dynrec.c added flush_io_cash() if someone did a read when using
- WRITE CASHING.
-
-Thu Apr 20 01:41:24 1995 Michael Widenius (monty@bitch)
-
-* fixed errno when got error of 'key-not-found' when updateing or
- deleting record.
-
-Tue Jan 17 19:37:48 1995 Michael Widenius (monty@bitch)
-
-* isamchk can now unpack databases.
-* prolinted all files.
-
-Fri May 27 15:01:06 1994 Michael Widenius (monty@bitch)
-
-* Don't lock packed databases.
-
-Sat Apr 16 22:41:23 1994 Michael Widenius (monty@bitch)
-
-* Added new function read_rsame_with_pos.
-
-Wed Mar 30 15:52:19 1994 Michael Widenius (monty@bitch)
-
-* Added creation and recover date to indexfile and isamchk.
-
-Sat Mar 26 15:03:37 1994 Michael Widenius (monty@bitch)
-
-* change is_panic() to close all files on ha_panic(write) on systems
- (VMS) with can't open one file twice.
-
-Fri Feb 4 21:09:56 1994 Michael Widenius (monty@bitch)
-
-* READ_CASH on packed files now makes them mem-mapped if possibly
-
-Sat Sep 18 14:56:32 1993 Michael Widenius (monty at bitch)
-
-* changed _search to use pointer to buffer when reading keys.
-
-Mon Aug 16 19:45:29 1993 Michael Widenius (monty at bitch)
-
-* isamchk and packisam resolves symbolic links before file is used.
- This forces temp-files on same disk as orginal file and rename
- of temp-files dosen't destroy symbolic links.
-
-Mon May 31 18:26:08 1993 Michael Widenius (monty at bitch)
-
-* Added crc-check of records when packing for safe test if pack ok.
-
-Tue Mar 2 19:16:00 1993 Michael Widenius (monty@bitch)
-
-* Added logging of records with ni_log().
-
-Fri Jan 29 00:56:58 1993 Michael Widenius (monty@bitch)
-
-* Fixed bug in _read_rnd_static_record ; A lock was made for
- each record even if it was in cash.
-
-Sun Nov 15 12:51:36 1992 Michael Widenius (monty@bitch)
-
-* last change breaked _dynrec, when not compileing with dbug.
-
-Fri Nov 6 03:46:38 1992 Michael Widenius (monty@bitch)
-
-* Fixed bugg when using packed records and reclength < 8 byte.
-
-Wed Oct 28 22:23:32 1992 Michael Widenius (monty@bitch)
-
-* Changed _cash.c to use io_cash to allow use of aioread.
-
-Fri Oct 23 00:45:53 1992 Michael Widenius (monty@bitch)
-
-* Added MY_WAIT_IF_FULL to pack_isam.
-
-Sat Oct 17 14:51:15 1992 Michael Widenius (monty@bitch)
-
-* Added use of subset of keys (isamchk -k#)
-
-Mon Oct 5 21:53:18 1992 Michael Widenius (monty@bitch)
-
-* Remove reloc of database ; Gives only problems with isamchk.
-
-Mon Aug 17 03:17:09 1992 Michael Widenius (monty@bitch)
-
-* Changed isam to use io_cash instead of rec_cash
diff --git a/isam/Makefile.am b/isam/Makefile.am
deleted file mode 100644
index 335346d2423..00000000000
--- a/isam/Makefile.am
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include
-LDADD = @CLIENT_EXTRA_LDFLAGS@ libnisam.a ../mysys/libmysys.a \
- ../dbug/libdbug.a ../strings/libmystrings.a
-pkglib_LIBRARIES = libnisam.a
-bin_PROGRAMS = isamchk isamlog pack_isam
-isamchk_DEPENDENCIES= $(LIBRARIES)
-isamlog_DEPENDENCIES= $(LIBRARIES)
-pack_isam_DEPENDENCIES= $(LIBRARIES)
-noinst_PROGRAMS = test1 test2 test3
-noinst_HEADERS = isamdef.h
-test1_DEPENDENCIES= $(LIBRARIES)
-test2_DEPENDENCIES= $(LIBRARIES)
-test3_DEPENDENCIES= $(LIBRARIES)
-libnisam_a_SOURCES = open.c extra.c info.c rkey.c rnext.c \
- _search.c _page.c _key.c _locking.c \
- rrnd.c _cache.c _statrec.c _packrec.c \
- _dynrec.c update.c write.c delete.c \
- rprev.c rfirst.c rlast.c rsame.c rsamepos.c \
- panic.c close.c create.c range.c _dbug.c \
- log.c changed.c static.c
-isamchk_SOURCES = isamchk.c sort.c
-CLEANFILES = test?.IS? isam.log
-
-# Move to automake rules ?
-prolint:; plparse -b -u -hF1 "-width(0,0)" "-format=%f:%l:\s%t:%n\s%m" \
- "-elib(????)" "+elib(?3??)" my.lnt $(nisam_SOURCES)
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/isam/_cache.c b/isam/_cache.c
deleted file mode 100644
index bca9a699a85..00000000000
--- a/isam/_cache.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Functions for read record cacheing with nisam */
-/* Used instead of my_b_read() to allow for no-cacheed seeks */
-
-#include "isamdef.h"
-
-#define READING_NEXT 1
-#define READING_HEADER 2
-
- /* Copy block from cache if it`s in it. If re_read_if_possibly is */
- /* set read to cache (if after current file-position) else read to */
- /* buff */
-
-int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length,
- int flag)
-{
- uint read_length,in_buff_length;
- ulong offset;
- char *in_buff_pos;
-
- if (pos < info->pos_in_file)
- {
- read_length= (uint) min((ulong) length,(ulong) (info->pos_in_file-pos));
- info->seek_not_done=1;
- VOID(my_seek(info->file,pos,MY_SEEK_SET,MYF(0)));
- if (my_read(info->file,buff,read_length,MYF(MY_NABP)))
- return 1;
- if (!(length-=read_length))
- return 0;
- pos+=read_length;
- buff+=read_length;
- }
- if ((offset=pos - (ulong) info->pos_in_file) <
- (ulong) (info->read_end - info->request_pos))
- {
- in_buff_pos=info->request_pos+(uint) offset;
- in_buff_length= min(length,(uint) (info->read_end-in_buff_pos));
- memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
- if (!(length-=in_buff_length))
- return 0;
- pos+=in_buff_length;
- buff+=in_buff_length;
- }
- else
- in_buff_length=0;
- if (flag & READING_NEXT)
- {
- if (pos != ((info)->pos_in_file +
- (uint) ((info)->read_end - (info)->request_pos)))
- {
- info->pos_in_file=pos; /* Force start here */
- info->read_pos=info->read_end=info->request_pos; /* Everything used */
- info->seek_not_done=1;
- }
- else
- info->read_pos=info->read_end; /* All block used */
- if (!(*info->read_function)(info,buff,length))
- return 0;
- if (!(flag & READING_HEADER) || info->error == -1 ||
- (uint) info->error+in_buff_length < 3)
- return 1;
- if (BLOCK_INFO_HEADER_LENGTH < in_buff_length + (uint) info->error)
- bzero(buff+info->error,BLOCK_INFO_HEADER_LENGTH - in_buff_length -
- (uint) info->error);
- return 0;
- }
- info->seek_not_done=1;
- VOID(my_seek(info->file,pos,MY_SEEK_SET,MYF(0)));
- if ((read_length=my_read(info->file,buff,length,MYF(0))) == length)
- return 0;
- if (!(flag & READING_HEADER) || (int) read_length == -1 ||
- read_length+in_buff_length < 3)
- return 1;
- bzero(buff+read_length,BLOCK_INFO_HEADER_LENGTH - in_buff_length -
- read_length);
- return 0;
-} /* _nisam_read_cache */
diff --git a/isam/_dbug.c b/isam/_dbug.c
deleted file mode 100644
index 0a52dbbc916..00000000000
--- a/isam/_dbug.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Support rutiner with are using with dbug */
-
-#include "isamdef.h"
-
- /* Print a key in user understandable format */
-
-void _nisam_print_key(FILE *stream, register N_KEYSEG *keyseg, const uchar *key)
-{
- int flag;
- short int s_1;
- long int l_1;
- float f_1;
- double d_1;
- uchar *end;
-
- VOID(fputs("Key: \"",stream));
- flag=0;
- for (; keyseg->base.type ;keyseg++)
- {
- if (flag++)
- VOID(putc('-',stream));
- end= (uchar*) key+ keyseg->base.length;
- switch (keyseg->base.type) {
- case HA_KEYTYPE_BINARY:
- if (!(keyseg->base.flag & HA_SPACE_PACK) && keyseg->base.length == 1)
- { /* packed binary digit */
- VOID(fprintf(stream,"%d",(uint) *key++));
- break;
- }
- /* fall through */
- case HA_KEYTYPE_TEXT:
- case HA_KEYTYPE_NUM:
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- VOID(fprintf(stream,"%.*s",(int) *key,key+1));
- key+= (int) *key+1;
- }
- else
- {
- VOID(fprintf(stream,"%.*s",(int) keyseg->base.length,key));
- key=end;
- }
- break;
- case HA_KEYTYPE_INT8:
- VOID(fprintf(stream,"%d",(int) *((signed char*) key)));
- key=end;
- break;
- case HA_KEYTYPE_SHORT_INT:
- shortget(s_1,key);
- VOID(fprintf(stream,"%d",(int) s_1));
- key=end;
- break;
- case HA_KEYTYPE_USHORT_INT:
- {
- ushort u_1;
- ushortget(u_1,key);
- VOID(fprintf(stream,"%u",(uint) u_1));
- key=end;
- break;
- }
- case HA_KEYTYPE_LONG_INT:
- longget(l_1,key);
- VOID(fprintf(stream,"%ld",l_1));
- key=end;
- break;
- case HA_KEYTYPE_ULONG_INT:
- longget(l_1,key);
- VOID(fprintf(stream,"%lu",(ulong) l_1));
- key=end;
- break;
- case HA_KEYTYPE_INT24:
- VOID(fprintf(stream,"%ld",(long) sint3korr(key)));
- key=end;
- break;
- case HA_KEYTYPE_UINT24:
- VOID(fprintf(stream,"%ld",(long) uint3korr(key)));
- key=end;
- break;
- case HA_KEYTYPE_FLOAT:
- bmove((byte*) &f_1,(byte*) key,(int) sizeof(float));
- VOID(fprintf(stream,"%g",(double) f_1));
- key=end;
- break;
- case HA_KEYTYPE_DOUBLE:
- doubleget(d_1,key);
- VOID(fprintf(stream,"%g",d_1));
- key=end;
- break;
-#ifdef HAVE_LONG_LONG
- case HA_KEYTYPE_LONGLONG:
- {
- char buff[21];
- longlong tmp;
- longlongget(tmp,key);
- longlong2str(tmp,buff,-10);
- VOID(fprintf(stream,"%s",buff));
- key=end;
- break;
- }
- case HA_KEYTYPE_ULONGLONG:
- {
- char buff[21];
- longlong tmp;
- longlongget(tmp,key);
- longlong2str(tmp,buff,10);
- VOID(fprintf(stream,"%s",buff));
- key=end;
- break;
- }
-#endif
- default: break; /* This never happens */
- }
- }
- VOID(fputs("\n",stream));
- return;
-} /* print_key */
diff --git a/isam/_dynrec.c b/isam/_dynrec.c
deleted file mode 100644
index 25fe01e23f2..00000000000
--- a/isam/_dynrec.c
+++ /dev/null
@@ -1,1247 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
- /* Functions to handle space-packed-records and blobs */
-
-#include "isamdef.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};
-
-static int write_dynamic_record(N_INFO *info,const byte *record,
- uint reclength);
-static int _nisam_find_writepos(N_INFO *info,uint reclength,ulong *filepos,
- uint *length);
-static int update_dynamic_record(N_INFO *info,ulong filepos,byte *record,
- uint reclength);
-static int delete_dynamic_record(N_INFO *info,ulong filepos,
- uint second_read);
-static int _nisam_cmp_buffer(File file, const byte *buff, ulong filepos,
- uint length);
-
-#ifdef THREAD
-/* Play it safe; We have a small stack when using threads */
-#undef my_alloca
-#undef my_afree
-#define my_alloca(A) my_malloc((A),MYF(0))
-#define my_afree(A) my_free((A),MYF(0))
-#endif
-
- /* Interface function from N_INFO */
-
-int _nisam_write_dynamic_record(N_INFO *info, const byte *record)
-{
- uint reclength=_nisam_rec_pack(info,info->rec_buff,record);
- return (write_dynamic_record(info,info->rec_buff,reclength));
-}
-
-int _nisam_update_dynamic_record(N_INFO *info, ulong pos, const byte *record)
-{
- uint length=_nisam_rec_pack(info,info->rec_buff,record);
- return (update_dynamic_record(info,pos,info->rec_buff,length));
-}
-
-int _nisam_write_blob_record(N_INFO *info, const byte *record)
-{
- byte *rec_buff;
- int error;
- uint reclength,extra;
-
- extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (!(rec_buff=(byte*) my_alloca(info->s->base.pack_reclength+
- _calc_total_blob_length(info,record)+
- extra)))
- return(-1);
- reclength=_nisam_rec_pack(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
- record);
- error=write_dynamic_record(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
- reclength);
- my_afree(rec_buff);
- return(error);
-}
-
-
-int _nisam_update_blob_record(N_INFO *info, ulong pos, const byte *record)
-{
- byte *rec_buff;
- int error;
- uint reclength,extra;
-
- extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (!(rec_buff=(byte*) my_alloca(info->s->base.pack_reclength+
- _calc_total_blob_length(info,record)+
- extra)))
- return(-1);
- reclength=_nisam_rec_pack(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
- record);
- error=update_dynamic_record(info,pos,
- rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
- reclength);
- my_afree(rec_buff);
- return(error);
-}
-
-int _nisam_delete_dynamic_record(N_INFO *info)
-{
- return delete_dynamic_record(info,info->lastpos,0);
-}
-
-
- /* Write record to data-file */
-
-static int write_dynamic_record(N_INFO *info, const byte *record,
- uint reclength)
-{
- int flag;
- uint length;
- ulong filepos;
- DBUG_ENTER("write_dynamic_record");
-
- flag=0;
- while (reclength)
- {
- if (_nisam_find_writepos(info,reclength,&filepos,&length))
- goto err;
- if (_nisam_write_part_record(info,filepos,length,info->s->state.dellink,
- (byte**) &record,&reclength,&flag))
- goto err;
- }
-
- DBUG_RETURN(0);
- err:
- DBUG_RETURN(1);
-}
-
-
- /* Get a block for data ; The given data-area must be used !! */
-
-static int _nisam_find_writepos(N_INFO *info,
- uint reclength, /* record length */
- ulong *filepos, /* Return file pos */
- uint *length) /* length of block at filepos */
-{
- BLOCK_INFO block_info;
- DBUG_ENTER("_nisam_find_writepos");
-
- if (info->s->state.dellink != NI_POS_ERROR)
- {
- *filepos=info->s->state.dellink;
- block_info.second_read=0;
- info->rec_cache.seek_not_done=1;
-
- if (!(_nisam_get_block_info(&block_info,info->dfile,
- info->s->state.dellink) & BLOCK_DELETED))
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(-1);
- }
- info->s->state.dellink=block_info.next_filepos;
- info->s->state.del--;
- info->s->state.empty-= block_info.block_len;
- *length= block_info.block_len;
- }
- else
- {
- if (info->s->state.data_file_length > info->s->base.max_data_file_length)
- {
- my_errno=HA_ERR_RECORD_FILE_FULL;
- DBUG_RETURN(-1);
- }
- *filepos=info->s->state.data_file_length; /* New block last */
- if ((*length=reclength+3 + test(reclength > 65532)) <
- info->s->base.min_block_length)
- *length=info->s->base.min_block_length;
- info->s->state.data_file_length+= *length;
- info->s->state.splitt++;
- info->update|=HA_STATE_WRITE_AT_END;
- }
- DBUG_RETURN(0);
-} /* _nisam_find_writepos */
-
-
- /* Write a block to datafile */
-
-int _nisam_write_part_record(N_INFO *info,
- ulong filepos, /* points at empty block */
- uint length, /* length of block */
- ulong next_filepos, /* Next empty block */
- byte **record, /* pointer to record ptr */
- uint *reclength, /* length of *record */
- int *flag) /* *flag == 0 if header */
-{
- uint head_length,res_length,extra_length,long_block,del_length;
- byte *pos,*record_end;
- uchar temp[N_SPLITT_LENGTH+DYN_DELETE_BLOCK_HEADER];
- DBUG_ENTER("_nisam_write_part_record");
-
- res_length=extra_length=0;
- if (length > *reclength + N_SPLITT_LENGTH)
- { /* Splitt big block */
- res_length=length- *reclength - 3 - N_EXTEND_BLOCK_LENGTH;
- length-= res_length; /* Use this for first part */
- }
- long_block= (length < 65535L && *reclength < 65535L) ? 0 : 1;
- if (length-long_block == *reclength+3 || length == *reclength + 4)
- { /* Exact what we need */
- temp[0]=(uchar) (1+ *flag); /* 1, or 9 */
- if (long_block)
- {
- int3store(temp+1,*reclength);
- }
- else
- {
- int2store(temp+1,*reclength);
- }
- head_length=3+long_block;
- if (length-long_block == *reclength+4)
- {
- length--;
- temp[0]++; /* 2 or 10 */
- extra_length++; /* One empty */
- }
- }
- else if (length-long_block*2 < *reclength+5)
- { /* To short block */
- if (next_filepos == NI_POS_ERROR)
- next_filepos=info->s->state.dellink != NI_POS_ERROR ?
- info->s->state.dellink : info->s->state.data_file_length;
- if (*flag == 0) /* First block */
- {
- head_length=5+4+long_block*2;
- temp[0]=4;
- if (long_block)
- {
- int3store(temp+1,*reclength);
- int3store(temp+4,length-head_length);
- int4store((byte*) temp+7,next_filepos);
- }
- else
- {
- int2store(temp+1,*reclength);
- int2store(temp+3,length-head_length);
- int4store((byte*) temp+5,next_filepos);
- }
- }
- else
- {
- head_length=3+4+long_block;
- temp[0]=12;
- if (long_block)
- {
- int3store(temp+1,length-head_length);
- int4store((byte*) temp+4,next_filepos);
- }
- else
- {
- int2store(temp+1,length-head_length);
- int4store((byte*) temp+3,next_filepos);
- }
- }
- }
- else
- { /* Block with empty info last */
- head_length=5+long_block*2;
- temp[0]= (uchar) (3+ *flag); /* 3 or 11 */
- if (long_block)
- {
- int3store(temp+1,*reclength);
- int3store(temp+4,length-7);
- }
- else
- {
- int2store(temp+1,*reclength);
- int2store(temp+3,length-5);
- }
- extra_length= length- *reclength-head_length;
- length= *reclength+head_length; /* Write only what is needed */
- }
- temp[0]+=(uchar) (long_block*4);
- DBUG_DUMP("header",(byte*) temp,head_length);
-
- /* Make a long block for one write */
- record_end= *record+length-head_length;
- del_length=(res_length ? DYN_DELETE_BLOCK_HEADER : 0);
- bmove((byte*) (*record-head_length),(byte*) temp,head_length);
- memcpy(temp,record_end,(size_t) (extra_length+del_length));
- bzero((byte*) record_end,extra_length);
- if (res_length)
- {
- pos=record_end+extra_length;
- pos[0]= '\0';
- int3store(pos+1,res_length);
- int4store(pos+4,info->s->state.dellink);
- info->s->state.dellink= filepos+length+extra_length;
- info->s->state.del++;
- info->s->state.empty+=res_length;
- info->s->state.splitt++;
- }
- if (info->opt_flag & WRITE_CACHE_USED && info->update & HA_STATE_WRITE_AT_END)
- {
- if (my_b_write(&info->rec_cache,(byte*) *record-head_length,
- length+extra_length+del_length))
- goto err;
- }
- else
- {
- info->rec_cache.seek_not_done=1;
- if (my_pwrite(info->dfile,(byte*) *record-head_length,length+extra_length+
- del_length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- goto err;
- }
- memcpy(record_end,temp,(size_t) (extra_length+del_length));
- *record=record_end;
- *reclength-=(length-head_length);
- *flag=8;
-
- DBUG_RETURN(0);
-err:
- DBUG_PRINT("exit",("errno: %d",my_errno));
- DBUG_RETURN(1);
-} /*_nisam_write_part_record */
-
-
- /* update record from datafile */
-
-static int update_dynamic_record(N_INFO *info, ulong filepos, byte *record, uint reclength)
-{
- int flag;
- uint error,length;
- BLOCK_INFO block_info;
- DBUG_ENTER("update_dynamic_record");
-
- flag=block_info.second_read=0;
- while (reclength > 0)
- {
- if (filepos != info->s->state.dellink)
- {
- block_info.next_filepos= NI_POS_ERROR;
- if ((error=_nisam_get_block_info(&block_info,info->dfile,filepos))
- & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if (!(error & BLOCK_FATAL_ERROR))
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
- length=(uint) (block_info.filepos-filepos) + block_info.block_len;
- }
- else
- {
- if (_nisam_find_writepos(info,reclength,&filepos,&length))
- goto err;
- }
- if (_nisam_write_part_record(info,filepos,length,block_info.next_filepos,
- &record,&reclength,&flag))
- goto err;
- if ((filepos=block_info.next_filepos) == NI_POS_ERROR)
- filepos=info->s->state.dellink;
- }
-
- if (block_info.next_filepos != NI_POS_ERROR)
- if (delete_dynamic_record(info,block_info.next_filepos,1))
- goto err;
- DBUG_RETURN(0);
-err:
- DBUG_RETURN(1);
-}
-
- /* Delete datarecord from database */
- /* info->rec_cache.seek_not_done is updated in cmp_record */
-
-static int delete_dynamic_record(N_INFO *info, ulong filepos, uint second_read)
-{
- uint length,b_type;
- BLOCK_INFO block_info;
- DBUG_ENTER("delete_dynamic_record");
-
- block_info.second_read=second_read;
- do
- {
- if ((b_type=_nisam_get_block_info(&block_info,info->dfile,filepos))
- & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR) ||
- (length=(uint) (block_info.filepos-filepos) +block_info.block_len) <
- N_MIN_BLOCK_LENGTH)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(1);
- }
- block_info.header[0]=0;
- length=(uint) (block_info.filepos-filepos) +block_info.block_len;
- int3store(block_info.header+1,length);
- int4store(block_info.header+4,info->s->state.dellink);
- if (my_pwrite(info->dfile,(byte*) block_info.header,8,filepos,
- MYF(MY_NABP)))
- DBUG_RETURN(1);
- info->s->state.dellink = filepos;
- info->s->state.del++;
- info->s->state.empty+=length;
- filepos=block_info.next_filepos;
- } while (!(b_type & BLOCK_LAST));
- DBUG_RETURN(0);
-}
-
-
- /* Pack a record. Return new reclength */
-
-uint _nisam_rec_pack(N_INFO *info, register byte *to, register const byte *from)
-{
- uint length,new_length,flag,bit,i;
- char *pos,*end,*startpos,*packpos;
- enum en_fieldtype type;
- reg3 N_RECINFO *rec;
- N_BLOB *blob;
- DBUG_ENTER("_nisam_rec_pack");
-
- flag=0 ; bit=1;
- startpos=packpos=to; to+= info->s->base.pack_bits; blob=info->blobs;
- rec=info->s->rec;
-
- for (i=info->s->base.fields ; i-- > 0; from+= (rec++)->base.length)
- {
- length=(uint) rec->base.length;
- if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
- {
- if (type == FIELD_BLOB)
- {
- if (!blob->length)
- flag|=bit;
- else
- {
- char *temp_pos;
- memcpy((byte*) to,from,(size_t) length);
- memcpy_fixed(&temp_pos,from+length,sizeof(char*));
- memcpy(to+length,temp_pos,(size_t) blob->length);
- to+=length+blob->length;
- }
- blob++;
- from+=sizeof(char*); /* Skip blob-pointer */
- }
- else if (type == FIELD_SKIP_ZERO)
- {
- if (memcmp((byte*) from,zero_string,length) == 0)
- flag|=bit;
- else
- {
- memcpy((byte*) to,from,(size_t) length); to+=length;
- }
- }
- else if (type == FIELD_SKIP_ENDSPACE ||
- type == FIELD_SKIP_PRESPACE)
- {
- pos= (byte*) from; end= (byte*) from + length;
- if (type == FIELD_SKIP_ENDSPACE)
- { /* Pack trailing spaces */
- while (end > from && *(end-1) == ' ')
- end--;
- }
- else
- { /* Pack pref-spaces */
- while (pos < end && *pos == ' ')
- pos++;
- }
- new_length=(uint) (end-pos);
- if (new_length +1 + test(rec->base.length > 255 && new_length > 127)
- < length)
- {
- if (rec->base.length > 255 && new_length > 127)
- {
- to[0]=(char) ((new_length & 127)+128);
- to[1]=(char) (new_length >> 7);
- to+=2;
- }
- else
- *to++= (char) new_length;
- memcpy((byte*) to,pos,(size_t) new_length); to+=new_length;
- flag|=bit;
- }
- else
- {
- memcpy(to,from,(size_t) length); to+=length;
- }
- }
- else if (type == FIELD_ZERO)
- continue; /* Don't store this */
- else
- {
- memcpy(to,from,(size_t) length); to+=length;
- continue; /* Normal field */
- }
- if ((bit= bit << 1) >= 256)
- {
- *packpos++ = (char) (uchar) flag;
- bit=1; flag=0;
- }
- }
- else
- {
- memcpy(to,from,(size_t) length); to+=length;
- }
- }
- if (bit != 1)
- *packpos= (char) (uchar) flag;
- DBUG_PRINT("exit",("packed length: %d",(int) (to-startpos)));
- DBUG_RETURN((uint) (to-startpos));
-} /* _nisam_rec_pack */
-
-
-
-/*
-** Check if a record was correctly packed. Used only by isamchk
-** Returns 0 if record is ok.
-*/
-
-my_bool _nisam_rec_check(N_INFO *info,const char *from)
-{
- uint length,new_length,flag,bit,i;
- char *pos,*end,*packpos,*to;
- enum en_fieldtype type;
- reg3 N_RECINFO *rec;
- DBUG_ENTER("_nisam_rec_check");
-
- packpos=info->rec_buff; to= info->rec_buff+info->s->base.pack_bits;
- rec=info->s->rec;
- flag= *packpos; bit=1;
-
- for (i=info->s->base.fields ; i-- > 0; from+= (rec++)->base.length)
- {
- length=(uint) rec->base.length;
- if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
- {
- if (type == FIELD_BLOB)
- {
- uint blob_length= _calc_blob_length(length,from);
- if (!blob_length && !(flag & bit))
- goto err;
- if (blob_length)
- to+=length+ blob_length;
- from+=sizeof(char*);
- }
- else if (type == FIELD_SKIP_ZERO)
- {
- if (memcmp((byte*) from,zero_string,length) == 0)
- {
- if (!(flag & bit))
- goto err;
- }
- else
- to+=length;
- }
- else if (type == FIELD_SKIP_ENDSPACE ||
- type == FIELD_SKIP_PRESPACE)
- {
- pos= (byte*) from; end= (byte*) from + length;
- if (type == FIELD_SKIP_ENDSPACE)
- { /* Pack trailing spaces */
- while (end > from && *(end-1) == ' ')
- end--;
- }
- else
- { /* Pack pre-spaces */
- while (pos < end && *pos == ' ')
- pos++;
- }
- new_length=(uint) (end-pos);
- if (new_length +1 + test(rec->base.length > 255 && new_length > 127)
- < length)
- {
- if (!(flag & bit))
- goto err;
- if (rec->base.length > 255 && new_length > 127)
- {
- if (to[0] != (char) ((new_length & 127)+128) ||
- to[1] != (char) (new_length >> 7))
- goto err;
- to+=2;
- }
- else if (*to++ != (char) new_length)
- goto err;
- to+=new_length;
- }
- else
- to+=length;
- }
- else
- {
- if (type != FIELD_ZERO)
- to+=length; /* Not packed field */
- continue;
- }
- if ((bit= bit << 1) >= 256)
- {
- flag= *++packpos;
- bit=1;
- }
- }
- else
- {
- to+=length;
- }
- }
- if (bit != 1)
- *packpos= (char) (uchar) flag;
- if (info->packed_length == (uint) (to - info->rec_buff) &&
- (bit == 1 || !(flag & ~(bit - 1))))
- DBUG_RETURN(0);
-
- err:
- DBUG_RETURN(1);
-}
-
-
-
- /* Unpacks a record */
- /* Returns -1 and my_errno =HA_ERR_RECORD_DELETED if reclength isn't */
- /* right. Returns reclength (>0) if ok */
-
-uint _nisam_rec_unpack(register N_INFO *info, register byte *to, byte *from,
- uint found_length)
-{
- uint flag,bit,length,rec_length,min_pack_length;
- enum en_fieldtype type;
- byte *from_end,*to_end,*packpos;
- reg3 N_RECINFO *rec,*end_field;
- DBUG_ENTER("_nisam_rec_unpack");
-
- to_end=to + info->s->base.reclength;
- from_end=from+found_length;
- flag= (uchar) *from; bit=1; packpos=from;
- if (found_length < info->s->base.min_pack_length)
- goto err;
- from+= info->s->base.pack_bits;
- min_pack_length=info->s->base.min_pack_length - info->s->base.pack_bits;
-
- for (rec=info->s->rec , end_field=rec+info->s->base.fields ;
- rec < end_field ; to+= rec_length, rec++)
- {
- rec_length=rec->base.length;
- if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
- {
- if (type == FIELD_ZERO)
- continue; /* Skip this */
- if (flag & bit)
- {
- if (type == FIELD_BLOB)
- {
- bzero((byte*) to,rec_length+sizeof(char*));
- to+=sizeof(char*);
- }
- else if (type == FIELD_SKIP_ZERO)
- bzero((byte*) to,rec_length);
- else if (type == FIELD_SKIP_ENDSPACE ||
- type == FIELD_SKIP_PRESPACE)
- {
- if (rec->base.length > 255 && *from & 128)
- {
- if (from + 1 >= from_end)
- goto err;
- length= (*from & 127)+ ((uint) (uchar) *(from+1) << 7); from+=2;
- }
- else
- {
- if (from == from_end)
- goto err;
- length= (uchar) *from++;
- }
- min_pack_length--;
- if (length >= rec_length ||
- min_pack_length + length > (uint) (from_end - from))
- goto err;
- if (type == FIELD_SKIP_ENDSPACE)
- {
- memcpy(to,(byte*) from,(size_t) length);
- bfill((byte*) to+length,rec_length-length,' ');
- }
- else
- {
- bfill((byte*) to,rec_length-length,' ');
- memcpy(to+rec_length-length,(byte*) from,(size_t) length);
- }
- from+=length;
- }
- }
- else if (type == FIELD_BLOB)
- {
- ulong blob_length=_calc_blob_length(rec_length,from);
- if ((ulong) (from_end-from) - rec_length < blob_length ||
- min_pack_length > (uint) (from_end -(from+rec_length+blob_length)))
- goto err;
- memcpy((byte*) to,(byte*) from,(size_t) rec_length);
- from+=rec_length;
- /* memcpy crasches alpha egcs 1.1.2 */
- bmove((byte*) to+rec_length,(byte*) &from,sizeof(char*));
- from+=blob_length;
- to+=sizeof(char*);
- }
- else
- {
- if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
- min_pack_length--;
- if (min_pack_length + rec_length > (uint) (from_end - from))
- goto err;
- memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
- }
- if ((bit= bit << 1) >= 256)
- {
- flag= (uchar) *++packpos; bit=1;
- }
- }
- else
- {
- if (min_pack_length > (uint) (from_end - from))
- goto err;
- min_pack_length-=rec_length;
- memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
- }
- }
- if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1))))
- DBUG_RETURN((info->packed_length=found_length));
- err:
- my_errno=HA_ERR_RECORD_DELETED;
- DBUG_PRINT("error",("to_end: %lx -> %lx from_end: %lx -> %lx",
- to,to_end,from,from_end));
- DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length);
- DBUG_RETURN(MY_FILE_ERROR);
-} /* _nisam_rec_unpack */
-
-
- /* Calc length of blob. Update info in blobs->length */
-
-uint _calc_total_blob_length(N_INFO *info, const byte *record)
-{
- uint i,length;
- N_BLOB *blob;
-
- for (i=length=0, blob= info->blobs; i++ < info->s->base.blobs ; blob++)
- {
- blob->length=_calc_blob_length(blob->pack_length,record + blob->offset);
- length+=blob->length;
- }
- return length;
-}
-
-
-uint _calc_blob_length(uint length, const byte *pos)
-{
- switch (length) {
- case 1:
- return (uint) (uchar) *pos;
- case 2:
- {
- short j; shortget(j,pos);
- return (uint) (unsigned short) j;
- }
-#ifdef MSDOS
- break; /* skip microsoft warning */
-#endif
- case 3:
- return uint3korr(pos);
- case 4:
- {
- long j; longget(j,pos);
- return (uint) j;
- }
-#ifdef MSDOS
- break;
-#endif
- default:
- break;
- }
- return 0; /* Impossible */
-}
-
- /* Read record from datafile */
- /* Returns 0 if ok, -1 if error */
-
-int _nisam_read_dynamic_record(N_INFO *info, ulong filepos, byte *buf)
-{
- int flag;
- uint b_type,left_length;
- byte *to;
- BLOCK_INFO block_info;
- File file;
- DBUG_ENTER("ni_read_dynamic_record");
-
- if (filepos != NI_POS_ERROR)
- {
- LINT_INIT(to);
- LINT_INIT(left_length);
- file=info->dfile;
- block_info.next_filepos=filepos; /* for easyer loop */
- flag=block_info.second_read=0;
- do
- {
- if (info->opt_flag & WRITE_CACHE_USED &&
- info->rec_cache.pos_in_file <= block_info.next_filepos &&
- flush_io_cache(&info->rec_cache))
- goto err;
- info->rec_cache.seek_not_done=1;
- if ((b_type=_nisam_get_block_info(&block_info,file,
- block_info.next_filepos))
- & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
- my_errno=HA_ERR_RECORD_DELETED;
- goto err;
- }
- if (flag == 0) /* First block */
- {
- flag=1;
- if (block_info.rec_len > (uint) info->s->base.max_pack_length)
- goto panic;
- if (info->s->base.blobs)
- {
- if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
- goto err;
- }
- else
- to= info->rec_buff;
- left_length=block_info.rec_len;
- }
- if (left_length < block_info.data_len || ! block_info.data_len)
- goto panic; /* Wrong linked record */
- if (my_pread(file,(byte*) to,block_info.data_len,block_info.filepos,
- MYF(MY_NABP)))
- goto panic;
- left_length-=block_info.data_len;
- to+=block_info.data_len;
- } while (left_length);
-
- info->update|= HA_STATE_AKTIV; /* We have a aktive record */
- VOID(_nisam_writeinfo(info,0));
- DBUG_RETURN(_nisam_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
- MY_FILE_ERROR ? 0 : -1);
- }
- VOID(_nisam_writeinfo(info,0));
- DBUG_RETURN(-1); /* Wrong data to read */
-
-panic:
- my_errno=HA_ERR_WRONG_IN_RECORD;
-err:
- VOID(_nisam_writeinfo(info,0));
- DBUG_RETURN(-1);
-}
-
-
-byte *fix_rec_buff_for_blob(N_INFO *info, uint length)
-{
- uint extra;
- if (! info->rec_buff || length > info->alloced_rec_buff_length)
- {
- byte *newptr;
- extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (!(newptr=(byte*) my_realloc((gptr) info->rec_alloc,length+extra,
- MYF(MY_ALLOW_ZERO_PTR))))
- return newptr;
- info->rec_alloc=newptr;
- info->rec_buff=newptr+ALIGN_SIZE(DYN_DELETE_BLOCK_HEADER);
- info->alloced_rec_buff_length=length;
- }
- return info->rec_buff;
-}
-
-
- /* Compare of record one disk with packed record in memory */
-
-int _nisam_cmp_dynamic_record(register N_INFO *info, register const byte *record)
-{
- uint flag,reclength,b_type;
- ulong filepos;
- byte *buffer;
- BLOCK_INFO block_info;
- DBUG_ENTER("_nisam_cmp_dynamic_record");
-
- /* We are going to do changes; dont let anybody disturb */
- dont_break(); /* Dont allow SIGHUP or SIGINT */
-
- if (info->opt_flag & WRITE_CACHE_USED)
- {
- info->update&= ~HA_STATE_WRITE_AT_END;
- if (flush_io_cache(&info->rec_cache))
- DBUG_RETURN(-1);
- }
- info->rec_cache.seek_not_done=1;
-
- /* If nobody have touched the database we don't have to test rec */
-
- buffer=info->rec_buff;
- if ((info->opt_flag & READ_CHECK_USED))
- { /* If check isn't disabled */
- if (info->s->base.blobs)
- {
- if (!(buffer=(byte*) my_alloca(info->s->base.pack_reclength+
- _calc_total_blob_length(info,record))))
- DBUG_RETURN(-1);
- }
- reclength=_nisam_rec_pack(info,buffer,record);
- record= buffer;
-
- filepos=info->lastpos;
- flag=block_info.second_read=0;
- block_info.next_filepos=filepos;
- while (reclength > 0)
- {
- if ((b_type=_nisam_get_block_info(&block_info,info->dfile,
- block_info.next_filepos))
- & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
- my_errno=HA_ERR_RECORD_CHANGED;
- goto err;
- }
- if (flag == 0) /* First block */
- {
- flag=1;
- if (reclength != block_info.rec_len)
- {
- my_errno=HA_ERR_RECORD_CHANGED;
- goto err;
- }
- } else if (reclength < block_info.data_len)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
- reclength-=block_info.data_len;
- if (_nisam_cmp_buffer(info->dfile,record,block_info.filepos,
- block_info.data_len))
- {
- my_errno=HA_ERR_RECORD_CHANGED;
- goto err;
- }
- flag=1;
- record+=block_info.data_len;
- }
- }
- my_errno=0;
- err:
- if (buffer != info->rec_buff)
- my_afree((gptr) buffer);
- DBUG_RETURN(my_errno);
-}
-
-
- /* Compare file to buffert */
-
-static int _nisam_cmp_buffer(File file, const byte *buff, ulong filepos, uint length)
-{
- uint next_length;
- char temp_buff[IO_SIZE*2];
- DBUG_ENTER("_nisam_cmp_buffer");
-
- VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
- next_length= IO_SIZE*2 - (uint) (filepos & (IO_SIZE-1));
-
- while (length > IO_SIZE*2)
- {
- if (my_read(file,temp_buff,next_length,MYF(MY_NABP)))
- goto err;
- if (memcmp((byte*) buff,temp_buff,next_length))
- DBUG_RETURN(1);
- buff+=next_length;
- length-= next_length;
- next_length=IO_SIZE*2;
- }
- if (my_read(file,temp_buff,length,MYF(MY_NABP)))
- goto err;
- DBUG_RETURN(memcmp((byte*) buff,temp_buff,length));
-err:
- DBUG_RETURN(1);
-}
-
-
-int _nisam_read_rnd_dynamic_record(N_INFO *info, byte *buf, register ulong filepos, int skipp_deleted_blocks)
-{
- int flag,info_read,fatal_errcode;
- uint left_len,b_type;
- byte *to;
- BLOCK_INFO block_info;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_read_rnd_dynamic_record");
-
- info_read=0;
- fatal_errcode= -1;
- LINT_INIT(to);
-
-#ifndef NO_LOCKING
- if (info->lock_type == F_UNLCK)
- {
-#ifndef UNSAFE_LOCKING
- if (share->r_locks == 0 && share->w_locks == 0)
- {
- if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
- DBUG_RETURN(fatal_errcode);
- }
-#else
- info->tmp_lock_type=F_RDLCK;
-#endif
- }
- else
- info_read=1; /* memory-keyinfoblock is ok */
-#endif /* !NO_LOCKING */
-
- flag=block_info.second_read=0;
- left_len=1;
- do
- {
- if (filepos >= share->state.data_file_length)
- {
-#ifndef NO_LOCKING
- if (!info_read)
- { /* Check if changed */
- info_read=1;
- info->rec_cache.seek_not_done=1;
- if (my_pread(share->kfile,(char*) &share->state.header,
- share->state_length, 0L,MYF(MY_NABP)))
- goto err;
- }
- if (filepos >= share->state.data_file_length)
-#endif
- {
- my_errno= HA_ERR_END_OF_FILE;
- goto err;
- }
- }
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (_nisam_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
- sizeof(block_info.header),
- test(!flag && skipp_deleted_blocks) | 2))
- goto err;
- b_type=_nisam_get_block_info(&block_info,-1,filepos);
- }
- else
- {
- if (info->opt_flag & WRITE_CACHE_USED &&
- info->rec_cache.pos_in_file <= filepos &&
- flush_io_cache(&info->rec_cache))
- DBUG_RETURN(-1);
- info->rec_cache.seek_not_done=1;
- b_type=_nisam_get_block_info(&block_info,info->dfile,filepos);
- }
-
- if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
- && skipp_deleted_blocks)
- {
- filepos=block_info.filepos+block_info.block_len;
- block_info.second_read=0;
- continue; /* Search after next_record */
- }
- if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
- {
- my_errno=HA_ERR_RECORD_DELETED;
- info->lastpos=block_info.filepos;
- info->nextpos=block_info.filepos+block_info.block_len;
- fatal_errcode=1;
- }
- goto err;
- }
- if (flag == 0) /* First block */
- {
- if (block_info.rec_len > (uint) share->base.max_pack_length)
- goto panic;
- info->lastpos=filepos;
- if (share->base.blobs)
- {
- if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
- goto err;
- }
- else
- to= info->rec_buff;
- left_len=block_info.rec_len;
- }
- if (left_len < block_info.data_len)
- goto panic; /* Wrong linked record */
-
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (_nisam_read_cache(&info->rec_cache,(byte*) to,block_info.filepos,
- block_info.data_len,
- test(!flag && skipp_deleted_blocks)))
- goto err;
- }
- else
- {
- VOID(my_seek(info->dfile,block_info.filepos,MY_SEEK_SET,MYF(0)));
- if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP)))
- goto err;
- }
- if (flag++ == 0)
- {
- info->nextpos=block_info.filepos+block_info.block_len;
- skipp_deleted_blocks=0;
- }
- left_len-=block_info.data_len;
- to+=block_info.data_len;
- filepos=block_info.next_filepos;
- } while (left_len);
-
- info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
- VOID(_nisam_writeinfo(info,0));
- if (_nisam_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
- MY_FILE_ERROR)
- DBUG_RETURN(0);
- DBUG_RETURN(fatal_errcode); /* Wrong record */
-
-panic:
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Something is fatal wrong */
-err:
- VOID(_nisam_writeinfo(info,0));
- DBUG_RETURN(fatal_errcode);
-}
-
-
- /* Read and process header from a dynamic-record-file */
-
-uint _nisam_get_block_info(BLOCK_INFO *info, File file, ulong filepos)
-{
- uint return_val=0,length;
- uchar *header=info->header;
-
- if (file >= 0)
- {
- VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
- if ((length=my_read(file,(char*) header,BLOCK_INFO_HEADER_LENGTH,MYF(0)))
- == MY_FILE_ERROR)
- return BLOCK_FATAL_ERROR;
- if (length != BLOCK_INFO_HEADER_LENGTH)
- { /* Test if short block */
- if (length < 3)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */
- return BLOCK_FATAL_ERROR;
- }
- bzero((byte*) header+length,BLOCK_INFO_HEADER_LENGTH-length);
- }
- }
- DBUG_DUMP("header",(byte*) header,BLOCK_INFO_HEADER_LENGTH);
- if (info->second_read)
- {
- if (info->header[0] <= 8)
- return_val=BLOCK_SYNC_ERROR;
- }
- else
- {
- if (info->header[0] > 8)
- return_val=BLOCK_SYNC_ERROR;
- }
- info->next_filepos= (ulong) NI_POS_ERROR; /* Dummy ifall no next block */
-
- switch (info->header[0]) {
- case 0:
- if ((info->block_len=(uint) uint3korr(header+1)) < N_MIN_BLOCK_LENGTH)
- return BLOCK_FATAL_ERROR;
- info->filepos=filepos;
- info->next_filepos=uint4korr(header+4);
- if (info->next_filepos == (uint32) ~0) /* Fix for 64 bit long */
- info->next_filepos=NI_POS_ERROR;
- return return_val | BLOCK_DELETED; /* Deleted block */
- case 1:
- info->rec_len=info->data_len=info->block_len=uint2korr(header+1);
- info->filepos=filepos+3;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 2:
- info->block_len=(info->rec_len=info->data_len=uint2korr(header+1))+1;
- info->filepos=filepos+3;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 3:
- info->rec_len=info->data_len=uint2korr(header+1);
- info->block_len=uint2korr(header+3);
- info->filepos=filepos+5;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 4:
- info->rec_len=uint2korr(header+1);
- info->block_len=info->data_len=uint2korr(header+3);
- info->next_filepos=uint4korr(header+5);
- info->second_read=1;
- info->filepos=filepos+9;
- return return_val | BLOCK_FIRST;
-#if defined(_MSC_VER) || !defined(__WIN__)
- case 5:
- info->rec_len=info->data_len=info->block_len=uint3korr(header+1);
- info->filepos=filepos+4;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 6:
- info->block_len=(info->rec_len=info->data_len=uint3korr(header+1))+1;
- info->filepos=filepos+4;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 7:
- info->rec_len=info->data_len=uint3korr(header+1);
- info->block_len=uint3korr(header+4);
- info->filepos=filepos+7;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 8:
- info->rec_len=uint3korr(header+1);
- info->block_len=info->data_len=uint3korr(header+4);
- info->next_filepos=uint4korr(header+7);
- info->second_read=1;
- info->filepos=filepos+11;
- return return_val | BLOCK_FIRST;
-#endif
- case 9:
- info->data_len=info->block_len=uint2korr(header+1);
- info->filepos=filepos+3;
- return return_val | BLOCK_LAST;
- case 10:
- info->block_len=(info->data_len=uint2korr(header+1))+1;
- info->filepos=filepos+3;
- return return_val | BLOCK_LAST;
- case 11:
- info->data_len=uint2korr(header+1);
- info->block_len=uint2korr(header+3);
- info->filepos=filepos+5;
- return return_val | BLOCK_LAST;
- case 12:
- info->data_len=info->block_len=uint2korr(header+1);
- info->next_filepos=uint4korr(header+3);
- info->second_read=1;
- info->filepos=filepos+7;
- return return_val;
-#if defined(_MSC_VER) || !defined(__WIN__)
- case 13:
- info->data_len=info->block_len=uint3korr(header+1);
- info->filepos=filepos+4;
- return return_val | BLOCK_LAST;
- case 14:
- info->block_len=(info->data_len=uint3korr(header+1))+1;
- info->filepos=filepos+4;
- return return_val | BLOCK_LAST;
- case 15:
- info->data_len=uint3korr(header+1);
- info->block_len=uint3korr(header+4);
- info->filepos=filepos+7;
- return return_val | BLOCK_LAST;
- case 16:
- info->data_len=info->block_len=uint3korr(header+1);
- info->next_filepos=uint4korr(header+4);
- info->second_read=1;
- info->filepos=filepos+8;
- return return_val;
-#endif
- default:
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */
- return BLOCK_ERROR;
- }
-}
diff --git a/isam/_key.c b/isam/_key.c
deleted file mode 100644
index 65d6885869e..00000000000
--- a/isam/_key.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Functions to handle keys */
-
-#include "isamdef.h"
-#include "m_ctype.h"
-
-static void _nisam_put_key_in_record(N_INFO *info,uint keynr,byte *record);
-
- /* Make a intern key from a record */
- /* If ascii key convert according to sortorder */
- /* Ret: Length of key */
-
-uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *record, ulong filepos)
-{
- uint length;
- byte *pos,*end;
- uchar *start;
- reg1 N_KEYSEG *keyseg;
- enum ha_base_keytype type;
- DBUG_ENTER("_nisam_make_key");
-
- start=key;
- for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->base.type ;keyseg++)
- {
- type=(enum ha_base_keytype) keyseg->base.type;
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- pos= (byte*) record+keyseg->base.start; end=pos+keyseg->base.length;
- if (type != HA_KEYTYPE_NUM)
- {
- while (end > pos && end[-1] == ' ')
- end--;
- }
- else
- {
- while (pos < end && pos[0] == ' ')
- pos++;
- }
- *key++= (uchar) (length=(uint) (end-pos));
- memcpy((byte*) key,(byte*) pos,(size_t) length);
- if (!use_strnxfrm(default_charset_info))
- {
- if (type == HA_KEYTYPE_TEXT)
- my_strnxfrm(default_charset_info,(uchar*) key, length,
- (uchar*) key, length);
- }
- key+=length;
- }
- else
- {
- memcpy((byte*) key,(byte*) record+keyseg->base.start,
- (size_t) keyseg->base.length);
- if (!use_strnxfrm(default_charset_info))
- {
- if (type == HA_KEYTYPE_TEXT)
- my_strnxfrm(default_charset_info,(uchar*) key,
- (uint) keyseg->base.length,
- (uchar*) key,
- (uint) keyseg->base.length);
- }
-#ifdef NAN_TEST
- else if (type == HA_KEYTYPE_FLOAT)
- {
- float nr;
- bmove((byte*) &nr,(byte*) key,sizeof(float));
- if (nr == (float) FLT_MAX)
- {
- nr= (float) FLT_MAX;
- bmove((byte*) key,(byte*) &nr,sizeof(float));
- }
- }
- else if (type == HA_KEYTYPE_DOUBLE)
- {
- double nr;
- bmove((byte*) &nr,(byte*) key,sizeof(double));
- if (nr == DBL_MAX)
- {
- nr=DBL_MAX;
- bmove((byte*) key,(byte*) &nr,sizeof(double));
- }
- }
-#endif
- key+= keyseg->base.length;
- }
- }
- _nisam_dpointer(info,key,filepos);
- DBUG_PRINT("exit",("keynr: %d",keynr));
- DBUG_DUMP("key",(byte*) start,(uint) (key-start)+keyseg->base.length);
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start););
- DBUG_RETURN((uint) (key-start)); /* Return keylength */
-} /* _nisam_make_key */
-
-
- /* Pack a key to intern format from given format (c_rkey) */
- /* if key_length is set returns new length of key */
-
-uint _nisam_pack_key(register N_INFO *info, uint keynr, uchar *key, uchar *old, uint key_length)
-
-
-
- /* Length of used key */
-{
- int k_length;
- uint length;
- uchar *pos,*end;
- reg1 N_KEYSEG *keyseg;
- enum ha_base_keytype type;
- DBUG_ENTER("_nisam_pack_key");
-
- if ((k_length=(int) key_length) <= 0)
- k_length=N_MAX_KEY_BUFF;
-
- for (keyseg=info->s->keyinfo[keynr].seg ;
- keyseg->base.type && k_length >0;
- k_length-=keyseg->base.length, old+=keyseg->base.length, keyseg++)
- {
- length=min((uint) keyseg->base.length,(uint) k_length);
- type=(enum ha_base_keytype) keyseg->base.type;
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- pos=old; end=pos+length;
- if (type != HA_KEYTYPE_NUM)
- {
- while (end > pos && end[-1] == ' ')
- end--;
- }
- else
- {
- while (pos < end && pos[0] == ' ')
- pos++;
- }
- *key++ = (uchar) (length=(uint) (end-pos));
- memcpy((byte*) key,pos,(size_t) length);
- }
- else
- memcpy((byte*) key,old,(size_t) length);
- if (!use_strnxfrm(default_charset_info))
- {
- if (type == HA_KEYTYPE_TEXT)
- my_strnxfrm(default_charset_info,(uchar*) key,length,
- (uchar*) key,length);
- }
- key+= length;
- }
- if (!keyseg->base.type)
- {
- if (k_length >= 0) /* Hole key */
- key_length=0;
- }
- else
- { /* Part-key ; fill with null */
- length= (uint) -k_length; /* unused part of last key */
- do
- {
- length+= (keyseg->base.flag & HA_SPACE_PACK) ? 1 :
- keyseg->base.length;
- keyseg++;
- } while (keyseg->base.type);
- bzero((byte*) key,length);
- }
- DBUG_RETURN(key_length); /* Return part-keylength */
-} /* _nisam_pack_key */
-
-
- /* Put a key in record */
- /* Used when only-keyread is wanted */
-
-static void _nisam_put_key_in_record(register N_INFO *info, uint keynr, byte *record)
-{
- uint length;
- reg2 byte *key;
- byte *pos;
- reg1 N_KEYSEG *keyseg;
- DBUG_ENTER("_nisam_put_key_in_record");
-
- key=(byte*) info->lastkey;
- for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->base.type ;keyseg++)
- {
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- length= (uint) (uchar) *key++;
- pos= record+keyseg->base.start;
- if (keyseg->base.type != (int) HA_KEYTYPE_NUM)
- {
- memcpy(pos,key,(size_t) length);
- bfill(pos+length,keyseg->base.length-length,' ');
- }
- else
- {
- bfill(pos,keyseg->base.length-length,' ');
- memcpy(pos+keyseg->base.length-length,key,(size_t) length);
- }
- key+=length;
- }
- else
- {
- memcpy(record+keyseg->base.start,(byte*) key,
- (size_t) keyseg->base.length);
- key+= keyseg->base.length;
- }
- }
- DBUG_VOID_RETURN;
-} /* _nisam_put_key_in_record */
-
-
- /* Here when key reads are used */
-
-int _nisam_read_key_record(N_INFO *info, ulong filepos, byte *buf)
-{
- VOID(_nisam_writeinfo(info,0));
- if (filepos != NI_POS_ERROR)
- {
- if (info->lastinx >= 0)
- { /* Read only key */
- _nisam_put_key_in_record(info,(uint) info->lastinx,buf);
- info->update|= HA_STATE_AKTIV; /* We should find a record */
- return 0;
- }
- my_errno=HA_ERR_WRONG_INDEX;
- return(-1);
- }
- return(-1); /* Wrong data to read */
-}
diff --git a/isam/_locking.c b/isam/_locking.c
deleted file mode 100644
index e19804549e5..00000000000
--- a/isam/_locking.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- locking of isam-tables.
- reads info from a isam-table. Must be first request before doing any furter
- calls to any isamfunktion. Is used to allow many process use the same
- isamdatabase.
- */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
-
-int nisam_lock_database(N_INFO *info, int lock_type)
-{
- int error;
- uint count;
- ISAM_SHARE *share;
- uint flag;
- DBUG_ENTER("nisam_lock_database");
-
- flag=error=0;
-#ifndef NO_LOCKING
- share=info->s;
- if (share->base.options & HA_OPTION_READ_ONLY_DATA ||
- info->lock_type == lock_type)
- DBUG_RETURN(0);
- pthread_mutex_lock(&share->intern_lock);
- switch (lock_type) {
- case F_UNLCK:
- if (info->lock_type == F_RDLCK)
- count= --share->r_locks;
- else
- count= --share->w_locks;
- if (info->lock_type == F_WRLCK && !share->w_locks &&
- flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_KEEP))
- error=my_errno;
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- if (end_io_cache(&info->rec_cache))
- error=my_errno;
-
- if (!count)
- {
- if (share->changed && !share->w_locks)
- {
- share->state.process= share->last_process=share->this_process;
- share->state.loop= info->last_loop= ++info->this_loop;
- share->state.uniq= info->last_uniq= info->this_uniq;
- if (my_pwrite(share->kfile,(char*) &share->state.header,
- share->state_length,0L,MYF(MY_NABP)))
- error=my_errno;
- share->changed=0;
-#ifdef __WIN__
- if (nisam_flush)
- {
- _commit(share->kfile);
- _commit(info->dfile);
- }
- else
- share->not_flushed=1;
-#endif
- }
- if (share->r_locks)
- { /* Only read locks left */
- flag=1;
- if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
- MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
- error=my_errno;
- }
- else if (!share->w_locks)
- { /* No more locks */
- flag=1;
- if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
- MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
- error=my_errno;
- }
- }
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- info->lock_type= F_UNLCK;
- break;
- case F_RDLCK:
- if (info->lock_type == F_WRLCK)
- { /* Change RW to READONLY */
- if (share->w_locks == 1)
- {
- flag=1;
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE)))
- {
- error=my_errno;
- break;
- }
- }
- share->w_locks--;
- share->r_locks++;
- info->lock_type=lock_type;
- break;
- }
- if (!share->r_locks && !share->w_locks)
- {
- flag=1;
-#ifdef HAVE_FCNTL
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
- {
- error=my_errno;
- break;
- }
- if (my_pread(share->kfile,
- (char*) &share->state.header,share->state_length,0L,
- MYF(MY_NABP)))
- {
- error=my_errno;
- VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
- my_errno=error;
- break;
- }
-#else
- VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
- {
- error=my_errno;
- break;
- }
- if (my_read(share->kfile,
- (char*) &share->state.header,share->state_length,
- MYF(MY_NABP)))
- {
- error=my_errno;
- VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
- my_errno=error;
- break;
- }
-#endif
- }
- VOID(_nisam_test_if_changed(info));
- share->r_locks++;
- info->lock_type=lock_type;
- break;
- case F_WRLCK:
- if (info->lock_type == F_RDLCK)
- { /* Change RW to READONLY */
- if (share->r_locks == 1)
- {
- flag=1;
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
- MYF(info->lock_wait | MY_SEEK_NOT_DONE)))
- {
- error=my_errno;
- break;
- }
- share->r_locks--;
- share->w_locks++;
- info->lock_type=lock_type;
- break;
- }
- }
- if (!(share->base.options & HA_OPTION_READ_ONLY_DATA) && !share->w_locks)
- {
- flag=1;
- VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
- {
- error=my_errno;
- break;
- }
- if (!share->r_locks)
- {
- if (my_read(share->kfile,
- (char*) &share->state.header,share->state_length,
- MYF(MY_NABP)))
- {
- error=my_errno;
- VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
- my_errno=error;
- break;
- }
- }
- }
- VOID(_nisam_test_if_changed(info));
- info->lock_type=lock_type;
- share->w_locks++;
- break;
- default:
- break; /* Impossible */
- }
- pthread_mutex_unlock(&share->intern_lock);
-#if defined(FULL_LOG) || defined(_lint)
- lock_type|=(int) (flag << 8); /* Set bit to set if real lock */
- nisam_log_command(LOG_LOCK,info,(byte*) &lock_type,sizeof(lock_type),
- error);
-#endif
-#endif
- DBUG_RETURN(error);
-} /* nisam_lock_database */
-
-
- /* Is used before access to database is granted */
-
-int _nisam_readinfo(register N_INFO *info, int lock_type, int check_keybuffer)
-{
- ISAM_SHARE *share;
- DBUG_ENTER("_nisam_readinfo");
-
- share=info->s;
- if (info->lock_type == F_UNLCK)
- {
- if (!share->r_locks && !share->w_locks)
- {
-#ifndef HAVE_FCNTL
- VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
-#endif
-#ifndef NO_LOCKING
-#ifdef UNSAFE_LOCKING
- if ((info->tmp_lock_type=lock_type) != F_RDLCK)
-#endif
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
- DBUG_RETURN(1);
-#endif
-#ifdef HAVE_FCNTL
- if (my_pread(share->kfile,
- (char*) &share->state.header,share->state_length,0L,
- MYF(MY_NABP)))
-#else
- if (my_read(share->kfile,
- (char*) &share->state.header,share->state_length,
- MYF(MY_NABP)))
-#endif
- {
-#ifndef NO_LOCKING
- int error=my_errno;
- VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE)));
- my_errno=error;
-#endif
- DBUG_RETURN(1);
- }
- }
- if (check_keybuffer)
- VOID(_nisam_test_if_changed(info));
- }
- else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
- {
- my_errno=EACCES; /* Not allowed to change */
- DBUG_RETURN(-1); /* when have read_lock() */
- }
- DBUG_RETURN(0);
-} /* _nisam_readinfo */
-
-
- /* Every isam-function that uppdates the isam-database must! end */
- /* with this request */
- /* ARGSUSED */
-
-int _nisam_writeinfo(register N_INFO *info, uint flags)
-{
- int error,olderror;
- ISAM_SHARE *share;
- DBUG_ENTER("_nisam_writeinfo");
-
- error=0;
- share=info->s;
- if (share->r_locks == 0 && share->w_locks == 0)
- {
- olderror=my_errno; /* Remember last error */
- if (flags)
- { /* Two threads can't be here */
- share->state.process= share->last_process= share->this_process;
- share->state.loop= info->last_loop= ++info->this_loop;
- share->state.uniq= info->last_uniq= info->this_uniq;
- if ((error=my_pwrite(share->kfile,(char*) &share->state.header,
- share->state_length,0L,MYF(MY_NABP)) != 0))
- olderror=my_errno;
-#ifdef __WIN__
- if (nisam_flush)
- {
- _commit(share->kfile);
- _commit(info->dfile);
- }
-#endif
- }
- if (flags != 2)
- {
-#ifndef NO_LOCKING
-#ifdef UNSAFE_LOCKING
- if (info->tmp_lock_type != F_RDLCK)
-#endif
- {
- if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
- MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
- DBUG_RETURN(1);
- }
-#endif
- }
- my_errno=olderror;
- }
- else if (flags)
- share->changed= 1; /* Mark keyfile changed */
- DBUG_RETURN(error);
-} /* _nisam_writeinfo */
-
-
- /* Test if someone has changed the database */
- /* (Should be called after readinfo) */
-
-int _nisam_test_if_changed(register N_INFO *info)
-{
-#ifndef NO_LOCKING
- {
- ISAM_SHARE *share=info->s;
- if (share->state.process != share->last_process ||
- share->state.loop != info->last_loop ||
- share->state.uniq != info->last_uniq)
- { /* Keyfile has changed */
- if (share->state.process != share->this_process)
- VOID(flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE));
- share->last_process=share->state.process;
- info->last_loop= share->state.loop;
- info->last_uniq= share->state.uniq;
- info->update|= HA_STATE_WRITTEN; /* Must use file on next */
- info->data_changed= 1; /* For nisam_is_changed */
- return 1;
- }
- }
-#endif
- return (!(info->update & HA_STATE_AKTIV) ||
- (info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED |
- HA_STATE_KEY_CHANGED)));
-} /* _nisam_test_if_changed */
diff --git a/isam/_packrec.c b/isam/_packrec.c
deleted file mode 100644
index 74a45852e63..00000000000
--- a/isam/_packrec.c
+++ /dev/null
@@ -1,1184 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
- /* Functions to compressed records */
-
-#include "isamdef.h"
-
-#define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */
-
-#if INT_MAX > 65536L
-#define BITS_SAVED 32
-#define MAX_QUICK_TABLE_BITS 9 /* Because we may shift in 24 bits */
-#else
-#define BITS_SAVED 16
-#define MAX_QUICK_TABLE_BITS 6
-#endif
-
-#define get_bit(BU) ((BU)->bits ? \
- (BU)->current_byte & ((bit_type) 1 << --(BU)->bits) :\
- (fill_buffer(BU), (BU)->bits= BITS_SAVED-1,\
- (BU)->current_byte & ((bit_type) 1 << (BITS_SAVED-1))))
-#define skipp_to_next_byte(BU) ((BU)->bits&=~7)
-#define get_bits(BU,count) (((BU)->bits >= count) ? (((BU)->current_byte >> ((BU)->bits-=count)) & mask[count]) : fill_and_get_bits(BU,count))
-
-#define decode_bytes_test_bit(bit) \
- if (low_byte & (1 << (7-bit))) \
- pos++; \
- if (*pos & IS_CHAR) \
- { bits-=(bit+1); break; } \
- pos+= *pos
-
-
- static void read_huff_table(BIT_BUFF *bit_buff,DECODE_TREE *decode_tree,
- uint16 **decode_table,byte **intervall_buff,
- uint16 *tmp_buff);
-static void make_quick_table(uint16 *to_table,uint16 *decode_table,
- uint *next_free,uint value,uint bits,
- uint max_bits);
-static void fill_quick_table(uint16 *table,uint bits, uint max_bits,
- uint value);
-static uint copy_decode_table(uint16 *to_pos,uint offset,
- uint16 *decode_table);
-static uint find_longest_bitstream(uint16 *table);
-static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *field,
- BIT_BUFF *buff,
- uchar *to,
- uchar *end);
-static void uf_zerofill_skipp_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_skipp_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_normal(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_endspace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to, uchar *end);
-static void uf_endspace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_endspace(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_endspace(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_prespace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to, uchar *end);
-static void uf_prespace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_prespace(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_prespace(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_zerofill_normal(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_constant(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_intervall(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void decode_bytes(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static uint decode_pos(BIT_BUFF *bit_buff,DECODE_TREE *decode_tree);
-static void init_bit_buffer(BIT_BUFF *bit_buff,char *buffer,uint length);
-static uint fill_and_get_bits(BIT_BUFF *bit_buff,uint count);
-static void fill_buffer(BIT_BUFF *bit_buff);
-static uint max_bit(uint value);
-#ifdef HAVE_MMAP
-static void _nisam_mempack_get_block_info(BLOCK_INFO *info,uint ref_length,
- uchar *header);
-#endif
-
-static uint mask[]=
-{
- 0x00000000,
- 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
- 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
- 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
- 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
-#if BITS_SAVED > 16
- 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
- 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
- 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
- 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
-#endif
- };
-
-
- /* Read all packed info, allocate memory and fix field structs */
-
-my_bool _nisam_read_pack_info(N_INFO *info, pbool fix_keys)
-{
- File file;
- int diff_length;
- uint i,trees,huff_tree_bits,rec_reflength,length;
- uint16 *decode_table,*tmp_buff;
- ulong elements,intervall_length;
- char *disk_cache,*intervall_buff;
- uchar header[32];
- ISAM_SHARE *share=info->s;
- BIT_BUFF bit_buff;
- DBUG_ENTER("_nisam_read_pack_info");
-
- if (nisam_quick_table_bits < 4)
- nisam_quick_table_bits=4;
- else if (nisam_quick_table_bits > MAX_QUICK_TABLE_BITS)
- nisam_quick_table_bits=MAX_QUICK_TABLE_BITS;
-
- file=info->dfile;
- my_errno=0;
- if (my_read(file,(byte*) header,sizeof(header),MYF(MY_NABP)))
- {
- if (!my_errno)
- my_errno=HA_ERR_END_OF_FILE;
- DBUG_RETURN(1);
- }
- if (memcmp((byte*) header,(byte*) nisam_pack_file_magic,4))
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(1);
- }
- share->pack.header_length=uint4korr(header+4);
- share->min_pack_length=(uint) uint4korr(header+8);
- share->max_pack_length=(uint) uint4korr(header+12);
- set_if_bigger(share->base.pack_reclength,share->max_pack_length);
- elements=uint4korr(header+16);
- intervall_length=uint4korr(header+20);
- trees=uint2korr(header+24);
- share->pack.ref_length=header[26];
- rec_reflength=header[27];
- diff_length=(int) rec_reflength - (int) share->base.rec_reflength;
- if (fix_keys)
- share->rec_reflength=rec_reflength;
- share->base.min_block_length=share->min_pack_length+share->pack.ref_length;
-
- if (!(share->decode_trees=(DECODE_TREE*)
- my_malloc((uint) (trees*sizeof(DECODE_TREE)+
- intervall_length*sizeof(byte)),
- MYF(MY_WME))))
- DBUG_RETURN(1);
- intervall_buff=(byte*) (share->decode_trees+trees);
-
- length=(uint) (elements*2+trees*(1 << nisam_quick_table_bits));
- if (!(share->decode_tables=(uint16*)
- my_malloc((length+512)*sizeof(uint16)+
- (uint) (share->pack.header_length+7),
- MYF(MY_WME | MY_ZEROFILL))))
- {
- my_free((gptr) share->decode_trees,MYF(0));
- DBUG_RETURN(1);
- }
- tmp_buff=share->decode_tables+length;
- disk_cache=(byte*) (tmp_buff+512);
-
- if (my_read(file,disk_cache,
- (uint) (share->pack.header_length-sizeof(header)),
- MYF(MY_NABP)))
- {
- my_free((gptr) share->decode_trees,MYF(0));
- my_free((gptr) share->decode_tables,MYF(0));
- DBUG_RETURN(1);
- }
-
- huff_tree_bits=max_bit(trees ? trees-1 : 0);
- init_bit_buffer(&bit_buff,disk_cache,
- (uint) (share->pack.header_length-sizeof(header)));
- /* Read new info for each field */
- for (i=0 ; i < share->base.fields ; i++)
- {
- share->rec[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,4);
- share->rec[i].pack_type=(uint) get_bits(&bit_buff,4);
- share->rec[i].space_length_bits=get_bits(&bit_buff,4);
- share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff,
- huff_tree_bits);
- share->rec[i].unpack=get_unpack_function(share->rec+i);
- }
- skipp_to_next_byte(&bit_buff);
- decode_table=share->decode_tables;
- for (i=0 ; i < trees ; i++)
- read_huff_table(&bit_buff,share->decode_trees+i,&decode_table,
- &intervall_buff,tmp_buff);
- decode_table=(uint16*)
- my_realloc((gptr) share->decode_tables,
- (uint) ((byte*) decode_table - (byte*) share->decode_tables),
- MYF(MY_HOLD_ON_ERROR));
- {
- my_ptrdiff_t diff=PTR_BYTE_DIFF(decode_table,share->decode_tables);
- share->decode_tables=decode_table;
- for (i=0 ; i < trees ; i++)
- share->decode_trees[i].table=ADD_TO_PTR(share->decode_trees[i].table,
- diff, uint16*);
- }
-
- /* Fix record-ref-length for keys */
- if (fix_keys)
- {
- for (i=0 ; i < share->base.keys ; i++)
- {
- share->keyinfo[i].base.keylength+=(uint16) diff_length;
- share->keyinfo[i].base.minlength+=(uint16) diff_length;
- share->keyinfo[i].base.maxlength+=(uint16) diff_length;
- share->keyinfo[i].seg[share->keyinfo[i].base.keysegs].base.length=
- (uint16) rec_reflength;
- }
- }
-
- if (bit_buff.error || bit_buff.pos < bit_buff.end)
- { /* info_length was wrong */
- my_errno=HA_ERR_WRONG_IN_RECORD;
- my_free((gptr) share->decode_trees,MYF(0));
- my_free((gptr) share->decode_tables,MYF(0));
- DBUG_RETURN(1);
- }
- DBUG_RETURN(0);
-}
-
-
- /* Read on huff-code-table from datafile */
-
-static void read_huff_table(BIT_BUFF *bit_buff, DECODE_TREE *decode_tree,
- uint16 **decode_table, byte **intervall_buff,
- uint16 *tmp_buff)
-{
- uint min_chr,elements,char_bits,offset_bits,size,intervall_length,table_bits,
- next_free_offset;
- uint16 *ptr,*end;
-
- LINT_INIT(ptr);
- if (!get_bits(bit_buff,1))
- {
- min_chr=get_bits(bit_buff,8);
- elements=get_bits(bit_buff,9);
- char_bits=get_bits(bit_buff,5);
- offset_bits=get_bits(bit_buff,5);
- intervall_length=0;
- ptr=tmp_buff;
- }
- else
- {
- min_chr=0;
- elements=get_bits(bit_buff,15);
- intervall_length=get_bits(bit_buff,16);
- char_bits=get_bits(bit_buff,5);
- offset_bits=get_bits(bit_buff,5);
- decode_tree->quick_table_bits=0;
- ptr= *decode_table;
- }
- size=elements*2-2;
-
- for (end=ptr+size ; ptr < end ; ptr++)
- {
- if (get_bit(bit_buff))
- *ptr= (uint16) get_bits(bit_buff,offset_bits);
- else
- *ptr= (uint16) (IS_CHAR + (get_bits(bit_buff,char_bits) + min_chr));
- }
- skipp_to_next_byte(bit_buff);
-
- decode_tree->table= *decode_table;
- decode_tree->intervalls= *intervall_buff;
- if (! intervall_length)
- {
- table_bits=find_longest_bitstream(tmp_buff);
- if (table_bits > nisam_quick_table_bits)
- table_bits=nisam_quick_table_bits;
- next_free_offset= (1 << table_bits);
- make_quick_table(*decode_table,tmp_buff,&next_free_offset,0,table_bits,
- table_bits);
- (*decode_table)+= next_free_offset;
- decode_tree->quick_table_bits=table_bits;
- }
- else
- {
- (*decode_table)=end;
- bit_buff->pos-= bit_buff->bits/8;
- memcpy(*intervall_buff,bit_buff->pos,(size_t) intervall_length);
- (*intervall_buff)+=intervall_length;
- bit_buff->pos+=intervall_length;
- bit_buff->bits=0;
- }
- return;
-}
-
-
-static void make_quick_table(uint16 *to_table, uint16 *decode_table, uint *next_free_offset, uint value, uint bits, uint max_bits)
-{
- if (!bits--)
- {
- to_table[value]= (uint16) *next_free_offset;
- *next_free_offset=copy_decode_table(to_table, *next_free_offset,
- decode_table);
- return;
- }
- if (!(*decode_table & IS_CHAR))
- {
- make_quick_table(to_table,decode_table+ *decode_table,
- next_free_offset,value,bits,max_bits);
- }
- else
- fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
- decode_table++;
- value|= (1 << bits);
- if (!(*decode_table & IS_CHAR))
- {
- make_quick_table(to_table,decode_table+ *decode_table,
- next_free_offset,value,bits,max_bits);
- }
- else
- fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
- return;
-}
-
-
-static void fill_quick_table(uint16 *table, uint bits, uint max_bits, uint value)
-{
- uint16 *end;
- value|=(max_bits-bits) << 8;
- for (end=table+ (1 << bits) ;
- table < end ;
- *table++ = (uint16) value | IS_CHAR) ;
-}
-
-
-static uint copy_decode_table(uint16 *to_pos, uint offset, uint16 *decode_table)
-{
- uint prev_offset;
- prev_offset= offset;
-
- if (!(*decode_table & IS_CHAR))
- {
- to_pos[offset]=2;
- offset=copy_decode_table(to_pos,offset+2,decode_table+ *decode_table);
- }
- else
- {
- to_pos[offset]= *decode_table;
- offset+=2;
- }
- decode_table++;
-
- if (!(*decode_table & IS_CHAR))
- {
- to_pos[prev_offset+1]=(uint16) (offset-prev_offset-1);
- offset=copy_decode_table(to_pos,offset,decode_table+ *decode_table);
- }
- else
- to_pos[prev_offset+1]= *decode_table;
- return offset;
-}
-
-
-static uint find_longest_bitstream(uint16 *table)
-{
- uint length=1,length2;
- if (!(*table & IS_CHAR))
- length=find_longest_bitstream(table+ *table)+1;
- table++;
- if (!(*table & IS_CHAR))
- {
- length2=find_longest_bitstream(table+ *table)+1;
- length=max(length,length2);
- }
- return length;
-}
-
-
- /* Read record from datafile */
- /* Returns length of packed record, -1 if error */
-
-int _nisam_read_pack_record(N_INFO *info, ulong filepos, byte *buf)
-{
- BLOCK_INFO block_info;
- File file;
- DBUG_ENTER("_nisam_read_pack_record");
-
- if (filepos == NI_POS_ERROR)
- DBUG_RETURN(-1); /* _search() didn't find record */
-
- file=info->dfile;
- if (_nisam_pack_get_block_info(&block_info,info->s->pack.ref_length,file,
- filepos))
- goto err;
- if (my_read(file,(byte*) info->rec_buff,block_info.rec_len,MYF(MY_NABP)))
- goto panic;
- info->update|= HA_STATE_AKTIV;
- DBUG_RETURN(_nisam_pack_rec_unpack(info,buf,info->rec_buff,
- block_info.rec_len));
-panic:
- my_errno=HA_ERR_WRONG_IN_RECORD;
-err:
- DBUG_RETURN(-1);
-}
-
-
-
-int _nisam_pack_rec_unpack(register N_INFO *info, register byte *to,
- byte *from, uint reclength)
-{
- byte *end_field;
- reg3 N_RECINFO *end;
- N_RECINFO *current_field;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_pack_rec_unpack");
-
- init_bit_buffer(&info->bit_buff,from,reclength);
-
- for (current_field=share->rec, end=current_field+share->base.fields ;
- current_field < end ;
- current_field++,to=end_field)
- {
- end_field=to+current_field->base.length;
- (*current_field->unpack)(current_field,&info->bit_buff,(uchar*) to,
- (uchar*) end_field);
- }
- if (! info->bit_buff.error &&
- info->bit_buff.pos - info->bit_buff.bits/8 == info->bit_buff.end)
- DBUG_RETURN(0);
- my_errno=HA_ERR_WRONG_IN_RECORD;
- info->update&= ~HA_STATE_AKTIV;
- DBUG_RETURN(-1);
-} /* _nisam_pack_rec_unpack */
-
-
- /* Return function to unpack field */
-
-static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *, BIT_BUFF *, uchar *, uchar *)
-{
- switch (rec->base_type) {
- case FIELD_SKIP_ZERO:
- if (rec->pack_type & PACK_TYPE_ZERO_FILL)
- return &uf_zerofill_skipp_zero;
- return &uf_skipp_zero;
- case FIELD_NORMAL:
- if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
- return &uf_space_normal;
- if (rec->pack_type & PACK_TYPE_ZERO_FILL)
- return &uf_zerofill_normal;
- return &decode_bytes;
- case FIELD_SKIP_ENDSPACE:
- if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
- {
- if (rec->pack_type & PACK_TYPE_SELECTED)
- return &uf_space_endspace_selected;
- return &uf_space_endspace;
- }
- if (rec->pack_type & PACK_TYPE_SELECTED)
- return &uf_endspace_selected;
- return &uf_endspace;
- case FIELD_SKIP_PRESPACE:
- if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
- {
- if (rec->pack_type & PACK_TYPE_SELECTED)
- return &uf_space_prespace_selected;
- return &uf_space_prespace;
- }
- if (rec->pack_type & PACK_TYPE_SELECTED)
- return &uf_prespace_selected;
- return &uf_prespace;
- case FIELD_CONSTANT:
- return &uf_constant;
- case FIELD_INTERVALL:
- return &uf_intervall;
- case FIELD_ZERO:
- return &uf_zero;
- case FIELD_BLOB: /* Write this sometimes.. */
- case FIELD_LAST:
- default:
- return 0; /* This should never happend */
- }
-}
-
- /* De different functions to unpack a field */
-
-static void uf_zerofill_skipp_zero(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- if (get_bit(bit_buff))
- bzero((char*) to,(uint) (end-to));
- else
- {
-#ifdef WORDS_BIGENDIAN
- bzero((char*) to,rec->space_length_bits);
- decode_bytes(rec,bit_buff,to+rec->space_length_bits,end);
-#else
- end-=rec->space_length_bits;
- decode_bytes(rec,bit_buff,to,end);
- bzero((byte*) end,rec->space_length_bits);
-#endif
- }
-}
-
-static void uf_skipp_zero(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- if (get_bit(bit_buff))
- bzero((char*) to,(uint) (end-to));
- else
- decode_bytes(rec,bit_buff,to,end);
-}
-
-static void uf_space_normal(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- decode_bytes(rec,bit_buff,to,end);
-}
-
-static void uf_space_endspace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- {
- if (get_bit(bit_buff))
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to,end-spaces);
- bfill((byte*) end-spaces,spaces,' ');
- }
- else
- decode_bytes(rec,bit_buff,to,end);
- }
-}
-
-static void uf_endspace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to,end-spaces);
- bfill((byte*) end-spaces,spaces,' ');
- }
- else
- decode_bytes(rec,bit_buff,to,end);
-}
-
-static void uf_space_endspace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to,end-spaces);
- bfill((byte*) end-spaces,spaces,' ');
- }
-}
-
-static void uf_endspace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to,
- uchar *end)
-{
- uint spaces;
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to,end-spaces);
- bfill((byte*) end-spaces,spaces,' ');
-}
-
-static void uf_space_prespace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- {
- if (get_bit(bit_buff))
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- bfill((byte*) to,spaces,' ');
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to+spaces,end);
- }
- else
- decode_bytes(rec,bit_buff,to,end);
- }
-}
-
-
-static void uf_prespace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- bfill((byte*) to,spaces,' ');
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to+spaces,end);
- }
- else
- decode_bytes(rec,bit_buff,to,end);
-}
-
-
-static void uf_space_prespace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- bfill((byte*) to,spaces,' ');
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to+spaces,end);
- }
-}
-
-static void uf_prespace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- bfill((byte*) to,spaces,' ');
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to+spaces,end);
-}
-
-static void uf_zerofill_normal(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
-#ifdef WORDS_BIGENDIAN
- bzero((char*) to,rec->space_length_bits);
- decode_bytes(rec,bit_buff,(uchar*) to+rec->space_length_bits,end);
-#else
- end-=rec->space_length_bits;
- decode_bytes(rec,bit_buff,(uchar*) to,end);
- bzero((byte*) end,rec->space_length_bits);
-#endif
-}
-
-static void uf_constant(N_RECINFO *rec,
- BIT_BUFF *bit_buff __attribute__((unused)),
- uchar *to, uchar *end)
-{
- memcpy(to,rec->huff_tree->intervalls,(size_t) (end-to));
-}
-
-static void uf_intervall(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- reg1 uint field_length=(uint) (end-to);
- memcpy(to,rec->huff_tree->intervalls+field_length*decode_pos(bit_buff,
- rec->huff_tree),
- (size_t) field_length);
-}
-
-
-/*ARGSUSED*/
-static void uf_zero(N_RECINFO *rec __attribute__((unused)),
- BIT_BUFF *bit_buff __attribute__((unused)),
- uchar *to, uchar *end)
-{
- bzero((char*) to,(uint) (end-to));
-}
-
-
- /* Functions to decode of buffer of bits */
-
-#if BITS_SAVED == 64
-
-static void decode_bytes(rec,bit_buff,to,end)
-N_RECINFO *rec;
-BIT_BUFF *bit_buff;
-uchar *to,*end;
-{
- reg1 uint bits,low_byte;
- reg3 uint16 *pos;
- reg4 uint table_bits,table_and;
- DECODE_TREE *decode_tree;
-
- decode_tree=rec->decode_tree;
- bits=bit_buff->bits; /* Save in reg for quicker access */
- table_bits=decode_tree->quick_table_bits;
- table_and= (1 << table_bits)-1;
-
- do
- {
- if (bits <= 32)
- {
- if (bit_buff->pos > bit_buff->end+4)
- return; /* Can't be right */
- bit_buff->current_byte= (bit_buff->current_byte << 32) +
- ((((uint) bit_buff->pos[3])) +
- (((uint) bit_buff->pos[2]) << 8) +
- (((uint) bit_buff->pos[1]) << 16) +
- (((uint) bit_buff->pos[0]) << 24));
- bit_buff->pos+=4;
- bits+=32;
- }
- /* First use info in quick_table */
- low_byte=(uint) (bit_buff->current_byte >> (bits - table_bits)) & table_and;
- low_byte=decode_tree->table[low_byte];
- if (low_byte & IS_CHAR)
- {
- *to++ = (low_byte & 255); /* Found char in quick table */
- bits-= ((low_byte >> 8) & 31); /* Remove bits used */
- }
- else
- { /* Map through rest of decode-table */
- pos=decode_tree->table+low_byte;
- bits-=table_bits;
- for (;;)
- {
- low_byte=(uint) (bit_buff->current_byte >> (bits-8));
- decode_bytes_test_bit(0);
- decode_bytes_test_bit(1);
- decode_bytes_test_bit(2);
- decode_bytes_test_bit(3);
- decode_bytes_test_bit(4);
- decode_bytes_test_bit(5);
- decode_bytes_test_bit(6);
- decode_bytes_test_bit(7);
- bits-=8;
- }
- *to++ = *pos;
- }
- } while (to != end);
-
- bit_buff->bits=bits;
- return;
-}
-
-#else
-
-static void decode_bytes(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- reg1 uint bits,low_byte;
- reg3 uint16 *pos;
- reg4 uint table_bits,table_and;
- DECODE_TREE *decode_tree;
-
- decode_tree=rec->huff_tree;
- bits=bit_buff->bits; /* Save in reg for quicker access */
- table_bits=decode_tree->quick_table_bits;
- table_and= (1 << table_bits)-1;
-
- do
- {
- if (bits < table_bits)
- {
- if (bit_buff->pos > bit_buff->end+1)
- return; /* Can't be right */
-#if BITS_SAVED == 32
- bit_buff->current_byte= (bit_buff->current_byte << 24) +
- (((uint) ((uchar) bit_buff->pos[2]))) +
- (((uint) ((uchar) bit_buff->pos[1])) << 8) +
- (((uint) ((uchar) bit_buff->pos[0])) << 16);
- bit_buff->pos+=3;
- bits+=24;
-#else
- if (bits) /* We must have at leasts 9 bits */
- {
- bit_buff->current_byte= (bit_buff->current_byte << 8) +
- (uint) ((uchar) bit_buff->pos[0]);
- bit_buff->pos++;
- bits+=8;
- }
- else
- {
- bit_buff->current_byte= ((uint) ((uchar) bit_buff->pos[0]) << 8) +
- ((uint) ((uchar) bit_buff->pos[1]));
- bit_buff->pos+=2;
- bits+=16;
- }
-#endif
- }
- /* First use info in quick_table */
- low_byte=(bit_buff->current_byte >> (bits - table_bits)) & table_and;
- low_byte=decode_tree->table[low_byte];
- if (low_byte & IS_CHAR)
- {
- *to++ = (low_byte & 255); /* Found char in quick table */
- bits-= ((low_byte >> 8) & 31); /* Remove bits used */
- }
- else
- { /* Map through rest of decode-table */
- pos=decode_tree->table+low_byte;
- bits-=table_bits;
- for (;;)
- {
- if (bits < 8)
- { /* We don't need to check end */
-#if BITS_SAVED == 32
- bit_buff->current_byte= (bit_buff->current_byte << 24) +
- (((uint) ((uchar) bit_buff->pos[2]))) +
- (((uint) ((uchar) bit_buff->pos[1])) << 8) +
- (((uint) ((uchar) bit_buff->pos[0])) << 16);
- bit_buff->pos+=3;
- bits+=24;
-#else
- bit_buff->current_byte= (bit_buff->current_byte << 8) +
- (uint) ((uchar) bit_buff->pos[0]);
- bit_buff->pos+=1;
- bits+=8;
-#endif
- }
- low_byte=(uint) (bit_buff->current_byte >> (bits-8));
- decode_bytes_test_bit(0);
- decode_bytes_test_bit(1);
- decode_bytes_test_bit(2);
- decode_bytes_test_bit(3);
- decode_bytes_test_bit(4);
- decode_bytes_test_bit(5);
- decode_bytes_test_bit(6);
- decode_bytes_test_bit(7);
- bits-=8;
- }
- *to++ = (uchar) *pos;
- }
- } while (to != end);
-
- bit_buff->bits=bits;
- return;
-}
-#endif /* BIT_SAVED == 64 */
-
-
-static uint decode_pos(BIT_BUFF *bit_buff, DECODE_TREE *decode_tree)
-{
- uint16 *pos=decode_tree->table;
- for (;;)
- {
- if (get_bit(bit_buff))
- pos++;
- if (*pos & IS_CHAR)
- return (uint) (*pos & ~IS_CHAR);
- pos+= *pos;
- }
-}
-
-
-int _nisam_read_rnd_pack_record(N_INFO *info, byte *buf,
- register ulong filepos,
- int skipp_deleted_blocks)
-{
- uint b_type;
- BLOCK_INFO block_info;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_read_rnd_pack_record");
-
- if (filepos >= share->state.data_file_length)
- {
- my_errno= HA_ERR_END_OF_FILE;
- goto err;
- }
-
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (_nisam_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
- share->pack.ref_length, skipp_deleted_blocks))
- goto err;
- b_type=_nisam_pack_get_block_info(&block_info,share->pack.ref_length,-1,
- filepos);
- }
- else
- b_type=_nisam_pack_get_block_info(&block_info,share->pack.ref_length,
- info->dfile,filepos);
- if (b_type)
- goto err;
-#ifndef DBUG_OFF
- if (block_info.rec_len > share->max_pack_length)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
-#endif
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (_nisam_read_cache(&info->rec_cache,(byte*) info->rec_buff,
- block_info.filepos, block_info.rec_len,
- skipp_deleted_blocks))
- goto err;
- }
- else
- {
- if (my_read(info->dfile,(byte*) info->rec_buff,block_info.rec_len,
- MYF(MY_NABP)))
- goto err;
- }
- info->packed_length=block_info.rec_len;
- info->lastpos=filepos;
- info->nextpos=block_info.filepos+block_info.rec_len;
- info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
-
- DBUG_RETURN (_nisam_pack_rec_unpack(info,buf,info->rec_buff,
- block_info.rec_len));
-err:
- DBUG_RETURN(-1);
-}
-
-
- /* Read and process header from a huff-record-file */
-
-uint _nisam_pack_get_block_info(BLOCK_INFO *info, uint ref_length, File file,
- ulong filepos)
-{
- uchar *header=info->header;
-
- if (file >= 0)
- {
- VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
- if (my_read(file,(char*) header,ref_length,MYF(MY_NABP)))
- return BLOCK_FATAL_ERROR;
- }
- DBUG_DUMP("header",(byte*) header,ref_length);
-
- switch (ref_length) {
- case 1:
- info->rec_len=header[0];
- info->filepos=filepos+1;
- break;
- case 2:
- info->rec_len=uint2korr(header);
- info->filepos=filepos+2;
- break;
- case 3:
- info->rec_len=(uint) (uint3korr(header));
- info->filepos=filepos+3;
- break;
- default: break;
- }
- return 0;
-}
-
-
- /* routines for bit buffer */
- /* Buffer must be 6 byte bigger */
-static void init_bit_buffer(BIT_BUFF *bit_buff, char *buffer, uint length)
-{
- bit_buff->pos=(uchar*) buffer;
- bit_buff->end=(uchar*) buffer+length;
- bit_buff->bits=bit_buff->error=0;
- bit_buff->current_byte=0; /* Avoid purify errors */
-}
-
-static uint fill_and_get_bits(BIT_BUFF *bit_buff, uint count)
-{
- uint tmp;
- count-=bit_buff->bits;
- tmp=(bit_buff->current_byte & mask[bit_buff->bits]) << count;
- fill_buffer(bit_buff);
- bit_buff->bits=BITS_SAVED - count;
- return tmp+(bit_buff->current_byte >> (BITS_SAVED - count));
-}
-
- /* Fill in empty bit_buff->current_byte from buffer */
- /* Sets bit_buff->error if buffer is exhausted */
-
-static void fill_buffer(BIT_BUFF *bit_buff)
-{
- if (bit_buff->pos >= bit_buff->end)
- {
- bit_buff->error= 1;
- bit_buff->current_byte=0;
- return;
- }
-#if BITS_SAVED == 64
- bit_buff->current_byte= ((((uint) ((uchar) bit_buff->pos[7]))) +
- (((uint) ((uchar) bit_buff->pos[6])) << 8) +
- (((uint) ((uchar) bit_buff->pos[5])) << 16) +
- (((uint) ((uchar) bit_buff->pos[4])) << 24) +
- ((ulonglong)
- ((((uint) ((uchar) bit_buff->pos[3]))) +
- (((uint) ((uchar) bit_buff->pos[2])) << 8) +
- (((uint) ((uchar) bit_buff->pos[1])) << 16) +
- (((uint) ((uchar) bit_buff->pos[0])) << 24)) << 32));
- bit_buff->pos+=8;
-#else
-#if BITS_SAVED == 32
- bit_buff->current_byte= (((uint) ((uchar) bit_buff->pos[3])) +
- (((uint) ((uchar) bit_buff->pos[2])) << 8) +
- (((uint) ((uchar) bit_buff->pos[1])) << 16) +
- (((uint) ((uchar) bit_buff->pos[0])) << 24));
- bit_buff->pos+=4;
-#else
- bit_buff->current_byte= (uint) (((uint) ((uchar) bit_buff->pos[1]))+
- (((uint) ((uchar) bit_buff->pos[0])) << 8));
- bit_buff->pos+=2;
-#endif
-#endif
-}
-
- /* Get number of bits neaded to represent value */
-
-static uint max_bit(register uint value)
-{
- reg2 uint power=1;
-
- while ((value>>=1))
- power++;
- return (power);
-}
-
-
-/*****************************************************************************
- Some redefined functions to handle files when we are using memmap
-*****************************************************************************/
-
-#ifdef HAVE_MMAP
-
-#include <sys/mman.h>
-
-static int _nisam_read_mempack_record(N_INFO *info,ulong filepos,byte *buf);
-static int _nisam_read_rnd_mempack_record(N_INFO*, byte *,ulong, int);
-
-#ifndef MAP_NORESERVE
-#define MAP_NORESERVE 0 /* For irix */
-#endif
-#ifndef MAP_FAILED
-#define MAP_FAILED -1
-#endif
-
-my_bool _nisam_memmap_file(N_INFO *info)
-{
- byte *file_map;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_memmap_file");
-
- if (!info->s->file_map)
- {
- if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) <
- share->state.data_file_length+MEMMAP_EXTRA_MARGIN)
- {
- DBUG_PRINT("warning",("File isn't extended for memmap"));
- DBUG_RETURN(0);
- }
- file_map=(byte*)
- mmap(0,share->state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ,
- MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
- if (file_map == (byte*) MAP_FAILED)
- {
- DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
- my_errno=errno;
- DBUG_RETURN(0);
- }
- info->s->file_map=file_map;
- }
- info->opt_flag|= MEMMAP_USED;
- info->read_record=share->read_record=_nisam_read_mempack_record;
- share->read_rnd=_nisam_read_rnd_mempack_record;
- DBUG_RETURN(1);
-}
-
-
-void _nisam_unmap_file(N_INFO *info)
-{
- if (info->s->file_map)
- (void) munmap((caddr_t) info->s->file_map,
- (size_t) info->s->state.data_file_length+
- MEMMAP_EXTRA_MARGIN);
-}
-
-
-static void _nisam_mempack_get_block_info(BLOCK_INFO *info, uint ref_length,
- uchar *header)
-{
- if (ref_length == 1) /* This is most usual */
- info->rec_len=header[0];
- else if (ref_length == 2)
- info->rec_len=uint2korr(header);
- else
- info->rec_len=(uint) (uint3korr(header));
-}
-
-
-static int _nisam_read_mempack_record(N_INFO *info, ulong filepos, byte *buf)
-{
- BLOCK_INFO block_info;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("ni_read_mempack_record");
-
- if (filepos == NI_POS_ERROR)
- DBUG_RETURN(-1); /* _search() didn't find record */
-
- _nisam_mempack_get_block_info(&block_info,share->pack.ref_length,
- (uchar*) share->file_map+filepos);
- DBUG_RETURN(_nisam_pack_rec_unpack(info,buf,share->file_map+
- share->pack.ref_length+filepos,
- block_info.rec_len));
-}
-
-
-/*ARGSUSED*/
-static int _nisam_read_rnd_mempack_record(N_INFO *info, byte *buf,
- register ulong filepos,
- int skipp_deleted_blocks
- __attribute__((unused)))
-{
- BLOCK_INFO block_info;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_read_rnd_mempack_record");
-
- if (filepos >= share->state.data_file_length)
- {
- my_errno=HA_ERR_END_OF_FILE;
- goto err;
- }
-
- _nisam_mempack_get_block_info(&block_info,share->pack.ref_length,
- (uchar*) share->file_map+filepos);
-#ifndef DBUG_OFF
- if (block_info.rec_len > info->s->max_pack_length)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
-#endif
- info->packed_length=block_info.rec_len;
- info->lastpos=filepos;
- info->nextpos=filepos+share->pack.ref_length+block_info.rec_len;
- info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
-
- DBUG_RETURN (_nisam_pack_rec_unpack(info,buf,share->file_map+
- share->pack.ref_length+filepos,
- block_info.rec_len));
-err:
- DBUG_RETURN(-1);
-}
-
-#endif /* HAVE_MMAP */
diff --git a/isam/_page.c b/isam/_page.c
deleted file mode 100644
index e31115e624f..00000000000
--- a/isam/_page.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser och skriver nyckelblock */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* Fetch a key-page in memory */
-
-uchar *_nisam_fetch_keypage(register N_INFO *info, N_KEYDEF *keyinfo,
- my_off_t page, uchar *buff, int return_buffer)
-{
- uchar *tmp;
- tmp=(uchar*) key_cache_read(dflt_key_cache,
- info->s->kfile,page,DFLT_INIT_HITS,(byte*) buff,
- (uint) keyinfo->base.block_length,
- (uint) keyinfo->base.block_length,
- return_buffer);
- if (tmp == info->buff)
- {
- info->update|=HA_STATE_BUFF_SAVED;
- info->int_pos=(ulong) page;
- info->buff_used=1;
- }
- else
- {
- info->update&= ~HA_STATE_BUFF_SAVED;
- if (tmp)
- info->int_pos=(ulong) page;
- else
- {
- info->int_pos=NI_POS_ERROR;
- DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno));
- my_errno=HA_ERR_CRASHED;
- }
- }
- return tmp;
-} /* _nisam_fetch_keypage */
-
-
- /* Write a key-page on disk */
-
-int _nisam_write_keypage(register N_INFO *info, register N_KEYDEF *keyinfo,
- my_off_t page, uchar *buff)
-{
- reg3 uint length;
-#ifndef QQ /* Safety check */
- if (page < info->s->base.keystart ||
- page+keyinfo->base.block_length > info->s->state.key_file_length ||
- page & (nisam_block_size-1))
- {
- DBUG_PRINT("error",("Trying to write outside key region: %lu",
- (long) page));
- my_errno=EINVAL;
- return(-1);
- }
- DBUG_PRINT("page",("write page at: %lu",(long) page,buff));
- DBUG_DUMP("buff",(byte*) buff,getint(buff));
-#endif
-
- if ((length=keyinfo->base.block_length) > IO_SIZE*2 &&
- info->s->state.key_file_length != page+length)
- length= ((getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1));
-#ifdef HAVE_purify
- {
- length=getint(buff);
- bzero((byte*) buff+length,keyinfo->base.block_length-length);
- length=keyinfo->base.block_length;
- }
-#endif
- return (key_cache_write(dflt_key_cache,
- info->s->kfile,page,DFLT_INIT_HITS,
- (byte*) buff,length,
- (uint) keyinfo->base.block_length,
- (int) (info->lock_type != F_UNLCK)));
-} /* nisam_write_keypage */
-
-
- /* Remove page from disk */
-
-int _nisam_dispose(register N_INFO *info, N_KEYDEF *keyinfo, my_off_t pos)
-{
- uint keynr= (uint) (keyinfo - info->s->keyinfo);
- ulong old_link; /* ulong is ok here */
- DBUG_ENTER("_nisam_dispose");
-
- old_link=info->s->state.key_del[keynr];
- info->s->state.key_del[keynr]=(ulong) pos;
- DBUG_RETURN(key_cache_write(dflt_key_cache,
- info->s->kfile,pos,DFLT_INIT_HITS,
- (byte*) &old_link,
- sizeof(long),
- (uint) keyinfo->base.block_length,
- (int) (info->lock_type != F_UNLCK)));
-} /* _nisam_dispose */
-
-
- /* Make new page on disk */
-
-ulong _nisam_new(register N_INFO *info, N_KEYDEF *keyinfo)
-{
- uint keynr= (uint) (keyinfo - info->s->keyinfo);
- ulong pos;
- DBUG_ENTER("_nisam_new");
-
- if ((pos=info->s->state.key_del[keynr]) == NI_POS_ERROR)
- {
- if (info->s->state.key_file_length >= info->s->base.max_key_file_length)
- {
- my_errno=HA_ERR_INDEX_FILE_FULL;
- DBUG_RETURN(NI_POS_ERROR);
- }
- pos=info->s->state.key_file_length;
- info->s->state.key_file_length+= keyinfo->base.block_length;
- }
- else
- {
- if (!key_cache_read(dflt_key_cache,
- info->s->kfile,pos,DFLT_INIT_HITS,
- (byte*) &info->s->state.key_del[keynr],
- (uint) sizeof(long),
- (uint) keyinfo->base.block_length,0))
- pos= NI_POS_ERROR;
- }
- DBUG_PRINT("exit",("Pos: %d",pos));
- DBUG_RETURN(pos);
-} /* _nisam_new */
diff --git a/isam/_search.c b/isam/_search.c
deleted file mode 100644
index fbffd6786e1..00000000000
--- a/isam/_search.c
+++ /dev/null
@@ -1,889 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* S|ker efter positionen f|r en nyckel samt d{rmedh|rande funktioner */
-
-#include "isamdef.h"
-#include "m_ctype.h"
-
-#define CMP(a,b) (a<b ? -1 : a == b ? 0 : 1)
-
- /* Check index */
-
-int _nisam_check_index(N_INFO *info, int inx)
-{
- if (inx == -1) /* Use last index */
- inx=info->lastinx;
- if (inx >= (int) info->s->state.keys || inx < 0)
- {
- my_errno=HA_ERR_WRONG_INDEX;
- return -1;
- }
- if (info->lastinx != inx) /* Index changed */
- {
- info->lastinx = inx;
- info->lastpos = NI_POS_ERROR;
- info->update= ((info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) |
- HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
- }
- if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
- return(-1);
- return(inx);
-} /* ni_check_index */
-
-
- /* S|ker reda p} positionen f|r ett record p} basen av en nyckel */
- /* Positionen l{ggs i info->lastpos */
- /* Returns -1 if not found and 1 if search at upper levels */
-
-int _nisam_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, uint key_len, uint nextflag, register ulong pos)
-{
- int error,flag;
- uint nod_flag;
- uchar *keypos,*maxpos;
- uchar lastkey[N_MAX_KEY_BUFF],*buff;
- DBUG_ENTER("_nisam_search");
- DBUG_PRINT("enter",("pos: %ld nextflag: %d lastpos: %ld",
- pos,nextflag,info->lastpos));
-
- if (pos == NI_POS_ERROR)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
- info->lastpos= NI_POS_ERROR;
- if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST)))
- DBUG_RETURN(-1); /* Not found ; return error */
- DBUG_RETURN(1); /* Search at upper levels */
- }
-
- if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,
- test(!(nextflag & SEARCH_SAVE_BUFF)))))
- goto err;
- DBUG_DUMP("page",(byte*) buff,getint(buff));
-
- flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
- &keypos,lastkey);
- nod_flag=test_if_nod(buff);
- maxpos=buff+getint(buff)-1;
-
- if (flag)
- {
- if ((error=_nisam_search(info,keyinfo,key,key_len,nextflag,
- _nisam_kpos(nod_flag,keypos))) <= 0)
- DBUG_RETURN(error);
-
- if (flag >0)
- {
- if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) &&
- keypos == buff+2+nod_flag)
- DBUG_RETURN(1); /* Bigger than key */
- }
- else if (nextflag & SEARCH_BIGGER && keypos >= maxpos)
- DBUG_RETURN(1); /* Smaller than key */
- }
- else
- {
- if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME)
- || key_len) && nod_flag)
- {
- if ((error=_nisam_search(info,keyinfo,key,key_len,SEARCH_FIND,
- _nisam_kpos(nod_flag,keypos))) >= 0 ||
- my_errno != HA_ERR_KEY_NOT_FOUND)
- DBUG_RETURN(error);
- info->int_pos= NI_POS_ERROR; /* Buffer not in memory */
- }
- }
- if (pos != info->int_pos)
- {
- uchar *old_buff=buff;
- if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,
- test(!(nextflag & SEARCH_SAVE_BUFF)))))
- goto err;
- keypos=buff+(keypos-old_buff);
- maxpos=buff+(maxpos-old_buff);
- }
-
- if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
- {
- keypos=_nisam_get_last_key(info,keyinfo,buff,lastkey,keypos);
- if (!(nextflag & SEARCH_SMALLER) &&
- _nisam_key_cmp(keyinfo->seg, lastkey, key, key_len, SEARCH_FIND))
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
- goto err;
- }
- }
-
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey));
- VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey));
- info->lastpos=_nisam_dpos(info,nod_flag,keypos);
- info->int_keypos=info->buff+ (keypos-buff);
- info->int_maxpos=info->buff+ (maxpos-buff);
- info->page_changed=0;
- info->buff_used= (info->buff != buff);
- info->last_search_keypage=info->int_pos;
-
- DBUG_PRINT("exit",("found key at %ld",info->lastpos));
- DBUG_RETURN(0);
-err:
- DBUG_PRINT("exit",("Error: %d",my_errno));
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN (-1);
-} /* _nisam_search */
-
-
- /* Search after key in page-block */
- /* If packed key puts smaller or identical key in buff */
- /* ret_pos point to where find or bigger key starts */
- /* ARGSUSED */
-
-int _nisam_bin_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page,
- uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
- uchar *buff __attribute__((unused)))
-{
- reg4 int start,mid,end;
- int flag;
- uint totlength,nod_flag;
- DBUG_ENTER("_nisam_bin_search");
-
- LINT_INIT(flag);
- totlength=keyinfo->base.keylength+(nod_flag=test_if_nod(page));
- start=0; mid=1;
- end= (int) ((getint(page)-2-nod_flag)/totlength-1);
- DBUG_PRINT("test",("getint: %d end: %d",getint(page),end));
- page+=2+nod_flag;
-
- while (start != end)
- {
- mid= (start+end)/2;
- if ((flag=_nisam_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
- comp_flag))
- >= 0)
- end=mid;
- else
- start=mid+1;
- }
- if (mid != start)
- flag=_nisam_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
- comp_flag);
- if (flag < 0)
- start++; /* point at next, bigger key */
- *ret_pos=page+(uint) start*totlength;
- DBUG_PRINT("exit",("flag: %d keypos: %d",flag,start));
- DBUG_RETURN(flag);
-} /* _nisam_bin_search */
-
-
- /* Used instead of _nisam_bin_search() when key is packed */
- /* Puts smaller or identical key in buff */
- /* Key is searched sequentially */
-
-int _nisam_seq_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff)
-{
- int flag;
- uint nod_flag,length;
- uchar t_buff[N_MAX_KEY_BUFF],*end;
- DBUG_ENTER("_nisam_seq_search");
-
- LINT_INIT(flag); LINT_INIT(length);
- end= page+getint(page);
- nod_flag=test_if_nod(page);
- page+=2+nod_flag;
- *ret_pos=page;
- while (page < end)
- {
- length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
- if ((flag=_nisam_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag)) >= 0)
- break;
-#ifdef EXTRA_DEBUG
- DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d",page,t_buff,flag));
-#endif
- memcpy(buff,t_buff,length);
- *ret_pos=page;
- }
- if (flag == 0)
- memcpy(buff,t_buff,length); /* Result is first key */
- DBUG_PRINT("exit",("flag: %d ret_pos: %lx",flag,*ret_pos));
- DBUG_RETURN(flag);
-} /* _nisam_seq_search */
-
-
- /* Get pos to a key_block */
-
-ulong _nisam_kpos(uint nod_flag, uchar *after_key)
-{
- after_key-=nod_flag;
- switch (nod_flag) {
- case 3:
- return uint3korr(after_key)*512L;
- case 2:
- return uint2korr(after_key)*512L;
- case 1:
- return (uint) (*after_key)*512L;
- case 0: /* At leaf page */
- default: /* Impossible */
- return(NI_POS_ERROR);
- }
-} /* _kpos */
-
-
- /* Save pos to a key_block */
-
-void _nisam_kpointer(register N_INFO *info, register uchar *buff, ulong pos)
-{
- pos/=512L;
- switch (info->s->base.key_reflength) {
- case 3: int3store(buff,pos); break;
- case 2: int2store(buff,(uint) pos); break;
- case 1: buff[0]= (uchar) pos; break;
- default: abort(); /* impossible */
- }
-} /* _nisam_kpointer */
-
-
- /* Calc pos to a data-record */
-
-ulong _nisam_dpos(N_INFO *info, uint nod_flag, uchar *after_key)
-{
- ulong pos;
- after_key-=(nod_flag + info->s->rec_reflength);
- switch (info->s->rec_reflength) {
- case 4:
- pos= (ulong) uint4korr(after_key);
- break;
- case 3:
- pos= (ulong) uint3korr(after_key);
- break;
- case 2:
- pos= (ulong) uint2korr(after_key);
- break;
- default:
- pos=0L; /* Shut compiler up */
- }
- return (info->s->base.options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
- pos*info->s->base.reclength;
-}
-
- /* save pos to record */
-
-void _nisam_dpointer(N_INFO *info, uchar *buff, ulong pos)
-{
- if (!(info->s->base.options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
- pos/=info->s->base.reclength;
-
- switch (info->s->rec_reflength) {
- case 4: int4store(buff,pos); break;
- case 3: int3store(buff,pos); break;
- case 2: int2store(buff,(uint) pos); break;
- default: abort(); /* Impossible */
- }
-} /* _nisam_dpointer */
-
-
- /*
- ** Compare two keys with is bigger
- ** Returns <0, 0, >0 acording to with is bigger
- ** Key_length specifies length of key to use. Number-keys can't
- ** be splitted
- ** If flag <> SEARCH_FIND compare also position
- */
-int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar *b, uint key_length, uint nextflag)
-{
- reg4 int flag,length_diff;
- int16 s_1,s_2;
- int32 l_1,l_2;
- uint32 u_1,u_2;
- float f_1,f_2;
- double d_1,d_2;
- reg5 uchar *end;
-
- if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))
- || key_length == 0)
- key_length=N_MAX_KEY_BUFF*2;
-
- for ( ; (int) key_length >0 ; key_length-= (keyseg++)->base.length)
- {
- end= a+ min(keyseg->base.length,key_length);
- switch ((enum ha_base_keytype) keyseg->base.type) {
- case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
- case HA_KEYTYPE_BINARY:
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- uchar *as, *bs;
- int length,b_length;
-
- as=a++; bs=b++;
- length= (length_diff= ((int) *as - (b_length= (int) *bs))) < 0 ?
- (int) *as : b_length;
- end= a+ min(key_length,(uint) length);
-
- if (use_strnxfrm(default_charset_info)) {
- if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
- {
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- else
- {
- if ((flag = my_strnncoll(default_charset_info,
- a, (int) (end-a), b, b_length)))
- return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag;
- b+= (uint) (end-a);
- a=end;
- }
- }
- else
- {
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- if (key_length < (uint) keyseg->base.length)
- { /* key_part */
- if (length_diff)
- {
- if (length_diff < 0 || (uint) *as <= key_length)
- return ((keyseg->base.flag & HA_REVERSE_SORT) ?
- -length_diff : length_diff);
- for (length= (int) key_length-b_length; length-- > 0 ;)
- {
- if (*a++ != ' ')
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -1 : 1);
- }
- }
- if (nextflag & SEARCH_NO_FIND) /* Find record after key */
- return (nextflag & SEARCH_BIGGER) ? -1 : 1;
- return 0;
- }
- else
- {
- if (length_diff)
- return ((keyseg->base.flag & HA_REVERSE_SORT) ?
- -length_diff : length_diff);
- }
- a=as+ (uint) *as+1 ; b= bs+ b_length+1; /* to next key */
- }
- else
- {
- if (use_strnxfrm(default_charset_info)) {
- if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
- {
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- else
- {
- if ((flag = my_strnncoll(default_charset_info,
- a, (int) (end-a), b, (int) (end-a))))
- return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag;
- b+= (uint) (end-a);
- a=end;
- }
- }
- else
- {
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- }
- break;
- case HA_KEYTYPE_INT8:
- {
- int i_1= (int) *((signed char*) a);
- int i_2= (int) *((signed char*) b);
- if ((flag = CMP(i_1,i_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b++;
- break;
- }
- case HA_KEYTYPE_SHORT_INT:
- shortget(s_1,a);
- shortget(s_2,b);
- if ((flag = CMP(s_1,s_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 2; /* sizeof(short int); */
- break;
- case HA_KEYTYPE_USHORT_INT:
- {
- uint16 us_1,us_2;
- ushortget(us_1,a);
- ushortget(us_2,b);
- if ((flag = CMP(us_1,us_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+=2; /* sizeof(short int); */
- break;
- }
- case HA_KEYTYPE_LONG_INT:
- longget(l_1,a);
- longget(l_2,b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 4; /* sizeof(long int); */
- break;
- case HA_KEYTYPE_ULONG_INT:
- ulongget(u_1,a);
- ulongget(u_2,b);
- if ((flag = CMP(u_1,u_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 4; /* sizeof(long int); */
- break;
- case HA_KEYTYPE_INT24:
- l_1=sint3korr(a);
- l_2=sint3korr(b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 3;
- break;
- case HA_KEYTYPE_UINT24:
- l_1=(long) uint3korr(a);
- l_2=(long) uint3korr(b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 3;
- break;
- case HA_KEYTYPE_FLOAT:
- bmove((byte*) &f_1,(byte*) a,(int) sizeof(float));
- bmove((byte*) &f_2,(byte*) b,(int) sizeof(float));
- if ((flag = CMP(f_1,f_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= sizeof(float);
- break;
- case HA_KEYTYPE_DOUBLE:
- doubleget(d_1,a);
- doubleget(d_2,b);
- if ((flag = CMP(d_1,d_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= sizeof(double);
- break;
- case HA_KEYTYPE_NUM: /* Numeric key */
- {
- int swap_flag=keyseg->base.flag & HA_REVERSE_SORT;
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- int alength,blength;
-
- if (swap_flag)
- swap_variables(uchar*, a, b);
- alength= *a++; blength= *b++;
- if ((flag=(int) (keyseg->base.length-key_length)) < 0)
- flag=0;
- if (alength != blength+flag)
- {
- if ((alength > blength+flag && *a != '-') ||
- (alength < blength+flag && *b == '-'))
- return 1;
- else
- return -1;
- }
- if (*a == '-' && *b == '-')
- {
- swap_flag=1;
- swap_variables(uchar*, a, b);
- }
- end=a+alength;
- while (a < end)
- if (*a++ != *b++)
- {
- a--; b--;
- if (my_isdigit(default_charset_info, (char) *a) &&
- my_isdigit(default_charset_info, (char) *b))
- return ((int) *a - (int) *b);
- if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
- return (-1);
- if (*b == '-' || *b++ == ' ' ||
- my_isdigit(default_charset_info,(char) *a))
- return (1);
- if (*a++ == ' ')
- return (-1);
- }
- }
- else
- {
- for ( ; a < end && *a == ' ' && *b == ' ' ; a++, b++) ;
- if (*a == '-' && *b == '-')
- swap_flag=1;
- if (swap_flag)
- {
- end=b+(int) (end-a);
- swap_variables(uchar*, a, b);
- }
- while (a < end)
- if (*a++ != *b++)
- {
- a--; b--;
- if (my_isdigit(default_charset_info,(char) *a) &&
- my_isdigit(default_charset_info,(char) *b))
- return ((int) *a - (int) *b);
- if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
- return (-1);
- if (*b == '-' || *b++ == ' ' ||
- my_isdigit(default_charset_info,(char) *a))
- return (1);
- if (*a++ == ' ')
- return -1;
- }
- }
- if (swap_flag)
- swap_variables(uchar*, a, b);
- break;
- }
-#ifdef HAVE_LONG_LONG
- case HA_KEYTYPE_LONGLONG:
- {
- longlong ll_a,ll_b;
- longlongget(ll_a,a);
- longlongget(ll_b,b);
- if ((flag = CMP(ll_a,ll_b)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= sizeof(longlong);
- break;
- }
- case HA_KEYTYPE_ULONGLONG:
- {
- ulonglong ll_a,ll_b;
- longlongget(ll_a,a);
- longlongget(ll_b,b);
- if ((flag = CMP(ll_a,ll_b)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= sizeof(ulonglong);
- break;
- }
-#endif
- case HA_KEYTYPE_END: /* Ready */
- case HA_KEYTYPE_VARTEXT: /* Impossible */
- case HA_KEYTYPE_VARBINARY: /* Impossible */
- goto end;
- }
- }
-end:
- if (!(nextflag & SEARCH_FIND))
- {
- if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
- return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
- LINT_INIT(l_1); LINT_INIT(l_2);
- switch (keyseg->base.length) {
- case 4:
- u_1= (ulong) uint4korr(a);
- u_2= (ulong) uint4korr(b);
- break;
- case 3:
- u_1= (ulong) uint3korr(a);
- u_2= (ulong) uint3korr(b);
- break;
- case 2:
- u_1= (ulong) uint2korr(a);
- u_2= (ulong) uint2korr(b);
- break;
- default: abort(); /* Impossible */
- }
- flag = CMP(u_1,u_2);
-
- if (nextflag & SEARCH_SAME)
- return (flag); /* read same */
- if (nextflag & SEARCH_BIGGER)
- return (flag <= 0 ? -1 : 1); /* read next */
- return (flag < 0 ? -1 : 1); /* read previous */
- }
- return 0;
-} /* _nisam_key_cmp */
-
-
- /* Get key from key-block */
- /* page points at previous key; its advanced to point at next key */
- /* key should contain previous key */
- /* Returns length of found key + pointers */
- /* nod_flag is a flag if we are on nod */
-
-uint _nisam_get_key(register N_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page, register uchar *key)
-{
- reg1 N_KEYSEG *keyseg;
- uchar *start,*start_key;
- uint length,c_length;
-
- LINT_INIT(start);
- start_key=key; c_length=0;
- for (keyseg=keyinfo->seg ; keyseg->base.type ;keyseg++)
- {
- if (keyseg->base.flag & (HA_SPACE_PACK | HA_PACK_KEY))
- {
- start=key;
- if (keyseg->base.flag & HA_SPACE_PACK)
- key++;
- if ((length= *(*page)++) & 128)
- {
- key+= (c_length=(length & 127));
- if (c_length == 0) /* Same key */
- {
- key+= *start; /* Same diff_key as prev */
- length=0;
- }
- else
- {
- if (keyseg->base.flag & HA_SPACE_PACK)
- length= *(*page)++;
- else
- length=keyseg->base.length-length+128; /* Rest of key */
- /* Prevent core dumps if wrong data formats */
- if (length > keyseg->base.length)
- length=0;
- }
- }
- }
- else
- length=keyseg->base.length;
- memcpy((byte*) key,(byte*) *page,(size_t) length); key+=length;
- if (keyseg->base.flag & HA_SPACE_PACK)
- *start= (uchar) ((key-start)-1);
- *page+=length;
- }
- length=keyseg->base.length+nod_flag;
- bmove((byte*) key,(byte*) *page,length);
- *page+=length;
- return((uint) (key-start_key)+keyseg->base.length);
-} /* _nisam_get_key */
-
-
- /* same as _nisam_get_key but used with fixed length keys */
-
-uint _nisam_get_static_key(register N_KEYDEF *keyinfo, uint nod_flag, register uchar **page, register uchar *key)
-{
- memcpy((byte*) key,(byte*) *page,
- (size_t) (keyinfo->base.keylength+nod_flag));
- *page+=keyinfo->base.keylength+nod_flag;
- return(keyinfo->base.keylength);
-} /* _nisam_get_static_key */
-
-
- /* Get last key from key-block, starting from keypos */
- /* Return pointer to where keystarts */
-
-uchar *_nisam_get_last_key(N_INFO *info, N_KEYDEF *keyinfo, uchar *keypos, uchar *lastkey, uchar *endpos)
-{
- uint nod_flag;
- uchar *lastpos;
-
- nod_flag=test_if_nod(keypos);
- if (! (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
- {
- lastpos=endpos-keyinfo->base.keylength-nod_flag;
- if (lastpos > keypos)
- bmove((byte*) lastkey,(byte*) lastpos,keyinfo->base.keylength+nod_flag);
- }
- else
- {
- lastpos=0 ; keypos+=2+nod_flag;
- lastkey[0]=0;
- while (keypos < endpos)
- {
- lastpos=keypos;
- VOID(_nisam_get_key(keyinfo,nod_flag,&keypos,lastkey));
- }
- }
- return lastpos;
-} /* _nisam_get_last_key */
-
-
- /* Calculate length of key */
-
-uint _nisam_keylength(N_KEYDEF *keyinfo, register uchar *key)
-{
- reg1 N_KEYSEG *keyseg;
- uchar *start;
-
- if (! (keyinfo->base.flag & HA_SPACE_PACK_USED))
- return (keyinfo->base.keylength);
-
- start=key;
- for (keyseg=keyinfo->seg ; keyseg->base.type ; keyseg++)
- {
- if (keyseg->base.flag & HA_SPACE_PACK)
- key+= *key+1;
- else
- key+= keyseg->base.length;
- }
- return((uint) (key-start)+keyseg->base.length);
-} /* _nisam_keylength */
-
-
- /* Move a key */
-
-uchar *_nisam_move_key(N_KEYDEF *keyinfo, uchar *to, uchar *from)
-{
- reg1 uint length;
- memcpy((byte*) to, (byte*) from,
- (size_t) (length=_nisam_keylength(keyinfo,from)));
- return to+length;
-}
-
- /* Find next/previous record with same key */
- /* This can't be used when database is touched after last read */
-
-int _nisam_search_next(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, uint nextflag, ulong pos)
-{
- int error;
- uint nod_flag;
- uchar lastkey[N_MAX_KEY_BUFF];
- DBUG_ENTER("_nisam_search_next");
- DBUG_PRINT("enter",("nextflag: %d lastpos: %d int_keypos: %lx",
- nextflag,info->lastpos,info->int_keypos));
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key););
-
- if ((nextflag & SEARCH_BIGGER && info->int_keypos >= info->int_maxpos) ||
- info->int_pos == NI_POS_ERROR || info->page_changed)
- DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- pos));
-
- if (info->buff_used)
- {
- if (!_nisam_fetch_keypage(info,keyinfo,info->last_search_keypage,
- info->buff,0))
- {
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
- info->buff_used=0;
- }
-
- /* Last used buffer is in info->buff */
-
- nod_flag=test_if_nod(info->buff);
- VOID(_nisam_move_key(keyinfo,lastkey,key));
-
- if (nextflag & SEARCH_BIGGER) /* Next key */
- {
- ulong tmp_pos=_nisam_kpos(nod_flag,info->int_keypos);
- if (tmp_pos != NI_POS_ERROR)
- {
- if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- tmp_pos)) <=0)
- DBUG_RETURN(error);
- }
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,lastkey));
- }
- else /* Previous key */
- {
- info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey,
- info->int_keypos);
- if (info->int_keypos == info->buff+2)
- DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- pos));
- if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- _nisam_kpos(nod_flag,info->int_keypos))) <= 0)
- DBUG_RETURN(error);
- }
-
- info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey,
- info->int_keypos);
- VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey));
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,info->lastkey));
- info->lastpos=_nisam_dpos(info,nod_flag,info->int_keypos);
- DBUG_PRINT("exit",("found key at %d",info->lastpos));
- DBUG_RETURN(0);
-} /* _nisam_search_next */
-
-
- /* S|ker reda p} positionen f|r f|rsta recordet i ett index */
- /* Positionen l{ggs i info->lastpos */
-
-int _nisam_search_first(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos)
-{
- uint nod_flag;
- uchar *page;
- DBUG_ENTER("_nisam_search_first");
-
- if (pos == NI_POS_ERROR)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND;
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
-
- do
- {
- if (!_nisam_fetch_keypage(info,keyinfo,pos,info->buff,0))
- {
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
- nod_flag=test_if_nod(info->buff);
- page=info->buff+2+nod_flag;
- } while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR);
-
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,info->lastkey));
- info->int_keypos=page; info->int_maxpos=info->buff+getint(info->buff)-1;
- info->lastpos=_nisam_dpos(info,nod_flag,page);
- info->page_changed=info->buff_used=0;
- info->last_search_keypage=info->int_pos;
-
- DBUG_PRINT("exit",("found key at %d",info->lastpos));
- DBUG_RETURN(0);
-} /* _nisam_search_first */
-
-
- /* S|ker reda p} positionen f|r sista recordet i ett index */
- /* Positionen l{ggs i info->lastpos */
-
-int _nisam_search_last(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos)
-{
- uint nod_flag;
- uchar *buff,*page;
- DBUG_ENTER("_nisam_search_last");
-
- if (pos == NI_POS_ERROR)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
-
- buff=info->buff;
- do
- {
- if (!_nisam_fetch_keypage(info,keyinfo,pos,buff,0))
- {
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
- page= buff+getint(buff);
- nod_flag=test_if_nod(buff);
- } while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR);
-
- VOID(_nisam_get_last_key(info,keyinfo,buff,info->lastkey,page));
- info->lastpos=_nisam_dpos(info,nod_flag,page);
- info->int_keypos=info->int_maxpos=page;
- info->page_changed=info->buff_used=0;
- info->last_search_keypage=info->int_pos;
-
- DBUG_PRINT("exit",("found key at %d",info->lastpos));
- DBUG_RETURN(0);
-} /* _nisam_search_last */
diff --git a/isam/_statrec.c b/isam/_statrec.c
deleted file mode 100644
index 9dbc948440f..00000000000
--- a/isam/_statrec.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
- /* Functions to handle fixed-length-records */
-
-#include "isamdef.h"
-
-
-int _nisam_write_static_record(N_INFO *info, const byte *record)
-{
- uchar temp[4]; /* Not sizeof(long) */
-
- if (info->s->state.dellink != NI_POS_ERROR)
- {
- ulong filepos=info->s->state.dellink;
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->s->state.dellink+1,MY_SEEK_SET,MYF(0)));
-
- if (my_read(info->dfile,(char*) &temp[0],sizeof(temp), MYF(MY_NABP)))
- goto err;
- info->s->state.dellink=uint4korr(temp);
- if (info->s->state.dellink == (uint32) ~0) /* Fix for 64 bit long */
- info->s->state.dellink=NI_POS_ERROR;
- info->s->state.del--;
- info->s->state.empty-=info->s->base.reclength;
- VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0)));
- if (my_write(info->dfile, (char*) record, info->s->base.reclength,
- MYF(MY_NABP)))
- goto err;
- }
- else
- {
- if (info->s->state.data_file_length > info->s->base.max_data_file_length)
- {
- my_errno=HA_ERR_RECORD_FILE_FULL;
- return(2);
- }
- if (info->opt_flag & WRITE_CACHE_USED)
- { /* Cash in use */
- if (my_b_write(&info->rec_cache, (byte*) record, info->s->base.reclength))
- goto err;
- }
- else
- {
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->s->state.data_file_length,
- MY_SEEK_SET,MYF(0)));
- if (my_write(info->dfile,(char*) record,info->s->base.reclength,
- MYF(MY_NABP | MY_WAIT_IF_FULL)))
- goto err;
- }
- info->s->state.data_file_length+=info->s->base.reclength;
- info->s->state.splitt++;
- }
- return 0;
- err:
- return 1;
-}
-
-int _nisam_update_static_record(N_INFO *info, ulong pos, const byte *record)
-{
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,pos,MY_SEEK_SET,MYF(0)));
- return (my_write(info->dfile,(char*) record,info->s->base.reclength,
- MYF(MY_NABP)) != 0);
-}
-
-
-int _nisam_delete_static_record(N_INFO *info)
-{
- uchar temp[5]; /* 1+sizeof(uint32) */
-
- info->s->state.del++;
- info->s->state.empty+=info->s->base.reclength;
- temp[0]= '\0'; /* Mark that record is deleted */
- int4store(temp+1,info->s->state.dellink);
- info->s->state.dellink = info->lastpos;
- info->rec_cache.seek_not_done=1;
- VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0)));
- return (my_write(info->dfile,(byte*) temp,(uint) sizeof(temp),
- MYF(MY_NABP)) != 0);
-}
-
-
-int _nisam_cmp_static_record(register N_INFO *info, register const byte *old)
-{
- DBUG_ENTER("_nisam_rectest");
-
- /* We are going to do changes; dont let anybody disturb */
- dont_break(); /* Dont allow SIGHUP or SIGINT */
-
- if (info->opt_flag & WRITE_CACHE_USED)
- {
- if (flush_io_cache(&info->rec_cache))
- {
- DBUG_RETURN(-1);
- }
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- }
-
- if ((info->opt_flag & READ_CHECK_USED))
- { /* If check isn't disabled */
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0)));
- if (my_read(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
- MYF(MY_NABP)))
- DBUG_RETURN(-1);
- if (memcmp((byte*) info->rec_buff, (byte*) old,
- (uint) info->s->base.reclength))
- {
- DBUG_DUMP("read",old,info->s->base.reclength);
- DBUG_DUMP("disk",info->rec_buff,info->s->base.reclength);
- my_errno=HA_ERR_RECORD_CHANGED; /* Record have changed */
- DBUG_RETURN(1);
- }
- }
- DBUG_RETURN(0);
-}
-
- /* Read a fixed-length-record */
- /* Returns 0 if Ok. */
- /* 1 if record is deleted */
- /* MY_FILE_ERROR on read-error or locking-error */
-
-int _nisam_read_static_record(register N_INFO *info, register ulong pos,
- register byte *record)
-{
- int error;
-
- if (pos != NI_POS_ERROR)
- {
- if (info->opt_flag & WRITE_CACHE_USED &&
- info->rec_cache.pos_in_file <= pos &&
- flush_io_cache(&info->rec_cache))
- return(-1);
- info->rec_cache.seek_not_done=1; /* We have done a seek */
-
- error=my_pread(info->dfile,(char*) record,info->s->base.reclength,
- pos,MYF(MY_NABP)) != 0;
- if (info->s->r_locks == 0 && info->s->w_locks == 0)
- VOID(_nisam_writeinfo(info,0));
- if (! error)
- {
- if (!*record) return(1); /* Record is deleted */
- info->update|= HA_STATE_AKTIV; /* Record is read */
- my_errno=HA_ERR_RECORD_DELETED;
- return(0);
- }
- return(-1); /* Error on read */
- }
- VOID(_nisam_writeinfo(info,0)); /* No such record */
- return(-1);
-} /* _nisam_read_record */
-
-
-int _nisam_read_rnd_static_record(N_INFO *info, byte *buf,
- register ulong filepos,
- int skipp_deleted_blocks)
-{
- int locked,error,cache_read;
- uint cache_length;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_read_rnd_static_record");
-
- cache_read=0;
- LINT_INIT(cache_length);
- if (info->opt_flag & WRITE_CACHE_USED &&
- (info->rec_cache.pos_in_file <= filepos || skipp_deleted_blocks) &&
- flush_io_cache(&info->rec_cache))
- DBUG_RETURN(-1);
- if (info->opt_flag & READ_CACHE_USED)
- { /* Cash in use */
- if (filepos == my_b_tell(&info->rec_cache) &&
- (skipp_deleted_blocks || !filepos))
- {
- cache_read=1; /* Read record using cache */
- cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
- }
- else
- info->rec_cache.seek_not_done=1; /* Filepos is changed */
- }
-#ifndef NO_LOCKING
- locked=0;
- if (info->lock_type == F_UNLCK)
- {
- if (filepos >= share->state.data_file_length)
- { /* Test if new records */
- if (_nisam_readinfo(info,F_RDLCK,0))
- DBUG_RETURN(-1);
- locked=1;
- }
- else
- { /* We don't nead new info */
-#ifndef UNSAFE_LOCKING
- if ((! cache_read || share->base.reclength > cache_length) &&
- share->r_locks == 0 && share->w_locks == 0)
- { /* record not in cache */
- if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
- DBUG_RETURN(-1);
- locked=1;
- }
-#else
- info->tmp_lock_type=F_RDLCK;
-#endif
- }
- }
-#endif
- if (filepos >= share->state.data_file_length)
- {
-#ifndef NO_LOCKING
- DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld",
- filepos/share->base.reclength,filepos,
- share->state.records, share->state.del));
- VOID(_nisam_writeinfo(info,0));
-#endif
- my_errno=HA_ERR_END_OF_FILE;
- DBUG_RETURN(-1);
- }
- info->lastpos= filepos;
- info->nextpos= filepos+share->base.reclength;
-
- if (! cache_read) /* No cacheing */
- {
- error=_nisam_read_static_record(info,filepos,buf);
- if (error > 0)
- my_errno=HA_ERR_RECORD_DELETED;
- DBUG_RETURN(error);
- }
-
- /* Read record with cacheing */
- error=my_b_read(&info->rec_cache,(byte*) buf,share->base.reclength);
-
-#ifndef NO_LOCKING
- if (locked)
- VOID(_nisam_writeinfo(info,0)); /* Unlock keyfile */
-#endif
- if (!error)
- {
- if (!buf[0])
- { /* Record is removed */
- my_errno=HA_ERR_RECORD_DELETED;
- DBUG_RETURN(1);
- }
- /* Found and may be updated */
- info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
- DBUG_RETURN(0);
- }
- if (info->rec_cache.error != -1 || my_errno == 0)
- my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(-1); /* Something wrong (EOF?) */
-}
diff --git a/isam/close.c b/isam/close.c
deleted file mode 100644
index 37425653a5d..00000000000
--- a/isam/close.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* close a isam-database */
-
-#include "isamdef.h"
-
-int nisam_close(register N_INFO *info)
-{
- int error=0,flag;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("nisam_close");
- DBUG_PRINT("enter",("base: %lx reopen: %u locks: %u",
- info,(uint) share->reopen,
- (uint) (share->w_locks+share->r_locks)));
-
- pthread_mutex_lock(&THR_LOCK_isam);
- if (info->lock_type == F_EXTRA_LCK)
- info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */
-
-#ifndef NO_LOCKING
- if (info->lock_type != F_UNLCK)
- VOID(nisam_lock_database(info,F_UNLCK));
-#else
- info->lock_type=F_UNLCK;
- share->w_locks--;
- if (_nisam_writeinfo(info,test(share->changed)))
- error=my_errno;
-#endif
- pthread_mutex_lock(&share->intern_lock);
-
- if (share->base.options & HA_OPTION_READ_ONLY_DATA)
- share->r_locks--;
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- {
- if (end_io_cache(&info->rec_cache))
- error=my_errno;
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- }
- flag= !--share->reopen;
- nisam_open_list=list_delete(nisam_open_list,&info->open_list);
- pthread_mutex_unlock(&share->intern_lock);
-
- if (flag)
- {
- if (share->kfile >= 0 &&
- flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE))
- error=my_errno;
- if (share->kfile >= 0 && my_close(share->kfile,MYF(0)))
- error = my_errno;
-#ifdef HAVE_MMAP
- _nisam_unmap_file(info);
-#endif
- if (share->decode_trees)
- {
- my_free((gptr) share->decode_trees,MYF(0));
- my_free((gptr) share->decode_tables,MYF(0));
- }
-#ifdef THREAD
- thr_lock_delete(&share->lock);
- VOID(pthread_mutex_destroy(&share->intern_lock));
-#endif
- my_free((gptr) info->s,MYF(0));
- }
- pthread_mutex_unlock(&THR_LOCK_isam);
- if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
- error = my_errno;
-
- nisam_log_command(LOG_CLOSE,info,NULL,0,error);
- my_free((gptr) info->rec_alloc,MYF(0));
- my_free((gptr) info,MYF(0));
-
- if (error)
- {
- my_errno=error;
- DBUG_RETURN(-1);
- }
- DBUG_RETURN(0);
-} /* nisam_close */
diff --git a/isam/create.c b/isam/create.c
deleted file mode 100644
index 204d3157d00..00000000000
--- a/isam/create.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Skapar en isam-databas */
-
-#include "isamdef.h"
-#if defined(MSDOS) || defined(__WIN__)
-#ifdef __WIN__
-#include <fcntl.h>
-#else
-#include <process.h> /* Prototype for getpid */
-#endif
-#endif
-
- /*
- ** Old options is used when recreating database, from isamchk
- ** Note that the minimun reclength that MySQL allows for static rows
- ** are 5. (Will be fixed in the next generation)
- */
-
-int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
- N_RECINFO *recinfo,
- ulong records,ulong reloc, uint flags,uint old_options,
- ulong data_file_length)
-{
- register uint i,j;
- File dfile,file;
- int errpos,save_errno;
- uint fields,length,max_key_length,packed,pointer,reclength,min_pack_length,
- key_length,info_length,key_segs,options,min_key_length_skipp,max_block,
- base_pos;
- char buff[max(FN_REFLEN,512)];
- ulong tot_length,pack_reclength;
- enum en_fieldtype type;
- ISAM_SHARE share;
- N_KEYDEF *keydef;
- N_KEYSEG *keyseg;
- N_RECINFO *rec;
- DBUG_ENTER("nisam_create");
-
- LINT_INIT(dfile);
- pthread_mutex_lock(&THR_LOCK_isam);
- errpos=0;
- options=0;
- base_pos=512; /* Enough for N_STATE_INFO */
- bzero((byte*) &share,sizeof(share));
- if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0,
- O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0)
- goto err;
- errpos=1;
- VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4));
- if (!(flags & HA_DONT_TOUCH_DATA))
- {
- if ((dfile = my_create(buff,0,O_RDWR | O_EXCL | O_NOFOLLOW,
- MYF(MY_WME))) < 0)
- goto err;
- errpos=2;
- }
- else if (!(old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
- options=old_options & (HA_OPTION_COMPRESS_RECORD |
- HA_OPTION_READ_ONLY_DATA | HA_OPTION_PACK_RECORD);
- if (reloc > records)
- reloc=records; /* Check if wrong parameter */
-
- /* Start by checking fields and field-types used */
- reclength=0;
- for (rec=recinfo, fields=packed=min_pack_length=0, pack_reclength=0L;
- rec->base.type != (int) FIELD_LAST;
- rec++,fields++)
- {
- reclength+=rec->base.length;
- if ((type=(enum en_fieldtype) rec->base.type))
- {
- packed++;
- if (type == FIELD_BLOB)
- {
- share.base.blobs++;
- rec->base.length-= sizeof(char*); /* Don't calc pointer */
- if (pack_reclength != NI_POS_ERROR)
- {
- if (rec->base.length == 4)
- pack_reclength= (ulong) NI_POS_ERROR;
- else
- pack_reclength+=sizeof(char*)+(1 << (rec->base.length*8));
- }
- }
- else if (type == FIELD_SKIP_PRESPACE ||
- type == FIELD_SKIP_ENDSPACE)
- {
- if (pack_reclength != NI_POS_ERROR)
- pack_reclength+= rec->base.length > 255 ? 2 : 1;
- min_pack_length++;
- }
- else if (type == FIELD_ZERO)
- packed--;
- else if (type != FIELD_SKIP_ZERO)
- {
- min_pack_length+=rec->base.length;
- packed--; /* Not a pack record type */
- }
- }
- else
- min_pack_length+=rec->base.length;
- }
- if ((packed & 7) == 1)
- { /* Bad packing, try to remove a zero-field */
- while (rec != recinfo)
- {
- rec--;
- if (rec->base.type == (int) FIELD_SKIP_ZERO && rec->base.length == 1)
- {
- rec->base.type=(int) FIELD_NORMAL;
- packed--;
- min_pack_length++;
- break;
- }
- }
- }
- if (packed && !(options & HA_OPTION_COMPRESS_RECORD))
- options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
-
- packed=(packed+7)/8;
- if (pack_reclength != NI_POS_ERROR)
- pack_reclength+= reclength+packed;
- min_pack_length+=packed;
-
- if (options & HA_OPTION_COMPRESS_RECORD)
- {
- if (data_file_length >= (1L << 24))
- pointer=4;
- else if (data_file_length >= (1L << 16))
- pointer=3;
- else
- pointer=2;
- }
- else if (((records == 0L && pack_reclength < 255) ||
- options & HA_OPTION_PACK_RECORD) ||
- records >= (ulong) 16000000L ||
- pack_reclength == (ulong) NI_POS_ERROR ||
- ((options & HA_OPTION_PACK_RECORD) &&
- pack_reclength+4 >= (ulong) 14000000L/records))
- pointer=4;
- else if (records == 0L || records >= (ulong) 65000L ||
- ((options & HA_OPTION_PACK_RECORD) &&
- pack_reclength+4 >= (ulong) 60000L/records))
- pointer=3;
- else
- pointer=2;
-
- max_block=max_key_length=0; tot_length=key_segs=0;
- for (i=0, keydef=keyinfo ; i < keys ; i++ , keydef++)
- {
- share.state.key_root[i]= share.state.key_del[i]= NI_POS_ERROR;
- share.base.rec_per_key[i]= (keydef->base.flag & HA_NOSAME) ? 1L : 0L;
- min_key_length_skipp=length=0;
- key_length=pointer;
-
- if (keydef->base.flag & HA_PACK_KEY &&
- keydef->seg[0].base.length > 127)
- keydef->base.flag&= ~HA_PACK_KEY; /* Can't pack long keys */
- if (keydef->base.flag & HA_PACK_KEY)
- {
- if ((keydef->seg[0].base.flag & HA_SPACE_PACK) &&
- keydef->seg[0].base.type == (int) HA_KEYTYPE_NUM)
- keydef->seg[0].base.flag&= ~HA_SPACE_PACK;
- if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
- length++;
- keydef->seg[0].base.flag|=HA_PACK_KEY; /* for easyer intern test */
- options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
- if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
- min_key_length_skipp+=keydef->seg[0].base.length;
- }
- keydef->base.keysegs=0;
- for (keyseg=keydef->seg ; keyseg->base.type ; keyseg++)
- {
- keydef->base.keysegs++;
- if (keyseg->base.length > 127)
- keyseg->base.flag&= ~(HA_SPACE_PACK | HA_PACK_KEY);
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- keydef->base.flag |= HA_SPACE_PACK_USED;
- options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
- length++;
- min_key_length_skipp+=keyseg->base.length;
- }
- key_length+= keyseg->base.length;
- }
- bzero((gptr) keyseg,sizeof(keyseg[0]));
- keyseg->base.length=(uint16) pointer; /* Last key part is pointer */
- key_segs+=keydef->base.keysegs;
- length+=key_length;
- keydef->base.block_length=nisam_block_size;
- keydef->base.keylength= (uint16) key_length;
- keydef->base.minlength= (uint16) (length-min_key_length_skipp);
- keydef->base.maxlength= (uint16) length;
-
- if ((uint) keydef->base.block_length > max_block)
- max_block=(uint) keydef->base.block_length;
- if (length > max_key_length)
- max_key_length= length;
- tot_length+= (records/(ulong) (((uint) keydef->base.block_length-5)/
- (length*2)))*
- (ulong) keydef->base.block_length;
- }
- info_length=(uint) (base_pos+sizeof(N_BASE_INFO)+keys*sizeof(N_SAVE_KEYDEF)+
- (keys+key_segs)*sizeof(N_SAVE_KEYSEG)+
- fields*sizeof(N_SAVE_RECINFO));
-
- bmove(share.state.header.file_version,(byte*) nisam_file_magic,4);
- old_options=options| (old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
- HA_OPTION_COMPRESS_RECORD |
- HA_OPTION_TEMP_COMPRESS_RECORD: 0);
- int2store(share.state.header.options,old_options);
- int2store(share.state.header.header_length,info_length);
- int2store(share.state.header.state_info_length,sizeof(N_STATE_INFO));
- int2store(share.state.header.base_info_length,sizeof(N_BASE_INFO));
- int2store(share.state.header.base_pos,base_pos);
-
- share.state.dellink = NI_POS_ERROR;
- share.state.process= (ulong) getpid();
- share.state.uniq= (ulong) file;
- share.state.loop= 0;
- share.state.version= (ulong) time((time_t*) 0);
- share.base.options=options;
- share.base.rec_reflength=pointer;
- share.base.key_reflength=((!tot_length || tot_length > 30000000L) ? 3 :
- tot_length > 120000L ? 2 : 1);
- share.base.keys= share.state.keys = keys;
- share.base.keystart = share.state.key_file_length=MY_ALIGN(info_length,
- nisam_block_size);
- share.base.max_block=max_block;
- share.base.max_key_length=(uint) ALIGN_SIZE(max_key_length+4);
- share.base.records=records;
- share.base.reloc=reloc;
- share.base.reclength=reclength;
- share.base.pack_reclength=
- (uint) (reclength+packed-share.base.blobs*sizeof(char*));
- share.base.max_pack_length=pack_reclength;
- share.base.min_pack_length=min_pack_length;
- share.base.pack_bits=packed;
- share.base.fields=fields;
- share.base.pack_fields=packed;
- share.base.sortkey= (ushort) ~0;
- share.base.max_data_file_length= (pointer == 4) ? (ulong) ~0L :
- (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
- (ulong) (1L << (pointer*8)) :
- (pointer == 3 && reclength >= 256L) ? (ulong) NI_POS_ERROR :
- ((ulong) reclength * (1L << (pointer*8)));
- share.base.max_key_file_length= (share.base.key_reflength == 3 ?
- NI_POS_ERROR :
- (ulong)
- (1L << (share.base.key_reflength*8))*512);
- share.base.min_block_length=
- (share.base.pack_reclength+3 < N_EXTEND_BLOCK_LENGTH &&
- ! share.base.blobs) ?
- max(share.base.pack_reclength,N_MIN_BLOCK_LENGTH) :
- N_EXTEND_BLOCK_LENGTH;
- if (! (flags & HA_DONT_TOUCH_DATA))
- share.base.create_time= (long) time((time_t*) 0);
-
- bzero(buff,base_pos);
- if (my_write(file,(char*) &share.state,sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
- my_write(file,buff,base_pos-sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
- my_write(file,(char*) &share.base,sizeof(N_BASE_INFO),MYF(MY_NABP)))
- goto err;
-
- for (i=0 ; i < share.base.keys ; i++)
- {
- if (my_write(file,(char*) &keyinfo[i].base,sizeof(N_SAVE_KEYDEF),
- MYF(MY_NABP)))
- goto err;
- for (j=0 ; j <= keyinfo[i].base.keysegs ; j++)
- {
- if (my_write(file,(char*) &keyinfo[i].seg[j].base,sizeof(N_SAVE_KEYSEG),
- MYF(MY_NABP)))
- goto err;
- }
- }
- for (i=0 ; i < share.base.fields ; i++)
- if (my_write(file,(char*) &recinfo[i].base, (uint) sizeof(N_SAVE_RECINFO),
- MYF(MY_NABP)))
- goto err;
-
- /* Enlarge files */
- if (my_chsize(file, (ulong) share.base.keystart, 0, MYF(0)))
- goto err;
-
- if (! (flags & HA_DONT_TOUCH_DATA))
- {
-#ifdef USE_RELOC
- if (my_chsize(dfile, share.base.min_pack_length*reloc, 0, MYF(0)))
- goto err;
-#endif
- errpos=1;
- if (my_close(dfile,MYF(0)))
- goto err;
- }
- errpos=0;
- pthread_mutex_unlock(&THR_LOCK_isam);
- if (my_close(file,MYF(0)))
- goto err;
- DBUG_RETURN(0);
-
-err:
- pthread_mutex_unlock(&THR_LOCK_isam);
- save_errno=my_errno;
- switch (errpos) {
- case 2:
- VOID(my_close(dfile,MYF(0)));
- /* fall through */
- case 1:
- VOID(my_close(file,MYF(0)));
- }
- my_errno=save_errno; /* R{tt felkod tillbaka */
- DBUG_RETURN(-1);
-} /* nisam_create */
diff --git a/isam/delete.c b/isam/delete.c
deleted file mode 100644
index 5aa542561c1..00000000000
--- a/isam/delete.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Tar bort ett record fr}n en isam-databas */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-#include <assert.h>
-
-static int d_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,ulong page,
- uchar *anc_buff);
-static int del(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uchar *anc_buff,
- ulong leaf_page,uchar *leaf_buff,uchar *keypos,
- ulong next_block,uchar *ret_key);
-static int underflow(N_INFO *info,N_KEYDEF *keyinfo,uchar *anc_buff,
- ulong leaf_page, uchar *leaf_buff,uchar *keypos);
-static uint remove_key(N_KEYDEF *keyinfo,uint nod_flag,uchar *keypos,
- uchar *lastkey,uchar *page_end);
-
-
-int nisam_delete(N_INFO *info,const byte *record)
-{
- uint i;
- uchar *old_key;
- int save_errno;
- uint32 lastpos;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("nisam_delete");
-
- /* Test if record is in datafile */
-
- if (!(info->update & HA_STATE_AKTIV))
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* No database read */
- DBUG_RETURN(-1);
- }
- if (share->base.options & HA_OPTION_READ_ONLY_DATA)
- {
- my_errno=EACCES;
- DBUG_RETURN(-1);
- }
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
-#endif
- if ((*share->compare_record)(info,record))
- goto err; /* Fel vid kontroll-l{sning */
-
- /* Remove all keys from the .ISAM file */
-
- old_key=info->lastkey+share->base.max_key_length;
- for (i=0 ; i < share->state.keys ; i++ )
- {
- VOID(_nisam_make_key(info,i,old_key,record,info->lastpos));
- if (_nisam_ck_delete(info,i,old_key)) goto err;
- }
-
- if ((*share->delete_record)(info))
- goto err; /* Remove record from database */
-
- info->update= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_DELETED;
- share->state.records--;
-
- lastpos= (uint32) info->lastpos;
- nisam_log_command(LOG_DELETE,info,(byte*) &lastpos,sizeof(lastpos),0);
- VOID(_nisam_writeinfo(info,1));
- allow_break(); /* Allow SIGHUP & SIGINT */
- DBUG_RETURN(0);
-
-err:
- save_errno=my_errno;
- lastpos= (uint32) info->lastpos;
- nisam_log_command(LOG_DELETE,info,(byte*) &lastpos, sizeof(lastpos),0);
- VOID(_nisam_writeinfo(info,1));
- info->update|=HA_STATE_WRITTEN; /* Buffer changed */
- allow_break(); /* Allow SIGHUP & SIGINT */
- my_errno=save_errno;
- if (save_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_CRASHED;
-
- DBUG_RETURN(-1);
-} /* nisam_delete */
-
-
- /* Tar bort en nyckel till isam-nyckelfilen */
-
-int _nisam_ck_delete(register N_INFO *info, uint keynr, uchar *key)
-{
- int error;
- uint nod_flag;
- ulong old_root;
- uchar *root_buff;
- N_KEYDEF *keyinfo;
- DBUG_ENTER("_nisam_ck_delete");
-
- if ((old_root=info->s->state.key_root[keynr]) == NI_POS_ERROR)
- {
- my_errno=HA_ERR_CRASHED;
- DBUG_RETURN(-1);
- }
- keyinfo=info->s->keyinfo+keynr;
- if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
- N_MAX_KEY_BUFF*2)))
- DBUG_RETURN(-1);
- if (!_nisam_fetch_keypage(info,keyinfo,old_root,root_buff,0))
- {
- error= -1;
- goto err;
- }
- if ((error=d_search(info,keyinfo,key,old_root,root_buff)) >0)
- {
- if (error == 2)
- {
- DBUG_PRINT("test",("Enlarging of root when deleting"));
- error=_nisam_enlarge_root(info,keynr,key);
- }
- else
- {
- error=0;
- if (getint(root_buff) <= (nod_flag=test_if_nod(root_buff))+3)
- {
- if (nod_flag)
- info->s->state.key_root[keynr]=_nisam_kpos(nod_flag,
- root_buff+2+nod_flag);
- else
- info->s->state.key_root[keynr]= NI_POS_ERROR;
- if (_nisam_dispose(info,keyinfo,old_root))
- error= -1;
- }
- }
- }
-err:
- my_afree((gptr) root_buff);
- DBUG_RETURN(error);
-} /* _nisam_ck_delete */
-
-
- /* Tar bort en nyckel under root */
- /* Returnerar 1 om nuvarande buffert minskade */
- /* Returnerar 2 om nuvarande buffert |kar */
-
-static int d_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, ulong page, uchar *anc_buff)
-{
- int flag,ret_value,save_flag;
- uint length,nod_flag;
- uchar *leaf_buff,*keypos,*next_keypos;
- ulong leaf_page,next_block;
- uchar lastkey[N_MAX_KEY_BUFF];
- DBUG_ENTER("d_search");
- DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff));
-
- flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,0,SEARCH_SAME,&keypos,
- lastkey);
- nod_flag=test_if_nod(anc_buff);
-
- leaf_buff=0;
- LINT_INIT(leaf_page);
- if (nod_flag)
- {
- leaf_page=_nisam_kpos(nod_flag,keypos);
- if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
- N_MAX_KEY_BUFF*2)))
- {
- my_errno=ENOMEM;
- DBUG_RETURN(-1);
- }
- if (!_nisam_fetch_keypage(info,keyinfo,leaf_page,leaf_buff,0))
- goto err;
- }
-
- if (flag != 0)
- {
- if (!nod_flag)
- {
- my_errno=HA_ERR_CRASHED; /* This should newer happend */
- goto err;
- }
- save_flag=0;
- ret_value=d_search(info,keyinfo,key,leaf_page,leaf_buff);
- }
- else
- { /* Found key */
- next_keypos=keypos; /* Find where next block is */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&next_keypos,lastkey));
- next_block=_nisam_kpos(nod_flag,next_keypos);
- length=getint(anc_buff);
- length-= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length);
- putint(anc_buff,length,nod_flag);
- if (!nod_flag)
- { /* On leaf page */
- if (_nisam_write_keypage(info,keyinfo,page,anc_buff))
- DBUG_RETURN(-1);
- DBUG_RETURN(length <= (uint) keyinfo->base.block_length/2);
- }
- save_flag=1;
- ret_value=del(info,keyinfo,key,anc_buff,leaf_page,leaf_buff,keypos,
- next_block,lastkey);
- }
- if (ret_value >0)
- {
- save_flag=1;
- if (ret_value == 1)
- ret_value= underflow(info,keyinfo,anc_buff,leaf_page,leaf_buff,keypos);
- else
- { /* This happens only with packed keys */
- DBUG_PRINT("test",("Enlarging of key when deleting"));
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,lastkey,keypos));
- ret_value=_nisam_insert(info,keyinfo,key,anc_buff,keypos,lastkey,
- (uchar*) 0,(uchar*) 0,0L);
- }
- }
- if (ret_value == 0 && getint(anc_buff) > keyinfo->base.block_length)
- {
- save_flag=1;
- ret_value=_nisam_splitt_page(info,keyinfo,key,anc_buff,lastkey) | 2;
- }
- if (save_flag)
- ret_value|=_nisam_write_keypage(info,keyinfo,page,anc_buff);
- else
- {
- DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff));
- }
- my_afree((byte*) leaf_buff);
- DBUG_RETURN(ret_value);
-err:
- my_afree((byte*) leaf_buff);
- DBUG_PRINT("exit",("Error: %d",my_errno));
- DBUG_RETURN (-1);
-} /* d_search */
-
-
- /* Remove a key that has a page-reference */
-
-static int del(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key,
- uchar *anc_buff, ulong leaf_page, uchar *leaf_buff,
- uchar *keypos, /* Pos to where deleted key was */
- ulong next_block,
- uchar *ret_key) /* key before keypos in anc_buff */
-{
- int ret_value,length;
- uint a_length,nod_flag;
- ulong next_page;
- uchar keybuff[N_MAX_KEY_BUFF],*endpos,*next_buff,*key_start;
- ISAM_SHARE *share=info->s;
- S_PARAM s_temp;
- DBUG_ENTER("del");
- DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos));
- DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff));
-
- endpos=leaf_buff+getint(leaf_buff);
- key_start=_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos);
-
- if ((nod_flag=test_if_nod(leaf_buff)))
- {
- next_page= _nisam_kpos(nod_flag,endpos);
- if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
- N_MAX_KEY_BUFF)))
- DBUG_RETURN(-1);
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,next_buff,0))
- ret_value= -1;
- else
- {
- DBUG_DUMP("next_page",(byte*) next_buff,getint(next_buff));
- if ((ret_value=del(info,keyinfo,key,anc_buff,next_page,next_buff,
- keypos,next_block,ret_key)) >0)
- {
- endpos=leaf_buff+getint(leaf_buff);
- if (ret_value == 1)
- {
- ret_value=underflow(info,keyinfo,leaf_buff,next_page,
- next_buff,endpos);
- if (ret_value == 0 && getint(leaf_buff) > keyinfo->base.block_length)
- {
- ret_value=_nisam_splitt_page(info,keyinfo,key,leaf_buff,ret_key) | 2;
- }
- }
- else
- {
- DBUG_PRINT("test",("Inserting of key when deleting"));
- VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos));
- ret_value=_nisam_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
- (uchar*) 0,(uchar*) 0,0L);
- }
- }
- if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
- goto err;
- }
- my_afree((byte*) next_buff);
- DBUG_RETURN(ret_value);
- }
-
- /* Remove last key from leaf page */
-
- putint(leaf_buff,key_start-leaf_buff,nod_flag);
- if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
- goto err;
-
- /* Place last key in ancestor page on deleted key position */
-
- a_length=getint(anc_buff);
- endpos=anc_buff+a_length;
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,ret_key,keypos));
- length=_nisam_get_pack_key_length(keyinfo,share->base.key_reflength,
- keypos == endpos ? (uchar*) 0 : keypos,
- ret_key,keybuff,&s_temp);
- if (length > 0)
- bmove_upp((byte*) endpos+length,(byte*) endpos,(uint) (endpos-keypos));
- else
- bmove(keypos,keypos-length, (int) (endpos-keypos)+length);
- _nisam_store_key(keyinfo,keypos,&s_temp);
- /* Save pointer to next leaf */
- VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key));
- _nisam_kpointer(info,keypos - share->base.key_reflength,next_block);
- putint(anc_buff,a_length+length,share->base.key_reflength);
-
- DBUG_RETURN( getint(leaf_buff) <= (uint) keyinfo->base.block_length/2 );
-err:
- DBUG_RETURN(-1);
-} /* del */
-
-
- /* Balances adjacent pages if underflow occours */
-
-static int underflow(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *anc_buff,
- ulong leaf_page, /* Ancestor page and underflow page */
- uchar *leaf_buff,
- uchar *keypos) /* Position to pos after key */
-{
- int t_length;
- uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag;
- ulong next_page;
- uchar anc_key[N_MAX_KEY_BUFF],leaf_key[N_MAX_KEY_BUFF],
- *buff,*endpos,*next_keypos,*half_pos,*temp_pos;
- S_PARAM s_temp;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("underflow");
- DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos));
- DBUG_DUMP("anc_buff",(byte*) anc_buff,getint(anc_buff));
- DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff));
-
- buff=info->buff;
- next_keypos=keypos;
- nod_flag=test_if_nod(leaf_buff);
- p_length=2+nod_flag;
- anc_length=getint(anc_buff);
- leaf_length=getint(leaf_buff);
- info->page_changed=1;
-
- if ((keypos < anc_buff+anc_length && (share->rnd++ & 1)) ||
- keypos == anc_buff+2+share->base.key_reflength)
- { /* Use page right of anc-page */
- DBUG_PRINT("test",("use right page"));
-
- VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos,
- buff));
- next_page= _nisam_kpos(share->base.key_reflength,next_keypos);
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0))
- goto err;
- buff_length=getint(buff);
- DBUG_DUMP("next",(byte*) buff,buff_length);
-
- /* find keys to make a big key-page */
- bmove((byte*) next_keypos-share->base.key_reflength,(byte*) buff+2,
- share->base.key_reflength);
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos));
- VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,leaf_key,
- leaf_buff+leaf_length));
-
- /* merge pages and put parting key from anc_buff between */
- t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,buff+p_length,
- (leaf_length == nod_flag+2 ?
- (uchar*) 0 : leaf_key),
- anc_key,&s_temp);
- length=buff_length-p_length;
- endpos=buff+length+leaf_length+t_length;
- bmove_upp((byte*) endpos, (byte*) buff+buff_length,length);
- memcpy((byte*) buff, (byte*) leaf_buff,(size_t) leaf_length);
- _nisam_store_key(keyinfo,buff+leaf_length,&s_temp);
- buff_length=(uint) (endpos-buff);
- putint(buff,buff_length,nod_flag);
-
- /* remove key from anc_buff */
-
- s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key,
- anc_buff+anc_length);
- putint(anc_buff,(anc_length-=s_length),share->base.key_reflength);
-
- if (buff_length <= keyinfo->base.block_length)
- { /* Keys in one page */
- memcpy((byte*) leaf_buff,(byte*) buff,(size_t) buff_length);
- if (_nisam_dispose(info,keyinfo,next_page))
- goto err;
- }
- else
- { /* Page is full */
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos));
- half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key);
- length=(uint) (half_pos-buff);
- memcpy((byte*) leaf_buff,(byte*) buff,(size_t) length);
- putint(leaf_buff,length,nod_flag);
- endpos=anc_buff+anc_length;
-
- /* Correct new keypointer to leaf_page */
- length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key);
- _nisam_kpointer(info,leaf_key+length,next_page);
- /* Save key in anc_buff */
- t_length=(int) _nisam_get_pack_key_length(keyinfo,
- share->base.key_reflength,
- keypos == endpos ?
- (uchar*) 0 : keypos,
- anc_key,leaf_key,&s_temp);
- if (t_length >= 0)
- bmove_upp((byte*) endpos+t_length,(byte*) endpos,
- (uint) (endpos-keypos));
- else
- bmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length);
- _nisam_store_key(keyinfo,keypos,&s_temp);
- putint(anc_buff,(anc_length+=t_length),share->base.key_reflength);
-
- /* Store new page */
- if (nod_flag)
- bmove((byte*) buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag);
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key));
- t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0,
- (uchar*) 0, leaf_key,&s_temp);
- s_temp.n_length= *half_pos; /* For _nisam_store_key */
- length=(uint) ((buff+getint(buff))-half_pos);
- bmove((byte*) buff+p_length+t_length,(byte*) half_pos,(size_t) length);
- _nisam_store_key(keyinfo,buff+p_length,&s_temp);
- putint(buff,length+t_length+p_length,nod_flag);
-
- if (_nisam_write_keypage(info,keyinfo,next_page,buff))
- goto err;
- }
- if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
- goto err;
- DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2);
- }
-
- DBUG_PRINT("test",("use left page"));
-
- keypos=_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos);
- next_page= _nisam_kpos(share->base.key_reflength,keypos);
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0))
- goto err;
- buff_length=getint(buff);
- endpos=buff+buff_length;
- DBUG_DUMP("prev",(byte*) buff,buff_length);
-
- /* find keys to make a big key-page */
- bmove((byte*) next_keypos - share->base.key_reflength,(byte*) leaf_buff+2,
- share->base.key_reflength);
- next_keypos=keypos;
- VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos,
- anc_key));
- VOID(_nisam_get_last_key(info,keyinfo,buff,leaf_key,endpos));
-
- /* merge pages and put parting key from anc_buff between */
- t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,
- leaf_buff+p_length,
- (leaf_length == nod_flag+2 ?
- (uchar*) 0 : leaf_key),
- anc_key,&s_temp);
- if (t_length >= 0)
- bmove((byte*) endpos+t_length,(byte*) leaf_buff+p_length,
- (size_t) (leaf_length-p_length));
- else /* We gained space */
- bmove((byte*) endpos,(byte*) leaf_buff+((int) p_length-t_length),
- (size_t) (leaf_length-p_length+t_length));
-
- _nisam_store_key(keyinfo,endpos,&s_temp);
- buff_length=buff_length+leaf_length-p_length+t_length;
- putint(buff,buff_length,nod_flag);
-
- /* remove key from anc_buff */
- s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key,
- anc_buff+anc_length);
- putint(anc_buff,(anc_length-=s_length),share->base.key_reflength);
-
- if (buff_length <= keyinfo->base.block_length)
- { /* Keys in one page */
- if (_nisam_dispose(info,keyinfo,leaf_page))
- goto err;
- }
- else
- { /* Page is full */
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos));
- endpos=half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key);
-
- /* Correct new keypointer to leaf_page */
- length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key);
- _nisam_kpointer(info,leaf_key+length,leaf_page);
- /* Save key in anc_buff */
- DBUG_DUMP("anc_buff",(byte*) anc_buff,anc_length);
- DBUG_DUMP("key",(byte*) leaf_key,16);
-
- temp_pos=anc_buff+anc_length;
- t_length=(int) _nisam_get_pack_key_length(keyinfo,
- share->base.key_reflength,
- keypos == temp_pos ? (uchar*) 0
- : keypos,
- anc_key,leaf_key,&s_temp);
- if (t_length > 0)
- bmove_upp((byte*) temp_pos+t_length,(byte*) temp_pos,
- (uint) (temp_pos-keypos));
- else
- bmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length);
- _nisam_store_key(keyinfo,keypos,&s_temp);
- putint(anc_buff,(anc_length+=t_length),share->base.key_reflength);
-
- /* Store new page */
- if (nod_flag)
- bmove((byte*) leaf_buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag);
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key));
- t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag, (uchar*) 0,
- (uchar*) 0, leaf_key, &s_temp);
- s_temp.n_length= *half_pos; /* For _nisam_store_key */
- length=(uint) ((buff+buff_length)-half_pos);
- bmove((byte*) leaf_buff+p_length+t_length,(byte*) half_pos,
- (size_t) length);
- _nisam_store_key(keyinfo,leaf_buff+p_length,&s_temp);
- putint(leaf_buff,length+t_length+p_length,nod_flag);
- putint(buff,endpos-buff,nod_flag);
- if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
- goto err;
- }
- if (_nisam_write_keypage(info,keyinfo,next_page,buff))
- goto err;
- DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2);
-err:
- DBUG_RETURN(-1);
-} /* underflow */
-
-
- /* remove a key from packed buffert */
- /* returns how many chars was removed */
-
-static uint remove_key(N_KEYDEF *keyinfo, uint nod_flag,
- uchar *keypos, /* Where key starts */
- uchar *lastkey, /* key to be removed */
- uchar *page_end) /* End of page */
-{
- int r_length,s_length,first,diff_flag;
- uchar *start;
- DBUG_ENTER("remove_key");
- DBUG_PRINT("enter",("keypos: %lx page_end: %lx",keypos,page_end));
-
- start=keypos;
- if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
- s_length=(int) (keyinfo->base.keylength+nod_flag);
- else
- { /* Let keypos point at next key */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey));
- s_length=(uint) (keypos-start);
- if (keyinfo->base.flag & HA_PACK_KEY)
- {
- diff_flag= (keyinfo->seg[0].base.flag & HA_SPACE_PACK);
- first= *start;
- if (keypos != page_end && *keypos & 128 && first != 128)
- { /* Referens length */
- if ((r_length= *keypos++ & 127) == 0)
- { /* Same key after */
- if (first & 128)
- start++; /* Skip ref length */
- if (diff_flag)
- start+= *start+1; /* Skip key length */
- else
- start+=keyinfo->seg[0].base.length- (first & 127);
- s_length=(uint)(keypos-start); /* Remove pntrs and next-key-flag */
- }
- else if (! (first & 128))
- { /* Deleted key was not compressed */
- if (diff_flag)
- {
- *start= (uchar) (r_length+ *keypos);
- start+=r_length+1; /* Let ref-part remain */
- s_length=(uint) (keypos-start)+1; /* Skip everything between */
- }
- else
- {
- start+=r_length+1; /* Let ref-part remain */
- s_length=(uint) (keypos-start); /* Skip everything between */
- }
- }
- else if ((first & 127) < r_length)
- { /* mid-part of key is used */
- r_length-=(first & 127);
- start++; /* Ref remains the same */
- if (diff_flag)
- *start++= (uchar) (*keypos++ + r_length);
- start+= r_length;
- s_length=(uint) (keypos-start); /* Skip everything between */
- }
- }
- }
- }
- bmove((byte*) start,(byte*) start+s_length,
- (uint) (page_end-start-s_length));
- DBUG_RETURN((uint) s_length);
-} /* remove_key */
diff --git a/isam/extra.c b/isam/extra.c
deleted file mode 100644
index 0d15cd948bb..00000000000
--- a/isam/extra.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Extra functions we want to do with a database */
-/* - Set flags for quicker databasehandler */
-/* - Set databasehandler to normal */
-/* - Reset recordpointers as after open database */
-
-#include "isamdef.h"
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* set extra flags for database */
-
-int nisam_extra(N_INFO *info, enum ha_extra_function function)
-{
- int error=0;
- DBUG_ENTER("nisam_extra");
-
- switch (function) {
- case HA_EXTRA_RESET:
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- {
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- error=end_io_cache(&info->rec_cache);
- }
- info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
-
- case HA_EXTRA_RESET_STATE:
- info->lastinx= 0; /* Use first index as def */
- info->int_pos=info->lastpos= NI_POS_ERROR;
- info->page_changed=1;
- /* Next/prev gives first/last */
- if (info->opt_flag & READ_CACHE_USED)
- {
- VOID(flush_io_cache(&info->rec_cache));
- reinit_io_cache(&info->rec_cache,READ_CACHE,0,
- (pbool) (info->lock_type != F_UNLCK),
- (pbool) test(info->update & HA_STATE_ROW_CHANGED));
- }
- info->update=((info->update & HA_STATE_CHANGED) |
- HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
- break;
- case HA_EXTRA_CACHE:
-#ifndef NO_LOCKING
- if (info->lock_type == F_UNLCK && (info->options & HA_OPTION_PACK_RECORD))
- {
- error=1; /* Not possibly if not locked */
- my_errno=EACCES;
- break;
- }
-#endif
-#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
- if ((info->options & HA_OPTION_COMPRESS_RECORD))
- {
- pthread_mutex_lock(&info->s->intern_lock);
- if (_nisam_memmap_file(info))
- {
- /* We don't nead MADV_SEQUENTIAL if small file */
- madvise(info->s->file_map,info->s->state.data_file_length,
- info->s->state.data_file_length <= RECORD_CACHE_SIZE*16 ?
- MADV_RANDOM : MADV_SEQUENTIAL);
- pthread_mutex_unlock(&info->s->intern_lock);
- break;
- }
- pthread_mutex_unlock(&info->s->intern_lock);
- }
-#endif
- if (info->opt_flag & WRITE_CACHE_USED)
- {
- info->opt_flag&= ~WRITE_CACHE_USED;
- if ((error=end_io_cache(&info->rec_cache)))
- break;
- }
- if (!(info->opt_flag &
- (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
- {
- if (!(init_io_cache(&info->rec_cache,info->dfile,
- (uint) min(info->s->state.data_file_length+1,
- my_default_record_cache_size),
- READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
- MYF(MY_WAIT_IF_FULL))))
- {
- info->opt_flag|=READ_CACHE_USED;
- info->update&= ~HA_STATE_ROW_CHANGED;
- }
- /* info->rec_cache.end_of_file=info->s->state.data_file_length; */
- }
- break;
- case HA_EXTRA_REINIT_CACHE:
- if (info->opt_flag & READ_CACHE_USED)
- {
- reinit_io_cache(&info->rec_cache,READ_CACHE,info->nextpos,
- (pbool) (info->lock_type != F_UNLCK),
- (pbool) test(info->update & HA_STATE_ROW_CHANGED));
- info->update&= ~HA_STATE_ROW_CHANGED;
- /* info->rec_cache.end_of_file=info->s->state.data_file_length; */
- }
- break;
- case HA_EXTRA_WRITE_CACHE:
-#ifndef NO_LOCKING
- if (info->lock_type == F_UNLCK)
- {
- error=1; /* Not possibly if not locked */
- break;
- }
-#endif
- if (!(info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)))
- {
- if (!(init_io_cache(&info->rec_cache,info->dfile,0,
- WRITE_CACHE,info->s->state.data_file_length,
- (pbool) (info->lock_type != F_UNLCK),
- MYF(MY_WAIT_IF_FULL))))
- {
- info->opt_flag|=WRITE_CACHE_USED;
- info->update&= ~HA_STATE_ROW_CHANGED;
- }
- }
- break;
- case HA_EXTRA_PREPARE_FOR_UPDATE:
- if (info->s->data_file_type != DYNAMIC_RECORD)
- break;
- /* Remove read/write cache if dynamic rows */
- case HA_EXTRA_NO_CACHE:
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- {
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- error=end_io_cache(&info->rec_cache);
- }
-#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
- if (info->opt_flag & MEMMAP_USED)
- madvise(info->s->file_map,info->s->state.data_file_length,MADV_RANDOM);
-#endif
- break;
- case HA_EXTRA_FLUSH_CACHE:
- if (info->opt_flag & WRITE_CACHE_USED)
- error=flush_io_cache(&info->rec_cache);
- break;
- case HA_EXTRA_NO_READCHECK:
- info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */
- break;
- case HA_EXTRA_READCHECK:
- info->opt_flag|= READ_CHECK_USED;
- break;
- case HA_EXTRA_KEYREAD: /* Read only keys to record */
- case HA_EXTRA_REMEMBER_POS:
- info->opt_flag |= REMEMBER_OLD_POS;
- bmove((byte*) info->lastkey+info->s->base.max_key_length*2,
- (byte*) info->lastkey,info->s->base.max_key_length);
- info->save_update= info->update;
- info->save_lastinx= info->lastinx;
- info->save_lastpos= info->lastpos;
- if (function == HA_EXTRA_REMEMBER_POS)
- break;
- /* fall through */
- case HA_EXTRA_KEYREAD_CHANGE_POS:
- info->opt_flag |= KEY_READ_USED;
- info->read_record=_nisam_read_key_record;
- break;
- case HA_EXTRA_NO_KEYREAD:
- case HA_EXTRA_RESTORE_POS:
- if (info->opt_flag & REMEMBER_OLD_POS)
- {
- bmove((byte*) info->lastkey,
- (byte*) info->lastkey+info->s->base.max_key_length*2,
- info->s->base.max_key_length);
- info->update= info->save_update | HA_STATE_WRITTEN;
- info->lastinx= info->save_lastinx;
- info->lastpos= info->save_lastpos;
- }
- info->read_record= info->s->read_record;
- info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
- break;
- case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
- info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
- break;
- case HA_EXTRA_WAIT_LOCK:
- info->lock_wait=0;
- break;
- case HA_EXTRA_NO_WAIT_LOCK:
- info->lock_wait=MY_DONT_WAIT;
- break;
- case HA_EXTRA_NO_KEYS:
-#ifndef NO_LOCKING
- if (info->lock_type == F_UNLCK)
- {
- error=1; /* Not possibly if not lock */
- break;
- }
-#endif
- info->s->state.keys=0;
- info->s->state.key_file_length=info->s->base.keystart;
- info->s->changed=1; /* Update on close */
- break;
- case HA_EXTRA_FORCE_REOPEN:
- case HA_EXTRA_PREPARE_FOR_DELETE:
- pthread_mutex_lock(&THR_LOCK_isam);
- info->s->last_version= 0L; /* Impossible version */
-#ifdef __WIN__
- /* Close the isam and data files as Win32 can't drop an open table */
- if (flush_key_blocks(dflt_key_cache, info->s->kfile, FLUSH_RELEASE))
- error=my_errno;
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- {
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- error=end_io_cache(&info->rec_cache);
- }
- if (info->lock_type != F_UNLCK && ! info->was_locked)
- {
- info->was_locked=info->lock_type;
- if (nisam_lock_database(info,F_UNLCK))
- error=my_errno;
- }
- if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0)))
- error=my_errno;
- {
- LIST *list_element ;
- for (list_element=nisam_open_list ;
- list_element ;
- list_element=list_element->next)
- {
- N_INFO *tmpinfo=(N_INFO*) list_element->data;
- if (tmpinfo->s == info->s)
- {
- if (tmpinfo->dfile >= 0 && my_close(tmpinfo->dfile,MYF(0)))
- error = my_errno;
- tmpinfo->dfile=-1;
- }
- }
- }
- info->s->kfile=-1; /* Files aren't open anymore */
-#endif
- pthread_mutex_unlock(&THR_LOCK_isam);
- break;
- case HA_EXTRA_FLUSH:
- if (info->s->not_flushed)
- {
- info->s->not_flushed=0;
- if (my_sync(info->s->kfile, MYF(0)))
- error= my_errno;
- if (my_sync(info->dfile, MYF(0)))
- error= my_errno;
- }
- break;
- case HA_EXTRA_NORMAL: /* Theese isn't in use */
- case HA_EXTRA_QUICK:
- case HA_EXTRA_KEY_CACHE:
- case HA_EXTRA_NO_KEY_CACHE:
- default:
- break;
- }
- nisam_log_command(LOG_EXTRA,info,(byte*) &function,sizeof(function),error);
- DBUG_RETURN(error);
-} /* nisam_extra */
diff --git a/isam/info.c b/isam/info.c
deleted file mode 100644
index a23494e4876..00000000000
--- a/isam/info.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Ger tillbaka en struct med information om isam-filen */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <sys/stat.h>
-#endif
-
-ulong nisam_position(N_INFO *info)
-{
- return info->lastpos;
-}
-
- /* If flag == 1 one only gets pos of last record */
- /* if flag == 2 one get current info (no sync from database */
-
-int nisam_info(N_INFO *info, register N_ISAMINFO *x, int flag)
-{
- struct stat state;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("nisam_info");
-
- x->recpos = info->lastpos;
- if (flag & (HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE |
- HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK))
- {
-#ifndef NO_LOCKING
- if (!(flag & HA_STATUS_NO_LOCK))
- {
- pthread_mutex_lock(&share->intern_lock);
- VOID(_nisam_readinfo(info,F_RDLCK,0));
- VOID(_nisam_writeinfo(info,0));
- pthread_mutex_unlock(&share->intern_lock);
- }
-#endif
- x->records = share->state.records;
- x->deleted = share->state.del;
- x->delete_length= share->state.empty;
- x->keys = share->state.keys;
- x->reclength = share->base.reclength;
- x->mean_reclength= share->state.records ?
- (share->state.data_file_length-share->state.empty)/share->state.records :
- share->min_pack_length;
- x->data_file_length=share->state.data_file_length;
- x->max_data_file_length=share->base.max_data_file_length;
- x->index_file_length=share->state.key_file_length;
- x->max_index_file_length=share->base.max_key_file_length;
- x->filenr = info->dfile;
- x->errkey = info->errkey;
- x->dupp_key_pos= info->dupp_key_pos;
- x->options = share->base.options;
- x->create_time=share->base.create_time;
- x->isamchk_time=share->base.isamchk_time;
- x->rec_per_key=share->base.rec_per_key;
- if ((flag & HA_STATUS_TIME) && !fstat(info->dfile,&state))
- x->update_time=state.st_mtime;
- else
- x->update_time=0;
- x->sortkey= -1; /* No clustering */
- }
- DBUG_RETURN(0);
-} /* nisam_info */
diff --git a/isam/isamchk.c b/isam/isamchk.c
deleted file mode 100644
index 2912131d25b..00000000000
--- a/isam/isamchk.c
+++ /dev/null
@@ -1,3433 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Descript, check and repair of ISAM tables */
-
-#include "isamdef.h"
-
-#include <m_ctype.h>
-#include <stdarg.h>
-#include <my_getopt.h>
-#ifdef HAVE_SYS_VADVICE_H
-#include <sys/vadvise.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-SET_STACK_SIZE(9000) /* Minimum stack size for program */
-
-#define T_VERBOSE 1
-#define T_SILENT 2
-#define T_DESCRIPT 4
-#define T_EXTEND 8
-#define T_INFO 16
-#define T_REP 32
-#define T_OPT 64 /* Not currently used */
-#define T_FORCE_CREATE 128
-#define T_WRITE_LOOP 256
-#define T_UNPACK 512
-#define T_STATISTICS 1024
-#define T_VERY_SILENT 2048
-#define T_SORT_RECORDS 4096
-#define T_SORT_INDEX 8192
-#define T_WAIT_FOREVER 16384
-#define T_REP_BY_SORT 32768L
-
-
-#define O_NEW_INDEX 1 /* Bits set in out_flag */
-#define O_NEW_DATA 2
-
-#if defined(_MSC_VER) && !defined(__WIN__)
-#define USE_BUFFER_INIT 250L*1024L
-#define READ_BUFFER_INIT ((uint) 32768-MALLOC_OVERHEAD)
-#define SORT_BUFFER_INIT (uint) (65536L-MALLOC_OVERHEAD)
-#define MIN_SORT_BUFFER (1024*16-MALLOC_OVERHEAD)
-#else
-#define USE_BUFFER_INIT (((1024L*512L-MALLOC_OVERHEAD)/IO_SIZE)*IO_SIZE)
-#define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD)
-#define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD)
-#define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD)
-#endif
-
-#define NEED_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */
-#define MAXERR 20
-#define BUFFERS_WHEN_SORTING 16 /* Alloc for sort-key-tree */
-#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE
-#define INDEX_TMP_EXT ".TMM"
-#define DATA_TMP_EXT ".TMD"
-#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
-
-#define UPDATE_TIME 1
-#define UPDATE_STAT 2
-#define UPDATE_SORT 4
-
-typedef struct st_isam_sort_key_blocks { /* Used when sorting */
- uchar *buff,*end_pos;
- uchar lastkey[N_MAX_POSSIBLE_KEY_BUFF];
- uint last_length;
- int inited;
-} ISAM_SORT_KEY_BLOCKS;
-
-typedef struct st_isam_sort_info {
- N_INFO *info;
- enum data_file_type new_data_file_type;
- ISAM_SORT_KEY_BLOCKS *key_block,*key_block_end;
- uint key,find_length;
- ulong pos,max_pos,filepos,start_recpos,filelength,dupp,max_records,unique,
- buff_length;
- my_bool fix_datafile;
- char *record,*buff;
- N_KEYDEF *keyinfo;
- N_KEYSEG *keyseg;
-} ISAM_SORT_INFO;
-
-enum ic_options {OPT_CHARSETS_DIR_IC=256, OPT_KEY_BUFFER_SIZE,
- OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE,
- OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS,
- OPT_DECODE_BITS, OPT_AUTO_CLOSE};
-
-static ulong use_buffers=0,read_buffer_length=0,write_buffer_length=0,
- sort_buffer_length=0,sort_key_blocks=0,crc=0,unique_count=0;
-static uint testflag=0,out_flag=0,warning_printed=0,error_printed=0,
- verbose=0,opt_follow_links=1;
-static my_bool rep_quick= 0;
-static uint opt_sort_key=0,total_files=0,max_level=0,max_key=N_MAXKEY;
-static ulong keydata=0,totaldata=0,key_blocks=0;
-static ulong new_file_pos=0,record_checksum=0,key_file_blocks=0,decode_bits;
-static ulong total_records=0,total_deleted=0;
-static ulong search_after_block=NI_POS_ERROR;
-static byte *record_buff;
-static char **defaults_alloc;
-static const char *type_names[]=
-{ "?","text","binary", "short", "long", "float",
- "double","number","unsigned short",
- "unsigned long","longlong","ulonglong","int24",
- "uint24","int8","?",},
- *packed_txt="packed ",
- *diff_txt="stripped ",
- *field_pack[]={"","no endspace", "no prespace",
- "no zeros", "blob", "constant", "table-lookup",
- "always zero","?","?",};
-
-static char temp_filename[FN_REFLEN], *isam_file_name, *default_charset;
-static IO_CACHE read_cache;
-static ISAM_SORT_INFO sort_info;
-static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
-
-static const char *load_default_groups[]= { "isamchk",0 };
-
- /* Functions defined in this file */
-
-extern int main(int argc,char * *argv);
-extern void print_error _VARARGS((const char *fmt,...));
-static void print_warning _VARARGS((const char *fmt,...));
-static void print_info _VARARGS((const char *fmt,...));
-static int nisamchk(char *filename);
-static void get_options(int *argc,char * * *argv);
-static int chk_del(N_INFO *info,uint testflag);
-static int check_k_link(N_INFO *info,uint nr);
-static int chk_size(N_INFO *info);
-static int chk_key(N_INFO *info);
-static int chk_index(N_INFO *info, N_KEYDEF *keyinfo, ulong page, uchar *buff,
- ulong *keys, uint level);
-static uint isam_key_length(N_INFO *info,N_KEYDEF *keyinfo);
-static unsigned long calc_checksum(ulong count);
-static int chk_data_link(N_INFO *info,int extend);
-static int rep(N_INFO *info,char *name);
-static int writekeys(N_INFO *info,byte *buff,ulong filepos);
-static void descript(N_INFO *info,char *name);
-static int movepoint(N_INFO *info,byte *record,ulong oldpos,ulong newpos,
- uint prot_key);
-static void lock_memory(void);
-static int flush_blocks(File file);
-static int sort_records(N_INFO *,my_string,uint,int);
-static int sort_index(N_INFO *info,my_string name);
-static int sort_record_index(N_INFO *info,N_KEYDEF *keyinfo,ulong page,
- uchar *buff,uint sortkey,File new_file);
-static int sort_one_index(N_INFO *info,N_KEYDEF *keyinfo,uchar *buff,
- File new_file);
-static int change_to_newfile(const char * filename,const char * old_ext,
- const char * new_ext);
-static int lock_file(File file,ulong start,int lock_type,const char* filetype,
- const char *filename);
-static int filecopy(File to,File from,ulong start,ulong length,
- const char * type);
-
-static void print_version(void);
-static int rep_by_sort(N_INFO *info,my_string name);
-static int sort_key_read(void *key);
-static int sort_get_next_record(void);
-static int sort_write_record(void);
-static int sort_key_cmp(const void *not_used, const void *a,const void *b);
-static int sort_key_write(const void *a);
-static ulong get_record_for_key(N_INFO *info,N_KEYDEF *keyinfo,
- uchar *key);
-static int sort_insert_key(reg1 ISAM_SORT_KEY_BLOCKS *key_block,uchar *key,
- ulong prev_block);
-static int sort_delete_record(void);
-static void usage(void);
-static int flush_pending_blocks(void);
-static ISAM_SORT_KEY_BLOCKS *alloc_key_blocks(uint blocks,uint buffer_length);
-static int test_if_almost_full(N_INFO *info);
-static int recreate_database(N_INFO **info,char *filename);
-static void save_integer(byte *pos,uint pack_length,ulong value);
-static int write_data_suffix(N_INFO *info);
-static int update_state_info(N_INFO *info,uint update);
-
-
- /* Main program */
-
-int main( int argc, char **argv)
-{
- int error;
- MY_INIT(argv[0]);
-
-#ifdef __EMX__
- _wildcard (&argc, &argv);
-#endif
-
- get_options(&argc,(char***) &argv);
- nisam_quick_table_bits=(uint) decode_bits;
- error=0;
- while (--argc >= 0)
- {
- error|= nisamchk(*(argv++));
- VOID(fflush(stdout));
- VOID(fflush(stderr));
- if ((error_printed | warning_printed) && (testflag & T_FORCE_CREATE) &&
- (!(testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS |
- T_SORT_INDEX))))
- {
- testflag|=T_REP;
- error|=nisamchk(argv[-1]);
- testflag&= ~T_REP;
- VOID(fflush(stdout));
- VOID(fflush(stderr));
- }
- if (argc && (!(testflag & T_SILENT) || testflag & T_INFO))
- {
- puts("\n---------\n");
- VOID(fflush(stdout));
- }
- }
- if (total_files > 1)
- { /* Only if descript */
- if (!(testflag & T_SILENT) || testflag & T_INFO)
- puts("\n---------\n");
- printf("\nTotal of all %d ISAM-files:\nData records: %8lu Deleted blocks: %8lu\n",total_files,total_records,total_deleted);
- }
- free_defaults(defaults_alloc);
- my_end(testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
- exit(error);
-#ifndef _lint
- return 0; /* No compiler warning */
-#endif
-} /* main */
-
-
-static struct my_option my_long_options[] =
-{
- {"analyze", 'a',
- "Analyze distribution of keys. Will make some joins in MySQL faster.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
- {"character-sets-dir", OPT_CHARSETS_DIR_IC,
- "Directory where character sets are", (gptr*) &charsets_dir,
- (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#ifndef DBUG_OFF
- {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#endif
- {"default-character-set", 'C', "Set the default character set",
- (gptr*) &default_charset, (gptr*) &default_charset, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"description", 'd', "Prints some information about table.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"extend-check", 'e',
- "Check the table VERY thoroughly. One need to use this only in extreme cases, because isamchk should normally find all errors even without this switch.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"information", 'i', "Print statistics information about the table",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"force", 'f',
- "Overwrite old temporary files. If one uses -f when checking tables (running isamchk without -r), isamchk will automatically restart with -r on any wrong table.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
- 0, 0, 0, 0, 0},
- {"keys-used", 'k',
- "Used with '-r'. Tell ISAM to update only the first # keys. This can be used to get faster inserts!",
- (gptr*) &max_key, (gptr*) &max_key, 0, GET_UINT, REQUIRED_ARG, N_MAXKEY, 0,
- 0, 0, 0, 0},
- {"no-symlinks", 'l',
- "Do not follow symbolic links when repairing. Normally isamchk repairs the table a symlink points at.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"quick", 'q',
- "Used with -r to get a faster repair. (The data file isn't touched.) One can give a second '-q' to force isamchk to modify the original datafile.",
- (gptr*) &rep_quick, (gptr*) &rep_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
- 0},
- {"recover", 'r',
- "Can fix almost anything except unique keys that aren't unique.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"safe-recover", 'o',
- "Uses old recovery method; slower than '-r' but can handle a couple of cases that '-r' cannot handle.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"set-variable", 'O',
- "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"block-search", 'b', "For debugging.", (gptr*) &search_after_block,
- (gptr*) &search_after_block, 0, GET_ULONG, REQUIRED_ARG,
- (longlong) NI_POS_ERROR, 0, 0, 0, 0, 0},
- {"silent", 's',
- "Only print errors. One can use two -s to make isamchk very silent.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"sort-index", 'S',
- "Sort index blocks. This speeds up 'read-next' in applications.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"sort-records", 'R',
- "Sort records according to an index. This makes your data much more localized and may speed up things (It may be VERY slow to do a sort the first time!)",
- (gptr*) &opt_sort_key, (gptr*) &opt_sort_key, 0, GET_UINT, REQUIRED_ARG,
- 0, 0, (N_MAXKEY - 1), 1, 0, 0},
- {"unpack", 'u', "Unpack file packed with pack_isam.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"verbose", 'v',
- "Print more information. This can be used with -d and -e. Use many -v for more verbosity!",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"version", 'V', "Print version and exit.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"wait", 'w', "Wait if table is locked.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "", (gptr*) &use_buffers,
- (gptr*) &use_buffers, 0, GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT,
- (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE,
- 0},
- {"read_buffer_size", OPT_READ_BUFFER_SIZE, "",
- (gptr*) &read_buffer_length, (gptr*) &read_buffer_length, 0, GET_ULONG,
- REQUIRED_ARG, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
- (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
- {"write_buffer_size", OPT_WRITE_BUFFER_SIZE, "",
- (gptr*) &write_buffer_length, (gptr*) &write_buffer_length, 0, GET_ULONG,
- REQUIRED_ARG, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L,
- (long) MALLOC_OVERHEAD, (long) 1L, 0},
- {"sort_buffer_size", OPT_SORT_BUFFER_SIZE, "",
- (gptr*) &sort_buffer_length, (gptr*) &sort_buffer_length, 0, GET_ULONG,
- REQUIRED_ARG, (long) SORT_BUFFER_INIT,
- (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L,
- (long) MALLOC_OVERHEAD, (long) 1L, 0},
- {"sort_key_blocks", OPT_SORT_KEY_BLOCKS, "",
- (gptr*) &sort_key_blocks, (gptr*) &sort_key_blocks, 0, GET_ULONG,
- REQUIRED_ARG, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
- {"decode_bits", OPT_DECODE_BITS, "",
- (gptr*) &decode_bits, (gptr*) &decode_bits, 0, GET_ULONG, REQUIRED_ARG,
- 9L, 4L, 17L, 0L, 1L, 0},
- {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
-};
-
-#include <help_start.h>
-
-static void print_version(void)
-{
- printf("%s Ver 6.01 for %s at %s\n", my_progname, SYSTEM_TYPE,
- MACHINE_TYPE);
- NETWARE_SET_SCREEN_MODE(1);
-}
-
-
-static void usage(void)
-{
- print_version();
- puts("MySQL AB, by Monty, for your professional use");
- puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
- puts("Description, check and repair of ISAM tables.");
- puts("Used without options all tables on the command will be checked for errors");
- printf("Usage: %s [OPTIONS] tables[.ISM]\n", my_progname);
- my_print_help(my_long_options);
- print_defaults("my", load_default_groups);
- my_print_variables(my_long_options);
-}
-
-#include <help_end.h>
-
- /* Check table */
-
-static int nisamchk(my_string filename)
-{
- int error,lock_type,recreate;
- N_INFO *info;
- File datafile;
- char fixed_name[FN_REFLEN];
- ISAM_SHARE *share;
- DBUG_ENTER("nisamchk");
-
- out_flag=error=warning_printed=error_printed=recreate=0;
- datafile=0;
- isam_file_name=filename; /* For error messages */
- if (!(info=nisam_open(filename,
- (testflag & T_DESCRIPT) ? O_RDONLY : O_RDWR,
- (testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED :
- (testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED :
- HA_OPEN_ABORT_IF_LOCKED)))
- {
- /* Avoid twice printing of isam file name */
- error_printed=1;
- switch (my_errno) {
- case HA_ERR_CRASHED:
- print_error("'%s' is not a ISAM-table",filename);
- break;
- case HA_ERR_OLD_FILE:
- print_error("'%s' is a old type of ISAM-table", filename);
- break;
- case HA_ERR_END_OF_FILE:
- print_error("Couldn't read compleat header from '%s'", filename);
- break;
- case EAGAIN:
- print_error("'%s' is locked. Use -w to wait until unlocked",filename);
- break;
- case ENOENT:
- print_error("File '%s' doesn't exist",filename);
- break;
- case EACCES:
- print_error("You don't have permission to use '%s'",filename);
- break;
- default:
- print_error("%d when opening ISAM-table '%s'",
- my_errno,filename);
- break;
- }
- DBUG_RETURN(1);
- }
- share=info->s;
- share->base.options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */
- share->r_locks=0;
- if ((testflag & (T_REP_BY_SORT | T_REP | T_STATISTICS |
- T_SORT_RECORDS | T_SORT_INDEX)) &&
- ((testflag & T_UNPACK && share->data_file_type == COMPRESSED_RECORD) ||
- share->state_length != sizeof(share->state) ||
- uint2korr(share->state.header.base_info_length) !=
- sizeof(share->base) ||
- (max_key && ! share->state.keys && share->base.keys) ||
- test_if_almost_full(info) ||
- info->s->state.header.file_version[3] != nisam_file_magic[3]))
- {
- if (recreate_database(&info,filename))
- {
- VOID(fprintf(stderr,
- "ISAM-table '%s' is not fixed because of errors\n",
- filename));
- return(-1);
- }
- recreate=1;
- if (!(testflag & (T_REP | T_REP_BY_SORT)))
- {
- testflag|=T_REP_BY_SORT; /* if only STATISTICS */
- if (!(testflag & T_SILENT))
- printf("- '%s' has old table-format. Recreating index\n",filename);
- if (!rep_quick)
- rep_quick=1;
- }
- share=info->s;
- share->r_locks=0;
- }
-
- if (testflag & T_DESCRIPT)
- {
- total_files++;
- total_records+=share->state.records; total_deleted+=share->state.del;
- descript(info,filename);
- }
- else
- {
- if (testflag & (T_REP+T_REP_BY_SORT+T_OPT+T_SORT_RECORDS+T_SORT_INDEX))
- lock_type = F_WRLCK; /* table is changed */
- else
- lock_type= F_RDLCK;
- if (info->lock_type == F_RDLCK)
- info->lock_type=F_UNLCK; /* Read only table */
- if (_nisam_readinfo(info,lock_type,0))
- {
- print_error("Can't lock indexfile of '%s', error: %d",
- filename,my_errno);
- error_printed=0;
- goto end2;
- }
- share->w_locks++; /* Mark (for writeinfo) */
- if (lock_file(info->dfile,0L,lock_type,"datafile of",filename))
- goto end;
- info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
- info->tmp_lock_type=lock_type;
- datafile=info->dfile;
- if (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX))
- {
- if (testflag & (T_REP+T_REP_BY_SORT))
- share->state.keys=min(share->base.keys,max_key);
- VOID(fn_format(fixed_name,filename,"",N_NAME_IEXT,
- 4+ (opt_follow_links ? 16 : 0)));
-
- if (rep_quick && (error=chk_del(info,testflag & ~T_VERBOSE)))
- print_error("Quick-recover aborted; Run recovery without switch 'q'");
- else
- {
- if (testflag & T_REP_BY_SORT &&
- (share->state.keys || (rep_quick && !max_key && ! recreate)))
- error=rep_by_sort(info,fixed_name);
- else if (testflag & (T_REP | T_REP_BY_SORT))
- error=rep(info,fixed_name);
- }
- if (!error && testflag & T_SORT_RECORDS)
- {
- if (out_flag & O_NEW_DATA)
- { /* Change temp file to org file */
- VOID(lock_file(datafile,0L,F_UNLCK,"datafile of",filename));
- VOID(my_close(datafile,MYF(MY_WME))); /* Close old file */
- VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */
- error|=change_to_newfile(fixed_name,N_NAME_DEXT,DATA_TMP_EXT);
- if ((info->dfile=my_open(fn_format(temp_filename,fixed_name,"",
- N_NAME_DEXT,2+4),
- O_RDWR | O_SHARE,
- MYF(MY_WME))) <= 0 ||
- lock_file(info->dfile,0L,F_WRLCK,"datafile",temp_filename))
- error=1;
- out_flag&= ~O_NEW_DATA; /* We are using new datafile */
- read_cache.file=info->dfile;
- }
- if (! error)
- error=sort_records(info,fixed_name,opt_sort_key,
- test(!(testflag & T_REP)));
- datafile=info->dfile; /* This is now locked */
- }
- if (!error && testflag & T_SORT_INDEX)
- error=sort_index(info,fixed_name);
- }
- else
- {
- if (!(testflag & T_SILENT) || testflag & T_INFO)
- printf("Checking ISAM file: %s\n",filename);
- if (!(testflag & T_SILENT))
- printf("Data records: %7ld Deleted blocks: %7ld\n",
- share->state.records,share->state.del);
- share->state.keys=min(share->state.keys,max_key);
- error =chk_size(info);
- error|=chk_del(info,testflag);
- error|=chk_key(info);
- if (!rep_quick)
- {
- if (testflag & T_EXTEND)
- VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,
- use_buffers,0,0));
- VOID(init_io_cache(&read_cache,datafile,(uint) read_buffer_length,
- READ_CACHE,share->pack.header_length,1,
- MYF(MY_WME)));
- lock_memory();
- error|=chk_data_link(info,testflag & T_EXTEND);
- error|=flush_blocks(share->kfile);
- VOID(end_io_cache(&read_cache));
- }
- }
- }
-end:
- if (!(testflag & T_DESCRIPT))
- {
- if (info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED))
- error|=update_state_info(info,
- ((testflag & (T_REP | T_REP_BY_SORT)) ?
- UPDATE_TIME | UPDATE_STAT : 0) |
- ((testflag & T_SORT_RECORDS) ?
- UPDATE_SORT : 0));
- VOID(lock_file(share->kfile,0L,F_UNLCK,"indexfile",filename));
- if (datafile > 0)
- VOID(lock_file(datafile,0L,F_UNLCK,"datafile of",filename));
- info->update&= ~(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- }
- share->w_locks--;
-end2:
- if (datafile && datafile != info->dfile)
- VOID(my_close(datafile,MYF(MY_WME)));
- if (nisam_close(info))
- {
- print_error("%d when closing ISAM-table '%s'",my_errno,filename);
- DBUG_RETURN(1);
- }
- if (error == 0)
- {
- if (out_flag & O_NEW_DATA)
- error|=change_to_newfile(fixed_name,N_NAME_DEXT,DATA_TMP_EXT);
- if (out_flag & O_NEW_INDEX)
- error|=change_to_newfile(fixed_name,N_NAME_IEXT,INDEX_TMP_EXT);
- }
- VOID(fflush(stdout)); VOID(fflush(stderr));
- if (error_printed)
- {
- if (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX))
- VOID(fprintf(stderr,
- "ISAM-table '%s' is not fixed because of errors\n",
- filename));
- else if (! (error_printed & 2) && !(testflag & T_FORCE_CREATE))
- VOID(fprintf(stderr,
- "ISAM-table '%s' is corrupted\nFix it using switch \"-r\" or \"-o\"\n",
- filename));
- }
- else if (warning_printed &&
- ! (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX+
- T_FORCE_CREATE)))
- VOID(fprintf(stderr, "ISAM-table '%s' is useable but should be fixed\n",
- filename));
- VOID(fflush(stderr));
- DBUG_RETURN(error);
-} /* nisamchk */
-
-
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-
-{
- switch(optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
- case 'a':
- testflag|= T_STATISTICS;
- break;
- case 's': /* silent */
- if (testflag & T_SILENT)
- testflag|=T_VERY_SILENT;
- testflag|= T_SILENT;
- testflag&= ~T_WRITE_LOOP;
- break;
- case 'w':
- testflag|= T_WAIT_FOREVER;
- break;
- case 'd': /* description if isam-file */
- testflag|= T_DESCRIPT;
- break;
- case 'e': /* extend check */
- testflag|= T_EXTEND;
- break;
- case 'i':
- testflag|= T_INFO;
- break;
- case 'f':
- tmpfile_createflag= O_RDWR | O_TRUNC;
- testflag|=T_FORCE_CREATE;
- break;
- case 'l':
- opt_follow_links=0;
- break;
- case 'r': /* Repair table */
- testflag= (testflag & ~T_REP) | T_REP_BY_SORT;
- break;
- case 'o':
- testflag= (testflag & ~T_REP_BY_SORT) | T_REP;
- my_disable_async_io=1; /* More safety */
- break;
- case 'u':
- testflag|= T_UNPACK | T_REP_BY_SORT;
- break;
- case 'v': /* Verbose */
- testflag|= T_VERBOSE;
- verbose++;
- break;
- case 'R': /* Sort records */
- testflag|= T_SORT_RECORDS;
- if (opt_sort_key >= N_MAXKEY)
- {
- fprintf(stderr,
- "The value of the sort key is bigger than max key: %d.\n",
- N_MAXKEY);
- exit(1);
- }
- break;
- case 'S': /* Sort index */
- testflag|= T_SORT_INDEX;
- break;
- case '#':
- DBUG_PUSH(argument ? argument : "d:t:o,/tmp/isamchk.trace");
- break;
- case 'V':
- print_version();
- exit(0);
- case '?':
- usage();
- exit(0);
- }
- return 0;
-}
-
- /* Read options */
-
-static void get_options(register int *argc, register char ***argv)
-{
- int ho_error;
-
- load_defaults("my",load_default_groups,argc,argv);
- defaults_alloc= *argv;
- if (isatty(fileno(stdout)))
- testflag|=T_WRITE_LOOP;
-
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
- exit(ho_error);
-
- if (*argc == 0)
- {
- usage();
- exit(-1);
- }
- if ((testflag & T_UNPACK) && (rep_quick || (testflag & T_SORT_RECORDS)))
- {
- VOID(fprintf(stderr,
- "%s: --unpack can't be used with --quick or --sort-records\n",
- my_progname));
- exit(1);
- }
- if (default_charset)
- {
- if (!(default_charset_info= get_charset_by_name(default_charset, MYF(MY_WME))))
- exit(1);
- }
- return;
-} /* get options */
-
-
- /* Check delete links */
-
-static int chk_del( reg1 N_INFO *info, uint test_flag)
-{
- reg2 ulong i;
- uint j,delete_link_length;
- ulong empty,next_link;
- uchar buff[8];
- DBUG_ENTER("chk_del");
- if (!(test_flag & T_SILENT)) puts("- check delete-chain");
-
- record_checksum=0L;
- key_file_blocks=info->s->base.keystart;
- for (j =0 ; j < info->s->state.keys ; j++)
- if (check_k_link(info,j))
- goto wrong;
- delete_link_length=(info->s->base.options & HA_OPTION_PACK_RECORD) ? 8 : 5;
-
- next_link=info->s->state.dellink;
- if (info->s->state.del == 0)
- {
- if (test_flag & T_VERBOSE)
- {
- puts("No recordlinks");
- }
- }
- else
- {
- if (test_flag & T_VERBOSE)
- printf("Recordlinks: ");
- empty=0;
- for (i= info->s->state.del ; i > 0L && next_link != NI_POS_ERROR ; i--)
- {
- if (test_flag & T_VERBOSE) printf("%10lu",next_link);
- if (next_link >= info->s->state.data_file_length)
- goto wrong;
- if (my_pread(info->dfile,(char*) buff,delete_link_length,
- next_link,MYF(MY_NABP)))
- {
- if (test_flag & T_VERBOSE) puts("");
- print_error("Can't read delete-link at filepos: %lu",
- (ulong) next_link);
- DBUG_RETURN(1);
- }
- if (*buff != '\0')
- {
- if (test_flag & T_VERBOSE) puts("");
- print_error("Record at pos: %lu is not remove-marked",
- (ulong) next_link);
- goto wrong;
- }
- if (info->s->base.options & HA_OPTION_PACK_RECORD)
- {
- next_link=uint4korr(buff+4);
- empty+=uint3korr(buff+1);
- }
- else
- {
- record_checksum+=next_link;
- next_link=uint4korr(buff+1);
- empty+=info->s->base.reclength;
- }
- if (next_link == (uint32) ~0) /* Fix for 64 bit long */
- next_link=NI_POS_ERROR;
- }
- if (empty != info->s->state.empty)
- {
- if (test_flag & T_VERBOSE) puts("");
- print_warning("Not used space is supposed to be: %lu but is: %lu",
- (ulong) info->s->state.empty,(ulong) empty);
- info->s->state.empty=empty;
- }
- if (i != 0 || next_link != NI_POS_ERROR)
- goto wrong;
-
- if (test_flag & T_VERBOSE) puts("\n");
- }
- DBUG_RETURN(0);
-wrong:
- if (test_flag & T_VERBOSE) puts("");
- print_error("delete-link-chain corrupted");
- DBUG_RETURN(1);
-} /* chk_del */
-
-
- /* Kontrollerar l{nkarna i nyckelfilen */
-
-static int check_k_link( register N_INFO *info, uint nr)
-{
- ulong next_link,records;
- DBUG_ENTER("check_k_link");
-
- if (testflag & T_VERBOSE)
- printf("index %2d: ",nr+1);
-
- next_link=info->s->state.key_del[nr];
- records= (info->s->state.key_file_length /
- info->s->keyinfo[nr].base.block_length);
- while (next_link != NI_POS_ERROR && records > 0)
- {
- if (testflag & T_VERBOSE) printf("%10lu",next_link);
- if (next_link > info->s->state.key_file_length ||
- next_link & (info->s->blocksize-1))
- DBUG_RETURN(1);
- if (my_pread(info->s->kfile,(char*) &next_link,sizeof(long),next_link,
- MYF(MY_NABP)))
- DBUG_RETURN(1);
- records--;
- key_file_blocks+=info->s->keyinfo[nr].base.block_length;
- }
- if (testflag & T_VERBOSE)
- {
- if (next_link != NI_POS_ERROR)
- printf("%10lu\n",next_link);
- else
- puts("");
- }
- DBUG_RETURN (next_link != NI_POS_ERROR);
-} /* check_k_link */
-
-
- /* Kontrollerar storleken p} filerna */
-
-static int chk_size(register N_INFO *info)
-{
- int error=0;
- register my_off_t skr,size;
- DBUG_ENTER("chk_size");
-
- if (!(testflag & T_SILENT)) puts("- check file-size");
-
- size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
- if ((skr=(my_off_t) info->s->state.key_file_length) != size)
- {
- if (skr > size)
- {
- error=1;
- print_error("Size of indexfile is: %-8lu Should be: %lu",
- (ulong) size, (ulong) skr);
- }
- else
- print_warning("Size of indexfile is: %-8lu Should be: %lu",
- (ulong) size,(ulong) skr);
- }
- if (!(testflag & T_VERY_SILENT) &&
- ! (info->s->base.options & HA_OPTION_COMPRESS_RECORD) &&
- info->s->state.key_file_length >
- (ulong) (ulong_to_double(info->s->base.max_key_file_length)*0.9))
- print_warning("Keyfile is almost full, %10lu of %10lu used",
- info->s->state.key_file_length,
- info->s->base.max_key_file_length-1);
-
- size=my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
- skr=(my_off_t) info->s->state.data_file_length;
- if (info->s->base.options & HA_OPTION_COMPRESS_RECORD)
- skr+= MEMMAP_EXTRA_MARGIN;
-#ifdef USE_RELOC
- if (info->data_file_type == STATIC_RECORD &&
- skr < (my_off_t) info->s->base.reloc*info->s->base.min_pack_length)
- skr=(my_off_t) info->s->base.reloc*info->s->base.min_pack_length;
-#endif
- if (skr != size)
- {
- info->s->state.data_file_length=(ulong) size; /* Skip other errors */
- if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN)
- {
- error=1;
- print_error("Size of datafile is: %-8lu Should be: %lu",
- (ulong) size,(ulong) skr);
- }
- else
- {
- print_warning("Size of datafile is: %-8lu Should be: %lu",
- (ulong) size,(ulong) skr);
-
- }
- }
- if (!(testflag & T_VERY_SILENT) &&
- !(info->s->base.options & HA_OPTION_COMPRESS_RECORD) &&
- info->s->state.data_file_length >
- (ulong) (ulong_to_double(info->s->base.max_data_file_length)*0.9))
- print_warning("Datafile is almost full, %10lu of %10lu used",
- info->s->state.data_file_length,
- info->s->base.max_data_file_length-1);
- DBUG_RETURN(error);
-} /* chk_size */
-
-
- /* Kontrollerar nycklarna */
-
-static int chk_key( register N_INFO *info)
-{
- uint key;
- ulong keys,all_keydata,all_totaldata,key_totlength,length,
- init_checksum,old_record_checksum;
- ISAM_SHARE *share=info->s;
- N_KEYDEF *keyinfo;
- DBUG_ENTER("chk_key");
-
- if (!(testflag & T_SILENT)) puts("- check index reference");
-
- all_keydata=all_totaldata=key_totlength=old_record_checksum=0;
- init_checksum=record_checksum;
- if (!(share->base.options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
- old_record_checksum=calc_checksum(share->state.records+share->state.del-1)*
- share->base.reclength;
- for (key= 0,keyinfo= &share->keyinfo[0]; key < share->state.keys ;
- key++,keyinfo++)
- {
- record_checksum=init_checksum;
- unique_count=0L;
- if ((!(testflag & T_SILENT)) && share->state.keys >1)
- printf ("- check data record references index: %d\n",key+1);
- if (share->state.key_root[key] == NI_POS_ERROR &&
- share->state.records == 0)
- continue;
- if (!_nisam_fetch_keypage(info,keyinfo,share->state.key_root[key],info->buff,
- 0))
- {
- print_error("Can't read indexpage from filepos: %lu",
- (ulong) share->state.key_root[key]);
- DBUG_RETURN(-1);
- }
- key_file_blocks+=keyinfo->base.block_length;
- keys=keydata=totaldata=key_blocks=0; max_level=0;
- if (chk_index(info,keyinfo,share->state.key_root[key],info->buff,&keys,1))
- DBUG_RETURN(-1);
- if (keys != share->state.records)
- {
- print_error("Found %lu keys of %lu",(ulong) keys,
- (ulong) share->state.records);
- DBUG_RETURN(-1);
- }
- if (!key && (share->base.options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
- old_record_checksum=record_checksum;
- else if (old_record_checksum != record_checksum)
- {
- if (key)
- print_error("Key %u doesn't point at same records that key 1",
- key+1);
- else
- print_error("Key 1 doesn't point at all records");
- DBUG_RETURN(-1);
- }
- length=(ulong) isam_key_length(info,keyinfo)*keys + key_blocks*2;
- if (testflag & T_INFO && totaldata != 0L && keys != 0L)
- printf("Key: %2d: Keyblocks used: %3d%% Packed: %4d%% Max levels: %2d\n",
- key+1,
- (int) (keydata*100.0/totaldata),
- (int) ((long) (length-keydata)*100.0/(double) length),
- max_level);
- all_keydata+=keydata; all_totaldata+=totaldata; key_totlength+=length;
- share->base.rec_per_key[key]=
- unique_count ? ((share->state.records+unique_count/2)/
- unique_count) : 1L;
- }
- if (testflag & T_INFO)
- {
- if (all_totaldata != 0L && share->state.keys != 1)
- printf("Total: Keyblocks used: %3d%% Packed: %4d%%\n\n",
- (int) (all_keydata*100.0/all_totaldata),
- (int) ((long) (key_totlength-all_keydata)*100.0/
- (double) key_totlength));
- else if (all_totaldata != 0L && share->state.keys)
- puts("");
- }
- if (key_file_blocks != share->state.key_file_length)
- print_warning("Some data are unreferenced in keyfile");
- record_checksum-=init_checksum; /* Remove delete links */
- if (testflag & T_STATISTICS)
- DBUG_RETURN(update_state_info(info,UPDATE_STAT));
- DBUG_RETURN(0);
-} /* chk_key */
-
-
- /* Check if index is ok */
-
-static int chk_index(N_INFO *info, N_KEYDEF *keyinfo, ulong page, uchar *buff,
- ulong *keys,uint level)
-{
- int flag;
- uint used_length,comp_flag,nod_flag;
- uchar key[N_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*endpos;
- ulong next_page,record;
- DBUG_ENTER("chk_index");
- DBUG_DUMP("buff",(byte*) buff,getint(buff));
-
- if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length)))
- {
- print_error("Not Enough memory");
- DBUG_RETURN(-1);
- }
-
- if (keyinfo->base.flag & HA_NOSAME)
- comp_flag=SEARCH_FIND; /* Not dupplicates */
- else
- comp_flag=SEARCH_SAME; /* Keys in positionorder */
- nod_flag=test_if_nod(buff);
- used_length=getint(buff);
- keypos=buff+2+nod_flag;
- endpos=buff+used_length;
-
- keydata+=used_length; totaldata+=keyinfo->base.block_length; /* INFO */
- key_blocks++;
- if (level > max_level)
- max_level=level;
-
- if (used_length > keyinfo->base.block_length)
- {
- print_error("Wrong pageinfo at page: %lu",(ulong) page);
- goto err;
- }
- for ( ;; )
- {
- if (nod_flag)
- {
- next_page=_nisam_kpos(nod_flag,keypos);
- if (next_page > info->s->state.key_file_length ||
- (nod_flag && (next_page & (info->s->blocksize -1))))
- {
- my_off_t max_length=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
- print_error("Wrong pagepointer: %lu at page: %lu",
- (ulong) next_page,(ulong) page);
-
- if (next_page+info->s->blocksize > max_length)
- goto err;
- info->s->state.key_file_length=(ulong) (max_length &
- ~ (my_off_t)
- (info->s->blocksize-1));
- }
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,temp_buff,0))
- {
- print_error("Can't read key from filepos: %lu",(ulong) next_page);
- goto err;
- }
- key_file_blocks+=keyinfo->base.block_length;
- if (chk_index(info,keyinfo,next_page,temp_buff,keys,level+1))
- goto err;
- }
- if (keypos >= endpos ||
- (*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key) == 0)
- break;
- if ((*keys)++ &&
- (flag=_nisam_key_cmp(keyinfo->seg,info->lastkey,key,0,comp_flag)) >=0)
- {
- DBUG_DUMP("old",(byte*) info->lastkey,
- _nisam_keylength(keyinfo,info->lastkey));
- DBUG_DUMP("new",(byte*) key,_nisam_keylength(keyinfo,key));
-
- if (comp_flag == SEARCH_FIND && flag == 0)
- print_error("Found dupplicated key at page %lu",(ulong) page);
- else
- print_error("Key in wrong position at page %lu",(ulong) page);
- goto err;
- }
- if (testflag & T_STATISTICS)
- {
- if (*keys == 1L ||
- _nisam_key_cmp(keyinfo->seg,info->lastkey,key,0,SEARCH_FIND))
- unique_count++;
- }
- VOID(_nisam_move_key(keyinfo,(uchar*) info->lastkey,key));
- record= _nisam_dpos(info,nod_flag,keypos);
- if (record >= info->s->state.data_file_length)
- {
- print_error("Found key at page %lu that points to record outside datafile",page);
- DBUG_PRINT("test",("page: %lu record: %lu filelength: %lu",
- (ulong) page,(ulong) record,
- (ulong) info->s->state.data_file_length));
- DBUG_DUMP("key",(byte*) info->lastkey,info->s->base.max_key_length);
- goto err;
- }
- record_checksum+=record;
- }
- if (keypos != endpos)
- {
- print_error("Keyblock size at page %lu is not correct. Block length: %d key length: %d",(ulong) page, used_length, (keypos - buff));
- goto err;
- }
- my_afree((byte*) temp_buff);
- DBUG_RETURN(0);
- err:
- my_afree((byte*) temp_buff);
- DBUG_RETURN(1);
-} /* chk_index */
-
-
- /* Calculate a checksum of 1+2+3+4...N = N*(N+1)/2 without overflow */
-
-static ulong calc_checksum(count)
-ulong count;
-{
- ulong sum,a,b;
- DBUG_ENTER("calc_checksum");
-
- sum=0;
- a=count; b=count+1;
- if (a & 1)
- b>>=1;
- else
- a>>=1;
- while (b)
- {
- if (b & 1)
- sum+=a;
- a<<=1; b>>=1;
- }
- DBUG_PRINT("exit",("sum: %lx",sum));
- DBUG_RETURN(sum);
-} /* calc_checksum */
-
-
- /* Calc length of key in normal isam */
-
-static uint isam_key_length( N_INFO *info, reg1 N_KEYDEF *keyinfo)
-{
- uint length;
- N_KEYSEG *keyseg;
- DBUG_ENTER("isam_key_length");
-
- length= info->s->rec_reflength;
- for (keyseg=keyinfo->seg ; keyseg->base.type ; keyseg++)
- length+= keyseg->base.length;
-
- DBUG_PRINT("exit",("length: %d",length));
- DBUG_RETURN(length);
-} /* key_length */
-
-
- /* Check that record-link is ok */
-
-static int chk_data_link(info,extend)
-reg1 N_INFO *info;
-int extend;
-{
- int error,got_error,flag;
- uint key,left_length,b_type;
- ulong records,del_blocks,used,empty,pos,splitts,start_recpos,
- del_length,link_used,intern_record_checksum,start_block;
- byte *record,*to;
- N_KEYDEF *keyinfo;
- BLOCK_INFO block_info;
- DBUG_ENTER("chk_data_link");
-
- if (! (info->s->base.options & (HA_OPTION_PACK_RECORD |
- HA_OPTION_COMPRESS_RECORD)) &&
- ! extend)
- DBUG_RETURN(0);
-
- if (!(testflag & T_SILENT))
- {
- if (extend)
- puts("- check records and index references");
- else
- puts("- check record links");
- }
-
- if (!(record= (byte*) my_alloca(info->s->base.reclength)))
- {
- print_error("Not Enough memory");
- DBUG_RETURN(-1);
- }
- records=used=link_used=splitts=del_blocks=del_length=
- intern_record_checksum=crc=0L;
- LINT_INIT(left_length); LINT_INIT(start_recpos); LINT_INIT(to);
- got_error=error=0;
- empty=pos=info->s->pack.header_length;
-
- while (pos < info->s->state.data_file_length)
- {
- switch (info->s->data_file_type) {
- case STATIC_RECORD:
- if (my_b_read(&read_cache,(byte*) record,info->s->base.reclength))
- goto err;
- start_recpos=pos;
- pos+=info->s->base.reclength;
- splitts++;
- if (*record == '\0')
- {
- del_blocks++;
- del_length+=info->s->base.reclength;
- continue; /* Record removed */
- }
- used+=info->s->base.reclength;
- break;
- case DYNAMIC_RECORD:
- flag=block_info.second_read=0;
- block_info.next_filepos=pos;
- do
- {
- if (_nisam_read_cache(&read_cache,(byte*) block_info.header,
- (start_block=block_info.next_filepos),
- sizeof(block_info.header),test(! flag) | 2))
- goto err;
- b_type=_nisam_get_block_info(&block_info,-1,start_block);
- if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if (b_type & BLOCK_SYNC_ERROR)
- {
- if (flag)
- {
- print_error("Unexpected byte: %d at link: %lu",
- (int) block_info.header[0],(ulong) start_block);
- goto err2;
- }
- pos=block_info.filepos+block_info.block_len;
- goto next;
- }
- if (b_type & BLOCK_DELETED)
- {
- if (block_info.block_len < info->s->base.min_block_length ||
- block_info.block_len-4 > (uint) info->s->base.max_pack_length)
- {
- print_error("Deleted block with impossible length %u at %lu",
- block_info.block_len,(ulong) pos);
- goto err2;
- }
- del_blocks++;
- del_length+=block_info.block_len;
- pos=block_info.filepos+block_info.block_len;
- splitts++;
- goto next;
- }
- print_error("Wrong bytesec: %d-%d-%d at linkstart: %lu",
- block_info.header[0],block_info.header[1],
- block_info.header[2],(ulong) start_block);
- goto err2;
- }
- if (info->s->state.data_file_length < block_info.filepos+
- block_info.block_len)
- {
- print_error("Recordlink that points outside datafile at %lu",
- (ulong) pos);
- got_error=1;
- break;
- }
- splitts++;
- if (!flag++) /* First block */
- {
- start_recpos=pos;
- pos=block_info.filepos+block_info.block_len;
- if (block_info.rec_len > (uint) info->s->base.max_pack_length)
- {
- print_error("Found too long record at %lu",(ulong) start_recpos);
- got_error=1;
- break;
- }
- if (info->s->base.blobs)
- {
- if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
- {
- print_error("Not enough memory for blob at %lu",
- (ulong) start_recpos);
- got_error=1;
- break;
- }
- }
- else
- to= info->rec_buff;
- left_length=block_info.rec_len;
- }
- if (left_length < block_info.data_len)
- {
- print_error("Found too long record at %lu",(ulong) start_recpos);
- got_error=1; break;
- }
- if (_nisam_read_cache(&read_cache,(byte*) to,block_info.filepos,
- (uint) block_info.data_len, test(flag == 1)))
- goto err;
- to+=block_info.data_len;
- link_used+= block_info.filepos-start_block;
- used+= block_info.filepos - start_block + block_info.data_len;
- empty+=block_info.block_len-block_info.data_len;
- left_length-=block_info.data_len;
- if (left_length)
- {
- if (b_type & BLOCK_LAST)
- {
- print_error("Record link to short for record at %lu",
- (ulong) start_recpos);
- got_error=1;
- break;
- }
- if (info->s->state.data_file_length < block_info.next_filepos)
- {
- print_error("Found next-recordlink that points outside datafile at %lu",
- (ulong) block_info.filepos);
- got_error=1;
- break;
- }
- }
- } while (left_length);
- if (! got_error)
- {
- if (_nisam_rec_unpack(info,record,info->rec_buff,block_info.rec_len) ==
- MY_FILE_ERROR)
- {
- print_error("Found wrong record at %lu",(ulong) start_recpos);
- got_error=1;
- }
- if (testflag & (T_EXTEND | T_VERBOSE))
- {
- if (_nisam_rec_check(info,record))
- {
- print_error("Found wrong packed record at %lu",
- (ulong) start_recpos);
- got_error=1;
- }
- }
- }
- else if (!flag)
- pos=block_info.filepos+block_info.block_len;
- break;
- case COMPRESSED_RECORD:
- if (_nisam_read_cache(&read_cache,(byte*) block_info.header,pos, 3,1))
- goto err;
- start_recpos=pos;
- splitts++;
- VOID(_nisam_pack_get_block_info(&block_info,info->s->pack.ref_length,-1,
- start_recpos));
- pos=start_recpos+info->s->pack.ref_length+block_info.rec_len;
- if (block_info.rec_len < (uint) info->s->min_pack_length ||
- block_info.rec_len > (uint) info->s->max_pack_length)
- {
- print_error("Found block with wrong recordlength: %d at %lu",
- block_info.rec_len,(ulong) start_recpos);
- got_error=1;
- break;
- }
- if (_nisam_read_cache(&read_cache,(byte*) info->rec_buff,
- block_info.filepos, block_info.rec_len,1))
- goto err;
- if (_nisam_pack_rec_unpack(info,record,info->rec_buff,block_info.rec_len))
- {
- print_error("Found wrong record at %lu",(ulong) start_recpos);
- got_error=1;
- }
- crc^=_nisam_checksum(record,info->s->base.reclength);
- link_used+=info->s->pack.ref_length;
- used+=block_info.rec_len+info->s->pack.ref_length;
- }
- if (! got_error)
- {
- intern_record_checksum+=start_recpos;
- records++;
- if (testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
- {
- printf("%lu\r",(ulong) records); VOID(fflush(stdout));
- }
-
- if (extend)
- {
- for (key=0,keyinfo= info->s->keyinfo; key<info->s->state.keys;
- key++,keyinfo++)
- {
- VOID(_nisam_make_key(info,key,info->lastkey,record,start_recpos));
- if (_nisam_search(info,keyinfo,info->lastkey,0,SEARCH_SAME,
- info->s->state.key_root[key]))
- {
- print_error("Record at: %10lu Can't find key for index: %2d",
- start_recpos,key+1);
- if (error++ > MAXERR || !(testflag & T_VERBOSE))
- goto err2;
- }
- }
- }
- }
- else
- {
- got_error=0;
- if (error++ > MAXERR || !(testflag & T_VERBOSE))
- goto err2;
- }
- next:; /* Next record */
- }
- if (testflag & T_WRITE_LOOP)
- {
- VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
- }
- if (records != info->s->state.records)
- {
- print_error("Record-count is not ok; is %-10lu Should be: %lu",
- (ulong) records,(ulong) info->s->state.records);
- error=1;
- }
- else if (record_checksum != intern_record_checksum && info->s->state.keys)
- {
- print_error("Keypointers and records don't match");
- error=1;
- }
- if (used+empty+del_length != info->s->state.data_file_length)
- {
- print_warning("Found %lu record-data and %lu unused data and %lu deleted-data\nTotal %lu, Should be: %lu",
- (ulong) used,(ulong) empty,(ulong) del_length,
- (ulong) (used+empty+del_length),
- (ulong) info->s->state.data_file_length);
- }
- if (del_blocks != info->s->state.del)
- {
- print_warning("Found %10lu deleted blocks Should be: %lu",
- (ulong) del_blocks,(ulong) info->s->state.del);
- }
- if (splitts != info->s->state.splitt)
- {
- print_warning("Found %10lu parts Should be: %lu parts",
- (ulong) splitts,(ulong) info->s->state.splitt);
- }
- if ((info->s->base.options & HA_OPTION_COMPRESS_RECORD) &&
- crc != info->s->state.uniq)
- print_warning("Wrong checksum for records; Restore uncompressed table");
-
- if (testflag & T_INFO)
- {
- if (warning_printed || error_printed)
- puts("");
- if (used != 0 && ! error_printed)
- {
- printf("Records:%17lu M.recordlength:%8lu Packed:%14.0f%%\n",
- records, (used-link_used)/records,
- (info->s->base.blobs ? 0 :
- (ulong_to_double(info->s->base.reclength*records)-used)/
- ulong_to_double(info->s->base.reclength*records)*100.0));
- printf("Recordspace used:%8.0f%% Empty space:%11d%% Blocks/Record: %6.2f\n",
- (ulong_to_double(used-link_used)/ulong_to_double(used-link_used+empty)*100.0),
- (!records ? 100 : (int) (ulong_to_double(del_length+empty)/used*100.0)),
- ulong_to_double(splitts - del_blocks) / records);
- }
- printf("Record blocks:%12lu Delete blocks:%10lu\n",
- splitts-del_blocks,del_blocks);
- printf("Record data: %12lu Deleted data :%10lu\n",
- used-link_used,del_length);
- printf("Lost space: %12lu Linkdata: %10lu\n",
- empty,link_used);
- }
- my_afree((gptr) record);
- DBUG_RETURN (error);
- err:
- print_error("got error: %d when reading datafile",my_errno);
- err2:
- my_afree((gptr) record);
- DBUG_RETURN(1);
-} /* chk_data_link */
-
-
- /* Recover old table by reading each record and writing all keys */
- /* Save new datafile-name in temp_filename */
-
-static int rep(info,name)
-reg1 N_INFO *info;
-my_string name;
-{
- int error,got_error;
- uint i;
- ulong start_records,new_header_length,del;
- File new_file;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("rep");
-
- start_records=share->state.records;
- new_header_length=(testflag & T_UNPACK) ? 0L : share->pack.header_length;
- got_error=1;
- new_file= -1;
- if (!(testflag & T_SILENT))
- {
- printf("- recovering ISAM-table '%s'\n",name);
- printf("Data records: %lu\n",(ulong) share->state.records);
- }
-
- VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,use_buffers,0,0));
- if (init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length,
- READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
- goto err;
- if (!rep_quick)
- if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length,
- WRITE_CACHE, new_header_length, 1,
- MYF(MY_WME | MY_WAIT_IF_FULL)))
- goto err;
- info->opt_flag|=WRITE_CACHE_USED;
- sort_info.start_recpos=0;
- sort_info.buff=0; sort_info.buff_length=0;
- if (!(sort_info.record=(byte*) my_alloca((uint) share->base.reclength)))
- {
- print_error("Not Enough memory");
- goto err;
- }
-
- if (!rep_quick)
- {
- if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT,
- 2+4),
- 0,tmpfile_createflag,MYF(0))) < 0)
- {
- print_error("Can't create new tempfile: '%s'",temp_filename);
- goto err;
- }
- if (filecopy(new_file,info->dfile,0L,new_header_length,"datafile-header"))
- goto err;
- share->state.dellink= NI_POS_ERROR;
- info->rec_cache.file=new_file;
- if (testflag & T_UNPACK)
- share->base.options&= ~HA_OPTION_COMPRESS_RECORD;
- }
-
- sort_info.info=info;
- sort_info.pos=sort_info.max_pos=share->pack.header_length;
- sort_info.filepos=new_header_length;
- read_cache.end_of_file=sort_info.filelength=(ulong)
- my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
- sort_info.dupp=0;
- sort_info.fix_datafile= (my_bool) (! rep_quick);
- sort_info.max_records=LONG_MAX;
- if ((sort_info.new_data_file_type=share->data_file_type) ==
- COMPRESSED_RECORD && testflag & T_UNPACK)
- {
- if (share->base.options & HA_OPTION_PACK_RECORD)
- sort_info.new_data_file_type = DYNAMIC_RECORD;
- else
- sort_info.new_data_file_type = STATIC_RECORD;
- }
-
- del=share->state.del;
- share->state.records=share->state.del=share->state.empty=
- share->state.splitt=0;
- info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- for (i=0 ; i < N_MAXKEY ; i++)
- share->state.key_del[i]=share->state.key_root[i]= NI_POS_ERROR;
- share->state.key_file_length=share->base.keystart;
-
- lock_memory(); /* Everything is alloced */
- while (!(error=sort_get_next_record()))
- {
- if (writekeys(info,(byte*) sort_info.record,sort_info.filepos))
- {
- if (my_errno != HA_ERR_FOUND_DUPP_KEY) goto err;
- DBUG_DUMP("record",(byte*) sort_info.record,share->base.pack_reclength);
- print_info("Dupplicate key %2d for record at %10lu against new record at %10lu",info->errkey+1,sort_info.start_recpos,info->int_pos);
- if (testflag & T_VERBOSE)
- {
- VOID(_nisam_make_key(info,(uint) info->errkey,info->lastkey,
- sort_info.record,0L));
- _nisam_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey);
- }
- sort_info.dupp++;
- if (rep_quick == 1)
- {
- error_printed=1;
- goto err;
- }
- continue;
- }
- if (sort_write_record())
- goto err;
- }
- if (error > 0 || write_data_suffix(info) ||
- flush_io_cache(&info->rec_cache) || read_cache.error < 0)
- goto err;
-
- if (testflag & T_WRITE_LOOP)
- {
- VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
- }
- if (my_chsize(share->kfile, share->state.key_file_length, 0, MYF(0)))
- {
- print_warning("Can't change size of indexfile, error: %d",my_errno);
- goto err;
- }
-
- if (rep_quick && del+sort_info.dupp != share->state.del)
- {
- print_error("Couldn't fix table with quick recovery: Found wrong number of deleted records");
- print_error("Run recovery again without -q");
- got_error=1;
- goto err;
- }
-
- if (!rep_quick)
- {
- info->dfile=new_file;
- share->state.data_file_length=sort_info.filepos;
- share->state.splitt=share->state.records; /* Only hole records */
- out_flag|=O_NEW_DATA; /* Data in new file */
- share->state.version=(ulong) time((time_t*) 0); /* Force reopen */
- }
- else
- share->state.data_file_length=sort_info.max_pos;
-
- if (!(testflag & T_SILENT))
- {
- if (start_records != share->state.records)
- printf("Data records: %lu\n",(ulong) share->state.records);
- if (sort_info.dupp)
- print_warning("%lu records have been removed",(ulong) sort_info.dupp);
- }
-
- got_error=0;
-err:
- if (got_error)
- {
- if (! error_printed)
- print_error("%d for record at pos %lu",my_errno,
- (ulong) sort_info.start_recpos);
- if (new_file >= 0)
- {
- VOID(my_close(new_file,MYF(0)));
- VOID(my_delete(temp_filename,MYF(MY_WME)));
- }
- }
- if (sort_info.record)
- {
- my_afree(sort_info.record);
- }
- my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
- VOID(end_io_cache(&read_cache));
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- VOID(end_io_cache(&info->rec_cache));
- got_error|=flush_blocks(share->kfile);
- if (!got_error && testflag & T_UNPACK)
- {
- share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
- share->pack.header_length=0;
- share->data_file_type=sort_info.new_data_file_type;
- }
- DBUG_RETURN(got_error);
-} /* rep */
-
-
- /* Uppdaterar nyckelfilen i samband med reparation */
-
-static int writekeys(register N_INFO *info,byte *buff,ulong filepos)
-{
- register uint i;
- uchar *key;
- DBUG_ENTER("writekeys");
-
- key=info->lastkey+info->s->base.max_key_length;
- for (i=0 ; i < info->s->state.keys ; i++)
- {
- VOID(_nisam_make_key(info,i,key,buff,filepos));
- if (_nisam_ck_write(info,i,key)) goto err;
- }
- DBUG_RETURN(0);
-
- err:
- if (my_errno == HA_ERR_FOUND_DUPP_KEY)
- {
- info->errkey=(int) i; /* This key was found */
- while ( i-- > 0 )
- {
- VOID(_nisam_make_key(info,i,key,buff,filepos));
- if (_nisam_ck_delete(info,i,key)) break;
- }
- }
- DBUG_PRINT("error",("errno: %d",my_errno));
- DBUG_RETURN(-1);
-} /* writekeys */
-
-
- /* Write info about table */
-
-static void descript(info,name)
-reg1 N_INFO *info;
-my_string name;
-{
- uint key,field,start,len;
- reg3 N_KEYDEF *keyinfo;
- reg2 N_KEYSEG *keyseg;
- reg4 const char *text;
- char buff[40],length[10],*pos,*end;
- enum en_fieldtype type;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("describe");
-
- printf("\nISAM file: %s\n",name);
- if (testflag & T_VERBOSE)
- {
- printf("Isam-version: %d\n",(int) share->state.header.file_version[3]);
- if (share->base.create_time)
- {
- get_date(buff,1,share->base.create_time);
- printf("Creation time: %s\n",buff);
- }
- if (share->base.isamchk_time)
- {
- get_date(buff,1,share->base.isamchk_time);
- printf("Recover time: %s\n",buff);
- }
- }
- printf("Data records: %10lu Deleted blocks: %10lu\n",
- share->state.records,share->state.del);
- if (testflag & T_SILENT)
- DBUG_VOID_RETURN; /* This is enough */
-
- if (testflag & T_VERBOSE)
- {
-#ifdef USE_RELOC
- printf("Init-relocation: %10lu\n",share->base.reloc);
-#endif
- printf("Datafile Parts: %10lu Deleted data: %10lu\n",
- share->state.splitt,share->state.empty);
- printf("Datafile pointer (bytes):%6d Keyfile pointer (bytes):%6d\n",
- share->rec_reflength,share->base.key_reflength);
- if (info->s->base.reloc == 1L && info->s->base.records == 1L)
- puts("This is a one-record table");
- else
- {
- if (share->base.max_data_file_length != NI_POS_ERROR ||
- share->base.max_key_file_length != NI_POS_ERROR)
- printf("Max datafile length: %10lu Max keyfile length: %10lu\n",
- share->base.max_data_file_length-1,
- share->base.max_key_file_length-1);
- }
- }
-
- printf("Recordlength: %10d\n",(int) share->base.reclength);
- VOID(fputs("Record format: ",stdout));
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- puts("Compressed");
- else if (share->base.options & HA_OPTION_PACK_RECORD)
- puts("Packed");
- else
- puts("Fixed length");
- if (share->state.keys != share->base.keys)
- printf("Using only %d keys of %d possibly keys\n",share->state.keys,
- share->base.keys);
-
- puts("\ntable description:");
- printf("Key Start Len Index Type");
- if (testflag & T_VERBOSE)
- printf(" Root Blocksize Rec/key");
- VOID(putchar('\n'));
-
- for (key=0, keyinfo= &share->keyinfo[0] ; key < share->base.keys;
- key++,keyinfo++)
- {
- keyseg=keyinfo->seg;
- if (keyinfo->base.flag & HA_NOSAME) text="unique ";
- else text="multip.";
-
- pos=buff;
- if (keyseg->base.flag & HA_REVERSE_SORT)
- *pos++ = '-';
- pos=strmov(pos,type_names[keyseg->base.type]);
- *pos++ = ' ';
- *pos=0;
- if (keyinfo->base.flag & HA_PACK_KEY)
- pos=strmov(pos,packed_txt);
- if (keyseg->base.flag & HA_SPACE_PACK)
- pos=strmov(pos,diff_txt);
- printf("%-4d%-6d%-3d %-8s%-21s",
- key+1,keyseg->base.start+1,keyseg->base.length,text,buff);
- if (testflag & T_VERBOSE)
- printf(" %9ld %9d %9ld",
- share->state.key_root[key],keyinfo->base.block_length,
- share->base.rec_per_key[key]);
- VOID(putchar('\n'));
- while ((++keyseg)->base.type)
- {
- pos=buff;
- if (keyseg->base.flag & HA_REVERSE_SORT)
- *pos++ = '-';
- pos=strmov(pos,type_names[keyseg->base.type]);
- *pos++= ' ';
- if (keyseg->base.flag & HA_SPACE_PACK)
- pos=strmov(pos,diff_txt);
- *pos=0;
- printf(" %-6d%-3d %-24s\n",
- keyseg->base.start+1,keyseg->base.length,buff);
- }
- }
- if (verbose > 1)
- {
- printf("\nField Start Length Type");
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- printf(" Huff tree Bits");
- VOID(putchar('\n'));
- if (verbose > 2 && share->base.pack_bits)
- printf("- %-7d%-35s\n",share->base.pack_bits,"bit field");
-
- start=1;
- for (field=0 ; field < share->base.fields ; field++)
- {
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- type=share->rec[field].base_type;
- else
- type=(enum en_fieldtype) share->rec[field].base.type;
- end=strmov(buff,field_pack[type]);
-#ifndef NOT_PACKED_DATABASES
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
- end=strmov(end,", not_always");
- if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
- end=strmov(end,", no empty");
- if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
- {
- sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
- end=strend(end);
- }
- }
- if (buff[0] == ',')
- strmov(buff,buff+2);
-#endif
- len=(uint) (int10_to_str((long) share->rec[field].base.length,length,10) -
- length);
- if (type == FIELD_BLOB)
- {
- length[len]='+';
- 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
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- if (share->rec[field].huff_tree)
- printf("%3d %2d",
- (uint) (share->rec[field].huff_tree-share->decode_trees)+1,
- share->rec[field].huff_tree->quick_table_bits);
- }
-#endif
- VOID(putchar('\n'));
- start+=share->rec[field].base.length;
- if (type == FIELD_BLOB)
- start+=sizeof(char*);
- }
- }
- DBUG_VOID_RETURN;
-} /* describe */
-
-
- /* Change all key-pointers that points to a records */
-
-static int movepoint(info,record,oldpos,newpos,prot_key)
-register N_INFO *info;
-byte *record;
-ulong oldpos,newpos;
-uint prot_key;
-{
- register uint i;
- uchar *key;
- DBUG_ENTER("movepoint");
-
- key=info->lastkey+info->s->base.max_key_length;
- for (i=0 ; i < info->s->state.keys; i++)
- {
- if (i != prot_key)
- {
- VOID(_nisam_make_key(info,i,key,record,oldpos));
- if (info->s->keyinfo[i].base.flag & HA_NOSAME)
- { /* Change pointer direct */
- uint nod_flag;
- N_KEYDEF *keyinfo;
- keyinfo=info->s->keyinfo+i;
- if (_nisam_search(info,keyinfo,key,USE_HOLE_KEY,
- (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
- info->s->state.key_root[i]))
- DBUG_RETURN(-1);
- nod_flag=test_if_nod(info->buff);
- _nisam_dpointer(info,info->int_keypos-nod_flag-
- info->s->rec_reflength,newpos);
- if (_nisam_write_keypage(info,keyinfo,info->int_pos,info->buff))
- DBUG_RETURN(-1);
- }
- else
- { /* Change old key to new */
- if (_nisam_ck_delete(info,i,key))
- DBUG_RETURN(-1);
- VOID(_nisam_make_key(info,i,key,record,newpos));
- if (_nisam_ck_write(info,i,key))
- DBUG_RETURN(-1);
- }
- }
- }
- DBUG_RETURN(0);
-} /* movepoint */
-
-
- /* Tell system that we want all memory for our cache */
-
-static void lock_memory(void)
-{
-#ifdef SUN_OS /* Key-cacheing thrases on sun 4.1 */
- int success;
-
- success = mlockall(MCL_CURRENT); /* or plock(DATLOCK); */
-
- if (geteuid() == 0 && success != 0)
- print_warning("Failed to lock memory. errno %d",my_errno);
-#endif
-} /* lock_memory */
-
-
- /* Flush all changed blocks to disk */
-
-static int flush_blocks(file)
-File file;
-{
- if (flush_key_blocks(dflt_key_cache,file,FLUSH_RELEASE))
- {
- print_error("%d when trying to write bufferts",my_errno);
- return(1);
- }
- end_key_cache(dflt_key_cache,1);
- return 0;
-} /* flush_blocks */
-
-
- /* Sort records according to one key */
-
-static int sort_records(info,name,sort_key,write_info)
-register N_INFO *info;
-my_string name;
-uint sort_key;
-int write_info;
-{
- int got_error;
- uint key;
- N_KEYDEF *keyinfo;
- File new_file;
- uchar *temp_buff;
- ulong old_record_count;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("sort_records");
-
- keyinfo= &share->keyinfo[sort_key];
- got_error=1;
- temp_buff=0; record_buff=0;
- new_file= -1;
-
- if (sort_key >= share->state.keys)
- {
- print_error("Can't sort table '%s' on key %d. It has only %d keys",
- name,sort_key+1,share->state.keys);
- error_printed=0;
- DBUG_RETURN(-1);
- }
- if (!(testflag & T_SILENT))
- {
- printf("- Sorting records in ISAM-table '%s'\n",name);
- if (write_info)
- printf("Data records: %7lu Deleted: %7lu\n",
- share->state.records,share->state.del);
- }
- if (share->state.key_root[sort_key] == NI_POS_ERROR)
- DBUG_RETURN(0); /* Nothing to do */
-
- init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,use_buffers, 0, 0);
- if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length,
- WRITE_CACHE,share->pack.header_length,1,
- MYF(MY_WME | MY_WAIT_IF_FULL)))
- goto err;
- info->opt_flag|=WRITE_CACHE_USED;
-
- if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length)))
- {
- print_error("Not Enough memory");
- goto err;
- }
- if (!(record_buff=(byte*) my_alloca((uint) share->base.reclength)))
- {
- print_error("Not Enough memory");
- goto err;
- }
- if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT,2+4),
- 0,tmpfile_createflag,MYF(0))) <= 0)
- {
- print_error("Can't create new tempfile: '%s'",temp_filename);
- goto err;
- }
- if (filecopy(new_file,info->dfile,0L,share->pack.header_length,
- "datafile-header"))
- goto err;
- info->rec_cache.file=new_file; /* Use this file for cacheing*/
-
- lock_memory();
- for (key=0 ; key < share->state.keys ; key++)
- share->keyinfo[key].base.flag|= HA_SORT_ALLOWS_SAME;
-
- if (my_pread(share->kfile,(byte*) temp_buff,
- (uint) keyinfo->base.block_length,
- share->state.key_root[sort_key],
- MYF(MY_NABP+MY_WME)))
- {
- print_error("Can't read indexpage from filepos: %lu",
- (ulong) share->state.key_root[sort_key]);
- goto err;
- }
-
- /* Setup param for sort_write_record */
- bzero((char*) &sort_info,sizeof(sort_info));
- sort_info.info=info;
- sort_info.new_data_file_type=share->data_file_type;
- sort_info.fix_datafile=1;
- sort_info.filepos=share->pack.header_length;
- sort_info.record=record_buff;
- old_record_count=share->state.records;
- share->state.records=0;
-
- if (sort_record_index(info,keyinfo,share->state.key_root[sort_key],temp_buff,
- sort_key,new_file) ||
- write_data_suffix(info) ||
- flush_io_cache(&info->rec_cache))
- goto err;
-
- if (share->state.records != old_record_count)
- {
- print_error("found %lu of %lu records",
- (ulong) share->state.records,(ulong) old_record_count);
- goto err;
- }
-
- /* Put same locks as old file */
- if (lock_file(new_file,0L,F_WRLCK,"tempfile",temp_filename))
- goto err;
- VOID(lock_file(info->dfile,0L,F_UNLCK,"datafile of",name));
- VOID(my_close(info->dfile,MYF(MY_WME)));
- out_flag|=O_NEW_DATA; /* Data in new file */
-
- info->dfile=new_file; /* Use new indexfile */
- share->state.del=share->state.empty=0;
- share->state.dellink= NI_POS_ERROR;
- share->state.data_file_length=sort_info.filepos;
- share->state.splitt=share->state.records; /* Only hole records */
- share->state.version=(ulong) time((time_t*) 0);
-
- info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
-
- if (testflag & T_WRITE_LOOP)
- {
- VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
- }
- got_error=0;
-
-err:
- if (got_error && new_file >= 0)
- {
- VOID(my_close(new_file,MYF(MY_WME)));
- VOID(my_delete(temp_filename,MYF(MY_WME)));
- }
- if (temp_buff)
- {
- my_afree((gptr) temp_buff);
- }
- if (record_buff)
- {
- my_afree(record_buff);
- }
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- VOID(end_io_cache(&info->rec_cache));
- share->base.sortkey=sort_key;
- DBUG_RETURN(flush_blocks(share->kfile) | got_error);
-} /* sort_records */
-
-
- /* Sort records recursive using one index */
-
-static int sort_record_index(info,keyinfo,page,buff,sort_key,new_file)
-N_INFO *info;
-N_KEYDEF *keyinfo;
-ulong page;
-uchar *buff;
-uint sort_key;
-File new_file;
-{
- uint nod_flag,used_length;
- uchar *temp_buff,*keypos,*endpos;
- ulong next_page,rec_pos;
- uchar lastkey[N_MAX_KEY_BUFF];
- DBUG_ENTER("sort_record_index");
-
- nod_flag=test_if_nod(buff);
- temp_buff=0;
-
- if (nod_flag)
- {
- if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length)))
- {
- print_error("Not Enough memory");
- DBUG_RETURN(-1);
- }
- }
- used_length=getint(buff);
- keypos=buff+2+nod_flag;
- endpos=buff+used_length;
- for ( ;; )
- {
- _sanity(__FILE__,__LINE__);
- if (nod_flag)
- {
- next_page=_nisam_kpos(nod_flag,keypos);
- if (my_pread(info->s->kfile,(byte*) temp_buff,
- (uint) keyinfo->base.block_length, next_page,
- MYF(MY_NABP+MY_WME)))
- {
- print_error("Can't read keys from filepos: %lu",(ulong) next_page);
- goto err;
- }
- if (sort_record_index(info,keyinfo,next_page,temp_buff,sort_key,
- new_file))
- goto err;
- }
- _sanity(__FILE__,__LINE__);
- if (keypos >= endpos ||
- (*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey) == 0)
- break;
- rec_pos= _nisam_dpos(info,nod_flag,keypos);
-
- if ((*info->s->read_rnd)(info,record_buff,rec_pos,0))
- {
- print_error("%d when reading datafile",my_errno);
- goto err;
- }
- if (rec_pos != sort_info.filepos)
- {
- _nisam_dpointer(info,keypos-nod_flag-info->s->rec_reflength,
- sort_info.filepos);
- if (movepoint(info,record_buff,rec_pos,sort_info.filepos,sort_key))
- {
- print_error("%d when updating key-pointers",my_errno);
- goto err;
- }
- }
- if (sort_write_record())
- goto err;
- }
- bzero((byte*) buff+used_length,keyinfo->base.block_length-used_length);
- if (my_pwrite(info->s->kfile,(byte*) buff,(uint) keyinfo->base.block_length,
- page,MYF_RW))
- {
- print_error("%d when updating keyblock",my_errno);
- goto err;
- }
- if (temp_buff)
- my_afree((gptr) temp_buff);
- DBUG_RETURN(0);
-err:
- if (temp_buff)
- my_afree((gptr) temp_buff);
- DBUG_RETURN(1);
-} /* sort_record_index */
-
-
- /* Sort index for more efficent reads */
-
-static int sort_index(info,name)
-register N_INFO *info;
-my_string name;
-{
- reg2 uint key;
- reg1 N_KEYDEF *keyinfo;
- File new_file;
- ulong index_pos[N_MAXKEY];
- DBUG_ENTER("sort_index");
-
- if (!(testflag & T_SILENT))
- printf("- Sorting index for ISAM-table '%s'\n",name);
-
- if ((new_file=my_create(fn_format(temp_filename,name,"",INDEX_TMP_EXT,2+4),
- 0,tmpfile_createflag,MYF(0))) <= 0)
- {
- print_error("Can't create new tempfile: '%s'",temp_filename);
- DBUG_RETURN(-1);
- }
- if (filecopy(new_file,info->s->kfile,0L,(ulong) info->s->base.keystart,
- "headerblock"))
- goto err;
-
- new_file_pos=info->s->base.keystart;
- for (key= 0,keyinfo= &info->s->keyinfo[0]; key < info->s->state.keys ;
- key++,keyinfo++)
- {
- if (info->s->state.key_root[key] != NI_POS_ERROR)
- {
- index_pos[key]=new_file_pos; /* Write first block here */
- if (!_nisam_fetch_keypage(info,keyinfo,info->s->state.key_root[key],
- info->buff,0))
- {
- print_error("Can't read indexpage from filepos: %lu",
- (ulong) info->s->state.key_root[key]);
- goto err;
- }
- if (sort_one_index(info,keyinfo,info->buff,new_file))
- goto err;
- }
- else
- index_pos[key]= NI_POS_ERROR; /* No blocks */
- }
-
- /* Put same locks as old file */
- if (lock_file(new_file,0L,F_WRLCK,"tempfile",temp_filename))
- goto err;
- info->s->state.version=(ulong) time((time_t*) 0);
- VOID(_nisam_writeinfo(info,1)); /* This unlocks table */
- VOID(my_close(info->s->kfile,MYF(MY_WME)));
- out_flag|=O_NEW_INDEX; /* Data in new file */
-
- info->s->kfile=new_file;
- info->s->state.key_file_length=new_file_pos;
- info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- for (key=0 ; key < info->s->state.keys ; key++)
- {
- info->s->state.key_root[key]=index_pos[key];
- info->s->state.key_del[key]= NI_POS_ERROR;
- }
- DBUG_RETURN(0);
-
-err:
- VOID(my_close(new_file,MYF(MY_WME)));
- VOID(my_delete(temp_filename,MYF(MY_WME)));
- DBUG_RETURN(-1);
-} /* sort_index */
-
-
- /* Sort records recursive using one index */
-
-static int sort_one_index(info,keyinfo,buff,new_file)
-N_INFO *info;
-N_KEYDEF *keyinfo;
-uchar *buff;
-File new_file;
-{
- uint length,nod_flag,used_length;
- uchar *temp_buff,*keypos,*endpos;
- ulong new_page_pos,next_page;
- DBUG_ENTER("sort_one_index");
-
- temp_buff=0;
- new_page_pos=new_file_pos;
- new_file_pos+=keyinfo->base.block_length;
-
- if ((nod_flag=test_if_nod(buff)))
- {
- if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length)))
- {
- print_error("Not Enough memory");
- DBUG_RETURN(-1);
- }
-
- used_length=getint(buff);
- keypos=buff+2+nod_flag;
- endpos=buff+used_length;
- for ( ;; )
- {
- if (nod_flag)
- {
- next_page=_nisam_kpos(nod_flag,keypos);
- _nisam_kpointer(info,keypos-nod_flag,new_file_pos); /* Save new pos */
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,temp_buff,0))
- {
- print_error("Can't read keys from filepos: %lu",
- (ulong) next_page);
- goto err;
- }
- if (sort_one_index(info,keyinfo,temp_buff,new_file))
- goto err;
- }
- if (keypos >= endpos ||
- ((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,info->lastkey)) == 0)
- break;
- }
- my_afree((gptr) temp_buff);
- }
-
- /* Fill block with zero and write it to new file */
-
- length=getint(buff);
- bzero((byte*) buff+length,keyinfo->base.block_length-length);
- if (my_pwrite(new_file,(byte*) buff,(uint) keyinfo->base.block_length,
- new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- {
- print_error("Can't write indexblock, error: %d",my_errno);
- goto err;
- }
- DBUG_RETURN(0);
-err:
- if (temp_buff)
- my_afree((gptr) temp_buff);
- DBUG_RETURN(1);
-} /* sort_one_index */
-
-
- /* Change to use new file */
- /* Copy stats from old file to new file, deletes orginal and */
- /* changes new file name to old file name */
-
-static int change_to_newfile(filename,old_ext,new_ext)
-const char *filename,*old_ext,*new_ext;
-{
- char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
-
- return my_redel(fn_format(old_filename,filename,"",old_ext,2+4),
- fn_format(new_filename,filename,"",new_ext,2+4),
- MYF(MY_WME+MY_LINK_WARNING));
-} /* change_to_newfile */
-
-
- /* Locks a hole file */
- /* Gives error-message if file can't be locked */
-
-static int lock_file(file,start,lock_type,filetype,filename)
-File file;
-ulong start;
-int lock_type;
-const char *filetype,*filename;
-{
-#ifndef NO_LOCKING
- if (my_lock(file,lock_type,start,F_TO_EOF,
- testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) :
- MYF(MY_SEEK_NOT_DONE | MY_DONT_WAIT)))
- {
- print_error(" %d when %s %s '%s'",my_errno,
- lock_type == F_UNLCK ? "unlocking": "locking",
- filetype,filename);
- error_printed=2; /* Don't give that data is crashed */
- return 1;
- }
-#endif
- return 0;
-} /* lock_file */
-
-
- /* Copy a block between two files */
-
-static int filecopy(File to,File from,ulong start,ulong length,
- const char *type)
-{
- char tmp_buff[IO_SIZE],*buff;
- ulong buff_length;
- DBUG_ENTER("filecopy");
-
- buff_length=min(write_buffer_length,length);
- if (!(buff=my_malloc(buff_length,MYF(0))))
- {
- buff=tmp_buff; buff_length=IO_SIZE;
- }
-
- VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
- while (length > buff_length)
- {
- if (my_read(from,(byte*) buff,buff_length,MYF(MY_NABP)) ||
- my_write(to,(byte*) buff,buff_length,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- goto err;
- length-= buff_length;
- }
- if (my_read(from,(byte*) buff,(uint) length,MYF(MY_NABP)) ||
- my_write(to,(byte*) buff,(uint) length,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- goto err;
- if (buff != tmp_buff)
- my_free(buff,MYF(0));
- DBUG_RETURN(0);
-err:
- if (buff != tmp_buff)
- my_free(buff,MYF(0));
- print_error("Can't copy %s to tempfile, error %d",type,my_errno);
- DBUG_RETURN(1);
-}
-
-
- /* Fix table using sorting */
- /* saves new table in temp_filename */
-
-static int rep_by_sort(info,name)
-reg1 N_INFO *info;
-my_string name;
-{
- int got_error;
- uint i,length;
- ulong start_records,new_header_length,del;
- File new_file;
- SORT_PARAM sort_param;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("rep_by_sort");
-
- start_records=share->state.records;
- got_error=1;
- new_file= -1;
- new_header_length=(testflag & T_UNPACK) ? 0 : share->pack.header_length;
- if (!(testflag & T_SILENT))
- {
- printf("- recovering ISAM-table '%s'\n",name);
- printf("Data records: %lu\n",(ulong) start_records);
- }
- bzero((char*) &sort_info,sizeof(sort_info));
- if (!(sort_info.key_block=alloc_key_blocks((uint) sort_key_blocks,
- share->base.max_block))
- || init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length,
- READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) ||
- (! rep_quick &&
- init_io_cache(&info->rec_cache,info->dfile,(uint) write_buffer_length,
- WRITE_CACHE,new_header_length,1,
- MYF(MY_WME | MY_WAIT_IF_FULL))))
- goto err;
- sort_info.key_block_end=sort_info.key_block+sort_key_blocks;
- info->opt_flag|=WRITE_CACHE_USED;
- info->rec_cache.file=info->dfile; /* for sort_delete_record */
-
- if (!(sort_info.record=(byte*) my_alloca((uint) share->base.reclength)))
- {
- print_error("Not enough memory for extra record");
- goto err;
- }
- if (!rep_quick)
- {
- if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT,
- 2+4),
- 0,tmpfile_createflag,MYF(0))) < 0)
- {
- print_error("Can't create new tempfile: '%s'",temp_filename);
- goto err;
- }
- if (filecopy(new_file,info->dfile,0L,new_header_length,"datafile-header"))
- goto err;
- if (testflag & T_UNPACK)
- share->base.options&= ~HA_OPTION_COMPRESS_RECORD;
- share->state.dellink= NI_POS_ERROR;
- info->rec_cache.file=new_file;
- }
-
- info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- for (i=0 ; i < N_MAXKEY ; i++)
- share->state.key_del[i]=share->state.key_root[i]= NI_POS_ERROR;
- share->state.key_file_length=share->base.keystart;
-
- sort_info.info=info;
- if ((sort_info.new_data_file_type=share->data_file_type) ==
- COMPRESSED_RECORD && testflag & T_UNPACK)
- {
- if (share->base.options & HA_OPTION_PACK_RECORD)
- sort_info.new_data_file_type = DYNAMIC_RECORD;
- else
- sort_info.new_data_file_type = STATIC_RECORD;
- }
-
- sort_info.filepos=new_header_length;
- sort_info.dupp=0;
- read_cache.end_of_file=sort_info.filelength=
- (ulong) my_seek(read_cache.file,0L,MY_SEEK_END,MYF(0));
-
- if (share->data_file_type == DYNAMIC_RECORD)
- length=max(share->base.min_pack_length+1,share->base.min_block_length);
- else if (share->data_file_type == COMPRESSED_RECORD)
- length=share->base.min_block_length;
- else
- length=share->base.reclength;
- sort_param.max_records=sort_info.max_records=sort_info.filelength/length+1;
- sort_param.key_cmp=sort_key_cmp;
- sort_param.key_write=sort_key_write;
- sort_param.key_read=sort_key_read;
- sort_param.lock_in_memory=lock_memory;
- del=share->state.del;
-
- for (sort_info.key=0 ; sort_info.key < share->state.keys ; sort_info.key++)
- {
- if ((!(testflag & T_SILENT)))
- printf ("- Fixing index %d\n",sort_info.key+1);
- sort_info.max_pos=sort_info.pos=share->pack.header_length;
- sort_info.keyinfo=share->keyinfo+sort_info.key;
- sort_info.keyseg=sort_info.keyinfo->seg;
- sort_info.fix_datafile= (my_bool) (sort_info.key == 0 && ! rep_quick);
- sort_info.unique=0;
- sort_param.key_length=share->rec_reflength;
- for (i=0 ; sort_info.keyseg[i].base.type ; i++)
- sort_param.key_length+=sort_info.keyseg[i].base.length+
- (sort_info.keyseg[i].base.flag & HA_SPACE_PACK ? 1 : 0);
- share->state.records=share->state.del=share->state.empty=share->state.splitt=0;
-
- if (_create_index_by_sort(&sort_param,
- (pbool) (!(testflag & T_VERBOSE)),
- (uint) sort_buffer_length))
- goto err;
- /* Set for next loop */
- sort_param.max_records=sort_info.max_records=share->state.records;
- share->base.rec_per_key[sort_info.key]=
- sort_info.unique ? ((sort_info.max_records+sort_info.unique/2)/
- sort_info.unique)
- : 1L;
-
- if (sort_info.fix_datafile)
- {
- info->dfile=new_file;
- share->state.data_file_length=sort_info.filepos;
- share->state.splitt=share->state.records; /* Only hole records */
- share->state.version=(ulong) time((time_t*) 0);
- out_flag|=O_NEW_DATA; /* Data in new file */
- read_cache.end_of_file=sort_info.filepos;
- if (write_data_suffix(info) || end_io_cache(&info->rec_cache))
- goto err;
- share->data_file_type=sort_info.new_data_file_type;
- share->pack.header_length=new_header_length;
- }
- else
- share->state.data_file_length=sort_info.max_pos;
-
- if (flush_pending_blocks())
- goto err;
-
- read_cache.file=info->dfile; /* re-init read cache */
- reinit_io_cache(&read_cache,READ_CACHE,share->pack.header_length,1,1);
- }
-
- if (testflag & T_WRITE_LOOP)
- {
- VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
- }
-
- if (rep_quick && del+sort_info.dupp != share->state.del)
- {
- print_error("Couldn't fix table with quick recovery: Found wrong number of deleted records");
- print_error("Run recovery again without -q");
- got_error=1;
- goto err;
- }
-
- if (rep_quick != 1)
- {
- ulong skr=share->state.data_file_length+
- (share->base.options & HA_OPTION_COMPRESS_RECORD ?
- MEMMAP_EXTRA_MARGIN : 0);
-#ifdef USE_RELOC
- if (share->data_file_type == STATIC_RECORD &&
- skr < share->base.reloc*share->base.min_pack_length)
- skr=share->base.reloc*share->base.min_pack_length;
-#endif
- if (skr != sort_info.filelength)
- if (my_chsize(info->dfile, skr, 0, MYF(0)))
- print_warning("Can't change size of datafile, error: %d",my_errno);
- }
- if (my_chsize(share->kfile, share->state.key_file_length, 0, MYF(0)))
- print_warning("Can't change size of indexfile, error: %d",my_errno);
-
- if (!(testflag & T_SILENT))
- {
- if (start_records != share->state.records)
- printf("Data records: %lu\n",(ulong) share->state.records);
- if (sort_info.dupp)
- print_warning("%lu records have been removed",(ulong) sort_info.dupp);
- }
- got_error=0;
-
-err:
- if (got_error)
- {
- if (! error_printed)
- print_error("%d when fixing table",my_errno);
- if (new_file >= 0)
- {
- VOID(end_io_cache(&info->rec_cache));
- VOID(my_close(new_file,MYF(0)));
- VOID(my_delete(temp_filename,MYF(MY_WME)));
- }
- }
- if (sort_info.key_block)
- my_free((gptr) sort_info.key_block,MYF(0));
- if (sort_info.record)
- {
- my_afree(sort_info.record);
- }
- VOID(end_io_cache(&read_cache));
- VOID(end_io_cache(&info->rec_cache));
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- if (!got_error && testflag & T_UNPACK)
- {
- share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
- share->pack.header_length=0;
- }
- DBUG_RETURN(got_error);
-} /* rep_by_sort */
-
-
- /* Read next record and return next key */
-
-static int sort_key_read(key)
-void *key;
-{
- int error;
- N_INFO *info;
- DBUG_ENTER("sort_key_read");
-
- info=sort_info.info;
-
- if ((error=sort_get_next_record()))
- DBUG_RETURN(error);
- if (info->s->state.records == sort_info.max_records)
- {
- print_error("Found too many records; Can`t continue");
- DBUG_RETURN(1);
- }
- VOID(_nisam_make_key(info,sort_info.key,key,sort_info.record,
- sort_info.filepos));
- DBUG_RETURN(sort_write_record());
-} /* sort_key_read */
-
-
- /* Read next record from file using parameters in sort_info */
- /* Return -1 if end of file, 0 if ok and > 0 if error */
-
-static int sort_get_next_record()
-{
- int searching;
- uint found_record,b_type,left_length;
- ulong pos;
- byte *to;
- BLOCK_INFO block_info;
- N_INFO *info;
- ISAM_SHARE *share;
- DBUG_ENTER("sort_get_next_record");
-
- info=sort_info.info;
- share=info->s;
- switch (share->data_file_type) {
- case STATIC_RECORD:
- for (;;)
- {
- if (my_b_read(&read_cache,sort_info.record,share->base.reclength))
- DBUG_RETURN(-1);
- sort_info.start_recpos=sort_info.pos;
- if (!sort_info.fix_datafile)
- sort_info.filepos=sort_info.pos;
- sort_info.max_pos=(sort_info.pos+=share->base.reclength);
- share->state.splitt++;
- if (*sort_info.record)
- DBUG_RETURN(0);
- if (!sort_info.fix_datafile)
- {
- share->state.del++;
- share->state.empty+=share->base.reclength;
- }
- }
- case DYNAMIC_RECORD:
- LINT_INIT(to);
- pos=sort_info.pos;
- searching=(sort_info.fix_datafile && (testflag & T_EXTEND));
- for (;;)
- {
- found_record=block_info.second_read= 0;
- left_length=1;
- do
- {
- if (pos > sort_info.max_pos)
- sort_info.max_pos=pos;
- if (found_record && pos == search_after_block)
- print_info("Block: %lu used by record at %lu",
- search_after_block,
- sort_info.start_recpos);
- if (_nisam_read_cache(&read_cache,(byte*) block_info.header,pos,
- BLOCK_INFO_HEADER_LENGTH, test(! found_record) | 2))
- {
- if (found_record)
- {
- print_info("Can't read whole record at %lu (errno: %d)",
- (ulong) sort_info.start_recpos,errno);
- goto try_next;
- }
- DBUG_RETURN(-1);
- }
- if (searching && ! sort_info.fix_datafile)
- {
- error_printed=1;
- DBUG_RETURN(1); /* Something wrong with data */
- }
- if (((b_type=_nisam_get_block_info(&block_info,-1,pos)) &
- (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
- ((b_type & BLOCK_FIRST) &&
- (block_info.rec_len < (uint) share->base.min_pack_length ||
- block_info.rec_len > (uint) share->base.max_pack_length)))
- {
- uint i;
- if (testflag & T_VERBOSE || searching == 0)
- print_info("Wrong bytesec: %3d-%3d-%3d at %10lu; Skipped",
- block_info.header[0],block_info.header[1],
- block_info.header[2],pos);
- if (found_record)
- goto try_next;
- block_info.second_read=0;
- searching=1;
- 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;
- continue;
- }
- if (block_info.block_len+ (uint) (block_info.filepos-pos) <
- share->base.min_block_length ||
- block_info.block_len-4 > (uint) share->base.max_pack_length)
- {
- if (!searching)
- print_info("Found block with impossible length %u at %lu; Skipped",
- block_info.block_len+ (uint) (block_info.filepos-pos),
- (ulong) pos);
- if (found_record)
- goto try_next;
- searching=1;
- pos++;
- block_info.second_read=0;
- continue;
- }
- if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
- {
- if (!sort_info.fix_datafile && (b_type & BLOCK_DELETED))
- {
- share->state.empty+=block_info.block_len;
- share->state.del++;
- share->state.splitt++;
- }
- if (found_record)
- goto try_next;
- /* Check if impossible big deleted block */
- if (block_info.block_len > share->base.max_pack_length +4)
- searching=1;
- if (searching)
- pos++;
- else
- pos=block_info.filepos+block_info.block_len;
- block_info.second_read=0;
- continue;
- }
-
- share->state.splitt++;
- if (! found_record++)
- {
- sort_info.find_length=left_length=block_info.rec_len;
- sort_info.start_recpos=pos;
- if (!sort_info.fix_datafile)
- sort_info.filepos=sort_info.start_recpos;
- if (sort_info.fix_datafile && (testflag & T_EXTEND))
- sort_info.pos=block_info.filepos+1;
- else
- sort_info.pos=block_info.filepos+block_info.block_len;
- if (share->base.blobs)
- {
- if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
- {
- print_error("Not enough memory for blob at %lu",
- (ulong) sort_info.start_recpos);
- DBUG_RETURN(-1);
- }
- }
- else
- to= info->rec_buff;
- }
- if (left_length < block_info.data_len || ! block_info.data_len)
- {
- print_info("Found block with too small length at %lu; Skipped",
- (ulong) sort_info.start_recpos);
- goto try_next;
- }
- if (block_info.filepos + block_info.data_len > read_cache.end_of_file)
- {
- print_info("Found block that points outside data file at %lu",
- (ulong) sort_info.start_recpos);
- goto try_next;
- }
- if (_nisam_read_cache(&read_cache,to,block_info.filepos,
- block_info.data_len, test(found_record == 1)))
- {
- print_info("Read error for block at: %lu (error: %d); Skipped",
- (ulong) block_info.filepos,my_errno);
- goto try_next;
- }
- left_length-=block_info.data_len;
- to+=block_info.data_len;
- pos=block_info.next_filepos;
- if (pos == NI_POS_ERROR && left_length)
- {
- print_info("Wrong block with wrong total length starting at %lu",
- (ulong) sort_info.start_recpos);
- goto try_next;
- }
- if (pos + BLOCK_INFO_HEADER_LENGTH > read_cache.end_of_file)
- {
- print_info("Found link that points at %lu (outside data file) at %lu",
- (ulong) pos,(ulong) sort_info.start_recpos);
- goto try_next;
- }
- } while (left_length);
-
- if (_nisam_rec_unpack(info,sort_info.record,info->rec_buff,
- sort_info.find_length) != MY_FILE_ERROR)
- {
- if (read_cache.error < 0)
- DBUG_RETURN(1);
- if ((testflag & (T_EXTEND | T_REP)) || searching)
- {
- if (_nisam_rec_check(info, sort_info.record))
- {
- print_info("Found wrong packed record at %lu",
- (ulong) sort_info.start_recpos);
- goto try_next;
- }
- }
- DBUG_RETURN(0);
- }
- if (!searching)
- {
- print_info("Found wrong packed record at %lu",
- (ulong) sort_info.start_recpos);
- }
- try_next:
- pos=sort_info.start_recpos+1;
- searching=1;
- }
- case COMPRESSED_RECORD:
- for (searching=0 ;; searching=1, sort_info.pos++)
- {
- if (_nisam_read_cache(&read_cache,(byte*) block_info.header,sort_info.pos,
- share->pack.ref_length,1))
- DBUG_RETURN(-1);
- if (searching && ! sort_info.fix_datafile)
- {
- error_printed=1;
- DBUG_RETURN(1); /* Something wrong with data */
- }
- sort_info.start_recpos=sort_info.pos;
- VOID(_nisam_pack_get_block_info(&block_info,share->pack.ref_length,-1,
- sort_info.pos));
- if (!block_info.rec_len &&
- sort_info.pos + MEMMAP_EXTRA_MARGIN == read_cache.end_of_file)
- DBUG_RETURN(-1);
- if (block_info.rec_len < (uint) share->min_pack_length ||
- block_info.rec_len > (uint) share->max_pack_length)
- {
- if (! searching)
- print_info("Found block with wrong recordlength: %d at %lu\n",
- block_info.rec_len, (ulong) sort_info.pos);
- continue;
- }
- if (_nisam_read_cache(&read_cache,(byte*) info->rec_buff,
- block_info.filepos, block_info.rec_len,1))
- {
- if (! searching)
- print_info("Couldn't read hole record from %lu",
- (ulong) sort_info.pos);
- continue;
- }
- if (_nisam_pack_rec_unpack(info,sort_info.record,info->rec_buff,
- block_info.rec_len))
- {
- if (! searching)
- print_info("Found wrong record at %lu",(ulong) sort_info.pos);
- continue;
- }
- if (!sort_info.fix_datafile)
- sort_info.filepos=sort_info.pos;
- sort_info.max_pos=(sort_info.pos+=share->pack.ref_length+
- block_info.rec_len);
- share->state.splitt++;
- info->packed_length=block_info.rec_len;
- DBUG_RETURN(0);
- }
- }
- DBUG_RETURN(1); /* Impossible */
-}
-
-
- /* Write record to new file */
-
-static int sort_write_record()
-{
- int flag;
- uint block_length,reclength;
- byte *from;
- uchar *block_buff[3];
- N_INFO *info;
- ISAM_SHARE *share;
- DBUG_ENTER("sort_write_record");
-
- info=sort_info.info;
- share=info->s;
- if (sort_info.fix_datafile)
- {
- switch (sort_info.new_data_file_type) {
- case STATIC_RECORD:
- if (my_b_write(&info->rec_cache,sort_info.record, share->base.reclength))
- {
- print_error("%d when writing to datafile",my_errno);
- DBUG_RETURN(1);
- }
- sort_info.filepos+=share->base.reclength;
- break;
- case DYNAMIC_RECORD:
- if (! info->blobs)
- from=info->rec_buff;
- else
- {
- /* must be sure that local buffer is big enough */
- reclength=info->s->base.pack_reclength+
- _calc_total_blob_length(info,sort_info.record)+
- ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (sort_info.buff_length < reclength)
- {
- if (!(sort_info.buff=my_realloc(sort_info.buff, (uint) reclength,
- MYF(MY_FREE_ON_ERROR |
- MY_ALLOW_ZERO_PTR))))
- DBUG_RETURN(1);
- sort_info.buff_length=reclength;
- }
- from=sort_info.buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER);
- }
- reclength=_nisam_rec_pack(info,from,sort_info.record);
- block_length=reclength+ 3 +test(reclength > 65532L);
- if (block_length < share->base.min_block_length)
- block_length=share->base.min_block_length;
- flag=0;
- info->update|=HA_STATE_WRITE_AT_END;
- if (_nisam_write_part_record(info,0L,block_length,NI_POS_ERROR,
- &from,&reclength,&flag))
- {
- print_error("%d when writing to datafile",my_errno);
- DBUG_RETURN(1);
- }
- sort_info.filepos+=block_length;
- break;
- case COMPRESSED_RECORD:
- reclength=info->packed_length;
- save_integer((byte*) block_buff,share->pack.ref_length,reclength);
- if (my_b_write(&info->rec_cache,(byte*) block_buff,share->pack.ref_length)
- || my_b_write(&info->rec_cache,(byte*) info->rec_buff,reclength))
- {
- print_error("%d when writing to datafile",my_errno);
- DBUG_RETURN(1);
- }
- sort_info.filepos+=reclength+share->pack.ref_length;
- break;
- }
- }
- share->state.records++;
- if (testflag & T_WRITE_LOOP && share->state.records % WRITE_COUNT == 0)
- {
- printf("%lu\r",(ulong) share->state.records); VOID(fflush(stdout));
- }
- DBUG_RETURN(0);
-} /* sort_write_record */
-
-
- /* Compare two keys from _create_index_by_sort */
-
-static int sort_key_cmp(const void *not_used __attribute__((unused)),
- const void *a,const void *b)
-{
- return (_nisam_key_cmp(sort_info.keyseg,*((uchar**) a),*((uchar**) b),0,
- SEARCH_SAME));
-} /* sort_key_cmp */
-
-
-static int sort_key_write( const void *a)
-{
- int cmp=sort_info.key_block->inited ?
- _nisam_key_cmp(sort_info.keyseg,sort_info.key_block->lastkey,(uchar*) a,
- 0,SEARCH_FIND) : -1L;
- if ((sort_info.keyinfo->base.flag & HA_NOSAME) &&
- cmp == 0)
- {
- sort_info.dupp++;
- print_warning("Dupplicate key for record at %10lu against record at %10lu",
- sort_info.info->lastpos=get_record_for_key(sort_info.info,
- sort_info.keyinfo,
- (uchar*) a),
- get_record_for_key(sort_info.info,sort_info.keyinfo,
- sort_info.key_block->lastkey));
- if (testflag & T_VERBOSE)
- _nisam_print_key(stdout,sort_info.keyseg,(uchar*) a);
- return(sort_delete_record());
- }
- if (cmp)
- sort_info.unique++;
-#ifndef DBUG_OFF
- if (cmp > 0)
- {
- print_error("Fatal intern error: Keys are not in order from sort");
- return(1);
- }
-#endif
- return (sort_insert_key(sort_info.key_block,(uchar*) a,NI_POS_ERROR));
-} /* sort_key_write */
-
-
- /* get pointer to record from a key */
-
-static ulong get_record_for_key( N_INFO *info, N_KEYDEF *keyinfo, uchar *key)
-{
- return _nisam_dpos(info,0,key+_nisam_keylength(keyinfo,key));
-} /* get_record_for_key */
-
-
- /* Insert a key in sort-key-blocks */
-
-static int sort_insert_key(reg1 ISAM_SORT_KEY_BLOCKS *key_block,
- uchar *key, ulong prev_block)
-{
- uint a_length,t_length,nod_flag;
- ulong filepos;
- uchar *anc_buff,*lastkey;
- S_PARAM s_temp;
- N_INFO *info;
- DBUG_ENTER("sort_insert_key");
-
- anc_buff=key_block->buff;
- info=sort_info.info;
- lastkey=key_block->lastkey;
- nod_flag= (key_block == sort_info.key_block ? 0 :
- sort_info.info->s->base.key_reflength);
-
- if (!key_block->inited)
- {
- key_block->inited=1;
- if (key_block == sort_info.key_block_end)
- {
- print_error("To many keyblocklevels; Try increasing sort_key_blocks");
- DBUG_RETURN(1);
- }
- a_length=2+nod_flag;
- key_block->end_pos=anc_buff+2;
- lastkey=0; /* No previous key in block */
- }
- else
- a_length=getint(anc_buff);
-
- /* Save pointer to previous block */
- if (nod_flag)
- _nisam_kpointer(info,key_block->end_pos,prev_block);
-
- t_length=_nisam_get_pack_key_length(sort_info.keyinfo,nod_flag,
- (uchar*) 0,lastkey,key,&s_temp);
- _nisam_store_key(sort_info.keyinfo,key_block->end_pos+nod_flag,&s_temp);
- a_length+=t_length;
- putint(anc_buff,a_length,nod_flag);
- key_block->end_pos+=t_length;
- if (a_length <= sort_info.keyinfo->base.block_length)
- {
- VOID(_nisam_move_key(sort_info.keyinfo,key_block->lastkey,key));
- key_block->last_length=a_length-t_length;
- DBUG_RETURN(0);
- }
-
- /* Fill block with end-zero and write filled block */
- putint(anc_buff,key_block->last_length,nod_flag);
- bzero((byte*) anc_buff+key_block->last_length,
- sort_info.keyinfo->base.block_length- key_block->last_length);
- if ((filepos=_nisam_new(info,sort_info.keyinfo)) == NI_POS_ERROR)
- return 1;
- if (my_pwrite(info->s->kfile,(byte*) anc_buff,
- (uint) sort_info.keyinfo->base.block_length,filepos,MYF_RW))
- DBUG_RETURN(1);
- DBUG_DUMP("buff",(byte*) anc_buff,getint(anc_buff));
-
- /* Write separator-key to block in next level */
- if (sort_insert_key(key_block+1,key_block->lastkey,filepos))
- DBUG_RETURN(1);
-
- /* clear old block and write new key in it */
- key_block->inited=0;
- DBUG_RETURN(sort_insert_key(key_block,key,prev_block));
-} /* sort_insert_key */
-
-
- /* Delete record when we found a dupplicated key */
-
-static int sort_delete_record()
-{
- uint i;
- int old_file,error;
- uchar *key;
- N_INFO *info;
- DBUG_ENTER("sort_delete_record");
-
- if (rep_quick == 1)
- {
- VOID(fputs("Quick-recover aborted; Run recovery without switch 'q' or with switch -qq\n",stderr));
- error_printed=1;
- DBUG_RETURN(1);
- }
- info=sort_info.info;
- if (info->s->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- VOID(fputs("Recover aborted; Can't run standard recovery on compressed tables\nwith errors in data-file\nUse switch '--safe-recover' to fix it\n",stderr));
- error_printed=1;
- DBUG_RETURN(1);
- }
-
- old_file=info->dfile;
- info->dfile=info->rec_cache.file;
- if (sort_info.key)
- {
- key=info->lastkey+info->s->base.max_key_length;
- if ((*info->s->read_rnd)(info,sort_info.record,info->lastpos,0) < 0)
- {
- print_error("Can't read record to be removed");
- info->dfile=old_file;
- DBUG_RETURN(1);
- }
-
- for (i=0 ; i < sort_info.key ; i++)
- {
- VOID(_nisam_make_key(info,i,key,sort_info.record,info->lastpos));
- if (_nisam_ck_delete(info,i,key))
- {
- print_error("Can't delete key %d from record to be removed",i+1);
- info->dfile=old_file;
- DBUG_RETURN(1);
- }
- }
- }
- error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
- info->dfile=old_file; /* restore actual value */
- info->s->state.records--;
- DBUG_RETURN(error);
-} /* sort_delete_record */
-
-
- /* Fix all pending blocks and flush everything to disk */
-
-static int flush_pending_blocks()
-{
- uint nod_flag,length;
- ulong filepos;
- N_INFO *info;
- ISAM_SORT_KEY_BLOCKS *key_block;
- DBUG_ENTER("flush_pending_blocks");
-
- filepos= NI_POS_ERROR; /* if empty file */
- info=sort_info.info;
- nod_flag=0;
- for (key_block=sort_info.key_block ; key_block->inited ; key_block++)
- {
- key_block->inited=0;
- length=getint(key_block->buff);
- if (nod_flag)
- _nisam_kpointer(info,key_block->end_pos,filepos);
- if ((filepos=_nisam_new(info,sort_info.keyinfo)) == NI_POS_ERROR)
- DBUG_RETURN(1);
- bzero((byte*) key_block->buff+length,
- sort_info.keyinfo->base.block_length-length);
- if (my_pwrite(info->s->kfile,(byte*) key_block->buff,
- (uint) sort_info.keyinfo->base.block_length,filepos,MYF_RW))
- DBUG_RETURN(1);
- DBUG_DUMP("buff",(byte*) key_block->buff,length);
- nod_flag=1;
- }
- info->s->state.key_root[sort_info.key]=filepos; /* Last is root for tree */
- DBUG_RETURN(0);
-} /* flush_pending_blocks */
-
-
- /* alloc space and pointers for key_blocks */
-
-static ISAM_SORT_KEY_BLOCKS *alloc_key_blocks(uint blocks, uint buffer_length)
-{
- reg1 uint i;
- ISAM_SORT_KEY_BLOCKS *block;
- DBUG_ENTER("alloc_key_blocks");
-
- if (!(block=(ISAM_SORT_KEY_BLOCKS*) my_malloc((sizeof(ISAM_SORT_KEY_BLOCKS)+
- buffer_length+IO_SIZE)*blocks,
- MYF(0))))
- {
- print_error("Not Enough memory for sort-key-blocks");
- return(0);
- }
- for (i=0 ; i < blocks ; i++)
- {
- block[i].inited=0;
- block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i;
- }
- DBUG_RETURN(block);
-} /* alloc_key_blocks */
-
-
- /* print warnings and errors */
- /* VARARGS */
-
-static void print_info(const char * fmt,...)
-{
- va_list args;
-
- va_start(args,fmt);
- VOID(vfprintf(stdout, fmt, args));
- VOID(fputc('\n',stdout));
- va_end(args);
- return;
-}
-
-/* VARARGS */
-
-static void print_warning(const char * fmt,...)
-{
- va_list args;
- DBUG_ENTER("print_warning");
-
- if (!warning_printed && !error_printed)
- {
- fflush(stdout);
- if (testflag & T_SILENT)
- fprintf(stderr,"%s: ISAM file %s\n",my_progname,isam_file_name);
- }
- warning_printed=1;
- va_start(args,fmt);
- fprintf(stderr,"%s: warning: ",my_progname);
- VOID(vfprintf(stderr, fmt, args));
- VOID(fputc('\n',stderr));
- va_end(args);
- DBUG_VOID_RETURN;
-}
-
-/* VARARGS */
-
-void print_error(const char *fmt,...)
-{
- va_list args;
- DBUG_ENTER("print_error");
- DBUG_PRINT("enter",("format: %s",fmt));
-
- if (!warning_printed && !error_printed)
- {
- fflush(stdout);
- if (testflag & T_SILENT)
- fprintf(stderr,"%s: ISAM file %s\n",my_progname,isam_file_name);
- }
- error_printed|=1;
- va_start(args,fmt);
- fprintf(stderr,"%s: error: ",my_progname);
- VOID(vfprintf(stderr, fmt, args));
- VOID(fputc('\n',stderr));
- va_end(args);
- DBUG_VOID_RETURN;
-}
-
- /* Check if file is almost full */
-
-static int test_if_almost_full(N_INFO *info)
-{
- double diff= 0.9;
- if (info->s->base.options & HA_OPTION_COMPRESS_RECORD)
- { /* Fix problem with pack_isam */
- diff=1.0;
- if (info->s->base.rec_reflength == 4)
- info->s->base.max_data_file_length= (uint32) ~0L;
- else
- info->s->base.max_data_file_length=
- 1L << (info->s->base.rec_reflength);
- }
- return (my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)) >
- (ulong) (info->s->base.max_key_file_length*diff) ||
- my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) >
- (ulong) (info->s->base.max_data_file_length*diff));
-}
-
- /* Recreate table with bigger more alloced record-data */
-
-static int recreate_database(N_INFO **org_info, char *filename)
-{
- int error;
- N_INFO info;
- ISAM_SHARE share;
- N_KEYDEF *keyinfo;
- N_RECINFO *recinfo,*rec,*end;
- uint unpack;
- ulong max_records;
- char name[FN_REFLEN];
-
- error=1; /* Default error */
- info= **org_info;
- share= *(*org_info)->s;
- unpack= (share.base.options & HA_OPTION_COMPRESS_RECORD) &&
- (testflag & T_UNPACK);
- if (!(keyinfo=(N_KEYDEF*) my_alloca(sizeof(N_KEYDEF)*share.base.keys)))
- return 0;
- memcpy((byte*) keyinfo,(byte*) share.keyinfo,
- (size_t) (sizeof(N_KEYDEF)*share.base.keys));
- if (!(recinfo=(N_RECINFO*)
- my_alloca(sizeof(N_RECINFO)*(share.base.fields+1))))
- {
- my_afree((gptr) keyinfo);
- return 1;
- }
- memcpy((byte*) recinfo,(byte*) share.rec,
- (size_t) (sizeof(N_RECINFO)*(share.base.fields+1)));
- for (rec=recinfo,end=recinfo+share.base.fields; rec != end ; rec++)
- {
- if (rec->base.type == (int) FIELD_BLOB)
- rec->base.length+=sizeof(char*);
- else if (unpack && !(share.base.options & HA_OPTION_PACK_RECORD))
- rec->base.type=(int) FIELD_NORMAL;
- }
-
- if (share.base.options & HA_OPTION_COMPRESS_RECORD)
- share.base.records=max_records=share.state.records;
- else if (share.base.min_pack_length)
- max_records=(ulong) (my_seek(info.dfile,0L,MY_SEEK_END,MYF(0)) /
- (ulong) share.base.min_pack_length);
- else
- max_records=0;
- unpack= (share.base.options & HA_OPTION_COMPRESS_RECORD) &&
- (testflag & T_UNPACK);
- share.base.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
- VOID(nisam_close(*org_info));
- if (nisam_create(fn_format(name,filename,"",N_NAME_IEXT,
- 4+ (opt_follow_links ? 16 : 0)),
- share.base.keys,keyinfo,recinfo,
- max(max_records,share.base.records),share.base.reloc,
- HA_DONT_TOUCH_DATA,
- share.base.options |
- (unpack ? HA_OPTION_TEMP_COMPRESS_RECORD
- : 0),
- (ulong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0))))
- {
- print_error("Got error %d when trying to recreate indexfile",my_errno);
- goto end;
- }
- *org_info=nisam_open(name,O_RDWR,
- (testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED :
- (testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED :
- HA_OPEN_ABORT_IF_LOCKED);
- if (!*org_info)
- {
- print_error("Got error %d when trying to open re-created indexfile",
- my_errno);
- goto end;
- }
- /* We are modifing */
- (*org_info)->s->base.options&= ~HA_OPTION_READ_ONLY_DATA;
- VOID(_nisam_readinfo(*org_info,F_WRLCK,0));
- (*org_info)->s->state.records=share.state.records;
- if (share.base.create_time)
- (*org_info)->s->base.create_time=share.base.create_time;
- (*org_info)->s->state.uniq=(*org_info)->this_uniq=
- share.state.uniq;
- (*org_info)->s->state.del=share.state.del;
- (*org_info)->s->state.dellink=share.state.dellink;
- (*org_info)->s->state.empty=share.state.empty;
- (*org_info)->s->state.data_file_length=share.state.data_file_length;
- if (update_state_info(*org_info,UPDATE_TIME | UPDATE_STAT))
- goto end;
- error=0;
-end:
- my_afree((gptr) keyinfo);
- my_afree((gptr) recinfo);
- return error;
-}
-
- /* Store long in 1,2,3 or 4 bytes */
-
-static void save_integer( byte *pos, uint pack_length, ulong value)
-{
- switch (pack_length) {
- case 4: int4store(pos,value); break;
- case 3: int3store(pos,value); break;
- case 2: int2store(pos,(uint) value); break;
- case 1: pos[0]= (char) (uchar) value; break;
- default: break;
- }
- return;
-}
-
- /* write suffix to data file if neaded */
-
-static int write_data_suffix( N_INFO *info)
-{
- if (info->s->base.options & HA_OPTION_COMPRESS_RECORD &&
- sort_info.fix_datafile)
- {
- char buff[MEMMAP_EXTRA_MARGIN];
- bzero(buff,sizeof(buff));
- if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
- {
- print_error("%d when writing to datafile",my_errno);
- return 1;
- }
- read_cache.end_of_file+=sizeof(buff);
- }
- return 0;
-}
-
-
- /* Update state and isamchk_time of indexfile */
-
-static int update_state_info( N_INFO *info, uint update)
-{
- ISAM_SHARE *share=info->s;
- uint base_pos=uint2korr(info->s->state.header.base_pos);
-
- if (update & (UPDATE_STAT | UPDATE_SORT | UPDATE_TIME))
- {
- if (offsetof(N_BASE_INFO,rec_per_key) >
- uint2korr(share->state.header.base_info_length))
- {
- VOID(fputs("Internal error: Trying to change base of old table\n",
- stderr));
- }
- else
- {
- if (update & UPDATE_TIME)
- {
- share->base.isamchk_time= (long) time((time_t*) 0);
- if (!share->base.create_time)
- share->base.create_time=share->base.isamchk_time;
- if (my_pwrite(share->kfile,(gptr) &share->base.create_time,
- sizeof(long)*2,
- base_pos+offsetof(N_BASE_INFO,create_time),
- MYF(MY_NABP)))
- goto err;
- }
- if (update & (UPDATE_STAT | UPDATE_SORT))
- {
- if (my_pwrite(share->kfile,(gptr) share->base.rec_per_key,
- sizeof(long)*share->state.keys+sizeof(uint),
- base_pos+offsetof(N_BASE_INFO,rec_per_key),
- MYF(MY_NABP)))
- goto err;
- }
- }
- }
- { /* Force update of status */
- int error;
- uint r_locks=share->r_locks,w_locks=share->w_locks;
- share->r_locks=share->w_locks=0;
- error=_nisam_writeinfo(info,2);
- share->r_locks=r_locks; share->w_locks=w_locks;
- if (!error)
- return 0;
- }
-err:
- print_error("%d when updating keyfile",my_errno);
- return 1;
-}
diff --git a/isam/isamdef.h b/isam/isamdef.h
deleted file mode 100644
index 7d89730fe32..00000000000
--- a/isam/isamdef.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Denna fil includeras i alla isam-filer */
-
-#define ISAM_LIBRARY
-#include <nisam.h> /* Structs & some defines */
-#ifdef THREAD
-#include <my_pthread.h>
-#include <thr_lock.h>
-#else
-#include <my_no_pthread.h>
-#endif
-#include <keycache.h>
-
-#ifdef my_write
-#undef my_write /* We want test if disk full */
-#endif
-#undef HA_SORT_ALLOWS_SAME
-#define HA_SORT_ALLOWS_SAME 128 /* Can't be > 128 in NISAM */
-
-#ifdef __WATCOMC__
-#pragma pack(2)
-#define uint uint16 /* Same format as in MSDOS */
-#endif
-#ifdef __ZTC__
-#pragma ZTC align 2
-#define uint uint16 /* Same format as in MSDOS */
-#endif
-#if defined(__WIN__) && defined(_MSC_VER)
-#pragma pack(push,isamdef,2)
-#define uint uint16
-#endif
-
-typedef struct st_state_info
-{
- struct { /* Fileheader */
- uchar file_version[4];
- uchar options[2];
- uchar header_length[2];
- uchar state_info_length[2];
- uchar base_info_length[2];
- uchar base_pos[2];
- uchar not_used[2];
- } header;
-
- ulong records; /* Antal record i databasen */
- ulong del; /* Antalet borttagna poster */
- ulong dellink; /* L{nk till n{sta borttagna */
- ulong key_file_length;
- ulong data_file_length;
- ulong splitt; /* Antal splittrade delar */
- ulong empty; /* Outnyttjat utrymme */
- ulong process; /* Vem som senast uppdatera */
- ulong loop; /* not used anymore */
- ulong uniq; /* Unik nr i denna process */
- ulong key_root[N_MAXKEY]; /* Pekare till rootblocken */
- ulong key_del[N_MAXKEY]; /* Del-l{nkar f|r n-block */
- ulong sec_index_changed; /* Updated when new sec_index */
- ulong sec_index_used; /* 1 bit for each sec index in use */
- ulong version; /* timestamp of create */
- uint keys; /* Keys in use for database */
-} N_STATE_INFO;
-
-
-typedef struct st_base_info
-{
- ulong keystart; /* Var nycklarna b|rjar */
- ulong records,reloc; /* Parameter vid skapandet */
- ulong max_pack_length; /* Max possibly length of packed rec.*/
- ulong max_data_file_length;
- ulong max_key_file_length;
- uint reclength; /* length of unpacked record */
- uint options; /* Options used */
- uint pack_reclength; /* Length of full packed rec. */
- uint min_pack_length;
- uint min_block_length;
- uint rec_reflength; /* = 2 or 3 or 4 */
- uint key_reflength; /* = 2 or 3 or 4 */
- uint keys; /* Keys defined for database */
- uint blobs; /* Number of blobs */
- uint max_block; /* Max blockl{ngd anv{nd */
- uint max_key_length; /* L{ngsta nyckel-l{ngden */
- uint fields, /* Antal f{lt i databasen */
- pack_fields, /* Packade f{lt i databasen */
- pack_bits; /* Length of packed bits */
- time_t create_time; /* Time when created database */
- time_t isamchk_time; /* Time for last recover */
- ulong rec_per_key[N_MAXKEY]; /* for sql optimizing */
- uint sortkey; /* sorted by this key */
-} N_BASE_INFO;
-
-
-#ifdef __ZTC__
-#pragma ZTC align
-#undef uint
-#endif
-#ifdef __WATCOMC__
-#pragma pack()
-#undef uint
-#endif
-#if defined(__WIN__) && defined(_MSC_VER)
-#pragma pack(pop,isamdef)
-#undef uint
-#endif
-
- /* Structs used intern in database */
-
-typedef struct st_n_blob /* Info of record */
-{
- uint offset; /* Offset to blob in record */
- uint pack_length; /* Type of packed length */
- uint length; /* Calc:ed for each record */
-} N_BLOB;
-
-
-typedef struct st_isam_pack {
- ulong header_length;
- uint ref_length;
-} N_PACK;
-
-
-typedef struct st_isam_share { /* Shared between opens */
- N_STATE_INFO state;
- N_BASE_INFO base;
- N_KEYDEF *keyinfo; /* Nyckelinfo */
- N_RECINFO *rec; /* Pointer till recdata */
- N_PACK pack; /* Data about packed records */
- N_BLOB *blobs; /* Pointer to blobs */
- char *filename; /* Name of indexfile */
- byte *file_map; /* mem-map of file if possible */
- ulong this_process; /* processid */
- ulong last_process; /* For table-change-check */
- ulong last_version; /* Version on start */
- uint rec_reflength; /* rec_reflength in use now */
- int kfile; /* Shared keyfile */
- int mode; /* mode of file on open */
- int reopen; /* How many times reopened */
- uint state_length;
- uint w_locks,r_locks; /* Number of read/write locks */
- uint min_pack_length; /* Theese is used by packed data */
- uint max_pack_length;
- uint blocksize; /* blocksize of keyfile */
- my_bool changed,not_flushed; /* If changed since lock */
- int rnd; /* rnd-counter */
- DECODE_TREE *decode_trees;
- uint16 *decode_tables;
- enum data_file_type data_file_type;
- int (*read_record)(struct st_isam_info*, ulong, byte*);
- int (*write_record)(struct st_isam_info*, const byte*);
- int (*update_record)(struct st_isam_info*, ulong, const byte*);
- int (*delete_record)(struct st_isam_info*);
- int (*read_rnd)(struct st_isam_info*, byte*, ulong, int);
- int (*compare_record)(struct st_isam_info*, const byte *);
-#ifdef THREAD
- THR_LOCK lock;
- pthread_mutex_t intern_lock; /* Locking for use with _locking */
-#endif
-} ISAM_SHARE;
-
-
-typedef uint bit_type;
-
-typedef struct st_bit_buff { /* Used for packing of record */
- bit_type current_byte;
- uint bits;
- uchar *pos,*end;
- uint error;
-} BIT_BUFF;
-
-
-typedef struct st_isam_info {
- ISAM_SHARE *s; /* Shared between open:s */
- N_BLOB *blobs; /* Pointer to blobs */
- int dfile; /* The datafile */
- BIT_BUFF bit_buff;
- uint options;
- uint opt_flag; /* Optim. for space/speed */
- uint update; /* If file changed since open */
- char *filename; /* parameter to open filename */
- ulong this_uniq; /* uniq filenumber or thread */
- ulong last_uniq; /* last uniq number */
- ulong this_loop; /* counter for this open */
- ulong last_loop; /* last used counter */
- ulong lastpos, /* Last record position */
- nextpos; /* Position to next record */
- ulong int_pos; /* Intern variabel */
- ulong dupp_key_pos; /* Position to record with dupp key */
- ulong last_search_keypage;
- ulong save_lastpos;
- uint packed_length; /* Length of found, packed record */
- uint alloced_rec_buff_length; /* Max recordlength malloced */
- uchar *buff, /* Temp area for key */
- *lastkey; /* Last used search key */
- byte *rec_buff, /* Tempbuff for recordpack */
- *rec_alloc; /* Malloced area for record */
- uchar *int_keypos, /* Intern variabel */
- *int_maxpos; /* Intern variabel */
- int lastinx; /* Last used index */
- int errkey; /* Got last error on this key */
- uint data_changed; /* Somebody has changed data */
- int lock_type; /* How database was locked */
- int tmp_lock_type; /* When locked by readinfo */
- int was_locked; /* Was locked in panic */
- myf lock_wait; /* is 0 or MY_DONT_WAIT */
- my_bool page_changed;
- my_bool buff_used;
- uint save_update; /* When using KEY_READ */
- int save_lastinx;
- int (*read_record)(struct st_isam_info*, ulong, byte*);
- LIST open_list;
- IO_CACHE rec_cache; /* When cacheing records */
-#ifdef THREAD
- THR_LOCK_DATA lock;
-#endif
-} N_INFO;
-
-
- /* Some defines used by isam-funktions */
-
-#define USE_HOLE_KEY 0 /* Use hole key in _nisam_search() */
-#define F_EXTRA_LCK -1
-
- /* bits in opt_flag */
-#define MEMMAP_USED 32
-#define REMEMBER_OLD_POS 64
-
-#define getint(x) ((uint) (uint16) *((int16*) (x)) & 32767)
-#define putint(x,y,nod) (*((uint16*) (x))= ((nod ? (uint16) 32768 : 0)+(uint16) (y)))
-#ifdef WORDS_BIGENDIAN
-#define test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0)
-#else
-#define test_if_nod(x) (x[1] & 128 ? info->s->base.key_reflength : 0)
-#endif
-
-#define N_MIN_BLOCK_LENGTH 8 /* Because of delete-link */
-#define N_EXTEND_BLOCK_LENGTH 20 /* Don't use to small record-blocks */
-#define N_SPLITT_LENGTH ((N_EXTEND_BLOCK_LENGTH+3)*2)
-#define MAX_DYN_BLOCK_HEADER 11 /* Max prefix of record-block */
-#define DYN_DELETE_BLOCK_HEADER 8 /* length of delete-block-header */
-#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */
-#define INDEX_BLOCK_MARGIN 16 /* Safety margin for .ISM tables */
-
-#define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */
-#define PACK_TYPE_SPACE_FIELDS 2
-#define PACK_TYPE_ZERO_FILL 4
-
-#ifdef THREAD
-extern pthread_mutex_t THR_LOCK_isam;
-#endif
-
- /* Some extern variables */
-
-extern LIST *nisam_open_list;
-extern uchar NEAR nisam_file_magic[],NEAR nisam_pack_file_magic[];
-extern uint NEAR nisam_read_vec[],nisam_quick_table_bits;
-extern File nisam_log_file;
-
- /* This is used by _nisam_get_pack_key_length och _nisam_store_key */
-
-typedef struct st_s_param
-{
- uint ref_length,key_length,
- n_ref_length,
- n_length,
- totlength,
- part_of_prev_key,prev_length;
- uchar *key, *prev_key;
-} S_PARAM;
-
- /* Prototypes for intern functions */
-
-extern int _nisam_read_dynamic_record(N_INFO *info,ulong filepos,byte *buf);
-extern int _nisam_write_dynamic_record(N_INFO*, const byte*);
-extern int _nisam_update_dynamic_record(N_INFO*, ulong, const byte*);
-extern int _nisam_delete_dynamic_record(N_INFO *info);
-extern int _nisam_cmp_dynamic_record(N_INFO *info,const byte *record);
-extern int _nisam_read_rnd_dynamic_record(N_INFO *, byte *,ulong, int);
-extern int _nisam_write_blob_record(N_INFO*, const byte*);
-extern int _nisam_update_blob_record(N_INFO*, ulong, const byte*);
-extern int _nisam_read_static_record(N_INFO *info,ulong filepos,byte *buf);
-extern int _nisam_write_static_record(N_INFO*, const byte*);
-extern int _nisam_update_static_record(N_INFO*, ulong, const byte*);
-extern int _nisam_delete_static_record(N_INFO *info);
-extern int _nisam_cmp_static_record(N_INFO *info,const byte *record);
-extern int _nisam_read_rnd_static_record(N_INFO*, byte *,ulong, int);
-extern int _nisam_ck_write(N_INFO *info,uint keynr,uchar *key);
-extern int _nisam_enlarge_root(N_INFO *info,uint keynr,uchar *key);
-extern int _nisam_insert(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- uchar *anc_buff,uchar *key_pos,uchar *key_buff,
- uchar *father_buff, uchar *father_keypos,
- ulong father_page);
-extern int _nisam_splitt_page(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- uchar *buff,uchar *key_buff);
-extern uchar *_nisam_find_half_pos(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,
- uchar *key);
-extern uint _nisam_get_pack_key_length(N_KEYDEF *keyinfo,uint nod_flag,
- uchar *key_pos,uchar *key_buff,
- uchar *key, S_PARAM *s_temp);
-extern void _nisam_store_key(N_KEYDEF *keyinfo,uchar *key_pos,
- S_PARAM *s_temp);
-extern int _nisam_ck_delete(N_INFO *info,uint keynr,uchar *key);
-extern int _nisam_readinfo(N_INFO *info,int lock_flag,int check_keybuffer);
-extern int _nisam_writeinfo(N_INFO *info, uint flag);
-extern int _nisam_test_if_changed(N_INFO *info);
-extern int _nisam_check_index(N_INFO *info,int inx);
-extern int _nisam_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uint key_len,uint nextflag,ulong pos);
-extern int _nisam_bin_search(struct st_isam_info *info,N_KEYDEF *keyinfo,uchar *page,uchar *key,uint key_len,uint comp_flag,uchar * *ret_pos,uchar *buff);
-extern int _nisam_seq_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,uchar *key,uint key_len,uint comp_flag,uchar * *ret_pos,uchar *buff);
-extern ulong _nisam_kpos(uint nod_flag,uchar *after_key);
-extern void _nisam_kpointer(N_INFO *info,uchar *buff,ulong pos);
-extern ulong _nisam_dpos(N_INFO *info, uint nod_flag,uchar *after_key);
-extern void _nisam_dpointer(N_INFO *info, uchar *buff,ulong pos);
-extern int _nisam_key_cmp(N_KEYSEG *keyseg,uchar *a,uchar *b,
- uint key_length,uint nextflag);
-extern uint _nisam_get_key(N_KEYDEF *keyinfo,uint nod_flag,uchar * *page,uchar *key);
-extern uint _nisam_get_static_key(N_KEYDEF *keyinfo,uint nod_flag,uchar * *page,uchar *key);
-extern uchar *_nisam_get_last_key(N_INFO *info,N_KEYDEF *keyinfo,uchar *keypos,uchar *lastkey,uchar *endpos);
-extern uint _nisam_keylength(N_KEYDEF *keyinfo,uchar *key);
-extern uchar *_nisam_move_key(N_KEYDEF *keyinfo,uchar *to,uchar *from);
-extern int _nisam_search_next(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uint nextflag,ulong pos);
-extern int _nisam_search_first(N_INFO *info,N_KEYDEF *keyinfo,ulong pos);
-extern int _nisam_search_last(N_INFO *info,N_KEYDEF *keyinfo,ulong pos);
-extern uchar *_nisam_fetch_keypage(N_INFO *info,N_KEYDEF *keyinfo,my_off_t page,
- uchar *buff,int return_buffer);
-extern int _nisam_write_keypage(N_INFO *info,N_KEYDEF *keyinfo,my_off_t page,
- uchar *buff);
-extern int _nisam_dispose(N_INFO *info,N_KEYDEF *keyinfo,my_off_t pos);
-extern ulong _nisam_new(N_INFO *info,N_KEYDEF *keyinfo);
-extern uint _nisam_make_key(N_INFO *info,uint keynr,uchar *key,
- const char *record,ulong filepos);
-extern uint _nisam_pack_key(N_INFO *info,uint keynr,uchar *key,uchar *old,uint key_length);
-extern int _nisam_read_key_record(N_INFO *info,ulong filepos,byte *buf);
-extern int _nisam_read_cache(IO_CACHE *info,byte *buff,ulong pos,
- uint length,int re_read_if_possibly);
-extern byte *fix_rec_buff_for_blob(N_INFO *info,uint blob_length);
-extern uint _nisam_rec_unpack(N_INFO *info,byte *to,byte *from,
- uint reclength);
-my_bool _nisam_rec_check(N_INFO *info,const char *from);
-extern int _nisam_write_part_record(N_INFO *info,ulong filepos,uint length,
- ulong next_filepos,byte **record,
- uint *reclength,int *flag);
-extern void _nisam_print_key(FILE *stream,N_KEYSEG *keyseg,const uchar *key);
-extern my_bool _nisam_read_pack_info(N_INFO *info,pbool fix_keys);
-extern int _nisam_read_pack_record(N_INFO *info,ulong filepos,byte *buf);
-extern int _nisam_read_rnd_pack_record(N_INFO*, byte *,ulong, int);
-extern int _nisam_pack_rec_unpack(N_INFO *info,byte *to,byte *from,
- uint reclength);
-extern ulong _nisam_checksum(const byte *mem, uint count);
-
-typedef struct st_sortinfo {
- uint key_length;
- ulong max_records;
- int (*key_cmp)(const void *, const void *, const void *);
- int (*key_read)(void *buff);
- int (*key_write)(const void *buff);
- void (*lock_in_memory)(void);
-} SORT_PARAM;
-
-int _create_index_by_sort(SORT_PARAM *info,pbool no_messages,
- uint sortbuff_size);
-
-#define BLOCK_INFO_HEADER_LENGTH 11
-
-typedef struct st_block_info { /* Parameter to _nisam_get_block_info */
- uchar header[BLOCK_INFO_HEADER_LENGTH];
- uint rec_len;
- uint data_len;
- uint block_len;
- ulong filepos; /* Must be ulong on Alpha! */
- ulong next_filepos;
- uint second_read;
-} BLOCK_INFO;
-
- /* bits in return from _nisam_get_block_info */
-
-#define BLOCK_FIRST 1
-#define BLOCK_LAST 2
-#define BLOCK_DELETED 4
-#define BLOCK_ERROR 8 /* Wrong data */
-#define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */
-#define BLOCK_FATAL_ERROR 32 /* hardware-error */
-
-enum nisam_log_commands {
- LOG_OPEN,LOG_WRITE,LOG_UPDATE,LOG_DELETE,LOG_CLOSE,LOG_EXTRA,LOG_LOCK
-};
-
-#define nisam_log_simple(a,b,c,d) if (nisam_log_file >= 0) _nisam_log(a,b,c,d)
-#define nisam_log_command(a,b,c,d,e) if (nisam_log_file >= 0) _nisam_log_command(a,b,c,d,e)
-#define nisam_log_record(a,b,c,d,e) if (nisam_log_file >= 0) _nisam_log_record(a,b,c,d,e)
-
-extern uint _nisam_get_block_info(BLOCK_INFO *,File, ulong);
-extern uint _nisam_rec_pack(N_INFO *info,byte *to,const byte *from);
-extern uint _nisam_pack_get_block_info(BLOCK_INFO *, uint, File, ulong);
-extern uint _calc_total_blob_length(N_INFO *info,const byte *record);
-extern void _nisam_log(enum nisam_log_commands command,N_INFO *info,
- const byte *buffert,uint length);
-extern void _nisam_log_command(enum nisam_log_commands command,
- N_INFO *info, const byte *buffert,
- uint length, int result);
-extern void _nisam_log_record(enum nisam_log_commands command,N_INFO *info,
- const byte *record,ulong filepos,
- int result);
-extern my_bool _nisam_memmap_file(N_INFO *info);
-extern void _nisam_unmap_file(N_INFO *info);
diff --git a/isam/isamlog.c b/isam/isamlog.c
deleted file mode 100644
index 5cc204b26aa..00000000000
--- a/isam/isamlog.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* write whats in isam.log */
-
-#ifndef USE_MY_FUNC
-#define USE_MY_FUNC
-#endif
-
-#include "isamdef.h"
-#include <my_tree.h>
-#include <stdarg.h>
-#ifdef HAVE_GETRUSAGE
-#include <sys/resource.h>
-#endif
-
-#define FILENAME(A) (A ? A->show_name : "Unknown")
-
-struct isamlog_file_info {
- long process;
- int filenr,id;
- my_string name,show_name,record;
- N_INFO *isam;
- bool closed,used;
- ulong accessed;
-};
-
-struct test_if_open_param {
- my_string name;
- int max_id;
-};
-
-struct st_access_param
-{
- ulong min_accessed;
- struct isamlog_file_info *found;
-};
-
-#define NO_FILEPOS (ulong) ~0L
-
-extern int main(int argc,char * *argv);
-static void get_options(int *argc,char ***argv);
-static int examine_log(my_string file_name,char **table_names);
-static int read_string(IO_CACHE *file,gptr *to,uint length);
-static int file_info_compare(void *a,void *b);
-static int test_if_open(struct isamlog_file_info *key,element_count count,
- struct test_if_open_param *param);
-static void fix_blob_pointers(N_INFO *isam,byte *record);
-static uint set_maximum_open_files(uint);
-static int test_when_accessed(struct isamlog_file_info *key,element_count count,
- struct st_access_param *access_param);
-static void file_info_free(struct isamlog_file_info *info);
-static int close_some_file(TREE *tree);
-static int reopen_closed_file(TREE *tree,struct isamlog_file_info *file_info);
-static int find_record_with_key(struct isamlog_file_info *file_info,
- byte *record);
-static void printf_log(const char *str,...);
-static bool cmp_filename(struct isamlog_file_info *file_info,my_string name);
-
-static uint verbose=0,update=0,test_info=0,max_files=0,re_open_count=0,
- recover=0,prefix_remove=0,opt_processes=0;
-static my_string log_filename=0,filepath=0,write_filename=0,record_pos_file=0;
-static ulong com_count[10][3],number_of_commands=(ulong) ~0L,start_offset=0,
- record_pos= NO_FILEPOS,isamlog_filepos,isamlog_process;
-static const char *command_name[]=
-{"open","write","update","delete","close","extra","lock","re-open",NullS};
-
-
-int main(int argc, char **argv)
-{
- int error,i,first;
- ulong total_count,total_error,total_recover;
- MY_INIT(argv[0]);
-
- log_filename=nisam_log_filename;
- get_options(&argc,&argv);
- /* Nr of isam-files */
- max_files=(set_maximum_open_files(min(max_files,8))-6)/2;
-
- if (update)
- printf("Trying to %s ISAM files according to log '%s'\n",
- (recover ? "recover" : "update"),log_filename);
- error= examine_log(log_filename,argv);
- if (update && ! error)
- puts("Tables updated successfully");
- total_count=total_error=total_recover=0;
- for (i=first=0 ; command_name[i] ; i++)
- {
- if (com_count[i][0])
- {
- if (!first++)
- {
- if (verbose || update)
- puts("");
- puts("Commands Used count Errors Recover errors");
- }
- printf("%-12s%9ld%10ld%17ld\n",command_name[i],com_count[i][0],
- com_count[i][1],com_count[i][2]);
- total_count+=com_count[i][0];
- total_error+=com_count[i][1];
- total_recover+=com_count[i][2];
- }
- }
- if (total_count)
- printf("%-12s%9ld%10ld%17ld\n","Total",total_count,total_error,
- total_recover);
- if (re_open_count)
- printf("Had to do %d re-open because of too few possibly open files\n",
- re_open_count);
- VOID(nisam_panic(HA_PANIC_CLOSE));
- my_end(test_info ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
- exit(error);
- return 0; /* No compiler warning */
-} /* main */
-
-
-static void get_options(register int *argc, register char ***argv)
-{
- int help,version;
- const char *pos,*usage;
- char option;
-
- help=0;
- usage="Usage: %s [-?iruvIPV] [-c #] [-f #] [-F filepath/] [-o #] [-R file recordpos] [-w write_file] [log-filename [table ...]] \n";
- pos= "";
-
- while (--*argc > 0 && *(pos = *(++*argv)) == '-' ) {
- while (*++pos)
- {
- version=0;
- switch((option=*pos)) {
- case '#':
- DBUG_PUSH (++pos);
- pos=" "; /* Skip rest of arg */
- break;
- case 'c':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- number_of_commands=(ulong) atol(pos);
- pos=" ";
- break;
- case 'u':
- update=1;
- break;
- case 'f':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- max_files=(uint) atoi(pos);
- pos=" ";
- break;
- case 'i':
- test_info=1;
- break;
- case 'o':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- start_offset=(ulong) atol(pos);
- pos=" ";
- break;
- case 'p':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- prefix_remove=atoi(pos);
- break;
- case 'r':
- update=1;
- recover++;
- break;
- case 'P':
- opt_processes=1;
- break;
- case 'R':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- record_pos_file=(char*) pos;
- if (!--*argc)
- goto err;
- record_pos=(ulong) atol(*(++*argv));
- pos= " ";
- break;
- case 'v':
- verbose++;
- break;
- case 'w':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- write_filename=(char*) pos;
- pos=" ";
- break;
- case 'F':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- filepath= (char*) pos;
- pos=" ";
- break;
- case 'V':
- version=1;
- /* Fall through */
- case 'I':
- case '?':
- printf("%s Ver 3.3 for %s at %s\n",my_progname,SYSTEM_TYPE,
- MACHINE_TYPE);
- puts("By Monty, for your professional use\n");
- if (version)
- break;
- puts("Write info about whats in a ISAM log file.");
- printf("If no file name is given %s is used\n",log_filename);
- puts("");
- printf(usage,my_progname);
- puts("");
- puts("Options: -? or -I \"Info\" -V \"version\" -c \"do only # commands\"");
- puts(" -f \"max open files\" -F \"filepath\" -i \"extra info\"");
- puts(" -o \"offset\" -p # \"remove # components from path\"");
- puts(" -r \"recover\" -R \"file recordposition\"");
- puts(" -u \"update\" -v \"verbose\" -w \"write file\"");
- puts(" -P \"processes\"");
- puts("\nOne can give a second and a third '-v' for more verbose.");
- puts("Normaly one does a update (-u).");
- puts("If a recover is done all writes and all possibly updates and deletes is done\nand errors are only counted.");
- puts("If one gives table names as arguments only these tables will be updated\n");
- help=1;
- break;
- default:
- printf("illegal option: \"-%c\"\n",*pos);
- break;
- }
- }
- }
- if (! *argc)
- {
- if (help)
- exit(0);
- (*argv)++;
- }
- if (*argc >= 1)
- {
- log_filename=(char*) pos;
- (*argc)--;
- (*argv)++;
- }
- return;
- err:
- VOID(fprintf(stderr,"option \"%c\" used without or with wrong argument\n",
- option));
- exit(1);
-}
-
-
-static int examine_log(my_string file_name, char **table_names)
-{
- uint command,result,files_open;
- ulong access_time,length;
- uint32 filepos;
- int lock_command,ni_result;
- char isam_file_name[FN_REFLEN];
- uchar head[20];
- gptr buff;
- struct test_if_open_param open_param;
- IO_CACHE cache;
- File file;
- FILE *write_file;
- enum ha_extra_function extra_command;
- TREE tree;
- struct isamlog_file_info file_info,*curr_file_info;
- char llbuff[22],llbuff2[22];
- DBUG_ENTER("examine_log");
-
- if ((file=my_open(file_name,O_RDONLY,MYF(MY_WME))) < 0)
- DBUG_RETURN(1);
- write_file=0;
- if (write_filename)
- {
- if (!(write_file=my_fopen(write_filename,O_WRONLY,MYF(MY_WME))))
- {
- my_close(file,MYF(0));
- DBUG_RETURN(1);
- }
- }
-
- init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
- bzero((gptr) com_count,sizeof(com_count));
- init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
- (tree_element_free) file_info_free, NULL);
- VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
- 0,0));
- files_open=0; access_time=0;
- while (access_time++ != number_of_commands &&
- !my_b_read(&cache,(byte*) head,9))
- {
- isamlog_filepos=my_b_tell(&cache)-9L;
- file_info.filenr=uint2korr(head+1);
- isamlog_process=file_info.process=(long) uint4korr(head+3);
- if (!opt_processes)
- file_info.process=0;
- result=uint2korr(head+7);
- if ((curr_file_info=(struct isamlog_file_info*)
- tree_search(&tree, &file_info, tree.custom_arg)))
- {
- curr_file_info->accessed=access_time;
- if (update && curr_file_info->used && curr_file_info->closed)
- {
- if (reopen_closed_file(&tree,curr_file_info))
- {
- command=sizeof(com_count)/sizeof(com_count[0][0])/3;
- result=0;
- goto com_err;
- }
- }
- }
- command=(uint) head[0];
- if (command < sizeof(com_count)/sizeof(com_count[0][0])/3 &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- {
- com_count[command][0]++;
- if (result)
- com_count[command][1]++;
- }
- switch ((enum nisam_log_commands) command) {
- case LOG_OPEN:
- if (!table_names[0])
- {
- com_count[command][0]--; /* Must be counted explicite */
- if (result)
- com_count[command][1]--;
- }
-
- if (curr_file_info)
- printf("\nWarning: %s is opened with same process and filenumber\nMaybe you should use the -P option ?\n",
- curr_file_info->show_name);
- if (my_b_read(&cache,(byte*) head,2))
- goto err;
- file_info.name=0;
- file_info.show_name=0;
- file_info.record=0;
- if (read_string(&cache,(gptr*) &file_info.name,(uint) uint2korr(head)))
- goto err;
- {
- uint i;
- char *pos,*to;
-
- /* Fix if old DOS files to new format */
- for (pos=file_info.name; (pos=strchr(pos,'\\')) ; pos++)
- *pos= '/';
-
- pos=file_info.name;
- for (i=0 ; i < prefix_remove ; i++)
- {
- char *next;
- if (!(next=strchr(pos,'/')))
- break;
- pos=next+1;
- }
- to=isam_file_name;
- if (filepath)
- to=convert_dirname(isam_file_name, filepath, NullS);
- strmov(to,pos);
- fn_ext(isam_file_name)[0]=0; /* Remove extension */
- }
- open_param.name=file_info.name;
- open_param.max_id=0;
- VOID(tree_walk(&tree,(tree_walk_action) test_if_open,(void*) &open_param,
- left_root_right));
- file_info.id=open_param.max_id+1;
- file_info.show_name=my_memdup(isam_file_name,
- (uint) strlen(isam_file_name)+6,
- MYF(MY_WME));
- if (file_info.id > 1)
- sprintf(strend(file_info.show_name),"<%d>",file_info.id);
- file_info.closed=1;
- file_info.accessed=access_time;
- file_info.used=1;
- if (table_names[0])
- {
- char **name;
- file_info.used=0;
- for (name=table_names ; *name ; name++)
- {
- if (!strcmp(*name,isam_file_name))
- file_info.used=1; /* Update/log only this */
- }
- }
- if (update && file_info.used)
- {
- if (files_open >= max_files)
- {
- if (close_some_file(&tree))
- goto com_err;
- files_open--;
- }
- if (!(file_info.isam= nisam_open(isam_file_name,O_RDWR,
- HA_OPEN_WAIT_IF_LOCKED)))
- goto com_err;
- if (!(file_info.record=my_malloc(file_info.isam->s->base.reclength,
- MYF(MY_WME))))
- goto end;
- files_open++;
- file_info.closed=0;
- }
- VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
- if (file_info.used)
- {
- if (verbose && !record_pos_file)
- printf_log("%s: open -> %d",file_info.show_name, file_info.filenr);
- com_count[command][0]++;
- if (result)
- com_count[command][1]++;
- }
- break;
- case LOG_CLOSE:
- if (verbose && !record_pos_file &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- printf_log("%s: %s -> %d",FILENAME(curr_file_info),
- command_name[command],result);
- if (curr_file_info)
- {
- if (!curr_file_info->closed)
- files_open--;
- VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
- }
- break;
- case LOG_EXTRA:
- if (my_b_read(&cache,(byte*) head,sizeof(extra_command)))
- goto err;
- memcpy_fixed(&extra_command,head,sizeof(extra_command));
- if (verbose && !record_pos_file &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- printf_log("%s: %s(%d) -> %d",FILENAME(curr_file_info),
- command_name[command], (int) extra_command,result);
- if (update && curr_file_info && !curr_file_info->closed)
- {
- if (nisam_extra(curr_file_info->isam,extra_command) != (int) result)
- {
- fflush(stdout);
- VOID(fprintf(stderr,
- "Warning: error %d, expected %d on command %s at %s\n",
- my_errno,result,command_name[command],
- llstr(isamlog_filepos,llbuff)));
- fflush(stderr);
- }
- }
- break;
- case LOG_DELETE:
- if (my_b_read(&cache,(byte*) head,sizeof(filepos)))
- goto err;
- memcpy_fixed(&filepos,head,sizeof(filepos));
- if (verbose && (!record_pos_file ||
- ((record_pos == filepos || record_pos == NO_FILEPOS) &&
- !cmp_filename(curr_file_info,record_pos_file))) &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- printf_log("%s: %s at %ld -> %d",FILENAME(curr_file_info),
- command_name[command],(long) filepos,result);
- if (update && curr_file_info && !curr_file_info->closed)
- {
- if (nisam_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
- {
- if (!recover)
- goto com_err;
- com_count[command][2]++; /* Mark error */
- }
- ni_result=nisam_delete(curr_file_info->isam,curr_file_info->record);
- if ((ni_result == 0 && result) ||
- (ni_result && (uint) my_errno != result))
- {
- if (!recover)
- goto com_err;
- if (ni_result)
- com_count[command][2]++; /* Mark error */
- if (verbose)
- printf_log("error: Got result %d from mi_delete instead of %d",
- ni_result, result);
- }
- }
- break;
- case LOG_WRITE:
- case LOG_UPDATE:
- if (my_b_read(&cache,(byte*) head,8))
- goto err;
- filepos=uint4korr(head);
- length=uint4korr(head+4);
- buff=0;
- if (read_string(&cache,&buff,(uint) length))
- goto err;
- if ((!record_pos_file ||
- ((record_pos == filepos || record_pos == NO_FILEPOS) &&
- !cmp_filename(curr_file_info,record_pos_file))) &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- {
- if (write_file &&
- (my_fwrite(write_file,buff,length,MYF(MY_WAIT_IF_FULL | MY_NABP))))
- goto end;
- if (verbose)
- printf_log("%s: %s at %ld, length=%ld -> %d",
- FILENAME(curr_file_info),
- command_name[command], filepos,length,result);
- }
- if (update && curr_file_info && !curr_file_info->closed)
- {
- if (curr_file_info->isam->s->base.blobs)
- fix_blob_pointers(curr_file_info->isam,buff);
- if ((enum nisam_log_commands) command == LOG_UPDATE)
- {
- if (nisam_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
- {
- if (!recover)
- {
- result=0;
- goto com_err;
- }
- if (verbose)
- printf_log("error: Didn't find row to update with mi_rrnd");
- if (recover == 1 || result ||
- find_record_with_key(curr_file_info,buff))
- {
- com_count[command][2]++; /* Mark error */
- break;
- }
- }
- ni_result=nisam_update(curr_file_info->isam,curr_file_info->record,
- buff);
- if ((ni_result == 0 && result) ||
- (ni_result && (uint) my_errno != result))
- {
- if (!recover)
- goto com_err;
- if (verbose)
- printf_log("error: Got result %d from mi_update instead of %d",
- ni_result, result);
- if (ni_result)
- com_count[command][2]++; /* Mark error */
- }
- }
- else
- {
- ni_result=nisam_write(curr_file_info->isam,buff);
- if ((ni_result == 0 && result) ||
- (ni_result && (uint) my_errno != result))
- {
- if (!recover)
- goto com_err;
- if (ni_result)
- com_count[command][2]++; /* Mark error */
- }
- if (! recover && filepos != curr_file_info->isam->lastpos)
- {
- printf("error: Wrote at position: %s, should have been %s",
- llstr(curr_file_info->isam->lastpos,llbuff),
- llstr(filepos,llbuff2));
- goto end;
- }
- }
- }
- my_free(buff,MYF(0));
- break;
- case LOG_LOCK:
- if (my_b_read(&cache,(byte*) head,sizeof(lock_command)))
- goto err;
- memcpy_fixed(&lock_command,head,sizeof(lock_command));
- if (verbose && !record_pos_file &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- printf_log("%s: %s(%d) -> %d\n",FILENAME(curr_file_info),
- command_name[command],lock_command,result);
- if (update && curr_file_info && !curr_file_info->closed)
- {
- if (nisam_lock_database(curr_file_info->isam,lock_command) !=
- (int) result)
- goto com_err;
- }
- break;
- default:
- VOID(fprintf(stderr,
- "Error: found unknown command %d in logfile, aborted\n",
- command));
- fflush(stderr);
- goto end;
- }
- }
- end_key_cache(dflt_key_cache,1);
- delete_tree(&tree);
- VOID(end_io_cache(&cache));
- VOID(my_close(file,MYF(0)));
- if (write_file && my_fclose(write_file,MYF(MY_WME)))
- DBUG_RETURN(1);
- DBUG_RETURN(0);
-
- err:
- fflush(stdout);
- VOID(fprintf(stderr,"Got error %d when reading from logfile\n",my_errno));
- fflush(stderr);
- goto end;
- com_err:
- fflush(stdout);
- VOID(fprintf(stderr,"Got error %d, expected %d on command %s at %s\n",
- my_errno,result,command_name[command],
- llstr(isamlog_filepos,llbuff)));
- fflush(stderr);
- end:
- end_key_cache(dflt_key_cache,1);
- delete_tree(&tree);
- VOID(end_io_cache(&cache));
- VOID(my_close(file,MYF(0)));
- if (write_file)
- VOID(my_fclose(write_file,MYF(MY_WME)));
- DBUG_RETURN(1);
-}
-
-
-static int read_string(IO_CACHE *file, reg1 gptr *to, reg2 uint length)
-{
- DBUG_ENTER("read_string");
-
- if (*to)
- my_free((gptr) *to,MYF(0));
- if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) ||
- my_b_read(file,(byte*) *to,length))
- {
- if (*to)
- my_free(*to,MYF(0));
- *to= 0;
- DBUG_RETURN(1);
- }
- *((char*) *to+length)= '\0';
- DBUG_RETURN (0);
-} /* read_string */
-
-
-static int file_info_compare(void *a, void *b)
-{
- long lint;
-
- if ((lint=((struct isamlog_file_info*) a)->process -
- ((struct isamlog_file_info*) b)->process))
- return lint < 0L ? -1 : 1;
- return (((struct isamlog_file_info*) a)->filenr -
- ((struct isamlog_file_info*) b)->filenr);
-}
-
- /* ARGSUSED */
-
-static int test_if_open (struct isamlog_file_info *key,
- element_count count __attribute__((unused)),
- struct test_if_open_param *param)
-{
- if (!strcmp(key->name,param->name) && key->id > param->max_id)
- param->max_id=key->id;
- return 0;
-}
-
-
-static void fix_blob_pointers( N_INFO *info, byte *record)
-{
- byte *pos;
- N_BLOB *blob,*end;
-
- pos=record+info->s->base.reclength;
- for (end=info->blobs+info->s->base.blobs, blob= info->blobs;
- blob != end ;
- blob++)
- {
- bmove(record+blob->offset+blob->pack_length,&pos,sizeof(char*));
- pos+=_calc_blob_length(blob->pack_length,record+blob->offset);
- }
-}
-
-static uint set_maximum_open_files(uint maximum_files)
-{
-#if defined(HAVE_GETRUSAGE) && defined(RLIMIT_NOFILE)
- struct rlimit rlimit;
- int old_max;
-
- if (maximum_files > MY_NFILE)
- maximum_files=MY_NFILE; /* Don't crash my_open */
-
- if (!getrlimit(RLIMIT_NOFILE,&rlimit))
- {
- old_max=rlimit.rlim_max;
- if (maximum_files && (int) maximum_files > old_max)
- rlimit.rlim_max=maximum_files;
- rlimit.rlim_cur=rlimit.rlim_max;
- if (setrlimit(RLIMIT_NOFILE,&rlimit))
- {
- if (old_max != (int) maximum_files)
- { /* Set as much as we can */
- rlimit.rlim_max=rlimit.rlim_cur=old_max;
- setrlimit(RLIMIT_NOFILE,&rlimit);
- }
- }
- getrlimit(RLIMIT_NOFILE,&rlimit); /* Read if broken setrlimit */
- if (maximum_files && maximum_files < rlimit.rlim_cur)
- VOID(fprintf(stderr,"Warning: Error from setrlimit: Max open files is %d\n",old_max));
- return rlimit.rlim_cur;
- }
-#endif
- return min(maximum_files,MY_NFILE);
-}
-
- /* close the file with hasn't been accessed for the longest time */
- /* ARGSUSED */
-
-static int test_when_accessed (struct isamlog_file_info *key,
- element_count count __attribute__((unused)),
- struct st_access_param *access_param)
-{
- if (key->accessed < access_param->min_accessed && ! key->closed)
- {
- access_param->min_accessed=key->accessed;
- access_param->found=key;
- }
- return 0;
-}
-
-
-static void file_info_free(struct isamlog_file_info *fileinfo)
-{
- DBUG_ENTER("file_info_free");
- if (update)
- {
- if (!fileinfo->closed)
- VOID(nisam_close(fileinfo->isam));
- if (fileinfo->record)
- my_free(fileinfo->record,MYF(0));
- }
- my_free(fileinfo->name,MYF(0));
- my_free(fileinfo->show_name,MYF(0));
- DBUG_VOID_RETURN;
-}
-
-
-
-static int close_some_file(TREE *tree)
-{
- struct st_access_param access_param;
-
- access_param.min_accessed=LONG_MAX;
- access_param.found=0;
-
- VOID(tree_walk(tree,(tree_walk_action) test_when_accessed,
- (void*) &access_param,left_root_right));
- if (!access_param.found)
- return 1; /* No open file that is possibly to close */
- if (nisam_close(access_param.found->isam))
- return 1;
- access_param.found->closed=1;
- return 0;
-}
-
-
-static int reopen_closed_file(TREE *tree, struct isamlog_file_info *fileinfo)
-{
- char name[FN_REFLEN];
- if (close_some_file(tree))
- return 1; /* No file to close */
- strmov(name,fileinfo->show_name);
- if (fileinfo->id > 1)
- *strrchr(name,'<')='\0'; /* Remove "<id>" */
-
- if (!(fileinfo->isam= nisam_open(name,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)))
- return 1;
- fileinfo->closed=0;
- re_open_count++;
- return 0;
-}
-
- /* Try to find record with uniq key */
-
-static int find_record_with_key(struct isamlog_file_info *file_info,
- byte *record)
-{
- uint key;
- N_INFO *info=file_info->isam;
- uchar tmp_key[N_MAX_KEY_BUFF];
-
- for (key=0 ; key < info->s->state.keys ; key++)
- {
- if (info->s->keyinfo[key].base.flag & HA_NOSAME)
- {
- VOID(_nisam_make_key(info,key,tmp_key,record,0L));
- return nisam_rkey(info,file_info->record,(int) key,(char*) tmp_key,0,
- HA_READ_KEY_EXACT);
- }
- }
- return 1;
-}
-
-
-static void printf_log(const char *format,...)
-{
- char llbuff[21];
- va_list args;
- va_start(args,format);
- if (verbose > 2)
- printf("%9s:",llstr(isamlog_filepos,llbuff));
- if (verbose > 1)
- printf("%5ld ",isamlog_process); /* Write process number */
- (void) vprintf((char*) format,args);
- putchar('\n');
- va_end(args);
-}
-
-
-static bool cmp_filename(struct isamlog_file_info *file_info,my_string name)
-{
- if (!file_info)
- return 1;
- return strcmp(file_info->name,name) ? 1 : 0;
-}
diff --git a/isam/log.c b/isam/log.c
deleted file mode 100644
index 78b56690401..00000000000
--- a/isam/log.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Logging of isamcommands and records on logfile */
-
-#include "isamdef.h"
-#if defined(MSDOS) || defined(__WIN__)
-#include <errno.h>
-#include <fcntl.h>
-#ifndef __WIN__
-#include <process.h>
-#endif
-#endif
-#ifdef VMS
-#include <processes.h>
-#endif
-
-#ifdef THREAD
-#undef GETPID
-#define GETPID() (log_type == 1 ? getpid() : (long) my_thread_id());
-#else
-#define GETPID() getpid()
-#endif
-
- /* Activate logging if flag is 1 and reset logging if flag is 0 */
-
-static int log_type=0;
-
-int nisam_log(int activate_log)
-{
- int error=0;
- char buff[FN_REFLEN];
- DBUG_ENTER("nisam_log");
-
- log_type=activate_log;
- if (activate_log)
- {
- if (nisam_log_file < 0)
- {
- if ((nisam_log_file = my_create(fn_format(buff,nisam_log_filename,
- "",".log",4),
- 0,(O_RDWR | O_BINARY | O_APPEND),MYF(0)))
- < 0)
- DBUG_RETURN(1);
- }
- }
- else if (nisam_log_file >= 0)
- {
- error=my_close(nisam_log_file,MYF(0));
- nisam_log_file= -1;
- }
- DBUG_RETURN(error);
-}
-
-
- /* Logging of records and commands on logfile */
- /* All logs starts with command(1) dfile(2) process(4) result(2) */
-
-void _nisam_log(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length)
-{
- char buff[11];
- int error,old_errno;
- ulong pid=(ulong) GETPID();
- old_errno=my_errno;
- bzero(buff,sizeof(buff));
- buff[0]=(char) command;
- int2store(buff+1,info->dfile);
- int4store(buff+3,pid);
- int2store(buff+9,length);
-
- pthread_mutex_lock(&THR_LOCK_isam);
- error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
- VOID(my_write(nisam_log_file,buffert,length,MYF(0)));
- if (!error)
- error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- pthread_mutex_unlock(&THR_LOCK_isam);
- my_errno=old_errno;
-}
-
-
-void _nisam_log_command(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length, int result)
-{
- char buff[9];
- int error,old_errno;
- ulong pid=(ulong) GETPID();
-
- old_errno=my_errno;
- buff[0]=(char) command;
- int2store(buff+1,info->dfile);
- int4store(buff+3,pid);
- int2store(buff+7,result);
- pthread_mutex_lock(&THR_LOCK_isam);
- error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
- if (buffert)
- VOID(my_write(nisam_log_file,buffert,length,MYF(0)));
- if (!error)
- error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- pthread_mutex_unlock(&THR_LOCK_isam);
- my_errno=old_errno;
-}
-
-
-void _nisam_log_record(enum nisam_log_commands command, N_INFO *info, const byte *record, ulong filepos, int result)
-{
- char buff[17],*pos;
- int error,old_errno;
- uint length;
- ulong pid=(ulong) GETPID();
-
- old_errno=my_errno;
- if (!info->s->base.blobs)
- length=info->s->base.reclength;
- else
- length=info->s->base.reclength+ _calc_total_blob_length(info,record);
- buff[0]=(char) command;
- int2store(buff+1,info->dfile);
- int4store(buff+3,pid);
- int2store(buff+7,result);
- int4store(buff+9,filepos);
- int4store(buff+13,length);
- pthread_mutex_lock(&THR_LOCK_isam);
- error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
- VOID(my_write(nisam_log_file,(byte*) record,info->s->base.reclength,MYF(0)));
- if (info->s->base.blobs)
- {
- N_BLOB *blob,*end;
-
- for (end=info->blobs+info->s->base.blobs, blob= info->blobs;
- blob != end ;
- blob++)
- {
- bmove(&pos,record+blob->offset+blob->pack_length,sizeof(char*));
- VOID(my_write(nisam_log_file,pos,blob->length,MYF(0)));
- }
- }
- if (!error)
- error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- pthread_mutex_unlock(&THR_LOCK_isam);
- my_errno=old_errno;
-}
diff --git a/isam/make-ccc b/isam/make-ccc
deleted file mode 100755
index d9a95dbc14b..00000000000
--- a/isam/make-ccc
+++ /dev/null
@@ -1,3 +0,0 @@
-ccc -DHAVE_CONFIG_H -I. -I. -I.. -I./../include -I../include -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c _cache.c _dbug.c _dynrec.c _key.c _locking.c _packrec.c _page.c _search.c _statrec.c changed.c close.c create.c delete.c extra.c info.c log.c open.c panic.c range.c rfirst.c rkey.c rlast.c rnext.c rprev.c rrnd.c rsame.c rsamepos.c static.c update.c write.c
-rm libnisam.a
-ar -cr libnisam.a _cache.o
diff --git a/isam/open.c b/isam/open.c
deleted file mode 100644
index be62fd86192..00000000000
--- a/isam/open.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* open a isam-database */
-
-#include "isamdef.h"
-#if defined(MSDOS) || defined(__WIN__)
-#ifdef __WIN__
-#include <fcntl.h>
-#else
-#include <process.h> /* Prototype for getpid */
-#endif
-#endif
-#ifdef VMS
-#include "static.c"
-#endif
-
-static void setup_functions(ISAM_SHARE *info);
-static void setup_key_functions(N_KEYDEF *keyinfo);
-
-#define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \
- pos+=size;}
-
-/******************************************************************************
-** Return the shared struct if the table is already open.
-** In MySQL the server will handle version issues.
-******************************************************************************/
-
-static N_INFO *test_if_reopen(char *filename)
-{
- LIST *pos;
-
- for (pos=nisam_open_list ; pos ; pos=pos->next)
- {
- N_INFO *info=(N_INFO*) pos->data;
- ISAM_SHARE *share=info->s;
- if (!strcmp(share->filename,filename) && share->last_version)
- return info;
- }
- return 0;
-}
-
-
-/******************************************************************************
- open a isam database.
- By default exit with error if database is locked
- if handle_locking & HA_OPEN_WAIT_IF_LOCKED then wait if database is locked
- if handle_locking & HA_OPEN_IGNORE_IF_LOCKED then continue, but count-vars
- in st_i_info may be wrong. count-vars are automaticly fixed after next
- isam request.
-******************************************************************************/
-
-
-N_INFO *nisam_open(const char *name, int mode, uint handle_locking)
-{
- int lock_error,kfile,open_mode,save_errno;
- uint i,j,len,errpos,head_length,base_pos,offset,info_length,extra;
- char name_buff[FN_REFLEN],*disk_cache,*disk_pos;
- N_INFO info,*m_info,*old_info;
- ISAM_SHARE share_buff,*share;
- DBUG_ENTER("nisam_open");
-
- LINT_INIT(m_info);
- kfile= -1;
- lock_error=1;
- errpos=0;
- head_length=sizeof(share_buff.state.header);
- bzero((byte*) &info,sizeof(info));
-
- VOID(fn_format(name_buff,name,"",N_NAME_IEXT,4+16+32));
- pthread_mutex_lock(&THR_LOCK_isam);
- if (!(old_info=test_if_reopen(name_buff)))
- {
- share= &share_buff;
- bzero((gptr) &share_buff,sizeof(share_buff));
-
- if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
- {
- if ((errno != EROFS && errno != EACCES) ||
- mode != O_RDONLY ||
- (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
- goto err;
- }
- errpos=1;
- if (my_read(kfile,(char*) share->state.header.file_version,head_length,
- MYF(MY_NABP)))
- goto err;
-
- if (memcmp((byte*) share->state.header.file_version,
- (byte*) nisam_file_magic, 3) ||
- share->state.header.file_version[3] == 0 ||
- (uchar) share->state.header.file_version[3] > 3)
- {
- DBUG_PRINT("error",("Wrong header in %s",name_buff));
- DBUG_DUMP("error_dump",(char*) share->state.header.file_version,
- head_length);
- my_errno=HA_ERR_CRASHED;
- goto err;
- }
- if (uint2korr(share->state.header.options) &
- ~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
- HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
- HA_OPTION_TEMP_COMPRESS_RECORD))
- {
- DBUG_PRINT("error",("wrong options: 0x%lx",
- uint2korr(share->state.header.options)));
- my_errno=HA_ERR_OLD_FILE;
- goto err;
- }
- info_length=uint2korr(share->state.header.header_length);
- base_pos=uint2korr(share->state.header.base_pos);
- if (!(disk_cache=(char*) my_alloca(info_length)))
- {
- my_errno=ENOMEM;
- goto err;
- }
- errpos=2;
-
- VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
-#ifndef NO_LOCKING
- if (!(handle_locking & HA_OPEN_TMP_TABLE))
- {
- if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF,
- MYF(handle_locking & HA_OPEN_WAIT_IF_LOCKED ?
- 0 : MY_DONT_WAIT))) &&
- !(handle_locking & HA_OPEN_IGNORE_IF_LOCKED))
- goto err;
- }
-#endif
- errpos=3;
- if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
- goto err;
- len=uint2korr(share->state.header.state_info_length);
- if (len != sizeof(N_STATE_INFO))
- {
- DBUG_PRINT("warning",
- ("saved_state_info_length: %d base_info_length: %d",
- len,sizeof(N_STATE_INFO)));
- }
- if (len > sizeof(N_STATE_INFO))
- len=sizeof(N_STATE_INFO);
- share->state_length=len;
- memcpy(&share->state.header.file_version[0],disk_cache,(size_t) len);
- len=uint2korr(share->state.header.base_info_length);
- if (len != sizeof(N_BASE_INFO))
- {
- DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
- len,sizeof(N_BASE_INFO)));
- if (len <= offsetof(N_BASE_INFO,sortkey))
- share->base.sortkey=(ushort) ~0;
- }
- memcpy((char*) (byte*) &share->base,disk_cache+base_pos,
- (size_t) min(len,sizeof(N_BASE_INFO)));
- disk_pos=disk_cache+base_pos+len;
- share->base.options=uint2korr(share->state.header.options);
- if (share->base.max_key_length > N_MAX_KEY_BUFF)
- {
- my_errno=HA_ERR_UNSUPPORTED;
- goto err;
- }
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- share->base.max_key_length+=2; /* For safety */
-
- if (!my_multi_malloc(MY_WME,
- &share,sizeof(*share),
- &share->keyinfo,share->base.keys*sizeof(N_KEYDEF),
- &share->rec,(share->base.fields+1)*sizeof(N_RECINFO),
- &share->blobs,sizeof(N_BLOB)*share->base.blobs,
- &share->filename,strlen(name_buff)+1,
- NullS))
- goto err;
- errpos=4;
- *share=share_buff;
- strmov(share->filename,name_buff);
-
- /* Fix key in used if old nisam-database */
- if (share->state_length <= offsetof(N_STATE_INFO,keys))
- share->state.keys=share->base.keys;
-
- share->blocksize=min(IO_SIZE,nisam_block_size);
- for (i=0 ; i < share->base.keys ; i++)
- {
- get_next_element(&share->keyinfo[i].base,disk_pos,sizeof(N_SAVE_KEYDEF));
- setup_key_functions(share->keyinfo+i);
- set_if_smaller(share->blocksize,share->keyinfo[i].base.block_length);
- for (j=0 ; j <= share->keyinfo[i].base.keysegs ; j++)
- {
- get_next_element(&share->keyinfo[i].seg[j],disk_pos,
- sizeof(N_SAVE_KEYSEG));
- }
- }
- if (!share->blocksize)
- {
- my_errno=HA_ERR_CRASHED;
- goto err;
- }
-
- for (i=j=offset=0 ; i < share->base.fields ; i++)
- {
- get_next_element(&share->rec[i].base,disk_pos,sizeof(N_SAVE_RECINFO));
-#ifndef NOT_PACKED_DATABASES
- share->rec[i].pack_type=0;
- share->rec[i].huff_tree=0;
-#endif
- if (share->rec[i].base.type == (int) FIELD_BLOB)
- {
- share->blobs[j].pack_length=share->rec[i].base.length;
- share->blobs[j].offset=offset;
- j++;
- offset+=sizeof(char*);
- }
- offset+=share->rec[i].base.length;
- }
- share->rec[i].base.type=(int) FIELD_LAST;
-
-#ifndef NO_LOCKING
- if (! lock_error)
- {
- VOID(my_lock(kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
- lock_error=1; /* Database unlocked */
- }
-#endif
-
- if ((info.dfile=my_open(fn_format(name_buff,name,"",N_NAME_DEXT,2+4),
- mode | O_SHARE,
- MYF(MY_WME))) < 0)
- goto err;
- errpos=5;
-
- share->kfile=kfile;
- share->mode=open_mode;
- share->this_process=(ulong) getpid();
- share->rnd= (int) share->this_process; /* rnd-counter for splitts */
-#ifndef DBUG_OFF
- share->rnd=0; /* To make things repeatable */
-#endif
- share->last_process= share->state.process;
- if (!(share->last_version=share->state.version))
- share->last_version=1; /* Safety */
- share->rec_reflength=share->base.rec_reflength; /* May be changed */
-
- share->data_file_type=STATIC_RECORD;
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- share->data_file_type = COMPRESSED_RECORD;
- share->base.options|= HA_OPTION_READ_ONLY_DATA;
- info.s=share;
- if (_nisam_read_pack_info(&info,
- (pbool) test(!(share->base.options &
- (HA_OPTION_PACK_RECORD |
- HA_OPTION_TEMP_COMPRESS_RECORD)))))
- goto err;
- }
- else if (share->base.options & HA_OPTION_PACK_RECORD)
- share->data_file_type = DYNAMIC_RECORD;
- my_afree((gptr) disk_cache);
- setup_functions(share);
-#ifdef THREAD
- thr_lock_init(&share->lock);
- VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
-#endif
- }
- else
- {
- share= old_info->s;
- if (mode == O_RDWR && share->mode == O_RDONLY)
- {
- my_errno=EACCES; /* Can't open in write mode*/
- goto err;
- }
- if ((info.dfile=my_open(fn_format(name_buff,old_info->filename,"",
- N_NAME_DEXT,2+4),
- mode | O_SHARE,MYF(MY_WME))) < 0)
- {
- my_errno=errno;
- goto err;
- }
- errpos=5;
- }
-
- /* alloc and set up private structure parts */
- if (!my_multi_malloc(MY_WME,
- &m_info,sizeof(N_INFO),
- &info.blobs,sizeof(N_BLOB)*share->base.blobs,
- &info.buff,(share->base.max_block*2+
- share->base.max_key_length),
- &info.lastkey,share->base.max_key_length*3+1,
- &info.filename,strlen(name)+1,
- NullS))
- goto err;
- errpos=6;
- strmov(info.filename,name);
- memcpy(info.blobs,share->blobs,sizeof(N_BLOB)*share->base.blobs);
-
- info.s=share;
- info.lastpos= NI_POS_ERROR;
- info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
- info.opt_flag=READ_CHECK_USED;
- info.alloced_rec_buff_length=share->base.pack_reclength;
- info.this_uniq= (ulong) info.dfile; /* Uniq number in process */
- info.this_loop=0; /* Update counter */
- info.last_uniq= share->state.uniq;
- info.last_loop= share->state.loop;
- info.options=share->base.options |
- (mode == O_RDONLY ? HA_OPTION_READ_ONLY_DATA : 0);
- info.lock_type=F_UNLCK;
- info.errkey= -1;
- pthread_mutex_lock(&share->intern_lock);
- info.read_record=share->read_record;
- share->reopen++;
- if (share->base.options & HA_OPTION_READ_ONLY_DATA)
- {
- info.lock_type=F_RDLCK;
- share->r_locks++;
- info.this_uniq=share->state.uniq; /* Row checksum */
- }
-#ifndef NO_LOCKING
- if (handle_locking & HA_OPEN_TMP_TABLE)
-#endif
- {
- share->w_locks++; /* We don't have to update status */
- info.lock_type=F_WRLCK;
- }
- pthread_mutex_unlock(&share->intern_lock);
-
- /* Allocate buffer for one record */
-
- extra=0;
- if (share->base.options & HA_OPTION_PACK_RECORD)
- extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (!(info.rec_alloc=(byte*) my_malloc(share->base.pack_reclength+extra+
- 6,
- MYF(MY_WME | MY_ZEROFILL))))
- goto err;
- if (extra)
- info.rec_buff=info.rec_alloc+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER);
- else
- info.rec_buff=info.rec_alloc;
-
- *m_info=info;
-#ifdef THREAD
- thr_lock_data_init(&share->lock,&m_info->lock,NULL);
-#endif
-
- m_info->open_list.data=(void*) m_info;
- nisam_open_list=list_add(nisam_open_list,&m_info->open_list);
-
- pthread_mutex_unlock(&THR_LOCK_isam);
- nisam_log_simple(LOG_OPEN,m_info,share->filename,
- (uint) strlen(share->filename));
- DBUG_RETURN(m_info);
-
-err:
- save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
- switch (errpos) {
- case 6:
- my_free((gptr) m_info,MYF(0));
- /* fall through */
- case 5:
- VOID(my_close(info.dfile,MYF(0)));
- if (old_info)
- break; /* Don't remove open table */
- /* fall through */
- case 4:
- my_free((gptr) share,MYF(0));
- /* fall through */
- case 3:
-#ifndef NO_LOCKING
- if (! lock_error)
- VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE)));
-#endif
- /* fall through */
- case 2:
- my_afree((gptr) disk_cache);
- /* fall through */
- case 1:
- VOID(my_close(kfile,MYF(0)));
- /* fall through */
- case 0:
- default:
- break;
- }
- pthread_mutex_unlock(&THR_LOCK_isam);
- my_errno=save_errno;
- DBUG_RETURN (NULL);
-} /* nisam_open */
-
-
- /* Set up functions in structs */
-
-static void setup_functions(register ISAM_SHARE *share)
-{
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- share->read_record=_nisam_read_pack_record;
- share->read_rnd=_nisam_read_rnd_pack_record;
- }
- else if (share->base.options & HA_OPTION_PACK_RECORD)
- {
- share->read_record=_nisam_read_dynamic_record;
- share->read_rnd=_nisam_read_rnd_dynamic_record;
- share->delete_record=_nisam_delete_dynamic_record;
- share->compare_record=_nisam_cmp_dynamic_record;
-
- /* add bits used to pack data to pack_reclength for faster allocation */
- share->base.pack_reclength+= share->base.pack_bits;
- if (share->base.blobs)
- {
- share->update_record=_nisam_update_blob_record;
- share->write_record=_nisam_write_blob_record;
- }
- else
- {
- share->write_record=_nisam_write_dynamic_record;
- share->update_record=_nisam_update_dynamic_record;
- }
- }
- else
- {
- share->read_record=_nisam_read_static_record;
- share->read_rnd=_nisam_read_rnd_static_record;
- share->delete_record=_nisam_delete_static_record;
- share->compare_record=_nisam_cmp_static_record;
- share->update_record=_nisam_update_static_record;
- share->write_record=_nisam_write_static_record;
- }
- return;
-}
-
-
-static void setup_key_functions(register N_KEYDEF *keyinfo)
-{
- if (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED))
- {
- keyinfo->bin_search=_nisam_seq_search;
- keyinfo->get_key=_nisam_get_key;
- }
- else
- {
- keyinfo->bin_search=_nisam_bin_search;
- keyinfo->get_key=_nisam_get_static_key;
- }
- return;
-}
-
-/*
- Calculate a long checksum for a memoryblock. Used to verify pack_isam
-
- SYNOPSIS
- checksum()
- mem Pointer to memory block
- count Count of bytes
-*/
-
-ulong _nisam_checksum(const byte *mem, uint count)
-{
- ulong crc;
- for (crc= 0; count-- ; mem++)
- crc= ((crc << 1) + *((uchar*) mem)) +
- test(crc & ((ulong) 1L << (8*sizeof(ulong)-1)));
- return crc;
-}
-
diff --git a/isam/pack_isam.c b/isam/pack_isam.c
deleted file mode 100644
index 0134e0411b2..00000000000
--- a/isam/pack_isam.c
+++ /dev/null
@@ -1,2046 +0,0 @@
-/* Copyright (C) 1979-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 */
-
-/* Pack isam file */
-
-#ifndef USE_MY_FUNC
-#define USE_MY_FUNC /* We nead at least my_malloc */
-#endif
-
-#include "isamdef.h"
-#include <queues.h>
-#include <my_tree.h>
-#include "mysys_err.h"
-#ifdef MSDOS
-#include <io.h>
-#endif
-#ifndef __GNU_LIBRARY__
-#define __GNU_LIBRARY__ /* Skip warnings in getopt.h */
-#endif
-#include <my_getopt.h>
-
-#if INT_MAX > 32767
-#define BITS_SAVED 32
-#else
-#define BITS_SAVED 16
-#endif
-
-#define IS_OFFSET ((uint) 32768) /* Bit if offset or char in tree */
-#define HEAD_LENGTH 32
-#define ALLOWED_JOIN_DIFF 256 /* Diff allowed to join trees */
-
-#define DATA_TMP_EXT ".TMD"
-#define OLD_EXT ".OLD"
-#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE
-
-struct st_file_buffer {
- File file;
- char *buffer,*pos,*end;
- my_off_t pos_in_file;
- int bits;
- uint bytes;
-};
-
-struct st_huff_tree;
-struct st_huff_element;
-
-typedef struct st_huff_counts {
- uint field_length,max_zero_fill;
- uint pack_type;
- uint max_end_space,max_pre_space,length_bits,min_space;
- enum en_fieldtype field_type;
- struct st_huff_tree *tree; /* Tree for field */
- my_off_t counts[256];
- my_off_t end_space[8];
- my_off_t pre_space[8];
- my_off_t tot_end_space,tot_pre_space,zero_fields,empty_fields,bytes_packed;
- TREE int_tree;
- byte *tree_buff;
- byte *tree_pos;
-} HUFF_COUNTS;
-
-typedef struct st_huff_element HUFF_ELEMENT;
-
-struct st_huff_element {
- my_off_t count;
- union un_element {
- struct st_nod {
- HUFF_ELEMENT *left,*right;
- } nod;
- struct st_leaf {
- HUFF_ELEMENT *null;
- uint element_nr; /* Number of element */
- } leaf;
- } a;
-};
-
-
-typedef struct st_huff_tree {
- HUFF_ELEMENT *root,*element_buffer;
- HUFF_COUNTS *counts;
- uint tree_number;
- uint elements;
- my_off_t bytes_packed;
- uint tree_pack_length;
- uint min_chr,max_chr,char_bits,offset_bits,max_offset,height;
- ulong *code;
- uchar *code_len;
-} HUFF_TREE;
-
-
-typedef struct st_isam_mrg {
- N_INFO **file,**current,**end;
- uint count;
- uint min_pack_length; /* Theese is used by packed data */
- uint max_pack_length;
- uint ref_length;
- my_off_t records;
-} MRG_INFO;
-
-
-extern int main(int argc,char * *argv);
-static void get_options(int *argc,char ***argv);
-static N_INFO *open_isam_file(char *name,int mode);
-static bool open_isam_files(MRG_INFO *mrg,char **names,uint count);
-static int compress(MRG_INFO *file,char *join_name);
-static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records);
-static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees,
- uint trees,
- HUFF_COUNTS *huff_counts,
- uint fields);
-static int compare_tree(const uchar *s,const uchar *t);
-static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts);
-static void check_counts(HUFF_COUNTS *huff_counts,uint trees,
- my_off_t records);
-static int test_space_compress(HUFF_COUNTS *huff_counts,my_off_t records,
- uint max_space_length,my_off_t *space_counts,
- my_off_t tot_space_count,
- enum en_fieldtype field_type);
-static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts,uint trees);
-static int make_huff_tree(HUFF_TREE *tree,HUFF_COUNTS *huff_counts);
-static int compare_huff_elements(void *not_used, byte *a,byte *b);
-static int save_counts_in_queue(byte *key,element_count count,
- HUFF_TREE *tree);
-static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,uint flag);
-static uint join_same_trees(HUFF_COUNTS *huff_counts,uint trees);
-static int make_huff_decode_table(HUFF_TREE *huff_tree,uint trees);
-static void make_traverse_code_tree(HUFF_TREE *huff_tree,
- HUFF_ELEMENT *element,uint size,
- ulong code);
-static int write_header(MRG_INFO *isam_file, uint header_length,uint trees,
- my_off_t tot_elements,my_off_t filelength);
-static void write_field_info(HUFF_COUNTS *counts, uint fields,uint trees);
-static my_off_t write_huff_tree(HUFF_TREE *huff_tree,uint trees);
-static uint *make_offset_code_tree(HUFF_TREE *huff_tree,
- HUFF_ELEMENT *element,
- uint *offset);
-static uint max_bit(uint value);
-static int compress_isam_file(MRG_INFO *file,HUFF_COUNTS *huff_counts);
-static char *make_new_name(char *new_name,char *old_name);
-static char *make_old_name(char *new_name,char *old_name);
-static void init_file_buffer(File file,pbool read_buffer);
-static int flush_buffer(uint neaded_length);
-static void end_file_buffer(void);
-static void write_bits(ulong value,uint bits);
-static void flush_bits(void);
-static void save_integer(byte *pos,uint pack_length,my_off_t value);
-static void save_state(N_INFO *isam_file,MRG_INFO *mrg,my_off_t new_length,
- ulong crc);
-static int save_state_mrg(File file,MRG_INFO *isam_file,my_off_t new_length,
- ulong crc);
-static int mrg_close(MRG_INFO *mrg);
-static int mrg_rrnd(MRG_INFO *info,byte *buf);
-static void mrg_reset(MRG_INFO *mrg);
-
-
-static int error_on_write=0,test_only=0,verbose=0,silent=0,
- write_loop=0,force_pack=0,isamchk_neaded=0;
-static my_bool backup, opt_wait;
-static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
-static uint tree_buff_length=8196-MALLOC_OVERHEAD,force_pack_ref_length;
-static char tmp_dir[FN_REFLEN]={0},*join_table;
-static my_off_t intervall_length;
-static ulong crc;
-static struct st_file_buffer file_buffer;
-static QUEUE queue;
-static HUFF_COUNTS *global_count;
-static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-static const char *load_default_groups[]= { "pack_isam",0 };
-
- /* The main program */
-
-int main(int argc, char **argv)
-{
- int error,ok;
- MRG_INFO merge;
- MY_INIT(argv[0]);
-
- load_defaults("my",load_default_groups,&argc,&argv);
- get_options(&argc,&argv);
-
- error=ok=isamchk_neaded=0;
- if (join_table)
- { /* Join files into one */
- if (open_isam_files(&merge,argv,(uint) argc) ||
- compress(&merge,join_table))
- error=1;
- }
- else while (argc--)
- {
- N_INFO *isam_file;
- if (!(isam_file=open_isam_file(*argv++,O_RDWR)))
- error=1;
- else
- {
- merge.file= &isam_file;
- merge.current=0;
- merge.count=1;
- if (compress(&merge,0))
- error=1;
- else
- ok=1;
- }
- }
- if (ok && isamchk_neaded && !silent)
- puts("Remember to run isamchk -rq on compressed databases");
- VOID(fflush(stdout)); VOID(fflush(stderr));
- my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
- exit(error ? 2 : 0);
-#ifndef _lint
- return 0; /* No compiler warning */
-#endif
-}
-
-
-static struct my_option my_long_options[] =
-{
- {"backup", 'b', "Make a backup of the table as table_name.OLD",
- (gptr*) &backup, (gptr*) &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
- 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
- {"force", 'f',
- "Force packing of table even if it's gets bigger or tempfile exists.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"join", 'j',
- "Join all given tables into 'new_table_name'. All tables MUST have the identical layout.",
- (gptr*) &join_table, (gptr*) &join_table, 0, GET_STR, REQUIRED_ARG, 0, 0,
- 0, 0, 0, 0},
- {"help", '?', "Display this help and exit.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"packlength", 'p', "Force storage size of recordlength (1, 2 or 3)",
- (gptr*) &force_pack_ref_length, (gptr*) &force_pack_ref_length, 0,
- GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"silent", 's', "Be more silent.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0},
- {"tmpdir", 'T', "Use temporary directory to store temporary table",
- (gptr*) &tmp_dir, (gptr*) &tmp_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
- 0, 0},
- {"test", 't', "Don't pack table, only test packing it",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0},
- {"verbose", 'v', "Write info about progress and packing result",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0},
- {"version", 'V', "output version information and exit",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0},
- {"wait", 'w', "Wait and retry if table is in use", (gptr*) &opt_wait,
- (gptr*) &opt_wait, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
-};
-
-
-#include <help_start.h>
-
-static void print_version(void)
-{
- printf("%s Ver 5.10 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
-}
-
-static void usage(void)
-{
- print_version();
- puts("Copyright (C) 2002 MySQL AB");
- 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("Pack a ISAM-table to take much smaller space");
- puts("Keys are not updated, so you must run isamchk -rq on any table");
- puts("that has keys after you have compressed it");
- puts("You should give the .ISM file as the filename argument");
-
- printf("\nUsage: %s [OPTIONS] filename...\n", my_progname);
- my_print_help(my_long_options);
- print_defaults("my", load_default_groups);
- my_print_variables(my_long_options);
-}
-
-#include <help_end.h>
-
-
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- uint length;
-
- switch(optid) {
- case 'f':
- force_pack= 1;
- tmpfile_createflag= O_RDWR | O_TRUNC;
- break;
- case 'p':
- if (force_pack_ref_length > 3)
- force_pack_ref_length= 0;
- break;
- case 's':
- write_loop= verbose= 0;
- silent= 1;
- break;
- case 't':
- test_only= verbose= 1;
- break;
- case 'T':
- length=(uint) (strmov(tmp_dir, argument) - tmp_dir);
- if (length != dirname_length(tmp_dir))
- {
- tmp_dir[length]= FN_LIBCHAR;
- tmp_dir[length + 1]= 0;
- }
- break;
- case 'v':
- verbose= 1;
- silent= 0;
- break;
- case '#':
- DBUG_PUSH(argument ? argument : "d:t:o");
- break;
- case 'V': print_version(); exit(0);
- case 'I':
- case '?':
- usage();
- exit(0);
- }
- return 0;
-}
-
- /* reads options */
- /* Initiates DEBUG - but no debugging here ! */
-
-static void get_options(int *argc, char ***argv)
-{
- int ho_error;
-
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
- exit(ho_error);
-
- my_progname= argv[0][0];
- if (isatty(fileno(stdout)))
- write_loop=1;
-
- if (!*argc)
- {
- usage();
- exit(1);
- }
- if (join_table)
- {
- backup=0; /* Not needed */
- tmp_dir[0]=0;
- }
- return;
-}
-
-
-static N_INFO *open_isam_file(char *name,int mode)
-{
- N_INFO *isam_file;
- ISAM_SHARE *share;
- DBUG_ENTER("open_isam_file");
-
- if (!(isam_file=nisam_open(name,mode,(opt_wait ? HA_OPEN_WAIT_IF_LOCKED :
- HA_OPEN_ABORT_IF_LOCKED))))
- {
- VOID(fprintf(stderr,"%s gave error %d on open\n",name,my_errno));
- DBUG_RETURN(0);
- }
- share=isam_file->s;
- if (share->base.blobs)
- {
- VOID(fprintf(stderr,"%s has blobs, can't pack it\n",name));
- VOID(nisam_close(isam_file));
- DBUG_RETURN(0);
- }
- if (share->base.options & HA_OPTION_COMPRESS_RECORD && !join_table)
- {
- if (!force_pack)
- {
- VOID(fprintf(stderr,"%s is already compressed\n",name));
- VOID(nisam_close(isam_file));
- DBUG_RETURN(0);
- }
- if (verbose)
- puts("Recompressing already compressed table");
- share->base.options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */
- }
- if (! force_pack && share->state.records != 0 &&
- (share->state.records <= 1 ||
- share->state.data_file_length < 1024) && ! join_table)
- {
- VOID(fprintf(stderr,"%s is too small to compress\n",name));
- VOID(nisam_close(isam_file));
- DBUG_RETURN(0);
- }
- VOID(nisam_lock_database(isam_file,F_WRLCK));
- DBUG_RETURN(isam_file);
-}
-
-
-static bool open_isam_files(MRG_INFO *mrg,char **names,uint count)
-{
- uint i,j;
- mrg->count=0;
- mrg->current=0;
- mrg->file=(N_INFO**) my_malloc(sizeof(N_INFO*)*count,MYF(MY_FAE));
- for (i=0; i < count ; i++)
- {
- if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY)))
- goto error;
- }
- /* Check that files are identical */
- for (j=0 ; j < count-1 ; j++)
- {
- N_RECINFO *m1,*m2,*end;
- if (mrg->file[j]->s->base.reclength != mrg->file[j+1]->s->base.reclength ||
- mrg->file[j]->s->base.fields != mrg->file[j+1]->s->base.fields)
- goto diff_file;
- m1=mrg->file[j]->s->rec;
- end=m1+mrg->file[j]->s->base.fields;
- m2=mrg->file[j+1]->s->rec;
- for ( ; m1 != end ; m1++,m2++)
- {
- if ((m1->base.type != m2->base.type && ! force_pack) ||
- m1->base.length != m2->base.length)
- goto diff_file;
- }
- }
- mrg->count=count;
- return 0;
-
- diff_file:
- fprintf(stderr,"%s: Tables '%s' and '%s' are not identical\n",
- my_progname,names[j],names[j+1]);
- error:
- while (i--)
- nisam_close(mrg->file[i]);
- return 1;
-}
-
-
-static int compress(MRG_INFO *mrg,char *result_table)
-{
- int error;
- File new_file,join_isam_file;
- N_INFO *isam_file;
- ISAM_SHARE *share;
- char org_name[FN_REFLEN],new_name[FN_REFLEN],temp_name[FN_REFLEN];
- uint i,header_length,fields,trees,used_trees;
- my_off_t old_length,new_length,tot_elements;
- HUFF_COUNTS *huff_counts;
- HUFF_TREE *huff_trees;
- DBUG_ENTER("compress");
-
- isam_file=mrg->file[0]; /* Take this as an example */
- share=isam_file->s;
- new_file=join_isam_file= -1;
- trees=fields=0;
- huff_trees=0;
- huff_counts=0;
-
- /* Create temporary or join file */
-
- if (backup)
- VOID(fn_format(org_name,isam_file->filename,"",N_NAME_DEXT,2));
- else
- VOID(fn_format(org_name,isam_file->filename,"",N_NAME_DEXT,2+4+16));
- if (!test_only && result_table)
- {
- /* Make a new indexfile based on first file in list */
- uint length;
- char *buff;
- strmov(org_name,result_table); /* Fix error messages */
- VOID(fn_format(new_name,result_table,"",N_NAME_IEXT,2));
- if ((join_isam_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME)))
- < 0)
- goto err;
- length=share->base.keystart;
- if (!(buff=my_malloc(length,MYF(MY_WME))))
- goto err;
- if (my_pread(share->kfile,buff,length,0L,MYF(MY_WME | MY_NABP)) ||
- my_write(join_isam_file,buff,length,
- MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)))
- {
- my_free(buff,MYF(0));
- goto err;
- }
- my_free(buff,MYF(0));
- VOID(fn_format(new_name,result_table,"",N_NAME_DEXT,2));
- }
- else if (!tmp_dir[0])
- VOID(make_new_name(new_name,org_name));
- else
- VOID(fn_format(new_name,org_name,tmp_dir,DATA_TMP_EXT,1+2+4));
- if (!test_only &&
- (new_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME))) < 0)
- goto err;
-
- /* Start calculating statistics */
-
- mrg->records=0;
- for (i=0 ; i < mrg->count ; i++)
- mrg->records+=mrg->file[i]->s->state.records;
- if (write_loop || verbose)
- {
- printf("Compressing %s: (%lu records)\n",
- result_table ? new_name : org_name,(ulong) mrg->records);
- }
- trees=fields=share->base.fields;
- huff_counts=init_huff_count(isam_file,mrg->records);
- QUICK_SAFEMALLOC;
- if (write_loop || verbose)
- printf("- Calculating statistics\n");
- if (get_statistic(mrg,huff_counts))
- goto err;
- NORMAL_SAFEMALLOC;
- old_length=0;
- for (i=0; i < mrg->count ; i++)
- old_length+= (mrg->file[i]->s->state.data_file_length -
- mrg->file[i]->s->state.empty);
-
- if (init_queue(&queue,256,0,0,compare_huff_elements,0))
- goto err;
- check_counts(huff_counts,fields,mrg->records);
- huff_trees=make_huff_trees(huff_counts,trees);
- if ((int) (used_trees=join_same_trees(huff_counts,trees)) < 0)
- goto err;
- if (make_huff_decode_table(huff_trees,fields))
- goto err;
-
- init_file_buffer(new_file,0);
- file_buffer.pos_in_file=HEAD_LENGTH;
- if (! test_only)
- VOID(my_seek(new_file,file_buffer.pos_in_file,MY_SEEK_SET,MYF(0)));
-
- write_field_info(huff_counts,fields,used_trees);
- if (!(tot_elements=write_huff_tree(huff_trees,trees)))
- goto err;
- header_length=(uint) file_buffer.pos_in_file+
- (uint) (file_buffer.pos-file_buffer.buffer);
-
- /* Compress file */
- if (write_loop || verbose)
- printf("- Compressing file\n");
- error=compress_isam_file(mrg,huff_counts);
- new_length=file_buffer.pos_in_file;
- if (!error && !test_only)
- {
- char buff[MEMMAP_EXTRA_MARGIN]; /* End marginal for memmap */
- bzero(buff,sizeof(buff));
- error=my_write(file_buffer.file,buff,sizeof(buff),
- MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
- }
- if (!error)
- error=write_header(mrg,header_length,used_trees,tot_elements,
- new_length);
- end_file_buffer();
-
- if (verbose && mrg->records)
- printf("Min record length: %6d Max length: %6d Mean total length: %6lu\n",
- mrg->min_pack_length,mrg->max_pack_length,
- (ulong) (new_length/mrg->records));
-
- if (!test_only)
- {
- error|=my_close(new_file,MYF(MY_WME));
- if (!result_table)
- {
- error|=my_close(isam_file->dfile,MYF(MY_WME));
- isam_file->dfile= -1; /* Tell nisam_close file is closed */
- }
- }
-
- free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields);
- if (! test_only && ! error)
- {
- if (result_table)
- {
- error=save_state_mrg(join_isam_file,mrg,new_length,crc);
- }
- else
- {
- if (backup)
- {
- if (my_rename(org_name,make_old_name(temp_name,isam_file->filename),
- MYF(MY_WME)))
- error=1;
- else
- {
- if (tmp_dir[0])
- {
- if (!(error=my_copy(new_name,org_name,MYF(MY_WME))))
- VOID(my_delete(new_name,MYF(MY_WME)));
- }
- else
- error=my_rename(new_name,org_name,MYF(MY_WME));
- if (!error)
- VOID(my_copystat(temp_name,org_name,MYF(MY_COPYTIME)));
- }
- }
- else
- {
- if (tmp_dir[0])
- {
-
- if (!(error=my_copy(new_name,org_name,
- MYF(MY_WME | MY_HOLD_ORIGINAL_MODES
- | MY_COPYTIME))))
- VOID(my_delete(new_name,MYF(MY_WME)));
- }
- else
- error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME));
- }
- if (! error)
- save_state(isam_file,mrg,new_length,crc);
- }
- }
- error|=mrg_close(mrg);
- if (join_isam_file >= 0)
- error|=my_close(join_isam_file,MYF(MY_WME));
- if (error)
- {
- VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name));
- DBUG_RETURN(-1);
- }
- if (write_loop || verbose)
- {
- if (old_length)
- printf("%.4g%% \n",
- my_off_t2double(old_length-new_length)*100.0/
- my_off_t2double(old_length));
- else
- puts("Empty file saved in compressed format");
- }
- DBUG_RETURN(0);
-
- err:
- free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields);
- if (new_file >= 0)
- VOID(my_close(new_file,MYF(0)));
- if (join_isam_file >= 0)
- VOID(my_close(join_isam_file,MYF(0)));
- mrg_close(mrg);
- VOID(fprintf(stderr,"Aborted: %s is not compressed\n",org_name));
- DBUG_RETURN(-1);
-}
-
- /* Init a huff_count-struct for each field and init it */
-
-static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records)
-{
- reg2 uint i;
- reg1 HUFF_COUNTS *count;
- if ((count = (HUFF_COUNTS*) my_malloc(info->s->base.fields*sizeof(HUFF_COUNTS),
- MYF(MY_ZEROFILL | MY_WME))))
- {
- for (i=0 ; i < info->s->base.fields ; i++)
- {
- enum en_fieldtype type;
- count[i].field_length=info->s->rec[i].base.length;
- type= count[i].field_type= (enum en_fieldtype) info->s->rec[i].base.type;
- if (type == FIELD_INTERVALL ||
- type == FIELD_CONSTANT ||
- type == FIELD_ZERO)
- type = FIELD_NORMAL;
- if (count[i].field_length <= 8 &&
- (type == FIELD_NORMAL ||
- type == FIELD_SKIP_ZERO))
- count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,
- NULL, NULL);
- if (records)
- count[i].tree_pos=count[i].tree_buff =
- my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
- MYF(MY_WME));
- }
- }
- return count;
-}
-
-
- /* Free memory used by counts and trees */
-
-static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees, uint trees, HUFF_COUNTS *huff_counts, uint fields)
-{
- register uint i;
-
- if (huff_trees)
- {
- for (i=0 ; i < trees ; i++)
- {
- if (huff_trees[i].element_buffer)
- my_free((gptr) huff_trees[i].element_buffer,MYF(0));
- if (huff_trees[i].code)
- my_free((gptr) huff_trees[i].code,MYF(0));
- }
- my_free((gptr) huff_trees,MYF(0));
- }
- if (huff_counts)
- {
- for (i=0 ; i < fields ; i++)
- {
- if (huff_counts[i].tree_buff)
- {
- my_free((gptr) huff_counts[i].tree_buff,MYF(0));
- delete_tree(&huff_counts[i].int_tree);
- }
- }
- my_free((gptr) huff_counts,MYF(0));
- }
- delete_queue(&queue); /* This is safe to free */
- return;
-}
-
- /* Read through old file and gather some statistics */
-
-static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
-{
- int error;
- uint length,reclength;
- byte *record,*pos,*next_pos,*end_pos,*start_pos;
- my_off_t record_count;
- HUFF_COUNTS *count,*end_count;
- TREE_ELEMENT *element;
- DBUG_ENTER("get_statistic");
-
- reclength=mrg->file[0]->s->base.reclength;
- record=(byte*) my_alloca(reclength);
- end_count=huff_counts+mrg->file[0]->s->base.fields;
- record_count=crc=0;
-
- mrg_reset(mrg);
- while ((error=mrg_rrnd(mrg,record)) >= 0)
- {
- if (! error)
- {
- crc^=_nisam_checksum(record,reclength);
- for (pos=record,count=huff_counts ;
- count < end_count ;
- count++,
- pos=next_pos)
- {
- next_pos=end_pos=(start_pos=pos)+count->field_length;
-
- /* Put value in tree if there is room for it */
- if (count->tree_buff)
- {
- global_count=count;
- if (!(element=tree_insert(&count->int_tree, pos, 0,
- count->int_tree.custom_arg)) ||
- ((element->count == 1 &&
- count->tree_buff + tree_buff_length <
- count->tree_pos + count->field_length) ||
- (count->field_length == 1 &&
- count->int_tree.elements_in_tree > 1)))
- {
- delete_tree(&count->int_tree);
- my_free(count->tree_buff,MYF(0));
- count->tree_buff=0;
- }
- else
- {
- if (element->count == 1)
- { /* New element */
- memcpy(count->tree_pos,pos,(size_t) count->field_length);
- tree_set_pointer(element,count->tree_pos);
- count->tree_pos+=count->field_length;
- }
- }
- }
-
- /* Save character counters and space-counts and zero-field-counts */
- if (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIP_ENDSPACE)
- {
- for ( ; end_pos > pos ; end_pos--)
- if (end_pos[-1] != ' ')
- break;
- if (end_pos == pos)
- {
- count->empty_fields++;
- count->max_zero_fill=0;
- continue;
- }
- length= (uint) (next_pos-end_pos);
- count->tot_end_space+=length;
- if (length < 8)
- count->end_space[length]++;
- if (count->max_end_space < length)
- count->max_end_space = length;
- }
- if (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIP_PRESPACE)
- {
- for (pos=start_pos; pos < end_pos ; pos++)
- if (pos[0] != ' ')
- break;
- if (end_pos == pos)
- {
- count->empty_fields++;
- count->max_zero_fill=0;
- continue;
- }
- length= (uint) (pos-start_pos);
- count->tot_pre_space+=length;
- if (length < 8)
- count->pre_space[length]++;
- if (count->max_pre_space < length)
- count->max_pre_space = length;
- }
- if (count->field_length <= 8 &&
- (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIP_ZERO))
- {
- uint i;
- if (!memcmp((byte*) start_pos,zero_string,count->field_length))
- {
- count->zero_fields++;
- continue;
- }
-#ifdef BYTE_ORDER_HIGH_FIRST
- for (i =0 ; i < count->max_zero_fill && ! start_pos[i] ; i++) ;
- if (i < count->max_zero_fill)
- count->max_zero_fill=i;
-#else
- for (i =0 ; i < count->max_zero_fill && ! end_pos[-1 - (int) i] ; i++) ;
- if (i < count->max_zero_fill)
- count->max_zero_fill=i;
-#endif
- }
- for (pos=start_pos ; pos < end_pos ; pos++)
- count->counts[(uchar) *pos]++;
- }
- record_count++;
- if (write_loop && record_count % WRITE_COUNT == 0)
- {
- printf("%lu\r",(ulong) record_count); VOID(fflush(stdout));
- }
- }
- }
- if (write_loop)
- {
- printf(" \r"); VOID(fflush(stdout));
- }
- mrg->records=record_count;
- my_afree((gptr) record);
- DBUG_RETURN(0);
-}
-
-static int compare_huff_elements(void *not_used __attribute__((unused)),
- byte *a, byte *b)
-{
- return *((my_off_t*) a) < *((my_off_t*) b) ? -1 :
- (*((my_off_t*) a) == *((my_off_t*) b) ? 0 : 1);
-}
-
- /* Check each tree if we should use pre-space-compress, end-space-
- compress, empty-field-compress or zero-field-compress */
-
-static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records)
-{
- uint space_fields,fill_zero_fields,field_count[(int) FIELD_ZERO+1];
- my_off_t old_length,new_length,length;
- DBUG_ENTER("check_counts");
-
- bzero((gptr) field_count,sizeof(field_count));
- space_fields=fill_zero_fields=0;
-
- for (; trees-- ; huff_counts++)
- {
- huff_counts->field_type=FIELD_NORMAL;
- huff_counts->pack_type=0;
-
- if (huff_counts->zero_fields || ! records)
- {
- my_off_t old_space_count;
- if (huff_counts->zero_fields == records)
- {
- huff_counts->field_type= FIELD_ZERO;
- huff_counts->bytes_packed=0;
- huff_counts->counts[0]=0;
- goto found_pack;
- }
- old_space_count=huff_counts->counts[' '];
- huff_counts->counts[' ']+=huff_counts->tot_end_space+
- huff_counts->tot_pre_space +
- huff_counts->empty_fields * huff_counts->field_length;
- old_length=calc_packed_length(huff_counts,0)+records/8;
- length=huff_counts->zero_fields*huff_counts->field_length;
- huff_counts->counts[0]+=length;
- new_length=calc_packed_length(huff_counts,0);
- if (old_length < new_length && huff_counts->field_length > 1)
- {
- huff_counts->field_type=FIELD_SKIP_ZERO;
- huff_counts->counts[0]-=length;
- huff_counts->bytes_packed=old_length- records/8;
- goto found_pack;
- }
- huff_counts->counts[' ']=old_space_count;
- }
- huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
- if (huff_counts->empty_fields)
- {
- if (huff_counts->field_length > 2 &&
- huff_counts->empty_fields + (records - huff_counts->empty_fields)*
- (1+max_bit(max(huff_counts->max_pre_space,
- huff_counts->max_end_space))) <
- records * max_bit(huff_counts->field_length))
- {
- huff_counts->pack_type |= PACK_TYPE_SPACE_FIELDS;
- }
- else
- {
- length=huff_counts->empty_fields*huff_counts->field_length;
- if (huff_counts->tot_end_space || ! huff_counts->tot_pre_space)
- {
- huff_counts->tot_end_space+=length;
- huff_counts->max_end_space=huff_counts->field_length;
- if (huff_counts->field_length < 8)
- huff_counts->end_space[huff_counts->field_length]+=
- huff_counts->empty_fields;
- }
- else
- {
- huff_counts->tot_pre_space+=length;
- huff_counts->max_pre_space=huff_counts->field_length;
- if (huff_counts->field_length < 8)
- huff_counts->pre_space[huff_counts->field_length]+=
- huff_counts->empty_fields;
- }
- }
- }
- if (huff_counts->tot_end_space)
- {
- huff_counts->counts[' ']+=huff_counts->tot_pre_space;
- if (test_space_compress(huff_counts,records,huff_counts->max_end_space,
- huff_counts->end_space,
- huff_counts->tot_end_space,FIELD_SKIP_ENDSPACE))
- goto found_pack;
- huff_counts->counts[' ']-=huff_counts->tot_pre_space;
- }
- if (huff_counts->tot_pre_space)
- {
- if (test_space_compress(huff_counts,records,huff_counts->max_pre_space,
- huff_counts->pre_space,
- huff_counts->tot_pre_space,FIELD_SKIP_PRESPACE))
- goto found_pack;
- }
-
- found_pack: /* Found field-packing */
-
- /* Test if we can use zero-fill */
-
- if (huff_counts->max_zero_fill &&
- (huff_counts->field_type == FIELD_NORMAL ||
- huff_counts->field_type == FIELD_SKIP_ZERO))
- {
- huff_counts->counts[0]-=huff_counts->max_zero_fill*
- (huff_counts->field_type == FIELD_SKIP_ZERO ?
- records - huff_counts->zero_fields : records);
- huff_counts->pack_type|=PACK_TYPE_ZERO_FILL;
- huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
- }
-
- /* Test if intervall-field is better */
-
- if (huff_counts->tree_buff)
- {
- HUFF_TREE tree;
-
- tree.element_buffer=0;
- if (!make_huff_tree(&tree,huff_counts) &&
- tree.bytes_packed+tree.tree_pack_length < huff_counts->bytes_packed)
- {
- if (tree.elements == 1)
- huff_counts->field_type=FIELD_CONSTANT;
- else
- huff_counts->field_type=FIELD_INTERVALL;
- huff_counts->pack_type=0;
- }
- else
- {
- my_free((gptr) huff_counts->tree_buff,MYF(0));
- delete_tree(&huff_counts->int_tree);
- huff_counts->tree_buff=0;
- }
- if (tree.element_buffer)
- my_free((gptr) tree.element_buffer,MYF(0));
- }
- if (huff_counts->pack_type & PACK_TYPE_SPACE_FIELDS)
- space_fields++;
- if (huff_counts->pack_type & PACK_TYPE_ZERO_FILL)
- fill_zero_fields++;
- field_count[huff_counts->field_type]++;
- }
- if (verbose)
- printf("\nnormal: %3d empty-space: %3d empty-zero: %3d empty-fill: %3d\npre-space: %3d end-space: %3d table-lookup: %3d zero: %3d\n",
- field_count[FIELD_NORMAL],space_fields,
- field_count[FIELD_SKIP_ZERO],fill_zero_fields,
- field_count[FIELD_SKIP_PRESPACE],
- field_count[FIELD_SKIP_ENDSPACE],
- field_count[FIELD_INTERVALL],
- field_count[FIELD_ZERO]);
- DBUG_VOID_RETURN;
-}
-
- /* Test if we can use space-compression and empty-field-compression */
-
-static int
-test_space_compress(HUFF_COUNTS *huff_counts, my_off_t records,
- uint max_space_length, my_off_t *space_counts,
- my_off_t tot_space_count, enum en_fieldtype field_type)
-{
- int min_pos;
- uint length_bits,i;
- my_off_t space_count,min_space_count,min_pack,new_length,skipp;
-
- length_bits=max_bit(max_space_length);
-
- /* Default no end_space-packing */
- space_count=huff_counts->counts[(uint) ' '];
- min_space_count= (huff_counts->counts[(uint) ' ']+= tot_space_count);
- min_pack=calc_packed_length(huff_counts,0);
- min_pos= -2;
- huff_counts->counts[(uint) ' ']=space_count;
-
- /* Test with allways space-count */
- new_length=huff_counts->bytes_packed+length_bits*records/8;
- if (new_length+1 < min_pack)
- {
- min_pos= -1;
- min_pack=new_length;
- min_space_count=space_count;
- }
- /* Test with length-flag */
- for (skipp=0L, i=0 ; i < 8 ; i++)
- {
- if (space_counts[i])
- {
- if (i)
- huff_counts->counts[(uint) ' ']+=space_counts[i];
- skipp+=huff_counts->pre_space[i];
- new_length=calc_packed_length(huff_counts,0)+
- (records+(records-skipp)*(1+length_bits))/8;
- if (new_length < min_pack)
- {
- min_pos=(int) i;
- min_pack=new_length;
- min_space_count=huff_counts->counts[(uint) ' '];
- }
- }
- }
-
- huff_counts->counts[(uint) ' ']=min_space_count;
- huff_counts->bytes_packed=min_pack;
- switch (min_pos) {
- case -2:
- return(0); /* No space-compress */
- case -1: /* Always space-count */
- huff_counts->field_type=field_type;
- huff_counts->min_space=0;
- huff_counts->length_bits=max_bit(max_space_length);
- break;
- default:
- huff_counts->field_type=field_type;
- huff_counts->min_space=(uint) min_pos;
- huff_counts->pack_type|=PACK_TYPE_SELECTED;
- huff_counts->length_bits=max_bit(max_space_length);
- break;
- }
- return(1); /* Using space-compress */
-}
-
-
- /* Make a huff_tree of each huff_count */
-
-static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts, uint trees)
-{
- uint tree;
- HUFF_TREE *huff_tree;
- DBUG_ENTER("make_huff_trees");
-
- if (!(huff_tree=(HUFF_TREE*) my_malloc(trees*sizeof(HUFF_TREE),
- MYF(MY_WME | MY_ZEROFILL))))
- DBUG_RETURN(0);
-
- for (tree=0 ; tree < trees ; tree++)
- {
- if (make_huff_tree(huff_tree+tree,huff_counts+tree))
- {
- while (tree--)
- my_free((gptr) huff_tree[tree].element_buffer,MYF(0));
- my_free((gptr) huff_tree,MYF(0));
- DBUG_RETURN(0);
- }
- }
- DBUG_RETURN(huff_tree);
-}
-
- /* Update huff_tree according to huff_counts->counts or
- huff_counts->tree_buff */
-
-static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
-{
- uint i,found,bits_packed,first,last;
- my_off_t bytes_packed;
- HUFF_ELEMENT *a,*b,*new;
-
- first=last=0;
- if (huff_counts->tree_buff)
- {
- found= (uint) (huff_counts->tree_pos - huff_counts->tree_buff) /
- huff_counts->field_length;
- first=0; last=found-1;
- }
- else
- {
- for (i=found=0 ; i < 256 ; i++)
- {
- if (huff_counts->counts[i])
- {
- if (! found++)
- first=i;
- last=i;
- }
- }
- if (found < 2)
- found=2;
- }
-
- if (queue.max_elements < found)
- {
- delete_queue(&queue);
- if (init_queue(&queue,found,0,0,compare_huff_elements,0))
- return -1;
- }
-
- if (!huff_tree->element_buffer)
- {
- if (!(huff_tree->element_buffer=
- (HUFF_ELEMENT*) my_malloc(found*2*sizeof(HUFF_ELEMENT),MYF(MY_WME))))
- return 1;
- }
- else
- {
- HUFF_ELEMENT *temp;
- if (!(temp=
- (HUFF_ELEMENT*) my_realloc((gptr) huff_tree->element_buffer,
- found*2*sizeof(HUFF_ELEMENT),
- MYF(MY_WME))))
- return 1;
- huff_tree->element_buffer=temp;
- }
-
- huff_counts->tree=huff_tree;
- huff_tree->counts=huff_counts;
- huff_tree->min_chr=first;
- huff_tree->max_chr=last;
- huff_tree->char_bits=max_bit(last-first);
- huff_tree->offset_bits=max_bit(found-1)+1;
-
- if (huff_counts->tree_buff)
- {
- huff_tree->elements=0;
- tree_walk(&huff_counts->int_tree,
- (int (*)(void*, element_count,void*)) save_counts_in_queue,
- (gptr) huff_tree, left_root_right);
- huff_tree->tree_pack_length=(1+15+16+5+5+
- (huff_tree->char_bits+1)*found+
- (huff_tree->offset_bits+1)*
- (found-2)+7)/8 +
- (uint) (huff_tree->counts->tree_pos-
- huff_tree->counts->tree_buff);
- }
- else
- {
- huff_tree->elements=found;
- huff_tree->tree_pack_length=(9+9+5+5+
- (huff_tree->char_bits+1)*found+
- (huff_tree->offset_bits+1)*
- (found-2)+7)/8;
-
- for (i=first, found=0 ; i <= last ; i++)
- {
- if (huff_counts->counts[i])
- {
- new=huff_tree->element_buffer+(found++);
- new->count=huff_counts->counts[i];
- new->a.leaf.null=0;
- new->a.leaf.element_nr=i;
- queue.root[found]=(byte*) new;
- }
- }
- while (found < 2)
- { /* Our huff_trees request at least 2 elements */
- new=huff_tree->element_buffer+(found++);
- new->count=0;
- new->a.leaf.null=0;
- if (last)
- new->a.leaf.element_nr=huff_tree->min_chr=last-1;
- else
- new->a.leaf.element_nr=huff_tree->max_chr=last+1;
- queue.root[found]=(byte*) new;
- }
- }
- queue.elements=found;
-
- for (i=found/2 ; i > 0 ; i--)
- _downheap(&queue,i);
- bytes_packed=0; bits_packed=0;
- for (i=1 ; i < found ; i++)
- {
- a=(HUFF_ELEMENT*) queue_remove(&queue,0);
- b=(HUFF_ELEMENT*) queue.root[1];
- new=huff_tree->element_buffer+found+i;
- new->count=a->count+b->count;
- bits_packed+=(uint) (new->count & 7);
- bytes_packed+=new->count/8;
- new->a.nod.left=a; /* lesser in left */
- new->a.nod.right=b;
- queue.root[1]=(byte*) new;
- queue_replaced(&queue);
- }
- huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
- huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8;
- return 0;
-}
-
-static int compare_tree(register const uchar *s, register const uchar *t)
-{
- uint length;
- for (length=global_count->field_length; length-- ;)
- if (*s++ != *t++)
- return (int) s[-1] - (int) t[-1];
- return 0;
-}
-
- /* Used by make_huff_tree to save intervall-counts in queue */
-
-static int save_counts_in_queue(byte *key, element_count count, HUFF_TREE *tree)
-{
- HUFF_ELEMENT *new;
-
- new=tree->element_buffer+(tree->elements++);
- new->count=count;
- new->a.leaf.null=0;
- new->a.leaf.element_nr= (uint) (key- tree->counts->tree_buff) /
- tree->counts->field_length;
- queue.root[tree->elements]=(byte*) new;
- return 0;
-}
-
-
- /* Calculate length of file if given counts should be used */
- /* Its actually a faster version of make_huff_tree */
-
-static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, uint add_tree_lenght)
-{
- uint i,found,bits_packed,first,last;
- my_off_t bytes_packed;
- HUFF_ELEMENT element_buffer[256];
- DBUG_ENTER("calc_packed_length");
-
- first=last=0;
- for (i=found=0 ; i < 256 ; i++)
- {
- if (huff_counts->counts[i])
- {
- if (! found++)
- first=i;
- last=i;
- queue.root[found]=(byte*) &huff_counts->counts[i];
- }
- }
- if (!found)
- DBUG_RETURN(0); /* Empty tree */
- if (found < 2)
- queue.root[++found]=(byte*) &huff_counts->counts[last ? 0 : 1];
-
- queue.elements=found;
-
- bytes_packed=0; bits_packed=0;
- if (add_tree_lenght)
- bytes_packed=(8+9+5+5+(max_bit(last-first)+1)*found+
- (max_bit(found-1)+1+1)*(found-2) +7)/8;
- for (i=(found+1)/2 ; i > 0 ; i--)
- _downheap(&queue,i);
- for (i=0 ; i < found-1 ; i++)
- {
- HUFF_ELEMENT *a,*b,*new;
- a=(HUFF_ELEMENT*) queue_remove(&queue,0);
- b=(HUFF_ELEMENT*) queue.root[1];
- new=element_buffer+i;
- new->count=a->count+b->count;
- bits_packed+=(uint) (new->count & 7);
- bytes_packed+=new->count/8;
- queue.root[1]=(byte*) new;
- queue_replaced(&queue);
- }
- DBUG_RETURN(bytes_packed+(bits_packed+7)/8);
-}
-
-
- /* Remove trees that don't give any compression */
-
-static uint join_same_trees(HUFF_COUNTS *huff_counts, uint trees)
-{
- uint k,tree_number;
- HUFF_COUNTS count,*i,*j,*last_count;
-
- last_count=huff_counts+trees;
- for (tree_number=0, i=huff_counts ; i < last_count ; i++)
- {
- if (!i->tree->tree_number)
- {
- i->tree->tree_number= ++tree_number;
- if (i->tree_buff)
- continue; /* Don't join intervall */
- for (j=i+1 ; j < last_count ; j++)
- {
- if (! j->tree->tree_number && ! j->tree_buff)
- {
- for (k=0 ; k < 256 ; k++)
- count.counts[k]=i->counts[k]+j->counts[k];
- if (calc_packed_length(&count,1) <=
- i->tree->bytes_packed + j->tree->bytes_packed+
- i->tree->tree_pack_length+j->tree->tree_pack_length+
- ALLOWED_JOIN_DIFF)
- {
- memcpy((byte*) i->counts,(byte*) count.counts,
- sizeof(count.counts[0])*256);
- my_free((gptr) j->tree->element_buffer,MYF(0));
- j->tree->element_buffer=0;
- j->tree=i->tree;
- bmove((byte*) i->counts,(byte*) count.counts,
- sizeof(count.counts[0])*256);
- if (make_huff_tree(i->tree,i))
- return (uint) -1;
- }
- }
- }
- }
- }
- if (verbose)
- printf("Original trees: %d After join: %d\n",trees,tree_number);
- return tree_number; /* Return trees left */
-}
-
-
- /* Fill in huff_tree decode tables */
-
-static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees)
-{
- uint elements;
- for ( ; trees-- ; huff_tree++)
- {
- if (huff_tree->tree_number > 0)
- {
- elements=huff_tree->counts->tree_buff ? huff_tree->elements : 256;
- if (!(huff_tree->code =
- (ulong*) my_malloc(elements*
- (sizeof(ulong)+sizeof(uchar)),
- MYF(MY_WME | MY_ZEROFILL))))
- return 1;
- huff_tree->code_len=(uchar*) (huff_tree->code+elements);
- make_traverse_code_tree(huff_tree,huff_tree->root,32,0);
- }
- }
- return 0;
-}
-
-
-static void make_traverse_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element,
- uint size, ulong code)
-{
- uint chr;
- if (!element->a.leaf.null)
- {
- chr=element->a.leaf.element_nr;
- huff_tree->code_len[chr]=(uchar) (32-size);
- huff_tree->code[chr]= (code >> size);
- if (huff_tree->height < 32-size)
- huff_tree->height= 32-size;
- }
- else
- {
- size--;
- make_traverse_code_tree(huff_tree,element->a.nod.left,size,code);
- make_traverse_code_tree(huff_tree,element->a.nod.right,size,
- code+((ulong) 1L << size));
- }
- return;
-}
-
-
- /* Write header to new packed data file */
-
-static int write_header(MRG_INFO *mrg,uint head_length,uint trees,
- my_off_t tot_elements,my_off_t filelength)
-{
- byte *buff=file_buffer.pos;
-
- bzero(buff,HEAD_LENGTH);
- memcpy(buff,nisam_pack_file_magic,4);
- int4store(buff+4,head_length);
- int4store(buff+8, mrg->min_pack_length);
- int4store(buff+12,mrg->max_pack_length);
- int4store(buff+16,tot_elements);
- int4store(buff+20,intervall_length);
- int2store(buff+24,trees);
- buff[26]=(char) mrg->ref_length;
- /* Save record pointer length */
- buff[27]= (uchar) (filelength >= (1L << 24) ? 4 :
- filelength >= (1L << 16) ? 3 : 2);
- if (test_only)
- return 0;
- VOID(my_seek(file_buffer.file,0L,MY_SEEK_SET,MYF(0)));
- return my_write(file_buffer.file,file_buffer.pos,HEAD_LENGTH,
- MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
-}
-
- /* Write fieldinfo to new packed file */
-
-static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees)
-{
- reg1 uint i;
- uint huff_tree_bits;
- huff_tree_bits=max_bit(trees ? trees-1 : 0);
-
- for (i=0 ; i++ < fields ; counts++)
- {
- write_bits((ulong) (int) counts->field_type,4);
- write_bits(counts->pack_type,4);
- if (counts->pack_type & PACK_TYPE_ZERO_FILL)
- write_bits(counts->max_zero_fill,4);
- else
- write_bits(counts->length_bits,4);
- write_bits((ulong) counts->tree->tree_number-1,huff_tree_bits);
- }
- flush_bits();
- return;
-}
-
- /* Write all huff_trees to new datafile. Return tot count of
- elements in all trees
- Returns 0 on error */
-
-static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
-{
- uint i,int_length;
- uint *packed_tree,*offset,length;
- my_off_t elements;
-
- for (i=length=0 ; i < trees ; i++)
- if (huff_tree[i].tree_number > 0 && huff_tree[i].elements > length)
- length=huff_tree[i].elements;
- if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2)))
- {
- my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2);
- return 0;
- }
-
- intervall_length=0;
- for (elements=0; trees-- ; huff_tree++)
- {
- if (huff_tree->tree_number == 0)
- continue; /* Deleted tree */
- elements+=huff_tree->elements;
- huff_tree->max_offset=2;
- if (huff_tree->elements <= 1)
- offset=packed_tree;
- else
- offset=make_offset_code_tree(huff_tree,huff_tree->root,packed_tree);
- huff_tree->offset_bits=max_bit(huff_tree->max_offset);
- if (huff_tree->max_offset >= IS_OFFSET)
- { /* This should be impossible */
- VOID(fprintf(stderr,"Tree offset got too big: %d, aborted\n",
- huff_tree->max_offset));
- my_afree((gptr) packed_tree);
- return 0;
- }
-
-#ifdef EXTRA_DBUG
- printf("pos: %d elements: %d tree-elements: %d char_bits: %d\n",
- (uint) (file_buffer.pos-file_buffer.buffer),
- huff_tree->elements, (offset-packed_tree),huff_tree->char_bits);
-#endif
- if (!huff_tree->counts->tree_buff)
- {
- write_bits(0,1);
- write_bits(huff_tree->min_chr,8);
- write_bits(huff_tree->elements,9);
- write_bits(huff_tree->char_bits,5);
- write_bits(huff_tree->offset_bits,5);
- int_length=0;
- }
- else
- {
- int_length=(uint) (huff_tree->counts->tree_pos -
- huff_tree->counts->tree_buff);
- write_bits(1,1);
- write_bits(huff_tree->elements,15);
- write_bits(int_length,16);
- write_bits(huff_tree->char_bits,5);
- write_bits(huff_tree->offset_bits,5);
- intervall_length+=int_length;
- }
- length=(uint) (offset-packed_tree);
- if (length != huff_tree->elements*2-2)
- printf("error: Huff-tree-length: %d != calc_length: %d\n",
- length,huff_tree->elements*2-2);
-
- for (i=0 ; i < length ; i++)
- {
- if (packed_tree[i] & IS_OFFSET)
- write_bits(packed_tree[i] - IS_OFFSET+ ((ulong) 1L << huff_tree->offset_bits),
- huff_tree->offset_bits+1);
- else
- write_bits(packed_tree[i]-huff_tree->min_chr,huff_tree->char_bits+1);
- }
- flush_bits();
- if (huff_tree->counts->tree_buff)
- {
- for (i=0 ; i < int_length ; i++)
- write_bits((uint) (uchar) huff_tree->counts->tree_buff[i],8);
- }
- flush_bits();
- }
- my_afree((gptr) packed_tree);
- return elements;
-}
-
-
-static uint *make_offset_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element,
- uint *offset)
-{
- uint *prev_offset;
-
- prev_offset= offset;
- if (!element->a.nod.left->a.leaf.null)
- {
- offset[0] =(uint) element->a.nod.left->a.leaf.element_nr;
- offset+=2;
- }
- else
- {
- prev_offset[0]= IS_OFFSET+2;
- offset=make_offset_code_tree(huff_tree,element->a.nod.left,offset+2);
- }
- if (!element->a.nod.right->a.leaf.null)
- {
- prev_offset[1]=element->a.nod.right->a.leaf.element_nr;
- return offset;
- }
- else
- {
- uint temp=(uint) (offset-prev_offset-1);
- prev_offset[1]= IS_OFFSET+ temp;
- if (huff_tree->max_offset < temp)
- huff_tree->max_offset = temp;
- return make_offset_code_tree(huff_tree,element->a.nod.right,offset);
- }
-}
-
- /* Get number of bits neaded to represent value */
-
-static uint max_bit(register uint value)
-{
- reg2 uint power=1;
-
- while ((value>>=1))
- power++;
- return (power);
-}
-
-
-static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
-{
- int error;
- uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length,
- intervall,field_length;
- my_off_t record_count,max_allowed_length;
- ulong length;
- byte *record,*pos,*end_pos,*record_pos,*start_pos;
- HUFF_COUNTS *count,*end_count;
- HUFF_TREE *tree;
- N_INFO *isam_file=mrg->file[0];
- DBUG_ENTER("compress_isam_file");
-
- if (!(record=(byte*) my_alloca(isam_file->s->base.reclength)))
- return -1;
- end_count=huff_counts+isam_file->s->base.fields;
- min_record_length= (uint) ~0;
- max_record_length=0;
-
- for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++)
- {
- if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL))
- huff_counts[i].max_zero_fill=0;
- if (huff_counts[i].field_type == FIELD_CONSTANT ||
- huff_counts[i].field_type == FIELD_ZERO)
- continue;
- if (huff_counts[i].field_type == FIELD_INTERVALL)
- max_calc_length+=huff_counts[i].tree->height;
- else
- max_calc_length+=
- (huff_counts[i].field_length - huff_counts[i].max_zero_fill)*
- huff_counts[i].tree->height+huff_counts[i].length_bits;
- }
- max_calc_length/=8;
- if (max_calc_length <= 255)
- pack_ref_length=1;
- else if (max_calc_length <= 65535)
- pack_ref_length=2;
- else
- pack_ref_length=3;
- if (force_pack_ref_length)
- pack_ref_length=force_pack_ref_length;
- max_allowed_length= 1L << (pack_ref_length*8);
- record_count=0;
-
- mrg_reset(mrg);
- while ((error=mrg_rrnd(mrg,record)) >= 0)
- {
- if (! error)
- {
- if (flush_buffer(max_calc_length+pack_ref_length))
- break;
- record_pos=file_buffer.pos;
- file_buffer.pos+=pack_ref_length;
- for (start_pos=record, count= huff_counts; count < end_count ; count++)
- {
- end_pos=start_pos+(field_length=count->field_length);
- tree=count->tree;
-
- if (count->pack_type & PACK_TYPE_SPACE_FIELDS)
- {
- for (pos=start_pos ; *pos == ' ' && pos < end_pos; pos++) ;
- if (pos == end_pos)
- {
- write_bits(1,1);
- start_pos=end_pos;
- continue;
- }
- write_bits(0,1);
- }
-
-#ifdef BYTE_ORDER_HIGH_FIRST
- start_pos+=count->max_zero_fill;
-#else
- end_pos-=count->max_zero_fill;
-#endif
- field_length-=count->max_zero_fill;
-
- switch(count->field_type) {
- case FIELD_SKIP_ZERO:
- if (!memcmp((byte*) start_pos,zero_string,field_length))
- {
- write_bits(1,1);
- start_pos=end_pos;
- break;
- }
- write_bits(0,1);
- /* Fall through */
- case FIELD_NORMAL:
- for ( ; start_pos < end_pos ; start_pos++)
- write_bits(tree->code[(uchar) *start_pos],
- (uint) tree->code_len[(uchar) *start_pos]);
- break;
- case FIELD_SKIP_ENDSPACE:
- for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ;
- length=(uint) (end_pos-pos);
- if (count->pack_type & PACK_TYPE_SELECTED)
- {
- if (length > count->min_space)
- {
- write_bits(1,1);
- write_bits(length,count->length_bits);
- }
- else
- {
- write_bits(0,1);
- pos=end_pos;
- }
- }
- else
- write_bits(length,count->length_bits);
- for ( ; start_pos < pos ; start_pos++)
- write_bits(tree->code[(uchar) *start_pos],
- (uint) tree->code_len[(uchar) *start_pos]);
- start_pos=end_pos;
- break;
- case FIELD_SKIP_PRESPACE:
- for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ;
- length=(uint) (pos-start_pos);
- if (count->pack_type & PACK_TYPE_SELECTED)
- {
- if (length > count->min_space)
- {
- write_bits(1,1);
- write_bits(length,count->length_bits);
- }
- else
- {
- pos=start_pos;
- write_bits(0,1);
- }
- }
- else
- write_bits(length,count->length_bits);
- for (start_pos=pos ; start_pos < end_pos ; start_pos++)
- write_bits(tree->code[(uchar) *start_pos],
- (uint) tree->code_len[(uchar) *start_pos]);
- break;
- case FIELD_CONSTANT:
- case FIELD_ZERO:
- start_pos=end_pos;
- break;
- case FIELD_INTERVALL:
- global_count=count;
- pos=(byte*) tree_search(&count->int_tree, start_pos,
- count->int_tree.custom_arg);
- intervall=(uint) (pos - count->tree_buff)/field_length;
- write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
- start_pos=end_pos;
- break;
- case FIELD_BLOB:
- VOID(fprintf(stderr,"Can't pack files with blobs. Aborting\n"));
- DBUG_RETURN(1);
- case FIELD_LAST:
- case FIELD_VARCHAR:
- case FIELD_CHECK:
- abort(); /* Impossible */
- }
-#ifndef BYTE_ORDER_HIGH_FIRST
- start_pos+=count->max_zero_fill;
-#endif
- }
- flush_bits();
- length=(ulong) (file_buffer.pos-record_pos)-pack_ref_length;
- save_integer(record_pos,pack_ref_length,length);
- if (length < (ulong) min_record_length)
- min_record_length=(uint) length;
- if (length > (ulong) max_record_length)
- {
- max_record_length=(uint) length;
- if (max_record_length >= max_allowed_length)
- {
- fprintf(stderr,
- "Error: Found record with packed-length: %d, max is: %lu\n",
- max_record_length, (ulong) max_allowed_length);
- error=1;
- break;
- }
- }
- if (write_loop && ++record_count % WRITE_COUNT == 0)
- {
- printf("%lu\r",(ulong) record_count); VOID(fflush(stdout));
- }
- }
- else if (my_errno != HA_ERR_RECORD_DELETED)
- break;
- }
- if (error < 0)
- {
- error=0;
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%s: Got error %d reading records\n",my_progname,my_errno);
- error= 1;
- }
- }
-
- my_afree((gptr) record);
- mrg->ref_length=pack_ref_length;
- mrg->min_pack_length=max_record_length ? min_record_length : 0;
- mrg->max_pack_length=max_record_length;
- if (verbose && max_record_length &&
- max_record_length < max_allowed_length/256)
- printf("Record-length is %d bytes, could have been %d bytes\nYou can change this by using -p=%d next time you pack this file\n",
- pack_ref_length,
- max_record_length/256+1,
- max_record_length/256+1);
- DBUG_RETURN(error || error_on_write || flush_buffer((uint) ~0));
-}
-
-
-static char *make_new_name(char *new_name, char *old_name)
-{
- return fn_format(new_name,old_name,"",DATA_TMP_EXT,2+4);
-}
-
-static char *make_old_name(char *new_name, char *old_name)
-{
- return fn_format(new_name,old_name,"",OLD_EXT,2+4);
-}
-
- /* rutines for bit writing buffer */
-
-static void init_file_buffer(File file, pbool read_buffer)
-{
- file_buffer.file=file;
- file_buffer.buffer=my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE),MYF(MY_WME));
- file_buffer.end=file_buffer.buffer+ALIGN_SIZE(RECORD_CACHE_SIZE)-4;
- file_buffer.pos_in_file=0;
- error_on_write=0;
- if (read_buffer)
- {
-
- file_buffer.pos=file_buffer.end;
- file_buffer.bits=0;
- }
- else
- {
- file_buffer.pos=file_buffer.buffer;
- file_buffer.bits=BITS_SAVED;
- }
- file_buffer.bytes=0;
-}
-
-
-static int flush_buffer(uint neaded_length)
-{
- uint length;
- if ((uint) (file_buffer.end - file_buffer.pos) > neaded_length)
- return 0;
- length=(uint) (file_buffer.pos-file_buffer.buffer);
- file_buffer.pos=file_buffer.buffer;
- file_buffer.pos_in_file+=length;
- if (test_only)
- return 0;
- return (error_on_write|=test(my_write(file_buffer.file,file_buffer.buffer,
- length,
- MYF(MY_WME | MY_NABP |
- MY_WAIT_IF_FULL))));
-}
-
-static void end_file_buffer(void)
-{
- my_free((gptr) file_buffer.buffer,MYF(0));
-}
-
- /* output `bits` low bits of `value' */
-
-static void write_bits (register ulong value, register uint bits)
-{
- if ((file_buffer.bits-=(int) bits) >= 0)
- {
- file_buffer.bytes|=value << file_buffer.bits;
- }
- else
- {
- reg3 uint byte_buff;
- bits= (uint) -file_buffer.bits;
- byte_buff=file_buffer.bytes | (uint) (value >> bits);
-#if BITS_SAVED == 32
- *file_buffer.pos++= (byte) (byte_buff >> 24) ;
- *file_buffer.pos++= (byte) (byte_buff >> 16) ;
-#endif
- *file_buffer.pos++= (byte) (byte_buff >> 8) ;
- *file_buffer.pos++= (byte) byte_buff;
-
- value&=((ulong) 1L << bits)-1;
-#if BITS_SAVED == 16
- if (bits >= sizeof(uint))
- {
- bits-=8;
- *file_buffer.pos++= (uchar) (value >> bits);
- value&= ((ulong) 1L << bits)-1;
- if (bits >= sizeof(uint))
- {
- bits-=8;
- *file_buffer.pos++= (uchar) (value >> bits);
- value&= ((ulong) 1L << bits)-1;
- }
- }
-#endif
- if (file_buffer.pos >= file_buffer.end)
- VOID(flush_buffer((uint) ~0));
- file_buffer.bits=(int) (BITS_SAVED - bits);
- file_buffer.bytes=(uint) (value << (BITS_SAVED - bits));
- }
- return;
-}
-
- /* Flush bits in bit_buffer to buffer */
-
-static void flush_bits (void)
-{
- uint bits,byte_buff;
-
- bits=(file_buffer.bits) & ~7;
- byte_buff = file_buffer.bytes >> bits;
- bits=BITS_SAVED - bits;
- while (bits > 0)
- {
- bits-=8;
- *file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ;
- }
- file_buffer.bits=BITS_SAVED;
- file_buffer.bytes=0;
- return;
-}
-
- /* Store long in 1,2,3,4 or 5 bytes */
-
-static void save_integer(byte *pos, uint pack_length, my_off_t value)
-{
- switch (pack_length) {
- case 5: int5store(pos,(ulonglong) value); break;
- default: int4store(pos,(ulong) value); break;
- case 3: int3store(pos,(ulong) value); break;
- case 2: int2store(pos,(uint) value); break;
- case 1: pos[0]= (byte) (uchar) value; break;
- }
- return;
-}
-
-
-/****************************************************************************
-** functions to handle the joined files
-****************************************************************************/
-
-static void save_state(N_INFO *isam_file,MRG_INFO *mrg,my_off_t new_length,
- ulong crc)
-{
- ISAM_SHARE *share=isam_file->s;
- uint options=uint2korr(share->state.header.options);
- DBUG_ENTER("save_state");
-
- options|= HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA;
- int2store(share->state.header.options,options);
-
- share->state.data_file_length=(ulong) new_length;
- share->state.del=share->state.empty=0;
- share->state.dellink= (ulong) NI_POS_ERROR;
- share->state.splitt=(ulong) mrg->records;
- share->state.version=(ulong) time((time_t*) 0);
- share->state.keys=0;
- share->state.key_file_length=share->base.keystart;
-
- isam_file->update|=(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- isam_file->this_uniq=crc; /* Save crc here */
- share->changed=1; /* Force write of header */
- VOID(my_chsize(share->kfile, share->state.key_file_length, 0,
- MYF(0)));
- if (share->state.keys != share->base.keys)
- isamchk_neaded=1;
- DBUG_VOID_RETURN;
-}
-
-
-static int save_state_mrg(File file,MRG_INFO *mrg,my_off_t new_length,
- ulong crc)
-{
- N_STATE_INFO state;
- N_INFO *isam_file=mrg->file[0];
- uint options;
- DBUG_ENTER("save_state_mrg");
-
- memcpy(&state,&isam_file->s->state,sizeof(state));
- options= (uint2korr(state.header.options) | HA_OPTION_COMPRESS_RECORD |
- HA_OPTION_READ_ONLY_DATA);
- int2store(state.header.options,options);
- state.data_file_length=(ulong) new_length;
- state.del=state.empty=0;
- state.dellink= (ulong) NI_POS_ERROR;
- state.records=state.splitt=(ulong) mrg->records;
- state.version=(ulong) time((time_t*) 0);
- state.keys=0;
- state.key_file_length=isam_file->s->base.keystart;
- state.uniq=crc;
- if (state.keys != isam_file->s->base.keys)
- isamchk_neaded=1;
- DBUG_RETURN (my_pwrite(file,(char*) &state.header,
- isam_file->s->state_length,0L,
- MYF(MY_NABP | MY_WME)) != 0);
-}
-
-
-/* reset for mrg_rrnd */
-
-static void mrg_reset(MRG_INFO *mrg)
-{
- if (mrg->current)
- {
- nisam_extra(*mrg->current,HA_EXTRA_NO_CACHE);
- mrg->current=0;
- }
-}
-
-static int mrg_rrnd(MRG_INFO *info,byte *buf)
-{
- int error;
- N_INFO *isam_info;
- my_off_t filepos;
-
- if (!info->current)
- {
- isam_info= *(info->current=info->file);
- info->end=info->current+info->count;
- nisam_extra(isam_info,HA_EXTRA_RESET);
- nisam_extra(isam_info,HA_EXTRA_CACHE);
- filepos=isam_info->s->pack.header_length;
- }
- else
- {
- isam_info= *info->current;
- filepos= isam_info->nextpos;
- }
-
- for (;;)
- {
- isam_info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- if ((error=(*isam_info->s->read_rnd)(isam_info,(byte*) buf,
- (ulong) filepos, 1)) >= 0 ||
- my_errno != HA_ERR_END_OF_FILE)
- return (error);
- nisam_extra(isam_info,HA_EXTRA_NO_CACHE);
- if (info->current+1 == info->end)
- return(-1);
- info->current++;
- isam_info= *info->current;
- filepos=isam_info->s->pack.header_length;
- nisam_extra(isam_info,HA_EXTRA_RESET);
- nisam_extra(isam_info,HA_EXTRA_CACHE);
- }
-}
-
-
-static int mrg_close(MRG_INFO *mrg)
-{
- uint i;
- int error=0;
- for (i=0 ; i < mrg->count ; i++)
- error|=nisam_close(mrg->file[i]);
- return error;
-}
diff --git a/isam/panic.c b/isam/panic.c
deleted file mode 100644
index 7af979a5104..00000000000
--- a/isam/panic.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "isamdef.h"
-
- /* if flag == HA_PANIC_CLOSE then all misam files are closed */
- /* if flag == HA_PANIC_WRITE then all misam files are unlocked and
- all changed data in single user misam is written to file */
- /* if flag == HA_PANIC_READ then all misam files that was locked when
- nisam_panic(HA_PANIC_WRITE) was done is locked. A ni_readinfo() is
- done for all single user files to get changes in database */
-
-
-int nisam_panic(enum ha_panic_function flag)
-{
- int error=0;
- LIST *list_element,*next_open;
- N_INFO *info;
- DBUG_ENTER("nisam_panic");
-
- pthread_mutex_lock(&THR_LOCK_isam);
- for (list_element=nisam_open_list ; list_element ; list_element=next_open)
- {
- next_open=list_element->next; /* Save if close */
- info=(N_INFO*) list_element->data;
- switch (flag) {
- case HA_PANIC_CLOSE:
- pthread_mutex_unlock(&THR_LOCK_isam); /* Not exactly right... */
- if (nisam_close(info))
- error=my_errno;
- pthread_mutex_lock(&THR_LOCK_isam);
- break;
- case HA_PANIC_WRITE: /* Do this to free databases */
-#ifdef CANT_OPEN_FILES_TWICE
- if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
- break;
-#endif
- if (flush_key_blocks(dflt_key_cache,info->s->kfile,FLUSH_RELEASE))
- error=my_errno;
- if (info->opt_flag & WRITE_CACHE_USED)
- if (flush_io_cache(&info->rec_cache))
- error=my_errno;
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (flush_io_cache(&info->rec_cache))
- error=my_errno;
- reinit_io_cache(&info->rec_cache,READ_CACHE,0,
- (pbool) (info->lock_type != F_UNLCK),1);
- }
-#ifndef NO_LOCKING
- if (info->lock_type != F_UNLCK && ! info->was_locked)
- {
- info->was_locked=info->lock_type;
- if (nisam_lock_database(info,F_UNLCK))
- error=my_errno;
- }
-#else
- {
- int save_status=info->s->w_locks; /* Only w_locks! */
- info->s->w_locks=0;
- if (_nisam_writeinfo(info, test(info->update & HA_STATE_CHANGED)))
- error=my_errno;
- info->s->w_locks=save_status;
- info->update&= ~HA_STATE_CHANGED; /* Not changed */
- }
-#endif /* NO_LOCKING */
-#ifdef CANT_OPEN_FILES_TWICE
- if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0)))
- error = my_errno;
- if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
- error = my_errno;
- info->s->kfile=info->dfile= -1; /* Files aren't open anymore */
- break;
-#endif
- case HA_PANIC_READ: /* Restore to before WRITE */
-#ifdef CANT_OPEN_FILES_TWICE
- { /* Open closed files */
- char name_buff[FN_REFLEN];
- if (info->s->kfile < 0)
- if ((info->s->kfile= my_open(fn_format(name_buff,info->filename,"",
- N_NAME_IEXT,4),info->mode,
- MYF(MY_WME))) < 0)
- error = my_errno;
- if (info->dfile < 0)
- {
- if ((info->dfile= my_open(fn_format(name_buff,info->filename,"",
- N_NAME_DEXT,4),info->mode,
- MYF(MY_WME))) < 0)
- error = my_errno;
- info->rec_cache.file=info->dfile;
- }
- }
-#endif
-#ifndef NO_LOCKING
- if (info->was_locked)
- {
- if (nisam_lock_database(info, info->was_locked))
- error=my_errno;
- info->was_locked=0;
- }
-#else
- {
- int lock_type,w_locks;
- lock_type=info->lock_type ; w_locks=info->s->w_locks;
- info->lock_type=0; info->s->w_locks=0;
- if (_nisam_readinfo(info,0,1)) /* Read changed data */
- error=my_errno;
- info->lock_type=lock_type; info->s->w_locks=w_locks;
- }
- /* Don't use buffer when doing next */
- info->update|=HA_STATE_WRITTEN;
-#endif /* NO_LOCKING */
- break;
- }
- }
- if (flag == HA_PANIC_CLOSE)
- VOID(nisam_log(0)); /* Close log if neaded */
- pthread_mutex_unlock(&THR_LOCK_isam);
- if (!error) DBUG_RETURN(0);
- my_errno=error;
- DBUG_RETURN(-1);
-} /* nisam_panic */
diff --git a/isam/range.c b/isam/range.c
deleted file mode 100644
index 3b79b6d93a9..00000000000
--- a/isam/range.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Gives a approximated number of how many records there is between two keys.
- Used when optimizing querries.
- */
-
-#include "isamdef.h"
-
-static ulong _nisam_record_pos(N_INFO *info,const byte *key,uint key_len,
- enum ha_rkey_function search_flag);
-static double _nisam_search_pos(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- uint key_len,uint nextflag,ulong pos);
-static uint _nisam_keynr(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,
- uchar *keypos,uint *ret_max_key);
-
-
- /* If start_key = 0 assume read from start */
- /* If end_key = 0 assume read to end */
- /* Returns NI_POS_ERROR on error */
-
-ulong nisam_records_in_range(N_INFO *info, int inx, const byte *start_key,
- uint start_key_len,
- enum ha_rkey_function start_search_flag,
- const byte *end_key, uint end_key_len,
- enum ha_rkey_function end_search_flag)
-{
- ulong start_pos,end_pos;
- DBUG_ENTER("nisam_records_in_range");
-
- if ((inx = _nisam_check_index(info,inx)) < 0)
- DBUG_RETURN(NI_POS_ERROR);
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1))
- DBUG_RETURN(NI_POS_ERROR);
-#endif
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- start_pos= (start_key ?
- _nisam_record_pos(info,start_key,start_key_len,start_search_flag) :
- 0L);
- end_pos= (end_key ?
- _nisam_record_pos(info,end_key,end_key_len,end_search_flag) :
- info->s->state.records+1L);
- VOID(_nisam_writeinfo(info,0));
- if (start_pos == NI_POS_ERROR || end_pos == NI_POS_ERROR)
- DBUG_RETURN(NI_POS_ERROR);
- DBUG_PRINT("info",("records: %ld",end_pos-start_pos));
- DBUG_RETURN(end_pos < start_pos ? 0L :
- (end_pos == start_pos ? 1L : end_pos-start_pos));
-}
-
-
- /* Find relative position (in records) for key in index-tree */
-
-static ulong _nisam_record_pos(N_INFO *info, const byte *key, uint key_len,
- enum ha_rkey_function search_flag)
-{
- uint inx=(uint) info->lastinx;
- N_KEYDEF *keyinfo=info->s->keyinfo+inx;
- uchar *key_buff;
- double pos;
-
- DBUG_ENTER("_nisam_record_pos");
- DBUG_PRINT("enter",("search_flag: %d",search_flag));
-
- if (key_len >= (keyinfo->base.keylength-info->s->rec_reflength)
- && !(keyinfo->base.flag & HA_SPACE_PACK_USED))
- key_len=USE_HOLE_KEY;
- key_buff=info->lastkey+info->s->base.max_key_length;
- key_len=_nisam_pack_key(info,inx,key_buff,(uchar*) key,key_len);
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,
- (uchar*) key_buff););
- pos=_nisam_search_pos(info,keyinfo,key_buff,key_len,
- nisam_read_vec[search_flag] | SEARCH_SAVE_BUFF,
- info->s->state.key_root[inx]);
- if (pos >= 0.0)
- {
- DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->s->state.records)));
- DBUG_RETURN((ulong) (pos*info->s->state.records+0.5));
- }
- DBUG_RETURN(NI_POS_ERROR);
-}
-
-
- /* This is a modified version of _nisam_search */
- /* Returns offset for key in indextable (decimal 0.0 <= x <= 1.0) */
-
-static double _nisam_search_pos(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, uint key_len, uint nextflag,
- register ulong pos)
-{
- int flag;
- uint nod_flag,keynr,max_keynr;
- uchar *keypos,*buff;
- double offset;
- DBUG_ENTER("_nisam_search_pos");
-
- if (pos == NI_POS_ERROR)
- DBUG_RETURN(0.5);
-
- if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,1)))
- goto err;
- flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
- &keypos,info->lastkey);
- nod_flag=test_if_nod(buff);
- keynr=_nisam_keynr(info,keyinfo,buff,keypos,&max_keynr);
-
- if (flag)
- {
- /*
- ** Didn't found match. keypos points at next (bigger) key
- * Try to find a smaller, better matching key.
- ** Matches keynr + [0-1]
- */
- if ((offset=_nisam_search_pos(info,keyinfo,key,key_len,nextflag,
- _nisam_kpos(nod_flag,keypos))) < 0)
- DBUG_RETURN(offset);
- }
- else
- {
- /*
- ** Found match. Keypos points at the start of the found key
- ** Matches keynr+1
- */
- offset=1.0; /* Matches keynr+1 */
- if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME)
- || key_len) && nod_flag)
- {
- /*
- ** There may be identical keys in the tree. Try to match on of those.
- ** Matches keynr + [0-1]
- */
- if ((offset=_nisam_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
- _nisam_kpos(nod_flag,keypos))) < 0)
- DBUG_RETURN(offset); /* Read error */
- }
- }
- DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d",
- keynr,offset,max_keynr,nod_flag,flag));
- DBUG_RETURN((keynr+offset)/(max_keynr+1));
-err:
- DBUG_PRINT("exit",("Error: %d",my_errno));
- DBUG_RETURN (-1.0);
-}
-
-
- /* Get keynummer of current key and max number of keys in nod */
-
-static uint _nisam_keynr(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *keypos, uint *ret_max_key)
-{
- uint nod_flag,keynr,max_key;
- uchar t_buff[N_MAX_KEY_BUFF],*end;
-
- end= page+getint(page);
- nod_flag=test_if_nod(page);
- page+=2+nod_flag;
-
- if (!(keyinfo->base.flag &
- (HA_PACK_KEY | HA_SPACE_PACK | HA_SPACE_PACK_USED)))
- {
- *ret_max_key= (uint) (end-page)/(keyinfo->base.keylength+nod_flag);
- return (uint) (keypos-page)/(keyinfo->base.keylength+nod_flag);
- }
-
- max_key=keynr=0;
- while (page < end)
- {
- t_buff[0]=0; /* Don't move packed key */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff));
- max_key++;
- if (page == keypos)
- keynr=max_key;
- }
- *ret_max_key=max_key;
- return(keynr);
-}
diff --git a/isam/rfirst.c b/isam/rfirst.c
deleted file mode 100644
index cc1cbee92bf..00000000000
--- a/isam/rfirst.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser f|rsta posten som har samma isam-nyckel */
-
-#include "isamdef.h"
-
- /*
- L{ser f|rsta posten med samma isamnyckel som f|reg}ende l{sning.
- Man kan ha gjort write, update eller delete p} f|reg}ende post.
- OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
- posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
- */
-
-int nisam_rfirst(N_INFO *info, byte *buf, int inx)
-{
- DBUG_ENTER("nisam_rfirst");
- info->lastpos= NI_POS_ERROR;
- info->update|= HA_STATE_PREV_FOUND;
- DBUG_RETURN(nisam_rnext(info,buf,inx));
-} /* nisam_rfirst */
diff --git a/isam/rkey.c b/isam/rkey.c
deleted file mode 100644
index bbe4576418b..00000000000
--- a/isam/rkey.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser p} basen av en isam_nyckel */
-
-#include "isamdef.h"
-
-
- /* Read a record using key */
- /* Ordinary search_flag is 0 ; Give error if no record with key */
-
-int nisam_rkey(N_INFO *info, byte *buf, int inx, const byte *key, uint key_len, enum ha_rkey_function search_flag)
-{
- uchar *key_buff;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("nisam_rkey");
- DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d",
- info,inx,search_flag));
-
- if ((inx = _nisam_check_index(info,inx)) < 0)
- DBUG_RETURN(-1);
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- if (key_len >= (share->keyinfo[inx].base.keylength - share->rec_reflength)
- && !(info->s->keyinfo[inx].base.flag & HA_SPACE_PACK_USED))
- key_len=USE_HOLE_KEY;
- key_buff=info->lastkey+info->s->base.max_key_length;
- key_len=_nisam_pack_key(info,(uint) inx,key_buff,(uchar*) key,key_len);
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,share->keyinfo[inx].seg,
- (uchar*) key););
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1))
- goto err;
-#endif
-
- VOID(_nisam_search(info,info->s->keyinfo+inx,key_buff,key_len,
- nisam_read_vec[search_flag],info->s->state.key_root[inx]));
- if ((*info->read_record)(info,info->lastpos,buf) >= 0)
- {
- info->update|= HA_STATE_AKTIV; /* Record is read */
- DBUG_RETURN(0);
- }
-
- info->lastpos = NI_POS_ERROR; /* Didn't find key */
- VOID(_nisam_move_key(info->s->keyinfo+inx,info->lastkey,key_buff));
- if (search_flag == HA_READ_AFTER_KEY)
- info->update|=HA_STATE_NEXT_FOUND; /* Previous gives last row */
-err:
- DBUG_RETURN(-1);
-} /* nisam_rkey */
diff --git a/isam/rlast.c b/isam/rlast.c
deleted file mode 100644
index a91f1f1011b..00000000000
--- a/isam/rlast.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser sista posten som har samma isam-nyckel */
-
-#include "isamdef.h"
-
- /*
- L{ser sista posten med samma isamnyckel som f|reg}ende l{sning.
- Man kan ha gjort write, update eller delete p} f|reg}ende post.
- OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
- posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
- */
-
-int nisam_rlast(N_INFO *info, byte *buf, int inx)
-{
- DBUG_ENTER("nisam_rlast");
- info->lastpos= NI_POS_ERROR;
- info->update|= HA_STATE_NEXT_FOUND;
- DBUG_RETURN(nisam_rprev(info,buf,inx));
-} /* nisam_rlast */
diff --git a/isam/rnext.c b/isam/rnext.c
deleted file mode 100644
index be26098c901..00000000000
--- a/isam/rnext.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser n{sta post med samma isam-nyckel */
-
-#include "isamdef.h"
-
- /*
- L{ser n{sta post med samma isamnyckel som f|reg}ende l{sning.
- Man kan ha gjort write, update eller delete p} f|reg}ende post.
- OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
- posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
- */
-
-int nisam_rnext(N_INFO *info, byte *buf, int inx)
-{
- int error,changed;
- uint flag;
- DBUG_ENTER("nisam_rnext");
-
- if ((inx = _nisam_check_index(info,inx)) < 0)
- DBUG_RETURN(-1);
- flag=SEARCH_BIGGER; /* Read next */
- if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_PREV_FOUND)
- flag=0; /* Read first */
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
-#endif
- changed=_nisam_test_if_changed(info);
- if (!flag)
- error=_nisam_search_first(info,info->s->keyinfo+inx,
- info->s->state.key_root[inx]);
- else if (!changed)
- error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag,
- info->s->state.key_root[inx]);
- else
- error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag,
- info->s->state.key_root[inx]);
-
- /* Don't clear if database-changed */
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |
- HA_STATE_BUFF_SAVED);
- info->update|= HA_STATE_NEXT_FOUND;
-
- if (error && my_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_END_OF_FILE;
- if ((*info->read_record)(info,info->lastpos,buf) >=0)
- {
- info->update|= HA_STATE_AKTIV; /* Record is read */
- DBUG_RETURN(0);
- }
- DBUG_RETURN(-1);
-} /* nisam_rnext */
diff --git a/isam/rprev.c b/isam/rprev.c
deleted file mode 100644
index 0997a04fbbe..00000000000
--- a/isam/rprev.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser f|reg}ende post med samma isam-nyckel */
-
-#include "isamdef.h"
-
- /*
- L{ser f|reg}ende post med samma isamnyckel som f|reg}ende l{sning.
- Man kan ha gjort write, update eller delete p} f|reg}ende post.
- OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
- posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
- */
-
-int nisam_rprev(N_INFO *info, byte *buf, int inx)
-{
- int error,changed;
- register uint flag;
- DBUG_ENTER("nisam_rprev");
-
- if ((inx = _nisam_check_index(info,inx)) < 0)
- DBUG_RETURN(-1);
- flag=SEARCH_SMALLER; /* Read previous */
- if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_NEXT_FOUND)
- flag=0; /* Read last */
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
-#endif
- changed=_nisam_test_if_changed(info);
- if (!flag)
- error=_nisam_search_last(info,info->s->keyinfo+inx,info->s->state.key_root[inx]);
- else if (!changed)
- error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag,
- info->s->state.key_root[inx]);
- else
- error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag,
- info->s->state.key_root[inx]);
-
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |
- HA_STATE_BUFF_SAVED);
- info->update|= HA_STATE_PREV_FOUND;
- if (error && my_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_END_OF_FILE;
- if ((*info->read_record)(info,info->lastpos,buf) >=0)
- {
- info->update|= HA_STATE_AKTIV; /* Record is read */
- DBUG_RETURN(0);
- }
- DBUG_RETURN(-1);
-} /* nisam_rprev */
diff --git a/isam/rrnd.c b/isam/rrnd.c
deleted file mode 100644
index 16b3ab1b859..00000000000
--- a/isam/rrnd.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Read a record with random-access. The position to the record must
- get by N_INFO. The next record can be read with pos= -1 */
-
-
-#include "isamdef.h"
-
-/*
- If filepos == NI_POS_ERROR, read next
- Returns:
- 0 = Ok.
- 1 = Row was deleted
- -1 = EOF (check errno to verify)
-*/
-
-int nisam_rrnd(N_INFO *info, byte *buf, register ulong filepos)
-{
- int skipp_deleted_blocks;
- DBUG_ENTER("nisam_rrnd");
-
- skipp_deleted_blocks=0;
-
- if (filepos == NI_POS_ERROR)
- {
- skipp_deleted_blocks=1;
- if (info->lastpos == NI_POS_ERROR) /* First read ? */
- filepos= info->s->pack.header_length; /* Read first record */
- else
- filepos= info->nextpos;
- }
-
- info->lastinx= -1; /* Can't forward or backward */
- /* Init all but update-flag */
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
-
- if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
- DBUG_RETURN(my_errno);
-
- DBUG_RETURN ((*info->s->read_rnd)(info,buf,filepos,skipp_deleted_blocks));
-}
diff --git a/isam/rsame.c b/isam/rsame.c
deleted file mode 100644
index 9a2a03da054..00000000000
--- a/isam/rsame.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser nuvarande record med direktl{sning */
-/* Klarar b}de poster l{sta med nyckel och rrnd. */
-
-#include "isamdef.h"
-
- /* Funktionen ger som resultat:
- 0 = Ok.
- 1 = Posten borttagen
- -1 = EOF (eller motsvarande: se errno) */
-
-
-int nisam_rsame(N_INFO *info, byte *record, int inx)
-
-
- /* If inx >= 0 find record using key */
-{
- DBUG_ENTER("nisam_rsame");
-
- if (inx >= (int) info->s->state.keys || inx < -1)
- {
- my_errno=HA_ERR_WRONG_INDEX;
- DBUG_RETURN(-1);
- }
- if (info->lastpos == NI_POS_ERROR || info->update & HA_STATE_DELETED)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* No current record */
- DBUG_RETURN(-1);
- }
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
-
- /* L{s record fr}n datafilen */
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1))
- DBUG_RETURN(-1);
-#endif
-
- if (inx >= 0)
- {
- info->lastinx=inx;
- VOID(_nisam_make_key(info,(uint) inx,info->lastkey,record,info->lastpos));
- VOID(_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,SEARCH_SAME,
- info->s->state.key_root[inx]));
- }
-
- if ((*info->read_record)(info,info->lastpos,record) == 0)
- DBUG_RETURN(0);
- if (my_errno == HA_ERR_RECORD_DELETED)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND;
- DBUG_RETURN(1);
- }
- DBUG_RETURN(-1);
-} /* nisam_rsame */
diff --git a/isam/rsamepos.c b/isam/rsamepos.c
deleted file mode 100644
index c64ac492d1a..00000000000
--- a/isam/rsamepos.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* read record through position and fix key-position */
-/* As nisam_rsame but supply a position */
-
-#include "isamdef.h"
-
-
- /*
- ** If inx >= 0 update index pointer
- ** Returns one of the following values:
- ** 0 = Ok.
- ** 1 = Record deleted
- ** -1 = EOF (or something similar. More information in my_errno)
- */
-
-int nisam_rsame_with_pos(N_INFO *info, byte *record, int inx, ulong filepos)
-{
- DBUG_ENTER("nisam_rsame_with_pos");
-
- if (inx >= (int) info->s->state.keys || inx < -1)
- {
- my_errno=HA_ERR_WRONG_INDEX;
- DBUG_RETURN(-1);
- }
-
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- if ((*info->s->read_rnd)(info,record,filepos,0))
- {
- if (my_errno == HA_ERR_RECORD_DELETED)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND;
- DBUG_RETURN(1);
- }
- DBUG_RETURN(-1);
- }
- info->lastpos=filepos;
- info->lastinx=inx;
- if (inx >= 0)
- {
- VOID(_nisam_make_key(info,(uint) inx,info->lastkey,record,info->lastpos));
- info->update|=HA_STATE_KEY_CHANGED; /* Don't use indexposition */
- }
- DBUG_RETURN(0);
-} /* nisam_rsame_pos */
diff --git a/isam/sort.c b/isam/sort.c
deleted file mode 100644
index 5d13f8085d2..00000000000
--- a/isam/sort.c
+++ /dev/null
@@ -1,561 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Creates a index for a database by reading keys, sorting them and outputing
- them in sorted order through SORT_INFO functions.
-*/
-
-#include "isamdef.h"
-#if defined(MSDOS) || defined(__WIN__)
-#include <fcntl.h>
-#else
-#include <stddef.h>
-#endif
-#include <queues.h>
-
- /* static variabels */
-
-#define MERGEBUFF 15
-#define MERGEBUFF2 31
-#define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD)
-#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
-
-typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
- my_off_t file_pos; /* Position var bufferten finns */
- ulong count; /* Antal nycklar i bufferten */
- uchar *base,*key; /* Pekare inom sort_key - indexdel */
- uint mem_count; /* Antal nycklar kvar i minnet */
- uint max_keys; /* Max keys in buffert */
-} BUFFPEK;
-
-extern void print_error _VARARGS((const char *fmt,...));
-
- /* functions defined in this file */
-
-static ulong NEAR_F find_all_keys(SORT_PARAM *info,uint keys,
- uchar * *sort_keys,
- BUFFPEK *buffpek,int *maxbuffer,
- FILE **tempfile, my_string tempname);
-static int NEAR_F write_keys(SORT_PARAM *info,uchar * *sort_keys,
- uint count, BUFFPEK *buffpek,FILE **tempfile,
- my_string tempname);
-static int NEAR_F write_index(SORT_PARAM *info,uchar * *sort_keys,
- uint count);
-static int NEAR_F merge_many_buff(SORT_PARAM *info,uint keys,
- uchar * *sort_keys,
- BUFFPEK *buffpek,int *maxbuffer,
- FILE * *t_file, my_string tempname);
-static uint NEAR_F read_to_buffer(FILE *fromfile,BUFFPEK *buffpek,
- uint sort_length);
-static int NEAR_F merge_buffers(SORT_PARAM *info,uint keys,FILE *from_file,
- FILE *to_file, uchar * *sort_keys,
- BUFFPEK *lastbuff,BUFFPEK *Fb,
- BUFFPEK *Tb);
-static int NEAR_F merge_index(SORT_PARAM *,uint,uchar **,BUFFPEK *, int,
- FILE *);
-static char **make_char_array(uint fields,uint length,myf my_flag);
-static FILE *opentemp(my_string name);
-static void closetemp(char *name,FILE *stream);
-
-
- /* Creates a index of sorted keys */
- /* Returns 0 if everything went ok */
-
-int _create_index_by_sort(info,no_messages,sortbuff_size)
-SORT_PARAM *info;
-pbool no_messages;
-uint sortbuff_size;
-{
- int error,maxbuffer,skr;
- uint memavl,old_memavl,keys,sort_length;
- BUFFPEK *buffpek;
- char tempname[FN_REFLEN];
- ulong records;
- uchar **sort_keys;
- FILE *tempfile;
- DBUG_ENTER("_create_index_by_sort");
-
- tempfile=0; buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1;
- maxbuffer=1;
-
- memavl=max(sortbuff_size,MIN_SORT_MEMORY);
- records= info->max_records;
- sort_length= info->key_length;
- LINT_INIT(keys);
-
- while (memavl >= MIN_SORT_MEMORY)
- {
- if ((records+1)*(sort_length+sizeof(char*)) < (ulong) memavl)
- keys= records+1;
- else
- do
- {
- skr=maxbuffer;
- if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer ||
- (keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/
- (sort_length+sizeof(char*))) <= 1)
- {
- print_error("Sortbuffer to small");
- goto err;
- }
- }
- while ((maxbuffer= (int) (records/(keys-1)+1)) != skr);
-
- if ((sort_keys= (uchar **) make_char_array(keys,sort_length,MYF(0))))
- {
- if ((buffpek = (BUFFPEK*) my_malloc((uint) (sizeof(BUFFPEK)*
- (uint) maxbuffer),
- MYF(0))))
- break;
- else
- {
- my_free((gptr) sort_keys,MYF(0));
- sort_keys= 0;
- }
- }
- old_memavl=memavl;
- if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY)
- memavl=MIN_SORT_MEMORY;
- }
- if (memavl < MIN_SORT_MEMORY)
- {
- print_error("Sortbuffer to small");
- goto err;
- }
- (*info->lock_in_memory)(); /* Everything is allocated */
-
- if (!no_messages)
- printf(" - Searching for keys, allocating buffer for %d keys\n",keys);
-
- if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile,
- tempname))
- == (ulong) -1)
- goto err;
- if (maxbuffer == 0)
- {
- if (!no_messages)
- printf(" - Dumping %lu keys\n",records);
- if (write_index(info,sort_keys,(uint) records))
- goto err;
- }
- else
- {
- keys=(keys*(sort_length+sizeof(char*)))/sort_length;
- if (maxbuffer >= MERGEBUFF2)
- {
- if (!no_messages)
- printf(" - Merging %lu keys\n",records);
- if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile,
- tempname))
- goto err;
- }
- if (!no_messages)
- puts(" - Last merge and dumping keys");
- if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile))
- goto err;
- }
- error =0;
-
-err:
- if (sort_keys)
- my_free((gptr) sort_keys,MYF(0));
- if (buffpek)
- my_free((gptr) buffpek,MYF(0));
- if (tempfile)
- closetemp(tempname,tempfile);
-
- DBUG_RETURN(error ? -1 : 0);
-} /* _create_index_by_sort */
-
-
- /* Search after all keys and place them in a temp. file */
-
-static ulong NEAR_F find_all_keys(info,keys,sort_keys,buffpek,maxbuffer,
- tempfile,tempname)
-SORT_PARAM *info;
-uint keys;
-uchar **sort_keys;
-BUFFPEK *buffpek;
-int *maxbuffer;
-FILE **tempfile;
-my_string tempname;
-{
- int error;
- uint index,indexpos;
- DBUG_ENTER("find_all_keys");
-
- index=indexpos=error=0;
-
- while (!(error=(*info->key_read)(sort_keys[index])))
- {
- if ((uint) ++index == keys)
- {
- if (indexpos >= (uint) *maxbuffer ||
- write_keys(info,sort_keys,index-1,buffpek+indexpos,tempfile,
- tempname))
- DBUG_RETURN(NI_POS_ERROR);
- memcpy(sort_keys[0],sort_keys[index-1],(size_t) info->key_length);
- index=1; indexpos++;
- }
- }
- if (error > 0)
- DBUG_RETURN(NI_POS_ERROR); /* Aborted by get_key */
- if (indexpos)
- if (indexpos >= (uint) *maxbuffer ||
- write_keys(info,sort_keys,index,buffpek+indexpos,tempfile,tempname))
- DBUG_RETURN(NI_POS_ERROR);
- *maxbuffer=(int) indexpos;
- DBUG_RETURN(indexpos*(keys-1)+index);
-} /* find_all_keys */
-
-
- /* Write all keys in memory to file for later merge */
-
-static int NEAR_F write_keys(info,sort_keys,count,buffpek,tempfile,tempname)
-SORT_PARAM *info;
-reg1 uchar **sort_keys;
-uint count;
-BUFFPEK *buffpek;
-reg2 FILE **tempfile;
-my_string tempname;
-{
- DBUG_ENTER("write_keys");
-
- qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp,
- NullS);
- if (! *tempfile && ! (*tempfile=opentemp(tempname)))
- DBUG_RETURN(1);
- buffpek->file_pos=my_ftell(*tempfile,MYF(0));
- buffpek->count=count;
- while (count--)
- if (my_fwrite(*tempfile,(byte*)*sort_keys++,info->key_length,MYF_RW))
- DBUG_RETURN(1);
- DBUG_RETURN(0);
-} /* write_keys */
-
-
- /* Write index */
-
-static int NEAR_F write_index(info,sort_keys,count)
-SORT_PARAM *info;
-reg1 uchar **sort_keys;
-reg2 uint count;
-{
- DBUG_ENTER("write_index");
-
- qsort2((gptr) sort_keys,(size_t) count,sizeof(byte*),
- (qsort2_cmp) info->key_cmp, NullS);
- while (count--)
- if ((*info->key_write)(*sort_keys++))
- DBUG_RETURN(-1);
- DBUG_RETURN(0);
-} /* write_index */
-
-
- /* Merge buffers to make < MERGEBUFF2 buffers */
-
-static int NEAR_F merge_many_buff(info,keys,sort_keys,buffpek,maxbuffer,t_file,
- t_name)
-SORT_PARAM *info;
-uint keys;
-uchar **sort_keys;
-int *maxbuffer;
-BUFFPEK *buffpek;
-FILE **t_file;
-my_string t_name;
-{
- register int i;
- FILE *from_file,*to_file,*temp;
- FILE *t_file2;
- char t_name2[FN_REFLEN];
- BUFFPEK *lastbuff;
- DBUG_ENTER("merge_many_buff");
-
- if (!(t_file2=opentemp(t_name2)))
- DBUG_RETURN(1);
-
- from_file= *t_file ; to_file= t_file2;
- while (*maxbuffer >= MERGEBUFF2)
- {
- lastbuff=buffpek;
- for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
- {
- if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
- buffpek+i,buffpek+i+MERGEBUFF-1))
- break;
- }
- if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
- buffpek+i,buffpek+ *maxbuffer))
- break;
- *maxbuffer= (int) (lastbuff-buffpek)-1;
- temp=from_file; from_file=to_file; to_file=temp;
- VOID(my_fseek(to_file,0L,MY_SEEK_SET,MYF(0)));
- }
- if (to_file == *t_file)
- {
- closetemp(t_name,to_file);
- *t_file=t_file2;
- VOID(strmov(t_name,t_name2));
- }
- else closetemp(t_name2,to_file);
-
- DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
-} /* merge_many_buff */
-
-
- /* Read data to buffer */
- /* This returns (uint) -1 if something goes wrong */
-
-static uint NEAR_F read_to_buffer(fromfile,buffpek,sort_length)
-FILE *fromfile;
-BUFFPEK *buffpek;
-uint sort_length;
-{
- register uint count;
- uint length;
-
- if ((count=(uint) min((ulong) buffpek->max_keys,buffpek->count)))
- {
- VOID(my_fseek(fromfile,buffpek->file_pos,MY_SEEK_SET,MYF(0)));
- if (my_fread(fromfile,(byte*) buffpek->base,
- (length= sort_length*count),MYF_RW))
- return((uint) -1);
- buffpek->key=buffpek->base;
- buffpek->file_pos+= length; /* New filepos */
- buffpek->count-= count;
- buffpek->mem_count= count;
- }
- return (count*sort_length);
-} /* read_to_buffer */
-
-
- /* Merge buffers to one buffer */
- /* If to_file == 0 then use info->key_write */
-
-static int NEAR_F merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff,
- Fb,Tb)
-SORT_PARAM *info;
-uint keys;
-FILE *from_file,*to_file;
-uchar **sort_keys;
-BUFFPEK *lastbuff,*Fb,*Tb;
-{
- int error;
- uint sort_length,maxcount;
- ulong count;
- my_off_t to_start_filepos;
- uchar *strpos;
- BUFFPEK *buffpek,**refpek;
- QUEUE queue;
- DBUG_ENTER("merge_buffers");
-
- count=error=0;
- maxcount=keys/((uint) (Tb-Fb) +1);
- sort_length=info->key_length;
-
- LINT_INIT(to_start_filepos);
- if (to_file)
- to_start_filepos=my_ftell(to_file,MYF(0));
- strpos=(uchar*) sort_keys;
-
- if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
- (int (*)(void *, byte *,byte *)) info->key_cmp,0))
- DBUG_RETURN(1);
-
- for (buffpek= Fb ; buffpek <= Tb && error != -1 ; buffpek++)
- {
- count+= buffpek->count;
- buffpek->base= strpos;
- buffpek->max_keys=maxcount;
- strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek,
- sort_length));
- queue_insert(&queue,(void*) buffpek);
- }
- if (error == -1)
- goto err;
-
- while (queue.elements > 1)
- {
- for (;;)
- {
- buffpek=(BUFFPEK*) queue_top(&queue);
- if (to_file)
- {
- if (my_fwrite(to_file,(byte*) buffpek->key,(uint) sort_length,
- MYF_RW | MY_WAIT_IF_FULL))
- {
- error=1; goto err;
- }
- }
- else
- {
- if ((*info->key_write)((void*) buffpek->key))
- {
- error=1; goto err;
- }
- }
- buffpek->key+=sort_length;
- if (! --buffpek->mem_count)
- {
- if (!(error=(int) read_to_buffer(from_file,buffpek,sort_length)))
- {
- uchar *base=buffpek->base;
- uint max_keys=buffpek->max_keys;
-
- VOID(queue_remove(&queue,0));
-
- /* Put room used by buffer to use in other buffer */
- for (refpek= (BUFFPEK**) &queue_top(&queue);
- refpek <= (BUFFPEK**) &queue_end(&queue);
- refpek++)
- {
- buffpek= *refpek;
- if (buffpek->base+buffpek->max_keys*sort_length == base)
- {
- buffpek->max_keys+=max_keys;
- break;
- }
- else if (base+max_keys*sort_length == buffpek->base)
- {
- buffpek->base=base;
- buffpek->max_keys+=max_keys;
- break;
- }
- }
- break; /* One buffer have been removed */
- }
- }
- queue_replaced(&queue); /* Top element has been replaced */
- }
- }
- buffpek=(BUFFPEK*) queue_top(&queue);
- buffpek->base=(uchar *) sort_keys;
- buffpek->max_keys=keys;
- do
- {
- if (to_file)
- {
- if (my_fwrite(to_file,(byte*) buffpek->key,
- (uint) (sort_length*buffpek->mem_count),
- MYF_RW | MY_WAIT_IF_FULL))
- {
- error=1; goto err;
- }
- }
- else
- {
- register uchar *end;
- strpos= buffpek->key;
- for (end=strpos+buffpek->mem_count*sort_length;
- strpos != end ;
- strpos+=sort_length)
- {
- if ((*info->key_write)((void*) strpos))
- {
- error=1; goto err;
- }
- }
- }
- }
- while ((error=(int) read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
- error != 0);
-
- lastbuff->count=count;
- if (to_file)
- lastbuff->file_pos=to_start_filepos; /* New block starts here */
-err:
- delete_queue(&queue);
- DBUG_RETURN(error);
-} /* merge_buffers */
-
-
- /* Do a merge to output-file (save only positions) */
-
-static int NEAR_F merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile)
-SORT_PARAM *info;
-uint keys;
-uchar **sort_keys;
-BUFFPEK *buffpek;
-int maxbuffer;
-FILE *tempfile;
-{
- DBUG_ENTER("merge_index");
- if (merge_buffers(info,keys,tempfile,(FILE*) 0,sort_keys,buffpek,buffpek,
- buffpek+maxbuffer))
- DBUG_RETURN(1);
- DBUG_RETURN(0);
-} /* merge_index */
-
-
- /* Make a pointer of arrays to keys */
-
-static char **make_char_array(fields,length,my_flag)
-register uint fields;
-uint length;
-myf my_flag;
-{
- register char **pos;
- char **old_pos,*char_pos;
- DBUG_ENTER("make_char_array");
-
- if ((old_pos= (char**) my_malloc( fields*(length+sizeof(char*)), my_flag)))
- {
- pos=old_pos; char_pos=((char*) (pos+fields)) -length;
- while (fields--)
- *(pos++) = (char_pos+= length);
- }
-
- DBUG_RETURN(old_pos);
-} /* make_char_array */
-
-
- /* |ppnar en tempor{rfil som kommer att raderas efter anv{nding */
-
-static FILE *opentemp(name)
-my_string name;
-{
- FILE *stream;
- reg1 my_string str_pos;
- DBUG_ENTER("opentemp");
-
- if (!(str_pos=my_tempnam(NullS,"ST",MYF(MY_WME))))
- DBUG_RETURN(0);
- VOID(strmov(name,str_pos));
- (*free)(str_pos); /* Inte via vanliga malloc */
-
- stream=my_fopen(name,(int) (O_RDWR | FILE_BINARY | O_CREAT | O_TEMPORARY),
- MYF(MY_WME));
-#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES)
- VOID(my_delete(name,MYF(MY_WME | ME_NOINPUT)));
-#endif
- DBUG_PRINT("exit",("stream: %lx",stream));
- DBUG_RETURN (stream);
-} /* opentemp */
-
-
-static void closetemp(char *name __attribute__((unused)) ,FILE *stream)
-{
- DBUG_ENTER("closetemp");
-
- if (stream)
- VOID(my_fclose(stream,MYF(MY_WME)));
-#ifdef CANT_DELETE_OPEN_FILES
- if (name)
- VOID(my_delete(name,MYF(MY_WME)));
-#endif
- DBUG_VOID_RETURN;
-} /* closetemp */
diff --git a/isam/static.c b/isam/static.c
deleted file mode 100644
index 0a8dc809ad7..00000000000
--- a/isam/static.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Static variables for ISAM library. All definied here for easy making of
- a shared library
-*/
-
-#ifndef _global_h
-#include "isamdef.h"
-#endif
-
-LIST *nisam_open_list=0;
-uchar NEAR nisam_file_magic[]=
-{ (uchar) 254, (uchar) 254,'\005', '\002', };
-uchar NEAR nisam_pack_file_magic[]=
-{ (uchar) 254, (uchar) 254,'\006', '\001', };
-my_string nisam_log_filename= (char*) "isam.log";
-File nisam_log_file= -1;
-uint nisam_quick_table_bits=9;
-uint nisam_block_size=1024; /* Best by test */
-my_bool nisam_flush=0;
-
-/* read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ */
-/* Position is , == , >= , <= , > , < */
-
-uint NEAR nisam_read_vec[]=
-{
- SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER,
- SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER,
- SEARCH_FIND, SEARCH_LAST,SEARCH_LAST | SEARCH_SMALLER
-};
diff --git a/isam/test1.c b/isam/test1.c
deleted file mode 100644
index b9f4d8242c3..00000000000
--- a/isam/test1.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "isamdef.h"
-
-static void get_options(int argc, char *argv[]);
-
-static int rec_pointer_size=0,verbose=0,remove_ant=0,pack_keys=1,flags[50],
- packed_field=FIELD_SKIP_PRESPACE;
-
-int main(int argc, char *argv[])
-{
- N_INFO *file;
- int i,j,error,deleted,found;
- char record[128],key[32],*filename,read_record[128];
- N_KEYDEF keyinfo[10];
- N_RECINFO recinfo[10];
- MY_INIT(argv[0]);
-
- filename= (char*) "test1";
- my_init();
- get_options(argc,argv);
- keyinfo[0].seg[0].base.type=HA_KEYTYPE_NUM;
- keyinfo[0].seg[0].base.flag=(uint8) (pack_keys ?
- HA_PACK_KEY | HA_SPACE_PACK : 0);
- keyinfo[0].seg[0].base.start=0;
- keyinfo[0].seg[0].base.length=6;
- keyinfo[0].seg[1].base.type=HA_KEYTYPE_END;
- keyinfo[0].base.flag = (uint8) (pack_keys ?
- HA_NOSAME | HA_PACK_KEY : HA_NOSAME);
-
- recinfo[0].base.type=packed_field; recinfo[0].base.length=6;
- recinfo[1].base.type=FIELD_NORMAL; recinfo[1].base.length=24;
- recinfo[2].base.type=FIELD_LAST;
-
- deleted=0;
- bzero((byte*) flags,sizeof(flags));
-
- printf("- Creating isam-file\n");
- if (nisam_create(filename,1,keyinfo,recinfo,
- (ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/40 :
- 0),10l,0,0,0L))
- goto err;
- if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
- goto err;
- printf("- Writing key:s\n");
- strmov(record," ..... key"); strappend(record,30,' ');
-
- my_errno=0;
- for (i=49 ; i>=1 ; i-=2 )
- {
- j=i%25 +1;
- sprintf(key,"%6d",j);
- bmove(record,key,6);
- error=nisam_write(file,record);
- flags[j]=1;
- if (verbose || error)
- printf("J= %2d nisam_write: %d errno: %d\n", j,error,my_errno);
- }
- if (nisam_close(file)) goto err;
- printf("- Reopening file\n");
- if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) goto err;
- printf("- Removing keys\n");
- for (i=1 ; i<=10 ; i++)
- {
- if (i == remove_ant) { VOID(nisam_close(file)) ; exit(0) ; }
- sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25)));
- my_errno=0;
- if ((error = nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)))
- {
- if (verbose || (flags[j] == 1 ||
- (error && my_errno != HA_ERR_KEY_NOT_FOUND)))
- printf("key: %s nisam_rkey: %3d errno: %3d\n",key,error,my_errno);
- }
- else
- {
- error=nisam_delete(file,read_record);
- if (verbose || error)
- printf("key: %s nisam_delete: %3d errno: %3d\n",key,error,my_errno);
- flags[j]=0;
- if (! error)
- deleted++;
- }
- }
- printf("- Reading records with key\n");
- for (i=1 ; i<=25 ; i++)
- {
- sprintf(key,"%6d",i);
- bmove(record,key,6);
- my_errno=0;
- error=nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT);
- if (verbose ||
- (error == 0 && flags[i] != 1) ||
- (error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
- {
- printf("key: %s nisam_rkey: %3d errno: %3d record: %s\n",
- key,error,my_errno,record+1);
- }
- }
-
- printf("- Reading records with position\n");
- for (i=1,found=0 ; i <= 30 ; i++)
- {
- my_errno=0;
- if ((error=nisam_rrnd(file,read_record,i == 1 ? 0L : NI_POS_ERROR)) == -1)
- {
- if (found != 25-deleted)
- printf("Found only %d of %d records\n",found,25-deleted);
- break;
- }
- if (!error)
- found++;
- if (verbose || (error != 0 && error != 1))
- {
- printf("pos: %2d nisam_rrnd: %3d errno: %3d record: %s\n",
- i-1,error,my_errno,read_record+1);
- }
- }
- if (nisam_close(file)) goto err;
- my_end(MY_CHECK_ERROR);
-
- exit(0);
-err:
- printf("got error: %3d when using nisam-database\n",my_errno);
- exit(1);
- return 0; /* skip warning */
-} /* main */
-
-
- /* l{ser optioner */
- /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
-
-static void get_options(int argc, char *argv[])
-{
- char *pos;
-
- while (--argc >0 && *(pos = *(++argv)) == '-' ) {
- switch(*++pos) {
- case 'R': /* Length of record pointer */
- rec_pointer_size=atoi(++pos);
- if (rec_pointer_size > 3)
- rec_pointer_size=0;
- break;
- case 'P':
- pack_keys=0; /* Don't use packed key */
- break;
- case 'S':
- packed_field=FIELD_NORMAL; /* static-size record*/
- break;
- case 'v': /* verbose */
- verbose=1;
- break;
- case 'm':
- remove_ant=atoi(++pos);
- break;
- case 'V':
- printf("isamtest1 Ver 1.0 \n");
- exit(0);
- case '#':
- DEBUGGER_ON;
- DBUG_PUSH (++pos);
- break;
- }
- }
- return;
-} /* get options */
diff --git a/isam/test2.c b/isam/test2.c
deleted file mode 100644
index 4b22f2d679c..00000000000
--- a/isam/test2.c
+++ /dev/null
@@ -1,841 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Test av isam-databas: stor test */
-
-#ifndef USE_MY_FUNC /* We want to be able to dbug this !! */
-#define USE_MY_FUNC
-#endif
-#ifdef DBUG_OFF
-#undef DBUG_OFF
-#endif
-#ifndef SAFEMALLOC
-#define SAFEMALLOC
-#endif
-
-#include "isamdef.h"
-
-#define STANDAR_LENGTH 37
-#define NISAM_KEYS 6
-#if !defined(MSDOS) && !defined(labs)
-#define labs(a) abs(a)
-#endif
-
-static void get_options(int argc, char *argv[]);
-static uint rnd(uint max_value);
-static void fix_length(byte *record,uint length);
-static void put_blob_in_record(char *blob_pos,char **blob_buffer);
-static void copy_key(struct st_isam_info *info,uint inx,
- uchar *record,uchar *key);
-
-static int verbose=0,testflag=0,pack_type=HA_SPACE_PACK,
- first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0,
- rec_pointer_size=0,pack_fields=1,use_log=0;
-static uint keys=NISAM_KEYS,recant=1000;
-static uint use_blob=0;
-static uint16 key1[1000],key3[5000];
-static char record[300],record2[300],key[100],key2[100],
- read_record[300],read_record2[300],read_record3[300];
-
-
- /* Test program */
-
-int main(int argc, char *argv[])
-{
- uint i;
- int j,n1,n2,n3,error,k;
- uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos,
- reclength,ant;
- ulong lastpos,range_records,records;
- N_INFO *file;
- N_KEYDEF keyinfo[10];
- N_RECINFO recinfo[10];
- N_ISAMINFO info;
- char *filename,*blob_buffer;
- MY_INIT(argv[0]);
-
- filename= (char*) "test2.ISM";
- get_options(argc,argv);
- if (! async_io)
- my_disable_async_io=1;
-
- reclength=STANDAR_LENGTH+60+(use_blob ? 8 : 0);
- blob_pos=STANDAR_LENGTH+60;
- keyinfo[0].seg[0].base.start=0;
- keyinfo[0].seg[0].base.length=6;
- keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[0].seg[0].base.flag=(uint8) pack_type;
- keyinfo[0].seg[1].base.type=0;
- keyinfo[0].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
- keyinfo[1].seg[0].base.start=7;
- keyinfo[1].seg[0].base.length=6;
- keyinfo[1].seg[0].base.type=HA_KEYTYPE_BINARY;
- keyinfo[1].seg[0].base.flag=0;
- keyinfo[1].seg[1].base.start=0; /* Tv}delad nyckel */
- keyinfo[1].seg[1].base.length=6;
- keyinfo[1].seg[1].base.type=HA_KEYTYPE_NUM;
- keyinfo[1].seg[1].base.flag=HA_REVERSE_SORT;
- keyinfo[1].seg[2].base.type=0;
- keyinfo[1].base.flag =0;
- keyinfo[2].seg[0].base.start=12;
- keyinfo[2].seg[0].base.length=8;
- keyinfo[2].seg[0].base.type=HA_KEYTYPE_BINARY;
- keyinfo[2].seg[0].base.flag=HA_REVERSE_SORT;
- keyinfo[2].seg[1].base.type=0;
- keyinfo[2].base.flag =HA_NOSAME;
- keyinfo[3].seg[0].base.start=0;
- keyinfo[3].seg[0].base.length=reclength-(use_blob ? 8 : 0);
- keyinfo[3].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[3].seg[0].base.flag=(uint8) pack_type;
- keyinfo[3].seg[1].base.type=0;
- keyinfo[3].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
- keyinfo[4].seg[0].base.start=0;
- keyinfo[4].seg[0].base.length=5;
- keyinfo[4].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[4].seg[0].base.flag=0;
- keyinfo[4].seg[1].base.type=0;
- keyinfo[4].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
- keyinfo[5].seg[0].base.start=0;
- keyinfo[5].seg[0].base.length=4;
- keyinfo[5].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[5].seg[0].base.flag=(uint8) pack_type;
- keyinfo[5].seg[1].base.type=0;
- keyinfo[5].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
-
- recinfo[0].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
- recinfo[0].base.length=7;
- recinfo[1].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
- recinfo[1].base.length=5;
- recinfo[2].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
- recinfo[2].base.length=9;
- recinfo[3].base.type=FIELD_NORMAL;
- recinfo[3].base.length=STANDAR_LENGTH-7-5-9-4;
- recinfo[4].base.type=pack_fields ? FIELD_SKIP_ZERO : 0;
- recinfo[4].base.length=4;
- recinfo[5].base.type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
- recinfo[5].base.length=60;
- if (use_blob)
- {
- recinfo[6].base.type=FIELD_BLOB;
- recinfo[6].base.length=4+sizeof(char*); /* 4 byte ptr, 4 byte length */
- recinfo[7].base.type= FIELD_LAST;
- }
- else
- recinfo[6].base.type= FIELD_LAST;
-
- write_count=update=dupp_keys=opt_delete=0;
- blob_buffer=0;
-
- for (i=999 ; i>0 ; i--) key1[i]=0;
- for (i=4999 ; i>0 ; i--) key3[i]=0;
-
- printf("- Creating isam-file\n");
- /* DBUG_PUSH(""); */
- my_delete(filename,MYF(0)); /* Remove old locks under gdb */
- file= 0;
- if (nisam_create(filename,keys,&keyinfo[first_key],&recinfo[0],
- (ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/
- reclength : 0),100l,0,0,0L))
- goto err;
- if (use_log)
- nisam_log(1);
- if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
- goto err;
- printf("- Writing key:s\n");
- if (key_cacheing)
- init_key_cache(dflt_key_cache,512,IO_SIZE*16,0,0); /* Use a small cache */
- if (locking)
- nisam_lock_database(file,F_WRLCK);
- if (write_cacheing)
- nisam_extra(file,HA_EXTRA_WRITE_CACHE);
-
- for (i=0 ; i < recant ; i++)
- {
- n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
- sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count);
- longstore(record+STANDAR_LENGTH-4,(long) i);
- fix_length(record,(uint) STANDAR_LENGTH+rnd(60));
- put_blob_in_record(record+blob_pos,&blob_buffer);
- DBUG_PRINT("test",("record: %d",i));
-
- if (nisam_write(file,record))
- {
- if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
- {
- printf("Error: %d in write at record: %d\n",my_errno,i);
- goto err;
- }
- if (verbose) printf(" Double key: %d\n",n3);
- }
- else
- {
- if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
- {
- printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
- goto err;
- }
- write_count++; key1[n1]++; key3[n3]=1;
- }
-
- /* Check if we can find key without flushing database */
- if (i == recant/2)
- {
- for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
- if (!j)
- for (j=999 ; j>0 && key1[j] == 0 ; j--) ;
- sprintf(key,"%6d",j);
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
- {
- printf("Test in loop: Can't find key: \"%s\"\n",key);
- goto err;
- }
- }
- }
- if (testflag==1) goto end;
-
- if (write_cacheing)
- if (nisam_extra(file,HA_EXTRA_NO_CACHE))
- {
- puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)");
- goto end;
- }
-
- printf("- Delete\n");
- for (i=0 ; i<recant/10 ; i++)
- {
- for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
- if (j != 0)
- {
- sprintf(key,"%6d",j);
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
- {
- printf("can't find key1: \"%s\"\n",key);
- goto err;
- }
- if (nisam_delete(file,read_record))
- {
- printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
- goto err;
- }
- opt_delete++;
- key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--;
- key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0;
- }
- }
- if (testflag==2) goto end;
-
- printf("- Update\n");
- for (i=0 ; i<recant/10 ; i++)
- {
- n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
- sprintf(record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update);
- longstore(record2+STANDAR_LENGTH-4,(long) i);
- fix_length(record2,(uint) STANDAR_LENGTH+rnd(60));
-
- for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
- if (j != 0)
- {
- sprintf(key,"%6d",j);
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
- {
- printf("can't find key1: \"%s\"\n",key);
- goto err;
- }
- if (use_blob)
- {
- if (i & 1)
- put_blob_in_record(record+blob_pos,&blob_buffer);
- else
- bmove(record+blob_pos,read_record+blob_pos,8);
- }
- if (nisam_update(file,read_record,record2))
- {
- if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
- {
- printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n",
- my_errno,read_record,record2);
- goto err;
- }
- if (verbose)
- printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n",record,record2);
- }
- else
- {
- key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--;
- key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0;
- key1[n1]++; key3[n3]=1;
- update++;
- }
- }
- }
- if (testflag==3) goto end;
-
- printf("- Same key: first - next -> last - prev -> first\n");
- DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
- for (i=999, dupp_keys=j=0 ; i>0 ; i--)
- {
- if (key1[i] >dupp_keys) { dupp_keys=key1[i]; j=i; }
- }
- sprintf(key,"%6d",j);
- if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys);
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
- if (nisam_rsame(file,read_record2,-1)) goto err;
- if (memcmp(read_record,read_record2,reclength) != 0)
- {
- printf("nisam_rsame didn't find same record\n");
- goto end;
- }
- nisam_info(file,&info,0);
- if (nisam_rfirst(file,read_record2,0) ||
- nisam_rsame_with_pos(file,read_record2,0,info.recpos) ||
- memcmp(read_record,read_record2,reclength) != 0)
- {
- printf("nisam_rsame_with_pos didn't find same record\n");
- goto end;
- }
- {
- int skr=nisam_rnext(file,read_record2,0);
- if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
- nisam_rprev(file,read_record2,-1) ||
- memcmp(read_record,read_record2,reclength) != 0)
- {
- printf("nisam_rsame_with_pos lost position\n");
- goto end;
- }
- }
- ant=1;
- start=keyinfo[0].seg[0].base.start; length=keyinfo[0].seg[0].base.length;
- while (nisam_rnext(file,read_record2,0) == 0 &&
- memcmp(read_record2+start,key,length) == 0) ant++;
- if (ant != dupp_keys)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys);
- goto end;
- }
- ant=0;
- while (nisam_rprev(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys)
- {
- printf("prev: I can only find: %d records of %d\n",ant,dupp_keys);
- goto end;
- }
-
- printf("- All keys: first - next -> last - prev -> first\n");
- DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first"));
- ant=1;
- if (nisam_rfirst(file,read_record,0))
- {
- printf("Can't find first record\n");
- goto end;
- }
- while (nisam_rnext(file,read_record3,0) == 0 && ant < write_count+10)
- ant++;
- if (ant != write_count - opt_delete)
- {
- printf("next: I found: %d records of %d\n",ant,write_count - opt_delete);
- goto end;
- }
- if (nisam_rlast(file,read_record2,0) ||
- bcmp(read_record2,read_record3,reclength))
- {
- printf("Can't find last record\n");
- DBUG_DUMP("record2",(byte*) read_record2,reclength);
- DBUG_DUMP("record3",(byte*) read_record3,reclength);
- goto end;
- }
- ant=1;
- while (nisam_rprev(file,read_record3,0) == 0 && ant < write_count+10)
- ant++;
- if (ant != write_count - opt_delete)
- {
- printf("prev: I found: %d records of %d\n",ant,write_count);
- goto end;
- }
- if (bcmp(read_record,read_record3,reclength))
- {
- printf("Can't find first record\n");
- goto end;
- }
-
- printf("- Test if: Read first - next - prev - prev - next == first\n");
- DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first"));
- if (nisam_rfirst(file,read_record,0) ||
- nisam_rnext(file,read_record3,0) ||
- nisam_rprev(file,read_record3,0) ||
- nisam_rprev(file,read_record3,0) == 0 ||
- nisam_rnext(file,read_record3,0))
- goto err;
- if (bcmp(read_record,read_record3,reclength) != 0)
- printf("Can't find first record\n");
-
- printf("- Test if: Read last - prev - next - next - prev == last\n");
- DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last"));
- if (nisam_rlast(file,read_record2,0) ||
- nisam_rprev(file,read_record3,0) ||
- nisam_rnext(file,read_record3,0) ||
- nisam_rnext(file,read_record3,0) == 0 ||
- nisam_rprev(file,read_record3,0))
- goto err;
- if (bcmp(read_record2,read_record3,reclength))
- printf("Can't find last record\n");
-
- puts("- Test read key-part");
- strmov(key2,key);
- for(i=strlen(key2) ; i-- > 1 ;)
- {
- key2[i]=0;
- if (nisam_rkey(file,read_record,0,key2,(uint) i,HA_READ_KEY_EXACT)) goto err;
- if (bcmp(read_record+start,key,(uint) i))
- {
- puts("Didn't find right record");
- goto end;
- }
- }
- if (dupp_keys > 2)
- {
- printf("- Read key (first) - next - delete - next -> last\n");
- DBUG_PRINT("progpos",("first - next - delete - next -> last"));
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
- if (nisam_rnext(file,read_record3,0)) goto err;
- if (nisam_delete(file,read_record3)) goto err;
- opt_delete++;
- ant=1;
- while (nisam_rnext(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys-1)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
- goto end;
- }
- }
- if (dupp_keys>4)
- {
- printf("- Read last of key - prev - delete - prev -> first\n");
- DBUG_PRINT("progpos",("last - prev - delete - prev -> first"));
- if (nisam_rprev(file,read_record3,0)) goto err;
- if (nisam_rprev(file,read_record3,0)) goto err;
- if (nisam_delete(file,read_record3)) goto err;
- opt_delete++;
- ant=1;
- while (nisam_rprev(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys-2)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
- goto end;
- }
- }
- if (dupp_keys > 6)
- {
- printf("- Read first - delete - next -> last\n");
- DBUG_PRINT("progpos",("first - delete - next -> last"));
- if (nisam_rkey(file,read_record3,0,key,0,HA_READ_KEY_EXACT)) goto err;
- if (nisam_delete(file,read_record3)) goto err;
- opt_delete++;
- ant=1;
- if (nisam_rnext(file,read_record,0))
- goto err; /* Skall finnas poster */
- while (nisam_rnext(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys-3)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
- goto end;
- }
-
- printf("- Read last - delete - prev -> first\n");
- DBUG_PRINT("progpos",("last - delete - prev -> first"));
- if (nisam_rprev(file,read_record3,0)) goto err;
- if (nisam_delete(file,read_record3)) goto err;
- opt_delete++;
- ant=0;
- while (nisam_rprev(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys-4)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
- goto end;
- }
- }
-
- puts("- Test if: Read rrnd - same");
- DBUG_PRINT("progpos",("Read rrnd - same"));
- for (i=0 ; i < write_count ; i++)
- {
- if (nisam_rrnd(file,read_record,i == 0 ? 0L : NI_POS_ERROR) == 0)
- break;
- }
- if (i == write_count)
- goto err;
-
- bmove(read_record2,read_record,reclength);
- for (i=2 ; i-- > 0 ;)
- {
- if (nisam_rsame(file,read_record2,(int) i)) goto err;
- if (bcmp(read_record,read_record2,reclength) != 0)
- {
- printf("is_rsame didn't find same record\n");
- goto end;
- }
- }
- puts("- Test nisam_records_in_range");
- nisam_info(file,&info,HA_STATUS_VARIABLE);
- for (i=0 ; i < info.keys ; i++)
- {
- if (nisam_rfirst(file,read_record,(int) i) ||
- nisam_rlast(file,read_record2,(int) i))
- goto err;
- copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key);
- copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2);
- range_records=nisam_records_in_range(file,(int) i,key,0,HA_READ_KEY_EXACT,
- key2,0,HA_READ_AFTER_KEY);
- if (range_records < info.records*8/10 ||
- range_records > info.records*12/10)
- {
- printf("ni_records_range returned %lu; Should be about %lu\n",
- range_records,info.records);
- goto end;
- }
- if (verbose)
- {
- printf("ni_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
- range_records,info.records,
- labs((long) range_records - (long) info.records)*100.0/
- info.records);
-
- }
- }
- for (i=0 ; i < 5 ; i++)
- {
- for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
- for (k=rnd(1000) ; k>0 && key1[k] == 0 ; k--) ;
- if (j != 0 && k != 0)
- {
- if (j > k)
- swap_variables(int, j, k);
- sprintf(key,"%6d",j);
- sprintf(key2,"%6d",k);
- range_records=nisam_records_in_range(file,0,key,0,HA_READ_AFTER_KEY,
- key2,0,HA_READ_BEFORE_KEY);
- records=0;
- for (j++ ; j < k ; j++)
- records+=key1[j];
- if ((long) range_records < (long) records*7/10-2 ||
- (long) range_records > (long) records*13/10+2)
- {
- printf("ni_records_range returned %ld; Should be about %ld\n",
- range_records,records);
- goto end;
- }
- if (verbose && records)
- {
- printf("ni_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
- range_records,records,
- labs((long) range_records-(long) records)*100.0/records);
-
- }
- }
- }
-
- printf("- nisam_info\n");
- nisam_info(file,&info,0);
- if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
- || info.keys != keys)
- {
- puts("Wrong info from nisam_info");
- printf("Got: records: %ld opt_delete: %ld i_keys: %d\n",
- info.records,info.deleted,info.keys);
- }
- if (verbose)
- {
- char buff[80];
- get_date(buff,3,info.create_time);
- printf("info: Created %s\n",buff);
- get_date(buff,3,info.isamchk_time);
- printf("info: checked %s\n",buff);
- get_date(buff,3,info.update_time);
- printf("info: Modified %s\n",buff);
- }
-
- nisam_panic(HA_PANIC_WRITE);
- nisam_panic(HA_PANIC_READ);
- if (nisam_is_changed(file))
- puts("Warning: nisam_is_changed reported that datafile was changed");
-
- printf("- nisam_extra(CACHE) + nisam_rrnd.... + nisam_extra(NO_CACHE)\n");
- if (nisam_extra(file,HA_EXTRA_RESET) || nisam_extra(file,HA_EXTRA_CACHE))
- {
- if (locking || (!use_blob && !pack_fields))
- {
- puts("got error from nisam_extra(HA_EXTRA_CACHE)");
- goto end;
- }
- }
- ant=0;
- while ((error=nisam_rrnd(file,record,NI_POS_ERROR)) >= 0 &&
- ant < write_count + 10)
- ant+= error ? 0 : 1;
- if (ant != write_count-opt_delete)
- {
- printf("rrnd with cache: I can only find: %d records of %d\n",
- ant,write_count-opt_delete);
- goto end;
- }
- if (nisam_extra(file,HA_EXTRA_NO_CACHE))
- {
- puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)");
- goto end;
- }
-
- if (testflag == 4) goto end;
-
- printf("- Removing keys\n");
- lastpos = NI_POS_ERROR;
- /* DBUG_POP(); */
- nisam_extra(file,HA_EXTRA_RESET);
- while ((error=nisam_rrnd(file,read_record,NI_POS_ERROR)) >=0)
- {
- nisam_info(file,&info,1);
- if (lastpos >= info.recpos && lastpos != NI_POS_ERROR)
- {
- printf("nisam_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
- lastpos,info.recpos);
- goto err;
- }
- lastpos=info.recpos;
- if (error == 0)
- {
- if (nisam_rsame(file,read_record,-1))
- {
- printf("can't find record %lx\n",info.recpos);
- goto err;
- }
- if (use_blob)
- {
- ulong blob_length,pos;
- uchar *ptr;
- longget(blob_length,read_record+blob_pos+4);
- ptr=(uchar*) blob_length;
- longget(blob_length,read_record+blob_pos);
- for (pos=0 ; pos < blob_length ; pos++)
- {
- if (ptr[pos] != (uchar) (blob_length+pos))
- {
- printf("found blob with wrong info at %ld\n",lastpos);
- use_blob=0;
- break;
- }
- }
- }
- if (nisam_delete(file,read_record))
- {
- printf("can't delete record: %s\n",read_record);
- goto err;
- }
- opt_delete++;
- }
- }
- if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED)
- printf("error: %d from nisam_rrnd\n",my_errno);
- if (write_count != opt_delete)
- {
- printf("Deleted only %d of %d records\n",write_count,opt_delete);
- goto err;
- }
-end:
- if (nisam_close(file))
- goto err;
- nisam_panic(HA_PANIC_CLOSE); /* Should close log */
- printf("\nFollowing test have been made:\n");
- printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
- if (rec_pointer_size)
- printf("Record pointer size: %d\n",rec_pointer_size);
- if (key_cacheing)
- puts("Key cacheing used");
- if (write_cacheing)
- puts("Write cacheing used");
- if (async_io && locking)
- puts("Asyncron io with locking used");
- else if (locking)
- puts("Locking used");
- if (use_blob)
- puts("blobs used");
- end_key_cache(dflt_key_cache,1);
- if (blob_buffer)
- my_free(blob_buffer,MYF(0));
- my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
- return(0);
-err:
- printf("got error: %d when using NISAM-database\n",my_errno);
- if (file)
- VOID(nisam_close(file));
- return(1);
-} /* main */
-
-
- /* l{ser optioner */
- /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
-
-static void get_options( int argc, char *argv[])
-{
- char *pos,*progname;
- DEBUGGER_OFF;
-
- progname= argv[0];
-
- while (--argc >0 && *(pos = *(++argv)) == '-' ) {
- switch(*++pos) {
- case 'b':
- if (*++pos)
- nisam_block_size= MY_ALIGN(atoi(pos),512);
- set_if_bigger(nisam_block_size,8192); /* Max block size */
- set_if_smaller(nisam_block_size,1024);
- break;
- case 'B':
- use_blob=1;
- break;
- case 'K': /* Use key cacheing */
- key_cacheing=1;
- break;
- case 'W': /* Use write cacheing */
- write_cacheing=1;
- if (*++pos)
- my_default_record_cache_size=atoi(pos);
- break;
- case 'i':
- if (*++pos)
- srand(atoi(pos));
- break;
- case 'l':
- use_log=1;
- break;
- case 'L':
- locking=1;
- break;
- case 'A': /* use asyncron io */
- async_io=1;
- if (*++pos)
- my_default_record_cache_size=atoi(pos);
- break;
- case 'v': /* verbose */
- verbose=1;
- break;
- case 'm': /* records */
- recant=atoi(++pos);
- break;
- case 'f':
- if ((first_key=atoi(++pos)) <0 || first_key >= NISAM_KEYS)
- first_key=0;
- break;
- case 'k':
- if ((keys=(uint) atoi(++pos)) < 1 ||
- keys > (uint) (NISAM_KEYS-first_key))
- keys=NISAM_KEYS-first_key;
- break;
- case 'P':
- pack_type=0; /* Don't use DIFF_LENGTH */
- break;
- case 'R': /* Length of record pointer */
- rec_pointer_size=atoi(++pos);
- if (rec_pointer_size > 3)
- rec_pointer_size=0;
- break;
- case 'S':
- pack_fields=0; /* Static-length-records */
- break;
- case 't':
- testflag=atoi(++pos); /* testmod */
- break;
- case '?':
- case 'I':
- case 'V':
- printf("%s Ver 1.4 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
- puts("TCX Datakonsult AB, by Monty, for your professional use\n");
- printf("Usage: %s [-?ABIKLPRSVWltv] [-b#] [-k#] [-f#] [-m#] [-t#]\n",progname);
- exit(0);
- case '#':
- DEBUGGER_ON;
- DBUG_PUSH (++pos);
- break;
- default:
- printf("Illegal option: '%c'\n",*pos);
- break;
- }
- }
- return;
-} /* get options */
-
- /* Ge ett randomv{rde inom ett intervall 0 <=x <= n */
-
-static uint rnd( uint max_value)
-{
- return (uint) ((rand() & 32767)/32767.0*max_value);
-} /* rnd */
-
-
- /* G|r en record av skiftande length */
-
-static void fix_length( byte *rec, uint length)
-{
- bmove(rec+STANDAR_LENGTH,
- "0123456789012345678901234567890123456789012345678901234567890",
- length-STANDAR_LENGTH);
- strfill(rec+length,STANDAR_LENGTH+60-length,' ');
-} /* fix_length */
-
-
- /* Put maybe a blob in record */
-
-static void put_blob_in_record(char *blob_pos, char **blob_buffer)
-{
- ulong i,length;
- if (use_blob)
- {
- if (rnd(10) == 0)
- {
- if (! *blob_buffer &&
- !(*blob_buffer=my_malloc((uint) use_blob,MYF(MY_WME))))
- {
- use_blob=0;
- return;
- }
- length=rnd(use_blob);
- for (i=0 ; i < length ; i++)
- (*blob_buffer)[i]=(char) (length+i);
- longstore(blob_pos,length);
- bmove(blob_pos+4,(char*) blob_buffer,sizeof(char*));
- }
- else
- {
- longstore(blob_pos,0);
- }
- }
- return;
-}
-
-
-static void copy_key( N_INFO *info, uint inx, uchar *rec, uchar *key_buff)
-{
- N_KEYSEG *keyseg;
-
- for (keyseg=info->s->keyinfo[inx].seg ; keyseg->base.type ; keyseg++)
- {
- memcpy(key_buff,rec+keyseg->base.start,(size_t) keyseg->base.length);
- key_buff+=keyseg->base.length;
- }
- return;
-}
diff --git a/isam/test3.c b/isam/test3.c
deleted file mode 100644
index 9195fcbf1b6..00000000000
--- a/isam/test3.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Test av locking */
-
-#ifndef __NETWARE__
-
-#include "nisam.h"
-#include <sys/types.h>
-#include <keycache.h>
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-#ifndef WEXITSTATUS
-# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
-#endif
-#ifndef WIFEXITED
-# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
-#endif
-
-
-#if defined(HAVE_LRAND48)
-#define rnd(X) (lrand48() % X)
-#define rnd_init(X) srand48(X)
-#else
-#define rnd(X) (random() % X)
-#define rnd_init(X) srandom(X)
-#endif
-
-
-const char *filename= "test3.ISM";
-uint tests=10,forks=10,key_cacheing=0,use_log=0;
-
-static void get_options(int argc, char *argv[]);
-void start_test(int id);
-int test_read(N_INFO *,int),test_write(N_INFO *,int,int),
- test_update(N_INFO *,int,int),test_rrnd(N_INFO *,int);
-
-struct record {
- char id[8];
- uint32 nr;
- char text[10];
-} record;
-
-
-int main(int argc,char **argv)
-{
- int status,wait_ret;
- uint i;
- N_KEYDEF keyinfo[10];
- N_RECINFO recinfo[10];
- MY_INIT(argv[0]);
-
- get_options(argc,argv);
-
- keyinfo[0].seg[0].base.start=0;
- keyinfo[0].seg[0].base.length=8;
- keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[0].seg[0].base.flag=HA_SPACE_PACK;
- keyinfo[0].seg[1].base.type=0;
- keyinfo[0].base.flag = (uint8) HA_PACK_KEY;
- keyinfo[1].seg[0].base.start=8;
- keyinfo[1].seg[0].base.length=sizeof(uint32);
- keyinfo[1].seg[0].base.type=HA_KEYTYPE_LONG_INT;
- keyinfo[1].seg[0].base.flag=0;
- keyinfo[1].seg[1].base.type=0;
- keyinfo[1].base.flag =HA_NOSAME;
-
- recinfo[0].base.type=0;
- recinfo[0].base.length=sizeof(record.id);
- recinfo[1].base.type=0;
- recinfo[1].base.length=sizeof(record.nr);
- recinfo[2].base.type=0;
- recinfo[2].base.length=sizeof(record.text);
- recinfo[3].base.type=FIELD_LAST;
-
- puts("- Creating isam-file");
- my_delete(filename,MYF(0)); /* Remove old locks under gdb */
- if (nisam_create(filename,2,&keyinfo[0],&recinfo[0],10000,0,0,0,0L))
- exit(1);
-
- rnd_init(0);
- printf("- Starting %d processes\n",forks); fflush(stdout);
- for (i=0 ; i < forks; i++)
- {
- if (!fork())
- {
- start_test(i+1);
- sleep(1);
- return 0;
- }
- VOID(rnd(1));
- }
-
- for (i=0 ; i < forks ; i++)
- while ((wait_ret=wait(&status)) && wait_ret == -1);
- return 0;
-}
-
-
-static void get_options(argc,argv)
-int argc;
-char *argv[];
-{
- char *pos,*progname;
- DEBUGGER_OFF;
-
- progname= argv[0];
-
- while (--argc >0 && *(pos = *(++argv)) == '-' ) {
- switch(*++pos) {
- case 'l':
- use_log=1;
- break;
- case 'f':
- forks=atoi(++pos);
- break;
- case 't':
- tests=atoi(++pos);
- break;
- case 'K': /* Use key cacheing */
- key_cacheing=1;
- break;
- case 'A': /* All flags */
- use_log=key_cacheing=1;
- break;
- case '?':
- case 'I':
- case 'V':
- printf("%s Ver 1.0 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
- puts("TCX Datakonsult AB, by Monty, for your professional use\n");
- puts("Test av locking with threads\n");
- printf("Usage: %s [-?lKA] [-f#] [-t#]\n",progname);
- exit(0);
- case '#':
- DEBUGGER_ON;
- DBUG_PUSH (++pos);
- break;
- default:
- printf("Illegal option: '%c'\n",*pos);
- break;
- }
- }
- return;
-}
-
-
-void start_test(int id)
-{
- uint i;
- int error,lock_type;
- N_ISAMINFO isam_info;
- N_INFO *file,*file1,*file2,*lock;
-
- if (use_log)
- nisam_log(1);
- if (!(file1=nisam_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)) ||
- !(file2=nisam_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)))
- {
- fprintf(stderr,"Can't open isam-file: %s\n",filename);
- exit(1);
- }
- if (key_cacheing && rnd(2) == 0)
- init_key_cache(dflt_key_cache,512,65536L,0,0);
- printf("Process %d, pid: %d\n",id,(int) getpid()); fflush(stdout);
-
- for (error=i=0 ; i < tests && !error; i++)
- {
- file= (rnd(2) == 1) ? file1 : file2;
- lock=0 ; lock_type=0;
- if (rnd(10) == 0)
- {
- if (nisam_lock_database(lock=(rnd(2) ? file1 : file2),
- lock_type=(rnd(2) == 0 ? F_RDLCK : F_WRLCK)))
- {
- fprintf(stderr,"%2d: start: Can't lock table %d\n",id,my_errno);
- error=1;
- break;
- }
- }
- switch (rnd(4)) {
- case 0: error=test_read(file,id); break;
- case 1: error=test_rrnd(file,id); break;
- case 2: error=test_write(file,id,lock_type); break;
- case 3: error=test_update(file,id,lock_type); break;
- }
- if (lock)
- nisam_lock_database(lock,F_UNLCK);
- }
- if (!error)
- {
- nisam_info(file1,&isam_info,0);
- printf("%2d: End of test. Records: %ld Deleted: %ld\n",
- id,isam_info.records,isam_info.deleted);
- fflush(stdout);
- }
-
- nisam_close(file1);
- nisam_close(file2);
- if (use_log)
- nisam_log(0);
- if (error)
- {
- printf("%2d: Aborted\n",id); fflush(stdout);
- exit(1);
- }
-}
-
-
-int test_read(N_INFO *file,int id)
-{
- uint i,lock,found,next,prev;
- ulong find;
-
- lock=0;
- if (rnd(2) == 0)
- {
- lock=1;
- if (nisam_lock_database(file,F_RDLCK))
- {
- fprintf(stderr,"%2d: Can't lock table %d\n",id,my_errno);
- return 1;
- }
- }
-
- found=next=prev=0;
- for (i=0 ; i < 100 ; i++)
- {
- find=rnd(100000);
- if (!nisam_rkey(file,record.id,1,(byte*) &find,
- sizeof(find),HA_READ_KEY_EXACT))
- found++;
- else
- {
- if (my_errno != HA_ERR_KEY_NOT_FOUND)
- {
- fprintf(stderr,"%2d: Got error %d from read in read\n",id,my_errno);
- return 1;
- }
- else if (!nisam_rnext(file,record.id,1))
- next++;
- else
- {
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rnext in read\n",id,my_errno);
- return 1;
- }
- else if (!nisam_rprev(file,record.id,1))
- prev++;
- else
- {
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rnext in read\n",
- id,my_errno);
- return 1;
- }
- }
- }
- }
- }
- if (lock)
- {
- if (nisam_lock_database(file,F_UNLCK))
- {
- fprintf(stderr,"%2d: Can't unlock table\n",id);
- return 1;
- }
- }
- printf("%2d: read: found: %5d next: %5d prev: %5d\n",
- id,found,next,prev);
- fflush(stdout);
- return 0;
-}
-
-
-int test_rrnd(N_INFO *file,int id)
-{
- uint count,lock;
-
- lock=0;
- if (rnd(2) == 0)
- {
- lock=1;
- if (nisam_lock_database(file,F_RDLCK))
- {
- fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
- nisam_close(file);
- return 1;
- }
- if (rnd(2) == 0)
- nisam_extra(file,HA_EXTRA_CACHE);
- }
-
- count=0;
- if (nisam_rrnd(file,record.id,0L))
- {
- if (my_errno == HA_ERR_END_OF_FILE)
- goto end;
- fprintf(stderr,"%2d: Can't read first record (%d)\n",id,my_errno);
- return 1;
- }
- for (count=1 ; !nisam_rrnd(file,record.id,NI_POS_ERROR) ;count++) ;
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rrnd\n",id,my_errno);
- return 1;
- }
-
-end:
- if (lock)
- {
- nisam_extra(file,HA_EXTRA_NO_CACHE);
- if (nisam_lock_database(file,F_UNLCK))
- {
- fprintf(stderr,"%2d: Can't unlock table\n",id);
- exit(0);
- }
- }
- printf("%2d: rrnd: %5d\n",id,count); fflush(stdout);
- return 0;
-}
-
-
-int test_write(N_INFO *file,int id,int lock_type)
-{
- uint i,tries,count,lock;
-
- lock=0;
- if (rnd(2) == 0 || lock_type == F_RDLCK)
- {
- lock=1;
- if (nisam_lock_database(file,F_WRLCK))
- {
- if (lock_type == F_RDLCK && my_errno == EDEADLK)
- {
- printf("%2d: write: deadlock\n",id); fflush(stdout);
- return 0;
- }
- fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
- nisam_close(file);
- return 1;
- }
- if (rnd(2) == 0)
- nisam_extra(file,HA_EXTRA_WRITE_CACHE);
- }
-
- sprintf(record.id,"%7d",(int) getpid());
- strmov(record.text,"Testing...");
-
- tries=(uint) rnd(100)+10;
- for (i=count=0 ; i < tries ; i++)
- {
- record.nr=rnd(80000)+20000;
- if (!nisam_write(file,record.id))
- count++;
- else
- {
- if (my_errno != HA_ERR_FOUND_DUPP_KEY)
- {
- fprintf(stderr,"%2d: Got error %d (errno %d) from write\n",id,my_errno,
- errno);
- return 1;
- }
- }
- }
- if (lock)
- {
- nisam_extra(file,HA_EXTRA_NO_CACHE);
- if (nisam_lock_database(file,F_UNLCK))
- {
- fprintf(stderr,"%2d: Can't unlock table\n",id);
- exit(0);
- }
- }
- printf("%2d: write: %5d\n",id,count); fflush(stdout);
- return 0;
-}
-
-
-int test_update(N_INFO *file,int id,int lock_type)
-{
- uint i,lock,found,next,prev,update;
- ulong find;
- struct record new_record;
-
- lock=0;
- if (rnd(2) == 0 || lock_type == F_RDLCK)
- {
- lock=1;
- if (nisam_lock_database(file,F_WRLCK))
- {
- if (lock_type == F_RDLCK && my_errno == EDEADLK)
- {
- printf("%2d: write: deadlock\n",id); fflush(stdout);
- return 0;
- }
- fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
- return 1;
- }
- }
- bzero((char*) &new_record,sizeof(new_record));
- strmov(new_record.text,"Updated");
-
- found=next=prev=update=0;
- for (i=0 ; i < 100 ; i++)
- {
- find=rnd(100000);
- if (!nisam_rkey(file,record.id,1,(byte*) &find,
- sizeof(find),HA_READ_KEY_EXACT))
- found++;
- else
- {
- if (my_errno != HA_ERR_KEY_NOT_FOUND)
- {
- fprintf(stderr,"%2d: Got error %d from read in update\n",id,my_errno);
- return 1;
- }
- else if (!nisam_rnext(file,record.id,1))
- next++;
- else
- {
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rnext in update\n",
- id,my_errno);
- return 1;
- }
- else if (!nisam_rprev(file,record.id,1))
- prev++;
- else
- {
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rnext in update\n",
- id,my_errno);
- return 1;
- }
- continue;
- }
- }
- }
- memcpy_fixed(new_record.id,record.id,sizeof(record.id));
- new_record.nr=rnd(20000)+40000;
- if (!nisam_update(file,record.id,new_record.id))
- update++;
- else
- {
- if (my_errno != HA_ERR_RECORD_CHANGED &&
- my_errno != HA_ERR_RECORD_DELETED &&
- my_errno != HA_ERR_FOUND_DUPP_KEY)
- {
- fprintf(stderr,"%2d: Got error %d from update\n",id,my_errno);
- return 1;
- }
- }
- }
- if (lock)
- {
- if (nisam_lock_database(file,F_UNLCK))
- {
- fprintf(stderr,"Can't unlock table,id, error%d\n",my_errno);
- return 1;
- }
- }
- printf("%2d: update: %5d\n",id,update); fflush(stdout);
- return 0;
-}
-
-#else /* __NETWARE__ */
-
-#include <stdio.h>
-
-main()
-{
- fprintf(stderr,"this test has not been ported to NetWare\n");
- return 0;
-}
-
-#endif /* __NETWARE__ */
diff --git a/isam/test_all b/isam/test_all
deleted file mode 100755
index 5de37e44585..00000000000
--- a/isam/test_all
+++ /dev/null
@@ -1,30 +0,0 @@
-echo "test2 -L -K -W -P"
-test2 -L -K -W -P
-echo "test2 -L -K -W -P -A"
-test2 -L -K -W -P -A
-echo "test2 -L -K -W -P -S -R1 -m500"
-test2 -L -K -W -P -S -R1 -m500
-echo "test2 -L -K -R1 -m2000 ; Should give error 135"
-test2 -L -K -R1 -m2000
-echo "test2 -L -K -P -S -R3 -m50 -b1000000"
-test2 -L -K -P -S -R3 -m50 -b1000000
-echo "test2 -L -B"
-test2 -L -B
-echo "test2 -L -K -W -P -m50 -l"
-test2 -L -K -W -P -m50 -l
-isamlog
-echo "test2 -L -K -W -P -m50 -l -b100"
-test2 -L -K -W -P -m50 -l -b100
-isamlog
-echo "time test2"
-time test2
-echo "time test2 -K"
-time test2 -K
-echo "time test2 -L"
-time test2 -L
-echo "time test2 -L -K"
-time test2 -L -K
-echo "time test2 -L -K -W"
-time test2 -L -K -W
-echo "time test2 -L -K -W -S"
-time test2 -L -K -W -S
diff --git a/isam/test_all.res b/isam/test_all.res
deleted file mode 100644
index 5de37e44585..00000000000
--- a/isam/test_all.res
+++ /dev/null
@@ -1,30 +0,0 @@
-echo "test2 -L -K -W -P"
-test2 -L -K -W -P
-echo "test2 -L -K -W -P -A"
-test2 -L -K -W -P -A
-echo "test2 -L -K -W -P -S -R1 -m500"
-test2 -L -K -W -P -S -R1 -m500
-echo "test2 -L -K -R1 -m2000 ; Should give error 135"
-test2 -L -K -R1 -m2000
-echo "test2 -L -K -P -S -R3 -m50 -b1000000"
-test2 -L -K -P -S -R3 -m50 -b1000000
-echo "test2 -L -B"
-test2 -L -B
-echo "test2 -L -K -W -P -m50 -l"
-test2 -L -K -W -P -m50 -l
-isamlog
-echo "test2 -L -K -W -P -m50 -l -b100"
-test2 -L -K -W -P -m50 -l -b100
-isamlog
-echo "time test2"
-time test2
-echo "time test2 -K"
-time test2 -K
-echo "time test2 -L"
-time test2 -L
-echo "time test2 -L -K"
-time test2 -L -K
-echo "time test2 -L -K -W"
-time test2 -L -K -W
-echo "time test2 -L -K -W -S"
-time test2 -L -K -W -S
diff --git a/isam/update.c b/isam/update.c
deleted file mode 100644
index b3b676f967d..00000000000
--- a/isam/update.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Uppdaterare nuvarande record i en pisam-databas */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* Updaterar senaste l{sta record i databasen */
-
-int nisam_update(register N_INFO *info, const byte *oldrec, const byte *newrec)
-{
- int flag,key_changed,save_errno;
- reg3 ulong pos;
- uint i,length;
- uchar old_key[N_MAX_KEY_BUFF],*new_key;
- DBUG_ENTER("nisam_update");
-
- LINT_INIT(save_errno);
- if (!(info->update & HA_STATE_AKTIV))
- {
- my_errno=HA_ERR_KEY_NOT_FOUND;
- DBUG_RETURN(-1);
- }
- if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
- {
- my_errno=EACCES;
- DBUG_RETURN(-1);
- }
- pos=info->lastpos;
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
-#endif
- if ((*info->s->compare_record)(info,oldrec))
- {
- save_errno=my_errno;
- goto err_end; /* Record has changed */
- }
- if (info->s->state.key_file_length >=
- info->s->base.max_key_file_length -
- info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys)
- {
- save_errno=HA_ERR_INDEX_FILE_FULL;
- goto err_end;
- }
-
- /* Flyttar de element i isamfilen som m}ste flyttas */
-
- new_key=info->lastkey+info->s->base.max_key_length;
- key_changed=HA_STATE_KEY_CHANGED; /* We changed current database */
- /* Remove key that didn't change */
- for (i=0 ; i < info->s->state.keys ; i++)
- {
- length=_nisam_make_key(info,i,new_key,newrec,pos);
- if (length != _nisam_make_key(info,i,old_key,oldrec,pos) ||
- memcmp((byte*) old_key,(byte*) new_key,length))
- {
- if ((int) i == info->lastinx)
- key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */
- if (_nisam_ck_delete(info,i,old_key)) goto err;
- if (_nisam_ck_write(info,i,new_key)) goto err;
- }
- }
-
- if ((*info->s->update_record)(info,pos,newrec))
- goto err;
-
- info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV |
- key_changed);
- nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,0);
- VOID(_nisam_writeinfo(info,test(key_changed)));
- allow_break(); /* Allow SIGHUP & SIGINT */
- DBUG_RETURN(0);
-
-err:
- DBUG_PRINT("error",("key: %d errno: %d",i,my_errno));
- save_errno=my_errno;
- if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
- {
- info->errkey= (int) i;
- flag=0;
- do
- {
- length=_nisam_make_key(info,i,new_key,newrec,pos);
- if (length != _nisam_make_key(info,i,old_key,oldrec,pos) ||
- memcmp((byte*) old_key,(byte*) new_key,length))
- {
- if ((flag++ && _nisam_ck_delete(info,i,new_key)) ||
- _nisam_ck_write(info,i,old_key))
- break;
- }
- } while (i-- != 0);
- }
- info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV |
- key_changed);
- err_end:
- nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,save_errno);
- VOID(_nisam_writeinfo(info,1));
- allow_break(); /* Allow SIGHUP & SIGINT */
- my_errno=(save_errno == HA_ERR_KEY_NOT_FOUND) ? HA_ERR_CRASHED : save_errno;
- DBUG_RETURN(-1);
-} /* nisam_update */
diff --git a/isam/write.c b/isam/write.c
deleted file mode 100644
index f2c0d8dbc45..00000000000
--- a/isam/write.c
+++ /dev/null
@@ -1,840 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Skriver ett record till en isam-databas */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* Functions declared in this file */
-
-static int w_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- ulong pos, uchar *father_buff, uchar *father_keypos,
- ulong father_page);
-static int _nisam_balance_page(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- uchar *curr_buff,uchar *father_buff,
- uchar *father_keypos,ulong father_page);
-
-
- /* Write new record to database */
-
-int nisam_write(N_INFO *info, const byte *record)
-{
- uint i;
- ulong filepos;
- uchar *buff;
- DBUG_ENTER("nisam_write");
- DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile));
-
- if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
- {
- my_errno=EACCES;
- DBUG_RETURN(-1);
- }
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
-#endif
- dont_break(); /* Dont allow SIGHUP or SIGINT */
-#if !defined(NO_LOCKING) && defined(USE_RECORD_LOCK)
- if (!info->locked && my_lock(info->dfile,F_WRLCK,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
- goto err;
-#endif
- filepos= ((info->s->state.dellink != NI_POS_ERROR) ?
- info->s->state.dellink :
- info->s->state.data_file_length);
-
- if (info->s->base.reloc == 1L && info->s->base.records == 1L &&
- info->s->state.records == 1L)
- { /* System file */
- my_errno=HA_ERR_RECORD_FILE_FULL;
- goto err2;
- }
- if (info->s->state.key_file_length >=
- info->s->base.max_key_file_length -
- info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys)
- {
- my_errno=HA_ERR_INDEX_FILE_FULL;
- goto err2;
- }
-
- /* Write all keys to indextree */
- buff=info->lastkey+info->s->base.max_key_length;
- for (i=0 ; i < info->s->state.keys ; i++)
- {
- VOID(_nisam_make_key(info,i,buff,record,filepos));
- if (_nisam_ck_write(info,i,buff)) goto err;
- }
-
- if ((*info->s->write_record)(info,record))
- goto err;
-
- info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |HA_STATE_AKTIV |
- HA_STATE_WRITTEN);
- info->s->state.records++;
- info->lastpos=filepos;
- nisam_log_record(LOG_WRITE,info,record,filepos,0);
- VOID(_nisam_writeinfo(info,1));
- allow_break(); /* Allow SIGHUP & SIGINT */
- DBUG_RETURN(0);
-
-err:
- if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
- {
- info->errkey= (int) i;
- while ( i-- > 0)
- {
- VOID(_nisam_make_key(info,i,buff,record,filepos));
- if (_nisam_ck_delete(info,i,buff))
- break;
- }
- }
- info->update=(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_WRITTEN);
-err2:
- nisam_log_record(LOG_WRITE,info,record,filepos,my_errno);
- VOID(_nisam_writeinfo(info,1));
- allow_break(); /* Allow SIGHUP & SIGINT */
- DBUG_RETURN(-1);
-} /* nisam_write */
-
-
- /* Write one key to btree */
-
-int _nisam_ck_write(register N_INFO *info, uint keynr, uchar *key)
-{
- int error;
- DBUG_ENTER("_nisam_ck_write");
-
- if ((error=w_search(info,info->s->keyinfo+keynr,key,
- info->s->state.key_root[keynr], (uchar *) 0, (uchar*) 0,
- 0L)) > 0)
- error=_nisam_enlarge_root(info,keynr,key);
- DBUG_RETURN(error);
-} /* _nisam_ck_write */
-
-
- /* Make a new root with key as only pointer */
-
-int _nisam_enlarge_root(register N_INFO *info, uint keynr, uchar *key)
-{
- uint t_length,nod_flag;
- reg2 N_KEYDEF *keyinfo;
- S_PARAM s_temp;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_enlarge_root");
-
- info->page_changed=1;
- nod_flag= (share->state.key_root[keynr] != NI_POS_ERROR) ?
- share->base.key_reflength : 0;
- _nisam_kpointer(info,info->buff+2,share->state.key_root[keynr]); /* if nod */
- keyinfo=share->keyinfo+keynr;
- t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0,(uchar*) 0,
- key,&s_temp);
- putint(info->buff,t_length+2+nod_flag,nod_flag);
- _nisam_store_key(keyinfo,info->buff+2+nod_flag,&s_temp);
- if ((share->state.key_root[keynr]= _nisam_new(info,keyinfo)) ==
- NI_POS_ERROR ||
- _nisam_write_keypage(info,keyinfo,share->state.key_root[keynr],info->buff))
- DBUG_RETURN(-1);
- DBUG_RETURN(0);
-} /* _nisam_enlarge_root */
-
-
- /* S|ker reda p} vart nyckeln skall s{ttas och placerar den dit */
- /* Returnerar -1 om fel ; 0 om ok. 1 om nyckel propagerar upp}t */
-
-static int w_search(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, ulong page, uchar *father_buff,
- uchar *father_keypos, ulong father_page)
-{
- int error,flag;
- uint comp_flag,nod_flag;
- uchar *temp_buff,*keypos;
- uchar keybuff[N_MAX_KEY_BUFF];
- DBUG_ENTER("w_search");
- DBUG_PRINT("enter",("page: %ld",page));
-
- if (page == NI_POS_ERROR)
- DBUG_RETURN(1); /* No key, make new */
-
- if (keyinfo->base.flag & HA_SORT_ALLOWS_SAME)
- comp_flag=SEARCH_BIGGER; /* Put after same key */
- else if (keyinfo->base.flag & HA_NOSAME)
- comp_flag=SEARCH_FIND; /* No dupplicates */
- else
- comp_flag=SEARCH_SAME; /* Keys in rec-pos order */
-
- if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
- N_MAX_KEY_BUFF)))
- DBUG_RETURN(-1);
- if (!_nisam_fetch_keypage(info,keyinfo,page,temp_buff,0))
- goto err;
-
- flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,0,comp_flag,&keypos,
- keybuff);
- nod_flag=test_if_nod(temp_buff);
- if (flag == 0)
- {
- my_errno=HA_ERR_FOUND_DUPP_KEY;
- /* get position to record with dupplicated key */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff));
- info->dupp_key_pos=_nisam_dpos(info,test_if_nod(temp_buff),keypos);
- my_afree((byte*) temp_buff);
- DBUG_RETURN(-1);
- }
- if ((error=w_search(info,keyinfo,key,_nisam_kpos(nod_flag,keypos),
- temp_buff,keypos,page)) >0)
- {
- error=_nisam_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff,
- father_keypos,father_page);
- if (_nisam_write_keypage(info,keyinfo,page,temp_buff))
- goto err;
- }
- my_afree((byte*) temp_buff);
- DBUG_RETURN(error);
-err:
- my_afree((byte*) temp_buff);
- DBUG_PRINT("exit",("Error: %d",my_errno));
- DBUG_RETURN (-1);
-} /* w_search */
-
-
- /* Insert new key at right of key_pos */
- /* Returns 2 if key contains key to upper level */
-
-int _nisam_insert(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff,
- uchar *father_buff, uchar *father_key_pos, ulong father_page)
-{
- uint a_length,t_length,nod_flag;
- uchar *endpos;
- int key_offset;
- S_PARAM s_temp;
- DBUG_ENTER("_nisam_insert");
- DBUG_PRINT("enter",("key_pos: %lx",key_pos));
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key););
-
- nod_flag=test_if_nod(anc_buff);
- a_length=getint(anc_buff);
- endpos= anc_buff+ a_length;
- t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,
- (key_pos == endpos ? (uchar*) 0 : key_pos),
- (key_pos == anc_buff+2+nod_flag ?
- (uchar*) 0 : key_buff),key,&s_temp);
-#ifndef DBUG_OFF
- if (key_pos != anc_buff+2+nod_flag)
- DBUG_DUMP("prev_key",(byte*) key_buff,_nisam_keylength(keyinfo,key_buff));
- if (keyinfo->base.flag & HA_PACK_KEY)
- {
- DBUG_PRINT("test",("t_length: %d ref_len: %d",
- t_length,s_temp.ref_length));
- DBUG_PRINT("test",("n_ref_len: %d n_length: %d key: %lx",
- s_temp.n_ref_length,s_temp.n_length,s_temp.key));
- }
-#endif
- key_offset = (uint)(endpos-key_pos);
- if((int) t_length < 0)
- key_offset += (int) t_length;
- if (key_offset < 0)
- {
- DBUG_PRINT("error",("Found a bug: negative key_offset %d\n", key_offset));
- DBUG_RETURN(-1);
- }
- if ((int) t_length >= 0) /* t_length is almost always > 0 */
- bmove_upp((byte*) endpos+t_length,(byte*) endpos,(uint)key_offset );
- else
- {
- /* This may happen if a key was deleted and the next key could be
- compressed better than before */
- DBUG_DUMP("anc_buff",(byte*) anc_buff,a_length);
-
- bmove(key_pos,key_pos - (int) t_length,(uint)key_offset);
- }
- _nisam_store_key(keyinfo,key_pos,&s_temp);
- a_length+=t_length;
- putint(anc_buff,a_length,nod_flag);
- if (a_length <= keyinfo->base.block_length)
- DBUG_RETURN(0); /* There is room on page */
-
- /* Page is full */
-
- if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)) &&
- father_buff)
- DBUG_RETURN(_nisam_balance_page(info,keyinfo,key,anc_buff,father_buff,
- father_key_pos,father_page));
- DBUG_RETURN(_nisam_splitt_page(info,keyinfo,key,anc_buff,key_buff));
-} /* _nisam_insert */
-
-
- /* splitt a full page in two and assign emerging item to key */
-
-int _nisam_splitt_page(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, uchar *buff, uchar *key_buff)
-{
- uint length,a_length,key_ref_length,t_length,nod_flag;
- uchar *key_pos,*pos;
- ulong new_pos;
- S_PARAM s_temp;
- DBUG_ENTER("ni_splitt_page");
- DBUG_DUMP("buff",(byte*) buff,getint(buff));
-
- nod_flag=test_if_nod(buff);
- key_ref_length=2+nod_flag;
- key_pos=_nisam_find_half_pos(info,keyinfo,buff,key_buff);
- length=(uint) (key_pos-buff);
- a_length=getint(buff);
- putint(buff,length,nod_flag);
- info->page_changed=1;
-
- /* Correct new page pointer */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff));
- if (nod_flag)
- {
- DBUG_PRINT("test",("Splitting nod"));
- pos=key_pos-nod_flag;
- memcpy((byte*) info->buff+2,(byte*) pos,(size_t) nod_flag);
- }
-
- /* Move midle item to key and pointer to new page */
- if ((new_pos=_nisam_new(info,keyinfo)) == NI_POS_ERROR)
- DBUG_RETURN(-1);
- _nisam_kpointer(info,_nisam_move_key(keyinfo,key,key_buff),new_pos);
-
- /* Store new page */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff));
- t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,(uchar *) 0, (uchar*) 0,
- key_buff, &s_temp);
- s_temp.n_length= *key_pos; /* Needed by ni_store_key */
- length=(uint) ((buff+a_length)-key_pos);
- memcpy((byte*) info->buff+key_ref_length+t_length,(byte*) key_pos,
- (size_t) length);
- _nisam_store_key(keyinfo,info->buff+key_ref_length,&s_temp);
- putint(info->buff,length+t_length+key_ref_length,nod_flag);
-
- if (_nisam_write_keypage(info,keyinfo,new_pos,info->buff))
- DBUG_RETURN(-1);
- DBUG_DUMP("key",(byte*) key,_nisam_keylength(keyinfo,key));
- DBUG_RETURN(2); /* Middle key up */
-} /* _nisam_splitt_page */
-
-
- /* find out how much more room a key will take */
-
-#ifdef QQ
-uint _nisam_get_pack_key_length(N_KEYDEF *keyinfo, uint nod_flag, uchar *key_pos, uchar *key_buff, uchar *key, S_PARAM *s_temp)
-
- /* If nod: Length of nod-pointer */
- /* Position to pos after key in buff */
- /* Last key before current key */
- /* Current key */
- /* How next key will be packed */
-{
- reg1 N_KEYSEG *keyseg;
- int length;
- uint key_length,ref_length,n_length,diff_flag,same_length;
- uchar *start,*end,*key_end;
-
- s_temp->key=key;
- if (!(keyinfo->base.flag & HA_PACK_KEY))
- return (s_temp->totlength=_nisam_keylength(keyinfo,key)+nod_flag);
- s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
- s_temp->prev_length=0;
-
- same_length=0; keyseg=keyinfo->seg;
- key_length=_nisam_keylength(keyinfo,key)+nod_flag;
-
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- diff_flag=1;
- end=key_end= key+ *key+1;
- if (key_buff)
- {
- if (*key == *key_buff && *key)
- same_length=1; /* Don't use key-pack if length == 0 */
- else if (*key > *key_buff)
- end=key+ *key_buff+1;
- key_buff++;
- }
- key++;
- }
- else
- {
- diff_flag=0;
- key_end=end= key+keyseg->base.length;
- }
-
- start=key;
- if (key_buff)
- while (key < end && *key == *key_buff)
- {
- key++; key_buff++;
- }
-
- s_temp->key=key; s_temp->key_length= (uint) (key_end-key);
-
- if (same_length && key == key_end)
- {
- s_temp->ref_length=128;
- length=(int) key_length-(int)(key_end-start); /* Same as prev key */
- if (key_pos)
- {
- s_temp->n_length= *key_pos;
- key_pos=0; /* Can't combine with next */
- }
- }
- else
- {
- if (start != key)
- { /* Starts as prev key */
- s_temp->ref_length= (uint) (key-start)+128;
- length=(int) (1+key_length-(uint) (key-start));
- }
- else
- length=(int) (key_length+ (1-diff_flag)); /* Not packed key */
- }
- s_temp->totlength=(uint) length;
-
- DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d",
- key_length,length,s_temp->key_length));
-
- /* If something after that is not 0 length test if we can combine */
-
- if (key_pos && (n_length= *key_pos))
- {
- key_pos++;
- ref_length=0;
- if (n_length & 128)
- {
- if ((ref_length=n_length & 127))
- if (diff_flag)
- n_length= *key_pos++; /* Length of key-part */
- else
- n_length=keyseg->base.length - ref_length;
- }
- else
- if (*start == *key_pos && diff_flag && start != key_end)
- length++; /* One new pos for ref.len */
-
- DBUG_PRINT("test",("length: %d key_pos: %lx",length,key_pos));
- if (n_length != 128)
- { /* Not same key after */
- key=start+ref_length;
- while (n_length > 0 && key < key_end && *key == *key_pos)
- {
- key++; key_pos++;
- ref_length++;
- n_length--;
- length--; /* We gained one char */
- }
-
- if (n_length == 0 && diff_flag)
- {
- n_length=128; /* Same as prev key */
- length--; /* We don't need key-length */
- }
- else if (ref_length)
- s_temp->n_ref_length=ref_length | 128;
- }
- s_temp->n_length=n_length;
- }
- return (uint) length;
-} /* _nisam_get_pack_key_length */
-
-#else
-
-uint
-_nisam_get_pack_key_length(N_KEYDEF *keyinfo,
- uint nod_flag, /* If nod: Length of nod-pointer */
- uchar *key_pos, /* Position to pos after key in buff */
- uchar *key_buff,/* Last key before current key */
- uchar *key, /* Current key */
- S_PARAM *s_temp/* How next key will be packed */
- )
-{
- reg1 N_KEYSEG *keyseg;
- int length;
- uint key_length,ref_length,n_length,diff_flag,same_length,org_key_length=0;
- uchar *start,*end,*key_end;
-
- s_temp->key=key;
- if (!(keyinfo->base.flag & HA_PACK_KEY))
- return (s_temp->totlength=_nisam_keylength(keyinfo,key)+nod_flag);
- s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
-
- same_length=0; keyseg=keyinfo->seg;
- key_length=_nisam_keylength(keyinfo,key)+nod_flag;
- s_temp->prev_key=key_buff;
-
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- diff_flag=1;
- end=key_end= key+ *key+1;
- if (key_buff)
- {
- org_key_length= (uint) *key_buff;
- if (*key == *key_buff && *key)
- same_length=1; /* Don't use key-pack if length == 0 */
- else if (*key > *key_buff)
- end=key+ org_key_length+1;
- key_buff++;
- }
- key++;
- }
- else
- {
- diff_flag=0;
- key_end=end= key+(org_key_length=keyseg->base.length);
- }
-
- start=key;
- if (key_buff)
- while (key < end && *key == *key_buff)
- {
- key++; key_buff++;
- }
-
- s_temp->key=key; s_temp->key_length= (uint) (key_end-key);
-
- if (same_length && key == key_end)
- {
- s_temp->ref_length=128;
- length=(int) key_length-(int)(key_end-start); /* Same as prev key */
- if (key_pos)
- { /* Can't combine with next */
- s_temp->n_length= *key_pos; /* Needed by _nisam_store_key */
- key_pos=0;
- }
- }
- else
- {
- if (start != key)
- { /* Starts as prev key */
- s_temp->ref_length= (uint) (key-start)+128;
- length=(int) (1+key_length-(uint) (key-start));
- }
- else
- length=(int) (key_length+ (1-diff_flag)); /* Not packed key */
- }
- s_temp->totlength=(uint) length;
- s_temp->prev_length=0;
- DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d",
- key_length,length,s_temp->key_length));
-
- /* If something after that is not 0 length test if we can combine */
-
- if (key_pos && (n_length= *key_pos++))
- {
- if (n_length == 128)
- {
- /*
- We put a different key between two identical keys
- Extend next key to have same prefix as this key
- */
- if (s_temp->ref_length)
- { /* make next key longer */
- s_temp->part_of_prev_key= s_temp->ref_length;
- s_temp->prev_length= org_key_length - (s_temp->ref_length-128);
- s_temp->n_length= s_temp->prev_length;
- s_temp->prev_key+= diff_flag + (s_temp->ref_length - 128);
- length+= s_temp->prev_length+diff_flag;
- }
- else
- { /* Can't use prev key */
- s_temp->part_of_prev_key=0;
- s_temp->prev_length= org_key_length;
- s_temp->n_length= org_key_length;
- s_temp->prev_key+= diff_flag; /* To start of key */
- length+= org_key_length;
- }
- return (uint) length;
- }
-
- if (n_length & 128)
- {
- ref_length=n_length & 127;
- if (diff_flag) /* If SPACE_PACK */
- n_length= *key_pos++; /* Length of key-part */
- else
- n_length=keyseg->base.length - ref_length;
-
- /* Test if new keys has fewer characters that match the previous key */
- if (!s_temp->ref_length)
- { /* Can't use prev key */
- s_temp->part_of_prev_key= 0;
- s_temp->prev_length= ref_length;
- s_temp->n_length= n_length+ref_length;
- s_temp->prev_key+= diff_flag; /* To start of key */
- return (uint) length+ref_length-diff_flag;
- }
- if (ref_length+128 > s_temp->ref_length)
- {
- /* We must copy characters from the original key to the next key */
- s_temp->part_of_prev_key= s_temp->ref_length;
- s_temp->prev_length= ref_length+128 - s_temp->ref_length;
- s_temp->n_length= n_length + s_temp->prev_length;
- s_temp->prev_key+= diff_flag + s_temp->ref_length -128;
- return (uint) length + s_temp->prev_length;
- }
- }
- else
- {
- ref_length=0;
- if (*start == *key_pos && diff_flag && start != key_end)
- length++; /* One new pos for ref.len */
- }
- DBUG_PRINT("test",("length: %d key_pos: %lx",length,key_pos));
-
- key=start+ref_length;
- while (n_length > 0 && key < key_end && *key == *key_pos)
- {
- key++; key_pos++;
- ref_length++;
- n_length--;
- length--; /* We gained one char */
- }
-
- if (n_length == 0 && diff_flag)
- {
- n_length=128; /* Same as prev key */
- length--; /* We don't need key-length */
- }
- else if (ref_length)
- s_temp->n_ref_length=ref_length | 128;
- s_temp->n_length=n_length;
- }
- return (uint) length;
-} /* _nisam_get_pack_key_length */
-#endif
-
-
- /* store a key in page-buffert */
-
-void _nisam_store_key(N_KEYDEF *keyinfo, register uchar *key_pos,
- register S_PARAM *s_temp)
-{
- uint length;
- uchar *start;
-
- if (! (keyinfo->base.flag & HA_PACK_KEY))
- {
- memcpy((byte*) key_pos,(byte*) s_temp->key,(size_t) s_temp->totlength);
- return;
- }
- start=key_pos;
- if ((*key_pos=(uchar) s_temp->ref_length))
- key_pos++;
- if (s_temp->ref_length == 0 ||
- (s_temp->ref_length > 128 &&
- (keyinfo->seg[0].base.flag & HA_SPACE_PACK)))
- *key_pos++= (uchar) s_temp->key_length;
- bmove((byte*) key_pos,(byte*) s_temp->key,
- (length=s_temp->totlength-(uint) (key_pos-start)));
- key_pos+=length;
-
- if (s_temp->prev_length)
- {
- /* Extend next key because new key didn't have same prefix as prev key */
- if (s_temp->part_of_prev_key)
- *key_pos++ = s_temp->part_of_prev_key;
- if (keyinfo->seg[0].base.flag & HA_SPACE_PACK)
- *key_pos++= s_temp->n_length;
- memcpy(key_pos, s_temp->prev_key, s_temp->prev_length);
- return;
- }
-
- if ((*key_pos = (uchar) s_temp->n_ref_length))
- {
- if (! (keyinfo->seg[0].base.flag & HA_SPACE_PACK))
- return; /* Don't save keylength */
- key_pos++; /* Store ref for next key */
- }
- *key_pos = (uchar) s_temp->n_length;
- return;
-} /* _nisam_store_key */
-
-
- /* Calculate how to much to move to split a page in two */
- /* Returns pointer and key for get_key() to get mid key */
- /* There is at last 2 keys after pointer in buff */
-
-uchar *_nisam_find_half_pos(N_INFO *info, N_KEYDEF *keyinfo, uchar *page, uchar *key)
-{
- uint keys,length,key_ref_length,nod_flag;
- uchar *end,*lastpos;
- DBUG_ENTER("_nisam_find_half_pos");
-
- nod_flag=test_if_nod(page);
- key_ref_length=2+nod_flag;
- length=getint(page)-key_ref_length;
- page+=key_ref_length;
- if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
- {
- keys=(length/(keyinfo->base.keylength+nod_flag))/2;
- DBUG_RETURN(page+keys*(keyinfo->base.keylength+nod_flag));
- }
-
- end=page+length/2-key_ref_length; /* This is aprox. half */
- *key='\0';
- do
- {
- lastpos=page;
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,key));
- } while (page < end);
-
- DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end));
- DBUG_RETURN(lastpos);
-} /* _nisam_find_half_pos */
-
-
- /* Balance page with not packed keys with page on right/left */
- /* returns 0 if balance was done */
-
-static int _nisam_balance_page(register N_INFO *info, N_KEYDEF *keyinfo,
- uchar *key, uchar *curr_buff, uchar *father_buff,
- uchar *father_key_pos, ulong father_page)
-{
- my_bool right;
- uint k_length,father_length,father_keylength,nod_flag,curr_keylength,
- right_length,left_length,new_right_length,new_left_length,extra_length,
- length,keys;
- uchar *pos,*buff,*extra_buff;
- ulong next_page,new_pos;
- byte tmp_part_key[N_MAX_KEY_BUFF];
- DBUG_ENTER("_nisam_balance_page");
-
- k_length=keyinfo->base.keylength;
- father_length=getint(father_buff);
- father_keylength=k_length+info->s->base.key_reflength;
- nod_flag=test_if_nod(curr_buff);
- curr_keylength=k_length+nod_flag;
- info->page_changed=1;
-
- if ((father_key_pos != father_buff+father_length && (info->s->rnd++ & 1)) ||
- father_key_pos == father_buff+2+info->s->base.key_reflength)
- {
- right=1;
- next_page= _nisam_kpos(info->s->base.key_reflength,
- father_key_pos+father_keylength);
- buff=info->buff;
- DBUG_PRINT("test",("use right page: %lu",next_page));
- }
- else
- {
- right=0;
- father_key_pos-=father_keylength;
- next_page= _nisam_kpos(info->s->base.key_reflength,father_key_pos);
- /* Fix that curr_buff is to left */
- buff=curr_buff; curr_buff=info->buff;
- DBUG_PRINT("test",("use left page: %lu",next_page));
- } /* father_key_pos ptr to parting key */
-
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,info->buff,0))
- goto err;
- DBUG_DUMP("next",(byte*) info->buff,getint(info->buff));
-
- /* Test if there is room to share keys */
-
- left_length=getint(curr_buff);
- right_length=getint(buff);
- keys=(left_length+right_length-4-nod_flag*2)/curr_keylength;
-
- if ((right ? right_length : left_length) + curr_keylength <=
- keyinfo->base.block_length)
- { /* Merge buffs */
- new_left_length=2+nod_flag+(keys/2)*curr_keylength;
- new_right_length=2+nod_flag+((keys+1)/2)*curr_keylength;
- putint(curr_buff,new_left_length,nod_flag);
- putint(buff,new_right_length,nod_flag);
-
- if (left_length < new_left_length)
- { /* Move keys buff -> leaf */
- pos=curr_buff+left_length;
- memcpy((byte*) pos,(byte*) father_key_pos, (size_t) k_length);
- memcpy((byte*) pos+k_length, (byte*) buff+2,
- (size_t) (length=new_left_length - left_length - k_length));
- pos=buff+2+length;
- memcpy((byte*) father_key_pos,(byte*) pos,(size_t) k_length);
- bmove((byte*) buff+2,(byte*) pos+k_length,new_right_length);
- }
- else
- { /* Move keys -> buff */
-
- bmove_upp((byte*) buff+new_right_length,(byte*) buff+right_length,
- right_length-2);
- length=new_right_length-right_length-k_length;
- memcpy((byte*) buff+2+length,father_key_pos,(size_t) k_length);
- pos=curr_buff+new_left_length;
- memcpy((byte*) father_key_pos,(byte*) pos,(size_t) k_length);
- memcpy((byte*) buff+2,(byte*) pos+k_length,(size_t) length);
- }
-
- if (_nisam_write_keypage(info,keyinfo,next_page,info->buff) ||
- _nisam_write_keypage(info,keyinfo,father_page,father_buff))
- goto err;
- DBUG_RETURN(0);
- }
-
- /* curr_buff[] and buff[] are full, lets splitt and make new nod */
-
- extra_buff=info->buff+info->s->base.max_block;
- new_left_length=new_right_length=2+nod_flag+(keys+1)/3*curr_keylength;
- if (keys == 5) /* Too few keys to balance */
- new_left_length-=curr_keylength;
- extra_length=nod_flag+left_length+right_length-new_left_length-new_right_length-curr_keylength;
- DBUG_PRINT("info",("left_length: %d right_length: %d new_left_length: %d new_right_length: %d extra_length: %d",
- left_length, right_length,
- new_left_length, new_right_length,
- extra_length));
- putint(curr_buff,new_left_length,nod_flag);
- putint(buff,new_right_length,nod_flag);
- putint(extra_buff,extra_length+2,nod_flag);
-
- /* move first largest keys to new page */
- pos=buff+right_length-extra_length;
- memcpy((byte*) extra_buff+2,pos,(size_t) extra_length);
-
- /* Save new parting key */
- memcpy(tmp_part_key, pos-k_length,k_length);
-
- /* Make place for new keys */
- bmove_upp((byte*) buff+new_right_length,(byte*) pos-k_length,
- right_length-extra_length-k_length-2);
- /* Copy keys from left page */
- pos= curr_buff+new_left_length;
- memcpy((byte*) buff+2,(byte*) pos+k_length,
- (size_t) (length=left_length-new_left_length-k_length));
- /* Copy old parting key */
- memcpy((byte*) buff+2+length,father_key_pos,(size_t) k_length);
-
- /* Move new parting keys up */
- memcpy((byte*) (right ? key : father_key_pos),pos, (size_t) k_length);
- memcpy((byte*) (right ? father_key_pos : key), tmp_part_key, k_length);
-
- if ((new_pos=_nisam_new(info,keyinfo)) == NI_POS_ERROR)
- goto err;
- _nisam_kpointer(info,key+k_length,new_pos);
- if (_nisam_write_keypage(info,keyinfo,(right ? new_pos : next_page),
- info->buff) ||
- _nisam_write_keypage(info,keyinfo,(right ? next_page : new_pos),extra_buff))
- goto err;
-
- DBUG_RETURN(1); /* Middle key up */
-
-err:
- DBUG_RETURN(-1);
-} /* _nisam_balance_page */
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index bb4d252f385..a4d616f936a 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -42,11 +42,11 @@ mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \
bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \
strtoull.lo strtoll.lo llstr.lo my_vsnprintf.lo \
ctype.lo ctype-simple.lo ctype-bin.lo ctype-mb.lo \
- ctype-big5.lo ctype-cp932.lo ctype-czech.lo ctype-euc_kr.lo \
+ ctype-big5.lo ctype-czech.lo ctype-cp932.lo ctype-eucjpms.lo ctype-euc_kr.lo \
ctype-win1250ch.lo ctype-utf8.lo ctype-extra.lo \
ctype-ucs2.lo ctype-gb2312.lo ctype-gbk.lo \
ctype-sjis.lo ctype-tis620.lo ctype-ujis.lo \
- ctype-uca.lo xml.lo my_strtoll10.lo
+ ctype-uca.lo xml.lo my_strtoll10.lo str_alloc.lo
mystringsextra= strto.c
dbugobjects = dbug.lo # IT IS IN SAFEMALLOC.C sanity.lo
@@ -61,12 +61,14 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
mf_format.lo mf_path.lo mf_unixpath.lo my_fopen.lo \
my_symlink.lo my_fstream.lo \
mf_loadpath.lo my_pthread.lo my_thr_init.lo \
- thr_mutex.lo mulalloc.lo string.lo default.lo \
+ thr_mutex.lo mulalloc.lo string.lo \
+ default.lo default_modify.lo \
my_compress.lo array.lo my_once.lo list.lo my_net.lo \
charset.lo charset-def.lo hash.lo mf_iocache.lo \
mf_iocache2.lo my_seek.lo my_sleep.lo \
- my_pread.lo mf_cache.lo md5.lo sha1.lo\
- my_getopt.lo my_gethostbyname.lo my_port.lo
+ my_pread.lo mf_cache.lo md5.lo sha1.lo \
+ my_getopt.lo my_gethostbyname.lo my_port.lo \
+ my_rename.lo my_chsize.lo
sqlobjects = net.lo
sql_cmn_objects = pack.lo client.lo my_time.lo
@@ -81,6 +83,8 @@ CLEANFILES = $(target_libadd) $(SHLIBOBJS) \
$(target)
DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
+ -DDEFAULT_HOME_ENV=MYSQL_HOME \
+ -DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" $(target_defs)
# The automatic dependencies miss this
diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h
index f53f054a28d..e0f093aa7c9 100644
--- a/libmysql/client_settings.h
+++ b/libmysql/client_settings.h
@@ -21,7 +21,7 @@ extern my_string mysql_unix_port;
CLIENT_TRANSACTIONS | \
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
-sig_handler pipe_sig_handler(int sig);
+sig_handler my_pipe_sig_handler(int sig);
void read_user_name(char *name);
my_bool handle_local_infile(MYSQL *mysql, const char *net_filename);
@@ -32,7 +32,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename);
#if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD)
#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0;
-#define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler)
+#define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE, my_pipe_sig_handler)
#define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler);
#else
#define init_sigpipe_variables
@@ -43,7 +43,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename);
void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group);
void mysql_detach_stmt_list(LIST **stmt_list);
-MYSQL * STDCALL
+MYSQL *
cli_mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,ulong client_flag);
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 5fa94e5ff0d..9e1d70a47df 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -80,6 +80,8 @@ const char *client_errors[]=
"Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch",
"Prepared statement contains no metadata",
+ "Attempt to read a row while there is no result set associated with the statement",
+ "This feature is not implemented yet",
""
};
@@ -141,6 +143,8 @@ const char *client_errors[]=
"Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch",
"Prepared statement contains no metadata",
+ "Attempt to read a row while there is no result set associated with the statement",
+ "This feature is not implemented yet",
""
};
@@ -200,12 +204,40 @@ const char *client_errors[]=
"Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch",
"Prepared statement contains no metadata",
+ "Attempt to read a row while there is no result set associated with the statement",
+ "This feature is not implemented yet",
""
};
#endif
+/*
+ Register client error messages for use with my_error().
+
+ SYNOPSIS
+ init_client_errs()
+
+ RETURN
+ void
+*/
+
void init_client_errs(void)
{
- my_errmsg[CLIENT_ERRMAP] = &client_errors[0];
+ (void) my_error_register(client_errors, CR_ERROR_FIRST, CR_ERROR_LAST);
+}
+
+
+/*
+ Unregister client error messages.
+
+ SYNOPSIS
+ finish_client_errs()
+
+ RETURN
+ void
+*/
+
+void finish_client_errs(void)
+{
+ (void) my_error_unregister(CR_ERROR_FIRST, CR_ERROR_LAST);
}
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 7c6d140d2ef..11ee7284cbf 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -92,7 +92,7 @@ my_bool net_flush(NET *net);
#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
static void append_wild(char *to,char *end,const char *wild);
-sig_handler pipe_sig_handler(int sig);
+sig_handler my_pipe_sig_handler(int sig);
static my_bool mysql_client_init= 0;
static my_bool org_my_init_done= 0;
@@ -186,6 +186,7 @@ void STDCALL mysql_server_end()
}
else
mysql_thread_end();
+ finish_client_errs();
free_charsets();
mysql_client_init= org_my_init_done= 0;
#ifdef EMBEDDED_SERVER
@@ -301,11 +302,11 @@ mysql_debug(const char *debug __attribute__((unused)))
**************************************************************************/
sig_handler
-pipe_sig_handler(int sig __attribute__((unused)))
+my_pipe_sig_handler(int sig __attribute__((unused)))
{
DBUG_PRINT("info",("Hit by signal %d",sig));
#ifdef DONT_REMEMBER_SIGNAL
- (void) signal(SIGPIPE,pipe_sig_handler);
+ (void) signal(SIGPIPE, my_pipe_sig_handler);
#endif
}
@@ -326,6 +327,7 @@ my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
DBUG_ENTER("mysql_master_send_query");
if (!master->net.vio && !mysql_real_connect(master,0,0,0,0,0,0,0))
DBUG_RETURN(1);
+ master->reconnect= 1;
mysql->last_used_con = master;
DBUG_RETURN(simple_command(master, COM_QUERY, q, length, 1));
}
@@ -360,6 +362,7 @@ my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
if (!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0,
0,0,0,0))
DBUG_RETURN(1);
+ slave_to_use->reconnect= 1;
DBUG_RETURN(simple_command(slave_to_use, COM_QUERY, q, length, 1));
}
@@ -457,6 +460,7 @@ static my_bool get_slaves_from_master(MYSQL* mysql)
expand_error(mysql, CR_PROBE_MASTER_CONNECT);
DBUG_RETURN(1);
}
+ mysql->reconnect= 1;
if (mysql_query(mysql, "SHOW SLAVE HOSTS") ||
!(res = mysql_store_result(mysql)))
@@ -624,6 +628,7 @@ mysql_connect(MYSQL *mysql,const char *host,
if (mysql->free_me)
my_free((gptr) mysql,MYF(0));
}
+ mysql->reconnect= 1;
DBUG_RETURN(res);
}
}
@@ -1119,25 +1124,6 @@ mysql_fetch_field(MYSQL_RES *result)
/**************************************************************************
- Get column lengths of the current row
- If one uses mysql_use_result, res->lengths contains the length information,
- else the lengths are calculated from the offset between pointers.
-**************************************************************************/
-
-ulong * STDCALL
-mysql_fetch_lengths(MYSQL_RES *res)
-{
- MYSQL_ROW column;
-
- if (!(column=res->current_row))
- return 0; /* Something is wrong */
- if (res->data)
- (*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
- return res->lengths;
-}
-
-
-/**************************************************************************
Move to a specific row and column
**************************************************************************/
@@ -1516,41 +1502,22 @@ const char * STDCALL mysql_character_set_name(MYSQL *mysql)
return mysql->charset->csname;
}
-
-int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
+void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *csinfo)
{
- struct charset_info_st *cs;
- const char *save_csdir= charsets_dir;
+ csinfo->number = mysql->charset->number;
+ csinfo->state = mysql->charset->state;
+ csinfo->csname = mysql->charset->csname;
+ csinfo->name = mysql->charset->name;
+ csinfo->comment = mysql->charset->comment;
+ csinfo->mbminlen = mysql->charset->mbminlen;
+ csinfo->mbmaxlen = mysql->charset->mbmaxlen;
if (mysql->options.charset_dir)
- charsets_dir= mysql->options.charset_dir;
-
- if (strlen(cs_name) < MY_CS_NAME_SIZE &&
- (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
- {
- char buff[MY_CS_NAME_SIZE + 10];
- charsets_dir= save_csdir;
- sprintf(buff, "SET NAMES %s", cs_name);
- if (!mysql_query(mysql, buff))
- {
- mysql->charset= cs;
- }
- }
+ csinfo->dir = mysql->options.charset_dir;
else
- {
- char cs_dir_name[FN_REFLEN];
- get_charsets_dir(cs_dir_name);
- mysql->net.last_errno= CR_CANT_READ_CHARSET;
- strmov(mysql->net.sqlstate, unknown_sqlstate);
- my_snprintf(mysql->net.last_error, sizeof(mysql->net.last_error) - 1,
- ER(mysql->net.last_errno), cs_name, cs_dir_name);
-
- }
- charsets_dir= save_csdir;
- return mysql->net.last_errno;
+ csinfo->dir = charsets_dir;
}
-
uint STDCALL mysql_thread_safe(void)
{
#ifdef THREAD
@@ -1631,14 +1598,16 @@ mysql_hex_string(char *to, const char *from, ulong length)
ulong STDCALL
mysql_escape_string(char *to,const char *from,ulong length)
{
- return escape_string_for_mysql(default_charset_info, to, from, length);
+ return escape_string_for_mysql(default_charset_info, to, 0, from, length);
}
ulong STDCALL
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
ulong length)
{
- return escape_string_for_mysql(mysql->charset, to, from, length);
+ if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
+ return escape_quotes_for_mysql(mysql->charset, to, 0, from, length);
+ return escape_string_for_mysql(mysql->charset, to, 0, from, length);
}
@@ -1758,6 +1727,9 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
/******************* Declarations ***********************************/
+/* Default number of rows fetched per one COM_STMT_FETCH command. */
+
+#define DEFAULT_PREFETCH_ROWS (ulong) 1
/*
These functions are called by function pointer MYSQL_STMT::read_row_func.
@@ -1769,13 +1741,24 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
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_from_cursor(MYSQL_STMT *stmt, unsigned char **row);
static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row);
+static int stmt_read_row_no_result_set(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);
+static my_bool setup_one_fetch_function(MYSQL_BIND *bind, MYSQL_FIELD *field);
+
+/* Auxilary function used to reset statement handle. */
+
+#define RESET_SERVER_SIDE 1
+#define RESET_LONG_DATA 2
+#define RESET_STORE_RESULT 4
+
+static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags);
/*
Maximum sizes of MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME
@@ -1799,6 +1782,20 @@ static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
#define MAX_DOUBLE_STRING_REP_LENGTH 331
+/* A macro to check truncation errors */
+
+#define IS_TRUNCATED(value, is_unsigned, min, max, umax) \
+ ((is_unsigned) ? (((value) > (umax) || (value) < 0) ? 1 : 0) : \
+ (((value) > (max) || (value) < (min)) ? 1 : 0))
+
+#define BIND_RESULT_DONE 1
+/*
+ We report truncations only if at least one of MYSQL_BIND::error
+ pointers is set. In this case stmt->bind_result_done |-ed with
+ this flag.
+*/
+#define REPORT_DATA_TRUNCATION 2
+
/**************** Misc utility functions ****************************/
/*
@@ -1842,7 +1839,6 @@ static void net_clear_error(NET *net)
}
}
-
static void stmt_clear_error(MYSQL_STMT *stmt)
{
if (stmt->last_errno)
@@ -1893,7 +1889,7 @@ void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
}
/*
- Read and unpack server reply to COM_PREPARE command (sent from
+ Read and unpack server reply to COM_STMT_PREPARE command (sent from
mysql_stmt_prepare).
SYNOPSIS
@@ -1910,12 +1906,14 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
{
uchar *pos;
uint field_count, param_count;
+ ulong packet_length;
MYSQL_DATA *fields_data;
- DBUG_ENTER("read_prepare_result");
+ DBUG_ENTER("cli_read_prepare_result");
mysql= mysql->last_used_con;
- if (net_safe_read(mysql) == packet_error)
+ if ((packet_length= net_safe_read(mysql)) == packet_error)
DBUG_RETURN(1);
+ mysql->warning_count= 0;
pos= (uchar*) mysql->net.read_pos;
stmt->stmt_id= uint4korr(pos+1); pos+= 5;
@@ -1923,6 +1921,8 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
field_count= uint2korr(pos); pos+= 2;
/* Number of placeholders in the statement */
param_count= uint2korr(pos); pos+= 2;
+ if (packet_length >= 12)
+ mysql->warning_count= uint2korr(pos+1);
if (param_count != 0)
{
@@ -1939,7 +1939,6 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
mysql->server_status|= SERVER_STATUS_IN_TRANS;
- mysql->extra_info= net_field_length_ll(&pos);
if (!(fields_data= (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,7)))
DBUG_RETURN(1);
if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root,
@@ -1947,9 +1946,10 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
mysql->server_capabilities)))
DBUG_RETURN(1);
}
- stmt->field_count= (uint) field_count;
+ stmt->field_count= field_count;
stmt->param_count= (ulong) param_count;
- mysql->warning_count= 0;
+ DBUG_PRINT("exit",("field_count: %u param_count: %u warning_count: %u",
+ field_count, param_count, (uint) mysql->warning_count));
DBUG_RETURN(0);
}
@@ -2006,7 +2006,8 @@ mysql_stmt_init(MYSQL *mysql)
stmt->list.data= stmt;
stmt->state= MYSQL_STMT_INIT_DONE;
stmt->mysql= mysql;
- stmt->read_row_func= stmt_read_row_no_data;
+ stmt->read_row_func= stmt_read_row_no_result_set;
+ stmt->prefetch_rows= DEFAULT_PREFETCH_ROWS;
/* The rest of statement members was bzeroed inside malloc */
DBUG_RETURN(stmt);
@@ -2065,7 +2066,8 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
/* This is second prepare with another statement */
char buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
- mysql_stmt_free_result(stmt);
+ if (reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT))
+ DBUG_RETURN(1);
/*
These members must be reset for API to
function in case of error or misuse.
@@ -2082,7 +2084,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
mysql_use_result it won't be freed in mysql_stmt_free_result and
we should get 'Commands out of sync' here.
*/
- if (simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1))
+ if (simple_command(mysql, COM_STMT_CLOSE, buff, 4, 1))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
@@ -2091,7 +2093,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
stmt->state= MYSQL_STMT_INIT_DONE;
}
- if (simple_command(mysql, COM_PREPARE, query, length, 1))
+ if (simple_command(mysql, COM_STMT_PREPARE, query, length, 1))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
@@ -2175,7 +2177,7 @@ static unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
/*
Update result set columns metadata if it was sent again in
- reply to COM_EXECUTE.
+ reply to COM_STMT_EXECUTE.
*/
static void update_stmt_fields(MYSQL_STMT *stmt)
@@ -2183,6 +2185,7 @@ 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;
+ MYSQL_BIND *bind= stmt->bind_result_done ? stmt->bind : 0;
DBUG_ASSERT(stmt->field_count == stmt->mysql->field_count);
@@ -2193,6 +2196,11 @@ static void update_stmt_fields(MYSQL_STMT *stmt)
stmt_field->type = field->type;
stmt_field->flags = field->flags;
stmt_field->decimals = field->decimals;
+ if (bind)
+ {
+ /* Ignore return value: it should be 0 if bind_result succeeded. */
+ (void) setup_one_fetch_function(bind++, stmt_field);
+ }
}
}
@@ -2484,7 +2492,7 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
/*
- Auxilary function to send COM_EXECUTE packet to server and read reply.
+ Auxilary function to send COM_STMT_EXECUTE packet to server and read reply.
Used from cli_stmt_execute, which is in turn used by mysql_stmt_execute.
*/
@@ -2495,13 +2503,13 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
char buff[4 /* size of stmt id */ +
5 /* execution flags */];
DBUG_ENTER("execute");
- DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
+ DBUG_DUMP("packet", packet, length);
mysql->last_used_con= mysql;
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
- buff[4]= (char) 0; /* no flags */
+ buff[4]= (char) stmt->flags;
int4store(buff+5, 1); /* iteration count */
- if (cli_advanced_command(mysql, COM_EXECUTE, buff, sizeof(buff),
+ if (cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
packet, length, 1) ||
(*mysql->methods->read_query_result)(mysql))
{
@@ -2509,6 +2517,7 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
DBUG_RETURN(1);
}
stmt->affected_rows= mysql->affected_rows;
+ stmt->server_status= mysql->server_status;
stmt->insert_id= mysql->insert_id;
DBUG_RETURN(0);
}
@@ -2679,6 +2688,58 @@ error:
return rc;
}
+
+/*
+ Fetch statement row using server side cursor.
+
+ SYNOPSIS
+ stmt_read_row_from_cursor()
+
+ RETURN VALUE
+ 0 success
+ 1 error
+ MYSQL_NO_DATA end of data
+*/
+
+static int
+stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
+{
+ if (stmt->data_cursor)
+ return stmt_read_row_buffered(stmt, row);
+ if (stmt->server_status & SERVER_STATUS_LAST_ROW_SENT)
+ stmt->server_status &= ~SERVER_STATUS_LAST_ROW_SENT;
+ else
+ {
+ MYSQL *mysql= stmt->mysql;
+ NET *net= &mysql->net;
+ MYSQL_DATA *result= &stmt->result;
+ char buff[4 /* statement id */ +
+ 4 /* number of rows to fetch */];
+
+ free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
+ result->data= NULL;
+ result->rows= 0;
+ /* Send row request to the server */
+ int4store(buff, stmt->stmt_id);
+ int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
+ if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
+ NullS, 0, 1))
+ {
+ set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
+ return 1;
+ }
+ if (cli_read_binary_rows(stmt))
+ return 1;
+ stmt->server_status= mysql->server_status;
+
+ stmt->data_cursor= result->data;
+ return stmt_read_row_buffered(stmt, row);
+ }
+ *row= 0;
+ return MYSQL_NO_DATA;
+}
+
+
/*
Default read row function to not SIGSEGV in client in
case of wrong sequence of API calls.
@@ -2688,14 +2749,17 @@ static int
stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)),
unsigned char **row __attribute__((unused)))
{
- if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
- {
- set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate);
- return 1;
- }
return MYSQL_NO_DATA;
}
+static int
+stmt_read_row_no_result_set(MYSQL_STMT *stmt __attribute__((unused)),
+ unsigned char **row __attribute__((unused)))
+{
+ set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate);
+ return 1;
+}
+
/*
Get/set statement attributes
@@ -2720,10 +2784,30 @@ 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;
+ case STMT_ATTR_CURSOR_TYPE:
+ {
+ ulong cursor_type;
+ cursor_type= value ? *(ulong*) value : 0UL;
+ if (cursor_type > (ulong) CURSOR_TYPE_READ_ONLY)
+ goto err_not_implemented;
+ stmt->flags= cursor_type;
+ break;
+ }
+ case STMT_ATTR_PREFETCH_ROWS:
+ {
+ ulong prefetch_rows= value ? *(ulong*) value : DEFAULT_PREFETCH_ROWS;
+ if (value == 0)
+ return TRUE;
+ stmt->prefetch_rows= prefetch_rows;
+ break;
+ }
default:
- return TRUE;
+ goto err_not_implemented;
}
return FALSE;
+err_not_implemented:
+ set_stmt_error(stmt, CR_NOT_IMPLEMENTED, unknown_sqlstate);
+ return TRUE;
}
@@ -2733,7 +2817,13 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
{
switch (attr_type) {
case STMT_ATTR_UPDATE_MAX_LENGTH:
- *(unsigned long *) value= stmt->update_max_length;
+ *(ulong*) value= stmt->update_max_length;
+ break;
+ case STMT_ATTR_CURSOR_TYPE:
+ *(ulong*) value= stmt->flags;
+ break;
+ case STMT_ATTR_PREFETCH_ROWS:
+ *(ulong*) value= stmt->prefetch_rows;
break;
default:
return TRUE;
@@ -2797,7 +2887,8 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
DBUG_RETURN(1);
}
- mysql_stmt_free_result(stmt);
+ if (reset_stmt_handle(stmt, RESET_STORE_RESULT))
+ DBUG_RETURN(1);
/*
No need to check for stmt->state: if the statement wasn't
prepared we'll get 'unknown statement handler' error from server.
@@ -2827,7 +2918,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
- if data dictionary changed between prepare and execute, for
example a table used in the query was altered.
Note, that now (4.1.3) we always send metadata in reply to
- COM_EXECUTE (even if it is not necessary), so either this or
+ COM_STMT_EXECUTE (even if it is not necessary), so either this or
previous branch always works.
TODO: send metadata only when it's really necessary and add a warning
'Metadata changed' when it's sent twice.
@@ -2838,9 +2929,28 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
stmt->state= MYSQL_STMT_EXECUTE_DONE;
if (stmt->field_count)
{
- stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
- stmt->unbuffered_fetch_cancelled= FALSE;
- stmt->read_row_func= stmt_read_row_unbuffered;
+ if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
+ {
+ mysql->status= MYSQL_STATUS_READY;
+ stmt->read_row_func= stmt_read_row_from_cursor;
+ }
+ else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
+ {
+ /*
+ This is a single-row result set, a result set with no rows, EXPLAIN,
+ SHOW VARIABLES, or some other command which either a) bypasses the
+ cursors framework in the server and writes rows directly to the
+ network or b) is more efficient if all (few) result set rows are
+ precached on client and server's resources are freed.
+ */
+ DBUG_RETURN(mysql_stmt_store_result(stmt));
+ }
+ else
+ {
+ stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
+ stmt->unbuffered_fetch_cancelled= FALSE;
+ stmt->read_row_func= stmt_read_row_unbuffered;
+ }
}
DBUG_RETURN(0);
}
@@ -3154,8 +3264,11 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
param->store_param_func= store_param_str;
/*
For variable length types user must set either length or
@@ -3275,8 +3388,9 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
Note that we don't get any ok packet from the server in this case
This is intentional to save bandwidth.
*/
- if ((*mysql->methods->advanced_command)(mysql, COM_LONG_DATA, buff,
- sizeof(buff), data, length, 1))
+ if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA,
+ buff, sizeof(buff), data,
+ length, 1))
{
set_stmt_errmsg(stmt, mysql->net.last_error,
mysql->net.last_errno, mysql->net.sqlstate);
@@ -3405,6 +3519,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
{
char *buffer= (char *)param->buffer;
int err= 0;
+ char *endptr= value + length;
/*
This function should support all target buffer types: the rest
@@ -3415,45 +3530,48 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
break;
case MYSQL_TYPE_TINY:
{
- uchar data= (uchar) my_strntol(&my_charset_latin1, value, length, 10,
- NULL, &err);
- *buffer= data;
+ longlong data= my_strtoll10(value, &endptr, &err);
+ *param->error= (IS_TRUNCATED(data, param->is_unsigned,
+ INT_MIN8, INT_MAX8, UINT_MAX8) || err > 0);
+ *buffer= (uchar) data;
break;
}
case MYSQL_TYPE_SHORT:
{
- short data= (short) my_strntol(&my_charset_latin1, value, length, 10,
- NULL, &err);
- shortstore(buffer, data);
+ longlong data= my_strtoll10(value, &endptr, &err);
+ *param->error= (IS_TRUNCATED(data, param->is_unsigned,
+ INT_MIN16, INT_MAX16, UINT_MAX16) || err > 0);
+ shortstore(buffer, (short) data);
break;
}
case MYSQL_TYPE_LONG:
{
- int32 data= (int32)my_strntol(&my_charset_latin1, value, length, 10,
- NULL, &err);
- longstore(buffer, data);
+ longlong data= my_strtoll10(value, &endptr, &err);
+ *param->error= (IS_TRUNCATED(data, param->is_unsigned,
+ INT_MIN32, INT_MAX32, UINT_MAX32) || err > 0);
+ longstore(buffer, (int32) data);
break;
}
case MYSQL_TYPE_LONGLONG:
{
- longlong data= my_strntoll(&my_charset_latin1, value, length, 10,
- NULL, &err);
+ longlong data= my_strtoll10(value, &endptr, &err);
+ *param->error= param->is_unsigned ? err != 0 :
+ (err > 0 || (err == 0 && data < 0));
longlongstore(buffer, data);
break;
}
case MYSQL_TYPE_FLOAT:
{
- char *end_not_used;
- float data = (float) my_strntod(&my_charset_latin1, value, length,
- &end_not_used, &err);
- floatstore(buffer, data);
+ double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
+ float fdata= (float) data;
+ *param->error= (fdata != data) | test(err);
+ floatstore(buffer, fdata);
break;
}
case MYSQL_TYPE_DOUBLE:
{
- char *end_not_used;
- double data= my_strntod(&my_charset_latin1, value, length, &end_not_used,
- &err);
+ double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
+ *param->error= test(err);
doublestore(buffer, data);
break;
}
@@ -3461,6 +3579,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
{
MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
str_to_time(value, length, tm, &err);
+ *param->error= test(err);
break;
}
case MYSQL_TYPE_DATE:
@@ -3468,13 +3587,17 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
case MYSQL_TYPE_TIMESTAMP:
{
MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
- str_to_datetime(value, length, tm, 0, &err);
+ (void) str_to_datetime(value, length, tm, TIME_FUZZY_DATE, &err);
+ *param->error= test(err) && (param->buffer_type == MYSQL_TYPE_DATE &&
+ tm->time_type != MYSQL_TIMESTAMP_DATE);
break;
}
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
default:
{
/*
@@ -3495,6 +3618,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
copy_length= 0;
if (copy_length < param->buffer_length)
buffer[copy_length]= '\0';
+ *param->error= copy_length > param->buffer_length;
/*
param->length will always contain length of entire column;
number of copied bytes may be way different:
@@ -3517,44 +3641,79 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
*/
static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
- longlong value)
+ longlong value, my_bool is_unsigned)
{
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->error= IS_TRUNCATED(value, param->is_unsigned,
+ INT_MIN8, INT_MAX8, UINT_MAX8);
*(uchar *)param->buffer= (uchar) value;
break;
case MYSQL_TYPE_SHORT:
- shortstore(buffer, value);
+ *param->error= IS_TRUNCATED(value, param->is_unsigned,
+ INT_MIN16, INT_MAX16, UINT_MAX16);
+ shortstore(buffer, (short) value);
break;
case MYSQL_TYPE_LONG:
- longstore(buffer, value);
+ *param->error= IS_TRUNCATED(value, param->is_unsigned,
+ INT_MIN32, INT_MAX32, UINT_MAX32);
+ longstore(buffer, (int32) value);
break;
case MYSQL_TYPE_LONGLONG:
longlongstore(buffer, value);
+ *param->error= param->is_unsigned != is_unsigned && value < 0;
break;
case MYSQL_TYPE_FLOAT:
{
- float data= field_is_unsigned ? (float) ulonglong2double(value) :
- (float) value;
+ /*
+ We need to store data in the buffer before the truncation check to
+ workaround Intel FPU executive precision feature.
+ (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
+ AFAIU it does not guarantee to work.
+ */
+ float data;
+ if (is_unsigned)
+ data= (float) ulonglong2double(value);
+ else
+ data= (float) value;
floatstore(buffer, data);
+ *param->error= is_unsigned ?
+ ((ulonglong) value) != ((ulonglong) (*(float*) buffer)) :
+ ((longlong) value) != ((longlong) (*(float*) buffer));
break;
}
case MYSQL_TYPE_DOUBLE:
{
- double data= field_is_unsigned ? ulonglong2double(value) :
- (double) value;
+ double data;
+ if (is_unsigned)
+ data= ulonglong2double(value);
+ else
+ data= (double)value;
doublestore(buffer, data);
+ *param->error= is_unsigned ?
+ ((ulonglong) value) != ((ulonglong) (*(double*) buffer)) :
+ ((longlong) value) != ((longlong) (*(double*) buffer));
+ break;
+ }
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ {
+ int error;
+ value= number_to_datetime(value, (MYSQL_TIME *) buffer, TIME_FUZZY_DATE,
+ &error);
+ *param->error= test(error);
break;
}
default:
{
char buff[22]; /* Enough for longlong */
- char *end= longlong10_to_str(value, buff, field_is_unsigned ? 10: -10);
+ char *end= longlong10_to_str(value, buff, is_unsigned ? 10: -10);
/* Resort to string conversion which supports all typecodes */
uint length= (uint) (end-buff);
@@ -3571,7 +3730,6 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
}
}
-
/*
Convert double/float column to supplied buffer of any type.
@@ -3588,29 +3746,73 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
double value, int width)
{
char *buffer= (char *)param->buffer;
+ double val64 = (value < 0 ? -floor(-value) : floor(value));
switch (param->buffer_type) {
case MYSQL_TYPE_NULL: /* do nothing */
break;
case MYSQL_TYPE_TINY:
- *buffer= (uchar)value;
+ /*
+ We need to _store_ data in the buffer before the truncation check to
+ workaround Intel FPU executive precision feature.
+ (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
+ Sic: AFAIU it does not guarantee to work.
+ */
+ if (param->is_unsigned)
+ *buffer= (uint8) value;
+ else
+ *buffer= (int8) value;
+ *param->error= val64 != (param->is_unsigned ? (double)((uint8) *buffer) :
+ (double)((int8) *buffer));
break;
case MYSQL_TYPE_SHORT:
- shortstore(buffer, (short)value);
+ if (param->is_unsigned)
+ {
+ ushort data= (ushort) value;
+ shortstore(buffer, data);
+ }
+ else
+ {
+ short data= (short) value;
+ shortstore(buffer, data);
+ }
+ *param->error= val64 != (param->is_unsigned ? (double) (*(ushort*) buffer):
+ (double) (*(short*) buffer));
break;
case MYSQL_TYPE_LONG:
- longstore(buffer, (long)value);
- break;
+ if (param->is_unsigned)
+ {
+ uint32 data= (uint32) value;
+ longstore(buffer, data);
+ }
+ else
+ {
+ int32 data= (int32) value;
+ longstore(buffer, data);
+ }
+ *param->error= val64 != (param->is_unsigned ? (double) (*(uint32*) buffer):
+ (double) (*(int32*) buffer));
+ break;
case MYSQL_TYPE_LONGLONG:
- {
- longlong val= (longlong) value;
- longlongstore(buffer, val);
+ if (param->is_unsigned)
+ {
+ ulonglong data= (ulonglong) value;
+ longlongstore(buffer, data);
+ }
+ else
+ {
+ longlong data= (longlong) value;
+ longlongstore(buffer, data);
+ }
+ *param->error= val64 != (param->is_unsigned ?
+ ulonglong2double(*(ulonglong*) buffer) :
+ (double) (*(longlong*) buffer));
break;
- }
case MYSQL_TYPE_FLOAT:
{
float data= (float) value;
floatstore(buffer, data);
+ *param->error= (*(float*) buffer) != value;
break;
}
case MYSQL_TYPE_DOUBLE:
@@ -3664,18 +3866,47 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
*/
static void fetch_datetime_with_conversion(MYSQL_BIND *param,
+ MYSQL_FIELD *field,
MYSQL_TIME *time)
{
switch (param->buffer_type) {
case MYSQL_TYPE_NULL: /* do nothing */
break;
case MYSQL_TYPE_DATE:
+ *(MYSQL_TIME *)(param->buffer)= *time;
+ *param->error= time->time_type != MYSQL_TIMESTAMP_DATE;
+ break;
case MYSQL_TYPE_TIME:
+ *(MYSQL_TIME *)(param->buffer)= *time;
+ *param->error= time->time_type != MYSQL_TIMESTAMP_TIME;
+ break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
- /* XXX: should we copy only relevant members here? */
*(MYSQL_TIME *)(param->buffer)= *time;
+ /* No error: time and date are compatible with datetime */
break;
+ case MYSQL_TYPE_YEAR:
+ shortstore(param->buffer, time->year);
+ *param->error= 1;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ {
+ ulonglong value= TIME_to_ulonglong(time);
+ fetch_float_with_conversion(param, field,
+ ulonglong2double(value), DBL_DIG);
+ break;
+ }
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_LONGLONG:
+ {
+ longlong value= (longlong) TIME_to_ulonglong(time);
+ fetch_long_with_conversion(param, field, value, TRUE);
+ break;
+ }
default:
{
/*
@@ -3721,7 +3952,7 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
/* sic: we need to cast to 'signed char' as 'char' may be unsigned */
longlong data= field_is_unsigned ? (longlong) value :
(longlong) (signed char) value;
- fetch_long_with_conversion(param, field, data);
+ fetch_long_with_conversion(param, field, data, 0);
*row+= 1;
break;
}
@@ -3731,7 +3962,7 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
short value= sint2korr(*row);
longlong data= field_is_unsigned ? (longlong) (unsigned short) value :
(longlong) value;
- fetch_long_with_conversion(param, field, data);
+ fetch_long_with_conversion(param, field, data, 0);
*row+= 2;
break;
}
@@ -3741,14 +3972,15 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
int32 value= sint4korr(*row);
longlong data= field_is_unsigned ? (longlong) (uint32) value :
(longlong) value;
- fetch_long_with_conversion(param, field, data);
+ fetch_long_with_conversion(param, field, data, 0);
*row+= 4;
break;
}
case MYSQL_TYPE_LONGLONG:
{
longlong value= (longlong)sint8korr(*row);
- fetch_long_with_conversion(param, field, value);
+ fetch_long_with_conversion(param, field, value,
+ field->flags & UNSIGNED_FLAG);
*row+= 8;
break;
}
@@ -3773,7 +4005,7 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
MYSQL_TIME tm;
read_binary_date(&tm, row);
- fetch_datetime_with_conversion(param, &tm);
+ fetch_datetime_with_conversion(param, field, &tm);
break;
}
case MYSQL_TYPE_TIME:
@@ -3781,7 +4013,7 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
MYSQL_TIME tm;
read_binary_time(&tm, row);
- fetch_datetime_with_conversion(param, &tm);
+ fetch_datetime_with_conversion(param, field, &tm);
break;
}
case MYSQL_TYPE_DATETIME:
@@ -3790,7 +4022,7 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
MYSQL_TIME tm;
read_binary_datetime(&tm, row);
- fetch_datetime_with_conversion(param, &tm);
+ fetch_datetime_with_conversion(param, field, &tm);
break;
}
default:
@@ -3823,34 +4055,51 @@ static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
none
*/
-static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
+static void fetch_result_tinyint(MYSQL_BIND *param, MYSQL_FIELD *field,
+ uchar **row)
{
- *(uchar *)param->buffer= **row;
+ my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
+ uchar data= **row;
+ *(uchar *)param->buffer= data;
+ *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX8;
(*row)++;
}
-static void fetch_result_short(MYSQL_BIND *param, uchar **row)
+static void fetch_result_short(MYSQL_BIND *param, MYSQL_FIELD *field,
+ uchar **row)
{
- short value = (short)sint2korr(*row);
- shortstore(param->buffer, value);
+ my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
+ ushort data= (ushort) sint2korr(*row);
+ shortstore(param->buffer, data);
+ *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX16;
*row+= 2;
}
-static void fetch_result_int32(MYSQL_BIND *param, uchar **row)
+static void fetch_result_int32(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
{
- int32 value= (int32)sint4korr(*row);
- longstore(param->buffer, value);
+ my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
+ uint32 data= (uint32) sint4korr(*row);
+ longstore(param->buffer, data);
+ *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX32;
*row+= 4;
}
-static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
+static void fetch_result_int64(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
{
- longlong value= (longlong)sint8korr(*row);
- longlongstore(param->buffer, value);
+ my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
+ ulonglong data= (ulonglong) sint8korr(*row);
+ *param->error= param->is_unsigned != field_is_unsigned && data > LONGLONG_MAX;
+ longlongstore(param->buffer, data);
*row+= 8;
}
-static void fetch_result_float(MYSQL_BIND *param, uchar **row)
+static void fetch_result_float(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
{
float value;
float4get(value,*row);
@@ -3858,7 +4107,9 @@ static void fetch_result_float(MYSQL_BIND *param, uchar **row)
*row+= 4;
}
-static void fetch_result_double(MYSQL_BIND *param, uchar **row)
+static void fetch_result_double(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
{
double value;
float8get(value,*row);
@@ -3866,34 +4117,45 @@ static void fetch_result_double(MYSQL_BIND *param, uchar **row)
*row+= 8;
}
-static void fetch_result_time(MYSQL_BIND *param, uchar **row)
+static void fetch_result_time(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
{
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
read_binary_time(tm, row);
}
-static void fetch_result_date(MYSQL_BIND *param, uchar **row)
+static void fetch_result_date(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
{
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
read_binary_date(tm, row);
}
-static void fetch_result_datetime(MYSQL_BIND *param, uchar **row)
+static void fetch_result_datetime(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
{
MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
read_binary_datetime(tm, row);
}
-static void fetch_result_bin(MYSQL_BIND *param, uchar **row)
+static void fetch_result_bin(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ 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->error= copy_length < length;
*row+= length;
}
-static void fetch_result_str(MYSQL_BIND *param, uchar **row)
+static void fetch_result_str(MYSQL_BIND *param,
+ MYSQL_FIELD *field __attribute__((unused)),
+ uchar **row)
{
ulong length= net_field_length(row);
ulong copy_length= min(length, param->buffer_length);
@@ -3902,6 +4164,7 @@ static void fetch_result_str(MYSQL_BIND *param, uchar **row)
if (copy_length != param->buffer_length)
((uchar *)param->buffer)[copy_length]= '\0';
*param->length= length; /* return total length */
+ *param->error= copy_length < length;
*row+= length;
}
@@ -3943,6 +4206,220 @@ static void skip_result_string(MYSQL_BIND *param __attribute__((unused)),
/*
+ Check that two field types are binary compatible i. e.
+ have equal representation in the binary protocol and
+ require client-side buffers of the same type.
+
+ SYNOPSIS
+ is_binary_compatible()
+ type1 parameter type supplied by user
+ type2 field type, obtained from result set metadata
+
+ RETURN
+ TRUE or FALSE
+*/
+
+static my_bool is_binary_compatible(enum enum_field_types type1,
+ enum enum_field_types type2)
+{
+ static const enum enum_field_types
+ range1[]= { MYSQL_TYPE_SHORT, MYSQL_TYPE_YEAR, MYSQL_TYPE_NULL },
+ range2[]= { MYSQL_TYPE_INT24, MYSQL_TYPE_LONG, MYSQL_TYPE_NULL },
+ range3[]= { MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_NULL },
+ range4[]= { MYSQL_TYPE_ENUM, MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
+ MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY,
+ MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NULL };
+ static const enum enum_field_types
+ *range_list[]= { range1, range2, range3, range4 },
+ **range_list_end= range_list + sizeof(range_list)/sizeof(*range_list);
+ const enum enum_field_types **range, *type;
+
+ if (type1 == type2)
+ return TRUE;
+ for (range= range_list; range != range_list_end; ++range)
+ {
+ /* check that both type1 and type2 are in the same range */
+ bool type1_found= FALSE, type2_found= FALSE;
+ for (type= *range; *type != MYSQL_TYPE_NULL; type++)
+ {
+ type1_found|= type1 == *type;
+ type2_found|= type2 == *type;
+ }
+ if (type1_found || type2_found)
+ return type1_found && type2_found;
+ }
+ return FALSE;
+}
+
+
+/*
+ Setup a fetch function for one column of a result set.
+
+ SYNOPSIS
+ setup_one_fetch_function()
+ param output buffer descriptor
+ field column descriptor
+
+ DESCRIPTION
+ When user binds result set buffers or when result set
+ metadata is changed, we need to setup fetch (and possibly
+ conversion) functions for all columns of the result set.
+ In addition to that here we set up skip_result function, used
+ to update result set metadata in case when
+ STMT_ATTR_UPDATE_MAX_LENGTH attribute is set.
+ Notice that while fetch_result is chosen depending on both
+ field->type and param->type, skip_result depends on field->type
+ only.
+
+ RETURN
+ TRUE fetch function for this typecode was not found (typecode
+ is not supported by the client library)
+ FALSE success
+*/
+
+static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
+{
+ /* Setup data copy functions for the different supported types */
+ switch (param->buffer_type) {
+ case MYSQL_TYPE_NULL: /* for dummy binds */
+ /*
+ It's not binary compatible with anything the server can return:
+ no need to setup fetch_result, as it'll be reset anyway
+ */
+ *param->length= 0;
+ break;
+ case MYSQL_TYPE_TINY:
+ param->fetch_result= fetch_result_tinyint;
+ *param->length= 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ param->fetch_result= fetch_result_short;
+ *param->length= 2;
+ break;
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ param->fetch_result= fetch_result_int32;
+ *param->length= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ param->fetch_result= fetch_result_int64;
+ *param->length= 8;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ param->fetch_result= fetch_result_float;
+ *param->length= 4;
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ param->fetch_result= fetch_result_double;
+ *param->length= 8;
+ break;
+ case MYSQL_TYPE_TIME:
+ param->fetch_result= fetch_result_time;
+ *param->length= sizeof(MYSQL_TIME);
+ break;
+ case MYSQL_TYPE_DATE:
+ param->fetch_result= fetch_result_date;
+ *param->length= sizeof(MYSQL_TIME);
+ break;
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ param->fetch_result= fetch_result_datetime;
+ *param->length= sizeof(MYSQL_TIME);
+ break;
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_BIT:
+ DBUG_ASSERT(param->buffer_length != 0);
+ param->fetch_result= fetch_result_bin;
+ break;
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ DBUG_ASSERT(param->buffer_length != 0);
+ param->fetch_result= fetch_result_str;
+ break;
+ default:
+ return TRUE;
+ }
+ if (! is_binary_compatible(param->buffer_type, field->type))
+ param->fetch_result= fetch_result_with_conversion;
+
+ /* Setup skip_result functions (to calculate max_length) */
+ param->skip_result= skip_result_fixed;
+ switch (field->type) {
+ case MYSQL_TYPE_NULL: /* for dummy binds */
+ param->pack_length= 0;
+ field->max_length= 0;
+ break;
+ case MYSQL_TYPE_TINY:
+ param->pack_length= 1;
+ field->max_length= 4; /* as in '-127' */
+ break;
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_SHORT:
+ param->pack_length= 2;
+ field->max_length= 6; /* as in '-32767' */
+ break;
+ case MYSQL_TYPE_INT24:
+ field->max_length= 9; /* as in '16777216' or in '-8388607' */
+ param->pack_length= 4;
+ break;
+ case MYSQL_TYPE_LONG:
+ field->max_length= 11; /* '-2147483647' */
+ param->pack_length= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ field->max_length= 21; /* '18446744073709551616' */
+ param->pack_length= 8;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ param->pack_length= 4;
+ field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ param->pack_length= 8;
+ field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
+ break;
+ case MYSQL_TYPE_TIME:
+ field->max_length= 15; /* 19:23:48.123456 */
+ param->skip_result= skip_result_with_length;
+ case MYSQL_TYPE_DATE:
+ field->max_length= 10; /* 2003-11-11 */
+ param->skip_result= skip_result_with_length;
+ break;
+ break;
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ param->skip_result= skip_result_with_length;
+ field->max_length= MAX_DATE_STRING_REP_LENGTH;
+ break;
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_BIT:
+ param->skip_result= skip_result_string;
+ break;
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
Setup the bind buffers for resultset processing
*/
@@ -3984,142 +4461,30 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
This is to make the execute code easier
*/
if (!param->is_null)
- param->is_null= &param->internal_is_null;
+ param->is_null= &param->is_null_value;
if (!param->length)
- param->length= &param->internal_length;
+ param->length= &param->length_value;
+
+ if (!param->error)
+ param->error= &param->error_value;
param->param_number= param_count++;
param->offset= 0;
- /* Setup data copy functions for the different supported types */
- switch (param->buffer_type) {
- case MYSQL_TYPE_NULL: /* for dummy binds */
- *param->length= 0;
- break;
- case MYSQL_TYPE_TINY:
- param->fetch_result= fetch_result_tinyint;
- *param->length= 1;
- break;
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_YEAR:
- param->fetch_result= fetch_result_short;
- *param->length= 2;
- break;
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_LONG:
- param->fetch_result= fetch_result_int32;
- *param->length= 4;
- break;
- case MYSQL_TYPE_LONGLONG:
- param->fetch_result= fetch_result_int64;
- *param->length= 8;
- break;
- case MYSQL_TYPE_FLOAT:
- param->fetch_result= fetch_result_float;
- *param->length= 4;
- break;
- case MYSQL_TYPE_DOUBLE:
- param->fetch_result= fetch_result_double;
- *param->length= 8;
- break;
- case MYSQL_TYPE_TIME:
- param->fetch_result= fetch_result_time;
- *param->length= sizeof(MYSQL_TIME);
- break;
- case MYSQL_TYPE_DATE:
- param->fetch_result= fetch_result_date;
- *param->length= sizeof(MYSQL_TIME);
- break;
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIMESTAMP:
- param->fetch_result= fetch_result_datetime;
- *param->length= sizeof(MYSQL_TIME);
- break;
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- DBUG_ASSERT(param->buffer_length != 0);
- param->fetch_result= fetch_result_bin;
- break;
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- DBUG_ASSERT(param->buffer_length != 0);
- param->fetch_result= fetch_result_str;
- break;
- default:
- strmov(stmt->sqlstate, unknown_sqlstate);
- sprintf(stmt->last_error,
- ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
- param->buffer_type, param_count);
- DBUG_RETURN(1);
- }
-
- /* Setup skip_result functions (to calculate max_length) */
- param->skip_result= skip_result_fixed;
- switch (field->type) {
- case MYSQL_TYPE_NULL: /* for dummy binds */
- param->pack_length= 0;
- field->max_length= 0;
- break;
- case MYSQL_TYPE_TINY:
- param->pack_length= 1;
- field->max_length= 4; /* as in '-127' */
- break;
- case MYSQL_TYPE_YEAR:
- case MYSQL_TYPE_SHORT:
- param->pack_length= 2;
- field->max_length= 6; /* as in '-32767' */
- break;
- case MYSQL_TYPE_INT24:
- field->max_length= 9; /* as in '16777216' or in '-8388607' */
- param->pack_length= 4;
- break;
- case MYSQL_TYPE_LONG:
- field->max_length= 11; /* '-2147483647' */
- param->pack_length= 4;
- break;
- case MYSQL_TYPE_LONGLONG:
- field->max_length= 21; /* '18446744073709551616' */
- param->pack_length= 8;
- break;
- case MYSQL_TYPE_FLOAT:
- param->pack_length= 4;
- field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
- break;
- case MYSQL_TYPE_DOUBLE:
- param->pack_length= 8;
- field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
- break;
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIMESTAMP:
- param->skip_result= skip_result_with_length;
- field->max_length= MAX_DATE_STRING_REP_LENGTH;
- break;
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- case MYSQL_TYPE_GEOMETRY:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- param->skip_result= skip_result_string;
- break;
- default:
+ if (setup_one_fetch_function(param, field))
+ {
strmov(stmt->sqlstate, unknown_sqlstate);
sprintf(stmt->last_error,
- ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
- field->type, param_count);
+ ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
+ field->type, param_count);
DBUG_RETURN(1);
}
}
- stmt->bind_result_done= TRUE;
+ stmt->bind_result_done= BIND_RESULT_DONE;
+ if (stmt->mysql->options.report_data_truncation)
+ stmt->bind_result_done|= REPORT_DATA_TRUNCATION;
+
DBUG_RETURN(0);
}
@@ -4133,6 +4498,7 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
MYSQL_BIND *bind, *end;
MYSQL_FIELD *field;
uchar *null_ptr, bit;
+ int truncation_count= 0;
/*
Precondition: if stmt->field_count is zero or row is NULL, read_row_*
function must return no data.
@@ -4155,26 +4521,25 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
bind < end ;
bind++, field++)
{
+ *bind->error= 0;
if (*null_ptr & bit)
{
/*
- We should set both inter_buffer and is_null to be able to see
+ We should set both row_ptr and is_null to be able to see
nulls in mysql_stmt_fetch_column. This is because is_null may point
to user data which can be overwritten between mysql_stmt_fetch and
mysql_stmt_fetch_column, and in this case nullness of column will be
lost. See mysql_stmt_fetch_column for details.
*/
- bind->inter_buffer= NULL;
+ bind->row_ptr= NULL;
*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
- fetch_result_with_conversion(bind, field, &row);
+ bind->row_ptr= row;
+ (*bind->fetch_result)(bind, field, &row);
+ truncation_count+= *bind->error;
}
if (!((bit<<=1) & 255))
{
@@ -4182,6 +4547,8 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
null_ptr++;
}
}
+ if (truncation_count && (stmt->bind_result_done & REPORT_DATA_TRUNCATION))
+ return MYSQL_DATA_TRUNCATED;
return 0;
}
@@ -4208,10 +4575,11 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
DBUG_ENTER("mysql_stmt_fetch");
if ((rc= (*stmt->read_row_func)(stmt, &row)) ||
- (rc= stmt_fetch_row(stmt, row)))
+ ((rc= stmt_fetch_row(stmt, row)) && rc != MYSQL_DATA_TRUNCATED))
{
stmt->state= MYSQL_STMT_PREPARE_DONE; /* XXX: this is buggy */
- stmt->read_row_func= stmt_read_row_no_data;
+ stmt->read_row_func= (rc == MYSQL_NO_DATA) ?
+ stmt_read_row_no_data : stmt_read_row_no_result_set;
}
else
{
@@ -4255,17 +4623,20 @@ int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
DBUG_RETURN(1);
}
- if (param->inter_buffer)
+ if (!bind->error)
+ bind->error= &bind->error_value;
+ *bind->error= 0;
+ if (param->row_ptr)
{
MYSQL_FIELD *field= stmt->fields+column;
- uchar *row= param->inter_buffer;
+ uchar *row= param->row_ptr;
bind->offset= offset;
if (bind->is_null)
*bind->is_null= 0;
if (bind->length) /* Set the length if non char/binary types */
*bind->length= *param->length;
else
- bind->length= &param->internal_length; /* Needed for fetch_result() */
+ bind->length= &param->length_value; /* Needed for fetch_result() */
fetch_result_with_conversion(bind, field, &row);
}
else
@@ -4511,18 +4882,26 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
DBUG_RETURN(stmt->result.rows);
}
-my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
-{
- MYSQL_DATA *result= &stmt->result;
- DBUG_ENTER("mysql_stmt_free_result");
- DBUG_ASSERT(stmt != 0);
+/*
+ Free the client side memory buffers, reset long data state
+ on client if necessary, and reset the server side statement if
+ this has been requested.
+*/
+static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
+{
+ /* If statement hasn't been prepared there is nothing to reset */
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
{
MYSQL *mysql= stmt->mysql;
+ MYSQL_DATA *result= &stmt->result;
- if (result->data)
+ /*
+ Reset stored result set if so was requested or it's a part
+ of cursor fetch.
+ */
+ if (result->data && (flags & RESET_STORE_RESULT))
{
/* Result buffered */
free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
@@ -4530,23 +4909,59 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
result->rows= 0;
stmt->data_cursor= NULL;
}
-
- if (mysql && stmt->field_count &&
- (int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
+ if (flags & RESET_LONG_DATA)
{
- if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
- mysql->unbuffered_fetch_owner= 0;
- if (mysql->status != MYSQL_STATUS_READY)
+ MYSQL_BIND *param= stmt->params, *param_end= param + stmt->param_count;
+ /* Clear long_data_used flags */
+ for (; param < param_end; param++)
+ param->long_data_used= 0;
+ }
+ stmt->read_row_func= stmt_read_row_no_result_set;
+ if (mysql)
+ {
+ if ((int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
{
- /* There is a result set and it belongs to this statement */
- (*mysql->methods->flush_use_result)(mysql);
- mysql->status= MYSQL_STATUS_READY;
+ if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
+ mysql->unbuffered_fetch_owner= 0;
+ if (stmt->field_count && mysql->status != MYSQL_STATUS_READY)
+ {
+ /* There is a result set and it belongs to this statement */
+ (*mysql->methods->flush_use_result)(mysql);
+ if (mysql->unbuffered_fetch_owner)
+ *mysql->unbuffered_fetch_owner= TRUE;
+ mysql->status= MYSQL_STATUS_READY;
+ }
+ }
+ if (flags & RESET_SERVER_SIDE)
+ {
+ /*
+ Reset the server side statement and close the server side
+ cursor if it exists.
+ */
+ char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
+ int4store(buff, stmt->stmt_id);
+ if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff,
+ sizeof(buff), 0, 0, 0))
+ {
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ mysql->net.sqlstate);
+ stmt->state= MYSQL_STMT_INIT_DONE;
+ return 1;
+ }
+ stmt_clear_error(stmt);
}
}
stmt->state= MYSQL_STMT_PREPARE_DONE;
- stmt->read_row_func= stmt_read_row_no_data;
}
- DBUG_RETURN(0);
+ return 0;
+}
+
+my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
+{
+ DBUG_ENTER("mysql_stmt_free_result");
+
+ /* Free the client side and close the server side cursor if there is one */
+ DBUG_RETURN(reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT));
}
/********************************************************************
@@ -4600,7 +5015,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
mysql->status= MYSQL_STATUS_READY;
}
int4store(buff, stmt->stmt_id);
- if ((rc= simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1)))
+ if ((rc= simple_command(mysql, COM_STMT_CLOSE, buff, 4, 1)))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
@@ -4619,34 +5034,10 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
{
- char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
- MYSQL *mysql;
- MYSQL_BIND *param, *param_end;
DBUG_ENTER("mysql_stmt_reset");
DBUG_ASSERT(stmt != 0);
-
- /* If statement hasnt been prepared there is nothing to reset */
- if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
- DBUG_RETURN(0);
-
- mysql= stmt->mysql->last_used_con;
- int4store(buff, stmt->stmt_id); /* Send stmt id to server */
- 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,
- mysql->net.sqlstate);
- DBUG_RETURN(1);
- }
-
- /* Clear long_data_used for next call (as we do in mysql_stmt_execute() */
- for (param= stmt->params, param_end= param + stmt->param_count;
- param < param_end;
- param++)
- param->long_data_used= 0;
- stmt_clear_error(stmt);
-
- DBUG_RETURN(0);
+ /* Reset the client and server sides of the prepared statement */
+ DBUG_RETURN(reset_stmt_handle(stmt, RESET_SERVER_SIDE | RESET_LONG_DATA));
}
/*
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index dce91c1e4c1..a469c67c466 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -1,5 +1,5 @@
LIBRARY LIBMYSQL
-DESCRIPTION 'MySQL 4.1 Client Library'
+DESCRIPTION 'MySQL 5.0 Client Library'
VERSION 6.0
EXPORTS
_dig_vec_lower
@@ -146,7 +146,9 @@ EXPORTS
mysql_rpl_query_type
mysql_slave_query
mysql_embedded
- mysql_set_character_set
mysql_server_init
mysql_server_end
- get_defaults_files
+ mysql_set_character_set
+ mysql_get_character_set_info
+ get_defaults_options
+ modify_defaults_file
diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am
index a76ef675189..65255066d45 100644
--- a/libmysql_r/Makefile.am
+++ b/libmysql_r/Makefile.am
@@ -24,10 +24,8 @@ target = libmysqlclient_r.la
target_defs = -DDONT_USE_RAID -DMYSQL_CLIENT @LIB_EXTRA_CCFLAGS@
LIBS = @LIBS@ @ZLIB_LIBS@ @openssl_libs@
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include \
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
$(openssl_includes) @ZLIB_INCLUDES@
-
## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include
include $(top_srcdir)/libmysql/Makefile.shared
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index f4e9d4e6b39..9aef03f20d2 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -25,9 +25,10 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\""
-INCLUDES= @MT_INCLUDES@ @bdb_includes@ \
+INCLUDES= @bdb_includes@ \
-I$(top_builddir)/include -I$(top_srcdir)/include \
- -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples \
+ -I$(top_srcdir)/regex \
$(openssl_includes) @ZLIB_INCLUDES@
noinst_LIBRARIES = libmysqld_int.a
@@ -41,7 +42,7 @@ sqlexamplessources = ha_example.cc ha_archive.cc ha_tina.cc
noinst_HEADERS = embedded_priv.h emb_qcache.h
sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
- ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \
+ ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_federated.cc \
ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \
hostname.cc init.cc password.c \
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
@@ -59,7 +60,9 @@ 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 tztime.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 sql_view.cc sql_trigger.cc my_decimal.cc \
ha_blackhole.cc
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources)
@@ -83,29 +86,25 @@ INC_LIB= $(top_builddir)/regex/libregex.a \
# To make it easy for the end user to use the embedded library we
# generate a total libmysqld.a from all library files,
+# note - InnoDB libraries have circular dependencies, so in INC_LIB
+# few libraries are present two times. Metrowerks linker doesn't like
+# it at all. Traditional ar has no problems with it, but still there's no
+# need to add the same file twice to the library, so 'sort -u' save us
+# some time and spares unnecessary work.
+
libmysqld.a: libmysqld_int.a $(INC_LIB)
if DARWIN_MWCC
- mwld -lib -o $@ libmysqld_int.a `ls -1 $(INC_LIB) | sort -u`
+ mwld -lib -o $@ libmysqld_int.a `echo $(INC_LIB) | sort -u`
else
+ -rm -f libmysqld.a
if test "$(host_os)" = "netware" ; \
then \
$(libmysqld_a_AR) libmysqld.a libmysqld_int.a $(INC_LIB) ; \
else \
- if test ! -d tmp ; then mkdir tmp ; fi ; \
- rm -f $@ libmysqld_int2.a tmp/*.o tmp/*.a ; \
- cp $(INC_LIB) tmp ; \
- cp libmysqld_int.a libmysqld_int2.a ; \
- cd tmp ; \
- for file in *.a ; do \
- bfile=`basename $$file .a` ; \
- $(AR) x $$file; \
- for obj in *.o ; do mv $$obj $${bfile}_$$obj ; done ; \
- $(AR) q ../libmysqld_int2.a *.o ; \
- rm -f *.o ; \
- done ; \
- cd .. ; \
- mv libmysqld_int2.a libmysqld.a ; \
- rm -f tmp/* ; \
+ for arc in ./libmysqld_int.a $(INC_LIB); do \
+ arpath=`echo $$arc|sed 's|[^/]*$$||'`; \
+ $(AR) t $$arc|sed "s|^|$$arpath|"; \
+ done | sort -u | xargs $(AR) cq libmysqld.a ; \
$(RANLIB) libmysqld.a ; \
fi
endif
diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am
index d19023c100f..476f297fe0d 100644
--- a/libmysqld/examples/Makefile.am
+++ b/libmysqld/examples/Makefile.am
@@ -14,10 +14,11 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-noinst_PROGRAMS = mysql
-bin_PROGRAMS = mysqltest_embedded mysql_client_test_embedded
-client_sources = $(mysqltest_embedded_SOURCES) $(mysql_SOURCES)
-tests_sources= $(mysql_client_test_embedded_SOURCES)
+noinst_PROGRAMS = mysql
+bin_PROGRAMS = mysqltest_embedded mysql_client_test_embedded
+client_sources = $(mysqltest_embedded_SOURCES) $(mysql_SOURCES)
+tests_sources = $(mysql_client_test_embedded_SOURCES)
+CLEANFILES = $(client_sources) $(tests_sources)
link_sources:
for f in $(client_sources); do \
@@ -30,8 +31,7 @@ link_sources:
done;
DEFS = -DEMBEDDED_LIBRARY
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \
-I$(top_srcdir) -I$(top_srcdir)/client -I$(top_srcdir)/regex \
$(openssl_includes)
LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@
@@ -46,11 +46,7 @@ mysql_SOURCES = mysql.cc readline.cc completion_hash.cc \
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD)
mysql_client_test_embedded_LINK = $(CXXLINK)
-mysql_client_test_embedded_SOURCES = mysql_client_test.c
-
-clean:
- rm -f $(client_sources)
- rm -f $(tests_sources)
+mysql_client_test_embedded_SOURCES = mysql_client_test.c
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/libmysqld/examples/builder-sample/emb_samples.cpp b/libmysqld/examples/builder-sample/emb_samples.cpp
index 4dfde111f84..411de26149b 100644
--- a/libmysqld/examples/builder-sample/emb_samples.cpp
+++ b/libmysqld/examples/builder-sample/emb_samples.cpp
@@ -109,6 +109,7 @@ bool __fastcall TForm1::connect_server()
ret_value = true;
is_server_started = true;
}
+ MySQL->reconnect= 1;
return ret_value;
}
//---------------------------------------------------------------------------
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 82e1c19d758..a86d467299c 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -28,10 +28,6 @@ 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 };
-
#if defined (__WIN__)
#include "../sql/mysqld.cpp"
#else
@@ -224,7 +220,7 @@ static int emb_stmt_execute(MYSQL_STMT *stmt)
THD *thd= (THD*)stmt->mysql->thd;
thd->client_param_count= stmt->param_count;
thd->client_params= stmt->params;
- if (emb_advanced_command(stmt->mysql, COM_EXECUTE,0,0,
+ if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0,
header, sizeof(header), 1) ||
emb_mysql_read_query_result(stmt->mysql))
{
@@ -620,7 +616,7 @@ static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
}
-bool Protocol::send_fields(List<Item> *list, uint flag)
+bool Protocol::send_fields(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
@@ -685,7 +681,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
if (INTERNAL_NUM_FIELD(client_field))
client_field->flags|= NUM_FLAG;
- if (flag & 2)
+ if (flags & (int) Protocol::SEND_DEFAULTS)
{
char buff[80];
String tmp(buff, sizeof(buff), default_charset_info), *res;
@@ -711,15 +707,10 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
DBUG_RETURN(prepare_for_send(list));
err:
- send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
-bool Protocol::send_records_num(List<Item> *list, ulonglong records)
-{
- return false;
-}
-
bool Protocol::write()
{
if (!thd->mysql) // bootstrap file handling
@@ -784,7 +775,7 @@ send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
}
void
-send_eof(THD *thd, bool no_flush)
+send_eof(THD *thd)
{
}
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 6fa41fb3fd0..70074e44c6f 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -199,6 +199,14 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
unix_socket=0;
db_name = db ? my_strdup(db,MYF(MY_WME)) : NULL;
+ /* Send client information for access check */
+ client_flag|=CLIENT_CAPABILITIES;
+ if (client_flag & CLIENT_MULTI_STATEMENTS)
+ client_flag|= CLIENT_MULTI_RESULTS;
+ client_flag&= ~CLIENT_COMPRESS;
+ if (db)
+ client_flag|=CLIENT_CONNECT_WITH_DB;
+
mysql->thd= create_embedded_thd(client_flag, db_name);
init_embedded_mysql(mysql, client_flag, db_name);
@@ -209,11 +217,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (mysql_init_charset(mysql))
goto error;
- /* Send client information for access check */
- client_flag|=CLIENT_CAPABILITIES;
- client_flag&= ~CLIENT_COMPRESS;
- if (db)
- client_flag|=CLIENT_CONNECT_WITH_DB;
mysql->server_status= SERVER_STATUS_AUTOCOMMIT;
if (mysql->options.init_commands)
diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def
index ea3133594f5..93456901a7d 100644
--- a/libmysqld/libmysqld.def
+++ b/libmysqld/libmysqld.def
@@ -1,6 +1,6 @@
LIBRARY LIBMYSQLD
-DESCRIPTION 'MySQL 4.1 Embedded Server Library'
-VERSION 4.1
+DESCRIPTION 'MySQL 5.0 Embedded Server Library'
+VERSION 5.0
EXPORTS
_dig_vec_upper
_dig_vec_lower
@@ -113,6 +113,7 @@ EXPORTS
my_charset_latin1
init_alloc_root
my_progname
+ get_charset_name
get_charset_by_csname
print_defaults
find_type
@@ -157,4 +158,7 @@ EXPORTS
mysql_stmt_attr_get
mysql_stmt_attr_set
mysql_stmt_field_count
- get_defaults_files
+ get_defaults_options
+ my_charset_bin
+ my_charset_same
+ modify_defaults_file
diff --git a/libmysqld/libmysqld.rc b/libmysqld/libmysqld.rc
index 5b6142faddf..5b6142faddf 100755..100644
--- a/libmysqld/libmysqld.rc
+++ b/libmysqld/libmysqld.rc
diff --git a/libmysqld/resource.h b/libmysqld/resource.h
index f770fe490a6..f770fe490a6 100755..100644
--- a/libmysqld/resource.h
+++ b/libmysqld/resource.h
diff --git a/ltconfig b/ltconfig
deleted file mode 100755
index cc52d4b824f..00000000000
--- a/ltconfig
+++ /dev/null
@@ -1,3154 +0,0 @@
-#! /bin/sh
-
-# ltconfig - Create a system-specific libtool.
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This file 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.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# A lot of this script is taken from autoconf-2.10.
-
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-echo=echo
-if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X$1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
- # Yippee, $echo works!
- :
-else
- # Restart under the correct shell.
- exec "$SHELL" "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<EOF
-$*
-EOF
- exit 0
-fi
-
-# Find the correct PATH separator. Usually this is `:', but
-# DJGPP uses `;' like DOS.
-if test "X${PATH_SEPARATOR+set}" != Xset; then
- UNAME=${UNAME-`uname 2>/dev/null`}
- case X$UNAME in
- *-DOS) PATH_SEPARATOR=';' ;;
- *) PATH_SEPARATOR=':' ;;
- esac
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
-
-if test "X${echo_test_string+set}" != Xset; then
- # find a string as large as possible, as long as the shell can cope with it
- for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
- # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
- if (echo_test_string="`eval $cmd`") 2>/dev/null &&
- echo_test_string="`eval $cmd`" &&
- (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
- break
- fi
- done
-fi
-
-if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
- test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
- # The Solaris, AIX, and Digital Unix default echo programs unquote
- # backslashes. This makes it impossible to quote backslashes using
- # echo "$something" | sed 's/\\/\\\\/g'
- #
- # So, first we look for a working echo in the user's PATH.
-
- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for dir in $PATH /usr/ucb; do
- if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
- test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
- test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- echo="$dir/echo"
- break
- fi
- done
- IFS="$save_ifs"
-
- if test "X$echo" = Xecho; then
- # We didn't find a better echo, so look for alternatives.
- if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
- test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- # This shell has a builtin print -r that does the trick.
- echo='print -r'
- elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
- test "X$CONFIG_SHELL" != X/bin/ksh; then
- # If we have ksh, try running ltconfig again with it.
- ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
- export ORIGINAL_CONFIG_SHELL
- CONFIG_SHELL=/bin/ksh
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
- else
- # Try using printf.
- echo='printf "%s\n"'
- if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
- test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- # Cool, printf works
- :
- elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
- test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
- export CONFIG_SHELL
- SHELL="$CONFIG_SHELL"
- export SHELL
- echo="$CONFIG_SHELL $0 --fallback-echo"
- elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
- test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
- echo="$CONFIG_SHELL $0 --fallback-echo"
- else
- # maybe with a smaller string...
- prev=:
-
- for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
- if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
- break
- fi
- prev="$cmd"
- done
-
- if test "$prev" != 'sed 50q "$0"'; then
- echo_test_string=`eval $prev`
- export echo_test_string
- exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
- else
- # Oops. We lost completely, so just stick with echo.
- echo=echo
- fi
- fi
- fi
- fi
-fi
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e s/^X//'
-sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# The name of this program.
-progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
-
-# Constants:
-PROGRAM=ltconfig
-PACKAGE=libtool
-VERSION=1.3.5
-TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)"
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-rm="rm -f"
-
-help="Try \`$progname --help' for more information."
-
-# Global variables:
-default_ofile=libtool
-can_build_shared=yes
-enable_shared=yes
-# All known linkers require a `.a' archive for static linking (except M$VC,
-# which needs '.lib').
-enable_static=yes
-enable_fast_install=yes
-enable_dlopen=unknown
-enable_win32_dll=no
-ltmain=
-silent=
-srcdir=
-ac_config_guess=
-ac_config_sub=
-host=
-nonopt=
-ofile="$default_ofile"
-verify_host=yes
-with_gcc=no
-with_gnu_ld=no
-need_locks=yes
-ac_ext=c
-objext=o
-libext=a
-exeext=
-cache_file=
-
-old_AR="$AR"
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-old_CPPFLAGS="$CPPFLAGS"
-old_LDFLAGS="$LDFLAGS"
-old_LD="$LD"
-old_LN_S="$LN_S"
-old_LIBS="$LIBS"
-old_NM="$NM"
-old_RANLIB="$RANLIB"
-old_DLLTOOL="$DLLTOOL"
-old_OBJDUMP="$OBJDUMP"
-old_AS="$AS"
-
-# Parse the command line options.
-args=
-prev=
-for option
-do
- case "$option" in
- -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) optarg= ;;
- esac
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- eval "$prev=\$option"
- prev=
- continue
- fi
-
- case "$option" in
- --help) cat <<EOM
-Usage: $progname [OPTION]... [HOST [LTMAIN]]
-
-Generate a system-specific libtool script.
-
- --debug enable verbose shell tracing
- --disable-shared do not build shared libraries
- --disable-static do not build static libraries
- --disable-fast-install do not optimize for fast installation
- --enable-dlopen enable dlopen support
- --enable-win32-dll enable building dlls on win32 hosts
- --help display this help and exit
- --no-verify do not verify that HOST is a valid host type
--o, --output=FILE specify the output file [default=$default_ofile]
- --quiet same as \`--silent'
- --silent do not print informational messages
- --srcdir=DIR find \`config.guess' in DIR
- --version output version information and exit
- --with-gcc assume that the GNU C compiler will be used
- --with-gnu-ld assume that the C compiler uses the GNU linker
- --disable-lock disable file locking
- --cache-file=FILE configure cache file
-
-LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
-that provides basic libtool functionality.
-
-HOST is the canonical host system name [default=guessed].
-EOM
- exit 0
- ;;
-
- --debug)
- echo "$progname: enabling shell trace mode"
- set -x
- ;;
-
- --disable-shared) enable_shared=no ;;
-
- --disable-static) enable_static=no ;;
-
- --disable-fast-install) enable_fast_install=no ;;
-
- --enable-dlopen) enable_dlopen=yes ;;
-
- --enable-win32-dll) enable_win32_dll=yes ;;
-
- --quiet | --silent) silent=yes ;;
-
- --srcdir) prev=srcdir ;;
- --srcdir=*) srcdir="$optarg" ;;
-
- --no-verify) verify_host=no ;;
-
- --output | -o) prev=ofile ;;
- --output=*) ofile="$optarg" ;;
-
- --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
-
- --with-gcc) with_gcc=yes ;;
- --with-gnu-ld) with_gnu_ld=yes ;;
-
- --disable-lock) need_locks=no ;;
-
- --cache-file=*) cache_file="$optarg" ;;
-
- -*)
- echo "$progname: unrecognized option \`$option'" 1>&2
- echo "$help" 1>&2
- exit 1
- ;;
-
- *)
- if test -z "$ltmain"; then
- ltmain="$option"
- elif test -z "$host"; then
-# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
-# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
-# echo "$progname: warning \`$option' is not a valid host type" 1>&2
-# fi
- host="$option"
- else
- echo "$progname: too many arguments" 1>&2
- echo "$help" 1>&2
- exit 1
- fi ;;
- esac
-done
-
-if test -z "$ltmain"; then
- echo "$progname: you must specify a LTMAIN file" 1>&2
- echo "$help" 1>&2
- exit 1
-fi
-
-if test ! -f "$ltmain"; then
- echo "$progname: \`$ltmain' does not exist" 1>&2
- echo "$help" 1>&2
- exit 1
-fi
-
-# Quote any args containing shell metacharacters.
-ltconfig_args=
-for arg
-do
- case "$arg" in
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ltconfig_args="$ltconfig_args '$arg'" ;;
- *) ltconfig_args="$ltconfig_args $arg" ;;
- esac
-done
-
-# A relevant subset of AC_INIT.
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 5 compiler messages saved in config.log
-# 6 checking for... messages and results
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
-fi
-exec 5>>./config.log
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi
-if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi
-
-if test -n "$cache_file" && test -r "$cache_file"; then
- echo "loading cache $cache_file within ltconfig"
- . $cache_file
-fi
-
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
-else
- ac_n= ac_c='\c' ac_t=
-fi
-
-if test -z "$srcdir"; then
- # Assume the source directory is the same one as the path to LTMAIN.
- srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
- test "$srcdir" = "$ltmain" && srcdir=.
-fi
-
-trap "$rm conftest*; exit 1" 1 2 15
-if test "$verify_host" = yes; then
- # Check for config.guess and config.sub.
- ac_aux_dir=
- for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
- if test -f $ac_dir/config.guess; then
- ac_aux_dir=$ac_dir
- break
- fi
- done
- if test -z "$ac_aux_dir"; then
- echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
- echo "$help" 1>&2
- exit 1
- fi
- ac_config_guess=$ac_aux_dir/config.guess
- ac_config_sub=$ac_aux_dir/config.sub
-
- # Make sure we can run config.sub.
- if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
- else
- echo "$progname: cannot run $ac_config_sub" 1>&2
- echo "$help" 1>&2
- exit 1
- fi
-
- echo $ac_n "checking host system type""... $ac_c" 1>&6
-
- host_alias=$host
- case "$host_alias" in
- "")
- if host_alias=`$SHELL $ac_config_guess`; then :
- else
- echo "$progname: cannot guess host type; you must specify one" 1>&2
- echo "$help" 1>&2
- exit 1
- fi ;;
- esac
- host=`$SHELL $ac_config_sub $host_alias`
- echo "$ac_t$host" 1>&6
-
- # Make sure the host verified.
- test -z "$host" && exit 1
-
-elif test -z "$host"; then
- echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
- echo "$help" 1>&2
- exit 1
-else
- host_alias=$host
-fi
-
-# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
-case "$host_os" in
-linux-gnu*) ;;
-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
-esac
-
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-
-case "$host_os" in
-aix3*)
- # AIX sometimes has problems with the GCC collect2 program. For some
- # reason, if we set the COLLECT_NAMES environment variable, the problems
- # vanish in a puff of smoke.
- if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
- fi
- ;;
-esac
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR cru $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-# Set a sane default for `AR'.
-test -z "$AR" && AR=ar
-
-# Set a sane default for `OBJDUMP'.
-test -z "$OBJDUMP" && OBJDUMP=objdump
-
-# If RANLIB is not set, then run the test.
-if test "${RANLIB+set}" != "set"; then
- result=no
-
- echo $ac_n "checking for ranlib... $ac_c" 1>&6
- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for dir in $PATH; do
- test -z "$dir" && dir=.
- if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
- RANLIB="ranlib"
- result="ranlib"
- break
- fi
- done
- IFS="$save_ifs"
-
- echo "$ac_t$result" 1>&6
-fi
-
-if test -n "$RANLIB"; then
- old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
- old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
-fi
-
-# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-test -z "$OBJDUMP" && OBJDUMP=objdump
-test -z "$AS" && AS=as
-
-# Check to see if we are using GCC.
-if test "$with_gcc" != yes || test -z "$CC"; then
- # If CC is not set, then try to find GCC or a usable CC.
- if test -z "$CC"; then
- echo $ac_n "checking for gcc... $ac_c" 1>&6
- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for dir in $PATH; do
- test -z "$dir" && dir=.
- if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
- CC="gcc"
- break
- fi
- done
- IFS="$save_ifs"
-
- if test -n "$CC"; then
- echo "$ac_t$CC" 1>&6
- else
- echo "$ac_t"no 1>&6
- fi
- fi
-
- # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
- if test -z "$CC"; then
- echo $ac_n "checking for cc... $ac_c" 1>&6
- IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- cc_rejected=no
- for dir in $PATH; do
- test -z "$dir" && dir=.
- if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
- if test "$dir/cc" = "/usr/ucb/cc"; then
- cc_rejected=yes
- continue
- fi
- CC="cc"
- break
- fi
- done
- IFS="$save_ifs"
- if test $cc_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $CC
- shift
- if test $# -gt 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same name, so the bogon will be chosen
- # first if we set CC to just the name; use the full file name.
- shift
- set dummy "$dir/cc" "$@"
- shift
- CC="$@"
- fi
- fi
-
- if test -n "$CC"; then
- echo "$ac_t$CC" 1>&6
- else
- echo "$ac_t"no 1>&6
- fi
-
- if test -z "$CC"; then
- echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
- exit 1
- fi
- fi
-
- # Now see if the compiler is really GCC.
- with_gcc=no
- echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
- echo "$progname:581: checking whether we are using GNU C" >&5
-
- $rm conftest.c
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
- if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- with_gcc=yes
- fi
- $rm conftest.c
- echo "$ac_t$with_gcc" 1>&6
-fi
-
-# Allow CC to be a program name with arguments.
-set dummy $CC
-compiler="$2"
-
-echo $ac_n "checking for object suffix... $ac_c" 1>&6
-$rm conftest*
-echo 'int i = 1;' > conftest.c
-echo "$progname:603: checking for object suffix" >& 5
-if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
- # Append any warnings to the config.log.
- cat conftest.err 1>&5
-
- for ac_file in conftest.*; do
- case $ac_file in
- *.c) ;;
- *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
- esac
- done
-else
- cat conftest.err 1>&5
- echo "$progname: failed program was:" >&5
- cat conftest.c >&5
-fi
-$rm conftest*
-echo "$ac_t$objext" 1>&6
-
-echo $ac_n "checking for executable suffix... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_cv_exeext="no"
- $rm conftest*
- echo 'main () { return 0; }' > conftest.c
- echo "$progname:629: checking for executable suffix" >& 5
- if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
- # Append any warnings to the config.log.
- cat conftest.err 1>&5
-
- for ac_file in conftest.*; do
- case $ac_file in
- *.c | *.err | *.$objext ) ;;
- *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
- esac
- done
- else
- cat conftest.err 1>&5
- echo "$progname: failed program was:" >&5
- cat conftest.c >&5
- fi
- $rm conftest*
-fi
-if test "X$ac_cv_exeext" = Xno; then
- exeext=""
-else
- exeext="$ac_cv_exeext"
-fi
-echo "$ac_t$ac_cv_exeext" 1>&6
-
-echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
-pic_flag=
-special_shlib_compile_flags=
-wl=
-link_static_flag=
-no_builtin_flag=
-
-if test "$with_gcc" = yes; then
- wl='-Wl,'
- link_static_flag='-static'
-
- case "$host_os" in
- beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
- aix*)
- # Below there is a dirty hack to force normal static linking with -ldl
- # The problem is because libdl dynamically linked with both libc and
- # libC (AIX C++ library), which obviously doesn't included in libraries
- # list by gcc. This cause undefined symbols with -static flags.
- # This hack allows C programs to be linked with "-static -ldl", but
- # we not sure about C++ programs.
- link_static_flag="$link_static_flag ${wl}-lC"
- ;;
- cygwin* | mingw* | os2*)
- # We can build DLLs from non-PIC.
- ;;
- amigaos*)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- pic_flag='-m68020 -resident32 -malways-restore-a4'
- ;;
- sysv4*MP*)
- if test -d /usr/nec; then
- pic_flag=-Kconform_pic
- fi
- ;;
- *)
- pic_flag='-fPIC'
- ;;
- esac
-else
- # PORTME Check for PIC flags for the system compiler.
- case "$host_os" in
- aix3* | aix4*)
- # All AIX code is PIC.
- link_static_flag='-bnso -bI:/lib/syscalls.exp'
- ;;
-
- hpux9* | hpux10* | hpux11*)
- # Is there a better link_static_flag that works with the bundled CC?
- wl='-Wl,'
- link_static_flag="${wl}-a ${wl}archive"
- pic_flag='+Z'
- ;;
-
- irix5* | irix6*)
- wl='-Wl,'
- link_static_flag='-non_shared'
- # PIC (with -KPIC) is the default.
- ;;
-
- cygwin* | mingw* | os2*)
- # We can build DLLs from non-PIC.
- ;;
-
- osf3* | osf4* | osf5*)
- # All OSF/1 code is PIC.
- wl='-Wl,'
- link_static_flag='-non_shared'
- ;;
-
- sco3.2v5*)
- pic_flag='-Kpic'
- link_static_flag='-dn'
- special_shlib_compile_flags='-belf'
- ;;
-
- solaris*)
- pic_flag='-KPIC'
- link_static_flag='-Bstatic'
- wl='-Wl,'
- ;;
-
- sunos4*)
- pic_flag='-PIC'
- link_static_flag='-Bstatic'
- wl='-Qoption ld '
- ;;
-
- sysv5UnixWare* | sysv5OpenUNIX*)
- pic_flag='-KPIC'
- link_static_flag='-Bstatic'
- wl='-Wl,'
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
- pic_flag='-KPIC'
- link_static_flag='-Bstatic'
- wl='-Wl,'
- ;;
-
- uts4*)
- pic_flag='-pic'
- link_static_flag='-Bstatic'
- ;;
- sysv4*MP*)
- if test -d /usr/nec ;then
- pic_flag='-Kconform_pic'
- link_static_flag='-Bstatic'
- fi
- ;;
- *)
- can_build_shared=no
- ;;
- esac
-fi
-
-if test -n "$pic_flag"; then
- echo "$ac_t$pic_flag" 1>&6
-
- # Check to make sure the pic_flag actually works.
- echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
- $rm conftest*
- echo "int some_variable = 0;" > conftest.c
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $pic_flag -DPIC"
- echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
- if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
- # Append any warnings to the config.log.
- cat conftest.err 1>&5
-
- case "$host_os" in
- hpux9* | hpux10* | hpux11*)
- # On HP-UX, both CC and GCC only warn that PIC is supported... then they
- # create non-PIC objects. So, if there were any warnings, we assume that
- # PIC is not supported.
- if test -s conftest.err; then
- echo "$ac_t"no 1>&6
- can_build_shared=no
- pic_flag=
- else
- echo "$ac_t"yes 1>&6
- pic_flag=" $pic_flag"
- fi
- ;;
- *)
- echo "$ac_t"yes 1>&6
- pic_flag=" $pic_flag"
- ;;
- esac
- else
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- can_build_shared=no
- pic_flag=
- echo "$ac_t"no 1>&6
- fi
- CFLAGS="$save_CFLAGS"
- $rm conftest*
-else
- echo "$ac_t"none 1>&6
-fi
-
-# Check to see if options -o and -c are simultaneously supported by compiler
-echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
-$rm -r conftest 2>/dev/null
-mkdir conftest
-cd conftest
-$rm conftest*
-echo "int some_variable = 0;" > conftest.c
-mkdir out
-# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
-# that will create temporary files in the current directory regardless of
-# the output directory. Thus, making CWD read-only will cause this test
-# to fail, enabling locking or at least warning the user not to do parallel
-# builds.
-chmod -w .
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -o out/conftest2.o"
-echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
-if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
-
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s out/conftest.err; then
- echo "$ac_t"no 1>&6
- compiler_c_o=no
- else
- echo "$ac_t"yes 1>&6
- compiler_c_o=yes
- fi
-else
- # Append any errors to the config.log.
- cat out/conftest.err 1>&5
- compiler_c_o=no
- echo "$ac_t"no 1>&6
-fi
-CFLAGS="$save_CFLAGS"
-chmod u+w .
-$rm conftest* out/*
-rmdir out
-cd ..
-rmdir conftest
-$rm -r conftest 2>/dev/null
-
-if test x"$compiler_c_o" = x"yes"; then
- # Check to see if we can write to a .lo
- echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
- $rm conftest*
- echo "int some_variable = 0;" > conftest.c
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -c -o conftest.lo"
- echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
-if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
-
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- echo "$ac_t"no 1>&6
- compiler_o_lo=no
- else
- echo "$ac_t"yes 1>&6
- compiler_o_lo=yes
- fi
- else
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- compiler_o_lo=no
- echo "$ac_t"no 1>&6
- fi
- CFLAGS="$save_CFLAGS"
- $rm conftest*
-else
- compiler_o_lo=no
-fi
-
-# Check to see if we can do hard links to lock some files if needed
-hard_links="nottested"
-if test "$compiler_c_o" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
- hard_links=yes
- $rm conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- echo "$ac_t$hard_links" 1>&6
- $rm conftest*
- if test "$hard_links" = no; then
- echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-
-if test "$with_gcc" = yes; then
- # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
- echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
- $rm conftest*
- echo "int some_variable = 0;" > conftest.c
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
- echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
- if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
-
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- echo "$ac_t"no 1>&6
- compiler_rtti_exceptions=no
- else
- echo "$ac_t"yes 1>&6
- compiler_rtti_exceptions=yes
- fi
- else
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- compiler_rtti_exceptions=no
- echo "$ac_t"no 1>&6
- fi
- CFLAGS="$save_CFLAGS"
- $rm conftest*
-
- if test "$compiler_rtti_exceptions" = "yes"; then
- no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
- else
- no_builtin_flag=' -fno-builtin'
- fi
-
-fi
-
-# Check for any special shared library compilation flags.
-if test -n "$special_shlib_compile_flags"; then
- echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
- if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then :
- else
- echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
- can_build_shared=no
- fi
-fi
-
-echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
-$rm conftest*
-echo 'main(){return(0);}' > conftest.c
-save_LDFLAGS="$LDFLAGS"
-LDFLAGS="$LDFLAGS $link_static_flag"
-echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
-if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- echo "$ac_t$link_static_flag" 1>&6
-else
- echo "$ac_t"none 1>&6
- link_static_flag=
-fi
-LDFLAGS="$save_LDFLAGS"
-$rm conftest*
-
-if test -z "$LN_S"; then
- # Check to see if we can use ln -s, or we need hard links.
- echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
- $rm conftest.dat
- if ln -s X conftest.dat 2>/dev/null; then
- $rm conftest.dat
- LN_S="ln -s"
- else
- LN_S=ln
- fi
- if test "$LN_S" = "ln -s"; then
- echo "$ac_t"yes 1>&6
- else
- echo "$ac_t"no 1>&6
- fi
-fi
-
-# Make sure LD is an absolute path.
-if test -z "$LD"; then
- ac_prog=ld
- if test "$with_gcc" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
- echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
- echo "$progname:991: checking for ld used by GCC" >&5
- ac_prog=`($CC -print-prog-name=ld) 2>&5`
- case "$ac_prog" in
- # Accept absolute paths.
- [\\/]* | [A-Za-z]:[\\/]*)
- re_direlt='/[^/][^/]*/\.\./'
- # Canonicalize the path of ld
- ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
- while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we are not using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
- elif test "$with_gnu_ld" = yes; then
- echo $ac_n "checking for GNU ld... $ac_c" 1>&6
- echo "$progname:1015: checking for GNU ld" >&5
- else
- echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
- echo "$progname:1018: checking for non-GNU ld" >&5
- fi
-
- if test -z "$LD"; then
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some GNU ld's only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
- test "$with_gnu_ld" != no && break
- else
- test "$with_gnu_ld" != yes && break
- fi
- fi
- done
- IFS="$ac_save_ifs"
- fi
-
- if test -n "$LD"; then
- echo "$ac_t$LD" 1>&6
- else
- echo "$ac_t"no 1>&6
- fi
-
- if test -z "$LD"; then
- echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
- exit 1
- fi
-fi
-
-# Check to see if it really is or is not GNU ld.
-echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
-# I'd rather use --version here, but apparently some GNU ld's only accept -v.
-if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
- with_gnu_ld=yes
-else
- with_gnu_ld=no
-fi
-echo "$ac_t$with_gnu_ld" 1>&6
-
-# See if the linker supports building shared libraries.
-echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
-
-allow_undefined_flag=
-no_undefined_flag=
-need_lib_prefix=unknown
-need_version=unknown
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-archive_cmds=
-archive_expsym_cmds=
-old_archive_from_new_cmds=
-export_dynamic_flag_spec=
-whole_archive_flag_spec=
-thread_safe_flag_spec=
-hardcode_libdir_flag_spec=
-hardcode_libdir_separator=
-hardcode_direct=no
-hardcode_minus_L=no
-hardcode_shlibpath_var=unsupported
-runpath_var=
-always_export_symbols=no
-export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
-# include_expsyms should be a list of space-separated symbols to be *always*
-# included in the symbol list
-include_expsyms=
-# exclude_expsyms can be an egrep regular expression of symbols to exclude
-# it will be wrapped by ` (' and `)$', so one must not match beginning or
-# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
-# as well as any symbol that contains `d'.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
-# platforms (ab)use it in PIC code, but their linkers get confused if
-# the symbol is explicitly referenced. Since portable code cannot
-# rely on this symbol name, it's probably fine to never include it in
-# preloaded symbol tables.
-
-case "$host_os" in
-cygwin* | mingw*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$with_gcc" != yes; then
- with_gnu_ld=no
- fi
- ;;
-
-esac
-
-ld_shlibs=yes
-if test "$with_gnu_ld" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # See if GNU ld supports shared libraries.
- case "$host_os" in
- aix3* | aix4*)
- # On AIX, the GNU linker is very broken
- ld_shlibs=no
- cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
- ;;
-
- amigaos*)
- archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
-
- # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
- # that the semantics of dynamic libraries on AmigaOS, at least up
- # to version 4, is to share data among multiple programs linked
- # with the same dynamic library. Since this doesn't match the
- # behavior of shared libraries on other platforms, we can use
- # them.
- ld_shlibs=no
- ;;
-
- beos*)
- if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
- allow_undefined_flag=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- cygwin* | mingw*)
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- hardcode_libdir_flag_spec='-L$libdir'
- allow_undefined_flag=unsupported
- always_export_symbols=yes
-
- # Extract the symbol export list from an `--export-all' def file,
- # then regenerate the def file from the symbol export list, so that
- # the compiled dll only exports the symbol export list.
- # Be careful not to strip the DATA tag left by newer dlltools.
- export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
- test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
- $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~
- sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $objdir/$soname-def > $export_symbols'
-
- # If DATA tags from a recent dlltool are present, honour them!
- archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
- _lt_hint=1;
- cat $export_symbols | while read symbol; do
- set dummy \$symbol;
- case \$# in
- 2) echo " \$2 @ \$_lt_hint ; " >> $objdir/$soname-def;;
- *) echo " \$2 @ \$_lt_hint \$3 ; " >> $objdir/$soname-def;;
- esac;
- _lt_hint=`expr 1 + \$_lt_hint`;
- done~
- test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
- test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
- $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
- $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
- $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
- $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
- $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
-
- old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a'
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
- # can we support soname and/or expsyms with a.out? -oliva
- fi
- ;;
-
- solaris* | sysv5*)
- if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
- ld_shlibs=no
- cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
- elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- sunos4*)
- archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
- wlarc=
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- *)
- if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
- esac
-
- if test "$ld_shlibs" = yes; then
- runpath_var=LD_RUN_PATH
- hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
- export_dynamic_flag_spec='${wl}--export-dynamic'
- case $host_os in
- cygwin* | mingw*)
- # dlltool doesn't understand --whole-archive et. al.
- whole_archive_flag_spec=
- ;;
- *)
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
- whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- whole_archive_flag_spec=
- fi
- ;;
- esac
- fi
-else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case "$host_os" in
- aix3*)
- allow_undefined_flag=unsupported
- always_export_symbols=yes
- archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- hardcode_minus_L=yes
- if test "$with_gcc" = yes && test -z "$link_static_flag"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- hardcode_direct=unsupported
- fi
- ;;
-
- aix4*)
- hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
- hardcode_libdir_separator=':'
- if test "$with_gcc" = yes; then
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" && \
- strings "$collect2name" | grep resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- hardcode_direct=yes
- else
- # We have old collect2
- hardcode_direct=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- hardcode_minus_L=yes
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_libdir_separator=
- fi
- shared_flag='-shared'
- else
- shared_flag='${wl}-bM:SRE'
- hardcode_direct=yes
- fi
- allow_undefined_flag=' ${wl}-berok'
- archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
- archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
- case "$host_os" in aix4.[01]|aix4.[01].*)
- # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
- always_export_symbols=yes ;;
- esac
- ;;
-
- amigaos*)
- archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- # see comment about different semantics on the GNU ld section
- ld_shlibs=no
- ;;
-
- cygwin* | mingw*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- hardcode_libdir_flag_spec=' '
- allow_undefined_flag=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # FIXME: Setting linknames here is a bad hack.
- archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- old_archive_from_new_cmds='true'
- # FIXME: Should let the user specify the lib program.
- old_archive_cmds='lib /OUT:$oldlib$oldobjs'
- fix_srcfile_path='`cygpath -w $srcfile`'
- ;;
-
- freebsd1*)
- ld_shlibs=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
- hardcode_direct=yes
- hardcode_minus_L=yes
- hardcode_shlibpath_var=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd*)
- archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- hpux9* | hpux10* | hpux11*)
- case "$host_os" in
- hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
- *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
- esac
- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator=:
- hardcode_direct=yes
- hardcode_minus_L=yes # Not in the search PATH, but as the default
- # location of the library.
- export_dynamic_flag_spec='${wl}-E'
- ;;
-
- irix5* | irix6*)
- if test "$with_gcc" = yes; then
- archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
- else
- archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- ;;
-
- netbsd*)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out
- else
- archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF
- fi
- hardcode_libdir_flag_spec='${wl}-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- openbsd*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- os2*)
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- allow_undefined_flag=" "
- archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll $linkflags -o $lib $libobjs $deplibs $objdir/$libname.def'
- old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$with_gcc" = yes; then
- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
- else
- allow_undefined_flag=' -expect_unresolved \*'
- archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- ;;
-
- osf4* | osf5*) # As osf3* with the addition of the -msym flag
- if test "$with_gcc" = yes; then
- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
- else
- allow_undefined_flag=' -expect_unresolved \*'
- archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- ;;
- rhapsody*)
- archive_cmds='$CC -bundle -undefined suppress -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flags_spec='-L$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- sco3.2v5*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_shlibpath_var=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- ;;
-
- solaris*)
- no_undefined_flag=' -z text'
- # $CC -shared without GNU ld will not create a library from C++
- # object files and a static libstdc++, better avoid it by now
- archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_shlibpath_var=no
- case "$host_os" in
- solaris2.[0-5] | solaris2.[0-5].*) ;;
- *) # Supported since Solaris 2.6 (maybe 2.5.1?)
- whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
- esac
- ;;
-
- sunos4*)
- archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_direct=yes
- hardcode_minus_L=yes
- hardcode_shlibpath_var=no
- ;;
-
- sysv4)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $linkopts'
- else
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- fi
- runpath_var='LD_RUN_PATH'
- hardcode_shlibpath_var=no
- hardcode_direct=no #Motorola manual says yes, but my tests say they lie
- ;;
-
- sysv4.3*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_shlibpath_var=no
- export_dynamic_flag_spec='-Bexport'
- ;;
-
- sysv5UnixWare* | sysv5OpenUNIX*)
- no_undefined_flag=' -z text'
- # $CC -shared without GNU ld will not create a library from C++
- # object files and a static libstdc++, better avoid it by now
- archive_cmds='$UW7_compile_command -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
- hardcode_libdir_flag_spec=
- hardcode_shlibpath_var=no
- runpath_var='LD_RUN_PATH'
- ;;
-
- sysv5*)
- no_undefined_flag=' -z text'
- # $CC -shared without GNU ld will not create a library from C++
- # object files and a static libstdc++, better avoid it by now
- archive_cmds='$UW7_compile_command -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
- hardcode_libdir_flag_spec=
- hardcode_shlibpath_var=no
- runpath_var='LD_RUN_PATH'
- ;;
-
- uts4*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_shlibpath_var=no
- ;;
-
- dgux*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_shlibpath_var=no
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- hardcode_shlibpath_var=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- ld_shlibs=yes
- fi
- ;;
-
- sysv4.2uw2*)
- archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts'
- hardcode_direct=yes
- hardcode_minus_L=no
- hardcode_shlibpath_var=no
- hardcode_runpath_var=yes
- runpath_var=LD_RUN_PATH
- ;;
-
- unixware7*)
- archive_cmds='$UW7_compile_command -G -h $soname -o $lib $libobjs $deplibs $linkopts'
- runpath_var='LD_RUN_PATH'
- hardcode_shlibpath_var=no
- ;;
-
- *)
- ld_shlibs=no
- ;;
- esac
-fi
-echo "$ac_t$ld_shlibs" 1>&6
-test "$ld_shlibs" = no && can_build_shared=no
-
-if test -z "$NM"; then
- echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
- case "$NM" in
- [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
- *)
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
- for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
- # Check to see if the nm accepts a BSD-compat flag.
- # Adding the `sed 1q' prevents false positives on HP-UX, which says:
- # nm: unknown option "B" ignored
- if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
- NM="$ac_dir/nm -B"
- break
- elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
- NM="$ac_dir/nm -p"
- break
- else
- NM=${NM="$ac_dir/nm"} # keep the first match, but
- continue # so that we can try to find one that supports BSD flags
- fi
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$NM" && NM=nm
- ;;
- esac
- echo "$ac_t$NM" 1>&6
-fi
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
-
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix. What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[BCDEGRST]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
-
-# Transform the above into a raw symbol and a C symbol.
-symxfrm='\1 \2\3 \3'
-
-# Transform an extracted symbol line into a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
-
-# Define system-specific variables.
-case "$host_os" in
-aix*)
- symcode='[BCDT]'
- ;;
-cygwin* | mingw*)
- symcode='[ABCDGISTW]'
- ;;
-hpux*) # Its linker distinguishes data from code symbols
- global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
- ;;
-irix*)
- symcode='[BCDEGRST]'
- ;;
-solaris*)
- symcode='[BDT]'
- ;;
-sysv4)
- symcode='[DFNSTU]'
- ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
- symcode='[ABCDGISTW]'
-fi
-
-# Try without a prefix undercore, then with it.
-for ac_symprfx in "" "_"; do
-
- # Write the raw and C identifiers.
- global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
-
- # Check to see that the pipe works correctly.
- pipe_works=no
- $rm conftest*
- cat > conftest.c <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(){}
-#ifdef __cplusplus
-}
-#endif
-main(){nm_test_var='a';nm_test_func();return(0);}
-EOF
-
- echo "$progname:1653: checking if global_symbol_pipe works" >&5
- if { (eval echo $progname:1654: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
- # Now try to grab the symbols.
- nlist=conftest.nm
- if { echo "$progname:1657: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
-
- # Try sorting and uniquifying the output.
- if sort "$nlist" | uniq > "$nlist"T; then
- mv -f "$nlist"T "$nlist"
- else
- rm -f "$nlist"T
- fi
-
- # Make sure that we snagged all the symbols we need.
- if egrep ' nm_test_var$' "$nlist" >/dev/null; then
- if egrep ' nm_test_func$' "$nlist" >/dev/null; then
- cat <<EOF > conftest.c
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EOF
- # Now generate the symbol file.
- eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
-
- cat <<EOF >> conftest.c
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
- const char *name;
- lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{
-EOF
- sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
- cat <<\EOF >> conftest.c
- {0, (lt_ptr_t) 0}
-};
-
-#ifdef __cplusplus
-}
-#endif
-EOF
- # Now try linking the two files.
- mv conftest.$objext conftstm.$objext
- save_LIBS="$LIBS"
- save_CFLAGS="$CFLAGS"
- LIBS="conftstm.$objext"
- CFLAGS="$CFLAGS$no_builtin_flag"
- if { (eval echo $progname:1709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- pipe_works=yes
- else
- echo "$progname: failed program was:" >&5
- cat conftest.c >&5
- fi
- LIBS="$save_LIBS"
- else
- echo "cannot find nm_test_func in $nlist" >&5
- fi
- else
- echo "cannot find nm_test_var in $nlist" >&5
- fi
- else
- echo "cannot run $global_symbol_pipe" >&5
- fi
- else
- echo "$progname: failed program was:" >&5
- cat conftest.c >&5
- fi
- $rm conftest* conftst*
-
- # Do not use the global_symbol_pipe unless it works.
- if test "$pipe_works" = yes; then
- break
- else
- global_symbol_pipe=
- fi
-done
-if test "$pipe_works" = yes; then
- echo "${ac_t}ok" 1>&6
-else
- echo "${ac_t}failed" 1>&6
-fi
-
-if test -z "$global_symbol_pipe"; then
- global_symbol_to_cdecl=
-fi
-
-# Check hardcoding attributes.
-echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" || \
- test -n "$runpath_var"; then
-
- # We can hardcode non-existant directories.
- if test "$hardcode_direct" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$hardcode_shlibpath_var" != no &&
- test "$hardcode_minus_L" != no; then
- # Linking always hardcodes the temporary library directory.
- hardcode_action=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- hardcode_action=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- hardcode_action=unsupported
-fi
-echo "$ac_t$hardcode_action" 1>&6
-
-
-reload_flag=
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
-# PORTME Some linkers may need a different reload flag.
-reload_flag='-r'
-echo "$ac_t$reload_flag" 1>&6
-test -n "$reload_flag" && reload_flag=" $reload_flag"
-
-# PORTME Fill in your ld.so characteristics
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-file_magic_cmd=
-file_magic_test_file=
-deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [regex]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given egrep regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
-case "$host_os" in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}.so$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}.so$major'
- ;;
-
-aix4*)
- version_type=linux
- # AIX has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- # We preserve .a as extension for shared libraries though AIX4.2
- # and later linker supports .so
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
- shlibpath_var=LIBPATH
- deplibs_check_method=pass_all
- ;;
-
-amigaos*)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
- ;;
-
-beos*)
- library_names_spec='${libname}.so'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- deplibs_check_method=pass_all
- lt_cv_dlopen="load_add_on"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ;;
-
-bsdi4*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=/shlib/libc.so
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- export_dynamic_flag_spec=-rdynamic
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw*)
- version_type=windows
- need_version=no
- need_lib_prefix=no
- if test "$with_gcc" = yes; then
- library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
- else
- library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
- fi
- dynamic_linker='Win32 ld.exe'
- deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
- file_magic_cmd='${OBJDUMP} -f'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- lt_cv_dlopen="LoadLibrary"
- lt_cv_dlopen_libs=
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-freebsd*)
- objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
- version_type=freebsd-$objformat
- case "$version_type" in
- freebsd-elf*)
- deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=`echo /usr/lib/libc.so*`
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- deplibs_check_method=unknown
- library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
- need_version=yes
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case "$host_os" in
- freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*)
- shlibpath_overrides_runpath=yes
- ;;
- *) # from 3.2 on
- shlibpath_overrides_runpath=no
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- deplibs_check_method=pass_all
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- dynamic_linker="$host_os dld.sl"
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
- soname_spec='${libname}${release}.sl$major'
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
- case "$host_os" in
- hpux10.20*)
- # TODO: Does this work for hpux-11 too?
- deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=/usr/lib/libc.sl
- ;;
- esac
- ;;
-
-irix5* | irix6*)
- version_type=irix
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}.so.$major'
- library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
- case "$host_os" in
- irix5*)
- libsuff= shlibsuff=
- # this will be overridden with pass_all, but let us keep it just in case
- deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
- ;;
- *)
- case "$LD" in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=`echo /lib${libsuff}/libc.so*`
- deplibs_check_method='pass_all'
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- deplibs_check_method=pass_all
-
- if test -f /lib/ld.so.1; then
- dynamic_linker='GNU ld.so'
- else
- # Only the GNU ld.so supports shared libraries on MkLinux.
- case "$host_cpu" in
- powerpc*) dynamic_linker=no ;;
- *) dynamic_linker='Linux ld.so' ;;
- esac
- fi
- ;;
-
-netbsd*)
- version_type=sunos
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
- soname_spec='${libname}${release}.so$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-openbsd*)
- version_type=sunos
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- need_version=no
- fi
- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-os2*)
- libname_spec='$name'
- need_lib_prefix=no
- library_names_spec='$libname.dll $libname.a'
- dynamic_linker='OS/2 ld.exe'
- deplibs_check_method=pass_all
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_version=no
- soname_spec='${libname}${release}.so'
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
- shlibpath_var=LD_LIBRARY_PATH
- # this will be overridden with pass_all, but let us keep it just in case
- deplibs_check_method='file_magic COFF format alpha shared library'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=/shlib/libc.so
- deplibs_check_method='pass_all'
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-rhapsody*)
- version_type=sunos
- library_names_spec='${libname}.so'
- soname_spec='${libname}.so'
- shlibpath_var=DYLD_LIBRARY_PATH
- deplibs_check_method=pass_all
- ;;
-
-sco3.2v5*)
- version_type=osf
- soname_spec='${libname}${release}.so$major'
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=/lib/libc.so
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv5UnixWare* | sysv5OpenUNIX*)
- version_type=linux
- soname_spec='${libname}${release}.so$major'
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
- version_type=linux
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- case "$host_vendor" in
- sequent)
- file_magic_cmd='/bin/file'
- deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
- ;;
- ncr)
- deplibs_check_method='pass_all'
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
- file_magic_cmd=/usr/bin/file
- file_magic_test_file=`echo /usr/lib/libc.so*`
- ;;
- esac
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
- soname_spec='${libname}${release}.so$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
- soname_spec='$libname.so.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-echo "$ac_t$dynamic_linker" 1>&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-# Report the final consequences.
-echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
-
-# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
-# configure.in, otherwise build static only libraries.
-case "$host_os" in
-cygwin* | mingw* | os2*)
- if test x$can_build_shared = xyes; then
- test x$enable_win32_dll = xno && can_build_shared=no
- echo "checking if package supports dlls... $can_build_shared" 1>&6
- fi
-;;
-esac
-
-if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
- case "$deplibs_check_method" in
- "file_magic "*)
- file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- egrep "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-EOF
- fi ;;
- esac
-fi
-
-echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case "$host_os" in
-aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-
-aix4*)
- test "$enable_shared" = yes && enable_static=no
- ;;
-esac
-
-echo "$ac_t$enable_shared" 1>&6
-
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-
-echo "checking whether to build static libraries... $enable_static" 1>&6
-
-if test "$hardcode_action" = relink; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-
-echo $ac_n "checking for objdir... $ac_c" 1>&6
-rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
- objdir=.libs
-else
- # MS-DOS does not allow filenames that begin with a dot.
- objdir=_libs
-fi
-rmdir .libs 2>/dev/null
-echo "$ac_t$objdir" 1>&6
-
-if test "x$enable_dlopen" != xyes; then
- enable_dlopen=unknown
- enable_dlopen_self=unknown
- enable_dlopen_self_static=unknown
-else
-if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
- lt_cv_dlopen=no lt_cv_dlopen_libs=
-echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "$progname:2248: checking for dlopen in -ldl" >&5
-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldl $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2256 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen();
-
-int main() {
-dlopen()
-; return 0; }
-EOF
-if { (eval echo $progname:2269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dlopen""... $ac_c" 1>&6
-echo "$progname:2288: checking for dlopen" >&5
-if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2293 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char dlopen(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_dlopen) || defined (__stub___dlopen)
-choke me
-#else
-dlopen();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_dlopen=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_dlopen=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="dlopen"
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
-echo "$progname:2335: checking for dld_link in -ldld" >&5
-ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldld $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2343 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dld_link();
-
-int main() {
-dld_link()
-; return 0; }
-EOF
-if { (eval echo $progname:2356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load""... $ac_c" 1>&6
-echo "$progname:2375: checking for shl_load" >&5
-if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2380 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char shl_load(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_shl_load) || defined (__stub___shl_load)
-choke me
-#else
-shl_load();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_shl_load=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_shl_load=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="shl_load"
-else
- echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "$progname:2423: checking for shl_load in -ldld" >&5
-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldld $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2431 "ltconfig"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load();
-
-int main() {
-shl_load()
-; return 0; }
-EOF
-if { (eval echo $progname:2445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
-else
- echo "$ac_t""no" 1>&6
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-fi
-
- if test "x$lt_cv_dlopen" != xno; then
- enable_dlopen=yes
- fi
-
- case "$lt_cv_dlopen" in
- dlopen)
-for ac_hdr in dlfcn.h; do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "$progname:2488: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2493 "ltconfig"
-#include <$ac_hdr>
-int fnord = 0;
-EOF
-ac_try="$ac_compile >/dev/null 2>conftest.out"
-{ (eval echo $progname:2498: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
- if test "x$ac_cv_header_dlfcn_h" = xyes; then
- CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
- fi
- eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
- LIBS="$lt_cv_dlopen_libs $LIBS"
-
- echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2526: checking whether a program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self+set}" = set; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- lt_cv_dlopen_self=cross
- else
- cat > conftest.c <<EOF
-#line 2534 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LTDL_GLOBAL DL_GLOBAL
-# else
-# define LTDL_GLOBAL 0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LTDL_LAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LTDL_LAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LTDL_LAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LTDL_LAZY_OR_NOW DL_NOW
-# else
-# define LTDL_LAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
- if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
- if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
-
-EOF
-if { (eval echo $progname:2580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- lt_cv_dlopen_self=yes
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- lt_cv_dlopen_self=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self" 1>&6
-
- if test "$lt_cv_dlopen_self" = yes; then
- LDFLAGS="$LDFLAGS $link_static_flag"
- echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2599: checking whether a statically linked program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self_static+set}" = set; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- lt_cv_dlopen_self_static=cross
- else
- cat > conftest.c <<EOF
-#line 2607 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LTDL_GLOBAL DL_GLOBAL
-# else
-# define LTDL_GLOBAL 0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LTDL_LAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LTDL_LAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LTDL_LAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LTDL_LAZY_OR_NOW DL_NOW
-# else
-# define LTDL_LAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
- if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
- if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
-
-EOF
-if { (eval echo $progname:2653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- lt_cv_dlopen_self_static=yes
-else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- lt_cv_dlopen_self_static=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
-fi
- ;;
- esac
-
- case "$lt_cv_dlopen_self" in
- yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
- *) enable_dlopen_self=unknown ;;
- esac
-
- case "$lt_cv_dlopen_self_static" in
- yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
- *) enable_dlopen_self_static=unknown ;;
- esac
-fi
-
-# Copy echo and quote the copy, instead of the original, because it is
-# used later.
-ltecho="$echo"
-if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
- ltecho="$CONFIG_SHELL \$0 --fallback-echo"
-fi
-LTSHELL="$SHELL"
-
-LTCONFIG_VERSION="$VERSION"
-
-# Only quote variables if we're using ltmain.sh.
-case "$ltmain" in
-*.sh)
- # Now quote all the things that may contain metacharacters.
- for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
- old_LD old_LDFLAGS old_LIBS \
- old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
- AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
- reload_flag reload_cmds wl \
- pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
- thread_safe_flag_spec whole_archive_flag_spec libname_spec \
- library_names_spec soname_spec \
- RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
- old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
- file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
- finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
- hardcode_libdir_flag_spec hardcode_libdir_separator \
- sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
- compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
-
- case "$var" in
- reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
- old_postinstall_cmds | old_postuninstall_cmds | \
- export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
- postinstall_cmds | postuninstall_cmds | \
- finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
- # Double-quote double-evaled strings.
- eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
- ;;
- *)
- eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
- ;;
- esac
- done
-
- case "$ltecho" in
- *'\$0 --fallback-echo"')
- ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
- ;;
- esac
-
- trap "$rm \"$ofile\"; exit 1" 1 2 15
- echo "creating $ofile"
- $rm "$ofile"
- cat <<EOF > "$ofile"
-#! $SHELL
-
-# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# 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.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="sed -e s/^X//"
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
-
-### BEGIN LIBTOOL CONFIG
-EOF
- cfgfile="$ofile"
- ;;
-
-*)
- # Double-quote the variables that need it (for aesthetics).
- for var in old_CC old_CFLAGS old_CPPFLAGS \
- old_LD old_LDFLAGS old_LIBS \
- old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
- eval "$var=\\\"\$var\\\""
- done
-
- # Just create a config file.
- cfgfile="$ofile.cfg"
- trap "$rm \"$cfgfile\"; exit 1" 1 2 15
- echo "creating $cfgfile"
- $rm "$cfgfile"
- cat <<EOF > "$cfgfile"
-# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-EOF
- ;;
-esac
-
-cat <<EOF >> "$cfgfile"
-# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
-# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
-# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
-# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
-# $0$ltconfig_args
-#
-# Compiler and other test output produced by $progname, useful for
-# debugging $progname, is in ./config.log if it exists.
-
-# The version of $progname that generated this script.
-LTCONFIG_VERSION=$LTCONFIG_VERSION
-
-# Shell to use when invoking shell scripts.
-SHELL=$LTSHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-
-# An echo program that does not interpret backslashes.
-echo=$ltecho
-
-# The archiver.
-AR=$AR
-
-# The default C compiler.
-CC=$CC
-
-# The linker used to build libraries.
-LD=$LD
-
-# Whether we need hard or soft links.
-LN_S=$LN_S
-
-# A BSD-compatible nm program.
-NM=$NM
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# compatibility with ancient libtool :)
-SED=sed
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$reload_flag
-reload_cmds=$reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$wl
-
-# Object file suffix (normally "o").
-objext="$objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$pic_flag
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$compiler_c_o
-
-# Can we write directly to a .lo ?
-compiler_o_lo=$compiler_o_lo
-
-# Must we lock files when doing compilation ?
-need_locks=$need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$link_static_flag
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$no_builtin_flag
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$whole_archive_flag_spec
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$thread_safe_flag_spec
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$RANLIB
-old_archive_cmds=$old_archive_cmds
-old_postinstall_cmds=$old_postinstall_cmds
-old_postuninstall_cmds=$old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$old_archive_from_new_cmds
-
-# Commands used to build and install a shared archive.
-archive_cmds=$archive_cmds
-archive_expsym_cmds=$archive_expsym_cmds
-postinstall_cmds=$postinstall_cmds
-postuninstall_cmds=$postuninstall_cmds
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$allow_undefined_flag
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$no_undefined_flag
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$global_symbol_to_cdecl
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
-
-# Check if debuild is being run by the current shell. If it is then,
-# the DEB_BUILD_ARCH variable should be of non-zero length, indicating
-# that we are in the middle of a Debian package build (assuming the
-# user isn't doing anything strange with environment variables).
-if test -n "`dpkg-architecture -qDEB_BUILD_ARCH 2>/dev/null`" && ps | grep debuild | grep -v grep > /dev/null; then
- # Debian policy mandates that rpaths should not be encoded into a binary
- # so it is overridden.
- hardcode_libdir_flag_spec=" -D_DEBIAN_PATCHED_LIBTOOL_ "
-fi
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$hardcode_libdir_separator
-
-# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$export_symbols_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$include_expsyms
-
-EOF
-
-case "$ltmain" in
-*.sh)
- echo '### END LIBTOOL CONFIG' >> "$ofile"
- echo >> "$ofile"
- case "$host_os" in
- aix3*)
- cat <<\EOF >> "$ofile"
-
-# AIX sometimes has problems with the GCC collect2 program. For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
-fi
-EOF
- ;;
- esac
-
- # Append the ltmain.sh script.
- sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
- # We use sed instead of cat because bash on DJGPP gets confused if
- # if finds mixed CR/LF and LF-only lines. Since sed operates in
- # text mode, it properly converts lines to CR/LF. This bash problem
- # is reportedly fixed, but why not run on old versions too?
-
- chmod +x "$ofile"
- ;;
-
-*)
- # Compile the libtool program.
- echo "FIXME: would compile $ltmain"
- ;;
-esac
-
-test -n "$cache_file" || exit 0
-
-# AC_CACHE_SAVE
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
- if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-exit 0
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/ltmain.sh b/ltmain.sh
deleted file mode 100644
index c2c73cad224..00000000000
--- a/ltmain.sh
+++ /dev/null
@@ -1,6297 +0,0 @@
-# ltmain.sh - Provide generalized library-building support services.
-# NOTE: Changing this file will not affect anything until you rerun configure.
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
-# Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# 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.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Check that we have a working $echo.
-if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X$1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
- # Yippee, $echo works!
- :
-else
- # Restart under the correct shell, and then maybe $echo will work.
- exec $SHELL "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<EOF
-$*
-EOF
- exit 0
-fi
-
-# libtool 1.4.2 workaround
-SED=${SED:-sed}
-
-# workaround against unset 'max_cmd_len': assume at least 4 kB
-max_cmd_len=${max_cmd_len:-4096}
-
-# The name of this program.
-progname=`$echo "$0" | ${SED} 's%^.*/%%'`
-modename="$progname"
-
-# Constants.
-PROGRAM=ltmain.sh
-PACKAGE=libtool
-VERSION=1.5
-TIMESTAMP=" (1.1220.2.1 2003/04/14 22:48:00)"
-
-default_mode=
-help="Try \`$progname --help' for more information."
-magic="%%%MAGIC variable%%%"
-mkdir="mkdir"
-mv="mv -f"
-rm="rm -f"
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed="${SED}"' -e 1s/^X//'
-sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
-# test EBCDIC or ASCII
-case `echo A|od -x` in
- *[Cc]1*) # EBCDIC based system
- SP2NL="tr '\100' '\n'"
- NL2SP="tr '\r\n' '\100\100'"
- ;;
- *) # Assume ASCII based system
- SP2NL="tr '\040' '\012'"
- NL2SP="tr '\015\012' '\040\040'"
- ;;
-esac
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-# We save the old values to restore during execute mode.
-if test "${LC_ALL+set}" = set; then
- save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
-fi
-if test "${LANG+set}" = set; then
- save_LANG="$LANG"; LANG=C; export LANG
-fi
-
-# Make sure IFS has a sensible default
-: ${IFS=" "}
-
-if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
- $echo "$modename: not configured to build any kind of library" 1>&2
- $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit 1
-fi
-
-# Global variables.
-mode=$default_mode
-nonopt=
-prev=
-prevopt=
-run=
-show="$echo"
-show_help=
-execute_dlfiles=
-lo2o="s/\\.lo\$/.${objext}/"
-o2lo="s/\\.${objext}\$/.lo/"
-
-#####################################
-# Shell function definitions:
-# This seems to be the best place for them
-
-# Need a lot of goo to handle *both* DLLs and import libs
-# Has to be a shell function in order to 'eat' the argument
-# that is supplied when $file_magic_command is called.
-win32_libid () {
- win32_libid_type="unknown"
- win32_fileres=`file -L $1 2>/dev/null`
- case $win32_fileres in
- *ar\ archive\ import\ library*) # definitely import
- win32_libid_type="x86 archive import"
- ;;
- *ar\ archive*) # could be an import, or static
- if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
- grep -E 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
- win32_nmres=`eval $NM -f posix -A $1 | \
- $SED -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'`
- if test "X$win32_nmres" = "Ximport" ; then
- win32_libid_type="x86 archive import"
- else
- win32_libid_type="x86 archive static"
- fi
- fi
- ;;
- *DLL*)
- win32_libid_type="x86 DLL"
- ;;
- *executable*) # but shell scripts are "executable" too...
- case $win32_fileres in
- *MS\ Windows\ PE\ Intel*)
- win32_libid_type="x86 DLL"
- ;;
- esac
- ;;
- esac
- $echo $win32_libid_type
-}
-
-# End of Shell function definitions
-#####################################
-
-# Parse our command line options once, thoroughly.
-while test "$#" -gt 0
-do
- arg="$1"
- shift
-
- case $arg in
- -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
- *) optarg= ;;
- esac
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- case $prev in
- execute_dlfiles)
- execute_dlfiles="$execute_dlfiles $arg"
- ;;
- tag)
- tagname="$arg"
-
- # Check whether tagname contains only valid characters
- case $tagname in
- *[!-_A-Za-z0-9,/]*)
- $echo "$progname: invalid tag name: $tagname" 1>&2
- exit 1
- ;;
- esac
-
- case $tagname in
- CC)
- # Don't test for the "default" C tag, as we know, it's there, but
- # not specially marked.
- ;;
- *)
- if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$0" > /dev/null; then
- taglist="$taglist $tagname"
- # Evaluate the configuration.
- eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $0`"
- else
- $echo "$progname: ignoring unknown tag $tagname" 1>&2
- fi
- ;;
- esac
- ;;
- *)
- eval "$prev=\$arg"
- ;;
- esac
-
- prev=
- prevopt=
- continue
- fi
-
- # Have we seen a non-optional argument yet?
- case $arg in
- --help)
- show_help=yes
- ;;
-
- --version)
- $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
- $echo
- $echo "Copyright (C) 2003 Free Software Foundation, Inc."
- $echo "This is free software; see the source for copying conditions. There is NO"
- $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
- exit 0
- ;;
-
- --config)
- ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
- # Now print the configurations for the tags.
- for tagname in $taglist; do
- ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$0"
- done
- exit 0
- ;;
-
- --debug)
- $echo "$progname: enabling shell trace mode"
- set -x
- ;;
-
- --dry-run | -n)
- run=:
- ;;
-
- --features)
- $echo "host: $host"
- if test "$build_libtool_libs" = yes; then
- $echo "enable shared libraries"
- else
- $echo "disable shared libraries"
- fi
- if test "$build_old_libs" = yes; then
- $echo "enable static libraries"
- else
- $echo "disable static libraries"
- fi
- exit 0
- ;;
-
- --finish) mode="finish" ;;
-
- --mode) prevopt="--mode" prev=mode ;;
- --mode=*) mode="$optarg" ;;
-
- --preserve-dup-deps) duplicate_deps="yes" ;;
-
- --quiet | --silent)
- show=:
- ;;
-
- --tag) prevopt="--tag" prev=tag ;;
- --tag=*)
- set tag "$optarg" ${1+"$@"}
- shift
- prev=tag
- ;;
-
- -dlopen)
- prevopt="-dlopen"
- prev=execute_dlfiles
- ;;
-
- -*)
- $echo "$modename: unrecognized option \`$arg'" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
-
- *)
- nonopt="$arg"
- break
- ;;
- esac
-done
-
-if test -n "$prevopt"; then
- $echo "$modename: option \`$prevopt' requires an argument" 1>&2
- $echo "$help" 1>&2
- exit 1
-fi
-
-# If this variable is set in any of the actions, the command in it
-# will be execed at the end. This prevents here-documents from being
-# left over by shells.
-exec_cmd=
-
-if test -z "$show_help"; then
-
- # Infer the operation mode.
- if test -z "$mode"; then
- $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
- $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2
- case $nonopt in
- *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
- mode=link
- for arg
- do
- case $arg in
- -c)
- mode=compile
- break
- ;;
- esac
- done
- ;;
- *db | *dbx | *strace | *truss)
- mode=execute
- ;;
- *install*|cp|mv)
- mode=install
- ;;
- *rm)
- mode=uninstall
- ;;
- *)
- # If we have no mode, but dlfiles were specified, then do execute mode.
- test -n "$execute_dlfiles" && mode=execute
-
- # Just use the default operation mode.
- if test -z "$mode"; then
- if test -n "$nonopt"; then
- $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
- else
- $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
- fi
- fi
- ;;
- esac
- fi
-
- # Only execute mode is allowed to have -dlopen flags.
- if test -n "$execute_dlfiles" && test "$mode" != execute; then
- $echo "$modename: unrecognized option \`-dlopen'" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Change the help message to a mode-specific one.
- generic_help="$help"
- help="Try \`$modename --help --mode=$mode' for more information."
-
- # These modes are in order of execution frequency so that they run quickly.
- case $mode in
- # libtool compile mode
- compile)
- modename="$modename: compile"
- # Get the compilation command and the source file.
- base_compile=
- srcfile="$nonopt" # always keep a non-empty value in "srcfile"
- suppress_output=
- arg_mode=normal
- libobj=
-
- for arg
- do
- case "$arg_mode" in
- arg )
- # do not "continue". Instead, add this to base_compile
- lastarg="$arg"
- arg_mode=normal
- ;;
-
- target )
- libobj="$arg"
- arg_mode=normal
- continue
- ;;
-
- normal )
- # Accept any command-line options.
- case $arg in
- -o)
- if test -n "$libobj" ; then
- $echo "$modename: you cannot specify \`-o' more than once" 1>&2
- exit 1
- fi
- arg_mode=target
- continue
- ;;
-
- -static)
- build_old_libs=yes
- continue
- ;;
-
- -prefer-pic)
- pic_mode=yes
- continue
- ;;
-
- -prefer-non-pic)
- pic_mode=no
- continue
- ;;
-
- -Xcompiler)
- arg_mode=arg # the next one goes into the "base_compile" arg list
- continue # The current "srcfile" will either be retained or
- ;; # replaced later. I would guess that would be a bug.
-
- -Wc,*)
- args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
- lastarg=
- save_ifs="$IFS"; IFS=','
- for arg in $args; do
- IFS="$save_ifs"
-
- # Double-quote args containing other shell metacharacters.
- # Many Bourne shells cannot handle close brackets correctly
- # in scan sets, so we specify it separately.
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- lastarg="$lastarg $arg"
- done
- IFS="$save_ifs"
- lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
-
- # Add the arguments to base_compile.
- base_compile="$base_compile $lastarg"
- continue
- ;;
-
- * )
- # Accept the current argument as the source file.
- # The previous "srcfile" becomes the current argument.
- #
- lastarg="$srcfile"
- srcfile="$arg"
- ;;
- esac # case $arg
- ;;
- esac # case $arg_mode
-
- # Aesthetically quote the previous argument.
- lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
-
- case $lastarg in
- # Double-quote args containing other shell metacharacters.
- # Many Bourne shells cannot handle close brackets correctly
- # in scan sets, so we specify it separately.
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- lastarg="\"$lastarg\""
- ;;
- esac
-
- base_compile="$base_compile $lastarg"
- done # for arg
-
- case $arg_mode in
- arg)
- $echo "$modename: you must specify an argument for -Xcompile"
- exit 1
- ;;
- target)
- $echo "$modename: you must specify a target with \`-o'" 1>&2
- exit 1
- ;;
- *)
- # Get the name of the library object.
- [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
- ;;
- esac
-
- # Recognize several different file suffixes.
- # If the user specifies -o file.o, it is replaced with file.lo
- xform='[cCFSifmso]'
- case $libobj in
- *.ada) xform=ada ;;
- *.adb) xform=adb ;;
- *.ads) xform=ads ;;
- *.asm) xform=asm ;;
- *.c++) xform=c++ ;;
- *.cc) xform=cc ;;
- *.ii) xform=ii ;;
- *.class) xform=class ;;
- *.cpp) xform=cpp ;;
- *.cxx) xform=cxx ;;
- *.f90) xform=f90 ;;
- *.for) xform=for ;;
- *.java) xform=java ;;
- esac
-
- libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
-
- case $libobj in
- *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
- *)
- $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
- exit 1
- ;;
- esac
-
- # Infer tagged configuration to use if any are available and
- # if one wasn't chosen via the "--tag" command line option.
- # Only attempt this if the compiler in the base compile
- # command doesn't match the default compiler.
- if test -n "$available_tags" && test -z "$tagname"; then
- case $base_compile in
- # Blanks in the command may have been stripped by the calling shell,
- # but not from the CC environment variable when configure was run.
- " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "*) ;;
- # Blanks at the start of $base_compile will cause this to fail
- # if we don't check for them as well.
- *)
- for z in $available_tags; do
- if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then
- # Evaluate the configuration.
- eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`"
- case "$base_compile " in
- "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*)
- # The compiler in the base compile command matches
- # the one in the tagged configuration.
- # Assume this is the tagged configuration we want.
- tagname=$z
- break
- ;;
- esac
- fi
- done
- # If $tagname still isn't set, then no tagged configuration
- # was found and let the user know that the "--tag" command
- # line option must be used.
- if test -z "$tagname"; then
- $echo "$modename: unable to infer tagged configuration"
- $echo "$modename: specify a tag with \`--tag'" 1>&2
- exit 1
-# else
-# $echo "$modename: using $tagname tagged configuration"
- fi
- ;;
- esac
- fi
-
- objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
- xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$obj"; then
- xdir=
- else
- xdir=$xdir/
- fi
- lobj=${xdir}$objdir/$objname
-
- if test -z "$base_compile"; then
- $echo "$modename: you must specify a compilation command" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Delete any leftover library objects.
- if test "$build_old_libs" = yes; then
- removelist="$obj $lobj $libobj ${libobj}T"
- else
- removelist="$lobj $libobj ${libobj}T"
- fi
-
- $run $rm $removelist
- trap "$run $rm $removelist; exit 1" 1 2 15
-
- # On Cygwin there's no "real" PIC flag so we must build both object types
- case $host_os in
- cygwin* | mingw* | pw32* | os2*)
- pic_mode=default
- ;;
- esac
- if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
- # non-PIC code in shared libraries is not supported
- pic_mode=default
- fi
-
- # Calculate the filename of the output object if compiler does
- # not support -o with -c
- if test "$compiler_c_o" = no; then
- output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
- lockfile="$output_obj.lock"
- removelist="$removelist $output_obj $lockfile"
- trap "$run $rm $removelist; exit 1" 1 2 15
- else
- output_obj=
- need_locks=no
- lockfile=
- fi
-
- # Lock this critical section if it is needed
- # We use this script file to make the link, it avoids creating a new file
- if test "$need_locks" = yes; then
- until $run ln "$0" "$lockfile" 2>/dev/null; do
- $show "Waiting for $lockfile to be removed"
- sleep 2
- done
- elif test "$need_locks" = warn; then
- if test -f "$lockfile"; then
- $echo "\
-*** ERROR, $lockfile exists and contains:
-`cat $lockfile 2>/dev/null`
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit 1
- fi
- $echo $srcfile > "$lockfile"
- fi
-
- if test -n "$fix_srcfile_path"; then
- eval srcfile=\"$fix_srcfile_path\"
- fi
-
- $run $rm "$libobj" "${libobj}T"
-
- # Create a libtool object file (analogous to a ".la" file),
- # but don't create it if we're doing a dry run.
- test -z "$run" && cat > ${libobj}T <<EOF
-# $libobj - a libtool object file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# Name of the PIC object.
-EOF
-
- # Only build a PIC object if we are building libtool libraries.
- if test "$build_libtool_libs" = yes; then
- # Without this assignment, base_compile gets emptied.
- fbsd_hideous_sh_bug=$base_compile
-
- if test "$pic_mode" != no; then
- command="$base_compile $srcfile $pic_flag"
- else
- # Don't build PIC code
- command="$base_compile $srcfile"
- fi
-
- if test ! -d "${xdir}$objdir"; then
- $show "$mkdir ${xdir}$objdir"
- $run $mkdir ${xdir}$objdir
- status=$?
- if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then
- exit $status
- fi
- fi
-
- if test -z "$output_obj"; then
- # Place PIC objects in $objdir
- command="$command -o $lobj"
- fi
-
- $run $rm "$lobj" "$output_obj"
-
- $show "$command"
- if $run eval "$command"; then :
- else
- test -n "$output_obj" && $run $rm $removelist
- exit 1
- fi
-
- if test "$need_locks" = warn &&
- test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
- $echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit 1
- fi
-
- # Just move the object if needed, then go on to compile the next one
- if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
- $show "$mv $output_obj $lobj"
- if $run $mv $output_obj $lobj; then :
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
- fi
-
- # Append the name of the PIC object to the libtool object file.
- test -z "$run" && cat >> ${libobj}T <<EOF
-pic_object='$objdir/$objname'
-
-EOF
-
- # Allow error messages only from the first compilation.
- suppress_output=' >/dev/null 2>&1'
- else
- # No PIC object so indicate it doesn't exist in the libtool
- # object file.
- test -z "$run" && cat >> ${libobj}T <<EOF
-pic_object=none
-
-EOF
- fi
-
- # Only build a position-dependent object if we build old libraries.
- if test "$build_old_libs" = yes; then
- if test "$pic_mode" != yes; then
- # Don't build PIC code
- command="$base_compile $srcfile"
- else
- command="$base_compile $srcfile $pic_flag"
- fi
- if test "$compiler_c_o" = yes; then
- command="$command -o $obj"
- fi
-
- # Suppress compiler output if we already did a PIC compilation.
- command="$command$suppress_output"
- $run $rm "$obj" "$output_obj"
- $show "$command"
- if $run eval "$command"; then :
- else
- $run $rm $removelist
- exit 1
- fi
-
- if test "$need_locks" = warn &&
- test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
- $echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit 1
- fi
-
- # Just move the object if needed
- if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
- $show "$mv $output_obj $obj"
- if $run $mv $output_obj $obj; then :
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
- fi
-
- # Append the name of the non-PIC object the libtool object file.
- # Only append if the libtool object file exists.
- test -z "$run" && cat >> ${libobj}T <<EOF
-# Name of the non-PIC object.
-non_pic_object='$objname'
-
-EOF
- else
- # Append the name of the non-PIC object the libtool object file.
- # Only append if the libtool object file exists.
- test -z "$run" && cat >> ${libobj}T <<EOF
-# Name of the non-PIC object.
-non_pic_object=none
-
-EOF
- fi
-
- $run $mv "${libobj}T" "${libobj}"
-
- # Unlock the critical section if it was locked
- if test "$need_locks" != no; then
- $run $rm "$lockfile"
- fi
-
- exit 0
- ;;
-
- # libtool link mode
- link | relink)
- modename="$modename: link"
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- # It is impossible to link a dll without this setting, and
- # we shouldn't force the makefile maintainer to figure out
- # which system we are compiling for in order to pass an extra
- # flag for every libtool invocation.
- # allow_undefined=no
-
- # FIXME: Unfortunately, there are problems with the above when trying
- # to make a dll which has undefined symbols, in which case not
- # even a static library is built. For now, we need to specify
- # -no-undefined on the libtool link line when we can be certain
- # that all symbols are satisfied, otherwise we get a static library.
- allow_undefined=yes
- ;;
- *)
- allow_undefined=yes
- ;;
- esac
- libtool_args="$nonopt"
- base_compile="$nonopt"
- compile_command="$nonopt"
- finalize_command="$nonopt"
-
- compile_rpath=
- finalize_rpath=
- compile_shlibpath=
- finalize_shlibpath=
- convenience=
- old_convenience=
- deplibs=
- old_deplibs=
- compiler_flags=
- linker_flags=
- dllsearchpath=
- lib_search_path=`pwd`
- inst_prefix_dir=
-
- avoid_version=no
- dlfiles=
- dlprefiles=
- dlself=no
- export_dynamic=no
- export_symbols=
- export_symbols_regex=
- generated=
- libobjs=
- ltlibs=
- module=no
- no_install=no
- objs=
- non_pic_objects=
- prefer_static_libs=no
- preload=no
- prev=
- prevarg=
- release=
- rpath=
- xrpath=
- perm_rpath=
- temp_rpath=
- thread_safe=no
- vinfo=
- vinfo_number=no
-
- # We need to know -static, to get the right output filenames.
- for arg
- do
- case $arg in
- -all-static | -static)
- if test "X$arg" = "X-all-static"; then
- if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
- $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
- fi
- if test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- else
- if test -z "$pic_flag" && test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- fi
- build_libtool_libs=no
- build_old_libs=yes
- prefer_static_libs=yes
- break
- ;;
- esac
- done
-
- # See if our shared archives depend on static archives.
- test -n "$old_archive_from_new_cmds" && build_old_libs=yes
-
- # Go through the arguments, transforming them on the way.
- while test "$#" -gt 0; do
- arg="$1"
- base_compile="$base_compile $arg"
- shift
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
- ;;
- *) qarg=$arg ;;
- esac
- libtool_args="$libtool_args $qarg"
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- case $prev in
- output)
- compile_command="$compile_command @OUTPUT@"
- finalize_command="$finalize_command @OUTPUT@"
- ;;
- esac
-
- case $prev in
- dlfiles|dlprefiles)
- if test "$preload" = no; then
- # Add the symbol object into the linking commands.
- compile_command="$compile_command @SYMFILE@"
- finalize_command="$finalize_command @SYMFILE@"
- preload=yes
- fi
- case $arg in
- *.la | *.lo) ;; # We handle these cases below.
- force)
- if test "$dlself" = no; then
- dlself=needless
- export_dynamic=yes
- fi
- prev=
- continue
- ;;
- self)
- if test "$prev" = dlprefiles; then
- dlself=yes
- elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
- dlself=yes
- else
- dlself=needless
- export_dynamic=yes
- fi
- prev=
- continue
- ;;
- *)
- if test "$prev" = dlfiles; then
- dlfiles="$dlfiles $arg"
- else
- dlprefiles="$dlprefiles $arg"
- fi
- prev=
- continue
- ;;
- esac
- ;;
- expsyms)
- export_symbols="$arg"
- if test ! -f "$arg"; then
- $echo "$modename: symbol file \`$arg' does not exist"
- exit 1
- fi
- prev=
- continue
- ;;
- expsyms_regex)
- export_symbols_regex="$arg"
- prev=
- continue
- ;;
- inst_prefix)
- inst_prefix_dir="$arg"
- prev=
- continue
- ;;
- release)
- release="-$arg"
- prev=
- continue
- ;;
- objectlist)
- if test -f "$arg"; then
- save_arg=$arg
- moreargs=
- for fil in `cat $save_arg`
- do
-# moreargs="$moreargs $fil"
- arg=$fil
- # A libtool-controlled object.
-
- # Check to see that this really is a libtool object.
- if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- pic_object=
- non_pic_object=
-
- # Read the .lo file
- # If there is no directory component, then add one.
- case $arg in
- */* | *\\*) . $arg ;;
- *) . ./$arg ;;
- esac
-
- if test -z "$pic_object" || \
- test -z "$non_pic_object" ||
- test "$pic_object" = none && \
- test "$non_pic_object" = none; then
- $echo "$modename: cannot find name of object for \`$arg'" 1>&2
- exit 1
- fi
-
- # Extract subdirectory from the argument.
- xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$arg"; then
- xdir=
- else
- xdir="$xdir/"
- fi
-
- if test "$pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- pic_object="$xdir$pic_object"
-
- if test "$prev" = dlfiles; then
- if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
- dlfiles="$dlfiles $pic_object"
- prev=
- continue
- else
- # If libtool objects are unsupported, then we need to preload.
- prev=dlprefiles
- fi
- fi
-
- # CHECK ME: I think I busted this. -Ossama
- if test "$prev" = dlprefiles; then
- # Preload the old-style object.
- dlprefiles="$dlprefiles $pic_object"
- prev=
- fi
-
- # A PIC object.
- libobjs="$libobjs $pic_object"
- arg="$pic_object"
- fi
-
- # Non-PIC object.
- if test "$non_pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- non_pic_object="$xdir$non_pic_object"
-
- # A standard non-PIC object
- non_pic_objects="$non_pic_objects $non_pic_object"
- if test -z "$pic_object" || test "$pic_object" = none ; then
- arg="$non_pic_object"
- fi
- fi
- else
- # Only an error if not doing a dry-run.
- if test -z "$run"; then
- $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
- exit 1
- else
- # Dry-run case.
-
- # Extract subdirectory from the argument.
- xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$arg"; then
- xdir=
- else
- xdir="$xdir/"
- fi
-
- pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
- non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
- libobjs="$libobjs $pic_object"
- non_pic_objects="$non_pic_objects $non_pic_object"
- fi
- fi
- done
- else
- $echo "$modename: link input file \`$save_arg' does not exist"
- exit 1
- fi
- arg=$save_arg
- prev=
- continue
- ;;
- rpath | xrpath)
- # We need an absolute path.
- case $arg in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- $echo "$modename: only absolute run-paths are allowed" 1>&2
- exit 1
- ;;
- esac
- if test "$prev" = rpath; then
- case "$rpath " in
- *" $arg "*) ;;
- *) rpath="$rpath $arg" ;;
- esac
- else
- case "$xrpath " in
- *" $arg "*) ;;
- *) xrpath="$xrpath $arg" ;;
- esac
- fi
- prev=
- continue
- ;;
- xcompiler)
- compiler_flags="$compiler_flags $qarg"
- prev=
- compile_command="$compile_command $qarg"
- finalize_command="$finalize_command $qarg"
- continue
- ;;
- xlinker)
- linker_flags="$linker_flags $qarg"
- compiler_flags="$compiler_flags $wl$qarg"
- prev=
- compile_command="$compile_command $wl$qarg"
- finalize_command="$finalize_command $wl$qarg"
- continue
- ;;
- xcclinker)
- linker_flags="$linker_flags $qarg"
- compiler_flags="$compiler_flags $qarg"
- prev=
- compile_command="$compile_command $qarg"
- finalize_command="$finalize_command $qarg"
- continue
- ;;
- *)
- eval "$prev=\"\$arg\""
- prev=
- continue
- ;;
- esac
- fi # test -n "$prev"
-
- prevarg="$arg"
-
- case $arg in
- -all-static)
- if test -n "$link_static_flag"; then
- compile_command="$compile_command $link_static_flag"
- finalize_command="$finalize_command $link_static_flag"
- fi
- continue
- ;;
-
- -allow-undefined)
- # FIXME: remove this flag sometime in the future.
- $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
- continue
- ;;
-
- -avoid-version)
- avoid_version=yes
- continue
- ;;
-
- -dlopen)
- prev=dlfiles
- continue
- ;;
-
- -dlpreopen)
- prev=dlprefiles
- continue
- ;;
-
- -export-dynamic)
- export_dynamic=yes
- continue
- ;;
-
- -export-symbols | -export-symbols-regex)
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: more than one -exported-symbols argument is not allowed"
- exit 1
- fi
- if test "X$arg" = "X-export-symbols"; then
- prev=expsyms
- else
- prev=expsyms_regex
- fi
- continue
- ;;
-
- -inst-prefix-dir)
- prev=inst_prefix
- continue
- ;;
-
- # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
- # so, if we see these flags be careful not to treat them like -L
- -L[A-Z][A-Z]*:*)
- case $with_gcc/$host in
- no/*-*-irix* | /*-*-irix*)
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- ;;
- esac
- continue
- ;;
-
- -L*)
- dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
- exit 1
- fi
- dir="$absdir"
- ;;
- esac
- case "$deplibs " in
- *" -L$dir "*) ;;
- *)
- deplibs="$deplibs -L$dir"
- lib_search_path="$lib_search_path $dir"
- ;;
- esac
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- case :$dllsearchpath: in
- *":$dir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$dir";;
- esac
- ;;
- esac
- continue
- ;;
-
- -l*)
- if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
- case $host in
- *-*-cygwin* | *-*-pw32* | *-*-beos*)
- # These systems don't actually have a C or math library (as such)
- continue
- ;;
- *-*-mingw* | *-*-os2*)
- # These systems don't actually have a C library (as such)
- test "X$arg" = "X-lc" && continue
- ;;
- *-*-openbsd* | *-*-freebsd*)
- # Do not include libc due to us having libc/libc_r.
- test "X$arg" = "X-lc" && continue
- ;;
- *-*-rhapsody* | *-*-darwin1.[012])
- # Rhapsody C and math libraries are in the System framework
- deplibs="$deplibs -framework System"
- continue
- esac
- elif test "X$arg" = "X-lc_r"; then
- case $host in
- *-*-openbsd* | *-*-freebsd*)
- # Do not include libc_r directly, use -pthread flag.
- continue
- ;;
- esac
- fi
- deplibs="$deplibs $arg"
- continue
- ;;
-
- -module)
- module=yes
- continue
- ;;
-
- # gcc -m* arguments should be passed to the linker via $compiler_flags
- # in order to pass architecture information to the linker
- # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo
- # but this is not reliable with gcc because gcc may use -mfoo to
- # select a different linker, different libraries, etc, while
- # -Wl,-mfoo simply passes -mfoo to the linker.
- -m*)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- if test "$with_gcc" = "yes" ; then
- compiler_flags="$compiler_flags $arg"
- fi
- continue
- ;;
-
- -shrext)
- prev=shrext
- continue
- ;;
-
- -no-fast-install)
- fast_install=no
- continue
- ;;
-
- -no-install)
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- # The PATH hackery in wrapper scripts is required on Windows
- # in order for the loader to find any dlls it needs.
- $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
- $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
- fast_install=no
- ;;
- *) no_install=yes ;;
- esac
- continue
- ;;
-
- -no-undefined)
- allow_undefined=no
- continue
- ;;
-
- -objectlist)
- prev=objectlist
- continue
- ;;
-
- -o) prev=output ;;
-
- -release)
- prev=release
- continue
- ;;
-
- -rpath)
- prev=rpath
- continue
- ;;
-
- -R)
- prev=xrpath
- continue
- ;;
-
- -R*)
- dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- $echo "$modename: only absolute run-paths are allowed" 1>&2
- exit 1
- ;;
- esac
- case "$xrpath " in
- *" $dir "*) ;;
- *) xrpath="$xrpath $dir" ;;
- esac
- continue
- ;;
-
- -static)
- # The effects of -static are defined in a previous loop.
- # We used to do the same as -all-static on platforms that
- # didn't have a PIC flag, but the assumption that the effects
- # would be equivalent was wrong. It would break on at least
- # Digital Unix and AIX.
- continue
- ;;
-
- -thread-safe)
- thread_safe=yes
- continue
- ;;
-
- -version-info)
- prev=vinfo
- continue
- ;;
- -version-number)
- prev=vinfo
- vinfo_number=yes
- continue
- ;;
-
- -Wc,*)
- args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
- arg=
- save_ifs="$IFS"; IFS=','
- for flag in $args; do
- IFS="$save_ifs"
- case $flag in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- flag="\"$flag\""
- ;;
- esac
- arg="$arg $wl$flag"
- compiler_flags="$compiler_flags $flag"
- done
- IFS="$save_ifs"
- arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
- ;;
-
- -Wl,*)
- args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
- arg=
- save_ifs="$IFS"; IFS=','
- for flag in $args; do
- IFS="$save_ifs"
- case $flag in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- flag="\"$flag\""
- ;;
- esac
- arg="$arg $wl$flag"
- compiler_flags="$compiler_flags $wl$flag"
- linker_flags="$linker_flags $flag"
- done
- IFS="$save_ifs"
- arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
- ;;
-
- -Xcompiler)
- prev=xcompiler
- continue
- ;;
-
- -Xlinker)
- prev=xlinker
- continue
- ;;
-
- -XCClinker)
- prev=xcclinker
- continue
- ;;
-
- # Some other compiler flag.
- -* | +*)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- ;;
-
- *.$objext)
- # A standard object.
- objs="$objs $arg"
- ;;
-
- *.lo)
- # A libtool-controlled object.
-
- # Check to see that this really is a libtool object.
- if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- pic_object=
- non_pic_object=
-
- # Read the .lo file
- # If there is no directory component, then add one.
- case $arg in
- */* | *\\*) . $arg ;;
- *) . ./$arg ;;
- esac
-
- if test -z "$pic_object" || \
- test -z "$non_pic_object" ||
- test "$pic_object" = none && \
- test "$non_pic_object" = none; then
- $echo "$modename: cannot find name of object for \`$arg'" 1>&2
- exit 1
- fi
-
- # Extract subdirectory from the argument.
- xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$arg"; then
- xdir=
- else
- xdir="$xdir/"
- fi
-
- if test "$pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- pic_object="$xdir$pic_object"
-
- if test "$prev" = dlfiles; then
- if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
- dlfiles="$dlfiles $pic_object"
- prev=
- continue
- else
- # If libtool objects are unsupported, then we need to preload.
- prev=dlprefiles
- fi
- fi
-
- # CHECK ME: I think I busted this. -Ossama
- if test "$prev" = dlprefiles; then
- # Preload the old-style object.
- dlprefiles="$dlprefiles $pic_object"
- prev=
- fi
-
- # A PIC object.
- libobjs="$libobjs $pic_object"
- arg="$pic_object"
- fi
-
- # Non-PIC object.
- if test "$non_pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- non_pic_object="$xdir$non_pic_object"
-
- # A standard non-PIC object
- non_pic_objects="$non_pic_objects $non_pic_object"
- if test -z "$pic_object" || test "$pic_object" = none ; then
- arg="$non_pic_object"
- fi
- fi
- else
- # Only an error if not doing a dry-run.
- if test -z "$run"; then
- $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
- exit 1
- else
- # Dry-run case.
-
- # Extract subdirectory from the argument.
- xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$arg"; then
- xdir=
- else
- xdir="$xdir/"
- fi
-
- pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
- non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
- libobjs="$libobjs $pic_object"
- non_pic_objects="$non_pic_objects $non_pic_object"
- fi
- fi
- ;;
-
- *.$libext)
- # An archive.
- deplibs="$deplibs $arg"
- old_deplibs="$old_deplibs $arg"
- continue
- ;;
-
- *.la)
- # A libtool-controlled library.
-
- if test "$prev" = dlfiles; then
- # This library was specified with -dlopen.
- dlfiles="$dlfiles $arg"
- prev=
- elif test "$prev" = dlprefiles; then
- # The library was specified with -dlpreopen.
- dlprefiles="$dlprefiles $arg"
- prev=
- else
- deplibs="$deplibs $arg"
- fi
- continue
- ;;
-
- # Some other compiler argument.
- *)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- ;;
- esac # arg
-
- # Now actually substitute the argument into the commands.
- if test -n "$arg"; then
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- fi
- done # argument parsing loop
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Infer tagged configuration to use if any are available and
- # if one wasn't chosen via the "--tag" command line option.
- # Only attempt this if the compiler in the base link
- # command doesn't match the default compiler.
- if test -n "$available_tags" && test -z "$tagname"; then
- case $base_compile in
- # Blanks in the command may have been stripped by the calling shell,
- # but not from the CC environment variable when configure was run.
- "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) ;;
- # Blanks at the start of $base_compile will cause this to fail
- # if we don't check for them as well.
- *)
- for z in $available_tags; do
- if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then
- # Evaluate the configuration.
- eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`"
- case $base_compile in
- "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*)
- # The compiler in $compile_command matches
- # the one in the tagged configuration.
- # Assume this is the tagged configuration we want.
- tagname=$z
- break
- ;;
- esac
- fi
- done
- # If $tagname still isn't set, then no tagged configuration
- # was found and let the user know that the "--tag" command
- # line option must be used.
- if test -z "$tagname"; then
- $echo "$modename: unable to infer tagged configuration"
- $echo "$modename: specify a tag with \`--tag'" 1>&2
- exit 1
-# else
-# $echo "$modename: using $tagname tagged configuration"
- fi
- ;;
- esac
- fi
-
- if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
- eval arg=\"$export_dynamic_flag_spec\"
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- fi
-
- oldlibs=
- # calculate the name of the file, without its directory
- outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
- libobjs_save="$libobjs"
-
- if test -n "$shlibpath_var"; then
- # get the directories listed in $shlibpath_var
- eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
- else
- shlib_search_path=
- fi
- eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
- eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
-
- output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$output_objdir" = "X$output"; then
- output_objdir="$objdir"
- else
- output_objdir="$output_objdir/$objdir"
- fi
- # Create the object directory.
- if test ! -d "$output_objdir"; then
- $show "$mkdir $output_objdir"
- $run $mkdir $output_objdir
- status=$?
- if test "$status" -ne 0 && test ! -d "$output_objdir"; then
- exit $status
- fi
- fi
-
- # Determine the type of output
- case $output in
- "")
- $echo "$modename: you must specify an output file" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
- *.$libext) linkmode=oldlib ;;
- *.lo | *.$objext) linkmode=obj ;;
- *.la) linkmode=lib ;;
- *) linkmode=prog ;; # Anything else should be a program.
- esac
-
- case $host in
- *cygwin* | *mingw* | *pw32*)
- # don't eliminate duplcations in $postdeps and $predeps
- duplicate_compiler_generated_deps=yes
- ;;
- *)
- duplicate_compiler_generated_deps=$duplicate_deps
- ;;
- esac
- specialdeplibs=
-
- libs=
- # Find all interdependent deplibs by searching for libraries
- # that are linked more than once (e.g. -la -lb -la)
- for deplib in $deplibs; do
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- libs="$libs $deplib"
- done
-
- if test "$linkmode" = lib; then
- libs="$predeps $libs $compiler_lib_search_path $postdeps"
-
- # Compute libraries that are listed more than once in $predeps
- # $postdeps and mark them as special (i.e., whose duplicates are
- # not to be eliminated).
- pre_post_deps=
- if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
- for pre_post_dep in $predeps $postdeps; do
- case "$pre_post_deps " in
- *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
- esac
- pre_post_deps="$pre_post_deps $pre_post_dep"
- done
- fi
- pre_post_deps=
- fi
-
- deplibs=
- newdependency_libs=
- newlib_search_path=
- need_relink=no # whether we're linking any uninstalled libtool libraries
- notinst_deplibs= # not-installed libtool libraries
- notinst_path= # paths that contain not-installed libtool libraries
- case $linkmode in
- lib)
- passes="conv link"
- for file in $dlfiles $dlprefiles; do
- case $file in
- *.la) ;;
- *)
- $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
- exit 1
- ;;
- esac
- done
- ;;
- prog)
- compile_deplibs=
- finalize_deplibs=
- alldeplibs=no
- newdlfiles=
- newdlprefiles=
- passes="conv scan dlopen dlpreopen link"
- ;;
- *) passes="conv"
- ;;
- esac
- for pass in $passes; do
- if test "$linkmode,$pass" = "lib,link" ||
- test "$linkmode,$pass" = "prog,scan"; then
- libs="$deplibs"
- deplibs=
- fi
- if test "$linkmode" = prog; then
- case $pass in
- dlopen) libs="$dlfiles" ;;
- dlpreopen) libs="$dlprefiles" ;;
- link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
- esac
- fi
- if test "$pass" = dlopen; then
- # Collect dlpreopened libraries
- save_deplibs="$deplibs"
- deplibs=
- fi
- for deplib in $libs; do
- lib=
- found=no
- case $deplib in
- -l*)
- if test "$linkmode" != lib && test "$linkmode" != prog; then
- $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
- continue
- fi
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
- for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
- # Search the libtool library
- lib="$searchdir/lib${name}.la"
- if test -f "$lib"; then
- found=yes
- break
- fi
- done
- if test "$found" != yes; then
- # deplib doesn't seem to be a libtool library
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- deplibs="$deplib $deplibs"
- test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
- fi
- continue
- else # deplib is a libtool library
- # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
- # We need to do some special things here, and not later.
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $deplib "*)
- if (${SED} -e '2q' $lib |
- grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- library_names=
- old_library=
- case $lib in
- */* | *\\*) . $lib ;;
- *) . ./$lib ;;
- esac
- for l in $old_library $library_names; do
- ll="$l"
- done
- if test "X$ll" = "X$old_library" ; then # only static version available
- found=no
- ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
- test "X$ladir" = "X$lib" && ladir="."
- lib=$ladir/$old_library
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- deplibs="$deplib $deplibs"
- test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
- fi
- continue
- fi
- fi
- ;;
- *) ;;
- esac
- fi
- fi
- ;; # -l
- -L*)
- case $linkmode in
- lib)
- deplibs="$deplib $deplibs"
- test "$pass" = conv && continue
- newdependency_libs="$deplib $newdependency_libs"
- newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
- ;;
- prog)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- if test "$pass" = scan; then
- deplibs="$deplib $deplibs"
- newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
- else
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- fi
- ;;
- *)
- $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
- ;;
- esac # linkmode
- continue
- ;; # -L
- -R*)
- if test "$pass" = link; then
- dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
- # Make sure the xrpath contains only unique directories.
- case "$xrpath " in
- *" $dir "*) ;;
- *) xrpath="$xrpath $dir" ;;
- esac
- fi
- deplibs="$deplib $deplibs"
- continue
- ;;
- *.la) lib="$deplib" ;;
- *.$libext)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- case $linkmode in
- lib)
- if test "$deplibs_check_method" != pass_all; then
- $echo
- $echo "*** Warning: Trying to link with static lib archive $deplib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because the file extensions .$libext of this argument makes me believe"
- $echo "*** that it is just a static archive that I should not used here."
- else
- $echo
- $echo "*** Warning: Linking the shared library $output against the"
- $echo "*** static library $deplib is not portable!"
- deplibs="$deplib $deplibs"
- fi
- continue
- ;;
- prog)
- if test "$pass" != link; then
- deplibs="$deplib $deplibs"
- else
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- fi
- continue
- ;;
- esac # linkmode
- ;; # *.$libext
- *.lo | *.$objext)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- elif test "$linkmode" = prog; then
- if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
- # If there is no dlopen support or we're linking statically,
- # we need to preload.
- newdlprefiles="$newdlprefiles $deplib"
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- newdlfiles="$newdlfiles $deplib"
- fi
- fi
- continue
- ;;
- %DEPLIBS%)
- alldeplibs=yes
- continue
- ;;
- esac # case $deplib
- if test "$found" = yes || test -f "$lib"; then :
- else
- $echo "$modename: cannot find the library \`$lib'" 1>&2
- exit 1
- fi
-
- # Check to see that this really is a libtool archive.
- if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- exit 1
- fi
-
- ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
- test "X$ladir" = "X$lib" && ladir="."
-
- dlname=
- dlopen=
- dlpreopen=
- libdir=
- library_names=
- old_library=
- # If the library was installed with an old release of libtool,
- # it will not redefine variables installed, or shouldnotlink
- installed=yes
- shouldnotlink=no
-
- # Read the .la file
- case $lib in
- */* | *\\*) . $lib ;;
- *) . ./$lib ;;
- esac
-
- if test "$linkmode,$pass" = "lib,link" ||
- test "$linkmode,$pass" = "prog,scan" ||
- { test "$linkmode" != prog && test "$linkmode" != lib; }; then
- test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
- test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
- fi
-
- if test "$pass" = conv; then
- # Only check for convenience libraries
- deplibs="$lib $deplibs"
- if test -z "$libdir"; then
- if test -z "$old_library"; then
- $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
- exit 1
- fi
- # It is a libtool convenience library, so add in its objects.
- convenience="$convenience $ladir/$objdir/$old_library"
- old_convenience="$old_convenience $ladir/$objdir/$old_library"
- tmp_libs=
- for deplib in $dependency_libs; do
- deplibs="$deplib $deplibs"
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done
- elif test "$linkmode" != prog && test "$linkmode" != lib; then
- $echo "$modename: \`$lib' is not a convenience library" 1>&2
- exit 1
- fi
- continue
- fi # $pass = conv
-
-
- # Get the name of the library we link against.
- linklib=
- for l in $old_library $library_names; do
- linklib="$l"
- done
- if test -z "$linklib"; then
- $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
- exit 1
- fi
-
- # This library was specified with -dlopen.
- if test "$pass" = dlopen; then
- if test -z "$libdir"; then
- $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
- exit 1
- fi
- if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
- # If there is no dlname, no dlopen support or we're linking
- # statically, we need to preload. We also need to preload any
- # dependent libraries so libltdl's deplib preloader doesn't
- # bomb out in the load deplibs phase.
- dlprefiles="$dlprefiles $lib $dependency_libs"
- else
- newdlfiles="$newdlfiles $lib"
- fi
- continue
- fi # $pass = dlopen
-
- # We need an absolute path.
- case $ladir in
- [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
- *)
- abs_ladir=`cd "$ladir" && pwd`
- if test -z "$abs_ladir"; then
- $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
- $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
- abs_ladir="$ladir"
- fi
- ;;
- esac
- laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
-
- # Find the relevant object directory and library name.
- if test "X$installed" = Xyes; then
- if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
- $echo "$modename: warning: library \`$lib' was moved." 1>&2
- dir="$ladir"
- absdir="$abs_ladir"
- libdir="$abs_ladir"
- else
- dir="$libdir"
- absdir="$libdir"
- fi
- else
- dir="$ladir/$objdir"
- absdir="$abs_ladir/$objdir"
- # Remove this search path later
- notinst_path="$notinst_path $abs_ladir"
- fi # $installed = yes
- name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
-
- # This library was specified with -dlpreopen.
- if test "$pass" = dlpreopen; then
- if test -z "$libdir"; then
- $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
- exit 1
- fi
- # Prefer using a static library (so that no silly _DYNAMIC symbols
- # are required to link).
- if test -n "$old_library"; then
- newdlprefiles="$newdlprefiles $dir/$old_library"
- # Otherwise, use the dlname, so that lt_dlopen finds it.
- elif test -n "$dlname"; then
- newdlprefiles="$newdlprefiles $dir/$dlname"
- else
- newdlprefiles="$newdlprefiles $dir/$linklib"
- fi
- fi # $pass = dlpreopen
-
- if test -z "$libdir"; then
- # Link the convenience library
- if test "$linkmode" = lib; then
- deplibs="$dir/$old_library $deplibs"
- elif test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$dir/$old_library $compile_deplibs"
- finalize_deplibs="$dir/$old_library $finalize_deplibs"
- else
- deplibs="$lib $deplibs" # used for prog,scan pass
- fi
- continue
- fi
-
-
- if test "$linkmode" = prog && test "$pass" != link; then
- newlib_search_path="$newlib_search_path $ladir"
- deplibs="$lib $deplibs"
-
- linkalldeplibs=no
- if test "$link_all_deplibs" != no || test -z "$library_names" ||
- test "$build_libtool_libs" = no; then
- linkalldeplibs=yes
- fi
-
- tmp_libs=
- for deplib in $dependency_libs; do
- case $deplib in
- -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
- esac
- # Need to link against all dependency_libs?
- if test "$linkalldeplibs" = yes; then
- deplibs="$deplib $deplibs"
- else
- # Need to hardcode shared library paths
- # or/and link against static libraries
- newdependency_libs="$deplib $newdependency_libs"
- fi
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done # for deplib
- continue
- fi # $linkmode = prog...
-
- if test "$linkmode,$pass" = "prog,link"; then
- if test -n "$library_names" &&
- { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
- # We need to hardcode the library path
- if test -n "$shlibpath_var"; then
- # Make sure the rpath contains only unique directories.
- case "$temp_rpath " in
- *" $dir "*) ;;
- *" $absdir "*) ;;
- *) temp_rpath="$temp_rpath $dir" ;;
- esac
- fi
-
- # Hardcode the library path.
- # Skip directories that are in the system default run-time
- # search path.
- case " $sys_lib_dlsearch_path " in
- *" $absdir "*) ;;
- *)
- case "$compile_rpath " in
- *" $absdir "*) ;;
- *) compile_rpath="$compile_rpath $absdir"
- esac
- ;;
- esac
- case " $sys_lib_dlsearch_path " in
- *" $libdir "*) ;;
- *)
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir"
- esac
- ;;
- esac
- fi # $linkmode,$pass = prog,link...
-
- if test "$alldeplibs" = yes &&
- { test "$deplibs_check_method" = pass_all ||
- { test "$build_libtool_libs" = yes &&
- test -n "$library_names"; }; }; then
- # We only need to search for static libraries
- continue
- fi
- fi
-
- link_static=no # Whether the deplib will be linked statically
- if test -n "$library_names" &&
- { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
- if test "$installed" = no; then
- notinst_deplibs="$notinst_deplibs $lib"
- need_relink=yes
- fi
- # This is a shared library
-
- # Warn about portability, can't link against -module's on some systems (darwin)
- if test "$shouldnotlink" = yes && test "$pass" = link ; then
- $echo
- if test "$linkmode" = prog; then
- $echo "*** Warning: Linking the executable $output against the loadable module"
- else
- $echo "*** Warning: Linking the shared library $output against the loadable module"
- fi
- $echo "*** $linklib is not portable!"
- fi
- if test "$linkmode" = lib &&
- test "$hardcode_into_libs" = yes; then
- # Hardcode the library path.
- # Skip directories that are in the system default run-time
- # search path.
- case " $sys_lib_dlsearch_path " in
- *" $absdir "*) ;;
- *)
- case "$compile_rpath " in
- *" $absdir "*) ;;
- *) compile_rpath="$compile_rpath $absdir"
- esac
- ;;
- esac
- case " $sys_lib_dlsearch_path " in
- *" $libdir "*) ;;
- *)
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir"
- esac
- ;;
- esac
- fi
-
- if test -n "$old_archive_from_expsyms_cmds"; then
- # figure out the soname
- set dummy $library_names
- realname="$2"
- shift; shift
- libname=`eval \\$echo \"$libname_spec\"`
- # use dlname if we got it. it's perfectly good, no?
- if test -n "$dlname"; then
- soname="$dlname"
- elif test -n "$soname_spec"; then
- # bleh windows
- case $host in
- *cygwin* | mingw*)
- major=`expr $current - $age`
- versuffix="-$major"
- ;;
- esac
- eval soname=\"$soname_spec\"
- else
- soname="$realname"
- fi
-
- # Make a new name for the extract_expsyms_cmds to use
- soroot="$soname"
- soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
- newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
-
- # If the library has no export list, then create one now
- if test -f "$output_objdir/$soname-def"; then :
- else
- $show "extracting exported symbol list from \`$soname'"
- save_ifs="$IFS"; IFS='~'
- eval cmds=\"$extract_expsyms_cmds\"
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
-
- # Create $newlib
- if test -f "$output_objdir/$newlib"; then :; else
- $show "generating import library for \`$soname'"
- save_ifs="$IFS"; IFS='~'
- eval cmds=\"$old_archive_from_expsyms_cmds\"
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
- # make sure the library variables are pointing to the new library
- dir=$output_objdir
- linklib=$newlib
- fi # test -n "$old_archive_from_expsyms_cmds"
-
- if test "$linkmode" = prog || test "$mode" != relink; then
- add_shlibpath=
- add_dir=
- add=
- lib_linked=yes
- case $hardcode_action in
- immediate | unsupported)
- if test "$hardcode_direct" = no; then
- add="$dir/$linklib"
- case $host in
- *-*-sco3.2v5* ) add_dir="-L$dir" ;;
- *-*-darwin* )
- # if the lib is a module then we can not link against it, someone
- # is ignoring the new warnings I added
- if /usr/bin/file -L $add 2> /dev/null | grep "bundle" >/dev/null ; then
- $echo "** Warning, lib $linklib is a module, not a shared library"
- if test -z "$old_library" ; then
- $echo
- $echo "** And there doesn't seem to be a static archive available"
- $echo "** The link will probably fail, sorry"
- else
- add="$dir/$old_library"
- fi
- fi
- esac
- elif test "$hardcode_minus_L" = no; then
- case $host in
- *-*-sunos*) add_shlibpath="$dir" ;;
- esac
- add_dir="-L$dir"
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = no; then
- add_shlibpath="$dir"
- add="-l$name"
- else
- lib_linked=no
- fi
- ;;
- relink)
- if test "$hardcode_direct" = yes; then
- add="$dir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- add_dir="-L$dir"
- # Try looking first in the location we're being installed to.
- if test -n "$inst_prefix_dir"; then
- case "$libdir" in
- [\\/]*)
- add_dir="-L$inst_prefix_dir$libdir $add_dir"
- ;;
- esac
- fi
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- add_shlibpath="$dir"
- add="-l$name"
- else
- lib_linked=no
- fi
- ;;
- *) lib_linked=no ;;
- esac
-
- if test "$lib_linked" != yes; then
- $echo "$modename: configuration error: unsupported hardcode properties"
- exit 1
- fi
-
- if test -n "$add_shlibpath"; then
- case :$compile_shlibpath: in
- *":$add_shlibpath:"*) ;;
- *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
- esac
- fi
- if test "$linkmode" = prog; then
- test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
- test -n "$add" && compile_deplibs="$add $compile_deplibs"
- else
- test -n "$add_dir" && deplibs="$add_dir $deplibs"
- test -n "$add" && deplibs="$add $deplibs"
- if test "$hardcode_direct" != yes && \
- test "$hardcode_minus_L" != yes && \
- test "$hardcode_shlibpath_var" = yes; then
- case :$finalize_shlibpath: in
- *":$libdir:"*) ;;
- *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
- esac
- fi
- fi
- fi
-
- if test "$linkmode" = prog || test "$mode" = relink; then
- add_shlibpath=
- add_dir=
- add=
- # Finalize command for both is simple: just hardcode it.
- if test "$hardcode_direct" = yes; then
- add="$libdir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- add_dir="-L$libdir"
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- case :$finalize_shlibpath: in
- *":$libdir:"*) ;;
- *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
- esac
- add="-l$name"
- elif test "$hardcode_automatic" = yes; then
- if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then
- add="$inst_prefix_dir$libdir/$linklib"
- else
- add="$libdir/$linklib"
- fi
- else
- # We cannot seem to hardcode it, guess we'll fake it.
- add_dir="-L$libdir"
- # Try looking first in the location we're being installed to.
- if test -n "$inst_prefix_dir"; then
- case "$libdir" in
- [\\/]*)
- add_dir="-L$inst_prefix_dir$libdir $add_dir"
- ;;
- esac
- fi
- add="-l$name"
- fi
-
- if test "$linkmode" = prog; then
- test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
- test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
- else
- test -n "$add_dir" && deplibs="$add_dir $deplibs"
- test -n "$add" && deplibs="$add $deplibs"
- fi
- fi
- elif test "$linkmode" = prog; then
- # Here we assume that one of hardcode_direct or hardcode_minus_L
- # is not unsupported. This is valid on all known static and
- # shared platforms.
- if test "$hardcode_direct" != unsupported; then
- test -n "$old_library" && linklib="$old_library"
- compile_deplibs="$dir/$linklib $compile_deplibs"
- finalize_deplibs="$dir/$linklib $finalize_deplibs"
- else
- compile_deplibs="-l$name -L$dir $compile_deplibs"
- finalize_deplibs="-l$name -L$dir $finalize_deplibs"
- fi
- elif test "$build_libtool_libs" = yes; then
- # Not a shared library
- if test "$deplibs_check_method" != pass_all; then
- # We're trying link a shared library against a static one
- # but the system doesn't support it.
-
- # Just print a warning and add the library to dependency_libs so
- # that the program can be linked against the static library.
- $echo
- $echo "*** Warning: This system can not link to static lib archive $lib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have."
- if test "$module" = yes; then
- $echo "*** But as you try to build a module library, libtool will still create "
- $echo "*** a static module, that should work as long as the dlopening application"
- $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
- if test -z "$global_symbol_pipe"; then
- $echo
- $echo "*** However, this would only work if libtool was able to extract symbol"
- $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
- $echo "*** not find such a program. So, this module is probably useless."
- $echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- fi
- else
- convenience="$convenience $dir/$old_library"
- old_convenience="$old_convenience $dir/$old_library"
- deplibs="$dir/$old_library $deplibs"
- link_static=yes
- fi
- fi # link shared/static library?
-
- if test "$linkmode" = lib; then
- if test -n "$dependency_libs" &&
- { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes ||
- test "$link_static" = yes; }; then
- # Extract -R from dependency_libs
- temp_deplibs=
- for libdir in $dependency_libs; do
- case $libdir in
- -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
- case " $xrpath " in
- *" $temp_xrpath "*) ;;
- *) xrpath="$xrpath $temp_xrpath";;
- esac;;
- *) temp_deplibs="$temp_deplibs $libdir";;
- esac
- done
- dependency_libs="$temp_deplibs"
- fi
-
- newlib_search_path="$newlib_search_path $absdir"
- # Link against this library
- test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
- # ... and its dependency_libs
- tmp_libs=
- for deplib in $dependency_libs; do
- newdependency_libs="$deplib $newdependency_libs"
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done
-
- if test "$link_all_deplibs" != no; then
- # Add the search paths of all dependency libraries
- for deplib in $dependency_libs; do
- case $deplib in
- -L*) path="$deplib" ;;
- *.la)
- dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$deplib" && dir="."
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
- absdir="$dir"
- fi
- ;;
- esac
- if grep "^installed=no" $deplib > /dev/null; then
- path="$absdir/$objdir"
- else
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- if test -z "$libdir"; then
- $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
- exit 1
- fi
- if test "$absdir" != "$libdir"; then
- $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
- fi
- path="$absdir"
- fi
- depdepl=
- case $host in
- *-*-darwin*)
- # we do not want to link against static libs, but need to link against shared
- eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
- if test -n "$deplibrary_names" ; then
- for tmp in $deplibrary_names ; do
- depdepl=$tmp
- done
- if test -f "$path/$depdepl" ; then
- depdepl="$path/$depdepl"
- fi
- newlib_search_path="$newlib_search_path $path"
- path=""
- fi
- ;;
- *)
- path="-L$path"
- ;;
- esac
-
- ;;
- -l*)
- case $host in
- *-*-darwin*)
- # Again, we only want to link against shared libraries
- eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
- for tmp in $newlib_search_path ; do
- if test -f "$tmp/lib$tmp_libs.dylib" ; then
- eval depdepl="$tmp/lib$tmp_libs.dylib"
- break
- fi
- done
- path=""
- ;;
- *) continue ;;
- esac
- ;;
- *) continue ;;
- esac
- case " $deplibs " in
- *" $depdepl "*) ;;
- *) deplibs="$deplibs $depdepl" ;;
- esac
- case " $deplibs " in
- *" $path "*) ;;
- *) deplibs="$deplibs $path" ;;
- esac
- done
- fi # link_all_deplibs != no
- fi # linkmode = lib
- done # for deplib in $libs
- dependency_libs="$newdependency_libs"
- if test "$pass" = dlpreopen; then
- # Link the dlpreopened libraries before other libraries
- for deplib in $save_deplibs; do
- deplibs="$deplib $deplibs"
- done
- fi
- if test "$pass" != dlopen; then
- if test "$pass" != conv; then
- # Make sure lib_search_path contains only unique directories.
- lib_search_path=
- for dir in $newlib_search_path; do
- case "$lib_search_path " in
- *" $dir "*) ;;
- *) lib_search_path="$lib_search_path $dir" ;;
- esac
- done
- newlib_search_path=
- fi
-
- if test "$linkmode,$pass" != "prog,link"; then
- vars="deplibs"
- else
- vars="compile_deplibs finalize_deplibs"
- fi
- for var in $vars dependency_libs; do
- # Add libraries to $var in reverse order
- eval tmp_libs=\"\$$var\"
- new_libs=
- for deplib in $tmp_libs; do
- # FIXME: Pedantically, this is the right thing to do, so
- # that some nasty dependency loop isn't accidentally
- # broken:
- #new_libs="$deplib $new_libs"
- # Pragmatically, this seems to cause very few problems in
- # practice:
- case $deplib in
- -L*) new_libs="$deplib $new_libs" ;;
- -R*) ;;
- *)
- # And here is the reason: when a library appears more
- # than once as an explicit dependence of a library, or
- # is implicitly linked in more than once by the
- # compiler, it is considered special, and multiple
- # occurrences thereof are not removed. Compare this
- # with having the same library being listed as a
- # dependency of multiple other libraries: in this case,
- # we know (pedantically, we assume) the library does not
- # need to be listed more than once, so we keep only the
- # last copy. This is not always right, but it is rare
- # enough that we require users that really mean to play
- # such unportable linking tricks to link the library
- # using -Wl,-lname, so that libtool does not consider it
- # for duplicate removal.
- case " $specialdeplibs " in
- *" $deplib "*) new_libs="$deplib $new_libs" ;;
- *)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$deplib $new_libs" ;;
- esac
- ;;
- esac
- ;;
- esac
- done
- tmp_libs=
- for deplib in $new_libs; do
- case $deplib in
- -L*)
- case " $tmp_libs " in
- *" $deplib "*) ;;
- *) tmp_libs="$tmp_libs $deplib" ;;
- esac
- ;;
- *) tmp_libs="$tmp_libs $deplib" ;;
- esac
- done
- eval $var=\"$tmp_libs\"
- done # for var
- fi
- # Last step: remove runtime libs from dependency_libs (they stay in deplibs)
- tmp_libs=
- for i in $dependency_libs ; do
- case " $predeps $postdeps $compiler_lib_search_path " in
- *" $i "*)
- i=""
- ;;
- esac
- if test -n "$i" ; then
- tmp_libs="$tmp_libs $i"
- fi
- done
- dependency_libs=$tmp_libs
- done # for pass
- if test "$linkmode" = prog; then
- dlfiles="$newdlfiles"
- dlprefiles="$newdlprefiles"
- fi
-
- case $linkmode in
- oldlib)
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
- fi
-
- if test -n "$rpath"; then
- $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
- fi
-
- if test -n "$xrpath"; then
- $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
- fi
-
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
- fi
-
- # Now set the variables for building old libraries.
- build_libtool_libs=no
- oldlibs="$output"
- objs="$objs$old_deplibs"
- ;;
-
- lib)
- # Make sure we only generate libraries of the form `libNAME.la'.
- case $outputname in
- lib*)
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
- eval shared_ext=\"$shrext\"
- eval libname=\"$libname_spec\"
- ;;
- *)
- if test "$module" = no; then
- $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
- if test "$need_lib_prefix" != no; then
- # Add the "lib" prefix for modules if required
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
- eval shared_ext=\"$shrext\"
- eval libname=\"$libname_spec\"
- else
- libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
- fi
- ;;
- esac
-
- if test -n "$objs"; then
- if test "$deplibs_check_method" != pass_all; then
- $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
- exit 1
- else
- $echo
- $echo "*** Warning: Linking the shared library $output against the non-libtool"
- $echo "*** objects $objs is not portable!"
- libobjs="$libobjs $objs"
- fi
- fi
-
- if test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
- fi
-
- set dummy $rpath
- if test "$#" -gt 2; then
- $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
- fi
- install_libdir="$2"
-
- oldlibs=
- if test -z "$rpath"; then
- if test "$build_libtool_libs" = yes; then
- # Building a libtool convenience library.
- # Some compilers have problems with a `.al' extension so
- # convenience libraries should have the same extension an
- # archive normally would.
- oldlibs="$output_objdir/$libname.$libext $oldlibs"
- build_libtool_libs=convenience
- build_old_libs=yes
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
- fi
- else
-
- # Parse the version information argument.
- save_ifs="$IFS"; IFS=':'
- set dummy $vinfo 0 0 0
- IFS="$save_ifs"
-
- if test -n "$8"; then
- $echo "$modename: too many parameters to \`-version-info'" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- # convert absolute version numbers to libtool ages
- # this retains compatibility with .la files and attempts
- # to make the code below a bit more comprehensible
-
- case $vinfo_number in
- yes)
- number_major="$2"
- number_minor="$3"
- number_revision="$4"
- #
- # There are really only two kinds -- those that
- # use the current revision as the major version
- # and those that subtract age and use age as
- # a minor version. But, then there is irix
- # which has an extra 1 added just for fun
- #
- case $version_type in
- darwin|linux|osf|windows)
- current=`expr $number_major + $number_minor`
- age="$number_minor"
- revision="$number_revision"
- ;;
- freebsd-aout|freebsd-elf|sunos)
- current="$number_major"
- revision="$number_minor"
- age="0"
- ;;
- irix|nonstopux)
- current=`expr $number_major + $number_minor - 1`
- age="$number_minor"
- revision="$number_minor"
- ;;
- esac
- ;;
- no)
- current="$2"
- revision="$3"
- age="$4"
- ;;
- esac
-
- # Check that each of the things are valid numbers.
- case $current in
- 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
- *)
- $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit 1
- ;;
- esac
-
- case $revision in
- 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
- *)
- $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit 1
- ;;
- esac
-
- case $age in
- 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
- *)
- $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit 1
- ;;
- esac
-
- if test "$age" -gt "$current"; then
- $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit 1
- fi
-
- # Calculate the version variables.
- major=
- versuffix=
- verstring=
- case $version_type in
- none) ;;
-
- darwin)
- # Like Linux, but with the current version available in
- # verstring for coding it into the library header
- major=.`expr $current - $age`
- versuffix="$major.$age.$revision"
- # Darwin ld doesn't like 0 for these options...
- minor_current=`expr $current + 1`
- verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
- ;;
-
- freebsd-aout)
- major=".$current"
- versuffix=".$current.$revision";
- ;;
-
- freebsd-elf)
- major=".$current"
- versuffix=".$current";
- ;;
-
- irix | nonstopux)
- major=`expr $current - $age + 1`
-
- case $version_type in
- nonstopux) verstring_prefix=nonstopux ;;
- *) verstring_prefix=sgi ;;
- esac
- verstring="$verstring_prefix$major.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$revision
- while test "$loop" -ne 0; do
- iface=`expr $revision - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring_prefix$major.$iface:$verstring"
- done
-
- # Before this point, $major must not contain `.'.
- major=.$major
- versuffix="$major.$revision"
- ;;
-
- linux)
- major=.`expr $current - $age`
- versuffix="$major.$age.$revision"
- ;;
-
- osf)
- major=.`expr $current - $age`
- versuffix=".$current.$age.$revision"
- verstring="$current.$age.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$age
- while test "$loop" -ne 0; do
- iface=`expr $current - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring:${iface}.0"
- done
-
- # Make executables depend on our current version.
- verstring="$verstring:${current}.0"
- ;;
-
- sunos)
- major=".$current"
- versuffix=".$current.$revision"
- ;;
-
- windows)
- # Use '-' rather than '.', since we only want one
- # extension on DOS 8.3 filesystems.
- major=`expr $current - $age`
- versuffix="-$major"
- ;;
-
- *)
- $echo "$modename: unknown library version type \`$version_type'" 1>&2
- $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit 1
- ;;
- esac
-
- # Clear the version info if we defaulted, and they specified a release.
- if test -z "$vinfo" && test -n "$release"; then
- major=
- case $version_type in
- darwin)
- # we can't check for "0.0" in archive_cmds due to quoting
- # problems, so we reset it completely
- verstring=
- ;;
- *)
- verstring="0.0"
- ;;
- esac
- if test "$need_version" = no; then
- versuffix=
- else
- versuffix=".0.0"
- fi
- fi
-
- # Remove version info from name if versioning should be avoided
- if test "$avoid_version" = yes && test "$need_version" = no; then
- major=
- versuffix=
- verstring=""
- fi
-
- # Check to see if the archive will have undefined symbols.
- if test "$allow_undefined" = yes; then
- if test "$allow_undefined_flag" = unsupported; then
- $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
- build_libtool_libs=no
- build_old_libs=yes
- fi
- else
- # Don't allow undefined symbols.
- allow_undefined_flag="$no_undefined_flag"
- fi
- fi
-
- if test "$mode" != relink; then
- # Remove our outputs, but don't remove object files since they
- # may have been created when compiling PIC objects.
- removelist=
- tempremovelist=`$echo "$output_objdir/*"`
- for p in $tempremovelist; do
- case $p in
- *.$objext)
- ;;
- $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
- removelist="$removelist $p"
- ;;
- *) ;;
- esac
- done
- if test -n "$removelist"; then
- $show "${rm}r $removelist"
- $run ${rm}r $removelist
- fi
- fi
-
- # Now set the variables for building old libraries.
- if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
- oldlibs="$oldlibs $output_objdir/$libname.$libext"
-
- # Transform .lo files to .o files.
- oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
- fi
-
- # Eliminate all temporary directories.
- for path in $notinst_path; do
- lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
- deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
- dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
- done
-
- if test -n "$xrpath"; then
- # If the user specified any rpath flags, then add them.
- temp_xrpath=
- for libdir in $xrpath; do
- temp_xrpath="$temp_xrpath -R$libdir"
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
- dependency_libs="$temp_xrpath $dependency_libs"
- fi
- fi
-
- # Make sure dlfiles contains only unique files that won't be dlpreopened
- old_dlfiles="$dlfiles"
- dlfiles=
- for lib in $old_dlfiles; do
- case " $dlprefiles $dlfiles " in
- *" $lib "*) ;;
- *) dlfiles="$dlfiles $lib" ;;
- esac
- done
-
- # Make sure dlprefiles contains only unique files
- old_dlprefiles="$dlprefiles"
- dlprefiles=
- for lib in $old_dlprefiles; do
- case "$dlprefiles " in
- *" $lib "*) ;;
- *) dlprefiles="$dlprefiles $lib" ;;
- esac
- done
-
- if test "$build_libtool_libs" = yes; then
- if test -n "$rpath"; then
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
- # these systems don't actually have a c library (as such)!
- ;;
- *-*-rhapsody* | *-*-darwin1.[012])
- # Rhapsody C library is in the System framework
- deplibs="$deplibs -framework System"
- ;;
- *-*-netbsd*)
- # Don't link with libc until the a.out ld.so is fixed.
- ;;
- *-*-openbsd* | *-*-freebsd*)
- # Do not include libc due to us having libc/libc_r.
- test "X$arg" = "X-lc" && continue
- ;;
- *)
- # Add libc to deplibs on all other systems if necessary.
- if test "$build_libtool_need_lc" = "yes"; then
- deplibs="$deplibs -lc"
- fi
- ;;
- esac
- fi
-
- # Transform deplibs into only deplibs that can be linked in shared.
- name_save=$name
- libname_save=$libname
- release_save=$release
- versuffix_save=$versuffix
- major_save=$major
- # I'm not sure if I'm treating the release correctly. I think
- # release should show up in the -l (ie -lgmp5) so we don't want to
- # add it in twice. Is that correct?
- release=""
- versuffix=""
- major=""
- newdeplibs=
- droppeddeps=no
- case $deplibs_check_method in
- pass_all)
- # Don't check for shared/static. Everything works.
- # This might be a little naive. We might want to check
- # whether the library exists or not. But this is on
- # osf3 & osf4 and I'm not really sure... Just
- # implementing what was already the behavior.
- newdeplibs=$deplibs
- ;;
- test_compile)
- # This code stresses the "libraries are programs" paradigm to its
- # limits. Maybe even breaks it. We compile a program, linking it
- # against the deplibs as a proxy for the library. Then we can check
- # whether they linked in statically or dynamically with ldd.
- $rm conftest.c
- cat > conftest.c <<EOF
- int main() { return 0; }
-EOF
- $rm conftest
- $LTCC -o conftest conftest.c $deplibs
- if test "$?" -eq 0 ; then
- ldd_output=`ldd conftest`
- for i in $deplibs; do
- name="`expr $i : '-l\(.*\)'`"
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" -ne "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $i "*)
- newdeplibs="$newdeplibs $i"
- i=""
- ;;
- esac
- fi
- if test -n "$i" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- deplib_matches=`eval \\$echo \"$library_names_spec\"`
- set dummy $deplib_matches
- deplib_match=$2
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning: dynamic linker does not accept needed library $i."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which I believe you do not have"
- $echo "*** because a test_compile did reveal that the linker did not use it for"
- $echo "*** its dynamic dependency list that programs get resolved with at runtime."
- fi
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- else
- # Error occurred in the first compile. Let's try to salvage
- # the situation: Compile a separate program for each library.
- for i in $deplibs; do
- name="`expr $i : '-l\(.*\)'`"
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" != "0"; then
- $rm conftest
- $LTCC -o conftest conftest.c $i
- # Did it work?
- if test "$?" -eq 0 ; then
- ldd_output=`ldd conftest`
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $i "*)
- newdeplibs="$newdeplibs $i"
- i=""
- ;;
- esac
- fi
- if test -n "$i" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- deplib_matches=`eval \\$echo \"$library_names_spec\"`
- set dummy $deplib_matches
- deplib_match=$2
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning: dynamic linker does not accept needed library $i."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because a test_compile did reveal that the linker did not use this one"
- $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
- fi
- fi
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning! Library $i is needed by this library but I was not able to"
- $echo "*** make it link in! You will probably need to install it or some"
- $echo "*** library that it depends on before this library will be fully"
- $echo "*** functional. Installing it before continuing would be even better."
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- fi
- ;;
- file_magic*)
- set dummy $deplibs_check_method
- file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- for a_deplib in $deplibs; do
- name="`expr $a_deplib : '-l\(.*\)'`"
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" != "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $a_deplib "*)
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- ;;
- esac
- fi
- if test -n "$a_deplib" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- # Follow soft links.
- if ls -lLd "$potent_lib" 2>/dev/null \
- | grep " -> " >/dev/null; then
- continue
- fi
- # The statement above tries to avoid entering an
- # endless loop below, in case of cyclic links.
- # We might still enter an endless loop, since a link
- # loop can be closed while we follow links,
- # but so what?
- potlib="$potent_lib"
- while test -h "$potlib" 2>/dev/null; do
- potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
- case $potliblink in
- [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
- *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
- esac
- done
- if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
- | ${SED} 10q \
- | $EGREP "$file_magic_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- $echo
- $echo "*** Warning: linker path does not have real file for library $a_deplib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
- $echo "*** with $libname but no candidates were found. (...for file magic test)"
- else
- $echo "*** with $libname and none of the candidates passed a file format test"
- $echo "*** using a file magic. Last file checked: $potlib"
- fi
- fi
- else
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- fi
- done # Gone through all deplibs.
- ;;
- match_pattern*)
- set dummy $deplibs_check_method
- match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- for a_deplib in $deplibs; do
- name="`expr $a_deplib : '-l\(.*\)'`"
- # If $name is empty we are operating on a -L argument.
- if test -n "$name" && test "$name" != "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $a_deplib "*)
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- ;;
- esac
- fi
- if test -n "$a_deplib" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- potlib="$potent_lib" # see symlink-check above in file_magic test
- if eval $echo \"$potent_lib\" 2>/dev/null \
- | ${SED} 10q \
- | $EGREP "$match_pattern_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- $echo
- $echo "*** Warning: linker path does not have real file for library $a_deplib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
- $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
- else
- $echo "*** with $libname and none of the candidates passed a file format test"
- $echo "*** using a regex pattern. Last file checked: $potlib"
- fi
- fi
- else
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- fi
- done # Gone through all deplibs.
- ;;
- none | unknown | *)
- newdeplibs=""
- tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
- -e 's/ -[LR][^ ]*//g'`
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- for i in $predeps $postdeps ; do
- # can't use Xsed below, because $i might contain '/'
- tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
- done
- fi
- if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
- | grep . >/dev/null; then
- $echo
- if test "X$deplibs_check_method" = "Xnone"; then
- $echo "*** Warning: inter-library dependencies are not supported in this platform."
- else
- $echo "*** Warning: inter-library dependencies are not known to be supported."
- fi
- $echo "*** All declared inter-library dependencies are being dropped."
- droppeddeps=yes
- fi
- ;;
- esac
- versuffix=$versuffix_save
- major=$major_save
- release=$release_save
- libname=$libname_save
- name=$name_save
-
- case $host in
- *-*-rhapsody* | *-*-darwin1.[012])
- # On Rhapsody replace the C library is the System framework
- newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
- ;;
- esac
-
- if test "$droppeddeps" = yes; then
- if test "$module" = yes; then
- $echo
- $echo "*** Warning: libtool could not satisfy all declared inter-library"
- $echo "*** dependencies of module $libname. Therefore, libtool will create"
- $echo "*** a static module, that should work as long as the dlopening"
- $echo "*** application is linked with the -dlopen flag."
- if test -z "$global_symbol_pipe"; then
- $echo
- $echo "*** However, this would only work if libtool was able to extract symbol"
- $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
- $echo "*** not find such a program. So, this module is probably useless."
- $echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- else
- $echo "*** The inter-library dependencies that have been dropped here will be"
- $echo "*** automatically added whenever a program is linked with this library"
- $echo "*** or is declared to -dlopen it."
-
- if test "$allow_undefined" = no; then
- $echo
- $echo "*** Since this library must not contain undefined symbols,"
- $echo "*** because either the platform does not support them or"
- $echo "*** it was explicitly requested with -no-undefined,"
- $echo "*** libtool will only create a static version of it."
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- fi
- fi
- fi
- # Done checking deplibs!
- deplibs=$newdeplibs
- fi
-
- # All the library-specific variables (install_libdir is set above).
- library_names=
- old_library=
- dlname=
-
- # Test again, we may have decided not to build it any more
- if test "$build_libtool_libs" = yes; then
- if test "$hardcode_into_libs" = yes; then
- # Hardcode the library paths
- hardcode_libdirs=
- dep_rpath=
- rpath="$finalize_rpath"
- test "$mode" != relink && rpath="$compile_rpath$rpath"
- for libdir in $rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- dep_rpath="$dep_rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- if test -n "$hardcode_libdir_flag_spec_ld"; then
- eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
- else
- eval dep_rpath=\"$hardcode_libdir_flag_spec\"
- fi
- fi
- if test -n "$runpath_var" && test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
- fi
- test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
- fi
-
- shlibpath="$finalize_shlibpath"
- test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
- if test -n "$shlibpath"; then
- eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
- fi
-
- # Get the real and link names of the library.
- eval shared_ext=\"$shrext\"
- eval library_names=\"$library_names_spec\"
- set dummy $library_names
- realname="$2"
- shift; shift
-
- if test -n "$soname_spec"; then
- eval soname=\"$soname_spec\"
- else
- soname="$realname"
- fi
- if test -z "$dlname"; then
- dlname=$soname
- fi
-
- lib="$output_objdir/$realname"
- for link
- do
- linknames="$linknames $link"
- done
-
- # Use standard objects if they are pic
- test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
- $show "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $run $rm $export_symbols
- eval cmds=\"$export_symbols_cmds\"
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- if len=`expr "X$cmd" : ".*"` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- $show "$cmd"
- $run eval "$cmd" || exit $?
- skipped_export=false
- else
- # The command line is too long to execute in one step.
- $show "using reloadable object file for export list..."
- skipped_export=:
- fi
- done
- IFS="$save_ifs"
- if test -n "$export_symbols_regex"; then
- $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
- $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
- $show "$mv \"${export_symbols}T\" \"$export_symbols\""
- $run eval '$mv "${export_symbols}T" "$export_symbols"'
- fi
- fi
- fi
-
- if test -n "$export_symbols" && test -n "$include_expsyms"; then
- $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
- fi
-
- tmp_deplibs=
- for test_deplib in $deplibs; do
- case " $convenience " in
- *" $test_deplib "*) ;;
- *)
- tmp_deplibs="$tmp_deplibs $test_deplib"
- ;;
- esac
- done
- deplibs="$tmp_deplibs"
-
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec"; then
- save_libobjs=$libobjs
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- else
- gentop="$output_objdir/${outputname}x"
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "$mkdir $gentop"
- $run $mkdir "$gentop"
- status=$?
- if test "$status" -ne 0 && test ! -d "$gentop"; then
- exit $status
- fi
- generated="$generated $gentop"
-
- for xlib in $convenience; do
- # Extract the objects.
- case $xlib in
- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
- *) xabs=`pwd`"/$xlib" ;;
- esac
- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
- xdir="$gentop/$xlib"
-
- $show "${rm}r $xdir"
- $run ${rm}r "$xdir"
- $show "$mkdir $xdir"
- $run $mkdir "$xdir"
- status=$?
- if test "$status" -ne 0 && test ! -d "$xdir"; then
- exit $status
- fi
- # We will extract separately just the conflicting names and we will no
- # longer touch any unique names. It is faster to leave these extract
- # automatically by $AR in one run.
- $show "(cd $xdir && $AR x $xabs)"
- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
- if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
- $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
- $AR t "$xabs" | sort | uniq -cd | while read -r count name
- do
- i=1
- while test "$i" -le "$count"
- do
- # Put our $i before any first dot (extension)
- # Never overwrite any file
- name_to="$name"
- while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
- do
- name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
- done
- $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
- $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
- i=`expr $i + 1`
- done
- done
- fi
-
- libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
- done
- fi
- fi
-
- if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
- eval flag=\"$thread_safe_flag_spec\"
- linker_flags="$linker_flags $flag"
- fi
-
- # Make a backup of the uninstalled library when relinking
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
- fi
-
- # Do each of the archive commands.
- if test "$module" = yes && test -n "$module_cmds" ; then
- if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
- eval cmds=\"$module_expsym_cmds\"
- else
- eval cmds=\"$module_cmds\"
- fi
- else
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- eval cmds=\"$archive_expsym_cmds\"
- else
- eval cmds=\"$archive_cmds\"
- fi
- fi
-
- if test "X$skipped_export" != "X:" && len=`expr "X$cmds" : ".*"` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- :
- else
- # The command line is too long to link in one step, link piecewise.
- $echo "creating reloadable object files..."
-
- # Save the value of $output and $libobjs because we want to
- # use them later. If we have whole_archive_flag_spec, we
- # want to use save_libobjs as it was before
- # whole_archive_flag_spec was expanded, because we can't
- # assume the linker understands whole_archive_flag_spec.
- # This may have to be revisited, in case too many
- # convenience libraries get linked in and end up exceeding
- # the spec.
- if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
- save_libobjs=$libobjs
- fi
- save_output=$output
-
- # Clear the reloadable object creation command queue and
- # initialize k to one.
- test_cmds=
- concat_cmds=
- objlist=
- delfiles=
- last_robj=
- k=1
- output=$output_objdir/$save_output-${k}.$objext
- # Loop over the list of objects to be linked.
- for obj in $save_libobjs
- do
- eval test_cmds=\"$reload_cmds $objlist $last_robj\"
- if test "X$objlist" = X ||
- { len=`expr "X$test_cmds" : ".*"` &&
- test "$len" -le "$max_cmd_len"; }; then
- objlist="$objlist $obj"
- else
- # The command $test_cmds is almost too long, add a
- # command to the queue.
- if test "$k" -eq 1 ; then
- # The first file doesn't have a previous command to add.
- eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
- else
- # All subsequent reloadable object files will link in
- # the last one created.
- eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
- fi
- last_robj=$output_objdir/$save_output-${k}.$objext
- k=`expr $k + 1`
- output=$output_objdir/$save_output-${k}.$objext
- objlist=$obj
- len=1
- fi
- done
- # Handle the remaining objects by creating one last
- # reloadable object file. All subsequent reloadable object
- # files will link in the last one created.
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
-
- if ${skipped_export-false}; then
- $show "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $run $rm $export_symbols
- libobjs=$output
- # Append the command to create the export file.
- eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
- fi
-
- # Set up a command to remove the reloadale object files
- # after they are used.
- i=0
- while test "$i" -lt "$k"
- do
- i=`expr $i + 1`
- delfiles="$delfiles $output_objdir/$save_output-${i}.$objext"
- done
-
- $echo "creating a temporary reloadable object file: $output"
-
- # Loop through the commands generated above and execute them.
- save_ifs="$IFS"; IFS='~'
- for cmd in $concat_cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- libobjs=$output
- # Restore the value of output.
- output=$save_output
-
- if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- fi
- # Expand the library linking commands again to reset the
- # value of $libobjs for piecewise linking.
-
- # Do each of the archive commands.
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- eval cmds=\"$archive_expsym_cmds\"
- else
- eval cmds=\"$archive_cmds\"
- fi
-
- # Append the command to remove the reloadable object files
- # to the just-reset $cmds.
- eval cmds=\"\$cmds~$rm $delfiles\"
- fi
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
- exit 0
- fi
-
- # Create links to the real library.
- for linkname in $linknames; do
- if test "$realname" != "$linkname"; then
- $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
- $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
- fi
- done
-
- # If -module or -export-dynamic was specified, set the dlname.
- if test "$module" = yes || test "$export_dynamic" = yes; then
- # On all known operating systems, these are identical.
- dlname="$soname"
- fi
- fi
- ;;
-
- obj)
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
- fi
-
- if test -n "$rpath"; then
- $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
- fi
-
- if test -n "$xrpath"; then
- $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
- fi
-
- case $output in
- *.lo)
- if test -n "$objs$old_deplibs"; then
- $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
- exit 1
- fi
- libobj="$output"
- obj=`$echo "X$output" | $Xsed -e "$lo2o"`
- ;;
- *)
- libobj=
- obj="$output"
- ;;
- esac
-
- # Delete the old objects.
- $run $rm $obj $libobj
-
- # Objects from convenience libraries. This assumes
- # single-version convenience libraries. Whenever we create
- # different ones for PIC/non-PIC, this we'll have to duplicate
- # the extraction.
- reload_conv_objs=
- gentop=
- # reload_cmds runs $LD directly, so let us get rid of
- # -Wl from whole_archive_flag_spec
- wl=
-
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec"; then
- eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
- else
- gentop="$output_objdir/${obj}x"
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "$mkdir $gentop"
- $run $mkdir "$gentop"
- status=$?
- if test "$status" -ne 0 && test ! -d "$gentop"; then
- exit $status
- fi
- generated="$generated $gentop"
-
- for xlib in $convenience; do
- # Extract the objects.
- case $xlib in
- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
- *) xabs=`pwd`"/$xlib" ;;
- esac
- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
- xdir="$gentop/$xlib"
-
- $show "${rm}r $xdir"
- $run ${rm}r "$xdir"
- $show "$mkdir $xdir"
- $run $mkdir "$xdir"
- status=$?
- if test "$status" -ne 0 && test ! -d "$xdir"; then
- exit $status
- fi
- # We will extract separately just the conflicting names and we will no
- # longer touch any unique names. It is faster to leave these extract
- # automatically by $AR in one run.
- $show "(cd $xdir && $AR x $xabs)"
- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
- if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
- $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
- $AR t "$xabs" | sort | uniq -cd | while read -r count name
- do
- i=1
- while test "$i" -le "$count"
- do
- # Put our $i before any first dot (extension)
- # Never overwrite any file
- name_to="$name"
- while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
- do
- name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
- done
- $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
- $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
- i=`expr $i + 1`
- done
- done
- fi
-
- reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
- done
- fi
- fi
-
- # Create the old-style object.
- reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
-
- output="$obj"
- eval cmds=\"$reload_cmds\"
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- # Exit if we aren't doing a library object file.
- if test -z "$libobj"; then
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- exit 0
- fi
-
- if test "$build_libtool_libs" != yes; then
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- # Create an invalid libtool object if no PIC, so that we don't
- # accidentally link it into a program.
- # $show "echo timestamp > $libobj"
- # $run eval "echo timestamp > $libobj" || exit $?
- exit 0
- fi
-
- if test -n "$pic_flag" || test "$pic_mode" != default; then
- # Only do commands if we really have different PIC objects.
- reload_objs="$libobjs $reload_conv_objs"
- output="$libobj"
- eval cmds=\"$reload_cmds\"
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
-
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- exit 0
- ;;
-
- prog)
- case $host in
- *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
- esac
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
- fi
-
- if test "$preload" = yes; then
- if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
- test "$dlopen_self_static" = unknown; then
- $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
- fi
- fi
-
- case $host in
- *-*-rhapsody* | *-*-darwin1.[012])
- # On Rhapsody replace the C library is the System framework
- compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
- finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
- ;;
- esac
-
- case $host in
- *darwin*)
- # Don't allow lazy linking, it breaks C++ global constructors
- if test "$tagname" = CXX ; then
- compile_command="$compile_command ${wl}-bind_at_load"
- finalize_command="$finalize_command ${wl}-bind_at_load"
- fi
- ;;
- esac
-
- compile_command="$compile_command $compile_deplibs"
- finalize_command="$finalize_command $finalize_deplibs"
-
- if test -n "$rpath$xrpath"; then
- # If the user specified any rpath flags, then add them.
- for libdir in $rpath $xrpath; do
- # This is the magic to use -rpath.
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- fi
-
- # Now hardcode the library paths
- rpath=
- hardcode_libdirs=
- for libdir in $compile_rpath $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- case :$dllsearchpath: in
- *":$libdir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$libdir";;
- esac
- ;;
- esac
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- compile_rpath="$rpath"
-
- rpath=
- hardcode_libdirs=
- for libdir in $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$finalize_perm_rpath " in
- *" $libdir "*) ;;
- *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- finalize_rpath="$rpath"
-
- if test -n "$libobjs" && test "$build_old_libs" = yes; then
- # Transform all the library objects into standard objects.
- compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- fi
-
- dlsyms=
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- if test -n "$NM" && test -n "$global_symbol_pipe"; then
- dlsyms="${outputname}S.c"
- else
- $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
- fi
- fi
-
- if test -n "$dlsyms"; then
- case $dlsyms in
- "") ;;
- *.c)
- # Discover the nlist of each of the dlfiles.
- nlist="$output_objdir/${outputname}.nm"
-
- $show "$rm $nlist ${nlist}S ${nlist}T"
- $run $rm "$nlist" "${nlist}S" "${nlist}T"
-
- # Parse the name list into a source file.
- $show "creating $output_objdir/$dlsyms"
-
- test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
-/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
-/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
-
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-
-/* Prevent the only kind of declaration conflicts we can make. */
-#define lt_preloaded_symbols some_other_symbol
-
-/* External symbol declarations for the compiler. */\
-"
-
- if test "$dlself" = yes; then
- $show "generating symbol list for \`$output'"
-
- test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
-
- # Add our own program objects to the symbol list.
- progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- for arg in $progfiles; do
- $show "extracting global C symbols from \`$arg'"
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -n "$exclude_expsyms"; then
- $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- if test -n "$export_symbols_regex"; then
- $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- export_symbols="$output_objdir/$output.exp"
- $run $rm $export_symbols
- $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
- else
- $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
- $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
- $run eval 'mv "$nlist"T "$nlist"'
- fi
- fi
-
- for arg in $dlprefiles; do
- $show "extracting global C symbols from \`$arg'"
- name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
- $run eval '$echo ": $name " >> "$nlist"'
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -z "$run"; then
- # Make sure we have at least an empty file.
- test -f "$nlist" || : > "$nlist"
-
- if test -n "$exclude_expsyms"; then
- $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
- $mv "$nlist"T "$nlist"
- fi
-
- # Try sorting and uniquifying the output.
- if grep -v "^: " < "$nlist" |
- if sort -k 3 </dev/null >/dev/null 2>&1; then
- sort -k 3
- else
- sort +2
- fi |
- uniq > "$nlist"S; then
- :
- else
- grep -v "^: " < "$nlist" > "$nlist"S
- fi
-
- if test -f "$nlist"S; then
- eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
- else
- $echo '/* NONE */' >> "$output_objdir/$dlsyms"
- fi
-
- $echo >> "$output_objdir/$dlsyms" "\
-
-#undef lt_preloaded_symbols
-
-#if defined (__STDC__) && __STDC__
-# define lt_ptr void *
-#else
-# define lt_ptr char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
- const char *name;
- lt_ptr address;
-}
-lt_preloaded_symbols[] =
-{\
-"
-
- eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
-
- $echo >> "$output_objdir/$dlsyms" "\
- {0, (lt_ptr) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
- return lt_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif\
-"
- fi
-
- pic_flag_for_symtable=
- case $host in
- # compiling the symbol table file with pic_flag works around
- # a FreeBSD bug that causes programs to crash when -lm is
- # linked before any other PIC object. But we must not use
- # pic_flag when linking with -static. The problem exists in
- # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
- *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
- case "$compile_command " in
- *" -static "*) ;;
- *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
- esac;;
- *-*-hpux*)
- case "$compile_command " in
- *" -static "*) ;;
- *) pic_flag_for_symtable=" $pic_flag";;
- esac
- esac
-
- # Now compile the dynamic symbol file.
- $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
- $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-
- # Clean up the generated files.
- $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
- $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
-
- # Transform the symbol file into the correct name.
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- ;;
- *)
- $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
- exit 1
- ;;
- esac
- else
- # We keep going just in case the user didn't refer to
- # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
- # really was required.
-
- # Nullify the symbol file.
- compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
- fi
-
- if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
- # Replace the output file specification.
- compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- link_command="$compile_command$compile_rpath"
-
- # We have no uninstalled library dependencies, so finalize right now.
- $show "$link_command"
- $run eval "$link_command"
- status=$?
-
- # Delete the generated files.
- if test -n "$dlsyms"; then
- $show "$rm $output_objdir/${outputname}S.${objext}"
- $run $rm "$output_objdir/${outputname}S.${objext}"
- fi
-
- exit $status
- fi
-
- if test -n "$shlibpath_var"; then
- # We should set the shlibpath_var
- rpath=
- for dir in $temp_rpath; do
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*)
- # Absolute path.
- rpath="$rpath$dir:"
- ;;
- *)
- # Relative path: add a thisdir entry.
- rpath="$rpath\$thisdir/$dir:"
- ;;
- esac
- done
- temp_rpath="$rpath"
- fi
-
- if test -n "$compile_shlibpath$finalize_shlibpath"; then
- compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
- fi
- if test -n "$finalize_shlibpath"; then
- finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
- fi
-
- compile_var=
- finalize_var=
- if test -n "$runpath_var"; then
- if test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- if test -n "$finalize_perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $finalize_perm_rpath; do
- rpath="$rpath$dir:"
- done
- finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- fi
-
- if test "$no_install" = yes; then
- # We don't need to create a wrapper script.
- link_command="$compile_var$compile_command$compile_rpath"
- # Replace the output file specification.
- link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- # Delete the old output file.
- $run $rm $output
- # Link the executable and exit
- $show "$link_command"
- $run eval "$link_command" || exit $?
- exit 0
- fi
-
- if test "$hardcode_action" = relink; then
- # Fast installation is not supported
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
-
- $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
- $echo "$modename: \`$output' will be relinked during installation" 1>&2
- else
- if test "$fast_install" != no; then
- link_command="$finalize_var$compile_command$finalize_rpath"
- if test "$fast_install" = yes; then
- relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
- else
- # fast_install is set to needless
- relink_command=
- fi
- else
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
- fi
- fi
-
- # Replace the output file specification.
- link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-
- # Delete the old output files.
- $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
-
- $show "$link_command"
- $run eval "$link_command" || exit $?
-
- # Now create the wrapper script.
- $show "creating $output"
-
- # Quote the relink command for shipping.
- if test -n "$relink_command"; then
- # Preserve any variables that may affect compiler behavior
- for var in $variables_saved_for_relink; do
- if eval test -z \"\${$var+set}\"; then
- relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
- elif eval var_value=\$$var; test -z "$var_value"; then
- relink_command="$var=; export $var; $relink_command"
- else
- var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
- relink_command="$var=\"$var_value\"; export $var; $relink_command"
- fi
- done
- relink_command="(cd `pwd`; $relink_command)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Quote $echo for shipping.
- if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
- case $0 in
- [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
- *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
- esac
- qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
- else
- qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Only actually do things if our run command is non-null.
- if test -z "$run"; then
- # win32 will think the script is a binary if it has
- # a .exe suffix, so we strip it off here.
- case $output in
- *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
- esac
- # test for cygwin because mv fails w/o .exe extensions
- case $host in
- *cygwin*)
- exeext=.exe
- outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
- *) exeext= ;;
- esac
- case $host in
- *cygwin* | *mingw* )
- cwrappersource=`$echo ${objdir}/lt-${output}.c`
- cwrapper=`$echo ${output}.exe`
- $rm $cwrappersource $cwrapper
- trap "$rm $cwrappersource $cwrapper; exit 1" 1 2 15
-
- cat > $cwrappersource <<EOF
-
-/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
- Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-
- The $output program cannot be directly executed until all the libtool
- libraries that it depends on are installed.
-
- This wrapper executable should never be moved out of the build directory.
- If it is, it will not operate correctly.
-
- Currently, it simply execs the wrapper *script* "/bin/sh $output",
- but could eventually absorb all of the scripts functionality and
- exec $objdir/$outputname directly.
-*/
-EOF
- cat >> $cwrappersource<<"EOF"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <assert.h>
-
-#if defined(PATH_MAX)
-# define LT_PATHMAX PATH_MAX
-#elif defined(MAXPATHLEN)
-# define LT_PATHMAX MAXPATHLEN
-#else
-# define LT_PATHMAX 1024
-#endif
-
-#ifndef DIR_SEPARATOR
-#define DIR_SEPARATOR '/'
-#endif
-
-#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
- defined (__OS2__)
-#define HAVE_DOS_BASED_FILE_SYSTEM
-#ifndef DIR_SEPARATOR_2
-#define DIR_SEPARATOR_2 '\\'
-#endif
-#endif
-
-#ifndef DIR_SEPARATOR_2
-# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
-#else /* DIR_SEPARATOR_2 */
-# define IS_DIR_SEPARATOR(ch) \
- (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
-#endif /* DIR_SEPARATOR_2 */
-
-#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
-#define XFREE(stale) do { \
- if (stale) { free ((void *) stale); stale = 0; } \
-} while (0)
-
-const char *program_name = NULL;
-
-void * xmalloc (size_t num);
-char * xstrdup (const char *string);
-char * basename (const char *name);
-char * fnqualify(const char *path);
-char * strendzap(char *str, const char *pat);
-void lt_fatal (const char *message, ...);
-
-int
-main (int argc, char *argv[])
-{
- char **newargz;
- int i;
-
- program_name = (char *) xstrdup ((char *) basename (argv[0]));
- newargz = XMALLOC(char *, argc+2);
-EOF
-
- cat >> $cwrappersource <<EOF
- newargz[0] = "$SHELL";
-EOF
-
- cat >> $cwrappersource <<"EOF"
- newargz[1] = fnqualify(argv[0]);
- /* we know the script has the same name, without the .exe */
- /* so make sure newargz[1] doesn't end in .exe */
- strendzap(newargz[1],".exe");
- for (i = 1; i < argc; i++)
- newargz[i+1] = xstrdup(argv[i]);
- newargz[argc+1] = NULL;
-EOF
-
- cat >> $cwrappersource <<EOF
- execv("$SHELL",newargz);
-EOF
-
- cat >> $cwrappersource <<"EOF"
-}
-
-void *
-xmalloc (size_t num)
-{
- void * p = (void *) malloc (num);
- if (!p)
- lt_fatal ("Memory exhausted");
-
- return p;
-}
-
-char *
-xstrdup (const char *string)
-{
- return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
-;
-}
-
-char *
-basename (const char *name)
-{
- const char *base;
-
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- /* Skip over the disk name in MSDOS pathnames. */
- if (isalpha (name[0]) && name[1] == ':')
- name += 2;
-#endif
-
- for (base = name; *name; name++)
- if (IS_DIR_SEPARATOR (*name))
- base = name + 1;
- return (char *) base;
-}
-
-char *
-fnqualify(const char *path)
-{
- size_t size;
- char *p;
- char tmp[LT_PATHMAX + 1];
-
- assert(path != NULL);
-
- /* Is it qualified already? */
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- if (isalpha (path[0]) && path[1] == ':')
- return xstrdup (path);
-#endif
- if (IS_DIR_SEPARATOR (path[0]))
- return xstrdup (path);
-
- /* prepend the current directory */
- /* doesn't handle '~' */
- if (getcwd (tmp, LT_PATHMAX) == NULL)
- lt_fatal ("getcwd failed");
- size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
- p = XMALLOC(char, size);
- sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
- return p;
-}
-
-char *
-strendzap(char *str, const char *pat)
-{
- size_t len, patlen;
-
- assert(str != NULL);
- assert(pat != NULL);
-
- len = strlen(str);
- patlen = strlen(pat);
-
- if (patlen <= len)
- {
- str += len - patlen;
- if (strcmp(str, pat) == 0)
- *str = '\0';
- }
- return str;
-}
-
-static void
-lt_error_core (int exit_status, const char * mode,
- const char * message, va_list ap)
-{
- fprintf (stderr, "%s: %s: ", program_name, mode);
- vfprintf (stderr, message, ap);
- fprintf (stderr, ".\n");
-
- if (exit_status >= 0)
- exit (exit_status);
-}
-
-void
-lt_fatal (const char *message, ...)
-{
- va_list ap;
- va_start (ap, message);
- lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
- va_end (ap);
-}
-EOF
- # we should really use a build-platform specific compiler
- # here, but OTOH, the wrappers (shell script and this C one)
- # are only useful if you want to execute the "real" binary.
- # Since the "real" binary is built for $host, then this
- # wrapper might as well be built for $host, too.
- $run $LTCC -s -o $cwrapper $cwrappersource
- ;;
- esac
- $rm $output
- trap "$rm $output; exit 1" 1 2 15
-
- $echo > $output "\
-#! $SHELL
-
-# $output - temporary wrapper script for $objdir/$outputname
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# The $output program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='${SED} -e 1s/^X//'
-sed_quote_subst='$sed_quote_subst'
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
-
-relink_command=\"$relink_command\"
-
-# This environment variable determines our operation mode.
-if test \"\$libtool_install_magic\" = \"$magic\"; then
- # install mode needs the following variable:
- notinst_deplibs='$notinst_deplibs'
-else
- # When we are sourced in execute mode, \$file and \$echo are already set.
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- echo=\"$qecho\"
- file=\"\$0\"
- # Make sure echo works.
- if test \"X\$1\" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
- elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
- # Yippee, \$echo works!
- :
- else
- # Restart under the correct shell, and then maybe \$echo will work.
- exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
- fi
- fi\
-"
- $echo >> $output "\
-
- # Find the directory that this script lives in.
- thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
- test \"x\$thisdir\" = \"x\$file\" && thisdir=.
-
- # Follow symbolic links until we get to the real thisdir.
- file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
- while test -n \"\$file\"; do
- destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
-
- # If there was a directory component, then change thisdir.
- if test \"x\$destdir\" != \"x\$file\"; then
- case \"\$destdir\" in
- [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
- *) thisdir=\"\$thisdir/\$destdir\" ;;
- esac
- fi
-
- file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
- file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
- done
-
- # Try to get the absolute directory name.
- absdir=\`cd \"\$thisdir\" && pwd\`
- test -n \"\$absdir\" && thisdir=\"\$absdir\"
-"
-
- if test "$fast_install" = yes; then
- $echo >> $output "\
- program=lt-'$outputname'$exeext
- progdir=\"\$thisdir/$objdir\"
-
- if test ! -f \"\$progdir/\$program\" || \\
- { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
- test \"X\$file\" != \"X\$progdir/\$program\"; }; then
-
- file=\"\$\$-\$program\"
-
- if test ! -d \"\$progdir\"; then
- $mkdir \"\$progdir\"
- else
- $rm \"\$progdir/\$file\"
- fi"
-
- $echo >> $output "\
-
- # relink executable if necessary
- if test -n \"\$relink_command\"; then
- if relink_command_output=\`eval \$relink_command 2>&1\`; then :
- else
- $echo \"\$relink_command_output\" >&2
- $rm \"\$progdir/\$file\"
- exit 1
- fi
- fi
-
- $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
- { $rm \"\$progdir/\$program\";
- $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
- $rm \"\$progdir/\$file\"
- fi"
- else
- $echo >> $output "\
- program='$outputname'
- progdir=\"\$thisdir/$objdir\"
-"
- fi
-
- $echo >> $output "\
-
- if test -f \"\$progdir/\$program\"; then"
-
- # Export our shlibpath_var if we have one.
- if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
- $echo >> $output "\
- # Add our own library path to $shlibpath_var
- $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
- # Some systems cannot cope with colon-terminated $shlibpath_var
- # The second colon is a workaround for a bug in BeOS R4 sed
- $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
- export $shlibpath_var
-"
- fi
-
- # fixup the dll searchpath if we need to.
- if test -n "$dllsearchpath"; then
- $echo >> $output "\
- # Add the dll search path components to the executable PATH
- PATH=$dllsearchpath:\$PATH
-"
- fi
-
- $echo >> $output "\
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- # Run the actual program with our arguments.
-"
- case $host in
- # Backslashes separate directories on plain windows
- *-*-mingw | *-*-os2*)
- $echo >> $output "\
- exec \$progdir\\\\\$program \${1+\"\$@\"}
-"
- ;;
-
- *)
- $echo >> $output "\
- exec \$progdir/\$program \${1+\"\$@\"}
-"
- ;;
- esac
- $echo >> $output "\
- \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
- exit 1
- fi
- else
- # The program doesn't exist.
- \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
- \$echo \"This script is just a wrapper for \$program.\" 1>&2
- $echo \"See the $PACKAGE documentation for more information.\" 1>&2
- exit 1
- fi
-fi\
-"
- chmod +x $output
- fi
- exit 0
- ;;
- esac
-
- # See if we need to build an old-fashioned archive.
- for oldlib in $oldlibs; do
-
- if test "$build_libtool_libs" = convenience; then
- oldobjs="$libobjs_save"
- addlibs="$convenience"
- build_libtool_libs=no
- else
- if test "$build_libtool_libs" = module; then
- oldobjs="$libobjs_save"
- build_libtool_libs=no
- else
- oldobjs="$old_deplibs $non_pic_objects"
- fi
- addlibs="$old_convenience"
- fi
-
- if test -n "$addlibs"; then
- gentop="$output_objdir/${outputname}x"
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "$mkdir $gentop"
- $run $mkdir "$gentop"
- status=$?
- if test "$status" -ne 0 && test ! -d "$gentop"; then
- exit $status
- fi
- generated="$generated $gentop"
-
- # Add in members from convenience archives.
- for xlib in $addlibs; do
- # Extract the objects.
- case $xlib in
- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
- *) xabs=`pwd`"/$xlib" ;;
- esac
- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
- xdir="$gentop/$xlib"
-
- $show "${rm}r $xdir"
- $run ${rm}r "$xdir"
- $show "$mkdir $xdir"
- $run $mkdir "$xdir"
- status=$?
- if test "$status" -ne 0 && test ! -d "$xdir"; then
- exit $status
- fi
- # We will extract separately just the conflicting names and we will no
- # longer touch any unique names. It is faster to leave these extract
- # automatically by $AR in one run.
- $show "(cd $xdir && $AR x $xabs)"
- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
- if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
- $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
- $AR t "$xabs" | sort | uniq -cd | while read -r count name
- do
- i=1
- while test "$i" -le "$count"
- do
- # Put our $i before any first dot (extension)
- # Never overwrite any file
- name_to="$name"
- while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
- do
- name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
- done
- $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
- $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
- i=`expr $i + 1`
- done
- done
- fi
-
- oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
- done
- fi
-
- # Do each command in the archive commands.
- if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
- eval cmds=\"$old_archive_from_new_cmds\"
- else
- eval cmds=\"$old_archive_cmds\"
-
- if len=`expr "X$cmds" : ".*"` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- :
- else
- # the command line is too long to link in one step, link in parts
- $echo "using piecewise archive linking..."
- save_RANLIB=$RANLIB
- RANLIB=:
- objlist=
- concat_cmds=
- save_oldobjs=$oldobjs
- # GNU ar 2.10+ was changed to match POSIX; thus no paths are
- # encoded into archives. This makes 'ar r' malfunction in
- # this piecewise linking case whenever conflicting object
- # names appear in distinct ar calls; check, warn and compensate.
- if (for obj in $save_oldobjs
- do
- $echo "X$obj" | $Xsed -e 's%^.*/%%'
- done | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
- $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
- AR_FLAGS=cq
- fi
- # Is there a better way of finding the last object in the list?
- for obj in $save_oldobjs
- do
- last_oldobj=$obj
- done
- for obj in $save_oldobjs
- do
- oldobjs="$objlist $obj"
- objlist="$objlist $obj"
- eval test_cmds=\"$old_archive_cmds\"
- if len=`expr "X$test_cmds" : ".*"` &&
- test "$len" -le "$max_cmd_len"; then
- :
- else
- # the above command should be used before it gets too long
- oldobjs=$objlist
- if test "$obj" = "$last_oldobj" ; then
- RANLIB=$save_RANLIB
- fi
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
- objlist=
- fi
- done
- RANLIB=$save_RANLIB
- oldobjs=$objlist
- if test "X$oldobjs" = "X" ; then
- eval cmds=\"\$concat_cmds\"
- else
- eval cmds=\"\$concat_cmds~$old_archive_cmds\"
- fi
- fi
- fi
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- done
-
- if test -n "$generated"; then
- $show "${rm}r$generated"
- $run ${rm}r$generated
- fi
-
- # Now create the libtool archive.
- case $output in
- *.la)
- old_library=
- test "$build_old_libs" = yes && old_library="$libname.$libext"
- $show "creating $output"
-
- # Preserve any variables that may affect compiler behavior
- for var in $variables_saved_for_relink; do
- if eval test -z \"\${$var+set}\"; then
- relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
- elif eval var_value=\$$var; test -z "$var_value"; then
- relink_command="$var=; export $var; $relink_command"
- else
- var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
- relink_command="$var=\"$var_value\"; export $var; $relink_command"
- fi
- done
- # Quote the link command for shipping.
- relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
-
- # Only create the output if not a dry run.
- if test -z "$run"; then
- for installed in no yes; do
- if test "$installed" = yes; then
- if test -z "$install_libdir"; then
- break
- fi
- output="$output_objdir/$outputname"i
- # Replace all uninstalled libtool libraries with the installed ones
- newdependency_libs=
- for deplib in $dependency_libs; do
- case $deplib in
- *.la)
- name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- if test -z "$libdir"; then
- $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
- exit 1
- fi
- newdependency_libs="$newdependency_libs $libdir/$name"
- ;;
- *) newdependency_libs="$newdependency_libs $deplib" ;;
- esac
- done
- dependency_libs="$newdependency_libs"
- newdlfiles=
- for lib in $dlfiles; do
- name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- if test -z "$libdir"; then
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- exit 1
- fi
- newdlfiles="$newdlfiles $libdir/$name"
- done
- dlfiles="$newdlfiles"
- newdlprefiles=
- for lib in $dlprefiles; do
- name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- if test -z "$libdir"; then
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- exit 1
- fi
- newdlprefiles="$newdlprefiles $libdir/$name"
- done
- dlprefiles="$newdlprefiles"
- fi
- $rm $output
- # place dlname in correct position for cygwin
- tdlname=$dlname
- case $host,$output,$installed,$module,$dlname in
- *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
- esac
- $echo > $output "\
-# $outputname - a libtool library file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# The name that we can dlopen(3).
-dlname='$tdlname'
-
-# Names of this library.
-library_names='$library_names'
-
-# The name of the static archive.
-old_library='$old_library'
-
-# Libraries that this one depends upon.
-dependency_libs='$dependency_libs'
-
-# Version information for $libname.
-current=$current
-age=$age
-revision=$revision
-
-# Is this an already installed library?
-installed=$installed
-
-# Should we warn about portability when linking against -modules?
-shouldnotlink=$module
-
-# Files to dlopen/dlpreopen
-dlopen='$dlfiles'
-dlpreopen='$dlprefiles'
-
-# Directory that this library needs to be installed in:
-libdir='$install_libdir'"
- if test "$installed" = no && test "$need_relink" = yes; then
- $echo >> $output "\
-relink_command=\"$relink_command\""
- fi
- done
- fi
-
- # Do a symbolic link so that the libtool archive can be found in
- # LD_LIBRARY_PATH before the program is installed.
- $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
- $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
- ;;
- esac
- exit 0
- ;;
-
- # libtool install mode
- install)
- modename="$modename: install"
-
- # There may be an optional sh(1) argument at the beginning of
- # install_prog (especially on Windows NT).
- if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
- # Allow the use of GNU shtool's install command.
- $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
- # Aesthetically quote it.
- arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- install_prog="$arg "
- arg="$1"
- shift
- else
- install_prog=
- arg="$nonopt"
- fi
-
- # The real first argument should be the name of the installation program.
- # Aesthetically quote it.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- install_prog="$install_prog$arg"
-
- # We need to accept at least all the BSD install flags.
- dest=
- files=
- opts=
- prev=
- install_type=
- isdir=no
- stripme=
- for arg
- do
- if test -n "$dest"; then
- files="$files $dest"
- dest="$arg"
- continue
- fi
-
- case $arg in
- -d) isdir=yes ;;
- -f) prev="-f" ;;
- -g) prev="-g" ;;
- -m) prev="-m" ;;
- -o) prev="-o" ;;
- -s)
- stripme=" -s"
- continue
- ;;
- -*) ;;
-
- *)
- # If the previous option needed an argument, then skip it.
- if test -n "$prev"; then
- prev=
- else
- dest="$arg"
- continue
- fi
- ;;
- esac
-
- # Aesthetically quote the argument.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- install_prog="$install_prog $arg"
- done
-
- if test -z "$install_prog"; then
- $echo "$modename: you must specify an install program" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prev' option requires an argument" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- if test -z "$files"; then
- if test -z "$dest"; then
- $echo "$modename: no file or destination specified" 1>&2
- else
- $echo "$modename: you must specify a destination" 1>&2
- fi
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Strip any trailing slash from the destination.
- dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
-
- # Check to see that the destination is a directory.
- test -d "$dest" && isdir=yes
- if test "$isdir" = yes; then
- destdir="$dest"
- destname=
- else
- destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
- test "X$destdir" = "X$dest" && destdir=.
- destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
-
- # Not a directory, so check to see that there is only one file specified.
- set dummy $files
- if test "$#" -gt 2; then
- $echo "$modename: \`$dest' is not a directory" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
- fi
- case $destdir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- for file in $files; do
- case $file in
- *.lo) ;;
- *)
- $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
- esac
- done
- ;;
- esac
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- staticlibs=
- future_libdirs=
- current_libdirs=
- for file in $files; do
-
- # Do each installation.
- case $file in
- *.$libext)
- # Do the static libraries later.
- staticlibs="$staticlibs $file"
- ;;
-
- *.la)
- # Check to see that this really is a libtool archive.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- library_names=
- old_library=
- relink_command=
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Add the libdir to current_libdirs if it is the destination.
- if test "X$destdir" = "X$libdir"; then
- case "$current_libdirs " in
- *" $libdir "*) ;;
- *) current_libdirs="$current_libdirs $libdir" ;;
- esac
- else
- # Note the libdir as a future libdir.
- case "$future_libdirs " in
- *" $libdir "*) ;;
- *) future_libdirs="$future_libdirs $libdir" ;;
- esac
- fi
-
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
- test "X$dir" = "X$file/" && dir=
- dir="$dir$objdir"
-
- if test -n "$relink_command"; then
- # Determine the prefix the user has applied to our future dir.
- inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
-
- # Don't allow the user to place us outside of our expected
- # location b/c this prevents finding dependent libraries that
- # are installed to the same prefix.
- # At present, this check doesn't affect windows .dll's that
- # are installed into $libdir/../bin (currently, that works fine)
- # but it's something to keep an eye on.
- if test "$inst_prefix_dir" = "$destdir"; then
- $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
- exit 1
- fi
-
- if test -n "$inst_prefix_dir"; then
- # Stick the inst_prefix_dir data into the link command.
- relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
- else
- relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
- fi
-
- $echo "$modename: warning: relinking \`$file'" 1>&2
- $show "$relink_command"
- if $run eval "$relink_command"; then :
- else
- $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
- exit 1
- fi
- fi
-
- # See the names of the shared library.
- set dummy $library_names
- if test -n "$2"; then
- realname="$2"
- shift
- shift
-
- srcname="$realname"
- test -n "$relink_command" && srcname="$realname"T
-
- # Install the shared library and build the symlinks.
- $show "$install_prog $dir/$srcname $destdir/$realname"
- $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
- if test -n "$stripme" && test -n "$striplib"; then
- $show "$striplib $destdir/$realname"
- $run eval "$striplib $destdir/$realname" || exit $?
- fi
-
- if test "$#" -gt 0; then
- # Delete the old symlinks, and create new ones.
- for linkname
- do
- if test "$linkname" != "$realname"; then
- $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
- $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
- fi
- done
- fi
-
- # Do each command in the postinstall commands.
- lib="$destdir/$realname"
- eval cmds=\"$postinstall_cmds\"
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
-
- # Install the pseudo-library for information purposes.
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- instname="$dir/$name"i
- $show "$install_prog $instname $destdir/$name"
- $run eval "$install_prog $instname $destdir/$name" || exit $?
-
- # Maybe install the static library, too.
- test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
- ;;
-
- *.lo)
- # Install (i.e. copy) a libtool object.
-
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- destfile="$destdir/$destfile"
- fi
-
- # Deduce the name of the destination old-style object file.
- case $destfile in
- *.lo)
- staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
- ;;
- *.$objext)
- staticdest="$destfile"
- destfile=
- ;;
- *)
- $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
- esac
-
- # Install the libtool object if requested.
- if test -n "$destfile"; then
- $show "$install_prog $file $destfile"
- $run eval "$install_prog $file $destfile" || exit $?
- fi
-
- # Install the old object if enabled.
- if test "$build_old_libs" = yes; then
- # Deduce the name of the old-style object file.
- staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
-
- $show "$install_prog $staticobj $staticdest"
- $run eval "$install_prog \$staticobj \$staticdest" || exit $?
- fi
- exit 0
- ;;
-
- *)
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- destfile="$destdir/$destfile"
- fi
-
- # If the file is missing, and there is a .exe on the end, strip it
- # because it is most likely a libtool script we actually want to
- # install
- stripped_ext=""
- case $file in
- *.exe)
- if test ! -f "$file"; then
- file=`$echo $file|${SED} 's,.exe$,,'`
- stripped_ext=".exe"
- fi
- ;;
- esac
-
- # Do a test to see if this is really a libtool program.
- case $host in
- *cygwin*|*mingw*)
- wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
- ;;
- *)
- wrapper=$file
- ;;
- esac
- if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
- notinst_deplibs=
- relink_command=
-
- # To insure that "foo" is sourced, and not "foo.exe",
- # finese the cygwin/MSYS system by explicitly sourcing "foo."
- # which disallows the automatic-append-.exe behavior.
- case $build in
- *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
- *) wrapperdot=${wrapper} ;;
- esac
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . ${wrapperdot} ;;
- *) . ./${wrapperdot} ;;
- esac
-
- # Check the variables that should have been set.
- if test -z "$notinst_deplibs"; then
- $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
- exit 1
- fi
-
- finalize=yes
- for lib in $notinst_deplibs; do
- # Check to see that each library is installed.
- libdir=
- if test -f "$lib"; then
- # If there is no directory component, then add one.
- case $lib in
- */* | *\\*) . $lib ;;
- *) . ./$lib ;;
- esac
- fi
- libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
- if test -n "$libdir" && test ! -f "$libfile"; then
- $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
- finalize=no
- fi
- done
-
- relink_command=
- # To insure that "foo" is sourced, and not "foo.exe",
- # finese the cygwin/MSYS system by explicitly sourcing "foo."
- # which disallows the automatic-append-.exe behavior.
- case $build in
- *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
- *) wrapperdot=${wrapper} ;;
- esac
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . ${wrapperdot} ;;
- *) . ./${wrapperdot} ;;
- esac
-
- outputname=
- if test "$fast_install" = no && test -n "$relink_command"; then
- if test "$finalize" = yes && test -z "$run"; then
- tmpdir="/tmp"
- test -n "$TMPDIR" && tmpdir="$TMPDIR"
- tmpdir=`mktemp -d $tmpdir/libtool-XXXXXX 2> /dev/null` ||
- tmpdir="$tmpdir/libtool-$$"
- if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
- else
- $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
- continue
- fi
- file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
- outputname="$tmpdir/$file"
- # Replace the output file specification.
- relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-
- $show "$relink_command"
- if $run eval "$relink_command"; then :
- else
- $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
- ${rm}r "$tmpdir"
- continue
- fi
- file="$outputname"
- else
- $echo "$modename: warning: cannot relink \`$file'" 1>&2
- fi
- else
- # Install the binary that we compiled earlier.
- file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
- fi
- fi
-
- # remove .exe since cygwin /usr/bin/install will append another
- # one anyways
- case $install_prog,$host in
- */usr/bin/install*,*cygwin*)
- case $file:$destfile in
- *.exe:*.exe)
- # this is ok
- ;;
- *.exe:*)
- destfile=$destfile.exe
- ;;
- *:*.exe)
- destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
- ;;
- esac
- ;;
- esac
- $show "$install_prog$stripme $file $destfile"
- $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
- test -n "$outputname" && ${rm}r "$tmpdir"
- ;;
- esac
- done
-
- for file in $staticlibs; do
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
- # Set up the ranlib parameters.
- oldlib="$destdir/$name"
-
- $show "$install_prog $file $oldlib"
- $run eval "$install_prog \$file \$oldlib" || exit $?
-
- if test -n "$stripme" && test -n "$striplib"; then
- $show "$old_striplib $oldlib"
- $run eval "$old_striplib $oldlib" || exit $?
- fi
-
- # Do each command in the postinstall commands.
- eval cmds=\"$old_postinstall_cmds\"
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- done
-
- if test -n "$future_libdirs"; then
- $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
- fi
-
- if test -n "$current_libdirs"; then
- # Maybe just do a dry run.
- test -n "$run" && current_libdirs=" -n$current_libdirs"
- exec_cmd='$SHELL $0 --finish$current_libdirs'
- else
- exit 0
- fi
- ;;
-
- # libtool finish mode
- finish)
- modename="$modename: finish"
- libdirs="$nonopt"
- admincmds=
-
- if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
- for dir
- do
- libdirs="$libdirs $dir"
- done
-
- for libdir in $libdirs; do
- if test -n "$finish_cmds"; then
- # Do each command in the finish commands.
- eval cmds=\"$finish_cmds\"
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || admincmds="$admincmds
- $cmd"
- done
- IFS="$save_ifs"
- fi
- if test -n "$finish_eval"; then
- # Do the single finish_eval.
- eval cmds=\"$finish_eval\"
- $run eval "$cmds" || admincmds="$admincmds
- $cmds"
- fi
- done
- fi
-
- # Exit here if they wanted silent mode.
- test "$show" = : && exit 0
-
- $echo "----------------------------------------------------------------------"
- $echo "Libraries have been installed in:"
- for libdir in $libdirs; do
- $echo " $libdir"
- done
- $echo
- $echo "If you ever happen to want to link against installed libraries"
- $echo "in a given directory, LIBDIR, you must either use libtool, and"
- $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
- $echo "flag during linking and do at least one of the following:"
- if test -n "$shlibpath_var"; then
- $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
- $echo " during execution"
- fi
- if test -n "$runpath_var"; then
- $echo " - add LIBDIR to the \`$runpath_var' environment variable"
- $echo " during linking"
- fi
- if test -n "$hardcode_libdir_flag_spec"; then
- libdir=LIBDIR
- eval flag=\"$hardcode_libdir_flag_spec\"
-
- $echo " - use the \`$flag' linker flag"
- fi
- if test -n "$admincmds"; then
- $echo " - have your system administrator run these commands:$admincmds"
- fi
- if test -f /etc/ld.so.conf; then
- $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
- fi
- $echo
- $echo "See any operating system documentation about shared libraries for"
- $echo "more information, such as the ld(1) and ld.so(8) manual pages."
- $echo "----------------------------------------------------------------------"
- exit 0
- ;;
-
- # libtool execute mode
- execute)
- modename="$modename: execute"
-
- # The first argument is the command name.
- cmd="$nonopt"
- if test -z "$cmd"; then
- $echo "$modename: you must specify a COMMAND" 1>&2
- $echo "$help"
- exit 1
- fi
-
- # Handle -dlopen flags immediately.
- for file in $execute_dlfiles; do
- if test ! -f "$file"; then
- $echo "$modename: \`$file' is not a file" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- dir=
- case $file in
- *.la)
- # Check to see that this really is a libtool archive.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Read the libtool library.
- dlname=
- library_names=
-
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Skip this library if it cannot be dlopened.
- if test -z "$dlname"; then
- # Warn if it was a shared library.
- test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
- continue
- fi
-
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
-
- if test -f "$dir/$objdir/$dlname"; then
- dir="$dir/$objdir"
- else
- $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
- exit 1
- fi
- ;;
-
- *.lo)
- # Just add the directory containing the .lo file.
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
- ;;
-
- *)
- $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
- continue
- ;;
- esac
-
- # Get the absolute pathname.
- absdir=`cd "$dir" && pwd`
- test -n "$absdir" && dir="$absdir"
-
- # Now add the directory to shlibpath_var.
- if eval "test -z \"\$$shlibpath_var\""; then
- eval "$shlibpath_var=\"\$dir\""
- else
- eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
- fi
- done
-
- # This variable tells wrapper scripts just to set shlibpath_var
- # rather than running their programs.
- libtool_execute_magic="$magic"
-
- # Check if any of the arguments is a wrapper script.
- args=
- for file
- do
- case $file in
- -*) ;;
- *)
- # Do a test to see if this is really a libtool program.
- if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Transform arg to wrapped name.
- file="$progdir/$program"
- fi
- ;;
- esac
- # Quote arguments (to preserve shell metacharacters).
- file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
- args="$args \"$file\""
- done
-
- if test -z "$run"; then
- if test -n "$shlibpath_var"; then
- # Export the shlibpath_var.
- eval "export $shlibpath_var"
- fi
-
- # Restore saved environment variables
- if test "${save_LC_ALL+set}" = set; then
- LC_ALL="$save_LC_ALL"; export LC_ALL
- fi
- if test "${save_LANG+set}" = set; then
- LANG="$save_LANG"; export LANG
- fi
-
- # Now prepare to actually exec the command.
- exec_cmd="\"\$cmd\"$args"
- else
- # Display what would be done.
- if test -n "$shlibpath_var"; then
- eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
- $echo "export $shlibpath_var"
- fi
- eval \$echo \"\$cmd\"$args
- exit 0
- fi
- ;;
-
- # libtool clean and uninstall mode
- clean | uninstall)
- modename="$modename: $mode"
- rm="$nonopt"
- files=
- rmforce=
- exit_status=0
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- for arg
- do
- case $arg in
- -f) rm="$rm $arg"; rmforce=yes ;;
- -*) rm="$rm $arg" ;;
- *) files="$files $arg" ;;
- esac
- done
-
- if test -z "$rm"; then
- $echo "$modename: you must specify an RM program" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- rmdirs=
-
- origobjdir="$objdir"
- for file in $files; do
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$dir" = "X$file"; then
- dir=.
- objdir="$origobjdir"
- else
- objdir="$dir/$origobjdir"
- fi
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- test "$mode" = uninstall && objdir="$dir"
-
- # Remember objdir for removal later, being careful to avoid duplicates
- if test "$mode" = clean; then
- case " $rmdirs " in
- *" $objdir "*) ;;
- *) rmdirs="$rmdirs $objdir" ;;
- esac
- fi
-
- # Don't error if the file doesn't exist and rm -f was used.
- if (test -L "$file") >/dev/null 2>&1 \
- || (test -h "$file") >/dev/null 2>&1 \
- || test -f "$file"; then
- :
- elif test -d "$file"; then
- exit_status=1
- continue
- elif test "$rmforce" = yes; then
- continue
- fi
-
- rmfiles="$file"
-
- case $name in
- *.la)
- # Possibly a libtool archive, so verify it.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- . $dir/$name
-
- # Delete the libtool libraries and symlinks.
- for n in $library_names; do
- rmfiles="$rmfiles $objdir/$n"
- done
- test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
- test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
-
- if test "$mode" = uninstall; then
- if test -n "$library_names"; then
- # Do each command in the postuninstall commands.
- eval cmds=\"$postuninstall_cmds\"
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd"
- if test "$?" -ne 0 && test "$rmforce" != yes; then
- exit_status=1
- fi
- done
- IFS="$save_ifs"
- fi
-
- if test -n "$old_library"; then
- # Do each command in the old_postuninstall commands.
- eval cmds=\"$old_postuninstall_cmds\"
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd"
- if test "$?" -ne 0 && test "$rmforce" != yes; then
- exit_status=1
- fi
- done
- IFS="$save_ifs"
- fi
- # FIXME: should reinstall the best remaining shared library.
- fi
- fi
- ;;
-
- *.lo)
- # Possibly a libtool object, so verify it.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-
- # Read the .lo file
- . $dir/$name
-
- # Add PIC object to the list of files to remove.
- if test -n "$pic_object" \
- && test "$pic_object" != none; then
- rmfiles="$rmfiles $dir/$pic_object"
- fi
-
- # Add non-PIC object to the list of files to remove.
- if test -n "$non_pic_object" \
- && test "$non_pic_object" != none; then
- rmfiles="$rmfiles $dir/$non_pic_object"
- fi
- fi
- ;;
-
- *)
- if test "$mode" = clean ; then
- noexename=$name
- case $file in
- *.exe)
- file=`$echo $file|${SED} 's,.exe$,,'`
- noexename=`$echo $name|${SED} 's,.exe$,,'`
- # $file with .exe has already been added to rmfiles,
- # add $file without .exe
- rmfiles="$rmfiles $file"
- ;;
- esac
- # Do a test to see if this is a libtool program.
- if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- relink_command=
- . $dir/$noexename
-
- # note $name still contains .exe if it was in $file originally
- # as does the version of $file that was added into $rmfiles
- rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
- if test "$fast_install" = yes && test -n "$relink_command"; then
- rmfiles="$rmfiles $objdir/lt-$name"
- fi
- if test "X$noexename" != "X$name" ; then
- rmfiles="$rmfiles $objdir/lt-${noexename}.c"
- fi
- fi
- fi
- ;;
- esac
- $show "$rm $rmfiles"
- $run $rm $rmfiles || exit_status=1
- done
- objdir="$origobjdir"
-
- # Try to remove the ${objdir}s in the directories where we deleted files
- for dir in $rmdirs; do
- if test -d "$dir"; then
- $show "rmdir $dir"
- $run rmdir $dir >/dev/null 2>&1
- fi
- done
-
- exit $exit_status
- ;;
-
- "")
- $echo "$modename: you must specify a MODE" 1>&2
- $echo "$generic_help" 1>&2
- exit 1
- ;;
- esac
-
- if test -z "$exec_cmd"; then
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$generic_help" 1>&2
- exit 1
- fi
-fi # test -z "$show_help"
-
-if test -n "$exec_cmd"; then
- eval exec $exec_cmd
- exit 1
-fi
-
-# We need to display help for each of the modes.
-case $mode in
-"") $echo \
-"Usage: $modename [OPTION]... [MODE-ARG]...
-
-Provide generalized library-building support services.
-
- --config show all configuration variables
- --debug enable verbose shell tracing
--n, --dry-run display commands without modifying any files
- --features display basic configuration information and exit
- --finish same as \`--mode=finish'
- --help display this help message and exit
- --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
- --quiet same as \`--silent'
- --silent don't print informational messages
- --tag=TAG use configuration variables from tag TAG
- --version print version information
-
-MODE must be one of the following:
-
- clean remove files from the build directory
- compile compile a source file into a libtool object
- execute automatically set library path, then run a program
- finish complete the installation of libtool libraries
- install install libraries or executables
- link create a library or an executable
- uninstall remove libraries from an installed directory
-
-MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
-a more detailed description of MODE.
-
-Report bugs to <bug-libtool@gnu.org>."
- exit 0
- ;;
-
-clean)
- $echo \
-"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
-
-Remove files from the build directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, object or program, all the files associated
-with it are deleted. Otherwise, only FILE itself is deleted using RM."
- ;;
-
-compile)
- $echo \
-"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
-
-Compile a source file into a libtool library object.
-
-This mode accepts the following additional options:
-
- -o OUTPUT-FILE set the output file name to OUTPUT-FILE
- -prefer-pic try to building PIC objects only
- -prefer-non-pic try to building non-PIC objects only
- -static always build a \`.o' file suitable for static linking
-
-COMPILE-COMMAND is a command to be used in creating a \`standard' object file
-from the given SOURCEFILE.
-
-The output file name is determined by removing the directory component from
-SOURCEFILE, then substituting the C source code suffix \`.c' with the
-library object suffix, \`.lo'."
- ;;
-
-execute)
- $echo \
-"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
-
-Automatically set library path, then run a program.
-
-This mode accepts the following additional options:
-
- -dlopen FILE add the directory containing FILE to the library path
-
-This mode sets the library path environment variable according to \`-dlopen'
-flags.
-
-If any of the ARGS are libtool executable wrappers, then they are translated
-into their corresponding uninstalled binary, and any of their required library
-directories are added to the library path.
-
-Then, COMMAND is executed, with ARGS as arguments."
- ;;
-
-finish)
- $echo \
-"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
-
-Complete the installation of libtool libraries.
-
-Each LIBDIR is a directory that contains libtool libraries.
-
-The commands that this mode executes may require superuser privileges. Use
-the \`--dry-run' option if you just want to see what would be executed."
- ;;
-
-install)
- $echo \
-"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
-
-Install executables or libraries.
-
-INSTALL-COMMAND is the installation command. The first component should be
-either the \`install' or \`cp' program.
-
-The rest of the components are interpreted as arguments to that command (only
-BSD-compatible install options are recognized)."
- ;;
-
-link)
- $echo \
-"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
-
-Link object files or libraries together to form another library, or to
-create an executable program.
-
-LINK-COMMAND is a command using the C compiler that you would use to create
-a program from several object files.
-
-The following components of LINK-COMMAND are treated specially:
-
- -all-static do not do any dynamic linking at all
- -avoid-version do not add a version suffix if possible
- -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
- -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
- -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
- -export-symbols SYMFILE
- try to export only the symbols listed in SYMFILE
- -export-symbols-regex REGEX
- try to export only the symbols matching REGEX
- -LLIBDIR search LIBDIR for required installed libraries
- -lNAME OUTPUT-FILE requires the installed library libNAME
- -module build a library that can dlopened
- -no-fast-install disable the fast-install mode
- -no-install link a not-installable executable
- -no-undefined declare that a library does not refer to external symbols
- -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
- -objectlist FILE Use a list of object files found in FILE to specify objects
- -release RELEASE specify package release information
- -rpath LIBDIR the created library will eventually be installed in LIBDIR
- -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
- -static do not do any dynamic linking of libtool libraries
- -version-info CURRENT[:REVISION[:AGE]]
- specify library version info [each variable defaults to 0]
-
-All other options (arguments beginning with \`-') are ignored.
-
-Every other argument is treated as a filename. Files ending in \`.la' are
-treated as uninstalled libtool libraries, other files are standard or library
-object files.
-
-If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
-only library objects (\`.lo' files) may be specified, and \`-rpath' is
-required, except when creating a convenience library.
-
-If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
-using \`ar' and \`ranlib', or on Windows using \`lib'.
-
-If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
-is created, otherwise an executable program is created."
- ;;
-
-uninstall)
- $echo \
-"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
-
-Remove libraries from an installation directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, all the files associated with it are deleted.
-Otherwise, only FILE itself is deleted using RM."
- ;;
-
-*)
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
-esac
-
-$echo
-$echo "Try \`$modename --help' for more information about other modes."
-
-exit 0
-
-# The TAGs below are defined such that we never get into a situation
-# in which we disable both kinds of libraries. Given conflicting
-# choices, we go for a static library, that is the most portable,
-# since we can't tell whether shared libraries were disabled because
-# the user asked for that or because the platform doesn't support
-# them. This is particularly important on AIX, because we don't
-# support having both static and shared libraries enabled at the same
-# time on that platform, so we default to a shared-only configuration.
-# If a disable-shared tag is given, we'll fallback to a static-only
-# configuration. But we'll never go from static-only to shared-only.
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
-build_libtool_libs=no
-build_old_libs=yes
-# ### END LIBTOOL TAG CONFIG: disable-shared
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-static
-build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac`
-# ### END LIBTOOL TAG CONFIG: disable-static
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/man/Makefile.am b/man/Makefile.am
index 539c43dfed6..8d18165191a 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -17,11 +17,11 @@
## Process this file with automake to create Makefile.in
-man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \
+man_MANS = mysql.1 mysql_zap.1 mysqlaccess.1 \
mysqladmin.1 mysqld.1 mysqld_multi.1 mysqldump.1 mysqlshow.1 \
perror.1 replace.1 mysqld_safe.1 mysql_fix_privilege_tables.1
-EXTRA_DIST = mysql.1.in isamchk.1.in isamlog.1.in mysql_zap.1.in \
+EXTRA_DIST = mysql.1.in mysql_zap.1.in \
mysqlaccess.1.in mysqladmin.1.in mysqld.1.in mysqld_multi.1.in \
mysqldump.1.in mysqlshow.1.in perror.1.in replace.1.in mysqlman.1.in \
mysqld_safe.1.in mysql_fix_privilege_tables.1.in
diff --git a/man/isamchk.1.in b/man/isamchk.1.in
deleted file mode 100644
index d908e8af3ee..00000000000
--- a/man/isamchk.1.in
+++ /dev/null
@@ -1,145 +0,0 @@
-.TH isamchk 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database"
-.SH NAME
-.BR isamchk
- \- Description, check and repair of ISAM tables.
-Used without options all tables on the command will be checked for errors
-.SH USAGE
-isamchk [OPTIONS] tables[.ISM]
-.SH SYNOPSIS
-.B isamchk
-.RB [ \-a | \-\-analyze ]
-.RB [ \-# | \-\-debug=... ]
-.RB [ \-\-character\-sets\-dir=...]
-.RB [ \-C | \-\-default\-character\-set=...]
-.RB [ \-d | \-\-description ]
-.RB [ \-e | \-\-extend\-check ]
-.RB [ \-f | \-\-force ]
-.RB [ \-? | \-\-help ]
-.RB [ \-i | \-\-information ]
-.RB [ \-k | \-\-keys\-used=# ]
-.RB [ \-l | \-\-no\-symlinks]
-.RB [ \-q | \-\-quick ]
-.RB [ \-r | \-\-recover ]
-.RB [ \-o | \-\-safe\-recover ]
-.RB [ \-O | "\-\-set\-variable var=option"]
-.RB [ \-s | \-\-silent ]
-.RB [ \-S | \-\-sort\-index ]
-.RB [ \-R | \-\-sort\-records=#]
-.RB [ \-u | \-\-unpack ]
-.RB [ \-v | \-\-verbose ]
-.RB [ \-V | \-\-version ]
-.RB [ \-w | \-\-wait ]
-.SH DESCRIPTION
-.TP
-.BR \-a | \-\-analyze
-Analyze distribution of keys. Will make some joins in
-MySQL faster.
-.TP
-.BR \-# | \-\-debug=...
-Output debug log. Often this is 'd:t:o ,filename`
-.TP
-.BR \-\-character\-sets\-dir=...
-Directory where character sets are
-.TP
-.BR \-C | \-\-default\-character\-set=...
-Set the default character set
-.TP
-.BR \-d | \-\-description
-Prints some information about table.
-.TP
-.BR \-e | \-\-extend\-check
-Check the table VERY thoroughly. One need use this
-only in extreme cases as isamchk should normally find
-all errors even without this switch
-.TP
-.BR \-f | \-\-force
-Overwrite old temporary files.
-If one uses \-f when checking tables (running isamchk
-without \-r), isamchk will automatically restart with
-\-r on any wrong table.
-.TP
-.BR \-? | \-\-help
-Display help and exit.
-.TP
-.BR \-i | \-\-information
-Print statistics information about the table
-.TP
-.BR \-k | \-\-keys\-used=#
-Used with '\-r'. Tell ISAM to update only the first
-# keys. This can be used to get faster inserts!
-.TP
-.BR \-l | \-\-no\-symlinks
-Do not follow symbolic links when repairing. Normally
-isamchk repairs the table a symlink points at.
-.TP
-.BR \-q | \-\-quick
-Used with \-r to get a faster repair. (The data file
-isn't touched.) One can give a second '\-q' to force
-isamchk to modify the original datafile.
-.TP
-.BR \-r | \-\-recover
-Can fix almost anything except unique keys that aren't
-unique.
-.TP
-.BR \-o | \-\-safe\-recover
-Uses old recovery method; slower than '\-r' but can
-handle a couple of cases that '\-r' cannot handle.
-.TP
-.BR \-O | " \-\-set\-variable var=option "
-Change the value of a variable.
-.TP
-.BR \-s | \-\-silent
-Only print errors. One can use two \-s to make isamchk
-very silent
-.TP
-.BR \-S | \-\-sort\-index
-Sort index blocks. This speeds up 'read\-next' in
-applications
-.TP
-.BR \-R | \-\-sort\-records=#
-Sort records according to an index. This makes your
-data much more localized and may speed up things
-(It may be VERY slow to do a sort the first time!)
-.TP
-.BR \-u | \-\-unpack
-Unpack file packed with pack_isam.
-.TP
-.BR \-v | \-\-verbose
-Print more information. This can be used with
-\-d and \-e. Use many \-v for more verbosity!
-.TP
-.BR \-V | \-\-version
-Print version and exit.
-.TP
-.BR \-w | \-\-wait
-Wait if table is locked.
-.SH "SEE ALSO"
-isamlog(1),
-mysql(1),
-mysqlaccess(1),
-mysqladmin(1),
-mysqld(1),
-mysqld_multi(1),
-mysqld_safe(1),
-mysqldump(1),
-mysql_fix_privilege_tables(1),
-mysqlshow(1),
-mysql_zap(1),
-perror(1),
-replace(1)
-.P
-For more information please refer to the MySQL reference
-manual, which may already be installed locally and which
-is also available online at http://dev.mysql.com/doc/mysql/en
-.SH BUGS
-Please refer to http://bugs.mysql.com/ to report bugs.
-.SH AUTHOR
-Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@
-Michael (Monty) Widenius (monty@mysql.com),
-MySQL AB (http://www.mysql.com/).
-This software comes with no warranty.
-Manual page by L. (Kill-9) Pedersen
-(kill-9@kill\-9.dk), Mercurmedia Data Model Architect /
-system developer (http://www.mercurmedia.com)
-
-.\" end of man page
diff --git a/man/isamlog.1.in b/man/isamlog.1.in
deleted file mode 100644
index 5f69e70297a..00000000000
--- a/man/isamlog.1.in
+++ /dev/null
@@ -1,107 +0,0 @@
-.TH isamlog 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database"
-.SH NAME
-isamlog - Write info about whats in a nisam log file.
-.SH USAGE
-isamlog [-?iruvIV] [-c #] [-f #] [-F filepath/] [-o #] [-R file recordpos] [-w write_file] [log-filename [table ...]]
-.SH SYNOPSIS
-.B isamlog
-.RB [ -? | -I ]
-.RB [ -V ]
-.RB [ -c ]
-.RB [ -f ]
-.RB [ -F ]
-.RB [ -i ]
-.RB [ -o ]
-.RB [ "-p #" ]
-.RB [ -r ]
-.RB [ -R ]
-.RB [ -u ]
-.RB [ -v ]
-.RB [ -w ]
-.SH DESCRIPTION
-.TP
-.BR isamlog
-.TP
-.BR -? | -I
-info
-.TP
-.BR -V
-version
-.TP
-.BR -c
-do only # commands
-.TP
-.BR -f
-max open files
-.TP
-.BR -F
-file path
-.TP
-.BR -i
-extra info
-.TP
-.BR -o
-offset
-.TP
-.BR "-p #"
-remove # components from path
-.TP
-.BR -r
-recover
-.TP
-.BR -R
-file recordposition
-.TP
-.BR -u
-update
-.TP
-.BR -v
-verbose
-.TP
-.BR -w
-write file
-.SH NOTE
-If no file name is given isam.log is used
-One can give a second and a third '-v' for more verbose.
-Normaly one does a update (-u).
-If a recover is done all writes and all possibly updates and deletes is done
-and errors are only counted.
-If one gives table names as arguments only these tables will be updated
-
-
-
-.SH "SEE ALSO"
-isamchk(1),
-mysql(1),
-mysqlaccess(1),
-mysqladmin(1),
-mysqld(1),
-mysqld_multi(1),
-mysqld_safe(1),
-mysqldump(1),
-mysql_fix_privilege_tables(1),
-mysqlshow(1),
-mysql_zap(1),
-perror(1),
-replace(1)
-.P
-For more information please refer to the MySQL reference
-manual, which may already be installed locally and which
-is also available online at http://dev.mysql.com/doc/mysql/en
-.SH BUGS
-Please refer to http://bugs.mysql.com/ to report bugs.
-
-.SH AUTHOR
-
-Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@
-Michael (Monty) Widenius (monty@mysql.com),
-MySQL AB (http://www.mysql.com/).
-This software comes with no warranty.
-Manual page by L. (Kill-9) Pedersen
-(kill-9@kill-9.dk), Mercurmedia Data Model Architect /
-system developer (http://www.mercurmedia.com)
-
-
-.\" end of man page
-
-
diff --git a/merge/.cvsignore b/merge/.cvsignore
deleted file mode 100644
index e9955884756..00000000000
--- a/merge/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-.deps
-Makefile
-Makefile.in
diff --git a/merge/Makefile.am b/merge/Makefile.am
deleted file mode 100644
index 080e5e61747..00000000000
--- a/merge/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include
-pkglib_LIBRARIES = libmerge.a
-noinst_HEADERS = mrg_def.h
-libmerge_a_SOURCES = mrg_open.c mrg_extra.c mrg_info.c mrg_locking.c \
- mrg_rrnd.c mrg_update.c mrg_delete.c mrg_rsame.c \
- mrg_panic.c mrg_close.c mrg_create.c mrg_static.c
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/merge/make-ccc b/merge/make-ccc
deleted file mode 100755
index 3f37c33638f..00000000000
--- a/merge/make-ccc
+++ /dev/null
@@ -1,3 +0,0 @@
-ccc -I./../include -I../include -DDBUG_OFF -fast -O3 -c _locking.c close.c create.c delete.c extra.c info.c open.c panic.c rrnd.c rsame.c static.c update.c
-rm libmerge.a
-ar -cr libmerge.a _locking.o
diff --git a/merge/mrg_close.c b/merge/mrg_close.c
deleted file mode 100644
index e835fd06e47..00000000000
--- a/merge/mrg_close.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* close a isam-database */
-
-#include "mrg_def.h"
-
-int mrg_close(register MRG_INFO *info)
-{
- int error=0,new_error;
- MRG_TABLE *file;
- DBUG_ENTER("mrg_close");
-
- for (file=info->open_tables ; file != info->end_table ; file++)
- if ((new_error=nisam_close(file->table)))
- error=new_error;
- pthread_mutex_lock(&THR_LOCK_open);
- mrg_open_list=list_delete(mrg_open_list,&info->open_list);
- pthread_mutex_unlock(&THR_LOCK_open);
- my_free((gptr) info,MYF(0));
- if (error)
- {
- my_errno=error;
- DBUG_RETURN(-1);
- }
- DBUG_RETURN(0);
-}
diff --git a/merge/mrg_create.c b/merge/mrg_create.c
deleted file mode 100644
index 3508b7967f4..00000000000
--- a/merge/mrg_create.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Create a MERGE-file */
-
-#include "mrg_def.h"
-
- /* create file named 'name' and save filenames in it
- table_names should be NULL or a vector of string-pointers with
- a NULL-pointer last
- */
-
-int mrg_create(const char *name, const char**table_names)
-{
- int save_errno;
- uint errpos;
- File file;
- char buff[FN_REFLEN],*end;
- DBUG_ENTER("mrg_create");
-
- errpos=0;
- if ((file = my_create(fn_format(buff,name,"",MRG_NAME_EXT,4),0,
- O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0)
- goto err;
- errpos=1;
- if (table_names)
- for ( ; *table_names ; table_names++)
- {
- strmov(buff,*table_names);
- fn_same(buff,name,4);
- *(end=strend(buff))='\n';
- if (my_write(file,*table_names,(uint) (end-buff+1),
- MYF(MY_WME | MY_NABP)))
- goto err;
- }
- if (my_close(file,MYF(0)))
- goto err;
- DBUG_RETURN(0);
-
-err:
- save_errno=my_errno;
- switch (errpos) {
- case 1:
- VOID(my_close(file,MYF(0)));
- }
- my_errno=save_errno; /* Return right errocode */
- DBUG_RETURN(-1);
-} /* mrg_create */
diff --git a/merge/mrg_extra.c b/merge/mrg_extra.c
deleted file mode 100644
index d37b1aaa03c..00000000000
--- a/merge/mrg_extra.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Extra functions we want to do with a database
- - All flags, exept record-cache-flags, are set in all used databases
- record-cache-flags are set in mrg_rrnd when we are changing database.
-*/
-
-#include "mrg_def.h"
-
-int mrg_extra(
-MRG_INFO *info,
-enum ha_extra_function function)
-{
- MRG_TABLE *file;
-
- if (function == HA_EXTRA_CACHE)
- info->cache_in_use=1;
- else
- {
- if (function == HA_EXTRA_NO_CACHE || function == HA_EXTRA_RESET)
- info->cache_in_use=0;
- if (function == HA_EXTRA_RESET || function == HA_EXTRA_RESET_STATE)
- {
- info->current_table=0;
- info->last_used_table=info->open_tables;
- }
- for (file=info->open_tables ; file != info->end_table ; file++)
- nisam_extra(file->table,function);
- }
- return 0;
-}
diff --git a/merge/mrg_info.c b/merge/mrg_info.c
deleted file mode 100644
index 57f22276487..00000000000
--- a/merge/mrg_info.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "mrg_def.h"
-
-ulong mrg_position(MRG_INFO *info)
-{
- MRG_TABLE *current_table;
-
- if (!(current_table = info->current_table) &&
- info->open_tables != info->end_table)
- current_table = info->open_tables;
- return (current_table ?
- (ulong) (current_table->table->lastpos +
- current_table->file_offset) :
- ~(ulong) 0);
-}
-
- /* If flag != 0 one only gets pos of last record */
-
-int mrg_info(MRG_INFO *info,register MERGE_INFO *x,int flag)
-{
- MRG_TABLE *current_table;
- DBUG_ENTER("mrg_info");
-
- if (!(current_table = info->current_table) &&
- info->open_tables != info->end_table)
- current_table = info->open_tables;
- x->recpos = info->current_table ?
- info->current_table->table->lastpos + info->current_table->file_offset :
- (ulong) -1L;
- if (flag != HA_STATUS_POS)
- {
- x->records = info->records;
- x->deleted = info->del;
- x->data_file_length = info->data_file_length;
- x->reclength = info->reclength;
- if (current_table)
- x->errkey = current_table->table->errkey;
- else
- { /* No tables in MRG */
- x->errkey=0;
- }
- x->options = info->options;
- }
- DBUG_RETURN(0);
-}
diff --git a/merge/mrg_open.c b/merge/mrg_open.c
deleted file mode 100644
index 6bf75392131..00000000000
--- a/merge/mrg_open.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* open a MERGE-database */
-
-#include "mrg_def.h"
-#include <stddef.h>
-#include <errno.h>
-#ifdef VMS
-#include "static.c"
-#endif
-
-/* open a MERGE-database.
-
- if handle_locking is 0 then exit with error if some database is locked
- if handle_locking is 1 then wait if database is locked
-*/
-
-
-MRG_INFO *mrg_open(
-const char *name,
-int mode,
-int handle_locking)
-{
- int save_errno,i,errpos;
- uint files,dir_length,length, options;
- ulonglong file_offset;
- char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
- MRG_INFO info,*m_info;
- File fd;
- IO_CACHE file;
- N_INFO *isam,*last_isam;
- DBUG_ENTER("mrg_open");
-
- LINT_INIT(last_isam);
- isam=0;
- errpos=files=0;
- bzero((gptr) &info,sizeof(info));
- bzero((char*) &file,sizeof(file));
- if ((fd=my_open(fn_format(name_buff,name,"",MRG_NAME_EXT,4),
- O_RDONLY | O_SHARE,MYF(0))) < 0 ||
- init_io_cache(&file, fd, IO_SIZE, READ_CACHE, 0, 0,
- MYF(MY_WME | MY_NABP)))
- goto err;
- errpos=1;
- dir_length=dirname_part(name_buff,name);
- info.reclength=0;
- while ((length=my_b_gets(&file,buff,FN_REFLEN-1)))
- {
- if ((end=buff+length)[-1] == '\n')
- end[-1]='\0';
- if (buff[0] && buff[0] != '#') /* Skip empty lines and comments */
- {
- last_isam=isam;
- if (!test_if_hard_path(buff))
- {
- VOID(strmake(name_buff+dir_length,buff,
- sizeof(name_buff)-1-dir_length));
- VOID(cleanup_dirname(buff,name_buff));
- }
- if (!(isam=nisam_open(buff,mode,test(handle_locking))))
- goto err;
- files++;
- }
- last_isam=isam;
- if (info.reclength && info.reclength != isam->s->base.reclength)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
- info.reclength=isam->s->base.reclength;
- }
- if (!(m_info= (MRG_INFO*) my_malloc(sizeof(MRG_INFO)+files*sizeof(MRG_TABLE),
- MYF(MY_WME))))
- goto err;
- *m_info=info;
- m_info->open_tables=(MRG_TABLE *) (m_info+1);
- m_info->tables=files;
-
- options= (uint) ~0;
- for (i=files ; i-- > 0 ; )
- {
- m_info->open_tables[i].table=isam;
- m_info->options|=isam->s->base.options;
- options&=isam->s->base.options;
- m_info->records+=isam->s->state.records;
- m_info->del+=isam->s->state.del;
- m_info->data_file_length=isam->s->state.data_file_length;
- if (i)
- isam=(N_INFO*) (isam->open_list.next->data);
- }
- /* Don't force readonly if not all tables are readonly */
- if (! (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA)))
- m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA);
-
- /* Fix fileinfo for easyer debugging (actually set by rrnd) */
- file_offset=0;
- for (i=0 ; (uint) i < files ; i++)
- {
- m_info->open_tables[i].file_offset=(my_off_t) file_offset;
- file_offset+=m_info->open_tables[i].table->s->state.data_file_length;
- }
- if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L)
- {
- my_errno=HA_ERR_RECORD_FILE_FULL;
- my_free((char*) m_info,MYF(0));
- goto err;
- }
-
- m_info->end_table=m_info->open_tables+files;
- m_info->last_used_table=m_info->open_tables;
-
- VOID(my_close(fd,MYF(0)));
- end_io_cache(&file);
- m_info->open_list.data=(void*) m_info;
- pthread_mutex_lock(&THR_LOCK_open);
- mrg_open_list=list_add(mrg_open_list,&m_info->open_list);
- pthread_mutex_unlock(&THR_LOCK_open);
- DBUG_RETURN(m_info);
-
-err:
- save_errno=my_errno;
- switch (errpos) {
- case 1:
- VOID(my_close(fd,MYF(0)));
- end_io_cache(&file);
- for (i=files ; i-- > 0 ; )
- {
- isam=last_isam;
- if (i)
- last_isam=(N_INFO*) (isam->open_list.next->data);
- nisam_close(isam);
- }
- }
- my_errno=save_errno;
- DBUG_RETURN (NULL);
-}
diff --git a/merge/mrg_panic.c b/merge/mrg_panic.c
deleted file mode 100644
index e9ad1974d8f..00000000000
--- a/merge/mrg_panic.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "mrg_def.h"
-
- /* if flag == HA_PANIC_CLOSE then all misam files are closed */
- /* if flag == HA_PANIC_WRITE then all misam files are unlocked and
- all changed data in single user misam is written to file */
- /* if flag == HA_PANIC_READ then all misam files that was locked when
- nisam_panic(HA_PANIC_WRITE) was done is locked. A ni_readinfo() is
- done for all single user files to get changes in database */
-
-
-int mrg_panic(
-enum ha_panic_function flag)
-{
- int error=0;
- LIST *list_element,*next_open;
- MRG_INFO *info;
- DBUG_ENTER("mrg_panic");
-
- for (list_element=mrg_open_list ; list_element ; list_element=next_open)
- {
- next_open=list_element->next; /* Save if close */
- info=(MRG_INFO*) list_element->data;
- if (flag == HA_PANIC_CLOSE && mrg_close(info))
- error=my_errno;
- }
- if (mrg_open_list && flag != HA_PANIC_CLOSE)
- DBUG_RETURN(nisam_panic(flag));
- if (!error) DBUG_RETURN(0);
- my_errno=error;
- DBUG_RETURN(-1);
-}
diff --git a/merge/mrg_rrnd.c b/merge/mrg_rrnd.c
deleted file mode 100644
index 206427d74d4..00000000000
--- a/merge/mrg_rrnd.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Read a record with random-access. The position to the record must
- get by mrg_info(). The next record can be read with pos= -1 */
-
-
-#include "mrg_def.h"
-
-static MRG_TABLE *find_table(MRG_TABLE *start,MRG_TABLE *end,mrg_off_t pos);
-
-/*
- If filepos == -1, read next
- Returns same as nisam_rrnd:
- 0 = Ok.
- 1 = Record deleted.
- -1 = EOF (or something, errno should be HA_ERR_END_OF_FILE)
-*/
-
-int mrg_rrnd(MRG_INFO *info,byte *buf,mrg_off_t filepos)
-{
- int error;
- N_INFO *isam_info;
-
- if (filepos == ~(mrg_off_t) 0) /* Can't use HA_POS_ERROR */
- {
- if (!info->current_table)
- {
- if (info->open_tables == info->end_table)
- { /* No tables */
- my_errno=HA_ERR_END_OF_FILE;
- return -1;
- }
- isam_info=(info->current_table=info->open_tables)->table;
- if (info->cache_in_use)
- nisam_extra(isam_info,HA_EXTRA_CACHE);
- filepos=isam_info->s->pack.header_length;
- isam_info->lastinx= (uint) -1; /* Can't forward or backward */
- }
- else
- {
- isam_info=info->current_table->table;
- filepos= isam_info->nextpos;
- }
-
- for (;;)
- {
- isam_info->update&= HA_STATE_CHANGED;
- if ((error=(*isam_info->s->read_rnd)(isam_info,(byte*) buf,
- filepos,1)) >= 0 ||
- my_errno != HA_ERR_END_OF_FILE)
- return (error);
- if (info->cache_in_use)
- nisam_extra(info->current_table->table,HA_EXTRA_NO_CACHE);
- if (info->current_table+1 == info->end_table)
- return(-1);
- info->current_table++;
- info->last_used_table=info->current_table;
- if (info->cache_in_use)
- nisam_extra(info->current_table->table,HA_EXTRA_CACHE);
- info->current_table->file_offset=
- info->current_table[-1].file_offset+
- info->current_table[-1].table->s->state.data_file_length;
-
- isam_info=info->current_table->table;
- filepos=isam_info->s->pack.header_length;
- isam_info->lastinx= (uint) -1;
- }
- }
- info->current_table=find_table(info->open_tables,
- info->end_table-1,filepos);
- isam_info=info->current_table->table;
- isam_info->update&= HA_STATE_CHANGED;
- return ((*isam_info->s->read_rnd)(isam_info,(byte*) buf,
- (ulong) (filepos -
- info->current_table->file_offset),
- 0));
-}
-
-
- /* Find which table to use according to file-pos */
-
-static MRG_TABLE *find_table(MRG_TABLE *start,MRG_TABLE *end,mrg_off_t pos)
-{
- MRG_TABLE *mid;
-
- while (start != end)
- {
- mid=start+((uint) (end-start)+1)/2;
- if (mid->file_offset > pos)
- end=mid-1;
- else
- start=mid;
- }
- return start;
-}
diff --git a/merge/mrg_rsame.c b/merge/mrg_rsame.c
deleted file mode 100644
index ee840bc3060..00000000000
--- a/merge/mrg_rsame.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "mrg_def.h"
-
-
-int mrg_rsame(
-MRG_INFO *info,
-byte *record,
-int inx) /* not used, should be 0 */
-{
- if (inx)
- {
- my_errno=HA_ERR_WRONG_INDEX;
- return(-1);
- }
- if (!info->current_table)
- {
- my_errno=HA_ERR_NO_ACTIVE_RECORD;
- return(-1);
- }
- return nisam_rsame(info->current_table->table,record,inx);
-}
diff --git a/missing b/missing
deleted file mode 100755
index 0a7fb5a2ace..00000000000
--- a/missing
+++ /dev/null
@@ -1,283 +0,0 @@
-#! /bin/sh
-# Common stub for a few missing GNU programs while installing.
-# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
-# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
-
-# 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, 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.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-if test $# -eq 0; then
- echo 1>&2 "Try \`$0 --help' for more information"
- exit 1
-fi
-
-run=:
-
-# In the cases where this matters, `missing' is being run in the
-# srcdir already.
-if test -f configure.ac; then
- configure_ac=configure.ac
-else
- configure_ac=configure.in
-fi
-
-case "$1" in
---run)
- # Try to run requested program, and just exit if it succeeds.
- run=
- shift
- "$@" && exit 0
- ;;
-esac
-
-# If it does not exist, or fails to run (possibly an outdated version),
-# try to emulate it.
-case "$1" in
-
- -h|--h|--he|--hel|--help)
- echo "\
-$0 [OPTION]... PROGRAM [ARGUMENT]...
-
-Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
-error status if there is no known handling for PROGRAM.
-
-Options:
- -h, --help display this help and exit
- -v, --version output version information and exit
- --run try to run the given command, and emulate it if it fails
-
-Supported PROGRAM values:
- aclocal touch file \`aclocal.m4'
- autoconf touch file \`configure'
- autoheader touch file \`config.h.in'
- automake touch all \`Makefile.in' files
- bison create \`y.tab.[ch]', if possible, from existing .[ch]
- flex create \`lex.yy.c', if possible, from existing .c
- help2man touch the output file
- lex create \`lex.yy.c', if possible, from existing .c
- makeinfo touch the output file
- tar try tar, gnutar, gtar, then tar without non-portable flags
- yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
- ;;
-
- -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
- echo "missing 0.3 - GNU automake"
- ;;
-
- -*)
- echo 1>&2 "$0: Unknown \`$1' option"
- echo 1>&2 "Try \`$0 --help' for more information"
- exit 1
- ;;
-
- aclocal)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified \`acinclude.m4' or \`${configure_ac}'. You might want
- to install the \`Automake' and \`Perl' packages. Grab them from
- any GNU archive site."
- touch aclocal.m4
- ;;
-
- autoconf)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified \`${configure_ac}'. You might want to install the
- \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
- archive site."
- touch configure
- ;;
-
- autoheader)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified \`acconfig.h' or \`${configure_ac}'. You might want
- to install the \`Autoconf' and \`GNU m4' packages. Grab them
- from any GNU archive site."
- files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
- test -z "$files" && files="config.h"
- touch_files=
- for f in $files; do
- case "$f" in
- *:*) touch_files="$touch_files "`echo "$f" |
- sed -e 's/^[^:]*://' -e 's/:.*//'`;;
- *) touch_files="$touch_files $f.in";;
- esac
- done
- touch $touch_files
- ;;
-
- automake)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
- You might want to install the \`Automake' and \`Perl' packages.
- Grab them from any GNU archive site."
- find . -type f -name Makefile.am -print |
- sed 's/\.am$/.in/' |
- while read f; do touch "$f"; done
- ;;
-
- bison|yacc)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified a \`.y' file. You may need the \`Bison' package
- in order for those modifications to take effect. You can get
- \`Bison' from any GNU archive site."
- rm -f y.tab.c y.tab.h
- if [ $# -ne 1 ]; then
- eval LASTARG="\${$#}"
- case "$LASTARG" in
- *.y)
- SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" y.tab.c
- fi
- SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" y.tab.h
- fi
- ;;
- esac
- fi
- if [ ! -f y.tab.h ]; then
- echo >y.tab.h
- fi
- if [ ! -f y.tab.c ]; then
- echo 'main() { return 0; }' >y.tab.c
- fi
- ;;
-
- lex|flex)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified a \`.l' file. You may need the \`Flex' package
- in order for those modifications to take effect. You can get
- \`Flex' from any GNU archive site."
- rm -f lex.yy.c
- if [ $# -ne 1 ]; then
- eval LASTARG="\${$#}"
- case "$LASTARG" in
- *.l)
- SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" lex.yy.c
- fi
- ;;
- esac
- fi
- if [ ! -f lex.yy.c ]; then
- echo 'main() { return 0; }' >lex.yy.c
- fi
- ;;
-
- help2man)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified a dependency of a manual page. You may need the
- \`Help2man' package in order for those modifications to take
- effect. You can get \`Help2man' from any GNU archive site."
-
- file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
- if test -z "$file"; then
- file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
- fi
- if [ -f "$file" ]; then
- touch $file
- else
- test -z "$file" || exec >$file
- echo ".ab help2man is required to generate this page"
- exit 1
- fi
- ;;
-
- makeinfo)
- if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
- # We have makeinfo, but it failed.
- exit 1
- fi
-
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified a \`.texi' or \`.texinfo' file, or any other file
- indirectly affecting the aspect of the manual. The spurious
- call might also be the consequence of using a buggy \`make' (AIX,
- DU, IRIX). You might want to install the \`Texinfo' package or
- the \`GNU make' package. Grab either from any GNU archive site."
- file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
- if test -z "$file"; then
- file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
- file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
- fi
- touch $file
- ;;
-
- tar)
- shift
- if test -n "$run"; then
- echo 1>&2 "ERROR: \`tar' requires --run"
- exit 1
- fi
-
- # We have already tried tar in the generic part.
- # Look for gnutar/gtar before invocation to avoid ugly error
- # messages.
- if (gnutar --version > /dev/null 2>&1); then
- gnutar ${1+"$@"} && exit 0
- fi
- if (gtar --version > /dev/null 2>&1); then
- gtar ${1+"$@"} && exit 0
- fi
- firstarg="$1"
- if shift; then
- case "$firstarg" in
- *o*)
- firstarg=`echo "$firstarg" | sed s/o//`
- tar "$firstarg" ${1+"$@"} && exit 0
- ;;
- esac
- case "$firstarg" in
- *h*)
- firstarg=`echo "$firstarg" | sed s/h//`
- tar "$firstarg" ${1+"$@"} && exit 0
- ;;
- esac
- fi
-
- echo 1>&2 "\
-WARNING: I can't seem to be able to run \`tar' with the given arguments.
- You may want to install GNU tar or Free paxutils, or check the
- command line arguments."
- exit 1
- ;;
-
- *)
- echo 1>&2 "\
-WARNING: \`$1' is needed, and you do not seem to have it handy on your
- system. You might have modified some files without having the
- proper tools for further handling them. Check the \`README' file,
- it often tells you about the needed prerequirements for installing
- this package. You may also peek at any GNU archive site, in case
- some other package would contain this missing \`$1' program."
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/mkinstalldirs b/mkinstalldirs
deleted file mode 100755
index f945dbf2bce..00000000000
--- a/mkinstalldirs
+++ /dev/null
@@ -1,38 +0,0 @@
-#! /bin/sh
-# mkinstalldirs --- make directory hierarchy
-# Author: Noah Friedman <friedman@prep.ai.mit.edu>
-# Created: 1993-05-16
-# Public domain
-
-errstatus=0
-
-for file
-do
- set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
- shift
-
- pathcomp=
- for d
- do
- pathcomp="$pathcomp$d"
- case "$pathcomp" in
- -* ) pathcomp=./$pathcomp ;;
- esac
-
- if test ! -d "$pathcomp"; then
- echo "mkdir $pathcomp" 1>&2
-
- mkdir "$pathcomp" || lasterr=$?
-
- if test ! -d "$pathcomp"; then
- errstatus=$lasterr
- fi
- fi
-
- pathcomp="$pathcomp/"
- done
-done
-
-exit $errstatus
-
-# mkinstalldirs ends here
diff --git a/myisam/Makefile.am b/myisam/Makefile.am
index 6f304c8143d..e4327070997 100644
--- a/myisam/Makefile.am
+++ b/myisam/Makefile.am
@@ -17,8 +17,7 @@
EXTRA_DIST = mi_test_all.sh mi_test_all.res
pkgdata_DATA = mi_test_all mi_test_all.res
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index f1ff8f6d886..c18984c7584 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -68,7 +68,7 @@ struct st_ftb_expr
my_off_t docid[2];
float weight;
float cur_weight;
- byte *quot, *qend;
+ LIST *phrase; /* phrase words */
uint yesses; /* number of "yes" words matched */
uint nos; /* number of "no" words matched */
uint ythresh; /* number of "yes" words in expr */
@@ -132,20 +132,22 @@ static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b)
}
static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
- FTB_EXPR *up, uint depth)
+ FTB_EXPR *up, uint depth, byte *up_quot)
{
byte res;
FTB_PARAM param;
FT_WORD w;
FTB_WORD *ftbw;
FTB_EXPR *ftbe;
+ FT_WORD *phrase_word;
+ LIST *phrase_list;
uint extra=HA_FT_WLEN+ftb->info->s->rec_reflength; /* just a shortcut */
if (ftb->state != UNINITIALIZED)
return;
param.prev=' ';
- param.quot=up->quot;
+ param.quot= up_quot;
while ((res=ft_get_word(ftb->charset,start,end,&w,&param)))
{
int r=param.plusminus;
@@ -172,6 +174,14 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
if (param.yesno > 0) up->ythresh++;
queue_insert(& ftb->queue, (byte *)ftbw);
ftb->with_scan|=(param.trunc & FTB_FLAG_TRUNC);
+ case 4: /* not indexed word (stopword or too short/long) */
+ if (! up_quot) break;
+ phrase_word= (FT_WORD *)alloc_root(&ftb->mem_root, sizeof(FT_WORD));
+ phrase_list= (LIST *)alloc_root(&ftb->mem_root, sizeof(LIST));
+ phrase_word->pos= w.pos;
+ phrase_word->len= w.len;
+ phrase_list->data= (void *)phrase_word;
+ up->phrase= list_add(up->phrase, phrase_list);
break;
case 2: /* left bracket */
ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR));
@@ -182,13 +192,14 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
ftbe->up=up;
ftbe->ythresh=ftbe->yweaks=0;
ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR;
- if ((ftbe->quot=param.quot)) ftb->with_scan|=2;
+ ftbe->phrase= NULL;
+ if (param.quot) ftb->with_scan|=2;
if (param.yesno > 0) up->ythresh++;
- _ftb_parse_query(ftb, start, end, ftbe, depth+1);
+ _ftb_parse_query(ftb, start, end, ftbe, depth+1, param.quot);
param.quot=0;
break;
case 3: /* right bracket */
- if (up->quot) up->qend=param.quot;
+ if (up_quot) up->phrase= list_reverse(up->phrase);
return;
}
}
@@ -212,6 +223,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
byte *lastkey_buf=ftbw->word+ftbw->off;
LINT_INIT(off);
+ LINT_INIT(off);
if (ftbw->flags & FTB_FLAG_TRUNC)
lastkey_buf+=ftbw->len;
@@ -410,12 +422,12 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
ftbe->weight=1;
ftbe->flags=FTB_FLAG_YES;
ftbe->nos=1;
- ftbe->quot=0;
ftbe->up=0;
ftbe->ythresh=ftbe->yweaks=0;
ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR;
+ ftbe->phrase= NULL;
ftb->root=ftbe;
- _ftb_parse_query(ftb, &query, query+query_len, ftbe, 0);
+ _ftb_parse_query(ftb, &query, query+query_len, ftbe, 0, NULL);
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
sizeof(FTB_WORD *)*ftb->queue.elements);
memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements);
@@ -431,29 +443,45 @@ err:
}
-/* 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)
+/*
+ Checks if given buffer matches phrase list.
+
+ SYNOPSIS
+ _ftb_check_phrase()
+ s0 start of buffer
+ e0 end of buffer
+ phrase broken into list phrase
+ cs charset info
+
+ RETURN VALUE
+ 1 is returned if phrase found, 0 else.
+*/
+
+static int _ftb_check_phrase(const byte *s0, const byte *e0,
+ LIST *phrase, CHARSET_INFO *cs)
{
- const byte *p0= s0;
- my_bool s_after= true_word_char(cs, s1[0]);
- my_bool e_before= true_word_char(cs, e1[-1]);
- uint p0_len;
- my_match_t m[2];
+ FT_WORD h_word;
+ const byte *h_start= s0;
+ DBUG_ENTER("_ftb_strstr");
+ DBUG_ASSERT(phrase);
- while (p0 < e0)
+ while (ft_simple_get_word(cs, (byte **)&h_start, e0, &h_word, FALSE))
{
- if (cs->coll->instr(cs, p0, e0 - p0, s1, e1 - s1, m, 2) != 2)
- return(0);
- if ((!s_after || p0 + m[1].beg == s0 || !true_word_char(cs, p0[m[1].beg-1])) &&
- (!e_before || p0 + m[1].end == e0 || !true_word_char(cs, p0[m[1].end])))
- return(1);
- p0+= m[1].beg;
- p0+= (p0_len= my_mbcharlen(cs, *(uchar *)p0)) ? p0_len : 1;
+ FT_WORD *n_word;
+ LIST *phrase_element= phrase;
+ const byte *h_start1= h_start;
+ for (;;)
+ {
+ n_word= (FT_WORD *)phrase_element->data;
+ if (my_strnncoll(cs, h_word.pos, h_word.len, n_word->pos, n_word->len))
+ break;
+ if (! (phrase_element= phrase_element->next))
+ DBUG_RETURN(1);
+ if (! ft_simple_get_word(cs, (byte **)&h_start1, e0, &h_word, FALSE))
+ DBUG_RETURN(0);
+ }
}
-
- return(0);
+ DBUG_RETURN(0);
}
@@ -484,7 +512,7 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
{
yn=ftbe->flags;
weight=ftbe->cur_weight*ftbe->weight;
- if (mode && ftbe->quot)
+ if (mode && ftbe->phrase)
{
int not_found=1;
@@ -493,8 +521,8 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
{
if (!ftsi.pos)
continue;
- not_found = ! _ftb_strstr(ftsi.pos, ftsi.pos+ftsi.len,
- ftbe->quot, ftbe->qend, ftb->charset);
+ not_found = ! _ftb_check_phrase(ftsi.pos, ftsi.pos+ftsi.len,
+ ftbe->phrase, ftb->charset);
}
if (not_found) break;
} /* ftbe->quot */
@@ -642,8 +670,8 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
continue;
end=ftsi.pos+ftsi.len;
- while (ft_simple_get_word(ftb->charset,
- (byte **) &ftsi.pos, (byte *) end, &word))
+ while (ft_simple_get_word(ftb->charset, (byte **) &ftsi.pos,
+ (byte *) end, &word, TRUE))
{
int a, b, c;
for (a=0, b=ftb->queue.elements, c=(a+b)/2; b-a>1; c=(a+b)/2)
diff --git a/myisam/ft_parser.c b/myisam/ft_parser.c
index 0b1e68b0d70..2fad2363ae2 100644
--- a/myisam/ft_parser.c
+++ b/myisam/ft_parser.c
@@ -93,12 +93,14 @@ my_bool ft_boolean_check_syntax_string(const byte *str)
return 0;
}
-/* returns:
- * 0 - eof
- * 1 - word found
- * 2 - left bracket
- * 3 - right bracket
- */
+/*
+ RETURN VALUE
+ 0 - eof
+ 1 - word found
+ 2 - left bracket
+ 3 - right bracket
+ 4 - stopword found
+*/
byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end,
FT_WORD *word, FTB_PARAM *param)
{
@@ -161,6 +163,11 @@ byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end,
*start=doc;
return 1;
}
+ else if (length) /* make sure length > 0 (if start contains spaces only) */
+ {
+ *start= doc;
+ return 4;
+ }
}
if (param->quot)
{
@@ -170,18 +177,19 @@ byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end,
return 0;
}
-byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, byte *end,
- FT_WORD *word)
+byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, const byte *end,
+ FT_WORD *word, my_bool skip_stopwords)
{
byte *doc= *start;
uint mwc, length, mbl;
DBUG_ENTER("ft_simple_get_word");
- while (doc<end)
+ do
{
- for (;doc<end;doc++)
+ for (;; doc++)
{
- if (true_word_char(cs,*doc)) break;
+ if (doc >= end) DBUG_RETURN(0);
+ if (true_word_char(cs, *doc)) break;
}
mwc= length= 0;
@@ -193,13 +201,14 @@ byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, byte *end,
word->len= (uint)(doc-word->pos) - mwc;
- if (length >= ft_min_word_len && length < ft_max_word_len &&
- !is_stopword(word->pos, word->len))
+ if (skip_stopwords == FALSE ||
+ (length >= ft_min_word_len && length < ft_max_word_len &&
+ !is_stopword(word->pos, word->len)))
{
*start= doc;
DBUG_RETURN(1);
}
- }
+ } while (doc < end);
DBUG_RETURN(0);
}
@@ -217,7 +226,7 @@ int ft_parse(TREE *wtree, byte *doc, int doclen, my_bool with_alloc)
FT_WORD w;
DBUG_ENTER("ft_parse");
- while (ft_simple_get_word(wtree->custom_arg, &doc,end,&w))
+ while (ft_simple_get_word(wtree->custom_arg, &doc, end, &w, TRUE))
{
if (with_alloc)
{
diff --git a/myisam/ft_static.c b/myisam/ft_static.c
index 994a94d0c49..e221950f445 100644
--- a/myisam/ft_static.c
+++ b/myisam/ft_static.c
@@ -25,23 +25,25 @@ char ft_boolean_syntax[]="+ -><()~*:\"\"&|";
const HA_KEYSEG ft_keysegs[FT_SEGS]={
{
- HA_KEYTYPE_VARTEXT, /* type */
- 63, /* language (will be overwritten) */
- 0, 0, 0, /* null_bit, bit_start, bit_end */
- HA_VAR_LENGTH | HA_PACK_KEY, /* flag */
- HA_FT_MAXBYTELEN, /* length */
- HA_FT_WLEN, /* start */
- 0, /* null_pos */
- NULL /* charset */
- },
- {
-/*
- Note, this (and the last HA_KEYTYPE_END) segment should NOT
- be packed in any way, otherwise w_search() won't be able to
- update key entry 'in vivo'
-*/
- HA_FT_WTYPE, 63, 0, 0, 0, HA_NO_SORT, HA_FT_WLEN, 0, 0, NULL
- }
+ 0, /* charset */
+ HA_FT_WLEN, /* start */
+ 0, /* null_pos */
+ 0, /* Bit pos */
+ HA_VAR_LENGTH_PART | HA_PACK_KEY, /* flag */
+ HA_FT_MAXBYTELEN, /* length */
+ HA_KEYTYPE_VARTEXT2, /* type */
+ 63, /* language (will be overwritten) */
+ 0, /* null_bit */
+ 2, 0, 0 /* bit_start, bit_end, bit_length */
+},
+{
+ /*
+ Note, this (and the last HA_KEYTYPE_END) segment should NOT
+ be packed in any way, otherwise w_search() won't be able to
+ update key entry 'in vivo'
+ */
+ 0, 0, 0, 0, HA_NO_SORT, HA_FT_WLEN, HA_FT_WTYPE, 63, 0, 0, 0, 0
+}
};
const struct _ft_vft _ft_vft_nlq = {
diff --git a/myisam/ft_stopwords.c b/myisam/ft_stopwords.c
index a4bce6ad4e8..ab51afb0e82 100644
--- a/myisam/ft_stopwords.c
+++ b/myisam/ft_stopwords.c
@@ -81,7 +81,7 @@ int ft_init_stopwords()
goto err0;
len=my_read(fd, buffer, len, MYF(MY_WME));
end=start+len;
- while (ft_simple_get_word(default_charset_info, &start, end, &w))
+ while (ft_simple_get_word(default_charset_info, &start, end, &w, TRUE))
{
if (ft_add_stopword(my_strdup_with_length(w.pos, w.len, MYF(0))))
goto err1;
diff --git a/myisam/ft_test1.c b/myisam/ft_test1.c
index f4884f8ca39..14be9aa1e8c 100644
--- a/myisam/ft_test1.c
+++ b/myisam/ft_test1.c
@@ -79,24 +79,24 @@ static int run_test(const char *filename)
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr :
extra_length);
if (extra_field == FIELD_VARCHAR)
- recinfo[0].length+=2;
+ recinfo[0].length+= HA_VARCHAR_PACKLENGTH(extra_length);
recinfo[1].type=key_field;
recinfo[1].length= (key_field == FIELD_BLOB ? 4+mi_portable_sizeof_char_ptr :
key_length);
if (key_field == FIELD_VARCHAR)
- recinfo[1].length+=2;
+ recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
keyinfo[0].seg[0].type= key_type;
- keyinfo[0].seg[0].flag= (key_field == FIELD_BLOB)?HA_BLOB_PART:
- (key_field == FIELD_VARCHAR)?HA_VAR_LENGTH:0;
+ keyinfo[0].seg[0].flag= (key_field == FIELD_BLOB) ? HA_BLOB_PART:
+ (key_field == FIELD_VARCHAR) ? HA_VAR_LENGTH_PART:0;
keyinfo[0].seg[0].start=recinfo[0].length;
keyinfo[0].seg[0].length=key_length;
keyinfo[0].seg[0].null_bit= 0;
keyinfo[0].seg[0].null_pos=0;
- keyinfo[0].seg[0].language=MY_CHARSET_CURRENT;
+ keyinfo[0].seg[0].language= default_charset_info->number;
keyinfo[0].flag = (no_fulltext?HA_PACK_KEY:HA_FULLTEXT);
if (!silent)
@@ -155,33 +155,42 @@ static int run_test(const char *filename)
if (!silent)
printf("- Reading rows with key\n");
for (i=0 ; i < NQUERIES ; i++)
- { FT_DOCLIST *result;
+ {
+ FT_DOCLIST *result;
result=ft_nlq_init_search(file,0,(char*) query[i],strlen(query[i]),1);
- if(!result) {
+ if(!result)
+ {
printf("Query %d: `%s' failed with errno %3d\n",i,query[i],my_errno);
continue;
}
printf("Query %d: `%s'. Found: %d. Top five documents:\n",
- i,query[i],result->ndocs);
- for(j=0;j<5;j++) { double w; int err;
- err=ft_nlq_read_next(result, read_record);
- if(err==HA_ERR_END_OF_FILE) {
- printf("No more matches!\n");
- break;
- } else if (err) {
- printf("ft_read_next %d failed with errno %3d\n",j,my_errno);
- break;
- }
- w=ft_nlq_get_relevance(result);
- if(key_field == FIELD_VARCHAR) {
- uint l;
- char *p;
- p=recinfo[0].length+read_record;
- l=uint2korr(p);
- printf("%10.7f: %.*s\n",w,(int) l,p+2);
- } else
- printf("%10.7f: %.*s\n",w,recinfo[1].length,
- recinfo[0].length+read_record);
+ i,query[i],result->ndocs);
+ for (j=0;j<5;j++)
+ {
+ double w; int err;
+ err= ft_nlq_read_next(result, read_record);
+ if (err==HA_ERR_END_OF_FILE)
+ {
+ printf("No more matches!\n");
+ break;
+ }
+ else if (err)
+ {
+ printf("ft_read_next %d failed with errno %3d\n",j,my_errno);
+ break;
+ }
+ w=ft_nlq_get_relevance(result);
+ if (key_field == FIELD_VARCHAR)
+ {
+ uint l;
+ char *p;
+ p=recinfo[0].length+read_record;
+ l=uint2korr(p);
+ printf("%10.7f: %.*s\n",w,(int) l,p+2);
+ }
+ else
+ printf("%10.7f: %.*s\n",w,recinfo[1].length,
+ recinfo[0].length+read_record);
}
ft_nlq_close_search(result);
}
@@ -215,9 +224,14 @@ void create_record(char *pos, int n)
else if (recinfo[0].type == FIELD_VARCHAR)
{
uint tmp;
- strnmov(pos+2,data[n].f0,keyinfo[0].seg[0].length);
- tmp=strlen(pos+2);
- int2store(pos,tmp);
+ /* -1 is here because pack_length is stored in seg->length */
+ uint pack_length= HA_VARCHAR_PACKLENGTH(keyinfo[0].seg[0].length-1);
+ strnmov(pos+pack_length,data[n].f0,keyinfo[0].seg[0].length);
+ tmp=strlen(pos+pack_length);
+ if (pack_length == 1)
+ *pos= (char) tmp;
+ else
+ int2store(pos,tmp);
pos+=recinfo[0].length;
}
else
@@ -239,9 +253,14 @@ void create_record(char *pos, int n)
else if (recinfo[1].type == FIELD_VARCHAR)
{
uint tmp;
- strnmov(pos+2,data[n].f2,keyinfo[0].seg[0].length);
- tmp=strlen(pos+2);
- int2store(pos,tmp);
+ /* -1 is here because pack_length is stored in seg->length */
+ uint pack_length= HA_VARCHAR_PACKLENGTH(keyinfo[0].seg[0].length-1);
+ strnmov(pos+pack_length,data[n].f2,keyinfo[0].seg[0].length);
+ tmp=strlen(pos+1);
+ if (pack_length == 1)
+ *pos= (char) tmp;
+ else
+ int2store(pos,tmp);
pos+=recinfo[1].length;
}
else
diff --git a/myisam/ft_update.c b/myisam/ft_update.c
index beccc062270..b8cd925bf4f 100644
--- a/myisam/ft_update.c
+++ b/myisam/ft_update.c
@@ -58,29 +58,27 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi)
DBUG_ENTER("_mi_ft_segiterator");
if (!ftsi->num)
- {
DBUG_RETURN(0);
- }
- else
- ftsi->num--;
+
+ ftsi->num--;
if (!ftsi->seg)
- {
DBUG_RETURN(1);
- }
- else
- ftsi->seg--;
+
+ ftsi->seg--;
if (ftsi->seg->null_bit &&
(ftsi->rec[ftsi->seg->null_pos] & ftsi->seg->null_bit))
{
- ftsi->pos=0;
- DBUG_RETURN(1);
+ ftsi->pos=0;
+ DBUG_RETURN(1);
}
ftsi->pos= ftsi->rec+ftsi->seg->start;
- if (ftsi->seg->flag & HA_VAR_LENGTH)
+ if (ftsi->seg->flag & HA_VAR_LENGTH_PART)
{
- ftsi->len=uint2korr(ftsi->pos);
- ftsi->pos+=2; /* Skip VARCHAR length */
+ uint pack_length= (ftsi->seg->bit_start);
+ ftsi->len= (pack_length == 1 ? (uint) *(uchar*) ftsi->pos :
+ uint2korr(ftsi->pos));
+ ftsi->pos+= pack_length; /* Skip VARCHAR length */
DBUG_RETURN(1);
}
if (ftsi->seg->flag & HA_BLOB_PART)
@@ -296,9 +294,11 @@ uint _ft_make_key(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wptr,
DBUG_RETURN(_mi_make_key(info,keynr,(uchar*) keybuf,buf,filepos));
}
+
/*
convert key value to ft2
*/
+
uint _mi_ft_convert_to_ft2(MI_INFO *info, uint keynr, uchar *key)
{
my_off_t root;
@@ -316,9 +316,12 @@ uint _mi_ft_convert_to_ft2(MI_INFO *info, uint keynr, uchar *key)
get_key_full_length_rdonly(key_length, key);
while (_mi_ck_delete(info, keynr, key, key_length) == 0)
- /* nothing to do here.
- _mi_ck_delete() will populate info->ft1_to_ft2 with deleted keys
- */;
+ {
+ /*
+ nothing to do here.
+ _mi_ck_delete() will populate info->ft1_to_ft2 with deleted keys
+ */
+ }
/* creating pageful of keys */
mi_putint(info->buff,length+2,0);
diff --git a/myisam/ftdefs.h b/myisam/ftdefs.h
index ddb9fbfead2..91c679a1e58 100644
--- a/myisam/ftdefs.h
+++ b/myisam/ftdefs.h
@@ -112,7 +112,8 @@ int is_stopword(char *word, uint len);
uint _ft_make_key(MI_INFO *, uint , byte *, FT_WORD *, my_off_t);
byte ft_get_word(CHARSET_INFO *, byte **, byte *, FT_WORD *, FTB_PARAM *);
-byte ft_simple_get_word(CHARSET_INFO *, byte **, byte *, FT_WORD *);
+byte ft_simple_get_word(CHARSET_INFO *, byte **, const byte *,
+ FT_WORD *, my_bool);
typedef struct _st_ft_seg_iterator {
uint num, len;
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 0c85b5234a1..1f453278eea 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -282,7 +282,8 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
if ((skr=(my_off_t) info->state->key_file_length) != size)
{
- if (skr > size)
+ /* Don't give error if file generated by myisampack */
+ if (skr > size && mi_is_any_key_active(info->s->state.key_map))
{
error=1;
mi_check_print_error(param,
@@ -379,7 +380,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
rec_per_key_part+=keyinfo->keysegs, key++, keyinfo++)
{
param->key_crc[key]=0;
- if (!(((ulonglong) 1 << key) & share->state.key_map))
+ if (! mi_is_key_active(share->state.key_map, key))
{
/* Remember old statistics for key */
memcpy((char*) rec_per_key_part,
@@ -507,7 +508,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
(int) ((my_off_t2double(key_totlength) -
my_off_t2double(all_keydata))*100.0/
my_off_t2double(key_totlength)));
- else if (all_totaldata != 0L && share->state.key_map)
+ else if (all_totaldata != 0L && mi_is_any_key_active(share->state.key_map))
puts("");
}
if (param->key_file_blocks != info->state->key_file_length &&
@@ -1035,7 +1036,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
for (key=0,keyinfo= info->s->keyinfo; key < info->s->base.keys;
key++,keyinfo++)
{
- if ((((ulonglong) 1 << key) & info->s->state.key_map))
+ if (mi_is_key_active(info->s->state.key_map, key))
{
if(!(keyinfo->flag & HA_FULLTEXT))
{
@@ -1303,8 +1304,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
*/
if (param->testflag & T_CREATE_MISSING_KEYS)
- share->state.key_map= ((((ulonglong) 1L << share->base.keys)-1) &
- param->keys_in_use);
+ mi_copy_keys_active(share->state.key_map, share->base.keys,
+ param->keys_in_use);
info->state->key_file_length=share->base.keystart;
@@ -1466,7 +1467,7 @@ static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff,
key=info->lastkey+info->s->base.max_key_length;
for (i=0 ; i < info->s->base.keys ; i++)
{
- if (((ulonglong) 1 << i) & info->s->state.key_map)
+ if (mi_is_key_active(info->s->state.key_map, i))
{
if (info->s->keyinfo[i].flag & HA_FULLTEXT )
{
@@ -1497,7 +1498,7 @@ static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff,
info->errkey=(int) i; /* This key was found */
while ( i-- > 0 )
{
- if (((ulonglong) 1 << i) & info->s->state.key_map)
+ if (mi_is_key_active(info->s->state.key_map, i))
{
if (info->s->keyinfo[i].flag & HA_FULLTEXT)
{
@@ -1534,7 +1535,7 @@ int movepoint(register MI_INFO *info, byte *record, my_off_t oldpos,
key=info->lastkey+info->s->base.max_key_length;
for (i=0 ; i < info->s->base.keys; i++)
{
- if (i != prot_key && (((ulonglong) 1 << i) & info->s->state.key_map))
+ if (i != prot_key && mi_is_key_active(info->s->state.key_map, i))
{
key_length=_mi_make_key(info,i,key,record,oldpos);
if (info->s->keyinfo[i].flag & HA_NOSAME)
@@ -1633,7 +1634,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
key++,keyinfo++)
{
- if (!(((ulonglong) 1 << key) & share->state.key_map))
+ if (! mi_is_key_active(info->s->state.key_map, key))
continue;
if (share->state.key_root[key] != HA_OFFSET_ERROR)
@@ -2028,7 +2029,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
sort_param.read_cache=param->read_cache;
sort_param.keyinfo=share->keyinfo+sort_param.key;
sort_param.seg=sort_param.keyinfo->seg;
- if (!(((ulonglong) 1 << sort_param.key) & key_map))
+ if (! mi_is_key_active(key_map, sort_param.key))
{
/* Remember old statistics for key */
memcpy((char*) rec_per_key_part,
@@ -2049,7 +2050,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
sort_param.key_length+=keyseg[i].length;
if (keyseg[i].flag & HA_SPACE_PACK)
sort_param.key_length+=get_pack_length(keyseg[i].length);
- if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
sort_param.key_length+=2 + test(keyseg[i].length >= 127);
if (keyseg[i].flag & HA_NULL_PART)
sort_param.key_length++;
@@ -2089,7 +2090,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
if (param->testflag & T_STATISTICS)
update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique,
(ulonglong) info->state->records);
- share->state.key_map|=(ulonglong) 1 << sort_param.key;
+ mi_set_key_active(share->state.key_map, sort_param.key);
if (sort_param.fix_datafile)
{
@@ -2410,7 +2411,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
sort_param[i].key=key;
sort_param[i].keyinfo=share->keyinfo+key;
sort_param[i].seg=sort_param[i].keyinfo->seg;
- if (!(((ulonglong) 1 << key) & key_map))
+ if (! mi_is_key_active(key_map, key))
{
/* Remember old statistics for key */
memcpy((char*) rec_per_key_part,
@@ -2458,7 +2459,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
sort_param[i].key_length+=keyseg->length;
if (keyseg->flag & HA_SPACE_PACK)
sort_param[i].key_length+=get_pack_length(keyseg->length);
- if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
sort_param[i].key_length+=2 + test(keyseg->length >= 127);
if (keyseg->flag & HA_NULL_PART)
sort_param[i].key_length++;
@@ -3925,8 +3926,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
{
byte *record;
if (!info->s->base.auto_key ||
- !(((ulonglong) 1 << (info->s->base.auto_key-1)
- & info->s->state.key_map)))
+ ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
{
if (!(param->testflag & T_VERY_SILENT))
mi_check_print_info(param,
@@ -4079,7 +4079,7 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows)
if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
{
- share->state.key_map&= ~ ((ulonglong) 1 << i);
+ mi_clear_key_active(share->state.key_map, i);
info->update|= HA_STATE_CHANGED;
}
}
@@ -4103,7 +4103,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
mi_repair_by_sort only works if we have at least one key. If we don't
have any keys, we should use the normal repair.
*/
- if (!key_map)
+ if (! mi_is_any_key_active(key_map))
return FALSE; /* Can't use sort */
for (i=0 ; i < share->base.keys ; i++,key++)
{
diff --git a/myisam/mi_checksum.c b/myisam/mi_checksum.c
index 95338434211..33a51068fb0 100644
--- a/myisam/mi_checksum.c
+++ b/myisam/mi_checksum.c
@@ -40,8 +40,12 @@ ha_checksum mi_checksum(MI_INFO *info, const byte *buf)
}
case FIELD_VARCHAR:
{
- length=uint2korr(buf);
- pos=buf+2;
+ uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length-1);
+ if (pack_length == 1)
+ length= (ulong) *(uchar*) buf;
+ else
+ length= uint2korr(buf);
+ pos= buf+pack_length;
break;
}
default:
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 41c965c7c80..6d4106afda5 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -43,7 +43,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
myf create_flag;
uint fields,length,max_key_length,packed,pointer,real_length_diff,
key_length,info_length,key_segs,options,min_key_length_skip,
- base_pos,varchar_count,long_varchar_count,varchar_length,
+ base_pos,long_varchar_count,varchar_length,
max_key_block_length,unique_key_parts,fulltext_keys,offset;
ulong reclength, real_reclength,min_pack_length;
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
@@ -99,7 +99,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Start by checking fields and field-types used */
- reclength=varchar_count=varchar_length=long_varchar_count=packed=
+ reclength=varchar_length=long_varchar_count=packed=
min_pack_length=pack_reclength=0;
for (rec=recinfo, fields=0 ;
fields != columns ;
@@ -130,14 +130,15 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
}
else if (type == FIELD_VARCHAR)
{
- varchar_count++;
- varchar_length+=rec->length-2;
+ varchar_length+= rec->length-1; /* Used for min_pack_length */
packed--;
- pack_reclength+=1;
- if (test(rec->length > 257))
- { /* May be packed on 3 bytes */
+ pack_reclength++;
+ min_pack_length++;
+ /* We must test for 257 as length includes pack-length */
+ if (test(rec->length >= 257))
+ {
long_varchar_count++;
- pack_reclength+=2;
+ pack_reclength+= 2; /* May be packed on 3 bytes */
}
}
else if (type != FIELD_SKIP_ZERO)
@@ -169,12 +170,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* We can't use checksum with static length rows */
if (!(options & HA_OPTION_PACK_RECORD))
options&= ~HA_OPTION_CHECKSUM;
- if (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
- min_pack_length+=varchar_count; /* Min length to pack */
- else
- {
- min_pack_length+=varchar_length+2*varchar_count;
- }
+ if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
+ min_pack_length+= varchar_length;
if (flags & HA_CREATE_TMP_TABLE)
{
options|= HA_OPTION_TMP_TABLE;
@@ -222,7 +219,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
reclength=pointer+1; /* reserve place for delete link */
}
else
- reclength+=long_varchar_count; /* We need space for this! */
+ reclength+= long_varchar_count; /* We need space for varchar! */
max_key_length=0; tot_length=0 ; key_segs=0;
fulltext_keys=0;
@@ -265,7 +262,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
j++, keyseg++)
{
if (keyseg->type != HA_KEYTYPE_BINARY &&
- keyseg->type != HA_KEYTYPE_VARBINARY)
+ keyseg->type != HA_KEYTYPE_VARBINARY1 &&
+ keyseg->type != HA_KEYTYPE_VARBINARY2)
{
my_errno=HA_WRONG_CREATE_OPTION;
goto err;
@@ -280,8 +278,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
goto err;
#endif /*HAVE_SPATIAL*/
}
- else
- if (keydef->flag & HA_FULLTEXT)
+ else if (keydef->flag & HA_FULLTEXT)
{
keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
@@ -290,11 +287,22 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
j++, keyseg++)
{
if (keyseg->type != HA_KEYTYPE_TEXT &&
- keyseg->type != HA_KEYTYPE_VARTEXT)
+ keyseg->type != HA_KEYTYPE_VARTEXT1 &&
+ keyseg->type != HA_KEYTYPE_VARTEXT2)
{
my_errno=HA_WRONG_CREATE_OPTION;
goto err;
}
+ if (!(keyseg->flag & HA_BLOB_PART) &&
+ (keyseg->type == HA_KEYTYPE_VARTEXT1 ||
+ keyseg->type == HA_KEYTYPE_VARTEXT2))
+ {
+ /* Make a flag that this is a VARCHAR */
+ keyseg->flag|= HA_VAR_LENGTH_PART;
+ /* Store in bit_start number of bytes used to pack the length */
+ keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1)?
+ 1 : 2);
+ }
}
fulltext_keys++;
@@ -315,7 +323,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Only use HA_PACK_KEY when first segment is a variable length key */
if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
- HA_VAR_LENGTH)))
+ HA_VAR_LENGTH_PART)))
{
/* pack relative to previous key */
keydef->flag&= ~HA_PACK_KEY;
@@ -349,12 +357,27 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
case HA_KEYTYPE_UINT24:
case HA_KEYTYPE_INT8:
keyseg->flag|= HA_SWAP_KEY;
- /* fall through */
+ break;
+ case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
+ case HA_KEYTYPE_VARBINARY1:
+ case HA_KEYTYPE_VARBINARY2:
+ if (!(keyseg->flag & HA_BLOB_PART))
+ {
+ /* Make a flag that this is a VARCHAR */
+ keyseg->flag|= HA_VAR_LENGTH_PART;
+ /* Store in bit_start number of bytes used to pack the length */
+ keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
+ keyseg->type == HA_KEYTYPE_VARBINARY1) ?
+ 1 : 2);
+ }
+ break;
default:
break;
}
if (keyseg->flag & HA_SPACE_PACK)
{
+ DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART));
keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
length++; /* At least one length byte */
@@ -365,8 +388,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
length+=2;
}
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
+ DBUG_ASSERT(!test_all_bits(keyseg->flag,
+ (HA_VAR_LENGTH_PART | HA_BLOB_PART)));
keydef->flag|=HA_VAR_LENGTH_KEY;
length++; /* At least one length byte */
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
@@ -485,7 +510,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
mi_int2store(share.state.header.key_parts,key_segs);
mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
- share.state.key_map = ((ulonglong) 1 << keys)-1;
+ mi_set_all_keys_active(share.state.key_map, keys);
share.base.keystart = share.state.state.key_file_length=
MY_ALIGN(info_length, myisam_block_size);
share.base.max_key_block_length=max_key_block_length;
@@ -621,10 +646,12 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{
HA_KEYSEG sseg;
sseg.type=SPTYPE;
- sseg.language= 7;
+ sseg.language= 7; /* Binary */
sseg.null_bit=0;
sseg.bit_start=0;
sseg.bit_end=0;
+ sseg.bit_length= 0;
+ sseg.bit_pos= 0;
sseg.length=SPLEN;
sseg.null_pos=0;
sseg.start=j*SPLEN;
@@ -642,7 +669,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{
tmp_keydef.keysegs=1;
tmp_keydef.flag= HA_UNIQUE_CHECK;
- tmp_keydef.block_length= myisam_block_size;
+ tmp_keydef.block_length= (uint16)myisam_block_size;
tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
@@ -657,11 +684,31 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Save unique definition */
for (i=0 ; i < share.state.header.uniques ; i++)
{
+ HA_KEYSEG *keyseg_end;
+ keyseg= uniquedefs[i].seg;
if (mi_uniquedef_write(file, &uniquedefs[i]))
goto err;
- for (j=0 ; j < uniquedefs[i].keysegs ; j++)
+ for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs;
+ keyseg < keyseg_end;
+ keyseg++)
{
- if (mi_keyseg_write(file, &uniquedefs[i].seg[j]))
+ switch (keyseg->type) {
+ case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
+ case HA_KEYTYPE_VARBINARY1:
+ case HA_KEYTYPE_VARBINARY2:
+ if (!(keyseg->flag & HA_BLOB_PART))
+ {
+ keyseg->flag|= HA_VAR_LENGTH_PART;
+ keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
+ keyseg->type == HA_KEYTYPE_VARBINARY1) ?
+ 1 : 2);
+ }
+ break;
+ default:
+ break;
+ }
+ if (mi_keyseg_write(file, keyseg))
goto err;
}
}
diff --git a/myisam/mi_dbug.c b/myisam/mi_dbug.c
index 02d1c7d05d6..e782d21afe7 100644
--- a/myisam/mi_dbug.c
+++ b/myisam/mi_dbug.c
@@ -131,9 +131,21 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg,
key=end;
break;
}
+ case HA_KEYTYPE_BIT:
+ {
+ uint i;
+ fputs("0x",stream);
+ for (i=0 ; i < keyseg->length ; i++)
+ fprintf(stream, "%02x", (uint) *key++);
+ key= end;
+ break;
+ }
+
#endif
- case HA_KEYTYPE_VARTEXT: /* VARCHAR and TEXT */
- case HA_KEYTYPE_VARBINARY: /* VARBINARY and BLOB */
+ case HA_KEYTYPE_VARTEXT1: /* VARCHAR and TEXT */
+ case HA_KEYTYPE_VARTEXT2: /* VARCHAR and TEXT */
+ case HA_KEYTYPE_VARBINARY1: /* VARBINARY and BLOB */
+ case HA_KEYTYPE_VARBINARY2: /* VARBINARY and BLOB */
{
uint tmp_length;
get_key_length(tmp_length,key);
diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c
index b964cb35dd8..60a07254e82 100644
--- a/myisam/mi_delete.c
+++ b/myisam/mi_delete.c
@@ -45,6 +45,12 @@ int mi_delete(MI_INFO *info,const byte *record)
/* Test if record is in datafile */
+ DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
+ mi_print_error(info->s, HA_ERR_CRASHED);
+ DBUG_RETURN(my_errno= HA_ERR_CRASHED););
+ DBUG_EXECUTE_IF("my_error_test_undefined_error",
+ mi_print_error(info->s, INT_MAX);
+ DBUG_RETURN(my_errno= INT_MAX););
if (!(info->update & HA_STATE_AKTIV))
{
DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND); /* No database read */
@@ -68,7 +74,7 @@ int mi_delete(MI_INFO *info,const byte *record)
old_key=info->lastkey2;
for (i=0 ; i < share->base.keys ; i++ )
{
- if (((ulonglong) 1 << i) & info->s->state.key_map)
+ if (mi_is_key_active(info->s->state.key_map, i))
{
info->s->keyinfo[i].version++;
if (info->s->keyinfo[i].flag & HA_FULLTEXT )
@@ -109,13 +115,19 @@ err:
mi_sizestore(lastpos,info->lastpos);
myisam_log_command(MI_LOG_DELETE,info,(byte*) lastpos, sizeof(lastpos),0);
if (save_errno != HA_ERR_RECORD_CHANGED)
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* mark table crashed */
+ }
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
allow_break(); /* Allow SIGHUP & SIGINT */
my_errno=save_errno;
if (save_errno == HA_ERR_KEY_NOT_FOUND)
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
+ }
DBUG_RETURN(my_errno);
} /* mi_delete */
@@ -142,6 +154,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
if ((old_root=*root) == HA_OFFSET_ERROR)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
DBUG_RETURN(my_errno=HA_ERR_CRASHED);
}
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
@@ -253,7 +266,12 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
my_off_t root;
uchar *kpos=keypos;
- tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey);
+ if (!(tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey)))
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
+ my_errno= HA_ERR_CRASHED;
+ DBUG_RETURN(-1);
+ }
root=_mi_dpos(info,nod_flag,kpos);
if (subkeys == -1)
{
@@ -302,6 +320,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (!nod_flag)
{
DBUG_PRINT("error",("Didn't find key"));
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED; /* This should newer happend */
goto err;
}
@@ -313,13 +332,10 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{ /* Found key */
uint tmp;
length=mi_getint(anc_buff);
- tmp=remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length,
- &next_block);
- if (tmp == 0)
- {
- DBUG_PRINT("exit",("Return: %d",0));
- DBUG_RETURN(0);
- }
+ if (!(tmp= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length,
+ &next_block)))
+ goto err;
+
length-= tmp;
mi_putint(anc_buff,length,nod_flag);
@@ -368,6 +384,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
my_afree((byte*) leaf_buff);
DBUG_PRINT("exit",("Return: %d",ret_value));
DBUG_RETURN(ret_value);
+
err:
my_afree((byte*) leaf_buff);
DBUG_PRINT("exit",("Error: %d",my_errno));
@@ -559,10 +576,10 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
/* remove key from anc_buff */
- s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
- anc_buff+anc_length,(my_off_t *) 0);
- if (!s_length)
+ if (!(s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
+ anc_buff+anc_length,(my_off_t *) 0)))
goto err;
+
anc_length-=s_length;
mi_putint(anc_buff,anc_length,key_reflength);
@@ -668,10 +685,10 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
mi_putint(buff,buff_length,nod_flag);
/* remove key from anc_buff */
- s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
- anc_buff+anc_length,(my_off_t *) 0);
- if (!s_length)
+ if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key,
+ anc_buff+anc_length,(my_off_t *) 0)))
goto err;
+
anc_length-=s_length;
mi_putint(anc_buff,anc_length,key_reflength);
@@ -731,6 +748,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff))
goto err;
DBUG_RETURN(anc_length <= (uint) keyinfo->block_length/2);
+
err:
DBUG_RETURN(-1);
} /* underflow */
@@ -768,6 +786,7 @@ static uint remove_key(MI_KEYDEF *keyinfo, uint nod_flag,
/* Calculate length of key */
if (!(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey))
DBUG_RETURN(0); /* Error */
+
if (next_block && nod_flag)
*next_block= _mi_kpos(nod_flag,keypos);
s_length=(int) (keypos-start);
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index 43783ca2d36..8de500a7351 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -149,7 +149,9 @@ static int write_dynamic_record(MI_INFO *info, const byte *record,
{
if (_mi_find_writepos(info,reclength,&filepos,&length))
goto err;
- if (_mi_write_part_record(info,filepos,length,info->s->state.dellink,
+ if (_mi_write_part_record(info,filepos,length,
+ (info->append_insert_at_end ?
+ HA_OFFSET_ERROR : info->s->state.dellink),
(byte**) &record,&reclength,&flag))
goto err;
} while (reclength);
@@ -171,7 +173,8 @@ static int _mi_find_writepos(MI_INFO *info,
ulong tmp;
DBUG_ENTER("_mi_find_writepos");
- if (info->s->state.dellink != HA_OFFSET_ERROR)
+ if (info->s->state.dellink != HA_OFFSET_ERROR &&
+ !info->append_insert_at_end)
{
/* Deleted blocks exists; Get last used block */
*filepos=info->s->state.dellink;
@@ -420,8 +423,9 @@ int _mi_write_part_record(MI_INFO *info,
else if (length-long_block < *reclength+4)
{ /* To short block */
if (next_filepos == HA_OFFSET_ERROR)
- next_filepos=info->s->state.dellink != HA_OFFSET_ERROR ?
- info->s->state.dellink : info->state->data_file_length;
+ next_filepos= (info->s->state.dellink != HA_OFFSET_ERROR &&
+ !info->append_insert_at_end ?
+ info->s->state.dellink : info->state->data_file_length);
if (*flag == 0) /* First block */
{
if (*reclength > MI_MAX_BLOCK_LENGTH)
@@ -768,11 +772,21 @@ uint _mi_rec_pack(MI_INFO *info, register byte *to, register const byte *from)
}
else if (type == FIELD_VARCHAR)
{
- uint tmp_length=uint2korr(from);
- store_key_length_inc(to,tmp_length);
- memcpy(to,from+2,tmp_length);
- to+=tmp_length;
- continue;
+ uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
+ uint tmp_length;
+ if (pack_length == 1)
+ {
+ tmp_length= (uint) *(uchar*) from;
+ *to++= *from;
+ }
+ else
+ {
+ tmp_length= uint2korr(from);
+ store_key_length_inc(to,tmp_length);
+ }
+ memcpy(to, from+pack_length,tmp_length);
+ to+= tmp_length;
+ continue;
}
else
{
@@ -878,9 +892,20 @@ my_bool _mi_rec_check(MI_INFO *info,const char *record, byte *rec_buff,
}
else if (type == FIELD_VARCHAR)
{
- uint tmp_length=uint2korr(record);
- to+=get_pack_length(tmp_length)+tmp_length;
- continue;
+ uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
+ uint tmp_length;
+ if (pack_length == 1)
+ {
+ tmp_length= (uint) *(uchar*) record;
+ to+= 1+ tmp_length;
+ continue;
+ }
+ else
+ {
+ tmp_length= uint2korr(record);
+ to+= get_pack_length(tmp_length)+tmp_length;
+ }
+ continue;
}
else
{
@@ -894,9 +919,7 @@ my_bool _mi_rec_check(MI_INFO *info,const char *record, byte *rec_buff,
}
}
else
- {
- to+=length;
- }
+ to+= length;
}
if (packed_length != (uint) (to - rec_buff) + test(info->s->calc_checksum) ||
(bit != 1 && (flag & ~(bit - 1))))
@@ -944,13 +967,27 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
{
if (type == FIELD_VARCHAR)
{
- get_key_length(length,from);
- if (length > rec_length-2)
- goto err;
- int2store(to,length);
- memcpy(to+2,from,length);
- from+=length;
- continue;
+ uint pack_length= HA_VARCHAR_PACKLENGTH(rec_length-1);
+ if (pack_length == 1)
+ {
+ length= (uint) *(uchar*) from;
+ if (length > rec_length-1)
+ goto err;
+ *to= *from++;
+ }
+ else
+ {
+ get_key_length(length, from);
+ if (length > rec_length-2)
+ goto err;
+ int2store(to,length);
+ }
+ if (from+length > from_end)
+ goto err;
+ memcpy(to+pack_length, from, length);
+ from+= length;
+ min_pack_length--;
+ continue;
}
if (flag & bit)
{
@@ -1018,15 +1055,17 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
if (min_pack_length > (uint) (from_end - from))
goto err;
min_pack_length-=rec_length;
- memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
+ memcpy(to, (byte*) from, (size_t) rec_length);
+ from+=rec_length;
}
}
if (info->s->calc_checksum)
from++;
if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1))))
DBUG_RETURN(found_length);
+
err:
- my_errno=HA_ERR_RECORD_DELETED;
+ my_errno= HA_ERR_WRONG_IN_RECORD;
DBUG_PRINT("error",("to_end: %lx -> %lx from_end: %lx -> %lx",
to,to_end,from,from_end));
DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length);
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index 1827aed98c3..7c0dd13b870 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "myisamdef.h"
-#ifdef HAVE_MMAP
+#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
@@ -186,7 +186,10 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (info->opt_flag & WRITE_CACHE_USED)
{
if ((error=flush_io_cache(&info->rec_cache)))
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
+ }
}
break;
case HA_EXTRA_NO_READCHECK:
@@ -241,7 +244,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
error=1; /* Not possibly if not lock */
break;
}
- if (share->state.key_map)
+ if (mi_is_any_key_active(share->state.key_map))
{
MI_KEYDEF *key=share->keyinfo;
uint i;
@@ -249,7 +252,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
{
if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
{
- share->state.key_map&= ~ ((ulonglong) 1 << i);
+ mi_clear_key_active(share->state.key_map, i);
info->update|= HA_STATE_CHANGED;
}
}
@@ -285,6 +288,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
{
error=my_errno;
share->changed=1;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
}
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
@@ -339,6 +343,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (error)
{
share->changed=1;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
}
}
diff --git a/myisam/mi_info.c b/myisam/mi_info.c
index cf63ef63618..bdece9c2ee3 100644
--- a/myisam/mi_info.c
+++ b/myisam/mi_info.c
@@ -105,3 +105,36 @@ int mi_status(MI_INFO *info, register MI_ISAMINFO *x, uint flag)
}
DBUG_RETURN(0);
}
+
+
+/*
+ Write a message to the error log.
+
+ SYNOPSIS
+ mi_report_error()
+ file_name Name of table file (e.g. index_file_name).
+ errcode Error number.
+
+ DESCRIPTION
+ This function supplies my_error() with a table name. Most error
+ messages need one. Since string arguments in error messages are limited
+ to 64 characters by convention, we ensure that in case of truncation,
+ that the end of the index file path is in the message. This contains
+ the most valuable information (the table name and the database name).
+
+ RETURN
+ void
+*/
+
+void mi_report_error(int errcode, const char *file_name)
+{
+ size_t lgt;
+ DBUG_ENTER("mi_report_error");
+ DBUG_PRINT("enter",("errcode %d, table '%s'", errcode, file_name));
+
+ if ((lgt= strlen(file_name)) > 64)
+ file_name+= lgt - 64;
+ my_error(errcode, MYF(ME_NOREFRESH), file_name);
+ DBUG_VOID_RETURN;
+}
+
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 9df22889b22..ae50900a190 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -34,10 +34,20 @@
static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record);
- /*
- ** Make a intern key from a record
- ** Ret: Length of key
- */
+/*
+ Make a intern key from a record
+
+ SYNOPSIS
+ _mi_make_key()
+ info MyiSAM handler
+ keynr key number
+ key Store created key here
+ record Record
+ filepos Position to record in the data file
+
+ RETURN
+ Length of key
+*/
uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
const byte *record, my_off_t filepos)
@@ -82,6 +92,19 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
length);
pos= (byte*) record+keyseg->start;
+ if (type == HA_KEYTYPE_BIT)
+ {
+ if (keyseg->bit_length)
+ {
+ uchar bits= get_rec_bits((uchar*) record + keyseg->bit_pos,
+ keyseg->bit_start, keyseg->bit_length);
+ *key++= bits;
+ length--;
+ }
+ memcpy((byte*) key, pos, length);
+ key+= length;
+ continue;
+ }
if (keyseg->flag & HA_SPACE_PACK)
{
end= pos + length;
@@ -102,10 +125,12 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
key+=char_length;
continue;
}
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
- uint tmp_length=uint2korr(pos);
- pos+=2; /* Skip VARCHAR length */
+ uint pack_length= keyseg->bit_start;
+ uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
+ uint2korr(pos));
+ pos+= pack_length; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length);
FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
@@ -161,7 +186,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
FIX_LENGTH(cs, pos, length, char_length);
memcpy((byte*) key, pos, char_length);
if (length > char_length)
- cs->cset->fill(cs, key+char_length, length-char_length, ' ');
+ cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
key+= length;
}
_mi_dpointer(info,key,filepos);
@@ -216,8 +241,11 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
if (!(*key++= (char) 1-*old++)) /* Copy null marker */
{
k_length-=length;
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+ {
k_length-=2; /* Skip length */
+ old+= 2;
+ }
continue; /* Found NULL */
}
}
@@ -244,7 +272,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
key+= char_length;
continue;
}
- else if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
/* Length of key-part used with mi_rkey() always 2 */
uint tmp_length=uint2korr(pos);
@@ -271,7 +299,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
FIX_LENGTH(cs, pos, length, char_length);
memcpy((byte*) key, pos, char_length);
if (length > char_length)
- cs->cset->fill(cs,key+char_length, length-char_length, ' ');
+ cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
key+= length;
k_length-=length;
}
@@ -344,6 +372,26 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
}
record[keyseg->null_pos]&= ~keyseg->null_bit;
}
+ if (keyseg->type == HA_KEYTYPE_BIT)
+ {
+ uint length= keyseg->length;
+
+ if (keyseg->bit_length)
+ {
+ uchar bits= *key++;
+ set_rec_bits(bits, record + keyseg->bit_pos, keyseg->bit_start,
+ keyseg->bit_length);
+ length--;
+ }
+ else
+ {
+ clr_rec_bits(record + keyseg->bit_pos, keyseg->bit_start,
+ keyseg->bit_length);
+ }
+ memcpy(record + keyseg->start, (byte*) key, length);
+ key+= length;
+ continue;
+ }
if (keyseg->flag & HA_SPACE_PACK)
{
uint length;
@@ -367,7 +415,7 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
continue;
}
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint length;
get_key_length(length,key);
@@ -375,7 +423,13 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
if (length > keyseg->length || key+length > key_end)
goto err;
#endif
- memcpy(record+keyseg->start,(byte*) key, length);
+ /* Store key length */
+ if (keyseg->bit_start == 1)
+ *(uchar*) (record+keyseg->start)= (uchar) length;
+ else
+ int2store(record+keyseg->start, length);
+ /* And key data */
+ memcpy(record+keyseg->start + keyseg->bit_start, (byte*) key, length);
key+= length;
}
else if (keyseg->flag & HA_BLOB_PART)
@@ -437,6 +491,7 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
{ /* Read only key */
if (_mi_put_key_in_record(info,(uint) info->lastinx,buf))
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return -1;
}
diff --git a/myisam/mi_keycache.c b/myisam/mi_keycache.c
index 99a2fd6db15..fb13f3703a2 100644
--- a/myisam/mi_keycache.c
+++ b/myisam/mi_keycache.c
@@ -79,6 +79,7 @@ int mi_assign_to_key_cache(MI_INFO *info,
if (flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE))
{
error= my_errno;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Mark that table must be checked */
}
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index 66950f62321..8d48c5242e5 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -66,6 +66,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
share->kfile,FLUSH_KEEP))
{
error=my_errno;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Mark that table must be checked */
}
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
@@ -73,6 +74,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
if (end_io_cache(&info->rec_cache))
{
error=my_errno;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
}
@@ -98,7 +100,10 @@ int mi_lock_database(MI_INFO *info, int lock_type)
else
share->not_flushed=1;
if (error)
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
+ }
}
if (info->lock_type != F_EXTRA_LCK)
{
@@ -233,13 +238,24 @@ int mi_lock_database(MI_INFO *info, int lock_type)
The following functions are called by thr_lock() in threaded applications
****************************************************************************/
-void mi_get_status(void* param)
+/*
+ Create a copy of the current status for the table
+
+ SYNOPSIS
+ mi_get_status()
+ param Pointer to Myisam handler
+ concurrent_insert Set to 1 if we are going to do concurrent inserts
+ (THR_WRITE_CONCURRENT_INSERT was used)
+*/
+
+void mi_get_status(void* param, int concurrent_insert)
{
MI_INFO *info=(MI_INFO*) param;
DBUG_ENTER("mi_get_status");
- DBUG_PRINT("info",("key_file: %ld data_file: %ld",
+ DBUG_PRINT("info",("key_file: %ld data_file: %ld concurrent_insert: %d",
(long) info->s->state.state.key_file_length,
- (long) info->s->state.state.data_file_length));
+ (long) info->s->state.state.data_file_length,
+ concurrent_insert));
#ifndef DBUG_OFF
if (info->state->key_file_length > info->s->state.state.key_file_length ||
info->state->data_file_length > info->s->state.state.data_file_length)
@@ -249,9 +265,11 @@ void mi_get_status(void* param)
#endif
info->save_state=info->s->state.state;
info->state= &info->save_state;
+ info->append_insert_at_end= concurrent_insert;
DBUG_VOID_RETURN;
}
+
void mi_update_status(void* param)
{
MI_INFO *info=(MI_INFO*) param;
@@ -276,6 +294,7 @@ void mi_update_status(void* param)
info->s->state.state= *info->state;
info->state= &info->s->state.state;
}
+ info->append_insert_at_end= 0;
/*
We have to flush the write cache here as other threads may start
@@ -285,6 +304,7 @@ void mi_update_status(void* param)
{
if (end_io_cache(&info->rec_cache))
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
info->opt_flag&= ~WRITE_CACHE_USED;
@@ -301,20 +321,37 @@ void mi_copy_status(void* to,void *from)
Check if should allow concurrent inserts
IMPLEMENTATION
- Don't allow concurrent inserts if we have a hole in the table.
+ Allow concurrent inserts if we don't have a hole in the table or
+ if there is no active write lock and there is active read locks and
+ myisam_concurrent_insert == 2. In this last case the new
+ row('s) are inserted at end of file instead of filling up the hole.
+
+ The last case is to allow one to inserts into a heavily read-used table
+ even if there is holes.
NOTES
- Rtree indexes are disabled in mi_open()
+ If there is a an rtree indexes in the table, concurrent inserts are
+ disabled in mi_open()
RETURN
0 ok to use concurrent inserts
1 not ok
*/
-my_bool mi_check_status(void* param)
+my_bool mi_check_status(void *param)
{
MI_INFO *info=(MI_INFO*) param;
- return (my_bool) (info->s->state.dellink != HA_OFFSET_ERROR);
+ /*
+ The test for w_locks == 1 is here because this thread has already done an
+ external lock (in other words: w_locks == 1 means no other threads has
+ a write lock)
+ */
+ DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u",
+ (long) info->s->state.dellink, (uint) info->s->r_locks,
+ (uint) info->s->w_locks));
+ return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
+ (myisam_concurrent_insert == 2 && info->s->r_locks &&
+ info->s->w_locks == 1));
}
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index a5b303f86d4..82663e0c318 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -106,6 +106,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share_buff.state.key_del=key_del;
share_buff.key_cache= multi_key_cache_search(name_buff, strlen(name_buff));
+ DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open",
+ if (strstr(name, "/t1"))
+ {
+ my_errno= HA_ERR_CRASHED;
+ goto err;
+ });
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
{
if ((errno != EROFS && errno != EACCES) ||
@@ -186,14 +192,14 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
}
share->state_diff_length=len-MI_STATE_INFO_SIZE;
- mi_state_info_read(disk_cache, &share->state);
+ mi_state_info_read((uchar*) disk_cache, &share->state);
len= mi_uint2korr(share->state.header.base_info_length);
if (len != MI_BASE_INFO_SIZE)
{
DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
len,MI_BASE_INFO_SIZE))
}
- disk_pos=my_n_base_info_read(disk_cache+base_pos, &share->base);
+ disk_pos=my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base);
share->state.state_length=base_pos;
if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
@@ -302,6 +308,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
HA_KEYSEG *pos=share->keyparts;
for (i=0 ; i < keys ; i++)
{
+ share->keyinfo[i].share= share;
disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
end_pos);
@@ -313,7 +320,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
{
disk_pos=mi_keyseg_read(disk_pos, pos);
- if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
+ if (pos->type == HA_KEYTYPE_TEXT ||
+ pos->type == HA_KEYTYPE_VARTEXT1 ||
+ pos->type == HA_KEYTYPE_VARTEXT2)
{
if (!pos->language)
pos->charset=default_charset_info;
@@ -388,7 +397,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
{
disk_pos=mi_keyseg_read(disk_pos, pos);
- if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
+ if (pos->type == HA_KEYTYPE_TEXT ||
+ pos->type == HA_KEYTYPE_VARTEXT1 ||
+ pos->type == HA_KEYTYPE_VARTEXT2)
{
if (!pos->language)
pos->charset=default_charset_info;
@@ -596,6 +607,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
err:
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
+ if ((save_errno == HA_ERR_CRASHED) ||
+ (save_errno == HA_ERR_CRASHED_ON_USAGE) ||
+ (save_errno == HA_ERR_CRASHED_ON_REPAIR))
+ mi_report_error(save_errno, name);
switch (errpos) {
case 6:
my_free((gptr) m_info,MYF(0));
@@ -848,7 +863,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
}
-char *mi_state_info_read(char *ptr, MI_STATE_INFO *state)
+char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state)
{
uint i,keys,key_parts,key_blocks;
memcpy_fixed(&state->header,ptr, sizeof(state->header));
@@ -914,7 +929,7 @@ uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead)
}
else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
return (MY_FILE_ERROR);
- mi_state_info_read(buff, state);
+ mi_state_info_read((uchar*) buff, state);
}
return 0;
}
@@ -959,7 +974,7 @@ uint mi_base_info_write(File file, MI_BASE_INFO *base)
}
-char *my_n_base_info_read(char *ptr, MI_BASE_INFO *base)
+char *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base)
{
base->keystart = mi_sizekorr(ptr); ptr +=8;
base->max_data_file_length = mi_sizekorr(ptr); ptr +=8;
@@ -1042,18 +1057,21 @@ int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
{
uchar buff[HA_KEYSEG_SIZE];
uchar *ptr=buff;
-
- *ptr++ =keyseg->type;
- *ptr++ =keyseg->language;
- *ptr++ =keyseg->null_bit;
- *ptr++ =keyseg->bit_start;
- *ptr++ =keyseg->bit_end;
- *ptr++ =0; /* Not used */
+ ulong pos;
+
+ *ptr++= keyseg->type;
+ *ptr++= keyseg->language;
+ *ptr++= keyseg->null_bit;
+ *ptr++= keyseg->bit_start;
+ *ptr++= keyseg->bit_end;
+ *ptr++= keyseg->bit_length;
mi_int2store(ptr,keyseg->flag); ptr+=2;
mi_int2store(ptr,keyseg->length); ptr+=2;
mi_int4store(ptr,keyseg->start); ptr+=4;
- mi_int4store(ptr,keyseg->null_pos); ptr+=4;
-
+ pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
+ mi_int4store(ptr, pos);
+ ptr+=4;
+
return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
}
@@ -1065,12 +1083,19 @@ char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg)
keyseg->null_bit = *ptr++;
keyseg->bit_start = *ptr++;
keyseg->bit_end = *ptr++;
- ptr++;
+ keyseg->bit_length = *ptr++;
keyseg->flag = mi_uint2korr(ptr); ptr +=2;
keyseg->length = mi_uint2korr(ptr); ptr +=2;
keyseg->start = mi_uint4korr(ptr); ptr +=4;
keyseg->null_pos = mi_uint4korr(ptr); ptr +=4;
keyseg->charset=0; /* Will be filled in later */
+ if (keyseg->null_bit)
+ keyseg->bit_pos= (uint16)(keyseg->null_pos + (keyseg->null_bit == 7));
+ else
+ {
+ keyseg->bit_pos= (uint16)keyseg->null_pos;
+ keyseg->null_pos= 0;
+ }
return ptr;
}
@@ -1179,7 +1204,7 @@ int mi_disable_indexes(MI_INFO *info)
{
MYISAM_SHARE *share= info->s;
- share->state.key_map= 0;
+ mi_clear_all_keys_active(share->state.key_map);
return 0;
}
@@ -1210,9 +1235,12 @@ int mi_enable_indexes(MI_INFO *info)
if (share->state.state.data_file_length ||
(share->state.state.key_file_length != share->base.keystart))
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
error= HA_ERR_CRASHED;
+ }
else
- share->state.key_map= ((ulonglong) 1L << share->base.keys) - 1;
+ mi_set_all_keys_active(share->state.key_map, share->base.keys);
return error;
}
@@ -1237,6 +1265,6 @@ int mi_indexes_are_disabled(MI_INFO *info)
{
MYISAM_SHARE *share= info->s;
- return (! share->state.key_map && share->base.keys);
+ return (! mi_is_any_key_active(share->state.key_map) && share->base.keys);
}
diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c
index 322420b71db..e242e9d506d 100644
--- a/myisam/mi_packrec.c
+++ b/myisam/mi_packrec.c
@@ -91,8 +91,10 @@ static void uf_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
uchar *to,uchar *end);
static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end);
-static void uf_varchar(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
- uchar *to, uchar *end);
+static void uf_varchar1(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
+ uchar *to, uchar *end);
+static void uf_varchar2(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
+ uchar *to, uchar *end);
static void decode_bytes(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
uchar *to,uchar *end);
static uint decode_pos(MI_BIT_BUFF *bit_buff,MI_DECODE_TREE *decode_tree);
@@ -415,8 +417,19 @@ static uint find_longest_bitstream(uint16 *table, uint16 *end)
}
- /* Read record from datafile */
- /* Returns length of packed record, -1 if error */
+/*
+ Read record from datafile.
+
+ SYNOPSIS
+ _mi_read_pack_record()
+ info A pointer to MI_INFO.
+ filepos File offset of the record.
+ buf RETURN The buffer to receive the record.
+
+ RETURN
+ 0 on success
+ HA_ERR_WRONG_IN_RECORD or -1 on error
+*/
int _mi_read_pack_record(MI_INFO *info, my_off_t filepos, byte *buf)
{
@@ -516,14 +529,16 @@ static void (*get_unpack_function(MI_COLUMNDEF *rec))
case FIELD_BLOB:
return &uf_blob;
case FIELD_VARCHAR:
- return &uf_varchar;
+ if (rec->length <= 256) /* 255 + 1 byte length */
+ return &uf_varchar1;
+ return &uf_varchar2;
case FIELD_LAST:
default:
return 0; /* This should never happend */
}
}
- /* De different functions to unpack a field */
+ /* The different functions to unpack a field */
static void uf_zerofill_skip_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end)
@@ -767,7 +782,22 @@ static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
}
}
-static void uf_varchar(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
+
+static void uf_varchar1(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
+ uchar *to, uchar *end __attribute__((unused)))
+{
+ if (get_bit(bit_buff))
+ to[0]= 0; /* Zero lengths */
+ else
+ {
+ ulong length=get_bits(bit_buff,rec->space_length_bits);
+ *to= (uchar) length;
+ decode_bytes(rec,bit_buff,to+1,to+1+length);
+ }
+}
+
+
+static void uf_varchar2(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end __attribute__((unused)))
{
if (get_bit(bit_buff))
@@ -1137,11 +1167,12 @@ static uint max_bit(register uint value)
/*****************************************************************************
Some redefined functions to handle files when we are using memmap
*****************************************************************************/
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
#ifdef HAVE_MMAP
-#include <sys/mman.h>
-
static int _mi_read_mempack_record(MI_INFO *info,my_off_t filepos,byte *buf);
static int _mi_read_rnd_mempack_record(MI_INFO*, byte *,my_off_t, my_bool);
@@ -1167,7 +1198,7 @@ my_bool _mi_memmap_file(MI_INFO *info)
DBUG_RETURN(0);
}
file_map=(byte*)
- mmap(0,share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ,
+ my_mmap(0,(size_t)(share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN),PROT_READ,
MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
if (file_map == (byte*) MAP_FAILED)
{
@@ -1186,7 +1217,7 @@ my_bool _mi_memmap_file(MI_INFO *info)
void _mi_unmap_file(MI_INFO *info)
{
- VOID(munmap((caddr_t) info->s->file_map,
+ VOID(my_munmap(info->s->file_map,
(size_t) info->s->state.state.data_file_length+
MEMMAP_EXTRA_MARGIN));
}
diff --git a/myisam/mi_page.c b/myisam/mi_page.c
index 16713c87e10..5240c063fba 100644
--- a/myisam/mi_page.c
+++ b/myisam/mi_page.c
@@ -40,6 +40,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
{
DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno));
info->last_keypage=HA_OFFSET_ERROR;
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
@@ -51,6 +52,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
(ulong) page, page_size));
DBUG_DUMP("page", (char*) tmp, keyinfo->block_length);
info->last_keypage = HA_OFFSET_ERROR;
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno = HA_ERR_CRASHED;
tmp = 0;
}
diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c
index 317ab4ad7fe..d63399b519d 100644
--- a/myisam/mi_preload.c
+++ b/myisam/mi_preload.c
@@ -51,7 +51,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
my_off_t pos= share->base.keystart;
DBUG_ENTER("mi_preload");
- if (!keys || !key_map || key_file_length == pos)
+ if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos)
DBUG_RETURN(0);
block_length= keyinfo[0].block_length;
diff --git a/myisam/mi_range.c b/myisam/mi_range.c
index 1e0fd42334e..e78f3b11625 100644
--- a/myisam/mi_range.c
+++ b/myisam/mi_range.c
@@ -172,9 +172,9 @@ static double _mi_search_pos(register MI_INFO *info,
if (flag == MI_FOUND_WRONG_KEY)
DBUG_RETURN(-1); /* error */
/*
- ** Didn't found match. keypos points at next (bigger) key
- * Try to find a smaller, better matching key.
- ** Matches keynr + [0-1]
+ Didn't found match. keypos points at next (bigger) key
+ Try to find a smaller, better matching key.
+ Matches keynr + [0-1]
*/
if (flag > 0 && ! nod_flag)
offset= 1.0;
@@ -185,8 +185,8 @@ static double _mi_search_pos(register MI_INFO *info,
else
{
/*
- ** Found match. Keypos points at the start of the found key
- ** Matches keynr+1
+ Found match. Keypos points at the start of the found key
+ Matches keynr+1
*/
offset=1.0; /* Matches keynr+1 */
if ((nextflag & SEARCH_FIND) && nod_flag &&
@@ -194,8 +194,8 @@ static double _mi_search_pos(register MI_INFO *info,
key_len != USE_WHOLE_KEY))
{
/*
- ** There may be identical keys in the tree. Try to match on of those.
- ** Matches keynr + [0-1]
+ There may be identical keys in the tree. Try to match on of those.
+ Matches keynr + [0-1]
*/
if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
_mi_kpos(nod_flag,keypos))) < 0)
@@ -213,7 +213,8 @@ err:
/* Get keynummer of current key and max number of keys in nod */
-static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uchar *keypos, uint *ret_max_key)
+static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
+ uchar *keypos, uint *ret_max_key)
{
uint nod_flag,keynr,max_key;
uchar t_buff[MI_MAX_KEY_BUFF],*end;
@@ -222,7 +223,7 @@ static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, u
nod_flag=mi_test_if_nod(page);
page+=2+nod_flag;
- if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY| HA_BINARY_PACK_KEY)))
+ if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
{
*ret_max_key= (uint) (end-page)/(keyinfo->keylength+nod_flag);
return (uint) (keypos-page)/(keyinfo->keylength+nod_flag);
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index 12db00337ee..635a7eb2c48 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -78,6 +78,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
case HA_KEY_ALG_RTREE:
if (rtree_find_first(info,inx,key_buff,use_key_length,nextflag) < 0)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
goto err;
}
diff --git a/myisam/mi_rsame.c b/myisam/mi_rsame.c
index 56c8d1226ca..321097744b9 100644
--- a/myisam/mi_rsame.c
+++ b/myisam/mi_rsame.c
@@ -30,7 +30,7 @@ int mi_rsame(MI_INFO *info, byte *record, int inx)
{
DBUG_ENTER("mi_rsame");
- if (inx != -1 && ! (((ulonglong) 1 << inx) & info->s->state.key_map))
+ if (inx != -1 && ! mi_is_key_active(info->s->state.key_map, inx))
{
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
}
diff --git a/myisam/mi_rsamepos.c b/myisam/mi_rsamepos.c
index a1d96fb7104..35cdd41e297 100644
--- a/myisam/mi_rsamepos.c
+++ b/myisam/mi_rsamepos.c
@@ -32,7 +32,7 @@ int mi_rsame_with_pos(MI_INFO *info, byte *record, int inx, my_off_t filepos)
{
DBUG_ENTER("mi_rsame_with_pos");
- if (inx < -1 || ! (((ulonglong) 1 << inx) & info->s->state.key_map))
+ if (inx < -1 || ! mi_is_key_active(info->s->state.key_map, inx))
{
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
}
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index 6ed245d9715..b7360dba7f3 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -29,7 +29,7 @@ int _mi_check_index(MI_INFO *info, int inx)
{
if (inx == -1) /* Use last index */
inx=info->lastinx;
- if (inx < 0 || ! (((ulonglong) 1 << inx) & info->s->state.key_map))
+ if (inx < 0 || ! mi_is_key_active(info->s->state.key_map, inx))
{
my_errno=HA_ERR_WRONG_INDEX;
return -1;
@@ -159,6 +159,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_PRINT("exit",("found key at %lu",(ulong) info->lastpos));
DBUG_RETURN(0);
+
err:
DBUG_PRINT("exit",("Error: %d",my_errno));
info->lastpos= HA_OFFSET_ERROR;
@@ -256,6 +257,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
if (length == 0 || page > end)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p",
length, page, end));
@@ -395,7 +397,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (!(*from++))
continue;
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
get_key_length(l,from);
}
@@ -411,6 +413,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (page > end)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p",
length, page, end));
@@ -461,7 +464,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (len < cmplen)
{
if ((keyinfo->seg->type != HA_KEYTYPE_TEXT &&
- keyinfo->seg->type != HA_KEYTYPE_VARTEXT))
+ keyinfo->seg->type != HA_KEYTYPE_VARTEXT1 &&
+ keyinfo->seg->type != HA_KEYTYPE_VARTEXT2))
my_flag= -1;
else
{
@@ -795,6 +799,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
{
if (length > (uint) keyseg->length)
{
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Error */
}
@@ -810,6 +815,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
("Found too long null packed key: %u of %u at %p",
length, keyseg->length, *page_pos));
DBUG_DUMP("key",(char*) *page_pos,16);
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0;
}
@@ -866,6 +872,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
DBUG_PRINT("error",("Found too long packed key: %u of %u at %p",
length, keyseg->length, *page_pos));
DBUG_DUMP("key",(char*) *page_pos,16);
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Error */
}
@@ -879,7 +886,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
continue;
}
if (keyseg->flag &
- (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
uchar *tmp=page;
get_key_length(length,tmp);
@@ -921,6 +928,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
DBUG_PRINT("error",("Found too long binary packed key: %u of %u at %p",
length, keyinfo->maxlength, *page_pos));
DBUG_DUMP("key",(char*) *page_pos,16);
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Wrong key */
}
@@ -944,7 +952,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if (!(*key++ = *from++))
continue; /* Null part */
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
/* Get length of dynamic length key part */
if (from == from_end) { from=page; from_end=page_end; }
@@ -982,6 +990,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if (from_end != page_end)
{
DBUG_PRINT("error",("Error when unpacking key"));
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Error */
}
@@ -1016,6 +1025,7 @@ uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
if (*return_key_length == 0)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
@@ -1053,6 +1063,7 @@ static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
if (*return_key_length == 0)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1);
}
@@ -1093,6 +1104,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
if (*return_key_length == 0)
{
DBUG_PRINT("error",("Couldn't find last key: page: %p", page));
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
@@ -1119,7 +1131,7 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
continue;
- if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint length;
get_key_length(length,key);
@@ -1151,7 +1163,7 @@ uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
continue;
- if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint length;
get_key_length(length,key);
@@ -1283,8 +1295,10 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
page=info->buff+2+nod_flag;
} while ((pos=_mi_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
- info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
- info->lastkey);
+ if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
+ info->lastkey)))
+ DBUG_RETURN(-1); /* Crashed */
+
info->int_keypos=page; info->int_maxpos=info->buff+mi_getint(info->buff)-1;
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
@@ -1419,7 +1433,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
sort_order=0;
if ((keyinfo->flag & HA_FULLTEXT) &&
((keyseg->type == HA_KEYTYPE_TEXT) ||
- (keyseg->type == HA_KEYTYPE_VARTEXT)) &&
+ (keyseg->type == HA_KEYTYPE_VARTEXT1) ||
+ (keyseg->type == HA_KEYTYPE_VARTEXT2)) &&
!use_strnxfrm(keyseg->charset))
sort_order=keyseg->charset->sort_order;
diff --git a/myisam/mi_static.c b/myisam/mi_static.c
index 9725c120f44..fc585eb5543 100644
--- a/myisam/mi_static.c
+++ b/myisam/mi_static.c
@@ -31,14 +31,13 @@ uchar NEAR myisam_pack_file_magic[]=
my_string myisam_log_filename=(char*) "myisam.log";
File myisam_log_file= -1;
uint myisam_quick_table_bits=9;
-uint myisam_block_size=MI_KEY_BLOCK_LENGTH; /* Best by test */
+ulong myisam_block_size= MI_KEY_BLOCK_LENGTH; /* Best by test */
my_bool myisam_flush=0, myisam_delay_key_write=0, myisam_single_user=0;
#if defined(THREAD) && !defined(DONT_USE_RW_LOCKS)
-my_bool myisam_concurrent_insert=1;
+ulong myisam_concurrent_insert= 2;
#else
-my_bool myisam_concurrent_insert=0;
+ulong myisam_concurrent_insert= 0;
#endif
-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_statrec.c b/myisam/mi_statrec.c
index 8f5cde45e24..42352f63c66 100644
--- a/myisam/mi_statrec.c
+++ b/myisam/mi_statrec.c
@@ -23,7 +23,8 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
{
uchar temp[8]; /* max pointer length */
- if (info->s->state.dellink != HA_OFFSET_ERROR)
+ if (info->s->state.dellink != HA_OFFSET_ERROR &&
+ !info->append_insert_at_end)
{
my_off_t filepos=info->s->state.dellink;
info->rec_cache.seek_not_done=1; /* We have done a seek */
diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c
index 77c4d3dfbad..5727c699469 100644
--- a/myisam/mi_test1.c
+++ b/myisam/mi_test1.c
@@ -75,11 +75,11 @@ static int run_test(const char *filename)
recinfo[1].length= (key_field == FIELD_BLOB ? 4+mi_portable_sizeof_char_ptr :
key_length);
if (key_field == FIELD_VARCHAR)
- recinfo[1].length+=2;
+ recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);;
recinfo[2].type=extra_field;
recinfo[2].length= (extra_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr : 24);
if (extra_field == FIELD_VARCHAR)
- recinfo[2].length+=2;
+ recinfo[2].length+= HA_VARCHAR_PACKLENGTH(recinfo[2].length);
if (opt_unique)
{
recinfo[3].type=FIELD_CHECK;
@@ -88,6 +88,9 @@ static int run_test(const char *filename)
rec_length=recinfo[0].length+recinfo[1].length+recinfo[2].length+
recinfo[3].length;
+ if (key_type == HA_KEYTYPE_VARTEXT1 &&
+ key_length > 255)
+ key_type= HA_KEYTYPE_VARTEXT2;
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
@@ -134,7 +137,7 @@ static int run_test(const char *filename)
uniqueseg[1].flag|= HA_BLOB_PART;
}
else if (extra_field == FIELD_VARCHAR)
- uniqueseg[1].flag|= HA_VAR_LENGTH;
+ uniqueseg[1].flag|= HA_VAR_LENGTH_PART;
}
else
uniques=0;
@@ -330,7 +333,8 @@ static void create_key_part(char *key,uint rownr)
{
sprintf(key,"%*d",keyinfo[0].seg[0].length,rownr);
}
- else if (keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT)
+ else if (keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT1 ||
+ keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT2)
{ /* Alpha record */
/* Create a key that may be easily packed */
bfill(key,keyinfo[0].seg[0].length,rownr < 10 ? 'A' : 'B');
@@ -372,7 +376,7 @@ static void create_key(char *key,uint rownr)
}
*key++=0;
}
- if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint tmp;
create_key_part(key+2,rownr);
@@ -410,11 +414,14 @@ static void create_record(char *record,uint rownr)
}
else if (recinfo[1].type == FIELD_VARCHAR)
{
- uint tmp;
- create_key_part(pos+2,rownr);
- tmp=strlen(pos+2);
- int2store(pos,tmp);
- pos+=recinfo[1].length;
+ uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
+ create_key_part(pos+pack_length,rownr);
+ tmp= strlen(pos+pack_length);
+ if (pack_length == 1)
+ *(uchar*) pos= (uchar) tmp;
+ else
+ int2store(pos,tmp);
+ pos+= recinfo[1].length;
}
else
{
@@ -434,10 +441,13 @@ static void create_record(char *record,uint rownr)
}
else if (recinfo[2].type == FIELD_VARCHAR)
{
- uint tmp;
- sprintf(pos+2,"... row: %d", rownr);
- tmp=strlen(pos+2);
- int2store(pos,tmp);
+ uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
+ sprintf(pos+pack_length, "... row: %d", rownr);
+ tmp= strlen(pos+pack_length);
+ if (pack_length == 1)
+ *(uchar*) pos= (uchar) tmp;
+ else
+ int2store(pos,tmp);
}
else
{
@@ -461,19 +471,25 @@ static void update_record(char *record)
ptr=blob_key;
memcpy_fixed(pos+4,&ptr,sizeof(char*)); /* Store pointer to new key */
if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
- my_casedn(default_charset_info,blob_key,length);
+ default_charset_info->cset->casedn(default_charset_info,
+ blob_key, length, blob_key, length);
pos+=recinfo[1].length;
}
else if (recinfo[1].type == FIELD_VARCHAR)
{
- uint length=uint2korr(pos);
- my_casedn(default_charset_info,pos+2,length);
+ uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
+ uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos);
+ default_charset_info->cset->casedn(default_charset_info,
+ pos + pack_length, length,
+ pos + pack_length, length);
pos+=recinfo[1].length;
}
else
{
if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
- my_casedn(default_charset_info,pos,keyinfo[0].seg[0].length);
+ default_charset_info->cset->casedn(default_charset_info,
+ pos, keyinfo[0].seg[0].length,
+ pos, keyinfo[0].seg[0].length);
pos+=recinfo[1].length;
}
@@ -493,10 +509,14 @@ static void update_record(char *record)
else if (recinfo[2].type == FIELD_VARCHAR)
{
/* Second field is longer than 10 characters */
- uint length=uint2korr(pos);
- bfill(pos+2+length,recinfo[2].length-length-2,'.');
- length=recinfo[2].length-2;
- int2store(pos,length);
+ uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
+ uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos);
+ bfill(pos+pack_length+length,recinfo[2].length-length-pack_length,'.');
+ length=recinfo[2].length-pack_length;
+ if (pack_length == 1)
+ *(uchar*) pos= (uchar) length;
+ else
+ int2store(pos,length);
}
else
{
@@ -519,12 +539,12 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"insert_rows", 'i', "Undocumented", (gptr*) &insert_count,
(gptr*) &insert_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0},
- {"key_alpha", 'a', "Undocumented",
+ {"key_alpha", 'a', "Use a key of type HA_KEYTYPE_TEXT",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_binary_pack", 'B', "Undocumented",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_blob", 'b', "Undocumented",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_cache", 'K', "Undocumented", (gptr*) &key_cacheing,
(gptr*) &key_cacheing, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_length", 'k', "Undocumented", (gptr*) &key_length, (gptr*) &key_length,
@@ -535,9 +555,9 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_space_pack", 'p', "Undocumented",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"key_varchar", 'w', "Undocumented",
+ {"key_varchar", 'w', "Test VARCHAR keys",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"null_fields", 'N', "Undocumented",
+ {"null_fields", 'N', "Define fields with NULL",
(gptr*) &null_fields, (gptr*) &null_fields, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"row_fixed_size", 'S', "Undocumented",
@@ -604,7 +624,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
key_field=FIELD_BLOB; /* blob key */
extra_field= FIELD_BLOB;
pack_seg|= HA_BLOB_PART;
- key_type= HA_KEYTYPE_VARTEXT;
+ key_type= HA_KEYTYPE_VARTEXT1;
break;
case 'k':
if (key_length < 4 || key_length > MI_MAX_KEY_LENGTH)
@@ -616,11 +636,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'w':
key_field=FIELD_VARCHAR; /* varchar keys */
extra_field= FIELD_VARCHAR;
- key_type= HA_KEYTYPE_VARTEXT;
- pack_seg|= HA_VAR_LENGTH;
+ key_type= HA_KEYTYPE_VARTEXT1;
+ pack_seg|= HA_VAR_LENGTH_PART;
create_flag|= HA_PACK_RECORD;
break;
- case 'K': /* Use key cacheing */
+ case 'K': /* Use key cacheing */
key_cacheing=1;
break;
case 'V':
diff --git a/myisam/mi_test3.c b/myisam/mi_test3.c
index 27d23317b5c..be4277cc65c 100644
--- a/myisam/mi_test3.c
+++ b/myisam/mi_test3.c
@@ -67,6 +67,7 @@ int main(int argc,char **argv)
bzero((char*) keyinfo,sizeof(keyinfo));
bzero((char*) recinfo,sizeof(recinfo));
+ bzero((char*) keyseg,sizeof(keyseg));
keyinfo[0].seg= &keyseg[0][0];
keyinfo[0].seg[0].start=0;
keyinfo[0].seg[0].length=8;
diff --git a/myisam/mi_test_all.res b/myisam/mi_test_all.res
index 94355bf1aa2..16b517d3f76 100644
--- a/myisam/mi_test_all.res
+++ b/myisam/mi_test_all.res
@@ -1,3 +1,6 @@
+myisamchk: MyISAM file test1
+myisamchk: warning: Size of indexfile is: 1024 Should be: 2048
+MyISAM-table 'test1' is usable but should be fixed
mi_test2 -s -L -K -R1 -m2000 ; Should give error 135
Error: 135 in write at record: 1105
got error: 135 when using MyISAM-database
@@ -5,46 +8,46 @@ myisamchk: MyISAM file test2
myisamchk: warning: Datafile is almost full, 65532 of 65534 used
MyISAM-table 'test2' is usable but should be fixed
Commands Used count Errors Recover errors
-open 17 0 0
-write 850 0 0
-update 85 0 0
-delete 850 0 0
-close 17 0 0
-extra 102 0 0
-Total 1921 0 0
+open 1 0 0
+write 50 0 0
+update 5 0 0
+delete 50 0 0
+close 1 0 0
+extra 6 0 0
+Total 113 0 0
Commands Used count Errors Recover errors
-open 18 0 0
-write 900 0 0
-update 90 0 0
-delete 900 0 0
-close 18 0 0
-extra 108 0 0
-Total 2034 0 0
+open 2 0 0
+write 100 0 0
+update 10 0 0
+delete 100 0 0
+close 2 0 0
+extra 12 0 0
+Total 226 0 0
-real 0m1.054s
-user 0m0.410s
-sys 0m0.640s
+real 0m0.791s
+user 0m0.137s
+sys 0m0.117s
-real 0m1.077s
-user 0m0.550s
-sys 0m0.530s
+real 0m0.659s
+user 0m0.252s
+sys 0m0.102s
-real 0m1.100s
-user 0m0.420s
-sys 0m0.680s
+real 0m0.571s
+user 0m0.188s
+sys 0m0.098s
-real 0m0.783s
-user 0m0.590s
-sys 0m0.200s
+real 0m1.111s
+user 0m0.236s
+sys 0m0.037s
-real 0m0.764s
-user 0m0.560s
-sys 0m0.210s
+real 0m0.621s
+user 0m0.242s
+sys 0m0.022s
-real 0m0.699s
-user 0m0.570s
-sys 0m0.130s
+real 0m0.698s
+user 0m0.248s
+sys 0m0.021s
-real 0m0.991s
-user 0m0.630s
-sys 0m0.350s
+real 0m0.683s
+user 0m0.265s
+sys 0m0.079s
diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c
index ad685f4cbdc..34f5f595f30 100644
--- a/myisam/mi_unique.c
+++ b/myisam/mi_unique.c
@@ -64,7 +64,12 @@ my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, byte *record,
}
-/* Calculate a hash for a row */
+/*
+ Calculate a hash for a row
+
+ TODO
+ Add support for bit fields
+*/
ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
{
@@ -93,10 +98,12 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
}
}
pos= record+keyseg->start;
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
- uint tmp_length=uint2korr(pos);
- pos+=2; /* Skip VARCHAR length */
+ uint pack_length= keyseg->bit_start;
+ uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
+ uint2korr(pos));
+ pos+= pack_length; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length);
}
else if (keyseg->flag & HA_BLOB_PART)
@@ -107,7 +114,8 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
length=tmp_length; /* The whole blob */
}
end= pos+length;
- if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
+ if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
+ type == HA_KEYTYPE_VARTEXT2)
{
keyseg->charset->coll->hash_sort(keyseg->charset,
(const uchar*) pos, length, &seed1,
@@ -123,9 +131,17 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
return crc;
}
- /*
- Returns 0 if both rows have equal unique value
- */
+
+/*
+ compare unique key for two rows
+
+ TODO
+ Add support for bit fields
+
+ RETURN
+ 0 if both rows have equal unique value
+ # Rows are different
+*/
int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
my_bool null_are_equal)
@@ -136,7 +152,8 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
{
enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
- uint length=keyseg->length;
+ uint a_length, b_length;
+ a_length= b_length= keyseg->length;
/* If part is NULL it's regarded as different */
if (keyseg->null_bit)
@@ -154,43 +171,59 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
}
pos_a= a+keyseg->start;
pos_b= b+keyseg->start;
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
- uint tmp_length=uint2korr(pos_a);
- if (tmp_length != uint2korr(pos_b))
- return 1;
- pos_a+=2; /* Skip VARCHAR length */
- pos_b+=2;
- set_if_smaller(length,tmp_length);
+ uint pack_length= keyseg->bit_start;
+ if (pack_length == 1)
+ {
+ a_length= (uint) *(uchar*) pos_a++;
+ b_length= (uint) *(uchar*) pos_b++;
+ }
+ else
+ {
+ a_length= uint2korr(pos_a);
+ b_length= uint2korr(pos_b);
+ pos_a+= 2; /* Skip VARCHAR length */
+ pos_b+= 2;
+ }
+ set_if_smaller(a_length, keyseg->length); /* Safety */
+ set_if_smaller(b_length, keyseg->length); /* safety */
}
else if (keyseg->flag & HA_BLOB_PART)
{
- /* Only compare 'length' characters if length<> 0 */
- uint a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
- uint b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
+ /* Only compare 'length' characters if length != 0 */
+ a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
+ b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
/* Check that a and b are of equal length */
- if (length && a_length > length)
- a_length=length;
- if (!length || length > b_length)
- length=b_length;
- if (length != a_length)
- return 1;
- /* Both strings are at least 'length' long */
+ if (keyseg->length)
+ {
+ /*
+ This is used in some cases when we are not interested in comparing
+ the whole length of the blob.
+ */
+ set_if_smaller(a_length, keyseg->length);
+ set_if_smaller(b_length, keyseg->length);
+ }
memcpy_fixed((byte*) &pos_a,pos_a+keyseg->bit_start,sizeof(char*));
memcpy_fixed((byte*) &pos_b,pos_b+keyseg->bit_start,sizeof(char*));
}
- if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
+ if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
+ type == HA_KEYTYPE_VARTEXT2)
{
- if (mi_compare_text(keyseg->charset, (uchar *) pos_a, length,
- (uchar *) pos_b, length, 0, 0))
- return 1;
+ if (mi_compare_text(keyseg->charset, (uchar *) pos_a, a_length,
+ (uchar *) pos_b, b_length, 0, 1))
+ return 1;
}
else
{
- end= pos_a+length;
+ if (a_length != b_length)
+ return 1;
+ end= pos_a+a_length;
while (pos_a != end)
+ {
if (*pos_a++ != *pos_b++)
return 1;
+ }
}
}
return 0;
diff --git a/myisam/mi_update.c b/myisam/mi_update.c
index f62be133ed9..ab23f2e6da9 100644
--- a/myisam/mi_update.c
+++ b/myisam/mi_update.c
@@ -34,6 +34,9 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
LINT_INIT(changed);
LINT_INIT(old_checksum);
+ DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
+ mi_print_error(info->s, HA_ERR_CRASHED);
+ DBUG_RETURN(my_errno= HA_ERR_CRASHED););
if (!(info->update & HA_STATE_AKTIV))
{
DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND);
@@ -84,7 +87,7 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
changed=0;
for (i=0 ; i < share->base.keys ; i++)
{
- if (((ulonglong) 1 << i) & share->state.key_map)
+ if (mi_is_key_active(share->state.key_map, i))
{
if (share->keyinfo[i].flag & HA_FULLTEXT )
{
@@ -205,7 +208,10 @@ err:
} while (i-- != 0);
}
else
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
+ }
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_ROW_CHANGED |
key_changed);
@@ -214,6 +220,9 @@ err:
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
allow_break(); /* Allow SIGHUP & SIGINT */
if (save_errno == HA_ERR_KEY_NOT_FOUND)
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
save_errno=HA_ERR_CRASHED;
+ }
DBUG_RETURN(my_errno=save_errno);
} /* mi_update */
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index cd9e73fba22..c8f9aa84a41 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -52,6 +52,9 @@ int mi_write(MI_INFO *info, byte *record)
DBUG_ENTER("mi_write");
DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile));
+ DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
+ mi_print_error(info->s, HA_ERR_CRASHED);
+ DBUG_RETURN(my_errno= HA_ERR_CRASHED););
if (share->options & HA_OPTION_READ_ONLY_DATA)
{
DBUG_RETURN(my_errno=EACCES);
@@ -64,7 +67,8 @@ int mi_write(MI_INFO *info, byte *record)
MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
goto err;
#endif
- filepos= ((share->state.dellink != HA_OFFSET_ERROR) ?
+ filepos= ((share->state.dellink != HA_OFFSET_ERROR &&
+ !info->append_insert_at_end) ?
share->state.dellink :
info->state->data_file_length);
@@ -97,7 +101,7 @@ int mi_write(MI_INFO *info, byte *record)
buff=info->lastkey2;
for (i=0 ; i < share->base.keys ; i++)
{
- if (((ulonglong) 1 << i) & share->state.key_map)
+ if (mi_is_key_active(share->state.key_map, i))
{
bool local_lock_tree= (lock_tree &&
!(info->bulk_insert &&
@@ -171,7 +175,7 @@ err:
info->errkey= (int) i;
while ( i-- > 0)
{
- if (((ulonglong) 1 << i) & share->state.key_map)
+ if (mi_is_key_active(share->state.key_map, i))
{
bool local_lock_tree= (lock_tree &&
!(info->bulk_insert &&
@@ -203,7 +207,10 @@ err:
}
}
else
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
+ }
info->update= (HA_STATE_CHANGED | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED);
my_errno=save_errno;
err2:
@@ -249,7 +256,7 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT))
{
- comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
+ comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No duplicates */
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
comp_flag|= SEARCH_NULL_ARE_EQUAL;
}
@@ -348,6 +355,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
dupp_key_pos=_mi_dpos(info,0,keybuff+tmp_key_length);
else
dupp_key_pos= HA_OFFSET_ERROR;
+
if (keyinfo->flag & HA_FULLTEXT)
{
uint off;
@@ -478,6 +486,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
if (t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
@@ -487,6 +496,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
if (-t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
@@ -582,6 +592,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
&after_key);
if (!key_pos)
DBUG_RETURN(-1);
+
length=(uint) (key_pos-buff);
a_length=mi_getint(buff);
mi_putint(buff,length,nod_flag);
@@ -602,6 +613,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
/* Store new page */
if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff))
DBUG_RETURN(-1);
+
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0,
(uchar*) 0, (uchar*) 0,
key_buff, &s_temp);
@@ -708,6 +720,7 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page,
memcpy(key, key_buff, length); /* previous key */
if (!(length=(*keyinfo->get_key)(keyinfo,0,&page,key_buff)))
{
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
@@ -931,20 +944,21 @@ int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows)
MI_KEYDEF *key=share->keyinfo;
bulk_insert_param *params;
uint i, num_keys, total_keylength;
- ulonglong key_map=0;
+ ulonglong key_map;
DBUG_ENTER("_mi_init_bulk_insert");
DBUG_PRINT("enter",("cache_size: %lu", cache_size));
DBUG_ASSERT(!info->bulk_insert &&
(!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT));
+ mi_clear_all_keys_active(key_map);
for (i=total_keylength=num_keys=0 ; i < share->base.keys ; i++)
{
- if (!(key[i].flag & HA_NOSAME) && share->base.auto_key != i+1
- && test(share->state.key_map & ((ulonglong) 1 << i)))
+ if (! (key[i].flag & HA_NOSAME) && (share->base.auto_key != i + 1) &&
+ mi_is_key_active(share->state.key_map, i))
{
num_keys++;
- key_map |=((ulonglong) 1 << i);
+ mi_set_key_active(key_map, i);
total_keylength+=key[i].maxlength+TREE_ELEMENT_EXTRA_SIZE;
}
}
@@ -968,7 +982,7 @@ int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows)
params=(bulk_insert_param *)(info->bulk_insert+share->base.keys);
for (i=0 ; i < share->base.keys ; i++)
{
- if (test(key_map & ((ulonglong) 1 << i)))
+ if (mi_is_key_active(key_map, i))
{
params->info=info;
params->keynr=i;
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 1a7d2b2d9a8..cfc3930779f 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -50,7 +50,7 @@ static int stopwords_inited= 0;
static MY_TMPDIR myisamchk_tmpdir;
static const char *type_names[]=
-{ "?","char","binary", "short", "long", "float",
+{ "impossible","char","binary", "short", "long", "float",
"double","number","unsigned short",
"unsigned long","longlong","ulonglong","int24",
"uint24","int8","varchar", "varbin","?",
@@ -905,8 +905,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
MI_STATE_INFO_SIZE ||
mi_uint2korr(share->state.header.base_info_length) !=
MI_BASE_INFO_SIZE ||
- ((param->keys_in_use & ~share->state.key_map) &
- (((ulonglong) 1L << share->base.keys)-1)) ||
+ mi_is_any_intersect_keys_active(param->keys_in_use, share->base.keys,
+ ~share->state.key_map) ||
test_if_almost_full(info) ||
info->s->state.header.file_version[3] != myisam_file_magic[3] ||
(set_collation &&
@@ -973,8 +973,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (param->testflag & T_REP_ANY)
{
ulonglong tmp=share->state.key_map;
- share->state.key_map= (((ulonglong) 1 << share->base.keys)-1)
- & param->keys_in_use;
+ mi_copy_keys_active(share->state.key_map, share->base.keys,
+ param->keys_in_use);
if (tmp != share->state.key_map)
info->update|=HA_STATE_CHANGED;
}
@@ -995,7 +995,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (!error)
{
if ((param->testflag & (T_REP_BY_SORT | T_REP_PARALLEL)) &&
- (share->state.key_map ||
+ (mi_is_any_key_active(share->state.key_map) ||
(rep_quick && !param->keys_in_use && !recreate)) &&
mi_test_if_sort_rep(info, info->state->records,
info->s->state.key_map,
@@ -1071,7 +1071,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
llstr(info->state->records,llbuff),
llstr(info->state->del,llbuff2));
error =chk_status(param,info);
- share->state.key_map &=param->keys_in_use;
+ mi_intersect_keys_active(share->state.key_map, param->keys_in_use);
error =chk_size(param,info);
if (!error || !(param->testflag & (T_FAST | T_FORCE_CREATE)))
error|=chk_del(param, info,param->testflag);
@@ -1300,7 +1300,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, my_string name)
}
printf("Recordlength: %13d\n",(int) share->base.pack_reclength);
- if (share->state.key_map != (((ulonglong) 1 << share->base.keys) -1))
+ if (! mi_is_all_keys_active(share->state.key_map, share->base.keys))
{
longlong2str(share->state.key_map,buff,2);
printf("Using only keys '%s' of %d possibly keys\n",
@@ -1482,7 +1482,7 @@ static int mi_sort_records(MI_CHECK *param,
temp_buff=0;
new_file= -1;
- if (!(((ulonglong) 1 << sort_key) & share->state.key_map))
+ if (! mi_is_key_active(share->state.key_map, sort_key))
{
mi_check_print_warning(param,
"Can't sort table '%s' on key %d; No such key",
@@ -1733,11 +1733,11 @@ err:
sorting
*/
-static my_bool not_killed= 0;
+static int not_killed= 0;
-volatile my_bool *killed_ptr(MI_CHECK *param __attribute__((unused)))
+volatile int *killed_ptr(MI_CHECK *param __attribute__((unused)))
{
- return &not_killed; /* always NULL */
+ return &not_killed; /* always NULL */
}
/* print warnings and errors */
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 15b310e907e..82f7fd7360e 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -272,6 +272,7 @@ struct st_myisam_info {
uint preload_buff_size; /* When preloading indexes */
myf lock_wait; /* is 0 or MY_DONT_WAIT */
my_bool was_locked; /* Was locked in panic */
+ my_bool append_insert_at_end; /* Set if concurrent insert */
my_bool quick_mode;
my_bool page_changed; /* If info->buff can't be used for rnext */
my_bool buff_used; /* If info->buff has to be reread for rnext */
@@ -357,6 +358,8 @@ typedef struct st_mi_sort_param
#define mi_mark_crashed_on_repair(x) { (x)->s->state.changed|=STATE_CRASHED|STATE_CRASHED_ON_REPAIR ; (x)->update|= HA_STATE_CHANGED; }
#define mi_is_crashed(x) ((x)->s->state.changed & STATE_CRASHED)
#define mi_is_crashed_on_repair(x) ((x)->s->state.changed & STATE_CRASHED_ON_REPAIR)
+#define mi_print_error(SHARE, ERRNO) \
+ mi_report_error((ERRNO), (SHARE)->index_file_name)
/* Functions to store length of space packed keys, VARCHAR or BLOB keys */
@@ -668,6 +671,7 @@ extern void _myisam_log_command(enum myisam_log_commands command,
extern void _myisam_log_record(enum myisam_log_commands command,MI_INFO *info,
const byte *record,my_off_t filepos,
int result);
+extern void mi_report_error(int errcode, const char *file_name);
extern my_bool _mi_memmap_file(MI_INFO *info);
extern void _mi_unmap_file(MI_INFO *info);
extern uint save_pack_length(uint version, byte *block_buff, ulong length);
@@ -675,10 +679,10 @@ extern uint read_pack_length(uint version, const uchar *buf, ulong *length);
extern uint calc_pack_length(uint version, ulong length);
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite);
-char *mi_state_info_read(char *ptr, MI_STATE_INFO *state);
+char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state);
uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead);
uint mi_base_info_write(File file, MI_BASE_INFO *base);
-char *my_n_base_info_read(char *ptr, MI_BASE_INFO *base);
+char *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base);
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg);
char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg);
uint mi_keydef_write(File file, MI_KEYDEF *keydef);
@@ -702,7 +706,7 @@ int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def,
const byte *record, my_off_t pos);
int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
my_bool null_are_equal);
-void mi_get_status(void* param);
+void mi_get_status(void* param, int concurrent_insert);
void mi_update_status(void* param);
void mi_copy_status(void* to,void *from);
my_bool mi_check_status(void* param);
@@ -715,7 +719,7 @@ int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
/* Functions needed by mi_check */
-volatile my_bool *killed_ptr(MI_CHECK *param);
+volatile int *killed_ptr(MI_CHECK *param);
void mi_check_print_error _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_warning _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_info _VARARGS((MI_CHECK *param, const char *fmt,...));
diff --git a/myisam/myisamlog.c b/myisam/myisamlog.c
index dc98d813266..de55b86252c 100644
--- a/myisam/myisamlog.c
+++ b/myisam/myisamlog.c
@@ -810,7 +810,7 @@ static int find_record_with_key(struct file_info *file_info, byte *record)
for (key=0 ; key < info->s->base.keys ; key++)
{
- if ((((ulonglong) 1 << key) & info->s->state.key_map) &&
+ if (mi_is_key_active(info->s->state.key_map, key) &&
info->s->keyinfo[key].flag & HA_NOSAME)
{
VOID(_mi_make_key(info,key,tmp_key,record,0L));
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index f017e4d23ab..3b091cd6ea2 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -33,10 +33,10 @@
#include <my_getopt.h>
#include <assert.h>
-#if INT_MAX > 32767
-#define BITS_SAVED 32
+#if SIZEOF_LONG_LONG > 4
+#define BITS_SAVED 64
#else
-#define BITS_SAVED 16
+#define BITS_SAVED 32
#endif
#define IS_OFFSET ((uint) 32768) /* Bit if offset or char in tree */
@@ -49,10 +49,10 @@
struct st_file_buffer {
File file;
- char *buffer,*pos,*end;
+ uchar *buffer,*pos,*end;
my_off_t pos_in_file;
int bits;
- uint current_byte;
+ ulonglong bitbucket;
};
struct st_huff_tree;
@@ -69,13 +69,17 @@ typedef struct st_huff_counts {
my_off_t end_space[8];
my_off_t pre_space[8];
my_off_t tot_end_space,tot_pre_space,zero_fields,empty_fields,bytes_packed;
- TREE int_tree;
- byte *tree_buff;
- byte *tree_pos;
+ TREE int_tree; /* Tree for detecting distinct column values. */
+ byte *tree_buff; /* Column values, 'field_length' each. */
+ byte *tree_pos; /* Points to end of column values in 'tree_buff'. */
} HUFF_COUNTS;
typedef struct st_huff_element HUFF_ELEMENT;
+/*
+ WARNING: It is crucial for the optimizations in calc_packed_length()
+ that 'count' is the first element of 'HUFF_ELEMENT'.
+*/
struct st_huff_element {
my_off_t count;
union un_element {
@@ -98,7 +102,7 @@ typedef struct st_huff_tree {
my_off_t bytes_packed;
uint tree_pack_length;
uint min_chr,max_chr,char_bits,offset_bits,max_offset,height;
- ulong *code;
+ ulonglong *code;
uchar *code_len;
} HUFF_TREE;
@@ -146,7 +150,7 @@ static uint join_same_trees(HUFF_COUNTS *huff_counts,uint trees);
static int make_huff_decode_table(HUFF_TREE *huff_tree,uint trees);
static void make_traverse_code_tree(HUFF_TREE *huff_tree,
HUFF_ELEMENT *element,uint size,
- ulong code);
+ ulonglong code);
static int write_header(PACK_MRG_INFO *isam_file, uint header_length,uint trees,
my_off_t tot_elements,my_off_t filelength);
static void write_field_info(HUFF_COUNTS *counts, uint fields,uint trees);
@@ -161,7 +165,7 @@ static char *make_old_name(char *new_name,char *old_name);
static void init_file_buffer(File file,pbool read_buffer);
static int flush_buffer(ulong neaded_length);
static void end_file_buffer(void);
-static void write_bits(ulong value,uint bits);
+static void write_bits(ulonglong value, uint bits);
static void flush_bits(void);
static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
ha_checksum crc);
@@ -170,13 +174,23 @@ static int save_state_mrg(File file,PACK_MRG_INFO *isam_file,my_off_t new_length
static int mrg_close(PACK_MRG_INFO *mrg);
static int mrg_rrnd(PACK_MRG_INFO *info,byte *buf);
static void mrg_reset(PACK_MRG_INFO *mrg);
+#if !defined(DBUG_OFF)
+static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count);
+static int fakecmp(my_off_t **count1, my_off_t **count2);
+#endif
static int error_on_write=0,test_only=0,verbose=0,silent=0,
write_loop=0,force_pack=0, isamchk_neaded=0;
static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
static my_bool backup, opt_wait;
-static uint tree_buff_length=8196-MALLOC_OVERHEAD;
+/*
+ tree_buff_length is somewhat arbitrary. The bigger it is the better
+ the chance to win in terms of compression factor. On the other hand,
+ this table becomes part of the compressed file header. And its length
+ is coded with 16 bits in the header. Hence the limit is 2**16 - 1.
+*/
+static uint tree_buff_length= 65536 - MALLOC_OVERHEAD;
static char tmp_dir[FN_REFLEN]={0},*join_table;
static my_off_t intervall_length;
static ha_checksum glob_crc;
@@ -225,7 +239,8 @@ int main(int argc, char **argv)
}
if (ok && isamchk_neaded && !silent)
puts("Remember to run myisamchk -rq on compressed tables");
- VOID(fflush(stdout)); VOID(fflush(stderr));
+ VOID(fflush(stdout));
+ VOID(fflush(stderr));
free_defaults(default_argv);
my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
exit(error ? 2 : 0);
@@ -264,7 +279,7 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"test", 't', "Don't pack table, only test packing it.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"verbose", 'v', "Write info about progress and packing result.",
+ {"verbose", 'v', "Write info about progress and packing result. Use many -v for more verbosity!",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -277,7 +292,8 @@ static struct my_option my_long_options[] =
static void print_version(void)
{
- printf("%s Ver 1.22 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
+ VOID(printf("%s Ver 1.23 for %s on %s\n",
+ my_progname, SYSTEM_TYPE, MACHINE_TYPE));
NETWARE_SET_SCREEN_MODE(1);
}
@@ -294,7 +310,7 @@ static void usage(void)
puts("afterwards to update the keys.");
puts("You should give the .MYI file as the filename argument.");
- printf("\nUsage: %s [OPTIONS] filename...\n", my_progname);
+ VOID(printf("\nUsage: %s [OPTIONS] filename...\n", my_progname));
my_print_help(my_long_options);
print_defaults("my", load_default_groups);
my_print_variables(my_long_options);
@@ -323,7 +339,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
silent= 1;
break;
case 't':
- test_only= verbose= 1;
+ test_only= 1;
+ /* Avoid to reset 'verbose' if it was already set > 1. */
+ if (! verbose)
+ verbose= 1;
break;
case 'T':
length= (uint) (strmov(tmp_dir, argument) - tmp_dir);
@@ -334,7 +353,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
break;
case 'v':
- verbose= 1;
+ verbose++; /* Allow for selecting the level of verbosity. */
silent= 0;
break;
case '#':
@@ -389,7 +408,7 @@ static MI_INFO *open_isam_file(char *name,int mode)
(opt_wait ? HA_OPEN_WAIT_IF_LOCKED :
HA_OPEN_ABORT_IF_LOCKED))))
{
- VOID(fprintf(stderr,"%s gave error %d on open\n",name,my_errno));
+ VOID(fprintf(stderr, "%s gave error %d on open\n", name, my_errno));
DBUG_RETURN(0);
}
share=isam_file->s;
@@ -397,7 +416,7 @@ static MI_INFO *open_isam_file(char *name,int mode)
{
if (!force_pack)
{
- VOID(fprintf(stderr,"%s is already compressed\n",name));
+ VOID(fprintf(stderr, "%s is already compressed\n", name));
VOID(mi_close(isam_file));
DBUG_RETURN(0);
}
@@ -409,7 +428,7 @@ static MI_INFO *open_isam_file(char *name,int mode)
(share->state.state.records <= 1 ||
share->state.state.data_file_length < 1024))
{
- VOID(fprintf(stderr,"%s is too small to compress\n",name));
+ VOID(fprintf(stderr, "%s is too small to compress\n", name));
VOID(mi_close(isam_file));
DBUG_RETURN(0);
}
@@ -431,9 +450,9 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count)
if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY)))
goto error;
- mrg->src_file_has_indexes_disabled|= ((mrg->file[i]->s->state.key_map !=
- (((ulonglong) 1) <<
- mrg->file[i]->s->base. keys) - 1));
+ mrg->src_file_has_indexes_disabled|=
+ ! mi_is_all_keys_active(mrg->file[i]->s->state.key_map,
+ mrg->file[i]->s->base.keys);
}
/* Check that files are identical */
for (j=0 ; j < count-1 ; j++)
@@ -455,8 +474,8 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count)
return 0;
diff_file:
- fprintf(stderr,"%s: Tables '%s' and '%s' are not identical\n",
- my_progname,names[j],names[j+1]);
+ VOID(fprintf(stderr, "%s: Tables '%s' and '%s' are not identical\n",
+ my_progname, names[j], names[j+1]));
error:
while (i--)
mi_close(mrg->file[i]);
@@ -527,16 +546,25 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
mrg->records=0;
for (i=0 ; i < mrg->count ; i++)
mrg->records+=mrg->file[i]->s->state.state.records;
+
+ DBUG_PRINT("info", ("Compressing %s: (%lu records)",
+ result_table ? new_name : org_name,
+ (ulong) mrg->records));
if (write_loop || verbose)
{
- printf("Compressing %s: (%lu records)\n",
- result_table ? new_name : org_name,(ulong) mrg->records);
+ VOID(printf("Compressing %s: (%lu records)\n",
+ result_table ? new_name : org_name, (ulong) mrg->records));
}
trees=fields=share->base.fields;
huff_counts=init_huff_count(isam_file,mrg->records);
QUICK_SAFEMALLOC;
+
+ /*
+ Read the whole data file(s) for statistics.
+ */
+ DBUG_PRINT("info", ("- Calculating statistics"));
if (write_loop || verbose)
- printf("- Calculating statistics\n");
+ VOID(printf("- Calculating statistics\n"));
if (get_statistic(mrg,huff_counts))
goto err;
NORMAL_SAFEMALLOC;
@@ -545,29 +573,74 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
old_length+= (mrg->file[i]->s->state.state.data_file_length -
mrg->file[i]->s->state.state.empty);
+ /*
+ Create a global priority queue in preparation for making
+ temporary Huffman trees.
+ */
if (init_queue(&queue,256,0,0,compare_huff_elements,0))
goto err;
+
+ /*
+ Check each column if we should use pre-space-compress, end-space-
+ compress, empty-field-compress or zero-field-compress.
+ */
check_counts(huff_counts,fields,mrg->records);
+
+ /*
+ Build a Huffman tree for each column.
+ */
huff_trees=make_huff_trees(huff_counts,trees);
+
+ /*
+ If the packed lengths of combined columns is less then the sum of
+ the non-combined columns, then create common Huffman trees for them.
+ We do this only for byte compressed columns, not for distinct values
+ compressed columns.
+ */
if ((int) (used_trees=join_same_trees(huff_counts,trees)) < 0)
goto err;
+
+ /*
+ Assign codes to all byte or column values.
+ */
if (make_huff_decode_table(huff_trees,fields))
goto err;
+ /* Prepare a file buffer. */
init_file_buffer(new_file,0);
+
+ /*
+ Reserve space in the target file for the fixed compressed file header.
+ */
file_buffer.pos_in_file=HEAD_LENGTH;
if (! test_only)
VOID(my_seek(new_file,file_buffer.pos_in_file,MY_SEEK_SET,MYF(0)));
+ /*
+ Write field infos: field type, pack type, length bits, tree number.
+ */
write_field_info(huff_counts,fields,used_trees);
+
+ /*
+ Write decode trees.
+ */
if (!(tot_elements=write_huff_tree(huff_trees,trees)))
goto err;
+
+ /*
+ Calculate the total length of the compression info header.
+ This includes the fixed compressed file header, the column compression
+ type descriptions, and the decode trees.
+ */
header_length=(uint) file_buffer.pos_in_file+
(uint) (file_buffer.pos-file_buffer.buffer);
- /* Compress file */
+ /*
+ Compress the source file into the target file.
+ */
+ DBUG_PRINT("info", ("- Compressing file"));
if (write_loop || verbose)
- printf("- Compressing file\n");
+ VOID(printf("- Compressing file\n"));
error=compress_isam_file(mrg,huff_counts);
new_length=file_buffer.pos_in_file;
if (!error && !test_only)
@@ -577,16 +650,28 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
error=my_write(file_buffer.file,buff,sizeof(buff),
MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
}
+
+ /*
+ Write the fixed compressed file header.
+ */
if (!error)
error=write_header(mrg,header_length,used_trees,tot_elements,
new_length);
+
+ /* Flush the file buffer. */
end_file_buffer();
+ /* Display statistics. */
+ DBUG_PRINT("info", ("Min record length: %6d Max length: %6d "
+ "Mean total length: %6ld\n",
+ mrg->min_pack_length, mrg->max_pack_length,
+ (ulong) (mrg->records ? (new_length/mrg->records) : 0)));
if (verbose && mrg->records)
- printf("Min record length: %6d Max length: %6d Mean total length: %6ld\n",
- mrg->min_pack_length,mrg->max_pack_length,
- (ulong) (new_length/mrg->records));
+ VOID(printf("Min record length: %6d Max length: %6d "
+ "Mean total length: %6ld\n", mrg->min_pack_length,
+ mrg->max_pack_length, (ulong) (new_length/mrg->records)));
+ /* Close source and target file. */
if (!test_only)
{
error|=my_close(new_file,MYF(MY_WME));
@@ -597,6 +682,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
}
}
+ /* Cleanup. */
free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields);
if (! test_only && ! error)
{
@@ -646,15 +732,16 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
error|=my_close(join_isam_file,MYF(MY_WME));
if (error)
{
- VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name));
+ VOID(fprintf(stderr, "Aborting: %s is not compressed\n", org_name));
VOID(my_delete(new_name,MYF(MY_WME)));
DBUG_RETURN(-1);
}
if (write_loop || verbose)
{
if (old_length)
- printf("%.4g%% \n", (((longlong) (old_length -new_length))*100.0/
- (longlong) old_length));
+ VOID(printf("%.4g%% \n",
+ (((longlong) (old_length - new_length)) * 100.0 /
+ (longlong) old_length)));
else
puts("Empty file saved in compressed format");
}
@@ -667,7 +754,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
if (join_isam_file >= 0)
VOID(my_close(join_isam_file,MYF(0)));
mrg_close(mrg);
- VOID(fprintf(stderr,"Aborted: %s is not compressed\n",org_name));
+ VOID(fprintf(stderr, "Aborted: %s is not compressed\n", org_name));
DBUG_RETURN(-1);
}
@@ -694,6 +781,12 @@ static HUFF_COUNTS *init_huff_count(MI_INFO *info,my_off_t records)
(type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
+ /*
+ For every column initialize a tree, which is used to detect distinct
+ column values. 'int_tree' works together with 'tree_buff' and
+ 'tree_pos'. It's keys are implemented by pointers into 'tree_buff'.
+ This is accomplished by '-1' as the element size.
+ */
init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, NULL,
NULL);
if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
@@ -765,7 +858,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
static_row_size=1;
for (count=huff_counts ; count < end_count ; count++)
{
- if (count->field_type == FIELD_BLOB || count->field_type == FIELD_VARCHAR)
+ if (count->field_type == FIELD_BLOB ||
+ count->field_type == FIELD_VARCHAR)
{
static_row_size=0;
break;
@@ -778,10 +872,13 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
ulong tot_blob_length=0;
if (! error)
{
+ /* glob_crc is a checksum over all bytes of all records. */
if (static_row_size)
glob_crc+=mi_static_checksum(mrg->file[0],record);
else
glob_crc+=mi_checksum(mrg->file[0],record);
+
+ /* Count the incidence of values separately for every column. */
for (pos=record,count=huff_counts ;
count < end_count ;
count++,
@@ -789,15 +886,48 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
{
next_pos=end_pos=(start_pos=pos)+count->field_length;
- /* Put value in tree if there is room for it */
+ /*
+ Put the whole column value in a tree if there is room for it.
+ 'int_tree' is used to quickly check for duplicate values.
+ 'tree_buff' collects as many distinct column values as
+ possible. If the field length is > 1, it is tree_buff_length,
+ else 2 bytes. Each value is 'field_length' bytes big. If there
+ are more distinct column values than fit into the buffer, we
+ give up with this tree. BLOBs and VARCHARs do not have a
+ tree_buff as it can only be used with fixed length columns.
+ For the special case of field length == 1, we handle only the
+ case that there is only one distinct value in the table(s).
+ Otherwise, we can have a maximum of 256 distinct values. This
+ is then handled by the normal Huffman tree build.
+
+ Another limit for collecting distinct column values is the
+ number of values itself. Since we would need to build a
+ Huffman tree for the values, we are limited by the 'IS_OFFSET'
+ constant. This constant expresses a bit which is used to
+ determine if a tree element holds a final value or an offset
+ to a child element. Hence, all values and offsets need to be
+ smaller than 'IS_OFFSET'. A tree element is implemented with
+ two integer values, one for the left branch and one for the
+ right branch. For the extreme case that the first element
+ points to the last element, the number of integers in the tree
+ must be less or equal to IS_OFFSET. So the number of elements
+ must be less or equal to IS_OFFSET / 2.
+
+ WARNING: At first, we insert a pointer into the record buffer
+ as the key for the tree. If we got a new distinct value, which
+ is really inserted into the tree, instead of being counted
+ only, we will copy the column value from the record buffer to
+ 'tree_buff' and adjust the key pointer of the tree accordingly.
+ */
if (count->tree_buff)
{
global_count=count;
if (!(element=tree_insert(&count->int_tree,pos, 0,
count->int_tree.custom_arg)) ||
(element->count == 1 &&
- count->tree_buff + tree_buff_length <
- count->tree_pos + count->field_length) ||
+ (count->tree_buff + tree_buff_length <
+ count->tree_pos + count->field_length)) ||
+ (count->int_tree.elements_in_tree > IS_OFFSET / 2) ||
(count->field_length == 1 &&
count->int_tree.elements_in_tree > 1))
{
@@ -807,10 +937,17 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
}
else
{
+ /*
+ If tree_insert() succeeds, it either creates a new element
+ or increments the counter of an existing element.
+ */
if (element->count == 1)
- { /* New element */
+ {
+ /* Copy the new column value into 'tree_buff'. */
memcpy(count->tree_pos,pos,(size_t) count->field_length);
+ /* Adjust the key pointer in the tree. */
tree_set_pointer(element,count->tree_pos);
+ /* Point behind the last column value so far. */
count->tree_pos+=count->field_length;
}
}
@@ -820,15 +957,21 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->field_type == FIELD_NORMAL ||
count->field_type == FIELD_SKIP_ENDSPACE)
{
+ /* Ignore trailing space. */
for ( ; end_pos > pos ; end_pos--)
if (end_pos[-1] != ' ')
break;
+ /* Empty fields are just counted. Go to the next record. */
if (end_pos == pos)
{
count->empty_fields++;
count->max_zero_fill=0;
continue;
}
+ /*
+ Count the total of all trailing spaces and the number of
+ short trailing spaces. Remember the longest trailing space.
+ */
length= (uint) (next_pos-end_pos);
count->tot_end_space+=length;
if (length < 8)
@@ -836,18 +979,25 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->max_end_space < length)
count->max_end_space = length;
}
+
if (count->field_type == FIELD_NORMAL ||
count->field_type == FIELD_SKIP_PRESPACE)
{
+ /* Ignore leading space. */
for (pos=start_pos; pos < end_pos ; pos++)
if (pos[0] != ' ')
break;
+ /* Empty fields are just counted. Go to the next record. */
if (end_pos == pos)
{
count->empty_fields++;
count->max_zero_fill=0;
continue;
}
+ /*
+ Count the total of all leading spaces and the number of
+ short leading spaces. Remember the longest leading space.
+ */
length= (uint) (pos-start_pos);
count->tot_pre_space+=length;
if (length < 8)
@@ -855,6 +1005,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->max_pre_space < length)
count->max_pre_space = length;
}
+
+ /* Calculate pos, end_pos, and max_length for variable length fields. */
if (count->field_type == FIELD_BLOB)
{
uint field_length=count->field_length -mi_portable_sizeof_char_ptr;
@@ -866,50 +1018,128 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
}
else if (count->field_type == FIELD_VARCHAR)
{
- length=uint2korr(start_pos);
- pos=start_pos+2;
- end_pos=start_pos+length;
+ uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
+ length= (pack_length == 1 ? (uint) *(uchar*) start_pos :
+ uint2korr(start_pos));
+ pos= start_pos+pack_length;
+ end_pos= pos+length;
set_if_bigger(count->max_length,length);
}
+
+ /* Evaluate 'max_zero_fill' for short fields. */
if (count->field_length <= 8 &&
(count->field_type == FIELD_NORMAL ||
count->field_type == FIELD_SKIP_ZERO))
{
uint i;
+ /* Zero fields are just counted. Go to the next record. */
if (!memcmp((byte*) start_pos,zero_string,count->field_length))
{
count->zero_fields++;
continue;
}
+ /*
+ max_zero_fill starts with field_length. It is decreased every
+ time a shorter "zero trailer" is found. It is set to zero when
+ an empty field is found (see above). This suggests that the
+ variable should be called 'min_zero_fill'.
+ */
for (i =0 ; i < count->max_zero_fill && ! end_pos[-1 - (int) i] ;
i++) ;
if (i < count->max_zero_fill)
count->max_zero_fill=i;
}
+
+ /* Ignore zero fields and check fields. */
if (count->field_type == FIELD_ZERO ||
count->field_type == FIELD_CHECK)
continue;
+
+ /*
+ Count the incidence of every byte value in the
+ significant field value.
+ */
for ( ; pos < end_pos ; pos++)
count->counts[(uchar) *pos]++;
+
+ /* Step to next field. */
}
+
if (tot_blob_length > max_blob_length)
max_blob_length=tot_blob_length;
record_count++;
if (write_loop && record_count % WRITE_COUNT == 0)
{
- printf("%lu\r",(ulong) record_count); VOID(fflush(stdout));
+ VOID(printf("%lu\r", (ulong) record_count));
+ VOID(fflush(stdout));
}
}
else if (error != HA_ERR_RECORD_DELETED)
{
- fprintf(stderr,"Got error %d while reading rows",error);
+ VOID(fprintf(stderr, "Got error %d while reading rows", error));
break;
}
+
+ /* Step to next record. */
}
if (write_loop)
{
- printf(" \r"); VOID(fflush(stdout));
+ VOID(printf(" \r"));
+ VOID(fflush(stdout));
}
+
+ /*
+ If --debug=d,fakebigcodes is set, fake the counts to get big Huffman
+ codes.
+ */
+ DBUG_EXECUTE_IF("fakebigcodes", fakebigcodes(huff_counts, end_count););
+
+ DBUG_PRINT("info", ("Found the following number of incidents "
+ "of the byte codes:"));
+ if (verbose >= 2)
+ VOID(printf("Found the following number of incidents "
+ "of the byte codes:\n"));
+ for (count= huff_counts ; count < end_count; count++)
+ {
+ uint idx;
+ my_off_t total_count;
+ char llbuf[32];
+
+ DBUG_PRINT("info", ("column: %3u", count - huff_counts + 1));
+ if (verbose >= 2)
+ VOID(printf("column: %3u\n", count - huff_counts + 1));
+ if (count->tree_buff)
+ {
+ DBUG_PRINT("info", ("number of distinct values: %u",
+ (count->tree_pos - count->tree_buff) /
+ count->field_length));
+ if (verbose >= 2)
+ VOID(printf("number of distinct values: %u\n",
+ (count->tree_pos - count->tree_buff) /
+ count->field_length));
+ }
+ total_count= 0;
+ for (idx= 0; idx < 256; idx++)
+ {
+ if (count->counts[idx])
+ {
+ total_count+= count->counts[idx];
+ DBUG_PRINT("info", ("counts[0x%02x]: %12s", idx,
+ llstr((longlong) count->counts[idx], llbuf)));
+ if (verbose >= 2)
+ VOID(printf("counts[0x%02x]: %12s\n", idx,
+ llstr((longlong) count->counts[idx], llbuf)));
+ }
+ }
+ DBUG_PRINT("info", ("total: %12s", llstr((longlong) total_count,
+ llbuf)));
+ if ((verbose >= 2) && total_count)
+ {
+ VOID(printf("total: %12s\n",
+ llstr((longlong) total_count, llbuf)));
+ }
+ }
+
mrg->records=record_count;
mrg->max_blob_length=max_blob_length;
my_afree((gptr) record);
@@ -958,9 +1188,14 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
huff_counts->field_type=FIELD_NORMAL;
huff_counts->pack_type=0;
+ /* Check for zero-filled records (in this column), or zero records. */
if (huff_counts->zero_fields || ! records)
{
my_off_t old_space_count;
+ /*
+ If there are only zero filled records (in this column),
+ or no records at all, we are done.
+ */
if (huff_counts->zero_fields == records)
{
huff_counts->field_type= FIELD_ZERO;
@@ -968,14 +1203,22 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
huff_counts->counts[0]=0;
goto found_pack;
}
+ /* Remeber the number of significant spaces. */
old_space_count=huff_counts->counts[' '];
- huff_counts->counts[' ']+=huff_counts->tot_end_space+
- huff_counts->tot_pre_space +
- huff_counts->empty_fields * huff_counts->field_length;
+ /* Add all leading and trailing spaces. */
+ huff_counts->counts[' ']+= (huff_counts->tot_end_space +
+ huff_counts->tot_pre_space +
+ huff_counts->empty_fields *
+ huff_counts->field_length);
+ /* Check, what the compressed length of this would be. */
old_length=calc_packed_length(huff_counts,0)+records/8;
+ /* Get the number of zero bytes. */
length=huff_counts->zero_fields*huff_counts->field_length;
+ /* Add it to the counts. */
huff_counts->counts[0]+=length;
+ /* Check, what the compressed length of this would be. */
new_length=calc_packed_length(huff_counts,0);
+ /* If the compression without the zeroes would be shorter, we are done. */
if (old_length < new_length && huff_counts->field_length > 1)
{
huff_counts->field_type=FIELD_SKIP_ZERO;
@@ -983,9 +1226,16 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
huff_counts->bytes_packed=old_length- records/8;
goto found_pack;
}
+ /* Remove the insignificant spaces, but keep the zeroes. */
huff_counts->counts[' ']=old_space_count;
}
+ /* Check, what the compressed length of this column would be. */
huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
+
+ /*
+ If there are enough empty records (in this column),
+ treating them specially may pay off.
+ */
if (huff_counts->empty_fields)
{
if (huff_counts->field_length > 2 &&
@@ -1017,6 +1267,11 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
}
}
}
+
+ /*
+ If there are enough trailing spaces (in this column),
+ treating them specially may pay off.
+ */
if (huff_counts->tot_end_space)
{
huff_counts->counts[' ']+=huff_counts->tot_pre_space;
@@ -1026,6 +1281,11 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
goto found_pack;
huff_counts->counts[' ']-=huff_counts->tot_pre_space;
}
+
+ /*
+ If there are enough leading spaces (in this column),
+ treating them specially may pay off.
+ */
if (huff_counts->tot_pre_space)
{
if (test_space_compress(huff_counts,records,huff_counts->max_pre_space,
@@ -1055,6 +1315,8 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
{
HUFF_TREE tree;
+ DBUG_EXECUTE_IF("forceintervall",
+ huff_counts->bytes_packed= ~ (my_off_t) 0;);
tree.element_buffer=0;
if (!make_huff_tree(&tree,huff_counts) &&
tree.bytes_packed+tree.tree_pack_length < huff_counts->bytes_packed)
@@ -1080,14 +1342,27 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
fill_zero_fields++;
field_count[huff_counts->field_type]++;
}
+ DBUG_PRINT("info", ("normal: %3d empty-space: %3d "
+ "empty-zero: %3d empty-fill: %3d",
+ field_count[FIELD_NORMAL],space_fields,
+ field_count[FIELD_SKIP_ZERO],fill_zero_fields));
+ DBUG_PRINT("info", ("pre-space: %3d end-space: %3d "
+ "intervall-fields: %3d zero: %3d",
+ field_count[FIELD_SKIP_PRESPACE],
+ field_count[FIELD_SKIP_ENDSPACE],
+ field_count[FIELD_INTERVALL],
+ field_count[FIELD_ZERO]));
if (verbose)
- printf("\nnormal: %3d empty-space: %3d empty-zero: %3d empty-fill: %3d\npre-space: %3d end-space: %3d intervall-fields: %3d zero: %3d\n",
- field_count[FIELD_NORMAL],space_fields,
- field_count[FIELD_SKIP_ZERO],fill_zero_fields,
- field_count[FIELD_SKIP_PRESPACE],
- field_count[FIELD_SKIP_ENDSPACE],
- field_count[FIELD_INTERVALL],
- field_count[FIELD_ZERO]);
+ VOID(printf("\nnormal: %3d empty-space: %3d "
+ "empty-zero: %3d empty-fill: %3d\n"
+ "pre-space: %3d end-space: %3d "
+ "intervall-fields: %3d zero: %3d\n",
+ field_count[FIELD_NORMAL],space_fields,
+ field_count[FIELD_SKIP_ZERO],fill_zero_fields,
+ field_count[FIELD_SKIP_PRESPACE],
+ field_count[FIELD_SKIP_ENDSPACE],
+ field_count[FIELD_INTERVALL],
+ field_count[FIELD_ZERO]));
DBUG_VOID_RETURN;
}
@@ -1184,8 +1459,24 @@ static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts, uint trees)
DBUG_RETURN(huff_tree);
}
- /* Update huff_tree according to huff_counts->counts or
- huff_counts->tree_buff */
+/*
+ Build a Huffman tree.
+
+ SYNOPSIS
+ make_huff_tree()
+ huff_tree The Huffman tree.
+ huff_counts The counts.
+
+ DESCRIPTION
+ Build a Huffman tree according to huff_counts->counts or
+ huff_counts->tree_buff. tree_buff, if non-NULL contains up to
+ tree_buff_length of distinct column values. In that case, whole
+ values can be Huffman encoded instead of single bytes.
+
+ RETURN
+ 0 OK
+ != 0 Error
+*/
static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
{
@@ -1196,12 +1487,14 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
first=last=0;
if (huff_counts->tree_buff)
{
+ /* Calculate the number of distinct values in tree_buff. */
found= (uint) (huff_counts->tree_pos - huff_counts->tree_buff) /
huff_counts->field_length;
first=0; last=found-1;
}
else
{
+ /* Count the number of byte codes found in the column. */
for (i=found=0 ; i < 256 ; i++)
{
if (huff_counts->counts[i])
@@ -1215,6 +1508,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
found=2;
}
+ /* When using 'tree_buff' we can have more that 256 values. */
if (queue.max_elements < found)
{
delete_queue(&queue);
@@ -1222,6 +1516,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
return -1;
}
+ /* Allocate or reallocate an element buffer for the Huffman tree. */
if (!huff_tree->element_buffer)
{
if (!(huff_tree->element_buffer=
@@ -1249,15 +1544,25 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
if (huff_counts->tree_buff)
{
huff_tree->elements=0;
- tree_walk(&huff_counts->int_tree,
- (int (*)(void*, element_count,void*)) save_counts_in_queue,
- (gptr) huff_tree, left_root_right);
huff_tree->tree_pack_length=(1+15+16+5+5+
(huff_tree->char_bits+1)*found+
(huff_tree->offset_bits+1)*
(found-2)+7)/8 +
(uint) (huff_tree->counts->tree_pos-
huff_tree->counts->tree_buff);
+ /*
+ Put a HUFF_ELEMENT into the queue for every distinct column value.
+
+ tree_walk() calls save_counts_in_queue() for every element in
+ 'int_tree'. This takes elements from the target trees element
+ buffer and places references to them into the buffer of the
+ priority queue. We insert in column value order, but the order is
+ in fact irrelevant here. We will establish the correct order
+ later.
+ */
+ tree_walk(&huff_counts->int_tree,
+ (int (*)(void*, element_count,void*)) save_counts_in_queue,
+ (gptr) huff_tree, left_root_right);
}
else
{
@@ -1266,7 +1571,15 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
(huff_tree->char_bits+1)*found+
(huff_tree->offset_bits+1)*
(found-2)+7)/8;
+ /*
+ Put a HUFF_ELEMENT into the queue for every byte code found in the column.
+ The elements are taken from the target trees element buffer.
+ Instead of using queue_insert(), we just place references to the
+ elements into the buffer of the priority queue. We insert in byte
+ value order, but the order is in fact irrelevant here. We will
+ establish the correct order later.
+ */
for (i=first, found=0 ; i <= last ; i++)
{
if (huff_counts->counts[i])
@@ -1278,8 +1591,13 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
queue.root[found]=(byte*) new_huff_el;
}
}
+ /*
+ If there is only a single byte value in this field in all records,
+ add a second element with zero incidence. This is required to enter
+ the loop, which builds the Huffman tree.
+ */
while (found < 2)
- { /* Our huff_trees request at least 2 elements */
+ {
new_huff_el=huff_tree->element_buffer+(found++);
new_huff_el->count=0;
new_huff_el->a.leaf.null=0;
@@ -1290,21 +1608,53 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
queue.root[found]=(byte*) new_huff_el;
}
}
+
+ /* Make a queue from the queue buffer. */
queue.elements=found;
+ /*
+ Make a priority queue from the queue. Construct its index so that we
+ have a partially ordered tree.
+ */
for (i=found/2 ; i > 0 ; i--)
_downheap(&queue,i);
+
+ /* The Huffman algorithm. */
bytes_packed=0; bits_packed=0;
for (i=1 ; i < found ; i++)
{
+ /*
+ Pop the top element from the queue (the one with the least incidence).
+ Popping from a priority queue includes a re-ordering of the queue,
+ to get the next least incidence element to the top.
+ */
a=(HUFF_ELEMENT*) queue_remove(&queue,0);
+ /*
+ Copy the next least incidence element. The queue implementation
+ reserves root[0] for temporary purposes. root[1] is the top.
+ */
b=(HUFF_ELEMENT*) queue.root[1];
+ /* Get a new element from the element buffer. */
new_huff_el=huff_tree->element_buffer+found+i;
+ /* The new element gets the sum of the two least incidence elements. */
new_huff_el->count=a->count+b->count;
+ /*
+ The Huffman algorithm assigns another bit to the code for a byte
+ every time that bytes incidence is combined (directly or indirectly)
+ to a new element as one of the two least incidence elements.
+ This means that one more bit per incidence of that byte is required
+ in the resulting file. So we add the new combined incidence as the
+ number of bits by which the result grows.
+ */
bits_packed+=(uint) (new_huff_el->count & 7);
bytes_packed+=new_huff_el->count/8;
- new_huff_el->a.nod.left=a; /* lesser in left */
+ /* The new element points to its children, lesser in left. */
+ new_huff_el->a.nod.left=a;
new_huff_el->a.nod.right=b;
+ /*
+ Replace the copied top element by the new element and re-order the
+ queue.
+ */
queue.root[1]=(byte*) new_huff_el;
queue_replaced(&queue);
}
@@ -1323,7 +1673,26 @@ static int compare_tree(void* cmp_arg __attribute__((unused)),
return 0;
}
- /* Used by make_huff_tree to save intervall-counts in queue */
+/*
+ Organize distinct column values and their incidences into a priority queue.
+
+ SYNOPSIS
+ save_counts_in_queue()
+ key The column value.
+ count The incidence of this value.
+ tree The Huffman tree to be built later.
+
+ DESCRIPTION
+ We use the element buffer of the targeted tree. The distinct column
+ values are organized in a priority queue first. The Huffman
+ algorithm will later organize the elements into a Huffman tree. For
+ the time being, we just place references to the elements into the
+ queue buffer. The buffer will later be organized into a priority
+ queue.
+
+ RETURN
+ 0
+ */
static int save_counts_in_queue(byte *key, element_count count,
HUFF_TREE *tree)
@@ -1340,8 +1709,23 @@ static int save_counts_in_queue(byte *key, element_count count,
}
- /* Calculate length of file if given counts should be used */
- /* Its actually a faster version of make_huff_tree */
+/*
+ Calculate length of file if given counts should be used.
+
+ SYNOPSIS
+ calc_packed_length()
+ huff_counts The counts for a column of the table(s).
+ add_tree_lenght If the decode tree length should be added.
+
+ DESCRIPTION
+ We need to follow the Huffman algorithm until we know, how many bits
+ are required for each byte code. But we do not need the resulting
+ Huffman tree. Hence, we can leave out some steps which are essential
+ in make_huff_tree().
+
+ RETURN
+ Number of bytes required to compress this table column.
+*/
static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
uint add_tree_lenght)
@@ -1351,6 +1735,23 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
HUFF_ELEMENT element_buffer[256];
DBUG_ENTER("calc_packed_length");
+ /*
+ WARNING: We use a small hack for efficiency: Instead of placing
+ references to HUFF_ELEMENTs into the queue, we just insert
+ references to the counts of the byte codes which appeared in this
+ table column. During the Huffman algorithm they are successively
+ replaced by references to HUFF_ELEMENTs. This works, because
+ HUFF_ELEMENTs have the incidence count at their beginning.
+ Regardless, wether the queue array contains references to counts of
+ type my_off_t or references to HUFF_ELEMENTs which have the count of
+ type my_off_t at their beginning, it always points to a count of the
+ same type.
+
+ Instead of using queue_insert(), we just copy the references into
+ the buffer of the priority queue. We insert in byte value order, but
+ the order is in fact irrelevant here. We will establish the correct
+ order later.
+ */
first=last=0;
for (i=found=0 ; i < 256 ; i++)
{
@@ -1359,31 +1760,73 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
if (! found++)
first=i;
last=i;
+ /* We start with root[1], which is the queues top element. */
queue.root[found]=(byte*) &huff_counts->counts[i];
}
}
if (!found)
DBUG_RETURN(0); /* Empty tree */
+ /*
+ If there is only a single byte value in this field in all records,
+ add a second element with zero incidence. This is required to enter
+ the loop, which follows the Huffman algorithm.
+ */
if (found < 2)
queue.root[++found]=(byte*) &huff_counts->counts[last ? 0 : 1];
+ /* Make a queue from the queue buffer. */
queue.elements=found;
bytes_packed=0; bits_packed=0;
+ /* Add the length of the coding table, which would become part of the file. */
if (add_tree_lenght)
bytes_packed=(8+9+5+5+(max_bit(last-first)+1)*found+
(max_bit(found-1)+1+1)*(found-2) +7)/8;
+
+ /*
+ Make a priority queue from the queue. Construct its index so that we
+ have a partially ordered tree.
+ */
for (i=(found+1)/2 ; i > 0 ; i--)
_downheap(&queue,i);
+
+ /* The Huffman algorithm. */
for (i=0 ; i < found-1 ; i++)
{
- HUFF_ELEMENT *a,*b,*new_huff_el;
- a=(HUFF_ELEMENT*) queue_remove(&queue,0);
- b=(HUFF_ELEMENT*) queue.root[1];
- new_huff_el=element_buffer+i;
- new_huff_el->count=a->count+b->count;
+ my_off_t *a;
+ my_off_t *b;
+ HUFF_ELEMENT *new_huff_el;
+
+ /*
+ Pop the top element from the queue (the one with the least
+ incidence). Popping from a priority queue includes a re-ordering
+ of the queue, to get the next least incidence element to the top.
+ */
+ a= (my_off_t*) queue_remove(&queue, 0);
+ /*
+ Copy the next least incidence element. The queue implementation
+ reserves root[0] for temporary purposes. root[1] is the top.
+ */
+ b= (my_off_t*) queue.root[1];
+ /* Create a new element in a local (automatic) buffer. */
+ new_huff_el= element_buffer + i;
+ /* The new element gets the sum of the two least incidence elements. */
+ new_huff_el->count= *a + *b;
+ /*
+ The Huffman algorithm assigns another bit to the code for a byte
+ every time that bytes incidence is combined (directly or indirectly)
+ to a new element as one of the two least incidence elements.
+ This means that one more bit per incidence of that byte is required
+ in the resulting file. So we add the new combined incidence as the
+ number of bits by which the result grows.
+ */
bits_packed+=(uint) (new_huff_el->count & 7);
bytes_packed+=new_huff_el->count/8;
+ /*
+ Replace the copied top element by the new element and re-order the
+ queue. This successively replaces the references to counts by
+ references to HUFF_ELEMENTs.
+ */
queue.root[1]=(byte*) new_huff_el;
queue_replaced(&queue);
}
@@ -1431,13 +1874,26 @@ static uint join_same_trees(HUFF_COUNTS *huff_counts, uint trees)
}
}
}
+ DBUG_PRINT("info", ("Original trees: %d After join: %d",
+ trees, tree_number));
if (verbose)
- printf("Original trees: %d After join: %d\n",trees,tree_number);
+ VOID(printf("Original trees: %d After join: %d\n", trees, tree_number));
return tree_number; /* Return trees left */
}
- /* Fill in huff_tree decode tables */
+/*
+ Fill in huff_tree encode tables.
+
+ SYNOPSIS
+ make_huff_decode_table()
+ huff_tree An array of HUFF_TREE which are to be encoded.
+ trees The number of HUFF_TREE in the array.
+
+ RETURN
+ 0 success
+ != 0 error
+*/
static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees)
{
@@ -1448,12 +1904,13 @@ static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees)
{
elements=huff_tree->counts->tree_buff ? huff_tree->elements : 256;
if (!(huff_tree->code =
- (ulong*) my_malloc(elements*
- (sizeof(ulong)+sizeof(uchar)),
- MYF(MY_WME | MY_ZEROFILL))))
+ (ulonglong*) my_malloc(elements*
+ (sizeof(ulonglong) + sizeof(uchar)),
+ MYF(MY_WME | MY_ZEROFILL))))
return 1;
huff_tree->code_len=(uchar*) (huff_tree->code+elements);
- make_traverse_code_tree(huff_tree,huff_tree->root,32,0);
+ make_traverse_code_tree(huff_tree, huff_tree->root,
+ 8 * sizeof(ulonglong), LL(0));
}
}
return 0;
@@ -1462,28 +1919,90 @@ static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees)
static void make_traverse_code_tree(HUFF_TREE *huff_tree,
HUFF_ELEMENT *element,
- uint size, ulong code)
+ uint size, ulonglong code)
{
uint chr;
if (!element->a.leaf.null)
{
chr=element->a.leaf.element_nr;
- huff_tree->code_len[chr]=(uchar) (32-size);
- huff_tree->code[chr]= (code >> size);
- if (huff_tree->height < 32-size)
- huff_tree->height= 32-size;
+ huff_tree->code_len[chr]= (uchar) (8 * sizeof(ulonglong) - size);
+ huff_tree->code[chr]= (code >> size);
+ if (huff_tree->height < 8 * sizeof(ulonglong) - size)
+ huff_tree->height= 8 * sizeof(ulonglong) - size;
}
else
{
size--;
make_traverse_code_tree(huff_tree,element->a.nod.left,size,code);
- make_traverse_code_tree(huff_tree,element->a.nod.right,size,
- code+((ulong) 1L << size));
+ make_traverse_code_tree(huff_tree, element->a.nod.right, size,
+ code + (((ulonglong) 1) << size));
}
return;
}
+/*
+ Convert a value into binary digits.
+
+ SYNOPSIS
+ bindigits()
+ value The value.
+ length The number of low order bits to convert.
+
+ NOTE
+ The result string is in static storage. It is reused on every call.
+ So you cannot use it twice in one expression.
+
+ RETURN
+ A pointer to a static NUL-terminated string.
+ */
+
+static char *bindigits(ulonglong value, uint bits)
+{
+ static char digits[72];
+ char *ptr= digits;
+ uint idx= bits;
+
+ DBUG_ASSERT(idx < sizeof(digits));
+ while (idx)
+ *(ptr++)= '0' + ((value >> (--idx)) & 1);
+ *ptr= '\0';
+ return digits;
+}
+
+
+/*
+ Convert a value into hexadecimal digits.
+
+ SYNOPSIS
+ hexdigits()
+ value The value.
+
+ NOTE
+ The result string is in static storage. It is reused on every call.
+ So you cannot use it twice in one expression.
+
+ RETURN
+ A pointer to a static NUL-terminated string.
+ */
+
+static char *hexdigits(ulonglong value)
+{
+ static char digits[20];
+ char *ptr= digits;
+ uint idx= 2 * sizeof(value); /* Two hex digits per byte. */
+
+ DBUG_ASSERT(idx < sizeof(digits));
+ while (idx)
+ {
+ if ((*(ptr++)= '0' + ((value >> (4 * (--idx))) & 0xf)) > '9')
+ *(ptr - 1)+= 'a' - '9' - 1;
+ }
+ *ptr= '\0';
+ return digits;
+}
+
+
/* Write header to new packed data file */
static int write_header(PACK_MRG_INFO *mrg,uint head_length,uint trees,
@@ -1517,15 +2036,64 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees)
uint huff_tree_bits;
huff_tree_bits=max_bit(trees ? trees-1 : 0);
+ DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", ("column types:"));
+ DBUG_PRINT("info", ("FIELD_NORMAL 0"));
+ DBUG_PRINT("info", ("FIELD_SKIP_ENDSPACE 1"));
+ DBUG_PRINT("info", ("FIELD_SKIP_PRESPACE 2"));
+ DBUG_PRINT("info", ("FIELD_SKIP_ZERO 3"));
+ DBUG_PRINT("info", ("FIELD_BLOB 4"));
+ DBUG_PRINT("info", ("FIELD_CONSTANT 5"));
+ DBUG_PRINT("info", ("FIELD_INTERVALL 6"));
+ DBUG_PRINT("info", ("FIELD_ZERO 7"));
+ DBUG_PRINT("info", ("FIELD_VARCHAR 8"));
+ DBUG_PRINT("info", ("FIELD_CHECK 9"));
+ DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", ("pack type as a set of flags:"));
+ DBUG_PRINT("info", ("PACK_TYPE_SELECTED 1"));
+ DBUG_PRINT("info", ("PACK_TYPE_SPACE_FIELDS 2"));
+ DBUG_PRINT("info", ("PACK_TYPE_ZERO_FILL 4"));
+ DBUG_PRINT("info", (""));
+ if (verbose >= 2)
+ {
+ VOID(printf("\n"));
+ VOID(printf("column types:\n"));
+ VOID(printf("FIELD_NORMAL 0\n"));
+ VOID(printf("FIELD_SKIP_ENDSPACE 1\n"));
+ VOID(printf("FIELD_SKIP_PRESPACE 2\n"));
+ VOID(printf("FIELD_SKIP_ZERO 3\n"));
+ VOID(printf("FIELD_BLOB 4\n"));
+ VOID(printf("FIELD_CONSTANT 5\n"));
+ VOID(printf("FIELD_INTERVALL 6\n"));
+ VOID(printf("FIELD_ZERO 7\n"));
+ VOID(printf("FIELD_VARCHAR 8\n"));
+ VOID(printf("FIELD_CHECK 9\n"));
+ VOID(printf("\n"));
+ VOID(printf("pack type as a set of flags:\n"));
+ VOID(printf("PACK_TYPE_SELECTED 1\n"));
+ VOID(printf("PACK_TYPE_SPACE_FIELDS 2\n"));
+ VOID(printf("PACK_TYPE_ZERO_FILL 4\n"));
+ VOID(printf("\n"));
+ }
for (i=0 ; i++ < fields ; counts++)
{
- write_bits((ulong) (int) counts->field_type,5);
+ write_bits((ulonglong) (int) counts->field_type, 5);
write_bits(counts->pack_type,6);
if (counts->pack_type & PACK_TYPE_ZERO_FILL)
write_bits(counts->max_zero_fill,5);
else
write_bits(counts->length_bits,5);
- write_bits((ulong) counts->tree->tree_number-1,huff_tree_bits);
+ write_bits((ulonglong) counts->tree->tree_number - 1, huff_tree_bits);
+ DBUG_PRINT("info", ("column: %3u type: %2u pack: %2u zero: %4u "
+ "lbits: %2u tree: %2u length: %4u",
+ i , counts->field_type, counts->pack_type,
+ counts->max_zero_fill, counts->length_bits,
+ counts->tree->tree_number, counts->field_length));
+ if (verbose >= 2)
+ VOID(printf("column: %3u type: %2u pack: %2u zero: %4u lbits: %2u "
+ "tree: %2u length: %4u\n", i , counts->field_type,
+ counts->pack_type, counts->max_zero_fill, counts->length_bits,
+ counts->tree->tree_number, counts->field_length));
}
flush_bits();
return;
@@ -1538,45 +2106,72 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees)
static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
{
uint i,int_length;
+ uint tree_no;
+ uint codes;
+ uint errors= 0;
uint *packed_tree,*offset,length;
my_off_t elements;
+ /* Find the highest number of elements in the trees. */
for (i=length=0 ; i < trees ; i++)
if (huff_tree[i].tree_number > 0 && huff_tree[i].elements > length)
length=huff_tree[i].elements;
+ /*
+ Allocate a buffer for packing a decode tree. Two numbers per element
+ (left child and right child).
+ */
if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2)))
{
my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2);
return 0;
}
+ DBUG_PRINT("info", (""));
+ if (verbose >= 2)
+ VOID(printf("\n"));
+ tree_no= 0;
intervall_length=0;
for (elements=0; trees-- ; huff_tree++)
{
+ /* Skip columns that have been joined with other columns. */
if (huff_tree->tree_number == 0)
continue; /* Deleted tree */
+ tree_no++;
+ DBUG_PRINT("info", (""));
+ if (verbose >= 3)
+ VOID(printf("\n"));
+ /* Count the total number of elements (byte codes or column values). */
elements+=huff_tree->elements;
huff_tree->max_offset=2;
+ /* Build a tree of offsets and codes for decoding in 'packed_tree'. */
if (huff_tree->elements <= 1)
offset=packed_tree;
else
offset=make_offset_code_tree(huff_tree,huff_tree->root,packed_tree);
+
+ /* This should be the same as 'length' above. */
huff_tree->offset_bits=max_bit(huff_tree->max_offset);
+
+ /*
+ Since we check this during collecting the distinct column values,
+ this should never happen.
+ */
if (huff_tree->max_offset >= IS_OFFSET)
{ /* This should be impossible */
- VOID(fprintf(stderr,"Tree offset got too big: %d, aborted\n",
- huff_tree->max_offset));
+ VOID(fprintf(stderr, "Tree offset got too big: %d, aborted\n",
+ huff_tree->max_offset));
my_afree((gptr) packed_tree);
return 0;
}
-#ifdef EXTRA_DBUG
- printf("pos: %d elements: %d tree-elements: %d char_bits: %d\n",
- (uint) (file_buffer.pos-file_buffer.buffer),
- huff_tree->elements, (offset-packed_tree),huff_tree->char_bits);
-#endif
+ DBUG_PRINT("info", ("pos: %lu elements: %u tree-elements: %lu "
+ "char_bits: %u\n",
+ (ulong) (file_buffer.pos - file_buffer.buffer),
+ huff_tree->elements, (ulong) (offset - packed_tree),
+ huff_tree->char_bits));
if (!huff_tree->counts->tree_buff)
{
+ /* We do a byte compression on this column. Mark with bit 0. */
write_bits(0,1);
write_bits(huff_tree->min_chr,8);
write_bits(huff_tree->elements,9);
@@ -1588,6 +2183,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
{
int_length=(uint) (huff_tree->counts->tree_pos -
huff_tree->counts->tree_buff);
+ /* We have distinct column values for this column. Mark with bit 1. */
write_bits(1,1);
write_bits(huff_tree->elements,15);
write_bits(int_length,16);
@@ -1595,10 +2191,29 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
write_bits(huff_tree->offset_bits,5);
intervall_length+=int_length;
}
+ DBUG_PRINT("info", ("tree: %2u elements: %4u char_bits: %2u "
+ "offset_bits: %2u %s: %5u codelen: %2u",
+ tree_no, huff_tree->elements, huff_tree->char_bits,
+ huff_tree->offset_bits, huff_tree->counts->tree_buff ?
+ "bufflen" : "min_chr", huff_tree->counts->tree_buff ?
+ int_length : huff_tree->min_chr, huff_tree->height));
+ if (verbose >= 2)
+ VOID(printf("tree: %2u elements: %4u char_bits: %2u offset_bits: %2u "
+ "%s: %5u codelen: %2u\n", tree_no, huff_tree->elements,
+ huff_tree->char_bits, huff_tree->offset_bits,
+ huff_tree->counts->tree_buff ? "bufflen" : "min_chr",
+ huff_tree->counts->tree_buff ? int_length :
+ huff_tree->min_chr, huff_tree->height));
+
+ /* Check that the code tree length matches the element count. */
length=(uint) (offset-packed_tree);
if (length != huff_tree->elements*2-2)
- printf("error: Huff-tree-length: %d != calc_length: %d\n",
- length,huff_tree->elements*2-2);
+ {
+ VOID(fprintf(stderr, "error: Huff-tree-length: %d != calc_length: %d\n",
+ length, huff_tree->elements * 2 - 2));
+ errors++;
+ break;
+ }
for (i=0 ; i < length ; i++)
{
@@ -1607,16 +2222,122 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
huff_tree->offset_bits+1);
else
write_bits(packed_tree[i]-huff_tree->min_chr,huff_tree->char_bits+1);
+ DBUG_PRINT("info", ("tree[0x%04x]: %s0x%04x",
+ i, (packed_tree[i] & IS_OFFSET) ?
+ " -> " : "", (packed_tree[i] & IS_OFFSET) ?
+ packed_tree[i] - IS_OFFSET + i : packed_tree[i]));
+ if (verbose >= 3)
+ VOID(printf("tree[0x%04x]: %s0x%04x\n",
+ i, (packed_tree[i] & IS_OFFSET) ? " -> " : "",
+ (packed_tree[i] & IS_OFFSET) ?
+ packed_tree[i] - IS_OFFSET + i : packed_tree[i]));
}
flush_bits();
+
+ /*
+ Display coding tables and check their correctness.
+ */
+ codes= huff_tree->counts->tree_buff ? huff_tree->elements : 256;
+ for (i= 0; i < codes; i++)
+ {
+ ulonglong code;
+ uint bits;
+ uint len;
+ uint idx;
+
+ if (! (len= huff_tree->code_len[i]))
+ continue;
+ DBUG_PRINT("info", ("code[0x%04x]: 0x%s bits: %2u bin: %s", i,
+ hexdigits(huff_tree->code[i]), huff_tree->code_len[i],
+ bindigits(huff_tree->code[i],
+ huff_tree->code_len[i])));
+ if (verbose >= 3)
+ VOID(printf("code[0x%04x]: 0x%s bits: %2u bin: %s\n", i,
+ hexdigits(huff_tree->code[i]), huff_tree->code_len[i],
+ bindigits(huff_tree->code[i], huff_tree->code_len[i])));
+
+ /* Check that the encode table decodes correctly. */
+ code= 0;
+ bits= 0;
+ idx= 0;
+ DBUG_EXECUTE_IF("forcechkerr1", len--;);
+ DBUG_EXECUTE_IF("forcechkerr2", bits= 8 * sizeof(code););
+ DBUG_EXECUTE_IF("forcechkerr3", idx= length;);
+ for (;;)
+ {
+ if (! len)
+ {
+ VOID(fflush(stdout));
+ VOID(fprintf(stderr, "error: code 0x%s with %u bits not found\n",
+ hexdigits(huff_tree->code[i]), huff_tree->code_len[i]));
+ errors++;
+ break;
+ }
+ code<<= 1;
+ code|= (huff_tree->code[i] >> (--len)) & 1;
+ bits++;
+ if (bits > 8 * sizeof(code))
+ {
+ VOID(fflush(stdout));
+ VOID(fprintf(stderr, "error: Huffman code too long: %u/%u\n",
+ bits, 8 * sizeof(code)));
+ errors++;
+ break;
+ }
+ idx+= code & 1;
+ if (idx >= length)
+ {
+ VOID(fflush(stdout));
+ VOID(fprintf(stderr, "error: illegal tree offset: %u/%u\n",
+ idx, length));
+ errors++;
+ break;
+ }
+ if (packed_tree[idx] & IS_OFFSET)
+ idx+= packed_tree[idx] & ~IS_OFFSET;
+ else
+ break; /* Hit a leaf. This contains the result value. */
+ }
+ if (errors)
+ break;
+
+ DBUG_EXECUTE_IF("forcechkerr4", packed_tree[idx]++;);
+ if (packed_tree[idx] != i)
+ {
+ VOID(fflush(stdout));
+ VOID(fprintf(stderr, "error: decoded value 0x%04x should be: 0x%04x\n",
+ packed_tree[idx], i));
+ errors++;
+ break;
+ }
+ } /*end for (codes)*/
+ if (errors)
+ break;
+
+ /* Write column values in case of distinct column value compression. */
if (huff_tree->counts->tree_buff)
{
for (i=0 ; i < int_length ; i++)
- write_bits((uint) (uchar) huff_tree->counts->tree_buff[i],8);
+ {
+ write_bits((ulonglong) (uchar) huff_tree->counts->tree_buff[i], 8);
+ DBUG_PRINT("info", ("column_values[0x%04x]: 0x%02x",
+ i, (uchar) huff_tree->counts->tree_buff[i]));
+ if (verbose >= 3)
+ VOID(printf("column_values[0x%04x]: 0x%02x\n",
+ i, (uchar) huff_tree->counts->tree_buff[i]));
+ }
}
flush_bits();
}
+ DBUG_PRINT("info", (""));
+ if (verbose >= 2)
+ VOID(printf("\n"));
my_afree((gptr) packed_tree);
+ if (errors)
+ {
+ VOID(fprintf(stderr, "Error: Generated decode trees are corrupt. Stop.\n"));
+ return 0;
+ }
return elements;
}
@@ -1627,23 +2348,43 @@ static uint *make_offset_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element,
uint *prev_offset;
prev_offset= offset;
+ /*
+ 'a.leaf.null' takes the same place as 'a.nod.left'. If this is null,
+ then there is no left child and, hence no right child either. This
+ is a property of a binary tree. An element is either a node with two
+ childs, or a leaf without childs.
+
+ The current element is always a node with two childs. Go left first.
+ */
if (!element->a.nod.left->a.leaf.null)
{
- offset[0] =(uint) element->a.nod.left->a.leaf.element_nr;
+ /* Store the byte code or the index of the column value. */
+ prev_offset[0] =(uint) element->a.nod.left->a.leaf.element_nr;
offset+=2;
}
else
{
+ /*
+ Recursively traverse the tree to the left. Mark it as an offset to
+ another tree node (in contrast to a byte code or column value index).
+ */
prev_offset[0]= IS_OFFSET+2;
offset=make_offset_code_tree(huff_tree,element->a.nod.left,offset+2);
}
+
+ /* Now, check the right child. */
if (!element->a.nod.right->a.leaf.null)
{
+ /* Store the byte code or the index of the column value. */
prev_offset[1]=element->a.nod.right->a.leaf.element_nr;
return offset;
}
else
{
+ /*
+ Recursively traverse the tree to the right. Mark it as an offset to
+ another tree node (in contrast to a byte code or column value index).
+ */
uint temp=(uint) (offset-prev_offset-1);
prev_offset[1]= IS_OFFSET+ temp;
if (huff_tree->max_offset < temp)
@@ -1670,6 +2411,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length,
intervall,field_length,max_pack_length,pack_blob_length;
my_off_t record_count;
+ char llbuf[32];
ulong length,pack_length;
byte *record,*pos,*end_pos,*record_pos,*start_pos;
HUFF_COUNTS *count,*end_count;
@@ -1678,12 +2420,23 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
uint pack_version= (uint) isam_file->s->pack.version;
DBUG_ENTER("compress_isam_file");
+ /* Allocate a buffer for the records (excluding blobs). */
if (!(record=(byte*) my_alloca(isam_file->s->base.reclength)))
return -1;
+
end_count=huff_counts+isam_file->s->base.fields;
min_record_length= (uint) ~0;
max_record_length=0;
+ /*
+ Calculate the maximum number of bits required to pack the records.
+ Remember to understand 'max_zero_fill' as 'min_zero_fill'.
+ The tree height determines the maximum number of bits per value.
+ Some fields skip leading or trailing spaces or zeroes. The skipped
+ number of bytes is encoded by 'length_bits' bits.
+ Empty blobs and varchar are encoded with a single 1 bit. Other blobs
+ and varchar get a leading 0 bit.
+ */
for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++)
{
if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL))
@@ -1702,13 +2455,15 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
(huff_counts[i].field_length - huff_counts[i].max_zero_fill)*
huff_counts[i].tree->height+huff_counts[i].length_bits;
}
- max_calc_length/=8;
+ max_calc_length= (max_calc_length + 7) / 8;
pack_ref_length= calc_pack_length(pack_version, max_calc_length);
record_count=0;
+ /* 'max_blob_length' is the max length of all blobs of a record. */
pack_blob_length= isam_file->s->base.blobs ?
calc_pack_length(pack_version, mrg->max_blob_length) : 0;
max_pack_length=pack_ref_length+pack_blob_length;
+ DBUG_PRINT("fields", ("==="));
mrg_reset(mrg);
while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE)
{
@@ -1724,15 +2479,29 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
end_pos=start_pos+(field_length=count->field_length);
tree=count->tree;
+ DBUG_PRINT("fields", ("column: %3lu type: %2u pack: %2u zero: %4u "
+ "lbits: %2u tree: %2u length: %4u",
+ (ulong) (count - huff_counts + 1),
+ count->field_type,
+ count->pack_type, count->max_zero_fill,
+ count->length_bits, count->tree->tree_number,
+ count->field_length));
+
+ /* Check if the column contains spaces only. */
if (count->pack_type & PACK_TYPE_SPACE_FIELDS)
{
for (pos=start_pos ; *pos == ' ' && pos < end_pos; pos++) ;
if (pos == end_pos)
{
+ DBUG_PRINT("fields",
+ ("PACK_TYPE_SPACE_FIELDS spaces only, bits: 1"));
+ DBUG_PRINT("fields", ("---"));
write_bits(1,1);
start_pos=end_pos;
continue;
}
+ DBUG_PRINT("fields",
+ ("PACK_TYPE_SPACE_FIELDS not only spaces, bits: 1"));
write_bits(0,1);
}
end_pos-=count->max_zero_fill;
@@ -1742,65 +2511,129 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
case FIELD_SKIP_ZERO:
if (!memcmp((byte*) start_pos,zero_string,field_length))
{
+ DBUG_PRINT("fields", ("FIELD_SKIP_ZERO zeroes only, bits: 1"));
write_bits(1,1);
start_pos=end_pos;
break;
}
+ DBUG_PRINT("fields", ("FIELD_SKIP_ZERO not only zeroes, bits: 1"));
write_bits(0,1);
/* Fall through */
case FIELD_NORMAL:
+ DBUG_PRINT("fields", ("FIELD_NORMAL %lu bytes",
+ (ulong) (end_pos - start_pos)));
for ( ; start_pos < end_pos ; start_pos++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *start_pos,
+ hexdigits(tree->code[(uchar) *start_pos]),
+ (uint) tree->code_len[(uchar) *start_pos],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint) tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
+ }
break;
case FIELD_SKIP_ENDSPACE:
for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ;
- length=(uint) (end_pos-pos);
+ length= (ulong) (end_pos - pos);
if (count->pack_type & PACK_TYPE_SELECTED)
{
if (length > count->min_space)
{
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_ENDSPACE more than min_space, bits: 1"));
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u",
+ length, field_length, count->length_bits));
write_bits(1,1);
write_bits(length,count->length_bits);
}
else
{
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_ENDSPACE not more than min_space, "
+ "bits: 1"));
write_bits(0,1);
pos=end_pos;
}
}
else
+ {
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u",
+ length, field_length, count->length_bits));
write_bits(length,count->length_bits);
+ }
+ /* Encode all significant bytes. */
+ DBUG_PRINT("fields", ("FIELD_SKIP_ENDSPACE %lu bytes",
+ (ulong) (pos - start_pos)));
for ( ; start_pos < pos ; start_pos++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *start_pos,
+ hexdigits(tree->code[(uchar) *start_pos]),
+ (uint) tree->code_len[(uchar) *start_pos],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint) tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
+ }
start_pos=end_pos;
break;
case FIELD_SKIP_PRESPACE:
for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ;
- length=(uint) (pos-start_pos);
+ length= (ulong) (pos - start_pos);
if (count->pack_type & PACK_TYPE_SELECTED)
{
if (length > count->min_space)
{
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_PRESPACE more than min_space, bits: 1"));
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u",
+ length, field_length, count->length_bits));
write_bits(1,1);
write_bits(length,count->length_bits);
}
else
{
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_PRESPACE not more than min_space, "
+ "bits: 1"));
pos=start_pos;
write_bits(0,1);
}
}
else
+ {
+ DBUG_PRINT("fields",
+ ("FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u",
+ length, field_length, count->length_bits));
write_bits(length,count->length_bits);
+ }
+ /* Encode all significant bytes. */
+ DBUG_PRINT("fields", ("FIELD_SKIP_PRESPACE %lu bytes",
+ (ulong) (end_pos - start_pos)));
for (start_pos=pos ; start_pos < end_pos ; start_pos++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *start_pos,
+ hexdigits(tree->code[(uchar) *start_pos]),
+ (uint) tree->code_len[(uchar) *start_pos],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint) tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
+ }
break;
case FIELD_CONSTANT:
case FIELD_ZERO:
case FIELD_CHECK:
+ DBUG_PRINT("fields", ("FIELD_CONSTANT/ZERO/CHECK"));
start_pos=end_pos;
break;
case FIELD_INTERVALL:
@@ -1808,6 +2641,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
pos=(byte*) tree_search(&count->int_tree, start_pos,
count->int_tree.custom_arg);
intervall=(uint) (pos - count->tree_buff)/field_length;
+ DBUG_PRINT("fields", ("FIELD_INTERVALL"));
+ DBUG_PRINT("fields", ("index: %4u code: 0x%s bits: %2u",
+ intervall, hexdigits(tree->code[intervall]),
+ (uint) tree->code_len[intervall]));
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
start_pos=end_pos;
break;
@@ -1816,21 +2653,36 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
ulong blob_length=_mi_calc_blob_length(field_length-
mi_portable_sizeof_char_ptr,
start_pos);
+ /* Empty blobs are encoded with a single 1 bit. */
if (!blob_length)
{
- write_bits(1,1); /* Empty blob */
+ DBUG_PRINT("fields", ("FIELD_BLOB empty, bits: 1"));
+ write_bits(1,1);
}
else
{
byte *blob,*blob_end;
+ DBUG_PRINT("fields", ("FIELD_BLOB not empty, bits: 1"));
write_bits(0,1);
+ /* Write the blob length. */
+ DBUG_PRINT("fields", ("FIELD_BLOB %lu bytes, bits: %2u",
+ blob_length, count->length_bits));
write_bits(blob_length,count->length_bits);
memcpy_fixed(&blob,end_pos-mi_portable_sizeof_char_ptr,
sizeof(char*));
blob_end=blob+blob_length;
+ /* Encode the blob bytes. */
for ( ; blob < blob_end ; blob++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *blob, hexdigits(tree->code[(uchar) *blob]),
+ (uint) tree->code_len[(uchar) *blob],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint)tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *blob],
(uint) tree->code_len[(uchar) *blob]);
+ }
tot_blob_length+=blob_length;
}
start_pos= end_pos;
@@ -1838,19 +2690,37 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
}
case FIELD_VARCHAR:
{
- ulong col_length= uint2korr(start_pos);
+ uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
+ ulong col_length= (pack_length == 1 ? (uint) *(uchar*) start_pos :
+ uint2korr(start_pos));
+ /* Empty varchar are encoded with a single 1 bit. */
if (!col_length)
{
+ DBUG_PRINT("fields", ("FIELD_VARCHAR empty, bits: 1"));
write_bits(1,1); /* Empty varchar */
}
else
{
- byte *end=start_pos+2+col_length;
+ byte *end=start_pos+pack_length+col_length;
+ DBUG_PRINT("fields", ("FIELD_VARCHAR not empty, bits: 1"));
write_bits(0,1);
+ /* Write the varchar length. */
+ DBUG_PRINT("fields", ("FIELD_VARCHAR %lu bytes, bits: %2u",
+ col_length, count->length_bits));
write_bits(col_length,count->length_bits);
- for (start_pos+=2 ; start_pos < end ; start_pos++)
+ /* Encode the varchar bytes. */
+ for (start_pos+=pack_length ; start_pos < end ; start_pos++)
+ {
+ DBUG_PRINT("fields",
+ ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
+ (uchar) *start_pos,
+ hexdigits(tree->code[(uchar) *start_pos]),
+ (uint) tree->code_len[(uchar) *start_pos],
+ bindigits(tree->code[(uchar) *start_pos],
+ (uint)tree->code_len[(uchar) *start_pos])));
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
+ }
}
start_pos= end_pos;
break;
@@ -1859,13 +2729,18 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
abort(); /* Impossible */
}
start_pos+=count->max_zero_fill;
+ DBUG_PRINT("fields", ("---"));
}
flush_bits();
- length=(ulong) (file_buffer.pos-record_pos)-max_pack_length;
+ length=(ulong) ((byte*) file_buffer.pos - record_pos) - max_pack_length;
pack_length= save_pack_length(pack_version, record_pos, length);
if (pack_blob_length)
pack_length+= save_pack_length(pack_version, record_pos + pack_length,
tot_blob_length);
+ DBUG_PRINT("fields", ("record: %lu length: %lu blob-length: %lu "
+ "length-bytes: %lu", (ulong) record_count, length,
+ tot_blob_length, pack_length));
+ DBUG_PRINT("fields", ("==="));
/* Correct file buffer if the header was smaller */
if (pack_length != max_pack_length)
@@ -1877,9 +2752,11 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
min_record_length=(uint) length;
if (length > (ulong) max_record_length)
max_record_length=(uint) length;
- if (write_loop && ++record_count % WRITE_COUNT == 0)
+ record_count++;
+ if (write_loop && record_count % WRITE_COUNT == 0)
{
- printf("%lu\r",(ulong) record_count); VOID(fflush(stdout));
+ VOID(printf("%lu\r", (ulong) record_count));
+ VOID(fflush(stdout));
}
}
else if (error != HA_ERR_RECORD_DELETED)
@@ -1889,8 +2766,11 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
error=0;
else
{
- fprintf(stderr,"%s: Got error %d reading records\n",my_progname,error);
+ VOID(fprintf(stderr, "%s: Got error %d reading records\n",
+ my_progname, error));
}
+ if (verbose >= 2)
+ VOID(printf("wrote %s records.\n", llstr((longlong) record_count, llbuf)));
my_afree((gptr) record);
mrg->ref_length=max_pack_length;
@@ -1930,7 +2810,7 @@ static void init_file_buffer(File file, pbool read_buffer)
file_buffer.pos=file_buffer.buffer;
file_buffer.bits=BITS_SAVED;
}
- file_buffer.current_byte=0;
+ file_buffer.bitbucket= 0;
}
@@ -1973,7 +2853,8 @@ static int flush_buffer(ulong neaded_length)
tmp=my_realloc(file_buffer.buffer, neaded_length,MYF(MY_WME));
if (!tmp)
return 1;
- file_buffer.pos= tmp + (ulong) (file_buffer.pos - file_buffer.buffer);
+ file_buffer.pos= ((uchar*) tmp +
+ (ulong) (file_buffer.pos - file_buffer.buffer));
file_buffer.buffer=tmp;
file_buffer.end=tmp+neaded_length-8;
}
@@ -1988,68 +2869,59 @@ static void end_file_buffer(void)
/* output `bits` low bits of `value' */
-static void write_bits (register ulong value, register uint bits)
+static void write_bits(register ulonglong value, register uint bits)
{
- if ((file_buffer.bits-=(int) bits) >= 0)
+ DBUG_ASSERT(((bits < 8 * sizeof(value)) && ! (value >> bits)) ||
+ (bits == 8 * sizeof(value)));
+
+ if ((file_buffer.bits-= (int) bits) >= 0)
{
- file_buffer.current_byte|=value << file_buffer.bits;
+ file_buffer.bitbucket|= value << file_buffer.bits;
}
else
{
- reg3 uint byte_buff;
+ reg3 ulonglong bit_buffer;
bits= (uint) -file_buffer.bits;
- DBUG_ASSERT(bits <= 8 * sizeof(value));
- byte_buff= (file_buffer.current_byte |
- ((bits != 8 * sizeof(value)) ? (uint) (value >> bits) : 0));
-#if BITS_SAVED == 32
- *file_buffer.pos++= (byte) (byte_buff >> 24) ;
- *file_buffer.pos++= (byte) (byte_buff >> 16) ;
+ bit_buffer= (file_buffer.bitbucket |
+ ((bits != 8 * sizeof(value)) ? (value >> bits) : 0));
+#if BITS_SAVED == 64
+ *file_buffer.pos++= (uchar) (bit_buffer >> 56);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 48);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 40);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 32);
#endif
- *file_buffer.pos++= (byte) (byte_buff >> 8) ;
- *file_buffer.pos++= (byte) byte_buff;
+ *file_buffer.pos++= (uchar) (bit_buffer >> 24);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 16);
+ *file_buffer.pos++= (uchar) (bit_buffer >> 8);
+ *file_buffer.pos++= (uchar) (bit_buffer);
- DBUG_ASSERT(bits <= 8 * sizeof(ulong));
if (bits != 8 * sizeof(value))
- value&= (((ulong) 1) << bits) - 1;
-#if BITS_SAVED == 16
- if (bits >= sizeof(uint))
- {
- bits-=8;
- *file_buffer.pos++= (uchar) (value >> bits);
- value&= (1 << bits)-1;
- if (bits >= sizeof(uint))
- {
- bits-=8;
- *file_buffer.pos++= (uchar) (value >> bits);
- value&= (1 << bits)-1;
- }
- }
-#endif
+ value&= (((ulonglong) 1) << bits) - 1;
if (file_buffer.pos >= file_buffer.end)
VOID(flush_buffer(~ (ulong) 0));
file_buffer.bits=(int) (BITS_SAVED - bits);
- file_buffer.current_byte=(uint) (value << (BITS_SAVED - bits));
+ file_buffer.bitbucket= value << (BITS_SAVED - bits);
}
return;
}
/* Flush bits in bit_buffer to buffer */
-static void flush_bits (void)
+static void flush_bits(void)
{
- uint bits,byte_buff;
+ int bits;
+ ulonglong bit_buffer;
- bits=(file_buffer.bits) & ~7;
- byte_buff = file_buffer.current_byte >> bits;
- bits=BITS_SAVED - bits;
+ bits= file_buffer.bits & ~7;
+ bit_buffer= file_buffer.bitbucket >> bits;
+ bits= BITS_SAVED - bits;
while (bits > 0)
{
- bits-=8;
- *file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ;
+ bits-= 8;
+ *file_buffer.pos++= (uchar) (bit_buffer >> bits);
}
- file_buffer.bits=BITS_SAVED;
- file_buffer.current_byte=0;
- return;
+ file_buffer.bits= BITS_SAVED;
+ file_buffer.bitbucket= 0;
}
@@ -2074,7 +2946,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
share->state.dellink= HA_OFFSET_ERROR;
share->state.split=(ha_rows) mrg->records;
share->state.version=(ulong) time((time_t*) 0);
- if (share->state.key_map != (ULL(1) << share->base.keys) - 1)
+ if (! mi_is_all_keys_active(share->state.key_map, share->base.keys))
{
/*
Some indexes are disabled, cannot use current key_file_length value
@@ -2088,7 +2960,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
original file so "myisamchk -rq" can use this value (this is necessary
because index size cannot be easily calculated for fulltext keys)
*/
- share->state.key_map=0;
+ mi_clear_all_keys_active(share->state.key_map);
for (key=0 ; key < share->base.keys ; key++)
share->state.key_root[key]= HA_OFFSET_ERROR;
for (key=0 ; key < share->state.header.max_block_size ; key++)
@@ -2128,7 +3000,7 @@ static int save_state_mrg(File file,PACK_MRG_INFO *mrg,my_off_t new_length,
}
state.dellink= HA_OFFSET_ERROR;
state.version=(ulong) time((time_t*) 0);
- state.key_map=0;
+ mi_clear_all_keys_active(state.key_map);
state.checksum=crc;
if (isam_file->s->base.keys)
isamchk_neaded=1;
@@ -2197,3 +3069,131 @@ static int mrg_close(PACK_MRG_INFO *mrg)
my_free((gptr) mrg->file,MYF(0));
return error;
}
+
+
+#if !defined(DBUG_OFF)
+/*
+ Fake the counts to get big Huffman codes.
+
+ SYNOPSIS
+ fakebigcodes()
+ huff_counts A pointer to the counts array.
+ end_count A pointer past the counts array.
+
+ DESCRIPTION
+
+ Huffman coding works by removing the two least frequent values from
+ the list of values and add a new value with the sum of their
+ incidences in a loop until only one value is left. Every time a
+ value is reused for a new value, it gets one more bit for its
+ encoding. Hence, the least frequent values get the longest codes.
+
+ To get a maximum code length for a value, two of the values must
+ have an incidence of 1. As their sum is 2, the next infrequent value
+ must have at least an incidence of 2, then 4, 8, 16 and so on. This
+ means that one needs 2**n bytes (values) for a code length of n
+ bits. However, using more distinct values forces the use of longer
+ codes, or reaching the code length with less total bytes (values).
+
+ To get 64(32)-bit codes, I sort the counts by decreasing incidence.
+ I assign counts of 1 to the two most frequent values, a count of 2
+ for the next one, then 4, 8, and so on until 2**64-1(2**30-1). All
+ the remaining values get 1. That way every possible byte has an
+ assigned code, though not all codes are used if not all byte values
+ are present in the column.
+
+ This strategy would work with distinct column values too, but
+ requires that at least 64(32) values are present. To make things
+ easier here, I cancel all distinct column values and force byte
+ compression for all columns.
+
+ RETURN
+ void
+*/
+
+static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count)
+{
+ HUFF_COUNTS *count;
+ my_off_t *cur_count_p;
+ my_off_t *end_count_p;
+ my_off_t **cur_sort_p;
+ my_off_t **end_sort_p;
+ my_off_t *sort_counts[256];
+ my_off_t total;
+ DBUG_ENTER("fakebigcodes");
+
+ for (count= huff_counts; count < end_count; count++)
+ {
+ /*
+ Remove distinct column values.
+ */
+ if (huff_counts->tree_buff)
+ {
+ my_free((gptr) huff_counts->tree_buff, MYF(0));
+ delete_tree(&huff_counts->int_tree);
+ huff_counts->tree_buff= NULL;
+ DBUG_PRINT("fakebigcodes", ("freed distinct column values"));
+ }
+
+ /*
+ Sort counts by decreasing incidence.
+ */
+ cur_count_p= count->counts;
+ end_count_p= cur_count_p + 256;
+ cur_sort_p= sort_counts;
+ while (cur_count_p < end_count_p)
+ *(cur_sort_p++)= cur_count_p++;
+ (void) qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp);
+
+ /*
+ Assign faked counts.
+ */
+ cur_sort_p= sort_counts;
+#if SIZEOF_LONG_LONG > 4
+ end_sort_p= sort_counts + 8 * sizeof(ulonglong) - 1;
+#else
+ end_sort_p= sort_counts + 8 * sizeof(ulonglong) - 2;
+#endif
+ /* Most frequent value gets a faked count of 1. */
+ **(cur_sort_p++)= 1;
+ total= 1;
+ while (cur_sort_p < end_sort_p)
+ {
+ **(cur_sort_p++)= total;
+ total<<= 1;
+ }
+ /* Set the last value. */
+ **(cur_sort_p++)= --total;
+ /*
+ Set the remaining counts.
+ */
+ end_sort_p= sort_counts + 256;
+ while (cur_sort_p < end_sort_p)
+ **(cur_sort_p++)= 1;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Compare two counts for reverse sorting.
+
+ SYNOPSIS
+ fakecmp()
+ count1 One count.
+ count2 Another count.
+
+ RETURN
+ 1 count1 < count2
+ 0 count1 == count2
+ -1 count1 > count2
+*/
+
+static int fakecmp(my_off_t **count1, my_off_t **count2)
+{
+ return ((**count1 < **count2) ? 1 :
+ (**count1 > **count2) ? -1 : 0);
+}
+#endif
+
+
diff --git a/myisam/rt_split.c b/myisam/rt_split.c
index 664dd2c75e3..31a7d09ab4f 100644
--- a/myisam/rt_split.c
+++ b/myisam/rt_split.c
@@ -257,19 +257,17 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
int n_dim;
uchar *source_cur, *cur1, *cur2;
uchar *new_page;
- int err_code = 0;
-
- uint nod_flag = mi_test_if_nod(page);
- uint full_length = key_length + (nod_flag ? nod_flag :
- info->s->base.rec_reflength);
-
- int max_keys = (mi_getint(page)-2) / (full_length);
+ int err_code= 0;
+ uint nod_flag= mi_test_if_nod(page);
+ uint full_length= key_length + (nod_flag ? nod_flag :
+ info->s->base.rec_reflength);
+ int max_keys= (mi_getint(page)-2) / (full_length);
n_dim = keyinfo->keysegs / 2;
if (!(coord_buf= (double*) my_alloca(n_dim * 2 * sizeof(double) *
- (max_keys + 1 + 4) +
- sizeof(SplitStruct) * (max_keys + 1))))
+ (max_keys + 1 + 4) +
+ sizeof(SplitStruct) * (max_keys + 1))))
return -1;
task= (SplitStruct *)(coord_buf + n_dim * 2 * (max_keys + 1 + 4));
@@ -312,8 +310,7 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
cur1 = rt_PAGE_FIRST_KEY(page, nod_flag);
cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag);
- n1 = 0;
- n2 = 0;
+ n1= n2 = 0;
for (cur = task; cur < stop; ++cur)
{
uchar *to;
diff --git a/myisam/sort.c b/myisam/sort.c
index e8cd9938e42..fabd713ef45 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -479,7 +479,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
}
if (!got_error)
{
- share->state.key_map|=(ulonglong) 1 << sinfo->key;
+ mi_set_key_active(share->state.key_map, sinfo->key);
if (param->testflag & T_STATISTICS)
update_key_parts(sinfo->keyinfo, rec_per_key_part,
sinfo->unique, (ulonglong) info->state->records);
@@ -862,7 +862,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
uchar *strpos;
BUFFPEK *buffpek,**refpek;
QUEUE queue;
- volatile my_bool *killed= killed_ptr(info->sort_info->param);
+ volatile int *killed= killed_ptr(info->sort_info->param);
+
DBUG_ENTER("merge_buffers");
count=error=0;
diff --git a/myisammrg/Makefile.am b/myisammrg/Makefile.am
index 3cd8cfdedea..14e3295c1ae 100644
--- a/myisammrg/Makefile.am
+++ b/myisammrg/Makefile.am
@@ -14,8 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
pkglib_LIBRARIES = libmyisammrg.a
noinst_HEADERS = myrg_def.h
libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index e7abcd3fc95..9b0db5774f5 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -32,7 +32,7 @@ endif
benchdir_root= $(prefix)
testdir = $(benchdir_root)/mysql-test
-EXTRA_SCRIPTS = mysql-test-run.sh mysql-test-run.pl install_test_db.sh
+EXTRA_SCRIPTS = mysql-test-run.sh mysql-test-run.pl install_test_db.sh valgrind.supp
EXTRA_DIST = $(EXTRA_SCRIPTS)
test_SCRIPTS = mysql-test-run install_test_db
test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem \
@@ -48,17 +48,22 @@ mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c my_create_tables.c
dist-hook:
mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \
$(distdir)/std_data $(distdir)/lib
- $(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t
+ -$(INSTALL_DATA) $(srcdir)/t/*.def $(distdir)/t
+ $(INSTALL_DATA) $(srcdir)/t/*.test $(distdir)/t
+ -$(INSTALL_DATA) $(srcdir)/t/*.imtest $(distdir)/t
+ $(INSTALL_DATA) $(srcdir)/t/*.sql $(distdir)/t
+ -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(distdir)/t
+ $(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t
$(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include
$(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r
$(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data
+ $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(distdir)/lib
$(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib
-
install-data-local:
$(mkinstalldirs) \
$(DESTDIR)$(testdir)/t \
@@ -67,7 +72,11 @@ install-data-local:
$(DESTDIR)$(testdir)/std_data \
$(DESTDIR)$(testdir)/lib
$(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir)
+ -$(INSTALL_DATA) $(srcdir)/t/*.def $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.test $(DESTDIR)$(testdir)/t
+ -$(INSTALL_DATA) $(srcdir)/t/*.imtest $(DESTDIR)$(testdir)/t
+ $(INSTALL_DATA) $(srcdir)/t/*.sql $(DESTDIR)$(testdir)/t
+ -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.slave-mi $(DESTDIR)$(testdir)/t
@@ -79,6 +88,7 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data
+ $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib
$(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib
diff --git a/mysql-test/create-test-result b/mysql-test/create-test-result
index b9be2300976..ad19cdf08a1 100755
--- a/mysql-test/create-test-result
+++ b/mysql-test/create-test-result
@@ -6,7 +6,7 @@
# to start mysqld yourself and run mysqltest -r
RESULT_DIR=r
-if [ -z $EDITOR] ; then
+if [ -z "$EDITOR" ] ; then
EDITOR=vi
fi
@@ -24,7 +24,7 @@ function usage()
test_name=$1
-[ -z $test_name ] && usage
+[ -z "$test_name" ] && usage
result_file=$RESULT_DIR/$test_name.result
reject_file=$RESULT_DIR/$test_name.reject
diff --git a/mysql-test/include/big_test.inc b/mysql-test/include/big_test.inc
new file mode 100644
index 00000000000..6b149540c96
--- /dev/null
+++ b/mysql-test/include/big_test.inc
@@ -0,0 +1,4 @@
+--require r/big_test.require
+disable_query_log;
+eval select $BIG_TEST as using_big_test;
+enable_query_log;
diff --git a/mysql-test/include/federated.inc b/mysql-test/include/federated.inc
new file mode 100644
index 00000000000..1c53b9ed2c5
--- /dev/null
+++ b/mysql-test/include/federated.inc
@@ -0,0 +1,21 @@
+--source ./include/have_federated_db.inc
+
+source ./include/master-slave.inc;
+
+# remote table creation
+
+connection slave;
+--replicate-ignore-db=federated
+stop slave;
+
+--disable_warnings
+# at this point, we are connected to master
+DROP DATABASE IF EXISTS federated;
+--enable_warnings
+CREATE DATABASE federated;
+
+connection master;
+--disable_warnings
+DROP DATABASE IF EXISTS federated;
+--enable_warnings
+CREATE DATABASE federated;
diff --git a/mysql-test/include/federated_cleanup.inc b/mysql-test/include/federated_cleanup.inc
new file mode 100644
index 00000000000..17a6e1e5100
--- /dev/null
+++ b/mysql-test/include/federated_cleanup.inc
@@ -0,0 +1,11 @@
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
+--enable_warnings
+
+connection slave;
+--disable_warnings
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
+--enable_warnings
diff --git a/mysql-test/include/have_eucjpms.inc b/mysql-test/include/have_eucjpms.inc
new file mode 100644
index 00000000000..a5e1a5ac547
--- /dev/null
+++ b/mysql-test/include/have_eucjpms.inc
@@ -0,0 +1,4 @@
+-- require r/have_eucjpms.require
+disable_query_log;
+show collation like "eucjpms_japanese_ci";
+enable_query_log;
diff --git a/mysql-test/include/have_federated_db.inc b/mysql-test/include/have_federated_db.inc
new file mode 100644
index 00000000000..e4cf1366fda
--- /dev/null
+++ b/mysql-test/include/have_federated_db.inc
@@ -0,0 +1,4 @@
+-- require r/have_federated_db.require
+disable_query_log;
+show variables like "have_federated_engine";
+enable_query_log;
diff --git a/mysql-test/include/have_isam.inc b/mysql-test/include/have_isam.inc
deleted file mode 100644
index 830170c921f..00000000000
--- a/mysql-test/include/have_isam.inc
+++ /dev/null
@@ -1,4 +0,0 @@
--- require r/have_isam.require
-disable_query_log;
-show variables like "have_isam";
-enable_query_log;
diff --git a/mysql-test/include/have_lowercase0.inc b/mysql-test/include/have_lowercase0.inc
index f967c18928b..8d3ae02f61e 100644
--- a/mysql-test/include/have_lowercase0.inc
+++ b/mysql-test/include/have_lowercase0.inc
@@ -1,4 +1,4 @@
--require r/lowercase0.require
---disable_query_log;
+--disable_query_log
show variables like "lower_case_%";
---enable_query_log;
+--enable_query_log
diff --git a/mysql-test/include/have_ndb.inc b/mysql-test/include/have_ndb.inc
index 9b85197abe8..28fcf18cb16 100644
--- a/mysql-test/include/have_ndb.inc
+++ b/mysql-test/include/have_ndb.inc
@@ -3,6 +3,4 @@
disable_query_log;
show variables like "have_ndbcluster";
enable_query_log;
-#connect (server1,127.0.0.1,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
-#connect (server2,127.0.0.1,root,,test,$MASTER_MYPORT1,$MASTER_MYSOCK1);
-#connection server1;
+
diff --git a/mysql-test/include/ndb_default_cluster.inc b/mysql-test/include/ndb_default_cluster.inc
new file mode 100644
index 00000000000..2f900b6a0b4
--- /dev/null
+++ b/mysql-test/include/ndb_default_cluster.inc
@@ -0,0 +1,4 @@
+-- require r/ndb_default_cluster.require
+disable_query_log;
+show status like "Ndb_connected_host";
+enable_query_log;
diff --git a/mysql-test/include/ps_conv.inc b/mysql-test/include/ps_conv.inc
index 348526202ec..0dd819f6e62 100644
--- a/mysql-test/include/ps_conv.inc
+++ b/mysql-test/include/ps_conv.inc
@@ -104,7 +104,7 @@ drop table t5 ;
# 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,
+# c17 year, c18 tinyint, c19 bool, c20 char,
# c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
# c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
# c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
diff --git a/mysql-test/include/ps_create.inc b/mysql-test/include/ps_create.inc
index dfc9c494b46..b2a6fc4b920 100644
--- a/mysql-test/include/ps_create.inc
+++ b/mysql-test/include/ps_create.inc
@@ -33,8 +33,8 @@ eval create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
- c17 year, c18 bit, c19 bool, c20 char,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
+ c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
diff --git a/mysql-test/include/ps_modify.inc b/mysql-test/include/ps_modify.inc
index eb6820934f3..633c317f4b2 100644
--- a/mysql-test/include/ps_modify.inc
+++ b/mysql-test/include/ps_modify.inc
@@ -59,7 +59,6 @@ execute stmt1 using @arg00;
select a,b from t1 where b=@arg00;
## truncate a table
---error 1295
prepare stmt1 from 'truncate table t1' ;
@@ -175,11 +174,8 @@ 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 ?';
+prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
+execute stmt1 using @arg00;
--disable_query_log
select '------ insert tests ------' as test_sequence ;
diff --git a/mysql-test/include/ps_query.inc b/mysql-test/include/ps_query.inc
index 9a413bff2f3..27a86f88231 100644
--- a/mysql-test/include/ps_query.inc
+++ b/mysql-test/include/ps_query.inc
@@ -300,10 +300,8 @@ set @arg00=1;
prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
-# currently (May 2004, Version 4.1) it is impossible
--- error 1064
-prepare stmt1 from ' select a,b from t1
-limit ? ';
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
+execute stmt1 using @arg00;
##### parameter used in many places
set @arg00='b' ;
diff --git a/mysql-test/include/rpl_stmt_seq.inc b/mysql-test/include/rpl_stmt_seq.inc
index d56ee02e33c..3c91505d0d6 100644
--- a/mysql-test/include/rpl_stmt_seq.inc
+++ b/mysql-test/include/rpl_stmt_seq.inc
@@ -7,7 +7,7 @@
###############################################################
# Debug options : To debug this test script
###############################################################
-let $showbinlog= 0;
+let $show_binlog= 0;
let $manipulate= 1;
######## The typical test sequence
diff --git a/mysql-test/include/show_msg.inc b/mysql-test/include/show_msg.inc
new file mode 100755
index 00000000000..659dce14686
--- /dev/null
+++ b/mysql-test/include/show_msg.inc
@@ -0,0 +1,25 @@
+#### include/show_msg.inc
+#
+# This file writes the value set in @message into the
+# a protocol file as part of executing a test sequence
+#
+# Usage:
+# Add the following to any *.test file:
+# :
+# let $message= <value>;
+# --source include/show_msg.inc
+# :
+#
+# Attention:
+# - Please do not write any spaces between $message and the "=", because the
+# assignment will not work.
+# - Be careful with single quotes. They must be escaped like "''" or "\'".
+#
+# "include/show_msg80.inc" contains a detailed description and examples.
+
+--disable_query_log
+eval SET @utf8_message = CONVERT('$message' using utf8);
+select @utf8_message as ""
+union
+select repeat(CONVERT('-' using utf8),char_length(@utf8_message));
+--enable_query_log
diff --git a/mysql-test/include/show_msg80.inc b/mysql-test/include/show_msg80.inc
new file mode 100755
index 00000000000..42fb35edbcc
--- /dev/null
+++ b/mysql-test/include/show_msg80.inc
@@ -0,0 +1,118 @@
+#### include/show_msg80.inc
+#
+# This file writes the value set in @message into the a protocol file as part
+# of executing a test sequence with a dash line that is fixed on 80 characters.
+#
+# This can be used in the case of long messages, multi line messages that
+# exceed 80 or if an 80 char line is desired for short messages.
+#
+# Usage:
+# Add the following to any *.test file:
+# :
+# let $message= <value>;
+# --source include/show_msg80.inc
+# :
+#
+# Attention:
+# - Please do not write any spaces between $message and the "=", because the
+# assignment will not work.
+# - Be careful with single quotes within the value. They must be escaped like
+# "''" or "\'".
+# - Do not keep the value between single quotes.
+#
+#
+# Content of "$message" and protocol output depending on the assignment:
+# ----------------------------------------------------------------------
+#
+# I is assumed, that the value is not kept between double quotes.
+#
+# <x> first character after "$message=",
+# where the content is not (space or tab)
+# <y*> first character after beginning of the line,
+# where the content is not (space or tab)
+# <z> last char before ";"
+# | beginning or end of line
+#
+# script: let $message= <x><whatever0>|
+# | <y1><whatever1>|
+# |................|
+# | <yn><whatevern><z>;
+# content: "<x><whatever0><new line><y1><whatever1><new line>
+# ....<new line><yn><whatevern><z>"
+# protocol output: |<x><whatever0>|
+# |<y1><whatever1>|
+# |.....|
+# |<yn><whatevern><z>|
+# |--- 80 dashes ---|
+#
+# Attention:
+# <x> and <y*> set to characters like "-$#" which are also used
+# to start comments, options and the names of mysqltest variables
+# lead to syntax errors or mangled messages.
+#
+#
+# Examples of messages:
+# ---------------------
+#
+# Variant1 (ease of use):
+# Several lines with indentation kept between double quotes
+# script: |let $message=
+# |" Testcase 3.1 : Ensure that Pi is not an|
+# | integer number.|
+# | Third line";
+# protocol: |" Testcase 3.1 : Ensure that Pi is not an|
+# | integer number.|
+# | Third line"|
+# |------ 80 dashes ----|
+#
+# Please mention that
+# - the '"' preserves the indentation.
+# - it is easy to write the script lines to get a fine indentation,
+# if the value starts at the beginning of a new line
+# - the '"' is printed
+# - there are the least or no problems with characters like "-#$"
+#
+#
+# Variant 2 (grep the messages from the protocol is easy):
+# Several lines with indentation + auxiliary character (".")
+# at the (non tab or space) beginning of every message line
+# script: |let $message= . Testcase 3.1 : Ensure that Pi is not an|
+# | . integer number.|
+# | . Third line;
+# protocol: |. Testcase 3.1 : Ensure that Pi is not an|
+# |. integer number.|
+# |. Third line|
+# |------ 80 dashes ----|
+# Please mention that
+# - the auxiliary character preserves the indentation.
+# - it is easy to write the script lines to get a fine indentation
+# - the auxiliary character is printed
+# - it is recommended to use "." as auxiliary character
+# - auxiliary characters like "-'$#" cause problems
+#
+#
+#
+# Bad variant1: Several lines with lost indentation
+# script: |let $message= Here is message line 1
+# | message line 2;
+# protocol: |Here is message line 1|
+# |message line 2|
+# |------ 80 dashes ----|
+# Please mention, that the leading spaces of the message lines disappeared.
+#
+# Bad variant2: Several lines leading to a syntax error, because of "-"
+# script: |let $message= - This is a message
+# | - with a second and
+# | - third line;
+# protocol: | - third line;;
+# |ERROR 42000: You have an error ... near '- third line'
+# + several following errors
+#
+#
+
+--disable_query_log
+eval SET @utf8_message = CONVERT('$message' using utf8);
+select @utf8_message as ""
+union
+select repeat(CONVERT('-' using utf8),80);
+--enable_query_log
diff --git a/mysql-test/include/system_db_struct.inc b/mysql-test/include/system_db_struct.inc
index 5a7aa26c65a..c66590b2fd8 100644
--- a/mysql-test/include/system_db_struct.inc
+++ b/mysql-test/include/system_db_struct.inc
@@ -10,3 +10,5 @@ show create table user;
show create table func;
show create table tables_priv;
show create table columns_priv;
+show create table procs_priv;
+show create table proc;
diff --git a/mysql-test/include/testdb_only.inc b/mysql-test/include/testdb_only.inc
new file mode 100644
index 00000000000..ddc3f123d45
--- /dev/null
+++ b/mysql-test/include/testdb_only.inc
@@ -0,0 +1,30 @@
+#################### include/testdb_only.inc ######################
+# #
+# We must prevent to work on databases created by customers, #
+# because we DROP/CREATE/MODIFY objects with sometimes common #
+# names like STAFF, EMPLOYEE etc. #
+# #
+# Therefore we check the environment variable USE_RUNNING_SERVER. #
+# USE_RUNNING_SERVER is exported by "mysql-test-run" and could #
+# contain the following values: #
+# 0 -- mysql-test-run was started without the --extern option #
+# That means the test will be performed within the test #
+# area 'mysql-test/var/...' . #
+# 1 -- mysql-test-run was started with the --extern option #
+# That means the test will be performed by an already #
+# running server and data modifications will most probably #
+# outside of the common test area 'mysql-test/var/...' . #
+# #
+# If USE_RUNNING_SERVER is not 0 the test will be skipped. #
+# #
+###################################################################
+
+--disable_query_log
+eval set @USE_RUNNING_SERVER= '$USE_RUNNING_SERVER';
+--require r/testdb_only.require
+SELECT 'use extern server'
+ AS "Variable_name ",
+ IF(@USE_RUNNING_SERVER= '1','YES',
+ IF(@USE_RUNNING_SERVER= '0','NO','UNEXPECTED'))
+ AS "Value" ;
+--enable_query_log
diff --git a/mysql-test/include/varchar.inc b/mysql-test/include/varchar.inc
new file mode 100644
index 00000000000..70b563e871c
--- /dev/null
+++ b/mysql-test/include/varchar.inc
@@ -0,0 +1,239 @@
+# Initialise
+--disable_warnings
+drop table if exists t1,t2,t3;
+--enable_warnings
+
+disable_query_log;
+select "--- Testing varchar ---";
+enable_query_log;
+
+#
+# Simple basic test that endspace is saved
+#
+
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+select concat('*',v,'*',c,'*',t,'*') from t1;
+
+# Check how columns are copied
+show create table t1;
+create table t2 like t1;
+show create table t2;
+create table t3 select * from t1;
+show create table t3;
+alter table t1 modify c varchar(10);
+show create table t1;
+alter table t1 modify v char(10);
+show create table t1;
+alter table t1 modify t varchar(10);
+show create table t1;
+select concat('*',v,'*',c,'*',t,'*') from t1;
+drop table t1,t2,t3;
+
+#
+# Testing of keys
+#
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+disable_query_log;
+let $1=10;
+while ($1)
+{
+ let $2=27;
+ eval set @space=repeat(' ',10-$1);
+ while ($2)
+ {
+ eval set @char=char(ascii('a')+$2-1);
+ insert into t1 values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
+ dec $2;
+ }
+ dec $1;
+}
+enable_query_log;
+select count(*) from t1;
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+select count(*) from t1 where c='a';
+select count(*) from t1 where t='a';
+select count(*) from t1 where v='a ';
+select count(*) from t1 where c='a ';
+select count(*) from t1 where t='a ';
+select count(*) from t1 where v between 'a' and 'a ';
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+select count(*) from t1 where v like 'a%';
+select count(*) from t1 where c like 'a%';
+select count(*) from t1 where t like 'a%';
+select count(*) from t1 where v like 'a %';
+# Test results differ for BDB, see comments in bdb.test
+# and they are also different from MySAM test results.
+--replace_column 9 #
+explain select count(*) from t1 where v='a ';
+--replace_column 9 #
+explain select count(*) from t1 where c='a ';
+--replace_column 9 #
+explain select count(*) from t1 where t='a ';
+--replace_column 9 #
+explain select count(*) from t1 where v like 'a%';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+
+--error 1062
+alter table t1 add unique(v);
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+--replace_column 6 # 9 #
+explain select * from t1 where v='a';
+
+# GROUP BY
+
+select v,count(*) from t1 group by v limit 10;
+select v,count(t) from t1 group by v limit 10;
+select v,count(c) from t1 group by v limit 10;
+select sql_big_result v,count(t) from t1 group by v limit 10;
+select sql_big_result v,count(c) from t1 group by v limit 10;
+select c,count(*) from t1 group by c limit 10;
+select c,count(t) from t1 group by c limit 10;
+select sql_big_result c,count(t) from t1 group by c limit 10;
+select t,count(*) from t1 group by t limit 10;
+select t,count(t) from t1 group by t limit 10;
+select sql_big_result t,count(t) from t1 group by t limit 10;
+
+#
+# Test varchar > 255 bytes
+#
+
+alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v);
+show create table t1;
+select count(*) from t1 where v='a';
+select count(*) from t1 where v='a ';
+select count(*) from t1 where v between 'a' and 'a ';
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+select count(*) from t1 where v like 'a%';
+select count(*) from t1 where v like 'a %';
+--replace_column 9 #
+explain select count(*) from t1 where v='a ';
+--replace_column 9 #
+explain select count(*) from t1 where v like 'a%';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+--replace_column 9 #
+explain select * from t1 where v='a';
+
+# GROUP BY
+
+select v,count(*) from t1 group by v limit 10;
+select v,count(t) from t1 group by v limit 10;
+select sql_big_result v,count(t) from t1 group by v limit 10;
+
+#
+# Test varchar > 255 bytes, key < 255
+#
+
+alter table t1 drop key v, add key v (v(30));
+show create table t1;
+select count(*) from t1 where v='a';
+select count(*) from t1 where v='a ';
+select count(*) from t1 where v between 'a' and 'a ';
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+select count(*) from t1 where v like 'a%';
+select count(*) from t1 where v like 'a %';
+--replace_column 9 #
+explain select count(*) from t1 where v='a ';
+--replace_column 9 #
+explain select count(*) from t1 where v like 'a%';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+--replace_column 9 #
+explain select * from t1 where v='a';
+
+# GROUP BY
+
+select v,count(*) from t1 group by v limit 10;
+select v,count(t) from t1 group by v limit 10;
+select sql_big_result v,count(t) from t1 group by v limit 10;
+
+#
+# Test varchar > 512 (special case for GROUP BY becasue of
+# CONVERT_IF_BIGGER_TO_BLOB define)
+#
+
+alter table t1 modify v varchar(600), drop key v, add key v (v);
+show create table t1;
+select v,count(*) from t1 group by v limit 10;
+select v,count(t) from t1 group by v limit 10;
+select sql_big_result v,count(t) from t1 group by v limit 10;
+
+drop table t1;
+
+#
+# Test unique keys
+#
+
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+
+alter table t1 modify a varchar(10);
+--error 1062
+insert into t1 values ('a '),('a '),('a '),('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+update t1 set a='a ' where a like 'a%';
+select concat(a,'.') from t1;
+update t1 set a='abc ' where a like 'a ';
+select concat(a,'.') from t1;
+update t1 set a='a ' where a like 'a %';
+select concat(a,'.') from t1;
+update t1 set a='a ' where a like 'a ';
+select concat(a,'.') from t1;
+drop table t1;
+
+#
+# test show create table
+#
+
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+drop table t1;
+
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+drop table t1;
+
+#
+# Test long varchars
+#
+
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+drop table t1;
+
+#
+# Bug #9489: problem with hash indexes
+# Bug #10802: Index is not used if table using BDB engine on HP-UX
+#
+
+create table t1(a int, b varchar(12), key ba(b, a));
+insert into t1 values (1, 'A'), (20, NULL);
+explain select * from t1 where a=20 and b is null;
+select * from t1 where a=20 and b is null;
+drop table t1;
diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql
index 6d5ec55a6ae..37353e5974f 100644
--- a/mysql-test/lib/init_db.sql
+++ b/mysql-test/lib/init_db.sql
@@ -17,6 +17,11 @@ CREATE TABLE db (
Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
PRIMARY KEY Host (Host,Db,User),
KEY User (User)
) engine=MyISAM
@@ -24,8 +29,8 @@ CHARACTER SET utf8 COLLATE utf8_bin
comment='Database privileges';
-INSERT INTO db VALUES ('%','test' ,'','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');
-INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');
+INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N');
+INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N');
CREATE TABLE host (
@@ -43,6 +48,11 @@ CREATE TABLE host (
Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
PRIMARY KEY Host (Host,Db)
) engine=MyISAM
CHARACTER SET utf8 COLLATE utf8_bin
@@ -74,6 +84,11 @@ CREATE TABLE user (
Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
+ Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
ssl_cipher BLOB NOT NULL,
x509_issuer BLOB NOT NULL,
@@ -81,15 +96,16 @@ CREATE TABLE user (
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,
+ max_user_connections int(11) unsigned DEFAULT 0 NOT NULL,
PRIMARY KEY Host (Host,User)
) engine=MyISAM
CHARACTER SET utf8 COLLATE utf8_bin
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 ('@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);
-REPLACE INTO user VALUES ('127.0.0.1' ,'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' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+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','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+REPLACE INTO user VALUES ('127.0.0.1' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
INSERT INTO user (host,user) VALUES ('localhost','');
INSERT INTO user (host,user) VALUES ('@HOSTNAME@%','');
@@ -112,7 +128,7 @@ CREATE TABLE tables_priv (
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') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
+ Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
PRIMARY KEY (Host,Db,User,Table_name),KEY Grantor (Grantor)
) engine=MyISAM
@@ -136,11 +152,11 @@ comment='Column privileges';
CREATE TABLE help_topic (
help_topic_id int unsigned not null,
- name varchar(64) not null,
+ name char(64) not null,
help_category_id smallint unsigned not null,
description text not null,
example text not null,
- url varchar(128) not null,
+ url char(128) not null,
primary key (help_topic_id),
unique index (name)
) engine=MyISAM
@@ -150,9 +166,9 @@ comment='help topics';
CREATE TABLE help_category (
help_category_id smallint unsigned not null,
- name varchar(64) not null,
+ name char(64) not null,
parent_category_id smallint unsigned null,
- url varchar(128) not null,
+ url char(128) not null,
primary key (help_category_id),unique index (name)
) engine=MyISAM
CHARACTER SET utf8
@@ -161,7 +177,7 @@ comment='help categories';
CREATE TABLE help_keyword (
help_keyword_id int unsigned not null,
- name varchar(64) not null,
+ name char(64) not null,
primary key (help_keyword_id),unique index (name)
) engine=MyISAM
CHARACTER SET utf8
@@ -469,3 +485,75 @@ INSERT INTO time_zone_leap_second (
,(662688015, 16) ,(709948816, 17) ,(741484817, 18)
,(773020818, 19) ,(820454419, 20) ,(867715220, 21)
,(915148821, 22);
+
+
+CREATE TABLE procs_priv (
+ Host char(60) binary DEFAULT '' NOT NULL,
+ Db char(64) binary DEFAULT '' NOT NULL,
+ User char(16) binary DEFAULT '' NOT NULL,
+ Routine_name char(64) binary DEFAULT '' NOT NULL,
+ Routine_type enum('FUNCTION','PROCEDURE') NOT NULL,
+ Grantor char(77) DEFAULT '' NOT NULL,
+ Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
+ Timestamp timestamp(14),
+ PRIMARY KEY (Host,Db,User,Routine_name,Routine_type),
+ KEY Grantor (Grantor)
+) engine=MyISAM
+CHARACTER SET utf8 COLLATE utf8_bin
+comment='Procedure privileges';
+
+
+CREATE TABLE proc (
+ db char(64) collate utf8_bin DEFAULT '' NOT NULL,
+ name char(64) DEFAULT '' NOT NULL,
+ type enum('FUNCTION','PROCEDURE') NOT NULL,
+ specific_name char(64) DEFAULT '' NOT NULL,
+ language enum('SQL') DEFAULT 'SQL' NOT NULL,
+ sql_data_access enum('CONTAINS_SQL',
+ 'NO_SQL',
+ 'READS_SQL_DATA',
+ 'MODIFIES_SQL_DATA'
+ ) DEFAULT 'CONTAINS_SQL' NOT NULL,
+ is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,
+ security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL,
+ param_list blob DEFAULT '' NOT NULL,
+ returns char(64) DEFAULT '' NOT NULL,
+ body longblob DEFAULT '' NOT NULL,
+ definer char(77) collate utf8_bin DEFAULT '' NOT NULL,
+ created timestamp,
+ modified timestamp,
+ sql_mode set(
+ 'REAL_AS_FLOAT',
+ 'PIPES_AS_CONCAT',
+ 'ANSI_QUOTES',
+ 'IGNORE_SPACE',
+ 'NOT_USED',
+ 'ONLY_FULL_GROUP_BY',
+ 'NO_UNSIGNED_SUBTRACTION',
+ 'NO_DIR_IN_CREATE',
+ 'POSTGRESQL',
+ 'ORACLE',
+ 'MSSQL',
+ 'DB2',
+ 'MAXDB',
+ 'NO_KEY_OPTIONS',
+ 'NO_TABLE_OPTIONS',
+ 'NO_FIELD_OPTIONS',
+ 'MYSQL323',
+ 'MYSQL40',
+ 'ANSI',
+ 'NO_AUTO_VALUE_ON_ZERO',
+ 'NO_BACKSLASH_ESCAPES',
+ 'STRICT_TRANS_TABLES',
+ 'STRICT_ALL_TABLES',
+ 'NO_ZERO_IN_DATE',
+ 'NO_ZERO_DATE',
+ 'INVALID_DATES',
+ 'ERROR_FOR_DIVISION_BY_ZERO',
+ 'TRADITIONAL',
+ 'NO_AUTO_CREATE_USER',
+ 'HIGH_NOT_PRECEDENCE'
+ ) DEFAULT '' NOT NULL,
+ comment char(64) collate utf8_bin DEFAULT '' NOT NULL,
+ PRIMARY KEY (db,name,type)
+) character set utf8 comment='Stored Procedures';
diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl
index 158fd602ef8..250c3562227 100644
--- a/mysql-test/lib/mtr_cases.pl
+++ b/mysql-test/lib/mtr_cases.pl
@@ -8,7 +8,7 @@ use File::Basename;
use strict;
sub collect_test_cases ($);
-sub collect_one_test_case ($$$$$$);
+sub collect_one_test_case ($$$$$$$);
##############################################################################
#
@@ -40,13 +40,84 @@ sub collect_test_cases ($) {
if ( @::opt_cases )
{
foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
- $tname= basename($tname, ".test");
- my $elem= "$tname.test";
- if ( ! -f "$testdir/$elem")
+ my $elem= undef;
+ my $component_id= undef;
+
+ # Get rid of directory part (path). Leave the extension since it is used
+ # to understand type of the test.
+
+ $tname = basename($tname);
+
+ # Check if the extenstion has been specified.
+
+ if ( mtr_match_extension($tname, "test") )
+ {
+ $elem= $tname;
+ $tname=~ s/\.test$//;
+ $component_id= 'mysqld';
+ }
+ elsif ( mtr_match_extension($tname, "imtest") )
+ {
+ $elem= $tname;
+ $tname =~ s/\.imtest$//;
+ $component_id= 'im';
+
+ if ( $::glob_use_embedded_server )
+ {
+ mtr_report(
+ "Instance Manager's tests are not available in embedded mode." .
+ "Test case '$tname' is skipped.");
+ next;
+ }
+
+ unless ( $::exe_im )
+ {
+ mtr_report(
+ "Instance Manager executable is unavailable. " .
+ "Test case '$tname' is skipped.");
+ next;
+ }
+ }
+
+ # If target component is known, check that the specified test case
+ # exists.
+ #
+ # Otherwise, try to guess the target component.
+
+ if ( defined $component_id )
{
- mtr_error("Test case $tname ($testdir/$elem) is not found");
+ if ( ! -f "$testdir/$elem")
+ {
+ mtr_error("Test case $tname ($testdir/$elem) is not found");
+ }
}
- collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{});
+ else
+ {
+ my $mysqld_test_exists = -f "$testdir/$tname.test";
+ my $im_test_exists = -f "$testdir/$tname.imtest";
+
+ if ( $mysqld_test_exists && $im_test_exists )
+ {
+ mtr_error("Ambiguos test case name ($tname)");
+ }
+ elsif ( ! $mysqld_test_exists && !$im_test_exists )
+ {
+ mtr_error("Test case $tname is not found");
+ }
+ elsif ( $mysqld_test_exists )
+ {
+ $elem= "$tname.test";
+ $component_id= 'mysqld';
+ }
+ elsif ( $im_test_exists )
+ {
+ $elem= "$tname.imtest";
+ $component_id= 'im';
+ }
+ }
+
+ collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{},
+ $component_id);
}
closedir TESTDIR;
}
@@ -70,11 +141,26 @@ sub collect_test_cases ($) {
}
foreach my $elem ( sort readdir(TESTDIR) ) {
- my $tname= mtr_match_extension($elem,"test");
- next if ! defined $tname;
+ my $component_id= undef;
+ my $tname= undef;
+
+ if ($tname= mtr_match_extension($elem, 'test'))
+ {
+ $component_id = 'mysqld';
+ }
+ elsif ($tname= mtr_match_extension($elem, 'imtest'))
+ {
+ $component_id = 'im';
+ }
+ else
+ {
+ next;
+ }
+
next if $::opt_do_test and ! defined mtr_match_prefix($elem,$::opt_do_test);
- collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled);
+ collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
+ $component_id);
}
closedir TESTDIR;
}
@@ -112,13 +198,14 @@ sub collect_test_cases ($) {
##############################################################################
-sub collect_one_test_case($$$$$$) {
+sub collect_one_test_case($$$$$$$) {
my $testdir= shift;
my $resdir= shift;
my $tname= shift;
my $elem= shift;
my $cases= shift;
my $disabled=shift;
+ my $component_id= shift;
my $path= "$testdir/$elem";
@@ -138,6 +225,7 @@ sub collect_one_test_case($$$$$$) {
my $tinfo= {};
$tinfo->{'name'}= $tname;
$tinfo->{'result_file'}= "$resdir/$tname.result";
+ $tinfo->{'component_id'} = $component_id;
push(@$cases, $tinfo);
if ( $::opt_skip_test and defined mtr_match_prefix($tname,$::opt_skip_test) )
@@ -188,6 +276,7 @@ sub collect_one_test_case($$$$$$) {
my $master_sh= "$testdir/$tname-master.sh";
my $slave_sh= "$testdir/$tname-slave.sh";
my $disabled_file= "$testdir/$tname.disabled";
+ my $im_opt_file= "$testdir/$tname-im.opt";
$tinfo->{'master_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : [];
$tinfo->{'slave_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : [];
@@ -290,6 +379,15 @@ sub collect_one_test_case($$$$$$) {
}
}
+ if ( -f $im_opt_file )
+ {
+ $tinfo->{'im_opts'} = mtr_get_opts_from_file($im_opt_file);
+ }
+ else
+ {
+ $tinfo->{'im_opts'} = [];
+ }
+
# FIXME why this late?
if ( $disabled->{$tname} )
{
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 9176a246835..5149d322f7f 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -823,7 +823,7 @@ sub sleep_until_file_created ($$$) {
}
# Check if it died after the fork() was successful
- if ( waitpid($pid,&WNOHANG) == $pid )
+ if ( $pid > 0 && waitpid($pid,&WNOHANG) == $pid )
{
return 0;
}
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 19a2679d956..2dda1b2a6e1 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -178,6 +178,8 @@ our $exe_mysqlshow; # Called from test case
our $exe_mysql_fix_system_tables;
our $exe_mysqltest;
our $exe_slave_mysqld;
+our $exe_im;
+our $exe_my_print_defaults;
our $opt_bench= 0;
our $opt_small_bench= 0;
@@ -216,6 +218,8 @@ our $opt_local_master;
our $master; # Will be struct in C
our $slave;
+our $instance_manager;
+
our $opt_ndbcluster_port;
our $opt_ndbconnectstring;
@@ -312,6 +316,8 @@ sub mysqld_arguments ($$$$$);
sub stop_masters_slaves ();
sub stop_masters ();
sub stop_slaves ();
+sub im_start ($$);
+sub im_stop ($);
sub run_mysqltest ($);
sub usage ($);
@@ -463,6 +469,9 @@ sub command_line_setup () {
my $opt_master_myport= 9306;
my $opt_slave_myport= 9308;
$opt_ndbcluster_port= 9350;
+ my $im_port= 9310;
+ my $im_mysqld1_port= 9312;
+ my $im_mysqld2_port= 9314;
# Read the command line
# Note: Keep list, and the order, in sync with usage at end of this file
@@ -489,6 +498,9 @@ sub command_line_setup () {
'slave_port=i' => \$opt_slave_myport,
'ndbcluster_port=i' => \$opt_ndbcluster_port,
'manager-port=i' => \$opt_manager_port, # Currently not used
+ 'im-port=i' => \$im_port, # Instance Manager port.
+ 'im-mysqld1-port=i' => \$im_mysqld1_port, # Port of mysqld, controlled by IM
+ 'im-mysqld2-port=i' => \$im_mysqld2_port, # Port of mysqld, controlled by IM
# Test case authoring
'record' => \$opt_record,
@@ -785,6 +797,37 @@ sub command_line_setup () {
$slave->[2]->{'path_myport'}= $opt_slave_myport + 2;
$slave->[2]->{'start_timeout'}= 300;
+ $instance_manager->{'path_err'}= "$opt_vardir/log/im.err";
+ $instance_manager->{'path_log'}= "$opt_vardir/log/im.log";
+ $instance_manager->{'path_pid'}= "$opt_vardir/run/im.pid";
+ $instance_manager->{'path_sock'}= "$opt_tmpdir/im.sock";
+ $instance_manager->{'port'}= $im_port;
+ $instance_manager->{'start_timeout'}= $master->[0]->{'start_timeout'};
+ $instance_manager->{'admin_login'}= 'im_admin';
+ $instance_manager->{'admin_password'}= 'im_admin_secret';
+ $instance_manager->{'admin_sha1'}= '*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295';
+ $instance_manager->{'password_file'}= "$opt_vardir/im.passwd";
+ $instance_manager->{'defaults_file'}= "$opt_vardir/im.cnf";
+
+ $instance_manager->{'instances'}->[0]->{'server_id'}= 1;
+ $instance_manager->{'instances'}->[0]->{'port'}= $im_mysqld1_port;
+ $instance_manager->{'instances'}->[0]->{'path_datadir'}=
+ "$opt_vardir/im_mysqld_1.data";
+ $instance_manager->{'instances'}->[0]->{'path_sock'}=
+ "$opt_vardir/mysqld_1.sock";
+ $instance_manager->{'instances'}->[0]->{'path_pid'}=
+ "$opt_vardir/mysqld_1.pid";
+
+ $instance_manager->{'instances'}->[1]->{'server_id'}= 2;
+ $instance_manager->{'instances'}->[1]->{'port'}= $im_mysqld2_port;
+ $instance_manager->{'instances'}->[1]->{'path_datadir'}=
+ "$opt_vardir/im_mysqld_2.data";
+ $instance_manager->{'instances'}->[1]->{'path_sock'}=
+ "$opt_vardir/mysqld_2.sock";
+ $instance_manager->{'instances'}->[1]->{'path_pid'}=
+ "$opt_vardir/mysqld_2.pid";
+ $instance_manager->{'instances'}->[1]->{'nonguarded'}= 1;
+
if ( $opt_extern )
{
$glob_use_running_server= 1;
@@ -820,6 +863,9 @@ sub executable_setup () {
$exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld");
$path_language= mtr_path_exists("$glob_basedir/sql/share/english/");
$path_charsetsdir= mtr_path_exists("$glob_basedir/sql/share/charsets");
+
+ $exe_im= mtr_exe_exists(
+ "$glob_basedir/server-tools/instance-manager/mysqlmanager");
}
if ( $glob_use_embedded_server )
@@ -844,6 +890,8 @@ sub executable_setup () {
$exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
$exe_mysql_fix_system_tables=
mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables");
+ $exe_my_print_defaults=
+ mtr_script_exists("$glob_basedir/extra/my_print_defaults");
$path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools");
$exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm";
}
@@ -859,6 +907,8 @@ sub executable_setup () {
$exe_mysql_fix_system_tables=
mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables",
"$glob_basedir/scripts/mysql_fix_privilege_tables");
+ $exe_my_print_defaults=
+ mtr_script_exists("$path_client_bindir/my_print_defaults");
$path_language= mtr_path_exists("$glob_basedir/share/mysql/english/",
"$glob_basedir/share/english/");
@@ -867,6 +917,8 @@ sub executable_setup () {
$exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld",
"$glob_basedir/bin/mysqld");
+ $exe_im= mtr_exe_exists("$glob_basedir/libexec/mysqlmanager",
+ "$glob_basedir/bin/mysqlmanager");
if ( $glob_use_embedded_server )
{
$exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded");
@@ -940,6 +992,11 @@ sub environment_setup () {
# $ENV{'MYSQL_TCP_PORT'}= '@MYSQL_TCP_PORT@'; # FIXME
$ENV{'MYSQL_TCP_PORT'}= 3306;
+ $ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock};
+ $ENV{'IM_MYSQLD1_PORT'}= $instance_manager->{instances}->[0]->{port};
+ $ENV{'IM_MYSQLD2_SOCK'}= $instance_manager->{instances}->[1]->{path_sock};
+ $ENV{'IM_MYSQLD2_PORT'}= $instance_manager->{instances}->[1]->{port};
+
if ( $glob_cygwin_perl )
{
foreach my $key ('MYSQL_TEST_WINDIR','MASTER_MYSOCK')
@@ -1030,6 +1087,11 @@ sub kill_and_cleanup () {
$slave->[1]->{'path_myddir'},
$slave->[2]->{'path_myddir'});
+ foreach my $instance (@{$instance_manager->{'instances'}})
+ {
+ push (@data_dir_lst, $instance->{'path_datadir'});
+ }
+
foreach my $data_dir (@data_dir_lst)
{
rmtree("$data_dir");
@@ -1082,10 +1144,8 @@ sub ndbcluster_install () {
}
mtr_report("Install ndbcluster");
my $ndbcluster_opts= $opt_bench ? "" : "--small";
- my $ndbcluster_port_base= $opt_ndbcluster_port + 2;
if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port",
- "--port-base=$ndbcluster_port_base",
"--data-dir=$opt_vardir",
$ndbcluster_opts,
"--initial"],
@@ -1126,7 +1186,6 @@ sub ndbcluster_stop () {
{
return;
}
- my $ndbcluster_port_base= $opt_ndbcluster_port + 2;
# FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port",
@@ -1276,6 +1335,11 @@ sub mysql_install_db () {
install_db('slave', $slave->[1]->{'path_myddir'});
install_db('slave', $slave->[2]->{'path_myddir'});
+ if ( defined $exe_im)
+ {
+ im_prepare_env($instance_manager);
+ }
+
if ( ndbcluster_install() )
{
# failed to install, disable usage but flag that its no ok
@@ -1350,6 +1414,101 @@ sub install_db ($$) {
}
+sub im_prepare_env($) {
+ my $instance_manager = shift;
+
+ im_create_passwd_file($instance_manager);
+ im_prepare_data_dir($instance_manager);
+}
+
+
+sub im_create_passwd_file($) {
+ my $instance_manager = shift;
+
+ my $pwd_file_path = $instance_manager->{'password_file'};
+
+ mtr_report("Creating IM password file ($pwd_file_path)");
+
+ open(OUT, ">", $pwd_file_path)
+ or mtr_error("Can't write to $pwd_file_path: $!");
+
+ print OUT $instance_manager->{'admin_login'}, ":",
+ $instance_manager->{'admin_sha1'}, "\n";
+
+ close(OUT);
+}
+
+
+sub im_create_defaults_file($) {
+ my $instance_manager = shift;
+
+ my $defaults_file = $instance_manager->{'defaults_file'};
+
+ open(OUT, ">", $defaults_file)
+ or mtr_error("Can't write to $defaults_file: $!");
+
+ print OUT <<EOF
+[mysql]
+
+[manager]
+pid-file = $instance_manager->{path_pid}
+socket = $instance_manager->{path_sock}
+port = $instance_manager->{port}
+password-file = $instance_manager->{password_file}
+default-mysqld-path = $exe_mysqld
+
+EOF
+;
+
+ foreach my $instance (@{$instance_manager->{'instances'}})
+ {
+ my $server_id = $instance->{'server_id'};
+
+ print OUT <<EOF
+[mysqld$server_id]
+socket = $instance->{path_sock}
+pid-file = $instance->{path_pid}
+port = $instance->{port}
+datadir = $instance->{path_datadir}
+log = $instance->{path_datadir}/mysqld$server_id.log
+log-error = $instance->{path_datadir}/mysqld$server_id.err.log
+log-slow-queries = $instance->{path_datadir}/mysqld$server_id.slow.log
+language = $path_language
+character-sets-dir = $path_charsetsdir
+basedir = $path_my_basedir
+server_id =$server_id
+skip-stack-trace
+skip-innodb
+skip-bdb
+skip-ndbcluster
+EOF
+;
+
+ if ( exists $instance->{nonguarded} and
+ defined $instance->{nonguarded} )
+ {
+ print OUT "nonguarded\n";
+ }
+
+ print OUT "\n";
+ }
+
+ close(OUT);
+}
+
+
+sub im_prepare_data_dir($) {
+ my $instance_manager = shift;
+
+ foreach my $instance (@{$instance_manager->{'instances'}})
+ {
+ install_db(
+ 'im_mysqld_' . $instance->{'server_id'},
+ $instance->{'path_datadir'});
+ }
+}
+
+
##############################################################################
#
# Run a single test case
@@ -1451,7 +1610,7 @@ sub run_testcase ($) {
# FIXME split up start and check that started so that can do
# starts in parallel, masters and slaves at the same time.
- if ( ! $opt_local_master )
+ if ( $tinfo->{'component_id'} eq 'mysqld' and ! $opt_local_master )
{
if ( $master->[0]->{'ndbcluster'} )
{
@@ -1490,6 +1649,17 @@ sub run_testcase ($) {
$master->[0]->{'running_master_is_special'}= 1;
}
}
+ elsif ( $tinfo->{'component_id'} eq 'im')
+ {
+ # We have to create defaults file every time, in order to ensure that it
+ # will be the same for each test. The problem is that test can change the
+ # file (by SET/UNSET commands), so w/o recreating the file, execution of
+ # one test can affect the other.
+
+ im_create_defaults_file($instance_manager);
+
+ im_start($instance_manager, $tinfo->{im_opts});
+ }
# ----------------------------------------------------------------------
# Start slaves - if needed
@@ -1572,6 +1742,15 @@ sub run_testcase ($) {
report_failure_and_restart($tinfo);
}
}
+
+ # ----------------------------------------------------------------------
+ # Stop Instance Manager if we are processing an IM-test case.
+ # ----------------------------------------------------------------------
+
+ if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' )
+ {
+ im_stop($instance_manager);
+ }
}
@@ -1716,6 +1895,7 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir);
mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir);
mtr_add_arg($args, "%s--core", $prefix);
+ mtr_add_arg($args, "%s--log-bin-trust-routine-creators", $prefix);
mtr_add_arg($args, "%s--default-character-set=latin1", $prefix);
mtr_add_arg($args, "%s--language=%s", $prefix, $path_language);
mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
@@ -1741,7 +1921,7 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--server-id=%d", $prefix, $id);
mtr_add_arg($args, "%s--socket=%s", $prefix,
$master->[$idx]->{'path_mysock'});
- mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:50M", $prefix);
+ mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:128M:autoextend", $prefix);
mtr_add_arg($args, "%s--local-infile", $prefix);
mtr_add_arg($args, "%s--datadir=%s", $prefix,
$master->[$idx]->{'path_myddir'});
@@ -1838,6 +2018,7 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix);
mtr_add_arg($args, "%s--sort_buffer=256K", $prefix);
mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix);
+ mtr_add_arg($args, "%s--log-bin-trust-routine-creators", $prefix);
if ( $opt_with_openssl )
{
@@ -1980,6 +2161,13 @@ sub mysqld_start ($$$$) {
sub stop_masters_slaves () {
print "Ending Tests\n";
+
+ if (defined $instance_manager->{'pid'})
+ {
+ print "Shutting-down Instance Manager\n";
+ im_stop($instance_manager);
+ }
+
print "Shutting-down MySQL daemon\n\n";
stop_masters();
print "Master(s) shutdown finished\n";
@@ -2038,6 +2226,97 @@ sub stop_slaves () {
mtr_stop_mysqld_servers(\@args);
}
+##############################################################################
+#
+# Instance Manager management routines.
+#
+##############################################################################
+
+sub im_start($$) {
+ my $instance_manager = shift;
+ my $opts = shift;
+
+ if ( ! defined $exe_im)
+ {
+ return;
+ }
+
+ my $args;
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--defaults-file=" . $instance_manager->{'defaults_file'});
+
+ foreach my $opt (@{$opts})
+ {
+ mtr_add_arg($args, $opt);
+ }
+
+ $instance_manager->{'pid'} =
+ mtr_spawn(
+ $exe_im, # path to the executable
+ $args, # cmd-line args
+ '', # stdin
+ $instance_manager->{'path_log'}, # stdout
+ $instance_manager->{'path_err'}, # stderr
+ '', # pid file path (not used)
+ { append_log_file => 1 } # append log files
+ );
+
+ if ( ! defined $instance_manager->{'pid'} )
+ {
+ mtr_report('Could not start Instance Manager');
+ return;
+ }
+
+ # Instance Manager can be run in daemon mode. In this case, it creates
+ # several processes and the parent process, created by mtr_spawn(), exits just
+ # after start. So, we have to obtain Instance Manager PID from the PID file.
+
+ sleep_until_file_created(
+ $instance_manager->{'path_pid'},
+ $instance_manager->{'start_timeout'},
+ -1); # real PID is still unknown
+
+ $instance_manager->{'pid'} =
+ mtr_get_pid_from_file($instance_manager->{'path_pid'});
+}
+
+sub im_stop($) {
+ my $instance_manager = shift;
+
+ if (! defined $instance_manager->{'pid'})
+ {
+ return;
+ }
+
+ # Inspired from mtr_stop_mysqld_servers().
+
+ start_reap_all();
+
+ # Create list of pids. We should stop Instance Manager and all started
+ # mysqld-instances. Some of them may be nonguarded, so IM will not stop them
+ # on shutdown.
+
+ my @pids = ( $instance_manager->{'pid'} );
+ my $instances = $instance_manager->{'instances'};
+
+ if ( -r $instances->[0]->{'path_pid'} )
+ {
+ push @pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'});
+ }
+
+ if ( -r $instances->[1]->{'path_pid'} )
+ {
+ push @pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'});
+ }
+
+ # Kill processes.
+
+ mtr_kill_processes(\@pids);
+
+ stop_reap_all();
+
+ $instance_manager->{'pid'} = undef;
+}
sub run_mysqltest ($) {
my $tinfo= shift;
@@ -2061,7 +2340,9 @@ sub run_mysqltest ($) {
}
my $cmdline_mysqlbinlog=
- "$exe_mysqlbinlog --no-defaults --local-load=$opt_tmpdir";
+ "$exe_mysqlbinlog" .
+ " --no-defaults --local-load=$opt_tmpdir" .
+ " --character-sets-dir=$path_charsetsdir";
if ( $opt_debug )
{
@@ -2105,6 +2386,7 @@ sub run_mysqltest ($) {
$ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables;
$ENV{'MYSQL_CLIENT_TEST'}= $cmdline_mysql_client_test;
$ENV{'CHARSETSDIR'}= $path_charsetsdir;
+ $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults;
$ENV{'NDB_STATUS_OK'}= $flag_ndb_status_ok;
$ENV{'NDB_MGM'}= $exe_ndb_mgm;
@@ -2124,15 +2406,26 @@ sub run_mysqltest ($) {
}
mtr_add_arg($args, "--no-defaults");
- mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
- mtr_add_arg($args, "--database=test");
- mtr_add_arg($args, "--user=%s", $opt_user);
- mtr_add_arg($args, "--password=");
mtr_add_arg($args, "--silent");
mtr_add_arg($args, "-v");
mtr_add_arg($args, "--skip-safemalloc");
mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
- mtr_add_arg($args, "--port=%d", $master->[0]->{'path_myport'});
+
+ if ($tinfo->{'component_id'} eq 'im')
+ {
+ mtr_add_arg($args, "--socket=%s", $instance_manager->{'path_sock'});
+ mtr_add_arg($args, "--port=%d", $instance_manager->{'port'});
+ mtr_add_arg($args, "--user=%s", $instance_manager->{'admin_login'});
+ mtr_add_arg($args, "--password=%s", $instance_manager->{'admin_password'});
+ }
+ else # component_id == mysqld
+ {
+ mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
+ mtr_add_arg($args, "--port=%d", $master->[0]->{'path_myport'});
+ mtr_add_arg($args, "--database=test");
+ mtr_add_arg($args, "--user=%s", $opt_user);
+ mtr_add_arg($args, "--password=");
+ }
if ( $opt_ps_protocol )
{
@@ -2260,7 +2553,6 @@ Options to control what engine/variation to run
ps-protocol Use the binary protocol between client and server
bench Run the benchmark suite FIXME
small-bench FIXME
- no-manager Use the istanse manager (currently disabled)
Options to control what test suites or cases to run
@@ -2277,7 +2569,6 @@ Options that specify ports
master_port=PORT Specify the port number used by the first master
slave_port=PORT Specify the port number used by the first slave
ndbcluster_port=PORT Specify the port number used by cluster
- manager-port=PORT Specify the port number used by manager (currently not used)
Options for test case authoring
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 3e7a54fdead..aadf9080348 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -189,7 +189,7 @@ FAST_START=""
MYSQL_TMP_DIR=$MYSQL_TEST_DIR/var/tmp
SLAVE_LOAD_TMPDIR=../../var/tmp #needs to be same length to test logging
RES_SPACE=" "
-MYSQLD_SRC_DIRS="strings mysys include extra regex isam merge myisam \
+MYSQLD_SRC_DIRS="strings mysys include extra regex myisam \
myisammrg heap sql"
MY_LOG_DIR="$MYSQL_TEST_DIR/var/log"
#
@@ -199,6 +199,13 @@ LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$BASEDIR/zlib/.libs:$LD_LI
DYLD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$BASEDIR/zlib/.libs:$DYLD_LIBRARY_PATH"
export LD_LIBRARY_PATH DYLD_LIBRARY_PATH
+#
+# Allow anyone in the group to see the generated database files
+#
+UMASK=0660
+UMASK_DIR=0770
+export UMASK UMASK_DIR
+
MASTER_RUNNING=0
MASTER1_RUNNING=0
MASTER_MYPORT=9306
@@ -216,8 +223,9 @@ FAILED_CASES=
EXTRA_MASTER_OPT=""
EXTRA_MYSQL_TEST_OPT=""
EXTRA_MYSQLDUMP_OPT=""
+EXTRA_MYSQLSHOW_OPT=""
EXTRA_MYSQLBINLOG_OPT=""
-USE_RUNNING_SERVER=""
+USE_RUNNING_SERVER=0
USE_NDBCLUSTER=@USE_NDBCLUSTER@
USE_RUNNING_NDBCLUSTER=""
USE_PURIFY=""
@@ -227,6 +235,7 @@ DO_GDB=""
MANUAL_GDB=""
DO_DDD=""
DO_CLIENT_GDB=""
+DO_VALGRIND_MYSQL_TEST=""
SLEEP_TIME_AFTER_RESTART=1
SLEEP_TIME_FOR_DELETE=10
SLEEP_TIME_FOR_FIRST_MASTER=400 # Enough time to create innodb tables
@@ -251,12 +260,12 @@ while test $# -gt 0; do
--embedded-server)
USE_EMBEDDED_SERVER=1
USE_MANAGER=0 NO_SLAVE=1
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
TEST_MODE="$TEST_MODE embedded" ;;
--purify)
USE_PURIFY=1
USE_MANAGER=0
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
TEST_MODE="$TEST_MODE purify" ;;
--user=*) DBUSER=`$ECHO "$1" | $SED -e "s;--user=;;"` ;;
--force) FORCE=1 ;;
@@ -267,8 +276,8 @@ while test $# -gt 0; do
MASTER_MYSQLD=`$ECHO "$1" | $SED -e "s;--master-binary=;;"` ;;
--slave-binary=*)
SLAVE_MYSQLD=`$ECHO "$1" | $SED -e "s;--slave-binary=;;"` ;;
- --local) USE_RUNNING_SERVER="" ;;
- --extern) USE_RUNNING_SERVER="1" ;;
+ --local) USE_RUNNING_SERVER=0 ;;
+ --extern) USE_RUNNING_SERVER=1 ;;
--with-ndbcluster)
USE_NDBCLUSTER="--ndbcluster" ;;
--ndb-connectstring=*)
@@ -292,20 +301,20 @@ while test $# -gt 0; do
--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 \
- --ssl-cert=$BASEDIR/SSL/server-cert.pem \
- --ssl-key=$BASEDIR/SSL/server-key.pem"
+ --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \
+ --ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem \
+ --ssl-key=$MYSQL_TEST_DIR/std_data/server-key.pem"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \
- --ssl-ca=$BASEDIR/SSL/cacert.pem \
- --ssl-cert=$BASEDIR/SSL/server-cert.pem \
- --ssl-key=$BASEDIR/SSL/server-key.pem"
- MYSQL_TEST_SSL_OPTS="--ssl-ca=$BASEDIR/SSL/cacert.pem \
- --ssl-cert=$BASEDIR/SSL/client-cert.pem \
- --ssl-key=$BASEDIR/SSL/client-key.pem" ;;
+ --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \
+ --ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem \
+ --ssl-key=$MYSQL_TEST_DIR/std_data/server-key.pem"
+ MYSQL_TEST_SSL_OPTS="--ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \
+ --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem \
+ --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem" ;;
--no-manager | --skip-manager) USE_MANAGER=0 ;;
--manager)
USE_MANAGER=1
- USE_RUNNING_SERVER=
+ USE_RUNNING_SERVER=0
;;
--start-and-exit)
START_AND_EXIT=1
@@ -374,7 +383,7 @@ while test $# -gt 0; do
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --gdb"
# This needs to be checked properly
# USE_MANAGER=1
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
;;
--client-gdb )
if [ x$BINARY_DIST = x1 ] ; then
@@ -387,7 +396,7 @@ while test $# -gt 0; do
--manual-gdb )
DO_GDB=1
MANUAL_GDB=1
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --gdb"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --gdb"
;;
@@ -396,7 +405,7 @@ while test $# -gt 0; do
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --ddd option"
fi
DO_DDD=1
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --gdb"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --gdb"
;;
@@ -409,12 +418,12 @@ while test $# -gt 0; do
fi
# >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr
valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck"
- VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16"
+ VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$CWD/valgrind.supp"
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc --skip-bdb"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc --skip-bdb"
SLEEP_TIME_AFTER_RESTART=10
SLEEP_TIME_FOR_DELETE=60
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
if test "$1" = "--valgrind-all"
then
VALGRIND="$VALGRIND -v --show-reachable=yes"
@@ -424,6 +433,9 @@ while test $# -gt 0; do
TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"`
VALGRIND="$VALGRIND $TMP"
;;
+ --valgrind-mysqltest)
+ DO_VALGRIND_MYSQL_TEST=1
+ ;;
--skip-ndbcluster | --skip-ndb)
USE_NDBCLUSTER=""
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-ndbcluster"
@@ -437,7 +449,7 @@ while test $# -gt 0; do
STRACE_CLIENT=1
;;
--debug)
- EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
+ EXTRA_MASTER_MYSQLD_TRACE=" \
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/master.trace"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/slave.trace"
@@ -445,6 +457,8 @@ while test $# -gt 0; do
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqltest.trace"
EXTRA_MYSQLDUMP_OPT="$EXTRA_MYSQLDUMP_OPT \
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqldump.trace"
+ EXTRA_MYSQLSHOW_OPT="$EXTRA_MYSQLSHOW_OPT \
+ --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlshow.trace"
EXTRA_MYSQLBINLOG_OPT="$EXTRA_MYSQLBINLOG_OPT \
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlbinlog.trace"
EXTRA_MYSQL_CLIENT_TEST_OPT="--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysql_client_test.trace"
@@ -452,6 +466,9 @@ while test $# -gt 0; do
--fast)
FAST_START=1
;;
+ --use-old-data)
+ USE_OLD_DATA=1;
+ ;;
-- ) shift; break ;;
--* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
* ) break ;;
@@ -489,10 +506,9 @@ 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 MASTER_MYPORT1 SLAVE_MYPORT MYSQL_TCP_PORT MASTER_MYSOCK MASTER_MYSOCK1
+export MASTER_MYPORT SLAVE_MYPORT MYSQL_TCP_PORT MASTER_MYSOCK MASTER_MYSOCK1
-NDBCLUSTER_BASE_PORT=`expr $NDBCLUSTER_PORT + 2`
-NDBCLUSTER_OPTS="--port=$NDBCLUSTER_PORT --port-base=$NDBCLUSTER_BASE_PORT --data-dir=$MYSQL_TEST_DIR/var --ndb_mgm-extra-opts=$NDB_MGM_EXTRA_OPTS --ndb_mgmd-extra-opts=$NDB_MGMD_EXTRA_OPTS --ndbd-extra-opts=$NDBD_EXTRA_OPTS"
+NDBCLUSTER_OPTS="--port=$NDBCLUSTER_PORT --data-dir=$MYSQL_TEST_DIR/var --ndb_mgm-extra-opts=$NDB_MGM_EXTRA_OPTS --ndb_mgmd-extra-opts=$NDB_MGMD_EXTRA_OPTS --ndbd-extra-opts=$NDBD_EXTRA_OPTS"
NDB_BACKUP_DIR=$MYSQL_TEST_DIR/var/ndbcluster-$NDBCLUSTER_PORT
NDB_TOOLS_OUTPUT=$MYSQL_TEST_DIR/var/log/ndb_tools.log
@@ -546,6 +562,11 @@ if [ x$SOURCE_DIST = x1 ] ; then
else
MYSQL_DUMP="$BASEDIR/client/mysqldump"
fi
+ if [ -f "$BASEDIR/client/.libs/mysqlshow" ] ; then
+ MYSQL_SHOW="$BASEDIR/client/.libs/mysqlshow"
+ else
+ MYSQL_SHOW="$BASEDIR/client/mysqlshow"
+ fi
if [ -f "$BASEDIR/client/.libs/mysqlbinlog" ] ; then
MYSQL_BINLOG="$BASEDIR/client/.libs/mysqlbinlog"
else
@@ -558,9 +579,10 @@ if [ x$SOURCE_DIST = x1 ] ; then
CLIENT_BINDIR="$BASEDIR/client"
MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
WAIT_PID="$BASEDIR/extra/mysql_waitpid"
- MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqlmanagerc"
- MYSQL_MANAGER="$BASEDIR/tools/mysqlmanager"
- MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqlmanager-pwgen"
+ MYSQL_MY_PRINT_DEFAULTS="$BASEDIR/extra/my_print_defaults"
+ MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqltestmanagerc"
+ MYSQL_MANAGER="$BASEDIR/tools/mysqltestmanager"
+ MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqltestmanager-pwgen"
MYSQL="$CLIENT_BINDIR/mysql"
LANGUAGE="$BASEDIR/sql/share/english/"
CHARSETSDIR="$BASEDIR/sql/share/charsets"
@@ -614,12 +636,14 @@ else
fi
MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
MYSQL_DUMP="$CLIENT_BINDIR/mysqldump"
+ MYSQL_SHOW="$CLIENT_BINDIR/mysqlshow"
MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog"
MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
WAIT_PID="$CLIENT_BINDIR/mysql_waitpid"
- MYSQL_MANAGER="$CLIENT_BINDIR/mysqlmanager"
- MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqlmanagerc"
- MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqlmanager-pwgen"
+ MYSQL_MY_PRINT_DEFAULTS="$CLIENT_BINDIR/my_print_defaults"
+ MYSQL_MANAGER="$CLIENT_BINDIR/mysqltestmanager"
+ MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqltestmanagerc"
+ MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqltestmanager-pwgen"
MYSQL="$CLIENT_BINDIR/mysql"
INSTALL_DB="./install_test_db --bin"
MYSQL_FIX_SYSTEM_TABLES="$CLIENT_BINDIR/mysql_fix_privilege_tables"
@@ -646,7 +670,7 @@ else
MYSQL_CLIENT_TEST="$CLIENT_BINDIR/mysql_client_test_embedded"
fi
else
- MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
+ MYSQL_TEST="$VALGRIND_MYSQLTEST $CLIENT_BINDIR/mysqltest"
MYSQL_CLIENT_TEST="$CLIENT_BINDIR/mysql_client_test"
fi
fi
@@ -661,13 +685,17 @@ then
SLAVE_MYSQLD=$MYSQLD
fi
+if [ x$DO_VALGRIND_MYSQL_TEST = x1 ] ; then
+ MYSQL_TEST="$VALGRIND $MYSQL_TEST"
+fi
+
# If we should run all tests cases, we will use a local server for that
if [ -z "$1" ]
then
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
fi
-if [ -n "$USE_RUNNING_SERVER" ]
+if [ $USE_RUNNING_SERVER -eq 1 ]
then
MASTER_MYSOCK=$LOCAL_SOCKET;
DBUSER=${DBUSER:-test}
@@ -693,11 +721,12 @@ fi
MYSQL_DUMP_DIR="$MYSQL_DUMP"
export MYSQL_DUMP_DIR
MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
-MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYSQLBINLOG_OPT"
+MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT"
+MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"
MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose"
MYSQL="$MYSQL --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD"
-export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES
-export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR
+export MYSQL MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES
+export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR MYSQL_MY_PRINT_DEFAULTS
export NDB_TOOLS_DIR
export NDB_MGM
export NDB_BACKUP_DIR
@@ -728,6 +757,8 @@ if [ -n "$DO_CLIENT_GDB" -o -n "$DO_GDB" ] ; then
XTERM=`which xterm`
fi
+export MYSQL MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES CLIENT_BINDIR MASTER_MYSOCK
+
#++
# Function Definitions
#--
@@ -838,6 +869,7 @@ report_current_test () {
fi
}
+
report_stats () {
if [ $TOT_FAIL = 0 ]; then
$ECHO "All $TOT_TEST tests were successful."
@@ -851,12 +883,12 @@ report_stats () {
$ECHO "Failed ${TOT_FAIL}/${TOT_TEST} tests, ${whole}.${deci}% were successful."
$ECHO ""
$ECHO "The log files in $MY_LOG_DIR may give you some hint"
- $ECHO "of what when wrong."
+ $ECHO "of what went wrong."
$ECHO "If you want to report this error, please read first the documentation at"
$ECHO "http://www.mysql.com/doc/en/MySQL_test_suite.html"
fi
- if test -z "$USE_RUNNING_SERVER"
+ if [ $USE_RUNNING_SERVER -eq 0 ]
then
# Report if there was any fatal warnings/errors in the log files
@@ -870,7 +902,7 @@ report_stats () {
found_error=0
# Find errors
- for i in "^Warning:" "^Error:" "^==.* at 0x"
+ for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning"
do
if $GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings
then
@@ -888,12 +920,14 @@ report_stats () {
mysql_install_db () {
$ECHO "Removing Stale Files"
- $RM -rf $MASTER_MYDDIR $MASTER_MYDDIR"1" $SLAVE_MYDDIR $MY_LOG_DIR/*
- $ECHO "Installing Master Databases"
- $INSTALL_DB
- if [ $? != 0 ]; then
+ if [ -z "$USE_OLD_DATA" ]; then
+ $RM -rf $MASTER_MYDDIR $MASTER_MYDDIR"1"
+ $ECHO "Installing Master Databases"
+ $INSTALL_DB
+ if [ $? != 0 ]; then
error "Could not install master test DBs"
- exit 1
+ exit 1
+ fi
fi
if [ ! -z "$USE_NDBCLUSTER" ]
then
@@ -905,6 +939,7 @@ mysql_install_db () {
fi
fi
$ECHO "Installing Slave Databases"
+ $RM -rf $SLAVE_MYDDIR $MY_LOG_DIR/*
$INSTALL_DB -slave
if [ $? != 0 ]; then
error "Could not install slave test DBs"
@@ -1140,6 +1175,10 @@ start_master()
this_master_myport=$MASTER_MYPORT
NOT_FIRST_MASTER_EXTRA_OPTS=""
fi
+ if [ -n "$EXTRA_MASTER_MYSQLD_TRACE" ]
+ then
+ CURR_MASTER_MYSQLD_TRACE="$EXTRA_MASTER_MYSQLD_TRACE$1"
+ fi
if [ -z "$DO_BENCH" ]
then
master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin$1 \
@@ -1158,12 +1197,13 @@ start_master()
--default-character-set=$CHARACTER_SET \
--tmpdir=$MYSQL_TMP_DIR \
--language=$LANGUAGE \
- --innodb_data_file_path=ibdata1:50M \
+ --innodb_data_file_path=ibdata1:128M:autoextend \
--open-files-limit=1024 \
+ --log-bin-trust-routine-creators \
$MASTER_40_ARGS \
$SMALL_SERVER \
$EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
- $NOT_FIRST_MASTER_EXTRA_OPTS"
+ $NOT_FIRST_MASTER_EXTRA_OPTS $CURR_MASTER_MYSQLD_TRACE"
else
master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin$1 \
--server-id=$id --rpl-recovery-rank=1 \
@@ -1179,7 +1219,8 @@ start_master()
$USE_NDBCLUSTER \
--tmpdir=$MYSQL_TMP_DIR \
--language=$LANGUAGE \
- --innodb_data_file_path=ibdata1:50M \
+ --innodb_data_file_path=ibdata1:128M:autoextend \
+ --log-bin-trust-routine-creators \
$MASTER_40_ARGS \
$SMALL_SERVER \
$EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
@@ -1312,6 +1353,7 @@ start_slave()
--report-port=$slave_port \
--master-retry-count=10 \
-O slave_net_timeout=10 \
+ --log-bin-trust-routine-creators \
$SMALL_SERVER \
$EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT"
CUR_MYERR=$slave_err
@@ -1440,18 +1482,21 @@ stop_master ()
mysql_stop ()
{
- $ECHO "Ending Tests"
- $ECHO "Shutting-down MySQL daemon"
- $ECHO ""
- stop_master
- stop_master 1
- $ECHO "Master shutdown finished"
- stop_slave
- stop_slave 1
- stop_slave 2
- $ECHO "Slave shutdown finished"
- stop_ndbcluster
- return 1
+ if [ "$MASTER_RUNNING" = 1 ]
+ then
+ $ECHO "Ending Tests"
+ $ECHO "Shutting-down MySQL daemon"
+ $ECHO ""
+ stop_master
+ stop_master 1
+ $ECHO "Master shutdown finished"
+ stop_slave
+ stop_slave 1
+ stop_slave 2
+ $ECHO "Slave shutdown finished"
+ stop_ndbcluster
+ fi
+ return 1
}
mysql_restart ()
@@ -1479,13 +1524,7 @@ run_testcase ()
tsrcdir=$TESTDIR/$tname-src
result_file="r/$tname.result"
echo $tname > $CURRENT_TEST
- SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
- if [ -f "$TESTDIR/$tname.disabled" ]
- then
- comment=`$CAT $TESTDIR/$tname.disabled`;
- disable_test $tname "$comment"
- return
- fi
+ SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0 \& \( $tname : federated \) = 0`
if [ "$USE_MANAGER" = 1 ] ; then
many_slaves=`$EXPR \( \( $tname : rpl_failsafe \) != 0 \) \| \( \( $tname : rpl_chain_temp_table \) != 0 \)`
fi
@@ -1515,6 +1554,22 @@ run_testcase ()
return
fi
+# if [ -f "$TESTDIR/$tname.disabled" ]
+# then
+# comment=`$CAT $TESTDIR/$tname.disabled`;
+# disable_test $tname "$comment"
+# return
+# fi
+ if [ -f "$TESTDIR/disabled.def" ] ; then
+ comment=`$GREP "^$tname *: *" $TESTDIR/disabled.def`;
+ if [ -n "$comment" ]
+ then
+ comment=`echo $comment | sed 's/^[^:]*: *//'`
+ disable_test $tname "$comment"
+ return
+ fi
+ fi
+
if [ "x$USE_EMBEDDED_SERVER" != "x1" ] ; then
# Stop all slave threads, so that we don't have useless reconnection
# attempts and error messages in case the slave and master servers restart.
@@ -1537,7 +1592,7 @@ run_testcase ()
done
fi
- if [ -z "$USE_RUNNING_SERVER" ] ;
+ if [ $USE_RUNNING_SERVER -eq 0 ] ;
then
if [ -f $master_opt_file ] ;
then
@@ -1679,7 +1734,7 @@ run_testcase ()
if [ x$FORCE != x1 ] ; then
$ECHO "Aborting: $tname failed in $TEST_MODE mode. To continue, re-run with '--force'."
$ECHO
- if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && \
+ if [ -z "$DO_GDB" ] && [ $USE_RUNNING_SERVER -eq 0 ] && \
[ -z "$DO_DDD" ] && [ -z "$USE_EMBEDDED_SERVER" ]
then
mysql_stop
@@ -1688,13 +1743,11 @@ run_testcase ()
exit 1
fi
FAILED_CASES="$FAILED_CASES $tname"
- if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && \
+ if [ -z "$DO_GDB" ] && [ $USE_RUNNING_SERVER -eq 0 ] && \
[ -z "$DO_DDD" ] && [ -z "$USE_EMBEDDED_SERVER" ]
then
mysql_restart
fi
- $ECHO "Resuming Tests"
- $ECHO ""
fi
fi
fi
@@ -1709,7 +1762,7 @@ run_testcase ()
[ "$DO_GCOV" ] && gcov_prepare
[ "$DO_GPROF" ] && gprof_prepare
-if [ -z "$USE_RUNNING_SERVER" ]
+if [ $USE_RUNNING_SERVER -eq 0 ]
then
if [ -z "$FAST_START" ]
then
@@ -1718,7 +1771,7 @@ then
$MYSQLADMIN --no-defaults --socket=$MASTER_MYSOCK1 -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
$MYSQLADMIN --no-defaults --socket=$SLAVE_MYSOCK -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
$MYSQLADMIN --no-defaults --host=$hostname --port=$MASTER_MYPORT -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
- $MYSQLADMIN --no-defaults --host=$hostname --port=$MASTER_MYPORT+1 -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
+ $MYSQLADMIN --no-defaults --host=$hostname --port=`expr $MASTER_MYPORT+1` -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
$MYSQLADMIN --no-defaults --host=$hostname --port=$SLAVE_MYPORT -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
$MYSQLADMIN --no-defaults --host=$hostname --port=`expr $SLAVE_MYPORT + 1` -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
sleep_until_file_deleted 0 $MASTER_MYPID
@@ -1755,6 +1808,11 @@ then
$ECHO "Installing Test Databases"
mysql_install_db
+ if [ -n "$1" -a `expr "X$*" : '.*ndb'` -eq 0 ]
+ then
+ USE_NDBCLUSTER=""
+ fi
+
start_manager
# Do not automagically start daemons if we are in gdb or running only one test
@@ -1769,6 +1827,9 @@ fi
$ECHO "Starting Tests"
+# Some test cases need USE_RUNNING_SERVER
+export USE_RUNNING_SERVER
+
#
# This can probably be deleted
#
@@ -1841,7 +1902,7 @@ fi
$ECHO $DASH72
$ECHO
-if [ -z "$DO_GDB" ] && [ -z "$USE_RUNNING_SERVER" ] && [ -z "$DO_DDD" ]
+if [ -z "$DO_GDB" ] && [ $USE_RUNNING_SERVER -eq 0 ] && [ -z "$DO_DDD" ]
then
mysql_stop
fi
diff --git a/mysql-test/mysql_test_run_new.c b/mysql-test/mysql_test_run_new.c
index 40e45a92851..b23b7ceb6a1 100644
--- a/mysql-test/mysql_test_run_new.c
+++ b/mysql-test/mysql_test_run_new.c
@@ -486,6 +486,7 @@ void start_master()
#endif
add_arg(&al, "--local-infile");
add_arg(&al, "--core");
+ add_arg(&al, "--log-bin-trust-routine-creators");
add_arg(&al, "--datadir=%s", master_dir);
#ifndef __WIN__
add_arg(&al, "--pid-file=%s", master_pid);
@@ -1345,11 +1346,11 @@ void setup(char *file __attribute__((unused)))
#endif /* HAVE_OPENSSL */
/* OpenSSL paths */
- snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir);
- snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir);
- snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir);
- snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir);
- snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir);
+ snprintf(ca_cert, FN_REFLEN, "%s/std_data/cacert.pem", mysql_test_dir);
+ snprintf(server_cert, FN_REFLEN, "%s/std_data/server-cert.pem", mysql_test_dir);
+ snprintf(server_key, FN_REFLEN, "%s/std_data/server-key.pem", mysql_test_dir);
+ snprintf(client_cert, FN_REFLEN, "%s/std_data/client-cert.pem", mysql_test_dir);
+ snprintf(client_key, FN_REFLEN, "%s/std_data/client-key.pem", mysql_test_dir);
/* setup files */
snprintf(mysqld_file, FN_REFLEN, "%s/mysqld", bin_dir);
@@ -1378,11 +1379,11 @@ void setup(char *file __attribute__((unused)))
#endif /* HAVE_OPENSSL */
/* OpenSSL paths */
- snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir);
- snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir);
- snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir);
- snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir);
- snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir);
+ snprintf(ca_cert, FN_REFLEN, "%s/std_data/cacert.pem", mysql_test_dir);
+ snprintf(server_cert, FN_REFLEN, "%s/std_data/server-cert.pem", mysql_test_dir);
+ snprintf(server_key, FN_REFLEN, "%s/std_data/server-key.pem", mysql_test_dir);
+ snprintf(client_cert, FN_REFLEN, "%s/std_data/client-cert.pem", mysql_test_dir);
+ snprintf(client_key, FN_REFLEN, "%s/std_data/client-key.pem", mysql_test_dir);
/* setup files */
#ifdef _DEBUG
@@ -1411,11 +1412,11 @@ void setup(char *file __attribute__((unused)))
#endif /* HAVE_OPENSSL */
/* OpenSSL paths */
- snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir);
- snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir);
- snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir);
- snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir);
- snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir);
+ snprintf(ca_cert, FN_REFLEN, "%s/std_data/cacert.pem", mysql_test_dir);
+ snprintf(server_cert, FN_REFLEN, "%s/std_data/server-cert.pem", mysql_test_dir);
+ snprintf(server_key, FN_REFLEN, "%s/std_data/server-key.pem", mysql_test_dir);
+ snprintf(client_cert, FN_REFLEN, "%s/std_data/client-cert.pem", mysql_test_dir);
+ snprintf(client_key, FN_REFLEN, "%s/std_data/client-key.pem", mysql_test_dir);
/* setup files */
snprintf(mysqld_file, FN_REFLEN, "%s/sql/mysqld", base_dir);
@@ -1507,9 +1508,12 @@ void setup(char *file __attribute__((unused)))
static char env_CHARSETSDIR[FN_REFLEN*2];
static char env_MYSQL[FN_REFLEN*2];
static char env_MYSQL_FIX_SYSTEM_TABLES[FN_REFLEN*2];
- static char env_NDB_TOOLS_DIR[FN_REFLEN*2];
static char env_CLIENT_BINDIR[FN_REFLEN*2];
static char env_MYSQL_CLIENT_TEST[FN_REFLEN*2];
+ static char env_NDB_TOOLS_DIR[FN_REFLEN*2];
+ static char env_NDB_MGM[FN_REFLEN*2];
+ static char env_NDB_BACKUP_DIR[FN_REFLEN*2];
+ static char env_NDB_TOOLS_OUTPUT[FN_REFLEN*2];
snprintf(env_MYSQL_TEST_DIR,FN_REFLEN*2,
"MYSQL_TEST_DIR=%s",mysql_test_dir);
@@ -1549,9 +1553,6 @@ void setup(char *file __attribute__((unused)))
base_dir,master_port, master_socket, base_dir, bin_dir);
putenv(env_MYSQL_FIX_SYSTEM_TABLES);
- snprintf(env_NDB_TOOLS_DIR, FN_REFLEN*2,
- "NDB_TOOLS_DIR=%s/ndb/tools", base_dir);
- putenv(env_NDB_TOOLS_DIR);
snprintf(env_CLIENT_BINDIR, FN_REFLEN*2,
"CLIENT_BINDIR=%s", bin_dir);
@@ -1563,6 +1564,30 @@ void setup(char *file __attribute__((unused)))
base_dir, master_socket, master_port);
putenv(env_MYSQL_CLIENT_TEST);
+ // NDB
+
+ snprintf(env_NDB_TOOLS_DIR, FN_REFLEN*2,
+ "NDB_TOOLS_DIR=%s/ndb/tools", base_dir);
+ putenv(env_NDB_TOOLS_DIR);
+
+ snprintf(env_NDB_MGM, FN_REFLEN*2,
+ "NDB_MGM=%s/ndb/src/mgmclient/ndb_mgm", base_dir);
+ putenv(env_NDB_MGM);
+
+ //NDBCLUSTER_PORT=9350
+ snprintf(env_NDB_BACKUP_DIR, FN_REFLEN*2,
+ "NDB_BACKUP_DIR=%s/var/ndbcluster-%i", mysql_test_dir, 9350);
+ putenv(env_NDB_BACKUP_DIR);
+
+ snprintf(env_NDB_TOOLS_OUTPUT, FN_REFLEN*2,
+ "NDB_TOOLS_OUTPUT=%s/var/log/ndb_tools.log", mysql_test_dir);
+ putenv(env_NDB_TOOLS_OUTPUT);
+
+ putenv((char *)"NDB_STATUS_OK=1");
+
+// NDB_MGM="$BASEDIR/ndb/src/mgmclient/ndb_mgm"
+// NDB_BACKUP_DIR=$MYSQL_TEST_DIR/var/ndbcluster-$NDBCLUSTER_PORT
+// NDB_TOOLS_OUTPUT=$MYSQL_TEST_DIR/var/log/ndb_tools.log
}
#endif
diff --git a/mysql-test/ndb/Makefile.am b/mysql-test/ndb/Makefile.am
index 502ccee099e..178e40fb19a 100644
--- a/mysql-test/ndb/Makefile.am
+++ b/mysql-test/ndb/Makefile.am
@@ -14,7 +14,6 @@ SUFFIXES = .sh
@RM@ -f $@ $@-t
@SED@ \
-e 's!@''ndb_port''@!$(ndb_port)!g' \
- -e 's!@''ndb_port_base''@!$(ndb_port_base)!g' \
-e 's!@''ndbbindir''@!$(ndbbindir)!g' \
-e 's!@''ndbtoolsdir''@!$(ndbtoolsdir)!g' \
$< > $@-t
diff --git a/mysql-test/ndb/basic.result b/mysql-test/ndb/basic.result
index 5ebd20a7f83..9d2b18881b9 100644
--- a/mysql-test/ndb/basic.result
+++ b/mysql-test/ndb/basic.result
@@ -26,17 +26,17 @@ CONNECT [<connectstring>] Connect to management server (reconnect i
QUIT Quit management client
<severity> = ALERT | CRITICAL | ERROR | WARNING | INFO | DEBUG
-<category> = STARTUP | SHUTDOWN | STATISTICS | CHECKPOINT | NODERESTART | CONNECTION | INFO | ERROR | GREP | DEBUG | BACKUP
+<category> = STARTUP | SHUTDOWN | STATISTICS | CHECKPOINT | NODERESTART | CONNECTION | INFO | ERROR | CONGESTION | DEBUG | BACKUP
<level> = 0 - 15
<id> = ALL | Any database node id
Connected to Management Server at: localhost:1186
-Node 1: started (Version 4.1.9)
-Node 2: started (Version 4.1.9)
+Node 1: started (Version 5.0.3)
+Node 2: started (Version 5.0.3)
-Node 1: started (Version 4.1.9)
+Node 1: started (Version 5.0.3)
-Node 2: started (Version 4.1.9)
+Node 2: started (Version 5.0.3)
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
diff --git a/mysql-test/ndb/ndb_config_2_node.ini b/mysql-test/ndb/ndb_config_2_node.ini
index c831a5c7ffa..a6a56376f33 100644
--- a/mysql-test/ndb/ndb_config_2_node.ini
+++ b/mysql-test/ndb/ndb_config_2_node.ini
@@ -15,6 +15,7 @@ HostName= CHOOSE_HOSTNAME_1 # hostname is a valid network adress
HostName= CHOOSE_HOSTNAME_2 # hostname is a valid network adress
[ndb_mgmd]
+HostName= CHOOSE_HOSTNAME_1 # hostname is a valid network adress
DataDir= CHOOSE_FILESYSTEM #
PortNumber= CHOOSE_PORT_MGM
@@ -25,6 +26,3 @@ PortNumber= CHOOSE_PORT_MGM
[mysqld]
[mysqld]
-
-[tcp default]
-PortNumber= CHOOSE_PORT_TRANSPORTER
diff --git a/mysql-test/ndb/ndb_range_bounds.pl b/mysql-test/ndb/ndb_range_bounds.pl
index 75b7f8a33e1..abe1ea28298 100644
--- a/mysql-test/ndb/ndb_range_bounds.pl
+++ b/mysql-test/ndb/ndb_range_bounds.pl
@@ -1,138 +1,218 @@
#
# test range scan bounds
-# output to mysql-test/t/ndb_range_bounds.test
-#
-# give option --all to generate all cases
+# give option --all to test all cases
+# set MYSQL_HOME to installation top
#
use strict;
use integer;
use Getopt::Long;
+use DBI;
my $opt_all = 0;
my $opt_cnt = 5;
-GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt)
- or die "options are: --all --cnt=N";
+my $opt_verbose = 0;
+GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt, "verbose" => \$opt_verbose)
+ or die "options are: --all --cnt=N --verbose";
-my $table = 't';
+my $mysql_home = $ENV{MYSQL_HOME};
+defined($mysql_home) or die "no MYSQL_HOME";
+my $dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$mysql_home/var/my.cnf";
+my $opts = { RaiseError => 0, PrintError => 0, AutoCommit => 1, };
-print <<EOF;
---source include/have_ndb.inc
+my $dbh;
+my $sth;
+my $sql;
---disable_warnings
-drop table if exists $table;
---enable_warnings
+$dbh = DBI->connect($dsn, "root", undef, $opts) or die $DBI::errstr;
-# test range scan bounds
-# generated by mysql-test/ndb/ndb_range_bounds.pl
-# all selects must return 0
+my $table = 't';
-EOF
+$sql = "drop table if exists $table";
+$dbh->do($sql) or die $DBI::errstr;
-sub cut ($$@) {
- my($op, $key, @v) = @_;
+sub cut ($$$) {
+ my($op, $key, $val) = @_;
$op = '==' if $op eq '=';
- my(@w);
- eval "\@w = grep(\$_ $op $key, \@v)";
+ my(@w) = @$val;
+ eval "\@w = grep(\$_ $op $key, \@w)";
$@ and die $@;
- return @w;
+ return [ @w ];
}
-sub mkdummy (\@) {
+sub mkdummy ($) {
my ($val) = @_;
return {
'dummy' => 1,
'exp' => '9 = 9',
- 'cnt' => scalar @$val,
+ 'res' => $val,
};
}
-sub mkone ($$$\@) {
+sub mkone ($$$$) {
my($col, $op, $key, $val) = @_;
- my $cnt = scalar cut($op, $key, @$val);
+ my $res = cut($op, $key, $val);
return {
'exp' => "$col $op $key",
- 'cnt' => $cnt,
+ 'res' => $res,
};
}
-sub mktwo ($$$$$\@) {
+sub mktwo ($$$$$$) {
my($col, $op1, $key1, $op2, $key2, $val) = @_;
- my $cnt = scalar cut($op2, $key2, cut($op1, $key1, @$val));
+ my $res = cut($op2, $key2, cut($op1, $key1, $val));
return {
'exp' => "$col $op1 $key1 and $col $op2 $key2",
- 'cnt' => $cnt,
+ 'res' => $res,
};
}
-sub mkall ($$$\@) {
+sub mkall ($$$$) {
my($col, $key1, $key2, $val) = @_;
my @a = ();
- my $p = mkdummy(@$val);
+ my $p = mkdummy($val);
push(@a, $p) if $opt_all;
my @ops = qw(< <= = >= >);
for my $op (@ops) {
- my $p = mkone($col, $op, $key1, @$val);
- push(@a, $p) if $opt_all || $p->{cnt} != 0;
+ my $p = mkone($col, $op, $key1, $val);
+ push(@a, $p) if $opt_all || @{$p->{res}} != 0;
}
my @ops1 = $opt_all ? @ops : qw(= >= >);
my @ops2 = $opt_all ? @ops : qw(<= <);
for my $op1 (@ops1) {
for my $op2 (@ops2) {
- my $p = mktwo($col, $op1, $key1, $op2, $key2, @$val);
- push(@a, $p) if $opt_all || $p->{cnt} != 0;
+ my $p = mktwo($col, $op1, $key1, $op2, $key2, $val);
+ push(@a, $p) if $opt_all || @{$p->{res}} != 0;
}
}
+ warn scalar(@a)." cases\n" if $opt_verbose;
return \@a;
}
+my $casecnt = 0;
+
+sub verify ($$$) {
+ my($sql, $ord, $res) = @_;
+ warn "$sql\n" if $opt_verbose;
+ $sth = $dbh->prepare($sql) or die "prepare: $sql: $DBI::errstr";
+ $sth->execute() or die "execute: $sql: $DBI::errstr";
+ #
+ # BUG: execute can return success on error so check again
+ #
+ $sth->err and die "execute: $sql: $DBI::errstr";
+ my @out = ();
+ for my $b (@{$res->[0]}) {
+ for my $c (@{$res->[1]}) {
+ for my $d (@{$res->[2]}) {
+ push(@out, [$b, $c, $d]);
+ }
+ }
+ }
+ if ($ord) {
+ @out = sort {
+ $ord * ($a->[0] - $b->[0]) ||
+ $ord * ($a->[1] - $b->[1]) ||
+ $ord * ($a->[2] - $b->[2]) ||
+ 0
+ } @out;
+ }
+ my $cnt = scalar @out;
+ my $n = 0;
+ while (1) {
+ my $row = $sth->fetchrow_arrayref;
+ $row || last;
+ @$row == 3 or die "bad row: $sql: @$row";
+ for my $v (@$row) {
+ $v =~ s/^\s+|\s+$//g;
+ $v =~ /^\d+$/ or die "bad value: $sql: $v";
+ }
+ if ($ord) {
+ my $out = $out[$n];
+ $row->[0] == $out->[0] &&
+ $row->[1] == $out->[1] &&
+ $row->[2] == $out->[2] or
+ die "$sql: row $n: got row @$row != @$out";
+ }
+ $n++;
+ }
+ $sth->err and die "fetch: $sql: $DBI::errstr";
+ $n == $cnt or die "verify: $sql: got row count $n != $cnt";
+ $casecnt++;
+}
+
for my $nn ("bcd", "") {
my %nn;
for my $x (qw(b c d)) {
$nn{$x} = $nn =~ /$x/ ? "not null" : "null";
}
- print <<EOF;
+ warn "create table\n";
+ $sql = <<EOF;
create table $table (
a int primary key,
b int $nn{b},
c int $nn{c},
d int $nn{d},
index (b, c, d)
-) engine=ndb;
+) engine=ndb
EOF
+ $dbh->do($sql) or die $DBI::errstr;
+ warn "insert\n";
+ $sql = "insert into $table values(?, ?, ?, ?)";
+ $sth = $dbh->prepare($sql) or die $DBI::errstr;
my @val = (0..($opt_cnt-1));
my $v0 = 0;
for my $v1 (@val) {
for my $v2 (@val) {
for my $v3 (@val) {
- print "insert into $table values($v0, $v1, $v2, $v3);\n";
+ $sth->bind_param(1, $v0) or die $DBI::errstr;
+ $sth->bind_param(2, $v1) or die $DBI::errstr;
+ $sth->bind_param(3, $v2) or die $DBI::errstr;
+ $sth->bind_param(4, $v3) or die $DBI::errstr;
+ $sth->execute or die $DBI::errstr;
$v0++;
}
}
}
+ warn "generate cases\n";
my $key1 = 1;
my $key2 = 3;
- my $a1 = mkall('b', $key1, $key2, @val);
- my $a2 = mkall('c', $key1, $key2, @val);
- my $a3 = mkall('d', $key1, $key2, @val);
- for my $p1 (@$a1) {
- my $cnt1 = $p1->{cnt} * @val * @val;
- print "select count(*) - $cnt1 from $table";
- print " where $p1->{exp};\n";
- for my $p2 (@$a2) {
- my $cnt2 = $p1->{cnt} * $p2->{cnt} * @val;
- print "select count(*) - $cnt2 from $table";
- print " where $p1->{exp} and $p2->{exp};\n";
- for my $p3 (@$a3) {
- my $cnt3 = $p1->{cnt} * $p2->{cnt} * $p3->{cnt};
- print "select count(*) - $cnt3 from $table";
- print " where $p1->{exp} and $p2->{exp} and $p3->{exp};\n";
+ my $a1 = mkall('b', $key1, $key2, \@val);
+ my $a2 = mkall('c', $key1, $key2, \@val);
+ my $a3 = mkall('d', $key1, $key2, \@val);
+ warn "select\n";
+ for my $ord (0, +1, -1) {
+ my $orderby =
+ $ord == 0 ? "" :
+ $ord == +1 ? " order by b, c, d" :
+ $ord == -1 ? " order by b desc, c desc, d desc" : die "not here";
+ for my $p1 (@$a1) {
+ my $res = [ $p1->{res}, \@val, \@val ];
+ $sql = "select b, c, d from $table" .
+ " where $p1->{exp}" .
+ $orderby;
+ verify($sql, $ord, $res);
+ for my $p2 (@$a2) {
+ my $res = [ $p1->{res}, $p2->{res}, \@val ];
+ $sql = "select b, c, d from $table" .
+ " where $p1->{exp} and $p2->{exp}" .
+ $orderby;
+ verify($sql, $ord, $res);
+ for my $p3 (@$a3) {
+ my $res = [ $p1->{res}, $p2->{res}, $p3->{res} ];
+ $sql = "select b, c, d from $table" .
+ " where $p1->{exp} and $p2->{exp} and $p3->{exp}" .
+ $orderby;
+ verify($sql, $ord, $res);
+ }
}
}
}
- print <<EOF;
-drop table $table;
-EOF
+ warn "drop table\n";
+ $sql = "drop table $table";
+ $dbh->do($sql) or die $DBI::errstr;
}
+warn "verified $casecnt cases\n";
+warn "done\n";
+
# vim: set sw=2:
diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh
index 16bb3a9b122..c09c013552e 100644
--- a/mysql-test/ndb/ndbcluster.sh
+++ b/mysql-test/ndb/ndbcluster.sh
@@ -6,7 +6,6 @@
# configurable parameters, make sure to change in mysqlcluterd as well
port=@ndb_port@
-port_base=@ndb_port_base@
fsdir=`pwd`
# end configurable parameters
@@ -96,7 +95,7 @@ while test $# -gt 0; do
port=`echo "$1" | sed -e "s;--port=;;"`
;;
--port-base=*)
- port_base=`echo "$1" | sed -e "s;--port-base=;;"`
+ $ECHO "--port-base option depricated. Ignored."
;;
--ndb_mgm-extra-opts=*)
NDB_MGM_EXTRA_OPTS=`echo "$1" | sed -e "s;--ndb_mgm-extra-opts=;;"`
@@ -192,7 +191,6 @@ if [ $initial_ndb ] ; then
-e s,"CHOOSE_HOSTNAME_".*,"$ndb_host",g \
-e s,"CHOOSE_FILESYSTEM","$fs_ndb",g \
-e s,"CHOOSE_PORT_MGM","$ndb_mgmd_port",g \
- -e s,"CHOOSE_PORT_TRANSPORTER","$port_base",g \
< ndb/ndb_config_2_node.ini \
> "$fs_ndb/config.ini"
fi
diff --git a/mysql-test/ndb/restart.test b/mysql-test/ndb/restart.test
index 6ea9e919368..4b4584dd739 100644
--- a/mysql-test/ndb/restart.test
+++ b/mysql-test/ndb/restart.test
@@ -8,5 +8,5 @@ sleep 5
all clusterlog connection=8
sleep 1
1 restart
-sleep 5
+sleep 10
clusterlog on all
diff --git a/mysql-test/r/alias.result b/mysql-test/r/alias.result
index 587c21e9129..6f0315da234 100644
--- a/mysql-test/r/alias.result
+++ b/mysql-test/r/alias.result
@@ -27,7 +27,7 @@ hdl_name varchar(30) default NULL,
prov_hdl_nr int(11) NOT NULL default '0',
auto_wirknetz varchar(50) default NULL,
auto_billing varchar(50) default NULL,
-touch timestamp(14) NOT NULL,
+touch timestamp NOT NULL,
kategorie varchar(50) default NULL,
kundentyp varchar(20) NOT NULL default '',
sammel_rech_msisdn varchar(30) NOT NULL default '',
@@ -58,6 +58,8 @@ INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05
SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie;
Kundentyp kategorie
Privat (Private Nutzung) Mobilfunk
+Warnings:
+Warning 1052 Column 'kundentyp' in group statement is ambiguous
drop table t1;
CREATE TABLE t1 (
AUFNR varchar(12) NOT NULL default '',
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index e9c9c873750..6a710a8de10 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -52,9 +52,9 @@ KEY NAME (NAME));
ALTER TABLE t1 CHANGE NAME NAME CHAR(80) not null;
SHOW FULL COLUMNS FROM t1;
Field Type Collation Null Key Default Extra Privileges Comment
-GROUP_ID int(10) unsigned NULL PRI 0 #
-LANG_ID smallint(5) unsigned NULL PRI 0 #
-NAME char(80) latin1_swedish_ci MUL #
+GROUP_ID int(10) unsigned NULL NO PRI 0 #
+LANG_ID smallint(5) unsigned NULL NO PRI 0 #
+NAME char(80) latin1_swedish_ci NO MUL #
DROP TABLE t1;
create table t1 (n int);
insert into t1 values(9),(3),(12),(10);
@@ -179,7 +179,7 @@ alter table t1 rename t2;
alter table t2 rename t1, add c char(10) comment "no comment";
show columns from t1;
Field Type Null Key Default Extra
-i int(10) unsigned PRI NULL auto_increment
+i int(10) unsigned NO PRI NULL auto_increment
c char(10) YES NULL
drop table t1;
create table t1 (a int, b int);
@@ -314,7 +314,7 @@ INSERT INTO t1 VALUES ('localhost','root'),('localhost',''),('games','monty');
SHOW INDEX FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE
-t1 0 PRIMARY 2 User A 3 NULL NULL BTREE
+t1 0 PRIMARY 2 User A 0 NULL NULL BTREE
ALTER TABLE t1 ENABLE KEYS;
UNLOCK TABLES;
CHECK TABLES t1;
@@ -338,7 +338,7 @@ INSERT INTO t1 VALUES ('localhost','root'),('localhost','');
SHOW INDEX FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE
-t1 0 PRIMARY 2 User A 2 NULL NULL BTREE
+t1 0 PRIMARY 2 User A 0 NULL NULL BTREE
t1 1 Host 1 Host A NULL NULL NULL BTREE disabled
ALTER TABLE t1 ENABLE KEYS;
SHOW INDEX FROM t1;
@@ -389,7 +389,7 @@ alter table t1 modify a varchar(10);
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `a` varchar(10) NOT NULL default '',
+ `a` varchar(10) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`)
flush tables;
@@ -397,7 +397,7 @@ alter table t1 modify a varchar(10) not null;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `a` varchar(10) NOT NULL default '',
+ `a` varchar(10) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`)
drop table if exists t1, t2;
@@ -405,17 +405,26 @@ create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, p
insert into t1 (a) values(1);
show table status 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 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL
+t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL
alter table t1 modify a int;
show table status 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 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL
+t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL
drop table t1;
create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM;
insert into t1 (a) values(1);
+Warnings:
+Warning 1364 Field 'b' doesn't have a default value
+Warning 1364 Field 'c' doesn't have a default value
+Warning 1364 Field 'd' doesn't have a default value
+Warning 1364 Field 'e' doesn't have a default value
+Warning 1364 Field 'f' doesn't have a default value
+Warning 1364 Field 'g' doesn't have a default value
+Warning 1364 Field 'h' doesn't have a default value
+Warning 1364 Field 'i' doesn't have a default value
show table status 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 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL
+t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL
drop table t1;
set names koi8r;
create table t1 (a char(10) character set koi8r);
@@ -501,7 +510,7 @@ ALTER TABLE t1 DROP PRIMARY KEY;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` int(11) default NULL,
UNIQUE KEY `b` (`b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -514,6 +523,10 @@ 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;
+CREATE TABLE T12207(a int) ENGINE=MYISAM;
+ALTER TABLE T12207 DISCARD TABLESPACE;
+ERROR HY000: Table storage engine for 'T12207' doesn't have this option
+DROP TABLE T12207;
create table t1 (a text) character set koi8r;
insert into t1 values (_koi8r'ÔÅÓÔ');
select hex(a) from t1;
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index 0ebd4a3e409..df524b491f1 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -36,16 +36,16 @@ create table t2 select * from t1 where 0=1 procedure analyse();
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `Field_name` binary(255) NOT NULL default '',
- `Min_value` binary(255) default NULL,
- `Max_value` binary(255) default NULL,
+ `Field_name` varbinary(255) NOT NULL default '',
+ `Min_value` varbinary(255) default NULL,
+ `Max_value` varbinary(255) default NULL,
`Min_length` bigint(11) NOT NULL default '0',
`Max_length` bigint(11) NOT NULL default '0',
`Empties_or_zeros` bigint(11) NOT NULL default '0',
`Nulls` bigint(11) NOT NULL default '0',
- `Avg_value_or_avg_length` binary(255) NOT NULL default '',
- `Std` binary(255) default NULL,
- `Optimal_fieldtype` binary(64) NOT NULL default ''
+ `Avg_value_or_avg_length` varbinary(255) NOT NULL default '',
+ `Std` varbinary(255) default NULL,
+ `Optimal_fieldtype` varbinary(64) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1 where 0=1 procedure analyse();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
@@ -55,16 +55,16 @@ create table t2 select * from t1 where 0=1 procedure analyse();
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `Field_name` binary(255) NOT NULL default '',
- `Min_value` binary(255) default NULL,
- `Max_value` binary(255) default NULL,
+ `Field_name` varbinary(255) NOT NULL default '',
+ `Min_value` varbinary(255) default NULL,
+ `Max_value` varbinary(255) default NULL,
`Min_length` bigint(11) NOT NULL default '0',
`Max_length` bigint(11) NOT NULL default '0',
`Empties_or_zeros` bigint(11) NOT NULL default '0',
`Nulls` bigint(11) NOT NULL default '0',
- `Avg_value_or_avg_length` binary(255) NOT NULL default '',
- `Std` binary(255) default NULL,
- `Optimal_fieldtype` binary(64) NOT NULL default ''
+ `Avg_value_or_avg_length` varbinary(255) NOT NULL default '',
+ `Std` varbinary(255) default NULL,
+ `Optimal_fieldtype` varbinary(64) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t2;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
@@ -78,16 +78,16 @@ create table t2 select * from t1 where 0=1 procedure analyse();
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `Field_name` binary(255) NOT NULL default '',
- `Min_value` binary(255) default NULL,
- `Max_value` binary(255) default NULL,
+ `Field_name` varbinary(255) NOT NULL default '',
+ `Min_value` varbinary(255) default NULL,
+ `Max_value` varbinary(255) default NULL,
`Min_length` bigint(11) NOT NULL default '0',
`Max_length` bigint(11) NOT NULL default '0',
`Empties_or_zeros` bigint(11) NOT NULL default '0',
`Nulls` bigint(11) NOT NULL default '0',
- `Avg_value_or_avg_length` binary(255) NOT NULL default '',
- `Std` binary(255) default NULL,
- `Optimal_fieldtype` binary(64) NOT NULL default ''
+ `Avg_value_or_avg_length` varbinary(255) NOT NULL default '',
+ `Std` varbinary(255) default NULL,
+ `Optimal_fieldtype` varbinary(64) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t2;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
@@ -102,6 +102,13 @@ select * from t1 procedure analyse();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t1.v " \\ 1 19 0 0 3.7619 NULL ENUM('"','""','"c','\'\0\\"','\'','\'\'','\'b','a\0\0\0b','a\0','a""""b','a\'\'\'\'b','abc','abc\'def\\hij"klm\0opq','a\\\\\\\\b','b\'','c"','d\\','The\ZEnd','\\','\\d','\\\\') NOT NULL
drop table t1;
+create table t1 (df decimal(5,1));
+insert into t1 values(1.1);
+insert into t1 values(2.2);
+select * from t1 procedure analyse();
+Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
+test.t1.df 1.1 2.2 8 8 0 0 1.650000000 0.302500000 ENUM('1.1','2.2') NOT NULL
+drop table t1;
create table t1 (d double);
insert into t1 values (100000);
select * from t1 procedure analyse (1,1);
diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result
index 212d28f918b..00a526df8ea 100644
--- a/mysql-test/r/ansi.result
+++ b/mysql-test/r/ansi.result
@@ -2,7 +2,7 @@ drop table if exists t1;
set sql_mode="MySQL40";
select @@sql_mode;
@@sql_mode
-NO_FIELD_OPTIONS,MYSQL40
+NO_FIELD_OPTIONS,MYSQL40,HIGH_NOT_PRECEDENCE
set @@sql_mode="ANSI";
select @@sql_mode;
@@sql_mode
diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result
index 246e96bf993..075f0f716d2 100644
--- a/mysql-test/r/archive.result
+++ b/mysql-test/r/archive.result
@@ -184,6 +184,22 @@ fld1 fld3
250503 heaving
250504 population
250505 bomb
+create table t3 engine=archive select * from t2;
+select * from t3 where fld3='bonfire';
+auto fld1 companynr fld3 fld4 fld5 fld6
+1191 068504 00 bonfire corresponds positively
+select count(*) from t3;
+count(*)
+1199
+rename table t3 to t4;
+Warnings:
+Error 7 Error on rename of './test/t3.ARN' to './test/t4.ARN' (Errcode: 2)
+select * from t4 where fld3='bonfire';
+auto fld1 companynr fld3 fld4 fld5 fld6
+1191 068504 00 bonfire corresponds positively
+select count(*) from t4;
+count(*)
+1199
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','');
@@ -2601,20 +2617,3644 @@ auto fld1 companynr fld3 fld4 fld5 fld6
2 011401 37 breaking dreaded Steinberg W
3 011402 37 Romans scholastics jarring
4 011403 37 intercepted audiology tinily
-create table t3 engine=archive select * from t2;
-select * from t3 where fld3='bonfire';
+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','');
+OPTIMIZE TABLE t2 EXTENDED;
+Table Op Msg_type Msg_text
+test.t2 optimize status OK
+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
-select count(*) from t3;
-count(*)
-1203
-rename table t3 to t4;
-select * from t4 where fld3='bonfire';
+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
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+REPAIR TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 repair status OK
+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
-select count(*) from t4;
-count(*)
-1203
+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
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+INSERT INTO t2 VALUES (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','');
+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
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+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
DELETE FROM t2;
SELECT * FROM t2;
auto fld1 companynr fld3 fld4 fld5 fld6
@@ -3821,6 +7461,13 @@ auto fld1 companynr fld3 fld4 fld5 fld6
2 011401 37 breaking dreaded Steinberg W
3 011402 37 Romans scholastics jarring
4 011403 37 intercepted audiology tinily
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+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
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','');
@@ -5032,6 +8679,13 @@ auto fld1 companynr fld3 fld4 fld5 fld6
2 011401 37 breaking dreaded Steinberg W
3 011402 37 Romans scholastics jarring
4 011403 37 intercepted audiology tinily
+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
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
TRUNCATE TABLE t2;
SELECT * FROM t2;
auto fld1 companynr fld3 fld4 fld5 fld6
@@ -6241,4 +9895,12 @@ auto fld1 companynr fld3 fld4 fld5 fld6
2 011401 37 breaking dreaded Steinberg W
3 011402 37 Romans scholastics jarring
4 011403 37 intercepted audiology tinily
+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
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+INSERT DELAYED INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
drop table t1, t2, t4;
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index 9f3695cb1b1..61a42b004a9 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -163,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 Out of range value adjusted for column 'i' at row 1
select last_insert_id();
last_insert_id()
255
@@ -232,7 +232,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 Column set to default value; 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);
@@ -274,7 +274,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 Column set to default value; 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
@@ -355,3 +355,42 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 ( `a` int(11) NOT NULL auto_increment, `b` int(11) default NULL,PRIMARY KEY (`a`),UNIQUE KEY `b` (`b`));
+insert into t1 (b) values (1);
+replace into t1 (b) values (2), (1), (3);
+select * from t1;
+a b
+3 1
+2 2
+4 3
+truncate table t1;
+insert into t1 (b) values (1);
+replace into t1 (b) values (2);
+replace into t1 (b) values (1);
+replace into t1 (b) values (3);
+select * from t1;
+a b
+3 1
+2 2
+4 3
+drop table t1;
+create table t1 (rowid int not null auto_increment, val int not null,primary
+key (rowid), unique(val));
+replace into t1 (val) values ('1'),('2');
+replace into t1 (val) values ('1'),('2');
+insert into t1 (val) values ('1'),('2');
+ERROR 23000: Duplicate entry '1' for key 2
+select * from t1;
+rowid val
+3 1
+4 2
+drop table t1;
+create table t1 (a int not null auto_increment primary key, val int);
+insert into t1 (val) values (1);
+update t1 set a=2 where a=1;
+insert into t1 (val) values (1);
+select * from t1;
+a val
+2 1
+3 1
+drop table t1;
diff --git a/mysql-test/r/backup.result b/mysql-test/r/backup.result
index e53c3c3eb55..c7b4b1c4155 100644
--- a/mysql-test/r/backup.result
+++ b/mysql-test/r/backup.result
@@ -5,6 +5,8 @@ backup table t4 to '../bogus';
Table Op Msg_type Msg_text
test.t4 backup error Failed copying .frm file (errno: X)
test.t4 backup status Operation failed
+Warnings:
+Error 1 Can't create/write to file 'MYSQL_TEST_DIR/var/bogus/t4.frm' (Errcode: X)
backup table t4 to '../tmp';
Table Op Msg_type Msg_text
test.t4 backup status OK
@@ -12,6 +14,8 @@ backup table t4 to '../tmp';
Table Op Msg_type Msg_text
test.t4 backup error Failed copying .frm file (errno: X)
test.t4 backup status Operation failed
+Warnings:
+Error 1 Can't create/write to file 'MYSQL_TEST_DIR/var/tmp/t4.frm' (Errcode: X)
drop table t4;
restore table t4 from '../tmp';
Table Op Msg_type Msg_text
@@ -28,6 +32,8 @@ drop table t1;
restore table t1 from '../bogus';
Table Op Msg_type Msg_text
t1 restore error Failed copying .frm file
+Warnings:
+Error 29 File 'MYSQL_TEST_DIR/var/bogus/t1.frm' not found (Errcode: X)
restore table t1 from '../tmp';
Table Op Msg_type Msg_text
test.t1 restore status OK
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 6da3dbb929d..d525b019c64 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -140,13 +140,13 @@ id parent_id level
1015 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
+1 SIMPLE t1 ref level level 1 const X Using index
explain select level,id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
+1 SIMPLE t1 ref level level 1 const X Using index
explain select level,id,parent_id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 Using where
+1 SIMPLE t1 ref level level 1 const X
select level,id from t1 where level=1;
level id
1 1002
@@ -625,7 +625,7 @@ id parent_id level
1016 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
+1 SIMPLE t1 ref level level 1 const X Using index
select level,id from t1 where level=1;
level id
1 1004
@@ -737,6 +737,11 @@ a
1
2
3
+select a from t1 natural join t1 as t2 where b >= @a order by a;
+a
+1
+2
+3
update t1 set a=5 where a=1;
select a from t1;
a
@@ -1284,3 +1289,609 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
id
4
DROP TABLE t1;
+create temporary table t1 (a int, primary key(a)) engine=bdb;
+select * from t1;
+a
+alter table t1 add b int;
+select * from t1;
+a b
+drop table t1;
+set storage_engine=bdb;
+drop table if exists t1,t2,t3;
+--- Testing varchar ---
+--- Testing varchar ---
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Note 1265 Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+ *+*+ *
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Note 1265 Data truncated for column 't' at row 2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(10) default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+ *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`),
+ KEY `c` (`c`),
+ KEY `t` (`t`(10))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const # Using where
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const # Using where
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t t 13 NULL # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v,v_2 # 13 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(*) from t1 group by c limit 10;
+c count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(*) from t1 group by t limit 10;
+t count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v);
+Warnings:
+Warning 1071 Specified key was too long; max key length is 255 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(300) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`(255))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 258 const # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 258 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 258 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 258 NULL # Using where
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 258 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 drop key v, add key v (v(30));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(300) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`(30))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 33 const # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 33 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 modify v varchar(600), drop key v, add key v (v);
+Warnings:
+Warning 1071 Specified key was too long; max key length is 255 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(600) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`(255))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a ');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a%';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='abc ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a %';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+drop table t1;
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`(5)),
+ KEY `c` (`c`(5)),
+ KEY `t` (`t`(5))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) character set utf8 default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+concat('*',v,'*',c,'*')
+*a*a*
+*a *a*
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+create table t1(a int, b varchar(12), key ba(b, a));
+insert into t1 values (1, 'A'), (20, NULL);
+explain select * from t1 where a=20 and b is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref ba ba 20 const,const 1 Using where
+select * from t1 where a=20 and b is null;
+a b
+20 NULL
+drop table t1;
+create table t1 (v varchar(65530), key(v));
+Warnings:
+Warning 1071 Specified key was too long; max key length is 255 bytes
+drop table if exists t1;
+create table t1 (v varchar(65536));
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext character set utf8
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+set storage_engine=MyISAM;
diff --git a/mysql-test/r/bench_count_distinct.result b/mysql-test/r/bench_count_distinct.result
index fcc0c0948b3..62312870f59 100644
--- a/mysql-test/r/bench_count_distinct.result
+++ b/mysql-test/r/bench_count_distinct.result
@@ -7,5 +7,5 @@ explain extended select count(distinct n) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL n 4 NULL 200 Using index
Warnings:
-Note 1003 select count(distinct test.t1.n) AS `count(distinct n)` from test.t1
+Note 1003 select count(distinct `test`.`t1`.`n`) AS `count(distinct n)` from `test`.`t1`
drop table t1;
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index e9a457c9dfa..ca9a2662f94 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -7,7 +7,7 @@ select 9223372036854775807,-009223372036854775808;
9223372036854775807 -9223372036854775808
select +9999999999999999999,-9999999999999999999;
9999999999999999999 -9999999999999999999
-9999999999999999999 -10000000000000000000
+9999999999999999999 -9999999999999999999
select cast(9223372036854775808 as unsigned)+1;
cast(9223372036854775808 as unsigned)+1
9223372036854775809
@@ -16,13 +16,13 @@ select 9223372036854775808+1;
9223372036854775809
select -(0-3),round(-(0-3)), round(9999999999999999999);
-(0-3) round(-(0-3)) round(9999999999999999999)
-3 3 10000000000000000000
+3 3 9999999999999999999
select 1,11,101,1001,10001,100001,1000001,10000001,100000001,1000000001,10000000001,100000000001,1000000000001,10000000000001,100000000000001,1000000000000001,10000000000000001,100000000000000001,1000000000000000001,10000000000000000001;
1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001
1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001
select -1,-11,-101,-1001,-10001,-100001,-1000001,-10000001,-100000001,-1000000001,-10000000001,-100000000001,-1000000000001,-10000000000001,-100000000000001,-1000000000000001,-10000000000000001,-100000000000000001,-1000000000000000001,-10000000000000000001;
-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000001
--1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000000
+-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000001
select conv(1,10,16),conv((1<<2)-1,10,16),conv((1<<10)-2,10,16),conv((1<<16)-3,10,16),conv((1<<25)-4,10,16),conv((1<<31)-5,10,16),conv((1<<36)-6,10,16),conv((1<<47)-7,10,16),conv((1<<48)-8,10,16),conv((1<<55)-9,10,16),conv((1<<56)-10,10,16),conv((1<<63)-11,10,16);
conv(1,10,16) conv((1<<2)-1,10,16) conv((1<<10)-2,10,16) conv((1<<16)-3,10,16) conv((1<<25)-4,10,16) conv((1<<31)-5,10,16) conv((1<<36)-6,10,16) conv((1<<47)-7,10,16) conv((1<<48)-8,10,16) conv((1<<55)-9,10,16) conv((1<<56)-10,10,16) conv((1<<63)-11,10,16)
1 3 3FE FFFD 1FFFFFC 7FFFFFFB FFFFFFFFA 7FFFFFFFFFF9 FFFFFFFFFFF8 7FFFFFFFFFFFF7 FFFFFFFFFFFFF6 7FFFFFFFFFFFFFF5
@@ -46,6 +46,14 @@ a
drop table t1;
create table t1 ( a int not null default 1, big bigint );
insert into t1 (big) values (-1),(12345678901234567),(9223372036854775807),(18446744073709551615);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'big' at row 4
+select * from t1;
+a big
+1 -1
+1 12345678901234567
+1 9223372036854775807
+1 9223372036854775807
select min(big),max(big),max(big)-1 from t1;
min(big) max(big) max(big)-1
-1 9223372036854775807 9223372036854775806
@@ -53,26 +61,51 @@ select min(big),max(big),max(big)-1 from t1 group by a;
min(big) max(big) max(big)-1
-1 9223372036854775807 9223372036854775806
alter table t1 modify big bigint unsigned not null;
+Warnings:
+Warning 1264 Out of range value adjusted for column 'big' at row 1
select min(big),max(big),max(big)-1 from t1;
min(big) max(big) max(big)-1
-12345678901234567 18446744073709551615 18446744073709551614
+0 9223372036854775807 9223372036854775806
select min(big),max(big),max(big)-1 from t1 group by a;
min(big) max(big) max(big)-1
-12345678901234567 18446744073709551615 18446744073709551614
+0 9223372036854775807 9223372036854775806
+insert into t1 (big) values (18446744073709551615);
+select * from t1;
+a big
+1 0
+1 12345678901234567
+1 9223372036854775807
+1 9223372036854775807
+1 18446744073709551615
+select min(big),max(big),max(big)-1 from t1;
+min(big) max(big) max(big)-1
+0 18446744073709551615 18446744073709551614
+select min(big),max(big),max(big)-1 from t1 group by a;
+min(big) max(big) max(big)-1
+0 18446744073709551615 18446744073709551614
alter table t1 add key (big);
select min(big),max(big),max(big)-1 from t1;
min(big) max(big) max(big)-1
-12345678901234567 18446744073709551615 18446744073709551614
+0 18446744073709551615 18446744073709551614
select min(big),max(big),max(big)-1 from t1 group by a;
min(big) max(big) max(big)-1
-12345678901234567 18446744073709551615 18446744073709551614
+0 18446744073709551615 18446744073709551614
alter table t1 modify big bigint not null;
+Warnings:
+Warning 1264 Out of range value adjusted for column 'big' at row 5
+select * from t1;
+a big
+1 0
+1 12345678901234567
+1 9223372036854775807
+1 9223372036854775807
+1 9223372036854775807
select min(big),max(big),max(big)-1 from t1;
min(big) max(big) max(big)-1
--1 9223372036854775807 9223372036854775806
+0 9223372036854775807 9223372036854775806
select min(big),max(big),max(big)-1 from t1 group by a;
min(big) max(big) max(big)-1
--1 9223372036854775807 9223372036854775806
+0 9223372036854775807 9223372036854775806
drop table t1;
create table t1 (id bigint auto_increment primary key, a int) auto_increment=9999999999;
insert into t1 values (null,1);
@@ -89,13 +122,15 @@ insert into t1 values (10000000000000000000.0);
insert into t1 values ('10000000000000000000');
select * from t1;
quantity
--8446744073709551616
+10000000000000000000
10000000000000000000
10000000000000000000
drop table t1;
SELECT '0x8000000000000001'+0;
'0x8000000000000001'+0
0
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '0x8000000000000001'
create table t1 (
value64 bigint unsigned not null,
value32 integer not null,
@@ -135,3 +170,165 @@ t2.value64=t1.value64;
value64 value32 value64 value32
9223372036854775807 2 9223372036854775807 4
drop table t1, t2;
+create table t1 select 1 as 'a';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(1) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 select 9223372036854775809 as 'a';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(19) unsigned NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t1;
+a
+9223372036854775809
+drop table t1;
+DROP DATABASE IF EXISTS `scott`;
+Warnings:
+Note 1008 Can't drop database 'scott'; database doesn't exist
+create table t1 (a char(100), b varchar(100), c text, d blob);
+insert into t1 values(
+18446744073709551615,18446744073709551615,
+18446744073709551615, 18446744073709551615
+);
+insert into t1 values (-1 | 0,-1 | 0,-1 | 0 ,-1 | 0);
+select * from t1;
+a b c d
+18446744073709551615 18446744073709551615 18446744073709551615 18446744073709551615
+18446744073709551615 18446744073709551615 18446744073709551615 18446744073709551615
+drop table t1;
+create table t1 ( quantity decimal(2) unsigned);
+insert into t1 values (500), (-500), (~0), (-1);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'quantity' at row 1
+Warning 1264 Out of range value adjusted for column 'quantity' at row 2
+Warning 1264 Out of range value adjusted for column 'quantity' at row 3
+Warning 1264 Out of range value adjusted for column 'quantity' at row 4
+select * from t1;
+quantity
+99
+0
+99
+0
+drop table t1;
+CREATE TABLE t1 (
+`col1` INT(1) NULL,
+`col2` INT(2) NULL,
+`col3` INT(3) NULL,
+`col4` INT(4) NULL,
+`col5` INT(5) NULL,
+`col6` INT(6) NULL,
+`col7` INT(7) NULL,
+`col8` INT(8) NULL,
+`col9` INT(9) NULL,
+`col10` BIGINT(10) NULL,
+`col11` BIGINT(11) NULL,
+`col12` BIGINT(12) NULL,
+`col13` BIGINT(13) NULL,
+`col14` BIGINT(14) NULL,
+`col15` BIGINT(15) NULL,
+`col16` BIGINT(16) NULL,
+`col17` BIGINT(17) NULL,
+`col18` BIGINT(18) NULL,
+`col19` DECIMAL(19, 0) NULL,
+`col20` DECIMAL(20, 0) NULL,
+`col21` DECIMAL(21, 0) NULL,
+`col22` DECIMAL(22, 0) NULL,
+`col23` DECIMAL(23, 0) NULL,
+`col24` DECIMAL(24, 0) NULL,
+`col25` DECIMAL(25, 0) NULL,
+`col26` DECIMAL(26, 0) NULL,
+`col27` DECIMAL(27, 0) NULL,
+`col28` DECIMAL(28, 0) NULL,
+`col29` DECIMAL(29, 0) NULL,
+`col30` DECIMAL(30, 0) NULL,
+`col31` DECIMAL(31, 0) NULL,
+`col32` DECIMAL(32, 0) NULL,
+`col33` DECIMAL(33, 0) NULL,
+`col34` DECIMAL(34, 0) NULL,
+`col35` DECIMAL(35, 0) NULL,
+`col36` DECIMAL(36, 0) NULL,
+`col37` DECIMAL(37, 0) NULL,
+`col38` DECIMAL(38, 0) NULL,
+`fix1` DECIMAL(38, 1) NULL,
+`fix2` DECIMAL(38, 2) NULL,
+`fix3` DECIMAL(38, 3) NULL,
+`fix4` DECIMAL(38, 4) NULL,
+`fix5` DECIMAL(38, 5) NULL,
+`fix6` DECIMAL(38, 6) NULL,
+`fix7` DECIMAL(38, 7) NULL,
+`fix8` DECIMAL(38, 8) NULL,
+`fix9` DECIMAL(38, 9) NULL,
+`fix10` DECIMAL(38, 10) NULL,
+`fix11` DECIMAL(38, 11) NULL,
+`fix12` DECIMAL(38, 12) NULL,
+`fix13` DECIMAL(38, 13) NULL,
+`fix14` DECIMAL(38, 14) NULL,
+`fix15` DECIMAL(38, 15) NULL,
+`fix16` DECIMAL(38, 16) NULL,
+`fix17` DECIMAL(38, 17) NULL,
+`fix18` DECIMAL(38, 18) NULL,
+`fix19` DECIMAL(38, 19) NULL,
+`fix20` DECIMAL(38, 20) NULL,
+`fix21` DECIMAL(38, 21) NULL,
+`fix22` DECIMAL(38, 22) NULL,
+`fix23` DECIMAL(38, 23) NULL,
+`fix24` DECIMAL(38, 24) NULL,
+`fix25` DECIMAL(38, 25) NULL,
+`fix26` DECIMAL(38, 26) NULL,
+`fix27` DECIMAL(38, 27) NULL,
+`fix28` DECIMAL(38, 28) NULL,
+`fix29` DECIMAL(38, 29) NULL,
+`fix30` DECIMAL(38, 30) NULL
+);
+INSERT INTO t1(`col1`, `col2`, `col3`, `col4`, `col5`, `col6`, `col7`, `col8`, `col9`, `col10`, `col11`, `col12`, `col13`, `col14`, `col15`, `col16`, `col17`, `col18`, `col19`, `col20`, `col21`, `col22`, `col23`, `col24`, `col25`, `col26`, `col27`, `col28`, `col29`, `col30`, `col31`, `col32`, `col33`, `col34`, `col35`, `col36`, `col37`, `col38`, `fix1`, `fix2`, `fix3`, `fix4`, `fix5`, `fix6`, `fix7`, `fix8`, `fix9`, `fix10`, `fix11`, `fix12`, `fix13`, `fix14`, `fix15`, `fix16`, `fix17`, `fix18`, `fix19`, `fix20`, `fix21`, `fix22`, `fix23`, `fix24`, `fix25`, `fix26`, `fix27`, `fix28`, `fix29`, `fix30`)
+VALUES (9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999,
+9999999999, 99999999999, 999999999999, 9999999999999, 99999999999999,
+999999999999999, 9999999999999999, 99999999999999999, 999999999999999999,
+9999999999999999999, 99999999999999999999, 999999999999999999999,
+9999999999999999999999, 99999999999999999999999, 999999999999999999999999,
+9999999999999999999999999, 99999999999999999999999999,
+999999999999999999999999999, 9999999999999999999999999999,
+99999999999999999999999999999, 999999999999999999999999999999,
+9999999999999999999999999999999, 99999999999999999999999999999999,
+999999999999999999999999999999999, 9999999999999999999999999999999999,
+99999999999999999999999999999999999, 999999999999999999999999999999999999,
+9999999999999999999999999999999999999, 99999999999999999999999999999999999999,
+9999999999999999999999999999999999999.9,
+999999999999999999999999999999999999.99,
+99999999999999999999999999999999999.999,
+9999999999999999999999999999999999.9999,
+999999999999999999999999999999999.99999,
+99999999999999999999999999999999.999999,
+9999999999999999999999999999999.9999999,
+999999999999999999999999999999.99999999,
+99999999999999999999999999999.999999999,
+9999999999999999999999999999.9999999999,
+999999999999999999999999999.99999999999,
+99999999999999999999999999.999999999999,
+9999999999999999999999999.9999999999999,
+999999999999999999999999.99999999999999,
+99999999999999999999999.999999999999999,
+9999999999999999999999.9999999999999999,
+999999999999999999999.99999999999999999,
+99999999999999999999.999999999999999999,
+9999999999999999999.9999999999999999999,
+999999999999999999.99999999999999999999,
+99999999999999999.999999999999999999999,
+9999999999999999.9999999999999999999999,
+999999999999999.99999999999999999999999,
+99999999999999.999999999999999999999999,
+9999999999999.9999999999999999999999999,
+999999999999.99999999999999999999999999,
+99999999999.999999999999999999999999999,
+9999999999.9999999999999999999999999999,
+999999999.99999999999999999999999999999,
+99999999.999999999999999999999999999999);
+SELECT * FROM t1;
+col1 col2 col3 col4 col5 col6 col7 col8 col9 col10 col11 col12 col13 col14 col15 col16 col17 col18 col19 col20 col21 col22 col23 col24 col25 col26 col27 col28 col29 col30 col31 col32 col33 col34 col35 col36 col37 col38 fix1 fix2 fix3 fix4 fix5 fix6 fix7 fix8 fix9 fix10 fix11 fix12 fix13 fix14 fix15 fix16 fix17 fix18 fix19 fix20 fix21 fix22 fix23 fix24 fix25 fix26 fix27 fix28 fix29 fix30
+9 99 999 9999 99999 999999 9999999 99999999 999999999 9999999999 99999999999 999999999999 9999999999999 99999999999999 999999999999999 9999999999999999 99999999999999999 999999999999999999 9999999999999999999 99999999999999999999 999999999999999999999 9999999999999999999999 99999999999999999999999 999999999999999999999999 9999999999999999999999999 99999999999999999999999999 999999999999999999999999999 9999999999999999999999999999 99999999999999999999999999999 999999999999999999999999999999 9999999999999999999999999999999 99999999999999999999999999999999 999999999999999999999999999999999 9999999999999999999999999999999999 99999999999999999999999999999999999 999999999999999999999999999999999999 9999999999999999999999999999999999999 99999999999999999999999999999999999999 9999999999999999999999999999999999999.9 999999999999999999999999999999999999.99 99999999999999999999999999999999999.999 9999999999999999999999999999999999.9999 999999999999999999999999999999999.99999 99999999999999999999999999999999.999999 9999999999999999999999999999999.9999999 999999999999999999999999999999.99999999 99999999999999999999999999999.999999999 9999999999999999999999999999.9999999999 999999999999999999999999999.99999999999 99999999999999999999999999.999999999999 9999999999999999999999999.9999999999999 999999999999999999999999.99999999999999 99999999999999999999999.999999999999999 9999999999999999999999.9999999999999999 999999999999999999999.99999999999999999 99999999999999999999.999999999999999999 9999999999999999999.9999999999999999999 999999999999999999.99999999999999999999 99999999999999999.999999999999999999999 9999999999999999.9999999999999999999999 999999999999999.99999999999999999999999 99999999999999.999999999999999999999999 9999999999999.9999999999999999999999999 999999999999.99999999999999999999999999 99999999999.999999999999999999999999999 9999999999.9999999999999999999999999999 999999999.99999999999999999999999999999 99999999.999999999999999999999999999999
+DROP TABLE t1;
diff --git a/mysql-test/r/binlog.result b/mysql-test/r/binlog.result
new file mode 100644
index 00000000000..5d5b78abe29
--- /dev/null
+++ b/mysql-test/r/binlog.result
@@ -0,0 +1,135 @@
+drop table if exists t1, t2;
+reset master;
+create table t1 (a int) engine=bdb;
+create table t2 (a int) engine=innodb;
+begin;
+insert t1 values (5);
+commit;
+begin;
+insert t2 values (5);
+commit;
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `test`; create table t1 (a int) engine=bdb
+master-bin.000001 # Query 1 # use `test`; create table t2 (a int) engine=innodb
+master-bin.000001 # Query 1 # use `test`; BEGIN
+master-bin.000001 # Query 1 # use `test`; insert t1 values (5)
+master-bin.000001 # Query 1 # use `test`; COMMIT
+master-bin.000001 # Query 1 # use `test`; BEGIN
+master-bin.000001 # Query 1 # use `test`; insert t2 values (5)
+master-bin.000001 # Xid 1 # COMMIT /* xid=11 */
+drop table t1,t2;
+reset master;
+create table t1 (n int) engine=innodb;
+begin;
+commit;
+drop table t1;
+show binlog events in 'master-bin.000001' from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `test`; create table t1 (n int) engine=innodb
+master-bin.000001 # Query 1 # use `test`; BEGIN
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(100 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(99 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(98 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(97 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(96 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(95 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(94 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(93 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(92 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(91 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(90 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(89 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(88 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(87 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(86 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(85 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(84 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(83 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(82 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(81 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(80 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(79 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(78 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(77 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(76 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(75 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(74 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(73 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(72 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(71 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(70 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(69 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(68 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(67 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(66 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(65 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(64 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(63 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(62 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(61 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(60 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(59 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(58 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(57 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(56 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(55 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(54 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(53 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(52 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(51 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(50 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(49 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(48 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(47 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(46 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(45 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(44 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(43 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(42 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(41 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(40 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(39 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(38 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(37 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(36 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(35 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(34 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(33 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(32 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(31 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(30 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(29 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(28 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(27 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(26 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(25 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(24 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(23 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(22 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(21 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(20 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(19 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(18 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(17 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(16 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(15 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(14 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(13 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(12 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(11 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(10 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(9 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(8 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(7 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(6 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(5 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(4 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(3 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(2 + 4)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values(1 + 4)
+master-bin.000001 # Xid 1 # COMMIT /* xid=18 */
+master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
+show binlog events in 'master-bin.000002' from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Query 1 # use `test`; drop table t1
diff --git a/mysql-test/r/blackhole.result b/mysql-test/r/blackhole.result
index 4b779094376..38e548490fe 100644
--- a/mysql-test/r/blackhole.result
+++ b/mysql-test/r/blackhole.result
@@ -73,7 +73,7 @@ explain extended select * from t1 where MATCH(a,b) AGAINST ("collections");
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 fulltext a a 0 1 Using where
Warnings:
-Note 1003 select test.t1.a AS `a`,test.t1.b AS `b` from test.t1 where (match test.t1.a,test.t1.b against (_latin1'collections'))
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (match `test`.`t1`.`a`,`test`.`t1`.`b` against (_latin1'collections'))
select * from t1 where MATCH(a,b) AGAINST ("indexes");
a b
Full-text indexes are called collections
@@ -105,8 +105,8 @@ a
select * from t3;
a
show binlog events;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 # Start 1 # Server ver: VERSION, Binlog ver: 3
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
master-bin.000001 # Query 1 # use `test`; drop table t1,t2
master-bin.000001 # Query 1 # use `test`; create table t1 (a int) engine=blackhole
master-bin.000001 # Query 1 # use `test`; delete from t1 where a=10
@@ -115,8 +115,8 @@ master-bin.000001 # Query 1 # use `test`; insert into t1 values(1)
master-bin.000001 # Query 1 # use `test`; insert ignore into t1 values(1)
master-bin.000001 # Query 1 # use `test`; replace into t1 values(100)
master-bin.000001 # Query 1 # use `test`; create table t2 (a varchar(200)) engine=blackhole
-master-bin.000001 # Create_file 1 # db=test;table=t2;file_id=1;block_len=581
-master-bin.000001 # Exec_load 1 # ;file_id=1
+master-bin.000001 # Begin_load_query 1 # ;file_id=1;block_len=581
+master-bin.000001 # Execute_load_query 1 # use `test`; load data infile '../../std_data/words.dat' into table t2 ;file_id=1
master-bin.000001 # Query 1 # use `test`; alter table t1 add b int
master-bin.000001 # Query 1 # use `test`; alter table t1 drop b
master-bin.000001 # Query 1 # use `test`; create table t3 like t1
diff --git a/mysql-test/r/bool.result b/mysql-test/r/bool.result
index a054eceec0c..184046a2d6f 100644
--- a/mysql-test/r/bool.result
+++ b/mysql-test/r/bool.result
@@ -33,6 +33,24 @@ a
SELECT * FROM t1 where (1 AND a) IS NULL;
a
NULL
+set sql_mode='high_not_precedence';
+select * from t1 where not a between 2 and 3;
+a
+set sql_mode=default;
+select * from t1 where not a between 2 and 3;
+a
+0
+1
+select a, a is false, a is true, a is unknown from t1;
+a a is false a is true a is unknown
+0 1 0 0
+1 0 1 0
+NULL 0 0 1
+select a, a is not false, a is not true, a is not unknown from t1;
+a a is not false a is not true a is not unknown
+0 0 1 1
+1 1 0 1
+NULL 1 1 0
SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
a
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index fb0bc19a67e..b02f85132aa 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -66,7 +66,7 @@ explain extended select case a when 1 then 2 when 2 then 3 else 0 end as fcase,
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort
Warnings:
-Note 1003 select (case test.t1.a when 1 then 2 when 2 then 3 else 0 end) AS `fcase`,count(0) AS `count(*)` from test.t1 group by (case test.t1.a when 1 then 2 when 2 then 3 else 0 end)
+Note 1003 select (case `test`.`t1`.`a` when 1 then 2 when 2 then 3 else 0 end) AS `fcase`,count(0) AS `count(*)` from `test`.`t1` group by (case `test`.`t1`.`a` when 1 then 2 when 2 then 3 else 0 end)
select case a when 1 then "one" when 2 then "two" else "nothing" end as fcase, count(*) from t1 group by fcase;
fcase count(*)
nothing 2
@@ -91,20 +91,26 @@ CASE WHEN 1 THEN 'a' ELSE 1.0 END AS c5,
CASE WHEN 1 THEN 1.0 ELSE 'a' END AS c6,
CASE WHEN 1 THEN 1 ELSE 1.0 END AS c7,
CASE WHEN 1 THEN 1.0 ELSE 1 END AS c8,
-CASE WHEN 1 THEN 1.0 END AS c9
+CASE WHEN 1 THEN 1.0 END AS c9,
+CASE WHEN 1 THEN 0.1e1 else 0.1 END AS c10,
+CASE WHEN 1 THEN 0.1e1 else 1 END AS c11,
+CASE WHEN 1 THEN 0.1e1 else '1' END AS c12
;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` char(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
- `c2` char(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
- `c3` binary(1) NOT NULL default '',
- `c4` binary(1) NOT NULL default '',
- `c5` binary(3) NOT NULL default '',
- `c6` binary(3) NOT NULL default '',
- `c7` double(3,1) NOT NULL default '0.0',
- `c8` double(3,1) NOT NULL default '0.0',
- `c9` double(3,1) default NULL
+ `c1` varchar(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
+ `c2` varchar(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
+ `c3` varbinary(1) NOT NULL default '',
+ `c4` varbinary(1) NOT NULL default '',
+ `c5` varbinary(4) NOT NULL default '',
+ `c6` varbinary(4) NOT NULL default '',
+ `c7` decimal(2,1) NOT NULL default '0.0',
+ `c8` decimal(2,1) NOT NULL default '0.0',
+ `c9` decimal(2,1) default NULL,
+ `c10` double NOT NULL default '0',
+ `c11` double NOT NULL default '0',
+ `c12` varbinary(5) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT CASE
@@ -141,17 +147,17 @@ COALESCE('a' COLLATE latin1_bin,'b');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select coalesce(1) AS `COALESCE(1)`,coalesce(1.0) AS `COALESCE(1.0)`,coalesce(_latin1'a') AS `COALESCE('a')`,coalesce(1,1.0) AS `COALESCE(1,1.0)`,coalesce(1,_latin1'1') AS `COALESCE(1,'1')`,coalesce(1.1,_latin1'1') AS `COALESCE(1.1,'1')`,coalesce((_latin1'a' collate _latin1'latin1_bin'),_latin1'b') AS `COALESCE('a' COLLATE latin1_bin,'b')`
+Note 1003 select coalesce(1) AS `COALESCE(1)`,coalesce(1.0) AS `COALESCE(1.0)`,coalesce(_latin1'a') AS `COALESCE('a')`,coalesce(1,1.0) AS `COALESCE(1,1.0)`,coalesce(1,_latin1'1') AS `COALESCE(1,'1')`,coalesce(1.1,_latin1'1') AS `COALESCE(1.1,'1')`,coalesce((_latin1'a' collate latin1_bin),_latin1'b') AS `COALESCE('a' COLLATE latin1_bin,'b')`
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE(1)` int(1) NOT NULL default '0',
- `COALESCE(1.0)` double(3,1) NOT NULL default '0.0',
- `COALESCE('a')` char(1) NOT NULL default '',
- `COALESCE(1,1.0)` double(3,1) NOT NULL default '0.0',
- `COALESCE(1,'1')` binary(1) NOT NULL default '',
- `COALESCE(1.1,'1')` binary(3) NOT NULL default '',
- `COALESCE('a' COLLATE latin1_bin,'b')` char(1) character set latin1 collate latin1_bin NOT NULL default ''
+ `COALESCE(1.0)` decimal(2,1) NOT NULL default '0.0',
+ `COALESCE('a')` varchar(1) NOT NULL default '',
+ `COALESCE(1,1.0)` decimal(2,1) NOT NULL default '0.0',
+ `COALESCE(1,'1')` varbinary(1) NOT NULL default '',
+ `COALESCE(1.1,'1')` varbinary(4) NOT NULL default '',
+ `COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT 'case+union+test'
@@ -169,3 +175,20 @@ SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
case+union+test
case+union+test
nobug
+CREATE TABLE t1 (EMPNUM INT);
+INSERT INTO t1 VALUES (0), (2);
+CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
+INSERT INTO t2 VALUES (0.0), (9.0);
+SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
+t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
+FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
+CEMPNUM EMPMUM1 EMPNUM2
+0.00 0 0.00
+2.00 2 NULL
+SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
+t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
+FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
+CEMPNUM EMPMUM1 EMPNUM2
+0.00 0 0.00
+2.00 2 NULL
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 7cd0934f7a3..1b5bdf98afd 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -4,6 +4,11 @@ CAST(1-2 AS UNSIGNED)
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER)
-1
+select CAST('10 ' as unsigned integer);
+CAST('10 ' as unsigned integer)
+10
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '10 '
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1
18446744073709551611 18446744073709551611
@@ -39,6 +44,15 @@ cast("1:2:3" as TIME)
select CONVERT("2004-01-22 21:45:33",DATE);
CONVERT("2004-01-22 21:45:33",DATE)
2004-01-22
+select 10+'10';
+10+'10'
+20
+select 10.0+'10';
+10.0+'10'
+20
+select 10E+0+'10';
+10E+0+'10'
+20
select CONVERT(DATE "2004-01-22 21:45:33" USING latin1);
CONVERT(DATE "2004-01-22 21:45:33" USING latin1)
2004-01-22 21:45:33
@@ -48,12 +62,43 @@ CONVERT(DATE "2004-01-22 21:45:33",CHAR)
select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4));
CONVERT(DATE "2004-01-22 21:45:33",CHAR(4))
2004
+Warnings:
+Warning 1292 Truncated incorrect CHAR(4) value: '2004-01-22 21:45:33'
select CONVERT(DATE "2004-01-22 21:45:33",BINARY(4));
CONVERT(DATE "2004-01-22 21:45:33",BINARY(4))
2004
+Warnings:
+Warning 1292 Truncated incorrect CHAR(4) value: '2004-01-22 21:45:33'
select CAST(DATE "2004-01-22 21:45:33" AS BINARY(4));
CAST(DATE "2004-01-22 21:45:33" AS BINARY(4))
2004
+Warnings:
+Warning 1292 Truncated incorrect CHAR(4) value: '2004-01-22 21:45:33'
+select cast('-10a' as signed integer);
+cast('-10a' as signed integer)
+-10
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '-10a'
+select cast('a10' as unsigned integer);
+cast('a10' as unsigned integer)
+0
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'a10'
+select 10+'a';
+10+'a'
+10
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'a'
+select 10.0+cast('a' as decimal);
+10.0+cast('a' as decimal)
+10.00
+Warnings:
+Warning 1292 Truncated incorrect DECIMAL value: 'a'
+select 10E+0+'a';
+10E+0+'a'
+10
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'a'
select cast('18446744073709551616' as unsigned);
cast('18446744073709551616' as unsigned)
18446744073709551615
@@ -100,7 +145,7 @@ create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `t` char(4) character set cp1251 NOT NULL default ''
+ `t` varchar(4) character set cp1251 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select
@@ -111,23 +156,34 @@ cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
c1 c2 c3 c4 c5
ab a ab a a
+Warnings:
+Warning 1292 Truncated incorrect CHAR(2) value: 'abc'
+Warning 1292 Truncated incorrect CHAR(2) value: 'a '
+select cast(1000 as CHAR(3));
+cast(1000 as CHAR(3))
+100
+Warnings:
+Warning 1292 Truncated incorrect CHAR(3) value: '1000'
create table t1 select
cast(_latin1'ab' AS char) as c1,
cast(_latin1'a ' AS char) as c2,
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
+Warnings:
+Warning 1292 Truncated incorrect CHAR(2) value: 'abc'
+Warning 1292 Truncated incorrect CHAR(2) value: 'a '
select * from t1;
c1 c2 c3 c4 c5
-ab a ab a a
+ab a ab a a
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` binary(2) NOT NULL default '',
- `c2` binary(2) NOT NULL default '',
- `c3` binary(2) NOT NULL default '',
- `c4` binary(2) NOT NULL default '',
- `c5` binary(2) NOT NULL default ''
+ `c1` varbinary(2) NOT NULL default '',
+ `c2` varbinary(2) NOT NULL default '',
+ `c3` varbinary(2) NOT NULL default '',
+ `c4` varbinary(2) NOT NULL default '',
+ `c5` varbinary(2) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select
@@ -138,23 +194,29 @@ cast(_koi8r'Æ ' AS nchar(2)) as c4,
cast(_koi8r'Æ' AS nchar(2)) as c5;
c1 c2 c3 c4 c5
фг ф фг ф ф
+Warnings:
+Warning 1292 Truncated incorrect CHAR(4) value: 'фгх'
+Warning 1292 Truncated incorrect CHAR(3) value: 'Ñ„ '
create table t1 select
cast(_koi8r'ÆÇ' AS nchar) as c1,
cast(_koi8r'Æ ' AS nchar) as c2,
cast(_koi8r'ÆÇÈ' AS nchar(2)) as c3,
cast(_koi8r'Æ ' AS nchar(2)) as c4,
cast(_koi8r'Æ' AS nchar(2)) as c5;
+Warnings:
+Warning 1292 Truncated incorrect CHAR(4) value: 'фгх'
+Warning 1292 Truncated incorrect CHAR(3) value: 'Ñ„ '
select * from t1;
c1 c2 c3 c4 c5
-фг ф фг ф ф
+фг ф фг ф ф
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` char(2) character set utf8 NOT NULL default '',
- `c2` char(2) character set utf8 NOT NULL default '',
- `c3` char(2) character set utf8 NOT NULL default '',
- `c4` char(2) character set utf8 NOT NULL default '',
- `c5` char(2) character set utf8 NOT NULL default ''
+ `c1` varchar(2) character set utf8 NOT NULL default '',
+ `c2` varchar(2) character set utf8 NOT NULL default '',
+ `c3` varchar(2) character set utf8 NOT NULL default '',
+ `c4` varchar(2) character set utf8 NOT NULL default '',
+ `c5` varchar(2) character set utf8 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a binary(10), b char(10) character set koi8r);
@@ -199,6 +261,10 @@ a CAST(a AS CHAR(3))
aac aac
aab aab
aaa aaa
+Warnings:
+Warning 1292 Truncated incorrect CHAR(2) value: 'aaa'
+Warning 1292 Truncated incorrect CHAR(2) value: 'aab'
+Warning 1292 Truncated incorrect CHAR(2) value: 'aac'
SELECT a, CAST(a AS UNSIGNED) FROM t1 ORDER BY CAST(a AS CHAR) ;
a CAST(a AS UNSIGNED)
aaa 3
@@ -209,6 +275,10 @@ a CAST(a AS CHAR(2))
aaa aa
aab aa
aac aa
+Warnings:
+Warning 1292 Truncated incorrect CHAR(2) value: 'aaa'
+Warning 1292 Truncated incorrect CHAR(2) value: 'aab'
+Warning 1292 Truncated incorrect CHAR(2) value: 'aac'
DROP TABLE t1;
select date_add(cast('2004-12-30 12:00:00' as date), interval 0 hour);
date_add(cast('2004-12-30 12:00:00' as date), interval 0 hour)
@@ -252,3 +322,36 @@ cast(repeat('1',20) as signed)
-7335632962598440505
Warnings:
Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
+select cast('1.2' as decimal(3,2));
+cast('1.2' as decimal(3,2))
+1.20
+select 1e18 * cast('1.2' as decimal(3,2));
+1e18 * cast('1.2' as decimal(3,2))
+1.2e+18
+select cast(cast('1.2' as decimal(3,2)) as signed);
+cast(cast('1.2' as decimal(3,2)) as signed)
+1
+set @v1=1e18;
+select cast(@v1 as decimal(22, 2));
+cast(@v1 as decimal(22, 2))
+1000000000000000000.00
+select cast(-1e18 as decimal(22,2));
+cast(-1e18 as decimal(22,2))
+-1000000000000000000.00
+create table t1(s1 time);
+insert into t1 values ('11:11:11');
+select cast(s1 as decimal(7,2)) from t1;
+cast(s1 as decimal(7,2))
+111111.00
+drop table t1;
+CREATE TABLE t1 (v varchar(10), tt tinytext, t text,
+mt mediumtext, lt longtext);
+INSERT INTO t1 VALUES ('1.01', '2.02', '3.03', '4.04', '5.05');
+SELECT CAST(v AS DECIMAL), CAST(tt AS DECIMAL), CAST(t AS DECIMAL),
+CAST(mt AS DECIMAL), CAST(lt AS DECIMAL) from t1;
+CAST(v AS DECIMAL) CAST(tt AS DECIMAL) CAST(t AS DECIMAL) CAST(mt AS DECIMAL) CAST(lt AS DECIMAL)
+1.01 2.02 3.03 4.04 5.05
+DROP TABLE t1;
+select cast(NULL as decimal(6)) as t1;
+t1
+NULL
diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result
index ecaa13642bd..4c565f4f1b1 100644
--- a/mysql-test/r/check.result
+++ b/mysql-test/r/check.result
@@ -5,3 +5,12 @@ insert into t1 values (200000);
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
+Create table t1(f1 int);
+Create table t2(f1 int);
+Create view v1 as Select * from t1;
+Check Table v1,t2;
+Table Op Msg_type Msg_text
+test.v1 check status OK
+test.t2 check status OK
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/r/client_xml.result b/mysql-test/r/client_xml.result
new file mode 100644
index 00000000000..24c05c7f9d6
--- /dev/null
+++ b/mysql-test/r/client_xml.result
@@ -0,0 +1,74 @@
+create table t1 (
+`a&b` int,
+`a<b` int,
+`a>b` text
+);
+insert into t1 values (1, 2, 'a&b a<b a>b');
+<?xml version="1.0"?>
+
+<resultset statement="select * from t1
+">
+ <row>
+ <field name="a&amp;b">1</field>
+ <field name="a&lt;b">2</field>
+ <field name="a&gt;b">a&amp;b a&lt;b a&gt;b</field>
+ </row>
+</resultset>
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="test">
+ <table_structure name="t1">
+ <field Field="a&amp;b" Type="int(11)" Null="YES" Key="" Extra="" />
+ <field Field="a&lt;b" Type="int(11)" Null="YES" Key="" Extra="" />
+ <field Field="a&gt;b" Type="text" Null="YES" Key="" Extra="" />
+ </table_structure>
+ <table_data name="t1">
+ <row>
+ <field name="a&amp;b">1</field>
+ <field name="a&lt;b">2</field>
+ <field name="a&gt;b">a&amp;b a&lt;b a&gt;b</field>
+ </row>
+ </table_data>
+</database>
+</mysqldump>
+<?xml version="1.0"?>
+
+<resultset statement="select count(*) from t1
+">
+ <row>
+ <field name="count(*)">1</field>
+ </row>
+</resultset>
+<?xml version="1.0"?>
+
+<resultset statement="select 1 &lt; 2 from dual
+">
+ <row>
+ <field name="1 &lt; 2">1</field>
+ </row>
+</resultset>
+<?xml version="1.0"?>
+
+<resultset statement="select 1 &gt; 2 from dual
+">
+ <row>
+ <field name="1 &gt; 2">0</field>
+ </row>
+</resultset>
+<?xml version="1.0"?>
+
+<resultset statement="select 1 &amp; 3 from dual
+">
+ <row>
+ <field name="1 &amp; 3">1</field>
+ </row>
+</resultset>
+<?xml version="1.0"?>
+
+<resultset statement="select null from dual
+">
+ <row>
+ <field name="NULL">NULL</field>
+ </row>
+</resultset>
+drop table t1;
diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result
index 68c86b80e60..2508d751b46 100644
--- a/mysql-test/r/connect.result
+++ b/mysql-test/r/connect.result
@@ -9,6 +9,8 @@ help_keyword
help_relation
help_topic
host
+proc
+procs_priv
tables_priv
time_zone
time_zone_leap_second
@@ -30,6 +32,8 @@ help_keyword
help_relation
help_topic
host
+proc
+procs_priv
tables_priv
time_zone
time_zone_leap_second
@@ -55,6 +59,8 @@ help_keyword
help_relation
help_topic
host
+proc
+procs_priv
tables_priv
time_zone
time_zone_leap_second
diff --git a/mysql-test/r/count_distinct.result b/mysql-test/r/count_distinct.result
index 16460580d6c..a21748359b9 100644
--- a/mysql-test/r/count_distinct.result
+++ b/mysql-test/r/count_distinct.result
@@ -53,3 +53,16 @@ select count(distinct f) from t1;
count(distinct f)
0
drop table t1;
+create table t1 (a char(3), b char(20), primary key (a, b));
+insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
+select count(distinct a) from t1 group by b;
+count(distinct a)
+1
+1
+drop table t1;
+create table t1 (f1 int, f2 int);
+insert into t1 values (0,1),(1,2);
+select count(distinct if(f1,3,f2)) from t1;
+count(distinct if(f1,3,f2))
+2
+drop table t1;
diff --git a/mysql-test/r/count_distinct2.result b/mysql-test/r/count_distinct2.result
index 131e3b325ec..b92665b5c56 100644
--- a/mysql-test/r/count_distinct2.result
+++ b/mysql-test/r/count_distinct2.result
@@ -116,7 +116,7 @@ count(distinct n)
5000
show status like 'Created_tmp_disk_tables';
Variable_name Value
-Created_tmp_disk_tables 1
+Created_tmp_disk_tables 0
drop table t1;
create table t1 (s text);
flush status;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 6edd4cbc48f..3e7c9d6eb4a 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -13,7 +13,7 @@ Warnings:
Note 1050 Table 't1' already exists
insert into t1 values (""),(null);
Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'b' at row 2
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'b' at row 2
select * from t1;
b
@@ -46,12 +46,24 @@ create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
ERROR 42000: Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int);
ERROR 42000: Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long
-create table test (a datetime default now());
+create table t1 (a datetime default now());
ERROR 42000: Invalid default value for 'a'
-create table test (a datetime on update now());
+create table t1 (a datetime on update now());
ERROR HY000: Invalid ON UPDATE clause for 'a' column
-create table test (a int default 100 auto_increment);
+create table t1 (a int default 100 auto_increment);
ERROR 42000: Invalid default value for 'a'
+create table t1 (a tinyint default 1000);
+ERROR 42000: Invalid default value for 'a'
+create table t1 (a varchar(5) default 'abcdef');
+ERROR 42000: Invalid default value for 'a'
+create table t1 (a varchar(5) default 'abcde');
+insert into t1 values();
+select * from t1;
+a
+abcde
+alter table t1 alter column a set default 'abcdef';
+ERROR 42000: Invalid default value for 'a'
+drop table t1;
create table 1ea10 (1a20 int,1e int);
insert into 1ea10 values(1,1);
select 1ea10.1a20,1e+ 1e+10 from 1ea10;
@@ -102,12 +114,12 @@ drop table t2;
create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f;
describe t2;
Field Type Null Key Default Extra
-a datetime 0000-00-00 00:00:00
-b time 00:00:00
-c date 0000-00-00
-d bigint(17) 0
-e double(18,1) 0.0
-f bigint(17) 0
+a datetime NO 0000-00-00 00:00:00
+b time NO 00:00:00
+c date NO 0000-00-00
+d int(3) NO 0
+e decimal(3,1) NO 0.0
+f bigint(19) NO 0
drop table t2;
create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) as t, CAST("2001-12-29 20:45:11" AS DATETIME) as dt;
describe t2;
@@ -154,7 +166,7 @@ create table t1 (a int not null, b int, primary key(a), key (b), key (b), key (b
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` int(11) default NULL,
PRIMARY KEY (`a`),
KEY `b` (`b`),
@@ -200,25 +212,25 @@ drop table if exists t1;
SET SESSION storage_engine="heap";
SELECT @@storage_engine;
@@storage_engine
-HEAP
+MEMORY
CREATE TABLE t1 (a int not null);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0'
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+ `a` int(11) NOT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
drop table t1;
SET SESSION storage_engine="gemini";
ERROR 42000: Unknown table engine 'gemini'
SELECT @@storage_engine;
@@storage_engine
-HEAP
+MEMORY
CREATE TABLE t1 (a int not null);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0'
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+ `a` int(11) NOT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
SET SESSION storage_engine=default;
drop table t1;
create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2));
@@ -267,6 +279,7 @@ insert into t1 values (1,1);
create table if not exists t1 select 2;
Warnings:
Note 1050 Table 't1' already exists
+Warning 1364 Field 'a' doesn't have a default value
select * from t1;
a b
1 1
@@ -274,6 +287,7 @@ a b
create table if not exists t1 select 3 as 'a',4 as 'b';
Warnings:
Note 1050 Table 't1' already exists
+Warning 1364 Field 'a' doesn't have a default value
create table if not exists t1 select 3 as 'a',3 as 'b';
ERROR 23000: Duplicate entry '3' for key 1
select * from t1;
@@ -305,14 +319,14 @@ create table t3 like t1;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
`name` char(20) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t3;
id name
create table if not exists t3 like t1;
Warnings:
-Warning 1050 Table 't3' already exists
+Note 1050 Table 't3' already exists
select @@warning_count;
@@warning_count
1
@@ -320,7 +334,7 @@ create temporary table t3 like t2;
show create table t3;
Table Create Table
t3 CREATE TEMPORARY TABLE `t3` (
- `id` int(11) NOT NULL default '0'
+ `id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t3;
id
@@ -328,7 +342,7 @@ drop table t3;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
`name` char(20) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t3;
@@ -340,14 +354,14 @@ create temporary table t3 like mysqltest.t3;
show create table t3;
Table Create Table
t3 CREATE TEMPORARY TABLE `t3` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
`name` char(20) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
create table t2 like t3;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
`name` char(20) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t2;
@@ -369,25 +383,25 @@ drop database mysqltest;
SET SESSION storage_engine="heap";
SELECT @@storage_engine;
@@storage_engine
-HEAP
+MEMORY
CREATE TABLE t1 (a int not null);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0'
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+ `a` int(11) NOT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
drop table t1;
SET SESSION storage_engine="gemini";
ERROR 42000: Unknown table engine 'gemini'
SELECT @@storage_engine;
@@storage_engine
-HEAP
+MEMORY
CREATE TABLE t1 (a int not null);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0'
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+ `a` int(11) NOT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
SET SESSION storage_engine=default;
drop table t1;
create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob);
@@ -426,13 +440,13 @@ from t1;
explain t2;
Field Type Null Key Default Extra
a int(11) YES NULL
-b bigint(11) 0
-c bigint(11) 0
+b bigint(11) NO 0
+c bigint(11) NO 0
d date YES NULL
-e char(1)
+e varchar(1) NO
f datetime YES NULL
g time YES NULL
-h longblob
+h longblob NO
dd time YES NULL
select * from t2;
a b c d e f g h dd
@@ -456,9 +470,9 @@ t2 CREATE TABLE `t2` (
`ifnull(j,j)` date default NULL,
`ifnull(k,k)` datetime NOT NULL default '0000-00-00 00:00:00',
`ifnull(l,l)` datetime default NULL,
- `ifnull(m,m)` char(1) default NULL,
- `ifnull(n,n)` char(3) default NULL,
- `ifnull(o,o)` char(10) default NULL
+ `ifnull(m,m)` varchar(1) default NULL,
+ `ifnull(n,n)` varchar(3) default NULL,
+ `ifnull(o,o)` varchar(10) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2;
create table t1(str varchar(10) default 'def',strnull varchar(10),intg int default '10',rel double default '3.14');
@@ -595,11 +609,10 @@ create table t1(t1.name int);
create table t2(test.t2.name int);
drop table t1,t2;
CREATE TABLE t1 (f1 VARCHAR(255) CHARACTER SET utf8);
-CREATE TABLE t2 AS SELECT LEFT(f1,86) AS f2 FROM t1 UNION SELECT LEFT(f1,86)
-AS f2 FROM t1;
+CREATE TABLE t2 AS SELECT LEFT(f1,171) AS f2 FROM t1 UNION SELECT LEFT(f1,171) AS f2 FROM t1;
DESC t2;
Field Type Null Key Default Extra
-f2 varchar(86) YES NULL
+f2 varchar(171) YES NULL
DROP TABLE t1,t2;
create database mysqltest;
use mysqltest;
@@ -608,6 +621,13 @@ create table test.t1 like x;
ERROR 42000: Incorrect database name 'NULL'
drop table if exists test.t1;
create database mysqltest;
+use mysqltest;
+create view v1 as select 'foo' from dual;
+create table t1 like v1;
+ERROR HY000: 'mysqltest.v1' is not BASE TABLE
+drop view v1;
+drop database mysqltest;
+create database mysqltest;
create database if not exists mysqltest character set latin2;
Warnings:
Note 1007 Can't create database 'mysqltest'; database exists
diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result
index cdf890f2c6c..66266d40fb3 100644
--- a/mysql-test/r/ctype_collate.result
+++ b/mysql-test/r/ctype_collate.result
@@ -484,11 +484,11 @@ ERROR HY000: Unknown collation: 'koi8r'
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `latin1_f` char(32) NOT NULL default ''
+ `latin1_f` char(32) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SHOW FIELDS FROM t1;
Field Type Null Key Default Extra
-latin1_f char(32)
+latin1_f char(32) NO
ALTER TABLE t1 CHANGE latin1_f
latin1_f CHAR(32) CHARACTER SET latin1 COLLATE latin1_bin;
SHOW CREATE TABLE t1;
diff --git a/mysql-test/r/ctype_cp932.result b/mysql-test/r/ctype_cp932.result
index d8221a58b9e..08206a91b7b 100644..100755
--- a/mysql-test/r/ctype_cp932.result
+++ b/mysql-test/r/ctype_cp932.result
@@ -360,7 +360,7 @@ INSERT INTO t1 VALUES
(0xF9E8),(0xF9E9),(0xF9EA),(0xF9EB),(0xF9EC),(0xF9ED),(0xF9EE),(0xF9EF),
(0xF9F0),(0xF9F1),(0xF9F2),(0xF9F3),(0xF9F4),(0xF9F5),(0xF9F6),(0xF9F7),
(0xF9F8),(0xF9F9),(0xF9FA),(0xF9FB),(0xF9FC);
-SELECT HEX(c1) FROM t1 ORDER BY BINARY c1;
+SELECT HEX(c1) FROM t1;
HEX(c1)
05
7E
@@ -829,6 +829,394 @@ EEF9
EEFA
EEFB
EEFC
+FA40
+FA41
+FA42
+FA43
+FA44
+FA45
+FA46
+FA47
+FA48
+FA49
+FA4A
+FA4B
+FA4C
+FA4D
+FA4E
+FA4F
+FA50
+FA51
+FA52
+FA53
+FA54
+FA55
+FA56
+FA57
+FA58
+FA59
+FA5A
+FA5B
+FA5C
+FA5D
+FA5E
+FA5F
+FA60
+FA61
+FA62
+FA63
+FA64
+FA65
+FA66
+FA67
+FA68
+FA69
+FA6A
+FA6B
+FA6C
+FA6D
+FA6E
+FA6F
+FA70
+FA71
+FA72
+FA73
+FA74
+FA75
+FA76
+FA77
+FA78
+FA79
+FA7A
+FA7B
+FA7C
+FA7D
+FA7E
+FA80
+FA81
+FA82
+FA83
+FA84
+FA85
+FA86
+FA87
+FA88
+FA89
+FA8A
+FA8B
+FA8C
+FA8D
+FA8E
+FA8F
+FA90
+FA91
+FA92
+FA93
+FA94
+FA95
+FA96
+FA97
+FA98
+FA99
+FA9A
+FA9B
+FA9C
+FA9D
+FA9E
+FA9F
+FAA0
+FAA1
+FAA2
+FAA3
+FAA4
+FAA5
+FAA6
+FAA7
+FAA8
+FAA9
+FAAA
+FAAB
+FAAC
+FAAD
+FAAE
+FAAF
+FAB0
+FAB1
+FAB2
+FAB3
+FAB4
+FAB5
+FAB6
+FAB7
+FAB8
+FAB9
+FABA
+FABB
+FABC
+FABD
+FABE
+FABF
+FAC0
+FAC1
+FAC2
+FAC3
+FAC4
+FAC5
+FAC6
+FAC7
+FAC8
+FAC9
+FACA
+FACB
+FACC
+FACD
+FACE
+FACF
+FAD0
+FAD1
+FAD2
+FAD3
+FAD4
+FAD5
+FAD6
+FAD7
+FAD8
+FAD9
+FADA
+FADB
+FADC
+FADD
+FADE
+FADF
+FAE0
+FAE1
+FAE2
+FAE3
+FAE4
+FAE5
+FAE6
+FAE7
+FAE8
+FAE9
+FAEA
+FAEB
+FAEC
+FAED
+FAEE
+FAEF
+FAF0
+FAF1
+FAF2
+FAF3
+FAF4
+FAF5
+FAF6
+FAF7
+FAF8
+FAF9
+FAFA
+FAFB
+FAFC
+FB40
+FB41
+FB42
+FB43
+FB44
+FB45
+FB46
+FB47
+FB48
+FB49
+FB4A
+FB4B
+FB4C
+FB4D
+FB4E
+FB4F
+FB50
+FB51
+FB52
+FB53
+FB54
+FB55
+FB56
+FB57
+FB58
+FB59
+FB5A
+FB5B
+FB5C
+FB5D
+FB5E
+FB5F
+FB60
+FB61
+FB62
+FB63
+FB64
+FB65
+FB66
+FB67
+FB68
+FB69
+FB6A
+FB6B
+FB6C
+FB6D
+FB6E
+FB6F
+FB70
+FB71
+FB72
+FB73
+FB74
+FB75
+FB76
+FB77
+FB78
+FB79
+FB7A
+FB7B
+FB7C
+FB7D
+FB7E
+FB80
+FB81
+FB82
+FB83
+FB84
+FB85
+FB86
+FB87
+FB88
+FB89
+FB8A
+FB8B
+FB8C
+FB8D
+FB8E
+FB8F
+FB90
+FB91
+FB92
+FB93
+FB94
+FB95
+FB96
+FB97
+FB98
+FB99
+FB9A
+FB9B
+FB9C
+FB9D
+FB9E
+FB9F
+FBA0
+FBA1
+FBA2
+FBA3
+FBA4
+FBA5
+FBA6
+FBA7
+FBA8
+FBA9
+FBAA
+FBAB
+FBAC
+FBAD
+FBAE
+FBAF
+FBB0
+FBB1
+FBB2
+FBB3
+FBB4
+FBB5
+FBB6
+FBB7
+FBB8
+FBB9
+FBBA
+FBBB
+FBBC
+FBBD
+FBBE
+FBBF
+FBC0
+FBC1
+FBC2
+FBC3
+FBC4
+FBC5
+FBC6
+FBC7
+FBC8
+FBC9
+FBCA
+FBCB
+FBCC
+FBCD
+FBCE
+FBCF
+FBD0
+FBD1
+FBD2
+FBD3
+FBD4
+FBD5
+FBD6
+FBD7
+FBD8
+FBD9
+FBDA
+FBDB
+FBDC
+FBDD
+FBDE
+FBDF
+FBE0
+FBE1
+FBE2
+FBE3
+FBE4
+FBE5
+FBE6
+FBE7
+FBE8
+FBE9
+FBEA
+FBEB
+FBEC
+FBED
+FBEE
+FBEF
+FBF0
+FBF1
+FBF2
+FBF3
+FBF4
+FBF5
+FBF6
+FBF7
+FBF8
+FBF9
+FBFA
+FBFB
+FBFC
+FC40
+FC41
+FC42
+FC43
+FC44
+FC45
+FC46
+FC47
+FC48
+FC49
+FC4A
+FC4B
F040
F041
F042
@@ -2709,459 +3097,19 @@ F9F9
F9FA
F9FB
F9FC
-FA40
-FA41
-FA42
-FA43
-FA44
-FA45
-FA46
-FA47
-FA48
-FA49
-FA4A
-FA4B
-FA4C
-FA4D
-FA4E
-FA4F
-FA50
-FA51
-FA52
-FA53
-FA54
-FA55
-FA56
-FA57
-FA58
-FA59
-FA5A
-FA5B
-FA5C
-FA5D
-FA5E
-FA5F
-FA60
-FA61
-FA62
-FA63
-FA64
-FA65
-FA66
-FA67
-FA68
-FA69
-FA6A
-FA6B
-FA6C
-FA6D
-FA6E
-FA6F
-FA70
-FA71
-FA72
-FA73
-FA74
-FA75
-FA76
-FA77
-FA78
-FA79
-FA7A
-FA7B
-FA7C
-FA7D
-FA7E
-FA80
-FA81
-FA82
-FA83
-FA84
-FA85
-FA86
-FA87
-FA88
-FA89
-FA8A
-FA8B
-FA8C
-FA8D
-FA8E
-FA8F
-FA90
-FA91
-FA92
-FA93
-FA94
-FA95
-FA96
-FA97
-FA98
-FA99
-FA9A
-FA9B
-FA9C
-FA9D
-FA9E
-FA9F
-FAA0
-FAA1
-FAA2
-FAA3
-FAA4
-FAA5
-FAA6
-FAA7
-FAA8
-FAA9
-FAAA
-FAAB
-FAAC
-FAAD
-FAAE
-FAAF
-FAB0
-FAB1
-FAB2
-FAB3
-FAB4
-FAB5
-FAB6
-FAB7
-FAB8
-FAB9
-FABA
-FABB
-FABC
-FABD
-FABE
-FABF
-FAC0
-FAC1
-FAC2
-FAC3
-FAC4
-FAC5
-FAC6
-FAC7
-FAC8
-FAC9
-FACA
-FACB
-FACC
-FACD
-FACE
-FACF
-FAD0
-FAD1
-FAD2
-FAD3
-FAD4
-FAD5
-FAD6
-FAD7
-FAD8
-FAD9
-FADA
-FADB
-FADC
-FADD
-FADE
-FADF
-FAE0
-FAE1
-FAE2
-FAE3
-FAE4
-FAE5
-FAE6
-FAE7
-FAE8
-FAE9
-FAEA
-FAEB
-FAEC
-FAED
-FAEE
-FAEF
-FAF0
-FAF1
-FAF2
-FAF3
-FAF4
-FAF5
-FAF6
-FAF7
-FAF8
-FAF9
-FAFA
-FAFB
-FAFC
-FB40
-FB41
-FB42
-FB43
-FB44
-FB45
-FB46
-FB47
-FB48
-FB49
-FB4A
-FB4B
-FB4C
-FB4D
-FB4E
-FB4F
-FB50
-FB51
-FB52
-FB53
-FB54
-FB55
-FB56
-FB57
-FB58
-FB59
-FB5A
-FB5B
-FB5C
-FB5D
-FB5E
-FB5F
-FB60
-FB61
-FB62
-FB63
-FB64
-FB65
-FB66
-FB67
-FB68
-FB69
-FB6A
-FB6B
-FB6C
-FB6D
-FB6E
-FB6F
-FB70
-FB71
-FB72
-FB73
-FB74
-FB75
-FB76
-FB77
-FB78
-FB79
-FB7A
-FB7B
-FB7C
-FB7D
-FB7E
-FB80
-FB81
-FB82
-FB83
-FB84
-FB85
-FB86
-FB87
-FB88
-FB89
-FB8A
-FB8B
-FB8C
-FB8D
-FB8E
-FB8F
-FB90
-FB91
-FB92
-FB93
-FB94
-FB95
-FB96
-FB97
-FB98
-FB99
-FB9A
-FB9B
-FB9C
-FB9D
-FB9E
-FB9F
-FBA0
-FBA1
-FBA2
-FBA3
-FBA4
-FBA5
-FBA6
-FBA7
-FBA8
-FBA9
-FBAA
-FBAB
-FBAC
-FBAD
-FBAE
-FBAF
-FBB0
-FBB1
-FBB2
-FBB3
-FBB4
-FBB5
-FBB6
-FBB7
-FBB8
-FBB9
-FBBA
-FBBB
-FBBC
-FBBD
-FBBE
-FBBF
-FBC0
-FBC1
-FBC2
-FBC3
-FBC4
-FBC5
-FBC6
-FBC7
-FBC8
-FBC9
-FBCA
-FBCB
-FBCC
-FBCD
-FBCE
-FBCF
-FBD0
-FBD1
-FBD2
-FBD3
-FBD4
-FBD5
-FBD6
-FBD7
-FBD8
-FBD9
-FBDA
-FBDB
-FBDC
-FBDD
-FBDE
-FBDF
-FBE0
-FBE1
-FBE2
-FBE3
-FBE4
-FBE5
-FBE6
-FBE7
-FBE8
-FBE9
-FBEA
-FBEB
-FBEC
-FBED
-FBEE
-FBEF
-FBF0
-FBF1
-FBF2
-FBF3
-FBF4
-FBF5
-FBF6
-FBF7
-FBF8
-FBF9
-FBFA
-FBFB
-FBFC
-FC40
-FC41
-FC42
-FC43
-FC44
-FC45
-FC46
-FC47
-FC48
-FC49
-FC4A
-FC4B
-CREATE TABLE t2 SELECT CONVERT(c1 USING ucs2) AS c1 FROM t1 ORDER BY BINARY c1;
-SELECT HEX(c1) FROM t2 ORDER BY BINARY c1;
+CREATE TABLE t2 SELECT CONVERT(c1 USING ucs2) AS c1 FROM t1;
+SELECT HEX(c1) FROM t2;
HEX(c1)
0005
007E
2015
-2116
-2116
-2121
-2121
-2160
-2160
-2161
-2161
-2162
-2162
-2163
-2163
-2164
-2164
-2165
-2165
-2166
-2166
-2167
-2167
-2168
-2168
-2169
-2169
-2170
-2170
-2171
-2171
-2172
-2172
-2173
-2173
-2174
-2174
-2175
-2175
-2176
-2176
-2177
-2177
-2178
-2178
-2179
-2179
-2211
-221A
-221F
-2220
+FF3C
+FF5E
2225
-2229
-222A
-222B
-222E
-2235
-2235
-2252
-2261
-22A5
-22BF
+FF0D
+FFE0
+FFE1
+FFE2
2460
2461
2462
@@ -3182,696 +3130,830 @@ HEX(c1)
2471
2472
2473
-301D
-301F
-3231
-3231
-3232
-3239
-32A4
-32A5
-32A6
-32A7
-32A8
-3303
-330D
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+3349
3314
-3318
3322
-3323
-3326
+334D
+3318
3327
-332B
+3303
3336
-333B
-3349
-334A
-334D
3351
3357
-337B
-337C
-337D
-337E
-338E
-338F
+330D
+3326
+3323
+332B
+334A
+333B
339C
339D
339E
-33A1
+338E
+338F
33C4
+33A1
+337B
+301D
+301F
+2116
33CD
+2121
+32A4
+32A5
+32A6
+32A7
+32A8
+3231
+3232
+3239
+337E
+337D
+337C
+2252
+2261
+222B
+222E
+2211
+221A
+22A5
+2220
+221F
+22BF
+2235
+2229
+222A
+7E8A
+891C
+9348
+9288
+84DC
+4FC9
+70BB
+6631
+68C8
+92F9
+66FB
+5F45
4E28
-4E28
-4EE1
4EE1
4EFC
-4EFC
-4F00
4F00
4F03
-4F03
-4F39
4F39
4F56
-4F56
-4F8A
-4F8A
-4F92
4F92
-4F94
-4F94
-4F9A
+4F8A
4F9A
-4FC9
-4FC9
-4FCD
+4F94
4FCD
+5040
+5022
4FFF
-4FFF
-501E
501E
-5022
-5022
-5040
-5040
-5042
-5042
-5046
5046
5070
-5070
-5094
+5042
5094
-50D8
-50D8
-50F4
50F4
-514A
+50D8
514A
5164
-5164
-519D
519D
51BE
-51BE
51EC
-51EC
-5215
5215
529C
-529C
-52A6
52A6
-52AF
-52AF
-52C0
52C0
52DB
-52DB
-5300
5300
5307
-5307
-5324
5324
5372
-5372
-5393
5393
53B2
-53B2
53DD
-53DD
-548A
-548A
-549C
+FA0E
549C
+548A
54A9
-54A9
-54FF
54FF
5586
-5586
-5759
5759
5765
-5765
-57AC
57AC
-57C7
-57C7
-57C8
57C8
-589E
+57C7
+FA0F
+FA10
589E
58B2
-58B2
-590B
590B
5953
-5953
595B
-595B
-595D
595D
5963
-5963
-59A4
59A4
59BA
-59BA
-5B56
5B56
5BC0
-5BC0
-5BD8
+752F
5BD8
5BEC
-5BEC
-5C1E
5C1E
5CA6
-5CA6
-5CBA
5CBA
5CF5
-5CF5
-5D27
5D27
-5D42
-5D42
5D53
-5D53
-5D6D
+FA11
+5D42
5D6D
5DB8
-5DB8
5DB9
-5DB9
-5DD0
5DD0
5F21
-5F21
-5F34
5F34
-5F45
-5F45
-5F67
5F67
5FB7
-5FB7
-5FDE
5FDE
605D
-605D
-6085
6085
608A
-608A
-60D5
-60D5
60DE
-60DE
-60F2
+60D5
+6120
60F2
6111
-6111
-6120
-6120
-6130
-6130
-6137
6137
-6198
+6130
6198
6213
-6213
-62A6
62A6
63F5
-63F5
6460
-6460
-649D
649D
64CE
-64CE
-654E
654E
6600
-6600
-6609
-6609
6615
-6615
-661E
+663B
+6609
+662E
661E
6624
-6624
-662E
-662E
-6631
-6631
-663B
-663B
-6657
+6665
6657
6659
-6659
-6665
-6665
-6673
+FA12
6673
6699
-6699
-66A0
66A0
66B2
-66B2
66BF
-66BF
-66FA
66FA
-66FB
-66FB
670E
-670E
-6766
+F929
6766
67BB
-67BB
-67C0
+6852
67C0
6801
-6801
6844
-6844
-6852
-6852
-68C8
-68C8
68CF
-68CF
-6968
+FA13
6968
+FA14
6998
-6998
-69E2
69E2
6A30
-6A30
-6A46
-6A46
-6A6B
6A6B
+6A46
6A73
-6A73
-6A7E
6A7E
6AE2
-6AE2
-6AE4
6AE4
6BD6
-6BD6
-6C3F
6C3F
6C5C
-6C5C
-6C6F
-6C6F
6C86
-6C86
-6CDA
+6C6F
6CDA
6D04
-6D04
-6D6F
-6D6F
-6D87
6D87
-6D96
+6D6F
6D96
6DAC
-6DAC
-6DCF
6DCF
-6DF2
-6DF2
6DF8
-6DF8
-6DFC
+6DF2
6DFC
-6E27
-6E27
-6E39
6E39
-6E3C
-6E3C
-6E5C
6E5C
+6E27
+6E3C
6EBF
-6EBF
-6F88
6F88
6FB5
-6FB5
-6FF5
6FF5
7005
-7005
7007
-7007
-7028
7028
7085
-7085
-70AB
70AB
-70BB
-70BB
-7104
-7104
-710F
710F
+7104
+715C
7146
-7146
-7147
7147
-715C
-715C
-71C1
+FA15
71C1
71FE
-71FE
-72B1
72B1
72BE
-72BE
-7324
7324
+FA16
7377
-7377
-73BD
73BD
73C9
-73C9
-73D2
-73D2
-73D6
73D6
73E3
-73E3
-73F5
-73F5
-7407
+73D2
7407
+73F5
7426
-7426
-7429
-7429
-742A
742A
-742E
+7429
742E
7462
-7462
-7489
7489
749F
-749F
-7501
7501
-752F
-752F
756F
-756F
-7682
7682
-769B
-769B
-769C
769C
769E
-769E
-76A6
+769B
76A6
+FA17
7746
-7746
-7821
+52AF
7821
784E
-784E
-7864
7864
787A
-787A
-7930
7930
+FA18
+FA19
+FA1A
7994
-7994
-799B
+FA1B
799B
7AD1
-7AD1
7AE7
-7AE7
-7AEB
+FA1C
7AEB
7B9E
-7B9E
-7D48
+FA1D
7D48
7D5C
-7D5C
-7DA0
-7DA0
-7DB7
7DB7
+7DA0
7DD6
-7DD6
-7E52
7E52
-7E8A
-7E8A
7F47
-7F47
-7FA1
7FA1
+FA1E
8301
-8301
-8362
8362
837F
-837F
-83C7
83C7
83F6
-83F6
-8448
8448
84B4
-84B4
-84DC
-84DC
8553
-8553
-8559
8559
856B
-856B
-85B0
+FA1F
85B0
-8807
+FA20
+FA21
8807
88F5
-88F5
-891C
-891C
-8A12
8A12
8A37
-8A37
8A79
-8A79
-8AA7
8AA7
8ABE
-8ABE
-8ADF
8ADF
+FA22
8AF6
-8AF6
-8B53
8B53
8B7F
-8B7F
-8CF0
8CF0
8CF4
-8CF4
-8D12
8D12
8D76
-8D76
-8ECF
+FA23
8ECF
+FA24
+FA25
9067
-9067
-90DE
90DE
-9115
+FA26
9115
9127
-9127
-91D7
-91D7
-91DA
91DA
+91D7
91DE
-91DE
-91E4
-91E4
-91E5
-91E5
-91ED
91ED
91EE
-91EE
-9206
+91E4
+91E5
9206
-920A
-920A
-9210
9210
-9239
-9239
-923A
+920A
923A
-923C
-923C
-9240
9240
+923C
924E
-924E
-9251
-9251
9259
-9259
-9267
+9251
+9239
9267
-9277
+92A7
9277
9278
-9278
-9288
-9288
-92A7
-92A7
-92D0
+92E7
+92D7
+92D9
92D0
-92D3
-92D3
-92D5
+FA27
92D5
-92D7
+92E0
+92D3
+9325
+9321
+92FB
+FA28
+931E
+92FF
+931D
+9302
+9370
+9357
+93A4
+93C6
+93DE
+93F8
+9431
+9445
+9448
+9592
+F9DC
+FA29
+969D
+96AF
+9733
+973B
+9743
+974D
+974F
+9751
+9755
+9857
+9865
+FA2A
+FA2B
+9927
+FA2C
+999E
+9A4E
+9AD9
+9ADC
+9B75
+9B72
+9B8F
+9BB1
+9BBB
+9C00
+9D70
+9D6B
+FA2D
+9E19
+9ED1
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+FFE2
+FFE4
+FF07
+FF02
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+FFE2
+FFE4
+FF07
+FF02
+3231
+2116
+2121
+2235
+7E8A
+891C
+9348
+9288
+84DC
+4FC9
+70BB
+6631
+68C8
+92F9
+66FB
+5F45
+4E28
+4EE1
+4EFC
+4F00
+4F03
+4F39
+4F56
+4F92
+4F8A
+4F9A
+4F94
+4FCD
+5040
+5022
+4FFF
+501E
+5046
+5070
+5042
+5094
+50F4
+50D8
+514A
+5164
+519D
+51BE
+51EC
+5215
+529C
+52A6
+52C0
+52DB
+5300
+5307
+5324
+5372
+5393
+53B2
+53DD
+FA0E
+549C
+548A
+54A9
+54FF
+5586
+5759
+5765
+57AC
+57C8
+57C7
+FA0F
+FA10
+589E
+58B2
+590B
+5953
+595B
+595D
+5963
+59A4
+59BA
+5B56
+5BC0
+752F
+5BD8
+5BEC
+5C1E
+5CA6
+5CBA
+5CF5
+5D27
+5D53
+FA11
+5D42
+5D6D
+5DB8
+5DB9
+5DD0
+5F21
+5F34
+5F67
+5FB7
+5FDE
+605D
+6085
+608A
+60DE
+60D5
+6120
+60F2
+6111
+6137
+6130
+6198
+6213
+62A6
+63F5
+6460
+649D
+64CE
+654E
+6600
+6615
+663B
+6609
+662E
+661E
+6624
+6665
+6657
+6659
+FA12
+6673
+6699
+66A0
+66B2
+66BF
+66FA
+670E
+F929
+6766
+67BB
+6852
+67C0
+6801
+6844
+68CF
+FA13
+6968
+FA14
+6998
+69E2
+6A30
+6A6B
+6A46
+6A73
+6A7E
+6AE2
+6AE4
+6BD6
+6C3F
+6C5C
+6C86
+6C6F
+6CDA
+6D04
+6D87
+6D6F
+6D96
+6DAC
+6DCF
+6DF8
+6DF2
+6DFC
+6E39
+6E5C
+6E27
+6E3C
+6EBF
+6F88
+6FB5
+6FF5
+7005
+7007
+7028
+7085
+70AB
+710F
+7104
+715C
+7146
+7147
+FA15
+71C1
+71FE
+72B1
+72BE
+7324
+FA16
+7377
+73BD
+73C9
+73D6
+73E3
+73D2
+7407
+73F5
+7426
+742A
+7429
+742E
+7462
+7489
+749F
+7501
+756F
+7682
+769C
+769E
+769B
+76A6
+FA17
+7746
+52AF
+7821
+784E
+7864
+787A
+7930
+FA18
+FA19
+FA1A
+7994
+FA1B
+799B
+7AD1
+7AE7
+FA1C
+7AEB
+7B9E
+FA1D
+7D48
+7D5C
+7DB7
+7DA0
+7DD6
+7E52
+7F47
+7FA1
+FA1E
+8301
+8362
+837F
+83C7
+83F6
+8448
+84B4
+8553
+8559
+856B
+FA1F
+85B0
+FA20
+FA21
+8807
+88F5
+8A12
+8A37
+8A79
+8AA7
+8ABE
+8ADF
+FA22
+8AF6
+8B53
+8B7F
+8CF0
+8CF4
+8D12
+8D76
+FA23
+8ECF
+FA24
+FA25
+9067
+90DE
+FA26
+9115
+9127
+91DA
+91D7
+91DE
+91ED
+91EE
+91E4
+91E5
+9206
+9210
+920A
+923A
+9240
+923C
+924E
+9259
+9251
+9239
+9267
+92A7
+9277
+9278
+92E7
92D7
92D9
-92D9
-92E0
+92D0
+FA27
+92D5
92E0
-92E7
-92E7
-92F9
-92F9
-92FB
+92D3
+9325
+9321
92FB
+FA28
+931E
92FF
-92FF
-9302
-9302
931D
-931D
-931E
-931E
-9321
-9321
-9325
-9325
-9348
-9348
-9357
-9357
-9370
+9302
9370
+9357
93A4
-93A4
-93C6
93C6
93DE
-93DE
-93F8
93F8
9431
-9431
-9445
9445
9448
-9448
-9592
9592
-969D
+F9DC
+FA29
969D
96AF
-96AF
-9733
9733
973B
-973B
-9743
9743
974D
-974D
-974F
974F
9751
-9751
-9755
9755
9857
-9857
-9865
9865
+FA2A
+FA2B
9927
-9927
-999E
+FA2C
999E
9A4E
-9A4E
-9AD9
9AD9
9ADC
-9ADC
-9B72
-9B72
9B75
-9B75
-9B8F
+9B72
9B8F
9BB1
-9BB1
9BBB
-9BBB
-9C00
9C00
-9D6B
-9D6B
-9D70
9D70
+9D6B
+FA2D
9E19
-9E19
-9ED1
9ED1
E000
E001
@@ -5753,90 +5835,8 @@ E754
E755
E756
E757
-F929
-F929
-F9DC
-F9DC
-FA0E
-FA0E
-FA0F
-FA0F
-FA10
-FA10
-FA11
-FA11
-FA12
-FA12
-FA13
-FA13
-FA14
-FA14
-FA15
-FA15
-FA16
-FA16
-FA17
-FA17
-FA18
-FA18
-FA19
-FA19
-FA1A
-FA1A
-FA1B
-FA1B
-FA1C
-FA1C
-FA1D
-FA1D
-FA1E
-FA1E
-FA1F
-FA1F
-FA20
-FA20
-FA21
-FA21
-FA22
-FA22
-FA23
-FA23
-FA24
-FA24
-FA25
-FA25
-FA26
-FA26
-FA27
-FA27
-FA28
-FA28
-FA29
-FA29
-FA2A
-FA2A
-FA2B
-FA2B
-FA2C
-FA2C
-FA2D
-FA2D
-FF02
-FF02
-FF07
-FF07
-FF0D
-FF3C
-FF5E
-FFE0
-FFE1
-FFE2
-FFE2
-FFE2
-FFE4
-FFE4
-CREATE TABLE t3 SELECT CONVERT(c1 USING cp932) AS c1 FROM t2 ORDER BY BINARY c1;
-SELECT HEX(c1) FROM t3 ORDER BY BINARY c1;
+CREATE TABLE t3 SELECT CONVERT(c1 USING cp932) AS c1 FROM t2;
+SELECT HEX(c1) FROM t3;
HEX(c1)
05
7E
@@ -5847,19 +5847,7 @@ HEX(c1)
817C
8191
8192
-81BE
-81BF
81CA
-81CA
-81CA
-81DA
-81DB
-81DF
-81E0
-81E3
-81E6
-81E6
-81E7
8740
8741
8742
@@ -5881,24 +5869,14 @@ HEX(c1)
8752
8753
8754
-8754
8755
-8755
-8756
8756
8757
-8757
-8758
8758
8759
-8759
-875A
875A
875B
-875B
875C
-875C
-875D
875D
875F
8760
@@ -5927,26 +5905,794 @@ HEX(c1)
8780
8781
8782
-8782
8783
8784
-8784
8785
8786
8787
8788
8789
878A
-878A
878B
878C
878D
878E
878F
+81E0
+81DF
+81E7
8793
8794
+81E3
+81DB
+81DA
8798
8799
+81E6
+81BF
+81BE
+FA5C
+FA5D
+FA5E
+FA5F
+FA60
+FA61
+FA62
+FA63
+FA64
+FA65
+FA66
+FA67
+FA68
+FA69
+FA6A
+FA6B
+FA6C
+FA6D
+FA6E
+FA6F
+FA70
+FA71
+FA72
+FA73
+FA74
+FA75
+FA76
+FA77
+FA78
+FA79
+FA7A
+FA7B
+FA7C
+FA7D
+FA7E
+FA80
+FA81
+FA82
+FA83
+FA84
+FA85
+FA86
+FA87
+FA88
+FA89
+FA8A
+FA8B
+FA8C
+FA8D
+FA8E
+FA8F
+FA90
+FA91
+FA92
+FA93
+FA94
+FA95
+FA96
+FA97
+FA98
+FA99
+FA9A
+FA9B
+FA9C
+FA9D
+FA9E
+FA9F
+FAA0
+FAA1
+FAA2
+FAA3
+FAA4
+FAA5
+FAA6
+FAA7
+FAA8
+FAA9
+FAAA
+FAAB
+FAAC
+FAAD
+FAAE
+FAAF
+FAB0
+FAB1
+FAB2
+FAB3
+FAB4
+FAB5
+FAB6
+FAB7
+FAB8
+FAB9
+FABA
+FABB
+FABC
+FABD
+FABE
+FABF
+FAC0
+FAC1
+FAC2
+FAC3
+FAC4
+FAC5
+FAC6
+FAC7
+FAC8
+FAC9
+FACA
+FACB
+FACC
+FACD
+FACE
+FACF
+FAD0
+FAD1
+FAD2
+FAD3
+FAD4
+FAD5
+FAD6
+FAD7
+FAD8
+FAD9
+FADA
+FADB
+FADC
+FADD
+FADE
+FADF
+FAE0
+FAE1
+FAE2
+FAE3
+FAE4
+FAE5
+FAE6
+FAE7
+FAE8
+FAE9
+FAEA
+FAEB
+FAEC
+FAED
+FAEE
+FAEF
+FAF0
+FAF1
+FAF2
+FAF3
+FAF4
+FAF5
+FAF6
+FAF7
+FAF8
+FAF9
+FAFA
+FAFB
+FAFC
+FB40
+FB41
+FB42
+FB43
+FB44
+FB45
+FB46
+FB47
+FB48
+FB49
+FB4A
+FB4B
+FB4C
+FB4D
+FB4E
+FB4F
+FB50
+FB51
+FB52
+FB53
+FB54
+FB55
+FB56
+FB57
+FB58
+FB59
+FB5A
+FB5B
+FB5C
+FB5D
+FB5E
+FB5F
+FB60
+FB61
+FB62
+FB63
+FB64
+FB65
+FB66
+FB67
+FB68
+FB69
+FB6A
+FB6B
+FB6C
+FB6D
+FB6E
+FB6F
+FB70
+FB71
+FB72
+FB73
+FB74
+FB75
+FB76
+FB77
+FB78
+FB79
+FB7A
+FB7B
+FB7C
+FB7D
+FB7E
+FB80
+FB81
+FB82
+FB83
+FB84
+FB85
+FB86
+FB87
+FB88
+FB89
+FB8A
+FB8B
+FB8C
+FB8D
+FB8E
+FB8F
+FB90
+FB91
+FB92
+FB93
+FB94
+FB95
+FB96
+FB97
+FB98
+FB99
+FB9A
+FB9B
+FB9C
+FB9D
+FB9E
+FB9F
+FBA0
+FBA1
+FBA2
+FBA3
+FBA4
+FBA5
+FBA6
+FBA7
+FBA8
+FBA9
+FBAA
+FBAB
+FBAC
+FBAD
+FBAE
+FBAF
+FBB0
+FBB1
+FBB2
+FBB3
+FBB4
+FBB5
+FBB6
+FBB7
+FBB8
+FBB9
+FBBA
+FBBB
+FBBC
+FBBD
+FBBE
+FBBF
+FBC0
+FBC1
+FBC2
+FBC3
+FBC4
+FBC5
+FBC6
+FBC7
+FBC8
+FBC9
+FBCA
+FBCB
+FBCC
+FBCD
+FBCE
+FBCF
+FBD0
+FBD1
+FBD2
+FBD3
+FBD4
+FBD5
+FBD6
+FBD7
+FBD8
+FBD9
+FBDA
+FBDB
+FBDC
+FBDD
+FBDE
+FBDF
+FBE0
+FBE1
+FBE2
+FBE3
+FBE4
+FBE5
+FBE6
+FBE7
+FBE8
+FBE9
+FBEA
+FBEB
+FBEC
+FBED
+FBEE
+FBEF
+FBF0
+FBF1
+FBF2
+FBF3
+FBF4
+FBF5
+FBF6
+FBF7
+FBF8
+FBF9
+FBFA
+FBFB
+FBFC
+FC40
+FC41
+FC42
+FC43
+FC44
+FC45
+FC46
+FC47
+FC48
+FC49
+FC4A
+FC4B
+FA40
+FA41
+FA42
+FA43
+FA44
+FA45
+FA46
+FA47
+FA48
+FA49
+81CA
+FA55
+FA56
+FA57
+FA40
+FA41
+FA42
+FA43
+FA44
+FA45
+FA46
+FA47
+FA48
+FA49
+8754
+8755
+8756
+8757
+8758
+8759
+875A
+875B
+875C
+875D
+81CA
+FA55
+FA56
+FA57
+878A
+8782
+8784
+81E6
+FA5C
+FA5D
+FA5E
+FA5F
+FA60
+FA61
+FA62
+FA63
+FA64
+FA65
+FA66
+FA67
+FA68
+FA69
+FA6A
+FA6B
+FA6C
+FA6D
+FA6E
+FA6F
+FA70
+FA71
+FA72
+FA73
+FA74
+FA75
+FA76
+FA77
+FA78
+FA79
+FA7A
+FA7B
+FA7C
+FA7D
+FA7E
+FA80
+FA81
+FA82
+FA83
+FA84
+FA85
+FA86
+FA87
+FA88
+FA89
+FA8A
+FA8B
+FA8C
+FA8D
+FA8E
+FA8F
+FA90
+FA91
+FA92
+FA93
+FA94
+FA95
+FA96
+FA97
+FA98
+FA99
+FA9A
+FA9B
+FA9C
+FA9D
+FA9E
+FA9F
+FAA0
+FAA1
+FAA2
+FAA3
+FAA4
+FAA5
+FAA6
+FAA7
+FAA8
+FAA9
+FAAA
+FAAB
+FAAC
+FAAD
+FAAE
+FAAF
+FAB0
+FAB1
+FAB2
+FAB3
+FAB4
+FAB5
+FAB6
+FAB7
+FAB8
+FAB9
+FABA
+FABB
+FABC
+FABD
+FABE
+FABF
+FAC0
+FAC1
+FAC2
+FAC3
+FAC4
+FAC5
+FAC6
+FAC7
+FAC8
+FAC9
+FACA
+FACB
+FACC
+FACD
+FACE
+FACF
+FAD0
+FAD1
+FAD2
+FAD3
+FAD4
+FAD5
+FAD6
+FAD7
+FAD8
+FAD9
+FADA
+FADB
+FADC
+FADD
+FADE
+FADF
+FAE0
+FAE1
+FAE2
+FAE3
+FAE4
+FAE5
+FAE6
+FAE7
+FAE8
+FAE9
+FAEA
+FAEB
+FAEC
+FAED
+FAEE
+FAEF
+FAF0
+FAF1
+FAF2
+FAF3
+FAF4
+FAF5
+FAF6
+FAF7
+FAF8
+FAF9
+FAFA
+FAFB
+FAFC
+FB40
+FB41
+FB42
+FB43
+FB44
+FB45
+FB46
+FB47
+FB48
+FB49
+FB4A
+FB4B
+FB4C
+FB4D
+FB4E
+FB4F
+FB50
+FB51
+FB52
+FB53
+FB54
+FB55
+FB56
+FB57
+FB58
+FB59
+FB5A
+FB5B
+FB5C
+FB5D
+FB5E
+FB5F
+FB60
+FB61
+FB62
+FB63
+FB64
+FB65
+FB66
+FB67
+FB68
+FB69
+FB6A
+FB6B
+FB6C
+FB6D
+FB6E
+FB6F
+FB70
+FB71
+FB72
+FB73
+FB74
+FB75
+FB76
+FB77
+FB78
+FB79
+FB7A
+FB7B
+FB7C
+FB7D
+FB7E
+FB80
+FB81
+FB82
+FB83
+FB84
+FB85
+FB86
+FB87
+FB88
+FB89
+FB8A
+FB8B
+FB8C
+FB8D
+FB8E
+FB8F
+FB90
+FB91
+FB92
+FB93
+FB94
+FB95
+FB96
+FB97
+FB98
+FB99
+FB9A
+FB9B
+FB9C
+FB9D
+FB9E
+FB9F
+FBA0
+FBA1
+FBA2
+FBA3
+FBA4
+FBA5
+FBA6
+FBA7
+FBA8
+FBA9
+FBAA
+FBAB
+FBAC
+FBAD
+FBAE
+FBAF
+FBB0
+FBB1
+FBB2
+FBB3
+FBB4
+FBB5
+FBB6
+FBB7
+FBB8
+FBB9
+FBBA
+FBBB
+FBBC
+FBBD
+FBBE
+FBBF
+FBC0
+FBC1
+FBC2
+FBC3
+FBC4
+FBC5
+FBC6
+FBC7
+FBC8
+FBC9
+FBCA
+FBCB
+FBCC
+FBCD
+FBCE
+FBCF
+FBD0
+FBD1
+FBD2
+FBD3
+FBD4
+FBD5
+FBD6
+FBD7
+FBD8
+FBD9
+FBDA
+FBDB
+FBDC
+FBDD
+FBDE
+FBDF
+FBE0
+FBE1
+FBE2
+FBE3
+FBE4
+FBE5
+FBE6
+FBE7
+FBE8
+FBE9
+FBEA
+FBEB
+FBEC
+FBED
+FBEE
+FBEF
+FBF0
+FBF1
+FBF2
+FBF3
+FBF4
+FBF5
+FBF6
+FBF7
+FBF8
+FBF9
+FBFA
+FBFB
+FBFC
+FC40
+FC41
+FC42
+FC43
+FC44
+FC45
+FC46
+FC47
+FC48
+FC49
+FC4A
+FC4B
F040
F041
F042
@@ -7827,767 +8573,2758 @@ F9F9
F9FA
F9FB
F9FC
-FA40
-FA40
-FA41
-FA41
-FA42
-FA42
-FA43
-FA43
-FA44
-FA44
-FA45
-FA45
-FA46
-FA46
-FA47
-FA47
-FA48
-FA48
-FA49
-FA49
-FA55
-FA55
-FA56
-FA56
-FA57
-FA57
-FA5C
-FA5C
-FA5D
-FA5D
-FA5E
-FA5E
-FA5F
-FA5F
-FA60
-FA60
-FA61
-FA61
-FA62
-FA62
-FA63
-FA63
-FA64
-FA64
-FA65
-FA65
-FA66
-FA66
-FA67
-FA67
-FA68
-FA68
-FA69
-FA69
-FA6A
-FA6A
-FA6B
-FA6B
-FA6C
-FA6C
-FA6D
-FA6D
-FA6E
-FA6E
-FA6F
-FA6F
-FA70
-FA70
-FA71
-FA71
-FA72
-FA72
-FA73
-FA73
-FA74
-FA74
-FA75
-FA75
-FA76
-FA76
-FA77
-FA77
-FA78
-FA78
-FA79
-FA79
-FA7A
-FA7A
-FA7B
-FA7B
-FA7C
-FA7C
-FA7D
-FA7D
-FA7E
-FA7E
-FA80
-FA80
-FA81
-FA81
-FA82
-FA82
-FA83
-FA83
-FA84
-FA84
-FA85
-FA85
-FA86
-FA86
-FA87
-FA87
-FA88
-FA88
-FA89
-FA89
-FA8A
-FA8A
-FA8B
-FA8B
-FA8C
-FA8C
-FA8D
-FA8D
-FA8E
-FA8E
-FA8F
-FA8F
-FA90
-FA90
-FA91
-FA91
-FA92
-FA92
-FA93
-FA93
-FA94
-FA94
-FA95
-FA95
-FA96
-FA96
-FA97
-FA97
-FA98
-FA98
-FA99
-FA99
-FA9A
-FA9A
-FA9B
-FA9B
-FA9C
-FA9C
-FA9D
-FA9D
-FA9E
-FA9E
-FA9F
-FA9F
-FAA0
-FAA0
-FAA1
+CREATE TABLE t4 SELECT CONVERT(c1 USING eucjpms) AS c1 FROM t1;
+SELECT HEX(c1) FROM t4;
+HEX(c1)
+05
+7E
+A1BD
+A1C0
+A1C1
+A1C2
+A1DD
+A1F1
+A1F2
+A2CC
+ADA1
+ADA2
+ADA3
+ADA4
+ADA5
+ADA6
+ADA7
+ADA8
+ADA9
+ADAA
+ADAB
+ADAC
+ADAD
+ADAE
+ADAF
+ADB0
+ADB1
+ADB2
+ADB3
+ADB4
+ADB5
+ADB6
+ADB7
+ADB8
+ADB9
+ADBA
+ADBB
+ADBC
+ADBD
+ADBE
+ADC0
+ADC1
+ADC2
+ADC3
+ADC4
+ADC5
+ADC6
+ADC7
+ADC8
+ADC9
+ADCA
+ADCB
+ADCC
+ADCD
+ADCE
+ADCF
+ADD0
+ADD1
+ADD2
+ADD3
+ADD4
+ADD5
+ADD6
+ADDF
+ADE0
+ADE1
+ADE2
+ADE3
+ADE4
+ADE5
+ADE6
+ADE7
+ADE8
+ADE9
+ADEA
+ADEB
+ADEC
+ADED
+ADEE
+ADEF
+A2E2
+A2E1
+A2E9
+ADF3
+ADF4
+A2E5
+A2DD
+A2DC
+ADF8
+ADF9
+A2E8
+A2C1
+A2C0
+8FD4E3
+8FDCDF
+8FE4E9
+8FE3F8
+8FD9A1
+8FB1BB
+8FF4AE
+8FC2AD
+8FC3FC
+8FE4D0
+8FC2BF
+8FBCF4
+8FB0A9
+8FB0C8
+8FF4AF
+8FB0D2
+8FB0D4
+8FB0E3
+8FB0EE
+8FB1A7
+8FB1A3
+8FB1AC
+8FB1A9
+8FB1BE
+8FB1DF
+8FB1D8
+8FB1C8
+8FB1D7
+8FB1E3
+8FB1F4
+8FB1E1
+8FB2A3
+8FF4B0
+8FB2BB
+8FB2E6
+8FB2ED
+8FB2F5
+8FB2FC
+8FF4B1
+8FB3B5
+8FB3D8
+8FB3DB
+8FB3E5
+8FB3EE
+8FB3FB
+8FF4B2
+8FF4B3
+8FB4C0
+8FB4C7
+8FB4D0
+8FB4DE
+8FF4B4
+8FB5AA
+8FF4B5
+8FB5AF
+8FB5C4
+8FB5E8
+8FF4B6
+8FB7C2
+8FB7E4
+8FB7E8
+8FB7E7
+8FF4B7
+8FF4B8
+8FF4B9
+8FB8CE
+8FB8E1
+8FB8F5
+8FB8F7
+8FB8F8
+8FB8FC
+8FB9AF
+8FB9B7
+8FBABE
+8FBADB
+8FCDAA
+8FBAE1
+8FF4BA
+8FBAEB
+8FBBB3
+8FBBB8
+8FF4BB
+8FBBCA
+8FF4BC
+8FF4BD
+8FBBD0
+8FBBDE
+8FBBF4
+8FBBF5
+8FBBF9
+8FBCE4
+8FBCED
+8FBCFE
+8FF4BE
+8FBDC2
+8FBDE7
+8FF4BF
+8FBDF0
+8FBEB0
+8FBEAC
+8FF4C0
+8FBEB3
+8FBEBD
+8FBECD
+8FBEC9
+8FBEE4
+8FBFA8
+8FBFC9
+8FC0C4
+8FC0E4
+8FC0F4
+8FC1A6
+8FF4C1
+8FC1F5
+8FC1FC
+8FF4C2
+8FC1F8
+8FC2AB
+8FC2A1
+8FC2A5
+8FF4C3
+8FC2B8
+8FC2BA
+8FF4C4
+8FC2C4
+8FC2D2
+8FC2D7
+8FC2DB
+8FC2DE
+8FC2ED
+8FC2F0
+8FF4C5
+8FC3A1
+8FC3B5
+8FC3C9
+8FC3B9
+8FF4C6
+8FC3D8
+8FC3FE
+8FF4C7
+8FC4CC
+8FF4C8
+8FC4D9
+8FC4EA
+8FC4FD
+8FF4C9
+8FC5A7
+8FC5B5
+8FC5B6
+8FF4CA
+8FC5D5
+8FC6B8
+8FC6D7
+8FC6E0
+8FC6EA
+8FC6E3
+8FC7A1
+8FC7AB
+8FC7C7
+8FC7C3
+8FC7CB
+8FC7CF
+8FC7D9
+8FF4CB
+8FF4CC
+8FC7E6
+8FC7EE
+8FC7FC
+8FC7EB
+8FC7F0
+8FC8B1
+8FC8E5
+8FC8F8
+8FC9A6
+8FC9AB
+8FC9AD
+8FF4CD
+8FC9CA
+8FC9D3
+8FC9E9
+8FC9E3
+8FC9FC
+8FC9F4
+8FC9F5
+8FF4CE
+8FCAB3
+8FCABD
+8FCAEF
+8FCAF1
+8FCBAE
+8FF4CF
+8FCBCA
+8FCBE6
+8FCBEA
+8FCBF0
+8FCBF4
+8FCBEE
+8FCCA5
+8FCBF9
+8FCCAB
+8FCCAE
+8FCCAD
+8FCCB2
+8FCCC2
+8FCCD0
+8FCCD9
+8FF4D0
+8FCDBB
+8FF4D1
+8FCEBB
+8FF4D2
+8FCEBA
+8FCEC3
+8FF4D3
+8FCEF2
+8FB3DD
+8FCFD5
+8FCFE2
+8FCFE9
+8FCFED
+8FF4D4
+8FF4D5
+8FF4D6
+8FF4D7
+8FD0E5
+8FF4D8
+8FD0E9
+8FD1E8
+8FF4D9
+8FF4DA
+8FD1EC
+8FD2BB
+8FF4DB
+8FD3E1
+8FD3E8
+8FD4A7
+8FF4DC
+8FF4DD
+8FD4D4
+8FD4F2
+8FD5AE
+8FF4DE
+8FD7DE
+8FF4DF
+8FD8A2
+8FD8B7
+8FD8C1
+8FD8D1
+8FD8F4
+8FD9C6
+8FD9C8
+8FD9D1
+8FF4E0
+8FF4E1
+8FF4E2
+8FF4E3
+8FF4E4
+8FDCD3
+8FDDC8
+8FDDD4
+8FDDEA
+8FDDFA
+8FDEA4
+8FDEB0
+8FF4E5
+8FDEB5
+8FDECB
+8FF4E6
+8FDFB9
+8FF4E7
+8FDFC3
+8FF4E8
+8FF4E9
+8FE0D9
+8FF4EA
+8FF4EB
+8FE1E2
+8FF4EC
+8FF4ED
+8FF4EE
+8FE2C7
+8FE3A8
+8FE3A6
+8FE3A9
+8FE3AF
+8FE3B0
+8FE3AA
+8FE3AB
+8FE3BC
+8FE3C1
+8FE3BF
+8FE3D5
+8FE3D8
+8FE3D6
+8FE3DF
+8FE3E3
+8FE3E1
+8FE3D4
+8FE3E9
+8FE4A6
+8FE3F1
+8FE3F2
+8FE4CB
+8FE4C1
+8FE4C3
+8FE4BE
+8FF4EF
+8FE4C0
+8FE4C7
+8FE4BF
+8FE4E0
+8FE4DE
+8FE4D1
+8FF4F0
+8FE4DC
+8FE4D2
+8FE4DB
+8FE4D4
+8FE4FA
+8FE4EF
+8FE5B3
+8FE5BF
+8FE5C9
+8FE5D0
+8FE5E2
+8FE5EA
+8FE5EB
+8FF4F1
+8FF4F2
+8FF4F3
+8FE6E8
+8FE6EF
+8FE7AC
+8FF4F4
+8FE7AE
+8FF4F5
+8FE7B1
+8FF4F6
+8FE7B2
+8FE8B1
+8FE8B6
+8FF4F7
+8FF4F8
+8FE8DD
+8FF4F9
+8FF4FA
+8FE9D1
+8FF4FB
+8FE9ED
+8FEACD
+8FF4FC
+8FEADB
+8FEAE6
+8FEAEA
+8FEBA5
+8FEBFB
+8FEBFA
+8FF4FD
+8FECD6
+8FF4FE
+8FF3F3
+8FF3F4
+8FF3F5
+8FF3F6
+8FF3F7
+8FF3F8
+8FF3F9
+8FF3FA
+8FF3FB
+8FF3FC
+A2CC
+8FA2C3
+8FF4A9
+8FF4AA
+8FF3F3
+8FF3F4
+8FF3F5
+8FF3F6
+8FF3F7
+8FF3F8
+8FF3F9
+8FF3FA
+8FF3FB
+8FF3FC
+ADB5
+ADB6
+ADB7
+ADB8
+ADB9
+ADBA
+ADBB
+ADBC
+ADBD
+ADBE
+A2CC
+8FA2C3
+8FF4A9
+8FF4AA
+ADEA
+ADE2
+ADE4
+A2E8
+8FD4E3
+8FDCDF
+8FE4E9
+8FE3F8
+8FD9A1
+8FB1BB
+8FF4AE
+8FC2AD
+8FC3FC
+8FE4D0
+8FC2BF
+8FBCF4
+8FB0A9
+8FB0C8
+8FF4AF
+8FB0D2
+8FB0D4
+8FB0E3
+8FB0EE
+8FB1A7
+8FB1A3
+8FB1AC
+8FB1A9
+8FB1BE
+8FB1DF
+8FB1D8
+8FB1C8
+8FB1D7
+8FB1E3
+8FB1F4
+8FB1E1
+8FB2A3
+8FF4B0
+8FB2BB
+8FB2E6
+8FB2ED
+8FB2F5
+8FB2FC
+8FF4B1
+8FB3B5
+8FB3D8
+8FB3DB
+8FB3E5
+8FB3EE
+8FB3FB
+8FF4B2
+8FF4B3
+8FB4C0
+8FB4C7
+8FB4D0
+8FB4DE
+8FF4B4
+8FB5AA
+8FF4B5
+8FB5AF
+8FB5C4
+8FB5E8
+8FF4B6
+8FB7C2
+8FB7E4
+8FB7E8
+8FB7E7
+8FF4B7
+8FF4B8
+8FF4B9
+8FB8CE
+8FB8E1
+8FB8F5
+8FB8F7
+8FB8F8
+8FB8FC
+8FB9AF
+8FB9B7
+8FBABE
+8FBADB
+8FCDAA
+8FBAE1
+8FF4BA
+8FBAEB
+8FBBB3
+8FBBB8
+8FF4BB
+8FBBCA
+8FF4BC
+8FF4BD
+8FBBD0
+8FBBDE
+8FBBF4
+8FBBF5
+8FBBF9
+8FBCE4
+8FBCED
+8FBCFE
+8FF4BE
+8FBDC2
+8FBDE7
+8FF4BF
+8FBDF0
+8FBEB0
+8FBEAC
+8FF4C0
+8FBEB3
+8FBEBD
+8FBECD
+8FBEC9
+8FBEE4
+8FBFA8
+8FBFC9
+8FC0C4
+8FC0E4
+8FC0F4
+8FC1A6
+8FF4C1
+8FC1F5
+8FC1FC
+8FF4C2
+8FC1F8
+8FC2AB
+8FC2A1
+8FC2A5
+8FF4C3
+8FC2B8
+8FC2BA
+8FF4C4
+8FC2C4
+8FC2D2
+8FC2D7
+8FC2DB
+8FC2DE
+8FC2ED
+8FC2F0
+8FF4C5
+8FC3A1
+8FC3B5
+8FC3C9
+8FC3B9
+8FF4C6
+8FC3D8
+8FC3FE
+8FF4C7
+8FC4CC
+8FF4C8
+8FC4D9
+8FC4EA
+8FC4FD
+8FF4C9
+8FC5A7
+8FC5B5
+8FC5B6
+8FF4CA
+8FC5D5
+8FC6B8
+8FC6D7
+8FC6E0
+8FC6EA
+8FC6E3
+8FC7A1
+8FC7AB
+8FC7C7
+8FC7C3
+8FC7CB
+8FC7CF
+8FC7D9
+8FF4CB
+8FF4CC
+8FC7E6
+8FC7EE
+8FC7FC
+8FC7EB
+8FC7F0
+8FC8B1
+8FC8E5
+8FC8F8
+8FC9A6
+8FC9AB
+8FC9AD
+8FF4CD
+8FC9CA
+8FC9D3
+8FC9E9
+8FC9E3
+8FC9FC
+8FC9F4
+8FC9F5
+8FF4CE
+8FCAB3
+8FCABD
+8FCAEF
+8FCAF1
+8FCBAE
+8FF4CF
+8FCBCA
+8FCBE6
+8FCBEA
+8FCBF0
+8FCBF4
+8FCBEE
+8FCCA5
+8FCBF9
+8FCCAB
+8FCCAE
+8FCCAD
+8FCCB2
+8FCCC2
+8FCCD0
+8FCCD9
+8FF4D0
+8FCDBB
+8FF4D1
+8FCEBB
+8FF4D2
+8FCEBA
+8FCEC3
+8FF4D3
+8FCEF2
+8FB3DD
+8FCFD5
+8FCFE2
+8FCFE9
+8FCFED
+8FF4D4
+8FF4D5
+8FF4D6
+8FF4D7
+8FD0E5
+8FF4D8
+8FD0E9
+8FD1E8
+8FF4D9
+8FF4DA
+8FD1EC
+8FD2BB
+8FF4DB
+8FD3E1
+8FD3E8
+8FD4A7
+8FF4DC
+8FF4DD
+8FD4D4
+8FD4F2
+8FD5AE
+8FF4DE
+8FD7DE
+8FF4DF
+8FD8A2
+8FD8B7
+8FD8C1
+8FD8D1
+8FD8F4
+8FD9C6
+8FD9C8
+8FD9D1
+8FF4E0
+8FF4E1
+8FF4E2
+8FF4E3
+8FF4E4
+8FDCD3
+8FDDC8
+8FDDD4
+8FDDEA
+8FDDFA
+8FDEA4
+8FDEB0
+8FF4E5
+8FDEB5
+8FDECB
+8FF4E6
+8FDFB9
+8FF4E7
+8FDFC3
+8FF4E8
+8FF4E9
+8FE0D9
+8FF4EA
+8FF4EB
+8FE1E2
+8FF4EC
+8FF4ED
+8FF4EE
+8FE2C7
+8FE3A8
+8FE3A6
+8FE3A9
+8FE3AF
+8FE3B0
+8FE3AA
+8FE3AB
+8FE3BC
+8FE3C1
+8FE3BF
+8FE3D5
+8FE3D8
+8FE3D6
+8FE3DF
+8FE3E3
+8FE3E1
+8FE3D4
+8FE3E9
+8FE4A6
+8FE3F1
+8FE3F2
+8FE4CB
+8FE4C1
+8FE4C3
+8FE4BE
+8FF4EF
+8FE4C0
+8FE4C7
+8FE4BF
+8FE4E0
+8FE4DE
+8FE4D1
+8FF4F0
+8FE4DC
+8FE4D2
+8FE4DB
+8FE4D4
+8FE4FA
+8FE4EF
+8FE5B3
+8FE5BF
+8FE5C9
+8FE5D0
+8FE5E2
+8FE5EA
+8FE5EB
+8FF4F1
+8FF4F2
+8FF4F3
+8FE6E8
+8FE6EF
+8FE7AC
+8FF4F4
+8FE7AE
+8FF4F5
+8FE7B1
+8FF4F6
+8FE7B2
+8FE8B1
+8FE8B6
+8FF4F7
+8FF4F8
+8FE8DD
+8FF4F9
+8FF4FA
+8FE9D1
+8FF4FB
+8FE9ED
+8FEACD
+8FF4FC
+8FEADB
+8FEAE6
+8FEAEA
+8FEBA5
+8FEBFB
+8FEBFA
+8FF4FD
+8FECD6
+8FF4FE
+F5A1
+F5A2
+F5A3
+F5A4
+F5A5
+F5A6
+F5A7
+F5A8
+F5A9
+F5AA
+F5AB
+F5AC
+F5AD
+F5AE
+F5AF
+F5B0
+F5B1
+F5B2
+F5B3
+F5B4
+F5B5
+F5B6
+F5B7
+F5B8
+F5B9
+F5BA
+F5BB
+F5BC
+F5BD
+F5BE
+F5BF
+F5C0
+F5C1
+F5C2
+F5C3
+F5C4
+F5C5
+F5C6
+F5C7
+F5C8
+F5C9
+F5CA
+F5CB
+F5CC
+F5CD
+F5CE
+F5CF
+F5D0
+F5D1
+F5D2
+F5D3
+F5D4
+F5D5
+F5D6
+F5D7
+F5D8
+F5D9
+F5DA
+F5DB
+F5DC
+F5DD
+F5DE
+F5DF
+F5E0
+F5E1
+F5E2
+F5E3
+F5E4
+F5E5
+F5E6
+F5E7
+F5E8
+F5E9
+F5EA
+F5EB
+F5EC
+F5ED
+F5EE
+F5EF
+F5F0
+F5F1
+F5F2
+F5F3
+F5F4
+F5F5
+F5F6
+F5F7
+F5F8
+F5F9
+F5FA
+F5FB
+F5FC
+F5FD
+F5FE
+F6A1
+F6A2
+F6A3
+F6A4
+F6A5
+F6A6
+F6A7
+F6A8
+F6A9
+F6AA
+F6AB
+F6AC
+F6AD
+F6AE
+F6AF
+F6B0
+F6B1
+F6B2
+F6B3
+F6B4
+F6B5
+F6B6
+F6B7
+F6B8
+F6B9
+F6BA
+F6BB
+F6BC
+F6BD
+F6BE
+F6BF
+F6C0
+F6C1
+F6C2
+F6C3
+F6C4
+F6C5
+F6C6
+F6C7
+F6C8
+F6C9
+F6CA
+F6CB
+F6CC
+F6CD
+F6CE
+F6CF
+F6D0
+F6D1
+F6D2
+F6D3
+F6D4
+F6D5
+F6D6
+F6D7
+F6D8
+F6D9
+F6DA
+F6DB
+F6DC
+F6DD
+F6DE
+F6DF
+F6E0
+F6E1
+F6E2
+F6E3
+F6E4
+F6E5
+F6E6
+F6E7
+F6E8
+F6E9
+F6EA
+F6EB
+F6EC
+F6ED
+F6EE
+F6EF
+F6F0
+F6F1
+F6F2
+F6F3
+F6F4
+F6F5
+F6F6
+F6F7
+F6F8
+F6F9
+F6FA
+F6FB
+F6FC
+F6FD
+F6FE
+F7A1
+F7A2
+F7A3
+F7A4
+F7A5
+F7A6
+F7A7
+F7A8
+F7A9
+F7AA
+F7AB
+F7AC
+F7AD
+F7AE
+F7AF
+F7B0
+F7B1
+F7B2
+F7B3
+F7B4
+F7B5
+F7B6
+F7B7
+F7B8
+F7B9
+F7BA
+F7BB
+F7BC
+F7BD
+F7BE
+F7BF
+F7C0
+F7C1
+F7C2
+F7C3
+F7C4
+F7C5
+F7C6
+F7C7
+F7C8
+F7C9
+F7CA
+F7CB
+F7CC
+F7CD
+F7CE
+F7CF
+F7D0
+F7D1
+F7D2
+F7D3
+F7D4
+F7D5
+F7D6
+F7D7
+F7D8
+F7D9
+F7DA
+F7DB
+F7DC
+F7DD
+F7DE
+F7DF
+F7E0
+F7E1
+F7E2
+F7E3
+F7E4
+F7E5
+F7E6
+F7E7
+F7E8
+F7E9
+F7EA
+F7EB
+F7EC
+F7ED
+F7EE
+F7EF
+F7F0
+F7F1
+F7F2
+F7F3
+F7F4
+F7F5
+F7F6
+F7F7
+F7F8
+F7F9
+F7FA
+F7FB
+F7FC
+F7FD
+F7FE
+F8A1
+F8A2
+F8A3
+F8A4
+F8A5
+F8A6
+F8A7
+F8A8
+F8A9
+F8AA
+F8AB
+F8AC
+F8AD
+F8AE
+F8AF
+F8B0
+F8B1
+F8B2
+F8B3
+F8B4
+F8B5
+F8B6
+F8B7
+F8B8
+F8B9
+F8BA
+F8BB
+F8BC
+F8BD
+F8BE
+F8BF
+F8C0
+F8C1
+F8C2
+F8C3
+F8C4
+F8C5
+F8C6
+F8C7
+F8C8
+F8C9
+F8CA
+F8CB
+F8CC
+F8CD
+F8CE
+F8CF
+F8D0
+F8D1
+F8D2
+F8D3
+F8D4
+F8D5
+F8D6
+F8D7
+F8D8
+F8D9
+F8DA
+F8DB
+F8DC
+F8DD
+F8DE
+F8DF
+F8E0
+F8E1
+F8E2
+F8E3
+F8E4
+F8E5
+F8E6
+F8E7
+F8E8
+F8E9
+F8EA
+F8EB
+F8EC
+F8ED
+F8EE
+F8EF
+F8F0
+F8F1
+F8F2
+F8F3
+F8F4
+F8F5
+F8F6
+F8F7
+F8F8
+F8F9
+F8FA
+F8FB
+F8FC
+F8FD
+F8FE
+F9A1
+F9A2
+F9A3
+F9A4
+F9A5
+F9A6
+F9A7
+F9A8
+F9A9
+F9AA
+F9AB
+F9AC
+F9AD
+F9AE
+F9AF
+F9B0
+F9B1
+F9B2
+F9B3
+F9B4
+F9B5
+F9B6
+F9B7
+F9B8
+F9B9
+F9BA
+F9BB
+F9BC
+F9BD
+F9BE
+F9BF
+F9C0
+F9C1
+F9C2
+F9C3
+F9C4
+F9C5
+F9C6
+F9C7
+F9C8
+F9C9
+F9CA
+F9CB
+F9CC
+F9CD
+F9CE
+F9CF
+F9D0
+F9D1
+F9D2
+F9D3
+F9D4
+F9D5
+F9D6
+F9D7
+F9D8
+F9D9
+F9DA
+F9DB
+F9DC
+F9DD
+F9DE
+F9DF
+F9E0
+F9E1
+F9E2
+F9E3
+F9E4
+F9E5
+F9E6
+F9E7
+F9E8
+F9E9
+F9EA
+F9EB
+F9EC
+F9ED
+F9EE
+F9EF
+F9F0
+F9F1
+F9F2
+F9F3
+F9F4
+F9F5
+F9F6
+F9F7
+F9F8
+F9F9
+F9FA
+F9FB
+F9FC
+F9FD
+F9FE
FAA1
FAA2
-FAA2
-FAA3
FAA3
FAA4
-FAA4
-FAA5
FAA5
FAA6
-FAA6
-FAA7
FAA7
FAA8
-FAA8
-FAA9
FAA9
FAAA
-FAAA
-FAAB
FAAB
FAAC
-FAAC
FAAD
-FAAD
-FAAE
FAAE
FAAF
-FAAF
-FAB0
FAB0
FAB1
-FAB1
-FAB2
FAB2
FAB3
-FAB3
FAB4
-FAB4
-FAB5
FAB5
FAB6
-FAB6
-FAB7
FAB7
FAB8
-FAB8
-FAB9
FAB9
FABA
-FABA
FABB
-FABB
-FABC
FABC
FABD
-FABD
-FABE
FABE
FABF
-FABF
-FAC0
FAC0
FAC1
-FAC1
-FAC2
FAC2
FAC3
-FAC3
-FAC4
FAC4
FAC5
-FAC5
-FAC6
FAC6
FAC7
-FAC7
-FAC8
FAC8
FAC9
-FAC9
FACA
-FACA
-FACB
FACB
FACC
-FACC
-FACD
FACD
FACE
-FACE
-FACF
FACF
FAD0
-FAD0
FAD1
-FAD1
-FAD2
FAD2
FAD3
-FAD3
-FAD4
FAD4
FAD5
-FAD5
-FAD6
FAD6
FAD7
-FAD7
FAD8
-FAD8
-FAD9
FAD9
FADA
-FADA
-FADB
FADB
FADC
-FADC
-FADD
FADD
FADE
-FADE
-FADF
FADF
FAE0
-FAE0
-FAE1
FAE1
FAE2
-FAE2
-FAE3
FAE3
FAE4
-FAE4
-FAE5
FAE5
FAE6
-FAE6
FAE7
-FAE7
-FAE8
FAE8
FAE9
-FAE9
-FAEA
FAEA
FAEB
-FAEB
-FAEC
FAEC
FAED
-FAED
FAEE
-FAEE
-FAEF
FAEF
FAF0
-FAF0
-FAF1
FAF1
FAF2
-FAF2
-FAF3
FAF3
FAF4
-FAF4
FAF5
-FAF5
-FAF6
FAF6
FAF7
-FAF7
-FAF8
FAF8
FAF9
-FAF9
-FAFA
FAFA
FAFB
-FAFB
-FAFC
FAFC
-FB40
-FB40
-FB41
-FB41
-FB42
-FB42
-FB43
-FB43
-FB44
-FB44
-FB45
-FB45
-FB46
-FB46
-FB47
-FB47
-FB48
-FB48
-FB49
-FB49
-FB4A
-FB4A
-FB4B
-FB4B
-FB4C
-FB4C
-FB4D
-FB4D
-FB4E
-FB4E
-FB4F
-FB4F
-FB50
-FB50
-FB51
-FB51
-FB52
-FB52
-FB53
-FB53
-FB54
-FB54
-FB55
-FB55
-FB56
-FB56
-FB57
-FB57
-FB58
-FB58
-FB59
-FB59
-FB5A
-FB5A
-FB5B
-FB5B
-FB5C
-FB5C
-FB5D
-FB5D
-FB5E
-FB5E
-FB5F
-FB5F
-FB60
-FB60
-FB61
-FB61
-FB62
-FB62
-FB63
-FB63
-FB64
-FB64
-FB65
-FB65
-FB66
-FB66
-FB67
-FB67
-FB68
-FB68
-FB69
-FB69
-FB6A
-FB6A
-FB6B
-FB6B
-FB6C
-FB6C
-FB6D
-FB6D
-FB6E
-FB6E
-FB6F
-FB6F
-FB70
-FB70
-FB71
-FB71
-FB72
-FB72
-FB73
-FB73
-FB74
-FB74
-FB75
-FB75
-FB76
-FB76
-FB77
-FB77
-FB78
-FB78
-FB79
-FB79
-FB7A
-FB7A
-FB7B
-FB7B
-FB7C
-FB7C
-FB7D
-FB7D
-FB7E
-FB7E
-FB80
-FB80
-FB81
-FB81
-FB82
-FB82
-FB83
-FB83
-FB84
-FB84
-FB85
-FB85
-FB86
-FB86
-FB87
-FB87
-FB88
-FB88
-FB89
-FB89
-FB8A
-FB8A
-FB8B
-FB8B
-FB8C
-FB8C
-FB8D
-FB8D
-FB8E
-FB8E
-FB8F
-FB8F
-FB90
-FB90
-FB91
-FB91
-FB92
-FB92
-FB93
-FB93
-FB94
-FB94
-FB95
-FB95
-FB96
-FB96
-FB97
-FB97
-FB98
-FB98
-FB99
-FB99
-FB9A
-FB9A
-FB9B
-FB9B
-FB9C
-FB9C
-FB9D
-FB9D
-FB9E
-FB9E
-FB9F
-FB9F
-FBA0
-FBA0
+FAFD
+FAFE
FBA1
-FBA1
-FBA2
FBA2
FBA3
-FBA3
FBA4
-FBA4
-FBA5
FBA5
FBA6
-FBA6
-FBA7
FBA7
FBA8
-FBA8
-FBA9
FBA9
FBAA
-FBAA
-FBAB
FBAB
FBAC
-FBAC
-FBAD
FBAD
FBAE
-FBAE
-FBAF
FBAF
FBB0
-FBB0
-FBB1
FBB1
FBB2
-FBB2
FBB3
-FBB3
-FBB4
FBB4
FBB5
-FBB5
-FBB6
FBB6
FBB7
-FBB7
-FBB8
FBB8
FBB9
-FBB9
FBBA
-FBBA
-FBBB
FBBB
FBBC
-FBBC
-FBBD
FBBD
FBBE
-FBBE
-FBBF
FBBF
FBC0
-FBC0
FBC1
-FBC1
-FBC2
FBC2
FBC3
-FBC3
-FBC4
FBC4
FBC5
-FBC5
-FBC6
FBC6
FBC7
-FBC7
-FBC8
FBC8
FBC9
-FBC9
-FBCA
FBCA
FBCB
-FBCB
-FBCC
FBCC
FBCD
-FBCD
-FBCE
FBCE
FBCF
-FBCF
FBD0
-FBD0
-FBD1
FBD1
FBD2
-FBD2
-FBD3
FBD3
FBD4
-FBD4
-FBD5
FBD5
FBD6
-FBD6
FBD7
-FBD7
-FBD8
FBD8
FBD9
-FBD9
-FBDA
FBDA
FBDB
-FBDB
-FBDC
FBDC
FBDD
-FBDD
FBDE
-FBDE
-FBDF
FBDF
FBE0
-FBE0
-FBE1
FBE1
FBE2
-FBE2
-FBE3
FBE3
FBE4
-FBE4
-FBE5
FBE5
FBE6
-FBE6
-FBE7
FBE7
FBE8
-FBE8
-FBE9
FBE9
FBEA
-FBEA
-FBEB
FBEB
FBEC
-FBEC
FBED
-FBED
-FBEE
FBEE
FBEF
-FBEF
-FBF0
FBF0
FBF1
-FBF1
-FBF2
FBF2
FBF3
-FBF3
FBF4
-FBF4
-FBF5
FBF5
FBF6
-FBF6
-FBF7
FBF7
FBF8
-FBF8
-FBF9
FBF9
FBFA
-FBFA
FBFB
-FBFB
-FBFC
FBFC
-FC40
-FC40
-FC41
-FC41
-FC42
-FC42
-FC43
-FC43
-FC44
-FC44
-FC45
-FC45
-FC46
-FC46
-FC47
-FC47
-FC48
-FC48
-FC49
-FC49
-FC4A
-FC4A
-FC4B
-FC4B
+FBFD
+FBFE
+FCA1
+FCA2
+FCA3
+FCA4
+FCA5
+FCA6
+FCA7
+FCA8
+FCA9
+FCAA
+FCAB
+FCAC
+FCAD
+FCAE
+FCAF
+FCB0
+FCB1
+FCB2
+FCB3
+FCB4
+FCB5
+FCB6
+FCB7
+FCB8
+FCB9
+FCBA
+FCBB
+FCBC
+FCBD
+FCBE
+FCBF
+FCC0
+FCC1
+FCC2
+FCC3
+FCC4
+FCC5
+FCC6
+FCC7
+FCC8
+FCC9
+FCCA
+FCCB
+FCCC
+FCCD
+FCCE
+FCCF
+FCD0
+FCD1
+FCD2
+FCD3
+FCD4
+FCD5
+FCD6
+FCD7
+FCD8
+FCD9
+FCDA
+FCDB
+FCDC
+FCDD
+FCDE
+FCDF
+FCE0
+FCE1
+FCE2
+FCE3
+FCE4
+FCE5
+FCE6
+FCE7
+FCE8
+FCE9
+FCEA
+FCEB
+FCEC
+FCED
+FCEE
+FCEF
+FCF0
+FCF1
+FCF2
+FCF3
+FCF4
+FCF5
+FCF6
+FCF7
+FCF8
+FCF9
+FCFA
+FCFB
+FCFC
+FCFD
+FCFE
+FDA1
+FDA2
+FDA3
+FDA4
+FDA5
+FDA6
+FDA7
+FDA8
+FDA9
+FDAA
+FDAB
+FDAC
+FDAD
+FDAE
+FDAF
+FDB0
+FDB1
+FDB2
+FDB3
+FDB4
+FDB5
+FDB6
+FDB7
+FDB8
+FDB9
+FDBA
+FDBB
+FDBC
+FDBD
+FDBE
+FDBF
+FDC0
+FDC1
+FDC2
+FDC3
+FDC4
+FDC5
+FDC6
+FDC7
+FDC8
+FDC9
+FDCA
+FDCB
+FDCC
+FDCD
+FDCE
+FDCF
+FDD0
+FDD1
+FDD2
+FDD3
+FDD4
+FDD5
+FDD6
+FDD7
+FDD8
+FDD9
+FDDA
+FDDB
+FDDC
+FDDD
+FDDE
+FDDF
+FDE0
+FDE1
+FDE2
+FDE3
+FDE4
+FDE5
+FDE6
+FDE7
+FDE8
+FDE9
+FDEA
+FDEB
+FDEC
+FDED
+FDEE
+FDEF
+FDF0
+FDF1
+FDF2
+FDF3
+FDF4
+FDF5
+FDF6
+FDF7
+FDF8
+FDF9
+FDFA
+FDFB
+FDFC
+FDFD
+FDFE
+FEA1
+FEA2
+FEA3
+FEA4
+FEA5
+FEA6
+FEA7
+FEA8
+FEA9
+FEAA
+FEAB
+FEAC
+FEAD
+FEAE
+FEAF
+FEB0
+FEB1
+FEB2
+FEB3
+FEB4
+FEB5
+FEB6
+FEB7
+FEB8
+FEB9
+FEBA
+FEBB
+FEBC
+FEBD
+FEBE
+FEBF
+FEC0
+FEC1
+FEC2
+FEC3
+FEC4
+FEC5
+FEC6
+FEC7
+FEC8
+FEC9
+FECA
+FECB
+FECC
+FECD
+FECE
+FECF
+FED0
+FED1
+FED2
+FED3
+FED4
+FED5
+FED6
+FED7
+FED8
+FED9
+FEDA
+FEDB
+FEDC
+FEDD
+FEDE
+FEDF
+FEE0
+FEE1
+FEE2
+FEE3
+FEE4
+FEE5
+FEE6
+FEE7
+FEE8
+FEE9
+FEEA
+FEEB
+FEEC
+FEED
+FEEE
+FEEF
+FEF0
+FEF1
+FEF2
+FEF3
+FEF4
+FEF5
+FEF6
+FEF7
+FEF8
+FEF9
+FEFA
+FEFB
+FEFC
+FEFD
+FEFE
+8FF5A1
+8FF5A2
+8FF5A3
+8FF5A4
+8FF5A5
+8FF5A6
+8FF5A7
+8FF5A8
+8FF5A9
+8FF5AA
+8FF5AB
+8FF5AC
+8FF5AD
+8FF5AE
+8FF5AF
+8FF5B0
+8FF5B1
+8FF5B2
+8FF5B3
+8FF5B4
+8FF5B5
+8FF5B6
+8FF5B7
+8FF5B8
+8FF5B9
+8FF5BA
+8FF5BB
+8FF5BC
+8FF5BD
+8FF5BE
+8FF5BF
+8FF5C0
+8FF5C1
+8FF5C2
+8FF5C3
+8FF5C4
+8FF5C5
+8FF5C6
+8FF5C7
+8FF5C8
+8FF5C9
+8FF5CA
+8FF5CB
+8FF5CC
+8FF5CD
+8FF5CE
+8FF5CF
+8FF5D0
+8FF5D1
+8FF5D2
+8FF5D3
+8FF5D4
+8FF5D5
+8FF5D6
+8FF5D7
+8FF5D8
+8FF5D9
+8FF5DA
+8FF5DB
+8FF5DC
+8FF5DD
+8FF5DE
+8FF5DF
+8FF5E0
+8FF5E1
+8FF5E2
+8FF5E3
+8FF5E4
+8FF5E5
+8FF5E6
+8FF5E7
+8FF5E8
+8FF5E9
+8FF5EA
+8FF5EB
+8FF5EC
+8FF5ED
+8FF5EE
+8FF5EF
+8FF5F0
+8FF5F1
+8FF5F2
+8FF5F3
+8FF5F4
+8FF5F5
+8FF5F6
+8FF5F7
+8FF5F8
+8FF5F9
+8FF5FA
+8FF5FB
+8FF5FC
+8FF5FD
+8FF5FE
+8FF6A1
+8FF6A2
+8FF6A3
+8FF6A4
+8FF6A5
+8FF6A6
+8FF6A7
+8FF6A8
+8FF6A9
+8FF6AA
+8FF6AB
+8FF6AC
+8FF6AD
+8FF6AE
+8FF6AF
+8FF6B0
+8FF6B1
+8FF6B2
+8FF6B3
+8FF6B4
+8FF6B5
+8FF6B6
+8FF6B7
+8FF6B8
+8FF6B9
+8FF6BA
+8FF6BB
+8FF6BC
+8FF6BD
+8FF6BE
+8FF6BF
+8FF6C0
+8FF6C1
+8FF6C2
+8FF6C3
+8FF6C4
+8FF6C5
+8FF6C6
+8FF6C7
+8FF6C8
+8FF6C9
+8FF6CA
+8FF6CB
+8FF6CC
+8FF6CD
+8FF6CE
+8FF6CF
+8FF6D0
+8FF6D1
+8FF6D2
+8FF6D3
+8FF6D4
+8FF6D5
+8FF6D6
+8FF6D7
+8FF6D8
+8FF6D9
+8FF6DA
+8FF6DB
+8FF6DC
+8FF6DD
+8FF6DE
+8FF6DF
+8FF6E0
+8FF6E1
+8FF6E2
+8FF6E3
+8FF6E4
+8FF6E5
+8FF6E6
+8FF6E7
+8FF6E8
+8FF6E9
+8FF6EA
+8FF6EB
+8FF6EC
+8FF6ED
+8FF6EE
+8FF6EF
+8FF6F0
+8FF6F1
+8FF6F2
+8FF6F3
+8FF6F4
+8FF6F5
+8FF6F6
+8FF6F7
+8FF6F8
+8FF6F9
+8FF6FA
+8FF6FB
+8FF6FC
+8FF6FD
+8FF6FE
+8FF7A1
+8FF7A2
+8FF7A3
+8FF7A4
+8FF7A5
+8FF7A6
+8FF7A7
+8FF7A8
+8FF7A9
+8FF7AA
+8FF7AB
+8FF7AC
+8FF7AD
+8FF7AE
+8FF7AF
+8FF7B0
+8FF7B1
+8FF7B2
+8FF7B3
+8FF7B4
+8FF7B5
+8FF7B6
+8FF7B7
+8FF7B8
+8FF7B9
+8FF7BA
+8FF7BB
+8FF7BC
+8FF7BD
+8FF7BE
+8FF7BF
+8FF7C0
+8FF7C1
+8FF7C2
+8FF7C3
+8FF7C4
+8FF7C5
+8FF7C6
+8FF7C7
+8FF7C8
+8FF7C9
+8FF7CA
+8FF7CB
+8FF7CC
+8FF7CD
+8FF7CE
+8FF7CF
+8FF7D0
+8FF7D1
+8FF7D2
+8FF7D3
+8FF7D4
+8FF7D5
+8FF7D6
+8FF7D7
+8FF7D8
+8FF7D9
+8FF7DA
+8FF7DB
+8FF7DC
+8FF7DD
+8FF7DE
+8FF7DF
+8FF7E0
+8FF7E1
+8FF7E2
+8FF7E3
+8FF7E4
+8FF7E5
+8FF7E6
+8FF7E7
+8FF7E8
+8FF7E9
+8FF7EA
+8FF7EB
+8FF7EC
+8FF7ED
+8FF7EE
+8FF7EF
+8FF7F0
+8FF7F1
+8FF7F2
+8FF7F3
+8FF7F4
+8FF7F5
+8FF7F6
+8FF7F7
+8FF7F8
+8FF7F9
+8FF7FA
+8FF7FB
+8FF7FC
+8FF7FD
+8FF7FE
+8FF8A1
+8FF8A2
+8FF8A3
+8FF8A4
+8FF8A5
+8FF8A6
+8FF8A7
+8FF8A8
+8FF8A9
+8FF8AA
+8FF8AB
+8FF8AC
+8FF8AD
+8FF8AE
+8FF8AF
+8FF8B0
+8FF8B1
+8FF8B2
+8FF8B3
+8FF8B4
+8FF8B5
+8FF8B6
+8FF8B7
+8FF8B8
+8FF8B9
+8FF8BA
+8FF8BB
+8FF8BC
+8FF8BD
+8FF8BE
+8FF8BF
+8FF8C0
+8FF8C1
+8FF8C2
+8FF8C3
+8FF8C4
+8FF8C5
+8FF8C6
+8FF8C7
+8FF8C8
+8FF8C9
+8FF8CA
+8FF8CB
+8FF8CC
+8FF8CD
+8FF8CE
+8FF8CF
+8FF8D0
+8FF8D1
+8FF8D2
+8FF8D3
+8FF8D4
+8FF8D5
+8FF8D6
+8FF8D7
+8FF8D8
+8FF8D9
+8FF8DA
+8FF8DB
+8FF8DC
+8FF8DD
+8FF8DE
+8FF8DF
+8FF8E0
+8FF8E1
+8FF8E2
+8FF8E3
+8FF8E4
+8FF8E5
+8FF8E6
+8FF8E7
+8FF8E8
+8FF8E9
+8FF8EA
+8FF8EB
+8FF8EC
+8FF8ED
+8FF8EE
+8FF8EF
+8FF8F0
+8FF8F1
+8FF8F2
+8FF8F3
+8FF8F4
+8FF8F5
+8FF8F6
+8FF8F7
+8FF8F8
+8FF8F9
+8FF8FA
+8FF8FB
+8FF8FC
+8FF8FD
+8FF8FE
+8FF9A1
+8FF9A2
+8FF9A3
+8FF9A4
+8FF9A5
+8FF9A6
+8FF9A7
+8FF9A8
+8FF9A9
+8FF9AA
+8FF9AB
+8FF9AC
+8FF9AD
+8FF9AE
+8FF9AF
+8FF9B0
+8FF9B1
+8FF9B2
+8FF9B3
+8FF9B4
+8FF9B5
+8FF9B6
+8FF9B7
+8FF9B8
+8FF9B9
+8FF9BA
+8FF9BB
+8FF9BC
+8FF9BD
+8FF9BE
+8FF9BF
+8FF9C0
+8FF9C1
+8FF9C2
+8FF9C3
+8FF9C4
+8FF9C5
+8FF9C6
+8FF9C7
+8FF9C8
+8FF9C9
+8FF9CA
+8FF9CB
+8FF9CC
+8FF9CD
+8FF9CE
+8FF9CF
+8FF9D0
+8FF9D1
+8FF9D2
+8FF9D3
+8FF9D4
+8FF9D5
+8FF9D6
+8FF9D7
+8FF9D8
+8FF9D9
+8FF9DA
+8FF9DB
+8FF9DC
+8FF9DD
+8FF9DE
+8FF9DF
+8FF9E0
+8FF9E1
+8FF9E2
+8FF9E3
+8FF9E4
+8FF9E5
+8FF9E6
+8FF9E7
+8FF9E8
+8FF9E9
+8FF9EA
+8FF9EB
+8FF9EC
+8FF9ED
+8FF9EE
+8FF9EF
+8FF9F0
+8FF9F1
+8FF9F2
+8FF9F3
+8FF9F4
+8FF9F5
+8FF9F6
+8FF9F7
+8FF9F8
+8FF9F9
+8FF9FA
+8FF9FB
+8FF9FC
+8FF9FD
+8FF9FE
+8FFAA1
+8FFAA2
+8FFAA3
+8FFAA4
+8FFAA5
+8FFAA6
+8FFAA7
+8FFAA8
+8FFAA9
+8FFAAA
+8FFAAB
+8FFAAC
+8FFAAD
+8FFAAE
+8FFAAF
+8FFAB0
+8FFAB1
+8FFAB2
+8FFAB3
+8FFAB4
+8FFAB5
+8FFAB6
+8FFAB7
+8FFAB8
+8FFAB9
+8FFABA
+8FFABB
+8FFABC
+8FFABD
+8FFABE
+8FFABF
+8FFAC0
+8FFAC1
+8FFAC2
+8FFAC3
+8FFAC4
+8FFAC5
+8FFAC6
+8FFAC7
+8FFAC8
+8FFAC9
+8FFACA
+8FFACB
+8FFACC
+8FFACD
+8FFACE
+8FFACF
+8FFAD0
+8FFAD1
+8FFAD2
+8FFAD3
+8FFAD4
+8FFAD5
+8FFAD6
+8FFAD7
+8FFAD8
+8FFAD9
+8FFADA
+8FFADB
+8FFADC
+8FFADD
+8FFADE
+8FFADF
+8FFAE0
+8FFAE1
+8FFAE2
+8FFAE3
+8FFAE4
+8FFAE5
+8FFAE6
+8FFAE7
+8FFAE8
+8FFAE9
+8FFAEA
+8FFAEB
+8FFAEC
+8FFAED
+8FFAEE
+8FFAEF
+8FFAF0
+8FFAF1
+8FFAF2
+8FFAF3
+8FFAF4
+8FFAF5
+8FFAF6
+8FFAF7
+8FFAF8
+8FFAF9
+8FFAFA
+8FFAFB
+8FFAFC
+8FFAFD
+8FFAFE
+8FFBA1
+8FFBA2
+8FFBA3
+8FFBA4
+8FFBA5
+8FFBA6
+8FFBA7
+8FFBA8
+8FFBA9
+8FFBAA
+8FFBAB
+8FFBAC
+8FFBAD
+8FFBAE
+8FFBAF
+8FFBB0
+8FFBB1
+8FFBB2
+8FFBB3
+8FFBB4
+8FFBB5
+8FFBB6
+8FFBB7
+8FFBB8
+8FFBB9
+8FFBBA
+8FFBBB
+8FFBBC
+8FFBBD
+8FFBBE
+8FFBBF
+8FFBC0
+8FFBC1
+8FFBC2
+8FFBC3
+8FFBC4
+8FFBC5
+8FFBC6
+8FFBC7
+8FFBC8
+8FFBC9
+8FFBCA
+8FFBCB
+8FFBCC
+8FFBCD
+8FFBCE
+8FFBCF
+8FFBD0
+8FFBD1
+8FFBD2
+8FFBD3
+8FFBD4
+8FFBD5
+8FFBD6
+8FFBD7
+8FFBD8
+8FFBD9
+8FFBDA
+8FFBDB
+8FFBDC
+8FFBDD
+8FFBDE
+8FFBDF
+8FFBE0
+8FFBE1
+8FFBE2
+8FFBE3
+8FFBE4
+8FFBE5
+8FFBE6
+8FFBE7
+8FFBE8
+8FFBE9
+8FFBEA
+8FFBEB
+8FFBEC
+8FFBED
+8FFBEE
+8FFBEF
+8FFBF0
+8FFBF1
+8FFBF2
+8FFBF3
+8FFBF4
+8FFBF5
+8FFBF6
+8FFBF7
+8FFBF8
+8FFBF9
+8FFBFA
+8FFBFB
+8FFBFC
+8FFBFD
+8FFBFE
+8FFCA1
+8FFCA2
+8FFCA3
+8FFCA4
+8FFCA5
+8FFCA6
+8FFCA7
+8FFCA8
+8FFCA9
+8FFCAA
+8FFCAB
+8FFCAC
+8FFCAD
+8FFCAE
+8FFCAF
+8FFCB0
+8FFCB1
+8FFCB2
+8FFCB3
+8FFCB4
+8FFCB5
+8FFCB6
+8FFCB7
+8FFCB8
+8FFCB9
+8FFCBA
+8FFCBB
+8FFCBC
+8FFCBD
+8FFCBE
+8FFCBF
+8FFCC0
+8FFCC1
+8FFCC2
+8FFCC3
+8FFCC4
+8FFCC5
+8FFCC6
+8FFCC7
+8FFCC8
+8FFCC9
+8FFCCA
+8FFCCB
+8FFCCC
+8FFCCD
+8FFCCE
+8FFCCF
+8FFCD0
+8FFCD1
+8FFCD2
+8FFCD3
+8FFCD4
+8FFCD5
+8FFCD6
+8FFCD7
+8FFCD8
+8FFCD9
+8FFCDA
+8FFCDB
+8FFCDC
+8FFCDD
+8FFCDE
+8FFCDF
+8FFCE0
+8FFCE1
+8FFCE2
+8FFCE3
+8FFCE4
+8FFCE5
+8FFCE6
+8FFCE7
+8FFCE8
+8FFCE9
+8FFCEA
+8FFCEB
+8FFCEC
+8FFCED
+8FFCEE
+8FFCEF
+8FFCF0
+8FFCF1
+8FFCF2
+8FFCF3
+8FFCF4
+8FFCF5
+8FFCF6
+8FFCF7
+8FFCF8
+8FFCF9
+8FFCFA
+8FFCFB
+8FFCFC
+8FFCFD
+8FFCFE
+8FFDA1
+8FFDA2
+8FFDA3
+8FFDA4
+8FFDA5
+8FFDA6
+8FFDA7
+8FFDA8
+8FFDA9
+8FFDAA
+8FFDAB
+8FFDAC
+8FFDAD
+8FFDAE
+8FFDAF
+8FFDB0
+8FFDB1
+8FFDB2
+8FFDB3
+8FFDB4
+8FFDB5
+8FFDB6
+8FFDB7
+8FFDB8
+8FFDB9
+8FFDBA
+8FFDBB
+8FFDBC
+8FFDBD
+8FFDBE
+8FFDBF
+8FFDC0
+8FFDC1
+8FFDC2
+8FFDC3
+8FFDC4
+8FFDC5
+8FFDC6
+8FFDC7
+8FFDC8
+8FFDC9
+8FFDCA
+8FFDCB
+8FFDCC
+8FFDCD
+8FFDCE
+8FFDCF
+8FFDD0
+8FFDD1
+8FFDD2
+8FFDD3
+8FFDD4
+8FFDD5
+8FFDD6
+8FFDD7
+8FFDD8
+8FFDD9
+8FFDDA
+8FFDDB
+8FFDDC
+8FFDDD
+8FFDDE
+8FFDDF
+8FFDE0
+8FFDE1
+8FFDE2
+8FFDE3
+8FFDE4
+8FFDE5
+8FFDE6
+8FFDE7
+8FFDE8
+8FFDE9
+8FFDEA
+8FFDEB
+8FFDEC
+8FFDED
+8FFDEE
+8FFDEF
+8FFDF0
+8FFDF1
+8FFDF2
+8FFDF3
+8FFDF4
+8FFDF5
+8FFDF6
+8FFDF7
+8FFDF8
+8FFDF9
+8FFDFA
+8FFDFB
+8FFDFC
+8FFDFD
+8FFDFE
+8FFEA1
+8FFEA2
+8FFEA3
+8FFEA4
+8FFEA5
+8FFEA6
+8FFEA7
+8FFEA8
+8FFEA9
+8FFEAA
+8FFEAB
+8FFEAC
+8FFEAD
+8FFEAE
+8FFEAF
+8FFEB0
+8FFEB1
+8FFEB2
+8FFEB3
+8FFEB4
+8FFEB5
+8FFEB6
+8FFEB7
+8FFEB8
+8FFEB9
+8FFEBA
+8FFEBB
+8FFEBC
+8FFEBD
+8FFEBE
+8FFEBF
+8FFEC0
+8FFEC1
+8FFEC2
+8FFEC3
+8FFEC4
+8FFEC5
+8FFEC6
+8FFEC7
+8FFEC8
+8FFEC9
+8FFECA
+8FFECB
+8FFECC
+8FFECD
+8FFECE
+8FFECF
+8FFED0
+8FFED1
+8FFED2
+8FFED3
+8FFED4
+8FFED5
+8FFED6
+8FFED7
+8FFED8
+8FFED9
+8FFEDA
+8FFEDB
+8FFEDC
+8FFEDD
+8FFEDE
+8FFEDF
+8FFEE0
+8FFEE1
+8FFEE2
+8FFEE3
+8FFEE4
+8FFEE5
+8FFEE6
+8FFEE7
+8FFEE8
+8FFEE9
+8FFEEA
+8FFEEB
+8FFEEC
+8FFEED
+8FFEEE
+8FFEEF
+8FFEF0
+8FFEF1
+8FFEF2
+8FFEF3
+8FFEF4
+8FFEF5
+8FFEF6
+8FFEF7
+8FFEF8
+8FFEF9
+8FFEFA
+8FFEFB
+8FFEFC
+8FFEFD
+8FFEFE
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;
+DROP TABLE t4;
RESET MASTER;
CREATE TABLE t1(f1 blob);
PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)';
SET @var1= x'8300';
EXECUTE stmt1 USING @var1;
-SHOW BINLOG EVENTS FROM 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=95,COLLATION_CONNECTION=95,COLLATION_DATABASE=95,COLLATION_SERVER=8
-master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(f1 blob)
-master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=95,COLLATION_CONNECTION=95,COLLATION_DATABASE=95,COLLATION_SERVER=8
-master-bin.000001 # User var 1 # @`var1`=_binary 0x8300 COLLATE binary
-master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES(@'var1')
+SHOW BINLOG EVENTS FROM 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 185 use `test`; CREATE TABLE t1(f1 blob)
+master-bin.000001 185 User var 1 224 @`var1`=_binary 0x8300 COLLATE binary
+master-bin.000001 224 Query 1 317 use `test`; INSERT INTO t1 VALUES(@'var1')
SELECT HEX(f1) FROM t1;
HEX(f1)
8300
@@ -8602,28 +11339,6 @@ cp932_japanese_ci 6109
cp932_japanese_ci 61
cp932_japanese_ci 6120
drop table t1;
-create table t1 engine=innodb select repeat('a',50) as c1;
-alter table t1 add index(c1(5));
-insert into t1 values ('abcdefg'),('abcde100'),('abcde110'),('abcde111');
-select collation(c1) from t1 limit 1;
-collation(c1)
-cp932_japanese_ci
-select c1 from t1 where c1 like 'abcdef%' order by c1;
-c1
-abcdefg
-select c1 from t1 where c1 like 'abcde1%' order by c1;
-c1
-abcde100
-abcde110
-abcde111
-select c1 from t1 where c1 like 'abcde11%' order by c1;
-c1
-abcde110
-abcde111
-select c1 from t1 where c1 like 'abcde111%' order by c1;
-c1
-abcde111
-drop table t1;
SET collation_connection='cp932_bin';
create table t1 select repeat('a',4000) a;
delete from t1;
@@ -8634,25 +11349,3 @@ cp932_bin 6109
cp932_bin 61
cp932_bin 6120
drop table t1;
-create table t1 engine=innodb select repeat('a',50) as c1;
-alter table t1 add index(c1(5));
-insert into t1 values ('abcdefg'),('abcde100'),('abcde110'),('abcde111');
-select collation(c1) from t1 limit 1;
-collation(c1)
-cp932_bin
-select c1 from t1 where c1 like 'abcdef%' order by c1;
-c1
-abcdefg
-select c1 from t1 where c1 like 'abcde1%' order by c1;
-c1
-abcde100
-abcde110
-abcde111
-select c1 from t1 where c1 like 'abcde11%' order by c1;
-c1
-abcde110
-abcde111
-select c1 from t1 where c1 like 'abcde111%' order by c1;
-c1
-abcde111
-drop table t1;
diff --git a/mysql-test/r/ctype_eucjpms.result b/mysql-test/r/ctype_eucjpms.result
new file mode 100755
index 00000000000..cdb28cd0fdd
--- /dev/null
+++ b/mysql-test/r/ctype_eucjpms.result
@@ -0,0 +1,9821 @@
+drop table if exists t1;
+drop table if exists t2;
+drop table if exists t3;
+drop table if exists t4;
+set names eucjpms;
+set character_set_database = eucjpms;
+CREATE TABLE t1(c1 CHAR(1)) DEFAULT CHARACTER SET = eucjpms;
+INSERT INTO t1 VALUES
+(0x5C),(0x7E),(0xA1B1),(0xA1BD),(0xA1C0),(0xA1C1),(0xA1C2),(0xA1DD),(0xA1F1),(0xA1F2),(0xA1EF),(0xA2CC),(0x8FA2B7),(0x8FA2C3);
+INSERT INTO t1 VALUES
+(0xADA1),(0xADA2),(0xADA3),(0xADA4),(0xADA5),(0xADA6),(0xADA7),(0xADA8),
+(0xADA9),(0xADAA),(0xADAB),(0xADAC),(0xADAD),(0xADAE),(0xADAF),(0xADB0),
+(0xADB1),(0xADB2),(0xADB3),(0xADB4),(0xADB5),(0xADB6),(0xADB7),(0xADB8),
+(0xADB9),(0xADBA),(0xADBB),(0xADBC),(0xADBD),(0xADBE),(0xADC0),(0xADC1),
+(0xADC2),(0xADC3),(0xADC4),(0xADC5),(0xADC6),(0xADC7),(0xADC8),(0xADC9),
+(0xADCA),(0xADCB),(0xADCC),(0xADCD),(0xADCE),(0xADCF),(0xADD0),(0xADD1),
+(0xADD2),(0xADD3),(0xADD4),(0xADD5),(0xADD6),(0xADDF),(0xADE0),(0xADE1),
+(0xADE2),(0xADE3),(0xADE4),(0xADE5),(0xADE6),(0xADE7),(0xADE8),(0xADE9),
+(0xADEA),(0xADEB),(0xADEC),(0xADED),(0xADEE),(0xADEF),(0xADF0),(0xADF1),
+(0xADF2),(0xADF3),(0xADF4),(0xADF5),(0xADF6),(0xADF7),(0xADF8),(0xADF9),
+(0xADFA),(0xADFB),(0xADFC);
+INSERT INTO t1 VALUES
+(0x8FF3F3),(0x8FF3F4),(0x8FF3F5),(0x8FF3F6),(0x8FF3F7),(0x8FF3F8),(0x8FF3F9),(0x8FF3FA),
+(0x8FF3FB),(0x8FF3FC),(0x8FF3FD),(0x8FF3FE),(0x8FF4A1),(0x8FF4A2),(0x8FF4A3),(0x8FF4A4),
+(0x8FF4A5),(0x8FF4A6),(0x8FF4A7),(0x8FF4A8),(0xA2CC),(0x8FA2C3),(0x8FF4A9),(0x8FF4AA),
+(0x8FF4AB),(0x8FF4AC),(0x8FF4AD),(0xA2E8),(0x8FD4E3),(0x8FDCDF),(0x8FE4E9),(0x8FE3F8),
+(0x8FD9A1),(0x8FB1BB),(0x8FF4AE),(0x8FC2AD),(0x8FC3FC),(0x8FE4D0),(0x8FC2BF),(0x8FBCF4),
+(0x8FB0A9),(0x8FB0C8),(0x8FF4AF),(0x8FB0D2),(0x8FB0D4),(0x8FB0E3),(0x8FB0EE),(0x8FB1A7),
+(0x8FB1A3),(0x8FB1AC),(0x8FB1A9),(0x8FB1BE),(0x8FB1DF),(0x8FB1D8),(0x8FB1C8),(0x8FB1D7),
+(0x8FB1E3),(0x8FB1F4),(0x8FB1E1),(0x8FB2A3),(0x8FF4B0),(0x8FB2BB),(0x8FB2E6),(0x8FB2ED),
+(0x8FB2F5),(0x8FB2FC),(0x8FF4B1),(0x8FB3B5),(0x8FB3D8),(0x8FB3DB),(0x8FB3E5),(0x8FB3EE),
+(0x8FB3FB),(0x8FF4B2),(0x8FF4B3),(0x8FB4C0),(0x8FB4C7),(0x8FB4D0),(0x8FB4DE),(0x8FF4B4),
+(0x8FB5AA),(0x8FF4B5),(0x8FB5AF),(0x8FB5C4),(0x8FB5E8),(0x8FF4B6),(0x8FB7C2),(0x8FB7E4),
+(0x8FB7E8),(0x8FB7E7),(0x8FF4B7),(0x8FF4B8),(0x8FF4B9),(0x8FB8CE),(0x8FB8E1),(0x8FB8F5),
+(0x8FB8F7),(0x8FB8F8),(0x8FB8FC),(0x8FB9AF),(0x8FB9B7),(0x8FBABE),(0x8FBADB),(0x8FCDAA),
+(0x8FBAE1),(0x8FF4BA),(0x8FBAEB),(0x8FBBB3),(0x8FBBB8),(0x8FF4BB),(0x8FBBCA),(0x8FF4BC),
+(0x8FF4BD),(0x8FBBD0),(0x8FBBDE),(0x8FBBF4),(0x8FBBF5),(0x8FBBF9),(0x8FBCE4),(0x8FBCED),
+(0x8FBCFE),(0x8FF4BE),(0x8FBDC2),(0x8FBDE7),(0x8FF4BF),(0x8FBDF0),(0x8FBEB0),(0x8FBEAC),
+(0x8FF4C0),(0x8FBEB3),(0x8FBEBD),(0x8FBECD),(0x8FBEC9),(0x8FBEE4),(0x8FBFA8),(0x8FBFC9),
+(0x8FC0C4),(0x8FC0E4),(0x8FC0F4),(0x8FC1A6),(0x8FF4C1),(0x8FC1F5),(0x8FC1FC),(0x8FF4C2),
+(0x8FC1F8),(0x8FC2AB),(0x8FC2A1),(0x8FC2A5),(0x8FF4C3),(0x8FC2B8),(0x8FC2BA),(0x8FF4C4),
+(0x8FC2C4),(0x8FC2D2),(0x8FC2D7),(0x8FC2DB),(0x8FC2DE),(0x8FC2ED),(0x8FC2F0),(0x8FF4C5),
+(0x8FC3A1),(0x8FC3B5),(0x8FC3C9),(0x8FC3B9),(0x8FF4C6),(0x8FC3D8),(0x8FC3FE),(0x8FF4C7),
+(0x8FC4CC),(0x8FF4C8),(0x8FC4D9),(0x8FC4EA),(0x8FC4FD),(0x8FF4C9),(0x8FC5A7),(0x8FC5B5),
+(0x8FC5B6),(0x8FF4CA),(0x8FC5D5),(0x8FC6B8),(0x8FC6D7),(0x8FC6E0),(0x8FC6EA),(0x8FC6E3),
+(0x8FC7A1),(0x8FC7AB),(0x8FC7C7),(0x8FC7C3),(0x8FC7CB),(0x8FC7CF),(0x8FC7D9),(0x8FF4CB),
+(0x8FF4CC),(0x8FC7E6),(0x8FC7EE),(0x8FC7FC),(0x8FC7EB),(0x8FC7F0),(0x8FC8B1),(0x8FC8E5),
+(0x8FC8F8),(0x8FC9A6),(0x8FC9AB),(0x8FC9AD),(0x8FF4CD),(0x8FC9CA),(0x8FC9D3),(0x8FC9E9),
+(0x8FC9E3),(0x8FC9FC),(0x8FC9F4),(0x8FC9F5),(0x8FF4CE),(0x8FCAB3),(0x8FCABD),(0x8FCAEF),
+(0x8FCAF1),(0x8FCBAE),(0x8FF4CF),(0x8FCBCA),(0x8FCBE6),(0x8FCBEA),(0x8FCBF0),(0x8FCBF4),
+(0x8FCBEE),(0x8FCCA5),(0x8FCBF9),(0x8FCCAB),(0x8FCCAE),(0x8FCCAD),(0x8FCCB2),(0x8FCCC2),
+(0x8FCCD0),(0x8FCCD9),(0x8FF4D0),(0x8FCDBB),(0x8FF4D1),(0x8FCEBB),(0x8FF4D2),(0x8FCEBA),
+(0x8FCEC3),(0x8FF4D3),(0x8FCEF2),(0x8FB3DD),(0x8FCFD5),(0x8FCFE2),(0x8FCFE9),(0x8FCFED),
+(0x8FF4D4),(0x8FF4D5),(0x8FF4D6),(0x8FF4D7),(0x8FD0E5),(0x8FF4D8),(0x8FD0E9),(0x8FD1E8),
+(0x8FF4D9),(0x8FF4DA),(0x8FD1EC),(0x8FD2BB),(0x8FF4DB),(0x8FD3E1),(0x8FD3E8),(0x8FD4A7),
+(0x8FF4DC),(0x8FF4DD),(0x8FD4D4),(0x8FD4F2),(0x8FD5AE),(0x8FF4DE),(0x8FD7DE),(0x8FF4DF),
+(0x8FD8A2),(0x8FD8B7),(0x8FD8C1),(0x8FD8D1),(0x8FD8F4),(0x8FD9C6),(0x8FD9C8),(0x8FD9D1),
+(0x8FF4E0),(0x8FF4E1),(0x8FF4E2),(0x8FF4E3),(0x8FF4E4),(0x8FDCD3),(0x8FDDC8),(0x8FDDD4),
+(0x8FDDEA),(0x8FDDFA),(0x8FDEA4),(0x8FDEB0),(0x8FF4E5),(0x8FDEB5),(0x8FDECB),(0x8FF4E6),
+(0x8FDFB9),(0x8FF4E7),(0x8FDFC3),(0x8FF4E8),(0x8FF4E9),(0x8FE0D9),(0x8FF4EA),(0x8FF4EB),
+(0x8FE1E2),(0x8FF4EC),(0x8FF4ED),(0x8FF4EE),(0x8FE2C7),(0x8FE3A8),(0x8FE3A6),(0x8FE3A9),
+(0x8FE3AF),(0x8FE3B0),(0x8FE3AA),(0x8FE3AB),(0x8FE3BC),(0x8FE3C1),(0x8FE3BF),(0x8FE3D5),
+(0x8FE3D8),(0x8FE3D6),(0x8FE3DF),(0x8FE3E3),(0x8FE3E1),(0x8FE3D4),(0x8FE3E9),(0x8FE4A6),
+(0x8FE3F1),(0x8FE3F2),(0x8FE4CB),(0x8FE4C1),(0x8FE4C3),(0x8FE4BE),(0x8FF4EF),(0x8FE4C0),
+(0x8FE4C7),(0x8FE4BF),(0x8FE4E0),(0x8FE4DE),(0x8FE4D1),(0x8FF4F0),(0x8FE4DC),(0x8FE4D2),
+(0x8FE4DB),(0x8FE4D4),(0x8FE4FA),(0x8FE4EF),(0x8FE5B3),(0x8FE5BF),(0x8FE5C9),(0x8FE5D0),
+(0x8FE5E2),(0x8FE5EA),(0x8FE5EB),(0x8FF4F1),(0x8FF4F2),(0x8FF4F3),(0x8FE6E8),(0x8FE6EF),
+(0x8FE7AC),(0x8FF4F4),(0x8FE7AE),(0x8FF4F5),(0x8FE7B1),(0x8FF4F6),(0x8FE7B2),(0x8FE8B1),
+(0x8FE8B6),(0x8FF4F7),(0x8FF4F8),(0x8FE8DD),(0x8FF4F9),(0x8FF4FA),(0x8FE9D1),(0x8FF4FB),
+(0x8FE9ED),(0x8FEACD),(0x8FF4FC),(0x8FEADB),(0x8FEAE6),(0x8FEAEA),(0x8FEBA5),(0x8FEBFB),
+(0x8FEBFA),(0x8FF4FD),(0x8FECD6),(0x8FF4FE);
+INSERT INTO t1 VALUES
+(0xF5A1),(0xF5A2),(0xF5A3),(0xF5A4),(0xF5A5),(0xF5A6),(0xF5A7),(0xF5A8),
+(0xF5A9),(0xF5AA),(0xF5AB),(0xF5AC),(0xF5AD),(0xF5AE),(0xF5AF),(0xF5B0),
+(0xF5B1),(0xF5B2),(0xF5B3),(0xF5B4),(0xF5B5),(0xF5B6),(0xF5B7),(0xF5B8),
+(0xF5B9),(0xF5BA),(0xF5BB),(0xF5BC),(0xF5BD),(0xF5BE),(0xF5BF),(0xF5C0),
+(0xF5C1),(0xF5C2),(0xF5C3),(0xF5C4),(0xF5C5),(0xF5C6),(0xF5C7),(0xF5C8),
+(0xF5C9),(0xF5CA),(0xF5CB),(0xF5CC),(0xF5CD),(0xF5CE),(0xF5CF),(0xF5D0),
+(0xF5D1),(0xF5D2),(0xF5D3),(0xF5D4),(0xF5D5),(0xF5D6),(0xF5D7),(0xF5D8),
+(0xF5D9),(0xF5DA),(0xF5DB),(0xF5DC),(0xF5DD),(0xF5DE),(0xF5DF),(0xF5E0),
+(0xF5E1),(0xF5E2),(0xF5E3),(0xF5E4),(0xF5E5),(0xF5E6),(0xF5E7),(0xF5E8),
+(0xF5E9),(0xF5EA),(0xF5EB),(0xF5EC),(0xF5ED),(0xF5EE),(0xF5EF),(0xF5F0),
+(0xF5F1),(0xF5F2),(0xF5F3),(0xF5F4),(0xF5F5),(0xF5F6),(0xF5F7),(0xF5F8),
+(0xF5F9),(0xF5FA),(0xF5FB),(0xF5FC),(0xF5FD),(0xF5FE),
+(0xF6A1),(0xF6A2),(0xF6A3),(0xF6A4),(0xF6A5),(0xF6A6),(0xF6A7),(0xF6A8),
+(0xF6A9),(0xF6AA),(0xF6AB),(0xF6AC),(0xF6AD),(0xF6AE),(0xF6AF),(0xF6B0),
+(0xF6B1),(0xF6B2),(0xF6B3),(0xF6B4),(0xF6B5),(0xF6B6),(0xF6B7),(0xF6B8),
+(0xF6B9),(0xF6BA),(0xF6BB),(0xF6BC),(0xF6BD),(0xF6BE),(0xF6BF),(0xF6C0),
+(0xF6C1),(0xF6C2),(0xF6C3),(0xF6C4),(0xF6C5),(0xF6C6),(0xF6C7),(0xF6C8),
+(0xF6C9),(0xF6CA),(0xF6CB),(0xF6CC),(0xF6CD),(0xF6CE),(0xF6CF),(0xF6D0),
+(0xF6D1),(0xF6D2),(0xF6D3),(0xF6D4),(0xF6D5),(0xF6D6),(0xF6D7),(0xF6D8),
+(0xF6D9),(0xF6DA),(0xF6DB),(0xF6DC),(0xF6DD),(0xF6DE),(0xF6DF),(0xF6E0),
+(0xF6E1),(0xF6E2),(0xF6E3),(0xF6E4),(0xF6E5),(0xF6E6),(0xF6E7),(0xF6E8),
+(0xF6E9),(0xF6EA),(0xF6EB),(0xF6EC),(0xF6ED),(0xF6EE),(0xF6EF),(0xF6F0),
+(0xF6F1),(0xF6F2),(0xF6F3),(0xF6F4),(0xF6F5),(0xF6F6),(0xF6F7),(0xF6F8),
+(0xF6F9),(0xF6FA),(0xF6FB),(0xF6FC),(0xF6FD),(0xF6FE),
+(0xF7A1),(0xF7A2),(0xF7A3),(0xF7A4),(0xF7A5),(0xF7A6),(0xF7A7),(0xF7A8),
+(0xF7A9),(0xF7AA),(0xF7AB),(0xF7AC),(0xF7AD),(0xF7AE),(0xF7AF),(0xF7B0),
+(0xF7B1),(0xF7B2),(0xF7B3),(0xF7B4),(0xF7B5),(0xF7B6),(0xF7B7),(0xF7B8),
+(0xF7B9),(0xF7BA),(0xF7BB),(0xF7BC),(0xF7BD),(0xF7BE),(0xF7BF),(0xF7C0),
+(0xF7C1),(0xF7C2),(0xF7C3),(0xF7C4),(0xF7C5),(0xF7C6),(0xF7C7),(0xF7C8),
+(0xF7C9),(0xF7CA),(0xF7CB),(0xF7CC),(0xF7CD),(0xF7CE),(0xF7CF),(0xF7D0),
+(0xF7D1),(0xF7D2),(0xF7D3),(0xF7D4),(0xF7D5),(0xF7D6),(0xF7D7),(0xF7D8),
+(0xF7D9),(0xF7DA),(0xF7DB),(0xF7DC),(0xF7DD),(0xF7DE),(0xF7DF),(0xF7E0),
+(0xF7E1),(0xF7E2),(0xF7E3),(0xF7E4),(0xF7E5),(0xF7E6),(0xF7E7),(0xF7E8),
+(0xF7E9),(0xF7EA),(0xF7EB),(0xF7EC),(0xF7ED),(0xF7EE),(0xF7EF),(0xF7F0),
+(0xF7F1),(0xF7F2),(0xF7F3),(0xF7F4),(0xF7F5),(0xF7F6),(0xF7F7),(0xF7F8),
+(0xF7F9),(0xF7FA),(0xF7FB),(0xF7FC),(0xF7FD),(0xF7FE),
+(0xF8A1),(0xF8A2),(0xF8A3),(0xF8A4),(0xF8A5),(0xF8A6),(0xF8A7),(0xF8A8),
+(0xF8A9),(0xF8AA),(0xF8AB),(0xF8AC),(0xF8AD),(0xF8AE),(0xF8AF),(0xF8B0),
+(0xF8B1),(0xF8B2),(0xF8B3),(0xF8B4),(0xF8B5),(0xF8B6),(0xF8B7),(0xF8B8),
+(0xF8B9),(0xF8BA),(0xF8BB),(0xF8BC),(0xF8BD),(0xF8BE),(0xF8BF),(0xF8C0),
+(0xF8C1),(0xF8C2),(0xF8C3),(0xF8C4),(0xF8C5),(0xF8C6),(0xF8C7),(0xF8C8),
+(0xF8C9),(0xF8CA),(0xF8CB),(0xF8CC),(0xF8CD),(0xF8CE),(0xF8CF),(0xF8D0),
+(0xF8D1),(0xF8D2),(0xF8D3),(0xF8D4),(0xF8D5),(0xF8D6),(0xF8D7),(0xF8D8),
+(0xF8D9),(0xF8DA),(0xF8DB),(0xF8DC),(0xF8DD),(0xF8DE),(0xF8DF),(0xF8E0),
+(0xF8E1),(0xF8E2),(0xF8E3),(0xF8E4),(0xF8E5),(0xF8E6),(0xF8E7),(0xF8E8),
+(0xF8E9),(0xF8EA),(0xF8EB),(0xF8EC),(0xF8ED),(0xF8EE),(0xF8EF),(0xF8F0),
+(0xF8F1),(0xF8F2),(0xF8F3),(0xF8F4),(0xF8F5),(0xF8F6),(0xF8F7),(0xF8F8),
+(0xF8F9),(0xF8FA),(0xF8FB),(0xF8FC),(0xF8FD),(0xF8FE),
+(0xF9A1),(0xF9A2),(0xF9A3),(0xF9A4),(0xF9A5),(0xF9A6),(0xF9A7),(0xF9A8),
+(0xF9A9),(0xF9AA),(0xF9AB),(0xF9AC),(0xF9AD),(0xF9AE),(0xF9AF),(0xF9B0),
+(0xF9B1),(0xF9B2),(0xF9B3),(0xF9B4),(0xF9B5),(0xF9B6),(0xF9B7),(0xF9B8),
+(0xF9B9),(0xF9BA),(0xF9BB),(0xF9BC),(0xF9BD),(0xF9BE),(0xF9BF),(0xF9C0),
+(0xF9C1),(0xF9C2),(0xF9C3),(0xF9C4),(0xF9C5),(0xF9C6),(0xF9C7),(0xF9C8),
+(0xF9C9),(0xF9CA),(0xF9CB),(0xF9CC),(0xF9CD),(0xF9CE),(0xF9CF),(0xF9D0),
+(0xF9D1),(0xF9D2),(0xF9D3),(0xF9D4),(0xF9D5),(0xF9D6),(0xF9D7),(0xF9D8),
+(0xF9D9),(0xF9DA),(0xF9DB),(0xF9DC),(0xF9DD),(0xF9DE),(0xF9DF),(0xF9E0),
+(0xF9E1),(0xF9E2),(0xF9E3),(0xF9E4),(0xF9E5),(0xF9E6),(0xF9E7),(0xF9E8),
+(0xF9E9),(0xF9EA),(0xF9EB),(0xF9EC),(0xF9ED),(0xF9EE),(0xF9EF),(0xF9F0),
+(0xF9F1),(0xF9F2),(0xF9F3),(0xF9F4),(0xF9F5),(0xF9F6),(0xF9F7),(0xF9F8),
+(0xF9F9),(0xF9FA),(0xF9FB),(0xF9FC),(0xF9FD),(0xF9FE),
+(0xFAA1),(0xFAA2),(0xFAA3),(0xFAA4),(0xFAA5),(0xFAA6),(0xFAA7),(0xFAA8),
+(0xFAA9),(0xFAAA),(0xFAAB),(0xFAAC),(0xFAAD),(0xFAAE),(0xFAAF),(0xFAB0),
+(0xFAB1),(0xFAB2),(0xFAB3),(0xFAB4),(0xFAB5),(0xFAB6),(0xFAB7),(0xFAB8),
+(0xFAB9),(0xFABA),(0xFABB),(0xFABC),(0xFABD),(0xFABE),(0xFABF),(0xFAC0),
+(0xFAC1),(0xFAC2),(0xFAC3),(0xFAC4),(0xFAC5),(0xFAC6),(0xFAC7),(0xFAC8),
+(0xFAC9),(0xFACA),(0xFACB),(0xFACC),(0xFACD),(0xFACE),(0xFACF),(0xFAD0),
+(0xFAD1),(0xFAD2),(0xFAD3),(0xFAD4),(0xFAD5),(0xFAD6),(0xFAD7),(0xFAD8),
+(0xFAD9),(0xFADA),(0xFADB),(0xFADC),(0xFADD),(0xFADE),(0xFADF),(0xFAE0),
+(0xFAE1),(0xFAE2),(0xFAE3),(0xFAE4),(0xFAE5),(0xFAE6),(0xFAE7),(0xFAE8),
+(0xFAE9),(0xFAEA),(0xFAEB),(0xFAEC),(0xFAED),(0xFAEE),(0xFAEF),(0xFAF0),
+(0xFAF1),(0xFAF2),(0xFAF3),(0xFAF4),(0xFAF5),(0xFAF6),(0xFAF7),(0xFAF8),
+(0xFAF9),(0xFAFA),(0xFAFB),(0xFAFC),(0xFAFD),(0xFAFE),
+(0xFBA1),(0xFBA2),(0xFBA3),(0xFBA4),(0xFBA5),(0xFBA6),(0xFBA7),(0xFBA8),
+(0xFBA9),(0xFBAA),(0xFBAB),(0xFBAC),(0xFBAD),(0xFBAE),(0xFBAF),(0xFBB0),
+(0xFBB1),(0xFBB2),(0xFBB3),(0xFBB4),(0xFBB5),(0xFBB6),(0xFBB7),(0xFBB8),
+(0xFBB9),(0xFBBA),(0xFBBB),(0xFBBC),(0xFBBD),(0xFBBE),(0xFBBF),(0xFBC0),
+(0xFBC1),(0xFBC2),(0xFBC3),(0xFBC4),(0xFBC5),(0xFBC6),(0xFBC7),(0xFBC8),
+(0xFBC9),(0xFBCA),(0xFBCB),(0xFBCC),(0xFBCD),(0xFBCE),(0xFBCF),(0xFBD0),
+(0xFBD1),(0xFBD2),(0xFBD3),(0xFBD4),(0xFBD5),(0xFBD6),(0xFBD7),(0xFBD8),
+(0xFBD9),(0xFBDA),(0xFBDB),(0xFBDC),(0xFBDD),(0xFBDE),(0xFBDF),(0xFBE0),
+(0xFBE1),(0xFBE2),(0xFBE3),(0xFBE4),(0xFBE5),(0xFBE6),(0xFBE7),(0xFBE8),
+(0xFBE9),(0xFBEA),(0xFBEB),(0xFBEC),(0xFBED),(0xFBEE),(0xFBEF),(0xFBF0),
+(0xFBF1),(0xFBF2),(0xFBF3),(0xFBF4),(0xFBF5),(0xFBF6),(0xFBF7),(0xFBF8),
+(0xFBF9),(0xFBFA),(0xFBFB),(0xFBFC),(0xFBFD),(0xFBFE),
+(0xFCA1),(0xFCA2),(0xFCA3),(0xFCA4),(0xFCA5),(0xFCA6),(0xFCA7),(0xFCA8),
+(0xFCA9),(0xFCAA),(0xFCAB),(0xFCAC),(0xFCAD),(0xFCAE),(0xFCAF),(0xFCB0),
+(0xFCB1),(0xFCB2),(0xFCB3),(0xFCB4),(0xFCB5),(0xFCB6),(0xFCB7),(0xFCB8),
+(0xFCB9),(0xFCBA),(0xFCBB),(0xFCBC),(0xFCBD),(0xFCBE),(0xFCBF),(0xFCC0),
+(0xFCC1),(0xFCC2),(0xFCC3),(0xFCC4),(0xFCC5),(0xFCC6),(0xFCC7),(0xFCC8),
+(0xFCC9),(0xFCCA),(0xFCCB),(0xFCCC),(0xFCCD),(0xFCCE),(0xFCCF),(0xFCD0),
+(0xFCD1),(0xFCD2),(0xFCD3),(0xFCD4),(0xFCD5),(0xFCD6),(0xFCD7),(0xFCD8),
+(0xFCD9),(0xFCDA),(0xFCDB),(0xFCDC),(0xFCDD),(0xFCDE),(0xFCDF),(0xFCE0),
+(0xFCE1),(0xFCE2),(0xFCE3),(0xFCE4),(0xFCE5),(0xFCE6),(0xFCE7),(0xFCE8),
+(0xFCE9),(0xFCEA),(0xFCEB),(0xFCEC),(0xFCED),(0xFCEE),(0xFCEF),(0xFCF0),
+(0xFCF1),(0xFCF2),(0xFCF3),(0xFCF4),(0xFCF5),(0xFCF6),(0xFCF7),(0xFCF8),
+(0xFCF9),(0xFCFA),(0xFCFB),(0xFCFC),(0xFCFD),(0xFCFE),
+(0xFDA1),(0xFDA2),(0xFDA3),(0xFDA4),(0xFDA5),(0xFDA6),(0xFDA7),(0xFDA8),
+(0xFDA9),(0xFDAA),(0xFDAB),(0xFDAC),(0xFDAD),(0xFDAE),(0xFDAF),(0xFDB0),
+(0xFDB1),(0xFDB2),(0xFDB3),(0xFDB4),(0xFDB5),(0xFDB6),(0xFDB7),(0xFDB8),
+(0xFDB9),(0xFDBA),(0xFDBB),(0xFDBC),(0xFDBD),(0xFDBE),(0xFDBF),(0xFDC0),
+(0xFDC1),(0xFDC2),(0xFDC3),(0xFDC4),(0xFDC5),(0xFDC6),(0xFDC7),(0xFDC8),
+(0xFDC9),(0xFDCA),(0xFDCB),(0xFDCC),(0xFDCD),(0xFDCE),(0xFDCF),(0xFDD0),
+(0xFDD1),(0xFDD2),(0xFDD3),(0xFDD4),(0xFDD5),(0xFDD6),(0xFDD7),(0xFDD8),
+(0xFDD9),(0xFDDA),(0xFDDB),(0xFDDC),(0xFDDD),(0xFDDE),(0xFDDF),(0xFDE0),
+(0xFDE1),(0xFDE2),(0xFDE3),(0xFDE4),(0xFDE5),(0xFDE6),(0xFDE7),(0xFDE8),
+(0xFDE9),(0xFDEA),(0xFDEB),(0xFDEC),(0xFDED),(0xFDEE),(0xFDEF),(0xFDF0),
+(0xFDF1),(0xFDF2),(0xFDF3),(0xFDF4),(0xFDF5),(0xFDF6),(0xFDF7),(0xFDF8),
+(0xFDF9),(0xFDFA),(0xFDFB),(0xFDFC),(0xFDFD),(0xFDFE),
+(0xFEA1),(0xFEA2),(0xFEA3),(0xFEA4),(0xFEA5),(0xFEA6),(0xFEA7),(0xFEA8),
+(0xFEA9),(0xFEAA),(0xFEAB),(0xFEAC),(0xFEAD),(0xFEAE),(0xFEAF),(0xFEB0),
+(0xFEB1),(0xFEB2),(0xFEB3),(0xFEB4),(0xFEB5),(0xFEB6),(0xFEB7),(0xFEB8),
+(0xFEB9),(0xFEBA),(0xFEBB),(0xFEBC),(0xFEBD),(0xFEBE),(0xFEBF),(0xFEC0),
+(0xFEC1),(0xFEC2),(0xFEC3),(0xFEC4),(0xFEC5),(0xFEC6),(0xFEC7),(0xFEC8),
+(0xFEC9),(0xFECA),(0xFECB),(0xFECC),(0xFECD),(0xFECE),(0xFECF),(0xFED0),
+(0xFED1),(0xFED2),(0xFED3),(0xFED4),(0xFED5),(0xFED6),(0xFED7),(0xFED8),
+(0xFED9),(0xFEDA),(0xFEDB),(0xFEDC),(0xFEDD),(0xFEDE),(0xFEDF),(0xFEE0),
+(0xFEE1),(0xFEE2),(0xFEE3),(0xFEE4),(0xFEE5),(0xFEE6),(0xFEE7),(0xFEE8),
+(0xFEE9),(0xFEEA),(0xFEEB),(0xFEEC),(0xFEED),(0xFEEE),(0xFEEF),(0xFEF0),
+(0xFEF1),(0xFEF2),(0xFEF3),(0xFEF4),(0xFEF5),(0xFEF6),(0xFEF7),(0xFEF8),
+(0xFEF9),(0xFEFA),(0xFEFB),(0xFEFC),(0xFEFD),(0xFEFE),
+(0x8FF5A1),(0x8FF5A2),(0x8FF5A3),(0x8FF5A4),(0x8FF5A5),(0x8FF5A6),(0x8FF5A7),(0x8FF5A8),
+(0x8FF5A9),(0x8FF5AA),(0x8FF5AB),(0x8FF5AC),(0x8FF5AD),(0x8FF5AE),(0x8FF5AF),(0x8FF5B0),
+(0x8FF5B1),(0x8FF5B2),(0x8FF5B3),(0x8FF5B4),(0x8FF5B5),(0x8FF5B6),(0x8FF5B7),(0x8FF5B8),
+(0x8FF5B9),(0x8FF5BA),(0x8FF5BB),(0x8FF5BC),(0x8FF5BD),(0x8FF5BE),(0x8FF5BF),(0x8FF5C0),
+(0x8FF5C1),(0x8FF5C2),(0x8FF5C3),(0x8FF5C4),(0x8FF5C5),(0x8FF5C6),(0x8FF5C7),(0x8FF5C8),
+(0x8FF5C9),(0x8FF5CA),(0x8FF5CB),(0x8FF5CC),(0x8FF5CD),(0x8FF5CE),(0x8FF5CF),(0x8FF5D0),
+(0x8FF5D1),(0x8FF5D2),(0x8FF5D3),(0x8FF5D4),(0x8FF5D5),(0x8FF5D6),(0x8FF5D7),(0x8FF5D8),
+(0x8FF5D9),(0x8FF5DA),(0x8FF5DB),(0x8FF5DC),(0x8FF5DD),(0x8FF5DE),(0x8FF5DF),(0x8FF5E0),
+(0x8FF5E1),(0x8FF5E2),(0x8FF5E3),(0x8FF5E4),(0x8FF5E5),(0x8FF5E6),(0x8FF5E7),(0x8FF5E8),
+(0x8FF5E9),(0x8FF5EA),(0x8FF5EB),(0x8FF5EC),(0x8FF5ED),(0x8FF5EE),(0x8FF5EF),(0x8FF5F0),
+(0x8FF5F1),(0x8FF5F2),(0x8FF5F3),(0x8FF5F4),(0x8FF5F5),(0x8FF5F6),(0x8FF5F7),(0x8FF5F8),
+(0x8FF5F9),(0x8FF5FA),(0x8FF5FB),(0x8FF5FC),(0x8FF5FD),(0x8FF5FE),
+(0x8FF6A1),(0x8FF6A2),(0x8FF6A3),(0x8FF6A4),(0x8FF6A5),(0x8FF6A6),(0x8FF6A7),(0x8FF6A8),
+(0x8FF6A9),(0x8FF6AA),(0x8FF6AB),(0x8FF6AC),(0x8FF6AD),(0x8FF6AE),(0x8FF6AF),(0x8FF6B0),
+(0x8FF6B1),(0x8FF6B2),(0x8FF6B3),(0x8FF6B4),(0x8FF6B5),(0x8FF6B6),(0x8FF6B7),(0x8FF6B8),
+(0x8FF6B9),(0x8FF6BA),(0x8FF6BB),(0x8FF6BC),(0x8FF6BD),(0x8FF6BE),(0x8FF6BF),(0x8FF6C0),
+(0x8FF6C1),(0x8FF6C2),(0x8FF6C3),(0x8FF6C4),(0x8FF6C5),(0x8FF6C6),(0x8FF6C7),(0x8FF6C8),
+(0x8FF6C9),(0x8FF6CA),(0x8FF6CB),(0x8FF6CC),(0x8FF6CD),(0x8FF6CE),(0x8FF6CF),(0x8FF6D0),
+(0x8FF6D1),(0x8FF6D2),(0x8FF6D3),(0x8FF6D4),(0x8FF6D5),(0x8FF6D6),(0x8FF6D7),(0x8FF6D8),
+(0x8FF6D9),(0x8FF6DA),(0x8FF6DB),(0x8FF6DC),(0x8FF6DD),(0x8FF6DE),(0x8FF6DF),(0x8FF6E0),
+(0x8FF6E1),(0x8FF6E2),(0x8FF6E3),(0x8FF6E4),(0x8FF6E5),(0x8FF6E6),(0x8FF6E7),(0x8FF6E8),
+(0x8FF6E9),(0x8FF6EA),(0x8FF6EB),(0x8FF6EC),(0x8FF6ED),(0x8FF6EE),(0x8FF6EF),(0x8FF6F0),
+(0x8FF6F1),(0x8FF6F2),(0x8FF6F3),(0x8FF6F4),(0x8FF6F5),(0x8FF6F6),(0x8FF6F7),(0x8FF6F8),
+(0x8FF6F9),(0x8FF6FA),(0x8FF6FB),(0x8FF6FC),(0x8FF6FD),(0x8FF6FE),
+(0x8FF7A1),(0x8FF7A2),(0x8FF7A3),(0x8FF7A4),(0x8FF7A5),(0x8FF7A6),(0x8FF7A7),(0x8FF7A8),
+(0x8FF7A9),(0x8FF7AA),(0x8FF7AB),(0x8FF7AC),(0x8FF7AD),(0x8FF7AE),(0x8FF7AF),(0x8FF7B0),
+(0x8FF7B1),(0x8FF7B2),(0x8FF7B3),(0x8FF7B4),(0x8FF7B5),(0x8FF7B6),(0x8FF7B7),(0x8FF7B8),
+(0x8FF7B9),(0x8FF7BA),(0x8FF7BB),(0x8FF7BC),(0x8FF7BD),(0x8FF7BE),(0x8FF7BF),(0x8FF7C0),
+(0x8FF7C1),(0x8FF7C2),(0x8FF7C3),(0x8FF7C4),(0x8FF7C5),(0x8FF7C6),(0x8FF7C7),(0x8FF7C8),
+(0x8FF7C9),(0x8FF7CA),(0x8FF7CB),(0x8FF7CC),(0x8FF7CD),(0x8FF7CE),(0x8FF7CF),(0x8FF7D0),
+(0x8FF7D1),(0x8FF7D2),(0x8FF7D3),(0x8FF7D4),(0x8FF7D5),(0x8FF7D6),(0x8FF7D7),(0x8FF7D8),
+(0x8FF7D9),(0x8FF7DA),(0x8FF7DB),(0x8FF7DC),(0x8FF7DD),(0x8FF7DE),(0x8FF7DF),(0x8FF7E0),
+(0x8FF7E1),(0x8FF7E2),(0x8FF7E3),(0x8FF7E4),(0x8FF7E5),(0x8FF7E6),(0x8FF7E7),(0x8FF7E8),
+(0x8FF7E9),(0x8FF7EA),(0x8FF7EB),(0x8FF7EC),(0x8FF7ED),(0x8FF7EE),(0x8FF7EF),(0x8FF7F0),
+(0x8FF7F1),(0x8FF7F2),(0x8FF7F3),(0x8FF7F4),(0x8FF7F5),(0x8FF7F6),(0x8FF7F7),(0x8FF7F8),
+(0x8FF7F9),(0x8FF7FA),(0x8FF7FB),(0x8FF7FC),(0x8FF7FD),(0x8FF7FE),
+(0x8FF8A1),(0x8FF8A2),(0x8FF8A3),(0x8FF8A4),(0x8FF8A5),(0x8FF8A6),(0x8FF8A7),(0x8FF8A8),
+(0x8FF8A9),(0x8FF8AA),(0x8FF8AB),(0x8FF8AC),(0x8FF8AD),(0x8FF8AE),(0x8FF8AF),(0x8FF8B0),
+(0x8FF8B1),(0x8FF8B2),(0x8FF8B3),(0x8FF8B4),(0x8FF8B5),(0x8FF8B6),(0x8FF8B7),(0x8FF8B8),
+(0x8FF8B9),(0x8FF8BA),(0x8FF8BB),(0x8FF8BC),(0x8FF8BD),(0x8FF8BE),(0x8FF8BF),(0x8FF8C0),
+(0x8FF8C1),(0x8FF8C2),(0x8FF8C3),(0x8FF8C4),(0x8FF8C5),(0x8FF8C6),(0x8FF8C7),(0x8FF8C8),
+(0x8FF8C9),(0x8FF8CA),(0x8FF8CB),(0x8FF8CC),(0x8FF8CD),(0x8FF8CE),(0x8FF8CF),(0x8FF8D0),
+(0x8FF8D1),(0x8FF8D2),(0x8FF8D3),(0x8FF8D4),(0x8FF8D5),(0x8FF8D6),(0x8FF8D7),(0x8FF8D8),
+(0x8FF8D9),(0x8FF8DA),(0x8FF8DB),(0x8FF8DC),(0x8FF8DD),(0x8FF8DE),(0x8FF8DF),(0x8FF8E0),
+(0x8FF8E1),(0x8FF8E2),(0x8FF8E3),(0x8FF8E4),(0x8FF8E5),(0x8FF8E6),(0x8FF8E7),(0x8FF8E8),
+(0x8FF8E9),(0x8FF8EA),(0x8FF8EB),(0x8FF8EC),(0x8FF8ED),(0x8FF8EE),(0x8FF8EF),(0x8FF8F0),
+(0x8FF8F1),(0x8FF8F2),(0x8FF8F3),(0x8FF8F4),(0x8FF8F5),(0x8FF8F6),(0x8FF8F7),(0x8FF8F8),
+(0x8FF8F9),(0x8FF8FA),(0x8FF8FB),(0x8FF8FC),(0x8FF8FD),(0x8FF8FE),
+(0x8FF9A1),(0x8FF9A2),(0x8FF9A3),(0x8FF9A4),(0x8FF9A5),(0x8FF9A6),(0x8FF9A7),(0x8FF9A8),
+(0x8FF9A9),(0x8FF9AA),(0x8FF9AB),(0x8FF9AC),(0x8FF9AD),(0x8FF9AE),(0x8FF9AF),(0x8FF9B0),
+(0x8FF9B1),(0x8FF9B2),(0x8FF9B3),(0x8FF9B4),(0x8FF9B5),(0x8FF9B6),(0x8FF9B7),(0x8FF9B8),
+(0x8FF9B9),(0x8FF9BA),(0x8FF9BB),(0x8FF9BC),(0x8FF9BD),(0x8FF9BE),(0x8FF9BF),(0x8FF9C0),
+(0x8FF9C1),(0x8FF9C2),(0x8FF9C3),(0x8FF9C4),(0x8FF9C5),(0x8FF9C6),(0x8FF9C7),(0x8FF9C8),
+(0x8FF9C9),(0x8FF9CA),(0x8FF9CB),(0x8FF9CC),(0x8FF9CD),(0x8FF9CE),(0x8FF9CF),(0x8FF9D0),
+(0x8FF9D1),(0x8FF9D2),(0x8FF9D3),(0x8FF9D4),(0x8FF9D5),(0x8FF9D6),(0x8FF9D7),(0x8FF9D8),
+(0x8FF9D9),(0x8FF9DA),(0x8FF9DB),(0x8FF9DC),(0x8FF9DD),(0x8FF9DE),(0x8FF9DF),(0x8FF9E0),
+(0x8FF9E1),(0x8FF9E2),(0x8FF9E3),(0x8FF9E4),(0x8FF9E5),(0x8FF9E6),(0x8FF9E7),(0x8FF9E8),
+(0x8FF9E9),(0x8FF9EA),(0x8FF9EB),(0x8FF9EC),(0x8FF9ED),(0x8FF9EE),(0x8FF9EF),(0x8FF9F0),
+(0x8FF9F1),(0x8FF9F2),(0x8FF9F3),(0x8FF9F4),(0x8FF9F5),(0x8FF9F6),(0x8FF9F7),(0x8FF9F8),
+(0x8FF9F9),(0x8FF9FA),(0x8FF9FB),(0x8FF9FC),(0x8FF9FD),(0x8FF9FE),
+(0x8FFAA1),(0x8FFAA2),(0x8FFAA3),(0x8FFAA4),(0x8FFAA5),(0x8FFAA6),(0x8FFAA7),(0x8FFAA8),
+(0x8FFAA9),(0x8FFAAA),(0x8FFAAB),(0x8FFAAC),(0x8FFAAD),(0x8FFAAE),(0x8FFAAF),(0x8FFAB0),
+(0x8FFAB1),(0x8FFAB2),(0x8FFAB3),(0x8FFAB4),(0x8FFAB5),(0x8FFAB6),(0x8FFAB7),(0x8FFAB8),
+(0x8FFAB9),(0x8FFABA),(0x8FFABB),(0x8FFABC),(0x8FFABD),(0x8FFABE),(0x8FFABF),(0x8FFAC0),
+(0x8FFAC1),(0x8FFAC2),(0x8FFAC3),(0x8FFAC4),(0x8FFAC5),(0x8FFAC6),(0x8FFAC7),(0x8FFAC8),
+(0x8FFAC9),(0x8FFACA),(0x8FFACB),(0x8FFACC),(0x8FFACD),(0x8FFACE),(0x8FFACF),(0x8FFAD0),
+(0x8FFAD1),(0x8FFAD2),(0x8FFAD3),(0x8FFAD4),(0x8FFAD5),(0x8FFAD6),(0x8FFAD7),(0x8FFAD8),
+(0x8FFAD9),(0x8FFADA),(0x8FFADB),(0x8FFADC),(0x8FFADD),(0x8FFADE),(0x8FFADF),(0x8FFAE0),
+(0x8FFAE1),(0x8FFAE2),(0x8FFAE3),(0x8FFAE4),(0x8FFAE5),(0x8FFAE6),(0x8FFAE7),(0x8FFAE8),
+(0x8FFAE9),(0x8FFAEA),(0x8FFAEB),(0x8FFAEC),(0x8FFAED),(0x8FFAEE),(0x8FFAEF),(0x8FFAF0),
+(0x8FFAF1),(0x8FFAF2),(0x8FFAF3),(0x8FFAF4),(0x8FFAF5),(0x8FFAF6),(0x8FFAF7),(0x8FFAF8),
+(0x8FFAF9),(0x8FFAFA),(0x8FFAFB),(0x8FFAFC),(0x8FFAFD),(0x8FFAFE),
+(0x8FFBA1),(0x8FFBA2),(0x8FFBA3),(0x8FFBA4),(0x8FFBA5),(0x8FFBA6),(0x8FFBA7),(0x8FFBA8),
+(0x8FFBA9),(0x8FFBAA),(0x8FFBAB),(0x8FFBAC),(0x8FFBAD),(0x8FFBAE),(0x8FFBAF),(0x8FFBB0),
+(0x8FFBB1),(0x8FFBB2),(0x8FFBB3),(0x8FFBB4),(0x8FFBB5),(0x8FFBB6),(0x8FFBB7),(0x8FFBB8),
+(0x8FFBB9),(0x8FFBBA),(0x8FFBBB),(0x8FFBBC),(0x8FFBBD),(0x8FFBBE),(0x8FFBBF),(0x8FFBC0),
+(0x8FFBC1),(0x8FFBC2),(0x8FFBC3),(0x8FFBC4),(0x8FFBC5),(0x8FFBC6),(0x8FFBC7),(0x8FFBC8),
+(0x8FFBC9),(0x8FFBCA),(0x8FFBCB),(0x8FFBCC),(0x8FFBCD),(0x8FFBCE),(0x8FFBCF),(0x8FFBD0),
+(0x8FFBD1),(0x8FFBD2),(0x8FFBD3),(0x8FFBD4),(0x8FFBD5),(0x8FFBD6),(0x8FFBD7),(0x8FFBD8),
+(0x8FFBD9),(0x8FFBDA),(0x8FFBDB),(0x8FFBDC),(0x8FFBDD),(0x8FFBDE),(0x8FFBDF),(0x8FFBE0),
+(0x8FFBE1),(0x8FFBE2),(0x8FFBE3),(0x8FFBE4),(0x8FFBE5),(0x8FFBE6),(0x8FFBE7),(0x8FFBE8),
+(0x8FFBE9),(0x8FFBEA),(0x8FFBEB),(0x8FFBEC),(0x8FFBED),(0x8FFBEE),(0x8FFBEF),(0x8FFBF0),
+(0x8FFBF1),(0x8FFBF2),(0x8FFBF3),(0x8FFBF4),(0x8FFBF5),(0x8FFBF6),(0x8FFBF7),(0x8FFBF8),
+(0x8FFBF9),(0x8FFBFA),(0x8FFBFB),(0x8FFBFC),(0x8FFBFD),(0x8FFBFE),
+(0x8FFCA1),(0x8FFCA2),(0x8FFCA3),(0x8FFCA4),(0x8FFCA5),(0x8FFCA6),(0x8FFCA7),(0x8FFCA8),
+(0x8FFCA9),(0x8FFCAA),(0x8FFCAB),(0x8FFCAC),(0x8FFCAD),(0x8FFCAE),(0x8FFCAF),(0x8FFCB0),
+(0x8FFCB1),(0x8FFCB2),(0x8FFCB3),(0x8FFCB4),(0x8FFCB5),(0x8FFCB6),(0x8FFCB7),(0x8FFCB8),
+(0x8FFCB9),(0x8FFCBA),(0x8FFCBB),(0x8FFCBC),(0x8FFCBD),(0x8FFCBE),(0x8FFCBF),(0x8FFCC0),
+(0x8FFCC1),(0x8FFCC2),(0x8FFCC3),(0x8FFCC4),(0x8FFCC5),(0x8FFCC6),(0x8FFCC7),(0x8FFCC8),
+(0x8FFCC9),(0x8FFCCA),(0x8FFCCB),(0x8FFCCC),(0x8FFCCD),(0x8FFCCE),(0x8FFCCF),(0x8FFCD0),
+(0x8FFCD1),(0x8FFCD2),(0x8FFCD3),(0x8FFCD4),(0x8FFCD5),(0x8FFCD6),(0x8FFCD7),(0x8FFCD8),
+(0x8FFCD9),(0x8FFCDA),(0x8FFCDB),(0x8FFCDC),(0x8FFCDD),(0x8FFCDE),(0x8FFCDF),(0x8FFCE0),
+(0x8FFCE1),(0x8FFCE2),(0x8FFCE3),(0x8FFCE4),(0x8FFCE5),(0x8FFCE6),(0x8FFCE7),(0x8FFCE8),
+(0x8FFCE9),(0x8FFCEA),(0x8FFCEB),(0x8FFCEC),(0x8FFCED),(0x8FFCEE),(0x8FFCEF),(0x8FFCF0),
+(0x8FFCF1),(0x8FFCF2),(0x8FFCF3),(0x8FFCF4),(0x8FFCF5),(0x8FFCF6),(0x8FFCF7),(0x8FFCF8),
+(0x8FFCF9),(0x8FFCFA),(0x8FFCFB),(0x8FFCFC),(0x8FFCFD),(0x8FFCFE),
+(0x8FFDA1),(0x8FFDA2),(0x8FFDA3),(0x8FFDA4),(0x8FFDA5),(0x8FFDA6),(0x8FFDA7),(0x8FFDA8),
+(0x8FFDA9),(0x8FFDAA),(0x8FFDAB),(0x8FFDAC),(0x8FFDAD),(0x8FFDAE),(0x8FFDAF),(0x8FFDB0),
+(0x8FFDB1),(0x8FFDB2),(0x8FFDB3),(0x8FFDB4),(0x8FFDB5),(0x8FFDB6),(0x8FFDB7),(0x8FFDB8),
+(0x8FFDB9),(0x8FFDBA),(0x8FFDBB),(0x8FFDBC),(0x8FFDBD),(0x8FFDBE),(0x8FFDBF),(0x8FFDC0),
+(0x8FFDC1),(0x8FFDC2),(0x8FFDC3),(0x8FFDC4),(0x8FFDC5),(0x8FFDC6),(0x8FFDC7),(0x8FFDC8),
+(0x8FFDC9),(0x8FFDCA),(0x8FFDCB),(0x8FFDCC),(0x8FFDCD),(0x8FFDCE),(0x8FFDCF),(0x8FFDD0),
+(0x8FFDD1),(0x8FFDD2),(0x8FFDD3),(0x8FFDD4),(0x8FFDD5),(0x8FFDD6),(0x8FFDD7),(0x8FFDD8),
+(0x8FFDD9),(0x8FFDDA),(0x8FFDDB),(0x8FFDDC),(0x8FFDDD),(0x8FFDDE),(0x8FFDDF),(0x8FFDE0),
+(0x8FFDE1),(0x8FFDE2),(0x8FFDE3),(0x8FFDE4),(0x8FFDE5),(0x8FFDE6),(0x8FFDE7),(0x8FFDE8),
+(0x8FFDE9),(0x8FFDEA),(0x8FFDEB),(0x8FFDEC),(0x8FFDED),(0x8FFDEE),(0x8FFDEF),(0x8FFDF0),
+(0x8FFDF1),(0x8FFDF2),(0x8FFDF3),(0x8FFDF4),(0x8FFDF5),(0x8FFDF6),(0x8FFDF7),(0x8FFDF8),
+(0x8FFDF9),(0x8FFDFA),(0x8FFDFB),(0x8FFDFC),(0x8FFDFD),(0x8FFDFE),
+(0x8FFEA1),(0x8FFEA2),(0x8FFEA3),(0x8FFEA4),(0x8FFEA5),(0x8FFEA6),(0x8FFEA7),(0x8FFEA8),
+(0x8FFEA9),(0x8FFEAA),(0x8FFEAB),(0x8FFEAC),(0x8FFEAD),(0x8FFEAE),(0x8FFEAF),(0x8FFEB0),
+(0x8FFEB1),(0x8FFEB2),(0x8FFEB3),(0x8FFEB4),(0x8FFEB5),(0x8FFEB6),(0x8FFEB7),(0x8FFEB8),
+(0x8FFEB9),(0x8FFEBA),(0x8FFEBB),(0x8FFEBC),(0x8FFEBD),(0x8FFEBE),(0x8FFEBF),(0x8FFEC0),
+(0x8FFEC1),(0x8FFEC2),(0x8FFEC3),(0x8FFEC4),(0x8FFEC5),(0x8FFEC6),(0x8FFEC7),(0x8FFEC8),
+(0x8FFEC9),(0x8FFECA),(0x8FFECB),(0x8FFECC),(0x8FFECD),(0x8FFECE),(0x8FFECF),(0x8FFED0),
+(0x8FFED1),(0x8FFED2),(0x8FFED3),(0x8FFED4),(0x8FFED5),(0x8FFED6),(0x8FFED7),(0x8FFED8),
+(0x8FFED9),(0x8FFEDA),(0x8FFEDB),(0x8FFEDC),(0x8FFEDD),(0x8FFEDE),(0x8FFEDF),(0x8FFEE0),
+(0x8FFEE1),(0x8FFEE2),(0x8FFEE3),(0x8FFEE4),(0x8FFEE5),(0x8FFEE6),(0x8FFEE7),(0x8FFEE8),
+(0x8FFEE9),(0x8FFEEA),(0x8FFEEB),(0x8FFEEC),(0x8FFEED),(0x8FFEEE),(0x8FFEEF),(0x8FFEF0),
+(0x8FFEF1),(0x8FFEF2),(0x8FFEF3),(0x8FFEF4),(0x8FFEF5),(0x8FFEF6),(0x8FFEF7),(0x8FFEF8),
+(0x8FFEF9),(0x8FFEFA),(0x8FFEFB),(0x8FFEFC),(0x8FFEFD),(0x8FFEFE);
+SELECT HEX(c1) FROM t1;
+HEX(c1)
+5C
+7E
+A1B1
+A1BD
+A1C0
+A1C1
+A1C2
+A1DD
+A1F1
+A1F2
+A1EF
+A2CC
+8FA2B7
+8FA2C3
+ADA1
+ADA2
+ADA3
+ADA4
+ADA5
+ADA6
+ADA7
+ADA8
+ADA9
+ADAA
+ADAB
+ADAC
+ADAD
+ADAE
+ADAF
+ADB0
+ADB1
+ADB2
+ADB3
+ADB4
+ADB5
+ADB6
+ADB7
+ADB8
+ADB9
+ADBA
+ADBB
+ADBC
+ADBD
+ADBE
+ADC0
+ADC1
+ADC2
+ADC3
+ADC4
+ADC5
+ADC6
+ADC7
+ADC8
+ADC9
+ADCA
+ADCB
+ADCC
+ADCD
+ADCE
+ADCF
+ADD0
+ADD1
+ADD2
+ADD3
+ADD4
+ADD5
+ADD6
+ADDF
+ADE0
+ADE1
+ADE2
+ADE3
+ADE4
+ADE5
+ADE6
+ADE7
+ADE8
+ADE9
+ADEA
+ADEB
+ADEC
+ADED
+ADEE
+ADEF
+ADF0
+ADF1
+ADF2
+ADF3
+ADF4
+ADF5
+ADF6
+ADF7
+ADF8
+ADF9
+ADFA
+ADFB
+ADFC
+8FF3F3
+8FF3F4
+8FF3F5
+8FF3F6
+8FF3F7
+8FF3F8
+8FF3F9
+8FF3FA
+8FF3FB
+8FF3FC
+8FF3FD
+8FF3FE
+8FF4A1
+8FF4A2
+8FF4A3
+8FF4A4
+8FF4A5
+8FF4A6
+8FF4A7
+8FF4A8
+A2CC
+8FA2C3
+8FF4A9
+8FF4AA
+8FF4AB
+8FF4AC
+8FF4AD
+A2E8
+8FD4E3
+8FDCDF
+8FE4E9
+8FE3F8
+8FD9A1
+8FB1BB
+8FF4AE
+8FC2AD
+8FC3FC
+8FE4D0
+8FC2BF
+8FBCF4
+8FB0A9
+8FB0C8
+8FF4AF
+8FB0D2
+8FB0D4
+8FB0E3
+8FB0EE
+8FB1A7
+8FB1A3
+8FB1AC
+8FB1A9
+8FB1BE
+8FB1DF
+8FB1D8
+8FB1C8
+8FB1D7
+8FB1E3
+8FB1F4
+8FB1E1
+8FB2A3
+8FF4B0
+8FB2BB
+8FB2E6
+8FB2ED
+8FB2F5
+8FB2FC
+8FF4B1
+8FB3B5
+8FB3D8
+8FB3DB
+8FB3E5
+8FB3EE
+8FB3FB
+8FF4B2
+8FF4B3
+8FB4C0
+8FB4C7
+8FB4D0
+8FB4DE
+8FF4B4
+8FB5AA
+8FF4B5
+8FB5AF
+8FB5C4
+8FB5E8
+8FF4B6
+8FB7C2
+8FB7E4
+8FB7E8
+8FB7E7
+8FF4B7
+8FF4B8
+8FF4B9
+8FB8CE
+8FB8E1
+8FB8F5
+8FB8F7
+8FB8F8
+8FB8FC
+8FB9AF
+8FB9B7
+8FBABE
+8FBADB
+8FCDAA
+8FBAE1
+8FF4BA
+8FBAEB
+8FBBB3
+8FBBB8
+8FF4BB
+8FBBCA
+8FF4BC
+8FF4BD
+8FBBD0
+8FBBDE
+8FBBF4
+8FBBF5
+8FBBF9
+8FBCE4
+8FBCED
+8FBCFE
+8FF4BE
+8FBDC2
+8FBDE7
+8FF4BF
+8FBDF0
+8FBEB0
+8FBEAC
+8FF4C0
+8FBEB3
+8FBEBD
+8FBECD
+8FBEC9
+8FBEE4
+8FBFA8
+8FBFC9
+8FC0C4
+8FC0E4
+8FC0F4
+8FC1A6
+8FF4C1
+8FC1F5
+8FC1FC
+8FF4C2
+8FC1F8
+8FC2AB
+8FC2A1
+8FC2A5
+8FF4C3
+8FC2B8
+8FC2BA
+8FF4C4
+8FC2C4
+8FC2D2
+8FC2D7
+8FC2DB
+8FC2DE
+8FC2ED
+8FC2F0
+8FF4C5
+8FC3A1
+8FC3B5
+8FC3C9
+8FC3B9
+8FF4C6
+8FC3D8
+8FC3FE
+8FF4C7
+8FC4CC
+8FF4C8
+8FC4D9
+8FC4EA
+8FC4FD
+8FF4C9
+8FC5A7
+8FC5B5
+8FC5B6
+8FF4CA
+8FC5D5
+8FC6B8
+8FC6D7
+8FC6E0
+8FC6EA
+8FC6E3
+8FC7A1
+8FC7AB
+8FC7C7
+8FC7C3
+8FC7CB
+8FC7CF
+8FC7D9
+8FF4CB
+8FF4CC
+8FC7E6
+8FC7EE
+8FC7FC
+8FC7EB
+8FC7F0
+8FC8B1
+8FC8E5
+8FC8F8
+8FC9A6
+8FC9AB
+8FC9AD
+8FF4CD
+8FC9CA
+8FC9D3
+8FC9E9
+8FC9E3
+8FC9FC
+8FC9F4
+8FC9F5
+8FF4CE
+8FCAB3
+8FCABD
+8FCAEF
+8FCAF1
+8FCBAE
+8FF4CF
+8FCBCA
+8FCBE6
+8FCBEA
+8FCBF0
+8FCBF4
+8FCBEE
+8FCCA5
+8FCBF9
+8FCCAB
+8FCCAE
+8FCCAD
+8FCCB2
+8FCCC2
+8FCCD0
+8FCCD9
+8FF4D0
+8FCDBB
+8FF4D1
+8FCEBB
+8FF4D2
+8FCEBA
+8FCEC3
+8FF4D3
+8FCEF2
+8FB3DD
+8FCFD5
+8FCFE2
+8FCFE9
+8FCFED
+8FF4D4
+8FF4D5
+8FF4D6
+8FF4D7
+8FD0E5
+8FF4D8
+8FD0E9
+8FD1E8
+8FF4D9
+8FF4DA
+8FD1EC
+8FD2BB
+8FF4DB
+8FD3E1
+8FD3E8
+8FD4A7
+8FF4DC
+8FF4DD
+8FD4D4
+8FD4F2
+8FD5AE
+8FF4DE
+8FD7DE
+8FF4DF
+8FD8A2
+8FD8B7
+8FD8C1
+8FD8D1
+8FD8F4
+8FD9C6
+8FD9C8
+8FD9D1
+8FF4E0
+8FF4E1
+8FF4E2
+8FF4E3
+8FF4E4
+8FDCD3
+8FDDC8
+8FDDD4
+8FDDEA
+8FDDFA
+8FDEA4
+8FDEB0
+8FF4E5
+8FDEB5
+8FDECB
+8FF4E6
+8FDFB9
+8FF4E7
+8FDFC3
+8FF4E8
+8FF4E9
+8FE0D9
+8FF4EA
+8FF4EB
+8FE1E2
+8FF4EC
+8FF4ED
+8FF4EE
+8FE2C7
+8FE3A8
+8FE3A6
+8FE3A9
+8FE3AF
+8FE3B0
+8FE3AA
+8FE3AB
+8FE3BC
+8FE3C1
+8FE3BF
+8FE3D5
+8FE3D8
+8FE3D6
+8FE3DF
+8FE3E3
+8FE3E1
+8FE3D4
+8FE3E9
+8FE4A6
+8FE3F1
+8FE3F2
+8FE4CB
+8FE4C1
+8FE4C3
+8FE4BE
+8FF4EF
+8FE4C0
+8FE4C7
+8FE4BF
+8FE4E0
+8FE4DE
+8FE4D1
+8FF4F0
+8FE4DC
+8FE4D2
+8FE4DB
+8FE4D4
+8FE4FA
+8FE4EF
+8FE5B3
+8FE5BF
+8FE5C9
+8FE5D0
+8FE5E2
+8FE5EA
+8FE5EB
+8FF4F1
+8FF4F2
+8FF4F3
+8FE6E8
+8FE6EF
+8FE7AC
+8FF4F4
+8FE7AE
+8FF4F5
+8FE7B1
+8FF4F6
+8FE7B2
+8FE8B1
+8FE8B6
+8FF4F7
+8FF4F8
+8FE8DD
+8FF4F9
+8FF4FA
+8FE9D1
+8FF4FB
+8FE9ED
+8FEACD
+8FF4FC
+8FEADB
+8FEAE6
+8FEAEA
+8FEBA5
+8FEBFB
+8FEBFA
+8FF4FD
+8FECD6
+8FF4FE
+F5A1
+F5A2
+F5A3
+F5A4
+F5A5
+F5A6
+F5A7
+F5A8
+F5A9
+F5AA
+F5AB
+F5AC
+F5AD
+F5AE
+F5AF
+F5B0
+F5B1
+F5B2
+F5B3
+F5B4
+F5B5
+F5B6
+F5B7
+F5B8
+F5B9
+F5BA
+F5BB
+F5BC
+F5BD
+F5BE
+F5BF
+F5C0
+F5C1
+F5C2
+F5C3
+F5C4
+F5C5
+F5C6
+F5C7
+F5C8
+F5C9
+F5CA
+F5CB
+F5CC
+F5CD
+F5CE
+F5CF
+F5D0
+F5D1
+F5D2
+F5D3
+F5D4
+F5D5
+F5D6
+F5D7
+F5D8
+F5D9
+F5DA
+F5DB
+F5DC
+F5DD
+F5DE
+F5DF
+F5E0
+F5E1
+F5E2
+F5E3
+F5E4
+F5E5
+F5E6
+F5E7
+F5E8
+F5E9
+F5EA
+F5EB
+F5EC
+F5ED
+F5EE
+F5EF
+F5F0
+F5F1
+F5F2
+F5F3
+F5F4
+F5F5
+F5F6
+F5F7
+F5F8
+F5F9
+F5FA
+F5FB
+F5FC
+F5FD
+F5FE
+F6A1
+F6A2
+F6A3
+F6A4
+F6A5
+F6A6
+F6A7
+F6A8
+F6A9
+F6AA
+F6AB
+F6AC
+F6AD
+F6AE
+F6AF
+F6B0
+F6B1
+F6B2
+F6B3
+F6B4
+F6B5
+F6B6
+F6B7
+F6B8
+F6B9
+F6BA
+F6BB
+F6BC
+F6BD
+F6BE
+F6BF
+F6C0
+F6C1
+F6C2
+F6C3
+F6C4
+F6C5
+F6C6
+F6C7
+F6C8
+F6C9
+F6CA
+F6CB
+F6CC
+F6CD
+F6CE
+F6CF
+F6D0
+F6D1
+F6D2
+F6D3
+F6D4
+F6D5
+F6D6
+F6D7
+F6D8
+F6D9
+F6DA
+F6DB
+F6DC
+F6DD
+F6DE
+F6DF
+F6E0
+F6E1
+F6E2
+F6E3
+F6E4
+F6E5
+F6E6
+F6E7
+F6E8
+F6E9
+F6EA
+F6EB
+F6EC
+F6ED
+F6EE
+F6EF
+F6F0
+F6F1
+F6F2
+F6F3
+F6F4
+F6F5
+F6F6
+F6F7
+F6F8
+F6F9
+F6FA
+F6FB
+F6FC
+F6FD
+F6FE
+F7A1
+F7A2
+F7A3
+F7A4
+F7A5
+F7A6
+F7A7
+F7A8
+F7A9
+F7AA
+F7AB
+F7AC
+F7AD
+F7AE
+F7AF
+F7B0
+F7B1
+F7B2
+F7B3
+F7B4
+F7B5
+F7B6
+F7B7
+F7B8
+F7B9
+F7BA
+F7BB
+F7BC
+F7BD
+F7BE
+F7BF
+F7C0
+F7C1
+F7C2
+F7C3
+F7C4
+F7C5
+F7C6
+F7C7
+F7C8
+F7C9
+F7CA
+F7CB
+F7CC
+F7CD
+F7CE
+F7CF
+F7D0
+F7D1
+F7D2
+F7D3
+F7D4
+F7D5
+F7D6
+F7D7
+F7D8
+F7D9
+F7DA
+F7DB
+F7DC
+F7DD
+F7DE
+F7DF
+F7E0
+F7E1
+F7E2
+F7E3
+F7E4
+F7E5
+F7E6
+F7E7
+F7E8
+F7E9
+F7EA
+F7EB
+F7EC
+F7ED
+F7EE
+F7EF
+F7F0
+F7F1
+F7F2
+F7F3
+F7F4
+F7F5
+F7F6
+F7F7
+F7F8
+F7F9
+F7FA
+F7FB
+F7FC
+F7FD
+F7FE
+F8A1
+F8A2
+F8A3
+F8A4
+F8A5
+F8A6
+F8A7
+F8A8
+F8A9
+F8AA
+F8AB
+F8AC
+F8AD
+F8AE
+F8AF
+F8B0
+F8B1
+F8B2
+F8B3
+F8B4
+F8B5
+F8B6
+F8B7
+F8B8
+F8B9
+F8BA
+F8BB
+F8BC
+F8BD
+F8BE
+F8BF
+F8C0
+F8C1
+F8C2
+F8C3
+F8C4
+F8C5
+F8C6
+F8C7
+F8C8
+F8C9
+F8CA
+F8CB
+F8CC
+F8CD
+F8CE
+F8CF
+F8D0
+F8D1
+F8D2
+F8D3
+F8D4
+F8D5
+F8D6
+F8D7
+F8D8
+F8D9
+F8DA
+F8DB
+F8DC
+F8DD
+F8DE
+F8DF
+F8E0
+F8E1
+F8E2
+F8E3
+F8E4
+F8E5
+F8E6
+F8E7
+F8E8
+F8E9
+F8EA
+F8EB
+F8EC
+F8ED
+F8EE
+F8EF
+F8F0
+F8F1
+F8F2
+F8F3
+F8F4
+F8F5
+F8F6
+F8F7
+F8F8
+F8F9
+F8FA
+F8FB
+F8FC
+F8FD
+F8FE
+F9A1
+F9A2
+F9A3
+F9A4
+F9A5
+F9A6
+F9A7
+F9A8
+F9A9
+F9AA
+F9AB
+F9AC
+F9AD
+F9AE
+F9AF
+F9B0
+F9B1
+F9B2
+F9B3
+F9B4
+F9B5
+F9B6
+F9B7
+F9B8
+F9B9
+F9BA
+F9BB
+F9BC
+F9BD
+F9BE
+F9BF
+F9C0
+F9C1
+F9C2
+F9C3
+F9C4
+F9C5
+F9C6
+F9C7
+F9C8
+F9C9
+F9CA
+F9CB
+F9CC
+F9CD
+F9CE
+F9CF
+F9D0
+F9D1
+F9D2
+F9D3
+F9D4
+F9D5
+F9D6
+F9D7
+F9D8
+F9D9
+F9DA
+F9DB
+F9DC
+F9DD
+F9DE
+F9DF
+F9E0
+F9E1
+F9E2
+F9E3
+F9E4
+F9E5
+F9E6
+F9E7
+F9E8
+F9E9
+F9EA
+F9EB
+F9EC
+F9ED
+F9EE
+F9EF
+F9F0
+F9F1
+F9F2
+F9F3
+F9F4
+F9F5
+F9F6
+F9F7
+F9F8
+F9F9
+F9FA
+F9FB
+F9FC
+F9FD
+F9FE
+FAA1
+FAA2
+FAA3
+FAA4
+FAA5
+FAA6
+FAA7
+FAA8
+FAA9
+FAAA
+FAAB
+FAAC
+FAAD
+FAAE
+FAAF
+FAB0
+FAB1
+FAB2
+FAB3
+FAB4
+FAB5
+FAB6
+FAB7
+FAB8
+FAB9
+FABA
+FABB
+FABC
+FABD
+FABE
+FABF
+FAC0
+FAC1
+FAC2
+FAC3
+FAC4
+FAC5
+FAC6
+FAC7
+FAC8
+FAC9
+FACA
+FACB
+FACC
+FACD
+FACE
+FACF
+FAD0
+FAD1
+FAD2
+FAD3
+FAD4
+FAD5
+FAD6
+FAD7
+FAD8
+FAD9
+FADA
+FADB
+FADC
+FADD
+FADE
+FADF
+FAE0
+FAE1
+FAE2
+FAE3
+FAE4
+FAE5
+FAE6
+FAE7
+FAE8
+FAE9
+FAEA
+FAEB
+FAEC
+FAED
+FAEE
+FAEF
+FAF0
+FAF1
+FAF2
+FAF3
+FAF4
+FAF5
+FAF6
+FAF7
+FAF8
+FAF9
+FAFA
+FAFB
+FAFC
+FAFD
+FAFE
+FBA1
+FBA2
+FBA3
+FBA4
+FBA5
+FBA6
+FBA7
+FBA8
+FBA9
+FBAA
+FBAB
+FBAC
+FBAD
+FBAE
+FBAF
+FBB0
+FBB1
+FBB2
+FBB3
+FBB4
+FBB5
+FBB6
+FBB7
+FBB8
+FBB9
+FBBA
+FBBB
+FBBC
+FBBD
+FBBE
+FBBF
+FBC0
+FBC1
+FBC2
+FBC3
+FBC4
+FBC5
+FBC6
+FBC7
+FBC8
+FBC9
+FBCA
+FBCB
+FBCC
+FBCD
+FBCE
+FBCF
+FBD0
+FBD1
+FBD2
+FBD3
+FBD4
+FBD5
+FBD6
+FBD7
+FBD8
+FBD9
+FBDA
+FBDB
+FBDC
+FBDD
+FBDE
+FBDF
+FBE0
+FBE1
+FBE2
+FBE3
+FBE4
+FBE5
+FBE6
+FBE7
+FBE8
+FBE9
+FBEA
+FBEB
+FBEC
+FBED
+FBEE
+FBEF
+FBF0
+FBF1
+FBF2
+FBF3
+FBF4
+FBF5
+FBF6
+FBF7
+FBF8
+FBF9
+FBFA
+FBFB
+FBFC
+FBFD
+FBFE
+FCA1
+FCA2
+FCA3
+FCA4
+FCA5
+FCA6
+FCA7
+FCA8
+FCA9
+FCAA
+FCAB
+FCAC
+FCAD
+FCAE
+FCAF
+FCB0
+FCB1
+FCB2
+FCB3
+FCB4
+FCB5
+FCB6
+FCB7
+FCB8
+FCB9
+FCBA
+FCBB
+FCBC
+FCBD
+FCBE
+FCBF
+FCC0
+FCC1
+FCC2
+FCC3
+FCC4
+FCC5
+FCC6
+FCC7
+FCC8
+FCC9
+FCCA
+FCCB
+FCCC
+FCCD
+FCCE
+FCCF
+FCD0
+FCD1
+FCD2
+FCD3
+FCD4
+FCD5
+FCD6
+FCD7
+FCD8
+FCD9
+FCDA
+FCDB
+FCDC
+FCDD
+FCDE
+FCDF
+FCE0
+FCE1
+FCE2
+FCE3
+FCE4
+FCE5
+FCE6
+FCE7
+FCE8
+FCE9
+FCEA
+FCEB
+FCEC
+FCED
+FCEE
+FCEF
+FCF0
+FCF1
+FCF2
+FCF3
+FCF4
+FCF5
+FCF6
+FCF7
+FCF8
+FCF9
+FCFA
+FCFB
+FCFC
+FCFD
+FCFE
+FDA1
+FDA2
+FDA3
+FDA4
+FDA5
+FDA6
+FDA7
+FDA8
+FDA9
+FDAA
+FDAB
+FDAC
+FDAD
+FDAE
+FDAF
+FDB0
+FDB1
+FDB2
+FDB3
+FDB4
+FDB5
+FDB6
+FDB7
+FDB8
+FDB9
+FDBA
+FDBB
+FDBC
+FDBD
+FDBE
+FDBF
+FDC0
+FDC1
+FDC2
+FDC3
+FDC4
+FDC5
+FDC6
+FDC7
+FDC8
+FDC9
+FDCA
+FDCB
+FDCC
+FDCD
+FDCE
+FDCF
+FDD0
+FDD1
+FDD2
+FDD3
+FDD4
+FDD5
+FDD6
+FDD7
+FDD8
+FDD9
+FDDA
+FDDB
+FDDC
+FDDD
+FDDE
+FDDF
+FDE0
+FDE1
+FDE2
+FDE3
+FDE4
+FDE5
+FDE6
+FDE7
+FDE8
+FDE9
+FDEA
+FDEB
+FDEC
+FDED
+FDEE
+FDEF
+FDF0
+FDF1
+FDF2
+FDF3
+FDF4
+FDF5
+FDF6
+FDF7
+FDF8
+FDF9
+FDFA
+FDFB
+FDFC
+FDFD
+FDFE
+FEA1
+FEA2
+FEA3
+FEA4
+FEA5
+FEA6
+FEA7
+FEA8
+FEA9
+FEAA
+FEAB
+FEAC
+FEAD
+FEAE
+FEAF
+FEB0
+FEB1
+FEB2
+FEB3
+FEB4
+FEB5
+FEB6
+FEB7
+FEB8
+FEB9
+FEBA
+FEBB
+FEBC
+FEBD
+FEBE
+FEBF
+FEC0
+FEC1
+FEC2
+FEC3
+FEC4
+FEC5
+FEC6
+FEC7
+FEC8
+FEC9
+FECA
+FECB
+FECC
+FECD
+FECE
+FECF
+FED0
+FED1
+FED2
+FED3
+FED4
+FED5
+FED6
+FED7
+FED8
+FED9
+FEDA
+FEDB
+FEDC
+FEDD
+FEDE
+FEDF
+FEE0
+FEE1
+FEE2
+FEE3
+FEE4
+FEE5
+FEE6
+FEE7
+FEE8
+FEE9
+FEEA
+FEEB
+FEEC
+FEED
+FEEE
+FEEF
+FEF0
+FEF1
+FEF2
+FEF3
+FEF4
+FEF5
+FEF6
+FEF7
+FEF8
+FEF9
+FEFA
+FEFB
+FEFC
+FEFD
+FEFE
+8FF5A1
+8FF5A2
+8FF5A3
+8FF5A4
+8FF5A5
+8FF5A6
+8FF5A7
+8FF5A8
+8FF5A9
+8FF5AA
+8FF5AB
+8FF5AC
+8FF5AD
+8FF5AE
+8FF5AF
+8FF5B0
+8FF5B1
+8FF5B2
+8FF5B3
+8FF5B4
+8FF5B5
+8FF5B6
+8FF5B7
+8FF5B8
+8FF5B9
+8FF5BA
+8FF5BB
+8FF5BC
+8FF5BD
+8FF5BE
+8FF5BF
+8FF5C0
+8FF5C1
+8FF5C2
+8FF5C3
+8FF5C4
+8FF5C5
+8FF5C6
+8FF5C7
+8FF5C8
+8FF5C9
+8FF5CA
+8FF5CB
+8FF5CC
+8FF5CD
+8FF5CE
+8FF5CF
+8FF5D0
+8FF5D1
+8FF5D2
+8FF5D3
+8FF5D4
+8FF5D5
+8FF5D6
+8FF5D7
+8FF5D8
+8FF5D9
+8FF5DA
+8FF5DB
+8FF5DC
+8FF5DD
+8FF5DE
+8FF5DF
+8FF5E0
+8FF5E1
+8FF5E2
+8FF5E3
+8FF5E4
+8FF5E5
+8FF5E6
+8FF5E7
+8FF5E8
+8FF5E9
+8FF5EA
+8FF5EB
+8FF5EC
+8FF5ED
+8FF5EE
+8FF5EF
+8FF5F0
+8FF5F1
+8FF5F2
+8FF5F3
+8FF5F4
+8FF5F5
+8FF5F6
+8FF5F7
+8FF5F8
+8FF5F9
+8FF5FA
+8FF5FB
+8FF5FC
+8FF5FD
+8FF5FE
+8FF6A1
+8FF6A2
+8FF6A3
+8FF6A4
+8FF6A5
+8FF6A6
+8FF6A7
+8FF6A8
+8FF6A9
+8FF6AA
+8FF6AB
+8FF6AC
+8FF6AD
+8FF6AE
+8FF6AF
+8FF6B0
+8FF6B1
+8FF6B2
+8FF6B3
+8FF6B4
+8FF6B5
+8FF6B6
+8FF6B7
+8FF6B8
+8FF6B9
+8FF6BA
+8FF6BB
+8FF6BC
+8FF6BD
+8FF6BE
+8FF6BF
+8FF6C0
+8FF6C1
+8FF6C2
+8FF6C3
+8FF6C4
+8FF6C5
+8FF6C6
+8FF6C7
+8FF6C8
+8FF6C9
+8FF6CA
+8FF6CB
+8FF6CC
+8FF6CD
+8FF6CE
+8FF6CF
+8FF6D0
+8FF6D1
+8FF6D2
+8FF6D3
+8FF6D4
+8FF6D5
+8FF6D6
+8FF6D7
+8FF6D8
+8FF6D9
+8FF6DA
+8FF6DB
+8FF6DC
+8FF6DD
+8FF6DE
+8FF6DF
+8FF6E0
+8FF6E1
+8FF6E2
+8FF6E3
+8FF6E4
+8FF6E5
+8FF6E6
+8FF6E7
+8FF6E8
+8FF6E9
+8FF6EA
+8FF6EB
+8FF6EC
+8FF6ED
+8FF6EE
+8FF6EF
+8FF6F0
+8FF6F1
+8FF6F2
+8FF6F3
+8FF6F4
+8FF6F5
+8FF6F6
+8FF6F7
+8FF6F8
+8FF6F9
+8FF6FA
+8FF6FB
+8FF6FC
+8FF6FD
+8FF6FE
+8FF7A1
+8FF7A2
+8FF7A3
+8FF7A4
+8FF7A5
+8FF7A6
+8FF7A7
+8FF7A8
+8FF7A9
+8FF7AA
+8FF7AB
+8FF7AC
+8FF7AD
+8FF7AE
+8FF7AF
+8FF7B0
+8FF7B1
+8FF7B2
+8FF7B3
+8FF7B4
+8FF7B5
+8FF7B6
+8FF7B7
+8FF7B8
+8FF7B9
+8FF7BA
+8FF7BB
+8FF7BC
+8FF7BD
+8FF7BE
+8FF7BF
+8FF7C0
+8FF7C1
+8FF7C2
+8FF7C3
+8FF7C4
+8FF7C5
+8FF7C6
+8FF7C7
+8FF7C8
+8FF7C9
+8FF7CA
+8FF7CB
+8FF7CC
+8FF7CD
+8FF7CE
+8FF7CF
+8FF7D0
+8FF7D1
+8FF7D2
+8FF7D3
+8FF7D4
+8FF7D5
+8FF7D6
+8FF7D7
+8FF7D8
+8FF7D9
+8FF7DA
+8FF7DB
+8FF7DC
+8FF7DD
+8FF7DE
+8FF7DF
+8FF7E0
+8FF7E1
+8FF7E2
+8FF7E3
+8FF7E4
+8FF7E5
+8FF7E6
+8FF7E7
+8FF7E8
+8FF7E9
+8FF7EA
+8FF7EB
+8FF7EC
+8FF7ED
+8FF7EE
+8FF7EF
+8FF7F0
+8FF7F1
+8FF7F2
+8FF7F3
+8FF7F4
+8FF7F5
+8FF7F6
+8FF7F7
+8FF7F8
+8FF7F9
+8FF7FA
+8FF7FB
+8FF7FC
+8FF7FD
+8FF7FE
+8FF8A1
+8FF8A2
+8FF8A3
+8FF8A4
+8FF8A5
+8FF8A6
+8FF8A7
+8FF8A8
+8FF8A9
+8FF8AA
+8FF8AB
+8FF8AC
+8FF8AD
+8FF8AE
+8FF8AF
+8FF8B0
+8FF8B1
+8FF8B2
+8FF8B3
+8FF8B4
+8FF8B5
+8FF8B6
+8FF8B7
+8FF8B8
+8FF8B9
+8FF8BA
+8FF8BB
+8FF8BC
+8FF8BD
+8FF8BE
+8FF8BF
+8FF8C0
+8FF8C1
+8FF8C2
+8FF8C3
+8FF8C4
+8FF8C5
+8FF8C6
+8FF8C7
+8FF8C8
+8FF8C9
+8FF8CA
+8FF8CB
+8FF8CC
+8FF8CD
+8FF8CE
+8FF8CF
+8FF8D0
+8FF8D1
+8FF8D2
+8FF8D3
+8FF8D4
+8FF8D5
+8FF8D6
+8FF8D7
+8FF8D8
+8FF8D9
+8FF8DA
+8FF8DB
+8FF8DC
+8FF8DD
+8FF8DE
+8FF8DF
+8FF8E0
+8FF8E1
+8FF8E2
+8FF8E3
+8FF8E4
+8FF8E5
+8FF8E6
+8FF8E7
+8FF8E8
+8FF8E9
+8FF8EA
+8FF8EB
+8FF8EC
+8FF8ED
+8FF8EE
+8FF8EF
+8FF8F0
+8FF8F1
+8FF8F2
+8FF8F3
+8FF8F4
+8FF8F5
+8FF8F6
+8FF8F7
+8FF8F8
+8FF8F9
+8FF8FA
+8FF8FB
+8FF8FC
+8FF8FD
+8FF8FE
+8FF9A1
+8FF9A2
+8FF9A3
+8FF9A4
+8FF9A5
+8FF9A6
+8FF9A7
+8FF9A8
+8FF9A9
+8FF9AA
+8FF9AB
+8FF9AC
+8FF9AD
+8FF9AE
+8FF9AF
+8FF9B0
+8FF9B1
+8FF9B2
+8FF9B3
+8FF9B4
+8FF9B5
+8FF9B6
+8FF9B7
+8FF9B8
+8FF9B9
+8FF9BA
+8FF9BB
+8FF9BC
+8FF9BD
+8FF9BE
+8FF9BF
+8FF9C0
+8FF9C1
+8FF9C2
+8FF9C3
+8FF9C4
+8FF9C5
+8FF9C6
+8FF9C7
+8FF9C8
+8FF9C9
+8FF9CA
+8FF9CB
+8FF9CC
+8FF9CD
+8FF9CE
+8FF9CF
+8FF9D0
+8FF9D1
+8FF9D2
+8FF9D3
+8FF9D4
+8FF9D5
+8FF9D6
+8FF9D7
+8FF9D8
+8FF9D9
+8FF9DA
+8FF9DB
+8FF9DC
+8FF9DD
+8FF9DE
+8FF9DF
+8FF9E0
+8FF9E1
+8FF9E2
+8FF9E3
+8FF9E4
+8FF9E5
+8FF9E6
+8FF9E7
+8FF9E8
+8FF9E9
+8FF9EA
+8FF9EB
+8FF9EC
+8FF9ED
+8FF9EE
+8FF9EF
+8FF9F0
+8FF9F1
+8FF9F2
+8FF9F3
+8FF9F4
+8FF9F5
+8FF9F6
+8FF9F7
+8FF9F8
+8FF9F9
+8FF9FA
+8FF9FB
+8FF9FC
+8FF9FD
+8FF9FE
+8FFAA1
+8FFAA2
+8FFAA3
+8FFAA4
+8FFAA5
+8FFAA6
+8FFAA7
+8FFAA8
+8FFAA9
+8FFAAA
+8FFAAB
+8FFAAC
+8FFAAD
+8FFAAE
+8FFAAF
+8FFAB0
+8FFAB1
+8FFAB2
+8FFAB3
+8FFAB4
+8FFAB5
+8FFAB6
+8FFAB7
+8FFAB8
+8FFAB9
+8FFABA
+8FFABB
+8FFABC
+8FFABD
+8FFABE
+8FFABF
+8FFAC0
+8FFAC1
+8FFAC2
+8FFAC3
+8FFAC4
+8FFAC5
+8FFAC6
+8FFAC7
+8FFAC8
+8FFAC9
+8FFACA
+8FFACB
+8FFACC
+8FFACD
+8FFACE
+8FFACF
+8FFAD0
+8FFAD1
+8FFAD2
+8FFAD3
+8FFAD4
+8FFAD5
+8FFAD6
+8FFAD7
+8FFAD8
+8FFAD9
+8FFADA
+8FFADB
+8FFADC
+8FFADD
+8FFADE
+8FFADF
+8FFAE0
+8FFAE1
+8FFAE2
+8FFAE3
+8FFAE4
+8FFAE5
+8FFAE6
+8FFAE7
+8FFAE8
+8FFAE9
+8FFAEA
+8FFAEB
+8FFAEC
+8FFAED
+8FFAEE
+8FFAEF
+8FFAF0
+8FFAF1
+8FFAF2
+8FFAF3
+8FFAF4
+8FFAF5
+8FFAF6
+8FFAF7
+8FFAF8
+8FFAF9
+8FFAFA
+8FFAFB
+8FFAFC
+8FFAFD
+8FFAFE
+8FFBA1
+8FFBA2
+8FFBA3
+8FFBA4
+8FFBA5
+8FFBA6
+8FFBA7
+8FFBA8
+8FFBA9
+8FFBAA
+8FFBAB
+8FFBAC
+8FFBAD
+8FFBAE
+8FFBAF
+8FFBB0
+8FFBB1
+8FFBB2
+8FFBB3
+8FFBB4
+8FFBB5
+8FFBB6
+8FFBB7
+8FFBB8
+8FFBB9
+8FFBBA
+8FFBBB
+8FFBBC
+8FFBBD
+8FFBBE
+8FFBBF
+8FFBC0
+8FFBC1
+8FFBC2
+8FFBC3
+8FFBC4
+8FFBC5
+8FFBC6
+8FFBC7
+8FFBC8
+8FFBC9
+8FFBCA
+8FFBCB
+8FFBCC
+8FFBCD
+8FFBCE
+8FFBCF
+8FFBD0
+8FFBD1
+8FFBD2
+8FFBD3
+8FFBD4
+8FFBD5
+8FFBD6
+8FFBD7
+8FFBD8
+8FFBD9
+8FFBDA
+8FFBDB
+8FFBDC
+8FFBDD
+8FFBDE
+8FFBDF
+8FFBE0
+8FFBE1
+8FFBE2
+8FFBE3
+8FFBE4
+8FFBE5
+8FFBE6
+8FFBE7
+8FFBE8
+8FFBE9
+8FFBEA
+8FFBEB
+8FFBEC
+8FFBED
+8FFBEE
+8FFBEF
+8FFBF0
+8FFBF1
+8FFBF2
+8FFBF3
+8FFBF4
+8FFBF5
+8FFBF6
+8FFBF7
+8FFBF8
+8FFBF9
+8FFBFA
+8FFBFB
+8FFBFC
+8FFBFD
+8FFBFE
+8FFCA1
+8FFCA2
+8FFCA3
+8FFCA4
+8FFCA5
+8FFCA6
+8FFCA7
+8FFCA8
+8FFCA9
+8FFCAA
+8FFCAB
+8FFCAC
+8FFCAD
+8FFCAE
+8FFCAF
+8FFCB0
+8FFCB1
+8FFCB2
+8FFCB3
+8FFCB4
+8FFCB5
+8FFCB6
+8FFCB7
+8FFCB8
+8FFCB9
+8FFCBA
+8FFCBB
+8FFCBC
+8FFCBD
+8FFCBE
+8FFCBF
+8FFCC0
+8FFCC1
+8FFCC2
+8FFCC3
+8FFCC4
+8FFCC5
+8FFCC6
+8FFCC7
+8FFCC8
+8FFCC9
+8FFCCA
+8FFCCB
+8FFCCC
+8FFCCD
+8FFCCE
+8FFCCF
+8FFCD0
+8FFCD1
+8FFCD2
+8FFCD3
+8FFCD4
+8FFCD5
+8FFCD6
+8FFCD7
+8FFCD8
+8FFCD9
+8FFCDA
+8FFCDB
+8FFCDC
+8FFCDD
+8FFCDE
+8FFCDF
+8FFCE0
+8FFCE1
+8FFCE2
+8FFCE3
+8FFCE4
+8FFCE5
+8FFCE6
+8FFCE7
+8FFCE8
+8FFCE9
+8FFCEA
+8FFCEB
+8FFCEC
+8FFCED
+8FFCEE
+8FFCEF
+8FFCF0
+8FFCF1
+8FFCF2
+8FFCF3
+8FFCF4
+8FFCF5
+8FFCF6
+8FFCF7
+8FFCF8
+8FFCF9
+8FFCFA
+8FFCFB
+8FFCFC
+8FFCFD
+8FFCFE
+8FFDA1
+8FFDA2
+8FFDA3
+8FFDA4
+8FFDA5
+8FFDA6
+8FFDA7
+8FFDA8
+8FFDA9
+8FFDAA
+8FFDAB
+8FFDAC
+8FFDAD
+8FFDAE
+8FFDAF
+8FFDB0
+8FFDB1
+8FFDB2
+8FFDB3
+8FFDB4
+8FFDB5
+8FFDB6
+8FFDB7
+8FFDB8
+8FFDB9
+8FFDBA
+8FFDBB
+8FFDBC
+8FFDBD
+8FFDBE
+8FFDBF
+8FFDC0
+8FFDC1
+8FFDC2
+8FFDC3
+8FFDC4
+8FFDC5
+8FFDC6
+8FFDC7
+8FFDC8
+8FFDC9
+8FFDCA
+8FFDCB
+8FFDCC
+8FFDCD
+8FFDCE
+8FFDCF
+8FFDD0
+8FFDD1
+8FFDD2
+8FFDD3
+8FFDD4
+8FFDD5
+8FFDD6
+8FFDD7
+8FFDD8
+8FFDD9
+8FFDDA
+8FFDDB
+8FFDDC
+8FFDDD
+8FFDDE
+8FFDDF
+8FFDE0
+8FFDE1
+8FFDE2
+8FFDE3
+8FFDE4
+8FFDE5
+8FFDE6
+8FFDE7
+8FFDE8
+8FFDE9
+8FFDEA
+8FFDEB
+8FFDEC
+8FFDED
+8FFDEE
+8FFDEF
+8FFDF0
+8FFDF1
+8FFDF2
+8FFDF3
+8FFDF4
+8FFDF5
+8FFDF6
+8FFDF7
+8FFDF8
+8FFDF9
+8FFDFA
+8FFDFB
+8FFDFC
+8FFDFD
+8FFDFE
+8FFEA1
+8FFEA2
+8FFEA3
+8FFEA4
+8FFEA5
+8FFEA6
+8FFEA7
+8FFEA8
+8FFEA9
+8FFEAA
+8FFEAB
+8FFEAC
+8FFEAD
+8FFEAE
+8FFEAF
+8FFEB0
+8FFEB1
+8FFEB2
+8FFEB3
+8FFEB4
+8FFEB5
+8FFEB6
+8FFEB7
+8FFEB8
+8FFEB9
+8FFEBA
+8FFEBB
+8FFEBC
+8FFEBD
+8FFEBE
+8FFEBF
+8FFEC0
+8FFEC1
+8FFEC2
+8FFEC3
+8FFEC4
+8FFEC5
+8FFEC6
+8FFEC7
+8FFEC8
+8FFEC9
+8FFECA
+8FFECB
+8FFECC
+8FFECD
+8FFECE
+8FFECF
+8FFED0
+8FFED1
+8FFED2
+8FFED3
+8FFED4
+8FFED5
+8FFED6
+8FFED7
+8FFED8
+8FFED9
+8FFEDA
+8FFEDB
+8FFEDC
+8FFEDD
+8FFEDE
+8FFEDF
+8FFEE0
+8FFEE1
+8FFEE2
+8FFEE3
+8FFEE4
+8FFEE5
+8FFEE6
+8FFEE7
+8FFEE8
+8FFEE9
+8FFEEA
+8FFEEB
+8FFEEC
+8FFEED
+8FFEEE
+8FFEEF
+8FFEF0
+8FFEF1
+8FFEF2
+8FFEF3
+8FFEF4
+8FFEF5
+8FFEF6
+8FFEF7
+8FFEF8
+8FFEF9
+8FFEFA
+8FFEFB
+8FFEFC
+8FFEFD
+8FFEFE
+CREATE TABLE t2 SELECT CONVERT(c1 USING ucs2) AS c1 FROM t1;
+SELECT HEX(c1) FROM t2;
+HEX(c1)
+005C
+007E
+FFE3
+2015
+FF3C
+FF5E
+2225
+FF0D
+FFE0
+FFE1
+FFE5
+FFE2
+FF5E
+FFE4
+2460
+2461
+2462
+2463
+2464
+2465
+2466
+2467
+2468
+2469
+246A
+246B
+246C
+246D
+246E
+246F
+2470
+2471
+2472
+2473
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+3349
+3314
+3322
+334D
+3318
+3327
+3303
+3336
+3351
+3357
+330D
+3326
+3323
+332B
+334A
+333B
+339C
+339D
+339E
+338E
+338F
+33C4
+33A1
+337B
+301D
+301F
+2116
+33CD
+2121
+32A4
+32A5
+32A6
+32A7
+32A8
+3231
+3232
+3239
+337E
+337D
+337C
+2252
+2261
+222B
+222E
+2211
+221A
+22A5
+2220
+221F
+22BF
+2235
+2229
+222A
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+FFE2
+FFE4
+FF07
+FF02
+3231
+2116
+2121
+2235
+7E8A
+891C
+9348
+9288
+84DC
+4FC9
+70BB
+6631
+68C8
+92F9
+66FB
+5F45
+4E28
+4EE1
+4EFC
+4F00
+4F03
+4F39
+4F56
+4F92
+4F8A
+4F9A
+4F94
+4FCD
+5040
+5022
+4FFF
+501E
+5046
+5070
+5042
+5094
+50F4
+50D8
+514A
+5164
+519D
+51BE
+51EC
+5215
+529C
+52A6
+52C0
+52DB
+5300
+5307
+5324
+5372
+5393
+53B2
+53DD
+FA0E
+549C
+548A
+54A9
+54FF
+5586
+5759
+5765
+57AC
+57C8
+57C7
+FA0F
+FA10
+589E
+58B2
+590B
+5953
+595B
+595D
+5963
+59A4
+59BA
+5B56
+5BC0
+752F
+5BD8
+5BEC
+5C1E
+5CA6
+5CBA
+5CF5
+5D27
+5D53
+FA11
+5D42
+5D6D
+5DB8
+5DB9
+5DD0
+5F21
+5F34
+5F67
+5FB7
+5FDE
+605D
+6085
+608A
+60DE
+60D5
+6120
+60F2
+6111
+6137
+6130
+6198
+6213
+62A6
+63F5
+6460
+649D
+64CE
+654E
+6600
+6615
+663B
+6609
+662E
+661E
+6624
+6665
+6657
+6659
+FA12
+6673
+6699
+66A0
+66B2
+66BF
+66FA
+670E
+F929
+6766
+67BB
+6852
+67C0
+6801
+6844
+68CF
+FA13
+6968
+FA14
+6998
+69E2
+6A30
+6A6B
+6A46
+6A73
+6A7E
+6AE2
+6AE4
+6BD6
+6C3F
+6C5C
+6C86
+6C6F
+6CDA
+6D04
+6D87
+6D6F
+6D96
+6DAC
+6DCF
+6DF8
+6DF2
+6DFC
+6E39
+6E5C
+6E27
+6E3C
+6EBF
+6F88
+6FB5
+6FF5
+7005
+7007
+7028
+7085
+70AB
+710F
+7104
+715C
+7146
+7147
+FA15
+71C1
+71FE
+72B1
+72BE
+7324
+FA16
+7377
+73BD
+73C9
+73D6
+73E3
+73D2
+7407
+73F5
+7426
+742A
+7429
+742E
+7462
+7489
+749F
+7501
+756F
+7682
+769C
+769E
+769B
+76A6
+FA17
+7746
+52AF
+7821
+784E
+7864
+787A
+7930
+FA18
+FA19
+FA1A
+7994
+FA1B
+799B
+7AD1
+7AE7
+FA1C
+7AEB
+7B9E
+FA1D
+7D48
+7D5C
+7DB7
+7DA0
+7DD6
+7E52
+7F47
+7FA1
+FA1E
+8301
+8362
+837F
+83C7
+83F6
+8448
+84B4
+8553
+8559
+856B
+FA1F
+85B0
+FA20
+FA21
+8807
+88F5
+8A12
+8A37
+8A79
+8AA7
+8ABE
+8ADF
+FA22
+8AF6
+8B53
+8B7F
+8CF0
+8CF4
+8D12
+8D76
+FA23
+8ECF
+FA24
+FA25
+9067
+90DE
+FA26
+9115
+9127
+91DA
+91D7
+91DE
+91ED
+91EE
+91E4
+91E5
+9206
+9210
+920A
+923A
+9240
+923C
+924E
+9259
+9251
+9239
+9267
+92A7
+9277
+9278
+92E7
+92D7
+92D9
+92D0
+FA27
+92D5
+92E0
+92D3
+9325
+9321
+92FB
+FA28
+931E
+92FF
+931D
+9302
+9370
+9357
+93A4
+93C6
+93DE
+93F8
+9431
+9445
+9448
+9592
+F9DC
+FA29
+969D
+96AF
+9733
+973B
+9743
+974D
+974F
+9751
+9755
+9857
+9865
+FA2A
+FA2B
+9927
+FA2C
+999E
+9A4E
+9AD9
+9ADC
+9B75
+9B72
+9B8F
+9BB1
+9BBB
+9C00
+9D70
+9D6B
+FA2D
+9E19
+9ED1
+E000
+E001
+E002
+E003
+E004
+E005
+E006
+E007
+E008
+E009
+E00A
+E00B
+E00C
+E00D
+E00E
+E00F
+E010
+E011
+E012
+E013
+E014
+E015
+E016
+E017
+E018
+E019
+E01A
+E01B
+E01C
+E01D
+E01E
+E01F
+E020
+E021
+E022
+E023
+E024
+E025
+E026
+E027
+E028
+E029
+E02A
+E02B
+E02C
+E02D
+E02E
+E02F
+E030
+E031
+E032
+E033
+E034
+E035
+E036
+E037
+E038
+E039
+E03A
+E03B
+E03C
+E03D
+E03E
+E03F
+E040
+E041
+E042
+E043
+E044
+E045
+E046
+E047
+E048
+E049
+E04A
+E04B
+E04C
+E04D
+E04E
+E04F
+E050
+E051
+E052
+E053
+E054
+E055
+E056
+E057
+E058
+E059
+E05A
+E05B
+E05C
+E05D
+E05E
+E05F
+E060
+E061
+E062
+E063
+E064
+E065
+E066
+E067
+E068
+E069
+E06A
+E06B
+E06C
+E06D
+E06E
+E06F
+E070
+E071
+E072
+E073
+E074
+E075
+E076
+E077
+E078
+E079
+E07A
+E07B
+E07C
+E07D
+E07E
+E07F
+E080
+E081
+E082
+E083
+E084
+E085
+E086
+E087
+E088
+E089
+E08A
+E08B
+E08C
+E08D
+E08E
+E08F
+E090
+E091
+E092
+E093
+E094
+E095
+E096
+E097
+E098
+E099
+E09A
+E09B
+E09C
+E09D
+E09E
+E09F
+E0A0
+E0A1
+E0A2
+E0A3
+E0A4
+E0A5
+E0A6
+E0A7
+E0A8
+E0A9
+E0AA
+E0AB
+E0AC
+E0AD
+E0AE
+E0AF
+E0B0
+E0B1
+E0B2
+E0B3
+E0B4
+E0B5
+E0B6
+E0B7
+E0B8
+E0B9
+E0BA
+E0BB
+E0BC
+E0BD
+E0BE
+E0BF
+E0C0
+E0C1
+E0C2
+E0C3
+E0C4
+E0C5
+E0C6
+E0C7
+E0C8
+E0C9
+E0CA
+E0CB
+E0CC
+E0CD
+E0CE
+E0CF
+E0D0
+E0D1
+E0D2
+E0D3
+E0D4
+E0D5
+E0D6
+E0D7
+E0D8
+E0D9
+E0DA
+E0DB
+E0DC
+E0DD
+E0DE
+E0DF
+E0E0
+E0E1
+E0E2
+E0E3
+E0E4
+E0E5
+E0E6
+E0E7
+E0E8
+E0E9
+E0EA
+E0EB
+E0EC
+E0ED
+E0EE
+E0EF
+E0F0
+E0F1
+E0F2
+E0F3
+E0F4
+E0F5
+E0F6
+E0F7
+E0F8
+E0F9
+E0FA
+E0FB
+E0FC
+E0FD
+E0FE
+E0FF
+E100
+E101
+E102
+E103
+E104
+E105
+E106
+E107
+E108
+E109
+E10A
+E10B
+E10C
+E10D
+E10E
+E10F
+E110
+E111
+E112
+E113
+E114
+E115
+E116
+E117
+E118
+E119
+E11A
+E11B
+E11C
+E11D
+E11E
+E11F
+E120
+E121
+E122
+E123
+E124
+E125
+E126
+E127
+E128
+E129
+E12A
+E12B
+E12C
+E12D
+E12E
+E12F
+E130
+E131
+E132
+E133
+E134
+E135
+E136
+E137
+E138
+E139
+E13A
+E13B
+E13C
+E13D
+E13E
+E13F
+E140
+E141
+E142
+E143
+E144
+E145
+E146
+E147
+E148
+E149
+E14A
+E14B
+E14C
+E14D
+E14E
+E14F
+E150
+E151
+E152
+E153
+E154
+E155
+E156
+E157
+E158
+E159
+E15A
+E15B
+E15C
+E15D
+E15E
+E15F
+E160
+E161
+E162
+E163
+E164
+E165
+E166
+E167
+E168
+E169
+E16A
+E16B
+E16C
+E16D
+E16E
+E16F
+E170
+E171
+E172
+E173
+E174
+E175
+E176
+E177
+E178
+E179
+E17A
+E17B
+E17C
+E17D
+E17E
+E17F
+E180
+E181
+E182
+E183
+E184
+E185
+E186
+E187
+E188
+E189
+E18A
+E18B
+E18C
+E18D
+E18E
+E18F
+E190
+E191
+E192
+E193
+E194
+E195
+E196
+E197
+E198
+E199
+E19A
+E19B
+E19C
+E19D
+E19E
+E19F
+E1A0
+E1A1
+E1A2
+E1A3
+E1A4
+E1A5
+E1A6
+E1A7
+E1A8
+E1A9
+E1AA
+E1AB
+E1AC
+E1AD
+E1AE
+E1AF
+E1B0
+E1B1
+E1B2
+E1B3
+E1B4
+E1B5
+E1B6
+E1B7
+E1B8
+E1B9
+E1BA
+E1BB
+E1BC
+E1BD
+E1BE
+E1BF
+E1C0
+E1C1
+E1C2
+E1C3
+E1C4
+E1C5
+E1C6
+E1C7
+E1C8
+E1C9
+E1CA
+E1CB
+E1CC
+E1CD
+E1CE
+E1CF
+E1D0
+E1D1
+E1D2
+E1D3
+E1D4
+E1D5
+E1D6
+E1D7
+E1D8
+E1D9
+E1DA
+E1DB
+E1DC
+E1DD
+E1DE
+E1DF
+E1E0
+E1E1
+E1E2
+E1E3
+E1E4
+E1E5
+E1E6
+E1E7
+E1E8
+E1E9
+E1EA
+E1EB
+E1EC
+E1ED
+E1EE
+E1EF
+E1F0
+E1F1
+E1F2
+E1F3
+E1F4
+E1F5
+E1F6
+E1F7
+E1F8
+E1F9
+E1FA
+E1FB
+E1FC
+E1FD
+E1FE
+E1FF
+E200
+E201
+E202
+E203
+E204
+E205
+E206
+E207
+E208
+E209
+E20A
+E20B
+E20C
+E20D
+E20E
+E20F
+E210
+E211
+E212
+E213
+E214
+E215
+E216
+E217
+E218
+E219
+E21A
+E21B
+E21C
+E21D
+E21E
+E21F
+E220
+E221
+E222
+E223
+E224
+E225
+E226
+E227
+E228
+E229
+E22A
+E22B
+E22C
+E22D
+E22E
+E22F
+E230
+E231
+E232
+E233
+E234
+E235
+E236
+E237
+E238
+E239
+E23A
+E23B
+E23C
+E23D
+E23E
+E23F
+E240
+E241
+E242
+E243
+E244
+E245
+E246
+E247
+E248
+E249
+E24A
+E24B
+E24C
+E24D
+E24E
+E24F
+E250
+E251
+E252
+E253
+E254
+E255
+E256
+E257
+E258
+E259
+E25A
+E25B
+E25C
+E25D
+E25E
+E25F
+E260
+E261
+E262
+E263
+E264
+E265
+E266
+E267
+E268
+E269
+E26A
+E26B
+E26C
+E26D
+E26E
+E26F
+E270
+E271
+E272
+E273
+E274
+E275
+E276
+E277
+E278
+E279
+E27A
+E27B
+E27C
+E27D
+E27E
+E27F
+E280
+E281
+E282
+E283
+E284
+E285
+E286
+E287
+E288
+E289
+E28A
+E28B
+E28C
+E28D
+E28E
+E28F
+E290
+E291
+E292
+E293
+E294
+E295
+E296
+E297
+E298
+E299
+E29A
+E29B
+E29C
+E29D
+E29E
+E29F
+E2A0
+E2A1
+E2A2
+E2A3
+E2A4
+E2A5
+E2A6
+E2A7
+E2A8
+E2A9
+E2AA
+E2AB
+E2AC
+E2AD
+E2AE
+E2AF
+E2B0
+E2B1
+E2B2
+E2B3
+E2B4
+E2B5
+E2B6
+E2B7
+E2B8
+E2B9
+E2BA
+E2BB
+E2BC
+E2BD
+E2BE
+E2BF
+E2C0
+E2C1
+E2C2
+E2C3
+E2C4
+E2C5
+E2C6
+E2C7
+E2C8
+E2C9
+E2CA
+E2CB
+E2CC
+E2CD
+E2CE
+E2CF
+E2D0
+E2D1
+E2D2
+E2D3
+E2D4
+E2D5
+E2D6
+E2D7
+E2D8
+E2D9
+E2DA
+E2DB
+E2DC
+E2DD
+E2DE
+E2DF
+E2E0
+E2E1
+E2E2
+E2E3
+E2E4
+E2E5
+E2E6
+E2E7
+E2E8
+E2E9
+E2EA
+E2EB
+E2EC
+E2ED
+E2EE
+E2EF
+E2F0
+E2F1
+E2F2
+E2F3
+E2F4
+E2F5
+E2F6
+E2F7
+E2F8
+E2F9
+E2FA
+E2FB
+E2FC
+E2FD
+E2FE
+E2FF
+E300
+E301
+E302
+E303
+E304
+E305
+E306
+E307
+E308
+E309
+E30A
+E30B
+E30C
+E30D
+E30E
+E30F
+E310
+E311
+E312
+E313
+E314
+E315
+E316
+E317
+E318
+E319
+E31A
+E31B
+E31C
+E31D
+E31E
+E31F
+E320
+E321
+E322
+E323
+E324
+E325
+E326
+E327
+E328
+E329
+E32A
+E32B
+E32C
+E32D
+E32E
+E32F
+E330
+E331
+E332
+E333
+E334
+E335
+E336
+E337
+E338
+E339
+E33A
+E33B
+E33C
+E33D
+E33E
+E33F
+E340
+E341
+E342
+E343
+E344
+E345
+E346
+E347
+E348
+E349
+E34A
+E34B
+E34C
+E34D
+E34E
+E34F
+E350
+E351
+E352
+E353
+E354
+E355
+E356
+E357
+E358
+E359
+E35A
+E35B
+E35C
+E35D
+E35E
+E35F
+E360
+E361
+E362
+E363
+E364
+E365
+E366
+E367
+E368
+E369
+E36A
+E36B
+E36C
+E36D
+E36E
+E36F
+E370
+E371
+E372
+E373
+E374
+E375
+E376
+E377
+E378
+E379
+E37A
+E37B
+E37C
+E37D
+E37E
+E37F
+E380
+E381
+E382
+E383
+E384
+E385
+E386
+E387
+E388
+E389
+E38A
+E38B
+E38C
+E38D
+E38E
+E38F
+E390
+E391
+E392
+E393
+E394
+E395
+E396
+E397
+E398
+E399
+E39A
+E39B
+E39C
+E39D
+E39E
+E39F
+E3A0
+E3A1
+E3A2
+E3A3
+E3A4
+E3A5
+E3A6
+E3A7
+E3A8
+E3A9
+E3AA
+E3AB
+E3AC
+E3AD
+E3AE
+E3AF
+E3B0
+E3B1
+E3B2
+E3B3
+E3B4
+E3B5
+E3B6
+E3B7
+E3B8
+E3B9
+E3BA
+E3BB
+E3BC
+E3BD
+E3BE
+E3BF
+E3C0
+E3C1
+E3C2
+E3C3
+E3C4
+E3C5
+E3C6
+E3C7
+E3C8
+E3C9
+E3CA
+E3CB
+E3CC
+E3CD
+E3CE
+E3CF
+E3D0
+E3D1
+E3D2
+E3D3
+E3D4
+E3D5
+E3D6
+E3D7
+E3D8
+E3D9
+E3DA
+E3DB
+E3DC
+E3DD
+E3DE
+E3DF
+E3E0
+E3E1
+E3E2
+E3E3
+E3E4
+E3E5
+E3E6
+E3E7
+E3E8
+E3E9
+E3EA
+E3EB
+E3EC
+E3ED
+E3EE
+E3EF
+E3F0
+E3F1
+E3F2
+E3F3
+E3F4
+E3F5
+E3F6
+E3F7
+E3F8
+E3F9
+E3FA
+E3FB
+E3FC
+E3FD
+E3FE
+E3FF
+E400
+E401
+E402
+E403
+E404
+E405
+E406
+E407
+E408
+E409
+E40A
+E40B
+E40C
+E40D
+E40E
+E40F
+E410
+E411
+E412
+E413
+E414
+E415
+E416
+E417
+E418
+E419
+E41A
+E41B
+E41C
+E41D
+E41E
+E41F
+E420
+E421
+E422
+E423
+E424
+E425
+E426
+E427
+E428
+E429
+E42A
+E42B
+E42C
+E42D
+E42E
+E42F
+E430
+E431
+E432
+E433
+E434
+E435
+E436
+E437
+E438
+E439
+E43A
+E43B
+E43C
+E43D
+E43E
+E43F
+E440
+E441
+E442
+E443
+E444
+E445
+E446
+E447
+E448
+E449
+E44A
+E44B
+E44C
+E44D
+E44E
+E44F
+E450
+E451
+E452
+E453
+E454
+E455
+E456
+E457
+E458
+E459
+E45A
+E45B
+E45C
+E45D
+E45E
+E45F
+E460
+E461
+E462
+E463
+E464
+E465
+E466
+E467
+E468
+E469
+E46A
+E46B
+E46C
+E46D
+E46E
+E46F
+E470
+E471
+E472
+E473
+E474
+E475
+E476
+E477
+E478
+E479
+E47A
+E47B
+E47C
+E47D
+E47E
+E47F
+E480
+E481
+E482
+E483
+E484
+E485
+E486
+E487
+E488
+E489
+E48A
+E48B
+E48C
+E48D
+E48E
+E48F
+E490
+E491
+E492
+E493
+E494
+E495
+E496
+E497
+E498
+E499
+E49A
+E49B
+E49C
+E49D
+E49E
+E49F
+E4A0
+E4A1
+E4A2
+E4A3
+E4A4
+E4A5
+E4A6
+E4A7
+E4A8
+E4A9
+E4AA
+E4AB
+E4AC
+E4AD
+E4AE
+E4AF
+E4B0
+E4B1
+E4B2
+E4B3
+E4B4
+E4B5
+E4B6
+E4B7
+E4B8
+E4B9
+E4BA
+E4BB
+E4BC
+E4BD
+E4BE
+E4BF
+E4C0
+E4C1
+E4C2
+E4C3
+E4C4
+E4C5
+E4C6
+E4C7
+E4C8
+E4C9
+E4CA
+E4CB
+E4CC
+E4CD
+E4CE
+E4CF
+E4D0
+E4D1
+E4D2
+E4D3
+E4D4
+E4D5
+E4D6
+E4D7
+E4D8
+E4D9
+E4DA
+E4DB
+E4DC
+E4DD
+E4DE
+E4DF
+E4E0
+E4E1
+E4E2
+E4E3
+E4E4
+E4E5
+E4E6
+E4E7
+E4E8
+E4E9
+E4EA
+E4EB
+E4EC
+E4ED
+E4EE
+E4EF
+E4F0
+E4F1
+E4F2
+E4F3
+E4F4
+E4F5
+E4F6
+E4F7
+E4F8
+E4F9
+E4FA
+E4FB
+E4FC
+E4FD
+E4FE
+E4FF
+E500
+E501
+E502
+E503
+E504
+E505
+E506
+E507
+E508
+E509
+E50A
+E50B
+E50C
+E50D
+E50E
+E50F
+E510
+E511
+E512
+E513
+E514
+E515
+E516
+E517
+E518
+E519
+E51A
+E51B
+E51C
+E51D
+E51E
+E51F
+E520
+E521
+E522
+E523
+E524
+E525
+E526
+E527
+E528
+E529
+E52A
+E52B
+E52C
+E52D
+E52E
+E52F
+E530
+E531
+E532
+E533
+E534
+E535
+E536
+E537
+E538
+E539
+E53A
+E53B
+E53C
+E53D
+E53E
+E53F
+E540
+E541
+E542
+E543
+E544
+E545
+E546
+E547
+E548
+E549
+E54A
+E54B
+E54C
+E54D
+E54E
+E54F
+E550
+E551
+E552
+E553
+E554
+E555
+E556
+E557
+E558
+E559
+E55A
+E55B
+E55C
+E55D
+E55E
+E55F
+E560
+E561
+E562
+E563
+E564
+E565
+E566
+E567
+E568
+E569
+E56A
+E56B
+E56C
+E56D
+E56E
+E56F
+E570
+E571
+E572
+E573
+E574
+E575
+E576
+E577
+E578
+E579
+E57A
+E57B
+E57C
+E57D
+E57E
+E57F
+E580
+E581
+E582
+E583
+E584
+E585
+E586
+E587
+E588
+E589
+E58A
+E58B
+E58C
+E58D
+E58E
+E58F
+E590
+E591
+E592
+E593
+E594
+E595
+E596
+E597
+E598
+E599
+E59A
+E59B
+E59C
+E59D
+E59E
+E59F
+E5A0
+E5A1
+E5A2
+E5A3
+E5A4
+E5A5
+E5A6
+E5A7
+E5A8
+E5A9
+E5AA
+E5AB
+E5AC
+E5AD
+E5AE
+E5AF
+E5B0
+E5B1
+E5B2
+E5B3
+E5B4
+E5B5
+E5B6
+E5B7
+E5B8
+E5B9
+E5BA
+E5BB
+E5BC
+E5BD
+E5BE
+E5BF
+E5C0
+E5C1
+E5C2
+E5C3
+E5C4
+E5C5
+E5C6
+E5C7
+E5C8
+E5C9
+E5CA
+E5CB
+E5CC
+E5CD
+E5CE
+E5CF
+E5D0
+E5D1
+E5D2
+E5D3
+E5D4
+E5D5
+E5D6
+E5D7
+E5D8
+E5D9
+E5DA
+E5DB
+E5DC
+E5DD
+E5DE
+E5DF
+E5E0
+E5E1
+E5E2
+E5E3
+E5E4
+E5E5
+E5E6
+E5E7
+E5E8
+E5E9
+E5EA
+E5EB
+E5EC
+E5ED
+E5EE
+E5EF
+E5F0
+E5F1
+E5F2
+E5F3
+E5F4
+E5F5
+E5F6
+E5F7
+E5F8
+E5F9
+E5FA
+E5FB
+E5FC
+E5FD
+E5FE
+E5FF
+E600
+E601
+E602
+E603
+E604
+E605
+E606
+E607
+E608
+E609
+E60A
+E60B
+E60C
+E60D
+E60E
+E60F
+E610
+E611
+E612
+E613
+E614
+E615
+E616
+E617
+E618
+E619
+E61A
+E61B
+E61C
+E61D
+E61E
+E61F
+E620
+E621
+E622
+E623
+E624
+E625
+E626
+E627
+E628
+E629
+E62A
+E62B
+E62C
+E62D
+E62E
+E62F
+E630
+E631
+E632
+E633
+E634
+E635
+E636
+E637
+E638
+E639
+E63A
+E63B
+E63C
+E63D
+E63E
+E63F
+E640
+E641
+E642
+E643
+E644
+E645
+E646
+E647
+E648
+E649
+E64A
+E64B
+E64C
+E64D
+E64E
+E64F
+E650
+E651
+E652
+E653
+E654
+E655
+E656
+E657
+E658
+E659
+E65A
+E65B
+E65C
+E65D
+E65E
+E65F
+E660
+E661
+E662
+E663
+E664
+E665
+E666
+E667
+E668
+E669
+E66A
+E66B
+E66C
+E66D
+E66E
+E66F
+E670
+E671
+E672
+E673
+E674
+E675
+E676
+E677
+E678
+E679
+E67A
+E67B
+E67C
+E67D
+E67E
+E67F
+E680
+E681
+E682
+E683
+E684
+E685
+E686
+E687
+E688
+E689
+E68A
+E68B
+E68C
+E68D
+E68E
+E68F
+E690
+E691
+E692
+E693
+E694
+E695
+E696
+E697
+E698
+E699
+E69A
+E69B
+E69C
+E69D
+E69E
+E69F
+E6A0
+E6A1
+E6A2
+E6A3
+E6A4
+E6A5
+E6A6
+E6A7
+E6A8
+E6A9
+E6AA
+E6AB
+E6AC
+E6AD
+E6AE
+E6AF
+E6B0
+E6B1
+E6B2
+E6B3
+E6B4
+E6B5
+E6B6
+E6B7
+E6B8
+E6B9
+E6BA
+E6BB
+E6BC
+E6BD
+E6BE
+E6BF
+E6C0
+E6C1
+E6C2
+E6C3
+E6C4
+E6C5
+E6C6
+E6C7
+E6C8
+E6C9
+E6CA
+E6CB
+E6CC
+E6CD
+E6CE
+E6CF
+E6D0
+E6D1
+E6D2
+E6D3
+E6D4
+E6D5
+E6D6
+E6D7
+E6D8
+E6D9
+E6DA
+E6DB
+E6DC
+E6DD
+E6DE
+E6DF
+E6E0
+E6E1
+E6E2
+E6E3
+E6E4
+E6E5
+E6E6
+E6E7
+E6E8
+E6E9
+E6EA
+E6EB
+E6EC
+E6ED
+E6EE
+E6EF
+E6F0
+E6F1
+E6F2
+E6F3
+E6F4
+E6F5
+E6F6
+E6F7
+E6F8
+E6F9
+E6FA
+E6FB
+E6FC
+E6FD
+E6FE
+E6FF
+E700
+E701
+E702
+E703
+E704
+E705
+E706
+E707
+E708
+E709
+E70A
+E70B
+E70C
+E70D
+E70E
+E70F
+E710
+E711
+E712
+E713
+E714
+E715
+E716
+E717
+E718
+E719
+E71A
+E71B
+E71C
+E71D
+E71E
+E71F
+E720
+E721
+E722
+E723
+E724
+E725
+E726
+E727
+E728
+E729
+E72A
+E72B
+E72C
+E72D
+E72E
+E72F
+E730
+E731
+E732
+E733
+E734
+E735
+E736
+E737
+E738
+E739
+E73A
+E73B
+E73C
+E73D
+E73E
+E73F
+E740
+E741
+E742
+E743
+E744
+E745
+E746
+E747
+E748
+E749
+E74A
+E74B
+E74C
+E74D
+E74E
+E74F
+E750
+E751
+E752
+E753
+E754
+E755
+E756
+E757
+CREATE TABLE t3 SELECT CONVERT(c1 USING eucjpms) AS c1 FROM t2;
+SELECT HEX(c1) FROM t3;
+HEX(c1)
+5C
+7E
+A1B1
+A1BD
+A1C0
+A1C1
+A1C2
+A1DD
+A1F1
+A1F2
+A1EF
+A2CC
+A1C1
+8FA2C3
+ADA1
+ADA2
+ADA3
+ADA4
+ADA5
+ADA6
+ADA7
+ADA8
+ADA9
+ADAA
+ADAB
+ADAC
+ADAD
+ADAE
+ADAF
+ADB0
+ADB1
+ADB2
+ADB3
+ADB4
+ADB5
+ADB6
+ADB7
+ADB8
+ADB9
+ADBA
+ADBB
+ADBC
+ADBD
+ADBE
+ADC0
+ADC1
+ADC2
+ADC3
+ADC4
+ADC5
+ADC6
+ADC7
+ADC8
+ADC9
+ADCA
+ADCB
+ADCC
+ADCD
+ADCE
+ADCF
+ADD0
+ADD1
+ADD2
+ADD3
+ADD4
+ADD5
+ADD6
+ADDF
+ADE0
+ADE1
+ADE2
+ADE3
+ADE4
+ADE5
+ADE6
+ADE7
+ADE8
+ADE9
+ADEA
+ADEB
+ADEC
+ADED
+ADEE
+ADEF
+A2E2
+A2E1
+A2E9
+ADF3
+ADF4
+A2E5
+A2DD
+A2DC
+ADF8
+ADF9
+A2E8
+A2C1
+A2C0
+8FF3F3
+8FF3F4
+8FF3F5
+8FF3F6
+8FF3F7
+8FF3F8
+8FF3F9
+8FF3FA
+8FF3FB
+8FF3FC
+ADB5
+ADB6
+ADB7
+ADB8
+ADB9
+ADBA
+ADBB
+ADBC
+ADBD
+ADBE
+A2CC
+8FA2C3
+8FF4A9
+8FF4AA
+ADEA
+ADE2
+ADE4
+A2E8
+8FD4E3
+8FDCDF
+8FE4E9
+8FE3F8
+8FD9A1
+8FB1BB
+8FF4AE
+8FC2AD
+8FC3FC
+8FE4D0
+8FC2BF
+8FBCF4
+8FB0A9
+8FB0C8
+8FF4AF
+8FB0D2
+8FB0D4
+8FB0E3
+8FB0EE
+8FB1A7
+8FB1A3
+8FB1AC
+8FB1A9
+8FB1BE
+8FB1DF
+8FB1D8
+8FB1C8
+8FB1D7
+8FB1E3
+8FB1F4
+8FB1E1
+8FB2A3
+8FF4B0
+8FB2BB
+8FB2E6
+8FB2ED
+8FB2F5
+8FB2FC
+8FF4B1
+8FB3B5
+8FB3D8
+8FB3DB
+8FB3E5
+8FB3EE
+8FB3FB
+8FF4B2
+8FF4B3
+8FB4C0
+8FB4C7
+8FB4D0
+8FB4DE
+8FF4B4
+8FB5AA
+8FF4B5
+8FB5AF
+8FB5C4
+8FB5E8
+8FF4B6
+8FB7C2
+8FB7E4
+8FB7E8
+8FB7E7
+8FF4B7
+8FF4B8
+8FF4B9
+8FB8CE
+8FB8E1
+8FB8F5
+8FB8F7
+8FB8F8
+8FB8FC
+8FB9AF
+8FB9B7
+8FBABE
+8FBADB
+8FCDAA
+8FBAE1
+8FF4BA
+8FBAEB
+8FBBB3
+8FBBB8
+8FF4BB
+8FBBCA
+8FF4BC
+8FF4BD
+8FBBD0
+8FBBDE
+8FBBF4
+8FBBF5
+8FBBF9
+8FBCE4
+8FBCED
+8FBCFE
+8FF4BE
+8FBDC2
+8FBDE7
+8FF4BF
+8FBDF0
+8FBEB0
+8FBEAC
+8FF4C0
+8FBEB3
+8FBEBD
+8FBECD
+8FBEC9
+8FBEE4
+8FBFA8
+8FBFC9
+8FC0C4
+8FC0E4
+8FC0F4
+8FC1A6
+8FF4C1
+8FC1F5
+8FC1FC
+8FF4C2
+8FC1F8
+8FC2AB
+8FC2A1
+8FC2A5
+8FF4C3
+8FC2B8
+8FC2BA
+8FF4C4
+8FC2C4
+8FC2D2
+8FC2D7
+8FC2DB
+8FC2DE
+8FC2ED
+8FC2F0
+8FF4C5
+8FC3A1
+8FC3B5
+8FC3C9
+8FC3B9
+8FF4C6
+8FC3D8
+8FC3FE
+8FF4C7
+8FC4CC
+8FF4C8
+8FC4D9
+8FC4EA
+8FC4FD
+8FF4C9
+8FC5A7
+8FC5B5
+8FC5B6
+8FF4CA
+8FC5D5
+8FC6B8
+8FC6D7
+8FC6E0
+8FC6EA
+8FC6E3
+8FC7A1
+8FC7AB
+8FC7C7
+8FC7C3
+8FC7CB
+8FC7CF
+8FC7D9
+8FF4CB
+8FF4CC
+8FC7E6
+8FC7EE
+8FC7FC
+8FC7EB
+8FC7F0
+8FC8B1
+8FC8E5
+8FC8F8
+8FC9A6
+8FC9AB
+8FC9AD
+8FF4CD
+8FC9CA
+8FC9D3
+8FC9E9
+8FC9E3
+8FC9FC
+8FC9F4
+8FC9F5
+8FF4CE
+8FCAB3
+8FCABD
+8FCAEF
+8FCAF1
+8FCBAE
+8FF4CF
+8FCBCA
+8FCBE6
+8FCBEA
+8FCBF0
+8FCBF4
+8FCBEE
+8FCCA5
+8FCBF9
+8FCCAB
+8FCCAE
+8FCCAD
+8FCCB2
+8FCCC2
+8FCCD0
+8FCCD9
+8FF4D0
+8FCDBB
+8FF4D1
+8FCEBB
+8FF4D2
+8FCEBA
+8FCEC3
+8FF4D3
+8FCEF2
+8FB3DD
+8FCFD5
+8FCFE2
+8FCFE9
+8FCFED
+8FF4D4
+8FF4D5
+8FF4D6
+8FF4D7
+8FD0E5
+8FF4D8
+8FD0E9
+8FD1E8
+8FF4D9
+8FF4DA
+8FD1EC
+8FD2BB
+8FF4DB
+8FD3E1
+8FD3E8
+8FD4A7
+8FF4DC
+8FF4DD
+8FD4D4
+8FD4F2
+8FD5AE
+8FF4DE
+8FD7DE
+8FF4DF
+8FD8A2
+8FD8B7
+8FD8C1
+8FD8D1
+8FD8F4
+8FD9C6
+8FD9C8
+8FD9D1
+8FF4E0
+8FF4E1
+8FF4E2
+8FF4E3
+8FF4E4
+8FDCD3
+8FDDC8
+8FDDD4
+8FDDEA
+8FDDFA
+8FDEA4
+8FDEB0
+8FF4E5
+8FDEB5
+8FDECB
+8FF4E6
+8FDFB9
+8FF4E7
+8FDFC3
+8FF4E8
+8FF4E9
+8FE0D9
+8FF4EA
+8FF4EB
+8FE1E2
+8FF4EC
+8FF4ED
+8FF4EE
+8FE2C7
+8FE3A8
+8FE3A6
+8FE3A9
+8FE3AF
+8FE3B0
+8FE3AA
+8FE3AB
+8FE3BC
+8FE3C1
+8FE3BF
+8FE3D5
+8FE3D8
+8FE3D6
+8FE3DF
+8FE3E3
+8FE3E1
+8FE3D4
+8FE3E9
+8FE4A6
+8FE3F1
+8FE3F2
+8FE4CB
+8FE4C1
+8FE4C3
+8FE4BE
+8FF4EF
+8FE4C0
+8FE4C7
+8FE4BF
+8FE4E0
+8FE4DE
+8FE4D1
+8FF4F0
+8FE4DC
+8FE4D2
+8FE4DB
+8FE4D4
+8FE4FA
+8FE4EF
+8FE5B3
+8FE5BF
+8FE5C9
+8FE5D0
+8FE5E2
+8FE5EA
+8FE5EB
+8FF4F1
+8FF4F2
+8FF4F3
+8FE6E8
+8FE6EF
+8FE7AC
+8FF4F4
+8FE7AE
+8FF4F5
+8FE7B1
+8FF4F6
+8FE7B2
+8FE8B1
+8FE8B6
+8FF4F7
+8FF4F8
+8FE8DD
+8FF4F9
+8FF4FA
+8FE9D1
+8FF4FB
+8FE9ED
+8FEACD
+8FF4FC
+8FEADB
+8FEAE6
+8FEAEA
+8FEBA5
+8FEBFB
+8FEBFA
+8FF4FD
+8FECD6
+8FF4FE
+F5A1
+F5A2
+F5A3
+F5A4
+F5A5
+F5A6
+F5A7
+F5A8
+F5A9
+F5AA
+F5AB
+F5AC
+F5AD
+F5AE
+F5AF
+F5B0
+F5B1
+F5B2
+F5B3
+F5B4
+F5B5
+F5B6
+F5B7
+F5B8
+F5B9
+F5BA
+F5BB
+F5BC
+F5BD
+F5BE
+F5BF
+F5C0
+F5C1
+F5C2
+F5C3
+F5C4
+F5C5
+F5C6
+F5C7
+F5C8
+F5C9
+F5CA
+F5CB
+F5CC
+F5CD
+F5CE
+F5CF
+F5D0
+F5D1
+F5D2
+F5D3
+F5D4
+F5D5
+F5D6
+F5D7
+F5D8
+F5D9
+F5DA
+F5DB
+F5DC
+F5DD
+F5DE
+F5DF
+F5E0
+F5E1
+F5E2
+F5E3
+F5E4
+F5E5
+F5E6
+F5E7
+F5E8
+F5E9
+F5EA
+F5EB
+F5EC
+F5ED
+F5EE
+F5EF
+F5F0
+F5F1
+F5F2
+F5F3
+F5F4
+F5F5
+F5F6
+F5F7
+F5F8
+F5F9
+F5FA
+F5FB
+F5FC
+F5FD
+F5FE
+F6A1
+F6A2
+F6A3
+F6A4
+F6A5
+F6A6
+F6A7
+F6A8
+F6A9
+F6AA
+F6AB
+F6AC
+F6AD
+F6AE
+F6AF
+F6B0
+F6B1
+F6B2
+F6B3
+F6B4
+F6B5
+F6B6
+F6B7
+F6B8
+F6B9
+F6BA
+F6BB
+F6BC
+F6BD
+F6BE
+F6BF
+F6C0
+F6C1
+F6C2
+F6C3
+F6C4
+F6C5
+F6C6
+F6C7
+F6C8
+F6C9
+F6CA
+F6CB
+F6CC
+F6CD
+F6CE
+F6CF
+F6D0
+F6D1
+F6D2
+F6D3
+F6D4
+F6D5
+F6D6
+F6D7
+F6D8
+F6D9
+F6DA
+F6DB
+F6DC
+F6DD
+F6DE
+F6DF
+F6E0
+F6E1
+F6E2
+F6E3
+F6E4
+F6E5
+F6E6
+F6E7
+F6E8
+F6E9
+F6EA
+F6EB
+F6EC
+F6ED
+F6EE
+F6EF
+F6F0
+F6F1
+F6F2
+F6F3
+F6F4
+F6F5
+F6F6
+F6F7
+F6F8
+F6F9
+F6FA
+F6FB
+F6FC
+F6FD
+F6FE
+F7A1
+F7A2
+F7A3
+F7A4
+F7A5
+F7A6
+F7A7
+F7A8
+F7A9
+F7AA
+F7AB
+F7AC
+F7AD
+F7AE
+F7AF
+F7B0
+F7B1
+F7B2
+F7B3
+F7B4
+F7B5
+F7B6
+F7B7
+F7B8
+F7B9
+F7BA
+F7BB
+F7BC
+F7BD
+F7BE
+F7BF
+F7C0
+F7C1
+F7C2
+F7C3
+F7C4
+F7C5
+F7C6
+F7C7
+F7C8
+F7C9
+F7CA
+F7CB
+F7CC
+F7CD
+F7CE
+F7CF
+F7D0
+F7D1
+F7D2
+F7D3
+F7D4
+F7D5
+F7D6
+F7D7
+F7D8
+F7D9
+F7DA
+F7DB
+F7DC
+F7DD
+F7DE
+F7DF
+F7E0
+F7E1
+F7E2
+F7E3
+F7E4
+F7E5
+F7E6
+F7E7
+F7E8
+F7E9
+F7EA
+F7EB
+F7EC
+F7ED
+F7EE
+F7EF
+F7F0
+F7F1
+F7F2
+F7F3
+F7F4
+F7F5
+F7F6
+F7F7
+F7F8
+F7F9
+F7FA
+F7FB
+F7FC
+F7FD
+F7FE
+F8A1
+F8A2
+F8A3
+F8A4
+F8A5
+F8A6
+F8A7
+F8A8
+F8A9
+F8AA
+F8AB
+F8AC
+F8AD
+F8AE
+F8AF
+F8B0
+F8B1
+F8B2
+F8B3
+F8B4
+F8B5
+F8B6
+F8B7
+F8B8
+F8B9
+F8BA
+F8BB
+F8BC
+F8BD
+F8BE
+F8BF
+F8C0
+F8C1
+F8C2
+F8C3
+F8C4
+F8C5
+F8C6
+F8C7
+F8C8
+F8C9
+F8CA
+F8CB
+F8CC
+F8CD
+F8CE
+F8CF
+F8D0
+F8D1
+F8D2
+F8D3
+F8D4
+F8D5
+F8D6
+F8D7
+F8D8
+F8D9
+F8DA
+F8DB
+F8DC
+F8DD
+F8DE
+F8DF
+F8E0
+F8E1
+F8E2
+F8E3
+F8E4
+F8E5
+F8E6
+F8E7
+F8E8
+F8E9
+F8EA
+F8EB
+F8EC
+F8ED
+F8EE
+F8EF
+F8F0
+F8F1
+F8F2
+F8F3
+F8F4
+F8F5
+F8F6
+F8F7
+F8F8
+F8F9
+F8FA
+F8FB
+F8FC
+F8FD
+F8FE
+F9A1
+F9A2
+F9A3
+F9A4
+F9A5
+F9A6
+F9A7
+F9A8
+F9A9
+F9AA
+F9AB
+F9AC
+F9AD
+F9AE
+F9AF
+F9B0
+F9B1
+F9B2
+F9B3
+F9B4
+F9B5
+F9B6
+F9B7
+F9B8
+F9B9
+F9BA
+F9BB
+F9BC
+F9BD
+F9BE
+F9BF
+F9C0
+F9C1
+F9C2
+F9C3
+F9C4
+F9C5
+F9C6
+F9C7
+F9C8
+F9C9
+F9CA
+F9CB
+F9CC
+F9CD
+F9CE
+F9CF
+F9D0
+F9D1
+F9D2
+F9D3
+F9D4
+F9D5
+F9D6
+F9D7
+F9D8
+F9D9
+F9DA
+F9DB
+F9DC
+F9DD
+F9DE
+F9DF
+F9E0
+F9E1
+F9E2
+F9E3
+F9E4
+F9E5
+F9E6
+F9E7
+F9E8
+F9E9
+F9EA
+F9EB
+F9EC
+F9ED
+F9EE
+F9EF
+F9F0
+F9F1
+F9F2
+F9F3
+F9F4
+F9F5
+F9F6
+F9F7
+F9F8
+F9F9
+F9FA
+F9FB
+F9FC
+F9FD
+F9FE
+FAA1
+FAA2
+FAA3
+FAA4
+FAA5
+FAA6
+FAA7
+FAA8
+FAA9
+FAAA
+FAAB
+FAAC
+FAAD
+FAAE
+FAAF
+FAB0
+FAB1
+FAB2
+FAB3
+FAB4
+FAB5
+FAB6
+FAB7
+FAB8
+FAB9
+FABA
+FABB
+FABC
+FABD
+FABE
+FABF
+FAC0
+FAC1
+FAC2
+FAC3
+FAC4
+FAC5
+FAC6
+FAC7
+FAC8
+FAC9
+FACA
+FACB
+FACC
+FACD
+FACE
+FACF
+FAD0
+FAD1
+FAD2
+FAD3
+FAD4
+FAD5
+FAD6
+FAD7
+FAD8
+FAD9
+FADA
+FADB
+FADC
+FADD
+FADE
+FADF
+FAE0
+FAE1
+FAE2
+FAE3
+FAE4
+FAE5
+FAE6
+FAE7
+FAE8
+FAE9
+FAEA
+FAEB
+FAEC
+FAED
+FAEE
+FAEF
+FAF0
+FAF1
+FAF2
+FAF3
+FAF4
+FAF5
+FAF6
+FAF7
+FAF8
+FAF9
+FAFA
+FAFB
+FAFC
+FAFD
+FAFE
+FBA1
+FBA2
+FBA3
+FBA4
+FBA5
+FBA6
+FBA7
+FBA8
+FBA9
+FBAA
+FBAB
+FBAC
+FBAD
+FBAE
+FBAF
+FBB0
+FBB1
+FBB2
+FBB3
+FBB4
+FBB5
+FBB6
+FBB7
+FBB8
+FBB9
+FBBA
+FBBB
+FBBC
+FBBD
+FBBE
+FBBF
+FBC0
+FBC1
+FBC2
+FBC3
+FBC4
+FBC5
+FBC6
+FBC7
+FBC8
+FBC9
+FBCA
+FBCB
+FBCC
+FBCD
+FBCE
+FBCF
+FBD0
+FBD1
+FBD2
+FBD3
+FBD4
+FBD5
+FBD6
+FBD7
+FBD8
+FBD9
+FBDA
+FBDB
+FBDC
+FBDD
+FBDE
+FBDF
+FBE0
+FBE1
+FBE2
+FBE3
+FBE4
+FBE5
+FBE6
+FBE7
+FBE8
+FBE9
+FBEA
+FBEB
+FBEC
+FBED
+FBEE
+FBEF
+FBF0
+FBF1
+FBF2
+FBF3
+FBF4
+FBF5
+FBF6
+FBF7
+FBF8
+FBF9
+FBFA
+FBFB
+FBFC
+FBFD
+FBFE
+FCA1
+FCA2
+FCA3
+FCA4
+FCA5
+FCA6
+FCA7
+FCA8
+FCA9
+FCAA
+FCAB
+FCAC
+FCAD
+FCAE
+FCAF
+FCB0
+FCB1
+FCB2
+FCB3
+FCB4
+FCB5
+FCB6
+FCB7
+FCB8
+FCB9
+FCBA
+FCBB
+FCBC
+FCBD
+FCBE
+FCBF
+FCC0
+FCC1
+FCC2
+FCC3
+FCC4
+FCC5
+FCC6
+FCC7
+FCC8
+FCC9
+FCCA
+FCCB
+FCCC
+FCCD
+FCCE
+FCCF
+FCD0
+FCD1
+FCD2
+FCD3
+FCD4
+FCD5
+FCD6
+FCD7
+FCD8
+FCD9
+FCDA
+FCDB
+FCDC
+FCDD
+FCDE
+FCDF
+FCE0
+FCE1
+FCE2
+FCE3
+FCE4
+FCE5
+FCE6
+FCE7
+FCE8
+FCE9
+FCEA
+FCEB
+FCEC
+FCED
+FCEE
+FCEF
+FCF0
+FCF1
+FCF2
+FCF3
+FCF4
+FCF5
+FCF6
+FCF7
+FCF8
+FCF9
+FCFA
+FCFB
+FCFC
+FCFD
+FCFE
+FDA1
+FDA2
+FDA3
+FDA4
+FDA5
+FDA6
+FDA7
+FDA8
+FDA9
+FDAA
+FDAB
+FDAC
+FDAD
+FDAE
+FDAF
+FDB0
+FDB1
+FDB2
+FDB3
+FDB4
+FDB5
+FDB6
+FDB7
+FDB8
+FDB9
+FDBA
+FDBB
+FDBC
+FDBD
+FDBE
+FDBF
+FDC0
+FDC1
+FDC2
+FDC3
+FDC4
+FDC5
+FDC6
+FDC7
+FDC8
+FDC9
+FDCA
+FDCB
+FDCC
+FDCD
+FDCE
+FDCF
+FDD0
+FDD1
+FDD2
+FDD3
+FDD4
+FDD5
+FDD6
+FDD7
+FDD8
+FDD9
+FDDA
+FDDB
+FDDC
+FDDD
+FDDE
+FDDF
+FDE0
+FDE1
+FDE2
+FDE3
+FDE4
+FDE5
+FDE6
+FDE7
+FDE8
+FDE9
+FDEA
+FDEB
+FDEC
+FDED
+FDEE
+FDEF
+FDF0
+FDF1
+FDF2
+FDF3
+FDF4
+FDF5
+FDF6
+FDF7
+FDF8
+FDF9
+FDFA
+FDFB
+FDFC
+FDFD
+FDFE
+FEA1
+FEA2
+FEA3
+FEA4
+FEA5
+FEA6
+FEA7
+FEA8
+FEA9
+FEAA
+FEAB
+FEAC
+FEAD
+FEAE
+FEAF
+FEB0
+FEB1
+FEB2
+FEB3
+FEB4
+FEB5
+FEB6
+FEB7
+FEB8
+FEB9
+FEBA
+FEBB
+FEBC
+FEBD
+FEBE
+FEBF
+FEC0
+FEC1
+FEC2
+FEC3
+FEC4
+FEC5
+FEC6
+FEC7
+FEC8
+FEC9
+FECA
+FECB
+FECC
+FECD
+FECE
+FECF
+FED0
+FED1
+FED2
+FED3
+FED4
+FED5
+FED6
+FED7
+FED8
+FED9
+FEDA
+FEDB
+FEDC
+FEDD
+FEDE
+FEDF
+FEE0
+FEE1
+FEE2
+FEE3
+FEE4
+FEE5
+FEE6
+FEE7
+FEE8
+FEE9
+FEEA
+FEEB
+FEEC
+FEED
+FEEE
+FEEF
+FEF0
+FEF1
+FEF2
+FEF3
+FEF4
+FEF5
+FEF6
+FEF7
+FEF8
+FEF9
+FEFA
+FEFB
+FEFC
+FEFD
+FEFE
+8FF5A1
+8FF5A2
+8FF5A3
+8FF5A4
+8FF5A5
+8FF5A6
+8FF5A7
+8FF5A8
+8FF5A9
+8FF5AA
+8FF5AB
+8FF5AC
+8FF5AD
+8FF5AE
+8FF5AF
+8FF5B0
+8FF5B1
+8FF5B2
+8FF5B3
+8FF5B4
+8FF5B5
+8FF5B6
+8FF5B7
+8FF5B8
+8FF5B9
+8FF5BA
+8FF5BB
+8FF5BC
+8FF5BD
+8FF5BE
+8FF5BF
+8FF5C0
+8FF5C1
+8FF5C2
+8FF5C3
+8FF5C4
+8FF5C5
+8FF5C6
+8FF5C7
+8FF5C8
+8FF5C9
+8FF5CA
+8FF5CB
+8FF5CC
+8FF5CD
+8FF5CE
+8FF5CF
+8FF5D0
+8FF5D1
+8FF5D2
+8FF5D3
+8FF5D4
+8FF5D5
+8FF5D6
+8FF5D7
+8FF5D8
+8FF5D9
+8FF5DA
+8FF5DB
+8FF5DC
+8FF5DD
+8FF5DE
+8FF5DF
+8FF5E0
+8FF5E1
+8FF5E2
+8FF5E3
+8FF5E4
+8FF5E5
+8FF5E6
+8FF5E7
+8FF5E8
+8FF5E9
+8FF5EA
+8FF5EB
+8FF5EC
+8FF5ED
+8FF5EE
+8FF5EF
+8FF5F0
+8FF5F1
+8FF5F2
+8FF5F3
+8FF5F4
+8FF5F5
+8FF5F6
+8FF5F7
+8FF5F8
+8FF5F9
+8FF5FA
+8FF5FB
+8FF5FC
+8FF5FD
+8FF5FE
+8FF6A1
+8FF6A2
+8FF6A3
+8FF6A4
+8FF6A5
+8FF6A6
+8FF6A7
+8FF6A8
+8FF6A9
+8FF6AA
+8FF6AB
+8FF6AC
+8FF6AD
+8FF6AE
+8FF6AF
+8FF6B0
+8FF6B1
+8FF6B2
+8FF6B3
+8FF6B4
+8FF6B5
+8FF6B6
+8FF6B7
+8FF6B8
+8FF6B9
+8FF6BA
+8FF6BB
+8FF6BC
+8FF6BD
+8FF6BE
+8FF6BF
+8FF6C0
+8FF6C1
+8FF6C2
+8FF6C3
+8FF6C4
+8FF6C5
+8FF6C6
+8FF6C7
+8FF6C8
+8FF6C9
+8FF6CA
+8FF6CB
+8FF6CC
+8FF6CD
+8FF6CE
+8FF6CF
+8FF6D0
+8FF6D1
+8FF6D2
+8FF6D3
+8FF6D4
+8FF6D5
+8FF6D6
+8FF6D7
+8FF6D8
+8FF6D9
+8FF6DA
+8FF6DB
+8FF6DC
+8FF6DD
+8FF6DE
+8FF6DF
+8FF6E0
+8FF6E1
+8FF6E2
+8FF6E3
+8FF6E4
+8FF6E5
+8FF6E6
+8FF6E7
+8FF6E8
+8FF6E9
+8FF6EA
+8FF6EB
+8FF6EC
+8FF6ED
+8FF6EE
+8FF6EF
+8FF6F0
+8FF6F1
+8FF6F2
+8FF6F3
+8FF6F4
+8FF6F5
+8FF6F6
+8FF6F7
+8FF6F8
+8FF6F9
+8FF6FA
+8FF6FB
+8FF6FC
+8FF6FD
+8FF6FE
+8FF7A1
+8FF7A2
+8FF7A3
+8FF7A4
+8FF7A5
+8FF7A6
+8FF7A7
+8FF7A8
+8FF7A9
+8FF7AA
+8FF7AB
+8FF7AC
+8FF7AD
+8FF7AE
+8FF7AF
+8FF7B0
+8FF7B1
+8FF7B2
+8FF7B3
+8FF7B4
+8FF7B5
+8FF7B6
+8FF7B7
+8FF7B8
+8FF7B9
+8FF7BA
+8FF7BB
+8FF7BC
+8FF7BD
+8FF7BE
+8FF7BF
+8FF7C0
+8FF7C1
+8FF7C2
+8FF7C3
+8FF7C4
+8FF7C5
+8FF7C6
+8FF7C7
+8FF7C8
+8FF7C9
+8FF7CA
+8FF7CB
+8FF7CC
+8FF7CD
+8FF7CE
+8FF7CF
+8FF7D0
+8FF7D1
+8FF7D2
+8FF7D3
+8FF7D4
+8FF7D5
+8FF7D6
+8FF7D7
+8FF7D8
+8FF7D9
+8FF7DA
+8FF7DB
+8FF7DC
+8FF7DD
+8FF7DE
+8FF7DF
+8FF7E0
+8FF7E1
+8FF7E2
+8FF7E3
+8FF7E4
+8FF7E5
+8FF7E6
+8FF7E7
+8FF7E8
+8FF7E9
+8FF7EA
+8FF7EB
+8FF7EC
+8FF7ED
+8FF7EE
+8FF7EF
+8FF7F0
+8FF7F1
+8FF7F2
+8FF7F3
+8FF7F4
+8FF7F5
+8FF7F6
+8FF7F7
+8FF7F8
+8FF7F9
+8FF7FA
+8FF7FB
+8FF7FC
+8FF7FD
+8FF7FE
+8FF8A1
+8FF8A2
+8FF8A3
+8FF8A4
+8FF8A5
+8FF8A6
+8FF8A7
+8FF8A8
+8FF8A9
+8FF8AA
+8FF8AB
+8FF8AC
+8FF8AD
+8FF8AE
+8FF8AF
+8FF8B0
+8FF8B1
+8FF8B2
+8FF8B3
+8FF8B4
+8FF8B5
+8FF8B6
+8FF8B7
+8FF8B8
+8FF8B9
+8FF8BA
+8FF8BB
+8FF8BC
+8FF8BD
+8FF8BE
+8FF8BF
+8FF8C0
+8FF8C1
+8FF8C2
+8FF8C3
+8FF8C4
+8FF8C5
+8FF8C6
+8FF8C7
+8FF8C8
+8FF8C9
+8FF8CA
+8FF8CB
+8FF8CC
+8FF8CD
+8FF8CE
+8FF8CF
+8FF8D0
+8FF8D1
+8FF8D2
+8FF8D3
+8FF8D4
+8FF8D5
+8FF8D6
+8FF8D7
+8FF8D8
+8FF8D9
+8FF8DA
+8FF8DB
+8FF8DC
+8FF8DD
+8FF8DE
+8FF8DF
+8FF8E0
+8FF8E1
+8FF8E2
+8FF8E3
+8FF8E4
+8FF8E5
+8FF8E6
+8FF8E7
+8FF8E8
+8FF8E9
+8FF8EA
+8FF8EB
+8FF8EC
+8FF8ED
+8FF8EE
+8FF8EF
+8FF8F0
+8FF8F1
+8FF8F2
+8FF8F3
+8FF8F4
+8FF8F5
+8FF8F6
+8FF8F7
+8FF8F8
+8FF8F9
+8FF8FA
+8FF8FB
+8FF8FC
+8FF8FD
+8FF8FE
+8FF9A1
+8FF9A2
+8FF9A3
+8FF9A4
+8FF9A5
+8FF9A6
+8FF9A7
+8FF9A8
+8FF9A9
+8FF9AA
+8FF9AB
+8FF9AC
+8FF9AD
+8FF9AE
+8FF9AF
+8FF9B0
+8FF9B1
+8FF9B2
+8FF9B3
+8FF9B4
+8FF9B5
+8FF9B6
+8FF9B7
+8FF9B8
+8FF9B9
+8FF9BA
+8FF9BB
+8FF9BC
+8FF9BD
+8FF9BE
+8FF9BF
+8FF9C0
+8FF9C1
+8FF9C2
+8FF9C3
+8FF9C4
+8FF9C5
+8FF9C6
+8FF9C7
+8FF9C8
+8FF9C9
+8FF9CA
+8FF9CB
+8FF9CC
+8FF9CD
+8FF9CE
+8FF9CF
+8FF9D0
+8FF9D1
+8FF9D2
+8FF9D3
+8FF9D4
+8FF9D5
+8FF9D6
+8FF9D7
+8FF9D8
+8FF9D9
+8FF9DA
+8FF9DB
+8FF9DC
+8FF9DD
+8FF9DE
+8FF9DF
+8FF9E0
+8FF9E1
+8FF9E2
+8FF9E3
+8FF9E4
+8FF9E5
+8FF9E6
+8FF9E7
+8FF9E8
+8FF9E9
+8FF9EA
+8FF9EB
+8FF9EC
+8FF9ED
+8FF9EE
+8FF9EF
+8FF9F0
+8FF9F1
+8FF9F2
+8FF9F3
+8FF9F4
+8FF9F5
+8FF9F6
+8FF9F7
+8FF9F8
+8FF9F9
+8FF9FA
+8FF9FB
+8FF9FC
+8FF9FD
+8FF9FE
+8FFAA1
+8FFAA2
+8FFAA3
+8FFAA4
+8FFAA5
+8FFAA6
+8FFAA7
+8FFAA8
+8FFAA9
+8FFAAA
+8FFAAB
+8FFAAC
+8FFAAD
+8FFAAE
+8FFAAF
+8FFAB0
+8FFAB1
+8FFAB2
+8FFAB3
+8FFAB4
+8FFAB5
+8FFAB6
+8FFAB7
+8FFAB8
+8FFAB9
+8FFABA
+8FFABB
+8FFABC
+8FFABD
+8FFABE
+8FFABF
+8FFAC0
+8FFAC1
+8FFAC2
+8FFAC3
+8FFAC4
+8FFAC5
+8FFAC6
+8FFAC7
+8FFAC8
+8FFAC9
+8FFACA
+8FFACB
+8FFACC
+8FFACD
+8FFACE
+8FFACF
+8FFAD0
+8FFAD1
+8FFAD2
+8FFAD3
+8FFAD4
+8FFAD5
+8FFAD6
+8FFAD7
+8FFAD8
+8FFAD9
+8FFADA
+8FFADB
+8FFADC
+8FFADD
+8FFADE
+8FFADF
+8FFAE0
+8FFAE1
+8FFAE2
+8FFAE3
+8FFAE4
+8FFAE5
+8FFAE6
+8FFAE7
+8FFAE8
+8FFAE9
+8FFAEA
+8FFAEB
+8FFAEC
+8FFAED
+8FFAEE
+8FFAEF
+8FFAF0
+8FFAF1
+8FFAF2
+8FFAF3
+8FFAF4
+8FFAF5
+8FFAF6
+8FFAF7
+8FFAF8
+8FFAF9
+8FFAFA
+8FFAFB
+8FFAFC
+8FFAFD
+8FFAFE
+8FFBA1
+8FFBA2
+8FFBA3
+8FFBA4
+8FFBA5
+8FFBA6
+8FFBA7
+8FFBA8
+8FFBA9
+8FFBAA
+8FFBAB
+8FFBAC
+8FFBAD
+8FFBAE
+8FFBAF
+8FFBB0
+8FFBB1
+8FFBB2
+8FFBB3
+8FFBB4
+8FFBB5
+8FFBB6
+8FFBB7
+8FFBB8
+8FFBB9
+8FFBBA
+8FFBBB
+8FFBBC
+8FFBBD
+8FFBBE
+8FFBBF
+8FFBC0
+8FFBC1
+8FFBC2
+8FFBC3
+8FFBC4
+8FFBC5
+8FFBC6
+8FFBC7
+8FFBC8
+8FFBC9
+8FFBCA
+8FFBCB
+8FFBCC
+8FFBCD
+8FFBCE
+8FFBCF
+8FFBD0
+8FFBD1
+8FFBD2
+8FFBD3
+8FFBD4
+8FFBD5
+8FFBD6
+8FFBD7
+8FFBD8
+8FFBD9
+8FFBDA
+8FFBDB
+8FFBDC
+8FFBDD
+8FFBDE
+8FFBDF
+8FFBE0
+8FFBE1
+8FFBE2
+8FFBE3
+8FFBE4
+8FFBE5
+8FFBE6
+8FFBE7
+8FFBE8
+8FFBE9
+8FFBEA
+8FFBEB
+8FFBEC
+8FFBED
+8FFBEE
+8FFBEF
+8FFBF0
+8FFBF1
+8FFBF2
+8FFBF3
+8FFBF4
+8FFBF5
+8FFBF6
+8FFBF7
+8FFBF8
+8FFBF9
+8FFBFA
+8FFBFB
+8FFBFC
+8FFBFD
+8FFBFE
+8FFCA1
+8FFCA2
+8FFCA3
+8FFCA4
+8FFCA5
+8FFCA6
+8FFCA7
+8FFCA8
+8FFCA9
+8FFCAA
+8FFCAB
+8FFCAC
+8FFCAD
+8FFCAE
+8FFCAF
+8FFCB0
+8FFCB1
+8FFCB2
+8FFCB3
+8FFCB4
+8FFCB5
+8FFCB6
+8FFCB7
+8FFCB8
+8FFCB9
+8FFCBA
+8FFCBB
+8FFCBC
+8FFCBD
+8FFCBE
+8FFCBF
+8FFCC0
+8FFCC1
+8FFCC2
+8FFCC3
+8FFCC4
+8FFCC5
+8FFCC6
+8FFCC7
+8FFCC8
+8FFCC9
+8FFCCA
+8FFCCB
+8FFCCC
+8FFCCD
+8FFCCE
+8FFCCF
+8FFCD0
+8FFCD1
+8FFCD2
+8FFCD3
+8FFCD4
+8FFCD5
+8FFCD6
+8FFCD7
+8FFCD8
+8FFCD9
+8FFCDA
+8FFCDB
+8FFCDC
+8FFCDD
+8FFCDE
+8FFCDF
+8FFCE0
+8FFCE1
+8FFCE2
+8FFCE3
+8FFCE4
+8FFCE5
+8FFCE6
+8FFCE7
+8FFCE8
+8FFCE9
+8FFCEA
+8FFCEB
+8FFCEC
+8FFCED
+8FFCEE
+8FFCEF
+8FFCF0
+8FFCF1
+8FFCF2
+8FFCF3
+8FFCF4
+8FFCF5
+8FFCF6
+8FFCF7
+8FFCF8
+8FFCF9
+8FFCFA
+8FFCFB
+8FFCFC
+8FFCFD
+8FFCFE
+8FFDA1
+8FFDA2
+8FFDA3
+8FFDA4
+8FFDA5
+8FFDA6
+8FFDA7
+8FFDA8
+8FFDA9
+8FFDAA
+8FFDAB
+8FFDAC
+8FFDAD
+8FFDAE
+8FFDAF
+8FFDB0
+8FFDB1
+8FFDB2
+8FFDB3
+8FFDB4
+8FFDB5
+8FFDB6
+8FFDB7
+8FFDB8
+8FFDB9
+8FFDBA
+8FFDBB
+8FFDBC
+8FFDBD
+8FFDBE
+8FFDBF
+8FFDC0
+8FFDC1
+8FFDC2
+8FFDC3
+8FFDC4
+8FFDC5
+8FFDC6
+8FFDC7
+8FFDC8
+8FFDC9
+8FFDCA
+8FFDCB
+8FFDCC
+8FFDCD
+8FFDCE
+8FFDCF
+8FFDD0
+8FFDD1
+8FFDD2
+8FFDD3
+8FFDD4
+8FFDD5
+8FFDD6
+8FFDD7
+8FFDD8
+8FFDD9
+8FFDDA
+8FFDDB
+8FFDDC
+8FFDDD
+8FFDDE
+8FFDDF
+8FFDE0
+8FFDE1
+8FFDE2
+8FFDE3
+8FFDE4
+8FFDE5
+8FFDE6
+8FFDE7
+8FFDE8
+8FFDE9
+8FFDEA
+8FFDEB
+8FFDEC
+8FFDED
+8FFDEE
+8FFDEF
+8FFDF0
+8FFDF1
+8FFDF2
+8FFDF3
+8FFDF4
+8FFDF5
+8FFDF6
+8FFDF7
+8FFDF8
+8FFDF9
+8FFDFA
+8FFDFB
+8FFDFC
+8FFDFD
+8FFDFE
+8FFEA1
+8FFEA2
+8FFEA3
+8FFEA4
+8FFEA5
+8FFEA6
+8FFEA7
+8FFEA8
+8FFEA9
+8FFEAA
+8FFEAB
+8FFEAC
+8FFEAD
+8FFEAE
+8FFEAF
+8FFEB0
+8FFEB1
+8FFEB2
+8FFEB3
+8FFEB4
+8FFEB5
+8FFEB6
+8FFEB7
+8FFEB8
+8FFEB9
+8FFEBA
+8FFEBB
+8FFEBC
+8FFEBD
+8FFEBE
+8FFEBF
+8FFEC0
+8FFEC1
+8FFEC2
+8FFEC3
+8FFEC4
+8FFEC5
+8FFEC6
+8FFEC7
+8FFEC8
+8FFEC9
+8FFECA
+8FFECB
+8FFECC
+8FFECD
+8FFECE
+8FFECF
+8FFED0
+8FFED1
+8FFED2
+8FFED3
+8FFED4
+8FFED5
+8FFED6
+8FFED7
+8FFED8
+8FFED9
+8FFEDA
+8FFEDB
+8FFEDC
+8FFEDD
+8FFEDE
+8FFEDF
+8FFEE0
+8FFEE1
+8FFEE2
+8FFEE3
+8FFEE4
+8FFEE5
+8FFEE6
+8FFEE7
+8FFEE8
+8FFEE9
+8FFEEA
+8FFEEB
+8FFEEC
+8FFEED
+8FFEEE
+8FFEEF
+8FFEF0
+8FFEF1
+8FFEF2
+8FFEF3
+8FFEF4
+8FFEF5
+8FFEF6
+8FFEF7
+8FFEF8
+8FFEF9
+8FFEFA
+8FFEFB
+8FFEFC
+8FFEFD
+8FFEFE
+CREATE TABLE t4 SELECT CONVERT(c1 USING cp932) AS c1 FROM t1;
+SELECT HEX(c1) FROM t4;
+HEX(c1)
+5C
+7E
+8150
+815C
+815F
+8160
+8161
+817C
+8191
+8192
+818F
+81CA
+8160
+FA55
+8740
+8741
+8742
+8743
+8744
+8745
+8746
+8747
+8748
+8749
+874A
+874B
+874C
+874D
+874E
+874F
+8750
+8751
+8752
+8753
+8754
+8755
+8756
+8757
+8758
+8759
+875A
+875B
+875C
+875D
+875F
+8760
+8761
+8762
+8763
+8764
+8765
+8766
+8767
+8768
+8769
+876A
+876B
+876C
+876D
+876E
+876F
+8770
+8771
+8772
+8773
+8774
+8775
+877E
+8780
+8781
+8782
+8783
+8784
+8785
+8786
+8787
+8788
+8789
+878A
+878B
+878C
+878D
+878E
+878F
+81E0
+81DF
+81E7
+8793
+8794
+81E3
+81DB
+81DA
+8798
+8799
+81E6
+81BF
+81BE
+FA40
+FA41
+FA42
+FA43
+FA44
+FA45
+FA46
+FA47
+FA48
+FA49
+8754
+8755
+8756
+8757
+8758
+8759
+875A
+875B
+875C
+875D
+81CA
+FA55
+FA56
+FA57
+878A
+8782
+8784
+81E6
+FA5C
+FA5D
+FA5E
+FA5F
+FA60
+FA61
+FA62
+FA63
+FA64
+FA65
+FA66
+FA67
+FA68
+FA69
+FA6A
+FA6B
+FA6C
+FA6D
+FA6E
+FA6F
+FA70
+FA71
+FA72
+FA73
+FA74
+FA75
+FA76
+FA77
+FA78
+FA79
+FA7A
+FA7B
+FA7C
+FA7D
+FA7E
+FA80
+FA81
+FA82
+FA83
+FA84
+FA85
+FA86
+FA87
+FA88
+FA89
+FA8A
+FA8B
+FA8C
+FA8D
+FA8E
+FA8F
+FA90
+FA91
+FA92
+FA93
+FA94
+FA95
+FA96
+FA97
+FA98
+FA99
+FA9A
+FA9B
+FA9C
+FA9D
+FA9E
+FA9F
+FAA0
+FAA1
+FAA2
+FAA3
+FAA4
+FAA5
+FAA6
+FAA7
+FAA8
+FAA9
+FAAA
+FAAB
+FAAC
+FAAD
+FAAE
+FAAF
+FAB0
+FAB1
+FAB2
+FAB3
+FAB4
+FAB5
+FAB6
+FAB7
+FAB8
+FAB9
+FABA
+FABB
+FABC
+FABD
+FABE
+FABF
+FAC0
+FAC1
+FAC2
+FAC3
+FAC4
+FAC5
+FAC6
+FAC7
+FAC8
+FAC9
+FACA
+FACB
+FACC
+FACD
+FACE
+FACF
+FAD0
+FAD1
+FAD2
+FAD3
+FAD4
+FAD5
+FAD6
+FAD7
+FAD8
+FAD9
+FADA
+FADB
+FADC
+FADD
+FADE
+FADF
+FAE0
+FAE1
+FAE2
+FAE3
+FAE4
+FAE5
+FAE6
+FAE7
+FAE8
+FAE9
+FAEA
+FAEB
+FAEC
+FAED
+FAEE
+FAEF
+FAF0
+FAF1
+FAF2
+FAF3
+FAF4
+FAF5
+FAF6
+FAF7
+FAF8
+FAF9
+FAFA
+FAFB
+FAFC
+FB40
+FB41
+FB42
+FB43
+FB44
+FB45
+FB46
+FB47
+FB48
+FB49
+FB4A
+FB4B
+FB4C
+FB4D
+FB4E
+FB4F
+FB50
+FB51
+FB52
+FB53
+FB54
+FB55
+FB56
+FB57
+FB58
+FB59
+FB5A
+FB5B
+FB5C
+FB5D
+FB5E
+FB5F
+FB60
+FB61
+FB62
+FB63
+FB64
+FB65
+FB66
+FB67
+FB68
+FB69
+FB6A
+FB6B
+FB6C
+FB6D
+FB6E
+FB6F
+FB70
+FB71
+FB72
+FB73
+FB74
+FB75
+FB76
+FB77
+FB78
+FB79
+FB7A
+FB7B
+FB7C
+FB7D
+FB7E
+FB80
+FB81
+FB82
+FB83
+FB84
+FB85
+FB86
+FB87
+FB88
+FB89
+FB8A
+FB8B
+FB8C
+FB8D
+FB8E
+FB8F
+FB90
+FB91
+FB92
+FB93
+FB94
+FB95
+FB96
+FB97
+FB98
+FB99
+FB9A
+FB9B
+FB9C
+FB9D
+FB9E
+FB9F
+FBA0
+FBA1
+FBA2
+FBA3
+FBA4
+FBA5
+FBA6
+FBA7
+FBA8
+FBA9
+FBAA
+FBAB
+FBAC
+FBAD
+FBAE
+FBAF
+FBB0
+FBB1
+FBB2
+FBB3
+FBB4
+FBB5
+FBB6
+FBB7
+FBB8
+FBB9
+FBBA
+FBBB
+FBBC
+FBBD
+FBBE
+FBBF
+FBC0
+FBC1
+FBC2
+FBC3
+FBC4
+FBC5
+FBC6
+FBC7
+FBC8
+FBC9
+FBCA
+FBCB
+FBCC
+FBCD
+FBCE
+FBCF
+FBD0
+FBD1
+FBD2
+FBD3
+FBD4
+FBD5
+FBD6
+FBD7
+FBD8
+FBD9
+FBDA
+FBDB
+FBDC
+FBDD
+FBDE
+FBDF
+FBE0
+FBE1
+FBE2
+FBE3
+FBE4
+FBE5
+FBE6
+FBE7
+FBE8
+FBE9
+FBEA
+FBEB
+FBEC
+FBED
+FBEE
+FBEF
+FBF0
+FBF1
+FBF2
+FBF3
+FBF4
+FBF5
+FBF6
+FBF7
+FBF8
+FBF9
+FBFA
+FBFB
+FBFC
+FC40
+FC41
+FC42
+FC43
+FC44
+FC45
+FC46
+FC47
+FC48
+FC49
+FC4A
+FC4B
+F040
+F041
+F042
+F043
+F044
+F045
+F046
+F047
+F048
+F049
+F04A
+F04B
+F04C
+F04D
+F04E
+F04F
+F050
+F051
+F052
+F053
+F054
+F055
+F056
+F057
+F058
+F059
+F05A
+F05B
+F05C
+F05D
+F05E
+F05F
+F060
+F061
+F062
+F063
+F064
+F065
+F066
+F067
+F068
+F069
+F06A
+F06B
+F06C
+F06D
+F06E
+F06F
+F070
+F071
+F072
+F073
+F074
+F075
+F076
+F077
+F078
+F079
+F07A
+F07B
+F07C
+F07D
+F07E
+F080
+F081
+F082
+F083
+F084
+F085
+F086
+F087
+F088
+F089
+F08A
+F08B
+F08C
+F08D
+F08E
+F08F
+F090
+F091
+F092
+F093
+F094
+F095
+F096
+F097
+F098
+F099
+F09A
+F09B
+F09C
+F09D
+F09E
+F09F
+F0A0
+F0A1
+F0A2
+F0A3
+F0A4
+F0A5
+F0A6
+F0A7
+F0A8
+F0A9
+F0AA
+F0AB
+F0AC
+F0AD
+F0AE
+F0AF
+F0B0
+F0B1
+F0B2
+F0B3
+F0B4
+F0B5
+F0B6
+F0B7
+F0B8
+F0B9
+F0BA
+F0BB
+F0BC
+F0BD
+F0BE
+F0BF
+F0C0
+F0C1
+F0C2
+F0C3
+F0C4
+F0C5
+F0C6
+F0C7
+F0C8
+F0C9
+F0CA
+F0CB
+F0CC
+F0CD
+F0CE
+F0CF
+F0D0
+F0D1
+F0D2
+F0D3
+F0D4
+F0D5
+F0D6
+F0D7
+F0D8
+F0D9
+F0DA
+F0DB
+F0DC
+F0DD
+F0DE
+F0DF
+F0E0
+F0E1
+F0E2
+F0E3
+F0E4
+F0E5
+F0E6
+F0E7
+F0E8
+F0E9
+F0EA
+F0EB
+F0EC
+F0ED
+F0EE
+F0EF
+F0F0
+F0F1
+F0F2
+F0F3
+F0F4
+F0F5
+F0F6
+F0F7
+F0F8
+F0F9
+F0FA
+F0FB
+F0FC
+F140
+F141
+F142
+F143
+F144
+F145
+F146
+F147
+F148
+F149
+F14A
+F14B
+F14C
+F14D
+F14E
+F14F
+F150
+F151
+F152
+F153
+F154
+F155
+F156
+F157
+F158
+F159
+F15A
+F15B
+F15C
+F15D
+F15E
+F15F
+F160
+F161
+F162
+F163
+F164
+F165
+F166
+F167
+F168
+F169
+F16A
+F16B
+F16C
+F16D
+F16E
+F16F
+F170
+F171
+F172
+F173
+F174
+F175
+F176
+F177
+F178
+F179
+F17A
+F17B
+F17C
+F17D
+F17E
+F180
+F181
+F182
+F183
+F184
+F185
+F186
+F187
+F188
+F189
+F18A
+F18B
+F18C
+F18D
+F18E
+F18F
+F190
+F191
+F192
+F193
+F194
+F195
+F196
+F197
+F198
+F199
+F19A
+F19B
+F19C
+F19D
+F19E
+F19F
+F1A0
+F1A1
+F1A2
+F1A3
+F1A4
+F1A5
+F1A6
+F1A7
+F1A8
+F1A9
+F1AA
+F1AB
+F1AC
+F1AD
+F1AE
+F1AF
+F1B0
+F1B1
+F1B2
+F1B3
+F1B4
+F1B5
+F1B6
+F1B7
+F1B8
+F1B9
+F1BA
+F1BB
+F1BC
+F1BD
+F1BE
+F1BF
+F1C0
+F1C1
+F1C2
+F1C3
+F1C4
+F1C5
+F1C6
+F1C7
+F1C8
+F1C9
+F1CA
+F1CB
+F1CC
+F1CD
+F1CE
+F1CF
+F1D0
+F1D1
+F1D2
+F1D3
+F1D4
+F1D5
+F1D6
+F1D7
+F1D8
+F1D9
+F1DA
+F1DB
+F1DC
+F1DD
+F1DE
+F1DF
+F1E0
+F1E1
+F1E2
+F1E3
+F1E4
+F1E5
+F1E6
+F1E7
+F1E8
+F1E9
+F1EA
+F1EB
+F1EC
+F1ED
+F1EE
+F1EF
+F1F0
+F1F1
+F1F2
+F1F3
+F1F4
+F1F5
+F1F6
+F1F7
+F1F8
+F1F9
+F1FA
+F1FB
+F1FC
+F240
+F241
+F242
+F243
+F244
+F245
+F246
+F247
+F248
+F249
+F24A
+F24B
+F24C
+F24D
+F24E
+F24F
+F250
+F251
+F252
+F253
+F254
+F255
+F256
+F257
+F258
+F259
+F25A
+F25B
+F25C
+F25D
+F25E
+F25F
+F260
+F261
+F262
+F263
+F264
+F265
+F266
+F267
+F268
+F269
+F26A
+F26B
+F26C
+F26D
+F26E
+F26F
+F270
+F271
+F272
+F273
+F274
+F275
+F276
+F277
+F278
+F279
+F27A
+F27B
+F27C
+F27D
+F27E
+F280
+F281
+F282
+F283
+F284
+F285
+F286
+F287
+F288
+F289
+F28A
+F28B
+F28C
+F28D
+F28E
+F28F
+F290
+F291
+F292
+F293
+F294
+F295
+F296
+F297
+F298
+F299
+F29A
+F29B
+F29C
+F29D
+F29E
+F29F
+F2A0
+F2A1
+F2A2
+F2A3
+F2A4
+F2A5
+F2A6
+F2A7
+F2A8
+F2A9
+F2AA
+F2AB
+F2AC
+F2AD
+F2AE
+F2AF
+F2B0
+F2B1
+F2B2
+F2B3
+F2B4
+F2B5
+F2B6
+F2B7
+F2B8
+F2B9
+F2BA
+F2BB
+F2BC
+F2BD
+F2BE
+F2BF
+F2C0
+F2C1
+F2C2
+F2C3
+F2C4
+F2C5
+F2C6
+F2C7
+F2C8
+F2C9
+F2CA
+F2CB
+F2CC
+F2CD
+F2CE
+F2CF
+F2D0
+F2D1
+F2D2
+F2D3
+F2D4
+F2D5
+F2D6
+F2D7
+F2D8
+F2D9
+F2DA
+F2DB
+F2DC
+F2DD
+F2DE
+F2DF
+F2E0
+F2E1
+F2E2
+F2E3
+F2E4
+F2E5
+F2E6
+F2E7
+F2E8
+F2E9
+F2EA
+F2EB
+F2EC
+F2ED
+F2EE
+F2EF
+F2F0
+F2F1
+F2F2
+F2F3
+F2F4
+F2F5
+F2F6
+F2F7
+F2F8
+F2F9
+F2FA
+F2FB
+F2FC
+F340
+F341
+F342
+F343
+F344
+F345
+F346
+F347
+F348
+F349
+F34A
+F34B
+F34C
+F34D
+F34E
+F34F
+F350
+F351
+F352
+F353
+F354
+F355
+F356
+F357
+F358
+F359
+F35A
+F35B
+F35C
+F35D
+F35E
+F35F
+F360
+F361
+F362
+F363
+F364
+F365
+F366
+F367
+F368
+F369
+F36A
+F36B
+F36C
+F36D
+F36E
+F36F
+F370
+F371
+F372
+F373
+F374
+F375
+F376
+F377
+F378
+F379
+F37A
+F37B
+F37C
+F37D
+F37E
+F380
+F381
+F382
+F383
+F384
+F385
+F386
+F387
+F388
+F389
+F38A
+F38B
+F38C
+F38D
+F38E
+F38F
+F390
+F391
+F392
+F393
+F394
+F395
+F396
+F397
+F398
+F399
+F39A
+F39B
+F39C
+F39D
+F39E
+F39F
+F3A0
+F3A1
+F3A2
+F3A3
+F3A4
+F3A5
+F3A6
+F3A7
+F3A8
+F3A9
+F3AA
+F3AB
+F3AC
+F3AD
+F3AE
+F3AF
+F3B0
+F3B1
+F3B2
+F3B3
+F3B4
+F3B5
+F3B6
+F3B7
+F3B8
+F3B9
+F3BA
+F3BB
+F3BC
+F3BD
+F3BE
+F3BF
+F3C0
+F3C1
+F3C2
+F3C3
+F3C4
+F3C5
+F3C6
+F3C7
+F3C8
+F3C9
+F3CA
+F3CB
+F3CC
+F3CD
+F3CE
+F3CF
+F3D0
+F3D1
+F3D2
+F3D3
+F3D4
+F3D5
+F3D6
+F3D7
+F3D8
+F3D9
+F3DA
+F3DB
+F3DC
+F3DD
+F3DE
+F3DF
+F3E0
+F3E1
+F3E2
+F3E3
+F3E4
+F3E5
+F3E6
+F3E7
+F3E8
+F3E9
+F3EA
+F3EB
+F3EC
+F3ED
+F3EE
+F3EF
+F3F0
+F3F1
+F3F2
+F3F3
+F3F4
+F3F5
+F3F6
+F3F7
+F3F8
+F3F9
+F3FA
+F3FB
+F3FC
+F440
+F441
+F442
+F443
+F444
+F445
+F446
+F447
+F448
+F449
+F44A
+F44B
+F44C
+F44D
+F44E
+F44F
+F450
+F451
+F452
+F453
+F454
+F455
+F456
+F457
+F458
+F459
+F45A
+F45B
+F45C
+F45D
+F45E
+F45F
+F460
+F461
+F462
+F463
+F464
+F465
+F466
+F467
+F468
+F469
+F46A
+F46B
+F46C
+F46D
+F46E
+F46F
+F470
+F471
+F472
+F473
+F474
+F475
+F476
+F477
+F478
+F479
+F47A
+F47B
+F47C
+F47D
+F47E
+F480
+F481
+F482
+F483
+F484
+F485
+F486
+F487
+F488
+F489
+F48A
+F48B
+F48C
+F48D
+F48E
+F48F
+F490
+F491
+F492
+F493
+F494
+F495
+F496
+F497
+F498
+F499
+F49A
+F49B
+F49C
+F49D
+F49E
+F49F
+F4A0
+F4A1
+F4A2
+F4A3
+F4A4
+F4A5
+F4A6
+F4A7
+F4A8
+F4A9
+F4AA
+F4AB
+F4AC
+F4AD
+F4AE
+F4AF
+F4B0
+F4B1
+F4B2
+F4B3
+F4B4
+F4B5
+F4B6
+F4B7
+F4B8
+F4B9
+F4BA
+F4BB
+F4BC
+F4BD
+F4BE
+F4BF
+F4C0
+F4C1
+F4C2
+F4C3
+F4C4
+F4C5
+F4C6
+F4C7
+F4C8
+F4C9
+F4CA
+F4CB
+F4CC
+F4CD
+F4CE
+F4CF
+F4D0
+F4D1
+F4D2
+F4D3
+F4D4
+F4D5
+F4D6
+F4D7
+F4D8
+F4D9
+F4DA
+F4DB
+F4DC
+F4DD
+F4DE
+F4DF
+F4E0
+F4E1
+F4E2
+F4E3
+F4E4
+F4E5
+F4E6
+F4E7
+F4E8
+F4E9
+F4EA
+F4EB
+F4EC
+F4ED
+F4EE
+F4EF
+F4F0
+F4F1
+F4F2
+F4F3
+F4F4
+F4F5
+F4F6
+F4F7
+F4F8
+F4F9
+F4FA
+F4FB
+F4FC
+F540
+F541
+F542
+F543
+F544
+F545
+F546
+F547
+F548
+F549
+F54A
+F54B
+F54C
+F54D
+F54E
+F54F
+F550
+F551
+F552
+F553
+F554
+F555
+F556
+F557
+F558
+F559
+F55A
+F55B
+F55C
+F55D
+F55E
+F55F
+F560
+F561
+F562
+F563
+F564
+F565
+F566
+F567
+F568
+F569
+F56A
+F56B
+F56C
+F56D
+F56E
+F56F
+F570
+F571
+F572
+F573
+F574
+F575
+F576
+F577
+F578
+F579
+F57A
+F57B
+F57C
+F57D
+F57E
+F580
+F581
+F582
+F583
+F584
+F585
+F586
+F587
+F588
+F589
+F58A
+F58B
+F58C
+F58D
+F58E
+F58F
+F590
+F591
+F592
+F593
+F594
+F595
+F596
+F597
+F598
+F599
+F59A
+F59B
+F59C
+F59D
+F59E
+F59F
+F5A0
+F5A1
+F5A2
+F5A3
+F5A4
+F5A5
+F5A6
+F5A7
+F5A8
+F5A9
+F5AA
+F5AB
+F5AC
+F5AD
+F5AE
+F5AF
+F5B0
+F5B1
+F5B2
+F5B3
+F5B4
+F5B5
+F5B6
+F5B7
+F5B8
+F5B9
+F5BA
+F5BB
+F5BC
+F5BD
+F5BE
+F5BF
+F5C0
+F5C1
+F5C2
+F5C3
+F5C4
+F5C5
+F5C6
+F5C7
+F5C8
+F5C9
+F5CA
+F5CB
+F5CC
+F5CD
+F5CE
+F5CF
+F5D0
+F5D1
+F5D2
+F5D3
+F5D4
+F5D5
+F5D6
+F5D7
+F5D8
+F5D9
+F5DA
+F5DB
+F5DC
+F5DD
+F5DE
+F5DF
+F5E0
+F5E1
+F5E2
+F5E3
+F5E4
+F5E5
+F5E6
+F5E7
+F5E8
+F5E9
+F5EA
+F5EB
+F5EC
+F5ED
+F5EE
+F5EF
+F5F0
+F5F1
+F5F2
+F5F3
+F5F4
+F5F5
+F5F6
+F5F7
+F5F8
+F5F9
+F5FA
+F5FB
+F5FC
+F640
+F641
+F642
+F643
+F644
+F645
+F646
+F647
+F648
+F649
+F64A
+F64B
+F64C
+F64D
+F64E
+F64F
+F650
+F651
+F652
+F653
+F654
+F655
+F656
+F657
+F658
+F659
+F65A
+F65B
+F65C
+F65D
+F65E
+F65F
+F660
+F661
+F662
+F663
+F664
+F665
+F666
+F667
+F668
+F669
+F66A
+F66B
+F66C
+F66D
+F66E
+F66F
+F670
+F671
+F672
+F673
+F674
+F675
+F676
+F677
+F678
+F679
+F67A
+F67B
+F67C
+F67D
+F67E
+F680
+F681
+F682
+F683
+F684
+F685
+F686
+F687
+F688
+F689
+F68A
+F68B
+F68C
+F68D
+F68E
+F68F
+F690
+F691
+F692
+F693
+F694
+F695
+F696
+F697
+F698
+F699
+F69A
+F69B
+F69C
+F69D
+F69E
+F69F
+F6A0
+F6A1
+F6A2
+F6A3
+F6A4
+F6A5
+F6A6
+F6A7
+F6A8
+F6A9
+F6AA
+F6AB
+F6AC
+F6AD
+F6AE
+F6AF
+F6B0
+F6B1
+F6B2
+F6B3
+F6B4
+F6B5
+F6B6
+F6B7
+F6B8
+F6B9
+F6BA
+F6BB
+F6BC
+F6BD
+F6BE
+F6BF
+F6C0
+F6C1
+F6C2
+F6C3
+F6C4
+F6C5
+F6C6
+F6C7
+F6C8
+F6C9
+F6CA
+F6CB
+F6CC
+F6CD
+F6CE
+F6CF
+F6D0
+F6D1
+F6D2
+F6D3
+F6D4
+F6D5
+F6D6
+F6D7
+F6D8
+F6D9
+F6DA
+F6DB
+F6DC
+F6DD
+F6DE
+F6DF
+F6E0
+F6E1
+F6E2
+F6E3
+F6E4
+F6E5
+F6E6
+F6E7
+F6E8
+F6E9
+F6EA
+F6EB
+F6EC
+F6ED
+F6EE
+F6EF
+F6F0
+F6F1
+F6F2
+F6F3
+F6F4
+F6F5
+F6F6
+F6F7
+F6F8
+F6F9
+F6FA
+F6FB
+F6FC
+F740
+F741
+F742
+F743
+F744
+F745
+F746
+F747
+F748
+F749
+F74A
+F74B
+F74C
+F74D
+F74E
+F74F
+F750
+F751
+F752
+F753
+F754
+F755
+F756
+F757
+F758
+F759
+F75A
+F75B
+F75C
+F75D
+F75E
+F75F
+F760
+F761
+F762
+F763
+F764
+F765
+F766
+F767
+F768
+F769
+F76A
+F76B
+F76C
+F76D
+F76E
+F76F
+F770
+F771
+F772
+F773
+F774
+F775
+F776
+F777
+F778
+F779
+F77A
+F77B
+F77C
+F77D
+F77E
+F780
+F781
+F782
+F783
+F784
+F785
+F786
+F787
+F788
+F789
+F78A
+F78B
+F78C
+F78D
+F78E
+F78F
+F790
+F791
+F792
+F793
+F794
+F795
+F796
+F797
+F798
+F799
+F79A
+F79B
+F79C
+F79D
+F79E
+F79F
+F7A0
+F7A1
+F7A2
+F7A3
+F7A4
+F7A5
+F7A6
+F7A7
+F7A8
+F7A9
+F7AA
+F7AB
+F7AC
+F7AD
+F7AE
+F7AF
+F7B0
+F7B1
+F7B2
+F7B3
+F7B4
+F7B5
+F7B6
+F7B7
+F7B8
+F7B9
+F7BA
+F7BB
+F7BC
+F7BD
+F7BE
+F7BF
+F7C0
+F7C1
+F7C2
+F7C3
+F7C4
+F7C5
+F7C6
+F7C7
+F7C8
+F7C9
+F7CA
+F7CB
+F7CC
+F7CD
+F7CE
+F7CF
+F7D0
+F7D1
+F7D2
+F7D3
+F7D4
+F7D5
+F7D6
+F7D7
+F7D8
+F7D9
+F7DA
+F7DB
+F7DC
+F7DD
+F7DE
+F7DF
+F7E0
+F7E1
+F7E2
+F7E3
+F7E4
+F7E5
+F7E6
+F7E7
+F7E8
+F7E9
+F7EA
+F7EB
+F7EC
+F7ED
+F7EE
+F7EF
+F7F0
+F7F1
+F7F2
+F7F3
+F7F4
+F7F5
+F7F6
+F7F7
+F7F8
+F7F9
+F7FA
+F7FB
+F7FC
+F840
+F841
+F842
+F843
+F844
+F845
+F846
+F847
+F848
+F849
+F84A
+F84B
+F84C
+F84D
+F84E
+F84F
+F850
+F851
+F852
+F853
+F854
+F855
+F856
+F857
+F858
+F859
+F85A
+F85B
+F85C
+F85D
+F85E
+F85F
+F860
+F861
+F862
+F863
+F864
+F865
+F866
+F867
+F868
+F869
+F86A
+F86B
+F86C
+F86D
+F86E
+F86F
+F870
+F871
+F872
+F873
+F874
+F875
+F876
+F877
+F878
+F879
+F87A
+F87B
+F87C
+F87D
+F87E
+F880
+F881
+F882
+F883
+F884
+F885
+F886
+F887
+F888
+F889
+F88A
+F88B
+F88C
+F88D
+F88E
+F88F
+F890
+F891
+F892
+F893
+F894
+F895
+F896
+F897
+F898
+F899
+F89A
+F89B
+F89C
+F89D
+F89E
+F89F
+F8A0
+F8A1
+F8A2
+F8A3
+F8A4
+F8A5
+F8A6
+F8A7
+F8A8
+F8A9
+F8AA
+F8AB
+F8AC
+F8AD
+F8AE
+F8AF
+F8B0
+F8B1
+F8B2
+F8B3
+F8B4
+F8B5
+F8B6
+F8B7
+F8B8
+F8B9
+F8BA
+F8BB
+F8BC
+F8BD
+F8BE
+F8BF
+F8C0
+F8C1
+F8C2
+F8C3
+F8C4
+F8C5
+F8C6
+F8C7
+F8C8
+F8C9
+F8CA
+F8CB
+F8CC
+F8CD
+F8CE
+F8CF
+F8D0
+F8D1
+F8D2
+F8D3
+F8D4
+F8D5
+F8D6
+F8D7
+F8D8
+F8D9
+F8DA
+F8DB
+F8DC
+F8DD
+F8DE
+F8DF
+F8E0
+F8E1
+F8E2
+F8E3
+F8E4
+F8E5
+F8E6
+F8E7
+F8E8
+F8E9
+F8EA
+F8EB
+F8EC
+F8ED
+F8EE
+F8EF
+F8F0
+F8F1
+F8F2
+F8F3
+F8F4
+F8F5
+F8F6
+F8F7
+F8F8
+F8F9
+F8FA
+F8FB
+F8FC
+F940
+F941
+F942
+F943
+F944
+F945
+F946
+F947
+F948
+F949
+F94A
+F94B
+F94C
+F94D
+F94E
+F94F
+F950
+F951
+F952
+F953
+F954
+F955
+F956
+F957
+F958
+F959
+F95A
+F95B
+F95C
+F95D
+F95E
+F95F
+F960
+F961
+F962
+F963
+F964
+F965
+F966
+F967
+F968
+F969
+F96A
+F96B
+F96C
+F96D
+F96E
+F96F
+F970
+F971
+F972
+F973
+F974
+F975
+F976
+F977
+F978
+F979
+F97A
+F97B
+F97C
+F97D
+F97E
+F980
+F981
+F982
+F983
+F984
+F985
+F986
+F987
+F988
+F989
+F98A
+F98B
+F98C
+F98D
+F98E
+F98F
+F990
+F991
+F992
+F993
+F994
+F995
+F996
+F997
+F998
+F999
+F99A
+F99B
+F99C
+F99D
+F99E
+F99F
+F9A0
+F9A1
+F9A2
+F9A3
+F9A4
+F9A5
+F9A6
+F9A7
+F9A8
+F9A9
+F9AA
+F9AB
+F9AC
+F9AD
+F9AE
+F9AF
+F9B0
+F9B1
+F9B2
+F9B3
+F9B4
+F9B5
+F9B6
+F9B7
+F9B8
+F9B9
+F9BA
+F9BB
+F9BC
+F9BD
+F9BE
+F9BF
+F9C0
+F9C1
+F9C2
+F9C3
+F9C4
+F9C5
+F9C6
+F9C7
+F9C8
+F9C9
+F9CA
+F9CB
+F9CC
+F9CD
+F9CE
+F9CF
+F9D0
+F9D1
+F9D2
+F9D3
+F9D4
+F9D5
+F9D6
+F9D7
+F9D8
+F9D9
+F9DA
+F9DB
+F9DC
+F9DD
+F9DE
+F9DF
+F9E0
+F9E1
+F9E2
+F9E3
+F9E4
+F9E5
+F9E6
+F9E7
+F9E8
+F9E9
+F9EA
+F9EB
+F9EC
+F9ED
+F9EE
+F9EF
+F9F0
+F9F1
+F9F2
+F9F3
+F9F4
+F9F5
+F9F6
+F9F7
+F9F8
+F9F9
+F9FA
+F9FB
+F9FC
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+DROP TABLE t4;
+CREATE TABLE t1(c1 varchar(10)) default character set = eucjpms;
+insert into t1 values(_ucs2 0x00F7);
+insert into t1 values(_eucjpms 0xA1E0);
+insert into t1 values(_ujis 0xA1E0);
+insert into t1 values(_sjis 0x8180);
+insert into t1 values(_cp932 0x8180);
+SELECT HEX(c1) FROM t1;
+HEX(c1)
+A1E0
+A1E0
+A1E0
+A1E0
+A1E0
+DROP TABLE t1;
+SET collation_connection='eucjpms_japanese_ci';
+create table t1 select repeat('a',4000) a;
+delete from t1;
+insert into t1 values ('a'), ('a '), ('a\t');
+select collation(a),hex(a) from t1 order by a;
+collation(a) hex(a)
+eucjpms_japanese_ci 6109
+eucjpms_japanese_ci 61
+eucjpms_japanese_ci 6120
+drop table t1;
+SET collation_connection='eucjpms_bin';
+create table t1 select repeat('a',4000) a;
+delete from t1;
+insert into t1 values ('a'), ('a '), ('a\t');
+select collation(a),hex(a) from t1 order by a;
+collation(a) hex(a)
+eucjpms_bin 6109
+eucjpms_bin 61
+eucjpms_bin 6120
+drop table t1;
diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
index f57d8c191bf..f60dc175cd6 100644
--- a/mysql-test/r/ctype_latin1_de.result
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -220,11 +220,11 @@ select * from t1 where match a against ("te*" in boolean mode)+0;
a
test
drop table t1;
-create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
+create table t1 (word varchar(255) not null, word2 varchar(255) not null default '', index(word));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `word` varchar(255) collate latin1_german2_ci NOT NULL default '',
+ `word` varchar(255) collate latin1_german2_ci NOT NULL,
`word2` varchar(255) collate latin1_german2_ci NOT NULL default '',
KEY `word` (`word`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german2_ci
@@ -338,3 +338,9 @@ ss
ss
ß
DROP TABLE t1;
+create table t1 (s1 char(5) character set latin1 collate latin1_german2_ci);
+insert into t1 values (0xf6) /* this is o-umlaut */;
+select * from t1 where length(s1)=1 and s1='oe';
+s1
+drop table t1;
diff --git a/mysql-test/r/ctype_many.result b/mysql-test/r/ctype_many.result
index 8bfc6e98226..87b83acfe0f 100644
--- a/mysql-test/r/ctype_many.result
+++ b/mysql-test/r/ctype_many.result
@@ -2,44 +2,44 @@ DROP TABLE IF EXISTS t1;
SET CHARACTER SET latin1;
CREATE TABLE t1 (
comment CHAR(32) ASCII NOT NULL,
-koi8_ru_f CHAR(32) CHARACTER SET koi8r NOT NULL
+koi8_ru_f CHAR(32) CHARACTER SET koi8r NOT NULL default ''
) CHARSET=latin5;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `comment` char(32) character set latin1 NOT NULL default '',
+ `comment` char(32) character set latin1 NOT NULL,
`koi8_ru_f` char(32) character set koi8r NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin5
ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `comment` char(32) character set latin2 NOT NULL default '',
+ `comment` char(32) character set latin2 NOT NULL,
`koi8_ru_f` char(32) character set koi8r NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin5
ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `comment` char(32) character set latin2 NOT NULL default '',
+ `comment` char(32) character set latin2 NOT NULL,
`koi8_ru_f` char(32) character set koi8r NOT NULL default '',
- `latin5_f` char(32) NOT NULL default ''
+ `latin5_f` char(32) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin5
ALTER TABLE t1 DEFAULT CHARSET=latin2;
ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `comment` char(32) NOT NULL default '',
+ `comment` char(32) NOT NULL,
`koi8_ru_f` char(32) character set koi8r NOT NULL default '',
- `latin5_f` char(32) character set latin5 NOT NULL default '',
- `latin2_f` char(32) NOT NULL default ''
+ `latin5_f` char(32) character set latin5 NOT NULL,
+ `latin2_f` char(32) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin2
ALTER TABLE t1 DROP latin2_f, DROP latin5_f;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `comment` char(32) NOT NULL default '',
+ `comment` char(32) NOT NULL,
`koi8_ru_f` char(32) character set koi8r NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin2
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A');
@@ -219,7 +219,7 @@ z LAT CAPIT Z 2
Ñ CYR CAPIT E 2
ÑŽ CYR CAPIT YU 2
Ñ CYR CAPIT YA 2
-ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL;
+ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL default '';
UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8);
SET CHARACTER SET koi8r;
SELECT * FROM t1;
@@ -340,7 +340,7 @@ CYR CAPIT SOFT SIGN ø ø
CYR CAPIT E ü ü
CYR CAPIT YU à à
CYR CAPIT YA ñ ñ
-ALTER TABLE t1 ADD bin_f CHAR(32) BYTE NOT NULL;
+ALTER TABLE t1 ADD bin_f CHAR(32) BYTE NOT NULL default '';
UPDATE t1 SET bin_f=koi8_ru_f;
SELECT COUNT(DISTINCT bin_f),COUNT(DISTINCT koi8_ru_f),COUNT(DISTINCT utf8_f) FROM t1;
COUNT(DISTINCT bin_f) COUNT(DISTINCT koi8_ru_f) COUNT(DISTINCT utf8_f)
diff --git a/mysql-test/r/ctype_mb.result b/mysql-test/r/ctype_mb.result
index dbdb9c1343c..f6e14e1a78f 100644
--- a/mysql-test/r/ctype_mb.result
+++ b/mysql-test/r/ctype_mb.result
@@ -3,16 +3,16 @@ CREATE TABLE t1 SELECT _utf8'test' as c1, _utf8'теÑÑ‚' as c2;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` char(4) character set utf8 NOT NULL default '',
- `c2` char(4) character set utf8 NOT NULL default ''
+ `c1` varchar(4) character set utf8 NOT NULL default '',
+ `c2` varchar(4) character set utf8 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DELETE FROM t1;
ALTER TABLE t1 ADD c3 CHAR(4) CHARACTER SET utf8;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` char(4) character set utf8 NOT NULL default '',
- `c2` char(4) character set utf8 NOT NULL default '',
+ `c1` varchar(4) character set utf8 NOT NULL default '',
+ `c2` varchar(4) character set utf8 NOT NULL default '',
`c3` char(4) character set utf8 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES ('aaaabbbbccccdddd','aaaabbbbccccdddd','aaaabbbbccccdddd');
diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result
index 1c75988fd21..da0007fdfbe 100644
--- a/mysql-test/r/ctype_recoding.result
+++ b/mysql-test/r/ctype_recoding.result
@@ -50,11 +50,11 @@ Tables_in_test
SHOW CREATE TABLE ÔÁÂÌÉÃÁ;
Table Create Table
ÔÁÂÌÉÃÁ CREATE TABLE `ÔÁÂÌÉÃÁ` (
- `ÐÏÌÅ` char(32) character set koi8r NOT NULL default '' COMMENT 'ËÏÍÍÅÎÔÁÒÉÊ ÐÏÌÑ'
+ `ÐÏÌÅ` char(32) character set koi8r NOT NULL COMMENT 'ËÏÍÍÅÎÔÁÒÉÊ ÐÏÌÑ'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='ËÏÍÍÅÎÔÁÒÉÊ ÔÁÂÌÉÃÙ'
SHOW FIELDS FROM ÔÁÂÌÉÃÁ;
Field Type Null Key Default Extra
-ÐÏÌÅ char(32)
+ÐÏÌÅ char(32) NO
SET CHARACTER SET cp1251;
SHOW TABLES;
Tables_in_test
@@ -62,11 +62,11 @@ Tables_in_test
SHOW CREATE TABLE òàáëèöà;
Table Create Table
òàáëèöà CREATE TABLE `òàáëèöà` (
- `ïîëå` char(32) character set koi8r NOT NULL default '' COMMENT 'êîììåíòàðèé ïîëÿ'
+ `ïîëå` char(32) character set koi8r NOT NULL COMMENT 'êîììåíòàðèé ïîëÿ'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='êîììåíòàðèé òàáëèöû'
SHOW FIELDS FROM òàáëèöà;
Field Type Null Key Default Extra
-ïîëå char(32)
+ïîëå char(32) NO
SET CHARACTER SET utf8;
SHOW TABLES;
Tables_in_test
@@ -74,11 +74,11 @@ Tables_in_test
SHOW CREATE TABLE таблица;
Table Create Table
таблица CREATE TABLE `таблица` (
- `поле` char(32) character set koi8r NOT NULL default '' COMMENT 'комментарий полÑ'
+ `поле` char(32) character set koi8r NOT NULL COMMENT 'комментарий полÑ'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='комментарий таблицы'
SHOW FIELDS FROM таблица;
Field Type Null Key Default Extra
-поле char(32)
+поле char(32) NO
SET CHARACTER SET koi8r;
DROP TABLE ÔÁÂÌÉÃÁ;
SET CHARACTER SET default;
diff --git a/mysql-test/r/ctype_tis620.result b/mysql-test/r/ctype_tis620.result
index 6d8bfe74c4b..5734f7cac86 100644
--- a/mysql-test/r/ctype_tis620.result
+++ b/mysql-test/r/ctype_tis620.result
@@ -259,8 +259,8 @@ WU
¡Ñ³°ªÒ
¡Ñ³°Ô¡Ò
¡Ñ³·ÔÁÒ
-¡Ñ¹µì
¡Ñ¹µÔ¡Ã
+¡Ñ¹µì
¡Ñ¹¸ÔªÒ
¡Ñ¹¸ÔÁÒ
¡Ñ¹ÂÒÃѵ¹ì
@@ -272,8 +272,8 @@ WU
¡Ò­¨¹ÇÃó
¡Ò­¨¹Ò
¡Ò¹´Ò
-¡Ò¹µì
¡Ò¹µìÃÇÕ
+¡Ò¹µì
¡ÒÂÊÔ·¸Ôì
¡ÒÃÇÔÍÃ
¡ÒÃسÕ
@@ -350,8 +350,8 @@ WU
à¡ÕÂõÔÈÑ¡´Ôì
à¡ÕÂõÔÊÇÑÊ´Ôì
à¡×éÍ¡ÙÅ
-á¡éÇ
á¡éÇã¨
+á¡éÇ
â¡Ážѹ¸ì
â¡àÁÈ
â¡ÅºÍÅ ¤Í¹à¹ç¤ªÑè¹Êì
@@ -368,8 +368,8 @@ WU
¢¨Ãà¡ÕÂõÔ
¢¨ÃÈÃÕ
¢¨ÃÈÑ¡´Ôì
-¢¹ÔÉ°ì
¢¹ÔÉ°Ò
+¢¹ÔÉ°ì
¢ÇÑ­ã¨
¢ÇÑ­ªÑÂ
¢ÇÑ­à´×͹
@@ -412,8 +412,8 @@ WU
ठÊËÒÂÍÔÁà»ê¡«ì
à¤.«Õ.¾Õ. áÁªªÕ¹à¹ÍÃÕè
षշÕÅÔÊ«Ôè§
-ह áÁ¡«ì (»ÃÐà·Èä·Â)
ह áÁç¡«ì (»ÃÐà·Èä·Â)
+ह áÁ¡«ì (»ÃÐà·Èä·Â)
à¤Ã×ÍÇÑÅÂì
᤹¹Ù ÍÔ¹àµÍÃìà·Ã´
á¤Ð¨éÍÂ
@@ -494,12 +494,12 @@ WU
¨ÓàÃÔ­
¨ÓÅͧ
¨Ô³³ì
-¨Ôµµì
¨Ôµµì¹ÔÉÒ
¨ÔµµÁÒÊ
¨ÔµµÒ
¨ÔµµÔ
¨ÔµµÔ¹¹Ñ¹·ì
+¨Ôµµì
¨ÔµÃÅ´Ò
¨ÔµÃÒ
¨ÔµÃÒÀóì
@@ -627,10 +627,10 @@ WU
ªÇ¹¾ÔÈ
ªÇÅÔµ
ªÇÔÈÒ
-ªèÍ
ªèͩѵÃ
ªèÍ·Ô¾Âì
ªèÍÍÑ­ªÑ­
+ªèÍ
ªÐ¹ÔÅ
ªÐÍé͹
ªÑªªÑÂ
@@ -758,12 +758,12 @@ WU
³¸ÔµÒ
³ÀÑ·Ã
³Àѷáóì
-³Ã§¤ì
³Ã§¤ìªÑÂ
³Ã§¤ì¾ÑªÃì
³Ã§¤ìÄ·¸Ôì
³Ã§¤ìÇÔ·Âì
³Ã§¤ìÈÑ¡´Ôì
+³Ã§¤ì
³Ã§ÃÑ¡Éì
³Ã§Ä·¸Ôì
³Ã§ÈÑ¡´Ôì
@@ -862,11 +862,11 @@ WU
µÐÇѹ
µÑ觨Ñè§ËÅÍ´ä¿
µÒà¿ç´
-µØê
µØ꡵Ò
µØéÁ
µØëÂ
µØÅÒÅѡɳì
+µØê
àµçÁà´ª
àµ×͹ã¨
àµ×͹µÒ
@@ -917,8 +917,8 @@ WU
·Ñº·ÔÁ
·ÑȹÇÃó
·ÑȹվÃ
-·ÑȹÕÂì
·ÑȹÕÂÒ
+·ÑȹÕÂì
·ÑÈÇÃó
·èÒ·ÃÒÂá¨é§ÇѲ¹Ò
·Ô¦ÑÁ¾Ã
@@ -1088,8 +1088,8 @@ WU
¹Ã¾Å
¹ÃÀÑ·Ãì
¹ÃÒ
-¹ÃÔ¹·Ãì
¹ÃÔ¹·Ãìà´ª
+¹ÃÔ¹·Ãì
¹ÃÔÈ
¹ÃÔÉ°
¹ÃÕ
@@ -1115,8 +1115,8 @@ WU
¹Ñ·¸Á¹
¹Ñ¹ªÑÂ
¹Ñ¹·ªÑÂ
-¹Ñ¹·¹ì
¹Ñ¹·¹Ò
+¹Ñ¹·¹ì
¹Ñ¹·¾Ã
¹Ñ¹·¾Å
¹Ñ¹·ÁÒÊ
@@ -1148,14 +1148,14 @@ WU
¹Ôà«Ð
¹Ô´
¹Ô´Ò
-¹ÔµÂì
¹ÔµÂÒ
+¹ÔµÂì
¹ÔµÔ
¹ÔµÔ¾§Éì
¹ÔµÔÁÒ
¹Ô·ÃÒ
-¹Ô·Ñȹì
¹Ô·ÑȹÕÂì
+¹Ô·Ñȹì
¹Ô¸ÔÇ´Õ
¹Ô»»Í¹à¾¹µì(»ÃÐà·Èä·Â)
¹Ô¾¹¸ì
@@ -1349,8 +1349,8 @@ WU
»ÃÒ³ÕÂì
»ÃÒâÁ·Âì
»ÃÒö¹Ò
-»ÃÔ­­ì
»ÃÔ­­Ò
+»ÃÔ­­ì
»ÃÔ­´Ò
»ÃÔ³´Ò
»ÃÔ·ÑÈ
@@ -1454,10 +1454,10 @@ WU
¾§ÉìÈÑ¡´Ôì
¾§ÉìÊѹµì
¾§Éì͹ѹµì
-¾¨¹ì
¾¨¹Ò
¾¨¹Òö
¾¨¹ÕÂì
+¾¨¹ì
¾¨ÁÒ¹
¾¨ÁÒÅÂì
¾¹Á
@@ -1504,8 +1504,8 @@ WU
¾ÃÊÇÃäì
¾ÃËÁ¾Ñ²¹ì
¾ÃéÍÁªÑÂ
-¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì
¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì ¨Ó¡Ñ´
+¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì
¾ÃÐÃÒÁ 3 ¤ÒÃìà«ç¹àµÍÃì
¾ÃÐÃÒÁ 3 Î͹´éÒ¤ÒÃìÊì
¾ÃÔéÁà¾ÃÒ
@@ -1604,10 +1604,10 @@ WU
¾Ùŷͧ¾Ãç;à¾ÍÃìµÕé_
¾ÙżÅ
à¾ç§ ¿Ù ËÅÔ¹
-à¾çªÃì
ྪÃÃѵ¹ì
ྪÃÅ´Ò
ྪÃÔ¹·Ãì
+à¾çªÃì
à¾ç­¨Ñ¹·Ãì
à¾ç­·Ô¾Âì
à¾ç­¹ÀÒ
@@ -1831,7 +1831,6 @@ WU
ÃÒàÁÈÃì
ÃÒÂÕ¹
Ã×è¹ÇÃÒËì
-ÃØé§
ÃØ觷ԾÂì
ÃØ觷ÔÇÒ
ÃØ觹ÀÒ
@@ -1840,11 +1839,12 @@ WU
ÃØè§Ãѵ¹ì
ÃØè§ÃÑÈÁÕ
ÃØè§àÃ×ͧ
-ÃØè§âè¹ì
ÃØè§âè¹ì¢¹Êè§
+ÃØè§âè¹ì
ÃØé§ÅÒÇÃó
ÃØè§ÇÔ·Âì
ÃØè§ÍÃس
+ÃØé§
ÃبÒ
ÃبÒÀÒ
ÃØËйÒ
@@ -1861,8 +1861,8 @@ WU
áþᾤ ¤Í¹ÊµÃѤªÑè¹
âç§Ò¹àËÅç¡¡Ãا෾Ï
âè¹ì»ÃÐàÊÃÔ°
-Ä·¸Ôì
Ä·¸ÔªÑÂ
+Ä·¸Ôì
ÅÅÔ´Ò
ÅÅÔµÒ
ÅÐÁèÍÁ
@@ -2050,8 +2050,8 @@ WU
ÇÔäÅÇÃó
ÇÔÇ
ÇÔÇÃø¹ì
-ÇÔÇѲ¹ì
ÇÔÇѲ¹ìªÑÂ
+ÇÔÇѲ¹ì
ÇÔȹÕ
ÇÔÈÃص
ÇÔÈÒÅ
@@ -2146,11 +2146,11 @@ WU
ÈÈÔÇÔÁÅ
ÈÈÔÉÒ
ÈÑ¡´Ò
-ÈÑ¡´Ôì
ÈÑ¡´ÔìªÑÂ
ÈÑ¡´ÔìàªÇ§
ÈÑ¡´Ôì´Ò
ÈÑ¡´ÔìÇÔºÙÅÂì
+ÈÑ¡´Ôì
ÈÑ¡ÃÔ¹·Ãì
ÈѹʹÕÂì
ÈÒ¹µÔᏴì
@@ -2348,18 +2348,18 @@ WU
ÊÓÃÒ­
ÊÓÄ·¸Ôì
ÊÓÅÕ
-ÊÔ§Ëì
ÊÔ§Ëì¾Å
ÊÔ§ËÒ
+ÊÔ§Ëì
ÊԵҹѹ
ÊÔµÒ¾Ã
ÊÔ·¸Ò
-ÊÔ·¸Ôì
ÊÔ·¸ÔªÑÂ
ÊÔ·¸Ôà´ª
ÊÔ·¸Ô¾Ã
ÊÔ·¸Ô¾Ãó
ÊÔ·¸Ô¾Å
+ÊÔ·¸Ôì
ÊÔ¹·ÇÕ
ÊÔÃÔªÑÂ
ÊÔÃÔà´ª
@@ -2393,15 +2393,15 @@ WU
ÊØ¢ÊÇÑÊ´Ôì¡Å¡ÒÃ
ÊØ¢Êѹµì
ÊØ¢ØÁ
-Êؤ¹¸ì
Êؤ¹¸Ò
+Êؤ¹¸ì
ÊبÒÃÕ
ÊبԵ
ÊبԵµÒ
ÊبԵÃÒ
ÊبԹ´Ò
-ÊبԹµì
ÊبԹµ¹ì
+ÊبԹµì
ÊتÅ
ÊتÑÂ
ÊتҴÒ
@@ -2443,13 +2443,13 @@ WU
ÊظԴÒ
ÊظÔÈÑ¡´Ôì
ÊظÕ
-ÊظÕÃì
ÊظÕÃÒ
+ÊظÕÃì
Êع·Ã
Êع·ÃÕ
Êعѷ·Õ
-Êعѹ·ì
Êعѹ·Ò
+Êعѹ·ì
ÊعԵÒ
ÊعÔÈÒ
ÊعÔÉÒ
@@ -2511,10 +2511,10 @@ WU
ÊØÃÈÑ¡´Ôì
ÊØÃÊÔ·¸Ôì
ÊØÃѪ¹Õ¡Ã
-ÊØÃѵ¹ì
ÊØÃѵ¹Ç´Õ
ÊØÃѵ¹ìÇ´Õ
ÊØÃѵ¹Ò
+ÊØÃѵ¹ì
ÊØÃѵÂÒ
ÊØÃÒ§¤¹Ò
ÊØÃÔªÑÂ
@@ -2529,8 +2529,8 @@ WU
ÊØÃÕ¸Ò¾Ã
ÊØÃÕ¾Ã
ÊØÃÕÁÒÈ
-ÊØÃÕÂì
ÊØÃÕÂì¾Ã
+ÊØÃÕÂì
ÊØÃÕÃѵ¹ì
ÊØÅÑ´´Ò
ÊØÇÀÑ·Ãì
@@ -2540,9 +2540,9 @@ WU
ÊØÇÃóÕ
ÊØÇÃóÕÂì
ÊØÇÃѵ¹ì
-ÊØÇѲ¹ì
ÊØÇѲ¹ìªÑÂ
ÊØÇѲ¹Ò
+ÊØÇѲ¹ì
ÊØÇѵªÑÂ
ÊØÇÒÃÕ
ÊØÇÔªÑÂ
@@ -2623,8 +2623,8 @@ WU
͹¹·ì
͹ÇѪ
͹ѭ­Ò
-͹ѹµì
͹ѹµÈÑ¡´Ôì
+͹ѹµì
͹ءԵÔ
͹ءÙÅ
͹تÒ
@@ -2770,8 +2770,8 @@ WU
ÍÒÃÒ¾Ã
ÍÒÃÔÂÒ
ÍÒÃÕ
-ÍÒÃÕÂì
ÍÒÃÕÂì àÊÁÒ©ÔÁ (ä·Âູ¡Ñ¹
+ÍÒÃÕÂì
ÍÒÃÕÃѵ¹ì
ÍÒÃÕÇÃó
ÍÓ¹ÇÂ
diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result
index c6e803904a3..e2805e41f3a 100644
--- a/mysql-test/r/ctype_uca.result
+++ b/mysql-test/r/ctype_uca.result
@@ -1905,6 +1905,116 @@ Z,z,Ź,ź,Ż,ż,Ž,ž
Ç
Ç‚
ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_esperanto_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
+Ç€
+Ç‚
+ǃ
drop table t1;
SET NAMES utf8;
CREATE TABLE t1 (c varchar(255) NOT NULL COLLATE utf8_general_ci, INDEX (c));
@@ -2396,3 +2506,27 @@ utf8_unicode_ci 6109
utf8_unicode_ci 61
utf8_unicode_ci 6120
drop table t1;
+CREATE TABLE t1 (id int, a varchar(30) character set utf8);
+INSERT INTO t1 VALUES (1, _ucs2 0x01310069), (2, _ucs2 0x01310131);
+INSERT INTO t1 VALUES (3, _ucs2 0x00690069), (4, _ucs2 0x01300049);
+INSERT INTO t1 VALUES (5, _ucs2 0x01300130), (6, _ucs2 0x00490049);
+SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
+FROM t1 ORDER BY id;
+a la l ll u lu
+ıi 3 ıi 3 II 2
+ıı 4 ıı 4 II 2
+ii 2 ii 2 II 2
+Ä°I 3 ii 2 Ä°I 3
+Ä°Ä° 4 ii 2 Ä°Ä° 4
+II 2 ii 2 II 2
+ALTER TABLE t1 MODIFY a VARCHAR(30) character set utf8 collate utf8_turkish_ci;
+SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
+FROM t1 ORDER BY id;
+a la l ll u lu
+ıi 3 ıi 3 Iİ 3
+ıı 4 ıı 4 II 2
+ii 2 ii 2 Ä°Ä° 4
+İI 3 iı 3 İI 3
+Ä°Ä° 4 ii 2 Ä°Ä° 4
+II 2 ıı 4 II 2
+DROP TABLE t1;
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 6d00f13737d..4bc2ed0fdc8 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -23,16 +23,24 @@ select binary 'a a' > 'a', binary 'a \0' > 'a', binary 'a\0' > 'a';
binary 'a a' > 'a' binary 'a \0' > 'a' binary 'a\0' > 'a'
1 1 1
SET CHARACTER SET koi8r;
-CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2);
-INSERT INTO t1 VALUES (_koi8r'ò'), (X'2004');
+CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004');
SELECT hex(word) FROM t1 ORDER BY word;
hex(word)
0420
2004
+SELECT hex(word2) FROM t1 ORDER BY word2;
+hex(word2)
+0420
+2004
DELETE FROM t1;
-INSERT INTO t1 VALUES (X'042000200020'), (X'200400200020');
+INSERT INTO t1 VALUES (X'042000200020',X'042000200020'), (X'200400200020', X'200400200020');
SELECT hex(word) FROM t1 ORDER BY word;
hex(word)
+042000200020
+200400200020
+SELECT hex(word2) FROM t1 ORDER BY word2;
+hex(word2)
0420
2004
DROP TABLE t1;
@@ -66,8 +74,8 @@ RPAD(_ucs2 X'0420',10,_ucs2 X'0421') r;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `l` char(10) character set ucs2 NOT NULL default '',
- `r` char(10) character set ucs2 NOT NULL default ''
+ `l` varchar(10) character set ucs2 NOT NULL default '',
+ `r` varchar(10) character set ucs2 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
create table t2(f1 Char(30));
@@ -85,10 +93,10 @@ create table t1 (a varchar(10) character set ucs2, key(a));
insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
explain select * from t1 where a like 'abc%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 21 NULL 1 Using where; Using index
+1 SIMPLE t1 range a a 23 NULL 1 Using where; Using index
explain select * from t1 where a like concat('abc','%');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 21 NULL 1 Using where; Using index
+1 SIMPLE t1 range a a 23 NULL 1 Using where; Using index
select * from t1 where a like "abc%";
a
abc
@@ -313,7 +321,7 @@ aardvark 0
aardvarz 0
EXPLAIN SELECT word FROM t1 ORDER BY word;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL PRIMARY 128 NULL 6 Using index
+1 SIMPLE t1 index NULL PRIMARY 130 NULL 6 Using index
SELECT word FROM t1 ORDER by word;
word
a
@@ -337,7 +345,7 @@ INSERT INTO t1 (word) VALUES ("aardvara");
INSERT INTO t1 (word) VALUES ("aardvarz");
EXPLAIN SELECT * FROM t1 ORDER BY WORD;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL PRIMARY 128 NULL 6 Using index
+1 SIMPLE t1 index NULL PRIMARY 130 NULL 6 Using index
SELECT * FROM t1 ORDER BY word;
word
a
@@ -627,7 +635,7 @@ DROP TABLE t1;
CREATE TABLE t1 (Field1 int(10) unsigned default '0');
INSERT INTO t1 VALUES ('-1');
Warnings:
-Warning 1265 Data truncated for column 'Field1' at row 1
+Warning 1264 Out of range value adjusted for column 'Field1' at row 1
DROP TABLE t1;
SET NAMES latin1;
CREATE TABLE t1 (
@@ -641,3 +649,30 @@ hex(a)
005B
803D
drop table t1;
+CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3));
+INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0);
+update t1 set b=a;
+SELECT * FROM t1;
+a b
+1.1 1.100
+2.1 2.100
+DROP TABLE t1;
+create table t1 (utext varchar(20) character set ucs2);
+insert into t1 values ("lily");
+insert into t1 values ("river");
+prepare stmt from 'select utext from t1 where utext like ?';
+set @param1='%%';
+execute stmt using @param1;
+utext
+lily
+river
+execute stmt using @param1;
+utext
+lily
+river
+select utext from t1 where utext like '%%';
+utext
+lily
+river
+drop table t1;
+deallocate prepare stmt;
diff --git a/mysql-test/r/ctype_ucs_binlog.result b/mysql-test/r/ctype_ucs_binlog.result
index 29718fa32a1..4267e495959 100644
--- a/mysql-test/r/ctype_ucs_binlog.result
+++ b/mysql-test/r/ctype_ucs_binlog.result
@@ -3,13 +3,20 @@ create table t2 (c char(30)) charset=ucs2;
set @v=convert('abc' using ucs2);
reset master;
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 @`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci
-master-bin.000001 119 Query 1 119 use `test`; insert into t2 values (@v)
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 User var 1 138 @`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci
+master-bin.000001 138 Query 1 227 use `test`; insert into t2 values (@v)
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET @`v`:=_ucs2 0x006100620063 COLLATE `ucs2_general_ci`;
use test;
SET TIMESTAMP=10000;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t2 values (@v);
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
drop table t2;
diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result
index dec1baf4a4b..0bc101d491d 100644
--- a/mysql-test/r/ctype_ujis.result
+++ b/mysql-test/r/ctype_ujis.result
@@ -123,7 +123,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=ujis
SHOW COLUMNS FROM t1;
Field Type Null Key Default Extra
-a char(1)
+a char(1) NO
b enum('¤¢','¤¤') YES NULL
DROP TABLE t1;
CREATE TABLE t1
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 9f2d7eac700..8e10e97d49d 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -124,7 +124,7 @@ create table t1 select date_format("2004-01-19 10:10:10", "%Y-%m-%d");
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` binary(10) default NULL
+ `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` varbinary(10) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1;
date_format("2004-01-19 10:10:10", "%Y-%m-%d")
@@ -285,7 +285,7 @@ create table t2 select ifnull(a,a) from t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `ifnull(a,a)` char(5) character set utf8 default NULL
+ `ifnull(a,a)` varchar(5) character set utf8 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t2;
ifnull(a,a)
@@ -413,7 +413,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`c` char(10) character set utf8 default NULL,
UNIQUE KEY `a` USING HASH (`c`(1))
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1 values ('aa');
ERROR 23000: Duplicate entry 'aa' for key 1
@@ -449,7 +449,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`c` char(10) character set utf8 default NULL,
UNIQUE KEY `a` USING BTREE (`c`(1))
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1 values ('aa');
ERROR 23000: Duplicate entry 'aa' for key 1
@@ -571,7 +571,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`c` char(10) character set utf8 collate utf8_bin default NULL,
UNIQUE KEY `a` USING HASH (`c`(1))
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1 values ('aa');
ERROR 23000: Duplicate entry 'aa' for key 1
@@ -607,7 +607,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`c` char(10) character set utf8 collate utf8_bin default NULL,
UNIQUE KEY `a` USING BTREE (`c`(1))
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
insert into t1 values ('aa');
ERROR 23000: Duplicate entry 'aa' for key 1
@@ -809,8 +809,8 @@ create table t2 select concat(a,_utf8'') as a, concat(b,_utf8'')as b from t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `a` char(5) character set utf8 NOT NULL default '',
- `b` char(15) character set utf8 NOT NULL default ''
+ `a` varchar(5) character set utf8 NOT NULL default '',
+ `b` varchar(15) character set utf8 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t2;
drop table t1;
@@ -997,18 +997,6 @@ select * from t1 where a like "%abc\d%";
a
abcd
drop table t1;
-set names utf8;
-create table t1 (a char(3), b varchar(10));
-insert into t1 values ('bar','kostja');
-prepare my_stmt from "select * from t1 where a=?";
-set @a:='bar';
-execute my_stmt using @a;
-a b
-bar kostja
-set @a:=NULL;
-execute my_stmt using @a;
-a b
-drop table t1;
CREATE TABLE t1 (
a varchar(255) NOT NULL default '',
KEY a (a)
@@ -1020,3 +1008,73 @@ hex(a)
5B
E880BD
drop table t1;
+CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa');
+SELECT id FROM t1;
+id
+xxx
+aa
+yyy
+aa
+SELECT DISTINCT id FROM t1;
+id
+xxx
+aa
+yyy
+SELECT DISTINCT id FROM t1 ORDER BY id;
+id
+aa
+xxx
+yyy
+DROP TABLE t1;
+set names utf8;
+select hex(char(1));
+hex(char(1))
+01
+select char(0xd1,0x8f);
+char(0xd1,0x8f)
+select char(0xd18f);
+char(0xd18f)
+select char(53647);
+char(53647)
+select char(0xff,0x8f);
+char(0xff,0x8f)
+ÿ
+Warnings:
+Warning 1300 Invalid utf8 character string: 'FF8F'
+set sql_mode=traditional;
+select char(0xff,0x8f);
+char(0xff,0x8f)
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'FF8F'
+select char(195);
+char(195)
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'C3'
+select char(196);
+char(196)
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'C4'
+select char(2557);
+char(2557)
+NULL
+Warnings:
+Error 1300 Invalid utf8 character string: 'FD'
+set names utf8;
+create table t1 (a char(1)) default character set utf8;
+create table t2 (a char(1)) default character set utf8;
+insert into t1 values('a'),('a'),(0xE38182),(0xE38182);
+insert into t1 values('i'),('i'),(0xE38184),(0xE38184);
+select * from t1 union distinct select * from t2;
+a
+a
+ã‚
+i
+ã„
+drop table t1,t2;
diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result
index 2db014c4a52..74ab1e35534 100644
--- a/mysql-test/r/date_formats.result
+++ b/mysql-test/r/date_formats.result
@@ -79,6 +79,11 @@ concat('%d-%m-%Y',' ','%H:%i:%s.%f'));
str_to_date(concat('15-01-2001',' 2:59:58.999'),
concat('%d-%m-%Y',' ','%H:%i:%s.%f'))
2001-01-15 02:59:58.999000
+select STR_TO_DATE('2004.12.12 22.30.61','%Y.%m.%d %T');
+STR_TO_DATE('2004.12.12 22.30.61','%Y.%m.%d %T')
+NULL
+Warnings:
+Error 1411 Incorrect time value: '22.30.61' for function str_to_time
create table t1 (date char(30), format char(30) not null);
insert into t1 values
('2003-01-02 10:11:12', '%Y-%m-%d %H:%i:%S'),
@@ -335,6 +340,22 @@ Tuesday 52 2001 %W %V %Y NULL
Tuesday 52 2001 %W %u %x NULL
7 53 1998 %w %u %Y NULL
NULL %m.%d.%Y NULL
+Warnings:
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_time
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12.123456' for function str_to_time
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12AM' for function str_to_time
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12AN' for function str_to_time
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_time
+Error 1411 Incorrect datetime value: '10:20:10AM' for function str_to_time
+Error 1411 Incorrect datetime value: '15 Septembei 2001' for function str_to_time
+Error 1411 Incorrect datetime value: '15 Ju 2001' for function str_to_time
+Error 1411 Incorrect datetime value: 'Sund 15 MA' for function str_to_time
+Error 1411 Incorrect datetime value: 'Thursdai 12 1998' for function str_to_time
+Error 1411 Incorrect datetime value: 'Sunday 01 2001' for function str_to_time
+Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_time
+Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_time
+Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_time
+Error 1411 Incorrect datetime value: '7 53 1998' for function str_to_time
select date,format,concat(str_to_date(date, format),'') as con from t1;
date format con
2003-01-02 10:11:12 PM %Y-%m-%d %H:%i:%S %p NULL
@@ -353,6 +374,22 @@ Tuesday 52 2001 %W %V %Y NULL
Tuesday 52 2001 %W %u %x NULL
7 53 1998 %w %u %Y NULL
NULL %m.%d.%Y NULL
+Warnings:
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_time
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12.123456' for function str_to_time
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12AM' for function str_to_time
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12AN' for function str_to_time
+Error 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_time
+Error 1411 Incorrect datetime value: '10:20:10AM' for function str_to_time
+Error 1411 Incorrect datetime value: '15 Septembei 2001' for function str_to_time
+Error 1411 Incorrect datetime value: '15 Ju 2001' for function str_to_time
+Error 1411 Incorrect datetime value: 'Sund 15 MA' for function str_to_time
+Error 1411 Incorrect datetime value: 'Thursdai 12 1998' for function str_to_time
+Error 1411 Incorrect datetime value: 'Sunday 01 2001' for function str_to_time
+Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_time
+Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_time
+Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_time
+Error 1411 Incorrect datetime value: '7 53 1998' for function str_to_time
truncate table t1;
insert into t1 values
('10:20:10AM', '%h:%i:%s'),
@@ -391,11 +428,13 @@ NULL
select str_to_date('15-01-2001 12:59:59', GET_FORMAT(DATE,'USA'));
str_to_date('15-01-2001 12:59:59', GET_FORMAT(DATE,'USA'))
NULL
+Warnings:
+Error 1411 Incorrect datetime value: '15-01-2001 12:59:59' for function str_to_time
explain extended select makedate(1997,1), addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002"),subtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002"),timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM"),cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME), maketime(23,11,12),microsecond("1997-12-31 23:59:59.000001");
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select makedate(1997,1) AS `makedate(1997,1)`,addtime(_latin1'31.12.97 11.59.59.999999 PM',_latin1'31.12.97 11.59.59.999999 PM') AS `addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002")`,subtime(_latin1'31.12.97 11.59.59.999999 PM',_latin1'31.12.97 11.59.59.999999 PM') AS `subtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002")`,timediff(_latin1'01.01.97 11:59:59.000001 PM',_latin1'31.12.95 11:59:59.000002 PM') AS `timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM")`,cast(str_to_date(_latin1'15-01-2001 12:59:59',_latin1'%d-%m-%Y %H:%i:%S') as time) AS `cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME)`,maketime(23,11,12) AS `maketime(23,11,12)`,microsecond(_latin1'1997-12-31 23:59:59.000001') AS `microsecond("1997-12-31 23:59:59.000001")`
+Note 1003 select makedate(1997,1) AS `makedate(1997,1)`,addtime(_latin1'31.12.97 11.59.59.999999 PM',_latin1'1 1.1.1.000002') AS `addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002")`,subtime(_latin1'31.12.97 11.59.59.999999 PM',_latin1'1 1.1.1.000002') AS `subtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002")`,timediff(_latin1'01.01.97 11:59:59.000001 PM',_latin1'31.12.95 11:59:59.000002 PM') AS `timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM")`,cast(str_to_date(_latin1'15-01-2001 12:59:59',_latin1'%d-%m-%Y %H:%i:%S') as time) AS `cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME)`,maketime(23,11,12) AS `maketime(23,11,12)`,microsecond(_latin1'1997-12-31 23:59:59.000001') AS `microsecond("1997-12-31 23:59:59.000001")`
create table t1 (d date);
insert into t1 values ('2004-07-14'),('2005-07-14');
select date_format(d,"%d") from t1 order by 1;
diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result
new file mode 100644
index 00000000000..7db20c2b096
--- /dev/null
+++ b/mysql-test/r/default.result
@@ -0,0 +1,138 @@
+drop table if exists t1,t2,t3,t4,t5,t6;
+drop database if exists mysqltest;
+CREATE TABLE t1 (a varchar(30) binary NOT NULL DEFAULT ' ',
+b varchar(1) binary NOT NULL DEFAULT ' ',
+c varchar(4) binary NOT NULL DEFAULT '0000',
+d tinyblob NULL,
+e tinyblob NULL,
+f tinyblob NULL,
+g tinyblob NULL,
+h tinyblob NULL,
+i tinyblob NULL,
+j tinyblob NULL,
+k tinyblob NULL,
+l tinyblob NULL,
+m tinyblob NULL,
+n tinyblob NULL,
+o tinyblob NULL,
+p tinyblob NULL,
+q varchar(30) binary NOT NULL DEFAULT ' ',
+r varchar(30) binary NOT NULL DEFAULT ' ',
+s tinyblob NULL,
+t varchar(4) binary NOT NULL DEFAULT ' ',
+u varchar(1) binary NOT NULL DEFAULT ' ',
+v varchar(30) binary NOT NULL DEFAULT ' ',
+w varchar(30) binary NOT NULL DEFAULT ' ',
+x tinyblob NULL,
+y varchar(5) binary NOT NULL DEFAULT ' ',
+z varchar(20) binary NOT NULL DEFAULT ' ',
+a1 varchar(30) binary NOT NULL DEFAULT ' ',
+b1 tinyblob NULL)
+ENGINE=InnoDB DEFAULT CHARACTER SET = latin1 COLLATE latin1_bin;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `b` varchar(1) collate latin1_bin NOT NULL default ' ',
+ `c` varchar(4) collate latin1_bin NOT NULL default '0000',
+ `d` tinyblob,
+ `e` tinyblob,
+ `f` tinyblob,
+ `g` tinyblob,
+ `h` tinyblob,
+ `i` tinyblob,
+ `j` tinyblob,
+ `k` tinyblob,
+ `l` tinyblob,
+ `m` tinyblob,
+ `n` tinyblob,
+ `o` tinyblob,
+ `p` tinyblob,
+ `q` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `r` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `s` tinyblob,
+ `t` varchar(4) collate latin1_bin NOT NULL default ' ',
+ `u` varchar(1) collate latin1_bin NOT NULL default ' ',
+ `v` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `w` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `x` tinyblob,
+ `y` varchar(5) collate latin1_bin NOT NULL default ' ',
+ `z` varchar(20) collate latin1_bin NOT NULL default ' ',
+ `a1` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `b1` tinyblob
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin
+INSERT into t1 (b) values ('1');
+SHOW WARNINGS;
+Level Code Message
+SELECT * from t1;
+a b c d e f g h i j k l m n o p q r s t u v w x y z a1 b1
+ 1 0000 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+CREATE TABLE t2 (a varchar(30) binary NOT NULL DEFAULT ' ',
+b varchar(1) binary NOT NULL DEFAULT ' ',
+c varchar(4) binary NOT NULL DEFAULT '0000',
+d tinyblob NULL,
+e tinyblob NULL,
+f tinyblob NULL,
+g tinyblob NULL,
+h tinyblob NULL,
+i tinyblob NULL,
+j tinyblob NULL,
+k tinyblob NULL,
+l tinyblob NULL,
+m tinyblob NULL,
+n tinyblob NULL,
+o tinyblob NULL,
+p tinyblob NULL,
+q varchar(30) binary NOT NULL DEFAULT ' ',
+r varchar(30) binary NOT NULL DEFAULT ' ',
+s tinyblob NULL,
+t varchar(4) binary NOT NULL DEFAULT ' ',
+u varchar(1) binary NOT NULL DEFAULT ' ',
+v varchar(30) binary NOT NULL DEFAULT ' ',
+w varchar(30) binary NOT NULL DEFAULT ' ',
+x tinyblob NULL,
+y varchar(5) binary NOT NULL DEFAULT ' ',
+z varchar(20) binary NOT NULL DEFAULT ' ',
+a1 varchar(30) binary NOT NULL DEFAULT ' ',
+b1 tinyblob NULL)
+ENGINE=MyISAM DEFAULT CHARACTER SET = latin1 COLLATE latin1_bin;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `b` varchar(1) collate latin1_bin NOT NULL default ' ',
+ `c` varchar(4) collate latin1_bin NOT NULL default '0000',
+ `d` tinyblob,
+ `e` tinyblob,
+ `f` tinyblob,
+ `g` tinyblob,
+ `h` tinyblob,
+ `i` tinyblob,
+ `j` tinyblob,
+ `k` tinyblob,
+ `l` tinyblob,
+ `m` tinyblob,
+ `n` tinyblob,
+ `o` tinyblob,
+ `p` tinyblob,
+ `q` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `r` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `s` tinyblob,
+ `t` varchar(4) collate latin1_bin NOT NULL default ' ',
+ `u` varchar(1) collate latin1_bin NOT NULL default ' ',
+ `v` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `w` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `x` tinyblob,
+ `y` varchar(5) collate latin1_bin NOT NULL default ' ',
+ `z` varchar(20) collate latin1_bin NOT NULL default ' ',
+ `a1` varchar(30) collate latin1_bin NOT NULL default ' ',
+ `b1` tinyblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin
+INSERT into t2 (b) values ('1');
+SHOW WARNINGS;
+Level Code Message
+SELECT * from t2;
+a b c d e f g h i j k l m n o p q r s t u v w x y z a1 b1
+ 1 0000 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+drop table t1;
+drop table t2;
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index ceb511a7891..f8ae61b03fb 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -22,6 +22,9 @@ insert delayed into t1 values (null,"c");
insert delayed into t1 values (3,"d"),(null,"e");
insert delayed into t1 values (3,"this will give an","error");
ERROR 21S01: Column count doesn't match value count at row 1
+show status like 'not_flushed_delayed_rows';
+Variable_name Value
+Not_flushed_delayed_rows 0
select * from t1;
a b
1 b
@@ -29,3 +32,10 @@ a b
3 d
4 e
drop table t1;
+create table t1 (a int not null primary key);
+insert into t1 values (1);
+insert delayed into t1 values (1);
+select * from t1;
+a
+1
+drop table t1;
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index 411cd52b4ca..ddfeeac77b5 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t11,t12,t2;
+drop table if exists t1,t2,t3,t11,t12;
CREATE TABLE t1 (a tinyint(3), b tinyint(5));
INSERT INTO t1 VALUES (1,1);
INSERT LOW_PRIORITY INTO t1 VALUES (1,2);
@@ -172,3 +172,23 @@ a
0
2
DROP TABLE t1;
+CREATE TABLE t1 (a int not null,b int not null);
+CREATE TABLE t2 (a int not null, b int not null, primary key (a,b));
+CREATE TABLE t3 (a int not null, b int not null, primary key (a,b));
+insert into t1 values (1,1),(2,1),(1,3);
+insert into t2 values (1,1),(2,2),(3,3);
+insert into t3 values (1,1),(2,1),(1,3);
+select * from t1,t2,t3 where t1.a=t2.a AND t2.b=t3.a and t1.b=t3.b;
+a b a b a b
+1 1 1 1 1 1
+2 1 2 2 2 1
+1 3 1 1 1 3
+explain select * from t1,t2,t3 where t1.a=t2.a AND t2.b=t3.a and t1.b=t3.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 index PRIMARY PRIMARY 8 NULL 3 Using where; Using index
+1 SIMPLE t3 index PRIMARY PRIMARY 8 NULL 3 Using where; Using index
+delete t2.*,t3.* from t1,t2,t3 where t1.a=t2.a AND t2.b=t3.a and t1.b=t3.b;
+select * from t3;
+a b
+drop table t1,t2,t3;
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index b4d9a921178..7c9d88acf90 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -111,7 +111,7 @@ a b
1 a
2 b
3 c
-explain select * from (select * from t1,t2 where t1.a=t2.a) t1;
+explain select * from (select t1.*, t2.a as t2a from t1,t2 where t1.a=t2.a) t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t2 system NULL NULL NULL NULL 1
@@ -149,8 +149,8 @@ SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
(SELECT * FROM (SELECT 1 as a) as a )
1
select * from (select 1 as a) b left join (select 2 as a) c using(a);
-a a
-1 NULL
+a
+1
SELECT * FROM (SELECT 1 UNION SELECT a) b;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
@@ -318,11 +318,11 @@ create table t2 (a int, b int, primary key (a));
insert into t2 values (1,7),(2,7);
explain select a from t2 where a>1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 2 Using where; Using index
+1 SIMPLE t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index
explain select a from (select a from t2 where a>1) tt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
-2 DERIVED t2 range PRIMARY PRIMARY 4 NULL 2 Using where; Using index
+2 DERIVED t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index
drop table t2;
CREATE TABLE `t1` ( `itemid` int(11) NOT NULL default '0', `grpid` varchar(15) NOT NULL default '', `vendor` int(11) NOT NULL default '0', `date_` date NOT NULL default '0000-00-00', `price` decimal(12,2) NOT NULL default '0.00', PRIMARY KEY (`itemid`,`grpid`,`vendor`,`date_`), KEY `itemid` (`itemid`,`vendor`), KEY `itemid_2` (`itemid`,`date_`));
insert into t1 values (128, 'rozn', 2, now(), 10),(128, 'rozn', 1, now(), 10);
@@ -339,6 +339,11 @@ select distinct sum(b) from (select a,b from t1) y group by a;
sum(b)
4
drop table t1;
+CREATE TABLE t1 (a char(10), b char(10));
+INSERT INTO t1 VALUES ('root','localhost'), ('root','%');
+SELECT * FROM (SELECT (SELECT a.a FROM t1 AS a WHERE a.a = b.a) FROM t1 AS b) AS c;
+ERROR 21000: Subquery returns more than 1 row
+DROP TABLE t1;
create table t1(a int);
create table t2(a int);
create table t3(a int);
@@ -358,3 +363,8 @@ a
3
3
drop table t1, t2, t3;
+create table t1 (a int);
+create table t2 (a int);
+select * from (select * from t1,t2) foo;
+ERROR 42S21: Duplicate column name 'a'
+drop table t1,t2;
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 8932285b5d0..00436019f85 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -212,7 +212,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 Using index
explain SELECT distinct a from t3 order by a desc limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 index NULL a 5 NULL 204 Using index
+1 SIMPLE t3 index NULL a 5 NULL 10 Using index
explain SELECT distinct a,b from t3 order by a+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
@@ -388,8 +388,8 @@ SELECT DISTINCTROW email, shipcode FROM t1, t2 WHERE t1.infoID=t2.infoID;
email shipcode
test1@testdomain.com Z001
test2@testdomain.com Z001
-test3@testdomain.com Z001
test2@testdomain.com R002
+test3@testdomain.com Z001
SELECT DISTINCTROW email FROM t1 ORDER BY dateentered DESC;
email
test1@testdomain.com
@@ -457,12 +457,12 @@ drop table t1,t2;
CREATE TABLE t1 (
html varchar(5) default NULL,
rin int(11) default '0',
-out int(11) default '0'
+rout int(11) default '0'
) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('1',1,0);
-SELECT DISTINCT html,SUM(out)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
+SELECT DISTINCT html,SUM(rout)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
html prod
-1 0.00
+1 0.0000
drop table t1;
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
@@ -504,3 +504,11 @@ a 2 b
2 2 4
3 2 5
DROP TABLE t1,t2;
+create table t1 (id int, dsc varchar(50));
+insert into t1 values (1, "line number one"), (2, "line number two"), (3, "line number three");
+select distinct id, IFNULL(dsc, '-') from t1;
+id IFNULL(dsc, '-')
+1 line number one
+2 line number two
+3 line number three
+drop table t1;
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index b07cf16aa64..979e5d48871 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -46,6 +46,7 @@ unlock tables;
create database mysqltest;
show databases;
Database
+information_schema
mysql
mysqltest
test
@@ -56,6 +57,7 @@ unlock tables;
drop database mysqltest;
show databases;
Database
+information_schema
mysql
test
drop database mysqltest;
diff --git a/mysql-test/r/drop_temp_table.result b/mysql-test/r/drop_temp_table.result
index 5f1f142cde5..26b8511661a 100644
--- a/mysql-test/r/drop_temp_table.result
+++ b/mysql-test/r/drop_temp_table.result
@@ -11,12 +11,11 @@ select get_lock("a",10);
get_lock("a",10)
1
show binlog events;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 # Start 1 # Server ver: VERSION, Binlog ver: 3
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
master-bin.000001 # Query 1 # create database `drop-temp+table-test`
master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn1 (a int)
master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table `table:name` (a int)
master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn2 (a int)
master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2`,`drop-temp+table-test`.`table:name`,`drop-temp+table-test`.`shortn1`
-master-bin.000001 # Query 1 # use `drop-temp+table-test`; DO RELEASE_LOCK("a")
drop database `drop-temp+table-test`;
diff --git a/mysql-test/r/endspace.result b/mysql-test/r/endspace.result
index 96210a0e16d..0e68418a80f 100644
--- a/mysql-test/r/endspace.result
+++ b/mysql-test/r/endspace.result
@@ -43,7 +43,7 @@ teststring
teststring
explain select * from t1 order by text1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL key1 32 NULL 3 Using index
+1 SIMPLE t1 index NULL key1 34 NULL 3 Using index
alter table t1 modify text1 char(32) binary not null;
check table t1;
Table Op Msg_type Msg_text
@@ -99,15 +99,15 @@ concat('|', text1, '|')
explain select concat('|', text1, '|') from t1 where text1='teststring ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range key1 key1 22 NULL 2 Using where
-select * from t1 where text1 like 'teststring_%';
-text1
-teststring
-teststring
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
-text1
-teststring
-teststring
-teststring
+select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
+concat('|', text1, '|')
+|teststring |
+|teststring |
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
+concat('|', text1, '|')
+|teststring |
+|teststring|
+|teststring |
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
concat('|', text1, '|')
|teststring|
@@ -121,14 +121,14 @@ concat('|', text1, '|')
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1)) pack_keys=0;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
-text1
-teststring
-teststring
-select * from t1 where text1='teststring' or text1 >= 'teststring\t';
-text1
-teststring
-teststring
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
+concat('|', text1, '|')
+|teststring |
+|teststring|
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 >= 'teststring\t';
+concat('|', text1, '|')
+|teststring |
+|teststring|
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
@@ -151,7 +151,7 @@ teststring
teststring
explain select * from t1 order by text1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL key1 32 NULL 3
+1 SIMPLE t1 index NULL key1 34 NULL 3
alter table t1 modify text1 char(32) binary not null;
select * from t1 order by text1;
text1
@@ -178,7 +178,7 @@ teststring
teststring
explain select * from t1 order by text1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL key1 32 NULL 3 Using index
+1 SIMPLE t1 index NULL key1 34 NULL 3 Using index
alter table t1 modify text1 char(32) binary not null;
select * from t1 order by text1;
text1
@@ -200,13 +200,13 @@ teststring
teststring
select text1, length(text1) from t1 where text1='teststring' or text1 like 'teststring_%';
text1 length(text1)
-teststring 10
teststring 11
+teststring 10
teststring 11
select text1, length(text1) from t1 where text1='teststring' or text1 >= 'teststring\t';
text1 length(text1)
-teststring 10
teststring 11
+teststring 10
teststring 11
select concat('|', text1, '|') from t1 order by text1;
concat('|', text1, '|')
diff --git a/mysql-test/r/errors.result b/mysql-test/r/errors.result
index d0011c8deb6..0c84f24a2e4 100644
--- a/mysql-test/r/errors.result
+++ b/mysql-test/r/errors.result
@@ -9,9 +9,9 @@ create table t1 (a int);
select count(test.t1.b) from t1;
ERROR 42S22: Unknown column 'test.t1.b' in 'field list'
select count(not_existing_database.t1) from t1;
-ERROR 42S02: Unknown table 'not_existing_database' in field list
+ERROR 42S22: Unknown column 'not_existing_database.t1' in 'field list'
select count(not_existing_database.t1.a) from t1;
-ERROR 42S02: Unknown table 'not_existing_database.t1' in field list
+ERROR 42S22: Unknown column 'not_existing_database.t1.a' in 'field list'
select count(not_existing_database.t1.a) from not_existing_database.t1;
Got one of the listed errors
select 1 from t1 order by 2;
@@ -23,3 +23,8 @@ ERROR 42S22: Unknown column 't1.b' in 'order clause'
select count(*),b from t1;
ERROR 42S22: Unknown column 'b' in 'field list'
drop table t1;
+create table t1 (a int(256));
+ERROR 42000: Display width out of range for column 'a' (max = 255)
+set sql_mode='traditional';
+create table t1 (a varchar(66000));
+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead
diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result
new file mode 100644
index 00000000000..1ec9857c8a7
--- /dev/null
+++ b/mysql-test/r/federated.result
@@ -0,0 +1,1463 @@
+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;
+stop slave;
+DROP DATABASE IF EXISTS federated;
+CREATE DATABASE federated;
+DROP DATABASE IF EXISTS federated;
+CREATE DATABASE federated;
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:@/too/many/items/federated/t1';
+ERROR HY000: Can't create federated table. The data source connection string 'mysql://root@127.0.0.1:@/too/many/items/federated/t1' is not in the correct format
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1';
+ERROR HY000: Can't create federated table. The data source connection string 'mysql://root@127.0.0.1' is not in the correct format
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3';
+ERROR HY000: Can't create federated table. Foreign data src error : ': 1146 : Table 'federated.t3' doesn't exist'
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1';
+ERROR HY000: Unable to connect to foreign data source - database ' database federated username user hostname 127.0.0.1'!
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (id, name) VALUES (1, 'foo');
+INSERT INTO federated.t1 (id, name) VALUES (2, 'fee');
+SELECT * FROM federated.t1;
+id name
+1 foo
+2 fee
+DELETE FROM federated.t1;
+DROP TABLE federated.t1;
+DROP TABLE IF EXISTS federated.t2;
+Warnings:
+Note 1051 Unknown table 't2'
+CREATE TABLE federated.t2 (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t2 (id, name) VALUES (1, 'foo');
+INSERT INTO federated.t2 (id, name) VALUES (2, 'fee');
+SELECT * FROM federated.t2;
+id name
+1 foo
+2 fee
+DROP TABLE federated.t2;
+DROP TABLE IF EXISTS federated.t1;
+DROP TABLE IF EXISTS federated.`t1%`;
+Warnings:
+Note 1051 Unknown table 't1%'
+CREATE TABLE federated.`t1%` (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1%';
+INSERT INTO federated.t1 (id, name) VALUES (1, 'foo');
+INSERT INTO federated.t1 (id, name) VALUES (2, 'fee');
+SELECT * FROM federated.t1;
+id name
+1 foo
+2 fee
+DELETE FROM federated.t1;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.`t1%` (
+`id` int(20) NOT NULL,
+`name` varchar(32) NOT NULL default ''
+ )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1%';
+INSERT INTO federated.`t1%` (id, name) VALUES (1, 'foo');
+INSERT INTO federated.`t1%` (id, name) VALUES (2, 'fee');
+SELECT * FROM federated.`t1%`;
+id name
+1 foo
+2 fee
+DELETE FROM federated.`t1%`;
+DROP TABLE IF EXISTS federated.`t1%`;
+DROP TABLE IF EXISTS federated.`t1%`;
+DROP TABLE IF EXISTS federated.t1;
+Warnings:
+Note 1051 Unknown table 't1'
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`name` varchar(32) NOT NULL default '',
+`other` int(20) NOT NULL default '0',
+`created` datetime default '2004-04-04 04:04:04',
+PRIMARY KEY (`id`))
+DEFAULT CHARSET=latin1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`name` varchar(32) NOT NULL default '',
+`other` int(20) NOT NULL default '0',
+`created` datetime default '2004-04-04 04:04:04',
+PRIMARY KEY (`id`))
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (name, other) VALUES ('First Name', 11111);
+INSERT INTO federated.t1 (name, other) VALUES ('Second Name', 22222);
+INSERT INTO federated.t1 (name, other) VALUES ('Third Name', 33333);
+INSERT INTO federated.t1 (name, other) VALUES ('Fourth Name', 44444);
+INSERT INTO federated.t1 (name, other) VALUES ('Fifth Name', 55555);
+INSERT INTO federated.t1 (name, other) VALUES ('Sixth Name', 66666);
+INSERT INTO federated.t1 (name, other) VALUES ('Seventh Name', 77777);
+INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888);
+INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999);
+INSERT INTO federated.t1 (name, other) VALUES ('Tenth Name', 101010);
+SELECT * FROM federated.t1;
+id name other created
+1 First Name 11111 2004-04-04 04:04:04
+2 Second Name 22222 2004-04-04 04:04:04
+3 Third Name 33333 2004-04-04 04:04:04
+4 Fourth Name 44444 2004-04-04 04:04:04
+5 Fifth Name 55555 2004-04-04 04:04:04
+6 Sixth Name 66666 2004-04-04 04:04:04
+7 Seventh Name 77777 2004-04-04 04:04:04
+8 Eigth Name 88888 2004-04-04 04:04:04
+9 Ninth Name 99999 2004-04-04 04:04:04
+10 Tenth Name 101010 2004-04-04 04:04:04
+SELECT * FROM federated.t1 WHERE id = 5;
+id name other created
+5 Fifth Name 55555 2004-04-04 04:04:04
+SELECT * FROM federated.t1 WHERE name = 'Sixth Name';
+id name other created
+6 Sixth Name 66666 2004-04-04 04:04:04
+SELECT * FROM federated.t1 WHERE id = 6 and name = 'Sixth Name';
+id name other created
+6 Sixth Name 66666 2004-04-04 04:04:04
+SELECT * FROM federated.t1 WHERE name = 'Sixth Name' AND other = 44444;
+id name other created
+SELECT * FROM federated.t1 WHERE name like '%th%';
+id name other created
+3 Third Name 33333 2004-04-04 04:04:04
+4 Fourth Name 44444 2004-04-04 04:04:04
+5 Fifth Name 55555 2004-04-04 04:04:04
+6 Sixth Name 66666 2004-04-04 04:04:04
+7 Seventh Name 77777 2004-04-04 04:04:04
+8 Eigth Name 88888 2004-04-04 04:04:04
+9 Ninth Name 99999 2004-04-04 04:04:04
+10 Tenth Name 101010 2004-04-04 04:04:04
+UPDATE federated.t1 SET name = '3rd name' WHERE id = 3;
+SELECT * FROM federated.t1 WHERE name = '3rd name';
+id name other created
+3 3rd name 33333 2004-04-04 04:04:04
+UPDATE federated.t1 SET name = 'Third name' WHERE name = '3rd name';
+SELECT * FROM federated.t1 WHERE name = 'Third name';
+id name other created
+3 Third name 33333 2004-04-04 04:04:04
+SELECT * FROM federated.t1 ORDER BY id DESC;
+id name other created
+10 Tenth Name 101010 2004-04-04 04:04:04
+9 Ninth Name 99999 2004-04-04 04:04:04
+8 Eigth Name 88888 2004-04-04 04:04:04
+7 Seventh Name 77777 2004-04-04 04:04:04
+6 Sixth Name 66666 2004-04-04 04:04:04
+5 Fifth Name 55555 2004-04-04 04:04:04
+4 Fourth Name 44444 2004-04-04 04:04:04
+3 Third name 33333 2004-04-04 04:04:04
+2 Second Name 22222 2004-04-04 04:04:04
+1 First Name 11111 2004-04-04 04:04:04
+SELECT * FROM federated.t1 ORDER BY name;
+id name other created
+8 Eigth Name 88888 2004-04-04 04:04:04
+5 Fifth Name 55555 2004-04-04 04:04:04
+1 First Name 11111 2004-04-04 04:04:04
+4 Fourth Name 44444 2004-04-04 04:04:04
+9 Ninth Name 99999 2004-04-04 04:04:04
+2 Second Name 22222 2004-04-04 04:04:04
+7 Seventh Name 77777 2004-04-04 04:04:04
+6 Sixth Name 66666 2004-04-04 04:04:04
+10 Tenth Name 101010 2004-04-04 04:04:04
+3 Third name 33333 2004-04-04 04:04:04
+SELECT * FROM federated.t1 ORDER BY name DESC;
+id name other created
+3 Third name 33333 2004-04-04 04:04:04
+10 Tenth Name 101010 2004-04-04 04:04:04
+6 Sixth Name 66666 2004-04-04 04:04:04
+7 Seventh Name 77777 2004-04-04 04:04:04
+2 Second Name 22222 2004-04-04 04:04:04
+9 Ninth Name 99999 2004-04-04 04:04:04
+4 Fourth Name 44444 2004-04-04 04:04:04
+1 First Name 11111 2004-04-04 04:04:04
+5 Fifth Name 55555 2004-04-04 04:04:04
+8 Eigth Name 88888 2004-04-04 04:04:04
+SELECT * FROM federated.t1 ORDER BY name ASC;
+id name other created
+8 Eigth Name 88888 2004-04-04 04:04:04
+5 Fifth Name 55555 2004-04-04 04:04:04
+1 First Name 11111 2004-04-04 04:04:04
+4 Fourth Name 44444 2004-04-04 04:04:04
+9 Ninth Name 99999 2004-04-04 04:04:04
+2 Second Name 22222 2004-04-04 04:04:04
+7 Seventh Name 77777 2004-04-04 04:04:04
+6 Sixth Name 66666 2004-04-04 04:04:04
+10 Tenth Name 101010 2004-04-04 04:04:04
+3 Third name 33333 2004-04-04 04:04:04
+SELECT * FROM federated.t1 GROUP BY other;
+id name other created
+1 First Name 11111 2004-04-04 04:04:04
+2 Second Name 22222 2004-04-04 04:04:04
+3 Third name 33333 2004-04-04 04:04:04
+4 Fourth Name 44444 2004-04-04 04:04:04
+5 Fifth Name 55555 2004-04-04 04:04:04
+6 Sixth Name 66666 2004-04-04 04:04:04
+7 Seventh Name 77777 2004-04-04 04:04:04
+8 Eigth Name 88888 2004-04-04 04:04:04
+9 Ninth Name 99999 2004-04-04 04:04:04
+10 Tenth Name 101010 2004-04-04 04:04:04
+DELETE FROM federated.t1 WHERE id = 5;
+SELECT * FROM federated.t1 WHERE id = 5;
+id name other created
+DELETE FROM federated.t1;
+SELECT * FROM federated.t1 WHERE id = 5;
+id name other created
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`name` varchar(32) NOT NULL default '',
+`other` int(20) NOT NULL default '0',
+`created` datetime NOT NULL,
+PRIMARY KEY (`id`),
+key name(`name`),
+key other(`other`),
+key created(`created`))
+DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`name` varchar(32) NOT NULL default '',
+`other` int(20) NOT NULL default '0',
+`created` datetime NOT NULL,
+PRIMARY KEY (`id`),
+key name(`name`),
+key other(`other`),
+key created(`created`))
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('First Name', 11111, '2004-01-01 01:01:01');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Second Name', 22222, '2004-01-23 02:43:00');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Third Name', 33333, '2004-02-14 02:14:00');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Fourth Name', 44444, '2003-04-05 00:00:00');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Fifth Name', 55555, '2001-02-02 02:02:02');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Sixth Name', 66666, '2005-06-06 15:30:00');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Seventh Name', 77777, '2003-12-12 18:32:00');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Eigth Name', 88888, '2005-03-12 11:00:00');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Ninth Name', 99999, '2005-03-12 11:00:01');
+INSERT INTO federated.t1 (name, other, created)
+VALUES ('Tenth Name', 101010, '2005-03-12 12:00:01');
+SELECT * FROM federated.t1;
+id name other created
+1 First Name 11111 2004-01-01 01:01:01
+2 Second Name 22222 2004-01-23 02:43:00
+3 Third Name 33333 2004-02-14 02:14:00
+4 Fourth Name 44444 2003-04-05 00:00:00
+5 Fifth Name 55555 2001-02-02 02:02:02
+6 Sixth Name 66666 2005-06-06 15:30:00
+7 Seventh Name 77777 2003-12-12 18:32:00
+8 Eigth Name 88888 2005-03-12 11:00:00
+9 Ninth Name 99999 2005-03-12 11:00:01
+10 Tenth Name 101010 2005-03-12 12:00:01
+SELECT * FROM federated.t1 WHERE id = 5;
+id name other created
+5 Fifth Name 55555 2001-02-02 02:02:02
+SELECT * FROM federated.t1 WHERE id = 6 and name = 'Sixth Name';
+id name other created
+6 Sixth Name 66666 2005-06-06 15:30:00
+SELECT * FROM federated.t1 WHERE other = 44444;
+id name other created
+4 Fourth Name 44444 2003-04-05 00:00:00
+SELECT * FROM federated.t1 WHERE name like '%th%';
+id name other created
+3 Third Name 33333 2004-02-14 02:14:00
+4 Fourth Name 44444 2003-04-05 00:00:00
+5 Fifth Name 55555 2001-02-02 02:02:02
+6 Sixth Name 66666 2005-06-06 15:30:00
+7 Seventh Name 77777 2003-12-12 18:32:00
+8 Eigth Name 88888 2005-03-12 11:00:00
+9 Ninth Name 99999 2005-03-12 11:00:01
+10 Tenth Name 101010 2005-03-12 12:00:01
+UPDATE federated.t1 SET name = '3rd name' WHERE id = 3;
+SELECT * FROM federated.t1 WHERE name = '3rd name';
+id name other created
+3 3rd name 33333 2004-02-14 02:14:00
+UPDATE federated.t1 SET name = 'Third name' WHERE name = '3rd name';
+SELECT * FROM federated.t1 WHERE name = 'Third name';
+id name other created
+3 Third name 33333 2004-02-14 02:14:00
+SELECT * FROM federated.t1 ORDER BY id DESC;
+id name other created
+10 Tenth Name 101010 2005-03-12 12:00:01
+9 Ninth Name 99999 2005-03-12 11:00:01
+8 Eigth Name 88888 2005-03-12 11:00:00
+7 Seventh Name 77777 2003-12-12 18:32:00
+6 Sixth Name 66666 2005-06-06 15:30:00
+5 Fifth Name 55555 2001-02-02 02:02:02
+4 Fourth Name 44444 2003-04-05 00:00:00
+3 Third name 33333 2004-02-14 02:14:00
+2 Second Name 22222 2004-01-23 02:43:00
+1 First Name 11111 2004-01-01 01:01:01
+SELECT * FROM federated.t1 ORDER BY name;
+id name other created
+8 Eigth Name 88888 2005-03-12 11:00:00
+5 Fifth Name 55555 2001-02-02 02:02:02
+1 First Name 11111 2004-01-01 01:01:01
+4 Fourth Name 44444 2003-04-05 00:00:00
+9 Ninth Name 99999 2005-03-12 11:00:01
+2 Second Name 22222 2004-01-23 02:43:00
+7 Seventh Name 77777 2003-12-12 18:32:00
+6 Sixth Name 66666 2005-06-06 15:30:00
+10 Tenth Name 101010 2005-03-12 12:00:01
+3 Third name 33333 2004-02-14 02:14:00
+SELECT * FROM federated.t1 ORDER BY name DESC;
+id name other created
+3 Third name 33333 2004-02-14 02:14:00
+10 Tenth Name 101010 2005-03-12 12:00:01
+6 Sixth Name 66666 2005-06-06 15:30:00
+7 Seventh Name 77777 2003-12-12 18:32:00
+2 Second Name 22222 2004-01-23 02:43:00
+9 Ninth Name 99999 2005-03-12 11:00:01
+4 Fourth Name 44444 2003-04-05 00:00:00
+1 First Name 11111 2004-01-01 01:01:01
+5 Fifth Name 55555 2001-02-02 02:02:02
+8 Eigth Name 88888 2005-03-12 11:00:00
+SELECT * FROM federated.t1 ORDER BY name ASC;
+id name other created
+8 Eigth Name 88888 2005-03-12 11:00:00
+5 Fifth Name 55555 2001-02-02 02:02:02
+1 First Name 11111 2004-01-01 01:01:01
+4 Fourth Name 44444 2003-04-05 00:00:00
+9 Ninth Name 99999 2005-03-12 11:00:01
+2 Second Name 22222 2004-01-23 02:43:00
+7 Seventh Name 77777 2003-12-12 18:32:00
+6 Sixth Name 66666 2005-06-06 15:30:00
+10 Tenth Name 101010 2005-03-12 12:00:01
+3 Third name 33333 2004-02-14 02:14:00
+SELECT * FROM federated.t1 GROUP BY other;
+id name other created
+1 First Name 11111 2004-01-01 01:01:01
+2 Second Name 22222 2004-01-23 02:43:00
+3 Third name 33333 2004-02-14 02:14:00
+4 Fourth Name 44444 2003-04-05 00:00:00
+5 Fifth Name 55555 2001-02-02 02:02:02
+6 Sixth Name 66666 2005-06-06 15:30:00
+7 Seventh Name 77777 2003-12-12 18:32:00
+8 Eigth Name 88888 2005-03-12 11:00:00
+9 Ninth Name 99999 2005-03-12 11:00:01
+10 Tenth Name 101010 2005-03-12 12:00:01
+DELETE FROM federated.t1 WHERE id = 5;
+SELECT * FROM federated.t1 WHERE id = 5;
+id name other created
+DELETE FROM federated.t1;
+SELECT * FROM federated.t1 WHERE id = 5;
+id name other created
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`name` varchar(32),
+`other` varchar(20),
+PRIMARY KEY (`id`) );
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`name` varchar(32),
+`other` varchar(20),
+PRIMARY KEY (`id`) )
+ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (name, other) VALUES ('First Name', 11111);
+INSERT INTO federated.t1 (name, other) VALUES ('Second Name', NULL);
+INSERT INTO federated.t1 (name, other) VALUES ('Third Name', 33333);
+INSERT INTO federated.t1 (name, other) VALUES (NULL, NULL);
+INSERT INTO federated.t1 (name, other) VALUES ('Fifth Name', 55555);
+INSERT INTO federated.t1 (name, other) VALUES ('Sixth Name', 66666);
+INSERT INTO federated.t1 (name) VALUES ('Seventh Name');
+INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888);
+INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999);
+INSERT INTO federated.t1 (other) VALUES ('fee fie foe fum');
+SELECT * FROM federated.t1 WHERE other IS NULL;
+id name other
+2 Second Name NULL
+4 NULL NULL
+7 Seventh Name NULL
+SELECT * FROM federated.t1 WHERE name IS NULL;
+id name other
+4 NULL NULL
+10 NULL fee fie foe fum
+SELECT * FROM federated.t1 WHERE name IS NULL and other IS NULL;
+id name other
+4 NULL NULL
+SELECT * FROM federated.t1 WHERE name IS NULL or other IS NULL;
+id name other
+2 Second Name NULL
+4 NULL NULL
+7 Seventh Name NULL
+10 NULL fee fie foe fum
+UPDATE federated.t1
+SET name = 'Fourth Name', other = 'four four four'
+WHERE name IS NULL AND other IS NULL;
+UPDATE federated.t1 SET other = 'two two two two' WHERE name = 'Second Name';
+UPDATE federated.t1 SET other = 'seven seven' WHERE name like 'Sev%';
+UPDATE federated.t1 SET name = 'Tenth Name' WHERE other like 'fee fie%';
+SELECT * FROM federated.t1 WHERE name IS NULL OR other IS NULL ;
+id name other
+SELECT * FROM federated.t1;
+id name other
+1 First Name 11111
+2 Second Name two two two two
+3 Third Name 33333
+4 Fourth Name four four four
+5 Fifth Name 55555
+6 Sixth Name 66666
+7 Seventh Name seven seven
+8 Eigth Name 88888
+9 Ninth Name 99999
+10 Tenth Name fee fie foe fum
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`name` varchar(32) NOT NULL DEFAULT '',
+`other` varchar(20) NOT NULL DEFAULT '',
+PRIMARY KEY (`id`),
+KEY nameoth (name, other) );
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`name` varchar(32) NOT NULL DEFAULT '',
+`other` varchar(20) NOT NULL DEFAULT '',
+PRIMARY KEY (`id`),
+KEY nameoth (name, other))
+ENGINE="FEDERATED" DEFAULT
+CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (name, other) VALUES ('First Name', '1111');
+INSERT INTO federated.t1 (name, other) VALUES ('Second Name', '2222');
+INSERT INTO federated.t1 (name, other) VALUES ('Third Name', '3333');
+SELECT * FROM federated.t1 WHERE name = 'Second Name';
+id name other
+2 Second Name 2222
+SELECT * FROM federated.t1 WHERE other = '2222';
+id name other
+2 Second Name 2222
+SELECT * FROM federated.t1 WHERE name = 'Third Name';
+id name other
+3 Third Name 3333
+SELECT * FROM federated.t1 WHERE name = 'Third Name' AND other = '3333';
+id name other
+3 Third Name 3333
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int NOT NULL auto_increment,
+`name` char(32) NOT NULL DEFAULT '',
+`bincol` binary(4) NOT NULL,
+`floatval` decimal(5,2) NOT NULL DEFAULT 0.0,
+`other` int NOT NULL DEFAULT 0,
+PRIMARY KEY (id),
+KEY nameoth(name, other),
+KEY bincol(bincol),
+KEY floatval(floatval));
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int NOT NULL auto_increment,
+`name` char(32) NOT NULL DEFAULT '',
+`bincol` binary(4) NOT NULL,
+`floatval` decimal(5,2) NOT NULL DEFAULT 0.0,
+`other` int NOT NULL DEFAULT 0,
+PRIMARY KEY (id),
+KEY nameoth(name,other),
+KEY bincol(bincol),
+KEY floatval(floatval))
+ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (name, bincol, floatval, other)
+VALUES ('first', 0x65, 11.11, 1111);
+INSERT INTO federated.t1 (name, bincol, floatval, other)
+VALUES ('second', 0x66, 22.22, 2222);
+INSERT INTO federated.t1 (name, bincol, floatval, other)
+VALUES ('third', 'g', 22.22, 2222);
+SELECT * FROM federated.t1;
+id name bincol floatval other
+1 first e 11.11 1111
+2 second f 22.22 2222
+3 third g 22.22 2222
+SELECT * FROM federated.t1 WHERE name = 'second';
+id name bincol floatval other
+2 second f 22.22 2222
+SELECT * FROM federated.t1 WHERE bincol= 'f';
+id name bincol floatval other
+2 second f 22.22 2222
+SELECT * FROM federated.t1 WHERE bincol= 0x66;
+id name bincol floatval other
+2 second f 22.22 2222
+SELECT * FROM federated.t1 WHERE bincol= 0x67;
+id name bincol floatval other
+3 third g 22.22 2222
+SELECT * FROM federated.t1 WHERE bincol= 'g';
+id name bincol floatval other
+3 third g 22.22 2222
+SELECT * FROM federated.t1 WHERE floatval=11.11;
+id name bincol floatval other
+1 first e 11.11 1111
+SELECT * FROM federated.t1 WHERE name='third';
+id name bincol floatval other
+3 third g 22.22 2222
+SELECT * FROM federated.t1 WHERE other=2222;
+id name bincol floatval other
+2 second f 22.22 2222
+3 third g 22.22 2222
+SELECT * FROM federated.t1 WHERE name='third' and other=2222;
+id name bincol floatval other
+3 third g 22.22 2222
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int NOT NULL auto_increment,
+`col1` int(10) NOT NULL DEFAULT 0,
+`col2` varchar(64) NOT NULL DEFAULT '',
+`col3` int(20) NOT NULL,
+`col4` int(40) NOT NULL,
+primary key (`id`, `col1`, `col2`, `col3`, `col4`),
+key col1(col1),
+key col2(col2),
+key col3(col3),
+key col4(col4));
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int NOT NULL auto_increment,
+`col1` int(10) NOT NULL DEFAULT 0,
+`col2` varchar(64) NOT NULL DEFAULT '',
+`col3` int(20) NOT NULL,
+`col4` int(40) NOT NULL,
+primary key (`id`, `col1`, `col2`, `col3`, `col4`),
+key col1(col1),
+key col2(col2),
+key col3(col3),
+key col4(col4))
+ENGINE="FEDERATED"
+ CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (1, 'one One', 11, 1111);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (2, 'Two two', 22, 2222);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (3, 'three Three', 33, 33333);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (4, 'fourfourfour', 444, 4444444);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (5, 'five 5 five five 5', 5, 55555);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (6, 'six six Sixsix', 6666, 6);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (7, 'seven Sevenseven', 77777, 7777);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (8, 'eight eight eight', 88888, 88);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (9, 'nine Nine', 999999, 999999);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES (10, 'Tenth ten TEN', 1010101, 1010);
+SELECT * FROM federated.t1 WHERE col2 = 'two two';
+id col1 col2 col3 col4
+2 2 Two two 22 2222
+SELECT * FROM federated.t1 WHERE col2 = 'two Two';
+id col1 col2 col3 col4
+2 2 Two two 22 2222
+SELECT * FROM federated.t1 WHERE id = 3;
+id col1 col2 col3 col4
+3 3 three Three 33 33333
+SELECT * FROM federated.t1 WHERE id = 3 AND col1 = 3;
+id col1 col2 col3 col4
+3 3 three Three 33 33333
+SELECT * FROM federated.t1 WHERE id = 4 AND col1 = 4 AND col2 = 'Two two';
+id col1 col2 col3 col4
+SELECT * FROM federated.t1 WHERE id = 4 AND col1 = 4 AND col2 = 'fourfourfour';
+id col1 col2 col3 col4
+4 4 fourfourfour 444 4444444
+SELECT * FROM federated.t1 WHERE id = 5 AND col2 = 'five 5 five five 5'
+AND col3 = 5;
+id col1 col2 col3 col4
+5 5 five 5 five five 5 5 55555
+SELECT * FROM federated.t1 WHERE id = 5 AND col2 = 'five 5 five five 5'
+AND col3 = 5
+AND col4 = 55555;
+id col1 col2 col3 col4
+5 5 five 5 five five 5 5 55555
+SELECT * FROM federated.t1 WHERE id = 5
+AND col2 = 'Two two' AND col3 = 22
+AND col4 = 33;
+id col1 col2 col3 col4
+SELECT * FROM federated.t1 WHERE id = 5
+AND col2 = 'five 5 five five 5' AND col3 = 5
+AND col4 = 55555;
+id col1 col2 col3 col4
+5 5 five 5 five five 5 5 55555
+SELECT * FROM federated.t1 WHERE (id = 5 AND col2 = 'five 5 five five 5')
+OR (col2 = 'three Three' AND col3 = 33);
+id col1 col2 col3 col4
+5 5 five 5 five five 5 5 55555
+3 3 three Three 33 33333
+SELECT * FROM federated.t1 WHERE (id = 5 AND col2 = 'Two two')
+OR (col2 = 444 AND col3 = 4444444);
+id col1 col2 col3 col4
+SELECT * FROM federated.t1 WHERE id = 1
+OR col1 = 10
+OR col2 = 'Two two'
+OR col3 = 33
+OR col4 = 4444444;
+id col1 col2 col3 col4
+1 1 one One 11 1111
+2 2 Two two 22 2222
+3 3 three Three 33 33333
+4 4 fourfourfour 444 4444444
+10 10 Tenth ten TEN 1010101 1010
+SELECT * FROM federated.t1 WHERE id > 5;
+id col1 col2 col3 col4
+6 6 six six Sixsix 6666 6
+7 7 seven Sevenseven 77777 7777
+8 8 eight eight eight 88888 88
+9 9 nine Nine 999999 999999
+10 10 Tenth ten TEN 1010101 1010
+SELECT * FROM federated.t1 WHERE id >= 5;
+id col1 col2 col3 col4
+5 5 five 5 five five 5 5 55555
+6 6 six six Sixsix 6666 6
+7 7 seven Sevenseven 77777 7777
+8 8 eight eight eight 88888 88
+9 9 nine Nine 999999 999999
+10 10 Tenth ten TEN 1010101 1010
+SELECT * FROM federated.t1 WHERE id < 5;
+id col1 col2 col3 col4
+1 1 one One 11 1111
+2 2 Two two 22 2222
+3 3 three Three 33 33333
+4 4 fourfourfour 444 4444444
+SELECT * FROM federated.t1 WHERE id <= 5;
+id col1 col2 col3 col4
+1 1 one One 11 1111
+2 2 Two two 22 2222
+3 3 three Three 33 33333
+4 4 fourfourfour 444 4444444
+5 5 five 5 five five 5 5 55555
+SELECT * FROM federated.t1 WHERE id != 5;
+id col1 col2 col3 col4
+1 1 one One 11 1111
+2 2 Two two 22 2222
+3 3 three Three 33 33333
+4 4 fourfourfour 444 4444444
+6 6 six six Sixsix 6666 6
+7 7 seven Sevenseven 77777 7777
+8 8 eight eight eight 88888 88
+9 9 nine Nine 999999 999999
+10 10 Tenth ten TEN 1010101 1010
+SELECT * FROM federated.t1 WHERE id > 3 AND id < 7;
+id col1 col2 col3 col4
+4 4 fourfourfour 444 4444444
+5 5 five 5 five five 5 5 55555
+6 6 six six Sixsix 6666 6
+SELECT * FROM federated.t1 WHERE id > 3 AND id <= 7;
+id col1 col2 col3 col4
+4 4 fourfourfour 444 4444444
+5 5 five 5 five five 5 5 55555
+6 6 six six Sixsix 6666 6
+7 7 seven Sevenseven 77777 7777
+SELECT * FROM federated.t1 WHERE id >= 3 AND id <= 7;
+id col1 col2 col3 col4
+3 3 three Three 33 33333
+4 4 fourfourfour 444 4444444
+5 5 five 5 five five 5 5 55555
+6 6 six six Sixsix 6666 6
+7 7 seven Sevenseven 77777 7777
+SELECT * FROM federated.t1 WHERE id < 3 AND id <= 7;
+id col1 col2 col3 col4
+1 1 one One 11 1111
+2 2 Two two 22 2222
+SELECT * FROM federated.t1 WHERE id < 3 AND id > 7;
+id col1 col2 col3 col4
+SELECT * FROM federated.t1 WHERE id < 3 OR id > 7;
+id col1 col2 col3 col4
+1 1 one One 11 1111
+2 2 Two two 22 2222
+8 8 eight eight eight 88888 88
+9 9 nine Nine 999999 999999
+10 10 Tenth ten TEN 1010101 1010
+SELECT * FROM federated.t1 WHERE col2 = 'three Three';
+id col1 col2 col3 col4
+3 3 three Three 33 33333
+SELECT * FROM federated.t1 WHERE col2 > 'one';
+id col1 col2 col3 col4
+1 1 one One 11 1111
+2 2 Two two 22 2222
+3 3 three Three 33 33333
+6 6 six six Sixsix 6666 6
+7 7 seven Sevenseven 77777 7777
+10 10 Tenth ten TEN 1010101 1010
+SELECT * FROM federated.t1 WHERE col2 LIKE 's%';
+id col1 col2 col3 col4
+7 7 seven Sevenseven 77777 7777
+6 6 six six Sixsix 6666 6
+SELECT * FROM federated.t1 WHERE col2 LIKE 'si%';
+id col1 col2 col3 col4
+6 6 six six Sixsix 6666 6
+SELECT * FROM federated.t1 WHERE col2 LIKE 'se%';
+id col1 col2 col3 col4
+7 7 seven Sevenseven 77777 7777
+SELECT * FROM federated.t1 WHERE col2 NOT LIKE 'e%';
+id col1 col2 col3 col4
+1 1 one One 11 1111
+2 2 Two two 22 2222
+3 3 three Three 33 33333
+4 4 fourfourfour 444 4444444
+5 5 five 5 five five 5 5 55555
+6 6 six six Sixsix 6666 6
+7 7 seven Sevenseven 77777 7777
+9 9 nine Nine 999999 999999
+10 10 Tenth ten TEN 1010101 1010
+SELECT * FROM federated.t1 WHERE col2 <> 'one One';
+id col1 col2 col3 col4
+4 4 fourfourfour 444 4444444
+5 5 five 5 five five 5 5 55555
+8 8 eight eight eight 88888 88
+9 9 nine Nine 999999 999999
+2 2 Two two 22 2222
+3 3 three Three 33 33333
+6 6 six six Sixsix 6666 6
+7 7 seven Sevenseven 77777 7777
+10 10 Tenth ten TEN 1010101 1010
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`col1` varchar(8) NOT NULL DEFAULT '',
+`col2` varchar(128) NOT NULL DEFAULT '',
+`col3` varchar(20) NOT NULL DEFAULT '',
+`col4` varchar(40) NOT NULL DEFAULT '',
+primary key (`col1`, `col2`, `col3`, `col4`),
+key 3key(`col2`,`col3`,`col4`),
+key 2key (`col3`,`col4`),
+key col4(col4));
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`col1` varchar(8) NOT NULL DEFAULT '',
+`col2` varchar(128) NOT NULL DEFAULT '',
+`col3` varchar(20) NOT NULL DEFAULT '',
+`col4` varchar(40) NOT NULL DEFAULT '',
+primary key (`col1`, `col2`, `col3`, `col4`),
+key 3key(`col2`,`col3`,`col4`),
+key 2key (`col3`,`col4`),
+key col4(col4))
+ENGINE="FEDERATED"
+ CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES ('aaaa', 'aaaaaaaaaaaaaaaaaaa', 'ababababab', 'acacacacacacacac');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES ('bbbb', 'bbbbbbbbbbbbbbbbbbb', 'bababababa', 'bcbcbcbcbcbcbcbc');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES ('cccc', 'ccccccccccccccccccc', 'cacacacaca', 'cbcbcbcbcbcbcbcb');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES ('dddd', 'ddddddddddddddddddd', 'dadadadada', 'dcdcdcdcdcdcdcdc');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES ('eeee', 'eeeeeeeeeeeeeeeeeee', 'eaeaeaeaea', 'ecececececececec');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES ('ffff', 'fffffffffffffffffff', 'fafafafafa', 'fcfcfcfcfcfcfcfc');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES ('gggg', 'ggggggggggggggggggg', 'gagagagaga', 'gcgcgcgcgcgcgcgc');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+VALUES ('hhhh', 'hhhhhhhhhhhhhhhhhhh', 'hahahahaha', 'hchchchchchchchc');
+SELECT * FROM federated.t1 WHERE col1 = 'cccc';
+col1 col2 col3 col4
+cccc ccccccccccccccccccc cacacacaca cbcbcbcbcbcbcbcb
+SELECT * FROM federated.t1 WHERE col2 = 'eeeeeeeeeeeeeeeeeee';
+col1 col2 col3 col4
+eeee eeeeeeeeeeeeeeeeeee eaeaeaeaea ecececececececec
+SELECT * FROM federated.t1 WHERE col3 = 'bababababa';
+col1 col2 col3 col4
+bbbb bbbbbbbbbbbbbbbbbbb bababababa bcbcbcbcbcbcbcbc
+SELECT * FROM federated.t1 WHERE col1 = 'gggg' AND col2 = 'ggggggggggggggggggg';
+col1 col2 col3 col4
+gggg ggggggggggggggggggg gagagagaga gcgcgcgcgcgcgcgc
+SELECT * FROM federated.t1 WHERE col1 = 'gggg' AND col3 = 'gagagagaga';
+col1 col2 col3 col4
+gggg ggggggggggggggggggg gagagagaga gcgcgcgcgcgcgcgc
+SELECT * FROM federated.t1 WHERE col1 = 'ffff' AND col4 = 'fcfcfcfcfcfcfcfc';
+col1 col2 col3 col4
+ffff fffffffffffffffffff fafafafafa fcfcfcfcfcfcfcfc
+SELECT * FROM federated.t1 WHERE col1 > 'bbbb';
+col1 col2 col3 col4
+cccc ccccccccccccccccccc cacacacaca cbcbcbcbcbcbcbcb
+dddd ddddddddddddddddddd dadadadada dcdcdcdcdcdcdcdc
+eeee eeeeeeeeeeeeeeeeeee eaeaeaeaea ecececececececec
+ffff fffffffffffffffffff fafafafafa fcfcfcfcfcfcfcfc
+gggg ggggggggggggggggggg gagagagaga gcgcgcgcgcgcgcgc
+hhhh hhhhhhhhhhhhhhhhhhh hahahahaha hchchchchchchchc
+SELECT * FROM federated.t1 WHERE col1 >= 'bbbb';
+col1 col2 col3 col4
+bbbb bbbbbbbbbbbbbbbbbbb bababababa bcbcbcbcbcbcbcbc
+cccc ccccccccccccccccccc cacacacaca cbcbcbcbcbcbcbcb
+dddd ddddddddddddddddddd dadadadada dcdcdcdcdcdcdcdc
+eeee eeeeeeeeeeeeeeeeeee eaeaeaeaea ecececececececec
+ffff fffffffffffffffffff fafafafafa fcfcfcfcfcfcfcfc
+gggg ggggggggggggggggggg gagagagaga gcgcgcgcgcgcgcgc
+hhhh hhhhhhhhhhhhhhhhhhh hahahahaha hchchchchchchchc
+SELECT * FROM federated.t1 WHERE col1 < 'bbbb';
+col1 col2 col3 col4
+aaaa aaaaaaaaaaaaaaaaaaa ababababab acacacacacacacac
+SELECT * FROM federated.t1 WHERE col1 <= 'bbbb';
+col1 col2 col3 col4
+aaaa aaaaaaaaaaaaaaaaaaa ababababab acacacacacacacac
+bbbb bbbbbbbbbbbbbbbbbbb bababababa bcbcbcbcbcbcbcbc
+SELECT * FROM federated.t1 WHERE col1 <> 'bbbb';
+col1 col2 col3 col4
+aaaa aaaaaaaaaaaaaaaaaaa ababababab acacacacacacacac
+cccc ccccccccccccccccccc cacacacaca cbcbcbcbcbcbcbcb
+dddd ddddddddddddddddddd dadadadada dcdcdcdcdcdcdcdc
+eeee eeeeeeeeeeeeeeeeeee eaeaeaeaea ecececececececec
+ffff fffffffffffffffffff fafafafafa fcfcfcfcfcfcfcfc
+gggg ggggggggggggggggggg gagagagaga gcgcgcgcgcgcgcgc
+hhhh hhhhhhhhhhhhhhhhhhh hahahahaha hchchchchchchchc
+SELECT * FROM federated.t1 WHERE col1 LIKE 'b%';
+col1 col2 col3 col4
+bbbb bbbbbbbbbbbbbbbbbbb bababababa bcbcbcbcbcbcbcbc
+SELECT * FROM federated.t1 WHERE col4 LIKE '%b%';
+col1 col2 col3 col4
+bbbb bbbbbbbbbbbbbbbbbbb bababababa bcbcbcbcbcbcbcbc
+cccc ccccccccccccccccccc cacacacaca cbcbcbcbcbcbcbcb
+SELECT * FROM federated.t1 WHERE col1 NOT LIKE 'c%';
+col1 col2 col3 col4
+aaaa aaaaaaaaaaaaaaaaaaa ababababab acacacacacacacac
+bbbb bbbbbbbbbbbbbbbbbbb bababababa bcbcbcbcbcbcbcbc
+dddd ddddddddddddddddddd dadadadada dcdcdcdcdcdcdcdc
+eeee eeeeeeeeeeeeeeeeeee eaeaeaeaea ecececececececec
+ffff fffffffffffffffffff fafafafafa fcfcfcfcfcfcfcfc
+gggg ggggggggggggggggggg gagagagaga gcgcgcgcgcgcgcgc
+hhhh hhhhhhhhhhhhhhhhhhh hahahahaha hchchchchchchchc
+SELECT * FROM federated.t1 WHERE col4 NOT LIKE '%c%';
+col1 col2 col3 col4
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`col1` varchar(8) NOT NULL DEFAULT '',
+`col2` int(8) NOT NULL DEFAULT 0,
+`col3` varchar(8) NOT NULL DEFAULT '',
+primary key (`col1`, `col2`, `col3`));
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`col1` varchar(8) NOT NULL DEFAULT '',
+`col2` varchar(8) NOT NULL DEFAULT '',
+`col3` varchar(8) NOT NULL DEFAULT '',
+primary key (`col1`, `col2`, `col3`))
+ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 VALUES ('a00', '110', 'cc0');
+INSERT INTO federated.t1 VALUES ('aaa', '111', 'ccc');
+INSERT INTO federated.t1 VALUES ('bbb', '222', 'yyy');
+INSERT INTO federated.t1 VALUES ('ccc', '111', 'zzz');
+INSERT INTO federated.t1 VALUES ('ccd', '112', 'zzzz');
+SELECT col3 FROM federated.t1 WHERE (
+(col1 = 'aaa' AND col2 >= '111') OR col1 > 'aaa') AND
+(col1 < 'ccc' OR ( col1 = 'ccc' AND col2 <= '111'));
+col3
+ccc
+yyy
+zzz
+SELECT col3 FROM federated.t1 WHERE (
+(col1 = 'aaa' AND col2 >= '111') OR col1 > 'aaa') AND
+(col1 < 'ccc' OR ( col1 = 'ccc' AND col2 <= '111'));
+col3
+ccc
+yyy
+zzz
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int,
+`name` varchar(32),
+`floatval` float,
+`other` int)
+DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int,
+`name` varchar(32),
+`floatval` float,
+`other` int)
+ENGINE="FEDERATED"
+DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 values (NULL, NULL, NULL, NULL);
+INSERT INTO federated.t1 values ();
+INSERT INTO federated.t1 (id) VALUES (1);
+INSERT INTO federated.t1 (name, floatval, other)
+VALUES ('foo', 33.33333332, NULL);
+INSERT INTO federated.t1 (name, floatval, other)
+VALUES (0, 00.3333, NULL);
+SELECT * FROM federated.t1;
+id name floatval other
+NULL NULL NULL NULL
+NULL NULL NULL NULL
+1 NULL NULL NULL
+NULL foo 33.3333 NULL
+NULL 0 0.3333 NULL
+SELECT count(*) FROM federated.t1
+WHERE id IS NULL
+AND name IS NULL
+AND floatval IS NULL
+AND other IS NULL;
+count(*)
+2
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`blurb_id` int NOT NULL DEFAULT 0,
+`blurb` text default '',
+PRIMARY KEY (blurb_id))
+DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`blurb_id` int NOT NULL DEFAULT 0,
+`blurb` text default '',
+PRIMARY KEY (blurb_id))
+ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 VALUES (1, " MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values.");
+INSERT INTO federated.t1 VALUES (2, "All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE.");
+INSERT INTO federated.t1 VALUES (3, " A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. ");
+INSERT INTO federated.t1 VALUES(4, "Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:");
+SELECT * FROM federated.t1;
+blurb_id blurb
+1 MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values.
+2 All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE.
+3 A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined.
+4 Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`a` int NOT NULL,
+`b` int NOT NULL,
+`c` int NOT NULL,
+PRIMARY KEY (a),key(b));
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`a` int NOT NULL,
+`b` int NOT NULL,
+`c` int NOT NULL,
+PRIMARY KEY (a),
+KEY (b))
+ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 VALUES (3,3,3),(1,1,1),(2,2,2),(4,4,4);
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
+int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17
+int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
+i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34
+int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int,
+i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51
+int, i52 int, i53 int, i54 int, i55 int, i56 int, i57 int, i58 int, i59 int,
+i60 int, i61 int, i62 int, i63 int, i64 int, i65 int, i66 int, i67 int, i68
+int, i69 int, i70 int, i71 int, i72 int, i73 int, i74 int, i75 int, i76 int,
+i77 int, i78 int, i79 int, i80 int, i81 int, i82 int, i83 int, i84 int, i85
+int, i86 int, i87 int, i88 int, i89 int, i90 int, i91 int, i92 int, i93 int,
+i94 int, i95 int, i96 int, i97 int, i98 int, i99 int, i100 int, i101 int, i102
+int, i103 int, i104 int, i105 int, i106 int, i107 int, i108 int, i109 int, i110
+int, i111 int, i112 int, i113 int, i114 int, i115 int, i116 int, i117 int, i118
+int, i119 int, i120 int, i121 int, i122 int, i123 int, i124 int, i125 int, i126
+int, i127 int, i128 int, i129 int, i130 int, i131 int, i132 int, i133 int, i134
+int, i135 int, i136 int, i137 int, i138 int, i139 int, i140 int, i141 int, i142
+int, i143 int, i144 int, i145 int, i146 int, i147 int, i148 int, i149 int, i150
+int, i151 int, i152 int, i153 int, i154 int, i155 int, i156 int, i157 int, i158
+int, i159 int, i160 int, i161 int, i162 int, i163 int, i164 int, i165 int, i166
+int, i167 int, i168 int, i169 int, i170 int, i171 int, i172 int, i173 int, i174
+int, i175 int, i176 int, i177 int, i178 int, i179 int, i180 int, i181 int, i182
+int, i183 int, i184 int, i185 int, i186 int, i187 int, i188 int, i189 int, i190
+int, i191 int, i192 int, i193 int, i194 int, i195 int, i196 int, i197 int, i198
+int, i199 int, i200 int, i201 int, i202 int, i203 int, i204 int, i205 int, i206
+int, i207 int, i208 int, i209 int, i210 int, i211 int, i212 int, i213 int, i214
+int, i215 int, i216 int, i217 int, i218 int, i219 int, i220 int, i221 int, i222
+int, i223 int, i224 int, i225 int, i226 int, i227 int, i228 int, i229 int, i230
+int, i231 int, i232 int, i233 int, i234 int, i235 int, i236 int, i237 int, i238
+int, i239 int, i240 int, i241 int, i242 int, i243 int, i244 int, i245 int, i246
+int, i247 int, i248 int, i249 int, i250 int, i251 int, i252 int, i253 int, i254
+int, i255 int, i256 int, i257 int, i258 int, i259 int, i260 int, i261 int, i262
+int, i263 int, i264 int, i265 int, i266 int, i267 int, i268 int, i269 int, i270
+int, i271 int, i272 int, i273 int, i274 int, i275 int, i276 int, i277 int, i278
+int, i279 int, i280 int, i281 int, i282 int, i283 int, i284 int, i285 int, i286
+int, i287 int, i288 int, i289 int, i290 int, i291 int, i292 int, i293 int, i294
+int, i295 int, i296 int, i297 int, i298 int, i299 int, i300 int, i301 int, i302
+int, i303 int, i304 int, i305 int, i306 int, i307 int, i308 int, i309 int, i310
+int, i311 int, i312 int, i313 int, i314 int, i315 int, i316 int, i317 int, i318
+int, i319 int, i320 int, i321 int, i322 int, i323 int, i324 int, i325 int, i326
+int, i327 int, i328 int, i329 int, i330 int, i331 int, i332 int, i333 int, i334
+int, i335 int, i336 int, i337 int, i338 int, i339 int, i340 int, i341 int, i342
+int, i343 int, i344 int, i345 int, i346 int, i347 int, i348 int, i349 int, i350
+int, i351 int, i352 int, i353 int, i354 int, i355 int, i356 int, i357 int, i358
+int, i359 int, i360 int, i361 int, i362 int, i363 int, i364 int, i365 int, i366
+int, i367 int, i368 int, i369 int, i370 int, i371 int, i372 int, i373 int, i374
+int, i375 int, i376 int, i377 int, i378 int, i379 int, i380 int, i381 int, i382
+int, i383 int, i384 int, i385 int, i386 int, i387 int, i388 int, i389 int, i390
+int, i391 int, i392 int, i393 int, i394 int, i395 int, i396 int, i397 int, i398
+int, i399 int, i400 int, i401 int, i402 int, i403 int, i404 int, i405 int, i406
+int, i407 int, i408 int, i409 int, i410 int, i411 int, i412 int, i413 int, i414
+int, i415 int, i416 int, i417 int, i418 int, i419 int, i420 int, i421 int, i422
+int, i423 int, i424 int, i425 int, i426 int, i427 int, i428 int, i429 int, i430
+int, i431 int, i432 int, i433 int, i434 int, i435 int, i436 int, i437 int, i438
+int, i439 int, i440 int, i441 int, i442 int, i443 int, i444 int, i445 int, i446
+int, i447 int, i448 int, i449 int, i450 int, i451 int, i452 int, i453 int, i454
+int, i455 int, i456 int, i457 int, i458 int, i459 int, i460 int, i461 int, i462
+int, i463 int, i464 int, i465 int, i466 int, i467 int, i468 int, i469 int, i470
+int, i471 int, i472 int, i473 int, i474 int, i475 int, i476 int, i477 int, i478
+int, i479 int, i480 int, i481 int, i482 int, i483 int, i484 int, i485 int, i486
+int, i487 int, i488 int, i489 int, i490 int, i491 int, i492 int, i493 int, i494
+int, i495 int, i496 int, i497 int, i498 int, i499 int, i500 int, i501 int, i502
+int, i503 int, i504 int, i505 int, i506 int, i507 int, i508 int, i509 int, i510
+int, i511 int, i512 int, i513 int, i514 int, i515 int, i516 int, i517 int, i518
+int, i519 int, i520 int, i521 int, i522 int, i523 int, i524 int, i525 int, i526
+int, i527 int, i528 int, i529 int, i530 int, i531 int, i532 int, i533 int, i534
+int, i535 int, i536 int, i537 int, i538 int, i539 int, i540 int, i541 int, i542
+int, i543 int, i544 int, i545 int, i546 int, i547 int, i548 int, i549 int, i550
+int, i551 int, i552 int, i553 int, i554 int, i555 int, i556 int, i557 int, i558
+int, i559 int, i560 int, i561 int, i562 int, i563 int, i564 int, i565 int, i566
+int, i567 int, i568 int, i569 int, i570 int, i571 int, i572 int, i573 int, i574
+int, i575 int, i576 int, i577 int, i578 int, i579 int, i580 int, i581 int, i582
+int, i583 int, i584 int, i585 int, i586 int, i587 int, i588 int, i589 int, i590
+int, i591 int, i592 int, i593 int, i594 int, i595 int, i596 int, i597 int, i598
+int, i599 int, i600 int, i601 int, i602 int, i603 int, i604 int, i605 int, i606
+int, i607 int, i608 int, i609 int, i610 int, i611 int, i612 int, i613 int, i614
+int, i615 int, i616 int, i617 int, i618 int, i619 int, i620 int, i621 int, i622
+int, i623 int, i624 int, i625 int, i626 int, i627 int, i628 int, i629 int, i630
+int, i631 int, i632 int, i633 int, i634 int, i635 int, i636 int, i637 int, i638
+int, i639 int, i640 int, i641 int, i642 int, i643 int, i644 int, i645 int, i646
+int, i647 int, i648 int, i649 int, i650 int, i651 int, i652 int, i653 int, i654
+int, i655 int, i656 int, i657 int, i658 int, i659 int, i660 int, i661 int, i662
+int, i663 int, i664 int, i665 int, i666 int, i667 int, i668 int, i669 int, i670
+int, i671 int, i672 int, i673 int, i674 int, i675 int, i676 int, i677 int, i678
+int, i679 int, i680 int, i681 int, i682 int, i683 int, i684 int, i685 int, i686
+int, i687 int, i688 int, i689 int, i690 int, i691 int, i692 int, i693 int, i694
+int, i695 int, i696 int, i697 int, i698 int, i699 int, i700 int, i701 int, i702
+int, i703 int, i704 int, i705 int, i706 int, i707 int, i708 int, i709 int, i710
+int, i711 int, i712 int, i713 int, i714 int, i715 int, i716 int, i717 int, i718
+int, i719 int, i720 int, i721 int, i722 int, i723 int, i724 int, i725 int, i726
+int, i727 int, i728 int, i729 int, i730 int, i731 int, i732 int, i733 int, i734
+int, i735 int, i736 int, i737 int, i738 int, i739 int, i740 int, i741 int, i742
+int, i743 int, i744 int, i745 int, i746 int, i747 int, i748 int, i749 int, i750
+int, i751 int, i752 int, i753 int, i754 int, i755 int, i756 int, i757 int, i758
+int, i759 int, i760 int, i761 int, i762 int, i763 int, i764 int, i765 int, i766
+int, i767 int, i768 int, i769 int, i770 int, i771 int, i772 int, i773 int, i774
+int, i775 int, i776 int, i777 int, i778 int, i779 int, i780 int, i781 int, i782
+int, i783 int, i784 int, i785 int, i786 int, i787 int, i788 int, i789 int, i790
+int, i791 int, i792 int, i793 int, i794 int, i795 int, i796 int, i797 int, i798
+int, i799 int, i800 int, i801 int, i802 int, i803 int, i804 int, i805 int, i806
+int, i807 int, i808 int, i809 int, i810 int, i811 int, i812 int, i813 int, i814
+int, i815 int, i816 int, i817 int, i818 int, i819 int, i820 int, i821 int, i822
+int, i823 int, i824 int, i825 int, i826 int, i827 int, i828 int, i829 int, i830
+int, i831 int, i832 int, i833 int, i834 int, i835 int, i836 int, i837 int, i838
+int, i839 int, i840 int, i841 int, i842 int, i843 int, i844 int, i845 int, i846
+int, i847 int, i848 int, i849 int, i850 int, i851 int, i852 int, i853 int, i854
+int, i855 int, i856 int, i857 int, i858 int, i859 int, i860 int, i861 int, i862
+int, i863 int, i864 int, i865 int, i866 int, i867 int, i868 int, i869 int, i870
+int, i871 int, i872 int, i873 int, i874 int, i875 int, i876 int, i877 int, i878
+int, i879 int, i880 int, i881 int, i882 int, i883 int, i884 int, i885 int, i886
+int, i887 int, i888 int, i889 int, i890 int, i891 int, i892 int, i893 int, i894
+int, i895 int, i896 int, i897 int, i898 int, i899 int, i900 int, i901 int, i902
+int, i903 int, i904 int, i905 int, i906 int, i907 int, i908 int, i909 int, i910
+int, i911 int, i912 int, i913 int, i914 int, i915 int, i916 int, i917 int, i918
+int, i919 int, i920 int, i921 int, i922 int, i923 int, i924 int, i925 int, i926
+int, i927 int, i928 int, i929 int, i930 int, i931 int, i932 int, i933 int, i934
+int, i935 int, i936 int, i937 int, i938 int, i939 int, i940 int, i941 int, i942
+int, i943 int, i944 int, i945 int, i946 int, i947 int, i948 int, i949 int, i950
+int, i951 int, i952 int, i953 int, i954 int, i955 int, i956 int, i957 int, i958
+int, i959 int, i960 int, i961 int, i962 int, i963 int, i964 int, i965 int, i966
+int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974
+int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982
+int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990
+int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998
+int, i999 int, i1000 int, b varchar(256)) row_format=dynamic;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1
+(i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
+int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int,
+i17 int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
+i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34
+int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int,
+i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51
+int, i52 int, i53 int, i54 int, i55 int, i56 int, i57 int, i58 int, i59 int,
+i60 int, i61 int, i62 int, i63 int, i64 int, i65 int, i66 int, i67 int, i68
+int, i69 int, i70 int, i71 int, i72 int, i73 int, i74 int, i75 int, i76 int,
+i77 int, i78 int, i79 int, i80 int, i81 int, i82 int, i83 int, i84 int, i85
+int, i86 int, i87 int, i88 int, i89 int, i90 int, i91 int, i92 int, i93 int,
+i94 int, i95 int, i96 int, i97 int, i98 int, i99 int, i100 int, i101 int, i102
+int, i103 int, i104 int, i105 int, i106 int, i107 int, i108 int, i109 int, i110
+int, i111 int, i112 int, i113 int, i114 int, i115 int, i116 int, i117 int, i118
+int, i119 int, i120 int, i121 int, i122 int, i123 int, i124 int, i125 int, i126
+int, i127 int, i128 int, i129 int, i130 int, i131 int, i132 int, i133 int, i134
+int, i135 int, i136 int, i137 int, i138 int, i139 int, i140 int, i141 int, i142
+int, i143 int, i144 int, i145 int, i146 int, i147 int, i148 int, i149 int, i150
+int, i151 int, i152 int, i153 int, i154 int, i155 int, i156 int, i157 int, i158
+int, i159 int, i160 int, i161 int, i162 int, i163 int, i164 int, i165 int, i166
+int, i167 int, i168 int, i169 int, i170 int, i171 int, i172 int, i173 int, i174
+int, i175 int, i176 int, i177 int, i178 int, i179 int, i180 int, i181 int, i182
+int, i183 int, i184 int, i185 int, i186 int, i187 int, i188 int, i189 int, i190
+int, i191 int, i192 int, i193 int, i194 int, i195 int, i196 int, i197 int, i198
+int, i199 int, i200 int, i201 int, i202 int, i203 int, i204 int, i205 int, i206
+int, i207 int, i208 int, i209 int, i210 int, i211 int, i212 int, i213 int, i214
+int, i215 int, i216 int, i217 int, i218 int, i219 int, i220 int, i221 int, i222
+int, i223 int, i224 int, i225 int, i226 int, i227 int, i228 int, i229 int, i230
+int, i231 int, i232 int, i233 int, i234 int, i235 int, i236 int, i237 int, i238
+int, i239 int, i240 int, i241 int, i242 int, i243 int, i244 int, i245 int, i246
+int, i247 int, i248 int, i249 int, i250 int, i251 int, i252 int, i253 int, i254
+int, i255 int, i256 int, i257 int, i258 int, i259 int, i260 int, i261 int, i262
+int, i263 int, i264 int, i265 int, i266 int, i267 int, i268 int, i269 int, i270
+int, i271 int, i272 int, i273 int, i274 int, i275 int, i276 int, i277 int, i278
+int, i279 int, i280 int, i281 int, i282 int, i283 int, i284 int, i285 int, i286
+int, i287 int, i288 int, i289 int, i290 int, i291 int, i292 int, i293 int, i294
+int, i295 int, i296 int, i297 int, i298 int, i299 int, i300 int, i301 int, i302
+int, i303 int, i304 int, i305 int, i306 int, i307 int, i308 int, i309 int, i310
+int, i311 int, i312 int, i313 int, i314 int, i315 int, i316 int, i317 int, i318
+int, i319 int, i320 int, i321 int, i322 int, i323 int, i324 int, i325 int, i326
+int, i327 int, i328 int, i329 int, i330 int, i331 int, i332 int, i333 int, i334
+int, i335 int, i336 int, i337 int, i338 int, i339 int, i340 int, i341 int, i342
+int, i343 int, i344 int, i345 int, i346 int, i347 int, i348 int, i349 int, i350
+int, i351 int, i352 int, i353 int, i354 int, i355 int, i356 int, i357 int, i358
+int, i359 int, i360 int, i361 int, i362 int, i363 int, i364 int, i365 int, i366
+int, i367 int, i368 int, i369 int, i370 int, i371 int, i372 int, i373 int, i374
+int, i375 int, i376 int, i377 int, i378 int, i379 int, i380 int, i381 int, i382
+int, i383 int, i384 int, i385 int, i386 int, i387 int, i388 int, i389 int, i390
+int, i391 int, i392 int, i393 int, i394 int, i395 int, i396 int, i397 int, i398
+int, i399 int, i400 int, i401 int, i402 int, i403 int, i404 int, i405 int, i406
+int, i407 int, i408 int, i409 int, i410 int, i411 int, i412 int, i413 int, i414
+int, i415 int, i416 int, i417 int, i418 int, i419 int, i420 int, i421 int, i422
+int, i423 int, i424 int, i425 int, i426 int, i427 int, i428 int, i429 int, i430
+int, i431 int, i432 int, i433 int, i434 int, i435 int, i436 int, i437 int, i438
+int, i439 int, i440 int, i441 int, i442 int, i443 int, i444 int, i445 int, i446
+int, i447 int, i448 int, i449 int, i450 int, i451 int, i452 int, i453 int, i454
+int, i455 int, i456 int, i457 int, i458 int, i459 int, i460 int, i461 int, i462
+int, i463 int, i464 int, i465 int, i466 int, i467 int, i468 int, i469 int, i470
+int, i471 int, i472 int, i473 int, i474 int, i475 int, i476 int, i477 int, i478
+int, i479 int, i480 int, i481 int, i482 int, i483 int, i484 int, i485 int, i486
+int, i487 int, i488 int, i489 int, i490 int, i491 int, i492 int, i493 int, i494
+int, i495 int, i496 int, i497 int, i498 int, i499 int, i500 int, i501 int, i502
+int, i503 int, i504 int, i505 int, i506 int, i507 int, i508 int, i509 int, i510
+int, i511 int, i512 int, i513 int, i514 int, i515 int, i516 int, i517 int, i518
+int, i519 int, i520 int, i521 int, i522 int, i523 int, i524 int, i525 int, i526
+int, i527 int, i528 int, i529 int, i530 int, i531 int, i532 int, i533 int, i534
+int, i535 int, i536 int, i537 int, i538 int, i539 int, i540 int, i541 int, i542
+int, i543 int, i544 int, i545 int, i546 int, i547 int, i548 int, i549 int, i550
+int, i551 int, i552 int, i553 int, i554 int, i555 int, i556 int, i557 int, i558
+int, i559 int, i560 int, i561 int, i562 int, i563 int, i564 int, i565 int, i566
+int, i567 int, i568 int, i569 int, i570 int, i571 int, i572 int, i573 int, i574
+int, i575 int, i576 int, i577 int, i578 int, i579 int, i580 int, i581 int, i582
+int, i583 int, i584 int, i585 int, i586 int, i587 int, i588 int, i589 int, i590
+int, i591 int, i592 int, i593 int, i594 int, i595 int, i596 int, i597 int, i598
+int, i599 int, i600 int, i601 int, i602 int, i603 int, i604 int, i605 int, i606
+int, i607 int, i608 int, i609 int, i610 int, i611 int, i612 int, i613 int, i614
+int, i615 int, i616 int, i617 int, i618 int, i619 int, i620 int, i621 int, i622
+int, i623 int, i624 int, i625 int, i626 int, i627 int, i628 int, i629 int, i630
+int, i631 int, i632 int, i633 int, i634 int, i635 int, i636 int, i637 int, i638
+int, i639 int, i640 int, i641 int, i642 int, i643 int, i644 int, i645 int, i646
+int, i647 int, i648 int, i649 int, i650 int, i651 int, i652 int, i653 int, i654
+int, i655 int, i656 int, i657 int, i658 int, i659 int, i660 int, i661 int, i662
+int, i663 int, i664 int, i665 int, i666 int, i667 int, i668 int, i669 int, i670
+int, i671 int, i672 int, i673 int, i674 int, i675 int, i676 int, i677 int, i678
+int, i679 int, i680 int, i681 int, i682 int, i683 int, i684 int, i685 int, i686
+int, i687 int, i688 int, i689 int, i690 int, i691 int, i692 int, i693 int, i694
+int, i695 int, i696 int, i697 int, i698 int, i699 int, i700 int, i701 int, i702
+int, i703 int, i704 int, i705 int, i706 int, i707 int, i708 int, i709 int, i710
+int, i711 int, i712 int, i713 int, i714 int, i715 int, i716 int, i717 int, i718
+int, i719 int, i720 int, i721 int, i722 int, i723 int, i724 int, i725 int, i726
+int, i727 int, i728 int, i729 int, i730 int, i731 int, i732 int, i733 int, i734
+int, i735 int, i736 int, i737 int, i738 int, i739 int, i740 int, i741 int, i742
+int, i743 int, i744 int, i745 int, i746 int, i747 int, i748 int, i749 int, i750
+int, i751 int, i752 int, i753 int, i754 int, i755 int, i756 int, i757 int, i758
+int, i759 int, i760 int, i761 int, i762 int, i763 int, i764 int, i765 int, i766
+int, i767 int, i768 int, i769 int, i770 int, i771 int, i772 int, i773 int, i774
+int, i775 int, i776 int, i777 int, i778 int, i779 int, i780 int, i781 int, i782
+int, i783 int, i784 int, i785 int, i786 int, i787 int, i788 int, i789 int, i790
+int, i791 int, i792 int, i793 int, i794 int, i795 int, i796 int, i797 int, i798
+int, i799 int, i800 int, i801 int, i802 int, i803 int, i804 int, i805 int, i806
+int, i807 int, i808 int, i809 int, i810 int, i811 int, i812 int, i813 int, i814
+int, i815 int, i816 int, i817 int, i818 int, i819 int, i820 int, i821 int, i822
+int, i823 int, i824 int, i825 int, i826 int, i827 int, i828 int, i829 int, i830
+int, i831 int, i832 int, i833 int, i834 int, i835 int, i836 int, i837 int, i838
+int, i839 int, i840 int, i841 int, i842 int, i843 int, i844 int, i845 int, i846
+int, i847 int, i848 int, i849 int, i850 int, i851 int, i852 int, i853 int, i854
+int, i855 int, i856 int, i857 int, i858 int, i859 int, i860 int, i861 int, i862
+int, i863 int, i864 int, i865 int, i866 int, i867 int, i868 int, i869 int, i870
+int, i871 int, i872 int, i873 int, i874 int, i875 int, i876 int, i877 int, i878
+int, i879 int, i880 int, i881 int, i882 int, i883 int, i884 int, i885 int, i886
+int, i887 int, i888 int, i889 int, i890 int, i891 int, i892 int, i893 int, i894
+int, i895 int, i896 int, i897 int, i898 int, i899 int, i900 int, i901 int, i902
+int, i903 int, i904 int, i905 int, i906 int, i907 int, i908 int, i909 int, i910
+int, i911 int, i912 int, i913 int, i914 int, i915 int, i916 int, i917 int, i918
+int, i919 int, i920 int, i921 int, i922 int, i923 int, i924 int, i925 int, i926
+int, i927 int, i928 int, i929 int, i930 int, i931 int, i932 int, i933 int, i934
+int, i935 int, i936 int, i937 int, i938 int, i939 int, i940 int, i941 int, i942
+int, i943 int, i944 int, i945 int, i946 int, i947 int, i948 int, i949 int, i950
+int, i951 int, i952 int, i953 int, i954 int, i955 int, i956 int, i957 int, i958
+int, i959 int, i960 int, i961 int, i962 int, i963 int, i964 int, i965 int, i966
+int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974
+int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982
+int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990
+int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998
+int, i999 int, i1000 int, b varchar(256))
+row_format=dynamic
+ENGINE="FEDERATED"
+DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1
+values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "PatrickG");
+UPDATE federated.t1 SET b=repeat('a',256);
+UPDATE federated.t1 SET i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0, i10=0;
+SELECT * FROM federated.t1 WHERE i9=0 and i10=0;
+i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30 i31 i32 i33 i34 i35 i36 i37 i38 i39 i40 i41 i42 i43 i44 i45 i46 i47 i48 i49 i50 i51 i52 i53 i54 i55 i56 i57 i58 i59 i60 i61 i62 i63 i64 i65 i66 i67 i68 i69 i70 i71 i72 i73 i74 i75 i76 i77 i78 i79 i80 i81 i82 i83 i84 i85 i86 i87 i88 i89 i90 i91 i92 i93 i94 i95 i96 i97 i98 i99 i100 i101 i102 i103 i104 i105 i106 i107 i108 i109 i110 i111 i112 i113 i114 i115 i116 i117 i118 i119 i120 i121 i122 i123 i124 i125 i126 i127 i128 i129 i130 i131 i132 i133 i134 i135 i136 i137 i138 i139 i140 i141 i142 i143 i144 i145 i146 i147 i148 i149 i150 i151 i152 i153 i154 i155 i156 i157 i158 i159 i160 i161 i162 i163 i164 i165 i166 i167 i168 i169 i170 i171 i172 i173 i174 i175 i176 i177 i178 i179 i180 i181 i182 i183 i184 i185 i186 i187 i188 i189 i190 i191 i192 i193 i194 i195 i196 i197 i198 i199 i200 i201 i202 i203 i204 i205 i206 i207 i208 i209 i210 i211 i212 i213 i214 i215 i216 i217 i218 i219 i220 i221 i222 i223 i224 i225 i226 i227 i228 i229 i230 i231 i232 i233 i234 i235 i236 i237 i238 i239 i240 i241 i242 i243 i244 i245 i246 i247 i248 i249 i250 i251 i252 i253 i254 i255 i256 i257 i258 i259 i260 i261 i262 i263 i264 i265 i266 i267 i268 i269 i270 i271 i272 i273 i274 i275 i276 i277 i278 i279 i280 i281 i282 i283 i284 i285 i286 i287 i288 i289 i290 i291 i292 i293 i294 i295 i296 i297 i298 i299 i300 i301 i302 i303 i304 i305 i306 i307 i308 i309 i310 i311 i312 i313 i314 i315 i316 i317 i318 i319 i320 i321 i322 i323 i324 i325 i326 i327 i328 i329 i330 i331 i332 i333 i334 i335 i336 i337 i338 i339 i340 i341 i342 i343 i344 i345 i346 i347 i348 i349 i350 i351 i352 i353 i354 i355 i356 i357 i358 i359 i360 i361 i362 i363 i364 i365 i366 i367 i368 i369 i370 i371 i372 i373 i374 i375 i376 i377 i378 i379 i380 i381 i382 i383 i384 i385 i386 i387 i388 i389 i390 i391 i392 i393 i394 i395 i396 i397 i398 i399 i400 i401 i402 i403 i404 i405 i406 i407 i408 i409 i410 i411 i412 i413 i414 i415 i416 i417 i418 i419 i420 i421 i422 i423 i424 i425 i426 i427 i428 i429 i430 i431 i432 i433 i434 i435 i436 i437 i438 i439 i440 i441 i442 i443 i444 i445 i446 i447 i448 i449 i450 i451 i452 i453 i454 i455 i456 i457 i458 i459 i460 i461 i462 i463 i464 i465 i466 i467 i468 i469 i470 i471 i472 i473 i474 i475 i476 i477 i478 i479 i480 i481 i482 i483 i484 i485 i486 i487 i488 i489 i490 i491 i492 i493 i494 i495 i496 i497 i498 i499 i500 i501 i502 i503 i504 i505 i506 i507 i508 i509 i510 i511 i512 i513 i514 i515 i516 i517 i518 i519 i520 i521 i522 i523 i524 i525 i526 i527 i528 i529 i530 i531 i532 i533 i534 i535 i536 i537 i538 i539 i540 i541 i542 i543 i544 i545 i546 i547 i548 i549 i550 i551 i552 i553 i554 i555 i556 i557 i558 i559 i560 i561 i562 i563 i564 i565 i566 i567 i568 i569 i570 i571 i572 i573 i574 i575 i576 i577 i578 i579 i580 i581 i582 i583 i584 i585 i586 i587 i588 i589 i590 i591 i592 i593 i594 i595 i596 i597 i598 i599 i600 i601 i602 i603 i604 i605 i606 i607 i608 i609 i610 i611 i612 i613 i614 i615 i616 i617 i618 i619 i620 i621 i622 i623 i624 i625 i626 i627 i628 i629 i630 i631 i632 i633 i634 i635 i636 i637 i638 i639 i640 i641 i642 i643 i644 i645 i646 i647 i648 i649 i650 i651 i652 i653 i654 i655 i656 i657 i658 i659 i660 i661 i662 i663 i664 i665 i666 i667 i668 i669 i670 i671 i672 i673 i674 i675 i676 i677 i678 i679 i680 i681 i682 i683 i684 i685 i686 i687 i688 i689 i690 i691 i692 i693 i694 i695 i696 i697 i698 i699 i700 i701 i702 i703 i704 i705 i706 i707 i708 i709 i710 i711 i712 i713 i714 i715 i716 i717 i718 i719 i720 i721 i722 i723 i724 i725 i726 i727 i728 i729 i730 i731 i732 i733 i734 i735 i736 i737 i738 i739 i740 i741 i742 i743 i744 i745 i746 i747 i748 i749 i750 i751 i752 i753 i754 i755 i756 i757 i758 i759 i760 i761 i762 i763 i764 i765 i766 i767 i768 i769 i770 i771 i772 i773 i774 i775 i776 i777 i778 i779 i780 i781 i782 i783 i784 i785 i786 i787 i788 i789 i790 i791 i792 i793 i794 i795 i796 i797 i798 i799 i800 i801 i802 i803 i804 i805 i806 i807 i808 i809 i810 i811 i812 i813 i814 i815 i816 i817 i818 i819 i820 i821 i822 i823 i824 i825 i826 i827 i828 i829 i830 i831 i832 i833 i834 i835 i836 i837 i838 i839 i840 i841 i842 i843 i844 i845 i846 i847 i848 i849 i850 i851 i852 i853 i854 i855 i856 i857 i858 i859 i860 i861 i862 i863 i864 i865 i866 i867 i868 i869 i870 i871 i872 i873 i874 i875 i876 i877 i878 i879 i880 i881 i882 i883 i884 i885 i886 i887 i888 i889 i890 i891 i892 i893 i894 i895 i896 i897 i898 i899 i900 i901 i902 i903 i904 i905 i906 i907 i908 i909 i910 i911 i912 i913 i914 i915 i916 i917 i918 i919 i920 i921 i922 i923 i924 i925 i926 i927 i928 i929 i930 i931 i932 i933 i934 i935 i936 i937 i938 i939 i940 i941 i942 i943 i944 i945 i946 i947 i948 i949 i950 i951 i952 i953 i954 i955 i956 i957 i958 i959 i960 i961 i962 i963 i964 i965 i966 i967 i968 i969 i970 i971 i972 i973 i974 i975 i976 i977 i978 i979 i980 i981 i982 i983 i984 i985 i986 i987 i988 i989 i990 i991 i992 i993 i994 i995 i996 i997 i998 i999 i1000 b
+0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+UPDATE federated.t1 SET i50=20;
+SELECT * FROM federated.t1;
+i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30 i31 i32 i33 i34 i35 i36 i37 i38 i39 i40 i41 i42 i43 i44 i45 i46 i47 i48 i49 i50 i51 i52 i53 i54 i55 i56 i57 i58 i59 i60 i61 i62 i63 i64 i65 i66 i67 i68 i69 i70 i71 i72 i73 i74 i75 i76 i77 i78 i79 i80 i81 i82 i83 i84 i85 i86 i87 i88 i89 i90 i91 i92 i93 i94 i95 i96 i97 i98 i99 i100 i101 i102 i103 i104 i105 i106 i107 i108 i109 i110 i111 i112 i113 i114 i115 i116 i117 i118 i119 i120 i121 i122 i123 i124 i125 i126 i127 i128 i129 i130 i131 i132 i133 i134 i135 i136 i137 i138 i139 i140 i141 i142 i143 i144 i145 i146 i147 i148 i149 i150 i151 i152 i153 i154 i155 i156 i157 i158 i159 i160 i161 i162 i163 i164 i165 i166 i167 i168 i169 i170 i171 i172 i173 i174 i175 i176 i177 i178 i179 i180 i181 i182 i183 i184 i185 i186 i187 i188 i189 i190 i191 i192 i193 i194 i195 i196 i197 i198 i199 i200 i201 i202 i203 i204 i205 i206 i207 i208 i209 i210 i211 i212 i213 i214 i215 i216 i217 i218 i219 i220 i221 i222 i223 i224 i225 i226 i227 i228 i229 i230 i231 i232 i233 i234 i235 i236 i237 i238 i239 i240 i241 i242 i243 i244 i245 i246 i247 i248 i249 i250 i251 i252 i253 i254 i255 i256 i257 i258 i259 i260 i261 i262 i263 i264 i265 i266 i267 i268 i269 i270 i271 i272 i273 i274 i275 i276 i277 i278 i279 i280 i281 i282 i283 i284 i285 i286 i287 i288 i289 i290 i291 i292 i293 i294 i295 i296 i297 i298 i299 i300 i301 i302 i303 i304 i305 i306 i307 i308 i309 i310 i311 i312 i313 i314 i315 i316 i317 i318 i319 i320 i321 i322 i323 i324 i325 i326 i327 i328 i329 i330 i331 i332 i333 i334 i335 i336 i337 i338 i339 i340 i341 i342 i343 i344 i345 i346 i347 i348 i349 i350 i351 i352 i353 i354 i355 i356 i357 i358 i359 i360 i361 i362 i363 i364 i365 i366 i367 i368 i369 i370 i371 i372 i373 i374 i375 i376 i377 i378 i379 i380 i381 i382 i383 i384 i385 i386 i387 i388 i389 i390 i391 i392 i393 i394 i395 i396 i397 i398 i399 i400 i401 i402 i403 i404 i405 i406 i407 i408 i409 i410 i411 i412 i413 i414 i415 i416 i417 i418 i419 i420 i421 i422 i423 i424 i425 i426 i427 i428 i429 i430 i431 i432 i433 i434 i435 i436 i437 i438 i439 i440 i441 i442 i443 i444 i445 i446 i447 i448 i449 i450 i451 i452 i453 i454 i455 i456 i457 i458 i459 i460 i461 i462 i463 i464 i465 i466 i467 i468 i469 i470 i471 i472 i473 i474 i475 i476 i477 i478 i479 i480 i481 i482 i483 i484 i485 i486 i487 i488 i489 i490 i491 i492 i493 i494 i495 i496 i497 i498 i499 i500 i501 i502 i503 i504 i505 i506 i507 i508 i509 i510 i511 i512 i513 i514 i515 i516 i517 i518 i519 i520 i521 i522 i523 i524 i525 i526 i527 i528 i529 i530 i531 i532 i533 i534 i535 i536 i537 i538 i539 i540 i541 i542 i543 i544 i545 i546 i547 i548 i549 i550 i551 i552 i553 i554 i555 i556 i557 i558 i559 i560 i561 i562 i563 i564 i565 i566 i567 i568 i569 i570 i571 i572 i573 i574 i575 i576 i577 i578 i579 i580 i581 i582 i583 i584 i585 i586 i587 i588 i589 i590 i591 i592 i593 i594 i595 i596 i597 i598 i599 i600 i601 i602 i603 i604 i605 i606 i607 i608 i609 i610 i611 i612 i613 i614 i615 i616 i617 i618 i619 i620 i621 i622 i623 i624 i625 i626 i627 i628 i629 i630 i631 i632 i633 i634 i635 i636 i637 i638 i639 i640 i641 i642 i643 i644 i645 i646 i647 i648 i649 i650 i651 i652 i653 i654 i655 i656 i657 i658 i659 i660 i661 i662 i663 i664 i665 i666 i667 i668 i669 i670 i671 i672 i673 i674 i675 i676 i677 i678 i679 i680 i681 i682 i683 i684 i685 i686 i687 i688 i689 i690 i691 i692 i693 i694 i695 i696 i697 i698 i699 i700 i701 i702 i703 i704 i705 i706 i707 i708 i709 i710 i711 i712 i713 i714 i715 i716 i717 i718 i719 i720 i721 i722 i723 i724 i725 i726 i727 i728 i729 i730 i731 i732 i733 i734 i735 i736 i737 i738 i739 i740 i741 i742 i743 i744 i745 i746 i747 i748 i749 i750 i751 i752 i753 i754 i755 i756 i757 i758 i759 i760 i761 i762 i763 i764 i765 i766 i767 i768 i769 i770 i771 i772 i773 i774 i775 i776 i777 i778 i779 i780 i781 i782 i783 i784 i785 i786 i787 i788 i789 i790 i791 i792 i793 i794 i795 i796 i797 i798 i799 i800 i801 i802 i803 i804 i805 i806 i807 i808 i809 i810 i811 i812 i813 i814 i815 i816 i817 i818 i819 i820 i821 i822 i823 i824 i825 i826 i827 i828 i829 i830 i831 i832 i833 i834 i835 i836 i837 i838 i839 i840 i841 i842 i843 i844 i845 i846 i847 i848 i849 i850 i851 i852 i853 i854 i855 i856 i857 i858 i859 i860 i861 i862 i863 i864 i865 i866 i867 i868 i869 i870 i871 i872 i873 i874 i875 i876 i877 i878 i879 i880 i881 i882 i883 i884 i885 i886 i887 i888 i889 i890 i891 i892 i893 i894 i895 i896 i897 i898 i899 i900 i901 i902 i903 i904 i905 i906 i907 i908 i909 i910 i911 i912 i913 i914 i915 i916 i917 i918 i919 i920 i921 i922 i923 i924 i925 i926 i927 i928 i929 i930 i931 i932 i933 i934 i935 i936 i937 i938 i939 i940 i941 i942 i943 i944 i945 i946 i947 i948 i949 i950 i951 i952 i953 i954 i955 i956 i957 i958 i959 i960 i961 i962 i963 i964 i965 i966 i967 i968 i969 i970 i971 i972 i973 i974 i975 i976 i977 i978 i979 i980 i981 i982 i983 i984 i985 i986 i987 i988 i989 i990 i991 i992 i993 i994 i995 i996 i997 i998 i999 i1000 b
+0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 20 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+DELETE FROM federated.t1 WHERE i51=20;
+SELECT * FROM federated.t1;
+i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30 i31 i32 i33 i34 i35 i36 i37 i38 i39 i40 i41 i42 i43 i44 i45 i46 i47 i48 i49 i50 i51 i52 i53 i54 i55 i56 i57 i58 i59 i60 i61 i62 i63 i64 i65 i66 i67 i68 i69 i70 i71 i72 i73 i74 i75 i76 i77 i78 i79 i80 i81 i82 i83 i84 i85 i86 i87 i88 i89 i90 i91 i92 i93 i94 i95 i96 i97 i98 i99 i100 i101 i102 i103 i104 i105 i106 i107 i108 i109 i110 i111 i112 i113 i114 i115 i116 i117 i118 i119 i120 i121 i122 i123 i124 i125 i126 i127 i128 i129 i130 i131 i132 i133 i134 i135 i136 i137 i138 i139 i140 i141 i142 i143 i144 i145 i146 i147 i148 i149 i150 i151 i152 i153 i154 i155 i156 i157 i158 i159 i160 i161 i162 i163 i164 i165 i166 i167 i168 i169 i170 i171 i172 i173 i174 i175 i176 i177 i178 i179 i180 i181 i182 i183 i184 i185 i186 i187 i188 i189 i190 i191 i192 i193 i194 i195 i196 i197 i198 i199 i200 i201 i202 i203 i204 i205 i206 i207 i208 i209 i210 i211 i212 i213 i214 i215 i216 i217 i218 i219 i220 i221 i222 i223 i224 i225 i226 i227 i228 i229 i230 i231 i232 i233 i234 i235 i236 i237 i238 i239 i240 i241 i242 i243 i244 i245 i246 i247 i248 i249 i250 i251 i252 i253 i254 i255 i256 i257 i258 i259 i260 i261 i262 i263 i264 i265 i266 i267 i268 i269 i270 i271 i272 i273 i274 i275 i276 i277 i278 i279 i280 i281 i282 i283 i284 i285 i286 i287 i288 i289 i290 i291 i292 i293 i294 i295 i296 i297 i298 i299 i300 i301 i302 i303 i304 i305 i306 i307 i308 i309 i310 i311 i312 i313 i314 i315 i316 i317 i318 i319 i320 i321 i322 i323 i324 i325 i326 i327 i328 i329 i330 i331 i332 i333 i334 i335 i336 i337 i338 i339 i340 i341 i342 i343 i344 i345 i346 i347 i348 i349 i350 i351 i352 i353 i354 i355 i356 i357 i358 i359 i360 i361 i362 i363 i364 i365 i366 i367 i368 i369 i370 i371 i372 i373 i374 i375 i376 i377 i378 i379 i380 i381 i382 i383 i384 i385 i386 i387 i388 i389 i390 i391 i392 i393 i394 i395 i396 i397 i398 i399 i400 i401 i402 i403 i404 i405 i406 i407 i408 i409 i410 i411 i412 i413 i414 i415 i416 i417 i418 i419 i420 i421 i422 i423 i424 i425 i426 i427 i428 i429 i430 i431 i432 i433 i434 i435 i436 i437 i438 i439 i440 i441 i442 i443 i444 i445 i446 i447 i448 i449 i450 i451 i452 i453 i454 i455 i456 i457 i458 i459 i460 i461 i462 i463 i464 i465 i466 i467 i468 i469 i470 i471 i472 i473 i474 i475 i476 i477 i478 i479 i480 i481 i482 i483 i484 i485 i486 i487 i488 i489 i490 i491 i492 i493 i494 i495 i496 i497 i498 i499 i500 i501 i502 i503 i504 i505 i506 i507 i508 i509 i510 i511 i512 i513 i514 i515 i516 i517 i518 i519 i520 i521 i522 i523 i524 i525 i526 i527 i528 i529 i530 i531 i532 i533 i534 i535 i536 i537 i538 i539 i540 i541 i542 i543 i544 i545 i546 i547 i548 i549 i550 i551 i552 i553 i554 i555 i556 i557 i558 i559 i560 i561 i562 i563 i564 i565 i566 i567 i568 i569 i570 i571 i572 i573 i574 i575 i576 i577 i578 i579 i580 i581 i582 i583 i584 i585 i586 i587 i588 i589 i590 i591 i592 i593 i594 i595 i596 i597 i598 i599 i600 i601 i602 i603 i604 i605 i606 i607 i608 i609 i610 i611 i612 i613 i614 i615 i616 i617 i618 i619 i620 i621 i622 i623 i624 i625 i626 i627 i628 i629 i630 i631 i632 i633 i634 i635 i636 i637 i638 i639 i640 i641 i642 i643 i644 i645 i646 i647 i648 i649 i650 i651 i652 i653 i654 i655 i656 i657 i658 i659 i660 i661 i662 i663 i664 i665 i666 i667 i668 i669 i670 i671 i672 i673 i674 i675 i676 i677 i678 i679 i680 i681 i682 i683 i684 i685 i686 i687 i688 i689 i690 i691 i692 i693 i694 i695 i696 i697 i698 i699 i700 i701 i702 i703 i704 i705 i706 i707 i708 i709 i710 i711 i712 i713 i714 i715 i716 i717 i718 i719 i720 i721 i722 i723 i724 i725 i726 i727 i728 i729 i730 i731 i732 i733 i734 i735 i736 i737 i738 i739 i740 i741 i742 i743 i744 i745 i746 i747 i748 i749 i750 i751 i752 i753 i754 i755 i756 i757 i758 i759 i760 i761 i762 i763 i764 i765 i766 i767 i768 i769 i770 i771 i772 i773 i774 i775 i776 i777 i778 i779 i780 i781 i782 i783 i784 i785 i786 i787 i788 i789 i790 i791 i792 i793 i794 i795 i796 i797 i798 i799 i800 i801 i802 i803 i804 i805 i806 i807 i808 i809 i810 i811 i812 i813 i814 i815 i816 i817 i818 i819 i820 i821 i822 i823 i824 i825 i826 i827 i828 i829 i830 i831 i832 i833 i834 i835 i836 i837 i838 i839 i840 i841 i842 i843 i844 i845 i846 i847 i848 i849 i850 i851 i852 i853 i854 i855 i856 i857 i858 i859 i860 i861 i862 i863 i864 i865 i866 i867 i868 i869 i870 i871 i872 i873 i874 i875 i876 i877 i878 i879 i880 i881 i882 i883 i884 i885 i886 i887 i888 i889 i890 i891 i892 i893 i894 i895 i896 i897 i898 i899 i900 i901 i902 i903 i904 i905 i906 i907 i908 i909 i910 i911 i912 i913 i914 i915 i916 i917 i918 i919 i920 i921 i922 i923 i924 i925 i926 i927 i928 i929 i930 i931 i932 i933 i934 i935 i936 i937 i938 i939 i940 i941 i942 i943 i944 i945 i946 i947 i948 i949 i950 i951 i952 i953 i954 i955 i956 i957 i958 i959 i960 i961 i962 i963 i964 i965 i966 i967 i968 i969 i970 i971 i972 i973 i974 i975 i976 i977 i978 i979 i980 i981 i982 i983 i984 i985 i986 i987 i988 i989 i990 i991 i992 i993 i994 i995 i996 i997 i998 i999 i1000 b
+0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 20 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+DELETE FROM federated.t1 WHERE i50=20;
+SELECT * FROM federated.t1;
+i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30 i31 i32 i33 i34 i35 i36 i37 i38 i39 i40 i41 i42 i43 i44 i45 i46 i47 i48 i49 i50 i51 i52 i53 i54 i55 i56 i57 i58 i59 i60 i61 i62 i63 i64 i65 i66 i67 i68 i69 i70 i71 i72 i73 i74 i75 i76 i77 i78 i79 i80 i81 i82 i83 i84 i85 i86 i87 i88 i89 i90 i91 i92 i93 i94 i95 i96 i97 i98 i99 i100 i101 i102 i103 i104 i105 i106 i107 i108 i109 i110 i111 i112 i113 i114 i115 i116 i117 i118 i119 i120 i121 i122 i123 i124 i125 i126 i127 i128 i129 i130 i131 i132 i133 i134 i135 i136 i137 i138 i139 i140 i141 i142 i143 i144 i145 i146 i147 i148 i149 i150 i151 i152 i153 i154 i155 i156 i157 i158 i159 i160 i161 i162 i163 i164 i165 i166 i167 i168 i169 i170 i171 i172 i173 i174 i175 i176 i177 i178 i179 i180 i181 i182 i183 i184 i185 i186 i187 i188 i189 i190 i191 i192 i193 i194 i195 i196 i197 i198 i199 i200 i201 i202 i203 i204 i205 i206 i207 i208 i209 i210 i211 i212 i213 i214 i215 i216 i217 i218 i219 i220 i221 i222 i223 i224 i225 i226 i227 i228 i229 i230 i231 i232 i233 i234 i235 i236 i237 i238 i239 i240 i241 i242 i243 i244 i245 i246 i247 i248 i249 i250 i251 i252 i253 i254 i255 i256 i257 i258 i259 i260 i261 i262 i263 i264 i265 i266 i267 i268 i269 i270 i271 i272 i273 i274 i275 i276 i277 i278 i279 i280 i281 i282 i283 i284 i285 i286 i287 i288 i289 i290 i291 i292 i293 i294 i295 i296 i297 i298 i299 i300 i301 i302 i303 i304 i305 i306 i307 i308 i309 i310 i311 i312 i313 i314 i315 i316 i317 i318 i319 i320 i321 i322 i323 i324 i325 i326 i327 i328 i329 i330 i331 i332 i333 i334 i335 i336 i337 i338 i339 i340 i341 i342 i343 i344 i345 i346 i347 i348 i349 i350 i351 i352 i353 i354 i355 i356 i357 i358 i359 i360 i361 i362 i363 i364 i365 i366 i367 i368 i369 i370 i371 i372 i373 i374 i375 i376 i377 i378 i379 i380 i381 i382 i383 i384 i385 i386 i387 i388 i389 i390 i391 i392 i393 i394 i395 i396 i397 i398 i399 i400 i401 i402 i403 i404 i405 i406 i407 i408 i409 i410 i411 i412 i413 i414 i415 i416 i417 i418 i419 i420 i421 i422 i423 i424 i425 i426 i427 i428 i429 i430 i431 i432 i433 i434 i435 i436 i437 i438 i439 i440 i441 i442 i443 i444 i445 i446 i447 i448 i449 i450 i451 i452 i453 i454 i455 i456 i457 i458 i459 i460 i461 i462 i463 i464 i465 i466 i467 i468 i469 i470 i471 i472 i473 i474 i475 i476 i477 i478 i479 i480 i481 i482 i483 i484 i485 i486 i487 i488 i489 i490 i491 i492 i493 i494 i495 i496 i497 i498 i499 i500 i501 i502 i503 i504 i505 i506 i507 i508 i509 i510 i511 i512 i513 i514 i515 i516 i517 i518 i519 i520 i521 i522 i523 i524 i525 i526 i527 i528 i529 i530 i531 i532 i533 i534 i535 i536 i537 i538 i539 i540 i541 i542 i543 i544 i545 i546 i547 i548 i549 i550 i551 i552 i553 i554 i555 i556 i557 i558 i559 i560 i561 i562 i563 i564 i565 i566 i567 i568 i569 i570 i571 i572 i573 i574 i575 i576 i577 i578 i579 i580 i581 i582 i583 i584 i585 i586 i587 i588 i589 i590 i591 i592 i593 i594 i595 i596 i597 i598 i599 i600 i601 i602 i603 i604 i605 i606 i607 i608 i609 i610 i611 i612 i613 i614 i615 i616 i617 i618 i619 i620 i621 i622 i623 i624 i625 i626 i627 i628 i629 i630 i631 i632 i633 i634 i635 i636 i637 i638 i639 i640 i641 i642 i643 i644 i645 i646 i647 i648 i649 i650 i651 i652 i653 i654 i655 i656 i657 i658 i659 i660 i661 i662 i663 i664 i665 i666 i667 i668 i669 i670 i671 i672 i673 i674 i675 i676 i677 i678 i679 i680 i681 i682 i683 i684 i685 i686 i687 i688 i689 i690 i691 i692 i693 i694 i695 i696 i697 i698 i699 i700 i701 i702 i703 i704 i705 i706 i707 i708 i709 i710 i711 i712 i713 i714 i715 i716 i717 i718 i719 i720 i721 i722 i723 i724 i725 i726 i727 i728 i729 i730 i731 i732 i733 i734 i735 i736 i737 i738 i739 i740 i741 i742 i743 i744 i745 i746 i747 i748 i749 i750 i751 i752 i753 i754 i755 i756 i757 i758 i759 i760 i761 i762 i763 i764 i765 i766 i767 i768 i769 i770 i771 i772 i773 i774 i775 i776 i777 i778 i779 i780 i781 i782 i783 i784 i785 i786 i787 i788 i789 i790 i791 i792 i793 i794 i795 i796 i797 i798 i799 i800 i801 i802 i803 i804 i805 i806 i807 i808 i809 i810 i811 i812 i813 i814 i815 i816 i817 i818 i819 i820 i821 i822 i823 i824 i825 i826 i827 i828 i829 i830 i831 i832 i833 i834 i835 i836 i837 i838 i839 i840 i841 i842 i843 i844 i845 i846 i847 i848 i849 i850 i851 i852 i853 i854 i855 i856 i857 i858 i859 i860 i861 i862 i863 i864 i865 i866 i867 i868 i869 i870 i871 i872 i873 i874 i875 i876 i877 i878 i879 i880 i881 i882 i883 i884 i885 i886 i887 i888 i889 i890 i891 i892 i893 i894 i895 i896 i897 i898 i899 i900 i901 i902 i903 i904 i905 i906 i907 i908 i909 i910 i911 i912 i913 i914 i915 i916 i917 i918 i919 i920 i921 i922 i923 i924 i925 i926 i927 i928 i929 i930 i931 i932 i933 i934 i935 i936 i937 i938 i939 i940 i941 i942 i943 i944 i945 i946 i947 i948 i949 i950 i951 i952 i953 i954 i955 i956 i957 i958 i959 i960 i961 i962 i963 i964 i965 i966 i967 i968 i969 i970 i971 i972 i973 i974 i975 i976 i977 i978 i979 i980 i981 i982 i983 i984 i985 i986 i987 i988 i989 i990 i991 i992 i993 i994 i995 i996 i997 i998 i999 i1000 b
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (id int NOT NULL auto_increment, code char(20) NOT NULL, fileguts blob NOT NULL, creation_date datetime, entered_time datetime default '2004-04-04 04:04:04', PRIMARY KEY(id), index(code), index(fileguts(10))) DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+id int NOT NULL auto_increment,
+code char(20) NOT NULL,
+fileguts blob NOT NULL,
+creation_date datetime,
+entered_time datetime default '2004-04-04 04:04:04',
+PRIMARY KEY(id),
+index(code),
+index(fileguts(10)))
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('ASDFWERQWETWETAWETA', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#<S-F8>*<S-F8><S-F8><S-F8>#<S-F8>#<S-F8>#<S-F8>[[', '2003-03-03 03:03:03');
+INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#<S-F8>*<S-F8><S-F8><S-F8>#<S-F8>#<S-F8>#<S-F8>[[', '2004-04-04 04:04:04');
+INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', 'jimbob', '2004-04-04 04:04:04');
+SELECT * FROM federated.t1;
+id code fileguts creation_date entered_time
+1 ASDFWERQWETWETAWETA *()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#<S-F8>*<S-F8><S-F8><S-F8>#<S-F8>#<S-F8>#<S-F8>[[ 2003-03-03 03:03:03 2004-04-04 04:04:04
+2 DEUEUEUEUEUEUEUEUEU *()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#<S-F8>*<S-F8><S-F8><S-F8>#<S-F8>#<S-F8>#<S-F8>[[ 2004-04-04 04:04:04 2004-04-04 04:04:04
+3 DEUEUEUEUEUEUEUEUEU jimbob 2004-04-04 04:04:04 2004-04-04 04:04:04
+SELECT * FROM federated.t1 WHERE fileguts = 'jimbob';
+id code fileguts creation_date entered_time
+3 DEUEUEUEUEUEUEUEUEU jimbob 2004-04-04 04:04:04 2004-04-04 04:04:04
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (`a` BLOB);
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`a` BLOB)
+ENGINE="FEDERATED"
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 VALUES (0x00);
+INSERT INTO federated.t1 VALUES (0x0001);
+INSERT INTO federated.t1 VALUES (0x0100);
+SELECT HEX(a) FROM federated.t1;
+HEX(a)
+00
+0001
+0100
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`country_id` int(20) NOT NULL DEFAULT 0,
+`name` varchar(32),
+`other` varchar(20),
+PRIMARY KEY (`id`),
+key (country_id));
+DROP TABLE IF EXISTS federated.countries;
+Warnings:
+Note 1051 Unknown table 'countries'
+CREATE TABLE federated.countries (
+`id` int(20) NOT NULL auto_increment,
+`country` varchar(32),
+PRIMARY KEY (id));
+INSERT INTO federated.countries (country) VALUES ('India');
+INSERT INTO federated.countries (country) VALUES ('Germany');
+INSERT INTO federated.countries (country) VALUES ('Italy');
+INSERT INTO federated.countries (country) VALUES ('Finland');
+INSERT INTO federated.countries (country) VALUES ('Ukraine');
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(20) NOT NULL auto_increment,
+`country_id` int(20) NOT NULL DEFAULT 0,
+`name` varchar(32),
+`other` varchar(20),
+PRIMARY KEY (`id`),
+KEY (country_id) )
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Kumar', 1, 11111);
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Lenz', 2, 22222);
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Marizio', 3, 33333);
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Monty', 4, 33333);
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Sanja', 5, 33333);
+SELECT federated.t1.name AS name, federated.t1.country_id AS country_id,
+federated.t1.other AS other, federated.countries.country AS country
+FROM federated.t1, federated.countries WHERE
+federated.t1.country_id = federated.countries.id;
+name country_id other country
+Kumar 1 11111 India
+Lenz 2 22222 Germany
+Marizio 3 33333 Italy
+Monty 4 33333 Finland
+Sanja 5 33333 Ukraine
+SELECT federated.t1.name AS name, federated.t1.country_id AS country_id,
+federated.t1.other AS other, federated.countries.country AS country
+FROM federated.t1 INNER JOIN federated.countries ON
+federated.t1.country_id = federated.countries.id;
+name country_id other country
+Kumar 1 11111 India
+Lenz 2 22222 Germany
+Marizio 3 33333 Italy
+Monty 4 33333 Finland
+Sanja 5 33333 Ukraine
+SELECT federated.t1.name AS name, federated.t1.country_id AS country_id,
+federated.t1.other AS other, federated.countries.country AS country
+FROM federated.t1 INNER JOIN federated.countries ON
+federated.t1.country_id = federated.countries.id
+WHERE federated.t1.name = 'Monty';
+name country_id other country
+Monty 4 33333 Finland
+SELECT federated.t1.*, federated.countries.country
+FROM federated.t1 LEFT JOIN federated.countries
+ON federated.t1.country_id = federated.countries.id
+ORDER BY federated.countries.id;
+id country_id name other country
+1 1 Kumar 11111 India
+2 2 Lenz 22222 Germany
+3 3 Marizio 33333 Italy
+4 4 Monty 33333 Finland
+5 5 Sanja 33333 Ukraine
+SELECT federated.t1.*, federated.countries.country
+FROM federated.t1 LEFT JOIN federated.countries
+ON federated.t1.country_id = federated.countries.id
+ORDER BY federated.countries.country;
+id country_id name other country
+4 4 Monty 33333 Finland
+2 2 Lenz 22222 Germany
+1 1 Kumar 11111 India
+3 3 Marizio 33333 Italy
+5 5 Sanja 33333 Ukraine
+SELECT federated.t1.*, federated.countries.country
+FROM federated.t1 RIGHT JOIN federated.countries
+ON federated.t1.country_id = federated.countries.id
+ORDER BY federated.t1.country_id;
+id country_id name other country
+1 1 Kumar 11111 India
+2 2 Lenz 22222 Germany
+3 3 Marizio 33333 Italy
+4 4 Monty 33333 Finland
+5 5 Sanja 33333 Ukraine
+DROP TABLE federated.countries;
+OPTIMIZE TABLE federated.t1;
+Table Op Msg_type Msg_text
+federated.t1 optimize status OK
+REPAIR TABLE federated.t1;
+Table Op Msg_type Msg_text
+federated.t1 repair status OK
+REPAIR TABLE federated.t1 QUICK;
+Table Op Msg_type Msg_text
+federated.t1 repair status OK
+REPAIR TABLE federated.t1 EXTENDED;
+Table Op Msg_type Msg_text
+federated.t1 repair status OK
+REPAIR TABLE federated.t1 USE_FRM;
+Table Op Msg_type Msg_text
+federated.t1 repair status OK
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
diff --git a/mysql-test/r/federated_archive.result b/mysql-test/r/federated_archive.result
new file mode 100644
index 00000000000..3fd7cb2acd4
--- /dev/null
+++ b/mysql-test/r/federated_archive.result
@@ -0,0 +1,48 @@
+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;
+stop slave;
+DROP DATABASE IF EXISTS federated;
+CREATE DATABASE federated;
+DROP DATABASE IF EXISTS federated;
+CREATE DATABASE federated;
+DROP TABLE IF EXISTS federated.archive_table;
+CREATE TABLE federated.archive_table (
+`id` int(4) NOT NULL,
+`name` varchar(54) default NULL
+) ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`id` int(4) NOT NULL,
+`name` varchar(54) default NULL,
+PRIMARY KEY (`id`)
+)
+ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/archive_table';
+INSERT INTO federated.t1 (id, name) VALUES (1, 'foo');
+INSERT INTO federated.t1 (id, name) VALUES (2, 'bar');
+SELECT * FROM federated.t1;
+id name
+1 foo
+2 bar
+DELETE FROM federated.t1 WHERE id = 1;
+ERROR HY000: Got error 10000 'Error on remote system: 1031: Table storage engine for 'archive_table' doesn't have this option' from FEDERATED
+SELECT * FROM federated.t1;
+id name
+1 foo
+2 bar
+UPDATE federated.t1 SET name='baz' WHERE id = 1;
+ERROR HY000: Got error 10000 'Error on remote system: 1031: Table storage engine for 'archive_table' doesn't have this option' from FEDERATED
+SELECT * FROM federated.t1;
+id name
+1 foo
+2 bar
+DROP TABLE federated.t1;
+DROP TABLE federated.archive_table;
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
diff --git a/mysql-test/r/federated_bug_13118.result b/mysql-test/r/federated_bug_13118.result
new file mode 100644
index 00000000000..cc14dae87d9
--- /dev/null
+++ b/mysql-test/r/federated_bug_13118.result
@@ -0,0 +1,39 @@
+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;
+stop slave;
+DROP DATABASE IF EXISTS federated;
+CREATE DATABASE federated;
+DROP DATABASE IF EXISTS federated;
+CREATE DATABASE federated;
+DROP TABLE IF EXISTS federated.bug_13118_table;
+CREATE TABLE federated.bug_13118_table (
+`foo` integer,
+`bar` integer
+);
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+`foo` integer,
+`bar` integer
+) ENGINE="FEDERATED"
+ CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/bug_13118_table';
+SELECT * from federated.t1;
+foo bar
+INSERT INTO federated.t1 VALUES (1,1);
+SELECT * FROM federated.t1;
+foo bar
+1 1
+INSERT INTO federated.t1 VALUES (1,1);
+SELECT * FROM federated.t1;
+foo bar
+1 1
+1 1
+DROP TABLE federated.t1;
+DROP TABLE federated.bug_13118_table;
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
+DROP TABLE IF EXISTS federated.t1;
+DROP DATABASE IF EXISTS federated;
diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result
index 384bdc1214b..16c308e3450 100644
--- a/mysql-test/r/flush.result
+++ b/mysql-test/r/flush.result
@@ -8,7 +8,7 @@ n
3
flush tables with read lock;
drop table t2;
-ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
+ERROR HY000: Can't execute the query because you have a conflicting read lock
drop table t2;
unlock tables;
create database mysqltest;
diff --git a/mysql-test/r/flush_block_commit.result b/mysql-test/r/flush_block_commit.result
index 2e9f1920937..2f6aca7e24a 100644
--- a/mysql-test/r/flush_block_commit.result
+++ b/mysql-test/r/flush_block_commit.result
@@ -37,3 +37,18 @@ show create database test;
Database Create Database
test CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */
drop table t1;
+create table t1 (a int) engine=innodb;
+reset master;
+set autocommit=0;
+insert t1 values (1);
+flush tables with read lock;
+show master status;
+File Position Binlog_Do_DB Binlog_Ignore_DB
+master-bin.000001 98
+ commit;
+show master status;
+File Position Binlog_Do_DB Binlog_Ignore_DB
+master-bin.000001 98
+unlock tables;
+drop table t1;
+set autocommit=1;
diff --git a/mysql-test/r/flush_read_lock_kill.result b/mysql-test/r/flush_read_lock_kill.result
new file mode 100644
index 00000000000..dfdcf51457a
--- /dev/null
+++ b/mysql-test/r/flush_read_lock_kill.result
@@ -0,0 +1,9 @@
+drop table if exists t1;
+create table t1 (kill_id int);
+insert into t1 values(connection_id());
+ flush tables with read lock;
+select ((@id := kill_id) - kill_id) from t1;
+((@id := kill_id) - kill_id)
+0
+kill connection @id;
+drop table t1;
diff --git a/mysql-test/r/flush_table.result b/mysql-test/r/flush_table.result
index 2ef4ab5b52b..db54d2e53ef 100644
--- a/mysql-test/r/flush_table.result
+++ b/mysql-test/r/flush_table.result
@@ -101,3 +101,6 @@ table_id
Record-02
handler t1 close;
drop table t1;
+FLUSH TABLES WITH READ LOCK ;
+FLUSH TABLES WITH READ LOCK ;
+UNLOCK TABLES;
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 8fa2df2e756..ea0ffe9d7dd 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -17,7 +17,7 @@ explain extended select * from t1 where MATCH(a,b) AGAINST ("collections");
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 fulltext a a 0 1 Using where
Warnings:
-Note 1003 select test.t1.a AS `a`,test.t1.b AS `b` from test.t1 where (match test.t1.a,test.t1.b against (_latin1'collections'))
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (match `test`.`t1`.`a`,`test`.`t1`.`b` against (_latin1'collections'))
select * from t1 where MATCH(a,b) AGAINST ("indexes");
a b
Full-text indexes are called collections
@@ -78,7 +78,7 @@ explain extended select * from t1 where MATCH(a,b) AGAINST("support -collections
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 fulltext a a 0 1 Using where
Warnings:
-Note 1003 select test.t1.a AS `a`,test.t1.b AS `b` from test.t1 where (match test.t1.a,test.t1.b against (_latin1'support -collections' in boolean mode))
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (match `test`.`t1`.`a`,`test`.`t1`.`b` against (_latin1'support -collections' in boolean mode))
select * from t1 where MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE);
a b
MySQL has now support for full-text search
@@ -130,6 +130,9 @@ a b
select * from t1 where MATCH a,b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE);
a b
MySQL has now support for full-text search
+select * from t1 where MATCH a,b AGAINST ('"now support"' IN BOOLEAN MODE);
+a b
+MySQL has now support for full-text search
select * from t1 where MATCH a,b AGAINST ('"text search" "now support"' IN BOOLEAN MODE);
a b
MySQL has now support for full-text search
@@ -151,8 +154,6 @@ a b
select * from t1 where MATCH a,b AGAINST ('+collections -supp* -foobar*' IN BOOLEAN MODE);
a b
Full-text indexes are called collections
-select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE);
-a b
select * from t1 where MATCH a,b AGAINST('"space model' IN BOOLEAN MODE);
a b
Full-text search in MySQL implements vector space model
@@ -220,14 +221,14 @@ select t1.id FROM t2 as ttxt,t1,t1 as ticket2
WHERE ticket2.id = ttxt.ticket AND t1.id = ticket2.ticket and
match(ttxt.inhalt) against ('foobar');
id
-select t1.id FROM t2 as ttxt,t1 INNER JOIN t1 as ticket2 ON
-ticket2.id = ttxt.ticket
-WHERE t1.id = ticket2.ticket and match(ttxt.inhalt) against ('foobar');
+select ticket2.id FROM t2 as ttxt,t2 INNER JOIN t1 as ticket2 ON
+ticket2.id = t2.ticket
+WHERE ticket2.id = ticket2.ticket and match(ttxt.inhalt) against ('foobar');
id
INSERT INTO t1 VALUES (3,3);
-select t1.id FROM t2 as ttxt,t1
-INNER JOIN t1 as ticket2 ON ticket2.id = ttxt.ticket
-WHERE t1.id = ticket2.ticket and
+select ticket2.id FROM t2 as ttxt,t2
+INNER JOIN t1 as ticket2 ON ticket2.id = t2.ticket
+WHERE ticket2.id = ticket2.ticket and
match(ttxt.inhalt) against ('foobar');
id
3
@@ -336,8 +337,8 @@ insert into t2 values (1, 1, 'xxfoo');
insert into t2 values (2, 1, 'xxbar');
insert into t2 values (3, 1, 'xxbuz');
select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode);
-t1_id name t2_id t1_id name
-1 data1 1 1 xxfoo
+t1_id name t2_id name
+1 data1 1 xxfoo
select * from t2 where match name against ('*a*b*c*d*e*f*' in boolean mode);
t2_id t1_id name
drop table t1,t2;
diff --git a/mysql-test/r/fulltext_order_by.result b/mysql-test/r/fulltext_order_by.result
index 0b77153248e..bc466b5aba7 100644
--- a/mysql-test/r/fulltext_order_by.result
+++ b/mysql-test/r/fulltext_order_by.result
@@ -1,4 +1,4 @@
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1,t2,t3;
CREATE TABLE t1 (
a INT AUTO_INCREMENT PRIMARY KEY,
message CHAR(20),
@@ -126,7 +126,7 @@ group by
a.text, b.id, b.betreff
order by
match(b.betreff) against ('+abc' in boolean mode) desc;
-ERROR 42S02: Unknown table 'b' in order clause
+ERROR 42S22: Unknown column 'b.betreff' in 'order clause'
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
@@ -142,7 +142,7 @@ where
match(c.beitrag) against ('+abc' in boolean mode)
order by
match(b.betreff) against ('+abc' in boolean mode) desc;
-ERROR 42S02: Unknown table 'b' in order clause
+ERROR 42S22: Unknown column 'b.betreff' in 'order clause'
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
diff --git a/mysql-test/r/func_concat.result b/mysql-test/r/func_concat.result
index cf6fbf2da4f..0bd53b32dd7 100644
--- a/mysql-test/r/func_concat.result
+++ b/mysql-test/r/func_concat.result
@@ -63,4 +63,8 @@ a0
select 'a' union select concat('a', -0.0);
a
a
-good
+a0.0
+select 'a' union select concat('a', -0.0000);
+a
+a
+a0.0000
diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result
index f4091ff4c0e..841d13a6ea6 100644
--- a/mysql-test/r/func_date_add.result
+++ b/mysql-test/r/func_date_add.result
@@ -4,7 +4,7 @@ visitor_id int(10) unsigned DEFAULT '0' NOT NULL,
group_id int(10) unsigned DEFAULT '0' NOT NULL,
hits int(10) unsigned DEFAULT '0' NOT NULL,
sessions int(10) unsigned DEFAULT '0' NOT NULL,
-ts timestamp(14),
+ts timestamp,
PRIMARY KEY (visitor_id,group_id)
)/*! engine=MyISAM */;
INSERT INTO t1 VALUES (465931136,7,2,2,20000318160952);
@@ -45,3 +45,29 @@ visitor_id mts
465931136 2000-03-18 16:09:53
1092858576 2000-03-19 01:34:45
drop table t1;
+set sql_mode='traditional';
+create table t1 (d date);
+insert into t1 (d) select date_sub('2000-01-01', INTERVAL 2001 YEAR);
+ERROR 22008: Datetime function: datetime field overflow
+insert into t1 (d) select date_add('2000-01-01',interval 8000 year);
+ERROR 22008: Datetime function: datetime field overflow
+insert into t1 values (date_add(NULL, INTERVAL 1 DAY));
+insert into t1 values (date_add('2000-01-04', INTERVAL NULL DAY));
+set sql_mode='';
+insert into t1 (d) select date_sub('2000-01-01', INTERVAL 2001 YEAR);
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
+insert into t1 (d) select date_add('2000-01-01',interval 8000 year);
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
+insert into t1 values (date_add(NULL, INTERVAL 1 DAY));
+insert into t1 values (date_add('2000-01-04', INTERVAL NULL DAY));
+select * from t1;
+d
+NULL
+NULL
+NULL
+NULL
+NULL
+NULL
+drop table t1;
diff --git a/mysql-test/r/func_default.result b/mysql-test/r/func_default.result
index 2993d79a870..5742ddd102b 100644
--- a/mysql-test/r/func_default.result
+++ b/mysql-test/r/func_default.result
@@ -8,7 +8,7 @@ explain extended select default(str), default(strnull), default(intg), default(r
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
Warnings:
-Note 1003 select default(test.t1.str) AS `default(str)`,default(test.t1.strnull) AS `default(strnull)`,default(test.t1.intg) AS `default(intg)`,default(test.t1.rel) AS `default(rel)` from test.t1
+Note 1003 select default(`test`.`t1`.`str`) AS `default(str)`,default(`test`.`t1`.`strnull`) AS `default(strnull)`,default(`test`.`t1`.`intg`) AS `default(intg)`,default(`test`.`t1`.`rel`) AS `default(rel)` from `test`.`t1`
select * from t1 where str <> default(str);
str strnull intg rel
0 0
@@ -16,3 +16,8 @@ explain select * from t1 where str <> default(str);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
drop table t1;
+CREATE TABLE t1 (id int(11), s varchar(20));
+INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
+SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
+ERROR HY000: Field 'mi' doesn't have a default value
+DROP TABLE t1;
diff --git a/mysql-test/r/func_equal.result b/mysql-test/r/func_equal.result
index 352b76f2744..fe5e5b1b371 100644
--- a/mysql-test/r/func_equal.result
+++ b/mysql-test/r/func_equal.result
@@ -1,7 +1,7 @@
drop table if exists t1,t2;
-select 0<=>0,0.0<=>0.0,"A"<=>"A",NULL<=>NULL;
-0<=>0 0.0<=>0.0 "A"<=>"A" NULL<=>NULL
-1 1 1 1
+select 0<=>0,0.0<=>0.0,0E0=0E0,"A"<=>"A",NULL<=>NULL;
+0<=>0 0.0<=>0.0 0E0=0E0 "A"<=>"A" NULL<=>NULL
+1 1 1 1 1
select 1<=>0,0<=>NULL,NULL<=>0;
1<=>0 0<=>NULL NULL<=>0
0 0 0
@@ -11,6 +11,12 @@ select 1.0<=>0.0,0.0<=>NULL,NULL<=>0.0;
select "A"<=>"B","A"<=>NULL,NULL<=>"A";
"A"<=>"B" "A"<=>NULL NULL<=>"A"
0 0 0
+select 0<=>0.0, 0.0<=>0E0, 0E0<=>"0", 10.0<=>1E1, 10<=>10.0, 10<=>1E1;
+0<=>0.0 0.0<=>0E0 0E0<=>"0" 10.0<=>1E1 10<=>10.0 10<=>1E1
+1 1 1 1 1 1
+select 1.0<=>0E1,10<=>NULL,NULL<=>0.0, NULL<=>0E0;
+1.0<=>0E1 10<=>NULL NULL<=>0.0 NULL<=>0E0
+0 0 0 0
create table t1 (id int, value int);
create table t2 (id int, value int);
insert into t1 values (1,null);
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index d7a741827d5..6461c393d51 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -18,7 +18,7 @@ explain extended select grp,group_concat(c) from t1 group by grp;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 9 Using filesort
Warnings:
-Note 1003 select test.t1.grp AS `grp`,group_concat(test.t1.c separator ',') AS `group_concat(c)` from test.t1 group by test.t1.grp
+Note 1003 select `test`.`t1`.`grp` AS `grp`,group_concat(`test`.`t1`.`c` separator ',') AS `group_concat(c)` from `test`.`t1` group by `test`.`t1`.`grp`
select grp,group_concat(a,c) from t1 group by grp;
grp group_concat(a,c)
1 1a
@@ -93,7 +93,7 @@ explain extended select grp,group_concat(distinct c order by c desc) from t1 gro
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 9 Using filesort
Warnings:
-Note 1003 select test.t1.grp AS `grp`,group_concat(distinct test.t1.c order by test.t1.c separator ',') AS `group_concat(distinct c order by c desc)` from test.t1 group by test.t1.grp
+Note 1003 select `test`.`t1`.`grp` AS `grp`,group_concat(distinct `test`.`t1`.`c` order by `test`.`t1`.`c` separator ',') AS `group_concat(distinct c order by c desc)` from `test`.`t1` group by `test`.`t1`.`grp`
select grp,group_concat(c order by c separator ",") from t1 group by grp;
grp group_concat(c order by c separator ",")
1 a
@@ -113,7 +113,7 @@ explain extended select grp,group_concat(distinct c order by c separator ",") fr
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 9 Using filesort
Warnings:
-Note 1003 select test.t1.grp AS `grp`,group_concat(distinct test.t1.c order by test.t1.c separator ',') AS `group_concat(distinct c order by c separator ",")` from test.t1 group by test.t1.grp
+Note 1003 select `test`.`t1`.`grp` AS `grp`,group_concat(distinct `test`.`t1`.`c` order by `test`.`t1`.`c` separator ',') AS `group_concat(distinct c order by c separator ",")` from `test`.`t1` group by `test`.`t1`.`grp`
select grp,group_concat(distinct c order by c desc separator ",") from t1 group by grp;
grp group_concat(distinct c order by c desc separator ",")
1 a
@@ -166,7 +166,7 @@ set group_concat_max_len = 1024;
select group_concat(sum(a)) from t1 group by grp;
ERROR HY000: Invalid use of group function
select grp,group_concat(c order by 2) from t1 group by grp;
-ERROR 42S22: Unknown column '2' in 'group statement'
+ERROR 42S22: Unknown column '2' in 'order clause'
drop table t1;
create table t1 ( URL_ID int(11), URL varchar(80));
create table t2 ( REQ_ID int(11), URL_ID int(11));
@@ -458,7 +458,7 @@ create table t2 select group_concat(a) as a from t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `a` longtext character set cp1250
+ `a` varchar(400) character set cp1250 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select collation(group_concat(a,_koi8r'test')) from t1;
collation(group_concat(a,_koi8r'test'))
@@ -526,6 +526,13 @@ a group_concat(distinct b order by b)
2 3,7
NULL 1,2,3,4,7
drop table t1;
+create table t1 (a char(3), b char(20), primary key (a, b));
+insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
+select group_concat(a) from t1 group by b;
+group_concat(a)
+ABW
+ABW
+drop table t1;
CREATE TABLE t1 (
aID smallint(5) unsigned NOT NULL auto_increment,
sometitle varchar(255) NOT NULL default '',
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 2fb18ca92c7..1542794798a 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -1,4 +1,9 @@
drop table if exists t1,t2;
+set @sav_dpi= @@div_precision_increment;
+set div_precision_increment= 5;
+show variables like 'div_precision_increment';
+Variable_name Value
+div_precision_increment 5
create table t1 (grp int, a bigint unsigned, c char(10) not null);
insert into t1 values (1,1,"a");
insert into t1 values (2,2,"b");
@@ -44,13 +49,13 @@ count(distinct a) count(distinct grp)
6 3
select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
sum(all a) count(all a) avg(all a) std(all a) variance(all a) bit_or(all a) bit_and(all a) min(all a) max(all a) min(all c) max(all c)
-21 6 3.5000 1.7078 2.9167 7 0 1 6 E
+21 6 3.50000 1.70783 2.91667 7 0 1 6 E
select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
grp sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
NULL NULL 0 NULL NULL NULL 0 18446744073709551615 NULL NULL
-1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a
-2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c
-3 15 3 5.0000 0.8165 0.6667 7 4 4 6 C E
+1 1 1 1.00000 0.00000 0.00000 1 1 1 1 a a
+2 5 2 2.50000 0.50000 0.25000 3 2 2 3 b c
+3 15 3 5.00000 0.81650 0.66667 7 4 4 6 C E
select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
grp sum
NULL NULL
@@ -74,12 +79,12 @@ CREATE TABLE t2 (id int(11),name char(20));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
select id, avg(value1), std(value1), variance(value1) from t1 group by id;
id avg(value1) std(value1) variance(value1)
-1 1.000000 0.816497 0.666667
-2 11.000000 0.816497 0.666667
+1 1.0000000 0.816497 0.666667
+2 11.0000000 0.816497 0.666667
select name, avg(value1), std(value1), variance(value1) from t1, t2 where t1.id = t2.id group by t1.id;
name avg(value1) std(value1) variance(value1)
-Set One 1.000000 0.816497 0.666667
-Set Two 11.000000 0.816497 0.666667
+Set One 1.0000000 0.816497 0.666667
+Set Two 11.0000000 0.816497 0.666667
drop table t1,t2;
create table t1 (id int not null);
create table t2 (id int not null,rating int null);
@@ -87,9 +92,29 @@ insert into t1 values(1),(2),(3);
insert into t2 values(1, 3),(2, NULL),(2, NULL),(3, 2),(3, NULL);
select t1.id, avg(rating) from t1 left join t2 on ( t1.id = t2.id ) group by t1.id;
id avg(rating)
-1 3.0000
+1 3.00000
2 NULL
-3 2.0000
+3 2.00000
+select sql_small_result t2.id, avg(rating) from t2 group by t2.id;
+id avg(rating)
+1 3.00000
+2 NULL
+3 2.00000
+select sql_big_result t2.id, avg(rating) from t2 group by t2.id;
+id avg(rating)
+1 3.00000
+2 NULL
+3 2.00000
+select sql_small_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
+id avg(rating+0.0e0)
+1 3
+2 NULL
+3 2
+select sql_big_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
+id avg(rating+0.0e0)
+1 3
+2 NULL
+3 2
drop table t1,t2;
create table t1 (a smallint(6) primary key, c char(10), b text);
INSERT INTO t1 VALUES (1,'1','1');
@@ -183,12 +208,12 @@ insert into t2 values('BBB', 20, 1.0);
select t1.a1, t1.a2, t2.a1, t2.a2 from t1,t2;
a1 a2 a1 a2
10 aaa AAA 10
-10 NULL AAA 10
-10 bbb AAA 10
-20 zzz AAA 10
10 aaa BBB 20
+10 NULL AAA 10
10 NULL BBB 20
+10 bbb AAA 10
10 bbb BBB 20
+20 zzz AAA 10
20 zzz BBB 20
select max(t1.a1), max(t2.a1) from t1, t2 where t2.a2=9;
max(t1.a1) max(t2.a1)
@@ -245,27 +270,27 @@ insert into t1 values (2,1);
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
-2 1 1 1.0000 0.0000 1 1 1 1
+2 1 1 1.00000 0.00000 1 1 1 1
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
-2 1 1 1.0000 0.0000 1 1 1 1
+2 1 1 1.00000 0.00000 1 1 1 1
insert into t1 values (3,1);
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
-2 1 1 1.0000 0.0000 1 1 1 1
-3 1 1 1.0000 0.0000 1 1 1 1
+2 1 1 1.00000 0.00000 1 1 1 1
+3 1 1 1.00000 0.00000 1 1 1 1
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) bit_xor(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0 0
-2 1 1 1.0000 0.0000 1 1 1 1 1
-3 1 1 1.0000 0.0000 1 1 1 1 1
+2 1 1 1.00000 0.00000 1 1 1 1 1
+3 1 1 1.00000 0.00000 1 1 1 1 1
explain extended select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using filesort
Warnings:
-Note 1003 select sql_big_result test.t1.a AS `a`,count(test.t1.b) AS `count(b)`,sum(test.t1.b) AS `sum(b)`,avg(test.t1.b) AS `avg(b)`,std(test.t1.b) AS `std(b)`,min(test.t1.b) AS `min(b)`,max(test.t1.b) AS `max(b)`,bit_and(test.t1.b) AS `bit_and(b)`,bit_or(test.t1.b) AS `bit_or(b)`,bit_xor(test.t1.b) AS `bit_xor(b)` from test.t1 group by test.t1.a
+Note 1003 select sql_big_result `test`.`t1`.`a` AS `a`,count(`test`.`t1`.`b`) AS `count(b)`,sum(`test`.`t1`.`b`) AS `sum(b)`,avg(`test`.`t1`.`b`) AS `avg(b)`,std(`test`.`t1`.`b`) AS `std(b)`,min(`test`.`t1`.`b`) AS `min(b)`,max(`test`.`t1`.`b`) AS `max(b)`,bit_and(`test`.`t1`.`b`) AS `bit_and(b)`,bit_or(`test`.`t1`.`b`) AS `bit_or(b)`,bit_xor(`test`.`t1`.`b`) AS `bit_xor(b)` from `test`.`t1` group by `test`.`t1`.`a`
drop table t1;
create table t1 (col int);
insert into t1 values (-1), (-2), (-3);
@@ -315,12 +340,14 @@ insert into t1 values('GTM',3,'DAL',0.070,date'1977-09-23');
insert into t1 values('SSJ',null,'CHI',null,date'1974-03-19');
insert into t1 values('KKK',3,'ATL',null,null);
insert into t1 values('XXX',null,'MIN',null,null);
+insert into t1 values('WWW',1,'LED',null,null);
insert into t2 values('TKF','Seattle','WA','AME');
insert into t2 values('LCC','Los Angeles','CA','TWU');
insert into t2 values('DEN','Denver','CO','BDL');
insert into t2 values('SDC','San Diego','CA','TWU');
insert into t2 values('NOL','New Orleans','LA','GTM');
insert into t2 values('LAK','Los Angeles','CA','TWU');
+insert into t2 values('AAA','AAA','AA','AME');
select * from t1;
a1 a2 a3 a4 a5
AME 0 SEA 0.1 1942-02-19
@@ -337,6 +364,7 @@ GTM 3 DAL 0.07 1977-09-23
SSJ NULL CHI NULL 1974-03-19
KKK 3 ATL NULL NULL
XXX NULL MIN NULL NULL
+WWW 1 LED NULL NULL
select * from t2;
a1 a2 a3 a4
TKF Seattle WA AME
@@ -345,6 +373,7 @@ DEN Denver CO BDL
SDC San Diego CA TWU
NOL New Orleans LA GTM
LAK Los Angeles CA TWU
+AAA AAA AA AME
explain
select min(a1) from t1;
id select_type table type possible_keys key key_len ref rows Extra
@@ -474,7 +503,7 @@ CHI Los Angeles
explain
select max(a3) from t1 where a2 is null and a2 = 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
select max(a3) from t1 where a2 is null and a2 = 2;
max(a3)
NULL
@@ -572,15 +601,15 @@ AME AME
explain
select min(a1) from t1 where a1 > 'KKK' or a1 < 'XXX';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 0 NULL 15 Using where; Using index
+1 SIMPLE t1 index PRIMARY PRIMARY 3 NULL 15 Using where; Using index
explain
select min(a1) from t1 where a1 != 'KKK';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 3 NULL 14 Using where; Using index
+1 SIMPLE t1 index PRIMARY PRIMARY 3 NULL 15 Using where; Using index
explain
select max(a3) from t1 where a2 < 2 and a3 < 'SEA';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range k1 k1 3 NULL 5 Using where; Using index
+1 SIMPLE t1 range k1 k1 3 NULL 6 Using where; Using index
explain
select max(t1.a3), min(t2.a2) from t1, t2 where t1.a2 = 2 and t1.a3 < 'MIN' and t2.a3 > 'CA';
id select_type table type possible_keys key key_len ref rows Extra
@@ -589,40 +618,40 @@ id select_type table type possible_keys key key_len ref rows Extra
explain
select min(a4 - 0.01) from t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL k2 12 NULL 14 Using index
+1 SIMPLE t1 index NULL k2 12 NULL 15 Using index
explain
select max(a4 + 0.01) from t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL k2 12 NULL 14 Using index
+1 SIMPLE t1 index NULL k2 12 NULL 15 Using index
explain
select min(a3) from t1 where (a2 +1 ) is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL k1 7 NULL 14 Using where; Using index
+1 SIMPLE t1 index NULL k1 7 NULL 15 Using where; Using index
explain
select min(a3) from t1 where (a2 + 1) = 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL k1 7 NULL 14 Using where; Using index
+1 SIMPLE t1 index NULL k1 7 NULL 15 Using where; Using index
explain
select min(a3) from t1 where 2 = (a2 + 1);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL k1 7 NULL 14 Using where; Using index
+1 SIMPLE t1 index NULL k1 7 NULL 15 Using where; Using index
explain
select min(a2) from t1 where a2 < 2 * a2 - 8;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL k1 7 NULL 14 Using where; Using index
+1 SIMPLE t1 index NULL k1 7 NULL 15 Using where; Using index
explain
select min(a1) from t1 where a1 between a3 and 'KKK';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 14 Using where
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 15 Using where
explain
select min(a4) from t1 where (a4 + 0.01) between 0.07 and 0.08;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL k2 12 NULL 14 Using where; Using index
+1 SIMPLE t1 index NULL k2 12 NULL 15 Using where; Using index
explain
select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range k2 k2 4 NULL 6 Using where; Using index
-1 SIMPLE t1 index NULL PRIMARY 3 NULL 14 Using index
+1 SIMPLE t1 index NULL PRIMARY 3 NULL 15 Using index
drop table t1, t2;
create table t1 (USR_ID integer not null, MAX_REQ integer not null, constraint PK_SEA_USER primary key (USR_ID)) engine=InnoDB;
insert into t1 values (1, 3);
@@ -645,6 +674,11 @@ select charset(max(a)), coercibility(max(a)),
charset(min(a)), coercibility(min(a)) from t1;
charset(max(a)) coercibility(max(a)) charset(min(a)) coercibility(min(a))
latin2 2 latin2 2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(1) character set latin2 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
create table t2 select max(a),min(a) from t1;
show create table t2;
Table Create Table
@@ -652,6 +686,13 @@ t2 CREATE TABLE `t2` (
`max(a)` char(1) character set latin2 default NULL,
`min(a)` char(1) character set latin2 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 select concat(a) from t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `concat(a)` varchar(1) character set latin2 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t2,t1;
create table t1 (a int);
insert into t1 values (1);
@@ -752,7 +793,7 @@ drop table t2;
create table t2 select f2 from (select now() f2 from t1) a;
show columns from t2;
Field Type Null Key Default Extra
-f2 datetime 0000-00-00 00:00:00
+f2 datetime NO 0000-00-00 00:00:00
drop table t2, t1;
CREATE TABLE t1(
id int PRIMARY KEY,
@@ -780,3 +821,135 @@ SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
MAX(id)
NULL
DROP TABLE t1;
+create table t2 (ff double);
+insert into t2 values (2.2);
+select cast(sum(distinct ff) as decimal(5,2)) from t2;
+cast(sum(distinct ff) as decimal(5,2))
+2.20
+select cast(sum(distinct ff) as signed) from t2;
+cast(sum(distinct ff) as signed)
+2
+select cast(variance(ff) as decimal(10,3)) from t2;
+cast(variance(ff) as decimal(10,3))
+0.000
+select cast(min(ff) as decimal(5,2)) from t2;
+cast(min(ff) as decimal(5,2))
+2.20
+create table t1 (df decimal(5,1));
+insert into t1 values(1.1);
+insert into t1 values(2.2);
+select cast(sum(distinct df) as signed) from t1;
+cast(sum(distinct df) as signed)
+3
+select cast(min(df) as signed) from t1;
+cast(min(df) as signed)
+0
+select 1e8 * sum(distinct df) from t1;
+1e8 * sum(distinct df)
+330000000
+select 1e8 * min(df) from t1;
+1e8 * min(df)
+110000000
+create table t3 (ifl int);
+insert into t3 values(1), (2);
+select cast(min(ifl) as decimal(5,2)) from t3;
+cast(min(ifl) as decimal(5,2))
+1.00
+drop table t1, t2, t3;
+CREATE TABLE t1 (id int(11),value1 float(10,2));
+INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00), (2,13.00);
+select id, stddev_pop(value1), var_pop(value1), stddev_samp(value1), var_samp(value1) from t1 group by id;
+id stddev_pop(value1) var_pop(value1) stddev_samp(value1) var_samp(value1)
+1 0.816497 0.666667 1.000000 1.000000
+2 1.118034 1.250000 1.290994 1.666667
+DROP TABLE t1;
+CREATE TABLE t1 (col1 decimal(16,12));
+INSERT INTO t1 VALUES (-5.00000000001),(-5.00000000002),(-5.00000000003),(-5.00000000000),(-5.00000000001),(-5.00000000002);
+insert into t1 select * from t1;
+select col1,count(col1),sum(col1),avg(col1) from t1 group by col1;
+col1 count(col1) sum(col1) avg(col1)
+-5.000000000030 2 -10.000000000060 -5.00000000003000000
+-5.000000000020 4 -20.000000000080 -5.00000000002000000
+-5.000000000010 4 -20.000000000040 -5.00000000001000000
+-5.000000000000 2 -10.000000000000 -5.00000000000000000
+DROP TABLE t1;
+create table t1 (col1 decimal(16,12));
+insert into t1 values (-5.00000000001);
+insert into t1 values (-5.00000000001);
+select col1,sum(col1),max(col1),min(col1) from t1 group by col1;
+col1 sum(col1) max(col1) min(col1)
+-5.000000000010 -10.000000000020 -5.000000000010 -5.000000000010
+delete from t1;
+insert into t1 values (5.00000000001);
+insert into t1 values (5.00000000001);
+select col1,sum(col1),max(col1),min(col1) from t1 group by col1;
+col1 sum(col1) max(col1) min(col1)
+5.000000000010 10.000000000020 5.000000000010 5.000000000010
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(400));
+INSERT INTO t1 (a) VALUES ("A"), ("a"), ("a "), ("a "),
+("B"), ("b"), ("b "), ("b ");
+SELECT COUNT(DISTINCT a) FROM t1;
+COUNT(DISTINCT a)
+2
+DROP TABLE t1;
+CREATE TABLE t1 (a int, b int, c int);
+INSERT INTO t1 (a, b, c) VALUES
+(1,1,1), (1,1,2), (1,1,3),
+(1,2,1), (1,2,2), (1,2,3),
+(1,3,1), (1,3,2), (1,3,3),
+(2,1,1), (2,1,2), (2,1,3),
+(2,2,1), (2,2,2), (2,2,3),
+(2,3,1), (2,3,2), (2,3,3),
+(3,1,1), (3,1,2), (3,1,3),
+(3,2,1), (3,2,2), (3,2,3),
+(3,3,1), (3,3,2), (3,3,3);
+SELECT b/c as v, a FROM t1 ORDER BY v;
+v a
+0.33333 3
+0.33333 1
+0.33333 2
+0.50000 1
+0.50000 2
+0.50000 3
+0.66667 2
+0.66667 1
+0.66667 3
+1.00000 3
+1.00000 2
+1.00000 3
+1.00000 1
+1.00000 2
+1.00000 3
+1.00000 2
+1.00000 1
+1.00000 1
+1.50000 3
+1.50000 2
+1.50000 1
+2.00000 1
+2.00000 3
+2.00000 2
+3.00000 3
+3.00000 2
+3.00000 1
+SELECT b/c as v, SUM(a) FROM t1 GROUP BY v;
+v SUM(a)
+0.33333 6
+0.50000 6
+0.66667 6
+1.00000 18
+1.50000 6
+2.00000 6
+3.00000 6
+SELECT SUM(a) FROM t1 GROUP BY b/c;
+SUM(a)
+6
+6
+6
+18
+6
+6
+6
+DROP TABLE t1;
+set div_precision_increment= @sav_dpi;
diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result
index 2c8f19f1754..aee23b38ca5 100644
--- a/mysql-test/r/func_if.result
+++ b/mysql-test/r/func_if.result
@@ -43,22 +43,27 @@ explain extended select if(u=1,st,binary st) s from t1 where st like "%a%" order
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where; Using filesort
Warnings:
-Note 1003 select if((test.t1.u = 1),test.t1.st,cast(test.t1.st as char charset binary)) AS `s` from test.t1 where (test.t1.st like _latin1'%a%') order by if((test.t1.u = 1),test.t1.st,cast(test.t1.st as char charset binary))
-select nullif(u=0, 'test') from t1;
-nullif(u=0, 'test')
+Note 1003 select if((`test`.`t1`.`u` = 1),`test`.`t1`.`st`,cast(`test`.`t1`.`st` as char charset binary)) AS `s` from `test`.`t1` where (`test`.`t1`.`st` like _latin1'%a%') order by if((`test`.`t1`.`u` = 1),`test`.`t1`.`st`,cast(`test`.`t1`.`st` as char charset binary))
+select nullif(u, 1) from t1;
+nullif(u, 1)
NULL
NULL
NULL
NULL
NULL
-1
-1
-explain extended select nullif(u=0, 'test') from t1;
+0
+0
+explain extended select nullif(u, 1) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7
Warnings:
-Note 1003 select nullif((test.t1.u = 0),_latin1'test') AS `nullif(u=0, 'test')` from test.t1
+Note 1003 select nullif(`test`.`t1`.`u`,1) AS `nullif(u, 1)` from `test`.`t1`
drop table t1;
+select nullif(1,'test');
+nullif(1,'test')
+1
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'test'
select NULLIF(NULL,NULL), NULLIF(NULL,1), NULLIF(NULL,1.0), NULLIF(NULL,"test");
NULLIF(NULL,NULL) NULLIF(NULL,1) NULLIF(NULL,1.0) NULLIF(NULL,"test")
NULL NULL NULL NULL
@@ -86,6 +91,23 @@ drop table t1;
SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL;
NULLIF(5,5) IS NULL NULLIF(5,5) IS NOT NULL
1 0
+CREATE TABLE `t1` (
+`id` int(11) NOT NULL ,
+`date` int(10) default NULL,
+`text` varchar(32) NOT NULL
+);
+INSERT INTO t1 VALUES (1,1110000000,'Day 1'),(2,1111000000,'Day 2'),(3,1112000000,'Day 3');
+SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord ASC;
+id date_ord text
+1 05-03-2005 Day 1
+2 16-03-2005 Day 2
+3 28-03-2005 Day 3
+SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord DESC;
+id date_ord text
+3 28-03-2005 Day 3
+2 16-03-2005 Day 2
+1 05-03-2005 Day 1
+DROP TABLE t1;
CREATE TABLE t1 (a CHAR(10));
INSERT INTO t1 VALUES ('aaa'), (NULL), (''), ('bbb');
SELECT a, NULLIF(a,'') FROM t1;
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index 516d0a28a21..a0868d09242 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -119,7 +119,7 @@ c char(1) character set latin1 collate latin1_danish_ci
insert into t1 values ('A','B','C');
insert into t1 values ('a','c','c');
select * from t1 where a in (b);
-ERROR HY000: Illegal mix of collations (latin1_general_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation ' IN '
+ERROR HY000: Illegal mix of collations (latin1_general_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '='
select * from t1 where a in (b,c);
ERROR HY000: Illegal mix of collations (latin1_general_ci,IMPLICIT), (latin1_swedish_ci,IMPLICIT), (latin1_danish_ci,IMPLICIT) for operation ' IN '
select * from t1 where 'a' in (a,b,c);
@@ -146,7 +146,7 @@ explain extended select * from t1 where 'a' in (a,b,c collate latin1_bin);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
Warnings:
-Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 where (_latin1'a' in (test.t1.a,test.t1.b,(test.t1.c collate _latin1'latin1_bin')))
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (_latin1'a' in (`test`.`t1`.`a`,`test`.`t1`.`b`,(`test`.`t1`.`c` collate latin1_bin)))
drop table t1;
set names utf8;
create table t1 (a char(10) character set utf8 not null);
@@ -193,3 +193,26 @@ select * from t1 where a in (NULL, 'aa');
a
aa
drop table t1;
+CREATE TABLE t1 (a int PRIMARY KEY);
+INSERT INTO t1 VALUES (44), (45), (46);
+SELECT * FROM t1 WHERE a IN (45);
+a
+45
+SELECT * FROM t1 WHERE a NOT IN (0, 45);
+a
+44
+46
+SELECT * FROM t1 WHERE a NOT IN (45);
+a
+44
+46
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE a NOT IN (45);
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` where (`t1`.`a` <> 45)
+SELECT * FROM v1;
+a
+44
+46
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result
index bc658f9f7de..7e6fedb9403 100644
--- a/mysql-test/r/func_like.result
+++ b/mysql-test/r/func_like.result
@@ -3,10 +3,10 @@ create table t1 (a varchar(10), key(a));
insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
explain select * from t1 where a like 'abc%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 11 NULL 1 Using where; Using index
+1 SIMPLE t1 index a a 13 NULL 5 Using where; Using index
explain select * from t1 where a like concat('abc','%');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 11 NULL 1 Using where; Using index
+1 SIMPLE t1 index a a 13 NULL 5 Using where; Using index
select * from t1 where a like "abc%";
a
abc
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index b36902d7872..5b6c29f87fb 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -120,6 +120,9 @@ ASIN(0.8+0.2)
SELECT ASIN(1.2-0.2);
ASIN(1.2-0.2)
1.5707963267949
+select format(4.55, 1), format(4.551, 1);
+format(4.55, 1) format(4.551, 1)
+4.6 4.6
explain extended select degrees(pi()),radians(360);
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
@@ -127,11 +130,33 @@ Warnings:
Note 1003 select degrees(pi()) AS `degrees(pi())`,radians(360) AS `radians(360)`
select rand(rand);
ERROR 42S22: Unknown column 'rand' in 'field list'
+create table t1 (col1 int, col2 decimal(60,30));
+insert into t1 values(1,1234567890.12345);
+select format(col2,7) from t1;
+format(col2,7)
+1,234,567,890.1234500
+select format(col2,8) from t1;
+format(col2,8)
+1,234,567,890.12345000
+insert into t1 values(7,1234567890123456.12345);
+select format(col2,6) from t1 where col1=7;
+format(col2,6)
+1,234,567,890,123,456.123450
+drop table t1;
+select round(150, 2);
+round(150, 2)
+150.00
+select ceil(0.09);
+ceil(0.09)
+1
+select ceil(0.000000000000000009);
+ceil(0.000000000000000009)
+1
create table t1 select round(1, 6);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `round(1, 6)` double(7,6) NOT NULL default '0.000000'
+ `round(1, 6)` decimal(7,6) NOT NULL default '0.000000'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1;
round(1, 6)
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index 2d464c891bf..36666fc827d 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -25,6 +25,8 @@ length(uuid()) charset(uuid()) length(unhex(replace(uuid(),_utf8'-',_utf8'')))
select length(format('nan', 2)) > 0;
length(format('nan', 2)) > 0
1
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'nan'
select concat("$",format(2500,2));
concat("$",format(2500,2))
$2,500.00
@@ -49,3 +51,46 @@ select a from t1 where mid(a+0,6,3) = ( mid(20040106123400,6,3) );
a
2004-01-06 12:34:00
drop table t1;
+create table t1 as select uuid(), length(uuid());
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `uuid()` varchar(36) character set utf8 NOT NULL default '',
+ `length(uuid())` int(10) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a timestamp default '2005-05-05 01:01:01',
+b timestamp default '2005-05-05 01:01:01');
+insert into t1 set a = now();
+select sleep(3);
+sleep(3)
+0
+update t1 set b = now();
+select timediff(b, a) >= '00:00:03' from t1;
+timediff(b, a) >= '00:00:03'
+1
+drop table t1;
+set global query_cache_size=1355776;
+create table t1 (a int);
+insert into t1 values (1),(1),(1);
+create table t2 (a datetime default null, b datetime default null);
+insert into t2 set a = now();
+select a from t1 where sleep(1);
+a
+update t2 set b = now() where b is null;
+insert into t2 set a = now();
+select a from t1 where sleep(a);
+a
+update t2 set b = now() where b is null;
+insert into t2 set a = now();
+select a from t1 where sleep(1);
+a
+update t2 set b = now() where b is null;
+select timediff(b, a) >= '00:00:03' from t2;
+timediff(b, a) >= '00:00:03'
+1
+1
+1
+drop table t2;
+drop table t1;
+set global query_cache_size=default;
diff --git a/mysql-test/r/func_op.result b/mysql-test/r/func_op.result
index 6cd975b0911..61b29e9380d 100644
--- a/mysql-test/r/func_op.result
+++ b/mysql-test/r/func_op.result
@@ -1,6 +1,6 @@
select 1+1,1-1,1+1*2,8/5,8%5,mod(8,5),mod(8,5)|0,-(1+1)*-2;
1+1 1-1 1+1*2 8/5 8%5 mod(8,5) mod(8,5)|0 -(1+1)*-2
-2 0 3 1.60 3 3 3 4
+2 0 3 1.6000 3 3 3 4
explain extended select 1+1,1-1,1+1*2,8/5,8%5,mod(8,5),mod(8,5)|0,-(1+1)*-2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
diff --git a/mysql-test/r/func_regexp.result b/mysql-test/r/func_regexp.result
index 8228d6982d3..787463c6aa3 100644
--- a/mysql-test/r/func_regexp.result
+++ b/mysql-test/r/func_regexp.result
@@ -40,7 +40,7 @@ explain extended select * from t1 where xxx regexp('is a test of some long text
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
Warnings:
-Note 1003 select test.t1.xxx AS `xxx` from test.t1 where (test.t1.xxx regexp _latin1'is a test of some long text to')
+Note 1003 select `test`.`t1`.`xxx` AS `xxx` from `test`.`t1` where (`test`.`t1`.`xxx` regexp _latin1'is a test of some long text to')
select * from t1 where xxx regexp('is a test of some long text to ');
xxx
this is a test of some long text to see what happens
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index 68c3baa7bde..f209866d953 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -56,15 +56,25 @@ subdate("1997-12-31 23:59:59.000001", 10)
select datediff("1997-12-31 23:59:59.000001","1997-12-30");
datediff("1997-12-31 23:59:59.000001","1997-12-30")
1
+select datediff("1997-11-30 23:59:59.000001","1997-12-31");
+datediff("1997-11-30 23:59:59.000001","1997-12-31")
+-31
+SET @@SQL_MODE="ALLOW_INVALID_DATES";
select datediff("1997-11-31 23:59:59.000001","1997-12-31");
datediff("1997-11-31 23:59:59.000001","1997-12-31")
-30
-select datediff("1997-11-31 23:59:59.000001",null);
-datediff("1997-11-31 23:59:59.000001",null)
+SET @@SQL_MODE="";
+select datediff("1997-11-31 23:59:59.000001","1997-12-31");
+datediff("1997-11-31 23:59:59.000001","1997-12-31")
+NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '1997-11-31 23:59:59.000001'
+select datediff("1997-11-30 23:59:59.000001",null);
+datediff("1997-11-30 23:59:59.000001",null)
NULL
-select weekofyear("1997-11-31 23:59:59.000001");
-weekofyear("1997-11-31 23:59:59.000001")
-49
+select weekofyear("1997-11-30 23:59:59.000001");
+weekofyear("1997-11-30 23:59:59.000001")
+48
select makedate(1997,1);
makedate(1997,1)
1997-01-01
@@ -167,12 +177,12 @@ date("1997-12-31 23:59:59.000001") as f8,
time("1997-12-31 23:59:59.000001") as f9;
describe t1;
Field Type Null Key Default Extra
-f1 date 0000-00-00
+f1 date NO 0000-00-00
f2 datetime YES NULL
f3 time YES NULL
-f4 time 00:00:00
-f5 time 00:00:00
-f6 time 00:00:00
+f4 time NO 00:00:00
+f5 time NO 00:00:00
+f6 time NO 00:00:00
f7 datetime YES NULL
f8 date YES NULL
f9 time YES NULL
@@ -199,16 +209,17 @@ ttt qqq
NULL NULL
NULL NULL
2001-01-01 02:02:02 26:02:02
-SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
-ttt qqq
--744:00:00 NULL
-26305:01:02 22:58:58
--26305:01:02 -22:58:58
-NULL 26:02:02
-00:00:00 -26:02:02
-NULL NULL
-NULL NULL
-00:00:00 -24:00:00
+SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq,
+TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test;
+ttt qqq eee rrr
+-744:00:00 NULL NULL NULL
+26305:01:02 22:58:58 -22:58:58 NULL
+-26305:01:02 -22:58:58 22:58:58 NULL
+NULL 26:02:02 -26:02:02 NULL
+00:00:00 -26:02:02 26:02:02 NULL
+NULL NULL NULL NULL
+NULL NULL NULL NULL
+00:00:00 -24:00:00 24:00:00 NULL
drop table t1, test;
select addtime("-01:01:01.01", "-23:59:59.1") as a;
a
diff --git a/mysql-test/r/func_set.result b/mysql-test/r/func_set.result
index ca6e0a8c319..aa71cee0752 100644
--- a/mysql-test/r/func_set.result
+++ b/mysql-test/r/func_set.result
@@ -30,6 +30,12 @@ Y-N-N-Y-N Y,N,N,Y,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,
select elt(2,1),field(NULL,"a","b","c");
elt(2,1) field(NULL,"a","b","c")
NULL 0
+select field("b","a",NULL),field(1,0,NULL)+0,field(1.0,0.0,NULL)+0.0,field(1.0e1,0.0e1,NULL)+0.0e1;
+field("b","a",NULL) field(1,0,NULL)+0 field(1.0,0.0,NULL)+0.0 field(1.0e1,0.0e1,NULL)+0.0e1
+0 0 0.0 0
+select field(NULL,"a",NULL),field(NULL,0,NULL)+0,field(NULL,0.0,NULL)+0.0,field(NULL,0.0e1,NULL)+0.0e1;
+field(NULL,"a",NULL) field(NULL,0,NULL)+0 field(NULL,0.0,NULL)+0.0 field(NULL,0.0e1,NULL)+0.0e1
+0 0 0.0 0
select find_in_set("","a,b,c"),find_in_set("","a,b,c,"),find_in_set("",",a,b,c");
find_in_set("","a,b,c") find_in_set("","a,b,c,") find_in_set("",",a,b,c")
0 4 1
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index ae6578795f6..577f943ebde 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
set names latin1;
select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo';
hello 'hello' ""hello"" 'h'e'l'l'o' hel"lo hel'lo
@@ -165,6 +165,9 @@ the king of the
select concat(':',ltrim(' left '),':',rtrim(' right '),':');
concat(':',ltrim(' left '),':',rtrim(' right '),':')
:left : right:
+select concat(':',trim(leading from ' left '),':',trim(trailing from ' right '),':');
+concat(':',trim(leading from ' left '),':',trim(trailing from ' right '),':')
+:left : right:
select concat(':',trim(LEADING FROM ' left'),':',trim(TRAILING FROM ' right '),':');
concat(':',trim(LEADING FROM ' left'),':',trim(TRAILING FROM ' right '),':')
:left: right:
@@ -284,7 +287,7 @@ lpad('STRING', 20, CONCAT('p','a','d') )
padpadpadpadpaSTRING
select LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'),GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD');
LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD') GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD')
-HAROLD HARRY
+NULL NULL
select least(1,2,3) | greatest(16,32,8), least(5,4)*1,greatest(-1.0,1.0)*1,least(3,2,1)*1.0,greatest(1,1.1,1.0),least("10",9),greatest("A","B","0");
least(1,2,3) | greatest(16,32,8) least(5,4)*1 greatest(-1.0,1.0)*1 least(3,2,1)*1.0 greatest(1,1.1,1.0) least("10",9) greatest("A","B","0")
33 4 1.0 1.0 1.1 9 B
@@ -350,6 +353,8 @@ Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - t
select position("0" in "baaa" in (1)),position("0" in "1" in (1,2,3)),position("sql" in ("mysql"));
position("0" in "baaa" in (1)) position("0" in "1" in (1,2,3)) position("sql" in ("mysql"))
1 0 3
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'baaa'
select position(("1" in (1,2,3)) in "01");
position(("1" in (1,2,3)) in "01")
2
@@ -376,7 +381,7 @@ category int(10) unsigned default NULL,
program int(10) unsigned default NULL,
bugdesc text,
created datetime default NULL,
-modified timestamp(14) NOT NULL,
+modified timestamp NOT NULL,
bugstatus int(10) unsigned default NULL,
submitter int(10) unsigned default NULL
) ENGINE=MyISAM;
@@ -507,9 +512,9 @@ select FIELD(_latin2'b','A','B');
ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'field'
select FIELD('b',_latin2'A','B');
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'field'
-select FIELD('b',_latin2'A','B',1);
-FIELD('b',_latin2'A','B',1)
-1
+select FIELD('1',_latin2'3','2',1);
+FIELD('1',_latin2'3','2',1)
+3
select POSITION(_latin1'B' IN _latin1'abcd');
POSITION(_latin1'B' IN _latin1'abcd')
2
@@ -534,9 +539,9 @@ select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2);
SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2)
abcdabc
select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2);
-ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substr_index'
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substring_index'
select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2);
-ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substr_index'
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substring_index'
select _latin1'B' between _latin1'a' and _latin1'c';
_latin1'B' between _latin1'a' and _latin1'c'
1
@@ -711,37 +716,37 @@ Warning 1265 Data truncated for column 'format(130,10)' at row 1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `bin(130)` char(64) NOT NULL default '',
- `oct(130)` char(64) NOT NULL default '',
- `conv(130,16,10)` char(64) NOT NULL default '',
- `hex(130)` char(6) NOT NULL default '',
- `char(130)` char(1) NOT NULL default '',
- `format(130,10)` char(4) NOT NULL default '',
- `left(_latin2'a',1)` char(1) character set latin2 NOT NULL default '',
- `right(_latin2'a',1)` char(1) character set latin2 NOT NULL default '',
- `lcase(_latin2'a')` char(1) character set latin2 NOT NULL default '',
- `ucase(_latin2'a')` char(1) character set latin2 NOT NULL default '',
- `substring(_latin2'a',1,1)` char(1) character set latin2 NOT NULL default '',
- `concat(_latin2'a',_latin2'b')` char(2) character set latin2 NOT NULL default '',
- `lpad(_latin2'a',4,_latin2'b')` char(4) character set latin2 NOT NULL default '',
- `rpad(_latin2'a',4,_latin2'b')` char(4) character set latin2 NOT NULL default '',
- `concat_ws(_latin2'a',_latin2'b')` char(1) character set latin2 NOT NULL default '',
- `make_set(255,_latin2'a',_latin2'b',_latin2'c')` char(5) character set latin2 NOT NULL default '',
- `export_set(255,_latin2'y',_latin2'n',_latin2' ')` char(127) character set latin2 NOT NULL default '',
- `trim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `ltrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `rtrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `trim(LEADING _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `trim(TRAILING _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `trim(BOTH _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `repeat(_latin2'a',10)` char(10) character set latin2 NOT NULL default '',
- `reverse(_latin2'ab')` char(2) character set latin2 NOT NULL default '',
- `quote(_latin2'ab')` char(6) character set latin2 NOT NULL default '',
- `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 '',
- `encode('abcd','ab')` binary(4) NOT NULL default ''
+ `bin(130)` varchar(64) NOT NULL default '',
+ `oct(130)` varchar(64) NOT NULL default '',
+ `conv(130,16,10)` varchar(64) NOT NULL default '',
+ `hex(130)` varchar(6) NOT NULL default '',
+ `char(130)` varchar(1) NOT NULL default '',
+ `format(130,10)` varchar(4) NOT NULL default '',
+ `left(_latin2'a',1)` varchar(1) character set latin2 NOT NULL default '',
+ `right(_latin2'a',1)` varchar(1) character set latin2 NOT NULL default '',
+ `lcase(_latin2'a')` varchar(1) character set latin2 NOT NULL default '',
+ `ucase(_latin2'a')` varchar(1) character set latin2 NOT NULL default '',
+ `substring(_latin2'a',1,1)` varchar(1) character set latin2 NOT NULL default '',
+ `concat(_latin2'a',_latin2'b')` varchar(2) character set latin2 NOT NULL default '',
+ `lpad(_latin2'a',4,_latin2'b')` varchar(4) character set latin2 NOT NULL default '',
+ `rpad(_latin2'a',4,_latin2'b')` varchar(4) character set latin2 NOT NULL default '',
+ `concat_ws(_latin2'a',_latin2'b')` varchar(1) character set latin2 NOT NULL default '',
+ `make_set(255,_latin2'a',_latin2'b',_latin2'c')` varchar(5) character set latin2 NOT NULL default '',
+ `export_set(255,_latin2'y',_latin2'n',_latin2' ')` varchar(127) character set latin2 NOT NULL default '',
+ `trim(_latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `ltrim(_latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `rtrim(_latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `trim(LEADING _latin2' ' FROM _latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `trim(TRAILING _latin2' ' FROM _latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `trim(BOTH _latin2' ' FROM _latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `repeat(_latin2'a',10)` varchar(10) character set latin2 NOT NULL default '',
+ `reverse(_latin2'ab')` varchar(2) character set latin2 NOT NULL default '',
+ `quote(_latin2'ab')` varchar(6) character set latin2 NOT NULL default '',
+ `soundex(_latin2'ab')` varchar(4) character set latin2 NOT NULL default '',
+ `substring(_latin2'ab',1)` varchar(2) character set latin2 NOT NULL default '',
+ `insert(_latin2'abcd',2,3,_latin2'ef')` varchar(6) character set latin2 NOT NULL default '',
+ `replace(_latin2'abcd',_latin2'b',_latin2'B')` varchar(4) character set latin2 NOT NULL default '',
+ `encode('abcd','ab')` varbinary(4) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a char character set latin2);
@@ -806,7 +811,7 @@ explain extended select md5('hello'), sha('abc'), sha1('abc'), soundex(''), 'moo
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select md5(_latin1'hello') AS `md5('hello')`,sha(_latin1'abc') AS `sha('abc')`,sha(_latin1'abc') AS `sha1('abc')`,soundex(_latin1'') AS `soundex('')`,(soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'`,aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')`,concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')`,reverse(_latin1'abc') AS `reverse('abc')`,rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')`,lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')`,concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')`,make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a',_latin2'b',_latin2'c')`,elt(2,1) AS `elt(2,1)`,locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)`,format(130,10) AS `format(130,10)`,char(0) AS `char(0)`,conv(130,16,10) AS `conv(130,16,10)`,hex(130) AS `hex(130)`,cast(_latin1'HE' as char charset binary) AS `binary 'HE'`,export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y',_latin2'n',_latin2' ')`,field((_latin1'b' collate _latin1'latin1_bin'),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')`,find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')`,collation(conv(130,16,10)) AS `collation(conv(130,16,10))`,coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))`,length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')`,length(_latin1'hello') AS `length('hello')`,char(ascii(_latin1'h')) AS `char(ascii('h'))`,ord(_latin1'h') AS `ord('h')`,quote((1 / 0)) AS `quote(1/0)`,crc32(_latin1'123') AS `crc32("123")`,replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')`,insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')`,left(_latin2'a',1) AS `left(_latin2'a',1)`,right(_latin2'a',1) AS `right(_latin2'a',1)`,lcase(_latin2'a') AS `lcase(_latin2'a')`,ucase(_latin2'a') AS `ucase(_latin2'a')`,substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)`,substr_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)`,trim(_latin2' a ') AS `trim(_latin2' a ')`,ltrim(_latin2' a ') AS `ltrim(_latin2' a ')`,rtrim(_latin2' a ') AS `rtrim(_latin2' a ')`,decode(encode(repeat(_latin1'a',100000))) AS `decode(encode(repeat("a",100000),"monty"),"monty")`
+Note 1003 select md5(_latin1'hello') AS `md5('hello')`,sha(_latin1'abc') AS `sha('abc')`,sha(_latin1'abc') AS `sha1('abc')`,soundex(_latin1'') AS `soundex('')`,(soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'`,aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')`,concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')`,reverse(_latin1'abc') AS `reverse('abc')`,rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')`,lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')`,concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')`,make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a',_latin2'b',_latin2'c')`,elt(2,1) AS `elt(2,1)`,locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)`,format(130,10) AS `format(130,10)`,char(0) AS `char(0)`,conv(130,16,10) AS `conv(130,16,10)`,hex(130) AS `hex(130)`,cast(_latin1'HE' as char charset binary) AS `binary 'HE'`,export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y',_latin2'n',_latin2' ')`,field((_latin1'b' collate latin1_bin),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')`,find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')`,collation(conv(130,16,10)) AS `collation(conv(130,16,10))`,coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))`,length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')`,length(_latin1'hello') AS `length('hello')`,char(ascii(_latin1'h')) AS `char(ascii('h'))`,ord(_latin1'h') AS `ord('h')`,quote((1 / 0)) AS `quote(1/0)`,crc32(_latin1'123') AS `crc32("123")`,replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')`,insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')`,left(_latin2'a',1) AS `left(_latin2'a',1)`,right(_latin2'a',1) AS `right(_latin2'a',1)`,lcase(_latin2'a') AS `lcase(_latin2'a')`,ucase(_latin2'a') AS `ucase(_latin2'a')`,substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)`,substring_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)`,trim(_latin2' a ') AS `trim(_latin2' a ')`,ltrim(_latin2' a ') AS `ltrim(_latin2' a ')`,rtrim(_latin2' a ') AS `rtrim(_latin2' a ')`,decode(encode(repeat(_latin1'a',100000))) AS `decode(encode(repeat("a",100000),"monty"),"monty")`
SELECT lpad(12345, 5, "#");
lpad(12345, 5, "#")
12345
@@ -826,16 +831,16 @@ drop table t1, t2;
create table t1 (c1 INT, c2 INT UNSIGNED);
insert into t1 values ('21474836461','21474836461');
Warnings:
-Warning 1265 Data truncated for column 'c1' at row 1
-Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
insert into t1 values ('-21474836461','-21474836461');
Warnings:
-Warning 1265 Data truncated for column 'c1' at row 1
-Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
show warnings;
Level Code Message
-Warning 1265 Data truncated for column 'c1' at row 1
-Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
select * from t1;
c1 c2
2147483647 4294967295
@@ -856,6 +861,12 @@ NULL
select trim('xyz' from null) as "must_be_null";
must_be_null
NULL
+select trim(leading NULL from 'kate') as "must_be_null";
+must_be_null
+NULL
+select trim(trailing NULL from 'xyz') as "must_be_null";
+must_be_null
+NULL
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
a bigint(20) unsigned default NULL,
diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result
index d49da90fa28..1c1c6dff21e 100644
--- a/mysql-test/r/func_system.result
+++ b/mysql-test/r/func_system.result
@@ -46,8 +46,8 @@ create table t1 (version char(40)) select database(), user(), version() as 'vers
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `database()` char(34) character set utf8 default NULL,
- `user()` char(77) character set utf8 NOT NULL default '',
+ `database()` varchar(34) character set utf8 default NULL,
+ `user()` varchar(77) character set utf8 NOT NULL default '',
`version` char(40) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
@@ -61,8 +61,8 @@ create table t1 select charset(_utf8'a'), collation(_utf8'a');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `charset(_utf8'a')` char(64) character set utf8 NOT NULL default '',
- `collation(_utf8'a')` char(64) character set utf8 NOT NULL default ''
+ `charset(_utf8'a')` varchar(64) character set utf8 NOT NULL default '',
+ `collation(_utf8'a')` varchar(64) character set utf8 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select TRUE,FALSE,NULL;
diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index 8a28312b348..d9437f6c515 100644
--- a/mysql-test/r/func_test.result
+++ b/mysql-test/r/func_test.result
@@ -77,9 +77,9 @@ select * from t1 where 1 xor 1;
a
explain extended select * from t1 where 1 xor 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
-Note 1003 select test.t1.a AS `a` from test.t1 where (1 xor 1)
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1`
select - a from t1;
- a
-1
@@ -87,7 +87,7 @@ explain extended select - a from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
Warnings:
-Note 1003 select -(test.t1.a) AS `- a` from test.t1
+Note 1003 select -(`test`.`t1`.`a`) AS `- a` from `test`.`t1`
drop table t1;
select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1;
5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1
@@ -108,7 +108,7 @@ explain extended select _koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select (_koi8r'a' = (_koi8r'A' collate _latin1'koi8r_general_ci')) AS `_koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci`
+Note 1003 select (_koi8r'a' = (_koi8r'A' collate koi8r_general_ci)) AS `_koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci`
select _koi8r'a' = _koi8r'A' COLLATE koi8r_bin;
_koi8r'a' = _koi8r'A' COLLATE koi8r_bin
0
@@ -166,7 +166,6 @@ CREATE TABLE t2 ( access_id smallint(6) NOT NULL default '0', name varchar(20
INSERT INTO t2 VALUES (1,'Everyone',2),(2,'Help',3),(3,'Customer Support',1);
SELECT f_acc.rank, a1.rank, a2.rank FROM t1 LEFT JOIN t1 f1 ON (f1.access_id=1 AND f1.faq_group_id = t1.faq_group_id) LEFT JOIN t2 a1 ON (a1.access_id = f1.access_id) LEFT JOIN t1 f2 ON (f2.access_id=3 AND f2.faq_group_id = t1.faq_group_id) LEFT JOIN t2 a2 ON (a2.access_id = f2.access_id), t2 f_acc WHERE LEAST(a1.rank,a2.rank) = f_acc.rank;
rank rank rank
-2 2 NULL
DROP TABLE t1,t2;
CREATE TABLE t1 (d varchar(6), k int);
INSERT INTO t1 VALUES (NULL, 2);
@@ -183,3 +182,25 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
5 mod 3 5 mod -3 -5 mod 3 -5 mod -3
2 2 -2 -2
+create table t1 (a int, b int);
+insert into t1 values (1,2), (2,3), (3,4), (4,5);
+select * from t1 where a not between 1 and 2;
+a b
+3 4
+4 5
+select * from t1 where a not between 1 and 2 and b not between 3 and 4;
+a b
+4 5
+drop table t1;
+SELECT GREATEST(1,NULL) FROM DUAL;
+GREATEST(1,NULL)
+NULL
+SELECT LEAST('xxx','aaa',NULL,'yyy') FROM DUAL;
+LEAST('xxx','aaa',NULL,'yyy')
+NULL
+SELECT LEAST(1.1,1.2,NULL,1.0) FROM DUAL;
+LEAST(1.1,1.2,NULL,1.0)
+NULL
+SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL;
+GREATEST(1.5E+2,1.3E+2,NULL)
+NULL
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index fc872285acb..9275a893309 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -247,9 +247,13 @@ date_add("1997-12-31 23:59:59",INTERVAL -100000 DAY)
select date_add("1997-12-31 23:59:59",INTERVAL 100000 MONTH);
date_add("1997-12-31 23:59:59",INTERVAL 100000 MONTH)
NULL
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
select date_add("1997-12-31 23:59:59",INTERVAL -100000 YEAR);
date_add("1997-12-31 23:59:59",INTERVAL -100000 YEAR)
NULL
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
select date_add("1997-12-31 23:59:59",INTERVAL "10000:1" MINUTE_SECOND);
date_add("1997-12-31 23:59:59",INTERVAL "10000:1" MINUTE_SECOND)
1998-01-07 22:40:00
@@ -301,9 +305,13 @@ NULL
select date_add("9999-12-31 23:59:59",INTERVAL 1 SECOND);
date_add("9999-12-31 23:59:59",INTERVAL 1 SECOND)
NULL
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
select date_sub("0000-00-00 00:00:00",INTERVAL 1 SECOND);
date_sub("0000-00-00 00:00:00",INTERVAL 1 SECOND)
NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '0000-00-00 00:00:00'
select date_add('1998-01-30',Interval 1 month);
date_add('1998-01-30',Interval 1 month)
1998-02-28
@@ -373,15 +381,23 @@ SELECT "1900-01-01 00:00:00" + INTERVAL 1<<20 HOUR;
SELECT "1900-01-01 00:00:00" + INTERVAL 1<<38 SECOND;
"1900-01-01 00:00:00" + INTERVAL 1<<38 SECOND
NULL
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
SELECT "1900-01-01 00:00:00" + INTERVAL 1<<33 MINUTE;
"1900-01-01 00:00:00" + INTERVAL 1<<33 MINUTE
NULL
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
SELECT "1900-01-01 00:00:00" + INTERVAL 1<<30 HOUR;
"1900-01-01 00:00:00" + INTERVAL 1<<30 HOUR
NULL
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
SELECT "1900-01-01 00:00:00" + INTERVAL "1000000000:214748364700" MINUTE_SECOND;
"1900-01-01 00:00:00" + INTERVAL "1000000000:214748364700" MINUTE_SECOND
NULL
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
create table t1 (ctime varchar(20));
insert into t1 values ('2001-01-12 12:23:40');
select ctime, hour(ctime) from t1;
@@ -424,6 +440,9 @@ insert into t1 values ("0000-00-00", "0000-00-00", "0000-00-00", "0000-00-00");
select dayofyear("0000-00-00"),dayofyear(d),dayofyear(dt),dayofyear(t),dayofyear(c) from t1;
dayofyear("0000-00-00") dayofyear(d) dayofyear(dt) dayofyear(t) dayofyear(c)
NULL NULL NULL NULL NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
select dayofmonth("0000-00-00"),dayofmonth(d),dayofmonth(dt),dayofmonth(t),dayofmonth(c) from t1;
dayofmonth("0000-00-00") dayofmonth(d) dayofmonth(dt) dayofmonth(t) dayofmonth(c)
0 0 0 0 0
@@ -436,22 +455,31 @@ quarter("0000-00-00") quarter(d) quarter(dt) quarter(t) quarter(c)
select week("0000-00-00"),week(d),week(dt),week(t),week(c) from t1;
week("0000-00-00") week(d) week(dt) week(t) week(c)
NULL NULL NULL NULL NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
select year("0000-00-00"),year(d),year(dt),year(t),year(c) from t1;
year("0000-00-00") year(d) year(dt) year(t) year(c)
0 0 0 0 0
select yearweek("0000-00-00"),yearweek(d),yearweek(dt),yearweek(t),yearweek(c) from t1;
yearweek("0000-00-00") yearweek(d) yearweek(dt) yearweek(t) yearweek(c)
NULL NULL NULL NULL NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
select to_days("0000-00-00"),to_days(d),to_days(dt),to_days(t),to_days(c) from t1;
to_days("0000-00-00") to_days(d) to_days(dt) to_days(t) to_days(c)
NULL NULL NULL NULL NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
select extract(MONTH FROM "0000-00-00"),extract(MONTH FROM d),extract(MONTH FROM dt),extract(MONTH FROM t),extract(MONTH FROM c) from t1;
extract(MONTH FROM "0000-00-00") extract(MONTH FROM d) extract(MONTH FROM dt) extract(MONTH FROM t) extract(MONTH FROM c)
0 0 0 0 0
drop table t1;
CREATE TABLE t1 ( start datetime default NULL);
INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00');
-CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL);
+CREATE TABLE t2 ( ctime1 timestamp NOT NULL, ctime2 timestamp NOT NULL);
INSERT INTO t2 VALUES (20021029165106,20021105164731);
CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
@@ -539,11 +567,68 @@ date_add(date,INTERVAL "1 1:1" DAY_MINUTE)
select date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) from t1;
date_add(date,INTERVAL "1 1:1:1" DAY_SECOND)
2003-01-03 01:01:01
+select date_add(date,INTERVAL "1" WEEK) from t1;
+date_add(date,INTERVAL "1" WEEK)
+2003-01-09 00:00:00
+select date_add(date,INTERVAL "1" QUARTER) from t1;
+date_add(date,INTERVAL "1" QUARTER)
+2003-04-02
+select timestampadd(MINUTE, 1, date) from t1;
+timestampadd(MINUTE, 1, date)
+2003-01-02 00:01:00
+select timestampadd(WEEK, 1, date) from t1;
+timestampadd(WEEK, 1, date)
+2003-01-09 00:00:00
+select timestampadd(SQL_TSI_SECOND, 1, date) from t1;
+timestampadd(SQL_TSI_SECOND, 1, date)
+2003-01-02 00:00:01
+select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1;
+timestampadd(SQL_TSI_FRAC_SECOND, 1, date)
+2003-01-02 00:00:00.000001
+select timestampdiff(MONTH, '2001-02-01', '2001-05-01') as a;
+a
+3
+select timestampdiff(YEAR, '2002-05-01', '2001-01-01') as a;
+a
+-1
+select timestampdiff(QUARTER, '2002-05-01', '2001-01-01') as a;
+a
+-5
+select timestampdiff(MONTH, '2000-03-28', '2000-02-29') as a;
+a
+0
+select timestampdiff(MONTH, '1991-03-28', '2000-02-29') as a;
+a
+107
+select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a;
+a
+12
+select timestampdiff(SQL_TSI_HOUR, '2001-02-01', '2001-05-01') as a;
+a
+2136
+select timestampdiff(SQL_TSI_DAY, '2001-02-01', '2001-05-01') as a;
+a
+89
+select timestampdiff(SQL_TSI_MINUTE, '2001-02-01 12:59:59', '2001-05-01 12:58:59') as a;
+a
+128159
+select timestampdiff(SQL_TSI_SECOND, '2001-02-01 12:59:59', '2001-05-01 12:58:58') as a;
+a
+7689539
+select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a;
+a
+7689538999999
+select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1,
+timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2,
+timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3,
+timestampdiff(SQL_TSI_DAY, '2000-02-01', '2000-03-01') as a4;
+a1 a2 a3 a4
+28 28 29 29
select date_add(time,INTERVAL 1 SECOND) from t1;
date_add(time,INTERVAL 1 SECOND)
NULL
Warnings:
-Warning 1264 Data truncated; out of range for column 'time' at row 1
+Warning 1264 Out of range value adjusted 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,
@@ -557,7 +642,7 @@ create table t1 select last_day('2000-02-05') as a,
from_days(to_days("960101")) as b;
describe t1;
Field Type Null Key Default Extra
-a date 0000-00-00
+a date NO 0000-00-00
b date YES NULL
select * from t1;
a b
@@ -601,7 +686,7 @@ explain extended select period_add("9602",-12),period_diff(199505,"9404"),from_d
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select sql_no_cache period_add(_latin1'9602',-(12)) AS `period_add("9602",-12)`,period_diff(199505,_latin1'9404') AS `period_diff(199505,"9404")`,from_days(to_days(_latin1'960101')) AS `from_days(to_days("960101"))`,dayofmonth(_latin1'1997-01-02') AS `dayofmonth("1997-01-02")`,month(_latin1'1997-01-02') AS `month("1997-01-02")`,monthname(_latin1'1972-03-04') AS `monthname("1972-03-04")`,dayofyear(_latin1'0000-00-00') AS `dayofyear("0000-00-00")`,hour(_latin1'1997-03-03 23:03:22') AS `HOUR("1997-03-03 23:03:22")`,minute(_latin1'23:03:22') AS `MINUTE("23:03:22")`,second(230322) AS `SECOND(230322)`,quarter(980303) AS `QUARTER(980303)`,week(_latin1'1998-03-03',0) AS `WEEK("1998-03-03")`,yearweek(_latin1'2000-01-01',1) AS `yearweek("2000-01-01",1)`,week(19950101,1) AS `week(19950101,1)`,year(_latin1'98-02-03') AS `year("98-02-03")`,(weekday(to_days(curdate())) - weekday(to_days(now()))) AS `weekday(curdate())-weekday(now())`,dayname(to_days(_latin1'1962-03-03')) AS `dayname("1962-03-03")`,unix_timestamp() AS `unix_timestamp()`,sec_to_time((time_to_sec(_latin1'0:30:47') / 6.21)) AS `sec_to_time(time_to_sec("0:30:47")/6.21)`,curtime() AS `curtime()`,utc_time() AS `utc_time()`,curdate() AS `curdate()`,utc_date() AS `utc_date()`,utc_timestamp() AS `utc_timestamp()`,date_format(_latin1'1997-01-02 03:04:05',_latin1'%M %W %D %Y %y %m %d %h %i %s %w') AS `date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w")`,from_unixtime(unix_timestamp(_latin1'1994-03-02 10:11:12')) AS `from_unixtime(unix_timestamp("1994-03-02 10:11:12"))`,(_latin1'1997-12-31 23:59:59' + interval 1 second) AS `"1997-12-31 23:59:59" + INTERVAL 1 SECOND`,(_latin1'1998-01-01 00:00:00' - interval 1 second) AS `"1998-01-01 00:00:00" - INTERVAL 1 SECOND`,(_latin1'1997-12-31' + interval 1 day) AS `INTERVAL 1 DAY + "1997-12-31"`,extract(year from _latin1'1999-01-02 10:11:12') AS `extract(YEAR FROM "1999-01-02 10:11:12")`,(_latin1'1997-12-31 23:59:59' + interval 1 second) AS `date_add("1997-12-31 23:59:59",INTERVAL 1 SECOND)`
+Note 1003 select sql_no_cache period_add(_latin1'9602',-(12)) AS `period_add("9602",-12)`,period_diff(199505,_latin1'9404') AS `period_diff(199505,"9404")`,from_days(to_days(_latin1'960101')) AS `from_days(to_days("960101"))`,dayofmonth(_latin1'1997-01-02') AS `dayofmonth("1997-01-02")`,month(_latin1'1997-01-02') AS `month("1997-01-02")`,monthname(_latin1'1972-03-04') AS `monthname("1972-03-04")`,dayofyear(_latin1'0000-00-00') AS `dayofyear("0000-00-00")`,hour(_latin1'1997-03-03 23:03:22') AS `HOUR("1997-03-03 23:03:22")`,minute(_latin1'23:03:22') AS `MINUTE("23:03:22")`,second(230322) AS `SECOND(230322)`,quarter(980303) AS `QUARTER(980303)`,week(_latin1'1998-03-03',0) AS `WEEK("1998-03-03")`,yearweek(_latin1'2000-01-01',1) AS `yearweek("2000-01-01",1)`,week(19950101,1) AS `week(19950101,1)`,year(_latin1'98-02-03') AS `year("98-02-03")`,(weekday(curdate()) - weekday(now())) AS `weekday(curdate())-weekday(now())`,dayname(_latin1'1962-03-03') AS `dayname("1962-03-03")`,unix_timestamp() AS `unix_timestamp()`,sec_to_time((time_to_sec(_latin1'0:30:47') / 6.21)) AS `sec_to_time(time_to_sec("0:30:47")/6.21)`,curtime() AS `curtime()`,utc_time() AS `utc_time()`,curdate() AS `curdate()`,utc_date() AS `utc_date()`,utc_timestamp() AS `utc_timestamp()`,date_format(_latin1'1997-01-02 03:04:05',_latin1'%M %W %D %Y %y %m %d %h %i %s %w') AS `date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w")`,from_unixtime(unix_timestamp(_latin1'1994-03-02 10:11:12')) AS `from_unixtime(unix_timestamp("1994-03-02 10:11:12"))`,(_latin1'1997-12-31 23:59:59' + interval 1 second) AS `"1997-12-31 23:59:59" + INTERVAL 1 SECOND`,(_latin1'1998-01-01 00:00:00' - interval 1 second) AS `"1998-01-01 00:00:00" - INTERVAL 1 SECOND`,(_latin1'1997-12-31' + interval 1 day) AS `INTERVAL 1 DAY + "1997-12-31"`,extract(year from _latin1'1999-01-02 10:11:12') AS `extract(YEAR FROM "1999-01-02 10:11:12")`,(_latin1'1997-12-31 23:59:59' + interval 1 second) AS `date_add("1997-12-31 23:59:59",INTERVAL 1 SECOND)`
SET @TMP=NOW();
CREATE TABLE t1 (d DATETIME);
INSERT INTO t1 VALUES (NOW());
@@ -611,6 +696,12 @@ SELECT count(*) FROM t1 WHERE d>FROM_DAYS(TO_DAYS(@TMP)) AND d<=FROM_DAYS(TO_DAY
count(*)
3
DROP TABLE t1;
+explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,
+timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select timestampdiff(WEEK,_latin1'2001-02-01',_latin1'2001-05-01') AS `a1`,timestampdiff(SECOND_FRAC,_latin1'2001-02-01 12:59:59.120000',_latin1'2001-05-01 12:58:58.119999') AS `a2`
select last_day('2005-00-00');
last_day('2005-00-00')
NULL
@@ -626,3 +717,46 @@ last_day('2005-01-00')
NULL
Warnings:
Warning 1292 Truncated incorrect datetime value: '2005-01-00'
+select time_format('100:00:00', '%H %k %h %I %l');
+time_format('100:00:00', '%H %k %h %I %l')
+100 100 04 04 4
+create table t1 (a timestamp default '2005-05-05 01:01:01',
+b timestamp default '2005-05-05 01:01:01');
+create function t_slow_sysdate() returns timestamp
+begin
+do sleep(2);
+return sysdate();
+end;
+//
+insert into t1 set a = sysdate(), b = t_slow_sysdate();//
+create trigger t_before before insert on t1
+for each row begin
+set new.b = t_slow_sysdate();
+end
+//
+insert into t1 set a = sysdate();
+select a != b from t1;
+a != b
+1
+1
+drop trigger t_before;
+drop function t_slow_sysdate;
+drop table t1;
+create table t1 (a datetime, i int, b datetime);
+insert into t1 select sysdate(), sleep(1), sysdate() from dual;
+select a != b from t1;
+a != b
+1
+drop table t1;
+create procedure t_sysdate()
+begin
+select sysdate() into @a;
+do sleep(2);
+select sysdate() into @b;
+select @a != @b;
+end;
+//
+call t_sysdate();
+@a != @b
+1
+drop procedure t_sysdate;
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index 5283ef4d889..0f95778ea75 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -8,7 +8,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`fid` int(11) NOT NULL auto_increment,
- `g` geometry NOT NULL default '',
+ `g` geometry NOT NULL,
PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`(32))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -167,7 +167,7 @@ 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 7 Using where
+1 SIMPLE t1 range g g 32 NULL 8 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)
@@ -291,7 +291,7 @@ SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`fid` int(11) NOT NULL auto_increment,
- `g` geometry NOT NULL default '',
+ `g` geometry NOT NULL,
PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`(32))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -758,7 +758,6 @@ SPATIAL KEY(g)
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(1 2, 2 3)')),(GeomFromText('LineString(1 2, 2 4)'));
drop table t1;
CREATE TABLE t1 (
-geoobjid INT NOT NULL,
line LINESTRING NOT NULL,
kind ENUM('po', 'pp', 'rr', 'dr', 'rd', 'ts', 'cl') NOT NULL DEFAULT 'po',
name VARCHAR(32),
@@ -802,7 +801,7 @@ CREATE TABLE t1 (st varchar(100));
INSERT INTO t1 VALUES ("Fake string");
CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
-ERROR HY000: Unknown error
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
drop table t1, t2;
CREATE TABLE t1 (`geometry` geometry NOT NULL default '',SPATIAL KEY `gndx` (`geometry`(32))) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 (geometry) VALUES
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index c51b07f09d6..78014137b50 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -9,35 +9,35 @@ CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMET
CREATE TABLE gis_geometry (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
SHOW FIELDS FROM gis_point;
Field Type Null Key Default Extra
-fid int(11) PRI 0
+fid int(11) NO PRI
g point YES NULL
SHOW FIELDS FROM gis_line;
Field Type Null Key Default Extra
-fid int(11) PRI 0
+fid int(11) NO PRI
g linestring YES NULL
SHOW FIELDS FROM gis_polygon;
Field Type Null Key Default Extra
-fid int(11) PRI 0
+fid int(11) NO PRI
g polygon YES NULL
SHOW FIELDS FROM gis_multi_point;
Field Type Null Key Default Extra
-fid int(11) PRI 0
+fid int(11) NO PRI
g multipoint YES NULL
SHOW FIELDS FROM gis_multi_line;
Field Type Null Key Default Extra
-fid int(11) PRI 0
+fid int(11) NO PRI
g multilinestring YES NULL
SHOW FIELDS FROM gis_multi_polygon;
Field Type Null Key Default Extra
-fid int(11) PRI 0
+fid int(11) NO PRI
g multipolygon YES NULL
SHOW FIELDS FROM gis_geometrycollection;
Field Type Null Key Default Extra
-fid int(11) PRI 0
+fid int(11) NO PRI
g geometrycollection YES NULL
SHOW FIELDS FROM gis_geometry;
Field Type Null Key Default Extra
-fid int(11) PRI 0
+fid int(11) NO PRI
g geometry YES NULL
INSERT INTO gis_point VALUES
(101, PointFromText('POINT(10 10)')),
@@ -228,7 +228,7 @@ explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelo
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21
Warnings:
-Note 1003 select dimension(test.gis_geometry.g) AS `Dimension(g)`,geometrytype(test.gis_geometry.g) AS `GeometryType(g)`,isempty(test.gis_geometry.g) AS `IsEmpty(g)`,astext(envelope(test.gis_geometry.g)) AS `AsText(Envelope(g))` from test.gis_geometry
+Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry`
SELECT fid, X(g) FROM gis_point;
fid X(g)
101 10
@@ -245,7 +245,7 @@ explain extended select X(g),Y(g) FROM gis_point;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE gis_point ALL NULL NULL NULL NULL 4
Warnings:
-Note 1003 select x(test.gis_point.g) AS `X(g)`,y(test.gis_point.g) AS `Y(g)` from test.gis_point
+Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point`
SELECT fid, AsText(StartPoint(g)) FROM gis_line;
fid AsText(StartPoint(g))
105 POINT(0 0)
@@ -280,7 +280,7 @@ explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),Num
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE gis_line ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select astext(startpoint(test.gis_line.g)) AS `AsText(StartPoint(g))`,astext(endpoint(test.gis_line.g)) AS `AsText(EndPoint(g))`,glength(test.gis_line.g) AS `GLength(g)`,numpoints(test.gis_line.g) AS `NumPoints(g)`,astext(pointn(test.gis_line.g,2)) AS `AsText(PointN(g, 2))`,isclosed(test.gis_line.g) AS `IsClosed(g)` from test.gis_line
+Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line`
SELECT fid, AsText(Centroid(g)) FROM gis_polygon;
fid AsText(Centroid(g))
108 POINT(15 15)
@@ -310,7 +310,7 @@ explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumI
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select astext(centroid(test.gis_polygon.g)) AS `AsText(Centroid(g))`,area(test.gis_polygon.g) AS `Area(g)`,astext(exteriorring(test.gis_polygon.g)) AS `AsText(ExteriorRing(g))`,numinteriorrings(test.gis_polygon.g) AS `NumInteriorRings(g)`,astext(interiorringn(test.gis_polygon.g,1)) AS `AsText(InteriorRingN(g, 1))` from test.gis_polygon
+Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon`
SELECT fid, IsClosed(g) FROM gis_multi_line;
fid IsClosed(g)
114 0
@@ -349,7 +349,7 @@ explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select test.gis_multi_point.fid AS `fid`,numgeometries(test.gis_multi_point.g) AS `NumGeometries(g)` from test.gis_multi_point
+Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point`
SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
fid AsText(GeometryN(g, 2))
111 POINT(10 10)
@@ -377,7 +377,7 @@ explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select test.gis_multi_point.fid AS `fid`,astext(geometryn(test.gis_multi_point.g,2)) AS `AsText(GeometryN(g, 2))` from test.gis_multi_point
+Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point`
SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
@@ -397,7 +397,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
1 SIMPLE g2 ALL NULL NULL NULL NULL 2
Warnings:
-Note 1003 select test.g1.fid AS `first`,test.g2.fid AS `second`,within(test.g1.g,test.g2.g) AS `w`,contains(test.g1.g,test.g2.g) AS `c`,overlaps(test.g1.g,test.g2.g) AS `o`,equals(test.g1.g,test.g2.g) AS `e`,disjoint(test.g1.g,test.g2.g) AS `d`,touches(test.g1.g,test.g2.g) AS `t`,intersects(test.g1.g,test.g2.g) AS `i`,crosses(test.g1.g,test.g2.g) AS `r` from test.gis_geometrycollection g1 join test.gis_geometrycollection g2 order by test.g1.fid,test.g2.fid
+Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid`
DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
CREATE TABLE t1 (
gp point,
@@ -430,7 +430,7 @@ mln multilinestring YES NULL
mpg multipolygon YES NULL
gc geometrycollection YES NULL
gm geometry YES NULL
-fid int(11) 0
+fid int(11) NO
DROP TABLE t1;
SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))));
AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))))
@@ -461,9 +461,9 @@ Note 1003 select issimple(multipoint(point(3,6),point(4,10))) AS `issimple(Multi
create table t1 (a geometry not null);
insert into t1 values (GeomFromText('Point(1 2)'));
insert into t1 values ('Garbage');
-ERROR HY000: Unknown error
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
insert IGNORE into t1 values ('Garbage');
-ERROR HY000: Unknown error
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
alter table t1 add spatial index(a);
drop table t1;
create table t1(a geometry not null, spatial index(a));
@@ -655,3 +655,28 @@ t1 where object_id=85984;
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
85984 MULTIPOLYGON 0 POINT(-114.87787186923 36.33101763469)
drop table t1;
+create table t1 (fl geometry);
+insert into t1 values (1);
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+insert into t1 values (1.11);
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+insert into t1 values ("qwerty");
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+insert into t1 values (pointfromtext('point(1,1)'));
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+drop table t1;
+create table t1 (s1 geometry not null,s2 char(100));
+create trigger t1_bu before update on t1 for each row set new.s1 = null;
+insert into t1 values (null,null);
+ERROR 23000: Column 's1' cannot be null
+drop table t1;
+drop procedure if exists fn3;
+create function fn3 () returns point return GeomFromText("point(1 1)");
+show create function fn3;
+Function sql_mode Create Function
+fn3 CREATE FUNCTION `fn3`() RETURNS point
+return GeomFromText("point(1 1)")
+select astext(fn3());
+astext(fn3())
+POINT(1 1)
+drop function fn3;
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index a50293752ec..14393be1cc8 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -1,4 +1,5 @@
drop table if exists t1;
+drop database if exists mysqltest;
SET NAMES binary;
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
@@ -10,8 +11,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
grant delete on mysqltest.* to mysqltest_1@localhost;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
@@ -41,15 +42,15 @@ delete from mysql.user where user='mysqltest_1';
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N 10 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N 10 20 30
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
@@ -84,7 +85,7 @@ revoke LOCK TABLES, ALTER on mysqltest.* from mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
flush privileges;
@@ -157,6 +158,10 @@ select 1;
1
1
insert into mysql.user (host, user) values ('localhost', 'test11');
+Warnings:
+Warning 1364 Field 'ssl_cipher' doesn't have a default value
+Warning 1364 Field 'x509_issuer' doesn't have a default value
+Warning 1364 Field 'x509_subject' doesn't have a default value
insert into mysql.db (host, db, user, select_priv) values
('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
alter table mysql.db order by db asc;
@@ -240,17 +245,19 @@ grant select on test.* to drop_user3@localhost;
grant select on *.* to drop_user4@localhost;
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
-ERROR HY000: Can't drop one or more of the requested users
revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
drop_user3@localhost, drop_user4@localhost;
+ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
+ERROR HY000: Operation DROP USER failed for 'drop_user1'@'localhost','drop_user2'@'localhost','drop_user3'@'localhost','drop_user4'@'localhost'
drop table t1;
grant usage on *.* to mysqltest_1@localhost identified by "password";
-grant select, update, insert on test.* to mysqltest@localhost;
+grant select, update, insert on test.* to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'
+GRANT SELECT, INSERT, UPDATE ON `test`.* TO 'mysqltest_1'@'localhost'
drop user mysqltest_1@localhost;
SET NAMES koi8r;
CREATE DATABASE ÂÄ;
@@ -274,6 +281,7 @@ Grants for ÀÚÅÒ@localhost
GRANT USAGE ON *.* TO 'ÀÚÅÒ'@'localhost'
GRANT SELECT (ËÏÌ) ON `ÂÄ`.`ÔÁÂ` TO 'ÀÚÅÒ'@'localhost'
REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost;
+DROP USER ÀÚÅÒ@localhost;
DROP DATABASE ÂÄ;
SET NAMES latin1;
USE test;
@@ -351,10 +359,10 @@ GRANT USAGE ON *.* TO 'grant_user'@'localhost'
GRANT INSERT (a, d, c, b) ON `test`.`t1` TO 'grant_user'@'localhost'
select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
Host Db User Table_name Column_name Column_priv
-localhost test grant_user t1 c Insert
localhost test grant_user t1 b Insert
-localhost test grant_user t1 a Insert
localhost test grant_user t1 d Insert
+localhost test grant_user t1 a Insert
+localhost test grant_user t1 c Insert
revoke ALL PRIVILEGES on t1 from grant_user@localhost;
show grants for grant_user@localhost;
Grants for grant_user@localhost
@@ -377,15 +385,17 @@ show grants for mysqltest_3@localhost;
Grants for mysqltest_3@localhost
GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost'
GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost'
-GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost'
GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost'
GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost'
+GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost'
update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for column 'q' in table 't1'
-update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1;
+update mysqltest_1.t2, mysqltest_2.t2 set d=20 where d=1;
ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'd' in table 't2'
+update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1;
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 't1'
update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1;
-ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for column 'c' in table 't1'
+ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for table 't1'
update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2;
ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 's' in table 't1'
update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10;
@@ -406,14 +416,14 @@ flush privileges;
use mysqltest_1;
update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600;
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
-ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for column 'a' in table 't1'
+ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for table 't1'
use mysqltest_2;
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
-ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysqltest_1'
+ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for table 't1'
update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200;
-ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysqltest_1'
+ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for table 't2'
update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200;
-ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysqltest_1'
+ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for table 't1'
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
a q b r
10 2 1 2
@@ -427,6 +437,35 @@ delete from mysql.columns_priv where user="mysqltest_3";
flush privileges;
drop database mysqltest_1;
drop database mysqltest_2;
+SHOW PRIVILEGES;
+Privilege Context Comment
+Alter Tables To alter the table
+Alter routine Functions,Procedures To alter or drop stored functions/procedures
+Create Databases,Tables,Indexes To create new databases and tables
+Create routine Functions,Procedures To use CREATE FUNCTION/PROCEDURE
+Create temporary tables Databases To use CREATE TEMPORARY TABLE
+Create view Tables To create new views
+Create user Server Admin To create new users
+Delete Tables To delete existing rows
+Drop Databases,Tables To drop databases, tables, and views
+Execute Functions,Procedures To execute stored routines
+File File access on server To read and write files on the server
+Grant option Databases,Tables,Functions,Procedures To give to other users those privileges you possess
+Index Tables To create or drop indexes
+Insert Tables To insert data into tables
+Lock tables Databases To use LOCK TABLES (together with SELECT privilege)
+Process Server Admin To view the plain text of currently executing queries
+References Databases,Tables To have references on tables
+Reload Server Admin To reload or refresh tables, logs and privileges
+Replication client Server Admin To ask where the slave or master servers are
+Replication slave Server Admin To read binary log events from the master
+Select Tables To retrieve rows from table
+Show databases Server Admin To see all databases with SHOW DATABASES
+Show view Tables To see views with SHOW CREATE VIEW
+Shutdown Server Admin To shut down the server
+Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
+Update Tables To update existing rows
+Usage Server Admin No privileges - allow connect only
create database mysqltest;
create table mysqltest.t1 (a int,b int,c int);
grant all on mysqltest.t1 to mysqltest_1@localhost;
@@ -435,6 +474,118 @@ ERROR 42000: INSERT,CREATE command denied to user 'mysqltest_1'@'localhost' for
revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
delete from mysql.user where user=_binary'mysqltest_1';
drop database mysqltest;
+CREATE USER dummy@localhost;
+CREATE DATABASE mysqltest;
+CREATE TABLE mysqltest.dummytable (dummyfield INT);
+CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable;
+GRANT ALL PRIVILEGES ON mysqltest.dummytable TO dummy@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.dummyview TO dummy@localhost;
+SHOW GRANTS FOR dummy@localhost;
+Grants for dummy@localhost
+GRANT USAGE ON *.* TO 'dummy'@'localhost'
+GRANT ALL PRIVILEGES ON `mysqltest`.`dummyview` TO 'dummy'@'localhost'
+GRANT ALL PRIVILEGES ON `mysqltest`.`dummytable` TO 'dummy'@'localhost'
+use INFORMATION_SCHEMA;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+TABLE_SCHEMA TABLE_NAME PRIVILEGES
+mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE
+mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE
+FLUSH PRIVILEGES;
+SHOW GRANTS FOR dummy@localhost;
+Grants for dummy@localhost
+GRANT USAGE ON *.* TO 'dummy'@'localhost'
+GRANT ALL PRIVILEGES ON `mysqltest`.`dummyview` TO 'dummy'@'localhost'
+GRANT ALL PRIVILEGES ON `mysqltest`.`dummytable` TO 'dummy'@'localhost'
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+TABLE_SCHEMA TABLE_NAME PRIVILEGES
+mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE
+mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE
+SHOW FIELDS FROM mysql.tables_priv;
+Field Type Null Key Default Extra
+Host char(60) NO PRI
+Db char(64) NO PRI
+User char(16) NO PRI
+Table_name char(64) NO PRI
+Grantor char(77) NO MUL
+Timestamp timestamp YES CURRENT_TIMESTAMP
+Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') NO
+Column_priv set('Select','Insert','Update','References') NO
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
+DROP USER dummy@localhost;
+DROP DATABASE mysqltest;
+CREATE USER dummy@localhost;
+CREATE DATABASE mysqltest;
+CREATE TABLE mysqltest.dummytable (dummyfield INT);
+CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable;
+GRANT CREATE VIEW ON mysqltest.dummytable TO dummy@localhost;
+GRANT CREATE VIEW ON mysqltest.dummyview TO dummy@localhost;
+SHOW GRANTS FOR dummy@localhost;
+Grants for dummy@localhost
+GRANT USAGE ON *.* TO 'dummy'@'localhost'
+GRANT CREATE VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost'
+GRANT CREATE VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost'
+use INFORMATION_SCHEMA;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+TABLE_SCHEMA TABLE_NAME PRIVILEGES
+mysqltest dummytable CREATE VIEW
+mysqltest dummyview CREATE VIEW
+FLUSH PRIVILEGES;
+SHOW GRANTS FOR dummy@localhost;
+Grants for dummy@localhost
+GRANT USAGE ON *.* TO 'dummy'@'localhost'
+GRANT CREATE VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost'
+GRANT CREATE VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost'
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+TABLE_SCHEMA TABLE_NAME PRIVILEGES
+mysqltest dummytable CREATE VIEW
+mysqltest dummyview CREATE VIEW
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
+DROP USER dummy@localhost;
+DROP DATABASE mysqltest;
+CREATE USER dummy@localhost;
+CREATE DATABASE mysqltest;
+CREATE TABLE mysqltest.dummytable (dummyfield INT);
+CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable;
+GRANT SHOW VIEW ON mysqltest.dummytable TO dummy@localhost;
+GRANT SHOW VIEW ON mysqltest.dummyview TO dummy@localhost;
+SHOW GRANTS FOR dummy@localhost;
+Grants for dummy@localhost
+GRANT USAGE ON *.* TO 'dummy'@'localhost'
+GRANT SHOW VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost'
+GRANT SHOW VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost'
+use INFORMATION_SCHEMA;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+TABLE_SCHEMA TABLE_NAME PRIVILEGES
+mysqltest dummytable SHOW VIEW
+mysqltest dummyview SHOW VIEW
+FLUSH PRIVILEGES;
+SHOW GRANTS FOR dummy@localhost;
+Grants for dummy@localhost
+GRANT USAGE ON *.* TO 'dummy'@'localhost'
+GRANT SHOW VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost'
+GRANT SHOW VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost'
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+TABLE_SCHEMA TABLE_NAME PRIVILEGES
+mysqltest dummytable SHOW VIEW
+mysqltest dummyview SHOW VIEW
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
+DROP USER dummy@localhost;
+DROP DATABASE mysqltest;
use mysql;
insert into tables_priv values ('','test_db','mysqltest_1','test_table','test_grantor',CURRENT_TIMESTAMP,'Select','Select');
flush privileges;
@@ -442,4 +593,4 @@ delete from tables_priv where host = '' and user = 'mysqltest_1';
flush privileges;
set @user123="non-existent";
select * from mysql.db where user=@user123;
-Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv
+Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 6b6bb697306..ca375ef5057 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -6,16 +6,42 @@ delete from mysql.db where user like 'mysqltest\_%';
delete from mysql.tables_priv where user like 'mysqltest\_%';
delete from mysql.columns_priv where user like 'mysqltest\_%';
flush privileges;
+grant all privileges on `my\_1`.* to mysqltest_1@localhost with grant option;
+grant create user on *.* to mysqltest_1@localhost;
+create user mysqltest_2@localhost;
+grant select on `my\_1`.* to mysqltest_2@localhost;
+grant select on `my\_1`.* to mysqltest_2@localhost identified by 'pass';
+ERROR 42000: You must have privileges to update tables in the mysql database to be able to change passwords for others
+grant update on mysql.* to mysqltest_1@localhost;
+grant select on `my\_1`.* to mysqltest_2@localhost identified by 'pass';
+grant select on `my\_1`.* to mysqltest_3@localhost;
+grant insert on mysql.* to mysqltest_1@localhost;
+grant select on `my\_1`.* to mysqltest_3@localhost;
+grant select on `my\_1`.* to mysqltest_4@localhost identified by 'pass';
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
grant all privileges on `my\_%`.* to mysqltest_1@localhost with grant option;
+grant create user on *.* to mysqltest_1@localhost;
select current_user();
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_%'
+set @@sql_mode='NO_AUTO_CREATE_USER';
+select @@sql_mode;
+@@sql_mode
+NO_AUTO_CREATE_USER
+grant select on `my\_1`.* to mysqltest_4@localhost with grant option;
+ERROR 42000: Can't find any matching row in the user table
+grant select on `my\_1`.* to mysqltest_4@localhost identified by 'mypass'
+with grant option;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
-GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT CREATE USER ON *.* TO 'mysqltest_1'@'localhost'
GRANT ALL PRIVILEGES ON `my\_%`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
show grants for mysqltest_2@localhost;
Grants for mysqltest_2@localhost
@@ -33,6 +59,7 @@ current_user()
mysqltest_1@localhost
show databases;
Database
+information_schema
mysqltest_1
test
grant all privileges on `mysqltest_1`.* to mysqltest_1@localhost with grant option;
@@ -56,9 +83,9 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, INSERT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
insert into t1 values (1, 'I can''t change it!');
update t1 set data='I can change it!' where id = 1;
-ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest'
+ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for table 't1'
insert into t1 values (1, 'XXX') on duplicate key update data= 'I can change it!';
-ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest'
+ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for table 't1'
select * from t1;
id data
1 I can't change it!
@@ -80,6 +107,169 @@ delete from mysql.columns_priv where user like 'mysqltest\_%';
flush privileges;
drop database mysqltest;
use test;
+set sql_mode='maxdb';
+drop table if exists t1, t2;
+create table t1(c1 int);
+create table t2(c1 int, c2 int);
+create user 'mysqltest_1';
+create user 'mysqltest_1';
+ERROR HY000: Operation CREATE USER failed for 'mysqltest_1'@'%'
+create user 'mysqltest_2' identified by 'Mysqltest-2';
+create user 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff';
+grant select on *.* to 'mysqltest_2';
+grant insert on test.* to 'mysqltest_2';
+grant update on test.t1 to 'mysqltest_2';
+grant update (c2) on test.t2 to 'mysqltest_2';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+host user password
+% mysqltest_1
+% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1
+% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+host db user
+% test mysqltest_2
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+host db user table_name
+% test mysqltest_2 t1
+% test mysqltest_2 t2
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+host db user table_name column_name
+% test mysqltest_2 t2 c2
+show grants for 'mysqltest_1';
+Grants for mysqltest_1@%
+GRANT USAGE ON *.* TO 'mysqltest_1'@'%'
+show grants for 'mysqltest_2';
+Grants for mysqltest_2@%
+GRANT SELECT ON *.* TO 'mysqltest_2'@'%' IDENTIFIED BY PASSWORD '*BD447CBA355AF58578D3AE33BA2E2CD388BA08D1'
+GRANT INSERT ON "test".* TO 'mysqltest_2'@'%'
+GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_2'@'%'
+GRANT UPDATE ON "test"."t1" TO 'mysqltest_2'@'%'
+drop user 'mysqltest_1';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+host user password
+% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1
+% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+host db user
+% test mysqltest_2
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+host db user table_name
+% test mysqltest_2 t1
+% test mysqltest_2 t2
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+host db user table_name column_name
+% test mysqltest_2 t2 c2
+show grants for 'mysqltest_1';
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
+rename user 'mysqltest_2' to 'mysqltest_1';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+host user password
+% mysqltest_1 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1
+% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+host db user
+% test mysqltest_1
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+host db user table_name
+% test mysqltest_1 t1
+% test mysqltest_1 t2
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+host db user table_name column_name
+% test mysqltest_1 t2 c2
+show grants for 'mysqltest_1';
+Grants for mysqltest_1@%
+GRANT SELECT ON *.* TO 'mysqltest_1'@'%' IDENTIFIED BY PASSWORD '*BD447CBA355AF58578D3AE33BA2E2CD388BA08D1'
+GRANT INSERT ON "test".* TO 'mysqltest_1'@'%'
+GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_1'@'%'
+GRANT UPDATE ON "test"."t1" TO 'mysqltest_1'@'%'
+drop user 'mysqltest_1', 'mysqltest_3';
+drop user 'mysqltest_1';
+ERROR HY000: Operation DROP USER failed for 'mysqltest_1'@'%'
+drop table t1, t2;
+insert into mysql.db set user='mysqltest_1', db='%', host='%';
+flush privileges;
+show grants for 'mysqltest_1';
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
+revoke all privileges, grant option from 'mysqltest_1';
+ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
+drop user 'mysqltest_1';
+select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user;
+host db user
+insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1';
+flush privileges;
+show grants for 'mysqltest_1';
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
+drop user 'mysqltest_1';
+select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name;
+host db user table_name
+insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1';
+flush privileges;
+show grants for 'mysqltest_1';
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
+drop user 'mysqltest_1';
+select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name;
+host db user table_name column_name
+create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+create user 'mysqltest_1', 'mysqltest_2' identified by 'Mysqltest-2', 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff';
+rename user 'mysqltest_1' to 'mysqltest_1a', 'mysqltest_2' TO 'mysqltest_2a', 'mysqltest_3' TO 'mysqltest_3a';
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+ERROR HY000: Operation DROP USER failed for 'mysqltest_1'@'%','mysqltest_2'@'%','mysqltest_3'@'%'
+drop user 'mysqltest_1a', 'mysqltest_2a', 'mysqltest_3a';
+create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+create user 'mysqltest_1a', 'mysqltest_2', 'mysqltest_3a';
+ERROR HY000: Operation CREATE USER failed for 'mysqltest_2'@'%'
+rename user 'mysqltest_1a' to 'mysqltest_1b', 'mysqltest_2a' TO 'mysqltest_2b', 'mysqltest_3a' TO 'mysqltest_3b';
+ERROR HY000: Operation RENAME USER failed for 'mysqltest_2a'@'%'
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+drop user 'mysqltest_1b', 'mysqltest_2b', 'mysqltest_3b';
+ERROR HY000: Operation DROP USER failed for 'mysqltest_2b'@'%'
+create user 'mysqltest_2' identified by 'Mysqltest-2';
+drop user 'mysqltest_2' identified by 'Mysqltest-2';
+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 'identified by 'Mysqltest-2'' at line 1
+create user '%@b'@'b';
+show grants for '%@b'@'b';
+Grants for %@b@b
+GRANT USAGE ON *.* TO '%@b'@'b'
+grant select on mysql.* to '%@b'@'b';
+show grants for '%@b'@'b';
+Grants for %@b@b
+GRANT USAGE ON *.* TO '%@b'@'b'
+GRANT SELECT ON "mysql".* TO '%@b'@'b'
+rename user '%@b'@'b' to '%@a'@'a';
+show grants for '%@b'@'b';
+ERROR 42000: There is no such grant defined for user '%@b' on host 'b'
+show grants for '%@a'@'a';
+Grants for %@a@a
+GRANT USAGE ON *.* TO '%@a'@'a'
+GRANT SELECT ON "mysql".* TO '%@a'@'a'
+drop user '%@a'@'a';
+create user mysqltest_2@localhost;
+grant create user on *.* to mysqltest_2@localhost;
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+ERROR 42000: SELECT command denied to user 'mysqltest_2'@'localhost' for table 'user'
+create user mysqltest_A@'%';
+rename user mysqltest_A@'%' to mysqltest_B@'%';
+drop user mysqltest_B@'%';
+drop user mysqltest_2@localhost;
+create user mysqltest_3@localhost;
+grant INSERT,DELETE,UPDATE on mysql.* to mysqltest_3@localhost;
+show grants;
+Grants for mysqltest_3@localhost
+GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost'
+GRANT INSERT, UPDATE, DELETE ON `mysql`.* TO 'mysqltest_3'@'localhost'
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 'user'
+insert into mysql.user set host='%', user='mysqltest_B';
+Warnings:
+Warning 1364 Field 'ssl_cipher' doesn't have a default value
+Warning 1364 Field 'x509_issuer' doesn't have a default value
+Warning 1364 Field 'x509_subject' doesn't have a default value
+create user mysqltest_A@'%';
+rename user mysqltest_B@'%' to mysqltest_C@'%';
+drop user mysqltest_C@'%';
+drop user mysqltest_3@localhost;
+set @@sql_mode='';
create database mysqltest_1;
create table mysqltest_1.t1 (i int);
insert into mysqltest_1.t1 values (1),(2),(3);
diff --git a/mysql-test/r/grant3.result b/mysql-test/r/grant3.result
new file mode 100644
index 00000000000..6193c4fd49d
--- /dev/null
+++ b/mysql-test/r/grant3.result
@@ -0,0 +1,18 @@
+SET NAMES binary;
+drop table if exists t1;
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
+create user mysqltest_1@localhost;
+grant create user on *.* to mysqltest_1@localhost;
+grant select on `my\_1`.* to mysqltest_1@localhost with grant option;
+grant select on `my\_1`.* to mysqltest_2@localhost;
+ERROR 42000: You are not allowed to create a user with GRANT
+create user mysqltest_2@localhost;
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result
index 2c6840d77d0..925a5918c1b 100644
--- a/mysql-test/r/grant_cache.result
+++ b/mysql-test/r/grant_cache.result
@@ -60,7 +60,7 @@ Variable_name Value
Qcache_hits 0
show status like "Qcache_not_cached";
Variable_name Value
-Qcache_not_cached 0
+Qcache_not_cached 5
select "user1";
user1
user1
@@ -72,7 +72,7 @@ Variable_name Value
Qcache_hits 0
show status like "Qcache_not_cached";
Variable_name Value
-Qcache_not_cached 1
+Qcache_not_cached 9
select * from t1;
a b c
1 1 1
@@ -85,7 +85,7 @@ Variable_name Value
Qcache_hits 1
show status like "Qcache_not_cached";
Variable_name Value
-Qcache_not_cached 1
+Qcache_not_cached 12
select a from t1 ;
a
1
@@ -98,7 +98,7 @@ Variable_name Value
Qcache_hits 2
show status like "Qcache_not_cached";
Variable_name Value
-Qcache_not_cached 1
+Qcache_not_cached 15
select c from t1;
c
1
@@ -111,7 +111,7 @@ Variable_name Value
Qcache_hits 3
show status like "Qcache_not_cached";
Variable_name Value
-Qcache_not_cached 1
+Qcache_not_cached 18
show grants for current_user();
Grants for @localhost
GRANT USAGE ON *.* TO ''@'localhost'
@@ -144,7 +144,7 @@ Variable_name Value
Qcache_hits 7
show status like "Qcache_not_cached";
Variable_name Value
-Qcache_not_cached 2
+Qcache_not_cached 22
select "user3";
user3
user3
@@ -168,7 +168,7 @@ Variable_name Value
Qcache_hits 7
show status like "Qcache_not_cached";
Variable_name Value
-Qcache_not_cached 7
+Qcache_not_cached 30
select "user4";
user4
user4
@@ -198,7 +198,7 @@ Variable_name Value
Qcache_hits 8
show status like "Qcache_not_cached";
Variable_name Value
-Qcache_not_cached 8
+Qcache_not_cached 34
set names binary;
delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
diff --git a/mysql-test/r/greedy_optimizer.result b/mysql-test/r/greedy_optimizer.result
new file mode 100644
index 00000000000..1da49fbedb0
--- /dev/null
+++ b/mysql-test/r/greedy_optimizer.result
@@ -0,0 +1,657 @@
+drop table if exists t1,t2,t3,t4,t5,t6,t7;
+create table t1 (
+c11 integer,c12 integer,c13 integer,c14 integer,c15 integer,c16 integer,
+primary key (c11)
+);
+create table t2 (
+c21 integer,c22 integer,c23 integer,c24 integer,c25 integer,c26 integer
+);
+create table t3 (
+c31 integer,c32 integer,c33 integer,c34 integer,c35 integer,c36 integer,
+primary key (c31)
+);
+create table t4 (
+c41 integer,c42 integer,c43 integer,c44 integer,c45 integer,c46 integer
+);
+create table t5 (
+c51 integer,c52 integer,c53 integer,c54 integer,c55 integer,c56 integer,
+primary key (c51)
+);
+create table t6 (
+c61 integer,c62 integer,c63 integer,c64 integer,c65 integer,c66 integer
+);
+create table t7 (
+c71 integer,c72 integer,c73 integer,c74 integer,c75 integer,c76 integer,
+primary key (c71)
+);
+insert into t1 values (1,2,3,4,5,6);
+insert into t1 values (2,2,3,4,5,6);
+insert into t1 values (3,2,3,4,5,6);
+insert into t2 values (1,2,3,4,5,6);
+insert into t2 values (2,2,3,4,5,6);
+insert into t2 values (3,2,3,4,5,6);
+insert into t2 values (4,2,3,4,5,6);
+insert into t2 values (5,2,3,4,5,6);
+insert into t2 values (6,2,3,4,5,6);
+insert into t3 values (1,2,3,4,5,6);
+insert into t3 values (2,2,3,4,5,6);
+insert into t3 values (3,2,3,4,5,6);
+insert into t3 values (4,2,3,4,5,6);
+insert into t3 values (5,2,3,4,5,6);
+insert into t3 values (6,2,3,4,5,6);
+insert into t3 values (7,2,3,4,5,6);
+insert into t3 values (8,2,3,4,5,6);
+insert into t3 values (9,2,3,4,5,6);
+insert into t4 values (1,2,3,4,5,6);
+insert into t4 values (2,2,3,4,5,6);
+insert into t4 values (3,2,3,4,5,6);
+insert into t4 values (4,2,3,4,5,6);
+insert into t4 values (5,2,3,4,5,6);
+insert into t4 values (6,2,3,4,5,6);
+insert into t4 values (7,2,3,4,5,6);
+insert into t4 values (8,2,3,4,5,6);
+insert into t4 values (9,2,3,4,5,6);
+insert into t4 values (10,2,3,4,5,6);
+insert into t4 values (11,2,3,4,5,6);
+insert into t4 values (12,2,3,4,5,6);
+insert into t5 values (1,2,3,4,5,6);
+insert into t5 values (2,2,3,4,5,6);
+insert into t5 values (3,2,3,4,5,6);
+insert into t5 values (4,2,3,4,5,6);
+insert into t5 values (5,2,3,4,5,6);
+insert into t5 values (6,2,3,4,5,6);
+insert into t5 values (7,2,3,4,5,6);
+insert into t5 values (8,2,3,4,5,6);
+insert into t5 values (9,2,3,4,5,6);
+insert into t5 values (10,2,3,4,5,6);
+insert into t5 values (11,2,3,4,5,6);
+insert into t5 values (12,2,3,4,5,6);
+insert into t5 values (13,2,3,4,5,6);
+insert into t5 values (14,2,3,4,5,6);
+insert into t5 values (15,2,3,4,5,6);
+insert into t6 values (1,2,3,4,5,6);
+insert into t6 values (2,2,3,4,5,6);
+insert into t6 values (3,2,3,4,5,6);
+insert into t6 values (4,2,3,4,5,6);
+insert into t6 values (5,2,3,4,5,6);
+insert into t6 values (6,2,3,4,5,6);
+insert into t6 values (7,2,3,4,5,6);
+insert into t6 values (8,2,3,4,5,6);
+insert into t6 values (9,2,3,4,5,6);
+insert into t6 values (10,2,3,4,5,6);
+insert into t6 values (11,2,3,4,5,6);
+insert into t6 values (12,2,3,4,5,6);
+insert into t6 values (13,2,3,4,5,6);
+insert into t6 values (14,2,3,4,5,6);
+insert into t6 values (15,2,3,4,5,6);
+insert into t6 values (16,2,3,4,5,6);
+insert into t6 values (17,2,3,4,5,6);
+insert into t6 values (18,2,3,4,5,6);
+insert into t7 values (1,2,3,4,5,6);
+insert into t7 values (2,2,3,4,5,6);
+insert into t7 values (3,2,3,4,5,6);
+insert into t7 values (4,2,3,4,5,6);
+insert into t7 values (5,2,3,4,5,6);
+insert into t7 values (6,2,3,4,5,6);
+insert into t7 values (7,2,3,4,5,6);
+insert into t7 values (8,2,3,4,5,6);
+insert into t7 values (9,2,3,4,5,6);
+insert into t7 values (10,2,3,4,5,6);
+insert into t7 values (11,2,3,4,5,6);
+insert into t7 values (12,2,3,4,5,6);
+insert into t7 values (13,2,3,4,5,6);
+insert into t7 values (14,2,3,4,5,6);
+insert into t7 values (15,2,3,4,5,6);
+insert into t7 values (16,2,3,4,5,6);
+insert into t7 values (17,2,3,4,5,6);
+insert into t7 values (18,2,3,4,5,6);
+insert into t7 values (19,2,3,4,5,6);
+insert into t7 values (20,2,3,4,5,6);
+insert into t7 values (21,2,3,4,5,6);
+select @@optimizer_search_depth;
+@@optimizer_search_depth
+62
+select @@optimizer_prune_level;
+@@optimizer_prune_level
+1
+set optimizer_search_depth=63;
+select @@optimizer_search_depth;
+@@optimizer_search_depth
+63
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+set optimizer_prune_level=0;
+select @@optimizer_prune_level;
+@@optimizer_prune_level
+0
+set optimizer_search_depth=0;
+select @@optimizer_search_depth;
+@@optimizer_search_depth
+0
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 274.418727
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 274.418727
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 274.418727
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 274.418727
+set optimizer_search_depth=1;
+select @@optimizer_search_depth;
+@@optimizer_search_depth
+1
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+set optimizer_search_depth=62;
+select @@optimizer_search_depth;
+@@optimizer_search_depth
+62
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 274.418727
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 274.418727
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 274.418727
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 274.418727
+set optimizer_prune_level=1;
+select @@optimizer_prune_level;
+@@optimizer_prune_level
+1
+set optimizer_search_depth=0;
+select @@optimizer_search_depth;
+@@optimizer_search_depth
+0
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+set optimizer_search_depth=1;
+select @@optimizer_search_depth;
+@@optimizer_search_depth
+1
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+set optimizer_search_depth=62;
+select @@optimizer_search_depth;
+@@optimizer_search_depth
+62
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 821.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where
+1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where
+show status like 'Last_query_cost';
+Variable_name Value
+Last_query_cost 794.837037
+drop table t1,t2,t3,t4,t5,t6,t7;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 4ad28091164..7bc886022cc 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -117,7 +117,7 @@ bug_file_loc text,
bug_severity enum('blocker','critical','major','normal','minor','trivial','enhancement') DEFAULT 'blocker' NOT NULL,
bug_status enum('','NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED') DEFAULT 'NEW' NOT NULL,
creation_ts datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
-delta_ts timestamp(14),
+delta_ts timestamp,
short_desc mediumtext,
long_desc mediumtext,
op_sys enum('All','Windows 3.1','Windows 95','Windows 98','Windows NT','Windows 2000','Linux','other') DEFAULT 'All' NOT NULL,
@@ -288,7 +288,7 @@ explain extended select sql_big_result spid,sum(userid) from t1 group by spid de
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using filesort
Warnings:
-Note 1003 select sql_big_result test.t1.spID AS `spid`,sum(test.t1.userID) AS `sum(userid)` from test.t1 group by test.t1.spID desc
+Note 1003 select sql_big_result `test`.`t1`.`spID` AS `spid`,sum(`test`.`t1`.`userID`) AS `sum(userid)` from `test`.`t1` group by `test`.`t1`.`spID` desc
explain select sql_big_result spid,sum(userid) from t1 group by spid desc order by null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using filesort
@@ -440,12 +440,12 @@ create table t2 (user_id integer not null, date date);
insert into t2 values (1, '2002-06-09'),(2, '2002-06-09'),(1, '2002-06-09'),(3, '2002-06-09'),(4, '2002-06-09'),(4, '2002-06-09');
select u.gender as gender, count(distinct u.id) as dist_count, (count(distinct u.id)/5*100) as percentage from t1 u, t2 l where l.user_id = u.id group by u.gender;
gender dist_count percentage
-F 3 60.00
-M 1 20.00
+F 3 60.0000
+M 1 20.0000
select u.gender as gender, count(distinct u.id) as dist_count, (count(distinct u.id)/5*100) as percentage from t1 u, t2 l where l.user_id = u.id group by u.gender order by percentage;
gender dist_count percentage
-M 1 20.00
-F 3 60.00
+M 1 20.0000
+F 3 60.0000
drop table t1,t2;
CREATE TABLE t1 (ID1 int, ID2 int, ID int NOT NULL AUTO_INCREMENT,PRIMARY KEY(ID
));
@@ -696,7 +696,7 @@ from t1 x3, t1 x4, t1 C, t1 D where x3.a < 3 and x4.a < 4 and D.a < 4;
delete from t2 where a = 2 and b = 'val-2' order by a,b,c,d limit 30;
explain select c from t2 where a = 2 and b = 'val-2' group by c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref PRIMARY,a PRIMARY 400 const,const 6 Using where
+1 SIMPLE t2 ref PRIMARY,a PRIMARY 402 const,const 6 Using where
select c from t2 where a = 2 and b = 'val-2' group by c;
c
val-74
@@ -745,18 +745,12 @@ CREATE TABLE t1 (id varchar(20) NOT NULL);
INSERT INTO t1 VALUES ('trans1'), ('trans2');
CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL);
INSERT INTO t2 VALUES ('trans1', 'a problem');
-SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS err_comment
-FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY err_comment;
-COUNT(DISTINCT(t1.id)) err_comment
+SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment
+FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment;
+COUNT(DISTINCT(t1.id)) comment
1 NULL
1 a problem
DROP TABLE t1, t2;
-CREATE TABLE t1 (n int);
-INSERT INTO t1 VALUES (1);
-SELECT n+1 AS n FROM t1 GROUP BY n;
-n
-2
-DROP TABLE t1;
create table t1 (f1 date);
insert into t1 values('2005-06-06');
insert into t1 values('2005-06-06');
@@ -764,6 +758,14 @@ select date(left(f1+0,8)) from t1 group by 1;
date(left(f1+0,8))
2005-06-06
drop table t1;
+CREATE TABLE t1 (n int);
+INSERT INTO t1 VALUES (1);
+SELECT n+1 AS n FROM t1 GROUP BY n;
+n
+2
+Warnings:
+Warning 1052 Column 'n' in group statement is ambiguous
+DROP TABLE t1;
create table t1(f1 varchar(5) key);
insert into t1 values (1),(2);
select sql_buffer_result max(f1) is null from t1;
@@ -773,3 +775,24 @@ select sql_buffer_result max(f1)+1 from t1;
max(f1)+1
3
drop table t1;
+create table t1 (c1 char(3), c2 char(3));
+create table t2 (c3 char(3), c4 char(3));
+insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2');
+insert into t2 values ('aaa', 'bb1'), ('aaa', 'bb2');
+select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4
+group by c2;
+c2
+aaa
+aaa
+Warnings:
+Warning 1052 Column 'c2' in group statement is ambiguous
+show warnings;
+Level Code Message
+Warning 1052 Column 'c2' in group statement is ambiguous
+select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4
+group by t1.c1;
+c2
+aaa
+show warnings;
+Level Code Message
+drop table t1, t2;
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
new file mode 100644
index 00000000000..e26f32e49e5
--- /dev/null
+++ b/mysql-test/r/group_min_max.result
@@ -0,0 +1,2010 @@
+drop table if exists t1;
+create table t1 (
+a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' '
+);
+insert into t1 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'),
+('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'),
+('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'),
+('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'),
+('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4'),
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'),
+('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'),
+('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'),
+('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'),
+('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4');
+create index idx_t1_0 on t1 (a1);
+create index idx_t1_1 on t1 (a1,a2,b,c);
+create index idx_t1_2 on t1 (a1,a2,b);
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+drop table if exists t2;
+create table t2 (
+a1 char(64), a2 char(64) not null, b char(16), c char(16), d char(16), dummy char(64) default ' '
+);
+insert into t2 select * from t1;
+insert into t2 (a1, a2, b, c, d) values
+('a','a',NULL,'a777','xyz'),('a','a',NULL,'a888','xyz'),('a','a',NULL,'a999','xyz'),
+('a','a','a',NULL,'xyz'),
+('a','a','b',NULL,'xyz'),
+('a','b','a',NULL,'xyz'),
+('c','a',NULL,'c777','xyz'),('c','a',NULL,'c888','xyz'),('c','a',NULL,'c999','xyz'),
+('d','b','b',NULL,'xyz'),
+('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),
+('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),
+('a','a',NULL,'a777','xyz'),('a','a',NULL,'a888','xyz'),('a','a',NULL,'a999','xyz'),
+('a','a','a',NULL,'xyz'),
+('a','a','b',NULL,'xyz'),
+('a','b','a',NULL,'xyz'),
+('c','a',NULL,'c777','xyz'),('c','a',NULL,'c888','xyz'),('c','a',NULL,'c999','xyz'),
+('d','b','b',NULL,'xyz'),
+('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),
+('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz');
+create index idx_t2_0 on t2 (a1);
+create index idx_t2_1 on t2 (a1,a2,b,c);
+create index idx_t2_2 on t2 (a1,a2,b);
+analyze table t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status Table is already up to date
+drop table if exists t3;
+create table t3 (
+a1 char(1), a2 char(1), b char(1), c char(4) not null, d char(3), dummy char(1) default ' '
+);
+insert into t3 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4');
+insert into t3 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4');
+insert into t3 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4');
+insert into t3 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4');
+create index idx_t3_0 on t3 (a1);
+create index idx_t3_1 on t3 (a1,a2,b,c);
+create index idx_t3_2 on t3 (a1,a2,b);
+analyze table t3;
+Table Op Msg_type Msg_text
+test.t3 analyze status Table is already up to date
+explain select a1, min(a2) from t1 group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using index for group-by
+explain select a1, max(a2) from t1 group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 65 NULL 5 Using index for group-by
+explain select a1, min(a2), max(a2) from t1 group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using index for group-by
+explain select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
+explain select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
+explain select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 # NULL # Using index for group-by
+explain select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using index for group-by
+explain select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
+explain select min(a2) from t1 group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using index for group-by
+explain select a2, min(c), max(c) from t1 group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
+select a1, min(a2) from t1 group by a1;
+a1 min(a2)
+a a
+b a
+c a
+d a
+select a1, max(a2) from t1 group by a1;
+a1 max(a2)
+a b
+b b
+c b
+d b
+select a1, min(a2), max(a2) from t1 group by a1;
+a1 min(a2) max(a2)
+a a b
+b a b
+c a b
+d a b
+select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a a111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b;
+a1 a2 b max(c) min(c)
+a a a d111 a111
+a a b h112 e112
+a b a l121 i121
+a b b p122 m122
+b a a d211 a211
+b a b h212 e212
+b b a l221 i221
+b b b p222 m222
+c a a d311 a311
+c a b h312 e312
+c b a l321 i321
+c b b p322 m322
+d a a d411 a411
+d a b h412 e412
+d b a l421 i421
+d b b p422 m422
+select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b;
+a1 a2 b max(c) min(c)
+a a NULL a999 a777
+a a a d111 a111
+a a b h112 e112
+a b a l121 i121
+a b b p122 m122
+b a a d211 a211
+b a b h212 e212
+b b a l221 i221
+b b b p222 m222
+c a NULL c999 c777
+c a a d311 a311
+c a b h312 e312
+c b a l321 i321
+c b b p322 m322
+d a a d411 a411
+d a b h412 e412
+d b a l421 i421
+d b b p422 m422
+e a a NULL NULL
+e a b NULL NULL
+select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1;
+min(a2) a1 max(a2) min(a2) a1
+a a b a a
+a b b a b
+a c b a c
+a d b a d
+select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b;
+a1 b min(c) a1 max(c) b a2 max(c) max(c)
+a a a111 a d111 a a d111 d111
+a b e112 a h112 b a h112 h112
+a a i121 a l121 a b l121 l121
+a b m122 a p122 b b p122 p122
+b a a211 b d211 a a d211 d211
+b b e212 b h212 b a h212 h212
+b a i221 b l221 a b l221 l221
+b b m222 b p222 b b p222 p222
+c a a311 c d311 a a d311 d311
+c b e312 c h312 b a h312 h312
+c a i321 c l321 a b l321 l321
+c b m322 c p322 b b p322 p322
+d a a411 d d411 a a d411 d411
+d b e412 d h412 b a h412 h412
+d a i421 d l421 a b l421 l421
+d b m422 d p422 b b p422 p422
+select min(a2) from t1 group by a1;
+min(a2)
+a
+a
+a
+a
+select a2, min(c), max(c) from t1 group by a1,a2,b;
+a2 min(c) max(c)
+a a111 d111
+a e112 h112
+b i121 l121
+b m122 p122
+a a211 d211
+a e212 h212
+b i221 l221
+b m222 p222
+a a311 d311
+a e312 h312
+b i321 l321
+b m322 p322
+a a411 d411
+a e412 h412
+b i421 l421
+b m422 p422
+explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where a1 < 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a a111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
+a1 a2 b min(c) max(c)
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+a1 a2 b max(c)
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+a1 max(c)
+a d111
+a h112
+a l121
+a p122
+c d311
+c h312
+c l321
+c p322
+d d411
+d h412
+d l421
+d p422
+select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a a111 d111
+a a b e112 h112
+b a a a211 d211
+b a b e212 h212
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+a1 a2 b max(c)
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+a1 a2 b min(c) max(c)
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+a1 a2 b max(c)
+a b a l121
+a b b p122
+b b a l221
+b b b p222
+c b a l321
+c b b p322
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a b a i121 l121
+a b b m122 p122
+b b a i221 l221
+b b b m222 p222
+c b a i321 l321
+c b b m322 p322
+d b a i421 l421
+d b b m422 p422
+select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
+a1 min(c) max(c)
+b a211 d211
+b e212 h212
+b i221 l221
+b m222 p222
+c a311 d311
+c e312 h312
+c i321 l321
+c m322 p322
+d a411 d411
+d e412 h412
+d i421 l421
+d m422 p422
+select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;
+a1 max(c)
+a d111
+a h112
+a l121
+a p122
+b d211
+b h212
+b l221
+b p222
+d d411
+d h412
+d l421
+d p422
+select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;
+a1 a2 b max(c)
+a a NULL a999
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+c a NULL c999
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+select a1,a2,b,min(c),max(c) from t2 where a1 < 'd' group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a NULL a777 a999
+a a a a111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a NULL c777 c999
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+select a1,a2,b,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
+a1 a2 b min(c) max(c)
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a NULL c777 c999
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+e a a NULL NULL
+e a b NULL NULL
+select a1,a2,b, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+a1 a2 b max(c)
+a a NULL a999
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+c a NULL c999
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+e a a NULL
+e a b NULL
+select a1, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+a1 max(c)
+a a999
+a d111
+a h112
+a l121
+a p122
+c c999
+c d311
+c h312
+c l321
+c p322
+d d411
+d h412
+d l421
+d p422
+e NULL
+e NULL
+select a1,a2,b,min(c),max(c) from t2 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a NULL a777 a999
+a a a a111 d111
+a a b e112 h112
+b a a a211 d211
+b a b e212 h212
+c a NULL c777 c999
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+e a a NULL NULL
+e a b NULL NULL
+select a1,a2,b, max(c) from t2 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+a1 a2 b max(c)
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t2 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+a1 a2 b min(c) max(c)
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+a1 a2 b max(c)
+a b a l121
+a b b p122
+b b a l221
+b b b p222
+c b a l321
+c b b p322
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a b a i121 l121
+a b b m122 p122
+b b a i221 l221
+b b b m222 p222
+c b a i321 l321
+c b b m322 p322
+d b a i421 l421
+d b b m422 p422
+select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
+a1 min(c) max(c)
+b a211 d211
+b e212 h212
+b i221 l221
+b m222 p222
+c c777 c999
+c a311 d311
+c e312 h312
+c i321 l321
+c m322 p322
+d a411 d411
+d e412 h412
+d i421 l421
+d m422 p422
+e NULL NULL
+e NULL NULL
+select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
+a1 max(c)
+a a999
+a d111
+a h112
+a l121
+a p122
+b d211
+b h212
+b l221
+b p222
+d d411
+d h412
+d l421
+d p422
+explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 5 Using where; Using index for group-by
+explain select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 5 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (b = 'b') group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using where; Using index for group-by
+explain select a1,a2, max(c) from t1 where (b = 'b') group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using where; Using index for group-by
+explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 5 Using where; Using index for group-by
+explain select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 5 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 10 Using where; Using index for group-by
+explain select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range NULL idx_t3_1 6 NULL 4 Using where; Using index for group-by
+explain select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range NULL idx_t3_1 6 NULL 4 Using where; Using index for group-by
+select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
+a1 a2 b max(c) min(c)
+a a b h112 e112
+b a b h212 e212
+c a b h312 e312
+d a b h412 e412
+select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
+a1 max(c) min(c)
+a h112 e112
+b h212 e212
+c h312 e312
+d h412 e412
+select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2;
+a1 a2 b max(c)
+a a b h112
+a b b p122
+b a b h212
+b b b p222
+c a b h312
+c b b p322
+d a b h412
+d b b p422
+select a1,a2,b,min(c),max(c) from t1 where (b = 'b') group by a1,a2;
+a1 a2 b min(c) max(c)
+a a b e112 h112
+a b b m122 p122
+b a b e212 h212
+b b b m222 p222
+c a b e312 h312
+c b b m322 p322
+d a b e412 h412
+d b b m422 p422
+select a1,a2, max(c) from t1 where (b = 'b') group by a1,a2;
+a1 a2 max(c)
+a a h112
+a b p122
+b a h212
+b b p222
+c a h312
+c b p322
+d a h412
+d b p422
+select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
+a1 a2 b max(c) min(c)
+a a b h112 e112
+b a b h212 e212
+c a b h312 e312
+d a b h412 e412
+e a b NULL NULL
+select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
+a1 max(c) min(c)
+a h112 e112
+b h212 e212
+c h312 e312
+d h412 e412
+e NULL NULL
+select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2;
+a1 a2 b max(c)
+a a b h112
+a b b p122
+b a b h212
+b b b p222
+c a b h312
+c b b p322
+d a b h412
+d b b p422
+e a b NULL
+select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
+a1 a2 b min(c) max(c)
+a a b e112 h112
+a b b m122 p122
+b a b e212 h212
+b b b m222 p222
+c a b e312 h312
+c b b m322 p322
+d a b e412 h412
+d b b m422 p422
+e a b NULL NULL
+select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
+a1 a2 max(c)
+a a h112
+a b p122
+b a h212
+b b p222
+c a h312
+c b p322
+d a h412
+d b p422
+e a NULL
+select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
+a1 a2 b max(c) min(c)
+a a b h112 e112
+b a b h212 e212
+c a b h312 e312
+select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
+a1 max(c) min(c)
+a h112 e112
+b h212 e212
+c h312 e312
+explain select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 5 Using where; Using index for group-by
+explain select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 5 Using where; Using index for group-by
+explain select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 10 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 10 Using where; Using index for group-by
+select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
+a1 a2 b min(c)
+a a NULL a777
+c a NULL c777
+select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
+a1 a2 b max(c)
+a a NULL a999
+c a NULL c999
+select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
+a1 a2 b min(c)
+a a NULL a777
+c a NULL c777
+select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2;
+a1 a2 b max(c)
+a a NULL a999
+c a NULL c999
+select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
+a1 a2 b min(c) max(c)
+a a NULL a777 a999
+c a NULL c777 c999
+select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
+a1 a2 b min(c) max(c)
+a a NULL a777 a999
+c a NULL c777 c999
+explain select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where (c > 'f123') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c > 'f123') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where (c < 'a0') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where (c < 'k321') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c < 'k321') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (c between 'b111' and 'g112') or (c between 'd000' and 'i110') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where (c > 'b1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where (c > 'f123') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (c > 'f123') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where (c < 'a0') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where (c < 'k321') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (c < 'k321') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b, max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b;
+a1 a2 b max(c)
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a b111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a b211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a a b311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a b411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t1 where (c > 'f123') group by a1,a2,b;
+a1 a2 b max(c)
+a a b h112
+a b a l121
+a b b p122
+b a b h212
+b b a l221
+b b b p222
+c a b h312
+c b a l321
+c b b p322
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t1 where (c > 'f123') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a b g112 h112
+a b a i121 l121
+a b b m122 p122
+b a b f212 h212
+b b a i221 l221
+b b b m222 p222
+c a b f312 h312
+c b a i321 l321
+c b b m322 p322
+d a b f412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t1 where (c < 'a0') group by a1,a2,b;
+a1 a2 b max(c)
+select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+select a1,a2,b, max(c) from t1 where (c < 'k321') group by a1,a2,b;
+a1 a2 b max(c)
+a a a d111
+a a b h112
+a b a k121
+b a a d211
+b a b h212
+b b a k221
+c a a d311
+c a b h312
+c b a j321
+d a a d411
+d a b h412
+d b a j421
+select a1,a2,b,min(c),max(c) from t1 where (c < 'k321') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a a111 d111
+a a b e112 h112
+a b a i121 k121
+b a a a211 d211
+b a b e212 h212
+b b a i221 k221
+c a a a311 d311
+c a b e312 h312
+c b a i321 j321
+d a a a411 d411
+d a b e412 h412
+d b a i421 j421
+select a1,a2,b, max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+a1 a2 b max(c)
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a b111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a b211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a a b311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a b411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+a1 a2 b max(c)
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a a111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b,min(c),max(c) from t1 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a c111 d111
+a a b e112 g112
+b a a b211 d211
+b a b e212 f212
+c a a b311 d311
+c a b e312 f312
+d a a b411 d411
+d a b e412 f412
+select a1,a2,b,min(c),max(c) from t1 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a a111 c111
+b a a a211 c211
+c a a a311 c311
+d a a a411 c411
+d a b g412 g412
+d b a k421 k421
+select a1,a2,b,min(c),max(c) from t1 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a c111 d111
+a a b e112 h112
+b a a b211 d211
+b a b e212 h212
+c a a b311 d311
+c a b e312 h312
+d a a b411 d411
+d a b e412 h412
+select a1,a2,b,min(c),max(c) from t1 where (c between 'b111' and 'g112') or (c between 'd000' and 'i110') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a b111 d111
+a a b e112 h112
+b a a b211 d211
+b a b e212 h212
+c a a b311 d311
+c a b e312 h312
+d a a b411 d411
+d a b e412 h412
+select a1,a2,b, max(c) from t2 where (c > 'b1') group by a1,a2,b;
+a1 a2 b max(c)
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+c a NULL c999
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a b111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a b211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a NULL c777 c999
+c a a b311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a b411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t2 where (c > 'f123') group by a1,a2,b;
+a1 a2 b max(c)
+a a b h112
+a b a l121
+a b b p122
+b a b h212
+b b a l221
+b b b p222
+c a b h312
+c b a l321
+c b b p322
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t2 where (c > 'f123') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a b g112 h112
+a b a i121 l121
+a b b m122 p122
+b a b f212 h212
+b b a i221 l221
+b b b m222 p222
+c a b f312 h312
+c b a i321 l321
+c b b m322 p322
+d a b f412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t2 where (c < 'a0') group by a1,a2,b;
+a1 a2 b max(c)
+select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+select a1,a2,b, max(c) from t2 where (c < 'k321') group by a1,a2,b;
+a1 a2 b max(c)
+a a NULL a999
+a a a d111
+a a b h112
+a b a k121
+b a a d211
+b a b h212
+b b a k221
+c a NULL c999
+c a a d311
+c a b h312
+c b a j321
+d a a d411
+d a b h412
+d b a j421
+select a1,a2,b,min(c),max(c) from t2 where (c < 'k321') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a NULL a777 a999
+a a a a111 d111
+a a b e112 h112
+a b a i121 k121
+b a a a211 d211
+b a b e212 h212
+b b a i221 k221
+c a NULL c777 c999
+c a a a311 d311
+c a b e312 h312
+c b a i321 j321
+d a a a411 d411
+d a b e412 h412
+d b a i421 j421
+select a1,a2,b, max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+a1 a2 b max(c)
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+c a NULL c999
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a b111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a b211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a NULL c777 c999
+c a a b311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a b411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b, max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+a1 a2 b max(c)
+a a NULL a999
+a a a d111
+a a b h112
+a b a l121
+a b b p122
+b a a d211
+b a b h212
+b b a l221
+b b b p222
+c a NULL c999
+c a a d311
+c a b h312
+c b a l321
+c b b p322
+d a a d411
+d a b h412
+d b a l421
+d b b p422
+select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a NULL a777 a999
+a a a a111 d111
+a a b e112 h112
+a b a i121 l121
+a b b m122 p122
+b a a a211 d211
+b a b e212 h212
+b b a i221 l221
+b b b m222 p222
+c a NULL c777 c999
+c a a a311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a a411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b,min(c),max(c) from t2 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a c111 d111
+a a b e112 g112
+b a a b211 d211
+b a b e212 f212
+c a NULL c777 c999
+c a a b311 d311
+c a b e312 f312
+d a a b411 d411
+d a b e412 f412
+select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a NULL a777 a999
+a a a a111 c111
+b a a a211 c211
+c a a a311 c311
+d a a a411 c411
+d a b g412 g412
+d b a k421 k421
+select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a c111 d111
+a a b e112 h112
+b a a b211 d211
+b a b e212 h212
+c a NULL c777 c999
+c a a b311 d311
+c a b e312 h312
+d a a b411 d411
+d a b e412 h412
+explain select a1,a2,b,min(c),max(c) from t1
+where exists ( select * from t2 where t2.c = t1.c )
+group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
+2 DEPENDENT SUBQUERY t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
+explain select a1,a2,b,min(c),max(c) from t1
+where exists ( select * from t2 where t2.c > 'b1' )
+group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
+2 SUBQUERY t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
+explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 14 Using where; Using index for group-by
+explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 14 Using where; Using index for group-by
+explain select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select a1,a2,b,min(c) from t1 where (ord(a1) > 97) and (ord(a2) + ord(a1) > 194) and (b = 'c') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c),max(c) from t2 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+explain select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a b e112 h112
+b a b e212 h212
+c a b e312 h312
+c b b m322 p322
+d a b e412 h412
+d b b m422 p422
+select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a c111 d111
+a a b e112 h112
+b a a b211 d211
+b a b e212 h212
+c a a b311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a b411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a b a i121 l121
+b b a i221 l221
+c b a i321 l321
+d b a i421 l421
+select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
+a1 a2 b min(c)
+b b a k221
+c b a k321
+d b a k421
+select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
+a1 a2 b min(c)
+b b a k221
+c b a k321
+d b a k421
+select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+a1 a2 b min(c)
+select a1,a2,b,min(c) from t1 where (ord(a1) > 97) and (ord(a2) + ord(a1) > 194) and (b = 'c') group by a1,a2,b;
+a1 a2 b min(c)
+select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a b e112 h112
+b a b e212 h212
+c a b e312 h312
+c b b m322 p322
+d a b e412 h412
+d b b m422 p422
+e a b NULL NULL
+select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a a a c111 d111
+a a b e112 h112
+b a a b211 d211
+b a b e212 h212
+c a NULL c777 c999
+c a a b311 d311
+c a b e312 h312
+c b a i321 l321
+c b b m322 p322
+d a a b411 d411
+d a b e412 h412
+d b a i421 l421
+d b b m422 p422
+select a1,a2,b,min(c),max(c) from t2 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
+a1 a2 b min(c) max(c)
+a b a i121 l121
+b b a i221 l221
+c b a i321 l321
+d b a i421 l421
+select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
+a1 a2 b min(c)
+b b a k221
+c b a k321
+d b a k421
+select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
+a1 a2 b min(c)
+b b a k221
+c b a k321
+d b a k421
+select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+a1 a2 b min(c)
+explain select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL # Using where; Using index
+explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+a1 a2 b
+a a b
+b a b
+c a b
+c b b
+d a b
+d b b
+select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+a1 a2 b
+a b a
+b b a
+c b a
+d b a
+select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+a1 a2 b c
+a b a i121
+select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+a1 a2 b
+select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+a1 a2 b
+a a b
+b a b
+c a b
+c b b
+d a b
+d b b
+e a b
+select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+a1 a2 b
+a b a
+b b a
+c b a
+d b a
+select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+a1 a2 b c
+a b a i121
+select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+a1 a2 b
+explain select distinct a1,a2,b from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
+explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
+explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select distinct b from t1 where (a2 >= 'b') and (b = 'a');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
+explain select distinct a1,a2,b from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using index for group-by
+explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
+explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select distinct b from t2 where (a2 >= 'b') and (b = 'a');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL idx_t2_2 146 NULL 164 Using where; Using index
+select distinct a1,a2,b from t1;
+a1 a2 b
+a a a
+a a b
+a b a
+a b b
+b a a
+b a b
+b b a
+b b b
+c a a
+c a b
+c b a
+c b b
+d a a
+d a b
+d b a
+d b b
+select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a');
+a1 a2 b
+a b a
+b b a
+c b a
+d b a
+select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+a1 a2 b c
+a b a i121
+select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+a1 a2 b
+select distinct b from t1 where (a2 >= 'b') and (b = 'a');
+b
+a
+select distinct a1,a2,b from t2;
+a1 a2 b
+a a NULL
+a a a
+a a b
+a b a
+a b b
+b a a
+b a b
+b b a
+b b b
+c a NULL
+c a a
+c a b
+c b a
+c b b
+d a a
+d a b
+d b a
+d b b
+e a a
+e a b
+select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a');
+a1 a2 b
+a b a
+b b a
+c b a
+d b a
+select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+a1 a2 b c
+a b a i121
+select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+a1 a2 b
+select distinct b from t2 where (a2 >= 'b') and (b = 'a');
+b
+a
+select distinct t_00.a1
+from t1 t_00
+where exists ( select * from t2 where a1 = t_00.a1 );
+a1
+a
+b
+c
+d
+select distinct a1,a1 from t1;
+a1 a1
+a a
+b b
+c c
+d d
+select distinct a2,a1,a2,a1 from t1;
+a2 a1 a2 a1
+a a a a
+b a b a
+a b a b
+b b b b
+a c a c
+b c b c
+a d a d
+b d b d
+select distinct t1.a1,t2.a1 from t1,t2;
+a1 a1
+a a
+b a
+c a
+d a
+a b
+b b
+c b
+d b
+a c
+b c
+c c
+d c
+a d
+b d
+c d
+d d
+a e
+b e
+c e
+d e
+explain select distinct a1,a2,b from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
+explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
+explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
+explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by
+explain select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by; Using temporary; Using filesort
+explain select distinct a1,a2,b from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using index for group-by
+explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL # Using where; Using index
+explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by; Using temporary; Using filesort
+select distinct a1,a2,b from t1;
+a1 a2 b
+a a a
+a a b
+a b a
+a b b
+b a a
+b a b
+b b a
+b b b
+c a a
+c a b
+c b a
+c b b
+d a a
+d a b
+d b a
+d b b
+select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+a1 a2 b
+a b a
+b b a
+c b a
+d b a
+select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+a1 a2 b c
+a b a i121
+select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+a1 a2 b
+select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+b
+a
+select distinct a1,a2,b from t2;
+a1 a2 b
+a a NULL
+a a a
+a a b
+a b a
+a b b
+b a a
+b a b
+b b a
+b b b
+c a NULL
+c a a
+c a b
+c b a
+c b b
+d a a
+d a b
+d b a
+d b b
+e a a
+e a b
+select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+a1 a2 b
+a b a
+b b a
+c b a
+d b a
+select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+a1 a2 b c
+a b a i121
+select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+a1 a2 b
+select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+b
+a
+explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
+explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
+explain select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 128 Using where; Using index
+explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
+explain select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 128 Using where; Using index
+select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
+count(distinct a1,a2,b)
+4
+select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+count(distinct a1,a2,b,c)
+1
+select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+count(distinct a1,a2,b)
+0
+select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
+count(distinct b)
+1
+select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
+ord(a1) + count(distinct a1,a2,b)
+104
+explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by
+explain select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using index for group-by
+select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
+a1 a2 b concat(min(c), max(c))
+a a a a111d111
+a a b e112h112
+a b a i121l121
+a b b m122p122
+b a a a211d211
+b a b e212h212
+b b a i221l221
+b b b m222p222
+c a a a311d311
+c a b e312h312
+c b a i321l321
+c b b m322p322
+select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
+concat(a1,min(c)) b
+aa111 a
+ae112 b
+ai121 a
+am122 b
+ba211 a
+be212 b
+bi221 a
+bm222 b
+ca311 a
+ce312 b
+ci321 a
+cm322 b
+select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;
+concat(a1,min(c)) b max(c)
+aa111 a d111
+ae112 b h112
+ai121 a l121
+am122 b p122
+ba211 a d211
+be212 b h212
+bi221 a l221
+bm222 b p222
+ca311 a d311
+ce312 b h312
+ci321 a l321
+cm322 b p322
+select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
+concat(a1,a2) b min(c) max(c)
+aa a a111 d111
+aa b e112 h112
+ab a i121 l121
+ab b m122 p122
+ba a a211 d211
+ba b e212 h212
+bb a i221 l221
+bb b m222 p222
+ca a a311 d311
+ca b e312 h312
+cb a i321 l321
+cb b m322 p322
+select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
+concat(ord(min(b)),ord(max(b))) min(b) max(b)
+9798 a b
+9798 a b
+9798 a b
+9798 a b
+9798 a b
+9798 a b
+9798 a b
+9798 a b
+explain select a1,a2,b,d,min(c),max(c) from t1 group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using temporary; Using filesort
+explain select a1,a2,b,d from t1 group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using temporary; Using filesort
+explain select a1,a2,min(b),max(b) from t1
+where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 76 Using where; Using index
+explain select a1,a2,b,min(c),max(c) from t1
+where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 Using where; Using temporary; Using filesort
+explain select a1,a2,b,c from t1
+where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 Using where; Using temporary; Using filesort
+explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
+explain select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 76 Using where; Using index
+explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
+select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
+a1 a2 min(b) c
+a a a a111
+explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b = 'a') group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
+explain select a1,a2,b,min(c),max(c) from t2
+where (c > 'a000') and (c <= 'd999') and (c like '_8__') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
+explain select a1, a2, b, c, min(d), max(d) from t1 group by a1,a2,b,c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using temporary; Using filesort
+explain select a1,a2,count(a2) from t1 group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using index
+explain select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 128 Using where; Using index
+explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 128 Using where; Using index
+explain select a1 from t1 where a2 = 'b' group by a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by
+select a1 from t1 where a2 = 'b' group by a1;
+a1
+a
+b
+c
+d
+explain select distinct a1 from t1 where a2 = 'b';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by
+select distinct a1 from t1 where a2 = 'b';
+a1
+a
+b
+c
+d
+create table bug12672 (
+pk_col int auto_increment primary key, a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' '
+) engine=innodb;
+insert into bug12672 (a1, a2, b, c, d, dummy) select * from t1;
+create index idx12672_0 on bug12672 (a1);
+create index idx12672_1 on bug12672 (a1,a2,b,c);
+create index idx12672_2 on bug12672 (a1,a2,b);
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+explain select distinct a1 from bug12672 where pk_col not in (1,2,3,4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE bug12672 range PRIMARY PRIMARY 4 NULL # Using where; Using temporary
+select distinct a1 from bug12672 where pk_col not in (1,2,3,4);
+a1
+a
+b
+c
+d
+drop table bug12672;
+drop table t1;
+drop table t2;
+drop table t3;
+create table t1 (
+a varchar(30), b varchar(30), primary key(a), key(b)
+) engine=innodb;
+select distinct a from t1;
+a
+drop table t1;
+create table t1(a int, key(a)) engine=innodb;
+insert into t1 values(1);
+select a, count(a) from t1 group by a with rollup;
+a count(a)
+1 1
+NULL 1
+drop table t1;
diff --git a/mysql-test/r/have_eucjpms.require b/mysql-test/r/have_eucjpms.require
new file mode 100644
index 00000000000..f35621b2c1a
--- /dev/null
+++ b/mysql-test/r/have_eucjpms.require
@@ -0,0 +1,2 @@
+Collation Charset Id Default Compiled Sortlen
+eucjpms_japanese_ci eucjpms 97 Yes Yes 1
diff --git a/mysql-test/r/have_federated_db.require b/mysql-test/r/have_federated_db.require
new file mode 100644
index 00000000000..f4c521a8f35
--- /dev/null
+++ b/mysql-test/r/have_federated_db.require
@@ -0,0 +1,2 @@
+Variable_name Value
+have_federated_engine YES
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 218276406b1..35a1358dd0c 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
create table t1 (a int);
select count(a) as b from t1 where a=0 having b > 0;
b
@@ -12,7 +12,7 @@ explain extended select count(a) as b from t1 where a=0 having b >=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select count(test.t1.a) AS `b` from test.t1 where (test.t1.a = 0) having (count(test.t1.a) >= 0)
+Note 1003 select count(`test`.`t1`.`a`) AS `b` from `test`.`t1` where (`test`.`t1`.`a` = 0) having (count(`test`.`t1`.`a`) >= 0)
drop table t1;
CREATE TABLE t1 (
raw_id int(10) NOT NULL default '0',
@@ -128,3 +128,204 @@ id description c
1 test 0
2 test2 0
drop table t1,t2,t3;
+create table t1 (col1 int, col2 varchar(5), col_t1 int);
+create table t2 (col1 int, col2 varchar(5), col_t2 int);
+create table t3 (col1 int, col2 varchar(5), col_t3 int);
+insert into t1 values(10,'hello',10);
+insert into t1 values(20,'hello',20);
+insert into t1 values(30,'hello',30);
+insert into t1 values(10,'bye',10);
+insert into t1 values(10,'sam',10);
+insert into t1 values(10,'bob',10);
+insert into t2 select * from t1;
+insert into t3 select * from t1;
+select count(*) from t1 group by col1 having col1 = 10;
+count(*)
+4
+select count(*) as count_col1 from t1 group by col1 having col1 = 10;
+count_col1
+4
+select count(*) as count_col1 from t1 as tmp1 group by col1 having col1 = 10;
+count_col1
+4
+select count(*) from t1 group by col2 having col2 = 'hello';
+count(*)
+3
+select count(*) from t1 group by col2 having col1 = 10;
+ERROR 42S22: Unknown column 'col1' in 'having clause'
+select col1 as count_col1 from t1 as tmp1 group by col1 having col1 = 10;
+count_col1
+10
+select col1 as count_col1 from t1 as tmp1 group by col1 having count_col1 = 10;
+count_col1
+10
+select col1 as count_col1 from t1 as tmp1 group by count_col1 having col1 = 10;
+count_col1
+10
+select col1 as count_col1 from t1 as tmp1 group by count_col1 having count_col1 = 10;
+count_col1
+10
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col1 = 10;
+count_col1 col2
+10 bob
+10 bye
+10 hello
+10 sam
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having count_col1 = 10;
+count_col1 col2
+10 bob
+10 bye
+10 hello
+10 sam
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col2 = 'hello';
+count_col1 col2
+10 hello
+20 hello
+30 hello
+select col1 as count_col1,col2 as group_col2 from t1 as tmp1 group by col1,col2 having group_col2 = 'hello';
+count_col1 group_col2
+10 hello
+20 hello
+30 hello
+select sum(col1) as co12 from t1 group by col2 having col2 10;
+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 '10' at line 1
+select sum(col1) as co2, count(col2) as cc from t1 group by col1 having col1 =10;
+co2 cc
+40 4
+select t2.col2 from t2 group by t2.col1, t2.col2 having t1.col1 <= 10;
+ERROR 42S22: Unknown column 't1.col1' in 'having clause'
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having t2.col1 <= 10);
+col1
+10
+20
+30
+10
+10
+10
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2
+having t2.col1 <=
+(select min(t3.col1) from t3));
+col1
+10
+20
+30
+10
+10
+10
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having t1.col1 <= 10);
+col1
+10
+10
+10
+10
+select t1.col1 as tmp_col from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having tmp_col <= 10);
+tmp_col
+10
+10
+10
+10
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having col_t1 <= 10);
+col1
+10
+10
+10
+10
+select sum(col1) from t1
+group by col_t1
+having (select col_t1 from t2 where col_t1 = col_t2 order by col_t2 limit 1);
+sum(col1)
+40
+20
+30
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having col_t1 <= 10)
+having col_t1 <= 20;
+ERROR 42S22: Unknown column 'col_t1' in 'having clause'
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having col_t1 <= 10)
+group by col_t1
+having col_t1 <= 20;
+col1
+10
+select col_t1, sum(col1) from t1
+group by col_t1
+having col_t1 > 10 and
+exists (select sum(t2.col1) from t2
+group by t2.col2 having t2.col2 > 'b');
+col_t1 sum(col1)
+20 20
+30 30
+select sum(col1) from t1
+group by col_t1
+having col_t1 in (select sum(t2.col1) from t2
+group by t2.col2, t2.col1 having t2.col1 = t1.col1);
+ERROR 42S22: Unknown column 't1.col1' in 'having clause'
+select sum(col1) from t1
+group by col_t1
+having col_t1 in (select sum(t2.col1) from t2
+group by t2.col2, t2.col1 having t2.col1 = col_t1);
+sum(col1)
+40
+20
+30
+select t1.col1, t2.col1 from t1, t2 where t1.col1 = t2.col1
+group by t1.col1, t2.col1 having col1 = 2;
+ERROR 23000: Column 'col1' in having clause is ambiguous
+select t1.col1*10+t2.col1 from t1,t2 where t1.col1=t2.col1
+group by t1.col1, t2.col1 having col1 = 2;
+ERROR 23000: Column 'col1' in having clause is ambiguous
+drop table t1, t2, t3;
+create table t1 (s1 int);
+insert into t1 values (1),(2),(3);
+select count(*) from t1 group by s1 having s1 is null;
+count(*)
+select s1*0 as s1 from t1 group by s1 having s1 <> 0;
+s1
+0
+0
+0
+Warnings:
+Warning 1052 Column 's1' in group statement is ambiguous
+Warning 1052 Column 's1' in having clause is ambiguous
+select s1*0 from t1 group by s1 having s1 = 0;
+s1*0
+select s1 from t1 group by 1 having 1 = 0;
+s1
+select count(s1) from t1 group by s1 having count(1+1)=2;
+count(s1)
+select count(s1) from t1 group by s1 having s1*0=0;
+count(s1)
+1
+1
+1
+select * from t1 a, t1 b group by a.s1 having s1 is null;
+ERROR 23000: Column 's1' in having clause is ambiguous
+drop table t1;
+create table t1 (s1 char character set latin1 collate latin1_german1_ci);
+insert into t1 values ('ü'),('y');
+Warnings:
+Warning 1265 Data truncated for column 's1' at row 1
+select s1,count(s1) from t1
+group by s1 collate latin1_swedish_ci having s1 = 'y';
+s1 count(s1)
+y 1
+drop table t1;
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index 53dec294ef8..969cb06e9fe 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2,t3;
create table t1 (a int not null,b int not null, primary key (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
insert into t1 values(1,1),(2,2),(3,3),(4,4);
delete from t1 where a=1 or a=0;
@@ -40,7 +40,7 @@ a b
4 4
drop table t1;
create table t1 (a int not null) engine=heap;
-insert into t1 values (869751),(736494),(226312),(802616);
+insert into t1 values (869751),(736494),(226312),(802616),(728912);
select * from t1 where a > 736494;
a
869751
@@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL btn NULL NULL NULL 11 Using where
explain select * from t1 where btn="a" and new_col="a";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref btn btn 11 const,const 2 Using where
+1 SIMPLE t1 ref btn btn 11 const,const 1 Using where
drop table t1;
CREATE TABLE t1 (
a int default NULL,
@@ -249,16 +249,425 @@ a
3
2
drop table t1;
+set storage_engine=HEAP;
+create table t1 (v varchar(10), c char(10), t varchar(50));
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Note 1265 Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+ *+*+ *
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Warning 1265 Data truncated for column 't' at row 2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(10) default NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+ *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL,
+ KEY `v` (`v`),
+ KEY `c` (`c`),
+ KEY `t` (`t`(10))
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const 10 Using where
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const 10 Using where
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref t t 13 const 10 Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*'));
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const 10 Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result trim(v),count(t) from t1 group by v limit 10;
+trim(v) count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result trim(v),count(c) from t1 group by v limit 10;
+trim(v) count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(*) from t1 group by c limit 10;
+c count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(*) from t1 group by t limit 10;
+t count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result trim(t),count(t) from t1 group by t limit 10;
+trim(t) count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a ';
+update t1 set a='a ' where a like 'a ';
+drop table t1;
+create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using btree (c), key using btree (t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL,
+ KEY `v` USING BTREE (`v`),
+ KEY `c` USING BTREE (`c`),
+ KEY `t` USING BTREE (`t`(10))
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const # Using where
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const # Using where
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref t t 13 const # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*'));
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const # Using where
+drop table t1;
+create table t1 (a char(10), unique using btree (a)) engine=heap;
+insert into t1 values ('a');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a ';
+update t1 set a='a ' where a like 'a ';
+drop table t1;
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL,
+ KEY `v` (`v`(5)),
+ KEY `c` (`c`(5)),
+ KEY `t` (`t`(5))
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(65530) default NULL,
+ KEY `v` (`v`(10))
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+set storage_engine=MyISAM;
create table t1 (a bigint unsigned auto_increment primary key, b int,
key (b, a)) engine=heap;
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
+insert t1 (b) values (1),(1),(1),(1),(1),(1),(1),(1);
select * from t1;
a b
1 1
@@ -272,14 +681,7 @@ a b
drop table t1;
create table t1 (a int not null, b int not null auto_increment,
primary key(a, b), key(b)) engine=heap;
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
+insert t1 (a) values (1),(1),(1),(1),(1),(1),(1),(1);
select * from t1;
a b
1 1
@@ -291,8 +693,18 @@ a b
1 7
1 8
drop table t1;
+create table t1 (a int not null, b int not null auto_increment,
+primary key(a, b)) engine=heap;
+ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key
create table t1 (c char(255), primary key(c(90)));
insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
-ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1
+ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1
drop table t1;
+create table t1 (c char(10)) engine=memory;
+create table t2 (c varchar(10)) engine=memory;
+show table status like 't_';
+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 MEMORY 10 Fixed 0 11 0 # 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 0 12 0 # 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+drop table t1, t2;
diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result
index 5c60c97d674..374d2c63632 100644
--- a/mysql-test/r/heap_btree.result
+++ b/mysql-test/r/heap_btree.result
@@ -40,7 +40,7 @@ a b
4 4
drop table t1;
create table t1 (a int not null) engine=heap;
-insert into t1 values (869751),(736494),(226312),(802616);
+insert into t1 values (869751),(736494),(226312),(802616),(728912);
select * from t1 where a > 736494;
a
869751
@@ -73,7 +73,7 @@ engine=heap;
insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
explain select * from t1 where x=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref x x 4 const 1 Using where
+1 SIMPLE t1 ref x x 4 const 1
select * from t1 where x=1;
x y
1 1
@@ -134,7 +134,7 @@ a b
1 1
explain select * from tx where b=x;
id select_type table type possible_keys key key_len ref rows Extra
-x SIMPLE tx ref b b x const x Using where
+x SIMPLE tx ref b b x const x
drop table t1;
create table t1 (id int unsigned not null, primary key using BTREE (id)) engine=HEAP;
insert into t1 values(1);
diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result
index e5098ab8c87..d8d89b786b5 100644
--- a/mysql-test/r/heap_hash.result
+++ b/mysql-test/r/heap_hash.result
@@ -40,7 +40,7 @@ a b
4 4
drop table t1;
create table t1 (a int not null) engine=heap;
-insert into t1 values (869751),(736494),(226312),(802616);
+insert into t1 values (869751),(736494),(226312),(802616),(728912);
select * from t1 where a > 736494;
a
869751
@@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL btn NULL NULL NULL 11 Using where
explain select * from t1 where btn="a" and new_col="a";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref btn btn 11 const,const 2 Using where
+1 SIMPLE t1 ref btn btn 11 const,const 1 Using where
drop table t1;
CREATE TABLE t1 (
a int default NULL,
@@ -291,28 +291,28 @@ insert into t1 (name) values ('Matt'), ('Lilu'), ('Corbin'), ('Carly'),
insert into t2 select * from t1;
explain select * from t1 where name='matt';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 20 const 1 Using where
+1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where
explain select * from t2 where name='matt';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 20 const 1 Using where
+1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where
explain select * from t1 where name='Lilu';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 20 const 1 Using where
+1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where
explain select * from t2 where name='Lilu';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 20 const 1 Using where
+1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where
explain select * from t1 where name='Phil';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 20 const 1 Using where
+1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where
explain select * from t2 where name='Phil';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 20 const 1 Using where
+1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where
explain select * from t1 where name='Lilu';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 20 const 1 Using where
+1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where
explain select * from t2 where name='Lilu';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 20 const 1 Using where
+1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where
insert into t1 (name) select name from t2;
insert into t1 (name) select name from t2;
insert into t1 (name) select name from t2;
@@ -325,7 +325,7 @@ count(*)
7
explain select * from t1 ignore index (btree_idx) where name='matt';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref heap_idx heap_idx 20 const 7 Using where
+1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where
show index from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 id NULL 91 NULL NULL HASH
@@ -353,8 +353,8 @@ t3 1 a 1 a NULL NULL NULL NULL HASH
t3 1 a 2 b NULL 13 NULL NULL HASH
explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref heap_idx heap_idx 20 const 7 Using where
-1 SIMPLE t3 ref a a 40 func,const 7 Using where
+1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where
+1 SIMPLE t3 ref a a 44 const,const 7 Using where
drop table t1, t2, t3;
create temporary table t1 ( a int, index (a) ) engine=memory;
insert into t1 values (1),(2),(3),(4),(5);
diff --git a/mysql-test/r/help.result b/mysql-test/r/help.result
index edf7d0e91cb..85ca832828d 100644
--- a/mysql-test/r/help.result
+++ b/mysql-test/r/help.result
@@ -1,32 +1,48 @@
insert into mysql.help_category(help_category_id,name)values(1,'impossible_category_1');
+Warnings:
+Warning 1364 Field 'url' doesn't have a default value
select @category1_id:= 1;
@category1_id:= 1
1
insert into mysql.help_category(help_category_id,name)values(2,'impossible_category_2');
+Warnings:
+Warning 1364 Field 'url' doesn't have a default value
select @category2_id:= 2;
@category2_id:= 2
2
insert into mysql.help_category(help_category_id,name,parent_category_id)values(3,'impossible_category_3',@category2_id);
+Warnings:
+Warning 1364 Field 'url' doesn't have a default value
select @category3_id:= 3;
@category3_id:= 3
3
insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(1,'impossible_function_1',@category1_id,'description of \n impossible_function1\n','example of \n impossible_function1');
+Warnings:
+Warning 1364 Field 'url' doesn't have a default value
select @topic1_id:= 1;
@topic1_id:= 1
1
insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(2,'impossible_function_2',@category1_id,'description of \n impossible_function2\n','example of \n impossible_function2');
+Warnings:
+Warning 1364 Field 'url' doesn't have a default value
select @topic2_id:= 2;
@topic2_id:= 2
2
insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(3,'impossible_function_3',@category2_id,'description of \n impossible_function3\n','example of \n impossible_function3');
+Warnings:
+Warning 1364 Field 'url' doesn't have a default value
select @topic3_id:= 3;
@topic3_id:= 3
3
insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(4,'impossible_function_4',@category2_id,'description of \n impossible_function4\n','example of \n impossible_function4');
+Warnings:
+Warning 1364 Field 'url' doesn't have a default value
select @topic4_id:= 4;
@topic4_id:= 4
4
insert into mysql.help_topic(help_topic_id,name,help_category_id,description,example)values(5,'impossible_function_7',@category3_id,'description of \n impossible_function5\n','example of \n impossible_function7');
+Warnings:
+Warning 1364 Field 'url' doesn't have a default value
select @topic5_id:= 5;
@topic5_id:= 5
5
diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result
new file mode 100644
index 00000000000..d039d5a04c9
--- /dev/null
+++ b/mysql-test/r/index_merge.result
@@ -0,0 +1,386 @@
+drop table if exists t0, t1, t2, t3, t4;
+create table t0
+(
+key1 int not null,
+INDEX i1(key1)
+);
+alter table t0 add key2 int not null, add index i2(key2);
+alter table t0 add key3 int not null, add index i3(key3);
+alter table t0 add key4 int not null, add index i4(key4);
+alter table t0 add key5 int not null, add index i5(key5);
+alter table t0 add key6 int not null, add index i6(key6);
+alter table t0 add key7 int not null, add index i7(key7);
+alter table t0 add key8 int not null, add index i8(key8);
+update t0 set key2=key1,key3=key1,key4=key1,key5=key1,key6=key1,key7=key1,key8=1024-key1;
+analyze table t0;
+Table Op Msg_type Msg_text
+test.t0 analyze status OK
+explain select * from t0 where key1 < 3 or key1 > 1020;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 range i1 i1 4 NULL 78 Using where
+explain
+select * from t0 where key1 < 3 or key2 > 1020;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 45 Using sort_union(i1,i2); Using where
+select * from t0 where key1 < 3 or key2 > 1020;
+key1 key2 key3 key4 key5 key6 key7 key8
+1 1 1 1 1 1 1 1023
+2 2 2 2 2 2 2 1022
+1021 1021 1021 1021 1021 1021 1021 3
+1022 1022 1022 1022 1022 1022 1022 2
+1023 1023 1023 1023 1023 1023 1023 1
+1024 1024 1024 1024 1024 1024 1024 0
+explain select * from t0 where key1 < 3 or key2 <4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using sort_union(i1,i2); Using where
+explain
+select * from t0 where (key1 > 30 and key1<35) or (key2 >32 and key2 < 40);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 11 Using sort_union(i1,i2); Using where
+select * from t0 where (key1 > 30 and key1<35) or (key2 >32 and key2 < 40);
+key1 key2 key3 key4 key5 key6 key7 key8
+31 31 31 31 31 31 31 993
+32 32 32 32 32 32 32 992
+33 33 33 33 33 33 33 991
+34 34 34 34 34 34 34 990
+35 35 35 35 35 35 35 989
+36 36 36 36 36 36 36 988
+37 37 37 37 37 37 37 987
+38 38 38 38 38 38 38 986
+39 39 39 39 39 39 39 985
+explain select * from t0 ignore index (i2) where key1 < 3 or key2 <4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL i1 NULL NULL NULL 1024 Using where
+explain select * from t0 where (key1 < 3 or key2 <4) and key3 = 50;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ref i1,i2,i3 i3 4 const 1 Using where
+explain select * from t0 use index (i1,i2) where (key1 < 3 or key2 <4) and key3 = 50;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using sort_union(i1,i2); Using where
+explain select * from t0 where (key1 > 1 or key2 > 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL i1,i2 NULL NULL NULL 1024 Using where
+explain select * from t0 force index (i1,i2) where (key1 > 1 or key2 > 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 1024 Using sort_union(i1,i2); Using where
+explain
+select * from t0 where key1<3 or key2<3 or (key1>5 and key1<8) or
+(key1>10 and key1<12) or (key2>100 and key2<110);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 17 Using sort_union(i1,i2); Using where
+explain select * from t0 where key2 = 45 or key1 <=> null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 range i1,i2 i2 4 NULL 1 Using where
+explain select * from t0 where key2 = 45 or key1 is not null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL i1,i2 NULL NULL NULL 1024 Using where
+explain select * from t0 where key2 = 45 or key1 is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ref i2 i2 4 const 1
+explain select * from t0 where key2=10 or key3=3 or key4 <=> null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i2,i3,i4 i2,i3 4,4 NULL 2 Using union(i2,i3); Using where
+explain select * from t0 where key2=10 or key3=3 or key4 is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i2,i3 i2,i3 4,4 NULL 2 Using union(i2,i3); Using where
+explain select key1 from t0 where (key1 <=> null) or (key2 < 5) or
+(key3=10) or (key4 <=> null);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i4 i2,i3 4,4 NULL 6 Using sort_union(i2,i3); Using where
+explain select key1 from t0 where (key1 <=> null) or (key1 < 5) or
+(key3=10) or (key4 <=> null);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i3,i4 i1,i3 4,4 NULL 6 Using sort_union(i1,i3); Using where
+explain select * from t0 where
+(key1 < 3 or key2 < 3) and (key3 < 4 or key4 < 4) and (key5 < 5 or key6 < 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i4,i5,i6 i1,i2 4,4 NULL 6 Using sort_union(i1,i2); Using where
+explain
+select * from t0 where (key1 < 3 or key2 < 6) and (key1 < 7 or key3 < 4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3 i1,i2 4,4 NULL 9 Using sort_union(i1,i2); Using where
+select * from t0 where (key1 < 3 or key2 < 6) and (key1 < 7 or key3 < 4);
+key1 key2 key3 key4 key5 key6 key7 key8
+1 1 1 1 1 1 1 1023
+2 2 2 2 2 2 2 1022
+3 3 3 3 3 3 3 1021
+4 4 4 4 4 4 4 1020
+5 5 5 5 5 5 5 1019
+explain select * from t0 where
+(key1 < 3 or key2 < 3) and (key3 < 4 or key4 < 4) and (key5 < 2 or key6 < 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i4,i5,i6 i1,i2 4,4 NULL 6 Using sort_union(i1,i2); Using where
+explain select * from t0 where
+(key1 < 3 or key2 < 3) and (key3 < 100);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 range i1,i2,i3 i3 4 NULL 95 Using where
+explain select * from t0 where
+(key1 < 3 or key2 < 3) and (key3 < 1000);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL i1,i2,i3 NULL NULL NULL 1024 Using where
+explain select * from t0 where
+((key1 < 4 or key2 < 4) and (key2 <5 or key3 < 4))
+or
+key2 > 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL i1,i2,i3 NULL NULL NULL 1024 Using where
+explain select * from t0 where
+((key1 < 4 or key2 < 4) and (key2 <5 or key3 < 4))
+or
+key1 < 7;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3 i1,i2 4,4 NULL 10 Using sort_union(i1,i2); Using where
+select * from t0 where
+((key1 < 4 or key2 < 4) and (key2 <5 or key3 < 4))
+or
+key1 < 7;
+key1 key2 key3 key4 key5 key6 key7 key8
+1 1 1 1 1 1 1 1023
+2 2 2 2 2 2 2 1022
+3 3 3 3 3 3 3 1021
+4 4 4 4 4 4 4 1020
+5 5 5 5 5 5 5 1019
+6 6 6 6 6 6 6 1018
+explain select * from t0 where
+((key1 < 4 or key2 < 4) and (key3 <5 or key5 < 4))
+or
+((key5 < 5 or key6 < 6) and (key7 <7 or key8 < 4));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7,i8 i1,i2,i5,i6 4,4,4,4 NULL 19 Using sort_union(i1,i2,i5,i6); Using where
+explain select * from t0 where
+((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+or
+((key7 <7 or key8 < 4) and (key5 < 5 or key6 < 6));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7,i8 i3,i5,i7,i8 4,4,4,4 NULL 20 Using sort_union(i3,i5,i7,i8); Using where
+explain select * from t0 where
+((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+or
+((key3 <7 or key5 < 2) and (key5 < 5 or key6 < 6));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 4,4 NULL 11 Using sort_union(i3,i5); Using where
+explain select * from t0 where
+((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+or
+(((key3 <7 and key7 < 6) or key5 < 2) and (key5 < 5 or key6 < 6));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7 i3,i5 4,4 NULL 11 Using sort_union(i3,i5); Using where
+explain select * from t0 where
+((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+or
+((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL i1,i2,i3,i5,i6 NULL NULL NULL 1024 Using where
+explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where
+((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+or
+((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 0,4 NULL 1024 Using sort_union(i3,i5); Using where
+select * from t0 where key1 < 5 or key8 < 4 order by key1;
+key1 key2 key3 key4 key5 key6 key7 key8
+1 1 1 1 1 1 1 1023
+2 2 2 2 2 2 2 1022
+3 3 3 3 3 3 3 1021
+4 4 4 4 4 4 4 1020
+1021 1021 1021 1021 1021 1021 1021 3
+1022 1022 1022 1022 1022 1022 1022 2
+1023 1023 1023 1023 1023 1023 1023 1
+1024 1024 1024 1024 1024 1024 1024 0
+explain
+select * from t0 where key1 < 5 or key8 < 4 order by key1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i8 i1,i8 4,4 NULL 9 Using sort_union(i1,i8); Using where; Using filesort
+create table t2 like t0;
+insert into t2 select * from t0;
+alter table t2 add index i1_3(key1, key3);
+alter table t2 add index i2_3(key2, key3);
+alter table t2 drop index i1;
+alter table t2 drop index i2;
+alter table t2 add index i321(key3, key2, key1);
+explain select key3 from t2 where key1 = 100 or key2 = 100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index_merge i1_3,i2_3 i1_3,i2_3 4,4 NULL 2 Using sort_union(i1_3,i2_3); Using where
+explain select key3 from t2 where key1 <100 or key2 < 100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index i1_3,i2_3 i321 12 NULL 1024 Using where; Using index
+explain select key7 from t2 where key1 <100 or key2 < 100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL i1_3,i2_3 NULL NULL NULL 1024 Using where
+create table t4 (
+key1a int not null,
+key1b int not null,
+key2 int not null,
+key2_1 int not null,
+key2_2 int not null,
+key3 int not null,
+index i1a (key1a, key1b),
+index i1b (key1b, key1a),
+index i2_1(key2, key2_1),
+index i2_2(key2, key2_1)
+);
+insert into t4 select key1,key1,key1 div 10, key1 % 10, key1 % 10, key1 from t0;
+select * from t4 where key1a = 3 or key1b = 4;
+key1a key1b key2 key2_1 key2_2 key3
+3 3 0 3 3 3
+4 4 0 4 4 4
+explain select * from t4 where key1a = 3 or key1b = 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 index_merge i1a,i1b i1a,i1b 4,4 NULL 2 Using sort_union(i1a,i1b); Using where
+explain select * from t4 where key2 = 1 and (key2_1 = 1 or key3 = 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ref i2_1,i2_2 i2_1 4 const 10 Using where
+explain select * from t4 where key2 = 1 and (key2_1 = 1 or key2_2 = 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ref i2_1,i2_2 i2_1 4 const 10 Using where
+explain select * from t4 where key2_1 = 1 or key2_2 = 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 1024 Using where
+create table t1 like t0;
+insert into t1 select * from t0;
+explain select * from t0 left join t1 on (t0.key1=t1.key1)
+where t0.key1=3 or t0.key2=4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
+1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1
+select * from t0 left join t1 on (t0.key1=t1.key1)
+where t0.key1=3 or t0.key2=4;
+key1 key2 key3 key4 key5 key6 key7 key8 key1 key2 key3 key4 key5 key6 key7 key8
+3 3 3 3 3 3 3 1021 3 3 3 3 3 3 3 1021
+4 4 4 4 4 4 4 1020 4 4 4 4 4 4 4 1020
+explain
+select * from t0,t1 where (t0.key1=t1.key1) and ( t0.key1=3 or t0.key2=4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
+1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1
+explain
+select * from t0,t1 where (t0.key1=t1.key1) and
+(t0.key1=3 or t0.key2=4) and t1.key1<200;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL i1,i2 NULL NULL NULL 1024 Using where
+1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1
+explain
+select * from t0,t1 where (t0.key1=t1.key1) and
+(t0.key1=3 or t0.key2<4) and t1.key1=2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ref i1,i2 i1 4 const 1 Using where
+1 SIMPLE t1 ref i1 i1 4 const 1
+explain select * from t0,t1 where t0.key1 = 5 and
+(t1.key1 = t0.key1 or t1.key8 = t0.key1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ref i1 i1 4 const 1
+1 SIMPLE t1 index_merge i1,i8 i1,i8 4,4 NULL 2 Using union(i1,i8); Using where
+explain select * from t0,t1 where t0.key1 < 3 and
+(t1.key1 = t0.key1 or t1.key8 = t0.key1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 range i1 i1 4 NULL 3 Using where
+1 SIMPLE t1 ALL i1,i8 NULL NULL NULL 1024 Range checked for each record (index map: 0x81)
+explain select * from t1 where key1=3 or key2=4
+union select * from t1 where key1<4 or key3=5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
+2 UNION t1 index_merge i1,i3 i1,i3 4,4 NULL 5 Using sort_union(i1,i3); Using where
+NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
+explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 1
+2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
+create table t3 like t0;
+insert into t3 select * from t0;
+alter table t3 add key9 int not null, add index i9(key9);
+alter table t3 add keyA int not null, add index iA(keyA);
+alter table t3 add keyB int not null, add index iB(keyB);
+alter table t3 add keyC int not null, add index iC(keyC);
+update t3 set key9=key1,keyA=key1,keyB=key1,keyC=key1;
+explain select * from t3 where
+key1=1 or key2=2 or key3=3 or key4=4 or
+key5=5 or key6=6 or key7=7 or key8=8 or
+key9=9 or keyA=10 or keyB=11 or keyC=12;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index_merge i1,i2,i3,i4,i5,i6,i7,i8,i9,iA,iB,iC i1,i2,i3,i4,i5,i6,i7,i8,i9,iA,iB,iC 4,4,4,4,4,4,4,4,4,4,4,4 NULL 12 Using union(i1,i2,i3,i4,i5,i6,i7,i8,i9,iA,iB,iC); Using where
+select * from t3 where
+key1=1 or key2=2 or key3=3 or key4=4 or
+key5=5 or key6=6 or key7=7 or key8=8 or
+key9=9 or keyA=10 or keyB=11 or keyC=12;
+key1 key2 key3 key4 key5 key6 key7 key8 key9 keyA keyB keyC
+1 1 1 1 1 1 1 1023 1 1 1 1
+2 2 2 2 2 2 2 1022 2 2 2 2
+3 3 3 3 3 3 3 1021 3 3 3 3
+4 4 4 4 4 4 4 1020 4 4 4 4
+5 5 5 5 5 5 5 1019 5 5 5 5
+6 6 6 6 6 6 6 1018 6 6 6 6
+7 7 7 7 7 7 7 1017 7 7 7 7
+9 9 9 9 9 9 9 1015 9 9 9 9
+10 10 10 10 10 10 10 1014 10 10 10 10
+11 11 11 11 11 11 11 1013 11 11 11 11
+12 12 12 12 12 12 12 1012 12 12 12 12
+1016 1016 1016 1016 1016 1016 1016 8 1016 1016 1016 1016
+explain select * from t0 where key1 < 3 or key2 < 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using sort_union(i1,i2); Using where
+select * from t0 where key1 < 3 or key2 < 4;
+key1 key2 key3 key4 key5 key6 key7 key8
+1 1 1 1 1 1 1 1023
+2 2 2 2 2 2 2 1022
+3 3 3 3 3 3 3 1021
+update t0 set key8=123 where key1 < 3 or key2 < 4;
+select * from t0 where key1 < 3 or key2 < 4;
+key1 key2 key3 key4 key5 key6 key7 key8
+1 1 1 1 1 1 1 123
+2 2 2 2 2 2 2 123
+3 3 3 3 3 3 3 123
+delete from t0 where key1 < 3 or key2 < 4;
+select * from t0 where key1 < 3 or key2 < 4;
+key1 key2 key3 key4 key5 key6 key7 key8
+select count(*) from t0;
+count(*)
+1021
+drop table t4;
+create table t4 (a int);
+insert into t4 values (1),(4),(3);
+set @save_join_buffer_size=@@join_buffer_size;
+set join_buffer_size= 4000;
+explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
+where (A.key1 < 500000 or A.key2 < 3)
+and (B.key1 < 500000 or B.key2 < 3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE A index_merge i1,i2 i1,i2 4,4 NULL 1013 Using sort_union(i1,i2); Using where
+1 SIMPLE B index_merge i1,i2 i1,i2 4,4 NULL 1013 Using sort_union(i1,i2); Using where
+select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
+where (A.key1 < 500000 or A.key2 < 3)
+and (B.key1 < 500000 or B.key2 < 3);
+max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+10240
+update t0 set key1=1;
+explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
+where (A.key1 = 1 or A.key2 = 1)
+and (B.key1 = 1 or B.key2 = 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE A index_merge i1,i2 i1,i2 4,4 NULL 1020 Using union(i1,i2); Using where
+1 SIMPLE B index_merge i1,i2 i1,i2 4,4 NULL 1020 Using union(i1,i2); Using where
+select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
+where (A.key1 = 1 or A.key2 = 1)
+and (B.key1 = 1 or B.key2 = 1);
+max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+8194
+alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(200);
+update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
+explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+from t0 as A, t0 as B
+where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
+and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL # Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where
+1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL # Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where
+select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+from t0 as A, t0 as B
+where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
+and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
+max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+8186
+set join_buffer_size= @save_join_buffer_size;
+drop table t0, t1, t2, t3, t4;
diff --git a/mysql-test/r/index_merge_bdb.result b/mysql-test/r/index_merge_bdb.result
new file mode 100644
index 00000000000..3113bf95d3a
--- /dev/null
+++ b/mysql-test/r/index_merge_bdb.result
@@ -0,0 +1,136 @@
+drop table if exists t1;
+create table t1 (
+pk int primary key,
+key1 int,
+key2 int,
+filler char(200),
+filler2 char(200),
+index(key1),
+index(key2)
+) engine=bdb;
+select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 );
+pk key1 key2 filler filler2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+9 9 9 filler-data filler-data-2
+10 10 10 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+5 5 5 filler-data filler-data-2
+6 6 6 filler-data filler-data-2
+7 7 7 filler-data filler-data-2
+8 8 8 filler-data filler-data-2
+set @maxv=1000;
+select * from t1 where
+(pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+or key1=18 or key1=60;
+pk key1 key2 filler filler2
+18 18 18 filler-data filler-data-2
+60 60 60 filler-data filler-data-2
+1 1 1 filler-data filler-data-2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+11 11 11 filler-data filler-data-2
+12 12 12 filler-data filler-data-2
+13 13 13 filler-data filler-data-2
+14 14 14 filler-data filler-data-2
+50 50 50 filler-data filler-data-2
+51 51 51 filler-data filler-data-2
+52 52 52 filler-data filler-data-2
+53 53 53 filler-data filler-data-2
+54 54 54 filler-data filler-data-2
+991 991 991 filler-data filler-data-2
+992 992 992 filler-data filler-data-2
+993 993 993 filler-data filler-data-2
+994 994 994 filler-data filler-data-2
+995 995 995 filler-data filler-data-2
+996 996 996 filler-data filler-data-2
+997 997 997 filler-data filler-data-2
+998 998 998 filler-data filler-data-2
+999 999 999 filler-data filler-data-2
+1000 1000 1000 filler-data filler-data-2
+select * from t1 where
+(pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+or key1 < 3 or key1 > @maxv-11;
+pk key1 key2 filler filler2
+990 990 990 filler-data filler-data-2
+1 1 1 filler-data filler-data-2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+11 11 11 filler-data filler-data-2
+12 12 12 filler-data filler-data-2
+13 13 13 filler-data filler-data-2
+14 14 14 filler-data filler-data-2
+50 50 50 filler-data filler-data-2
+51 51 51 filler-data filler-data-2
+52 52 52 filler-data filler-data-2
+53 53 53 filler-data filler-data-2
+54 54 54 filler-data filler-data-2
+991 991 991 filler-data filler-data-2
+992 992 992 filler-data filler-data-2
+993 993 993 filler-data filler-data-2
+994 994 994 filler-data filler-data-2
+995 995 995 filler-data filler-data-2
+996 996 996 filler-data filler-data-2
+997 997 997 filler-data filler-data-2
+998 998 998 filler-data filler-data-2
+999 999 999 filler-data filler-data-2
+1000 1000 1000 filler-data filler-data-2
+select * from t1 where
+(pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+or
+(key1 < 5) or (key1 > 10 and key1 < 15) or (key1 >= 50 and key1 < 55 ) or (key1 > @maxv-10);
+pk key1 key2 filler filler2
+1 1 1 filler-data filler-data-2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+11 11 11 filler-data filler-data-2
+12 12 12 filler-data filler-data-2
+13 13 13 filler-data filler-data-2
+14 14 14 filler-data filler-data-2
+50 50 50 filler-data filler-data-2
+51 51 51 filler-data filler-data-2
+52 52 52 filler-data filler-data-2
+53 53 53 filler-data filler-data-2
+54 54 54 filler-data filler-data-2
+991 991 991 filler-data filler-data-2
+992 992 992 filler-data filler-data-2
+993 993 993 filler-data filler-data-2
+994 994 994 filler-data filler-data-2
+995 995 995 filler-data filler-data-2
+996 996 996 filler-data filler-data-2
+997 997 997 filler-data filler-data-2
+998 998 998 filler-data filler-data-2
+999 999 999 filler-data filler-data-2
+1000 1000 1000 filler-data filler-data-2
+select * from t1 where
+(pk > 10 and pk < 15) or (pk >= 50 and pk < 55 )
+or
+(key1 < 5) or (key1 > @maxv-10);
+pk key1 key2 filler filler2
+1 1 1 filler-data filler-data-2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+991 991 991 filler-data filler-data-2
+992 992 992 filler-data filler-data-2
+993 993 993 filler-data filler-data-2
+994 994 994 filler-data filler-data-2
+995 995 995 filler-data filler-data-2
+996 996 996 filler-data filler-data-2
+997 997 997 filler-data filler-data-2
+998 998 998 filler-data filler-data-2
+999 999 999 filler-data filler-data-2
+1000 1000 1000 filler-data filler-data-2
+11 11 11 filler-data filler-data-2
+12 12 12 filler-data filler-data-2
+13 13 13 filler-data filler-data-2
+14 14 14 filler-data filler-data-2
+50 50 50 filler-data filler-data-2
+51 51 51 filler-data filler-data-2
+52 52 52 filler-data filler-data-2
+53 53 53 filler-data filler-data-2
+54 54 54 filler-data filler-data-2
+drop table t1;
diff --git a/mysql-test/r/index_merge_innodb.result b/mysql-test/r/index_merge_innodb.result
new file mode 100644
index 00000000000..81e5fa6767d
--- /dev/null
+++ b/mysql-test/r/index_merge_innodb.result
@@ -0,0 +1,205 @@
+drop table if exists t1,t2;
+create table t1
+(
+key1 int not null,
+key2 int not null,
+INDEX i1(key1),
+INDEX i2(key2)
+) engine=innodb;
+explain select * from t1 where key1 < 5 or key2 > 197;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
+select * from t1 where key1 < 5 or key2 > 197;
+key1 key2
+0 200
+1 199
+2 198
+3 197
+4 196
+explain select * from t1 where key1 < 3 or key2 > 195;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
+select * from t1 where key1 < 3 or key2 > 195;
+key1 key2
+0 200
+1 199
+2 198
+3 197
+4 196
+alter table t1 add str1 char (255) not null,
+add zeroval int not null default 0,
+add str2 char (255) not null,
+add str3 char (255) not null;
+update t1 set str1='aaa', str2='bbb', str3=concat(key2, '-', key1 div 2, '_' ,if(key1 mod 2 = 0, 'a', 'A'));
+alter table t1 add primary key (str1, zeroval, str2, str3);
+explain select * from t1 where key1 < 5 or key2 > 197;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
+select * from t1 where key1 < 5 or key2 > 197;
+key1 key2 str1 zeroval str2 str3
+4 196 aaa 0 bbb 196-2_a
+3 197 aaa 0 bbb 197-1_A
+2 198 aaa 0 bbb 198-1_a
+1 199 aaa 0 bbb 199-0_A
+0 200 aaa 0 bbb 200-0_a
+explain select * from t1 where key1 < 3 or key2 > 195;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
+select * from t1 where key1 < 3 or key2 > 195;
+key1 key2 str1 zeroval str2 str3
+4 196 aaa 0 bbb 196-2_a
+3 197 aaa 0 bbb 197-1_A
+2 198 aaa 0 bbb 198-1_a
+1 199 aaa 0 bbb 199-0_A
+0 200 aaa 0 bbb 200-0_a
+drop table t1;
+create table t1 (
+pk integer not null auto_increment primary key,
+key1 integer,
+key2 integer not null,
+filler char (200),
+index (key1),
+index (key2)
+) engine=innodb;
+show warnings;
+Level Code Message
+explain select pk from t1 where key1 = 1 and key2 = 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 5,4 NULL 1 Using intersect(key1,key2); Using where; Using index
+select pk from t1 where key2 = 1 and key1 = 1;
+pk
+26
+27
+select pk from t1 ignore index(key1,key2) where key2 = 1 and key1 = 1;
+pk
+26
+27
+drop table t1;
+create table t1 (
+pk int primary key auto_increment,
+key1a int,
+key2a int,
+key1b int,
+key2b int,
+dummy1 int,
+dummy2 int,
+dummy3 int,
+dummy4 int,
+key3a int,
+key3b int,
+filler1 char (200),
+index i1(key1a, key1b),
+index i2(key2a, key2b),
+index i3(key3a, key3b)
+) engine=innodb;
+create table t2 (a int);
+insert into t2 values (0),(1),(2),(3),(4),(NULL);
+insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
+select A.a, B.a, C.a, D.a, C.a, D.a from t2 A,t2 B,t2 C, t2 D;
+insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
+select key1a, key1b, key2a, key2b, key3a, key3b from t1;
+insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
+select key1a, key1b, key2a, key2b, key3a, key3b from t1;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+select count(*) from t1;
+count(*)
+5184
+explain select count(*) from t1 where
+key1a = 2 and key1b is null and key2a = 2 and key2b is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 3 Using intersect(i1,i2); Using where; Using index
+select count(*) from t1 where
+key1a = 2 and key1b is null and key2a = 2 and key2b is null;
+count(*)
+4
+explain select count(*) from t1 where
+key1a = 2 and key1b is null and key3a = 2 and key3b is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 3 Using intersect(i1,i3); Using where; Using index
+select count(*) from t1 where
+key1a = 2 and key1b is null and key3a = 2 and key3b is null;
+count(*)
+4
+drop table t1,t2;
+create table t1 (
+id1 int,
+id2 date ,
+index idx2 (id1,id2),
+index idx1 (id2)
+) engine = innodb;
+insert into t1 values(1,'20040101'), (2,'20040102');
+select * from t1 where id1 = 1 and id2= '20040101';
+id1 id2
+1 2004-01-01
+drop table t1;
+drop view if exists v1;
+CREATE TABLE t1 (
+`oid` int(11) unsigned NOT NULL auto_increment,
+`fk_bbk_niederlassung` int(11) unsigned NOT NULL,
+`fk_wochentag` int(11) unsigned NOT NULL,
+`uhrzeit_von` time NOT NULL COMMENT 'HH:MM',
+`uhrzeit_bis` time NOT NULL COMMENT 'HH:MM',
+`geloescht` tinyint(4) NOT NULL,
+`version` int(5) NOT NULL,
+PRIMARY KEY (`oid`),
+KEY `fk_bbk_niederlassung` (`fk_bbk_niederlassung`),
+KEY `fk_wochentag` (`fk_wochentag`),
+KEY `ix_version` (`version`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+insert into t1 values
+(1, 38, 1, '08:00:00', '13:00:00', 0, 1),
+(2, 38, 2, '08:00:00', '13:00:00', 0, 1),
+(3, 38, 3, '08:00:00', '13:00:00', 0, 1),
+(4, 38, 4, '08:00:00', '13:00:00', 0, 1),
+(5, 38, 5, '08:00:00', '13:00:00', 0, 1),
+(6, 38, 5, '08:00:00', '13:00:00', 1, 2),
+(7, 38, 3, '08:00:00', '13:00:00', 1, 2),
+(8, 38, 1, '08:00:00', '13:00:00', 1, 2),
+(9, 38, 2, '08:00:00', '13:00:00', 1, 2),
+(10, 38, 4, '08:00:00', '13:00:00', 1, 2),
+(11, 38, 1, '08:00:00', '13:00:00', 0, 3),
+(12, 38, 2, '08:00:00', '13:00:00', 0, 3),
+(13, 38, 3, '08:00:00', '13:00:00', 0, 3),
+(14, 38, 4, '08:00:00', '13:00:00', 0, 3),
+(15, 38, 5, '08:00:00', '13:00:00', 0, 3),
+(16, 38, 4, '08:00:00', '13:00:00', 0, 4),
+(17, 38, 5, '08:00:00', '13:00:00', 0, 4),
+(18, 38, 1, '08:00:00', '13:00:00', 0, 4),
+(19, 38, 2, '08:00:00', '13:00:00', 0, 4),
+(20, 38, 3, '08:00:00', '13:00:00', 0, 4),
+(21, 7, 1, '08:00:00', '13:00:00', 0, 1),
+(22, 7, 2, '08:00:00', '13:00:00', 0, 1),
+(23, 7, 3, '08:00:00', '13:00:00', 0, 1),
+(24, 7, 4, '08:00:00', '13:00:00', 0, 1),
+(25, 7, 5, '08:00:00', '13:00:00', 0, 1);
+create view v1 as
+select
+zeit1.oid AS oid,
+zeit1.fk_bbk_niederlassung AS fk_bbk_niederlassung,
+zeit1.fk_wochentag AS fk_wochentag,
+zeit1.uhrzeit_von AS uhrzeit_von,
+zeit1.uhrzeit_bis AS uhrzeit_bis,
+zeit1.geloescht AS geloescht,
+zeit1.version AS version
+from
+t1 zeit1
+where
+(zeit1.version =
+(select max(zeit2.version) AS `max(version)`
+ from t1 zeit2
+where
+((zeit1.fk_bbk_niederlassung = zeit2.fk_bbk_niederlassung) and
+(zeit1.fk_wochentag = zeit2.fk_wochentag) and
+(zeit1.uhrzeit_von = zeit2.uhrzeit_von) and
+(zeit1.uhrzeit_bis = zeit2.uhrzeit_bis)
+)
+)
+)
+and (zeit1.geloescht = 0);
+select * from v1 where oid = 21;
+oid fk_bbk_niederlassung fk_wochentag uhrzeit_von uhrzeit_bis geloescht version
+21 7 1 08:00:00 13:00:00 0 1
+drop view v1;
+drop table t1;
diff --git a/mysql-test/r/index_merge_innodb2.result b/mysql-test/r/index_merge_innodb2.result
new file mode 100644
index 00000000000..91dd989fe90
--- /dev/null
+++ b/mysql-test/r/index_merge_innodb2.result
@@ -0,0 +1,136 @@
+drop table if exists t1;
+create table t1 (
+pk int primary key,
+key1 int,
+key2 int,
+filler char(200),
+filler2 char(200),
+index(key1),
+index(key2)
+) engine=innodb;
+select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 );
+pk key1 key2 filler filler2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+9 9 9 filler-data filler-data-2
+10 10 10 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+5 5 5 filler-data filler-data-2
+6 6 6 filler-data filler-data-2
+7 7 7 filler-data filler-data-2
+8 8 8 filler-data filler-data-2
+set @maxv=1000;
+select * from t1 where
+(pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+or key1=18 or key1=60;
+pk key1 key2 filler filler2
+18 18 18 filler-data filler-data-2
+60 60 60 filler-data filler-data-2
+1 1 1 filler-data filler-data-2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+11 11 11 filler-data filler-data-2
+12 12 12 filler-data filler-data-2
+13 13 13 filler-data filler-data-2
+14 14 14 filler-data filler-data-2
+50 50 50 filler-data filler-data-2
+51 51 51 filler-data filler-data-2
+52 52 52 filler-data filler-data-2
+53 53 53 filler-data filler-data-2
+54 54 54 filler-data filler-data-2
+991 991 991 filler-data filler-data-2
+992 992 992 filler-data filler-data-2
+993 993 993 filler-data filler-data-2
+994 994 994 filler-data filler-data-2
+995 995 995 filler-data filler-data-2
+996 996 996 filler-data filler-data-2
+997 997 997 filler-data filler-data-2
+998 998 998 filler-data filler-data-2
+999 999 999 filler-data filler-data-2
+1000 1000 1000 filler-data filler-data-2
+select * from t1 where
+(pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+or key1 < 3 or key1 > @maxv-11;
+pk key1 key2 filler filler2
+990 990 990 filler-data filler-data-2
+1 1 1 filler-data filler-data-2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+11 11 11 filler-data filler-data-2
+12 12 12 filler-data filler-data-2
+13 13 13 filler-data filler-data-2
+14 14 14 filler-data filler-data-2
+50 50 50 filler-data filler-data-2
+51 51 51 filler-data filler-data-2
+52 52 52 filler-data filler-data-2
+53 53 53 filler-data filler-data-2
+54 54 54 filler-data filler-data-2
+991 991 991 filler-data filler-data-2
+992 992 992 filler-data filler-data-2
+993 993 993 filler-data filler-data-2
+994 994 994 filler-data filler-data-2
+995 995 995 filler-data filler-data-2
+996 996 996 filler-data filler-data-2
+997 997 997 filler-data filler-data-2
+998 998 998 filler-data filler-data-2
+999 999 999 filler-data filler-data-2
+1000 1000 1000 filler-data filler-data-2
+select * from t1 where
+(pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+or
+(key1 < 5) or (key1 > 10 and key1 < 15) or (key1 >= 50 and key1 < 55 ) or (key1 > @maxv-10);
+pk key1 key2 filler filler2
+1 1 1 filler-data filler-data-2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+11 11 11 filler-data filler-data-2
+12 12 12 filler-data filler-data-2
+13 13 13 filler-data filler-data-2
+14 14 14 filler-data filler-data-2
+50 50 50 filler-data filler-data-2
+51 51 51 filler-data filler-data-2
+52 52 52 filler-data filler-data-2
+53 53 53 filler-data filler-data-2
+54 54 54 filler-data filler-data-2
+991 991 991 filler-data filler-data-2
+992 992 992 filler-data filler-data-2
+993 993 993 filler-data filler-data-2
+994 994 994 filler-data filler-data-2
+995 995 995 filler-data filler-data-2
+996 996 996 filler-data filler-data-2
+997 997 997 filler-data filler-data-2
+998 998 998 filler-data filler-data-2
+999 999 999 filler-data filler-data-2
+1000 1000 1000 filler-data filler-data-2
+select * from t1 where
+(pk > 10 and pk < 15) or (pk >= 50 and pk < 55 )
+or
+(key1 < 5) or (key1 > @maxv-10);
+pk key1 key2 filler filler2
+1 1 1 filler-data filler-data-2
+2 2 2 filler-data filler-data-2
+3 3 3 filler-data filler-data-2
+4 4 4 filler-data filler-data-2
+991 991 991 filler-data filler-data-2
+992 992 992 filler-data filler-data-2
+993 993 993 filler-data filler-data-2
+994 994 994 filler-data filler-data-2
+995 995 995 filler-data filler-data-2
+996 996 996 filler-data filler-data-2
+997 997 997 filler-data filler-data-2
+998 998 998 filler-data filler-data-2
+999 999 999 filler-data filler-data-2
+1000 1000 1000 filler-data filler-data-2
+11 11 11 filler-data filler-data-2
+12 12 12 filler-data filler-data-2
+13 13 13 filler-data filler-data-2
+14 14 14 filler-data filler-data-2
+50 50 50 filler-data filler-data-2
+51 51 51 filler-data filler-data-2
+52 52 52 filler-data filler-data-2
+53 53 53 filler-data filler-data-2
+54 54 54 filler-data filler-data-2
+drop table t1;
diff --git a/mysql-test/r/index_merge_ror.result b/mysql-test/r/index_merge_ror.result
new file mode 100644
index 00000000000..69cd11d1dbf
--- /dev/null
+++ b/mysql-test/r/index_merge_ror.result
@@ -0,0 +1,196 @@
+drop table if exists t0,t1,t2;
+select count(*) from t1;
+count(*)
+64801
+explain select key1,key2 from t1 where key1=100 and key2=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 58 Using intersect(key1,key2); Using where; Using index
+select key1,key2 from t1 where key1=100 and key2=100;
+key1 key2
+100 100
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 154 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+key1 key2 key3 key4 filler1
+100 100 100 100 key1-key2-key3-key4
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, -1, -1, 'key1-key2');
+insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 100, 100, 'key4-key3');
+explain select key1,key2,filler1 from t1 where key1=100 and key2=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 58 Using intersect(key1,key2); Using where
+select key1,key2,filler1 from t1 where key1=100 and key2=100;
+key1 key2 filler1
+100 100 key1-key2-key3-key4
+100 100 key1-key2
+explain select key1,key2 from t1 where key1=100 and key2=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 58 Using intersect(key1,key2); Using where; Using index
+select key1,key2 from t1 where key1=100 and key2=100;
+key1 key2
+100 100
+100 100
+explain select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 154 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
+select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+key1 key2 key3 key4
+100 100 100 100
+100 100 -1 -1
+-1 -1 100 100
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 154 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+key1 key2 key3 key4 filler1
+100 100 100 100 key1-key2-key3-key4
+100 100 -1 -1 key1-key2
+-1 -1 100 100 key4-key3
+explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 2 Using intersect(key1,key2,key3); Using where; Using index
+select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
+key1 key2 key3
+100 100 100
+insert into t1 (key1,key2,key3,key4,filler1) values (101,101,101,101, 'key1234-101');
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 83 Using union(intersect(key1,key2),key3); Using where
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
+key1 key2 key3 key4 filler1
+100 100 100 100 key1-key2-key3-key4
+100 100 -1 -1 key1-key2
+101 101 101 101 key1234-101
+select key1,key2, filler1 from t1 where key1=100 and key2=100;
+key1 key2 filler1
+100 100 key1-key2-key3-key4
+100 100 key1-key2
+update t1 set filler1='to be deleted' where key1=100 and key2=100;
+update t1 set key1=200,key2=200 where key1=100 and key2=100;
+delete from t1 where key1=200 and key2=200;
+select key1,key2,filler1 from t1 where key2=100 and key2=200;
+key1 key2 filler1
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 152 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+key1 key2 key3 key4 filler1
+-1 -1 100 100 key4-key3
+delete from t1 where key3=100 and key4=100;
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 152 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+key1 key2 key3 key4 filler1
+explain select key1,key2 from t1 where key1=100 and key2=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 57 Using intersect(key1,key2); Using where; Using index
+select key1,key2 from t1 where key1=100 and key2=100;
+key1 key2
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-1');
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-2');
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-3');
+explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 136 Using union(key3,intersect(key1,key2),key4); Using where
+select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+key1 key2 key3 key4 filler1
+100 100 200 200 key1-key2-key3-key4-3
+100 100 200 200 key1-key2-key3-key4-2
+100 100 200 200 key1-key2-key3-key4-1
+insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, -1, 200,'key4');
+explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 146 Using union(key3,intersect(key1,key2),key4); Using where
+select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+key1 key2 key3 key4 filler1
+100 100 200 200 key1-key2-key3-key4-3
+100 100 200 200 key1-key2-key3-key4-2
+100 100 200 200 key1-key2-key3-key4-1
+-1 -1 -1 200 key4
+insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 200, -1,'key3');
+explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 156 Using union(key3,intersect(key1,key2),key4); Using where
+select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+key1 key2 key3 key4 filler1
+100 100 200 200 key1-key2-key3-key4-3
+100 100 200 200 key1-key2-key3-key4-2
+100 100 200 200 key1-key2-key3-key4-1
+-1 -1 -1 200 key4
+-1 -1 200 -1 key3
+explain select * from t1 where st_a=1 and st_b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b st_a,st_b 4,4 NULL 2637 Using intersect(st_a,st_b); Using where
+explain select st_a,st_b from t1 where st_a=1 and st_b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b st_a,st_b 4,4 NULL 2637 Using intersect(st_a,st_b); Using where; Using index
+explain select st_a from t1 ignore index (st_a) where st_a=1 and st_b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,stb_swt1a_2b,stb_swt1b,st_b st_b 4 const 15093 Using where
+explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a sta_swt21a 12 const,const,const 971
+explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref stb_swt1a_2b,stb_swt1b,st_b stb_swt1a_2b 8 const,const 3879 Using where
+explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt12a,stb_swt1a_2b 12,12 NULL 44 Using intersect(sta_swt12a,stb_swt1a_2b); Using where
+explain select * from t1 ignore index (sta_swt21a, stb_swt1a_2b)
+where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,st_a,stb_swt1b,st_b sta_swt12a,stb_swt1b 12,8 NULL 44 Using intersect(sta_swt12a,stb_swt1b); Using where
+explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b)
+where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt1a,sta_swt2a,st_a,stb_swt1b,st_b sta_swt1a,sta_swt2a,stb_swt1b 8,8,8 NULL 43 Using intersect(sta_swt1a,sta_swt2a,stb_swt1b); Using where
+explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b, stb_swt1b)
+where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt1a,sta_swt2a,st_a,st_b sta_swt1a,sta_swt2a,st_b 8,8,4 NULL 168 Using intersect(sta_swt1a,sta_swt2a,st_b); Using where
+explain select * from t1
+where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt12a,stb_swt1a_2b 12,12 NULL 44 Using intersect(sta_swt12a,stb_swt1a_2b); Using where
+explain select * from t1
+where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 174 Using intersect(sta_swt1a,stb_swt1b); Using where
+explain select st_a from t1
+where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 174 Using intersect(sta_swt1a,stb_swt1b); Using where; Using index
+explain select st_a from t1
+where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 174 Using intersect(sta_swt1a,stb_swt1b); Using where; Using index
+drop table t0,t1;
+create table t2 (
+a char(10),
+b char(10),
+filler1 char(255),
+filler2 char(255),
+key(a(5)),
+key(b(5))
+);
+select count(a) from t2 where a='BBBBBBBB';
+count(a)
+4
+select count(a) from t2 where b='BBBBBBBB';
+count(a)
+4
+expla_or_bin select count(a_or_b) from t2 where a_or_b='AAAAAAAA' a_or_bnd a_or_b='AAAAAAAA';
+id select_type ta_or_ba_or_ble type possia_or_ble_keys key key_len ref rows Extra_or_b
+1 SIMPLE t2 ref a_or_b,a_or_b a_or_b 6 const 4 Using where
+select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
+count(a)
+4
+select count(a) from t2 ignore index(a,b) where a='AAAAAAAA' and b='AAAAAAAA';
+count(a)
+4
+insert into t2 values ('ab', 'ab', 'uh', 'oh');
+explain select a from t2 where a='ab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref a a 6 const 1 Using where
+drop table t2;
diff --git a/mysql-test/r/index_merge_ror_cpk.result b/mysql-test/r/index_merge_ror_cpk.result
new file mode 100644
index 00000000000..79bb1297abf
--- /dev/null
+++ b/mysql-test/r/index_merge_ror_cpk.result
@@ -0,0 +1,120 @@
+drop table if exists t1;
+create table t1
+(
+pk1 int not null,
+pk2 int not null,
+key1 int not null,
+key2 int not null,
+pktail1ok int not null,
+pktail2ok int not null,
+pktail3bad int not null,
+pktail4bad int not null,
+pktail5bad int not null,
+pk2copy int not null,
+badkey int not null,
+filler1 char (200),
+filler2 char (200),
+key (key1),
+key (key2),
+/* keys with tails from CPK members */
+key (pktail1ok, pk1),
+key (pktail2ok, pk1, pk2),
+key (pktail3bad, pk2, pk1),
+key (pktail4bad, pk1, pk2copy),
+key (pktail5bad, pk1, pk2, pk2copy),
+primary key (pk1, pk2)
+) engine=innodb;
+explain select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,key1 PRIMARY 8 NULL 9 Using where
+select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
+pk1 pk2 key1 key2 pktail1ok pktail2ok pktail3bad pktail4bad pktail5bad pk2copy badkey filler1 filler2
+1 10 0 0 0 0 0 0 0 10 0 filler-data-10 filler2
+1 11 0 0 0 0 0 0 0 11 0 filler-data-11 filler2
+1 12 0 0 0 0 0 0 0 12 0 filler-data-12 filler2
+1 13 0 0 0 0 0 0 0 13 0 filler-data-13 filler2
+1 14 0 0 0 0 0 0 0 14 0 filler-data-14 filler2
+1 15 0 0 0 0 0 0 0 15 0 filler-data-15 filler2
+1 16 0 0 0 0 0 0 0 16 0 filler-data-16 filler2
+1 17 0 0 0 0 0 0 0 17 0 filler-data-17 filler2
+1 18 0 0 0 0 0 0 0 18 0 filler-data-18 filler2
+1 19 0 0 0 0 0 0 0 19 0 filler-data-19 filler2
+explain select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 4,4 NULL 1 Using intersect(key1,key2); Using where; Using index
+select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
+pk1 pk2
+95 50
+95 51
+95 52
+95 53
+95 54
+95 55
+95 56
+95 57
+95 58
+95 59
+explain select * from t1 where badkey=1 and key1=10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref key1 key1 4 const 100 Using where
+explain select * from t1 where pk1 < 7500 and key1 = 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge PRIMARY,key1 key1,PRIMARY 4,4 NULL ROWS Using intersect(key1,PRIMARY); Using where
+explain select * from t1 where pktail1ok=1 and key1=10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,pktail1ok key1,pktail1ok 4,4 NULL 1 Using intersect(key1,pktail1ok); Using where
+explain select * from t1 where pktail2ok=1 and key1=10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,pktail2ok key1,pktail2ok 4,4 NULL 1 Using intersect(key1,pktail2ok); Using where
+select ' The following is actually a deficiency, it uses sort_union currently:' as 'note:';
+note:
+ The following is actually a deficiency, it uses sort_union currently:
+explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge PRIMARY,key1,pktail2ok pktail2ok,key1 8,4 NULL 199 Using sort_union(pktail2ok,key1); Using where
+explain select * from t1 where pktail3bad=1 and key1=10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref key1,pktail3bad key1 4 const 100 Using where
+explain select * from t1 where pktail4bad=1 and key1=10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref key1,pktail4bad key1 4 const 100 Using where
+explain select * from t1 where pktail5bad=1 and key1=10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref key1,pktail5bad key1 4 const 100 Using where
+explain select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 4,4 NULL 1 Using intersect(key1,key2); Using where; Using index
+select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
+pk1 pk2 key1 key2
+95 50 10 10
+95 51 10 10
+95 52 10 10
+95 53 10 10
+95 54 10 10
+95 55 10 10
+95 56 10 10
+95 57 10 10
+95 58 10 10
+95 59 10 10
+drop table t1;
+create table t1
+(
+RUNID varchar(22),
+SUBMITNR varchar(5),
+ORDERNR char(1) ,
+PROGRAMM varchar(8),
+TESTID varchar(4),
+UCCHECK char(1),
+ETEXT varchar(80),
+ETEXT_TYPE char(1),
+INFO char(1),
+SEVERITY tinyint(3),
+TADIRFLAG char(1),
+PRIMARY KEY (RUNID,SUBMITNR,ORDERNR,PROGRAMM,TESTID,UCCHECK),
+KEY `TVERM~KEY` (PROGRAMM,TESTID,UCCHECK)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+update t1 set `ETEXT` = '', `ETEXT_TYPE`='', `INFO`='', `SEVERITY`='', `TADIRFLAG`=''
+WHERE
+`RUNID`= '' AND `SUBMITNR`= '' AND `ORDERNR`='' AND `PROGRAMM`='' AND
+`TESTID`='' AND `UCCHECK`='';
+drop table t1;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
new file mode 100644
index 00000000000..1407c17f623
--- /dev/null
+++ b/mysql-test/r/information_schema.result
@@ -0,0 +1,1014 @@
+DROP TABLE IF EXISTS t0,t1,t2,t3,t5;
+show variables where variable_name like "skip_show_database";
+Variable_name Value
+skip_show_database OFF
+grant select, update, execute on test.* to mysqltest_2@localhost;
+grant select, update on test.* to mysqltest_1@localhost;
+create user mysqltest_3@localhost;
+create user mysqltest_3;
+select * from information_schema.SCHEMATA where schema_name > 'm';
+CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME SQL_PATH
+NULL mysql latin1 latin1_swedish_ci NULL
+NULL test latin1 latin1_swedish_ci NULL
+select schema_name from information_schema.schemata;
+schema_name
+information_schema
+mysql
+test
+show databases like 't%';
+Database (t%)
+test
+show databases;
+Database
+information_schema
+mysql
+test
+show databases where `database` = 't%';
+Database
+create database mysqltest;
+create table mysqltest.t1(a int, b VARCHAR(30), KEY string_data (b));
+create table test.t2(a int);
+create table t3(a int, KEY a_data (a));
+create table mysqltest.t4(a int);
+create table t5 (id int auto_increment primary key);
+insert into t5 values (10);
+create view v1 (c) as select table_name from information_schema.TABLES;
+select * from v1;
+c
+CHARACTER_SETS
+COLLATIONS
+COLLATION_CHARACTER_SET_APPLICABILITY
+COLUMNS
+COLUMN_PRIVILEGES
+KEY_COLUMN_USAGE
+ROUTINES
+SCHEMATA
+SCHEMA_PRIVILEGES
+STATISTICS
+TABLES
+TABLE_CONSTRAINTS
+TABLE_PRIVILEGES
+TRIGGERS
+VIEWS
+USER_PRIVILEGES
+columns_priv
+db
+func
+help_category
+help_keyword
+help_relation
+help_topic
+host
+proc
+procs_priv
+tables_priv
+time_zone
+time_zone_leap_second
+time_zone_name
+time_zone_transition
+time_zone_transition_type
+user
+t1
+t4
+t2
+t3
+t5
+v1
+select c,table_name from v1
+inner join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+c table_name
+TABLES TABLES
+TABLE_CONSTRAINTS TABLE_CONSTRAINTS
+TABLE_PRIVILEGES TABLE_PRIVILEGES
+TRIGGERS TRIGGERS
+tables_priv tables_priv
+time_zone time_zone
+time_zone_leap_second time_zone_leap_second
+time_zone_name time_zone_name
+time_zone_transition time_zone_transition
+time_zone_transition_type time_zone_transition_type
+t1 t1
+t4 t4
+t2 t2
+t3 t3
+t5 t5
+select c,table_name from v1
+left join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+c table_name
+TABLES TABLES
+TABLE_CONSTRAINTS TABLE_CONSTRAINTS
+TABLE_PRIVILEGES TABLE_PRIVILEGES
+TRIGGERS TRIGGERS
+tables_priv tables_priv
+time_zone time_zone
+time_zone_leap_second time_zone_leap_second
+time_zone_name time_zone_name
+time_zone_transition time_zone_transition
+time_zone_transition_type time_zone_transition_type
+t1 t1
+t4 t4
+t2 t2
+t3 t3
+t5 t5
+select c, v2.table_name from v1
+right join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+c table_name
+TABLES TABLES
+TABLE_CONSTRAINTS TABLE_CONSTRAINTS
+TABLE_PRIVILEGES TABLE_PRIVILEGES
+TRIGGERS TRIGGERS
+tables_priv tables_priv
+time_zone time_zone
+time_zone_leap_second time_zone_leap_second
+time_zone_name time_zone_name
+time_zone_transition time_zone_transition
+time_zone_transition_type time_zone_transition_type
+t1 t1
+t4 t4
+t2 t2
+t3 t3
+t5 t5
+select table_name from information_schema.TABLES
+where table_schema = "mysqltest" and table_name like "t%";
+table_name
+t1
+t4
+select * from information_schema.STATISTICS where TABLE_SCHEMA = "mysqltest";
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT
+NULL mysqltest t1 1 mysqltest string_data 1 b A NULL NULL NULL YES BTREE
+show keys from t3 where Key_name = "a_data";
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t3 1 a_data 1 a A NULL NULL NULL YES BTREE
+show tables like 't%';
+Tables_in_test (t%)
+t2
+t3
+t5
+show table status;
+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 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL
+t3 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL
+t5 MyISAM 10 Fixed 1 7 7 # 2048 0 11 # # NULL latin1_swedish_ci NULL
+v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW
+show full columns from t3 like "a%";
+Field Type Collation Null Key Default Extra Privileges Comment
+a int(11) NULL YES MUL NULL select,insert,update,references
+show full columns from mysql.db like "Insert%";
+Field Type Collation Null Key Default Extra Privileges Comment
+Insert_priv enum('N','Y') utf8_general_ci NO N select,insert,update,references
+show full columns from v1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c varchar(64) utf8_general_ci NO select,insert,update,references
+select * from information_schema.COLUMNS where table_name="t1"
+and column_name= "a";
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT
+NULL mysqltest t1 a 1 NULL YES int NULL NULL 10 0 NULL NULL int(11) select,insert,update,references
+show columns from mysqltest.t1 where field like "%a%";
+Field Type Null Key Default Extra
+a int(11) YES NULL
+create view mysqltest.v1 (c) as select a from mysqltest.t1;
+grant select (a) on mysqltest.t1 to mysqltest_2@localhost;
+grant select on mysqltest.v1 to mysqltest_3;
+select table_name, column_name, privileges from information_schema.columns
+where table_schema = 'mysqltest' and table_name = 't1';
+table_name column_name privileges
+t1 a select
+show columns from mysqltest.t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b varchar(30) YES MUL NULL
+select table_name, column_name, privileges from information_schema.columns
+where table_schema = 'mysqltest' and table_name = 'v1';
+table_name column_name privileges
+v1 c select
+drop view v1, mysqltest.v1;
+drop tables mysqltest.t4, mysqltest.t1, t2, t3, t5;
+drop database mysqltest;
+select * from information_schema.CHARACTER_SETS
+where CHARACTER_SET_NAME like 'latin1%';
+CHARACTER_SET_NAME DEFAULT_COLLATE_NAME DESCRIPTION MAXLEN
+latin1 latin1_swedish_ci cp1252 West European 1
+SHOW CHARACTER SET LIKE 'latin1%';
+Charset Description Default collation Maxlen
+latin1 cp1252 West European latin1_swedish_ci 1
+SHOW CHARACTER SET WHERE charset like 'latin1%';
+Charset Description Default collation Maxlen
+latin1 cp1252 West European latin1_swedish_ci 1
+select * from information_schema.COLLATIONS
+where COLLATION_NAME like 'latin1%';
+COLLATION_NAME CHARACTER_SET_NAME ID IS_DEFAULT IS_COMPILED SORTLEN
+latin1_german1_ci latin1 5 0
+latin1_swedish_ci latin1 8 Yes Yes 1
+latin1_danish_ci latin1 15 0
+latin1_german2_ci latin1 31 Yes 2
+latin1_bin latin1 47 Yes 1
+latin1_general_ci latin1 48 0
+latin1_general_cs latin1 49 0
+latin1_spanish_ci latin1 94 0
+SHOW COLLATION LIKE 'latin1%';
+Collation Charset Id Default Compiled Sortlen
+latin1_german1_ci latin1 5 0
+latin1_swedish_ci latin1 8 Yes Yes 1
+latin1_danish_ci latin1 15 0
+latin1_german2_ci latin1 31 Yes 2
+latin1_bin latin1 47 Yes 1
+latin1_general_ci latin1 48 0
+latin1_general_cs latin1 49 0
+latin1_spanish_ci latin1 94 0
+SHOW COLLATION WHERE collation like 'latin1%';
+Collation Charset Id Default Compiled Sortlen
+latin1_german1_ci latin1 5 0
+latin1_swedish_ci latin1 8 Yes Yes 1
+latin1_danish_ci latin1 15 0
+latin1_german2_ci latin1 31 Yes 2
+latin1_bin latin1 47 Yes 1
+latin1_general_ci latin1 48 0
+latin1_general_cs latin1 49 0
+latin1_spanish_ci latin1 94 0
+select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY
+where COLLATION_NAME like 'latin1%';
+COLLATION_NAME CHARACTER_SET_NAME
+latin1_german1_ci latin1
+latin1_swedish_ci latin1
+latin1_danish_ci latin1
+latin1_german2_ci latin1
+latin1_bin latin1
+latin1_general_ci latin1
+latin1_general_cs latin1
+latin1_spanish_ci latin1
+drop procedure if exists sel2;
+drop function if exists sub1;
+drop function if exists sub2;
+create function sub1(i int) returns int
+return i+1;
+create procedure sel2()
+begin
+select * from t1;
+select * from t2;
+end|
+select parameter_style, sql_data_access, dtd_identifier
+from information_schema.routines;
+parameter_style sql_data_access dtd_identifier
+SQL CONTAINS SQL NULL
+SQL CONTAINS SQL int(11)
+show procedure status;
+Db Name Type Definer Modified Created Security_type Comment
+test sel2 PROCEDURE root@localhost # # DEFINER
+show function status;
+Db Name Type Definer Modified Created Security_type Comment
+test sub1 FUNCTION root@localhost # # DEFINER
+select a.ROUTINE_NAME from information_schema.ROUTINES a,
+information_schema.SCHEMATA b where
+a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
+ROUTINE_NAME
+sel2
+sub1
+explain select a.ROUTINE_NAME from information_schema.ROUTINES a,
+information_schema.SCHEMATA b where
+a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE # ALL NULL NULL NULL NULL 2
+1 SIMPLE # ALL NULL NULL NULL NULL 2 Using where
+select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a,
+mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1;
+ROUTINE_NAME name
+sel2 sel2
+sub1 sub1
+select count(*) from information_schema.ROUTINES;
+count(*)
+2
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+ROUTINE_NAME ROUTINE_DEFINITION
+show create function sub1;
+ERROR 42000: FUNCTION sub1 does not exist
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+ROUTINE_NAME ROUTINE_DEFINITION
+sel2
+sub1
+grant all privileges on test.* to mysqltest_1@localhost;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+ROUTINE_NAME ROUTINE_DEFINITION
+sel2
+sub1
+create function sub2(i int) returns int
+return i+1;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+ROUTINE_NAME ROUTINE_DEFINITION
+sel2
+sub1
+sub2 return i+1
+show create procedure sel2;
+Procedure sql_mode Create Procedure
+sel2
+show create function sub1;
+Function sql_mode Create Function
+sub1
+show create function sub2;
+Function sql_mode Create Function
+sub2 CREATE FUNCTION `sub2`(i int) RETURNS int(11)
+return i+1
+show function status like "sub2";
+Db Name Type Definer Modified Created Security_type Comment
+test sub2 FUNCTION mysqltest_1@localhost # # DEFINER
+drop function sub2;
+show create procedure sel2;
+Procedure sql_mode Create Procedure
+sel2 CREATE PROCEDURE `sel2`()
+begin
+select * from t1;
+select * from t2;
+end
+create view v0 (c) as select schema_name from information_schema.schemata;
+select * from v0;
+c
+information_schema
+mysql
+test
+explain select * from v0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY # ALL NULL NULL NULL NULL 2
+create view v1 (c) as select table_name from information_schema.tables
+where table_name="v1";
+select * from v1;
+c
+v1
+create view v2 (c) as select column_name from information_schema.columns
+where table_name="v2";
+select * from v2;
+c
+c
+create view v3 (c) as select CHARACTER_SET_NAME from information_schema.character_sets
+where CHARACTER_SET_NAME like "latin1%";
+select * from v3;
+c
+latin1
+create view v4 (c) as select COLLATION_NAME from information_schema.collations
+where COLLATION_NAME like "latin1%";
+select * from v4;
+c
+latin1_german1_ci
+latin1_swedish_ci
+latin1_danish_ci
+latin1_german2_ci
+latin1_bin
+latin1_general_ci
+latin1_general_cs
+latin1_spanish_ci
+show keys from v4;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+select * from information_schema.views where TABLE_NAME like "v%";
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE DEFINER SECURITY_TYPE
+NULL test v0 select sql_no_cache `schemata`.`SCHEMA_NAME` AS `c` from `information_schema`.`schemata` NONE NO root@localhost DEFINER
+NULL test v1 select sql_no_cache `tables`.`TABLE_NAME` AS `c` from `information_schema`.`tables` where (`tables`.`TABLE_NAME` = _utf8'v1') NONE NO root@localhost DEFINER
+NULL test v2 select sql_no_cache `columns`.`COLUMN_NAME` AS `c` from `information_schema`.`columns` where (`columns`.`TABLE_NAME` = _utf8'v2') NONE NO root@localhost DEFINER
+NULL test v3 select sql_no_cache `character_sets`.`CHARACTER_SET_NAME` AS `c` from `information_schema`.`character_sets` where (`character_sets`.`CHARACTER_SET_NAME` like _utf8'latin1%') NONE NO root@localhost DEFINER
+NULL test v4 select sql_no_cache `collations`.`COLLATION_NAME` AS `c` from `information_schema`.`collations` where (`collations`.`COLLATION_NAME` like _utf8'latin1%') NONE NO root@localhost DEFINER
+drop view v0, v1, v2, v3, v4;
+create table t1 (a int);
+grant select,update,insert on t1 to mysqltest_1@localhost;
+grant select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
+grant all on test.* to mysqltest_1@localhost with grant option;
+select * from information_schema.USER_PRIVILEGES where grantee like '%mysqltest_1%';
+GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
+'mysqltest_1'@'localhost' NULL USAGE NO
+select * from information_schema.SCHEMA_PRIVILEGES where grantee like '%mysqltest_1%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
+'mysqltest_1'@'localhost' NULL test SELECT YES
+'mysqltest_1'@'localhost' NULL test INSERT YES
+'mysqltest_1'@'localhost' NULL test UPDATE YES
+'mysqltest_1'@'localhost' NULL test DELETE YES
+'mysqltest_1'@'localhost' NULL test CREATE YES
+'mysqltest_1'@'localhost' NULL test DROP YES
+'mysqltest_1'@'localhost' NULL test REFERENCES YES
+'mysqltest_1'@'localhost' NULL test INDEX YES
+'mysqltest_1'@'localhost' NULL test ALTER YES
+'mysqltest_1'@'localhost' NULL test CREATE TEMPORARY TABLES YES
+'mysqltest_1'@'localhost' NULL test LOCK TABLES YES
+'mysqltest_1'@'localhost' NULL test EXECUTE YES
+'mysqltest_1'@'localhost' NULL test CREATE VIEW YES
+'mysqltest_1'@'localhost' NULL test SHOW VIEW YES
+'mysqltest_1'@'localhost' NULL test CREATE ROUTINE YES
+'mysqltest_1'@'localhost' NULL test ALTER ROUTINE YES
+select * from information_schema.TABLE_PRIVILEGES where grantee like '%mysqltest_1%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'mysqltest_1'@'localhost' NULL test t1 SELECT NO
+'mysqltest_1'@'localhost' NULL test t1 INSERT NO
+'mysqltest_1'@'localhost' NULL test t1 UPDATE NO
+select * from information_schema.COLUMN_PRIVILEGES where grantee like '%mysqltest_1%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'mysqltest_1'@'localhost' NULL test t1 a SELECT NO
+'mysqltest_1'@'localhost' NULL test t1 a INSERT NO
+'mysqltest_1'@'localhost' NULL test t1 a UPDATE NO
+'mysqltest_1'@'localhost' NULL test t1 a REFERENCES NO
+delete from mysql.user where user like 'mysqltest%';
+delete from mysql.db where user like 'mysqltest%';
+delete from mysql.tables_priv where user like 'mysqltest%';
+delete from mysql.columns_priv where user like 'mysqltest%';
+flush privileges;
+drop table t1;
+create table t1 (a int null, primary key(a));
+alter table t1 add constraint constraint_1 unique (a);
+alter table t1 add constraint unique key_1(a);
+alter table t1 add constraint constraint_2 unique key_2(a);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ PRIMARY KEY (`a`),
+ UNIQUE KEY `constraint_1` (`a`),
+ UNIQUE KEY `key_1` (`a`),
+ UNIQUE KEY `key_2` (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_SCHEMA= "test";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE
+NULL test PRIMARY test t1 PRIMARY KEY
+NULL test constraint_1 test t1 UNIQUE
+NULL test key_1 test t1 UNIQUE
+NULL test key_2 test t1 UNIQUE
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_SCHEMA= "test";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME
+NULL test PRIMARY NULL test t1 a 1 NULL NULL NULL NULL
+NULL test constraint_1 NULL test t1 a 1 NULL NULL NULL NULL
+NULL test key_1 NULL test t1 a 1 NULL NULL NULL NULL
+NULL test key_2 NULL test t1 a 1 NULL NULL NULL NULL
+select table_name from information_schema.TABLES where table_schema like "test%";
+table_name
+t1
+select table_name,column_name from information_schema.COLUMNS where table_schema like "test%";
+table_name column_name
+t1 a
+select ROUTINE_NAME from information_schema.ROUTINES;
+ROUTINE_NAME
+sel2
+sub1
+delete from mysql.user where user='mysqltest_1';
+drop table t1;
+drop procedure sel2;
+drop function sub1;
+create table t1(a int);
+create view v1 (c) as select a from t1 with check option;
+create view v2 (c) as select a from t1 WITH LOCAL CHECK OPTION;
+create view v3 (c) as select a from t1 WITH CASCADED CHECK OPTION;
+select * from information_schema.views;
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE DEFINER SECURITY_TYPE
+NULL test v1 select `test`.`t1`.`a` AS `c` from `test`.`t1` CASCADED YES root@localhost DEFINER
+NULL test v2 select `test`.`t1`.`a` AS `c` from `test`.`t1` LOCAL YES root@localhost DEFINER
+NULL test v3 select `test`.`t1`.`a` AS `c` from `test`.`t1` CASCADED YES root@localhost DEFINER
+grant select (a) on test.t1 to joe@localhost with grant option;
+select * from INFORMATION_SCHEMA.COLUMN_PRIVILEGES;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'joe'@'localhost' NULL test t1 a SELECT YES
+select * from INFORMATION_SCHEMA.TABLE_PRIVILEGES;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+drop view v1, v2, v3;
+drop table t1;
+delete from mysql.user where user='joe';
+delete from mysql.db where user='joe';
+delete from mysql.tables_priv where user='joe';
+delete from mysql.columns_priv where user='joe';
+flush privileges;
+create table t1 (a int not null auto_increment,b int, primary key (a));
+insert into t1 values (1,1),(NULL,3),(NULL,4);
+select AUTO_INCREMENT from information_schema.tables where table_name = 't1';
+AUTO_INCREMENT
+4
+drop table t1;
+create table t1 (s1 int);
+insert into t1 values (0),(9),(0);
+select s1 from t1 where s1 in (select version from
+information_schema.tables) union select version from
+information_schema.tables;
+s1
+0
+10
+drop table t1;
+SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
+Table Create Table
+CHARACTER_SETS CREATE TEMPORARY TABLE `CHARACTER_SETS` (
+ `CHARACTER_SET_NAME` varchar(64) NOT NULL default '',
+ `DEFAULT_COLLATE_NAME` varchar(64) NOT NULL default '',
+ `DESCRIPTION` varchar(60) NOT NULL default '',
+ `MAXLEN` bigint(3) NOT NULL default '0'
+) ENGINE=MEMORY DEFAULT CHARSET=utf8
+set names latin2;
+SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
+Table Create Table
+CHARACTER_SETS CREATE TEMPORARY TABLE `CHARACTER_SETS` (
+ `CHARACTER_SET_NAME` varchar(64) NOT NULL default '',
+ `DEFAULT_COLLATE_NAME` varchar(64) NOT NULL default '',
+ `DESCRIPTION` varchar(60) NOT NULL default '',
+ `MAXLEN` bigint(3) NOT NULL default '0'
+) ENGINE=MEMORY DEFAULT CHARSET=utf8
+set names latin1;
+create table t1 select * from information_schema.CHARACTER_SETS
+where CHARACTER_SET_NAME like "latin1";
+select * from t1;
+CHARACTER_SET_NAME DEFAULT_COLLATE_NAME DESCRIPTION MAXLEN
+latin1 latin1_swedish_ci cp1252 West European 1
+alter table t1 default character set utf8;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `CHARACTER_SET_NAME` varchar(64) NOT NULL default '',
+ `DEFAULT_COLLATE_NAME` varchar(64) NOT NULL default '',
+ `DESCRIPTION` varchar(60) NOT NULL default '',
+ `MAXLEN` bigint(3) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+drop table t1;
+create view v1 as select * from information_schema.TABLES;
+drop view v1;
+create table t1(a NUMERIC(5,3), b NUMERIC(5,1), c float(5,2),
+d NUMERIC(6,4), e float, f DECIMAL(6,3), g int(11), h DOUBLE(10,3),
+i DOUBLE);
+select COLUMN_NAME,COLUMN_TYPE, CHARACTER_MAXIMUM_LENGTH,
+CHARACTER_OCTET_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE
+from information_schema.columns where table_name= 't1';
+COLUMN_NAME COLUMN_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE
+a decimal(5,3) NULL NULL 5 3
+b decimal(5,1) NULL NULL 5 1
+c float(5,2) NULL NULL 5 2
+d decimal(6,4) NULL NULL 6 4
+e float NULL NULL 12 NULL
+f decimal(6,3) NULL NULL 6 3
+g int(11) NULL NULL 10 0
+h double(10,3) NULL NULL 10 3
+i double NULL NULL 22 NULL
+drop table t1;
+create table t115 as select table_name, column_name, column_type
+from information_schema.columns where table_name = 'proc';
+select * from t115;
+table_name column_name column_type
+proc db char(64)
+proc name char(64)
+proc type enum('FUNCTION','PROCEDURE')
+proc specific_name char(64)
+proc language enum('SQL')
+proc sql_data_access enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')
+proc is_deterministic enum('YES','NO')
+proc security_type enum('INVOKER','DEFINER')
+proc param_list blob
+proc returns char(64)
+proc body longblob
+proc definer char(77)
+proc created timestamp
+proc modified timestamp
+proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE')
+proc comment char(64)
+drop table t115;
+create procedure p108 () begin declare c cursor for select data_type
+from information_schema.columns; open c; open c; end;//
+call p108()//
+ERROR 24000: Cursor is already open
+drop procedure p108;
+create view v1 as select A1.table_name from information_schema.TABLES A1
+where table_name= "user";
+select * from v1;
+table_name
+user
+drop view v1;
+create view vo as select 'a' union select 'a';
+show index from vo;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_NAME= "vo";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_NAME= "vo";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME
+drop view vo;
+select TABLE_NAME,TABLE_TYPE,ENGINE
+from information_schema.tables
+where table_schema='information_schema' limit 2;
+TABLE_NAME TABLE_TYPE ENGINE
+CHARACTER_SETS SYSTEM VIEW MEMORY
+COLLATIONS SYSTEM VIEW MEMORY
+show tables from information_schema like "T%";
+Tables_in_information_schema (T%)
+TABLES
+TABLE_CONSTRAINTS
+TABLE_PRIVILEGES
+TRIGGERS
+create database information_schema;
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
+use information_schema;
+show full tables like "T%";
+Tables_in_information_schema (T%) Table_type
+TABLES SYSTEM VIEW
+TABLE_CONSTRAINTS SYSTEM VIEW
+TABLE_PRIVILEGES SYSTEM VIEW
+TRIGGERS SYSTEM VIEW
+create table t1(a int);
+ERROR 42S02: Unknown table 't1' in information_schema
+use test;
+show tables;
+Tables_in_test
+use information_schema;
+show tables like "T%";
+Tables_in_information_schema (T%)
+TABLES
+TABLE_CONSTRAINTS
+TABLE_PRIVILEGES
+TRIGGERS
+select table_name from tables where table_name='user';
+table_name
+user
+select column_name, privileges from columns
+where table_name='user' and column_name like '%o%';
+column_name privileges
+Host select,insert,update,references
+Password select,insert,update,references
+Drop_priv select,insert,update,references
+Reload_priv select,insert,update,references
+Shutdown_priv select,insert,update,references
+Process_priv select,insert,update,references
+Show_db_priv select,insert,update,references
+Lock_tables_priv select,insert,update,references
+Show_view_priv select,insert,update,references
+Create_routine_priv select,insert,update,references
+Alter_routine_priv select,insert,update,references
+max_questions select,insert,update,references
+max_connections select,insert,update,references
+max_user_connections select,insert,update,references
+use test;
+create function sub1(i int) returns int
+return i+1;
+create table t1(f1 int);
+create view t2 (c) as select f1 from t1;
+create view t3 (c) as select sub1(1);
+create table t4(f1 int, KEY f1_key (f1));
+drop table t1;
+drop function sub1;
+select table_name from information_schema.views
+where table_schema='test';
+table_name
+Warnings:
+Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s)
+select table_name from information_schema.views
+where table_schema='test';
+table_name
+Warnings:
+Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s)
+select column_name from information_schema.columns
+where table_schema='test';
+column_name
+f1
+Warnings:
+Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s)
+select index_name from information_schema.statistics where table_schema='test';
+index_name
+f1_key
+select constraint_name from information_schema.table_constraints
+where table_schema='test';
+constraint_name
+drop view t2;
+drop view t3;
+drop table t4;
+select * from information_schema.table_names;
+ERROR 42S02: Unknown table 'table_names' in information_schema
+select column_type from information_schema.columns
+where table_schema="information_schema" and table_name="COLUMNS" and
+(column_name="character_set_name" or column_name="collation_name");
+column_type
+varchar(64)
+varchar(64)
+select TABLE_ROWS from information_schema.tables where
+table_schema="information_schema" and table_name="COLUMNS";
+TABLE_ROWS
+NULL
+select table_type from information_schema.tables
+where table_schema="mysql" and table_name="user";
+table_type
+BASE TABLE
+show open tables where `table` like "user";
+Database Table In_use Name_locked
+mysql user 0 0
+show status where variable_name like "%database%";
+Variable_name Value
+Com_show_databases 3
+show variables where variable_name like "skip_show_databas";
+Variable_name Value
+show global status like "Threads_running";
+Variable_name Value
+Threads_running #
+create table t1(f1 int);
+create table t2(f2 int);
+create view v1 as select * from t1, t2;
+set @got_val= (select count(*) from information_schema.columns);
+drop view v1;
+drop table t1, t2;
+CREATE TABLE t_crashme ( f1 BIGINT);
+CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
+CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
+count(*)
+101
+drop view a2, a1;
+drop table t_crashme;
+select table_schema,table_name, column_name from
+information_schema.columns
+where data_type = 'longtext';
+table_schema table_name column_name
+information_schema COLUMNS COLUMN_TYPE
+information_schema ROUTINES ROUTINE_DEFINITION
+information_schema ROUTINES SQL_MODE
+information_schema TRIGGERS ACTION_CONDITION
+information_schema TRIGGERS ACTION_STATEMENT
+information_schema TRIGGERS SQL_MODE
+information_schema VIEWS VIEW_DEFINITION
+select table_name, column_name, data_type from information_schema.columns
+where data_type = 'datetime';
+table_name column_name data_type
+ROUTINES CREATED datetime
+ROUTINES LAST_ALTERED datetime
+TABLES CREATE_TIME datetime
+TABLES UPDATE_TIME datetime
+TABLES CHECK_TIME datetime
+TRIGGERS CREATED datetime
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES A
+WHERE NOT EXISTS
+(SELECT * FROM INFORMATION_SCHEMA.COLUMNS B
+WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA
+AND A.TABLE_NAME = B.TABLE_NAME);
+COUNT(*)
+0
+create table t1
+( x_bigint BIGINT,
+x_integer INTEGER,
+x_smallint SMALLINT,
+x_decimal DECIMAL(5,3),
+x_numeric NUMERIC(5,3),
+x_real REAL,
+x_float FLOAT,
+x_double_precision DOUBLE PRECISION );
+SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH
+FROM INFORMATION_SCHEMA.COLUMNS
+WHERE TABLE_NAME= 't1';
+COLUMN_NAME CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH
+x_bigint NULL NULL
+x_integer NULL NULL
+x_smallint NULL NULL
+x_decimal NULL NULL
+x_numeric NULL NULL
+x_real NULL NULL
+x_float NULL NULL
+x_double_precision NULL NULL
+drop table t1;
+grant select on test.* to mysqltest_4@localhost;
+SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS
+where COLUMN_NAME='TABLE_NAME';
+TABLE_NAME COLUMN_NAME PRIVILEGES
+COLUMNS TABLE_NAME select
+COLUMN_PRIVILEGES TABLE_NAME select
+KEY_COLUMN_USAGE TABLE_NAME select
+STATISTICS TABLE_NAME select
+TABLES TABLE_NAME select
+TABLE_CONSTRAINTS TABLE_NAME select
+TABLE_PRIVILEGES TABLE_NAME select
+VIEWS TABLE_NAME select
+delete from mysql.user where user='mysqltest_4';
+delete from mysql.db where user='mysqltest_4';
+flush privileges;
+SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
+table_schema count(*)
+information_schema 16
+mysql 17
+create table t1 (i int, j int);
+create trigger trg1 before insert on t1 for each row
+begin
+if new.j > 10 then
+set new.j := 10;
+end if;
+end|
+create trigger trg2 before update on t1 for each row
+begin
+if old.i % 2 = 0 then
+set new.j := -1;
+end if;
+end|
+create trigger trg3 after update on t1 for each row
+begin
+if new.j = -1 then
+set @fired:= "Yes";
+end if;
+end|
+show triggers;
+Trigger Event Table Statement Timing Created sql_mode
+trg1 INSERT t1
+begin
+if new.j > 10 then
+set new.j := 10;
+end if;
+end BEFORE NULL
+trg2 UPDATE t1
+begin
+if old.i % 2 = 0 then
+set new.j := -1;
+end if;
+end BEFORE NULL
+trg3 UPDATE t1
+begin
+if new.j = -1 then
+set @fired:= "Yes";
+end if;
+end AFTER NULL
+select * from information_schema.triggers;
+TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE
+NULL test trg1 INSERT NULL test t1 0 NULL
+begin
+if new.j > 10 then
+set new.j := 10;
+end if;
+end ROW BEFORE NULL NULL OLD NEW NULL
+NULL test trg2 UPDATE NULL test t1 0 NULL
+begin
+if old.i % 2 = 0 then
+set new.j := -1;
+end if;
+end ROW BEFORE NULL NULL OLD NEW NULL
+NULL test trg3 UPDATE NULL test t1 0 NULL
+begin
+if new.j = -1 then
+set @fired:= "Yes";
+end if;
+end ROW AFTER NULL NULL OLD NEW NULL
+drop trigger trg1;
+drop trigger trg2;
+drop trigger trg3;
+drop table t1;
+create database mysqltest;
+create table mysqltest.t1 (f1 int, f2 int);
+create table mysqltest.t2 (f1 int);
+grant select (f1) on mysqltest.t1 to user1@localhost;
+grant select on mysqltest.t2 to user2@localhost;
+grant select on mysqltest.* to user3@localhost;
+grant select on *.* to user4@localhost;
+select * from information_schema.column_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'user1'@'localhost' NULL mysqltest t1 f1 SELECT NO
+select * from information_schema.table_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+select * from information_schema.schema_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
+select * from information_schema.user_privileges;
+GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
+'user1'@'localhost' NULL USAGE NO
+show grants;
+Grants for user1@localhost
+GRANT USAGE ON *.* TO 'user1'@'localhost'
+GRANT SELECT (f1) ON `mysqltest`.`t1` TO 'user1'@'localhost'
+select * from information_schema.column_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
+select * from information_schema.table_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'user2'@'localhost' NULL mysqltest t2 SELECT NO
+select * from information_schema.schema_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
+select * from information_schema.user_privileges;
+GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
+'user2'@'localhost' NULL USAGE NO
+show grants;
+Grants for user2@localhost
+GRANT USAGE ON *.* TO 'user2'@'localhost'
+GRANT SELECT ON `mysqltest`.`t2` TO 'user2'@'localhost'
+select * from information_schema.column_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
+select * from information_schema.table_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+select * from information_schema.schema_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
+'user3'@'localhost' NULL mysqltest SELECT NO
+select * from information_schema.user_privileges;
+GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
+'user3'@'localhost' NULL USAGE NO
+show grants;
+Grants for user3@localhost
+GRANT USAGE ON *.* TO 'user3'@'localhost'
+GRANT SELECT ON `mysqltest`.* TO 'user3'@'localhost'
+select * from information_schema.column_privileges where grantee like '%user%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'user1'@'localhost' NULL mysqltest t1 f1 SELECT NO
+select * from information_schema.table_privileges where grantee like '%user%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'user2'@'localhost' NULL mysqltest t2 SELECT NO
+select * from information_schema.schema_privileges where grantee like '%user%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
+'user3'@'localhost' NULL mysqltest SELECT NO
+select * from information_schema.user_privileges where grantee like '%user%';
+GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
+'user1'@'localhost' NULL USAGE NO
+'user2'@'localhost' NULL USAGE NO
+'user3'@'localhost' NULL USAGE NO
+'user4'@'localhost' NULL SELECT NO
+show grants;
+Grants for user4@localhost
+GRANT SELECT ON *.* TO 'user4'@'localhost'
+drop user user1@localhost, user2@localhost, user3@localhost, user4@localhost;
+use test;
+drop database mysqltest;
+drop procedure if exists p1;
+drop procedure if exists p2;
+create procedure p1 () modifies sql data set @a = 5;
+create procedure p2 () set @a = 5;
+select sql_data_access from information_schema.routines
+where specific_name like 'p%';
+sql_data_access
+MODIFIES SQL DATA
+CONTAINS SQL
+drop procedure p1;
+drop procedure p2;
+show create database information_schema;
+Database Create Database
+information_schema CREATE DATABASE `information_schema` /*!40100 DEFAULT CHARACTER SET utf8 */
+create table t1(f1 LONGBLOB, f2 LONGTEXT);
+select column_name,data_type,CHARACTER_OCTET_LENGTH,
+CHARACTER_MAXIMUM_LENGTH
+from information_schema.columns
+where table_name='t1';
+column_name data_type CHARACTER_OCTET_LENGTH CHARACTER_MAXIMUM_LENGTH
+f1 longblob 4294967295 4294967295
+f2 longtext 4294967295 4294967295
+drop table t1;
+create table t1(f1 tinyint, f2 SMALLINT, f3 mediumint, f4 int,
+f5 BIGINT, f6 BIT, f7 bit(64));
+select column_name, NUMERIC_PRECISION, NUMERIC_SCALE
+from information_schema.columns
+where table_name='t1';
+column_name NUMERIC_PRECISION NUMERIC_SCALE
+f1 3 0
+f2 5 0
+f3 7 0
+f4 10 0
+f5 19 0
+f6 1 NULL
+f7 64 NULL
+drop table t1;
+create table t1 (f1 integer);
+create trigger tr1 after insert on t1 for each row set @test_var=42;
+use information_schema;
+select trigger_schema, trigger_name from triggers where
+trigger_name='tr1';
+trigger_schema trigger_name
+test tr1
+use test;
+drop table t1;
+create table t1 (a int not null, b int);
+use information_schema;
+select column_name, column_default from columns
+where table_schema='test' and table_name='t1';
+column_name column_default
+a NULL
+b NULL
+use test;
+show columns from t1;
+Field Type Null Key Default Extra
+a int(11) NO
+b int(11) YES NULL
+drop table t1;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (b int);
+SHOW TABLE STATUS FROM test
+WHERE name IN ( SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
+WHERE TABLE_SCHEMA='test' AND TABLE_TYPE='BASE TABLE');
+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 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL
+t2 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL
+DROP TABLE t1,t2;
+create table t1(f1 int);
+create view v1 (c) as select f1 from t1;
+select database();
+database()
+NULL
+show fields from test.v1;
+Field Type Null Key Default Extra
+c int(11) YES NULL
+drop view v1;
+drop table t1;
+alter database information_schema;
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
+drop database information_schema;
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
+drop table information_schema.tables;
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
+alter table information_schema.tables;
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
+use information_schema;
+create temporary table schemata(f1 char(10));
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
+CREATE PROCEDURE p1 ()
+BEGIN
+SELECT 'foo' FROM DUAL;
+END |
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
+select ROUTINE_NAME from routines;
+ROUTINE_NAME
+grant all on information_schema.* to 'user1'@'localhost';
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
+grant select on information_schema.* to 'user1'@'localhost';
+ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
new file mode 100644
index 00000000000..d3ff310b812
--- /dev/null
+++ b/mysql-test/r/information_schema_db.result
@@ -0,0 +1,30 @@
+use INFORMATION_SCHEMA;
+show tables;
+Tables_in_information_schema
+CHARACTER_SETS
+COLLATIONS
+COLLATION_CHARACTER_SET_APPLICABILITY
+COLUMNS
+COLUMN_PRIVILEGES
+KEY_COLUMN_USAGE
+ROUTINES
+SCHEMATA
+SCHEMA_PRIVILEGES
+STATISTICS
+TABLES
+TABLE_CONSTRAINTS
+TABLE_PRIVILEGES
+TRIGGERS
+VIEWS
+USER_PRIVILEGES
+show tables from INFORMATION_SCHEMA like 'T%';
+Tables_in_information_schema (T%)
+TABLES
+TABLE_CONSTRAINTS
+TABLE_PRIVILEGES
+TRIGGERS
+create database `inf%`;
+use `inf%`;
+show tables;
+Tables_in_inf%
+drop database `inf%`;
diff --git a/mysql-test/r/information_schema_inno.result b/mysql-test/r/information_schema_inno.result
new file mode 100644
index 00000000000..9dd92baf62f
--- /dev/null
+++ b/mysql-test/r/information_schema_inno.result
@@ -0,0 +1,27 @@
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id, id),
+FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE CASCADE,
+FOREIGN KEY (t1_id) REFERENCES t1(id) ON UPDATE CASCADE) ENGINE=INNODB;
+CREATE TABLE t3 (id INT PRIMARY KEY, t2_id INT, INDEX par_ind (t2_id),
+FOREIGN KEY (id, t2_id) REFERENCES t2(t1_id, id) ON DELETE CASCADE) ENGINE=INNODB;
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_SCHEMA= "test";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE
+NULL test PRIMARY test t1 PRIMARY KEY
+NULL test PRIMARY test t2 PRIMARY KEY
+NULL test t2_ibfk_1 test t2 FOREIGN KEY
+NULL test t2_ibfk_2 test t2 FOREIGN KEY
+NULL test PRIMARY test t3 PRIMARY KEY
+NULL test t3_ibfk_1 test t3 FOREIGN KEY
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_SCHEMA= "test";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME
+NULL test PRIMARY NULL test t1 id 1 NULL NULL NULL NULL
+NULL test PRIMARY NULL test t2 id 1 NULL NULL NULL NULL
+NULL test t2_ibfk_1 NULL test t2 t1_id 1 1 test t1 id
+NULL test t2_ibfk_2 NULL test t2 t1_id 1 1 test t1 id
+NULL test PRIMARY NULL test t3 id 1 NULL NULL NULL NULL
+NULL test t3_ibfk_1 NULL test t3 id 1 1 test t2 t1_id
+NULL test t3_ibfk_1 NULL test t3 t2_id 2 2 test t2 id
+drop table t3, t2, t1;
diff --git a/mysql-test/r/init_connect.result b/mysql-test/r/init_connect.result
index db1e72dfca9..eeae422edc4 100644
--- a/mysql-test/r/init_connect.result
+++ b/mysql-test/r/init_connect.result
@@ -12,7 +12,7 @@ set GLOBAL init_connect=DEFAULT;
select @a;
@a
NULL
-set global init_connect="create table t1(a char(10));\
+set global init_connect="drop table if exists t1; create table t1(a char(10));\
insert into t1 values ('\0');insert into t1 values('abc')";
select hex(a) from t1;
hex(a)
diff --git a/mysql-test/r/innodb-big.result b/mysql-test/r/innodb-big.result
new file mode 100644
index 00000000000..19204b7cc65
--- /dev/null
+++ b/mysql-test/r/innodb-big.result
@@ -0,0 +1,34 @@
+DROP TABLE IF EXISTS t1, t2, t3, t4;
+CREATE TABLE t1 (id INTEGER) ENGINE=MYISAM;
+CREATE TABLE t2 (id INTEGER primary key) ENGINE=INNODB;
+CREATE TABLE t3 (a char(32) primary key,id INTEGER) ENGINE=INNODB;
+CREATE TABLE t4 (a char(32) primary key,id INTEGER) ENGINE=MYISAM;
+INSERT INTO t1 (id) VALUES (1);
+INSERT INTO t1 SELECT id+1 FROM t1;
+INSERT INTO t1 SELECT id+2 FROM t1;
+INSERT INTO t1 SELECT id+4 FROM t1;
+INSERT INTO t1 SELECT id+8 FROM t1;
+INSERT INTO t1 SELECT id+16 FROM t1;
+INSERT INTO t1 SELECT id+32 FROM t1;
+INSERT INTO t1 SELECT id+64 FROM t1;
+INSERT INTO t1 SELECT id+128 FROM t1;
+INSERT INTO t1 SELECT id+256 FROM t1;
+INSERT INTO t1 SELECT id+512 FROM t1;
+INSERT INTO t1 SELECT id+1024 FROM t1;
+INSERT INTO t1 SELECT id+2048 FROM t1;
+INSERT INTO t1 SELECT id+4096 FROM t1;
+INSERT INTO t1 SELECT id+8192 FROM t1;
+INSERT INTO t1 SELECT id+16384 FROM t1;
+INSERT INTO t1 SELECT id+32768 FROM t1;
+INSERT INTO t1 SELECT id+65536 FROM t1;
+INSERT INTO t1 SELECT id+131072 FROM t1;
+INSERT INTO t1 SELECT id+262144 FROM t1;
+INSERT INTO t1 SELECT id+524288 FROM t1;
+INSERT INTO t1 SELECT id+1048576 FROM t1;
+INSERT INTO t2 SELECT * FROM t1;
+INSERT INTO t3 SELECT concat(id),id from t2 ORDER BY -id;
+INSERT INTO t4 SELECT * from t3 ORDER BY concat(a);
+select sum(id) from t3;
+sum(id)
+2199024304128
+drop table t1,t2,t3,t4;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index c7aef8ed792..4dd1d694401 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -141,13 +141,13 @@ id parent_id level
1015 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const # Using where; Using index
+1 SIMPLE t1 ref level level 1 const # Using index
explain select level,id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const # Using where; Using index
+1 SIMPLE t1 ref level level 1 const # Using index
explain select level,id,parent_id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const # Using where
+1 SIMPLE t1 ref level level 1 const #
select level,id from t1 where level=1;
level id
1 1002
@@ -249,6 +249,40 @@ n
4
5
6
+set autocommit=0;
+begin;
+savepoint `my_savepoint`;
+insert into t1 values (7);
+savepoint `savept2`;
+insert into t1 values (3);
+select n from t1;
+n
+3
+4
+5
+6
+7
+savepoint savept3;
+rollback to savepoint savept2;
+rollback to savepoint savept3;
+ERROR 42000: SAVEPOINT savept3 does not exist
+rollback to savepoint savept2;
+release savepoint `my_savepoint`;
+select n from t1;
+n
+4
+5
+6
+7
+rollback to savepoint `my_savepoint`;
+ERROR 42000: SAVEPOINT my_savepoint does not exist
+rollback to savepoint savept2;
+ERROR 42000: SAVEPOINT savept2 does not exist
+insert into t1 values (8);
+savepoint sv;
+commit;
+savepoint sv;
+set autocommit=1;
rollback;
drop table t1;
create table t1 (n int not null primary key) engine=innodb;
@@ -609,7 +643,7 @@ id parent_id level
1016 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const # Using where; Using index
+1 SIMPLE t1 ref level level 1 const # Using index
select level,id from t1 where level=1;
level id
1 1004
@@ -721,6 +755,11 @@ a
1
2
3
+select a from t1 natural join t1 as t2 where b >= @a order by a;
+a
+1
+2
+3
update t1 set a=5 where a=1;
select a from t1;
a
@@ -870,7 +909,7 @@ insert into mysqltest.t3 values(1);
commit;
drop database mysqltest;
show tables from mysqltest;
-Got one of the listed errors
+ERROR 42000: Unknown database 'mysqltest'
set autocommit=0;
create table t1 (a int not null) engine= innodb;
insert into t1 values(1),(2);
@@ -931,16 +970,16 @@ drop table t1;
create table t1 (t int not null default 1, key (t)) engine=innodb;
desc t1;
Field Type Null Key Default Extra
-t int(11) MUL 1
+t int(11) NO MUL 1
drop table t1;
CREATE TABLE t1 (
number bigint(20) NOT NULL default '0',
cname char(15) NOT NULL default '',
carrier_id smallint(6) NOT NULL default '0',
privacy tinyint(4) NOT NULL default '0',
-last_mod_date timestamp(14) NOT NULL,
+last_mod_date timestamp NOT NULL,
last_mod_id smallint(6) NOT NULL default '0',
-last_app_date timestamp(14) NOT NULL,
+last_app_date timestamp NOT NULL,
last_app_id smallint(6) default '-1',
version smallint(6) NOT NULL default '0',
assigned_scps int(11) default '0',
@@ -957,9 +996,9 @@ number bigint(20) NOT NULL default '0',
cname char(15) NOT NULL default '',
carrier_id smallint(6) NOT NULL default '0',
privacy tinyint(4) NOT NULL default '0',
-last_mod_date timestamp(14) NOT NULL,
+last_mod_date timestamp NOT NULL,
last_mod_id smallint(6) NOT NULL default '0',
-last_app_date timestamp(14) NOT NULL,
+last_app_date timestamp NOT NULL,
last_app_id smallint(6) default '-1',
version smallint(6) NOT NULL default '0',
assigned_scps int(11) default '0',
@@ -1326,8 +1365,8 @@ truncate table t1;
insert into t1 (a) values (NULL),(NULL);
SELECT * from t1;
a
-3
-4
+1
+2
drop table t1;
CREATE TABLE t1 (`id 1` INT NOT NULL, PRIMARY KEY (`id 1`)) ENGINE=INNODB;
CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id), FOREIGN KEY (`t1_id`) REFERENCES `t1`(`id 1`) ON DELETE CASCADE ) ENGINE=INNODB;
@@ -1343,7 +1382,7 @@ ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fail
update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
-ERROR 42S02: Unknown table 't1' in where clause
+ERROR 42S22: Unknown column 't1.id' in 'where clause'
drop table t3,t2,t1;
create table t1(
id int primary key,
@@ -1376,7 +1415,7 @@ CREATE TABLE t1 (
`id` int(10) unsigned NOT NULL auto_increment,
`id_object` int(10) unsigned default '0',
`id_version` int(10) unsigned NOT NULL default '1',
-label varchar(100) NOT NULL default '',
+`label` varchar(100) NOT NULL default '',
`description` text,
PRIMARY KEY (`id`),
KEY `id_object` (`id_object`),
@@ -1390,8 +1429,8 @@ PRIMARY KEY (`id`),
KEY `id_version` (`id_version`)
) ENGINE=InnoDB;
INSERT INTO t2 VALUES("3524", "1"),("3525", "1"),("1794", "4"),("102", "5"),("1822", "6"),("3382", "9");
-SELECT t2.id, t1.label FROM t2 INNER JOIN
-(SELECT t1.id_object as id_object FROM t1 WHERE t1.label LIKE '%test%') AS lbl
+SELECT t2.id, t1.`label` FROM t2 INNER JOIN
+(SELECT t1.id_object as id_object FROM t1 WHERE t1.`label` LIKE '%test%') AS lbl
ON (t2.id = lbl.id_object) INNER JOIN t1 ON (t2.id = t1.id_object);
id label
3382 Test
@@ -1409,22 +1448,28 @@ insert t2 select * from t1;
insert t3 select * from t1;
checksum table t1, t2, t3, t4 quick;
Table Checksum
-test.t1 968604391
+test.t1 2948697075
test.t2 NULL
test.t3 NULL
test.t4 NULL
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
checksum table t1, t2, t3, t4;
Table Checksum
-test.t1 968604391
-test.t2 968604391
-test.t3 968604391
+test.t1 2948697075
+test.t2 3835700799
+test.t3 3835700799
test.t4 NULL
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
checksum table t1, t2, t3, t4 extended;
Table Checksum
-test.t1 968604391
-test.t2 968604391
-test.t3 968604391
+test.t1 3092701434
+test.t2 3835700799
+test.t3 3835700799
test.t4 NULL
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
drop table t1,t2,t3;
create table t1 (id int, name char(10) not null, name2 char(10) not null) engine=innodb;
insert into t1 values(1,'first','fff'),(2,'second','sss'),(3,'third','ttt');
@@ -1448,14 +1493,14 @@ create table t2 (id int(11) not null, constraint t1_id_fk foreign key ( id ) ref
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `id` int(11) NOT NULL default '0',
- `id2` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
+ `id2` int(11) NOT NULL,
UNIQUE KEY `id` (`id`,`id2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
KEY `t1_id_fk` (`id`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
@@ -1463,7 +1508,7 @@ create index id on t2 (id);
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
KEY `id` (`id`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
@@ -1471,7 +1516,7 @@ create index id2 on t2 (id);
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
KEY `id` (`id`),
KEY `id2` (`id`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
@@ -1482,7 +1527,7 @@ Got one of the listed errors
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
KEY `id` (`id`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
@@ -1491,8 +1536,8 @@ create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
- `id2` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
+ `id2` int(11) NOT NULL,
KEY `t1_id_fk` (`id`,`id2`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`, `id2`) REFERENCES `t1` (`id`, `id2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
@@ -1500,8 +1545,8 @@ create unique index id on t2 (id,id2);
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
- `id2` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
+ `id2` int(11) NOT NULL,
UNIQUE KEY `id` (`id`,`id2`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`, `id2`) REFERENCES `t1` (`id`, `id2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
@@ -1510,8 +1555,8 @@ create table t2 (id int(11) not null, id2 int(11) not null, unique (id,id2),cons
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
- `id2` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
+ `id2` int(11) NOT NULL,
UNIQUE KEY `id` (`id`,`id2`),
KEY `t1_id_fk` (`id2`,`id`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id2`, `id`) REFERENCES `t1` (`id`, `id2`)
@@ -1521,8 +1566,8 @@ create table t2 (id int(11) not null, id2 int(11) not null, unique (id,id2), con
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
- `id2` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
+ `id2` int(11) NOT NULL,
UNIQUE KEY `id` (`id`,`id2`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
@@ -1531,8 +1576,8 @@ create table t2 (id int(11) not null, id2 int(11) not null, unique (id,id2),cons
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `id` int(11) NOT NULL default '0',
- `id2` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
+ `id2` int(11) NOT NULL,
UNIQUE KEY `id` (`id`,`id2`),
KEY `t1_id_fk` (`id2`,`id`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id2`, `id`) REFERENCES `t1` (`id`, `id2`)
@@ -1543,7 +1588,7 @@ show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL auto_increment,
- `id2` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`,`id2`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
@@ -1554,7 +1599,7 @@ show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL auto_increment,
- `id2` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL,
KEY `t1_id_fk` (`id`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
@@ -1563,14 +1608,14 @@ show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`id` int(11) NOT NULL auto_increment,
- `id2` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL,
KEY `id_test` (`id`),
KEY `id_test2` (`id`,`id2`),
CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2;
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
-ERROR HY000: Can't create table './test/t2.frm' (errno: 150)
+ERROR HY000: Can't create table './test/t2' (errno: 150)
create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb;
show create table t2;
Table Create Table
@@ -1597,14 +1642,14 @@ t2 CREATE TABLE `t2` (
drop table t2, t1;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 25
+Binlog_cache_use 155
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 26
+Binlog_cache_use 156
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
@@ -1613,7 +1658,7 @@ delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 27
+Binlog_cache_use 157
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
@@ -1694,3 +1739,823 @@ select min(b) from t1 where a='8';
min(b)
6
drop table t1;
+create table t1 (x bigint unsigned not null primary key) engine=innodb;
+insert into t1(x) values (0xfffffffffffffff0),(0xfffffffffffffff1);
+select * from t1;
+x
+18446744073709551600
+18446744073709551601
+select count(*) from t1 where x>0;
+count(*)
+2
+select count(*) from t1 where x=0;
+count(*)
+0
+select count(*) from t1 where x<0;
+count(*)
+0
+select count(*) from t1 where x < -16;
+count(*)
+0
+select count(*) from t1 where x = -16;
+count(*)
+0
+explain select count(*) from t1 where x > -16;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 2 Using where; Using index
+select count(*) from t1 where x > -16;
+count(*)
+2
+select * from t1 where x > -16;
+x
+18446744073709551600
+18446744073709551601
+select count(*) from t1 where x = 18446744073709551601;
+count(*)
+1
+drop table t1;
+show status like "Innodb_buffer_pool_pages_total";
+Variable_name Value
+Innodb_buffer_pool_pages_total 512
+show status like "Innodb_page_size";
+Variable_name Value
+Innodb_page_size 16384
+show status like "Innodb_rows_deleted";
+Variable_name Value
+Innodb_rows_deleted 2070
+show status like "Innodb_rows_inserted";
+Variable_name Value
+Innodb_rows_inserted 31725
+show status like "Innodb_rows_updated";
+Variable_name Value
+Innodb_rows_updated 29530
+show status like "Innodb_row_lock_waits";
+Variable_name Value
+Innodb_row_lock_waits 0
+show status like "Innodb_row_lock_current_waits";
+Variable_name Value
+Innodb_row_lock_current_waits 0
+show status like "Innodb_row_lock_time";
+Variable_name Value
+Innodb_row_lock_time 0
+show status like "Innodb_row_lock_time_max";
+Variable_name Value
+Innodb_row_lock_time_max 0
+show status like "Innodb_row_lock_time_avg";
+Variable_name Value
+Innodb_row_lock_time_avg 0
+show variables like "innodb_sync_spin_loops";
+Variable_name Value
+innodb_sync_spin_loops 20
+set global innodb_sync_spin_loops=1000;
+show variables like "innodb_sync_spin_loops";
+Variable_name Value
+innodb_sync_spin_loops 1000
+set global innodb_sync_spin_loops=0;
+show variables like "innodb_sync_spin_loops";
+Variable_name Value
+innodb_sync_spin_loops 0
+set global innodb_sync_spin_loops=20;
+show variables like "innodb_sync_spin_loops";
+Variable_name Value
+innodb_sync_spin_loops 20
+show variables like "innodb_thread_concurrency";
+Variable_name Value
+innodb_thread_concurrency 20
+set global innodb_thread_concurrency=1000;
+show variables like "innodb_thread_concurrency";
+Variable_name Value
+innodb_thread_concurrency 1000
+set global innodb_thread_concurrency=0;
+show variables like "innodb_thread_concurrency";
+Variable_name Value
+innodb_thread_concurrency 1
+set global innodb_thread_concurrency=16;
+show variables like "innodb_thread_concurrency";
+Variable_name Value
+innodb_thread_concurrency 16
+show variables like "innodb_concurrency_tickets";
+Variable_name Value
+innodb_concurrency_tickets 500
+set global innodb_concurrency_tickets=1000;
+show variables like "innodb_concurrency_tickets";
+Variable_name Value
+innodb_concurrency_tickets 1000
+set global innodb_concurrency_tickets=0;
+show variables like "innodb_concurrency_tickets";
+Variable_name Value
+innodb_concurrency_tickets 1
+set global innodb_concurrency_tickets=500;
+show variables like "innodb_concurrency_tickets";
+Variable_name Value
+innodb_concurrency_tickets 500
+show variables like "innodb_thread_sleep_delay";
+Variable_name Value
+innodb_thread_sleep_delay 10000
+set global innodb_thread_sleep_delay=100000;
+show variables like "innodb_thread_sleep_delay";
+Variable_name Value
+innodb_thread_sleep_delay 100000
+set global innodb_thread_sleep_delay=0;
+show variables like "innodb_thread_sleep_delay";
+Variable_name Value
+innodb_thread_sleep_delay 0
+set global innodb_thread_sleep_delay=10000;
+show variables like "innodb_thread_sleep_delay";
+Variable_name Value
+innodb_thread_sleep_delay 10000
+set storage_engine=INNODB;
+drop table if exists t1,t2,t3;
+--- Testing varchar ---
+--- Testing varchar ---
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Note 1265 Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+ *+*+ *
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Note 1265 Data truncated for column 't' at row 2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(10) default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+ *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`),
+ KEY `c` (`c`),
+ KEY `t` (`t`(10))
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const # Using where; Using index
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const # Using where; Using index
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t t 13 NULL # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where; Using index
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v,v_2 # 13 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(*) from t1 group by c limit 10;
+c count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(*) from t1 group by t limit 10;
+t count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(300) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 303 const # Using where; Using index
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 303 NULL # Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 303 NULL # Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 303 NULL # Using where; Using index
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 303 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 drop key v, add key v (v(30));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(300) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`(30))
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 33 const # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 33 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 modify v varchar(600), drop key v, add key v (v);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(600) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a ');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a%';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='abc ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a %';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+drop table t1;
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`(5)),
+ KEY `c` (`c`(5)),
+ KEY `t` (`t`(5))
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) character set utf8 default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+concat('*',v,'*',c,'*')
+*a*a*
+*a *a*
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+create table t1(a int, b varchar(12), key ba(b, a));
+insert into t1 values (1, 'A'), (20, NULL);
+explain select * from t1 where a=20 and b is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref ba ba 20 const,const 1 Using where; Using index
+select * from t1 where a=20 and b is null;
+a b
+20 NULL
+drop table t1;
+create table t1 (v varchar(65530), key(v));
+ERROR HY000: Can't create table './test/t1' (errno: 139)
+create table t1 (v varchar(65536));
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext character set utf8
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+set storage_engine=MyISAM;
+create table t1 (v varchar(16384)) engine=innodb;
+drop table t1;
+create table t1 (a char(1), b char(1), key(a, b)) engine=innodb;
+insert into t1 values ('8', '6'), ('4', '7');
+select min(a) from t1;
+min(a)
+4
+select min(b) from t1 where a='8';
+min(b)
+6
+drop table t1;
+CREATE TABLE t1 ( `a` int(11) NOT NULL auto_increment, `b` int(11) default NULL,PRIMARY KEY (`a`),UNIQUE KEY `b` (`b`)) ENGINE=innodb;
+insert into t1 (b) values (1);
+replace into t1 (b) values (2), (1), (3);
+select * from t1;
+a b
+3 1
+2 2
+4 3
+truncate table t1;
+insert into t1 (b) values (1);
+replace into t1 (b) values (2);
+replace into t1 (b) values (1);
+replace into t1 (b) values (3);
+select * from t1;
+a b
+3 1
+2 2
+4 3
+drop table t1;
+create table t1 (rowid int not null auto_increment, val int not null,primary
+key (rowid), unique(val)) engine=innodb;
+replace into t1 (val) values ('1'),('2');
+replace into t1 (val) values ('1'),('2');
+insert into t1 (val) values ('1'),('2');
+ERROR 23000: Duplicate entry '1' for key 2
+select * from t1;
+rowid val
+3 1
+4 2
+drop table t1;
+create table t1 (a int not null auto_increment primary key, val int) engine=InnoDB;
+insert into t1 (val) values (1);
+update t1 set a=2 where a=1;
+insert into t1 (val) values (1);
+ERROR 23000: Duplicate entry '2' for key 1
+select * from t1;
+a val
+2 1
+drop table t1;
+CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB;
+INSERT INTO t1 (GRADE) VALUES (151),(252),(343);
+SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300;
+GRADE
+252
+SELECT GRADE FROM t1 WHERE GRADE= 151;
+GRADE
+151
+DROP TABLE t1;
+create table t1 (f1 varchar(10), f2 varchar(10), primary key (f1,f2)) engine=innodb;
+create table t2 (f3 varchar(10), f4 varchar(10), key (f4)) engine=innodb;
+insert into t2 values ('aa','cc');
+insert into t1 values ('aa','bb'),('aa','cc');
+delete t1 from t1,t2 where f1=f3 and f4='cc';
+select * from t1;
+f1 f2
+drop table t1,t2;
+CREATE TABLE t1 (
+id INTEGER NOT NULL AUTO_INCREMENT, PRIMARY KEY (id)
+) ENGINE=InnoDB;
+CREATE TABLE t2 (
+id INTEGER NOT NULL,
+FOREIGN KEY (id) REFERENCES t1 (id)
+) ENGINE=InnoDB;
+INSERT INTO t1 (id) VALUES (NULL);
+SELECT * FROM t1;
+id
+1
+TRUNCATE t1;
+INSERT INTO t1 (id) VALUES (NULL);
+SELECT * FROM t1;
+id
+1
+DELETE FROM t1;
+TRUNCATE t1;
+INSERT INTO t1 (id) VALUES (NULL);
+SELECT * FROM t1;
+id
+1
+DROP TABLE t2, t1;
+CREATE TABLE t1
+(
+id INT PRIMARY KEY
+) ENGINE=InnoDB;
+CREATE TEMPORARY TABLE t2
+(
+id INT NOT NULL PRIMARY KEY,
+b INT,
+FOREIGN KEY (b) REFERENCES test.t1(id)
+) ENGINE=InnoDB;
+Got one of the listed errors
+DROP TABLE t1;
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 71b10699fa9..f788576f824 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
create table t1 (a int not null);
insert into t1 values (1);
insert into t1 values (a+2);
@@ -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 Column set to default value; NULL supplied to NOT NULL column 'id' at row 2
select * from t1;
id
1
@@ -157,20 +157,20 @@ f_float_3_1_u 0.0
set @value= "1e+1111111111a";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings:
-Warning 1265 Data truncated for column 'f_double' at row 1
-Warning 1265 Data truncated for column 'f_float' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float' at row 1
-Warning 1265 Data truncated for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
-Warning 1265 Data truncated for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
-Warning 1265 Data truncated for column 'f_double_u' at row 1
-Warning 1265 Data truncated for column 'f_float_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
-Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
-Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_7_2' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_7_2' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_4_3' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_4_3' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_15_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_15_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_3_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 4
original_value 1e+1111111111a
@@ -185,21 +185,21 @@ f_float_3_1_u 99.9
set @value= "-1e+1111111111a";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings:
-Warning 1265 Data truncated for column 'f_double' at row 1
-Warning 1265 Data truncated for column 'f_float' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float' at row 1
-Warning 1265 Data truncated for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
-Warning 1265 Data truncated for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
-Warning 1265 Data truncated for column 'f_double_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_u' at row 1
-Warning 1265 Data truncated for column 'f_float_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
-Warning 1265 Data truncated for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
-Warning 1265 Data truncated for column 'f_float_3_1_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_7_2' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_7_2' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_4_3' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_4_3' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_15_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_15_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_3_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
number 5
original_value -1e+1111111111a
@@ -212,57 +212,20 @@ f_float_u 0
f_double_15_1_u 0.0
f_float_3_1_u 0.0
set @value= 1e+1111111111;
-insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
-Warnings:
-Warning 1264 Data truncated; out of range for column 'f_float' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
-select * from t1 where number =last_insert_id();
-number 6
-original_value 1.7976931348623e+308
-f_double 1.79769313486232e+308
-f_float 3.40282e+38
-f_double_7_2 99999.99
-f_float_4_3 9.999
-f_double_u 1.79769313486232e+308
-f_float_u 3.40282e+38
-f_double_15_1_u 99999999999999.9
-f_float_3_1_u 99.9
+ERROR 22007: Illegal double '1e+1111111111' value found during parsing
set @value= -1e+1111111111;
-insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
-Warnings:
-Warning 1264 Data truncated; out of range for column 'f_float' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_7_2' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_4_3' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_double_15_1_u' at row 1
-Warning 1264 Data truncated; out of range for column 'f_float_3_1_u' at row 1
-select * from t1 where number =last_insert_id();
-number 7
-original_value -1.7976931348623e+308
-f_double -1.79769313486232e+308
-f_float -3.40282e+38
-f_double_7_2 -99999.99
-f_float_4_3 -9.999
-f_double_u 0
-f_float_u 0
-f_double_15_1_u 0.0
-f_float_3_1_u 0.0
+ERROR 22007: Illegal double '1e+1111111111' value found during parsing
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 Out of range value adjusted for column 'f_float' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_7_2' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_4_3' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_15_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
-number 8
+number 6
original_value 1e+111
f_double 1e+111
f_float 3.40282e+38
@@ -275,15 +238,15 @@ 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 Out of range value adjusted for column 'f_float' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_7_2' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_4_3' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_15_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
-number 9
+number 7
original_value -1e+111
f_double -1e+111
f_float -3.40282e+38
@@ -296,7 +259,7 @@ f_float_3_1_u 0.0
set @value= 1;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
select * from t1 where number =last_insert_id();
-number 10
+number 8
original_value 1
f_double 1
f_float 1
@@ -309,12 +272,12 @@ 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 Out of range value adjusted for column 'f_double_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_double_15_1_u' at row 1
+Warning 1264 Out of range value adjusted for column 'f_float_3_1_u' at row 1
select * from t1 where number =last_insert_id();
-number 11
+number 9
original_value -1
f_double -1
f_float -1
@@ -325,3 +288,14 @@ f_float_u 0
f_double_15_1_u 0.0
f_float_3_1_u 0.0
drop table t1;
+create table t1(id1 int not null auto_increment primary key, t char(12));
+create table t2(id2 int not null, t char(12));
+create table t3(id3 int not null, t char(12), index(id3));
+select count(*) from t2;
+count(*)
+500
+insert into t2 select t1.* from t1, t2 t, t3 where t1.id1 = t.id2 and t.id2 = t3.id3;
+select count(*) from t2;
+count(*)
+25500
+drop table t1,t2,t3;
diff --git a/mysql-test/r/insert_select-binlog.result b/mysql-test/r/insert_select-binlog.result
index bca28059787..76f460b1de2 100644
--- a/mysql-test/r/insert_select-binlog.result
+++ b/mysql-test/r/insert_select-binlog.result
@@ -6,9 +6,9 @@ reset master;
insert into t1 select * from t2;
ERROR 23000: Duplicate entry '2' for key 1
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`; insert into t1 select * from t2
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 98 Server ver: VERSION, Binlog ver: 4
+master-bin.000001 98 Query 1 192 use `test`; insert into t1 select * from t2
select * from t1;
a
1
@@ -20,6 +20,6 @@ reset master;
create table t2(unique(a)) select a from t1;
ERROR 23000: Duplicate entry '1' for key 1
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
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 98 Server ver: VERSION, Binlog ver: 4
drop table t1;
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index d4eb4e8b788..17f65d96abc 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -606,8 +606,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 Column set to default value; NULL supplied to NOT NULL column 'No' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'No' at row 2
select * from t2;
No Field Count
0 1 100
@@ -664,17 +664,7 @@ insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= a +
insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b;
ERROR 23000: Column 'a' in field list is ambiguous
insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b;
-ERROR 42S02: Unknown table 't2' in field list
+ERROR 42S22: Unknown column 't2.a' in 'field list'
insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b;
-ERROR 42S02: Unknown table 't2' in field list
+ERROR 42S22: Unknown column 't2.b' in 'field list'
drop table t1,t2,t3;
-create table t1(f1 varchar(5) key);
-insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
-insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
-insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
-select * from t1;
-f1
-2000
-2001
-2002
-drop table t1;
diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result
index 9e674cc4aae..dbe5d600a95 100644
--- a/mysql-test/r/insert_update.result
+++ b/mysql-test/r/insert_update.result
@@ -1,4 +1,4 @@
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
INSERT t1 VALUES (1,2,10), (3,4,20);
INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100;
@@ -60,12 +60,12 @@ explain extended SELECT *, VALUES(a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5
Warnings:
-Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c`,values(test.t1.a) AS `VALUES(a)` from test.t1
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,values(`test`.`t1`.`a`) AS `VALUES(a)` from `test`.`t1`
explain extended select * from t1 where values(a);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
-Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1`
DROP TABLE t1;
create table t1(a int primary key, b int);
insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5);
diff --git a/mysql-test/r/isam.result b/mysql-test/r/isam.result
index 52eb2d73ed5..cb308a1c71d 100644
--- a/mysql-test/r/isam.result
+++ b/mysql-test/r/isam.result
@@ -65,14 +65,14 @@ test.t2 check error Table 't2' was not locked with LOCK TABLES
test.t1 check status OK
show columns from t1;
Field Type Null Key Default Extra
-a int(11) PRI 0
-b int(11) MUL 0
-c int(11) 0
+a int(11) PRI
+b int(11) MUL
+c int(11)
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
-a int(11) NULL PRI 0 select,insert,update,references
-b int(11) NULL MUL 0 select,insert,update,references
-c int(11) NULL 0 select,insert,update,references
+a int(11) NULL PRI select,insert,update,references
+b int(11) NULL MUL select,insert,update,references
+c int(11) NULL select,insert,update,references
show index from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 a A 4 NULL NULL BTREE
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index dc763472b0e..c887dc9d6a7 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -10,21 +10,21 @@ SELECT * FROM t1 INNER JOIN t2;
S1 S1
1 2
SELECT * from t1 JOIN t2 USING (S1);
-S1 S1
+S1
SELECT * FROM t1 INNER JOIN t2 USING (S1);
-S1 S1
+S1
SELECT * from t1 CROSS JOIN t2;
S1 S1
1 2
SELECT * from t1 LEFT JOIN t2 USING(S1);
-S1 S1
-1 NULL
+S1
+1
SELECT * from t1 LEFT JOIN t2 ON(t2.S1=2);
S1 S1
1 2
SELECT * from t1 RIGHT JOIN t2 USING(S1);
-S1 S1
-NULL 2
+S1
+2
SELECT * from t1 RIGHT JOIN t2 ON(t1.S1=1);
S1 S1
1 2
@@ -127,6 +127,12 @@ a
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
+select 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);
+a
+1
+2
+select 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
drop table t1;
CREATE TABLE t1 (
a int(11) NOT NULL,
@@ -146,9 +152,12 @@ CREATE TABLE t1 (d DATE NOT NULL);
CREATE TABLE t2 (d DATE NOT NULL);
INSERT INTO t1 (d) VALUES ('2001-08-01'),('0000-00-00');
SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE t2.d IS NULL;
-d d
-2001-08-01 NULL
-0000-00-00 NULL
+d
+2001-08-01
+0000-00-00
+SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE d IS NULL;
+d
+0000-00-00
SELECT * from t1 WHERE t1.d IS NULL;
d
0000-00-00
@@ -271,6 +280,12 @@ cust 20
SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith';
rate_code base_rate
cust 20
+SELECT rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND siteid = 'rivercats';
+rate_code base_rate
+cust 20
+SELECT rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE siteid = 'rivercats' AND emp.emp_id = 'psmith';
+rate_code base_rate
+cust 20
drop table t1,t2;
CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, Value1 VARCHAR(255));
CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255));
@@ -296,43 +311,43 @@ insert into t1 values(1),(2);
insert into t2 values(2),(3);
insert into t3 values (2),(4);
select * from t1 natural left join t2;
-i i
-1 NULL
-2 2
+i
+1
+2
select * from t1 left join t2 on (t1.i=t2.i);
i i
1 NULL
2 2
select * from t1 natural left join t2 natural left join t3;
-i i i
-1 NULL NULL
-2 2 2
+i
+1
+2
select * from t1 left join t2 on (t1.i=t2.i) left join t3 on (t2.i=t3.i);
i i i
1 NULL NULL
2 2 2
select * from t3 natural right join t2;
-i i
-2 2
-NULL 3
+i
+2
+3
select * from t3 right join t2 on (t3.i=t2.i);
i i
2 2
NULL 3
select * from t3 natural right join t2 natural right join t1;
-i i i
-NULL NULL 1
-2 2 2
+i
+1
+2
select * from t3 right join t2 on (t3.i=t2.i) right join t1 on (t2.i=t1.i);
i i i
NULL NULL 1
2 2 2
select * from t1,t2 natural left join t3 order by t1.i,t2.i,t3.i;
-i i i
-1 2 2
-1 3 NULL
-2 2 2
-2 3 NULL
+i i
+1 2
+1 3
+2 2
+2 3
select * from t1,t2 left join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i;
i i i
1 2 2
@@ -352,11 +367,11 @@ i i i
2 2 2
2 3 NULL
select * from t1,t2 natural right join t3 order by t1.i,t2.i,t3.i;
-i i i
-1 NULL 4
-1 2 2
-2 NULL 4
-2 2 2
+i i
+1 4
+1 2
+2 4
+2 2
select * from t1,t2 right join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i;
i i i
1 NULL 4
diff --git a/mysql-test/r/join_crash.result b/mysql-test/r/join_crash.result
index c1671ea7e20..f1a3b4956a8 100644
--- a/mysql-test/r/join_crash.result
+++ b/mysql-test/r/join_crash.result
@@ -75,18 +75,11 @@ t1.client_ptr as client_ptr,
t1.comments as comments,
sum( t3.amount_received ) + sum( t3.adjustment ) as total_budget
from
-t1 ,
t2 as client_period ,
-t2 as project_period
-left join
-t3
-on
-t3.project_ptr = t1.project_id
-and t3.date_received <= '2001-03-22 14:15:09'
- left join
-t4
-on
-t4.client_id = t1.client_ptr
+t2 as project_period,
+t3 left join t1 on (t3.project_ptr = t1.project_id and
+t3.date_received <= '2001-03-22 14:15:09')
+left join t4 on t4.client_id = t1.client_ptr
where
1
and ( client_period.period_type = 'client_table'
diff --git a/mysql-test/r/join_nested.result b/mysql-test/r/join_nested.result
new file mode 100644
index 00000000000..f9a25898a6f
--- /dev/null
+++ b/mysql-test/r/join_nested.result
@@ -0,0 +1,1377 @@
+DROP TABLE IF EXISTS t0,t1,t2,t3,t4,t5,t6,t7,t8,t9;
+CREATE TABLE t0 (a int, b int, c int);
+CREATE TABLE t1 (a int, b int, c int);
+CREATE TABLE t2 (a int, b int, c int);
+CREATE TABLE t3 (a int, b int, c int);
+CREATE TABLE t4 (a int, b int, c int);
+CREATE TABLE t5 (a int, b int, c int);
+CREATE TABLE t6 (a int, b int, c int);
+CREATE TABLE t7 (a int, b int, c int);
+CREATE TABLE t8 (a int, b int, c int);
+CREATE TABLE t9 (a int, b int, c int);
+INSERT INTO t0 VALUES (1,1,0), (1,2,0), (2,2,0);
+INSERT INTO t1 VALUES (1,3,0), (2,2,0), (3,2,0);
+INSERT INTO t2 VALUES (3,3,0), (4,2,0), (5,3,0);
+INSERT INTO t3 VALUES (1,2,0), (2,2,0);
+INSERT INTO t4 VALUES (3,2,0), (4,2,0);
+INSERT INTO t5 VALUES (3,1,0), (2,2,0), (3,3,0);
+INSERT INTO t6 VALUES (3,2,0), (6,2,0), (6,1,0);
+INSERT INTO t7 VALUES (1,1,0), (2,2,0);
+INSERT INTO t8 VALUES (0,2,0), (1,2,0);
+INSERT INTO t9 VALUES (1,1,0), (1,2,0), (3,3,0);
+SELECT t2.a,t2.b
+FROM t2;
+a b
+3 3
+4 2
+5 3
+SELECT t3.a,t3.b
+FROM t3;
+a b
+1 2
+2 2
+SELECT t4.a,t4.b
+FROM t4;
+a b
+3 2
+4 2
+SELECT t3.a,t3.b,t4.a,t4.b
+FROM t3,t4;
+a b a b
+1 2 3 2
+2 2 3 2
+1 2 4 2
+2 2 4 2
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t2.b=t4.b;
+a b a b a b
+3 3 NULL NULL NULL NULL
+4 2 1 2 3 2
+4 2 1 2 4 2
+4 2 2 2 3 2
+4 2 2 2 4 2
+5 3 NULL NULL NULL NULL
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b;
+a b a b a b
+3 3 NULL NULL NULL NULL
+4 2 1 2 3 2
+4 2 1 2 4 2
+5 3 NULL NULL NULL NULL
+EXPLAIN EXTENDED
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t2.b=t4.b
+WHERE t3.a=1 OR t3.c IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 2
+Warnings:
+Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t2` left join (`test`.`t3` join `test`.`t4`) on((`test`.`t4`.`b` = `test`.`t2`.`b`)) where ((`test`.`t3`.`a` = 1) or isnull(`test`.`t3`.`c`))
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t2.b=t4.b
+WHERE t3.a=1 OR t3.c IS NULL;
+a b a b a b
+3 3 NULL NULL NULL NULL
+4 2 1 2 3 2
+4 2 1 2 4 2
+5 3 NULL NULL NULL NULL
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t2.b=t4.b
+WHERE t3.a>1 OR t3.c IS NULL;
+a b a b a b
+3 3 NULL NULL NULL NULL
+4 2 2 2 3 2
+4 2 2 2 4 2
+5 3 NULL NULL NULL NULL
+SELECT t5.a,t5.b
+FROM t5;
+a b
+3 1
+2 2
+3 3
+SELECT t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+FROM t3,t4,t5;
+a b a b a b
+1 2 3 2 3 1
+2 2 3 2 3 1
+1 2 4 2 3 1
+2 2 4 2 3 1
+1 2 3 2 2 2
+2 2 3 2 2 2
+1 2 4 2 2 2
+2 2 4 2 2 2
+1 2 3 2 3 3
+2 2 3 2 3 3
+1 2 4 2 3 3
+2 2 4 2 3 3
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+FROM t2
+LEFT JOIN
+(t3, t4, t5)
+ON t2.b=t4.b;
+a b a b a b a b
+3 3 NULL NULL NULL NULL NULL NULL
+4 2 1 2 3 2 3 1
+4 2 1 2 3 2 2 2
+4 2 1 2 3 2 3 3
+4 2 1 2 4 2 3 1
+4 2 1 2 4 2 2 2
+4 2 1 2 4 2 3 3
+4 2 2 2 3 2 3 1
+4 2 2 2 3 2 2 2
+4 2 2 2 3 2 3 3
+4 2 2 2 4 2 3 1
+4 2 2 2 4 2 2 2
+4 2 2 2 4 2 3 3
+5 3 NULL NULL NULL NULL NULL NULL
+EXPLAIN EXTENDED
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+FROM t2
+LEFT JOIN
+(t3, t4, t5)
+ON t2.b=t4.b
+WHERE t3.a>1 OR t3.c IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 2
+1 SIMPLE t5 ALL NULL NULL NULL NULL 3
+Warnings:
+Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t5`.`a` AS `a`,`test`.`t5`.`b` AS `b` from `test`.`t2` left join (`test`.`t3` join `test`.`t4` join `test`.`t5`) on((`test`.`t4`.`b` = `test`.`t2`.`b`)) where ((`test`.`t3`.`a` > 1) or isnull(`test`.`t3`.`c`))
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+FROM t2
+LEFT JOIN
+(t3, t4, t5)
+ON t2.b=t4.b
+WHERE t3.a>1 OR t3.c IS NULL;
+a b a b a b a b
+3 3 NULL NULL NULL NULL NULL NULL
+4 2 2 2 3 2 3 1
+4 2 2 2 3 2 2 2
+4 2 2 2 3 2 3 3
+4 2 2 2 4 2 3 1
+4 2 2 2 4 2 2 2
+4 2 2 2 4 2 3 3
+5 3 NULL NULL NULL NULL NULL NULL
+EXPLAIN EXTENDED
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+FROM t2
+LEFT JOIN
+(t3, t4, t5)
+ON t2.b=t4.b
+WHERE (t3.a>1 OR t3.c IS NULL) AND
+(t5.a<3 OR t5.c IS NULL);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 2
+1 SIMPLE t5 ALL NULL NULL NULL NULL 3 Using where
+Warnings:
+Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t5`.`a` AS `a`,`test`.`t5`.`b` AS `b` from `test`.`t2` left join (`test`.`t3` join `test`.`t4` join `test`.`t5`) on((`test`.`t4`.`b` = `test`.`t2`.`b`)) where (((`test`.`t3`.`a` > 1) or isnull(`test`.`t3`.`c`)) and ((`test`.`t5`.`a` < 3) or isnull(`test`.`t5`.`c`)))
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+FROM t2
+LEFT JOIN
+(t3, t4, t5)
+ON t2.b=t4.b
+WHERE (t3.a>1 OR t3.c IS NULL) AND
+(t5.a<3 OR t5.c IS NULL);
+a b a b a b a b
+3 3 NULL NULL NULL NULL NULL NULL
+4 2 2 2 3 2 2 2
+4 2 2 2 4 2 2 2
+5 3 NULL NULL NULL NULL NULL NULL
+SELECT t6.a,t6.b
+FROM t6;
+a b
+3 2
+6 2
+6 1
+SELECT t7.a,t7.b
+FROM t7;
+a b
+1 1
+2 2
+SELECT t6.a,t6.b,t7.a,t7.b
+FROM t6,t7;
+a b a b
+3 2 1 1
+3 2 2 2
+6 2 1 1
+6 2 2 2
+6 1 1 1
+6 1 2 2
+SELECT t8.a,t8.b
+FROM t8;
+a b
+0 2
+1 2
+EXPLAIN EXTENDED
+SELECT t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM (t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t7 ALL NULL NULL NULL NULL 2
+1 SIMPLE t6 ALL NULL NULL NULL NULL 3
+1 SIMPLE t8 ALL NULL NULL NULL NULL 2
+Warnings:
+Note 1003 select `test`.`t6`.`a` AS `a`,`test`.`t6`.`b` AS `b`,`test`.`t7`.`a` AS `a`,`test`.`t7`.`b` AS `b`,`test`.`t8`.`a` AS `a`,`test`.`t8`.`b` AS `b` from `test`.`t6` join `test`.`t7` left join `test`.`t8` on(((`test`.`t7`.`b` = `test`.`t8`.`b`) and (`test`.`t6`.`b` < 10))) where 1
+SELECT t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM (t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10;
+a b a b a b
+3 2 1 1 NULL NULL
+3 2 2 2 0 2
+3 2 2 2 1 2
+6 2 1 1 NULL NULL
+6 2 2 2 0 2
+6 2 2 2 1 2
+6 1 1 1 NULL NULL
+6 1 2 2 0 2
+6 1 2 2 1 2
+SELECT t5.a,t5.b
+FROM t5;
+a b
+3 1
+2 2
+3 3
+SELECT t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b;
+a b a b a b a b
+3 1 3 2 1 1 NULL NULL
+3 1 6 2 1 1 NULL NULL
+2 2 3 2 2 2 0 2
+2 2 3 2 2 2 1 2
+2 2 6 2 2 2 0 2
+2 2 6 2 2 2 1 2
+3 3 NULL NULL NULL NULL NULL NULL
+SELECT t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b AND
+(t8.a < 1 OR t8.c IS NULL);
+a b a b a b a b
+3 1 3 2 1 1 NULL NULL
+3 1 6 2 1 1 NULL NULL
+2 2 3 2 2 2 0 2
+2 2 6 2 2 2 0 2
+3 3 NULL NULL NULL NULL NULL NULL
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b;
+a b a b a b
+3 3 NULL NULL NULL NULL
+4 2 1 2 3 2
+4 2 1 2 4 2
+5 3 NULL NULL NULL NULL
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b;
+a b a b a b a b a b a b a b
+3 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+3 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+4 2 1 2 3 2 3 1 3 2 1 1 NULL NULL
+4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL
+4 2 1 2 4 2 3 1 3 2 1 1 NULL NULL
+4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL
+5 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+3 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+3 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+3 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+3 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+4 2 1 2 3 2 2 2 3 2 2 2 0 2
+4 2 1 2 3 2 2 2 3 2 2 2 1 2
+4 2 1 2 3 2 2 2 6 2 2 2 0 2
+4 2 1 2 3 2 2 2 6 2 2 2 1 2
+4 2 1 2 4 2 2 2 3 2 2 2 0 2
+4 2 1 2 4 2 2 2 3 2 2 2 1 2
+4 2 1 2 4 2 2 2 6 2 2 2 0 2
+4 2 1 2 4 2 2 2 6 2 2 2 1 2
+5 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+5 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+5 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+3 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL
+4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL
+5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+WHERE t2.a > 3 AND
+(t6.a < 6 OR t6.c IS NULL);
+a b a b a b a b a b a b a b
+4 2 1 2 3 2 3 1 3 2 1 1 NULL NULL
+4 2 1 2 4 2 3 1 3 2 1 1 NULL NULL
+5 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+4 2 1 2 3 2 2 2 3 2 2 2 0 2
+4 2 1 2 3 2 2 2 3 2 2 2 1 2
+4 2 1 2 4 2 2 2 3 2 2 2 0 2
+4 2 1 2 4 2 2 2 3 2 2 2 1 2
+5 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+5 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL
+4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL
+5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+SELECT t1.a,t1.b
+FROM t1;
+a b
+1 3
+2 2
+3 2
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2);
+a b a b a b a b a b a b a b a b
+1 3 3 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+1 3 3 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+1 3 3 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+1 3 3 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+1 3 3 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+1 3 3 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+1 3 3 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+1 3 4 2 1 2 3 2 3 1 3 2 1 1 NULL NULL
+1 3 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL
+1 3 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL
+1 3 4 2 1 2 4 2 3 1 3 2 1 1 NULL NULL
+1 3 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL
+1 3 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL
+1 3 5 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+1 3 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+1 3 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+1 3 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+1 3 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+1 3 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+1 3 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+2 2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+3 2 3 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+3 2 3 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+3 2 3 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+3 2 3 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+3 2 3 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+3 2 3 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+3 2 3 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+3 2 4 2 1 2 3 2 3 1 3 2 1 1 NULL NULL
+3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL
+3 2 4 2 1 2 3 2 2 2 3 2 2 2 0 2
+3 2 4 2 1 2 3 2 2 2 3 2 2 2 1 2
+3 2 4 2 1 2 3 2 2 2 6 2 2 2 0 2
+3 2 4 2 1 2 3 2 2 2 6 2 2 2 1 2
+3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL
+3 2 4 2 1 2 4 2 3 1 3 2 1 1 NULL NULL
+3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL
+3 2 4 2 1 2 4 2 2 2 3 2 2 2 0 2
+3 2 4 2 1 2 4 2 2 2 3 2 2 2 1 2
+3 2 4 2 1 2 4 2 2 2 6 2 2 2 0 2
+3 2 4 2 1 2 4 2 2 2 6 2 2 2 1 2
+3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL
+3 2 5 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+3 2 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+3 2 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2)
+WHERE (t2.a >= 4 OR t2.c IS NULL);
+a b a b a b a b a b a b a b a b
+1 3 4 2 1 2 3 2 3 1 3 2 1 1 NULL NULL
+1 3 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL
+1 3 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL
+1 3 4 2 1 2 4 2 3 1 3 2 1 1 NULL NULL
+1 3 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL
+1 3 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL
+1 3 5 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+1 3 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+1 3 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+1 3 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+1 3 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+1 3 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+1 3 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+2 2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+3 2 4 2 1 2 3 2 3 1 3 2 1 1 NULL NULL
+3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL
+3 2 4 2 1 2 3 2 2 2 3 2 2 2 0 2
+3 2 4 2 1 2 3 2 2 2 3 2 2 2 1 2
+3 2 4 2 1 2 3 2 2 2 6 2 2 2 0 2
+3 2 4 2 1 2 3 2 2 2 6 2 2 2 1 2
+3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL
+3 2 4 2 1 2 4 2 3 1 3 2 1 1 NULL NULL
+3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL
+3 2 4 2 1 2 4 2 2 2 3 2 2 2 0 2
+3 2 4 2 1 2 4 2 2 2 3 2 2 2 1 2
+3 2 4 2 1 2 4 2 2 2 6 2 2 2 0 2
+3 2 4 2 1 2 4 2 2 2 6 2 2 2 1 2
+3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL
+3 2 5 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+3 2 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+3 2 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+SELECT t0.a,t0.b
+FROM t0;
+a b
+1 1
+1 2
+2 2
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2)
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2
+1 SIMPLE t4 ALL NULL NULL NULL NULL 2
+1 SIMPLE t5 ALL NULL NULL NULL NULL 3
+1 SIMPLE t7 ALL NULL NULL NULL NULL 2
+1 SIMPLE t6 ALL NULL NULL NULL NULL 3
+1 SIMPLE t8 ALL NULL NULL NULL NULL 2
+Warnings:
+Note 1003 select `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t5`.`a` AS `a`,`test`.`t5`.`b` AS `b`,`test`.`t6`.`a` AS `a`,`test`.`t6`.`b` AS `b`,`test`.`t7`.`a` AS `a`,`test`.`t7`.`b` AS `b`,`test`.`t8`.`a` AS `a`,`test`.`t8`.`b` AS `b` from `test`.`t0` join `test`.`t1` left join (`test`.`t2` left join (`test`.`t3` join `test`.`t4`) on(((`test`.`t4`.`b` = `test`.`t2`.`b`) and (`test`.`t3`.`a` = 1))) join `test`.`t5` left join (`test`.`t6` join `test`.`t7` left join `test`.`t8` on(((`test`.`t8`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` < 10)))) on(((`test`.`t7`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` >= 2)))) on((((`test`.`t3`.`b` = 2) or isnull(`test`.`t3`.`c`)) and ((`test`.`t6`.`b` = 2) or isnull(`test`.`t6`.`c`)) and ((`test`.`t5`.`b` = `test`.`t0`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t6`.`c`) or isnull(`test`.`t8`.`c`)) and (`test`.`t1`.`a` <> 2))) where ((`test`.`t1`.`b` = `test`.`t0`.`b`) and (`test`.`t0`.`a` = 1) and ((`test`.`t2`.`a` >= 4) or isnull(`test`.`t2`.`c`)))
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2)
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL);
+a b a b a b a b a b a b a b a b a b
+1 2 2 2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+1 2 3 2 4 2 1 2 3 2 3 1 3 2 1 1 NULL NULL
+1 2 3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL
+1 2 3 2 4 2 1 2 3 2 2 2 3 2 2 2 0 2
+1 2 3 2 4 2 1 2 3 2 2 2 3 2 2 2 1 2
+1 2 3 2 4 2 1 2 3 2 2 2 6 2 2 2 0 2
+1 2 3 2 4 2 1 2 3 2 2 2 6 2 2 2 1 2
+1 2 3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL
+1 2 3 2 4 2 1 2 4 2 3 1 3 2 1 1 NULL NULL
+1 2 3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL
+1 2 3 2 4 2 1 2 4 2 2 2 3 2 2 2 0 2
+1 2 3 2 4 2 1 2 4 2 2 2 3 2 2 2 1 2
+1 2 3 2 4 2 1 2 4 2 2 2 6 2 2 2 0 2
+1 2 3 2 4 2 1 2 4 2 2 2 6 2 2 2 1 2
+1 2 3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL
+1 2 3 2 5 3 NULL NULL NULL NULL 3 1 3 2 1 1 NULL NULL
+1 2 3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL
+1 2 3 2 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 0 2
+1 2 3 2 5 3 NULL NULL NULL NULL 2 2 3 2 2 2 1 2
+1 2 3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2
+1 2 3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 1 2
+1 2 3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2),
+t9
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL) AND
+(t3.a < 5 OR t3.c IS NULL) AND
+(t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+(t5.a >=2 OR t5.c IS NULL) AND
+(t6.a >=4 OR t6.c IS NULL) AND
+(t7.a <= 2 OR t7.c IS NULL) AND
+(t8.a < 1 OR t8.c IS NULL) AND
+(t8.b=t9.b OR t8.c IS NULL) AND
+(t9.a=1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t5 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t8 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t9 ALL NULL NULL NULL NULL 3 Using where
+Warnings:
+Note 1003 select `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t5`.`a` AS `a`,`test`.`t5`.`b` AS `b`,`test`.`t6`.`a` AS `a`,`test`.`t6`.`b` AS `b`,`test`.`t7`.`a` AS `a`,`test`.`t7`.`b` AS `b`,`test`.`t8`.`a` AS `a`,`test`.`t8`.`b` AS `b`,`test`.`t9`.`a` AS `a`,`test`.`t9`.`b` AS `b` from `test`.`t0` join `test`.`t1` left join (`test`.`t2` left join (`test`.`t3` join `test`.`t4`) on(((`test`.`t4`.`b` = `test`.`t2`.`b`) and (`test`.`t3`.`a` = 1))) join `test`.`t5` left join (`test`.`t6` join `test`.`t7` left join `test`.`t8` on(((`test`.`t8`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` < 10)))) on(((`test`.`t7`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` >= 2)))) on((((`test`.`t3`.`b` = 2) or isnull(`test`.`t3`.`c`)) and ((`test`.`t6`.`b` = 2) or isnull(`test`.`t6`.`c`)) and ((`test`.`t5`.`b` = `test`.`t0`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t6`.`c`) or isnull(`test`.`t8`.`c`)) and (`test`.`t1`.`a` <> 2))) join `test`.`t9` where ((`test`.`t9`.`a` = 1) and (`test`.`t1`.`b` = `test`.`t0`.`b`) and (`test`.`t0`.`a` = 1) and ((`test`.`t2`.`a` >= 4) or isnull(`test`.`t2`.`c`)) and ((`test`.`t3`.`a` < 5) or isnull(`test`.`t3`.`c`)) and ((`test`.`t4`.`b` = `test`.`t3`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t4`.`c`)) and ((`test`.`t5`.`a` >= 2) or isnull(`test`.`t5`.`c`)) and ((`test`.`t6`.`a` >= 4) or isnull(`test`.`t6`.`c`)) and ((`test`.`t7`.`a` <= 2) or isnull(`test`.`t7`.`c`)) and ((`test`.`t8`.`a` < 1) or isnull(`test`.`t8`.`c`)) and ((`test`.`t9`.`b` = `test`.`t8`.`b`) or isnull(`test`.`t8`.`c`)))
+SELECT t9.a,t9.b
+FROM t9;
+a b
+1 1
+1 2
+3 3
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2),
+t9
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL) AND
+(t3.a < 5 OR t3.c IS NULL) AND
+(t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+(t5.a >=2 OR t5.c IS NULL) AND
+(t6.a >=4 OR t6.c IS NULL) AND
+(t7.a <= 2 OR t7.c IS NULL) AND
+(t8.a < 1 OR t8.c IS NULL) AND
+(t8.b=t9.b OR t8.c IS NULL) AND
+(t9.a=1);
+a b a b a b a b a b a b a b a b a b a b
+1 2 2 2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 1
+1 2 3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL 1 1
+1 2 3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL 1 1
+1 2 3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL 1 1
+1 2 3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL 1 1
+1 2 3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL 1 1
+1 2 3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL 1 1
+1 2 2 2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 2
+1 2 3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL 1 2
+1 2 3 2 4 2 1 2 3 2 2 2 6 2 2 2 0 2 1 2
+1 2 3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL 1 2
+1 2 3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL 1 2
+1 2 3 2 4 2 1 2 4 2 2 2 6 2 2 2 0 2 1 2
+1 2 3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL 1 2
+1 2 3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL 1 2
+1 2 3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2 1 2
+1 2 3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL 1 2
+SELECT t1.a,t1.b
+FROM t1;
+a b
+1 3
+2 2
+3 2
+SELECT t2.a,t2.b
+FROM t2;
+a b
+3 3
+4 2
+5 3
+SELECT t3.a,t3.b
+FROM t3;
+a b
+1 2
+2 2
+SELECT t2.a,t2.b,t3.a,t3.b
+FROM t2
+LEFT JOIN
+t3
+ON t2.b=t3.b;
+a b a b
+3 3 NULL NULL
+4 2 1 2
+4 2 2 2
+5 3 NULL NULL
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b
+FROM t1, t2
+LEFT JOIN
+t3
+ON t2.b=t3.b
+WHERE t1.a <= 2;
+a b a b a b
+1 3 3 3 NULL NULL
+2 2 3 3 NULL NULL
+1 3 4 2 1 2
+1 3 4 2 2 2
+2 2 4 2 1 2
+2 2 4 2 2 2
+1 3 5 3 NULL NULL
+2 2 5 3 NULL NULL
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b
+FROM t1, t3
+RIGHT JOIN
+t2
+ON t2.b=t3.b
+WHERE t1.a <= 2;
+a b a b a b
+1 3 3 3 NULL NULL
+2 2 3 3 NULL NULL
+1 3 4 2 1 2
+1 3 4 2 2 2
+2 2 4 2 1 2
+2 2 4 2 2 2
+1 3 5 3 NULL NULL
+2 2 5 3 NULL NULL
+SELECT t3.a,t3.b,t4.a,t4.b
+FROM t3,t4;
+a b a b
+1 2 3 2
+2 2 3 2
+1 2 4 2
+2 2 4 2
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b;
+a b a b a b
+3 3 NULL NULL NULL NULL
+4 2 1 2 3 2
+4 2 1 2 4 2
+5 3 NULL NULL NULL NULL
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t1, t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b
+WHERE t1.a <= 2;
+a b a b a b a b
+1 3 3 3 NULL NULL NULL NULL
+2 2 3 3 NULL NULL NULL NULL
+1 3 4 2 1 2 3 2
+1 3 4 2 1 2 4 2
+2 2 4 2 1 2 3 2
+2 2 4 2 1 2 4 2
+1 3 5 3 NULL NULL NULL NULL
+2 2 5 3 NULL NULL NULL NULL
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t1, (t3, t4)
+RIGHT JOIN
+t2
+ON t3.a=1 AND t2.b=t4.b
+WHERE t1.a <= 2;
+a b a b a b a b
+1 3 3 3 NULL NULL NULL NULL
+2 2 3 3 NULL NULL NULL NULL
+1 3 4 2 1 2 3 2
+1 3 4 2 1 2 4 2
+2 2 4 2 1 2 3 2
+2 2 4 2 1 2 4 2
+1 3 5 3 NULL NULL NULL NULL
+2 2 5 3 NULL NULL NULL NULL
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t1, (t3, t4)
+RIGHT JOIN
+t2
+ON t3.a=1 AND t2.b=t4.b
+WHERE t1.a <= 2;
+a b a b a b a b
+1 3 3 3 NULL NULL NULL NULL
+2 2 3 3 NULL NULL NULL NULL
+1 3 4 2 1 2 3 2
+1 3 4 2 1 2 4 2
+2 2 4 2 1 2 3 2
+2 2 4 2 1 2 4 2
+1 3 5 3 NULL NULL NULL NULL
+2 2 5 3 NULL NULL NULL NULL
+EXPLAIN EXTENDED
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM t1, (t3, t4)
+RIGHT JOIN
+t2
+ON t3.a=1 AND t2.b=t4.b
+WHERE t1.a <= 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2
+1 SIMPLE t4 ALL NULL NULL NULL NULL 2
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t1` join `test`.`t2` left join (`test`.`t3` join `test`.`t4`) on(((`test`.`t4`.`b` = `test`.`t2`.`b`) and (`test`.`t3`.`a` = 1))) where (`test`.`t1`.`a` <= 2)
+CREATE INDEX idx_b ON t2(b);
+EXPLAIN EXTENDED
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM (t3,t4)
+LEFT JOIN
+(t1,t2)
+ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2
+1 SIMPLE t4 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ref idx_b idx_b 5 test.t3.b 2
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+Warnings:
+Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t3` join `test`.`t4` left join (`test`.`t1` join `test`.`t2`) on(((`test`.`t3`.`a` = 1) and (`test`.`t3`.`b` = `test`.`t2`.`b`) and (`test`.`t2`.`b` = `test`.`t4`.`b`))) where 1
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+FROM (t3,t4)
+LEFT JOIN
+(t1,t2)
+ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b;
+a b a b a b
+4 2 1 2 3 2
+4 2 1 2 3 2
+4 2 1 2 3 2
+NULL NULL 2 2 3 2
+4 2 1 2 4 2
+4 2 1 2 4 2
+4 2 1 2 4 2
+NULL NULL 2 2 4 2
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2),
+t9
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL) AND
+(t3.a < 5 OR t3.c IS NULL) AND
+(t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+(t5.a >=2 OR t5.c IS NULL) AND
+(t6.a >=4 OR t6.c IS NULL) AND
+(t7.a <= 2 OR t7.c IS NULL) AND
+(t8.a < 1 OR t8.c IS NULL) AND
+(t8.b=t9.b OR t8.c IS NULL) AND
+(t9.a=1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t4 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t5 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t8 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t9 ALL NULL NULL NULL NULL 3 Using where
+Warnings:
+Note 1003 select `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t5`.`a` AS `a`,`test`.`t5`.`b` AS `b`,`test`.`t6`.`a` AS `a`,`test`.`t6`.`b` AS `b`,`test`.`t7`.`a` AS `a`,`test`.`t7`.`b` AS `b`,`test`.`t8`.`a` AS `a`,`test`.`t8`.`b` AS `b`,`test`.`t9`.`a` AS `a`,`test`.`t9`.`b` AS `b` from `test`.`t0` join `test`.`t1` left join (`test`.`t2` left join (`test`.`t3` join `test`.`t4`) on(((`test`.`t4`.`b` = `test`.`t2`.`b`) and (`test`.`t3`.`a` = 1))) join `test`.`t5` left join (`test`.`t6` join `test`.`t7` left join `test`.`t8` on(((`test`.`t8`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` < 10)))) on(((`test`.`t7`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` >= 2)))) on((((`test`.`t3`.`b` = 2) or isnull(`test`.`t3`.`c`)) and ((`test`.`t6`.`b` = 2) or isnull(`test`.`t6`.`c`)) and ((`test`.`t5`.`b` = `test`.`t0`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t6`.`c`) or isnull(`test`.`t8`.`c`)) and (`test`.`t1`.`a` <> 2))) join `test`.`t9` where ((`test`.`t9`.`a` = 1) and (`test`.`t1`.`b` = `test`.`t0`.`b`) and (`test`.`t0`.`a` = 1) and ((`test`.`t2`.`a` >= 4) or isnull(`test`.`t2`.`c`)) and ((`test`.`t3`.`a` < 5) or isnull(`test`.`t3`.`c`)) and ((`test`.`t4`.`b` = `test`.`t3`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t4`.`c`)) and ((`test`.`t5`.`a` >= 2) or isnull(`test`.`t5`.`c`)) and ((`test`.`t6`.`a` >= 4) or isnull(`test`.`t6`.`c`)) and ((`test`.`t7`.`a` <= 2) or isnull(`test`.`t7`.`c`)) and ((`test`.`t8`.`a` < 1) or isnull(`test`.`t8`.`c`)) and ((`test`.`t9`.`b` = `test`.`t8`.`b`) or isnull(`test`.`t8`.`c`)))
+CREATE INDEX idx_b ON t4(b);
+CREATE INDEX idx_b ON t5(b);
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2),
+t9
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL) AND
+(t3.a < 5 OR t3.c IS NULL) AND
+(t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+(t5.a >=2 OR t5.c IS NULL) AND
+(t6.a >=4 OR t6.c IS NULL) AND
+(t7.a <= 2 OR t7.c IS NULL) AND
+(t8.a < 1 OR t8.c IS NULL) AND
+(t8.b=t9.b OR t8.c IS NULL) AND
+(t9.a=1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t4 ref idx_b idx_b 5 test.t2.b 2 Using where
+1 SIMPLE t5 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t8 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t9 ALL NULL NULL NULL NULL 3 Using where
+Warnings:
+Note 1003 select `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t5`.`a` AS `a`,`test`.`t5`.`b` AS `b`,`test`.`t6`.`a` AS `a`,`test`.`t6`.`b` AS `b`,`test`.`t7`.`a` AS `a`,`test`.`t7`.`b` AS `b`,`test`.`t8`.`a` AS `a`,`test`.`t8`.`b` AS `b`,`test`.`t9`.`a` AS `a`,`test`.`t9`.`b` AS `b` from `test`.`t0` join `test`.`t1` left join (`test`.`t2` left join (`test`.`t3` join `test`.`t4`) on(((`test`.`t4`.`b` = `test`.`t2`.`b`) and (`test`.`t3`.`a` = 1))) join `test`.`t5` left join (`test`.`t6` join `test`.`t7` left join `test`.`t8` on(((`test`.`t8`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` < 10)))) on(((`test`.`t7`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` >= 2)))) on((((`test`.`t3`.`b` = 2) or isnull(`test`.`t3`.`c`)) and ((`test`.`t6`.`b` = 2) or isnull(`test`.`t6`.`c`)) and ((`test`.`t5`.`b` = `test`.`t0`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t6`.`c`) or isnull(`test`.`t8`.`c`)) and (`test`.`t1`.`a` <> 2))) join `test`.`t9` where ((`test`.`t9`.`a` = 1) and (`test`.`t1`.`b` = `test`.`t0`.`b`) and (`test`.`t0`.`a` = 1) and ((`test`.`t2`.`a` >= 4) or isnull(`test`.`t2`.`c`)) and ((`test`.`t3`.`a` < 5) or isnull(`test`.`t3`.`c`)) and ((`test`.`t4`.`b` = `test`.`t3`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t4`.`c`)) and ((`test`.`t5`.`a` >= 2) or isnull(`test`.`t5`.`c`)) and ((`test`.`t6`.`a` >= 4) or isnull(`test`.`t6`.`c`)) and ((`test`.`t7`.`a` <= 2) or isnull(`test`.`t7`.`c`)) and ((`test`.`t8`.`a` < 1) or isnull(`test`.`t8`.`c`)) and ((`test`.`t9`.`b` = `test`.`t8`.`b`) or isnull(`test`.`t8`.`c`)))
+CREATE INDEX idx_b ON t8(b);
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2),
+t9
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL) AND
+(t3.a < 5 OR t3.c IS NULL) AND
+(t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+(t5.a >=2 OR t5.c IS NULL) AND
+(t6.a >=4 OR t6.c IS NULL) AND
+(t7.a <= 2 OR t7.c IS NULL) AND
+(t8.a < 1 OR t8.c IS NULL) AND
+(t8.b=t9.b OR t8.c IS NULL) AND
+(t9.a=1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t4 ref idx_b idx_b 5 test.t2.b 2 Using where
+1 SIMPLE t5 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t8 ref idx_b idx_b 5 test.t5.b 2 Using where
+1 SIMPLE t9 ALL NULL NULL NULL NULL 3 Using where
+Warnings:
+Note 1003 select `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t5`.`a` AS `a`,`test`.`t5`.`b` AS `b`,`test`.`t6`.`a` AS `a`,`test`.`t6`.`b` AS `b`,`test`.`t7`.`a` AS `a`,`test`.`t7`.`b` AS `b`,`test`.`t8`.`a` AS `a`,`test`.`t8`.`b` AS `b`,`test`.`t9`.`a` AS `a`,`test`.`t9`.`b` AS `b` from `test`.`t0` join `test`.`t1` left join (`test`.`t2` left join (`test`.`t3` join `test`.`t4`) on(((`test`.`t4`.`b` = `test`.`t2`.`b`) and (`test`.`t3`.`a` = 1))) join `test`.`t5` left join (`test`.`t6` join `test`.`t7` left join `test`.`t8` on(((`test`.`t8`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` < 10)))) on(((`test`.`t7`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` >= 2)))) on((((`test`.`t3`.`b` = 2) or isnull(`test`.`t3`.`c`)) and ((`test`.`t6`.`b` = 2) or isnull(`test`.`t6`.`c`)) and ((`test`.`t5`.`b` = `test`.`t0`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t6`.`c`) or isnull(`test`.`t8`.`c`)) and (`test`.`t1`.`a` <> 2))) join `test`.`t9` where ((`test`.`t9`.`a` = 1) and (`test`.`t1`.`b` = `test`.`t0`.`b`) and (`test`.`t0`.`a` = 1) and ((`test`.`t2`.`a` >= 4) or isnull(`test`.`t2`.`c`)) and ((`test`.`t3`.`a` < 5) or isnull(`test`.`t3`.`c`)) and ((`test`.`t4`.`b` = `test`.`t3`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t4`.`c`)) and ((`test`.`t5`.`a` >= 2) or isnull(`test`.`t5`.`c`)) and ((`test`.`t6`.`a` >= 4) or isnull(`test`.`t6`.`c`)) and ((`test`.`t7`.`a` <= 2) or isnull(`test`.`t7`.`c`)) and ((`test`.`t8`.`a` < 1) or isnull(`test`.`t8`.`c`)) and ((`test`.`t9`.`b` = `test`.`t8`.`b`) or isnull(`test`.`t8`.`c`)))
+CREATE INDEX idx_b ON t1(b);
+CREATE INDEX idx_a ON t0(a);
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2),
+t9
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL) AND
+(t3.a < 5 OR t3.c IS NULL) AND
+(t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+(t5.a >=2 OR t5.c IS NULL) AND
+(t6.a >=4 OR t6.c IS NULL) AND
+(t7.a <= 2 OR t7.c IS NULL) AND
+(t8.a < 1 OR t8.c IS NULL) AND
+(t8.b=t9.b OR t8.c IS NULL) AND
+(t9.a=1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ref idx_a idx_a 5 const 1 Using where
+1 SIMPLE t1 ref idx_b idx_b 5 test.t0.b 2 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t4 ref idx_b idx_b 5 test.t2.b 2 Using where
+1 SIMPLE t5 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t7 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE t6 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t8 ref idx_b idx_b 5 test.t5.b 2 Using where
+1 SIMPLE t9 ALL NULL NULL NULL NULL 3 Using where
+Warnings:
+Note 1003 select `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t5`.`a` AS `a`,`test`.`t5`.`b` AS `b`,`test`.`t6`.`a` AS `a`,`test`.`t6`.`b` AS `b`,`test`.`t7`.`a` AS `a`,`test`.`t7`.`b` AS `b`,`test`.`t8`.`a` AS `a`,`test`.`t8`.`b` AS `b`,`test`.`t9`.`a` AS `a`,`test`.`t9`.`b` AS `b` from `test`.`t0` join `test`.`t1` left join (`test`.`t2` left join (`test`.`t3` join `test`.`t4`) on(((`test`.`t4`.`b` = `test`.`t2`.`b`) and (`test`.`t3`.`a` = 1))) join `test`.`t5` left join (`test`.`t6` join `test`.`t7` left join `test`.`t8` on(((`test`.`t8`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` < 10)))) on(((`test`.`t7`.`b` = `test`.`t5`.`b`) and (`test`.`t6`.`b` >= 2)))) on((((`test`.`t3`.`b` = 2) or isnull(`test`.`t3`.`c`)) and ((`test`.`t6`.`b` = 2) or isnull(`test`.`t6`.`c`)) and ((`test`.`t5`.`b` = `test`.`t0`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t6`.`c`) or isnull(`test`.`t8`.`c`)) and (`test`.`t1`.`a` <> 2))) join `test`.`t9` where ((`test`.`t9`.`a` = 1) and (`test`.`t1`.`b` = `test`.`t0`.`b`) and (`test`.`t0`.`a` = 1) and ((`test`.`t2`.`a` >= 4) or isnull(`test`.`t2`.`c`)) and ((`test`.`t3`.`a` < 5) or isnull(`test`.`t3`.`c`)) and ((`test`.`t4`.`b` = `test`.`t3`.`b`) or isnull(`test`.`t3`.`c`) or isnull(`test`.`t4`.`c`)) and ((`test`.`t5`.`a` >= 2) or isnull(`test`.`t5`.`c`)) and ((`test`.`t6`.`a` >= 4) or isnull(`test`.`t6`.`c`)) and ((`test`.`t7`.`a` <= 2) or isnull(`test`.`t7`.`c`)) and ((`test`.`t8`.`a` < 1) or isnull(`test`.`t8`.`c`)) and ((`test`.`t9`.`b` = `test`.`t8`.`b`) or isnull(`test`.`t8`.`c`)))
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+FROM t0,t1
+LEFT JOIN
+(
+t2
+LEFT JOIN
+(t3, t4)
+ON t3.a=1 AND t2.b=t4.b,
+t5
+LEFT JOIN
+(
+(t6, t7)
+LEFT JOIN
+t8
+ON t7.b=t8.b AND t6.b < 10
+)
+ON t6.b >= 2 AND t5.b=t7.b
+)
+ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+(t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+(t1.a != 2),
+t9
+WHERE t0.a=1 AND
+t0.b=t1.b AND
+(t2.a >= 4 OR t2.c IS NULL) AND
+(t3.a < 5 OR t3.c IS NULL) AND
+(t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+(t5.a >=2 OR t5.c IS NULL) AND
+(t6.a >=4 OR t6.c IS NULL) AND
+(t7.a <= 2 OR t7.c IS NULL) AND
+(t8.a < 1 OR t8.c IS NULL) AND
+(t8.b=t9.b OR t8.c IS NULL) AND
+(t9.a=1);
+a b a b a b a b a b a b a b a b a b a b
+1 2 2 2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 1
+1 2 3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL 1 1
+1 2 3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL 1 1
+1 2 3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL 1 1
+1 2 3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL 1 1
+1 2 3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL 1 1
+1 2 3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL 1 1
+1 2 2 2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 2
+1 2 3 2 4 2 1 2 3 2 3 1 6 2 1 1 NULL NULL 1 2
+1 2 3 2 4 2 1 2 3 2 2 2 6 2 2 2 0 2 1 2
+1 2 3 2 4 2 1 2 3 2 3 3 NULL NULL NULL NULL NULL NULL 1 2
+1 2 3 2 4 2 1 2 4 2 3 1 6 2 1 1 NULL NULL 1 2
+1 2 3 2 4 2 1 2 4 2 2 2 6 2 2 2 0 2 1 2
+1 2 3 2 4 2 1 2 4 2 3 3 NULL NULL NULL NULL NULL NULL 1 2
+1 2 3 2 5 3 NULL NULL NULL NULL 3 1 6 2 1 1 NULL NULL 1 2
+1 2 3 2 5 3 NULL NULL NULL NULL 2 2 6 2 2 2 0 2 1 2
+1 2 3 2 5 3 NULL NULL NULL NULL 3 3 NULL NULL NULL NULL NULL NULL 1 2
+SELECT t2.a,t2.b
+FROM t2;
+a b
+3 3
+4 2
+5 3
+SELECT t3.a,t3.b
+FROM t3;
+a b
+1 2
+2 2
+SELECT t2.a,t2.b,t3.a,t3.b
+FROM t2 LEFT JOIN t3 ON t2.b=t3.b
+WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL);
+a b a b
+4 2 1 2
+4 2 2 2
+5 3 NULL NULL
+SELECT t2.a,t2.b,t3.a,t3.b
+FROM t2 LEFT JOIN (t3) ON t2.b=t3.b
+WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL);
+a b a b
+4 2 1 2
+4 2 2 2
+5 3 NULL NULL
+ALTER TABLE t3
+CHANGE COLUMN a a1 int,
+CHANGE COLUMN c c1 int;
+SELECT t2.a,t2.b,t3.a1,t3.b
+FROM t2 LEFT JOIN t3 ON t2.b=t3.b
+WHERE t2.a = 4 OR (t2.a > 4 AND t3.a1 IS NULL);
+a b a1 b
+4 2 1 2
+4 2 2 2
+5 3 NULL NULL
+SELECT t2.a,t2.b,t3.a1,t3.b
+FROM t2 NATURAL LEFT JOIN t3
+WHERE t2.a = 4 OR (t2.a > 4 AND t3.a1 IS NULL);
+a b a1 b
+4 2 1 2
+4 2 2 2
+5 3 NULL NULL
+DROP TABLE t0,t1,t2,t3,t4,t5,t6,t7,t8,t9;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE TABLE t3 (a int);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t3 VALUES (2);
+INSERT INTO t1 VALUES (2);
+SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a) ON t1.a=t3.a;
+a a a
+1 NULL NULL
+2 2 2
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.a=t3.a;
+a a a
+1 NULL NULL
+2 2 2
+DELETE FROM t1 WHERE a=2;
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.a=t3.a;
+a a a
+1 NULL NULL
+DELETE FROM t2;
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.a=t3.a;
+a a a
+1 NULL NULL
+DROP TABLE t1,t2,t3;
+CREATE TABLE t1(a int, key (a));
+CREATE TABLE t2(b int, key (b));
+CREATE TABLE t3(c int, key (c));
+INSERT INTO t1 VALUES (NULL), (0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
+(10), (11), (12), (13), (14), (15), (16), (17), (18), (19);
+INSERT INTO t2 VALUES (NULL), (0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
+(10), (11), (12), (13), (14), (15), (16), (17), (18), (19);
+INSERT INTO t3 VALUES (0), (1), (2), (3), (4), (5);
+EXPLAIN SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON c < 3 and b = c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 21 Using index
+1 SIMPLE t3 index c c 5 NULL 6 Using index
+1 SIMPLE t2 ref b b 5 test.t3.c 2 Using index
+EXPLAIN SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 21 Using index
+1 SIMPLE t3 index c c 5 NULL 6 Using index
+1 SIMPLE t2 ref b b 5 test.t3.c 2 Using index
+SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
+a b c
+NULL 0 0
+NULL 1 1
+NULL 2 2
+0 0 0
+0 1 1
+0 2 2
+1 0 0
+1 1 1
+1 2 2
+2 0 0
+2 1 1
+2 2 2
+3 0 0
+3 1 1
+3 2 2
+4 0 0
+4 1 1
+4 2 2
+5 0 0
+5 1 1
+5 2 2
+6 0 0
+6 1 1
+6 2 2
+7 0 0
+7 1 1
+7 2 2
+8 0 0
+8 1 1
+8 2 2
+9 0 0
+9 1 1
+9 2 2
+10 0 0
+10 1 1
+10 2 2
+11 0 0
+11 1 1
+11 2 2
+12 0 0
+12 1 1
+12 2 2
+13 0 0
+13 1 1
+13 2 2
+14 0 0
+14 1 1
+14 2 2
+15 0 0
+15 1 1
+15 2 2
+16 0 0
+16 1 1
+16 2 2
+17 0 0
+17 1 1
+17 2 2
+18 0 0
+18 1 1
+18 2 2
+19 0 0
+19 1 1
+19 2 2
+DELETE FROM t3;
+EXPLAIN SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 21 Using index
+1 SIMPLE t3 index c c 5 NULL 0 Using index
+1 SIMPLE t2 ref b b 5 test.t3.c 2 Using index
+SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
+a b c
+NULL NULL NULL
+0 NULL NULL
+1 NULL NULL
+2 NULL NULL
+3 NULL NULL
+4 NULL NULL
+5 NULL NULL
+6 NULL NULL
+7 NULL NULL
+8 NULL NULL
+9 NULL NULL
+10 NULL NULL
+11 NULL NULL
+12 NULL NULL
+13 NULL NULL
+14 NULL NULL
+15 NULL NULL
+16 NULL NULL
+17 NULL NULL
+18 NULL NULL
+19 NULL NULL
+DROP TABLE t1,t2,t3;
+CREATE TABLE t1 (c11 int);
+CREATE TABLE t2 (c21 int);
+CREATE TABLE t3 (c31 int);
+INSERT INTO t1 VALUES (4), (5);
+SELECT * FROM t1 LEFT JOIN t2 ON c11=c21;
+c11 c21
+4 NULL
+5 NULL
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON c11=c21;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 system NULL NULL NULL NULL 0 const row not found
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON c21=c31) ON c11=c21;
+c11 c21 c31
+4 NULL NULL
+5 NULL NULL
+EXPLAIN SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON c21=c31) ON c11=c21;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL NULL NULL NULL NULL 0
+1 SIMPLE t3 ALL NULL NULL NULL NULL 0
+DROP TABLE t1,t2,t3;
+CREATE TABLE t1 (goods int(12) NOT NULL, price varchar(128) NOT NULL);
+INSERT INTO t1 VALUES (23, 2340), (26, 9900);
+CREATE TABLE t2 (goods int(12), name varchar(50), shop char(2));
+INSERT INTO t2 VALUES (23, 'as300', 'fr'), (26, 'as600', 'fr');
+create table t3 (groupid int(12) NOT NULL, goodsid int(12) NOT NULL);
+INSERT INTO t3 VALUES (3,23), (6,26);
+CREATE TABLE t4 (groupid int(12));
+INSERT INTO t4 VALUES (1), (2), (3), (4), (5), (6);
+SELECT * FROM
+(SELECT DISTINCT gl.groupid, gp.price
+FROM t4 gl
+LEFT JOIN
+(t3 g INNER JOIN t2 p ON g.goodsid = p.goods
+INNER JOIN t1 gp ON p.goods = gp.goods)
+ON gl.groupid = g.groupid and p.shop = 'fr') t;
+groupid price
+1 NULL
+2 NULL
+3 2340
+4 NULL
+5 NULL
+6 9900
+CREATE VIEW v1 AS
+SELECT g.groupid groupid, p.goods goods,
+p.name name, p.shop shop,
+gp.price price
+FROM t3 g INNER JOIN t2 p ON g.goodsid = p.goods
+INNER JOIN t1 gp on p.goods = gp.goods;
+CREATE VIEW v2 AS
+SELECT DISTINCT g.groupid, fr.price
+FROM t4 g
+LEFT JOIN
+v1 fr on g.groupid = fr.groupid and fr.shop = 'fr';
+SELECT * FROM v2;
+groupid price
+1 NULL
+2 NULL
+3 2340
+4 NULL
+5 NULL
+6 9900
+SELECT * FROM
+(SELECT DISTINCT g.groupid, fr.price
+FROM t4 g
+LEFT JOIN
+v1 fr on g.groupid = fr.groupid and fr.shop = 'fr') t;
+groupid price
+1 NULL
+2 NULL
+3 2340
+4 NULL
+5 NULL
+6 9900
+DROP VIEW v1,v2;
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index d5ae1a58e83..92b352aa608 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2,t3,t4,t5;
+drop table if exists t0,t1,t2,t3,t4,t5;
CREATE TABLE t1 (
grp int(11) default NULL,
a bigint(20) unsigned default NULL,
@@ -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 42S22: Unknown column 't3.a' in 'on clause'
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 42S22: Unknown column 't3.a' in 'on clause'
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 42S22: Unknown column 't3.a' in 'on clause'
select t1.*,t2.* from t1 inner join t2 using (a);
grp a c id a c d
1 1 a 1 1 a 1
@@ -124,8 +124,8 @@ grp a c id a c d
3 5 C 3 5 B 5
3 6 D 3 6 C 6
select t1.*,t2.* from t1 natural join t2;
-grp a c id d
-1 1 a 1 1
+grp a c id a c d
+1 1 a 1 1 a 1
drop table t1,t2;
CREATE TABLE t1 (
usr_id INT unsigned NOT NULL,
@@ -200,7 +200,7 @@ INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas
INSERT INTO t1 VALUES (11403,'Projecte Fi de Carrera','Proyecto Fin de Carrera','Projecte Fi de Carrera','PFC',9.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11404,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',15.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11405,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',18.0,NULL,NULL,NULL);
-INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
CREATE TABLE t2 (
idAssignatura int(11) DEFAULT '0' NOT NULL,
Grup int(11) DEFAULT '0' NOT NULL,
@@ -356,13 +356,7 @@ select t1.name, t2.name, t2.id, t2.owner, t3.id from t1 left join t2 on (t1.id =
name name id owner id
Antonio Paz El Gato 1 1 1
Antonio Paz Perrito 2 1 1
-Lilliana Angelovska NULL NULL NULL 1
-Thimble Smith NULL NULL NULL 1
-Antonio Paz NULL NULL NULL 2
-Lilliana Angelovska NULL NULL NULL 2
-Thimble Smith NULL NULL NULL 2
-Antonio Paz NULL NULL NULL 3
-Lilliana Angelovska NULL NULL NULL 3
+NULL NULL NULL NULL 2
Thimble Smith Happy 3 3 3
drop table t1,t2;
create table t1 (id int not null, str char(10), index(str));
@@ -406,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 42S22: Unknown column 't2.t2_id' in 'on clause'
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));
@@ -467,10 +461,10 @@ count color
15 white
7 green
select * from t2 natural join t1;
-count color name
-10 green lime
-7 green lime
-5 black grape
+color count name
+green 10 lime
+green 7 lime
+black 5 grape
select t2.count, t1.name from t2 natural join t1;
count name
10 lime
@@ -634,7 +628,7 @@ insert into t2 values (10,1),(20,2),(30,3);
explain select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL PRIMARY 4 NULL 3 Using index
-1 SIMPLE t1 const PRIMARY PRIMARY 2 const 1 Using where; Using index
+1 SIMPLE t1 const PRIMARY PRIMARY 2 const 1 Using index
select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
fooID barID fooID
10 1 NULL
@@ -653,9 +647,22 @@ insert into t1 values(1),(2);
insert into t2 values(2),(3);
insert into t3 values(2),(4);
select * from t1 natural left join t2 natural left join t3;
-i i i
-1 NULL NULL
-2 2 2
+i
+1
+2
+select * from t1 natural left join t2 where (t2.i is not null)=0;
+i
+1
+select * from t1 natural left join t2 where (t2.i is not null) is not null;
+i
+1
+2
+select * from t1 natural left join t2 where (i is not null)=0;
+i
+select * from t1 natural left join t2 where (i is not null) is not null;
+i
+1
+2
drop table t1,t2,t3;
create table t1 (f1 integer,f2 integer,f3 integer);
create table t2 (f2 integer,f4 integer);
@@ -663,7 +670,7 @@ create table t3 (f3 integer,f5 integer);
select * from t1
left outer join t2 using (f2)
left outer join t3 using (f3);
-ERROR 42S22: Unknown column 'test.t2.f3' in 'on clause'
+f3 f2 f1 f4 f5
drop table t1,t2,t3;
create table t1 (a1 int, a2 int);
create table t2 (b1 int not null, b2 int);
@@ -729,13 +736,13 @@ explain select s.*, '*', m.*, (s.match_1_h - m.home) UUX from
order by m.match_id desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE s ALL NULL NULL NULL NULL 10
-1 SIMPLE m const match_id,match_id_2 match_id 1 const 1 Using where
+1 SIMPLE m const match_id,match_id_2 match_id 1 const 1
explain select s.*, '*', m.*, (s.match_1_h - m.home) UUX from
(t2 s left join t1 m on m.match_id = 1)
order by UUX desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE s ALL NULL NULL NULL NULL 10 Using temporary; Using filesort
-1 SIMPLE m const match_id,match_id_2 match_id 1 const 1 Using where
+1 SIMPLE m const match_id,match_id_2 match_id 1 const 1
select s.*, '*', m.*, (s.match_1_h - m.home) UUX from
(t2 s left join t1 m on m.match_id = 1)
order by UUX desc;
@@ -755,7 +762,7 @@ t2 s straight_join t1 m where m.match_id = 1
order by UUX desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE s ALL NULL NULL NULL NULL 10 Using temporary; Using filesort
-1 SIMPLE m const match_id,match_id_2 match_id 1 const 1 Using where
+1 SIMPLE m const match_id,match_id_2 match_id 1 const 1
select s.*, '*', m.*, (s.match_1_h - m.home) UUX from
t2 s straight_join t1 m where m.match_id = 1
order by UUX desc;
@@ -810,32 +817,91 @@ t2.flag_value IS NULL;
flag_name flag_value
flag2 NULL
DROP TABLE t1,t2;
-CREATE TABLE invoice (
+CREATE TABLE t1 (
id int(11) unsigned NOT NULL auto_increment,
text_id int(10) unsigned default NULL,
PRIMARY KEY (id)
);
-INSERT INTO invoice VALUES("1", "0");
-INSERT INTO invoice VALUES("2", "10");
-CREATE TABLE text_table (
+INSERT INTO t1 VALUES("1", "0");
+INSERT INTO t1 VALUES("2", "10");
+CREATE TABLE t2 (
text_id char(3) NOT NULL default '',
language_id char(3) NOT NULL default '',
text_data text,
PRIMARY KEY (text_id,language_id)
);
-INSERT INTO text_table VALUES("0", "EN", "0-EN");
-INSERT INTO text_table VALUES("0", "SV", "0-SV");
-INSERT INTO text_table VALUES("10", "EN", "10-EN");
-INSERT INTO text_table VALUES("10", "SV", "10-SV");
-SELECT invoice.id, invoice.text_id, text_table.text_data
-FROM invoice LEFT JOIN text_table
-ON invoice.text_id = text_table.text_id
-AND text_table.language_id = 'SV'
- WHERE (invoice.id LIKE '%' OR text_table.text_data LIKE '%');
+INSERT INTO t2 VALUES("0", "EN", "0-EN");
+INSERT INTO t2 VALUES("0", "SV", "0-SV");
+INSERT INTO t2 VALUES("10", "EN", "10-EN");
+INSERT INTO t2 VALUES("10", "SV", "10-SV");
+SELECT t1.id, t1.text_id, t2.text_data
+FROM t1 LEFT JOIN t2
+ON t1.text_id = t2.text_id
+AND t2.language_id = 'SV'
+ WHERE (t1.id LIKE '%' OR t2.text_data LIKE '%');
id text_id text_data
1 0 0-SV
2 10 10-SV
-DROP TABLE invoice, text_table;
+DROP TABLE t1, t2;
+CREATE TABLE t0 (a0 int PRIMARY KEY);
+CREATE TABLE t1 (a1 int PRIMARY KEY);
+CREATE TABLE t2 (a2 int);
+CREATE TABLE t3 (a3 int);
+INSERT INTO t0 VALUES (1);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1), (2);
+INSERT INTO t3 VALUES (1), (2);
+SELECT * FROM t1 LEFT JOIN t2 ON a1=0;
+a1 a2
+1 NULL
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON a1=0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+SELECT * FROM t1 LEFT JOIN (t2,t3) ON a1=0;
+a1 a2 a3
+1 NULL NULL
+EXPLAIN SELECT * FROM t1 LEFT JOIN (t2,t3) ON a1=0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2
+SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=0 WHERE a0=a1;
+a0 a1 a2 a3
+1 1 NULL NULL
+EXPLAIN SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=0 WHERE a0=a1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 system PRIMARY NULL NULL NULL 1
+1 SIMPLE t1 system PRIMARY NULL NULL NULL 1
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2
+INSERT INTO t0 VALUES (0);
+INSERT INTO t1 VALUES (0);
+SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
+a0 a1 a2 a3
+1 1 NULL NULL
+EXPLAIN SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2
+drop table t1,t2;
+create table t1 (a int, b int);
+insert into t1 values (1,1),(2,2),(3,3);
+create table t2 (a int, b int);
+insert into t2 values (1,1), (2,2);
+select * from t2 right join t1 on t2.a=t1.a;
+a b a b
+1 1 1 1
+2 2 2 2
+NULL NULL 3 3
+select straight_join * from t2 right join t1 on t2.a=t1.a;
+a b a b
+1 1 1 1
+2 2 2 2
+NULL NULL 3 3
+DROP TABLE t0,t1,t2,t3;
CREATE TABLE t1 (a int PRIMARY KEY, b int);
CREATE TABLE t2 (a int PRIMARY KEY, b int);
INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (4,2);
@@ -881,8 +947,60 @@ aaaaa
bbbbb
Warnings:
Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by a;
+group_concat(t1.b,t2.c)
+aaaaa
+bbbbb
+Warnings:
+Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by a;
+group_concat(t1.b,t2.c)
+aaaaa
+bbbbb
+Warnings:
+Warning 1260 2 line(s) were cut by GROUP_CONCAT()
drop table t1, t2;
set group_concat_max_len=default;
+create table t1 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, art int(11) not null, primary key (gid,x,y));
+insert t1 values (1, -5, -8, 2), (1, 2, 2, 1), (1, 1, 1, 1);
+create table t2 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, id int(11) not null, primary key (gid,id,x,y), key id (id));
+insert t2 values (1, -5, -8, 1), (1, 1, 1, 1), (1, 2, 2, 1);
+create table t3 ( set_id smallint(5) unsigned not null, id tinyint(4) unsigned not null, name char(12) not null, primary key (id,set_id));
+insert t3 values (0, 1, 'a'), (1, 1, 'b'), (0, 2, 'c'), (1, 2, 'd'), (1, 3, 'e'), (1, 4, 'f'), (1, 5, 'g'), (1, 6, 'h');
+explain select name from t1 left join t2 on t1.x = t2.x and t1.y = t2.y
+left join t3 on t1.art = t3.id where t2.id =1 and t2.x = -5 and t2.y =-8
+and t1.gid =1 and t2.gid =1 and t3.set_id =1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 10 const,const,const 1
+1 SIMPLE t2 const PRIMARY,id PRIMARY 14 const,const,const,const 1 Using index
+1 SIMPLE t3 const PRIMARY PRIMARY 3 const,const 1
+drop tables t1,t2,t3;
+CREATE TABLE t1 (EMPNUM INT, GRP INT);
+INSERT INTO t1 VALUES (0, 10);
+INSERT INTO t1 VALUES (2, 30);
+CREATE TABLE t2 (EMPNUM INT, NAME CHAR(5));
+INSERT INTO t2 VALUES (0, 'KERI');
+INSERT INTO t2 VALUES (9, 'BARRY');
+CREATE VIEW v1 AS
+SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS EMPNUM, NAME, GRP
+FROM t2 LEFT OUTER JOIN t1 ON t2.EMPNUM=t1.EMPNUM;
+SELECT * FROM v1;
+EMPNUM NAME GRP
+0 KERI 10
+9 BARRY NULL
+SELECT * FROM v1 WHERE EMPNUM < 10;
+EMPNUM NAME GRP
+0 KERI 10
+9 BARRY NULL
+DROP TABLE t1,t2;
+CREATE TABLE t1 (c11 int);
+CREATE TABLE t2 (c21 int);
+INSERT INTO t1 VALUES (30), (40), (50);
+INSERT INTO t2 VALUES (300), (400), (500);
+SELECT * FROM t1 LEFT JOIN t2 ON (c11=c21 AND c21=30) WHERE c11=40;
+c11 c21
+40 NULL
+DROP TABLE t1, t2;
CREATE TABLE t1 (a int PRIMARY KEY, b int);
CREATE TABLE t2 (a int PRIMARY KEY, b int);
INSERT INTO t1 VALUES (1,2), (2,1), (3,2), (4,3), (5,6), (6,5), (7,8), (8,7), (9,10);
@@ -1005,14 +1123,14 @@ a b a b
7 8 7 5
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
-1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a > IF(t1.a = t2.b-2, t2.b, t2.b-1);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
-1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
DROP TABLE t1,t2;
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index f0a7afa239f..bc9d3935bc4 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -110,7 +110,11 @@ name_id name
SELECT * FROM t2 WHERE name='[T,U]_axpby';
name_id name
2 [T,U]_axpby
-drop table t1,t2;
+CREATE TABLE t3 SELECT * FROM t2 WHERE name='[T,U]_axpby';
+SELECT * FROM t2 WHERE name='[T,U]_axpby';
+name_id name
+2 [T,U]_axpby
+drop table t1,t2,t3;
create table t1
(
SEQNO numeric(12 ) not null,
@@ -155,8 +159,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 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'c' at row 2
SELECT * FROM t1;
c i
1
@@ -212,14 +216,14 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
explain select 1 from t1 where id =2 or id=3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where; Using index
+1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 7 Using where; Using index
explain select name from t1 where id =2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
ALTER TABLE t1 DROP PRIMARY KEY, ADD INDEX (id);
explain select 1 from t1 where id =2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref id id 4 const 1 Using where; Using index
+1 SIMPLE t1 ref id id 4 const 1 Using index
drop table t1;
CREATE TABLE t1 (numeropost mediumint(8) unsigned NOT NULL default '0', numreponse int(10) unsigned NOT NULL auto_increment, PRIMARY KEY (numeropost,numreponse), UNIQUE KEY numreponse (numreponse));
INSERT INTO t1 (numeropost,numreponse) VALUES ('1','1'),('1','2'),('2','3'),('2','4');
@@ -341,3 +345,54 @@ c1 c2
2 Test String
3
Test String
+drop table t1;
+create table t1 (a varchar(10), b varchar(10), key(a(10),b(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) default NULL,
+ `b` varchar(10) default NULL,
+ KEY `a` (`a`,`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify b varchar(20);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) default NULL,
+ `b` varchar(20) default NULL,
+ KEY `a` (`a`,`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify a varchar(20);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(20) default NULL,
+ `b` varchar(20) default NULL,
+ KEY `a` (`a`,`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null primary key, b varchar(20) not null unique);
+desc t1;
+Field Type Null Key Default Extra
+a int(11) NO PRI
+b varchar(20) NO UNI
+drop table t1;
+create table t1 (a int not null primary key, b int not null unique);
+desc t1;
+Field Type Null Key Default Extra
+a int(11) NO PRI
+b int(11) NO UNI
+drop table t1;
+create table t1 (a int not null primary key, b varchar(20) not null, unique (b(10)));
+desc t1;
+Field Type Null Key Default Extra
+a int(11) NO PRI
+b varchar(20) NO UNI
+drop table t1;
+create table t1 (a int not null primary key, b varchar(20) not null, c varchar(20) not null, unique(b(10),c(10)));
+desc t1;
+Field Type Null Key Default Extra
+a int(11) NO PRI
+b varchar(20) NO MUL
+c varchar(20) NO
+drop table t1;
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index 41aaa21eea3..de9a2b2c003 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -193,6 +193,8 @@ cache index t1 key (unknown_key) in keycache1;
Table Op Msg_type Msg_text
test.t1 assign_to_keycache error Key column 'unknown_key' doesn't exist in table
test.t1 assign_to_keycache status Operation failed
+Warnings:
+Error 1072 Key column 'unknown_key' doesn't exist in table
select @@keycache2.key_buffer_size;
@@keycache2.key_buffer_size
4194304
@@ -287,3 +289,9 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
+set @@global.key_buffer_size=0;
+Warnings:
+Warning 1438 Cannot drop default keycache
+select @@global.key_buffer_size;
+@@global.key_buffer_size
+2097152
diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result
index c218379110f..88a0ab8abd5 100644
--- a/mysql-test/r/keywords.result
+++ b/mysql-test/r/keywords.result
@@ -1,12 +1,14 @@
drop table if exists t1;
-create table t1 (time time, date date, timestamp timestamp);
-insert into t1 values ("12:22:22","97:02:03","1997-01-02");
+create table t1 (time time, date date, timestamp timestamp,
+quarter int, week int, year int, timestampadd int, timestampdiff int);
+insert into t1 values ("12:22:22","97:02:03","1997-01-02",1,2,3,4,5);
select * from t1;
-time date timestamp
-12:22:22 1997-02-03 1997-01-02 00:00:00
-select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1;
-t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time)
-122222 19970203 19970102000000 1997-02-03 12:22:22
+time date timestamp quarter week year timestampadd timestampdiff
+12:22:22 1997-02-03 1997-01-02 00:00:00 1 2 3 4 5
+select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time),
+t1.quarter+t1.week, t1.year+timestampadd, timestampdiff from t1;
+t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time) t1.quarter+t1.week t1.year+timestampadd timestampdiff
+122222 19970203 19970102000000 1997-02-03 12:22:22 3 7 5
drop table t1;
create table events(binlog int);
insert into events values(1);
diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result
index ba9ba2833f6..754568093ff 100644
--- a/mysql-test/r/kill.result
+++ b/mysql-test/r/kill.result
@@ -17,3 +17,15 @@ select 4;
4
4
drop table t1;
+select get_lock("a", 10);
+get_lock("a", 10)
+1
+ select get_lock("a", 10);
+get_lock("a", 10)
+NULL
+select 1;
+1
+1
+select RELEASE_LOCK("a");
+RELEASE_LOCK("a")
+1
diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result
index 6a3d2bffab0..1e38f762dd1 100644
--- a/mysql-test/r/limit.result
+++ b/mysql-test/r/limit.result
@@ -1,5 +1,5 @@
drop table if exists t1;
-create table t1 (a int primary key, b int not null);
+create table t1 (a int not null default 0 primary key, b int not null default 0);
insert into t1 () values ();
insert into t1 values (1,1),(2,1),(3,1);
update t1 set a=4 where b=1 limit 1;
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
index c0baabcc507..d76fff372f5 100644
--- a/mysql-test/r/loaddata.result
+++ b/mysql-test/r/loaddata.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1, t2;
create table t1 (a date, b date, c date not null, d date);
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
Warnings:
@@ -43,9 +43,9 @@ drop table t1;
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 1264 Out of range value adjusted for column 'a' at row 3
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 1264 Out of range value adjusted for column 'a' at row 5
Warning 1262 Row 5 was truncated; it contained more data than there were input columns
select * from t1;
a b
@@ -57,7 +57,7 @@ a b
truncate table t1;
load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
Warnings:
-Warning 1265 Data truncated for column 'a' at row 4
+Warning 1264 Out of range value adjusted for column 'a' at row 4
Warning 1261 Row 4 doesn't contain data for all columns
select * from t1;
a b
@@ -66,3 +66,57 @@ a b
3 row 3
0
drop table t1;
+create table t1 (a int default 100, b int, c varchar(60));
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set b=@b+10, c=concat("b=",@b);
+select * from t1;
+a b c
+NULL 20 b=10
+NULL 25 b=15
+truncate table t1;
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set c= if(a is null,"oops",a);
+select * from t1;
+a b c
+NULL NULL oops
+NULL NULL oops
+truncate table t1;
+set @c:=123;
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, b) set c= if(@a is null,@c,b);
+select * from t1;
+a b c
+100 10 123
+100 15 123
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, @b);
+select * from t1;
+a b c
+100 10 123
+100 15 123
+100 NULL NULL
+100 NULL NULL
+select @a, @b;
+@a @b
+NULL 15
+truncate table t1;
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c="Wow";
+select * from t1;
+a b c
+1 2 Wow
+3 4 Wow
+5 6 Wow
+truncate table t1;
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c=concat(a,"+",b,"+",@c,"+",b,"+",if(c is null,"NIL",c));
+select * from t1;
+a b c
+1 2 1+2+123+2+NIL
+3 4 3+4+123+4+NIL
+5 6 5+6+123+6+NIL
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, @b);
+ERROR HY000: Can't load value from file with fixed size rows to variable
+create table t2 (num int primary key, str varchar(10));
+insert into t2 values (10,'Ten'), (15,'Fifteen');
+truncate table t1;
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@dummy,@n) set a= @n, c= (select str from t2 where num=@n);
+select * from t1;
+a b c
+10 NULL Ten
+15 NULL Fifteen
+drop table t1, t2;
diff --git a/mysql-test/r/lock.result b/mysql-test/r/lock.result
index 54162a36d83..a1efb1a8e69 100644
--- a/mysql-test/r/lock.result
+++ b/mysql-test/r/lock.result
@@ -41,7 +41,7 @@ lock tables t1 write;
check table t2;
Table Op Msg_type Msg_text
test.t2 check error Table 't2' was not locked with LOCK TABLES
-insert into t1 select nr from t1;
+insert into t1 select index1,nr from t1;
ERROR HY000: Table 't1' was not locked with LOCK TABLES
unlock tables;
lock tables t1 write, t1 as t1_alias read;
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
index 9eedbf50064..73e3a9d32e3 100644
--- a/mysql-test/r/lock_multi.result
+++ b/mysql-test/r/lock_multi.result
@@ -36,3 +36,10 @@ lock table t1 write, t2 write;
drop table t2;
ERROR 42S02: Table 'test.t2' doesn't exist
drop table t1;
+create table t1(a int);
+lock tables t1 write;
+show columns from t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+unlock tables;
+drop table t1;
diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result
index ef379cebaa9..7705961d08d 100644
--- a/mysql-test/r/lowercase_table.result
+++ b/mysql-test/r/lowercase_table.result
@@ -1,6 +1,7 @@
drop table if exists t1,t2,t3,t4;
drop table if exists t0,t5,t6,t7,t8,t9;
drop database if exists mysqltest;
+drop view if exists v0, v1, v2, v3, v4;
create table T1 (id int primary key, Word varchar(40) not null, Index(Word));
create table t4 (id int primary key, Word varchar(40) not null);
INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c');
diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result
index 8182d07c26b..995a2c0d08a 100644
--- a/mysql-test/r/lowercase_table3.result
+++ b/mysql-test/r/lowercase_table3.result
@@ -6,5 +6,5 @@ drop table t1;
flush tables;
CREATE TABLE t1 (a int) ENGINE=INNODB;
SELECT * from T1;
-ERROR HY000: Can't open file: 'T1.ibd' (errno: 1)
+ERROR 42S02: Table 'test.T1' doesn't exist
drop table t1;
diff --git a/mysql-test/r/lowercase_table_grant.result b/mysql-test/r/lowercase_table_grant.result
index 3889bd418db..c3813d57074 100644
--- a/mysql-test/r/lowercase_table_grant.result
+++ b/mysql-test/r/lowercase_table_grant.result
@@ -6,8 +6,8 @@ Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT ALL PRIVILEGES ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
select * from db where user = 'mysqltest_1';
-Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv
-localhost mysqltest mysqltest_1 Y Y Y Y Y Y N Y Y Y Y Y
+Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv
+localhost mysqltest mysqltest_1 Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y
update db set db = 'MYSQLtest' where db = 'mysqltest' and user = 'mysqltest_1' and host = 'localhost';
flush privileges;
show grants for mysqltest_1@localhost;
@@ -15,8 +15,8 @@ Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT ALL PRIVILEGES ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
select * from db where user = 'mysqltest_1';
-Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv
-localhost MYSQLtest mysqltest_1 Y Y Y Y Y Y N Y Y Y Y Y
+Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv
+localhost MYSQLtest mysqltest_1 Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y
delete from db where db = 'MYSQLtest' and user = 'mysqltest_1' and host = 'localhost';
flush privileges;
drop user mysqltest_1@localhost;
diff --git a/mysql-test/r/lowercase_view.result b/mysql-test/r/lowercase_view.result
new file mode 100644
index 00000000000..f09725dafcb
--- /dev/null
+++ b/mysql-test/r/lowercase_view.result
@@ -0,0 +1,133 @@
+drop table if exists t1Aa,t2Aa,v1Aa,v2Aa;
+drop view if exists t1Aa,t2Aa,v1Aa,v2Aa;
+drop database if exists MySQLTest;
+create database MySQLTest;
+use MySQLTest;
+create table TaB (Field int);
+create view ViE as select * from TAb;
+show create table VIe;
+View Create View
+vie CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vie` AS select `tab`.`Field` AS `Field` from `tab`
+drop database MySQLTest;
+use test;
+create table t1Aa (col1 int);
+create table t2aA (col1 int);
+create view v1Aa as select * from t1aA;
+create view v2aA as select * from v1aA;
+create view v3Aa as select v2Aa.col1 from v2aA,t2Aa where v2Aa.col1 = t2aA.col1;
+update v2aA set col1 = (select max(col1) from v1Aa);
+ERROR HY000: The definition of table 'v1Aa' prevents operation UPDATE on table 'v2aA'.
+update v2Aa set col1 = (select max(col1) from t1Aa);
+ERROR HY000: The definition of table 'v2Aa' prevents operation UPDATE on table 'v2Aa'.
+update v2aA set col1 = (select max(col1) from v2Aa);
+ERROR HY000: You can't specify target table 'v2aA' for update in FROM clause
+update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from v1aA) where v2aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 'v2aA'.
+update t1aA,t2Aa set t1Aa.col1 = (select max(col1) from v1Aa) where t1aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1Aa' prevents operation UPDATE on table 't1aA'.
+update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from v1aA) where v1Aa.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 'v1aA' for update in FROM clause
+update t2Aa,v2Aa set v2aA.col1 = (select max(col1) from v1aA) where v2Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 't2Aa'.
+update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from v1Aa) where t1Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1Aa' prevents operation UPDATE on table 't2Aa'.
+update t2Aa,v1aA set v1Aa.col1 = (select max(col1) from v1aA) where v1Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 't2Aa'.
+update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from t1aA) where v2aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 'v2aA'.
+update t1Aa,t2Aa set t1aA.col1 = (select max(col1) from t1Aa) where t1aA.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 't1Aa' for update in FROM clause
+update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from t1Aa) where v1aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 'v1aA'.
+update t2Aa,v2Aa set v2aA.col1 = (select max(col1) from t1aA) where v2Aa.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 't2Aa' for update in FROM clause
+update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from t1Aa) where t1aA.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 't2Aa' for update in FROM clause
+update t2Aa,v1Aa set v1aA.col1 = (select max(col1) from t1Aa) where v1Aa.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 't2Aa' for update in FROM clause
+update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from v2aA) where v2Aa.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 'v2aA' for update in FROM clause
+update t1aA,t2Aa set t1Aa.col1 = (select max(col1) from v2aA) where t1aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 't1aA'.
+update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from v2Aa) where v1aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2Aa' prevents operation UPDATE on table 'v1aA'.
+update t2Aa,v2aA set v2Aa.col1 = (select max(col1) from v2aA) where v2Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 't2Aa'.
+update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from v2aA) where t1Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 't2Aa'.
+update t2Aa,v1Aa set v1aA.col1 = (select max(col1) from v2Aa) where v1Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2Aa' prevents operation UPDATE on table 't2Aa'.
+update v3aA set v3Aa.col1 = (select max(col1) from v1aA);
+ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 'v3aA'.
+update v3aA set v3Aa.col1 = (select max(col1) from t1aA);
+ERROR HY000: The definition of table 'v3aA' prevents operation UPDATE on table 'v3aA'.
+update v3aA set v3Aa.col1 = (select max(col1) from v2aA);
+ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 'v3aA'.
+update v3aA set v3Aa.col1 = (select max(col1) from v3aA);
+ERROR HY000: You can't specify target table 'v3aA' for update in FROM clause
+delete from v2Aa where col1 = (select max(col1) from v1Aa);
+ERROR HY000: The definition of table 'v1Aa' prevents operation DELETE on table 'v2Aa'.
+delete from v2aA where col1 = (select max(col1) from t1Aa);
+ERROR HY000: The definition of table 'v2aA' prevents operation DELETE on table 'v2aA'.
+delete from v2Aa where col1 = (select max(col1) from v2aA);
+ERROR HY000: You can't specify target table 'v2Aa' for update in FROM clause
+delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1aA' prevents operation DELETE on table 'v2aA'.
+delete t1aA from t1Aa,t2Aa where (select max(col1) from v1Aa) > 0 and t1aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1Aa' prevents operation DELETE on table 't1Aa'.
+delete v1aA from v1Aa,t2Aa where (select max(col1) from v1aA) > 0 and v1Aa.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 'v1Aa' for update in FROM clause
+delete v2aA from v2Aa,t2Aa where (select max(col1) from t1Aa) > 0 and v2aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2Aa' prevents operation DELETE on table 'v2Aa'.
+delete t1aA from t1Aa,t2Aa where (select max(col1) from t1aA) > 0 and t1Aa.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 't1Aa' for update in FROM clause
+delete v1aA from v1Aa,t2Aa where (select max(col1) from t1aA) > 0 and v1aA.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v1Aa' prevents operation DELETE on table 'v1Aa'.
+delete v2Aa from v2aA,t2Aa where (select max(col1) from v2Aa) > 0 and v2aA.col1 = t2aA.col1;
+ERROR HY000: You can't specify target table 'v2aA' for update in FROM clause
+delete t1Aa from t1aA,t2Aa where (select max(col1) from v2Aa) > 0 and t1Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2Aa' prevents operation DELETE on table 't1aA'.
+delete v1Aa from v1aA,t2Aa where (select max(col1) from v2aA) > 0 and v1Aa.col1 = t2aA.col1;
+ERROR HY000: The definition of table 'v2aA' prevents operation DELETE on table 'v1aA'.
+insert into v2Aa values ((select max(col1) from v1aA));
+ERROR HY000: The definition of table 'v1aA' prevents operation INSERT on table 'v2Aa'.
+insert into t1aA values ((select max(col1) from v1Aa));
+ERROR HY000: The definition of table 'v1Aa' prevents operation INSERT on table 't1aA'.
+insert into v2aA values ((select max(col1) from v1aA));
+ERROR HY000: The definition of table 'v1aA' prevents operation INSERT on table 'v2aA'.
+insert into v2Aa values ((select max(col1) from t1Aa));
+ERROR HY000: The definition of table 'v2Aa' prevents operation INSERT on table 'v2Aa'.
+insert into t1aA values ((select max(col1) from t1Aa));
+ERROR HY000: You can't specify target table 't1aA' for update in FROM clause
+insert into v2aA values ((select max(col1) from t1aA));
+ERROR HY000: The definition of table 'v2aA' prevents operation INSERT on table 'v2aA'.
+insert into v2Aa values ((select max(col1) from v2aA));
+ERROR HY000: You can't specify target table 'v2Aa' for update in FROM clause
+insert into t1Aa values ((select max(col1) from v2Aa));
+ERROR HY000: The definition of table 'v2Aa' prevents operation INSERT on table 't1Aa'.
+insert into v2aA values ((select max(col1) from v2Aa));
+ERROR HY000: You can't specify target table 'v2aA' for update in FROM clause
+insert into v3Aa (col1) values ((select max(col1) from v1Aa));
+ERROR HY000: The definition of table 'v1Aa' prevents operation INSERT on table 'v3Aa'.
+insert into v3aA (col1) values ((select max(col1) from t1aA));
+ERROR HY000: The definition of table 'v3aA' prevents operation INSERT on table 'v3aA'.
+insert into v3Aa (col1) values ((select max(col1) from v2aA));
+ERROR HY000: The definition of table 'v2aA' prevents operation INSERT on table 'v3Aa'.
+drop view v3aA,v2Aa,v1aA;
+drop table t1Aa,t2Aa;
+create table t1Aa (col1 int);
+create view v1Aa as select col1 from t1Aa as AaA;
+show create view v1AA;
+View Create View
+v1aa CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1aa` AS select `aaa`.`col1` AS `col1` from `t1aa` `AaA`
+drop view v1AA;
+select Aaa.col1 from t1Aa as AaA;
+col1
+create view v1Aa as select Aaa.col1 from t1Aa as AaA;
+drop view v1AA;
+create view v1Aa as select AaA.col1 from t1Aa as AaA;
+show create view v1AA;
+View Create View
+v1aa CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1aa` AS select `aaa`.`col1` AS `col1` from `t1aa` `AaA`
+drop view v1AA;
+drop table t1Aa;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 6e14e9a56a8..d4e19201173 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -39,7 +39,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 range a a 4 NULL 18 Using where
explain select * from t3 where a > 10 and a < 20;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range a a 4 NULL 16 Using where
+1 SIMPLE t3 range a a 4 NULL 17 Using where
select * from t3 where a = 10;
a b
10 Testing
@@ -172,22 +172,22 @@ a b
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` char(20) default NULL,
KEY `a` (`a`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
select * from t4;
-ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
+ERROR HY000: All tables in the MERGE table are not identically defined
alter table t4 add column c int;
-ERROR HY000: Can't open file: 't4.MRG' (errno: 143)
+ERROR HY000: All tables in the MERGE table are not identically defined
create database mysqltest;
create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
create table t5 (a int not null, b char(20), key(a)) engine=MERGE UNION=(test.t1,mysqltest.t6);
show create table t5;
Table Create Table
t5 CREATE TABLE `t5` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` char(20) default NULL,
KEY `a` (`a`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`mysqltest`.`t6`)
@@ -260,16 +260,16 @@ ENGINE=MERGE UNION=(t1,t2);
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `incr` int(11) NOT NULL default '0',
- `othr` int(11) NOT NULL default '0',
+ `incr` int(11) NOT NULL,
+ `othr` int(11) NOT NULL,
PRIMARY KEY (`incr`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
alter table t3 drop primary key;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `incr` int(11) NOT NULL default '0',
- `othr` int(11) NOT NULL default '0'
+ `incr` int(11) NOT NULL,
+ `othr` int(11) NOT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
drop table t3,t2,t1;
create table t1 (a int not null, key(a)) engine=merge;
@@ -296,28 +296,28 @@ create table t6 (a int not null, b int not null auto_increment, primary key(a,b)
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `a` int(11) NOT NULL default '0',
- `b` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
+ `b` int(11) NOT NULL,
KEY `a` (`a`,`b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
show create table t4;
Table Create Table
t4 CREATE TABLE `t4` (
- `a` int(11) NOT NULL default '0',
- `b` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
+ `b` int(11) NOT NULL,
KEY `a` (`a`,`b`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
show create table t5;
Table Create Table
t5 CREATE TABLE `t5` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`)
show create table t6;
Table Create Table
t6 CREATE TABLE `t6` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
@@ -382,8 +382,8 @@ alter table t4 UNION=(t1,t2,t3);
show create table t4;
Table Create Table
t4 CREATE TABLE `t4` (
- `a` int(11) NOT NULL default '0',
- `b` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
+ `b` int(11) NOT NULL,
KEY `a` (`a`,`b`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`,`t3`)
select * from t4 order by a,b;
@@ -408,8 +408,8 @@ alter table t4 INSERT_METHOD=FIRST;
show create table t4;
Table Create Table
t4 CREATE TABLE `t4` (
- `a` int(11) NOT NULL default '0',
- `b` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
+ `b` int(11) NOT NULL,
KEY `a` (`a`,`b`)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`,`t3`)
insert into t4 values (4,1),(4,2);
@@ -614,19 +614,19 @@ KEY files (fileset_id,fileset_root_id)
EXPLAIN SELECT * FROM t2 IGNORE INDEX (files) WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range PRIMARY PRIMARY 33 NULL 5 Using where
+1 SIMPLE t2 range PRIMARY PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range PRIMARY,files PRIMARY 33 NULL 5 Using where
+1 SIMPLE t2 range PRIMARY,files PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,files PRIMARY 33 NULL 5 Using where
+1 SIMPLE t1 range PRIMARY,files PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 const PRIMARY,files PRIMARY 33 const,const 1
+1 SIMPLE t2 ref PRIMARY,files PRIMARY 35 const,const 1 Using where
DROP TABLE t2, t1;
create table t1 (x int, y int, index xy(x, y));
create table t2 (x int, y int, index xy(x, y));
@@ -650,6 +650,8 @@ create table t3 engine=merge union=(t1, t2) select * from t1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
create table t3 engine=merge union=(t1, t2) select * from t2;
ERROR HY000: You can't specify target table 't2' for update in FROM clause
+create table t3 engine=merge union=(t1, t2) select (select max(a) from t2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
drop table t1, t2;
create table t1 (a int,b int,c int, index (a,b,c));
create table t2 (a int,b int,c int, index (a,b,c));
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index 6297f9cdcb5..50b0b6ae294 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -2,9 +2,9 @@ drop table if exists t1,t2;
select 1, 1.0, -1, "hello", NULL;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def 1 8 1 1 N 32897 0 63
-def 1.0 5 3 3 N 32897 1 63
+def 1.0 246 4 3 N 129 1 63
def -1 8 2 2 N 32897 0 63
-def hello 254 5 5 N 1 31 8
+def hello 253 5 5 N 1 31 8
def NULL 6 0 0 Y 32896 0 63
1 1.0 -1 hello NULL
1 1.0 -1 hello NULL
@@ -18,7 +18,7 @@ def test t1 t1 d d 3 11 0 Y 32768 0 63
def test t1 t1 e e 8 20 0 Y 32768 0 63
def test t1 t1 f f 4 3 0 Y 32768 2 63
def test t1 t1 g g 5 4 0 Y 32768 3 63
-def test t1 t1 h h 0 7 0 Y 32768 4 63
+def test t1 t1 h h 246 7 0 Y 0 4 63
def test t1 t1 i i 13 4 0 Y 32864 0 63
def test t1 t1 j j 10 10 0 Y 128 0 63
def test t1 t1 k k 7 19 0 N 1249 0 63
diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result
index 72288d1027b..e4528450b31 100644
--- a/mysql-test/r/mix_innodb_myisam_binlog.result
+++ b/mysql-test/r/mix_innodb_myisam_binlog.result
@@ -6,12 +6,12 @@ begin;
insert into t1 values(1);
insert into t2 select * from t1;
commit;
-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`; BEGIN
-master-bin.000001 119 Query 1 79 use `test`; insert into t1 values(1)
-master-bin.000001 178 Query 1 79 use `test`; insert into t2 select * from t1
-master-bin.000001 244 Query 1 244 use `test`; COMMIT
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; BEGIN
+master-bin.000001 166 Query 1 # use `test`; insert into t1 values(1)
+master-bin.000001 253 Query 1 # use `test`; insert into t2 select * from t1
+master-bin.000001 347 Xid 1 # COMMIT /* xid=8 */
delete from t1;
delete from t2;
reset master;
@@ -21,12 +21,12 @@ insert into t2 select * from t1;
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
-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`; BEGIN
-master-bin.000001 119 Query 1 79 use `test`; insert into t1 values(2)
-master-bin.000001 178 Query 1 79 use `test`; insert into t2 select * from t1
-master-bin.000001 244 Query 1 244 use `test`; ROLLBACK
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; BEGIN
+master-bin.000001 166 Query 1 # use `test`; insert into t1 values(2)
+master-bin.000001 253 Query 1 # use `test`; insert into t2 select * from t1
+master-bin.000001 347 Query 1 # use `test`; ROLLBACK
delete from t1;
delete from t2;
reset master;
@@ -39,15 +39,15 @@ rollback to savepoint my_savepoint;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
commit;
-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`; BEGIN
-master-bin.000001 119 Query 1 79 use `test`; insert into t1 values(3)
-master-bin.000001 178 Query 1 79 use `test`; savepoint my_savepoint
-master-bin.000001 235 Query 1 79 use `test`; insert into t1 values(4)
-master-bin.000001 294 Query 1 79 use `test`; insert into t2 select * from t1
-master-bin.000001 360 Query 1 79 use `test`; rollback to savepoint my_savepoint
-master-bin.000001 429 Query 1 429 use `test`; COMMIT
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; BEGIN
+master-bin.000001 166 Query 1 # use `test`; insert into t1 values(3)
+master-bin.000001 253 Query 1 # use `test`; savepoint my_savepoint
+master-bin.000001 338 Query 1 # use `test`; insert into t1 values(4)
+master-bin.000001 425 Query 1 # use `test`; insert into t2 select * from t1
+master-bin.000001 519 Query 1 # use `test`; rollback to savepoint my_savepoint
+master-bin.000001 616 Xid 1 # COMMIT /* xid=25 */
delete from t1;
delete from t2;
reset master;
@@ -65,16 +65,16 @@ select a from t1 order by a;
a
5
7
-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`; BEGIN
-master-bin.000001 119 Query 1 79 use `test`; insert into t1 values(5)
-master-bin.000001 178 Query 1 79 use `test`; savepoint my_savepoint
-master-bin.000001 235 Query 1 79 use `test`; insert into t1 values(6)
-master-bin.000001 294 Query 1 79 use `test`; insert into t2 select * from t1
-master-bin.000001 360 Query 1 79 use `test`; rollback to savepoint my_savepoint
-master-bin.000001 429 Query 1 79 use `test`; insert into t1 values(7)
-master-bin.000001 488 Query 1 488 use `test`; COMMIT
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; BEGIN
+master-bin.000001 166 Query 1 # use `test`; insert into t1 values(5)
+master-bin.000001 253 Query 1 # use `test`; savepoint my_savepoint
+master-bin.000001 338 Query 1 # use `test`; insert into t1 values(6)
+master-bin.000001 425 Query 1 # use `test`; insert into t2 select * from t1
+master-bin.000001 519 Query 1 # use `test`; rollback to savepoint my_savepoint
+master-bin.000001 616 Query 1 # use `test`; insert into t1 values(7)
+master-bin.000001 703 Xid 1 # COMMIT /* xid=37 */
delete from t1;
delete from t2;
reset master;
@@ -87,40 +87,43 @@ insert into t2 select * from t1;
select get_lock("a",10);
get_lock("a",10)
1
-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`; BEGIN
-master-bin.000001 119 Query 1 79 use `test`; insert into t1 values(8)
-master-bin.000001 178 Query 1 79 use `test`; insert into t2 select * from t1
-master-bin.000001 244 Query 1 244 use `test`; ROLLBACK
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; BEGIN
+master-bin.000001 166 Query 1 # use `test`; insert into t1 values(8)
+master-bin.000001 253 Query 1 # use `test`; insert into t2 select * from t1
+master-bin.000001 347 Query 1 # use `test`; ROLLBACK
delete from t1;
delete from t2;
reset master;
insert into t1 values(9);
insert into t2 select * from t1;
-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`; insert into t1 values(9)
-master-bin.000001 138 Query 1 138 use `test`; insert into t2 select * from t1
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; insert into t1 values(9)
+master-bin.000001 185 Xid 1 # COMMIT /* xid=60 */
+master-bin.000001 212 Query 1 # use `test`; insert into t2 select * from t1
delete from t1;
delete from t2;
reset master;
insert into t1 values(10);
begin;
insert into t2 select * from t1;
-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`; insert into t1 values(10)
-master-bin.000001 139 Query 1 139 use `test`; insert into t2 select * from t1
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; insert into t1 values(10)
+master-bin.000001 186 Xid 1 # COMMIT /* xid=66 */
+master-bin.000001 213 Query 1 # use `test`; insert into t2 select * from t1
insert into t1 values(11);
commit;
-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`; insert into t1 values(10)
-master-bin.000001 139 Query 1 139 use `test`; insert into t2 select * from t1
-master-bin.000001 205 Query 1 205 use `test`; BEGIN
-master-bin.000001 245 Query 1 205 use `test`; insert into t1 values(11)
-master-bin.000001 305 Query 1 305 use `test`; COMMIT
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; insert into t1 values(10)
+master-bin.000001 186 Xid 1 # COMMIT /* xid=66 */
+master-bin.000001 213 Query 1 # use `test`; insert into t2 select * from t1
+master-bin.000001 307 Query 1 # use `test`; BEGIN
+master-bin.000001 375 Query 1 # use `test`; insert into t1 values(11)
+master-bin.000001 463 Xid 1 # COMMIT /* xid=68 */
alter table t2 engine=INNODB;
delete from t1;
delete from t2;
@@ -129,12 +132,12 @@ begin;
insert into t1 values(12);
insert into t2 select * from t1;
commit;
-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`; BEGIN
-master-bin.000001 119 Query 1 79 use `test`; insert into t1 values(12)
-master-bin.000001 179 Query 1 79 use `test`; insert into t2 select * from t1
-master-bin.000001 245 Query 1 245 use `test`; COMMIT
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; BEGIN
+master-bin.000001 166 Query 1 # use `test`; insert into t1 values(12)
+master-bin.000001 254 Query 1 # use `test`; insert into t2 select * from t1
+master-bin.000001 348 Xid 1 # COMMIT /* xid=78 */
delete from t1;
delete from t2;
reset master;
@@ -142,8 +145,8 @@ begin;
insert into t1 values(13);
insert into t2 select * from t1;
rollback;
-show binlog events from 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
delete from t1;
delete from t2;
reset master;
@@ -154,11 +157,11 @@ insert into t1 values(15);
insert into t2 select * from t1;
rollback to savepoint my_savepoint;
commit;
-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`; BEGIN
-master-bin.000001 119 Query 1 79 use `test`; insert into t1 values(14)
-master-bin.000001 179 Query 1 179 use `test`; COMMIT
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; BEGIN
+master-bin.000001 166 Query 1 # use `test`; insert into t1 values(14)
+master-bin.000001 254 Xid 1 # COMMIT /* xid=94 */
delete from t1;
delete from t2;
reset master;
@@ -174,12 +177,12 @@ select a from t1 order by a;
a
16
18
-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`; BEGIN
-master-bin.000001 119 Query 1 79 use `test`; insert into t1 values(16)
-master-bin.000001 179 Query 1 79 use `test`; insert into t1 values(18)
-master-bin.000001 239 Query 1 239 use `test`; COMMIT
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 # use `test`; BEGIN
+master-bin.000001 166 Query 1 # use `test`; insert into t1 values(16)
+master-bin.000001 254 Query 1 # use `test`; insert into t1 values(18)
+master-bin.000001 342 Xid 1 # COMMIT /* xid=105 */
delete from t1;
delete from t2;
alter table t2 type=MyISAM;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index dba10296063..ea02a703c65 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -1,5 +1,6 @@
drop table if exists t1,t2,t3;
drop database if exists mysqltest;
+drop view if exists v1;
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=_binary'mysqltest_1';
@@ -134,16 +135,16 @@ create table t1 (n numeric(10));
create table t2 (n numeric(10));
insert into t2 values (1),(2),(4),(8),(16),(32);
select * from t2 left outer join t1 using (n);
-n n
-1 NULL
-2 NULL
-4 NULL
-8 NULL
-16 NULL
-32 NULL
+n
+1
+2
+4
+8
+16
+32
delete t1,t2 from t2 left outer join t1 using (n);
select * from t2 left outer join t1 using (n);
-n n
+n
drop table t1,t2 ;
create table t1 (n int(10) not null primary key, d int(10));
create table t2 (n int(10) not null primary key, d int(10));
@@ -475,3 +476,46 @@ aclid bigint, index idx_acl(aclid)
insert into t2 values(1,null);
delete t2, t1 from t2 left join t1 on (t2.aclid=t1.aclid) where t2.refid='1';
drop table t1, t2;
+create table t1 ( c char(8) not null ) engine=innodb;
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+create table t2 like t1;
+insert into t2 select * from t1;
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+drop table t1,t2;
+create table t1 ( c char(8) not null ) engine=bdb;
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+create table t2 like t1;
+insert into t2 select * from t1;
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+drop table t1,t2;
+create table t1 (a int, b int);
+insert into t1 values (1, 2), (2, 3), (3, 4);
+create table t2 (a int);
+insert into t2 values (10), (20), (30);
+create view v1 as select a as b, a/10 as a from t2;
+lock table t1 write;
+ alter table t1 add column c int default 100 after a;
+ update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
+unlock tables;
+select * from t1;
+a c b
+1 100 13
+2 100 25
+3 100 37
+select * from t2;
+a
+10
+20
+30
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index b3144a6903b..99f84f0a67b 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -408,8 +408,8 @@ Table Op Msg_type Msg_text
test.t1 repair status OK
select concat(a,'.') from t1 where a='aaa';
concat(a,'.')
-aaa.
aaa .
+aaa.
select concat(a,'.') from t1 where binary a='aaa';
concat(a,'.')
aaa.
@@ -461,20 +461,27 @@ concat(a,'.')
a .
drop table t1;
create table t1 (a int not null auto_increment primary key, b text not null, unique b (b(20)));
-insert into t1 (b) values ('a'),('a '),('a ');
+insert into t1 (b) values ('a'),('b'),('c');
select concat(b,'.') from t1;
concat(b,'.')
a.
-a .
-a .
+b.
+c.
update t1 set b='b ' where a=2;
update t1 set b='b ' where a > 1;
ERROR 23000: Duplicate entry 'b ' for key 2
+insert into t1 (b) values ('b');
+ERROR 23000: Duplicate entry 'b' for key 2
+select * from t1;
+a b
+1 a
+2 b
+3 c
delete from t1 where b='b';
select a,concat(b,'.') from t1;
a concat(b,'.')
1 a.
-3 a .
+3 c.
drop table t1;
create table t1 (a int not null);
create table t2 (a int not null, primary key (a));
@@ -506,19 +513,25 @@ insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
insert t2 select * from t1;
checksum table t1, t2, t3 quick;
Table Checksum
-test.t1 968604391
+test.t1 2948697075
test.t2 NULL
test.t3 NULL
+Warnings:
+Error 1146 Table 'test.t3' doesn't exist
checksum table t1, t2, t3;
Table Checksum
-test.t1 968604391
-test.t2 968604391
+test.t1 2948697075
+test.t2 3092701434
test.t3 NULL
+Warnings:
+Error 1146 Table 'test.t3' doesn't exist
checksum table t1, t2, t3 extended;
Table Checksum
-test.t1 968604391
-test.t2 968604391
+test.t1 3092701434
+test.t2 3092701434
test.t3 NULL
+Warnings:
+Error 1146 Table 'test.t3' doesn't exist
drop table t1,t2;
create table t1 (a int, key (a));
show keys from t1;
@@ -581,20 +594,6 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
-create table t1 (a int, key(a));
-insert into t1 values (1),(2),(3),(4),(NULL),(NULL),(NULL),(NULL);
-analyze table t1;
-Table Op Msg_type Msg_text
-test.t1 analyze status OK
-show keys from t1;
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
-t1 1 a 1 a A 8 NULL NULL YES BTREE
-alter table t1 disable keys;
-alter table t1 enable keys;
-show keys from t1;
-Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
-t1 1 a 1 a A 8 NULL NULL YES BTREE
-drop table t1;
create table t1 (c1 int);
insert into t1 values (1),(2),(3),(4);
checksum table t1;
@@ -670,3 +669,689 @@ 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 10 NULL NULL YES BTREE
drop table t1;
+set storage_engine=MyISAM;
+drop table if exists t1,t2,t3;
+--- Testing varchar ---
+--- Testing varchar ---
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Note 1265 Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+ *+*+ *
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Note 1265 Data truncated for column 't' at row 2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+ *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`),
+ KEY `c` (`c`),
+ KEY `t` (`t`(10))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const # Using where; Using index
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const # Using where; Using index
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t t 13 NULL # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where; Using index
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v,v_2 # 13 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(*) from t1 group by c limit 10;
+c count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(*) from t1 group by t limit 10;
+t count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(300) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 303 const # Using where; Using index
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 303 NULL # Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 303 NULL # Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 303 NULL # Using where; Using index
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 303 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 drop key v, add key v (v(30));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(300) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`(30))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 33 const # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 33 NULL # Using where
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 33 const # Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+alter table t1 modify v varchar(600), drop key v, add key v (v);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(600) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `c` (`c`),
+ KEY `t` (`t`(10)),
+ KEY `v` (`v`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a ');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a%';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='abc ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a %';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+drop table t1;
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`(5)),
+ KEY `c` (`c`(5)),
+ KEY `t` (`t`(5))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) character set utf8 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+concat('*',v,'*',c,'*')
+*a*a*
+*a *a*
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+create table t1(a int, b varchar(12), key ba(b, a));
+insert into t1 values (1, 'A'), (20, NULL);
+explain select * from t1 where a=20 and b is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref ba ba 20 const,const 1 Using where; Using index
+select * from t1 where a=20 and b is null;
+a b
+20 NULL
+drop table t1;
+create table t1 (v varchar(65530), key(v));
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+drop table if exists t1;
+create table t1 (v varchar(65536));
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext character set utf8
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65535));
+ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
+set storage_engine=MyISAM;
+create table t1 (a int) engine=myisam;
+drop table if exists t1;
+Warnings:
+Error 2 Can't find file: 't1' (errno: 2)
+create table t1 (a int) engine=myisam;
+drop table t1;
+Got one of the listed errors
+create table t1 (a int) engine=myisam;
+drop table t1;
+Got one of the listed errors
+drop table t1;
+ERROR 42S02: Unknown table 't1'
+set @save_concurrent_insert=@@concurrent_insert;
+set global concurrent_insert=1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5);
+lock table t1 read local;
+insert into t1 values(6),(7);
+unlock tables;
+delete from t1 where a>=3 and a<=4;
+lock table t1 read local;
+set global concurrent_insert=2;
+insert into t1 values (8),(9);
+unlock tables;
+insert into t1 values (10),(11),(12);
+select * from t1;
+a
+1
+2
+11
+10
+5
+6
+7
+8
+9
+12
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+create table t1 (a int, b varchar(30) default "hello");
+insert into t1 (a) values (1),(2),(3),(4),(5);
+lock table t1 read local;
+insert into t1 (a) values(6),(7);
+unlock tables;
+delete from t1 where a>=3 and a<=4;
+lock table t1 read local;
+set global concurrent_insert=2;
+insert into t1 (a) values (8),(9);
+unlock tables;
+insert into t1 (a) values (10),(11),(12);
+select a from t1;
+a
+1
+2
+11
+10
+5
+6
+7
+8
+9
+12
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+set global concurrent_insert=@save_concurrent_insert;
+create table t1 (a int, key(a));
+insert into t1 values (1),(2),(3),(4),(NULL),(NULL),(NULL),(NULL);
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 1 a 1 a A 8 NULL NULL YES BTREE
+alter table t1 disable keys;
+alter table t1 enable keys;
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 1 a 1 a A 8 NULL NULL YES BTREE
+drop table t1;
+create table t1 (c1 int) engine=myisam pack_keys=0;
+create table t2 (c1 int) engine=myisam pack_keys=1;
+create table t3 (c1 int) engine=myisam pack_keys=default;
+create table t4 (c1 int) engine=myisam pack_keys=2;
+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' at line 1
+drop table t1, t2, t3;
diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result
new file mode 100644
index 00000000000..eeb6abd9f41
--- /dev/null
+++ b/mysql-test/r/mysql.result
@@ -0,0 +1,60 @@
+drop table if exists t1;
+create table t1(a int);
+insert into t1 values(1);
+
+Test default delimiter ;
+a
+1
+
+Test delimiter without arg
+
+Test delimiter :
+a
+1
+
+Test delimiter :
+a
+1
+
+Test delimiter :;
+a
+1
+
+Test delimiter //
+a
+1
+
+Test delimiter MySQL
+a
+1
+
+Test delimiter delimiter
+a
+1
+Tables_in_test
+t1
+t2
+t3
+
+Test delimiter : from command line
+a
+1
+
+Test delimiter :; from command line
+a
+1
+
+Test 'go' command(vertical output) G
+*************************** 1. row ***************************
+a: 1
+
+Test 'go' command g
+a
+1
+drop table t1;
+create table t1(a int);
+lock tables t1 write;
+database()
+test
+unlock tables;
+drop table t1;
diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result
index e88ece6b361..8765e65f11b 100644
--- a/mysql-test/r/mysqlbinlog.result
+++ b/mysql-test/r/mysqlbinlog.result
@@ -9,14 +9,18 @@ load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
insert into t1 values ("Alas");
flush logs;
--- Local --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
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 @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
drop table if exists t1,t2;
SET TIMESTAMP=1000000000;
create table t1 (word varchar(20));
@@ -27,32 +31,58 @@ insert into t1 values ("abirvalg");
SET INSERT_ID=1;
SET TIMESTAMP=1000000000;
insert into t2 values ();
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-1-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-2-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-3-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-4-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-5-0' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
+SET TIMESTAMP=1000000000;
+load data LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/SQL_LOAD_MB-1-0' INTO table t1;
+SET TIMESTAMP=1000000000;
+load data LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/SQL_LOAD_MB-2-0' INTO table t1;
+SET TIMESTAMP=1000000000;
+load data LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/SQL_LOAD_MB-3-0' INTO table t1;
+SET TIMESTAMP=1000000000;
+load data LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/SQL_LOAD_MB-4-0' INTO table t1;
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- Broken LOAD DATA --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=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 @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values ("Alas");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- --database --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=1;
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- --position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=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 @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values ("Alas");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- Remote --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
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 @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
drop table if exists t1,t2;
SET TIMESTAMP=1000000000;
create table t1 (word varchar(20));
@@ -63,25 +93,67 @@ insert into t1 values ("abirvalg");
SET INSERT_ID=1;
SET TIMESTAMP=1000000000;
insert into t2 values ();
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-1-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-2-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-3-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-4-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
-LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/words.dat-5-1' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' STARTING BY '' (word);
+SET TIMESTAMP=1000000000;
+load data LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/SQL_LOAD_MB-1-2' INTO table t1;
+SET TIMESTAMP=1000000000;
+load data LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/SQL_LOAD_MB-2-2' INTO table t1;
+SET TIMESTAMP=1000000000;
+load data LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/SQL_LOAD_MB-3-2' INTO table t1;
+SET TIMESTAMP=1000000000;
+load data LOCAL INFILE 'MYSQL_TEST_DIR/var/tmp/SQL_LOAD_MB-4-2' INTO table t1;
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- Broken LOAD DATA --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=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 @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values ("Alas");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- --database --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=1;
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- --position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=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 @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values ("Alas");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+
+--- reading stdin --
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
+use test;
+SET TIMESTAMP=1108844556;
+BEGIN;
+SET TIMESTAMP=1108844555;
+insert t1 values (1);
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+use test;
+SET TIMESTAMP=1108844556;
+BEGIN;
+SET TIMESTAMP=1108844555;
+insert t1 values (1);
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
drop table t1, t2;
diff --git a/mysql-test/r/mysqlbinlog2.result b/mysql-test/r/mysqlbinlog2.result
index 3c1b85e05a1..9899fa54301 100644
--- a/mysql-test/r/mysqlbinlog2.result
+++ b/mysql-test/r/mysqlbinlog2.result
@@ -16,8 +16,13 @@ insert into t1 values(null, "f");
--- Local --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -34,12 +39,19 @@ insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- offset --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=1;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "a");
SET INSERT_ID=2;
SET TIMESTAMP=1579609942;
@@ -53,20 +65,34 @@ insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- start-position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+SET INSERT_ID=4;
use test;
SET TIMESTAMP=1579609946;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- stop-position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -77,13 +103,19 @@ insert into t1 values(null, "b");
SET INSERT_ID=3;
SET TIMESTAMP=1579609944;
insert into t1 values(null, "c");
-SET INSERT_ID=4;
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- start-datetime --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=3;
use test;
SET TIMESTAMP=1579609944;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "c");
SET INSERT_ID=4;
SET TIMESTAMP=1579609946;
@@ -91,11 +123,18 @@ insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- stop-datetime --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -103,11 +142,18 @@ insert into t1 values(null, "a");
SET INSERT_ID=2;
SET TIMESTAMP=1579609942;
insert into t1 values(null, "b");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- Local with 2 binlogs on command line --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -127,13 +173,23 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
use test;
SET TIMESTAMP=1579609943;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- offset --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=1;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "a");
SET INSERT_ID=2;
SET TIMESTAMP=1579609942;
@@ -150,12 +206,22 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
use test;
SET TIMESTAMP=1579609943;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- start-position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+SET INSERT_ID=4;
use test;
SET TIMESTAMP=1579609946;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
@@ -163,12 +229,22 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
use test;
SET TIMESTAMP=1579609943;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- stop-position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -186,12 +262,19 @@ SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
SET INSERT_ID=6;
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- start-datetime --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=3;
use test;
SET TIMESTAMP=1579609944;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "c");
SET INSERT_ID=4;
SET TIMESTAMP=1579609946;
@@ -202,12 +285,22 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
use test;
SET TIMESTAMP=1579609943;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- stop-datetime --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -215,11 +308,18 @@ insert into t1 values(null, "a");
SET INSERT_ID=2;
SET TIMESTAMP=1579609942;
insert into t1 values(null, "b");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- Remote --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -236,12 +336,19 @@ insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- offset --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=1;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "a");
SET INSERT_ID=2;
SET TIMESTAMP=1579609942;
@@ -255,20 +362,34 @@ insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- start-position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+SET INSERT_ID=4;
use test;
SET TIMESTAMP=1579609946;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- stop-position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -279,13 +400,19 @@ insert into t1 values(null, "b");
SET INSERT_ID=3;
SET TIMESTAMP=1579609944;
insert into t1 values(null, "c");
-SET INSERT_ID=4;
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- start-datetime --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=3;
use test;
SET TIMESTAMP=1579609944;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "c");
SET INSERT_ID=4;
SET TIMESTAMP=1579609946;
@@ -293,11 +420,18 @@ insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- stop-datetime --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -305,11 +439,18 @@ insert into t1 values(null, "a");
SET INSERT_ID=2;
SET TIMESTAMP=1579609942;
insert into t1 values(null, "b");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- Remote with 2 binlogs on command line --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -329,13 +470,23 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
use test;
SET TIMESTAMP=1579609943;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- offset --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=1;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "a");
SET INSERT_ID=2;
SET TIMESTAMP=1579609942;
@@ -352,12 +503,22 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
use test;
SET TIMESTAMP=1579609943;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- start-position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+SET INSERT_ID=4;
use test;
SET TIMESTAMP=1579609946;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "d");
SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
@@ -365,12 +526,22 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
use test;
SET TIMESTAMP=1579609943;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- stop-position --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -388,12 +559,19 @@ SET INSERT_ID=5;
SET TIMESTAMP=1579609946;
insert into t1 values(null, "e");
SET INSERT_ID=6;
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- start-datetime --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET INSERT_ID=3;
use test;
SET TIMESTAMP=1579609944;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "c");
SET INSERT_ID=4;
SET TIMESTAMP=1579609946;
@@ -404,12 +582,22 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
use test;
SET TIMESTAMP=1579609943;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- stop-datetime --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -417,11 +605,18 @@ insert into t1 values(null, "a");
SET INSERT_ID=2;
SET TIMESTAMP=1579609942;
insert into t1 values(null, "b");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- to-last-log --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
use test;
SET TIMESTAMP=1579609942;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
create table t1 (a int auto_increment not null primary key, b char(3));
SET INSERT_ID=1;
SET TIMESTAMP=1579609942;
@@ -441,6 +636,8 @@ insert into t1 values(null, "e");
SET INSERT_ID=6;
SET TIMESTAMP=1579609943;
insert into t1 values(null, "f");
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
--- end of test --
drop table t1;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index cb2e8e5528a..48e6ded689e 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -1,4 +1,8 @@
-DROP TABLE IF EXISTS t1, `"t"1`;
+DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa;
+drop database if exists mysqldump_test_db;
+drop database if exists db1;
+drop database if exists db2;
+drop view if exists v1, v2, v3;
CREATE TABLE t1(a int);
INSERT INTO t1 VALUES (1), (2);
<?xml version="1.0"?>
@@ -18,16 +22,18 @@ INSERT INTO t1 VALUES (1), (2);
</database>
</mysqldump>
DROP TABLE t1;
-CREATE TABLE t1 (a decimal(240, 20));
+CREATE TABLE t1 (a decimal(64, 20));
INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
("0987654321098765432109876543210987654321");
CREATE TABLE `t1` (
- `a` decimal(240,20) default NULL
+ `a` decimal(64,20) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
-INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('0987654321098765432109876543210987654321.00000000000000000000');
+INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000');
DROP TABLE t1;
CREATE TABLE t1 (a double);
-INSERT INTO t1 VALUES (-9e999999);
+INSERT INTO t1 VALUES ('-9e999999');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
CREATE TABLE `t1` (
`a` double default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
@@ -108,7 +114,7 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES");
<table_structure name="t1">
<field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
<field Field="b" Type="text" Null="YES" Key="" Extra="" />
- <field Field="c" Type="char(3)" Null="YES" Key="" Extra="" />
+ <field Field="c" Type="varchar(3)" Null="YES" Key="" Extra="" />
</table_structure>
<table_data name="t1">
<row>
@@ -560,9 +566,9 @@ UNLOCK TABLES;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
DROP TABLE t1;
-CREATE TABLE t1 (a decimal(240, 20));
-INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
-("0987654321098765432109876543210987654321");
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 VALUES (4),(5),(6);
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
@@ -574,13 +580,13 @@ INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
- `a` decimal(240,20) default NULL
+ `a` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
LOCK TABLES `t1` WRITE;
-INSERT IGNORE INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('0987654321098765432109876543210987654321.00000000000000000000');
+INSERT IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6);
UNLOCK TABLES;
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
@@ -603,12 +609,14 @@ UNLOCK TABLES;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
- `a` decimal(240,20) default NULL
+ `a` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
-INSERT DELAYED IGNORE INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('0987654321098765432109876543210987654321.00000000000000000000');
+LOCK TABLES `t1` WRITE;
+INSERT IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6);
+UNLOCK TABLES;
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
@@ -1349,6 +1357,86 @@ UNLOCK TABLES;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
DROP TABLE t1;
+create database db1;
+use db1;
+CREATE TABLE t2 (
+a varchar(30) default NULL,
+KEY a (a(5))
+);
+INSERT INTO t2 VALUES ('alfred');
+INSERT INTO t2 VALUES ('angie');
+INSERT INTO t2 VALUES ('bingo');
+INSERT INTO t2 VALUES ('waffle');
+INSERT INTO t2 VALUES ('lemon');
+create view v2 as select * from t2 where a like 'a%' with check option;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t2`;
+CREATE TABLE `t2` (
+ `a` varchar(30) default NULL,
+ KEY `a` (`a`(5))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
+LOCK TABLES `t2` WRITE;
+INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon');
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
+DROP TABLE IF EXISTS `v2`;
+/*!50001 DROP VIEW IF EXISTS `v2`*/;
+/*!50001 CREATE TABLE `v2` (
+ `a` varchar(30) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1*/;
+/*!50001 DROP TABLE IF EXISTS `v2`*/;
+/*!50001 DROP VIEW IF EXISTS `v2`*/;
+/*!50001 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where (`t2`.`a` like _latin1'a%') WITH CASCADED CHECK OPTION*/;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+drop table t2;
+drop view v2;
+drop database db1;
+create database db2;
+use db2;
+create table t1 (a int);
+create table t2 (a int, b varchar(10), primary key(a));
+insert into t2 values (1, "on"), (2, "off"), (10, "pol"), (12, "meg");
+insert into t1 values (289), (298), (234), (456), (789);
+create view v1 as select * from t2;
+create view v2 as select * from t1;
+drop table t1, t2;
+drop view v1, v2;
+drop database db2;
+create database db1;
+use db1;
+show tables;
+Tables_in_db1
+t1
+t2
+v1
+v2
+select * from t2 order by a;
+a b
+1 on
+2 off
+10 pol
+12 meg
+drop table t1, t2;
+drop database db1;
CREATE DATABASE mysqldump_test_db;
USE mysqldump_test_db;
CREATE TABLE t1 ( a INT );
@@ -1407,6 +1495,28 @@ CREATE TABLE `t2` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="mysqldump_test_db">
+ <table_structure name="t1">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+ <table_structure name="t2">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+</database>
+</mysqldump>
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="mysqldump_test_db">
+ <table_structure name="t1">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+ <table_structure name="t2">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ </table_structure>
+</database>
+</mysqldump>
DROP TABLE t1, t2;
DROP DATABASE mysqldump_test_db;
create database mysqldump_test_db;
@@ -1493,3 +1603,482 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir
</database>
</mysqldump>
drop table t1, t2;
+create table t1(a int);
+create view v1 as select * from t1;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+DROP TABLE IF EXISTS `v1`;
+/*!50001 DROP VIEW IF EXISTS `v1`*/;
+/*!50001 CREATE TABLE `v1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1*/;
+/*!50001 DROP TABLE IF EXISTS `v1`*/;
+/*!50001 DROP VIEW IF EXISTS `v1`*/;
+/*!50001 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1`*/;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+drop view v1;
+drop table t1;
+create database mysqldump_test_db;
+use mysqldump_test_db;
+CREATE TABLE t2 (
+a varchar(30) default NULL,
+KEY a (a(5))
+);
+INSERT INTO t2 VALUES ('alfred');
+INSERT INTO t2 VALUES ('angie');
+INSERT INTO t2 VALUES ('bingo');
+INSERT INTO t2 VALUES ('waffle');
+INSERT INTO t2 VALUES ('lemon');
+create view v2 as select * from t2 where a like 'a%' with check option;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t2`;
+CREATE TABLE `t2` (
+ `a` varchar(30) default NULL,
+ KEY `a` (`a`(5))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
+LOCK TABLES `t2` WRITE;
+INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon');
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
+DROP TABLE IF EXISTS `v2`;
+/*!50001 DROP VIEW IF EXISTS `v2`*/;
+/*!50001 CREATE TABLE `v2` (
+ `a` varchar(30) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1*/;
+/*!50001 DROP TABLE IF EXISTS `v2`*/;
+/*!50001 DROP VIEW IF EXISTS `v2`*/;
+/*!50001 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where (`t2`.`a` like _latin1'a%') WITH CASCADED CHECK OPTION*/;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+drop table t2;
+drop view v2;
+drop database mysqldump_test_db;
+use test;
+CREATE TABLE t1 (a char(10));
+INSERT INTO t1 VALUES ('\'');
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` char(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES ('\'');
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+DROP TABLE t1;
+create table t1(a int, b int, c varchar(30));
+insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three");
+create view v3 as
+select * from t1;
+create view v1 as
+select * from v3 where b in (1, 2, 3, 4, 5, 6, 7);
+create view v2 as
+select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1;
+drop view v1, v2, v3;
+drop table t1;
+show full tables;
+Tables_in_test Table_type
+t1 BASE TABLE
+v1 VIEW
+v2 VIEW
+v3 VIEW
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `v3`.`a` AS `a`,`v3`.`b` AS `b`,`v3`.`c` AS `c` from `v3` where (`v3`.`b` in (1,2,3,4,5,6,7))
+select * from v1;
+a b c
+1 2 one
+2 4 two
+3 6 three
+drop view v1, v2, v3;
+drop table t1;
+CREATE TABLE t1 (a int, b bigint default NULL);
+CREATE TABLE t2 (a int);
+create trigger trg1 before insert on t1 for each row
+begin
+if new.a > 10 then
+set new.a := 10;
+set new.a := 11;
+end if;
+end|
+create trigger trg2 before update on t1 for each row begin
+if old.a % 2 = 0 then set new.b := 12; end if;
+end|
+set sql_mode="traditional"|
+create trigger trg3 after update on t1 for each row
+begin
+if new.a = -1 then
+set @fired:= "Yes";
+end if;
+end|
+create trigger trg4 before insert on t2 for each row
+begin
+if new.a > 10 then
+set @fired:= "No";
+end if;
+end|
+set sql_mode=default|
+show triggers like "t1";
+Trigger Event Table Statement Timing Created sql_mode
+trg1 INSERT t1
+begin
+if new.a > 10 then
+set new.a := 10;
+set new.a := 11;
+end if;
+end BEFORE 0000-00-00 00:00:00
+trg2 UPDATE t1 begin
+if old.a % 2 = 0 then set new.b := 12; end if;
+end BEFORE 0000-00-00 00:00:00
+trg3 UPDATE t1
+begin
+if new.a = -1 then
+set @fired:= "Yes";
+end if;
+end AFTER 0000-00-00 00:00:00 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+INSERT INTO t1 (a) VALUES (1),(2),(3),(22);
+update t1 set a = 4 where a=3;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
+
+USE `test`;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL,
+ `b` bigint(20) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES (1,NULL),(2,NULL),(4,NULL),(11,NULL);
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;
+DELIMITER //;
+/*!50003 SET SESSION SQL_MODE="" */ //
+/*!50003 CREATE TRIGGER `trg1` BEFORE INSERT ON `t1` FOR EACH ROW
+begin
+if new.a > 10 then
+set new.a := 10;
+set new.a := 11;
+end if;
+end */ //
+
+/*!50003 SET SESSION SQL_MODE="" */ //
+/*!50003 CREATE TRIGGER `trg2` BEFORE UPDATE ON `t1` FOR EACH ROW begin
+if old.a % 2 = 0 then set new.b := 12; end if;
+end */ //
+
+/*!50003 SET SESSION SQL_MODE="STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER" */ //
+/*!50003 CREATE TRIGGER `trg3` AFTER UPDATE ON `t1` FOR EACH ROW
+begin
+if new.a = -1 then
+set @fired:= "Yes";
+end if;
+end */ //
+
+DELIMITER ;//
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;DROP TABLE IF EXISTS `t2`;
+CREATE TABLE `t2` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
+LOCK TABLES `t2` WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
+
+/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;
+DELIMITER //;
+/*!50003 SET SESSION SQL_MODE="STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER" */ //
+/*!50003 CREATE TRIGGER `trg4` BEFORE INSERT ON `t2` FOR EACH ROW
+begin
+if new.a > 10 then
+set @fired:= "No";
+end if;
+end */ //
+
+DELIMITER ;//
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
+
+USE `test`;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL,
+ `b` bigint(20) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES (1,NULL),(2,NULL),(4,NULL),(11,NULL);
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+DROP TABLE IF EXISTS `t2`;
+CREATE TABLE `t2` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
+LOCK TABLES `t2` WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+drop table t1;
+show tables;
+Tables_in_test
+t1
+t2
+show triggers;
+Trigger Event Table Statement Timing Created sql_mode
+trg1 INSERT t1
+begin
+if new.a > 10 then
+set new.a := 10;
+set new.a := 11;
+end if;
+end BEFORE #
+trg2 UPDATE t1 begin
+if old.a % 2 = 0 then set new.b := 12; end if;
+end BEFORE #
+trg3 UPDATE t1
+begin
+if new.a = -1 then
+set @fired:= "Yes";
+end if;
+end AFTER # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+trg4 INSERT t2
+begin
+if new.a > 10 then
+set @fired:= "No";
+end if;
+end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+DROP TABLE t1, t2;
+--port=1234
+--port=1234
+DROP TABLE IF EXISTS `test1`;
+Warnings:
+Note 1051 Unknown table 'test1'
+CREATE TABLE `test1` (
+`a1` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS `test2`;
+Warnings:
+Note 1051 Unknown table 'test2'
+CREATE TABLE `test2` (
+`a2` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+CREATE TRIGGER `testref` BEFORE INSERT ON `test1` FOR EACH ROW BEGIN
+INSERT INTO test2 SET a2 = NEW.a1; END //
+INSERT INTO `test1` VALUES (1);
+SELECT * FROM `test2`;
+a2
+1
+SHOW TRIGGERS;
+Trigger Event Table Statement Timing Created sql_mode
+testref INSERT test1 BEGIN
+INSERT INTO test2 SET a2 = NEW.a1; END BEFORE NULL
+SELECT * FROM `test1`;
+a1
+1
+SELECT * FROM `test2`;
+a2
+1
+DROP TRIGGER testref;
+DROP TABLE test1;
+DROP TABLE test2;
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS bug9056_func1;
+DROP FUNCTION IF EXISTS bug9056_func2;
+DROP PROCEDURE IF EXISTS bug9056_proc1;
+DROP PROCEDURE IF EXISTS bug9056_proc2;
+CREATE TABLE t1 (id int);
+INSERT INTO t1 VALUES(1), (2), (3), (4), (5);
+CREATE FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11) RETURN a+b //
+CREATE PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
+BEGIN SELECT a+b INTO c; end //
+create function bug9056_func2(f1 char binary) returns char binary
+begin
+set f1= concat( 'hello', f1 );
+return f1;
+end //
+CREATE PROCEDURE bug9056_proc2(OUT a INT)
+BEGIN
+select sum(id) from t1 into a;
+END //
+set sql_mode='ansi';
+create procedure `a'b` () select 1;
+set sql_mode='';
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
+
+USE `test`;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `id` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES (1),(2),(3),(4),(5);
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+DELIMITER //
+/*!50003 DROP FUNCTION IF EXISTS `bug9056_func1` */ //
+/*!50003 SET SESSION SQL_MODE=""*/ //
+/*!50003 CREATE FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11)
+RETURN a+b */ //
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/ //
+/*!50003 DROP FUNCTION IF EXISTS `bug9056_func2` */ //
+/*!50003 SET SESSION SQL_MODE=""*/ //
+/*!50003 CREATE FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1)
+begin
+set f1= concat( 'hello', f1 );
+return f1;
+end */ //
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/ //
+/*!50003 DROP PROCEDURE IF EXISTS `a'b` */ //
+/*!50003 SET SESSION SQL_MODE="REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI"*/ //
+/*!50003 CREATE PROCEDURE "a'b"()
+select 1 */ //
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/ //
+/*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc1` */ //
+/*!50003 SET SESSION SQL_MODE=""*/ //
+/*!50003 CREATE PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
+BEGIN SELECT a+b INTO c; end */ //
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/ //
+/*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc2` */ //
+/*!50003 SET SESSION SQL_MODE=""*/ //
+/*!50003 CREATE PROCEDURE `bug9056_proc2`(OUT a INT)
+BEGIN
+select sum(id) from t1 into a;
+END */ //
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/ //
+DELIMITER ;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+DROP FUNCTION bug9056_func1;
+DROP FUNCTION bug9056_func2;
+DROP PROCEDURE bug9056_proc1;
+DROP PROCEDURE bug9056_proc2;
+drop table t1;
diff --git a/mysql-test/r/mysqlshow.result b/mysql-test/r/mysqlshow.result
new file mode 100644
index 00000000000..a04a7081b34
--- /dev/null
+++ b/mysql-test/r/mysqlshow.result
@@ -0,0 +1,76 @@
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE TABLE t2 (a int, b int);
+show tables;
+Tables_in_test
+t1
+t2
+select "--------------------" as "";
+
+--------------------
+Database: test
++--------+
+| Tables |
++--------+
+| t1 |
+| t2 |
++--------+
+select "---- -v ------------" as "";
+
+---- -v ------------
+Database: test
++--------+----------+
+| Tables | Columns |
++--------+----------+
+| t1 | 1 |
+| t2 | 2 |
++--------+----------+
+2 rows in set.
+
+select "---- -v -v ---------" as "";
+
+---- -v -v ---------
+Database: test
++--------+----------+------------+
+| Tables | Columns | Total Rows |
++--------+----------+------------+
+| t1 | 1 | 3 |
+| t2 | 2 | 0 |
++--------+----------+------------+
+2 rows in set.
+
+select "----- -t -----------" as "";
+
+----- -t -----------
+Database: test
++--------+------------+
+| Tables | table_type |
++--------+------------+
+| t1 | BASE TABLE |
+| t2 | BASE TABLE |
++--------+------------+
+select "---- -v -t ---------" as "";
+
+---- -v -t ---------
+Database: test
++--------+------------+----------+
+| Tables | table_type | Columns |
++--------+------------+----------+
+| t1 | BASE TABLE | 1 |
+| t2 | BASE TABLE | 2 |
++--------+------------+----------+
+2 rows in set.
+
+select "---- -v -v -t ------" as "";
+
+---- -v -v -t ------
+Database: test
++--------+------------+----------+------------+
+| Tables | table_type | Columns | Total Rows |
++--------+------------+----------+------------+
+| t1 | BASE TABLE | 1 | 3 |
+| t2 | BASE TABLE | 2 | 0 |
++--------+------------+----------+------------+
+2 rows in set.
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index ae44233aab6..c643a5ae647 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -152,6 +152,7 @@ mysqltest: At line 1: End of line junk detected: "6"
mysqltest: At line 1: End of line junk detected: "6"
mysqltest: At line 1: Missing delimiter
mysqltest: At line 1: Extra delimiter ";" found
+mysqltest: At line 1: Extra delimiter ";" found
MySQL
"MySQL"
MySQL: The world''s most popular open source database
@@ -350,3 +351,27 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
SELECT 1 as a;
a
1
+select 1 as `a'b`, 2 as `a"b`;
+a'b a"b
+1 2
+select 'aaa\\','aa''a',"aa""a";
+aaa\ aa'a aa"a
+aaa\ aa'a aa"a
+
+Here comes a message
+--------------------
+
+root@localhost
+--------------
+
+"Here comes a very very long message that
+ - is longer then 80 characters and
+ - consists of several lines"
+--------------------------------------------------------------------------------
+
+. Here comes a very very long message that
+. - is longer then 80 characters and
+. - consists of several lines
+--------------------------------------------------------------------------------
+this will be executed
+this will be executed
diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result
index 63afc07718f..ed49e7f3943 100644
--- a/mysql-test/r/ndb_alter_table.result
+++ b/mysql-test/r/ndb_alter_table.result
@@ -34,13 +34,13 @@ col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null,
col6 int not null, to_be_deleted int) ENGINE=ndbcluster;
show table status;
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 ndbcluster 9 Dynamic 0 0 0 NULL 0 0 1 NULL NULL NULL latin1_swedish_ci NULL
+t1 ndbcluster 10 Dynamic 0 0 # # 0 # 1 # # # latin1_swedish_ci NULL #
SET SQL_MODE=NO_AUTO_VALUE_ON_ZERO;
insert into t1 values
(0,4,3,5,"PENDING",1,7),(NULL,4,3,5,"PENDING",1,7),(31,4,3,5,"PENDING",1,7), (7,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7), (100,4,3,5,"PENDING",1,7), (99,4,3,5,"PENDING",1,7), (8,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7);
show table status;
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 ndbcluster 9 Dynamic 9 0 0 NULL 0 0 102 NULL NULL NULL latin1_swedish_ci NULL
+t1 ndbcluster 10 Dynamic 9 96 # # 0 # 102 # # # latin1_swedish_ci NULL #
select * from t1 order by col1;
col1 col2 col3 col4 col5 col6 to_be_deleted
0 4 3 5 PENDING 1 7
@@ -60,7 +60,7 @@ change column col2 fourth varchar(30) not null after col3,
modify column col6 int not null first;
show table status;
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 ndbcluster 9 Dynamic 9 0 0 NULL 0 0 102 NULL NULL NULL latin1_swedish_ci NULL
+t1 ndbcluster 10 Dynamic 9 152 # # 0 # 102 # # # latin1_swedish_ci NULL #
select * from t1 order by col1;
col6 col1 col3 fourth col4 col4_5 col5 col7 col8
1 0 3 4 5 PENDING 0000-00-00 00:00:00
@@ -75,7 +75,7 @@ col6 col1 col3 fourth col4 col4_5 col5 col7 col8
insert into t1 values (2, NULL,4,3,5,99,"PENDING","EXTRA",'2004-01-01 00:00:00');
show table status;
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 ndbcluster 9 Dynamic 10 0 0 NULL 0 0 103 NULL NULL NULL latin1_swedish_ci NULL
+t1 ndbcluster 10 Dynamic 10 152 # # 0 # 103 # # # latin1_swedish_ci NULL #
select * from t1 order by col1;
col6 col1 col3 fourth col4 col4_5 col5 col7 col8
1 0 3 4 5 PENDING 0000-00-00 00:00:00
diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result
index c61270c02a8..6d1b7eb152d 100644
--- a/mysql-test/r/ndb_autodiscover.result
+++ b/mysql-test/r/ndb_autodiscover.result
@@ -107,7 +107,7 @@ Handler_discover 0
SHOW CREATE TABLE t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `id` int(11) NOT NULL default '0',
+ `id` int(11) NOT NULL,
`name` char(255) default NULL,
PRIMARY KEY (`id`)
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
@@ -146,8 +146,8 @@ Handler_discover 1
flush tables;
show table status;
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
-t6 MyISAM 9 Fixed 1 260 # # # 0 NULL # # NULL # NULL
-t7 ndbcluster 9 Fixed 1 0 # # # 0 NULL # # NULL # NULL
+t6 MyISAM 10 Fixed 1 260 # # # 0 NULL # # NULL # NULL #
+t7 ndbcluster 10 Fixed 1 276 # # # 0 NULL # # NULL # NULL #
show status like 'handler_discover%';
Variable_name Value
Handler_discover 2
@@ -169,6 +169,25 @@ show status like 'handler_discover%';
Variable_name Value
Handler_discover 0
drop table t4;
+ERROR 42S02: Unknown table 't4'
+create table t4(
+id int not null primary key,
+name char(27)
+) engine=ndb;
+insert into t4 values (1, "Automatic");
+select * from t4;
+id name
+1 Automatic
+select * from t4;
+ERROR 42S02: Table 'test.t4' doesn't exist
+drop table if exists t4;
+Warnings:
+Error 155 Table 'test.t4' doesn't exist
+drop table t5;
+ERROR 42S02: Unknown table 't5'
+drop table if exists t5;
+Warnings:
+Note 1051 Unknown table 't5'
flush status;
create table t4(
id int not null primary key,
@@ -355,11 +374,17 @@ drop table t1;
use test2;
drop table t2;
drop database test2;
-show databases;
-Database
-mysql
-test
use test;
+drop database if exists test_only_ndb_tables;
+create database test_only_ndb_tables;
+use test_only_ndb_tables;
+create table t1 (a int primary key) engine=ndb;
+select * from t1;
+a
+select * from t1;
+ERROR HY000: Can't lock file (errno: 4009)
+use test;
+drop database test_only_ndb_tables;
CREATE TABLE t9 (
a int NOT NULL PRIMARY KEY,
b int
diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result
index 3712fa2b5ca..a374f845933 100644
--- a/mysql-test/r/ndb_basic.result
+++ b/mysql-test/r/ndb_basic.result
@@ -577,7 +577,7 @@ create table t1
(a bigint, b bigint, c bigint, d bigint,
primary key (a,b,c,d))
engine=ndb
-max_rows=200000000;
+max_rows=800000000;
Warnings:
Warning 1105 Ndb might have problems storing the max amount of rows specified
insert into t1 values
@@ -667,3 +667,9 @@ counter datavalue
57 newval
58 newval
drop table t1;
+create table atablewithareallylongandirritatingname (a int);
+insert into atablewithareallylongandirritatingname values (2);
+select * from atablewithareallylongandirritatingname;
+a
+2
+drop table atablewithareallylongandirritatingname;
diff --git a/mysql-test/r/ndb_bitfield.result b/mysql-test/r/ndb_bitfield.result
new file mode 100644
index 00000000000..bf5a9b1ade1
--- /dev/null
+++ b/mysql-test/r/ndb_bitfield.result
@@ -0,0 +1,210 @@
+drop table if exists t1;
+create table t1 (
+pk1 int not null primary key,
+b bit(64)
+) engine=ndbcluster;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk1` int(11) NOT NULL,
+ `b` bit(64) default NULL,
+ PRIMARY KEY (`pk1`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+insert into t1 values
+(0,b'1111111111111111111111111111111111111111111111111111111111111111'),
+(1,b'1000000000000000000000000000000000000000000000000000000000000000'),
+(2,b'0000000000000000000000000000000000000000000000000000000000000001'),
+(3,b'1010101010101010101010101010101010101010101010101010101010101010'),
+(4,b'0101010101010101010101010101010101010101010101010101010101010101');
+select hex(b) from t1 order by pk1;
+hex(b)
+FFFFFFFFFFFFFFFF
+8000000000000000
+1
+AAAAAAAAAAAAAAAA
+5555555555555555
+drop table t1;
+create table t1 (
+pk1 int not null primary key,
+b bit(9)
+) engine=ndbcluster;
+insert into t1 values
+(0,b'000000000'),
+(1,b'000000001'),
+(2,b'000000010'),
+(3,b'000000011'),
+(4,b'000000100');
+select hex(b) from t1 order by pk1;
+hex(b)
+0
+1
+2
+3
+4
+update t1 set b = b + b'101010101';
+select hex(b) from t1 order by pk1;
+hex(b)
+155
+156
+157
+158
+159
+drop table t1;
+create table t1 (a bit(7), b bit(9)) engine = ndbcluster;
+insert into t1 values
+(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177),
+(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380),
+(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36),
+(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499),
+(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403),
+(44, 307), (68, 454), (57, 135);
+select a+0 from t1 order by a;
+a+0
+0
+4
+5
+9
+23
+24
+28
+29
+30
+31
+34
+44
+49
+56
+57
+59
+60
+61
+68
+68
+75
+77
+78
+79
+87
+88
+94
+94
+104
+106
+108
+111
+116
+118
+119
+122
+123
+127
+select b+0 from t1 order by b;
+b+0
+36
+42
+46
+67
+83
+118
+123
+133
+135
+152
+177
+178
+188
+202
+206
+245
+280
+307
+343
+345
+349
+351
+363
+368
+368
+379
+380
+390
+398
+399
+403
+411
+411
+438
+446
+454
+468
+499
+drop table t1;
+create table t1 (
+dummyKey INTEGER NOT NULL,
+a001 TINYINT,
+a010 TINYINT,
+a012 TINYINT,
+a015 TINYINT,
+a016 TINYINT,
+a017 TINYINT,
+a019 TINYINT,
+a029 TINYINT,
+a030 TINYINT,
+a031 TINYINT,
+a032 TINYINT,
+a042 TINYINT,
+a043 TINYINT,
+a044 TINYINT,
+a3001 TINYINT,
+a3002 TINYINT,
+a3003 TINYINT,
+a3004 TINYINT,
+a3005 TINYINT,
+a3021 TINYINT,
+a3022 TINYINT,
+a BIT(6),
+b BIT(6),
+c BIT(6),
+d TINYINT,
+e TINYINT,
+f TINYINT,
+g TINYINT,
+h TINYINT,
+i TINYINT,
+j TINYINT,
+k TINYINT,
+l TINYINT,
+m TINYINT,
+n TINYINT,
+o TINYINT,
+a034 TINYINT,
+PRIMARY KEY USING HASH (dummyKey) ) engine=ndb;
+INSERT INTO `t1` VALUES
+(1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000001',b'111111',b'111110',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000010',b'000000',b'111101',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000100',b'001111',b'111011',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'001000',b'110000',b'110111',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'010000',b'100001',b'101111',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'100000',b'010010',b'011111',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'001100',b'111111',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO `t1` VALUES (1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x01,0x3F,0x3E,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO `t1` VALUES (2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x02,0x00,0x3D,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO `t1` VALUES (3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x04,0x0F,0x3B,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO `t1` VALUES (4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x08,0x30,0x37,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO `t1` VALUES (5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x10,0x21,0x2F,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO `t1` VALUES (6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x20,0x12,0x1F,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO `t1` VALUES (7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x00,0x0C,0x3F,4,5,5,5,5,5,5,5,5,5,3,2,1);
+INSERT INTO `t1` VALUES (8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x3F,0x00,0x00,4,5,5,5,5,5,5,5,5,5,3,2,1);
+drop table t1;
+create table t1 (
+pk1 bit(9) not null primary key,
+b int
+) engine=ndbcluster;
+ERROR HY000: Can't create table './test/t1.frm' (errno: 739)
+create table t1 (
+pk1 int not null primary key,
+b bit(9),
+key(b)
+) engine=ndbcluster;
+ERROR HY000: Can't create table './test/t1.frm' (errno: 743)
diff --git a/mysql-test/r/ndb_blob.result b/mysql-test/r/ndb_blob.result
index 6f25ec95c80..f806cf08ea9 100644
--- a/mysql-test/r/ndb_blob.result
+++ b/mysql-test/r/ndb_blob.result
@@ -134,7 +134,7 @@ insert into t1 values(2,@b2,222,@d2);
commit;
explain select * from t1 where c = 111;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref c c 4 const 10 Using where
+1 SIMPLE t1 ref c c 4 const 10
select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3)
from t1 where c=111;
a length(b) substr(b,1+2*900,2) length(d) substr(d,1+3*900,3)
diff --git a/mysql-test/r/ndb_cache.result b/mysql-test/r/ndb_cache.result
index 714e1831267..478663b1aa1 100644
--- a/mysql-test/r/ndb_cache.result
+++ b/mysql-test/r/ndb_cache.result
@@ -1,43 +1,191 @@
+drop table if exists t1;
+set GLOBAL query_cache_type=on;
set GLOBAL query_cache_size=1355776;
reset query cache;
flush status;
-drop table if exists t1,t2;
-CREATE TABLE t1 (a int) ENGINE=ndbcluster;
-CREATE TABLE t2 (a int);
+CREATE TABLE t1 ( pk int not null primary key,
+a int, b int not null, c varchar(20)) ENGINE=ndbcluster;
+insert into t1 value (1, 2, 3, 'First row');
select * from t1;
-a
+pk a b c
+1 2 3 First row
show status like "Qcache_queries_in_cache";
Variable_name Value
-Qcache_queries_in_cache 0
+Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
-Qcache_inserts 0
+Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
-select * from t2;
-a
+select * from t1;
+pk a b c
+1 2 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+update t1 set a=3 where pk=1;
+select * from t1;
+pk a b c
+1 3 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+select * from t1 order by pk;
+pk a b c
+1 3 3 First row
+2 7 8 Second row
+4 5 6 Fourth row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+select * from t1 order by pk;
+pk a b c
+1 3 3 First row
+2 7 8 Second row
+4 5 6 Fourth row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+delete from t1 where c='Fourth row';
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+use test;
+select * from t1 order by pk;
+pk a b c
+1 3 3 First row
+2 7 8 Second row
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 4
+update t1 set a=4 where b=3;
+use test;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 5
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
-Qcache_inserts 1
+Qcache_inserts 7
show status like "Qcache_hits";
Variable_name Value
-Qcache_hits 0
-select * from t1;
-a
-select * from t2;
-a
+Qcache_hits 7
+begin;
+update t1 set a=5 where pk=1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
-Qcache_inserts 1
+Qcache_inserts 8
show status like "Qcache_hits";
Variable_name Value
-Qcache_hits 1
-drop table t1, t2;
+Qcache_hits 7
+commit;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 8
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 9
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 9
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 8
+drop table t1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
SET GLOBAL query_cache_size=0;
diff --git a/mysql-test/r/ndb_cache2.result b/mysql-test/r/ndb_cache2.result
new file mode 100644
index 00000000000..2876002f864
--- /dev/null
+++ b/mysql-test/r/ndb_cache2.result
@@ -0,0 +1,623 @@
+drop table if exists t1, t2, t3, t4, t5;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=100;
+reset query cache;
+flush status;
+CREATE TABLE t1 (
+pk int not null primary key,
+a1 int,
+b1 int not null,
+c1 varchar(20)
+) ENGINE=ndb;
+CREATE TABLE t2 (
+pk int not null primary key,
+a2 int,
+b2 int not null
+) ENGINE=ndb;
+CREATE TABLE t3 (
+pk int not null primary key,
+a3 int,
+b3 int not null,
+c3 int not null,
+d3 varchar(20)
+) ENGINE=ndb;
+CREATE TABLE t4 (
+a4 int,
+b4 int not null,
+c4 char(20)
+) ENGINE=ndbcluster;
+CREATE TABLE t5 (
+pk int not null primary key,
+a5 int,
+b5 int not null,
+c5 varchar(255)
+) ENGINE=ndbcluster;
+insert into t1 value (1, 2, 3, 'First row');
+insert into t2 value (1, 2, 3);
+insert into t3 value (1, 2, 3, 4, '3 - First row');
+insert into t4 value (2, 3, '4 - First row');
+insert into t5 value (1, 2, 3, '5 - First row');
+select * from t1;
+pk a1 b1 c1
+1 2 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+pk a1 b1 c1
+1 2 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+update t1 set a1=3 where pk=1;
+select * from t1;
+pk a1 b1 c1
+1 3 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+select * from t1 order by pk desc;
+pk a1 b1 c1
+4 5 6 Fourth row
+2 7 8 Second row
+1 3 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+select * from t1 order by pk desc;
+pk a1 b1 c1
+4 5 6 Fourth row
+2 7 8 Second row
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+select * from t1 where b1=3;
+pk a1 b1 c1
+1 3 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+select * from t1 where b1=3;
+pk a1 b1 c1
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+delete from t1 where c1='Fourth row';
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1 where b1=3;
+pk a1 b1 c1
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+use test;
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 3 3 First row
+select * from t1 where b1=3;
+pk a1 b1 c1
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 4
+update t1 set a1=4 where b1=3;
+use test;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 4 3 First row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 4 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 5
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 4 3 First row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 4 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t2;
+pk a2 b2
+1 2 3
+select * from t3;
+pk a3 b3 c3 d3
+1 2 3 4 3 - First row
+select * from t4;
+a4 b4 c4
+2 3 4 - First row
+select * from t5;
+pk a5 b5 c5
+1 2 3 5 - First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+flush status;
+begin;
+update t1 set a1=5 where pk=1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 4
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 4 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+commit;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+flush status;
+begin;
+update t1 set a1=6 where pk=1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 4
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 5 3 First row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 6 3 First row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 6 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+commit;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 6 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 6 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+flush status;
+begin;
+insert into t1 set pk=5, a1=6, b1=3, c1="New row";
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 4
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 where pk=5;
+pk a1 b1 c1
+select * from t1 order by pk desc;
+pk a1 b1 c1
+2 7 8 Second row
+1 6 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 where pk=5;
+pk a1 b1 c1
+5 6 3 New row
+select * from t1 where pk=5;
+pk a1 b1 c1
+5 6 3 New row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+2 7 8 Second row
+1 6 3 First row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+2 7 8 Second row
+1 6 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+commit;
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+2 7 8 Second row
+1 6 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+flush status;
+begin;
+delete from t1 where pk=2;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 4
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 where pk=2;
+pk a1 b1 c1
+2 7 8 Second row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+2 7 8 Second row
+1 6 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 where pk=2;
+pk a1 b1 c1
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 6 3 First row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 6 3 First row
+select * from t1 where pk=2;
+pk a1 b1 c1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+commit;
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 6 3 First row
+select * from t1 where pk=2;
+pk a1 b1 c1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 6
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 4
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+flush status;
+begin;
+update t1 set a1=9 where pk=1;
+update t2 set a2=9 where pk=1;
+update t3 set a3=9 where pk=1;
+update t4 set a4=9 where a4=2;
+update t5 set a5=9 where pk=1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 6 3 First row
+select * from t2;
+pk a2 b2
+1 2 3
+select * from t3;
+pk a3 b3 c3 d3
+1 2 3 4 3 - First row
+select * from t4;
+a4 b4 c4
+2 3 4 - First row
+select * from t5;
+pk a5 b5 c5
+1 2 3 5 - First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 5
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 9 3 First row
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 9 3 First row
+select * from t2;
+pk a2 b2
+1 9 3
+select * from t3;
+pk a3 b3 c3 d3
+1 9 3 4 3 - First row
+select * from t4;
+a4 b4 c4
+9 3 4 - First row
+select * from t5;
+pk a5 b5 c5
+1 9 3 5 - First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 5
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+commit;
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 9 3 First row
+select * from t2;
+pk a2 b2
+1 9 3
+select * from t3;
+pk a3 b3 c3 d3
+1 9 3 4 3 - First row
+select * from t4;
+a4 b4 c4
+9 3 4 - First row
+select * from t5;
+pk a5 b5 c5
+1 9 3 5 - First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 10
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 9 3 First row
+select * from t2;
+pk a2 b2
+1 9 3
+select * from t3;
+pk a3 b3 c3 d3
+1 9 3 4 3 - First row
+select * from t4;
+a4 b4 c4
+9 3 4 - First row
+select * from t5;
+pk a5 b5 c5
+1 9 3 5 - First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 10
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 5
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 9 3 First row
+select * from t2;
+pk a2 b2
+1 9 3
+select * from t3;
+pk a3 b3 c3 d3
+1 9 3 4 3 - First row
+select * from t4;
+a4 b4 c4
+9 3 4 - First row
+select * from t5;
+pk a5 b5 c5
+1 9 3 5 - First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 10
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 10
+select * from t1 order by pk desc;
+pk a1 b1 c1
+5 6 3 New row
+1 9 3 First row
+select * from t2;
+pk a2 b2
+1 9 3
+select * from t3;
+pk a3 b3 c3 d3
+1 9 3 4 3 - First row
+select * from t4;
+a4 b4 c4
+9 3 4 - First row
+select * from t5;
+pk a5 b5 c5
+1 9 3 5 - First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 5
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 10
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 15
+drop table t1, t2, t3, t4, t5;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+SET GLOBAL query_cache_size=0;
+SET GLOBAL ndb_cache_check_time=0;
diff --git a/mysql-test/r/ndb_cache_multi.result b/mysql-test/r/ndb_cache_multi.result
new file mode 100644
index 00000000000..c7135ed9e8a
--- /dev/null
+++ b/mysql-test/r/ndb_cache_multi.result
@@ -0,0 +1,72 @@
+drop table if exists t1, t2;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+a
+2
+select * from t2;
+a
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+update t1 set a=3 where a=2;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+drop table t1, t2;
diff --git a/mysql-test/r/ndb_cache_multi2.result b/mysql-test/r/ndb_cache_multi2.result
new file mode 100644
index 00000000000..2863908a436
--- /dev/null
+++ b/mysql-test/r/ndb_cache_multi2.result
@@ -0,0 +1,82 @@
+drop table if exists t1, t2;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=1;
+reset query cache;
+flush status;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=1;
+reset query cache;
+flush status;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+a
+2
+select * from t2;
+a
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+update t1 set a=3 where a=2;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+drop table t1, t2;
+set GLOBAL query_cache_size=0;
+set GLOBAL ndb_cache_check_time=0;
+reset query cache;
+flush status;
+set GLOBAL query_cache_size=0;
+set GLOBAL ndb_cache_check_time=0;
+reset query cache;
+flush status;
diff --git a/mysql-test/r/ndb_charset.result b/mysql-test/r/ndb_charset.result
index 00bc36a7c0d..500b0497890 100644
--- a/mysql-test/r/ndb_charset.result
+++ b/mysql-test/r/ndb_charset.result
@@ -47,6 +47,40 @@ a
aAa
drop table t1;
create table t1 (
+a varchar(20) character set latin1 collate latin1_swedish_ci primary key
+) engine=ndb;
+insert into t1 values ('A'),('b '),('C '),('d '),('E'),('f');
+insert into t1 values('b');
+ERROR 23000: Duplicate entry 'b' for key 1
+insert into t1 values('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+select a,length(a) from t1 order by a;
+a length(a)
+A 1
+b 2
+C 3
+d 7
+E 1
+f 1
+select a,length(a) from t1 order by a desc;
+a length(a)
+f 1
+E 1
+d 7
+C 3
+b 2
+A 1
+select * from t1 where a = 'a';
+a
+A
+select * from t1 where a = 'a ';
+a
+A
+select * from t1 where a = 'd';
+a
+d
+drop table t1;
+create table t1 (
p int primary key,
a char(3) character set latin1 collate latin1_bin not null,
unique key(a)
@@ -99,6 +133,42 @@ p a
drop table t1;
create table t1 (
p int primary key,
+a varchar(20) character set latin1 collate latin1_swedish_ci not null,
+unique key(a)
+) engine=ndb;
+insert into t1 values (1,'A'),(2,'b '),(3,'C '),(4,'d '),(5,'E'),(6,'f');
+insert into t1 values(99,'b');
+ERROR 23000: Duplicate entry '99' for key 1
+insert into t1 values(99,'a ');
+ERROR 23000: Duplicate entry '99' for key 1
+select a,length(a) from t1 order by a;
+a length(a)
+A 1
+b 2
+C 3
+d 7
+E 1
+f 1
+select a,length(a) from t1 order by a desc;
+a length(a)
+f 1
+E 1
+d 7
+C 3
+b 2
+A 1
+select * from t1 where a = 'a';
+p a
+1 A
+select * from t1 where a = 'a ';
+p a
+1 A
+select * from t1 where a = 'd';
+p a
+4 d
+drop table t1;
+create table t1 (
+p int primary key,
a char(3) character set latin1 collate latin1_bin not null,
index(a)
) engine=ndb;
@@ -190,7 +260,52 @@ p a
6 AAA
drop table t1;
create table t1 (
-a varchar(10) primary key
+p int primary key,
+a varchar(20) character set latin1 collate latin1_swedish_ci not null,
+index(a, p)
+) engine=ndb;
+insert into t1 values (1,'A'),(2,'b '),(3,'C '),(4,'d '),(5,'E'),(6,'f');
+insert into t1 values (7,'a'),(8,'B '),(9,'c '),(10,'D'),(11,'e'),(12,'F ');
+select p,a,length(a) from t1 order by a, p;
+p a length(a)
+1 A 1
+7 a 1
+2 b 2
+8 B 2
+3 C 3
+9 c 3
+4 d 7
+10 D 1
+5 E 1
+11 e 1
+6 f 1
+12 F 3
+select * from t1 where a = 'a ' order by a desc, p desc;
+p a
+7 a
+1 A
+select * from t1 where a >= 'D' order by a, p;
+p a
+4 d
+10 D
+5 E
+11 e
+6 f
+12 F
+select * from t1 where a < 'D' order by a, p;
+p a
+1 A
+7 a
+2 b
+8 B
+3 C
+9 c
+select count(*) from t1 x, t1 y, t1 z where x.a = y.a and y.a = z.a;
+count(*)
+48
+drop table t1;
+create table t1 (
+a char(10) primary key
) engine=ndb;
insert into t1 values ('jonas % ');
replace into t1 values ('jonas % ');
diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result
new file mode 100644
index 00000000000..1c3da1b486f
--- /dev/null
+++ b/mysql-test/r/ndb_condition_pushdown.result
@@ -0,0 +1,1770 @@
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (
+auto int(5) unsigned NOT NULL auto_increment,
+string char(10),
+vstring varchar(10),
+bin binary(7),
+vbin varbinary(7),
+tiny tinyint(4) DEFAULT '0' NOT NULL ,
+short smallint(6) DEFAULT '1' NOT NULL ,
+medium mediumint(8) DEFAULT '0' NOT NULL,
+long_int int(11) DEFAULT '0' NOT NULL,
+longlong bigint(13) DEFAULT '0' NOT NULL,
+real_float float(13,1) DEFAULT 0.0 NOT NULL,
+real_double double(16,4),
+real_decimal decimal(16,4),
+utiny tinyint(3) unsigned DEFAULT '0' NOT NULL,
+ushort smallint(5) unsigned zerofill DEFAULT '00000' NOT NULL,
+umedium mediumint(8) unsigned DEFAULT '0' NOT NULL,
+ulong int(11) unsigned DEFAULT '0' NOT NULL,
+ulonglong bigint(13) unsigned DEFAULT '0' NOT NULL,
+bits bit(3),
+options enum('zero','one','two','three','four') not null,
+flags set('zero','one','two','three','four') not null,
+date_field date,
+year_field year,
+time_field time,
+date_time datetime,
+time_stamp timestamp,
+PRIMARY KEY (auto)
+) engine=ndb;
+insert into t1 values
+(NULL,"aaaa","aaaa",0xAAAA,0xAAAA,-1,-1,-1,-1,-1,1.1,1.1,1.1,1,1,1,1,1,
+b'001','one','one',
+'1901-01-01','1901',
+'01:01:01','1901-01-01 01:01:01',NULL),
+(NULL,"bbbb","bbbb",0xBBBB,0xBBBB,-2,-2,-2,-2,-2,2.2,2.2,2.2,2,2,2,2,2,
+b'010','two','one,two',
+'1902-02-02','1902',
+'02:02:02','1902-02-02 02:02:02',NULL),
+(NULL,"cccc","cccc",0xCCCC,0xCCCC,-3,-3,-3,-3,-3,3.3,3.3,3.3,3,3,3,3,3,
+b'011','three','one,two,three',
+'1903-03-03','1903',
+'03:03:03','1903-03-03 03:03:03',NULL),
+(NULL,"dddd","dddd",0xDDDD,0xDDDD,-4,-4,-4,-4,-4,4.4,4.4,4.4,4,4,4,4,4,
+b'100','four','one,two,three,four',
+'1904-04-04','1904',
+'04:04:04','1904-04-04 04:04:04',NULL);
+CREATE TABLE t2 (pk1 int unsigned NOT NULL PRIMARY KEY, attr1 int unsigned NOT NULL, attr2 int unsigned, attr3 VARCHAR(10) ) ENGINE=ndbcluster;
+insert into t2 values (0,0,0, "a"),(1,1,1,"b"),(2,2,NULL,NULL),(3,3,3,"d"),(4,4,4,"e"),(5,5,5,"f");
+CREATE TABLE t3 (pk1 int unsigned NOT NULL PRIMARY KEY, attr1 int unsigned NOT NULL, attr2 bigint unsigned, attr3 tinyint unsigned, attr4 VARCHAR(10) ) ENGINE=ndbcluster;
+insert into t3 values (0,0,0,0,"a"),(1,1,9223372036854775803,1,"b"),(2,2,9223372036854775804,2,"c"),(3,3,9223372036854775805,3,"d"),(4,4,9223372036854775806,4,"e"),(5,5,9223372036854775807,5,"f");
+CREATE TABLE t4 (pk1 int unsigned NOT NULL PRIMARY KEY, attr1 int unsigned NOT NULL, attr2 bigint unsigned, attr3 tinyint unsigned, attr4 VARCHAR(10) , KEY (attr1)) ENGINE=ndbcluster;
+insert into t4 values (0,0,0,0,"a"),(1,1,9223372036854775803,1,"b"),(2,2,9223372036854775804,2,"c"),(3,3,9223372036854775805,3,"d"),(4,4,9223372036854775806,4,"e"),(5,5,9223372036854775807,5,"f");
+set @old_ecpd = @@session.engine_condition_pushdown;
+set engine_condition_pushdown = off;
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+bits = b'001' and
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+auto
+1
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+bits != b'001' and
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+auto
+2
+3
+4
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+bits > b'001' and
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+auto
+2
+3
+4
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+bits >= b'001' and
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+auto
+1
+2
+3
+4
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+bits < b'100' and
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+auto
+1
+2
+3
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 and
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+bits <= b'100' and
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+auto
+1
+2
+3
+4
+select auto from t1 where
+string like "b%" and
+vstring like "b%" and
+bin like concat(0xBB, '%') and
+vbin like concat(0xBB, '%')
+order by auto;
+auto
+2
+select auto from t1 where
+string not like "b%" and
+vstring not like "b%" and
+bin not like concat(0xBB, '%') and
+vbin not like concat(0xBB, '%')
+order by auto;
+auto
+1
+3
+4
+select auto from t1 where
+(string between "aaaa" and "cccc") and
+(vstring between "aaaa" and "cccc") and
+(bin between 0xAAAA and 0xCCCC) and
+(vbin between 0xAAAA and 0xCCCC) and
+(tiny between -3 and -1) and
+(short between -3 and -1) and
+(medium between -3 and -1) and
+(long_int between -3 and -1) and
+(longlong between -3 and -1) and
+(utiny between 1 and 3) and
+(ushort between 1 and 3) and
+(umedium between 1 and 3) and
+(ulong between 1 and 3) and
+(ulonglong between 1 and 3) and
+(bits between b'001' and b'011') and
+(options between 'one' and 'three') and
+(flags between 'one' and 'one,two,three') and
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+auto
+1
+3
+select auto from t1 where
+("aaaa" between string and string) and
+("aaaa" between vstring and vstring) and
+(0xAAAA between bin and bin) and
+(0xAAAA between vbin and vbin) and
+(-1 between tiny and tiny) and
+(-1 between short and short) and
+(-1 between medium and medium) and
+(-1 between long_int and long_int) and
+(-1 between longlong and longlong) and
+(1 between utiny and utiny) and
+(1 between ushort and ushort) and
+(1 between umedium and umedium) and
+(1 between ulong and ulong) and
+(1 between ulonglong and ulonglong) and
+(b'001' between bits and bits) and
+('one' between options and options) and
+('one' between flags and flags) and
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and
+('1901-01-01 01:01:01' between date_time and date_time)
+order by auto;
+auto
+1
+select auto from t1 where
+(string not between "aaaa" and "cccc") and
+(vstring not between "aaaa" and "cccc") and
+(bin not between 0xAAAA and 0xCCCC) and
+(vbin not between 0xAAAA and 0xCCCC) and
+(tiny not between -3 and -1) and
+(short not between -3 and -1) and
+(medium not between -3 and -1) and
+(long_int not between -3 and -1) and
+(longlong not between -3 and -1) and
+(utiny not between 1 and 3) and
+(ushort not between 1 and 3) and
+(umedium not between 1 and 3) and
+(ulong not between 1 and 3) and
+(ulonglong not between 1 and 3) and
+(bits not between b'001' and b'011') and
+(options not between 'one' and 'three') and
+(flags not between 'one' and 'one,two,three') and
+(date_field not between '1901-01-01' and '1903-03-03') and
+(year_field not between '1901' and '1903') and
+(time_field not between '01:01:01' and '03:03:03') and
+(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+auto
+4
+select auto from t1 where
+("aaaa" not between string and string) and
+("aaaa" not between vstring and vstring) and
+(0xAAAA not between bin and bin) and
+(0xAAAA not between vbin and vbin) and
+(-1 not between tiny and tiny) and
+(-1 not between short and short) and
+(-1 not between medium and medium) and
+(-1 not between long_int and long_int) and
+(-1 not between longlong and longlong) and
+(1 not between utiny and utiny) and
+(1 not between ushort and ushort) and
+(1 not between umedium and umedium) and
+(1 not between ulong and ulong) and
+(1 not between ulonglong and ulonglong) and
+(b'001' not between bits and bits) and
+('one' not between options and options) and
+('one' not between flags and flags) and
+('1901-01-01' not between date_field and date_field) and
+('1901' not between year_field and year_field) and
+('01:01:01' not between time_field and time_field) and
+('1901-01-01 01:01:01' not between date_time and date_time)
+order by auto;
+auto
+2
+3
+4
+select auto from t1 where
+string in("aaaa","cccc") and
+vstring in("aaaa","cccc") and
+bin in(0xAAAA,0xCCCC) and
+vbin in(0xAAAA,0xCCCC) and
+tiny in(-1,-3) and
+short in(-1,-3) and
+medium in(-1,-3) and
+long_int in(-1,-3) and
+longlong in(-1,-3) and
+utiny in(1,3) and
+ushort in(1,3) and
+umedium in(1,3) and
+ulong in(1,3) and
+ulonglong in(1,3) and
+bits in(b'001',b'011') and
+options in('one','three') and
+flags in('one','one,two,three') and
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+auto
+1
+3
+select auto from t1 where
+"aaaa" in(string) and
+"aaaa" in(vstring) and
+0xAAAA in(bin) and
+0xAAAA in(vbin) and
+(-1 in(tiny)) and
+(-1 in(short)) and
+(-1 in(medium)) and
+(-1 in(long_int)) and
+(-1 in(longlong)) and
+1 in(utiny) and
+1 in(ushort) and
+1 in(umedium) and
+1 in(ulong) and
+1 in(ulonglong) and
+b'001' in(bits) and
+'one' in(options) and
+'one' in(flags) and
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and
+'1901-01-01 01:01:01' in(date_time)
+order by auto;
+auto
+1
+select auto from t1 where
+string not in("aaaa","cccc") and
+vstring not in("aaaa","cccc") and
+bin not in(0xAAAA,0xCCCC) and
+vbin not in(0xAAAA,0xCCCC) and
+tiny not in(-1,-3) and
+short not in(-1,-3) and
+medium not in(-1,-3) and
+long_int not in(-1,-3) and
+longlong not in(-1,-3) and
+utiny not in(1,3) and
+ushort not in(1,3) and
+umedium not in(1,3) and
+ulong not in(1,3) and
+ulonglong not in(1,3) and
+bits not in(b'001',b'011') and
+options not in('one','three') and
+flags not in('one','one,two,three') and
+date_field not in('1901-01-01','1903-03-03') and
+year_field not in('1901','1903') and
+time_field not in('01:01:01','03:03:03') and
+date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+auto
+2
+4
+select auto from t1 where
+"aaaa" not in(string) and
+"aaaa" not in(vstring) and
+0xAAAA not in(bin) and
+0xAAAA not in(vbin) and
+(-1 not in(tiny)) and
+(-1 not in(short)) and
+(-1 not in(medium)) and
+(-1 not in(long_int)) and
+(-1 not in(longlong)) and
+1 not in(utiny) and
+1 not in(ushort) and
+1 not in(umedium) and
+1 not in(ulong) and
+1 not in(ulonglong) and
+b'001' not in(bits) and
+'one' not in(options) and
+'one' not in(flags) and
+'1901-01-01' not in(date_field) and
+'1901' not in(year_field) and
+'01:01:01' not in(time_field) and
+'1901-01-01 01:01:01' not in(date_time)
+order by auto;
+auto
+2
+3
+4
+select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
+pk1 attr1 attr2 attr3
+2 2 NULL NULL
+3 3 3 d
+select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
+pk1 attr1 attr2 attr3
+3 3 3 d
+4 4 4 e
+5 5 5 f
+select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
+pk1 attr1 attr2 attr3 attr4
+2 2 9223372036854775804 2 c
+4 4 9223372036854775806 4 e
+5 5 9223372036854775807 5 f
+select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
+pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3 attr4
+0 0 0 a 0 0 0 0 a
+select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
+pk1 attr1 attr2 attr3 attr4
+2 2 9223372036854775804 2 c
+4 4 9223372036854775806 4 e
+select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1;
+pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4
+2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c
+3 3 9223372036854775805 3 d 3 3 9223372036854775805 3 d
+4 4 9223372036854775806 4 e 4 4 9223372036854775806 4 e
+set engine_condition_pushdown = on;
+explain
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+auto
+1
+explain
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+/* bits != b'001' and */
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+/* bits != b'001' and */
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+auto
+2
+3
+4
+explain
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+/* bits > b'001' and */
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+/* bits > b'001' and */
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+auto
+2
+3
+4
+explain
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+/* bits >= b'001' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+/* bits >= b'001' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+auto
+1
+2
+3
+4
+explain
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+/* bits < b'100' and */
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+/* bits < b'100' and */
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+auto
+1
+2
+3
+explain
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 - 1 + 1 and /* Checking function composition */
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+/* bits <= b'100' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 - 1 + 1 and /* Checking function composition */
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+/* bits <= b'100' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+auto
+1
+2
+3
+4
+create index medium_index on t1(medium);
+explain
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref medium_index medium_index 3 const 10 Using where with pushed condition; Using filesort
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+auto
+1
+explain
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+/* bits != b'001' and */
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 20 Using where with pushed condition; Using filesort
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+/* bits != b'001' and */
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+auto
+2
+3
+4
+explain
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+/* bits > b'001' and */
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 10 Using where with pushed condition; Using filesort
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+/* bits > b'001' and */
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+auto
+2
+3
+4
+explain
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+/* bits >= b'001' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 10 Using where with pushed condition; Using filesort
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+/* bits >= b'001' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+auto
+1
+2
+3
+4
+explain
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+/* bits < b'100' and */
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 10 Using where with pushed condition; Using filesort
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+/* bits < b'100' and */
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+auto
+1
+2
+3
+explain
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 - 1 + 1 and /* Checking function composition */
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+/* bits <= b'100' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 10 Using where with pushed condition; Using filesort
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 - 1 + 1 and /* Checking function composition */
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+/* bits <= b'100' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+auto
+1
+2
+3
+4
+explain
+select auto from t1 where
+string like "b%" and
+vstring like "b%" and
+bin like concat(0xBB, '%') and
+vbin like concat(0xBB, '%')
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+string like "b%" and
+vstring like "b%" and
+bin like concat(0xBB, '%') and
+vbin like concat(0xBB, '%')
+order by auto;
+auto
+2
+explain
+select auto from t1 where
+string not like "b%" and
+vstring not like "b%" and
+bin not like concat(0xBB, '%') and
+vbin not like concat(0xBB, '%')
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+string not like "b%" and
+vstring not like "b%" and
+bin not like concat(0xBB, '%') and
+vbin not like concat(0xBB, '%')
+order by auto;
+auto
+1
+3
+4
+explain
+select auto from t1 where
+(string between "aaaa" and "cccc") and
+(vstring between "aaaa" and "cccc") and
+(bin between 0xAAAA and 0xCCCC) and
+(vbin between 0xAAAA and 0xCCCC) and
+(tiny between -3 and -1) and
+(short between -3 and -1) and
+(medium between -3 and -1) and
+(long_int between -3 and -1) and
+(longlong between -3 and -1) and
+(utiny between 1 and 3) and
+(ushort between 1 and 3) and
+(umedium between 1 and 3) and
+(ulong between 1 and 3) and
+(ulonglong between 1 and 3) and
+/* (bits between b'001' and b'011') and */
+(options between 'one' and 'three') and
+(flags between 'one' and 'one,two,three') and
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 10 Using where with pushed condition; Using filesort
+select auto from t1 where
+(string between "aaaa" and "cccc") and
+(vstring between "aaaa" and "cccc") and
+(bin between 0xAAAA and 0xCCCC) and
+(vbin between 0xAAAA and 0xCCCC) and
+(tiny between -3 and -1) and
+(short between -3 and -1) and
+(medium between -3 and -1) and
+(long_int between -3 and -1) and
+(longlong between -3 and -1) and
+(utiny between 1 and 3) and
+(ushort between 1 and 3) and
+(umedium between 1 and 3) and
+(ulong between 1 and 3) and
+(ulonglong between 1 and 3) and
+/* (bits between b'001' and b'011') and */
+(options between 'one' and 'three') and
+(flags between 'one' and 'one,two,three') and
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+auto
+1
+3
+explain
+select auto from t1 where
+("aaaa" between string and string) and
+("aaaa" between vstring and vstring) and
+(0xAAAA between bin and bin) and
+(0xAAAA between vbin and vbin) and
+(-1 between tiny and tiny) and
+(-1 between short and short) and
+(-1 between medium and medium) and
+(-1 between long_int and long_int) and
+(-1 between longlong and longlong) and
+(1 between utiny and utiny) and
+(1 between ushort and ushort) and
+(1 between umedium and umedium) and
+(1 between ulong and ulong) and
+(1 between ulonglong and ulonglong) and
+/* (b'001' between bits and bits) and */
+('one' between options and options) and
+('one' between flags and flags) and
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and
+('1901-01-01 01:01:01' between date_time and date_time)
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+("aaaa" between string and string) and
+("aaaa" between vstring and vstring) and
+(0xAAAA between bin and bin) and
+(0xAAAA between vbin and vbin) and
+(-1 between tiny and tiny) and
+(-1 between short and short) and
+(-1 between medium and medium) and
+(-1 between long_int and long_int) and
+(-1 between longlong and longlong) and
+(1 between utiny and utiny) and
+(1 between ushort and ushort) and
+(1 between umedium and umedium) and
+(1 between ulong and ulong) and
+(1 between ulonglong and ulonglong) and
+/* (b'001' between bits and bits) and */
+('one' between options and options) and
+('one' between flags and flags) and
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and
+('1901-01-01 01:01:01' between date_time and date_time)
+order by auto;
+auto
+1
+explain
+select auto from t1 where
+(string not between "aaaa" and "cccc") and
+(vstring not between "aaaa" and "cccc") and
+(bin not between 0xAAAA and 0xCCCC) and
+(vbin not between 0xAAAA and 0xCCCC) and
+(tiny not between -3 and -1) and
+(short not between -3 and -1) and
+(medium not between -3 and -1) and
+(long_int not between -3 and -1) and
+(longlong not between -3 and -1) and
+(utiny not between 1 and 3) and
+(ushort not between 1 and 3) and
+(umedium not between 1 and 3) and
+(ulong not between 1 and 3) and
+(ulonglong not between 1 and 3) and
+/* (bits not between b'001' and b'011') and */
+(options not between 'one' and 'three') and
+(flags not between 'one' and 'one,two,three') and
+(date_field not between '1901-01-01' and '1903-03-03') and
+(year_field not between '1901' and '1903') and
+(time_field not between '01:01:01' and '03:03:03') and
+(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 20 Using where with pushed condition; Using filesort
+select auto from t1 where
+(string not between "aaaa" and "cccc") and
+(vstring not between "aaaa" and "cccc") and
+(bin not between 0xAAAA and 0xCCCC) and
+(vbin not between 0xAAAA and 0xCCCC) and
+(tiny not between -3 and -1) and
+(short not between -3 and -1) and
+(medium not between -3 and -1) and
+(long_int not between -3 and -1) and
+(longlong not between -3 and -1) and
+(utiny not between 1 and 3) and
+(ushort not between 1 and 3) and
+(umedium not between 1 and 3) and
+(ulong not between 1 and 3) and
+(ulonglong not between 1 and 3) and
+/* (bits not between b'001' and b'011') and */
+(options not between 'one' and 'three') and
+(flags not between 'one' and 'one,two,three') and
+(date_field not between '1901-01-01' and '1903-03-03') and
+(year_field not between '1901' and '1903') and
+(time_field not between '01:01:01' and '03:03:03') and
+(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+auto
+4
+explain
+select auto from t1 where
+("aaaa" not between string and string) and
+("aaaa" not between vstring and vstring) and
+(0xAAAA not between bin and bin) and
+(0xAAAA not between vbin and vbin) and
+(-1 not between tiny and tiny) and
+(-1 not between short and short) and
+(-1 not between medium and medium) and
+(-1 not between long_int and long_int) and
+(-1 not between longlong and longlong) and
+(1 not between utiny and utiny) and
+(1 not between ushort and ushort) and
+(1 not between umedium and umedium) and
+(1 not between ulong and ulong) and
+(1 not between ulonglong and ulonglong) and
+/* (b'001' not between bits and bits) and */
+('one' not between options and options) and
+('one' not between flags and flags) and
+('1901-01-01' not between date_field and date_field) and
+('1901' not between year_field and year_field) and
+('01:01:01' not between time_field and time_field) and
+('1901-01-01 01:01:01' not between date_time and date_time)
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+("aaaa" not between string and string) and
+("aaaa" not between vstring and vstring) and
+(0xAAAA not between bin and bin) and
+(0xAAAA not between vbin and vbin) and
+(-1 not between tiny and tiny) and
+(-1 not between short and short) and
+(-1 not between medium and medium) and
+(-1 not between long_int and long_int) and
+(-1 not between longlong and longlong) and
+(1 not between utiny and utiny) and
+(1 not between ushort and ushort) and
+(1 not between umedium and umedium) and
+(1 not between ulong and ulong) and
+(1 not between ulonglong and ulonglong) and
+/* (b'001' not between bits and bits) and */
+('one' not between options and options) and
+('one' not between flags and flags) and
+('1901-01-01' not between date_field and date_field) and
+('1901' not between year_field and year_field) and
+('01:01:01' not between time_field and time_field) and
+('1901-01-01 01:01:01' not between date_time and date_time)
+order by auto;
+auto
+2
+3
+4
+explain
+select auto from t1 where
+string in("aaaa","cccc") and
+vstring in("aaaa","cccc") and
+bin in(0xAAAA,0xCCCC) and
+vbin in(0xAAAA,0xCCCC) and
+tiny in(-1,-3) and
+short in(-1,-3) and
+medium in(-1,-3) and
+long_int in(-1,-3) and
+longlong in(-1,-3) and
+utiny in(1,3) and
+ushort in(1,3) and
+umedium in(1,3) and
+ulong in(1,3) and
+ulonglong in(1,3) and
+/* bits in(b'001',b'011') and */
+options in('one','three') and
+flags in('one','one,two,three') and
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 20 Using where with pushed condition; Using filesort
+select auto from t1 where
+string in("aaaa","cccc") and
+vstring in("aaaa","cccc") and
+bin in(0xAAAA,0xCCCC) and
+vbin in(0xAAAA,0xCCCC) and
+tiny in(-1,-3) and
+short in(-1,-3) and
+medium in(-1,-3) and
+long_int in(-1,-3) and
+longlong in(-1,-3) and
+utiny in(1,3) and
+ushort in(1,3) and
+umedium in(1,3) and
+ulong in(1,3) and
+ulonglong in(1,3) and
+/* bits in(b'001',b'011') and */
+options in('one','three') and
+flags in('one','one,two,three') and
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+auto
+1
+3
+explain
+select auto from t1 where
+"aaaa" in(string) and
+"aaaa" in(vstring) and
+0xAAAA in(bin) and
+0xAAAA in(vbin) and
+(-1 in(tiny)) and
+(-1 in (short)) and
+(-1 in(medium)) and
+(-1 in(long_int)) and
+(-1 in(longlong)) and
+1 in(utiny) and
+1 in(ushort) and
+1 in(umedium) and
+1 in(ulong) and
+1 in(ulonglong) and
+/* b'001' in(bits) and */
+'one' in(options) and
+'one' in(flags) and
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and
+'1901-01-01 01:01:01' in(date_time)
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref medium_index medium_index 3 const 10 Using where with pushed condition; Using filesort
+select auto from t1 where
+"aaaa" in(string) and
+"aaaa" in(vstring) and
+0xAAAA in(bin) and
+0xAAAA in(vbin) and
+(-1 in(tiny)) and
+(-1 in (short)) and
+(-1 in(medium)) and
+(-1 in(long_int)) and
+(-1 in(longlong)) and
+1 in(utiny) and
+1 in(ushort) and
+1 in(umedium) and
+1 in(ulong) and
+1 in(ulonglong) and
+/* b'001' in(bits) and */
+'one' in(options) and
+'one' in(flags) and
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and
+'1901-01-01 01:01:01' in(date_time)
+order by auto;
+auto
+1
+explain
+select auto from t1 where
+string not in("aaaa","cccc") and
+vstring not in("aaaa","cccc") and
+bin not in(0xAAAA,0xCCCC) and
+vbin not in(0xAAAA,0xCCCC) and
+tiny not in(-1,-3) and
+short not in(-1,-3) and
+medium not in(-1,-3) and
+long_int not in(-1,-3) and
+longlong not in(-1,-3) and
+utiny not in(1,3) and
+ushort not in(1,3) and
+umedium not in(1,3) and
+ulong not in(1,3) and
+ulonglong not in(1,3) and
+/* bits not in(b'001',b'011') and */
+options not in('one','three') and
+flags not in('one','one,two,three') and
+date_field not in('1901-01-01','1903-03-03') and
+year_field not in('1901','1903') and
+time_field not in('01:01:01','03:03:03') and
+date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range medium_index medium_index 3 NULL 30 Using where with pushed condition; Using filesort
+select auto from t1 where
+string not in("aaaa","cccc") and
+vstring not in("aaaa","cccc") and
+bin not in(0xAAAA,0xCCCC) and
+vbin not in(0xAAAA,0xCCCC) and
+tiny not in(-1,-3) and
+short not in(-1,-3) and
+medium not in(-1,-3) and
+long_int not in(-1,-3) and
+longlong not in(-1,-3) and
+utiny not in(1,3) and
+ushort not in(1,3) and
+umedium not in(1,3) and
+ulong not in(1,3) and
+ulonglong not in(1,3) and
+/* bits not in(b'001',b'011') and */
+options not in('one','three') and
+flags not in('one','one,two,three') and
+date_field not in('1901-01-01','1903-03-03') and
+year_field not in('1901','1903') and
+time_field not in('01:01:01','03:03:03') and
+date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+auto
+2
+4
+explain
+select auto from t1 where
+"aaaa" not in(string) and
+"aaaa" not in(vstring) and
+0xAAAA not in(bin) and
+0xAAAA not in(vbin) and
+(-1 not in(tiny)) and
+(-1 not in(short)) and
+(-1 not in(medium)) and
+(-1 not in(long_int)) and
+(-1 not in(longlong)) and
+1 not in(utiny) and
+1 not in(ushort) and
+1 not in(umedium) and
+1 not in(ulong) and
+1 not in(ulonglong) and
+/* b'001' not in(bits) and */
+'one' not in(options) and
+'one' not in(flags) and
+'1901-01-01' not in(date_field) and
+'1901' not in(year_field) and
+'01:01:01' not in(time_field) and
+'1901-01-01 01:01:01' not in(date_time)
+order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
+select auto from t1 where
+"aaaa" not in(string) and
+"aaaa" not in(vstring) and
+0xAAAA not in(bin) and
+0xAAAA not in(vbin) and
+(-1 not in(tiny)) and
+(-1 not in(short)) and
+(-1 not in(medium)) and
+(-1 not in(long_int)) and
+(-1 not in(longlong)) and
+1 not in(utiny) and
+1 not in(ushort) and
+1 not in(umedium) and
+1 not in(ulong) and
+1 not in(ulonglong) and
+/* b'001' not in(bits) and */
+'one' not in(options) and
+'one' not in(flags) and
+'1901-01-01' not in(date_field) and
+'1901' not in(year_field) and
+'01:01:01' not in(time_field) and
+'1901-01-01 01:01:01' not in(date_time)
+order by auto;
+auto
+2
+3
+4
+update t1
+set medium = 17
+where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01';
+delete from t1
+where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = 17 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01';
+select count(*) from t1;
+count(*)
+3
+explain
+select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 6 Using where with pushed condition; Using filesort
+select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
+pk1 attr1 attr2 attr3
+2 2 NULL NULL
+3 3 3 d
+explain
+select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where with pushed condition; Using filesort
+select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
+pk1 attr1 attr2 attr3
+3 3 3 d
+4 4 4 e
+5 5 5 f
+explain
+select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 6 Using where with pushed condition; Using filesort
+select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
+pk1 attr1 attr2 attr3 attr4
+2 2 9223372036854775804 2 c
+4 4 9223372036854775806 4 e
+5 5 9223372036854775807 5 f
+explain
+select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where with pushed condition; Using temporary; Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 6 Using where with pushed condition
+select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
+pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3 attr4
+0 0 0 a 0 0 0 0 a
+explain
+select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 range attr1 attr1 4 NULL 10 Using where with pushed condition; Using filesort
+select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
+pk1 attr1 attr2 attr3 attr4
+2 2 9223372036854775804 2 c
+4 4 9223372036854775806 4 e
+explain
+select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 range attr1 attr1 4 NULL 10 Using where with pushed condition; Using temporary; Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 6 Using where
+select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1;
+pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4
+2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c
+3 3 9223372036854775805 3 d 3 3 9223372036854775805 3 d
+4 4 9223372036854775806 4 e 4 4 9223372036854775806 4 e
+explain
+select auto from t1 where string = "aaaa" collate latin1_general_ci order by auto;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+explain
+select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where; Using filesort
+explain
+select * from t3 left join t4 on t4.attr2 = t3.attr2 where t4.attr1 > 1 and t4.attr3 < 5 or t4.attr1 is null order by t4.pk1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
+1 SIMPLE t4 ALL NULL NULL NULL NULL 6 Using where
+set engine_condition_pushdown = @old_ecpd;
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/r/ndb_config.result b/mysql-test/r/ndb_config.result
index f720b8e98df..c2557f85c0b 100644
--- a/mysql-test/r/ndb_config.result
+++ b/mysql-test/r/ndb_config.result
@@ -1,4 +1,4 @@
-ndbd,1,localhost ndbd,2,localhost ndb_mgmd,3, mysqld,4, mysqld,5, mysqld,6, mysqld,7,
+ndbd,1,localhost ndbd,2,localhost ndb_mgmd,3,localhost mysqld,4, mysqld,5, mysqld,6, mysqld,7,
1,localhost,41943040,12582912 2,localhost,41943040,12582912
1 localhost 41943040 12582912
2 localhost 41943040 12582912
diff --git a/mysql-test/r/ndb_default_cluster.require b/mysql-test/r/ndb_default_cluster.require
new file mode 100644
index 00000000000..aa4988cdca3
--- /dev/null
+++ b/mysql-test/r/ndb_default_cluster.require
@@ -0,0 +1,2 @@
+Variable_name Value
+Ndb_connected_host localhost
diff --git a/mysql-test/r/ndb_grant.result b/mysql-test/r/ndb_grant.result
index 6583065a0c4..6192a7cace5 100644
--- a/mysql-test/r/ndb_grant.result
+++ b/mysql-test/r/ndb_grant.result
@@ -31,8 +31,8 @@ begin;
grant delete on mysqltest.* to mysqltest_1@localhost;
commit;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
@@ -99,7 +99,7 @@ commit;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
begin;
revoke all privileges on mysqltest.* from mysqltest_1@localhost;
commit;
@@ -271,23 +271,26 @@ grant select on test.t1 to drop_user2@localhost;
grant select on test.* to drop_user3@localhost;
grant select on *.* to drop_user4@localhost;
commit;
+flush privileges;
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
-ERROR HY000: Can't drop one or more of the requested users
begin;
revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
drop_user3@localhost, drop_user4@localhost;
+ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
commit;
+flush privileges;
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
drop table t1;
begin;
grant usage on *.* to mysqltest_1@localhost identified by "password";
-grant select, update, insert on test.* to mysqltest@localhost;
+grant select, update, insert on test.* to mysqltest_1@localhost;
commit;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'
+GRANT SELECT, INSERT, UPDATE ON `test`.* TO 'mysqltest_1'@'localhost'
drop user mysqltest_1@localhost;
SET NAMES koi8r;
CREATE DATABASE ÂÄ;
@@ -396,6 +399,31 @@ DROP DATABASE testdb7;
DROP DATABASE testdb8;
DROP DATABASE testdb9;
DROP DATABASE testdb10;
+SHOW PRIVILEGES;
+Privilege Context Comment
+Alter Tables To alter the table
+Create Databases,Tables,Indexes To create new databases and tables
+Create temporary tables Databases To use CREATE TEMPORARY TABLE
+Create view Tables To create new views
+Delete Tables To delete existing rows
+Drop Databases,Tables To drop databases, tables, and views
+File File access on server To read and write files on the server
+Grant option Databases,Tables To give to other users those privileges you possess
+Index Tables To create or drop indexes
+Insert Tables To insert data into tables
+Lock tables Databases To use LOCK TABLES (together with SELECT privilege)
+Process Server Admin To view the plain text of currently executing queries
+References Databases,Tables To have references on tables
+Reload Server Admin To reload or refresh tables, logs and privileges
+Replication client Server Admin To ask where the slave or master servers are
+Replication slave Server Admin To read binary log events from the master
+Select Tables To retrieve rows from table
+Show databases Server Admin To see all databases with SHOW DATABASES
+Show view Tables To see views with SHOW CREATE VIEW
+Shutdown Server Admin To shut down the server
+Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
+Update Tables To update existing rows
+Usage Server Admin No privileges - allow connect only
use mysql;
alter table columns_priv engine=myisam;
alter table db engine=myisam;
diff --git a/mysql-test/r/ndb_index_ordered.result b/mysql-test/r/ndb_index_ordered.result
index f5794d477f3..36bac7b0f9d 100644
--- a/mysql-test/r/ndb_index_ordered.result
+++ b/mysql-test/r/ndb_index_ordered.result
@@ -275,6 +275,115 @@ a b c
1 1 1
4 4 NULL
drop table t1;
+create table t1 (
+a int unsigned primary key,
+b int unsigned,
+c char(10),
+key bc (b, c)
+) engine=ndb;
+insert into t1 values(1,1,'a'),(2,2,'b'),(3,3,'c'),(4,4,'d'),(5,5,'e');
+insert into t1 select a*7,10*b,'f' from t1;
+insert into t1 select a*13,10*b,'g' from t1;
+insert into t1 select a*17,10*b,'h' from t1;
+insert into t1 select a*19,10*b,'i' from t1;
+insert into t1 select a*23,10*b,'j' from t1;
+insert into t1 select a*29,10*b,'k' from t1;
+select b, c from t1 where b <= 10 and c <'f' order by b, c;
+b c
+1 a
+2 b
+3 c
+4 d
+5 e
+select b, c from t1 where b <= 10 and c <'f' order by b desc, c desc;
+b c
+5 e
+4 d
+3 c
+2 b
+1 a
+select b, c from t1 where b=4000 and c<'k' order by b, c;
+b c
+4000 h
+4000 i
+4000 i
+4000 i
+4000 j
+4000 j
+4000 j
+4000 j
+4000 j
+4000 j
+select b, c from t1 where b=4000 and c<'k' order by b desc, c desc;
+b c
+4000 j
+4000 j
+4000 j
+4000 j
+4000 j
+4000 j
+4000 i
+4000 i
+4000 i
+4000 h
+select b, c from t1 where 1000<=b and b<=100000 and c<'j' order by b, c;
+b c
+1000 h
+1000 i
+1000 i
+1000 i
+2000 h
+2000 i
+2000 i
+2000 i
+3000 h
+3000 i
+3000 i
+3000 i
+4000 h
+4000 i
+4000 i
+4000 i
+5000 h
+5000 i
+5000 i
+5000 i
+10000 i
+20000 i
+30000 i
+40000 i
+50000 i
+select b, c from t1 where 1000<=b and b<=100000 and c<'j' order by b desc, c desc;
+b c
+50000 i
+40000 i
+30000 i
+20000 i
+10000 i
+5000 i
+5000 i
+5000 i
+5000 h
+4000 i
+4000 i
+4000 i
+4000 h
+3000 i
+3000 i
+3000 i
+3000 h
+2000 i
+2000 i
+2000 i
+2000 h
+1000 i
+1000 i
+1000 i
+1000 h
+select min(b), max(b) from t1;
+min(b) max(b)
+1 5000000
+drop table t1;
CREATE TABLE test1 (
SubscrID int(11) NOT NULL auto_increment,
UsrID int(11) NOT NULL default '0',
@@ -543,3 +652,9 @@ show tables;
Tables_in_test
t1
drop table t1;
+create table t1 (a int, c varchar(10),
+primary key using hash (a), index(c)) engine=ndb;
+insert into t1 (a, c) values (1,'aaa'),(3,'bbb');
+select count(*) from t1 where c<'bbb';
+count(*)
+1
diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result
index 598b9dcccf7..1401ae26ddb 100644
--- a/mysql-test/r/ndb_index_unique.result
+++ b/mysql-test/r/ndb_index_unique.result
@@ -1,4 +1,4 @@
-drop table if exists t1, t2, t3, t4, t5, t6, t7;
+drop table if exists t1, t2, t3, t4, t5, t6, t7, t8;
CREATE TABLE t1 (
a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null,
@@ -248,8 +248,8 @@ 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',
+rid bigint(20) unsigned NOT NULL,
+cid bigint(20) unsigned NOT NULL,
UNIQUE KEY m (uid,gid,rid,cid)
) engine=ndbcluster;
INSERT INTO t4 VALUES (1,1,2,4);
@@ -275,8 +275,8 @@ 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',
+rid bigint(20) unsigned NOT NULL,
+cid bigint(20) unsigned NOT NULL,
UNIQUE KEY m (uid,gid,rid,cid)
) engine=ndbcluster;
INSERT INTO t7 VALUES(1, 1, 1, 1, 1);
diff --git a/mysql-test/r/ndb_read_multi_range.result b/mysql-test/r/ndb_read_multi_range.result
new file mode 100644
index 00000000000..f42ac394b6c
--- /dev/null
+++ b/mysql-test/r/ndb_read_multi_range.result
@@ -0,0 +1,265 @@
+DROP TABLE IF EXISTS t1, r1;
+create table t1 (
+a int primary key,
+b int not null,
+c int not null,
+index(b), unique index using hash(c)
+) engine = ndb;
+insert into t1 values
+(1,2,1),(2,3,2),(3,4,3),(4,5,4),
+(5,2,12),(6,3,11),(7,4,10),(8,5,9),
+(9,2,8),(10,3,7),(11,4,6),(12,5,5);
+create table r1 as select * from t1 where a in (2,8,12);
+select * from r1 order by a;
+a b c
+2 3 2
+8 5 9
+12 5 5
+drop table r1;
+create table r1 as select * from t1 where b in (1,2,5);
+select * from r1 order by a;
+a b c
+1 2 1
+4 5 4
+5 2 12
+8 5 9
+9 2 8
+12 5 5
+drop table r1;
+create table r1 as select * from t1 where c in (2,8,12);
+select * from r1 order by a;
+a b c
+2 3 2
+5 2 12
+9 2 8
+drop table r1;
+create table r1 as select * from t1 where a in (2,8) or (a > 11) or (a <= 1);
+select * from r1 order by a;
+a b c
+1 2 1
+2 3 2
+8 5 9
+12 5 5
+drop table r1;
+create table r1 as select * from t1 where a in (33,8,12);
+select * from r1 order by a;
+a b c
+8 5 9
+12 5 5
+drop table r1;
+create table r1 as select * from t1 where a in (2,33,8,12,34);
+select * from r1 order by a;
+a b c
+2 3 2
+8 5 9
+12 5 5
+drop table r1;
+create table r1 as select * from t1 where b in (1,33,5);
+select * from r1 order by a;
+a b c
+4 5 4
+8 5 9
+12 5 5
+drop table r1;
+select * from t1 where b in (1,33,5) order by a;
+a b c
+4 5 4
+8 5 9
+12 5 5
+create table r1 as select * from t1 where b in (45,1,33,5,44);
+select * from r1 order by a;
+a b c
+4 5 4
+8 5 9
+12 5 5
+drop table r1;
+select * from t1 where b in (45,22) order by a;
+a b c
+create table r1 as select * from t1 where c in (2,8,33);
+select * from r1 order by a;
+a b c
+2 3 2
+9 2 8
+drop table r1;
+create table r1 as select * from t1 where c in (13,2,8,33,12);
+select * from r1 order by a;
+a b c
+2 3 2
+5 2 12
+9 2 8
+drop table r1;
+select * from t1 where a in (33,8,12) order by a;
+a b c
+8 5 9
+12 5 5
+select * from t1 where a in (33,34,35) order by a;
+a b c
+select * from t1 where a in (2,8) or (a > 11) or (a <= 1) order by a;
+a b c
+1 2 1
+2 3 2
+8 5 9
+12 5 5
+select * from t1 where b in (6,7) or (b <= 5) or (b >= 10) order by b,a;
+a b c
+1 2 1
+5 2 12
+9 2 8
+2 3 2
+6 3 11
+10 3 7
+3 4 3
+7 4 10
+11 4 6
+4 5 4
+8 5 9
+12 5 5
+select * from t1 where c in (13,2,8,33,12) order by c,a;
+a b c
+2 3 2
+9 2 8
+5 2 12
+drop table t1;
+create table t1 (
+a int not null,
+b int not null,
+c int not null,
+d int not null,
+e int not null,
+primary key (a,b,c,d), index (d)
+) engine = ndb;
+insert into t1 values
+(1,2,1,1,1),(2,3,2,3,1),(3,4,3,1,1),(4,5,4,7,1),
+(5,2,12,12,1),(6,3,11,1,1),(7,4,10,3,1),(8,5,9,5,1),
+(9,2,8,6,1),(10,3,7,5,1),(11,4,6,3,1),(12,5,5,2,1),
+(1,2,1,2,1),
+(1,2,1,3,1),
+(1,2,1,4,1),
+(1,2,1,5,1);
+create table r1 as select * from t1
+where a=1 and b=2 and c=1 and d in (1,4,3,2);
+select * from r1 order by a,b,c,d;
+a b c d e
+1 2 1 1 1
+1 2 1 2 1
+1 2 1 3 1
+1 2 1 4 1
+drop table r1;
+update t1 set e = 100
+where d in (12,6,7);
+select * from t1 where d in (12,6,7) order by a,b,c,d;
+a b c d e
+4 5 4 7 100
+5 2 12 12 100
+9 2 8 6 100
+select * from t1 where d not in (12,6,7) and e = 100;
+a b c d e
+update t1
+set e = 101
+where a=1 and
+b=2 and
+c=1 and
+d in (1,4,3,2);
+select *
+from t1
+where a=1 and b=2 and c=1 and d in (1,4,3,2)
+order by a,b,c,d;
+a b c d e
+1 2 1 1 101
+1 2 1 2 101
+1 2 1 3 101
+1 2 1 4 101
+select *
+from t1
+where not (a=1 and b=2 and c=1 and d in (1,4,3,2))
+and e=101;
+a b c d e
+update t1
+set e =
+(case d
+when 12 then 112
+when 6 then 106
+when 7 then 107
+end)
+where d in (12,6,7);
+select * from t1 where d in (12,6,7) order by a,b,c,d;
+a b c d e
+4 5 4 7 107
+5 2 12 12 112
+9 2 8 6 106
+update t1
+set e =
+(case d
+when 1 then 111
+when 4 then 444
+when 3 then 333
+when 2 then 222
+end)
+where a=1 and
+b=2 and
+c=1 and
+d in (1,4,3,2);
+select *
+from t1
+where a=1 and b=2 and c=1 and d in (1,4,3,2)
+order by a,b,c,d;
+a b c d e
+1 2 1 1 111
+1 2 1 2 222
+1 2 1 3 333
+1 2 1 4 444
+delete from t1 where d in (12,6,7);
+select * from t1 where d in (12,6,7);
+a b c d e
+drop table t1;
+create table t1 (
+a int not null primary key,
+b int,
+c int,
+d int,
+unique index (b),
+index(c)
+) engine = ndb;
+insert into t1 values
+(1,null,1,1),
+(2,2,2,2),
+(3,null,null,3),
+(4,4,null,4),
+(5,null,5,null),
+(6,6,6,null),
+(7,null,null,null),
+(8,8,null,null),
+(9,null,9,9),
+(10,10,10,10),
+(11,null,null,11),
+(12,12,null,12),
+(13,null,13,null),
+(14,14,14,null),
+(15,null,null,null),
+(16,16,null,null);
+create table t2 as select * from t1 where a in (5,6,7,8,9,10);
+select * from t2 order by a;
+a b c d
+5 NULL 5 NULL
+6 6 6 NULL
+7 NULL NULL NULL
+8 8 NULL NULL
+9 NULL 9 9
+10 10 10 10
+drop table t2;
+create table t2 as select * from t1 where b in (5,6,7,8,9,10);
+select * from t2 order by a;
+a b c d
+6 6 6 NULL
+8 8 NULL NULL
+10 10 10 10
+drop table t2;
+create table t2 as select * from t1 where c in (5,6,7,8,9,10);
+select * from t2 order by a;
+a b c d
+5 NULL 5 NULL
+6 6 6 NULL
+9 NULL 9 9
+10 10 10 10
+drop table t2;
+drop table t1;
diff --git a/mysql-test/r/ndb_subquery.result b/mysql-test/r/ndb_subquery.result
index f65f09b71b3..b19571b05c1 100644
--- a/mysql-test/r/ndb_subquery.result
+++ b/mysql-test/r/ndb_subquery.result
@@ -40,3 +40,22 @@ p u o
5 5 5
drop table t1;
drop table t2;
+create table t1 (p int not null primary key, u int not null) engine=ndb;
+insert into t1 values (1,1),(2,2),(3,3);
+create table t2 as
+select t1.*
+from t1 as t1, t1 as t2, t1 as t3, t1 as t4, t1 as t5, t1 as t6, t1 as t7, t1 as t8
+where t1.u = t2.u
+and t2.u = t3.u
+and t3.u = t4.u
+and t4.u = t5.u
+and t5.u = t6.u
+and t6.u = t7.u
+and t7.u = t8.u;
+select * from t2 order by 1;
+p u
+1 1
+2 2
+3 3
+drop table t1;
+drop table t2;
diff --git a/mysql-test/r/ndb_types.result b/mysql-test/r/ndb_types.result
index 5afa9c57e38..37ce7732f65 100644
--- a/mysql-test/r/ndb_types.result
+++ b/mysql-test/r/ndb_types.result
@@ -12,11 +12,13 @@ long_int int(11) DEFAULT '0' NOT NULL,
longlong bigint(13) DEFAULT '0' NOT NULL,
real_float float(13,1) DEFAULT 0.0 NOT NULL,
real_double double(16,4),
+real_decimal decimal(16,4),
utiny tinyint(3) unsigned DEFAULT '0' NOT NULL,
ushort smallint(5) unsigned zerofill DEFAULT '00000' NOT NULL,
umedium mediumint(8) unsigned DEFAULT '0' NOT NULL,
ulong int(11) unsigned DEFAULT '0' NOT NULL,
ulonglong bigint(13) unsigned DEFAULT '0' NOT NULL,
+bits bit(3),
options enum('one','two','tree') not null,
flags set('one','two','tree') not null,
date_field date,
@@ -40,32 +42,33 @@ KEY (options,flags)
set @now = now();
insert into t1
(string,vstring,bin,vbin,tiny,short,medium,long_int,longlong,
-real_float,real_double, utiny, ushort, umedium,ulong,ulonglong,
-options,flags,date_field,year_field,time_field,date_time)
+real_float,real_double, real_decimal,utiny, ushort, umedium,ulong,ulonglong,
+bits,options,flags,date_field,year_field,time_field,date_time)
values
-("aaaa","aaaa",0xAAAA,0xAAAA,-1,-1,-1,-1,-1,1.1,1.1,1,1,1,1,1,
-'one','one', '1901-01-01','1901','01:01:01','1901-01-01 01:01:01');
+("aaaa","aaaa",0xAAAA,0xAAAA,-1,-1,-1,-1,-1,1.1,1.1,1.1,1,1,1,1,1,
+b'001','one','one', '1901-01-01','1901','01:01:01','1901-01-01 01:01:01');
select auto,string,vstring,bin,vbin,tiny,short,medium,long_int,longlong,
-real_float,real_double, utiny, ushort, umedium,ulong,ulonglong,
-options,flags,date_field,year_field,time_field,date_time
+real_float,real_double,real_decimal,utiny,ushort,umedium,ulong,ulonglong,
+bits,options,flags,date_field,year_field,time_field,date_time
from t1;
-auto string vstring bin vbin tiny short medium long_int longlong real_float real_double utiny ushort umedium ulong ulonglong options flags date_field year_field time_field date_time
-1 aaaa aaaa ªª ªª -1 -1 -1 -1 -1 1.1 1.1000 1 00001 1 1 1 one one 1901-01-01 1901 01:01:01 1901-01-01 01:01:01
+auto string vstring bin vbin tiny short medium long_int longlong real_float real_double real_decimal utiny ushort umedium ulong ulonglong bits options flags date_field year_field time_field date_time
+1 aaaa aaaa ªª ªª -1 -1 -1 -1 -1 1.1 1.1000 1.1000 1 00001 1 1 1  one one 1901-01-01 1901 01:01:01 1901-01-01 01:01:01
select time_stamp>@now from t1;
time_stamp>@now
1
set @now = now();
update t1 set string="bbbb",vstring="bbbb",bin=0xBBBB,vbin=0xBBBB,
tiny=-2,short=-2,medium=-2,long_int=-2,longlong=-2,real_float=2.2,
-real_double=2.2,utiny=2,ushort=2,umedium=2,ulong=2,ulonglong=2,
+real_double=2.2,real_decimal=2.2,utiny=2,ushort=2,umedium=2,ulong=2,
+ulonglong=2, bits=b'010',
options='one',flags='one', date_field='1902-02-02',year_field='1902',
time_field='02:02:02',date_time='1902-02-02 02:02:02' where auto=1;
select auto,string,vstring,bin,vbin,tiny,short,medium,long_int,longlong,
-real_float,real_double, utiny, ushort, umedium,ulong,ulonglong,
-options,flags,date_field,year_field,time_field,date_time
+real_float,real_double,real_decimal,utiny,ushort,umedium,ulong,ulonglong,
+bits,options,flags,date_field,year_field,time_field,date_time
from t1;
-auto string vstring bin vbin tiny short medium long_int longlong real_float real_double utiny ushort umedium ulong ulonglong options flags date_field year_field time_field date_time
-1 bbbb bbbb »» »» -2 -2 -2 -2 -2 2.2 2.2000 2 00002 2 2 2 one one 1902-02-02 1902 02:02:02 1902-02-02 02:02:02
+auto string vstring bin vbin tiny short medium long_int longlong real_float real_double real_decimal utiny ushort umedium ulong ulonglong bits options flags date_field year_field time_field date_time
+1 bbbb bbbb »» »» -2 -2 -2 -2 -2 2.2 2.2000 2.2000 2 00002 2 2 2  one one 1902-02-02 1902 02:02:02 1902-02-02 02:02:02
select time_stamp>@now from t1;
time_stamp>@now
1
diff --git a/mysql-test/r/negation_elimination.result b/mysql-test/r/negation_elimination.result
index 9193a125cd1..a7dbe0d9052 100644
--- a/mysql-test/r/negation_elimination.result
+++ b/mysql-test/r/negation_elimination.result
@@ -387,5 +387,5 @@ explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like "
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 5 NULL 5 Using where; Using index
Warnings:
-Note 1003 select test.t1.a AS `a`,(test.t1.a <> 0) AS `not(not(a))`,((test.t1.a > 2) or test.t1.a) AS `not(a <= 2 and not(a))`,(test.t1.a like _latin1'1') AS `not(a not like "1")`,(test.t1.a in (1,2)) AS `not (a not in (1,2))`,(test.t1.a = 2) AS `not(a != 2)` from test.t1 where test.t1.a having test.t1.a
+Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or `test`.`t1`.`a`) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like _latin1'1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where `test`.`t1`.`a` having `test`.`t1`.`a`
drop table t1;
diff --git a/mysql-test/r/not_embedded_server.result b/mysql-test/r/not_embedded_server.result
index 082ebe72ba4..e471b5a3afa 100644
--- a/mysql-test/r/not_embedded_server.result
+++ b/mysql-test/r/not_embedded_server.result
@@ -1,5 +1,5 @@
prepare stmt1 from ' show full processlist ';
execute stmt1;
Id User Host db Command Time State Info
-number root localhost test Execute time NULL show full processlist
+number root localhost test Query time NULL show full processlist
deallocate prepare stmt1;
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 3e233eb512a..1425b2a7f89 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -88,7 +88,7 @@ b ifnull(t2.b,"this is null")
NULL this is null
NULL this is null
drop table t1;
-CREATE TABLE t1 (a varchar(16) NOT NULL, b smallint(6) NOT NULL, c datetime NOT NULL, d smallint(6) NOT NULL);
+CREATE TABLE t1 (a varchar(16) NOT NULL default '', b smallint(6) NOT NULL default 0, c datetime NOT NULL default '0000-00-00 00:00:00', d smallint(6) NOT NULL default 0);
INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55";
Warnings:
Warning 1265 Data truncated for column 'd' at row 1
@@ -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 Column set to default value; 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 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Column set to default value; 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 Column set to default value; NULL supplied to NOT NULL column 'b' at row 1
+Warning 1263 Column set to default value; 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 Column set to default value; NULL supplied to NOT NULL column 'c' at row 1
+Warning 1263 Column set to default value; 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 Column set to default value; NULL supplied to NOT NULL column 'd' at row 1
+Warning 1263 Column set to default value; 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
@@ -167,13 +167,22 @@ insert into t1 select i*2 from t1;
insert into t1 select i*2 from t1;
insert into t1 select i*2 from t1;
insert into t1 select i*2 from t1;
+insert into t1 values(null);
explain select * from t1 where i=2 or i is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref_or_null i i 5 const 10 Using where; Using index
+1 SIMPLE t1 ref_or_null i i 5 const 9 Using where; Using index
+select count(*) from t1 where i=2 or i is null;
+count(*)
+10
alter table t1 change i i int not null;
+Warnings:
+Warning 1265 Data truncated for column 'i' at row 513
explain select * from t1 where i=2 or i is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref i i 4 const 7 Using where; Using index
+1 SIMPLE t1 ref i i 4 const 7 Using index
+select count(*) from t1 where i=2 or i is null;
+count(*)
+9
drop table t1;
set names latin2;
create table t1 select
@@ -227,10 +236,10 @@ t1 CREATE TABLE `t1` (
`c06` varchar(6) character set latin2 default NULL,
`c07` varchar(6) character set latin2 default NULL,
`c08` varchar(6) character set latin2 default NULL,
- `c09` varchar(6) character set latin2 NOT NULL default '',
- `c10` varchar(6) character set latin2 NOT NULL default '',
- `c11` varchar(6) character set latin2 NOT NULL default '',
- `c12` varchar(6) character set latin2 NOT NULL default '',
+ `c09` varchar(6) character set latin2 default NULL,
+ `c10` varchar(6) character set latin2 default NULL,
+ `c11` varchar(6) character set latin2 default NULL,
+ `c12` varchar(6) character set latin2 default NULL,
`c13` varchar(6) character set latin2 default NULL,
`c14` char(0) character set latin2 default NULL,
`c15` char(0) character set latin2 default NULL,
@@ -246,14 +255,14 @@ t1 CREATE TABLE `t1` (
`c25` varchar(12) character set latin2 default NULL,
`c26` varchar(7) character set latin2 default NULL,
`c27` varchar(7) character set latin2 default NULL,
- `c29` longtext character set latin2,
- `c30` longtext character set latin2,
+ `c29` varchar(381) character set latin2 default NULL,
+ `c30` varchar(317) character set latin2 default NULL,
`c31` varchar(192) character set latin2 default NULL,
`c32` char(0) character set latin2 default NULL,
- `c33` char(3) character set latin2 default NULL,
- `c34` char(3) character set latin2 default NULL,
- `c35` char(3) character set latin2 default NULL,
- `c36` char(3) character set latin2 default NULL,
+ `c33` varchar(3) character set latin2 default NULL,
+ `c34` varchar(3) character set latin2 default NULL,
+ `c35` varchar(3) character set latin2 default NULL,
+ `c36` varchar(3) character set latin2 default NULL,
`c37` varchar(10) character set latin2 default NULL,
`c38` varchar(10) character set latin2 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result
index 36d3e005828..7f746a3dbd8 100644
--- a/mysql-test/r/null_key.result
+++ b/mysql-test/r/null_key.result
@@ -30,7 +30,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using where; Using index
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 9 NULL 2 Using where; Using index
+1 SIMPLE t1 ref a,b a 5 const 2 Using where; Using index
explain select * from t1 where a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 5 NULL 1 Using where; Using index
@@ -66,6 +66,11 @@ a b
NULL 7
NULL 9
NULL 9
+select * from t1 where a > 1 and a < 3 limit 1;
+a b
+2 2
+select * from t1 where a > 8 and a < 9;
+a b
create table t2 like t1;
insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
@@ -153,12 +158,12 @@ a b
7 NULL
explain select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 10 NULL 3 Using where; Using index
+1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using where; Using index
select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
a b
-NULL 7
7 NULL
7 7
+NULL 7
explain select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null a a 5 const 5 Using where; Using index
@@ -337,7 +342,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 Column set to default value; NULL supplied to NOT NULL column 'id2' at row 1
select * from t1;
id id2
NULL 0
diff --git a/mysql-test/r/odbc.result b/mysql-test/r/odbc.result
index c0b2ada0053..2d9d39393b1 100644
--- a/mysql-test/r/odbc.result
+++ b/mysql-test/r/odbc.result
@@ -12,5 +12,5 @@ select * from t1 where a is null;
a b
explain select * from t1 where b is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
drop table t1;
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index fef990297d9..225e306b3cf 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -1,4 +1,9 @@
drop table if exists t1,t2;
+set @sav_dpi= @@div_precision_increment;
+set div_precision_increment= 5;
+show variables like 'div_precision_increment';
+Variable_name Value
+div_precision_increment 5
create table t1 (product varchar(32), country_id int not null, year int, profit int);
insert into t1 values ( 'Computer', 2,2000, 1200),
( 'TV', 1, 1999, 150),
@@ -40,11 +45,11 @@ TV 600
NULL 7785
select product, sum(profit),avg(profit) from t1 group by product with rollup;
product sum(profit) avg(profit)
-Calculator 275 68.7500
-Computer 6900 1380.0000
-Phone 10 10.0000
-TV 600 120.0000
-NULL 7785 519.0000
+Calculator 275 68.75000
+Computer 6900 1380.00000
+Phone 10 10.00000
+TV 600 120.00000
+NULL 7785 519.00000
select product, country_id , year, sum(profit) from t1 group by product, country_id, year;
product country_id year sum(profit)
Calculator 1 1999 50
@@ -85,7 +90,7 @@ explain extended select product, country_id , year, sum(profit) from t1 group by
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using filesort
Warnings:
-Note 1003 select test.t1.product AS `product`,test.t1.country_id AS `country_id`,test.t1.year AS `year`,sum(test.t1.profit) AS `sum(profit)` from test.t1 group by test.t1.product,test.t1.country_id,test.t1.year with rollup
+Note 1003 select `test`.`t1`.`product` AS `product`,`test`.`t1`.`country_id` AS `country_id`,`test`.`t1`.`year` AS `year`,sum(`test`.`t1`.`profit`) AS `sum(profit)` from `test`.`t1` group by `test`.`t1`.`product`,`test`.`t1`.`country_id`,`test`.`t1`.`year` with rollup
select product, country_id , sum(profit) from t1 group by product desc, country_id with rollup;
product country_id sum(profit)
TV 1 400
@@ -164,48 +169,48 @@ product country_id year sum(profit)
NULL NULL NULL 7785
select concat(product,':',country_id) as 'prod', concat(":",year,":") as 'year',1+1, sum(profit)/count(*) from t1 group by 1,2 with rollup;
prod year 1+1 sum(profit)/count(*)
-Calculator:1 :1999: 2 50.00
-Calculator:1 :2000: 2 75.00
-Calculator:1 NULL 2 62.50
-Calculator:2 :2000: 2 75.00
-Calculator:2 NULL 2 75.00
-Computer:1 :1999: 2 1350.00
-Computer:1 :2000: 2 1500.00
-Computer:1 NULL 2 1400.00
-Computer:2 :2000: 2 1350.00
-Computer:2 NULL 2 1350.00
-Phone:3 :2003: 2 10.00
-Phone:3 NULL 2 10.00
-TV:1 :1999: 2 125.00
-TV:1 :2000: 2 150.00
-TV:1 NULL 2 133.33
-TV:2 :2000: 2 100.00
-TV:2 NULL 2 100.00
-NULL NULL 2 519.00
+Calculator:1 :1999: 2 50.00000
+Calculator:1 :2000: 2 75.00000
+Calculator:1 NULL 2 62.50000
+Calculator:2 :2000: 2 75.00000
+Calculator:2 NULL 2 75.00000
+Computer:1 :1999: 2 1350.00000
+Computer:1 :2000: 2 1500.00000
+Computer:1 NULL 2 1400.00000
+Computer:2 :2000: 2 1350.00000
+Computer:2 NULL 2 1350.00000
+Phone:3 :2003: 2 10.00000
+Phone:3 NULL 2 10.00000
+TV:1 :1999: 2 125.00000
+TV:1 :2000: 2 150.00000
+TV:1 NULL 2 133.33333
+TV:2 :2000: 2 100.00000
+TV:2 NULL 2 100.00000
+NULL NULL 2 519.00000
select product, sum(profit)/count(*) from t1 group by product with rollup;
product sum(profit)/count(*)
-Calculator 68.75
-Computer 1380.00
-Phone 10.00
-TV 120.00
-NULL 519.00
+Calculator 68.75000
+Computer 1380.00000
+Phone 10.00000
+TV 120.00000
+NULL 519.00000
select left(product,4) as prod, sum(profit)/count(*) from t1 group by prod with rollup;
prod sum(profit)/count(*)
-Calc 68.75
-Comp 1380.00
-Phon 10.00
-TV 120.00
-NULL 519.00
+Calc 68.75000
+Comp 1380.00000
+Phon 10.00000
+TV 120.00000
+NULL 519.00000
select concat(product,':',country_id), 1+1, sum(profit)/count(*) from t1 group by concat(product,':',country_id) with rollup;
concat(product,':',country_id) 1+1 sum(profit)/count(*)
-Calculator:1 2 62.50
-Calculator:2 2 75.00
-Computer:1 2 1400.00
-Computer:2 2 1350.00
-Phone:3 2 10.00
-TV:1 2 133.33
-TV:2 2 100.00
-NULL 2 519.00
+Calculator:1 2 62.50000
+Calculator:2 2 75.00000
+Computer:1 2 1400.00000
+Computer:2 2 1350.00000
+Phone:3 2 10.00000
+TV:1 2 133.33333
+TV:2 2 100.00000
+NULL 2 519.00000
select product, country , year, sum(profit) from t1,t2 where t1.country_id=t2.country_id group by product, country, year with rollup;
product country year sum(profit)
Calculator India 2000 150
@@ -244,11 +249,11 @@ select product, country_id , year, sum(profit) from t1 group by product, country
product country_id year sum(profit)
select concat(':',product,':'), sum(profit),avg(profit) from t1 group by product with rollup;
concat(':',product,':') sum(profit) avg(profit)
-:Calculator: 275 68.7500
-:Computer: 6900 1380.0000
-:Phone: 10 10.0000
-:TV: 600 120.0000
-NULL 7785 519.0000
+:Calculator: 275 68.75000
+:Computer: 6900 1380.00000
+:Phone: 10 10.00000
+:TV: 600 120.00000
+NULL 7785 519.00000
select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
@@ -378,6 +383,51 @@ a sum(b)
2 6
4 4
NULL 14
+SELECT b, a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
+b a sum(b)
+4 1 4
+NULL 1 4
+1 2 2
+2 2 4
+NULL 2 6
+1 4 4
+NULL 4 4
+NULL NULL 14
+SELECT DISTINCT b,a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
+b a sum(b)
+4 1 4
+NULL 1 4
+1 2 2
+2 2 4
+NULL 2 6
+1 4 4
+NULL 4 4
+NULL NULL 14
+ALTER TABLE t1 ADD COLUMN c INT;
+SELECT a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP;
+a b sum(c)
+1 4 NULL
+1 4 NULL
+1 NULL NULL
+2 1 NULL
+2 1 NULL
+2 2 NULL
+2 2 NULL
+2 NULL NULL
+4 1 NULL
+4 1 NULL
+4 NULL NULL
+NULL NULL NULL
+SELECT distinct a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP;
+a b sum(c)
+1 4 NULL
+1 NULL NULL
+2 1 NULL
+2 2 NULL
+2 NULL NULL
+4 1 NULL
+4 NULL NULL
+NULL NULL NULL
DROP TABLE t1;
CREATE TABLE t1 (a int, b int);
INSERT INTO t1 VALUES
@@ -405,6 +455,7 @@ a m
2 2
NULL 3
DROP TABLE t1;
+set div_precision_increment= @sav_dpi;
CREATE TABLE t1 (a int(11));
INSERT INTO t1 VALUES (1),(2);
SELECT a, SUM(a), SUM(a)+1 FROM (SELECT a FROM t1 UNION select 2) d
@@ -541,3 +592,41 @@ a max(b)
NULL 2
a 1
drop table t1;
+CREATE TABLE t1(id int, type char(1));
+INSERT INTO t1 VALUES
+(1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"),
+(6,"B"),(7,"A"),(8,"C"),(9,"A"),(10,"C");
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT type FROM t1 GROUP BY type WITH ROLLUP;
+type
+A
+B
+C
+NULL
+SELECT type FROM v1 GROUP BY type WITH ROLLUP;
+type
+A
+B
+C
+NULL
+EXPLAIN SELECT type FROM v1 GROUP BY type WITH ROLLUP;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using filesort
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a int(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+CREATE VIEW v1 AS
+SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
+DESC v1;
+Field Type Null Key Default Extra
+a bigint(11) YES NULL
+LENGTH(a) bigint(10) YES NULL
+COUNT(*) bigint(21) NO 0
+SELECT * FROM v1;
+a LENGTH(a) COUNT(*)
+1 1 1
+2 1 1
+NULL NULL 2
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index f7cb17a1a74..035c84431f8 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: DELETE command denied to user 'ssl_user1'@'localhost' for table 't1'
select * from t1;
f1
5
delete from t1;
-ERROR 42000: Access denied for user 'ssl_user2'@'localhost' to database 'test'
+ERROR 42000: DELETE command denied to user 'ssl_user2'@'localhost' for table 't1'
select * from t1;
f1
5
delete from t1;
-ERROR 42000: Access denied for user 'ssl_user3'@'localhost' to database 'test'
+ERROR 42000: DELETE command denied to user 'ssl_user3'@'localhost' for table 't1'
select * from t1;
f1
5
delete from t1;
-ERROR 42000: Access denied for user 'ssl_user4'@'localhost' to database 'test'
+ERROR 42000: DELETE command denied to user 'ssl_user4'@'localhost' for table 't1'
delete from mysql.user where user='ssl_user%';
delete from mysql.db where user='ssl_user%';
flush privileges;
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index ee8ca5f0328..6864c35dbfc 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -189,6 +189,15 @@ a b if(b = 1,i,if(b = 2,v,''))
4 2 453 Boardwalk
SELECT a,b,if(b = 1,i,if(b = 2,v,''))
FROM t1
+LEFT JOIN t2 ON t1.c = t2.c
+LEFT JOIN t3 ON t3.c = t1.c;
+a b if(b = 1,i,if(b = 2,v,''))
+1 1 50
+2 1 25
+3 2 123 Park Place
+4 2 453 Boardwalk
+SELECT a,b,if(b = 1,i,if(b = 2,v,''))
+FROM t1
LEFT JOIN t2 USING(c)
LEFT JOIN t3 ON t3.c = t1.c
ORDER BY a;
@@ -197,6 +206,16 @@ a b if(b = 1,i,if(b = 2,v,''))
2 1 25
3 2 123 Park Place
4 2 453 Boardwalk
+SELECT a,b,if(b = 1,i,if(b = 2,v,''))
+FROM t1
+LEFT JOIN t2 ON t1.c = t2.c
+LEFT JOIN t3 ON t3.c = t1.c
+ORDER BY a;
+a b if(b = 1,i,if(b = 2,v,''))
+1 1 50
+2 1 25
+3 2 123 Park Place
+4 2 453 Boardwalk
drop table t1,t2,t3;
create table t1 (ID int not null primary key, TransactionID int not null);
insert into t1 (ID, TransactionID) values (1, 87), (2, 89), (3, 92), (4, 94), (5, 486), (6, 490), (7, 753), (9, 828), (10, 832), (11, 834), (12, 840);
@@ -257,7 +276,7 @@ favo_tijdschrift varchar(50) NOT NULL default '',
favo_tv varchar(50) NOT NULL default '',
favo_eten varchar(50) NOT NULL default '',
favo_muziek varchar(30) NOT NULL default '',
-info text NOT NULL,
+info text NOT NULL default '',
ipnr varchar(30) NOT NULL default '',
PRIMARY KEY (member_id)
) ENGINE=MyISAM PACK_KEYS=1;
@@ -272,7 +291,7 @@ create table t1 (a int not null, b int, c varchar(10), key (a, b, c));
insert into t1 values (1, NULL, NULL), (1, NULL, 'b'), (1, 1, NULL), (1, 1, 'b'), (1, 1, 'b'), (2, 1, 'a'), (2, 1, 'b'), (2, 2, 'a'), (2, 2, 'b'), (2, 3, 'c'),(1,3,'b');
explain select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 20 NULL 2 Using where; Using index
+1 SIMPLE t1 index a a 22 NULL 11 Using where; Using index
select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
a b c
1 NULL b
@@ -348,7 +367,7 @@ Warning 1265 Data truncated for column 'b' at row 2
Warning 1265 Data truncated for column 'c' at row 3
explain select * from t1 order by a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 18 NULL 11 Using index
+1 SIMPLE t1 index NULL a 20 NULL 11 Using index
select * from t1 order by a, b, c;
a b c
1 0
@@ -364,7 +383,7 @@ a b c
2 3 c
explain select * from t1 order by a desc, b desc, c desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 18 NULL 11 Using index
+1 SIMPLE t1 index NULL a 20 NULL 11 Using index
select * from t1 order by a desc, b desc, c desc;
a b c
2 3 c
@@ -380,7 +399,7 @@ a b c
1 0
explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 18 NULL 3 Using where; Using index
+1 SIMPLE t1 range a a 20 NULL 3 Using where; Using index
select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
a b c
1 1 b
@@ -526,9 +545,15 @@ INSERT INTO t2 (numeropost,pseudo) VALUES (1,'joce'),(1,'bug');
SELECT titre,t1.numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest
test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug
+SELECT titre,numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
+titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest
+test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug
SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest
test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug
+SELECT titre,numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
+titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest
+test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug
drop table t1,t2;
CREATE TABLE t1 (a int, b int);
INSERT INTO t1 VALUES (1, 2);
@@ -574,7 +599,7 @@ KEY StringField (FieldKey,StringVal(32))
INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 36 const 3 Using where
+1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 38 const 3 Using where
SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
FieldKey LongVal StringVal
1 0 2
@@ -582,7 +607,7 @@ FieldKey LongVal StringVal
1 2 1
EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range FieldKey,LongField,StringField FieldKey 36 NULL 4 Using where; Using filesort
+1 SIMPLE t1 range FieldKey,LongField,StringField FieldKey 38 NULL 4 Using where; Using filesort
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
FieldKey LongVal StringVal
3 1 2
@@ -590,7 +615,7 @@ FieldKey LongVal StringVal
3 3 3
EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range FieldKey,LongField,StringField LongField 36 NULL 4 Using where
+1 SIMPLE t1 range FieldKey,LongField,StringField LongField 38 NULL 4 Using where
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
FieldKey LongVal StringVal
3 1 2
@@ -733,6 +758,13 @@ xxxxxxxxxxxxxxxxxxxaa
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxz
drop table t1;
+create table t1 (a int not null, b int not null, c int not null);
+insert t1 values (1,1,1),(1,1,2),(1,2,1);
+select a, b from t1 group by a, b order by sum(c);
+a b
+1 2
+1 1
+drop table t1;
create table t1 (
`sid` decimal(8,0) default null,
`wnid` varchar(11) not null default '',
@@ -757,7 +789,7 @@ insert into t1 (`sid`, `wnid`) values
('25295','02071491000'),('25296','02071491000'),('25297','02071499000');
explain select * from t1 where wnid like '0101%' order by wnid;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range wnid14,wnid wnid 11 NULL 10 Using where
+1 SIMPLE t1 range wnid14,wnid wnid 13 NULL 10 Using where
select * from t1 where wnid like '0101%' order by wnid;
sid wnid
10100 01019000000
diff --git a/mysql-test/r/preload.result b/mysql-test/r/preload.result
index 7237a0da7e0..b668b07b398 100644
--- a/mysql-test/r/preload.result
+++ b/mysql-test/r/preload.result
@@ -55,15 +55,15 @@ count(*)
4181
show status like "key_read%";
Variable_name Value
-Key_read_requests 217
-Key_reads 45
+Key_read_requests 294
+Key_reads 60
select count(*) from t1 where b = 'test1';
count(*)
4181
show status like "key_read%";
Variable_name Value
-Key_read_requests 434
-Key_reads 45
+Key_read_requests 588
+Key_reads 60
flush tables;
flush status;
select @@preload_buffer_size;
@@ -74,15 +74,15 @@ Table Op Msg_type Msg_text
test.t1 preload_keys status OK
show status like "key_read%";
Variable_name Value
-Key_read_requests 581
-Key_reads 581
+Key_read_requests 774
+Key_reads 774
select count(*) from t1 where b = 'test1';
count(*)
4181
show status like "key_read%";
Variable_name Value
-Key_read_requests 798
-Key_reads 581
+Key_read_requests 1068
+Key_reads 774
flush tables;
flush status;
show status like "key_read%";
@@ -98,15 +98,15 @@ Table Op Msg_type Msg_text
test.t1 preload_keys status OK
show status like "key_read%";
Variable_name Value
-Key_read_requests 10
-Key_reads 10
+Key_read_requests 17
+Key_reads 17
select count(*) from t1 where b = 'test1';
count(*)
4181
show status like "key_read%";
Variable_name Value
-Key_read_requests 227
-Key_reads 52
+Key_read_requests 311
+Key_reads 75
flush tables;
flush status;
show status like "key_read%";
@@ -123,8 +123,8 @@ test.t1 preload_keys status OK
test.t2 preload_keys status OK
show status like "key_read%";
Variable_name Value
-Key_read_requests 587
-Key_reads 587
+Key_read_requests 785
+Key_reads 785
select count(*) from t1 where b = 'test1';
count(*)
4181
@@ -133,8 +133,8 @@ count(*)
2584
show status like "key_read%";
Variable_name Value
-Key_read_requests 938
-Key_reads 613
+Key_read_requests 1266
+Key_reads 821
flush tables;
flush status;
show status like "key_read%";
@@ -145,10 +145,12 @@ load index into cache t3, t2 key (primary,b) ;
Table Op Msg_type Msg_text
test.t3 preload_keys error Table 'test.t3' doesn't exist
test.t2 preload_keys status OK
+Warnings:
+Error 1146 Table 'test.t3' doesn't exist
show status like "key_read%";
Variable_name Value
-Key_read_requests 355
-Key_reads 355
+Key_read_requests 478
+Key_reads 478
flush tables;
flush status;
show status like "key_read%";
@@ -160,6 +162,9 @@ Table Op Msg_type Msg_text
test.t3 preload_keys error Table 'test.t3' doesn't exist
test.t2 preload_keys error Key column 'c' doesn't exist in table
test.t2 preload_keys status Operation failed
+Warnings:
+Error 1146 Table 'test.t3' doesn't exist
+Error 1072 Key column 'c' doesn't exist in table
show status like "key_read%";
Variable_name Value
Key_read_requests 0
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index f5bf3ffa96d..f1c3672083d 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2;
+drop database if exists client_test_db;
create table t1
(
a int primary key,
@@ -137,7 +138,7 @@ create table t1
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 bit, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -153,24 +154,24 @@ id select_type table type possible_keys key key_len ref rows Extra
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
+3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
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
+3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
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
+3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
deallocate prepare stmt1;
drop tables t1,t2;
set @arg00=1;
@@ -207,10 +208,10 @@ 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
+t1 MyISAM 10 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
+t1 MyISAM 10 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
deallocate prepare stmt1 ;
drop table t1;
create table t1(a varchar(2), b varchar(3));
@@ -480,6 +481,11 @@ execute stmt;
pnum
deallocate prepare stmt;
drop table t1, t2;
+create table t1 (a varchar(20));
+insert into t1 values ('foo');
+prepare stmt FROM 'SELECT char_length (a) FROM t1';
+ERROR 42000: FUNCTION test.char_length does not exist
+drop table t1;
prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0";
execute stmt;
foo
@@ -492,6 +498,77 @@ SELECT FOUND_ROWS();
FOUND_ROWS()
2
deallocate prepare stmt;
+create table t1 (a char(3) not null, b char(3) not null,
+c char(3) not null, primary key (a, b, c));
+create table t2 like t1;
+prepare stmt from
+"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b)
+ where t1.a=1";
+execute stmt;
+a
+execute stmt;
+a
+execute stmt;
+a
+prepare stmt from
+"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from
+(t1 left outer join t2 on t2.a=? and t1.b=t2.b)
+left outer join t2 t3 on t3.a=? where t1.a=?";
+set @a:=1, @b:=1, @c:=1;
+execute stmt using @a, @b, @c;
+a b c a b c
+execute stmt using @a, @b, @c;
+a b c a b c
+execute stmt using @a, @b, @c;
+a b c a b c
+deallocate prepare stmt;
+drop table t1,t2;
+SET @aux= "SELECT COUNT(*)
+ FROM INFORMATION_SCHEMA.COLUMNS A,
+ INFORMATION_SCHEMA.COLUMNS B
+ WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA
+ AND A.TABLE_NAME = B.TABLE_NAME
+ AND A.COLUMN_NAME = B.COLUMN_NAME AND
+ A.TABLE_NAME = 'user'";
+prepare my_stmt from @aux;
+execute my_stmt;
+COUNT(*)
+37
+execute my_stmt;
+COUNT(*)
+37
+execute my_stmt;
+COUNT(*)
+37
+deallocate prepare my_stmt;
+drop procedure if exists p1|
+drop table if exists t1|
+create table t1 (id int)|
+insert into t1 values(1)|
+create procedure p1(a int, b int)
+begin
+declare c int;
+select max(id)+1 into c from t1;
+insert into t1 select a+b;
+insert into t1 select a-b;
+insert into t1 select a-c;
+end|
+set @a= 3, @b= 4|
+prepare stmt from "call p1(?, ?)"|
+execute stmt using @a, @b|
+execute stmt using @a, @b|
+select * from t1|
+id
+1
+7
+-1
+1
+7
+-1
+-5
+deallocate prepare stmt|
+drop procedure p1|
+drop table t1|
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
@@ -555,6 +632,47 @@ id
3
deallocate prepare stmt;
drop table t1, t2;
+create table t1 (a int);
+insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+prepare stmt from "select * from t1 limit ?, ?";
+set @offset=0, @limit=1;
+execute stmt using @offset, @limit;
+a
+1
+select * from t1 limit 0, 1;
+a
+1
+set @offset=3, @limit=2;
+execute stmt using @offset, @limit;
+a
+4
+5
+select * from t1 limit 3, 2;
+a
+4
+5
+prepare stmt from "select * from t1 limit ?";
+execute stmt using @limit;
+a
+1
+2
+prepare stmt from "select * from t1 where a in (select a from t1 limit ?)";
+ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+prepare stmt from "select * from t1 union all select * from t1 limit ?, ?";
+set @offset=9;
+set @limit=2;
+execute stmt using @offset, @limit;
+a
+10
+1
+prepare stmt from "(select * from t1 limit ?, ?) union all
+ (select * from t1 limit ?, ?) order by a limit ?";
+execute stmt using @offset, @limit, @offset, @limit, @limit;
+a
+10
+10
+drop table t1;
+deallocate prepare stmt;
create table t1 (id int);
prepare stmt from "insert into t1 (id) select id from t1 union select id from t1";
execute stmt;
@@ -639,25 +757,6 @@ execute stmt using @a, @b;
?=?
1
deallocate prepare stmt;
-create table t1 (utext varchar(20) character set ucs2);
-insert into t1 values ("lily");
-insert into t1 values ("river");
-prepare stmt from 'select utext from t1 where utext like ?';
-set @param1='%%';
-execute stmt using @param1;
-utext
-lily
-river
-execute stmt using @param1;
-utext
-lily
-river
-select utext from t1 where utext like '%%';
-utext
-lily
-river
-drop table t1;
-deallocate prepare stmt;
create table t1 (a int);
prepare stmt from "select ??";
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
@@ -674,6 +773,14 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
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 '? from t1' at line 1
drop table t1;
+CREATE TABLE b12651_T1(a int) ENGINE=MYISAM;
+CREATE TABLE b12651_T2(b int) ENGINE=MYISAM;
+CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2;
+PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)';
+EXECUTE b12651;
+1
+DROP VIEW b12651_V1;
+DROP TABLE b12651_T1, b12651_T2;
prepare stmt from "select @@time_zone";
execute stmt;
@@time_zone
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 49e858eca56..7fb1e1b4df4 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -1,6 +1,9 @@
drop table if exists t5, t6, t7, t8;
drop database if exists mysqltest ;
drop database if exists client_test_db;
+drop database if exists testtets;
+drop table if exists t1Aa,t2Aa,v1Aa,v2Aa;
+drop view if exists t1Aa,t2Aa,v1Aa,v2Aa;
test_sequence
------ basic tests ------
drop table if exists t1, t9 ;
@@ -14,8 +17,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -255,16 +258,29 @@ a int primary key, b char(10)
prepare stmt4 from ' show databases ';
execute stmt4;
Database
+information_schema
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 where field in (select ?) ';
+SET @arg00="a";
+execute stmt4 using @arg00;
+Field Type Null Key Default Extra
+a int(11) NO PRI
+SET @arg00="b";
+execute stmt4 using @arg00;
+Field Type Null Key Default Extra
+b char(10) YES NULL
+SET @arg00=1;
+execute stmt4 using @arg00;
+Field Type Null Key Default Extra
prepare stmt4 from ' show columns from t2 from test like ''a%'' ';
execute stmt4;
Field Type Null Key Default Extra
-a int(11) PRI 0
+a int(11) NO PRI
create index t2_idx on t2(b);
prepare stmt4 from ' show index from t2 from test ';
execute stmt4;
@@ -274,11 +290,11 @@ 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
+t2 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show table status from test like ''t9%'' ';
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
-t9 MyISAM 9 Dynamic 2 220 440 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL
+t9 MyISAM 10 Dynamic 2 216 432 # 2048 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show status like ''Threads_running'' ';
execute stmt4;
Variable_name Value
@@ -306,8 +322,8 @@ prepare stmt4 from ' show storage engines ';
execute stmt4;
Engine Support Comment
MyISAM YES/NO Default engine as of MySQL 3.23 with great performance
-HEAP YES/NO Alias for MEMORY
MEMORY YES/NO Hash based, stored in memory, useful for temporary tables
+HEAP YES/NO Alias for MEMORY
MERGE YES/NO Collection of identical MyISAM tables
MRG_MYISAM YES/NO Alias for MERGE
ISAM YES/NO Obsolete storage engine, now replaced by MyISAM
@@ -321,7 +337,8 @@ NDB YES/NO Alias for NDBCLUSTER
EXAMPLE YES/NO Example storage engine
ARCHIVE YES/NO Archive storage engine
CSV YES/NO CSV storage engine
-BLACKHOLE YES/NO Storage engine designed to act as null storage
+FEDERATED YES/NO Federated MySQL storage engine
+BLACKHOLE YES/NO /dev/null storage engine (anything you write to it disappears)
drop table if exists t5;
prepare stmt1 from ' drop table if exists t5 ' ;
execute stmt1 ;
@@ -393,22 +410,10 @@ create database mysqltest ;
prepare stmt3 from ' drop database mysqltest ';
ERROR HY000: This command is not supported in the prepared statement protocol yet
drop database mysqltest ;
-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
+a int(11) NO PRI
b char(10) YES MUL NULL
drop table t2 ;
execute stmt3;
@@ -435,9 +440,7 @@ ERROR HY000: This command is not supported in the prepared statement protocol ye
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' ;
@@ -445,17 +448,17 @@ select 'a' || 'b' ;
ab
prepare stmt4 from ' SET sql_mode="" ';
execute stmt4;
-select 'a' || 'b' ;
-'a' || 'b'
-0
-prepare stmt5 from ' select ''a'' || ''b'' ' ;
+select '2' || '3' ;
+'2' || '3'
+1
+prepare stmt5 from ' select ''2'' || ''3'' ' ;
execute stmt5;
-'a' || 'b'
-0
+'2' || '3'
+1
SET sql_mode=ansi;
execute stmt5;
-'a' || 'b'
-0
+'2' || '3'
+1
SET sql_mode="";
prepare stmt1 from ' flush local privileges ' ;
ERROR HY000: This command is not supported in the prepared statement protocol yet
@@ -472,7 +475,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32928 0 63
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 14 N 1 31 8
@@ -488,7 +491,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 5 Y 0 31 8
def possible_keys 253 4096 7 Y 0 31 8
def key 253 64 7 Y 0 31 8
-def key_len 8 3 1 Y 32928 0 63
+def key_len 253 4096 1 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 27 N 1 31 8
@@ -545,11 +548,8 @@ 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;
@@ -560,7 +560,7 @@ drop table t2;
prepare stmt1 from ' rename table t5 to t6, t7 to t8 ' ;
create table t5 (a int) ;
execute stmt1 ;
-ERROR HY000: Can't find file: './test/t7.frm' (errno: 2)
+ERROR HY000: Can't find file: './test/t7' (errno: 2)
create table t7 (a int) ;
execute stmt1 ;
execute stmt1 ;
@@ -803,4 +803,4 @@ prepare stmt1 from @string ;
execute stmt1 ;
prepare stmt1 from ' select * from t5 ' ;
execute stmt1 ;
-drop table t5 ;
+drop table t5, t9;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 4b655cfb854..16ead200933 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -10,8 +10,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -59,17 +59,17 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
-def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
def test t9 t9 c16 c16 11 8 8 Y 128 0 63
def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
-def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c18 c18 1 4 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -444,9 +444,10 @@ 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
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
+execute stmt1 using @arg00;
+a b
+1 one
set @arg00='b' ;
set @arg01=0 ;
set @arg02=2 ;
@@ -530,44 +531,44 @@ the join statement is:
SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
@@ -593,44 +594,44 @@ the join statement is:
SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
@@ -656,23 +657,23 @@ the join statement is:
SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
@@ -1155,7 +1156,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32928 0 63
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
@@ -1223,7 +1224,6 @@ 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 ;
@@ -1302,7 +1302,7 @@ set @arg00=NULL;
set @arg01=2;
execute stmt1 using @arg00, @arg01;
Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
select a,b from t1 order by a;
a b
0 two
@@ -1382,10 +1382,8 @@ 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
+prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
+execute stmt1 using @arg00;
test_sequence
------ insert tests ------
delete from t1 ;
@@ -1713,8 +1711,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@@ -1732,8 +1730,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
drop table t2;
drop table if exists t5 ;
@@ -1777,13 +1775,13 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` double(3,1) NOT NULL default '0.0',
- `param02` double default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
- `const05` binary(3) NOT NULL default '',
+ `const05` varbinary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`param06` longtext,
@@ -1799,7 +1797,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` double default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1807,13 +1805,13 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 5 3 3 N 32769 1 63
-def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
-def test t5 t5 const03 const03 5 23 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const03 const03 5 17 1 N 32769 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8
@@ -1829,13 +1827,13 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
param01 8
const02 8.0
-param02 8
+param02 8.000000000000000000000000000000
const03 8
param03 8
const04 abc
@@ -1917,40 +1915,40 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
@@ -1964,38 +1962,38 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -2014,78 +2012,78 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2102,40 +2100,40 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select 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
@@ -2146,38 +2144,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2192,76 +2190,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
@@ -2572,12 +2570,12 @@ set @arg00= 9223372036854775807 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2589,18 +2587,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '9223372036854775807' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2612,18 +2610,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -9223372036854775808 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2641,12 +2639,12 @@ set @arg00= '-9223372036854775808' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2664,14 +2662,14 @@ set @arg00= 1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2683,7 +2681,7 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '1.11111111111111111111e+50' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@@ -2695,8 +2693,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
c2 1
@@ -2708,20 +2706,20 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2745,8 +2743,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
c2 -1
@@ -2818,10 +2816,10 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
41 4 41 41 41 41 41 41 41 41 41 41
42 4 42 42 42 42 42 42 42 42 42 42
43 4 43 43 43 43 43 43 43 43 43 43
-50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
-51 5 51 51 51 51 51 51 51 51 51 51
-52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
-53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+50 5 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0
+51 5 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0
+52 5 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0
+53 5 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0
54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
55 5 55 55 55 55 55 55 55 55 55 55
56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
@@ -2977,45 +2975,45 @@ Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
c1 c13 c14 c15 c16 c17
20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 4d2a62887d6..9ab5a79f755 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -10,8 +10,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -59,17 +59,17 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
-def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
def test t9 t9 c16 c16 11 8 8 Y 128 0 63
def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
-def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c18 c18 1 4 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -444,9 +444,10 @@ 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
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
+execute stmt1 using @arg00;
+a b
+1 one
set @arg00='b' ;
set @arg01=0 ;
set @arg02=2 ;
@@ -530,44 +531,44 @@ the join statement is:
SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
@@ -593,44 +594,44 @@ the join statement is:
SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
@@ -656,23 +657,23 @@ the join statement is:
SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
@@ -1155,7 +1156,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32928 0 63
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
@@ -1206,7 +1207,6 @@ 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 ;
@@ -1285,7 +1285,7 @@ set @arg00=NULL;
set @arg01=2;
execute stmt1 using @arg00, @arg01;
Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
select a,b from t1 order by a;
a b
0 two
@@ -1365,10 +1365,8 @@ 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
+prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
+execute stmt1 using @arg00;
test_sequence
------ insert tests ------
delete from t1 ;
@@ -1696,8 +1694,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@@ -1715,8 +1713,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
drop table t2;
drop table if exists t5 ;
@@ -1760,13 +1758,13 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` double(3,1) NOT NULL default '0.0',
- `param02` double default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
- `const05` binary(3) NOT NULL default '',
+ `const05` varbinary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`param06` longtext,
@@ -1782,7 +1780,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` double default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1790,13 +1788,13 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 5 3 3 N 32769 1 63
-def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
-def test t5 t5 const03 const03 5 23 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const03 const03 5 17 1 N 32769 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8
@@ -1812,13 +1810,13 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
param01 8
const02 8.0
-param02 8
+param02 8.000000000000000000000000000000
const03 8
param03 8
const04 abc
@@ -1900,40 +1898,40 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
@@ -1947,38 +1945,38 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -1997,78 +1995,78 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2085,40 +2083,40 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select 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
@@ -2129,38 +2127,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2175,76 +2173,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
@@ -2555,12 +2553,12 @@ set @arg00= 9223372036854775807 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2572,18 +2570,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '9223372036854775807' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2595,18 +2593,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -9223372036854775808 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2624,12 +2622,12 @@ set @arg00= '-9223372036854775808' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2647,14 +2645,14 @@ set @arg00= 1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2666,7 +2664,7 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '1.11111111111111111111e+50' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@@ -2678,8 +2676,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
c2 1
@@ -2691,20 +2689,20 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2728,8 +2726,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
c2 -1
@@ -2801,10 +2799,10 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
41 4 41 41 41 41 41 41 41 41 41 41
42 4 42 42 42 42 42 42 42 42 42 42
43 4 43 43 43 43 43 43 43 43 43 43
-50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
-51 5 51 51 51 51 51 51 51 51 51 51
-52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
-53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+50 5 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0
+51 5 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0
+52 5 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0
+53 5 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0
54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
55 5 55 55 55 55 55 55 55 55 55 55
56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
@@ -2960,45 +2958,45 @@ Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
c1 c13 c14 c15 c16 c17
20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index a4919b664c4..8336a5bf99b 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -11,11 +11,11 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-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'),
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100),
+c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100),
+c29 varchar(100), c30 varchar(100), c31 enum('one', 'two', 'three'),
c32 set('monday', 'tuesday', 'wednesday'),
primary key(c1)
) engine = 'HEAP' ;
@@ -60,17 +60,17 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
-def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
def test t9 t9 c16 c16 11 8 8 Y 128 0 63
def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
-def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c18 c18 1 4 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 253 100 8 Y 0 0 8
def test t9 t9 c24 c24 253 100 8 Y 0 0 8
@@ -445,9 +445,10 @@ 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
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
+execute stmt1 using @arg00;
+a b
+1 one
set @arg00='b' ;
set @arg01=0 ;
set @arg02=2 ;
@@ -531,44 +532,44 @@ the join statement is:
SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
@@ -594,44 +595,44 @@ the join statement is:
SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
@@ -657,23 +658,23 @@ the join statement is:
SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
@@ -1156,7 +1157,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32928 0 63
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
@@ -1207,7 +1208,6 @@ 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 ;
@@ -1286,7 +1286,7 @@ set @arg00=NULL;
set @arg01=2;
execute stmt1 using @arg00, @arg01;
Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
select a,b from t1 order by a;
a b
0 two
@@ -1366,10 +1366,8 @@ 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
+prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
+execute stmt1 using @arg00;
test_sequence
------ insert tests ------
delete from t1 ;
@@ -1697,8 +1695,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@@ -1716,8 +1714,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
drop table t2;
drop table if exists t5 ;
@@ -1761,13 +1759,13 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` double(3,1) NOT NULL default '0.0',
- `param02` double default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
- `const05` binary(3) NOT NULL default '',
+ `const05` varbinary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`param06` longtext,
@@ -1783,7 +1781,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` double default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1791,13 +1789,13 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 5 3 3 N 32769 1 63
-def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
-def test t5 t5 const03 const03 5 23 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const03 const03 5 17 1 N 32769 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8
@@ -1813,13 +1811,13 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
param01 8
const02 8.0
-param02 8
+param02 8.000000000000000000000000000000
const03 8
param03 8
const04 abc
@@ -1901,40 +1899,40 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 0 31 8
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 0 31 8
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 0 31 8
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 0 31 8
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
@@ -1948,38 +1946,38 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 0 31 8
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 0 31 8
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 0 31 8
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 0 31 8
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 0 31 8
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 0 31 8
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 0 31 8
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 0 31 8
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -1998,78 +1996,78 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 0 31 8
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 0 31 8
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 0 31 8
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 0 31 8
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 0 31 8
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 0 31 8
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 0 31 8
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 0 31 8
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 0 31 8
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 0 31 8
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 0 31 8
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 0 31 8
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2086,40 +2084,40 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 0 31 8
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 0 31 8
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 0 31 8
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 0 31 8
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select 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
@@ -2130,38 +2128,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 0 31 8
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 0 31 8
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 0 31 8
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 0 31 8
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 0 31 8
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 0 31 8
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 0 31 8
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 0 31 8
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2176,76 +2174,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 0 31 8
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 0 31 8
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 0 31 8
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 0 31 8
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 0 31 8
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 0 31 8
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 0 31 8
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 0 31 8
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 0 31 8
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 0 31 8
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 0 31 8
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 0 31 8
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
@@ -2556,12 +2554,12 @@ set @arg00= 9223372036854775807 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2573,18 +2571,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '9223372036854775807' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2596,18 +2594,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -9223372036854775808 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2625,12 +2623,12 @@ set @arg00= '-9223372036854775808' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2648,14 +2646,14 @@ set @arg00= 1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2667,7 +2665,7 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '1.11111111111111111111e+50' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@@ -2679,8 +2677,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
c2 1
@@ -2692,20 +2690,20 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2729,8 +2727,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
c2 -1
@@ -2802,10 +2800,10 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
41 4 41 41 41 41 41 41 41 41 41 41
42 4 42 42 42 42 42 42 42 42 42 42
43 4 43 43 43 43 43 43 43 43 43 43
-50 5 50 50 50 50 50 50 50 50 50 50
-51 5 51 51 51 51 51 51 51 51 51 51
-52 5 52 52 52 52 52 52 52 52 52 52
-53 5 53 53 53 53 53 53 53 53 53 53
+50 5 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0
+51 5 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0
+52 5 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0
+53 5 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0
54 5 54 54 54 54 54 54 54 54 54 54
55 5 55 55 55 55 55 55 55 55 55 55
56 6 56 56 56 56 56 56 56 56 56 56
@@ -2961,45 +2959,45 @@ Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
c1 c13 c14 c15 c16 c17
20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index f98cc1b3cdf..f341247a417 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -12,8 +12,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -32,8 +32,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -52,8 +52,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -102,17 +102,17 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
-def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
def test t9 t9 c16 c16 11 8 8 Y 128 0 63
def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
-def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c18 c18 1 4 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -487,9 +487,10 @@ 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
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
+execute stmt1 using @arg00;
+a b
+1 one
set @arg00='b' ;
set @arg01=0 ;
set @arg02=2 ;
@@ -573,44 +574,44 @@ the join statement is:
SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
@@ -636,44 +637,44 @@ the join statement is:
SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
@@ -699,23 +700,23 @@ the join statement is:
SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
@@ -1198,7 +1199,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32928 0 63
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
@@ -1249,7 +1250,6 @@ 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 ;
@@ -1328,7 +1328,7 @@ set @arg00=NULL;
set @arg01=2;
execute stmt1 using @arg00, @arg01;
Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
select a,b from t1 order by a;
a b
0 two
@@ -1408,10 +1408,8 @@ 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
+prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
+execute stmt1 using @arg00;
test_sequence
------ insert tests ------
delete from t1 ;
@@ -1697,13 +1695,13 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` double(3,1) NOT NULL default '0.0',
- `param02` double default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
- `const05` binary(3) NOT NULL default '',
+ `const05` varbinary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`param06` longtext,
@@ -1719,7 +1717,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` double default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1727,13 +1725,13 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 5 3 3 N 32769 1 63
-def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
-def test t5 t5 const03 const03 5 23 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const03 const03 5 17 1 N 32769 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8
@@ -1749,13 +1747,13 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
param01 8
const02 8.0
-param02 8
+param02 8.000000000000000000000000000000
const03 8
param03 8
const04 abc
@@ -1837,40 +1835,40 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
@@ -1884,38 +1882,38 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -1934,78 +1932,78 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2022,40 +2020,40 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select 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
@@ -2066,38 +2064,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2112,76 +2110,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
@@ -2492,12 +2490,12 @@ set @arg00= 9223372036854775807 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2509,18 +2507,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '9223372036854775807' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2532,18 +2530,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -9223372036854775808 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2561,12 +2559,12 @@ set @arg00= '-9223372036854775808' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2584,14 +2582,14 @@ set @arg00= 1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2603,7 +2601,7 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '1.11111111111111111111e+50' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@@ -2615,8 +2613,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
c2 1
@@ -2628,20 +2626,20 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2665,8 +2663,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
c2 -1
@@ -2738,10 +2736,10 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
41 4 41 41 41 41 41 41 41 41 41 41
42 4 42 42 42 42 42 42 42 42 42 42
43 4 43 43 43 43 43 43 43 43 43 43
-50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
-51 5 51 51 51 51 51 51 51 51 51 51
-52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
-53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+50 5 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0
+51 5 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0
+52 5 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0
+53 5 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0
54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
55 5 55 55 55 55 55 55 55 55 55 55
56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
@@ -2897,45 +2895,45 @@ Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
c1 c13 c14 c15 c16 c17
20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
@@ -3066,8 +3064,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -3116,17 +3114,17 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
-def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
def test t9 t9 c16 c16 11 8 8 Y 128 0 63
def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
-def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c18 c18 1 4 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -3501,9 +3499,10 @@ 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
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
+execute stmt1 using @arg00;
+a b
+1 one
set @arg00='b' ;
set @arg01=0 ;
set @arg02=2 ;
@@ -3587,44 +3586,44 @@ the join statement is:
SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
@@ -3650,44 +3649,44 @@ the join statement is:
SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
@@ -3713,23 +3712,23 @@ the join statement is:
SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
@@ -4212,7 +4211,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32928 0 63
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
@@ -4263,7 +4262,6 @@ 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 ;
@@ -4342,7 +4340,7 @@ set @arg00=NULL;
set @arg01=2;
execute stmt1 using @arg00, @arg01;
Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
select a,b from t1 order by a;
a b
0 two
@@ -4422,10 +4420,8 @@ 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
+prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
+execute stmt1 using @arg00;
test_sequence
------ insert tests ------
delete from t1 ;
@@ -4711,13 +4707,13 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` double(3,1) NOT NULL default '0.0',
- `param02` double default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
- `const05` binary(3) NOT NULL default '',
+ `const05` varbinary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`param06` longtext,
@@ -4733,7 +4729,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` double default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -4741,13 +4737,13 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 5 3 3 N 32769 1 63
-def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
-def test t5 t5 const03 const03 5 23 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const03 const03 5 17 1 N 32769 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8
@@ -4763,13 +4759,13 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
param01 8
const02 8.0
-param02 8
+param02 8.000000000000000000000000000000
const03 8
param03 8
const04 abc
@@ -4851,40 +4847,40 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
@@ -4898,38 +4894,38 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -4948,78 +4944,78 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -5036,40 +5032,40 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select 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
@@ -5080,38 +5076,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -5126,76 +5122,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
@@ -5506,12 +5502,12 @@ set @arg00= 9223372036854775807 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -5523,18 +5519,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '9223372036854775807' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -5546,18 +5542,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -9223372036854775808 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -5575,12 +5571,12 @@ set @arg00= '-9223372036854775808' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -5598,14 +5594,14 @@ set @arg00= 1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -5617,7 +5613,7 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '1.11111111111111111111e+50' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@@ -5629,8 +5625,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
c2 1
@@ -5642,20 +5638,20 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -5679,8 +5675,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
c2 -1
@@ -5752,10 +5748,10 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
41 4 41 41 41 41 41 41 41 41 41 41
42 4 42 42 42 42 42 42 42 42 42 42
43 4 43 43 43 43 43 43 43 43 43 43
-50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
-51 5 51 51 51 51 51 51 51 51 51 51
-52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
-53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+50 5 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0
+51 5 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0
+52 5 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0
+53 5 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0
54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
55 5 55 55 55 55 55 55 55 55 55 55
56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
@@ -5911,45 +5907,45 @@ Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
c1 c13 c14 c15 c16 c17
20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index acd7f45de95..fe4536827e6 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -10,8 +10,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -59,17 +59,17 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
-def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
def test t9 t9 c16 c16 11 8 8 Y 128 0 63
def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
-def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c18 c18 1 4 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -444,9 +444,10 @@ 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
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
+execute stmt1 using @arg00;
+a b
+1 one
set @arg00='b' ;
set @arg01=0 ;
set @arg02=2 ;
@@ -530,44 +531,44 @@ the join statement is:
SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
@@ -593,44 +594,44 @@ the join statement is:
SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
@@ -656,23 +657,23 @@ the join statement is:
SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
@@ -1155,7 +1156,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32928 0 63
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
@@ -1206,7 +1207,6 @@ 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 ;
@@ -1285,7 +1285,7 @@ set @arg00=NULL;
set @arg01=2;
execute stmt1 using @arg00, @arg01;
Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
select a,b from t1 order by a;
a b
0 two
@@ -1365,10 +1365,8 @@ 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
+prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
+execute stmt1 using @arg00;
test_sequence
------ insert tests ------
delete from t1 ;
@@ -1696,8 +1694,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@@ -1715,8 +1713,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
drop table t2;
drop table if exists t5 ;
@@ -1760,13 +1758,13 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` double(3,1) NOT NULL default '0.0',
- `param02` double default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
- `const05` binary(3) NOT NULL default '',
+ `const05` varbinary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`param06` longtext,
@@ -1782,7 +1780,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` double default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1790,13 +1788,13 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 5 3 3 N 32769 1 63
-def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
-def test t5 t5 const03 const03 5 23 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const03 const03 5 17 1 N 32769 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8
@@ -1812,13 +1810,13 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
param01 8
const02 8.0
-param02 8
+param02 8.000000000000000000000000000000
const03 8
param03 8
const04 abc
@@ -1900,40 +1898,40 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
@@ -1947,38 +1945,38 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -1997,78 +1995,78 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2085,40 +2083,40 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select 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
@@ -2129,38 +2127,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2175,76 +2173,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
@@ -2555,12 +2553,12 @@ set @arg00= 9223372036854775807 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2572,18 +2570,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '9223372036854775807' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2595,18 +2593,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -9223372036854775808 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2624,12 +2622,12 @@ set @arg00= '-9223372036854775808' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2647,14 +2645,14 @@ set @arg00= 1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2666,7 +2664,7 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '1.11111111111111111111e+50' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@@ -2678,8 +2676,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
c2 1
@@ -2691,20 +2689,20 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2728,8 +2726,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
c2 -1
@@ -2801,10 +2799,10 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
41 4 41 41 41 41 41 41 41 41 41 41
42 4 42 42 42 42 42 42 42 42 42 42
43 4 43 43 43 43 43 43 43 43 43 43
-50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
-51 5 51 51 51 51 51 51 51 51 51 51
-52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
-53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+50 5 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0
+51 5 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0
+52 5 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0
+53 5 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0
54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
55 5 55 55 55 55 55 55 55 55 55 55
56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
@@ -2960,45 +2958,45 @@ Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
c1 c13 c14 c15 c16 c17
20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index 27a1ea0925d..c4cb92bdc02 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -10,8 +10,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
-c13 date, c14 datetime, c15 timestamp(14), c16 time,
-c17 year, c18 bit, c19 bool, c20 char,
+c13 date, c14 datetime, c15 timestamp, c16 time,
+c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -59,17 +59,17 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
-def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
def test t9 t9 c16 c16 11 8 8 Y 128 0 63
def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
-def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c18 c18 1 4 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -444,9 +444,10 @@ 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
+prepare stmt1 from ' select a,b from t1 order by a limit ? ';
+execute stmt1 using @arg00;
+a b
+1 one
set @arg00='b' ;
set @arg01=0 ;
set @arg02=2 ;
@@ -530,44 +531,44 @@ the join statement is:
SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
@@ -593,44 +594,44 @@ the join statement is:
SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b
+1 one
+2 two
+3 three
+4 four
the join statement is:
SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
@@ -656,23 +657,23 @@ the join statement is:
SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
-execute stmt1 ;
-a b a b
-1 one 1 one
-2 two 2 two
-3 three 3 three
-4 four 4 four
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
+execute stmt1 ;
+a b b
+1 one one
+2 two two
+3 three three
+4 four four
the join statement is:
SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
@@ -1155,7 +1156,7 @@ def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32928 0 63
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
@@ -1206,7 +1207,6 @@ 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 ;
@@ -1285,7 +1285,7 @@ set @arg00=NULL;
set @arg01=2;
execute stmt1 using @arg00, @arg01;
Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
select a,b from t1 order by a;
a b
0 two
@@ -1365,10 +1365,8 @@ 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
+prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
+execute stmt1 using @arg00;
test_sequence
------ insert tests ------
delete from t1 ;
@@ -1696,8 +1694,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@@ -1715,8 +1713,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
drop table t2;
drop table if exists t5 ;
@@ -1760,13 +1758,13 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` double(3,1) NOT NULL default '0.0',
- `param02` double default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
- `const05` binary(3) NOT NULL default '',
+ `const05` varbinary(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`param06` longtext,
@@ -1782,7 +1780,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` double default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1790,13 +1788,13 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 5 3 3 N 32769 1 63
-def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
-def test t5 t5 const03 const03 5 23 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const03 const03 5 17 1 N 32769 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8
@@ -1812,13 +1810,13 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
param01 8
const02 8.0
-param02 8
+param02 8.000000000000000000000000000000
const03 8
param03 8
const04 abc
@@ -1900,40 +1898,40 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
@@ -1947,38 +1945,38 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -1997,78 +1995,78 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2085,40 +2083,40 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
select 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
@@ -2129,38 +2127,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2175,76 +2173,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
-1 1 1 1 1 1 1 1 1 1 1 1 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
+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
set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 0 31 8
-def @arg21 254 8192 0 Y 0 31 8
-def @arg22 254 8192 0 Y 0 31 8
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 0 31 8
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 0 31 8
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 0 31 8
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 0 31 8
-def @arg31 254 8192 0 Y 0 31 8
-def @arg32 254 8192 0 Y 0 31 8
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
@@ -2555,12 +2553,12 @@ set @arg00= 9223372036854775807 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2572,18 +2570,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '9223372036854775807' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2595,18 +2593,18 @@ c7 9.22337e+18
c8 9.22337203685478e+18
c9 9.22337203685478e+18
c10 9.22337203685478e+18
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -9223372036854775808 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2624,12 +2622,12 @@ set @arg00= '-9223372036854775808' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2647,14 +2645,14 @@ set @arg00= 1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2666,7 +2664,7 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= '1.11111111111111111111e+50' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@@ -2678,8 +2676,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
c2 1
@@ -2691,20 +2689,20 @@ c7 3.40282e+38
c8 1.11111111111111e+50
c9 1.11111111111111e+50
c10 1.11111111111111e+50
-c12 99999.9999
+c12 9999.9999
execute my_delete ;
set @arg00= -1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2728,8 +2726,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
c2 -1
@@ -2801,10 +2799,10 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
41 4 41 41 41 41 41 41 41 41 41 41
42 4 42 42 42 42 42 42 42 42 42 42
43 4 43 43 43 43 43 43 43 43 43 43
-50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
-51 5 51 51 51 51 51 51 51 51 51 51
-52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
-53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+50 5 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0 50.0
+51 5 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0
+52 5 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0
+53 5 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0
54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
55 5 55 55 55 55 55 55 55 55 55 55
56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
@@ -2960,45 +2958,45 @@ Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
-Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
c1 c13 c14 c15 c16 c17
20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
diff --git a/mysql-test/r/ps_grant.result b/mysql-test/r/ps_grant.result
index f883bef8591..fdc1f97bb4c 100644
--- a/mysql-test/r/ps_grant.result
+++ b/mysql-test/r/ps_grant.result
@@ -32,19 +32,19 @@ identified by 'looser' ;
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
drop table mysqltest.t9 ;
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
prepare s_t1 from 'select a as my_col from t1' ;
execute s_t1 ;
my_col
@@ -76,3 +76,15 @@ commit ;
show grants for second_user@localhost ;
ERROR 42000: There is no such grant defined for user 'second_user' on host 'localhost'
drop database mysqltest;
+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;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index ed87e2be2b4..0efd5ac1566 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -231,7 +231,7 @@ explain extended select benchmark(1,1) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select sql_no_cache benchmark(1,1) AS `benchmark(1,1)` from test.t1
+Note 1003 select sql_no_cache benchmark(1,1) AS `benchmark(1,1)` from `test`.`t1`
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
@@ -776,6 +776,7 @@ Qcache_hits 6
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 4
+SET NAMES default;
DROP TABLE t1;
CREATE TABLE t1 (a int(1));
CREATE DATABASE mysqltest;
@@ -848,6 +849,42 @@ group_concat(a)
12345678901234567890
set group_concat_max_len=default;
drop table t1;
+create table t1 (a int);
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 18
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 6
+/**/ select * from t1;
+a
+/**/ select * from t1;
+a
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 19
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+DROP TABLE t1;
+SET GLOBAL query_cache_size=0;
+SET SESSION query_cache_type = 2;
+create table t1(a int);
+select table_name from information_schema.tables
+where table_schema="test";
+table_name
+t1
+drop table t1;
+select table_name from information_schema.tables
+where table_schema="test";
+table_name
+SET SESSION query_cache_type = 1;
set global query_cache_size=1024*1024;
flush query cache;
create table t1 ( a int );
@@ -895,6 +932,8 @@ abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba
flush query cache;
drop table t1, t2;
+set GLOBAL query_cache_size=1355776
+#;
flush status;
CREATE TABLE t1 (
`date` datetime NOT NULL default '0000-00-00 00:00:00',
@@ -906,20 +945,20 @@ SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid';
COUNT(*)
0
Warnings:
-Warning 1292 Truncated incorrect datetime value: '20050327 invalid'
-Warning 1292 Truncated incorrect datetime value: '20050327 invalid'
+Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
+Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid';
COUNT(*)
0
Warnings:
-Warning 1292 Truncated incorrect datetime value: '20050328 invalid'
-Warning 1292 Truncated incorrect datetime value: '20050328 invalid'
+Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1
+Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1
SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid';
COUNT(*)
0
Warnings:
-Warning 1292 Truncated incorrect datetime value: '20050327 invalid'
-Warning 1292 Truncated incorrect datetime value: '20050327 invalid'
+Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
+Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
@@ -982,4 +1021,109 @@ show status like "Qcache_hits";
Variable_name Value
Qcache_hits 1
drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(2);
+CREATE PROCEDURE `p1`()
+begin
+Declare c1 cursor for select a from t1;
+open c1;
+select * from t1;
+end//
+call p1()//
+a
+1
+2
+drop procedure p1;
+create function f1() returns int
+begin
+Declare var1 int;
+select max(a) from t1 into var1;
+return var1;
+end//
+create procedure `p1`()
+begin
+select a, f1() from t1;
+end//
+call p1()//
+a f1()
+1 2
+2 2
+drop procedure p1//
+drop table t1//
+flush query cache;
+reset query cache;
+flush status;
+create table t1 (s1 int)//
+create procedure f1 () begin
+select sql_cache * from t1;
+select sql_cache * from t1;
+end;//
+call f1();
+s1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+call f1();
+s1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+call f1();
+s1
+select sql_cache * from t1;
+s1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 5
+insert into t1 values (1);
+select sql_cache * from t1;
+s1
+1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 5
+call f1();
+s1
+1
+call f1();
+s1
+1
+select sql_cache * from t1;
+s1
+1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 4
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 9
+drop procedure f1;
+drop table t1;
set GLOBAL query_cache_size=0;
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index 07e96aee22b..f490c2e1383 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -218,26 +218,26 @@ drop table t1;
create table t1 (x int, y int, index(x), index(y));
insert into t1 (x) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
update t1 set y=x;
-explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 7 and t1.y+0;
+explain select * from t1, t1 t2 where t1.y = 8 and t2.x between 7 and t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
-1 SIMPLE t2 range x x 5 NULL 4 Range checked for each record (index map: 0x1)
-explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 7 and t2.x <= t1.y+0;
+1 SIMPLE t2 range x x 5 NULL 2 Using where
+explain select * from t1, t1 t2 where t1.y = 8 and t2.x >= 7 and t2.x <= t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
-1 SIMPLE t2 range x x 5 NULL 4 Using where
+1 SIMPLE t2 range x x 5 NULL 2 Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
-1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 0x1)
+1 SIMPLE t2 range x x 5 NULL 3 Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
-1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 0x1)
+1 SIMPLE t2 range x x 5 NULL 3 Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
-1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 0x1)
+1 SIMPLE t2 range x x 5 NULL 2 Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 0 and t2.x <= t1.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
@@ -247,16 +247,21 @@ id select_type table type possible_keys key key_len ref rows Extra
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 range x x 5 NULL 2 Using where; Using index
+1 SIMPLE t1 index x x 5 NULL 9 Using where; Using index
drop table t1;
CREATE TABLE t1 (key1 int(11) NOT NULL default '0', KEY i1 (key1));
-INSERT INTO t1 VALUES (0),(0),(1),(1);
+INSERT INTO t1 VALUES (0),(0),(0),(0),(0),(1),(1);
CREATE TABLE t2 (keya int(11) NOT NULL default '0', KEY j1 (keya));
INSERT INTO t2 VALUES (0),(0),(1),(1),(2),(2);
explain select * from t1, t2 where (t1.key1 <t2.keya + 1) and t2.keya=3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref j1 j1 4 const 1 Using where; Using index
-1 SIMPLE t1 ALL i1 NULL NULL NULL 4 Range checked for each record (index map: 0x1)
+1 SIMPLE t2 ref j1 j1 4 const 1 Using index
+1 SIMPLE t1 index i1 i1 4 NULL 7 Using where; Using index
+explain select * from t1 force index(i1), t2 force index(j1) where
+(t1.key1 <t2.keya + 1) and t2.keya=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref j1 j1 4 const 1 Using index
+1 SIMPLE t1 index i1 i1 4 NULL 7 Using where; Using index
DROP TABLE t1,t2;
CREATE TABLE t1 (
a int(11) default NULL,
@@ -410,13 +415,25 @@ count(*)
select count(*) from t2;
count(*)
1026
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range uid_index uid_index 4 NULL 128 Using where
+1 SIMPLE t1 range uid_index uid_index 4 NULL 112 Using where
+1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
+explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range uid_index uid_index 4 NULL 112 Using where
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid != 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range uid_index uid_index 4 NULL 129 Using where
+1 SIMPLE t1 range uid_index uid_index 4 NULL 113 Using where
+1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
+explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid != 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range uid_index uid_index 4 NULL 113 Using where
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
id name uid id name uid
@@ -504,8 +521,8 @@ select count(*) from t1 where x = 18446744073709551601;
count(*)
1
create table t2 (x bigint not null);
-insert into t2(x) values (0xfffffffffffffff0);
-insert into t2(x) values (0xfffffffffffffff1);
+insert into t2(x) values (cast(0xfffffffffffffff0+0 as signed));
+insert into t2(x) values (cast(0xfffffffffffffff1+0 as signed));
select * from t2;
x
-16
@@ -531,7 +548,7 @@ count(*)
select count(*) from t2 where x = 18446744073709551601;
count(*)
0
-drop table t1;
+drop table t1,t2;
create table t1 (x bigint unsigned not null primary key) engine=innodb;
insert into t1(x) values (0xfffffffffffffff0);
insert into t1(x) values (0xfffffffffffffff1);
@@ -627,3 +644,127 @@ SELECT count(*) FROM t1 WHERE CLIENT='000' AND (ARG1 != ' 2' OR ARG1 != ' 1');
count(*)
4
drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+status varchar(20),
+PRIMARY KEY (id),
+KEY (status)
+);
+INSERT INTO t1 VALUES
+(1,'B'), (2,'B'), (3,'B'), (4,'B'), (5,'B'), (6,'B'),
+(7,'B'), (8,'B'), (9,'B'), (10,'B'), (11,'B'), (12,'B'),
+(13,'B'), (14,'B'), (15,'B'), (16,'B'), (17,'B'), (18,'B'),
+(19,'B'), (20,'B'), (21,'B'), (22,'B'), (23,'B'), (24,'B'),
+(25,'A'), (26,'A'), (27,'A'), (28,'A'), (29,'A'), (30,'A'),
+(31,'A'), (32,'A'), (33,'A'), (34,'A'), (35,'A'), (36,'A'),
+(37,'A'), (38,'A'), (39,'A'), (40,'A'), (41,'A'), (42,'A'),
+(43,'A'), (44,'A'), (45,'A'), (46,'A'), (47,'A'), (48,'A'),
+(49,'A'), (50,'A'), (51,'A'), (52,'A'), (53,'C'), (54,'C'),
+(55,'C'), (56,'C'), (57,'C'), (58,'C'), (59,'C'), (60,'C');
+EXPLAIN SELECT * FROM t1 WHERE status <> 'A' AND status <> 'B';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range status status 23 NULL 11 Using where
+EXPLAIN SELECT * FROM t1 WHERE status NOT IN ('A','B');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range status status 23 NULL 11 Using where
+SELECT * FROM t1 WHERE status <> 'A' AND status <> 'B';
+id status
+53 C
+54 C
+55 C
+56 C
+57 C
+58 C
+59 C
+60 C
+SELECT * FROM t1 WHERE status NOT IN ('A','B');
+id status
+53 C
+54 C
+55 C
+56 C
+57 C
+58 C
+59 C
+60 C
+EXPLAIN SELECT status FROM t1 WHERE status <> 'A' AND status <> 'B';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range status status 23 NULL 11 Using where; Using index
+EXPLAIN SELECT status FROM t1 WHERE status NOT IN ('A','B');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range status status 23 NULL 11 Using where; Using index
+EXPLAIN SELECT * FROM t1 WHERE status NOT BETWEEN 'A' AND 'B';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range status status 23 NULL 10 Using where
+EXPLAIN SELECT * FROM t1 WHERE status < 'A' OR status > 'B';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range status status 23 NULL 10 Using where
+SELECT * FROM t1 WHERE status NOT BETWEEN 'A' AND 'B';
+id status
+53 C
+54 C
+55 C
+56 C
+57 C
+58 C
+59 C
+60 C
+SELECT * FROM t1 WHERE status < 'A' OR status > 'B';
+id status
+53 C
+54 C
+55 C
+56 C
+57 C
+58 C
+59 C
+60 C
+DROP TABLE t1;
+CREATE TABLE t1 (a int, b int, primary key(a,b));
+INSERT INTO t1 VALUES
+(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3);
+CREATE VIEW v1 as SELECT a,b FROM t1 WHERE b=3;
+EXPLAIN SELECT a,b FROM t1 WHERE a < 2 and b=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index
+EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index
+EXPLAIN SELECT a,b FROM t1 WHERE a < 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index
+EXPLAIN SELECT a,b FROM v1 WHERE a < 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index
+SELECT a,b FROM t1 WHERE a < 2 and b=3;
+a b
+1 3
+SELECT a,b FROM v1 WHERE a < 2 and b=3;
+a b
+1 3
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (name varchar(15) NOT NULL, KEY idx(name));
+INSERT INTO t1 VALUES ('Betty'), ('Anna');
+SELECT * FROM t1;
+name
+Anna
+Betty
+DELETE FROM t1 WHERE name NOT LIKE 'A%a';
+SELECT * FROM t1;
+name
+Anna
+DROP TABLE t1;
+CREATE TABLE t1 (a int, KEY idx(a));
+INSERT INTO t1 VALUES (NULL), (1), (2), (3);
+SELECT * FROM t1;
+a
+NULL
+1
+2
+3
+DELETE FROM t1 WHERE NOT(a <=> 2);
+SELECT * FROM t1;
+a
+2
+DROP TABLE t1;
diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result
index dbca5c39a6c..d8fa4dbbb72 100644
--- a/mysql-test/r/repair.result
+++ b/mysql-test/r/repair.result
@@ -27,11 +27,15 @@ drop table t1;
repair table t1 use_frm;
Table Op Msg_type Msg_text
test.t1 repair error Table 'test.t1' doesn't exist
+Warnings:
+Error 1146 Table 'test.t1' doesn't exist
create table t1 engine=myisam SELECT 1,"table 1";
flush tables;
repair table t1;
Table Op Msg_type Msg_text
-test.t1 repair error Can't open file: 't1.MYI' (errno: 130)
+test.t1 repair error Incorrect file format 't1'
+Warnings:
+Error 130 Incorrect file format 't1'
repair table t1 use_frm;
Table Op Msg_type Msg_text
test.t1 repair warning Number of rows changed from 0 to 1
diff --git a/mysql-test/r/replace.result b/mysql-test/r/replace.result
index 83cde76215a..a7d59fcfa62 100644
--- a/mysql-test/r/replace.result
+++ b/mysql-test/r/replace.result
@@ -3,12 +3,10 @@ CREATE TABLE t1 (
gesuchnr int(11) DEFAULT '0' NOT NULL,
benutzer_id int(11) DEFAULT '0' NOT NULL,
PRIMARY KEY (gesuchnr,benutzer_id)
-) engine=ISAM;
+);
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);
-alter table t1 engine=myisam;
-replace into t1 (gesuchnr,benutzer_id) values (1,1);
alter table t1 engine=heap;
replace into t1 (gesuchnr,benutzer_id) values (1,1);
drop table t1;
diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result
index 76d6fa13766..1762587415d 100644
--- a/mysql-test/r/row.result
+++ b/mysql-test/r/row.result
@@ -14,12 +14,17 @@ row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3))
select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'));
row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'))
1
-select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
-row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3))
-1
+Warnings:
+Warning 1292 Truncated incorrect DECIMAL value: 'a'
+Warning 1292 Truncated incorrect INTEGER value: 'a'
select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3));
row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3))
1
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'a'
+select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
+row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3))
+1
select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3))
1
@@ -53,7 +58,7 @@ SELECT (1,2,3)=(1,NULL,3);
NULL
SELECT (1,2,3)=(1,NULL,0);
(1,2,3)=(1,NULL,0)
-NULL
+0
SELECT ROW(1,2,3)=ROW(1,2,3);
ROW(1,2,3)=ROW(1,2,3)
1
@@ -170,3 +175,9 @@ ROW(2,10) <=> ROW(3,4)
SELECT ROW(NULL,10) <=> ROW(3,NULL);
ROW(NULL,10) <=> ROW(3,NULL)
0
+SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ;
+1 0 0 0 null
+1 0 0 0 NULL
+select row(NULL,1)=(2,0);
+row(NULL,1)=(2,0)
+0
diff --git a/mysql-test/r/rowid_order_bdb.result b/mysql-test/r/rowid_order_bdb.result
new file mode 100644
index 00000000000..bbdc6f6ff77
--- /dev/null
+++ b/mysql-test/r/rowid_order_bdb.result
@@ -0,0 +1,186 @@
+drop table if exists t1, t2, t3,t4;
+create table t1 (
+pk1 int not NULL,
+key1 int(11),
+key2 int(11),
+PRIMARY KEY (pk1),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=bdb;
+insert into t1 values (-5, 1, 1),
+(-100, 1, 1),
+(3, 1, 1),
+(0, 1, 1),
+(10, 1, 1);
+explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 5 Using sort_union(key1,key2); Using where
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 key1 key2
+-100 1 1
+-5 1 1
+0 1 1
+3 1 1
+10 1 1
+drop table t1;
+create table t1 (
+pk1 int unsigned not NULL,
+key1 int(11),
+key2 int(11),
+PRIMARY KEY (pk1),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=bdb;
+insert into t1 values (0, 1, 1),
+(0xFFFFFFFF, 1, 1),
+(0xFFFFFFFE, 1, 1),
+(1, 1, 1),
+(2, 1, 1);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 key1 key2
+0 1 1
+1 1 1
+2 1 1
+4294967294 1 1
+4294967295 1 1
+drop table t1;
+create table t1 (
+pk1 char(4) not NULL,
+key1 int(11),
+key2 int(11),
+PRIMARY KEY (pk1),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=bdb collate latin2_general_ci;
+insert into t1 values ('a1', 1, 1),
+('b2', 1, 1),
+('A3', 1, 1),
+('B4', 1, 1);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 key1 key2
+a1 1 1
+A3 1 1
+b2 1 1
+B4 1 1
+drop table t1;
+create table t1 (
+pk1 int not NULL,
+pk2 char(4) not NULL collate latin1_german1_ci,
+pk3 char(4) not NULL collate latin1_bin,
+key1 int(11),
+key2 int(11),
+PRIMARY KEY (pk1,pk2,pk3),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=bdb;
+insert into t1 values
+(1, 'u', 'u', 1, 1),
+(1, 'u', char(0xEC), 1, 1),
+(1, 'u', 'x', 1, 1);
+insert ignore into t1 select pk1, char(0xEC), pk3, key1, key2 from t1;
+insert ignore into t1 select pk1, 'x', pk3, key1, key2 from t1 where pk2='u';
+insert ignore into t1 select 2, pk2, pk3, key1, key2 from t1;
+select * from t1;
+pk1 pk2 pk3 key1 key2
+1 ì u 1 1
+1 ì x 1 1
+1 ì ì 1 1
+1 u u 1 1
+1 u x 1 1
+1 u ì 1 1
+1 x u 1 1
+1 x x 1 1
+1 x ì 1 1
+2 ì u 1 1
+2 ì x 1 1
+2 ì ì 1 1
+2 u u 1 1
+2 u x 1 1
+2 u ì 1 1
+2 x u 1 1
+2 x x 1 1
+2 x ì 1 1
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 pk2 pk3 key1 key2
+1 ì u 1 1
+1 ì x 1 1
+1 ì ì 1 1
+1 u u 1 1
+1 u x 1 1
+1 u ì 1 1
+1 x u 1 1
+1 x x 1 1
+1 x ì 1 1
+2 ì u 1 1
+2 ì x 1 1
+2 ì ì 1 1
+2 u u 1 1
+2 u x 1 1
+2 u ì 1 1
+2 x u 1 1
+2 x x 1 1
+2 x ì 1 1
+alter table t1 drop primary key;
+select * from t1;
+pk1 pk2 pk3 key1 key2
+1 ì u 1 1
+1 ì x 1 1
+1 ì ì 1 1
+1 u u 1 1
+1 u x 1 1
+1 u ì 1 1
+1 x u 1 1
+1 x x 1 1
+1 x ì 1 1
+2 ì u 1 1
+2 ì x 1 1
+2 ì ì 1 1
+2 u u 1 1
+2 u x 1 1
+2 u ì 1 1
+2 x u 1 1
+2 x x 1 1
+2 x ì 1 1
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 pk2 pk3 key1 key2
+1 ì u 1 1
+1 ì x 1 1
+1 ì ì 1 1
+1 u u 1 1
+1 u x 1 1
+1 u ì 1 1
+1 x u 1 1
+1 x x 1 1
+1 x ì 1 1
+2 ì u 1 1
+2 ì x 1 1
+2 ì ì 1 1
+2 u u 1 1
+2 u x 1 1
+2 u ì 1 1
+2 x u 1 1
+2 x x 1 1
+2 x ì 1 1
+drop table t1;
+create table t1 (
+pk1 varchar(8) NOT NULL default '',
+pk2 varchar(4) NOT NULL default '',
+key1 int(11),
+key2 int(11),
+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;
diff --git a/mysql-test/r/rowid_order_innodb.result b/mysql-test/r/rowid_order_innodb.result
new file mode 100644
index 00000000000..d55029f9064
--- /dev/null
+++ b/mysql-test/r/rowid_order_innodb.result
@@ -0,0 +1,186 @@
+drop table if exists t1, t2, t3,t4;
+create table t1 (
+pk1 int not NULL,
+key1 int(11),
+key2 int(11),
+PRIMARY KEY (pk1),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=innodb;
+insert into t1 values (-5, 1, 1),
+(-100, 1, 1),
+(3, 1, 1),
+(0, 1, 1),
+(10, 1, 1);
+explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 4 Using sort_union(key1,key2); Using where
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 key1 key2
+-100 1 1
+-5 1 1
+0 1 1
+3 1 1
+10 1 1
+drop table t1;
+create table t1 (
+pk1 int unsigned not NULL,
+key1 int(11),
+key2 int(11),
+PRIMARY KEY (pk1),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=innodb;
+insert into t1 values (0, 1, 1),
+(0xFFFFFFFF, 1, 1),
+(0xFFFFFFFE, 1, 1),
+(1, 1, 1),
+(2, 1, 1);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 key1 key2
+0 1 1
+1 1 1
+2 1 1
+4294967294 1 1
+4294967295 1 1
+drop table t1;
+create table t1 (
+pk1 char(4) not NULL,
+key1 int(11),
+key2 int(11),
+PRIMARY KEY (pk1),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=innodb collate latin2_general_ci;
+insert into t1 values ('a1', 1, 1),
+('b2', 1, 1),
+('A3', 1, 1),
+('B4', 1, 1);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 key1 key2
+a1 1 1
+A3 1 1
+b2 1 1
+B4 1 1
+drop table t1;
+create table t1 (
+pk1 int not NULL,
+pk2 char(4) not NULL collate latin1_german1_ci,
+pk3 char(4) not NULL collate latin1_bin,
+key1 int(11),
+key2 int(11),
+PRIMARY KEY (pk1,pk2,pk3),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=innodb;
+insert into t1 values
+(1, 'u', 'u', 1, 1),
+(1, 'u', char(0xEC), 1, 1),
+(1, 'u', 'x', 1, 1);
+insert ignore into t1 select pk1, char(0xEC), pk3, key1, key2 from t1;
+insert ignore into t1 select pk1, 'x', pk3, key1, key2 from t1 where pk2='u';
+insert ignore into t1 select 2, pk2, pk3, key1, key2 from t1;
+select * from t1;
+pk1 pk2 pk3 key1 key2
+1 ì u 1 1
+1 ì x 1 1
+1 ì ì 1 1
+1 u u 1 1
+1 u x 1 1
+1 u ì 1 1
+1 x u 1 1
+1 x x 1 1
+1 x ì 1 1
+2 ì u 1 1
+2 ì x 1 1
+2 ì ì 1 1
+2 u u 1 1
+2 u x 1 1
+2 u ì 1 1
+2 x u 1 1
+2 x x 1 1
+2 x ì 1 1
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 pk2 pk3 key1 key2
+1 ì u 1 1
+1 ì x 1 1
+1 ì ì 1 1
+1 u u 1 1
+1 u x 1 1
+1 u ì 1 1
+1 x u 1 1
+1 x x 1 1
+1 x ì 1 1
+2 ì u 1 1
+2 ì x 1 1
+2 ì ì 1 1
+2 u u 1 1
+2 u x 1 1
+2 u ì 1 1
+2 x u 1 1
+2 x x 1 1
+2 x ì 1 1
+alter table t1 drop primary key;
+select * from t1;
+pk1 pk2 pk3 key1 key2
+1 ì u 1 1
+1 ì x 1 1
+1 ì ì 1 1
+1 u u 1 1
+1 u x 1 1
+1 u ì 1 1
+1 x u 1 1
+1 x x 1 1
+1 x ì 1 1
+2 ì u 1 1
+2 ì x 1 1
+2 ì ì 1 1
+2 u u 1 1
+2 u x 1 1
+2 u ì 1 1
+2 x u 1 1
+2 x x 1 1
+2 x ì 1 1
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+pk1 pk2 pk3 key1 key2
+1 ì u 1 1
+1 ì x 1 1
+1 ì ì 1 1
+1 u u 1 1
+1 u x 1 1
+1 u ì 1 1
+1 x u 1 1
+1 x x 1 1
+1 x ì 1 1
+2 ì u 1 1
+2 ì x 1 1
+2 ì ì 1 1
+2 u u 1 1
+2 u x 1 1
+2 u ì 1 1
+2 x u 1 1
+2 x x 1 1
+2 x ì 1 1
+drop table t1;
+create table t1 (
+pk1 varchar(8) NOT NULL default '',
+pk2 varchar(4) NOT NULL default '',
+key1 int(11),
+key2 int(11),
+primary key(pk1, pk2),
+KEY key1 (key1),
+KEY key2 (key2)
+) engine=innodb;
+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
+a a--a 2 2
+bb b--b 2 2
+ccc c--c 2 2
+dddd d--d 2 2
+ empt 2 2
+drop table t1;
diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result
index eef986d8f8c..450e728090e 100644
--- a/mysql-test/r/rpl000001.result
+++ b/mysql-test/r/rpl000001.result
@@ -33,27 +33,12 @@ select sum(length(word)) from t1;
sum(length(word))
1022
drop table t1,t3;
+create table t1 (n int) engine=myisam;
reset master;
stop slave;
reset slave;
-create table t1(n int);
-select get_lock("hold_slave",10);
-get_lock("hold_slave",10)
-1
-explain extended select get_lock("hold_slave",10);
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-Warnings:
-Note 1003 select sql_no_cache get_lock(_latin1'hold_slave',10) AS `get_lock("hold_slave",10)`
+lock tables t1 read;
start slave;
-select release_lock("hold_slave");
-release_lock("hold_slave")
-1
-explain extended select release_lock("hold_slave");
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-Warnings:
-Note 1003 select sql_no_cache release_lock(_latin1'hold_slave') AS `release_lock("hold_slave")`
unlock tables;
create table t2(id int);
insert into t2 values(connection_id());
@@ -76,6 +61,10 @@ create table t1 (n int);
insert into t1 values(3456);
insert into mysql.user (Host, User, Password)
VALUES ("10.10.10.%", "blafasel2", password("blafasel2"));
+Warnings:
+Warning 1364 Field 'ssl_cipher' doesn't have a default value
+Warning 1364 Field 'x509_issuer' doesn't have a default value
+Warning 1364 Field 'x509_subject' doesn't have a default value
select select_priv,user from mysql.user where user = _binary'blafasel2';
select_priv user
N blafasel2
diff --git a/mysql-test/r/rpl000009.result b/mysql-test/r/rpl000009.result
index bb82dcb1e6a..a4dbf54f39b 100644
--- a/mysql-test/r/rpl000009.result
+++ b/mysql-test/r/rpl000009.result
@@ -32,6 +32,7 @@ create database mysqltest2;
create database mysqltest;
show databases;
Database
+information_schema
mysql
mysqltest
mysqltest2
@@ -48,6 +49,7 @@ insert into mysqltest.t2 values (11, 'eleven test'), (12, 'twelve test'),
set sql_log_bin = 1;
show databases;
Database
+information_schema
mysql
test
create database mysqltest2;
@@ -66,6 +68,7 @@ insert into mysqltest.t3 values (1, 'original bar.t3');
load data from master;
show databases;
Database
+information_schema
mysql
mysqltest
mysqltest2
diff --git a/mysql-test/r/rpl000015.result b/mysql-test/r/rpl000015.result
index 8cbbe3ab0e8..e33201ced93 100644
--- a/mysql-test/r/rpl000015.result
+++ b/mysql-test/r/rpl000015.result
@@ -1,23 +1,23 @@
reset master;
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000001 79
+master-bin.000001 98
reset slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
change master to master_host='127.0.0.1';
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 test MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No #
+# 127.0.0.1 test MASTER_PORT 7 4 # # No No 0 0 0 # None 0 No #
change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=MASTER_PORT;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 7 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No #
+# 127.0.0.1 root MASTER_PORT 7 4 # # No No 0 0 0 # None 0 No #
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 7 master-bin.000001 79 slave-relay-bin.000001 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No #
+# 127.0.0.1 root MASTER_PORT 7 master-bin.000001 98 # # master-bin.000001 Yes Yes 0 0 98 # None 0 No #
drop table if exists t1;
create table t1 (n int);
insert into t1 values (10),(45),(90);
diff --git a/mysql-test/r/rpl_EE_error.result b/mysql-test/r/rpl_EE_error.result
index 49ad4832c81..f4765b4b13c 100644
--- a/mysql-test/r/rpl_EE_error.result
+++ b/mysql-test/r/rpl_EE_error.result
@@ -6,7 +6,9 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
create table t1 (a int) engine=myisam;
flush tables;
-drop table t1;
+drop table if exists t1;
+Warnings:
+Error 2 Can't find file: 't1' (errno: 2)
create table t1 (a int, unique(a)) engine=myisam;
set sql_log_bin=0;
insert into t1 values(2);
diff --git a/mysql-test/r/rpl_auto_increment.result b/mysql-test/r/rpl_auto_increment.result
new file mode 100644
index 00000000000..9eca51ad2d9
--- /dev/null
+++ b/mysql-test/r/rpl_auto_increment.result
@@ -0,0 +1,185 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table t1 (a int not null auto_increment,b int, primary key (a)) engine=myisam auto_increment=3;
+insert into t1 values (NULL,1),(NULL,2),(NULL,3);
+select * from t1;
+a b
+12 1
+22 2
+32 3
+select * from t1;
+a b
+12 1
+22 2
+32 3
+drop table t1;
+create table t1 (a int not null auto_increment,b int, primary key (a)) engine=myisam;
+insert into t1 values (1,1),(NULL,2),(3,3),(NULL,4);
+delete from t1 where b=4;
+insert into t1 values (NULL,5),(NULL,6);
+select * from t1;
+a b
+1 1
+2 2
+3 3
+22 5
+32 6
+select * from t1;
+a b
+1 1
+2 2
+3 3
+22 5
+32 6
+drop table t1;
+set @@session.auto_increment_increment=100, @@session.auto_increment_offset=10;
+show variables like "%auto_inc%";
+Variable_name Value
+auto_increment_increment 100
+auto_increment_offset 10
+create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
+insert into t1 values (NULL),(5),(NULL);
+insert into t1 values (250),(NULL);
+select * from t1;
+a
+5
+10
+110
+250
+310
+insert into t1 values (1000);
+set @@insert_id=400;
+insert into t1 values(NULL),(NULL);
+select * from t1;
+a
+5
+10
+110
+250
+310
+400
+410
+1000
+select * from t1;
+a
+5
+10
+110
+250
+310
+400
+410
+1000
+drop table t1;
+create table t1 (a int not null auto_increment, primary key (a)) engine=innodb;
+insert into t1 values (NULL),(5),(NULL);
+insert into t1 values (250),(NULL);
+select * from t1;
+a
+5
+10
+110
+250
+310
+insert into t1 values (1000);
+set @@insert_id=400;
+insert into t1 values(NULL),(NULL);
+select * from t1;
+a
+5
+10
+110
+250
+310
+400
+410
+1000
+select * from t1;
+a
+5
+10
+110
+250
+310
+400
+410
+1000
+drop table t1;
+set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
+create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
+insert into t1 values (NULL),(5),(NULL),(NULL);
+insert into t1 values (500),(NULL),(502),(NULL),(NULL);
+select * from t1;
+a
+1
+5
+6
+7
+500
+501
+502
+503
+504
+set @@insert_id=600;
+insert into t1 values(600),(NULL),(NULL);
+ERROR 23000: Duplicate entry '600' for key 1
+set @@insert_id=600;
+insert ignore into t1 values(600),(NULL),(NULL),(610),(NULL);
+select * from t1;
+a
+1
+5
+6
+7
+500
+501
+502
+503
+504
+600
+610
+611
+select * from t1;
+a
+1
+5
+6
+7
+500
+501
+502
+503
+504
+600
+610
+611
+drop table t1;
+set @@session.auto_increment_increment=10, @@session.auto_increment_offset=1;
+create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
+insert into t1 values(2),(12),(22),(32),(42);
+insert into t1 values (NULL),(NULL);
+insert into t1 values (3),(NULL),(NULL);
+select * from t1;
+a
+1
+3
+11
+21
+31
+select * from t1;
+a
+1
+2
+3
+11
+12
+21
+22
+31
+32
+42
+drop table t1;
diff --git a/mysql-test/r/rpl_change_master.result b/mysql-test/r/rpl_change_master.result
index a6342d47b49..7f2ba568fb3 100644
--- a/mysql-test/r/rpl_change_master.result
+++ b/mysql-test/r/rpl_change_master.result
@@ -4,26 +4,20 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
-select get_lock("a",5);
-get_lock("a",5)
-1
create table t1(n int);
-insert into t1 values(1+get_lock("a",15)*0);
-insert into t1 values(2);
-stop slave;
select * from t1;
n
-1
+stop slave sql_thread;
+insert into t1 values(1);
+insert into t1 values(2);
+stop slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 273 slave-relay-bin.000002 258 master-bin.000001 No No 0 0 214 317 None 0 No #
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 357 # # master-bin.000001 No No 0 0 183 # None 0 No #
change master to master_user='root';
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 214 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 214 4 None 0 No #
-select release_lock("a");
-release_lock("a")
-1
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 183 # # master-bin.000001 No No 0 0 183 # None 0 No #
start slave;
select * from t1;
n
diff --git a/mysql-test/r/rpl_charset.result b/mysql-test/r/rpl_charset.result
index 292cfb19175..b27acc0972e 100644
--- a/mysql-test/r/rpl_charset.result
+++ b/mysql-test/r/rpl_charset.result
@@ -4,6 +4,7 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
+set timestamp=1000000000;
drop database if exists mysqltest2;
drop database if exists mysqltest3;
create database mysqltest2 character set latin2;
@@ -87,7 +88,6 @@ a b
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));
@@ -103,68 +103,44 @@ a b
1 cp850_general_ci
drop database mysqltest2;
drop database mysqltest3;
-show binlog events from 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 79 Query 1 79 drop database if exists mysqltest2
-master-bin.000001 154 Query 1 154 drop database if exists mysqltest3
-master-bin.000001 229 Query 1 229 create database mysqltest2 character set latin2
-master-bin.000001 317 Query 1 317 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=30
-master-bin.000001 451 Query 1 451 create database mysqltest3
-master-bin.000001 518 Query 1 518 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=64
-master-bin.000001 652 Query 1 652 drop database mysqltest3
-master-bin.000001 717 Query 1 717 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=64
-master-bin.000001 851 Query 1 851 create database mysqltest3
-master-bin.000001 918 Query 1 918 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 1058 Query 1 1058 use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100))
-master-bin.000001 1165 Query 1 1165 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 1306 Intvar 1 1306 INSERT_ID=1
-master-bin.000001 1334 Query 1 1334 use `mysqltest2`; insert into t1 (b) values(@@character_set_server)
-master-bin.000001 1424 Query 1 1424 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 1565 Intvar 1 1565 INSERT_ID=2
-master-bin.000001 1593 Query 1 1593 use `mysqltest2`; insert into t1 (b) values(@@collation_server)
-master-bin.000001 1679 Query 1 1679 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 1820 Intvar 1 1820 INSERT_ID=3
-master-bin.000001 1848 Query 1 1848 use `mysqltest2`; insert into t1 (b) values(@@character_set_client)
-master-bin.000001 1938 Query 1 1938 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 2079 Intvar 1 2079 INSERT_ID=4
-master-bin.000001 2107 Query 1 2107 use `mysqltest2`; insert into t1 (b) values(@@character_set_connection)
-master-bin.000001 2201 Query 1 2201 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 2342 Intvar 1 2342 INSERT_ID=5
-master-bin.000001 2370 Query 1 2370 use `mysqltest2`; insert into t1 (b) values(@@collation_connection)
-master-bin.000001 2460 Query 1 2460 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=5,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 2600 Query 1 2600 use `mysqltest2`; truncate table t1
-master-bin.000001 2658 Query 1 2658 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=5,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 2798 Intvar 1 2798 INSERT_ID=1
-master-bin.000001 2826 Query 1 2826 use `mysqltest2`; insert into t1 (b) values(@@collation_connection)
-master-bin.000001 2916 Query 1 2916 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=5,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 3056 Intvar 1 3056 INSERT_ID=2
-master-bin.000001 3084 Query 1 3084 use `mysqltest2`; insert into t1 (b) values(LEAST("Müller","Muffler"))
-master-bin.000001 3177 Query 1 3177 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 3318 Intvar 1 3318 INSERT_ID=3
-master-bin.000001 3346 Query 1 3346 use `mysqltest2`; insert into t1 (b) values(@@collation_connection)
-master-bin.000001 3436 Query 1 3436 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 3577 Intvar 1 3577 INSERT_ID=4
-master-bin.000001 3605 Query 1 3605 use `mysqltest2`; insert into t1 (b) values(LEAST("Müller","Muffler"))
-master-bin.000001 3698 Query 1 3698 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 3839 Intvar 1 3839 INSERT_ID=74
-master-bin.000001 3867 Create_file 1 3867 db=mysqltest2;table=t1;file_id=1;block_len=581
-master-bin.000001 4540 Query 1 4540 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 4681 Intvar 1 4681 INSERT_ID=5
-master-bin.000001 4709 Exec_load 1 4709 ;file_id=1
-master-bin.000001 4732 Query 1 4732 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 4873 Query 1 4873 use `mysqltest2`; truncate table t1
-master-bin.000001 4931 Query 1 4931 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 5072 Intvar 1 5072 INSERT_ID=1
-master-bin.000001 5100 User var 1 5100 @`a`=_cp850 0x4DFC6C6C6572 COLLATE cp850_general_ci
-master-bin.000001 5140 Query 1 5140 use `mysqltest2`; insert into t1 (b) values(collation(@a))
-master-bin.000001 5221 Query 1 5221 use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 5362 Query 1 5362 drop database mysqltest2
-master-bin.000001 5427 Query 1 5427 SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 5558 Query 1 5558 drop database mysqltest3
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # drop database if exists mysqltest2
+master-bin.000001 # Query 1 # drop database if exists mysqltest3
+master-bin.000001 # Query 1 # create database mysqltest2 character set latin2
+master-bin.000001 # Query 1 # create database mysqltest3
+master-bin.000001 # Query 1 # drop database mysqltest3
+master-bin.000001 # Query 1 # create database mysqltest3
+master-bin.000001 # Query 1 # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100))
+master-bin.000001 # Intvar 1 # INSERT_ID=1
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(@@character_set_server)
+master-bin.000001 # Intvar 1 # INSERT_ID=2
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(@@collation_server)
+master-bin.000001 # Intvar 1 # INSERT_ID=3
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(@@character_set_client)
+master-bin.000001 # Intvar 1 # INSERT_ID=4
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(@@character_set_connection)
+master-bin.000001 # Intvar 1 # INSERT_ID=5
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(@@collation_connection)
+master-bin.000001 # Query 1 # use `mysqltest2`; truncate table t1
+master-bin.000001 # Intvar 1 # INSERT_ID=1
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(@@collation_connection)
+master-bin.000001 # Intvar 1 # INSERT_ID=2
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(LEAST("Müller","Muffler"))
+master-bin.000001 # Intvar 1 # INSERT_ID=3
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(@@collation_connection)
+master-bin.000001 # Intvar 1 # INSERT_ID=4
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(LEAST("Müller","Muffler"))
+master-bin.000001 # Query 1 # use `mysqltest2`; truncate table t1
+master-bin.000001 # Intvar 1 # INSERT_ID=1
+master-bin.000001 # User var 1 # @`a`=_cp850 0x4DFC6C6C6572 COLLATE cp850_general_ci
+master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(collation(@a))
+master-bin.000001 # Query 1 # drop database mysqltest2
+master-bin.000001 # Query 1 # drop database mysqltest3
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=latin1;
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=latin1;
set one_shot @@character_set_server=latin5;
set @@max_join_size=1000;
select @@character_set_server;
@@ -181,7 +157,7 @@ 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
+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;
@@ -198,14 +174,80 @@ CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
select hex(c1), hex(c2) from t1;
hex(c1) hex(c2)
CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
-stop slave;
-delete from t1;
-change master to master_log_pos=5847;
-start slave until master_log_file='master-bin.000001', master_log_pos=5983;
-start slave;
-select hex(c1), hex(c2) from t1;
-hex(c1) hex(c2)
-CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
+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 @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
+drop database if exists mysqltest2;
+SET TIMESTAMP=1000000000;
+drop database if exists mysqltest3;
+SET TIMESTAMP=1000000000;
+create database mysqltest2 character set latin2;
+SET TIMESTAMP=1000000000;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=30;
+create database mysqltest3;
+SET TIMESTAMP=1000000000;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=64;
+drop database mysqltest3;
+SET TIMESTAMP=1000000000;
+create database mysqltest3;
+use mysqltest2;
+SET TIMESTAMP=1000000000;
+create table t1 (a int auto_increment primary key, b varchar(100));
+SET INSERT_ID=1;
+SET TIMESTAMP=1000000000;
+SET @@session.character_set_client=4,@@session.collation_connection=27,@@session.collation_server=64;
+insert into t1 (b) values(@@character_set_server);
+SET INSERT_ID=2;
+SET TIMESTAMP=1000000000;
+insert into t1 (b) values(@@collation_server);
+SET INSERT_ID=3;
+SET TIMESTAMP=1000000000;
+insert into t1 (b) values(@@character_set_client);
+SET INSERT_ID=4;
+SET TIMESTAMP=1000000000;
+insert into t1 (b) values(@@character_set_connection);
+SET INSERT_ID=5;
+SET TIMESTAMP=1000000000;
+insert into t1 (b) values(@@collation_connection);
+SET TIMESTAMP=1000000000;
+SET @@session.character_set_client=8,@@session.collation_connection=5,@@session.collation_server=64;
+truncate table t1;
+SET INSERT_ID=1;
+SET TIMESTAMP=1000000000;
+insert into t1 (b) values(@@collation_connection);
+SET INSERT_ID=2;
+SET TIMESTAMP=1000000000;
+insert into t1 (b) values(LEAST("Müller","Muffler"));
+SET INSERT_ID=3;
+SET TIMESTAMP=1000000000;
+SET @@session.character_set_client=8,@@session.collation_connection=31,@@session.collation_server=64;
+insert into t1 (b) values(@@collation_connection);
+SET INSERT_ID=4;
+SET TIMESTAMP=1000000000;
+insert into t1 (b) values(LEAST("Müller","Muffler"));
+SET TIMESTAMP=1000000000;
+truncate table t1;
+SET INSERT_ID=1;
+SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`;
+SET TIMESTAMP=1000000000;
+insert into t1 (b) values(collation(@a));
+SET TIMESTAMP=1000000000;
+drop database mysqltest2;
+SET TIMESTAMP=1000000000;
+drop database mysqltest3;
+use test;
+SET TIMESTAMP=1000000000;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=30;
+CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255));
+SET TIMESTAMP=1000000000;
+SET @@session.character_set_client=7,@@session.collation_connection=51,@@session.collation_server=30;
+INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ');
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
drop table t1;
create table `t1` (
`pk` varchar(10) not null default '',
diff --git a/mysql-test/r/rpl_create_database.result b/mysql-test/r/rpl_create_database.result
index 2375e13bb5c..ca4585d0d8d 100644
--- a/mysql-test/r/rpl_create_database.result
+++ b/mysql-test/r/rpl_create_database.result
@@ -22,6 +22,7 @@ USE mysqltest_sisyfos;
ALTER DATABASE mysqltest_bob CHARACTER SET latin1;
SHOW DATABASES;
Database
+information_schema
mysql
mysqltest_bob
mysqltest_prometheus
@@ -29,6 +30,7 @@ mysqltest_sisyfos
test
SHOW DATABASES;
Database
+information_schema
mysql
mysqltest_prometheus
mysqltest_sisyfos
@@ -41,22 +43,23 @@ CREATE DATABASE mysqltest_sisyfos;
USE mysqltest_sisyfos;
CREATE TABLE t2 (a INT);
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 DROP DATABASE IF EXISTS mysqltest_prometheus
-master-bin.000001 174 Query 1 174 DROP DATABASE IF EXISTS mysqltest_sisyfos
-master-bin.000001 263 Query 1 263 CREATE DATABASE mysqltest_prometheus
-master-bin.000001 350 Query 1 350 CREATE DATABASE mysqltest_sisyfos
-master-bin.000001 431 Query 1 431 use `mysqltest_sisyfos`; CREATE TABLE t1 (b int)
-master-bin.000001 502 Query 1 502 use `mysqltest_sisyfos`; INSERT INTO t1 VALUES(1)
-master-bin.000001 574 Query 1 574 ALTER DATABASE mysqltest_sisyfos CHARACTER SET latin1
-master-bin.000001 675 Query 1 675 DROP DATABASE IF EXISTS mysqltest_sisyfos
-master-bin.000001 764 Query 1 764 use `mysqltest_prometheus`; CREATE TABLE t1 (a INT)
-master-bin.000001 838 Query 1 838 use `mysqltest_prometheus`; INSERT INTO t1 VALUES (1)
-master-bin.000001 914 Query 1 914 CREATE DATABASE mysqltest_sisyfos
-master-bin.000001 995 Query 1 995 use `mysqltest_sisyfos`; CREATE TABLE t2 (a INT)
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS mysqltest_prometheus
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS mysqltest_sisyfos
+master-bin.000001 # Query 1 # CREATE DATABASE mysqltest_prometheus
+master-bin.000001 # Query 1 # CREATE DATABASE mysqltest_sisyfos
+master-bin.000001 # Query 1 # use `mysqltest_sisyfos`; CREATE TABLE t1 (b int)
+master-bin.000001 # Query 1 # use `mysqltest_sisyfos`; INSERT INTO t1 VALUES(1)
+master-bin.000001 # Query 1 # ALTER DATABASE mysqltest_sisyfos CHARACTER SET latin1
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS mysqltest_sisyfos
+master-bin.000001 # Query 1 # use `mysqltest_prometheus`; CREATE TABLE t1 (a INT)
+master-bin.000001 # Query 1 # use `mysqltest_prometheus`; INSERT INTO t1 VALUES (1)
+master-bin.000001 # Query 1 # CREATE DATABASE mysqltest_sisyfos
+master-bin.000001 # Query 1 # use `mysqltest_sisyfos`; CREATE TABLE t2 (a INT)
SHOW DATABASES;
Database
+information_schema
mysql
mysqltest_bob
mysqltest_prometheus
@@ -64,6 +67,7 @@ mysqltest_sisyfos
test
SHOW DATABASES;
Database
+information_schema
mysql
mysqltest_prometheus
mysqltest_sisyfos
diff --git a/mysql-test/r/rpl_ddl.result b/mysql-test/r/rpl_ddl.result
index 3737883b694..9f90001ab67 100644
--- a/mysql-test/r/rpl_ddl.result
+++ b/mysql-test/r/rpl_ddl.result
@@ -1072,6 +1072,188 @@ Database (mysqltest3)
mysqltest3
-------- switch to master -------
+
+######## CREATE PROCEDURE p1() READS SQL DATA SELECT "this is p1" ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 15 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+16
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+15
+
+-------- switch to master -------
+CREATE PROCEDURE p1() READS SQL DATA SELECT "this is p1";
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+16
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+16
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+16
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+16
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW PROCEDURE STATUS LIKE 'p1';
+Db mysqltest1
+Name p1
+Type PROCEDURE
+Definer root@localhost
+Modified #
+Created #
+Security_type DEFINER
+Comment
+ -------- switch to slave -------
+SHOW PROCEDURE STATUS LIKE 'p1';
+Db mysqltest1
+Name p1
+Type PROCEDURE
+Definer @
+Modified #
+Created #
+Security_type DEFINER
+Comment
+
+######## ALTER PROCEDURE p1 COMMENT "I have been altered" ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 16 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+17
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+16
+
+-------- switch to master -------
+ALTER PROCEDURE p1 COMMENT "I have been altered";
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+17
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+17
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+17
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+17
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW PROCEDURE STATUS LIKE 'p1';
+Db mysqltest1
+Name p1
+Type PROCEDURE
+Definer root@localhost
+Modified #
+Created #
+Security_type DEFINER
+Comment I have been altered
+ -------- switch to slave -------
+SHOW PROCEDURE STATUS LIKE 'p1';
+Db mysqltest1
+Name p1
+Type PROCEDURE
+Definer @
+Modified #
+Created #
+Security_type DEFINER
+Comment I have been altered
+
+######## DROP PROCEDURE p1 ########
+
+-------- switch to master -------
+INSERT INTO t1 SET f1= 17 + 1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+18
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+17
+
+-------- switch to master -------
+DROP PROCEDURE p1;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+18
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+18
+
+-------- switch to master -------
+ROLLBACK;
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+18
+
+TEST-INFO: MASTER: The INSERT is committed (Succeeded)
+
+-------- switch to slave --------
+SELECT MAX(f1) FROM t1;
+MAX(f1)
+18
+
+TEST-INFO: SLAVE: The INSERT is committed (Succeeded)
+
+-------- switch to master -------
+flush logs;
+
+-------- switch to slave --------
+flush logs;
+
+-------- switch to master -------
+SHOW PROCEDURE STATUS LIKE 'p1';
+ -------- switch to slave -------
+SHOW PROCEDURE STATUS LIKE 'p1';
DROP DATABASE IF EXISTS mysqltest1;
DROP DATABASE IF EXISTS mysqltest2;
DROP DATABASE IF EXISTS mysqltest3;
diff --git a/mysql-test/r/rpl_deadlock.result b/mysql-test/r/rpl_deadlock.result
index 8eb9d64fcae..b112a51a145 100644
--- a/mysql-test/r/rpl_deadlock.result
+++ b/mysql-test/r/rpl_deadlock.result
@@ -10,17 +10,17 @@ create table t3 (a int) engine=innodb;
create table t4 (a int) engine=innodb;
show variables like 'slave_transaction_retries';
Variable_name Value
-slave_transaction_retries 0
+slave_transaction_retries 10
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show variables like 'slave_transaction_retries';
@@ -45,9 +45,9 @@ a
22
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 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 18911 # # master-bin.000001 Yes Yes 0 0 18911 # None 0 No #
stop slave;
-change master to master_log_pos=401;
+change master to master_log_pos=532;
begin;
select * from t2 for update;
a
@@ -63,10 +63,10 @@ a
22
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 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 18911 # # master-bin.000001 Yes Yes 0 0 18911 # None 0 No #
set global max_relay_log_size=0;
stop slave;
-change master to master_log_pos=401;
+change master to master_log_pos=532;
begin;
select * from t2 for update;
a
@@ -83,5 +83,5 @@ a
22
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 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 18911 # # master-bin.000001 Yes Yes 0 0 18911 # None 0 No #
drop table t1,t2,t3,t4;
diff --git a/mysql-test/r/rpl_delete_all.result b/mysql-test/r/rpl_delete_all.result
index 5ed221823e8..1aa556270c9 100644
--- a/mysql-test/r/rpl_delete_all.result
+++ b/mysql-test/r/rpl_delete_all.result
@@ -9,7 +9,7 @@ drop database if exists mysqltest;
Warnings:
Note 1008 Can't drop database 'mysqltest'; database doesn't exist
show tables from mysqltest;
-ERROR HY000: Can't read dir of './mysqltest/' (Errcode: X)
+ERROR 42000: Unknown database 'mysqltest'
create table t1 (a int);
drop table if exists t1;
Warnings:
diff --git a/mysql-test/r/rpl_error_ignored_table.result b/mysql-test/r/rpl_error_ignored_table.result
index 4a562dbfc70..a0a808ce9a8 100644
--- a/mysql-test/r/rpl_error_ignored_table.result
+++ b/mysql-test/r/rpl_error_ignored_table.result
@@ -9,7 +9,7 @@ insert into t1 values (1),(1);
ERROR 23000: Duplicate entry '1' for key 1
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 213 slave-relay-bin.000002 257 master-bin.000001 Yes Yes test.t3,test.t1,test.t2 0 0 213 257 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 288 # # master-bin.000001 Yes Yes test.t3,test.t1,test.t2 0 0 288 # None 0 No #
show tables like 't1';
Tables_in_test (t1)
drop table t1;
@@ -26,14 +26,14 @@ select (@id := id) - id from t3;
0
kill @id;
drop table t2,t3;
-show binlog events from 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 79 Query 1 79 use `test`; create table t1 (a int primary key)
-master-bin.000001 149 Query 1 149 use `test`; insert into t1 values (1),(1)
-master-bin.000001 213 Query 1 213 use `test`; drop table t1
-master-bin.000001 261 Query 1 261 use `test`; create table t2 (a int primary key)
-master-bin.000001 331 Query 1 331 use `test`; insert into t2 values(1)
-master-bin.000001 390 Query 1 390 use `test`; create table t3 (id int)
-master-bin.000001 449 Query 1 449 use `test`; insert into t3 values(connection_id())
-master-bin.000001 522 Query 1 522 use `test`; update t2 set a = a + 1 + get_lock('crash_lock%20C', 10)
-master-bin.000001 613 Query 1 613 use `test`; drop table t2,t3
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `test`; create table t1 (a int primary key)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values (1),(1)
+master-bin.000001 # Query 1 # use `test`; drop table t1
+master-bin.000001 # Query 1 # use `test`; create table t2 (a int primary key)
+master-bin.000001 # Query 1 # use `test`; insert into t2 values(1)
+master-bin.000001 # Query 1 # use `test`; create table t3 (id int)
+master-bin.000001 # Query 1 # use `test`; insert into t3 values(connection_id())
+master-bin.000001 # Query 1 # use `test`; update t2 set a = a + 1 + get_lock('crash_lock%20C', 10)
+master-bin.000001 # Query 1 # use `test`; drop table t2,t3
diff --git a/mysql-test/r/rpl_failed_optimize.result b/mysql-test/r/rpl_failed_optimize.result
index 120bb53ed25..fd711f89222 100644
--- a/mysql-test/r/rpl_failed_optimize.result
+++ b/mysql-test/r/rpl_failed_optimize.result
@@ -11,6 +11,10 @@ OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize error Lock wait timeout exceeded; try restarting transaction
test.t1 optimize status Operation failed
+Warnings:
+Error 1205 Lock wait timeout exceeded; try restarting transaction
OPTIMIZE TABLE non_existing;
Table Op Msg_type Msg_text
test.non_existing optimize error Table 'test.non_existing' doesn't exist
+Warnings:
+Error 1146 Table 'test.non_existing' doesn't exist
diff --git a/mysql-test/r/rpl_flush_log_loop.result b/mysql-test/r/rpl_flush_log_loop.result
index 0a2d7e5e72a..f9bd42ec26c 100644
--- a/mysql-test/r/rpl_flush_log_loop.result
+++ b/mysql-test/r/rpl_flush_log_loop.result
@@ -14,4 +14,4 @@ start slave;
flush logs;
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 SLAVE_PORT 60 slave-bin.000001 161 relay-log.000002 4 slave-bin.000001 Yes Yes 0 0 161 4 None 0 No #
+# 127.0.0.1 root SLAVE_PORT 60 slave-bin.000001 208 # # slave-bin.000001 Yes Yes 0 0 208 # None 0 No #
diff --git a/mysql-test/r/rpl_flush_tables.result b/mysql-test/r/rpl_flush_tables.result
index 70e4774a920..ca2e77cac66 100644
--- a/mysql-test/r/rpl_flush_tables.result
+++ b/mysql-test/r/rpl_flush_tables.result
@@ -13,28 +13,28 @@ insert into t4 select * from t3;
rename table t1 to t5, t2 to t1;
flush no_write_to_binlog tables;
show binlog events;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 4 Start 1 4 Server ver: SERVER_VERSION, Binlog ver: 3
-master-bin.000001 79 Query 1 79 use `test`; create table t1 (a int)
-master-bin.000001 137 Query 1 137 use `test`; insert into t1 values (10)
-master-bin.000001 198 Query 1 198 use `test`; create table t2 (a int)
-master-bin.000001 256 Query 1 256 use `test`; create table t3 (a int) engine=merge union(t1)
-master-bin.000001 337 Query 1 337 use `test`; create table t4 (a int)
-master-bin.000001 395 Query 1 395 use `test`; insert into t4 select * from t3
-master-bin.000001 461 Query 1 461 use `test`; rename table t1 to t5, t2 to t1
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc 1 # Server ver: SERVER_VERSION, Binlog ver: 4
+master-bin.000001 # Query 1 # use `test`; create table t1 (a int)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values (10)
+master-bin.000001 # Query 1 # use `test`; create table t2 (a int)
+master-bin.000001 # Query 1 # use `test`; create table t3 (a int) engine=merge union(t1)
+master-bin.000001 # Query 1 # use `test`; create table t4 (a int)
+master-bin.000001 # Query 1 # use `test`; insert into t4 select * from t3
+master-bin.000001 # Query 1 # use `test`; rename table t1 to t5, t2 to t1
select * from t3;
a
flush tables;
show binlog events;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 4 Start 1 4 Server ver: SERVER_VERSION, Binlog ver: 3
-master-bin.000001 79 Query 1 79 use `test`; create table t1 (a int)
-master-bin.000001 137 Query 1 137 use `test`; insert into t1 values (10)
-master-bin.000001 198 Query 1 198 use `test`; create table t2 (a int)
-master-bin.000001 256 Query 1 256 use `test`; create table t3 (a int) engine=merge union(t1)
-master-bin.000001 337 Query 1 337 use `test`; create table t4 (a int)
-master-bin.000001 395 Query 1 395 use `test`; insert into t4 select * from t3
-master-bin.000001 461 Query 1 461 use `test`; rename table t1 to t5, t2 to t1
-master-bin.000001 527 Query 1 527 use `test`; flush tables
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc 1 # Server ver: SERVER_VERSION, Binlog ver: 4
+master-bin.000001 # Query 1 # use `test`; create table t1 (a int)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values (10)
+master-bin.000001 # Query 1 # use `test`; create table t2 (a int)
+master-bin.000001 # Query 1 # use `test`; create table t3 (a int) engine=merge union(t1)
+master-bin.000001 # Query 1 # use `test`; create table t4 (a int)
+master-bin.000001 # Query 1 # use `test`; insert into t4 select * from t3
+master-bin.000001 # Query 1 # use `test`; rename table t1 to t5, t2 to t1
+master-bin.000001 # Query 1 # use `test`; flush tables
select * from t3;
a
diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result
index 65fc9d1b415..dc11d10fab8 100644
--- a/mysql-test/r/rpl_loaddata.result
+++ b/mysql-test/r/rpl_loaddata.result
@@ -22,7 +22,7 @@ day id category name
2003-03-22 2416 a bbbbb
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
-slave-bin.000001 964
+slave-bin.000001 1286
drop table t1;
drop table t2;
drop table t3;
@@ -33,7 +33,7 @@ set global sql_slave_skip_counter=1;
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1311 slave-relay-bin.000002 1355 master-bin.000001 Yes Yes 0 0 1311 1355 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1789 # # master-bin.000001 Yes Yes 0 0 1789 # None 0 No #
set sql_log_bin=0;
delete from t1;
set sql_log_bin=1;
@@ -43,7 +43,7 @@ change master to master_user='test';
change master to master_user='root';
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1419 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 1419 4 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1824 # # master-bin.000001 No No 0 0 1824 # None 0 No #
set global sql_slave_skip_counter=1;
start slave;
set sql_log_bin=0;
@@ -54,15 +54,28 @@ stop slave;
reset slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 4 # # No No 0 0 0 # None 0 No #
reset master;
create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60),
-unique(day));
+unique(day)) engine=MyISAM;
load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields
terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by
'\n##\n' starting by '>' ignore 1 lines;
ERROR 23000: Duplicate entry '2003-03-22' for key 1
-show master status;
-File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000001 491
+select * from t2;
+day id category name
+2003-02-22 2461 b a a a @ %  ' " a
+2003-03-22 2161 c asdf
+start slave;
+select * from t2;
+day id category name
+2003-02-22 2461 b a a a @ %  ' " a
+2003-03-22 2161 c asdf
+alter table t2 drop key day;
+delete from t2;
+load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields
+terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by
+'\n##\n' starting by '>' ignore 1 lines;
+ERROR 23000: Duplicate entry '2003-03-22' for key 1
+drop table t2;
drop table t2;
diff --git a/mysql-test/r/rpl_loaddata_rule_m.result b/mysql-test/r/rpl_loaddata_rule_m.result
index 08f2c2ec071..3571c9973ea 100644
--- a/mysql-test/r/rpl_loaddata_rule_m.result
+++ b/mysql-test/r/rpl_loaddata_rule_m.result
@@ -10,8 +10,10 @@ create database mysqltest;
create table t1(a int, b int, unique(b));
use mysqltest;
load data infile '../../std_data/rpl_loaddata.dat' into table test.t1;
-show binlog events from 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 79 Query 1 79 drop database if exists mysqltest
-master-bin.000001 152 Query 1 152 create database mysqltest
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # drop database if exists mysqltest
+master-bin.000001 # Query 1 # create database mysqltest
+master-bin.000001 # Begin_load_query 1 # ;file_id=1;block_len=12
+master-bin.000001 # Execute_load_query 1 # use `mysqltest`; load data infile '../../std_data/rpl_loaddata.dat' into table test.t1 ;file_id=1
drop database mysqltest;
diff --git a/mysql-test/r/rpl_loaddata_rule_s.result b/mysql-test/r/rpl_loaddata_rule_s.result
index 26893cb1e9e..16720c81374 100644
--- a/mysql-test/r/rpl_loaddata_rule_s.result
+++ b/mysql-test/r/rpl_loaddata_rule_s.result
@@ -10,5 +10,5 @@ load data infile '../../std_data/rpl_loaddata.dat' into table test.t1;
select count(*) from t1;
count(*)
2
-show binlog events from 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
diff --git a/mysql-test/r/rpl_loaddatalocal.result b/mysql-test/r/rpl_loaddatalocal.result
index b49ea842485..c29825c3c98 100644
--- a/mysql-test/r/rpl_loaddatalocal.result
+++ b/mysql-test/r/rpl_loaddatalocal.result
@@ -12,3 +12,20 @@ select a,count(*) from t1 group by a;
a count(*)
1 10000
drop table t1;
+create table t1(a int);
+insert into t1 values (1), (2), (2), (3);
+select * into outfile '../../var/master-data/rpl_loaddatalocal.select_outfile' from t1;
+drop table t1;
+create table t1(a int primary key);
+load data local infile './var/master-data/rpl_loaddatalocal.select_outfile' into table t1;
+select * from t1;
+a
+1
+2
+3
+select * from t1;
+a
+1
+2
+3
+drop table t1;
diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result
index 9fcab2a7cbe..be8d5291ad9 100644
--- a/mysql-test/r/rpl_log.result
+++ b/mysql-test/r/rpl_log.result
@@ -18,26 +18,26 @@ count(*)
69
drop table t1;
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(n int not null auto_increment primary key)
-master-bin.000001 172 Intvar 1 172 INSERT_ID=1
-master-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
-master-bin.000001 263 Query 1 263 use `test`; drop table t1
-master-bin.000001 311 Query 1 311 use `test`; create table t1 (word char(20) not null)
-master-bin.000001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=581
-master-bin.000001 1056 Exec_load 1 1056 ;file_id=1
-master-bin.000001 1079 Query 1 1079 use `test`; drop table t1
-show binlog events from 79 limit 1;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
-show binlog events from 79 limit 2;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
-master-bin.000001 172 Intvar 1 172 INSERT_ID=1
-show binlog events from 79 limit 2,1;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 98 Server ver: VERSION, Binlog ver: 4
+master-bin.000001 98 Query 1 219 use `test`; create table t1(n int not null auto_increment primary key)
+master-bin.000001 219 Intvar 1 247 INSERT_ID=1
+master-bin.000001 247 Query 1 338 use `test`; insert into t1 values (NULL)
+master-bin.000001 338 Query 1 414 use `test`; drop table t1
+master-bin.000001 414 Query 1 517 use `test`; create table t1 (word char(20) not null)
+master-bin.000001 517 Begin_load_query 1 1121 ;file_id=1;block_len=581
+master-bin.000001 1121 Execute_load_query 1 1269 use `test`; load data infile '../../std_data/words.dat' into table t1 ignore 1 lines ;file_id=1
+master-bin.000001 1269 Query 1 1345 use `test`; drop table t1
+show binlog events from 98 limit 1;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 219 use `test`; create table t1(n int not null auto_increment primary key)
+show binlog events from 98 limit 2;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 Query 1 219 use `test`; create table t1(n int not null auto_increment primary key)
+master-bin.000001 219 Intvar 1 247 INSERT_ID=1
+show binlog events from 98 limit 2,1;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 247 Query 1 338 use `test`; insert into t1 values (NULL)
flush logs;
create table t5 (a int);
drop table t5;
@@ -48,54 +48,56 @@ create table t1 (n int);
insert into t1 values (1);
drop table t1;
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(n int not null auto_increment primary key)
-master-bin.000001 172 Intvar 1 172 INSERT_ID=1
-master-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
-master-bin.000001 263 Query 1 263 use `test`; drop table t1
-master-bin.000001 311 Query 1 311 use `test`; create table t1 (word char(20) not null)
-master-bin.000001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=581
-master-bin.000001 1056 Exec_load 1 1056 ;file_id=1
-master-bin.000001 1079 Query 1 1079 use `test`; drop table t1
-master-bin.000001 1127 Rotate 1 1127 master-bin.000002;pos=4
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 98 Server ver: VERSION, Binlog ver: 4
+master-bin.000001 98 Query 1 219 use `test`; create table t1(n int not null auto_increment primary key)
+master-bin.000001 219 Intvar 1 247 INSERT_ID=1
+master-bin.000001 247 Query 1 338 use `test`; insert into t1 values (NULL)
+master-bin.000001 338 Query 1 414 use `test`; drop table t1
+master-bin.000001 414 Query 1 517 use `test`; create table t1 (word char(20) not null)
+master-bin.000001 517 Begin_load_query 1 1121 ;file_id=1;block_len=581
+master-bin.000001 1121 Execute_load_query 1 1269 use `test`; load data infile '../../std_data/words.dat' into table t1 ignore 1 lines ;file_id=1
+master-bin.000001 1269 Query 1 1345 use `test`; drop table t1
+master-bin.000001 1345 Rotate 1 1389 master-bin.000002;pos=4
show binlog events in 'master-bin.000002';
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000002 4 Query 1 4 use `test`; create table t5 (a int)
-master-bin.000002 62 Query 1 62 use `test`; drop table t5
-master-bin.000002 110 Query 1 110 use `test`; create table t1 (n int)
-master-bin.000002 168 Query 1 168 use `test`; insert into t1 values (1)
-master-bin.000002 228 Query 1 228 use `test`; drop table t1
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 4 Format_desc 1 98 Server ver: VERSION, Binlog ver: 4
+master-bin.000002 98 Query 1 184 use `test`; create table t5 (a int)
+master-bin.000002 184 Query 1 260 use `test`; drop table t5
+master-bin.000002 260 Query 1 346 use `test`; create table t1 (n int)
+master-bin.000002 346 Query 1 434 use `test`; insert into t1 values (1)
+master-bin.000002 434 Query 1 510 use `test`; drop table t1
show binary logs;
Log_name File_size
-master-bin.000001 1171
-master-bin.000002 276
+master-bin.000001 1389
+master-bin.000002 510
start slave;
show binary logs;
Log_name File_size
-slave-bin.000001 1285
-slave-bin.000002 170
+slave-bin.000001 1559
+slave-bin.000002 348
show binlog events in 'slave-bin.000001' from 4;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-slave-bin.000001 4 Start 2 4 Server ver: VERSION, Binlog ver: 3
-slave-bin.000001 79 Query 1 79 use `test`; create table t1(n int not null auto_increment primary key)
-slave-bin.000001 172 Intvar 1 172 INSERT_ID=1
-slave-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
-slave-bin.000001 263 Query 1 263 use `test`; drop table t1
-slave-bin.000001 311 Query 1 311 use `test`; create table t1 (word char(20) not null)
-slave-bin.000001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=581
-slave-bin.000001 1065 Exec_load 1 1065 ;file_id=1
-slave-bin.000001 1088 Query 1 1088 use `test`; drop table t1
-slave-bin.000001 1136 Query 1 1136 use `test`; create table t5 (a int)
-slave-bin.000001 1194 Query 1 1194 use `test`; drop table t5
-slave-bin.000001 1242 Rotate 2 1242 slave-bin.000002;pos=4
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 4 Format_desc 2 98 Server ver: VERSION, Binlog ver: 4
+slave-bin.000001 98 Query 1 219 use `test`; create table t1(n int not null auto_increment primary key)
+slave-bin.000001 219 Intvar 1 247 INSERT_ID=1
+slave-bin.000001 247 Query 1 338 use `test`; insert into t1 values (NULL)
+slave-bin.000001 338 Query 1 414 use `test`; drop table t1
+slave-bin.000001 414 Query 1 517 use `test`; create table t1 (word char(20) not null)
+slave-bin.000001 517 Begin_load_query 1 1121 ;file_id=1;block_len=581
+slave-bin.000001 1121 Execute_load_query 1 1278 use `test`; load data INFILE '../../var/tmp/SQL_LOAD-2-1-1.data' INTO table t1 ignore 1 lines ;file_id=1
+slave-bin.000001 1278 Query 1 1354 use `test`; drop table t1
+slave-bin.000001 1354 Query 1 1440 use `test`; create table t5 (a int)
+slave-bin.000001 1440 Query 1 1516 use `test`; drop table t5
+slave-bin.000001 1516 Rotate 2 1559 slave-bin.000002;pos=4
show binlog events in 'slave-bin.000002' from 4;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-slave-bin.000002 4 Query 1 4 use `test`; create table t1 (n int)
-slave-bin.000002 62 Query 1 62 use `test`; insert into t1 values (1)
-slave-bin.000002 122 Query 1 122 use `test`; drop table t1
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000002 4 Format_desc 2 98 Server ver: VERSION, Binlog ver: 4
+slave-bin.000002 98 Query 1 184 use `test`; create table t1 (n int)
+slave-bin.000002 184 Query 1 272 use `test`; insert into t1 values (1)
+slave-bin.000002 272 Query 1 348 use `test`; drop table t1
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 276 slave-relay-bin.000003 214 master-bin.000002 Yes Yes 0 0 276 214 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 510 # # master-bin.000002 Yes Yes 0 0 510 # None 0 No #
show binlog events in 'slave-bin.000005' from 4;
ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log
diff --git a/mysql-test/r/rpl_log_pos.result b/mysql-test/r/rpl_log_pos.result
index 10c78272de6..cf13756966e 100644
--- a/mysql-test/r/rpl_log_pos.result
+++ b/mysql-test/r/rpl_log_pos.result
@@ -6,10 +6,10 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000001 79
+master-bin.000001 98
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 98 # # master-bin.000001 Yes Yes 0 0 98 # None 0 No #
stop slave;
change master to master_log_pos=73;
start slave;
@@ -17,26 +17,26 @@ stop slave;
change master to master_log_pos=73;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 73 4 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 # # master-bin.000001 No No 0 0 73 # None 0 No #
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 48 master-bin.000001 No Yes 0 0 73 48 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 # # master-bin.000001 No Yes 0 0 73 # None 0 No #
stop slave;
change master to master_log_pos=173;
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 173 slave-relay-bin.000001 4 master-bin.000001 No Yes 0 0 173 4 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 173 # # master-bin.000001 No Yes 0 0 173 # None 0 No #
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000001 79
+master-bin.000001 98
create table if not exists t1 (n int);
drop table if exists t1;
create table t1 (n int);
insert into t1 values (1),(2),(3);
stop slave;
-change master to master_log_pos=79;
+change master to master_log_pos=98;
start slave;
select * from t1;
n
diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result
index 5c3360b0f66..fbe3b89828a 100644
--- a/mysql-test/r/rpl_max_relay_size.result
+++ b/mysql-test/r/rpl_max_relay_size.result
@@ -16,7 +16,7 @@ select @@global.max_relay_log_size;
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000014 1221 master-bin.000001 Yes Yes 0 0 50477 1221 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 72952 # # master-bin.000001 Yes Yes 0 0 72952 # None 0 No #
stop slave;
reset slave;
set global max_relay_log_size=(5*4096);
@@ -26,7 +26,7 @@ select @@global.max_relay_log_size;
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000004 9457 master-bin.000001 Yes Yes 0 0 50477 9457 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 72952 # # master-bin.000001 Yes Yes 0 0 72952 # None 0 No #
stop slave;
reset slave;
set global max_relay_log_size=0;
@@ -36,26 +36,26 @@ select @@global.max_relay_log_size;
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000008 1283 master-bin.000001 Yes Yes 0 0 50477 1283 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 72952 # # master-bin.000001 Yes Yes 0 0 72952 # None 0 No #
stop slave;
reset slave;
flush logs;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 4 # # No No 0 0 0 # None 0 No #
reset slave;
start slave;
flush logs;
create table t1 (a int);
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50535 slave-relay-bin.000009 62 master-bin.000001 Yes Yes 0 0 50535 62 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73038 # # master-bin.000001 Yes Yes 0 0 73038 # None 0 No #
flush logs;
drop table t1;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50583 slave-relay-bin.000010 52 master-bin.000001 Yes Yes 0 0 50583 52 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73114 # # master-bin.000001 Yes Yes 0 0 73114 # None 0 No #
flush logs;
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000002 4
+master-bin.000002 98
diff --git a/mysql-test/r/rpl_multi_query.result b/mysql-test/r/rpl_multi_query.result
index 2521dbe1ed9..f2d8ea77536 100644
--- a/mysql-test/r/rpl_multi_query.result
+++ b/mysql-test/r/rpl_multi_query.result
@@ -19,8 +19,8 @@ n
3
4
5
-show binlog events from 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query 1 # drop database if exists mysqltest
master-bin.000001 # Query 1 # create database mysqltest
master-bin.000001 # Query 1 # use `test`; create table mysqltest.t1 ( n int)
diff --git a/mysql-test/r/rpl_openssl.result b/mysql-test/r/rpl_openssl.result
index ad7251fd631..d916e9f2c5c 100644
--- a/mysql-test/r/rpl_openssl.result
+++ b/mysql-test/r/rpl_openssl.result
@@ -4,7 +4,7 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
-grant replication slave on *.* to replssl@'%' require ssl;
+grant replication slave on *.* to replssl@localhost require ssl;
create table t1 (t int);
stop slave;
change master to master_user='replssl',master_password='';
@@ -20,11 +20,11 @@ t
1
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 replssl MASTER_MYPORT 1 master-bin.000001 289 slave-relay-bin.000001 108 master-bin.000001 Yes Yes 0 0 289 108 None 0 Yes MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem #
+# 127.0.0.1 replssl MASTER_MYPORT 1 master-bin.000001 398 # # master-bin.000001 Yes Yes 0 0 398 # None 0 Yes MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem #
stop slave;
change master to master_user='root',master_password='', master_ssl=0;
start slave;
drop table t1;
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 337 slave-relay-bin.000001 96 master-bin.000001 Yes Yes 0 0 337 96 None 0 No MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem #
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 474 # # master-bin.000001 Yes Yes 0 0 474 # None 0 No MYSQL_TEST_DIR/std_data/cacert.pem MYSQL_TEST_DIR/std_data/client-cert.pem MYSQL_TEST_DIR/std_data/client-key.pem #
diff --git a/mysql-test/r/rpl_relayrotate.result b/mysql-test/r/rpl_relayrotate.result
index bf9bbbb9b93..c79187e12d0 100644
--- a/mysql-test/r/rpl_relayrotate.result
+++ b/mysql-test/r/rpl_relayrotate.result
@@ -13,7 +13,10 @@ start slave;
select master_pos_wait('master-bin.001',3000)>=0;
master_pos_wait('master-bin.001',3000)>=0
1
-select * from t1 where a=8000;
-a
+select max(a) from t1;
+max(a)
8000
+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 735186 # # master-bin.000001 Yes Yes 0 0 735186 # None 0 No #
drop table t1;
diff --git a/mysql-test/r/rpl_replicate_do.result b/mysql-test/r/rpl_replicate_do.result
index 45ef6cb9b7b..d8666080a71 100644
--- a/mysql-test/r/rpl_replicate_do.result
+++ b/mysql-test/r/rpl_replicate_do.result
@@ -28,7 +28,7 @@ ERROR 42S02: Table 'test.t11' doesn't exist
drop table if exists t1,t2,t11;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1340 slave-relay-bin.000002 1384 master-bin.000001 Yes Yes test.t1 0 0 1340 1384 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1658 # # master-bin.000001 Yes Yes test.t1 0 0 1658 # None 0 No #
create table t1 (ts timestamp);
set one_shot time_zone='met';
insert into t1 values('2005-08-12 00:00:00');
diff --git a/mysql-test/r/rpl_reset_slave.result b/mysql-test/r/rpl_reset_slave.result
index 42d41533cb0..ab55423b773 100644
--- a/mysql-test/r/rpl_reset_slave.result
+++ b/mysql-test/r/rpl_reset_slave.result
@@ -6,20 +6,20 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 98 # # master-bin.000001 Yes Yes 0 0 98 # None 0 No #
stop slave;
change master to master_user='test';
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 test MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000001 4 master-bin.000001 No No 0 0 79 4 None 0 No #
+# 127.0.0.1 test MASTER_PORT 1 master-bin.000001 98 # # master-bin.000001 No No 0 0 98 # None 0 No #
reset slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 4 # # No No 0 0 0 # None 0 No #
start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 98 # # master-bin.000001 Yes Yes 0 0 98 # None 0 No #
stop slave;
reset slave;
start slave;
diff --git a/mysql-test/r/rpl_rewrite_db.result b/mysql-test/r/rpl_rewrite_db.result
index da3ec0243fe..d4a24626cc3 100644
--- a/mysql-test/r/rpl_rewrite_db.result
+++ b/mysql-test/r/rpl_rewrite_db.result
@@ -67,9 +67,9 @@ drop table t1;
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 1264 Out of range value adjusted for column 'a' at row 3
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 1264 Out of range value adjusted for column 'a' at row 5
Warning 1262 Row 5 was truncated; it contained more data than there were input columns
select * from rewrite.t1;
a b
@@ -81,7 +81,7 @@ a b
truncate table t1;
load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
Warnings:
-Warning 1265 Data truncated for column 'a' at row 4
+Warning 1264 Out of range value adjusted for column 'a' at row 4
Warning 1261 Row 4 doesn't contain data for all columns
select * from rewrite.t1;
a b
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index 9f74cdb9502..bf2ef98c87f 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -1,7 +1,7 @@
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
+Got one of the listed errors
start slave;
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';
@@ -16,7 +16,7 @@ create table t1 (s text);
insert into t1 values('Could not break slave'),('Tried hard');
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 60 master-bin.000001 417 slave-relay-bin.000001 461 master-bin.000001 Yes Yes 0 0 417 461 None 0 No #
+# 127.0.0.1 root MASTER_PORT 60 master-bin.000001 548 # # master-bin.000001 Yes Yes 0 0 548 # None 0 No #
select * from t1;
s
Could not break slave
@@ -27,9 +27,9 @@ insert into t2 values (34),(67),(123);
flush logs;
show binary logs;
Log_name File_size
-master-bin.000001 461
-master-bin.000002 213
-master-bin.000003 4
+master-bin.000001 592
+master-bin.000002 363
+master-bin.000003 98
create table t3 select * from temp_table;
select * from t3;
a
@@ -43,21 +43,21 @@ start slave;
purge master logs to 'master-bin.000002';
show master logs;
Log_name File_size
-master-bin.000002 213
-master-bin.000003 229
+master-bin.000002 363
+master-bin.000003 407
purge binary logs to 'master-bin.000002';
show binary logs;
Log_name File_size
-master-bin.000002 213
-master-bin.000003 229
+master-bin.000002 363
+master-bin.000003 407
purge master logs before now();
show binary logs;
Log_name File_size
-master-bin.000003 229
+master-bin.000003 407
insert into t2 values (65);
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 60 master-bin.000003 290 slave-relay-bin.000001 1088 master-bin.000003 Yes Yes 0 0 290 1088 None 0 No #
+# 127.0.0.1 root MASTER_PORT 60 master-bin.000003 496 # # master-bin.000003 Yes Yes 0 0 496 # None 0 No #
select * from t2;
m
34
@@ -74,17 +74,18 @@ count(*)
create table t4 select * from temp_table;
show binary logs;
Log_name File_size
-master-bin.000003 4167
-master-bin.000004 2886
+master-bin.000003 4185
+master-bin.000004 4190
+master-bin.000005 2032
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000004 2886
+master-bin.000005 2032
select * from t4;
a
testing temporary tables part 2
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 60 master-bin.000004 2886 slave-relay-bin.000001 7891 master-bin.000004 Yes Yes 0 0 2886 7891 None 0 No #
+# 127.0.0.1 root MASTER_PORT 60 master-bin.000005 2032 # # master-bin.000005 Yes Yes 0 0 2032 # None 0 No #
lock tables t3 read;
select count(*) from t3 where n >= 4;
count(*)
diff --git a/mysql-test/r/rpl_server_id1.result b/mysql-test/r/rpl_server_id1.result
index 32e14b053d7..a3ab6672f69 100644
--- a/mysql-test/r/rpl_server_id1.result
+++ b/mysql-test/r/rpl_server_id1.result
@@ -10,7 +10,7 @@ stop slave;
change master to master_port=SLAVE_PORT;
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 SLAVE_PORT 1 4 slave-relay-bin.000001 4 No No # 0 0 0 4 None 0 No NULL
+ 127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.000001 4 No No # 0 0 0 98 None 0 No NULL
start slave;
insert into t1 values (1);
show status like "slave_running";
diff --git a/mysql-test/r/rpl_server_id2.result b/mysql-test/r/rpl_server_id2.result
index 82ab1ff85a7..b196646aecc 100644
--- a/mysql-test/r/rpl_server_id2.result
+++ b/mysql-test/r/rpl_server_id2.result
@@ -10,7 +10,7 @@ stop slave;
change master to master_port=SLAVE_PORT;
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 SLAVE_PORT 1 4 slave-relay-bin.000001 4 No No # 0 0 0 4 None 0 No NULL
+ 127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.000001 4 No No # 0 0 0 98 None 0 No NULL
start slave;
insert into t1 values (1);
select * from t1;
diff --git a/mysql-test/r/rpl_session_var.result b/mysql-test/r/rpl_session_var.result
new file mode 100644
index 00000000000..b5b4b815ade
--- /dev/null
+++ b/mysql-test/r/rpl_session_var.result
@@ -0,0 +1,43 @@
+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;
+Warnings:
+Note 1051 Unknown table 't1'
+create table t1(a varchar(100),b int);
+set @@session.sql_mode=pipes_as_concat;
+insert into t1 values('My'||'SQL', 1);
+set @@session.sql_mode=default;
+insert into t1 values('1'||'2', 2);
+select * from t1 where b<3 order by a;
+a b
+1 2
+MySQL 1
+select * from t1 where b<3 order by a;
+a b
+1 2
+MySQL 1
+set @@session.sql_mode=ignore_space;
+insert into t1 values(password ('MySQL'), 3);
+set @@session.sql_mode=ansi_quotes;
+create table "t2" ("a" int);
+drop table t1, t2;
+set @@session.sql_mode=default;
+create table t1(a int auto_increment primary key);
+create table t2(b int, a int);
+set @@session.sql_auto_is_null=1;
+insert into t1 values(null);
+insert into t2 select 1,a from t1 where a is null;
+set @@session.sql_auto_is_null=0;
+insert into t1 values(null);
+insert into t2 select 2,a from t1 where a is null;
+select * from t2 order by b;
+b a
+1 1
+select * from t2 order by b;
+b a
+1 1
+drop table t1,t2;
diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result
new file mode 100644
index 00000000000..394f93f2ea0
--- /dev/null
+++ b/mysql-test/r/rpl_sp.result
@@ -0,0 +1,269 @@
+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 if not exists mysqltest1;
+use mysqltest1;
+create table t1 (a varchar(100));
+use mysqltest1;
+drop procedure if exists foo;
+drop procedure if exists foo2;
+drop procedure if exists foo3;
+drop procedure if exists foo4;
+drop procedure if exists bar;
+drop function if exists fn1;
+create procedure foo()
+begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end|
+ERROR HY000: This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+show binlog events from 98|
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # create database if not exists mysqltest1
+master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a varchar(100))
+create procedure foo() deterministic
+begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end|
+select * from mysql.proc where name='foo' and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 foo PROCEDURE foo SQL CONTAINS_SQL YES DEFINER begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end root@localhost # #
+select * from mysql.proc where name='foo' and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 foo PROCEDURE foo SQL CONTAINS_SQL YES DEFINER begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end @ # #
+set timestamp=1000000000;
+call foo();
+show binlog events from 308;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo() deterministic
+begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8))
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp())
+select * from t1;
+a
+8
+1000000000
+select * from t1;
+a
+8
+1000000000
+delete from t1;
+create procedure foo2()
+not deterministic
+reads sql data
+select * from mysqltest1.t1;
+call foo2();
+a
+show binlog events from 518;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8))
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp())
+master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
+master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo2()
+not deterministic
+reads sql data
+select * from mysqltest1.t1
+alter procedure foo2 contains sql;
+ERROR HY000: This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+drop table t1;
+create table t1 (a int);
+create table t2 like t1;
+create procedure foo3()
+deterministic
+insert into t1 values (15);
+grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1;
+create procedure foo4()
+deterministic
+insert into t1 values (10);
+ERROR HY000: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+set global log_bin_trust_routine_creators=1;
+create procedure foo4()
+deterministic
+begin
+insert into t2 values(3);
+insert into t1 values (5);
+end|
+call foo4();
+Got one of the listed errors
+show warnings;
+Level Code Message
+Error 1142 INSERT command denied to user 'zedjzlcsjhd'@'localhost' for table 't1'
+Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
+call foo3();
+show warnings;
+Level Code Message
+call foo4();
+Got one of the listed errors
+show warnings;
+Level Code Message
+Error 1142 INSERT command denied to user 'zedjzlcsjhd'@'localhost' for table 't1'
+Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
+alter procedure foo4 sql security invoker;
+call foo4();
+show warnings;
+Level Code Message
+show binlog events from 990;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
+master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int)
+master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 like t1
+master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo3()
+deterministic
+insert into t1 values (15)
+master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1
+master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1
+master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1
+master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4()
+deterministic
+begin
+insert into t2 values(3);
+insert into t1 values (5);
+end
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3)
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (15)
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3)
+master-bin.000001 # Query 1 # use `mysqltest1`; alter procedure foo4 sql security invoker
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(3)
+master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (5)
+select * from t1;
+a
+15
+5
+select * from t2;
+a
+3
+3
+3
+select * from t1;
+a
+15
+5
+select * from t2;
+a
+3
+3
+3
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 foo4 PROCEDURE foo4 SQL CONTAINS_SQL YES INVOKER begin
+insert into t2 values(3);
+insert into t1 values (5);
+end @ # #
+drop procedure foo4;
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+drop procedure foo;
+drop procedure foo2;
+drop procedure foo3;
+create function fn1(x int)
+returns int
+deterministic
+begin
+insert into t1 values (x);
+return x+2;
+end|
+delete t1,t2 from t1,t2;
+select fn1(20);
+fn1(20)
+22
+insert into t2 values(fn1(21));
+select * from t1;
+a
+21
+20
+select * from t2;
+a
+23
+select * from t1;
+a
+21
+20
+select * from t2;
+a
+23
+drop function fn1;
+create function fn1()
+returns int
+deterministic
+begin
+return unix_timestamp();
+end|
+delete from t1;
+set timestamp=1000000000;
+insert into t1 values(fn1());
+select * from mysql.proc where db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 fn1 FUNCTION fn1 SQL CONTAINS_SQL YES DEFINER int(11) begin
+return unix_timestamp();
+end root@localhost # #
+select * from t1;
+a
+1000000000
+use mysqltest1;
+select * from t1;
+a
+1000000000
+select * from mysql.proc where db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 fn1 FUNCTION fn1 SQL CONTAINS_SQL YES DEFINER int(11) begin
+return unix_timestamp();
+end @ # #
+create trigger trg before insert on t1 for each row set new.a= 10;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+flush logs;
+delete from t1;
+create trigger trg before insert on t1 for each row set new.a= 10;
+insert into t1 values (1);
+select * from t1;
+a
+10
+select * from t1;
+a
+10
+delete from t1;
+drop trigger trg;
+insert into t1 values (1);
+select * from t1;
+a
+1
+show binlog events in 'master-bin.000002' from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1
+master-bin.000002 # Query 1 # use `mysqltest1`; create trigger trg before insert on t1 for each row set new.a= 10
+master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1)
+master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1
+master-bin.000002 # Query 1 # use `mysqltest1`; drop trigger trg
+master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1)
+select * from t1;
+a
+1
+drop function fn1;
+drop database mysqltest1;
+drop user "zedjzlcsjhd"@127.0.0.1;
diff --git a/mysql-test/r/rpl_sp_effects.result b/mysql-test/r/rpl_sp_effects.result
new file mode 100644
index 00000000000..bf8128d9385
--- /dev/null
+++ b/mysql-test/r/rpl_sp_effects.result
@@ -0,0 +1,215 @@
+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 procedure if exists p1;
+drop procedure if exists p2;
+drop function if exists f1;
+drop table if exists t1,t2;
+drop view if exists v1;
+create table t1 (a int);
+create procedure p1()
+begin
+declare spv int default 0;
+while spv < 5 do
+insert into t1 values(spv+1);
+set spv=spv+1;
+end while;
+end//
+call p1();
+select * from t1;
+a
+1
+2
+3
+4
+5
+delete from t1;
+create procedure p2()
+begin
+declare a int default 4;
+create table t2 as select a;
+end//
+call p2();
+select * from t2;
+a
+4
+select * from t2;
+a
+4
+drop procedure p1;
+drop procedure p2;
+drop table t2;
+create function f1(x int) returns int
+begin
+insert into t1 values(x);
+return x+1;
+end//
+create procedure p1(a int, b int)
+begin
+declare v int default f1(5);
+if (f1(6)) then
+select 'yes';
+end if;
+set v = f1(7);
+while f1(8) < 1 do
+select 'this cant be';
+end while;
+end//
+call p1(f1(1), f1(2));
+yes
+yes
+select * from t1;
+a
+1
+2
+5
+6
+7
+8
+create table t2(a int);
+insert into t2 values (10),(11);
+select a,f1(a) from t2;
+a f1(a)
+10 11
+11 12
+insert into t2 select f1(3);
+select 'master:',a from t1;
+master: a
+master: 1
+master: 2
+master: 5
+master: 6
+master: 7
+master: 8
+master: 10
+master: 11
+master: 3
+select 'slave:',a from t1;
+slave: a
+slave: 1
+slave: 2
+slave: 5
+slave: 6
+slave: 7
+slave: 8
+slave: 10
+slave: 11
+slave: 3
+drop procedure p1;
+delete from t1;
+delete from t2;
+delete from t1;
+insert into t2 values(1),(2);
+create view v1 as select f1(a) from t2;
+select * from v1;
+f1(a)
+2
+3
+select 'master:',a from t1;
+master: a
+master: 1
+master: 2
+select 'slave:',a from t1;
+slave: a
+slave: 1
+slave: 2
+drop view v1;
+delete from t1;
+prepare s1 from 'select f1(?)';
+set @xx=123;
+execute s1 using @xx;
+f1(?)
+124
+select 'master:',a from t1;
+master: a
+master: 123
+select 'slave:',a from t1;
+slave: a
+slave: 123
+delete from t1;
+create procedure p1(spv int)
+begin
+declare c cursor for select f1(spv) from t2;
+while (spv > 2) do
+open c;
+fetch c into spv;
+close c;
+set spv= spv - 10;
+end while;
+end//
+call p1(15);
+select 'master:',a from t1;
+master: a
+master: 15
+master: 15
+master: 6
+master: 6
+select 'slave:',a from t1;
+slave: a
+slave: 15
+slave: 15
+slave: 6
+slave: 6
+drop procedure p1;
+drop function f1;
+drop table t1,t2;
+create table t1 (a int);
+create procedure p1()
+begin
+insert into t1 values(@x);
+set @x=@x+1;
+insert into t1 values(@x);
+if (f2()) then
+insert into t1 values(1243);
+end if;
+end//
+create function f2() returns int
+begin
+insert into t1 values(@z);
+set @z=@z+1;
+insert into t1 values(@z);
+return 0;
+end//
+create function f1() returns int
+begin
+insert into t1 values(@y);
+call p1();
+return 0;
+end//
+set @x=10;
+set @y=20;
+set @z=100;
+select f1();
+f1()
+0
+set @x=30;
+call p1();
+select 'master', a from t1;
+master a
+master 20
+master 10
+master 11
+master 100
+master 101
+master 30
+master 31
+master 101
+master 102
+select 'slave', a from t1;
+slave a
+slave 20
+slave 10
+slave 11
+slave 100
+slave 101
+slave 30
+slave 31
+slave 101
+slave 102
+drop table t1;
+drop function f1;
+drop function f2;
+drop procedure p1;
diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result
index b9865d282fa..a76fb87a52b 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 42000: 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 42000: 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
@@ -37,20 +37,20 @@ f
5
7
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`; drop table if exists t1,t2
-master-bin.000001 140 Query 1 140 use `test`; create table t1(f int)
-master-bin.000001 197 Query 1 197 use `test`; create table t2(f int)
-master-bin.000001 254 Query 1 254 use `test`; insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
-master-bin.000001 351 Query 1 351 use `test`; create temporary table t3(f int)
-master-bin.000001 418 Query 1 418 use `test`; insert into t3 select * from t1 where f<6
-master-bin.000001 494 Query 1 494 use `test`; create temporary table t3(f int)
-master-bin.000001 561 Query 1 561 use `test`; insert into t2 select count(*) from t3
-master-bin.000001 634 Query 1 634 use `test`; insert into t3 select * from t1 where f>=4
-master-bin.000001 711 Query 1 711 use `test`; drop temporary table t3
-master-bin.000001 769 Query 1 769 use `test`; insert into t2 select count(*) from t3
-master-bin.000001 842 Query 1 842 use `test`; drop temporary table t3
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
+master-bin.000001 # Query 1 # use `test`; drop table if exists t1,t2
+master-bin.000001 # Query 1 # use `test`; create table t1(f int)
+master-bin.000001 # Query 1 # use `test`; create table t2(f int)
+master-bin.000001 # Query 1 # use `test`; insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
+master-bin.000001 # Query 1 # use `test`; create temporary table t3(f int)
+master-bin.000001 # Query 1 # use `test`; insert into t3 select * from t1 where f<6
+master-bin.000001 # Query 1 # use `test`; create temporary table t3(f int)
+master-bin.000001 # Query 1 # use `test`; insert into t2 select count(*) from t3
+master-bin.000001 # Query 1 # use `test`; insert into t3 select * from t1 where f>=4
+master-bin.000001 # Query 1 # use `test`; drop temporary table t3
+master-bin.000001 # Query 1 # use `test`; insert into t2 select count(*) from t3
+master-bin.000001 # Query 1 # use `test`; drop temporary table t3
drop table t1, t2;
use test;
SET TIMESTAMP=1040323920;
diff --git a/mysql-test/r/rpl_timezone.result b/mysql-test/r/rpl_timezone.result
index c7be3324533..85637638f99 100644
--- a/mysql-test/r/rpl_timezone.result
+++ b/mysql-test/r/rpl_timezone.result
@@ -4,21 +4,31 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
+set timestamp=100000000;
create table t1 (t timestamp);
create table t2 (t char(32));
select @@time_zone;
@@time_zone
+Japan
+select @@time_zone;
+@@time_zone
Europe/Moscow
+insert into t1 values ('20050101000000'), ('20050611093902');
set time_zone='UTC';
insert into t1 values ('20040101000000'), ('20040611093902');
select * from t1;
t
+2004-12-31 21:00:00
+2005-06-11 05:39:02
2004-01-01 00:00:00
2004-06-11 09:39:02
+set time_zone='UTC';
select * from t1;
t
-2004-01-01 03:00:00
-2004-06-11 13:39:02
+2004-12-31 21:00:00
+2005-06-11 05:39:02
+2004-01-01 00:00:00
+2004-06-11 09:39:02
delete from t1;
set time_zone='Europe/Moscow';
insert into t1 values ('20040101000000'), ('20040611093902');
@@ -26,19 +36,51 @@ select * from t1;
t
2004-01-01 00:00:00
2004-06-11 09:39:02
+set time_zone='Europe/Moscow';
+select * from t1;
+t
+2004-01-01 00:00:00
+2004-06-11 09:39:02
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
+use test;
+SET TIMESTAMP=100000000;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
+create table t1 (t timestamp);
+SET TIMESTAMP=100000000;
+create table t2 (t char(32));
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='Europe/Moscow';
+insert into t1 values ('20050101000000'), ('20050611093902');
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='UTC';
+insert into t1 values ('20040101000000'), ('20040611093902');
+SET TIMESTAMP=100000000;
+delete from t1;
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='Europe/Moscow';
+insert into t1 values ('20040101000000'), ('20040611093902');
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+delete from t1;
+set time_zone='UTC';
+load data infile '../../std_data/rpl_timezone.dat' into table t1;
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='UTC';
+select * from t1;
+t
+2004-01-01 00:00:00
+2004-06-11 09:39:02
+set time_zone='Europe/Moscow';
+set time_zone='Europe/Moscow';
+delete from t1;
+insert into t1 values ('20040101000000'), ('20040611093902');
set time_zone='MET';
insert into t2 (select t from t1);
select * from t1;
@@ -52,10 +94,6 @@ t
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
@@ -73,5 +111,16 @@ 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
+delete from t2;
+set time_zone='UTC';
+insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone));
+insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan'));
+select * from t2;
+t
+2003-12-31 23:00:00
+2005-01-01 08:00:00
+select * from t2;
+t
+2003-12-31 23:00:00
+2005-01-01 08:00:00
drop table t1, t2;
diff --git a/mysql-test/r/rpl_trigger.result b/mysql-test/r/rpl_trigger.result
new file mode 100644
index 00000000000..db824c9c423
--- /dev/null
+++ b/mysql-test/r/rpl_trigger.result
@@ -0,0 +1,108 @@
+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 auto_increment, primary key (a), b int, rand_value double not null);
+create table t2 (a int auto_increment, primary key (a), b int);
+create table t3 (a int auto_increment, primary key (a), name varchar(64) not null, old_a int, old_b int, rand_value double not null);
+create trigger t1 before insert on t1 for each row
+begin
+insert into t3 values (NULL, "t1", new.a, new.b, rand());
+end|
+create trigger t2 after insert on t2 for each row
+begin
+insert into t3 values (NULL, "t2", new.a, new.b, rand());
+end|
+insert into t3 values(100,"log",0,0,0);
+SET @@RAND_SEED1=658490765, @@RAND_SEED2=635893186;
+insert into t1 values(1,1,rand()),(NULL,2,rand());
+insert into t2 (b) values(last_insert_id());
+insert into t2 values(3,0),(NULL,0);
+insert into t2 values(NULL,0),(500,0);
+select a,b, truncate(rand_value,4) from t1;
+a b truncate(rand_value,4)
+1 1 0.4320
+2 2 0.3055
+select * from t2;
+a b
+1 2
+3 0
+4 0
+5 0
+500 0
+select a,name, old_a, old_b, truncate(rand_value,4) from t3;
+a name old_a old_b truncate(rand_value,4)
+100 log 0 0 0.0000
+101 t1 1 1 0.3203
+102 t1 0 2 0.5666
+103 t2 1 2 0.9164
+104 t2 3 0 0.8826
+105 t2 4 0 0.6635
+106 t2 5 0 0.6699
+107 t2 500 0 0.3593
+
+--- On slave --
+select a,b, truncate(rand_value,4) from t1;
+a b truncate(rand_value,4)
+1 1 0.4320
+2 2 0.3055
+select * from t2;
+a b
+1 2
+3 0
+4 0
+5 0
+500 0
+select a,name, old_a, old_b, truncate(rand_value,4) from t3;
+a name old_a old_b truncate(rand_value,4)
+100 log 0 0 0.0000
+101 t1 1 1 0.3203
+102 t1 0 2 0.5666
+103 t2 1 2 0.9164
+104 t2 3 0 0.8826
+105 t2 4 0 0.6635
+106 t2 5 0 0.6699
+107 t2 500 0 0.3593
+drop table t1,t2,t3;
+select get_lock("bug12480",2);
+get_lock("bug12480",2)
+1
+create table t1 (a datetime,b datetime, c datetime);
+drop function if exists bug12480;
+Warnings:
+Note 1305 FUNCTION bug12480 does not exist
+create function bug12480() returns datetime
+begin
+set @a=get_lock("bug12480",2);
+return now();
+end|
+create trigger t1_first before insert on t1
+for each row begin
+set @a=get_lock("bug12480",2);
+set new.b= now();
+set new.c= bug12480();
+end
+|
+insert into t1 set a = now();
+select a=b && a=c from t1;
+a=b && a=c
+1
+
+--- On slave --
+select a=b && a=c from t1;
+a=b && a=c
+1
+test
+1
+truncate table t1;
+drop trigger t1_first;
+insert into t1 values ("2003-03-03","2003-03-03","2003-03-03"),(bug12480(),bug12480(),bug12480()),(now(),now(),now());
+select a=b && a=c from t1;
+a=b && a=c
+1
+1
+1
+drop function bug12480;
+drop table t1;
diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result
deleted file mode 100644
index 085a2937584..00000000000
--- a/mysql-test/r/rpl_trunc_binlog.result
+++ /dev/null
@@ -1,13 +0,0 @@
-stop slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-start slave;
-stop slave;
-flush logs;
-reset slave;
-start slave;
-show slave status;
-Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 slave-relay-bin.000002 123 master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. A probable cause is that the master died while writing the transaction to its binary log. 0 79 # None 0 No #
diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result
index 5772f176919..64efeab0145 100644
--- a/mysql-test/r/rpl_until.result
+++ b/mysql-test/r/rpl_until.result
@@ -13,16 +13,16 @@ insert into t2 values (1),(2);
insert into t2 values (3),(4);
drop table t2;
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(n int not null auto_increment primary key)
-master-bin.000001 172 Query 1 172 use `test`; insert into t1 values (1),(2),(3),(4)
-master-bin.000001 244 Query 1 244 use `test`; drop table t1
-master-bin.000001 292 Query 1 292 use `test`; create table t2(n int not null auto_increment primary key)
-master-bin.000001 385 Query 1 385 use `test`; insert into t2 values (1),(2)
-master-bin.000001 449 Query 1 449 use `test`; insert into t2 values (3),(4)
-master-bin.000001 513 Query 1 513 use `test`; drop table t2
-start slave until master_log_file='master-bin.000001', master_log_pos=244;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 98 Server ver: VERSION, Binlog ver: 4
+master-bin.000001 98 Query 1 219 use `test`; create table t1(n int not null auto_increment primary key)
+master-bin.000001 219 Query 1 319 use `test`; insert into t1 values (1),(2),(3),(4)
+master-bin.000001 319 Query 1 395 use `test`; drop table t1
+master-bin.000001 395 Query 1 516 use `test`; create table t2(n int not null auto_increment primary key)
+master-bin.000001 516 Query 1 608 use `test`; insert into t2 values (1),(2)
+master-bin.000001 608 Query 1 700 use `test`; insert into t2 values (3),(4)
+master-bin.000001 700 Query 1 776 use `test`; drop table t2
+start slave until master_log_file='master-bin.000001', master_log_pos=319;
select * from t1;
n
1
@@ -31,7 +31,7 @@ n
4
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 561 slave-relay-bin.000002 # master-bin.000001 Yes No 0 0 244 # Master master-bin.000001 244 No #
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 319 # Master master-bin.000001 319 No #
start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
select * from t1;
n
@@ -41,21 +41,21 @@ n
4
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 561 slave-relay-bin.000002 # master-bin.000001 Yes No 0 0 244 # Master master-no-such-bin.000001 291 No #
-start slave until relay_log_file='slave-relay-bin.000002', relay_log_pos=537;
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 319 # Master master-no-such-bin.000001 291 No #
+start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746;
select * from t2;
n
1
2
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 561 slave-relay-bin.000002 # master-bin.000001 Yes No 0 0 449 # Relay slave-relay-bin.000002 537 No #
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 608 # Relay slave-relay-bin.000004 746 No #
start slave;
stop slave;
-start slave until master_log_file='master-bin.000001', master_log_pos=561;
+start slave until master_log_file='master-bin.000001', master_log_pos=776;
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 561 slave-relay-bin.000002 # master-bin.000001 Yes No 0 0 561 # Master master-bin.000001 561 No #
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 776 # Master master-bin.000001 776 No #
start slave until master_log_file='master-bin', master_log_pos=561;
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;
@@ -67,6 +67,6 @@ ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UN
start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561;
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=561;
+start slave until master_log_file='master-bin.000001', master_log_pos=776;
Warnings:
Note 1254 Slave is already running
diff --git a/mysql-test/r/rpl_user_variables.result b/mysql-test/r/rpl_user_variables.result
index 85768270ba3..4198bbcc154 100644
--- a/mysql-test/r/rpl_user_variables.result
+++ b/mysql-test/r/rpl_user_variables.result
@@ -76,34 +76,35 @@ abcn1n2
NULL
NULL
NULL
-show binlog events from 141;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-slave-bin.000001 141 User var 2 141 @`i1`=12345678901234
-slave-bin.000001 184 User var 2 184 @`i2`=-12345678901234
-slave-bin.000001 227 User var 2 227 @`i3`=0
-slave-bin.000001 270 User var 2 270 @`i4`=-1
-slave-bin.000001 313 Query 1 313 use `test`; insert into t1 values (@i1), (@i2), (@i3), (@i4)
-slave-bin.000001 396 User var 2 396 @`r1`=12.5
-slave-bin.000001 439 User var 2 439 @`r2`=-12.5
-slave-bin.000001 482 Query 1 482 use `test`; insert into t1 values (@r1), (@r2)
-slave-bin.000001 551 User var 2 551 @`s1`=_latin1 0x5468697320697320612074657374 COLLATE latin1_swedish_ci
-slave-bin.000001 600 User var 2 600 @`s2`=_latin1 "" COLLATE latin1_swedish_ci
-slave-bin.000001 635 User var 2 635 @`s3`=_latin1 0x61626327646566 COLLATE latin1_swedish_ci
-slave-bin.000001 677 User var 2 677 @`s4`=_latin1 0x6162635C646566 COLLATE latin1_swedish_ci
-slave-bin.000001 719 User var 2 719 @`s5`=_latin1 0x61626327646566 COLLATE latin1_swedish_ci
-slave-bin.000001 761 Query 1 761 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5)
-slave-bin.000001 851 User var 2 851 @`n1`=NULL
-slave-bin.000001 877 Query 1 877 use `test`; insert into t1 values (@n1)
-slave-bin.000001 939 User var 2 939 @`n2`=NULL
-slave-bin.000001 965 Query 1 965 use `test`; insert into t1 values (@n2)
-slave-bin.000001 1027 Query 1 1027 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1)
-slave-bin.000001 1115 User var 2 1115 @`a`=2
-slave-bin.000001 1157 Query 1 1157 use `test`; insert into t1 values (@a+(@b:=@a+1))
-slave-bin.000001 1229 User var 2 1229 @`q`=_latin1 0x616263 COLLATE latin1_swedish_ci
-slave-bin.000001 1266 Query 1 1266 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'))
-slave-bin.000001 1370 User var 2 1370 @`a`=5
-slave-bin.000001 1412 Query 1 1412 use `test`; insert into t1 values (@a),(@a)
-slave-bin.000001 1478 User var 2 1478 @`a`=NULL
-slave-bin.000001 1503 Query 1 1503 use `test`; insert into t1 values (@a),(@a),(@a*5)
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Query 1 # use `test`; create table t1(n char(30))
+slave-bin.000001 # User var 2 # @`i1`=12345678901234
+slave-bin.000001 # User var 2 # @`i2`=-12345678901234
+slave-bin.000001 # User var 2 # @`i3`=0
+slave-bin.000001 # User var 2 # @`i4`=-1
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@i1), (@i2), (@i3), (@i4)
+slave-bin.000001 # User var 2 # @`r1`=12.5
+slave-bin.000001 # User var 2 # @`r2`=-12.5
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@r1), (@r2)
+slave-bin.000001 # User var 2 # @`s1`=_latin1 0x5468697320697320612074657374 COLLATE latin1_swedish_ci
+slave-bin.000001 # User var 2 # @`s2`=_latin1 "" COLLATE latin1_swedish_ci
+slave-bin.000001 # User var 2 # @`s3`=_latin1 0x61626327646566 COLLATE latin1_swedish_ci
+slave-bin.000001 # User var 2 # @`s4`=_latin1 0x6162635C646566 COLLATE latin1_swedish_ci
+slave-bin.000001 # User var 2 # @`s5`=_latin1 0x61626327646566 COLLATE latin1_swedish_ci
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5)
+slave-bin.000001 # User var 2 # @`n1`=NULL
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@n1)
+slave-bin.000001 # User var 2 # @`n2`=NULL
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@n2)
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1)
+slave-bin.000001 # User var 2 # @`a`=2
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@a+(@b:=@a+1))
+slave-bin.000001 # User var 2 # @`q`=_latin1 0x616263 COLLATE latin1_swedish_ci
+slave-bin.000001 # Query 1 # use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'))
+slave-bin.000001 # User var 2 # @`a`=5
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@a),(@a)
+slave-bin.000001 # User var 2 # @`a`=NULL
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (@a),(@a),(@a*5)
drop table t1;
stop slave;
diff --git a/mysql-test/r/rpl_variables.result b/mysql-test/r/rpl_variables.result
index 227d8ecfad9..25b5ca13f77 100644
--- a/mysql-test/r/rpl_variables.result
+++ b/mysql-test/r/rpl_variables.result
@@ -6,3 +6,12 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
set global slave_net_timeout=100;
set global sql_slave_skip_counter=100;
+show variables like 'slave_compressed_protocol';
+Variable_name Value
+slave_compressed_protocol OFF
+show variables like 'slave_load_tmpdir';
+Variable_name Value
+slave_load_tmpdir SLAVE_LOAD_TMPDIR
+show variables like 'slave_skip_errors';
+Variable_name Value
+slave_skip_errors 3,100,137,643,1752
diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result
new file mode 100644
index 00000000000..cf4c161b296
--- /dev/null
+++ b/mysql-test/r/rpl_view.result
@@ -0,0 +1,56 @@
+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,v1;
+drop view if exists t1,v1;
+reset master;
+create table t1 (a int);
+insert into t1 values (1);
+create view v1 as select a from t1;
+insert into v1 values (2);
+select * from v1 order by a;
+a
+1
+2
+select * from v1 order by a;
+a
+1
+2
+update v1 set a=3 where a=1;
+select * from v1 order by a;
+a
+2
+3
+select * from v1 order by a;
+a
+2
+3
+delete from v1 where a=2;
+select * from v1 order by a;
+a
+3
+select * from v1 order by a;
+a
+3
+alter view v1 as select a as b from t1;
+select * from v1 order by 1;
+b
+3
+drop view v1;
+select * from v1 order by a;
+ERROR 42S02: Table 'test.v1' doesn't exist
+drop table t1;
+show binlog events limit 1,100;
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Query 1 # use `test`; create table t1 (a int)
+slave-bin.000001 # Query 1 # use `test`; insert into t1 values (1)
+slave-bin.000001 # Query 1 # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW v1 AS select a from t1
+slave-bin.000001 # Query 1 # use `test`; insert into v1 values (2)
+slave-bin.000001 # Query 1 # use `test`; update v1 set a=3 where a=1
+slave-bin.000001 # Query 1 # use `test`; delete from v1 where a=2
+slave-bin.000001 # Query 1 # use `test`; ALTER ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW v1 AS select a as b from t1
+slave-bin.000001 # Query 1 # use `test`; drop view v1
+slave-bin.000001 # Query 1 # use `test`; drop table t1
diff --git a/mysql-test/r/schema.result b/mysql-test/r/schema.result
new file mode 100644
index 00000000000..48e6ebcfad2
--- /dev/null
+++ b/mysql-test/r/schema.result
@@ -0,0 +1,11 @@
+create schema foo;
+show create schema foo;
+Database Create Database
+foo CREATE DATABASE `foo` /*!40100 DEFAULT CHARACTER SET latin1 */
+show schemas;
+Database
+information_schema
+foo
+mysql
+test
+drop schema foo;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 993fe7d22f1..e3af75a4573 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -1,5 +1,6 @@
drop table if exists t1,t2,t3,t4;
-drop table if exists t1_1,t1_2,t9_1,t9_2;
+drop table if exists t1_1,t1_2,t9_1,t9_2,t1aa,t2aa;
+drop view if exists v1;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
@@ -1363,6 +1364,17 @@ explain select t2.companynr,companyname from t4 left join t2 using (companynr) w
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 12
1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists
+select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+companynr companyname
+select count(*) from t2 left join t4 using (companynr) where companynr is not null;
+count(*)
+1200
+explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
delete from t2 where fld1=999999;
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;
id select_type table type possible_keys key key_len ref rows Extra
@@ -1375,7 +1387,19 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
-1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 12
@@ -1388,14 +1412,26 @@ explain select t2.companynr,companyname from t4 left join t2 using (companynr) w
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 12
1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
companynr companynr
37 36
41 40
explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using temporary
-1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using where; Using index
+1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008;
fld1 companynr fld3 period
038008 37 reporters 1008
@@ -1471,7 +1507,7 @@ explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
Warnings:
-Note 1003 select count(0) AS `count(*)`,min(test.t2.fld4) AS `min(fld4)`,max(test.t2.fld4) AS `max(fld4)`,sum(test.t2.fld1) AS `sum(fld1)`,avg(test.t2.fld1) AS `avg(fld1)`,std(test.t2.fld1) AS `std(fld1)`,variance(test.t2.fld1) AS `variance(fld1)` from test.t2 where ((test.t2.companynr = 34) and (test.t2.fld4 <> _latin1''))
+Note 1003 select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where ((`test`.`t2`.`companynr` = 34) and (`test`.`t2`.`fld4` <> _latin1''))
select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087
@@ -1671,7 +1707,7 @@ fld1 count(*)
158402 4181
select sum(Period)/count(*) from t1;
sum(Period)/count(*)
-9410.00
+9410.0000
select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr;
companynr count sum diff func
37 12543 309394878010 0.0000 464091
@@ -1683,7 +1719,7 @@ companynr count sum diff func
512 4181 3288532102 0.0000 2140672
select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg;
companynr avg
-154 983543950.00
+154 983543950.0000
select companynr,count(*) from t2 group by companynr order by 2 desc;
companynr count(*)
37 588
@@ -2033,20 +2069,20 @@ show tables from test like "t?";
Tables_in_test (t?)
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(11) NULL PRI NULL auto_increment #
-fld1 int(6) unsigned zerofill NULL UNI 000000 #
-companynr tinyint(2) unsigned zerofill NULL 00 #
-fld3 char(30) latin1_swedish_ci MUL #
-fld4 char(35) latin1_swedish_ci #
-fld5 char(35) latin1_swedish_ci #
-fld6 char(4) latin1_swedish_ci #
+auto int(11) NULL NO PRI NULL auto_increment #
+fld1 int(6) unsigned zerofill NULL NO UNI 000000 #
+companynr tinyint(2) unsigned zerofill NULL NO 00 #
+fld3 char(30) latin1_swedish_ci NO MUL #
+fld4 char(35) latin1_swedish_ci NO #
+fld5 char(35) latin1_swedish_ci NO #
+fld6 char(4) latin1_swedish_ci NO #
show full columns from t2 from test like 'f%';
Field Type Collation Null Key Default Extra Privileges Comment
-fld1 int(6) unsigned zerofill NULL UNI 000000 #
-fld3 char(30) latin1_swedish_ci MUL #
-fld4 char(35) latin1_swedish_ci #
-fld5 char(35) latin1_swedish_ci #
-fld6 char(4) latin1_swedish_ci #
+fld1 int(6) unsigned zerofill NULL NO UNI 000000 #
+fld3 char(30) latin1_swedish_ci NO MUL #
+fld4 char(35) latin1_swedish_ci NO #
+fld5 char(35) latin1_swedish_ci NO #
+fld6 char(4) latin1_swedish_ci NO #
show full columns from t2 from test like 's%';
Field Type Collation Null Key Default Extra Privileges Comment
show keys from t2;
@@ -2072,17 +2108,15 @@ INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 1 as rnd1 from t1 where rand() > 2;
rnd1
DROP TABLE t1;
-CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp(14) NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
+CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL);
CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM;
INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35);
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'
+Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
+Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
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;
@@ -2110,196 +2144,165 @@ select @b;
aaaa
select @c;
@c
-6.26
+6.260
create table t1 (a int not null auto_increment primary key);
insert into t1 values ();
insert into t1 values ();
insert into t1 values ();
select * from (t1 as t2 left join t1 as t3 using (a)), t1;
-a a a
-1 1 1
-2 2 1
-3 3 1
-1 1 2
-2 2 2
-3 3 2
-1 1 3
-2 2 3
-3 3 3
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
select * from t1, (t1 as t2 left join t1 as t3 using (a));
-a a a
-1 1 1
-2 1 1
-3 1 1
-1 2 2
-2 2 2
-3 2 2
-1 3 3
-2 3 3
-3 3 3
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
select * from (t1 as t2 left join t1 as t3 using (a)) straight_join t1;
-a a a
-1 1 1
-2 2 1
-3 3 1
-1 1 2
-2 2 2
-3 3 2
-1 1 3
-2 2 3
-3 3 3
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
select * from t1 straight_join (t1 as t2 left join t1 as t3 using (a));
-a a a
-1 1 1
-2 1 1
-3 1 1
-1 2 2
-2 2 2
-3 2 2
-1 3 3
-2 3 3
-3 3 3
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 on t1.a>1;
-a a a
-1 1 2
-1 1 3
-2 2 2
-2 2 3
-3 3 2
-3 3 3
+a a
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
-a a a
-1 1 NULL
-2 1 1
-3 1 1
-1 2 NULL
-2 2 2
-3 2 2
-1 3 NULL
-2 3 3
-3 3 3
+a a
+2 1
+3 1
+2 2
+3 2
+2 3
+3 3
select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 using ( a );
-a a a
-1 1 1
-2 2 2
-3 3 3
+a
+1
+2
+3
select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) using ( a );
-a a a
-1 1 1
-2 1 NULL
-3 1 NULL
-1 2 NULL
-2 2 2
-3 2 NULL
-1 3 NULL
-2 3 NULL
-3 3 3
+a
+1
+2
+3
select * from (t1 as t2 left join t1 as t3 using (a)) left outer join t1 on t1.a>1;
-a a a
-1 1 2
-1 1 3
-2 2 2
-2 2 3
-3 3 2
-3 3 3
+a a
+1 2
+1 3
+2 2
+2 3
+3 2
+3 3
select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
-a a a
-1 1 NULL
-2 1 1
-3 1 1
-1 2 NULL
-2 2 2
-3 2 2
-1 3 NULL
-2 3 3
-3 3 3
+a a
+1 NULL
+2 1
+2 2
+2 3
+3 1
+3 2
+3 3
select * from (t1 as t2 left join t1 as t3 using (a)) left join t1 using ( a );
-a a a
-1 1 1
-2 2 2
-3 3 3
+a
+1
+2
+3
select * from t1 left join (t1 as t2 left join t1 as t3 using (a)) using ( a );
-a a a
-1 1 1
-2 1 NULL
-3 1 NULL
-1 2 NULL
-2 2 2
-3 2 NULL
-1 3 NULL
-2 3 NULL
-3 3 3
+a
+1
+2
+3
select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
-a a a
-1 1 1
-2 2 2
-3 3 3
+a
+1
+2
+3
select * from t1 natural left join (t1 as t2 left join t1 as t3 using (a));
-a a a
-1 1 1
-2 2 2
-3 3 3
+a
+1
+2
+3
select * from (t1 as t2 left join t1 as t3 using (a)) right join t1 on t1.a>1;
-a a a
-1 NULL 1
-2 NULL 1
-3 NULL 1
-1 1 2
-2 2 2
-3 3 2
-1 1 3
-2 2 3
-3 3 3
+a a
+NULL 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
select * from t1 right join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
-a a a
-2 1 1
-3 1 1
-2 2 2
-3 2 2
-2 3 3
-3 3 3
+a a
+2 1
+3 1
+2 2
+3 2
+2 3
+3 3
select * from (t1 as t2 left join t1 as t3 using (a)) right outer join t1 using ( a );
-a a a
-1 1 1
-2 NULL 1
-3 NULL 1
-1 NULL 2
-2 2 2
-3 NULL 2
-1 NULL 3
-2 NULL 3
-3 3 3
+a
+1
+2
+3
select * from t1 right outer join (t1 as t2 left join t1 as t3 using (a)) using ( a );
-a a a
-1 1 1
-2 2 2
-3 3 3
+a
+1
+2
+3
select * from (t1 as t2 left join t1 as t3 using (a)) natural right join t1;
-a a a
-1 1 1
-2 NULL 1
-3 NULL 1
-1 NULL 2
-2 2 2
-3 NULL 2
-1 NULL 3
-2 NULL 3
-3 3 3
+a
+1
+2
+3
select * from t1 natural right join (t1 as t2 left join t1 as t3 using (a));
-a a a
-1 1 1
-2 2 2
-3 3 3
+a
+1
+2
+3
select * from t1 natural join (t1 as t2 left join t1 as t3 using (a));
-a a
-1 1
-2 2
-3 3
+a
+1
+2
+3
select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1;
-a a a
-1 1 1
-2 2 2
-3 3 3
+a
+1
+2
+3
drop table t1;
CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) ENGINE=MyISAM;
INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522);
@@ -2345,7 +2348,7 @@ select * from t2 where s = 'one';
s
select * from t3 where s = 'one';
s
-one
+one
select * from t1,t2 where t1.s = t2.s;
s s
two two
@@ -2617,3 +2620,343 @@ select found_rows();
found_rows()
1
DROP TABLE t1;
+CREATE TABLE t1 ( city char(30) );
+INSERT INTO t1 VALUES ('London');
+INSERT INTO t1 VALUES ('Paris');
+SELECT * FROM t1 WHERE city='London';
+city
+London
+SELECT * FROM t1 WHERE city='london';
+city
+London
+EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+SELECT * FROM t1 WHERE city='London' AND city='london';
+city
+London
+EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
+city
+London
+DROP TABLE t1;
+create table t1 (a int(11) unsigned, b int(11) unsigned);
+insert into t1 values (1,0), (1,1), (1,2);
+select a-b from t1 order by 1;
+a-b
+0
+1
+18446744073709551615
+select a-b , (a-b < 0) from t1 order by 1;
+a-b (a-b < 0)
+0 0
+1 0
+18446744073709551615 0
+select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
+d (a-b >= 0) b
+1 1 0
+0 1 1
+18446744073709551615 1 2
+select cast((a - b) as unsigned) from t1 order by 1;
+cast((a - b) as unsigned)
+0
+1
+18446744073709551615
+drop table t1;
+create table t1 (a int(11));
+select all all * from t1;
+a
+select distinct distinct * from t1;
+a
+select all distinct * from t1;
+ERROR HY000: Incorrect usage of ALL and DISTINCT
+select distinct all * from t1;
+ERROR HY000: Incorrect usage of ALL and DISTINCT
+drop table t1;
+CREATE TABLE t1 (
+K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '',
+K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000',
+F2I4 int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO t1 VALUES
+('W%RT', '0100', 1),
+('W-RT', '0100', 1),
+('WART', '0100', 1),
+('WART', '0200', 1),
+('WERT', '0100', 2),
+('WORT','0200', 2),
+('WT', '0100', 2),
+('W_RT', '0100', 2),
+('WaRT', '0100', 3),
+('WART', '0300', 3),
+('WRT' , '0400', 3),
+('WURM', '0500', 3),
+('W%T', '0600', 4),
+('WA%T', '0700', 4),
+('WA_T', '0800', 4);
+SELECT K2C4, K4N4, F2I4 FROM t1
+WHERE K2C4 = 'WART' AND
+(F2I4 = 2 AND K2C4 = 'WART' OR (F2I4 = 2 OR K4N4 = '0200'));
+K2C4 K4N4 F2I4
+WART 0200 1
+SELECT K2C4, K4N4, F2I4 FROM t1
+WHERE K2C4 = 'WART' AND (K2C4 = 'WART' OR K4N4 = '0200');
+K2C4 K4N4 F2I4
+WART 0100 1
+WART 0200 1
+WART 0300 3
+DROP TABLE t1;
+CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
+CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
+INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
+INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref a a 23 test.t1.a 2
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref a a 23 test.t1.a 2
+DROP TABLE t1, t2;
+create table t1 (a int, b int);
+create table t2 like t1;
+select t1.a from (t1 inner join t2 on t1.a=t2.a) where t2.a=1;
+a
+select t1.a from ((t1 inner join t2 on t1.a=t2.a)) where t2.a=1;
+a
+select x.a, y.a, z.a from ( (t1 x inner join t2 y on x.a=y.a) inner join t2 z on y.a=z.a) WHERE x.a=1;
+a a a
+drop table t1,t2;
+create table t1 (s1 varchar(5));
+insert into t1 values ('Wall');
+select min(s1) from t1 group by s1 with rollup;
+min(s1)
+Wall
+Wall
+drop table t1;
+create table t1 (s1 int) engine=myisam;
+insert into t1 values (0);
+select avg(distinct s1) from t1 group by s1 with rollup;
+avg(distinct s1)
+0.0000
+0.0000
+drop table t1;
+create table t1 (s1 int);
+insert into t1 values (null),(1);
+select distinct avg(s1) as x from t1 group by s1 with rollup;
+x
+NULL
+1.0000
+drop table t1;
+create table t1 (a int(11));
+select all all * from t1;
+a
+select distinct distinct * from t1;
+a
+select all distinct * from t1;
+ERROR HY000: Incorrect usage of ALL and DISTINCT
+select distinct all * from t1;
+ERROR HY000: Incorrect usage of ALL and DISTINCT
+drop table t1;
+CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
+CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
+INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
+INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref a a 23 test.t1.a 2
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref a a 23 test.t1.a 2
+DROP TABLE t1, t2;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+INSERT INTO t2 VALUES (2), (4), (6);
+SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a;
+a
+2
+4
+EXPLAIN SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
+EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+DROP TABLE t1,t2;
+select x'10' + 0, X'10' + 0, b'10' + 0, B'10' + 0;
+x'10' + 0 X'10' + 0 b'10' + 0 B'10' + 0
+16 16 2 2
+create table t1 (f1 varchar(6) default NULL, f2 int(6) primary key not null);
+create table t2 (f3 varchar(5) not null, f4 varchar(5) not null, UNIQUE KEY UKEY (f3,f4));
+insert into t1 values (" 2", 2);
+insert into t2 values (" 2", " one "),(" 2", " two ");
+select * from t1 left join t2 on f1 = f3;
+f1 f2 f3 f4
+ 2 2 2 one
+ 2 2 2 two
+drop table t1,t2;
+create table t1 (empnum smallint, grp int);
+create table t2 (empnum int, name char(5));
+insert into t1 values(1,1);
+insert into t2 values(1,'bob');
+create view v1 as select * from t2 inner join t1 using (empnum);
+select * from v1;
+empnum name grp
+1 bob 1
+drop table t1,t2;
+drop view v1;
+create table t1 (pk int primary key, b int);
+create table t2 (pk int primary key, c int);
+select pk from t1 inner join t2 using (pk);
+pk
+drop table t1,t2;
+create table t1 (s1 int, s2 char(5), s3 decimal(10));
+create view v1 as select s1, s2, 'x' as s3 from t1;
+select * from t1 natural join v1;
+s1 s2 s3
+insert into t1 values (1,'x',5);
+select * from t1 natural join v1;
+s1 s2 s3
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'x'
+drop table t1;
+drop view v1;
+create table t1(a1 int);
+create table t2(a2 int);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+create view v2 (c) as select a1 from t1;
+select * from t1 natural left join t2;
+a1 a2
+1 1
+1 2
+2 1
+2 2
+select * from t1 natural right join t2;
+a2 a1
+1 1
+1 2
+2 1
+2 2
+select * from v2 natural left join t2;
+c a2
+1 1
+1 2
+2 1
+2 2
+select * from v2 natural right join t2;
+a2 c
+1 1
+1 2
+2 1
+2 2
+drop table t1, t2;
+drop view v2;
+create table t1 (a int(10), t1_val int(10));
+create table t2 (b int(10), t2_val int(10));
+create table t3 (a int(10), b int(10));
+insert into t1 values (1,1),(2,2);
+insert into t2 values (1,1),(2,2),(3,3);
+insert into t3 values (1,1),(2,1),(3,1),(4,1);
+select * from t1 natural join t2 natural join t3;
+a b t1_val t2_val
+1 1 1 1
+2 1 2 1
+select * from t1 natural join t3 natural join t2;
+b a t1_val t2_val
+1 1 1 1
+1 2 2 1
+drop table t1, t2, t3;
+DO IFNULL(NULL, NULL);
+SELECT CAST(IFNULL(NULL, NULL) AS DECIMAL);
+CAST(IFNULL(NULL, NULL) AS DECIMAL)
+NULL
+SELECT ABS(IFNULL(NULL, NULL));
+ABS(IFNULL(NULL, NULL))
+NULL
+SELECT IFNULL(NULL, NULL);
+IFNULL(NULL, NULL)
+NULL
+create table t1 (a char(1));
+create table t2 (a char(1));
+insert into t1 values ('a'),('b'),('c');
+insert into t2 values ('b'),('c'),('d');
+select a from t1 natural join t2;
+a
+b
+c
+select * from t1 natural join t2 where a = 'b';
+a
+b
+drop table t1, t2;
+CREATE TABLE t1 (`id` TINYINT);
+CREATE TABLE t2 (`id` TINYINT);
+CREATE TABLE t3 (`id` TINYINT);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t3 VALUES (3);
+SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.notacolumn=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT id,t3.id FROM (t1 JOIN t2 ON (t2.id=t1.id)) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+drop table t1, t2, t3;
+create table t1 (a int(10),b int(10));
+create table t2 (a int(10),b int(10));
+insert into t1 values (1,10),(2,20),(3,30);
+insert into t2 values (1,10);
+select * from t1 inner join t2 using (A);
+a b b
+1 10 10
+select * from t1 inner join t2 using (a);
+a b b
+1 10 10
+drop table t1, t2;
+create table t1 (a int, c int);
+create table t2 (b int);
+create table t3 (b int, a int);
+create table t4 (c int);
+insert into t1 values (1,1);
+insert into t2 values (1);
+insert into t3 values (1,1);
+insert into t4 values (1);
+select * from t1 join t2 join t3 on (t2.b = t3.b and t1.a = t3.a);
+a c b b a
+1 1 1 1 1
+select * from t1, t2 join t3 on (t2.b = t3.b and t1.a = t3.a);
+ERROR 42S22: Unknown column 't1.a' in 'on clause'
+select * from t1 join t2 join t3 join t4 on (t1.a = t4.c and t2.b = t4.c);
+a c b b a c
+1 1 1 1 1 1
+select * from t1 join t2 join t4 using (c);
+c a b
+1 1 1
+drop table t1, t2, t3, t4;
+create table t1(x int, y int);
+create table t2(x int, y int);
+create table t3(x int, primary key(x));
+insert into t1 values (1, 1), (2, 1), (3, 1), (4, 3), (5, 6), (6, 6);
+insert into t2 values (1, 1), (2, 1), (3, 3), (4, 6), (5, 6);
+insert into t3 values (1), (2), (3), (4), (5);
+select t1.x, t3.x from t1, t2, t3 where t1.x = t2.x and t3.x >= t1.y and t3.x <= t2.y;
+x x
+1 1
+2 1
+3 1
+3 2
+3 3
+4 3
+4 4
+4 5
+drop table t1,t2,t3;
diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result
index b8178bbeb52..7abd65beb46 100644
--- a/mysql-test/r/select_found.result
+++ b/mysql-test/r/select_found.result
@@ -84,7 +84,7 @@ UNIQUE KEY e_n (email,name)
EXPLAIN SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system PRIMARY,kid NULL NULL NULL 0 const row not found
-1 SIMPLE t2 index NULL e_n 100 NULL 200
+1 SIMPLE t2 index NULL e_n 104 NULL 200
SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
email
email1
diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result
index 7a29db42dd9..feac9efcb13 100644
--- a/mysql-test/r/select_safe.result
+++ b/mysql-test/r/select_safe.result
@@ -60,9 +60,6 @@ a b
3 a
4 a
5 a
-SELECT @@MAX_SEEKS_FOR_KEY;
-@@MAX_SEEKS_FOR_KEY
-4294967295
analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
@@ -87,7 +84,7 @@ set local max_join_size=8;
select * from (select * from t1) x;
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 local max_join_size=1;
-select * from (select * from t1 a, t1 b) x;
+select * from (select a.a as aa, b.a as ba from t1 a, t1 b) x;
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 local max_join_size=1;
select * from (select 1 union select 2 union select 3) x;
diff --git a/mysql-test/r/have_isam.require b/mysql-test/r/server_id.require
index 9b4142361ed..adffcc483b1 100644
--- a/mysql-test/r/have_isam.require
+++ b/mysql-test/r/server_id.require
@@ -1,2 +1,2 @@
Variable_name Value
-have_isam YES
+server_id 1
diff --git a/mysql-test/r/server_id1.require b/mysql-test/r/server_id1.require
new file mode 100644
index 00000000000..666c94ef633
--- /dev/null
+++ b/mysql-test/r/server_id1.require
@@ -0,0 +1,2 @@
+Variable_name Value
+server_id 102
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 1e5e8f442a8..c143c7f0f29 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2;
+drop table if exists t1aa,t2aa;
drop database if exists mysqltest;
delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
@@ -50,6 +51,7 @@ show table status from test like "this_doesn't_exists%";
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
+information_schema
mysql
test
show databases like "test%";
@@ -80,13 +82,13 @@ create temporary table t1 (a int not null);
show create table t1;
Table Create Table
t1 CREATE TEMPORARY TABLE `t1` (
- `a` int(11) NOT NULL default '0'
+ `a` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 rename t2;
show create table t2;
Table Create Table
t2 CREATE TEMPORARY TABLE `t2` (
- `a` int(11) NOT NULL default '0'
+ `a` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t2;
create table t1 (
@@ -101,7 +103,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`test_set` set('val1','val2','val3') NOT NULL default '',
`name` char(20) default 'O''Brien' COMMENT 'O''Brien as default',
- `c` int(11) NOT NULL default '0' COMMENT 'int column',
+ `c` int(11) NOT NULL COMMENT 'int column',
`c-b` int(11) default NULL COMMENT 'name with a minus',
`space 2` int(11) default NULL COMMENT 'name with a space'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='it''s a table'
@@ -110,17 +112,17 @@ show create table t1;
Table Create Table
t1 CREATE TABLE t1 (
test_set set('val1','val2','val3') NOT NULL default '',
- name char(20) default 'O''Brien' COMMENT 'O''Brien as default',
- c int(11) NOT NULL default '0' COMMENT 'int column',
+ `name` char(20) default 'O''Brien' COMMENT 'O''Brien as default',
+ c int(11) NOT NULL COMMENT 'int column',
`c-b` int(11) default NULL COMMENT 'name with a minus',
`space 2` int(11) default NULL COMMENT 'name with a space'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='it''s a table'
set sql_quote_show_create=1;
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
-test_set set('val1','val2','val3') latin1_swedish_ci select,insert,update,references
+test_set set('val1','val2','val3') latin1_swedish_ci NO select,insert,update,references
name char(20) latin1_swedish_ci YES O'Brien select,insert,update,references O'Brien as default
-c int(11) NULL 0 select,insert,update,references int column
+c int(11) NULL NO select,insert,update,references int column
c-b int(11) NULL YES NULL select,insert,update,references name with a minus
space 2 int(11) NULL YES NULL select,insert,update,references name with a space
drop table t1;
@@ -128,7 +130,7 @@ create table t1 (a int not null, unique aa (a));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
UNIQUE KEY `aa` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
@@ -136,7 +138,7 @@ create table t1 (a int not null, primary key (a));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
@@ -153,15 +155,15 @@ create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CH
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
- `b` char(10) default NULL,
+ `a` int(11) NOT NULL,
+ `b` varchar(10) default NULL,
KEY `b` (`b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` varchar(10) default NULL,
KEY `b` (`b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=200 AVG_ROW_LENGTH=10 PACK_KEYS=0 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='test'
@@ -169,7 +171,7 @@ ALTER TABLE t1 AVG_ROW_LENGTH=0 CHECKSUM=0 COMMENT="" MIN_ROWS=0 MAX_ROWS=0 PACK
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` varchar(10) default NULL,
KEY `b` (`b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -193,7 +195,7 @@ h float(3,2) NULL YES NULL select,insert,update,references
i float(3,0) NULL YES NULL select,insert,update,references
drop table t1;
create table t1 (
-type_bool bool not null,
+type_bool bool not null default 0,
type_tiny tinyint not null auto_increment primary key,
type_short smallint(3),
type_mediumint mediumint,
@@ -204,9 +206,9 @@ empty_char char(0),
type_char char(2),
type_varchar varchar(10),
type_timestamp timestamp not null,
-type_date date not null,
-type_time time not null,
-type_datetime datetime not null,
+type_date date not null default '0000-00-00',
+type_time time not null default '00:00:00',
+type_datetime datetime not null default '0000-00-00 00:00:00',
type_year year,
type_enum enum ('red', 'green', 'blue'),
type_set enum ('red', 'green', 'blue'),
@@ -250,11 +252,9 @@ type_bool type_tiny type_short type_mediumint type_bigint type_decimal type_nume
drop table t1;
create table t1 (a int not null);
create table t2 select max(a) from t1;
-Warnings:
-Warning 1263 Data truncated; NULL supplied to NOT NULL column 'max(a)' at row 1
show columns from t2;
Field Type Null Key Default Extra
-max(a) int(11) 0
+max(a) int(11) YES NULL
drop table t1,t2;
create table t1 (c decimal, d double, f float, r real);
show columns from t1;
@@ -267,15 +267,14 @@ drop table t1;
create table t1 (c decimal(3,3), d double(3,3), f float(3,3));
show columns from t1;
Field Type Null Key Default Extra
-c decimal(4,3) YES NULL
-d double(4,3) YES NULL
-f float(4,3) YES NULL
+c decimal(3,3) YES NULL
+d double(3,3) YES NULL
+f float(3,3) YES NULL
drop table t1;
SET @old_sql_mode= @@sql_mode, sql_mode= '';
SET @old_sql_quote_show_create= @@sql_quote_show_create, sql_quote_show_create= OFF;
CREATE TABLE `a/b` (i INT);
ERROR 42000: Incorrect table name 'a/b'
-SET sql_mode= 'ANSI_QUOTES';
SET sql_mode= '';
SET sql_quote_show_create= OFF;
CREATE TABLE t1 (i INT);
@@ -299,7 +298,7 @@ select @@max_heap_table_size;
1047552
CREATE TABLE t1 (
a int(11) default NULL,
-KEY a TYPE BTREE (a)
+KEY a USING BTREE (a)
) ENGINE=HEAP;
CREATE TABLE t2 (
b int(11) default NULL,
@@ -308,7 +307,7 @@ index(b)
CREATE TABLE t3 (
a int(11) default NULL,
b int(11) default NULL,
-KEY a TYPE BTREE (a),
+KEY a USING BTREE (a),
index(b)
) ENGINE=HEAP;
insert into t1 values (1),(2);
@@ -316,57 +315,57 @@ insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
show table status;
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 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 2 # # # # 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 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 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 4 # # # # 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 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 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 5 # # # # 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 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 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP 9 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP 9 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1;
delete from t2;
delete from t3;
show table status;
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 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 0 # # # # 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 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 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 1 # # # # 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 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 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 HEAP 9 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 HEAP 9 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
+t1 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
+t3 MEMORY 10 Fixed 0 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL
drop table t1, t2, t3;
create database mysqltest;
show create database mysqltest;
@@ -384,19 +383,19 @@ show create database mysqltest;
Database Create Database
mysqltest CREATE DATABASE `mysqltest` /*!40100 DEFAULT CHARACTER SET latin1 */
drop table t1;
-ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest'
+ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 't1'
drop database mysqltest;
ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysqltest'
select * from mysqltest.t1;
-ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'mysqltest'
+ERROR 42000: SELECT command denied to user 'mysqltest_2'@'localhost' for table 't1'
show create database mysqltest;
ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'mysqltest'
drop table mysqltest.t1;
-ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'mysqltest'
+ERROR 42000: DROP command denied to user 'mysqltest_2'@'localhost' for table 't1'
drop database mysqltest;
ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'mysqltest'
select * from mysqltest.t1;
-ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysqltest'
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 't1'
show create database mysqltest;
ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysqltest'
drop table mysqltest.t1;
@@ -413,7 +412,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) default NULL,
KEY `i` (`i`)
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (i int, KEY USING HASH (i)) ENGINE=MEMORY;
SHOW CREATE TABLE t1;
@@ -421,7 +420,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) default NULL,
KEY `i` USING HASH (`i`)
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (i int, KEY USING BTREE (i)) ENGINE=MEMORY;
SHOW CREATE TABLE t1;
@@ -429,7 +428,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) default NULL,
KEY `i` USING BTREE (`i`)
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (i int, KEY (i)) ENGINE=MyISAM;
SHOW CREATE TABLE t1;
@@ -460,7 +459,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) default NULL,
KEY `i` (`i`)
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (i int, KEY USING BTREE (i)) ENGINE=MyISAM;
SHOW CREATE TABLE t1;
@@ -475,7 +474,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`i` int(11) default NULL,
KEY `i` USING BTREE (`i`)
-) ENGINE=HEAP DEFAULT CHARSET=latin1
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1(
field1 text NOT NULL,
@@ -483,18 +482,18 @@ PRIMARY KEY(field1(1000))
);
show index from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def Table 253 64 2 N 129 31 63
-def Non_unique 1 1 1 N 32929 0 63
-def Key_name 253 64 7 N 129 31 63
-def Seq_in_index 1 2 1 N 32929 0 63
-def Column_name 253 64 6 N 129 31 63
-def Collation 253 1 1 Y 128 31 63
-def Cardinality 8 21 1 Y 32896 0 63
-def Sub_part 2 3 4 Y 32928 0 63
-def Packed 253 10 0 Y 128 31 63
-def Null 253 3 0 N 129 31 63
-def Index_type 253 16 5 N 129 31 63
-def Comment 253 255 0 N 129 31 63
+def STATISTICS TABLE_NAME Table 253 64 2 N 1 0 63
+def STATISTICS NON_UNIQUE Non_unique 8 1 1 N 32769 0 63
+def STATISTICS INDEX_NAME Key_name 253 64 7 N 1 0 63
+def STATISTICS SEQ_IN_INDEX Seq_in_index 8 2 1 N 32769 0 63
+def STATISTICS COLUMN_NAME Column_name 253 64 6 N 1 0 63
+def STATISTICS COLLATION Collation 253 1 1 Y 0 0 63
+def STATISTICS CARDINALITY Cardinality 8 21 1 Y 32768 0 63
+def STATISTICS SUB_PART Sub_part 8 3 4 Y 32768 0 63
+def STATISTICS PACKED Packed 253 10 0 Y 0 0 63
+def STATISTICS NULLABLE Null 253 3 0 N 1 0 63
+def STATISTICS INDEX_TYPE Index_type 253 16 5 N 1 0 63
+def STATISTICS COMMENT Comment 253 16 0 Y 0 0 63
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 field1 A 0 1000 NULL BTREE
drop table t1;
@@ -507,9 +506,54 @@ INDEX USING BTREE(c2)
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` int(11) NOT NULL default '0',
- `c2` int(11) NOT NULL default '0',
+ `c1` int(11) NOT NULL,
+ `c2` int(11) NOT NULL,
PRIMARY KEY USING HASH (`c1`),
KEY `c2` USING BTREE (`c2`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
+CREATE TABLE txt1(a int);
+CREATE TABLE tyt2(a int);
+CREATE TABLE urkunde(a int);
+FLUSH TABLES;
+SELECT 1 FROM mysql.db, mysql.proc, mysql.user, mysql.time_zone, mysql.time_zone_name, txt1, tyt2, urkunde LIMIT 0;
+1
+SHOW OPEN TABLES;
+Database Table In_use Name_locked
+mysql db 0 0
+test urkunde 0 0
+mysql time_zone 0 0
+mysql user 0 0
+test txt1 0 0
+mysql proc 0 0
+test tyt2 0 0
+mysql time_zone_name 0 0
+SHOW OPEN TABLES FROM mysql;
+Database Table In_use Name_locked
+mysql db 0 0
+mysql time_zone 0 0
+mysql user 0 0
+mysql proc 0 0
+mysql time_zone_name 0 0
+SHOW OPEN TABLES FROM mysql LIKE 'u%';
+Database Table In_use Name_locked
+mysql user 0 0
+SHOW OPEN TABLES LIKE 't%';
+Database Table In_use Name_locked
+mysql time_zone 0 0
+test txt1 0 0
+test tyt2 0 0
+mysql time_zone_name 0 0
+SHOW OPEN TABLES LIKE '%o%';
+Database Table In_use Name_locked
+mysql time_zone 0 0
+mysql proc 0 0
+mysql time_zone_name 0 0
+FLUSH TABLES;
+SHOW OPEN TABLES;
+Database Table In_use Name_locked
+DROP TABLE txt1;
+DROP TABLE tyt2;
+DROP TABLE urkunde;
+SHOW TABLES FROM non_existing_database;
+ERROR 42000: Unknown database 'non_existing_database'
diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result
new file mode 100644
index 00000000000..c1c31eb91c9
--- /dev/null
+++ b/mysql-test/r/skip_grants.result
@@ -0,0 +1,10 @@
+drop table if exists t1,v1;
+drop view if exists t1,v1;
+drop procedure if exists f1;
+use test;
+create table t1 (field1 INT);
+CREATE VIEW v1 AS SELECT field1 FROM t1;
+ERROR HY000: View definer is not fully qualified
+drop table t1;
+create procedure f1() select 1;
+drop procedure f1;
diff --git a/mysql-test/r/sp-big.result b/mysql-test/r/sp-big.result
new file mode 100644
index 00000000000..004ff586aab
--- /dev/null
+++ b/mysql-test/r/sp-big.result
@@ -0,0 +1,15 @@
+drop procedure if exists test.longprocedure;
+drop table if exists t1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3);
+length
+107520
+select length(routine_definition) from information_schema.routines where routine_schema = 'test' and routine_name = 'longprocedure';
+length(routine_definition)
+107530
+call test.longprocedure(@value);
+select @value;
+@value
+3
+drop procedure test.longprocedure;
+drop table t1;
diff --git a/mysql-test/r/sp-dynamic.result b/mysql-test/r/sp-dynamic.result
new file mode 100644
index 00000000000..8fe469431cc
--- /dev/null
+++ b/mysql-test/r/sp-dynamic.result
@@ -0,0 +1,364 @@
+create procedure p1()
+begin
+prepare stmt from "select 1";
+execute stmt;
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+end|
+call p1()|
+1
+1
+1
+1
+1
+1
+call p1()|
+1
+1
+1
+1
+1
+1
+call p1()|
+1
+1
+1
+1
+1
+1
+drop procedure p1|
+create procedure p1()
+begin
+execute stmt;
+end|
+prepare stmt from "call p1()"|
+execute stmt|
+ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
+execute stmt|
+ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
+execute stmt|
+ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
+call p1()|
+ERROR HY000: Recursive stored routines are not allowed.
+call p1()|
+ERROR HY000: Recursive stored routines are not allowed.
+call p1()|
+ERROR HY000: Recursive stored routines are not allowed.
+drop procedure p1|
+create procedure p1()
+begin
+prepare stmt from "create procedure p2() begin select 1; end";
+execute stmt;
+deallocate prepare stmt;
+end|
+call p1()|
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+call p1()|
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop procedure p1|
+create procedure p1()
+begin
+prepare stmt from "drop procedure p2";
+execute stmt;
+deallocate prepare stmt;
+end|
+call p1()|
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+call p1()|
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+drop procedure p1|
+create procedure p1()
+begin
+prepare stmt_drop from "drop table if exists t1";
+execute stmt_drop;
+prepare stmt from "create table t1 (a int)";
+execute stmt;
+insert into t1 (a) values (1);
+select * from t1;
+deallocate prepare stmt;
+deallocate prepare stmt_drop;
+end|
+call p1()|
+a
+1
+Warnings:
+Note 1051 Unknown table 't1'
+call p1()|
+a
+1
+drop procedure p1|
+create procedure p1()
+begin
+set @tab_name=concat("tab_", replace(curdate(), '-', '_'));
+set @drop_sql=concat("drop table if exists ", @tab_name);
+set @create_sql=concat("create table ", @tab_name, " (a int)");
+set @insert_sql=concat("insert into ", @tab_name, " values (1), (2), (3)");
+set @select_sql=concat("select * from ", @tab_name);
+select @tab_name;
+select @drop_sql;
+select @create_sql;
+select @insert_sql;
+select @select_sql;
+prepare stmt_drop from @drop_sql;
+execute stmt_drop;
+prepare stmt from @create_sql;
+execute stmt;
+prepare stmt from @insert_sql;
+execute stmt;
+prepare stmt from @select_sql;
+execute stmt;
+execute stmt_drop;
+deallocate prepare stmt;
+deallocate prepare stmt_drop;
+end|
+call p1()|
+call p1()|
+drop procedure p1|
+create procedure p1()
+begin
+prepare stmt_drop from "drop table if exists t1";
+execute stmt_drop;
+prepare stmt from "create table t1 (a int)";
+execute stmt;
+deallocate prepare stmt;
+deallocate prepare stmt_drop;
+end|
+drop function if exists f1|
+create function f1(a int) returns int
+begin
+call p1();
+return 1;
+end|
+select f1(0)|
+ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
+select f1(f1(0))|
+ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
+select f1(f1(f1(0)))|
+ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
+drop function f1|
+drop procedure p1|
+create procedure p1()
+begin
+drop table if exists t1;
+create table t1 (id integer not null primary key,
+name varchar(20) not null);
+insert into t1 (id, name) values (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+prepare stmt from "select name from t1";
+execute stmt;
+select name from t1;
+execute stmt;
+prepare stmt from
+"select name from t1 where name=(select name from t1 where id=2)";
+execute stmt;
+select name from t1 where name=(select name from t1 where id=2);
+execute stmt;
+end|
+call p1()|
+name
+aaa
+bbb
+ccc
+name
+aaa
+bbb
+ccc
+name
+aaa
+bbb
+ccc
+name
+bbb
+name
+bbb
+name
+bbb
+call p1()|
+name
+aaa
+bbb
+ccc
+name
+aaa
+bbb
+ccc
+name
+aaa
+bbb
+ccc
+name
+bbb
+name
+bbb
+name
+bbb
+drop procedure p1|
+prepare stmt from "select * from t1"|
+create procedure p1()
+begin
+execute stmt;
+deallocate prepare stmt;
+end|
+call p1()|
+id name
+1 aaa
+2 bbb
+3 ccc
+call p1()|
+ERROR HY000: Unknown prepared statement handler (stmt) given to EXECUTE
+drop procedure p1|
+create procedure p1()
+begin
+declare a char(10);
+set a="sp-variable";
+set @a="mysql-variable";
+prepare stmt from "select 'dynamic sql:', @a, a";
+execute stmt;
+end|
+call p1()|
+ERROR 42S22: Unknown column 'a' in 'field list'
+call p1()|
+ERROR 42S22: Unknown column 'a' in 'field list'
+drop procedure p1|
+create procedure p1()
+begin
+prepare stmt from 'select ? as a';
+execute stmt using @a;
+end|
+set @a=1|
+call p1()|
+a
+1
+call p1()|
+a
+1
+drop procedure p1|
+drop table if exists t1|
+create table t1 (id integer primary key auto_increment,
+stmt_text char(35), status varchar(20))|
+insert into t1 (stmt_text) values
+("select 1"), ("flush tables"), ("handler t1 open as ha"),
+("analyze table t1"), ("check table t1"), ("checksum table t1"),
+("check table t1"), ("optimize table t1"), ("repair table t1"),
+("describe extended select * from t1"),
+("help help"), ("show databases"), ("show tables"),
+("show table status"), ("show open tables"), ("show storage engines"),
+("insert into t1 (id) values (1)"), ("update t1 set status=''"),
+("delete from t1"), ("truncate t1"), ("call p1()"), ("foo bar")|
+create procedure p1()
+begin
+declare v_stmt_text varchar(255);
+declare v_id integer;
+declare done int default 0;
+declare c cursor for select id, stmt_text from t1;
+declare continue handler for 1295 -- ER_UNSUPPORTED_PS
+set @status='not supported';
+declare continue handler for 1064 -- ER_SYNTAX_ERROR
+set @status='syntax error';
+declare continue handler for sqlstate '02000' set done = 1;
+prepare update_stmt from "update t1 set status=? where id=?";
+open c;
+repeat
+if not done then
+fetch c into v_id, v_stmt_text;
+set @id=v_id, @stmt_text=v_stmt_text;
+set @status="supported";
+prepare stmt from @stmt_text;
+execute update_stmt using @status, @id;
+end if;
+until done end repeat;
+deallocate prepare update_stmt;
+end|
+call p1()|
+select * from t1|
+id stmt_text status
+1 select 1 supported
+2 flush tables not supported
+3 handler t1 open as ha not supported
+4 analyze table t1 not supported
+5 check table t1 not supported
+6 checksum table t1 not supported
+7 check table t1 not supported
+8 optimize table t1 not supported
+9 repair table t1 not supported
+10 describe extended select * from t1 supported
+11 help help not supported
+12 show databases supported
+13 show tables supported
+14 show table status supported
+15 show open tables supported
+16 show storage engines supported
+17 insert into t1 (id) values (1) supported
+18 update t1 set status='' supported
+19 delete from t1 supported
+20 truncate t1 supported
+21 call p1() supported
+22 foo bar syntax error
+drop procedure p1|
+drop table t1|
+prepare stmt from 'select 1'|
+create procedure p1() execute stmt|
+call p1()|
+1
+1
+call p1()|
+1
+1
+drop procedure p1|
+create function f1() returns int
+begin
+deallocate prepare stmt;
+return 1;
+end|
+ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
+create procedure p1()
+begin
+prepare stmt from 'select 1 A';
+execute stmt;
+end|
+prepare stmt from 'call p1()'|
+execute stmt|
+ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
+execute stmt|
+ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
+drop procedure p1|
+drop table if exists t1, t2|
+create procedure p1 (a int) language sql deterministic
+begin
+declare rsql varchar(100);
+drop table if exists t1, t2;
+set @rsql= "create table t1 (a int)";
+select @rsql;
+prepare pst from @rsql;
+execute pst;
+set @rsql= null;
+set @rsql= "create table t2 (a int)";
+select @rsql;
+prepare pst from @rsql;
+execute pst;
+drop table if exists t1, t2;
+end|
+set @a:=0|
+call p1(@a)|
+@rsql
+create table t1 (a int)
+@rsql
+create table t2 (a int)
+Warnings:
+Note 1051 Unknown table 't1'
+Note 1051 Unknown table 't2'
+select @a|
+@a
+0
+call p1(@a)|
+@rsql
+create table t1 (a int)
+@rsql
+create table t2 (a int)
+Warnings:
+Note 1051 Unknown table 't1'
+Note 1051 Unknown table 't2'
+select @a|
+@a
+0
+drop procedure if exists p1|
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
new file mode 100644
index 00000000000..17a2050437f
--- /dev/null
+++ b/mysql-test/r/sp-error.result
@@ -0,0 +1,835 @@
+drop table if exists t1, t2;
+delete from mysql.proc;
+create procedure syntaxerror(t 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
+create procedure syntaxerror(t 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
+create procedure syntaxerror(t 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
+drop table if exists t3|
+create table t3 ( x int )|
+insert into t3 values (2), (3)|
+create procedure bad_into(out param int)
+select x from t3 into param|
+call bad_into(@x)|
+ERROR 42000: Result consisted of more than one row
+drop procedure bad_into|
+drop table t3|
+create procedure proc1()
+set @x = 42|
+create function func1() returns int
+return 42|
+create procedure foo()
+create procedure bar() set @x=3|
+ERROR 2F003: Can't create a PROCEDURE from within another stored routine
+create procedure foo()
+create function bar() returns double return 2.3|
+ERROR 2F003: Can't create a FUNCTION from within another stored routine
+create procedure proc1()
+set @x = 42|
+ERROR 42000: PROCEDURE proc1 already exists
+create function func1() returns int
+return 42|
+ERROR 42000: FUNCTION func1 already exists
+drop procedure proc1|
+drop function func1|
+alter procedure foo|
+ERROR 42000: PROCEDURE test.foo does not exist
+alter function foo|
+ERROR 42000: FUNCTION test.foo does not exist
+drop procedure foo|
+ERROR 42000: PROCEDURE test.foo does not exist
+drop function foo|
+ERROR 42000: FUNCTION test.foo does not exist
+call foo()|
+ERROR 42000: PROCEDURE test.foo does not exist
+drop procedure if exists foo|
+Warnings:
+Note 1305 PROCEDURE foo does not exist
+show create procedure foo|
+ERROR 42000: PROCEDURE foo does not exist
+show create function foo|
+ERROR 42000: FUNCTION foo does not exist
+create procedure foo()
+foo: loop
+leave bar;
+end loop|
+ERROR 42000: LEAVE with no matching label: bar
+create procedure foo()
+foo: loop
+iterate bar;
+end loop|
+ERROR 42000: ITERATE with no matching label: bar
+create procedure foo()
+foo: begin
+iterate foo;
+end|
+ERROR 42000: ITERATE with no matching label: foo
+create procedure foo()
+foo: loop
+foo: loop
+set @x=2;
+end loop foo;
+end loop foo|
+ERROR 42000: Redefining label foo
+create procedure foo()
+foo: loop
+set @x=2;
+end loop bar|
+ERROR 42000: End-label bar without match
+create procedure foo()
+return 42|
+ERROR 42000: RETURN is only allowed in a FUNCTION
+create procedure p(x int)
+set @x = x|
+create function f(x int) returns int
+return x+42|
+call p()|
+ERROR 42000: Incorrect number of arguments for PROCEDURE test.p; expected 1, got 0
+call p(1, 2)|
+ERROR 42000: Incorrect number of arguments for PROCEDURE test.p; expected 1, got 2
+select f()|
+ERROR 42000: Incorrect number of arguments for FUNCTION test.f; expected 1, got 0
+select f(1, 2)|
+ERROR 42000: Incorrect number of arguments for FUNCTION test.f; expected 1, got 2
+drop procedure p|
+drop function f|
+create procedure p(val int, out res int)
+begin
+declare x int default 0;
+declare continue handler for foo set x = 1;
+insert into test.t1 values (val);
+if (x) then
+set res = 0;
+else
+set res = 1;
+end if;
+end|
+ERROR 42000: Undefined CONDITION: foo
+create procedure p(val int, out res int)
+begin
+declare x int default 0;
+declare foo condition for 1146;
+declare continue handler for bar set x = 1;
+insert into test.t1 values (val);
+if (x) then
+set res = 0;
+else
+set res = 1;
+end if;
+end|
+ERROR 42000: Undefined CONDITION: bar
+create function f(val int) returns int
+begin
+declare x int;
+set x = val+3;
+end|
+ERROR 42000: No RETURN found in FUNCTION f
+create function f(val int) returns int
+begin
+declare x int;
+set x = val+3;
+if x < 4 then
+return x;
+end if;
+end|
+select f(10)|
+ERROR 2F005: FUNCTION f ended without RETURN
+drop function f|
+create procedure p()
+begin
+declare c cursor for insert into test.t1 values ("foo", 42);
+open c;
+close c;
+end|
+ERROR 42000: Cursor statement must be a SELECT
+create procedure p()
+begin
+declare x int;
+declare c cursor for select * into x from test.t limit 1;
+open c;
+close c;
+end|
+ERROR 42000: Cursor SELECT must not have INTO
+create procedure p()
+begin
+declare c cursor for select * from test.t;
+open cc;
+close c;
+end|
+ERROR 42000: Undefined CURSOR: cc
+drop table if exists t1|
+create table t1 (val int)|
+create procedure p()
+begin
+declare c cursor for select * from test.t1;
+open c;
+open c;
+close c;
+end|
+call p()|
+ERROR 24000: Cursor is already open
+drop procedure p|
+create procedure p()
+begin
+declare c cursor for select * from test.t1;
+open c;
+close c;
+close c;
+end|
+call p()|
+ERROR 24000: Cursor is not open
+drop procedure p|
+alter procedure bar3 sql security invoker|
+ERROR 42000: PROCEDURE test.bar3 does not exist
+drop table t1|
+drop table if exists t1|
+create table t1 (val int, x float)|
+insert into t1 values (42, 3.1), (19, 1.2)|
+create procedure p()
+begin
+declare x int;
+declare c cursor for select * from t1;
+open c;
+fetch c into x, y;
+close c;
+end|
+ERROR 42000: Undeclared variable: y
+create procedure p()
+begin
+declare x int;
+declare c cursor for select * from t1;
+open c;
+fetch c into x;
+close c;
+end|
+call p()|
+ERROR HY000: Incorrect number of FETCH variables
+drop procedure p|
+create procedure p()
+begin
+declare x int;
+declare y float;
+declare z int;
+declare c cursor for select * from t1;
+open c;
+fetch c into x, y, z;
+close c;
+end|
+call p()|
+ERROR HY000: Incorrect number of FETCH variables
+drop procedure p|
+create procedure p(in x int, x char(10))
+begin
+end|
+ERROR 42000: Duplicate parameter: x
+create function p(x int, x char(10))
+begin
+end|
+ERROR 42000: Duplicate parameter: x
+create procedure p()
+begin
+declare x float;
+declare x int;
+end|
+ERROR 42000: Duplicate variable: x
+create procedure p()
+begin
+declare c condition for 1064;
+declare c condition for 1065;
+end|
+ERROR 42000: Duplicate condition: c
+create procedure p()
+begin
+declare c cursor for select * from t1;
+declare c cursor for select field from t1;
+end|
+ERROR 42000: Duplicate cursor: c
+create procedure u()
+use sptmp|
+ERROR 0A000: USE is not allowed in stored procedures
+create procedure p()
+begin
+declare c cursor for select * from t1;
+declare x int;
+end|
+ERROR 42000: Variable or condition declaration after cursor or handler declaration
+create procedure p()
+begin
+declare x int;
+declare continue handler for sqlstate '42S99' set x = 1;
+declare foo condition for sqlstate '42S99';
+end|
+ERROR 42000: Variable or condition declaration after cursor or handler declaration
+create procedure p()
+begin
+declare x int;
+declare continue handler for sqlstate '42S99' set x = 1;
+declare c cursor for select * from t1;
+end|
+ERROR 42000: Cursor declaration after handler declaration
+drop procedure if exists p|
+create procedure p(in x int, inout y int, out z int)
+begin
+set y = x+y;
+set z = x+y;
+end|
+set @tmp_x = 42|
+set @tmp_y = 3|
+set @tmp_z = 0|
+call p(@tmp_x, @tmp_y, @tmp_z)|
+select @tmp_x, @tmp_y, @tmp_z|
+@tmp_x @tmp_y @tmp_z
+42 45 87
+call p(42, 43, @tmp_z)|
+ERROR 42000: OUT or INOUT argument 2 for routine test.p is not a variable
+call p(42, @tmp_y, 43)|
+ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable
+drop procedure p|
+create procedure p() begin end|
+lock table t1 read|
+call p()|
+unlock tables|
+drop procedure p|
+lock tables t1 read, mysql.proc write|
+ERROR HY000: You can't combine write-locking of system 'mysql.proc' table with other tables
+lock tables mysql.proc write, mysql.user write|
+ERROR HY000: You can't combine write-locking of system 'mysql.proc' table with other tables
+lock tables t1 read, mysql.proc read|
+unlock tables|
+lock tables mysql.proc write|
+unlock tables|
+drop function if exists f1|
+create function f1(i int) returns int
+begin
+insert into t1 (val) values (i);
+return 0;
+end|
+select val, f1(val) from t1|
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+select val, f1(val) from t1 as tab|
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+select * from t1|
+val x
+42 3.1
+19 1.2
+update t1 set val= f1(val)|
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+select * from t1|
+val x
+42 3.1
+19 1.2
+select f1(17)|
+f1(17)
+0
+select * from t1|
+val x
+42 3.1
+19 1.2
+17 NULL
+delete from t1 where val= 17|
+drop function f1|
+create procedure bug1965()
+begin
+declare c cursor for select val from t1 order by valname;
+open c;
+close c;
+end|
+call bug1965()|
+ERROR 42S22: Unknown column 'valname' in 'order clause'
+drop procedure bug1965|
+select 1 into a|
+ERROR 42000: Undeclared variable: a
+drop table if exists t3|
+create table t3 (column_1_0 int)|
+create procedure bug1653()
+update t3 set column_1 = 0|
+call bug1653()|
+ERROR 42S22: Unknown column 'column_1' in 'field list'
+drop table t3|
+create table t3 (column_1 int)|
+call bug1653()|
+drop procedure bug1653|
+drop table t3|
+create procedure bug2259()
+begin
+declare v1 int;
+declare c1 cursor for select s1 from t1;
+fetch c1 into v1;
+end|
+call bug2259()|
+ERROR 24000: Cursor is not open
+drop procedure bug2259|
+create procedure bug2272()
+begin
+declare v int;
+update t1 set v = 42;
+end|
+insert into t1 values (666, 51.3)|
+call bug2272()|
+ERROR 42S22: Unknown column 'v' in 'field list'
+delete from t1|
+drop procedure bug2272|
+create procedure bug2329_1()
+begin
+declare v int;
+insert into t1 (v) values (5);
+end|
+create procedure bug2329_2()
+begin
+declare v int;
+replace t1 set v = 5;
+end|
+call bug2329_1()|
+ERROR 42S22: Unknown column 'v' in 'field list'
+call bug2329_2()|
+ERROR 42S22: Unknown column 'v' in 'field list'
+drop procedure bug2329_1|
+drop procedure bug2329_2|
+create function bug3287() returns int
+begin
+declare v int default null;
+case
+when v is not null then return 1;
+end case;
+return 2;
+end|
+select bug3287()|
+ERROR 20000: Case not found for CASE statement
+drop function bug3287|
+create procedure bug3287(x int)
+case x
+when 0 then
+insert into test.t1 values (x, 0.1);
+when 1 then
+insert into test.t1 values (x, 1.1);
+end case|
+call bug3287(2)|
+ERROR 20000: Case not found for CASE statement
+drop procedure bug3287|
+drop table if exists t3|
+create table t3 (s1 int, primary key (s1))|
+insert into t3 values (5),(6)|
+create procedure bug3279(out y int)
+begin
+declare x int default 0;
+begin
+declare exit handler for sqlexception set x = x+1;
+insert into t3 values (5);
+end;
+if x < 2 then
+set x = x+1;
+insert into t3 values (6);
+end if;
+set y = x;
+end|
+set @x = 0|
+call bug3279(@x)|
+ERROR 23000: Duplicate entry '6' for key 1
+select @x|
+@x
+0
+drop procedure bug3279|
+drop table t3|
+create procedure nodb.bug3339() begin end|
+ERROR 42000: Unknown database 'nodb'
+create procedure bug2653_1(a int, out b int)
+set b = aa|
+create procedure bug2653_2(a int, out b int)
+begin
+if aa < 0 then
+set b = - a;
+else
+set b = a;
+end if;
+end|
+call bug2653_1(1, @b)|
+ERROR 42S22: Unknown column 'aa' in 'order clause'
+call bug2653_2(2, @b)|
+ERROR 42S22: Unknown column 'aa' in 'order clause'
+drop procedure bug2653_1|
+drop procedure bug2653_2|
+create procedure bug4344() drop procedure bug4344|
+ERROR HY000: Can't drop or alter a PROCEDURE from within another stored routine
+create procedure bug4344() drop function bug4344|
+ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine
+drop procedure if exists bug3294|
+create procedure bug3294()
+begin
+declare continue handler for sqlexception drop table t5;
+drop table t5;
+drop table t5;
+end|
+create table t5 (x int)|
+call bug3294()|
+ERROR 42S02: Unknown table 't5'
+drop procedure bug3294|
+drop procedure if exists bug6807|
+create procedure bug6807()
+begin
+declare id int;
+set id = connection_id();
+kill query id;
+select 'Not reached';
+end|
+call bug6807()|
+ERROR 70100: Query execution was interrupted
+call bug6807()|
+ERROR 70100: Query execution was interrupted
+drop procedure bug6807|
+drop procedure if exists bug8776_1|
+drop procedure if exists bug8776_2|
+drop procedure if exists bug8776_3|
+drop procedure if exists bug8776_4|
+create procedure bug8776_1()
+begin
+declare continue handler for sqlstate '42S0200test' begin end;
+begin end;
+end|
+ERROR 42000: Bad SQLSTATE: '42S0200test'
+create procedure bug8776_2()
+begin
+declare continue handler for sqlstate '4200' begin end;
+begin end;
+end|
+ERROR 42000: Bad SQLSTATE: '4200'
+create procedure bug8776_3()
+begin
+declare continue handler for sqlstate '420000' begin end;
+begin end;
+end|
+ERROR 42000: Bad SQLSTATE: '420000'
+create procedure bug8776_4()
+begin
+declare continue handler for sqlstate '42x00' begin end;
+begin end;
+end|
+ERROR 42000: Bad SQLSTATE: '42x00'
+create procedure bug6600()
+check table t1|
+ERROR 0A000: CHECK is not allowed in stored procedures
+create procedure bug6600()
+lock table t1 read|
+ERROR 0A000: LOCK is not allowed in stored procedures
+create procedure bug6600()
+unlock table t1|
+ERROR 0A000: UNLOCK is not allowed in stored procedures
+drop procedure if exists bug9566|
+create procedure bug9566()
+begin
+select * from t1;
+end|
+lock table t1 read|
+alter procedure bug9566 comment 'Some comment'|
+ERROR HY000: Table 'proc' was not locked with LOCK TABLES
+unlock tables|
+drop procedure bug9566|
+drop procedure if exists bug7299|
+create procedure bug7299()
+begin
+declare v int;
+declare c cursor for select val from t1;
+declare exit handler for sqlexception select 'Error!';
+open c;
+fetch c into v;
+end|
+delete from t1|
+call bug7299()|
+ERROR 02000: No data to FETCH
+drop procedure bug7299|
+create procedure bug9073()
+begin
+declare continue handler for sqlexception select 1;
+declare continue handler for sqlexception select 2;
+end|
+ERROR 42000: Duplicate handler declared in the same block
+create procedure bug9073()
+begin
+declare condname1 condition for 1234;
+declare continue handler for condname1 select 1;
+declare exit handler for condname1 select 2;
+end|
+ERROR 42000: Duplicate handler declared in the same block
+create procedure bug9073()
+begin
+declare condname1 condition for sqlstate '42000';
+declare condname2 condition for sqlstate '42000';
+declare exit handler for condname1 select 1;
+declare continue handler for condname2 select 2;
+end|
+ERROR 42000: Duplicate handler declared in the same block
+create procedure bug9073()
+begin
+declare condname1 condition for sqlstate '42000';
+declare exit handler for condname1 select 1;
+declare exit handler for sqlstate '42000' select 2;
+end|
+ERROR 42000: Duplicate handler declared in the same block
+drop procedure if exists bug9073|
+create procedure bug9073()
+begin
+declare condname1 condition for sqlstate '42000';
+declare continue handler for condname1 select 1;
+begin
+declare exit handler for sqlstate '42000' select 2;
+begin
+declare continue handler for sqlstate '42000' select 3;
+end;
+end;
+end|
+drop procedure bug9073|
+create procedure bug7047()
+alter procedure bug7047|
+ERROR HY000: Can't drop or alter a PROCEDURE from within another stored routine
+create function bug7047() returns int
+begin
+alter function bug7047;
+return 0;
+end|
+ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine
+create function bug8408() returns int
+begin
+select * from t1;
+return 0;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+create function bug8408() returns int
+begin
+show warnings;
+return 0;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+create function bug8408(a int) returns int
+begin
+declare b int;
+select b;
+return b;
+end|
+ERROR 0A000: Not allowed to return a result set from a function
+drop function if exists bug8408_f|
+drop procedure if exists bug8408_p|
+create function bug8408_f() returns int
+begin
+call bug8408_p();
+return 0;
+end|
+create procedure bug8408_p()
+select * from t1|
+call bug8408_p()|
+val x
+select bug8408_f()|
+ERROR 0A000: Not allowed to return a result set from a function
+drop procedure bug8408_p|
+drop function bug8408_f|
+create function bug8408() returns int
+begin
+declare n int default 0;
+select count(*) into n from t1;
+return n;
+end|
+insert into t1 value (2, 2.7), (3, 3.14), (7, 7.0)|
+select *,bug8408() from t1|
+val x bug8408()
+2 2.7 3
+3 3.14 3
+7 7 3
+drop function bug8408|
+delete from t1|
+drop procedure if exists bug10537|
+create procedure bug10537()
+load data local infile '/tmp/somefile' into table t1|
+ERROR 0A000: LOAD DATA is not allowed in stored procedures
+drop function if exists bug8409|
+create function bug8409()
+returns int
+begin
+flush tables;
+return 5;
+end|
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create procedure bug9529_90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123()
+begin
+end|
+ERROR 42000: Identifier name 'bug9529_90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' is too long
+drop procedure if exists bug10969|
+create procedure bug10969()
+begin
+declare s1 int default 0;
+select default(s1) from t30;
+end|
+ERROR 42000: Incorrect column name 's1'
+create procedure bug10969()
+begin
+declare s1 int default 0;
+select default(t30.s1) from t30;
+end|
+drop procedure bug10969|
+drop table t1|
+create table t1(f1 int);
+create table t2(f1 int);
+CREATE PROCEDURE SP001()
+P1: BEGIN
+DECLARE ENDTABLE INT DEFAULT 0;
+DECLARE TEMP_NUM INT;
+DECLARE TEMP_SUM INT;
+DECLARE C1 CURSOR FOR SELECT F1 FROM t1;
+DECLARE C2 CURSOR FOR SELECT F1 FROM t2;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET ENDTABLE = 1;
+SET ENDTABLE=0;
+SET TEMP_SUM=0;
+SET TEMP_NUM=0;
+OPEN C1;
+FETCH C1 INTO TEMP_NUM;
+WHILE ENDTABLE = 0 DO
+SET TEMP_SUM=TEMP_NUM+TEMP_SUM;
+FETCH C1 INTO TEMP_NUM;
+END WHILE;
+SELECT TEMP_SUM;
+CLOSE C1;
+CLOSE C1;
+SELECT 'end of proc';
+END P1|
+call SP001();
+TEMP_SUM
+0
+drop procedure SP001;
+drop table t1, t2;
+drop function if exists bug11394|
+drop function if exists bug11394_1|
+drop function if exists bug11394_2|
+drop procedure if exists bug11394|
+create function bug11394(i int) returns int
+begin
+if i <= 0 then
+return 0;
+else
+return (i in (100, 200, bug11394(i-1), 400));
+end if;
+end|
+select bug11394(2)|
+ERROR HY000: Recursive stored routines are not allowed.
+drop function bug11394|
+create function bug11394_1(i int) returns int
+begin
+if i <= 0 then
+return 0;
+else
+return (select bug11394_1(i-1));
+end if;
+end|
+select bug11394_1(2)|
+ERROR HY000: Recursive stored routines are not allowed.
+drop function bug11394_1|
+create function bug11394_2(i int) returns int return i|
+select bug11394_2(bug11394_2(10))|
+bug11394_2(bug11394_2(10))
+10
+drop function bug11394_2|
+create procedure bug11394(i int, j int)
+begin
+if i > 0 then
+call bug11394(i - 1,(select 1));
+end if;
+end|
+call bug11394(2, 1)|
+ERROR HY000: Recursive stored routines are not allowed.
+drop procedure bug11394|
+CREATE PROCEDURE BUG_12490() HELP CONTENTS;
+ERROR 0A000: HELP is not allowed in stored procedures
+CREATE FUNCTION BUG_12490() RETURNS INT HELP CONTENTS;
+ERROR 0A000: HELP is not allowed in stored procedures
+CREATE TABLE t_bug_12490(a int);
+CREATE TRIGGER BUG_12490 BEFORE UPDATE ON t_bug_12490 FOR EACH ROW HELP CONTENTS;
+ERROR 0A000: HELP is not allowed in stored procedures
+DROP TABLE t_bug_12490;
+drop function if exists bug11834_1;
+drop function if exists bug11834_2;
+create function bug11834_1() returns int return 10;
+create function bug11834_2() returns int return bug11834_1();
+prepare stmt from "select bug11834_2()";
+execute stmt;
+bug11834_2()
+10
+execute stmt;
+bug11834_2()
+10
+drop function bug11834_1;
+execute stmt;
+ERROR 42000: FUNCTION test.bug11834_1 does not exist
+deallocate prepare stmt;
+drop function bug11834_2;
+DROP FUNCTION IF EXISTS bug12953|
+CREATE FUNCTION bug12953() RETURNS INT
+BEGIN
+OPTIMIZE TABLE t1;
+RETURN 1;
+END|
+ERROR 0A000: OPTIMIZE TABLE is not allowed in stored procedures
+DROP FUNCTION IF EXISTS bug12995|
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+HANDLER t1 OPEN;
+RETURN 1;
+END|
+ERROR 0A000: HANDLER is not allowed in stored procedures
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+HANDLER t1 READ FIRST;
+RETURN 1;
+END|
+ERROR 0A000: HANDLER is not allowed in stored procedures
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+HANDLER t1 CLOSE;
+RETURN 1;
+END|
+ERROR 0A000: HANDLER is not allowed in stored procedures
+SELECT bug12995()|
+ERROR 42000: FUNCTION test.bug12995 does not exist
+drop procedure if exists bug12712;
+drop function if exists bug12712;
+create procedure bug12712()
+set session autocommit = 0;
+select @@autocommit;
+@@autocommit
+1
+set @au = @@autocommit;
+call bug12712();
+select @@autocommit;
+@@autocommit
+0
+set session autocommit = @au;
+create function bug12712()
+returns int
+begin
+call bug12712();
+return 0;
+end|
+set @x = bug12712()|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+drop procedure bug12712|
+drop function bug12712|
+create function bug12712()
+returns int
+begin
+set session autocommit = 0;
+return 0;
+end|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+create function bug12712()
+returns int
+begin
+set @@autocommit = 0;
+return 0;
+end|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+create function bug12712()
+returns int
+begin
+set local autocommit = 0;
+return 0;
+end|
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
+create trigger bug12712
+before insert on t1 for each row set session autocommit = 0;
+ERROR HY000: Not allowed to set autocommit from a stored function or trigger
diff --git a/mysql-test/r/sp-goto.result b/mysql-test/r/sp-goto.result
new file mode 100644
index 00000000000..ca560f62318
--- /dev/null
+++ b/mysql-test/r/sp-goto.result
@@ -0,0 +1,205 @@
+drop table if exists t1;
+create table t1 (
+id char(16) not null default '',
+data int not null
+);
+drop procedure if exists goto1//
+create procedure goto1()
+begin
+declare y int;
+label a;
+select * from t1;
+select count(*) into y from t1;
+if y > 2 then
+goto b;
+end if;
+insert into t1 values ("j", y);
+goto a;
+label b;
+end//
+call goto1()//
+id data
+id data
+j 0
+id data
+j 0
+j 1
+id data
+j 0
+j 1
+j 2
+drop procedure goto1//
+drop procedure if exists goto2//
+create procedure goto2(a int)
+begin
+declare x int default 0;
+declare continue handler for sqlstate '42S98' set x = 1;
+label a;
+select * from t1;
+b:
+while x < 2 do
+begin
+declare continue handler for sqlstate '42S99' set x = 2;
+if a = 0 then
+set x = x + 1;
+iterate b;
+elseif a = 1 then
+leave b;
+elseif a = 2 then
+set a = 1;
+goto a;
+end if;
+end;
+end while b;
+select * from t1;
+end//
+call goto2(0)//
+id data
+j 0
+j 1
+j 2
+id data
+j 0
+j 1
+j 2
+call goto2(1)//
+id data
+j 0
+j 1
+j 2
+id data
+j 0
+j 1
+j 2
+call goto2(2)//
+id data
+j 0
+j 1
+j 2
+id data
+j 0
+j 1
+j 2
+id data
+j 0
+j 1
+j 2
+drop procedure goto2//
+delete from t1//
+drop procedure if exists goto3//
+create procedure goto3()
+begin
+label L1;
+begin
+end;
+goto L1;
+end//
+drop procedure goto3//
+drop procedure if exists goto4//
+create procedure goto4()
+begin
+begin
+label lab1;
+begin
+goto lab1;
+end;
+end;
+end//
+drop procedure goto4//
+drop procedure if exists goto5//
+create procedure goto5()
+begin
+begin
+begin
+goto lab1;
+end;
+label lab1;
+end;
+end//
+drop procedure goto5//
+drop procedure if exists goto6//
+create procedure goto6()
+begin
+label L1;
+goto L5;
+begin
+label L2;
+goto L1;
+goto L5;
+begin
+label L3;
+goto L1;
+goto L2;
+goto L3;
+goto L4;
+goto L5;
+end;
+goto L2;
+goto L4;
+label L4;
+end;
+label L5;
+goto L1;
+end//
+drop procedure goto6//
+create procedure foo()
+begin
+goto foo;
+end//
+ERROR 42000: GOTO with no matching label: foo
+create procedure foo()
+begin
+begin
+label foo;
+end;
+goto foo;
+end//
+ERROR 42000: GOTO with no matching label: foo
+create procedure foo()
+begin
+goto foo;
+begin
+label foo;
+end;
+end//
+ERROR 42000: GOTO with no matching label: foo
+create procedure foo()
+begin
+begin
+goto foo;
+end;
+begin
+label foo;
+end;
+end//
+ERROR 42000: GOTO with no matching label: foo
+create procedure foo()
+begin
+begin
+label foo;
+end;
+begin
+goto foo;
+end;
+end//
+ERROR 42000: GOTO with no matching label: foo
+create procedure p()
+begin
+declare continue handler for sqlexception
+begin
+goto L1;
+end;
+select field from t1;
+label L1;
+end//
+ERROR HY000: GOTO is not allowed in a stored procedure handler
+drop procedure if exists bug6898//
+create procedure bug6898()
+begin
+goto label1;
+label label1;
+begin end;
+goto label1;
+end//
+drop procedure bug6898//
+drop table t1;
diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result
new file mode 100644
index 00000000000..32d6d4e6264
--- /dev/null
+++ b/mysql-test/r/sp-prelocking.result
@@ -0,0 +1,215 @@
+drop database if exists mysqltest;
+drop table if exists t1, t2, t3, t4;
+drop procedure if exists sp1;
+drop procedure if exists sp2;
+drop procedure if exists sp3;
+drop procedure if exists sp4;
+drop function if exists f1;
+drop function if exists f2;
+drop function if exists f3;
+create database mysqltest;
+use mysqltest//
+create procedure sp1 ()
+begin
+drop table if exists t1;
+select 1 as "my-col";
+end;
+//
+select database();
+database()
+mysqltest
+call sp1();
+my-col
+1
+Warnings:
+Note 1051 Unknown table 't1'
+select database();
+database()
+mysqltest
+use test;
+select database();
+database()
+test
+call mysqltest.sp1();
+my-col
+1
+Warnings:
+Note 1051 Unknown table 't1'
+select database();
+database()
+test
+drop procedure mysqltest.sp1;
+drop database mysqltest;
+create procedure sp1()
+begin
+create table t1 (a int);
+insert into t1 values (10);
+end//
+create procedure sp2()
+begin
+create table t2(a int);
+insert into t2 values(1);
+call sp1();
+end//
+create function f1() returns int
+begin
+return (select max(a) from t1);
+end//
+create procedure sp3()
+begin
+call sp1();
+select 'func', f1();
+end//
+call sp1();
+select 't1',a from t1;
+t1 a
+t1 10
+drop table t1;
+call sp2();
+select 't1',a from t1;
+t1 a
+t1 10
+select 't2',a from t2;
+t2 a
+t2 1
+drop table t1, t2;
+call sp3();
+func f1()
+func 10
+select 't1',a from t1;
+t1 a
+t1 10
+drop table t1;
+drop procedure sp1;
+drop procedure sp2;
+drop procedure sp3;
+drop function f1;
+create procedure sp1()
+begin
+create temporary table t2(a int);
+insert into t2 select * from t1;
+end//
+create procedure sp2()
+begin
+create temporary table t1 (a int);
+insert into t1 values(1);
+call sp1();
+select 't1', a from t1;
+select 't2', a from t2;
+drop table t1;
+drop table t2;
+end//
+call sp2();
+t1 a
+t1 1
+t2 a
+t2 1
+drop procedure sp1;
+drop procedure sp2;
+create table t1 (a int);
+insert into t1 values(1),(2);
+create table t2 as select * from t1;
+create table t3 as select * from t1;
+create table t4 as select * from t1;
+create procedure sp1(a int)
+begin
+select a;
+end //
+create function f1() returns int
+begin
+return (select max(a) from t1);
+end //
+CALL sp1(f1());
+a
+2
+create procedure sp2(a int)
+begin
+select * from t3;
+select a;
+end //
+create procedure sp3()
+begin
+select * from t1;
+call sp2(5);
+end //
+create procedure sp4()
+begin
+select * from t2;
+call sp3();
+end //
+call sp4();
+a
+1
+2
+a
+1
+2
+a
+1
+2
+a
+5
+drop procedure sp1;
+drop procedure sp2;
+drop procedure sp3;
+drop procedure sp4;
+drop function f1;
+drop view if exists v1;
+create function f1(ab int) returns int
+begin
+declare i int;
+set i= (select max(a) from t1 where a < ab) ;
+return i;
+end //
+create function f2(ab int) returns int
+begin
+declare i int;
+set i= (select max(a) from t2 where a < ab) ;
+return i;
+end //
+create view v1 as
+select t3.a as x, t4.a as y, f2(3) as z
+from t3, t4 where t3.a = t4.a //
+create procedure sp1()
+begin
+declare a int;
+set a= (select f1(4) + count(*) A from t1, v1);
+end //
+create function f3() returns int
+begin
+call sp1();
+return 1;
+end //
+call sp1() //
+select f3() //
+f3()
+1
+select f3() //
+f3()
+1
+call sp1() //
+drop procedure sp1//
+drop function f3//
+create procedure sp1()
+begin
+declare x int;
+declare c cursor for select f1(3) + count(*) from v1;
+open c;
+fetch c into x;
+end;//
+create function f3() returns int
+begin
+call sp1();
+return 1;
+end //
+call sp1() //
+call sp1() //
+select f3() //
+f3()
+1
+call sp1() //
+drop table t1,t2,t3;
+drop function f1;
+drop function f2;
+drop function f3;
+drop procedure sp1;
diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result
new file mode 100644
index 00000000000..eb2e2ce334e
--- /dev/null
+++ b/mysql-test/r/sp-security.result
@@ -0,0 +1,253 @@
+use test;
+grant usage on *.* to user1@localhost;
+flush privileges;
+drop table if exists t1;
+drop database if exists db1_secret;
+create database db1_secret;
+create procedure db1_secret.dummy() begin end;
+drop procedure db1_secret.dummy;
+use db1_secret;
+create table t1 ( u varchar(64), i int );
+create procedure stamp(i int)
+insert into db1_secret.t1 values (user(), i);
+show procedure status like 'stamp';
+Db Name Type Definer Modified Created Security_type Comment
+db1_secret stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+create function db() returns varchar(64) return database();
+show function status like 'db';
+Db Name Type Definer Modified Created Security_type Comment
+db1_secret db FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+call stamp(1);
+select * from t1;
+u i
+root@localhost 1
+select db();
+db()
+db1_secret
+grant execute on procedure db1_secret.stamp to user1@'%';
+grant execute on function db1_secret.db to user1@'%';
+grant execute on procedure db1_secret.stamp to ''@'%';
+grant execute on function db1_secret.db to ''@'%';
+call db1_secret.stamp(2);
+select db1_secret.db();
+db1_secret.db()
+db1_secret
+select * from db1_secret.t1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+create procedure db1_secret.dummy() begin end;
+ERROR 42000: Access denied for user 'user1'@'localhost' to database 'db1_secret'
+drop procedure db1_secret.dummy;
+ERROR 42000: PROCEDURE db1_secret.dummy does not exist
+call db1_secret.stamp(3);
+select db1_secret.db();
+db1_secret.db()
+db1_secret
+select * from db1_secret.t1;
+ERROR 42000: SELECT command denied to user ''@'localhost' for table 't1'
+create procedure db1_secret.dummy() begin end;
+ERROR 42000: Access denied for user ''@'localhost' to database 'db1_secret'
+drop procedure db1_secret.dummy;
+ERROR 42000: PROCEDURE db1_secret.dummy does not exist
+select * from t1;
+u i
+root@localhost 1
+user1@localhost 2
+anon@localhost 3
+alter procedure stamp sql security invoker;
+show procedure status like 'stamp';
+Db Name Type Definer Modified Created Security_type Comment
+db1_secret stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER
+alter function db sql security invoker;
+show function status like 'db';
+Db Name Type Definer Modified Created Security_type Comment
+db1_secret db FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER
+call stamp(4);
+select * from t1;
+u i
+root@localhost 1
+user1@localhost 2
+anon@localhost 3
+root@localhost 4
+select db();
+db()
+db1_secret
+call db1_secret.stamp(5);
+ERROR 42000: Access denied for user 'user1'@'localhost' to database 'db1_secret'
+select db1_secret.db();
+ERROR 42000: Access denied for user 'user1'@'localhost' to database 'db1_secret'
+call db1_secret.stamp(6);
+ERROR 42000: Access denied for user ''@'localhost' to database 'db1_secret'
+select db1_secret.db();
+ERROR 42000: Access denied for user ''@'localhost' to database 'db1_secret'
+drop database if exists db2;
+create database db2;
+use db2;
+create table t2 (s1 int);
+insert into t2 values (0);
+grant usage on db2.* to user1@localhost;
+grant select on db2.* to user1@localhost;
+grant usage on db2.* to user2@localhost;
+grant select,insert,update,delete,create routine on db2.* to user2@localhost;
+grant create routine on db2.* to user1@localhost;
+flush privileges;
+use db2;
+create procedure p () insert into t2 values (1);
+call p();
+ERROR 42000: INSERT command denied to user 'user1'@'localhost' for table 't2'
+use db2;
+call p();
+ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'db2.p'
+select * from t2;
+s1
+0
+create procedure q () insert into t2 values (2);
+call q();
+select * from t2;
+s1
+0
+2
+grant usage on procedure db2.q to user2@localhost with grant option;
+grant execute on procedure db2.q to user1@localhost;
+use db2;
+call q();
+select * from t2;
+s1
+0
+2
+2
+alter procedure p modifies sql data;
+drop procedure p;
+alter procedure q modifies sql data;
+ERROR 42000: alter routine command denied to user 'user1'@'localhost' for routine 'db2.q'
+drop procedure q;
+ERROR 42000: alter routine command denied to user 'user1'@'localhost' for routine 'db2.q'
+use db2;
+alter procedure q modifies sql data;
+drop procedure q;
+use test;
+select type,db,name from mysql.proc;
+type db name
+FUNCTION db1_secret db
+PROCEDURE db1_secret stamp
+drop database db1_secret;
+drop database db2;
+select type,db,name from mysql.proc;
+type db name
+delete from mysql.user where user='user1' or user='user2';
+delete from mysql.procs_priv where user='user1' or user='user2';
+grant usage on *.* to usera@localhost;
+grant usage on *.* to userb@localhost;
+grant usage on *.* to userc@localhost;
+create database sptest;
+create table t1 ( u varchar(64), i int );
+create procedure sptest.p1(i int) insert into test.t1 values (user(), i);
+grant insert on t1 to usera@localhost;
+grant execute on procedure sptest.p1 to usera@localhost;
+show grants for usera@localhost;
+Grants for usera@localhost
+GRANT USAGE ON *.* TO 'usera'@'localhost'
+GRANT INSERT ON `test`.`t1` TO 'usera'@'localhost'
+GRANT EXECUTE ON PROCEDURE `sptest`.`p1` TO 'usera'@'localhost'
+grant execute on procedure sptest.p1 to userc@localhost with grant option;
+show grants for userc@localhost;
+Grants for userc@localhost
+GRANT USAGE ON *.* TO 'userc'@'localhost'
+GRANT EXECUTE ON PROCEDURE `sptest`.`p1` TO 'userc'@'localhost' WITH GRANT OPTION
+call sptest.p1(1);
+grant execute on procedure sptest.p1 to userb@localhost;
+ERROR 42000: grant command denied to user 'usera'@'localhost' for routine 'sptest.p1'
+drop procedure sptest.p1;
+ERROR 42000: alter routine command denied to user 'usera'@'localhost' for routine 'sptest.p1'
+call sptest.p1(2);
+ERROR 42000: execute command denied to user 'userb'@'localhost' for routine 'sptest.p1'
+grant execute on procedure sptest.p1 to userb@localhost;
+ERROR 42000: execute command denied to user 'userb'@'localhost' for routine 'sptest.p1'
+drop procedure sptest.p1;
+ERROR 42000: alter routine command denied to user 'userb'@'localhost' for routine 'sptest.p1'
+call sptest.p1(3);
+grant execute on procedure sptest.p1 to userb@localhost;
+drop procedure sptest.p1;
+ERROR 42000: alter routine command denied to user 'userc'@'localhost' for routine 'sptest.p1'
+call sptest.p1(4);
+grant execute on procedure sptest.p1 to userb@localhost;
+ERROR 42000: grant command denied to user 'userb'@'localhost' for routine 'sptest.p1'
+drop procedure sptest.p1;
+ERROR 42000: alter routine command denied to user 'userb'@'localhost' for routine 'sptest.p1'
+select * from t1;
+u i
+usera@localhost 1
+userc@localhost 3
+userb@localhost 4
+grant all privileges on procedure sptest.p1 to userc@localhost;
+show grants for userc@localhost;
+Grants for userc@localhost
+GRANT USAGE ON *.* TO 'userc'@'localhost'
+GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `sptest`.`p1` TO 'userc'@'localhost' WITH GRANT OPTION
+show grants for userb@localhost;
+Grants for userb@localhost
+GRANT USAGE ON *.* TO 'userb'@'localhost'
+GRANT EXECUTE ON PROCEDURE `sptest`.`p1` TO 'userb'@'localhost'
+revoke all privileges on procedure sptest.p1 from userb@localhost;
+show grants for userb@localhost;
+Grants for userb@localhost
+GRANT USAGE ON *.* TO 'userb'@'localhost'
+use test;
+drop database sptest;
+delete from mysql.user where user='usera' or user='userb' or user='userc';
+delete from mysql.procs_priv where user='usera' or user='userb' or user='userc';
+drop function if exists bug_9503;
+create database mysqltest//
+use mysqltest//
+create table t1 (s1 int)//
+grant select on t1 to user1@localhost//
+create function bug_9503 () returns int sql security invoker begin declare v int;
+select min(s1) into v from t1; return v; end//
+use mysqltest;
+select bug_9503();
+ERROR 42000: execute command denied to user 'user1'@'localhost' for routine 'mysqltest.bug_9503'
+grant execute on function bug_9503 to user1@localhost;
+do 1;
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost;
+drop function bug_9503;
+use test;
+drop database mysqltest;
+use test;
+select current_user();
+current_user()
+root@localhost
+select user();
+user()
+root@localhost
+create procedure bug7291_0 () sql security invoker select current_user(), user();
+create procedure bug7291_1 () sql security definer call bug7291_0();
+create procedure bug7291_2 () sql security invoker call bug7291_0();
+grant execute on procedure bug7291_0 to user1@localhost;
+grant execute on procedure bug7291_1 to user1@localhost;
+grant execute on procedure bug7291_2 to user1@localhost;
+call bug7291_2();
+current_user() user()
+user1@localhost user1@localhost
+call bug7291_1();
+current_user() user()
+root@localhost user1@localhost
+drop procedure bug7291_1;
+drop procedure bug7291_2;
+drop procedure bug7291_0;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost;
+drop user user1@localhost;
+drop database if exists mysqltest_1;
+create database mysqltest_1;
+create procedure mysqltest_1.p1()
+begin
+select 1 from dual;
+end//
+grant usage on *.* to mysqltest_1@localhost;
+call mysqltest_1.p1();
+ERROR 42000: execute command denied to user 'mysqltest_1'@'localhost' for routine 'mysqltest_1.p1'
+call mysqltest_1.p1();
+ERROR 42000: execute command denied to user 'mysqltest_1'@'localhost' for routine 'mysqltest_1.p1'
+drop procedure mysqltest_1.p1;
+drop database mysqltest_1;
+revoke usage on *.* from mysqltest_1@localhost;
+drop user mysqltest_1@localhost;
diff --git a/mysql-test/r/sp-threads.result b/mysql-test/r/sp-threads.result
new file mode 100644
index 00000000000..c516d7a643f
--- /dev/null
+++ b/mysql-test/r/sp-threads.result
@@ -0,0 +1,91 @@
+use test;
+drop table if exists t1;
+create table t1 (s1 int, s2 int, s3 int);
+create procedure bug4934()
+begin
+insert into t1 values (1,0,1);
+end//
+use test;
+call bug4934();
+select * from t1;
+s1 s2 s3
+1 0 1
+drop table t1;
+create table t1 (s1 int, s2 int, s3 int);
+drop procedure bug4934;
+create procedure bug4934()
+begin
+end//
+select * from t1;
+s1 s2 s3
+call bug4934();
+select * from t1;
+s1 s2 s3
+drop table t1;
+drop procedure bug4934;
+drop procedure if exists bug9486;
+drop table if exists t1, t2;
+create table t1 (id1 int, val int);
+create table t2 (id2 int);
+create procedure bug9486()
+update t1, t2 set val= 1 where id1=id2;
+call bug9486();
+lock tables t2 write;
+ call bug9486();
+show processlist;
+Id User Host db Command Time State Info
+# root localhost test Sleep # NULL
+# root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2
+# root localhost test Query # NULL show processlist
+# root localhost test Sleep # NULL
+unlock tables;
+drop procedure bug9486;
+drop table t1, t2;
+drop procedure if exists bug11158;
+create procedure bug11158() delete t1 from t1, t2 where t1.id = t2.id;
+create table t1 (id int, j int);
+insert into t1 values (1, 1), (2, 2);
+create table t2 (id int);
+insert into t2 values (1);
+call bug11158();
+select * from t1;
+id j
+2 2
+lock tables t2 read;
+call bug11158();
+unlock tables;
+drop procedure bug11158;
+drop table t1, t2;
+drop function if exists bug11554;
+drop view if exists v1;
+create table t1 (i int);
+create function bug11554 () returns int return 1;
+create view v1 as select bug11554() as f;
+insert into t1 (select f from v1);
+drop function bug11554;
+drop table t1;
+drop view v1;
+drop procedure if exists p1;
+drop procedure if exists p2;
+create table t1 (s1 int)|
+create procedure p1() select * from t1|
+create procedure p2()
+begin
+insert into t1 values (1);
+call p1();
+select * from t1;
+end|
+use test;
+lock table t1 write;
+ call p2();
+use test;
+drop procedure p1;
+create procedure p1() select * from t1;
+unlock tables;
+s1
+1
+s1
+1
+drop procedure p1;
+drop procedure p2;
+drop table t1;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
new file mode 100644
index 00000000000..aedaaad9398
--- /dev/null
+++ b/mysql-test/r/sp.result
@@ -0,0 +1,3351 @@
+use test;
+drop table if exists t1,t2,t3,t4;
+create table t1 (
+id char(16) not null default '',
+data int not null
+);
+create table t2 (
+s char(16),
+i int,
+d double
+);
+drop procedure if exists foo42;
+create procedure foo42()
+insert into test.t1 values ("foo", 42);
+call foo42();
+select * from t1;
+id data
+foo 42
+delete from t1;
+drop procedure foo42;
+drop procedure if exists bar;
+create procedure bar(x char(16), y int)
+insert into test.t1 values (x, y);
+call bar("bar", 666);
+select * from t1;
+id data
+bar 666
+delete from t1;
+drop procedure if exists empty|
+create procedure empty()
+begin
+end|
+call empty()|
+drop procedure empty|
+drop procedure if exists scope|
+create procedure scope(a int, b float)
+begin
+declare b int;
+declare c float;
+begin
+declare c int;
+end;
+end|
+drop procedure scope|
+drop procedure if exists two|
+create procedure two(x1 char(16), x2 char(16), y int)
+begin
+insert into test.t1 values (x1, y);
+insert into test.t1 values (x2, y);
+end|
+call two("one", "two", 3)|
+select * from t1|
+id data
+one 3
+two 3
+delete from t1|
+drop procedure two|
+drop procedure if exists locset|
+create procedure locset(x char(16), y int)
+begin
+declare z1, z2 int;
+set z1 = y;
+set z2 = z1+2;
+insert into test.t1 values (x, z2);
+end|
+call locset("locset", 19)|
+select * from t1|
+id data
+locset 21
+delete from t1|
+drop procedure locset|
+drop procedure if exists setcontext|
+create procedure setcontext()
+begin
+declare data int default 2;
+insert into t1 (id, data) values ("foo", 1);
+replace t1 set data = data, id = "bar";
+update t1 set id = "kaka", data = 3 where t1.data = data;
+end|
+call setcontext()|
+select * from t1|
+id data
+foo 1
+kaka 3
+delete from t1|
+drop procedure setcontext|
+create table t3 ( d date, i int, f double, s varchar(32) )|
+drop procedure if exists nullset|
+create procedure nullset()
+begin
+declare ld date;
+declare li int;
+declare lf double;
+declare ls varchar(32);
+set ld = null, li = null, lf = null, ls = null;
+insert into t3 values (ld, li, lf, ls);
+insert into t3 (i, f, s) values ((ld is null), 1, "ld is null"),
+((li is null), 1, "li is null"),
+((li = 0), null, "li = 0"),
+((lf is null), 1, "lf is null"),
+((lf = 0), null, "lf = 0"),
+((ls is null), 1, "ls is null");
+end|
+call nullset()|
+select * from t3|
+d i f s
+NULL NULL NULL NULL
+NULL 1 1 ld is null
+NULL 1 1 li is null
+NULL NULL NULL li = 0
+NULL 1 1 lf is null
+NULL NULL NULL lf = 0
+NULL 1 1 ls is null
+drop table t3|
+drop procedure nullset|
+drop procedure if exists mixset|
+create procedure mixset(x char(16), y int)
+begin
+declare z int;
+set @z = y, z = 666, max_join_size = 100;
+insert into test.t1 values (x, z);
+end|
+call mixset("mixset", 19)|
+show variables like 'max_join_size'|
+Variable_name Value
+max_join_size 100
+select id,data,@z from t1|
+id data @z
+mixset 666 19
+delete from t1|
+drop procedure mixset|
+drop procedure if exists zip|
+create procedure zip(x char(16), y int)
+begin
+declare z int;
+call zap(y, z);
+call bar(x, z);
+end|
+drop procedure if exists zap|
+create procedure zap(x int, out y int)
+begin
+declare z int;
+set z = x+1, y = z;
+end|
+call zip("zip", 99)|
+select * from t1|
+id data
+zip 100
+delete from t1|
+drop procedure zip|
+drop procedure bar|
+call zap(7, @zap)|
+select @zap|
+@zap
+8
+drop procedure zap|
+drop procedure if exists c1|
+create procedure c1(x int)
+call c2("c", x)|
+drop procedure if exists c2|
+create procedure c2(s char(16), x int)
+call c3(x, s)|
+drop procedure if exists c3|
+create procedure c3(x int, s char(16))
+call c4("level", x, s)|
+drop procedure if exists c4|
+create procedure c4(l char(8), x int, s char(16))
+insert into t1 values (concat(l,s), x)|
+call c1(42)|
+select * from t1|
+id data
+levelc 42
+delete from t1|
+drop procedure c1|
+drop procedure c2|
+drop procedure c3|
+drop procedure c4|
+drop procedure if exists iotest|
+create procedure iotest(x1 char(16), x2 char(16), y int)
+begin
+call inc2(x2, y);
+insert into test.t1 values (x1, y);
+end|
+drop procedure if exists inc2|
+create procedure inc2(x char(16), y int)
+begin
+call inc(y);
+insert into test.t1 values (x, y);
+end|
+drop procedure if exists inc|
+create procedure inc(inout io int)
+set io = io + 1|
+call iotest("io1", "io2", 1)|
+select * from t1|
+id data
+io2 2
+io1 1
+delete from t1|
+drop procedure iotest|
+drop procedure inc2|
+drop procedure if exists incr|
+create procedure incr(inout x int)
+call inc(x)|
+select @zap|
+@zap
+8
+call incr(@zap)|
+select @zap|
+@zap
+9
+drop procedure inc|
+drop procedure incr|
+drop procedure if exists cbv1|
+create procedure cbv1()
+begin
+declare y int default 3;
+call cbv2(y+1, y);
+insert into test.t1 values ("cbv1", y);
+end|
+drop procedure if exists cbv2|
+create procedure cbv2(y1 int, inout y2 int)
+begin
+set y2 = 4711;
+insert into test.t1 values ("cbv2", y1);
+end|
+call cbv1()|
+select * from t1|
+id data
+cbv2 4
+cbv1 4711
+delete from t1|
+drop procedure cbv1|
+drop procedure cbv2|
+insert into t2 values ("a", 1, 1.1), ("b", 2, 1.2), ("c", 3, 1.3)|
+drop procedure if exists sub1|
+create procedure sub1(id char(16), x int)
+insert into test.t1 values (id, x)|
+drop procedure if exists sub2|
+create procedure sub2(id char(16))
+begin
+declare x int;
+set x = (select sum(t.i) from test.t2 t);
+insert into test.t1 values (id, x);
+end|
+drop procedure if exists sub3|
+create function sub3(i int) returns int
+return i+1|
+call sub1("sub1a", (select 7))|
+call sub1("sub1b", (select max(i) from t2))|
+call sub1("sub1c", (select i,d from t2 limit 1))|
+call sub1("sub1d", (select 1 from (select 1) a))|
+call sub2("sub2")|
+select * from t1|
+id data
+sub1a 7
+sub1b 3
+sub1c 1
+sub1d 1
+sub2 6
+select sub3((select max(i) from t2))|
+sub3((select max(i) from t2))
+4
+drop procedure sub1|
+drop procedure sub2|
+drop function sub3|
+delete from t1|
+delete from t2|
+drop procedure if exists a0|
+create procedure a0(x int)
+while x do
+set x = x-1;
+insert into test.t1 values ("a0", x);
+end while|
+call a0(3)|
+select * from t1|
+id data
+a0 2
+a0 1
+a0 0
+delete from t1|
+drop procedure a0|
+drop procedure if exists a|
+create procedure a(x int)
+while x > 0 do
+set x = x-1;
+insert into test.t1 values ("a", x);
+end while|
+call a(3)|
+select * from t1|
+id data
+a 2
+a 1
+a 0
+delete from t1|
+drop procedure a|
+drop procedure if exists b|
+create procedure b(x int)
+repeat
+insert into test.t1 values (repeat("b",3), x);
+set x = x-1;
+until x = 0 end repeat|
+call b(3)|
+select * from t1|
+id data
+bbb 3
+bbb 2
+bbb 1
+delete from t1|
+drop procedure b|
+drop procedure if exists b2|
+create procedure b2(x int)
+repeat(select 1 into outfile 'b2');
+insert into test.t1 values (repeat("b2",3), x);
+set x = x-1;
+until x = 0 end repeat|
+drop procedure b2|
+drop procedure if exists c|
+create procedure c(x int)
+hmm: while x > 0 do
+insert into test.t1 values ("c", x);
+set x = x-1;
+iterate hmm;
+insert into test.t1 values ("x", x);
+end while hmm|
+call c(3)|
+select * from t1|
+id data
+c 3
+c 2
+c 1
+delete from t1|
+drop procedure c|
+drop procedure if exists d|
+create procedure d(x int)
+hmm: while x > 0 do
+insert into test.t1 values ("d", x);
+set x = x-1;
+leave hmm;
+insert into test.t1 values ("x", x);
+end while|
+call d(3)|
+select * from t1|
+id data
+d 3
+delete from t1|
+drop procedure d|
+drop procedure if exists e|
+create procedure e(x int)
+foo: loop
+if x = 0 then
+leave foo;
+end if;
+insert into test.t1 values ("e", x);
+set x = x-1;
+end loop foo|
+call e(3)|
+select * from t1|
+id data
+e 3
+e 2
+e 1
+delete from t1|
+drop procedure e|
+drop procedure if exists f|
+create procedure f(x int)
+if x < 0 then
+insert into test.t1 values ("f", 0);
+elseif x = 0 then
+insert into test.t1 values ("f", 1);
+else
+insert into test.t1 values ("f", 2);
+end if|
+call f(-2)|
+call f(0)|
+call f(4)|
+select * from t1|
+id data
+f 0
+f 1
+f 2
+delete from t1|
+drop procedure f|
+drop procedure if exists g|
+create procedure g(x int)
+case
+when x < 0 then
+insert into test.t1 values ("g", 0);
+when x = 0 then
+insert into test.t1 values ("g", 1);
+else
+insert into test.t1 values ("g", 2);
+end case|
+call g(-42)|
+call g(0)|
+call g(1)|
+select * from t1|
+id data
+g 0
+g 1
+g 2
+delete from t1|
+drop procedure g|
+drop procedure if exists h|
+create procedure h(x int)
+case x
+when 0 then
+insert into test.t1 values ("h0", x);
+when 1 then
+insert into test.t1 values ("h1", x);
+else
+insert into test.t1 values ("h?", x);
+end case|
+call h(0)|
+call h(1)|
+call h(17)|
+select * from t1|
+id data
+h0 0
+h1 1
+h? 17
+delete from t1|
+drop procedure h|
+drop procedure if exists i|
+create procedure i(x int)
+foo:
+begin
+if x = 0 then
+leave foo;
+end if;
+insert into test.t1 values ("i", x);
+end foo|
+call i(0)|
+call i(3)|
+select * from t1|
+id data
+i 3
+delete from t1|
+drop procedure i|
+insert into t1 values ("foo", 3), ("bar", 19)|
+insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
+drop procedure if exists sel1|
+create procedure sel1()
+begin
+select * from t1;
+end|
+call sel1()|
+id data
+foo 3
+bar 19
+drop procedure sel1|
+drop procedure if exists sel2|
+create procedure sel2()
+begin
+select * from t1;
+select * from t2;
+end|
+call sel2()|
+id data
+foo 3
+bar 19
+s i d
+x 9 4.1
+y -1 19.2
+z 3 2.2
+drop procedure sel2|
+delete from t1|
+delete from t2|
+drop procedure if exists into_test|
+create procedure into_test(x char(16), y int)
+begin
+insert into test.t1 values (x, y);
+select id,data into x,y from test.t1 limit 1;
+insert into test.t1 values (concat(x, "2"), y+2);
+end|
+call into_test("into", 100)|
+select * from t1|
+id data
+into 100
+into2 102
+delete from t1|
+drop procedure into_test|
+drop procedure if exists into_tes2|
+create procedure into_test2(x char(16), y int)
+begin
+insert into test.t1 values (x, y);
+select id,data into x,@z from test.t1 limit 1;
+insert into test.t1 values (concat(x, "2"), y+2);
+end|
+call into_test2("into", 100)|
+select id,data,@z from t1|
+id data @z
+into 100 100
+into2 102 100
+delete from t1|
+drop procedure into_test2|
+drop procedure if exists into_test3|
+create procedure into_test3()
+begin
+declare x char(16);
+declare y int;
+select * into x,y from test.t1 limit 1;
+insert into test.t2 values (x, y, 0.0);
+end|
+insert into t1 values ("into3", 19)|
+call into_test3()|
+call into_test3()|
+select * from t2|
+s i d
+into3 19 0
+into3 19 0
+delete from t1|
+delete from t2|
+drop procedure into_test3|
+drop procedure if exists into_test4|
+create procedure into_test4()
+begin
+declare x int;
+select data into x from test.t1 limit 1;
+insert into test.t3 values ("into4", x);
+end|
+delete from t1|
+create table t3 ( s char(16), d int)|
+call into_test4()|
+Warnings:
+Warning 1329 No data to FETCH
+select * from t3|
+s d
+into4 NULL
+insert into t1 values ("i4", 77)|
+call into_test4()|
+select * from t3|
+s d
+into4 NULL
+into4 77
+delete from t1|
+drop table t3|
+drop procedure into_test4|
+drop procedure if exists into_outfile|
+create procedure into_outfile(x char(16), y int)
+begin
+insert into test.t1 values (x, y);
+select * into outfile "/tmp/spout" from test.t1;
+insert into test.t1 values (concat(x, "2"), y+2);
+end|
+call into_outfile("ofile", 1)|
+delete from t1|
+drop procedure into_outfile|
+drop procedure if exists into_dumpfile|
+create procedure into_dumpfile(x char(16), y int)
+begin
+insert into test.t1 values (x, y);
+select * into dumpfile "/tmp/spdump" from test.t1 limit 1;
+insert into test.t1 values (concat(x, "2"), y+2);
+end|
+call into_dumpfile("dfile", 1)|
+delete from t1|
+drop procedure into_dumpfile|
+drop procedure if exists create_select|
+create procedure create_select(x char(16), y int)
+begin
+insert into test.t1 values (x, y);
+create temporary table test.t3 select * from test.t1;
+insert into test.t3 values (concat(x, "2"), y+2);
+end|
+call create_select("cs", 90)|
+select * from t1, t3|
+id data id data
+cs 90 cs 90
+cs 90 cs2 92
+drop table t3|
+delete from t1|
+drop procedure create_select|
+drop function if exists e|
+create function e() returns double
+return 2.7182818284590452354|
+set @e = e()|
+select e(), @e|
+e() @e
+2.718281828459 2.718281828459
+drop function if exists inc|
+create function inc(i int) returns int
+return i+1|
+select inc(1), inc(99), inc(-71)|
+inc(1) inc(99) inc(-71)
+2 100 -70
+drop function if exists mul|
+create function mul(x int, y int) returns int
+return x*y|
+select mul(1,1), mul(3,5), mul(4711, 666)|
+mul(1,1) mul(3,5) mul(4711, 666)
+1 15 3137526
+drop function if exists append|
+create function append(s1 char(8), s2 char(8)) returns char(16)
+return concat(s1, s2)|
+select append("foo", "bar")|
+append("foo", "bar")
+foobar
+drop function if exists fac|
+create function fac(n int unsigned) returns bigint unsigned
+begin
+declare f bigint unsigned default 1;
+while n > 1 do
+set f = f * n;
+set n = n - 1;
+end while;
+return f;
+end|
+select fac(1), fac(2), fac(5), fac(10)|
+fac(1) fac(2) fac(5) fac(10)
+1 2 120 3628800
+drop function if exists fun|
+create function fun(d double, i int, u int unsigned) returns double
+return mul(inc(i), fac(u)) / e()|
+select fun(2.3, 3, 5)|
+fun(2.3, 3, 5)
+176.58213176229
+insert into t2 values (append("xxx", "yyy"), mul(4,3), e())|
+insert into t2 values (append("a", "b"), mul(2,mul(3,4)), fun(1.7, 4, 6))|
+select * from t2 where s = append("a", "b")|
+s i d
+ab 24 1324.36598821719
+select * from t2 where i = mul(4,3) or i = mul(mul(3,4),2)|
+s i d
+xxxyyy 12 2.71828182845905
+ab 24 1324.36598821719
+select * from t2 where d = e()|
+s i d
+xxxyyy 12 2.71828182845905
+select * from t2|
+s i d
+xxxyyy 12 2.71828182845905
+ab 24 1324.36598821719
+delete from t2|
+drop function e|
+drop function inc|
+drop function mul|
+drop function append|
+drop function fun|
+drop procedure if exists hndlr1|
+create procedure hndlr1(val int)
+begin
+declare x int default 0;
+declare foo condition for 1136;
+declare bar condition for sqlstate '42S98'; # Just for testing syntax
+declare zip condition for sqlstate value '42S99'; # Just for testing syntax
+declare continue handler for foo set x = 1;
+insert into test.t1 values ("hndlr1", val, 2); # Too many values
+if (x) then
+insert into test.t1 values ("hndlr1", val); # This instead then
+end if;
+end|
+call hndlr1(42)|
+select * from t1|
+id data
+hndlr1 42
+delete from t1|
+drop procedure hndlr1|
+drop procedure if exists hndlr2|
+create procedure hndlr2(val int)
+begin
+declare x int default 0;
+begin
+declare exit handler for sqlstate '21S01' set x = 1;
+insert into test.t1 values ("hndlr2", val, 2); # Too many values
+end;
+insert into test.t1 values ("hndlr2", x);
+end|
+call hndlr2(42)|
+select * from t1|
+id data
+hndlr2 1
+delete from t1|
+drop procedure hndlr2|
+drop procedure if exists hndlr3|
+create procedure hndlr3(val int)
+begin
+declare x int default 0;
+declare continue handler for sqlexception # Any error
+begin
+declare z int;
+set z = 2 * val;
+set x = 1;
+end;
+if val < 10 then
+begin
+declare y int;
+set y = val + 10;
+insert into test.t1 values ("hndlr3", y, 2); # Too many values
+if x then
+insert into test.t1 values ("hndlr3", y);
+end if;
+end;
+end if;
+end|
+call hndlr3(3)|
+select * from t1|
+id data
+hndlr3 13
+delete from t1|
+drop procedure hndlr3|
+create table t3 ( id char(16), data int )|
+drop procedure if exists hndlr4|
+create procedure hndlr4()
+begin
+declare x int default 0;
+declare val int; # No default
+declare continue handler for sqlstate '02000' set x=1;
+select data into val from test.t3 where id='z' limit 1; # No hits
+insert into test.t3 values ('z', val);
+end|
+call hndlr4()|
+select * from t3|
+id data
+z NULL
+drop table t3|
+drop procedure hndlr4|
+drop procedure if exists cur1|
+create procedure cur1()
+begin
+declare a char(16);
+declare b int;
+declare c double;
+declare done int default 0;
+declare c cursor for select * from test.t2;
+declare continue handler for sqlstate '02000' set done = 1;
+open c;
+repeat
+fetch c into a, b, c;
+if not done then
+insert into test.t1 values (a, b+c);
+end if;
+until done end repeat;
+close c;
+end|
+insert into t2 values ("foo", 42, -1.9), ("bar", 3, 12.1), ("zap", 666, -3.14)|
+call cur1()|
+select * from t1|
+id data
+foo 40
+bar 15
+zap 663
+drop procedure cur1|
+create table t3 ( s char(16), i int )|
+drop procedure if exists cur2|
+create procedure cur2()
+begin
+declare done int default 0;
+declare c1 cursor for select id,data from test.t1;
+declare c2 cursor for select i from test.t2;
+declare continue handler for sqlstate '02000' set done = 1;
+open c1;
+open c2;
+repeat
+begin
+declare a char(16);
+declare b,c int;
+fetch from c1 into a, b;
+fetch next from c2 into c;
+if not done then
+if b < c then
+insert into test.t3 values (a, b);
+else
+insert into test.t3 values (a, c);
+end if;
+end if;
+end;
+until done end repeat;
+close c1;
+close c2;
+end|
+call cur2()|
+select * from t3|
+s i
+foo 40
+bar 3
+zap 663
+delete from t1|
+delete from t2|
+drop table t3|
+drop procedure cur2|
+drop procedure if exists chistics|
+create procedure chistics()
+language sql
+modifies sql data
+not deterministic
+sql security definer
+comment 'Characteristics procedure test'
+ insert into t1 values ("chistics", 1)|
+show create procedure chistics|
+Procedure sql_mode Create Procedure
+chistics CREATE PROCEDURE `chistics`()
+ MODIFIES SQL DATA
+ COMMENT 'Characteristics procedure test'
+insert into t1 values ("chistics", 1)
+call chistics()|
+select * from t1|
+id data
+chistics 1
+delete from t1|
+alter procedure chistics sql security invoker|
+show create procedure chistics|
+Procedure sql_mode Create Procedure
+chistics CREATE PROCEDURE `chistics`()
+ MODIFIES SQL DATA
+ SQL SECURITY INVOKER
+ COMMENT 'Characteristics procedure test'
+insert into t1 values ("chistics", 1)
+drop procedure chistics|
+drop function if exists chistics|
+create function chistics() returns int
+language sql
+deterministic
+sql security invoker
+comment 'Characteristics procedure test'
+ return 42|
+show create function chistics|
+Function sql_mode Create Function
+chistics CREATE FUNCTION `chistics`() RETURNS int(11)
+ DETERMINISTIC
+ SQL SECURITY INVOKER
+ COMMENT 'Characteristics procedure test'
+return 42
+select chistics()|
+chistics()
+42
+alter function chistics
+no sql
+comment 'Characteristics function test'|
+show create function chistics|
+Function sql_mode Create Function
+chistics CREATE FUNCTION `chistics`() RETURNS int(11)
+ NO SQL
+ DETERMINISTIC
+ SQL SECURITY INVOKER
+ COMMENT 'Characteristics function test'
+return 42
+drop function chistics|
+insert into t1 values ("foo", 1), ("bar", 2), ("zip", 3)|
+set @@sql_mode = 'ANSI'|
+drop procedure if exists modes$
+create procedure modes(out c1 int, out c2 int)
+begin
+declare done int default 0;
+declare x int;
+declare c cursor for select data from t1;
+declare continue handler for sqlstate '02000' set done = 1;
+select 1 || 2 into c1;
+set c2 = 0;
+open c;
+repeat
+fetch c into x;
+if not done then
+set c2 = c2 + 1;
+end if;
+until done end repeat;
+close c;
+end$
+set @@sql_mode = ''|
+set sql_select_limit = 1|
+call modes(@c1, @c2)|
+set sql_select_limit = default|
+select @c1, @c2|
+@c1 @c2
+12 3
+delete from t1|
+drop procedure modes|
+create database sp_db1|
+drop database sp_db1|
+create database sp_db2|
+use sp_db2|
+create table t3 ( s char(4), t int )|
+insert into t3 values ("abcd", 42), ("dcba", 666)|
+use test|
+drop database sp_db2|
+create database sp_db3|
+use sp_db3|
+drop procedure if exists dummy|
+create procedure dummy(out x int)
+set x = 42|
+use test|
+drop database sp_db3|
+select type,db,name from mysql.proc where db = 'sp_db3'|
+type db name
+drop procedure if exists rc|
+create procedure rc()
+begin
+delete from t1;
+insert into t1 values ("a", 1), ("b", 2), ("c", 3);
+end|
+call rc()|
+select row_count()|
+row_count()
+3
+update t1 set data=42 where id = "b";
+select row_count()|
+row_count()
+1
+delete from t1|
+select row_count()|
+row_count()
+3
+delete from t1|
+select row_count()|
+row_count()
+0
+select * from t1|
+id data
+select row_count()|
+row_count()
+-1
+drop procedure rc|
+drop function if exists f0|
+drop function if exists f1|
+drop function if exists f2|
+drop function if exists f3|
+drop function if exists f4|
+drop function if exists f5|
+drop function if exists f6|
+drop function if exists f7|
+drop function if exists f8|
+drop view if exists v0|
+drop view if exists v1|
+drop view if exists v2|
+delete from t1|
+delete from t2|
+insert into t1 values ("a", 1), ("b", 2) |
+insert into t2 values ("a", 1, 1.0), ("b", 2, 2.0), ("c", 3, 3.0) |
+create function f1() returns int
+return (select sum(data) from t1)|
+select f1()|
+f1()
+3
+select id, f1() from t1|
+id f1()
+a 3
+b 3
+create function f2() returns int
+return (select data from t1 where data <= (select sum(data) from t1) limit 1)|
+select f2()|
+f2()
+1
+select id, f2() from t1|
+id f2()
+a 1
+b 1
+create function f3() returns int
+begin
+declare n int;
+declare m int;
+set n:= (select min(data) from t1);
+set m:= (select max(data) from t1);
+return n < m;
+end|
+select f3()|
+f3()
+1
+select id, f3() from t1|
+id f3()
+a 1
+b 1
+select f1(), f3()|
+f1() f3()
+3 1
+select id, f1(), f3() from t1|
+id f1() f3()
+a 3 1
+b 3 1
+create function f4() returns double
+return (select d from t1, t2 where t1.data = t2.i and t1.id= "b")|
+select f4()|
+f4()
+2
+select s, f4() from t2|
+s f4()
+a 2
+b 2
+c 2
+create function f5(i int) returns int
+begin
+if i <= 0 then
+return 0;
+elseif i = 1 then
+return (select count(*) from t1 where data = i);
+else
+return (select count(*) + f5( i - 1) from t1 where data = i);
+end if;
+end|
+select f5(1)|
+f5(1)
+1
+create function f6() returns int
+begin
+declare n int;
+set n:= f1();
+return (select count(*) from t1 where data <= f7() and data <= n);
+end|
+create function f7() returns int
+return (select sum(data) from t1 where data <= f1())|
+select f6()|
+f6()
+2
+select id, f6() from t1|
+id f6()
+a 2
+b 2
+create view v1 (a) as select f1()|
+select * from v1|
+a
+3
+select id, a from t1, v1|
+id a
+a 3
+b 3
+select * from v1, v1 as v|
+a a
+3 3
+create view v2 (a) as select a*10 from v1|
+select * from v2|
+a
+30
+select id, a from t1, v2|
+id a
+a 30
+b 30
+select * from v1, v2|
+a a
+3 30
+create function f8 () returns int
+return (select count(*) from v2)|
+select *, f8() from v1|
+a f8()
+3 1
+drop function f1|
+select * from v1|
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s)
+create function f1() returns int
+return (select sum(data) from t1) + (select sum(data) from v1)|
+drop function f1|
+create function f1() returns int
+return (select sum(data) from t1)|
+create function f0() returns int
+return (select * from (select 100) as r)|
+select f0()|
+f0()
+100
+select *, f0() from (select 1) as t|
+1 f0()
+1 100
+create view v0 as select f0()|
+select * from v0|
+f0()
+100
+select *, f0() from v0|
+f0() f0()
+100 100
+lock tables t1 read, t1 as t11 read, mysql.proc read|
+select f3()|
+f3()
+1
+select id, f3() from t1 as t11|
+id f3()
+a 1
+b 1
+select f0()|
+f0()
+100
+select * from v0|
+f0()
+100
+select *, f0() from v0, (select 123) as d1|
+f0() 123 f0()
+100 123 100
+select id, f3() from t1|
+ERROR HY000: Table 't1' was not locked with LOCK TABLES
+select f4()|
+ERROR HY000: Table 't2' was not locked with LOCK TABLES
+unlock tables|
+lock tables v2 read, mysql.proc read|
+select * from v2|
+a
+30
+select * from v1|
+a
+3
+select * from v1, t1|
+ERROR HY000: Table 't1' was not locked with LOCK TABLES
+select f4()|
+ERROR HY000: Table 't2' was not locked with LOCK TABLES
+unlock tables|
+drop function f0|
+drop function f1|
+drop function f2|
+drop function f3|
+drop function f4|
+drop function f5|
+drop function f6|
+drop function f7|
+drop function f8|
+drop view v0|
+drop view v1|
+drop view v2|
+delete from t1 |
+delete from t2 |
+drop table if exists fac|
+create table fac (n int unsigned not null primary key, f bigint unsigned)|
+drop procedure if exists ifac|
+create procedure ifac(n int unsigned)
+begin
+declare i int unsigned default 1;
+if n > 20 then
+set n = 20; # bigint overflow otherwise
+end if;
+while i <= n do
+begin
+insert into test.fac values (i, fac(i));
+set i = i + 1;
+end;
+end while;
+end|
+call ifac(20)|
+select * from fac|
+n f
+1 1
+2 2
+3 6
+4 24
+5 120
+6 720
+7 5040
+8 40320
+9 362880
+10 3628800
+11 39916800
+12 479001600
+13 6227020800
+14 87178291200
+15 1307674368000
+16 20922789888000
+17 355687428096000
+18 6402373705728000
+19 121645100408832000
+20 2432902008176640000
+drop table fac|
+show function status like '%f%'|
+Db Name Type Definer Modified Created Security_type Comment
+test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+drop procedure ifac|
+drop function fac|
+show function status like '%f%'|
+Db Name Type Definer Modified Created Security_type Comment
+drop table if exists primes|
+create table primes (
+i int unsigned not null primary key,
+p bigint unsigned not null
+)|
+insert into primes values
+( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13),
+( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31),
+(10, 37), (11, 41), (12, 43), (13, 47), (14, 53),
+(15, 59), (16, 61), (17, 67), (18, 71), (19, 73),
+(20, 79), (21, 83), (22, 89), (23, 97), (24, 101),
+(25, 103), (26, 107), (27, 109), (28, 113), (29, 127),
+(30, 131), (31, 137), (32, 139), (33, 149), (34, 151),
+(35, 157), (36, 163), (37, 167), (38, 173), (39, 179),
+(40, 181), (41, 191), (42, 193), (43, 197), (44, 199)|
+drop procedure if exists opp|
+create procedure opp(n bigint unsigned, out pp bool)
+begin
+declare r double;
+declare b, s bigint unsigned default 0;
+set r = sqrt(n);
+again:
+loop
+if s = 45 then
+set b = b+200, s = 0;
+else
+begin
+declare p bigint unsigned;
+select t.p into p from test.primes t where t.i = s;
+if b+p > r then
+set pp = 1;
+leave again;
+end if;
+if mod(n, b+p) = 0 then
+set pp = 0;
+leave again;
+end if;
+set s = s+1;
+end;
+end if;
+end loop;
+end|
+drop procedure if exists ip|
+create procedure ip(m int unsigned)
+begin
+declare p bigint unsigned;
+declare i int unsigned;
+set i=45, p=201;
+while i < m do
+begin
+declare pp bool default 0;
+call opp(p, pp);
+if pp then
+insert into test.primes values (i, p);
+set i = i+1;
+end if;
+set p = p+2;
+end;
+end while;
+end|
+show create procedure opp|
+Procedure sql_mode Create Procedure
+opp CREATE PROCEDURE `opp`(n bigint unsigned, out pp bool)
+begin
+declare r double;
+declare b, s bigint unsigned default 0;
+set r = sqrt(n);
+again:
+loop
+if s = 45 then
+set b = b+200, s = 0;
+else
+begin
+declare p bigint unsigned;
+select t.p into p from test.primes t where t.i = s;
+if b+p > r then
+set pp = 1;
+leave again;
+end if;
+if mod(n, b+p) = 0 then
+set pp = 0;
+leave again;
+end if;
+set s = s+1;
+end;
+end if;
+end loop;
+end
+show procedure status like '%p%'|
+Db Name Type Definer Modified Created Security_type Comment
+test ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+test opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+call ip(200)|
+select * from primes where i=45 or i=100 or i=199|
+i p
+45 211
+100 557
+199 1229
+drop table primes|
+drop procedure opp|
+drop procedure ip|
+show procedure status like '%p%'|
+Db Name Type Definer Modified Created Security_type Comment
+drop procedure if exists bar|
+create procedure bar(x char(16), y int)
+comment "111111111111" sql security invoker
+insert into test.t1 values (x, y)|
+show procedure status like 'bar'|
+Db Name Type Definer Modified Created Security_type Comment
+test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER 111111111111
+alter procedure bar comment "2222222222" sql security definer|
+alter procedure bar comment "3333333333"|
+alter procedure bar|
+show create procedure bar|
+Procedure sql_mode Create Procedure
+bar CREATE PROCEDURE `bar`(x char(16), y int)
+ COMMENT '3333333333'
+insert into test.t1 values (x, y)
+show procedure status like 'bar'|
+Db Name Type Definer Modified Created Security_type Comment
+test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER 3333333333
+drop procedure bar|
+drop procedure if exists p1|
+create procedure p1 ()
+select (select s1 from t3) from t3|
+create table t3 (s1 int)|
+call p1()|
+(select s1 from t3)
+insert into t3 values (1)|
+call p1()|
+(select s1 from t3)
+1
+drop procedure p1|
+drop table t3|
+drop function if exists foo|
+create function `foo` () returns int
+return 5|
+select `foo` ()|
+`foo` ()
+5
+drop function `foo`|
+drop function if exists t1max|
+Warnings:
+Note 1305 FUNCTION t1max does not exist
+create function t1max() returns int
+begin
+declare x int;
+select max(data) into x from t1;
+return x;
+end|
+insert into t1 values ("foo", 3), ("bar", 2), ("zip", 5), ("zap", 1)|
+select t1max()|
+t1max()
+5
+drop function t1max|
+create table t3 (
+v char(16) not null primary key,
+c int unsigned not null
+)|
+create function getcount(s char(16)) returns int
+begin
+declare x int;
+select count(*) into x from t3 where v = s;
+if x = 0 then
+insert into t3 values (s, 1);
+else
+update t3 set c = c+1 where v = s;
+end if;
+return x;
+end|
+select * from t1 where data = getcount("bar")|
+id data
+zap 1
+select * from t3|
+v c
+bar 4
+select getcount("zip")|
+getcount("zip")
+0
+select getcount("zip")|
+getcount("zip")
+1
+select * from t3|
+v c
+bar 4
+zip 2
+select getcount(id) from t1 where data = 3|
+getcount(id)
+0
+select getcount(id) from t1 where data = 5|
+getcount(id)
+1
+select * from t3|
+v c
+bar 4
+zip 3
+foo 1
+drop table t3|
+drop function getcount|
+drop procedure if exists bug822|
+create procedure bug822(a_id char(16), a_data int)
+begin
+declare n int;
+select count(*) into n from t1 where id = a_id and data = a_data;
+if n = 0 then
+insert into t1 (id, data) values (a_id, a_data);
+end if;
+end|
+delete from t1|
+call bug822('foo', 42)|
+call bug822('foo', 42)|
+call bug822('bar', 666)|
+select * from t1|
+id data
+foo 42
+bar 666
+delete from t1|
+drop procedure bug822|
+drop procedure if exists bug1495|
+create procedure bug1495()
+begin
+declare x int;
+select data into x from t1 order by id limit 1;
+if x > 10 then
+insert into t1 values ("less", x-10);
+else
+insert into t1 values ("more", x+10);
+end if;
+end|
+insert into t1 values ('foo', 12)|
+call bug1495()|
+delete from t1 where id='foo'|
+insert into t1 values ('bar', 7)|
+call bug1495()|
+delete from t1 where id='bar'|
+select * from t1|
+id data
+less 2
+more 17
+delete from t1|
+drop procedure bug1495|
+drop procedure if exists bug1547|
+create procedure bug1547(s char(16))
+begin
+declare x int;
+select data into x from t1 where s = id limit 1;
+if x > 10 then
+insert into t1 values ("less", x-10);
+else
+insert into t1 values ("more", x+10);
+end if;
+end|
+insert into t1 values ("foo", 12), ("bar", 7)|
+call bug1547("foo")|
+call bug1547("bar")|
+select * from t1|
+id data
+foo 12
+bar 7
+less 2
+more 17
+delete from t1|
+drop procedure bug1547|
+drop table if exists t70|
+create table t70 (s1 int,s2 int)|
+insert into t70 values (1,2)|
+drop procedure if exists bug1656|
+create procedure bug1656(out p1 int, out p2 int)
+select * into p1, p1 from t70|
+call bug1656(@1, @2)|
+select @1, @2|
+@1 @2
+2 NULL
+drop table t70|
+drop procedure bug1656|
+create table t3(a int)|
+drop procedure if exists bug1862|
+create procedure bug1862()
+begin
+insert into t3 values(2);
+flush tables;
+end|
+call bug1862()|
+call bug1862()|
+select * from t3|
+a
+2
+2
+drop table t3|
+drop procedure bug1862|
+drop procedure if exists bug1874|
+create procedure bug1874()
+begin
+declare x int;
+declare y double;
+select max(data) into x from t1;
+insert into t2 values ("max", x, 0);
+select min(data) into x from t1;
+insert into t2 values ("min", x, 0);
+select sum(data) into x from t1;
+insert into t2 values ("sum", x, 0);
+select avg(data) into y from t1;
+insert into t2 values ("avg", 0, y);
+end|
+insert into t1 (data) values (3), (1), (5), (9), (4)|
+call bug1874()|
+select * from t2|
+s i d
+max 9 0
+min 1 0
+sum 22 0
+avg 0 4.4
+delete from t1|
+delete from t2|
+drop procedure bug1874|
+drop procedure if exists bug2260|
+create procedure bug2260()
+begin
+declare v1 int;
+declare c1 cursor for select data from t1;
+declare continue handler for not found set @x2 = 1;
+open c1;
+fetch c1 into v1;
+set @x2 = 2;
+close c1;
+end|
+call bug2260()|
+select @x2|
+@x2
+2
+drop procedure bug2260|
+drop procedure if exists bug2227|
+create procedure bug2227(x int)
+begin
+declare y float default 2.6;
+declare z char(16) default "zzz";
+select 1.3, x, y, 42, z;
+end|
+call bug2227(9)|
+1.3 x y 42 z
+1.3 9 2.6 42 zzz
+drop procedure bug2227|
+drop function if exists bug2674|
+create function bug2674() returns int
+return @@sort_buffer_size|
+set @osbs = @@sort_buffer_size|
+set @@sort_buffer_size = 262000|
+select bug2674()|
+bug2674()
+262000
+drop function bug2674|
+set @@sort_buffer_size = @osbs|
+drop procedure if exists bug3259_1 |
+create procedure bug3259_1 () begin end|
+drop procedure if exists BUG3259_2 |
+create procedure BUG3259_2 () begin end|
+drop procedure if exists Bug3259_3 |
+create procedure Bug3259_3 () begin end|
+call BUG3259_1()|
+call BUG3259_1()|
+call bug3259_2()|
+call Bug3259_2()|
+call bug3259_3()|
+call bUG3259_3()|
+drop procedure bUg3259_1|
+drop procedure BuG3259_2|
+drop procedure BUG3259_3|
+drop function if exists bug2772|
+create function bug2772() returns char(10) character set latin2
+return 'a'|
+select bug2772()|
+bug2772()
+a
+drop function bug2772|
+drop procedure if exists bug2776_1|
+create procedure bug2776_1(out x int)
+begin
+declare v int;
+set v = default;
+set x = v;
+end|
+drop procedure if exists bug2776_2|
+create procedure bug2776_2(out x int)
+begin
+declare v int default 42;
+set v = default;
+set x = v;
+end|
+set @x = 1|
+call bug2776_1(@x)|
+select @x|
+@x
+NULL
+call bug2776_2(@x)|
+select @x|
+@x
+42
+drop procedure bug2776_1|
+drop procedure bug2776_2|
+create table t3 (s1 smallint)|
+insert into t3 values (123456789012)|
+Warnings:
+Warning 1264 Out of range value adjusted for column 's1' at row 1
+drop procedure if exists bug2780|
+create procedure bug2780()
+begin
+declare exit handler for sqlwarning set @x = 1;
+set @x = 0;
+insert into t3 values (123456789012);
+insert into t3 values (0);
+end|
+call bug2780()|
+select @x|
+@x
+1
+select * from t3|
+s1
+32767
+32767
+drop procedure bug2780|
+drop table t3|
+create table t3 (content varchar(10) )|
+insert into t3 values ("test1")|
+insert into t3 values ("test2")|
+create table t4 (f1 int, rc int, t3 int)|
+drop procedure if exists bug1863|
+create procedure bug1863(in1 int)
+begin
+declare ind int default 0;
+declare t1 int;
+declare t2 int;
+declare t3 int;
+declare rc int default 0;
+declare continue handler for 1065 set rc = 1;
+drop temporary table if exists temp_t1;
+create temporary table temp_t1 (
+f1 int auto_increment, f2 varchar(20), primary key (f1)
+);
+insert into temp_t1 (f2) select content from t3;
+select f2 into t3 from temp_t1 where f1 = 10;
+if (rc) then
+insert into t4 values (1, rc, t3);
+end if;
+insert into t4 values (2, rc, t3);
+end|
+call bug1863(10)|
+Warnings:
+Note 1051 Unknown table 'temp_t1'
+Warning 1329 No data to FETCH
+call bug1863(10)|
+Warnings:
+Warning 1329 No data to FETCH
+select * from t4|
+f1 rc t3
+2 0 NULL
+2 0 NULL
+drop procedure bug1863|
+drop temporary table temp_t1;
+drop table t3, t4|
+create table t3 (
+OrderID int not null,
+MarketID int,
+primary key (OrderID)
+)|
+create table t4 (
+MarketID int not null,
+Market varchar(60),
+Status char(1),
+primary key (MarketID)
+)|
+insert t3 (OrderID,MarketID) values (1,1)|
+insert t3 (OrderID,MarketID) values (2,2)|
+insert t4 (MarketID,Market,Status) values (1,"MarketID One","A")|
+insert t4 (MarketID,Market,Status) values (2,"MarketID Two","A")|
+drop procedure if exists bug2656_1|
+create procedure bug2656_1()
+begin
+select
+m.Market
+from t4 m JOIN t3 o
+ON o.MarketID != 1 and o.MarketID = m.MarketID;
+end |
+drop procedure if exists bug2656_2|
+create procedure bug2656_2()
+begin
+select
+m.Market
+from
+t4 m, t3 o
+where
+m.MarketID != 1 and m.MarketID = o.MarketID;
+end |
+call bug2656_1()|
+Market
+MarketID Two
+call bug2656_1()|
+Market
+MarketID Two
+call bug2656_2()|
+Market
+MarketID Two
+call bug2656_2()|
+Market
+MarketID Two
+drop procedure bug2656_1|
+drop procedure bug2656_2|
+drop table t3, t4|
+drop procedure if exists bug3426|
+create procedure bug3426(in_time int unsigned, out x int)
+begin
+if in_time is null then
+set @stamped_time=10;
+set x=1;
+else
+set @stamped_time=in_time;
+set x=2;
+end if;
+end|
+call bug3426(1000, @i)|
+select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
+@i time
+2 01-01-1970 03:16:40
+call bug3426(NULL, @i)|
+select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
+@i time
+1 01-01-1970 03:00:10
+alter procedure bug3426 sql security invoker|
+call bug3426(NULL, @i)|
+select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
+@i time
+1 01-01-1970 03:00:10
+call bug3426(1000, @i)|
+select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
+@i time
+2 01-01-1970 03:16:40
+drop procedure bug3426|
+create table t3 (
+a int primary key,
+ach char(1)
+) engine = innodb|
+create table t4 (
+b int primary key ,
+bch char(1)
+) engine = innodb|
+insert into t3 values (1 , 'aCh1' ) , ('2' , 'aCh2')|
+Warnings:
+Warning 1265 Data truncated for column 'ach' at row 1
+Warning 1265 Data truncated for column 'ach' at row 2
+insert into t4 values (1 , 'bCh1' )|
+Warnings:
+Warning 1265 Data truncated for column 'bch' at row 1
+drop procedure if exists bug3448|
+create procedure bug3448()
+select * from t3 inner join t4 on t3.a = t4.b|
+select * from t3 inner join t4 on t3.a = t4.b|
+a ach b bch
+1 a 1 b
+call bug3448()|
+a ach b bch
+1 a 1 b
+call bug3448()|
+a ach b bch
+1 a 1 b
+drop procedure bug3448|
+drop table t3, t4|
+create table t3 (
+id int unsigned auto_increment not null primary key,
+title VARCHAR(200),
+body text,
+fulltext (title,body)
+)|
+insert into t3 (title,body) values
+('MySQL Tutorial','DBMS stands for DataBase ...'),
+('How To Use MySQL Well','After you went through a ...'),
+('Optimizing MySQL','In this tutorial we will show ...'),
+('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
+('MySQL vs. YourSQL','In the following database comparison ...'),
+('MySQL Security','When configured properly, MySQL ...')|
+drop procedure if exists bug3734 |
+create procedure bug3734 (param1 varchar(100))
+select * from t3 where match (title,body) against (param1)|
+call bug3734('database')|
+id title body
+5 MySQL vs. YourSQL In the following database comparison ...
+1 MySQL Tutorial DBMS stands for DataBase ...
+call bug3734('Security')|
+id title body
+6 MySQL Security When configured properly, MySQL ...
+drop procedure bug3734|
+drop table t3|
+drop procedure if exists bug3863|
+create procedure bug3863()
+begin
+set @a = 0;
+while @a < 5 do
+set @a = @a + 1;
+end while;
+end|
+call bug3863()|
+select @a|
+@a
+5
+call bug3863()|
+select @a|
+@a
+5
+drop procedure bug3863|
+create table t3 (
+id int(10) unsigned not null default 0,
+rid int(10) unsigned not null default 0,
+msg text not null,
+primary key (id),
+unique key rid (rid, id)
+)|
+drop procedure if exists bug2460_1|
+create procedure bug2460_1(in v int)
+begin
+( select n0.id from t3 as n0 where n0.id = v )
+union
+( select n0.id from t3 as n0, t3 as n1
+where n0.id = n1.rid and n1.id = v )
+union
+( select n0.id from t3 as n0, t3 as n1, t3 as n2
+where n0.id = n1.rid and n1.id = n2.rid and n2.id = v );
+end|
+call bug2460_1(2)|
+id
+call bug2460_1(2)|
+id
+insert into t3 values (1, 1, 'foo'), (2, 1, 'bar'), (3, 1, 'zip zap')|
+call bug2460_1(2)|
+id
+2
+1
+call bug2460_1(2)|
+id
+2
+1
+drop procedure if exists bug2460_2|
+create procedure bug2460_2()
+begin
+drop table if exists t3;
+create temporary table t3 (s1 int);
+insert into t3 select 1 union select 1;
+end|
+call bug2460_2()|
+call bug2460_2()|
+select * from t3|
+s1
+1
+drop procedure bug2460_1|
+drop procedure bug2460_2|
+drop table t3|
+set @@sql_mode = ''|
+drop procedure if exists bug2564_1|
+create procedure bug2564_1()
+comment 'Joe''s procedure'
+ insert into `t1` values ("foo", 1)|
+set @@sql_mode = 'ANSI_QUOTES'|
+drop procedure if exists bug2564_2|
+create procedure bug2564_2()
+insert into "t1" values ('foo', 1)|
+set @@sql_mode = ''$
+drop function if exists bug2564_3$
+create function bug2564_3(x int, y int) returns int
+return x || y$
+set @@sql_mode = 'ANSI'$
+drop function if exists bug2564_4$
+create function bug2564_4(x int, y int) returns int
+return x || y$
+set @@sql_mode = ''|
+show create procedure bug2564_1|
+Procedure sql_mode Create Procedure
+bug2564_1 CREATE PROCEDURE `bug2564_1`()
+ COMMENT 'Joe''s procedure'
+insert into `t1` values ("foo", 1)
+show create procedure bug2564_2|
+Procedure sql_mode Create Procedure
+bug2564_2 ANSI_QUOTES CREATE PROCEDURE "bug2564_2"()
+insert into "t1" values ('foo', 1)
+show create function bug2564_3|
+Function sql_mode Create Function
+bug2564_3 CREATE FUNCTION `bug2564_3`(x int, y int) RETURNS int(11)
+return x || y
+show create function bug2564_4|
+Function sql_mode Create Function
+bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI CREATE FUNCTION "bug2564_4"(x int, y int) RETURNS int(11)
+return x || y
+drop procedure bug2564_1|
+drop procedure bug2564_2|
+drop function bug2564_3|
+drop function bug2564_4|
+drop function if exists bug3132|
+create function bug3132(s char(20)) returns char(50)
+return concat('Hello, ', s, '!')|
+select bug3132('Bob') union all select bug3132('Judy')|
+bug3132('Bob')
+Hello, Bob!
+Hello, Judy!
+drop function bug3132|
+drop procedure if exists bug3843|
+create procedure bug3843()
+analyze table t1|
+call bug3843()|
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+call bug3843()|
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+select 1+2|
+1+2
+3
+drop procedure bug3843|
+create table t3 ( s1 char(10) )|
+insert into t3 values ('a'), ('b')|
+drop procedure if exists bug3368|
+create procedure bug3368(v char(10))
+begin
+select group_concat(v) from t3;
+end|
+call bug3368('x')|
+group_concat(v)
+x,x
+call bug3368('yz')|
+group_concat(v)
+yz,yz
+drop procedure bug3368|
+drop table t3|
+create table t3 (f1 int, f2 int)|
+insert into t3 values (1,1)|
+drop procedure if exists bug4579_1|
+create procedure bug4579_1 ()
+begin
+declare sf1 int;
+select f1 into sf1 from t3 where f1=1 and f2=1;
+update t3 set f2 = f2 + 1 where f1=1 and f2=1;
+call bug4579_2();
+end|
+drop procedure if exists bug4579_2|
+create procedure bug4579_2 ()
+begin
+end|
+call bug4579_1()|
+call bug4579_1()|
+Warnings:
+Warning 1329 No data to FETCH
+call bug4579_1()|
+Warnings:
+Warning 1329 No data to FETCH
+drop procedure bug4579_1|
+drop procedure bug4579_2|
+drop table t3|
+drop procedure if exists bug2773|
+create function bug2773() returns int return null|
+create table t3 as select bug2773()|
+show create table t3|
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `bug2773()` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t3|
+drop function bug2773|
+drop procedure if exists bug3788|
+create function bug3788() returns date return cast("2005-03-04" as date)|
+select bug3788()|
+bug3788()
+2005-03-04
+drop function bug3788|
+create function bug3788() returns binary(5) return 5|
+select bug3788()|
+bug3788()
+5
+drop function bug3788|
+create table t3 (f1 int, f2 int, f3 int)|
+insert into t3 values (1,1,1)|
+drop procedure if exists bug4726|
+create procedure bug4726()
+begin
+declare tmp_o_id INT;
+declare tmp_d_id INT default 1;
+while tmp_d_id <= 2 do
+begin
+select f1 into tmp_o_id from t3 where f2=1 and f3=1;
+set tmp_d_id = tmp_d_id + 1;
+end;
+end while;
+end|
+call bug4726()|
+call bug4726()|
+call bug4726()|
+drop procedure bug4726|
+drop table t3|
+drop procedure if exists bug4902|
+create procedure bug4902()
+begin
+show charset like 'foo';
+show collation like 'foo';
+show column types;
+show create table t1;
+show create database test;
+show databases like 'foo';
+show errors;
+show columns from t1;
+show grants for 'root'@'localhost';
+show keys from t1;
+show open tables like 'foo';
+show privileges;
+show status like 'foo';
+show tables like 'foo';
+show variables like 'foo';
+show warnings;
+end|
+call bug4902()|
+Charset Description Default collation Maxlen
+Collation Charset Id Default Compiled Sortlen
+Type Size Min_Value Max_Value Prec Scale Nullable Auto_Increment Unsigned Zerofill Searchable Case_Sensitive Default Comment
+tinyint 1 -128 127 0 0 YES YES NO YES YES NO NULL,0 A very small integer
+tinyint unsigned 1 0 255 0 0 YES YES YES YES YES NO NULL,0 A very small integer
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` char(16) NOT NULL default '',
+ `data` int(11) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+Database Create Database
+test CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */
+Database (foo)
+Level Code Message
+Field Type Null Key Default Extra
+id char(16) NO
+data int(11) NO
+Grants for root@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+Database Table In_use Name_locked
+Privilege Context Comment
+Alter Tables To alter the table
+Alter routine Functions,Procedures To alter or drop stored functions/procedures
+Create Databases,Tables,Indexes To create new databases and tables
+Create routine Functions,Procedures To use CREATE FUNCTION/PROCEDURE
+Create temporary tables Databases To use CREATE TEMPORARY TABLE
+Create view Tables To create new views
+Create user Server Admin To create new users
+Delete Tables To delete existing rows
+Drop Databases,Tables To drop databases, tables, and views
+Execute Functions,Procedures To execute stored routines
+File File access on server To read and write files on the server
+Grant option Databases,Tables,Functions,Procedures To give to other users those privileges you possess
+Index Tables To create or drop indexes
+Insert Tables To insert data into tables
+Lock tables Databases To use LOCK TABLES (together with SELECT privilege)
+Process Server Admin To view the plain text of currently executing queries
+References Databases,Tables To have references on tables
+Reload Server Admin To reload or refresh tables, logs and privileges
+Replication client Server Admin To ask where the slave or master servers are
+Replication slave Server Admin To read binary log events from the master
+Select Tables To retrieve rows from table
+Show databases Server Admin To see all databases with SHOW DATABASES
+Show view Tables To see views with SHOW CREATE VIEW
+Shutdown Server Admin To shut down the server
+Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
+Update Tables To update existing rows
+Usage Server Admin No privileges - allow connect only
+Variable_name Value
+Tables_in_test (foo)
+Variable_name Value
+Level Code Message
+call bug4902()|
+Charset Description Default collation Maxlen
+Collation Charset Id Default Compiled Sortlen
+Type Size Min_Value Max_Value Prec Scale Nullable Auto_Increment Unsigned Zerofill Searchable Case_Sensitive Default Comment
+tinyint 1 -128 127 0 0 YES YES NO YES YES NO NULL,0 A very small integer
+tinyint unsigned 1 0 255 0 0 YES YES YES YES YES NO NULL,0 A very small integer
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` char(16) NOT NULL default '',
+ `data` int(11) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+Database Create Database
+test CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */
+Database (foo)
+Level Code Message
+Field Type Null Key Default Extra
+id char(16) NO
+data int(11) NO
+Grants for root@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+Database Table In_use Name_locked
+Privilege Context Comment
+Alter Tables To alter the table
+Alter routine Functions,Procedures To alter or drop stored functions/procedures
+Create Databases,Tables,Indexes To create new databases and tables
+Create routine Functions,Procedures To use CREATE FUNCTION/PROCEDURE
+Create temporary tables Databases To use CREATE TEMPORARY TABLE
+Create view Tables To create new views
+Create user Server Admin To create new users
+Delete Tables To delete existing rows
+Drop Databases,Tables To drop databases, tables, and views
+Execute Functions,Procedures To execute stored routines
+File File access on server To read and write files on the server
+Grant option Databases,Tables,Functions,Procedures To give to other users those privileges you possess
+Index Tables To create or drop indexes
+Insert Tables To insert data into tables
+Lock tables Databases To use LOCK TABLES (together with SELECT privilege)
+Process Server Admin To view the plain text of currently executing queries
+References Databases,Tables To have references on tables
+Reload Server Admin To reload or refresh tables, logs and privileges
+Replication client Server Admin To ask where the slave or master servers are
+Replication slave Server Admin To read binary log events from the master
+Select Tables To retrieve rows from table
+Show databases Server Admin To see all databases with SHOW DATABASES
+Show view Tables To see views with SHOW CREATE VIEW
+Shutdown Server Admin To shut down the server
+Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
+Update Tables To update existing rows
+Usage Server Admin No privileges - allow connect only
+Variable_name Value
+Tables_in_test (foo)
+Variable_name Value
+Level Code Message
+drop procedure bug4902|
+drop procedure if exists bug4902_2|
+create procedure bug4902_2()
+begin
+show processlist;
+end|
+call bug4902_2()|
+Id User Host db Command Time State Info
+# root localhost test Query # NULL show processlist
+call bug4902_2()|
+Id User Host db Command Time State Info
+# root localhost test Query # NULL show processlist
+drop procedure bug4902_2|
+drop procedure if exists bug4904|
+create procedure bug4904()
+begin
+declare continue handler for sqlstate 'HY000' begin end;
+create table t2 as select * from t3;
+end|
+call bug4904()|
+ERROR 42S02: Table 'test.t3' doesn't exist
+drop procedure bug4904|
+create table t3 (s1 char character set latin1, s2 char character set latin2)|
+drop procedure if exists bug4904|
+create procedure bug4904 ()
+begin
+declare continue handler for sqlstate 'HY000' begin end;
+select s1 from t3 union select s2 from t3;
+end|
+call bug4904()|
+drop procedure bug4904|
+drop table t3|
+drop procedure if exists bug336|
+create procedure bug336(out y int)
+begin
+declare x int;
+set x = (select sum(t.data) from test.t1 t);
+set y = x;
+end|
+insert into t1 values ("a", 2), ("b", 3)|
+call bug336(@y)|
+select @y|
+@y
+5
+delete from t1|
+drop procedure bug336|
+drop procedure if exists bug3157|
+create procedure bug3157()
+begin
+if exists(select * from t1) then
+set @n= @n + 1;
+end if;
+if (select count(*) from t1) then
+set @n= @n + 1;
+end if;
+end|
+set @n = 0|
+insert into t1 values ("a", 1)|
+call bug3157()|
+select @n|
+@n
+2
+delete from t1|
+drop procedure bug3157|
+drop procedure if exists bug5251|
+create procedure bug5251()
+begin
+end|
+select created into @c1 from mysql.proc
+where db='test' and name='bug5251'|
+alter procedure bug5251 comment 'foobar'|
+select count(*) from mysql.proc
+where db='test' and name='bug5251' and created = @c1|
+count(*)
+1
+drop procedure bug5251|
+drop procedure if exists bug5251|
+create procedure bug5251()
+checksum table t1|
+call bug5251()|
+Table Checksum
+test.t1 0
+call bug5251()|
+Table Checksum
+test.t1 0
+drop procedure bug5251|
+drop procedure if exists bug5287|
+create procedure bug5287(param1 int)
+label1:
+begin
+declare c cursor for select 5;
+loop
+if param1 >= 0 then
+leave label1;
+end if;
+end loop;
+end|
+call bug5287(1)|
+drop procedure bug5287|
+drop procedure if exists bug5307|
+create procedure bug5307()
+begin
+end; set @x = 3|
+call bug5307()|
+select @x|
+@x
+3
+drop procedure bug5307|
+drop procedure if exists bug5258|
+create procedure bug5258()
+begin
+end|
+drop procedure if exists bug5258_aux|
+create procedure bug5258_aux()
+begin
+declare c, m char(19);
+select created,modified into c,m from mysql.proc where name = 'bug5258';
+if c = m then
+select 'Ok';
+else
+select c, m;
+end if;
+end|
+call bug5258_aux()|
+Ok
+Ok
+drop procedure bug5258|
+drop procedure bug5258_aux|
+drop function if exists bug4487|
+create function bug4487() returns char
+begin
+declare v char;
+return v;
+end|
+select bug4487()|
+bug4487()
+NULL
+drop function bug4487|
+drop procedure if exists bug4941|
+drop procedure if exists bug4941|
+create procedure bug4941(out x int)
+begin
+declare c cursor for select i from t2 limit 1;
+open c;
+fetch c into x;
+close c;
+end|
+insert into t2 values (null, null, null)|
+set @x = 42|
+call bug4941(@x)|
+select @x|
+@x
+NULL
+delete from t1|
+drop procedure bug4941|
+drop procedure if exists bug3583|
+drop procedure if exists bug3583|
+create procedure bug3583()
+begin
+declare c int;
+select * from t1;
+select count(*) into c from t1;
+select c;
+end|
+insert into t1 values ("x", 3), ("y", 5)|
+set @x = @@query_cache_size|
+set global query_cache_size = 10*1024*1024|
+flush status|
+flush query cache|
+show status like 'Qcache_hits'|
+Variable_name Value
+Qcache_hits 0
+call bug3583()|
+id data
+x 3
+y 5
+c
+2
+show status like 'Qcache_hits'|
+Variable_name Value
+Qcache_hits 0
+call bug3583()|
+id data
+x 3
+y 5
+c
+2
+call bug3583()|
+id data
+x 3
+y 5
+c
+2
+show status like 'Qcache_hits'|
+Variable_name Value
+Qcache_hits 2
+set global query_cache_size = @x|
+flush status|
+flush query cache|
+delete from t1|
+drop procedure bug3583|
+drop procedure if exists bug4905|
+create table t3 (s1 int,primary key (s1))|
+drop procedure if exists bug4905|
+create procedure bug4905()
+begin
+declare v int;
+declare continue handler for sqlstate '23000' set v = 5;
+insert into t3 values (1);
+end|
+call bug4905()|
+select row_count()|
+row_count()
+1
+call bug4905()|
+select row_count()|
+row_count()
+0
+call bug4905()|
+select row_count()|
+row_count()
+0
+select * from t3|
+s1
+1
+drop procedure bug4905|
+drop table t3|
+drop procedure if exists bug6029|
+drop procedure if exists bug6029|
+create procedure bug6029()
+begin
+declare exit handler for 1136 select '1136';
+declare exit handler for sqlstate '23000' select 'sqlstate 23000';
+declare continue handler for sqlexception select 'sqlexception';
+insert into t3 values (1);
+insert into t3 values (1,2);
+end|
+create table t3 (s1 int, primary key (s1))|
+insert into t3 values (1)|
+call bug6029()|
+sqlstate 23000
+sqlstate 23000
+delete from t3|
+call bug6029()|
+1136
+1136
+drop procedure bug6029|
+drop table t3|
+drop procedure if exists bug8540|
+create procedure bug8540()
+begin
+declare x int default 1;
+select x as y, x+0 as z;
+end|
+call bug8540()|
+y z
+1 1
+drop procedure bug8540|
+create table t3 (s1 int)|
+drop procedure if exists bug6642|
+create procedure bug6642()
+select abs(count(s1)) from t3|
+call bug6642()|
+abs(count(s1))
+0
+call bug6642()|
+abs(count(s1))
+0
+drop procedure bug6642|
+insert into t3 values (0),(1)|
+drop procedure if exists bug7013|
+create procedure bug7013()
+select s1,count(s1) from t3 group by s1 with rollup|
+call bug7013()|
+s1 count(s1)
+0 1
+1 1
+NULL 2
+call bug7013()|
+s1 count(s1)
+0 1
+1 1
+NULL 2
+drop procedure bug7013|
+drop table if exists t4|
+create table t4 (
+a mediumint(8) unsigned not null auto_increment,
+b smallint(5) unsigned not null,
+c char(32) not null,
+primary key (a)
+) engine=myisam default charset=latin1|
+insert into t4 values (1, 2, 'oneword')|
+insert into t4 values (2, 2, 'anotherword')|
+drop procedure if exists bug7743|
+create procedure bug7743 ( searchstring char(28) )
+begin
+declare var mediumint(8) unsigned;
+select a into var from t4 where b = 2 and c = binary searchstring limit 1;
+select var;
+end|
+call bug7743("oneword")|
+var
+1
+call bug7743("OneWord")|
+var
+NULL
+Warnings:
+Warning 1329 No data to FETCH
+call bug7743("anotherword")|
+var
+2
+call bug7743("AnotherWord")|
+var
+NULL
+Warnings:
+Warning 1329 No data to FETCH
+drop procedure bug7743|
+drop table t4|
+delete from t3|
+insert into t3 values(1)|
+drop procedure if exists bug7992_1|
+Warnings:
+Note 1305 PROCEDURE bug7992_1 does not exist
+drop procedure if exists bug7992_2|
+Warnings:
+Note 1305 PROCEDURE bug7992_2 does not exist
+create procedure bug7992_1()
+begin
+declare i int;
+select max(s1)+1 into i from t3;
+end|
+create procedure bug7992_2()
+insert into t3 (s1) select max(t4.s1)+1 from t3 as t4|
+call bug7992_1()|
+call bug7992_1()|
+call bug7992_2()|
+call bug7992_2()|
+drop procedure bug7992_1|
+drop procedure bug7992_2|
+drop table t3|
+create table t3 ( userid bigint(20) not null default 0 )|
+drop procedure if exists bug8116|
+create procedure bug8116(in _userid int)
+select * from t3 where userid = _userid|
+call bug8116(42)|
+userid
+call bug8116(42)|
+userid
+drop procedure bug8116|
+drop table t3|
+drop procedure if exists bug6857|
+create procedure bug6857(counter int)
+begin
+declare t0, t1 int;
+declare plus bool default 0;
+set t0 = current_time();
+while counter > 0 do
+set counter = counter - 1;
+end while;
+set t1 = current_time();
+if t1 > t0 then
+set plus = 1;
+end if;
+select plus;
+end|
+drop procedure bug6857|
+drop procedure if exists bug8757|
+create procedure bug8757()
+begin
+declare x int;
+declare c1 cursor for select data from t1 limit 1;
+begin
+declare y int;
+declare c2 cursor for select i from t2 limit 1;
+open c2;
+fetch c2 into y;
+close c2;
+select 2,y;
+end;
+open c1;
+fetch c1 into x;
+close c1;
+select 1,x;
+end|
+delete from t1|
+delete from t2|
+insert into t1 values ("x", 1)|
+insert into t2 values ("y", 2, 0.0)|
+call bug8757()|
+2 y
+2 2
+1 x
+1 1
+delete from t1|
+delete from t2|
+drop procedure bug8757|
+drop procedure if exists bug8762|
+drop procedure if exists bug8762; create procedure bug8762() begin end|
+drop procedure if exists bug8762; create procedure bug8762() begin end|
+drop procedure bug8762|
+drop function if exists bug5240|
+create function bug5240 () returns int
+begin
+declare x int;
+declare c cursor for select data from t1 limit 1;
+open c;
+fetch c into x;
+close c;
+return x;
+end|
+delete from t1|
+insert into t1 values ("answer", 42)|
+select id, bug5240() from t1|
+id bug5240()
+answer 42
+drop function bug5240|
+drop function if exists bug5278|
+create function bug5278 () returns char
+begin
+SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
+return 'okay';
+end|
+select bug5278()|
+ERROR 42000: Can't find any matching row in the user table
+select bug5278()|
+ERROR 42000: Can't find any matching row in the user table
+drop function bug5278|
+drop procedure if exists p1|
+create table t3(id int)|
+insert into t3 values(1)|
+create procedure bug7992()
+begin
+declare i int;
+select max(id)+1 into i from t3;
+end|
+call bug7992()|
+call bug7992()|
+drop procedure bug7992|
+drop table t3|
+create table t3 (
+lpitnumber int(11) default null,
+lrecordtype int(11) default null
+)|
+create table t4 (
+lbsiid int(11) not null default '0',
+ltradingmodeid int(11) not null default '0',
+ltradingareaid int(11) not null default '0',
+csellingprice decimal(19,4) default null,
+primary key (lbsiid,ltradingmodeid,ltradingareaid)
+)|
+create table t5 (
+lbsiid int(11) not null default '0',
+ltradingareaid int(11) not null default '0',
+primary key (lbsiid,ltradingareaid)
+)|
+drop procedure if exists bug8849|
+create procedure bug8849()
+begin
+insert into t5
+(
+t5.lbsiid,
+t5.ltradingareaid
+)
+select distinct t3.lpitnumber, t4.ltradingareaid
+from
+t4 join t3 on
+t3.lpitnumber = t4.lbsiid
+and t3.lrecordtype = 1
+left join t4 as price01 on
+price01.lbsiid = t4.lbsiid and
+price01.ltradingmodeid = 1 and
+t4.ltradingareaid = price01.ltradingareaid;
+end|
+call bug8849()|
+call bug8849()|
+call bug8849()|
+drop procedure bug8849|
+drop tables t3,t4,t5|
+drop procedure if exists bug8937|
+create procedure bug8937()
+begin
+declare s,x,y,z int;
+declare a float;
+select sum(data),avg(data),min(data),max(data) into s,x,y,z from t1;
+select s,x,y,z;
+select avg(data) into a from t1;
+select a;
+end|
+delete from t1|
+insert into t1 (data) values (1), (2), (3), (4), (6)|
+call bug8937()|
+s x y z
+16 3 1 6
+a
+3.2000
+drop procedure bug8937|
+delete from t1|
+drop procedure if exists bug6900|
+drop procedure if exists bug9074|
+drop procedure if exists bug6900_9074|
+create table t3 (w char unique, x char)|
+insert into t3 values ('a', 'b')|
+create procedure bug6900()
+begin
+declare exit handler for sqlexception select '1';
+begin
+declare exit handler for sqlexception select '2';
+insert into t3 values ('x', 'y', 'z');
+end;
+end|
+create procedure bug9074()
+begin
+declare x1, x2, x3, x4, x5, x6 int default 0;
+begin
+declare continue handler for sqlstate '23000' set x5 = 1;
+insert into t3 values ('a', 'b');
+set x6 = 1;
+end;
+begin1_label:
+begin
+declare continue handler for sqlstate '23000' set x1 = 1;
+insert into t3 values ('a', 'b');
+set x2 = 1;
+begin2_label:
+begin
+declare exit handler for sqlstate '23000' set x3 = 1;
+set x4= 1;
+insert into t3 values ('a','b');
+set x4= 0;
+end begin2_label;
+end begin1_label;
+select x1, x2, x3, x4, x5, x6;
+end|
+create procedure bug6900_9074(z int)
+begin
+declare exit handler for sqlstate '23000' select '23000';
+begin
+declare exit handler for sqlexception select 'sqlexception';
+if z = 1 then
+insert into t3 values ('a', 'b');
+else
+insert into t3 values ('x', 'y', 'z');
+end if;
+end;
+end|
+call bug6900()|
+2
+2
+call bug9074()|
+x1 x2 x3 x4 x5 x6
+1 1 1 1 1 1
+call bug6900_9074(0)|
+sqlexception
+sqlexception
+call bug6900_9074(1)|
+23000
+23000
+drop procedure bug6900|
+drop procedure bug9074|
+drop procedure bug6900_9074|
+drop table t3|
+drop procedure if exists avg|
+create procedure avg ()
+begin
+end|
+call avg ()|
+drop procedure avg|
+drop procedure if exists bug6129|
+set @old_mode= @@sql_mode;
+set @@sql_mode= "ERROR_FOR_DIVISION_BY_ZERO";
+create procedure bug6129()
+select @@sql_mode|
+call bug6129()|
+@@sql_mode
+ERROR_FOR_DIVISION_BY_ZERO
+set @@sql_mode= "NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO"|
+call bug6129()|
+@@sql_mode
+ERROR_FOR_DIVISION_BY_ZERO
+set @@sql_mode= "NO_ZERO_IN_DATE"|
+call bug6129()|
+@@sql_mode
+ERROR_FOR_DIVISION_BY_ZERO
+set @@sql_mode=@old_mode;
+drop procedure bug6129|
+drop procedure if exists bug9856|
+create procedure bug9856()
+begin
+declare v int;
+declare c cursor for select data from t1;
+declare exit handler for sqlexception, not found select '16';
+open c;
+fetch c into v;
+select v;
+end|
+delete from t1|
+call bug9856()|
+16
+16
+call bug9856()|
+16
+16
+drop procedure bug9856|
+drop procedure if exists bug9674_1|
+drop procedure if exists bug9674_2|
+create procedure bug9674_1(out arg int)
+begin
+declare temp_in1 int default 0;
+declare temp_fl1 int default 0;
+set temp_in1 = 100;
+set temp_fl1 = temp_in1/10;
+set arg = temp_fl1;
+end|
+create procedure bug9674_2()
+begin
+declare v int default 100;
+select v/10;
+end|
+call bug9674_1(@sptmp)|
+call bug9674_1(@sptmp)|
+select @sptmp|
+@sptmp
+10
+call bug9674_2()|
+v/10
+10.0000
+call bug9674_2()|
+v/10
+10.0000
+drop procedure bug9674_1|
+drop procedure bug9674_2|
+drop procedure if exists bug9598_1|
+drop procedure if exists bug9598_2|
+create procedure bug9598_1(in var_1 char(16),
+out var_2 integer, out var_3 integer)
+begin
+set var_2 = 50;
+set var_3 = 60;
+end|
+create procedure bug9598_2(in v1 char(16),
+in v2 integer,
+in v3 integer,
+in v4 integer,
+in v5 integer)
+begin
+select v1,v2,v3,v4,v5;
+call bug9598_1(v1,@tmp1,@tmp2);
+select v1,v2,v3,v4,v5;
+end|
+call bug9598_2('Test',2,3,4,5)|
+v1 v2 v3 v4 v5
+Test 2 3 4 5
+v1 v2 v3 v4 v5
+Test 2 3 4 5
+select @tmp1, @tmp2|
+@tmp1 @tmp2
+50 60
+drop procedure bug9598_1|
+drop procedure bug9598_2|
+drop procedure if exists bug9902|
+create function bug9902() returns int(11)
+begin
+set @x = @x + 1;
+return @x;
+end|
+set @qcs1 = @@query_cache_size|
+set global query_cache_size = 100000|
+set @x = 1|
+insert into t1 values ("qc", 42)|
+select bug9902() from t1|
+bug9902()
+2
+select bug9902() from t1|
+bug9902()
+3
+select @x|
+@x
+3
+set global query_cache_size = @qcs1|
+delete from t1|
+drop function bug9902|
+drop function if exists bug9102|
+create function bug9102() returns blob return 'a'|
+select bug9102()|
+bug9102()
+a
+drop function bug9102|
+drop function if exists bug7648|
+create function bug7648() returns bit(8) return 'a'|
+select bug7648()|
+bug7648()
+a
+drop function bug7648|
+drop function if exists bug9775|
+create function bug9775(v1 char(1)) returns enum('a','b') return v1|
+select bug9775('a'),bug9775('b'),bug9775('c')|
+bug9775('a') bug9775('b') bug9775('c')
+a b
+drop function bug9775|
+create function bug9775(v1 int) returns enum('a','b') return v1|
+select bug9775(1),bug9775(2),bug9775(3)|
+bug9775(1) bug9775(2) bug9775(3)
+a b
+drop function bug9775|
+create function bug9775(v1 char(1)) returns set('a','b') return v1|
+select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')|
+bug9775('a') bug9775('b') bug9775('a,b') bug9775('c')
+a b a,b
+drop function bug9775|
+create function bug9775(v1 int) returns set('a','b') return v1|
+select bug9775(1),bug9775(2),bug9775(3),bug9775(4)|
+bug9775(1) bug9775(2) bug9775(3) bug9775(4)
+a b a,b
+drop function bug9775|
+drop function if exists bug8861|
+create function bug8861(v1 int) returns year return v1|
+select bug8861(05)|
+bug8861(05)
+2005
+set @x = bug8861(05)|
+select @x|
+@x
+2005
+drop function bug8861|
+drop procedure if exists bug9004_1|
+drop procedure if exists bug9004_2|
+create procedure bug9004_1(x char(16))
+begin
+insert into t1 values (x, 42);
+insert into t1 values (x, 17);
+end|
+create procedure bug9004_2(x char(16))
+call bug9004_1(x)|
+call bug9004_1('12345678901234567')|
+Warnings:
+Warning 1265 Data truncated for column 'id' at row 1
+Warning 1265 Data truncated for column 'id' at row 2
+call bug9004_2('12345678901234567890')|
+Warnings:
+Warning 1265 Data truncated for column 'id' at row 1
+Warning 1265 Data truncated for column 'id' at row 2
+delete from t1|
+drop procedure bug9004_1|
+drop procedure bug9004_2|
+drop procedure if exists bug7293|
+insert into t1 values ('secret', 0)|
+create procedure bug7293(p1 varchar(100))
+begin
+if exists (select id from t1 where soundex(p1)=soundex(id)) then
+select 'yes';
+end if;
+end;|
+call bug7293('secret')|
+yes
+yes
+call bug7293 ('secrete')|
+yes
+yes
+drop procedure bug7293|
+delete from t1|
+drop procedure if exists bug9841|
+drop view if exists v1|
+create view v1 as select * from t1, t2 where id = s|
+create procedure bug9841 ()
+update v1 set data = 10|
+call bug9841()|
+drop view v1|
+drop procedure bug9841|
+drop procedure if exists bug5963|
+create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;|
+create table t3 (s1 int)|
+insert into t3 values (5)|
+call bug5963_1()|
+v
+5
+call bug5963_1()|
+v
+5
+drop procedure bug5963_1|
+drop table t3|
+create procedure bug5963_2 (cfk_value int)
+begin
+if cfk_value in (select cpk from t3) then
+set @x = 5;
+end if;
+end;
+|
+create table t3 (cpk int)|
+insert into t3 values (1)|
+call bug5963_2(1)|
+call bug5963_2(1)|
+drop procedure bug5963_2|
+drop table t3|
+drop function if exists bug9559|
+create function bug9559()
+returns int
+begin
+set @y = -6/2;
+return @y;
+end|
+select bug9559()|
+bug9559()
+-3
+drop function bug9559|
+drop procedure if exists bug10961|
+create procedure bug10961()
+begin
+declare v char;
+declare x int;
+declare c cursor for select * from dual;
+declare continue handler for sqlexception select x;
+set x = 1;
+open c;
+set x = 2;
+fetch c into v;
+set x = 3;
+close c;
+end|
+call bug10961()|
+x
+1
+x
+2
+x
+3
+call bug10961()|
+x
+1
+x
+2
+x
+3
+drop procedure bug10961|
+DROP PROCEDURE IF EXISTS bug6866|
+DROP VIEW IF EXISTS tv|
+Warnings:
+Note 1051 Unknown table 'test.tv'
+DROP TABLE IF EXISTS tt1,tt2,tt3|
+Warnings:
+Note 1051 Unknown table 'tt1'
+Note 1051 Unknown table 'tt2'
+Note 1051 Unknown table 'tt3'
+CREATE TABLE tt1 (a1 int, a2 int, a3 int, data varchar(10))|
+CREATE TABLE tt2 (a2 int, data2 varchar(10))|
+CREATE TABLE tt3 (a3 int, data3 varchar(10))|
+INSERT INTO tt1 VALUES (1, 1, 4, 'xx')|
+INSERT INTO tt2 VALUES (1, 'a')|
+INSERT INTO tt2 VALUES (2, 'b')|
+INSERT INTO tt2 VALUES (3, 'c')|
+INSERT INTO tt3 VALUES (4, 'd')|
+INSERT INTO tt3 VALUES (5, 'e')|
+INSERT INTO tt3 VALUES (6, 'f')|
+CREATE VIEW tv AS
+SELECT tt1.*, tt2.data2, tt3.data3
+FROM tt1 INNER JOIN tt2 ON tt1.a2 = tt2.a2
+LEFT JOIN tt3 ON tt1.a3 = tt3.a3
+ORDER BY tt1.a1, tt2.a2, tt3.a3|
+CREATE PROCEDURE bug6866 (_a1 int)
+BEGIN
+SELECT * FROM tv WHERE a1 = _a1;
+END|
+CALL bug6866(1)|
+a1 a2 a3 data data2 data3
+1 1 4 xx a d
+CALL bug6866(1)|
+a1 a2 a3 data data2 data3
+1 1 4 xx a d
+CALL bug6866(1)|
+a1 a2 a3 data data2 data3
+1 1 4 xx a d
+DROP PROCEDURE bug6866;
+DROP VIEW tv|
+DROP TABLE tt1, tt2, tt3|
+DROP PROCEDURE IF EXISTS bug10136|
+create table t3 ( name char(5) not null primary key, val float not null)|
+insert into t3 values ('aaaaa', 1), ('bbbbb', 2), ('ccccc', 3)|
+create procedure bug10136()
+begin
+declare done int default 3;
+repeat
+select * from t3;
+set done = done - 1;
+until done <= 0 end repeat;
+end|
+call bug10136()|
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+call bug10136()|
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+call bug10136()|
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+name val
+aaaaa 1
+bbbbb 2
+ccccc 3
+drop procedure bug10136|
+drop table t3|
+drop procedure if exists bug11529|
+create procedure bug11529()
+begin
+declare c cursor for select id, data from t1 where data in (10,13);
+open c;
+begin
+declare vid char(16);
+declare vdata int;
+declare exit handler for not found begin end;
+while true do
+fetch c into vid, vdata;
+end while;
+end;
+close c;
+end|
+insert into t1 values
+('Name1', 10),
+('Name2', 11),
+('Name3', 12),
+('Name4', 13),
+('Name5', 14)|
+call bug11529()|
+call bug11529()|
+delete from t1|
+drop procedure bug11529|
+drop procedure if exists bug6063|
+drop procedure if exists bug7088_1|
+drop procedure if exists bug7088_2|
+drop procedure if exists bug9565_sub|
+drop procedure if exists bug9565|
+create procedure bug9565_sub()
+begin
+select * from t1;
+end|
+create procedure bug9565()
+begin
+insert into t1 values ("one", 1);
+call bug9565_sub();
+end|
+call bug9565()|
+id data
+one 1
+delete from t1|
+drop procedure bug9565_sub|
+drop procedure bug9565|
+drop procedure if exists bug9538|
+create procedure bug9538()
+set @@sort_buffer_size = 1000000|
+set @x = @@sort_buffer_size|
+set @@sort_buffer_size = 2000000|
+select @@sort_buffer_size|
+@@sort_buffer_size
+2000000
+call bug9538()|
+select @@sort_buffer_size|
+@@sort_buffer_size
+1000000
+set @@sort_buffer_size = @x|
+drop procedure bug9538|
+drop procedure if exists bug8692|
+create table t3 (c1 varchar(5), c2 char(5), c3 enum('one','two'), c4 text, c5 blob, c6 char(5), c7 varchar(5))|
+insert into t3 values ('', '', '', '', '', '', NULL)|
+Warnings:
+Warning 1265 Data truncated for column 'c3' at row 1
+create procedure bug8692()
+begin
+declare v1 VARCHAR(10);
+declare v2 VARCHAR(10);
+declare v3 VARCHAR(10);
+declare v4 VARCHAR(10);
+declare v5 VARCHAR(10);
+declare v6 VARCHAR(10);
+declare v7 VARCHAR(10);
+declare c8692 cursor for select c1,c2,c3,c4,c5,c6,c7 from t3;
+open c8692;
+fetch c8692 into v1,v2,v3,v4,v5,v6,v7;
+select v1, v2, v3, v4, v5, v6, v7;
+end|
+call bug8692()|
+v1 v2 v3 v4 v5 v6 v7
+ NULL
+drop procedure bug8692|
+drop table t3|
+drop function if exists bug10055|
+create function bug10055(v char(255)) returns char(255) return lower(v)|
+select t.column_name, bug10055(t.column_name)
+from information_schema.columns as t
+where t.table_schema = 'test' and t.table_name = 't1'|
+column_name bug10055(t.column_name)
+id id
+data data
+drop function bug10055|
+drop procedure if exists bug12297|
+create procedure bug12297(lim int)
+begin
+set @x = 0;
+repeat
+insert into t1(id,data)
+values('aa', @x);
+set @x = @x + 1;
+until @x >= lim
+end repeat;
+end|
+call bug12297(10)|
+drop procedure bug12297|
+drop function if exists f_bug11247|
+drop procedure if exists p_bug11247|
+create function f_bug11247(param int)
+returns int
+return param + 1|
+create procedure p_bug11247(lim int)
+begin
+declare v int default 0;
+while v < lim do
+set v= f_bug11247(v);
+end while;
+end|
+call p_bug11247(10)|
+drop function f_bug11247|
+drop procedure p_bug11247|
+drop procedure if exists bug12168|
+drop table if exists t3, t4|
+create table t3 (a int)|
+insert into t3 values (1),(2),(3),(4)|
+create table t4 (a int)|
+create procedure bug12168(arg1 char(1))
+begin
+declare b, c integer;
+if arg1 = 'a' then
+begin
+declare c1 cursor for select a from t3 where a % 2;
+declare continue handler for not found set b = 1;
+set b = 0;
+open c1;
+c1_repeat: repeat
+fetch c1 into c;
+if (b = 1) then
+leave c1_repeat;
+end if;
+insert into t4 values (c);
+until b = 1
+end repeat;
+end;
+end if;
+if arg1 = 'b' then
+begin
+declare c2 cursor for select a from t3 where not a % 2;
+declare continue handler for not found set b = 1;
+set b = 0;
+open c2;
+c2_repeat: repeat
+fetch c2 into c;
+if (b = 1) then
+leave c2_repeat;
+end if;
+insert into t4 values (c);
+until b = 1
+end repeat;
+end;
+end if;
+end|
+call bug12168('a')|
+select * from t4|
+a
+1
+3
+truncate t4|
+call bug12168('b')|
+select * from t4|
+a
+2
+4
+truncate t4|
+call bug12168('a')|
+select * from t4|
+a
+1
+3
+truncate t4|
+call bug12168('b')|
+select * from t4|
+a
+2
+4
+truncate t4|
+drop table t3, t4|
+drop procedure if exists bug12168|
+drop table if exists t3|
+drop procedure if exists bug11333|
+create table t3 (c1 char(128))|
+insert into t3 values
+('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')|
+create procedure bug11333(i int)
+begin
+declare tmp varchar(128);
+set @x = 0;
+repeat
+select c1 into tmp from t3
+where c1 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
+set @x = @x + 1;
+until @x >= i
+end repeat;
+end|
+call bug11333(10)|
+drop procedure bug11333|
+drop table t3|
+drop function if exists bug9048|
+create function bug9048(f1 char binary) returns char binary
+begin
+set f1= concat( 'hello', f1 );
+return f1;
+end|
+drop function bug9048|
+drop procedure if exists bug12849_1|
+create procedure bug12849_1(inout x char) select x into x|
+set @var='a'|
+call bug12849_1(@var)|
+select @var|
+@var
+a
+drop procedure bug12849_1|
+drop procedure if exists bug12849_2|
+create procedure bug12849_2(inout foo varchar(15))
+begin
+select concat(foo, foo) INTO foo;
+end|
+set @var='abcd'|
+call bug12849_2(@var)|
+select @var|
+@var
+abcdabcd
+drop procedure bug12849_2|
+drop procedure if exists bug131333|
+drop function if exists bug131333|
+create procedure bug131333()
+begin
+begin
+declare a int;
+select a;
+set a = 1;
+select a;
+end;
+begin
+declare b int;
+select b;
+end;
+end|
+create function bug131333()
+returns int
+begin
+begin
+declare a int;
+set a = 1;
+end;
+begin
+declare b int;
+return b;
+end;
+end|
+call bug131333()|
+a
+NULL
+a
+1
+b
+NULL
+select bug131333()|
+bug131333()
+NULL
+drop procedure bug131333|
+drop function bug131333|
+drop function if exists bug12379|
+drop procedure if exists bug12379_1|
+drop procedure if exists bug12379_2|
+drop procedure if exists bug12379_3|
+drop table if exists t3|
+create table t3 (c1 char(1) primary key not null)|
+create function bug12379()
+returns integer
+begin
+insert into t3 values('X');
+insert into t3 values('X');
+return 0;
+end|
+create procedure bug12379_1()
+begin
+declare exit handler for sqlexception select 42;
+select bug12379();
+END|
+create procedure bug12379_2()
+begin
+declare exit handler for sqlexception begin end;
+select bug12379();
+end|
+create procedure bug12379_3()
+begin
+select bug12379();
+end|
+select bug12379()|
+ERROR 23000: Duplicate entry 'X' for key 1
+select 1|
+1
+1
+call bug12379_1()|
+bug12379()
+42
+42
+Warnings:
+Error 1062 Duplicate entry 'X' for key 1
+Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
+select 2|
+2
+2
+call bug12379_2()|
+bug12379()
+Warnings:
+Error 1062 Duplicate entry 'X' for key 1
+Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
+select 3|
+3
+3
+call bug12379_3()|
+ERROR 23000: Duplicate entry 'X' for key 1
+select 4|
+4
+4
+drop function bug12379|
+drop procedure bug12379_1|
+drop procedure bug12379_2|
+drop procedure bug12379_3|
+drop table t3|
+drop procedure if exists bug13124|
+create procedure bug13124()
+begin
+declare y integer;
+set @x=y;
+end|
+call bug13124()|
+drop procedure bug13124|
+drop procedure if exists bug12979_1|
+create procedure bug12979_1(inout d decimal(5)) set d = d / 2|
+set @bug12979_user_var = NULL|
+call bug12979_1(@bug12979_user_var)|
+drop procedure bug12979_1|
+drop procedure if exists bug12979_2|
+create procedure bug12979_2()
+begin
+declare internal_var decimal(5);
+set internal_var= internal_var / 2;
+select internal_var;
+end|
+call bug12979_2()|
+internal_var
+NULL
+drop procedure bug12979_2|
+drop table t1,t2;
diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result
new file mode 100644
index 00000000000..6077087ab87
--- /dev/null
+++ b/mysql-test/r/sp_trans.result
@@ -0,0 +1,176 @@
+drop table if exists t1, t2;
+drop procedure if exists bug8850|
+create table t1 (a int) engine=innodb|
+create procedure bug8850()
+begin
+truncate table t1; insert t1 values (1); rollback;
+end|
+set autocommit=0|
+insert t1 values (2)|
+call bug8850()|
+commit|
+select * from t1|
+a
+call bug8850()|
+set autocommit=1|
+select * from t1|
+a
+drop table t1|
+drop procedure bug8850|
+drop function if exists bug10015_1|
+drop function if exists bug10015_2|
+drop function if exists bug10015_3|
+drop function if exists bug10015_4|
+drop function if exists bug10015_5|
+drop function if exists bug10015_6|
+drop function if exists bug10015_7|
+drop procedure if exists bug10015_8|
+create table t1 (id int) engine=innodb|
+create table t2 (id int primary key, j int) engine=innodb|
+insert into t1 values (1),(2),(3)|
+create function bug10015_1() returns int return (select count(*) from t1)|
+select *, bug10015_1() from t1|
+id bug10015_1()
+1 3
+2 3
+3 3
+drop function bug10015_1|
+create function bug10015_2() returns int
+begin
+declare i, s int;
+set i:= (select min(id) from t1);
+set s:= (select max(id) from t1);
+return (s - i);
+end|
+select *, bug10015_2() from t1|
+id bug10015_2()
+1 2
+2 2
+3 2
+drop function bug10015_2|
+create function bug10015_3() returns int
+return (select max(a.id - b.id) from t1 as a, t1 as b where a.id >= b.id)|
+select *, bug10015_3() from t1|
+id bug10015_3()
+1 2
+2 2
+3 2
+drop function bug10015_3|
+create function bug10015_4(i int) returns int
+begin
+declare m int;
+set m:= (select max(id) from t2);
+insert into t2 values (i, m);
+return m;
+end|
+select *, bug10015_4(id) from t1|
+id bug10015_4(id)
+1 NULL
+2 1
+3 2
+select * from t2|
+id j
+1 NULL
+2 1
+3 2
+drop function bug10015_4|
+create function bug10015_5(i int) returns int
+begin
+if (i = 5) then
+insert into t2 values (1, 0);
+end if;
+return i;
+end|
+insert into t1 values (bug10015_5(4)), (bug10015_5(5))|
+ERROR 23000: Duplicate entry '1' for key 1
+select * from t1|
+id
+1
+2
+3
+drop function bug10015_5|
+create function bug10015_6(i int) returns int
+begin
+declare continue handler for sqlexception set @error_in_func:= 1;
+if (i = 5) then
+insert into t2 values (4, 0), (1, 0);
+end if;
+return i;
+end|
+set @error_in_func:= 0|
+insert into t1 values (bug10015_6(5)), (bug10015_6(6))|
+select @error_in_func|
+@error_in_func
+1
+select * from t1|
+id
+1
+2
+3
+5
+6
+select * from t2|
+id j
+1 NULL
+2 1
+3 2
+4 0
+drop function bug10015_6|
+create function bug10015_7() returns int
+begin
+alter table t1 add k int;
+return 1;
+end|
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+create function bug10015_7() returns int
+begin
+start transaction;
+return 1;
+end|
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+create function bug10015_7() returns int
+begin
+drop table t1;
+return 1;
+end|
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+create function bug10015_7() returns int
+begin
+drop temporary table t1;
+return 1;
+end|
+drop function bug10015_7|
+create function bug10015_7() returns int
+begin
+commit;
+return 1;
+end|
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+create function bug10015_7() returns int
+begin
+call bug10015_8();
+return 1;
+end|
+create procedure bug10015_8() alter table t1 add k int|
+select *, bug10015_7() from t1|
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+drop procedure bug10015_8|
+create procedure bug10015_8() start transaction|
+select *, bug10015_7() from t1|
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+drop procedure bug10015_8|
+create procedure bug10015_8() drop temporary table if exists t1_temp|
+select *, bug10015_7() from t1|
+id bug10015_7()
+1 1
+2 1
+3 1
+5 1
+6 1
+drop procedure bug10015_8|
+create procedure bug10015_8() commit|
+select *, bug10015_7() from t1|
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+drop procedure bug10015_8|
+drop function bug10015_7|
+drop table t1, t2|
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 4e1693e15ec..6ceb1cda888 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -18,7 +18,7 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY (`a`),
UNIQUE KEY `email` USING BTREE (`email`)
-) ENGINE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
+) ENGINE=MEMORY DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="ansi_quotes";
show variables like 'sql_mode';
Variable_name Value
@@ -31,7 +31,7 @@ t1 CREATE TABLE "t1" (
"email" varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY ("a"),
UNIQUE KEY "email" USING BTREE ("email")
-) ENGINE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
+) ENGINE=MEMORY DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="no_table_options";
show variables like 'sql_mode';
Variable_name Value
@@ -57,11 +57,11 @@ t1 CREATE TABLE `t1` (
`email` varchar(60) character set latin2 NOT NULL default '',
PRIMARY KEY (`a`),
UNIQUE KEY `email` (`email`)
-) ENGINE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
+) ENGINE=MEMORY DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode';
Variable_name Value
-sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40
+sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40,HIGH_NOT_PRECEDENCE
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -74,7 +74,7 @@ t1 CREATE TABLE `t1` (
set sql_mode="postgresql,oracle,mssql,db2,maxdb";
select @@sql_mode;
@@sql_mode
-PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS
+PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER
show create table t1;
Table Create Table
t1 CREATE TABLE "t1" (
@@ -120,7 +120,7 @@ create table t1 ( min_num dec(6,6) default .000001);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `min_num` decimal(7,6) default '0.000001'
+ `min_num` decimal(6,6) default '0.000001'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1 ;
set session sql_mode = 'IGNORE_SPACE';
@@ -128,15 +128,333 @@ create table t1 ( min_num dec(6,6) default 0.000001);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `min_num` decimal(7,6) default '0.000001'
+ `min_num` decimal(6,6) default '0.000001'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1 ;
create table t1 ( min_num dec(6,6) default .000001);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `min_num` decimal(7,6) default '0.000001'
+ `min_num` decimal(6,6) default '0.000001'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1 ;
set @@SQL_MODE=NULL;
ERROR 42000: Variable 'sql_mode' can't be set to the value of 'NULL'
+SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE='';
+show local variables like 'SQL_MODE';
+Variable_name Value
+sql_mode
+CREATE TABLE t1 (p int not null auto_increment, a varchar(20), primary key(p));
+INSERT t1 (a) VALUES
+('\\'),
+('\n'),
+('\b'),
+('\r'),
+('\t'),
+('\x'),
+('\a'),
+('\aa'),
+('\\a'),
+('\\aa'),
+('_'),
+('\_'),
+('\\_'),
+('\\\_'),
+('\\\\_'),
+('%'),
+('\%'),
+('\\%'),
+('\\\%'),
+('\\\\%')
+;
+SELECT p, hex(a) FROM t1;
+p hex(a)
+1 5C
+2 0A
+3 08
+4 0D
+5 09
+6 78
+7 61
+8 6161
+9 5C61
+10 5C6161
+11 5F
+12 5C5F
+13 5C5F
+14 5C5C5F
+15 5C5C5F
+16 25
+17 5C25
+18 5C25
+19 5C5C25
+20 5C5C25
+delete from t1 where a in ('\n','\r','\t', '\b');
+select
+masks.p,
+masks.a as mask,
+examples.a as example
+from
+t1 as masks
+left join t1 as examples on examples.a LIKE masks.a
+order by masks.p, example;
+p mask example
+1 \ \
+6 x x
+7 a a
+8 aa aa
+9 \a a
+10 \aa aa
+11 _ %
+11 _ a
+11 _ x
+11 _ \
+11 _ _
+12 \_ _
+13 \_ _
+14 \\_ \%
+14 \\_ \%
+14 \\_ \a
+14 \\_ \_
+14 \\_ \_
+15 \\_ \%
+15 \\_ \%
+15 \\_ \a
+15 \\_ \_
+15 \\_ \_
+16 % %
+16 % a
+16 % aa
+16 % x
+16 % \
+16 % \%
+16 % \%
+16 % \a
+16 % \aa
+16 % \\%
+16 % \\%
+16 % \\_
+16 % \\_
+16 % \_
+16 % \_
+16 % _
+17 \% %
+18 \% %
+19 \\% \
+19 \\% \%
+19 \\% \%
+19 \\% \a
+19 \\% \aa
+19 \\% \\%
+19 \\% \\%
+19 \\% \\_
+19 \\% \\_
+19 \\% \_
+19 \\% \_
+20 \\% \
+20 \\% \%
+20 \\% \%
+20 \\% \a
+20 \\% \aa
+20 \\% \\%
+20 \\% \\%
+20 \\% \\_
+20 \\% \\_
+20 \\% \_
+20 \\% \_
+DROP TABLE t1;
+SET @@SQL_MODE='NO_BACKSLASH_ESCAPES';
+show local variables like 'SQL_MODE';
+Variable_name Value
+sql_mode NO_BACKSLASH_ESCAPES
+CREATE TABLE t1 (p int not null auto_increment, a varchar(20), primary key(p));
+INSERT t1 (a) VALUES
+('\\'),
+('\n'),
+('\b'),
+('\r'),
+('\t'),
+('\x'),
+('\a'),
+('\aa'),
+('\\a'),
+('\\aa'),
+('_'),
+('\_'),
+('\\_'),
+('\\\_'),
+('\\\\_'),
+('%'),
+('\%'),
+('\\%'),
+('\\\%'),
+('\\\\%')
+;
+SELECT p, hex(a) FROM t1;
+p hex(a)
+1 5C5C
+2 5C6E
+3 5C62
+4 5C72
+5 5C74
+6 5C78
+7 5C61
+8 5C6161
+9 5C5C61
+10 5C5C6161
+11 5F
+12 5C5F
+13 5C5C5F
+14 5C5C5C5F
+15 5C5C5C5C5F
+16 25
+17 5C25
+18 5C5C25
+19 5C5C5C25
+20 5C5C5C5C25
+delete from t1 where a in ('\n','\r','\t', '\b');
+select
+masks.p,
+masks.a as mask,
+examples.a as example
+from
+t1 as masks
+left join t1 as examples on examples.a LIKE masks.a
+order by masks.p, example;
+p mask example
+1 \\ \\
+6 \x \x
+7 \a \a
+8 \aa \aa
+9 \\a \\a
+10 \\aa \\aa
+11 _ %
+11 _ _
+12 \_ \%
+12 \_ \a
+12 \_ \x
+12 \_ \\
+12 \_ \_
+13 \\_ \\%
+13 \\_ \\a
+13 \\_ \\_
+14 \\\_ \\\%
+14 \\\_ \\\_
+15 \\\\_ \\\\%
+15 \\\\_ \\\\_
+16 % %
+16 % \%
+16 % \a
+16 % \aa
+16 % \x
+16 % \\
+16 % \\%
+16 % \\a
+16 % \\aa
+16 % \\\%
+16 % \\\\%
+16 % \\\\_
+16 % \\\_
+16 % \\_
+16 % \_
+16 % _
+17 \% \%
+17 \% \a
+17 \% \aa
+17 \% \x
+17 \% \\
+17 \% \\%
+17 \% \\a
+17 \% \\aa
+17 \% \\\%
+17 \% \\\\%
+17 \% \\\\_
+17 \% \\\_
+17 \% \\_
+17 \% \_
+18 \\% \\
+18 \\% \\%
+18 \\% \\a
+18 \\% \\aa
+18 \\% \\\%
+18 \\% \\\\%
+18 \\% \\\\_
+18 \\% \\\_
+18 \\% \\_
+19 \\\% \\\%
+19 \\\% \\\\%
+19 \\\% \\\\_
+19 \\\% \\\_
+20 \\\\% \\\\%
+20 \\\\% \\\\_
+DROP TABLE t1;
+SET @@SQL_MODE='NO_BACKSLASH_ESCAPES';
+SELECT 'a\\b', 'a\\\"b', 'a''\\b', 'a''\\\"b';
+a\\b a\\\"b a'\\b a'\\\"b
+a\\b a\\\"b a'\\b a'\\\"b
+SELECT "a\\b", "a\\\'b", "a""\\b", "a""\\\'b";
+a\\b a\\\'b a"\\b a"\\\'b
+a\\b a\\\'b a"\\b a"\\\'b
+SET @@SQL_MODE='';
+SELECT 'a\\b', 'a\\\"b', 'a''\\b', 'a''\\\"b';
+a\b a\"b a'\b a'\"b
+a\b a\"b a'\b a'\"b
+SELECT "a\\b", "a\\\'b", "a""\\b", "a""\\\'b";
+a\b a\'b a"\b a"\'b
+a\b a\'b a"\b a"\'b
+set session sql_mode = 'NO_ENGINE_SUBSTITUTION';
+create table t1 (a int) engine=isam;
+ERROR HY000: The 'ISAM' feature is disabled; you need MySQL built with 'ISAM' to have it working
+show create table t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
+set session sql_mode = '';
+create table t1 (a int) engine=isam;
+Warnings:
+Warning 1266 Using storage engine MyISAM for table 't1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+SET @@SQL_MODE='';
+create function `foo` () returns int return 5;
+show create function `foo`;
+Function sql_mode Create Function
+foo CREATE FUNCTION `foo`() RETURNS int(11)
+return 5
+SET @@SQL_MODE='ANSI_QUOTES';
+show create function `foo`;
+Function sql_mode Create Function
+foo CREATE FUNCTION `foo`() RETURNS int(11)
+return 5
+drop function `foo`;
+create function `foo` () returns int return 5;
+show create function `foo`;
+Function sql_mode Create Function
+foo ANSI_QUOTES CREATE FUNCTION "foo"() RETURNS int(11)
+return 5
+SET @@SQL_MODE='';
+show create function `foo`;
+Function sql_mode Create Function
+foo ANSI_QUOTES CREATE FUNCTION "foo"() RETURNS int(11)
+return 5
+drop function `foo`;
+SET @@SQL_MODE='';
+create table t1 (a int);
+create table t2 (a int);
+create view v1 as select a from t1;
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1`
+SET @@SQL_MODE='ANSI_QUOTES';
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER="root"@"localhost" SQL SECURITY DEFINER VIEW "v1" AS select "t1"."a" AS "a" from "t1"
+create view v2 as select a from t2 where a in (select a from v1);
+drop view v2, v1;
+drop table t1, t2;
+SET @@SQL_MODE=@OLD_SQL_MODE;
diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result
new file mode 100644
index 00000000000..2b1a47ed337
--- /dev/null
+++ b/mysql-test/r/strict.result
@@ -0,0 +1,1290 @@
+set @org_mode=@@sql_mode;
+set @@sql_mode='ansi,traditional';
+select @@sql_mode;
+@@sql_mode
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (col1 date);
+INSERT INTO t1 VALUES('2004-01-01'),('0000-10-31'),('2004-02-29');
+INSERT INTO t1 VALUES('2004-0-31');
+ERROR 22007: Incorrect date value: '2004-0-31' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-01-02'),('2004-0-31');
+ERROR 22007: Incorrect date value: '2004-0-31' for column 'col1' at row 2
+INSERT INTO t1 VALUES('2004-10-0');
+ERROR 22007: Incorrect date value: '2004-10-0' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-09-31');
+ERROR 22007: Incorrect date value: '2004-09-31' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-10-32');
+ERROR 22007: Incorrect date value: '2004-10-32' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2003-02-29');
+ERROR 22007: Incorrect date value: '2003-02-29' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-13-15');
+ERROR 22007: Incorrect date value: '2004-13-15' for column 'col1' at row 1
+INSERT INTO t1 VALUES('0000-00-00');
+ERROR 22007: Incorrect date value: '0000-00-00' for column 'col1' at row 1
+INSERT INTO t1 VALUES ('59');
+ERROR 22007: Incorrect date value: '59' for column 'col1' at row 1
+set @@sql_mode='STRICT_ALL_TABLES';
+INSERT INTO t1 VALUES('2004-01-03'),('2004-0-31');
+set @@sql_mode='STRICT_ALL_TABLES,NO_ZERO_IN_DATE';
+INSERT INTO t1 VALUES('2004-0-30');
+ERROR 22007: Incorrect date value: '2004-0-30' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-01-04'),('2004-0-31'),('2004-01-05');
+ERROR 22007: Incorrect date value: '2004-0-31' for column 'col1' at row 2
+INSERT INTO t1 VALUES('0000-00-00');
+INSERT IGNORE INTO t1 VALUES('2004-0-29');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+set @@sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';
+INSERT INTO t1 VALUES('0000-00-00');
+ERROR 22007: Incorrect date value: '0000-00-00' for column 'col1' at row 1
+INSERT IGNORE INTO t1 VALUES('0000-00-00');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT INTO t1 VALUES ('2004-0-30');
+INSERT INTO t1 VALUES ('2004-2-30');
+ERROR 22007: Incorrect date value: '2004-2-30' for column 'col1' at row 1
+set @@sql_mode='STRICT_ALL_TABLES,ALLOW_INVALID_DATES';
+INSERT INTO t1 VALUES ('2004-2-30');
+set @@sql_mode='ansi,traditional';
+INSERT IGNORE INTO t1 VALUES('2004-02-29'),('2004-13-15'),('0000-00-00');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 2
+Warning 1265 Data truncated for column 'col1' at row 3
+select * from t1;
+col1
+2004-01-01
+0000-10-31
+2004-02-29
+2004-01-02
+2004-01-03
+2004-00-31
+2004-01-04
+0000-00-00
+0000-00-00
+0000-00-00
+2004-00-30
+2004-02-30
+2004-02-29
+0000-00-00
+0000-00-00
+drop table t1;
+set @@sql_mode='strict_trans_tables';
+CREATE TABLE t1 (col1 date) engine=myisam;
+INSERT INTO t1 VALUES('2004-13-31'),('2004-1-1');
+ERROR 22007: Incorrect date value: '2004-13-31' for column 'col1' at row 1
+INSERT INTO t1 VALUES ('2004-1-2'), ('2004-13-31'),('2004-1-3');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 2
+INSERT IGNORE INTO t1 VALUES('2004-13-31'),('2004-1-4');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT INTO t1 VALUES ('2003-02-29');
+ERROR 22007: Incorrect date value: '2003-02-29' for column 'col1' at row 1
+INSERT ignore INTO t1 VALUES('2003-02-30');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+set @@sql_mode='STRICT_ALL_TABLES,ALLOW_INVALID_DATES';
+INSERT ignore INTO t1 VALUES('2003-02-31');
+select * from t1;
+col1
+2004-01-02
+0000-00-00
+2004-01-03
+0000-00-00
+2004-01-04
+0000-00-00
+2003-02-31
+drop table t1;
+set @@sql_mode='strict_trans_tables';
+CREATE TABLE t1 (col1 date) engine=innodb;
+INSERT INTO t1 VALUES('2004-13-31'),('2004-1-1');
+ERROR 22007: Incorrect date value: '2004-13-31' for column 'col1' at row 1
+INSERT INTO t1 VALUES ('2004-1-2'), ('2004-13-31'),('2004-1-3');
+ERROR 22007: Incorrect date value: '2004-13-31' for column 'col1' at row 2
+INSERT IGNORE INTO t1 VALUES('2004-13-31'),('2004-1-4');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT INTO t1 VALUES ('2003-02-29');
+ERROR 22007: Incorrect date value: '2003-02-29' for column 'col1' at row 1
+INSERT ignore INTO t1 VALUES('2003-02-30');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+set @@sql_mode='STRICT_ALL_TABLES,ALLOW_INVALID_DATES';
+INSERT ignore INTO t1 VALUES('2003-02-31');
+select * from t1;
+col1
+0000-00-00
+2004-01-04
+0000-00-00
+2003-02-31
+drop table t1;
+set @@sql_mode='ansi,traditional';
+CREATE TABLE t1 (col1 datetime);
+INSERT INTO t1 VALUES('2004-10-31 15:30:00'),('0000-10-31 15:30:00'),('2004-02-29 15:30:00');
+INSERT INTO t1 VALUES('2004-0-31 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-0-31 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-10-0 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-10-0 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-09-31 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-09-31 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-10-32 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-10-32 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2003-02-29 15:30:00');
+ERROR 22007: Incorrect datetime value: '2003-02-29 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-13-15 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-13-15 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('0000-00-00 15:30:00');
+ERROR 22007: Incorrect datetime value: '0000-00-00 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES ('59');
+ERROR 22007: Incorrect datetime value: '59' for column 'col1' at row 1
+select * from t1;
+col1
+2004-10-31 15:30:00
+0000-10-31 15:30:00
+2004-02-29 15:30:00
+drop table t1;
+CREATE TABLE t1 (col1 timestamp);
+INSERT INTO t1 VALUES('2004-10-31 15:30:00'),('2004-02-29 15:30:00');
+INSERT INTO t1 VALUES('0000-10-31 15:30:00');
+ERROR 22007: Incorrect datetime value: '0000-10-31 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-0-31 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-0-31 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-10-0 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-10-0 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-09-31 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-09-31 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-10-32 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-10-32 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2003-02-29 15:30:00');
+ERROR 22007: Incorrect datetime value: '2003-02-29 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-13-15 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-13-15 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-02-29 25:30:00');
+ERROR 22007: Incorrect datetime value: '2004-02-29 25:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-02-29 15:65:00');
+ERROR 22007: Incorrect datetime value: '2004-02-29 15:65:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-02-29 15:31:61');
+ERROR 22007: Incorrect datetime value: '2004-02-29 15:31:61' for column 'col1' at row 1
+INSERT INTO t1 VALUES('0000-00-00 15:30:00');
+ERROR 22007: Incorrect datetime value: '0000-00-00 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('0000-00-00 00:00:00');
+ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'col1' at row 1
+INSERT IGNORE INTO t1 VALUES('0000-00-00 00:00:00');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT INTO t1 VALUES ('59');
+ERROR 22007: Incorrect datetime value: '59' for column 'col1' at row 1
+set @@sql_mode='STRICT_ALL_TABLES,ALLOW_INVALID_DATES';
+INSERT INTO t1 VALUES('2004-0-31 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-0-31 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-10-0 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-10-0 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-10-32 15:30:00');
+ERROR 22007: Incorrect datetime value: '2004-10-32 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 VALUES('2004-02-30 15:30:04');
+ERROR 22007: Incorrect datetime value: '2004-02-30 15:30:04' for column 'col1' at row 1
+INSERT INTO t1 VALUES('0000-00-00 00:00:00');
+set @@sql_mode='STRICT_ALL_TABLES,NO_ZERO_IN_DATE';
+INSERT INTO t1 VALUES('0000-00-00 00:00:00');
+set @@sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';
+INSERT INTO t1 VALUES('0000-00-00 00:00:00');
+ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'col1' at row 1
+set @@sql_mode='ansi,traditional';
+SELECT * FROM t1;
+col1
+2004-10-31 15:30:00
+2004-02-29 15:30:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+DROP TABLE t1;
+CREATE TABLE t1 (col1 date, col2 datetime, col3 timestamp);
+INSERT INTO t1 (col1) VALUES (STR_TO_DATE('15.10.2004','%d.%m.%Y'));
+INSERT INTO t1 (col2) VALUES (STR_TO_DATE('15.10.2004 10.15','%d.%m.%Y %H.%i'));
+INSERT INTO t1 (col3) VALUES (STR_TO_DATE('15.10.2004 10.15','%d.%m.%Y %H.%i'));
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('31.10.0000 15.30','%d.%m.%Y %H.%i'));
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('31.0.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect date value: '2004-00-31 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('0.10.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect date value: '2004-10-00 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('31.9.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect date value: '2004-09-31 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR HY000: Incorrect datetime value: '32.10.2004 15.30' for function str_to_time
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('29.02.2003 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect date value: '2003-02-29 15:30:00' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('15.13.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR HY000: Incorrect datetime value: '15.13.2004 15.30' for function str_to_time
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('00.00.0000','%d.%m.%Y'));
+ERROR 22007: Incorrect date value: '0000-00-00' for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('31.10.0000 15.30','%d.%m.%Y %H.%i'));
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('31.0.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '2004-00-31 15:30:00' for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('0.10.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('31.9.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '2004-09-31 15:30:00' for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR HY000: Incorrect datetime value: '32.10.2004 15.30' for function str_to_time
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('29.02.2003 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '2003-02-29 15:30:00' for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('15.13.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR HY000: Incorrect datetime value: '15.13.2004 15.30' for function str_to_time
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('00.00.0000','%d.%m.%Y'));
+ERROR 22007: Incorrect datetime value: '0000-00-00' for column 'col2' at row 1
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('31.10.0000 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '0000-10-31 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('31.0.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '2004-00-31 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('0.10.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('31.9.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '2004-09-31 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR HY000: Incorrect datetime value: '32.10.2004 15.30' for function str_to_time
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('29.02.2003 15.30','%d.%m.%Y %H.%i'));
+ERROR 22007: Incorrect datetime value: '2003-02-29 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('15.13.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR HY000: Incorrect datetime value: '15.13.2004 15.30' for function str_to_time
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('00.00.0000','%d.%m.%Y'));
+ERROR 22007: Incorrect datetime value: '0000-00-00' for column 'col3' at row 1
+drop table t1;
+CREATE TABLE t1 (col1 date, col2 datetime, col3 timestamp);
+INSERT INTO t1 (col1) VALUES (CAST('2004-10-15' AS DATE));
+INSERT INTO t1 (col2) VALUES (CAST('2004-10-15 10:15' AS DATETIME));
+INSERT INTO t1 (col3) VALUES (CAST('2004-10-15 10:15' AS DATETIME));
+INSERT INTO t1 (col1) VALUES(CAST('0000-10-31' AS DATE));
+INSERT INTO t1 (col1) VALUES(CAST('2004-10-0' AS DATE));
+ERROR 22007: Incorrect date value: '2004-10-00' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(CAST('2004-0-10' AS DATE));
+ERROR 22007: Incorrect date value: '2004-00-10' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(CAST('0000-00-00' AS DATE));
+ERROR 22007: Truncated incorrect datetime value: '0000-00-00'
+INSERT INTO t1 (col2) VALUES(CAST('0000-10-31 15:30' AS DATETIME));
+INSERT INTO t1 (col2) VALUES(CAST('2004-10-0 15:30' AS DATETIME));
+ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(CAST('2004-0-10 15:30' AS DATETIME));
+ERROR 22007: Incorrect datetime value: '2004-00-10 15:30:00' for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(CAST('0000-00-00' AS DATETIME));
+ERROR 22007: Truncated incorrect datetime value: '0000-00-00'
+INSERT INTO t1 (col3) VALUES(CAST('0000-10-31 15:30' AS DATETIME));
+ERROR 22007: Incorrect datetime value: '0000-10-31 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(CAST('2004-10-0 15:30' AS DATETIME));
+ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(CAST('2004-0-10 15:30' AS DATETIME));
+ERROR 22007: Incorrect datetime value: '2004-00-10 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(CAST('0000-00-00' AS DATETIME));
+ERROR 22007: Truncated incorrect datetime value: '0000-00-00'
+drop table t1;
+CREATE TABLE t1 (col1 date, col2 datetime, col3 timestamp);
+INSERT INTO t1 (col1) VALUES (CONVERT('2004-10-15',DATE));
+INSERT INTO t1 (col2) VALUES (CONVERT('2004-10-15 10:15',DATETIME));
+INSERT INTO t1 (col3) VALUES (CONVERT('2004-10-15 10:15',DATETIME));
+INSERT INTO t1 (col1) VALUES(CONVERT('0000-10-31' , DATE));
+INSERT INTO t1 (col1) VALUES(CONVERT('2004-10-0' , DATE));
+ERROR 22007: Incorrect date value: '2004-10-00' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(CONVERT('2004-0-10' , DATE));
+ERROR 22007: Incorrect date value: '2004-00-10' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(CONVERT('0000-00-00',DATE));
+ERROR 22007: Truncated incorrect datetime value: '0000-00-00'
+INSERT INTO t1 (col2) VALUES(CONVERT('0000-10-31 15:30',DATETIME));
+INSERT INTO t1 (col2) VALUES(CONVERT('2004-10-0 15:30',DATETIME));
+ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(CONVERT('2004-0-10 15:30',DATETIME));
+ERROR 22007: Incorrect datetime value: '2004-00-10 15:30:00' for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(CONVERT('0000-00-00',DATETIME));
+ERROR 22007: Truncated incorrect datetime value: '0000-00-00'
+INSERT INTO t1 (col3) VALUES(CONVERT('0000-10-31 15:30',DATETIME));
+ERROR 22007: Incorrect datetime value: '0000-10-31 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(CONVERT('2004-10-0 15:30',DATETIME));
+ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(CONVERT('2004-0-10 15:30',DATETIME));
+ERROR 22007: Incorrect datetime value: '2004-00-10 15:30:00' for column 'col3' at row 1
+INSERT INTO t1 (col3) VALUES(CONVERT('0000-00-00',DATETIME));
+ERROR 22007: Truncated incorrect datetime value: '0000-00-00'
+drop table t1;
+CREATE TABLE t1(col1 TINYINT, col2 TINYINT UNSIGNED);
+INSERT INTO t1 VALUES(-128,0),(0,0),(127,255),('-128','0'),('0','0'),('127','255'),(-128.0,0.0),(0.0,0.0),(127.0,255.0);
+SELECT MOD(col1,0) FROM t1 WHERE col1 > 0 LIMIT 2;
+MOD(col1,0)
+NULL
+NULL
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+INSERT INTO t1 (col1) VALUES(-129);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(128);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(256);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES('-129');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES('128');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES('-1');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES('256');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES(128.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(256.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+SELECT MOD(col1,0) FROM t1 WHERE col1 > 0 LIMIT 1;
+MOD(col1,0)
+NULL
+Warnings:
+Error 1365 Division by 0
+UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+UPDATE t1 SET col2=col2 + 50 WHERE col2 > 0;
+ERROR 22003: Out of range value adjusted for column 'col2' at row 3
+UPDATE t1 SET col1=col1 / 0 WHERE col1 > 0;
+ERROR 22012: Division by 0
+set @@sql_mode='ERROR_FOR_DIVISION_BY_ZERO';
+INSERT INTO t1 values (1/0,1/0);
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+set @@sql_mode='ansi,traditional';
+SELECT MOD(col1,0) FROM t1 WHERE col1 > 0 LIMIT 2;
+MOD(col1,0)
+NULL
+NULL
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+INSERT INTO t1 (col1) VALUES ('');
+ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('a59b');
+ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('1a');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 values (1/0,1/0);
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+set @@sql_mode='ansi';
+INSERT INTO t1 values (1/0,1/0);
+set @@sql_mode='ansi,traditional';
+INSERT IGNORE INTO t1 VALUES('-129','-1'),('128','256');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 VALUES(-129.0,-1.0),(128.0,256.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+SELECT * FROM t1;
+col1 col2
+-128 0
+0 NULL
+127 255
+-128 0
+0 NULL
+127 255
+-128 0
+0 NULL
+127 255
+NULL NULL
+2 NULL
+NULL NULL
+NULL NULL
+-128 0
+127 255
+-128 0
+127 255
+DROP TABLE t1;
+CREATE TABLE t1(col1 SMALLINT, col2 SMALLINT UNSIGNED);
+INSERT INTO t1 VALUES(-32768,0),(0,0),(32767,65535),('-32768','0'),('32767','65535'),(-32768.0,0.0),(32767.0,65535.0);
+INSERT INTO t1 (col1) VALUES(-32769);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(32768);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(65536);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES('-32769');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES('32768');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES('-1');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES('65536');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES(-32769.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(32768.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(65536.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+UPDATE t1 SET col2 = col2 + 50 WHERE col2 > 0;
+ERROR 22003: Out of range value adjusted for column 'col2' at row 3
+UPDATE t1 SET col1 = col1 / 0 WHERE col1 > 0;
+ERROR 22012: Division by 0
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+ERROR 22012: Division by 0
+INSERT INTO t1 (col1) VALUES ('');
+ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('a59b');
+ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('1a');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 values (1/0,1/0);
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+INSERT IGNORE INTO t1 VALUES(-32769,-1),(32768,65536);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 VALUES('-32769','-1'),('32768','65536');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 VALUES(-32769,-1.0),(32768.0,65536.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+SELECT * FROM t1;
+col1 col2
+-32768 0
+0 NULL
+32767 65535
+-32768 0
+32767 65535
+-32768 0
+32767 65535
+2 NULL
+NULL NULL
+-32768 0
+32767 65535
+-32768 0
+32767 65535
+-32768 0
+32767 65535
+DROP TABLE t1;
+CREATE TABLE t1 (col1 MEDIUMINT, col2 MEDIUMINT UNSIGNED);
+INSERT INTO t1 VALUES(-8388608,0),(0,0),(8388607,16777215),('-8388608','0'),('8388607','16777215'),(-8388608.0,0.0),(8388607.0,16777215.0);
+INSERT INTO t1 (col1) VALUES(-8388609);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(8388608);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(16777216);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES('-8388609');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES('8388608');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES('-1');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES('16777216');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES(-8388609.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(8388608.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(16777216.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+UPDATE t1 SET col2 = col2 + 50 WHERE col2 > 0;
+ERROR 22003: Out of range value adjusted for column 'col2' at row 3
+UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
+ERROR 22012: Division by 0
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+ERROR 22012: Division by 0
+INSERT INTO t1 (col1) VALUES ('');
+ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('a59b');
+ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('1a');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 values (1/0,1/0);
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+INSERT IGNORE INTO t1 VALUES(-8388609,-1),(8388608,16777216);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 VALUES('-8388609','-1'),('8388608','16777216');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 VALUES(-8388609.0,-1.0),(8388608.0,16777216.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+SELECT * FROM t1;
+col1 col2
+-8388608 0
+0 NULL
+8388607 16777215
+-8388608 0
+8388607 16777215
+-8388608 0
+8388607 16777215
+2 NULL
+NULL NULL
+-8388608 0
+8388607 16777215
+-8388608 0
+8388607 16777215
+-8388608 0
+8388607 16777215
+DROP TABLE t1;
+CREATE TABLE t1 (col1 INT, col2 INT UNSIGNED);
+INSERT INTO t1 VALUES(-2147483648,0),(0,0),(2147483647,4294967295),('-2147483648','0'),('2147483647','4294967295'),(-2147483648.0,0.0),(2147483647.0,4294967295.0);
+INSERT INTO t1 (col1) VALUES(-2147483649);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(2147643648);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(4294967296);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES('-2147483649');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES('2147643648');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES('-1');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES('4294967296');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES(-2147483649.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(2147643648.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(4294967296.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+UPDATE t1 SET col2 =col2 + 50 WHERE col2 > 0;
+ERROR 22003: Out of range value adjusted for column 'col2' at row 3
+UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
+ERROR 22012: Division by 0
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+ERROR 22012: Division by 0
+INSERT INTO t1 (col1) VALUES ('');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('a59b');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('1a');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 values (1/0,1/0);
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+INSERT IGNORE INTO t1 values (-2147483649, -1),(2147643648,4294967296);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 values ('-2147483649', '-1'),('2147643648','4294967296');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 values (-2147483649.0, -1.0),(2147643648.0,4294967296.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+SELECT * FROM t1;
+col1 col2
+-2147483648 0
+0 NULL
+2147483647 4294967295
+-2147483648 0
+2147483647 4294967295
+-2147483648 0
+2147483647 4294967295
+2 NULL
+NULL NULL
+-2147483648 0
+2147483647 4294967295
+-2147483648 0
+2147483647 4294967295
+-2147483648 0
+2147483647 4294967295
+DROP TABLE t1;
+CREATE TABLE t1 (col1 BIGINT, col2 BIGINT UNSIGNED);
+INSERT INTO t1 VALUES(-9223372036854775808,0),(0,0),(9223372036854775807,18446744073709551615);
+INSERT INTO t1 VALUES('-9223372036854775808','0'),('9223372036854775807','18446744073709551615');
+INSERT INTO t1 VALUES(-9223372036854774000.0,0.0),(9223372036854775700.0,1844674407370954000.0);
+INSERT INTO t1 (col1) VALUES(-9223372036854775809);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(9223372036854775808);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(18446744073709551616);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES('-9223372036854775809');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES('9223372036854775808');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES('-1');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES('18446744073709551616');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES(-9223372036854785809.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES(9223372036854785808.0);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES(-1.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES(18446744073709551616.0);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
+ERROR 22012: Division by 0
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+ERROR 22012: Division by 0
+INSERT INTO t1 (col1) VALUES ('');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('a59b');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('1a');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 values (1/0,1/0);
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+INSERT IGNORE INTO t1 VALUES(-9223372036854775809,-1),(9223372036854775808,18446744073709551616);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 VALUES('-9223372036854775809','-1'),('9223372036854775808','18446744073709551616');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+INSERT IGNORE INTO t1 VALUES(-9223372036854785809.0,-1.0),(9223372036854785808.0,18446744073709551616.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+SELECT * FROM t1;
+col1 col2
+-9223372036854775808 0
+0 NULL
+9223372036854775807 18446744073709551615
+-9223372036854775808 0
+9223372036854775807 18446744073709551615
+-9223372036854774000 0
+9223372036854775700 1844674407370954000
+2 NULL
+NULL NULL
+-9223372036854775808 0
+9223372036854775807 18446744073709551615
+-9223372036854775808 0
+9223372036854775807 18446744073709551615
+-9223372036854775808 0
+9223372036854775807 18446744073709551615
+DROP TABLE t1;
+CREATE TABLE t1 (col1 NUMERIC(4,2));
+INSERT INTO t1 VALUES (10.55),(10.5555),(0),(-10.55),(-10.5555),(11),(1e+01);
+Warnings:
+Note 1265 Data truncated for column 'col1' at row 2
+Note 1265 Data truncated for column 'col1' at row 5
+INSERT INTO t1 VALUES ('10.55'),('10.5555'),('-10.55'),('-10.5555'),('11'),('1e+01');
+Warnings:
+Note 1265 Data truncated for column 'col1' at row 2
+Note 1265 Data truncated for column 'col1' at row 4
+INSERT INTO t1 VALUES (101.55);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES (101);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES (-101.55);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES (1010.55);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES (1010);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES ('101.55');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES ('101');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES ('-101.55');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES ('-1010.55');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES ('-100E+1');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 VALUES ('-100E');
+ERROR HY000: Incorrect decimal value: '-100E' for column 'col1' at row 1
+UPDATE t1 SET col1 =col1 * 50000 WHERE col1 =11;
+ERROR 22003: Out of range value adjusted for column 'col1' at row 6
+UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
+ERROR 22012: Division by 0
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+ERROR 22012: Division by 0
+INSERT INTO t1 (col1) VALUES ('');
+ERROR HY000: Incorrect decimal value: '' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('a59b');
+ERROR HY000: Incorrect decimal value: 'a59b' for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('1a');
+ERROR HY000: Incorrect decimal value: '1a' for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+Warnings:
+Note 1265 Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 values (1/0);
+Warnings:
+Error 1365 Division by 0
+INSERT IGNORE INTO t1 VALUES(1000),(-1000);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+INSERT IGNORE INTO t1 VALUES('1000'),('-1000');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+INSERT IGNORE INTO t1 VALUES(1000.0),(-1000.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+UPDATE IGNORE t1 SET col1=1/NULL where col1=0;
+SELECT * FROM t1;
+col1
+10.55
+10.56
+NULL
+-10.55
+-10.56
+11.00
+10.00
+10.55
+10.56
+-10.55
+-10.56
+11.00
+10.00
+2.00
+NULL
+99.99
+-99.99
+99.99
+-99.99
+99.99
+-99.99
+DROP TABLE t1;
+CREATE TABLE t1 (col1 FLOAT, col2 FLOAT UNSIGNED);
+INSERT INTO t1 VALUES (-1.1E-37,0),(+3.4E+38,+3.4E+38);
+INSERT INTO t1 VALUES ('-1.1E-37',0),('+3.4E+38','+3.4E+38');
+INSERT INTO t1 (col1) VALUES (3E-46);
+INSERT INTO t1 (col1) VALUES (+3.4E+39);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES (-1.1E-3);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES ('+3.4E+39');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES ('-1.1E-3');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+UPDATE t1 SET col1 =col1 * 5000 WHERE col1 > 0;
+ERROR 22003: Out of range value adjusted for column 'col1' at row 2
+UPDATE t1 SET col2 =col2 / 0 WHERE col2 > 0;
+ERROR 22012: Division by 0
+UPDATE t1 SET col2= MOD(col2,0) WHERE col2 > 0;
+ERROR 22012: Division by 0
+INSERT INTO t1 (col1) VALUES ('');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('a59b');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('1a');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES (1/0);
+Warnings:
+Error 1365 Division by 0
+INSERT IGNORE INTO t1 VALUES (+3.4E+39,-3.4E+39);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+INSERT IGNORE INTO t1 VALUES ('+3.4E+39','-3.4E+39');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+SELECT * FROM t1;
+col1 col2
+-1.1e-37 0
+3.4e+38 3.4e+38
+-1.1e-37 0
+3.4e+38 3.4e+38
+0 NULL
+2 NULL
+NULL NULL
+3.40282e+38 0
+3.40282e+38 0
+DROP TABLE t1;
+CREATE TABLE t1 (col1 DOUBLE PRECISION, col2 DOUBLE PRECISION UNSIGNED);
+INSERT INTO t1 VALUES (-2.2E-307,0),(2E-307,0),(+1.7E+308,+1.7E+308);
+INSERT INTO t1 VALUES ('-2.2E-307',0),('-2E-307',0),('+1.7E+308','+1.7E+308');
+INSERT INTO t1 (col1) VALUES (-2.2E-330);
+INSERT INTO t1 (col1) VALUES (+1.7E+309);
+Got one of the listed errors
+INSERT INTO t1 (col2) VALUES (-1.1E-3);
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+INSERT INTO t1 (col1) VALUES ('+1.8E+309');
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES ('-1.2E-3');
+ERROR 22003: Out of range value adjusted for column 'col2' at row 1
+UPDATE t1 SET col1 =col1 * 5000 WHERE col1 > 0;
+ERROR 22003: Out of range value adjusted for column 'col1' at row 3
+UPDATE t1 SET col2 =col2 / 0 WHERE col2 > 0;
+ERROR 22012: Division by 0
+UPDATE t1 SET col2= MOD(col2,0) WHERE col2 > 0;
+ERROR 22012: Division by 0
+INSERT INTO t1 (col1) VALUES ('');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('a59b');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('1a');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+INSERT IGNORE INTO t1 (col1) values (1/0);
+Warnings:
+Error 1365 Division by 0
+INSERT IGNORE INTO t1 VALUES (+1.9E+309,-1.9E+309);
+ERROR 22007: Illegal double '1.9E+309' value found during parsing
+INSERT IGNORE INTO t1 VALUES ('+2.0E+309','-2.0E+309');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+SELECT * FROM t1;
+col1 col2
+0 0
+1e-303 0
+1.7e+308 1.7e+308
+0 0
+-2e-307 0
+1.7e+308 1.7e+308
+0 NULL
+2 NULL
+NULL NULL
+1.79769313486232e+308 0
+DROP TABLE t1;
+CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
+INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
+INSERT INTO t1 (col1) VALUES ('hellobob');
+ERROR 22001: Data too long for column 'col1' at row 1
+INSERT INTO t1 (col2) VALUES ('hellobob');
+ERROR 22001: Data too long for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES ('hello ');
+Warnings:
+Note 1265 Data truncated for column 'col2' at row 1
+UPDATE t1 SET col1 ='hellobob' WHERE col1 ='he';
+ERROR 22001: Data too long for column 'col1' at row 2
+UPDATE t1 SET col2 ='hellobob' WHERE col2 ='he';
+ERROR 22001: Data too long for column 'col2' at row 2
+INSERT IGNORE INTO t1 VALUES ('hellobob', 'hellobob');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+Warning 1265 Data truncated for column 'col2' at row 1
+UPDATE IGNORE t1 SET col2 ='hellotrudy' WHERE col2 ='he';
+Warnings:
+Warning 1265 Data truncated for column 'col2' at row 2
+SELECT * FROM t1;
+col1 col2
+hello hello
+he hellot
+hello hello
+NULL hello
+hello hellob
+DROP TABLE t1;
+CREATE TABLE t1 (col1 enum('red','blue','green'));
+INSERT INTO t1 VALUES ('red'),('blue'),('green');
+INSERT INTO t1 (col1) VALUES ('yellow');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT INTO t1 (col1) VALUES ('redd');
+ERROR 01000: Data truncated for column 'col1' at row 1
+INSERT INTO t1 VALUES ('');
+ERROR 01000: Data truncated for column 'col1' at row 1
+UPDATE t1 SET col1 ='yellow' WHERE col1 ='green';
+ERROR 01000: Data truncated for column 'col1' at row 3
+INSERT IGNORE INTO t1 VALUES ('yellow');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+UPDATE IGNORE t1 SET col1 ='yellow' WHERE col1 ='blue';
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 2
+SELECT * FROM t1;
+col1
+red
+
+green
+
+DROP TABLE t1;
+CREATE TABLE t1 (col1 INT NOT NULL, col2 CHAR(5) NOT NULL, col3 DATE NOT NULL);
+INSERT INTO t1 VALUES (100, 'hello', '2004-08-20');
+INSERT INTO t1 (col1,col2,col3) VALUES (101, 'hell2', '2004-08-21');
+INSERT INTO t1 (col1,col2,col3) VALUES (NULL, '', '2004-01-01');
+ERROR 23000: Column 'col1' cannot be null
+INSERT INTO t1 (col1,col2,col3) VALUES (102, NULL, '2004-01-01');
+ERROR 23000: Column 'col2' cannot be null
+INSERT INTO t1 VALUES (103,'',NULL);
+ERROR 23000: Column 'col3' cannot be null
+UPDATE t1 SET col1=NULL WHERE col1 =100;
+ERROR 22004: Column set to default value; NULL supplied to NOT NULL column 'col1' at row 1
+UPDATE t1 SET col2 =NULL WHERE col2 ='hello';
+ERROR 22004: Column set to default value; NULL supplied to NOT NULL column 'col2' at row 1
+UPDATE t1 SET col2 =NULL where col3 IS NOT NULL;
+ERROR 22004: Column set to default value; NULL supplied to NOT NULL column 'col2' at row 1
+INSERT IGNORE INTO t1 values (NULL,NULL,NULL);
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'col1' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'col2' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'col3' at row 1
+SELECT * FROM t1;
+col1 col2 col3
+100 hello 2004-08-20
+101 hell2 2004-08-21
+0 0000-00-00
+DROP TABLE t1;
+CREATE TABLE t1 (col1 INT NOT NULL default 99, col2 CHAR(6) NOT NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "col1" int(11) NOT NULL default '99',
+ "col2" char(6) NOT NULL
+)
+INSERT INTO t1 VALUES (1, 'hello');
+INSERT INTO t1 (col2) VALUES ('hello2');
+INSERT INTO t1 (col2) VALUES (NULL);
+ERROR 23000: Column 'col2' cannot be null
+INSERT INTO t1 (col1) VALUES (2);
+ERROR HY000: Field 'col2' doesn't have a default value
+INSERT INTO t1 VALUES(default(col1),default(col2));
+ERROR HY000: Field 'col2' doesn't have a default value
+INSERT INTO t1 (col1) SELECT 1;
+ERROR HY000: Field 'col2' doesn't have a default value
+INSERT INTO t1 SELECT 1,NULL;
+ERROR 22004: Column set to default value; NULL supplied to NOT NULL column 'col2' at row 1
+INSERT IGNORE INTO t1 values (NULL,NULL);
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'col1' at row 1
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'col2' at row 1
+INSERT IGNORE INTO t1 (col1) values (3);
+Warnings:
+Warning 1364 Field 'col2' doesn't have a default value
+INSERT IGNORE INTO t1 () values ();
+Warnings:
+Warning 1364 Field 'col2' doesn't have a default value
+SELECT * FROM t1;
+col1 col2
+1 hello
+99 hello2
+0
+3
+99
+DROP TABLE t1;
+set sql_mode='traditional';
+create table t1 (charcol char(255), varcharcol varchar(255),
+binarycol binary(255), varbinarycol varbinary(255), tinytextcol tinytext,
+tinyblobcol tinyblob);
+insert into t1 (charcol) values (repeat('x',256));
+ERROR 22001: Data too long for column 'charcol' at row 1
+insert into t1 (varcharcol) values (repeat('x',256));
+ERROR 22001: Data too long for column 'varcharcol' at row 1
+insert into t1 (binarycol) values (repeat('x',256));
+ERROR 22001: Data too long for column 'binarycol' at row 1
+insert into t1 (varbinarycol) values (repeat('x',256));
+ERROR 22001: Data too long for column 'varbinarycol' at row 1
+insert into t1 (tinytextcol) values (repeat('x',256));
+ERROR 22001: Data too long for column 'tinytextcol' at row 1
+insert into t1 (tinyblobcol) values (repeat('x',256));
+ERROR 22001: Data too long for column 'tinyblobcol' at row 1
+select * from t1;
+charcol varcharcol binarycol varbinarycol tinytextcol tinyblobcol
+drop table t1;
+set sql_mode='traditional';
+create table t1 (col1 datetime);
+insert into t1 values(STR_TO_DATE('31.10.2004 15.30 abc','%d.%m.%Y %H.%i'));
+ERROR 22007: Truncated incorrect datetime value: '31.10.2004 15.30 abc'
+insert into t1 values(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+ERROR HY000: Incorrect datetime value: '32.10.2004 15.30' for function str_to_time
+insert into t1 values(STR_TO_DATE('2004.12.12 22:22:33 AM','%Y.%m.%d %r'));
+ERROR HY000: Incorrect time value: '22:22:33 AM' for function str_to_time
+insert into t1 values(STR_TO_DATE('2004.12.12 abc','%Y.%m.%d %T'));
+ERROR HY000: Incorrect time value: 'abc' for function str_to_time
+set sql_mode='';
+insert into t1 values(STR_TO_DATE('31.10.2004 15.30 abc','%d.%m.%Y %H.%i'));
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '31.10.2004 15.30 abc'
+insert into t1 values(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+Warnings:
+Error 1411 Incorrect datetime value: '32.10.2004 15.30' for function str_to_time
+insert into t1 values(STR_TO_DATE('2004.12.12 22:22:33 AM','%Y.%m.%d %r'));
+Warnings:
+Error 1411 Incorrect time value: '22:22:33 AM' for function str_to_time
+insert into t1 values(STR_TO_DATE('2004.12.12 abc','%Y.%m.%d %T'));
+Warnings:
+Error 1411 Incorrect time value: 'abc' for function str_to_time
+insert into t1 values(STR_TO_DATE('31.10.2004 15.30','%d.%m.%Y %H.%i'));
+insert into t1 values(STR_TO_DATE('2004.12.12 11:22:33 AM','%Y.%m.%d %r'));
+insert into t1 values(STR_TO_DATE('2004.12.12 10:22:59','%Y.%m.%d %T'));
+select * from t1;
+col1
+2004-10-31 15:30:00
+NULL
+NULL
+NULL
+2004-10-31 15:30:00
+2004-12-12 11:22:33
+2004-12-12 10:22:59
+set sql_mode='traditional';
+select count(*) from t1 where STR_TO_DATE('2004.12.12 10:22:61','%Y.%m.%d %T') IS NULL;
+count(*)
+7
+Warnings:
+Error 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_time
+Error 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_time
+Error 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_time
+drop table t1;
+create table t1 (col1 char(3), col2 integer);
+insert into t1 (col1) values (cast(1000 as char(3)));
+ERROR 22007: Truncated incorrect CHAR(3) value: '1000'
+insert into t1 (col1) values (cast(1000E+0 as char(3)));
+ERROR 22007: Truncated incorrect CHAR(3) value: '1000'
+insert into t1 (col1) values (cast(1000.0 as char(3)));
+ERROR 22007: Truncated incorrect CHAR(3) value: '1000.0'
+insert into t1 (col2) values (cast('abc' as signed integer));
+ERROR 22007: Truncated incorrect INTEGER value: 'abc'
+insert into t1 (col2) values (10E+0 + 'a');
+ERROR 22007: Truncated incorrect DOUBLE value: 'a'
+insert into t1 (col2) values (cast('10a' as unsigned integer));
+ERROR 22007: Truncated incorrect INTEGER value: '10a'
+insert into t1 (col2) values (cast('10' as unsigned integer));
+insert into t1 (col2) values (cast('10' as signed integer));
+insert into t1 (col2) values (10E+0 + '0 ');
+select * from t1;
+col1 col2
+NULL 10
+NULL 10
+NULL 10
+drop table t1;
+create table t1 (col1 date, col2 datetime, col3 timestamp);
+insert into t1 values (0,0,0);
+ERROR 22007: Incorrect date value: '0' for column 'col1' at row 1
+insert into t1 values (0.0,0.0,0.0);
+ERROR 22007: Incorrect date value: '0' for column 'col1' at row 1
+insert into t1 (col1) values (convert('0000-00-00',date));
+ERROR 22007: Truncated incorrect datetime value: '0000-00-00'
+insert into t1 (col1) values (cast('0000-00-00' as date));
+ERROR 22007: Truncated incorrect datetime value: '0000-00-00'
+set sql_mode='no_zero_date';
+insert into t1 values (0,0,0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1265 Data truncated for column 'col3' at row 1
+insert into t1 values (0.0,0.0,0.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col2' at row 1
+Warning 1265 Data truncated for column 'col3' at row 1
+drop table t1;
+set sql_mode='traditional';
+create table t1 (col1 date);
+insert ignore into t1 values ('0000-00-00');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+insert into t1 select * from t1;
+ERROR 22007: Incorrect date value: '0000-00-00' for column 'col1' at row 1
+insert ignore into t1 values ('0000-00-00');
+Warnings:
+Warning 1265 Data truncated for column 'col1' at row 1
+insert ignore into t1 (col1) values (cast('0000-00-00' as date));
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '0000-00-00'
+insert into t1 select * from t1;
+ERROR 22007: Incorrect date value: '0000-00-00' for column 'col1' at row 1
+alter table t1 modify col1 datetime;
+ERROR 22007: Incorrect datetime value: '0000-00-00' for column 'col1' at row 1
+alter ignore table t1 modify col1 datetime;
+Warnings:
+Warning 1264 Out of range value adjusted for column 'col1' at row 1
+Warning 1264 Out of range value adjusted for column 'col1' at row 2
+insert into t1 select * from t1;
+ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'col1' at row 1
+select * from t1;
+col1
+0000-00-00 00:00:00
+0000-00-00 00:00:00
+NULL
+drop table t1;
+create table t1 (col1 tinyint);
+drop procedure if exists t1;
+Warnings:
+Note 1305 PROCEDURE t1 does not exist
+create procedure t1 () begin declare exit handler for sqlexception
+select'a'; insert into t1 values (200); end;|
+call t1();
+a
+a
+select * from t1;
+col1
+drop procedure t1;
+drop table t1;
+set sql_mode=@org_mode;
+SET @@sql_mode = 'traditional';
+CREATE TABLE t1 (i int not null);
+INSERT INTO t1 VALUES ();
+ERROR HY000: Field 'i' doesn't have a default value
+INSERT INTO t1 VALUES (DEFAULT);
+ERROR HY000: Field 'i' doesn't have a default value
+INSERT INTO t1 VALUES (DEFAULT(i));
+ERROR HY000: Field 'i' doesn't have a default value
+ALTER TABLE t1 ADD j int;
+INSERT INTO t1 SET j = 1;
+ERROR HY000: Field 'i' doesn't have a default value
+INSERT INTO t1 SET j = 1, i = DEFAULT;
+ERROR HY000: Field 'i' doesn't have a default value
+INSERT INTO t1 SET j = 1, i = DEFAULT(i);
+ERROR HY000: Field 'i' doesn't have a default value
+INSERT INTO t1 VALUES (DEFAULT,1);
+ERROR HY000: Field 'i' doesn't have a default value
+DROP TABLE t1;
+SET @@sql_mode = '';
+CREATE TABLE t1 (i int not null);
+INSERT INTO t1 VALUES ();
+Warnings:
+Warning 1364 Field 'i' doesn't have a default value
+INSERT INTO t1 VALUES (DEFAULT);
+Warnings:
+Warning 1364 Field 'i' doesn't have a default value
+INSERT INTO t1 VALUES (DEFAULT(i));
+ERROR HY000: Field 'i' doesn't have a default value
+ALTER TABLE t1 ADD j int;
+INSERT INTO t1 SET j = 1;
+Warnings:
+Warning 1364 Field 'i' doesn't have a default value
+INSERT INTO t1 SET j = 1, i = DEFAULT;
+Warnings:
+Warning 1364 Field 'i' doesn't have a default value
+INSERT INTO t1 SET j = 1, i = DEFAULT(i);
+ERROR HY000: Field 'i' doesn't have a default value
+INSERT INTO t1 VALUES (DEFAULT,1);
+Warnings:
+Warning 1364 Field 'i' doesn't have a default value
+DROP TABLE t1;
+set @@sql_mode='traditional';
+create table t1(a varchar(65537));
+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead
+create table t1(a varbinary(65537));
+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead
+set @@sql_mode='traditional';
+create table t1(a int, b date not null);
+alter table t1 modify a bigint unsigned not null;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) unsigned NOT NULL,
+ `b` date NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @@sql_mode='traditional';
+create table t1 (d date);
+insert into t1 values ('2000-10-00');
+ERROR 22007: Incorrect date value: '2000-10-00' for column 'd' at row 1
+insert into t1 values (1000);
+ERROR 22007: Incorrect date value: '1000' for column 'd' at row 1
+insert into t1 values ('2000-10-01');
+update t1 set d = 1100;
+ERROR 22007: Incorrect date value: '1100' for column 'd' at row 1
+select * from t1;
+d
+2000-10-01
+drop table t1;
+set @@sql_mode='traditional';
+create table t1(a int, b timestamp);
+alter table t1 add primary key(a);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1(a int, b timestamp default 20050102030405);
+alter table t1 add primary key(a);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` timestamp NOT NULL default '2005-01-02 03:04:05',
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @@sql_mode='traditional';
+create table t1(a bit(2));
+insert into t1 values(b'101');
+ERROR 22001: Data too long for column 'a' at row 1
+select * from t1;
+a
+drop table t1;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 8652ed89a65..14806279362 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -50,7 +50,7 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
Note 1276 Field or reference 'a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 1 AS `1` from (select 1 AS `a`) b having ((select b.a AS `a`) = 1)
+Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having ((select `b`.`a` AS `a`) = 1)
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@@ -117,15 +117,17 @@ SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
(SELECT 1.5,2,'a') = ROW(1.5,2,'b')
0
-SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
-(SELECT 1.5,2,'a') = ROW('b',2,'b')
+SELECT (SELECT 1.5,2,'a') = ROW('1.5b',2,'b');
+(SELECT 1.5,2,'a') = ROW('1.5b',2,'b')
0
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '1.5b'
SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
(SELECT 'b',2,'a') = ROW(1.5,2,'a')
0
-SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
-(SELECT 1.5,2,'a') = ROW(1.5,'c','a')
-0
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,'2','a');
+(SELECT 1.5,2,'a') = ROW(1.5,'2','a')
+1
SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
(SELECT 1.5,'c','a') = ROW(1.5,2,'a')
0
@@ -186,7 +188,7 @@ id select_type table type possible_keys key key_len ref rows Extra
4 SUBQUERY t2 ALL NULL NULL NULL NULL 2
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.b = (select test.t3.a AS `a` from test.t3 order by test.t3.a desc limit 1))) union (select test.t4.a AS `a`,test.t4.b AS `b` from test.t4 where (test.t4.b = (select (max(test.t2.a) * 4) AS `max(t2.a)*4` from test.t2)) order by a)
+Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`b` = (select `test`.`t3`.`a` AS `a` from `test`.`t3` order by 1 desc limit 1))) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where (`test`.`t4`.`b` = (select (max(`test`.`t2`.`a`) * 4) AS `max(t2.a)*4` from `test`.`t2`)) order by `a`)
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1
@@ -202,7 +204,7 @@ id select_type table type possible_keys key key_len ref rows Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 2 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
Warnings:
-Note 1003 select (select test.t3.a AS `a` from test.t3 where (test.t3.a < 8) order by test.t3.a desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,tt.a AS `a` from (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.a > 1)) tt
+Note 1003 select (select `test`.`t3`.`a` AS `a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` > 1)) `tt`
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
2
@@ -223,7 +225,7 @@ id select_type table type possible_keys key key_len ref rows Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where
Warnings:
Note 1276 Field or reference 't4.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select test.t4.b AS `b`,(select avg((test.t2.a + (select min(test.t3.a) AS `min(t3.a)` from test.t3 where (test.t3.a >= test.t4.a)))) AS `avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a))` from test.t2) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from test.t4
+Note 1003 select `test`.`t4`.`b` AS `b`,(select avg((`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) AS `min(t3.a)` from `test`.`t3` where (`test`.`t3`.`a` >= `test`.`t4`.`a`)))) AS `avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a))` from `test`.`t2`) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
@@ -269,7 +271,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3 where <nop>((test.t3.a >= (select min(test.t2.b) from test.t2)))
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>((`test`.`t3`.`a` >= (select min(`test`.`t2`.`b`) from `test`.`t2`)))
select * from t3 where a >= all (select b from t2);
a
7
@@ -313,7 +315,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 't2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 't2.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select (select test.t1.a AS `a` from test.t1 where (test.t1.a = test.t2.a) union select test.t5.a AS `a` from test.t5 where (test.t5.a = test.t2.a)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,test.t2.a AS `a` from test.t2
+Note 1003 select (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = `test`.`t2`.`a`) union select `test`.`t5`.`a` AS `a` from `test`.`t5` where (`test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
ERROR 21000: Subquery returns more than 1 row
create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -331,7 +333,7 @@ id select_type table type possible_keys key key_len ref rows Extra
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 1 AS `Not_used` 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 t1,t2,t3;
@@ -361,12 +363,12 @@ INSERT INTO t8 (pseudo,email) VALUES ('joce1','test1');
INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t8 const PRIMARY PRIMARY 35 const 1 Using index
-4 SUBQUERY t8 const PRIMARY PRIMARY 35 1 Using index
-2 SUBQUERY t8 const PRIMARY PRIMARY 35 const 1
-3 SUBQUERY t8 const PRIMARY PRIMARY 35 1 Using index
+1 PRIMARY t8 ref PRIMARY PRIMARY 37 const 1 Using where; Using index
+4 SUBQUERY t8 ref PRIMARY PRIMARY 37 1 Using where; Using index
+2 SUBQUERY t8 ref PRIMARY PRIMARY 37 const 1 Using where
+3 SUBQUERY t8 ref PRIMARY PRIMARY 37 1 Using where; Using index
Warnings:
-Note 1003 select test.t8.pseudo AS `pseudo`,(select test.t8.email AS `email` from test.t8 where (test.t8.pseudo = (select test.t8.pseudo AS `pseudo` from test.t8 where (test.t8.pseudo = _latin1'joce')))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from test.t8 where (test.t8.pseudo = (select test.t8.pseudo AS `pseudo` from test.t8 where (test.t8.pseudo = _latin1'joce')))
+Note 1003 select `test`.`t8`.`pseudo` AS `pseudo`,(select `test`.`t8`.`email` AS `email` from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
@@ -390,15 +392,15 @@ INSERT INTO t1 (topic,date,pseudo) VALUES
('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
EXPLAIN EXTENDED SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL PRIMARY 41 NULL 2 Using where; Using index
+1 SIMPLE t1 index NULL PRIMARY 43 NULL 2 Using where; Using index
Warnings:
-Note 1003 select distinct test.t1.date AS `date` from test.t1 where (test.t1.date = 20020803)
+Note 1003 select distinct `test`.`t1`.`date` AS `date` from `test`.`t1` where (`test`.`t1`.`date` = 20020803)
EXPLAIN EXTENDED SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
-2 SUBQUERY t1 index NULL PRIMARY 41 NULL 2 Using where; Using index
+2 SUBQUERY t1 index NULL PRIMARY 43 NULL 2 Using where; Using index
Warnings:
-Note 1003 select (select distinct test.t1.date AS `date` from test.t1 where (test.t1.date = 20020803)) AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
+Note 1003 select (select distinct `test`.`t1`.`date` AS `date` from `test`.`t1` where (`test`.`t1`.`date` = 20020803)) AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date
2002-08-03
@@ -419,7 +421,7 @@ 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 <union2,3> ALL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 1 AS `1` from test.t1
+Note 1003 select 1 AS `1` from `test`.`t1`
drop table t1;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@@ -539,13 +541,13 @@ EXPLAIN EXTENDED SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select max(test.t1.numreponse) AS `MAX(numreponse)` from test.t1 where (test.t1.numeropost = _latin1'1')
+Note 1003 select max(`test`.`t1`.`numreponse`) AS `MAX(numreponse)` from `test`.`t1` where (`test`.`t1`.`numeropost` = _latin1'1')
EXPLAIN EXTENDED SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select test.t1.numreponse AS `numreponse` from test.t1 where ((test.t1.numeropost = _latin1'1') and (test.t1.numreponse = 3))
+Note 1003 select `test`.`t1`.`numreponse` AS `numreponse` from `test`.`t1` where ((`test`.`t1`.`numreponse` = (select max(`test`.`t1`.`numreponse`) AS `MAX(numreponse)` from `test`.`t1` where (`test`.`t1`.`numeropost` = _latin1'1'))) and (`test`.`t1`.`numeropost` = _latin1'1'))
drop table t1;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
@@ -652,6 +654,14 @@ x
3
3
INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
+select * from t1;
+x
+1
+2
+3
+3
+11
+11
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
ERROR 42S22: Unknown column 'x' in 'field list'
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
@@ -713,7 +723,7 @@ 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 optimization
-Note 1003 select test.t2.id AS `id` from test.t2 where (test.t2.id = 1)
+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
1
@@ -726,7 +736,7 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
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))
+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
1 PRIMARY t2 index NULL id 5 NULL 2 Using where; Using index
@@ -734,7 +744,7 @@ id select_type table type possible_keys key key_len ref rows Extra
3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select test.t2.id AS `id` from test.t2 where <in_optimizer>(test.t2.id,<exists>(select 1 AS `Not_used` having (<cache>(test.t2.id) = <null_helper>(1)) union select 1 AS `Not_used` having (<cache>(test.t2.id) = <null_helper>(3))))
+Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 AS `Not_used` having (<cache>(`test`.`t2`.`id`) = <null_helper>(1)) union select 1 AS `Not_used` having (<cache>(`test`.`t2`.`id`) = <null_helper>(3))))
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -860,7 +870,7 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
Note 1276 Field or reference 'a' of SELECT #2 was resolved in SELECT #1
Note 1249 Select 2 was reduced during optimization
-Note 1003 select (test.t1.a + 1) AS `(select a+1)` from test.t1
+Note 1003 select (`test`.`t1`.`a` + 1) AS `(select a+1)` from `test`.`t1`
select (select a+1) from t1;
(select a+1)
2.5
@@ -882,7 +892,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 Using index
2 DEPENDENT SUBQUERY t2 index_subquery a a 5 func 2 Using index
Warnings:
-Note 1003 select test.t1.a AS `a`,<in_optimizer>(test.t1.a,<exists>(<index_lookup>(<cache>(test.t1.a) in t2 on a chicking NULL))) AS `t1.a in (select t2.a from t2)` from test.t1
+Note 1003 select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -897,7 +907,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where
Warnings:
-Note 1003 select test.t1.a AS `a`,<in_optimizer>(test.t1.a,<exists>(select 1 AS `Not_used` from test.t2 join test.t3 where ((test.t3.a = test.t2.a) and ((<cache>(test.t1.a) = test.t2.a) or isnull(test.t2.a))) having <is_not_null_test>(test.t2.a))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from test.t1
+Note 1003 select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
create table t1 (a float);
select 10.5 IN (SELECT * from t1 LIMIT 1);
@@ -913,7 +923,7 @@ select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a') (select c from t1 where a=t2.a)
1 1 a
2 0 b
-NULL NULL NULL
+NULL 0 NULL
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b'),(select c from t1 where a=t2.a) from t2;
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b') (select c from t1 where a=t2.a)
1 0 a
@@ -923,7 +933,7 @@ select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c') (select c from t1 where a=t2.a)
1 0 a
2 0 b
-NULL NULL NULL
+NULL 0 NULL
drop table t1,t2;
create table t1 (a int, b real, c varchar(10));
insert into t1 values (1, 1, 'a'), (2,2,'b'), (NULL, 2, 'b');
@@ -1009,19 +1019,19 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select sql_no_cache (select sql_no_cache rand() AS `RAND()` from test.t1) AS `(SELECT RAND() FROM t1)` from test.t1
+Note 1003 select sql_no_cache (select sql_no_cache rand() AS `RAND()` from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select sql_no_cache (select sql_no_cache ecrypt(_latin1'test') AS `ENCRYPT('test')` from test.t1) AS `(SELECT ENCRYPT('test') FROM t1)` from test.t1
+Note 1003 select sql_no_cache (select sql_no_cache encrypt(_latin1'test') AS `ENCRYPT('test')` from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select sql_no_cache (select sql_no_cache benchmark(1,1) AS `BENCHMARK(1,1)` from test.t1) AS `(SELECT BENCHMARK(1,1) FROM t1)` from test.t1
+Note 1003 select sql_no_cache (select sql_no_cache benchmark(1,1) AS `BENCHMARK(1,1)` from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
@@ -1077,24 +1087,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(20) NOT NULL default '0',
- `(SELECT 1)` bigint(20) NOT NULL default '0'
+ `a` bigint(1) NOT NULL default '0',
+ `(SELECT 1)` bigint(1) 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(20) NOT NULL default '0',
- `(SELECT a)` bigint(20) NOT NULL default '0'
+ `a` bigint(1) NOT NULL default '0',
+ `(SELECT a)` bigint(1) 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(20) NOT NULL default '0',
- `(SELECT a+0)` bigint(20) NOT NULL default '0'
+ `a` bigint(1) NOT NULL default '0',
+ `(SELECT a+0)` bigint(3) 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;
@@ -1116,7 +1126,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3
3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3
Warnings:
-Note 1003 select sql_no_cache test.t1.a AS `a`,(select sql_no_cache (select sql_no_cache rand() AS `rand()` from test.t1 limit 1) AS `(select rand() from t1 limit 1)` from test.t1 limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from test.t1
+Note 1003 select sql_no_cache `test`.`t1`.`a` AS `a`,(select sql_no_cache (select sql_no_cache rand() AS `rand()` from `test`.`t1` limit 1) AS `(select rand() from t1 limit 1)` from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
drop table t1;
select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
ERROR 42S02: Table 'test.t1' doesn't exist
@@ -1170,7 +1180,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 AS `Not_used` from test.t1 a)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 select <in_optimizer>(0,<exists>(select 1 AS `Not_used` from `test`.`t1` `a`)) AS `0 IN (SELECT 1 FROM t1 a)`
INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 0 IN (SELECT 1 FROM t1 a);
0 IN (SELECT 1 FROM t1 a)
@@ -1180,7 +1190,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 AS `Not_used` from test.t1 a)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 select <in_optimizer>(0,<exists>(select 1 AS `Not_used` from `test`.`t1` `a`)) AS `0 IN (SELECT 1 FROM t1 a)`
drop table t1;
CREATE TABLE `t1` (
`i` int(11) NOT NULL default '0',
@@ -1190,7 +1200,7 @@ INSERT INTO t1 VALUES (1);
UPDATE t1 SET i=i+(SELECT MAX(i) FROM (SELECT 1) t) WHERE i=(SELECT MAX(i));
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t);
-ERROR 42S02: Unknown table 't' in field list
+ERROR 42S22: Unknown column 't.i' in 'field list'
select * from t1;
i
1
@@ -1225,7 +1235,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ref salary salary 5 const 1 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select test.t1.id AS `id` from test.t1 where (test.t1.salary = (select max(test.t1.salary) AS `MAX(salary)` from test.t1))
+Note 1003 select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`salary` = (select max(`test`.`t1`.`salary`) AS `MAX(salary)` from `test`.`t1`))
drop table t1;
CREATE TABLE t1 (
ID int(10) unsigned NOT NULL auto_increment,
@@ -1287,7 +1297,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index
Warnings:
-Note 1003 select test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<primary_index_lookup>(<cache>(test.t2.a) in t1 on PRIMARY)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY)))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1297,7 +1307,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
Warnings:
-Note 1003 select test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<primary_index_lookup>(<cache>(test.t2.a) in t1 on PRIMARY where (test.t1.b <> 30))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY where (`test`.`t1`.`b` <> 30))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1308,7 +1318,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 func 1 Using where
2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 Using where; Using index
Warnings:
-Note 1003 select test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and (<cache>(test.t2.a) = test.t1.a))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`b`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a));
@@ -1326,7 +1336,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index
Warnings:
-Note 1003 select test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<index_lookup>(<cache>(test.t2.a) in t1 on a)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a)))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1336,7 +1346,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index; Using where
Warnings:
-Note 1003 select test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<index_lookup>(<cache>(test.t2.a) in t1 on a where (test.t1.b <> 30))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where (`test`.`t1`.`b` <> 30))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1344,10 +1354,10 @@ a
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
-2 DEPENDENT SUBQUERY t1 ref a a 5 func 1001 Using where; Using index
-2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using where; Using index
+2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using index
+2 DEPENDENT SUBQUERY t1 ref a a 10 func,test.t3.a 1167 Using where; Using index
Warnings:
-Note 1003 select test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and (<cache>(test.t2.a) = test.t1.a))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`a`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -1363,7 +1373,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index; Using where
Warnings:
-Note 1003 select test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<index_lookup>(<cache>(test.t2.a) in t1 on a where (test.t1.b <> 30))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where (`test`.`t1`.`b` <> 30))))
drop table t1, t2, t3;
create table t1 (a int, b int);
create table t2 (a int, b int);
@@ -1420,7 +1430,7 @@ explain extended (select * from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
Warnings:
-Note 1003 (select test.t1.s1 AS `s1` from test.t1)
+Note 1003 (select `test`.`t1`.`s1` AS `s1` from `test`.`t1`)
(select * from t1);
s1
tttt
@@ -1454,25 +1464,25 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 Using index
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings:
-Note 1003 select test.t1.s1 AS `s1`,not(<in_optimizer>(test.t1.s1,<exists>(<index_lookup>(<cache>(test.t1.s1) in t2 on s1 chicking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from test.t1
+Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 Using index
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings:
-Note 1003 select test.t1.s1 AS `s1`,<in_optimizer>(test.t1.s1,<exists>(<index_lookup>(<cache>(test.t1.s1) in t2 on s1 chicking NULL))) AS `s1 = ANY (SELECT s1 FROM t2)` from test.t1
+Note 1003 select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 Using index
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings:
-Note 1003 select test.t1.s1 AS `s1`,not(<in_optimizer>(test.t1.s1,<exists>(<index_lookup>(<cache>(test.t1.s1) in t2 on s1 chicking NULL)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from test.t1
+Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 Using index
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 1 Using index; Using where
Warnings:
-Note 1003 select test.t1.s1 AS `s1`,not(<in_optimizer>(test.t1.s1,<exists>(<index_lookup>(<cache>(test.t1.s1) in t2 on s1 chicking NULL where (test.t2.s1 < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from test.t1
+Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int);
create table t3 (a int);
@@ -1487,7 +1497,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3 where <not>((test.t3.a < (select max(test.t2.b) from test.t2)))
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>((`test`.`t3`.`a` < (select max(`test`.`t2`.`b`) from `test`.`t2`)))
select * from t3 where a >= some (select b from t2);
a
explain extended select * from t3 where a >= some (select b from t2);
@@ -1495,7 +1505,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3 where <nop>((test.t3.a >= (select min(test.t2.b) from test.t2)))
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>((`test`.`t3`.`a` >= (select min(`test`.`t2`.`b`) from `test`.`t2`)))
select * from t3 where a >= all (select b from t2 group by 1);
a
6
@@ -1506,7 +1516,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3 where <not>((test.t3.a < <max>(select test.t2.b AS `b` from test.t2 group by test.t2.b)))
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>((`test`.`t3`.`a` < <max>(select `test`.`t2`.`b` AS `b` from `test`.`t2` group by 1)))
select * from t3 where a >= some (select b from t2 group by 1);
a
explain extended select * from t3 where a >= some (select b from t2 group by 1);
@@ -1514,7 +1524,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3 where <nop>((test.t3.a >= <min>(select test.t2.b AS `b` from test.t2 group by test.t2.b)))
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>((`test`.`t3`.`a` >= <min>(select `test`.`t2`.`b` AS `b` from `test`.`t2` group by 1)))
select * from t3 where NULL >= any (select b from t2);
a
explain extended select * from t3 where NULL >= any (select b from t2);
@@ -1522,7 +1532,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3`
select * from t3 where NULL >= any (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= any (select b from t2 group by 1);
@@ -1530,7 +1540,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3`
select * from t3 where NULL >= some (select b from t2);
a
explain extended select * from t3 where NULL >= some (select b from t2);
@@ -1538,7 +1548,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3`
select * from t3 where NULL >= some (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= some (select b from t2 group by 1);
@@ -1546,7 +1556,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3`
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
a
@@ -1557,7 +1567,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort
Warnings:
-Note 1003 select test.t3.a AS `a` from test.t3 where <not>((test.t3.a <= <max>(select max(test.t2.b) AS `max(b)` from test.t2 group by test.t2.a)))
+Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>((`test`.`t3`.`a` <= <max>(select max(`test`.`t2`.`b`) AS `max(b)` from `test`.`t2` group by `test`.`t2`.`a`)))
drop table t2, t3;
CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) ENGINE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now());
@@ -1590,6 +1600,8 @@ insert into t1 values (2);
set sort_buffer_size = (select s1 from t1);
ERROR 21000: Subquery returns more than 1 row
do (select * from t1);
+Warnings:
+Error 1242 Subquery returns more than 1 row
drop table t1;
create table t1 (s1 char);
insert into t1 values ('e');
@@ -1606,7 +1618,7 @@ id select_type table type possible_keys key key_len ref rows Extra
3 UNION t1 system NULL NULL NULL NULL 1
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select test.t1.s1 AS `s1` from test.t1
+Note 1003 select `test`.`t1`.`s1` AS `s1` from `test`.`t1`
drop table t1;
CREATE TABLE t1 (number char(11) NOT NULL default '') ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('69294728265'),('18621828126'),('89356874041'),('95895001874');
@@ -1626,7 +1638,7 @@ ERROR 42S22: Unknown column 't1.s2' in 'where clause'
select * from t1 where (select count(*) from t2 group by t1.s2) = 1;
ERROR 42S22: Unknown column 't1.s2' in 'group statement'
select count(*) from t2 group by t1.s2;
-ERROR 42S02: Unknown table 't1' in group statement
+ERROR 42S22: Unknown column 't1.s2' in 'group statement'
drop table t1, t2;
CREATE TABLE t1(COLA FLOAT NOT NULL,COLB FLOAT NOT NULL,COLC VARCHAR(20) DEFAULT NULL,PRIMARY KEY (COLA, COLB));
CREATE TABLE t2(COLA FLOAT NOT NULL,COLB FLOAT NOT NULL,COLC CHAR(1) NOT NULL,PRIMARY KEY (COLA));
@@ -1725,14 +1737,14 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
Warnings:
-Note 1003 select test.t1.id AS `id`,test.t1.text AS `text` from test.t1 where not(<in_optimizer>(test.t1.id,<exists>(<primary_index_lookup>(<cache>(test.t1.id) in t1 on PRIMARY where (test.t1.id < 8)))))
+Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where not(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where (`test`.`t1`.`id` < 8)))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 7 Using where; Using index
+2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 Using where; Using index
Warnings:
Note 1276 Field or reference 'tt.id' of SELECT #2 was resolved in SELECT #1
-Note 1003 select test.tt.id AS `id`,test.tt.text AS `text` from test.t1 tt where not(exists(select test.t1.id AS `id` from test.t1 where ((test.t1.id < 8) and ((test.t1.id = test.tt.id) or isnull(test.t1.id))) having (test.t1.id is not null)))
+Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where not(exists(select `test`.`t1`.`id` AS `id` from `test`.`t1` where ((`test`.`t1`.`id` < 8) and (`test`.`t1`.`id` = `test`.`tt`.`id`)) having (`test`.`t1`.`id` is not null)))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
@@ -1758,7 +1770,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE b eq_ref PRIMARY PRIMARY 4 test.a.id 2
1 SIMPLE c eq_ref PRIMARY PRIMARY 4 func 1 Using where
Warnings:
-Note 1003 select test.a.id AS `id`,test.a.text AS `text`,test.b.id AS `id`,test.b.text AS `text`,test.c.id AS `id`,test.c.text AS `text` from test.t1 a left join test.t2 b on(((test.a.id = test.b.id) or isnull(test.b.id))) join test.t1 c where (if(isnull(test.b.id),1000,test.b.id) = test.c.id)
+Note 1003 select `test`.`a`.`id` AS `id`,`test`.`a`.`text` AS `text`,`test`.`b`.`id` AS `id`,`test`.`b`.`text` AS `text`,`test`.`c`.`id` AS `id`,`test`.`c`.`text` AS `text` from `test`.`t1` `a` left join `test`.`t2` `b` on(((`test`.`b`.`id` = `test`.`a`.`id`) or isnull(`test`.`b`.`id`))) join `test`.`t1` `c` where (if(isnull(`test`.`b`.`id`),1000,`test`.`b`.`id`) = `test`.`c`.`id`)
drop table t1,t2;
create table t1 (a int);
insert into t1 values (1);
@@ -1781,10 +1793,18 @@ SELECT t1.id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t
id c
1 1
2 0
+SELECT id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id);
+id c
+1 1
+2 0
SELECT t1.id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id) ORDER BY t1.id;
id c
1 1
2 0
+SELECT id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id) ORDER BY id;
+id c
+1 1
+2 0
DROP TABLE t1,t2;
CREATE TABLE t1 ( a int, b int );
INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
@@ -2260,7 +2280,7 @@ id select_type table type possible_keys key key_len ref rows Extra
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))
+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);
@@ -2797,19 +2817,19 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where
Warnings:
-Note 1003 select test.t1.one AS `one`,test.t1.two AS `two`,<in_optimizer>((test.t1.one,test.t1.two),<exists>(select test.t2.one AS `one`,test.t2.two AS `two` from test.t2 where ((test.t2.flag = _latin1'0') and ((<cache>(test.t1.one) = test.t2.one) or isnull(test.t2.one)) and ((<cache>(test.t1.two) = test.t2.two) or isnull(test.t2.two))) having (<is_not_null_test>(test.t2.one) and <is_not_null_test>(test.t2.two)))) AS `test` from test.t1
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'0') and ((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`)) and ((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`))) having (<is_not_null_test>(`test`.`t2`.`one`) and <is_not_null_test>(`test`.`t2`.`two`)))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where
Warnings:
-Note 1003 select test.t1.one AS `one`,test.t1.two AS `two` from test.t1 where <in_optimizer>((test.t1.one,test.t1.two),<exists>(select test.t2.one AS `one`,test.t2.two AS `two` from test.t2 where ((test.t2.flag = _latin1'N') and (<cache>(test.t1.one) = test.t2.one) and (<cache>(test.t1.two) = test.t2.two))))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'N') and (<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) and (<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`))))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select test.t1.one AS `one`,test.t1.two AS `two`,<in_optimizer>((test.t1.one,test.t1.two),<exists>(select test.t2.one AS `one`,test.t2.two AS `two` from test.t2 where (test.t2.flag = _latin1'0') group by test.t2.one,test.t2.two having (((<cache>(test.t1.one) = test.t2.one) or isnull(test.t2.one)) and ((<cache>(test.t1.two) = test.t2.two) or isnull(test.t2.two)) and <is_not_null_test>(test.t2.one) and <is_not_null_test>(test.t2.two)))) AS `test` from test.t1
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = _latin1'0') group by `test`.`t2`.`one`,`test`.`t2`.`two` having (((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`)) and ((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)) and <is_not_null_test>(`test`.`t2`.`one`) and <is_not_null_test>(`test`.`t2`.`two`)))) AS `test` from `test`.`t1`
DROP TABLE t1,t2;
CREATE TABLE t1 (a char(5), b char(5));
INSERT INTO t1 VALUES (NULL,'aaa'), ('aaa','aaa');
@@ -2834,3 +2854,136 @@ a
3
4
DROP TABLE t1,t2,t3;
+create table t1 (df decimal(5,1));
+insert into t1 values(1.1);
+insert into t1 values(2.2);
+select * from t1 where df <= all (select avg(df) from t1 group by df);
+df
+1.1
+select * from t1 where df >= all (select avg(df) from t1 group by df);
+df
+2.2
+drop table t1;
+create table t1 (df decimal(5,1));
+insert into t1 values(1.1);
+select 1.1 * exists(select * from t1);
+1.1 * exists(select * from t1)
+1.1
+drop table t1;
+CREATE TABLE t1 (
+grp int(11) default NULL,
+a decimal(10,2) default NULL);
+insert into t1 values (1, 1), (2, 2), (2, 3), (3, 4), (3, 5), (3, 6), (NULL, NULL);
+select * from t1;
+grp a
+1 1.00
+2 2.00
+2 3.00
+3 4.00
+3 5.00
+3 6.00
+NULL NULL
+select min(a) from t1 group by grp;
+min(a)
+NULL
+1.00
+2.00
+4.00
+drop table t1;
+CREATE table t1 ( c1 integer );
+INSERT INTO t1 VALUES ( 1 );
+INSERT INTO t1 VALUES ( 2 );
+INSERT INTO t1 VALUES ( 3 );
+CREATE TABLE t2 ( c2 integer );
+INSERT INTO t2 VALUES ( 1 );
+INSERT INTO t2 VALUES ( 4 );
+INSERT INTO t2 VALUES ( 5 );
+SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2 WHERE c2 IN (1);
+c1 c2
+1 1
+SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2
+WHERE c2 IN ( SELECT c2 FROM t2 WHERE c2 IN ( 1 ) );
+c1 c2
+1 1
+DROP TABLE t1,t2;
+CREATE TABLE t1 ( c1 integer );
+INSERT INTO t1 VALUES ( 1 );
+INSERT INTO t1 VALUES ( 2 );
+INSERT INTO t1 VALUES ( 3 );
+INSERT INTO t1 VALUES ( 6 );
+CREATE TABLE t2 ( c2 integer );
+INSERT INTO t2 VALUES ( 1 );
+INSERT INTO t2 VALUES ( 4 );
+INSERT INTO t2 VALUES ( 5 );
+INSERT INTO t2 VALUES ( 6 );
+CREATE TABLE t3 ( c3 integer );
+INSERT INTO t3 VALUES ( 7 );
+INSERT INTO t3 VALUES ( 8 );
+SELECT c1,c2 FROM t1 LEFT JOIN t2 ON c1 = c2
+WHERE EXISTS (SELECT c3 FROM t3 WHERE c2 IS NULL );
+c1 c2
+2 NULL
+3 NULL
+DROP TABLE t1,t2,t3;
+CREATE TABLE `t1` (
+`itemid` bigint(20) unsigned NOT NULL auto_increment,
+`sessionid` bigint(20) unsigned default NULL,
+`time` int(10) unsigned NOT NULL default '0',
+`type` set('A','D','E','F','G','I','L','N','U') collate latin1_general_ci NOT
+NULL default '',
+`data` text collate latin1_general_ci NOT NULL,
+PRIMARY KEY (`itemid`)
+) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+INSERT INTO `t1` VALUES (1, 1, 1, 'D', '');
+CREATE TABLE `t2` (
+`sessionid` bigint(20) unsigned NOT NULL auto_increment,
+`pid` int(10) unsigned NOT NULL default '0',
+`date` int(10) unsigned NOT NULL default '0',
+`ip` varchar(15) collate latin1_general_ci NOT NULL default '',
+PRIMARY KEY (`sessionid`)
+) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+INSERT INTO `t2` VALUES (1, 1, 1, '10.10.10.1');
+SELECT s.ip, count( e.itemid ) FROM `t1` e JOIN t2 s ON s.sessionid = e.sessionid WHERE e.sessionid = ( SELECT sessionid FROM t2 ORDER BY sessionid DESC LIMIT 1 ) GROUP BY s.ip HAVING count( e.itemid ) >0 LIMIT 0 , 30;
+ip count( e.itemid )
+10.10.10.1 1
+drop tables t1,t2;
+CREATE TABLE t1 (EMPNUM CHAR(3));
+CREATE TABLE t2 (EMPNUM CHAR(3) );
+INSERT INTO t1 VALUES ('E1'),('E2');
+INSERT INTO t2 VALUES ('E1');
+DELETE FROM t1
+WHERE t1.EMPNUM NOT IN
+(SELECT t2.EMPNUM
+FROM t2
+WHERE t1.EMPNUM = t2.EMPNUM);
+select * from t1;
+EMPNUM
+E1
+DROP TABLE t1,t2;
+CREATE TABLE t1(select_id BIGINT, values_id BIGINT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TABLE t2 (select_id BIGINT, values_id BIGINT,
+PRIMARY KEY(select_id,values_id));
+INSERT INTO t2 VALUES (0, 1), (0, 2), (0, 3), (1, 5);
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+WHERE select_id IN (1, 0));
+values_id
+1
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+WHERE select_id BETWEEN 0 AND 1);
+values_id
+1
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+WHERE select_id = 0 OR select_id = 1);
+values_id
+1
+DROP TABLE t1, t2;
+create table t1 (fld enum('0','1'));
+insert into t1 values ('1');
+select * from (select max(fld) from t1) as foo;
+max(fld)
+1
+drop table t1;
diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result
index 148c670c589..bc902ea7b0f 100644
--- a/mysql-test/r/subselect2.result
+++ b/mysql-test/r/subselect2.result
@@ -121,11 +121,11 @@ c373e9f5ad07993f3859444553544200 Last Discussion c373e9f5ad079174ff1744455354420
EXPLAIN SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JOIN t4 ON t2.DOCTYPEID = t4.DOCTYPEID LEFT OUTER JOIN t1 ON t2.DOCID = t1.DOCID WHERE t2.FOLDERID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t3.FOLDERNAME = 'Level1') AND t3.FOLDERNAME = 'Level2') AND t3.FOLDERNAME = 'Level3') AND t3.FOLDERNAME = 'CopiedFolder') AND t3.FOLDERNAME = 'Movie Reviews') AND t2.DOCNAME = 'Last Discussion';
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL DDOCTYPEID_IDX NULL NULL NULL 9 Using where
-1 PRIMARY t4 eq_ref PRIMARY PRIMARY 32 test.t2.DOCTYPEID 1
-1 PRIMARY t1 eq_ref PRIMARY PRIMARY 32 test.t2.DOCID 1
-2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
-3 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
-4 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
-5 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
-6 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 32 func 1 Using index; Using where
+1 PRIMARY t1 eq_ref PRIMARY PRIMARY 34 test.t2.DOCID 1
+1 PRIMARY t4 eq_ref PRIMARY PRIMARY 34 test.t2.DOCTYPEID 1
+2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 34 func 1 Using index; Using where
+3 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 34 func 1 Using index; Using where
+4 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 34 func 1 Using index; Using where
+5 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 34 func 1 Using index; Using where
+6 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 func 1 Using index; Using where
drop table t1, t2, t3, t4;
diff --git a/mysql-test/r/sum_distinct-big.result b/mysql-test/r/sum_distinct-big.result
new file mode 100644
index 00000000000..06bfc6b1f78
--- /dev/null
+++ b/mysql-test/r/sum_distinct-big.result
@@ -0,0 +1,108 @@
+using_big_test
+0
+CREATE TABLE t1 (id INTEGER);
+CREATE TABLE t2 (id INTEGER);
+INSERT INTO t1 (id) VALUES (1), (1), (1),(1);
+INSERT INTO t1 (id) SELECT id FROM t1;
+/* 8 */
+INSERT INTO t1 (id) SELECT id FROM t1;
+/* 12 */
+INSERT INTO t1 (id) SELECT id FROM t1;
+/* 16 */
+INSERT INTO t1 (id) SELECT id FROM t1;
+/* 20 */
+INSERT INTO t1 (id) SELECT id FROM t1;
+/* 24 */
+INSERT INTO t1 SELECT id+1 FROM t1;
+INSERT INTO t1 SELECT id+2 FROM t1;
+INSERT INTO t1 SELECT id+4 FROM t1;
+INSERT INTO t1 SELECT id+8 FROM t1;
+INSERT INTO t1 SELECT id+16 FROM t1;
+INSERT INTO t1 SELECT id+32 FROM t1;
+INSERT INTO t1 SELECT id+64 FROM t1;
+INSERT INTO t1 SELECT id+128 FROM t1;
+INSERT INTO t1 SELECT id+256 FROM t1;
+INSERT INTO t1 SELECT id+512 FROM t1;
+SELECT AVG(DISTINCT id) FROM t1 GROUP BY id % 13;
+AVG(DISTINCT id)
+513.5000
+508.0000
+509.0000
+510.0000
+511.0000
+512.0000
+513.0000
+514.0000
+515.0000
+516.0000
+517.0000
+511.5000
+512.5000
+SELECT SUM(DISTINCT id)/COUNT(DISTINCT id) FROM t1 GROUP BY id % 13;
+SUM(DISTINCT id)/COUNT(DISTINCT id)
+513.50000
+508.00000
+509.00000
+510.00000
+511.00000
+512.00000
+513.00000
+514.00000
+515.00000
+516.00000
+517.00000
+511.50000
+512.50000
+INSERT INTO t1 SELECT id+1024 FROM t1;
+INSERT INTO t1 SELECT id+2048 FROM t1;
+INSERT INTO t1 SELECT id+4096 FROM t1;
+INSERT INTO t1 SELECT id+8192 FROM t1;
+INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand();
+SELECT SUM(DISTINCT id) sm FROM t1;
+sm
+134225920
+SELECT SUM(DISTINCT id) sm FROM t2;
+sm
+134225920
+SELECT SUM(DISTINCT id) sm FROM t1 group by id % 13;
+sm
+10327590
+10328851
+10330112
+10331373
+10332634
+10317510
+10318770
+10320030
+10321290
+10322550
+10323810
+10325070
+10326330
+SET max_heap_table_size=16384;
+SHOW variables LIKE 'max_heap_table_size';
+Variable_name Value
+max_heap_table_size 16384
+SELECT SUM(DISTINCT id) sm FROM t1;
+sm
+134225920
+SELECT SUM(DISTINCT id) sm FROM t2;
+sm
+134225920
+SELECT SUM(DISTINCT id) sm FROM t1 GROUP BY id % 13;
+sm
+10327590
+10328851
+10330112
+10331373
+10332634
+10317510
+10318770
+10320030
+10321290
+10322550
+10323810
+10325070
+10326330
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/r/sum_distinct.result b/mysql-test/r/sum_distinct.result
new file mode 100644
index 00000000000..c615817f52d
--- /dev/null
+++ b/mysql-test/r/sum_distinct.result
@@ -0,0 +1,97 @@
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (
+id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+gender CHAR(1),
+name VARCHAR(20)
+);
+SELECT SUM(DISTINCT LENGTH(name)) s1 FROM t1;
+s1
+NULL
+INSERT INTO t1 (gender, name) VALUES (NULL, NULL);
+INSERT INTO t1 (gender, name) VALUES (NULL, NULL);
+INSERT INTO t1 (gender, name) VALUES (NULL, NULL);
+SELECT SUM(DISTINCT LENGTH(name)) s1 FROM t1;
+s1
+NULL
+INSERT INTO t1 (gender, name) VALUES ('F', 'Helen'), ('F', 'Anastasia'),
+('F', 'Katherine'), ('F', 'Margo'), ('F', 'Magdalene'), ('F', 'Mary');
+CREATE TABLE t2 SELECT name FROM t1;
+SELECT (SELECT SUM(DISTINCT LENGTH(name)) FROM t1) FROM t2;
+(SELECT SUM(DISTINCT LENGTH(name)) FROM t1)
+18
+18
+18
+18
+18
+18
+18
+18
+18
+DROP TABLE t2;
+INSERT INTO t1 (gender, name) VALUES ('F', 'Eva'), ('F', 'Sofia'),
+('F', 'Sara'), ('F', 'Golda'), ('F', 'Toba'), ('F', 'Victory'),
+('F', 'Faina'), ('F', 'Miriam'), ('F', 'Beki'), ('F', 'America'),
+('F', 'Susan'), ('F', 'Glory'), ('F', 'Priscilla'), ('F', 'Rosmary'),
+('F', 'Rose'), ('F', 'Margareth'), ('F', 'Elizabeth'), ('F', 'Meredith'),
+('F', 'Julie'), ('F', 'Xenia'), ('F', 'Zena'), ('F', 'Olga'),
+('F', 'Brunhilda'), ('F', 'Nataly'), ('F', 'Lara'), ('F', 'Svetlana'),
+('F', 'Grethem'), ('F', 'Irene');
+SELECT
+SUM(DISTINCT LENGTH(name)) s1,
+SUM(DISTINCT SUBSTRING(NAME, 1, 3)) s2,
+SUM(DISTINCT LENGTH(SUBSTRING(name, 1, 4))) s3
+FROM t1;
+s1 s2 s3
+42 0 7
+SELECT
+SUM(DISTINCT LENGTH(g1.name)) s1,
+SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2,
+SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3
+FROM t1 g1, t1 g2, t1 g3;
+s1 s2 s3
+42 0 7
+SELECT
+SUM(DISTINCT LENGTH(g1.name)) s1,
+SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2,
+SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3
+FROM t1 g1, t1 g2, t1 g3 GROUP BY LENGTH(SUBSTRING(g3.name, 5, 10));
+s1 s2 s3
+42 0 NULL
+42 0 7
+42 0 4
+42 0 4
+42 0 4
+42 0 4
+42 0 4
+SELECT SQL_BUFFER_RESULT
+SUM(DISTINCT LENGTH(name)) s1,
+SUM(DISTINCT SUBSTRING(NAME, 1, 3)) s2,
+SUM(DISTINCT LENGTH(SUBSTRING(name, 1, 4))) s3
+FROM t1;
+s1 s2 s3
+42 0 7
+SELECT SQL_BUFFER_RESULT
+SUM(DISTINCT LENGTH(g1.name)) s1,
+SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2,
+SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3
+FROM t1 g1, t1 g2, t1 g3 GROUP BY LENGTH(SUBSTRING(g3.name, 5, 10));
+s1 s2 s3
+42 0 NULL
+42 0 7
+42 0 4
+42 0 4
+42 0 4
+42 0 4
+42 0 4
+SET @l=1;
+UPDATE t1 SET name=CONCAT(name, @l:=@l+1);
+SELECT SUM(DISTINCT RIGHT(name, 1)) FROM t1;
+SUM(DISTINCT RIGHT(name, 1))
+45
+SELECT SUM(DISTINCT id) FROM t1;
+SUM(DISTINCT id)
+703
+SELECT SUM(DISTINCT id % 11) FROM t1;
+SUM(DISTINCT id % 11)
+55
+DROP TABLE t1;
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 26612ec81fd..b36020bc2a3 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -37,14 +37,23 @@ show create table t9;
Table Create Table
t9 CREATE TABLE `t9` (
`a` int(11) NOT NULL auto_increment,
- `b` char(16) NOT NULL default '',
- `c` int(11) NOT NULL default '0',
+ `b` char(16) NOT NULL,
+ `c` int(11) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/'
alter table t9 rename t8, add column d int not null;
alter table t8 rename t7;
rename table t7 to t9;
drop table t1;
+SHOW CREATE TABLE t9;
+Table Create Table
+t9 CREATE TABLE `t9` (
+ `a` int(11) NOT NULL auto_increment,
+ `b` char(16) NOT NULL,
+ `c` int(11) NOT NULL,
+ `d` int(11) NOT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/'
Got one of the listed errors
Got one of the listed errors
Got one of the listed errors
@@ -58,9 +67,9 @@ show create table mysqltest.t9;
Table Create Table
t9 CREATE TABLE `t9` (
`a` int(11) NOT NULL auto_increment,
- `b` char(16) NOT NULL default '',
- `c` int(11) NOT NULL default '0',
- `d` int(11) NOT NULL default '0',
+ `b` char(16) NOT NULL,
+ `c` int(11) NOT NULL,
+ `d` int(11) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/'
drop database mysqltest;
@@ -68,19 +77,19 @@ create table t1 (a int not null) engine=myisam;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0'
+ `a` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 add b int;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL default '0',
+ `a` int(11) NOT NULL,
`b` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
diff --git a/mysql-test/r/synchronization.result b/mysql-test/r/synchronization.result
index ad9443c86da..0b84697066c 100644
--- a/mysql-test/r/synchronization.result
+++ b/mysql-test/r/synchronization.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
CREATE TABLE t1 (x1 int);
ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index 141878a7bf6..d2872878cb9 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -1,3 +1,4 @@
+drop table if exists t1,t1aa,t2aa;
show tables;
Tables_in_db
columns_priv
@@ -8,6 +9,8 @@ help_keyword
help_relation
help_topic
host
+proc
+procs_priv
tables_priv
time_zone
time_zone_leap_second
@@ -33,6 +36,11 @@ db CREATE TABLE `db` (
`Alter_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Create_tmp_table_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Lock_tables_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Create_view_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Show_view_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Create_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
PRIMARY KEY (`Host`,`Db`,`User`),
KEY `User` (`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges'
@@ -53,14 +61,19 @@ host CREATE TABLE `host` (
`Alter_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Create_tmp_table_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Lock_tables_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Create_view_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Show_view_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Create_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
PRIMARY KEY (`Host`,`Db`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges'
show create table user;
Table Create Table
user CREATE TABLE `user` (
- `Host` varchar(60) collate utf8_bin NOT NULL default '',
- `User` varchar(16) collate utf8_bin NOT NULL default '',
- `Password` varchar(41) collate utf8_bin NOT NULL default '',
+ `Host` char(60) collate utf8_bin NOT NULL default '',
+ `User` char(16) collate utf8_bin NOT NULL default '',
+ `Password` char(41) collate utf8_bin NOT NULL default '',
`Select_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Insert_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Update_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
@@ -82,6 +95,11 @@ user CREATE TABLE `user` (
`Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Repl_slave_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Repl_client_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Create_view_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Show_view_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Create_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Create_user_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`ssl_type` enum('','ANY','X509','SPECIFIED') character set utf8 NOT NULL default '',
`ssl_cipher` blob NOT NULL,
`x509_issuer` blob NOT NULL,
@@ -89,6 +107,7 @@ user CREATE TABLE `user` (
`max_questions` int(11) unsigned NOT NULL default '0',
`max_updates` int(11) unsigned NOT NULL default '0',
`max_connections` int(11) unsigned NOT NULL default '0',
+ `max_user_connections` int(11) unsigned NOT NULL default '0',
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
@@ -97,7 +116,7 @@ func CREATE TABLE `func` (
`name` char(64) collate utf8_bin NOT NULL default '',
`ret` tinyint(1) NOT NULL default '0',
`dl` char(128) collate utf8_bin NOT NULL default '',
- `type` enum('function','aggregate') character set utf8 NOT NULL default 'function',
+ `type` enum('function','aggregate') character set utf8 NOT NULL,
PRIMARY KEY (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions'
show create table tables_priv;
@@ -109,7 +128,7 @@ tables_priv CREATE TABLE `tables_priv` (
`Table_name` char(64) collate utf8_bin NOT NULL default '',
`Grantor` char(77) collate utf8_bin NOT NULL default '',
`Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
- `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') character set utf8 NOT NULL default '',
+ `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') character set utf8 NOT NULL default '',
`Column_priv` set('Select','Insert','Update','References') character set utf8 NOT NULL default '',
PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`),
KEY `Grantor` (`Grantor`)
@@ -126,5 +145,40 @@ columns_priv CREATE TABLE `columns_priv` (
`Column_priv` set('Select','Insert','Update','References') character set utf8 NOT NULL default '',
PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges'
+show create table procs_priv;
+Table Create Table
+procs_priv CREATE TABLE `procs_priv` (
+ `Host` char(60) collate utf8_bin NOT NULL default '',
+ `Db` char(64) collate utf8_bin NOT NULL default '',
+ `User` char(16) collate utf8_bin NOT NULL default '',
+ `Routine_name` char(64) collate utf8_bin NOT NULL default '',
+ `Routine_type` enum('FUNCTION','PROCEDURE') collate utf8_bin NOT NULL,
+ `Grantor` char(77) collate utf8_bin NOT NULL default '',
+ `Proc_priv` set('Execute','Alter Routine','Grant') character set utf8 NOT NULL default '',
+ `Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+ PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`),
+ KEY `Grantor` (`Grantor`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'
+show create table proc;
+Table Create Table
+proc CREATE TABLE `proc` (
+ `db` char(64) character set utf8 collate utf8_bin NOT NULL default '',
+ `name` char(64) NOT NULL default '',
+ `type` enum('FUNCTION','PROCEDURE') NOT NULL,
+ `specific_name` char(64) NOT NULL default '',
+ `language` enum('SQL') NOT NULL default 'SQL',
+ `sql_data_access` enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NOT NULL default 'CONTAINS_SQL',
+ `is_deterministic` enum('YES','NO') NOT NULL default 'NO',
+ `security_type` enum('INVOKER','DEFINER') NOT NULL default 'DEFINER',
+ `param_list` blob NOT NULL,
+ `returns` char(64) NOT NULL default '',
+ `body` longblob NOT NULL,
+ `definer` char(77) character set utf8 collate utf8_bin NOT NULL default '',
+ `created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+ `modified` timestamp NOT NULL default '0000-00-00 00:00:00',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') NOT NULL default '',
+ `comment` char(64) character set utf8 collate utf8_bin NOT NULL default '',
+ PRIMARY KEY (`db`,`name`,`type`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures'
show tables;
Tables_in_test
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index 0b6bc48c350..726861bb525 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -97,8 +97,34 @@ d
show status like "created_tmp%tables";
Variable_name Value
Created_tmp_disk_tables 0
-Created_tmp_tables 1
+Created_tmp_tables 2
drop table t1;
+create temporary table t1 as select 'This is temp. table' A;
+create view t1 as select 'This is view' A;
+select * from t1;
+A
+This is temp. table
+show create table t1;
+Table Create Table
+t1 CREATE TEMPORARY TABLE `t1` (
+ `A` varchar(19) NOT NULL default ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create view t1;
+View Create View
+t1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `t1` AS select _latin1'This is view' AS `A`
+drop view t1;
+select * from t1;
+A
+This is temp. table
+create view t1 as select 'This is view again' A;
+select * from t1;
+A
+This is temp. table
+drop table t1;
+select * from t1;
+A
+This is view again
+drop view t1;
create table t1 (a int, b int, index(a), index(b));
create table t2 (c int auto_increment, d varchar(255), primary key (c));
insert into t1 values (3,1),(3,2);
diff --git a/mysql-test/r/testdb_only.require b/mysql-test/r/testdb_only.require
new file mode 100644
index 00000000000..e717418fdb6
--- /dev/null
+++ b/mysql-test/r/testdb_only.require
@@ -0,0 +1,2 @@
+Variable_name Value
+use extern server NO
diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result
index 199b48ef1aa..df51a6aac9b 100644
--- a/mysql-test/r/timezone2.result
+++ b/mysql-test/r/timezone2.result
@@ -40,6 +40,12 @@ insert into t1 (i, ts) values
Warnings:
Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2
insert into t1 (i, ts) values
+(unix_timestamp(20030330015959),20030330015959),
+(unix_timestamp(20030330023000),20030330023000),
+(unix_timestamp(20030330030000),20030330030000);
+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'),
@@ -54,6 +60,9 @@ i ts
1048985999 2003-03-30 00:59:59
1048986000 2003-03-30 01:00:00
1048986000 2003-03-30 01: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
@@ -108,9 +117,9 @@ 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
+Warning 1264 Out of range value adjusted for column 'ts' at row 2
+Warning 1264 Out of range value adjusted for column 'ts' at row 3
+Warning 1264 Out of range value adjusted for column 'ts' at row 6
select * from t1;
ts
0000-00-00 00:00:00
@@ -125,9 +134,9 @@ 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
+Warning 1264 Out of range value adjusted for column 'ts' at row 2
+Warning 1264 Out of range value adjusted for column 'ts' at row 3
+Warning 1264 Out of range value adjusted for column 'ts' at row 6
select * from t1;
ts
0000-00-00 00:00:00
@@ -142,9 +151,9 @@ 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
+Warning 1264 Out of range value adjusted for column 'ts' at row 2
+Warning 1264 Out of range value adjusted for column 'ts' at row 3
+Warning 1264 Out of range value adjusted for column 'ts' at row 6
select * from t1;
ts
0000-00-00 00:00:00
diff --git a/mysql-test/r/timezone_grant.result b/mysql-test/r/timezone_grant.result
index 471cacde300..3758f3c2645 100644
--- a/mysql-test/r/timezone_grant.result
+++ b/mysql-test/r/timezone_grant.result
@@ -20,9 +20,9 @@ convert_tz(b, 'Europe/Moscow', 'UTC')
update t1, t2 set t1.b = convert_tz('2004-10-21 19:00:00', 'Europe/Moscow', 'UTC')
where t1.a = t2.c and t2.d = (select max(d) from t2);
select * from mysql.time_zone_name;
-ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysql'
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'time_zone_name'
select Name, convert_tz('2004-10-21 19:00:00', Name, 'UTC') from mysql.time_zone_name;
-ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'mysql'
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'time_zone_name'
delete from mysql.db where user like 'mysqltest\_%';
flush privileges;
grant all privileges on test.t1 to mysqltest_1@localhost;
@@ -36,7 +36,9 @@ set time_zone= '+00:00';
set time_zone= 'Europe/Moscow';
select convert_tz('2004-11-31 12:00:00', 'Europe/Moscow', 'UTC');
convert_tz('2004-11-31 12:00:00', 'Europe/Moscow', 'UTC')
-2004-12-01 09:00:00
+NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2004-11-31 12:00:00'
select convert_tz(b, 'Europe/Moscow', 'UTC') from t1;
convert_tz(b, 'Europe/Moscow', 'UTC')
update t1, t2 set t1.b = convert_tz('2004-11-30 12:00:00', 'Europe/Moscow', 'UTC')
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
new file mode 100644
index 00000000000..b305691fa18
--- /dev/null
+++ b/mysql-test/r/trigger.result
@@ -0,0 +1,740 @@
+drop table if exists t1, t2, t3;
+drop view if exists v1;
+drop database if exists mysqltest;
+drop function if exists f1;
+drop procedure if exists p1;
+create table t1 (i int);
+create trigger trg before insert on t1 for each row set @a:=1;
+set @a:=0;
+select @a;
+@a
+0
+insert into t1 values (1);
+select @a;
+@a
+1
+drop trigger trg;
+create trigger trg before insert on t1 for each row set @a:=new.i;
+insert into t1 values (123);
+select @a;
+@a
+123
+drop trigger trg;
+drop table t1;
+create table t1 (i int not null, j int);
+create trigger trg before insert on t1 for each row
+begin
+if isnull(new.j) then
+set new.j:= new.i * 10;
+end if;
+end|
+insert into t1 (i) values (1)|
+insert into t1 (i,j) values (2, 3)|
+select * from t1|
+i j
+1 10
+2 3
+drop trigger trg|
+drop table t1|
+create table t1 (i int not null primary key);
+create trigger trg after insert on t1 for each row
+set @a:= if(@a,concat(@a, ":", new.i), new.i);
+set @a:="";
+insert into t1 values (2),(3),(4),(5);
+select @a;
+@a
+2:3:4:5
+drop trigger trg;
+drop table t1;
+create table t1 (aid int not null primary key, balance int not null default 0);
+insert into t1 values (1, 1000), (2,3000);
+create trigger trg before update on t1 for each row
+begin
+declare loc_err varchar(255);
+if abs(new.balance - old.balance) > 1000 then
+set new.balance:= old.balance;
+set loc_err := concat("Too big change for aid = ", new.aid);
+set @update_failed:= if(@update_failed, concat(@a, ":", loc_err), loc_err);
+end if;
+end|
+set @update_failed:=""|
+update t1 set balance=1500|
+select @update_failed;
+select * from t1|
+@update_failed
+Too big change for aid = 2
+aid balance
+1 1500
+2 3000
+drop trigger trg|
+drop table t1|
+create table t1 (i int);
+insert into t1 values (1),(2),(3),(4);
+create trigger trg after update on t1 for each row
+set @total_change:=@total_change + new.i - old.i;
+set @total_change:=0;
+update t1 set i=3;
+select @total_change;
+@total_change
+2
+drop trigger trg;
+drop table t1;
+create table t1 (i int);
+insert into t1 values (1),(2),(3),(4);
+create trigger trg before delete on t1 for each row
+set @del_sum:= @del_sum + old.i;
+set @del_sum:= 0;
+delete from t1 where i <= 3;
+select @del_sum;
+@del_sum
+6
+drop trigger trg;
+drop table t1;
+create table t1 (i int);
+insert into t1 values (1),(2),(3),(4);
+create trigger trg after delete on t1 for each row set @del:= 1;
+set @del:= 0;
+delete from t1 where i <> 0;
+select @del;
+@del
+1
+drop trigger trg;
+drop table t1;
+create table t1 (i int, j int);
+create trigger trg1 before insert on t1 for each row
+begin
+if new.j > 10 then
+set new.j := 10;
+end if;
+end|
+create trigger trg2 before update on t1 for each row
+begin
+if old.i % 2 = 0 then
+set new.j := -1;
+end if;
+end|
+create trigger trg3 after update on t1 for each row
+begin
+if new.j = -1 then
+set @fired:= "Yes";
+end if;
+end|
+set @fired:="";
+insert into t1 values (1,2),(2,3),(3,14);
+select @fired;
+@fired
+
+select * from t1;
+i j
+1 2
+2 3
+3 10
+update t1 set j= 20;
+select @fired;
+@fired
+Yes
+select * from t1;
+i j
+1 20
+2 -1
+3 20
+drop trigger trg1;
+drop trigger trg2;
+drop trigger trg3;
+drop table t1;
+create table t1 (id int not null primary key, data int);
+create trigger t1_bi before insert on t1 for each row
+set @log:= concat(@log, "(BEFORE_INSERT: new=(id=", new.id, ", data=", new.data,"))");
+create trigger t1_ai after insert on t1 for each row
+set @log:= concat(@log, "(AFTER_INSERT: new=(id=", new.id, ", data=", new.data,"))");
+create trigger t1_bu before update on t1 for each row
+set @log:= concat(@log, "(BEFORE_UPDATE: old=(id=", old.id, ", data=", old.data,
+") new=(id=", new.id, ", data=", new.data,"))");
+create trigger t1_au after update on t1 for each row
+set @log:= concat(@log, "(AFTER_UPDATE: old=(id=", old.id, ", data=", old.data,
+") new=(id=", new.id, ", data=", new.data,"))");
+create trigger t1_bd before delete on t1 for each row
+set @log:= concat(@log, "(BEFORE_DELETE: old=(id=", old.id, ", data=", old.data,"))");
+create trigger t1_ad after delete on t1 for each row
+set @log:= concat(@log, "(AFTER_DELETE: old=(id=", old.id, ", data=", old.data,"))");
+set @log:= "";
+insert into t1 values (1, 1);
+select @log;
+@log
+(BEFORE_INSERT: new=(id=1, data=1))(AFTER_INSERT: new=(id=1, data=1))
+set @log:= "";
+insert ignore t1 values (1, 2);
+select @log;
+@log
+(BEFORE_INSERT: new=(id=1, data=2))
+set @log:= "";
+replace t1 values (1, 3), (2, 2);
+select @log;
+@log
+(BEFORE_INSERT: new=(id=1, data=3))(BEFORE_UPDATE: old=(id=1, data=1) new=(id=1, data=3))(AFTER_UPDATE: old=(id=1, data=1) new=(id=1, data=3))(BEFORE_INSERT: new=(id=2, data=2))(AFTER_INSERT: new=(id=2, data=2))
+alter table t1 add ts timestamp default now();
+set @log:= "";
+replace t1 (id, data) values (1, 4);
+select @log;
+@log
+(BEFORE_INSERT: new=(id=1, data=4))(BEFORE_DELETE: old=(id=1, data=3))(AFTER_DELETE: old=(id=1, data=3))(AFTER_INSERT: new=(id=1, data=4))
+set @log:= "";
+insert into t1 (id, data) values (1, 5), (3, 3) on duplicate key update data= data + 2;
+select @log;
+@log
+(BEFORE_INSERT: new=(id=1, data=5))(BEFORE_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(AFTER_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(BEFORE_INSERT: new=(id=3, data=3))(AFTER_INSERT: new=(id=3, data=3))
+drop table t1;
+create table t1 (id int primary key, data varchar(10), fk int);
+create table t2 (event varchar(100));
+create table t3 (id int primary key);
+create trigger t1_ai after insert on t1 for each row
+insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "'"));
+insert into t1 (id, data) values (1, "one"), (2, "two");
+select * from t1;
+id data fk
+1 one NULL
+2 two NULL
+select * from t2;
+event
+INSERT INTO t1 id=1 data='one'
+INSERT INTO t1 id=2 data='two'
+drop trigger t1_ai;
+create trigger t1_bi before insert on t1 for each row
+begin
+if exists (select id from t3 where id=new.fk) then
+insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "' fk=", new.fk));
+else
+insert into t2 values (concat("INSERT INTO t1 FAILED id=", new.id, " data='", new.data, "' fk=", new.fk));
+set new.id= NULL;
+end if;
+end|
+insert into t3 values (1);
+insert into t1 values (4, "four", 1), (5, "five", 2);
+ERROR 23000: Column 'id' cannot be null
+select * from t1;
+id data fk
+1 one NULL
+2 two NULL
+4 four 1
+select * from t2;
+event
+INSERT INTO t1 id=1 data='one'
+INSERT INTO t1 id=2 data='two'
+INSERT INTO t1 id=4 data='four' fk=1
+INSERT INTO t1 FAILED id=5 data='five' fk=2
+drop table t1, t2, t3;
+create table t1 (id int primary key, data varchar(10));
+create table t2 (seq int);
+insert into t2 values (10);
+create function f1 () returns int return (select max(seq) from t2);
+create trigger t1_bi before insert on t1 for each row
+begin
+if new.id > f1() then
+set new.id:= f1();
+end if;
+end|
+insert into t1 values (1, "first");
+insert into t1 values (f1(), "max");
+select * from t1;
+id data
+1 first
+10 max
+drop table t1, t2;
+drop function f1;
+create table t1 (id int primary key, fk_t2 int);
+create table t2 (id int primary key, fk_t3 int);
+create table t3 (id int primary key);
+insert into t1 values (1,1), (2,1), (3,2);
+insert into t2 values (1,1), (2,2);
+insert into t3 values (1), (2);
+create trigger t3_ad after delete on t3 for each row
+delete from t2 where fk_t3=old.id;
+create trigger t2_ad after delete on t2 for each row
+delete from t1 where fk_t2=old.id;
+delete from t3 where id = 1;
+select * from t1 left join (t2 left join t3 on t2.fk_t3 = t3.id) on t1.fk_t2 = t2.id;
+id fk_t2 id fk_t3 id
+3 2 2 2 2
+drop table t1, t2, t3;
+create table t1 (id int primary key, copy int);
+create table t2 (id int primary key, data int);
+insert into t2 values (1,1), (2,2);
+create trigger t1_bi before insert on t1 for each row
+set new.copy= (select data from t2 where id = new.id);
+create trigger t1_bu before update on t1 for each row
+set new.copy= (select data from t2 where id = new.id);
+insert into t1 values (1,3), (2,4), (3,3);
+update t1 set copy= 1 where id = 2;
+select * from t1;
+id copy
+1 1
+2 2
+3 NULL
+drop table t1, t2;
+create table t1 (i int);
+create table t3 (i int);
+create trigger trg before insert on t1 for each row set @a:= old.i;
+ERROR HY000: There is no OLD row in on INSERT trigger
+create trigger trg before delete on t1 for each row set @a:= new.i;
+ERROR HY000: There is no NEW row in on DELETE trigger
+create trigger trg before update on t1 for each row set old.i:=1;
+ERROR HY000: Updating of OLD row is not allowed in trigger
+create trigger trg before delete on t1 for each row set new.i:=1;
+ERROR HY000: There is no NEW row in on DELETE trigger
+create trigger trg after update on t1 for each row set new.i:=1;
+ERROR HY000: Updating of NEW row is not allowed in after trigger
+create trigger trg before update on t1 for each row set new.j:=1;
+ERROR 42S22: Unknown column 'j' in 'NEW'
+create trigger trg before update on t1 for each row set @a:=old.j;
+ERROR 42S22: Unknown column 'j' in 'OLD'
+create trigger trg before insert on t2 for each row set @a:=1;
+ERROR 42S02: Table 'test.t2' doesn't exist
+create trigger trg before insert on t1 for each row set @a:=1;
+create trigger trg after insert on t1 for each row set @a:=1;
+ERROR HY000: Trigger already exists
+create trigger trg2 before insert on t1 for each row set @a:=1;
+ERROR HY000: Trigger already exists
+create trigger trg before insert on t3 for each row set @a:=1;
+ERROR HY000: Trigger already exists
+create trigger trg2 before insert on t3 for each row set @a:=1;
+drop trigger trg2;
+drop trigger trg;
+drop trigger trg;
+ERROR HY000: Trigger does not exist
+create view v1 as select * from t1;
+create trigger trg before insert on v1 for each row set @a:=1;
+ERROR HY000: 'test.v1' is not BASE TABLE
+drop view v1;
+drop table t1;
+drop table t3;
+create temporary table t1 (i int);
+create trigger trg before insert on t1 for each row set @a:=1;
+ERROR HY000: Trigger's 't1' is view or temporary table
+drop table t1;
+create table t1 (x1col char);
+create trigger tx1 before insert on t1 for each row set new.x1col = 'x';
+insert into t1 values ('y');
+drop trigger tx1;
+drop table t1;
+create table t1 (i int) engine=myisam;
+insert into t1 values (1), (2);
+create trigger trg1 before delete on t1 for each row set @del_before:= @del_before + old.i;
+create trigger trg2 after delete on t1 for each row set @del_after:= @del_after + old.i;
+set @del_before:=0, @del_after:= 0;
+delete from t1;
+select @del_before, @del_after;
+@del_before @del_after
+3 3
+drop trigger trg1;
+drop trigger trg2;
+drop table t1;
+create table t1 (a int);
+create trigger trg1 before insert on t1 for each row set new.a= 10;
+drop table t1;
+create table t1 (a int);
+insert into t1 values ();
+select * from t1;
+a
+NULL
+drop table t1;
+create database mysqltest;
+use mysqltest;
+create table t1 (i int);
+create trigger trg1 before insert on t1 for each row set @a:= 1;
+drop database mysqltest;
+use test;
+create database mysqltest;
+create table mysqltest.t1 (i int);
+create trigger trg1 before insert on mysqltest.t1 for each row set @a:= 1;
+ERROR HY000: Trigger in wrong schema
+use mysqltest;
+create trigger test.trg1 before insert on t1 for each row set @a:= 1;
+ERROR HY000: Trigger in wrong schema
+drop database mysqltest;
+use test;
+create table t1 (i int, j int default 10, k int not null, key (k));
+create table t2 (i int);
+insert into t1 (i, k) values (1, 1);
+insert into t2 values (1);
+create trigger trg1 before update on t1 for each row set @a:= @a + new.j - old.j;
+create trigger trg2 after update on t1 for each row set @b:= "Fired";
+set @a:= 0, @b:= "";
+update t1, t2 set j = j + 10 where t1.i = t2.i;
+select @a, @b;
+@a @b
+10 Fired
+insert into t1 values (2, 13, 2);
+insert into t2 values (2);
+set @a:= 0, @b:= "";
+update t1, t2 set j = j + 15 where t1.i = t2.i and t1.k >= 2;
+select @a, @b;
+@a @b
+15 Fired
+create trigger trg3 before delete on t1 for each row set @c:= @c + old.j;
+create trigger trg4 before delete on t2 for each row set @d:= @d + old.i;
+create trigger trg5 after delete on t1 for each row set @e:= "After delete t1 fired";
+create trigger trg6 after delete on t2 for each row set @f:= "After delete t2 fired";
+set @c:= 0, @d:= 0, @e:= "", @f:= "";
+delete t1, t2 from t1, t2 where t1.i = t2.i;
+select @c, @d, @e, @f;
+@c @d @e @f
+48 3 After delete t1 fired After delete t2 fired
+drop table t1, t2;
+create table t1 (i int, j int default 10)|
+create table t2 (i int)|
+insert into t2 values (1), (2)|
+create trigger trg1 before insert on t1 for each row
+begin
+if new.i = 1 then
+set new.j := 1;
+end if;
+end|
+create trigger trg2 after insert on t1 for each row set @a:= 1|
+set @a:= 0|
+insert into t1 (i) select * from t2|
+select * from t1|
+i j
+1 1
+2 10
+select @a|
+@a
+1
+drop table t1, t2|
+create table t1 (i int, j int, k int);
+create trigger trg1 before insert on t1 for each row set new.k = new.i;
+create trigger trg2 after insert on t1 for each row set @b:= "Fired";
+set @b:="";
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, i);
+select *, @b from t1;
+i j k @b
+10 NULL 10 Fired
+15 NULL 15 Fired
+set @b:="";
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, j);
+select *, @b from t1;
+i j k @b
+10 NULL 10 Fired
+15 NULL 15 Fired
+1 2 1 Fired
+3 4 3 Fired
+5 6 5 Fired
+drop table t1;
+create table t1 (i int, at int, k int, key(k)) engine=myisam;
+create table t2 (i int);
+insert into t1 values (1, 1, 1);
+insert into t2 values (1), (2), (3);
+create trigger ai after insert on t1 for each row set @a:= new.at;
+create trigger au after update on t1 for each row set @a:= new.at;
+create trigger ad after delete on t1 for each row set @a:= old.at;
+alter table t1 drop column at;
+select * from t1;
+i k
+1 1
+insert into t1 values (2, 1);
+ERROR 42S22: Unknown column 'at' in 'NEW'
+select * from t1;
+i k
+1 1
+2 1
+update t1 set k = 2 where i = 2;
+ERROR 42S22: Unknown column 'at' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+delete from t1 where i = 2;
+ERROR 42S22: Unknown column 'at' in 'OLD'
+select * from t1;
+i k
+1 1
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, k);
+ERROR 42S22: Unknown column 'at' in 'NEW'
+select * from t1;
+i k
+1 1
+1 2
+insert into t1 select 3, 3;
+ERROR 42S22: Unknown column 'at' in 'NEW'
+select * from t1;
+i k
+1 1
+1 2
+3 3
+update t1, t2 set k = k + 10 where t1.i = t2.i;
+ERROR 42S22: Unknown column 'at' in 'NEW'
+select * from t1;
+i k
+1 11
+1 2
+3 3
+update t1, t2 set k = k + 10 where t1.i = t2.i and k < 3;
+ERROR 42S22: Unknown column 'at' in 'NEW'
+select * from t1;
+i k
+1 11
+1 12
+3 3
+delete t1, t2 from t1 straight_join t2 where t1.i = t2.i;
+ERROR 42S22: Unknown column 'at' in 'OLD'
+select * from t1;
+i k
+1 12
+3 3
+delete t2, t1 from t2 straight_join t1 where t1.i = t2.i;
+ERROR 42S22: Unknown column 'at' in 'OLD'
+select * from t1;
+i k
+3 3
+alter table t1 add primary key (i);
+insert into t1 values (3, 4) on duplicate key update k= k + 10;
+ERROR 42S22: Unknown column 'at' in 'NEW'
+select * from t1;
+i k
+3 13
+replace into t1 values (3, 3);
+ERROR 42S22: Unknown column 'at' in 'NEW'
+select * from t1;
+i k
+3 3
+alter table t1 add ts timestamp default now();
+replace into t1 (i, k) values (3, 13);
+ERROR 42S22: Unknown column 'at' in 'OLD'
+select * from t1;
+i k ts
+drop table t1, t2;
+create table t1 (i int, bt int, k int, key(k)) engine=myisam;
+create table t2 (i int);
+insert into t1 values (1, 1, 1), (2, 2, 2);
+insert into t2 values (1), (2), (3);
+create trigger bi before insert on t1 for each row set @a:= new.bt;
+create trigger bu before update on t1 for each row set @a:= new.bt;
+create trigger bd before delete on t1 for each row set @a:= old.bt;
+alter table t1 drop column bt;
+insert into t1 values (3, 3);
+ERROR 42S22: Unknown column 'bt' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+update t1 set i = 2;
+ERROR 42S22: Unknown column 'bt' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+delete from t1;
+ERROR 42S22: Unknown column 'bt' in 'OLD'
+select * from t1;
+i k
+1 1
+2 2
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, k);
+ERROR 42S22: Unknown column 'bt' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+insert into t1 select 3, 3;
+ERROR 42S22: Unknown column 'bt' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+update t1, t2 set k = k + 10 where t1.i = t2.i;
+ERROR 42S22: Unknown column 'bt' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+update t1, t2 set k = k + 10 where t1.i = t2.i and k < 2;
+ERROR 42S22: Unknown column 'bt' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+delete t1, t2 from t1 straight_join t2 where t1.i = t2.i;
+ERROR 42S22: Unknown column 'bt' in 'OLD'
+select * from t1;
+i k
+1 1
+2 2
+delete t2, t1 from t2 straight_join t1 where t1.i = t2.i;
+ERROR 42S22: Unknown column 'bt' in 'OLD'
+select * from t1;
+i k
+1 1
+2 2
+alter table t1 add primary key (i);
+drop trigger bi;
+insert into t1 values (2, 4) on duplicate key update k= k + 10;
+ERROR 42S22: Unknown column 'bt' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+replace into t1 values (2, 4);
+ERROR 42S22: Unknown column 'bt' in 'NEW'
+select * from t1;
+i k
+1 1
+2 2
+alter table t1 add ts timestamp default now();
+replace into t1 (i, k) values (2, 11);
+ERROR 42S22: Unknown column 'bt' in 'OLD'
+select * from t1;
+i k ts
+1 1 0000-00-00 00:00:00
+2 2 0000-00-00 00:00:00
+drop table t1, t2;
+drop function if exists bug5893;
+create table t1 (col1 int, col2 int);
+insert into t1 values (1, 2);
+create function bug5893 () returns int return 5;
+create trigger t1_bu before update on t1 for each row set new.col1= bug5893();
+drop function bug5893;
+update t1 set col2 = 4;
+ERROR 42000: FUNCTION test.bug5893 does not exist
+drop trigger t1_bu;
+drop table t1;
+set sql_mode='ansi';
+create table t1 ("t1 column" int);
+create trigger t1_bi before insert on t1 for each row set new."t1 column" = 5;
+set sql_mode="";
+insert into t1 values (0);
+create trigger t1_af after insert on t1 for each row set @a=10;
+insert into t1 values (0);
+select * from t1;
+t1 column
+5
+5
+select @a;
+@a
+10
+show triggers;
+Trigger Event Table Statement Timing Created sql_mode
+t1_bi INSERT t1 set new."t1 column" = 5 BEFORE # REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
+t1_af INSERT t1 set @a=10 AFTER #
+drop table t1;
+set sql_mode="traditional";
+create table t1 (a date);
+insert into t1 values ('2004-01-00');
+ERROR 22007: Incorrect date value: '2004-01-00' for column 'a' at row 1
+set sql_mode="";
+create trigger t1_bi before insert on t1 for each row set new.a = '2004-01-00';
+set sql_mode="traditional";
+insert into t1 values ('2004-01-01');
+select * from t1;
+a
+2004-01-00
+set sql_mode=default;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` date default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show triggers;
+Trigger Event Table Statement Timing Created sql_mode
+t1_bi INSERT t1 set new.a = '2004-01-00' BEFORE #
+drop table t1;
+create table t1 (id int);
+create trigger t1_ai after insert on t1 for each row flush tables;
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create trigger t1_ai after insert on t1 for each row flush privileges;
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+create procedure p1() flush tables;
+create trigger t1_ai after insert on t1 for each row call p1();
+insert into t1 values (0);
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+drop procedure p1;
+create procedure p1() flush privileges;
+insert into t1 values (0);
+ERROR 0A000: FLUSH is not allowed in stored function or trigger
+drop procedure p1;
+drop table t1;
+create table t1 (id int, data int, username varchar(16));
+insert into t1 (id, data) values (1, 0);
+create trigger t1_whoupdated before update on t1 for each row
+begin
+declare user varchar(32);
+declare i int;
+select user() into user;
+set NEW.username = user;
+select count(*) from ((select 1) union (select 2)) as d1 into i;
+end|
+update t1 set data = 1;
+update t1 set data = 2;
+drop table t1;
+create table t1 (c1 int, c2 datetime);
+create trigger tr1 before insert on t1 for each row
+begin
+set new.c2= '2004-04-01';
+select 'hello';
+end|
+ERROR 0A000: Not allowed to return a result set from a trigger
+insert into t1 (c1) values (1),(2),(3);
+select * from t1;
+c1 c2
+1 NULL
+2 NULL
+3 NULL
+drop procedure if exists bug11587;
+create procedure bug11587(x char(16))
+begin
+select "hello";
+select "hello again";
+end|
+create trigger tr1 before insert on t1 for each row
+begin
+call bug11587();
+set new.c2= '2004-04-02';
+end|
+insert into t1 (c1) values (4),(5),(6);
+ERROR 0A000: Not allowed to return a result set from a trigger
+select * from t1;
+c1 c2
+1 NULL
+2 NULL
+3 NULL
+drop procedure bug11587;
+drop table t1;
+create table t1 (f1 integer);
+create table t2 (f2 integer);
+create trigger t1_ai after insert on t1
+for each row insert into t2 values (new.f1+1);
+create trigger t2_ai after insert on t2
+for each row insert into t1 values (new.f2+1);
+insert into t1 values (1);
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+select * from t1;
+f1
+1
+select * from t2;
+f2
+2
+drop trigger t1_ai;
+drop trigger t2_ai;
+create trigger t1_bu before update on t1
+for each row insert into t1 values (2);
+update t1 set f1= 10;
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+select * from t1;
+f1
+1
+drop trigger t1_bu;
+create trigger t1_bu before update on t1
+for each row delete from t1 where f1=new.f1;
+update t1 set f1= 10;
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+select * from t1;
+f1
+1
+drop trigger t1_bu;
+create trigger t1_bi before insert on t1
+for each row set new.f1=(select sum(f1) from t1);
+insert into t1 values (3);
+select * from t1;
+f1
+1
+1
+drop trigger t1_bi;
+drop tables t1, t2;
diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result
new file mode 100644
index 00000000000..5988b4f745e
--- /dev/null
+++ b/mysql-test/r/type_bit.result
@@ -0,0 +1,555 @@
+select 0 + b'1';
+0 + b'1'
+1
+select 0 + b'0';
+0 + b'0'
+0
+select 0 + b'000001';
+0 + b'000001'
+1
+select 0 + b'000011';
+0 + b'000011'
+3
+select 0 + b'000101';
+0 + b'000101'
+5
+select 0 + b'000000';
+0 + b'000000'
+0
+select 0 + b'10000000';
+0 + b'10000000'
+128
+select 0 + b'11111111';
+0 + b'11111111'
+255
+select 0 + b'10000001';
+0 + b'10000001'
+129
+select 0 + b'1000000000000000';
+0 + b'1000000000000000'
+32768
+select 0 + b'1111111111111111';
+0 + b'1111111111111111'
+65535
+select 0 + b'1000000000000001';
+0 + b'1000000000000001'
+32769
+drop table if exists t1,t2;
+create table t1 (a bit(65));
+ERROR 42000: Display width out of range for column 'a' (max = 64)
+create table t1 (a bit(0));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bit(1) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a bit(64));
+insert into t1 values
+(b'1111111111111111111111111111111111111111111111111111111111111111'),
+(b'1000000000000000000000000000000000000000000000000000000000000000'),
+(b'0000000000000000000000000000000000000000000000000000000000000001'),
+(b'1010101010101010101010101010101010101010101010101010101010101010'),
+(b'0101010101010101010101010101010101010101010101010101010101010101');
+select hex(a) from t1;
+hex(a)
+FFFFFFFFFFFFFFFF
+8000000000000000
+1
+AAAAAAAAAAAAAAAA
+5555555555555555
+drop table t1;
+create table t1 (a bit);
+insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+select hex(a) from t1;
+hex(a)
+0
+1
+0
+1
+1
+alter table t1 add unique (a);
+ERROR 23000: Duplicate entry '' for key 1
+drop table t1;
+create table t1 (a bit(2));
+insert into t1 values (b'00'), (b'01'), (b'10'), (b'100');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+select a+0 from t1;
+a+0
+0
+1
+2
+3
+alter table t1 add key (a);
+explain select a+0 from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 2 NULL 4 Using index
+select a+0 from t1;
+a+0
+0
+1
+2
+3
+drop table t1;
+create table t1 (a bit(7), b bit(9), key(a, b));
+insert into t1 values
+(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177),
+(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380),
+(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36),
+(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499),
+(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403),
+(44, 307), (68, 454), (57, 135);
+explain select a+0 from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 38 Using index
+select a+0 from t1;
+a+0
+0
+4
+5
+9
+23
+24
+28
+29
+30
+31
+34
+44
+49
+56
+57
+59
+60
+61
+68
+68
+75
+77
+78
+79
+87
+88
+94
+94
+104
+106
+108
+111
+116
+118
+119
+122
+123
+127
+explain select b+0 from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 38 Using index
+select b+0 from t1;
+b+0
+177
+245
+178
+363
+36
+398
+499
+399
+83
+438
+202
+307
+345
+379
+135
+188
+343
+152
+206
+454
+42
+133
+123
+349
+351
+411
+46
+468
+280
+446
+67
+368
+390
+380
+368
+118
+411
+403
+explain select a+0, b+0 from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 38 Using index
+select a+0, b+0 from t1;
+a+0 b+0
+0 177
+4 245
+5 178
+9 363
+23 36
+24 398
+28 499
+29 399
+30 83
+31 438
+34 202
+44 307
+49 345
+56 379
+57 135
+59 188
+60 343
+61 152
+68 206
+68 454
+75 42
+77 133
+78 123
+79 349
+87 351
+88 411
+94 46
+94 468
+104 280
+106 446
+108 67
+111 368
+116 390
+118 380
+119 368
+122 118
+123 411
+127 403
+explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 2 NULL 27 Using where; Using index; Using filesort
+select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+a+0 b+0
+44 307
+49 345
+56 379
+60 343
+68 206
+68 454
+79 349
+87 351
+88 411
+94 468
+104 280
+106 446
+111 368
+116 390
+118 380
+119 368
+123 411
+127 403
+explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 2 NULL 8 Using where; Using index; Using filesort
+select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+a+0 b+0
+57 135
+61 152
+59 188
+68 206
+44 307
+60 343
+49 345
+56 379
+68 454
+set @@max_length_for_sort_data=0;
+select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+a+0 b+0
+57 135
+61 152
+59 188
+68 206
+44 307
+60 343
+49 345
+56 379
+68 454
+select hex(min(a)) from t1;
+hex(min(a))
+0
+select hex(min(b)) from t1;
+hex(min(b))
+24
+select hex(min(a)), hex(max(a)), hex(min(b)), hex(max(b)) from t1;
+hex(min(a)) hex(max(a)) hex(min(b)) hex(max(b))
+0 7F 24 1F3
+drop table t1;
+create table t1 (a int not null, b bit, c bit(9), key(a, b, c));
+insert into t1 values
+(4, NULL, 1), (4, 0, 3), (2, 1, 4), (1, 1, 100), (4, 0, 23), (4, 0, 54),
+(56, 0, 22), (4, 1, 100), (23, 0, 1), (4, 0, 34);
+select a+0, b+0, c+0 from t1;
+a+0 b+0 c+0
+1 1 100
+2 1 4
+4 NULL 1
+4 0 3
+4 0 23
+4 0 34
+4 0 54
+4 1 100
+23 0 1
+56 0 22
+select hex(min(b)) from t1 where a = 4;
+hex(min(b))
+0
+select hex(min(c)) from t1 where a = 4 and b = 0;
+hex(min(c))
+3
+select hex(max(b)) from t1;
+hex(max(b))
+1
+select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2;
+a+0 b+0 c+0
+4 0 3
+4 0 23
+select a+0, b+0, c+0 from t1 where a = 4 and b = 1;
+a+0 b+0 c+0
+4 1 100
+select a+0, b+0, c+0 from t1 where a = 4 and b = 1 and c=100;
+a+0 b+0 c+0
+4 1 100
+select a+0, b+0, c+0 from t1 order by b desc;
+a+0 b+0 c+0
+2 1 4
+1 1 100
+4 1 100
+4 0 3
+4 0 23
+4 0 54
+56 0 22
+23 0 1
+4 0 34
+4 NULL 1
+select a+0, b+0, c+0 from t1 order by c;
+a+0 b+0 c+0
+4 NULL 1
+23 0 1
+4 0 3
+2 1 4
+56 0 22
+4 0 23
+4 0 34
+4 0 54
+1 1 100
+4 1 100
+drop table t1;
+create table t1(a bit(2), b bit(2));
+insert into t1 (a) values (0x01), (0x03), (0x02);
+update t1 set b= concat(a);
+select a+0, b+0 from t1;
+a+0 b+0
+1 1
+3 3
+2 2
+drop table t1;
+create table t1 (a bit(7), key(a));
+insert into t1 values (44), (57);
+select a+0 from t1;
+a+0
+44
+57
+drop table t1;
+create table t1 (a bit(3), b bit(12));
+insert into t1 values (7,(1<<12)-2), (0x01,0x01ff);
+select hex(a),hex(b) from t1;
+hex(a) hex(b)
+7 FFE
+1 1FF
+select hex(concat(a)),hex(concat(b)) from t1;
+hex(concat(a)) hex(concat(b))
+07 0FFE
+01 01FF
+drop table t1;
+create table t1(a int, b bit not null);
+alter table t1 add primary key (a);
+drop table t1;
+create table t1 (a bit(19), b bit(5));
+insert into t1 values (1000, 10), (3, 8), (200, 6), (2303, 2), (12345, 4), (1, 0);
+select a+0, b+0 from t1;
+a+0 b+0
+1000 10
+3 8
+200 6
+2303 2
+12345 4
+1 0
+alter table t1 engine=heap;
+select a+0, b+0 from t1;
+a+0 b+0
+1000 10
+3 8
+200 6
+2303 2
+12345 4
+1 0
+alter table t1 add key(a, b);
+select a+0, b+0 from t1;
+a+0 b+0
+1000 10
+3 8
+200 6
+2303 2
+12345 4
+1 0
+alter table t1 engine=myisam;
+select a+0, b+0 from t1;
+a+0 b+0
+1 0
+3 8
+200 6
+1000 10
+2303 2
+12345 4
+create table t2 engine=heap select * from t1;
+select a+0, b+0 from t2;
+a+0 b+0
+1 0
+3 8
+200 6
+1000 10
+2303 2
+12345 4
+drop table t1;
+create table t1 select * from t2;
+select a+0, b+0 from t1;
+a+0 b+0
+1 0
+3 8
+200 6
+1000 10
+2303 2
+12345 4
+drop table t1, t2;
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+g bit(1) NOT NULL default 1, h char(1) default 'a');
+insert into t1 set a=1;
+select hex(g), h from t1;
+hex(g) h
+1 a
+drop table t1;
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+g bit(1) NOT NULL default 1);
+insert into t1 set a=1;
+select hex(g) from t1;
+hex(g)
+1
+drop table t1;
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+h char(1) default 'a') engine=myisam;
+insert into t1 set a=1;
+select h from t1;
+h
+a
+drop table t1;
+create table t1 (a bit(8)) engine=heap;
+insert into t1 values ('1111100000');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select a+0 from t1;
+a+0
+255
+drop table t1;
+create table t1 (a bit(7));
+insert into t1 values (120), (0), (111);
+select a+0 from t1 union select a+0 from t1;
+a+0
+120
+0
+111
+select a+0 from t1 union select NULL;
+a+0
+120
+0
+111
+NULL
+select NULL union select a+0 from t1;
+NULL
+NULL
+120
+0
+111
+create table t2 select a from t1 union select a from t1;
+select a+0 from t2;
+a+0
+120
+0
+111
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` bit(7) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1, t2;
+create table t1 (id1 int(11), b1 bit(1));
+create table t2 (id2 int(11), b2 bit(1));
+insert into t1 values (1, 1), (2, 0), (3, 1);
+insert into t2 values (2, 1), (3, 0), (4, 0);
+create algorithm=undefined view v1 as
+select b1+0, b2+0 from t1, t2 where id1 = id2 and b1 = 0
+union
+select b1+0, b2+0 from t1, t2 where id1 = id2 and b2 = 1;
+select * from v1;
+b1+0 b2+0
+0 1
+drop table t1, t2;
+drop view v1;
+create table t1(a bit(4));
+insert into t1(a) values (1), (2), (5), (4), (3);
+insert into t1 select * from t1;
+select a+0 from t1;
+a+0
+1
+2
+5
+4
+3
+1
+2
+5
+4
+3
+drop table t1;
+create table t1 (a1 int(11), b1 bit(2));
+create table t2 (a2 int(11), b2 bit(2));
+insert into t1 values (1, 1), (2, 0), (3, 1), (4, 2);
+insert into t2 values (2, 1), (3, 0), (4, 1), (5, 2);
+select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2;
+a1 a2 b1+0 b2+0
+2 2 0 1
+3 3 1 0
+4 4 2 1
+select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2 order by a1;
+a1 a2 b1+0 b2+0
+2 2 0 1
+3 3 1 0
+4 4 2 1
+select a1, a2, b1+0, b2+0 from t1 join t2 on b1 = b2;
+a1 a2 b1+0 b2+0
+1 2 1 1
+3 2 1 1
+2 3 0 0
+1 4 1 1
+3 4 1 1
+4 5 2 2
+select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1;
+sum(a1) b1+0 b2+0
+2 0 0
+4 2 2
+8 1 1
diff --git a/mysql-test/r/type_bit_innodb.result b/mysql-test/r/type_bit_innodb.result
new file mode 100644
index 00000000000..8d9c9756a33
--- /dev/null
+++ b/mysql-test/r/type_bit_innodb.result
@@ -0,0 +1,404 @@
+select 0 + b'1';
+0 + b'1'
+1
+select 0 + b'0';
+0 + b'0'
+0
+select 0 + b'000001';
+0 + b'000001'
+1
+select 0 + b'000011';
+0 + b'000011'
+3
+select 0 + b'000101';
+0 + b'000101'
+5
+select 0 + b'000000';
+0 + b'000000'
+0
+select 0 + b'10000000';
+0 + b'10000000'
+128
+select 0 + b'11111111';
+0 + b'11111111'
+255
+select 0 + b'10000001';
+0 + b'10000001'
+129
+select 0 + b'1000000000000000';
+0 + b'1000000000000000'
+32768
+select 0 + b'1111111111111111';
+0 + b'1111111111111111'
+65535
+select 0 + b'1000000000000001';
+0 + b'1000000000000001'
+32769
+drop table if exists t1;
+create table t1 (a bit(65)) engine=innodb;
+ERROR 42000: Display width out of range for column 'a' (max = 64)
+create table t1 (a bit(0)) engine=innodb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bit(1) default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a bit(64)) engine=innodb;
+insert into t1 values
+(b'1111111111111111111111111111111111111111111111111111111111111111'),
+(b'1000000000000000000000000000000000000000000000000000000000000000'),
+(b'0000000000000000000000000000000000000000000000000000000000000001'),
+(b'1010101010101010101010101010101010101010101010101010101010101010'),
+(b'0101010101010101010101010101010101010101010101010101010101010101');
+select hex(a) from t1;
+hex(a)
+FFFFFFFFFFFFFFFF
+8000000000000000
+1
+AAAAAAAAAAAAAAAA
+5555555555555555
+drop table t1;
+create table t1 (a bit) engine=innodb;
+insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+select hex(a) from t1;
+hex(a)
+0
+1
+0
+1
+1
+alter table t1 add unique (a);
+ERROR 23000: Duplicate entry '' for key 1
+drop table t1;
+create table t1 (a bit(2)) engine=innodb;
+insert into t1 values (b'00'), (b'01'), (b'10'), (b'100');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+select a+0 from t1;
+a+0
+0
+1
+2
+3
+alter table t1 add key (a);
+explain select a+0 from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 2 NULL 4 Using index
+select a+0 from t1;
+a+0
+0
+1
+2
+3
+drop table t1;
+create table t1 (a bit(7), b bit(9), key(a, b)) engine=innodb;
+insert into t1 values
+(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177),
+(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380),
+(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36),
+(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499),
+(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403),
+(44, 307), (68, 454), (57, 135);
+explain select a+0 from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 38 Using index
+select a+0 from t1;
+a+0
+0
+4
+5
+9
+23
+24
+28
+29
+30
+31
+34
+44
+49
+56
+57
+59
+60
+61
+68
+68
+75
+77
+78
+79
+87
+88
+94
+94
+104
+106
+108
+111
+116
+118
+119
+122
+123
+127
+explain select b+0 from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 38 Using index
+select b+0 from t1;
+b+0
+177
+245
+178
+363
+36
+398
+499
+399
+83
+438
+202
+307
+345
+379
+135
+188
+343
+152
+206
+454
+42
+133
+123
+349
+351
+411
+46
+468
+280
+446
+67
+368
+390
+380
+368
+118
+411
+403
+explain select a+0, b+0 from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 38 Using index
+select a+0, b+0 from t1;
+a+0 b+0
+0 177
+4 245
+5 178
+9 363
+23 36
+24 398
+28 499
+29 399
+30 83
+31 438
+34 202
+44 307
+49 345
+56 379
+57 135
+59 188
+60 343
+61 152
+68 206
+68 454
+75 42
+77 133
+78 123
+79 349
+87 351
+88 411
+94 46
+94 468
+104 280
+106 446
+108 67
+111 368
+116 390
+118 380
+119 368
+122 118
+123 411
+127 403
+explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 2 NULL 19 Using where; Using index; Using filesort
+select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+a+0 b+0
+44 307
+49 345
+56 379
+60 343
+68 206
+68 454
+79 349
+87 351
+88 411
+94 468
+104 280
+106 446
+111 368
+116 390
+118 380
+119 368
+123 411
+127 403
+explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 2 NULL 8 Using where; Using index; Using filesort
+select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+a+0 b+0
+57 135
+61 152
+59 188
+68 206
+44 307
+60 343
+49 345
+56 379
+68 454
+set @@max_length_for_sort_data=0;
+select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+a+0 b+0
+57 135
+61 152
+59 188
+68 206
+44 307
+60 343
+49 345
+56 379
+68 454
+select hex(min(a)) from t1;
+hex(min(a))
+0
+select hex(min(b)) from t1;
+hex(min(b))
+24
+select hex(min(a)), hex(max(a)), hex(min(b)), hex(max(b)) from t1;
+hex(min(a)) hex(max(a)) hex(min(b)) hex(max(b))
+0 7F 24 1F3
+drop table t1;
+create table t1 (a int not null, b bit, c bit(9), key(a, b, c)) engine=innodb;
+insert into t1 values
+(4, NULL, 1), (4, 0, 3), (2, 1, 4), (1, 1, 100), (4, 0, 23), (4, 0, 54),
+(56, 0, 22), (4, 1, 100), (23, 0, 1), (4, 0, 34);
+select a+0, b+0, c+0 from t1;
+a+0 b+0 c+0
+1 1 100
+2 1 4
+4 NULL 1
+4 0 3
+4 0 23
+4 0 34
+4 0 54
+4 1 100
+23 0 1
+56 0 22
+select hex(min(b)) from t1 where a = 4;
+hex(min(b))
+0
+select hex(min(c)) from t1 where a = 4 and b = 0;
+hex(min(c))
+3
+select hex(max(b)) from t1;
+hex(max(b))
+1
+select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2;
+a+0 b+0 c+0
+4 0 3
+4 0 23
+select a+0, b+0, c+0 from t1 where a = 4 and b = 1;
+a+0 b+0 c+0
+4 1 100
+select a+0, b+0, c+0 from t1 where a = 4 and b = 1 and c=100;
+a+0 b+0 c+0
+4 1 100
+select a+0, b+0, c+0 from t1 order by b desc;
+a+0 b+0 c+0
+2 1 4
+1 1 100
+4 1 100
+4 0 3
+4 0 23
+4 0 54
+56 0 22
+23 0 1
+4 0 34
+4 NULL 1
+select a+0, b+0, c+0 from t1 order by c;
+a+0 b+0 c+0
+4 NULL 1
+23 0 1
+4 0 3
+2 1 4
+56 0 22
+4 0 23
+4 0 34
+4 0 54
+1 1 100
+4 1 100
+drop table t1;
+create table t1(a bit(2), b bit(2)) engine=innodb;
+insert into t1 (a) values (0x01), (0x03), (0x02);
+update t1 set b= concat(a);
+select a+0, b+0 from t1;
+a+0 b+0
+1 1
+3 3
+2 2
+drop table t1;
+create table t1 (a bit(7), key(a)) engine=innodb;
+insert into t1 values (44), (57);
+select a+0 from t1;
+a+0
+44
+57
+drop table t1;
+create table t1 (a bit(3), b bit(12)) engine=innodb;
+insert into t1 values (7,(1<<12)-2), (0x01,0x01ff);
+select hex(a),hex(b) from t1;
+hex(a) hex(b)
+7 FFE
+1 1FF
+select hex(concat(a)),hex(concat(b)) from t1;
+hex(concat(a)) hex(concat(b))
+07 0FFE
+01 01FF
+drop table t1;
+create table t1(a int, b bit not null) engine=innodb;
+alter table t1 add primary key (a);
+drop table t1;
+create table t1 (a bit, b bit(10)) engine=innodb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bit(1) default NULL,
+ `b` bit(10) default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t1 engine=heap;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bit(1) default NULL,
+ `b` bit(10) default NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+alter table t1 engine=innodb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bit(1) default NULL,
+ `b` bit(10) default NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 6b4b54fbb66..193ed298339 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -7,14 +7,16 @@ b text YES NULL
c tinyblob YES NULL
d mediumtext YES NULL
e longtext YES NULL
-CREATE TABLE t2 (a char(257), b varbinary(70000), c varchar(70000000));
+CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
Warnings:
-Warning 1246 Converting column 'a' from CHAR to TEXT
-Warning 1246 Converting column 'b' from CHAR to BLOB
-Warning 1246 Converting column 'c' from CHAR to TEXT
+Note 1246 Converting column 'b' from VARBINARY to BLOB
+Note 1246 Converting column 'c' from VARCHAR to TEXT
+CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
+Warnings:
+Note 1246 Converting column 'c' from VARCHAR to TEXT
show columns from t2;
Field Type Null Key Default Extra
-a text YES NULL
+a char(255) YES NULL
b mediumblob YES NULL
c longtext YES NULL
create table t3 (a long, b long byte);
@@ -24,10 +26,18 @@ t3 CREATE TABLE `t3` (
`a` mediumtext,
`b` mediumblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
-drop table t1,t2,t3
-#;
+show create TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c` mediumtext character set utf8 NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1,t2,t3,t4;
CREATE TABLE t1 (a char(257) default "hello");
ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead
+CREATE TABLE t2 (a char(256));
+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead
+CREATE TABLE t1 (a varchar(70000) default "hello");
+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT 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;
@@ -71,16 +81,16 @@ lock tables t1 READ;
show full fields from t1;
Field Type Collation Null Key Default Extra Privileges Comment
t text latin1_swedish_ci YES NULL #
-c varchar(10) latin1_swedish_ci YES NULL #
+c char(10) latin1_swedish_ci YES NULL #
b blob NULL YES NULL #
-d varbinary(10) NULL YES NULL #
+d binary(10) NULL YES NULL #
lock tables t1 WRITE;
show full fields from t1;
Field Type Collation Null Key Default Extra Privileges Comment
t text latin1_swedish_ci YES NULL #
-c varchar(10) latin1_swedish_ci YES NULL #
+c char(10) latin1_swedish_ci YES NULL #
b blob NULL YES NULL #
-d varbinary(10) NULL YES NULL #
+d binary(10) NULL YES NULL #
unlock tables;
select t from t1 where t like "hello";
t
@@ -492,7 +502,7 @@ select foobar, boggle from t1 where foobar = 'fish' and boggle = 10;
foobar boggle
fish 10
drop table t1;
-create table t1 (id integer auto_increment unique,imagem LONGBLOB not null);
+create table t1 (id integer auto_increment unique,imagem LONGBLOB not null default '');
insert into t1 (id) values (1);
select
charset(load_file('../../std_data/words.dat')),
@@ -520,6 +530,11 @@ l longblob NULL YES NULL #
drop table t1;
create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy ');
+ERROR 23000: Duplicate entry 'Chevy ' for key 2
+insert into t1 (txt) values ('Chevy'), ('CHEVY');
+ERROR 23000: Duplicate entry 'Chevy' for key 2
+alter table t1 drop index txt_index, add index txt_index (txt(20));
+insert into t1 (txt) values ('Chevy ');
select * from t1 where txt='Chevy';
id txt
1 Chevy
@@ -589,7 +604,7 @@ id txt
2 Chevy
3 Ford
drop table t1;
-create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20)));
+create table t1 (id integer primary key auto_increment, txt text, index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL;
id txt
@@ -688,3 +703,18 @@ select max(i) from t1 where c = '';
max(i)
4
drop table t1;
+create table t1 (a int, b int, c tinyblob, d int, e int);
+alter table t1 add primary key (a,b,c(255),d);
+alter table t1 add key (a,b,d,e);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) NOT NULL default '0',
+ `c` tinyblob NOT NULL,
+ `d` int(11) NOT NULL default '0',
+ `e` int(11) default NULL,
+ PRIMARY KEY (`a`,`b`,`c`(255),`d`),
+ KEY `a` (`a`,`b`,`d`,`e`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index 3428b5969d9..e88eebffb55 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -99,7 +99,7 @@ DROP TABLE t1, t2, t3;
CREATE TABLE t1 (y YEAR);
INSERT INTO t1 VALUES ('abc');
Warnings:
-Warning 1265 Data truncated for column 'y' at row 1
+Warning 1264 Out of range value adjusted for column 'y' at row 1
SELECT * FROM t1;
y
0000
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index f313a6b934b..85f899be5d8 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -52,7 +52,7 @@ t
truncate table t1;
insert into t1 values("2003-0303 12:13:14");
Warnings:
-Warning 1264 Data truncated; out of range for column 't' at row 1
+Warning 1264 Out of range value adjusted for column 't' at row 1
select * from t1;
t
0000-00-00 00:00:00
@@ -101,7 +101,7 @@ date numfacture expedition
0000-00-00 00:00:00 1212 0001-00-00 00:00:00
EXPLAIN SELECT * FROM t1 WHERE expedition='0001-00-00 00:00:00';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref expedition expedition 8 const 1 Using where
+1 SIMPLE t1 ref expedition expedition 8 const 1
drop table t1;
create table t1 (a datetime not null, b datetime not null);
insert into t1 values (now(), now());
@@ -113,12 +113,12 @@ create table t1 (t datetime);
insert into t1 values (20030102030460),(20030102036301),(20030102240401),
(20030132030401),(20031302030401),(100001202030401);
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
-Warning 1265 Data truncated for column 't' at row 6
+Warning 1264 Out of range value adjusted for column 't' at row 1
+Warning 1264 Out of range value adjusted for column 't' at row 2
+Warning 1264 Out of range value adjusted for column 't' at row 3
+Warning 1264 Out of range value adjusted for column 't' at row 4
+Warning 1264 Out of range value adjusted for column 't' at row 5
+Warning 1264 Out of range value adjusted for column 't' at row 6
select * from t1;
t
0000-00-00 00:00:00
@@ -132,12 +132,12 @@ insert into t1 values
("2003-01-02 03:04:60"),("2003-01-02 03:63:01"),("2003-01-02 24:04:01"),
("2003-01-32 03:04:01"),("2003-13-02 03:04:01"), ("10000-12-02 03:04:00");
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
-Warning 1264 Data truncated; out of range for column 't' at row 6
+Warning 1264 Out of range value adjusted for column 't' at row 1
+Warning 1264 Out of range value adjusted for column 't' at row 2
+Warning 1264 Out of range value adjusted for column 't' at row 3
+Warning 1264 Out of range value adjusted for column 't' at row 4
+Warning 1264 Out of range value adjusted for column 't' at row 5
+Warning 1264 Out of range value adjusted for column 't' at row 6
select * from t1;
t
0000-00-00 00:00:00
@@ -149,8 +149,8 @@ t
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
+Warning 1264 Out of range value adjusted for column 't' at row 1
+Warning 1264 Out of range value adjusted for column 't' at row 2
select * from t1;
t
0000-00-00 00:00:00
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index a9dcabd121e..15f9b839994 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -1,4 +1,4 @@
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1, t2;
SET SQL_WARNINGS=1;
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
@@ -156,42 +156,62 @@ insert into t1 values ("0.0"),("-0.0"),("+0.0"),("01.0"),("+01.0"),("-01.0");
insert into t1 values ("-.1"),("+.1"),(".1");
insert into t1 values ("00000000000001"),("+0000000000001"),("-0000000000001");
insert into t1 values ("+111111111.11"),("111111111.11"),("-11111111.11");
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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 1265 Data truncated for column 'a' at row 2
-Warning 1264 Data truncated; out of range for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Note 1265 Data truncated for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+insert into t1 values ("1e+4294967296"),("1e-4294967296");
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Note 1265 Data truncated for column 'a' at row 2
+insert into t1 values ("1e+18446744073709551615"),("1e+18446744073709551616"),("1e-9223372036854775807"),("1e-9223372036854775809");
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1366 Incorrect decimal value: '1e+18446744073709551616' for column 'a' at row 2
+Note 1265 Data truncated for column 'a' at row 3
+Warning 1366 Incorrect decimal value: '1e-9223372036854775809' for column 'a' at row 4
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
+Note 1265 Data truncated for column 'a' at row 1
+Note 1265 Data truncated for column 'a' at row 3
select * from t1;
a
0.00
--0.00
-+0.00
-01.00
-+01.00
--01.00
+0.00
+0.00
+1.00
+1.00
+-1.00
-0.10
-+0.10
0.10
-000000001.00
-+00000001.00
--00000001.00
-111111111.11
-111111111.11
+0.10
+1.00
+1.00
+-1.00
+99999999.99
+99999999.99
-11111111.11
-99999999.99
-999999999.99
-999999999.99
-999999999.99
+99999999.99
+99999999.99
+99999999.99
0.00
-99999999.99
+99999999.99
+0.00
+99999999.99
+0.00
+0.00
+0.00
123.40
12340.00
1.23
@@ -201,45 +221,46 @@ 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 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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 Out of range value adjusted 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 Out of range value adjusted 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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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 1265 Data truncated for column 'a' at row 2
-Warning 1264 Data truncated; out of range for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Note 1265 Data truncated for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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
+Note 1265 Data truncated for column 'a' at row 1
+Note 1265 Data truncated for column 'a' at row 3
select * from t1;
a
0.00
0.00
-+0.00
-01.00
-+01.00
+0.00
+1.00
+1.00
0.00
0.00
-+0.10
0.10
-00000001.00
-+0000001.00
+0.10
+1.00
+1.00
0.00
99999999.99
99999999.99
@@ -259,32 +280,33 @@ 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 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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 Out of range value adjusted 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 Out of range value adjusted 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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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 1265 Data truncated for column 'a' at row 2
-Warning 1264 Data truncated; out of range for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Note 1265 Data truncated for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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
+Note 1265 Data truncated for column 'a' at row 1
+Note 1265 Data truncated for column 'a' at row 3
select * from t1;
a
00000000.00
@@ -319,20 +341,27 @@ insert into t1 values (0.0),("-0.0"),(+0.0),(01.0),(+01.0),(-01.0);
insert into t1 values (-.1),(+.1),(.1);
insert into t1 values (00000000000001),(+0000000000001),(-0000000000001);
insert into t1 values (+111111111.11),(111111111.11),(-11111111.11);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted 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 Out of range value adjusted for column 'a' at row 1
+Note 1265 Data truncated for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 3
insert into t1 values (123.4e0),(123.4e+2),(123.4e-2),(123e1),(123e+0);
+Warnings:
+Note 1265 Data truncated for column 'a' at row 3
+insert into t1 values (MID("987",1,2)),("987 "),("987.6e+2 ");
select * from t1;
a
0.00
--0.00
+0.00
0.00
1.00
1.00
@@ -343,13 +372,13 @@ a
1.00
1.00
-1.00
-111111111.11
-111111111.11
+99999999.99
+99999999.99
-11111111.11
-99999999.99
-999999999.99
-999999999.99
-999999999.99
+99999999.99
+99999999.99
+99999999.99
0.00
-99999999.99
123.40
@@ -357,44 +386,48 @@ a
1.23
1230.00
123.00
+98.00
+987.00
+98760.00
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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 6
+Warning 1264 Out of range value adjusted for column 'a' at row 7
select * from t1;
a
-9999999999
-1
-+1
-01
-+0000000001
-12345678901
-99999999999
+1
+1
+1
+9999999999
+9999999999
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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 7
select * from t1;
a
0
0
-+1
-01
-+000000001
+1
+1
+1
1234567890
9999999999
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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 7
select * from t1;
a
0000000000
@@ -408,9 +441,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 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 7
select * from t1;
a
0000000000
@@ -424,19 +457,17 @@ drop table t1;
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 Out of range value adjusted for column 'a' at row 1
select * from t1;
a
-99999999999
+9999999999
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 Out of range value adjusted for column 'a' at row 1
select * from t1;
a
-99999999999
+9999999999
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
@@ -445,75 +476,70 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
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
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;
+ERROR 42000: Scale may not be larger than the precision (column 'a_dec').
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;
a
1.000
-+1.000
+1.000
+-1.000
+1.000
+1.000
-1.000
-00001.000
-+0001.000
--0001.000
10.000
-+10.000
+10.000
+-10.000
+10.000
+10.000
-10.000
-00010.000
-+0010.000
--0010.000
100.000
-+100.000
+100.000
-100.000
-00100.000
-+0100.000
--0100.000
+100.000
+100.000
+-100.000
+1000.000
1000.000
-+1000.000
-1000.000
-01000.000
-+1000.000
+1000.000
+1000.000
-1000.000
-10000.000
-10000.000
+9999.999
+9999.999
-9999.999
-10000.000
-10000.000
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
-99999.999
-99999.999
+9999.999
+9999.999
-9999.999
drop table t1;
create table t1(a decimal(7,3) unsigned);
@@ -521,22 +547,22 @@ insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000
select * from t1;
a
1.000
-+1.000
+1.000
0.000
-0001.000
-+001.000
+1.000
+1.000
0.000
10.000
-+10.000
+10.000
0.000
-0010.000
-+010.000
+10.000
+10.000
0.000
100.000
-+100.000
+100.000
0.000
-0100.000
-+100.000
+100.000
+100.000
0.000
1000.000
1000.000
@@ -646,3 +672,92 @@ a
9999.999
0000.000
drop table t1;
+CREATE TABLE t1
+(EMPNUM CHAR(3) NOT NULL,
+HOURS DECIMAL(5));
+CREATE TABLE t2
+(EMPNUM CHAR(3) NOT NULL,
+HOURS BIGINT);
+INSERT INTO t1 VALUES ('E1',40);
+INSERT INTO t1 VALUES ('E8',NULL);
+INSERT INTO t2 VALUES ('E1',40);
+SELECT EMPNUM FROM t1 WHERE HOURS IN (SELECT HOURS FROM t2);
+EMPNUM
+E1
+SELECT EMPNUM FROM t1 WHERE HOURS IN (SELECT HOURS FROM t1);
+EMPNUM
+E1
+DROP TABLE t1,t2;
+create table t1 (d decimal(64,0));
+insert into t1 values (1);
+select * from t1;
+d
+1
+drop table t1;
+create table t1 (d decimal(5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` decimal(5,0) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (d decimal);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` decimal(10,0) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (d decimal(66,0));
+ERROR 42000: Too big precision 66 specified for column 'd'. Maximum is 65.
+CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2));
+INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
+(2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
+(2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
+(4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
+(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
+(6, 0.00, 0.00), (6, -51.40, 0.00);
+SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1 GROUP BY i HAVING a <> b;
+i a b
+6 -51.40 0.00
+SELECT i, ROUND(SUM(d1), 2) AS a, ROUND(SUM(d2), 2) AS b FROM t1 GROUP BY i
+HAVING a <> b;
+i a b
+6 -51.40 0.00
+drop table t1;
+create table t1 (c1 varchar(100), c2 longtext);
+insert into t1 set c1= 'non PS, 1.0 as constant', c2=1.0;
+prepare stmt from "insert into t1 set c1='PS, 1.0 as constant ', c2=1.0";
+execute stmt;
+set @a=1.0;
+insert into t1 set c1='non PS, 1.0 in parameter', c2=@a;
+prepare stmt from "insert into t1 set c1='PS, 1.0 in parameter ', c2=?";
+execute stmt using @a;
+select * from t1;
+c1 c2
+non PS, 1.0 as constant 1.0
+PS, 1.0 as constant 1.0
+non PS, 1.0 in parameter 1.0
+PS, 1.0 in parameter 1.0
+deallocate prepare stmt;
+drop table t1;
+create table t1 (
+strippedproductid char(15) not null default '',
+zlevelprice decimal(10,2) default null,
+primary key (strippedproductid)
+);
+create table t2 (
+productid char(15) not null default '',
+zlevelprice char(21) default null,
+primary key (productid)
+);
+insert into t1 values ('002trans','49.99');
+insert into t1 values ('003trans','39.98');
+insert into t1 values ('004trans','31.18');
+insert INTO t2 SELECT * FROM t1;
+select * from t2;
+productid zlevelprice
+002trans 49.99
+003trans 39.98
+004trans 31.18
+drop table t1, t2;
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index ab3c441a7e2..02ba3c7ebd3 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1626,7 +1626,7 @@ create table t1 (a enum (' ','a','b') not null);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` enum('','a','b') NOT NULL default ''
+ `a` enum('','a','b') NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a enum (' ','a','b ') not null default 'b ');
@@ -1654,7 +1654,7 @@ set names latin1;
create table t1 (a enum(0xE4, '1', '2') not null default 0xE4);
show columns from t1;
Field Type Null Key Default Extra
-a enum('ä','1','2') ä
+a enum('ä','1','2') NO ä
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -1670,12 +1670,12 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) default '1',
- `b` enum('value','öäü_value','ÊÃÕ') NOT NULL default 'value'
+ `b` enum('value','öäü_value','ÊÃÕ') NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
show columns from t1;
Field Type Null Key Default Extra
a int(11) YES 1
-b enum('value','öäü_value','ÊÃÕ') value
+b enum('value','öäü_value','ÊÃÕ') NO
drop table t1;
CREATE TABLE t1 (c enum('a', 'A') BINARY);
INSERT INTO t1 VALUES ('a'),('A');
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index 319a957498b..d243985332e 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -24,8 +24,8 @@ f1 float NULL YES NULL #
f2 double NULL YES NULL #
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 Out of range value adjusted for column 'f1' at row 7
+Warning 1264 Out of range value adjusted 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
@@ -72,7 +72,7 @@ select a from t1 order by a;
a
-0.010
-0.002
--0.000
+0.000
0.000
1.000
select min(a) from t1;
@@ -103,7 +103,7 @@ select max(a),min(a),avg(a) from t1;
max(a) min(a) avg(a)
1 1 1
drop table t1;
-create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6));
+create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(7,6));
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
f float NULL YES NULL #
@@ -125,7 +125,7 @@ select a from t1 order by a;
a
-0.010
-0.002
--0.000
+0.000
0.000
1.000
select min(a) from t1;
@@ -133,17 +133,7 @@ min(a)
-0.010
drop table t1;
create table t1 (a float(200,100), b double(200,100));
-insert t1 values (1.0, 2.0);
-select * from t1;
-a b
-1.000000000000000000000000000000 2.000000000000000000000000000000
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` float(200,30) default NULL,
- `b` double(200,30) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-drop table t1;
+ERROR 42000: Too big scale 100 specified for column 'a'. Maximum is 30.
create table t1 (c20 char);
insert into t1 values (5000.0);
Warnings:
@@ -159,7 +149,7 @@ create table t1 (d1 double, d2 double unsigned);
insert into t1 set d1 = -1.0;
update t1 set d2 = d1;
Warnings:
-Warning 1264 Data truncated; out of range for column 'd2' at row 1
+Warning 1264 Out of range value adjusted for column 'd2' at row 1
select * from t1;
d1 d2
-1 0
@@ -167,12 +157,12 @@ drop table t1;
create table t1 (f float(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
Warnings:
-Warning 1264 Data truncated; out of range for column 'f' at row 1
-Warning 1264 Data truncated; out of range for column 'f' at row 2
-Warning 1264 Data truncated; out of range for column 'f' at row 3
-Warning 1264 Data truncated; out of range for column 'f' at row 4
-Warning 1264 Data truncated; out of range for column 'f' at row 5
-Warning 1264 Data truncated; out of range for column 'f' at row 6
+Warning 1264 Out of range value adjusted for column 'f' at row 1
+Warning 1264 Out of range value adjusted for column 'f' at row 2
+Warning 1264 Out of range value adjusted for column 'f' at row 3
+Warning 1264 Out of range value adjusted for column 'f' at row 4
+Warning 1264 Out of range value adjusted for column 'f' at row 5
+Warning 1264 Out of range value adjusted for column 'f' at row 6
select * from t1;
f
-9.999
@@ -185,12 +175,12 @@ drop table if exists t1;
create table t1 (f double(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
Warnings:
-Warning 1264 Data truncated; out of range for column 'f' at row 1
-Warning 1264 Data truncated; out of range for column 'f' at row 2
-Warning 1264 Data truncated; out of range for column 'f' at row 3
-Warning 1264 Data truncated; out of range for column 'f' at row 4
-Warning 1264 Data truncated; out of range for column 'f' at row 5
-Warning 1264 Data truncated; out of range for column 'f' at row 6
+Warning 1264 Out of range value adjusted for column 'f' at row 1
+Warning 1264 Out of range value adjusted for column 'f' at row 2
+Warning 1264 Out of range value adjusted for column 'f' at row 3
+Warning 1264 Out of range value adjusted for column 'f' at row 4
+Warning 1264 Out of range value adjusted for column 'f' at row 5
+Warning 1264 Out of range value adjusted for column 'f' at row 6
select * from t1;
f
-9.999
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
new file mode 100644
index 00000000000..d821339a229
--- /dev/null
+++ b/mysql-test/r/type_newdecimal.result
@@ -0,0 +1,1021 @@
+drop table if exists t1;
+select 1.1 IN (1.0, 1.2);
+1.1 IN (1.0, 1.2)
+0
+select 1.1 IN (1.0, 1.2, 1.1, 1.4, 0.5);
+1.1 IN (1.0, 1.2, 1.1, 1.4, 0.5)
+1
+select 1.1 IN (1.0, 1.2, NULL, 1.4, 0.5);
+1.1 IN (1.0, 1.2, NULL, 1.4, 0.5)
+NULL
+select 0.5 IN (1.0, 1.2, NULL, 1.4, 0.5);
+0.5 IN (1.0, 1.2, NULL, 1.4, 0.5)
+1
+select 1 IN (1.11, 1.2, 1.1, 1.4, 1, 0.5);
+1 IN (1.11, 1.2, 1.1, 1.4, 1, 0.5)
+1
+select 1 IN (1.11, 1.2, 1.1, 1.4, NULL, 0.5);
+1 IN (1.11, 1.2, 1.1, 1.4, NULL, 0.5)
+NULL
+select case 1.0 when 0.1 then "a" when 1.0 then "b" else "c" END;
+case 1.0 when 0.1 then "a" when 1.0 then "b" else "c" END
+b
+select case 0.1 when 0.1 then "a" when 1.0 then "b" else "c" END;
+case 0.1 when 0.1 then "a" when 1.0 then "b" else "c" END
+a
+select case 1 when 0.1 then "a" when 1.0 then "b" else "c" END;
+case 1 when 0.1 then "a" when 1.0 then "b" else "c" END
+b
+select case 1.0 when 0.1 then "a" when 1 then "b" else "c" END;
+case 1.0 when 0.1 then "a" when 1 then "b" else "c" END
+b
+select case 1.001 when 0.1 then "a" when 1 then "b" else "c" END;
+case 1.001 when 0.1 then "a" when 1 then "b" else "c" END
+c
+create table t1 (a decimal(6,3));
+insert into t1 values (1.0), (NULL), (0.1);
+select * from t1;
+a
+1.000
+NULL
+0.100
+select 0.1 in (1.0, 1.2, 1.1, a, 1.4, 0.5) from t1;
+0.1 in (1.0, 1.2, 1.1, a, 1.4, 0.5)
+0
+NULL
+1
+drop table t1;
+create table t1 select if(1, 1.1, 1.2), if(0, 1.1, 1.2), if(0.1, 1.1, 1.2), if(0, 1, 1.1), if(0, NULL, 1.2), if(1, 0.22e1, 1.1), if(1E0, 1.1, 1.2);
+select * from t1;
+if(1, 1.1, 1.2) if(0, 1.1, 1.2) if(0.1, 1.1, 1.2) if(0, 1, 1.1) if(0, NULL, 1.2) if(1, 0.22e1, 1.1) if(1E0, 1.1, 1.2)
+1.1 1.2 1.1 1.1 1.2 2.2 1.1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `if(1, 1.1, 1.2)` decimal(2,1) NOT NULL default '0.0',
+ `if(0, 1.1, 1.2)` decimal(2,1) NOT NULL default '0.0',
+ `if(0.1, 1.1, 1.2)` decimal(2,1) NOT NULL default '0.0',
+ `if(0, 1, 1.1)` decimal(2,1) NOT NULL default '0.0',
+ `if(0, NULL, 1.2)` decimal(2,1) default NULL,
+ `if(1, 0.22e1, 1.1)` double NOT NULL default '0',
+ `if(1E0, 1.1, 1.2)` decimal(2,1) NOT NULL default '0.0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 select nullif(1.1, 1.1), nullif(1.1, 1.2), nullif(1.1, 0.11e1), nullif(1.0, 1), nullif(1, 1.0), nullif(1, 1.1);
+select * from t1;
+nullif(1.1, 1.1) nullif(1.1, 1.2) nullif(1.1, 0.11e1) nullif(1.0, 1) nullif(1, 1.0) nullif(1, 1.1)
+NULL 1.1 NULL NULL NULL 1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `nullif(1.1, 1.1)` decimal(2,1) default NULL,
+ `nullif(1.1, 1.2)` decimal(2,1) default NULL,
+ `nullif(1.1, 0.11e1)` decimal(2,1) default NULL,
+ `nullif(1.0, 1)` decimal(2,1) default NULL,
+ `nullif(1, 1.0)` int(1) default NULL,
+ `nullif(1, 1.1)` int(1) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a decimal(4,2));
+insert into t1 value (10000), (1.1e10), ("11111"), (100000.1);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+insert into t1 value (-10000), (-1.1e10), ("-11111"), (-100000.1);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+select a from t1;
+a
+99.99
+99.99
+99.99
+99.99
+-99.99
+-99.99
+-99.99
+-99.99
+drop table t1;
+create table t1 (a decimal(4,2) unsigned);
+insert into t1 value (10000), (1.1e10), ("11111"), (100000.1);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+insert into t1 value (-10000), (-1.1e10), ("-11111"), (-100000.1);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+select a from t1;
+a
+99.99
+99.99
+99.99
+99.99
+0.00
+0.00
+0.00
+0.00
+drop table t1;
+create table t1 (a bigint);
+insert into t1 values (18446744073709551615.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+insert into t1 values (9223372036854775808.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+insert into t1 values (-18446744073709551615.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select * from t1;
+a
+9223372036854775807
+9223372036854775807
+-9223372036854775808
+drop table t1;
+create table t1 (a bigint unsigned);
+insert into t1 values (18446744073709551615.0);
+insert into t1 values (9223372036854775808.0);
+insert into t1 values (9999999999999999999999999.000);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+insert into t1 values (-1.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select * from t1;
+a
+18446744073709551615
+9223372036854775808
+18446744073709551615
+0
+drop table t1;
+create table t1 (a tinyint);
+insert into t1 values (18446744073709551615.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+insert into t1 values (9223372036854775808.0);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select * from t1;
+a
+127
+127
+drop table t1;
+create table t1 select round(15.4,-1), truncate(-5678.123451,-3), abs(-1.1), -(-1.1);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `round(15.4,-1)` decimal(3,0) NOT NULL default '0',
+ `truncate(-5678.123451,-3)` decimal(4,0) NOT NULL default '0',
+ `abs(-1.1)` decimal(3,1) NOT NULL default '0.0',
+ `-(-1.1)` decimal(2,1) NOT NULL default '0.0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set session sql_mode='traditional';
+select 1e10/0e0;
+1e10/0e0
+NULL
+Warnings:
+Error 1365 Division by 0
+create table wl1612 (col1 int, col2 decimal(38,10), col3 numeric(38,10));
+insert into wl1612 values(1,12345678901234567890.1234567890,12345678901234567890.1234567890);
+select * from wl1612;
+col1 col2 col3
+1 12345678901234567890.1234567890 12345678901234567890.1234567890
+insert into wl1612 values(2,01234567890123456789.0123456789,01234567890123456789.0123456789);
+select * from wl1612 where col1=2;
+col1 col2 col3
+2 1234567890123456789.0123456789 1234567890123456789.0123456789
+insert into wl1612 values(3,1234567890123456789012345678.0123456789,1234567890123456789012345678.0123456789);
+select * from wl1612 where col1=3;
+col1 col2 col3
+3 1234567890123456789012345678.0123456789 1234567890123456789012345678.0123456789
+select col1/0 from wl1612;
+col1/0
+NULL
+NULL
+NULL
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+Error 1365 Division by 0
+select col2/0 from wl1612;
+col2/0
+NULL
+NULL
+NULL
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+Error 1365 Division by 0
+select col3/0 from wl1612;
+col3/0
+NULL
+NULL
+NULL
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+Error 1365 Division by 0
+insert into wl1612 values(5,5000.0005,5000.0005);
+insert into wl1612 values(6,5000.0005,5000.0005);
+select sum(col2),sum(col3) from wl1612;
+sum(col2) sum(col3)
+1234567903703703580370380357.1491481468 1234567903703703580370380357.1491481468
+insert into wl1612 values(7,500000.000005,500000.000005);
+insert into wl1612 values(8,500000.000005,500000.000005);
+select sum(col2),sum(col3) from wl1612 where col1>4;
+sum(col2) sum(col3)
+1010000.0010100000 1010000.0010100000
+insert into wl1612 (col1, col2) values(9,1.01234567891);
+Warnings:
+Note 1265 Data truncated for column 'col2' at row 1
+insert into wl1612 (col1, col2) values(10,1.01234567894);
+Warnings:
+Note 1265 Data truncated for column 'col2' at row 1
+insert into wl1612 (col1, col2) values(11,1.01234567895);
+Warnings:
+Note 1265 Data truncated for column 'col2' at row 1
+insert into wl1612 (col1, col2) values(12,1.01234567896);
+Warnings:
+Note 1265 Data truncated for column 'col2' at row 1
+select col1,col2 from wl1612 where col1>8;
+col1 col2
+9 1.0123456789
+10 1.0123456789
+11 1.0123456790
+12 1.0123456790
+insert into wl1612 (col1, col3) values(13,1.01234567891);
+Warnings:
+Note 1265 Data truncated for column 'col3' at row 1
+insert into wl1612 (col1, col3) values(14,1.01234567894);
+Warnings:
+Note 1265 Data truncated for column 'col3' at row 1
+insert into wl1612 (col1, col3) values(15,1.01234567895);
+Warnings:
+Note 1265 Data truncated for column 'col3' at row 1
+insert into wl1612 (col1, col3) values(16,1.01234567896);
+Warnings:
+Note 1265 Data truncated for column 'col3' at row 1
+select col1,col3 from wl1612 where col1>12;
+col1 col3
+13 1.0123456789
+14 1.0123456789
+15 1.0123456790
+16 1.0123456790
+select col1 from wl1612 where col1>4 and col2=1.01234567891;
+col1
+select col1 from wl1612 where col1>4 and col2=1.0123456789;
+col1
+9
+10
+select col1 from wl1612 where col1>4 and col2<>1.0123456789;
+col1
+5
+6
+7
+8
+11
+12
+select col1 from wl1612 where col1>4 and col2<1.0123456789;
+col1
+select col1 from wl1612 where col1>4 and col2<=1.0123456789;
+col1
+9
+10
+select col1 from wl1612 where col1>4 and col2>1.0123456789;
+col1
+5
+6
+7
+8
+11
+12
+select col1 from wl1612 where col1>4 and col2>=1.0123456789;
+col1
+5
+6
+7
+8
+9
+10
+11
+12
+select col1 from wl1612 where col1>4 and col2=1.012345679;
+col1
+11
+12
+select col1 from wl1612 where col1>4 and col2<>1.012345679;
+col1
+5
+6
+7
+8
+9
+10
+select col1 from wl1612 where col1>4 and col3=1.01234567891;
+col1
+select col1 from wl1612 where col1>4 and col3=1.0123456789;
+col1
+13
+14
+select col1 from wl1612 where col1>4 and col3<>1.0123456789;
+col1
+5
+6
+7
+8
+15
+16
+select col1 from wl1612 where col1>4 and col3<1.0123456789;
+col1
+select col1 from wl1612 where col1>4 and col3<=1.0123456789;
+col1
+13
+14
+select col1 from wl1612 where col1>4 and col3>1.0123456789;
+col1
+5
+6
+7
+8
+15
+16
+select col1 from wl1612 where col1>4 and col3>=1.0123456789;
+col1
+5
+6
+7
+8
+13
+14
+15
+16
+select col1 from wl1612 where col1>4 and col3=1.012345679;
+col1
+15
+16
+select col1 from wl1612 where col1>4 and col3<>1.012345679;
+col1
+5
+6
+7
+8
+13
+14
+drop table wl1612;
+select 1/3;
+1/3
+0.3333
+select 0.8=0.7+0.1;
+0.8=0.7+0.1
+1
+select 0.7+0.1;
+0.7+0.1
+0.8
+create table wl1612_1 (col1 int);
+insert into wl1612_1 values(10);
+select * from wl1612_1 where 0.8=0.7+0.1;
+col1
+10
+select 0.07+0.07 from wl1612_1;
+0.07+0.07
+0.14
+select 0.07-0.07 from wl1612_1;
+0.07-0.07
+0.00
+select 0.07*0.07 from wl1612_1;
+0.07*0.07
+0.0049
+select 0.07/0.07 from wl1612_1;
+0.07/0.07
+1.000000
+drop table wl1612_1;
+create table wl1612_2 (col1 decimal(10,2), col2 numeric(10,2));
+insert into wl1612_2 values(1,1);
+insert into wl1612_2 values(+1,+1);
+insert into wl1612_2 values(+01,+01);
+insert into wl1612_2 values(+001,+001);
+select col1,count(*) from wl1612_2 group by col1;
+col1 count(*)
+1.00 4
+select col2,count(*) from wl1612_2 group by col2;
+col2 count(*)
+1.00 4
+drop table wl1612_2;
+create table wl1612_3 (col1 decimal(10,2), col2 numeric(10,2));
+insert into wl1612_3 values('1','1');
+insert into wl1612_3 values('+1','+1');
+insert into wl1612_3 values('+01','+01');
+insert into wl1612_3 values('+001','+001');
+select col1,count(*) from wl1612_3 group by col1;
+col1 count(*)
+1.00 4
+select col2,count(*) from wl1612_3 group by col2;
+col2 count(*)
+1.00 4
+drop table wl1612_3;
+select mod(234,10) ;
+mod(234,10)
+4
+select mod(234.567,10.555);
+mod(234.567,10.555)
+2.357
+select mod(-234.567,10.555);
+mod(-234.567,10.555)
+-2.357
+select mod(234.567,-10.555);
+mod(234.567,-10.555)
+2.357
+select round(15.1);
+round(15.1)
+15
+select round(15.4);
+round(15.4)
+15
+select round(15.5);
+round(15.5)
+16
+select round(15.6);
+round(15.6)
+16
+select round(15.9);
+round(15.9)
+16
+select round(-15.1);
+round(-15.1)
+-15
+select round(-15.4);
+round(-15.4)
+-15
+select round(-15.5);
+round(-15.5)
+-16
+select round(-15.6);
+round(-15.6)
+-16
+select round(-15.9);
+round(-15.9)
+-16
+select round(15.1,1);
+round(15.1,1)
+15.1
+select round(15.4,1);
+round(15.4,1)
+15.4
+select round(15.5,1);
+round(15.5,1)
+15.5
+select round(15.6,1);
+round(15.6,1)
+15.6
+select round(15.9,1);
+round(15.9,1)
+15.9
+select round(-15.1,1);
+round(-15.1,1)
+-15.1
+select round(-15.4,1);
+round(-15.4,1)
+-15.4
+select round(-15.5,1);
+round(-15.5,1)
+-15.5
+select round(-15.6,1);
+round(-15.6,1)
+-15.6
+select round(-15.9,1);
+round(-15.9,1)
+-15.9
+select round(15.1,0);
+round(15.1,0)
+15
+select round(15.4,0);
+round(15.4,0)
+15
+select round(15.5,0);
+round(15.5,0)
+16
+select round(15.6,0);
+round(15.6,0)
+16
+select round(15.9,0);
+round(15.9,0)
+16
+select round(-15.1,0);
+round(-15.1,0)
+-15
+select round(-15.4,0);
+round(-15.4,0)
+-15
+select round(-15.5,0);
+round(-15.5,0)
+-16
+select round(-15.6,0);
+round(-15.6,0)
+-16
+select round(-15.9,0);
+round(-15.9,0)
+-16
+select round(15.1,-1);
+round(15.1,-1)
+20
+select round(15.4,-1);
+round(15.4,-1)
+20
+select round(15.5,-1);
+round(15.5,-1)
+20
+select round(15.6,-1);
+round(15.6,-1)
+20
+select round(15.9,-1);
+round(15.9,-1)
+20
+select round(-15.1,-1);
+round(-15.1,-1)
+-20
+select round(-15.4,-1);
+round(-15.4,-1)
+-20
+select round(-15.5,-1);
+round(-15.5,-1)
+-20
+select round(-15.6,-1);
+round(-15.6,-1)
+-20
+select round(-15.91,-1);
+round(-15.91,-1)
+-20
+select truncate(5678.123451,0);
+truncate(5678.123451,0)
+5678
+select truncate(5678.123451,1);
+truncate(5678.123451,1)
+5678.1
+select truncate(5678.123451,2);
+truncate(5678.123451,2)
+5678.12
+select truncate(5678.123451,3);
+truncate(5678.123451,3)
+5678.123
+select truncate(5678.123451,4);
+truncate(5678.123451,4)
+5678.1234
+select truncate(5678.123451,5);
+truncate(5678.123451,5)
+5678.12345
+select truncate(5678.123451,6);
+truncate(5678.123451,6)
+5678.123451
+select truncate(5678.123451,-1);
+truncate(5678.123451,-1)
+5670
+select truncate(5678.123451,-2);
+truncate(5678.123451,-2)
+5600
+select truncate(5678.123451,-3);
+truncate(5678.123451,-3)
+5000
+select truncate(5678.123451,-4);
+truncate(5678.123451,-4)
+0
+select truncate(-5678.123451,0);
+truncate(-5678.123451,0)
+-5678
+select truncate(-5678.123451,1);
+truncate(-5678.123451,1)
+-5678.1
+select truncate(-5678.123451,2);
+truncate(-5678.123451,2)
+-5678.12
+select truncate(-5678.123451,3);
+truncate(-5678.123451,3)
+-5678.123
+select truncate(-5678.123451,4);
+truncate(-5678.123451,4)
+-5678.1234
+select truncate(-5678.123451,5);
+truncate(-5678.123451,5)
+-5678.12345
+select truncate(-5678.123451,6);
+truncate(-5678.123451,6)
+-5678.123451
+select truncate(-5678.123451,-1);
+truncate(-5678.123451,-1)
+-5670
+select truncate(-5678.123451,-2);
+truncate(-5678.123451,-2)
+-5600
+select truncate(-5678.123451,-3);
+truncate(-5678.123451,-3)
+-5000
+select truncate(-5678.123451,-4);
+truncate(-5678.123451,-4)
+0
+create table wl1612_4 (col1 int, col2 decimal(30,25), col3 numeric(30,25));
+insert into wl1612_4 values(1,0.0123456789012345678912345,0.0123456789012345678912345);
+select col2/9999999999 from wl1612_4 where col1=1;
+col2/9999999999
+0.00000000000123456789024691358
+select col3/9999999999 from wl1612_4 where col1=1;
+col3/9999999999
+0.00000000000123456789024691358
+select 9999999999/col2 from wl1612_4 where col1=1;
+9999999999/col2
+810000007209.0001
+select 9999999999/col3 from wl1612_4 where col1=1;
+9999999999/col3
+810000007209.0001
+select col2*9999999999 from wl1612_4 where col1=1;
+col2*9999999999
+123456789.0000000000111104321087655
+select col3*9999999999 from wl1612_4 where col1=1;
+col3*9999999999
+123456789.0000000000111104321087655
+insert into wl1612_4 values(2,55555.0123456789012345678912345,55555.0123456789012345678912345);
+select col2/9999999999 from wl1612_4 where col1=2;
+col2/9999999999
+0.00000555550123512344024696913
+select col3/9999999999 from wl1612_4 where col1=2;
+col3/9999999999
+0.00000555550123512344024696913
+select 9999999999/col2 from wl1612_4 where col1=2;
+9999999999/col2
+180001.7600
+select 9999999999/col3 from wl1612_4 where col1=2;
+9999999999/col3
+180001.7600
+select col2*9999999999 from wl1612_4 where col1=2;
+col2*9999999999
+555550123401234.0000000000111104321087655
+select col3*9999999999 from wl1612_4 where col1=2;
+col3*9999999999
+555550123401234.0000000000111104321087655
+drop table wl1612_4;
+set sql_mode='';
+select 23.4 + (-41.7), 23.4 - (41.7) = -18.3;
+23.4 + (-41.7) 23.4 - (41.7) = -18.3
+-18.3 1
+select -18.3=-18.3;
+-18.3=-18.3
+1
+select 18.3=18.3;
+18.3=18.3
+1
+select -18.3=18.3;
+-18.3=18.3
+0
+select 0.8 = 0.7 + 0.1;
+0.8 = 0.7 + 0.1
+1
+create procedure p1 () begin
+declare v1, v2, v3, v4 decimal(16,12); declare v5 int;
+set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0;
+while v5 < 100000 do
+set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1;
+end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;//
+call p1()//
+v1 v2 v3 * 0.000000000001 v4 * 0.000000000001
+1.000000100000 1.999999900000 1.000000100000 1.999999900000
+drop procedure p1;
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
+create table t1 (col1 decimal(38));
+insert into t1 values (12345678901234567890123456789012345678);
+select * from t1;
+col1
+12345678901234567890123456789012345678
+drop table t1;
+create table t1 (col1 decimal(31,30));
+insert into t1 values (0.00000000001);
+select * from t1;
+col1
+0.000000000010000000000000000000
+drop table t1;
+select 7777777777777777777777777777777777777 * 10;
+7777777777777777777777777777777777777 * 10
+77777777777777777777777777777777777770
+select .7777777777777777777777777777777777777 *
+1000000000000000000;
+.7777777777777777777777777777777777777 *
+1000000000000000000
+777777777777777777.777777777777777777700000000000
+select .7777777777777777777777777777777777777 - 0.1;
+.7777777777777777777777777777777777777 - 0.1
+0.6777777777777777777777777777777777777
+select .343434343434343434 + .343434343434343434;
+.343434343434343434 + .343434343434343434
+0.686868686868686868
+select abs(9999999999999999999999);
+abs(9999999999999999999999)
+9999999999999999999999
+select abs(-9999999999999999999999);
+abs(-9999999999999999999999)
+9999999999999999999999
+select ceiling(999999999999999999);
+ceiling(999999999999999999)
+999999999999999999
+select ceiling(99999999999999999999);
+ceiling(99999999999999999999)
+99999999999999999999
+select ceiling(9.9999999999999999999);
+ceiling(9.9999999999999999999)
+10
+select ceiling(-9.9999999999999999999);
+ceiling(-9.9999999999999999999)
+-9
+select floor(999999999999999999);
+floor(999999999999999999)
+999999999999999999
+select floor(9999999999999999999999);
+floor(9999999999999999999999)
+9999999999999999999999
+select floor(9.999999999999999999999);
+floor(9.999999999999999999999)
+9
+select floor(-9.999999999999999999999);
+floor(-9.999999999999999999999)
+-10
+select floor(-999999999999999999999.999);
+floor(-999999999999999999999.999)
+-1000000000000000000000
+select ceiling(999999999999999999999.999);
+ceiling(999999999999999999999.999)
+1000000000000000000000
+select 99999999999999999999999999999999999999 mod 3;
+99999999999999999999999999999999999999 mod 3
+0
+select round(99999999999999999.999);
+round(99999999999999999.999)
+100000000000000000
+select round(-99999999999999999.999);
+round(-99999999999999999.999)
+-100000000000000000
+select round(99999999999999999.999,3);
+round(99999999999999999.999,3)
+99999999999999999.999
+select round(-99999999999999999.999,3);
+round(-99999999999999999.999,3)
+-99999999999999999.999
+select truncate(99999999999999999999999999999999999999,31);
+truncate(99999999999999999999999999999999999999,31)
+99999999999999999999999999999999999999.000000000000000000000000000000
+select truncate(99.999999999999999999999999999999999999,31);
+truncate(99.999999999999999999999999999999999999,31)
+100.000000000000000000000000000000
+select truncate(99999999999999999999999999999999999999,-31);
+truncate(99999999999999999999999999999999999999,-31)
+99999990000000000000000000000000000000
+create table t1 as select 0.5;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `0.5` decimal(2,1) NOT NULL default '0.0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+select round(1.5),round(2.5);
+round(1.5) round(2.5)
+2 3
+select 0.07 * 0.07;
+0.07 * 0.07
+0.0049
+set sql_mode='traditional';
+select 1E-500 = 0;
+1E-500 = 0
+1
+select 1 / 1E-500;
+1 / 1E-500
+NULL
+Warnings:
+Error 1365 Division by 0
+select 1 / 0;
+1 / 0
+NULL
+Warnings:
+Error 1365 Division by 0
+set sql_mode='ansi,traditional';
+CREATE TABLE Sow6_2f (col1 NUMERIC(4,2));
+INSERT INTO Sow6_2f VALUES (10.55);
+INSERT INTO Sow6_2f VALUES (10.5555);
+Warnings:
+Note 1265 Data truncated for column 'col1' at row 1
+INSERT INTO Sow6_2f VALUES (-10.55);
+INSERT INTO Sow6_2f VALUES (-10.5555);
+Warnings:
+Note 1265 Data truncated for column 'col1' at row 1
+INSERT INTO Sow6_2f VALUES (11);
+INSERT INTO Sow6_2f VALUES (101.55);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+UPDATE Sow6_2f SET col1 = col1 * 50 WHERE col1 = 11;
+ERROR 22003: Out of range value adjusted for column 'col1' at row 5
+UPDATE Sow6_2f SET col1 = col1 / 0 WHERE col1 > 0;
+ERROR 22012: Division by 0
+SELECT MOD(col1,0) FROM Sow6_2f;
+MOD(col1,0)
+NULL
+NULL
+NULL
+NULL
+NULL
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
+Error 1365 Division by 0
+Error 1365 Division by 0
+Error 1365 Division by 0
+INSERT INTO Sow6_2f VALUES ('a59b');
+ERROR HY000: Incorrect decimal value: 'a59b' for column 'col1' at row 1
+drop table Sow6_2f;
+select 10.3330000000000/12.34500000;
+10.3330000000000/12.34500000
+0.83701903604698258
+set sql_mode='';
+select 0/0;
+0/0
+NULL
+select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 as x;
+x
+999999999999999999999999999999999999999999999999999999999999999999999999999999999
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x;
+x
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select 0.190287977636363637 + 0.040372670 * 0 - 0;
+0.190287977636363637 + 0.040372670 * 0 - 0
+0.190287977636363637
+select -0.123 * 0;
+-0.123 * 0
+0.000
+CREATE TABLE t1 (f1 DECIMAL (12,9), f2 DECIMAL(2,2));
+INSERT INTO t1 VALUES (10.5, 0);
+UPDATE t1 SET f1 = 4.5;
+SELECT * FROM t1;
+f1 f2
+4.500000000 0.00
+DROP TABLE t1;
+CREATE TABLE t1 (f1 DECIMAL (64,20), f2 DECIMAL(2,2));
+INSERT INTO t1 VALUES (9999999999999999999999999999999999, 0);
+SELECT * FROM t1;
+f1 f2
+9999999999999999999999999999999999.00000000000000000000 0.00
+DROP TABLE t1;
+select abs(10/0);
+abs(10/0)
+NULL
+select abs(NULL);
+abs(NULL)
+NULL
+set @@sql_mode='traditional';
+create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (22) unsigned);
+insert into t1 values(1,-1,-1);
+ERROR 22003: Out of range value adjusted for column 'd2' at row 1
+drop table t1;
+create table t1 (col1 decimal(5,2), col2 numeric(5,2));
+insert into t1 values (999.999,999.999);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+insert into t1 values (-999.999,-999.999);
+ERROR 22003: Out of range value adjusted for column 'col1' at row 1
+select * from t1;
+col1 col2
+drop table t1;
+set sql_mode='';
+set @sav_dpi= @@div_precision_increment;
+set @@div_precision_increment=15;
+create table t1 (col1 int, col2 decimal(30,25), col3 numeric(30,25));
+insert into t1 values (1,0.0123456789012345678912345,0.0123456789012345678912345);
+select col2/9999999999 from t1 where col1=1;
+col2/9999999999
+0.000000000001234567890246913578
+select 9999999999/col2 from t1 where col1=1;
+9999999999/col2
+810000007209.000065537105051
+select 77777777/7777777;
+77777777/7777777
+10.000000900000090
+drop table t1;
+set div_precision_increment= @sav_dpi;
+create table t1 (a decimal(4,2));
+insert into t1 values (0.00);
+select * from t1 where a > -0.00;
+a
+select * from t1 where a = -0.00;
+a
+0.00
+drop table t1;
+create table t1 (col1 bigint default -9223372036854775808);
+insert into t1 values (default);
+select * from t1;
+col1
+-9223372036854775808
+drop table t1;
+select cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15));
+cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15))
+0.000000000100000
+select ln(14000) c1, convert(ln(14000),decimal(2,3)) c2, cast(ln(14000) as decimal(2,3)) c3;
+c1 c2 c3
+9.5468126085974 9.547 9.547
+create table t1 (sl decimal(70,30));
+ERROR 42000: Too big precision 70 specified for column 'sl'. Maximum is 65.
+create table t1 (sl decimal(32,31));
+ERROR 42000: Too big scale 31 specified for column 'sl'. Maximum is 30.
+create table t1 (sl decimal(0,38));
+ERROR 42000: Too big scale 38 specified for column 'sl'. Maximum is 30.
+create table t1 (sl decimal(0,30));
+ERROR 42000: Scale may not be larger than the precision (column 'sl').
+create table t1 (sl decimal(5, 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `sl` decimal(5,5) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (sl decimal(65, 30));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `sl` decimal(65,30) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (
+f1 decimal unsigned not null default 17.49,
+f2 decimal unsigned not null default 17.68,
+f3 decimal unsigned not null default 99.2,
+f4 decimal unsigned not null default 99.7,
+f5 decimal unsigned not null default 104.49,
+f6 decimal unsigned not null default 199.91,
+f7 decimal unsigned not null default 999.9,
+f8 decimal unsigned not null default 9999.99);
+Warnings:
+Note 1265 Data truncated for column 'f1' at row 1
+Note 1265 Data truncated for column 'f2' at row 1
+Note 1265 Data truncated for column 'f3' at row 1
+Note 1265 Data truncated for column 'f4' at row 1
+Note 1265 Data truncated for column 'f5' at row 1
+Note 1265 Data truncated for column 'f6' at row 1
+Note 1265 Data truncated for column 'f7' at row 1
+Note 1265 Data truncated for column 'f8' at row 1
+insert into t1 (f1) values (1);
+select * from t1;
+f1 f2 f3 f4 f5 f6 f7 f8
+1 18 99 100 104 200 1000 10000
+drop table t1;
+create table t1 (
+f0 decimal (30,30) zerofill not null DEFAULT 0,
+f1 decimal (0,0) zerofill not null default 0);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f0` decimal(30,30) unsigned zerofill NOT NULL default '0.000000000000000000000000000000',
+ `f1` decimal(10,0) unsigned zerofill NOT NULL default '0000000000'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+drop procedure if exists wg2;
+Warnings:
+Note 1305 PROCEDURE wg2 does not exist
+create procedure wg2()
+begin
+declare v int default 1;
+declare tdec decimal(5) default 0;
+while v <= 9 do set tdec =tdec * 10;
+select v, tdec;
+set v = v + 1;
+end while;
+end//
+call wg2()//
+v tdec
+1 0
+v tdec
+2 0
+v tdec
+3 0
+v tdec
+4 0
+v tdec
+5 0
+v tdec
+6 0
+v tdec
+7 0
+v tdec
+8 0
+v tdec
+9 0
+drop procedure wg2;
+select cast(@non_existing_user_var/2 as DECIMAL);
+cast(@non_existing_user_var/2 as DECIMAL)
+NULL
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index 90207f39417..ff07dcca106 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -21,10 +21,10 @@ time_field time,
date_time datetime,
blob_col blob,
tinyblob_col tinyblob,
-mediumblob_col mediumblob not null,
-longblob_col longblob not null,
-options enum('one','two','tree') not null,
-flags set('one','two','tree') not null,
+mediumblob_col mediumblob not null default '',
+longblob_col longblob not null default '',
+options enum('one','two','tree') not null ,
+flags set('one','two','tree') not null default '',
PRIMARY KEY (auto),
KEY (utiny),
KEY (tiny),
@@ -40,30 +40,30 @@ KEY (options,flags)
);
show full fields from t1;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(5) unsigned NULL PRI NULL auto_increment #
-string varchar(10) latin1_swedish_ci YES hello #
-tiny tinyint(4) NULL MUL 0 #
-short smallint(6) NULL MUL 1 #
-medium mediumint(8) NULL MUL 0 #
-long_int int(11) NULL 0 #
-longlong bigint(13) NULL MUL 0 #
-real_float float(13,1) NULL MUL 0.0 #
+auto int(5) unsigned NULL NO PRI NULL auto_increment #
+string char(10) latin1_swedish_ci YES hello #
+tiny tinyint(4) NULL NO MUL 0 #
+short smallint(6) NULL NO MUL 1 #
+medium mediumint(8) NULL NO MUL 0 #
+long_int int(11) NULL NO 0 #
+longlong bigint(13) NULL NO MUL 0 #
+real_float float(13,1) NULL NO MUL 0.0 #
real_double double(16,4) NULL YES NULL #
-utiny tinyint(3) unsigned NULL MUL 0 #
-ushort smallint(5) unsigned zerofill NULL MUL 00000 #
-umedium mediumint(8) unsigned NULL MUL 0 #
-ulong int(11) unsigned NULL MUL 0 #
-ulonglong bigint(13) unsigned NULL MUL 0 #
+utiny tinyint(3) unsigned NULL NO MUL 0 #
+ushort smallint(5) unsigned zerofill NULL NO MUL 00000 #
+umedium mediumint(8) unsigned NULL NO MUL 0 #
+ulong int(11) unsigned NULL NO MUL 0 #
+ulonglong bigint(13) unsigned NULL NO MUL 0 #
time_stamp timestamp NULL YES CURRENT_TIMESTAMP #
date_field date NULL YES NULL #
time_field time NULL YES NULL #
date_time datetime NULL YES NULL #
blob_col blob NULL YES NULL #
tinyblob_col tinyblob NULL YES NULL #
-mediumblob_col mediumblob NULL #
-longblob_col longblob NULL #
-options enum('one','two','tree') latin1_swedish_ci MUL one #
-flags set('one','two','tree') latin1_swedish_ci #
+mediumblob_col mediumblob NULL NO #
+longblob_col longblob NULL NO #
+options enum('one','two','tree') latin1_swedish_ci NO MUL #
+flags set('one','two','tree') latin1_swedish_ci NO #
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 auto A 0 NULL NULL BTREE
@@ -87,51 +87,55 @@ DROP INDEX test ON t1;
insert into t1 values (10, 1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','one');
insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,NULL,2,2,'two','two,one');
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);
+Warnings:
+Warning 1265 Data truncated for column 'string' at row 1
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 Out of range value adjusted for column 'utiny' at row 1
+Warning 1264 Out of range value adjusted for column 'ushort' at row 1
+Warning 1264 Out of range value adjusted for column 'umedium' at row 1
+Warning 1264 Out of range value adjusted for column 'ulong' at row 1
+Warning 1264 Out of range value adjusted for column 'ulonglong' 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 Out of range value adjusted for column 'tiny' at row 1
+Warning 1264 Out of range value adjusted for column 'short' at row 1
+Warning 1264 Out of range value adjusted for column 'medium' at row 1
+Warning 1264 Out of range value adjusted for column 'long_int' at row 1
+Warning 1264 Out of range value adjusted for column 'utiny' at row 1
+Warning 1264 Out of range value adjusted for column 'ushort' at row 1
+Warning 1264 Out of range value adjusted for column 'umedium' at row 1
+Warning 1264 Out of range value adjusted for column 'ulong' at row 1
+Warning 1264 Out of range value adjusted for column 'ulonglong' 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 Out of range value adjusted for column 'tiny' at row 1
+Warning 1264 Out of range value adjusted for column 'short' at row 1
+Warning 1264 Out of range value adjusted for column 'medium' at row 1
+Warning 1264 Out of range value adjusted for column 'long_int' at row 1
+Warning 1264 Out of range value adjusted for column 'utiny' at row 1
+Warning 1264 Out of range value adjusted for column 'ushort' at row 1
+Warning 1264 Out of range value adjusted 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;
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
10 1 1 1 1 1 1 1.0 1.0000 1 00001 1 1 1 0 0000-00-00 00:00:00 0000-00-00 00:00:00 1 1 1 1
11 2 2 2 2 2 2 2.0 2.0000 2 00002 2 2 2 0 NULL NULL NULL NULL NULL 2 2
-12 0.33 3 3 3 3 3 3.0 3.0000 3 00003 3 3 3 0 1997-03-03 10:10:10 1997-03-03 10:10:10 3
-13 -1 -1 -1 -1 -1 -1 -1.0 -1.0000 0 00000 0 0 18446744073709551615 0 1997-08-07 08:07:06 1997-04-03 09:08:07 -1 -1 -1 -1
-14 -429496729 -128 -32768 -8388608 -2147483648 -4294967295 -4294967296.0 -4294967295.0000 0 00000 0 0 18446744069414584321 0 0000-00-00 00:00:00 0000-00-00 00:00:00 -4294967295 -4294967295 -4294967295 -4294967295
+12 0.33333333 3 3 3 3 3 3.0 3.0000 3 00003 3 3 3 0 1997-03-03 10:10:10 1997-03-03 10:10:10 3
+13 -1 -1 -1 -1 -1 -1 -1.0 -1.0000 0 00000 0 0 0 0 1997-08-07 08:07:06 1997-04-03 09:08:07 -1 -1 -1 -1
+14 -429496729 -128 -32768 -8388608 -2147483648 -4294967295 -4294967296.0 -4294967295.0000 0 00000 0 0 0 0 0000-00-00 00:00:00 0000-00-00 00:00:00 -4294967295 -4294967295 -4294967295 -4294967295
15 4294967295 127 32767 8388607 2147483647 4294967295 4294967296.0 4294967295.0000 255 65535 16777215 4294967295 4294967295 0 0000-00-00 00:00:00 0000-00-00 00:00:00 4294967295 4294967295 4294967295 4294967295
16 hello 1 1 0 0 0 0.0 NULL 0 00000 0 0 0 0 NULL NULL NULL NULL NULL
ALTER TABLE t1
add new_field char(10) default "new" not null,
change blob_col new_blob_col varchar(20),
change date_field date_field char(10),
-alter column string set default "new default",
+alter column string set default "newdefault",
alter short drop default,
DROP INDEX utiny,
DROP INDEX ushort,
@@ -174,7 +178,7 @@ Warning 1265 Data truncated for column 'new_field' at row 7
select * from t2;
auto string mediumblob_col new_field
1 2 2 ne
-2 0.33 ne
+2 0.33333333 ne
3 -1 -1 ne
4 -429496729 -4294967295 ne
5 4294967295 4294967295 ne
@@ -208,56 +212,56 @@ Warning 1265 Data truncated for column 'options' at row 6
update t2 set string="changed" where auto=16;
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(5) unsigned NULL MUL NULL auto_increment #
-string varchar(10) latin1_swedish_ci YES new defaul #
-tiny tinyint(4) NULL MUL 0 #
-short smallint(6) NULL MUL 0 #
-medium mediumint(8) NULL MUL 0 #
-long_int int(11) NULL 0 #
-longlong bigint(13) NULL MUL 0 #
-real_float float(13,1) NULL MUL 0.0 #
+auto int(5) unsigned NULL NO MUL NULL auto_increment #
+string char(10) latin1_swedish_ci YES newdefault #
+tiny tinyint(4) NULL NO MUL 0 #
+short smallint(6) NULL NO MUL 0 #
+medium mediumint(8) NULL NO MUL 0 #
+long_int int(11) NULL NO 0 #
+longlong bigint(13) NULL NO MUL 0 #
+real_float float(13,1) NULL NO MUL 0.0 #
real_double double(16,4) NULL YES NULL #
-utiny tinyint(3) unsigned NULL 0 #
-ushort smallint(5) unsigned zerofill NULL 00000 #
-umedium mediumint(8) unsigned NULL MUL 0 #
-ulong int(11) unsigned NULL MUL 0 #
-ulonglong bigint(13) unsigned NULL MUL 0 #
+utiny tinyint(3) unsigned NULL NO 0 #
+ushort smallint(5) unsigned zerofill NULL NO 00000 #
+umedium mediumint(8) unsigned NULL NO MUL 0 #
+ulong int(11) unsigned NULL NO MUL 0 #
+ulonglong bigint(13) unsigned NULL NO MUL 0 #
time_stamp timestamp NULL YES CURRENT_TIMESTAMP #
-date_field varchar(10) latin1_swedish_ci YES NULL #
+date_field char(10) latin1_swedish_ci YES NULL #
time_field time NULL YES NULL #
date_time datetime NULL YES NULL #
new_blob_col varchar(20) latin1_swedish_ci YES NULL #
tinyblob_col tinyblob NULL YES NULL #
-mediumblob_col mediumblob NULL #
-options enum('one','two','tree') latin1_swedish_ci MUL one #
-flags set('one','two','tree') latin1_swedish_ci #
-new_field varchar(10) latin1_swedish_ci new #
+mediumblob_col mediumblob NULL NO #
+options enum('one','two','tree') latin1_swedish_ci NO MUL #
+flags set('one','two','tree') latin1_swedish_ci NO #
+new_field char(10) latin1_swedish_ci NO new #
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(5) unsigned NULL 0 #
-string varchar(10) latin1_swedish_ci YES new defaul #
-tiny tinyint(4) NULL 0 #
-short smallint(6) NULL 0 #
-medium mediumint(8) NULL 0 #
-long_int int(11) NULL 0 #
-longlong bigint(13) NULL 0 #
-real_float float(13,1) NULL 0.0 #
+auto int(5) unsigned NULL NO 0 #
+string char(10) latin1_swedish_ci YES newdefault #
+tiny tinyint(4) NULL NO 0 #
+short smallint(6) NULL NO 0 #
+medium mediumint(8) NULL NO 0 #
+long_int int(11) NULL NO 0 #
+longlong bigint(13) NULL NO 0 #
+real_float float(13,1) NULL NO 0.0 #
real_double double(16,4) NULL YES NULL #
-utiny tinyint(3) unsigned NULL 0 #
-ushort smallint(5) unsigned zerofill NULL 00000 #
-umedium mediumint(8) unsigned NULL 0 #
-ulong int(11) unsigned NULL 0 #
-ulonglong bigint(13) unsigned NULL 0 #
+utiny tinyint(3) unsigned NULL NO 0 #
+ushort smallint(5) unsigned zerofill NULL NO 00000 #
+umedium mediumint(8) unsigned NULL NO 0 #
+ulong int(11) unsigned NULL NO 0 #
+ulonglong bigint(13) unsigned NULL NO 0 #
time_stamp timestamp NULL YES 0000-00-00 00:00:00 #
-date_field varchar(10) latin1_swedish_ci YES NULL #
+date_field char(10) latin1_swedish_ci YES NULL #
time_field time NULL YES NULL #
date_time datetime NULL YES NULL #
new_blob_col varchar(20) latin1_swedish_ci YES NULL #
tinyblob_col tinyblob NULL YES NULL #
-mediumblob_col mediumblob NULL #
-options enum('one','two','tree') latin1_swedish_ci one #
-flags set('one','two','tree') latin1_swedish_ci #
-new_field varchar(10) latin1_swedish_ci new #
+mediumblob_col mediumblob NULL NO #
+options enum('one','two','tree') latin1_swedish_ci NO one #
+flags set('one','two','tree') latin1_swedish_ci NO #
+new_field char(10) latin1_swedish_ci NO new #
select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and ((t1.string<>t2.string and (t1.string is not null or t2.string is not null)) or (t1.tiny<>t2.tiny and (t1.tiny is not null or t2.tiny is not null)) or (t1.short<>t2.short and (t1.short is not null or t2.short is not null)) or (t1.medium<>t2.medium and (t1.medium is not null or t2.medium is not null)) or (t1.long_int<>t2.long_int and (t1.long_int is not null or t2.long_int is not null)) or (t1.longlong<>t2.longlong and (t1.longlong is not null or t2.longlong is not null)) or (t1.real_float<>t2.real_float and (t1.real_float is not null or t2.real_float is not null)) or (t1.real_double<>t2.real_double and (t1.real_double is not null or t2.real_double is not null)) or (t1.utiny<>t2.utiny and (t1.utiny is not null or t2.utiny is not null)) or (t1.ushort<>t2.ushort and (t1.ushort is not null or t2.ushort is not null)) or (t1.umedium<>t2.umedium and (t1.umedium is not null or t2.umedium is not null)) or (t1.ulong<>t2.ulong and (t1.ulong is not null or t2.ulong is not null)) or (t1.ulonglong<>t2.ulonglong and (t1.ulonglong is not null or t2.ulonglong is not null)) or (t1.time_stamp<>t2.time_stamp and (t1.time_stamp is not null or t2.time_stamp is not null)) or (t1.date_field<>t2.date_field and (t1.date_field is not null or t2.date_field is not null)) or (t1.time_field<>t2.time_field and (t1.time_field is not null or t2.time_field is not null)) or (t1.date_time<>t2.date_time and (t1.date_time is not null or t2.date_time is not null)) or (t1.new_blob_col<>t2.new_blob_col and (t1.new_blob_col is not null or t2.new_blob_col is not null)) or (t1.tinyblob_col<>t2.tinyblob_col and (t1.tinyblob_col is not null or t2.tinyblob_col is not null)) or (t1.mediumblob_col<>t2.mediumblob_col and (t1.mediumblob_col is not null or t2.mediumblob_col is not null)) or (t1.options<>t2.options and (t1.options is not null or t2.options is not null)) or (t1.flags<>t2.flags and (t1.flags is not null or t2.flags is not null)) or (t1.new_field<>t2.new_field and (t1.new_field is not null or t2.new_field is not null)));
auto auto
16 16
@@ -265,23 +269,27 @@ select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and not (t1.string<=>t2.
auto auto
16 16
drop table t2;
-create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, "a" as t2, repeat("a",256) as t3, binary repeat("b",256) as t4 from t1;
+create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
-auto bigint(17) unsigned NULL PRI 0 #
-t1 bigint(1) NULL 0 #
-t2 char(1) latin1_swedish_ci #
-t3 longtext latin1_swedish_ci #
-t4 longblob NULL #
-select * from t2;
-auto t1 t2 t3 t4
-11 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-12 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-13 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-14 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-15 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-16 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-17 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+auto bigint(12) unsigned NULL NO PRI 0 #
+t1 bigint(1) NULL NO 0 #
+t2 varchar(1) latin1_swedish_ci NO #
+t3 varchar(256) latin1_swedish_ci NO #
+t4 varbinary(256) NULL NO #
+t5 longtext latin1_swedish_ci NO #
+t6 longblob NULL NO #
+t7 char(0) latin1_swedish_ci NO #
+t8 binary(0) NULL NO #
+select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
+t1 t2 length(t3) length(t4) length(t5) length(t6) t7 t8
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
drop table t1,t2;
create table t1 (c int);
insert into t1 values(1),(2);
@@ -293,7 +301,7 @@ show full columns from t3;
Field Type Collation Null Key Default Extra Privileges Comment
c1 int(11) NULL YES NULL #
c2 int(11) NULL YES NULL #
-const bigint(1) NULL 0 #
+const bigint(1) NULL NO 0 #
drop table t1,t2,t3;
create table t1 ( myfield INT NOT NULL, UNIQUE INDEX (myfield), unique (myfield), index(myfield));
drop table t1;
@@ -305,16 +313,32 @@ select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
id_A id_B
1 1
2 NULL
+select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id);
+id_A id_B
+1 1
+2 NULL
create table t3 (id_A integer unsigned not null, id_B integer unsigned null );
insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
select * from t3;
id_A id_B
1 1
2 NULL
+delete from t3;
+insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id);
+select * from t3;
+id_A id_B
+1 1
+2 NULL
drop table t3;
create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
select * from t3;
id_A id_B
1 1
2 NULL
+drop table t3;
+create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id);
+select * from t3;
+id_A id_B
+1 1
+2 NULL
drop table t1,t2,t3;
diff --git a/mysql-test/r/type_set.result b/mysql-test/r/type_set.result
index 5aedefda283..fdda4aca25c 100644
--- a/mysql-test/r/type_set.result
+++ b/mysql-test/r/type_set.result
@@ -3,7 +3,7 @@ create table t1 (a set (' ','a','b') not null);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` set('','a','b') NOT NULL default ''
+ `a` set('','a','b') NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a set (' ','a','b ') not null default 'b ');
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index 025cf2a57f1..442435b0459 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -26,9 +26,9 @@ t
insert into t1 values("10.22.22"),(1234567),(123456789),(123456789.10),("10 22:22"),("12.45a");
Warnings:
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 1264 Out of range value adjusted for column 't' at row 2
+Warning 1264 Out of range value adjusted for column 't' at row 3
+Warning 1264 Out of range value adjusted for column 't' at row 4
Warning 1265 Data truncated for column 't' at row 6
select * from t1;
t
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index c0396e4640d..61ed6bbabf3 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -35,6 +35,10 @@ UPDATE t1 SET value="my value" WHERE id="myKey";
SELECT stamp FROM t1 WHERE id="myKey";
stamp
1999-04-02 00:00:00
+UPDATE t1 SET id="myKey" WHERE value="my value";
+SELECT stamp FROM t1 WHERE id="myKey";
+stamp
+1999-04-02 00:00:00
drop table t1;
create table t1 (a timestamp);
insert into t1 values (now());
@@ -95,6 +99,14 @@ drop table t1;
create table t1 (t2 timestamp(2), t4 timestamp(4), t6 timestamp(6),
t8 timestamp(8), t10 timestamp(10), t12 timestamp(12),
t14 timestamp(14));
+Warnings:
+Warning 1287 'TIMESTAMP(2)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(4)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(6)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(8)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(10)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(12)' is deprecated; use 'TIMESTAMP' instead
+Warning 1287 'TIMESTAMP(14)' is deprecated; use 'TIMESTAMP' instead
insert t1 values (0,0,0,0,0,0,0),
("1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59",
"1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59",
diff --git a/mysql-test/r/type_uint.result b/mysql-test/r/type_uint.result
index d8edf9085b7..0474f3a24f4 100644
--- a/mysql-test/r/type_uint.result
+++ b/mysql-test/r/type_uint.result
@@ -4,10 +4,10 @@ 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 Out of range value adjusted for column 'this' at row 1
insert into t1 values ('5000000000');
Warnings:
-Warning 1265 Data truncated for column 'this' at row 1
+Warning 1264 Out of range value adjusted for column 'this' at row 1
select * from t1;
this
1
diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result
new file mode 100644
index 00000000000..e3b12cc36e3
--- /dev/null
+++ b/mysql-test/r/type_varchar.result
@@ -0,0 +1,417 @@
+drop table if exists t1, t2;
+create table t1 (v varchar(30), c char(3), e enum('abc','def','ghi'), t text);
+truncate table vchar;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(30) default NULL,
+ `c` char(3) default NULL,
+ `e` enum('abc','def','ghi') default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table vchar;
+Table Create Table
+vchar CREATE TABLE `vchar` (
+ `v` varchar(30) default NULL,
+ `c` char(3) default NULL,
+ `e` enum('abc','def','ghi') default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc', 'de', 'ghi', 'jkl');
+insert into t1 values ('abc ', 'de ', 'ghi', 'jkl ');
+insert into t1 values ('abc ', 'd ', 'ghi', 'jkl ');
+insert into vchar values ('abc', 'de', 'ghi', 'jkl');
+insert into vchar values ('abc ', 'de ', 'ghi', 'jkl ');
+insert into vchar values ('abc ', 'd ', 'ghi', 'jkl ');
+select length(v),length(c),length(e),length(t) from t1;
+length(v) length(c) length(e) length(t)
+3 2 3 3
+4 2 3 4
+7 1 3 7
+select length(v),length(c),length(e),length(t) from vchar;
+length(v) length(c) length(e) length(t)
+3 2 3 3
+3 2 3 4
+3 1 3 7
+alter table vchar add i int;
+show create table vchar;
+Table Create Table
+vchar CREATE TABLE `vchar` (
+ `v` varchar(30) default NULL,
+ `c` char(3) default NULL,
+ `e` enum('abc','def','ghi') default NULL,
+ `t` text,
+ `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select length(v),length(c),length(e),length(t) from vchar;
+length(v) length(c) length(e) length(t)
+3 2 3 3
+3 2 3 4
+3 1 3 7
+drop table t1, vchar;
+create table t1 (v varchar(20));
+insert into t1 values('a ');
+select v='a' from t1;
+v='a'
+1
+select binary v='a' from t1;
+binary v='a'
+0
+select binary v='a ' from t1;
+binary v='a '
+1
+insert into t1 values('a');
+alter table t1 add primary key (v);
+ERROR 23000: Duplicate entry 'a' for key 1
+drop table t1;
+create table t1 (v varbinary(20));
+insert into t1 values('a');
+insert into t1 values('a ');
+alter table t1 add primary key (v);
+drop table t1;
+create table t1 (v varchar(254), index (v));
+insert into t1 values ("This is a test ");
+insert into t1 values ("Some sample data");
+insert into t1 values (" garbage ");
+insert into t1 values (" This is a test ");
+insert into t1 values ("This is a test");
+insert into t1 values ("Hello world");
+insert into t1 values ("Foo bar");
+insert into t1 values ("This is a test");
+insert into t1 values ("MySQL varchar test");
+insert into t1 values ("test MySQL varchar");
+insert into t1 values ("This is a long string to have some random length data included");
+insert into t1 values ("Short string");
+insert into t1 values ("VSS");
+insert into t1 values ("Some samples");
+insert into t1 values ("Bar foo");
+insert into t1 values ("Bye");
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 257 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 257 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 257 NULL 2 Using where; Using index
+alter table t1 change v v varchar(255);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 258 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 258 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 258 NULL 2 Using where; Using index
+alter table t1 change v v varchar(256);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 259 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 259 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 259 NULL 2 Using where; Using index
+alter table t1 change v v varchar(257);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 260 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 260 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 260 NULL 2 Using where; Using index
+alter table t1 change v v varchar(258);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 261 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 261 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 261 NULL 2 Using where; Using index
+alter table t1 change v v varchar(259);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 262 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 262 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 262 NULL 2 Using where; Using index
+alter table t1 change v v varchar(258);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 261 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 261 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 261 NULL 2 Using where; Using index
+alter table t1 change v v varchar(257);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 260 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 260 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 260 NULL 2 Using where; Using index
+alter table t1 change v v varchar(256);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 259 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 259 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 259 NULL 2 Using where; Using index
+alter table t1 change v v varchar(255);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 258 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 258 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 258 NULL 2 Using where; Using index
+alter table t1 change v v varchar(254);
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 257 NULL 3 Using where; Using index
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 257 const 3 Using where; Using index
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 257 NULL 2 Using where; Using index
+alter table t1 change v v varchar(253);
+alter table t1 change v v varchar(254), drop key v;
+alter table t1 change v v varchar(300), add key (v(10));
+select * from t1 where v like 'This is a test' order by v;
+v
+This is a test
+This is a test
+select * from t1 where v='This is a test' order by v;
+v
+This is a test
+This is a test
+This is a test
+select * from t1 where v like 'S%' order by v;
+v
+Short string
+Some sample data
+Some samples
+explain select * from t1 where v like 'This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL 4 Using where; Using filesort
+explain select * from t1 where v='This is a test' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const 4 Using where
+explain select * from t1 where v like 'S%' order by v;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL 2 Using where; Using filesort
+drop table t1;
+create table t1 (pkcol varchar(16), othercol varchar(16), primary key (pkcol));
+insert into t1 values ('test', 'something');
+update t1 set othercol='somethingelse' where pkcol='test';
+select * from t1;
+pkcol othercol
+test somethingelse
+drop table t1;
+create table t1 (a int, b varchar(12));
+insert into t1 values (1, 'A'), (22, NULL);
+create table t2 (a int);
+insert into t2 values (22), (22);
+select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a
+group by t1.b, t1.a;
+a b min(t1.b)
+22 NULL NULL
+drop table t1, t2;
+create table t1 (f1 varchar(65500));
+create index index1 on t1(f1(10));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` varchar(65500) default NULL,
+ KEY `index1` (`f1`(10))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify f1 varchar(255);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` varchar(255) default NULL,
+ KEY `index1` (`f1`(10))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify f1 tinytext;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `f1` tinytext,
+ KEY `index1` (`f1`(10))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 1b5fa69d713..eb129e32983 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -88,7 +88,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 UNION t2 ALL NULL NULL NULL NULL 4 Using filesort
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL Using filesort
Warnings:
-Note 1003 (select test.t1.a AS `a`,test.t1.b AS `b` from test.t1 limit 2) union all (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 order by test.t2.a limit 1) order by b desc
+Note 1003 (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` limit 2) union all (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`a` limit 1) order by `b` desc
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
a b
1 a
@@ -430,7 +430,7 @@ drop temporary table t1;
create table t1 select a from t1 union select a from t2;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
select a from t1 union select a from t2 order by t2.a;
-ERROR 42S02: Unknown table 't2' in order clause
+ERROR 42S22: Unknown column 't2.a' in 'order clause'
drop table t1,t2;
select length(version()) > 1 as `*` UNION select 2;
*
@@ -480,7 +480,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 UNION t2 const PRIMARY PRIMARY 4 const 1
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select test.t1.a AS `a`,test.t1.b AS `b` from test.t1 where (test.t1.a = 1)) union (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.a = 1))
+Note 1003 (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a` = 1)) union (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` = 1))
(select * from t1 where a=5) union (select * from t2 where a=1);
a b
1 10
@@ -543,7 +543,7 @@ aa
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` char(2) NOT NULL default ''
+ `a` varchar(2) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT 12 as a UNION select "aa" as a;
@@ -554,7 +554,7 @@ aa
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` binary(20) NOT NULL default ''
+ `a` varbinary(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;
@@ -565,7 +565,7 @@ a
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` double(53,1) NOT NULL default '0.0'
+ `a` decimal(3,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);
@@ -788,11 +788,11 @@ create table t3 select * from t2 union select * from t1;
select * from t3;
d
1.234567800
-100000000.0
+100000000.000000000
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `d` decimal(10,9) default NULL
+ `d` decimal(18,9) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2,t3;
create table t1 select 1 union select -1;
@@ -812,7 +812,7 @@ create table t1 select _latin2"test" union select _latin2"testt" ;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `test` char(5) character set latin2 NOT NULL default ''
+ `test` varchar(5) character set latin2 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (s char(200));
@@ -851,27 +851,27 @@ count(*)
26
show status like 'Slow_queries';
Variable_name Value
-Slow_queries 0
+Slow_queries 1
select count(*) from t1 where b=13;
count(*)
10
show status like 'Slow_queries';
Variable_name Value
-Slow_queries 1
+Slow_queries 3
select count(*) from t1 where b=13 union select count(*) from t1 where a=7;
count(*)
10
26
show status like 'Slow_queries';
Variable_name Value
-Slow_queries 2
+Slow_queries 5
select count(*) from t1 where a=7 union select count(*) from t1 where b=13;
count(*)
26
10
show status like 'Slow_queries';
Variable_name Value
-Slow_queries 3
+Slow_queries 7
flush status;
select a from t1 where b not in (1,2,3) union select a from t1 where b not in (4,5,6);
a
@@ -1056,7 +1056,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `test` char(4) NOT NULL default ''
+ `test` varchar(4) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
@@ -1114,7 +1114,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a collate latin1_german1_ci` char(1) character set latin1 collate latin1_german1_ci default NULL
+ `a collate latin1_german1_ci` varchar(1) character set latin1 collate latin1_german1_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as
@@ -1123,7 +1123,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` char(1) character set latin1 collate latin1_german1_ci default NULL
+ `a` varchar(1) character set latin1 collate latin1_german1_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as
@@ -1133,7 +1133,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` char(1) character set latin1 collate latin1_german1_ci default NULL
+ `a` varchar(1) character set latin1 collate latin1_german1_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
drop table t2;
@@ -1226,7 +1226,7 @@ drop table t2;
create table t2 select a from t1 union select a from t1;
show columns from t2;
Field Type Null Key Default Extra
-a char(1)
+a varchar(1) NO
drop table t2;
create table t2 select a from t1 union select c from t1;
ERROR HY000: Illegal mix of collations (utf8_general_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation 'UNION'
@@ -1235,6 +1235,23 @@ show columns from t2;
Field Type Null Key Default Extra
a varchar(3) YES NULL
drop table t2, t1;
+create table t1 (a varchar(5));
+create table t2 select * from t1 union select 'abcdefghijkl';
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(12) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select row_format from information_schema.TABLES where table_schema="test" and table_name="t2";
+row_format
+Dynamic
+alter table t2 ROW_FORMAT=fixed;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(12) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+drop table t1,t2;
CREATE TABLE t1 (a mediumtext);
CREATE TABLE t2 (b varchar(20));
INSERT INTO t1 VALUES ('a'),('b');
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index e35d4e29fe4..42fb8064044 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -58,7 +58,7 @@ ushows int(10) unsigned DEFAULT '0' NOT NULL,
clicks int(10) unsigned DEFAULT '0' NOT NULL,
iclicks int(10) unsigned DEFAULT '0' NOT NULL,
uclicks int(10) unsigned DEFAULT '0' NOT NULL,
-ts timestamp(14),
+ts timestamp,
PRIMARY KEY (place_id,ts)
);
INSERT INTO t1 (place_id,shows,ishows,ushows,clicks,iclicks,uclicks,ts)
@@ -75,7 +75,7 @@ client varchar(255) NOT NULL default '',
replyto varchar(255) NOT NULL default '',
subject varchar(100) NOT NULL default '',
timestamp int(10) unsigned NOT NULL default '0',
-tstamp timestamp(14) NOT NULL,
+tstamp timestamp NOT NULL,
status int(3) NOT NULL default '0',
type varchar(15) NOT NULL default '',
assignment int(10) unsigned NOT NULL default '0',
diff --git a/mysql-test/r/user_limits.result b/mysql-test/r/user_limits.result
new file mode 100644
index 00000000000..a94eb4616d1
--- /dev/null
+++ b/mysql-test/r/user_limits.result
@@ -0,0 +1,96 @@
+drop table if exists t1;
+create table t1 (i int);
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
+grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 2;
+flush user_resources;
+select * from t1;
+i
+select * from t1;
+i
+select * from t1;
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_questions' resource (current value: 2)
+select * from t1;
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_questions' resource (current value: 2)
+drop user mysqltest_1@localhost;
+grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 2;
+flush user_resources;
+select * from t1;
+i
+select * from t1;
+i
+select * from t1;
+i
+delete from t1;
+delete from t1;
+delete from t1;
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_updates' resource (current value: 2)
+select * from t1;
+i
+delete from t1;
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_updates' resource (current value: 2)
+select * from t1;
+i
+drop user mysqltest_1@localhost;
+grant usage on *.* to mysqltest_1@localhost with max_connections_per_hour 2;
+flush user_resources;
+select * from t1;
+i
+select * from t1;
+i
+connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_connections_per_hour' resource (current value: 2)
+select * from t1;
+i
+connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_connections_per_hour' resource (current value: 2)
+drop user mysqltest_1@localhost;
+flush privileges;
+grant usage on *.* to mysqltest_1@localhost with max_user_connections 2;
+flush user_resources;
+select * from t1;
+i
+select * from t1;
+i
+connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 2)
+select * from t1;
+i
+grant usage on *.* to mysqltest_1@localhost with max_user_connections 3;
+flush user_resources;
+select * from t1;
+i
+connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 3)
+drop user mysqltest_1@localhost;
+select @@session.max_user_connections, @@global.max_user_connections;
+@@session.max_user_connections @@global.max_user_connections
+0 0
+set session max_user_connections= 2;
+ERROR HY000: Variable 'max_user_connections' is a GLOBAL variable and should be set with SET GLOBAL
+set global max_user_connections= 2;
+select @@session.max_user_connections, @@global.max_user_connections;
+@@session.max_user_connections @@global.max_user_connections
+2 2
+grant usage on *.* to mysqltest_1@localhost;
+flush user_resources;
+select @@session.max_user_connections, @@global.max_user_connections;
+@@session.max_user_connections @@global.max_user_connections
+2 2
+select * from t1;
+i
+connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
+ERROR 42000: User mysqltest_1 already has more than 'max_user_connections' active connections
+grant usage on *.* to mysqltest_1@localhost with max_user_connections 3;
+flush user_resources;
+select @@session.max_user_connections, @@global.max_user_connections;
+@@session.max_user_connections @@global.max_user_connections
+3 2
+connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 3)
+set global max_user_connections= 0;
+drop user mysqltest_1@localhost;
+drop table t1;
diff --git a/mysql-test/r/user_var-binlog.result b/mysql-test/r/user_var-binlog.result
index 06a2a846a0e..0e9692523ef 100644
--- a/mysql-test/r/user_var-binlog.result
+++ b/mysql-test/r/user_var-binlog.result
@@ -6,20 +6,27 @@ INSERT INTO t1 VALUES(@`a b`);
set @var1= "';aaa";
SET @var2=char(ascii('a'));
insert into t1 values (@var1),(@var2);
-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 User var 1 226 @`var2`=_latin1 0x61 COLLATE latin1_swedish_ci
-master-bin.000001 264 Query 1 264 use `test`; insert into t1 values (@var1),(@var2)
+show binlog events from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 98 User var 1 139 @`a b`=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci
+master-bin.000001 139 Query 1 231 use `test`; INSERT INTO t1 VALUES(@`a b`)
+master-bin.000001 231 User var 1 273 @`var1`=_latin1 0x273B616161 COLLATE latin1_swedish_ci
+master-bin.000001 273 User var 1 311 @`var2`=_latin1 0x61 COLLATE latin1_swedish_ci
+master-bin.000001 311 Query 1 411 use `test`; insert into t1 values (@var1),(@var2)
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
SET @`a b`:=_latin1 0x68656C6C6F COLLATE `latin1_swedish_ci`;
use test;
SET TIMESTAMP=10000;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
INSERT INTO t1 VALUES(@`a b`);
SET @`var1`:=_latin1 0x273B616161 COLLATE `latin1_swedish_ci`;
SET @`var2`:=_latin1 0x61 COLLATE `latin1_swedish_ci`;
SET TIMESTAMP=10000;
insert into t1 values (@var1),(@var2);
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
drop table t1;
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 58b785d1432..acdc793fb69 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -23,7 +23,11 @@ i @vv1:=if(sv1.i,1,0) @vv2:=if(sv2.i,1,0) @vv3:=if(sv3.i,1,0) @vv1+@vv2+@vv3
2 1 0 0 1
explain select * from t1 where i=@vv1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref i i 4 const 1 Using where
+1 SIMPLE t1 ref i i 4 const 1
+select @vv1,i,v from t1 where i=@vv1;
+@vv1 i v
+1 1 1
+1 1 3
explain select * from t1 where @vv1:=@vv1+1 and i=@vv1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
@@ -32,7 +36,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL i 4 NULL 3 Using where; Using index
explain select * from t1 where i=@vv1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref i i 4 const 1 Using where
+1 SIMPLE t1 ref i i 4 const 1
drop table t1,t2;
set @a=0,@b=0;
select @a:=10, @b:=1, @a > @b, @a < @b;
@@ -178,7 +182,7 @@ coercibility(@v1) coercibility(@v2) coercibility(@v3) coercibility(@v4)
set session @honk=99;
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 '@honk=99' at line 1
set one_shot @honk=99;
-ERROR HY000: The SET ONE_SHOT syntax is reserved for purposes internal to the MySQL server
+ERROR HY000: The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server
select @@local.max_allowed_packet;
@@local.max_allowed_packet
#
@@ -203,3 +207,44 @@ select @@global.version;
select @@session.VERSION;
@@session.VERSION
#
+set @first_var= NULL;
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @first_var= cast(NULL as signed integer);
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` bigint(20) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @first_var= NULL;
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` bigint(20) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @first_var= concat(NULL);
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @first_var=1;
+set @first_var= cast(NULL as CHAR);
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` longtext
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result
index ab5779859ae..e55e6b35915 100644
--- a/mysql-test/r/varbinary.result
+++ b/mysql-test/r/varbinary.result
@@ -15,7 +15,7 @@ explain extended select * from t1 where UNIQ=0x38afba1d73e6a18a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const UNIQ UNIQ 8 const 1
Warnings:
-Note 1003 select test.t1.ID AS `ID`,test.t1.UNIQ AS `UNIQ` from test.t1 where (test.t1.UNIQ = 4084688022709641610)
+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
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index 67c78d82a24..265f353ae3c 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -1,8 +1,30 @@
drop table if exists t1,t2;
-set @`test`=1,@TEST=3,@select=2,@t5=1.23456;
-select @test,@`select`,@TEST,@not_used;
-@test @`select` @TEST @not_used
-1 2 3 NULL
+set @`test`=1;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+@test @`test` @TEST @`TEST` @"teSt"
+1 1 1 1 1
+set @TEST=2;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+@test @`test` @TEST @`TEST` @"teSt"
+2 2 2 2 2
+set @"tEST"=3;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+@test @`test` @TEST @`TEST` @"teSt"
+3 3 3 3 3
+set @`TeST`=4;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+@test @`test` @TEST @`TEST` @"teSt"
+4 4 4 4 4
+select @`teST`:=5;
+@`teST`:=5
+5
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+@test @`test` @TEST @`TEST` @"teSt"
+5 5 5 5 5
+set @select=2,@t5=1.23456;
+select @`select`,@not_used;
+@`select` @not_used
+2 NULL
set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL;
select @test_int,@test_double,@test_string,@test_string2,@select;
@test_int @test_double @test_string @test_string2 @select
@@ -95,30 +117,34 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
Note 1003 select sql_no_cache 345 AS `@@IDENTITY`,last_insert_id() AS `last_insert_id()`,345 AS `@@identity`
set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON";
-set global concurrent_insert=ON;
+set global concurrent_insert=2;
show variables like 'concurrent_insert';
Variable_name Value
-concurrent_insert ON
+concurrent_insert 2
set global concurrent_insert=1;
show variables like 'concurrent_insert';
Variable_name Value
-concurrent_insert ON
+concurrent_insert 1
set global concurrent_insert=0;
show variables like 'concurrent_insert';
Variable_name Value
-concurrent_insert OFF
-set global concurrent_insert=OFF;
-show variables like 'concurrent_insert';
-Variable_name Value
-concurrent_insert OFF
+concurrent_insert 0
set global concurrent_insert=DEFAULT;
-show variables like 'concurrent_insert';
+select @@concurrent_insert;
+@@concurrent_insert
+1
+set global timed_mutexes=ON;
+show variables like 'timed_mutexes';
+Variable_name Value
+timed_mutexes ON
+set global timed_mutexes=0;
+show variables like 'timed_mutexes';
Variable_name Value
-concurrent_insert ON
+timed_mutexes OFF
set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="MERGE";
show local variables like 'storage_engine';
Variable_name Value
-storage_engine HEAP
+storage_engine MEMORY
show global variables like 'storage_engine';
Variable_name Value
storage_engine MERGE
@@ -230,7 +256,7 @@ set storage_engine=MERGE, big_tables=2;
ERROR 42000: Variable 'big_tables' can't be set to the value of '2'
show local variables like 'storage_engine';
Variable_name Value
-storage_engine HEAP
+storage_engine MEMORY
set SESSION query_cache_size=10000;
ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
set GLOBAL storage_engine=DEFAULT;
@@ -257,8 +283,6 @@ select @@global.sql_auto_is_null;
ERROR HY000: Variable 'sql_auto_is_null' is a SESSION variable
set myisam_max_sort_file_size=100;
ERROR HY000: Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
-set myisam_max_extra_sort_file_size=100;
-ERROR HY000: Variable 'myisam_max_extra_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
set @@SQL_WARNINGS=NULL;
ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'NULL'
set autocommit=1;
@@ -314,11 +338,6 @@ select @@max_user_connections;
@@max_user_connections
100
set global max_write_lock_count=100;
-set global myisam_max_extra_sort_file_size=100;
-select @@myisam_max_extra_sort_file_size;
-@@myisam_max_extra_sort_file_size
-100
-set global myisam_max_sort_file_size=100;
set myisam_sort_buffer_size=100;
set net_buffer_length=100;
set net_read_timeout=100;
@@ -346,6 +365,8 @@ set sql_buffer_result=1;
set sql_log_bin=1;
set sql_log_off=1;
set sql_log_update=1;
+Warnings:
+Note 1315 The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored
set sql_low_priority_updates=1;
set sql_max_join_size=200;
select @@sql_max_join_size,@@max_join_size;
@@ -472,14 +493,15 @@ t1 CREATE TABLE `t1` (
`c5` bigint(20) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
-set @arg00= 8, @arg01= 8.8, @arg02= 'a string';
-create table t1 as select @arg00 as c1, @arg01 as c2, @arg02 as c3;
+set @arg00= 8, @arg01= 8.8, @arg02= 'a string', @arg03= 0.2e0;
+create table t1 as select @arg00 as c1, @arg01 as c2, @arg02 as c3, @arg03 as c4;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` bigint(20) default NULL,
- `c2` double default NULL,
- `c3` longtext
+ `c2` decimal(65,30) default NULL,
+ `c3` longtext,
+ `c4` double default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
SET GLOBAL MYISAM_DATA_POINTER_SIZE= 7;
@@ -496,6 +518,37 @@ select ifnull(@@character_set_results,"really null");
ifnull(@@character_set_results,"really null")
really null
set names latin1;
+create table t1 (a int);
+select a into @x from t1;
+Warnings:
+Warning 1329 No data to FETCH
+show warnings;
+Level Code Message
+Warning 1329 No data to FETCH
+drop table t1;
+set @@warning_count=1;
+ERROR HY000: Variable 'warning_count' is a read only variable
+set @@global.error_count=1;
+ERROR HY000: Variable 'error_count' is a read only variable
+set @@max_heap_table_size= 4294967296;
+select @@max_heap_table_size > 0;
+@@max_heap_table_size > 0
+1
+set global max_heap_table_size= 4294967296;
+select @@max_heap_table_size > 0;
+@@max_heap_table_size > 0
+1
+set @@max_heap_table_size= 4294967296;
+select @@max_heap_table_size > 0;
+@@max_heap_table_size > 0
+1
select @@have_innodb;
@@have_innodb
#
+select @@character_set_system;
+@@character_set_system
+utf8
+set global character_set_system = latin1;
+ERROR HY000: Variable 'character_set_system' is a read only variable
+set @@global.version_compile_os='234';
+ERROR HY000: Variable 'version_compile_os' is a read only variable
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
new file mode 100644
index 00000000000..5ae99e029e7
--- /dev/null
+++ b/mysql-test/r/view.result
@@ -0,0 +1,2264 @@
+drop table if exists t1,t2,t9,`t1a``b`,v1,v2,v3,v4,v5,v6;
+drop view if exists t1,t2,`t1a``b`,v1,v2,v3,v4,v5,v6;
+drop database if exists mysqltest;
+use test;
+create view v1 (c,d) as select a,b from t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+create temporary table t1 (a int, b int);
+create view v1 (c) as select b+1 from t1;
+ERROR HY000: View's SELECT refers to a temporary table 't1'
+drop table t1;
+create table t1 (a int, b int);
+insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
+create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
+ERROR HY000: View's SELECT contains a variable or parameter
+create view v1 (c) as select b+1 from t1;
+select c from v1;
+c
+3
+4
+5
+6
+11
+create temporary table t1 (a int, b int);
+select * from t1;
+a b
+select c from v1;
+c
+3
+4
+5
+6
+11
+show create table v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1`
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1`
+show create view t1;
+ERROR HY000: 'test.t1' is not VIEW
+drop table t1;
+select a from v1;
+ERROR 42S22: Unknown column 'a' in 'field list'
+select v1.a from v1;
+ERROR 42S22: Unknown column 'v1.a' in 'field list'
+select b from v1;
+ERROR 42S22: Unknown column 'b' in 'field list'
+select v1.b from v1;
+ERROR 42S22: Unknown column 'v1.b' in 'field list'
+explain extended select c from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+Warnings:
+Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1`
+create algorithm=temptable view v2 (c) as select b+1 from t1;
+show create view v2;
+View Create View
+v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select (`t1`.`b` + 1) AS `c` from `t1`
+select c from v2;
+c
+3
+4
+5
+6
+11
+explain extended select c from v2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
+2 DERIVED t1 ALL NULL NULL NULL NULL 5
+Warnings:
+Note 1003 select `v2`.`c` AS `c` from `test`.`v2`
+create view v3 (c) as select a+1 from v1;
+ERROR 42S22: Unknown column 'a' in 'field list'
+create view v3 (c) as select b+1 from v1;
+ERROR 42S22: Unknown column 'b' in 'field list'
+create view v3 (c) as select c+1 from v1;
+select c from v3;
+c
+4
+5
+6
+7
+12
+explain extended select c from v3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+Warnings:
+Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`t1`
+create algorithm=temptable view v4 (c) as select c+1 from v2;
+select c from v4;
+c
+4
+5
+6
+7
+12
+explain extended select c from v4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
+2 DERIVED <derived3> ALL NULL NULL NULL NULL 5
+3 DERIVED t1 ALL NULL NULL NULL NULL 5
+Warnings:
+Note 1003 select `v4`.`c` AS `c` from `test`.`v4`
+create view v5 (c) as select c+1 from v2;
+select c from v5;
+c
+4
+5
+6
+7
+12
+explain extended select c from v5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived3> ALL NULL NULL NULL NULL 5
+3 DERIVED t1 ALL NULL NULL NULL NULL 5
+Warnings:
+Note 1003 select (`v2`.`c` + 1) AS `c` from `test`.`v2`
+create algorithm=temptable view v6 (c) as select c+1 from v1;
+select c from v6;
+c
+4
+5
+6
+7
+12
+explain extended select c from v6;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
+2 DERIVED t1 ALL NULL NULL NULL NULL 5
+Warnings:
+Note 1003 select `v6`.`c` AS `c` from `test`.`v6`
+show tables;
+Tables_in_test
+t1
+v1
+v2
+v3
+v4
+v5
+v6
+show full tables;
+Tables_in_test Table_type
+t1 BASE TABLE
+v1 VIEW
+v2 VIEW
+v3 VIEW
+v4 VIEW
+v5 VIEW
+v6 VIEW
+show table status;
+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 10 Fixed 5 9 45 # 1024 0 NULL # # NULL latin1_swedish_ci NULL
+v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW
+v2 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW
+v3 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW
+v4 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW
+v5 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW
+v6 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL VIEW
+drop view v1,v2,v3,v4,v5,v6;
+create view v1 (c,d,e,f) as select a,b,
+a in (select a+2 from t1), a = all (select a from t1) from t1;
+create view v2 as select c, d from v1;
+select * from v1;
+c d e f
+1 2 0 0
+1 3 0 0
+2 4 0 0
+2 5 0 0
+3 10 1 0
+select * from v2;
+c d
+1 2
+1 3
+2 4
+2 5
+3 10
+create view v1 (c,d,e,f) as select a,b, a in (select a+2 from t1), a = all (select a from t1) from t1;
+ERROR 42S01: Table 'v1' already exists
+create or replace view v1 (c,d,e,f) as select a,b, a in (select a+2 from t1), a = all (select a from t1) from t1;
+drop view v2;
+alter view v2 as select c, d from v1;
+ERROR 42S02: Table 'test.v2' doesn't exist
+create or replace view v2 as select c, d from v1;
+alter view v1 (c,d) as select a,max(b) from t1 group by a;
+select * from v1;
+c d
+1 3
+2 5
+3 10
+select * from v2;
+c d
+1 3
+2 5
+3 10
+drop view v100;
+ERROR 42S02: Unknown table 'test.v100'
+drop view t1;
+ERROR HY000: 'test.t1' is not VIEW
+drop table v1;
+ERROR 42S02: Unknown table 'v1'
+drop view v1,v2;
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+create view v1 (a) as select a+1 from t1;
+create view v2 (a) as select a-1 from t1;
+drop view v1, v2;
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1), (2), (3), (1), (2), (3);
+create view v1 as select distinct a from t1;
+select * from v1;
+a
+1
+2
+3
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a
+1
+2
+3
+1
+2
+3
+drop view v1;
+drop table t1;
+create table t1 (a int);
+create view v1 as select distinct a from t1 WITH CHECK OPTION;
+ERROR HY000: CHECK OPTION on non-updatable view 'test.v1'
+create view v1 as select a from t1 WITH CHECK OPTION;
+create view v2 as select a from t1 WITH CASCADED CHECK OPTION;
+create view v3 as select a from t1 WITH LOCAL CHECK OPTION;
+drop view v3 RESTRICT;
+drop view v2 CASCADE;
+drop view v1;
+drop table t1;
+create table t1 (a int, b int);
+insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
+create view v1 (c) as select b+1 from t1;
+select test.c from v1 test;
+c
+3
+4
+5
+6
+11
+create algorithm=temptable view v2 (c) as select b+1 from t1;
+select test.c from v2 test;
+c
+3
+4
+5
+6
+11
+select test1.* from v1 test1, v2 test2 where test1.c=test2.c;
+c
+3
+4
+5
+6
+11
+select test2.* from v1 test1, v2 test2 where test1.c=test2.c;
+c
+3
+4
+5
+6
+11
+drop table t1;
+drop view v1,v2;
+create table t1 (a int);
+insert into t1 values (1), (2), (3), (4);
+create view v1 as select a+1 from t1 order by 1 desc limit 2;
+select * from v1;
+a+1
+5
+4
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
+drop view v1;
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1), (2), (3), (4);
+create view v1 as select a+1 from t1;
+create table t2 select * from v1;
+show columns from t2;
+Field Type Null Key Default Extra
+a+1 bigint(12) YES NULL
+select * from t2;
+a+1
+2
+3
+4
+5
+drop view v1;
+drop table t1,t2;
+create table t1 (a int, b int, primary key(a));
+insert into t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
+create view v1 (a,c) as select a, b+1 from t1;
+create algorithm=temptable view v2 (a,c) as select a, b+1 from t1;
+update v1 set c=a+c;
+ERROR HY000: Column 'c' is not updatable
+update v2 set a=a+c;
+ERROR HY000: The target table v2 of the UPDATE is not updatable
+update v1 set a=a+c;
+select * from v1;
+a c
+13 3
+24 4
+35 5
+46 6
+61 11
+select * from t1;
+a b
+13 2
+24 3
+35 4
+46 5
+61 10
+drop table t1;
+drop view v1,v2;
+create table t1 (a int, b int, primary key(a));
+insert into t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
+create table t2 (x int);
+insert into t2 values (10), (20);
+create view v1 (a,c) as select a, b+1 from t1;
+create algorithm=temptable view v2 (a,c) as select a, b+1 from t1;
+update t2,v1 set v1.c=v1.a+v1.c where t2.x=v1.a;
+ERROR HY000: Column 'c' is not updatable
+update t2,v2 set v2.a=v2.v2.a+c where t2.x=v2.a;
+ERROR HY000: The target table v2 of the UPDATE is not updatable
+update t2,v1 set v1.a=v1.a+v1.c where t2.x=v1.a;
+select * from v1;
+a c
+13 3
+24 4
+30 5
+40 6
+50 11
+select * from t1;
+a b
+13 2
+24 3
+30 4
+40 5
+50 10
+drop table t1,t2;
+drop view v1,v2;
+create table t1 (a int, b int, primary key(b));
+insert into t1 values (1,20), (2,30), (3,40), (4,50), (5,100);
+create view v1 (c) as select b from t1 where a<3;
+select * from v1;
+c
+20
+30
+explain extended select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`t1` where (`test`.`t1`.`a` < 3)
+update v1 set c=c+1;
+select * from t1;
+a b
+1 21
+2 31
+3 40
+4 50
+5 100
+create view v2 (c) as select b from t1 where a>=3;
+select * from v1, v2;
+c c
+21 40
+31 40
+21 50
+31 50
+21 100
+31 100
+drop view v1, v2;
+drop table t1;
+create table t1 (a int, b int, primary key(a));
+insert into t1 values (1,2), (2,3), (3,4), (4,5), (5,10);
+create view v1 (a,c) as select a, b+1 from t1;
+create algorithm=temptable view v2 (a,c) as select a, b+1 from t1;
+delete from v2 where c < 4;
+ERROR HY000: The target table v2 of the DELETE is not updatable
+delete from v1 where c < 4;
+select * from v1;
+a c
+2 4
+3 5
+4 6
+5 11
+select * from t1;
+a b
+2 3
+3 4
+4 5
+5 10
+drop table t1;
+drop view v1,v2;
+create table t1 (a int, b int, primary key(a));
+insert into t1 values (1,2), (2,3), (3,4), (4,5), (5,10);
+create table t2 (x int);
+insert into t2 values (1), (2), (3), (4);
+create view v1 (a,c) as select a, b+1 from t1;
+create algorithm=temptable view v2 (a,c) as select a, b+1 from t1;
+delete v2 from t2,v2 where t2.x=v2.a;
+ERROR HY000: The target table v2 of the DELETE is not updatable
+delete v1 from t2,v1 where t2.x=v1.a;
+select * from v1;
+a c
+5 11
+select * from t1;
+a b
+5 10
+drop table t1,t2;
+drop view v1,v2;
+create table t1 (a int, b int, c int, primary key(a,b));
+insert into t1 values (10,2,-1), (20,3,-2), (30,4,-3), (40,5,-4), (50,10,-5);
+create view v1 (x,y) as select a, b from t1;
+create view v2 (x,y) as select a, c from t1;
+set updatable_views_with_limit=NO;
+update v1 set x=x+1;
+update v2 set x=x+1;
+update v1 set x=x+1 limit 1;
+update v2 set x=x+1 limit 1;
+ERROR HY000: The target table v2 of the UPDATE is not updatable
+set updatable_views_with_limit=YES;
+update v1 set x=x+1 limit 1;
+update v2 set x=x+1 limit 1;
+Warnings:
+Note 1355 View being updated does not have complete key of underlying table in it
+set updatable_views_with_limit=DEFAULT;
+show variables like "updatable_views_with_limit";
+Variable_name Value
+updatable_views_with_limit YES
+select * from t1;
+a b c
+15 2 -1
+22 3 -2
+32 4 -3
+42 5 -4
+52 10 -5
+drop table t1;
+drop view v1,v2;
+create table t1 (a int, b int, c int, primary key(a,b));
+insert into t1 values (10,2,-1), (20,3,-2);
+create view v1 (x,y,z) as select c, b, a from t1;
+create view v2 (x,y) as select b, a from t1;
+create view v3 (x,y,z) as select b, a, b from t1;
+create view v4 (x,y,z) as select c+1, b, a from t1;
+create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1;
+insert into v3 values (-60,4,30);
+ERROR HY000: The target table v3 of the INSERT is not updatable
+insert into v4 values (-60,4,30);
+ERROR HY000: The target table v4 of the INSERT is not updatable
+insert into v5 values (-60,4,30);
+ERROR HY000: The target table v5 of the INSERT is not updatable
+insert into v1 values (-60,4,30);
+insert into v1 (z,y,x) values (50,6,-100);
+insert into v2 values (5,40);
+select * from t1;
+a b c
+10 2 -1
+20 3 -2
+30 4 -60
+50 6 -100
+40 5 NULL
+drop table t1;
+drop view v1,v2,v3,v4,v5;
+create table t1 (a int, b int, c int, primary key(a,b));
+insert into t1 values (10,2,-1), (20,3,-2);
+create table t2 (a int, b int, c int, primary key(a,b));
+insert into t2 values (30,4,-60);
+create view v1 (x,y,z) as select c, b, a from t1;
+create view v2 (x,y) as select b, a from t1;
+create view v3 (x,y,z) as select b, a, b from t1;
+create view v4 (x,y,z) as select c+1, b, a from t1;
+create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1;
+insert into v3 select c, b, a from t2;
+ERROR HY000: The target table v3 of the INSERT is not updatable
+insert into v4 select c, b, a from t2;
+ERROR HY000: The target table v4 of the INSERT is not updatable
+insert into v5 select c, b, a from t2;
+ERROR HY000: The target table v5 of the INSERT is not updatable
+insert into v1 select c, b, a from t2;
+insert into v1 (z,y,x) select a+20,b+2,-100 from t2;
+insert into v2 select b+1, a+10 from t2;
+select * from t1;
+a b c
+10 2 -1
+20 3 -2
+30 4 -60
+50 6 -100
+40 5 NULL
+drop table t1, t2;
+drop view v1,v2,v3,v4,v5;
+create table t1 (a int, primary key(a));
+insert into t1 values (1), (2), (3);
+create view v1 (x) as select a from t1 where a > 1;
+select t1.a, v1.x from t1 left join v1 on (t1.a= v1.x);
+a x
+1 NULL
+2 2
+3 3
+drop table t1;
+drop view v1;
+create table t1 (a int, primary key(a));
+insert into t1 values (1), (2), (3), (200);
+create view v1 (x) as select a from t1 where a > 1;
+create view v2 (y) as select x from v1 where x < 100;
+select * from v2;
+y
+2
+3
+drop table t1;
+drop view v1,v2;
+create table t1 (a int, primary key(a));
+insert into t1 values (1), (2), (3), (200);
+create ALGORITHM=TEMPTABLE view v1 (x) as select a from t1;
+create view v2 (y) as select x from v1;
+update v2 set y=10 where y=2;
+ERROR HY000: The target table v2 of the UPDATE is not updatable
+drop table t1;
+drop view v1,v2;
+create table t1 (a int not null auto_increment, b int not null, primary key(a), unique(b));
+create view v1 (x) as select b from t1;
+insert into v1 values (1);
+select last_insert_id();
+last_insert_id()
+0
+insert into t1 (b) values (2);
+select last_insert_id();
+last_insert_id()
+2
+select * from t1;
+a b
+1 1
+2 2
+drop view v1;
+drop table t1;
+set sql_mode='ansi';
+create table t1 ("a*b" int);
+create view v1 as select "a*b" from t1;
+show create view v1;
+View Create View
+v1 CREATE VIEW "v1" AS select "t1"."a*b" AS "a*b" from "t1"
+drop view v1;
+drop table t1;
+set sql_mode=default;
+create table t1 (t_column int);
+create view v1 as select 'a';
+select * from v1, t1;
+a t_column
+drop view v1;
+drop table t1;
+create table `t1a``b` (col1 char(2));
+create view v1 as select * from `t1a``b`;
+select * from v1;
+col1
+describe v1;
+Field Type Null Key Default Extra
+col1 char(2) YES NULL
+drop view v1;
+drop table `t1a``b`;
+create table t1 (col1 char(5),col2 char(5));
+create view v1 as select * from t1;
+drop table t1;
+create table t1 (col1 char(5),newcol2 char(5));
+insert into v1 values('a','aa');
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s)
+drop table t1;
+select * from v1;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s)
+drop view v1;
+create view v1 (a,a) as select 'a','a';
+ERROR 42S21: Duplicate column name 'a'
+drop procedure if exists p1;
+create procedure p1 () begin declare v int; create view v1 as select v; end;//
+call p1();
+ERROR HY000: View's SELECT contains a variable or parameter
+drop procedure p1;
+create table t1 (col1 int,col2 char(22));
+insert into t1 values(5,'Hello, world of views');
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+update v2 set col2='Hello, view world';
+select * from t1;
+col1 col2
+5 Hello, view world
+drop view v2, v1;
+drop table t1;
+create table t1 (a int, b int);
+create view v1 as select a, sum(b) from t1 group by a;
+select b from v1 use index (some_index) where b=1;
+ERROR 42000: Key column 'some_index' doesn't exist in table
+drop view v1;
+drop table t1;
+create table t1 (col1 char(5),col2 char(5));
+create view v1 (col1,col2) as select col1,col2 from t1;
+insert into v1 values('s1','p1'),('s1','p2'),('s1','p3'),('s1','p4'),('s2','p1'),('s3','p2'),('s4','p4');
+select distinct first.col2 from t1 first where first.col2 in (select second.col2 from t1 second where second.col1<>first.col1);
+col2
+p1
+p2
+p4
+select distinct first.col2 from v1 first where first.col2 in (select second.col2 from t1 second where second.col1<>first.col1);
+col2
+p1
+p2
+p4
+drop view v1;
+drop table t1;
+create table t1 (a int);
+create view v1 as select a from t1;
+insert into t1 values (1);
+SET @v0 = '2';
+PREPARE stmt FROM 'UPDATE v1 SET a = ?';
+EXECUTE stmt USING @v0;
+DEALLOCATE PREPARE stmt;
+SET @v0 = '3';
+PREPARE stmt FROM 'insert into v1 values (?)';
+EXECUTE stmt USING @v0;
+DEALLOCATE PREPARE stmt;
+SET @v0 = '4';
+PREPARE stmt FROM 'insert into v1 (a) values (?)';
+EXECUTE stmt USING @v0;
+DEALLOCATE PREPARE stmt;
+select * from t1;
+a
+2
+3
+4
+drop view v1;
+drop table t1;
+CREATE VIEW v02 AS SELECT * FROM DUAL;
+ERROR HY000: No tables used
+SHOW TABLES;
+Tables_in_test
+CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2);
+select * from v1;
+EXISTS (SELECT 1 UNION SELECT 2)
+1
+drop view v1;
+create table t1 (col1 int,col2 char(22));
+create view v1 as select * from t1;
+create index i1 on v1 (col1);
+ERROR HY000: 'test.v1' is not BASE TABLE
+drop view v1;
+drop table t1;
+CREATE VIEW v1 (f1,f2,f3,f4) AS SELECT connection_id(), pi(), current_user(), version();
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache connection_id() AS `f1`,pi() AS `f2`,current_user() AS `f3`,version() AS `f4`
+drop view v1;
+create table t1 (s1 int);
+create table t2 (s2 int);
+insert into t1 values (1), (2);
+insert into t2 values (2), (3);
+create view v1 as select * from t1,t2 union all select * from t1,t2;
+select * from v1;
+s1 s2
+1 2
+2 2
+1 3
+2 3
+1 2
+2 2
+1 3
+2 3
+drop view v1;
+drop tables t1, t2;
+create table t1 (col1 int);
+insert into t1 values (1);
+create view v1 as select count(*) from t1;
+insert into t1 values (null);
+select * from v1;
+count(*)
+2
+drop view v1;
+drop table t1;
+create table t1 (a int);
+create table t2 (a int);
+create view v1 as select a from t1;
+create view v2 as select a from t2 where a in (select a from v1);
+show create view v2;
+View Create View
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where `a` in (select `v1`.`a` AS `a` from `v1`)
+drop view v2, v1;
+drop table t1, t2;
+CREATE VIEW `v 1` AS select 5 AS `5`;
+show create view `v 1`;
+View Create View
+v 1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v 1` AS select 5 AS `5`
+drop view `v 1`;
+create database mysqltest;
+create table mysqltest.t1 (a int, b int);
+create view mysqltest.v1 as select a from mysqltest.t1;
+alter view mysqltest.v1 as select b from mysqltest.t1;
+alter view mysqltest.v1 as select a from mysqltest.t1;
+drop database mysqltest;
+CREATE TABLE t1 (c1 int not null auto_increment primary key, c2 varchar(20), fulltext(c2));
+insert into t1 (c2) VALUES ('real Beer'),('Water'),('Kossu'),('Coca-Cola'),('Vodka'),('Wine'),('almost real Beer');
+select * from t1 WHERE match (c2) against ('Beer');
+c1 c2
+1 real Beer
+7 almost real Beer
+CREATE VIEW v1 AS SELECT * from t1 WHERE match (c2) against ('Beer');
+select * from v1;
+c1 c2
+1 real Beer
+7 almost real Beer
+drop view v1;
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(1),(2),(2),(3),(3);
+create view v1 as select a from t1;
+select distinct a from v1;
+a
+1
+2
+3
+select distinct a from v1 limit 2;
+a
+1
+2
+select distinct a from t1 limit 2;
+a
+1
+2
+prepare stmt1 from "select distinct a from v1 limit 2";
+execute stmt1;
+a
+1
+2
+execute stmt1;
+a
+1
+2
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+create table t1 (tg_column bigint);
+create view v1 as select count(tg_column) as vg_column from t1;
+select avg(vg_column) from v1;
+avg(vg_column)
+0.0000
+drop view v1;
+drop table t1;
+create table t1 (col1 bigint not null, primary key (col1));
+create table t2 (col1 bigint not null, key (col1));
+create view v1 as select * from t1;
+create view v2 as select * from t2;
+insert into v1 values (1);
+insert into v2 values (1);
+create view v3 (a,b) as select v1.col1 as a, v2.col1 as b from v1, v2 where v1.col1 = v2.col1;
+select * from v3;
+a b
+1 1
+show create view v3;
+View Create View
+v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `v1`.`col1` AS `a`,`v2`.`col1` AS `b` from (`v1` join `v2`) where (`v1`.`col1` = `v2`.`col1`)
+drop view v3, v2, v1;
+drop table t2, t1;
+create function `f``1` () returns int return 5;
+create view v1 as select test.`f``1` ();
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache `test`.`f``1`() AS `test.``f````1`` ()`
+select * from v1;
+test.`f``1` ()
+5
+drop view v1;
+drop function `f``1`;
+create function x () returns int return 5;
+create view v1 as select x ();
+select * from v1;
+x ()
+5
+drop view v1;
+drop function x;
+create table t2 (col1 char collate latin1_german2_ci);
+create view v2 as select col1 collate latin1_german1_ci from t2;
+show create view v2;
+View Create View
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select (`t2`.`col1` collate latin1_german1_ci) AS `col1 collate latin1_german1_ci` from `t2`
+show create view v2;
+View Create View
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select (`t2`.`col1` collate latin1_german1_ci) AS `col1 collate latin1_german1_ci` from `t2`
+drop view v2;
+drop table t2;
+create table t1 (a int);
+insert into t1 values (1), (2);
+create view v1 as select 5 from t1 order by 1;
+select * from v1;
+5
+5
+5
+drop view v1;
+drop table t1;
+create function x1 () returns int return 5;
+create table t1 (s1 int);
+create view v1 as select x1() from t1;
+drop function x1;
+select * from v1;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s)
+show table status;
+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 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL
+v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL View 'test.v1' references invalid table(s) or column(s) or function(s)
+drop view v1;
+drop table t1;
+create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1;
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 99999999999999999999999999999999999999999999999999999 AS `col1`
+drop view v1;
+create table tü (cü char);
+create view vü as select cü from tü;
+insert into vü values ('ü');
+select * from vü;
+cü
+drop view vü;
+drop table tü;
+create table t1 (a int, b int);
+insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
+create view v1(c) as select a+1 from t1 where b >= 4;
+select c from v1 where exists (select * from t1 where a=2 and b=c);
+c
+4
+drop view v1;
+drop table t1;
+create view v1 as select cast(1 as char(3));
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(1 as char(3) charset latin1) AS `cast(1 as char(3))`
+select * from v1;
+cast(1 as char(3))
+1
+drop view v1;
+create table t1 (a int);
+create view v1 as select a from t1;
+create database seconddb;
+rename table v1 to seconddb.v1;
+ERROR HY000: Changing schema from 'test' to 'seconddb' is not allowed.
+rename table v1 to v2;
+drop table t1;
+drop view v2;
+drop database seconddb;
+create view v1 as select 'a',1;
+create view v2 as select * from v1 union all select * from v1;
+create view v3 as select * from v2 where 1 = (select `1` from v2);
+create view v4 as select * from v3;
+select * from v4;
+ERROR 21000: Subquery returns more than 1 row
+drop view v4, v3, v2, v1;
+create view v1 as select 5 into @w;
+ERROR HY000: View's SELECT contains a 'INTO' clause
+create view v1 as select 5 into outfile 'ttt';
+ERROR HY000: View's SELECT contains a 'INTO' clause
+create table t1 (a int);
+create view v1 as select a from t1 procedure analyse();
+ERROR HY000: View's SELECT contains a 'PROCEDURE' clause
+drop table t1;
+create table t1 (s1 int, primary key (s1));
+create view v1 as select * from t1;
+insert into v1 values (1) on duplicate key update s1 = 7;
+insert into v1 values (1) on duplicate key update s1 = 7;
+select * from t1;
+s1
+7
+drop view v1;
+drop table t1;
+create table t1 (col1 int);
+create table t2 (col1 int);
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+create view v3 as select v2.col1 from v2,t2 where v2.col1 = t2.col1;
+update v2 set col1 = (select max(col1) from v1);
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'v2'.
+update v2 set col1 = (select max(col1) from t1);
+ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v2'.
+update v2 set col1 = (select max(col1) from v2);
+ERROR HY000: You can't specify target table 'v2' for update in FROM clause
+update v2,t2 set v2.col1 = (select max(col1) from v1) where v2.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'v2'.
+update t1,t2 set t1.col1 = (select max(col1) from v1) where t1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't1'.
+update v1,t2 set v1.col1 = (select max(col1) from v1) where v1.col1 = t2.col1;
+ERROR HY000: You can't specify target table 'v1' for update in FROM clause
+update t2,v2 set v2.col1 = (select max(col1) from v1) where v2.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't2'.
+update t2,t1 set t1.col1 = (select max(col1) from v1) where t1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't2'.
+update t2,v1 set v1.col1 = (select max(col1) from v1) where v1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't2'.
+update v2,t2 set v2.col1 = (select max(col1) from t1) where v2.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v2'.
+update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
+update v1,t2 set v1.col1 = (select max(col1) from t1) where v1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'v1'.
+update t2,v2 set v2.col1 = (select max(col1) from t1) where v2.col1 = t2.col1;
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+update t2,t1 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+update t2,v1 set v1.col1 = (select max(col1) from t1) where v1.col1 = t2.col1;
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+update v2,t2 set v2.col1 = (select max(col1) from v2) where v2.col1 = t2.col1;
+ERROR HY000: You can't specify target table 'v2' for update in FROM clause
+update t1,t2 set t1.col1 = (select max(col1) from v2) where t1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 't1'.
+update v1,t2 set v1.col1 = (select max(col1) from v2) where v1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v1'.
+update t2,v2 set v2.col1 = (select max(col1) from v2) where v2.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 't2'.
+update t2,t1 set t1.col1 = (select max(col1) from v2) where t1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 't2'.
+update t2,v1 set v1.col1 = (select max(col1) from v2) where v1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 't2'.
+update v3 set v3.col1 = (select max(col1) from v1);
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'v3'.
+update v3 set v3.col1 = (select max(col1) from t1);
+ERROR HY000: The definition of table 'v3' prevents operation UPDATE on table 'v3'.
+update v3 set v3.col1 = (select max(col1) from v2);
+ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v3'.
+update v3 set v3.col1 = (select max(col1) from v3);
+ERROR HY000: You can't specify target table 'v3' for update in FROM clause
+delete from v2 where col1 = (select max(col1) from v1);
+ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2'.
+delete from v2 where col1 = (select max(col1) from t1);
+ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 'v2'.
+delete from v2 where col1 = (select max(col1) from v2);
+ERROR HY000: You can't specify target table 'v2' for update in FROM clause
+delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2'.
+delete t1 from t1,t2 where (select max(col1) from v1) > 0 and t1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 't1'.
+delete v1 from v1,t2 where (select max(col1) from v1) > 0 and v1.col1 = t2.col1;
+ERROR HY000: You can't specify target table 'v1' for update in FROM clause
+delete v2 from v2,t2 where (select max(col1) from t1) > 0 and v2.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 'v2'.
+delete t1 from t1,t2 where (select max(col1) from t1) > 0 and t1.col1 = t2.col1;
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
+delete v1 from v1,t2 where (select max(col1) from t1) > 0 and v1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v1'.
+delete v2 from v2,t2 where (select max(col1) from v2) > 0 and v2.col1 = t2.col1;
+ERROR HY000: You can't specify target table 'v2' for update in FROM clause
+delete t1 from t1,t2 where (select max(col1) from v2) > 0 and t1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 't1'.
+delete v1 from v1,t2 where (select max(col1) from v2) > 0 and v1.col1 = t2.col1;
+ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 'v1'.
+insert into v2 values ((select max(col1) from v1));
+ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v2'.
+insert into t1 values ((select max(col1) from v1));
+ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 't1'.
+insert into v2 values ((select max(col1) from v1));
+ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v2'.
+insert into v2 values ((select max(col1) from t1));
+ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v2'.
+insert into t1 values ((select max(col1) from t1));
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
+insert into v2 values ((select max(col1) from t1));
+ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v2'.
+insert into v2 values ((select max(col1) from v2));
+ERROR HY000: You can't specify target table 'v2' for update in FROM clause
+insert into t1 values ((select max(col1) from v2));
+ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 't1'.
+insert into v2 values ((select max(col1) from v2));
+ERROR HY000: You can't specify target table 'v2' for update in FROM clause
+insert into v3 (col1) values ((select max(col1) from v1));
+ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v3'.
+insert into v3 (col1) values ((select max(col1) from t1));
+ERROR HY000: The definition of table 'v3' prevents operation INSERT on table 'v3'.
+insert into v3 (col1) values ((select max(col1) from v2));
+ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v3'.
+insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from v2));
+ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v3'.
+insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from t2));
+insert into mysql.time_zone values ('', (select CONVERT_TZ('20050101000000','UTC','MET') from t2));
+ERROR 23000: Column 'Use_leap_seconds' cannot be null
+create algorithm=temptable view v4 as select * from t1;
+insert into t1 values (1),(2),(3);
+insert into t1 (col1) values ((select max(col1) from v4));
+select * from t1;
+col1
+NULL
+1
+2
+3
+3
+drop view v4,v3,v2,v1;
+drop table t1,t2;
+create table t1 (s1 int);
+create view v1 as select * from t1;
+handler v1 open as xx;
+ERROR HY000: 'test.v1' is not BASE TABLE
+drop view v1;
+drop table t1;
+create table t1(a int);
+insert into t1 values (0), (1), (2), (3);
+create table t2 (a int);
+insert into t2 select a from t1 where a > 1;
+create view v1 as select a from t1 where a > 1;
+select * from t1 left join (t2 as t, v1) on v1.a=t1.a;
+a a a
+0 NULL NULL
+1 NULL NULL
+2 2 2
+2 3 2
+3 2 3
+3 3 3
+select * from t1 left join (t2 as t, t2) on t2.a=t1.a;
+a a a
+0 NULL NULL
+1 NULL NULL
+2 2 2
+2 3 2
+3 2 3
+3 3 3
+drop view v1;
+drop table t1, t2;
+create table t1 (s1 char);
+create view v1 as select s1 collate latin1_german1_ci as s1 from t1;
+insert into v1 values ('a');
+select * from v1;
+s1
+a
+update v1 set s1='b';
+select * from v1;
+s1
+b
+update v1,t1 set v1.s1='c' where t1.s1=v1.s1;
+select * from v1;
+s1
+c
+prepare stmt1 from "update v1,t1 set v1.s1=? where t1.s1=v1.s1";
+set @arg='d';
+execute stmt1 using @arg;
+select * from v1;
+s1
+d
+set @arg='e';
+execute stmt1 using @arg;
+select * from v1;
+s1
+e
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+create table t1 (a int);
+create table t2 (a int);
+create view v1 as select * from t1;
+lock tables t1 read, v1 read;
+select * from v1;
+a
+select * from t2;
+ERROR HY000: Table 't2' was not locked with LOCK TABLES
+drop view v1;
+drop table t1, t2;
+create table t1 (a int);
+create view v1 as select * from t1 where a < 2 with check option;
+insert into v1 values(1);
+insert into v1 values(3);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+insert ignore into v1 values (2),(3),(0);
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a
+1
+0
+delete from t1;
+insert into v1 SELECT 1;
+insert into v1 SELECT 3;
+ERROR HY000: CHECK OPTION failed 'test.v1'
+create table t2 (a int);
+insert into t2 values (2),(3),(0);
+insert ignore into v1 SELECT a from t2;
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a
+1
+0
+update v1 set a=-1 where a=0;
+update v1 set a=2 where a=1;
+ERROR HY000: CHECK OPTION failed 'test.v1'
+select * from t1;
+a
+1
+-1
+update v1 set a=0 where a=0;
+insert into t2 values (1);
+update v1,t2 set v1.a=v1.a-1 where v1.a=t2.a;
+select * from t1;
+a
+0
+-1
+update v1 set a=a+1;
+update ignore v1,t2 set v1.a=v1.a+1 where v1.a=t2.a;
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a
+1
+1
+drop view v1;
+drop table t1, t2;
+create table t1 (a int);
+create view v1 as select * from t1 where a < 2 with check option;
+create view v2 as select * from v1 where a > 0 with local check option;
+create view v3 as select * from v1 where a > 0 with cascaded check option;
+insert into v2 values (1);
+insert into v3 values (1);
+insert into v2 values (0);
+ERROR HY000: CHECK OPTION failed 'test.v2'
+insert into v3 values (0);
+ERROR HY000: CHECK OPTION failed 'test.v3'
+insert into v2 values (2);
+insert into v3 values (2);
+ERROR HY000: CHECK OPTION failed 'test.v3'
+select * from t1;
+a
+1
+1
+2
+drop view v3,v2,v1;
+drop table t1;
+create table t1 (a int, primary key (a));
+create view v1 as select * from t1 where a < 2 with check option;
+insert into v1 values (1) on duplicate key update a=2;
+insert into v1 values (1) on duplicate key update a=2;
+ERROR HY000: CHECK OPTION failed 'test.v1'
+insert ignore into v1 values (1) on duplicate key update a=2;
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a
+1
+drop view v1;
+drop table t1;
+create table t1 (s1 int);
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+alter view v1 as select * from v2;
+ERROR 42S02: Table 'test.v1' doesn't exist
+alter view v1 as select * from v1;
+ERROR 42S02: Table 'test.v1' doesn't exist
+create or replace view v1 as select * from v2;
+ERROR 42S02: Table 'test.v1' doesn't exist
+create or replace view v1 as select * from v1;
+ERROR 42S02: Table 'test.v1' doesn't exist
+drop view v2,v1;
+drop table t1;
+create table t1 (a int);
+create view v1 as select * from t1;
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1`
+alter algorithm=undefined view v1 as select * from t1 with check option;
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` WITH CASCADED CHECK OPTION
+alter algorithm=merge view v1 as select * from t1 with cascaded check option;
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` WITH CASCADED CHECK OPTION
+alter algorithm=temptable view v1 as select * from t1;
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1`
+drop view v1;
+drop table t1;
+create table t1 (s1 int);
+create table t2 (s1 int);
+create view v2 as select * from t2 where s1 in (select s1 from t1);
+insert into v2 values (5);
+insert into t1 values (5);
+select * from v2;
+s1
+5
+update v2 set s1 = 0;
+select * from v2;
+s1
+select * from t2;
+s1
+0
+alter view v2 as select * from t2 where s1 in (select s1 from t1) with check option;
+insert into v2 values (5);
+update v2 set s1 = 1;
+ERROR HY000: CHECK OPTION failed 'test.v2'
+insert into t1 values (1);
+update v2 set s1 = 1;
+select * from v2;
+s1
+1
+select * from t2;
+s1
+0
+1
+prepare stmt1 from "select * from v2;";
+execute stmt1;
+s1
+1
+insert into t1 values (0);
+execute stmt1;
+s1
+0
+1
+deallocate prepare stmt1;
+drop view v2;
+drop table t1, t2;
+create table t1 (t time);
+create view v1 as select substring_index(t,':',2) as t from t1;
+insert into t1 (t) values ('12:24:10');
+select substring_index(t,':',2) from t1;
+substring_index(t,':',2)
+12:24
+select substring_index(t,':',2) from v1;
+substring_index(t,':',2)
+12:24
+drop view v1;
+drop table t1;
+create table t1 (s1 tinyint);
+create view v1 as select * from t1 where s1 <> 0 with local check option;
+create view v2 as select * from v1 with cascaded check option;
+insert into v2 values (0);
+ERROR HY000: CHECK OPTION failed 'test.v2'
+drop view v2, v1;
+drop table t1;
+create table t1 (s1 int);
+create view v1 as select * from t1 where s1 < 5 with check option;
+insert ignore into v1 values (6);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+insert ignore into v1 values (6),(3);
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+s1
+3
+drop view v1;
+drop table t1;
+create table t1 (s1 tinyint);
+create trigger t1_bi before insert on t1 for each row set new.s1 = 500;
+create view v1 as select * from t1 where s1 <> 127 with check option;
+insert into v1 values (0);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+select * from v1;
+s1
+select * from t1;
+s1
+drop trigger t1_bi;
+drop view v1;
+drop table t1;
+create table t1 (s1 tinyint);
+create view v1 as select * from t1 where s1 <> 0;
+create view v2 as select * from v1 where s1 <> 1 with cascaded check option;
+insert into v2 values (0);
+ERROR HY000: CHECK OPTION failed 'test.v2'
+select * from v2;
+s1
+select * from t1;
+s1
+drop view v2, v1;
+drop table t1;
+create table t1 (a int, b char(10));
+create view v1 as select * from t1 where a != 0 with check option;
+load data infile '../../std_data/loaddata3.dat' into table v1 fields terminated by '' enclosed by '' ignore 1 lines;
+ERROR HY000: CHECK OPTION failed 'test.v1'
+select * from t1;
+a b
+1 row 1
+2 row 2
+select * from v1;
+a b
+1 row 1
+2 row 2
+delete from t1;
+load data infile '../../std_data/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines;
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a b
+1 row 1
+2 row 2
+3 row 3
+select * from v1;
+a b
+1 row 1
+2 row 2
+3 row 3
+drop view v1;
+drop table t1;
+create table t1 (a text, b text);
+create view v1 as select * from t1 where a <> 'Field A' with check option;
+load data infile '../../std_data/loaddata2.dat' into table v1 fields terminated by ',' enclosed by '''';
+ERROR HY000: CHECK OPTION failed 'test.v1'
+select concat('|',a,'|'), concat('|',b,'|') from t1;
+concat('|',a,'|') concat('|',b,'|')
+select concat('|',a,'|'), concat('|',b,'|') from v1;
+concat('|',a,'|') concat('|',b,'|')
+delete from t1;
+load data infile '../../std_data/loaddata2.dat' ignore into table v1 fields terminated by ',' enclosed by '''';
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1261 Row 2 doesn't contain data for all columns
+select concat('|',a,'|'), concat('|',b,'|') from t1;
+concat('|',a,'|') concat('|',b,'|')
+|Field 1| |Field 2'
+Field 3,'Field 4|
+|Field 5' ,'Field 6| NULL
+|Field 6| | 'Field 7'|
+select concat('|',a,'|'), concat('|',b,'|') from v1;
+concat('|',a,'|') concat('|',b,'|')
+|Field 1| |Field 2'
+Field 3,'Field 4|
+|Field 5' ,'Field 6| NULL
+|Field 6| | 'Field 7'|
+drop view v1;
+drop table t1;
+create table t1 (s1 smallint);
+create view v1 as select * from t1 where 20 < (select (s1) from t1);
+insert into v1 values (30);
+ERROR HY000: The target table v1 of the INSERT is not updatable
+create view v2 as select * from t1;
+create view v3 as select * from t1 where 20 < (select (s1) from v2);
+insert into v3 values (30);
+ERROR HY000: The target table v3 of the INSERT is not updatable
+create view v4 as select * from v2 where 20 < (select (s1) from t1);
+insert into v4 values (30);
+ERROR HY000: The target table v4 of the INSERT is not updatable
+drop view v4, v3, v2, v1;
+drop table t1;
+create table t1 (a int);
+create view v1 as select * from t1;
+check table t1,v1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+test.v1 check status OK
+check table v1,t1;
+Table Op Msg_type Msg_text
+test.v1 check status OK
+test.t1 check status OK
+drop table t1;
+check table v1;
+Table Op Msg_type Msg_text
+test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s)
+drop view v1;
+create table t1 (a int);
+create table t2 (a int);
+create table t3 (a int);
+insert into t1 values (1), (2), (3);
+insert into t2 values (1), (3);
+insert into t3 values (1), (2), (4);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1 left join t2 on (t1.a=t2.a);
+select * from t3 left join v3 on (t3.a = v3.a);
+a a b
+1 1 1
+2 2 NULL
+4 NULL NULL
+explain extended select * from t3 left join v3 on (t3.a = v3.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 3
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2
+Warnings:
+Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join `test`.`t2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
+create view v1 (a) as select a from t1;
+create view v2 (a) as select a from t2;
+create view v4 (a,b) as select v1.a as a, v2.a as b from v1 left join v2 on (v1.a=v2.a);
+select * from t3 left join v4 on (t3.a = v4.a);
+a a b
+1 1 1
+2 2 NULL
+4 NULL NULL
+explain extended select * from t3 left join v4 on (t3.a = v4.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 3
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2
+Warnings:
+Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join (`test`.`t2`) on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
+prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
+execute stmt1;
+a a b
+1 1 1
+2 2 NULL
+4 NULL NULL
+execute stmt1;
+a a b
+1 1 1
+2 2 NULL
+4 NULL NULL
+deallocate prepare stmt1;
+drop view v4,v3,v2,v1;
+drop tables t1,t2,t3;
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a));
+insert into t1 values (1,100), (2,200);
+insert into t2 values (1), (3);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+update v3 set a= 10 where a=1;
+select * from t1;
+a b
+10 100
+2 200
+select * from t2;
+a
+1
+3
+create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
+set updatable_views_with_limit=NO;
+update v2 set a= 10 where a=200 limit 1;
+ERROR HY000: The target table t1 of the UPDATE is not updatable
+set updatable_views_with_limit=DEFAULT;
+select * from v3;
+a b
+2 1
+10 1
+2 3
+10 3
+select * from v2;
+a b
+100 1
+200 1
+100 3
+200 3
+set @a= 10;
+set @b= 100;
+prepare stmt1 from "update v3 set a= ? where a=?";
+execute stmt1 using @a,@b;
+select * from v3;
+a b
+2 1
+10 1
+2 3
+10 3
+set @a= 300;
+set @b= 10;
+execute stmt1 using @a,@b;
+select * from v3;
+a b
+2 1
+300 1
+2 3
+300 3
+deallocate prepare stmt1;
+drop view v3,v2;
+drop tables t1,t2;
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a), b int);
+insert into t2 values (1000, 2000);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+insert into v3 values (1,2);
+ERROR HY000: Can not insert into join view 'test.v3' without fields list
+insert into v3 select * from t2;
+ERROR HY000: Can not insert into join view 'test.v3' without fields list
+insert into v3(a,b) values (1,2);
+ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
+insert into v3(a,b) select * from t2;
+ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
+insert into v3(a) values (1);
+insert into v3(b) values (10);
+insert into v3(a) select a from t2;
+insert into v3(b) select b from t2;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 2
+insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a);
+select * from t1;
+a b
+10002 NULL
+10 NULL
+1000 NULL
+select * from t2;
+a b
+1000 2000
+10 NULL
+2000 NULL
+0 NULL
+delete from v3;
+ERROR HY000: Can not delete from join view 'test.v3'
+delete v3,t1 from v3,t1;
+ERROR HY000: Can not delete from join view 'test.v3'
+delete t1,v3 from t1,v3;
+ERROR HY000: Can not delete from join view 'test.v3'
+delete from t1;
+prepare stmt1 from "insert into v3(a) values (?);";
+set @a= 100;
+execute stmt1 using @a;
+set @a= 300;
+execute stmt1 using @a;
+deallocate prepare stmt1;
+prepare stmt1 from "insert into v3(a) select ?;";
+set @a= 101;
+execute stmt1 using @a;
+set @a= 301;
+execute stmt1 using @a;
+deallocate prepare stmt1;
+select * from v3;
+a b
+100 1000
+101 1000
+300 1000
+301 1000
+100 10
+101 10
+300 10
+301 10
+100 2000
+101 2000
+300 2000
+301 2000
+100 0
+101 0
+300 0
+301 0
+drop view v3;
+drop tables t1,t2;
+create table t1(f1 int);
+create view v1 as select f1 from t1;
+select * from v1 where F1 = 1;
+f1
+drop view v1;
+drop table t1;
+create table t1(c1 int);
+create table t2(c2 int);
+insert into t1 values (1),(2),(3);
+insert into t2 values (1);
+SELECT c1 FROM t1 WHERE c1 IN (SELECT c2 FROM t2);
+c1
+1
+SELECT c1 FROM t1 WHERE EXISTS (SELECT c2 FROM t2 WHERE c2 = c1);
+c1
+1
+create view v1 as SELECT c1 FROM t1 WHERE c1 IN (SELECT c2 FROM t2);
+create view v2 as SELECT c1 FROM t1 WHERE EXISTS (SELECT c2 FROM t2 WHERE c2 = c1);
+select * from v1;
+c1
+1
+select * from v2;
+c1
+1
+select * from (select c1 from v2) X;
+c1
+1
+drop view v2, v1;
+drop table t1, t2;
+CREATE TABLE t1 (C1 INT, C2 INT);
+CREATE TABLE t2 (C2 INT);
+CREATE VIEW v1 AS SELECT C2 FROM t2;
+CREATE VIEW v2 AS SELECT C1 FROM t1 LEFT OUTER JOIN v1 USING (C2);
+SELECT * FROM v2;
+C1
+drop view v2, v1;
+drop table t1, t2;
+create table t1 (col1 char(5),col2 int,col3 int);
+insert into t1 values ('one',10,25), ('two',10,50), ('two',10,50), ('one',20,25), ('one',30,25);
+create view v1 as select * from t1;
+select col1,group_concat(col2,col3) from t1 group by col1;
+col1 group_concat(col2,col3)
+one 1025,2025,3025
+two 1050,1050
+select col1,group_concat(col2,col3) from v1 group by col1;
+col1 group_concat(col2,col3)
+one 1025,2025,3025
+two 1050,1050
+drop view v1;
+drop table t1;
+create table t1 (s1 int, s2 char);
+create view v1 as select s1, s2 from t1;
+select s2 from v1 vq1 where 2 = (select count(*) from v1 vq2 having vq1.s2 = vq2.s2);
+ERROR 42S22: Unknown column 'vq2.s2' in 'having clause'
+select s2 from v1 vq1 where 2 = (select count(*) aa from v1 vq2 having vq1.s2 = aa);
+s2
+drop view v1;
+drop table t1;
+CREATE TABLE t1 (a1 int);
+CREATE TABLE t2 (a2 int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+INSERT INTO t2 VALUES (1), (2), (3);
+CREATE VIEW v1(a,b) AS SELECT a1,a2 FROM t1 JOIN t2 ON a1=a2 WHERE a1>1;
+SELECT * FROM v1;
+a b
+2 2
+3 3
+CREATE TABLE t3 SELECT * FROM v1;
+SELECT * FROM t3;
+a b
+2 2
+3 3
+DROP VIEW v1;
+DROP TABLE t1,t2,t3;
+create table t1 (a int);
+create table t2 like t1;
+create table t3 like t1;
+create view v1 as select t1.a x, t2.a y from t1 join t2 where t1.a=t2.a;
+insert into t3 select x from v1;
+insert into t2 select x from v1;
+drop view v1;
+drop table t1,t2,t3;
+CREATE TABLE t1 (col1 int PRIMARY KEY, col2 varchar(10));
+INSERT INTO t1 VALUES(1,'trudy');
+INSERT INTO t1 VALUES(2,'peter');
+INSERT INTO t1 VALUES(3,'sanja');
+INSERT INTO t1 VALUES(4,'monty');
+INSERT INTO t1 VALUES(5,'david');
+INSERT INTO t1 VALUES(6,'kent');
+INSERT INTO t1 VALUES(7,'carsten');
+INSERT INTO t1 VALUES(8,'ranger');
+INSERT INTO t1 VALUES(10,'matt');
+CREATE TABLE t2 (col1 int, col2 int, col3 char(1));
+INSERT INTO t2 VALUES (1,1,'y');
+INSERT INTO t2 VALUES (1,2,'y');
+INSERT INTO t2 VALUES (2,1,'n');
+INSERT INTO t2 VALUES (3,1,'n');
+INSERT INTO t2 VALUES (4,1,'y');
+INSERT INTO t2 VALUES (4,2,'n');
+INSERT INTO t2 VALUES (4,3,'n');
+INSERT INTO t2 VALUES (6,1,'n');
+INSERT INTO t2 VALUES (8,1,'y');
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT a.col1,a.col2,b.col2,b.col3
+FROM t1 a LEFT JOIN t2 b ON a.col1=b.col1
+WHERE b.col2 IS NULL OR
+b.col2=(SELECT MAX(col2) FROM t2 b WHERE b.col1=a.col1);
+col1 col2 col2 col3
+1 trudy 2 y
+2 peter 1 n
+3 sanja 1 n
+4 monty 3 n
+5 david NULL NULL
+6 kent 1 n
+7 carsten NULL NULL
+8 ranger 1 y
+10 matt NULL NULL
+SELECT a.col1,a.col2,b.col2,b.col3
+FROM v1 a LEFT JOIN t2 b ON a.col1=b.col1
+WHERE b.col2 IS NULL OR
+b.col2=(SELECT MAX(col2) FROM t2 b WHERE b.col1=a.col1);
+col1 col2 col2 col3
+1 trudy 2 y
+2 peter 1 n
+3 sanja 1 n
+4 monty 3 n
+5 david NULL NULL
+6 kent 1 n
+7 carsten NULL NULL
+8 ranger 1 y
+10 matt NULL NULL
+CREATE VIEW v2 AS SELECT * FROM t2;
+SELECT a.col1,a.col2,b.col2,b.col3
+FROM v2 b RIGHT JOIN v1 a ON a.col1=b.col1
+WHERE b.col2 IS NULL OR
+b.col2=(SELECT MAX(col2) FROM v2 b WHERE b.col1=a.col1);
+col1 col2 col2 col3
+1 trudy 2 y
+2 peter 1 n
+3 sanja 1 n
+4 monty 3 n
+5 david NULL NULL
+6 kent 1 n
+7 carsten NULL NULL
+8 ranger 1 y
+10 matt NULL NULL
+SELECT a.col1,a.col2,b.col2,b.col3
+FROM v2 b RIGHT JOIN v1 a ON a.col1=b.col1
+WHERE a.col1 IN (1,5,9) AND
+(b.col2 IS NULL OR
+b.col2=(SELECT MAX(col2) FROM v2 b WHERE b.col1=a.col1));
+col1 col2 col2 col3
+1 trudy 2 y
+5 david NULL NULL
+CREATE VIEW v3 AS SELECT * FROM t1 WHERE col1 IN (1,5,9);
+SELECT a.col1,a.col2,b.col2,b.col3
+FROM v2 b RIGHT JOIN v3 a ON a.col1=b.col1
+WHERE b.col2 IS NULL OR
+b.col2=(SELECT MAX(col2) FROM v2 b WHERE b.col1=a.col1);
+col1 col2 col2 col3
+1 trudy 2 y
+5 david NULL NULL
+DROP VIEW v1,v2,v3;
+DROP TABLE t1,t2;
+create table t1 as select 1 A union select 2 union select 3;
+create table t2 as select * from t1;
+create view v1 as select * from t1 where a in (select * from t2);
+select * from v1 A, v1 B where A.a = B.a;
+A A
+1 1
+2 2
+3 3
+create table t3 as select a a,a b from t2;
+create view v2 as select * from t3 where
+a in (select * from t1) or b in (select * from t2);
+select * from v2 A, v2 B where A.a = B.b;
+a b a b
+1 1 1 1
+2 2 2 2
+3 3 3 3
+drop view v1, v2;
+drop table t1, t2, t3;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+INSERT INTO t2 VALUES (4), (2);
+CREATE VIEW v1 AS SELECT * FROM t1,t2 WHERE t1.a=t2.b;
+SELECT * FROM v1;
+a b
+2 2
+4 4
+CREATE VIEW v2 AS SELECT * FROM v1;
+SELECT * FROM v2;
+a b
+2 2
+4 4
+DROP VIEW v2,v1;
+DROP TABLE t1, t2;
+create table t1 (a int);
+create view v1 as select sum(a) from t1 group by a;
+create procedure p1()
+begin
+select * from v1;
+end//
+call p1();
+sum(a)
+call p1();
+sum(a)
+drop procedure p1;
+drop view v1;
+drop table t1;
+CREATE TABLE t1(a char(2) primary key, b char(2));
+CREATE TABLE t2(a char(2), b char(2), index i(a));
+INSERT INTO t1 VALUES ('a','1'), ('b','2');
+INSERT INTO t2 VALUES ('a','5'), ('a','6'), ('b','5'), ('b','6');
+CREATE VIEW v1 AS
+SELECT t1.b as c, t2.b as d FROM t1,t2 WHERE t1.a=t2.a;
+SELECT d, c FROM v1 ORDER BY d,c;
+d c
+5 1
+5 2
+6 1
+6 2
+DROP VIEW v1;
+DROP TABLE t1, t2;
+create table t1 (s1 int);
+create view v1 as select sum(distinct s1) from t1;
+select * from v1;
+sum(distinct s1)
+NULL
+drop view v1;
+create view v1 as select avg(distinct s1) from t1;
+select * from v1;
+avg(distinct s1)
+NULL
+drop view v1;
+drop table t1;
+create view v1 as select cast(1 as decimal);
+select * from v1;
+cast(1 as decimal)
+1.00
+drop view v1;
+create table t1(f1 int);
+create table t2(f2 int);
+insert into t1 values(1),(2),(3);
+insert into t2 values(1),(2),(3);
+create view v1 as select * from t1,t2 where f1=f2;
+create table t3 (f1 int, f2 int);
+insert into t3 select * from v1 order by 1;
+select * from t3;
+f1 f2
+1 1
+2 2
+3 3
+drop view v1;
+drop table t1,t2,t3;
+create view v1 as select '\\','\\shazam';
+select * from v1;
+\ \shazam
+\ \shazam
+drop view v1;
+create view v1 as select '\'','\shazam';
+select * from v1;
+' shazam
+' shazam
+drop view v1;
+create view v1 as select 'k','K';
+select * from v1;
+k My_exp_K
+k K
+drop view v1;
+create table t1 (s1 int);
+create view v1 as select s1, 's1' from t1;
+select * from v1;
+s1 My_exp_s1
+drop view v1;
+create view v1 as select 's1', s1 from t1;
+select * from v1;
+My_exp_s1 s1
+drop view v1;
+create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
+select * from v1;
+My_exp_1_s1 s1 My_exp_s1
+drop view v1;
+create view v1 as select 1 as My_exp_s1, 's1', s1 from t1;
+select * from v1;
+My_exp_s1 My_exp_1_s1 s1
+drop view v1;
+create view v1 as select 1 as s1, 's1', 's1' from t1;
+select * from v1;
+s1 My_exp_s1 My_exp_1_s1
+drop view v1;
+create view v1 as select 's1', 's1', 1 as s1 from t1;
+select * from v1;
+My_exp_1_s1 My_exp_s1 s1
+drop view v1;
+create view v1 as select s1, 's1', 's1' from t1;
+select * from v1;
+s1 My_exp_s1 My_exp_1_s1
+drop view v1;
+create view v1 as select 's1', 's1', s1 from t1;
+select * from v1;
+My_exp_1_s1 My_exp_s1 s1
+drop view v1;
+create view v1 as select 1 as s1, 's1', s1 from t1;
+ERROR 42S21: Duplicate column name 's1'
+create view v1 as select 's1', s1, 1 as s1 from t1;
+ERROR 42S21: Duplicate column name 's1'
+drop table t1;
+create view v1(k, K) as select 1,2;
+ERROR 42S21: Duplicate column name 'K'
+create view v1 as SELECT TIME_FORMAT(SEC_TO_TIME(3600),'%H:%i') as t;
+select * from v1;
+t
+01:00
+drop view v1;
+create table t1 (a timestamp default now());
+create table t2 (b timestamp default now());
+create view v1 as select a,b,t1.a < now() from t1,t2 where t1.a < now();
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache `t1`.`a` AS `a`,`t2`.`b` AS `b`,(`t1`.`a` < now()) AS `t1.a < now()` from (`t1` join `t2`) where (`t1`.`a` < now())
+drop view v1;
+drop table t1, t2;
+CREATE TABLE t1 ( a varchar(50) );
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE a = CURRENT_USER();
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache `t1`.`a` AS `a` from `t1` where (`t1`.`a` = current_user())
+DROP VIEW v1;
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE a = VERSION();
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` where (`t1`.`a` = version())
+DROP VIEW v1;
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE a = DATABASE();
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache `t1`.`a` AS `a` from `t1` where (`t1`.`a` = database())
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (col1 time);
+CREATE TABLE t2 (col1 time);
+CREATE VIEW v1 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1;
+CREATE VIEW v2 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2;
+CREATE VIEW v3 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1;
+CREATE VIEW v4 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2;
+CREATE VIEW v5 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1;
+CREATE VIEW v6 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2;
+DROP TABLE t1;
+CHECK TABLE v1, v2, v3, v4, v5, v6;
+Table Op Msg_type Msg_text
+test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s)
+test.v2 check status OK
+test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s)
+test.v4 check status OK
+test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s)
+test.v6 check status OK
+drop view v1, v2, v3, v4, v5, v6;
+drop table t2;
+drop function if exists f1;
+drop function if exists f2;
+CREATE TABLE t1 (col1 time);
+CREATE TABLE t2 (col1 time);
+CREATE TABLE t3 (col1 time);
+create function f1 () returns int return (select max(col1) from t1);
+create function f2 () returns int return (select max(col1) from t2);
+CREATE VIEW v1 AS SELECT f1() FROM t3;
+CREATE VIEW v2 AS SELECT f2() FROM t3;
+CREATE VIEW v3 AS SELECT f1() FROM t3;
+CREATE VIEW v4 AS SELECT f2() FROM t3;
+CREATE VIEW v5 AS SELECT f1() FROM t3;
+CREATE VIEW v6 AS SELECT f2() FROM t3;
+drop function f1;
+CHECK TABLE v1, v2, v3, v4, v5, v6;
+Table Op Msg_type Msg_text
+test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s)
+test.v2 check status OK
+test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s)
+test.v4 check status OK
+test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s)
+test.v6 check status OK
+create function f1 () returns int return (select max(col1) from t1);
+DROP TABLE t1;
+CHECK TABLE v1, v2, v3, v4, v5, v6;
+Table Op Msg_type Msg_text
+test.v1 check error Table 'test.t1' doesn't exist
+test.v2 check status OK
+test.v3 check error Table 'test.t1' doesn't exist
+test.v4 check status OK
+test.v5 check error Table 'test.t1' doesn't exist
+test.v6 check status OK
+drop function f1;
+drop function f2;
+drop view v1, v2, v3, v4, v5, v6;
+drop table t2,t3;
+create table t1 (f1 date);
+insert into t1 values ('2005-01-01'),('2005-02-02');
+create view v1 as select * from t1;
+select * from v1 where f1='2005.02.02';
+f1
+2005-02-02
+select * from v1 where '2005.02.02'=f1;
+f1
+2005-02-02
+drop view v1;
+drop table t1;
+CREATE VIEW v1 AS SELECT ENCRYPT("dhgdhgd");
+SELECT * FROM v1;
+drop view v1;
+CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1);
+SELECT * FROM v1;
+SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1)
+dkjhgd
+drop view v1;
+create table t1 (f59 int, f60 int, f61 int);
+insert into t1 values (19,41,32);
+create view v1 as select f59, f60 from t1 where f59 in
+(select f59 from t1);
+update v1 set f60=2345;
+ERROR HY000: The target table v1 of the UPDATE is not updatable
+update t1 set f60=(select max(f60) from v1);
+ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't1'.
+drop view v1;
+drop table t1;
+create table t1 (s1 int);
+create view v1 as select var_samp(s1) from t1;
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select var_samp(`t1`.`s1`) AS `var_samp(s1)` from `t1`
+drop view v1;
+drop table t1;
+set sql_mode='strict_all_tables';
+CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
+CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
+CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
+INSERT INTO t1 (col1) VALUES(12);
+ERROR HY000: Field 'col2' doesn't have a default value
+INSERT INTO v1 (vcol1) VALUES(12);
+ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
+INSERT INTO v2 (vcol1) VALUES(12);
+ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
+set sql_mode=default;
+drop view v2,v1;
+drop table t1;
+create table t1 (f1 int);
+insert into t1 values (1);
+create view v1 as select f1 from t1;
+select f1 as alias from v1;
+alias
+1
+drop view v1;
+drop table t1;
+CREATE TABLE t1 (s1 int, s2 int);
+INSERT INTO t1 VALUES (1,2);
+CREATE VIEW v1 AS SELECT s2 AS s1, s1 AS s2 FROM t1;
+SELECT * FROM v1;
+s1 s2
+2 1
+CREATE PROCEDURE p1 () SELECT * FROM v1;
+CALL p1();
+s1 s2
+2 1
+ALTER VIEW v1 AS SELECT s1 AS s1, s2 AS s2 FROM t1;
+CALL p1();
+s1 s2
+1 2
+DROP VIEW v1;
+CREATE VIEW v1 AS SELECT s2 AS s1, s1 AS s2 FROM t1;
+CALL p1();
+s1 s2
+2 1
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
+create table t1 (f1 int, f2 int);
+create view v1 as select f1 as f3, f2 as f1 from t1;
+insert into t1 values (1,3),(2,1),(3,2);
+select * from v1 order by f1;
+f3 f1
+2 1
+3 2
+1 3
+drop view v1;
+drop table t1;
+CREATE TABLE t1 (f1 char) ENGINE = innodb;
+INSERT INTO t1 VALUES ('A');
+CREATE VIEW v1 AS SELECT * FROM t1;
+INSERT INTO t1 VALUES('B');
+SELECT * FROM v1;
+f1
+A
+B
+SELECT * FROM t1;
+f1
+A
+B
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 ( bug_table_seq INTEGER NOT NULL);
+CREATE OR REPLACE VIEW v1 AS SELECT * from t1;
+DROP PROCEDURE IF EXISTS p1;
+Warnings:
+Note 1305 PROCEDURE p1 does not exist
+CREATE PROCEDURE p1 ( )
+BEGIN
+DO (SELECT @next := IFNULL(max(bug_table_seq),0) + 1 FROM v1);
+INSERT INTO t1 VALUES (1);
+END //
+CALL p1();
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
+create table t1 (f1 tinyint(1), f2 char(1), f3 varchar(1), f4 geometry, f5 datetime);
+create view v1 as select * from t1;
+desc v1;
+Field Type Null Key Default Extra
+f1 tinyint(1) YES NULL
+f2 char(1) YES NULL
+f3 varchar(1) YES NULL
+f4 geometry YES NULL
+f5 datetime YES NULL
+drop view v1;
+drop table t1;
+create table t1(f1 datetime);
+insert into t1 values('2005.01.01 12:0:0');
+create view v1 as select f1, subtime(f1, '1:1:1') as sb from t1;
+select * from v1;
+f1 sb
+2005-01-01 12:00:00 2005-01-01 10:58:59
+drop view v1;
+drop table t1;
+CREATE TABLE t1 (
+aid int PRIMARY KEY,
+fn varchar(20) NOT NULL,
+ln varchar(20) NOT NULL
+);
+CREATE TABLE t2 (
+aid int NOT NULL,
+pid int NOT NULL
+);
+INSERT INTO t1 VALUES(1,'a','b'), (2,'c','d');
+INSERT INTO t2 values (1,1), (2,1), (2,2);
+CREATE VIEW v1 AS SELECT t1.*,t2.pid FROM t1,t2 WHERE t1.aid = t2.aid;
+SELECT pid,GROUP_CONCAT(CONCAT(fn,' ',ln) ORDER BY 1) FROM t1,t2
+WHERE t1.aid = t2.aid GROUP BY pid;
+pid GROUP_CONCAT(CONCAT(fn,' ',ln) ORDER BY 1)
+1 a b,c d
+2 c d
+SELECT pid,GROUP_CONCAT(CONCAT(fn,' ',ln) ORDER BY 1) FROM v1 GROUP BY pid;
+pid GROUP_CONCAT(CONCAT(fn,' ',ln) ORDER BY 1)
+1 a b,c d
+2 c d
+DROP VIEW v1;
+DROP TABLE t1,t2;
+CREATE TABLE t1 (id int PRIMARY KEY, f varchar(255));
+CREATE VIEW v1 AS SELECT id, f FROM t1 WHERE id <= 2;
+INSERT INTO t1 VALUES (2, 'foo2');
+INSERT INTO t1 VALUES (1, 'foo1');
+SELECT * FROM v1;
+id f
+1 foo1
+2 foo2
+SELECT * FROM v1;
+id f
+1 foo1
+2 foo2
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (pk int PRIMARY KEY, b int);
+CREATE TABLE t2 (pk int PRIMARY KEY, fk int, INDEX idx(fk));
+CREATE TABLE t3 (pk int PRIMARY KEY, fk int, INDEX idx(fk));
+CREATE TABLE t4 (pk int PRIMARY KEY, fk int, INDEX idx(fk));
+CREATE TABLE t5 (pk int PRIMARY KEY, fk int, INDEX idx(fk));
+CREATE VIEW v1 AS
+SELECT t1.pk as a FROM t1,t2,t3,t4,t5
+WHERE t1.b IS NULL AND
+t1.pk=t2.fk AND t2.pk=t3.fk AND t3.pk=t4.fk AND t4.pk=t5.fk;
+SELECT a FROM v1;
+a
+DROP VIEW v1;
+DROP TABLE t1,t2,t3,t4,t5;
+create view v1 as select timestampdiff(day,'1997-01-01 00:00:00','1997-01-02 00:00:00') as f1;
+select * from v1;
+f1
+1
+drop view v1;
+create table t1(a int);
+create procedure p1() create view v1 as select * from t1;
+drop table t1;
+call p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+call p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop procedure p1;
+create table t1 (f1 int);
+create table t2 (f1 int);
+insert into t1 values (1);
+insert into t2 values (2);
+create view v1 as select * from t1 union select * from t2 union all select * from t2;
+select * from v1;
+f1
+1
+2
+2
+drop view v1;
+drop table t1,t2;
+CREATE TEMPORARY TABLE t1 (a int);
+CREATE FUNCTION f1 () RETURNS int RETURN (SELECT COUNT(*) FROM t1);
+CREATE VIEW v1 AS SELECT f1();
+ERROR HY000: View's SELECT refers to a temporary table 't1'
+DROP FUNCTION f1;
+DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+CREATE TABLE t1 (f4 CHAR(5));
+CREATE VIEW v1 AS SELECT * FROM t1;
+DESCRIBE v1;
+Field Type Null Key Default Extra
+f4 char(5) YES NULL
+ALTER TABLE t1 CHANGE COLUMN f4 f4x CHAR(5);
+DESCRIBE v1;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s)
+DROP TABLE t1;
+DROP VIEW v1;
+create table t1 (f1 char);
+create view v1 as select strcmp(f1,'a') from t1;
+select * from v1;
+strcmp(f1,'a')
+drop view v1;
+drop table t1;
+create table t1 (f1 int, f2 int,f3 int);
+insert into t1 values (1,10,20),(2,0,0);
+create view v1 as select * from t1;
+select if(sum(f1)>1,f2,f3) from v1 group by f1;
+if(sum(f1)>1,f2,f3)
+20
+0
+drop view v1;
+drop table t1;
+create table t1 (
+r_object_id char(16) NOT NULL,
+group_name varchar(32) NOT NULL
+) engine = InnoDB;
+create table t2 (
+r_object_id char(16) NOT NULL,
+i_position int(11) NOT NULL,
+users_names varchar(32) default NULL
+) Engine = InnoDB;
+create view v1 as select r_object_id, group_name from t1;
+create view v2 as select r_object_id, i_position, users_names from t2;
+create unique index r_object_id on t1(r_object_id);
+create index group_name on t1(group_name);
+create unique index r_object_id_i_position on t2(r_object_id,i_position);
+create index users_names on t2(users_names);
+insert into t1 values('120001a080000542','tstgroup1');
+insert into t2 values('120001a080000542',-1, 'guser01');
+insert into t2 values('120001a080000542',-2, 'guser02');
+select v1.r_object_id, v2.users_names from v1, v2
+where (v1.group_name='tstgroup1') and v2.r_object_id=v1.r_object_id
+order by users_names;
+r_object_id users_names
+120001a080000542 guser01
+120001a080000542 guser02
+drop view v1, v2;
+drop table t1, t2;
+create definer=some_user@__% sql security invoker view v1 as select 1;
+ERROR HY000: View definer is not fully qualified
+create definer=some_user@localhost sql security invoker view v1 as select 1;
+Warnings:
+Note 1449 There is not some_user@localhost registered
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1`
+drop view v1;
+create table t1 (s1 int);
+create view abc as select * from t1 as abc;
+drop table t1;
+drop view abc;
+create table t1(f1 char(1));
+create view v1 as select * from t1;
+select * from (select f1 as f2 from v1) v where v.f2='a';
+f2
+drop view v1;
+drop table t1;
+create view v1 as SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
+select * from v1;
+CONVERT_TZ('2004-01-01 12:00:00','GMT','MET')
+NULL
+drop view v1;
+CREATE TABLE t1 (date DATE NOT NULL);
+INSERT INTO t1 VALUES ('2005-09-06');
+CREATE VIEW v1 AS SELECT DAYNAME(date) FROM t1;
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select dayname(`t1`.`date`) AS `DAYNAME(date)` from `t1`
+CREATE VIEW v2 AS SELECT DAYOFWEEK(date) FROM t1;
+SHOW CREATE VIEW v2;
+View Create View
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select dayofweek(`t1`.`date`) AS `DAYOFWEEK(date)` from `t1`
+CREATE VIEW v3 AS SELECT WEEKDAY(date) FROM t1;
+SHOW CREATE VIEW v3;
+View Create View
+v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select weekday(`t1`.`date`) AS `WEEKDAY(date)` from `t1`
+SELECT DAYNAME('2005-09-06');
+DAYNAME('2005-09-06')
+Tuesday
+SELECT DAYNAME(date) FROM t1;
+DAYNAME(date)
+Tuesday
+SELECT * FROM v1;
+DAYNAME(date)
+Tuesday
+SELECT DAYOFWEEK('2005-09-06');
+DAYOFWEEK('2005-09-06')
+3
+SELECT DAYOFWEEK(date) FROM t1;
+DAYOFWEEK(date)
+3
+SELECT * FROM v2;
+DAYOFWEEK(date)
+3
+SELECT WEEKDAY('2005-09-06');
+WEEKDAY('2005-09-06')
+1
+SELECT WEEKDAY(date) FROM t1;
+WEEKDAY(date)
+1
+SELECT * FROM v3;
+WEEKDAY(date)
+1
+DROP TABLE t1;
+DROP VIEW v1, v2, v3;
diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result
new file mode 100644
index 00000000000..bac6e691069
--- /dev/null
+++ b/mysql-test/r/view_grant.result
@@ -0,0 +1,309 @@
+grant create view on test.* to test@localhost;
+show grants for test@localhost;
+Grants for test@localhost
+GRANT USAGE ON *.* TO 'test'@'localhost'
+GRANT CREATE VIEW ON `test`.* TO 'test'@'localhost'
+revoke create view on test.* from test@localhost;
+show grants for test@localhost;
+Grants for test@localhost
+GRANT USAGE ON *.* TO 'test'@'localhost'
+create database mysqltest;
+create table mysqltest.t1 (a int, b int);
+create table mysqltest.t2 (a int, b int);
+grant select on mysqltest.t1 to mysqltest_1@localhost;
+grant create view,select on test.* to mysqltest_1@localhost;
+create definer=root@localhost view v1 as select * from mysqltest.t1;
+ERROR HY000: You need the SUPER privilege for creation view with root@localhost definer
+create view v1 as select * from mysqltest.t1;
+alter view v1 as select * from mysqltest.t1;
+ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 'v1'
+create or replace view v1 as select * from mysqltest.t1;
+ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 'v1'
+create view mysqltest.v2 as select * from mysqltest.t1;
+ERROR 42000: CREATE VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2'
+create view v2 as select * from mysqltest.t2;
+ERROR 42000: ANY command denied to user 'mysqltest_1'@'localhost' for table 't2'
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_1`@`localhost` SQL SECURITY DEFINER VIEW `test`.`v1` AS select `mysqltest`.`t1`.`a` AS `a`,`mysqltest`.`t1`.`b` AS `b` from `mysqltest`.`t1`
+grant create view,drop,select on test.* to mysqltest_1@localhost;
+use test;
+alter view v1 as select * from mysqltest.t1;
+create or replace view v1 as select * from mysqltest.t1;
+revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
+revoke all privileges on test.* from mysqltest_1@localhost;
+drop database mysqltest;
+drop view test.v1;
+create database mysqltest;
+create table mysqltest.t1 (a int, b int);
+create view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1;
+grant select (c) on mysqltest.v1 to mysqltest_1@localhost;
+select c from mysqltest.v1;
+c
+select d from mysqltest.v1;
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'd' in table 'v1'
+revoke all privileges on mysqltest.v1 from mysqltest_1@localhost;
+delete from mysql.user where user='mysqltest_1';
+drop database mysqltest;
+create database mysqltest;
+create table mysqltest.t1 (a int, b int);
+create algorithm=temptable view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1;
+grant select (c) on mysqltest.v1 to mysqltest_1@localhost;
+select c from mysqltest.v1;
+c
+select d from mysqltest.v1;
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'd' in table 'v1'
+revoke all privileges on mysqltest.v1 from mysqltest_1@localhost;
+delete from mysql.user where user='mysqltest_1';
+drop database mysqltest;
+create database mysqltest;
+create table mysqltest.t1 (a int, b int);
+create table mysqltest.t2 (a int, b int);
+create view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1;
+create algorithm=temptable view mysqltest.v2 (c,d) as select a+1,b+1 from mysqltest.t1;
+create view mysqltest.v3 (c,d) as select a+1,b+1 from mysqltest.t2;
+create algorithm=temptable view mysqltest.v4 (c,d) as select a+1,b+1 from mysqltest.t2;
+grant select on mysqltest.v1 to mysqltest_1@localhost;
+grant select on mysqltest.v2 to mysqltest_1@localhost;
+grant select on mysqltest.v3 to mysqltest_1@localhost;
+grant select on mysqltest.v4 to mysqltest_1@localhost;
+select c from mysqltest.v1;
+c
+select c from mysqltest.v2;
+c
+select c from mysqltest.v3;
+c
+select c from mysqltest.v4;
+c
+show columns from mysqltest.v1;
+Field Type Null Key Default Extra
+c bigint(12) YES NULL
+d bigint(12) YES NULL
+show columns from mysqltest.v2;
+Field Type Null Key Default Extra
+c bigint(12) YES NULL
+d bigint(12) YES NULL
+explain select c from mysqltest.v1;
+ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
+show create view mysqltest.v1;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1'
+explain select c from mysqltest.v2;
+ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
+show create view mysqltest.v2;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2'
+explain select c from mysqltest.v3;
+ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
+show create view mysqltest.v3;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v3'
+explain select c from mysqltest.v4;
+ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
+show create view mysqltest.v4;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v4'
+grant select on mysqltest.t1 to mysqltest_1@localhost;
+explain select c from mysqltest.v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
+show create view mysqltest.v1;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1'
+explain select c from mysqltest.v2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+show create view mysqltest.v2;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2'
+explain select c from mysqltest.v3;
+ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
+show create view mysqltest.v3;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v3'
+explain select c from mysqltest.v4;
+ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
+show create view mysqltest.v4;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v4'
+grant show view on mysqltest.* to mysqltest_1@localhost;
+explain select c from mysqltest.v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
+show create view mysqltest.v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1`
+explain select c from mysqltest.v2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+show create view mysqltest.v2;
+View Create View
+v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v2` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1`
+explain select c from mysqltest.v3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 system NULL NULL NULL NULL 0 const row not found
+show create view mysqltest.v3;
+View Create View
+v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2`
+explain select c from mysqltest.v4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+show create view mysqltest.v4;
+View Create View
+v4 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v4` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2`
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+delete from mysql.user where user='mysqltest_1';
+drop database mysqltest;
+create database mysqltest;
+create table mysqltest.t1 (a int, b int, primary key(a));
+insert into mysqltest.t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
+create table mysqltest.t2 (x int);
+insert into mysqltest.t2 values (3), (4), (5), (6);
+create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1;
+create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1;
+create view mysqltest.v3 (a,c) as select a, b+1 from mysqltest.t1;
+grant update (a) on mysqltest.v2 to mysqltest_1@localhost;
+grant update on mysqltest.v1 to mysqltest_1@localhost;
+grant select on mysqltest.* to mysqltest_1@localhost;
+use mysqltest;
+update t2,v1 set v1.a=v1.a+v1.c where t2.x=v1.c;
+select * from t1;
+a b
+13 2
+24 3
+35 4
+46 5
+50 10
+update v1 set a=a+c;
+select * from t1;
+a b
+16 2
+28 3
+40 4
+52 5
+61 10
+update t2,v2 set v2.a=v2.a+v2.c where t2.x=v2.c;
+select * from t1;
+a b
+16 2
+31 3
+44 4
+57 5
+61 10
+update v2 set a=a+c;
+select * from t1;
+a b
+18 2
+34 3
+48 4
+62 5
+71 10
+update t2,v2 set v2.c=v2.a+v2.c where t2.x=v2.c;
+ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for column 'c' in table 'v2'
+update v2 set c=a+c;
+ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for column 'c' in table 'v2'
+update t2,v3 set v3.a=v3.a+v3.c where t2.x=v3.c;
+ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for table 'v3'
+update v3 set a=a+c;
+ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for table 'v3'
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
+drop database mysqltest;
+create database mysqltest;
+create table mysqltest.t1 (a int, b int, primary key(a));
+insert into mysqltest.t1 values (1,2), (2,3), (3,4), (4,5), (5,10);
+create table mysqltest.t2 (x int);
+insert into mysqltest.t2 values (3), (4), (5), (6);
+create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1;
+create view mysqltest.v2 (a,c) as select a, b+1 from mysqltest.t1;
+grant delete on mysqltest.v1 to mysqltest_1@localhost;
+grant select on mysqltest.* to mysqltest_1@localhost;
+use mysqltest;
+delete from v1 where c < 4;
+select * from t1;
+a b
+2 3
+3 4
+4 5
+5 10
+delete v1 from t2,v1 where t2.x=v1.c;
+select * from t1;
+a b
+5 10
+delete v2 from t2,v2 where t2.x=v2.c;
+ERROR 42000: DELETE command denied to user 'mysqltest_1'@'localhost' for table 'v2'
+delete from v2 where c < 4;
+ERROR 42000: DELETE command denied to user 'mysqltest_1'@'localhost' for table 'v2'
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
+drop database mysqltest;
+create database mysqltest;
+create table mysqltest.t1 (a int, b int, primary key(a));
+insert into mysqltest.t1 values (1,2), (2,3);
+create table mysqltest.t2 (x int, y int);
+insert into mysqltest.t2 values (3,4);
+create view mysqltest.v1 (a,c) as select a, b from mysqltest.t1;
+create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1;
+grant insert on mysqltest.v1 to mysqltest_1@localhost;
+grant select on mysqltest.* to mysqltest_1@localhost;
+use mysqltest;
+insert into v1 values (5,6);
+select * from t1;
+a b
+1 2
+2 3
+5 6
+insert into v1 select x,y from t2;
+select * from t1;
+a b
+1 2
+2 3
+5 6
+3 4
+insert into v2 values (5,6);
+ERROR 42000: INSERT command denied to user 'mysqltest_1'@'localhost' for table 'v2'
+insert into v2 select x,y from t2;
+ERROR 42000: INSERT command denied to user 'mysqltest_1'@'localhost' for table 'v2'
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
+drop database mysqltest;
+create database mysqltest;
+create table mysqltest.t1 (a int, b int);
+create table mysqltest.t2 (a int, b int);
+grant update on mysqltest.t1 to mysqltest_1@localhost;
+grant update(b) on mysqltest.t2 to mysqltest_1@localhost;
+grant create view,update on test.* to mysqltest_1@localhost;
+create view v1 as select * from mysqltest.t1;
+create view v2 as select b from mysqltest.t2;
+create view mysqltest.v1 as select * from mysqltest.t1;
+ERROR 42000: CREATE VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1'
+create view v3 as select a from mysqltest.t2;
+ERROR 42000: ANY command denied to user 'mysqltest_1'@'localhost' for column 'a' in table 't2'
+create table mysqltest.v3 (b int);
+grant create view on mysqltest.v3 to mysqltest_1@localhost;
+drop table mysqltest.v3;
+create view mysqltest.v3 as select b from mysqltest.t2;
+grant create view, update on mysqltest.v3 to mysqltest_1@localhost;
+drop view mysqltest.v3;
+create view mysqltest.v3 as select b from mysqltest.t2;
+grant create view, update, insert on mysqltest.v3 to mysqltest_1@localhost;
+drop view mysqltest.v3;
+create view mysqltest.v3 as select b from mysqltest.t2;
+ERROR 42000: create view command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 'v3'
+create table mysqltest.v3 (b int);
+grant select(b) on mysqltest.v3 to mysqltest_1@localhost;
+drop table mysqltest.v3;
+create view mysqltest.v3 as select b from mysqltest.t2;
+ERROR 42000: create view command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 'v3'
+create view v4 as select b+1 from mysqltest.t2;
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 't2'
+grant create view,update,select on test.* to mysqltest_1@localhost;
+create view v4 as select b+1 from mysqltest.t2;
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 't2'
+grant update,select(b) on mysqltest.t2 to mysqltest_1@localhost;
+create view v4 as select b+1 from mysqltest.t2;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
+drop database mysqltest;
+drop view v1,v2,v4;
+create database mysqltest;
+create table mysqltest.t1 (a int);
+grant all privileges on mysqltest.* to mysqltest_1@localhost;
+use mysqltest;
+create view v1 as select * from t1;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+drop database mysqltest;
diff --git a/mysql-test/r/view_query_cache.result b/mysql-test/r/view_query_cache.result
new file mode 100644
index 00000000000..e6c2c0152f3
--- /dev/null
+++ b/mysql-test/r/view_query_cache.result
@@ -0,0 +1,126 @@
+drop table if exists t1,t2,v1,v2,v3;
+drop view if exists t1,t2,v1,v2,v3;
+set GLOBAL query_cache_size=1355776;
+flush status;
+create table t1 (a int, b int);
+create view v1 (c,d) as select sql_no_cache a,b from t1;
+create view v2 (c,d) as select a+rand(),b from t1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from v1;
+c d
+select * from v2;
+c d
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from v1;
+c d
+select * from v2;
+c d
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+drop view v1,v2;
+set query_cache_type=demand;
+flush status;
+create view v1 (c,d) as select sql_cache a,b from t1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from v1;
+c d
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a b
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from v1;
+c d
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+select * from t1;
+a b
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+drop view v1;
+set query_cache_type=default;
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+create view v1 as select a from t1 where a > 1;
+select * from v1;
+a
+2
+3
+alter view v1 as select a from t1 where a > 2;
+select * from v1;
+a
+3
+drop view v1;
+select * from v1;
+ERROR 42S02: Table 'test.v1' doesn't exist
+drop table t1;
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a), b int);
+insert into t2 values (1000, 2000);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+select * from v3;
+a b
+drop view v3;
+drop table t1, t2;
+set GLOBAL query_cache_size=default;
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index b9c05bc388c..d8329e446ac 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -31,19 +31,19 @@ Error 1064 You have an error in your SQL syntax; check the manual that correspon
insert into t1 values (1);
insert into t1 values ("hej");
Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 1
insert into t1 values ("hej"),("då");
Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
-Warning 1265 Data truncated for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
set SQL_WARNINGS=1;
insert into t1 values ("hej");
Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 1
insert into t1 values ("hej"),("då");
Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
-Warning 1265 Data truncated for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
drop table t1;
set SQL_WARNINGS=0;
drop temporary table if exists not_exists;
@@ -72,13 +72,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 Column set to default value; 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 1264 Out of range value adjusted for column 'a' at row 8
select @@warning_count;
@@warning_count
7
@@ -86,11 +86,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 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
+Warning 1264 Out of range value adjusted 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 Out of range value adjusted for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'b' at row 3
Warning 1265 Data truncated for column 'c' at row 3
alter table t1 modify c char(4);
Warnings:
@@ -99,7 +99,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 Column set to default value; 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
@@ -115,14 +115,16 @@ 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 Column set to default value; 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:
+Warning 1364 Field 'a' doesn't have a default value
Warning 1265 Data truncated for column 'b' at row 1
set sql_warnings=1;
insert into t2(b) values('mysqlab');
Warnings:
+Warning 1364 Field 'a' doesn't have a default value
Warning 1265 Data truncated for column 'b' at row 1
set sql_warnings=0;
drop table t1, t2;
@@ -185,44 +187,44 @@ create table t1 (a int);
insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
update t1 set a='abc';
Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
-Warning 1265 Data truncated for column 'a' at row 2
-Warning 1265 Data truncated for column 'a' at row 3
-Warning 1265 Data truncated for column 'a' at row 4
-Warning 1265 Data truncated for column 'a' at row 5
-Warning 1265 Data truncated for column 'a' at row 6
-Warning 1265 Data truncated for column 'a' at row 7
-Warning 1265 Data truncated for column 'a' at row 8
-Warning 1265 Data truncated for column 'a' at row 9
-Warning 1265 Data truncated for column 'a' at row 10
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+Warning 1264 Out of range value adjusted for column 'a' at row 5
+Warning 1264 Out of range value adjusted for column 'a' at row 6
+Warning 1264 Out of range value adjusted for column 'a' at row 7
+Warning 1264 Out of range value adjusted for column 'a' at row 8
+Warning 1264 Out of range value adjusted for column 'a' at row 9
+Warning 1264 Out of range value adjusted for column 'a' at row 10
show warnings limit 2, 1;
Level Code Message
-Warning 1265 Data truncated for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 3
show warnings limit 0, 10;
Level Code Message
-Warning 1265 Data truncated for column 'a' at row 1
-Warning 1265 Data truncated for column 'a' at row 2
-Warning 1265 Data truncated for column 'a' at row 3
-Warning 1265 Data truncated for column 'a' at row 4
-Warning 1265 Data truncated for column 'a' at row 5
-Warning 1265 Data truncated for column 'a' at row 6
-Warning 1265 Data truncated for column 'a' at row 7
-Warning 1265 Data truncated for column 'a' at row 8
-Warning 1265 Data truncated for column 'a' at row 9
-Warning 1265 Data truncated for column 'a' at row 10
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 2
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+Warning 1264 Out of range value adjusted for column 'a' at row 5
+Warning 1264 Out of range value adjusted for column 'a' at row 6
+Warning 1264 Out of range value adjusted for column 'a' at row 7
+Warning 1264 Out of range value adjusted for column 'a' at row 8
+Warning 1264 Out of range value adjusted for column 'a' at row 9
+Warning 1264 Out of range value adjusted for column 'a' at row 10
show warnings limit 9, 1;
Level Code Message
-Warning 1265 Data truncated for column 'a' at row 10
+Warning 1264 Out of range value adjusted for column 'a' at row 10
show warnings limit 10, 1;
Level Code Message
show warnings limit 9, 2;
Level Code Message
-Warning 1265 Data truncated for column 'a' at row 10
+Warning 1264 Out of range value adjusted for column 'a' at row 10
show warnings limit 0, 0;
Level Code Message
show warnings limit 1;
Level Code Message
-Warning 1265 Data truncated for column 'a' at row 1
+Warning 1264 Out of range value adjusted for column 'a' at row 1
show warnings limit 0;
Level Code Message
show warnings limit 1, 0;
diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result
new file mode 100644
index 00000000000..f3d7e151628
--- /dev/null
+++ b/mysql-test/r/xa.result
@@ -0,0 +1,47 @@
+drop table if exists t1, t2;
+create table t1 (a int) engine=innodb;
+xa start 'test1';
+insert t1 values (10);
+xa end 'test1';
+xa prepare 'test1';
+xa rollback 'test1';
+select * from t1;
+a
+xa start 'test2';
+xa start 'test-bad';
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed in the ACTIVE state
+insert t1 values (20);
+xa prepare 'test2';
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed in the ACTIVE state
+xa end 'test2';
+xa prepare 'test2';
+xa commit 'test2';
+select * from t1;
+a
+20
+xa start 'testa','testb';
+insert t1 values (30);
+xa end 'testa','testb';
+xa start 'testa','testb';
+ERROR XAE08: XAER_DUPID: The XID already exists
+xa start 0x7465737462, 0x2030405060, 0xb;
+insert t1 values (40);
+xa end 'testb',' 0@P`',11;
+xa prepare 'testb',0x2030405060,11;
+xa recover;
+formatID gtrid_length bqual_length data
+11 5 5 testb 0@P`
+xa prepare 'testa','testb';
+xa recover;
+formatID gtrid_length bqual_length data
+11 5 5 testb 0@P`
+1 5 5 testatestb
+xa commit 'testb',0x2030405060,11;
+ERROR XAE04: XAER_NOTA: Unknown XID
+xa rollback 'testa','testb';
+xa start 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
+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 * from t1;
+a
+20
+drop table t1;
diff --git a/mysql-test/std_data/loaddata5.dat b/mysql-test/std_data/loaddata5.dat
new file mode 100644
index 00000000000..6e1881bd8e2
--- /dev/null
+++ b/mysql-test/std_data/loaddata5.dat
@@ -0,0 +1,3 @@
+1 2
+3 4
+5 6
diff --git a/mysql-test/std_data/rpl_timezone.dat b/mysql-test/std_data/rpl_timezone.dat
new file mode 100644
index 00000000000..2df8a39f1e3
--- /dev/null
+++ b/mysql-test/std_data/rpl_timezone.dat
@@ -0,0 +1,2 @@
+20040101000000
+20040611093902
diff --git a/mysql-test/std_data/trunc_binlog.000001 b/mysql-test/std_data/trunc_binlog.000001
index 2c2b4ec6ce4..3da2490eab2 100644
--- a/mysql-test/std_data/trunc_binlog.000001
+++ b/mysql-test/std_data/trunc_binlog.000001
Binary files differ
diff --git a/mysql-test/std_data/vchar.frm b/mysql-test/std_data/vchar.frm
new file mode 100644
index 00000000000..5f037261d5f
--- /dev/null
+++ b/mysql-test/std_data/vchar.frm
Binary files differ
diff --git a/mysql-test/t/alias.test b/mysql-test/t/alias.test
index 941bc8091fc..2746409c7e5 100644
--- a/mysql-test/t/alias.test
+++ b/mysql-test/t/alias.test
@@ -30,7 +30,7 @@ CREATE TABLE t1 (
prov_hdl_nr int(11) NOT NULL default '0',
auto_wirknetz varchar(50) default NULL,
auto_billing varchar(50) default NULL,
- touch timestamp(14) NOT NULL,
+ touch timestamp NOT NULL,
kategorie varchar(50) default NULL,
kundentyp varchar(20) NOT NULL default '',
sammel_rech_msisdn varchar(30) NOT NULL default '',
@@ -61,8 +61,9 @@ INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05
INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
# This died because we used the field Kundentyp twice
-
+--disable_ps_protocol
SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie;
+--enable_ps_protocol
drop table t1;
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 9bd34c2a610..5695822be6b 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -338,6 +338,14 @@ alter table t1 drop key a;
drop table t1;
#
+# BUG 12207 alter table ... discard table space on MyISAM table causes ERROR 2013 (HY000)
+#
+CREATE TABLE T12207(a int) ENGINE=MYISAM;
+--error 1031
+ALTER TABLE T12207 DISCARD TABLESPACE;
+DROP TABLE T12207;
+
+#
# Bug #6479 ALTER TABLE ... changing charset fails for TEXT columns
#
# The column's character set was changed but the actual data was not
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index e38e43381bc..4060892c389 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -48,6 +48,14 @@ insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),(
select * from t1 procedure analyse();
drop table t1;
+#decimal-related test
+
+create table t1 (df decimal(5,1));
+insert into t1 values(1.1);
+insert into t1 values(2.2);
+select * from t1 procedure analyse();
+drop table t1;
+
#
# Bug#10716 - Procedure Analyse results in wrong values for optimal field type
#
@@ -58,3 +66,4 @@ select * from t1 procedure analyse (1,1);
drop table t1;
# End of 4.1 tests
+
diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
index f10ff0f648e..4318525fe43 100644
--- a/mysql-test/t/archive.test
+++ b/mysql-test/t/archive.test
@@ -1289,16 +1289,6 @@ 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;
-OPTIMIZE TABLE t2;
-SELECT * FROM t2;
#
# Test rename of table
@@ -1306,14 +1296,38 @@ SELECT * FROM t2;
create table t3 engine=archive select * from t2;
select * from t3 where fld3='bonfire';
select count(*) from t3;
+# Clean up path in error message
+--replace_result $MYSQL_TEST_DIR . /var/master-data/ /
rename table t3 to t4;
select * from t4 where fld3='bonfire';
select count(*) from t4;
-
# End of 4.1 tests
#
+# 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;
+OPTIMIZE TABLE t2;
+SELECT * FROM t2;
+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','');
+OPTIMIZE TABLE t2 EXTENDED;
+SELECT * FROM t2;
+REPAIR TABLE t2;
+SELECT * FROM t2;
+
+#
+# Test bulk inserts
+INSERT INTO t2 VALUES (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','');
+SELECT * FROM t2;
+
+#
# For bug #12836
# Delete was allowing all rows to be removed
DELETE FROM t2;
@@ -1325,4 +1339,13 @@ SELECT * FROM t2;
TRUNCATE TABLE t2;
SELECT * FROM t2;
+
+# Just test syntax, we will never know if the out put is right or wrong
+# Must be the last test
+INSERT DELAYED INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
+#
+# Cleanup, test is over
+#
+
+
drop table t1, t2, t4;
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index b6a0aeb9a19..b20fe80303d 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -220,3 +220,39 @@ CHECK TABLE t1;
DROP TABLE IF EXISTS t1;
# End of 4.1 tests
+
+#
+# Bug #11080 & #11005 Multi-row REPLACE fails on a duplicate key error
+#
+
+CREATE TABLE t1 ( `a` int(11) NOT NULL auto_increment, `b` int(11) default NULL,PRIMARY KEY (`a`),UNIQUE KEY `b` (`b`));
+insert into t1 (b) values (1);
+replace into t1 (b) values (2), (1), (3);
+select * from t1;
+truncate table t1;
+insert into t1 (b) values (1);
+replace into t1 (b) values (2);
+replace into t1 (b) values (1);
+replace into t1 (b) values (3);
+select * from t1;
+drop table t1;
+
+create table t1 (rowid int not null auto_increment, val int not null,primary
+key (rowid), unique(val));
+replace into t1 (val) values ('1'),('2');
+replace into t1 (val) values ('1'),('2');
+--error 1062
+insert into t1 (val) values ('1'),('2');
+select * from t1;
+drop table t1;
+
+#
+# Test that update changes internal auto-increment value
+#
+
+create table t1 (a int not null auto_increment primary key, val int);
+insert into t1 (val) values (1);
+update t1 set a=2 where a=1;
+insert into t1 (val) values (1);
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test
index b6b3ef1c060..3034129ad4b 100644
--- a/mysql-test/t/backup.test
+++ b/mysql-test/t/backup.test
@@ -10,10 +10,10 @@ set SQL_LOG_BIN=0;
drop table if exists t1, t2, t3;
--enable_warnings
create table t4(n int);
---replace_result "errno: 1" "errno: X" "errno: 2" "errno: X" "errno: 22" "errno: X" "errno: 23" "errno: X"
+--replace_result ": 1" ": X" ": 2" ": X" ": 22" ": X" ": 23" ": X" $MYSQL_TEST_DIR MYSQL_TEST_DIR
backup table t4 to '../bogus';
backup table t4 to '../tmp';
---replace_result "errno: 7" "errno: X" "errno: 17" "errno: X"
+--replace_result ": 7" ": X" ": 17" ": X" $MYSQL_TEST_DIR MYSQL_TEST_DIR
backup table t4 to '../tmp';
drop table t4;
restore table t4 from '../tmp';
@@ -23,6 +23,7 @@ create table t1(n int);
insert into t1 values (23),(45),(67);
backup table t1 to '../tmp';
drop table t1;
+--replace_result ": 1" ": X" ": 2" ": X" ": 22" ": X" ": 23" ": X" $MYSQL_TEST_DIR MYSQL_TEST_DIR
restore table t1 from '../bogus';
restore table t1 from '../tmp';
select n from t1;
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 6ceb0ea0789..3167682f816 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -42,8 +42,13 @@ update ignore t1 set id=id+1; # This will change all rows
select * from t1;
update ignore t1 set id=1023 where id=1010;
select * from t1 where parent_id=102 order by parent_id,id;
+# Here and below the differences in result are caused by difference in
+# floating point calculations performed in BDB handler.
+--replace_result 5 X 6 X
explain select level from t1 where level=1;
+--replace_result 5 X 6 X
explain select level,id from t1 where level=1;
+--replace_result 5 X 6 X
explain select level,id,parent_id from t1 where level=1;
select level,id from t1 where level=1;
select level,id,parent_id from t1 where level=1;
@@ -349,6 +354,7 @@ update ignore t1 set id=id+1; # This will change all rows
select * from t1;
update ignore t1 set id=1023 where id=1010;
select * from t1 where parent_id=102;
+--replace_result 5 X 6 X
explain select level from t1 where level=1;
select level,id from t1 where level=1;
select level,id,parent_id from t1 where level=1;
@@ -395,6 +401,7 @@ set @a:=now();
CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) engine=bdb;
insert into t1 (a) values(1),(2),(3);
select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a;
+select a from t1 natural join t1 as t2 where b >= @a order by a;
update t1 set a=5 where a=1;
select a from t1;
drop table t1;
@@ -824,7 +831,7 @@ select a from t1;
drop table t1;
#
-# bug#2686 - index_merge select on BerkeleyDB table with varchar PK causes mysqld to crash
+# bug#2686 - index_merge select on BerkeleyDB table with varchar PK crashes
#
create table t1(
@@ -842,7 +849,8 @@ select substring(pk1, 1, 4), substring(pk1, 4001),
drop table t1;
#
-# bug#2688 - Wrong index_merge query results for BDB table with variable length primary key
+# bug#2688 - Wrong index_merge query results for BDB table with
+# variable length primary key
#
create table t1 (
@@ -931,3 +939,37 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
DROP TABLE t1;
# End of 4.1 tests
+
+#
+# alter temp table
+#
+create temporary table t1 (a int, primary key(a)) engine=bdb;
+select * from t1;
+alter table t1 add b int;
+select * from t1;
+drop table t1;
+
+
+#
+# Test varchar
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=bdb;
+source include/varchar.inc;
+
+#
+# Some errors/warnings on create
+#
+
+create table t1 (v varchar(65530), key(v));
+drop table if exists t1;
+create table t1 (v varchar(65536));
+show create table t1;
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+show create table t1;
+drop table t1;
+
+# End varchar test
+eval set storage_engine=$default;
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index 8a238d33e08..d9c1abd9ba9 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -35,21 +35,27 @@ drop table t1;
create table t1 ( a int not null default 1, big bigint );
insert into t1 (big) values (-1),(12345678901234567),(9223372036854775807),(18446744073709551615);
+select * from t1;
select min(big),max(big),max(big)-1 from t1;
select min(big),max(big),max(big)-1 from t1 group by a;
alter table t1 modify big bigint unsigned not null;
select min(big),max(big),max(big)-1 from t1;
select min(big),max(big),max(big)-1 from t1 group by a;
+insert into t1 (big) values (18446744073709551615);
+select * from t1;
+select min(big),max(big),max(big)-1 from t1;
+select min(big),max(big),max(big)-1 from t1 group by a;
alter table t1 add key (big);
select min(big),max(big),max(big)-1 from t1;
select min(big),max(big),max(big)-1 from t1 group by a;
alter table t1 modify big bigint not null;
+select * from t1;
select min(big),max(big),max(big)-1 from t1;
select min(big),max(big),max(big)-1 from t1 group by a;
drop table t1;
#
-# Test problem with big values fir auto_increment
+# Test problem with big values for auto_increment
#
create table t1 (id bigint auto_increment primary key, a int) auto_increment=9999999999;
@@ -108,3 +114,159 @@ t2.value64=t1.value64;
drop table t1, t2;
# End of 4.1 tests
+
+#
+# Test of CREATE ... SELECT and unsigned integers
+#
+
+create table t1 select 1 as 'a';
+show create table t1;
+drop table t1;
+create table t1 select 9223372036854775809 as 'a';
+show create table t1;
+select * from t1;
+drop table t1;
+DROP DATABASE IF EXISTS `scott`;
+
+
+#
+# Check various conversions from/to unsigned bigint.
+#
+
+create table t1 (a char(100), b varchar(100), c text, d blob);
+insert into t1 values(
+ 18446744073709551615,18446744073709551615,
+ 18446744073709551615, 18446744073709551615
+);
+
+insert into t1 values (-1 | 0,-1 | 0,-1 | 0 ,-1 | 0);
+select * from t1;
+drop table t1;
+
+create table t1 ( quantity decimal(2) unsigned);
+insert into t1 values (500), (-500), (~0), (-1);
+select * from t1;
+drop table t1;
+
+#
+# Test of storing decimal values in BIGINT range
+# (Bug #12750: Incorrect storage of 9999999999999999999 in DECIMAL(19, 0))
+#
+
+CREATE TABLE t1 (
+ `col1` INT(1) NULL,
+ `col2` INT(2) NULL,
+ `col3` INT(3) NULL,
+ `col4` INT(4) NULL,
+ `col5` INT(5) NULL,
+ `col6` INT(6) NULL,
+ `col7` INT(7) NULL,
+ `col8` INT(8) NULL,
+ `col9` INT(9) NULL,
+ `col10` BIGINT(10) NULL,
+ `col11` BIGINT(11) NULL,
+ `col12` BIGINT(12) NULL,
+ `col13` BIGINT(13) NULL,
+ `col14` BIGINT(14) NULL,
+ `col15` BIGINT(15) NULL,
+ `col16` BIGINT(16) NULL,
+ `col17` BIGINT(17) NULL,
+ `col18` BIGINT(18) NULL,
+ `col19` DECIMAL(19, 0) NULL,
+ `col20` DECIMAL(20, 0) NULL,
+ `col21` DECIMAL(21, 0) NULL,
+ `col22` DECIMAL(22, 0) NULL,
+ `col23` DECIMAL(23, 0) NULL,
+ `col24` DECIMAL(24, 0) NULL,
+ `col25` DECIMAL(25, 0) NULL,
+ `col26` DECIMAL(26, 0) NULL,
+ `col27` DECIMAL(27, 0) NULL,
+ `col28` DECIMAL(28, 0) NULL,
+ `col29` DECIMAL(29, 0) NULL,
+ `col30` DECIMAL(30, 0) NULL,
+ `col31` DECIMAL(31, 0) NULL,
+ `col32` DECIMAL(32, 0) NULL,
+ `col33` DECIMAL(33, 0) NULL,
+ `col34` DECIMAL(34, 0) NULL,
+ `col35` DECIMAL(35, 0) NULL,
+ `col36` DECIMAL(36, 0) NULL,
+ `col37` DECIMAL(37, 0) NULL,
+ `col38` DECIMAL(38, 0) NULL,
+ `fix1` DECIMAL(38, 1) NULL,
+ `fix2` DECIMAL(38, 2) NULL,
+ `fix3` DECIMAL(38, 3) NULL,
+ `fix4` DECIMAL(38, 4) NULL,
+ `fix5` DECIMAL(38, 5) NULL,
+ `fix6` DECIMAL(38, 6) NULL,
+ `fix7` DECIMAL(38, 7) NULL,
+ `fix8` DECIMAL(38, 8) NULL,
+ `fix9` DECIMAL(38, 9) NULL,
+ `fix10` DECIMAL(38, 10) NULL,
+ `fix11` DECIMAL(38, 11) NULL,
+ `fix12` DECIMAL(38, 12) NULL,
+ `fix13` DECIMAL(38, 13) NULL,
+ `fix14` DECIMAL(38, 14) NULL,
+ `fix15` DECIMAL(38, 15) NULL,
+ `fix16` DECIMAL(38, 16) NULL,
+ `fix17` DECIMAL(38, 17) NULL,
+ `fix18` DECIMAL(38, 18) NULL,
+ `fix19` DECIMAL(38, 19) NULL,
+ `fix20` DECIMAL(38, 20) NULL,
+ `fix21` DECIMAL(38, 21) NULL,
+ `fix22` DECIMAL(38, 22) NULL,
+ `fix23` DECIMAL(38, 23) NULL,
+ `fix24` DECIMAL(38, 24) NULL,
+ `fix25` DECIMAL(38, 25) NULL,
+ `fix26` DECIMAL(38, 26) NULL,
+ `fix27` DECIMAL(38, 27) NULL,
+ `fix28` DECIMAL(38, 28) NULL,
+ `fix29` DECIMAL(38, 29) NULL,
+ `fix30` DECIMAL(38, 30) NULL
+);
+
+INSERT INTO t1(`col1`, `col2`, `col3`, `col4`, `col5`, `col6`, `col7`, `col8`, `col9`, `col10`, `col11`, `col12`, `col13`, `col14`, `col15`, `col16`, `col17`, `col18`, `col19`, `col20`, `col21`, `col22`, `col23`, `col24`, `col25`, `col26`, `col27`, `col28`, `col29`, `col30`, `col31`, `col32`, `col33`, `col34`, `col35`, `col36`, `col37`, `col38`, `fix1`, `fix2`, `fix3`, `fix4`, `fix5`, `fix6`, `fix7`, `fix8`, `fix9`, `fix10`, `fix11`, `fix12`, `fix13`, `fix14`, `fix15`, `fix16`, `fix17`, `fix18`, `fix19`, `fix20`, `fix21`, `fix22`, `fix23`, `fix24`, `fix25`, `fix26`, `fix27`, `fix28`, `fix29`, `fix30`)
+VALUES (9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999,
+9999999999, 99999999999, 999999999999, 9999999999999, 99999999999999,
+999999999999999, 9999999999999999, 99999999999999999, 999999999999999999,
+9999999999999999999, 99999999999999999999, 999999999999999999999,
+9999999999999999999999, 99999999999999999999999, 999999999999999999999999,
+9999999999999999999999999, 99999999999999999999999999,
+999999999999999999999999999, 9999999999999999999999999999,
+99999999999999999999999999999, 999999999999999999999999999999,
+9999999999999999999999999999999, 99999999999999999999999999999999,
+999999999999999999999999999999999, 9999999999999999999999999999999999,
+99999999999999999999999999999999999, 999999999999999999999999999999999999,
+9999999999999999999999999999999999999, 99999999999999999999999999999999999999,
+9999999999999999999999999999999999999.9,
+999999999999999999999999999999999999.99,
+99999999999999999999999999999999999.999,
+9999999999999999999999999999999999.9999,
+999999999999999999999999999999999.99999,
+99999999999999999999999999999999.999999,
+9999999999999999999999999999999.9999999,
+999999999999999999999999999999.99999999,
+99999999999999999999999999999.999999999,
+9999999999999999999999999999.9999999999,
+999999999999999999999999999.99999999999,
+99999999999999999999999999.999999999999,
+9999999999999999999999999.9999999999999,
+999999999999999999999999.99999999999999,
+99999999999999999999999.999999999999999,
+9999999999999999999999.9999999999999999,
+999999999999999999999.99999999999999999,
+99999999999999999999.999999999999999999,
+9999999999999999999.9999999999999999999,
+999999999999999999.99999999999999999999,
+99999999999999999.999999999999999999999,
+9999999999999999.9999999999999999999999,
+999999999999999.99999999999999999999999,
+99999999999999.999999999999999999999999,
+9999999999999.9999999999999999999999999,
+999999999999.99999999999999999999999999,
+99999999999.999999999999999999999999999,
+9999999999.9999999999999999999999999999,
+999999999.99999999999999999999999999999,
+99999999.999999999999999999999999999999);
+
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/binlog-master.opt b/mysql-test/t/binlog-master.opt
new file mode 100644
index 00000000000..ad2c6a647b5
--- /dev/null
+++ b/mysql-test/t/binlog-master.opt
@@ -0,0 +1 @@
+-O max_binlog_size=4096
diff --git a/mysql-test/t/binlog.test b/mysql-test/t/binlog.test
new file mode 100644
index 00000000000..2310e800df7
--- /dev/null
+++ b/mysql-test/t/binlog.test
@@ -0,0 +1,48 @@
+#
+# misc binlogging tests that do not require a slave running
+#
+-- source include/have_bdb.inc
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+reset master;
+
+create table t1 (a int) engine=bdb;
+create table t2 (a int) engine=innodb;
+begin;
+insert t1 values (5);
+commit;
+begin;
+insert t2 values (5);
+commit;
+# first COMMIT must be Query_log_event, second - Xid_log_event
+--replace_result "xid=18" "xid=11"
+--replace_column 2 # 5 #
+show binlog events from 98;
+drop table t1,t2;
+
+#
+# binlog rotation after one big transaction
+#
+reset master;
+let $1=100;
+
+create table t1 (n int) engine=innodb;
+begin;
+--disable_query_log
+while ($1)
+{
+ eval insert into t1 values($1 + 4);
+ dec $1;
+}
+--enable_query_log
+commit;
+drop table t1;
+--replace_result "xid=29" "xid=18"
+--replace_column 2 # 5 #
+show binlog events in 'master-bin.000001' from 98;
+--replace_column 2 # 5 #
+show binlog events in 'master-bin.000002' from 98;
+
diff --git a/mysql-test/t/bool.test b/mysql-test/t/bool.test
index 67b9eeaeb94..34c51c648d3 100644
--- a/mysql-test/t/bool.test
+++ b/mysql-test/t/bool.test
@@ -20,6 +20,16 @@ SELECT * FROM t1 where (1 AND a)=0;
SELECT * FROM t1 where (1 AND a)=1;
SELECT * FROM t1 where (1 AND a) IS NULL;
+# WL#638 - Behaviour of NOT does not follow SQL specification
+set sql_mode='high_not_precedence';
+select * from t1 where not a between 2 and 3;
+set sql_mode=default;
+select * from t1 where not a between 2 and 3;
+
+# SQL boolean tests
+select a, a is false, a is true, a is unknown from t1;
+select a, a is not false, a is not true, a is not unknown from t1;
+
# Verify that NULL optimisation works in AND clause:
SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index fbbbce15576..555e34d5cf2 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -58,7 +58,10 @@ CREATE TABLE t1 SELECT
CASE WHEN 1 THEN 1.0 ELSE 'a' END AS c6,
CASE WHEN 1 THEN 1 ELSE 1.0 END AS c7,
CASE WHEN 1 THEN 1.0 ELSE 1 END AS c8,
- CASE WHEN 1 THEN 1.0 END AS c9
+ CASE WHEN 1 THEN 1.0 END AS c9,
+ CASE WHEN 1 THEN 0.1e1 else 0.1 END AS c10,
+ CASE WHEN 1 THEN 0.1e1 else 1 END AS c11,
+ CASE WHEN 1 THEN 0.1e1 else '1' END AS c12
;
SHOW CREATE TABLE t1;
DROP TABLE t1;
@@ -120,3 +123,23 @@ UNION
SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
# End of 4.1 tests
+
+
+#
+# Tests for bug #9939: conversion of the arguments for COALESCE and IFNULL
+#
+
+CREATE TABLE t1 (EMPNUM INT);
+INSERT INTO t1 VALUES (0), (2);
+CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
+INSERT INTO t2 VALUES (0.0), (9.0);
+
+SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
+ t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
+ FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
+
+SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
+ t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
+ FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
+
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index 394971f9648..2049c17580e 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -4,6 +4,7 @@
select CAST(1-2 AS UNSIGNED);
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
+select CAST('10 ' as unsigned integer);
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
select ~5, cast(~5 as signed);
@@ -15,11 +16,22 @@ select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A";
select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME);
select cast("1:2:3" as TIME);
select CONVERT("2004-01-22 21:45:33",DATE);
+select 10+'10';
+select 10.0+'10';
+select 10E+0+'10';
+
+# The following cast creates warnings
+
select CONVERT(DATE "2004-01-22 21:45:33" USING latin1);
select CONVERT(DATE "2004-01-22 21:45:33",CHAR);
select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4));
select CONVERT(DATE "2004-01-22 21:45:33",BINARY(4));
select CAST(DATE "2004-01-22 21:45:33" AS BINARY(4));
+select cast('-10a' as signed integer);
+select cast('a10' as unsigned integer);
+select 10+'a';
+select 10.0+cast('a' as decimal);
+select 10E+0+'a';
# out-of-range cases
select cast('18446744073709551616' as unsigned);
@@ -49,6 +61,7 @@ select
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
+select cast(1000 as CHAR(3));
create table t1 select
cast(_latin1'ab' AS char) as c1,
@@ -144,3 +157,34 @@ select cast(repeat('1',20) as unsigned);
select cast(repeat('1',20) as signed);
# End of 4.1 tests
+
+
+#decimal-related additions
+select cast('1.2' as decimal(3,2));
+select 1e18 * cast('1.2' as decimal(3,2));
+select cast(cast('1.2' as decimal(3,2)) as signed);
+set @v1=1e18;
+select cast(@v1 as decimal(22, 2));
+select cast(-1e18 as decimal(22,2));
+
+create table t1(s1 time);
+insert into t1 values ('11:11:11');
+select cast(s1 as decimal(7,2)) from t1;
+drop table t1;
+
+#
+# Test for bug #11283: field conversion from varchar, and text types to decimal
+#
+
+CREATE TABLE t1 (v varchar(10), tt tinytext, t text,
+ mt mediumtext, lt longtext);
+INSERT INTO t1 VALUES ('1.01', '2.02', '3.03', '4.04', '5.05');
+
+SELECT CAST(v AS DECIMAL), CAST(tt AS DECIMAL), CAST(t AS DECIMAL),
+ CAST(mt AS DECIMAL), CAST(lt AS DECIMAL) from t1;
+
+DROP TABLE t1;
+# Bug @10237 (CAST(NULL DECIMAL) crashes server)
+#
+select cast(NULL as decimal(6)) as t1;
+
diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test
index 4ce2cb04a3b..8d9d70bd29a 100644
--- a/mysql-test/t/check.test
+++ b/mysql-test/t/check.test
@@ -23,3 +23,16 @@ reap;
drop table t1;
# End of 4.1 tests
+
+#
+# Bug #9897 Views: 'Check Table' crashes MySQL, with a view and a table
+# in the statement
+#
+
+connection default;
+Create table t1(f1 int);
+Create table t2(f1 int);
+Create view v1 as Select * from t1;
+Check Table v1,t2;
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/t/client_xml.test b/mysql-test/t/client_xml.test
new file mode 100644
index 00000000000..58e9178ef3a
--- /dev/null
+++ b/mysql-test/t/client_xml.test
@@ -0,0 +1,21 @@
+# Can't run with embedded server
+-- source include/not_embedded.inc
+
+# Test of the xml output of the 'mysql' and 'mysqldump' clients -- makes
+# sure that basic encoding issues are handled properly
+create table t1 (
+ `a&b` int,
+ `a<b` int,
+ `a>b` text
+);
+insert into t1 values (1, 2, 'a&b a<b a>b');
+--exec $MYSQL --xml test -e 'select * from t1'
+--exec $MYSQL_DUMP --xml --skip-create test
+
+--exec $MYSQL --xml test -e 'select count(*) from t1'
+--exec $MYSQL --xml test -e 'select 1 < 2 from dual'
+--exec $MYSQL --xml test -e 'select 1 > 2 from dual'
+--exec $MYSQL --xml test -e 'select 1 & 3 from dual'
+--exec $MYSQL --xml test -e 'select null from dual'
+
+drop table t1;
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index ff15d74e5ac..60ac7b88bbe 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -56,7 +56,7 @@ flush privileges;
#show tables;
connect (con1,localhost,test,gambling2,mysql);
set password="";
---error 1105
+--error 1372
set password='gambling3';
set password=old_password('gambling3');
show tables;
diff --git a/mysql-test/t/count_distinct.test b/mysql-test/t/count_distinct.test
index 8e3ca7025b4..e63bdabdb95 100644
--- a/mysql-test/t/count_distinct.test
+++ b/mysql-test/t/count_distinct.test
@@ -56,3 +56,24 @@ select count(distinct f) from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Bug #6515
+#
+
+create table t1 (a char(3), b char(20), primary key (a, b));
+insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
+select count(distinct a) from t1 group by b;
+drop table t1;
+
+#
+# Bug #9593 "The combination of COUNT, DISTINCT and CONCAT
+# seems to lock the server"
+# Bug appears only on Windows system
+#
+
+create table t1 (f1 int, f2 int);
+insert into t1 values (0,1),(1,2);
+select count(distinct if(f1,3,f2)) from t1;
+drop table t1;
+
diff --git a/mysql-test/t/count_distinct2.test b/mysql-test/t/count_distinct2.test
index dd43fe6f7ba..8dcb2a70065 100644
--- a/mysql-test/t/count_distinct2.test
+++ b/mysql-test/t/count_distinct2.test
@@ -64,7 +64,7 @@ select count(distinct n) from t1;
show status like 'Created_tmp_disk_tables';
drop table t1;
-#test conversion from heap to MyISAM
+# Test use of MyISAM tmp tables
create table t1 (s text);
let $1=5000;
disable_query_log;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 73184853d1a..b72dc49e89a 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -49,14 +49,25 @@ create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int);
#
-# Some wrong defaults, so these creates should fail too
+# Some wrong defaults, so these creates should fail too (Bug #5902)
#
--error 1067
-create table test (a datetime default now());
+create table t1 (a datetime default now());
--error 1294
-create table test (a datetime on update now());
+create table t1 (a datetime on update now());
--error 1067
-create table test (a int default 100 auto_increment);
+create table t1 (a int default 100 auto_increment);
+--error 1067
+create table t1 (a tinyint default 1000);
+--error 1067
+create table t1 (a varchar(5) default 'abcdef');
+
+create table t1 (a varchar(5) default 'abcde');
+insert into t1 values();
+select * from t1;
+--error 1067
+alter table t1 alter column a set default 'abcdef';
+drop table t1;
#
# test of dummy table names
@@ -273,8 +284,8 @@ create table t3 like t1;
show create table t3;
select * from t3;
# Disable PS becasue of @@warning_count
---disable_ps_protocol
create table if not exists t3 like t1;
+--disable_ps_protocol
select @@warning_count;
--enable_ps_protocol
create temporary table t3 like t2;
@@ -496,8 +507,7 @@ drop table t1,t2;
# Bug #12537: UNION produces longtext instead of varchar
#
CREATE TABLE t1 (f1 VARCHAR(255) CHARACTER SET utf8);
-CREATE TABLE t2 AS SELECT LEFT(f1,86) AS f2 FROM t1 UNION SELECT LEFT(f1,86)
-AS f2 FROM t1;
+CREATE TABLE t2 AS SELECT LEFT(f1,171) AS f2 FROM t1 UNION SELECT LEFT(f1,171) AS f2 FROM t1;
DESC t2;
DROP TABLE t1,t2;
@@ -514,6 +524,15 @@ drop table if exists test.t1;
--enable_warnings
#
+# Bug #6859: Bogus error message on attempt to CREATE TABLE t LIKE view
+#
+create database mysqltest;
+use mysqltest;
+create view v1 as select 'foo' from dual;
+--error 1347
+create table t1 like v1;
+drop view v1;
+drop database mysqltest;
# Bug #6008 MySQL does not create warnings when
# creating database and using IF NOT EXISTS
#
diff --git a/mysql-test/t/ctype_cp932.test b/mysql-test/t/ctype_cp932.test
index 8e6c53af095..3d630311b3a 100644
--- a/mysql-test/t/ctype_cp932.test
+++ b/mysql-test/t/ctype_cp932.test
@@ -379,27 +379,24 @@ INSERT INTO t1 VALUES
(0xF9F8),(0xF9F9),(0xF9FA),(0xF9FB),(0xF9FC);
#Test that all the characters are stored correctly
-SELECT HEX(c1) FROM t1 ORDER BY BINARY c1;
+SELECT HEX(c1) FROM t1;
#Test conversion to ucs2
-CREATE TABLE t2 SELECT CONVERT(c1 USING ucs2) AS c1 FROM t1 ORDER BY BINARY c1;
-SELECT HEX(c1) FROM t2 ORDER BY BINARY c1;
+CREATE TABLE t2 SELECT CONVERT(c1 USING ucs2) AS c1 FROM t1;
+SELECT HEX(c1) FROM t2;
#Test round trip conversion
-CREATE TABLE t3 SELECT CONVERT(c1 USING cp932) AS c1 FROM t2 ORDER BY BINARY c1;
-SELECT HEX(c1) FROM t3 ORDER BY BINARY c1;
+CREATE TABLE t3 SELECT CONVERT(c1 USING cp932) AS c1 FROM t2;
+SELECT HEX(c1) FROM t3;
-#eucjpms is only available from version 5.0
-#skip this test in version 4.1
-#
#Test conversion to eucjpms
-#CREATE TABLE t4 SELECT CONVERT(c1 USING eucjpms) AS c1 FROM t1 ORDER BY BINARY c1;
-#SELECT HEX(c1) FROM t4 ORDER BY BINARY c1;
+CREATE TABLE t4 SELECT CONVERT(c1 USING eucjpms) AS c1 FROM t1;
+SELECT HEX(c1) FROM t4;
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;
-#DROP TABLE t4;
+DROP TABLE t4;
# Test prepared statement with 0x8300 sequence in parameter while
# running with cp932 client character set.
@@ -418,17 +415,12 @@ SET @var1= x'8300';
# code (and I have used it to test the fix) until there is some way to
# exercise this code from mysql-test-run.
EXECUTE stmt1 USING @var1;
---replace_column 2 # 5 #
-SHOW BINLOG EVENTS FROM 79;
+SHOW BINLOG EVENTS FROM 98;
SELECT HEX(f1) FROM t1;
DROP table t1;
# end test for bug#11338
SET collation_connection='cp932_japanese_ci';
-- source include/ctype_filesort.inc
--- source include/ctype_innodb_like.inc
SET collation_connection='cp932_bin';
-- source include/ctype_filesort.inc
--- source include/ctype_innodb_like.inc
-
-# End of 4.1 tests
diff --git a/mysql-test/t/ctype_eucjpms.test b/mysql-test/t/ctype_eucjpms.test
new file mode 100644
index 00000000000..3609407fe96
--- /dev/null
+++ b/mysql-test/t/ctype_eucjpms.test
@@ -0,0 +1,365 @@
+-- source include/have_eucjpms.inc
+
+
+--disable_warnings
+drop table if exists t1;
+drop table if exists t2;
+drop table if exists t3;
+drop table if exists t4;
+--enable_warnings
+
+set names eucjpms;
+set character_set_database = eucjpms;
+
+CREATE TABLE t1(c1 CHAR(1)) DEFAULT CHARACTER SET = eucjpms;
+
+#Characters which are converted to Unicode ambiguously
+INSERT INTO t1 VALUES
+(0x5C),(0x7E),(0xA1B1),(0xA1BD),(0xA1C0),(0xA1C1),(0xA1C2),(0xA1DD),(0xA1F1),(0xA1F2),(0xA1EF),(0xA2CC),(0x8FA2B7),(0x8FA2C3);
+
+#NEC ROW 13 characters (0x8740 - 0x879C of cp932)
+INSERT INTO t1 VALUES
+(0xADA1),(0xADA2),(0xADA3),(0xADA4),(0xADA5),(0xADA6),(0xADA7),(0xADA8),
+(0xADA9),(0xADAA),(0xADAB),(0xADAC),(0xADAD),(0xADAE),(0xADAF),(0xADB0),
+(0xADB1),(0xADB2),(0xADB3),(0xADB4),(0xADB5),(0xADB6),(0xADB7),(0xADB8),
+(0xADB9),(0xADBA),(0xADBB),(0xADBC),(0xADBD),(0xADBE),(0xADC0),(0xADC1),
+(0xADC2),(0xADC3),(0xADC4),(0xADC5),(0xADC6),(0xADC7),(0xADC8),(0xADC9),
+(0xADCA),(0xADCB),(0xADCC),(0xADCD),(0xADCE),(0xADCF),(0xADD0),(0xADD1),
+(0xADD2),(0xADD3),(0xADD4),(0xADD5),(0xADD6),(0xADDF),(0xADE0),(0xADE1),
+(0xADE2),(0xADE3),(0xADE4),(0xADE5),(0xADE6),(0xADE7),(0xADE8),(0xADE9),
+(0xADEA),(0xADEB),(0xADEC),(0xADED),(0xADEE),(0xADEF),(0xADF0),(0xADF1),
+(0xADF2),(0xADF3),(0xADF4),(0xADF5),(0xADF6),(0xADF7),(0xADF8),(0xADF9),
+(0xADFA),(0xADFB),(0xADFC);
+
+#IBM Selected Kanji and Non-Kanji (0xFA40 - 0xFC4B of cp932)
+INSERT INTO t1 VALUES
+(0x8FF3F3),(0x8FF3F4),(0x8FF3F5),(0x8FF3F6),(0x8FF3F7),(0x8FF3F8),(0x8FF3F9),(0x8FF3FA),
+(0x8FF3FB),(0x8FF3FC),(0x8FF3FD),(0x8FF3FE),(0x8FF4A1),(0x8FF4A2),(0x8FF4A3),(0x8FF4A4),
+(0x8FF4A5),(0x8FF4A6),(0x8FF4A7),(0x8FF4A8),(0xA2CC),(0x8FA2C3),(0x8FF4A9),(0x8FF4AA),
+(0x8FF4AB),(0x8FF4AC),(0x8FF4AD),(0xA2E8),(0x8FD4E3),(0x8FDCDF),(0x8FE4E9),(0x8FE3F8),
+(0x8FD9A1),(0x8FB1BB),(0x8FF4AE),(0x8FC2AD),(0x8FC3FC),(0x8FE4D0),(0x8FC2BF),(0x8FBCF4),
+(0x8FB0A9),(0x8FB0C8),(0x8FF4AF),(0x8FB0D2),(0x8FB0D4),(0x8FB0E3),(0x8FB0EE),(0x8FB1A7),
+(0x8FB1A3),(0x8FB1AC),(0x8FB1A9),(0x8FB1BE),(0x8FB1DF),(0x8FB1D8),(0x8FB1C8),(0x8FB1D7),
+(0x8FB1E3),(0x8FB1F4),(0x8FB1E1),(0x8FB2A3),(0x8FF4B0),(0x8FB2BB),(0x8FB2E6),(0x8FB2ED),
+(0x8FB2F5),(0x8FB2FC),(0x8FF4B1),(0x8FB3B5),(0x8FB3D8),(0x8FB3DB),(0x8FB3E5),(0x8FB3EE),
+(0x8FB3FB),(0x8FF4B2),(0x8FF4B3),(0x8FB4C0),(0x8FB4C7),(0x8FB4D0),(0x8FB4DE),(0x8FF4B4),
+(0x8FB5AA),(0x8FF4B5),(0x8FB5AF),(0x8FB5C4),(0x8FB5E8),(0x8FF4B6),(0x8FB7C2),(0x8FB7E4),
+(0x8FB7E8),(0x8FB7E7),(0x8FF4B7),(0x8FF4B8),(0x8FF4B9),(0x8FB8CE),(0x8FB8E1),(0x8FB8F5),
+(0x8FB8F7),(0x8FB8F8),(0x8FB8FC),(0x8FB9AF),(0x8FB9B7),(0x8FBABE),(0x8FBADB),(0x8FCDAA),
+(0x8FBAE1),(0x8FF4BA),(0x8FBAEB),(0x8FBBB3),(0x8FBBB8),(0x8FF4BB),(0x8FBBCA),(0x8FF4BC),
+(0x8FF4BD),(0x8FBBD0),(0x8FBBDE),(0x8FBBF4),(0x8FBBF5),(0x8FBBF9),(0x8FBCE4),(0x8FBCED),
+(0x8FBCFE),(0x8FF4BE),(0x8FBDC2),(0x8FBDE7),(0x8FF4BF),(0x8FBDF0),(0x8FBEB0),(0x8FBEAC),
+(0x8FF4C0),(0x8FBEB3),(0x8FBEBD),(0x8FBECD),(0x8FBEC9),(0x8FBEE4),(0x8FBFA8),(0x8FBFC9),
+(0x8FC0C4),(0x8FC0E4),(0x8FC0F4),(0x8FC1A6),(0x8FF4C1),(0x8FC1F5),(0x8FC1FC),(0x8FF4C2),
+(0x8FC1F8),(0x8FC2AB),(0x8FC2A1),(0x8FC2A5),(0x8FF4C3),(0x8FC2B8),(0x8FC2BA),(0x8FF4C4),
+(0x8FC2C4),(0x8FC2D2),(0x8FC2D7),(0x8FC2DB),(0x8FC2DE),(0x8FC2ED),(0x8FC2F0),(0x8FF4C5),
+(0x8FC3A1),(0x8FC3B5),(0x8FC3C9),(0x8FC3B9),(0x8FF4C6),(0x8FC3D8),(0x8FC3FE),(0x8FF4C7),
+(0x8FC4CC),(0x8FF4C8),(0x8FC4D9),(0x8FC4EA),(0x8FC4FD),(0x8FF4C9),(0x8FC5A7),(0x8FC5B5),
+(0x8FC5B6),(0x8FF4CA),(0x8FC5D5),(0x8FC6B8),(0x8FC6D7),(0x8FC6E0),(0x8FC6EA),(0x8FC6E3),
+(0x8FC7A1),(0x8FC7AB),(0x8FC7C7),(0x8FC7C3),(0x8FC7CB),(0x8FC7CF),(0x8FC7D9),(0x8FF4CB),
+(0x8FF4CC),(0x8FC7E6),(0x8FC7EE),(0x8FC7FC),(0x8FC7EB),(0x8FC7F0),(0x8FC8B1),(0x8FC8E5),
+(0x8FC8F8),(0x8FC9A6),(0x8FC9AB),(0x8FC9AD),(0x8FF4CD),(0x8FC9CA),(0x8FC9D3),(0x8FC9E9),
+(0x8FC9E3),(0x8FC9FC),(0x8FC9F4),(0x8FC9F5),(0x8FF4CE),(0x8FCAB3),(0x8FCABD),(0x8FCAEF),
+(0x8FCAF1),(0x8FCBAE),(0x8FF4CF),(0x8FCBCA),(0x8FCBE6),(0x8FCBEA),(0x8FCBF0),(0x8FCBF4),
+(0x8FCBEE),(0x8FCCA5),(0x8FCBF9),(0x8FCCAB),(0x8FCCAE),(0x8FCCAD),(0x8FCCB2),(0x8FCCC2),
+(0x8FCCD0),(0x8FCCD9),(0x8FF4D0),(0x8FCDBB),(0x8FF4D1),(0x8FCEBB),(0x8FF4D2),(0x8FCEBA),
+(0x8FCEC3),(0x8FF4D3),(0x8FCEF2),(0x8FB3DD),(0x8FCFD5),(0x8FCFE2),(0x8FCFE9),(0x8FCFED),
+(0x8FF4D4),(0x8FF4D5),(0x8FF4D6),(0x8FF4D7),(0x8FD0E5),(0x8FF4D8),(0x8FD0E9),(0x8FD1E8),
+(0x8FF4D9),(0x8FF4DA),(0x8FD1EC),(0x8FD2BB),(0x8FF4DB),(0x8FD3E1),(0x8FD3E8),(0x8FD4A7),
+(0x8FF4DC),(0x8FF4DD),(0x8FD4D4),(0x8FD4F2),(0x8FD5AE),(0x8FF4DE),(0x8FD7DE),(0x8FF4DF),
+(0x8FD8A2),(0x8FD8B7),(0x8FD8C1),(0x8FD8D1),(0x8FD8F4),(0x8FD9C6),(0x8FD9C8),(0x8FD9D1),
+(0x8FF4E0),(0x8FF4E1),(0x8FF4E2),(0x8FF4E3),(0x8FF4E4),(0x8FDCD3),(0x8FDDC8),(0x8FDDD4),
+(0x8FDDEA),(0x8FDDFA),(0x8FDEA4),(0x8FDEB0),(0x8FF4E5),(0x8FDEB5),(0x8FDECB),(0x8FF4E6),
+(0x8FDFB9),(0x8FF4E7),(0x8FDFC3),(0x8FF4E8),(0x8FF4E9),(0x8FE0D9),(0x8FF4EA),(0x8FF4EB),
+(0x8FE1E2),(0x8FF4EC),(0x8FF4ED),(0x8FF4EE),(0x8FE2C7),(0x8FE3A8),(0x8FE3A6),(0x8FE3A9),
+(0x8FE3AF),(0x8FE3B0),(0x8FE3AA),(0x8FE3AB),(0x8FE3BC),(0x8FE3C1),(0x8FE3BF),(0x8FE3D5),
+(0x8FE3D8),(0x8FE3D6),(0x8FE3DF),(0x8FE3E3),(0x8FE3E1),(0x8FE3D4),(0x8FE3E9),(0x8FE4A6),
+(0x8FE3F1),(0x8FE3F2),(0x8FE4CB),(0x8FE4C1),(0x8FE4C3),(0x8FE4BE),(0x8FF4EF),(0x8FE4C0),
+(0x8FE4C7),(0x8FE4BF),(0x8FE4E0),(0x8FE4DE),(0x8FE4D1),(0x8FF4F0),(0x8FE4DC),(0x8FE4D2),
+(0x8FE4DB),(0x8FE4D4),(0x8FE4FA),(0x8FE4EF),(0x8FE5B3),(0x8FE5BF),(0x8FE5C9),(0x8FE5D0),
+(0x8FE5E2),(0x8FE5EA),(0x8FE5EB),(0x8FF4F1),(0x8FF4F2),(0x8FF4F3),(0x8FE6E8),(0x8FE6EF),
+(0x8FE7AC),(0x8FF4F4),(0x8FE7AE),(0x8FF4F5),(0x8FE7B1),(0x8FF4F6),(0x8FE7B2),(0x8FE8B1),
+(0x8FE8B6),(0x8FF4F7),(0x8FF4F8),(0x8FE8DD),(0x8FF4F9),(0x8FF4FA),(0x8FE9D1),(0x8FF4FB),
+(0x8FE9ED),(0x8FEACD),(0x8FF4FC),(0x8FEADB),(0x8FEAE6),(0x8FEAEA),(0x8FEBA5),(0x8FEBFB),
+(0x8FEBFA),(0x8FF4FD),(0x8FECD6),(0x8FF4FE);
+
+#User defined characters (0xF040-F9FC of cp932)
+INSERT INTO t1 VALUES
+(0xF5A1),(0xF5A2),(0xF5A3),(0xF5A4),(0xF5A5),(0xF5A6),(0xF5A7),(0xF5A8),
+(0xF5A9),(0xF5AA),(0xF5AB),(0xF5AC),(0xF5AD),(0xF5AE),(0xF5AF),(0xF5B0),
+(0xF5B1),(0xF5B2),(0xF5B3),(0xF5B4),(0xF5B5),(0xF5B6),(0xF5B7),(0xF5B8),
+(0xF5B9),(0xF5BA),(0xF5BB),(0xF5BC),(0xF5BD),(0xF5BE),(0xF5BF),(0xF5C0),
+(0xF5C1),(0xF5C2),(0xF5C3),(0xF5C4),(0xF5C5),(0xF5C6),(0xF5C7),(0xF5C8),
+(0xF5C9),(0xF5CA),(0xF5CB),(0xF5CC),(0xF5CD),(0xF5CE),(0xF5CF),(0xF5D0),
+(0xF5D1),(0xF5D2),(0xF5D3),(0xF5D4),(0xF5D5),(0xF5D6),(0xF5D7),(0xF5D8),
+(0xF5D9),(0xF5DA),(0xF5DB),(0xF5DC),(0xF5DD),(0xF5DE),(0xF5DF),(0xF5E0),
+(0xF5E1),(0xF5E2),(0xF5E3),(0xF5E4),(0xF5E5),(0xF5E6),(0xF5E7),(0xF5E8),
+(0xF5E9),(0xF5EA),(0xF5EB),(0xF5EC),(0xF5ED),(0xF5EE),(0xF5EF),(0xF5F0),
+(0xF5F1),(0xF5F2),(0xF5F3),(0xF5F4),(0xF5F5),(0xF5F6),(0xF5F7),(0xF5F8),
+(0xF5F9),(0xF5FA),(0xF5FB),(0xF5FC),(0xF5FD),(0xF5FE),
+(0xF6A1),(0xF6A2),(0xF6A3),(0xF6A4),(0xF6A5),(0xF6A6),(0xF6A7),(0xF6A8),
+(0xF6A9),(0xF6AA),(0xF6AB),(0xF6AC),(0xF6AD),(0xF6AE),(0xF6AF),(0xF6B0),
+(0xF6B1),(0xF6B2),(0xF6B3),(0xF6B4),(0xF6B5),(0xF6B6),(0xF6B7),(0xF6B8),
+(0xF6B9),(0xF6BA),(0xF6BB),(0xF6BC),(0xF6BD),(0xF6BE),(0xF6BF),(0xF6C0),
+(0xF6C1),(0xF6C2),(0xF6C3),(0xF6C4),(0xF6C5),(0xF6C6),(0xF6C7),(0xF6C8),
+(0xF6C9),(0xF6CA),(0xF6CB),(0xF6CC),(0xF6CD),(0xF6CE),(0xF6CF),(0xF6D0),
+(0xF6D1),(0xF6D2),(0xF6D3),(0xF6D4),(0xF6D5),(0xF6D6),(0xF6D7),(0xF6D8),
+(0xF6D9),(0xF6DA),(0xF6DB),(0xF6DC),(0xF6DD),(0xF6DE),(0xF6DF),(0xF6E0),
+(0xF6E1),(0xF6E2),(0xF6E3),(0xF6E4),(0xF6E5),(0xF6E6),(0xF6E7),(0xF6E8),
+(0xF6E9),(0xF6EA),(0xF6EB),(0xF6EC),(0xF6ED),(0xF6EE),(0xF6EF),(0xF6F0),
+(0xF6F1),(0xF6F2),(0xF6F3),(0xF6F4),(0xF6F5),(0xF6F6),(0xF6F7),(0xF6F8),
+(0xF6F9),(0xF6FA),(0xF6FB),(0xF6FC),(0xF6FD),(0xF6FE),
+(0xF7A1),(0xF7A2),(0xF7A3),(0xF7A4),(0xF7A5),(0xF7A6),(0xF7A7),(0xF7A8),
+(0xF7A9),(0xF7AA),(0xF7AB),(0xF7AC),(0xF7AD),(0xF7AE),(0xF7AF),(0xF7B0),
+(0xF7B1),(0xF7B2),(0xF7B3),(0xF7B4),(0xF7B5),(0xF7B6),(0xF7B7),(0xF7B8),
+(0xF7B9),(0xF7BA),(0xF7BB),(0xF7BC),(0xF7BD),(0xF7BE),(0xF7BF),(0xF7C0),
+(0xF7C1),(0xF7C2),(0xF7C3),(0xF7C4),(0xF7C5),(0xF7C6),(0xF7C7),(0xF7C8),
+(0xF7C9),(0xF7CA),(0xF7CB),(0xF7CC),(0xF7CD),(0xF7CE),(0xF7CF),(0xF7D0),
+(0xF7D1),(0xF7D2),(0xF7D3),(0xF7D4),(0xF7D5),(0xF7D6),(0xF7D7),(0xF7D8),
+(0xF7D9),(0xF7DA),(0xF7DB),(0xF7DC),(0xF7DD),(0xF7DE),(0xF7DF),(0xF7E0),
+(0xF7E1),(0xF7E2),(0xF7E3),(0xF7E4),(0xF7E5),(0xF7E6),(0xF7E7),(0xF7E8),
+(0xF7E9),(0xF7EA),(0xF7EB),(0xF7EC),(0xF7ED),(0xF7EE),(0xF7EF),(0xF7F0),
+(0xF7F1),(0xF7F2),(0xF7F3),(0xF7F4),(0xF7F5),(0xF7F6),(0xF7F7),(0xF7F8),
+(0xF7F9),(0xF7FA),(0xF7FB),(0xF7FC),(0xF7FD),(0xF7FE),
+(0xF8A1),(0xF8A2),(0xF8A3),(0xF8A4),(0xF8A5),(0xF8A6),(0xF8A7),(0xF8A8),
+(0xF8A9),(0xF8AA),(0xF8AB),(0xF8AC),(0xF8AD),(0xF8AE),(0xF8AF),(0xF8B0),
+(0xF8B1),(0xF8B2),(0xF8B3),(0xF8B4),(0xF8B5),(0xF8B6),(0xF8B7),(0xF8B8),
+(0xF8B9),(0xF8BA),(0xF8BB),(0xF8BC),(0xF8BD),(0xF8BE),(0xF8BF),(0xF8C0),
+(0xF8C1),(0xF8C2),(0xF8C3),(0xF8C4),(0xF8C5),(0xF8C6),(0xF8C7),(0xF8C8),
+(0xF8C9),(0xF8CA),(0xF8CB),(0xF8CC),(0xF8CD),(0xF8CE),(0xF8CF),(0xF8D0),
+(0xF8D1),(0xF8D2),(0xF8D3),(0xF8D4),(0xF8D5),(0xF8D6),(0xF8D7),(0xF8D8),
+(0xF8D9),(0xF8DA),(0xF8DB),(0xF8DC),(0xF8DD),(0xF8DE),(0xF8DF),(0xF8E0),
+(0xF8E1),(0xF8E2),(0xF8E3),(0xF8E4),(0xF8E5),(0xF8E6),(0xF8E7),(0xF8E8),
+(0xF8E9),(0xF8EA),(0xF8EB),(0xF8EC),(0xF8ED),(0xF8EE),(0xF8EF),(0xF8F0),
+(0xF8F1),(0xF8F2),(0xF8F3),(0xF8F4),(0xF8F5),(0xF8F6),(0xF8F7),(0xF8F8),
+(0xF8F9),(0xF8FA),(0xF8FB),(0xF8FC),(0xF8FD),(0xF8FE),
+(0xF9A1),(0xF9A2),(0xF9A3),(0xF9A4),(0xF9A5),(0xF9A6),(0xF9A7),(0xF9A8),
+(0xF9A9),(0xF9AA),(0xF9AB),(0xF9AC),(0xF9AD),(0xF9AE),(0xF9AF),(0xF9B0),
+(0xF9B1),(0xF9B2),(0xF9B3),(0xF9B4),(0xF9B5),(0xF9B6),(0xF9B7),(0xF9B8),
+(0xF9B9),(0xF9BA),(0xF9BB),(0xF9BC),(0xF9BD),(0xF9BE),(0xF9BF),(0xF9C0),
+(0xF9C1),(0xF9C2),(0xF9C3),(0xF9C4),(0xF9C5),(0xF9C6),(0xF9C7),(0xF9C8),
+(0xF9C9),(0xF9CA),(0xF9CB),(0xF9CC),(0xF9CD),(0xF9CE),(0xF9CF),(0xF9D0),
+(0xF9D1),(0xF9D2),(0xF9D3),(0xF9D4),(0xF9D5),(0xF9D6),(0xF9D7),(0xF9D8),
+(0xF9D9),(0xF9DA),(0xF9DB),(0xF9DC),(0xF9DD),(0xF9DE),(0xF9DF),(0xF9E0),
+(0xF9E1),(0xF9E2),(0xF9E3),(0xF9E4),(0xF9E5),(0xF9E6),(0xF9E7),(0xF9E8),
+(0xF9E9),(0xF9EA),(0xF9EB),(0xF9EC),(0xF9ED),(0xF9EE),(0xF9EF),(0xF9F0),
+(0xF9F1),(0xF9F2),(0xF9F3),(0xF9F4),(0xF9F5),(0xF9F6),(0xF9F7),(0xF9F8),
+(0xF9F9),(0xF9FA),(0xF9FB),(0xF9FC),(0xF9FD),(0xF9FE),
+(0xFAA1),(0xFAA2),(0xFAA3),(0xFAA4),(0xFAA5),(0xFAA6),(0xFAA7),(0xFAA8),
+(0xFAA9),(0xFAAA),(0xFAAB),(0xFAAC),(0xFAAD),(0xFAAE),(0xFAAF),(0xFAB0),
+(0xFAB1),(0xFAB2),(0xFAB3),(0xFAB4),(0xFAB5),(0xFAB6),(0xFAB7),(0xFAB8),
+(0xFAB9),(0xFABA),(0xFABB),(0xFABC),(0xFABD),(0xFABE),(0xFABF),(0xFAC0),
+(0xFAC1),(0xFAC2),(0xFAC3),(0xFAC4),(0xFAC5),(0xFAC6),(0xFAC7),(0xFAC8),
+(0xFAC9),(0xFACA),(0xFACB),(0xFACC),(0xFACD),(0xFACE),(0xFACF),(0xFAD0),
+(0xFAD1),(0xFAD2),(0xFAD3),(0xFAD4),(0xFAD5),(0xFAD6),(0xFAD7),(0xFAD8),
+(0xFAD9),(0xFADA),(0xFADB),(0xFADC),(0xFADD),(0xFADE),(0xFADF),(0xFAE0),
+(0xFAE1),(0xFAE2),(0xFAE3),(0xFAE4),(0xFAE5),(0xFAE6),(0xFAE7),(0xFAE8),
+(0xFAE9),(0xFAEA),(0xFAEB),(0xFAEC),(0xFAED),(0xFAEE),(0xFAEF),(0xFAF0),
+(0xFAF1),(0xFAF2),(0xFAF3),(0xFAF4),(0xFAF5),(0xFAF6),(0xFAF7),(0xFAF8),
+(0xFAF9),(0xFAFA),(0xFAFB),(0xFAFC),(0xFAFD),(0xFAFE),
+(0xFBA1),(0xFBA2),(0xFBA3),(0xFBA4),(0xFBA5),(0xFBA6),(0xFBA7),(0xFBA8),
+(0xFBA9),(0xFBAA),(0xFBAB),(0xFBAC),(0xFBAD),(0xFBAE),(0xFBAF),(0xFBB0),
+(0xFBB1),(0xFBB2),(0xFBB3),(0xFBB4),(0xFBB5),(0xFBB6),(0xFBB7),(0xFBB8),
+(0xFBB9),(0xFBBA),(0xFBBB),(0xFBBC),(0xFBBD),(0xFBBE),(0xFBBF),(0xFBC0),
+(0xFBC1),(0xFBC2),(0xFBC3),(0xFBC4),(0xFBC5),(0xFBC6),(0xFBC7),(0xFBC8),
+(0xFBC9),(0xFBCA),(0xFBCB),(0xFBCC),(0xFBCD),(0xFBCE),(0xFBCF),(0xFBD0),
+(0xFBD1),(0xFBD2),(0xFBD3),(0xFBD4),(0xFBD5),(0xFBD6),(0xFBD7),(0xFBD8),
+(0xFBD9),(0xFBDA),(0xFBDB),(0xFBDC),(0xFBDD),(0xFBDE),(0xFBDF),(0xFBE0),
+(0xFBE1),(0xFBE2),(0xFBE3),(0xFBE4),(0xFBE5),(0xFBE6),(0xFBE7),(0xFBE8),
+(0xFBE9),(0xFBEA),(0xFBEB),(0xFBEC),(0xFBED),(0xFBEE),(0xFBEF),(0xFBF0),
+(0xFBF1),(0xFBF2),(0xFBF3),(0xFBF4),(0xFBF5),(0xFBF6),(0xFBF7),(0xFBF8),
+(0xFBF9),(0xFBFA),(0xFBFB),(0xFBFC),(0xFBFD),(0xFBFE),
+(0xFCA1),(0xFCA2),(0xFCA3),(0xFCA4),(0xFCA5),(0xFCA6),(0xFCA7),(0xFCA8),
+(0xFCA9),(0xFCAA),(0xFCAB),(0xFCAC),(0xFCAD),(0xFCAE),(0xFCAF),(0xFCB0),
+(0xFCB1),(0xFCB2),(0xFCB3),(0xFCB4),(0xFCB5),(0xFCB6),(0xFCB7),(0xFCB8),
+(0xFCB9),(0xFCBA),(0xFCBB),(0xFCBC),(0xFCBD),(0xFCBE),(0xFCBF),(0xFCC0),
+(0xFCC1),(0xFCC2),(0xFCC3),(0xFCC4),(0xFCC5),(0xFCC6),(0xFCC7),(0xFCC8),
+(0xFCC9),(0xFCCA),(0xFCCB),(0xFCCC),(0xFCCD),(0xFCCE),(0xFCCF),(0xFCD0),
+(0xFCD1),(0xFCD2),(0xFCD3),(0xFCD4),(0xFCD5),(0xFCD6),(0xFCD7),(0xFCD8),
+(0xFCD9),(0xFCDA),(0xFCDB),(0xFCDC),(0xFCDD),(0xFCDE),(0xFCDF),(0xFCE0),
+(0xFCE1),(0xFCE2),(0xFCE3),(0xFCE4),(0xFCE5),(0xFCE6),(0xFCE7),(0xFCE8),
+(0xFCE9),(0xFCEA),(0xFCEB),(0xFCEC),(0xFCED),(0xFCEE),(0xFCEF),(0xFCF0),
+(0xFCF1),(0xFCF2),(0xFCF3),(0xFCF4),(0xFCF5),(0xFCF6),(0xFCF7),(0xFCF8),
+(0xFCF9),(0xFCFA),(0xFCFB),(0xFCFC),(0xFCFD),(0xFCFE),
+(0xFDA1),(0xFDA2),(0xFDA3),(0xFDA4),(0xFDA5),(0xFDA6),(0xFDA7),(0xFDA8),
+(0xFDA9),(0xFDAA),(0xFDAB),(0xFDAC),(0xFDAD),(0xFDAE),(0xFDAF),(0xFDB0),
+(0xFDB1),(0xFDB2),(0xFDB3),(0xFDB4),(0xFDB5),(0xFDB6),(0xFDB7),(0xFDB8),
+(0xFDB9),(0xFDBA),(0xFDBB),(0xFDBC),(0xFDBD),(0xFDBE),(0xFDBF),(0xFDC0),
+(0xFDC1),(0xFDC2),(0xFDC3),(0xFDC4),(0xFDC5),(0xFDC6),(0xFDC7),(0xFDC8),
+(0xFDC9),(0xFDCA),(0xFDCB),(0xFDCC),(0xFDCD),(0xFDCE),(0xFDCF),(0xFDD0),
+(0xFDD1),(0xFDD2),(0xFDD3),(0xFDD4),(0xFDD5),(0xFDD6),(0xFDD7),(0xFDD8),
+(0xFDD9),(0xFDDA),(0xFDDB),(0xFDDC),(0xFDDD),(0xFDDE),(0xFDDF),(0xFDE0),
+(0xFDE1),(0xFDE2),(0xFDE3),(0xFDE4),(0xFDE5),(0xFDE6),(0xFDE7),(0xFDE8),
+(0xFDE9),(0xFDEA),(0xFDEB),(0xFDEC),(0xFDED),(0xFDEE),(0xFDEF),(0xFDF0),
+(0xFDF1),(0xFDF2),(0xFDF3),(0xFDF4),(0xFDF5),(0xFDF6),(0xFDF7),(0xFDF8),
+(0xFDF9),(0xFDFA),(0xFDFB),(0xFDFC),(0xFDFD),(0xFDFE),
+(0xFEA1),(0xFEA2),(0xFEA3),(0xFEA4),(0xFEA5),(0xFEA6),(0xFEA7),(0xFEA8),
+(0xFEA9),(0xFEAA),(0xFEAB),(0xFEAC),(0xFEAD),(0xFEAE),(0xFEAF),(0xFEB0),
+(0xFEB1),(0xFEB2),(0xFEB3),(0xFEB4),(0xFEB5),(0xFEB6),(0xFEB7),(0xFEB8),
+(0xFEB9),(0xFEBA),(0xFEBB),(0xFEBC),(0xFEBD),(0xFEBE),(0xFEBF),(0xFEC0),
+(0xFEC1),(0xFEC2),(0xFEC3),(0xFEC4),(0xFEC5),(0xFEC6),(0xFEC7),(0xFEC8),
+(0xFEC9),(0xFECA),(0xFECB),(0xFECC),(0xFECD),(0xFECE),(0xFECF),(0xFED0),
+(0xFED1),(0xFED2),(0xFED3),(0xFED4),(0xFED5),(0xFED6),(0xFED7),(0xFED8),
+(0xFED9),(0xFEDA),(0xFEDB),(0xFEDC),(0xFEDD),(0xFEDE),(0xFEDF),(0xFEE0),
+(0xFEE1),(0xFEE2),(0xFEE3),(0xFEE4),(0xFEE5),(0xFEE6),(0xFEE7),(0xFEE8),
+(0xFEE9),(0xFEEA),(0xFEEB),(0xFEEC),(0xFEED),(0xFEEE),(0xFEEF),(0xFEF0),
+(0xFEF1),(0xFEF2),(0xFEF3),(0xFEF4),(0xFEF5),(0xFEF6),(0xFEF7),(0xFEF8),
+(0xFEF9),(0xFEFA),(0xFEFB),(0xFEFC),(0xFEFD),(0xFEFE),
+(0x8FF5A1),(0x8FF5A2),(0x8FF5A3),(0x8FF5A4),(0x8FF5A5),(0x8FF5A6),(0x8FF5A7),(0x8FF5A8),
+(0x8FF5A9),(0x8FF5AA),(0x8FF5AB),(0x8FF5AC),(0x8FF5AD),(0x8FF5AE),(0x8FF5AF),(0x8FF5B0),
+(0x8FF5B1),(0x8FF5B2),(0x8FF5B3),(0x8FF5B4),(0x8FF5B5),(0x8FF5B6),(0x8FF5B7),(0x8FF5B8),
+(0x8FF5B9),(0x8FF5BA),(0x8FF5BB),(0x8FF5BC),(0x8FF5BD),(0x8FF5BE),(0x8FF5BF),(0x8FF5C0),
+(0x8FF5C1),(0x8FF5C2),(0x8FF5C3),(0x8FF5C4),(0x8FF5C5),(0x8FF5C6),(0x8FF5C7),(0x8FF5C8),
+(0x8FF5C9),(0x8FF5CA),(0x8FF5CB),(0x8FF5CC),(0x8FF5CD),(0x8FF5CE),(0x8FF5CF),(0x8FF5D0),
+(0x8FF5D1),(0x8FF5D2),(0x8FF5D3),(0x8FF5D4),(0x8FF5D5),(0x8FF5D6),(0x8FF5D7),(0x8FF5D8),
+(0x8FF5D9),(0x8FF5DA),(0x8FF5DB),(0x8FF5DC),(0x8FF5DD),(0x8FF5DE),(0x8FF5DF),(0x8FF5E0),
+(0x8FF5E1),(0x8FF5E2),(0x8FF5E3),(0x8FF5E4),(0x8FF5E5),(0x8FF5E6),(0x8FF5E7),(0x8FF5E8),
+(0x8FF5E9),(0x8FF5EA),(0x8FF5EB),(0x8FF5EC),(0x8FF5ED),(0x8FF5EE),(0x8FF5EF),(0x8FF5F0),
+(0x8FF5F1),(0x8FF5F2),(0x8FF5F3),(0x8FF5F4),(0x8FF5F5),(0x8FF5F6),(0x8FF5F7),(0x8FF5F8),
+(0x8FF5F9),(0x8FF5FA),(0x8FF5FB),(0x8FF5FC),(0x8FF5FD),(0x8FF5FE),
+(0x8FF6A1),(0x8FF6A2),(0x8FF6A3),(0x8FF6A4),(0x8FF6A5),(0x8FF6A6),(0x8FF6A7),(0x8FF6A8),
+(0x8FF6A9),(0x8FF6AA),(0x8FF6AB),(0x8FF6AC),(0x8FF6AD),(0x8FF6AE),(0x8FF6AF),(0x8FF6B0),
+(0x8FF6B1),(0x8FF6B2),(0x8FF6B3),(0x8FF6B4),(0x8FF6B5),(0x8FF6B6),(0x8FF6B7),(0x8FF6B8),
+(0x8FF6B9),(0x8FF6BA),(0x8FF6BB),(0x8FF6BC),(0x8FF6BD),(0x8FF6BE),(0x8FF6BF),(0x8FF6C0),
+(0x8FF6C1),(0x8FF6C2),(0x8FF6C3),(0x8FF6C4),(0x8FF6C5),(0x8FF6C6),(0x8FF6C7),(0x8FF6C8),
+(0x8FF6C9),(0x8FF6CA),(0x8FF6CB),(0x8FF6CC),(0x8FF6CD),(0x8FF6CE),(0x8FF6CF),(0x8FF6D0),
+(0x8FF6D1),(0x8FF6D2),(0x8FF6D3),(0x8FF6D4),(0x8FF6D5),(0x8FF6D6),(0x8FF6D7),(0x8FF6D8),
+(0x8FF6D9),(0x8FF6DA),(0x8FF6DB),(0x8FF6DC),(0x8FF6DD),(0x8FF6DE),(0x8FF6DF),(0x8FF6E0),
+(0x8FF6E1),(0x8FF6E2),(0x8FF6E3),(0x8FF6E4),(0x8FF6E5),(0x8FF6E6),(0x8FF6E7),(0x8FF6E8),
+(0x8FF6E9),(0x8FF6EA),(0x8FF6EB),(0x8FF6EC),(0x8FF6ED),(0x8FF6EE),(0x8FF6EF),(0x8FF6F0),
+(0x8FF6F1),(0x8FF6F2),(0x8FF6F3),(0x8FF6F4),(0x8FF6F5),(0x8FF6F6),(0x8FF6F7),(0x8FF6F8),
+(0x8FF6F9),(0x8FF6FA),(0x8FF6FB),(0x8FF6FC),(0x8FF6FD),(0x8FF6FE),
+(0x8FF7A1),(0x8FF7A2),(0x8FF7A3),(0x8FF7A4),(0x8FF7A5),(0x8FF7A6),(0x8FF7A7),(0x8FF7A8),
+(0x8FF7A9),(0x8FF7AA),(0x8FF7AB),(0x8FF7AC),(0x8FF7AD),(0x8FF7AE),(0x8FF7AF),(0x8FF7B0),
+(0x8FF7B1),(0x8FF7B2),(0x8FF7B3),(0x8FF7B4),(0x8FF7B5),(0x8FF7B6),(0x8FF7B7),(0x8FF7B8),
+(0x8FF7B9),(0x8FF7BA),(0x8FF7BB),(0x8FF7BC),(0x8FF7BD),(0x8FF7BE),(0x8FF7BF),(0x8FF7C0),
+(0x8FF7C1),(0x8FF7C2),(0x8FF7C3),(0x8FF7C4),(0x8FF7C5),(0x8FF7C6),(0x8FF7C7),(0x8FF7C8),
+(0x8FF7C9),(0x8FF7CA),(0x8FF7CB),(0x8FF7CC),(0x8FF7CD),(0x8FF7CE),(0x8FF7CF),(0x8FF7D0),
+(0x8FF7D1),(0x8FF7D2),(0x8FF7D3),(0x8FF7D4),(0x8FF7D5),(0x8FF7D6),(0x8FF7D7),(0x8FF7D8),
+(0x8FF7D9),(0x8FF7DA),(0x8FF7DB),(0x8FF7DC),(0x8FF7DD),(0x8FF7DE),(0x8FF7DF),(0x8FF7E0),
+(0x8FF7E1),(0x8FF7E2),(0x8FF7E3),(0x8FF7E4),(0x8FF7E5),(0x8FF7E6),(0x8FF7E7),(0x8FF7E8),
+(0x8FF7E9),(0x8FF7EA),(0x8FF7EB),(0x8FF7EC),(0x8FF7ED),(0x8FF7EE),(0x8FF7EF),(0x8FF7F0),
+(0x8FF7F1),(0x8FF7F2),(0x8FF7F3),(0x8FF7F4),(0x8FF7F5),(0x8FF7F6),(0x8FF7F7),(0x8FF7F8),
+(0x8FF7F9),(0x8FF7FA),(0x8FF7FB),(0x8FF7FC),(0x8FF7FD),(0x8FF7FE),
+(0x8FF8A1),(0x8FF8A2),(0x8FF8A3),(0x8FF8A4),(0x8FF8A5),(0x8FF8A6),(0x8FF8A7),(0x8FF8A8),
+(0x8FF8A9),(0x8FF8AA),(0x8FF8AB),(0x8FF8AC),(0x8FF8AD),(0x8FF8AE),(0x8FF8AF),(0x8FF8B0),
+(0x8FF8B1),(0x8FF8B2),(0x8FF8B3),(0x8FF8B4),(0x8FF8B5),(0x8FF8B6),(0x8FF8B7),(0x8FF8B8),
+(0x8FF8B9),(0x8FF8BA),(0x8FF8BB),(0x8FF8BC),(0x8FF8BD),(0x8FF8BE),(0x8FF8BF),(0x8FF8C0),
+(0x8FF8C1),(0x8FF8C2),(0x8FF8C3),(0x8FF8C4),(0x8FF8C5),(0x8FF8C6),(0x8FF8C7),(0x8FF8C8),
+(0x8FF8C9),(0x8FF8CA),(0x8FF8CB),(0x8FF8CC),(0x8FF8CD),(0x8FF8CE),(0x8FF8CF),(0x8FF8D0),
+(0x8FF8D1),(0x8FF8D2),(0x8FF8D3),(0x8FF8D4),(0x8FF8D5),(0x8FF8D6),(0x8FF8D7),(0x8FF8D8),
+(0x8FF8D9),(0x8FF8DA),(0x8FF8DB),(0x8FF8DC),(0x8FF8DD),(0x8FF8DE),(0x8FF8DF),(0x8FF8E0),
+(0x8FF8E1),(0x8FF8E2),(0x8FF8E3),(0x8FF8E4),(0x8FF8E5),(0x8FF8E6),(0x8FF8E7),(0x8FF8E8),
+(0x8FF8E9),(0x8FF8EA),(0x8FF8EB),(0x8FF8EC),(0x8FF8ED),(0x8FF8EE),(0x8FF8EF),(0x8FF8F0),
+(0x8FF8F1),(0x8FF8F2),(0x8FF8F3),(0x8FF8F4),(0x8FF8F5),(0x8FF8F6),(0x8FF8F7),(0x8FF8F8),
+(0x8FF8F9),(0x8FF8FA),(0x8FF8FB),(0x8FF8FC),(0x8FF8FD),(0x8FF8FE),
+(0x8FF9A1),(0x8FF9A2),(0x8FF9A3),(0x8FF9A4),(0x8FF9A5),(0x8FF9A6),(0x8FF9A7),(0x8FF9A8),
+(0x8FF9A9),(0x8FF9AA),(0x8FF9AB),(0x8FF9AC),(0x8FF9AD),(0x8FF9AE),(0x8FF9AF),(0x8FF9B0),
+(0x8FF9B1),(0x8FF9B2),(0x8FF9B3),(0x8FF9B4),(0x8FF9B5),(0x8FF9B6),(0x8FF9B7),(0x8FF9B8),
+(0x8FF9B9),(0x8FF9BA),(0x8FF9BB),(0x8FF9BC),(0x8FF9BD),(0x8FF9BE),(0x8FF9BF),(0x8FF9C0),
+(0x8FF9C1),(0x8FF9C2),(0x8FF9C3),(0x8FF9C4),(0x8FF9C5),(0x8FF9C6),(0x8FF9C7),(0x8FF9C8),
+(0x8FF9C9),(0x8FF9CA),(0x8FF9CB),(0x8FF9CC),(0x8FF9CD),(0x8FF9CE),(0x8FF9CF),(0x8FF9D0),
+(0x8FF9D1),(0x8FF9D2),(0x8FF9D3),(0x8FF9D4),(0x8FF9D5),(0x8FF9D6),(0x8FF9D7),(0x8FF9D8),
+(0x8FF9D9),(0x8FF9DA),(0x8FF9DB),(0x8FF9DC),(0x8FF9DD),(0x8FF9DE),(0x8FF9DF),(0x8FF9E0),
+(0x8FF9E1),(0x8FF9E2),(0x8FF9E3),(0x8FF9E4),(0x8FF9E5),(0x8FF9E6),(0x8FF9E7),(0x8FF9E8),
+(0x8FF9E9),(0x8FF9EA),(0x8FF9EB),(0x8FF9EC),(0x8FF9ED),(0x8FF9EE),(0x8FF9EF),(0x8FF9F0),
+(0x8FF9F1),(0x8FF9F2),(0x8FF9F3),(0x8FF9F4),(0x8FF9F5),(0x8FF9F6),(0x8FF9F7),(0x8FF9F8),
+(0x8FF9F9),(0x8FF9FA),(0x8FF9FB),(0x8FF9FC),(0x8FF9FD),(0x8FF9FE),
+(0x8FFAA1),(0x8FFAA2),(0x8FFAA3),(0x8FFAA4),(0x8FFAA5),(0x8FFAA6),(0x8FFAA7),(0x8FFAA8),
+(0x8FFAA9),(0x8FFAAA),(0x8FFAAB),(0x8FFAAC),(0x8FFAAD),(0x8FFAAE),(0x8FFAAF),(0x8FFAB0),
+(0x8FFAB1),(0x8FFAB2),(0x8FFAB3),(0x8FFAB4),(0x8FFAB5),(0x8FFAB6),(0x8FFAB7),(0x8FFAB8),
+(0x8FFAB9),(0x8FFABA),(0x8FFABB),(0x8FFABC),(0x8FFABD),(0x8FFABE),(0x8FFABF),(0x8FFAC0),
+(0x8FFAC1),(0x8FFAC2),(0x8FFAC3),(0x8FFAC4),(0x8FFAC5),(0x8FFAC6),(0x8FFAC7),(0x8FFAC8),
+(0x8FFAC9),(0x8FFACA),(0x8FFACB),(0x8FFACC),(0x8FFACD),(0x8FFACE),(0x8FFACF),(0x8FFAD0),
+(0x8FFAD1),(0x8FFAD2),(0x8FFAD3),(0x8FFAD4),(0x8FFAD5),(0x8FFAD6),(0x8FFAD7),(0x8FFAD8),
+(0x8FFAD9),(0x8FFADA),(0x8FFADB),(0x8FFADC),(0x8FFADD),(0x8FFADE),(0x8FFADF),(0x8FFAE0),
+(0x8FFAE1),(0x8FFAE2),(0x8FFAE3),(0x8FFAE4),(0x8FFAE5),(0x8FFAE6),(0x8FFAE7),(0x8FFAE8),
+(0x8FFAE9),(0x8FFAEA),(0x8FFAEB),(0x8FFAEC),(0x8FFAED),(0x8FFAEE),(0x8FFAEF),(0x8FFAF0),
+(0x8FFAF1),(0x8FFAF2),(0x8FFAF3),(0x8FFAF4),(0x8FFAF5),(0x8FFAF6),(0x8FFAF7),(0x8FFAF8),
+(0x8FFAF9),(0x8FFAFA),(0x8FFAFB),(0x8FFAFC),(0x8FFAFD),(0x8FFAFE),
+(0x8FFBA1),(0x8FFBA2),(0x8FFBA3),(0x8FFBA4),(0x8FFBA5),(0x8FFBA6),(0x8FFBA7),(0x8FFBA8),
+(0x8FFBA9),(0x8FFBAA),(0x8FFBAB),(0x8FFBAC),(0x8FFBAD),(0x8FFBAE),(0x8FFBAF),(0x8FFBB0),
+(0x8FFBB1),(0x8FFBB2),(0x8FFBB3),(0x8FFBB4),(0x8FFBB5),(0x8FFBB6),(0x8FFBB7),(0x8FFBB8),
+(0x8FFBB9),(0x8FFBBA),(0x8FFBBB),(0x8FFBBC),(0x8FFBBD),(0x8FFBBE),(0x8FFBBF),(0x8FFBC0),
+(0x8FFBC1),(0x8FFBC2),(0x8FFBC3),(0x8FFBC4),(0x8FFBC5),(0x8FFBC6),(0x8FFBC7),(0x8FFBC8),
+(0x8FFBC9),(0x8FFBCA),(0x8FFBCB),(0x8FFBCC),(0x8FFBCD),(0x8FFBCE),(0x8FFBCF),(0x8FFBD0),
+(0x8FFBD1),(0x8FFBD2),(0x8FFBD3),(0x8FFBD4),(0x8FFBD5),(0x8FFBD6),(0x8FFBD7),(0x8FFBD8),
+(0x8FFBD9),(0x8FFBDA),(0x8FFBDB),(0x8FFBDC),(0x8FFBDD),(0x8FFBDE),(0x8FFBDF),(0x8FFBE0),
+(0x8FFBE1),(0x8FFBE2),(0x8FFBE3),(0x8FFBE4),(0x8FFBE5),(0x8FFBE6),(0x8FFBE7),(0x8FFBE8),
+(0x8FFBE9),(0x8FFBEA),(0x8FFBEB),(0x8FFBEC),(0x8FFBED),(0x8FFBEE),(0x8FFBEF),(0x8FFBF0),
+(0x8FFBF1),(0x8FFBF2),(0x8FFBF3),(0x8FFBF4),(0x8FFBF5),(0x8FFBF6),(0x8FFBF7),(0x8FFBF8),
+(0x8FFBF9),(0x8FFBFA),(0x8FFBFB),(0x8FFBFC),(0x8FFBFD),(0x8FFBFE),
+(0x8FFCA1),(0x8FFCA2),(0x8FFCA3),(0x8FFCA4),(0x8FFCA5),(0x8FFCA6),(0x8FFCA7),(0x8FFCA8),
+(0x8FFCA9),(0x8FFCAA),(0x8FFCAB),(0x8FFCAC),(0x8FFCAD),(0x8FFCAE),(0x8FFCAF),(0x8FFCB0),
+(0x8FFCB1),(0x8FFCB2),(0x8FFCB3),(0x8FFCB4),(0x8FFCB5),(0x8FFCB6),(0x8FFCB7),(0x8FFCB8),
+(0x8FFCB9),(0x8FFCBA),(0x8FFCBB),(0x8FFCBC),(0x8FFCBD),(0x8FFCBE),(0x8FFCBF),(0x8FFCC0),
+(0x8FFCC1),(0x8FFCC2),(0x8FFCC3),(0x8FFCC4),(0x8FFCC5),(0x8FFCC6),(0x8FFCC7),(0x8FFCC8),
+(0x8FFCC9),(0x8FFCCA),(0x8FFCCB),(0x8FFCCC),(0x8FFCCD),(0x8FFCCE),(0x8FFCCF),(0x8FFCD0),
+(0x8FFCD1),(0x8FFCD2),(0x8FFCD3),(0x8FFCD4),(0x8FFCD5),(0x8FFCD6),(0x8FFCD7),(0x8FFCD8),
+(0x8FFCD9),(0x8FFCDA),(0x8FFCDB),(0x8FFCDC),(0x8FFCDD),(0x8FFCDE),(0x8FFCDF),(0x8FFCE0),
+(0x8FFCE1),(0x8FFCE2),(0x8FFCE3),(0x8FFCE4),(0x8FFCE5),(0x8FFCE6),(0x8FFCE7),(0x8FFCE8),
+(0x8FFCE9),(0x8FFCEA),(0x8FFCEB),(0x8FFCEC),(0x8FFCED),(0x8FFCEE),(0x8FFCEF),(0x8FFCF0),
+(0x8FFCF1),(0x8FFCF2),(0x8FFCF3),(0x8FFCF4),(0x8FFCF5),(0x8FFCF6),(0x8FFCF7),(0x8FFCF8),
+(0x8FFCF9),(0x8FFCFA),(0x8FFCFB),(0x8FFCFC),(0x8FFCFD),(0x8FFCFE),
+(0x8FFDA1),(0x8FFDA2),(0x8FFDA3),(0x8FFDA4),(0x8FFDA5),(0x8FFDA6),(0x8FFDA7),(0x8FFDA8),
+(0x8FFDA9),(0x8FFDAA),(0x8FFDAB),(0x8FFDAC),(0x8FFDAD),(0x8FFDAE),(0x8FFDAF),(0x8FFDB0),
+(0x8FFDB1),(0x8FFDB2),(0x8FFDB3),(0x8FFDB4),(0x8FFDB5),(0x8FFDB6),(0x8FFDB7),(0x8FFDB8),
+(0x8FFDB9),(0x8FFDBA),(0x8FFDBB),(0x8FFDBC),(0x8FFDBD),(0x8FFDBE),(0x8FFDBF),(0x8FFDC0),
+(0x8FFDC1),(0x8FFDC2),(0x8FFDC3),(0x8FFDC4),(0x8FFDC5),(0x8FFDC6),(0x8FFDC7),(0x8FFDC8),
+(0x8FFDC9),(0x8FFDCA),(0x8FFDCB),(0x8FFDCC),(0x8FFDCD),(0x8FFDCE),(0x8FFDCF),(0x8FFDD0),
+(0x8FFDD1),(0x8FFDD2),(0x8FFDD3),(0x8FFDD4),(0x8FFDD5),(0x8FFDD6),(0x8FFDD7),(0x8FFDD8),
+(0x8FFDD9),(0x8FFDDA),(0x8FFDDB),(0x8FFDDC),(0x8FFDDD),(0x8FFDDE),(0x8FFDDF),(0x8FFDE0),
+(0x8FFDE1),(0x8FFDE2),(0x8FFDE3),(0x8FFDE4),(0x8FFDE5),(0x8FFDE6),(0x8FFDE7),(0x8FFDE8),
+(0x8FFDE9),(0x8FFDEA),(0x8FFDEB),(0x8FFDEC),(0x8FFDED),(0x8FFDEE),(0x8FFDEF),(0x8FFDF0),
+(0x8FFDF1),(0x8FFDF2),(0x8FFDF3),(0x8FFDF4),(0x8FFDF5),(0x8FFDF6),(0x8FFDF7),(0x8FFDF8),
+(0x8FFDF9),(0x8FFDFA),(0x8FFDFB),(0x8FFDFC),(0x8FFDFD),(0x8FFDFE),
+(0x8FFEA1),(0x8FFEA2),(0x8FFEA3),(0x8FFEA4),(0x8FFEA5),(0x8FFEA6),(0x8FFEA7),(0x8FFEA8),
+(0x8FFEA9),(0x8FFEAA),(0x8FFEAB),(0x8FFEAC),(0x8FFEAD),(0x8FFEAE),(0x8FFEAF),(0x8FFEB0),
+(0x8FFEB1),(0x8FFEB2),(0x8FFEB3),(0x8FFEB4),(0x8FFEB5),(0x8FFEB6),(0x8FFEB7),(0x8FFEB8),
+(0x8FFEB9),(0x8FFEBA),(0x8FFEBB),(0x8FFEBC),(0x8FFEBD),(0x8FFEBE),(0x8FFEBF),(0x8FFEC0),
+(0x8FFEC1),(0x8FFEC2),(0x8FFEC3),(0x8FFEC4),(0x8FFEC5),(0x8FFEC6),(0x8FFEC7),(0x8FFEC8),
+(0x8FFEC9),(0x8FFECA),(0x8FFECB),(0x8FFECC),(0x8FFECD),(0x8FFECE),(0x8FFECF),(0x8FFED0),
+(0x8FFED1),(0x8FFED2),(0x8FFED3),(0x8FFED4),(0x8FFED5),(0x8FFED6),(0x8FFED7),(0x8FFED8),
+(0x8FFED9),(0x8FFEDA),(0x8FFEDB),(0x8FFEDC),(0x8FFEDD),(0x8FFEDE),(0x8FFEDF),(0x8FFEE0),
+(0x8FFEE1),(0x8FFEE2),(0x8FFEE3),(0x8FFEE4),(0x8FFEE5),(0x8FFEE6),(0x8FFEE7),(0x8FFEE8),
+(0x8FFEE9),(0x8FFEEA),(0x8FFEEB),(0x8FFEEC),(0x8FFEED),(0x8FFEEE),(0x8FFEEF),(0x8FFEF0),
+(0x8FFEF1),(0x8FFEF2),(0x8FFEF3),(0x8FFEF4),(0x8FFEF5),(0x8FFEF6),(0x8FFEF7),(0x8FFEF8),
+(0x8FFEF9),(0x8FFEFA),(0x8FFEFB),(0x8FFEFC),(0x8FFEFD),(0x8FFEFE);
+
+#Test that all the characters are stored correctly
+SELECT HEX(c1) FROM t1;
+
+#Test conversion to ucs2
+CREATE TABLE t2 SELECT CONVERT(c1 USING ucs2) AS c1 FROM t1;
+SELECT HEX(c1) FROM t2;
+
+#Test round trip conversion
+CREATE TABLE t3 SELECT CONVERT(c1 USING eucjpms) AS c1 FROM t2;
+SELECT HEX(c1) FROM t3;
+
+#Test conversion to cp932
+CREATE TABLE t4 SELECT CONVERT(c1 USING cp932) AS c1 FROM t1;
+SELECT HEX(c1) FROM t4;
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+DROP TABLE t4;
+
+#Test bug#11717
+CREATE TABLE t1(c1 varchar(10)) default character set = eucjpms;
+
+insert into t1 values(_ucs2 0x00F7);
+insert into t1 values(_eucjpms 0xA1E0);
+insert into t1 values(_ujis 0xA1E0);
+insert into t1 values(_sjis 0x8180);
+insert into t1 values(_cp932 0x8180);
+
+SELECT HEX(c1) FROM t1;
+
+DROP TABLE t1;
+
+SET collation_connection='eucjpms_japanese_ci';
+-- source include/ctype_filesort.inc
+SET collation_connection='eucjpms_bin';
+-- source include/ctype_filesort.inc
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
index 58153913648..d6a11a22857 100644
--- a/mysql-test/t/ctype_latin1_de.test
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -66,7 +66,7 @@ drop table t1;
#
# The below checks both binary and character comparisons.
#
-create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
+create table t1 (word varchar(255) not null, word2 varchar(255) not null default '', index(word));
show create table t1;
insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word;
@@ -134,3 +134,11 @@ SELECT * FROM t1 WHERE col1='ß' ORDER BY col1, BINARY col1;
DROP TABLE t1;
# End of 4.1 tests
+
+#
+# Bug#9509
+#
+create table t1 (s1 char(5) character set latin1 collate latin1_german2_ci);
+insert into t1 values (0xf6) /* this is o-umlaut */;
+select * from t1 where length(s1)=1 and s1='oe';
+drop table t1;
diff --git a/mysql-test/t/ctype_many.test b/mysql-test/t/ctype_many.test
index 26dc6282e1e..22e844c6868 100644
--- a/mysql-test/t/ctype_many.test
+++ b/mysql-test/t/ctype_many.test
@@ -8,7 +8,7 @@ SET CHARACTER SET latin1;
CREATE TABLE t1 (
comment CHAR(32) ASCII NOT NULL,
- koi8_ru_f CHAR(32) CHARACTER SET koi8r NOT NULL
+ koi8_ru_f CHAR(32) CHARACTER SET koi8r NOT NULL default ''
) CHARSET=latin5;
SHOW CREATE TABLE t1;
@@ -142,13 +142,13 @@ INSERT INTO t1 (koi8_ru_f,comment) VALUES (_koi8r'ñ','CYR CAPIT YA');
SET CHARACTER SET utf8;
SELECT koi8_ru_f,MIN(comment),COUNT(*) FROM t1 GROUP BY 1;
-ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL;
+ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL default '';
UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8);
SET CHARACTER SET koi8r;
SELECT * FROM t1;
-ALTER TABLE t1 ADD bin_f CHAR(32) BYTE NOT NULL;
+ALTER TABLE t1 ADD bin_f CHAR(32) BYTE NOT NULL default '';
UPDATE t1 SET bin_f=koi8_ru_f;
SELECT COUNT(DISTINCT bin_f),COUNT(DISTINCT koi8_ru_f),COUNT(DISTINCT utf8_f) FROM t1;
diff --git a/mysql-test/t/ctype_uca.test b/mysql-test/t/ctype_uca.test
index 9d81aa74e90..43ef0cc8755 100644
--- a/mysql-test/t/ctype_uca.test
+++ b/mysql-test/t/ctype_uca.test
@@ -211,6 +211,7 @@ select group_concat(c1 order by c1) from t1 group by c1 collate utf8_lithuanian_
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;
select group_concat(c1 order by c1) from t1 group by c1 collate utf8_roman_ci;
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_esperanto_ci;
drop table t1;
@@ -457,3 +458,18 @@ SET collation_connection='utf8_unicode_ci';
-- source include/ctype_filesort.inc
# End of 4.1 tests
+
+#
+# Check UPPER/LOWER changeing length
+#
+# Result shorter than argument
+CREATE TABLE t1 (id int, a varchar(30) character set utf8);
+INSERT INTO t1 VALUES (1, _ucs2 0x01310069), (2, _ucs2 0x01310131);
+INSERT INTO t1 VALUES (3, _ucs2 0x00690069), (4, _ucs2 0x01300049);
+INSERT INTO t1 VALUES (5, _ucs2 0x01300130), (6, _ucs2 0x00490049);
+SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
+FROM t1 ORDER BY id;
+ALTER TABLE t1 MODIFY a VARCHAR(30) character set utf8 collate utf8_turkish_ci;
+SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
+FROM t1 ORDER BY id;
+DROP TABLE t1;
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 4a5c80bed6e..668edb3fafe 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -20,17 +20,19 @@ SET CHARACTER SET koi8r;
# which contains 0x20 in the high byte.
#
-CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2);
-INSERT INTO t1 VALUES (_koi8r'ò'), (X'2004');
+CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004');
SELECT hex(word) FROM t1 ORDER BY word;
+SELECT hex(word2) FROM t1 ORDER BY word2;
DELETE FROM t1;
#
# Check that real spaces are correctly trimmed.
#
-INSERT INTO t1 VALUES (X'042000200020'), (X'200400200020');
+INSERT INTO t1 VALUES (X'042000200020',X'042000200020'), (X'200400200020', X'200400200020');
SELECT hex(word) FROM t1 ORDER BY word;
+SELECT hex(word2) FROM t1 ORDER BY word2;
DROP TABLE t1;
#
@@ -52,7 +54,6 @@ RPAD(_ucs2 X'0420',10,_ucs2 X'0421') r;
SHOW CREATE TABLE t1;
DROP TABLE t1;
-
#
# BUG3946
#
@@ -61,6 +62,7 @@ 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
@@ -418,3 +420,26 @@ select hex(a) from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Conversion from an UCS2 string to a decimal column
+#
+CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3));
+INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0);
+update t1 set b=a;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Bug#9442 Set parameter make query fail if column character set is UCS2
+#
+create table t1 (utext varchar(20) character set ucs2);
+insert into t1 values ("lily");
+insert into t1 values ("river");
+prepare stmt from 'select utext from t1 where utext like ?';
+set @param1='%%';
+execute stmt using @param1;
+execute stmt using @param1;
+select utext from t1 where utext like '%%';
+drop table t1;
+deallocate prepare stmt;
diff --git a/mysql-test/t/ctype_ucs_binlog.test b/mysql-test/t/ctype_ucs_binlog.test
index 7faefde7d1a..1ce55edd469 100644
--- a/mysql-test/t/ctype_ucs_binlog.test
+++ b/mysql-test/t/ctype_ucs_binlog.test
@@ -9,7 +9,7 @@ create table t2 (c char(30)) charset=ucs2;
set @v=convert('abc' using ucs2);
reset master;
insert into t2 values (@v);
-show binlog events from 79;
+show binlog events from 98;
# more important than SHOW BINLOG EVENTS, mysqlbinlog (where we
# absolutely need variables names to be quoted and strings to be
# escaped).
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 0cdda648899..b009e13874f 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -838,20 +838,6 @@ drop table t1;
#
-# Bug #12371 executing prepared statement fails (illegal mix of collations)
-#
-set names utf8;
-create table t1 (a char(3), b varchar(10));
-insert into t1 values ('bar','kostja');
-prepare my_stmt from "select * from t1 where a=?";
-set @a:='bar';
-execute my_stmt using @a;
-set @a:=NULL;
-execute my_stmt using @a;
-drop table t1;
-
-
-#
# Bug#9557 MyISAM utf8 table crash
#
CREATE TABLE t1 (
@@ -864,3 +850,45 @@ select hex(a) from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Test for bug #11484: wrong results for a DISTINCT varchar column in uft8.
+#
+
+CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa');
+
+SELECT id FROM t1;
+SELECT DISTINCT id FROM t1;
+SELECT DISTINCT id FROM t1 ORDER BY id;
+
+DROP TABLE t1;
+
+#
+# Bugs#10504: Character set does not support traditional mode
+#
+set names utf8;
+# correct value
+select hex(char(1));
+select char(0xd1,0x8f);
+select char(0xd18f);
+select char(53647);
+# incorrect value: return with warning
+select char(0xff,0x8f);
+# incorrect value in strict mode: return NULL with "Error" level warning
+set sql_mode=traditional;
+select char(0xff,0x8f);
+select char(195);
+select char(196);
+select char(2557);
+
+#
+# Bug#12891: UNION doesn't return DISTINCT result for multi-byte characters
+#
+set names utf8;
+create table t1 (a char(1)) default character set utf8;
+create table t2 (a char(1)) default character set utf8;
+insert into t1 values('a'),('a'),(0xE38182),(0xE38182);
+insert into t1 values('i'),('i'),(0xE38184),(0xE38184);
+select * from t1 union distinct select * from t2;
+drop table t1,t2;
diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test
index 62e9d81021e..f76f51fd12d 100644
--- a/mysql-test/t/date_formats.test
+++ b/mysql-test/t/date_formats.test
@@ -122,6 +122,7 @@ SET datetime_format=default;
--disable_ps_protocol
select str_to_date(concat('15-01-2001',' 2:59:58.999'),
concat('%d-%m-%Y',' ','%H:%i:%s.%f'));
+select STR_TO_DATE('2004.12.12 22.30.61','%Y.%m.%d %T');
--enable_ps_protocol
create table t1 (date char(30), format char(30) not null);
diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test
new file mode 100644
index 00000000000..42620a27b66
--- /dev/null
+++ b/mysql-test/t/default.test
@@ -0,0 +1,85 @@
+#
+# test of already fixed bugs
+#
+--disable_warnings
+drop table if exists t1,t2,t3,t4,t5,t6;
+drop database if exists mysqltest;
+
+#
+# Bug 10838
+# Insert causes warnings for no default values and corrupts tables
+#
+CREATE TABLE t1 (a varchar(30) binary NOT NULL DEFAULT ' ',
+ b varchar(1) binary NOT NULL DEFAULT ' ',
+ c varchar(4) binary NOT NULL DEFAULT '0000',
+ d tinyblob NULL,
+ e tinyblob NULL,
+ f tinyblob NULL,
+ g tinyblob NULL,
+ h tinyblob NULL,
+ i tinyblob NULL,
+ j tinyblob NULL,
+ k tinyblob NULL,
+ l tinyblob NULL,
+ m tinyblob NULL,
+ n tinyblob NULL,
+ o tinyblob NULL,
+ p tinyblob NULL,
+ q varchar(30) binary NOT NULL DEFAULT ' ',
+ r varchar(30) binary NOT NULL DEFAULT ' ',
+ s tinyblob NULL,
+ t varchar(4) binary NOT NULL DEFAULT ' ',
+ u varchar(1) binary NOT NULL DEFAULT ' ',
+ v varchar(30) binary NOT NULL DEFAULT ' ',
+ w varchar(30) binary NOT NULL DEFAULT ' ',
+ x tinyblob NULL,
+ y varchar(5) binary NOT NULL DEFAULT ' ',
+ z varchar(20) binary NOT NULL DEFAULT ' ',
+ a1 varchar(30) binary NOT NULL DEFAULT ' ',
+ b1 tinyblob NULL)
+ENGINE=InnoDB DEFAULT CHARACTER SET = latin1 COLLATE latin1_bin;
+--enable_warnings
+
+SHOW CREATE TABLE t1;
+INSERT into t1 (b) values ('1');
+SHOW WARNINGS;
+SELECT * from t1;
+
+CREATE TABLE t2 (a varchar(30) binary NOT NULL DEFAULT ' ',
+ b varchar(1) binary NOT NULL DEFAULT ' ',
+ c varchar(4) binary NOT NULL DEFAULT '0000',
+ d tinyblob NULL,
+ e tinyblob NULL,
+ f tinyblob NULL,
+ g tinyblob NULL,
+ h tinyblob NULL,
+ i tinyblob NULL,
+ j tinyblob NULL,
+ k tinyblob NULL,
+ l tinyblob NULL,
+ m tinyblob NULL,
+ n tinyblob NULL,
+ o tinyblob NULL,
+ p tinyblob NULL,
+ q varchar(30) binary NOT NULL DEFAULT ' ',
+ r varchar(30) binary NOT NULL DEFAULT ' ',
+ s tinyblob NULL,
+ t varchar(4) binary NOT NULL DEFAULT ' ',
+ u varchar(1) binary NOT NULL DEFAULT ' ',
+ v varchar(30) binary NOT NULL DEFAULT ' ',
+ w varchar(30) binary NOT NULL DEFAULT ' ',
+ x tinyblob NULL,
+ y varchar(5) binary NOT NULL DEFAULT ' ',
+ z varchar(20) binary NOT NULL DEFAULT ' ',
+ a1 varchar(30) binary NOT NULL DEFAULT ' ',
+ b1 tinyblob NULL)
+ENGINE=MyISAM DEFAULT CHARACTER SET = latin1 COLLATE latin1_bin;
+
+SHOW CREATE TABLE t2;
+INSERT into t2 (b) values ('1');
+SHOW WARNINGS;
+SELECT * from t2;
+
+drop table t1;
+drop table t2;
+
diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
index a32eec536ea..ca34cc020f3 100644
--- a/mysql-test/t/delayed.test
+++ b/mysql-test/t/delayed.test
@@ -31,8 +31,19 @@ insert delayed into t1 values (null,"c");
insert delayed into t1 values (3,"d"),(null,"e");
--error 1136
insert delayed into t1 values (3,"this will give an","error");
---sleep 2
+# 2 was not enough for --ps-protocol
+--sleep 4
+show status like 'not_flushed_delayed_rows';
select * from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Bug #12226: Crash when a delayed insert fails due to a duplicate key
+#
+create table t1 (a int not null primary key);
+insert into t1 values (1);
+insert delayed into t1 values (1);
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test
index 98e4c4e35fa..4284bd2a06d 100644
--- a/mysql-test/t/delete.test
+++ b/mysql-test/t/delete.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1,t11,t12,t2;
+drop table if exists t1,t2,t3,t11,t12;
--enable_warnings
CREATE TABLE t1 (a tinyint(3), b tinyint(5));
INSERT INTO t1 VALUES (1,1);
@@ -154,3 +154,20 @@ SELECT * FROM t1;
DROP TABLE t1;
# End of 4.1 tests
+
+#
+# Test of multi-delete where we are not scanning the first table
+#
+
+CREATE TABLE t1 (a int not null,b int not null);
+CREATE TABLE t2 (a int not null, b int not null, primary key (a,b));
+CREATE TABLE t3 (a int not null, b int not null, primary key (a,b));
+insert into t1 values (1,1),(2,1),(1,3);
+insert into t2 values (1,1),(2,2),(3,3);
+insert into t3 values (1,1),(2,1),(1,3);
+select * from t1,t2,t3 where t1.a=t2.a AND t2.b=t3.a and t1.b=t3.b;
+explain select * from t1,t2,t3 where t1.a=t2.a AND t2.b=t3.a and t1.b=t3.b;
+delete t2.*,t3.* from t1,t2,t3 where t1.a=t2.a AND t2.b=t3.a and t1.b=t3.b;
+# This should be empty
+select * from t3;
+drop table t1,t2,t3;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 91fa3238e69..f52e12849e4 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -42,7 +42,7 @@ CREATE TABLE t2 (a int not null);
insert into t2 values(1);
select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a;
-explain select * from (select * from t1,t2 where t1.a=t2.a) t1;
+explain select * from (select t1.*, t2.a as t2a from t1,t2 where t1.a=t2.a) t1;
drop table t1, t2;
create table t1(a int not null, t char(8), index(a));
disable_query_log;
@@ -140,7 +140,6 @@ select * from ( select * from t1 union select * from t1) a,(select * from t1 uni
explain select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
drop table t1;
-
#
# multi-update & multi-delete with derived tables
#
@@ -224,6 +223,19 @@ select distinct sum(b) from t1 group by a;
select distinct sum(b) from (select a,b from t1) y group by a;
drop table t1;
+
+#
+# Test for bug #7413 "Subquery with non-scalar results participating in
+# select list of derived table crashes server" aka "VIEW with sub query can
+# cause the MySQL server to crash". If we have encountered problem during
+# filling of derived table we should report error and perform cleanup
+# properly.
+#
+CREATE TABLE t1 (a char(10), b char(10));
+INSERT INTO t1 VALUES ('root','localhost'), ('root','%');
+--error 1242
+SELECT * FROM (SELECT (SELECT a.a FROM t1 AS a WHERE a.a = b.a) FROM t1 AS b) AS c;
+DROP TABLE t1;
#
# test of union subquery in the FROM clause with complex distinct/all (BUG#6565)
#
@@ -237,4 +249,13 @@ select * from t1 union distinct select * from t2 union all select * from t3;
select * from (select * from t1 union distinct select * from t2 union all select * from t3) X;
drop table t1, t2, t3;
+#
+# Bug #11864 non unique names are allowed in subquery
+#
+create table t1 (a int);
+create table t2 (a int);
+--error 1060
+select * from (select * from t1,t2) foo;
+drop table t1,t2;
+
# End of 4.1 tests
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
new file mode 100644
index 00000000000..fe95a543fb5
--- /dev/null
+++ b/mysql-test/t/disabled.def
@@ -0,0 +1,17 @@
+##############################################################################
+#
+# List the test cases that are to be disabled temporarely.
+#
+# Separate the test case name and the comment with ':'.
+#
+# <testcasename> : Comment test
+#
+# Don't use any TAB characters for whitespace.
+#
+##############################################################################
+
+sp-goto : GOTO is currently is disabled - will be fixed in the future
+rpl_relayrotate : Unstable test case, bug#12429
+rpl_until : Unstable test case, bug#12429
+rpl_deadlock : Unstable test case, bug#12429
+kill : Unstable test case, bug#9712
diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test
index f2fe1ec6372..6483284633f 100644
--- a/mysql-test/t/distinct.test
+++ b/mysql-test/t/distinct.test
@@ -326,11 +326,11 @@ drop table t1,t2;
CREATE TABLE t1 (
html varchar(5) default NULL,
rin int(11) default '0',
- out int(11) default '0'
+ rout int(11) default '0'
) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('1',1,0);
-SELECT DISTINCT html,SUM(out)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
+SELECT DISTINCT html,SUM(rout)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
drop table t1;
#
@@ -350,4 +350,11 @@ SELECT DISTINCT a, 2, b FROM t2;
DROP TABLE t1,t2;
+# Bug 9784 DISTINCT IFNULL truncates data
+#
+create table t1 (id int, dsc varchar(50));
+insert into t1 values (1, "line number one"), (2, "line number two"), (3, "line number three");
+select distinct id, IFNULL(dsc, '-') from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/endspace.test b/mysql-test/t/endspace.test
index 28b288e34a3..c4d53450910 100644
--- a/mysql-test/t/endspace.test
+++ b/mysql-test/t/endspace.test
@@ -41,16 +41,16 @@ alter table t1 modify text1 text not null, pack_keys=1;
select concat('|', text1, '|') from t1 where text1='teststring';
select concat('|', text1, '|') from t1 where text1='teststring ';
explain select concat('|', text1, '|') from t1 where text1='teststring ';
-select * from t1 where text1 like 'teststring_%';
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
+select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
select concat('|', text1, '|') from t1 order by text1;
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1)) pack_keys=0;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
-select * from t1 where text1='teststring' or text1 >= 'teststring\t';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 >= 'teststring\t';
drop table t1;
# Test HEAP tables (with BTREE keys)
diff --git a/mysql-test/t/errors.test b/mysql-test/t/errors.test
index 93668ffdd3d..f5647a293e8 100644
--- a/mysql-test/t/errors.test
+++ b/mysql-test/t/errors.test
@@ -14,9 +14,9 @@ update t1 set a=1;
create table t1 (a int);
--error 1054
select count(test.t1.b) from t1;
---error 1109
+--error 1054
select count(not_existing_database.t1) from t1;
---error 1109
+--error 1054
select count(not_existing_database.t1.a) from t1;
--error 1044,1146
select count(not_existing_database.t1.a) from not_existing_database.t1;
@@ -31,3 +31,14 @@ select count(*),b from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Bug #6080: Error message for a field with a display width that is too long
+#
+--error 1439
+create table t1 (a int(256));
+set sql_mode='traditional';
+--error 1074
+create table t1 (a varchar(66000));
+
+# End of 5.0 tests
diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test
new file mode 100644
index 00000000000..28091676dd7
--- /dev/null
+++ b/mysql-test/t/federated.test
@@ -0,0 +1,1147 @@
+source include/federated.inc;
+
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ DEFAULT CHARSET=latin1;
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+# test too many items (malformed) in the comment string url
+--error 1432
+CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:@/too/many/items/federated/t1';
+
+# test not enough items (malformed) in the comment string url
+--error 1432
+CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1';
+
+# test non-existant table
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error 1434
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t3';
+
+# test bad user/password
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--error 1429
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://user:pass@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+DROP TABLE IF EXISTS federated.t1;
+# # correct connection, same named tables
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (id, name) VALUES (1, 'foo');
+INSERT INTO federated.t1 (id, name) VALUES (2, 'fee');
+
+SELECT * FROM federated.t1;
+DELETE FROM federated.t1;
+DROP TABLE federated.t1;
+
+# correct connection, differently named tables
+DROP TABLE IF EXISTS federated.t2;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t2 (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t2 (id, name) VALUES (1, 'foo');
+INSERT INTO federated.t2 (id, name) VALUES (2, 'fee');
+
+SELECT * FROM federated.t2;
+DROP TABLE federated.t2;
+
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+
+DROP TABLE IF EXISTS federated.`t1%`;
+CREATE TABLE federated.`t1%` (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ DEFAULT CHARSET=latin1;
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1%';
+
+INSERT INTO federated.t1 (id, name) VALUES (1, 'foo');
+INSERT INTO federated.t1 (id, name) VALUES (2, 'fee');
+
+SELECT * FROM federated.t1;
+DELETE FROM federated.t1;
+DROP TABLE IF EXISTS federated.t1;
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.`t1%` (
+ `id` int(20) NOT NULL,
+ `name` varchar(32) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1%';
+
+INSERT INTO federated.`t1%` (id, name) VALUES (1, 'foo');
+INSERT INTO federated.`t1%` (id, name) VALUES (2, 'fee');
+
+SELECT * FROM federated.`t1%`;
+DELETE FROM federated.`t1%`;
+DROP TABLE IF EXISTS federated.`t1%`;
+
+connection slave;
+DROP TABLE IF EXISTS federated.`t1%`;
+
+# I wanted to use timestamp, but results will fail if so!!!
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `name` varchar(32) NOT NULL default '',
+ `other` int(20) NOT NULL default '0',
+ `created` datetime default '2004-04-04 04:04:04',
+ PRIMARY KEY (`id`))
+ DEFAULT CHARSET=latin1;
+
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `name` varchar(32) NOT NULL default '',
+ `other` int(20) NOT NULL default '0',
+ `created` datetime default '2004-04-04 04:04:04',
+ PRIMARY KEY (`id`))
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (name, other) VALUES ('First Name', 11111);
+INSERT INTO federated.t1 (name, other) VALUES ('Second Name', 22222);
+INSERT INTO federated.t1 (name, other) VALUES ('Third Name', 33333);
+INSERT INTO federated.t1 (name, other) VALUES ('Fourth Name', 44444);
+INSERT INTO federated.t1 (name, other) VALUES ('Fifth Name', 55555);
+INSERT INTO federated.t1 (name, other) VALUES ('Sixth Name', 66666);
+INSERT INTO federated.t1 (name, other) VALUES ('Seventh Name', 77777);
+INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888);
+INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999);
+INSERT INTO federated.t1 (name, other) VALUES ('Tenth Name', 101010);
+
+# basic select
+SELECT * FROM federated.t1;
+# with PRIMARY KEY index_read_idx
+SELECT * FROM federated.t1 WHERE id = 5;
+SELECT * FROM federated.t1 WHERE name = 'Sixth Name';
+SELECT * FROM federated.t1 WHERE id = 6 and name = 'Sixth Name';
+SELECT * FROM federated.t1 WHERE name = 'Sixth Name' AND other = 44444;
+SELECT * FROM federated.t1 WHERE name like '%th%';
+UPDATE federated.t1 SET name = '3rd name' WHERE id = 3;
+SELECT * FROM federated.t1 WHERE name = '3rd name';
+UPDATE federated.t1 SET name = 'Third name' WHERE name = '3rd name';
+SELECT * FROM federated.t1 WHERE name = 'Third name';
+# rnd_post, ::position
+SELECT * FROM federated.t1 ORDER BY id DESC;
+SELECT * FROM federated.t1 ORDER BY name;
+SELECT * FROM federated.t1 ORDER BY name DESC;
+SELECT * FROM federated.t1 ORDER BY name ASC;
+SELECT * FROM federated.t1 GROUP BY other;
+
+# ::delete_row
+DELETE FROM federated.t1 WHERE id = 5;
+SELECT * FROM federated.t1 WHERE id = 5;
+
+# ::delete_all_rows
+DELETE FROM federated.t1;
+SELECT * FROM federated.t1 WHERE id = 5;
+
+# previous test, but this time with indexes
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `name` varchar(32) NOT NULL default '',
+ `other` int(20) NOT NULL default '0',
+ `created` datetime NOT NULL,
+ PRIMARY KEY (`id`),
+ key name(`name`),
+ key other(`other`),
+ key created(`created`))
+ DEFAULT CHARSET=latin1;
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `name` varchar(32) NOT NULL default '',
+ `other` int(20) NOT NULL default '0',
+ `created` datetime NOT NULL,
+ PRIMARY KEY (`id`),
+ key name(`name`),
+ key other(`other`),
+ key created(`created`))
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('First Name', 11111, '2004-01-01 01:01:01');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Second Name', 22222, '2004-01-23 02:43:00');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Third Name', 33333, '2004-02-14 02:14:00');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Fourth Name', 44444, '2003-04-05 00:00:00');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Fifth Name', 55555, '2001-02-02 02:02:02');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Sixth Name', 66666, '2005-06-06 15:30:00');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Seventh Name', 77777, '2003-12-12 18:32:00');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Eigth Name', 88888, '2005-03-12 11:00:00');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Ninth Name', 99999, '2005-03-12 11:00:01');
+INSERT INTO federated.t1 (name, other, created)
+ VALUES ('Tenth Name', 101010, '2005-03-12 12:00:01');
+
+# basic select
+SELECT * FROM federated.t1;
+# with PRIMARY KEY index_read_idx
+SELECT * FROM federated.t1 WHERE id = 5;
+# with regular key index_read -> index_read_idx
+# regular and PRIMARY KEY index_read_idx
+SELECT * FROM federated.t1 WHERE id = 6 and name = 'Sixth Name';
+# with regular key index_read -> index_read_idx
+SELECT * FROM federated.t1 WHERE other = 44444;
+SELECT * FROM federated.t1 WHERE name like '%th%';
+# update - update_row, index_read_idx
+UPDATE federated.t1 SET name = '3rd name' WHERE id = 3;
+SELECT * FROM federated.t1 WHERE name = '3rd name';
+# update - update_row, index_read -> index_read_idx
+UPDATE federated.t1 SET name = 'Third name' WHERE name = '3rd name';
+SELECT * FROM federated.t1 WHERE name = 'Third name';
+# rnd_post, ::position
+SELECT * FROM federated.t1 ORDER BY id DESC;
+SELECT * FROM federated.t1 ORDER BY name;
+SELECT * FROM federated.t1 ORDER BY name DESC;
+SELECT * FROM federated.t1 ORDER BY name ASC;
+SELECT * FROM federated.t1 GROUP BY other;
+
+# ::delete_row
+DELETE FROM federated.t1 WHERE id = 5;
+SELECT * FROM federated.t1 WHERE id = 5;
+
+# ::delete_all_rows
+DELETE FROM federated.t1;
+SELECT * FROM federated.t1 WHERE id = 5;
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `name` varchar(32),
+ `other` varchar(20),
+ PRIMARY KEY (`id`) );
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `name` varchar(32),
+ `other` varchar(20),
+ PRIMARY KEY (`id`) )
+ ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (name, other) VALUES ('First Name', 11111);
+INSERT INTO federated.t1 (name, other) VALUES ('Second Name', NULL);
+INSERT INTO federated.t1 (name, other) VALUES ('Third Name', 33333);
+INSERT INTO federated.t1 (name, other) VALUES (NULL, NULL);
+INSERT INTO federated.t1 (name, other) VALUES ('Fifth Name', 55555);
+INSERT INTO federated.t1 (name, other) VALUES ('Sixth Name', 66666);
+INSERT INTO federated.t1 (name) VALUES ('Seventh Name');
+INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888);
+INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999);
+INSERT INTO federated.t1 (other) VALUES ('fee fie foe fum');
+
+SELECT * FROM federated.t1 WHERE other IS NULL;
+SELECT * FROM federated.t1 WHERE name IS NULL;
+SELECT * FROM federated.t1 WHERE name IS NULL and other IS NULL;
+SELECT * FROM federated.t1 WHERE name IS NULL or other IS NULL;
+
+UPDATE federated.t1
+SET name = 'Fourth Name', other = 'four four four'
+WHERE name IS NULL AND other IS NULL;
+
+UPDATE federated.t1 SET other = 'two two two two' WHERE name = 'Second Name';
+UPDATE federated.t1 SET other = 'seven seven' WHERE name like 'Sev%';
+UPDATE federated.t1 SET name = 'Tenth Name' WHERE other like 'fee fie%';
+SELECT * FROM federated.t1 WHERE name IS NULL OR other IS NULL ;
+SELECT * FROM federated.t1;
+
+# test multi-keys
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `name` varchar(32) NOT NULL DEFAULT '',
+ `other` varchar(20) NOT NULL DEFAULT '',
+ PRIMARY KEY (`id`),
+ KEY nameoth (name, other) );
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `name` varchar(32) NOT NULL DEFAULT '',
+ `other` varchar(20) NOT NULL DEFAULT '',
+ PRIMARY KEY (`id`),
+ KEY nameoth (name, other))
+ ENGINE="FEDERATED" DEFAULT
+ CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (name, other) VALUES ('First Name', '1111');
+INSERT INTO federated.t1 (name, other) VALUES ('Second Name', '2222');
+INSERT INTO federated.t1 (name, other) VALUES ('Third Name', '3333');
+SELECT * FROM federated.t1 WHERE name = 'Second Name';
+SELECT * FROM federated.t1 WHERE other = '2222';
+SELECT * FROM federated.t1 WHERE name = 'Third Name';
+SELECT * FROM federated.t1 WHERE name = 'Third Name' AND other = '3333';
+
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int NOT NULL auto_increment,
+ `name` char(32) NOT NULL DEFAULT '',
+ `bincol` binary(4) NOT NULL,
+ `floatval` decimal(5,2) NOT NULL DEFAULT 0.0,
+ `other` int NOT NULL DEFAULT 0,
+ PRIMARY KEY (id),
+ KEY nameoth(name, other),
+ KEY bincol(bincol),
+ KEY floatval(floatval));
+
+# test other types of indexes
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int NOT NULL auto_increment,
+ `name` char(32) NOT NULL DEFAULT '',
+ `bincol` binary(4) NOT NULL,
+ `floatval` decimal(5,2) NOT NULL DEFAULT 0.0,
+ `other` int NOT NULL DEFAULT 0,
+ PRIMARY KEY (id),
+ KEY nameoth(name,other),
+ KEY bincol(bincol),
+ KEY floatval(floatval))
+ ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (name, bincol, floatval, other)
+ VALUES ('first', 0x65, 11.11, 1111);
+INSERT INTO federated.t1 (name, bincol, floatval, other)
+ VALUES ('second', 0x66, 22.22, 2222);
+INSERT INTO federated.t1 (name, bincol, floatval, other)
+ VALUES ('third', 'g', 22.22, 2222);
+SELECT * FROM federated.t1;
+SELECT * FROM federated.t1 WHERE name = 'second';
+SELECT * FROM federated.t1 WHERE bincol= 'f';
+SELECT * FROM federated.t1 WHERE bincol= 0x66;
+SELECT * FROM federated.t1 WHERE bincol= 0x67;
+SELECT * FROM federated.t1 WHERE bincol= 'g';
+SELECT * FROM federated.t1 WHERE floatval=11.11;
+SELECT * FROM federated.t1 WHERE name='third';
+SELECT * FROM federated.t1 WHERE other=2222;
+SELECT * FROM federated.t1 WHERE name='third' and other=2222;
+
+# more multi-column indexes, in the primary key
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int NOT NULL auto_increment,
+ `col1` int(10) NOT NULL DEFAULT 0,
+ `col2` varchar(64) NOT NULL DEFAULT '',
+ `col3` int(20) NOT NULL,
+ `col4` int(40) NOT NULL,
+ primary key (`id`, `col1`, `col2`, `col3`, `col4`),
+ key col1(col1),
+ key col2(col2),
+ key col3(col3),
+ key col4(col4));
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int NOT NULL auto_increment,
+ `col1` int(10) NOT NULL DEFAULT 0,
+ `col2` varchar(64) NOT NULL DEFAULT '',
+ `col3` int(20) NOT NULL,
+ `col4` int(40) NOT NULL,
+ primary key (`id`, `col1`, `col2`, `col3`, `col4`),
+ key col1(col1),
+ key col2(col2),
+ key col3(col3),
+ key col4(col4))
+ ENGINE="FEDERATED"
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (1, 'one One', 11, 1111);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (2, 'Two two', 22, 2222);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (3, 'three Three', 33, 33333);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (4, 'fourfourfour', 444, 4444444);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (5, 'five 5 five five 5', 5, 55555);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (6, 'six six Sixsix', 6666, 6);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (7, 'seven Sevenseven', 77777, 7777);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (8, 'eight eight eight', 88888, 88);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (9, 'nine Nine', 999999, 999999);
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES (10, 'Tenth ten TEN', 1010101, 1010);
+
+SELECT * FROM federated.t1 WHERE col2 = 'two two';
+SELECT * FROM federated.t1 WHERE col2 = 'two Two';
+SELECT * FROM federated.t1 WHERE id = 3;
+SELECT * FROM federated.t1 WHERE id = 3 AND col1 = 3;
+SELECT * FROM federated.t1 WHERE id = 4 AND col1 = 4 AND col2 = 'Two two';
+SELECT * FROM federated.t1 WHERE id = 4 AND col1 = 4 AND col2 = 'fourfourfour';
+SELECT * FROM federated.t1 WHERE id = 5 AND col2 = 'five 5 five five 5'
+ AND col3 = 5;
+SELECT * FROM federated.t1 WHERE id = 5 AND col2 = 'five 5 five five 5'
+ AND col3 = 5
+ AND col4 = 55555;
+SELECT * FROM federated.t1 WHERE id = 5
+ AND col2 = 'Two two' AND col3 = 22
+ AND col4 = 33;
+SELECT * FROM federated.t1 WHERE id = 5
+ AND col2 = 'five 5 five five 5' AND col3 = 5
+ AND col4 = 55555;
+SELECT * FROM federated.t1 WHERE (id = 5 AND col2 = 'five 5 five five 5')
+ OR (col2 = 'three Three' AND col3 = 33);
+SELECT * FROM federated.t1 WHERE (id = 5 AND col2 = 'Two two')
+ OR (col2 = 444 AND col3 = 4444444);
+SELECT * FROM federated.t1 WHERE id = 1
+ OR col1 = 10
+ OR col2 = 'Two two'
+ OR col3 = 33
+ OR col4 = 4444444;
+SELECT * FROM federated.t1 WHERE id > 5;
+SELECT * FROM federated.t1 WHERE id >= 5;
+SELECT * FROM federated.t1 WHERE id < 5;
+SELECT * FROM federated.t1 WHERE id <= 5;
+SELECT * FROM federated.t1 WHERE id != 5;
+SELECT * FROM federated.t1 WHERE id > 3 AND id < 7;
+SELECT * FROM federated.t1 WHERE id > 3 AND id <= 7;
+SELECT * FROM federated.t1 WHERE id >= 3 AND id <= 7;
+SELECT * FROM federated.t1 WHERE id < 3 AND id <= 7;
+SELECT * FROM federated.t1 WHERE id < 3 AND id > 7;
+SELECT * FROM federated.t1 WHERE id < 3 OR id > 7;
+SELECT * FROM federated.t1 WHERE col2 = 'three Three';
+SELECT * FROM federated.t1 WHERE col2 > 'one';
+SELECT * FROM federated.t1 WHERE col2 LIKE 's%';
+SELECT * FROM federated.t1 WHERE col2 LIKE 'si%';
+SELECT * FROM federated.t1 WHERE col2 LIKE 'se%';
+SELECT * FROM federated.t1 WHERE col2 NOT LIKE 'e%';
+SELECT * FROM federated.t1 WHERE col2 <> 'one One';
+
+# more multi-column indexes, in the primary key
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `col1` varchar(8) NOT NULL DEFAULT '',
+ `col2` varchar(128) NOT NULL DEFAULT '',
+ `col3` varchar(20) NOT NULL DEFAULT '',
+ `col4` varchar(40) NOT NULL DEFAULT '',
+ primary key (`col1`, `col2`, `col3`, `col4`),
+ key 3key(`col2`,`col3`,`col4`),
+ key 2key (`col3`,`col4`),
+ key col4(col4));
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `col1` varchar(8) NOT NULL DEFAULT '',
+ `col2` varchar(128) NOT NULL DEFAULT '',
+ `col3` varchar(20) NOT NULL DEFAULT '',
+ `col4` varchar(40) NOT NULL DEFAULT '',
+ primary key (`col1`, `col2`, `col3`, `col4`),
+ key 3key(`col2`,`col3`,`col4`),
+ key 2key (`col3`,`col4`),
+ key col4(col4))
+ ENGINE="FEDERATED"
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES ('aaaa', 'aaaaaaaaaaaaaaaaaaa', 'ababababab', 'acacacacacacacac');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES ('bbbb', 'bbbbbbbbbbbbbbbbbbb', 'bababababa', 'bcbcbcbcbcbcbcbc');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES ('cccc', 'ccccccccccccccccccc', 'cacacacaca', 'cbcbcbcbcbcbcbcb');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES ('dddd', 'ddddddddddddddddddd', 'dadadadada', 'dcdcdcdcdcdcdcdc');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES ('eeee', 'eeeeeeeeeeeeeeeeeee', 'eaeaeaeaea', 'ecececececececec');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES ('ffff', 'fffffffffffffffffff', 'fafafafafa', 'fcfcfcfcfcfcfcfc');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES ('gggg', 'ggggggggggggggggggg', 'gagagagaga', 'gcgcgcgcgcgcgcgc');
+INSERT INTO federated.t1 (col1, col2, col3, col4)
+ VALUES ('hhhh', 'hhhhhhhhhhhhhhhhhhh', 'hahahahaha', 'hchchchchchchchc');
+
+SELECT * FROM federated.t1 WHERE col1 = 'cccc';
+SELECT * FROM federated.t1 WHERE col2 = 'eeeeeeeeeeeeeeeeeee';
+SELECT * FROM federated.t1 WHERE col3 = 'bababababa';
+SELECT * FROM federated.t1 WHERE col1 = 'gggg' AND col2 = 'ggggggggggggggggggg';
+SELECT * FROM federated.t1 WHERE col1 = 'gggg' AND col3 = 'gagagagaga';
+SELECT * FROM federated.t1 WHERE col1 = 'ffff' AND col4 = 'fcfcfcfcfcfcfcfc';
+SELECT * FROM federated.t1 WHERE col1 > 'bbbb';
+SELECT * FROM federated.t1 WHERE col1 >= 'bbbb';
+SELECT * FROM federated.t1 WHERE col1 < 'bbbb';
+SELECT * FROM federated.t1 WHERE col1 <= 'bbbb';
+SELECT * FROM federated.t1 WHERE col1 <> 'bbbb';
+SELECT * FROM federated.t1 WHERE col1 LIKE 'b%';
+SELECT * FROM federated.t1 WHERE col4 LIKE '%b%';
+SELECT * FROM federated.t1 WHERE col1 NOT LIKE 'c%';
+SELECT * FROM federated.t1 WHERE col4 NOT LIKE '%c%';
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `col1` varchar(8) NOT NULL DEFAULT '',
+ `col2` int(8) NOT NULL DEFAULT 0,
+ `col3` varchar(8) NOT NULL DEFAULT '',
+ primary key (`col1`, `col2`, `col3`));
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `col1` varchar(8) NOT NULL DEFAULT '',
+ `col2` varchar(8) NOT NULL DEFAULT '',
+ `col3` varchar(8) NOT NULL DEFAULT '',
+ primary key (`col1`, `col2`, `col3`))
+ ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 VALUES ('a00', '110', 'cc0');
+INSERT INTO federated.t1 VALUES ('aaa', '111', 'ccc');
+INSERT INTO federated.t1 VALUES ('bbb', '222', 'yyy');
+INSERT INTO federated.t1 VALUES ('ccc', '111', 'zzz');
+INSERT INTO federated.t1 VALUES ('ccd', '112', 'zzzz');
+
+# let's see what the foreign database says
+connection slave;
+SELECT col3 FROM federated.t1 WHERE (
+(col1 = 'aaa' AND col2 >= '111') OR col1 > 'aaa') AND
+(col1 < 'ccc' OR ( col1 = 'ccc' AND col2 <= '111'));
+
+connection master;
+SELECT col3 FROM federated.t1 WHERE (
+(col1 = 'aaa' AND col2 >= '111') OR col1 > 'aaa') AND
+(col1 < 'ccc' OR ( col1 = 'ccc' AND col2 <= '111'));
+
+# test NULLs
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int,
+ `name` varchar(32),
+ `floatval` float,
+ `other` int)
+DEFAULT CHARSET=latin1;
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int,
+ `name` varchar(32),
+ `floatval` float,
+ `other` int)
+ENGINE="FEDERATED"
+DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+# these both should be the same
+INSERT INTO federated.t1 values (NULL, NULL, NULL, NULL);
+INSERT INTO federated.t1 values ();
+INSERT INTO federated.t1 (id) VALUES (1);
+INSERT INTO federated.t1 (name, floatval, other)
+ VALUES ('foo', 33.33333332, NULL);
+INSERT INTO federated.t1 (name, floatval, other)
+ VALUES (0, 00.3333, NULL);
+SELECT * FROM federated.t1;
+SELECT count(*) FROM federated.t1
+WHERE id IS NULL
+AND name IS NULL
+AND floatval IS NULL
+AND other IS NULL;
+
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `blurb_id` int NOT NULL DEFAULT 0,
+ `blurb` text default '',
+ PRIMARY KEY (blurb_id))
+ DEFAULT CHARSET=latin1;
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `blurb_id` int NOT NULL DEFAULT 0,
+ `blurb` text default '',
+ PRIMARY KEY (blurb_id))
+ ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 VALUES (1, " MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values.");
+INSERT INTO federated.t1 VALUES (2, "All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE.");
+INSERT INTO federated.t1 VALUES (3, " A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. ");
+INSERT INTO federated.t1 VALUES(4, "Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:");
+SELECT * FROM federated.t1;
+
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `a` int NOT NULL,
+ `b` int NOT NULL,
+ `c` int NOT NULL,
+ PRIMARY KEY (a),key(b));
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `a` int NOT NULL,
+ `b` int NOT NULL,
+ `c` int NOT NULL,
+ PRIMARY KEY (a),
+ KEY (b))
+ ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 VALUES (3,3,3),(1,1,1),(2,2,2),(4,4,4);
+
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
+int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17
+int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
+i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34
+int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int,
+i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51
+int, i52 int, i53 int, i54 int, i55 int, i56 int, i57 int, i58 int, i59 int,
+i60 int, i61 int, i62 int, i63 int, i64 int, i65 int, i66 int, i67 int, i68
+int, i69 int, i70 int, i71 int, i72 int, i73 int, i74 int, i75 int, i76 int,
+i77 int, i78 int, i79 int, i80 int, i81 int, i82 int, i83 int, i84 int, i85
+int, i86 int, i87 int, i88 int, i89 int, i90 int, i91 int, i92 int, i93 int,
+i94 int, i95 int, i96 int, i97 int, i98 int, i99 int, i100 int, i101 int, i102
+int, i103 int, i104 int, i105 int, i106 int, i107 int, i108 int, i109 int, i110
+int, i111 int, i112 int, i113 int, i114 int, i115 int, i116 int, i117 int, i118
+int, i119 int, i120 int, i121 int, i122 int, i123 int, i124 int, i125 int, i126
+int, i127 int, i128 int, i129 int, i130 int, i131 int, i132 int, i133 int, i134
+int, i135 int, i136 int, i137 int, i138 int, i139 int, i140 int, i141 int, i142
+int, i143 int, i144 int, i145 int, i146 int, i147 int, i148 int, i149 int, i150
+int, i151 int, i152 int, i153 int, i154 int, i155 int, i156 int, i157 int, i158
+int, i159 int, i160 int, i161 int, i162 int, i163 int, i164 int, i165 int, i166
+int, i167 int, i168 int, i169 int, i170 int, i171 int, i172 int, i173 int, i174
+int, i175 int, i176 int, i177 int, i178 int, i179 int, i180 int, i181 int, i182
+int, i183 int, i184 int, i185 int, i186 int, i187 int, i188 int, i189 int, i190
+int, i191 int, i192 int, i193 int, i194 int, i195 int, i196 int, i197 int, i198
+int, i199 int, i200 int, i201 int, i202 int, i203 int, i204 int, i205 int, i206
+int, i207 int, i208 int, i209 int, i210 int, i211 int, i212 int, i213 int, i214
+int, i215 int, i216 int, i217 int, i218 int, i219 int, i220 int, i221 int, i222
+int, i223 int, i224 int, i225 int, i226 int, i227 int, i228 int, i229 int, i230
+int, i231 int, i232 int, i233 int, i234 int, i235 int, i236 int, i237 int, i238
+int, i239 int, i240 int, i241 int, i242 int, i243 int, i244 int, i245 int, i246
+int, i247 int, i248 int, i249 int, i250 int, i251 int, i252 int, i253 int, i254
+int, i255 int, i256 int, i257 int, i258 int, i259 int, i260 int, i261 int, i262
+int, i263 int, i264 int, i265 int, i266 int, i267 int, i268 int, i269 int, i270
+int, i271 int, i272 int, i273 int, i274 int, i275 int, i276 int, i277 int, i278
+int, i279 int, i280 int, i281 int, i282 int, i283 int, i284 int, i285 int, i286
+int, i287 int, i288 int, i289 int, i290 int, i291 int, i292 int, i293 int, i294
+int, i295 int, i296 int, i297 int, i298 int, i299 int, i300 int, i301 int, i302
+int, i303 int, i304 int, i305 int, i306 int, i307 int, i308 int, i309 int, i310
+int, i311 int, i312 int, i313 int, i314 int, i315 int, i316 int, i317 int, i318
+int, i319 int, i320 int, i321 int, i322 int, i323 int, i324 int, i325 int, i326
+int, i327 int, i328 int, i329 int, i330 int, i331 int, i332 int, i333 int, i334
+int, i335 int, i336 int, i337 int, i338 int, i339 int, i340 int, i341 int, i342
+int, i343 int, i344 int, i345 int, i346 int, i347 int, i348 int, i349 int, i350
+int, i351 int, i352 int, i353 int, i354 int, i355 int, i356 int, i357 int, i358
+int, i359 int, i360 int, i361 int, i362 int, i363 int, i364 int, i365 int, i366
+int, i367 int, i368 int, i369 int, i370 int, i371 int, i372 int, i373 int, i374
+int, i375 int, i376 int, i377 int, i378 int, i379 int, i380 int, i381 int, i382
+int, i383 int, i384 int, i385 int, i386 int, i387 int, i388 int, i389 int, i390
+int, i391 int, i392 int, i393 int, i394 int, i395 int, i396 int, i397 int, i398
+int, i399 int, i400 int, i401 int, i402 int, i403 int, i404 int, i405 int, i406
+int, i407 int, i408 int, i409 int, i410 int, i411 int, i412 int, i413 int, i414
+int, i415 int, i416 int, i417 int, i418 int, i419 int, i420 int, i421 int, i422
+int, i423 int, i424 int, i425 int, i426 int, i427 int, i428 int, i429 int, i430
+int, i431 int, i432 int, i433 int, i434 int, i435 int, i436 int, i437 int, i438
+int, i439 int, i440 int, i441 int, i442 int, i443 int, i444 int, i445 int, i446
+int, i447 int, i448 int, i449 int, i450 int, i451 int, i452 int, i453 int, i454
+int, i455 int, i456 int, i457 int, i458 int, i459 int, i460 int, i461 int, i462
+int, i463 int, i464 int, i465 int, i466 int, i467 int, i468 int, i469 int, i470
+int, i471 int, i472 int, i473 int, i474 int, i475 int, i476 int, i477 int, i478
+int, i479 int, i480 int, i481 int, i482 int, i483 int, i484 int, i485 int, i486
+int, i487 int, i488 int, i489 int, i490 int, i491 int, i492 int, i493 int, i494
+int, i495 int, i496 int, i497 int, i498 int, i499 int, i500 int, i501 int, i502
+int, i503 int, i504 int, i505 int, i506 int, i507 int, i508 int, i509 int, i510
+int, i511 int, i512 int, i513 int, i514 int, i515 int, i516 int, i517 int, i518
+int, i519 int, i520 int, i521 int, i522 int, i523 int, i524 int, i525 int, i526
+int, i527 int, i528 int, i529 int, i530 int, i531 int, i532 int, i533 int, i534
+int, i535 int, i536 int, i537 int, i538 int, i539 int, i540 int, i541 int, i542
+int, i543 int, i544 int, i545 int, i546 int, i547 int, i548 int, i549 int, i550
+int, i551 int, i552 int, i553 int, i554 int, i555 int, i556 int, i557 int, i558
+int, i559 int, i560 int, i561 int, i562 int, i563 int, i564 int, i565 int, i566
+int, i567 int, i568 int, i569 int, i570 int, i571 int, i572 int, i573 int, i574
+int, i575 int, i576 int, i577 int, i578 int, i579 int, i580 int, i581 int, i582
+int, i583 int, i584 int, i585 int, i586 int, i587 int, i588 int, i589 int, i590
+int, i591 int, i592 int, i593 int, i594 int, i595 int, i596 int, i597 int, i598
+int, i599 int, i600 int, i601 int, i602 int, i603 int, i604 int, i605 int, i606
+int, i607 int, i608 int, i609 int, i610 int, i611 int, i612 int, i613 int, i614
+int, i615 int, i616 int, i617 int, i618 int, i619 int, i620 int, i621 int, i622
+int, i623 int, i624 int, i625 int, i626 int, i627 int, i628 int, i629 int, i630
+int, i631 int, i632 int, i633 int, i634 int, i635 int, i636 int, i637 int, i638
+int, i639 int, i640 int, i641 int, i642 int, i643 int, i644 int, i645 int, i646
+int, i647 int, i648 int, i649 int, i650 int, i651 int, i652 int, i653 int, i654
+int, i655 int, i656 int, i657 int, i658 int, i659 int, i660 int, i661 int, i662
+int, i663 int, i664 int, i665 int, i666 int, i667 int, i668 int, i669 int, i670
+int, i671 int, i672 int, i673 int, i674 int, i675 int, i676 int, i677 int, i678
+int, i679 int, i680 int, i681 int, i682 int, i683 int, i684 int, i685 int, i686
+int, i687 int, i688 int, i689 int, i690 int, i691 int, i692 int, i693 int, i694
+int, i695 int, i696 int, i697 int, i698 int, i699 int, i700 int, i701 int, i702
+int, i703 int, i704 int, i705 int, i706 int, i707 int, i708 int, i709 int, i710
+int, i711 int, i712 int, i713 int, i714 int, i715 int, i716 int, i717 int, i718
+int, i719 int, i720 int, i721 int, i722 int, i723 int, i724 int, i725 int, i726
+int, i727 int, i728 int, i729 int, i730 int, i731 int, i732 int, i733 int, i734
+int, i735 int, i736 int, i737 int, i738 int, i739 int, i740 int, i741 int, i742
+int, i743 int, i744 int, i745 int, i746 int, i747 int, i748 int, i749 int, i750
+int, i751 int, i752 int, i753 int, i754 int, i755 int, i756 int, i757 int, i758
+int, i759 int, i760 int, i761 int, i762 int, i763 int, i764 int, i765 int, i766
+int, i767 int, i768 int, i769 int, i770 int, i771 int, i772 int, i773 int, i774
+int, i775 int, i776 int, i777 int, i778 int, i779 int, i780 int, i781 int, i782
+int, i783 int, i784 int, i785 int, i786 int, i787 int, i788 int, i789 int, i790
+int, i791 int, i792 int, i793 int, i794 int, i795 int, i796 int, i797 int, i798
+int, i799 int, i800 int, i801 int, i802 int, i803 int, i804 int, i805 int, i806
+int, i807 int, i808 int, i809 int, i810 int, i811 int, i812 int, i813 int, i814
+int, i815 int, i816 int, i817 int, i818 int, i819 int, i820 int, i821 int, i822
+int, i823 int, i824 int, i825 int, i826 int, i827 int, i828 int, i829 int, i830
+int, i831 int, i832 int, i833 int, i834 int, i835 int, i836 int, i837 int, i838
+int, i839 int, i840 int, i841 int, i842 int, i843 int, i844 int, i845 int, i846
+int, i847 int, i848 int, i849 int, i850 int, i851 int, i852 int, i853 int, i854
+int, i855 int, i856 int, i857 int, i858 int, i859 int, i860 int, i861 int, i862
+int, i863 int, i864 int, i865 int, i866 int, i867 int, i868 int, i869 int, i870
+int, i871 int, i872 int, i873 int, i874 int, i875 int, i876 int, i877 int, i878
+int, i879 int, i880 int, i881 int, i882 int, i883 int, i884 int, i885 int, i886
+int, i887 int, i888 int, i889 int, i890 int, i891 int, i892 int, i893 int, i894
+int, i895 int, i896 int, i897 int, i898 int, i899 int, i900 int, i901 int, i902
+int, i903 int, i904 int, i905 int, i906 int, i907 int, i908 int, i909 int, i910
+int, i911 int, i912 int, i913 int, i914 int, i915 int, i916 int, i917 int, i918
+int, i919 int, i920 int, i921 int, i922 int, i923 int, i924 int, i925 int, i926
+int, i927 int, i928 int, i929 int, i930 int, i931 int, i932 int, i933 int, i934
+int, i935 int, i936 int, i937 int, i938 int, i939 int, i940 int, i941 int, i942
+int, i943 int, i944 int, i945 int, i946 int, i947 int, i948 int, i949 int, i950
+int, i951 int, i952 int, i953 int, i954 int, i955 int, i956 int, i957 int, i958
+int, i959 int, i960 int, i961 int, i962 int, i963 int, i964 int, i965 int, i966
+int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974
+int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982
+int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990
+int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998
+int, i999 int, i1000 int, b varchar(256)) row_format=dynamic;
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1
+(i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
+int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int,
+i17 int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
+i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34
+int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int,
+i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51
+int, i52 int, i53 int, i54 int, i55 int, i56 int, i57 int, i58 int, i59 int,
+i60 int, i61 int, i62 int, i63 int, i64 int, i65 int, i66 int, i67 int, i68
+int, i69 int, i70 int, i71 int, i72 int, i73 int, i74 int, i75 int, i76 int,
+i77 int, i78 int, i79 int, i80 int, i81 int, i82 int, i83 int, i84 int, i85
+int, i86 int, i87 int, i88 int, i89 int, i90 int, i91 int, i92 int, i93 int,
+i94 int, i95 int, i96 int, i97 int, i98 int, i99 int, i100 int, i101 int, i102
+int, i103 int, i104 int, i105 int, i106 int, i107 int, i108 int, i109 int, i110
+int, i111 int, i112 int, i113 int, i114 int, i115 int, i116 int, i117 int, i118
+int, i119 int, i120 int, i121 int, i122 int, i123 int, i124 int, i125 int, i126
+int, i127 int, i128 int, i129 int, i130 int, i131 int, i132 int, i133 int, i134
+int, i135 int, i136 int, i137 int, i138 int, i139 int, i140 int, i141 int, i142
+int, i143 int, i144 int, i145 int, i146 int, i147 int, i148 int, i149 int, i150
+int, i151 int, i152 int, i153 int, i154 int, i155 int, i156 int, i157 int, i158
+int, i159 int, i160 int, i161 int, i162 int, i163 int, i164 int, i165 int, i166
+int, i167 int, i168 int, i169 int, i170 int, i171 int, i172 int, i173 int, i174
+int, i175 int, i176 int, i177 int, i178 int, i179 int, i180 int, i181 int, i182
+int, i183 int, i184 int, i185 int, i186 int, i187 int, i188 int, i189 int, i190
+int, i191 int, i192 int, i193 int, i194 int, i195 int, i196 int, i197 int, i198
+int, i199 int, i200 int, i201 int, i202 int, i203 int, i204 int, i205 int, i206
+int, i207 int, i208 int, i209 int, i210 int, i211 int, i212 int, i213 int, i214
+int, i215 int, i216 int, i217 int, i218 int, i219 int, i220 int, i221 int, i222
+int, i223 int, i224 int, i225 int, i226 int, i227 int, i228 int, i229 int, i230
+int, i231 int, i232 int, i233 int, i234 int, i235 int, i236 int, i237 int, i238
+int, i239 int, i240 int, i241 int, i242 int, i243 int, i244 int, i245 int, i246
+int, i247 int, i248 int, i249 int, i250 int, i251 int, i252 int, i253 int, i254
+int, i255 int, i256 int, i257 int, i258 int, i259 int, i260 int, i261 int, i262
+int, i263 int, i264 int, i265 int, i266 int, i267 int, i268 int, i269 int, i270
+int, i271 int, i272 int, i273 int, i274 int, i275 int, i276 int, i277 int, i278
+int, i279 int, i280 int, i281 int, i282 int, i283 int, i284 int, i285 int, i286
+int, i287 int, i288 int, i289 int, i290 int, i291 int, i292 int, i293 int, i294
+int, i295 int, i296 int, i297 int, i298 int, i299 int, i300 int, i301 int, i302
+int, i303 int, i304 int, i305 int, i306 int, i307 int, i308 int, i309 int, i310
+int, i311 int, i312 int, i313 int, i314 int, i315 int, i316 int, i317 int, i318
+int, i319 int, i320 int, i321 int, i322 int, i323 int, i324 int, i325 int, i326
+int, i327 int, i328 int, i329 int, i330 int, i331 int, i332 int, i333 int, i334
+int, i335 int, i336 int, i337 int, i338 int, i339 int, i340 int, i341 int, i342
+int, i343 int, i344 int, i345 int, i346 int, i347 int, i348 int, i349 int, i350
+int, i351 int, i352 int, i353 int, i354 int, i355 int, i356 int, i357 int, i358
+int, i359 int, i360 int, i361 int, i362 int, i363 int, i364 int, i365 int, i366
+int, i367 int, i368 int, i369 int, i370 int, i371 int, i372 int, i373 int, i374
+int, i375 int, i376 int, i377 int, i378 int, i379 int, i380 int, i381 int, i382
+int, i383 int, i384 int, i385 int, i386 int, i387 int, i388 int, i389 int, i390
+int, i391 int, i392 int, i393 int, i394 int, i395 int, i396 int, i397 int, i398
+int, i399 int, i400 int, i401 int, i402 int, i403 int, i404 int, i405 int, i406
+int, i407 int, i408 int, i409 int, i410 int, i411 int, i412 int, i413 int, i414
+int, i415 int, i416 int, i417 int, i418 int, i419 int, i420 int, i421 int, i422
+int, i423 int, i424 int, i425 int, i426 int, i427 int, i428 int, i429 int, i430
+int, i431 int, i432 int, i433 int, i434 int, i435 int, i436 int, i437 int, i438
+int, i439 int, i440 int, i441 int, i442 int, i443 int, i444 int, i445 int, i446
+int, i447 int, i448 int, i449 int, i450 int, i451 int, i452 int, i453 int, i454
+int, i455 int, i456 int, i457 int, i458 int, i459 int, i460 int, i461 int, i462
+int, i463 int, i464 int, i465 int, i466 int, i467 int, i468 int, i469 int, i470
+int, i471 int, i472 int, i473 int, i474 int, i475 int, i476 int, i477 int, i478
+int, i479 int, i480 int, i481 int, i482 int, i483 int, i484 int, i485 int, i486
+int, i487 int, i488 int, i489 int, i490 int, i491 int, i492 int, i493 int, i494
+int, i495 int, i496 int, i497 int, i498 int, i499 int, i500 int, i501 int, i502
+int, i503 int, i504 int, i505 int, i506 int, i507 int, i508 int, i509 int, i510
+int, i511 int, i512 int, i513 int, i514 int, i515 int, i516 int, i517 int, i518
+int, i519 int, i520 int, i521 int, i522 int, i523 int, i524 int, i525 int, i526
+int, i527 int, i528 int, i529 int, i530 int, i531 int, i532 int, i533 int, i534
+int, i535 int, i536 int, i537 int, i538 int, i539 int, i540 int, i541 int, i542
+int, i543 int, i544 int, i545 int, i546 int, i547 int, i548 int, i549 int, i550
+int, i551 int, i552 int, i553 int, i554 int, i555 int, i556 int, i557 int, i558
+int, i559 int, i560 int, i561 int, i562 int, i563 int, i564 int, i565 int, i566
+int, i567 int, i568 int, i569 int, i570 int, i571 int, i572 int, i573 int, i574
+int, i575 int, i576 int, i577 int, i578 int, i579 int, i580 int, i581 int, i582
+int, i583 int, i584 int, i585 int, i586 int, i587 int, i588 int, i589 int, i590
+int, i591 int, i592 int, i593 int, i594 int, i595 int, i596 int, i597 int, i598
+int, i599 int, i600 int, i601 int, i602 int, i603 int, i604 int, i605 int, i606
+int, i607 int, i608 int, i609 int, i610 int, i611 int, i612 int, i613 int, i614
+int, i615 int, i616 int, i617 int, i618 int, i619 int, i620 int, i621 int, i622
+int, i623 int, i624 int, i625 int, i626 int, i627 int, i628 int, i629 int, i630
+int, i631 int, i632 int, i633 int, i634 int, i635 int, i636 int, i637 int, i638
+int, i639 int, i640 int, i641 int, i642 int, i643 int, i644 int, i645 int, i646
+int, i647 int, i648 int, i649 int, i650 int, i651 int, i652 int, i653 int, i654
+int, i655 int, i656 int, i657 int, i658 int, i659 int, i660 int, i661 int, i662
+int, i663 int, i664 int, i665 int, i666 int, i667 int, i668 int, i669 int, i670
+int, i671 int, i672 int, i673 int, i674 int, i675 int, i676 int, i677 int, i678
+int, i679 int, i680 int, i681 int, i682 int, i683 int, i684 int, i685 int, i686
+int, i687 int, i688 int, i689 int, i690 int, i691 int, i692 int, i693 int, i694
+int, i695 int, i696 int, i697 int, i698 int, i699 int, i700 int, i701 int, i702
+int, i703 int, i704 int, i705 int, i706 int, i707 int, i708 int, i709 int, i710
+int, i711 int, i712 int, i713 int, i714 int, i715 int, i716 int, i717 int, i718
+int, i719 int, i720 int, i721 int, i722 int, i723 int, i724 int, i725 int, i726
+int, i727 int, i728 int, i729 int, i730 int, i731 int, i732 int, i733 int, i734
+int, i735 int, i736 int, i737 int, i738 int, i739 int, i740 int, i741 int, i742
+int, i743 int, i744 int, i745 int, i746 int, i747 int, i748 int, i749 int, i750
+int, i751 int, i752 int, i753 int, i754 int, i755 int, i756 int, i757 int, i758
+int, i759 int, i760 int, i761 int, i762 int, i763 int, i764 int, i765 int, i766
+int, i767 int, i768 int, i769 int, i770 int, i771 int, i772 int, i773 int, i774
+int, i775 int, i776 int, i777 int, i778 int, i779 int, i780 int, i781 int, i782
+int, i783 int, i784 int, i785 int, i786 int, i787 int, i788 int, i789 int, i790
+int, i791 int, i792 int, i793 int, i794 int, i795 int, i796 int, i797 int, i798
+int, i799 int, i800 int, i801 int, i802 int, i803 int, i804 int, i805 int, i806
+int, i807 int, i808 int, i809 int, i810 int, i811 int, i812 int, i813 int, i814
+int, i815 int, i816 int, i817 int, i818 int, i819 int, i820 int, i821 int, i822
+int, i823 int, i824 int, i825 int, i826 int, i827 int, i828 int, i829 int, i830
+int, i831 int, i832 int, i833 int, i834 int, i835 int, i836 int, i837 int, i838
+int, i839 int, i840 int, i841 int, i842 int, i843 int, i844 int, i845 int, i846
+int, i847 int, i848 int, i849 int, i850 int, i851 int, i852 int, i853 int, i854
+int, i855 int, i856 int, i857 int, i858 int, i859 int, i860 int, i861 int, i862
+int, i863 int, i864 int, i865 int, i866 int, i867 int, i868 int, i869 int, i870
+int, i871 int, i872 int, i873 int, i874 int, i875 int, i876 int, i877 int, i878
+int, i879 int, i880 int, i881 int, i882 int, i883 int, i884 int, i885 int, i886
+int, i887 int, i888 int, i889 int, i890 int, i891 int, i892 int, i893 int, i894
+int, i895 int, i896 int, i897 int, i898 int, i899 int, i900 int, i901 int, i902
+int, i903 int, i904 int, i905 int, i906 int, i907 int, i908 int, i909 int, i910
+int, i911 int, i912 int, i913 int, i914 int, i915 int, i916 int, i917 int, i918
+int, i919 int, i920 int, i921 int, i922 int, i923 int, i924 int, i925 int, i926
+int, i927 int, i928 int, i929 int, i930 int, i931 int, i932 int, i933 int, i934
+int, i935 int, i936 int, i937 int, i938 int, i939 int, i940 int, i941 int, i942
+int, i943 int, i944 int, i945 int, i946 int, i947 int, i948 int, i949 int, i950
+int, i951 int, i952 int, i953 int, i954 int, i955 int, i956 int, i957 int, i958
+int, i959 int, i960 int, i961 int, i962 int, i963 int, i964 int, i965 int, i966
+int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974
+int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982
+int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990
+int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998
+int, i999 int, i1000 int, b varchar(256))
+row_format=dynamic
+ENGINE="FEDERATED"
+DEFAULT CHARSET=latin1
+CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1
+values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "PatrickG");
+UPDATE federated.t1 SET b=repeat('a',256);
+UPDATE federated.t1 SET i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0, i10=0;
+SELECT * FROM federated.t1 WHERE i9=0 and i10=0;
+UPDATE federated.t1 SET i50=20;
+SELECT * FROM federated.t1;
+DELETE FROM federated.t1 WHERE i51=20;
+SELECT * FROM federated.t1;
+DELETE FROM federated.t1 WHERE i50=20;
+SELECT * FROM federated.t1;
+
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (id int NOT NULL auto_increment, code char(20) NOT NULL, fileguts blob NOT NULL, creation_date datetime, entered_time datetime default '2004-04-04 04:04:04', PRIMARY KEY(id), index(code), index(fileguts(10))) DEFAULT CHARSET=latin1;
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ id int NOT NULL auto_increment,
+ code char(20) NOT NULL,
+ fileguts blob NOT NULL,
+ creation_date datetime,
+ entered_time datetime default '2004-04-04 04:04:04',
+ PRIMARY KEY(id),
+ index(code),
+ index(fileguts(10)))
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('ASDFWERQWETWETAWETA', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#<S-F8>*<S-F8><S-F8><S-F8>#<S-F8>#<S-F8>#<S-F8>[[', '2003-03-03 03:03:03');
+INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#<S-F8>*<S-F8><S-F8><S-F8>#<S-F8>#<S-F8>#<S-F8>[[', '2004-04-04 04:04:04');
+INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', 'jimbob', '2004-04-04 04:04:04');
+SELECT * FROM federated.t1;
+# test blob indexes
+SELECT * FROM federated.t1 WHERE fileguts = 'jimbob';
+
+# test blob with binary
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (`a` BLOB);
+
+connection master;
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `a` BLOB)
+ENGINE="FEDERATED"
+CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 VALUES (0x00);
+INSERT INTO federated.t1 VALUES (0x0001);
+INSERT INTO federated.t1 VALUES (0x0100);
+SELECT HEX(a) FROM federated.t1;
+
+# # simple tests for cyrillic, given to me by
+# DROP TABLE IF EXISTS federated.t1;
+# --replace_result $SLAVE_MYPORT SLAVE_PORT
+# eval CREATE TABLE federated.t1
+# (a char(20)) charset=cp1251
+# ENGINE="FEDERATED" CONNECTION="mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1";
+# #
+# connection slave;
+# DROP TABLE IF EXISTS federated.t1;
+# CREATE TABLE federated.t1 (a char(20)) charset=cp1251;
+# #
+# connection master;
+# INSERT INTO federated.t1 values (_cp1251'À-ÁÂÃ-1');
+# INSERT INTO federated.t1 values (_cp1251'Á-ÂÃÄ-2');
+# SELECT * FROM federated.t1;
+# SET names cp1251;
+# INSERT INTO federated.t1 values ('Â-ÃÄÅ-3');
+# INSERT INTO federated.t1 values ('Ã-ŨÆ-4');
+# SELECT * FROM federated.t1;
+# SELECT hex(a) from federated.t1;
+# SELECT hex(a) from federated.t1 ORDER BY a desc;
+# UPDATE federated.t1 SET a='À-ÁÂÃ-1íîâûé' WHERE a='À-ÁÂÃ-1';
+# SELECT * FROM federated.t1;
+# DELETE FROM federated.t1 WHERE a='Ã-ŨÆ-4';
+# SELECT * FROM federated.t1;
+# DELETE FROM federated.t1 WHERE a>'Â-';
+# SELECT * FROM federated.t1;
+# SET names default;
+# DROP TABLE IF EXISTS federated.t1;
+
+#
+# DROP TABLE IF EXISTS federated.t1;
+#
+
+# test joins with non-federated table
+connection slave;
+DROP TABLE IF EXISTS federated.t1;
+CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `country_id` int(20) NOT NULL DEFAULT 0,
+ `name` varchar(32),
+ `other` varchar(20),
+ PRIMARY KEY (`id`),
+ key (country_id));
+
+connection master;
+DROP TABLE IF EXISTS federated.countries;
+CREATE TABLE federated.countries (
+ `id` int(20) NOT NULL auto_increment,
+ `country` varchar(32),
+ PRIMARY KEY (id));
+INSERT INTO federated.countries (country) VALUES ('India');
+INSERT INTO federated.countries (country) VALUES ('Germany');
+INSERT INTO federated.countries (country) VALUES ('Italy');
+INSERT INTO federated.countries (country) VALUES ('Finland');
+INSERT INTO federated.countries (country) VALUES ('Ukraine');
+
+DROP TABLE IF EXISTS federated.t1;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL auto_increment,
+ `country_id` int(20) NOT NULL DEFAULT 0,
+ `name` varchar(32),
+ `other` varchar(20),
+ PRIMARY KEY (`id`),
+ KEY (country_id) )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Kumar', 1, 11111);
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Lenz', 2, 22222);
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Marizio', 3, 33333);
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Monty', 4, 33333);
+INSERT INTO federated.t1 (name, country_id, other) VALUES ('Sanja', 5, 33333);
+
+#inner join
+SELECT federated.t1.name AS name, federated.t1.country_id AS country_id,
+federated.t1.other AS other, federated.countries.country AS country
+FROM federated.t1, federated.countries WHERE
+federated.t1.country_id = federated.countries.id;
+
+SELECT federated.t1.name AS name, federated.t1.country_id AS country_id,
+federated.t1.other AS other, federated.countries.country AS country
+FROM federated.t1 INNER JOIN federated.countries ON
+federated.t1.country_id = federated.countries.id;
+
+SELECT federated.t1.name AS name, federated.t1.country_id AS country_id,
+federated.t1.other AS other, federated.countries.country AS country
+FROM federated.t1 INNER JOIN federated.countries ON
+federated.t1.country_id = federated.countries.id
+WHERE federated.t1.name = 'Monty';
+
+#left join
+SELECT federated.t1.*, federated.countries.country
+FROM federated.t1 LEFT JOIN federated.countries
+ON federated.t1.country_id = federated.countries.id
+ORDER BY federated.countries.id;
+
+SELECT federated.t1.*, federated.countries.country
+FROM federated.t1 LEFT JOIN federated.countries
+ON federated.t1.country_id = federated.countries.id
+ORDER BY federated.countries.country;
+
+#right join
+SELECT federated.t1.*, federated.countries.country
+FROM federated.t1 RIGHT JOIN federated.countries
+ON federated.t1.country_id = federated.countries.id
+ORDER BY federated.t1.country_id;
+
+DROP TABLE federated.countries;
+
+# optimize and repair tests
+OPTIMIZE TABLE federated.t1;
+REPAIR TABLE federated.t1;
+REPAIR TABLE federated.t1 QUICK;
+REPAIR TABLE federated.t1 EXTENDED;
+REPAIR TABLE federated.t1 USE_FRM;
+
+source include/federated_cleanup.inc;
diff --git a/mysql-test/t/federated_archive.test b/mysql-test/t/federated_archive.test
new file mode 100644
index 00000000000..6d80664fef7
--- /dev/null
+++ b/mysql-test/t/federated_archive.test
@@ -0,0 +1,58 @@
+source include/have_archive.inc;
+source include/federated.inc;
+
+
+connection slave;
+--disable_warnings
+DROP TABLE IF EXISTS federated.archive_table;
+--enable_warnings
+
+CREATE TABLE federated.archive_table (
+ `id` int(4) NOT NULL,
+ `name` varchar(54) default NULL
+ ) ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
+
+
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS federated.t1;
+--enable_warnings
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `id` int(4) NOT NULL,
+ `name` varchar(54) default NULL,
+ PRIMARY KEY (`id`)
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/archive_table';
+
+INSERT INTO federated.t1 (id, name) VALUES (1, 'foo');
+INSERT INTO federated.t1 (id, name) VALUES (2, 'bar');
+
+SELECT * FROM federated.t1;
+
+--error 1296
+DELETE FROM federated.t1 WHERE id = 1;
+
+SELECT * FROM federated.t1;
+
+
+--error 1296
+UPDATE federated.t1 SET name='baz' WHERE id = 1;
+
+SELECT * FROM federated.t1;
+
+
+# --error 1296
+# TRUNCATE federated.t1;
+#
+# SELECT * from federated.t1;
+
+DROP TABLE federated.t1;
+connection slave;
+DROP TABLE federated.archive_table;
+
+
+source include/federated_cleanup.inc;
+
diff --git a/mysql-test/t/federated_bug_13118.test b/mysql-test/t/federated_bug_13118.test
new file mode 100644
index 00000000000..deec79becd2
--- /dev/null
+++ b/mysql-test/t/federated_bug_13118.test
@@ -0,0 +1,42 @@
+source include/federated.inc;
+
+
+connection slave;
+--disable_warnings
+DROP TABLE IF EXISTS federated.bug_13118_table;
+--enable_warnings
+
+CREATE TABLE federated.bug_13118_table (
+ `foo` integer,
+ `bar` integer
+ );
+
+
+connection master;
+--disable_warnings
+DROP TABLE IF EXISTS federated.t1;
+--enable_warnings
+
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval CREATE TABLE federated.t1 (
+ `foo` integer,
+ `bar` integer
+ ) ENGINE="FEDERATED"
+ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/bug_13118_table';
+
+SELECT * from federated.t1;
+
+INSERT INTO federated.t1 VALUES (1,1);
+SELECT * FROM federated.t1;
+
+INSERT INTO federated.t1 VALUES (1,1);
+SELECT * FROM federated.t1;
+
+
+DROP TABLE federated.t1;
+connection slave;
+DROP TABLE federated.bug_13118_table;
+
+
+source include/federated_cleanup.inc;
+
diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test
index aedf8e85b65..f5fd9fcadf2 100644
--- a/mysql-test/t/flush.test
+++ b/mysql-test/t/flush.test
@@ -37,7 +37,7 @@ connection con1;
select * from t1;
connection con2;
flush tables with read lock;
---error 1099
+--error 1223
drop table t2;
connection con1;
send drop table t2;
diff --git a/mysql-test/t/flush_block_commit.test b/mysql-test/t/flush_block_commit.test
index 1e7ecd2548c..ebb48242a4d 100644
--- a/mysql-test/t/flush_block_commit.test
+++ b/mysql-test/t/flush_block_commit.test
@@ -78,3 +78,24 @@ show create database test;
drop table t1;
# End of 4.1 tests
+
+# FLUSH TABLES WITH READ LOCK should block writes to binlog too
+connection con1;
+create table t1 (a int) engine=innodb;
+reset master;
+set autocommit=0;
+insert t1 values (1);
+connection con2;
+flush tables with read lock;
+show master status;
+connection con1;
+send commit;
+connection con2;
+sleep 1;
+show master status;
+unlock tables;
+connection con1;
+reap;
+drop table t1;
+set autocommit=1;
+
diff --git a/mysql-test/t/flush_read_lock_kill-master.opt b/mysql-test/t/flush_read_lock_kill-master.opt
new file mode 100644
index 00000000000..2b2b5eb5ebf
--- /dev/null
+++ b/mysql-test/t/flush_read_lock_kill-master.opt
@@ -0,0 +1 @@
+--loose-debug=d,make_global_read_lock_block_commit_loop
diff --git a/mysql-test/t/flush_read_lock_kill.test b/mysql-test/t/flush_read_lock_kill.test
new file mode 100644
index 00000000000..de2576300dc
--- /dev/null
+++ b/mysql-test/t/flush_read_lock_kill.test
@@ -0,0 +1,49 @@
+# Let's see if FLUSH TABLES WITH READ LOCK can be killed when waiting
+# for running commits to finish (in the past it could not)
+# This will not be a meaningful test on non-debug servers so will be
+# skipped.
+# If running mysql-test-run --debug, the --debug added by
+# mysql-test-run to the mysqld command line will override the one of
+# -master.opt. But this test is designed to still pass then (though it
+# won't test anything interesting).
+
+# This also won't work with the embedded server test
+-- source include/not_embedded.inc
+
+-- source include/have_debug.inc
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+connection con1;
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (kill_id int);
+insert into t1 values(connection_id());
+
+# Thanks to the parameter we passed to --debug, this FLUSH will
+# block on a debug build running with our --debug=make_global... It
+# will block until killed. In other cases (non-debug build or other
+# --debug) it will succeed immediately
+
+connection con1;
+send flush tables with read lock;
+
+# kill con1
+connection con2;
+select ((@id := kill_id) - kill_id) from t1;
+
+--sleep 2 # leave time for FLUSH to block
+kill connection @id;
+
+connection con1;
+# On debug builds it will be error 1053 (killed); on non-debug, or
+# debug build running without our --debug=make_global..., will be
+# error 0 (no error). The only important thing to test is that on
+# debug builds with our --debug=make_global... we don't hang forever.
+--error 0,1053
+reap;
+
+connection con2;
+drop table t1;
diff --git a/mysql-test/t/flush_table.test b/mysql-test/t/flush_table.test
index 0330582bc34..e46b67ad3d0 100644
--- a/mysql-test/t/flush_table.test
+++ b/mysql-test/t/flush_table.test
@@ -73,4 +73,11 @@ handler t1 read next limit 1;
handler t1 close;
drop table t1;
+#
+# Bug #11934 Two sequential FLUSH TABLES WITH READ LOCK hangs client
+#
+FLUSH TABLES WITH READ LOCK ;
+FLUSH TABLES WITH READ LOCK ;
+UNLOCK TABLES;
+
# End of 4.1 tests
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index fa63778c4c1..08648f4e0a6 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -59,6 +59,7 @@ select * from t1 where MATCH a,b AGAINST ("+call* +coll*" IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"support now"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE);
+select * from t1 where MATCH a,b AGAINST ('"now support"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"text search" "now support"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"text search" -"now support"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"text search" +"now support"' IN BOOLEAN MODE);
@@ -68,7 +69,6 @@ select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('+(support collections) +foobar*' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('+(+(support collections)) +foobar*' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('+collections -supp* -foobar*' IN BOOLEAN MODE);
-select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE);
# bug#2708, bug#3870 crash
@@ -128,14 +128,14 @@ WHERE ticket2.id = ttxt.ticket AND t1.id = ticket2.ticket and
match(ttxt.inhalt) against ('foobar');
# In the following query MySQL didn't use the fulltext index
-select t1.id FROM t2 as ttxt,t1 INNER JOIN t1 as ticket2 ON
-ticket2.id = ttxt.ticket
-WHERE t1.id = ticket2.ticket and match(ttxt.inhalt) against ('foobar');
+select ticket2.id FROM t2 as ttxt,t2 INNER JOIN t1 as ticket2 ON
+ticket2.id = t2.ticket
+WHERE ticket2.id = ticket2.ticket and match(ttxt.inhalt) against ('foobar');
INSERT INTO t1 VALUES (3,3);
-select t1.id FROM t2 as ttxt,t1
-INNER JOIN t1 as ticket2 ON ticket2.id = ttxt.ticket
-WHERE t1.id = ticket2.ticket and
+select ticket2.id FROM t2 as ttxt,t2
+INNER JOIN t1 as ticket2 ON ticket2.id = t2.ticket
+WHERE ticket2.id = ticket2.ticket and
match(ttxt.inhalt) against ('foobar');
# Check that we get 'fulltext' index in SHOW CREATE
diff --git a/mysql-test/t/fulltext_order_by.test b/mysql-test/t/fulltext_order_by.test
index da05fd494c4..074aefbf943 100644
--- a/mysql-test/t/fulltext_order_by.test
+++ b/mysql-test/t/fulltext_order_by.test
@@ -1,5 +1,5 @@
--disable_warnings
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1,t2,t3;
--enable_warnings
CREATE TABLE t1 (
@@ -80,7 +80,7 @@ CREATE TABLE t3 (
FULLTEXT KEY betreff (betreff)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ;
---error 1109
+--error 1054
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
@@ -100,7 +100,7 @@ group by
order by
match(b.betreff) against ('+abc' in boolean mode) desc;
---error 1109
+--error 1054
select a.text, b.id, b.betreff
from
t2 a inner join t3 b on a.id = b.forum inner join
diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test
index 6b85062b9fa..a78017ddb2f 100644
--- a/mysql-test/t/func_compress.test
+++ b/mysql-test/t/func_compress.test
@@ -2,6 +2,8 @@
#
# Test for compress and uncompress functions:
#
+# Note that this test gives error in the gzip library when running under
+# valgrind, but these warnings can be ignored
select @test_compress_string:='string for test compress function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ';
select length(@test_compress_string);
diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test
index 69ce10c83c9..37fc0e105b8 100644
--- a/mysql-test/t/func_concat.test
+++ b/mysql-test/t/func_concat.test
@@ -46,8 +46,10 @@ select 'a' union select concat('a', -'3');
select 'a' union select concat('a', -concat('3',4));
select 'a' union select concat('a', -0);
-
---replace_result 'a-0.0' good 'a0.0' good
+--replace_result a-0.0 a0.0
select 'a' union select concat('a', -0.0);
+--replace_result a-0.0000 a0.0000
+select 'a' union select concat('a', -0.0000);
+
# End of 4.1 tests
diff --git a/mysql-test/t/func_date_add.test b/mysql-test/t/func_date_add.test
index 5213395c35d..e01fce30577 100644
--- a/mysql-test/t/func_date_add.test
+++ b/mysql-test/t/func_date_add.test
@@ -11,7 +11,7 @@ CREATE TABLE t1 (
group_id int(10) unsigned DEFAULT '0' NOT NULL,
hits int(10) unsigned DEFAULT '0' NOT NULL,
sessions int(10) unsigned DEFAULT '0' NOT NULL,
- ts timestamp(14),
+ ts timestamp,
PRIMARY KEY (visitor_id,group_id)
)/*! engine=MyISAM */;
INSERT INTO t1 VALUES (465931136,7,2,2,20000318160952);
@@ -41,4 +41,27 @@ select visitor_id,max(ts) as mts from t1 group by visitor_id
having DATE_ADD(mts,INTERVAL 3 MONTH) < NOW();
drop table t1;
+#
+# Bug #10627: Invalid date turned to NULL from date_sub/date_add in
+# traditional mode
+#
+set sql_mode='traditional';
+create table t1 (d date);
+--error S22008
+insert into t1 (d) select date_sub('2000-01-01', INTERVAL 2001 YEAR);
+--error S22008
+insert into t1 (d) select date_add('2000-01-01',interval 8000 year);
+# No warnings/errors from the next two
+insert into t1 values (date_add(NULL, INTERVAL 1 DAY));
+insert into t1 values (date_add('2000-01-04', INTERVAL NULL DAY));
+set sql_mode='';
+# These will all work now, and we'll end up with some NULL entries in the
+# table and some warnings.
+insert into t1 (d) select date_sub('2000-01-01', INTERVAL 2001 YEAR);
+insert into t1 (d) select date_add('2000-01-01',interval 8000 year);
+insert into t1 values (date_add(NULL, INTERVAL 1 DAY));
+insert into t1 values (date_add('2000-01-04', INTERVAL NULL DAY));
+select * from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/func_default.test b/mysql-test/t/func_default.test
index 836511cc07a..7bebd4b4b72 100644
--- a/mysql-test/t/func_default.test
+++ b/mysql-test/t/func_default.test
@@ -19,3 +19,13 @@ explain select * from t1 where str <> default(str);
drop table t1;
# End of 4.1 tests
+
+#
+# Bug #11314 (HAVING DEFAULT() hangs)
+#
+CREATE TABLE t1 (id int(11), s varchar(20));
+INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
+--error 1364
+SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
+DROP TABLE t1;
+
diff --git a/mysql-test/t/func_equal.test b/mysql-test/t/func_equal.test
index 18d34e3ba16..4c88ed170a1 100644
--- a/mysql-test/t/func_equal.test
+++ b/mysql-test/t/func_equal.test
@@ -11,10 +11,12 @@ drop table if exists t1,t2;
# First some simple tests
#
-select 0<=>0,0.0<=>0.0,"A"<=>"A",NULL<=>NULL;
+select 0<=>0,0.0<=>0.0,0E0=0E0,"A"<=>"A",NULL<=>NULL;
select 1<=>0,0<=>NULL,NULL<=>0;
select 1.0<=>0.0,0.0<=>NULL,NULL<=>0.0;
select "A"<=>"B","A"<=>NULL,NULL<=>"A";
+select 0<=>0.0, 0.0<=>0E0, 0E0<=>"0", 10.0<=>1E1, 10<=>10.0, 10<=>1E1;
+select 1.0<=>0E1,10<=>NULL,NULL<=>0.0, NULL<=>0E0;
#
# Test with tables
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index eb1cbc3d667..a519d51e0b5 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -321,6 +321,13 @@ select a, group_concat(distinct b order by b) from t1 group by a with rollup;
drop table t1;
#
+# Bug #6475
+#
+create table t1 (a char(3), b char(20), primary key (a, b));
+insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
+select group_concat(a) from t1 group by b;
+drop table t1;
+#
# Bug #12095: GROUP_CONCAT for one row table
#
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 4dc8d66c4f1..fb9470c16dd 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -6,6 +6,9 @@
drop table if exists t1,t2;
--enable_warnings
+set @sav_dpi= @@div_precision_increment;
+set div_precision_increment= 5;
+show variables like 'div_precision_increment';
create table t1 (grp int, a bigint unsigned, c char(10) not null);
insert into t1 values (1,1,"a");
insert into t1 values (2,2,"b");
@@ -32,9 +35,7 @@ create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
# REPLACE ... SELECT doesn't yet work with PS
---disable_ps_protocol
replace into t2 select grp, a, c from t1 limit 2,1;
---enable_ps_protocol
select * from t2;
drop table t1,t2;
@@ -60,6 +61,11 @@ create table t2 (id int not null,rating int null);
insert into t1 values(1),(2),(3);
insert into t2 values(1, 3),(2, NULL),(2, NULL),(3, 2),(3, NULL);
select t1.id, avg(rating) from t1 left join t2 on ( t1.id = t2.id ) group by t1.id;
+# Test different types with avg()
+select sql_small_result t2.id, avg(rating) from t2 group by t2.id;
+select sql_big_result t2.id, avg(rating) from t2 group by t2.id;
+select sql_small_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
+select sql_big_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
drop table t1,t2;
#
@@ -216,6 +222,7 @@ insert into t1 values('GTM',3,'DAL',0.070,date'1977-09-23');
insert into t1 values('SSJ',null,'CHI',null,date'1974-03-19');
insert into t1 values('KKK',3,'ATL',null,null);
insert into t1 values('XXX',null,'MIN',null,null);
+insert into t1 values('WWW',1,'LED',null,null);
# Populate table t2
insert into t2 values('TKF','Seattle','WA','AME');
@@ -224,6 +231,7 @@ insert into t2 values('DEN','Denver','CO','BDL');
insert into t2 values('SDC','San Diego','CA','TWU');
insert into t2 values('NOL','New Orleans','LA','GTM');
insert into t2 values('LAK','Los Angeles','CA','TWU');
+insert into t2 values('AAA','AAA','AA','AME');
# Show the table contents
select * from t1;
@@ -390,8 +398,12 @@ create table t1 (a char character set latin2);
insert into t1 values ('a'),('b');
select charset(max(a)), coercibility(max(a)),
charset(min(a)), coercibility(min(a)) from t1;
+show create table t1;
create table t2 select max(a),min(a) from t1;
show create table t2;
+drop table t2;
+create table t2 select concat(a) from t1;
+show create table t2;
drop table t2,t1;
#
@@ -528,3 +540,95 @@ SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
DROP TABLE t1;
# End of 4.1 tests
+
+#
+# decimal-related tests
+#
+create table t2 (ff double);
+insert into t2 values (2.2);
+select cast(sum(distinct ff) as decimal(5,2)) from t2;
+select cast(sum(distinct ff) as signed) from t2;
+select cast(variance(ff) as decimal(10,3)) from t2;
+select cast(min(ff) as decimal(5,2)) from t2;
+
+create table t1 (df decimal(5,1));
+insert into t1 values(1.1);
+insert into t1 values(2.2);
+select cast(sum(distinct df) as signed) from t1;
+select cast(min(df) as signed) from t1;
+select 1e8 * sum(distinct df) from t1;
+select 1e8 * min(df) from t1;
+
+create table t3 (ifl int);
+insert into t3 values(1), (2);
+select cast(min(ifl) as decimal(5,2)) from t3;
+
+drop table t1, t2, t3;
+
+
+#
+# BUG#3190, WL#1639: Standard Deviation STDDEV - 2 different calculations
+#
+
+CREATE TABLE t1 (id int(11),value1 float(10,2));
+INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00), (2,13.00);
+select id, stddev_pop(value1), var_pop(value1), stddev_samp(value1), var_samp(value1) from t1 group by id;
+DROP TABLE t1;
+
+#
+# BUG#8464 decimal AVG returns incorrect result
+#
+
+CREATE TABLE t1 (col1 decimal(16,12));
+INSERT INTO t1 VALUES (-5.00000000001),(-5.00000000002),(-5.00000000003),(-5.00000000000),(-5.00000000001),(-5.00000000002);
+insert into t1 select * from t1;
+select col1,count(col1),sum(col1),avg(col1) from t1 group by col1;
+DROP TABLE t1;
+
+#
+# BUG#8465 decimal MIN and MAX return incorrect result
+#
+
+create table t1 (col1 decimal(16,12));
+insert into t1 values (-5.00000000001);
+insert into t1 values (-5.00000000001);
+select col1,sum(col1),max(col1),min(col1) from t1 group by col1;
+delete from t1;
+insert into t1 values (5.00000000001);
+insert into t1 values (5.00000000001);
+select col1,sum(col1),max(col1),min(col1) from t1 group by col1;
+DROP TABLE t1;
+
+#
+# Test that new VARCHAR correctly works with COUNT(DISTINCT)
+#
+
+CREATE TABLE t1 (a VARCHAR(400));
+INSERT INTO t1 (a) VALUES ("A"), ("a"), ("a "), ("a "),
+ ("B"), ("b"), ("b "), ("b ");
+SELECT COUNT(DISTINCT a) FROM t1;
+DROP TABLE t1;
+
+#
+# Test for buf #9210: GROUP BY with expression if a decimal type
+#
+
+CREATE TABLE t1 (a int, b int, c int);
+INSERT INTO t1 (a, b, c) VALUES
+ (1,1,1), (1,1,2), (1,1,3),
+ (1,2,1), (1,2,2), (1,2,3),
+ (1,3,1), (1,3,2), (1,3,3),
+ (2,1,1), (2,1,2), (2,1,3),
+ (2,2,1), (2,2,2), (2,2,3),
+ (2,3,1), (2,3,2), (2,3,3),
+ (3,1,1), (3,1,2), (3,1,3),
+ (3,2,1), (3,2,2), (3,2,3),
+ (3,3,1), (3,3,2), (3,3,3);
+
+SELECT b/c as v, a FROM t1 ORDER BY v;
+SELECT b/c as v, SUM(a) FROM t1 GROUP BY v;
+SELECT SUM(a) FROM t1 GROUP BY b/c;
+
+DROP TABLE t1;
+set div_precision_increment= @sav_dpi;
+
diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test
index 5756793c673..4e0f426c10b 100644
--- a/mysql-test/t/func_if.test
+++ b/mysql-test/t/func_if.test
@@ -25,9 +25,10 @@ explain extended select if(u=1,st,binary st) s from t1 where st like "%a%" order
#
# NULLIF test
#
-select nullif(u=0, 'test') from t1;
-explain extended select nullif(u=0, 'test') from t1;
+select nullif(u, 1) from t1;
+explain extended select nullif(u, 1) from t1;
drop table t1;
+select nullif(1,'test');
#
# Bug 2629
@@ -62,6 +63,20 @@ drop table t1;
SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL;
#
+# Bug #9669 Ordering on IF function with FROM_UNIXTIME function fails
+#
+CREATE TABLE `t1` (
+ `id` int(11) NOT NULL ,
+ `date` int(10) default NULL,
+ `text` varchar(32) NOT NULL
+);
+INSERT INTO t1 VALUES (1,1110000000,'Day 1'),(2,1111000000,'Day 2'),(3,1112000000,'Day 3');
+SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord ASC;
+SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord DESC;
+DROP TABLE t1;
+
+
+#
# Test for bug #11142: evaluation of NULLIF when the first argument is NULL
#
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index aec2de7a467..7bf737402ef 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -103,3 +103,21 @@ select * from t1 where a in (NULL, 'aa');
drop table t1;
# End of 4.1 tests
+
+#
+# Bug #11885: WHERE condition with NOT IN (one element)
+#
+
+CREATE TABLE t1 (a int PRIMARY KEY);
+INSERT INTO t1 VALUES (44), (45), (46);
+
+SELECT * FROM t1 WHERE a IN (45);
+SELECT * FROM t1 WHERE a NOT IN (0, 45);
+SELECT * FROM t1 WHERE a NOT IN (45);
+
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE a NOT IN (45);
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index c75454a96d4..633e36f51ab 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -54,6 +54,11 @@ SELECT ASIN(1.2-0.2);
#select floor(log(8)/log(2));
#select floor(log(16)/log(2));
+#
+# Bug #9060 (format returns incorrect result)
+#
+select format(4.55, 1), format(4.551, 1);
+
explain extended select degrees(pi()),radians(360);
#
@@ -63,6 +68,31 @@ explain extended select degrees(pi()),radians(360);
--error 1054
select rand(rand);
+# End of 4.1 tests
+
+#
+# Bug #8459 (FORMAT returns incorrect result)
+#
+create table t1 (col1 int, col2 decimal(60,30));
+insert into t1 values(1,1234567890.12345);
+select format(col2,7) from t1;
+select format(col2,8) from t1;
+insert into t1 values(7,1234567890123456.12345);
+select format(col2,6) from t1 where col1=7;
+drop table t1;
+
+
+#
+# Bug #10083 (round doesn't increase decimals)
+#
+select round(150, 2);
+
+#
+# Bug @10632 (Ceiling function returns wrong answer)
+#
+select ceil(0.09);
+select ceil(0.000000000000000009);
+
#
# Bug #9837: problem with round()
#
diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
index 72af9024070..4a618a56483 100644
--- a/mysql-test/t/func_misc.test
+++ b/mysql-test/t/func_misc.test
@@ -39,3 +39,42 @@ select a from t1 where mid(a+0,6,3) = ( mid(20040106123400,6,3) );
drop table t1;
# End of 4.1 tests
+
+#
+# Test for BUG#9535
+#
+create table t1 as select uuid(), length(uuid());
+show create table t1;
+drop table t1;
+
+# Bug #6760: Add SLEEP() function
+create table t1 (a timestamp default '2005-05-05 01:01:01',
+ b timestamp default '2005-05-05 01:01:01');
+insert into t1 set a = now();
+select sleep(3);
+update t1 set b = now();
+select timediff(b, a) >= '00:00:03' from t1;
+drop table t1;
+
+#
+# Bug #12689: SLEEP() gets incorrectly cached/optimized-away
+#
+set global query_cache_size=1355776;
+create table t1 (a int);
+insert into t1 values (1),(1),(1);
+create table t2 (a datetime default null, b datetime default null);
+insert into t2 set a = now();
+select a from t1 where sleep(1);
+update t2 set b = now() where b is null;
+insert into t2 set a = now();
+select a from t1 where sleep(a);
+update t2 set b = now() where b is null;
+insert into t2 set a = now();
+select a from t1 where sleep(1);
+update t2 set b = now() where b is null;
+select timediff(b, a) >= '00:00:03' from t2;
+drop table t2;
+drop table t1;
+set global query_cache_size=default;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index 8fd793f067b..6189712b5fe 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -30,10 +30,16 @@ select adddate("1997-12-31 23:59:59.000001", 10);
select subdate("1997-12-31 23:59:59.000001", 10);
select datediff("1997-12-31 23:59:59.000001","1997-12-30");
+select datediff("1997-11-30 23:59:59.000001","1997-12-31");
+SET @@SQL_MODE="ALLOW_INVALID_DATES";
select datediff("1997-11-31 23:59:59.000001","1997-12-31");
-select datediff("1997-11-31 23:59:59.000001",null);
+SET @@SQL_MODE="";
-select weekofyear("1997-11-31 23:59:59.000001");
+-- This will give a warning
+select datediff("1997-11-31 23:59:59.000001","1997-12-31");
+select datediff("1997-11-30 23:59:59.000001",null);
+
+select weekofyear("1997-11-30 23:59:59.000001");
select makedate(1997,1);
select makedate(1997,0);
@@ -108,7 +114,8 @@ insert into test values
SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test;
# PS doesn't support fractional seconds
--disable_ps_protocol
-SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
+SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq,
+ TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test;
--enable_ps_protocol
drop table t1, test;
diff --git a/mysql-test/t/func_set.test b/mysql-test/t/func_set.test
index c003826ff5a..710b9b90a05 100644
--- a/mysql-test/t/func_set.test
+++ b/mysql-test/t/func_set.test
@@ -18,6 +18,8 @@ select export_set(9,"Y","N","-",5),export_set(9,"Y","N"),export_set(9,"Y","N",""
# Wrong usage of functions
#
select elt(2,1),field(NULL,"a","b","c");
+select field("b","a",NULL),field(1,0,NULL)+0,field(1.0,0.0,NULL)+0.0,field(1.0e1,0.0e1,NULL)+0.0e1;
+select field(NULL,"a",NULL),field(NULL,0,NULL)+0,field(NULL,0.0,NULL)+0.0,field(NULL,0.0e1,NULL)+0.0e1;
select find_in_set("","a,b,c"),find_in_set("","a,b,c,"),find_in_set("",",a,b,c");
select find_in_set("abc","abc"),find_in_set("ab","abc"),find_in_set("abcd","abc");
select interval(null, 1, 10, 100);
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 8afbe673ce3..4a6c98c8d7f 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -3,7 +3,7 @@
# Testing string functions
--disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2;
--enable_warnings
set names latin1;
@@ -64,6 +64,7 @@ select substring_index('the king of the the hill','the',2);
select substring_index('the king of the the hill','the',3);
select concat(':',ltrim(' left '),':',rtrim(' right '),':');
+select concat(':',trim(leading from ' left '),':',trim(trailing from ' right '),':');
select concat(':',trim(LEADING FROM ' left'),':',trim(TRAILING FROM ' right '),':');
select concat(':',trim(' m '),':',trim(BOTH FROM ' y '),':',trim('*' FROM '*s*'),':');
select concat(':',trim(BOTH 'ab' FROM 'ababmyabab'),':',trim(BOTH '*' FROM '***sql'),':');
@@ -166,7 +167,7 @@ CREATE TABLE t1 (
program int(10) unsigned default NULL,
bugdesc text,
created datetime default NULL,
- modified timestamp(14) NOT NULL,
+ modified timestamp NOT NULL,
bugstatus int(10) unsigned default NULL,
submitter int(10) unsigned default NULL
) ENGINE=MyISAM;
@@ -282,7 +283,7 @@ select FIELD('b','A' COLLATE latin1_bin,'B');
select FIELD(_latin2'b','A','B');
--error 1270
select FIELD('b',_latin2'A','B');
-select FIELD('b',_latin2'A','B',1);
+select FIELD('1',_latin2'3','2',1);
select POSITION(_latin1'B' IN _latin1'abcd');
select POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin);
@@ -511,6 +512,8 @@ drop table t1;
#
select trim(null from 'kate') as "must_be_null";
select trim('xyz' from null) as "must_be_null";
+select trim(leading NULL from 'kate') as "must_be_null";
+select trim(trailing NULL from 'xyz') as "must_be_null";
#
# Bug #7751 - conversion for a bigint unsigned constant
@@ -560,7 +563,6 @@ SELECT t1.id, aes_decrypt(str, 'bar') FROM t1, t2 WHERE t1.id = t2.id
DROP TABLE t1, t2;
-
#
# Bug #10944: Mishandling of NULL arguments in FIELD()
#
diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test
index 2ad64b6c5a6..f2ff47704c9 100644
--- a/mysql-test/t/func_test.test
+++ b/mysql-test/t/func_test.test
@@ -109,3 +109,21 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
# End of 4.1 tests
+
+#
+# Bug#6726: NOT BETWEEN parse failure
+#
+create table t1 (a int, b int);
+insert into t1 values (1,2), (2,3), (3,4), (4,5);
+select * from t1 where a not between 1 and 2;
+select * from t1 where a not between 1 and 2 and b not between 3 and 4;
+drop table t1;
+
+#
+# Test for bug #12791: one of the arguments of LEAST/GREATEST is NULL
+#
+
+SELECT GREATEST(1,NULL) FROM DUAL;
+SELECT LEAST('xxx','aaa',NULL,'yyy') FROM DUAL;
+SELECT LEAST(1.1,1.2,NULL,1.0) FROM DUAL;
+SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL;
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 68a33afd85c..3dd7f7276fb 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -211,7 +211,7 @@ drop table t1;
CREATE TABLE t1 ( start datetime default NULL);
INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00');
-CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL);
+CREATE TABLE t2 ( ctime1 timestamp NOT NULL, ctime2 timestamp NOT NULL);
INSERT INTO t2 VALUES (20021029165106,20021105164731);
CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
@@ -266,6 +266,33 @@ 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;
+select timestampadd(WEEK, 1, date) from t1;
+select timestampadd(SQL_TSI_SECOND, 1, date) from t1;
+# Prepared statements doesn't support FRAC_SECOND yet
+--disable_ps_protocol
+select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1;
+--enable_ps_protocol
+
+select timestampdiff(MONTH, '2001-02-01', '2001-05-01') as a;
+select timestampdiff(YEAR, '2002-05-01', '2001-01-01') as a;
+select timestampdiff(QUARTER, '2002-05-01', '2001-01-01') as a;
+select timestampdiff(MONTH, '2000-03-28', '2000-02-29') as a;
+select timestampdiff(MONTH, '1991-03-28', '2000-02-29') as a;
+select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a;
+select timestampdiff(SQL_TSI_HOUR, '2001-02-01', '2001-05-01') as a;
+select timestampdiff(SQL_TSI_DAY, '2001-02-01', '2001-05-01') as a;
+select timestampdiff(SQL_TSI_MINUTE, '2001-02-01 12:59:59', '2001-05-01 12:58:59') as a;
+select timestampdiff(SQL_TSI_SECOND, '2001-02-01 12:59:59', '2001-05-01 12:58:58') as a;
+select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a;
+
+select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1,
+ timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2,
+ timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3,
+ timestampdiff(SQL_TSI_DAY, '2000-02-01', '2000-03-01') as a4;
+
select date_add(time,INTERVAL 1 SECOND) from t1;
drop table t1;
@@ -307,6 +334,12 @@ INSERT INTO t1 VALUES (NOW());
SELECT count(*) FROM t1 WHERE d>FROM_DAYS(TO_DAYS(@TMP)) AND d<=FROM_DAYS(TO_DAYS(@TMP)+1);
DROP TABLE t1;
+
+# End of 4.1 tests
+
+explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,
+ timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2;
+
#
# Bug #10568
#
@@ -315,4 +348,60 @@ select last_day('2005-00-00');
select last_day('2005-00-01');
select last_day('2005-01-00');
-# End of 4.1 tests
+#
+# Bug #10590: %h, %I, and %l format specifies should all return results in
+# the 0-11 range
+#
+select time_format('100:00:00', '%H %k %h %I %l');
+
+#
+# Bug #12562: Make SYSDATE behave like it does in Oracle: always the current
+# time, regardless of magic to make NOW() always the same for the
+# entirety of a statement.
+create table t1 (a timestamp default '2005-05-05 01:01:01',
+ b timestamp default '2005-05-05 01:01:01');
+delimiter //;
+create function t_slow_sysdate() returns timestamp
+begin
+ do sleep(2);
+ return sysdate();
+end;
+//
+
+insert into t1 set a = sysdate(), b = t_slow_sysdate();//
+
+create trigger t_before before insert on t1
+for each row begin
+ set new.b = t_slow_sysdate();
+end
+//
+
+delimiter ;//
+
+insert into t1 set a = sysdate();
+
+select a != b from t1;
+
+drop trigger t_before;
+drop function t_slow_sysdate;
+drop table t1;
+
+create table t1 (a datetime, i int, b datetime);
+insert into t1 select sysdate(), sleep(1), sysdate() from dual;
+select a != b from t1;
+drop table t1;
+
+delimiter //;
+create procedure t_sysdate()
+begin
+ select sysdate() into @a;
+ do sleep(2);
+ select sysdate() into @b;
+ select @a != @b;
+end;
+//
+delimiter ;//
+call t_sysdate();
+drop procedure t_sysdate;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test
index 682f67c61c4..02e45861706 100644
--- a/mysql-test/t/gis-rtree.test
+++ b/mysql-test/t/gis-rtree.test
@@ -120,7 +120,6 @@ INSERT INTO t1 (g) VALUES (GeomFromText('LineString(1 2, 2 3)')),(GeomFromText('
drop table t1;
CREATE TABLE t1 (
- geoobjid INT NOT NULL,
line LINESTRING NOT NULL,
kind ENUM('po', 'pp', 'rr', 'dr', 'rd', 'ts', 'cl') NOT NULL DEFAULT 'po',
name VARCHAR(32),
@@ -169,7 +168,7 @@ drop table t1;
CREATE TABLE t1 (st varchar(100));
INSERT INTO t1 VALUES ("Fake string");
CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
---error 1105
+--error 1416
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
drop table t1, t2;
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index b204bc11e2f..aba2f33833a 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -165,9 +165,9 @@ explain extended select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimpl
create table t1 (a geometry not null);
insert into t1 values (GeomFromText('Point(1 2)'));
--- error 1105
+-- error 1416
insert into t1 values ('Garbage');
--- error 1105
+-- error 1416
insert IGNORE into t1 values ('Garbage');
alter table t1 add spatial index(a);
@@ -360,4 +360,38 @@ t1 where object_id=85984;
drop table t1;
+create table t1 (fl geometry);
+--error 1416
+insert into t1 values (1);
+--error 1416
+insert into t1 values (1.11);
+--error 1416
+insert into t1 values ("qwerty");
+--error 1416
+insert into t1 values (pointfromtext('point(1,1)'));
+
+drop table t1;
+
# End of 4.1 tests
+
+#
+# Bug #12281 (Geometry: crash in trigger)
+#
+
+create table t1 (s1 geometry not null,s2 char(100));
+create trigger t1_bu before update on t1 for each row set new.s1 = null;
+--error 1048
+insert into t1 values (null,null);
+drop table t1;
+
+#
+# Bug #10499 (function creation with GEOMETRY datatype)
+#
+--disable_warnings
+drop procedure if exists fn3;
+--enable_warnings
+create function fn3 () returns point return GeomFromText("point(1 1)");
+show create function fn3;
+select astext(fn3());
+drop function fn3;
+
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index b0de62e679c..635c7a3f4e7 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -6,6 +6,7 @@
# Cleanup
--disable_warnings
drop table if exists t1;
+drop database if exists mysqltest;
--enable_warnings
connect (master,localhost,root,,);
@@ -184,16 +185,18 @@ grant select(a) on test.t1 to drop_user1@localhost;
grant select on test.t1 to drop_user2@localhost;
grant select on test.* to drop_user3@localhost;
grant select on *.* to drop_user4@localhost;
---error 1268
+# Drop user now implicitly revokes all privileges.
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
+--error 1269
revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
drop_user3@localhost, drop_user4@localhost;
+--error 1396
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
drop table t1;
grant usage on *.* to mysqltest_1@localhost identified by "password";
-grant select, update, insert on test.* to mysqltest@localhost;
+grant select, update, insert on test.* to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
drop user mysqltest_1@localhost;
@@ -217,6 +220,9 @@ GRANT SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ TO ÀÚÅÒ@localhost;
SHOW GRANTS FOR ÀÚÅÒ@localhost;
REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost;
+# Revoke does not drop user. Leave a clean user table for the next tests.
+DROP USER ÀÚÅÒ@localhost;
+
DROP DATABASE ÂÄ;
SET NAMES latin1;
@@ -324,8 +330,10 @@ show grants for mysqltest_3@localhost;
--error 1143
update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
--error 1143
+update mysqltest_1.t2, mysqltest_2.t2 set d=20 where d=1;
+--error 1142
update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1;
---error 1143
+--error 1142
update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1;
--error 1143
update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2;
@@ -350,15 +358,15 @@ connection conn2;
use mysqltest_1;
update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600;
# the following failed before, should fail now.
---error 1143
+--error 1142
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
use mysqltest_2;
#the following used to succeed, it must fail now.
---error 1044
+--error 1142
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
---error 1044
+--error 1142
update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200;
---error 1044
+--error 1142
update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200;
#lets see the result
connection master;
@@ -374,6 +382,11 @@ drop database mysqltest_1;
drop database mysqltest_2;
#
+# just SHOW PRIVILEGES test
+#
+SHOW PRIVILEGES;
+
+#
# Rights for renaming test (Bug #3270)
#
connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
@@ -393,6 +406,71 @@ delete from mysql.user where user=_binary'mysqltest_1';
drop database mysqltest;
#
+# check all new table priveleges
+#
+CREATE USER dummy@localhost;
+CREATE DATABASE mysqltest;
+CREATE TABLE mysqltest.dummytable (dummyfield INT);
+CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable;
+GRANT ALL PRIVILEGES ON mysqltest.dummytable TO dummy@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.dummyview TO dummy@localhost;
+SHOW GRANTS FOR dummy@localhost;
+use INFORMATION_SCHEMA;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+FLUSH PRIVILEGES;
+SHOW GRANTS FOR dummy@localhost;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+SHOW FIELDS FROM mysql.tables_priv;
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
+DROP USER dummy@localhost;
+DROP DATABASE mysqltest;
+# check view only privileges
+CREATE USER dummy@localhost;
+CREATE DATABASE mysqltest;
+CREATE TABLE mysqltest.dummytable (dummyfield INT);
+CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable;
+GRANT CREATE VIEW ON mysqltest.dummytable TO dummy@localhost;
+GRANT CREATE VIEW ON mysqltest.dummyview TO dummy@localhost;
+SHOW GRANTS FOR dummy@localhost;
+use INFORMATION_SCHEMA;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+FLUSH PRIVILEGES;
+SHOW GRANTS FOR dummy@localhost;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
+DROP USER dummy@localhost;
+DROP DATABASE mysqltest;
+CREATE USER dummy@localhost;
+CREATE DATABASE mysqltest;
+CREATE TABLE mysqltest.dummytable (dummyfield INT);
+CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable;
+GRANT SHOW VIEW ON mysqltest.dummytable TO dummy@localhost;
+GRANT SHOW VIEW ON mysqltest.dummyview TO dummy@localhost;
+SHOW GRANTS FOR dummy@localhost;
+use INFORMATION_SCHEMA;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+FLUSH PRIVILEGES;
+SHOW GRANTS FOR dummy@localhost;
+SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY
+PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE
+= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME;
+use test;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost;
+DROP USER dummy@localhost;
+DROP DATABASE mysqltest;
+#
# Bug #11330: Entry in tables_priv with host = '' causes crash
#
connection default;
diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test
index cb00c41a0ca..2fa82ce5dce 100644
--- a/mysql-test/t/grant2.test
+++ b/mysql-test/t/grant2.test
@@ -21,17 +21,61 @@ delete from mysql.columns_priv where user like 'mysqltest\_%';
flush privileges;
+grant all privileges on `my\_1`.* to mysqltest_1@localhost with grant option;
+grant create user on *.* to mysqltest_1@localhost;
+create user mysqltest_2@localhost;
+connect (user_a,localhost,mysqltest_1,,);
+connection user_a;
+grant select on `my\_1`.* to mysqltest_2@localhost;
+--error 1132
+grant select on `my\_1`.* to mysqltest_2@localhost identified by 'pass';
+disconnect user_a;
+connection default;
+grant update on mysql.* to mysqltest_1@localhost;
+connect (user_b,localhost,mysqltest_1,,);
+connection user_b;
+grant select on `my\_1`.* to mysqltest_2@localhost identified by 'pass';
+grant select on `my\_1`.* to mysqltest_3@localhost;
+disconnect user_b;
+connection default;
+grant insert on mysql.* to mysqltest_1@localhost;
+connect (user_c,localhost,mysqltest_1,,);
+connection user_c;
+grant select on `my\_1`.* to mysqltest_3@localhost;
+grant select on `my\_1`.* to mysqltest_4@localhost identified by 'pass';
+disconnect user_c;
+connection default;
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
+
#
# wild_compare fun
#
grant all privileges on `my\_%`.* to mysqltest_1@localhost with grant option;
+grant create user on *.* to mysqltest_1@localhost;
connect (user1,localhost,mysqltest_1,,);
connection user1;
select current_user();
grant all privileges on `my\_1`.* to mysqltest_2@localhost with grant option;
--error 1044
grant all privileges on `my_%`.* to mysqltest_3@localhost with grant option;
+
+#
+# NO_AUTO_CREATE_USER mode
+#
+set @@sql_mode='NO_AUTO_CREATE_USER';
+select @@sql_mode;
+#
+# GRANT without IDENTIFIED BY does not create new users
+#
+--error 1133
+grant select on `my\_1`.* to mysqltest_4@localhost with grant option;
+grant select on `my\_1`.* to mysqltest_4@localhost identified by 'mypass'
+with grant option;
disconnect user1;
connection default;
show grants for mysqltest_1@localhost;
@@ -75,10 +119,10 @@ connect (mrbad, localhost, mysqltest_1,,mysqltest);
connection mrbad;
show grants for current_user();
insert into t1 values (1, 'I can''t change it!');
---error 1044
+--error 1142
update t1 set data='I can change it!' where id = 1;
# This should not be allowed since it too require UPDATE privilege.
---error 1044
+--error 1142
insert into t1 values (1, 'XXX') on duplicate key update data= 'I can change it!';
select * from t1;
disconnect mrbad;
@@ -88,7 +132,8 @@ drop table t1;
delete from mysql.user where user like 'mysqltest\_%';
delete from mysql.db where user like 'mysqltest\_%';
flush privileges;
-
+#
+#
create table t1 (a int, b int);
grant select (a) on t1 to mysqltest_1@localhost with grant option;
connect (mrugly, localhost, mysqltest_1,,mysqltest);
@@ -110,7 +155,150 @@ flush privileges;
drop database mysqltest;
use test;
+#
+# Create and drop user
+#
+set sql_mode='maxdb';
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1(c1 int);
+create table t2(c1 int, c2 int);
+#
+# Three forms of CREATE USER
+create user 'mysqltest_1';
+--error 1396
+create user 'mysqltest_1';
+create user 'mysqltest_2' identified by 'Mysqltest-2';
+create user 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff';
+grant select on *.* to 'mysqltest_2';
+grant insert on test.* to 'mysqltest_2';
+grant update on test.t1 to 'mysqltest_2';
+grant update (c2) on test.t2 to 'mysqltest_2';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+show grants for 'mysqltest_1';
+show grants for 'mysqltest_2';
+#
+# Drop
+drop user 'mysqltest_1';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+--error 1141
+show grants for 'mysqltest_1';
+#
+# Rename
+rename user 'mysqltest_2' to 'mysqltest_1';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+show grants for 'mysqltest_1';
+drop user 'mysqltest_1', 'mysqltest_3';
+--error 1396
+drop user 'mysqltest_1';
+#
+# Cleanup
+drop table t1, t2;
+#
+# Add a stray record
+insert into mysql.db set user='mysqltest_1', db='%', host='%';
+flush privileges;
+--error 1141
+show grants for 'mysqltest_1';
+--error 1269
+revoke all privileges, grant option from 'mysqltest_1';
+drop user 'mysqltest_1';
+select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user;
+#
+# Add a stray record
+insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1';
+flush privileges;
+--error 1141
+show grants for 'mysqltest_1';
+drop user 'mysqltest_1';
+select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name;
+#
+# Add a stray record
+insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1';
+flush privileges;
+--error 1141
+show grants for 'mysqltest_1';
+drop user 'mysqltest_1';
+select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name;
+#
+# Handle multi user lists
+create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+create user 'mysqltest_1', 'mysqltest_2' identified by 'Mysqltest-2', 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff';
+rename user 'mysqltest_1' to 'mysqltest_1a', 'mysqltest_2' TO 'mysqltest_2a', 'mysqltest_3' TO 'mysqltest_3a';
+--error 1396
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+drop user 'mysqltest_1a', 'mysqltest_2a', 'mysqltest_3a';
+#
+# Let one of multiple users fail
+create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+--error 1396
+create user 'mysqltest_1a', 'mysqltest_2', 'mysqltest_3a';
+--error 1396
+rename user 'mysqltest_1a' to 'mysqltest_1b', 'mysqltest_2a' TO 'mysqltest_2b', 'mysqltest_3a' TO 'mysqltest_3b';
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+--error 1396
+drop user 'mysqltest_1b', 'mysqltest_2b', 'mysqltest_3b';
+#
+# Obsolete syntax has been dropped
+create user 'mysqltest_2' identified by 'Mysqltest-2';
+--error 1064
+drop user 'mysqltest_2' identified by 'Mysqltest-2';
+#
+# Strange user names
+create user '%@b'@'b';
+show grants for '%@b'@'b';
+grant select on mysql.* to '%@b'@'b';
+show grants for '%@b'@'b';
+rename user '%@b'@'b' to '%@a'@'a';
+--error 1141
+show grants for '%@b'@'b';
+show grants for '%@a'@'a';
+drop user '%@a'@'a';
+#
+# CREATE USER privilege is enough
+#
+create user mysqltest_2@localhost;
+grant create user on *.* to mysqltest_2@localhost;
+connect (user3,localhost,mysqltest_2,,);
+connection user3;
+--error 1142
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+create user mysqltest_A@'%';
+rename user mysqltest_A@'%' to mysqltest_B@'%';
+drop user mysqltest_B@'%';
+disconnect user3;
+connection default;
+drop user mysqltest_2@localhost;
+#
+# INSERT/UPDATE/DELETE is ok too
+create user mysqltest_3@localhost;
+grant INSERT,DELETE,UPDATE on mysql.* to mysqltest_3@localhost;
+connect (user4,localhost,mysqltest_3,,);
+connection user4;
+show grants;
+--error 1142
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+insert into mysql.user set host='%', user='mysqltest_B';
+create user mysqltest_A@'%';
+rename user mysqltest_B@'%' to mysqltest_C@'%';
+drop user mysqltest_C@'%';
+disconnect user4;
+connection default;
+drop user mysqltest_3@localhost;
+#
# Bug #3309: Test IP addresses with netmask
+set @@sql_mode='';
create database mysqltest_1;
create table mysqltest_1.t1 (i int);
insert into mysqltest_1.t1 values (1),(2),(3);
diff --git a/mysql-test/t/grant3-master.opt b/mysql-test/t/grant3-master.opt
new file mode 100644
index 00000000000..4b11f5902c1
--- /dev/null
+++ b/mysql-test/t/grant3-master.opt
@@ -0,0 +1 @@
+--safe-user-create
diff --git a/mysql-test/t/grant3.test b/mysql-test/t/grant3.test
new file mode 100644
index 00000000000..115586e807d
--- /dev/null
+++ b/mysql-test/t/grant3.test
@@ -0,0 +1,36 @@
+# Can't run with embedded server
+-- source include/not_embedded.inc
+
+# Test of GRANT commands
+
+SET NAMES binary;
+connect (master,localhost,root,,);
+connection master;
+
+# Cleanup
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
+
+create user mysqltest_1@localhost;
+grant create user on *.* to mysqltest_1@localhost;
+grant select on `my\_1`.* to mysqltest_1@localhost with grant option;
+connect (user_a,localhost,mysqltest_1,,);
+connection user_a;
+--error 1410
+grant select on `my\_1`.* to mysqltest_2@localhost;
+create user mysqltest_2@localhost;
+disconnect user_a;
+connection default;
+
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
diff --git a/mysql-test/t/grant_cache.test b/mysql-test/t/grant_cache.test
index 703ad5d8004..7e17a03ec21 100644
--- a/mysql-test/t/grant_cache.test
+++ b/mysql-test/t/grant_cache.test
@@ -14,7 +14,7 @@ set GLOBAL query_cache_size=1355776;
reset query cache;
flush status;
-connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock);
+connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
connection root;
show grants for current_user;
show grants;
@@ -29,7 +29,7 @@ insert into mysqltest.t2 values (3,3,3);
create table test.t1 (a char (10));
insert into test.t1 values ("test.t1");
select * from t1;
-connect (root2,localhost,root,,mysqltest,$MASTER_MYPORT,master.sock);
+connect (root2,localhost,root,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK);
connection root2;
# put queries in cache
select * from t1;
@@ -47,7 +47,7 @@ grant SELECT on test.t1 to mysqltest_2@localhost;
grant SELECT(a) on mysqltest.t1 to mysqltest_3@localhost;
# The following queries should be fetched from cache
-connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,master.sock);
+connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK);
connection user1;
show grants for current_user();
show status like "Qcache_queries_in_cache";
@@ -72,12 +72,12 @@ show status like "Qcache_hits";
show status like "Qcache_not_cached";
# Don't use '' as user because it will pick Unix login
-connect (unkuser,localhost,unkuser,,,$MASTER_MYPORT,master.sock);
+connect (unkuser,localhost,unkuser,,,$MASTER_MYPORT,$MASTER_MYSOCK);
connection unkuser;
show grants for current_user();
# The following queries should be fetched from cache
-connect (user2,localhost,mysqltest_2,,mysqltest,$MASTER_MYPORT,master.sock);
+connect (user2,localhost,mysqltest_2,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK);
connection user2;
select "user2";
select * from t1;
@@ -92,7 +92,7 @@ show status like "Qcache_hits";
show status like "Qcache_not_cached";
# The following queries should not be fetched from cache
-connect (user3,localhost,mysqltest_3,,mysqltest,$MASTER_MYPORT,master.sock);
+connect (user3,localhost,mysqltest_3,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK);
connection user3;
select "user3";
--replace_result 127.0.0.1 localhost
@@ -113,7 +113,7 @@ show status like "Qcache_hits";
show status like "Qcache_not_cached";
# Connect without a database
-connect (user4,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,master.sock);
+connect (user4,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,$MASTER_MYSOCK);
connection user4;
select "user4";
show grants;
diff --git a/mysql-test/t/greedy_optimizer.test b/mysql-test/t/greedy_optimizer.test
new file mode 100644
index 00000000000..e547d85b7f3
--- /dev/null
+++ b/mysql-test/t/greedy_optimizer.test
@@ -0,0 +1,313 @@
+#
+# A simple test of the greedy query optimization algorithm and the switches that
+# control the optimizationprocess.
+#
+
+#
+# Schema
+#
+--disable_warnings
+drop table if exists t1,t2,t3,t4,t5,t6,t7;
+--enable_warnings
+
+create table t1 (
+ c11 integer,c12 integer,c13 integer,c14 integer,c15 integer,c16 integer,
+ primary key (c11)
+);
+create table t2 (
+ c21 integer,c22 integer,c23 integer,c24 integer,c25 integer,c26 integer
+);
+create table t3 (
+ c31 integer,c32 integer,c33 integer,c34 integer,c35 integer,c36 integer,
+ primary key (c31)
+);
+create table t4 (
+ c41 integer,c42 integer,c43 integer,c44 integer,c45 integer,c46 integer
+);
+create table t5 (
+ c51 integer,c52 integer,c53 integer,c54 integer,c55 integer,c56 integer,
+ primary key (c51)
+);
+create table t6 (
+ c61 integer,c62 integer,c63 integer,c64 integer,c65 integer,c66 integer
+);
+create table t7 (
+ c71 integer,c72 integer,c73 integer,c74 integer,c75 integer,c76 integer,
+ primary key (c71)
+);
+
+#
+# Data
+# cardinality(Ti) = cardinality(T(i-1)) + 3
+#
+insert into t1 values (1,2,3,4,5,6);
+insert into t1 values (2,2,3,4,5,6);
+insert into t1 values (3,2,3,4,5,6);
+
+insert into t2 values (1,2,3,4,5,6);
+insert into t2 values (2,2,3,4,5,6);
+insert into t2 values (3,2,3,4,5,6);
+insert into t2 values (4,2,3,4,5,6);
+insert into t2 values (5,2,3,4,5,6);
+insert into t2 values (6,2,3,4,5,6);
+
+insert into t3 values (1,2,3,4,5,6);
+insert into t3 values (2,2,3,4,5,6);
+insert into t3 values (3,2,3,4,5,6);
+insert into t3 values (4,2,3,4,5,6);
+insert into t3 values (5,2,3,4,5,6);
+insert into t3 values (6,2,3,4,5,6);
+insert into t3 values (7,2,3,4,5,6);
+insert into t3 values (8,2,3,4,5,6);
+insert into t3 values (9,2,3,4,5,6);
+
+insert into t4 values (1,2,3,4,5,6);
+insert into t4 values (2,2,3,4,5,6);
+insert into t4 values (3,2,3,4,5,6);
+insert into t4 values (4,2,3,4,5,6);
+insert into t4 values (5,2,3,4,5,6);
+insert into t4 values (6,2,3,4,5,6);
+insert into t4 values (7,2,3,4,5,6);
+insert into t4 values (8,2,3,4,5,6);
+insert into t4 values (9,2,3,4,5,6);
+insert into t4 values (10,2,3,4,5,6);
+insert into t4 values (11,2,3,4,5,6);
+insert into t4 values (12,2,3,4,5,6);
+
+insert into t5 values (1,2,3,4,5,6);
+insert into t5 values (2,2,3,4,5,6);
+insert into t5 values (3,2,3,4,5,6);
+insert into t5 values (4,2,3,4,5,6);
+insert into t5 values (5,2,3,4,5,6);
+insert into t5 values (6,2,3,4,5,6);
+insert into t5 values (7,2,3,4,5,6);
+insert into t5 values (8,2,3,4,5,6);
+insert into t5 values (9,2,3,4,5,6);
+insert into t5 values (10,2,3,4,5,6);
+insert into t5 values (11,2,3,4,5,6);
+insert into t5 values (12,2,3,4,5,6);
+insert into t5 values (13,2,3,4,5,6);
+insert into t5 values (14,2,3,4,5,6);
+insert into t5 values (15,2,3,4,5,6);
+
+insert into t6 values (1,2,3,4,5,6);
+insert into t6 values (2,2,3,4,5,6);
+insert into t6 values (3,2,3,4,5,6);
+insert into t6 values (4,2,3,4,5,6);
+insert into t6 values (5,2,3,4,5,6);
+insert into t6 values (6,2,3,4,5,6);
+insert into t6 values (7,2,3,4,5,6);
+insert into t6 values (8,2,3,4,5,6);
+insert into t6 values (9,2,3,4,5,6);
+insert into t6 values (10,2,3,4,5,6);
+insert into t6 values (11,2,3,4,5,6);
+insert into t6 values (12,2,3,4,5,6);
+insert into t6 values (13,2,3,4,5,6);
+insert into t6 values (14,2,3,4,5,6);
+insert into t6 values (15,2,3,4,5,6);
+insert into t6 values (16,2,3,4,5,6);
+insert into t6 values (17,2,3,4,5,6);
+insert into t6 values (18,2,3,4,5,6);
+
+insert into t7 values (1,2,3,4,5,6);
+insert into t7 values (2,2,3,4,5,6);
+insert into t7 values (3,2,3,4,5,6);
+insert into t7 values (4,2,3,4,5,6);
+insert into t7 values (5,2,3,4,5,6);
+insert into t7 values (6,2,3,4,5,6);
+insert into t7 values (7,2,3,4,5,6);
+insert into t7 values (8,2,3,4,5,6);
+insert into t7 values (9,2,3,4,5,6);
+insert into t7 values (10,2,3,4,5,6);
+insert into t7 values (11,2,3,4,5,6);
+insert into t7 values (12,2,3,4,5,6);
+insert into t7 values (13,2,3,4,5,6);
+insert into t7 values (14,2,3,4,5,6);
+insert into t7 values (15,2,3,4,5,6);
+insert into t7 values (16,2,3,4,5,6);
+insert into t7 values (17,2,3,4,5,6);
+insert into t7 values (18,2,3,4,5,6);
+insert into t7 values (19,2,3,4,5,6);
+insert into t7 values (20,2,3,4,5,6);
+insert into t7 values (21,2,3,4,5,6);
+
+#
+# The actual test begins here
+#
+
+# Check the default values for the optimizer paramters
+
+select @@optimizer_search_depth;
+select @@optimizer_prune_level;
+
+-- This value swithes back to the old implementation of 'find_best()'
+-- set optimizer_search_depth=63; - old (independent of the optimizer_prune_level)
+--
+-- These are the values for the parameters that control the greedy optimizer
+-- (total 6 combinations - 3 for optimizer_search_depth, 2 for optimizer_prune_level):
+--
+-- set optimizer_search_depth=0; - automatic
+-- set optimizer_search_depth=1; - min
+-- set optimizer_search_depth=62; - max (default)
+--
+-- set optimizer_prune_level=0 - exhaustive;
+-- set optimizer_prune_level=1 - heuristic; -- default
+
+
+#
+# Compile several queries with all combinations of the query
+# optimizer parameters. Each test query has two variants, where
+# in the second variant the tables in the FROM clause are in
+# inverse order to the tables in the first variant.
+# Due to pre-sorting of tables before compilation, there should
+# be no difference in the plans for each two such query variants.
+#
+
+# First, for reference compile the test queries with the 'old' optimization
+# procedure 'find_best'. Notice that 'find_best' does not depend on the
+# choice of heuristic.
+
+set optimizer_search_depth=63;
+select @@optimizer_search_depth;
+
+-- 6-table join, chain
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, star
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, clique
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+
+
+# Test the new optimization procedures
+
+set optimizer_prune_level=0;
+select @@optimizer_prune_level;
+
+set optimizer_search_depth=0;
+select @@optimizer_search_depth;
+
+-- 6-table join, chain
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, star
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, clique
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+
+set optimizer_search_depth=1;
+select @@optimizer_search_depth;
+
+-- 6-table join, chain
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, star
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, clique
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+
+set optimizer_search_depth=62;
+select @@optimizer_search_depth;
+
+-- 6-table join, chain
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, star
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, clique
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+
+
+set optimizer_prune_level=1;
+select @@optimizer_prune_level;
+
+set optimizer_search_depth=0;
+select @@optimizer_search_depth;
+
+-- 6-table join, chain
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, star
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, clique
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+
+set optimizer_search_depth=1;
+select @@optimizer_search_depth;
+
+-- 6-table join, chain
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, star
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, clique
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+
+set optimizer_search_depth=62;
+select @@optimizer_search_depth;
+
+-- 6-table join, chain
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, star
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
+show status like 'Last_query_cost';
+-- 6-table join, clique
+explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
+show status like 'Last_query_cost';
+
+drop table t1,t2,t3,t4,t5,t6,t7;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index f14fab2d30e..bf557029a55 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -135,7 +135,7 @@ CREATE TABLE t1 (
bug_severity enum('blocker','critical','major','normal','minor','trivial','enhancement') DEFAULT 'blocker' NOT NULL,
bug_status enum('','NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED') DEFAULT 'NEW' NOT NULL,
creation_ts datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
- delta_ts timestamp(14),
+ delta_ts timestamp,
short_desc mediumtext,
long_desc mediumtext,
op_sys enum('All','Windows 3.1','Windows 95','Windows 98','Windows NT','Windows 2000','Linux','other') DEFAULT 'All' NOT NULL,
@@ -575,22 +575,12 @@ CREATE TABLE t1 (id varchar(20) NOT NULL);
INSERT INTO t1 VALUES ('trans1'), ('trans2');
CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL);
INSERT INTO t2 VALUES ('trans1', 'a problem');
-
-SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS err_comment
- FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY err_comment;
+SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment
+ FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment;
DROP TABLE t1, t2;
#
-# Test for bug #11414: crash on Windows for a simple GROUP BY query
-#
-
-CREATE TABLE t1 (n int);
-INSERT INTO t1 VALUES (1);
-SELECT n+1 AS n FROM t1 GROUP BY n;
-DROP TABLE t1;
-
-#
# Bug #12266 GROUP BY expression on DATE column produces result with
# reduced length
#
@@ -601,6 +591,17 @@ select date(left(f1+0,8)) from t1 group by 1;
drop table t1;
#
+# Test for bug #11414: crash on Windows for a simple GROUP BY query
+#
+
+CREATE TABLE t1 (n int);
+INSERT INTO t1 VALUES (1);
+--disable_ps_protocol
+SELECT n+1 AS n FROM t1 GROUP BY n;
+--enable_ps_protocol
+DROP TABLE t1;
+
+#
# BUG#12695: Item_func_isnull::update_used_tables
# did not update const_item_cache
#
@@ -611,3 +612,27 @@ select sql_buffer_result max(f1)+1 from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Bug#11211: Ambiguous column reference in GROUP BY.
+#
+
+create table t1 (c1 char(3), c2 char(3));
+create table t2 (c3 char(3), c4 char(3));
+insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2');
+insert into t2 values ('aaa', 'bb1'), ('aaa', 'bb2');
+
+# query with ambiguous column reference 'c2'
+--disable_ps_protocol
+select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4
+group by c2;
+show warnings;
+--enable_ps_protocol
+
+# this query has no ambiguity
+select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4
+group by t1.c1;
+
+show warnings;
+drop table t1, t2;
+
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
new file mode 100644
index 00000000000..da3fdec80d2
--- /dev/null
+++ b/mysql-test/t/group_min_max.test
@@ -0,0 +1,700 @@
+#
+# Test file for WL#1724 (Min/Max Optimization for Queries with Group By Clause).
+# The queries in this file test query execution via QUICK_GROUP_MIN_MAX_SELECT.
+#
+
+#
+# TODO:
+# Add queries with:
+# - C != const
+# - C IS NOT NULL
+# - HAVING clause
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (
+ a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' '
+);
+
+insert into t1 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'),
+('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'),
+('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'),
+('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'),
+('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4'),
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'),
+('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'),
+('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'),
+('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'),
+('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4');
+
+create index idx_t1_0 on t1 (a1);
+create index idx_t1_1 on t1 (a1,a2,b,c);
+create index idx_t1_2 on t1 (a1,a2,b);
+analyze table t1;
+
+-- t2 is the same as t1, but with some NULLs in the MIN/MAX column, and one more
+-- nullable attribute
+
+--disable_warnings
+drop table if exists t2;
+--enable_warnings
+
+create table t2 (
+ a1 char(64), a2 char(64) not null, b char(16), c char(16), d char(16), dummy char(64) default ' '
+);
+insert into t2 select * from t1;
+-- add few rows with NULL's in the MIN/MAX column
+insert into t2 (a1, a2, b, c, d) values
+('a','a',NULL,'a777','xyz'),('a','a',NULL,'a888','xyz'),('a','a',NULL,'a999','xyz'),
+('a','a','a',NULL,'xyz'),
+('a','a','b',NULL,'xyz'),
+('a','b','a',NULL,'xyz'),
+('c','a',NULL,'c777','xyz'),('c','a',NULL,'c888','xyz'),('c','a',NULL,'c999','xyz'),
+('d','b','b',NULL,'xyz'),
+('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),
+('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),
+('a','a',NULL,'a777','xyz'),('a','a',NULL,'a888','xyz'),('a','a',NULL,'a999','xyz'),
+('a','a','a',NULL,'xyz'),
+('a','a','b',NULL,'xyz'),
+('a','b','a',NULL,'xyz'),
+('c','a',NULL,'c777','xyz'),('c','a',NULL,'c888','xyz'),('c','a',NULL,'c999','xyz'),
+('d','b','b',NULL,'xyz'),
+('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),('e','a','a',NULL,'xyz'),
+('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz'),('e','a','b',NULL,'xyz');
+
+create index idx_t2_0 on t2 (a1);
+create index idx_t2_1 on t2 (a1,a2,b,c);
+create index idx_t2_2 on t2 (a1,a2,b);
+analyze table t2;
+
+-- Table t3 is the same as t1, but with smaller column lenghts.
+-- This allows to test different branches of the cost computation procedure
+-- when the number of keys per block are less than the number of keys in the
+-- sub-groups formed by predicates over non-group attributes.
+
+--disable_warnings
+drop table if exists t3;
+--enable_warnings
+
+create table t3 (
+ a1 char(1), a2 char(1), b char(1), c char(4) not null, d char(3), dummy char(1) default ' '
+);
+
+insert into t3 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4');
+insert into t3 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4');
+insert into t3 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4');
+insert into t3 (a1, a2, b, c, d) values
+('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'),
+('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'),
+('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'),
+('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'),
+('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'),
+('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'),
+('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'),
+('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'),
+('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'),
+('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'),
+('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'),
+('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4');
+
+create index idx_t3_0 on t3 (a1);
+create index idx_t3_1 on t3 (a1,a2,b,c);
+create index idx_t3_2 on t3 (a1,a2,b);
+analyze table t3;
+
+
+--
+-- Queries without a WHERE clause. These queries do not use ranges.
+--
+
+-- plans
+explain select a1, min(a2) from t1 group by a1;
+explain select a1, max(a2) from t1 group by a1;
+explain select a1, min(a2), max(a2) from t1 group by a1;
+explain select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b;
+explain select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b;
+--replace_column 7 # 9 #
+explain select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b;
+-- Select fields in different order
+explain select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1;
+explain select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b;
+explain select min(a2) from t1 group by a1;
+explain select a2, min(c), max(c) from t1 group by a1,a2,b;
+
+-- queries
+select a1, min(a2) from t1 group by a1;
+select a1, max(a2) from t1 group by a1;
+select a1, min(a2), max(a2) from t1 group by a1;
+select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b;
+select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b;
+select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b;
+-- Select fields in different order
+select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1;
+select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b;
+select min(a2) from t1 group by a1;
+select a2, min(c), max(c) from t1 group by a1,a2,b;
+
+--
+-- Queries with a where clause
+--
+
+-- A) Preds only over the group 'A' attributes
+-- plans
+explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
+explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+explain select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
+explain select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+explain select a1,a2,b, max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+explain select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
+explain select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;
+
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where a1 < 'd' group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+--replace_column 9 #
+explain select a1, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
+--replace_column 9 #
+explain select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
+
+-- queries
+select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
+select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
+select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+select a1,a2,b, max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
+select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;
+
+select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where a1 < 'd' group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
+select a1,a2,b, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+select a1, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
+select a1,a2,b, max(c) from t2 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
+select a1,a2,b, max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
+select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
+select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
+
+-- B) Equalities only over the non-group 'B' attributes
+-- plans
+explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
+explain select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
+explain select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2;
+explain select a1,a2,b,min(c),max(c) from t1 where (b = 'b') group by a1,a2;
+explain select a1,a2, max(c) from t1 where (b = 'b') group by a1,a2;
+
+explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
+explain select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
+explain select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2;
+explain select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
+explain select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
+
+-- these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost()
+explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
+explain select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
+
+-- queries
+select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
+select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
+select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2;
+select a1,a2,b,min(c),max(c) from t1 where (b = 'b') group by a1,a2;
+select a1,a2, max(c) from t1 where (b = 'b') group by a1,a2;
+
+select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
+select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
+select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2;
+select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
+select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
+
+-- these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost()
+select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
+select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
+
+
+-- IS NULL (makes sense for t2 only)
+-- plans
+explain select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
+explain select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
+explain select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
+explain select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2;
+explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
+explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
+-- queries
+select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
+select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
+select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
+select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2;
+select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
+select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
+
+-- C) Range predicates for the MIN/MAX attribute
+-- plans
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b;
+explain select a1,a2,b, max(c) from t1 where (c > 'f123') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c > 'f123') group by a1,a2,b;
+explain select a1,a2,b, max(c) from t1 where (c < 'a0') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') group by a1,a2,b;
+explain select a1,a2,b, max(c) from t1 where (c < 'k321') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c < 'k321') group by a1,a2,b;
+explain select a1,a2,b, max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+explain select a1,a2,b, max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (c between 'b111' and 'g112') or (c between 'd000' and 'i110') group by a1,a2,b;
+
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where (c > 'b1') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where (c > 'f123') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (c > 'f123') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where (c < 'a0') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where (c < 'k321') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (c < 'k321') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b, max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
+
+-- queries
+select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b;
+select a1,a2,b, max(c) from t1 where (c > 'f123') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c > 'f123') group by a1,a2,b;
+select a1,a2,b, max(c) from t1 where (c < 'a0') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') group by a1,a2,b;
+select a1,a2,b, max(c) from t1 where (c < 'k321') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c < 'k321') group by a1,a2,b;
+select a1,a2,b, max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+select a1,a2,b, max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (c between 'b111' and 'g112') or (c between 'd000' and 'i110') group by a1,a2,b;
+
+select a1,a2,b, max(c) from t2 where (c > 'b1') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') group by a1,a2,b;
+select a1,a2,b, max(c) from t2 where (c > 'f123') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (c > 'f123') group by a1,a2,b;
+select a1,a2,b, max(c) from t2 where (c < 'a0') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') group by a1,a2,b;
+select a1,a2,b, max(c) from t2 where (c < 'k321') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (c < 'k321') group by a1,a2,b;
+select a1,a2,b, max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
+select a1,a2,b, max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
+
+-- analyze the sub-select
+explain select a1,a2,b,min(c),max(c) from t1
+where exists ( select * from t2 where t2.c = t1.c )
+group by a1,a2,b;
+
+-- the sub-select is unrelated to MIN/MAX
+explain select a1,a2,b,min(c),max(c) from t1
+where exists ( select * from t2 where t2.c > 'b1' )
+group by a1,a2,b;
+
+
+-- A,B,C) Predicates referencing mixed classes of attributes
+-- plans
+explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
+explain select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
+explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
+explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
+explain select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+explain select a1,a2,b,min(c) from t1 where (ord(a1) > 97) and (ord(a2) + ord(a1) > 194) and (b = 'c') group by a1,a2,b;
+
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c),max(c) from t2 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+
+-- queries
+select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
+select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
+select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
+select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+select a1,a2,b,min(c) from t1 where (ord(a1) > 97) and (ord(a2) + ord(a1) > 194) and (b = 'c') group by a1,a2,b;
+
+select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
+select a1,a2,b,min(c),max(c) from t2 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
+select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
+select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
+select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+
+
+--
+-- GROUP BY queries without MIN/MAX
+--
+
+-- plans
+explain select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+explain select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+explain select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+explain select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+
+--replace_column 9 #
+explain select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+--replace_column 9 #
+explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+
+-- queries
+select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+
+select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
+select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+
+--
+-- DISTINCT queries
+--
+
+-- plans
+explain select distinct a1,a2,b from t1;
+explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a');
+explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+explain select distinct b from t1 where (a2 >= 'b') and (b = 'a');
+
+--replace_column 9 #
+explain select distinct a1,a2,b from t2;
+--replace_column 9 #
+explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a');
+explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+--replace_column 9 #
+explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+explain select distinct b from t2 where (a2 >= 'b') and (b = 'a');
+
+-- queries
+select distinct a1,a2,b from t1;
+select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a');
+select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+select distinct b from t1 where (a2 >= 'b') and (b = 'a');
+
+select distinct a1,a2,b from t2;
+select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a');
+select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+select distinct b from t2 where (a2 >= 'b') and (b = 'a');
+
+-- BUG #6303
+select distinct t_00.a1
+from t1 t_00
+where exists ( select * from t2 where a1 = t_00.a1 );
+
+-- BUG #8532 - SELECT DISTINCT a, a causes server to crash
+select distinct a1,a1 from t1;
+select distinct a2,a1,a2,a1 from t1;
+select distinct t1.a1,t2.a1 from t1,t2;
+
+
+--
+-- DISTINCT queries with GROUP-BY
+--
+
+-- plans
+explain select distinct a1,a2,b from t1;
+explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+explain select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+
+--replace_column 9 #
+explain select distinct a1,a2,b from t2;
+--replace_column 9 #
+explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+--replace_column 9 #
+explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+--replace_column 9 #
+explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+--replace_column 9 #
+explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+
+-- queries
+select distinct a1,a2,b from t1;
+select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+
+select distinct a1,a2,b from t2;
+select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
+select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
+select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
+
+
+--
+-- COUNT (DISTINCT cols) queries
+--
+
+explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
+explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+explain select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
+explain select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
+
+select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
+select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
+select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
+select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
+select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
+
+--
+-- Queries with expressions in the select clause
+--
+
+explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
+explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
+explain select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;
+explain select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
+explain select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
+
+select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
+select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
+select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;
+select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
+select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
+
+
+--
+-- Negative examples: queries that should NOT be treated as optimizable by
+-- QUICK_GROUP_MIN_MAX_SELECT
+--
+
+-- select a non-indexed attribute
+explain select a1,a2,b,d,min(c),max(c) from t1 group by a1,a2,b;
+
+explain select a1,a2,b,d from t1 group by a1,a2,b;
+
+-- predicate that references an attribute that is after the MIN/MAX argument
+-- in the index
+explain select a1,a2,min(b),max(b) from t1
+where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2;
+
+-- predicate that references a non-indexed attribute
+explain select a1,a2,b,min(c),max(c) from t1
+where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b;
+
+explain select a1,a2,b,c from t1
+where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c;
+
+-- non-equality predicate for a non-group select attribute
+explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1;
+explain select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b;
+
+-- non-group field with an equality predicate that references a keypart after the
+-- MIN/MAX argument
+explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
+select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
+
+-- disjunction for a non-group select attribute
+explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b = 'a') group by a1;
+
+-- non-range predicate for the MIN/MAX attribute
+explain select a1,a2,b,min(c),max(c) from t2
+where (c > 'a000') and (c <= 'd999') and (c like '_8__') group by a1,a2,b;
+
+-- not all attributes are indexed by one index
+explain select a1, a2, b, c, min(d), max(d) from t1 group by a1,a2,b,c;
+
+-- other aggregate functions than MIN/MAX
+explain select a1,a2,count(a2) from t1 group by a1,a2,b;
+explain select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
+explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
+
+#
+# BUG#11044: DISTINCT or GROUP BY queries with equality predicates instead of MIN/MAX.
+#
+
+explain select a1 from t1 where a2 = 'b' group by a1;
+select a1 from t1 where a2 = 'b' group by a1;
+
+explain select distinct a1 from t1 where a2 = 'b';
+select distinct a1 from t1 where a2 = 'b';
+
+#
+# Bug #12672: primary key implcitly included in every innodb index
+#
+
+create table bug12672 (
+ pk_col int auto_increment primary key, a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' '
+) engine=innodb;
+
+insert into bug12672 (a1, a2, b, c, d, dummy) select * from t1;
+
+create index idx12672_0 on bug12672 (a1);
+create index idx12672_1 on bug12672 (a1,a2,b,c);
+create index idx12672_2 on bug12672 (a1,a2,b);
+analyze table t1;
+
+--replace_column 9 #
+explain select distinct a1 from bug12672 where pk_col not in (1,2,3,4);
+select distinct a1 from bug12672 where pk_col not in (1,2,3,4);
+
+drop table bug12672;
+
+drop table t1;
+drop table t2;
+drop table t3;
+
+#
+# Bug #6142: a problem with the empty innodb table
+#
+
+--disable_warnings
+create table t1 (
+ a varchar(30), b varchar(30), primary key(a), key(b)
+) engine=innodb;
+--enable_warnings
+select distinct a from t1;
+drop table t1;
+
+#
+# Bug #9798: group by with rollup
+#
+
+--disable_warnings
+create table t1(a int, key(a)) engine=innodb;
+--enable_warnings
+insert into t1 values(1);
+select a, count(a) from t1 group by a with rollup;
+drop table t1;
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 920a3b752ab..fb223d2a9af 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -2,7 +2,7 @@
#
--disable_warnings
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
--enable_warnings
create table t1 (a int);
@@ -124,3 +124,198 @@ having (a.description is not null) and (c=0);
drop table t1,t2,t3;
# End of 4.1 tests
+
+#
+# Tests for WL#1972 CORRECT EVALUATION OF COLUMN REFERENCES IN THE HAVING CLAUSE
+# Per the SAP VERI tests and WL#1972, MySQL must ensure that HAVING can
+# correctly evaluate column references from the GROUP BY clause, even if the
+# same references are not also found in the select list.
+#
+
+# set global sql_mode='ansi';
+# set session sql_mode='ansi';
+
+create table t1 (col1 int, col2 varchar(5), col_t1 int);
+create table t2 (col1 int, col2 varchar(5), col_t2 int);
+create table t3 (col1 int, col2 varchar(5), col_t3 int);
+
+insert into t1 values(10,'hello',10);
+insert into t1 values(20,'hello',20);
+insert into t1 values(30,'hello',30);
+insert into t1 values(10,'bye',10);
+insert into t1 values(10,'sam',10);
+insert into t1 values(10,'bob',10);
+
+insert into t2 select * from t1;
+insert into t3 select * from t1;
+
+select count(*) from t1 group by col1 having col1 = 10;
+select count(*) as count_col1 from t1 group by col1 having col1 = 10;
+select count(*) as count_col1 from t1 as tmp1 group by col1 having col1 = 10;
+select count(*) from t1 group by col2 having col2 = 'hello';
+--error 1054
+select count(*) from t1 group by col2 having col1 = 10;
+select col1 as count_col1 from t1 as tmp1 group by col1 having col1 = 10;
+select col1 as count_col1 from t1 as tmp1 group by col1 having count_col1 = 10;
+select col1 as count_col1 from t1 as tmp1 group by count_col1 having col1 = 10;
+# ANSI: should return SQLSTATE 42000 Syntax error or access violation
+# MySQL: returns 10 - because of GROUP BY name resolution
+select col1 as count_col1 from t1 as tmp1 group by count_col1 having count_col1 = 10;
+# ANSI: should return SQLSTATE 42000 Syntax error or access violation
+# MySQL: returns 10 - because of GROUP BY name resolution
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col1 = 10;
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having count_col1 = 10;
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col2 = 'hello';
+select col1 as count_col1,col2 as group_col2 from t1 as tmp1 group by col1,col2 having group_col2 = 'hello';
+--error 1064
+select sum(col1) as co12 from t1 group by col2 having col2 10;
+select sum(col1) as co2, count(col2) as cc from t1 group by col1 having col1 =10;
+--error 1054
+select t2.col2 from t2 group by t2.col1, t2.col2 having t1.col1 <= 10;
+
+
+#
+# queries with nested sub-queries
+#
+
+# the having column is resolved in the same query
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having t2.col1 <= 10);
+
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2
+ having t2.col1 <=
+ (select min(t3.col1) from t3));
+
+# the having column is resolved in the SELECT clause of the outer query -
+# works in ANSI
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having t1.col1 <= 10);
+
+# the having column is resolved in the SELECT clause of the outer query -
+# error in ANSI, works with MySQL extension
+select t1.col1 as tmp_col from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having tmp_col <= 10);
+
+# the having column is resolved in the FROM clause of the outer query -
+# works in ANSI
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having col_t1 <= 10);
+
+# Item_field must be resolved in the same way as Item_ref
+select sum(col1) from t1
+group by col_t1
+having (select col_t1 from t2 where col_t1 = col_t2 order by col_t2 limit 1);
+
+# nested queries with HAVING, inner having column resolved in outer FROM clause
+# the outer having column is not referenced in GROUP BY which results in an error
+--error 1054
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having col_t1 <= 10)
+having col_t1 <= 20;
+
+# both having columns are resolved in the GROUP clause of the outer query
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having col_t1 <= 10)
+group by col_t1
+having col_t1 <= 20;
+
+#
+# nested HAVING clauses
+#
+
+# non-correlated subqueries
+select col_t1, sum(col1) from t1
+group by col_t1
+having col_t1 > 10 and
+ exists (select sum(t2.col1) from t2
+ group by t2.col2 having t2.col2 > 'b');
+
+# correlated subqueries - inner having column 't1.col2' resolves to
+# the outer FROM clause, which cannot be used because the outer query
+# is grouped
+--error 1054
+select sum(col1) from t1
+group by col_t1
+having col_t1 in (select sum(t2.col1) from t2
+ group by t2.col2, t2.col1 having t2.col1 = t1.col1);
+
+# correlated subqueries - inner having column 'col_t1' resolves to
+# the outer GROUP clause
+select sum(col1) from t1
+group by col_t1
+having col_t1 in (select sum(t2.col1) from t2
+ group by t2.col2, t2.col1 having t2.col1 = col_t1);
+
+#
+# queries with joins and ambiguous column names
+#
+--error 1052
+select t1.col1, t2.col1 from t1, t2 where t1.col1 = t2.col1
+group by t1.col1, t2.col1 having col1 = 2;
+
+--error 1052
+select t1.col1*10+t2.col1 from t1,t2 where t1.col1=t2.col1
+group by t1.col1, t2.col1 having col1 = 2;
+
+drop table t1, t2, t3;
+
+# More queries to test ANSI compatibility
+create table t1 (s1 int);
+insert into t1 values (1),(2),(3);
+
+select count(*) from t1 group by s1 having s1 is null;
+
+# prepared statements prints warnings too early
+--disable_ps_protocol
+select s1*0 as s1 from t1 group by s1 having s1 <> 0;
+--enable_ps_protocol
+
+# ANSI requires: 3 rows
+# MySQL returns: 0 rows - because of GROUP BY name resolution
+
+select s1*0 from t1 group by s1 having s1 = 0;
+
+select s1 from t1 group by 1 having 1 = 0;
+
+select count(s1) from t1 group by s1 having count(1+1)=2;
+# ANSI requires: 3 rows
+# MySQL returns: 0 rows - because of GROUP BY name resolution
+
+select count(s1) from t1 group by s1 having s1*0=0;
+
+-- error 1052
+select * from t1 a, t1 b group by a.s1 having s1 is null;
+# ANSI requires: 0 rows
+# MySQL returns:
+# "ERROR 1052 (23000): Column 's1' in having clause is ambiguous"
+# I think the column is ambiguous in ANSI too.
+# It is the same as:
+# select a.s1, b.s1 from t1 a, t1 b group by a.s1 having s1 is null;
+# currently we first check SELECT, thus s1 is ambiguous.
+
+drop table t1;
+
+create table t1 (s1 char character set latin1 collate latin1_german1_ci);
+insert into t1 values ('ü'),('y');
+
+select s1,count(s1) from t1
+group by s1 collate latin1_swedish_ci having s1 = 'y';
+# ANSI requires: 1 row, with count(s1) = 2
+# MySQL returns: 1 row, with count(s1) = 1
+
+drop table t1;
diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test
index 270b8a1df6f..fcaa4c41ece 100644
--- a/mysql-test/t/heap.test
+++ b/mysql-test/t/heap.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2,t3;
--enable_warnings
create table t1 (a int not null,b int not null, primary key (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
@@ -34,7 +34,7 @@ select * from t1;
drop table t1;
create table t1 (a int not null) engine=heap;
-insert into t1 values (869751),(736494),(226312),(802616);
+insert into t1 values (869751),(736494),(226312),(802616),(728912);
select * from t1 where a > 736494;
alter table t1 add unique uniq_id(a);
select * from t1 where a > 736494;
@@ -197,34 +197,236 @@ select * from t1;
drop table t1;
#
+# Test varchar
+# We can't use varchar.inc becasue heap doesn't support blob's
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=HEAP;
+
+#
+# Simple basic test that endspace is saved
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50));
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+select concat('*',v,'*',c,'*',t,'*') from t1;
+
+# Check how columns are copied
+show create table t1;
+create table t2 like t1;
+show create table t2;
+create table t3 select * from t1;
+show create table t3;
+alter table t1 modify c varchar(10);
+show create table t1;
+alter table t1 modify v char(10);
+show create table t1;
+alter table t1 modify t varchar(10);
+show create table t1;
+select concat('*',v,'*',c,'*',t,'*') from t1;
+drop table t1,t2,t3;
+
+#
+# Testing of keys
+#
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10)));
+show create table t1;
+disable_query_log;
+let $1=10;
+while ($1)
+{
+ let $2=27;
+ eval set @space=repeat(' ',10-$1);
+ while ($2)
+ {
+ eval set @char=char(ascii('a')+$2-1);
+ insert into t1 values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
+ dec $2;
+ }
+ dec $1;
+}
+enable_query_log;
+select count(*) from t1;
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+select count(*) from t1 where c='a';
+select count(*) from t1 where t='a';
+select count(*) from t1 where v='a ';
+select count(*) from t1 where c='a ';
+select count(*) from t1 where t='a ';
+select count(*) from t1 where v between 'a' and 'a ';
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+select count(*) from t1 where v like 'a%';
+select count(*) from t1 where c like 'a%';
+select count(*) from t1 where t like 'a%';
+select count(*) from t1 where v like 'a %';
+explain select count(*) from t1 where v='a ';
+explain select count(*) from t1 where c='a ';
+explain select count(*) from t1 where t='a ';
+explain select count(*) from t1 where v like 'a%';
+explain select count(*) from t1 where v between 'a' and 'a ';
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+
+--error 1062
+alter table t1 add unique(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*'));
+explain select * from t1 where v='a';
+
+# GROUP BY
+
+select v,count(*) from t1 group by v limit 10;
+select v,count(t) from t1 group by v limit 10;
+select v,count(c) from t1 group by v limit 10;
+select sql_big_result trim(v),count(t) from t1 group by v limit 10;
+select sql_big_result trim(v),count(c) from t1 group by v limit 10;
+select c,count(*) from t1 group by c limit 10;
+select c,count(t) from t1 group by c limit 10;
+select sql_big_result c,count(t) from t1 group by c limit 10;
+select t,count(*) from t1 group by t limit 10;
+select t,count(t) from t1 group by t limit 10;
+select sql_big_result trim(t),count(t) from t1 group by t limit 10;
+drop table t1;
+
+#
+# Test unique keys
+#
+
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a');
+--error 1062
+insert into t1 values ('a ');
+
+alter table t1 modify a varchar(10);
+--error 1062
+insert into t1 values ('a '),('a '),('a '),('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+update t1 set a='a ' where a like 'a ';
+update t1 set a='a ' where a like 'a ';
+drop table t1;
+
+#
+# Testing of btree keys
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using btree (c), key using btree (t(10)));
+show create table t1;
+disable_query_log;
+let $1=10;
+while ($1)
+{
+ let $2=27;
+ eval set @space=repeat(' ',10-$1);
+ while ($2)
+ {
+ eval set @char=char(ascii('a')+$2-1);
+ insert into t1 values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
+ dec $2;
+ }
+ dec $1;
+}
+enable_query_log;
+select count(*) from t1;
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+select count(*) from t1 where c='a';
+select count(*) from t1 where t='a';
+select count(*) from t1 where v='a ';
+select count(*) from t1 where c='a ';
+select count(*) from t1 where t='a ';
+select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+--replace_column 9 #
+explain select count(*) from t1 where v='a ';
+--replace_column 9 #
+explain select count(*) from t1 where c='a ';
+--replace_column 9 #
+explain select count(*) from t1 where t='a ';
+--replace_column 9 #
+explain select count(*) from t1 where v like 'a%';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+
+--error 1062
+alter table t1 add unique(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*'));
+# Number of rows is not constant for b-trees keys
+--replace_column 9 #
+explain select * from t1 where v='a';
+
+drop table t1;
+
+#
+# Test unique btree keys
+#
+
+create table t1 (a char(10), unique using btree (a)) engine=heap;
+insert into t1 values ('a');
+--error 1062
+insert into t1 values ('a ');
+
+alter table t1 modify a varchar(10);
+--error 1062
+insert into t1 values ('a '),('a '),('a '),('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+update t1 set a='a ' where a like 'a ';
+update t1 set a='a ' where a like 'a ';
+drop table t1;
+
+#
+# test show create table
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+drop table t1;
+
+create table t1 (v varchar(65530), key(v(10)));
+show create table t1;
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+drop table t1;
+
+#
+# Reset varchar test
+#
+eval set storage_engine=$default;
+
+#
# Bug #8489: Strange auto_increment behaviour
#
create table t1 (a bigint unsigned auto_increment primary key, b int,
key (b, a)) engine=heap;
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-insert t1 (b) values (1);
-select * from t1;
+insert t1 (b) values (1),(1),(1),(1),(1),(1),(1),(1);
+select * from t1;
drop table t1;
+
create table t1 (a int not null, b int not null auto_increment,
primary key(a, b), key(b)) engine=heap;
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-insert t1 (a) values (1);
-select * from t1;
+insert t1 (a) values (1),(1),(1),(1),(1),(1),(1),(1);
+select * from t1;
drop table t1;
+--error 1075
+create table t1 (a int not null, b int not null auto_increment,
+ primary key(a, b)) engine=heap;
+
#
# Bug #10566: Verify that we can create a prefixed key with length > 255
#
@@ -235,3 +437,14 @@ insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
drop table t1;
# End of 4.1 tests
+
+#
+# Bug #3094: Row format of memory tables should always be reported as Fixed
+#
+create table t1 (c char(10)) engine=memory;
+create table t2 (c varchar(10)) engine=memory;
+--replace_column 8 #
+show table status like 't_';
+drop table t1, t2;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test
index aea9e9486e5..5e493c2643b 100644
--- a/mysql-test/t/heap_btree.test
+++ b/mysql-test/t/heap_btree.test
@@ -34,7 +34,7 @@ select * from t1;
drop table t1;
create table t1 (a int not null) engine=heap;
-insert into t1 values (869751),(736494),(226312),(802616);
+insert into t1 values (869751),(736494),(226312),(802616),(728912);
select * from t1 where a > 736494;
alter table t1 add unique uniq_id using BTREE (a);
select * from t1 where a > 736494;
diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test
index 2cdec652688..28a75a5ee11 100644
--- a/mysql-test/t/heap_hash.test
+++ b/mysql-test/t/heap_hash.test
@@ -34,7 +34,7 @@ select * from t1;
drop table t1;
create table t1 (a int not null) engine=heap;
-insert into t1 values (869751),(736494),(226312),(802616);
+insert into t1 values (869751),(736494),(226312),(802616),(728912);
select * from t1 where a > 736494;
alter table t1 add unique uniq_id using HASH (a);
select * from t1 where a > 736494;
diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test
new file mode 100644
index 00000000000..42175a757c2
--- /dev/null
+++ b/mysql-test/t/index_merge.test
@@ -0,0 +1,329 @@
+#
+# Index merge tests
+#
+--disable_warnings
+drop table if exists t0, t1, t2, t3, t4;
+--enable_warnings
+
+# Create and fill a table with simple keys
+create table t0
+(
+ key1 int not null,
+ INDEX i1(key1)
+);
+
+--disable_query_log
+insert into t0 values (1),(2),(3),(4),(5),(6),(7),(8);
+
+let $1=7;
+set @d=8;
+while ($1)
+{
+ eval insert into t0 select key1+@d from t0;
+ eval set @d=@d*2;
+ dec $1;
+}
+--enable_query_log
+
+alter table t0 add key2 int not null, add index i2(key2);
+alter table t0 add key3 int not null, add index i3(key3);
+alter table t0 add key4 int not null, add index i4(key4);
+alter table t0 add key5 int not null, add index i5(key5);
+alter table t0 add key6 int not null, add index i6(key6);
+alter table t0 add key7 int not null, add index i7(key7);
+alter table t0 add key8 int not null, add index i8(key8);
+
+update t0 set key2=key1,key3=key1,key4=key1,key5=key1,key6=key1,key7=key1,key8=1024-key1;
+analyze table t0;
+
+# 1. One index
+explain select * from t0 where key1 < 3 or key1 > 1020;
+
+# 2. Simple cases
+explain
+select * from t0 where key1 < 3 or key2 > 1020;
+select * from t0 where key1 < 3 or key2 > 1020;
+
+explain select * from t0 where key1 < 3 or key2 <4;
+
+explain
+select * from t0 where (key1 > 30 and key1<35) or (key2 >32 and key2 < 40);
+select * from t0 where (key1 > 30 and key1<35) or (key2 >32 and key2 < 40);
+
+# 3. Check that index_merge doesn't break "ignore/force/use index"
+explain select * from t0 ignore index (i2) where key1 < 3 or key2 <4;
+explain select * from t0 where (key1 < 3 or key2 <4) and key3 = 50;
+explain select * from t0 use index (i1,i2) where (key1 < 3 or key2 <4) and key3 = 50;
+
+explain select * from t0 where (key1 > 1 or key2 > 2);
+explain select * from t0 force index (i1,i2) where (key1 > 1 or key2 > 2);
+
+
+# 4. Check if conjuncts are grouped by keyuse
+explain
+ select * from t0 where key1<3 or key2<3 or (key1>5 and key1<8) or
+ (key1>10 and key1<12) or (key2>100 and key2<110);
+
+# 5. Check index_merge with conjuncts that are always true/false
+# verify fallback to "range" if there is only one non-confluent condition
+explain select * from t0 where key2 = 45 or key1 <=> null;
+
+explain select * from t0 where key2 = 45 or key1 is not null;
+explain select * from t0 where key2 = 45 or key1 is null;
+
+# the last conj. is always false and will be discarded
+explain select * from t0 where key2=10 or key3=3 or key4 <=> null;
+
+# the last conj. is always true and will cause 'all' scan
+explain select * from t0 where key2=10 or key3=3 or key4 is null;
+
+# some more complicated cases
+explain select key1 from t0 where (key1 <=> null) or (key2 < 5) or
+ (key3=10) or (key4 <=> null);
+explain select key1 from t0 where (key1 <=> null) or (key1 < 5) or
+ (key3=10) or (key4 <=> null);
+
+# 6.Several ways to do index_merge, (ignored) index_merge vs. range
+explain select * from t0 where
+ (key1 < 3 or key2 < 3) and (key3 < 4 or key4 < 4) and (key5 < 5 or key6 < 5);
+
+explain
+select * from t0 where (key1 < 3 or key2 < 6) and (key1 < 7 or key3 < 4);
+
+select * from t0 where (key1 < 3 or key2 < 6) and (key1 < 7 or key3 < 4);
+
+
+explain select * from t0 where
+ (key1 < 3 or key2 < 3) and (key3 < 4 or key4 < 4) and (key5 < 2 or key6 < 2);
+
+# now index_merge is not used at all when "range" is possible
+explain select * from t0 where
+ (key1 < 3 or key2 < 3) and (key3 < 100);
+
+# this even can cause "all" scan:
+explain select * from t0 where
+ (key1 < 3 or key2 < 3) and (key3 < 1000);
+
+
+# 7. Complex cases
+# tree_or(List<SEL_IMERGE>, range SEL_TREE).
+explain select * from t0 where
+ ((key1 < 4 or key2 < 4) and (key2 <5 or key3 < 4))
+ or
+ key2 > 5;
+
+explain select * from t0 where
+ ((key1 < 4 or key2 < 4) and (key2 <5 or key3 < 4))
+ or
+ key1 < 7;
+
+select * from t0 where
+ ((key1 < 4 or key2 < 4) and (key2 <5 or key3 < 4))
+ or
+ key1 < 7;
+
+# tree_or(List<SEL_IMERGE>, List<SEL_IMERGE>).
+explain select * from t0 where
+ ((key1 < 4 or key2 < 4) and (key3 <5 or key5 < 4))
+ or
+ ((key5 < 5 or key6 < 6) and (key7 <7 or key8 < 4));
+
+explain select * from t0 where
+ ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+ or
+ ((key7 <7 or key8 < 4) and (key5 < 5 or key6 < 6));
+
+explain select * from t0 where
+ ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+ or
+ ((key3 <7 or key5 < 2) and (key5 < 5 or key6 < 6));
+
+explain select * from t0 where
+ ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+ or
+ (((key3 <7 and key7 < 6) or key5 < 2) and (key5 < 5 or key6 < 6));
+
+explain select * from t0 where
+ ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+ or
+ ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6));
+
+explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where
+ ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+ or
+ ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6));
+
+# 8. Verify that "order by" after index merge uses filesort
+select * from t0 where key1 < 5 or key8 < 4 order by key1;
+
+explain
+select * from t0 where key1 < 5 or key8 < 4 order by key1;
+
+# 9. Check that index_merge cost is compared to 'index' where possible
+create table t2 like t0;
+insert into t2 select * from t0;
+
+alter table t2 add index i1_3(key1, key3);
+alter table t2 add index i2_3(key2, key3);
+alter table t2 drop index i1;
+alter table t2 drop index i2;
+alter table t2 add index i321(key3, key2, key1);
+
+# index_merge vs 'index', index_merge is better.
+explain select key3 from t2 where key1 = 100 or key2 = 100;
+
+# index_merge vs 'index', 'index' is better.
+explain select key3 from t2 where key1 <100 or key2 < 100;
+
+# index_merge vs 'all', index_merge is better.
+explain select key7 from t2 where key1 <100 or key2 < 100;
+
+# 10. Multipart keys.
+create table t4 (
+ key1a int not null,
+ key1b int not null,
+ key2 int not null,
+ key2_1 int not null,
+ key2_2 int not null,
+ key3 int not null,
+
+ index i1a (key1a, key1b),
+ index i1b (key1b, key1a),
+
+ index i2_1(key2, key2_1),
+ index i2_2(key2, key2_1)
+);
+
+insert into t4 select key1,key1,key1 div 10, key1 % 10, key1 % 10, key1 from t0;
+
+# the following will be handled by index_merge:
+select * from t4 where key1a = 3 or key1b = 4;
+explain select * from t4 where key1a = 3 or key1b = 4;
+
+# and the following will not
+explain select * from t4 where key2 = 1 and (key2_1 = 1 or key3 = 5);
+
+explain select * from t4 where key2 = 1 and (key2_1 = 1 or key2_2 = 5);
+
+explain select * from t4 where key2_1 = 1 or key2_2 = 5;
+
+
+# 11. Multitable selects
+create table t1 like t0;
+insert into t1 select * from t0;
+
+# index_merge on first table in join
+explain select * from t0 left join t1 on (t0.key1=t1.key1)
+ where t0.key1=3 or t0.key2=4;
+
+select * from t0 left join t1 on (t0.key1=t1.key1)
+ where t0.key1=3 or t0.key2=4;
+
+explain
+select * from t0,t1 where (t0.key1=t1.key1) and ( t0.key1=3 or t0.key2=4);
+
+# index_merge vs. ref
+explain
+select * from t0,t1 where (t0.key1=t1.key1) and
+ (t0.key1=3 or t0.key2=4) and t1.key1<200;
+
+# index_merge vs. ref
+explain
+select * from t0,t1 where (t0.key1=t1.key1) and
+ (t0.key1=3 or t0.key2<4) and t1.key1=2;
+
+# index_merge on second table in join
+explain select * from t0,t1 where t0.key1 = 5 and
+ (t1.key1 = t0.key1 or t1.key8 = t0.key1);
+
+# Fix for bug#1974
+explain select * from t0,t1 where t0.key1 < 3 and
+ (t1.key1 = t0.key1 or t1.key8 = t0.key1);
+
+# index_merge inside union
+explain select * from t1 where key1=3 or key2=4
+ union select * from t1 where key1<4 or key3=5;
+
+# index merge in subselect
+explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5;
+
+# 12. check for long index_merges.
+create table t3 like t0;
+insert into t3 select * from t0;
+alter table t3 add key9 int not null, add index i9(key9);
+alter table t3 add keyA int not null, add index iA(keyA);
+alter table t3 add keyB int not null, add index iB(keyB);
+alter table t3 add keyC int not null, add index iC(keyC);
+update t3 set key9=key1,keyA=key1,keyB=key1,keyC=key1;
+
+explain select * from t3 where
+ key1=1 or key2=2 or key3=3 or key4=4 or
+ key5=5 or key6=6 or key7=7 or key8=8 or
+ key9=9 or keyA=10 or keyB=11 or keyC=12;
+
+select * from t3 where
+ key1=1 or key2=2 or key3=3 or key4=4 or
+ key5=5 or key6=6 or key7=7 or key8=8 or
+ key9=9 or keyA=10 or keyB=11 or keyC=12;
+
+# Test for Bug#3183
+explain select * from t0 where key1 < 3 or key2 < 4;
+select * from t0 where key1 < 3 or key2 < 4;
+
+update t0 set key8=123 where key1 < 3 or key2 < 4;
+select * from t0 where key1 < 3 or key2 < 4;
+
+delete from t0 where key1 < 3 or key2 < 4;
+select * from t0 where key1 < 3 or key2 < 4;
+select count(*) from t0;
+
+# Test for BUG#4177
+drop table t4;
+create table t4 (a int);
+insert into t4 values (1),(4),(3);
+set @save_join_buffer_size=@@join_buffer_size;
+set join_buffer_size= 4000;
+explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+ from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
+ where (A.key1 < 500000 or A.key2 < 3)
+ and (B.key1 < 500000 or B.key2 < 3);
+
+select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+ from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
+ where (A.key1 < 500000 or A.key2 < 3)
+ and (B.key1 < 500000 or B.key2 < 3);
+
+update t0 set key1=1;
+explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+ from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
+ where (A.key1 = 1 or A.key2 = 1)
+ and (B.key1 = 1 or B.key2 = 1);
+
+select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+ from t0 as A force index(i1,i2), t0 as B force index (i1,i2)
+ where (A.key1 = 1 or A.key2 = 1)
+ and (B.key1 = 1 or B.key2 = 1);
+
+alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(200);
+update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
+
+# The next query will not use index i7 in intersection if the OS doesn't
+# support file sizes > 2GB. (ha_myisam::ref_length depends on this and index
+# scan cost estimates depend on ha_myisam::ref_length)
+--replace_column 9 #
+--replace_result "4,4,4,4,4,4,4" X "4,4,4,4,4,4" X "i6,i7" "i6,i7?" "i6" "i6,i7?"
+explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+ from t0 as A, t0 as B
+ where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
+ and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
+
+select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
+ from t0 as A, t0 as B
+ where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
+ and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
+
+set join_buffer_size= @save_join_buffer_size;
+# Test for BUG#4177 ends
+
+drop table t0, t1, t2, t3, t4;
+
diff --git a/mysql-test/t/index_merge_bdb.test b/mysql-test/t/index_merge_bdb.test
new file mode 100644
index 00000000000..c49e6ab3175
--- /dev/null
+++ b/mysql-test/t/index_merge_bdb.test
@@ -0,0 +1,52 @@
+#
+# 2-sweeps read Index_merge test
+#
+-- source include/have_bdb.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (
+ pk int primary key,
+ key1 int,
+ key2 int,
+ filler char(200),
+ filler2 char(200),
+ index(key1),
+ index(key2)
+) engine=bdb;
+
+
+--disable_query_log
+let $1=1000;
+while ($1)
+{
+ eval insert into t1 values($1, $1, $1, 'filler-data','filler-data-2');
+ dec $1;
+}
+--enable_query_log
+
+select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 );
+
+set @maxv=1000;
+
+select * from t1 where
+ (pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+ or key1=18 or key1=60;
+
+select * from t1 where
+ (pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+ or key1 < 3 or key1 > @maxv-11;
+
+select * from t1 where
+ (pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+ or
+ (key1 < 5) or (key1 > 10 and key1 < 15) or (key1 >= 50 and key1 < 55 ) or (key1 > @maxv-10);
+
+select * from t1 where
+ (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 )
+ or
+ (key1 < 5) or (key1 > @maxv-10);
+
+drop table t1;
diff --git a/mysql-test/t/index_merge_innodb.test b/mysql-test/t/index_merge_innodb.test
new file mode 100644
index 00000000000..3ed7d44981b
--- /dev/null
+++ b/mysql-test/t/index_merge_innodb.test
@@ -0,0 +1,206 @@
+#
+# Index merge tests
+#
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+create table t1
+(
+ key1 int not null,
+ key2 int not null,
+
+ INDEX i1(key1),
+ INDEX i2(key2)
+) engine=innodb;
+
+--disable_query_log
+let $1=200;
+while ($1)
+{
+ eval insert into t1 values (200-$1, $1);
+ dec $1;
+}
+--enable_query_log
+
+# No primary key
+explain select * from t1 where key1 < 5 or key2 > 197;
+
+select * from t1 where key1 < 5 or key2 > 197;
+
+explain select * from t1 where key1 < 3 or key2 > 195;
+select * from t1 where key1 < 3 or key2 > 195;
+
+# Primary key as case-sensitive string with \0s.
+# also make primary key be longer then max. index length of MyISAM.
+alter table t1 add str1 char (255) not null,
+ add zeroval int not null default 0,
+ add str2 char (255) not null,
+ add str3 char (255) not null;
+
+update t1 set str1='aaa', str2='bbb', str3=concat(key2, '-', key1 div 2, '_' ,if(key1 mod 2 = 0, 'a', 'A'));
+
+alter table t1 add primary key (str1, zeroval, str2, str3);
+
+explain select * from t1 where key1 < 5 or key2 > 197;
+
+select * from t1 where key1 < 5 or key2 > 197;
+
+explain select * from t1 where key1 < 3 or key2 > 195;
+select * from t1 where key1 < 3 or key2 > 195;
+
+# Test for BUG#5401
+drop table t1;
+create table t1 (
+ pk integer not null auto_increment primary key,
+ key1 integer,
+ key2 integer not null,
+ filler char (200),
+ index (key1),
+ index (key2)
+) engine=innodb;
+show warnings;
+--disable_query_log
+let $1=30;
+while ($1)
+{
+ eval insert into t1 (key1, key2, filler) values ($1/4, $1/8, 'filler-data');
+ dec $1;
+}
+--enable_query_log
+explain select pk from t1 where key1 = 1 and key2 = 1;
+select pk from t1 where key2 = 1 and key1 = 1;
+select pk from t1 ignore index(key1,key2) where key2 = 1 and key1 = 1;
+
+# More tests for BUG#5401.
+drop table t1;
+create table t1 (
+ pk int primary key auto_increment,
+ key1a int,
+ key2a int,
+ key1b int,
+ key2b int,
+ dummy1 int,
+ dummy2 int,
+ dummy3 int,
+ dummy4 int,
+ key3a int,
+ key3b int,
+ filler1 char (200),
+ index i1(key1a, key1b),
+ index i2(key2a, key2b),
+ index i3(key3a, key3b)
+) engine=innodb;
+
+create table t2 (a int);
+insert into t2 values (0),(1),(2),(3),(4),(NULL);
+
+insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
+ select A.a, B.a, C.a, D.a, C.a, D.a from t2 A,t2 B,t2 C, t2 D;
+insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
+ select key1a, key1b, key2a, key2b, key3a, key3b from t1;
+insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
+ select key1a, key1b, key2a, key2b, key3a, key3b from t1;
+analyze table t1;
+select count(*) from t1;
+
+explain select count(*) from t1 where
+ key1a = 2 and key1b is null and key2a = 2 and key2b is null;
+
+select count(*) from t1 where
+ key1a = 2 and key1b is null and key2a = 2 and key2b is null;
+
+explain select count(*) from t1 where
+ key1a = 2 and key1b is null and key3a = 2 and key3b is null;
+
+select count(*) from t1 where
+ key1a = 2 and key1b is null and key3a = 2 and key3b is null;
+
+drop table t1,t2;
+
+# Test for BUG#8441
+create table t1 (
+ id1 int,
+ id2 date ,
+ index idx2 (id1,id2),
+ index idx1 (id2)
+) engine = innodb;
+insert into t1 values(1,'20040101'), (2,'20040102');
+select * from t1 where id1 = 1 and id2= '20040101';
+drop table t1;
+
+# Test for BUG#12720
+--disable_warnings
+drop view if exists v1;
+--enable_warnings
+CREATE TABLE t1 (
+ `oid` int(11) unsigned NOT NULL auto_increment,
+ `fk_bbk_niederlassung` int(11) unsigned NOT NULL,
+ `fk_wochentag` int(11) unsigned NOT NULL,
+ `uhrzeit_von` time NOT NULL COMMENT 'HH:MM',
+ `uhrzeit_bis` time NOT NULL COMMENT 'HH:MM',
+ `geloescht` tinyint(4) NOT NULL,
+ `version` int(5) NOT NULL,
+ PRIMARY KEY (`oid`),
+ KEY `fk_bbk_niederlassung` (`fk_bbk_niederlassung`),
+ KEY `fk_wochentag` (`fk_wochentag`),
+ KEY `ix_version` (`version`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+insert into t1 values
+(1, 38, 1, '08:00:00', '13:00:00', 0, 1),
+(2, 38, 2, '08:00:00', '13:00:00', 0, 1),
+(3, 38, 3, '08:00:00', '13:00:00', 0, 1),
+(4, 38, 4, '08:00:00', '13:00:00', 0, 1),
+(5, 38, 5, '08:00:00', '13:00:00', 0, 1),
+(6, 38, 5, '08:00:00', '13:00:00', 1, 2),
+(7, 38, 3, '08:00:00', '13:00:00', 1, 2),
+(8, 38, 1, '08:00:00', '13:00:00', 1, 2),
+(9, 38, 2, '08:00:00', '13:00:00', 1, 2),
+(10, 38, 4, '08:00:00', '13:00:00', 1, 2),
+(11, 38, 1, '08:00:00', '13:00:00', 0, 3),
+(12, 38, 2, '08:00:00', '13:00:00', 0, 3),
+(13, 38, 3, '08:00:00', '13:00:00', 0, 3),
+(14, 38, 4, '08:00:00', '13:00:00', 0, 3),
+(15, 38, 5, '08:00:00', '13:00:00', 0, 3),
+(16, 38, 4, '08:00:00', '13:00:00', 0, 4),
+(17, 38, 5, '08:00:00', '13:00:00', 0, 4),
+(18, 38, 1, '08:00:00', '13:00:00', 0, 4),
+(19, 38, 2, '08:00:00', '13:00:00', 0, 4),
+(20, 38, 3, '08:00:00', '13:00:00', 0, 4),
+(21, 7, 1, '08:00:00', '13:00:00', 0, 1),
+(22, 7, 2, '08:00:00', '13:00:00', 0, 1),
+(23, 7, 3, '08:00:00', '13:00:00', 0, 1),
+(24, 7, 4, '08:00:00', '13:00:00', 0, 1),
+(25, 7, 5, '08:00:00', '13:00:00', 0, 1);
+
+create view v1 as
+select
+ zeit1.oid AS oid,
+ zeit1.fk_bbk_niederlassung AS fk_bbk_niederlassung,
+ zeit1.fk_wochentag AS fk_wochentag,
+ zeit1.uhrzeit_von AS uhrzeit_von,
+ zeit1.uhrzeit_bis AS uhrzeit_bis,
+ zeit1.geloescht AS geloescht,
+ zeit1.version AS version
+from
+ t1 zeit1
+where
+(zeit1.version =
+ (select max(zeit2.version) AS `max(version)`
+ from t1 zeit2
+ where
+ ((zeit1.fk_bbk_niederlassung = zeit2.fk_bbk_niederlassung) and
+ (zeit1.fk_wochentag = zeit2.fk_wochentag) and
+ (zeit1.uhrzeit_von = zeit2.uhrzeit_von) and
+ (zeit1.uhrzeit_bis = zeit2.uhrzeit_bis)
+ )
+ )
+)
+and (zeit1.geloescht = 0);
+
+select * from v1 where oid = 21;
+drop view v1;
+drop table t1;
diff --git a/mysql-test/t/index_merge_innodb2.test b/mysql-test/t/index_merge_innodb2.test
new file mode 100644
index 00000000000..ec4ea672bc1
--- /dev/null
+++ b/mysql-test/t/index_merge_innodb2.test
@@ -0,0 +1,52 @@
+#
+# 2-sweeps read Index_merge test
+#
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (
+ pk int primary key,
+ key1 int,
+ key2 int,
+ filler char(200),
+ filler2 char(200),
+ index(key1),
+ index(key2)
+) engine=innodb;
+
+
+--disable_query_log
+let $1=1000;
+while ($1)
+{
+ eval insert into t1 values($1, $1, $1, 'filler-data','filler-data-2');
+ dec $1;
+}
+--enable_query_log
+
+select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 );
+
+set @maxv=1000;
+
+select * from t1 where
+ (pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+ or key1=18 or key1=60;
+
+select * from t1 where
+ (pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+ or key1 < 3 or key1 > @maxv-11;
+
+select * from t1 where
+ (pk < 5) or (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 ) or (pk > @maxv-10)
+ or
+ (key1 < 5) or (key1 > 10 and key1 < 15) or (key1 >= 50 and key1 < 55 ) or (key1 > @maxv-10);
+
+select * from t1 where
+ (pk > 10 and pk < 15) or (pk >= 50 and pk < 55 )
+ or
+ (key1 < 5) or (key1 > @maxv-10);
+
+drop table t1;
diff --git a/mysql-test/t/index_merge_ror.test b/mysql-test/t/index_merge_ror.test
new file mode 100644
index 00000000000..48fe5526f11
--- /dev/null
+++ b/mysql-test/t/index_merge_ror.test
@@ -0,0 +1,252 @@
+#
+# ROR-index_merge tests.
+#
+--disable_warnings
+drop table if exists t0,t1,t2;
+--enable_warnings
+--disable_query_log
+create table t1
+(
+ /* Field names reflect value(rowid) distribution, st=STairs, swt= SaWTooth */
+ st_a int not null default 0,
+ swt1a int not null default 0,
+ swt2a int not null default 0,
+
+ st_b int not null default 0,
+ swt1b int not null default 0,
+ swt2b int not null default 0,
+
+ /* fields/keys for row retrieval tests */
+ key1 int,
+ key2 int,
+ key3 int,
+ key4 int,
+
+ /* make rows much bigger then keys */
+ filler1 char (200),
+ filler2 char (200),
+ filler3 char (200),
+ filler4 char (200),
+ filler5 char (200),
+ filler6 char (200),
+
+ /* order of keys is important */
+ key sta_swt12a(st_a,swt1a,swt2a),
+ key sta_swt1a(st_a,swt1a),
+ key sta_swt2a(st_a,swt2a),
+ key sta_swt21a(st_a,swt2a,swt1a),
+
+ key st_a(st_a),
+ key stb_swt1a_2b(st_b,swt1b,swt2a),
+ key stb_swt1b(st_b,swt1b),
+ key st_b(st_b),
+
+ key(key1),
+ key(key2),
+ key(key3),
+ key(key4)
+) ;
+
+# Fill table
+create table t0 as select * from t1;
+let $cnt=1000;
+while ($cnt)
+{
+ eval insert into t0 values (1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 'data1', 'data2', 'data3', 'data4', 'data5', 'data6');
+ dec $cnt;
+}
+
+alter table t1 disable keys;
+let $1=4;
+while ($1)
+{
+ let $2=4;
+ while ($2)
+ {
+ let $3=4;
+ while ($3)
+ {
+ eval insert into t1 select $1, $2, $3, $1 ,$2, $3, key1, key2, key3, key4, filler1, filler2, filler3, filler4, filler5, filler6 from t0;
+ dec $3;
+ }
+ dec $2;
+ }
+ dec $1;
+}
+
+# Row retrieval tests
+# -1 is used for values 'out of any range we are using'
+# insert enough rows for index intersection to be used for (key1,key2)
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 100, 100,'key1-key2-key3-key4');
+let $cnt=400;
+while ($cnt)
+{
+ eval insert into t1 (key1, key2, key3, key4, filler1) values (100, -1, 100, -1,'key1-key3');
+ dec $cnt;
+}
+let $cnt=400;
+while ($cnt)
+{
+ eval insert into t1 (key1, key2, key3, key4, filler1) values (-1, 100, -1, 100,'key2-key4');
+ dec $cnt;
+}
+alter table t1 enable keys;
+--enable_query_log
+select count(*) from t1;
+
+# One row results tests for cases where a single row matches all conditions
+explain select key1,key2 from t1 where key1=100 and key2=100;
+select key1,key2 from t1 where key1=100 and key2=100;
+
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+
+# Several-rows results
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, -1, -1, 'key1-key2');
+insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 100, 100, 'key4-key3');
+
+# ROR-intersection, not covering
+explain select key1,key2,filler1 from t1 where key1=100 and key2=100;
+select key1,key2,filler1 from t1 where key1=100 and key2=100;
+
+# ROR-intersection, covering
+explain select key1,key2 from t1 where key1=100 and key2=100;
+select key1,key2 from t1 where key1=100 and key2=100;
+
+# ROR-union of ROR-intersections
+explain select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+
+# 3-way ROR-intersection
+explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
+select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
+
+# ROR-union(ROR-intersection, ROR-range)
+insert into t1 (key1,key2,key3,key4,filler1) values (101,101,101,101, 'key1234-101');
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
+
+# Run some ROR updates/deletes
+select key1,key2, filler1 from t1 where key1=100 and key2=100;
+update t1 set filler1='to be deleted' where key1=100 and key2=100;
+update t1 set key1=200,key2=200 where key1=100 and key2=100;
+delete from t1 where key1=200 and key2=200;
+select key1,key2,filler1 from t1 where key2=100 and key2=200;
+
+# ROR-union(ROR-intersection) with one of ROR-intersection giving empty
+# results
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+
+delete from t1 where key3=100 and key4=100;
+
+# ROR-union with all ROR-intersections giving empty results
+explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+
+# ROR-intersection with empty result
+explain select key1,key2 from t1 where key1=100 and key2=100;
+select key1,key2 from t1 where key1=100 and key2=100;
+
+# ROR-union tests with various cases.
+# All scans returning duplicate rows:
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-1');
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-2');
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-3');
+
+explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+
+insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, -1, 200,'key4');
+
+explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+
+insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 200, -1,'key3');
+
+explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
+
+##
+## Optimizer tests
+##
+
+# Check that the shortest key is used for ROR-intersection, covering and non-covering.
+explain select * from t1 where st_a=1 and st_b=1;
+explain select st_a,st_b from t1 where st_a=1 and st_b=1;
+
+# Check if "ingore index" syntax works
+explain select st_a from t1 ignore index (st_a) where st_a=1 and st_b=1;
+
+# Do many tests
+# Check that keys that don't improve selectivity are skipped.
+#
+
+# Different value on 32 and 64 bit
+--replace_result sta_swt12a sta_swt21a sta_swt12a, sta_swt12a,
+explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1;
+
+explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1;
+
+explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
+
+explain select * from t1 ignore index (sta_swt21a, stb_swt1a_2b)
+ where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
+
+explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b)
+ where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
+
+explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b, stb_swt1b)
+ where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
+
+explain select * from t1
+ where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1;
+
+explain select * from t1
+ where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
+
+explain select st_a from t1
+ where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
+
+explain select st_a from t1
+ where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
+
+drop table t0,t1;
+
+# 'Partially' covered fields test
+
+create table t2 (
+ a char(10),
+ b char(10),
+ filler1 char(255),
+ filler2 char(255),
+ key(a(5)),
+ key(b(5))
+);
+
+--disable_query_log
+let $1=8;
+while ($1)
+{
+ eval insert into t2 values (repeat(char($1+64), 8),repeat(char($1+64), 8),'filler1', 'filler2');
+ dec $1;
+}
+insert into t2 select * from t2;
+insert into t2 select * from t2;
+--enable_query_log
+
+# The table row buffer is reused. Fill it with rows that don't match.
+select count(a) from t2 where a='BBBBBBBB';
+select count(a) from t2 where b='BBBBBBBB';
+
+# BUG#1:
+--replace_result a a_or_b b a_or_b
+explain select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
+select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
+select count(a) from t2 ignore index(a,b) where a='AAAAAAAA' and b='AAAAAAAA';
+
+insert into t2 values ('ab', 'ab', 'uh', 'oh');
+explain select a from t2 where a='ab';
+drop table t2;
diff --git a/mysql-test/t/index_merge_ror_cpk.test b/mysql-test/t/index_merge_ror_cpk.test
new file mode 100644
index 00000000000..94abf395d0a
--- /dev/null
+++ b/mysql-test/t/index_merge_ror_cpk.test
@@ -0,0 +1,111 @@
+#
+# Clustered PK ROR-index_merge tests
+#
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1
+(
+ pk1 int not null,
+ pk2 int not null,
+
+ key1 int not null,
+ key2 int not null,
+
+ pktail1ok int not null,
+ pktail2ok int not null,
+ pktail3bad int not null,
+ pktail4bad int not null,
+ pktail5bad int not null,
+
+ pk2copy int not null,
+ badkey int not null,
+
+ filler1 char (200),
+ filler2 char (200),
+ key (key1),
+ key (key2),
+
+ /* keys with tails from CPK members */
+ key (pktail1ok, pk1),
+ key (pktail2ok, pk1, pk2),
+ key (pktail3bad, pk2, pk1),
+ key (pktail4bad, pk1, pk2copy),
+ key (pktail5bad, pk1, pk2, pk2copy),
+
+ primary key (pk1, pk2)
+) engine=innodb;
+
+--disable_query_log
+set autocommit=0;
+let $1=10000;
+while ($1)
+{
+ eval insert into t1 values ($1 div 10,$1 mod 100, $1/100,$1/100, $1/100,$1/100,$1/100,$1/100,$1/100, $1 mod 100, $1/1000,'filler-data-$1','filler2');
+ dec $1;
+}
+set autocommit=1;
+--enable_query_log
+
+# Verify that range scan on CPK is ROR
+# (use index_intersection because it is impossible to check that for index union)
+explain select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
+# CPK scan + 1 ROR range scan is a special case
+select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
+
+# Verify that CPK fields are considered to be covered by index scans
+explain select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
+select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
+
+# Verify that CPK is always used for index intersection scans
+# (this is because it is used as a filter, not for retrieval)
+explain select * from t1 where badkey=1 and key1=10;
+--replace_result 38 ROWS 37 ROWS
+explain select * from t1 where pk1 < 7500 and key1 = 10;
+
+# Verify that keys with 'tails' of PK members are ok.
+explain select * from t1 where pktail1ok=1 and key1=10;
+explain select * from t1 where pktail2ok=1 and key1=10;
+
+select ' The following is actually a deficiency, it uses sort_union currently:' as 'note:';
+explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10;
+
+# The expected rows differs a bit from platform to platform
+--replace_result 98 ROWS 99 ROWS
+explain select * from t1 where pktail3bad=1 and key1=10;
+explain select * from t1 where pktail4bad=1 and key1=10;
+explain select * from t1 where pktail5bad=1 and key1=10;
+
+# Test for problem with innodb key values prefetch buffer:
+explain select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
+select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
+
+drop table t1;
+# Testcase for BUG#4984
+create table t1
+(
+ RUNID varchar(22),
+ SUBMITNR varchar(5),
+ ORDERNR char(1) ,
+ PROGRAMM varchar(8),
+ TESTID varchar(4),
+ UCCHECK char(1),
+ ETEXT varchar(80),
+ ETEXT_TYPE char(1),
+ INFO char(1),
+ SEVERITY tinyint(3),
+ TADIRFLAG char(1),
+ PRIMARY KEY (RUNID,SUBMITNR,ORDERNR,PROGRAMM,TESTID,UCCHECK),
+ KEY `TVERM~KEY` (PROGRAMM,TESTID,UCCHECK)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+update t1 set `ETEXT` = '', `ETEXT_TYPE`='', `INFO`='', `SEVERITY`='', `TADIRFLAG`=''
+WHERE
+ `RUNID`= '' AND `SUBMITNR`= '' AND `ORDERNR`='' AND `PROGRAMM`='' AND
+ `TESTID`='' AND `UCCHECK`='';
+
+drop table t1;
+
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
new file mode 100644
index 00000000000..51cca0a3db1
--- /dev/null
+++ b/mysql-test/t/information_schema.test
@@ -0,0 +1,716 @@
+# This test uses grants, which can't get tested for embedded server
+-- source include/not_embedded.inc
+
+# Test for information_schema.schemata &
+# show databases
+
+--disable_warnings
+DROP TABLE IF EXISTS t0,t1,t2,t3,t5;
+--enable_warnings
+
+
+show variables where variable_name like "skip_show_database";
+grant select, update, execute on test.* to mysqltest_2@localhost;
+grant select, update on test.* to mysqltest_1@localhost;
+create user mysqltest_3@localhost;
+create user mysqltest_3;
+
+
+select * from information_schema.SCHEMATA where schema_name > 'm';
+select schema_name from information_schema.schemata;
+show databases like 't%';
+show databases;
+show databases where `database` = 't%';
+
+# Test for information_schema.tables &
+# show tables
+
+create database mysqltest;
+create table mysqltest.t1(a int, b VARCHAR(30), KEY string_data (b));
+create table test.t2(a int);
+create table t3(a int, KEY a_data (a));
+create table mysqltest.t4(a int);
+create table t5 (id int auto_increment primary key);
+insert into t5 values (10);
+create view v1 (c) as select table_name from information_schema.TABLES;
+select * from v1;
+
+select c,table_name from v1
+inner join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+
+select c,table_name from v1
+left join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+
+select c, v2.table_name from v1
+right join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+
+select table_name from information_schema.TABLES
+where table_schema = "mysqltest" and table_name like "t%";
+
+select * from information_schema.STATISTICS where TABLE_SCHEMA = "mysqltest";
+show keys from t3 where Key_name = "a_data";
+
+show tables like 't%';
+--replace_column 8 # 12 # 13 #
+show table status;
+show full columns from t3 like "a%";
+show full columns from mysql.db like "Insert%";
+show full columns from v1;
+select * from information_schema.COLUMNS where table_name="t1"
+and column_name= "a";
+show columns from mysqltest.t1 where field like "%a%";
+
+create view mysqltest.v1 (c) as select a from mysqltest.t1;
+grant select (a) on mysqltest.t1 to mysqltest_2@localhost;
+grant select on mysqltest.v1 to mysqltest_3;
+connect (user3,localhost,mysqltest_2,,);
+connection user3;
+select table_name, column_name, privileges from information_schema.columns
+where table_schema = 'mysqltest' and table_name = 't1';
+show columns from mysqltest.t1;
+connect (user4,localhost,mysqltest_3,,mysqltest);
+connection user4;
+select table_name, column_name, privileges from information_schema.columns
+where table_schema = 'mysqltest' and table_name = 'v1';
+connection default;
+
+drop view v1, mysqltest.v1;
+drop tables mysqltest.t4, mysqltest.t1, t2, t3, t5;
+drop database mysqltest;
+
+# Test for information_schema.CHARACTER_SETS &
+# SHOW CHARACTER SET
+
+select * from information_schema.CHARACTER_SETS
+where CHARACTER_SET_NAME like 'latin1%';
+SHOW CHARACTER SET LIKE 'latin1%';
+SHOW CHARACTER SET WHERE charset like 'latin1%';
+
+# Test for information_schema.COLLATIONS &
+# SHOW COLLATION
+
+select * from information_schema.COLLATIONS
+where COLLATION_NAME like 'latin1%';
+SHOW COLLATION LIKE 'latin1%';
+SHOW COLLATION WHERE collation like 'latin1%';
+
+select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY
+where COLLATION_NAME like 'latin1%';
+
+# Test for information_schema.ROUTINES &
+#
+
+--disable_warnings
+drop procedure if exists sel2;
+drop function if exists sub1;
+drop function if exists sub2;
+--enable_warnings
+
+create function sub1(i int) returns int
+ return i+1;
+delimiter |;
+create procedure sel2()
+begin
+ select * from t1;
+ select * from t2;
+end|
+delimiter ;|
+
+#
+# Bug#7222 information_schema: errors in "routines"
+#
+select parameter_style, sql_data_access, dtd_identifier
+from information_schema.routines;
+
+--replace_column 5 # 6 #
+show procedure status;
+--replace_column 5 # 6 #
+show function status;
+select a.ROUTINE_NAME from information_schema.ROUTINES a,
+information_schema.SCHEMATA b where
+a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
+--replace_column 3 #
+explain select a.ROUTINE_NAME from information_schema.ROUTINES a,
+information_schema.SCHEMATA b where
+a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
+
+select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a,
+mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1;
+select count(*) from information_schema.ROUTINES;
+
+connect (user1,localhost,mysqltest_1,,);
+connection user1;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+--error 1305
+show create function sub1;
+connection user3;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+connection default;
+grant all privileges on test.* to mysqltest_1@localhost;
+connect (user2,localhost,mysqltest_1,,);
+connection user2;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+create function sub2(i int) returns int
+ return i+1;
+select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
+show create procedure sel2;
+show create function sub1;
+show create function sub2;
+--replace_column 5 # 6 #
+show function status like "sub2";
+connection default;
+disconnect user1;
+drop function sub2;
+show create procedure sel2;
+
+#
+# Test for views
+#
+create view v0 (c) as select schema_name from information_schema.schemata;
+select * from v0;
+--replace_column 3 #
+explain select * from v0;
+create view v1 (c) as select table_name from information_schema.tables
+where table_name="v1";
+select * from v1;
+create view v2 (c) as select column_name from information_schema.columns
+where table_name="v2";
+select * from v2;
+create view v3 (c) as select CHARACTER_SET_NAME from information_schema.character_sets
+where CHARACTER_SET_NAME like "latin1%";
+select * from v3;
+create view v4 (c) as select COLLATION_NAME from information_schema.collations
+where COLLATION_NAME like "latin1%";
+select * from v4;
+show keys from v4;
+select * from information_schema.views where TABLE_NAME like "v%";
+drop view v0, v1, v2, v3, v4;
+
+#
+# Test for privileges tables
+#
+create table t1 (a int);
+grant select,update,insert on t1 to mysqltest_1@localhost;
+grant select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
+grant all on test.* to mysqltest_1@localhost with grant option;
+select * from information_schema.USER_PRIVILEGES where grantee like '%mysqltest_1%';
+select * from information_schema.SCHEMA_PRIVILEGES where grantee like '%mysqltest_1%';
+select * from information_schema.TABLE_PRIVILEGES where grantee like '%mysqltest_1%';
+select * from information_schema.COLUMN_PRIVILEGES where grantee like '%mysqltest_1%';
+delete from mysql.user where user like 'mysqltest%';
+delete from mysql.db where user like 'mysqltest%';
+delete from mysql.tables_priv where user like 'mysqltest%';
+delete from mysql.columns_priv where user like 'mysqltest%';
+flush privileges;
+drop table t1;
+
+
+#
+# Test for KEY_COLUMN_USAGE & TABLE_CONSTRAINTS tables
+#
+
+create table t1 (a int null, primary key(a));
+alter table t1 add constraint constraint_1 unique (a);
+alter table t1 add constraint unique key_1(a);
+alter table t1 add constraint constraint_2 unique key_2(a);
+show create table t1;
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_SCHEMA= "test";
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_SCHEMA= "test";
+
+connection user2;
+select table_name from information_schema.TABLES where table_schema like "test%";
+select table_name,column_name from information_schema.COLUMNS where table_schema like "test%";
+select ROUTINE_NAME from information_schema.ROUTINES;
+disconnect user2;
+connection default;
+delete from mysql.user where user='mysqltest_1';
+drop table t1;
+drop procedure sel2;
+drop function sub1;
+
+create table t1(a int);
+create view v1 (c) as select a from t1 with check option;
+create view v2 (c) as select a from t1 WITH LOCAL CHECK OPTION;
+create view v3 (c) as select a from t1 WITH CASCADED CHECK OPTION;
+select * from information_schema.views;
+grant select (a) on test.t1 to joe@localhost with grant option;
+select * from INFORMATION_SCHEMA.COLUMN_PRIVILEGES;
+select * from INFORMATION_SCHEMA.TABLE_PRIVILEGES;
+drop view v1, v2, v3;
+drop table t1;
+delete from mysql.user where user='joe';
+delete from mysql.db where user='joe';
+delete from mysql.tables_priv where user='joe';
+delete from mysql.columns_priv where user='joe';
+flush privileges;
+
+# QQ This results in NULLs instead of the version numbers when
+# QQ a LOCK TABLES is in effect when selecting from
+# QQ information_schema.tables.
+
+--disable_parsing # until bug is fixed
+delimiter //;
+create procedure px5 ()
+begin
+declare v int;
+declare c cursor for select version from
+information_schema.tables where table_schema <> 'information_schema';
+open c;
+fetch c into v;
+select v;
+close c;
+end;//
+
+call px5()//
+call px5()//
+delimiter ;//
+select sql_mode from information_schema.ROUTINES;
+drop procedure px5;
+--enable_parsing
+
+create table t1 (a int not null auto_increment,b int, primary key (a));
+insert into t1 values (1,1),(NULL,3),(NULL,4);
+select AUTO_INCREMENT from information_schema.tables where table_name = 't1';
+drop table t1;
+
+create table t1 (s1 int);
+insert into t1 values (0),(9),(0);
+select s1 from t1 where s1 in (select version from
+information_schema.tables) union select version from
+information_schema.tables;
+drop table t1;
+
+SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
+set names latin2;
+SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
+set names latin1;
+
+create table t1 select * from information_schema.CHARACTER_SETS
+where CHARACTER_SET_NAME like "latin1";
+select * from t1;
+alter table t1 default character set utf8;
+show create table t1;
+drop table t1;
+
+create view v1 as select * from information_schema.TABLES;
+drop view v1;
+create table t1(a NUMERIC(5,3), b NUMERIC(5,1), c float(5,2),
+ d NUMERIC(6,4), e float, f DECIMAL(6,3), g int(11), h DOUBLE(10,3),
+ i DOUBLE);
+select COLUMN_NAME,COLUMN_TYPE, CHARACTER_MAXIMUM_LENGTH,
+ CHARACTER_OCTET_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE
+from information_schema.columns where table_name= 't1';
+drop table t1;
+
+create table t115 as select table_name, column_name, column_type
+from information_schema.columns where table_name = 'proc';
+select * from t115;
+drop table t115;
+
+delimiter //;
+create procedure p108 () begin declare c cursor for select data_type
+from information_schema.columns; open c; open c; end;//
+--error 1325
+call p108()//
+delimiter ;//
+drop procedure p108;
+
+create view v1 as select A1.table_name from information_schema.TABLES A1
+where table_name= "user";
+select * from v1;
+drop view v1;
+
+create view vo as select 'a' union select 'a';
+show index from vo;
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_NAME= "vo";
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_NAME= "vo";
+drop view vo;
+
+select TABLE_NAME,TABLE_TYPE,ENGINE
+from information_schema.tables
+where table_schema='information_schema' limit 2;
+show tables from information_schema like "T%";
+
+--error 1044
+create database information_schema;
+use information_schema;
+show full tables like "T%";
+--error 1109
+create table t1(a int);
+use test;
+show tables;
+use information_schema;
+show tables like "T%";
+
+#
+# Bug#7210: information_schema: can't access when table-name = reserved word
+#
+select table_name from tables where table_name='user';
+select column_name, privileges from columns
+where table_name='user' and column_name like '%o%';
+
+#
+# Bug#7212: information_schema: "Can't find file" errors if storage engine gone
+# Bug#7211: information_schema: crash if bad view
+#
+use test;
+create function sub1(i int) returns int
+ return i+1;
+create table t1(f1 int);
+create view t2 (c) as select f1 from t1;
+create view t3 (c) as select sub1(1);
+create table t4(f1 int, KEY f1_key (f1));
+drop table t1;
+drop function sub1;
+select table_name from information_schema.views
+where table_schema='test';
+select table_name from information_schema.views
+where table_schema='test';
+select column_name from information_schema.columns
+where table_schema='test';
+select index_name from information_schema.statistics where table_schema='test';
+select constraint_name from information_schema.table_constraints
+where table_schema='test';
+drop view t2;
+drop view t3;
+drop table t4;
+
+#
+# Bug#7213: information_schema: redundant non-standard TABLE_NAMES table
+#
+--error 1109
+select * from information_schema.table_names;
+
+#
+# Bug#2719 information_schema: errors in "columns"
+#
+select column_type from information_schema.columns
+where table_schema="information_schema" and table_name="COLUMNS" and
+(column_name="character_set_name" or column_name="collation_name");
+
+#
+# Bug#2718 information_schema: errors in "tables"
+#
+select TABLE_ROWS from information_schema.tables where
+table_schema="information_schema" and table_name="COLUMNS";
+select table_type from information_schema.tables
+where table_schema="mysql" and table_name="user";
+
+# test for 'show open tables ... where'
+show open tables where `table` like "user";
+# test for 'show status ... where'
+show status where variable_name like "%database%";
+# test for 'show variables ... where'
+show variables where variable_name like "skip_show_databas";
+
+#
+# Bug #7981:SHOW GLOBAL STATUS crashes server
+#
+# We don't actually care about the value, just that it doesn't crash.
+--replace_column 2 #
+show global status like "Threads_running";
+
+#
+# Bug #7915 crash,JOIN VIEW, subquery,
+# SELECT .. FROM INFORMATION_SCHEMA.COLUMNS
+#
+create table t1(f1 int);
+create table t2(f2 int);
+create view v1 as select * from t1, t2;
+set @got_val= (select count(*) from information_schema.columns);
+drop view v1;
+drop table t1, t2;
+
+#
+# Bug #7476: crash on SELECT * FROM INFORMATION_SCHEMA.TABLES
+#
+
+CREATE TABLE t_crashme ( f1 BIGINT);
+CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
+CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
+let $tab_count= 65;
+--disable_query_log
+while ($tab_count)
+{
+ EVAL CREATE TABLE t_$tab_count (f1 BIGINT);
+ dec $tab_count ;
+}
+--disable_result_log
+SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES;
+--enable_result_log
+SELECT count(*) FROM INFORMATION_SCHEMA.TABLES;
+let $tab_count= 65;
+while ($tab_count)
+{
+ EVAL DROP TABLE t_$tab_count;
+ dec $tab_count ;
+}
+--enable_query_log
+drop view a2, a1;
+drop table t_crashme;
+
+#
+# Bug #7215 information_schema: columns are longtext instead of varchar
+# Bug #7217 information_schema: columns are varbinary() instead of timestamp
+#
+select table_schema,table_name, column_name from
+information_schema.columns
+where data_type = 'longtext';
+select table_name, column_name, data_type from information_schema.columns
+where data_type = 'datetime';
+
+#
+# Bug #8164 subquery with INFORMATION_SCHEMA.COLUMNS, 100 % CPU
+#
+SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES A
+WHERE NOT EXISTS
+(SELECT * FROM INFORMATION_SCHEMA.COLUMNS B
+ WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA
+ AND A.TABLE_NAME = B.TABLE_NAME);
+
+#
+# Bug #9344 INFORMATION_SCHEMA, wrong content, numeric columns
+#
+
+create table t1
+( x_bigint BIGINT,
+ x_integer INTEGER,
+ x_smallint SMALLINT,
+ x_decimal DECIMAL(5,3),
+ x_numeric NUMERIC(5,3),
+ x_real REAL,
+ x_float FLOAT,
+ x_double_precision DOUBLE PRECISION );
+SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH
+FROM INFORMATION_SCHEMA.COLUMNS
+WHERE TABLE_NAME= 't1';
+drop table t1;
+
+#
+# Bug#10261 INFORMATION_SCHEMA.COLUMNS, incomplete result for non root user
+#
+
+grant select on test.* to mysqltest_4@localhost;
+connect (user4,localhost,mysqltest_4,,);
+connection user4;
+SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS
+where COLUMN_NAME='TABLE_NAME';
+connection default;
+delete from mysql.user where user='mysqltest_4';
+delete from mysql.db where user='mysqltest_4';
+flush privileges;
+
+#
+# Bug #9404 information_schema: Weird error messages
+# with SELECT SUM() ... GROUP BY queries
+#
+SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
+
+
+#
+# TRIGGERS table test
+#
+create table t1 (i int, j int);
+
+delimiter |;
+create trigger trg1 before insert on t1 for each row
+begin
+ if new.j > 10 then
+ set new.j := 10;
+ end if;
+end|
+create trigger trg2 before update on t1 for each row
+begin
+ if old.i % 2 = 0 then
+ set new.j := -1;
+ end if;
+end|
+create trigger trg3 after update on t1 for each row
+begin
+ if new.j = -1 then
+ set @fired:= "Yes";
+ end if;
+end|
+delimiter ;|
+show triggers;
+select * from information_schema.triggers;
+
+drop trigger trg1;
+drop trigger trg2;
+drop trigger trg3;
+drop table t1;
+
+
+#
+# Bug #10964 Information Schema:Authorization check on privilege tables is improper
+#
+
+create database mysqltest;
+create table mysqltest.t1 (f1 int, f2 int);
+create table mysqltest.t2 (f1 int);
+grant select (f1) on mysqltest.t1 to user1@localhost;
+grant select on mysqltest.t2 to user2@localhost;
+grant select on mysqltest.* to user3@localhost;
+grant select on *.* to user4@localhost;
+
+connect (con1,localhost,user1,,mysqltest);
+connect (con2,localhost,user2,,mysqltest);
+connect (con3,localhost,user3,,mysqltest);
+connect (con4,localhost,user4,,);
+connection con1;
+select * from information_schema.column_privileges;
+select * from information_schema.table_privileges;
+select * from information_schema.schema_privileges;
+select * from information_schema.user_privileges;
+show grants;
+connection con2;
+select * from information_schema.column_privileges;
+select * from information_schema.table_privileges;
+select * from information_schema.schema_privileges;
+select * from information_schema.user_privileges;
+show grants;
+connection con3;
+select * from information_schema.column_privileges;
+select * from information_schema.table_privileges;
+select * from information_schema.schema_privileges;
+select * from information_schema.user_privileges;
+show grants;
+connection con4;
+select * from information_schema.column_privileges where grantee like '%user%';
+select * from information_schema.table_privileges where grantee like '%user%';
+select * from information_schema.schema_privileges where grantee like '%user%';
+select * from information_schema.user_privileges where grantee like '%user%';
+show grants;
+connection default;
+drop user user1@localhost, user2@localhost, user3@localhost, user4@localhost;
+use test;
+drop database mysqltest;
+
+#
+# Bug #11055 information_schema: routines.sql_data_access has wrong value
+#
+--disable_warnings
+drop procedure if exists p1;
+drop procedure if exists p2;
+--enable_warnings
+
+create procedure p1 () modifies sql data set @a = 5;
+create procedure p2 () set @a = 5;
+select sql_data_access from information_schema.routines
+where specific_name like 'p%';
+drop procedure p1;
+drop procedure p2;
+
+#
+# Bug #9434 SHOW CREATE DATABASE information_schema;
+#
+show create database information_schema;
+
+#
+# Bug #11057 information_schema: columns table has some questionable contents
+# Bug #12301 information_schema: NUMERIC_SCALE must be 0 for integer columns
+#
+create table t1(f1 LONGBLOB, f2 LONGTEXT);
+select column_name,data_type,CHARACTER_OCTET_LENGTH,
+ CHARACTER_MAXIMUM_LENGTH
+from information_schema.columns
+where table_name='t1';
+drop table t1;
+create table t1(f1 tinyint, f2 SMALLINT, f3 mediumint, f4 int,
+ f5 BIGINT, f6 BIT, f7 bit(64));
+select column_name, NUMERIC_PRECISION, NUMERIC_SCALE
+from information_schema.columns
+where table_name='t1';
+drop table t1;
+
+#
+# Bug #12127 triggers do not show in info_schema before they are used if set to the database
+#
+create table t1 (f1 integer);
+create trigger tr1 after insert on t1 for each row set @test_var=42;
+use information_schema;
+select trigger_schema, trigger_name from triggers where
+trigger_name='tr1';
+use test;
+drop table t1;
+
+#
+# Bug#12518 COLUMN_DEFAULT has wrong value if NOT NULL is set
+#
+create table t1 (a int not null, b int);
+use information_schema;
+select column_name, column_default from columns
+ where table_schema='test' and table_name='t1';
+use test;
+show columns from t1;
+drop table t1;
+
+#
+# Bug #12636: SHOW TABLE STATUS with where condition containing a subquery
+# over information schema
+#
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (b int);
+
+--replace_column 8 # 12 # 13 #
+SHOW TABLE STATUS FROM test
+ WHERE name IN ( SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
+ WHERE TABLE_SCHEMA='test' AND TABLE_TYPE='BASE TABLE');
+
+DROP TABLE t1,t2;
+
+#
+# Bug #12905 show fields from view behaving erratically with current database
+#
+create table t1(f1 int);
+create view v1 (c) as select f1 from t1;
+connect (con5,localhost,root,,*NO-ONE*);
+select database();
+show fields from test.v1;
+connection default;
+drop view v1;
+drop table t1;
+
+#
+# Bug #9846 Inappropriate error displayed while dropping table from 'INFORMATION_SCHEMA'
+#
+--error 1044
+alter database information_schema;
+--error 1044
+drop database information_schema;
+--error 1044
+drop table information_schema.tables;
+--error 1044
+alter table information_schema.tables;
+#
+# Bug #9683 INFORMATION_SCH: Creation of temporary table allowed in Information_schema DB
+#
+use information_schema;
+--error 1044
+create temporary table schemata(f1 char(10));
+#
+# Bug #10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA
+#
+delimiter |;
+--error 1044
+CREATE PROCEDURE p1 ()
+BEGIN
+ SELECT 'foo' FROM DUAL;
+END |
+delimiter ;|
+select ROUTINE_NAME from routines;
+#
+# Bug #10734 Grant of privileges other than 'select' and 'create view' should fail on schema
+#
+--error 1044
+grant all on information_schema.* to 'user1'@'localhost';
+--error 1044
+grant select on information_schema.* to 'user1'@'localhost';
diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test
new file mode 100644
index 00000000000..efb738d682c
--- /dev/null
+++ b/mysql-test/t/information_schema_db.test
@@ -0,0 +1,11 @@
+-- source include/testdb_only.inc
+
+use INFORMATION_SCHEMA;
+--replace_result Tables_in_INFORMATION_SCHEMA Tables_in_information_schema
+show tables;
+--replace_result 'Tables_in_INFORMATION_SCHEMA (T%)' 'Tables_in_information_schema (T%)'
+show tables from INFORMATION_SCHEMA like 'T%';
+create database `inf%`;
+use `inf%`;
+show tables;
+drop database `inf%`;
diff --git a/mysql-test/t/information_schema_inno.test b/mysql-test/t/information_schema_inno.test
new file mode 100644
index 00000000000..dd7015bfd9a
--- /dev/null
+++ b/mysql-test/t/information_schema_inno.test
@@ -0,0 +1,23 @@
+-- source include/have_innodb.inc
+--disable_warnings
+DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
+
+#
+# Test for KEY_COLUMN_USAGE & TABLE_CONSTRAINTS tables
+#
+
+CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id, id),
+FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE CASCADE,
+FOREIGN KEY (t1_id) REFERENCES t1(id) ON UPDATE CASCADE) ENGINE=INNODB;
+
+CREATE TABLE t3 (id INT PRIMARY KEY, t2_id INT, INDEX par_ind (t2_id),
+FOREIGN KEY (id, t2_id) REFERENCES t2(t1_id, id) ON DELETE CASCADE) ENGINE=INNODB;
+
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_SCHEMA= "test";
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_SCHEMA= "test";
+
+drop table t3, t2, t1;
diff --git a/mysql-test/t/init_connect.test b/mysql-test/t/init_connect.test
index f90d1b8670d..2e3c67a7d38 100644
--- a/mysql-test/t/init_connect.test
+++ b/mysql-test/t/init_connect.test
@@ -19,7 +19,7 @@ connect (con3,localhost,user_1,,);
connection con3;
select @a;
connection con0;
-set global init_connect="create table t1(a char(10));\
+set global init_connect="drop table if exists t1; create table t1(a char(10));\
insert into t1 values ('\0');insert into t1 values('abc')";
connect (con4,localhost,user_1,,);
connection con4;
diff --git a/mysql-test/t/innodb-big.test b/mysql-test/t/innodb-big.test
new file mode 100644
index 00000000000..ade69ffdb45
--- /dev/null
+++ b/mysql-test/t/innodb-big.test
@@ -0,0 +1,46 @@
+#
+# Test some things that takes a long time
+
+-- source include/big_test.inc
+-- source include/have_innodb.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, t3, t4;
+--enable_warnings
+
+#
+# Test test how filesort and buffered-record-reads works with innodb
+#
+
+CREATE TABLE t1 (id INTEGER) ENGINE=MYISAM;
+CREATE TABLE t2 (id INTEGER primary key) ENGINE=INNODB;
+CREATE TABLE t3 (a char(32) primary key,id INTEGER) ENGINE=INNODB;
+CREATE TABLE t4 (a char(32) primary key,id INTEGER) ENGINE=MYISAM;
+
+INSERT INTO t1 (id) VALUES (1);
+INSERT INTO t1 SELECT id+1 FROM t1;
+INSERT INTO t1 SELECT id+2 FROM t1;
+INSERT INTO t1 SELECT id+4 FROM t1;
+INSERT INTO t1 SELECT id+8 FROM t1;
+INSERT INTO t1 SELECT id+16 FROM t1;
+INSERT INTO t1 SELECT id+32 FROM t1;
+INSERT INTO t1 SELECT id+64 FROM t1;
+INSERT INTO t1 SELECT id+128 FROM t1;
+INSERT INTO t1 SELECT id+256 FROM t1;
+INSERT INTO t1 SELECT id+512 FROM t1;
+INSERT INTO t1 SELECT id+1024 FROM t1;
+INSERT INTO t1 SELECT id+2048 FROM t1;
+INSERT INTO t1 SELECT id+4096 FROM t1;
+INSERT INTO t1 SELECT id+8192 FROM t1;
+INSERT INTO t1 SELECT id+16384 FROM t1;
+INSERT INTO t1 SELECT id+32768 FROM t1;
+INSERT INTO t1 SELECT id+65536 FROM t1;
+INSERT INTO t1 SELECT id+131072 FROM t1;
+INSERT INTO t1 SELECT id+262144 FROM t1;
+INSERT INTO t1 SELECT id+524288 FROM t1;
+INSERT INTO t1 SELECT id+1048576 FROM t1;
+INSERT INTO t2 SELECT * FROM t1;
+INSERT INTO t3 SELECT concat(id),id from t2 ORDER BY -id;
+INSERT INTO t4 SELECT * from t3 ORDER BY concat(a);
+select sum(id) from t3;
+drop table t1,t2,t3,t4;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index b966ea5b281..94f33738c8c 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -129,6 +129,32 @@ insert into t1 values (6);
-- error 1062
insert into t1 values (4);
select n from t1;
+set autocommit=0;
+#
+# savepoints
+#
+begin;
+savepoint `my_savepoint`;
+insert into t1 values (7);
+savepoint `savept2`;
+insert into t1 values (3);
+select n from t1;
+savepoint savept3;
+rollback to savepoint savept2;
+--error 1305
+rollback to savepoint savept3;
+rollback to savepoint savept2;
+release savepoint `my_savepoint`;
+select n from t1;
+-- error 1305
+rollback to savepoint `my_savepoint`;
+--error 1305
+rollback to savepoint savept2;
+insert into t1 values (8);
+savepoint sv;
+commit;
+savepoint sv;
+set autocommit=1;
# nop
rollback;
drop table t1;
@@ -415,6 +441,7 @@ set @a:=now();
CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) engine=innodb;
insert into t1 (a) values(1),(2),(3);
select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a;
+select a from t1 natural join t1 as t2 where b >= @a order by a;
update t1 set a=5 where a=1;
select a from t1;
drop table t1;
@@ -560,7 +587,7 @@ insert into mysqltest.t3 values(1);
commit;
drop database mysqltest;
# Don't check error message
---error 12,12
+--error 1049
show tables from mysqltest;
#
@@ -634,9 +661,9 @@ CREATE TABLE t1 (
cname char(15) NOT NULL default '',
carrier_id smallint(6) NOT NULL default '0',
privacy tinyint(4) NOT NULL default '0',
- last_mod_date timestamp(14) NOT NULL,
+ last_mod_date timestamp NOT NULL,
last_mod_id smallint(6) NOT NULL default '0',
- last_app_date timestamp(14) NOT NULL,
+ last_app_date timestamp NOT NULL,
last_app_id smallint(6) default '-1',
version smallint(6) NOT NULL default '0',
assigned_scps int(11) default '0',
@@ -653,9 +680,9 @@ CREATE TABLE t2 (
cname char(15) NOT NULL default '',
carrier_id smallint(6) NOT NULL default '0',
privacy tinyint(4) NOT NULL default '0',
- last_mod_date timestamp(14) NOT NULL,
+ last_mod_date timestamp NOT NULL,
last_mod_id smallint(6) NOT NULL default '0',
- last_app_date timestamp(14) NOT NULL,
+ last_app_date timestamp NOT NULL,
last_app_id smallint(6) default '-1',
version smallint(6) NOT NULL default '0',
assigned_scps int(11) default '0',
@@ -955,7 +982,7 @@ insert into `t3`values ( 1 ) ;
delete t3,t2,t1 from t1,t2,t3 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
--error 1217
update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
---error 1109
+--error 1054
update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
drop table t3,t2,t1;
@@ -998,7 +1025,7 @@ CREATE TABLE t1 (
`id` int(10) unsigned NOT NULL auto_increment,
`id_object` int(10) unsigned default '0',
`id_version` int(10) unsigned NOT NULL default '1',
- label varchar(100) NOT NULL default '',
+ `label` varchar(100) NOT NULL default '',
`description` text,
PRIMARY KEY (`id`),
KEY `id_object` (`id_object`),
@@ -1016,8 +1043,8 @@ CREATE TABLE t2 (
INSERT INTO t2 VALUES("3524", "1"),("3525", "1"),("1794", "4"),("102", "5"),("1822", "6"),("3382", "9");
-SELECT t2.id, t1.label FROM t2 INNER JOIN
-(SELECT t1.id_object as id_object FROM t1 WHERE t1.label LIKE '%test%') AS lbl
+SELECT t2.id, t1.`label` FROM t2 INNER JOIN
+(SELECT t1.id_object as id_object FROM t1 WHERE t1.`label` LIKE '%test%') AS lbl
ON (t2.id = lbl.id_object) INNER JOIN t1 ON (t2.id = t1.id_object);
drop table t1,t2;
@@ -1097,7 +1124,10 @@ show create table t2;
drop table t2;
# Test error handling
---replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ /
+
+# Clean up filename -- embedded server reports whole path without .frm,
+# regular server reports relative path with .frm (argh!)
+--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2
--error 1005
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
@@ -1143,7 +1173,6 @@ delete from t1;
commit;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
-
drop table t1;
#
@@ -1240,3 +1269,216 @@ select min(a) from t1;
select min(b) from t1 where a='8';
drop table t1;
# End of 4.1 tests
+
+#
+# range optimizer problem
+#
+
+create table t1 (x bigint unsigned not null primary key) engine=innodb;
+insert into t1(x) values (0xfffffffffffffff0),(0xfffffffffffffff1);
+select * from t1;
+select count(*) from t1 where x>0;
+select count(*) from t1 where x=0;
+select count(*) from t1 where x<0;
+select count(*) from t1 where x < -16;
+select count(*) from t1 where x = -16;
+explain select count(*) from t1 where x > -16;
+select count(*) from t1 where x > -16;
+select * from t1 where x > -16;
+select count(*) from t1 where x = 18446744073709551601;
+drop table t1;
+
+
+# Test for testable InnoDB status variables. This test
+# uses previous ones(pages_created, rows_deleted, ...).
+show status like "Innodb_buffer_pool_pages_total";
+show status like "Innodb_page_size";
+show status like "Innodb_rows_deleted";
+show status like "Innodb_rows_inserted";
+show status like "Innodb_rows_updated";
+
+# Test for row locks InnoDB status variables.
+show status like "Innodb_row_lock_waits";
+show status like "Innodb_row_lock_current_waits";
+show status like "Innodb_row_lock_time";
+show status like "Innodb_row_lock_time_max";
+show status like "Innodb_row_lock_time_avg";
+
+# Test for innodb_sync_spin_loops variable
+show variables like "innodb_sync_spin_loops";
+set global innodb_sync_spin_loops=1000;
+show variables like "innodb_sync_spin_loops";
+set global innodb_sync_spin_loops=0;
+show variables like "innodb_sync_spin_loops";
+set global innodb_sync_spin_loops=20;
+show variables like "innodb_sync_spin_loops";
+
+# Test for innodb_thread_concurrency variable
+show variables like "innodb_thread_concurrency";
+set global innodb_thread_concurrency=1000;
+show variables like "innodb_thread_concurrency";
+set global innodb_thread_concurrency=0;
+show variables like "innodb_thread_concurrency";
+set global innodb_thread_concurrency=16;
+show variables like "innodb_thread_concurrency";
+
+# Test for innodb_concurrency_tickets variable
+show variables like "innodb_concurrency_tickets";
+set global innodb_concurrency_tickets=1000;
+show variables like "innodb_concurrency_tickets";
+set global innodb_concurrency_tickets=0;
+show variables like "innodb_concurrency_tickets";
+set global innodb_concurrency_tickets=500;
+show variables like "innodb_concurrency_tickets";
+
+# Test for innodb_thread_sleep_delay variable
+show variables like "innodb_thread_sleep_delay";
+set global innodb_thread_sleep_delay=100000;
+show variables like "innodb_thread_sleep_delay";
+set global innodb_thread_sleep_delay=0;
+show variables like "innodb_thread_sleep_delay";
+set global innodb_thread_sleep_delay=10000;
+show variables like "innodb_thread_sleep_delay";
+
+#
+# Test varchar
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=INNODB;
+source include/varchar.inc;
+
+#
+# Some errors/warnings on create
+#
+
+# Clean up filename -- embedded server reports whole path without .frm,
+# regular server reports relative path with .frm (argh!)
+--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t1.frm t1
+--error 1005
+create table t1 (v varchar(65530), key(v));
+create table t1 (v varchar(65536));
+show create table t1;
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+show create table t1;
+drop table t1;
+
+eval set storage_engine=$default;
+
+# InnoDB specific varchar tests
+create table t1 (v varchar(16384)) engine=innodb;
+drop table t1;
+
+#
+# BUG#11039 Wrong key length in min()
+#
+
+create table t1 (a char(1), b char(1), key(a, b)) engine=innodb;
+insert into t1 values ('8', '6'), ('4', '7');
+select min(a) from t1;
+select min(b) from t1 where a='8';
+drop table t1;
+
+#
+# Bug #11080 & #11005 Multi-row REPLACE fails on a duplicate key error
+#
+
+CREATE TABLE t1 ( `a` int(11) NOT NULL auto_increment, `b` int(11) default NULL,PRIMARY KEY (`a`),UNIQUE KEY `b` (`b`)) ENGINE=innodb;
+insert into t1 (b) values (1);
+replace into t1 (b) values (2), (1), (3);
+select * from t1;
+truncate table t1;
+insert into t1 (b) values (1);
+replace into t1 (b) values (2);
+replace into t1 (b) values (1);
+replace into t1 (b) values (3);
+select * from t1;
+drop table t1;
+
+create table t1 (rowid int not null auto_increment, val int not null,primary
+key (rowid), unique(val)) engine=innodb;
+replace into t1 (val) values ('1'),('2');
+replace into t1 (val) values ('1'),('2');
+--error 1062
+insert into t1 (val) values ('1'),('2');
+select * from t1;
+drop table t1;
+
+#
+# Test that update does not change internal auto-increment value
+#
+
+create table t1 (a int not null auto_increment primary key, val int) engine=InnoDB;
+insert into t1 (val) values (1);
+update t1 set a=2 where a=1;
+# We should get the following error because InnoDB does not update the counter
+--error 1062
+insert into t1 (val) values (1);
+select * from t1;
+drop table t1;
+#
+# Bug #10465
+#
+
+--disable_warnings
+CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB;
+--enable_warnings
+INSERT INTO t1 (GRADE) VALUES (151),(252),(343);
+SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300;
+SELECT GRADE FROM t1 WHERE GRADE= 151;
+DROP TABLE t1;
+
+#
+# Bug #12340 multitable delete deletes only one record
+#
+create table t1 (f1 varchar(10), f2 varchar(10), primary key (f1,f2)) engine=innodb;
+create table t2 (f3 varchar(10), f4 varchar(10), key (f4)) engine=innodb;
+insert into t2 values ('aa','cc');
+insert into t1 values ('aa','bb'),('aa','cc');
+delete t1 from t1,t2 where f1=f3 and f4='cc';
+select * from t1;
+drop table t1,t2;
+
+#
+# Test that the slow TRUNCATE implementation resets autoincrement columns
+# (bug #11946)
+#
+
+CREATE TABLE t1 (
+id INTEGER NOT NULL AUTO_INCREMENT, PRIMARY KEY (id)
+) ENGINE=InnoDB;
+
+CREATE TABLE t2 (
+id INTEGER NOT NULL,
+FOREIGN KEY (id) REFERENCES t1 (id)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 (id) VALUES (NULL);
+SELECT * FROM t1;
+TRUNCATE t1;
+INSERT INTO t1 (id) VALUES (NULL);
+SELECT * FROM t1;
+
+# continued from above; test that doing a slow TRUNCATE on a table with 0
+# rows resets autoincrement columns
+DELETE FROM t1;
+TRUNCATE t1;
+INSERT INTO t1 (id) VALUES (NULL);
+SELECT * FROM t1;
+DROP TABLE t2, t1;
+
+-- Test that foreign keys in temporary tables are not accepted (bug #12084)
+CREATE TABLE t1
+(
+ id INT PRIMARY KEY
+) ENGINE=InnoDB;
+
+--error 1005,1005
+CREATE TEMPORARY TABLE t2
+(
+ id INT NOT NULL PRIMARY KEY,
+ b INT,
+ FOREIGN KEY (b) REFERENCES test.t1(id)
+) ENGINE=InnoDB;
+DROP TABLE t1;
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index 0c8252ad479..51d936f5b4f 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
--enable_warnings
create table t1 (a int not null);
@@ -87,6 +87,7 @@ use mysqltest;
create table t1 (c int);
insert into mysqltest.t1 set mysqltest.t1.c = '1';
drop database mysqltest;
+use test;
#
# Test of wrong values for float data (bug #2082)
@@ -94,7 +95,6 @@ drop database mysqltest;
# PS gives sligthly different numbers for max-float/max-double
--disable_ps_protocol
-use test;
create table t1(number int auto_increment primary key, original_value varchar(50), f_double double, f_float float, f_double_7_2 double(7,2), f_float_4_3 float (4,3), f_double_u double unsigned, f_float_u float unsigned, f_double_15_1_u double(15,1) unsigned, f_float_3_1_u float (3,1) unsigned);
set @value= "aa";
@@ -122,15 +122,11 @@ insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@val
--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
+--error 1367
set @value= 1e+1111111111;
-insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
---replace_result e-0 e- e+0 e+
---query_vertical select * from t1 where number =last_insert_id()
-
+--error 1367
set @value= -1e+1111111111;
-insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
---replace_result e-0 e- e+0 e+
---query_vertical select * from t1 where number =last_insert_id()
+
set @value= 1e+111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
@@ -156,3 +152,35 @@ drop table t1;
--enable_ps_protocol
# End of 4.1 tests
+
+#
+# Test automatic result buffering with INSERT INTO t1 ... SELECT ... FROM t1
+#
+
+create table t1(id1 int not null auto_increment primary key, t char(12));
+create table t2(id2 int not null, t char(12));
+create table t3(id3 int not null, t char(12), index(id3));
+disable_query_log;
+let $1 = 100;
+while ($1)
+ {
+ let $2 = 5;
+ eval insert into t1(t) values ('$1');
+ while ($2)
+ {
+ eval insert into t2(id2,t) values ($1,'$2');
+ let $3 = 10;
+ while ($3)
+ {
+ eval insert into t3(id3,t) values ($1,'$2');
+ dec $3;
+ }
+ dec $2;
+ }
+ dec $1;
+ }
+enable_query_log;
+select count(*) from t2;
+insert into t2 select t1.* from t1, t2 t, t3 where t1.id1 = t.id2 and t.id2 = t3.id3;
+select count(*) from t2;
+drop table t1,t2,t3;
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 6fcdef6ab03..7116a25ff39 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -105,9 +105,7 @@ insert into t2 values (2,"t2:2"), (3,"t2:3");
insert into t1 select * from t2;
select * from t1;
# REPLACE .. SELECT is not yet supported by PS
---disable_ps_protocol
replace into t1 select * from t2;
---enable_ps_protocol
select * from t1;
drop table t1,t2;
@@ -198,20 +196,10 @@ insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= a +
#Some error cases
--error 1052
insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b;
---error 1109
+--error 1054
insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b;
---error 1109
+--error 1054
insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b;
drop table t1,t2,t3;
-#
-# Bug #12695 Item_func_isnull::update_used_tables() did not update
-# const_item_cache
-create table t1(f1 varchar(5) key);
-insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
-insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
-insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
-select * from t1;
-drop table t1;
-
# End of 4.1 tests
diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test
index 8038bd7bfe7..eda768be1bc 100644
--- a/mysql-test/t/insert_update.test
+++ b/mysql-test/t/insert_update.test
@@ -1,5 +1,5 @@
--disable_warnings
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1, t2;
--enable_warnings
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
diff --git a/mysql-test/t/isam.test b/mysql-test/t/isam.test
deleted file mode 100644
index 7fa841c11a3..00000000000
--- a/mysql-test/t/isam.test
+++ /dev/null
@@ -1,249 +0,0 @@
--- source include/have_isam.inc
-
---disable_warnings
-drop table if exists t1,t2;
---enable_warnings
-
-#
-# Test possible problem with rows that are about 65535 bytes long
-#
-
-create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)) engine=isam;
-
-let $1=100;
-disable_query_log;
---disable_warnings
-while ($1)
-{
- eval insert into t1 (b) values(repeat(char(65+$1),65540-$1));
- dec $1;
-}
-enable_query_log;
---enable_warnings
-delete from t1 where (a & 1);
-select sum(length(b)) from t1;
-drop table t1;
-
-#
-# Test of auto_increment; The test for BDB tables is in bdb.test
-#
-
-create table t1 (a int not null auto_increment,b int, primary key (a)) engine=isam;
-insert into t1 values (1,1),(NULL,2),(3,3),(NULL,4);
-delete from t1 where a=4 or a=2;
-insert into t1 values (NULL,4),(NULL,5),(6,6);
-select * from t1;
-delete from t1 where a=6;
-#show table status like "t1";
-replace t1 values (3,1);
-replace t1 values (3,3);
-ALTER TABLE t1 add c int;
-insert into t1 values (NULL,6,6);
-select * from t1;
-drop table t1;
-
-#
-# Test of some CREATE TABLE's that should fail
-#
---error 1121
-create table t1 (a int,b text, index(a)) engine=isam;
---error 1073
-create table t1 (a int,b text, index(b)) engine=isam;
---error 1075
-create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) engine=isam;
---error 1121
-create table t1 (ordid int(8), unique (ordid)) engine=isam;
-drop table if exists t1;
-
-#
-# Test of some show commands
-#
-
-create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
-insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
-create table t2 engine=isam select * from t1;
-optimize table t1;
-check table t1,t2;
-repair table t1,t2;
-check table t2,t1;
-lock tables t1 write;
-check table t2,t1;
-show columns from t1;
-show full columns from t1;
-show index from t1;
-drop table t1,t2;
-
-#
-# test of table with huge number of packed fields
-#
-
-create table t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
-int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17
-int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
-i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34
-int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int,
-i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51
-int, i52 int, i53 int, i54 int, i55 int, i56 int, i57 int, i58 int, i59 int,
-i60 int, i61 int, i62 int, i63 int, i64 int, i65 int, i66 int, i67 int, i68
-int, i69 int, i70 int, i71 int, i72 int, i73 int, i74 int, i75 int, i76 int,
-i77 int, i78 int, i79 int, i80 int, i81 int, i82 int, i83 int, i84 int, i85
-int, i86 int, i87 int, i88 int, i89 int, i90 int, i91 int, i92 int, i93 int,
-i94 int, i95 int, i96 int, i97 int, i98 int, i99 int, i100 int, i101 int, i102
-int, i103 int, i104 int, i105 int, i106 int, i107 int, i108 int, i109 int, i110
-int, i111 int, i112 int, i113 int, i114 int, i115 int, i116 int, i117 int, i118
-int, i119 int, i120 int, i121 int, i122 int, i123 int, i124 int, i125 int, i126
-int, i127 int, i128 int, i129 int, i130 int, i131 int, i132 int, i133 int, i134
-int, i135 int, i136 int, i137 int, i138 int, i139 int, i140 int, i141 int, i142
-int, i143 int, i144 int, i145 int, i146 int, i147 int, i148 int, i149 int, i150
-int, i151 int, i152 int, i153 int, i154 int, i155 int, i156 int, i157 int, i158
-int, i159 int, i160 int, i161 int, i162 int, i163 int, i164 int, i165 int, i166
-int, i167 int, i168 int, i169 int, i170 int, i171 int, i172 int, i173 int, i174
-int, i175 int, i176 int, i177 int, i178 int, i179 int, i180 int, i181 int, i182
-int, i183 int, i184 int, i185 int, i186 int, i187 int, i188 int, i189 int, i190
-int, i191 int, i192 int, i193 int, i194 int, i195 int, i196 int, i197 int, i198
-int, i199 int, i200 int, i201 int, i202 int, i203 int, i204 int, i205 int, i206
-int, i207 int, i208 int, i209 int, i210 int, i211 int, i212 int, i213 int, i214
-int, i215 int, i216 int, i217 int, i218 int, i219 int, i220 int, i221 int, i222
-int, i223 int, i224 int, i225 int, i226 int, i227 int, i228 int, i229 int, i230
-int, i231 int, i232 int, i233 int, i234 int, i235 int, i236 int, i237 int, i238
-int, i239 int, i240 int, i241 int, i242 int, i243 int, i244 int, i245 int, i246
-int, i247 int, i248 int, i249 int, i250 int, i251 int, i252 int, i253 int, i254
-int, i255 int, i256 int, i257 int, i258 int, i259 int, i260 int, i261 int, i262
-int, i263 int, i264 int, i265 int, i266 int, i267 int, i268 int, i269 int, i270
-int, i271 int, i272 int, i273 int, i274 int, i275 int, i276 int, i277 int, i278
-int, i279 int, i280 int, i281 int, i282 int, i283 int, i284 int, i285 int, i286
-int, i287 int, i288 int, i289 int, i290 int, i291 int, i292 int, i293 int, i294
-int, i295 int, i296 int, i297 int, i298 int, i299 int, i300 int, i301 int, i302
-int, i303 int, i304 int, i305 int, i306 int, i307 int, i308 int, i309 int, i310
-int, i311 int, i312 int, i313 int, i314 int, i315 int, i316 int, i317 int, i318
-int, i319 int, i320 int, i321 int, i322 int, i323 int, i324 int, i325 int, i326
-int, i327 int, i328 int, i329 int, i330 int, i331 int, i332 int, i333 int, i334
-int, i335 int, i336 int, i337 int, i338 int, i339 int, i340 int, i341 int, i342
-int, i343 int, i344 int, i345 int, i346 int, i347 int, i348 int, i349 int, i350
-int, i351 int, i352 int, i353 int, i354 int, i355 int, i356 int, i357 int, i358
-int, i359 int, i360 int, i361 int, i362 int, i363 int, i364 int, i365 int, i366
-int, i367 int, i368 int, i369 int, i370 int, i371 int, i372 int, i373 int, i374
-int, i375 int, i376 int, i377 int, i378 int, i379 int, i380 int, i381 int, i382
-int, i383 int, i384 int, i385 int, i386 int, i387 int, i388 int, i389 int, i390
-int, i391 int, i392 int, i393 int, i394 int, i395 int, i396 int, i397 int, i398
-int, i399 int, i400 int, i401 int, i402 int, i403 int, i404 int, i405 int, i406
-int, i407 int, i408 int, i409 int, i410 int, i411 int, i412 int, i413 int, i414
-int, i415 int, i416 int, i417 int, i418 int, i419 int, i420 int, i421 int, i422
-int, i423 int, i424 int, i425 int, i426 int, i427 int, i428 int, i429 int, i430
-int, i431 int, i432 int, i433 int, i434 int, i435 int, i436 int, i437 int, i438
-int, i439 int, i440 int, i441 int, i442 int, i443 int, i444 int, i445 int, i446
-int, i447 int, i448 int, i449 int, i450 int, i451 int, i452 int, i453 int, i454
-int, i455 int, i456 int, i457 int, i458 int, i459 int, i460 int, i461 int, i462
-int, i463 int, i464 int, i465 int, i466 int, i467 int, i468 int, i469 int, i470
-int, i471 int, i472 int, i473 int, i474 int, i475 int, i476 int, i477 int, i478
-int, i479 int, i480 int, i481 int, i482 int, i483 int, i484 int, i485 int, i486
-int, i487 int, i488 int, i489 int, i490 int, i491 int, i492 int, i493 int, i494
-int, i495 int, i496 int, i497 int, i498 int, i499 int, i500 int, i501 int, i502
-int, i503 int, i504 int, i505 int, i506 int, i507 int, i508 int, i509 int, i510
-int, i511 int, i512 int, i513 int, i514 int, i515 int, i516 int, i517 int, i518
-int, i519 int, i520 int, i521 int, i522 int, i523 int, i524 int, i525 int, i526
-int, i527 int, i528 int, i529 int, i530 int, i531 int, i532 int, i533 int, i534
-int, i535 int, i536 int, i537 int, i538 int, i539 int, i540 int, i541 int, i542
-int, i543 int, i544 int, i545 int, i546 int, i547 int, i548 int, i549 int, i550
-int, i551 int, i552 int, i553 int, i554 int, i555 int, i556 int, i557 int, i558
-int, i559 int, i560 int, i561 int, i562 int, i563 int, i564 int, i565 int, i566
-int, i567 int, i568 int, i569 int, i570 int, i571 int, i572 int, i573 int, i574
-int, i575 int, i576 int, i577 int, i578 int, i579 int, i580 int, i581 int, i582
-int, i583 int, i584 int, i585 int, i586 int, i587 int, i588 int, i589 int, i590
-int, i591 int, i592 int, i593 int, i594 int, i595 int, i596 int, i597 int, i598
-int, i599 int, i600 int, i601 int, i602 int, i603 int, i604 int, i605 int, i606
-int, i607 int, i608 int, i609 int, i610 int, i611 int, i612 int, i613 int, i614
-int, i615 int, i616 int, i617 int, i618 int, i619 int, i620 int, i621 int, i622
-int, i623 int, i624 int, i625 int, i626 int, i627 int, i628 int, i629 int, i630
-int, i631 int, i632 int, i633 int, i634 int, i635 int, i636 int, i637 int, i638
-int, i639 int, i640 int, i641 int, i642 int, i643 int, i644 int, i645 int, i646
-int, i647 int, i648 int, i649 int, i650 int, i651 int, i652 int, i653 int, i654
-int, i655 int, i656 int, i657 int, i658 int, i659 int, i660 int, i661 int, i662
-int, i663 int, i664 int, i665 int, i666 int, i667 int, i668 int, i669 int, i670
-int, i671 int, i672 int, i673 int, i674 int, i675 int, i676 int, i677 int, i678
-int, i679 int, i680 int, i681 int, i682 int, i683 int, i684 int, i685 int, i686
-int, i687 int, i688 int, i689 int, i690 int, i691 int, i692 int, i693 int, i694
-int, i695 int, i696 int, i697 int, i698 int, i699 int, i700 int, i701 int, i702
-int, i703 int, i704 int, i705 int, i706 int, i707 int, i708 int, i709 int, i710
-int, i711 int, i712 int, i713 int, i714 int, i715 int, i716 int, i717 int, i718
-int, i719 int, i720 int, i721 int, i722 int, i723 int, i724 int, i725 int, i726
-int, i727 int, i728 int, i729 int, i730 int, i731 int, i732 int, i733 int, i734
-int, i735 int, i736 int, i737 int, i738 int, i739 int, i740 int, i741 int, i742
-int, i743 int, i744 int, i745 int, i746 int, i747 int, i748 int, i749 int, i750
-int, i751 int, i752 int, i753 int, i754 int, i755 int, i756 int, i757 int, i758
-int, i759 int, i760 int, i761 int, i762 int, i763 int, i764 int, i765 int, i766
-int, i767 int, i768 int, i769 int, i770 int, i771 int, i772 int, i773 int, i774
-int, i775 int, i776 int, i777 int, i778 int, i779 int, i780 int, i781 int, i782
-int, i783 int, i784 int, i785 int, i786 int, i787 int, i788 int, i789 int, i790
-int, i791 int, i792 int, i793 int, i794 int, i795 int, i796 int, i797 int, i798
-int, i799 int, i800 int, i801 int, i802 int, i803 int, i804 int, i805 int, i806
-int, i807 int, i808 int, i809 int, i810 int, i811 int, i812 int, i813 int, i814
-int, i815 int, i816 int, i817 int, i818 int, i819 int, i820 int, i821 int, i822
-int, i823 int, i824 int, i825 int, i826 int, i827 int, i828 int, i829 int, i830
-int, i831 int, i832 int, i833 int, i834 int, i835 int, i836 int, i837 int, i838
-int, i839 int, i840 int, i841 int, i842 int, i843 int, i844 int, i845 int, i846
-int, i847 int, i848 int, i849 int, i850 int, i851 int, i852 int, i853 int, i854
-int, i855 int, i856 int, i857 int, i858 int, i859 int, i860 int, i861 int, i862
-int, i863 int, i864 int, i865 int, i866 int, i867 int, i868 int, i869 int, i870
-int, i871 int, i872 int, i873 int, i874 int, i875 int, i876 int, i877 int, i878
-int, i879 int, i880 int, i881 int, i882 int, i883 int, i884 int, i885 int, i886
-int, i887 int, i888 int, i889 int, i890 int, i891 int, i892 int, i893 int, i894
-int, i895 int, i896 int, i897 int, i898 int, i899 int, i900 int, i901 int, i902
-int, i903 int, i904 int, i905 int, i906 int, i907 int, i908 int, i909 int, i910
-int, i911 int, i912 int, i913 int, i914 int, i915 int, i916 int, i917 int, i918
-int, i919 int, i920 int, i921 int, i922 int, i923 int, i924 int, i925 int, i926
-int, i927 int, i928 int, i929 int, i930 int, i931 int, i932 int, i933 int, i934
-int, i935 int, i936 int, i937 int, i938 int, i939 int, i940 int, i941 int, i942
-int, i943 int, i944 int, i945 int, i946 int, i947 int, i948 int, i949 int, i950
-int, i951 int, i952 int, i953 int, i954 int, i955 int, i956 int, i957 int, i958
-int, i959 int, i960 int, i961 int, i962 int, i963 int, i964 int, i965 int, i966
-int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974
-int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982
-int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990
-int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998
-int, i999 int, i1000 int, b blob) row_format=dynamic;
-insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "Sergei");
-update t1 set b=repeat('a',256);
-update t1 set i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0;
-check table t1;
-drop table t1;
-
-# End of 4.1 tests
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index 2715f30b6cf..bb82a93c6c4 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -115,6 +115,10 @@ select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using
--replace_result "31 tables" "XX tables" "61 tables" "XX tables"
--error 1116
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);
+select 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);
+--replace_result "31 tables" "XX tables" "61 tables" "XX tables"
+--error 1116
+select 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);
drop table t1;
#
@@ -145,6 +149,7 @@ CREATE TABLE t1 (d DATE NOT NULL);
CREATE TABLE t2 (d DATE NOT NULL);
INSERT INTO t1 (d) VALUES ('2001-08-01'),('0000-00-00');
SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE t2.d IS NULL;
+SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE d IS NULL;
SELECT * from t1 WHERE t1.d IS NULL;
SELECT * FROM t1 WHERE 1/0 IS NULL;
DROP TABLE t1,t2;
@@ -268,6 +273,8 @@ CREATE TABLE t2 (
INSERT INTO t2 VALUES ('rivercats','cust',20);
SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND lr.siteid = 'rivercats';
SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith';
+SELECT rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND siteid = 'rivercats';
+SELECT rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE siteid = 'rivercats' AND emp.emp_id = 'psmith';
drop table t1,t2;
#
diff --git a/mysql-test/t/join_crash.test b/mysql-test/t/join_crash.test
index 68fd9226e41..2ec96dc2c28 100644
--- a/mysql-test/t/join_crash.test
+++ b/mysql-test/t/join_crash.test
@@ -92,18 +92,11 @@ select distinct
t1.comments as comments,
sum( t3.amount_received ) + sum( t3.adjustment ) as total_budget
from
- t1 ,
t2 as client_period ,
- t2 as project_period
- left join
- t3
- on
- t3.project_ptr = t1.project_id
- and t3.date_received <= '2001-03-22 14:15:09'
- left join
- t4
- on
- t4.client_id = t1.client_ptr
+ t2 as project_period,
+ t3 left join t1 on (t3.project_ptr = t1.project_id and
+ t3.date_received <= '2001-03-22 14:15:09')
+ left join t4 on t4.client_id = t1.client_ptr
where
1
and ( client_period.period_type = 'client_table'
diff --git a/mysql-test/t/join_nested.test b/mysql-test/t/join_nested.test
new file mode 100644
index 00000000000..482c7f9f8b9
--- /dev/null
+++ b/mysql-test/t/join_nested.test
@@ -0,0 +1,803 @@
+
+--disable_warnings
+DROP TABLE IF EXISTS t0,t1,t2,t3,t4,t5,t6,t7,t8,t9;
+--enable_warnings
+
+CREATE TABLE t0 (a int, b int, c int);
+CREATE TABLE t1 (a int, b int, c int);
+CREATE TABLE t2 (a int, b int, c int);
+CREATE TABLE t3 (a int, b int, c int);
+CREATE TABLE t4 (a int, b int, c int);
+CREATE TABLE t5 (a int, b int, c int);
+CREATE TABLE t6 (a int, b int, c int);
+CREATE TABLE t7 (a int, b int, c int);
+CREATE TABLE t8 (a int, b int, c int);
+CREATE TABLE t9 (a int, b int, c int);
+
+INSERT INTO t0 VALUES (1,1,0), (1,2,0), (2,2,0);
+INSERT INTO t1 VALUES (1,3,0), (2,2,0), (3,2,0);
+INSERT INTO t2 VALUES (3,3,0), (4,2,0), (5,3,0);
+INSERT INTO t3 VALUES (1,2,0), (2,2,0);
+INSERT INTO t4 VALUES (3,2,0), (4,2,0);
+INSERT INTO t5 VALUES (3,1,0), (2,2,0), (3,3,0);
+INSERT INTO t6 VALUES (3,2,0), (6,2,0), (6,1,0);
+INSERT INTO t7 VALUES (1,1,0), (2,2,0);
+INSERT INTO t8 VALUES (0,2,0), (1,2,0);
+INSERT INTO t9 VALUES (1,1,0), (1,2,0), (3,3,0);
+
+
+SELECT t2.a,t2.b
+ FROM t2;
+
+SELECT t3.a,t3.b
+ FROM t3;
+
+SELECT t4.a,t4.b
+ FROM t4;
+
+SELECT t3.a,t3.b,t4.a,t4.b
+ FROM t3,t4;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t2.b=t4.b;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b;
+
+EXPLAIN EXTENDED
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t2.b=t4.b
+ WHERE t3.a=1 OR t3.c IS NULL;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t2.b=t4.b
+ WHERE t3.a=1 OR t3.c IS NULL;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t2.b=t4.b
+ WHERE t3.a>1 OR t3.c IS NULL;
+
+SELECT t5.a,t5.b
+ FROM t5;
+
+SELECT t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+ FROM t3,t4,t5;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4, t5)
+ ON t2.b=t4.b;
+
+EXPLAIN EXTENDED
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4, t5)
+ ON t2.b=t4.b
+ WHERE t3.a>1 OR t3.c IS NULL;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4, t5)
+ ON t2.b=t4.b
+ WHERE t3.a>1 OR t3.c IS NULL;
+
+EXPLAIN EXTENDED
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4, t5)
+ ON t2.b=t4.b
+ WHERE (t3.a>1 OR t3.c IS NULL) AND
+ (t5.a<3 OR t5.c IS NULL);
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,t5.a,t5.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4, t5)
+ ON t2.b=t4.b
+ WHERE (t3.a>1 OR t3.c IS NULL) AND
+ (t5.a<3 OR t5.c IS NULL);
+
+SELECT t6.a,t6.b
+ FROM t6;
+
+SELECT t7.a,t7.b
+ FROM t7;
+
+SELECT t6.a,t6.b,t7.a,t7.b
+ FROM t6,t7;
+
+SELECT t8.a,t8.b
+ FROM t8;
+
+EXPLAIN EXTENDED
+SELECT t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10;
+
+SELECT t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10;
+
+SELECT t5.a,t5.b
+ FROM t5;
+
+SELECT t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b;
+
+SELECT t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b AND
+ (t8.a < 1 OR t8.c IS NULL);
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ WHERE t2.a > 3 AND
+ (t6.a < 6 OR t6.c IS NULL);
+
+SELECT t1.a,t1.b
+ FROM t1;
+
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2);
+
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2)
+ WHERE (t2.a >= 4 OR t2.c IS NULL);
+
+SELECT t0.a,t0.b
+ FROM t0;
+
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2)
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL);
+
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2)
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL);
+
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2),
+ t9
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL) AND
+ (t3.a < 5 OR t3.c IS NULL) AND
+ (t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+ (t5.a >=2 OR t5.c IS NULL) AND
+ (t6.a >=4 OR t6.c IS NULL) AND
+ (t7.a <= 2 OR t7.c IS NULL) AND
+ (t8.a < 1 OR t8.c IS NULL) AND
+ (t8.b=t9.b OR t8.c IS NULL) AND
+ (t9.a=1);
+
+SELECT t9.a,t9.b
+ FROM t9;
+
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2),
+ t9
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL) AND
+ (t3.a < 5 OR t3.c IS NULL) AND
+ (t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+ (t5.a >=2 OR t5.c IS NULL) AND
+ (t6.a >=4 OR t6.c IS NULL) AND
+ (t7.a <= 2 OR t7.c IS NULL) AND
+ (t8.a < 1 OR t8.c IS NULL) AND
+ (t8.b=t9.b OR t8.c IS NULL) AND
+ (t9.a=1);
+
+SELECT t1.a,t1.b
+ FROM t1;
+
+SELECT t2.a,t2.b
+ FROM t2;
+
+SELECT t3.a,t3.b
+ FROM t3;
+
+SELECT t2.a,t2.b,t3.a,t3.b
+ FROM t2
+ LEFT JOIN
+ t3
+ ON t2.b=t3.b;
+
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b
+ FROM t1, t2
+ LEFT JOIN
+ t3
+ ON t2.b=t3.b
+ WHERE t1.a <= 2;
+
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b
+ FROM t1, t3
+ RIGHT JOIN
+ t2
+ ON t2.b=t3.b
+ WHERE t1.a <= 2;
+
+SELECT t3.a,t3.b,t4.a,t4.b
+ FROM t3,t4;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b;
+
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t1, t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b
+ WHERE t1.a <= 2;
+
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t1, (t3, t4)
+ RIGHT JOIN
+ t2
+ ON t3.a=1 AND t2.b=t4.b
+ WHERE t1.a <= 2;
+
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t1, (t3, t4)
+ RIGHT JOIN
+ t2
+ ON t3.a=1 AND t2.b=t4.b
+ WHERE t1.a <= 2;
+
+EXPLAIN EXTENDED
+SELECT t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM t1, (t3, t4)
+ RIGHT JOIN
+ t2
+ ON t3.a=1 AND t2.b=t4.b
+ WHERE t1.a <= 2;
+
+CREATE INDEX idx_b ON t2(b);
+
+EXPLAIN EXTENDED
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM (t3,t4)
+ LEFT JOIN
+ (t1,t2)
+ ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b;
+
+SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
+ FROM (t3,t4)
+ LEFT JOIN
+ (t1,t2)
+ ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b;
+
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2),
+ t9
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL) AND
+ (t3.a < 5 OR t3.c IS NULL) AND
+ (t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+ (t5.a >=2 OR t5.c IS NULL) AND
+ (t6.a >=4 OR t6.c IS NULL) AND
+ (t7.a <= 2 OR t7.c IS NULL) AND
+ (t8.a < 1 OR t8.c IS NULL) AND
+ (t8.b=t9.b OR t8.c IS NULL) AND
+ (t9.a=1);
+
+CREATE INDEX idx_b ON t4(b);
+CREATE INDEX idx_b ON t5(b);
+
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2),
+ t9
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL) AND
+ (t3.a < 5 OR t3.c IS NULL) AND
+ (t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+ (t5.a >=2 OR t5.c IS NULL) AND
+ (t6.a >=4 OR t6.c IS NULL) AND
+ (t7.a <= 2 OR t7.c IS NULL) AND
+ (t8.a < 1 OR t8.c IS NULL) AND
+ (t8.b=t9.b OR t8.c IS NULL) AND
+ (t9.a=1);
+
+CREATE INDEX idx_b ON t8(b);
+
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2),
+ t9
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL) AND
+ (t3.a < 5 OR t3.c IS NULL) AND
+ (t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+ (t5.a >=2 OR t5.c IS NULL) AND
+ (t6.a >=4 OR t6.c IS NULL) AND
+ (t7.a <= 2 OR t7.c IS NULL) AND
+ (t8.a < 1 OR t8.c IS NULL) AND
+ (t8.b=t9.b OR t8.c IS NULL) AND
+ (t9.a=1);
+
+CREATE INDEX idx_b ON t1(b);
+CREATE INDEX idx_a ON t0(a);
+
+EXPLAIN EXTENDED
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2),
+ t9
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL) AND
+ (t3.a < 5 OR t3.c IS NULL) AND
+ (t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+ (t5.a >=2 OR t5.c IS NULL) AND
+ (t6.a >=4 OR t6.c IS NULL) AND
+ (t7.a <= 2 OR t7.c IS NULL) AND
+ (t8.a < 1 OR t8.c IS NULL) AND
+ (t8.b=t9.b OR t8.c IS NULL) AND
+ (t9.a=1);
+
+SELECT t0.a,t0.b,t1.a,t1.b,t2.a,t2.b,t3.a,t3.b,t4.a,t4.b,
+ t5.a,t5.b,t6.a,t6.b,t7.a,t7.b,t8.a,t8.b,t9.a,t9.b
+ FROM t0,t1
+ LEFT JOIN
+ (
+ t2
+ LEFT JOIN
+ (t3, t4)
+ ON t3.a=1 AND t2.b=t4.b,
+ t5
+ LEFT JOIN
+ (
+ (t6, t7)
+ LEFT JOIN
+ t8
+ ON t7.b=t8.b AND t6.b < 10
+ )
+ ON t6.b >= 2 AND t5.b=t7.b
+ )
+ ON (t3.b=2 OR t3.c IS NULL) AND (t6.b=2 OR t6.c IS NULL) AND
+ (t1.b=t5.b OR t3.c IS NULL OR t6.c IS NULL or t8.c IS NULL) AND
+ (t1.a != 2),
+ t9
+ WHERE t0.a=1 AND
+ t0.b=t1.b AND
+ (t2.a >= 4 OR t2.c IS NULL) AND
+ (t3.a < 5 OR t3.c IS NULL) AND
+ (t3.b=t4.b OR t3.c IS NULL OR t4.c IS NULL) AND
+ (t5.a >=2 OR t5.c IS NULL) AND
+ (t6.a >=4 OR t6.c IS NULL) AND
+ (t7.a <= 2 OR t7.c IS NULL) AND
+ (t8.a < 1 OR t8.c IS NULL) AND
+ (t8.b=t9.b OR t8.c IS NULL) AND
+ (t9.a=1);
+
+SELECT t2.a,t2.b
+ FROM t2;
+
+SELECT t3.a,t3.b
+ FROM t3;
+
+SELECT t2.a,t2.b,t3.a,t3.b
+ FROM t2 LEFT JOIN t3 ON t2.b=t3.b
+ WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL);
+
+SELECT t2.a,t2.b,t3.a,t3.b
+ FROM t2 LEFT JOIN (t3) ON t2.b=t3.b
+ WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL);
+
+ALTER TABLE t3
+ CHANGE COLUMN a a1 int,
+ CHANGE COLUMN c c1 int;
+
+SELECT t2.a,t2.b,t3.a1,t3.b
+ FROM t2 LEFT JOIN t3 ON t2.b=t3.b
+ WHERE t2.a = 4 OR (t2.a > 4 AND t3.a1 IS NULL);
+
+SELECT t2.a,t2.b,t3.a1,t3.b
+ FROM t2 NATURAL LEFT JOIN t3
+ WHERE t2.a = 4 OR (t2.a > 4 AND t3.a1 IS NULL);
+
+DROP TABLE t0,t1,t2,t3,t4,t5,t6,t7,t8,t9;
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE TABLE t3 (a int);
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t3 VALUES (2);
+INSERT INTO t1 VALUES (2);
+
+#check proper syntax for nested outer joins
+
+SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a) ON t1.a=t3.a;
+
+#must be equivalent to:
+
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.a=t3.a;
+
+#check that everything is al right when all tables contain not more than 1 row
+#(bug #4922)
+
+DELETE FROM t1 WHERE a=2;
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.a=t3.a;
+DELETE FROM t2;
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.a=t3.a;
+
+DROP TABLE t1,t2,t3;
+
+#on expression for a nested outer join does not depend on the outer table
+#bug #4976
+
+CREATE TABLE t1(a int, key (a));
+CREATE TABLE t2(b int, key (b));
+CREATE TABLE t3(c int, key (c));
+
+INSERT INTO t1 VALUES (NULL), (0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
+(10), (11), (12), (13), (14), (15), (16), (17), (18), (19);
+
+INSERT INTO t2 VALUES (NULL), (0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
+(10), (11), (12), (13), (14), (15), (16), (17), (18), (19);
+
+INSERT INTO t3 VALUES (0), (1), (2), (3), (4), (5);
+
+EXPLAIN SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON c < 3 and b = c;
+EXPLAIN SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
+SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
+
+DELETE FROM t3;
+EXPLAIN SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
+SELECT a, b, c FROM t1 LEFT JOIN (t2, t3) ON b < 3 and b = c;
+
+DROP TABLE t1,t2,t3;
+
+#
+# Test for bug #11284: empty table in a nested left join
+#
+
+CREATE TABLE t1 (c11 int);
+CREATE TABLE t2 (c21 int);
+CREATE TABLE t3 (c31 int);
+
+INSERT INTO t1 VALUES (4), (5);
+
+SELECT * FROM t1 LEFT JOIN t2 ON c11=c21;
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON c11=c21;
+
+SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON c21=c31) ON c11=c21;
+EXPLAIN SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON c21=c31) ON c11=c21;
+
+DROP TABLE t1,t2,t3;
+
+#
+# Bug #12154: creation of temp table for a query with nested outer join
+#
+
+CREATE TABLE t1 (goods int(12) NOT NULL, price varchar(128) NOT NULL);
+INSERT INTO t1 VALUES (23, 2340), (26, 9900);
+
+CREATE TABLE t2 (goods int(12), name varchar(50), shop char(2));
+INSERT INTO t2 VALUES (23, 'as300', 'fr'), (26, 'as600', 'fr');
+
+create table t3 (groupid int(12) NOT NULL, goodsid int(12) NOT NULL);
+INSERT INTO t3 VALUES (3,23), (6,26);
+
+CREATE TABLE t4 (groupid int(12));
+INSERT INTO t4 VALUES (1), (2), (3), (4), (5), (6);
+
+SELECT * FROM
+(SELECT DISTINCT gl.groupid, gp.price
+ FROM t4 gl
+ LEFT JOIN
+ (t3 g INNER JOIN t2 p ON g.goodsid = p.goods
+ INNER JOIN t1 gp ON p.goods = gp.goods)
+ ON gl.groupid = g.groupid and p.shop = 'fr') t;
+
+CREATE VIEW v1 AS
+SELECT g.groupid groupid, p.goods goods,
+ p.name name, p.shop shop,
+ gp.price price
+ FROM t3 g INNER JOIN t2 p ON g.goodsid = p.goods
+ INNER JOIN t1 gp on p.goods = gp.goods;
+
+CREATE VIEW v2 AS
+SELECT DISTINCT g.groupid, fr.price
+ FROM t4 g
+ LEFT JOIN
+ v1 fr on g.groupid = fr.groupid and fr.shop = 'fr';
+
+SELECT * FROM v2;
+
+SELECT * FROM
+(SELECT DISTINCT g.groupid, fr.price
+ FROM t4 g
+ LEFT JOIN
+ v1 fr on g.groupid = fr.groupid and fr.shop = 'fr') t;
+
+DROP VIEW v1,v2;
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index 05cd2fb152e..367b98f2485 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1,t2,t3,t4,t5;
+drop table if exists t0,t1,t2,t3,t4,t5;
--enable_warnings
CREATE TABLE t1 (
@@ -34,13 +34,13 @@ explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
select t1.*,t2.*,t3.a from t1 left join t2 on (t1.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
# The next query should rearange the left joins to get this to work
---error 1120
+--error 1054
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 1120
+--error 1054
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);
# The next query should give an error in MySQL
---error 1120
+--error 1054
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);
# Test of inner join
@@ -135,7 +135,7 @@ INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas
INSERT INTO t1 VALUES (11403,'Projecte Fi de Carrera','Proyecto Fin de Carrera','Projecte Fi de Carrera','PFC',9.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11404,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',15.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11405,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',18.0,NULL,NULL,NULL);
-INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
+INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
CREATE TABLE t2 (
idAssignatura int(11) DEFAULT '0' NOT NULL,
@@ -292,7 +292,7 @@ insert into t3 values (1);
insert into t4 values (1,1);
insert into t5 values (1,1);
---error 1120
+--error 1054
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;
drop table t1,t2,t3,t4,t5;
@@ -430,6 +430,10 @@ insert into t1 values(1),(2);
insert into t2 values(2),(3);
insert into t3 values(2),(4);
select * from t1 natural left join t2 natural left join t3;
+select * from t1 natural left join t2 where (t2.i is not null)=0;
+select * from t1 natural left join t2 where (t2.i is not null) is not null;
+select * from t1 natural left join t2 where (i is not null)=0;
+select * from t1 natural left join t2 where (i is not null) is not null;
drop table t1,t2,t3;
#
@@ -438,7 +442,6 @@ drop table t1,t2,t3;
create table t1 (f1 integer,f2 integer,f3 integer);
create table t2 (f2 integer,f4 integer);
create table t3 (f3 integer,f5 integer);
---error 1054
select * from t1
left outer join t2 using (f2)
left outer join t3 using (f3);
@@ -567,34 +570,68 @@ SELECT t1.flag_name,t2.flag_value
DROP TABLE t1,t2;
-CREATE TABLE invoice (
+CREATE TABLE t1 (
id int(11) unsigned NOT NULL auto_increment,
text_id int(10) unsigned default NULL,
PRIMARY KEY (id)
);
-INSERT INTO invoice VALUES("1", "0");
-INSERT INTO invoice VALUES("2", "10");
+INSERT INTO t1 VALUES("1", "0");
+INSERT INTO t1 VALUES("2", "10");
-CREATE TABLE text_table (
+CREATE TABLE t2 (
text_id char(3) NOT NULL default '',
language_id char(3) NOT NULL default '',
text_data text,
PRIMARY KEY (text_id,language_id)
);
-INSERT INTO text_table VALUES("0", "EN", "0-EN");
-INSERT INTO text_table VALUES("0", "SV", "0-SV");
-INSERT INTO text_table VALUES("10", "EN", "10-EN");
-INSERT INTO text_table VALUES("10", "SV", "10-SV");
+INSERT INTO t2 VALUES("0", "EN", "0-EN");
+INSERT INTO t2 VALUES("0", "SV", "0-SV");
+INSERT INTO t2 VALUES("10", "EN", "10-EN");
+INSERT INTO t2 VALUES("10", "SV", "10-SV");
+SELECT t1.id, t1.text_id, t2.text_data
+ FROM t1 LEFT JOIN t2
+ ON t1.text_id = t2.text_id
+ AND t2.language_id = 'SV'
+ WHERE (t1.id LIKE '%' OR t2.text_data LIKE '%');
+
+DROP TABLE t1, t2;
+
+# Test for bug #5896
+
+CREATE TABLE t0 (a0 int PRIMARY KEY);
+CREATE TABLE t1 (a1 int PRIMARY KEY);
+CREATE TABLE t2 (a2 int);
+CREATE TABLE t3 (a3 int);
+INSERT INTO t0 VALUES (1);
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1), (2);
+INSERT INTO t3 VALUES (1), (2);
+
+SELECT * FROM t1 LEFT JOIN t2 ON a1=0;
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON a1=0;
+SELECT * FROM t1 LEFT JOIN (t2,t3) ON a1=0;
+EXPLAIN SELECT * FROM t1 LEFT JOIN (t2,t3) ON a1=0;
+SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=0 WHERE a0=a1;
+EXPLAIN SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=0 WHERE a0=a1;
+
+INSERT INTO t0 VALUES (0);
+INSERT INTO t1 VALUES (0);
+SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
+EXPLAIN SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
+
+# Test for BUG#4480
+drop table t1,t2;
+create table t1 (a int, b int);
+insert into t1 values (1,1),(2,2),(3,3);
+create table t2 (a int, b int);
+insert into t2 values (1,1), (2,2);
-SELECT invoice.id, invoice.text_id, text_table.text_data
- FROM invoice LEFT JOIN text_table
- ON invoice.text_id = text_table.text_id
- AND text_table.language_id = 'SV'
- WHERE (invoice.id LIKE '%' OR text_table.text_data LIKE '%');
+select * from t2 right join t1 on t2.a=t1.a;
+select straight_join * from t2 right join t1 on t2.a=t1.a;
-DROP TABLE invoice, text_table;
+DROP TABLE t0,t1,t2,t3;
#
# Test for bug #9017: left join mistakingly converted to inner join
@@ -622,9 +659,59 @@ insert into t1 values (1,"aaaaaaaaaa"),(2,"bbbbbbbbbb");
insert into t2 values (1,"cccccccccc"),(2,"dddddddddd");
select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by t1.a;
select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a;
+select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by a;
+select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by a;
drop table t1, t2;
set group_concat_max_len=default;
+# End of 4.1 tests
+
+#
+# BUG#10162 - ON is merged with WHERE, left join is convered to a regular join
+#
+create table t1 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, art int(11) not null, primary key (gid,x,y));
+insert t1 values (1, -5, -8, 2), (1, 2, 2, 1), (1, 1, 1, 1);
+create table t2 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, id int(11) not null, primary key (gid,id,x,y), key id (id));
+insert t2 values (1, -5, -8, 1), (1, 1, 1, 1), (1, 2, 2, 1);
+create table t3 ( set_id smallint(5) unsigned not null, id tinyint(4) unsigned not null, name char(12) not null, primary key (id,set_id));
+insert t3 values (0, 1, 'a'), (1, 1, 'b'), (0, 2, 'c'), (1, 2, 'd'), (1, 3, 'e'), (1, 4, 'f'), (1, 5, 'g'), (1, 6, 'h');
+explain select name from t1 left join t2 on t1.x = t2.x and t1.y = t2.y
+left join t3 on t1.art = t3.id where t2.id =1 and t2.x = -5 and t2.y =-8
+and t1.gid =1 and t2.gid =1 and t3.set_id =1;
+drop tables t1,t2,t3;
+
+#
+# Test for bug #9938: invalid conversion from outer join to inner join
+# for queries containing indirect reference in WHERE clause
+#
+
+CREATE TABLE t1 (EMPNUM INT, GRP INT);
+INSERT INTO t1 VALUES (0, 10);
+INSERT INTO t1 VALUES (2, 30);
+
+CREATE TABLE t2 (EMPNUM INT, NAME CHAR(5));
+INSERT INTO t2 VALUES (0, 'KERI');
+INSERT INTO t2 VALUES (9, 'BARRY');
+
+CREATE VIEW v1 AS
+SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS EMPNUM, NAME, GRP
+ FROM t2 LEFT OUTER JOIN t1 ON t2.EMPNUM=t1.EMPNUM;
+
+SELECT * FROM v1;
+SELECT * FROM v1 WHERE EMPNUM < 10;
+
+DROP TABLE t1,t2;
+
+#
+# Test for bug #11285: false Item_equal on expression in outer join
+#
+
+CREATE TABLE t1 (c11 int);
+CREATE TABLE t2 (c21 int);
+INSERT INTO t1 VALUES (30), (40), (50);
+INSERT INTO t2 VALUES (300), (400), (500);
+SELECT * FROM t1 LEFT JOIN t2 ON (c11=c21 AND c21=30) WHERE c11=40;
+DROP TABLE t1, t2;
#
# Test for bugs
# #12101: erroneously applied outer join elimination in case of WHERE NOT BETWEEN
@@ -671,4 +758,3 @@ EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a > IF(t1.a = t2.b
DROP TABLE t1,t2;
-# End of 4.1 tests
diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test
index 85728582c75..31763b84379 100644
--- a/mysql-test/t/key.test
+++ b/mysql-test/t/key.test
@@ -129,7 +129,11 @@ create table t2
INSERT t2 select * from t1;
SELECT * FROM t2 WHERE name='[T,U]_axpy';
SELECT * FROM t2 WHERE name='[T,U]_axpby';
-drop table t1,t2;
+# Test possible problems with warnings in CREATE ... SELECT
+CREATE TABLE t3 SELECT * FROM t2 WHERE name='[T,U]_axpby';
+SELECT * FROM t2 WHERE name='[T,U]_axpby';
+
+drop table t1,t2,t3;
#
# Test bug with long primary key
@@ -295,7 +299,7 @@ drop table t1;
# create dedicated error code for this and
# and change my_printf_error() to my_error
---error 1105
+--error 1391
create table t1 (c char(10), index (c(0)));
#
@@ -336,5 +340,35 @@ insert into t1 values (2,' \t\tTest String');
insert into t1 values (3,' \n\tTest String');
update t1 set c2 = 'New Test String' where c1 = 1;
select * from t1;
+drop table t1;
+
+#
+# If we use a partial field for a key that is actually the length of the
+# field, and we extend the field, we end up with a key that includes the
+# whole new length of the field.
+#
+create table t1 (a varchar(10), b varchar(10), key(a(10),b(10)));
+show create table t1;
+alter table t1 modify b varchar(20);
+show create table t1;
+alter table t1 modify a varchar(20);
+show create table t1;
+drop table t1;
+
+#
+# Bug #11227: Incorrectly reporting 'MUL' vs. 'UNI' on varchar
+#
+create table t1 (a int not null primary key, b varchar(20) not null unique);
+desc t1;
+drop table t1;
+create table t1 (a int not null primary key, b int not null unique);
+desc t1;
+drop table t1;
+create table t1 (a int not null primary key, b varchar(20) not null, unique (b(10)));
+desc t1;
+drop table t1;
+create table t1 (a int not null primary key, b varchar(20) not null, c varchar(20) not null, unique(b(10),c(10)));
+desc t1;
+drop table t1;
# End of 4.1 tests
diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test
index 5d0f904a716..df584021af1 100644
--- a/mysql-test/t/key_cache.test
+++ b/mysql-test/t/key_cache.test
@@ -168,4 +168,11 @@ check table t1;
drop table t1;
+#
+# Bug#10473 - Can't set 'key_buffer_size' system variable to ZERO
+# (One cannot drop the default key cache.)
+#
+set @@global.key_buffer_size=0;
+select @@global.key_buffer_size;
+
# End of 4.1 tests
diff --git a/mysql-test/t/keywords.test b/mysql-test/t/keywords.test
index 96c3dc3f17c..de0159a950e 100644
--- a/mysql-test/t/keywords.test
+++ b/mysql-test/t/keywords.test
@@ -6,10 +6,12 @@
drop table if exists t1;
--enable_warnings
-create table t1 (time time, date date, timestamp timestamp);
-insert into t1 values ("12:22:22","97:02:03","1997-01-02");
+create table t1 (time time, date date, timestamp timestamp,
+quarter int, week int, year int, timestampadd int, timestampdiff int);
+insert into t1 values ("12:22:22","97:02:03","1997-01-02",1,2,3,4,5);
select * from t1;
-select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1;
+select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time),
+ t1.quarter+t1.week, t1.year+timestampadd, timestampdiff from t1;
drop table t1;
create table events(binlog int);
insert into events values(1);
diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test
index fdedaa8cd7f..97842d6b4e6 100644
--- a/mysql-test/t/kill.test
+++ b/mysql-test/t/kill.test
@@ -15,6 +15,7 @@ connection con1;
drop table if exists t1;
--enable_warnings
+--disable_reconnect
create table t1 (kill_id int);
insert into t1 values(connection_id());
@@ -25,7 +26,6 @@ kill @id;
connection con1;
---disable_reconnect
# this statement should fail
--error 2006,2013
select 1;
@@ -40,3 +40,22 @@ select 4;
drop table t1;
# End of 4.1 tests
+
+#
+# test of blocking of sending ERROR after OK or EOF
+#
+connection con1;
+select get_lock("a", 10);
+connection con2;
+let $ID= `select connection_id()`;
+send select get_lock("a", 10);
+real_sleep 2;
+connection con1;
+disable_query_log;
+eval kill query $ID;
+enable_query_log;
+connection con2;
+reap;
+select 1;
+connection con1;
+select RELEASE_LOCK("a");
diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test
index ef9f63067a4..6df865278f6 100644
--- a/mysql-test/t/limit.test
+++ b/mysql-test/t/limit.test
@@ -6,7 +6,7 @@
drop table if exists t1;
--enable_warnings
-create table t1 (a int primary key, b int not null);
+create table t1 (a int not null default 0 primary key, b int not null default 0);
insert into t1 () values (); -- Testing default values
insert into t1 values (1,1),(2,1),(3,1);
update t1 set a=4 where b=1 limit 1;
diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
index 689bdbbf92d..fe6828916a3 100644
--- a/mysql-test/t/loaddata.test
+++ b/mysql-test/t/loaddata.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1;
+drop table if exists t1, t2;
--enable_warnings
create table t1 (a date, b date, c date not null, d date);
@@ -32,3 +32,47 @@ select * from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Let us test extended LOAD DATA features
+#
+create table t1 (a int default 100, b int, c varchar(60));
+# we can do something like this
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set b=@b+10, c=concat("b=",@b);
+select * from t1;
+truncate table t1;
+# we can use filled fields in expressions
+# we also assigning NULL value to field with non-NULL default here
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set c= if(a is null,"oops",a);
+select * from t1;
+truncate table t1;
+# we even can use variables in set clause, and missed columns will be set
+# with default values
+set @c:=123;
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, b) set c= if(@a is null,@c,b);
+select * from t1;
+# let us test side-effect of such load
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, @b);
+select * from t1;
+select @a, @b;
+truncate table t1;
+# now going to test fixed field-row file format
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c="Wow";
+select * from t1;
+truncate table t1;
+# this also should work
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c=concat(a,"+",b,"+",@c,"+",b,"+",if(c is null,"NIL",c));
+select * from t1;
+# and this should bark
+--error 1409
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, @b);
+
+# Now let us test LOAD DATA with subselect
+create table t2 (num int primary key, str varchar(10));
+insert into t2 values (10,'Ten'), (15,'Fifteen');
+truncate table t1;
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@dummy,@n) set a= @n, c= (select str from t2 where num=@n);
+select * from t1;
+
+# cleanup
+drop table t1, t2;
diff --git a/mysql-test/t/lock.test b/mysql-test/t/lock.test
index 4809dcc5abe..4815c1a30b7 100644
--- a/mysql-test/t/lock.test
+++ b/mysql-test/t/lock.test
@@ -54,7 +54,7 @@ check table t1;
lock tables t1 write;
check table t2;
--error 1100
-insert into t1 select nr from t1;
+insert into t1 select index1,nr from t1;
unlock tables;
lock tables t1 write, t1 as t1_alias read;
insert into t1 select index1,nr from t1 as t1_alias;
diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test
index 2e40aeaccb7..0d2266fc2ae 100644
--- a/mysql-test/t/lock_multi.test
+++ b/mysql-test/t/lock_multi.test
@@ -96,3 +96,14 @@ connection locker;
drop table t1;
# End of 4.1 tests
+
+#
+# BUG#9998 - MySQL client hangs on USE "database"
+#
+create table t1(a int);
+lock tables t1 write;
+connection reader;
+show columns from t1;
+connection locker;
+unlock tables;
+drop table t1;
diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test
index 709743ce687..96437bc7636 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -7,6 +7,7 @@ drop table if exists t1,t2,t3,t4;
# Clear up from other tests (to ensure that SHOW TABLES below is right)
drop table if exists t0,t5,t6,t7,t8,t9;
drop database if exists mysqltest;
+drop view if exists v0, v1, v2, v3, v4;
--enable_warnings
create table T1 (id int primary key, Word varchar(40) not null, Index(Word));
diff --git a/mysql-test/t/lowercase_table3.test b/mysql-test/t/lowercase_table3.test
index 9208f3a76ec..75f6e5188c5 100644
--- a/mysql-test/t/lowercase_table3.test
+++ b/mysql-test/t/lowercase_table3.test
@@ -5,12 +5,8 @@
#
--source include/have_innodb.inc
---require r/lowercase0.require
-disable_query_log;
-show variables like "lower_case_%";
---require r/true.require
-select convert(@@version_compile_os using latin1) NOT IN ("NT","WIN2000","Win95/Win98","XP") as "TRUE";
-enable_query_log;
+--source include/have_lowercase0.inc
+--source include/not_windows.inc
--disable_warnings
DROP TABLE IF EXISTS t1,T1;
@@ -32,7 +28,7 @@ flush tables;
#
CREATE TABLE t1 (a int) ENGINE=INNODB;
---error 1016
+--error 1146
SELECT * from T1;
drop table t1;
diff --git a/mysql-test/t/lowercase_view-master.opt b/mysql-test/t/lowercase_view-master.opt
new file mode 100644
index 00000000000..62ab6dad1e0
--- /dev/null
+++ b/mysql-test/t/lowercase_view-master.opt
@@ -0,0 +1 @@
+--lower_case_table_names=1
diff --git a/mysql-test/t/lowercase_view.test b/mysql-test/t/lowercase_view.test
new file mode 100644
index 00000000000..e9cc26bec18
--- /dev/null
+++ b/mysql-test/t/lowercase_view.test
@@ -0,0 +1,140 @@
+--disable_warnings
+drop table if exists t1Aa,t2Aa,v1Aa,v2Aa;
+drop view if exists t1Aa,t2Aa,v1Aa,v2Aa;
+drop database if exists MySQLTest;
+--enable_warnings
+
+#
+# different cases in VIEW
+#
+create database MySQLTest;
+use MySQLTest;
+create table TaB (Field int);
+create view ViE as select * from TAb;
+show create table VIe;
+drop database MySQLTest;
+use test;
+
+#
+# test of updating and fetching from the same table check
+#
+create table t1Aa (col1 int);
+create table t2aA (col1 int);
+create view v1Aa as select * from t1aA;
+create view v2aA as select * from v1aA;
+create view v3Aa as select v2Aa.col1 from v2aA,t2Aa where v2Aa.col1 = t2aA.col1;
+-- error 1443
+update v2aA set col1 = (select max(col1) from v1Aa);
+-- error 1443
+update v2Aa set col1 = (select max(col1) from t1Aa);
+-- error 1093
+update v2aA set col1 = (select max(col1) from v2Aa);
+-- error 1443
+update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from v1aA) where v2aA.col1 = t2aA.col1;
+-- error 1443
+update t1aA,t2Aa set t1Aa.col1 = (select max(col1) from v1Aa) where t1aA.col1 = t2aA.col1;
+-- error 1093
+update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from v1aA) where v1Aa.col1 = t2aA.col1;
+-- error 1443
+update t2Aa,v2Aa set v2aA.col1 = (select max(col1) from v1aA) where v2Aa.col1 = t2aA.col1;
+-- error 1443
+update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from v1Aa) where t1Aa.col1 = t2aA.col1;
+-- error 1443
+update t2Aa,v1aA set v1Aa.col1 = (select max(col1) from v1aA) where v1Aa.col1 = t2aA.col1;
+-- error 1443
+update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from t1aA) where v2aA.col1 = t2aA.col1;
+-- error 1093
+update t1Aa,t2Aa set t1aA.col1 = (select max(col1) from t1Aa) where t1aA.col1 = t2aA.col1;
+-- error 1443
+update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from t1Aa) where v1aA.col1 = t2aA.col1;
+-- error 1093
+update t2Aa,v2Aa set v2aA.col1 = (select max(col1) from t1aA) where v2Aa.col1 = t2aA.col1;
+-- error 1093
+update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from t1Aa) where t1aA.col1 = t2aA.col1;
+-- error 1093
+update t2Aa,v1Aa set v1aA.col1 = (select max(col1) from t1Aa) where v1Aa.col1 = t2aA.col1;
+-- error 1093
+update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from v2aA) where v2Aa.col1 = t2aA.col1;
+-- error 1443
+update t1aA,t2Aa set t1Aa.col1 = (select max(col1) from v2aA) where t1aA.col1 = t2aA.col1;
+-- error 1443
+update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from v2Aa) where v1aA.col1 = t2aA.col1;
+-- error 1443
+update t2Aa,v2aA set v2Aa.col1 = (select max(col1) from v2aA) where v2Aa.col1 = t2aA.col1;
+-- error 1443
+update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from v2aA) where t1Aa.col1 = t2aA.col1;
+-- error 1443
+update t2Aa,v1Aa set v1aA.col1 = (select max(col1) from v2Aa) where v1Aa.col1 = t2aA.col1;
+-- error 1443
+update v3aA set v3Aa.col1 = (select max(col1) from v1aA);
+-- error 1443
+update v3aA set v3Aa.col1 = (select max(col1) from t1aA);
+-- error 1443
+update v3aA set v3Aa.col1 = (select max(col1) from v2aA);
+-- error 1093
+update v3aA set v3Aa.col1 = (select max(col1) from v3aA);
+-- error 1443
+delete from v2Aa where col1 = (select max(col1) from v1Aa);
+-- error 1443
+delete from v2aA where col1 = (select max(col1) from t1Aa);
+-- error 1093
+delete from v2Aa where col1 = (select max(col1) from v2aA);
+-- error 1443
+delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1;
+-- error 1443
+delete t1aA from t1Aa,t2Aa where (select max(col1) from v1Aa) > 0 and t1aA.col1 = t2aA.col1;
+-- error 1093
+delete v1aA from v1Aa,t2Aa where (select max(col1) from v1aA) > 0 and v1Aa.col1 = t2aA.col1;
+-- error 1443
+delete v2aA from v2Aa,t2Aa where (select max(col1) from t1Aa) > 0 and v2aA.col1 = t2aA.col1;
+-- error 1093
+delete t1aA from t1Aa,t2Aa where (select max(col1) from t1aA) > 0 and t1Aa.col1 = t2aA.col1;
+-- error 1443
+delete v1aA from v1Aa,t2Aa where (select max(col1) from t1aA) > 0 and v1aA.col1 = t2aA.col1;
+-- error 1093
+delete v2Aa from v2aA,t2Aa where (select max(col1) from v2Aa) > 0 and v2aA.col1 = t2aA.col1;
+-- error 1443
+delete t1Aa from t1aA,t2Aa where (select max(col1) from v2Aa) > 0 and t1Aa.col1 = t2aA.col1;
+-- error 1443
+delete v1Aa from v1aA,t2Aa where (select max(col1) from v2aA) > 0 and v1Aa.col1 = t2aA.col1;
+-- error 1443
+insert into v2Aa values ((select max(col1) from v1aA));
+-- error 1443
+insert into t1aA values ((select max(col1) from v1Aa));
+-- error 1443
+insert into v2aA values ((select max(col1) from v1aA));
+-- error 1443
+insert into v2Aa values ((select max(col1) from t1Aa));
+-- error 1093
+insert into t1aA values ((select max(col1) from t1Aa));
+-- error 1443
+insert into v2aA values ((select max(col1) from t1aA));
+-- error 1093
+insert into v2Aa values ((select max(col1) from v2aA));
+-- error 1443
+insert into t1Aa values ((select max(col1) from v2Aa));
+-- error 1093
+insert into v2aA values ((select max(col1) from v2Aa));
+-- error 1443
+insert into v3Aa (col1) values ((select max(col1) from v1Aa));
+-- error 1443
+insert into v3aA (col1) values ((select max(col1) from t1aA));
+-- error 1443
+insert into v3Aa (col1) values ((select max(col1) from v2aA));
+drop view v3aA,v2Aa,v1aA;
+drop table t1Aa,t2Aa;
+
+#
+# aliases in VIEWs
+#
+create table t1Aa (col1 int);
+create view v1Aa as select col1 from t1Aa as AaA;
+show create view v1AA;
+drop view v1AA;
+select Aaa.col1 from t1Aa as AaA;
+create view v1Aa as select Aaa.col1 from t1Aa as AaA;
+drop view v1AA;
+create view v1Aa as select AaA.col1 from t1Aa as AaA;
+show create view v1AA;
+drop view v1AA;
+drop table t1Aa;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index fa13107ca04..7d708243a10 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -47,9 +47,9 @@ show create table t3;
# The following should give errors
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
---error 1016
+--error 1168
select * from t4;
---error 1016
+--error 1168
alter table t4 add column c int;
#
@@ -284,6 +284,8 @@ insert into t2 values (1);
create table t3 engine=merge union=(t1, t2) select * from t1;
--error 1093
create table t3 engine=merge union=(t1, t2) select * from t2;
+--error 1093
+create table t3 engine=merge union=(t1, t2) select (select max(a) from t2);
drop table t1, t2;
# BUG#6699 : no sorting on 'ref' retrieval
diff --git a/mysql-test/t/mix_innodb_myisam_binlog.test b/mysql-test/t/mix_innodb_myisam_binlog.test
index 6eb9eae2d99..2e804f4c986 100644
--- a/mysql-test/t/mix_innodb_myisam_binlog.test
+++ b/mysql-test/t/mix_innodb_myisam_binlog.test
@@ -28,7 +28,9 @@ insert into t1 values(1);
insert into t2 select * from t1;
commit;
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=15" "xid=8"
+show binlog events from 98;
delete from t1;
delete from t2;
@@ -40,7 +42,8 @@ insert into t2 select * from t1;
# should say some changes to non-transact1onal tables couldn't be rolled back
rollback;
-show binlog events from 79;
+--replace_column 5 #
+show binlog events from 98;
delete from t1;
delete from t2;
@@ -54,7 +57,9 @@ insert into t2 select * from t1;
rollback to savepoint my_savepoint;
commit;
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=48" "xid=25"
+show binlog events from 98;
delete from t1;
delete from t2;
@@ -70,7 +75,9 @@ insert into t1 values(7);
commit;
select a from t1 order by a; # check that savepoints work :)
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=70" "xid=37"
+show binlog events from 98;
# and when ROLLBACK is not explicit?
delete from t1;
@@ -90,7 +97,8 @@ connection con2;
# so SHOW BINLOG EVENTS may come before con1 does the loggin. To be sure that
# logging has been done, we use a user lock.
select get_lock("a",10);
-show binlog events from 79;
+--replace_column 5 #
+show binlog events from 98;
# and when not in a transact1on?
delete from t1;
@@ -100,10 +108,12 @@ reset master;
insert into t1 values(9);
insert into t2 select * from t1;
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=119" "xid=60"
+show binlog events from 98;
# Check that when the query updat1ng the MyISAM table is the first in the
-# transact1on, we log it immediately.
+# transaction, we log it immediately.
delete from t1;
delete from t2;
reset master;
@@ -111,11 +121,15 @@ reset master;
insert into t1 values(10); # first make t1 non-empty
begin;
insert into t2 select * from t1;
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=133" "xid=66"
+show binlog events from 98;
insert into t1 values(11);
commit;
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=133" "xid=66" "xid=136" "xid=68"
+show binlog events from 98;
# Check that things work like before this BEGIN/ROLLBACK code was added,
@@ -132,7 +146,9 @@ insert into t1 values(12);
insert into t2 select * from t1;
commit;
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=155" "xid=78"
+show binlog events from 98;
delete from t1;
delete from t2;
@@ -143,7 +159,8 @@ insert into t1 values(13);
insert into t2 select * from t1;
rollback;
-show binlog events from 79;
+--replace_column 5 #
+show binlog events from 98;
delete from t1;
delete from t2;
@@ -157,7 +174,9 @@ insert into t2 select * from t1;
rollback to savepoint my_savepoint;
commit;
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=187" "xid=94"
+show binlog events from 98;
delete from t1;
delete from t2;
@@ -173,7 +192,9 @@ insert into t1 values(18);
commit;
select a from t1 order by a; # check that savepoints work :)
-show binlog events from 79;
+--replace_column 5 #
+--replace_result "xid=208" "xid=105"
+show binlog events from 98;
# Test for BUG#5714, where a MyISAM update in the transaction used to
# release row-level locks in InnoDB
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 27bdf4df3d7..5e3be6d45eb 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -2,9 +2,13 @@
# Test of update statement that uses many tables.
#
+# Requires grants, so won't work with embedded server test
+-- source include/not_embedded.inc
+
--disable_warnings
drop table if exists t1,t2,t3;
drop database if exists mysqltest;
+drop view if exists v1;
--error 0,1141,1147
revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
--error 0,1141,1147
@@ -449,3 +453,76 @@ delete t2, t1 from t2 left join t1 on (t2.aclid=t1.aclid) where t2.refid='1';
drop table t1, t2;
# End of 4.1 tests
+
+#
+# Test for bug #1980.
+#
+--disable_warnings
+create table t1 ( c char(8) not null ) engine=innodb;
+--enable_warnings
+
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+
+create table t2 like t1;
+insert into t2 select * from t1;
+
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+
+drop table t1,t2;
+
+--disable_warnings
+create table t1 ( c char(8) not null ) engine=bdb;
+--enable_warnings
+
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+
+create table t2 like t1;
+insert into t2 select * from t1;
+
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+
+drop table t1,t2;
+
+create table t1 (a int, b int);
+insert into t1 values (1, 2), (2, 3), (3, 4);
+create table t2 (a int);
+insert into t2 values (10), (20), (30);
+create view v1 as select a as b, a/10 as a from t2;
+
+connect (locker,localhost,root,,test);
+connection locker;
+lock table t1 write;
+
+connect (changer,localhost,root,,test);
+connection changer;
+send alter table t1 add column c int default 100 after a;
+
+connect (updater,localhost,root,,test);
+connection updater;
+send update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
+
+connection locker;
+sleep 2;
+unlock tables;
+
+connection changer;
+reap;
+
+connection updater;
+reap;
+select * from t1;
+select * from t2;
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index dc40ecc2dd4..73afcab5e27 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -450,11 +450,14 @@ drop table t1;
# Test text and unique
#
create table t1 (a int not null auto_increment primary key, b text not null, unique b (b(20)));
-insert into t1 (b) values ('a'),('a '),('a ');
+insert into t1 (b) values ('a'),('b'),('c');
select concat(b,'.') from t1;
update t1 set b='b ' where a=2;
--error 1062
update t1 set b='b ' where a > 1;
+--error 1062
+insert into t1 (b) values ('b');
+select * from t1;
delete from t1 where b='b';
select a,concat(b,'.') from t1;
drop table t1;
@@ -561,20 +564,6 @@ check table t1;
drop table t1;
-# BUG#9622 - ANALYZE TABLE and ALTER TABLE .. ENABLE INDEX produce
-# different statistics on the same table with NULL values.
-create table t1 (a int, key(a));
-
-insert into t1 values (1),(2),(3),(4),(NULL),(NULL),(NULL),(NULL);
-analyze table t1;
-show keys from t1;
-
-alter table t1 disable keys;
-alter table t1 enable keys;
-show keys from t1;
-
-drop table t1;
-
#
# Bug#12296 - CHECKSUM TABLE reports 0 for the table
# This happened if the first record was marked as deleted.
@@ -590,7 +579,10 @@ checksum table t1;
checksum table t2;
drop table t1, t2;
+#
# BUG#12232: New myisam_stats_method variable.
+#
+
show variables like 'myisam_stats_method';
create table t1 (a int, key(a));
@@ -638,3 +630,126 @@ show index from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Test varchar
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=MyISAM;
+source include/varchar.inc;
+
+#
+# Some errors/warnings on create
+#
+
+create table t1 (v varchar(65530), key(v));
+drop table if exists t1;
+create table t1 (v varchar(65536));
+show create table t1;
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+show create table t1;
+drop table t1;
+
+# MyISAM specific varchar tests
+--error 1118
+create table t1 (v varchar(65535));
+
+eval set storage_engine=$default;
+
+#
+# Test how DROP TABLE works if the index or data file doesn't exists
+
+create table t1 (a int) engine=myisam;
+system rm ./var/master-data/test/t1.MYI ;
+drop table if exists t1;
+create table t1 (a int) engine=myisam;
+system rm ./var/master-data/test/t1.MYI ;
+--error 1051,6
+drop table t1;
+create table t1 (a int) engine=myisam;
+system rm ./var/master-data/test/t1.MYD ;
+--error 1105,6,29
+drop table t1;
+--error 1051
+drop table t1;
+
+#
+# Test concurrent insert
+# First with static record length
+#
+set @save_concurrent_insert=@@concurrent_insert;
+set global concurrent_insert=1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5);
+lock table t1 read local;
+connect (con1,localhost,root,,);
+connection con1;
+# Insert in table without hole
+insert into t1 values(6),(7);
+connection default;
+unlock tables;
+delete from t1 where a>=3 and a<=4;
+lock table t1 read local;
+connection con1;
+set global concurrent_insert=2;
+# Insert in table with hole -> Should insert at end
+insert into t1 values (8),(9);
+connection default;
+unlock tables;
+# Insert into hole
+insert into t1 values (10),(11),(12);
+select * from t1;
+check table t1;
+drop table t1;
+
+# Same test with dynamic record length
+create table t1 (a int, b varchar(30) default "hello");
+insert into t1 (a) values (1),(2),(3),(4),(5);
+lock table t1 read local;
+connect (con1,localhost,root,,);
+connection con1;
+# Insert in table without hole
+insert into t1 (a) values(6),(7);
+connection default;
+unlock tables;
+delete from t1 where a>=3 and a<=4;
+lock table t1 read local;
+connection con1;
+set global concurrent_insert=2;
+# Insert in table with hole -> Should insert at end
+insert into t1 (a) values (8),(9);
+connection default;
+unlock tables;
+# Insert into hole
+insert into t1 (a) values (10),(11),(12);
+select a from t1;
+check table t1;
+drop table t1;
+set global concurrent_insert=@save_concurrent_insert;
+
+# BUG#9622 - ANALYZE TABLE and ALTER TABLE .. ENABLE INDEX produce
+# different statistics on the same table with NULL values.
+create table t1 (a int, key(a));
+
+insert into t1 values (1),(2),(3),(4),(NULL),(NULL),(NULL),(NULL);
+analyze table t1;
+show keys from t1;
+
+alter table t1 disable keys;
+alter table t1 enable keys;
+show keys from t1;
+
+drop table t1;
+
+#
+# Bug#10056 - PACK_KEYS option take values greater than 1 while creating table
+#
+create table t1 (c1 int) engine=myisam pack_keys=0;
+create table t2 (c1 int) engine=myisam pack_keys=1;
+create table t3 (c1 int) engine=myisam pack_keys=default;
+--error 1064
+create table t4 (c1 int) engine=myisam pack_keys=2;
+drop table t1, t2, t3;
+
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
new file mode 100644
index 00000000000..c1d9813ea39
--- /dev/null
+++ b/mysql-test/t/mysql.test
@@ -0,0 +1,43 @@
+#
+# Testing the MySQL command line client(mysql)
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Test the "delimiter" functionality
+# Bug#9879
+#
+create table t1(a int);
+insert into t1 values(1);
+
+# Test delimiters
+--exec $MYSQL test < "./t/mysql_delimiter.sql"
+
+--disable_query_log
+# Test delimiter : supplied on the command line
+select "Test delimiter : from command line" as " ";
+--exec $MYSQL test --delimiter=':' -e 'select * from t1:'
+# Test delimiter :; supplied on the command line
+select "Test delimiter :; from command line" as " ";
+--exec $MYSQL test --delimiter=':;' -e 'select * from t1:;'
+# Test 'go' command (vertical output) \G
+select "Test 'go' command(vertical output) \G" as " ";
+--exec $MYSQL test -e 'select * from t1\G'
+# Test 'go' command \g
+select "Test 'go' command \g" as " ";
+--exec $MYSQL test -e 'select * from t1\g'
+--enable_query_log
+drop table t1;
+
+#
+# BUG9998 - MySQL client hangs on USE "database"
+#
+create table t1(a int);
+lock tables t1 write;
+--exec $MYSQL -e 'use test; select database();'
+unlock tables;
+drop table t1;
+
diff --git a/mysql-test/t/mysql_delimiter.sql b/mysql-test/t/mysql_delimiter.sql
new file mode 100644
index 00000000000..fa80c980b29
--- /dev/null
+++ b/mysql-test/t/mysql_delimiter.sql
@@ -0,0 +1,51 @@
+
+# Test default delimiter ;
+select "Test default delimiter ;" as " ";
+select * from t1;
+
+# Test delimiter without argument
+select "Test delimiter without arg" as " ";
+# Nothing should be displayed, error is returned
+delimiter
+delimiter ; # Reset delimiter
+
+# Test delimiter :
+select "Test delimiter :" as " ";
+delimiter :
+select * from t1:
+delimiter ; # Reset delimiter
+
+# Test delimiter ':'
+select "Test delimiter :" as " ";
+delimiter ':'
+select * from t1:
+delimiter ; # Reset delimiter
+
+# Test delimiter :;
+select "Test delimiter :;" as " ";
+delimiter :;
+select * from t1 :;
+delimiter ; # Reset delimiter
+
+## Test delimiter //
+select "Test delimiter //" as " ";
+delimiter //
+select * from t1//
+delimiter ; # Reset delimiter
+
+# Test delimiter 'MySQL'
+select "Test delimiter MySQL" as " ";
+delimiter 'MySQL'
+select * from t1MySQL
+delimiter ; # Reset delimiter
+
+# Test delimiter 'delimiter'(should be allowed according to the code)
+select "Test delimiter delimiter" as " ";
+delimiter delimiter
+select * from t1 delimiter
+delimiter ; # Reset delimiter
+
+#
+# Bug #11523: \d works differently than delimiter
+#
+source t/mysql_delimiter_source.sql
diff --git a/mysql-test/t/mysql_delimiter_source.sql b/mysql-test/t/mysql_delimiter_source.sql
new file mode 100644
index 00000000000..f645091f3d4
--- /dev/null
+++ b/mysql-test/t/mysql_delimiter_source.sql
@@ -0,0 +1,8 @@
+delimiter //
+create table t2 (a int) //
+delimiter ;
+\d //
+create table t3 (a int) //
+\d ;
+show tables;
+drop table t2, t3;
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index 0f9faa5c337..e5bd8c554cb 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -27,7 +27,6 @@ load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
-load data infile '../../std_data/words.dat' into table t1;
# simple query to show more in second binlog
insert into t1 values ("Alas");
flush logs;
@@ -64,7 +63,7 @@ select "--- --database --" as "";
select "--- --position --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --position=27 $MYSQL_TEST_DIR/var/log/master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --position=231 $MYSQL_TEST_DIR/var/log/master-bin.000002
# These are tests for remote binlog.
# They should return the same as previous test.
@@ -96,7 +95,17 @@ select "--- --database --" as "";
select "--- --position --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --position=27 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --position=231 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
+
+# Bug#7853 (mysqlbinlog does not accept input from stdin)
+--disable_query_log
+select "--- reading stdin --" as "";
+--enable_query_log
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec cat $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 | $MYSQL_BINLOG --short-form -
+
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec cat $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 | $MYSQL_BINLOG --short-form --position=79 -
# clean up
drop table t1, t2;
diff --git a/mysql-test/t/mysqlbinlog2.test b/mysql-test/t/mysqlbinlog2.test
index 67131dd9d0d..a2f1aba05b0 100644
--- a/mysql-test/t/mysqlbinlog2.test
+++ b/mysql-test/t/mysqlbinlog2.test
@@ -49,11 +49,11 @@ select "--- offset --" as "";
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=497 $MYSQL_TEST_DIR/var/log/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --start-position=600 $MYSQL_TEST_DIR/var/log/master-bin.000001
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=497 $MYSQL_TEST_DIR/var/log/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --stop-position=600 $MYSQL_TEST_DIR/var/log/master-bin.000001
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -78,11 +78,11 @@ select "--- offset --" as "";
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=497 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
+--exec $MYSQL_BINLOG --short-form --start-position=600 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=32 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
+--exec $MYSQL_BINLOG --short-form --stop-position=126 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -105,11 +105,11 @@ select "--- offset --" as "";
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=497 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+--exec $MYSQL_BINLOG --short-form --start-position=600 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=497 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+--exec $MYSQL_BINLOG --short-form --stop-position=600 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -132,11 +132,11 @@ select "--- offset --" as "";
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=497 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
+--exec $MYSQL_BINLOG --short-form --start-position=600 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=32 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
+--exec $MYSQL_BINLOG --short-form --stop-position=126 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index f2d56eed151..2ce4b1071e2 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -2,7 +2,11 @@
--source include/not_embedded.inc
--disable_warnings
-DROP TABLE IF EXISTS t1, `"t"1`;
+DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa;
+drop database if exists mysqldump_test_db;
+drop database if exists db1;
+drop database if exists db2;
+drop view if exists v1, v2, v3;
--enable_warnings
# XML output
@@ -16,7 +20,7 @@ DROP TABLE t1;
# Bug #2005
#
-CREATE TABLE t1 (a decimal(240, 20));
+CREATE TABLE t1 (a decimal(64, 20));
INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
("0987654321098765432109876543210987654321");
--exec $MYSQL_DUMP --compact test t1
@@ -27,7 +31,7 @@ DROP TABLE t1;
#
CREATE TABLE t1 (a double);
-INSERT INTO t1 VALUES (-9e999999);
+INSERT INTO t1 VALUES ('-9e999999');
# The following replaces is here because some systems replaces the above
# double with '-inf' and others with MAX_DOUBLE
--replace_result (-1.79769313486232e+308) (RES) (NULL) (RES)
@@ -189,11 +193,11 @@ DROP TABLE t1;
# Test for --insert-ignore
#
-CREATE TABLE t1 (a decimal(240, 20));
-INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
-("0987654321098765432109876543210987654321");
---exec $MYSQL_DUMP --insert-ignore --skip-comments test t1
---exec $MYSQL_DUMP --insert-ignore --skip-comments --delayed-insert test t1
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 VALUES (4),(5),(6);
+--exec $MYSQL_DUMP --skip-comments --insert-ignore test t1
+--exec $MYSQL_DUMP --skip-comments --insert-ignore --delayed-insert test t1
DROP TABLE t1;
#
@@ -544,6 +548,63 @@ INSERT INTO t1 VALUES (1),(2),(3);
--exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test
DROP TABLE t1;
+
+#
+# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X)
+#
+
+create database db1;
+use db1;
+
+CREATE TABLE t2 (
+ a varchar(30) default NULL,
+ KEY a (a(5))
+);
+
+INSERT INTO t2 VALUES ('alfred');
+INSERT INTO t2 VALUES ('angie');
+INSERT INTO t2 VALUES ('bingo');
+INSERT INTO t2 VALUES ('waffle');
+INSERT INTO t2 VALUES ('lemon');
+create view v2 as select * from t2 where a like 'a%' with check option;
+--exec $MYSQL_DUMP --skip-comments db1
+drop table t2;
+drop view v2;
+drop database db1;
+
+#
+# Bug 10713 mysqldump includes database in create view and referenced tables
+#
+
+# create table and views in db2
+create database db2;
+use db2;
+create table t1 (a int);
+create table t2 (a int, b varchar(10), primary key(a));
+insert into t2 values (1, "on"), (2, "off"), (10, "pol"), (12, "meg");
+insert into t1 values (289), (298), (234), (456), (789);
+create view v1 as select * from t2;
+create view v2 as select * from t1;
+
+# dump tables and view from db2
+--exec $MYSQL_DUMP db2 > var/tmp/bug10713.sql
+
+# drop the db, tables and views
+drop table t1, t2;
+drop view v1, v2;
+drop database db2;
+
+# create db1 and reload dump
+create database db1;
+use db1;
+--exec $MYSQL db1 < var/tmp/bug10713.sql
+
+# check that all tables and views could be created
+show tables;
+select * from t2 order by a;
+
+drop table t1, t2;
+drop database db1;
#
# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data
#
@@ -556,6 +617,8 @@ INSERT INTO t1 VALUES (1), (2);
INSERT INTO t2 VALUES (1), (2);
--exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db
--exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db t1 t2
+--exec $MYSQL_DUMP --skip-comments --skip-create --xml --no-data mysqldump_test_db
+--exec $MYSQL_DUMP --skip-comments --skip-create --xml --no-data mysqldump_test_db t1 t2
DROP TABLE t1, t2;
DROP DATABASE mysqldump_test_db;
@@ -581,7 +644,7 @@ select '------ Testing with illegal table names ------' as test_sequence ;
--error 6
--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1
-
+
--error 6
--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1
@@ -622,7 +685,6 @@ drop table t1, t2, t3;
drop database mysqldump_test_db;
use test;
-
#
# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly
#
@@ -636,3 +698,222 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir
drop table t1, t2;
# End of 4.1 tests
+
+#
+# dump of view
+#
+create table t1(a int);
+create view v1 as select * from t1;
+--exec $MYSQL_DUMP --skip-comments test
+drop view v1;
+drop table t1;
+
+#
+# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X)
+#
+
+create database mysqldump_test_db;
+use mysqldump_test_db;
+
+CREATE TABLE t2 (
+ a varchar(30) default NULL,
+ KEY a (a(5))
+);
+
+INSERT INTO t2 VALUES ('alfred');
+INSERT INTO t2 VALUES ('angie');
+INSERT INTO t2 VALUES ('bingo');
+INSERT INTO t2 VALUES ('waffle');
+INSERT INTO t2 VALUES ('lemon');
+create view v2 as select * from t2 where a like 'a%' with check option;
+--exec $MYSQL_DUMP --skip-comments mysqldump_test_db
+drop table t2;
+drop view v2;
+drop database mysqldump_test_db;
+use test;
+
+#
+# Bug #9756
+#
+
+CREATE TABLE t1 (a char(10));
+INSERT INTO t1 VALUES ('\'');
+--exec $MYSQL_DUMP --skip-comments test t1
+DROP TABLE t1;
+
+#
+# Bug #10927 mysqldump: Can't reload dump with view that consist of other view
+#
+
+create table t1(a int, b int, c varchar(30));
+
+insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three");
+
+create view v3 as
+select * from t1;
+
+create view v1 as
+select * from v3 where b in (1, 2, 3, 4, 5, 6, 7);
+
+create view v2 as
+select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1;
+
+--exec $MYSQL_DUMP test > var/tmp/bug10927.sql
+drop view v1, v2, v3;
+drop table t1;
+--exec $MYSQL test < var/tmp/bug10927.sql
+
+# Without dropping the original tables in between
+--exec $MYSQL_DUMP test > var/tmp/bug10927.sql
+--exec $MYSQL test < var/tmp/bug10927.sql
+show full tables;
+show create view v1;
+select * from v1;
+
+drop view v1, v2, v3;
+drop table t1;
+#
+# Test for dumping triggers
+#
+
+CREATE TABLE t1 (a int, b bigint default NULL);
+CREATE TABLE t2 (a int);
+delimiter |;
+create trigger trg1 before insert on t1 for each row
+begin
+ if new.a > 10 then
+ set new.a := 10;
+ set new.a := 11;
+ end if;
+end|
+create trigger trg2 before update on t1 for each row begin
+ if old.a % 2 = 0 then set new.b := 12; end if;
+end|
+set sql_mode="traditional"|
+create trigger trg3 after update on t1 for each row
+begin
+ if new.a = -1 then
+ set @fired:= "Yes";
+ end if;
+end|
+create trigger trg4 before insert on t2 for each row
+begin
+ if new.a > 10 then
+ set @fired:= "No";
+ end if;
+end|
+set sql_mode=default|
+delimiter ;|
+--replace_column 6 '0000-00-00 00:00:00'
+show triggers like "t1";
+INSERT INTO t1 (a) VALUES (1),(2),(3),(22);
+update t1 set a = 4 where a=3;
+# Triggers should be dumped by default
+--exec $MYSQL_DUMP --skip-comments --databases test
+# Skip dumping triggers
+--exec $MYSQL_DUMP --skip-comments --databases --skip-triggers test
+# Dump and reload...
+--exec $MYSQL_DUMP --skip-comments --databases test > var/tmp/mysqldump.sql
+drop table t1;
+--exec $MYSQL test < var/tmp/mysqldump.sql
+# Check that tables have been reloaded
+show tables;
+--replace_column 6 #
+show triggers;
+DROP TABLE t1, t2;
+
+#
+# Bugs #9136, #12917: problems with --defaults-extra-file option
+#
+
+--exec echo "[mysqltest1]" > $MYSQL_TEST_DIR/var/tmp/tmp.cnf
+--exec echo "port=1234" >> $MYSQL_TEST_DIR/var/tmp/tmp.cnf
+--exec $MYSQL_MY_PRINT_DEFAULTS -c $MYSQL_TEST_DIR/var/tmp/tmp.cnf mysqltest1
+--exec $MYSQL_MY_PRINT_DEFAULTS -e $MYSQL_TEST_DIR/var/tmp/tmp.cnf mysqltest1 mysqltest1
+--exec rm $MYSQL_TEST_DIR/var/tmp/tmp.cnf
+
+#
+# Test of fix to BUG 12597
+#
+
+DROP TABLE IF EXISTS `test1`;
+CREATE TABLE `test1` (
+ `a1` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `test2`;
+CREATE TABLE `test2` (
+ `a2` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DELIMITER //;
+CREATE TRIGGER `testref` BEFORE INSERT ON `test1` FOR EACH ROW BEGIN
+INSERT INTO test2 SET a2 = NEW.a1; END //
+DELIMITER ;//
+
+INSERT INTO `test1` VALUES (1);
+SELECT * FROM `test2`;
+
+# dump
+--exec $MYSQL_DUMP --skip-comments --databases test > var/tmp/mysqldump.sql
+
+#DROP TRIGGER testref;
+#DROP TABLE test1;
+#DROP TABLE test2;
+# restore
+--exec $MYSQL test < var/tmp/mysqldump.sql
+SHOW TRIGGERS;
+SELECT * FROM `test1`;
+SELECT * FROM `test2`;
+
+DROP TRIGGER testref;
+DROP TABLE test1;
+DROP TABLE test2;
+
+#
+# BUG#9056 - mysqldump does not dump routines
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS bug9056_func1;
+DROP FUNCTION IF EXISTS bug9056_func2;
+DROP PROCEDURE IF EXISTS bug9056_proc1;
+DROP PROCEDURE IF EXISTS bug9056_proc2;
+--enable_warnings
+
+CREATE TABLE t1 (id int);
+INSERT INTO t1 VALUES(1), (2), (3), (4), (5);
+
+DELIMITER //;
+CREATE FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11) RETURN a+b //
+CREATE PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
+BEGIN SELECT a+b INTO c; end //
+
+create function bug9056_func2(f1 char binary) returns char binary
+begin
+ set f1= concat( 'hello', f1 );
+ return f1;
+end //
+
+CREATE PROCEDURE bug9056_proc2(OUT a INT)
+BEGIN
+ select sum(id) from t1 into a;
+END //
+
+DELIMITER ;//
+
+set sql_mode='ansi';
+create procedure `a'b` () select 1; # to fix syntax highlighting :')
+set sql_mode='';
+
+# Dump the DB and ROUTINES
+--exec $MYSQL_DUMP --skip-comments --routines --databases test
+
+# ok, now blow it all away
+DROP FUNCTION bug9056_func1;
+DROP FUNCTION bug9056_func2;
+DROP PROCEDURE bug9056_proc1;
+DROP PROCEDURE bug9056_proc2;
+drop table t1;
+
diff --git a/mysql-test/t/mysqlshow.test b/mysql-test/t/mysqlshow.test
new file mode 100644
index 00000000000..33ae8aef9a0
--- /dev/null
+++ b/mysql-test/t/mysqlshow.test
@@ -0,0 +1,23 @@
+# Can't run test of external client with embedded server
+-- source include/not_embedded.inc
+
+#
+## Bug #5036 mysqlshow is missing a column
+#
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE TABLE t2 (a int, b int);
+show tables;
+select "--------------------" as "";
+--exec $MYSQL_SHOW test
+select "---- -v ------------" as "";
+--exec $MYSQL_SHOW test -v
+select "---- -v -v ---------" as "";
+--exec $MYSQL_SHOW test -v -v
+select "----- -t -----------" as "";
+--exec $MYSQL_SHOW test -t
+select "---- -v -t ---------" as "";
+--exec $MYSQL_SHOW test -v -t
+select "---- -v -v -t ------" as "";
+--exec $MYSQL_SHOW test -v -v -t
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index 4d3bcc037d1..c903749839d 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -369,6 +369,8 @@ select 3 from t1 ;
#
--error 1
--exec echo "--sleep 4;" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--disable_query_log;" | $MYSQL_TEST 2>&1
# Allow trailing # comment
@@ -838,3 +840,50 @@ while ($num)
SELECT 1 as a;
+
+#
+# Bug #10251: Identifiers containing quotes not handled correctly
+#
+select 1 as `a'b`, 2 as `a"b`;
+
+# Test escaping of quotes
+select 'aaa\\','aa''a',"aa""a";
+
+#
+# Check of include/show_msg.inc and include/show_msg80.inc
+#
+
+# The message contains in most cases a string with the default character set
+let $message= Here comes a message;
+--source include/show_msg.inc
+
+# The message could also contain a string with character set utf8
+let $message= `SELECT USER()`;
+--source include/show_msg.inc
+
+# The message contains more then 80 characters on multiple lines
+# and is kept between double quotes.
+let $message=
+"Here comes a very very long message that
+ - is longer then 80 characters and
+ - consists of several lines";
+--source include/show_msg80.inc
+
+# The message contains more then 80 characters on multiple lines
+# and uses the auxiliary character "." at the beginning of the message lines.
+let $message= . Here comes a very very long message that
+ . - is longer then 80 characters and
+ . - consists of several lines;
+--source include/show_msg80.inc
+
+#
+# Test --enable_parsning / disable_parsning
+#
+--disable_query_log
+--disable_parsing
+# The following will not enable query logging
+--enable_query_log
+select "this will not be executed";
+--enable_parsing
+select "this will be executed";
+--enable_query_log
diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test
index b5b73ad1998..0f7b0bb7edc 100644
--- a/mysql-test/t/ndb_alter_table.test
+++ b/mysql-test/t/ndb_alter_table.test
@@ -56,10 +56,12 @@ 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) ENGINE=ndbcluster;
+--replace_column 7 # 8 # 10 # 12 # 13 # 14 # 18 #
show table status;
SET SQL_MODE=NO_AUTO_VALUE_ON_ZERO;
insert into t1 values
(0,4,3,5,"PENDING",1,7),(NULL,4,3,5,"PENDING",1,7),(31,4,3,5,"PENDING",1,7), (7,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7), (100,4,3,5,"PENDING",1,7), (99,4,3,5,"PENDING",1,7), (8,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7);
+--replace_column 7 # 8 # 10 # 12 # 13 # 14 # 18 #
show table status;
select * from t1 order by col1;
alter table t1
@@ -68,9 +70,11 @@ 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;
+--replace_column 7 # 8 # 10 # 12 # 13 # 14 # 18 #
show table status;
select * from t1 order by col1;
insert into t1 values (2, NULL,4,3,5,99,"PENDING","EXTRA",'2004-01-01 00:00:00');
+--replace_column 7 # 8 # 10 # 12 # 13 # 14 # 18 #
show table status;
select * from t1 order by col1;
delete from t1;
@@ -200,3 +204,4 @@ show tables;
connection server1;
# End of 4.1 tests
+
diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test
index e45133afbca..6bbb1c2f2f2 100644
--- a/mysql-test/t/ndb_autodiscover.test
+++ b/mysql-test/t/ndb_autodiscover.test
@@ -177,7 +177,7 @@ show status like 'handler_discover%';
flush tables;
system rm var/master-data/test/t7.frm ;
---replace_column 7 # 8 # 9 # 12 # 13 # 15 #
+--replace_column 7 # 8 # 9 # 12 # 13 # 15 # 18 #
show table status;
show status like 'handler_discover%';
@@ -210,8 +210,30 @@ select * from t4;
select * from t4;
show status like 'handler_discover%';
+--error 1051
drop table t4;
+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 exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 >> $NDB_TOOLS_OUTPUT ;
+
+--error 1146
+select * from t4;
+
+drop table if exists t4;
+
+# Test that dropping a table that does not exists
+# on disk or in NDB gives same result as above
+--error 1051
+drop table t5;
+drop table if exists t5;
+
#######################################################
# Test that a table that has been dropped from NDB
@@ -450,9 +472,28 @@ drop table t1;
use test2;
drop table t2;
drop database test2;
-show databases;
use test;
+#########################################################
+# Bug#8035
+# mysqld would segfault on second select * before bug was fixed
+#
+--disable_warnings
+drop database if exists test_only_ndb_tables;
+--enable_warnings
+create database test_only_ndb_tables;
+use test_only_ndb_tables;
+create table t1 (a int primary key) engine=ndb;
+select * from t1;
+--exec $NDB_MGM --no-defaults -e "all restart -n" > /dev/null
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults --not-started > /dev/null
+--error 1015
+select * from t1;
+--exec $NDB_MGM --no-defaults -e "all start" > /dev/null
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults > /dev/null
+use test;
+drop database test_only_ndb_tables;
+
#####################################################
# Test that it's not possible to create tables
# with same name as NDB internal tables
diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test
index 144e466d937..1c78a4b8744 100644
--- a/mysql-test/t/ndb_basic.test
+++ b/mysql-test/t/ndb_basic.test
@@ -551,7 +551,7 @@ create table t1
(a bigint, b bigint, c bigint, d bigint,
primary key (a,b,c,d))
engine=ndb
- max_rows=200000000;
+ max_rows=800000000;
insert into t1 values
(1,2,3,4),(2,3,4,5),(3,4,5,6),
(3,2,3,4),(1,3,4,5),(2,4,5,6),
@@ -607,3 +607,11 @@ select * from t1 order by counter;
drop table t1;
# End of 4.1 tests
+
+#
+# Test long table name
+#
+create table atablewithareallylongandirritatingname (a int);
+insert into atablewithareallylongandirritatingname values (2);
+select * from atablewithareallylongandirritatingname;
+drop table atablewithareallylongandirritatingname;
diff --git a/mysql-test/t/ndb_bitfield.test b/mysql-test/t/ndb_bitfield.test
new file mode 100644
index 00000000000..0256ecf89ed
--- /dev/null
+++ b/mysql-test/t/ndb_bitfield.test
@@ -0,0 +1,114 @@
+-- source include/have_ndb.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (
+ pk1 int not null primary key,
+ b bit(64)
+) engine=ndbcluster;
+
+show create table t1;
+insert into t1 values
+(0,b'1111111111111111111111111111111111111111111111111111111111111111'),
+(1,b'1000000000000000000000000000000000000000000000000000000000000000'),
+(2,b'0000000000000000000000000000000000000000000000000000000000000001'),
+(3,b'1010101010101010101010101010101010101010101010101010101010101010'),
+(4,b'0101010101010101010101010101010101010101010101010101010101010101');
+select hex(b) from t1 order by pk1;
+drop table t1;
+
+create table t1 (
+ pk1 int not null primary key,
+ b bit(9)
+) engine=ndbcluster;
+insert into t1 values
+(0,b'000000000'),
+(1,b'000000001'),
+(2,b'000000010'),
+(3,b'000000011'),
+(4,b'000000100');
+select hex(b) from t1 order by pk1;
+update t1 set b = b + b'101010101';
+select hex(b) from t1 order by pk1;
+drop table t1;
+
+create table t1 (a bit(7), b bit(9)) engine = ndbcluster;
+insert into t1 values
+(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177),
+(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380),
+(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36),
+(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499),
+(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403),
+(44, 307), (68, 454), (57, 135);
+select a+0 from t1 order by a;
+select b+0 from t1 order by b;
+drop table t1;
+
+create table t1 (
+ dummyKey INTEGER NOT NULL,
+ a001 TINYINT,
+ a010 TINYINT,
+ a012 TINYINT,
+ a015 TINYINT,
+ a016 TINYINT,
+ a017 TINYINT,
+ a019 TINYINT,
+ a029 TINYINT,
+ a030 TINYINT,
+ a031 TINYINT,
+ a032 TINYINT,
+ a042 TINYINT,
+ a043 TINYINT,
+ a044 TINYINT,
+ a3001 TINYINT,
+ a3002 TINYINT,
+ a3003 TINYINT,
+ a3004 TINYINT,
+ a3005 TINYINT,
+ a3021 TINYINT,
+ a3022 TINYINT,
+ a BIT(6),
+ b BIT(6),
+ c BIT(6),
+ d TINYINT,
+ e TINYINT,
+ f TINYINT,
+ g TINYINT,
+ h TINYINT,
+ i TINYINT,
+ j TINYINT,
+ k TINYINT,
+ l TINYINT,
+ m TINYINT,
+ n TINYINT,
+ o TINYINT,
+ a034 TINYINT,
+PRIMARY KEY USING HASH (dummyKey) ) engine=ndb;
+INSERT INTO `t1` VALUES
+(1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000001',b'111111',b'111110',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000010',b'000000',b'111101',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000100',b'001111',b'111011',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'001000',b'110000',b'110111',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'010000',b'100001',b'101111',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'100000',b'010010',b'011111',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'001100',b'111111',4,5,5,5,5,5,5,5,5,5,3,2,1),
+(8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1);
+--exec $MYSQL_DUMP --hex-blob --compact --order-by-primary --skip-extended-insert --no-create-info test t1
+drop table t1;
+
+--error 1005
+create table t1 (
+ pk1 bit(9) not null primary key,
+ b int
+) engine=ndbcluster;
+
+--error 1005
+create table t1 (
+ pk1 int not null primary key,
+ b bit(9),
+ key(b)
+) engine=ndbcluster;
+
diff --git a/mysql-test/t/ndb_cache.test b/mysql-test/t/ndb_cache.test
index 481ec156307..9c299b61c24 100644
--- a/mysql-test/t/ndb_cache.test
+++ b/mysql-test/t/ndb_cache.test
@@ -2,32 +2,120 @@
-- source include/have_ndb.inc
-- source include/not_embedded.inc
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+# Turn on and reset query cache
+set GLOBAL query_cache_type=on;
set GLOBAL query_cache_size=1355776;
reset query cache;
flush status;
---disable_warnings
-drop table if exists t1,t2;
---enable_warnings
+# Create test table in NDB
+CREATE TABLE t1 ( pk int not null primary key,
+ a int, b int not null, c varchar(20)) ENGINE=ndbcluster;
+insert into t1 value (1, 2, 3, 'First row');
-CREATE TABLE t1 (a int) ENGINE=ndbcluster;
-CREATE TABLE t2 (a int);
+# Perform one query which should be inerted in query cache
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Perform the same query and make sure the query cache is hit
+select * from t1;
+show status like "Qcache_hits";
+# Update the table and make sure the correct data is returned
+update t1 set a=3 where pk=1;
select * from t1;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Insert a new record and make sure the correct data is returned
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+select * from t1 order by pk;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1 order by pk;
+show status like "Qcache_hits";
+
+# Perform a "new" query and make sure the query cache is not hit
+select * from t1 where b=3;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+
+# Same query again...
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Delete from the table
+delete from t1 where c='Fourth row';
show status like "Qcache_queries_in_cache";
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Start another connection and check that the query cache is hit
+connect (con1,localhost,root,,);
+connection con1;
+use test;
+select * from t1 order by pk;
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Update the table and switch to other connection
+update t1 set a=4 where b=3;
+connect (con2,localhost,root,,);
+connection con2;
+use test;
+show status like "Qcache_queries_in_cache";
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
show status like "Qcache_inserts";
show status like "Qcache_hits";
-select * from t2;
+connection con1;
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
show status like "Qcache_queries_in_cache";
show status like "Qcache_inserts";
show status like "Qcache_hits";
-select * from t1;
-select * from t2;
+
+# Use transactions and make sure the query cache is not updated until
+# transaction is commited
+begin;
+update t1 set a=5 where pk=1;
+# Note!! the below test shows that table is invalidated
+# before transaction is committed
+# TODO Fix so that cache is not invalidated HERE!
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+commit;
+# TODO Here query is invalidated once again, commit count in NDB has changed
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+select * from t1 order by pk desc;
show status like "Qcache_queries_in_cache";
show status like "Qcache_inserts";
show status like "Qcache_hits";
-drop table t1, t2;
+drop table t1;
+
+show status like "Qcache_queries_in_cache";
SET GLOBAL query_cache_size=0;
diff --git a/mysql-test/t/ndb_cache2.test b/mysql-test/t/ndb_cache2.test
new file mode 100644
index 00000000000..352b01ef73f
--- /dev/null
+++ b/mysql-test/t/ndb_cache2.test
@@ -0,0 +1,361 @@
+-- source include/have_query_cache.inc
+-- source include/have_ndb.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+drop table if exists t1, t2, t3, t4, t5;
+--enable_warnings
+
+
+# Turn on and reset query cache
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+# Turn on thread that will fetch commit count for open tables
+set GLOBAL ndb_cache_check_time=100;
+reset query cache;
+flush status;
+
+# Create test tables in NDB
+CREATE TABLE t1 (
+ pk int not null primary key,
+ a1 int,
+ b1 int not null,
+ c1 varchar(20)
+) ENGINE=ndb;
+CREATE TABLE t2 (
+ pk int not null primary key,
+ a2 int,
+ b2 int not null
+) ENGINE=ndb;
+CREATE TABLE t3 (
+ pk int not null primary key,
+ a3 int,
+ b3 int not null,
+ c3 int not null,
+ d3 varchar(20)
+) ENGINE=ndb;
+CREATE TABLE t4 (
+ a4 int,
+ b4 int not null,
+ c4 char(20)
+) ENGINE=ndbcluster;
+CREATE TABLE t5 (
+ pk int not null primary key,
+ a5 int,
+ b5 int not null,
+ c5 varchar(255)
+) ENGINE=ndbcluster;
+insert into t1 value (1, 2, 3, 'First row');
+insert into t2 value (1, 2, 3);
+insert into t3 value (1, 2, 3, 4, '3 - First row');
+insert into t4 value (2, 3, '4 - First row');
+insert into t5 value (1, 2, 3, '5 - First row');
+
+# Perform one query which should be inserted in query cache
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Perform the same query and make sure the query cache is hit
+select * from t1;
+show status like "Qcache_hits";
+
+# Update the table and make sure the correct data is returned
+update t1 set a1=3 where pk=1;
+select * from t1;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Insert a new record and make sure the correct data is returned
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1 order by pk desc;
+show status like "Qcache_hits";
+
+# Perform a "new" query and make sure the query cache is not hit
+select * from t1 where b1=3;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+
+# Same query again...
+select * from t1 where b1=3;
+show status like "Qcache_hits";
+
+# Delete from the table
+delete from t1 where c1='Fourth row';
+show status like "Qcache_queries_in_cache";
+select * from t1 where b1=3;
+show status like "Qcache_hits";
+
+# Start another connection and check that the query cache is hit
+connect (con1,localhost,root,,);
+connection con1;
+use test;
+select * from t1 order by pk desc;
+select * from t1 where b1=3;
+show status like "Qcache_hits";
+
+# Update the table and switch to other connection
+update t1 set a1=4 where b1=3;
+connect (con2,localhost,root,,);
+connection con2;
+use test;
+show status like "Qcache_queries_in_cache";
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Load all tables into cache
+select * from t2;
+select * from t3;
+select * from t4;
+select * from t5;
+show status like "Qcache_queries_in_cache";
+
+#####################################################################
+# Start transaction and perform update
+# Switch to other transaction and check that update does not show up
+# Switch back and commit transaction
+# Switch to other transaction and check that update shows up
+#####################################################################
+connection con1;
+flush status;
+begin;
+update t1 set a1=5 where pk=1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+commit;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+#####################################################################
+# Start transaction and perform update
+# Switch to other transaction and check that update does not show up
+# Switch back, perform selects and commit transaction
+# Switch to other transaction and check that update shows up
+#####################################################################
+connection con1;
+flush status;
+begin;
+update t1 set a1=6 where pk=1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+# The two queries below will not hit cache since transaction is ongoing
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+commit;
+
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+#####################################################################
+# Start transaction and perform insert
+# Switch to other transaction and check that insert does not show up
+# Switch back, perform selects and commit transaction
+# Switch to other transaction and check that update shows up
+#####################################################################
+connection con1;
+flush status;
+begin;
+insert into t1 set pk=5, a1=6, b1=3, c1="New row";
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 where pk=5;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+# The below four queries will not be cached, trans is ongoing
+select * from t1 where pk=5;
+select * from t1 where pk=5;
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+commit;
+
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+connection con1;
+
+#####################################################################
+# Start transaction and perform delete
+# Switch to other transaction and check that delete does not show up
+# Switch back, perform selects and commit transaction
+# Switch to other transaction and check that update shows up
+#####################################################################
+connection con1;
+flush status;
+begin;
+delete from t1 where pk=2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 where pk=2;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+# The below four queries will not be cached, trans is ongoing
+select * from t1 where pk=2;
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+select * from t1 where pk=2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+commit;
+
+connection con2;
+select * from t1 order by pk desc;
+select * from t1 where pk=2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+connection con1;
+
+#####################################################################
+# Start a transaction which updates all tables
+# Switch to other transaction and check updates does not show up
+# Switch back, perform selects and commit transaction
+# Switch to other transaction and check that update shows up
+#####################################################################
+flush status;
+begin;
+update t1 set a1=9 where pk=1;
+update t2 set a2=9 where pk=1;
+update t3 set a3=9 where pk=1;
+update t4 set a4=9 where a4=2;
+update t5 set a5=9 where pk=1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+select * from t2;
+select * from t3;
+select * from t4;
+select * from t5;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+# The below five queries will not be cached, trans is ongoing
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+select * from t2;
+select * from t3;
+select * from t4;
+select * from t5;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+commit;
+
+connection con2;
+select * from t1 order by pk desc;
+select * from t2;
+select * from t3;
+select * from t4;
+select * from t5;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+connection con1;
+select * from t1 order by pk desc;
+select * from t2;
+select * from t3;
+select * from t4;
+select * from t5;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1 order by pk desc;
+select * from t2;
+select * from t3;
+select * from t4;
+select * from t5;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+connection con2;
+select * from t1 order by pk desc;
+select * from t2;
+select * from t3;
+select * from t4;
+select * from t5;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop table t1, t2, t3, t4, t5;
+
+# There should be no queries in cache, when tables have been dropped
+show status like "Qcache_queries_in_cache";
+
+SET GLOBAL query_cache_size=0;
+SET GLOBAL ndb_cache_check_time=0;
+
+
diff --git a/mysql-test/t/ndb_cache_multi.test b/mysql-test/t/ndb_cache_multi.test
new file mode 100644
index 00000000000..beb8e4bc2ac
--- /dev/null
+++ b/mysql-test/t/ndb_cache_multi.test
@@ -0,0 +1,65 @@
+-- source include/have_query_cache.inc
+-- source include/have_ndb.inc
+-- source include/have_multi_ndb.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+
+# Turn on and reset query cache on server1
+connection server1;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+
+# Turn on and reset query cache on server2
+connection server2;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+
+
+
+# Create test tables in NDB and load them into cache
+# on server1
+connection server1;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+select * from t2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+
+# Connect server2, load table in to cache, then update the table
+connection server2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+update t1 set a=3 where a=2;
+
+# Connect to server1 and check that cache is invalidated
+# and correct data is returned
+connection server1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop table t1, t2;
+
+
diff --git a/mysql-test/t/ndb_cache_multi2.test b/mysql-test/t/ndb_cache_multi2.test
new file mode 100644
index 00000000000..9352505649c
--- /dev/null
+++ b/mysql-test/t/ndb_cache_multi2.test
@@ -0,0 +1,82 @@
+-- source include/have_query_cache.inc
+-- source include/have_ndb.inc
+-- source include/have_multi_ndb.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+
+# Turn on and reset query cache on server1
+connection server1;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=1;
+reset query cache;
+flush status;
+
+# Turn on and reset query cache on server2
+connection server2;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=1;
+reset query cache;
+flush status;
+
+# Sleep so that the query cache check thread has time to start
+sleep 15;
+
+
+# Create test tables in NDB and load them into cache
+# on server1
+connection server1;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+select * from t2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+
+# Connect server2, load table in to cache, then update the table
+connection server2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+update t1 set a=3 where a=2;
+
+# Sleep so that the query cache check thread has time to run
+sleep 5;
+
+# Connect to server1 and check that cache is invalidated
+# and correct data is returned
+connection server1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop table t1, t2;
+
+# Turn off and reset query cache on server1 and server2
+connection server1;
+set GLOBAL query_cache_size=0;
+set GLOBAL ndb_cache_check_time=0;
+reset query cache;
+flush status;
+connection server2;
+set GLOBAL query_cache_size=0;
+set GLOBAL ndb_cache_check_time=0;
+reset query cache;
+flush status;
diff --git a/mysql-test/t/ndb_charset.test b/mysql-test/t/ndb_charset.test
index 89f1ed17cfb..fb43e1831f3 100644
--- a/mysql-test/t/ndb_charset.test
+++ b/mysql-test/t/ndb_charset.test
@@ -54,6 +54,25 @@ select * from t1 where a = 'AaA';
select * from t1 where a = 'AAA';
drop table t1;
+# pk - varchar
+
+create table t1 (
+ a varchar(20) character set latin1 collate latin1_swedish_ci primary key
+) engine=ndb;
+#
+insert into t1 values ('A'),('b '),('C '),('d '),('E'),('f');
+-- error 1062
+insert into t1 values('b');
+-- error 1062
+insert into t1 values('a ');
+#
+select a,length(a) from t1 order by a;
+select a,length(a) from t1 order by a desc;
+select * from t1 where a = 'a';
+select * from t1 where a = 'a ';
+select * from t1 where a = 'd';
+drop table t1;
+
# unique hash index - binary
create table t1 (
@@ -103,6 +122,27 @@ select * from t1 where a = 'AaA';
select * from t1 where a = 'AAA';
drop table t1;
+# unique hash index - varchar
+
+create table t1 (
+ p int primary key,
+ a varchar(20) character set latin1 collate latin1_swedish_ci not null,
+ unique key(a)
+) engine=ndb;
+#
+insert into t1 values (1,'A'),(2,'b '),(3,'C '),(4,'d '),(5,'E'),(6,'f');
+-- error 1062
+insert into t1 values(99,'b');
+-- error 1062
+insert into t1 values(99,'a ');
+#
+select a,length(a) from t1 order by a;
+select a,length(a) from t1 order by a desc;
+select * from t1 where a = 'a';
+select * from t1 where a = 'a ';
+select * from t1 where a = 'd';
+drop table t1;
+
# ordered index - binary
create table t1 (
@@ -159,9 +199,47 @@ select * from t1 where a = 'AaA' order by p;
select * from t1 where a = 'AAA' order by p;
drop table t1;
+# ordered index - varchar
+
+create table t1 (
+ p int primary key,
+ a varchar(20) character set latin1 collate latin1_swedish_ci not null,
+ index(a, p)
+) engine=ndb;
+#
+insert into t1 values (1,'A'),(2,'b '),(3,'C '),(4,'d '),(5,'E'),(6,'f');
+insert into t1 values (7,'a'),(8,'B '),(9,'c '),(10,'D'),(11,'e'),(12,'F ');
+select p,a,length(a) from t1 order by a, p;
+select * from t1 where a = 'a ' order by a desc, p desc;
+select * from t1 where a >= 'D' order by a, p;
+select * from t1 where a < 'D' order by a, p;
+#
+select count(*) from t1 x, t1 y, t1 z where x.a = y.a and y.a = z.a;
+drop table t1;
+
+# minimal multi-byte test
+# removed by jonas as this requires a configure --with-extra-charsets
+#create table t1 (
+# a char(5) character set ucs2,
+# b varchar(7) character set utf8,
+# primary key(a, b)
+#) engine=ndb;
+#
+#insert into t1 values
+# ('a','A '),('B ','b'),('c','C '),('D','d'),('e ','E'),('F','f '),
+# ('A','b '),('b ','C'),('C','d '),('d','E'),('E ','f'),
+# ('a','C '),('B ','d'),('c','E '),('D','f');
+#-- error 1062
+#insert into t1 values('d','f');
+#
+#select a,b,length(a),length(b) from t1 order by a,b limit 3;
+#select a,b,length(a),length(b) from t1 order by a desc, b desc limit 3;
+#select a,b,length(a),length(b) from t1 where a='c' and b='c';
+#drop table t1;
+
# bug
create table t1 (
- a varchar(10) primary key
+ a char(10) primary key
) engine=ndb;
insert into t1 values ('jonas % ');
replace into t1 values ('jonas % ');
diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test
new file mode 100644
index 00000000000..d090d12e81b
--- /dev/null
+++ b/mysql-test/t/ndb_condition_pushdown.test
@@ -0,0 +1,1643 @@
+-- source include/have_ndb.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
+
+#
+# Test of condition pushdown to storage engine
+#
+CREATE TABLE t1 (
+ auto int(5) unsigned NOT NULL auto_increment,
+ string char(10),
+ vstring varchar(10),
+ bin binary(7),
+ vbin varbinary(7),
+ tiny tinyint(4) DEFAULT '0' NOT NULL ,
+ short smallint(6) DEFAULT '1' NOT NULL ,
+ medium mediumint(8) DEFAULT '0' NOT NULL,
+ long_int int(11) DEFAULT '0' NOT NULL,
+ longlong bigint(13) DEFAULT '0' NOT NULL,
+ real_float float(13,1) DEFAULT 0.0 NOT NULL,
+ real_double double(16,4),
+ real_decimal decimal(16,4),
+ utiny tinyint(3) unsigned DEFAULT '0' NOT NULL,
+ ushort smallint(5) unsigned zerofill DEFAULT '00000' NOT NULL,
+ umedium mediumint(8) unsigned DEFAULT '0' NOT NULL,
+ ulong int(11) unsigned DEFAULT '0' NOT NULL,
+ ulonglong bigint(13) unsigned DEFAULT '0' NOT NULL,
+ bits bit(3),
+ options enum('zero','one','two','three','four') not null,
+ flags set('zero','one','two','three','four') not null,
+ date_field date,
+ year_field year,
+ time_field time,
+ date_time datetime,
+ time_stamp timestamp,
+ PRIMARY KEY (auto)
+) engine=ndb;
+
+insert into t1 values
+(NULL,"aaaa","aaaa",0xAAAA,0xAAAA,-1,-1,-1,-1,-1,1.1,1.1,1.1,1,1,1,1,1,
+ b'001','one','one',
+ '1901-01-01','1901',
+'01:01:01','1901-01-01 01:01:01',NULL),
+(NULL,"bbbb","bbbb",0xBBBB,0xBBBB,-2,-2,-2,-2,-2,2.2,2.2,2.2,2,2,2,2,2,
+ b'010','two','one,two',
+ '1902-02-02','1902',
+'02:02:02','1902-02-02 02:02:02',NULL),
+(NULL,"cccc","cccc",0xCCCC,0xCCCC,-3,-3,-3,-3,-3,3.3,3.3,3.3,3,3,3,3,3,
+ b'011','three','one,two,three',
+ '1903-03-03','1903',
+'03:03:03','1903-03-03 03:03:03',NULL),
+(NULL,"dddd","dddd",0xDDDD,0xDDDD,-4,-4,-4,-4,-4,4.4,4.4,4.4,4,4,4,4,4,
+ b'100','four','one,two,three,four',
+ '1904-04-04','1904',
+'04:04:04','1904-04-04 04:04:04',NULL);
+
+CREATE TABLE t2 (pk1 int unsigned NOT NULL PRIMARY KEY, attr1 int unsigned NOT NULL, attr2 int unsigned, attr3 VARCHAR(10) ) ENGINE=ndbcluster;
+
+insert into t2 values (0,0,0, "a"),(1,1,1,"b"),(2,2,NULL,NULL),(3,3,3,"d"),(4,4,4,"e"),(5,5,5,"f");
+
+CREATE TABLE t3 (pk1 int unsigned NOT NULL PRIMARY KEY, attr1 int unsigned NOT NULL, attr2 bigint unsigned, attr3 tinyint unsigned, attr4 VARCHAR(10) ) ENGINE=ndbcluster;
+
+insert into t3 values (0,0,0,0,"a"),(1,1,9223372036854775803,1,"b"),(2,2,9223372036854775804,2,"c"),(3,3,9223372036854775805,3,"d"),(4,4,9223372036854775806,4,"e"),(5,5,9223372036854775807,5,"f");
+
+CREATE TABLE t4 (pk1 int unsigned NOT NULL PRIMARY KEY, attr1 int unsigned NOT NULL, attr2 bigint unsigned, attr3 tinyint unsigned, attr4 VARCHAR(10) , KEY (attr1)) ENGINE=ndbcluster;
+
+insert into t4 values (0,0,0,0,"a"),(1,1,9223372036854775803,1,"b"),(2,2,9223372036854775804,2,"c"),(3,3,9223372036854775805,3,"d"),(4,4,9223372036854775806,4,"e"),(5,5,9223372036854775807,5,"f");
+
+set @old_ecpd = @@session.engine_condition_pushdown;
+set engine_condition_pushdown = off;
+
+# Test all types and compare operators
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+bits = b'001' and
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+bits != b'001' and
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+bits > b'001' and
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+bits >= b'001' and
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+bits < b'100' and
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 and
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+bits <= b'100' and
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+
+# Test LIKE/NOT LIKE
+select auto from t1 where
+string like "b%" and
+vstring like "b%" and
+bin like concat(0xBB, '%') and
+vbin like concat(0xBB, '%')
+order by auto;
+
+select auto from t1 where
+string not like "b%" and
+vstring not like "b%" and
+bin not like concat(0xBB, '%') and
+vbin not like concat(0xBB, '%')
+order by auto;
+
+# BETWEEN
+select auto from t1 where
+(string between "aaaa" and "cccc") and
+(vstring between "aaaa" and "cccc") and
+(bin between 0xAAAA and 0xCCCC) and
+(vbin between 0xAAAA and 0xCCCC) and
+(tiny between -3 and -1) and
+(short between -3 and -1) and
+(medium between -3 and -1) and
+(long_int between -3 and -1) and
+(longlong between -3 and -1) and
+(utiny between 1 and 3) and
+(ushort between 1 and 3) and
+(umedium between 1 and 3) and
+(ulong between 1 and 3) and
+(ulonglong between 1 and 3) and
+(bits between b'001' and b'011') and
+(options between 'one' and 'three') and
+(flags between 'one' and 'one,two,three') and
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+
+select auto from t1 where
+("aaaa" between string and string) and
+("aaaa" between vstring and vstring) and
+(0xAAAA between bin and bin) and
+(0xAAAA between vbin and vbin) and
+(-1 between tiny and tiny) and
+(-1 between short and short) and
+(-1 between medium and medium) and
+(-1 between long_int and long_int) and
+(-1 between longlong and longlong) and
+(1 between utiny and utiny) and
+(1 between ushort and ushort) and
+(1 between umedium and umedium) and
+(1 between ulong and ulong) and
+(1 between ulonglong and ulonglong) and
+(b'001' between bits and bits) and
+('one' between options and options) and
+('one' between flags and flags) and
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and
+('1901-01-01 01:01:01' between date_time and date_time)
+order by auto;
+
+# NOT BETWEEN
+select auto from t1 where
+(string not between "aaaa" and "cccc") and
+(vstring not between "aaaa" and "cccc") and
+(bin not between 0xAAAA and 0xCCCC) and
+(vbin not between 0xAAAA and 0xCCCC) and
+(tiny not between -3 and -1) and
+(short not between -3 and -1) and
+(medium not between -3 and -1) and
+(long_int not between -3 and -1) and
+(longlong not between -3 and -1) and
+(utiny not between 1 and 3) and
+(ushort not between 1 and 3) and
+(umedium not between 1 and 3) and
+(ulong not between 1 and 3) and
+(ulonglong not between 1 and 3) and
+(bits not between b'001' and b'011') and
+(options not between 'one' and 'three') and
+(flags not between 'one' and 'one,two,three') and
+(date_field not between '1901-01-01' and '1903-03-03') and
+(year_field not between '1901' and '1903') and
+(time_field not between '01:01:01' and '03:03:03') and
+(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+
+select auto from t1 where
+("aaaa" not between string and string) and
+("aaaa" not between vstring and vstring) and
+(0xAAAA not between bin and bin) and
+(0xAAAA not between vbin and vbin) and
+(-1 not between tiny and tiny) and
+(-1 not between short and short) and
+(-1 not between medium and medium) and
+(-1 not between long_int and long_int) and
+(-1 not between longlong and longlong) and
+(1 not between utiny and utiny) and
+(1 not between ushort and ushort) and
+(1 not between umedium and umedium) and
+(1 not between ulong and ulong) and
+(1 not between ulonglong and ulonglong) and
+(b'001' not between bits and bits) and
+('one' not between options and options) and
+('one' not between flags and flags) and
+('1901-01-01' not between date_field and date_field) and
+('1901' not between year_field and year_field) and
+('01:01:01' not between time_field and time_field) and
+('1901-01-01 01:01:01' not between date_time and date_time)
+order by auto;
+
+# IN
+select auto from t1 where
+string in("aaaa","cccc") and
+vstring in("aaaa","cccc") and
+bin in(0xAAAA,0xCCCC) and
+vbin in(0xAAAA,0xCCCC) and
+tiny in(-1,-3) and
+short in(-1,-3) and
+medium in(-1,-3) and
+long_int in(-1,-3) and
+longlong in(-1,-3) and
+utiny in(1,3) and
+ushort in(1,3) and
+umedium in(1,3) and
+ulong in(1,3) and
+ulonglong in(1,3) and
+bits in(b'001',b'011') and
+options in('one','three') and
+flags in('one','one,two,three') and
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+
+select auto from t1 where
+"aaaa" in(string) and
+"aaaa" in(vstring) and
+0xAAAA in(bin) and
+0xAAAA in(vbin) and
+(-1 in(tiny)) and
+(-1 in(short)) and
+(-1 in(medium)) and
+(-1 in(long_int)) and
+(-1 in(longlong)) and
+1 in(utiny) and
+1 in(ushort) and
+1 in(umedium) and
+1 in(ulong) and
+1 in(ulonglong) and
+b'001' in(bits) and
+'one' in(options) and
+'one' in(flags) and
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and
+'1901-01-01 01:01:01' in(date_time)
+order by auto;
+
+# NOT IN
+select auto from t1 where
+string not in("aaaa","cccc") and
+vstring not in("aaaa","cccc") and
+bin not in(0xAAAA,0xCCCC) and
+vbin not in(0xAAAA,0xCCCC) and
+tiny not in(-1,-3) and
+short not in(-1,-3) and
+medium not in(-1,-3) and
+long_int not in(-1,-3) and
+longlong not in(-1,-3) and
+utiny not in(1,3) and
+ushort not in(1,3) and
+umedium not in(1,3) and
+ulong not in(1,3) and
+ulonglong not in(1,3) and
+bits not in(b'001',b'011') and
+options not in('one','three') and
+flags not in('one','one,two,three') and
+date_field not in('1901-01-01','1903-03-03') and
+year_field not in('1901','1903') and
+time_field not in('01:01:01','03:03:03') and
+date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+
+select auto from t1 where
+"aaaa" not in(string) and
+"aaaa" not in(vstring) and
+0xAAAA not in(bin) and
+0xAAAA not in(vbin) and
+(-1 not in(tiny)) and
+(-1 not in(short)) and
+(-1 not in(medium)) and
+(-1 not in(long_int)) and
+(-1 not in(longlong)) and
+1 not in(utiny) and
+1 not in(ushort) and
+1 not in(umedium) and
+1 not in(ulong) and
+1 not in(ulonglong) and
+b'001' not in(bits) and
+'one' not in(options) and
+'one' not in(flags) and
+'1901-01-01' not in(date_field) and
+'1901' not in(year_field) and
+'01:01:01' not in(time_field) and
+'1901-01-01 01:01:01' not in(date_time)
+order by auto;
+
+# Various tests
+select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
+select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
+select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
+select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
+select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
+select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1;
+
+set engine_condition_pushdown = on;
+
+# Test all types and compare operators
+explain
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+
+explain
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+/* bits != b'001' and */
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+/* bits != b'001' and */
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+
+explain
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+/* bits > b'001' and */
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+/* bits > b'001' and */
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+
+explain
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+/* bits >= b'001' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+/* bits >= b'001' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+
+explain
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+/* bits < b'100' and */
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+/* bits < b'100' and */
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+
+explain
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 - 1 + 1 and /* Checking function composition */
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+/* bits <= b'100' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 - 1 + 1 and /* Checking function composition */
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+/* bits <= b'100' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+
+# Test index scan with filter
+create index medium_index on t1(medium);
+
+# Test all types and compare operators
+explain
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01'
+order by auto;
+
+explain
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+/* bits != b'001' and */
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string != "aaaa" and
+vstring != "aaaa" and
+bin != 0xAAAA and
+vbin != 0xAAAA and
+tiny != -1 and
+short != -1 and
+medium != -1 and
+long_int != -1 and
+longlong != -1 and
+(real_float < 1.0 or real_float > 2.0) and
+(real_double < 1.0 or real_double > 2.0) and
+(real_decimal < 1.0 or real_decimal > 2.0) and
+utiny != 1 and
+ushort != 1 and
+umedium != 1 and
+ulong != 1 and
+ulonglong != 1 and
+/* bits != b'001' and */
+options != 'one' and
+flags != 'one' and
+date_field != '1901-01-01' and
+year_field != '1901' and
+time_field != '01:01:01' and
+date_time != '1901-01-01 01:01:01'
+order by auto;
+
+explain
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+/* bits > b'001' and */
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string > "aaaa" and
+vstring > "aaaa" and
+bin > 0xAAAA and
+vbin > 0xAAAA and
+tiny < -1 and
+short < -1 and
+medium < -1 and
+long_int < -1 and
+longlong < -1 and
+real_float > 1.1 and
+real_double > 1.1 and
+real_decimal > 1.1 and
+utiny > 1 and
+ushort > 1 and
+umedium > 1 and
+ulong > 1 and
+ulonglong > 1 and
+/* bits > b'001' and */
+(options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field > '1901-01-01' and
+year_field > '1901' and
+time_field > '01:01:01' and
+date_time > '1901-01-01 01:01:01'
+order by auto;
+
+explain
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+/* bits >= b'001' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+
+select auto from t1 where
+string >= "aaaa" and
+vstring >= "aaaa" and
+bin >= 0xAAAA and
+vbin >= 0xAAAA and
+tiny <= -1 and
+short <= -1 and
+medium <= -1 and
+long_int <= -1 and
+longlong <= -1 and
+real_float >= 1.0 and
+real_double >= 1.0 and
+real_decimal >= 1.0 and
+utiny >= 1 and
+ushort >= 1 and
+umedium >= 1 and
+ulong >= 1 and
+ulonglong >= 1 and
+/* bits >= b'001' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field >= '1901-01-01' and
+year_field >= '1901' and
+time_field >= '01:01:01' and
+date_time >= '1901-01-01 01:01:01'
+order by auto;
+
+explain
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+/* bits < b'100' and */
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+
+select auto from t1 where
+string < "dddd" and
+vstring < "dddd" and
+bin < 0xDDDD and
+vbin < 0xDDDD and
+tiny > -4 and
+short > -4 and
+medium > -4 and
+long_int > -4 and
+longlong > -4 and
+real_float < 4.4 and
+real_double < 4.4 and
+real_decimal < 4.4 and
+utiny < 4 and
+ushort < 4 and
+umedium < 4 and
+ulong < 4 and
+ulonglong < 4 and
+/* bits < b'100' and */
+(options = 'one' or options = 'two' or options = 'three') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three') and
+date_field < '1904-01-01' and
+year_field < '1904' and
+time_field < '04:04:04' and
+date_time < '1904-04-04 04:04:04'
+order by auto;
+
+explain
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 - 1 + 1 and /* Checking function composition */
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+/* bits <= b'100' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+
+select auto from t1 where
+string <= "dddd" and
+vstring <= "dddd" and
+bin <= 0xDDDD and
+vbin <= 0xDDDD and
+tiny >= -4 and
+short >= -4 and
+medium >= -4 and
+long_int >= -4 and
+longlong >= -4 and
+real_float <= 4.5 and
+real_double <= 4.5 and
+real_decimal <= 4.5 and
+utiny <= 4 - 1 + 1 and /* Checking function composition */
+ushort <= 4 and
+umedium <= 4 and
+ulong <= 4 and
+ulonglong <= 4 and
+/* bits <= b'100' and */
+(options = 'one' or options = 'two' or options = 'three' or options = 'four') and
+(flags = 'one' or flags = 'one,two' or flags = 'one,two,three' or flags = 'one,two,three,four') and
+date_field <= '1904-04-04' and
+year_field <= '1904' and
+time_field <= '04:04:04' and
+date_time <= '1904-04-04 04:04:04'
+order by auto;
+
+# Test LIKE/NOT LIKE
+explain
+select auto from t1 where
+string like "b%" and
+vstring like "b%" and
+bin like concat(0xBB, '%') and
+vbin like concat(0xBB, '%')
+order by auto;
+
+select auto from t1 where
+string like "b%" and
+vstring like "b%" and
+bin like concat(0xBB, '%') and
+vbin like concat(0xBB, '%')
+order by auto;
+
+explain
+select auto from t1 where
+string not like "b%" and
+vstring not like "b%" and
+bin not like concat(0xBB, '%') and
+vbin not like concat(0xBB, '%')
+order by auto;
+
+select auto from t1 where
+string not like "b%" and
+vstring not like "b%" and
+bin not like concat(0xBB, '%') and
+vbin not like concat(0xBB, '%')
+order by auto;
+
+# BETWEEN
+explain
+select auto from t1 where
+(string between "aaaa" and "cccc") and
+(vstring between "aaaa" and "cccc") and
+(bin between 0xAAAA and 0xCCCC) and
+(vbin between 0xAAAA and 0xCCCC) and
+(tiny between -3 and -1) and
+(short between -3 and -1) and
+(medium between -3 and -1) and
+(long_int between -3 and -1) and
+(longlong between -3 and -1) and
+(utiny between 1 and 3) and
+(ushort between 1 and 3) and
+(umedium between 1 and 3) and
+(ulong between 1 and 3) and
+(ulonglong between 1 and 3) and
+/* (bits between b'001' and b'011') and */
+(options between 'one' and 'three') and
+(flags between 'one' and 'one,two,three') and
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+
+select auto from t1 where
+(string between "aaaa" and "cccc") and
+(vstring between "aaaa" and "cccc") and
+(bin between 0xAAAA and 0xCCCC) and
+(vbin between 0xAAAA and 0xCCCC) and
+(tiny between -3 and -1) and
+(short between -3 and -1) and
+(medium between -3 and -1) and
+(long_int between -3 and -1) and
+(longlong between -3 and -1) and
+(utiny between 1 and 3) and
+(ushort between 1 and 3) and
+(umedium between 1 and 3) and
+(ulong between 1 and 3) and
+(ulonglong between 1 and 3) and
+/* (bits between b'001' and b'011') and */
+(options between 'one' and 'three') and
+(flags between 'one' and 'one,two,three') and
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+
+explain
+select auto from t1 where
+("aaaa" between string and string) and
+("aaaa" between vstring and vstring) and
+(0xAAAA between bin and bin) and
+(0xAAAA between vbin and vbin) and
+(-1 between tiny and tiny) and
+(-1 between short and short) and
+(-1 between medium and medium) and
+(-1 between long_int and long_int) and
+(-1 between longlong and longlong) and
+(1 between utiny and utiny) and
+(1 between ushort and ushort) and
+(1 between umedium and umedium) and
+(1 between ulong and ulong) and
+(1 between ulonglong and ulonglong) and
+/* (b'001' between bits and bits) and */
+('one' between options and options) and
+('one' between flags and flags) and
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and
+('1901-01-01 01:01:01' between date_time and date_time)
+order by auto;
+
+select auto from t1 where
+("aaaa" between string and string) and
+("aaaa" between vstring and vstring) and
+(0xAAAA between bin and bin) and
+(0xAAAA between vbin and vbin) and
+(-1 between tiny and tiny) and
+(-1 between short and short) and
+(-1 between medium and medium) and
+(-1 between long_int and long_int) and
+(-1 between longlong and longlong) and
+(1 between utiny and utiny) and
+(1 between ushort and ushort) and
+(1 between umedium and umedium) and
+(1 between ulong and ulong) and
+(1 between ulonglong and ulonglong) and
+/* (b'001' between bits and bits) and */
+('one' between options and options) and
+('one' between flags and flags) and
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and
+('1901-01-01 01:01:01' between date_time and date_time)
+order by auto;
+
+# NOT BETWEEN
+explain
+select auto from t1 where
+(string not between "aaaa" and "cccc") and
+(vstring not between "aaaa" and "cccc") and
+(bin not between 0xAAAA and 0xCCCC) and
+(vbin not between 0xAAAA and 0xCCCC) and
+(tiny not between -3 and -1) and
+(short not between -3 and -1) and
+(medium not between -3 and -1) and
+(long_int not between -3 and -1) and
+(longlong not between -3 and -1) and
+(utiny not between 1 and 3) and
+(ushort not between 1 and 3) and
+(umedium not between 1 and 3) and
+(ulong not between 1 and 3) and
+(ulonglong not between 1 and 3) and
+/* (bits not between b'001' and b'011') and */
+(options not between 'one' and 'three') and
+(flags not between 'one' and 'one,two,three') and
+(date_field not between '1901-01-01' and '1903-03-03') and
+(year_field not between '1901' and '1903') and
+(time_field not between '01:01:01' and '03:03:03') and
+(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+
+select auto from t1 where
+(string not between "aaaa" and "cccc") and
+(vstring not between "aaaa" and "cccc") and
+(bin not between 0xAAAA and 0xCCCC) and
+(vbin not between 0xAAAA and 0xCCCC) and
+(tiny not between -3 and -1) and
+(short not between -3 and -1) and
+(medium not between -3 and -1) and
+(long_int not between -3 and -1) and
+(longlong not between -3 and -1) and
+(utiny not between 1 and 3) and
+(ushort not between 1 and 3) and
+(umedium not between 1 and 3) and
+(ulong not between 1 and 3) and
+(ulonglong not between 1 and 3) and
+/* (bits not between b'001' and b'011') and */
+(options not between 'one' and 'three') and
+(flags not between 'one' and 'one,two,three') and
+(date_field not between '1901-01-01' and '1903-03-03') and
+(year_field not between '1901' and '1903') and
+(time_field not between '01:01:01' and '03:03:03') and
+(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
+order by auto;
+
+explain
+select auto from t1 where
+("aaaa" not between string and string) and
+("aaaa" not between vstring and vstring) and
+(0xAAAA not between bin and bin) and
+(0xAAAA not between vbin and vbin) and
+(-1 not between tiny and tiny) and
+(-1 not between short and short) and
+(-1 not between medium and medium) and
+(-1 not between long_int and long_int) and
+(-1 not between longlong and longlong) and
+(1 not between utiny and utiny) and
+(1 not between ushort and ushort) and
+(1 not between umedium and umedium) and
+(1 not between ulong and ulong) and
+(1 not between ulonglong and ulonglong) and
+/* (b'001' not between bits and bits) and */
+('one' not between options and options) and
+('one' not between flags and flags) and
+('1901-01-01' not between date_field and date_field) and
+('1901' not between year_field and year_field) and
+('01:01:01' not between time_field and time_field) and
+('1901-01-01 01:01:01' not between date_time and date_time)
+order by auto;
+
+select auto from t1 where
+("aaaa" not between string and string) and
+("aaaa" not between vstring and vstring) and
+(0xAAAA not between bin and bin) and
+(0xAAAA not between vbin and vbin) and
+(-1 not between tiny and tiny) and
+(-1 not between short and short) and
+(-1 not between medium and medium) and
+(-1 not between long_int and long_int) and
+(-1 not between longlong and longlong) and
+(1 not between utiny and utiny) and
+(1 not between ushort and ushort) and
+(1 not between umedium and umedium) and
+(1 not between ulong and ulong) and
+(1 not between ulonglong and ulonglong) and
+/* (b'001' not between bits and bits) and */
+('one' not between options and options) and
+('one' not between flags and flags) and
+('1901-01-01' not between date_field and date_field) and
+('1901' not between year_field and year_field) and
+('01:01:01' not between time_field and time_field) and
+('1901-01-01 01:01:01' not between date_time and date_time)
+order by auto;
+
+# IN
+explain
+select auto from t1 where
+string in("aaaa","cccc") and
+vstring in("aaaa","cccc") and
+bin in(0xAAAA,0xCCCC) and
+vbin in(0xAAAA,0xCCCC) and
+tiny in(-1,-3) and
+short in(-1,-3) and
+medium in(-1,-3) and
+long_int in(-1,-3) and
+longlong in(-1,-3) and
+utiny in(1,3) and
+ushort in(1,3) and
+umedium in(1,3) and
+ulong in(1,3) and
+ulonglong in(1,3) and
+/* bits in(b'001',b'011') and */
+options in('one','three') and
+flags in('one','one,two,three') and
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+
+select auto from t1 where
+string in("aaaa","cccc") and
+vstring in("aaaa","cccc") and
+bin in(0xAAAA,0xCCCC) and
+vbin in(0xAAAA,0xCCCC) and
+tiny in(-1,-3) and
+short in(-1,-3) and
+medium in(-1,-3) and
+long_int in(-1,-3) and
+longlong in(-1,-3) and
+utiny in(1,3) and
+ushort in(1,3) and
+umedium in(1,3) and
+ulong in(1,3) and
+ulonglong in(1,3) and
+/* bits in(b'001',b'011') and */
+options in('one','three') and
+flags in('one','one,two,three') and
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+
+explain
+select auto from t1 where
+"aaaa" in(string) and
+"aaaa" in(vstring) and
+0xAAAA in(bin) and
+0xAAAA in(vbin) and
+(-1 in(tiny)) and
+(-1 in (short)) and
+(-1 in(medium)) and
+(-1 in(long_int)) and
+(-1 in(longlong)) and
+1 in(utiny) and
+1 in(ushort) and
+1 in(umedium) and
+1 in(ulong) and
+1 in(ulonglong) and
+/* b'001' in(bits) and */
+'one' in(options) and
+'one' in(flags) and
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and
+'1901-01-01 01:01:01' in(date_time)
+order by auto;
+
+select auto from t1 where
+"aaaa" in(string) and
+"aaaa" in(vstring) and
+0xAAAA in(bin) and
+0xAAAA in(vbin) and
+(-1 in(tiny)) and
+(-1 in (short)) and
+(-1 in(medium)) and
+(-1 in(long_int)) and
+(-1 in(longlong)) and
+1 in(utiny) and
+1 in(ushort) and
+1 in(umedium) and
+1 in(ulong) and
+1 in(ulonglong) and
+/* b'001' in(bits) and */
+'one' in(options) and
+'one' in(flags) and
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and
+'1901-01-01 01:01:01' in(date_time)
+order by auto;
+
+# NOT IN
+explain
+select auto from t1 where
+string not in("aaaa","cccc") and
+vstring not in("aaaa","cccc") and
+bin not in(0xAAAA,0xCCCC) and
+vbin not in(0xAAAA,0xCCCC) and
+tiny not in(-1,-3) and
+short not in(-1,-3) and
+medium not in(-1,-3) and
+long_int not in(-1,-3) and
+longlong not in(-1,-3) and
+utiny not in(1,3) and
+ushort not in(1,3) and
+umedium not in(1,3) and
+ulong not in(1,3) and
+ulonglong not in(1,3) and
+/* bits not in(b'001',b'011') and */
+options not in('one','three') and
+flags not in('one','one,two,three') and
+date_field not in('1901-01-01','1903-03-03') and
+year_field not in('1901','1903') and
+time_field not in('01:01:01','03:03:03') and
+date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+
+select auto from t1 where
+string not in("aaaa","cccc") and
+vstring not in("aaaa","cccc") and
+bin not in(0xAAAA,0xCCCC) and
+vbin not in(0xAAAA,0xCCCC) and
+tiny not in(-1,-3) and
+short not in(-1,-3) and
+medium not in(-1,-3) and
+long_int not in(-1,-3) and
+longlong not in(-1,-3) and
+utiny not in(1,3) and
+ushort not in(1,3) and
+umedium not in(1,3) and
+ulong not in(1,3) and
+ulonglong not in(1,3) and
+/* bits not in(b'001',b'011') and */
+options not in('one','three') and
+flags not in('one','one,two,three') and
+date_field not in('1901-01-01','1903-03-03') and
+year_field not in('1901','1903') and
+time_field not in('01:01:01','03:03:03') and
+date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03')
+order by auto;
+
+explain
+select auto from t1 where
+"aaaa" not in(string) and
+"aaaa" not in(vstring) and
+0xAAAA not in(bin) and
+0xAAAA not in(vbin) and
+(-1 not in(tiny)) and
+(-1 not in(short)) and
+(-1 not in(medium)) and
+(-1 not in(long_int)) and
+(-1 not in(longlong)) and
+1 not in(utiny) and
+1 not in(ushort) and
+1 not in(umedium) and
+1 not in(ulong) and
+1 not in(ulonglong) and
+/* b'001' not in(bits) and */
+'one' not in(options) and
+'one' not in(flags) and
+'1901-01-01' not in(date_field) and
+'1901' not in(year_field) and
+'01:01:01' not in(time_field) and
+'1901-01-01 01:01:01' not in(date_time)
+order by auto;
+
+select auto from t1 where
+"aaaa" not in(string) and
+"aaaa" not in(vstring) and
+0xAAAA not in(bin) and
+0xAAAA not in(vbin) and
+(-1 not in(tiny)) and
+(-1 not in(short)) and
+(-1 not in(medium)) and
+(-1 not in(long_int)) and
+(-1 not in(longlong)) and
+1 not in(utiny) and
+1 not in(ushort) and
+1 not in(umedium) and
+1 not in(ulong) and
+1 not in(ulonglong) and
+/* b'001' not in(bits) and */
+'one' not in(options) and
+'one' not in(flags) and
+'1901-01-01' not in(date_field) and
+'1901' not in(year_field) and
+'01:01:01' not in(time_field) and
+'1901-01-01 01:01:01' not in(date_time)
+order by auto;
+
+# Update test
+update t1
+set medium = 17
+where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = -1 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01';
+
+# Delete test
+delete from t1
+where
+string = "aaaa" and
+vstring = "aaaa" and
+bin = 0xAAAA and
+vbin = 0xAAAA and
+tiny = -1 and
+short = -1 and
+medium = 17 and
+long_int = -1 and
+longlong = -1 and
+real_float > 1.0 and real_float < 2.0 and
+real_double > 1.0 and real_double < 2.0 and
+real_decimal > 1.0 and real_decimal < 2.0 and
+utiny = 1 and
+ushort = 1 and
+umedium = 1 and
+ulong = 1 and
+ulonglong = 1 and
+/* bits = b'001' and */
+options = 'one' and
+flags = 'one' and
+date_field = '1901-01-01' and
+year_field = '1901' and
+time_field = '01:01:01' and
+date_time = '1901-01-01 01:01:01';
+
+select count(*) from t1;
+
+# Various tests
+explain
+select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
+select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
+
+explain
+select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
+select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
+
+explain
+select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
+select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
+
+explain
+select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
+select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
+
+explain
+select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
+select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
+
+explain
+select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1;
+select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1;
+
+# Some tests that are currently not supported and should not push condition
+explain
+select auto from t1 where string = "aaaa" collate latin1_general_ci order by auto;
+explain
+select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1;
+explain
+select * from t3 left join t4 on t4.attr2 = t3.attr2 where t4.attr1 > 1 and t4.attr3 < 5 or t4.attr1 is null order by t4.pk1;
+
+set engine_condition_pushdown = @old_ecpd;
+DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test
index 66287bf6d29..ab3063af672 100644
--- a/mysql-test/t/ndb_config.test
+++ b/mysql-test/t/ndb_config.test
@@ -1,4 +1,5 @@
-- source include/have_ndb.inc
+-- source include/ndb_default_cluster.inc
-- source include/not_embedded.inc
--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=type,nodeid,host 2> /dev/null
diff --git a/mysql-test/t/ndb_grant.later b/mysql-test/t/ndb_grant.later
index 5258501d79e..5431d94e1f8 100644
--- a/mysql-test/t/ndb_grant.later
+++ b/mysql-test/t/ndb_grant.later
@@ -226,19 +226,23 @@ grant select on test.t1 to drop_user2@localhost;
grant select on test.* to drop_user3@localhost;
grant select on *.* to drop_user4@localhost;
commit;
---error 1268
+flush privileges;
+# Drop user now implicitly revokes all privileges.
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
begin;
+--error 1269
revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
drop_user3@localhost, drop_user4@localhost;
commit;
+flush privileges;
+#--error 1268
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
drop table t1;
begin;
grant usage on *.* to mysqltest_1@localhost identified by "password";
-grant select, update, insert on test.* to mysqltest@localhost;
+grant select, update, insert on test.* to mysqltest_1@localhost;
commit;
show grants for mysqltest_1@localhost;
drop user mysqltest_1@localhost;
@@ -352,6 +356,11 @@ DROP DATABASE testdb9;
DROP DATABASE testdb10;
#
+# just SHOW PRIVILEGES test
+#
+SHOW PRIVILEGES;
+
+#
# Alter mysql system tables back to myisam
#
use mysql;
diff --git a/mysql-test/t/ndb_index_ordered.test b/mysql-test/t/ndb_index_ordered.test
index eb2b4e86343..e6827bdbe12 100644
--- a/mysql-test/t/ndb_index_ordered.test
+++ b/mysql-test/t/ndb_index_ordered.test
@@ -149,6 +149,37 @@ select * from t1 use index (bc) where b IS NOT NULL order by a;
drop table t1;
#
+# Order by again, including descending.
+#
+
+create table t1 (
+ a int unsigned primary key,
+ b int unsigned,
+ c char(10),
+ key bc (b, c)
+) engine=ndb;
+
+insert into t1 values(1,1,'a'),(2,2,'b'),(3,3,'c'),(4,4,'d'),(5,5,'e');
+insert into t1 select a*7,10*b,'f' from t1;
+insert into t1 select a*13,10*b,'g' from t1;
+insert into t1 select a*17,10*b,'h' from t1;
+insert into t1 select a*19,10*b,'i' from t1;
+insert into t1 select a*23,10*b,'j' from t1;
+insert into t1 select a*29,10*b,'k' from t1;
+#
+select b, c from t1 where b <= 10 and c <'f' order by b, c;
+select b, c from t1 where b <= 10 and c <'f' order by b desc, c desc;
+#
+select b, c from t1 where b=4000 and c<'k' order by b, c;
+select b, c from t1 where b=4000 and c<'k' order by b desc, c desc;
+select b, c from t1 where 1000<=b and b<=100000 and c<'j' order by b, c;
+select b, c from t1 where 1000<=b and b<=100000 and c<'j' order by b desc, c desc;
+#
+select min(b), max(b) from t1;
+#
+drop table t1;
+
+#
# Bug #6435
CREATE TABLE test1 (
SubscrID int(11) NOT NULL auto_increment,
@@ -318,4 +349,10 @@ select a from t1 where b = 2;
show tables;
drop table t1;
+# mysqld 5.0.13 crash, no bug#
+create table t1 (a int, c varchar(10),
+ primary key using hash (a), index(c)) engine=ndb;
+insert into t1 (a, c) values (1,'aaa'),(3,'bbb');
+select count(*) from t1 where c<'bbb';
+
# End of 4.1 tests
diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test
index 458f6a165f8..2185276c2c6 100644
--- a/mysql-test/t/ndb_index_unique.test
+++ b/mysql-test/t/ndb_index_unique.test
@@ -2,7 +2,7 @@
-- source include/not_embedded.inc
--disable_warnings
-drop table if exists t1, t2, t3, t4, t5, t6, t7;
+drop table if exists t1, t2, t3, t4, t5, t6, t7, t8;
--enable_warnings
#
@@ -183,8 +183,8 @@ 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',
+ rid bigint(20) unsigned NOT NULL,
+ cid bigint(20) unsigned NOT NULL,
UNIQUE KEY m (uid,gid,rid,cid)
) engine=ndbcluster;
INSERT INTO t4 VALUES (1,1,2,4);
@@ -210,8 +210,8 @@ 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',
+ rid bigint(20) unsigned NOT NULL,
+ cid bigint(20) unsigned NOT NULL,
UNIQUE KEY m (uid,gid,rid,cid)
) engine=ndbcluster;
INSERT INTO t7 VALUES(1, 1, 1, 1, 1);
diff --git a/mysql-test/t/ndb_read_multi_range.test b/mysql-test/t/ndb_read_multi_range.test
new file mode 100644
index 00000000000..9d1f918fef0
--- /dev/null
+++ b/mysql-test/t/ndb_read_multi_range.test
@@ -0,0 +1,202 @@
+-- source include/have_ndb.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, r1;
+--enable_warnings
+
+#
+# Basic test to see that batching is working
+#
+
+create table t1 (
+ a int primary key,
+ b int not null,
+ c int not null,
+ index(b), unique index using hash(c)
+) engine = ndb;
+insert into t1 values
+ (1,2,1),(2,3,2),(3,4,3),(4,5,4),
+ (5,2,12),(6,3,11),(7,4,10),(8,5,9),
+ (9,2,8),(10,3,7),(11,4,6),(12,5,5);
+
+# batch on primary key
+create table r1 as select * from t1 where a in (2,8,12);
+select * from r1 order by a;
+drop table r1;
+
+# batch on ordered index
+create table r1 as select * from t1 where b in (1,2,5);
+select * from r1 order by a;
+drop table r1;
+
+# batch on unique hash index
+create table r1 as select * from t1 where c in (2,8,12);
+select * from r1 order by a;
+drop table r1;
+
+# batch mixed
+create table r1 as select * from t1 where a in (2,8) or (a > 11) or (a <= 1);
+select * from r1 order by a;
+drop table r1;
+
+# batch on primary key, missing values
+create table r1 as select * from t1 where a in (33,8,12);
+select * from r1 order by a;
+drop table r1;
+create table r1 as select * from t1 where a in (2,33,8,12,34);
+select * from r1 order by a;
+drop table r1;
+
+# batch on ordered index, missing values
+create table r1 as select * from t1 where b in (1,33,5);
+select * from r1 order by a;
+drop table r1;
+select * from t1 where b in (1,33,5) order by a;
+create table r1 as select * from t1 where b in (45,1,33,5,44);
+select * from r1 order by a;
+drop table r1;
+select * from t1 where b in (45,22) order by a;
+
+# batch on unique hash index, missing values
+create table r1 as select * from t1 where c in (2,8,33);
+select * from r1 order by a;
+drop table r1;
+create table r1 as select * from t1 where c in (13,2,8,33,12);
+select * from r1 order by a;
+drop table r1;
+
+select * from t1 where a in (33,8,12) order by a;
+select * from t1 where a in (33,34,35) order by a;
+select * from t1 where a in (2,8) or (a > 11) or (a <= 1) order by a;
+select * from t1 where b in (6,7) or (b <= 5) or (b >= 10) order by b,a;
+select * from t1 where c in (13,2,8,33,12) order by c,a;
+drop table t1;
+
+#
+# Somewhat more complicated
+#
+
+create table t1 (
+ a int not null,
+ b int not null,
+ c int not null,
+ d int not null,
+ e int not null,
+ primary key (a,b,c,d), index (d)
+) engine = ndb;
+
+insert into t1 values
+ (1,2,1,1,1),(2,3,2,3,1),(3,4,3,1,1),(4,5,4,7,1),
+ (5,2,12,12,1),(6,3,11,1,1),(7,4,10,3,1),(8,5,9,5,1),
+ (9,2,8,6,1),(10,3,7,5,1),(11,4,6,3,1),(12,5,5,2,1),
+ (1,2,1,2,1),
+ (1,2,1,3,1),
+ (1,2,1,4,1),
+ (1,2,1,5,1);
+
+# batch on primary key
+create table r1 as select * from t1
+ where a=1 and b=2 and c=1 and d in (1,4,3,2);
+select * from r1 order by a,b,c,d;
+drop table r1;
+
+# batched update ordered index, one value for all
+update t1 set e = 100
+ where d in (12,6,7);
+select * from t1 where d in (12,6,7) order by a,b,c,d;
+select * from t1 where d not in (12,6,7) and e = 100;
+
+# batched update primary key, one value for all
+update t1
+ set e = 101
+ where a=1 and
+ b=2 and
+ c=1 and
+ d in (1,4,3,2);
+select *
+ from t1
+ where a=1 and b=2 and c=1 and d in (1,4,3,2)
+ order by a,b,c,d;
+select *
+ from t1
+ where not (a=1 and b=2 and c=1 and d in (1,4,3,2))
+ and e=101;
+
+
+# batched update ordered index, different values
+update t1
+ set e =
+ (case d
+ when 12 then 112
+ when 6 then 106
+ when 7 then 107
+ end)
+ where d in (12,6,7);
+select * from t1 where d in (12,6,7) order by a,b,c,d;
+
+# batched update primary key, different values
+update t1
+ set e =
+ (case d
+ when 1 then 111
+ when 4 then 444
+ when 3 then 333
+ when 2 then 222
+ end)
+ where a=1 and
+ b=2 and
+ c=1 and
+ d in (1,4,3,2);
+select *
+ from t1
+ where a=1 and b=2 and c=1 and d in (1,4,3,2)
+ order by a,b,c,d;
+
+# batched delete
+delete from t1 where d in (12,6,7);
+select * from t1 where d in (12,6,7);
+
+drop table t1;
+
+# null handling
+create table t1 (
+ a int not null primary key,
+ b int,
+ c int,
+ d int,
+ unique index (b),
+ index(c)
+) engine = ndb;
+
+insert into t1 values
+ (1,null,1,1),
+ (2,2,2,2),
+ (3,null,null,3),
+ (4,4,null,4),
+ (5,null,5,null),
+ (6,6,6,null),
+ (7,null,null,null),
+ (8,8,null,null),
+ (9,null,9,9),
+ (10,10,10,10),
+ (11,null,null,11),
+ (12,12,null,12),
+ (13,null,13,null),
+ (14,14,14,null),
+ (15,null,null,null),
+ (16,16,null,null);
+
+create table t2 as select * from t1 where a in (5,6,7,8,9,10);
+select * from t2 order by a;
+drop table t2;
+
+create table t2 as select * from t1 where b in (5,6,7,8,9,10);
+select * from t2 order by a;
+drop table t2;
+
+create table t2 as select * from t1 where c in (5,6,7,8,9,10);
+select * from t2 order by a;
+drop table t2;
+
+drop table t1;
diff --git a/mysql-test/t/ndb_restore.test b/mysql-test/t/ndb_restore.test
index 586c39ed96b..049b07d5a8b 100644
--- a/mysql-test/t/ndb_restore.test
+++ b/mysql-test/t/ndb_restore.test
@@ -1,4 +1,5 @@
-- source include/have_ndb.inc
+-- source include/ndb_default_cluster.inc
-- source include/not_embedded.inc
--disable_warnings
diff --git a/mysql-test/t/ndb_subquery.test b/mysql-test/t/ndb_subquery.test
index 135dc4fb862..93c45c521a0 100644
--- a/mysql-test/t/ndb_subquery.test
+++ b/mysql-test/t/ndb_subquery.test
@@ -39,3 +39,27 @@ drop table t2;
##########
# End of 4.1 tests
+
+#
+# bug#11205
+#
+create table t1 (p int not null primary key, u int not null) engine=ndb;
+insert into t1 values (1,1),(2,2),(3,3);
+
+create table t2 as
+select t1.*
+from t1 as t1, t1 as t2, t1 as t3, t1 as t4, t1 as t5, t1 as t6, t1 as t7, t1 as t8
+where t1.u = t2.u
+ and t2.u = t3.u
+ and t3.u = t4.u
+ and t4.u = t5.u
+ and t5.u = t6.u
+ and t6.u = t7.u
+ and t7.u = t8.u;
+
+select * from t2 order by 1;
+
+drop table t1;
+drop table t2;
+
+
diff --git a/mysql-test/t/ndb_types.test b/mysql-test/t/ndb_types.test
index 1ca89447892..3446a409b2a 100644
--- a/mysql-test/t/ndb_types.test
+++ b/mysql-test/t/ndb_types.test
@@ -21,11 +21,13 @@ CREATE TABLE t1 (
longlong bigint(13) DEFAULT '0' NOT NULL,
real_float float(13,1) DEFAULT 0.0 NOT NULL,
real_double double(16,4),
+ real_decimal decimal(16,4),
utiny tinyint(3) unsigned DEFAULT '0' NOT NULL,
ushort smallint(5) unsigned zerofill DEFAULT '00000' NOT NULL,
umedium mediumint(8) unsigned DEFAULT '0' NOT NULL,
ulong int(11) unsigned DEFAULT '0' NOT NULL,
ulonglong bigint(13) unsigned DEFAULT '0' NOT NULL,
+ bits bit(3),
options enum('one','two','tree') not null,
flags set('one','two','tree') not null,
date_field date,
@@ -51,15 +53,15 @@ set @now = now();
sleep 1;
insert into t1
(string,vstring,bin,vbin,tiny,short,medium,long_int,longlong,
- real_float,real_double, utiny, ushort, umedium,ulong,ulonglong,
- options,flags,date_field,year_field,time_field,date_time)
+ real_float,real_double, real_decimal,utiny, ushort, umedium,ulong,ulonglong,
+ bits,options,flags,date_field,year_field,time_field,date_time)
values
-("aaaa","aaaa",0xAAAA,0xAAAA,-1,-1,-1,-1,-1,1.1,1.1,1,1,1,1,1,
- 'one','one', '1901-01-01','1901','01:01:01','1901-01-01 01:01:01');
+("aaaa","aaaa",0xAAAA,0xAAAA,-1,-1,-1,-1,-1,1.1,1.1,1.1,1,1,1,1,1,
+ b'001','one','one', '1901-01-01','1901','01:01:01','1901-01-01 01:01:01');
select auto,string,vstring,bin,vbin,tiny,short,medium,long_int,longlong,
- real_float,real_double, utiny, ushort, umedium,ulong,ulonglong,
- options,flags,date_field,year_field,time_field,date_time
+ real_float,real_double,real_decimal,utiny,ushort,umedium,ulong,ulonglong,
+ bits,options,flags,date_field,year_field,time_field,date_time
from t1;
select time_stamp>@now from t1;
@@ -67,13 +69,14 @@ set @now = now();
sleep 1;
update t1 set string="bbbb",vstring="bbbb",bin=0xBBBB,vbin=0xBBBB,
tiny=-2,short=-2,medium=-2,long_int=-2,longlong=-2,real_float=2.2,
-real_double=2.2,utiny=2,ushort=2,umedium=2,ulong=2,ulonglong=2,
+real_double=2.2,real_decimal=2.2,utiny=2,ushort=2,umedium=2,ulong=2,
+ulonglong=2, bits=b'010',
options='one',flags='one', date_field='1902-02-02',year_field='1902',
time_field='02:02:02',date_time='1902-02-02 02:02:02' where auto=1;
select auto,string,vstring,bin,vbin,tiny,short,medium,long_int,longlong,
- real_float,real_double, utiny, ushort, umedium,ulong,ulonglong,
- options,flags,date_field,year_field,time_field,date_time
+ real_float,real_double,real_decimal,utiny,ushort,umedium,ulong,ulonglong,
+ bits,options,flags,date_field,year_field,time_field,date_time
from t1;
select time_stamp>@now from t1;
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index 731f0a4cb34..183308880ed 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -59,7 +59,7 @@ drop table t1;
#
# Test inserting and updating with NULL
#
-CREATE TABLE t1 (a varchar(16) NOT NULL, b smallint(6) NOT NULL, c datetime NOT NULL, d smallint(6) NOT NULL);
+CREATE TABLE t1 (a varchar(16) NOT NULL default '', b smallint(6) NOT NULL default 0, c datetime NOT NULL default '0000-00-00 00:00:00', d smallint(6) NOT NULL default 0);
INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55";
UPDATE t1 SET d=1/NULL;
UPDATE t1 SET d=NULL;
@@ -100,9 +100,9 @@ drop table t1;
select cast(NULL as signed);
#
-# Test case for bug #4256
+# IS NULL is unable to use index in range if column is declared not null
+# (Bug #4256)
#
-
create table t1(i int, key(i));
insert into t1 values(1);
insert into t1 select i*2 from t1;
@@ -114,9 +114,12 @@ insert into t1 select i*2 from t1;
insert into t1 select i*2 from t1;
insert into t1 select i*2 from t1;
insert into t1 select i*2 from t1;
+insert into t1 values(null);
explain select * from t1 where i=2 or i is null;
+select count(*) from t1 where i=2 or i is null;
alter table t1 change i i int not null;
explain select * from t1 where i=2 or i is null;
+select count(*) from t1 where i=2 or i is null;
drop table t1;
#
diff --git a/mysql-test/t/null_key.test b/mysql-test/t/null_key.test
index a43916d6397..e15aec01d2a 100644
--- a/mysql-test/t/null_key.test
+++ b/mysql-test/t/null_key.test
@@ -26,6 +26,8 @@ select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
select * from t1 where (a is null or a > 0 and a < 3) and b > 7 limit 3;
select * from t1 where (a is null or a = 7) and b=7;
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
+select * from t1 where a > 1 and a < 3 limit 1;
+select * from t1 where a > 8 and a < 9;
create table t2 like t1;
insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index 4f9790b0de6..e34ac6a865c 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -2,6 +2,10 @@
drop table if exists t1,t2;
--enable_warnings
+set @sav_dpi= @@div_precision_increment;
+set div_precision_increment= 5;
+show variables like 'div_precision_increment';
+
create table t1 (product varchar(32), country_id int not null, year int, profit int);
insert into t1 values ( 'Computer', 2,2000, 1200),
( 'TV', 1, 1999, 150),
@@ -153,6 +157,13 @@ SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1
SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
+SELECT b, a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
+SELECT DISTINCT b,a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
+
+ALTER TABLE t1 ADD COLUMN c INT;
+SELECT a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP;
+SELECT distinct a,b,sum(c) FROM t1 GROUP BY a,b,c WITH ROLLUP;
+
DROP TABLE t1;
#
@@ -184,6 +195,7 @@ SELECT a, SUM(a) m FROM t1 GROUP BY a WITH ROLLUP;
SELECT * FROM ( SELECT a, SUM(a) m FROM t1 GROUP BY a WITH ROLLUP ) t2;
DROP TABLE t1;
+set div_precision_increment= @sav_dpi;
#
# Tests for bug #7914: ROLLUP over expressions on temporary table
@@ -250,9 +262,8 @@ SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP;
DROP TABLE t1;
-#
-# Bug #11885: derived table specified by a subquery with
-# ROLLUP over expressions on not nullable group by attributes
+# Bug #12885(1): derived table specified by a subquery with
+# ROLLUP over expressions on not nullable group by attributes
#
CREATE TABLE t1 (a int(11) NOT NULL);
@@ -273,3 +284,38 @@ select distinct a, max(b) from t1 group by a with rollup;
drop table t1;
# End of 4.1 tests
+
+#
+# Tests for bug #11639: ROLLUP over view executed through filesort
+#
+
+CREATE TABLE t1(id int, type char(1));
+INSERT INTO t1 VALUES
+ (1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"),
+ (6,"B"),(7,"A"),(8,"C"),(9,"A"),(10,"C");
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+SELECT type FROM t1 GROUP BY type WITH ROLLUP;
+SELECT type FROM v1 GROUP BY type WITH ROLLUP;
+EXPLAIN SELECT type FROM v1 GROUP BY type WITH ROLLUP;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# Bug #12885(2): view specified by a subquery with
+# ROLLUP over expressions on not nullable group by attributes
+#
+
+CREATE TABLE t1 (a int(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+
+CREATE VIEW v1 AS
+ SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
+
+DESC v1;
+SELECT * FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+# End of 4.1 tests
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index 3f398a91834..e04c77ddf45 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -20,22 +20,22 @@ connect (con4,localhost,ssl_user4,,);
connection con1;
select * from t1;
---error 1044
+--error 1142
delete from t1;
connection con2;
select * from t1;
---error 1044
+--error 1142
delete from t1;
connection con3;
select * from t1;
---error 1044
+--error 1142
delete from t1;
connection con4;
select * from t1;
---error 1044
+--error 1142
delete from t1;
connection default;
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 4b7ec84dc54..b1807579b20 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -158,10 +158,21 @@ LEFT JOIN t3 ON t3.c = t1.c;
SELECT a,b,if(b = 1,i,if(b = 2,v,''))
FROM t1
+LEFT JOIN t2 ON t1.c = t2.c
+LEFT JOIN t3 ON t3.c = t1.c;
+
+SELECT a,b,if(b = 1,i,if(b = 2,v,''))
+FROM t1
LEFT JOIN t2 USING(c)
LEFT JOIN t3 ON t3.c = t1.c
ORDER BY a;
+SELECT a,b,if(b = 1,i,if(b = 2,v,''))
+FROM t1
+LEFT JOIN t2 ON t1.c = t2.c
+LEFT JOIN t3 ON t3.c = t1.c
+ORDER BY a;
+
drop table t1,t2,t3;
#
@@ -206,7 +217,7 @@ CREATE TABLE t1 (
favo_tv varchar(50) NOT NULL default '',
favo_eten varchar(50) NOT NULL default '',
favo_muziek varchar(30) NOT NULL default '',
- info text NOT NULL,
+ info text NOT NULL default '',
ipnr varchar(30) NOT NULL default '',
PRIMARY KEY (member_id)
) ENGINE=MyISAM PACK_KEYS=1;
@@ -340,7 +351,9 @@ CREATE TABLE t2 (
INSERT INTO t1 (titre,auteur,dest) VALUES ('test','joce','bug');
INSERT INTO t2 (numeropost,pseudo) VALUES (1,'joce'),(1,'bug');
SELECT titre,t1.numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
+SELECT titre,numeropost,auteur,icone,nbrep,0,date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
+SELECT titre,numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,dest FROM t2 LEFT JOIN t1 USING(numeropost) WHERE t2.pseudo='joce' ORDER BY date DESC LIMIT 0,30;
drop table t1,t2;
#
@@ -501,6 +514,11 @@ set max_sort_length=20;
select a from t1 order by a;
drop table t1;
+create table t1 (a int not null, b int not null, c int not null);
+insert t1 values (1,1,1),(1,1,2),(1,2,1);
+select a, b from t1 group by a, b order by sum(c);
+drop table t1;
+
#
# Bug #7331
#
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index c4cb0056763..94ee2b1ca39 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -3,6 +3,9 @@
#
--disable_warnings
drop table if exists t1,t2;
+
+# Avoid wrong warnings if mysql_client_test fails
+drop database if exists client_test_db;
--enable_warnings
create table t1
@@ -146,7 +149,7 @@ create table t1
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
c17 year, c18 bit, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
@@ -483,6 +486,17 @@ execute stmt;
deallocate prepare stmt;
drop table t1, t2;
+#
+# Bug#6102 "Server crash with prepared statement and blank after
+# function name"
+# ensure that stored functions are cached when preparing a statement
+# before we open tables
+#
+create table t1 (a varchar(20));
+insert into t1 values ('foo');
+--error 1305
+prepare stmt FROM 'SELECT char_length (a) FROM t1';
+drop table t1;
#
# Bug #6089: FOUND_ROWS returns wrong values when no table/view is used
@@ -496,6 +510,86 @@ SELECT FOUND_ROWS();
deallocate prepare stmt;
#
+# Bug#8115: equality propagation and prepared statements
+#
+
+create table t1 (a char(3) not null, b char(3) not null,
+ c char(3) not null, primary key (a, b, c));
+create table t2 like t1;
+
+# reduced query
+prepare stmt from
+ "select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b)
+ where t1.a=1";
+execute stmt;
+execute stmt;
+execute stmt;
+
+# original query
+prepare stmt from
+"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from
+(t1 left outer join t2 on t2.a=? and t1.b=t2.b)
+left outer join t2 t3 on t3.a=? where t1.a=?";
+
+set @a:=1, @b:=1, @c:=1;
+
+execute stmt using @a, @b, @c;
+execute stmt using @a, @b, @c;
+execute stmt using @a, @b, @c;
+
+deallocate prepare stmt;
+
+drop table t1,t2;
+
+
+#
+# Bug#9383: INFORMATION_SCHEMA.COLUMNS, JOIN, Crash, prepared statement
+#
+
+eval SET @aux= "SELECT COUNT(*)
+ FROM INFORMATION_SCHEMA.COLUMNS A,
+ INFORMATION_SCHEMA.COLUMNS B
+ WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA
+ AND A.TABLE_NAME = B.TABLE_NAME
+ AND A.COLUMN_NAME = B.COLUMN_NAME AND
+ A.TABLE_NAME = 'user'";
+
+let $exec_loop_count= 3;
+eval prepare my_stmt from @aux;
+while ($exec_loop_count)
+{
+ eval execute my_stmt;
+ dec $exec_loop_count;
+}
+deallocate prepare my_stmt;
+
+# Test CALL in prepared mode
+delimiter |;
+--disable_warnings
+drop procedure if exists p1|
+drop table if exists t1|
+--enable_warnings
+create table t1 (id int)|
+insert into t1 values(1)|
+create procedure p1(a int, b int)
+begin
+ declare c int;
+ select max(id)+1 into c from t1;
+ insert into t1 select a+b;
+ insert into t1 select a-b;
+ insert into t1 select a-c;
+end|
+set @a= 3, @b= 4|
+prepare stmt from "call p1(?, ?)"|
+execute stmt using @a, @b|
+execute stmt using @a, @b|
+select * from t1|
+deallocate prepare stmt|
+drop procedure p1|
+drop table t1|
+delimiter ;|
+
+#
# Bug#9096 "select doesn't return all matched records if prepared statements
# is used"
# The bug was is bad co-operation of the optimizer's algorithm which determines
@@ -520,6 +614,7 @@ set @a=200887, @b=860;
# this query did not return all matching rows
execute stmt using @a, @b;
deallocate prepare stmt;
+
drop table t1;
#
@@ -569,6 +664,35 @@ deallocate prepare stmt;
drop table t1, t2;
#
+# Bug#7306 LIMIT ?, ? and also WL#1785 " Prepared statements: implement
+# support for placeholders in LIMIT clause."
+# Add basic test coverage for the feature.
+#
+create table t1 (a int);
+insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+prepare stmt from "select * from t1 limit ?, ?";
+set @offset=0, @limit=1;
+execute stmt using @offset, @limit;
+select * from t1 limit 0, 1;
+set @offset=3, @limit=2;
+execute stmt using @offset, @limit;
+select * from t1 limit 3, 2;
+prepare stmt from "select * from t1 limit ?";
+execute stmt using @limit;
+--error 1235
+prepare stmt from "select * from t1 where a in (select a from t1 limit ?)";
+prepare stmt from "select * from t1 union all select * from t1 limit ?, ?";
+set @offset=9;
+set @limit=2;
+execute stmt using @offset, @limit;
+prepare stmt from "(select * from t1 limit ?, ?) union all
+ (select * from t1 limit ?, ?) order by a limit ?";
+execute stmt using @offset, @limit, @offset, @limit, @limit;
+
+drop table t1;
+deallocate prepare stmt;
+
+#
# Bug#11060 "Server crashes on calling stored procedure with INSERT SELECT
# UNION SELECT" aka "Server crashes on re-execution of prepared INSERT ...
# SELECT with UNION".
@@ -579,7 +703,6 @@ execute stmt;
execute stmt;
deallocate prepare stmt;
drop table t1;
-
#
# Bug#11458 "Prepared statement with subselects return random data":
# drop PARAM_TABLE_BIT from the list of tables used by a subquery
@@ -648,7 +771,6 @@ execute stmt using @user_id, @id;
execute stmt using @user_id, @id;
deallocate prepare stmt;
drop table t1, t2, t3, t4;
-
#
# Bug#9379: make sure that Item::collation is reset when one sets
# a parameter marker from a string variable.
@@ -665,19 +787,6 @@ set @b='CHRISTINE';
execute stmt using @a, @b;
deallocate prepare stmt;
#
-# Bug#9442 Set parameter make query fail if column character set is UCS2
-#
-create table t1 (utext varchar(20) character set ucs2);
-insert into t1 values ("lily");
-insert into t1 values ("river");
-prepare stmt from 'select utext from t1 where utext like ?';
-set @param1='%%';
-execute stmt using @param1;
-execute stmt using @param1;
-select utext from t1 where utext like '%%';
-drop table t1;
-deallocate prepare stmt;
-#
# Bug#11299 "prepared statement makes wrong SQL syntax in binlog which stops
# replication": check that errouneous queries with placeholders are not
# allowed
@@ -700,6 +809,21 @@ select ??;
select ? from t1;
--enable_ps_protocol
drop table t1;
+
+#
+# Bug#12651
+# (Crash on a PS including a subquery which is a select from a simple view)
+#
+CREATE TABLE b12651_T1(a int) ENGINE=MYISAM;
+CREATE TABLE b12651_T2(b int) ENGINE=MYISAM;
+CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2;
+
+PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)';
+EXECUTE b12651;
+
+DROP VIEW b12651_V1;
+DROP TABLE b12651_T1, b12651_T2;
+
#
# Bug#9359 "Prepared statements take snapshot of system vars at PREPARE
# time"
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index 5752e6b0b66..6abfd8f28a7 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -11,7 +11,12 @@
--disable_warnings
drop table if exists t5, t6, t7, t8;
drop database if exists mysqltest ;
+
+# Cleanup from other tests
drop database if exists client_test_db;
+drop database if exists testtets;
+drop table if exists t1Aa,t2Aa,v1Aa,v2Aa;
+drop view if exists t1Aa,t2Aa,v1Aa,v2Aa;
--enable_warnings
--disable_query_log
@@ -287,6 +292,14 @@ 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 where field in (select ?) ';
+SET @arg00="a";
+execute stmt4 using @arg00;
+SET @arg00="b";
+execute stmt4 using @arg00;
+SET @arg00=1;
+execute stmt4 using @arg00;
+
prepare stmt4 from ' show columns from t2 from test like ''a%'' ';
execute stmt4;
create index t2_idx on t2(b);
@@ -294,15 +307,13 @@ 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 #
---replace_result 2147483647 64424509439
+--replace_column 8 # 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 ''t9%'' ';
# egalize date and time values
---replace_column 12 # 13 # 14 #
---replace_result 2147483647 4294967295
+--replace_column 8 # 12 # 13 # 14 #
# Bug#4288
execute stmt4;
prepare stmt4 from ' show status like ''Threads_running'' ';
@@ -423,20 +434,6 @@ create database mysqltest ;
prepare stmt3 from ' drop database mysqltest ';
drop database mysqltest ;
-## 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;
-
#### table related commands
## describe
prepare stmt3 from ' describe t2 ';
@@ -472,9 +469,7 @@ prepare stmt1 from ' handler t1 open ';
## commit/rollback
---error 1295
prepare stmt3 from ' commit ' ;
---error 1295
prepare stmt3 from ' rollback ' ;
@@ -486,10 +481,10 @@ select 'a' || 'b' ;
prepare stmt4 from ' SET sql_mode="" ';
execute stmt4;
# check if the sql_mode is not ansi
-select 'a' || 'b' ;
+select '2' || '3' ;
# Will a switch of the sqlmode affect the execution of already prepared
# statements ?
-prepare stmt5 from ' select ''a'' || ''b'' ' ;
+prepare stmt5 from ' select ''2'' || ''3'' ' ;
execute stmt5;
SET sql_mode=ansi;
execute stmt5;
@@ -575,11 +570,8 @@ 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 ';
## RENAME TABLE
@@ -598,7 +590,7 @@ prepare stmt1 from ' rename table t5 to t6, t7 to t8 ' ;
create table t5 (a int) ;
# rename must fail, t7 does not exist
# Clean up the filename here because embedded server reports whole path
---replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ /
+--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t7.frm t7
--error 1017
execute stmt1 ;
create table t7 (a int) ;
@@ -839,7 +831,7 @@ execute stmt1 ;
--disable_metadata
--horizontal_results
-drop table t5 ;
+drop table t5, t9;
##### RULES OF THUMB TO PRESERVE THE SYSTEMATICS OF THE PS TEST CASES #####
#
diff --git a/mysql-test/t/ps_4heap.test b/mysql-test/t/ps_4heap.test
index 9538224bb95..f16d4599a74 100644
--- a/mysql-test/t/ps_4heap.test
+++ b/mysql-test/t/ps_4heap.test
@@ -31,11 +31,11 @@ eval create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
- 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'),
+ c13 date, c14 datetime, c15 timestamp, c16 time,
+ c17 year, c18 tinyint, c19 bool, c20 char,
+ c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100),
+ c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100),
+ c29 varchar(100), c30 varchar(100), c31 enum('one', 'two', 'three'),
c32 set('monday', 'tuesday', 'wednesday'),
primary key(c1)
) engine = $type ;
diff --git a/mysql-test/t/ps_5merge.test b/mysql-test/t/ps_5merge.test
index 3f4468d569f..e6ce9bf42d3 100644
--- a/mysql-test/t/ps_5merge.test
+++ b/mysql-test/t/ps_5merge.test
@@ -31,8 +31,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
- c17 year, c18 bit, c19 bool, c20 char,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
+ c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
@@ -62,8 +62,8 @@ create table t9
c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
- c17 year, c18 bit, c19 bool, c20 char,
+ c13 date, c14 datetime, c15 timestamp, c16 time,
+ c17 year, c18 tinyint, c19 bool, c20 char,
c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
diff --git a/mysql-test/t/ps_grant.test b/mysql-test/t/ps_grant.test
index 4cb056db358..81c842de459 100644
--- a/mysql-test/t/ps_grant.test
+++ b/mysql-test/t/ps_grant.test
@@ -113,3 +113,19 @@ show grants for second_user@localhost ;
drop database mysqltest;
# End of 4.1 tests
+
+#
+# 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;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index d08dc5fb352..822c27fe40d 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -554,9 +554,8 @@ set character_set_results=cp1251;
SELECT a,'Â','â'='Â' FROM t1;
show status like "Qcache_hits";
show status like "Qcache_queries_in_cache";
-#
-# Keep things tidy
-#
+SET NAMES default;
+
DROP TABLE t1;
#
@@ -576,7 +575,6 @@ DROP TABLE t1;
set character_set_results=null;
select @@character_set_results;
set character_set_results=default;
-
#
# query cache and environment variables
#
@@ -611,7 +609,36 @@ select group_concat(a) FROM t1 group by b;
set group_concat_max_len=default;
drop table t1;
+# comments before command
+#
+create table t1 (a int);
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+/**/ select * from t1;
+/**/ select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+#
+# Keep things tidy
+#
+DROP TABLE t1;
+SET GLOBAL query_cache_size=0;
+
+#
+# Information schema & query cache test
+#
+SET SESSION query_cache_type = 2;
+create table t1(a int);
+select table_name from information_schema.tables
+where table_schema="test";
+drop table t1;
+select table_name from information_schema.tables
+where table_schema="test";
# Bug #8480: REPAIR TABLE needs to flush the table from the query cache
+SET SESSION query_cache_type = 1;
set global query_cache_size=1024*1024;
flush query cache;
create table t1 ( a int );
@@ -623,9 +650,10 @@ repair table t1;
show status like 'qcache_queries_in_cache';
drop table t1;
+#
# Bug #9549: Make sure cached queries that span more than one cache block
# are handled properly in the embedded server.
-
+#
# We just want a small query cache, so we can fragment it easily
set GLOBAL query_cache_size=64*1024;
# This actually gives us a usable cache size of about 48K
@@ -667,6 +695,8 @@ select a from t1;
flush query cache;
drop table t1, t2;
+set GLOBAL query_cache_size=1355776
+
#
# Query with warning prohibited to query cache (BUG#9414)
@@ -712,6 +742,77 @@ show status like "Qcache_inserts";
show status like "Qcache_hits";
drop table t1;
+#
+# SP cursors and selects with query cache (BUG#9715)
+#
+create table t1 (a int);
+insert into t1 values (1),(2);
+
+delimiter //;
+CREATE PROCEDURE `p1`()
+begin
+Declare c1 cursor for select a from t1;
+open c1;
+select * from t1;
+end//
+call p1()//
+drop procedure p1;
+
+create function f1() returns int
+begin
+Declare var1 int;
+select max(a) from t1 into var1;
+return var1;
+end//
+create procedure `p1`()
+begin
+ select a, f1() from t1;
+end//
+call p1()//
+drop procedure p1//
+
+drop table t1//
+delimiter ;//
+
+#
+# query in QC from normal execution and SP (BUG#6897)
+#
+flush query cache;
+reset query cache;
+flush status;
+delimiter //;
+create table t1 (s1 int)//
+create procedure f1 () begin
+select sql_cache * from t1;
+select sql_cache * from t1;
+end;//
+delimiter ;//
+call f1();
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+insert into t1 values (1);
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+call f1();
+call f1();
+select sql_cache * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+drop procedure f1;
+drop table t1;
set GLOBAL query_cache_size=0;
# End of 4.1 tests
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index 944cf6ced18..bbe5798e7e5 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -181,8 +181,8 @@ create table t1 (x int, y int, index(x), index(y));
insert into t1 (x) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
update t1 set y=x;
# between with only one end fixed
-explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 7 and t1.y+0;
-explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 7 and t2.x <= t1.y+0;
+explain select * from t1, t1 t2 where t1.y = 8 and t2.x between 7 and t1.y+0;
+explain select * from t1, t1 t2 where t1.y = 8 and t2.x >= 7 and t2.x <= t1.y+0;
# between with both expressions on both ends
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
@@ -195,13 +195,15 @@ explain select count(*) from t1 where x in (1,2);
drop table t1;
#
-# bug #1172
+# bug #1172: "Force index" option caused server crash
#
CREATE TABLE t1 (key1 int(11) NOT NULL default '0', KEY i1 (key1));
-INSERT INTO t1 VALUES (0),(0),(1),(1);
+INSERT INTO t1 VALUES (0),(0),(0),(0),(0),(1),(1);
CREATE TABLE t2 (keya int(11) NOT NULL default '0', KEY j1 (keya));
INSERT INTO t2 VALUES (0),(0),(1),(1),(2),(2);
explain select * from t1, t2 where (t1.key1 <t2.keya + 1) and t2.keya=3;
+explain select * from t1 force index(i1), t2 force index(j1) where
+ (t1.key1 <t2.keya + 1) and t2.keya=3;
DROP TABLE t1,t2;
#
@@ -376,8 +378,12 @@ insert into t2(id, uid, name) select id, uid, name from t1;
select count(*) from t1;
select count(*) from t2;
+analyze table t1,t2;
+
explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
+explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid > 0;
explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid != 0;
+explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid != 0;
select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
select * from t1, t2 where t1.uid=t2.uid AND t1.uid != 0;
@@ -400,8 +406,8 @@ select count(*) from t1 where x = 18446744073709551601;
create table t2 (x bigint not null);
-insert into t2(x) values (0xfffffffffffffff0);
-insert into t2(x) values (0xfffffffffffffff1);
+insert into t2(x) values (cast(0xfffffffffffffff0+0 as signed));
+insert into t2(x) values (cast(0xfffffffffffffff1+0 as signed));
select * from t2;
select count(*) from t2 where x>0;
select count(*) from t2 where x=0;
@@ -410,8 +416,8 @@ select count(*) from t2 where x < -16;
select count(*) from t2 where x = -16;
select count(*) from t2 where x > -16;
select count(*) from t2 where x = 18446744073709551601;
+drop table t1,t2;
-drop table t1;
--disable_warnings
create table t1 (x bigint unsigned not null primary key) engine=innodb;
--enable_warnings
@@ -485,3 +491,90 @@ SELECT count(*) FROM t1 WHERE CLIENT='000' AND (ARG1 != ' 2' OR ARG1 != ' 1');
drop table t1;
# End of 4.1 tests
+
+#
+# Test for optimization request #10561: to use keys for
+# NOT IN (c1,...,cn) and NOT BETWEEN c1 AND c2
+#
+
+CREATE TABLE t1 (
+ id int(11) NOT NULL auto_increment,
+ status varchar(20),
+ PRIMARY KEY (id),
+ KEY (status)
+);
+
+INSERT INTO t1 VALUES
+(1,'B'), (2,'B'), (3,'B'), (4,'B'), (5,'B'), (6,'B'),
+(7,'B'), (8,'B'), (9,'B'), (10,'B'), (11,'B'), (12,'B'),
+(13,'B'), (14,'B'), (15,'B'), (16,'B'), (17,'B'), (18,'B'),
+(19,'B'), (20,'B'), (21,'B'), (22,'B'), (23,'B'), (24,'B'),
+(25,'A'), (26,'A'), (27,'A'), (28,'A'), (29,'A'), (30,'A'),
+(31,'A'), (32,'A'), (33,'A'), (34,'A'), (35,'A'), (36,'A'),
+(37,'A'), (38,'A'), (39,'A'), (40,'A'), (41,'A'), (42,'A'),
+(43,'A'), (44,'A'), (45,'A'), (46,'A'), (47,'A'), (48,'A'),
+(49,'A'), (50,'A'), (51,'A'), (52,'A'), (53,'C'), (54,'C'),
+(55,'C'), (56,'C'), (57,'C'), (58,'C'), (59,'C'), (60,'C');
+
+EXPLAIN SELECT * FROM t1 WHERE status <> 'A' AND status <> 'B';
+EXPLAIN SELECT * FROM t1 WHERE status NOT IN ('A','B');
+
+SELECT * FROM t1 WHERE status <> 'A' AND status <> 'B';
+SELECT * FROM t1 WHERE status NOT IN ('A','B');
+
+EXPLAIN SELECT status FROM t1 WHERE status <> 'A' AND status <> 'B';
+EXPLAIN SELECT status FROM t1 WHERE status NOT IN ('A','B');
+
+EXPLAIN SELECT * FROM t1 WHERE status NOT BETWEEN 'A' AND 'B';
+EXPLAIN SELECT * FROM t1 WHERE status < 'A' OR status > 'B';
+
+SELECT * FROM t1 WHERE status NOT BETWEEN 'A' AND 'B';
+SELECT * FROM t1 WHERE status < 'A' OR status > 'B';
+
+DROP TABLE t1;
+
+#
+# Test for bug #10031: range to be used over a view
+#
+
+CREATE TABLE t1 (a int, b int, primary key(a,b));
+
+INSERT INTO t1 VALUES
+ (1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3);
+
+CREATE VIEW v1 as SELECT a,b FROM t1 WHERE b=3;
+
+EXPLAIN SELECT a,b FROM t1 WHERE a < 2 and b=3;
+EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3;
+
+EXPLAIN SELECT a,b FROM t1 WHERE a < 2;
+EXPLAIN SELECT a,b FROM v1 WHERE a < 2;
+
+SELECT a,b FROM t1 WHERE a < 2 and b=3;
+SELECT a,b FROM v1 WHERE a < 2 and b=3;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# Bug #11853: DELETE statement with a NOT (LIKE/<=>) where condition
+# for an indexed attribute
+#
+
+CREATE TABLE t1 (name varchar(15) NOT NULL, KEY idx(name));
+INSERT INTO t1 VALUES ('Betty'), ('Anna');
+
+SELECT * FROM t1;
+DELETE FROM t1 WHERE name NOT LIKE 'A%a';
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+CREATE TABLE t1 (a int, KEY idx(a));
+INSERT INTO t1 VALUES (NULL), (1), (2), (3);
+
+SELECT * FROM t1;
+DELETE FROM t1 WHERE NOT(a <=> 2);
+SELECT * FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/replace.test b/mysql-test/t/replace.test
index 81f7b0089b8..10703eaafb8 100644
--- a/mysql-test/t/replace.test
+++ b/mysql-test/t/replace.test
@@ -1,7 +1,5 @@
--- source include/have_isam.inc
-
#
-# Test of REPLACE with ISAM and MyISAM and HEAP
+# Test of REPLACE with MyISAM and HEAP
#
--disable_warnings
@@ -12,13 +10,11 @@ CREATE TABLE t1 (
gesuchnr int(11) DEFAULT '0' NOT NULL,
benutzer_id int(11) DEFAULT '0' NOT NULL,
PRIMARY KEY (gesuchnr,benutzer_id)
-) engine=ISAM;
+);
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);
-alter table t1 engine=myisam;
-replace into t1 (gesuchnr,benutzer_id) values (1,1);
alter table t1 engine=heap;
replace into t1 (gesuchnr,benutzer_id) values (1,1);
drop table t1;
diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test
index d8d9a244134..6301cc0f584 100644
--- a/mysql-test/t/row.test
+++ b/mysql-test/t/row.test
@@ -7,9 +7,11 @@ select (1,2,3) IN ((3,2,3), (1,2,3), (1,3,3));
select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+--disable_ps_warnings
select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'));
-select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3));
+--enable_ps_warnings
+select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3));
@@ -84,3 +86,9 @@ SELECT ROW(2,10) <=> ROW(3,4);
SELECT ROW(NULL,10) <=> ROW(3,NULL);
# End of 4.1 tests
+
+#
+# Correct NULL handling in row comporison (BUG#12509)
+#
+SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ;
+select row(NULL,1)=(2,0);
diff --git a/mysql-test/t/rowid_order_bdb.test b/mysql-test/t/rowid_order_bdb.test
new file mode 100644
index 00000000000..ef133054c35
--- /dev/null
+++ b/mysql-test/t/rowid_order_bdb.test
@@ -0,0 +1,108 @@
+#
+# Test for rowid ordering (and comparison) functions.
+# do index_merge select for tables with PK of various types.
+#
+--disable_warnings
+drop table if exists t1, t2, t3,t4;
+--enable_warnings
+
+-- source include/have_bdb.inc
+
+# Signed number as rowid
+create table t1 (
+ pk1 int not NULL,
+ key1 int(11),
+ key2 int(11),
+ PRIMARY KEY (pk1),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=bdb;
+insert into t1 values (-5, 1, 1),
+ (-100, 1, 1),
+ (3, 1, 1),
+ (0, 1, 1),
+ (10, 1, 1);
+explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+# Unsigned numbers as rowids
+create table t1 (
+ pk1 int unsigned not NULL,
+ key1 int(11),
+ key2 int(11),
+ PRIMARY KEY (pk1),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=bdb;
+insert into t1 values (0, 1, 1),
+ (0xFFFFFFFF, 1, 1),
+ (0xFFFFFFFE, 1, 1),
+ (1, 1, 1),
+ (2, 1, 1);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+# Case-insensitive char(N)
+create table t1 (
+ pk1 char(4) not NULL,
+ key1 int(11),
+ key2 int(11),
+ PRIMARY KEY (pk1),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=bdb collate latin2_general_ci;
+insert into t1 values ('a1', 1, 1),
+ ('b2', 1, 1),
+ ('A3', 1, 1),
+ ('B4', 1, 1);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+# Multi-part PK
+create table t1 (
+ pk1 int not NULL,
+ pk2 char(4) not NULL collate latin1_german1_ci,
+ pk3 char(4) not NULL collate latin1_bin,
+ key1 int(11),
+ key2 int(11),
+ PRIMARY KEY (pk1,pk2,pk3),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=bdb;
+insert into t1 values
+ (1, 'u', 'u', 1, 1),
+ (1, 'u', char(0xEC), 1, 1),
+ (1, 'u', 'x', 1, 1);
+insert ignore into t1 select pk1, char(0xEC), pk3, key1, key2 from t1;
+insert ignore into t1 select pk1, 'x', pk3, key1, key2 from t1 where pk2='u';
+insert ignore into t1 select 2, pk2, pk3, key1, key2 from t1;
+select * from t1;
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+
+# Hidden PK
+alter table t1 drop primary key;
+select * from t1;
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+# Variable-length PK
+# this is also test for Bug#2688
+create table t1 (
+ pk1 varchar(8) NOT NULL default '',
+ pk2 varchar(4) NOT NULL default '',
+ key1 int(11),
+ key2 int(11),
+ 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;
+
diff --git a/mysql-test/t/rowid_order_innodb.test b/mysql-test/t/rowid_order_innodb.test
new file mode 100644
index 00000000000..fb4959d78e6
--- /dev/null
+++ b/mysql-test/t/rowid_order_innodb.test
@@ -0,0 +1,108 @@
+#
+# Test for rowid ordering (and comparison) functions.
+# do index_merge select for tables with PK of various types.
+#
+--disable_warnings
+drop table if exists t1, t2, t3,t4;
+--enable_warnings
+
+-- source include/have_innodb.inc
+
+# Signed number as rowid
+create table t1 (
+ pk1 int not NULL,
+ key1 int(11),
+ key2 int(11),
+ PRIMARY KEY (pk1),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=innodb;
+insert into t1 values (-5, 1, 1),
+ (-100, 1, 1),
+ (3, 1, 1),
+ (0, 1, 1),
+ (10, 1, 1);
+explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+# Unsigned numbers as rowids
+create table t1 (
+ pk1 int unsigned not NULL,
+ key1 int(11),
+ key2 int(11),
+ PRIMARY KEY (pk1),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=innodb;
+insert into t1 values (0, 1, 1),
+ (0xFFFFFFFF, 1, 1),
+ (0xFFFFFFFE, 1, 1),
+ (1, 1, 1),
+ (2, 1, 1);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+# Case-insensitive char(N)
+create table t1 (
+ pk1 char(4) not NULL,
+ key1 int(11),
+ key2 int(11),
+ PRIMARY KEY (pk1),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=innodb collate latin2_general_ci;
+insert into t1 values ('a1', 1, 1),
+ ('b2', 1, 1),
+ ('A3', 1, 1),
+ ('B4', 1, 1);
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+# Multi-part PK
+create table t1 (
+ pk1 int not NULL,
+ pk2 char(4) not NULL collate latin1_german1_ci,
+ pk3 char(4) not NULL collate latin1_bin,
+ key1 int(11),
+ key2 int(11),
+ PRIMARY KEY (pk1,pk2,pk3),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=innodb;
+insert into t1 values
+ (1, 'u', 'u', 1, 1),
+ (1, 'u', char(0xEC), 1, 1),
+ (1, 'u', 'x', 1, 1);
+insert ignore into t1 select pk1, char(0xEC), pk3, key1, key2 from t1;
+insert ignore into t1 select pk1, 'x', pk3, key1, key2 from t1 where pk2='u';
+insert ignore into t1 select 2, pk2, pk3, key1, key2 from t1;
+select * from t1;
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+
+# Hidden PK
+alter table t1 drop primary key;
+select * from t1;
+select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+drop table t1;
+
+# Variable-length PK
+# this is also test for Bug#2688
+create table t1 (
+ pk1 varchar(8) NOT NULL default '',
+ pk2 varchar(4) NOT NULL default '',
+ key1 int(11),
+ key2 int(11),
+ primary key(pk1, pk2),
+ KEY key1 (key1),
+ KEY key2 (key2)
+) engine=innodb;
+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;
+
diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test
index 8f7ba50476a..3d03823d474 100644
--- a/mysql-test/t/rpl000001.test
+++ b/mysql-test/t/rpl000001.test
@@ -39,7 +39,13 @@ save_master_pos;
connection slave;
sync_with_master;
-#test handling of aborted connection in the middle of update
+# Test if the slave SQL thread can be more than 16K behind the slave
+# I/O thread (> IO_SIZE)
+
+connection master;
+# we'll use table-level locking to delay slave SQL thread
+create table t1 (n int) engine=myisam;
+sync_slave_with_master;
connection master;
reset master;
connection slave;
@@ -47,29 +53,26 @@ stop slave;
reset slave;
connection master;
-create table t1(n int);
-#we want the log to exceed 16K to test deal with the log that is bigger than
-#IO_SIZE
let $1=5000;
+# Generate 16K of relay log
disable_query_log;
while ($1)
{
- eval insert into t1 values($1+get_lock("hold_slave",10)*0);
+ eval insert into t1 values($1);
dec $1;
}
enable_query_log;
-# Try to cause a large relay log lag on the slave
+# Try to cause a large relay log lag on the slave by locking t1
connection slave;
-select get_lock("hold_slave",10);
-explain extended select get_lock("hold_slave",10);
+lock tables t1 read;
start slave;
#hope this is long enough for I/O thread to fetch over 16K relay log data
sleep 3;
-select release_lock("hold_slave");
-explain extended select release_lock("hold_slave");
unlock tables;
+#test handling of aborted connection in the middle of update
+
connection master;
create table t2(id int);
insert into t2 values(connection_id());
diff --git a/mysql-test/t/rpl000010-slave.opt b/mysql-test/t/rpl000010-slave.opt
index 429a7f63f7b..0dbfb311e33 100644
--- a/mysql-test/t/rpl000010-slave.opt
+++ b/mysql-test/t/rpl000010-slave.opt
@@ -1 +1 @@
---disconnect-slave-event-count=1
+--disconnect-slave-event-count=2
diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test
index a9520676e1e..a53049386af 100644
--- a/mysql-test/t/rpl000015.test
+++ b/mysql-test/t/rpl000015.test
@@ -1,4 +1,4 @@
-connect (master,localhost,root,,test,$MASTER_MYPORT,master.sock);
+connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
connect (slave,localhost,root,,test,$SLAVE_MYPORT,slave.sock);
connection master;
reset master;
@@ -7,24 +7,24 @@ save_master_pos;
connection slave;
reset slave;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
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 $MYSQL_TCP_PORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=$MASTER_MYPORT;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
start slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
connection master;
--disable_warnings
diff --git a/mysql-test/t/rpl000017.test b/mysql-test/t/rpl000017.test
index 7b4e6bf4d3a..3b4574e9547 100644
--- a/mysql-test/t/rpl000017.test
+++ b/mysql-test/t/rpl000017.test
@@ -1,4 +1,4 @@
-connect (master,localhost,root,,test,$MASTER_MYPORT,master.sock);
+connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
connect (slave,localhost,root,,test,$SLAVE_MYPORT,slave.sock);
connection master;
reset master;
diff --git a/mysql-test/t/rpl000018.test b/mysql-test/t/rpl000018.test
index aee052ffd28..bc6d887cc99 100644
--- a/mysql-test/t/rpl000018.test
+++ b/mysql-test/t/rpl000018.test
@@ -4,7 +4,7 @@
#
require_manager;
-connect (master,localhost,root,,test,0,master.sock);
+connect (master,localhost,root,,test,0,$MASTER_MYPORT);
connect (slave,localhost,root,,test,0,slave.sock);
connection master;
reset master;
diff --git a/mysql-test/t/rpl_EE_error.test b/mysql-test/t/rpl_EE_error.test
index 5f68b699e9f..72df0c20ef8 100644
--- a/mysql-test/t/rpl_EE_error.test
+++ b/mysql-test/t/rpl_EE_error.test
@@ -9,7 +9,7 @@ source include/master-slave.inc;
create table t1 (a int) engine=myisam;
flush tables;
system rm ./var/master-data/test/t1.MYI ;
-drop table t1;
+drop table if exists t1;
save_master_pos;
connection slave;
sync_with_master;
diff --git a/mysql-test/t/rpl_auto_increment-master.opt b/mysql-test/t/rpl_auto_increment-master.opt
new file mode 100644
index 00000000000..a8a6af19da9
--- /dev/null
+++ b/mysql-test/t/rpl_auto_increment-master.opt
@@ -0,0 +1 @@
+--auto-increment-increment=10 --auto-increment-offset=2
diff --git a/mysql-test/t/rpl_auto_increment.test b/mysql-test/t/rpl_auto_increment.test
new file mode 100644
index 00000000000..71032404307
--- /dev/null
+++ b/mysql-test/t/rpl_auto_increment.test
@@ -0,0 +1,104 @@
+#
+# Test of auto_increment with offset
+#
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+create table t1 (a int not null auto_increment,b int, primary key (a)) engine=myisam auto_increment=3;
+insert into t1 values (NULL,1),(NULL,2),(NULL,3);
+select * from t1;
+
+sync_slave_with_master;
+select * from t1;
+connection master;
+drop table t1;
+
+create table t1 (a int not null auto_increment,b int, primary key (a)) engine=myisam;
+insert into t1 values (1,1),(NULL,2),(3,3),(NULL,4);
+delete from t1 where b=4;
+insert into t1 values (NULL,5),(NULL,6);
+select * from t1;
+
+sync_slave_with_master;
+select * from t1;
+connection master;
+
+drop table t1;
+
+set @@session.auto_increment_increment=100, @@session.auto_increment_offset=10;
+show variables like "%auto_inc%";
+
+create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
+# Insert with 2 insert statements to get better testing of logging
+insert into t1 values (NULL),(5),(NULL);
+insert into t1 values (250),(NULL);
+select * from t1;
+insert into t1 values (1000);
+set @@insert_id=400;
+insert into t1 values(NULL),(NULL);
+select * from t1;
+
+sync_slave_with_master;
+select * from t1;
+connection master;
+drop table t1;
+
+#
+# Same test with innodb (as the innodb code is a bit different)
+#
+create table t1 (a int not null auto_increment, primary key (a)) engine=innodb;
+# Insert with 2 insert statements to get better testing of logging
+insert into t1 values (NULL),(5),(NULL);
+insert into t1 values (250),(NULL);
+select * from t1;
+insert into t1 values (1000);
+set @@insert_id=400;
+insert into t1 values(NULL),(NULL);
+select * from t1;
+
+sync_slave_with_master;
+select * from t1;
+connection master;
+drop table t1;
+
+set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
+create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
+# Insert with 2 insert statements to get better testing of logging
+insert into t1 values (NULL),(5),(NULL),(NULL);
+insert into t1 values (500),(NULL),(502),(NULL),(NULL);
+select * from t1;
+set @@insert_id=600;
+--error 1062
+insert into t1 values(600),(NULL),(NULL);
+set @@insert_id=600;
+insert ignore into t1 values(600),(NULL),(NULL),(610),(NULL);
+select * from t1;
+
+sync_slave_with_master;
+select * from t1;
+connection master;
+drop table t1;
+
+#
+# Test that auto-increment works when slave has rows in the table
+#
+set @@session.auto_increment_increment=10, @@session.auto_increment_offset=1;
+
+create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
+
+sync_slave_with_master;
+insert into t1 values(2),(12),(22),(32),(42);
+connection master;
+
+insert into t1 values (NULL),(NULL);
+insert into t1 values (3),(NULL),(NULL);
+select * from t1;
+
+sync_slave_with_master;
+select * from t1;
+connection master;
+
+drop table t1;
+
+# End cleanup
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_change_master.test b/mysql-test/t/rpl_change_master.test
index befc469e7b5..6c055a81ceb 100644
--- a/mysql-test/t/rpl_change_master.test
+++ b/mysql-test/t/rpl_change_master.test
@@ -1,25 +1,30 @@
+# Verify that after CHANGE MASTER, replication (I/O thread and SQL
+# thread) restart from where SQL thread left, not from where
+# I/O thread left (some old bug fixed in 4.0.17)
+
source include/master-slave.inc;
-connection slave;
-select get_lock("a",5);
connection master;
+# Make SQL slave thread advance a bit
create table t1(n int);
-insert into t1 values(1+get_lock("a",15)*0);
+sync_slave_with_master;
+select * from t1;
+# Now stop it and make I/O slave thread be ahead
+stop slave sql_thread;
+connection master;
+insert into t1 values(1);
insert into t1 values(2);
save_master_pos;
connection slave;
---real_sleep 3 # can't sync_with_master as we should be blocked
+--real_sleep 3 # wait for I/O thread to have read updates
stop slave;
-select * from t1;
--replace_result $MASTER_MYPORT MASTER_MYPORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
change master to master_user='root';
--replace_result $MASTER_MYPORT MASTER_MYPORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
-# Will restart from after the values(2), which is bug
-select release_lock("a");
start slave;
sync_with_master;
select * from t1;
diff --git a/mysql-test/t/rpl_charset.test b/mysql-test/t/rpl_charset.test
index cf079048fc3..e5ddf084461 100644
--- a/mysql-test/t/rpl_charset.test
+++ b/mysql-test/t/rpl_charset.test
@@ -1,11 +1,9 @@
# 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
+set timestamp=1000000000;
drop database if exists mysqltest2;
drop database if exists mysqltest3;
--enable_warnings
@@ -46,7 +44,7 @@ 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).
+# needn't be replicated (Bar said in Jan 2005).
insert into t1 (b) values(@@character_set_client);
# collation_client does not exist
insert into t1 (b) values(@@character_set_connection);
@@ -79,9 +77,10 @@ select "--- --slave--" as "";
--enable_query_log
select * from mysqltest2.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);
+# Presently charset info is not logged with LOAD DATA but it will
+# change in Jan 2005 when Dmitri pushes his new LOAD DATA,
+# before 5.0.3 goes out. When done, LOAD DATA INFILE should be tested
+# here.
# 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
@@ -90,6 +89,7 @@ load data infile '../../std_data/words.dat' into table t1 (b);
# 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.
+connection master;
set @a= _cp850 'Müller' collate cp850_general_ci;
truncate table t1;
insert into t1 (b) values(collation(@a));
@@ -106,16 +106,17 @@ select * from mysqltest2.t1 order by a;
connection master;
drop database mysqltest2;
drop database mysqltest3;
-show binlog events from 79;
+--replace_column 2 # 5 #
+show binlog events from 98;
sync_slave_with_master;
-# Check that we can't change global.collation_server
+# Check that we can change global.collation_server (since 5.0.3)
-error 1105;
set global character_set_server=latin2;
+set global character_set_server=latin1; # back
connection master;
-error 1105;
set global character_set_server=latin2;
+set global character_set_server=latin1; # back
# Check that SET ONE_SHOT is really one shot
@@ -128,7 +129,7 @@ select @@character_set_server;
select @@character_set_server;
# ONE_SHOT on not charset/collation stuff is not allowed
-error 1105;
+-- error 1382
set one_shot max_join_size=10;
# Test of wrong character set numbers;
@@ -149,24 +150,10 @@ select hex(c1), hex(c2) from t1;
sync_slave_with_master;
select hex(c1), hex(c2) from t1;
-# Now test for BUG##5705: SET CHARATER_SET_SERVERetc will be lost if
-# STOP SLAVE before following query
-
-stop slave;
-delete from t1;
-change master to master_log_pos=5847;
-start slave until master_log_file='master-bin.000001', master_log_pos=5983;
-# Slave is supposed to stop _after_ the INSERT, even though 5983 is
-# the position of the beginning of the INSERT; after SET slave is not
-# supposed to increment position.
-wait_for_slave_to_stop;
-# When you merge this into 5.0 you will have to adjust positions
-# above; the first master_log_pos above should be the one of the SET,
-# the second should be the one of the INSERT.
-start slave;
-sync_with_master;
-select hex(c1), hex(c2) from t1;
connection master;
+# Let's have a look at generated SETs.
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
drop table t1;
sync_slave_with_master;
diff --git a/mysql-test/t/rpl_create_database.test b/mysql-test/t/rpl_create_database.test
index 96781b25f20..cfccc4567b5 100644
--- a/mysql-test/t/rpl_create_database.test
+++ b/mysql-test/t/rpl_create_database.test
@@ -56,6 +56,7 @@ USE mysqltest_sisyfos;
CREATE TABLE t2 (a INT);
let $VERSION=`select version()`;
--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
SHOW BINLOG EVENTS;
SHOW DATABASES;
sync_slave_with_master;
diff --git a/mysql-test/t/rpl_ddl.test b/mysql-test/t/rpl_ddl.test
index ce9518e80ec..60a00a7b1b4 100644
--- a/mysql-test/t/rpl_ddl.test
+++ b/mysql-test/t/rpl_ddl.test
@@ -34,6 +34,10 @@
###############################################################
# Some preparations
###############################################################
+# The sync_slave_with_master is needed to make the xids deterministic.
+sync_slave_with_master;
+connection master;
+
SET AUTOCOMMIT = 1;
#
# 1. DROP all objects, which probably already exist, but must be created here
@@ -336,6 +340,57 @@ connection master;
SELECT '-------- switch to master -------' as "";
--enable_query_log
+# End of 4.1 tests
+
+###############################################################
+# Cases with stored procedures
+###############################################################
+let $my_stmt= CREATE PROCEDURE p1() READS SQL DATA SELECT "this is p1";
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+--vertical_results
+--replace_column 5 # 6 #
+SHOW PROCEDURE STATUS LIKE 'p1';
+--disable_query_log
+SELECT '-------- switch to slave -------' as "";
+--enable_query_log
+connection slave;
+--replace_column 5 # 6 #
+SHOW PROCEDURE STATUS LIKE 'p1';
+connection master;
+--horizontal_results
+
+let $my_stmt= ALTER PROCEDURE p1 COMMENT "I have been altered";
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+--vertical_results
+--replace_column 5 # 6 #
+SHOW PROCEDURE STATUS LIKE 'p1';
+--disable_query_log
+SELECT '-------- switch to slave -------' as "";
+--enable_query_log
+connection slave;
+--replace_column 5 # 6 #
+SHOW PROCEDURE STATUS LIKE 'p1';
+connection master;
+--horizontal_results
+
+let $my_stmt= DROP PROCEDURE p1;
+let $my_master_commit= true;
+let $my_slave_commit= true;
+--source include/rpl_stmt_seq.inc
+--vertical_results
+SHOW PROCEDURE STATUS LIKE 'p1';
+--disable_query_log
+SELECT '-------- switch to slave -------' as "";
+--enable_query_log
+connection slave;
+SHOW PROCEDURE STATUS LIKE 'p1';
+connection master;
+--horizontal_results
+
###############################################################
# Cleanup
###############################################################
@@ -345,4 +400,4 @@ DROP DATABASE IF EXISTS mysqltest2;
DROP DATABASE IF EXISTS mysqltest3;
--enable_warnings
-# End of 4.1 tests
+
diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test
index d3bc31addff..d2a8fc0c844 100644
--- a/mysql-test/t/rpl_deadlock.test
+++ b/mysql-test/t/rpl_deadlock.test
@@ -72,7 +72,7 @@ show slave status;
# 2) Test lock wait timeout
stop slave;
-change master to master_log_pos=401; # the BEGIN log event
+change master to master_log_pos=532; # the BEGIN log event
begin;
select * from t2 for update; # hold lock
start slave;
@@ -93,7 +93,7 @@ set global max_relay_log_size=0;
# This is really copy-paste of 2) of above
stop slave;
-change master to master_log_pos=401;
+change master to master_log_pos=532;
begin;
select * from t2 for update;
start slave;
diff --git a/mysql-test/t/rpl_delete_all.test b/mysql-test/t/rpl_delete_all.test
index db33ee3bb86..e0c0757bbc2 100644
--- a/mysql-test/t/rpl_delete_all.test
+++ b/mysql-test/t/rpl_delete_all.test
@@ -7,7 +7,7 @@ drop database if exists mysqltest;
sync_slave_with_master;
# can't read dir
--replace_result "Errcode: 1" "Errcode: X" "Errcode: 2" "Errcode: X" \\ /
---error 12
+--error 1049
show tables from mysqltest;
connection slave;
diff --git a/mysql-test/t/rpl_empty_master_crash.test b/mysql-test/t/rpl_empty_master_crash.test
index eae967a4bb1..5f26bedc9fe 100644
--- a/mysql-test/t/rpl_empty_master_crash.test
+++ b/mysql-test/t/rpl_empty_master_crash.test
@@ -1,6 +1,6 @@
source include/master-slave.inc;
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
#
diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test
index 96900697d5b..cb4137c49e0 100644
--- a/mysql-test/t/rpl_error_ignored_table.test
+++ b/mysql-test/t/rpl_error_ignored_table.test
@@ -15,7 +15,7 @@ sync_with_master;
# The port number is different when doing the release build with
# Do-compile, hence we have to replace the port number here accordingly
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# check that the table has been ignored, because otherwise the test is nonsense
show tables like 't1';
@@ -48,7 +48,8 @@ connection master;
--error 0,1053
reap;
connection master1;
-show binlog events from 79;
+--replace_column 2 # 5 #
+show binlog events from 98;
save_master_pos;
connection slave;
# SQL slave thread should not have stopped (because table of the killed
@@ -56,3 +57,4 @@ connection slave;
sync_with_master;
# End of 4.1 tests
+# Adding comment for force manual merge 5.0 -> wl1012. delete me if needed
diff --git a/mysql-test/t/rpl_flush_log_loop.test b/mysql-test/t/rpl_flush_log_loop.test
index e08f1a23ef3..6e45047bd30 100644
--- a/mysql-test/t/rpl_flush_log_loop.test
+++ b/mysql-test/t/rpl_flush_log_loop.test
@@ -18,7 +18,7 @@ sleep 5;
flush logs;
sleep 5;
--replace_result $SLAVE_MYPORT SLAVE_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_flush_tables.test b/mysql-test/t/rpl_flush_tables.test
index 04158aed9e0..4411d6ea1c9 100644
--- a/mysql-test/t/rpl_flush_tables.test
+++ b/mysql-test/t/rpl_flush_tables.test
@@ -21,6 +21,7 @@ rename table t1 to t5, t2 to t1;
flush no_write_to_binlog tables;
# Check that it's not in the binlog.
--replace_result $SERVER_VERSION SERVER_VERSION
+--replace_column 2 # 5 #
show binlog events;
# Check that the master is not confused.
select * from t3;
@@ -28,6 +29,7 @@ select * from t3;
flush tables;
# Check that it's in the binlog.
--replace_result $SERVER_VERSION SERVER_VERSION
+--replace_column 2 # 5 #
show binlog events;
save_master_pos;
connection slave;
@@ -38,3 +40,4 @@ select * from t3;
# in the .err files; these are not fatal and are not reported by mysql-test-run.
# End of 4.1 tests
+# Adding comment for force manual merge 5.0 -> wl1012. Delete me if needed.
diff --git a/mysql-test/t/rpl_get_lock.test b/mysql-test/t/rpl_get_lock.test
index a0e3c829c11..945bd98c993 100644
--- a/mysql-test/t/rpl_get_lock.test
+++ b/mysql-test/t/rpl_get_lock.test
@@ -22,6 +22,13 @@ connection slave;
sync_with_master;
select get_lock("lock",3);
select * from t1;
+# There is no point in testing REPLICATIION of the IS_*_LOCK
+# functions; slave does not run with the same concurrency context as
+# master (generally in slave we can't know that on master this lock
+# was already held by another connection and so that the the
+# get_lock() we're replicating timed out on master hence returned 0,
+# or that the is_free_lock() we're playing returned 0 etc.
+# But here all we do is test these functions outside of replication.
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
diff --git a/mysql-test/t/rpl_heap.test b/mysql-test/t/rpl_heap.test
index 66dac1d7926..3ee335fe58d 100644
--- a/mysql-test/t/rpl_heap.test
+++ b/mysql-test/t/rpl_heap.test
@@ -7,7 +7,7 @@ require_manager;
# issue a query after the server restart.
# Maybe this is something awkward in mysqltest or in the manager?
# So we use sockets.
-connect (master,localhost,root,,test,0,master.sock);
+connect (master,localhost,root,,test,0,$MASTER_MYPORT);
connect (slave,localhost,root,,test,0,slave.sock);
connection master;
diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test
index 21515080ca2..00121092bbf 100644
--- a/mysql-test/t/rpl_loaddata.test
+++ b/mysql-test/t/rpl_loaddata.test
@@ -36,8 +36,7 @@ select * from t3;
# But we can't simply read this binlog, because as the slave has not been
# restarted for this test, the file_id is uncertain (would cause test
# failures). So instead, we test if the binlog looks long enough to
-# contain LOAD DATA. That is, I (Guilhem) have done SHOW BINLOG EVENTS on my
-# machine, saw that the binlog is of size 964 when things go fine.
+# contain LOAD DATA. Since 5.0.3 we assume that binlog of 1292 is ok.
# If LOAD DATA was not logged, the binlog would be shorter.
show master status;
@@ -72,7 +71,7 @@ set global sql_slave_skip_counter=1;
start slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# Trigger error again to test CHANGE MASTER
@@ -84,7 +83,9 @@ set sql_log_bin=1;
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
save_master_pos;
connection slave;
-# The SQL slave thread should be stopped now.
+# The SQL slave thread should be stopped now.
+# Exec_Master_Log_Pos should point to the start of Execute event
+# for last load data.
wait_for_slave_to_stop;
# CHANGE MASTER and see if error is cleared in SHOW SLAVE STATUS.
@@ -92,7 +93,7 @@ stop slave;
change master to master_user='test';
change master to master_user='root';
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# Trigger error again to test RESET SLAVE
@@ -114,7 +115,7 @@ wait_for_slave_to_stop;
stop slave;
reset slave;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# Finally, see if logging is done ok on master for a failing LOAD DATA INFILE
@@ -122,14 +123,31 @@ show slave status;
connection master;
reset master;
create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60),
-unique(day));
+unique(day)) engine=MyISAM; # no transactions
--error 1062
load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields
terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by
'\n##\n' starting by '>' ignore 1 lines;
-# To test that there is Create_file & Delete_file, we test if the binlog is as
-# long as expected (can't do SHOW BINLOG EVENTS because of varying file_id).
-show master status;
+select * from t2;
+save_master_pos;
+connection slave;
+start slave;
+sync_with_master;
+select * from t2;
+
+# verify that if no error on slave, this is an error
+
+alter table t2 drop key day;
+connection master;
+delete from t2;
+--error 1062
+load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields
+terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by
+'\n##\n' starting by '>' ignore 1 lines;
+connection slave;
+wait_for_slave_to_stop;
+drop table t2;
+connection master;
drop table t2;
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_loaddata_rule_m.test b/mysql-test/t/rpl_loaddata_rule_m.test
index 1ece82122ea..c956f2c7720 100644
--- a/mysql-test/t/rpl_loaddata_rule_m.test
+++ b/mysql-test/t/rpl_loaddata_rule_m.test
@@ -19,7 +19,12 @@ create database mysqltest;
create table t1(a int, b int, unique(b));
use mysqltest;
load data infile '../../std_data/rpl_loaddata.dat' into table test.t1;
-show binlog events from 79; # should be nothing
+# Starting from 5.0.3 LOAD DATA is replicated much in the same way as ordinary
+# query so "show binlog ..." should show two events (before 5.0.3 no events
+# were returned).
+--replace_column 2 # 5 #
+show binlog events from 98;
drop database mysqltest;
# End of 4.1 tests
+# Adding comment for force manual merge 5.0 -> wl1012: Delete me
diff --git a/mysql-test/t/rpl_loaddata_rule_s.test b/mysql-test/t/rpl_loaddata_rule_s.test
index b4a9b5b2ee0..98fad3cc06f 100644
--- a/mysql-test/t/rpl_loaddata_rule_s.test
+++ b/mysql-test/t/rpl_loaddata_rule_s.test
@@ -17,6 +17,6 @@ save_master_pos;
connection slave;
sync_with_master;
select count(*) from t1; # check that LOAD was replicated
-show binlog events from 79; # should be nothing
+show binlog events from 98; # should be nothing
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_loaddatalocal.test b/mysql-test/t/rpl_loaddatalocal.test
index 2ca142c3b64..0b54de8462e 100644
--- a/mysql-test/t/rpl_loaddatalocal.test
+++ b/mysql-test/t/rpl_loaddatalocal.test
@@ -36,3 +36,27 @@ connection slave;
sync_with_master;
# End of 4.1 tests
+
+#
+# Now let us test how well we replicate LOAD DATA LOCAL in situation when
+# we met duplicates in tables to which we are adding rows.
+# (It supposed that LOAD DATA LOCAL ignores such errors)
+#
+connection master;
+create table t1(a int);
+insert into t1 values (1), (2), (2), (3);
+select * into outfile '../../var/master-data/rpl_loaddatalocal.select_outfile' from t1;
+drop table t1;
+create table t1(a int primary key);
+load data local infile './var/master-data/rpl_loaddatalocal.select_outfile' into table t1;
+system rm ./var/master-data/rpl_loaddatalocal.select_outfile ;
+select * from t1;
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from t1;
+connection master;
+drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test
index 7a67ab2311a..1f71d2981c5 100644
--- a/mysql-test/t/rpl_log.test
+++ b/mysql-test/t/rpl_log.test
@@ -38,9 +38,9 @@ select count(*) from t1;
drop table t1;
--replace_result $VERSION VERSION
show binlog events;
-show binlog events from 79 limit 1;
-show binlog events from 79 limit 2;
-show binlog events from 79 limit 2,1;
+show binlog events from 98 limit 1;
+show binlog events from 98 limit 2;
+show binlog events from 98 limit 2,1;
flush logs;
# We need an extra update before doing save_master_pos.
@@ -82,6 +82,7 @@ insert into t1 values (1);
drop table t1;
--replace_result $VERSION VERSION
show binlog events;
+--replace_result $VERSION VERSION
show binlog events in 'master-bin.000002';
show binary logs;
save_master_pos;
@@ -94,7 +95,7 @@ show binlog events in 'slave-bin.000001' from 4;
--replace_result $MASTER_MYPORT MASTER_PORT $VERSION VERSION
show binlog events in 'slave-bin.000002' from 4;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# Need to recode the following
@@ -109,3 +110,4 @@ show slave status;
show binlog events in 'slave-bin.000005' from 4;
# End of 4.1 tests
+# Adding comment for force manual merge 5.0 -> wl1012: Delete me
diff --git a/mysql-test/t/rpl_log_pos.test b/mysql-test/t/rpl_log_pos.test
index 25a485c7947..979b146bb22 100644
--- a/mysql-test/t/rpl_log_pos.test
+++ b/mysql-test/t/rpl_log_pos.test
@@ -5,7 +5,7 @@ source include/master-slave.inc;
show master status;
sync_slave_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
stop slave;
change master to master_log_pos=73;
@@ -15,19 +15,19 @@ stop slave;
change master to master_log_pos=73;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
start slave;
sleep 5;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
stop slave;
change master to master_log_pos=173;
start slave;
sleep 2;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
connection master;
show master status;
@@ -38,7 +38,7 @@ insert into t1 values (1),(2),(3);
save_master_pos;
connection slave;
stop slave;
-change master to master_log_pos=79;
+change master to master_log_pos=98;
start slave;
sync_with_master;
select * from t1;
diff --git a/mysql-test/t/rpl_max_relay_size.test b/mysql-test/t/rpl_max_relay_size.test
index c01041d7eee..9b6b06e0b14 100644
--- a/mysql-test/t/rpl_max_relay_size.test
+++ b/mysql-test/t/rpl_max_relay_size.test
@@ -29,7 +29,7 @@ select @@global.max_relay_log_size;
start slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
stop slave;
reset slave;
@@ -38,7 +38,7 @@ select @@global.max_relay_log_size;
start slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
stop slave;
reset slave;
@@ -47,7 +47,7 @@ select @@global.max_relay_log_size;
start slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# Tests below are mainly to ensure that we have not coded with wrong assumptions
@@ -58,7 +58,7 @@ reset slave;
# (to make sure it does not crash).
flush logs;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
reset slave;
@@ -74,7 +74,7 @@ save_master_pos;
connection slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# one more rotation, to be sure Relay_Log_Space is correctly updated
flush logs;
@@ -84,7 +84,7 @@ save_master_pos;
connection slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
connection master;
@@ -93,3 +93,4 @@ flush logs;
show master status;
# End of 4.1 tests
+#
diff --git a/mysql-test/t/rpl_multi_query.test b/mysql-test/t/rpl_multi_query.test
index 7c764bd4ea2..b4cd88f756e 100644
--- a/mysql-test/t/rpl_multi_query.test
+++ b/mysql-test/t/rpl_multi_query.test
@@ -24,8 +24,9 @@ sync_slave_with_master;
select * from mysqltest.t1;
connection master;
--replace_column 2 # 5 #
-show binlog events from 79;
+show binlog events from 98;
drop database mysqltest;
sync_slave_with_master;
# End of 4.1 tests
+#
diff --git a/mysql-test/t/rpl_openssl.test b/mysql-test/t/rpl_openssl.test
index a9138d1d46a..3c151721d8e 100644
--- a/mysql-test/t/rpl_openssl.test
+++ b/mysql-test/t/rpl_openssl.test
@@ -7,7 +7,7 @@ source include/master-slave.inc;
# creating replication user for whom ssl auth is required
# preparing playground
connection master;
-grant replication slave on *.* to replssl@'%' require ssl;
+grant replication slave on *.* to replssl@localhost require ssl;
create table t1 (t int);
save_master_pos;
@@ -45,7 +45,7 @@ select * from t1;
#checking show slave status
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
#checking if replication works without ssl also performing clean up
@@ -58,7 +58,7 @@ save_master_pos;
connection slave;
sync_with_master;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_redirect.test b/mysql-test/t/rpl_redirect.test
index 18f68b1fd03..beb18348b40 100644
--- a/mysql-test/t/rpl_redirect.test
+++ b/mysql-test/t/rpl_redirect.test
@@ -14,7 +14,7 @@ sync_with_master;
#discover slaves
connection master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
SHOW SLAVE STATUS;
--replace_result $SLAVE_MYPORT SLAVE_PORT
SHOW SLAVE HOSTS;
diff --git a/mysql-test/t/rpl_relayrotate-slave.opt b/mysql-test/t/rpl_relayrotate-slave.opt
index 8b671423363..3a4abbf091e 100644
--- a/mysql-test/t/rpl_relayrotate-slave.opt
+++ b/mysql-test/t/rpl_relayrotate-slave.opt
@@ -1,4 +1,3 @@
--O max_binlog_size=16384
+-O max_relay_log_size=16384
--innodb
--log-warnings
-
diff --git a/mysql-test/t/rpl_relayrotate.test b/mysql-test/t/rpl_relayrotate.test
index 1dab8bf4ed5..b66cf7a6e0d 100644
--- a/mysql-test/t/rpl_relayrotate.test
+++ b/mysql-test/t/rpl_relayrotate.test
@@ -55,8 +55,10 @@ start slave;
# reading, MASTER_POS_WAIT() will do it for sure
# (the only statement with position>=3000 is COMMIT).
select master_pos_wait('master-bin.001',3000)>=0;
-select * from t1 where a=8000;
-
+select max(a) from t1;
+--replace_column 1 # 8 # 9 # 23 # 33 #
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+show slave status;
connection master;
# The following DROP is a very important cleaning task:
diff --git a/mysql-test/t/rpl_replicate_do.test b/mysql-test/t/rpl_replicate_do.test
index 9bbaa9f0076..b8559af2394 100644
--- a/mysql-test/t/rpl_replicate_do.test
+++ b/mysql-test/t/rpl_replicate_do.test
@@ -33,7 +33,7 @@ connection slave;
sync_with_master;
# show slave status, just to see of it prints replicate-do-table
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
#
diff --git a/mysql-test/t/rpl_reset_slave.test b/mysql-test/t/rpl_reset_slave.test
index 102c72d9882..00b1cf68294 100644
--- a/mysql-test/t/rpl_reset_slave.test
+++ b/mysql-test/t/rpl_reset_slave.test
@@ -11,24 +11,24 @@ save_master_pos;
connection slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
stop slave;
change master to master_user='test';
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
reset slave;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
start slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# test of crash with temp tables & RESET SLAVE
@@ -48,3 +48,4 @@ sync_with_master;
show status like 'slave_open_temp_tables';
# End of 4.1 tests
+#
diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test
index 891582a167c..b125408d89e 100644
--- a/mysql-test/t/rpl_rotate_logs.test
+++ b/mysql-test/t/rpl_rotate_logs.test
@@ -9,7 +9,7 @@
# changes
# - Test creating a duplicate key error and recover from it
-connect (master,localhost,root,,test,$MASTER_MYPORT,master.sock);
+connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
--disable_warnings
drop table if exists t1, t2, t3, t4;
--enable_warnings
@@ -23,7 +23,8 @@ drop table if exists t1, t2, t3, t4;
# START SLAVE will fail because it can't read the file (mode 000)
# (system error 13)
---error 1201
+--replace_result $MYSQL_TEST_DIR TESTDIR
+--error 1105,1105,29
start slave;
system chmod 600 var/slave-data/master.info;
# It will fail again because the file is empty so the slave cannot get valuable
@@ -55,7 +56,7 @@ create table t1 (s text);
insert into t1 values('Could not break slave'),('Tried hard');
sync_slave_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
select * from t1;
connection master;
@@ -108,7 +109,7 @@ show binary logs;
insert into t2 values (65);
sync_slave_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
select * from t2;
@@ -140,7 +141,7 @@ sync_with_master;
select * from t4;
--replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 33 #
+--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
# because of concurrent insert, the table may not be up to date
# if we do not lock
diff --git a/mysql-test/t/rpl_session_var.test b/mysql-test/t/rpl_session_var.test
new file mode 100644
index 00000000000..a6f4b496a23
--- /dev/null
+++ b/mysql-test/t/rpl_session_var.test
@@ -0,0 +1,42 @@
+# Replication of session variables.
+# FOREIGN_KEY_CHECKS is tested in rpl_insert_id.test
+
+source include/master-slave.inc;
+drop table if exists t1;
+create table t1(a varchar(100),b int);
+set @@session.sql_mode=pipes_as_concat;
+insert into t1 values('My'||'SQL', 1);
+set @@session.sql_mode=default;
+insert into t1 values('1'||'2', 2);
+select * from t1 where b<3 order by a;
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from t1 where b<3 order by a;
+connection master;
+# if the slave does the next sync_with_master fine, then it means it accepts the
+# two lines of ANSI syntax below, which is what we want to check.
+set @@session.sql_mode=ignore_space;
+insert into t1 values(password ('MySQL'), 3);
+set @@session.sql_mode=ansi_quotes;
+create table "t2" ("a" int);
+drop table t1, t2;
+set @@session.sql_mode=default;
+create table t1(a int auto_increment primary key);
+create table t2(b int, a int);
+set @@session.sql_auto_is_null=1;
+insert into t1 values(null);
+insert into t2 select 1,a from t1 where a is null;
+set @@session.sql_auto_is_null=0;
+insert into t1 values(null);
+insert into t2 select 2,a from t1 where a is null;
+select * from t2 order by b;
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from t2 order by b;
+connection master;
+drop table t1,t2;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl_sp-master.opt b/mysql-test/t/rpl_sp-master.opt
new file mode 100644
index 00000000000..709a224fd92
--- /dev/null
+++ b/mysql-test/t/rpl_sp-master.opt
@@ -0,0 +1 @@
+--log_bin_trust_routine_creators=0
diff --git a/mysql-test/t/rpl_sp-slave.opt b/mysql-test/t/rpl_sp-slave.opt
new file mode 100644
index 00000000000..709a224fd92
--- /dev/null
+++ b/mysql-test/t/rpl_sp-slave.opt
@@ -0,0 +1 @@
+--log_bin_trust_routine_creators=0
diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test
new file mode 100644
index 00000000000..fa44b68bd8c
--- /dev/null
+++ b/mysql-test/t/rpl_sp.test
@@ -0,0 +1,266 @@
+# Test of replication of stored procedures (WL#2146 for MySQL 5.0)
+
+source include/master-slave.inc;
+
+# First let's test replication of current_user() (that's a related thing)
+# we need a db != test, where we don't have automatic grants
+create database if not exists mysqltest1;
+use mysqltest1;
+create table t1 (a varchar(100));
+sync_slave_with_master;
+use mysqltest1;
+
+# ********************** PART 1 : STORED PROCEDURES ***************
+
+# Does the same proc as on master get inserted into mysql.proc ?
+# (same definer, same properties...)
+
+connection master;
+# cleanup
+--disable_warnings
+drop procedure if exists foo;
+drop procedure if exists foo2;
+drop procedure if exists foo3;
+drop procedure if exists foo4;
+drop procedure if exists bar;
+drop function if exists fn1;
+--enable_warnings
+
+delimiter |;
+--error 1418 # not deterministic
+create procedure foo()
+begin
+ declare b int;
+ set b = 8;
+ insert into t1 values (b);
+ insert into t1 values (unix_timestamp());
+end|
+
+--replace_column 2 # 5 #
+show binlog events from 98| # check that not there
+
+create procedure foo() deterministic
+begin
+ declare b int;
+ set b = 8;
+ insert into t1 values (b);
+ insert into t1 values (unix_timestamp());
+end|
+delimiter ;|
+
+# we replace columns having times
+# (even with fixed timestamp displayed time may changed based on TZ)
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name='foo' and db='mysqltest1';
+sync_slave_with_master;
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name='foo' and db='mysqltest1';
+
+# Now when we call it, does the CALL() get into binlog,
+# or the substatements?
+connection master;
+# see if timestamp used in SP on slave is same as on master
+set timestamp=1000000000;
+call foo();
+--replace_column 2 # 5 #
+show binlog events from 308;
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+
+# Now a SP which is supposed to not update tables (CALL should not be
+# binlogged) as it's "read sql data", so should not give error even if
+# non-deterministic.
+
+connection master;
+delete from t1;
+create procedure foo2()
+ not deterministic
+ reads sql data
+ select * from mysqltest1.t1;
+call foo2();
+# verify CALL is not in binlog
+--replace_column 2 # 5 #
+show binlog events from 518;
+
+--error 1418
+alter procedure foo2 contains sql;
+
+# SP with definer's right
+
+drop table t1;
+create table t1 (a int);
+create table t2 like t1;
+
+create procedure foo3()
+ deterministic
+ insert into t1 values (15);
+
+# let's create a non-privileged user
+grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1;
+
+connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,);
+connection con1;
+
+--error 1419 # only full-global-privs user can create a routine
+create procedure foo4()
+ deterministic
+ insert into t1 values (10);
+
+connection master;
+set global log_bin_trust_routine_creators=1;
+connection con1;
+
+delimiter |;
+create procedure foo4()
+ deterministic
+ begin
+ insert into t2 values(3);
+ insert into t1 values (5);
+ end|
+
+delimiter ;|
+
+# I add ,0 so that it does not print the error in the test output,
+# because this error is hostname-dependent
+--error 1142,0
+call foo4(); # invoker has no INSERT grant on table => failure
+show warnings;
+
+connection master;
+call foo3(); # success (definer == root)
+show warnings;
+
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--error 1142,0
+call foo4(); # definer's rights => failure
+show warnings;
+
+# we test replication of ALTER PROCEDURE
+alter procedure foo4 sql security invoker;
+call foo4(); # invoker's rights => success
+show warnings;
+
+# Check that only successful CALLs are in binlog
+--replace_column 2 # 5 #
+show binlog events from 990;
+
+# Note that half-failed CALLs are not in binlog, which is a known
+# bug. If we compare t2 on master and slave we see they differ:
+
+select * from t1;
+select * from t2;
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+
+# Test of DROP PROCEDURE
+
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+connection master;
+drop procedure foo4;
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+sync_slave_with_master;
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+
+# ********************** PART 2 : FUNCTIONS ***************
+
+connection master;
+drop procedure foo;
+drop procedure foo2;
+drop procedure foo3;
+
+delimiter |;
+create function fn1(x int)
+ returns int
+ deterministic
+begin
+ insert into t1 values (x);
+ return x+2;
+end|
+
+delimiter ;|
+delete t1,t2 from t1,t2;
+select fn1(20);
+insert into t2 values(fn1(21));
+select * from t1;
+select * from t2;
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+
+connection master;
+delimiter |;
+
+drop function fn1;
+
+create function fn1()
+ returns int
+ deterministic
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+delete from t1;
+set timestamp=1000000000;
+insert into t1 values(fn1());
+
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where db='mysqltest1';
+select * from t1;
+
+sync_slave_with_master;
+use mysqltest1;
+select * from t1;
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where db='mysqltest1';
+
+# And now triggers
+
+connection con1;
+--error 1227
+create trigger trg before insert on t1 for each row set new.a= 10;
+
+connection master;
+# fn1() above uses timestamps, so in !ps-protocol, the timezone will be
+# binlogged, but in --ps-protocol it will not be (BUG#9359) so
+# the binlog offsets get shifted which spoils SHOW BINLOG EVENTS.
+# To be immune, we take a new binlog.
+flush logs;
+delete from t1;
+# TODO: when triggers can contain an update, test that this update
+# does not go into binlog.
+# I'm not setting user vars in the trigger, because replication of user vars
+# would take care of propagating the user var's value to slave, so even if
+# the trigger was not executed on slave it would not be discovered.
+create trigger trg before insert on t1 for each row set new.a= 10;
+insert into t1 values (1);
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+
+connection master;
+delete from t1;
+drop trigger trg;
+insert into t1 values (1);
+select * from t1;
+--replace_column 2 # 5 #
+show binlog events in 'master-bin.000002' from 98;
+sync_slave_with_master;
+select * from t1;
+
+
+# Clean up
+connection master;
+drop function fn1;
+drop database mysqltest1;
+drop user "zedjzlcsjhd"@127.0.0.1;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_sp_effects-master.opt b/mysql-test/t/rpl_sp_effects-master.opt
new file mode 100644
index 00000000000..61dd7a6ad0e
--- /dev/null
+++ b/mysql-test/t/rpl_sp_effects-master.opt
@@ -0,0 +1 @@
+--log_bin_trust_routine_creators=1
diff --git a/mysql-test/t/rpl_sp_effects-slave.opt b/mysql-test/t/rpl_sp_effects-slave.opt
new file mode 100644
index 00000000000..61dd7a6ad0e
--- /dev/null
+++ b/mysql-test/t/rpl_sp_effects-slave.opt
@@ -0,0 +1 @@
+--log_bin_trust_routine_creators=1
diff --git a/mysql-test/t/rpl_sp_effects.test b/mysql-test/t/rpl_sp_effects.test
new file mode 100644
index 00000000000..9da5723b993
--- /dev/null
+++ b/mysql-test/t/rpl_sp_effects.test
@@ -0,0 +1,203 @@
+# Test of replication of stored procedures (WL#2146 for MySQL 5.0)
+
+source include/master-slave.inc;
+
+# ****************************************************************
+connection master;
+
+# cleanup
+--disable_warnings
+drop procedure if exists p1;
+drop procedure if exists p2;
+drop function if exists f1;
+drop table if exists t1,t2;
+drop view if exists v1;
+--enable_warnings
+create table t1 (a int);
+
+# 1. Test simple variables use.
+delimiter //;
+create procedure p1()
+begin
+ declare spv int default 0;
+ while spv < 5 do
+ insert into t1 values(spv+1);
+ set spv=spv+1;
+ end while;
+end//
+delimiter ;//
+
+call p1();
+
+sync_slave_with_master;
+connection slave;
+select * from t1;
+connection master;
+delete from t1;
+
+# 2. Test SP variable name
+delimiter //;
+create procedure p2()
+begin
+ declare a int default 4;
+ create table t2 as select a;
+end//
+delimiter ;//
+
+call p2();
+select * from t2;
+sync_slave_with_master;
+connection slave;
+select * from t2;
+
+connection master;
+drop procedure p1;
+drop procedure p2;
+drop table t2;
+
+# 3. Test FUNCTIONs in various places
+
+delimiter //;
+create function f1(x int) returns int
+begin
+ insert into t1 values(x);
+ return x+1;
+end//
+
+create procedure p1(a int, b int)
+begin
+ declare v int default f1(5);
+ if (f1(6)) then
+ select 'yes';
+ end if;
+ set v = f1(7);
+ while f1(8) < 1 do
+ select 'this cant be';
+ end while;
+
+end//
+delimiter ;//
+
+call p1(f1(1), f1(2));
+select * from t1;
+
+create table t2(a int);
+insert into t2 values (10),(11);
+select a,f1(a) from t2;
+
+# This shouldn't put separate 'call f1(3)' into binlog:
+insert into t2 select f1(3);
+select 'master:',a from t1;
+
+sync_slave_with_master;
+connection slave;
+select 'slave:',a from t1;
+
+connection master;
+drop procedure p1;
+delete from t1;
+delete from t2;
+
+# 4. VIEWs
+delete from t1;
+insert into t2 values(1),(2);
+create view v1 as select f1(a) from t2;
+select * from v1;
+select 'master:',a from t1;
+
+sync_slave_with_master;
+connection slave;
+select 'slave:',a from t1;
+
+connection master;
+drop view v1;
+delete from t1;
+
+# 5. Prepared statements.
+prepare s1 from 'select f1(?)';
+set @xx=123;
+execute s1 using @xx;
+select 'master:',a from t1;
+
+sync_slave_with_master;
+connection slave;
+select 'slave:',a from t1;
+
+connection master;
+delete from t1;
+
+# 5. Cursors.
+# t2 has (1),(2);
+delimiter //;
+create procedure p1(spv int)
+begin
+ declare c cursor for select f1(spv) from t2;
+ while (spv > 2) do
+ open c;
+ fetch c into spv;
+ close c;
+ set spv= spv - 10;
+ end while;
+end//
+delimiter ;//
+
+call p1(15);
+select 'master:',a from t1;
+sync_slave_with_master;
+connection slave;
+select 'slave:',a from t1;
+
+connection master;
+drop procedure p1;
+drop function f1;
+drop table t1,t2;
+
+# BUG#12637: User variables + SPs replication
+create table t1 (a int);
+delimiter //;
+create procedure p1()
+begin
+ insert into t1 values(@x);
+ set @x=@x+1;
+ insert into t1 values(@x);
+ if (f2()) then
+ insert into t1 values(1243);
+ end if;
+end//
+
+create function f2() returns int
+begin
+ insert into t1 values(@z);
+ set @z=@z+1;
+ insert into t1 values(@z);
+ return 0;
+end//
+
+create function f1() returns int
+begin
+ insert into t1 values(@y);
+ call p1();
+ return 0;
+end//
+
+delimiter ;//
+
+set @x=10;
+set @y=20;
+set @z=100;
+select f1();
+
+set @x=30;
+call p1();
+
+select 'master', a from t1;
+sync_slave_with_master;
+connection slave;
+select 'slave', a from t1;
+
+connection master;
+drop table t1;
+drop function f1;
+drop function f2;
+drop procedure p1;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test
index 8dead9138c1..fcb2391a9d8 100644
--- a/mysql-test/t/rpl_temporary.test
+++ b/mysql-test/t/rpl_temporary.test
@@ -82,6 +82,7 @@ drop temporary table t3;
select * from t2;
--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
show binlog events;
drop table t1, t2;
diff --git a/mysql-test/t/rpl_timezone-slave.opt b/mysql-test/t/rpl_timezone-slave.opt
index 8e43bfbbb7e..191182c329c 100644
--- a/mysql-test/t/rpl_timezone-slave.opt
+++ b/mysql-test/t/rpl_timezone-slave.opt
@@ -1 +1 @@
---default-time-zone=Europe/Moscow
+--default-time-zone=Japan
diff --git a/mysql-test/t/rpl_timezone.test b/mysql-test/t/rpl_timezone.test
index d371e8b62e5..2e9883141d8 100644
--- a/mysql-test/t/rpl_timezone.test
+++ b/mysql-test/t/rpl_timezone.test
@@ -1,23 +1,38 @@
# Test of replication of time zones.
+
+# There is currently some bug possibly in prepared statements (this
+# test fails with --ps-protocol): sys_var_thd_time_zone::value_ptr()
+# is called only at prepare time, not at execution time. So,
+# thd->time_zone_used is not equal to 1 (it is back to 0, because of
+# reset_thd_for_next_command called at execution time), so the
+# timezone used in CONVERT_TZ is not binlogged. To debug (by Guilhem
+# and possibly Konstantin).
+
+--disable_ps_protocol
+
source include/master-slave.inc;
# Some preparations
let $VERSION=`select version()`;
+set timestamp=100000000; # for fixed output of mysqlbinlog
create table t1 (t timestamp);
create table t2 (t char(32));
+connection slave;
+select @@time_zone;
+
#
# Let us check how well replication works when we are saving datetime
# value in TIMESTAMP field.
#
connection master;
select @@time_zone;
+insert into t1 values ('20050101000000'), ('20050611093902');
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;
+set time_zone='UTC';
select * from t1;
# Let us check also that setting of time_zone back to default also works
@@ -28,11 +43,29 @@ set time_zone='Europe/Moscow';
insert into t1 values ('20040101000000'), ('20040611093902');
select * from t1;
sync_slave_with_master;
+set time_zone='Europe/Moscow';
select * from t1;
connection master;
-# We should not see SET ONE_SHOT time_zone before second insert
---replace_result $VERSION VERSION
-show binlog events;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
+
+# Let us check with LOAD DATA INFILE
+# (we do it after mysqlbinlog because the temp files names are not constant)
+connection master;
+delete from t1;
+set time_zone='UTC';
+load data infile '../../std_data/rpl_timezone.dat' into table t1;
+select * from t1;
+sync_slave_with_master;
+set time_zone='UTC';
+select * from t1;
+set time_zone='Europe/Moscow';
+
+# Put back values of before the LOAD
+connection master;
+set time_zone='Europe/Moscow';
+delete from t1;
+insert into t1 values ('20040101000000'), ('20040611093902');
#
# Now let us check how well we replicate statments reading TIMESTAMP fields
@@ -53,10 +86,6 @@ 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;
#
@@ -72,14 +101,25 @@ sync_slave_with_master;
select * from t2;
#
-# Let us check that we are not allowing to set global time_zone with
+# Let us check that we are allowing to set global time_zone with
# replication
#
connection master;
---error 1105
set global time_zone='MET';
+#
+# Let us see if CONVERT_TZ(@@time_zone) replicates
+#
+delete from t2;
+set time_zone='UTC';
+insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone));
+insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan'));
+select * from t2;
+sync_slave_with_master;
+select * from t2;
+
# Clean up
+connection master;
drop table t1, t2;
sync_slave_with_master;
diff --git a/mysql-test/t/rpl_trigger.test b/mysql-test/t/rpl_trigger.test
new file mode 100644
index 00000000000..715222f0314
--- /dev/null
+++ b/mysql-test/t/rpl_trigger.test
@@ -0,0 +1,118 @@
+#
+# Test of triggers with replication
+#
+
+source include/master-slave.inc;
+
+#
+# #12482: Triggers has side effects with auto_increment values
+#
+
+create table t1 (a int auto_increment, primary key (a), b int, rand_value double not null);
+create table t2 (a int auto_increment, primary key (a), b int);
+create table t3 (a int auto_increment, primary key (a), name varchar(64) not null, old_a int, old_b int, rand_value double not null);
+
+delimiter |;
+create trigger t1 before insert on t1 for each row
+begin
+ insert into t3 values (NULL, "t1", new.a, new.b, rand());
+end|
+
+create trigger t2 after insert on t2 for each row
+begin
+ insert into t3 values (NULL, "t2", new.a, new.b, rand());
+end|
+delimiter ;|
+
+insert into t3 values(100,"log",0,0,0);
+
+# Ensure we always have same random numbers
+SET @@RAND_SEED1=658490765, @@RAND_SEED2=635893186;
+
+# Emulate that we have rows 2-9 deleted on the slave
+insert into t1 values(1,1,rand()),(NULL,2,rand());
+insert into t2 (b) values(last_insert_id());
+insert into t2 values(3,0),(NULL,0);
+insert into t2 values(NULL,0),(500,0);
+
+select a,b, truncate(rand_value,4) from t1;
+select * from t2;
+select a,name, old_a, old_b, truncate(rand_value,4) from t3;
+save_master_pos;
+connection slave;
+sync_with_master;
+--disable_query_log
+select "--- On slave --" as "";
+--enable_query_log
+select a,b, truncate(rand_value,4) from t1;
+select * from t2;
+select a,name, old_a, old_b, truncate(rand_value,4) from t3;
+connection master;
+drop table t1,t2,t3;
+
+#
+# #12480: NOW() is not constant in a trigger
+# #12481: Using NOW() in a stored function breaks statement based replication
+#
+
+# Start by getting a lock on 'bug12480' to be able to use get_lock() as sleep()
+connect (con2,localhost,root,,);
+connection con2;
+select get_lock("bug12480",2);
+connection default;
+
+create table t1 (a datetime,b datetime, c datetime);
+--ignore_warnings
+drop function if exists bug12480;
+--enable_warnings
+
+delimiter |;
+
+create function bug12480() returns datetime
+begin
+ set @a=get_lock("bug12480",2);
+ return now();
+end|
+
+create trigger t1_first before insert on t1
+for each row begin
+ set @a=get_lock("bug12480",2);
+ set new.b= now();
+ set new.c= bug12480();
+end
+|
+
+delimiter ;|
+insert into t1 set a = now();
+select a=b && a=c from t1;
+let $time=`select a from t1`;
+
+save_master_pos;
+connection slave;
+sync_with_master;
+--disable_query_log
+select "--- On slave --" as "";
+--enable_query_log
+select a=b && a=c from t1;
+--disable_query_log
+eval select a='$time' as 'test' from t1;
+--enable_query_log
+
+connection master;
+disconnect con2;
+
+truncate table t1;
+drop trigger t1_first;
+
+insert into t1 values ("2003-03-03","2003-03-03","2003-03-03"),(bug12480(),bug12480(),bug12480()),(now(),now(),now());
+select a=b && a=c from t1;
+
+drop function bug12480;
+drop table t1;
+
+#
+# End of test
+#
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test
deleted file mode 100644
index 9cdf1d8ddbd..00000000000
--- a/mysql-test/t/rpl_trunc_binlog.test
+++ /dev/null
@@ -1,27 +0,0 @@
-# We are testing if a binlog which contains BEGIN but not COMMIT (the
-# master did while writing the transaction to the binlog) triggers an
-# error on slave. So we use such a truncated binlog and simulate that
-# the master restarted after this.
-
-source include/master-slave.inc;
-
-connection slave;
-# If we are not supporting transactions in the slave, the unfinished transaction
-# won't cause any error, so we need to skip the test. In the 4.0 testsuite, the
-# slave always runs without InnoDB, so we check for BDB.
-source include/have_bdb.inc;
-stop slave;
-connection master;
-flush logs;
-system mv -f var/log/master-bin.000001 var/log/master-bin.000002;
-system cp std_data/trunc_binlog.000001 var/log/master-bin.000001;
-connection slave;
-reset slave;
-start slave;
-# can't sync_with_master so we must sleep
-sleep 3;
---replace_result $MASTER_MYPORT MASTER_PORT
---replace_column 1 # 23 # 33 #
-show slave status;
-
-# End of 4.1 tests
diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test
index 6fd58252ed4..5bc7a040b1b 100644
--- a/mysql-test/t/rpl_until.test
+++ b/mysql-test/t/rpl_until.test
@@ -24,8 +24,9 @@ show binlog events;
# try to replicate all queries until drop of t1
connection slave;
-start slave until master_log_file='master-bin.000001', master_log_pos=244;
+start slave until master_log_file='master-bin.000001', master_log_pos=319;
sleep 2;
+wait_for_slave_to_stop;
# here table should be still not deleted
select * from t1;
--replace_result $MASTER_MYPORT MASTER_MYPORT
@@ -37,13 +38,15 @@ start slave until master_log_file='master-no-such-bin.000001', master_log_pos=29
# again this table should be still not deleted
select * from t1;
sleep 2;
+wait_for_slave_to_stop;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 23 # 33 #
show slave status;
# try replicate all until second insert to t2;
-start slave until relay_log_file='slave-relay-bin.000002', relay_log_pos=537;
-sleep 4;
+start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746;
+sleep 2;
+wait_for_slave_to_stop;
select * from t2;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 23 # 33 #
@@ -57,10 +60,10 @@ connection slave;
sync_with_master;
stop slave;
-# this should stop immideately
-start slave until master_log_file='master-bin.000001', master_log_pos=561;
-# 2 is not enough when running with valgrind
---real_sleep 4
+# this should stop immediately as we are already there
+start slave until master_log_file='master-bin.000001', master_log_pos=776;
+sleep 2;
+wait_for_slave_to_stop;
# here the sql slave thread should be stopped
--replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
--replace_column 1 # 9 # 23 # 33 #
@@ -77,8 +80,8 @@ start slave until master_log_file='master-bin.000001';
start slave until relay_log_file='slave-relay-bin.000002';
--error 1277
start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561;
-
+# Warning should be given for second command
start slave sql_thread;
-start slave until master_log_file='master-bin.000001', master_log_pos=561;
+start slave until master_log_file='master-bin.000001', master_log_pos=776;
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test
index 5cf502e05bd..e8985397703 100644
--- a/mysql-test/t/rpl_user_variables.test
+++ b/mysql-test/t/rpl_user_variables.test
@@ -46,7 +46,8 @@ save_master_pos;
connection slave;
sync_with_master;
select * from t1;
-show binlog events from 141;
+--replace_column 2 # 5 #
+show binlog events from 98;
connection master;
drop table t1;
save_master_pos;
diff --git a/mysql-test/t/rpl_variables-master.opt b/mysql-test/t/rpl_variables-master.opt
new file mode 100644
index 00000000000..a668c6bfbe8
--- /dev/null
+++ b/mysql-test/t/rpl_variables-master.opt
@@ -0,0 +1 @@
+--slave-skip-errors=3,100,137,643,1752
diff --git a/mysql-test/t/rpl_variables.test b/mysql-test/t/rpl_variables.test
index 8c5279c0420..57ae2b9c3c4 100644
--- a/mysql-test/t/rpl_variables.test
+++ b/mysql-test/t/rpl_variables.test
@@ -4,3 +4,11 @@ set global slave_net_timeout=100;
set global sql_slave_skip_counter=100;
# End of 4.1 tests
+
+# BUG #7800: Add various-slave related variables to SHOW VARIABLES
+show variables like 'slave_compressed_protocol';
+--replace_column 2 SLAVE_LOAD_TMPDIR
+show variables like 'slave_load_tmpdir';
+# We just set some arbitrary values in variables-master.opt so we can test
+# that a list of values works correctly
+show variables like 'slave_skip_errors';
diff --git a/mysql-test/t/rpl_view.test b/mysql-test/t/rpl_view.test
new file mode 100644
index 00000000000..0a0c6a6dddb
--- /dev/null
+++ b/mysql-test/t/rpl_view.test
@@ -0,0 +1,47 @@
+source include/master-slave.inc;
+--disable_warnings
+drop table if exists t1,v1;
+drop view if exists t1,v1;
+sync_slave_with_master;
+reset master;
+--enable_warnings
+
+#
+# Check that createion drop of view is replicated, also check replication of
+# updating of view
+#
+connection master;
+create table t1 (a int);
+insert into t1 values (1);
+create view v1 as select a from t1;
+insert into v1 values (2);
+select * from v1 order by a;
+sync_slave_with_master;
+# view already have to be on slave
+select * from v1 order by a;
+connection master;
+update v1 set a=3 where a=1;
+select * from v1 order by a;
+sync_slave_with_master;
+select * from v1 order by a;
+connection master;
+delete from v1 where a=2;
+select * from v1 order by a;
+sync_slave_with_master;
+select * from v1 order by a;
+connection master;
+# 'alter view' internally maped to creation, but still check that it works
+alter view v1 as select a as b from t1;
+sync_slave_with_master;
+select * from v1 order by 1;
+connection master;
+drop view v1;
+sync_slave_with_master;
+#error, because view have to be removed from slave
+-- error 1146
+select * from v1 order by a;
+connection master;
+drop table t1;
+sync_slave_with_master;
+--replace_column 2 # 5 #
+show binlog events limit 1,100;
diff --git a/mysql-test/t/schema.test b/mysql-test/t/schema.test
new file mode 100644
index 00000000000..d9bd607b2db
--- /dev/null
+++ b/mysql-test/t/schema.test
@@ -0,0 +1,8 @@
+#
+# Just a couple of tests to make sure that schema works.
+#
+
+create schema foo;
+show create schema foo;
+show schemas;
+drop schema foo;
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index b51ea89c7dd..620a9fb55b7 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -9,7 +9,8 @@
--disable_warnings
drop table if exists t1,t2,t3,t4;
# The following may be left from older tests
-drop table if exists t1_1,t1_2,t9_1,t9_2;
+drop table if exists t1_1,t1_2,t9_1,t9_2,t1aa,t2aa;
+drop view if exists v1;
--enable_warnings
CREATE TABLE t1 (
@@ -1541,6 +1542,11 @@ select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.
select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null;
explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null;
+
+select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+select count(*) from t2 left join t4 using (companynr) where companynr is not null;
+explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null;
delete from t2 where fld1=999999;
#
@@ -1549,11 +1555,19 @@ delete from t2 where fld1=999999;
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0;
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
+
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;
# Following can't be optimized
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0;
explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0;
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;
+explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;
+
#
# Joins with forms.
#
@@ -1764,9 +1778,9 @@ DO benchmark(100,1+1),1,1;
# Bug #6449: do default;
#
---error 1064
+--error ER_PARSE_ERROR
do default;
---error 1054
+--error ER_BAD_FIELD_ERROR
do foobar;
#
@@ -1788,11 +1802,14 @@ DROP TABLE t1;
# Test of bug with SUM(CASE...)
#
-CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp(14) NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
+CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL);
CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM;
INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35);
+# Disable PS becasue we get more warnings from PS than from normal execution
+--disable_ps_protocol
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;
+--enable_ps_protocol
# 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;
@@ -2117,8 +2134,8 @@ WHERE
drop table t1,t2,t3;
#
-# Bug #11482 4.1.12 produces different resultset for a complex query
-# than in previous 4.1.x
+# Bug #11482 Wrongly applied optimization was erroneously rejecting valid
+# rows
create table t1 (f1 int);
insert into t1 values (1),(NULL);
create table t2 (f2 int, f3 int, f4 int);
@@ -2165,3 +2182,356 @@ select found_rows();
DROP TABLE t1;
# End of 4.1 tests
+
+#
+# Test case for bug 7098: substitution of a constant for a string field
+#
+
+CREATE TABLE t1 ( city char(30) );
+INSERT INTO t1 VALUES ('London');
+INSERT INTO t1 VALUES ('Paris');
+
+SELECT * FROM t1 WHERE city='London';
+SELECT * FROM t1 WHERE city='london';
+EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london';
+SELECT * FROM t1 WHERE city='London' AND city='london';
+EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
+SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
+
+DROP TABLE t1;
+
+#
+# Bug#7425 inconsistent sort order on unsigned columns result of substraction
+#
+
+create table t1 (a int(11) unsigned, b int(11) unsigned);
+insert into t1 values (1,0), (1,1), (1,2);
+select a-b from t1 order by 1;
+select a-b , (a-b < 0) from t1 order by 1;
+select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
+select cast((a - b) as unsigned) from t1 order by 1;
+drop table t1;
+
+
+#
+# Bug#8733 server accepts malformed query (multiply mentioned distinct)
+#
+create table t1 (a int(11));
+select all all * from t1;
+select distinct distinct * from t1;
+--error 1221
+select all distinct * from t1;
+--error 1221
+select distinct all * from t1;
+drop table t1;
+
+#
+# Test for bug #6474
+#
+
+CREATE TABLE t1 (
+K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '',
+K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000',
+F2I4 int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+INSERT INTO t1 VALUES
+('W%RT', '0100', 1),
+('W-RT', '0100', 1),
+('WART', '0100', 1),
+('WART', '0200', 1),
+('WERT', '0100', 2),
+('WORT','0200', 2),
+('WT', '0100', 2),
+('W_RT', '0100', 2),
+('WaRT', '0100', 3),
+('WART', '0300', 3),
+('WRT' , '0400', 3),
+('WURM', '0500', 3),
+('W%T', '0600', 4),
+('WA%T', '0700', 4),
+('WA_T', '0800', 4);
+
+SELECT K2C4, K4N4, F2I4 FROM t1
+ WHERE K2C4 = 'WART' AND
+ (F2I4 = 2 AND K2C4 = 'WART' OR (F2I4 = 2 OR K4N4 = '0200'));
+SELECT K2C4, K4N4, F2I4 FROM t1
+ WHERE K2C4 = 'WART' AND (K2C4 = 'WART' OR K4N4 = '0200');
+DROP TABLE t1;
+
+#
+# Test case for bug 7520: a wrong cost of the index for a BLOB field
+#
+
+CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
+CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
+
+INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
+INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
+
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
+
+DROP TABLE t1, t2;
+
+#
+# Bug#8670
+#
+create table t1 (a int, b int);
+create table t2 like t1;
+select t1.a from (t1 inner join t2 on t1.a=t2.a) where t2.a=1;
+select t1.a from ((t1 inner join t2 on t1.a=t2.a)) where t2.a=1;
+select x.a, y.a, z.a from ( (t1 x inner join t2 y on x.a=y.a) inner join t2 z on y.a=z.a) WHERE x.a=1;
+drop table t1,t2;
+
+#
+# Bug#9820
+#
+
+create table t1 (s1 varchar(5));
+insert into t1 values ('Wall');
+select min(s1) from t1 group by s1 with rollup;
+drop table t1;
+
+#
+# Bug#9799
+#
+
+create table t1 (s1 int) engine=myisam;
+insert into t1 values (0);
+select avg(distinct s1) from t1 group by s1 with rollup;
+drop table t1;
+
+#
+# Bug#9800
+#
+
+create table t1 (s1 int);
+insert into t1 values (null),(1);
+select distinct avg(s1) as x from t1 group by s1 with rollup;
+drop table t1;
+
+
+#
+# Bug#8733 server accepts malformed query (multiply mentioned distinct)
+#
+create table t1 (a int(11));
+select all all * from t1;
+select distinct distinct * from t1;
+--error 1221
+select all distinct * from t1;
+--error 1221
+select distinct all * from t1;
+drop table t1;
+
+
+#
+# Test case for bug 7520: a wrong cost of the index for a BLOB field
+#
+
+CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
+CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
+
+INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
+INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
+
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
+
+DROP TABLE t1, t2;
+
+#
+# Test for bug #10084: STRAIGHT_JOIN with ON expression
+#
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+INSERT INTO t2 VALUES (2), (4), (6);
+
+SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a;
+
+EXPLAIN SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a;
+EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a;
+
+DROP TABLE t1,t2;
+
+#
+# Bug #10650
+#
+
+select x'10' + 0, X'10' + 0, b'10' + 0, B'10' + 0;
+
+#
+# Bug #11398 Bug in field_conv() results in wrong result of join with index
+#
+create table t1 (f1 varchar(6) default NULL, f2 int(6) primary key not null);
+create table t2 (f3 varchar(5) not null, f4 varchar(5) not null, UNIQUE KEY UKEY (f3,f4));
+insert into t1 values (" 2", 2);
+insert into t2 values (" 2", " one "),(" 2", " two ");
+select * from t1 left join t2 on f1 = f3;
+drop table t1,t2;
+
+#
+# Bug #6558 Views: CREATE VIEW fails with JOIN ... USING
+#
+
+create table t1 (empnum smallint, grp int);
+create table t2 (empnum int, name char(5));
+insert into t1 values(1,1);
+insert into t2 values(1,'bob');
+create view v1 as select * from t2 inner join t1 using (empnum);
+select * from v1;
+drop table t1,t2;
+drop view v1;
+
+#
+# Bug #10646 Columns included in the join between two tables are ambigious
+# in the select
+#
+
+create table t1 (pk int primary key, b int);
+create table t2 (pk int primary key, c int);
+select pk from t1 inner join t2 using (pk);
+drop table t1,t2;
+
+#
+# Bug #10972 Natural join of view and underlying table gives wrong result
+#
+
+create table t1 (s1 int, s2 char(5), s3 decimal(10));
+create view v1 as select s1, s2, 'x' as s3 from t1;
+select * from t1 natural join v1;
+insert into t1 values (1,'x',5);
+select * from t1 natural join v1;
+drop table t1;
+drop view v1;
+
+#
+# Bug #6276 A SELECT that does a NATURAL OUTER JOIN without common
+# columns crashes server because of empty ON condition
+#
+
+create table t1(a1 int);
+create table t2(a2 int);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+create view v2 (c) as select a1 from t1;
+
+select * from t1 natural left join t2;
+select * from t1 natural right join t2;
+
+select * from v2 natural left join t2;
+select * from v2 natural right join t2;
+
+drop table t1, t2;
+drop view v2;
+
+
+#
+# Bug #4789 Incosistent results of more than 2-way natural joins due to
+# incorrect transformation to join ... on.
+#
+
+create table t1 (a int(10), t1_val int(10));
+create table t2 (b int(10), t2_val int(10));
+create table t3 (a int(10), b int(10));
+insert into t1 values (1,1),(2,2);
+insert into t2 values (1,1),(2,2),(3,3);
+insert into t3 values (1,1),(2,1),(3,1),(4,1);
+# the following two queries must return the same result
+select * from t1 natural join t2 natural join t3;
+select * from t1 natural join t3 natural join t2;
+drop table t1, t2, t3;
+
+
+#
+# Bug #12841: Server crash on DO IFNULL(NULL,NULL)
+#
+# (testing returning of int, decimal, real, string)
+DO IFNULL(NULL, NULL);
+SELECT CAST(IFNULL(NULL, NULL) AS DECIMAL);
+SELECT ABS(IFNULL(NULL, NULL));
+SELECT IFNULL(NULL, NULL);
+
+#
+# Bug #6495 Illogical requirement for column qualification in NATURAL join
+#
+
+create table t1 (a char(1));
+create table t2 (a char(1));
+insert into t1 values ('a'),('b'),('c');
+insert into t2 values ('b'),('c'),('d');
+select a from t1 natural join t2;
+select * from t1 natural join t2 where a = 'b';
+drop table t1, t2;
+
+#
+# Bug #12977 Compare table names with qualifying field tables only
+# for base tables, search all nested join operands of natural joins.
+#
+
+CREATE TABLE t1 (`id` TINYINT);
+CREATE TABLE t2 (`id` TINYINT);
+CREATE TABLE t3 (`id` TINYINT);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t3 VALUES (3);
+-- error 1052
+SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
+-- error 1052
+SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.notacolumn=t1.id) LEFT JOIN t3 USING (id);
+-- error 1052
+SELECT id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
+-- error 1052
+SELECT id,t3.id FROM (t1 JOIN t2 ON (t2.id=t1.id)) LEFT JOIN t3 USING (id);
+
+drop table t1, t2, t3;
+
+#
+# Bug #13067 JOIN xxx USING is case sensitive
+#
+
+create table t1 (a int(10),b int(10));
+create table t2 (a int(10),b int(10));
+insert into t1 values (1,10),(2,20),(3,30);
+insert into t2 values (1,10);
+# both queries should produce the same result
+select * from t1 inner join t2 using (A);
+select * from t1 inner join t2 using (a);
+drop table t1, t2;
+
+#
+# Bug #12943 Incorrect nesting of [INNER| CROSS] JOIN due to unspecified
+# associativity in the parser.
+#
+
+create table t1 (a int, c int);
+create table t2 (b int);
+create table t3 (b int, a int);
+create table t4 (c int);
+insert into t1 values (1,1);
+insert into t2 values (1);
+insert into t3 values (1,1);
+insert into t4 values (1);
+
+select * from t1 join t2 join t3 on (t2.b = t3.b and t1.a = t3.a);
+# Notice that ',' has lower priority than 'join', thus we have that:
+# t1, t2 join t3 <==> t1, (t2 join t3).
+-- error 1054
+select * from t1, t2 join t3 on (t2.b = t3.b and t1.a = t3.a);
+select * from t1 join t2 join t3 join t4 on (t1.a = t4.c and t2.b = t4.c);
+select * from t1 join t2 join t4 using (c);
+drop table t1, t2, t3, t4;
+
+#
+# Bug #12291 Table wasn't reinited for index scan after sequential scan
+#
+create table t1(x int, y int);
+create table t2(x int, y int);
+create table t3(x int, primary key(x));
+insert into t1 values (1, 1), (2, 1), (3, 1), (4, 3), (5, 6), (6, 6);
+insert into t2 values (1, 1), (2, 1), (3, 3), (4, 6), (5, 6);
+insert into t3 values (1), (2), (3), (4), (5);
+select t1.x, t3.x from t1, t2, t3 where t1.x = t2.x and t3.x >= t1.y and t3.x <= t2.y;
+drop table t1,t2,t3;
diff --git a/mysql-test/t/select_safe.test b/mysql-test/t/select_safe.test
index 236370bef03..481779e76d7 100644
--- a/mysql-test/t/select_safe.test
+++ b/mysql-test/t/select_safe.test
@@ -56,7 +56,6 @@ SELECT * from t1;
#
# Test MAX_SEEKS_FOR_KEY
#
-SELECT @@MAX_SEEKS_FOR_KEY;
analyze table t1;
insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a");
explain select STRAIGHT_JOIN * from t1,t1 as t2 where t1.b=t2.b;
@@ -79,7 +78,7 @@ select * from (select * from t1) x;
set local max_join_size=1;
--error 1104
-select * from (select * from t1 a, t1 b) x;
+select * from (select a.a as aa, b.a as ba from t1 a, t1 b) x;
set local max_join_size=1;
--error 1104
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index e6a404e3b57..b9fc991dc80 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -8,6 +8,7 @@
--disable_warnings
drop table if exists t1,t2;
+drop table if exists t1aa,t2aa;
drop database if exists mysqltest;
delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
@@ -105,7 +106,7 @@ drop table t1;
# Do a create table that tries to cover all types and options
#
create table t1 (
-type_bool bool not null,
+type_bool bool not null default 0,
type_tiny tinyint not null auto_increment primary key,
type_short smallint(3),
type_mediumint mediumint,
@@ -116,9 +117,9 @@ empty_char char(0),
type_char char(2),
type_varchar varchar(10),
type_timestamp timestamp not null,
-type_date date not null,
-type_time time not null,
-type_datetime datetime not null,
+type_date date not null default '0000-00-00',
+type_time time not null default '00:00:00',
+type_datetime datetime not null default '0000-00-00 00:00:00',
type_year year,
type_enum enum ('red', 'green', 'blue'),
type_set enum ('red', 'green', 'blue'),
@@ -176,16 +177,24 @@ CREATE TABLE `a/b` (i INT);
#CREATE TABLE ```ab````cd``` (i INT);
#SHOW CREATE TABLE ```ab````cd```;
#DROP TABLE ```ab````cd```;
-
+#
#CREATE TABLE ```a` (i INT);
#SHOW CREATE TABLE ```a`;
#DROP TABLE ```a`;
-
-SET sql_mode= 'ANSI_QUOTES';
-
+#
+#SET sql_mode= 'ANSI_QUOTES';
+#
#CREATE TABLE """a" (i INT);
#SHOW CREATE TABLE """a";
#DROP TABLE """a";
+#
+#Bug #4374 SHOW TABLE STATUS FROM ignores collation_connection
+#set names latin1;
+#create database `ä`;
+#create table `ä`.`ä` (a int) engine=heap;
+#--replace_column 7 # 8 # 9 #
+#show table status from `ä` LIKE 'ä';
+#drop database `ä`;
#########################################################
# end of part that must be uncommented when WL#1324 is done
#########################################################
@@ -214,7 +223,7 @@ select @@max_heap_table_size;
CREATE TABLE t1 (
a int(11) default NULL,
- KEY a TYPE BTREE (a)
+ KEY a USING BTREE (a)
) ENGINE=HEAP;
CREATE TABLE t2 (
@@ -225,7 +234,7 @@ CREATE TABLE t2 (
CREATE TABLE t3 (
a int(11) default NULL,
b int(11) default NULL,
- KEY a TYPE BTREE (a),
+ KEY a USING BTREE (a),
index(b)
) ENGINE=HEAP;
@@ -283,25 +292,25 @@ connect (con1,localhost,mysqltest_1,,mysqltest);
connection con1;
select * from t1;
show create database mysqltest;
---error 1044
+--error 1142
drop table t1;
--error 1044
drop database mysqltest;
connect (con2,localhost,mysqltest_2,,test);
connection con2;
---error 1044
+--error 1142
select * from mysqltest.t1;
--error 1044
show create database mysqltest;
---error 1044
+--error 1142
drop table mysqltest.t1;
--error 1044
drop database mysqltest;
connect (con3,localhost,mysqltest_3,,test);
connection con3;
---error 1044
+--error 1142
select * from mysqltest.t1;
--error 1044
show create database mysqltest;
@@ -316,7 +325,6 @@ delete from mysql.db
where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
flush privileges;
-#Bug #4374 SHOW TABLE STATUS FROM ignores collation_connection
# This test fails on MAC OSX, so it is temporary disabled.
# This needs WL#1324 to be done.
#set names latin1;
@@ -379,3 +387,26 @@ SHOW CREATE TABLE t1;
DROP TABLE t1;
# End of 4.1 tests
+#
+# BUG 12183 - SHOW OPEN TABLES behavior doesn't match grammar
+# First we close all open tables with FLUSH tables and then we open some.
+CREATE TABLE txt1(a int);
+CREATE TABLE tyt2(a int);
+CREATE TABLE urkunde(a int);
+FLUSH TABLES;
+SELECT 1 FROM mysql.db, mysql.proc, mysql.user, mysql.time_zone, mysql.time_zone_name, txt1, tyt2, urkunde LIMIT 0;
+SHOW OPEN TABLES;
+SHOW OPEN TABLES FROM mysql;
+SHOW OPEN TABLES FROM mysql LIKE 'u%';
+SHOW OPEN TABLES LIKE 't%';
+SHOW OPEN TABLES LIKE '%o%';
+FLUSH TABLES;
+SHOW OPEN TABLES;
+DROP TABLE txt1;
+DROP TABLE tyt2;
+DROP TABLE urkunde;
+#
+# BUG #12591 (SHOW TABLES FROM dbname produces wrong error message)
+#
+--error 1049
+SHOW TABLES FROM non_existing_database;
diff --git a/mysql-test/t/skip_grants-master.opt b/mysql-test/t/skip_grants-master.opt
new file mode 100644
index 00000000000..5699a3387b8
--- /dev/null
+++ b/mysql-test/t/skip_grants-master.opt
@@ -0,0 +1 @@
+--skip-grant-tables
diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test
new file mode 100644
index 00000000000..156547ea6aa
--- /dev/null
+++ b/mysql-test/t/skip_grants.test
@@ -0,0 +1,21 @@
+--disable_warnings
+drop table if exists t1,v1;
+drop view if exists t1,v1;
+drop procedure if exists f1;
+--enable_warnings
+use test;
+
+#
+# test that we can create VIEW if privileges check switched off
+#
+create table t1 (field1 INT);
+-- error ER_NO_VIEW_USER
+CREATE VIEW v1 AS SELECT field1 FROM t1;
+drop table t1;
+
+#
+# Test that we can create and drop procedure without warnings
+# see bug#9993
+#
+create procedure f1() select 1;
+drop procedure f1;
diff --git a/mysql-test/t/sp-big.test b/mysql-test/t/sp-big.test
new file mode 100644
index 00000000000..769d77dbef9
--- /dev/null
+++ b/mysql-test/t/sp-big.test
@@ -0,0 +1,33 @@
+#
+# Bug #11602: SP with very large body not handled well
+#
+
+--disable_warnings
+drop procedure if exists test.longprocedure;
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (a int);
+insert into t1 values (1),(2),(3);
+
+let $body=`select repeat('select count(*) into out1 from t1;\n', 3072)`;
+
+delimiter //;
+--disable_query_log
+eval select length('$body') as length//
+eval create procedure test.longprocedure (out out1 int) deterministic
+begin
+ $body
+end//
+--enable_query_log
+
+delimiter ;//
+
+# this is larger than the length above, because it includes the 'begin' and
+# 'end' bits and some whitespace
+select length(routine_definition) from information_schema.routines where routine_schema = 'test' and routine_name = 'longprocedure';
+
+call test.longprocedure(@value); select @value;
+
+drop procedure test.longprocedure;
+drop table t1;
diff --git a/mysql-test/t/sp-dynamic.test b/mysql-test/t/sp-dynamic.test
new file mode 100644
index 00000000000..e9816ee3ef0
--- /dev/null
+++ b/mysql-test/t/sp-dynamic.test
@@ -0,0 +1,335 @@
+delimiter |;
+######################################################################
+# Test Dynamic SQL in stored procedures. #############################
+######################################################################
+#
+# A. Basics
+#
+create procedure p1()
+begin
+ prepare stmt from "select 1";
+ execute stmt;
+ execute stmt;
+ execute stmt;
+ deallocate prepare stmt;
+end|
+call p1()|
+call p1()|
+call p1()|
+drop procedure p1|
+#
+# B. Recursion. Recusion is disabled in SP, and recursive use of PS is not
+# possible as well.
+#
+create procedure p1()
+begin
+ execute stmt;
+end|
+prepare stmt from "call p1()"|
+--error ER_PS_NO_RECURSION
+execute stmt|
+--error ER_PS_NO_RECURSION
+execute stmt|
+--error ER_PS_NO_RECURSION
+execute stmt|
+--error ER_SP_NO_RECURSION
+call p1()|
+--error ER_SP_NO_RECURSION
+call p1()|
+--error ER_SP_NO_RECURSION
+call p1()|
+drop procedure p1|
+#
+# C. Create/drop a stored procedure in Dynamic SQL.
+# One cannot create stored procedure from a stored procedure because of
+# the way MySQL SP cache works: it's important that this limitation is not
+# possible to circumvent by means of Dynamic SQL.
+#
+create procedure p1()
+begin
+ prepare stmt from "create procedure p2() begin select 1; end";
+ execute stmt;
+ deallocate prepare stmt;
+end|
+--error ER_UNSUPPORTED_PS
+call p1()|
+--error ER_UNSUPPORTED_PS
+call p1()|
+drop procedure p1|
+create procedure p1()
+begin
+ prepare stmt from "drop procedure p2";
+ execute stmt;
+ deallocate prepare stmt;
+end|
+--error ER_UNSUPPORTED_PS
+call p1()|
+--error ER_UNSUPPORTED_PS
+call p1()|
+drop procedure p1|
+#
+# D. Create/Drop a table (a DDL that issues a commit) in Dynamic SQL.
+# (should work ok).
+#
+create procedure p1()
+begin
+ prepare stmt_drop from "drop table if exists t1";
+ execute stmt_drop;
+ prepare stmt from "create table t1 (a int)";
+ execute stmt;
+ insert into t1 (a) values (1);
+ select * from t1;
+ deallocate prepare stmt;
+ deallocate prepare stmt_drop;
+end|
+call p1()|
+call p1()|
+drop procedure p1|
+#
+# A more real example (a case similar to submitted by 24/7).
+#
+create procedure p1()
+begin
+ set @tab_name=concat("tab_", replace(curdate(), '-', '_'));
+ set @drop_sql=concat("drop table if exists ", @tab_name);
+ set @create_sql=concat("create table ", @tab_name, " (a int)");
+ set @insert_sql=concat("insert into ", @tab_name, " values (1), (2), (3)");
+ set @select_sql=concat("select * from ", @tab_name);
+ select @tab_name;
+ select @drop_sql;
+ select @create_sql;
+ select @insert_sql;
+ select @select_sql;
+ prepare stmt_drop from @drop_sql;
+ execute stmt_drop;
+ prepare stmt from @create_sql;
+ execute stmt;
+ prepare stmt from @insert_sql;
+ execute stmt;
+ prepare stmt from @select_sql;
+ execute stmt;
+ execute stmt_drop;
+ deallocate prepare stmt;
+ deallocate prepare stmt_drop;
+end|
+--disable_result_log
+call p1()|
+call p1()|
+--enable_result_log
+drop procedure p1|
+#
+# E. Calling a stored procedure with Dynamic SQL
+# from a stored function (currently disabled).
+#
+create procedure p1()
+begin
+ prepare stmt_drop from "drop table if exists t1";
+ execute stmt_drop;
+ prepare stmt from "create table t1 (a int)";
+ execute stmt;
+ deallocate prepare stmt;
+ deallocate prepare stmt_drop;
+end|
+--disable_warnings
+drop function if exists f1|
+--enable_warnings
+create function f1(a int) returns int
+begin
+ call p1();
+ return 1;
+end|
+
+# Every stored procedure that contains Dynamic SQL is marked as
+# such. Stored procedures that contain Dynamic SQL are not
+# allowed in a stored function or trigger, and here we get the
+# corresponding error message.
+
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+select f1(0)|
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+select f1(f1(0))|
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+select f1(f1(f1(0)))|
+drop function f1|
+drop procedure p1|
+#
+# F. Rollback and cleanup lists management in Dynamic SQL.
+#
+create procedure p1()
+begin
+ drop table if exists t1;
+ create table t1 (id integer not null primary key,
+ name varchar(20) not null);
+ insert into t1 (id, name) values (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+ prepare stmt from "select name from t1";
+ execute stmt;
+ select name from t1;
+ execute stmt;
+ prepare stmt from
+ "select name from t1 where name=(select name from t1 where id=2)";
+ execute stmt;
+ select name from t1 where name=(select name from t1 where id=2);
+ execute stmt;
+end|
+call p1()|
+call p1()|
+drop procedure p1|
+#
+# H. Executing a statement prepared externally in SP.
+#
+prepare stmt from "select * from t1"|
+create procedure p1()
+begin
+ execute stmt;
+ deallocate prepare stmt;
+end|
+call p1()|
+--error ER_UNKNOWN_STMT_HANDLER
+call p1()|
+drop procedure p1|
+#
+# I. Use of an SP variable in Dynamic SQL is not possible and
+# this limitation is necessary for correct binary logging: prepared
+# statements do not substitute SP variables with their values for binlog, so
+# SP variables must be not accessible in Dynamic SQL.
+#
+create procedure p1()
+begin
+ declare a char(10);
+ set a="sp-variable";
+ set @a="mysql-variable";
+ prepare stmt from "select 'dynamic sql:', @a, a";
+ execute stmt;
+end|
+--error ER_BAD_FIELD_ERROR
+call p1()|
+--error ER_BAD_FIELD_ERROR
+call p1()|
+drop procedure p1|
+#
+# J. Use of placeholders in Dynamic SQL.
+#
+create procedure p1()
+begin
+ prepare stmt from 'select ? as a';
+ execute stmt using @a;
+end|
+set @a=1|
+call p1()|
+call p1()|
+drop procedure p1|
+#
+# K. Use of continue handlers with Dynamic SQL.
+#
+drop table if exists t1|
+create table t1 (id integer primary key auto_increment,
+ stmt_text char(35), status varchar(20))|
+insert into t1 (stmt_text) values
+ ("select 1"), ("flush tables"), ("handler t1 open as ha"),
+ ("analyze table t1"), ("check table t1"), ("checksum table t1"),
+ ("check table t1"), ("optimize table t1"), ("repair table t1"),
+ ("describe extended select * from t1"),
+ ("help help"), ("show databases"), ("show tables"),
+ ("show table status"), ("show open tables"), ("show storage engines"),
+ ("insert into t1 (id) values (1)"), ("update t1 set status=''"),
+ ("delete from t1"), ("truncate t1"), ("call p1()"), ("foo bar")|
+create procedure p1()
+begin
+ declare v_stmt_text varchar(255);
+ declare v_id integer;
+ declare done int default 0;
+ declare c cursor for select id, stmt_text from t1;
+ declare continue handler for 1295 -- ER_UNSUPPORTED_PS
+ set @status='not supported';
+ declare continue handler for 1064 -- ER_SYNTAX_ERROR
+ set @status='syntax error';
+ declare continue handler for sqlstate '02000' set done = 1;
+
+ prepare update_stmt from "update t1 set status=? where id=?";
+ open c;
+ repeat
+ if not done then
+ fetch c into v_id, v_stmt_text;
+ set @id=v_id, @stmt_text=v_stmt_text;
+ set @status="supported";
+ prepare stmt from @stmt_text;
+ execute update_stmt using @status, @id;
+ end if;
+ until done end repeat;
+ deallocate prepare update_stmt;
+end|
+call p1()|
+select * from t1|
+drop procedure p1|
+drop table t1|
+#
+# Bug#7115 "Prepared Statements: packet error if execution within stored
+# procedure".
+#
+prepare stmt from 'select 1'|
+create procedure p1() execute stmt|
+call p1()|
+call p1()|
+drop procedure p1|
+#
+# Bug#10975 "Prepared statements: crash if function deallocates"
+# Check that a prepared statement that is currently in use
+# can't be deallocated.
+#
+# a) Prepared statements and stored procedure cache:
+#
+# TODO: add when the corresponding bug (Bug #12093 "SP not found on second
+# PS execution if another thread drops other SP in between") is fixed.
+#
+# b) attempt to deallocate a prepared statement that is being executed
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+create function f1() returns int
+begin
+ deallocate prepare stmt;
+ return 1;
+end|
+
+# b)-2 a crash (#1) spotted by Sergey Petrunia during code review
+create procedure p1()
+begin
+ prepare stmt from 'select 1 A';
+ execute stmt;
+end|
+prepare stmt from 'call p1()'|
+--error ER_PS_NO_RECURSION
+execute stmt|
+--error ER_PS_NO_RECURSION
+execute stmt|
+drop procedure p1|
+
+#
+# Bug#10605 "Stored procedure with multiple SQL prepared statements
+# disconnects client"
+#
+--disable_warnings
+drop table if exists t1, t2|
+--enable_warnings
+create procedure p1 (a int) language sql deterministic
+begin
+ declare rsql varchar(100);
+ drop table if exists t1, t2;
+ set @rsql= "create table t1 (a int)";
+ select @rsql;
+ prepare pst from @rsql;
+ execute pst;
+ set @rsql= null;
+ set @rsql= "create table t2 (a int)";
+ select @rsql;
+ prepare pst from @rsql;
+ execute pst;
+ drop table if exists t1, t2;
+end|
+set @a:=0|
+call p1(@a)|
+select @a|
+call p1(@a)|
+select @a|
+drop procedure if exists p1|
+
+# End of the test
+delimiter ;|
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
new file mode 100644
index 00000000000..40f59f3f124
--- /dev/null
+++ b/mysql-test/t/sp-error.test
@@ -0,0 +1,1197 @@
+#
+# Stored PROCEDURE error tests
+#
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+# Make sure we don't have any procedures left.
+delete from mysql.proc;
+
+delimiter |;
+
+# This should give three syntax errors (sometimes crashed; bug #643)
+# (Unfortunately, this is not a 100% test, on some platforms this
+# passed despite the bug.)
+--error 1064
+create procedure syntaxerror(t int)|
+--error 1064
+create procedure syntaxerror(t int)|
+--error 1064
+create procedure syntaxerror(t int)|
+
+# Check that we get the right error, i.e. UDF declaration parses correctly,
+# but foo.so doesn't exist.
+# This generates an error message containing a misleading errno which
+# might vary between systems (it usually doesn't have anything to do with
+# the actual failing dlopen()).
+#--error 1126
+#create function foo returns real soname "foo.so"|
+
+
+--disable_warnings
+drop table if exists t3|
+--enable_warnings
+create table t3 ( x int )|
+insert into t3 values (2), (3)|
+
+create procedure bad_into(out param int)
+ select x from t3 into param|
+
+--error 1172
+call bad_into(@x)|
+
+drop procedure bad_into|
+drop table t3|
+
+
+create procedure proc1()
+ set @x = 42|
+
+create function func1() returns int
+ return 42|
+
+# Can't create recursively
+--error 1303
+create procedure foo()
+ create procedure bar() set @x=3|
+--error 1303
+create procedure foo()
+ create function bar() returns double return 2.3|
+
+# Already exists
+--error 1304
+create procedure proc1()
+ set @x = 42|
+--error 1304
+create function func1() returns int
+ return 42|
+
+drop procedure proc1|
+drop function func1|
+
+# Does not exist
+--error 1305
+alter procedure foo|
+--error 1305
+alter function foo|
+--error 1305
+drop procedure foo|
+--error 1305
+drop function foo|
+--error 1305
+call foo()|
+drop procedure if exists foo|
+--error 1305
+show create procedure foo|
+--error 1305
+show create function foo|
+
+# LEAVE/ITERATE with no match
+--error 1308
+create procedure foo()
+foo: loop
+ leave bar;
+end loop|
+--error 1308
+create procedure foo()
+foo: loop
+ iterate bar;
+end loop|
+--error 1308
+create procedure foo()
+foo: begin
+ iterate foo;
+end|
+
+# Redefining label
+--error 1309
+create procedure foo()
+foo: loop
+ foo: loop
+ set @x=2;
+ end loop foo;
+end loop foo|
+
+# End label mismatch
+--error 1310
+create procedure foo()
+foo: loop
+ set @x=2;
+end loop bar|
+
+# RETURN in FUNCTION only
+--error 1313
+create procedure foo()
+ return 42|
+
+# Wrong number of arguments
+create procedure p(x int)
+ set @x = x|
+create function f(x int) returns int
+ return x+42|
+
+--error 1318
+call p()|
+--error 1318
+call p(1, 2)|
+--error 1318
+select f()|
+--error 1318
+select f(1, 2)|
+
+drop procedure p|
+drop function f|
+
+--error 1319
+create procedure p(val int, out res int)
+begin
+ declare x int default 0;
+ declare continue handler for foo set x = 1;
+
+ insert into test.t1 values (val);
+ if (x) then
+ set res = 0;
+ else
+ set res = 1;
+ end if;
+end|
+
+--error 1319
+create procedure p(val int, out res int)
+begin
+ declare x int default 0;
+ declare foo condition for 1146;
+ declare continue handler for bar set x = 1;
+
+ insert into test.t1 values (val);
+ if (x) then
+ set res = 0;
+ else
+ set res = 1;
+ end if;
+end|
+
+--error 1320
+create function f(val int) returns int
+begin
+ declare x int;
+
+ set x = val+3;
+end|
+
+create function f(val int) returns int
+begin
+ declare x int;
+
+ set x = val+3;
+ if x < 4 then
+ return x;
+ end if;
+end|
+
+--error 1321
+select f(10)|
+
+drop function f|
+
+--error 1322
+create procedure p()
+begin
+ declare c cursor for insert into test.t1 values ("foo", 42);
+
+ open c;
+ close c;
+end|
+
+--error 1323
+create procedure p()
+begin
+ declare x int;
+ declare c cursor for select * into x from test.t limit 1;
+
+ open c;
+ close c;
+end|
+
+--error 1324
+create procedure p()
+begin
+ declare c cursor for select * from test.t;
+
+ open cc;
+ close c;
+end|
+
+--disable_warnings
+drop table if exists t1|
+--enable_warnings
+create table t1 (val int)|
+
+create procedure p()
+begin
+ declare c cursor for select * from test.t1;
+
+ open c;
+ open c;
+ close c;
+end|
+--error 1325
+call p()|
+drop procedure p|
+
+create procedure p()
+begin
+ declare c cursor for select * from test.t1;
+
+ open c;
+ close c;
+ close c;
+end|
+--error 1326
+call p()|
+drop procedure p|
+
+--error 1305
+alter procedure bar3 sql security invoker|
+
+drop table t1|
+
+--disable_warnings
+drop table if exists t1|
+--enable_warnings
+create table t1 (val int, x float)|
+insert into t1 values (42, 3.1), (19, 1.2)|
+
+--error 1327
+create procedure p()
+begin
+ declare x int;
+ declare c cursor for select * from t1;
+
+ open c;
+ fetch c into x, y;
+ close c;
+end|
+
+create procedure p()
+begin
+ declare x int;
+ declare c cursor for select * from t1;
+
+ open c;
+ fetch c into x;
+ close c;
+end|
+--error 1328
+call p()|
+drop procedure p|
+
+create procedure p()
+begin
+ declare x int;
+ declare y float;
+ declare z int;
+ declare c cursor for select * from t1;
+
+ open c;
+ fetch c into x, y, z;
+ close c;
+end|
+--error 1328
+call p()|
+drop procedure p|
+
+--error 1330
+create procedure p(in x int, x char(10))
+begin
+end|
+--error 1330
+create function p(x int, x char(10))
+begin
+end|
+
+--error 1331
+create procedure p()
+begin
+ declare x float;
+ declare x int;
+end|
+
+--error 1332
+create procedure p()
+begin
+ declare c condition for 1064;
+ declare c condition for 1065;
+end|
+
+--error 1333
+create procedure p()
+begin
+ declare c cursor for select * from t1;
+ declare c cursor for select field from t1;
+end|
+
+# USE is not allowed
+--error ER_SP_BADSTATEMENT
+create procedure u()
+ use sptmp|
+
+# Enforced standard order of declarations
+--error 1337
+create procedure p()
+begin
+ declare c cursor for select * from t1;
+ declare x int;
+end|
+--error 1337
+create procedure p()
+begin
+ declare x int;
+ declare continue handler for sqlstate '42S99' set x = 1;
+ declare foo condition for sqlstate '42S99';
+end|
+
+--error 1338
+create procedure p()
+begin
+ declare x int;
+ declare continue handler for sqlstate '42S99' set x = 1;
+ declare c cursor for select * from t1;
+end|
+
+# Check in and inout arguments.
+--disable_warnings
+drop procedure if exists p|
+--enable_warnings
+create procedure p(in x int, inout y int, out z int)
+begin
+ set y = x+y;
+ set z = x+y;
+end|
+
+set @tmp_x = 42|
+set @tmp_y = 3|
+set @tmp_z = 0|
+# For reference: this is ok
+call p(@tmp_x, @tmp_y, @tmp_z)|
+select @tmp_x, @tmp_y, @tmp_z|
+
+--error ER_SP_NOT_VAR_ARG
+call p(42, 43, @tmp_z)|
+--error ER_SP_NOT_VAR_ARG
+call p(42, @tmp_y, 43)|
+
+drop procedure p|
+
+
+#
+# Let us test that we can access mysql.proc table for routines
+# definitions lookup without locking it explicitly.
+#
+create procedure p() begin end|
+lock table t1 read|
+# This should succeed
+call p()|
+unlock tables|
+drop procedure p|
+# Let us check restrictions which this ability puts on mysql.proc locking.
+--error ER_WRONG_LOCK_OF_SYSTEM_TABLE
+lock tables t1 read, mysql.proc write|
+--error ER_WRONG_LOCK_OF_SYSTEM_TABLE
+lock tables mysql.proc write, mysql.user write|
+# Locking for read should be OK
+lock tables t1 read, mysql.proc read|
+unlock tables|
+# You also should be able lock only mysql.proc for write
+lock tables mysql.proc write|
+unlock tables|
+
+
+#
+# Check that in functions we don't allow to update tables which
+# are used by statements which invoke these functions.
+#
+--disable_warnings
+drop function if exists f1|
+--enable_warnings
+create function f1(i int) returns int
+begin
+ insert into t1 (val) values (i);
+ return 0;
+end|
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+select val, f1(val) from t1|
+# Table alias should not matter
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+select val, f1(val) from t1 as tab|
+select * from t1|
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+update t1 set val= f1(val)|
+select * from t1|
+# But this should be OK
+select f1(17)|
+select * from t1|
+# Cleanup
+delete from t1 where val= 17|
+drop function f1|
+
+
+#
+# BUG#1965
+#
+create procedure bug1965()
+begin
+ declare c cursor for select val from t1 order by valname;
+ open c;
+ close c;
+end|
+
+--error 1054
+call bug1965()|
+drop procedure bug1965|
+
+#
+# BUG#1966
+#
+--error 1327
+select 1 into a|
+
+#
+# BUG#1653
+#
+--disable_warnings
+drop table if exists t3|
+--enable_warnings
+create table t3 (column_1_0 int)|
+
+create procedure bug1653()
+ update t3 set column_1 = 0|
+
+--error 1054
+call bug1653()|
+drop table t3|
+create table t3 (column_1 int)|
+call bug1653()|
+
+drop procedure bug1653|
+drop table t3|
+
+#
+# BUG#2259
+#
+# Note: When this bug existed, it did not necessarily cause a crash
+# in all builds, but valgrind did give warnings.
+create procedure bug2259()
+begin
+ declare v1 int;
+ declare c1 cursor for select s1 from t1;
+
+ fetch c1 into v1;
+end|
+
+--error 1326
+call bug2259()|
+drop procedure bug2259|
+
+#
+# BUG#2272
+#
+create procedure bug2272()
+begin
+ declare v int;
+
+ update t1 set v = 42;
+end|
+
+insert into t1 values (666, 51.3)|
+--error 1054
+call bug2272()|
+delete from t1|
+drop procedure bug2272|
+
+#
+# BUG#2329
+#
+create procedure bug2329_1()
+begin
+ declare v int;
+
+ insert into t1 (v) values (5);
+end|
+
+create procedure bug2329_2()
+begin
+ declare v int;
+
+ replace t1 set v = 5;
+end|
+
+--error 1054
+call bug2329_1()|
+--error 1054
+call bug2329_2()|
+drop procedure bug2329_1|
+drop procedure bug2329_2|
+
+#
+# BUG#3287
+#
+create function bug3287() returns int
+begin
+ declare v int default null;
+
+ case
+ when v is not null then return 1;
+ end case;
+ return 2;
+end|
+--error 1339
+select bug3287()|
+drop function bug3287|
+
+create procedure bug3287(x int)
+case x
+when 0 then
+ insert into test.t1 values (x, 0.1);
+when 1 then
+ insert into test.t1 values (x, 1.1);
+end case|
+--error 1339
+call bug3287(2)|
+drop procedure bug3287|
+
+#
+# BUG#3297
+#
+--disable_warnings
+drop table if exists t3|
+--enable_warnings
+create table t3 (s1 int, primary key (s1))|
+insert into t3 values (5),(6)|
+
+create procedure bug3279(out y int)
+begin
+ declare x int default 0;
+ begin
+ declare exit handler for sqlexception set x = x+1;
+ insert into t3 values (5);
+ end;
+ if x < 2 then
+ set x = x+1;
+ insert into t3 values (6);
+ end if;
+ set y = x;
+end|
+
+set @x = 0|
+--error 1062
+call bug3279(@x)|
+select @x|
+drop procedure bug3279|
+drop table t3|
+
+#
+# BUG#3339
+#
+--error 1049
+create procedure nodb.bug3339() begin end|
+
+#
+# BUG#2653
+#
+create procedure bug2653_1(a int, out b int)
+ set b = aa|
+
+create procedure bug2653_2(a int, out b int)
+begin
+ if aa < 0 then
+ set b = - a;
+ else
+ set b = a;
+ end if;
+end|
+
+--error 1054
+call bug2653_1(1, @b)|
+--error 1054
+call bug2653_2(2, @b)|
+
+drop procedure bug2653_1|
+drop procedure bug2653_2|
+
+#
+# BUG#4344
+#
+--error 1357
+create procedure bug4344() drop procedure bug4344|
+--error 1357
+create procedure bug4344() drop function bug4344|
+
+#
+# BUG#3294: Stored procedure crash if table dropped before use
+# (Actually, when an error occurs within an error handler.)
+--disable_warnings
+drop procedure if exists bug3294|
+--enable_warnings
+create procedure bug3294()
+begin
+ declare continue handler for sqlexception drop table t5;
+ drop table t5;
+ drop table t5;
+end|
+
+create table t5 (x int)|
+--error 1051
+call bug3294()|
+drop procedure bug3294|
+
+#
+# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
+#
+--disable_warnings
+drop procedure if exists bug6807|
+--enable_warnings
+create procedure bug6807()
+begin
+ declare id int;
+
+ set id = connection_id();
+ kill query id;
+ select 'Not reached';
+end|
+
+--error 1317
+call bug6807()|
+--error 1317
+call bug6807()|
+
+drop procedure bug6807|
+
+#
+# BUG#876: Stored Procedures: Invalid SQLSTATE is allowed in
+# a DECLARE ? HANDLER FOR stmt.
+#
+--disable_warnings
+drop procedure if exists bug8776_1|
+drop procedure if exists bug8776_2|
+drop procedure if exists bug8776_3|
+drop procedure if exists bug8776_4|
+--enable_warnings
+--error ER_SP_BAD_SQLSTATE
+create procedure bug8776_1()
+begin
+ declare continue handler for sqlstate '42S0200test' begin end;
+ begin end;
+end|
+
+--error ER_SP_BAD_SQLSTATE
+create procedure bug8776_2()
+begin
+ declare continue handler for sqlstate '4200' begin end;
+ begin end;
+end|
+
+--error ER_SP_BAD_SQLSTATE
+create procedure bug8776_3()
+begin
+ declare continue handler for sqlstate '420000' begin end;
+ begin end;
+end|
+
+--error ER_SP_BAD_SQLSTATE
+create procedure bug8776_4()
+begin
+ declare continue handler for sqlstate '42x00' begin end;
+ begin end;
+end|
+
+
+#
+# BUG#6600: Stored procedure crash after repeated calls with check table
+#
+--error ER_SP_BADSTATEMENT
+create procedure bug6600()
+ check table t1|
+
+# Check these two as well, while we're at it. (Although it isn't really
+# related to the bug report, but to the fix.)
+--error ER_SP_BADSTATEMENT
+create procedure bug6600()
+ lock table t1 read|
+--error ER_SP_BADSTATEMENT
+create procedure bug6600()
+ unlock table t1|
+
+#
+# BUG#9566: explicit LOCK TABLE and store procedures result in illegal state
+#
+# We should not think that mysql.proc table does not exist if we are unable
+# to open it under LOCK TABLE or in prelocked mode.
+#
+--disable_warnings
+drop procedure if exists bug9566|
+--enable_warnings
+create procedure bug9566()
+begin
+ select * from t1;
+end|
+lock table t1 read|
+# This should fail since we forgot to lock mysql.proc for writing
+# explicitly, and we can't open mysql.proc for _writing_ if there
+# are locked tables.
+--error 1100
+alter procedure bug9566 comment 'Some comment'|
+unlock tables|
+# This should succeed
+drop procedure bug9566|
+
+
+#
+# BUG#7299: Stored procedures: exception handler catches not-found conditions
+#
+--disable_warnings
+drop procedure if exists bug7299|
+--enable_warnings
+create procedure bug7299()
+begin
+ declare v int;
+ declare c cursor for select val from t1;
+ declare exit handler for sqlexception select 'Error!';
+
+ open c;
+ fetch c into v;
+end|
+
+delete from t1|
+--error ER_SP_FETCH_NO_DATA
+call bug7299()|
+drop procedure bug7299|
+
+
+#
+# BUG#9073: Able to declare two handlers for same condition in same scope
+#
+--error ER_SP_DUP_HANDLER
+create procedure bug9073()
+begin
+ declare continue handler for sqlexception select 1;
+ declare continue handler for sqlexception select 2;
+end|
+--error ER_SP_DUP_HANDLER
+create procedure bug9073()
+begin
+ declare condname1 condition for 1234;
+ declare continue handler for condname1 select 1;
+ declare exit handler for condname1 select 2;
+end|
+--error ER_SP_DUP_HANDLER
+create procedure bug9073()
+begin
+ declare condname1 condition for sqlstate '42000';
+ declare condname2 condition for sqlstate '42000';
+ declare exit handler for condname1 select 1;
+ declare continue handler for condname2 select 2;
+end|
+--error ER_SP_DUP_HANDLER
+create procedure bug9073()
+begin
+ declare condname1 condition for sqlstate '42000';
+ declare exit handler for condname1 select 1;
+ declare exit handler for sqlstate '42000' select 2;
+end|
+
+# This should still work.
+--disable_warnings
+drop procedure if exists bug9073|
+--enable_warnings
+create procedure bug9073()
+begin
+ declare condname1 condition for sqlstate '42000';
+ declare continue handler for condname1 select 1;
+ begin
+ declare exit handler for sqlstate '42000' select 2;
+ begin
+ declare continue handler for sqlstate '42000' select 3;
+ end;
+ end;
+end|
+drop procedure bug9073|
+
+
+#
+# BUG#7047: Stored procedure crash if alter procedure
+#
+--error ER_SP_NO_DROP_SP
+create procedure bug7047()
+ alter procedure bug7047|
+--error ER_SP_NO_DROP_SP
+create function bug7047() returns int
+begin
+ alter function bug7047;
+ return 0;
+end|
+
+
+#
+# BUG#8408: Stored procedure crash if function contains SHOW
+# BUG#9058: Stored Procedures: Crash if function included SELECT
+#
+
+# Some things are caught when parsing
+--error ER_SP_NO_RETSET
+create function bug8408() returns int
+begin
+ select * from t1;
+ return 0;
+end|
+--error ER_SP_NO_RETSET
+create function bug8408() returns int
+begin
+ show warnings;
+ return 0;
+end|
+--error ER_SP_NO_RETSET
+create function bug8408(a int) returns int
+begin
+ declare b int;
+ select b;
+ return b;
+end|
+
+--disable_warnings
+drop function if exists bug8408_f|
+drop procedure if exists bug8408_p|
+--enable_warnings
+
+# Some things must be caught at invokation time
+create function bug8408_f() returns int
+begin
+ call bug8408_p();
+ return 0;
+end|
+create procedure bug8408_p()
+ select * from t1|
+
+call bug8408_p()|
+--error ER_SP_NO_RETSET
+select bug8408_f()|
+
+drop procedure bug8408_p|
+drop function bug8408_f|
+
+# But this is ok
+create function bug8408() returns int
+begin
+ declare n int default 0;
+ select count(*) into n from t1;
+ return n;
+end|
+
+insert into t1 value (2, 2.7), (3, 3.14), (7, 7.0)|
+select *,bug8408() from t1|
+
+drop function bug8408|
+delete from t1|
+
+
+#
+# BUG#10537: Server crashes while loading data file into table through
+# procedure.
+# Disable load until it's PS and SP safe
+--disable_warnings
+drop procedure if exists bug10537|
+--enable_warnings
+--error ER_SP_BADSTATEMENT
+create procedure bug10537()
+ load data local infile '/tmp/somefile' into table t1|
+
+
+#
+# BUG#8409: Stored procedure crash if function contains FLUSH
+#
+--disable_warnings
+drop function if exists bug8409|
+--enable_warnings
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+create function bug8409()
+ returns int
+begin
+ flush tables;
+ return 5;
+end|
+
+
+#
+# BUG#9529: Stored Procedures: No Warning on truncation of procedure name
+# during creation.
+# Note: When using utf8 for mysql.proc, this limit is much higher than before
+--error ER_TOO_LONG_IDENT
+create procedure bug9529_90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123()
+begin
+end|
+
+
+#
+# BUG#10969: Stored procedures: crash if default() function
+#
+--disable_warnings
+drop procedure if exists bug10969|
+--enable_warnings
+--error ER_WRONG_COLUMN_NAME
+create procedure bug10969()
+begin
+ declare s1 int default 0;
+ select default(s1) from t30;
+end|
+
+# This should work
+create procedure bug10969()
+begin
+ declare s1 int default 0;
+ select default(t30.s1) from t30;
+end|
+
+drop procedure bug10969|
+
+
+drop table t1|
+
+delimiter ;|
+
+# BUG#9814: Closing a cursor that is not open
+create table t1(f1 int);
+create table t2(f1 int);
+
+delimiter |;
+CREATE PROCEDURE SP001()
+P1: BEGIN
+ DECLARE ENDTABLE INT DEFAULT 0;
+ DECLARE TEMP_NUM INT;
+ DECLARE TEMP_SUM INT;
+ DECLARE C1 CURSOR FOR SELECT F1 FROM t1;
+ DECLARE C2 CURSOR FOR SELECT F1 FROM t2;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET ENDTABLE = 1;
+
+ SET ENDTABLE=0;
+ SET TEMP_SUM=0;
+ SET TEMP_NUM=0;
+
+ OPEN C1;
+
+ FETCH C1 INTO TEMP_NUM;
+ WHILE ENDTABLE = 0 DO
+ SET TEMP_SUM=TEMP_NUM+TEMP_SUM;
+ FETCH C1 INTO TEMP_NUM;
+ END WHILE;
+ SELECT TEMP_SUM;
+ CLOSE C1;
+ CLOSE C1;
+ SELECT 'end of proc';
+END P1|
+delimiter ;|
+call SP001();
+drop procedure SP001;
+drop table t1, t2;
+
+# Bug #11394 "Recursion in SP crash server" and bug #11600 "Stored
+# procedures: crash with function calling itself".
+# We have to disable recursion since in many cases LEX and many
+# Item's can't be used in reentrant way nowdays.
+delimiter |;
+--disable_warnings
+drop function if exists bug11394|
+drop function if exists bug11394_1|
+drop function if exists bug11394_2|
+drop procedure if exists bug11394|
+--enable_warnings
+create function bug11394(i int) returns int
+begin
+ if i <= 0 then
+ return 0;
+ else
+ return (i in (100, 200, bug11394(i-1), 400));
+ end if;
+end|
+# If we allow recursive functions without additional modifications
+# this will crash server since Item for "IN" is not reenterable.
+--error 1424
+select bug11394(2)|
+drop function bug11394|
+create function bug11394_1(i int) returns int
+begin
+ if i <= 0 then
+ return 0;
+ else
+ return (select bug11394_1(i-1));
+ end if;
+end|
+# The following statement will crash because some LEX members responsible
+# for selects cannot be used in reentrant fashion.
+--error 1424
+select bug11394_1(2)|
+drop function bug11394_1|
+# Note that the following should be allowed since it does not contains
+# recursion
+create function bug11394_2(i int) returns int return i|
+select bug11394_2(bug11394_2(10))|
+drop function bug11394_2|
+create procedure bug11394(i int, j int)
+begin
+ if i > 0 then
+ call bug11394(i - 1,(select 1));
+ end if;
+end|
+# Again if we allow recursion for stored procedures (without
+# additional efforts) the following statement will crash the server.
+--error 1424
+call bug11394(2, 1)|
+drop procedure bug11394|
+delimiter ;|
+
+
+#
+# BUG 12490 (Packets out of order if calling HELP CONTENTS from Stored Procedure)
+#
+--error 1314
+CREATE PROCEDURE BUG_12490() HELP CONTENTS;
+--error 1314
+CREATE FUNCTION BUG_12490() RETURNS INT HELP CONTENTS;
+CREATE TABLE t_bug_12490(a int);
+--error 1314
+CREATE TRIGGER BUG_12490 BEFORE UPDATE ON t_bug_12490 FOR EACH ROW HELP CONTENTS;
+DROP TABLE t_bug_12490;
+
+#
+# Bug#11834 "Re-execution of prepared statement with dropped function
+# crashes server". Also tests handling of prepared stmts which use
+# stored functions but does not require prelocking.
+#
+--disable_warnings
+drop function if exists bug11834_1;
+drop function if exists bug11834_2;
+--enable_warnings
+create function bug11834_1() returns int return 10;
+create function bug11834_2() returns int return bug11834_1();
+prepare stmt from "select bug11834_2()";
+execute stmt;
+# Re-execution of statement should not crash server.
+execute stmt;
+drop function bug11834_1;
+# Attempt to execute statement should return proper error and
+# should not crash server.
+--error ER_SP_DOES_NOT_EXIST
+execute stmt;
+deallocate prepare stmt;
+drop function bug11834_2;
+
+#
+# Bug#12953 "Stored procedures: crash if OPTIMIZE TABLE in function"
+#
+delimiter |;
+--disable_warnings
+DROP FUNCTION IF EXISTS bug12953|
+--enable_warnings
+--error ER_SP_BADSTATEMENT
+CREATE FUNCTION bug12953() RETURNS INT
+BEGIN
+ OPTIMIZE TABLE t1;
+ RETURN 1;
+END|
+delimiter ;|
+
+#
+# Bug##12995 "Inside function "Table 't4' was not locked with LOCK TABLES"
+#
+delimiter |;
+--disable_warnings
+DROP FUNCTION IF EXISTS bug12995|
+--enable_warnings
+--error ER_SP_BADSTATEMENT
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+ HANDLER t1 OPEN;
+ RETURN 1;
+END|
+--error ER_SP_BADSTATEMENT
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+ HANDLER t1 READ FIRST;
+ RETURN 1;
+END|
+--error ER_SP_BADSTATEMENT
+CREATE FUNCTION bug12995() RETURNS INT
+BEGIN
+ HANDLER t1 CLOSE;
+ RETURN 1;
+END|
+--error 1305
+SELECT bug12995()|
+delimiter ;|
+
+
+#
+# BUG#12712: SET AUTOCOMMIT should fail within SP/functions/triggers
+#
+--disable_warnings
+drop procedure if exists bug12712;
+drop function if exists bug12712;
+--enable_warnings
+# Can...
+create procedure bug12712()
+ set session autocommit = 0;
+
+select @@autocommit;
+set @au = @@autocommit;
+call bug12712();
+select @@autocommit;
+set session autocommit = @au;
+
+delimiter |;
+create function bug12712()
+ returns int
+begin
+ call bug12712();
+ return 0;
+end|
+
+# Can't...
+--error ER_SP_CANT_SET_AUTOCOMMIT
+set @x = bug12712()|
+drop procedure bug12712|
+drop function bug12712|
+--error ER_SP_CANT_SET_AUTOCOMMIT
+create function bug12712()
+ returns int
+begin
+ set session autocommit = 0;
+ return 0;
+end|
+--error ER_SP_CANT_SET_AUTOCOMMIT
+create function bug12712()
+ returns int
+begin
+ set @@autocommit = 0;
+ return 0;
+end|
+--error ER_SP_CANT_SET_AUTOCOMMIT
+create function bug12712()
+ returns int
+begin
+ set local autocommit = 0;
+ return 0;
+end|
+delimiter ;|
+--error ER_SP_CANT_SET_AUTOCOMMIT
+create trigger bug12712
+ before insert on t1 for each row set session autocommit = 0;
+
+
+#
+# BUG#NNNN: New bug synopsis
+#
+#--disable_warnings
+#drop procedure if exists bugNNNN|
+#--enable_warnings
+#create procedure bugNNNN...
diff --git a/mysql-test/t/sp-goto.test b/mysql-test/t/sp-goto.test
new file mode 100644
index 00000000000..e770dd285ff
--- /dev/null
+++ b/mysql-test/t/sp-goto.test
@@ -0,0 +1,238 @@
+#
+# The non-standard GOTO, for compatibility
+#
+# QQQ The "label" syntax is temporary, it will (hopefully)
+# change to the more common "L:" syntax soon.
+# For the time being, this feature is disabled, until
+# the syntax (and some other known bugs) can be fixed.
+#
+# Test cases for bugs are added at the end. See template there.
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (
+ id char(16) not null default '',
+ data int not null
+);
+
+delimiter //;
+
+--disable_warnings
+drop procedure if exists goto1//
+--enable_warnings
+create procedure goto1()
+begin
+ declare y int;
+
+label a;
+ select * from t1;
+ select count(*) into y from t1;
+ if y > 2 then
+ goto b;
+ end if;
+ insert into t1 values ("j", y);
+ goto a;
+label b;
+end//
+
+call goto1()//
+drop procedure goto1//
+
+# With dummy handlers, just to test restore of contexts with jumps
+--disable_warnings
+drop procedure if exists goto2//
+--enable_warnings
+create procedure goto2(a int)
+begin
+ declare x int default 0;
+ declare continue handler for sqlstate '42S98' set x = 1;
+
+label a;
+ select * from t1;
+b:
+ while x < 2 do
+ begin
+ declare continue handler for sqlstate '42S99' set x = 2;
+
+ if a = 0 then
+ set x = x + 1;
+ iterate b;
+ elseif a = 1 then
+ leave b;
+ elseif a = 2 then
+ set a = 1;
+ goto a;
+ end if;
+ end;
+ end while b;
+
+ select * from t1;
+end//
+
+call goto2(0)//
+call goto2(1)//
+call goto2(2)//
+
+drop procedure goto2//
+delete from t1//
+
+# Check label visibility for some more cases. We don't call these.
+--disable_warnings
+drop procedure if exists goto3//
+--enable_warnings
+create procedure goto3()
+begin
+ label L1;
+ begin
+ end;
+ goto L1;
+end//
+drop procedure goto3//
+
+--disable_warnings
+drop procedure if exists goto4//
+--enable_warnings
+create procedure goto4()
+begin
+ begin
+ label lab1;
+ begin
+ goto lab1;
+ end;
+ end;
+end//
+drop procedure goto4//
+
+--disable_warnings
+drop procedure if exists goto5//
+--enable_warnings
+create procedure goto5()
+begin
+ begin
+ begin
+ goto lab1;
+ end;
+ label lab1;
+ end;
+end//
+drop procedure goto5//
+
+--disable_warnings
+drop procedure if exists goto6//
+--enable_warnings
+create procedure goto6()
+begin
+ label L1;
+ goto L5;
+ begin
+ label L2;
+ goto L1;
+ goto L5;
+ begin
+ label L3;
+ goto L1;
+ goto L2;
+ goto L3;
+ goto L4;
+ goto L5;
+ end;
+ goto L2;
+ goto L4;
+ label L4;
+ end;
+ label L5;
+ goto L1;
+end//
+drop procedure goto6//
+
+# Mismatching labels
+--error 1308
+create procedure foo()
+begin
+ goto foo;
+end//
+--error 1308
+create procedure foo()
+begin
+ begin
+ label foo;
+ end;
+ goto foo;
+end//
+--error 1308
+create procedure foo()
+begin
+ goto foo;
+ begin
+ label foo;
+ end;
+end//
+--error 1308
+create procedure foo()
+begin
+ begin
+ goto foo;
+ end;
+ begin
+ label foo;
+ end;
+end//
+--error 1308
+create procedure foo()
+begin
+ begin
+ label foo;
+ end;
+ begin
+ goto foo;
+ end;
+end//
+
+# No goto in a handler
+--error 1358
+create procedure p()
+begin
+ declare continue handler for sqlexception
+ begin
+ goto L1;
+ end;
+
+ select field from t1;
+ label L1;
+end//
+
+
+#
+# Test cases for old bugs
+#
+
+#
+# BUG#6898: Stored procedure crash if GOTO statements exist
+#
+--disable_warnings
+drop procedure if exists bug6898//
+--enable_warnings
+create procedure bug6898()
+begin
+ goto label1;
+ label label1;
+ begin end;
+ goto label1;
+end//
+drop procedure bug6898//
+
+#
+# BUG#NNNN: New bug synopsis
+#
+#--disable_warnings
+#drop procedure if exists bugNNNN//
+#--enable_warnings
+#create procedure bugNNNN...
+
+
+# Add bugs above this line. Use existing tables t1 and t2 when
+# practical, or create table t3, t4 etc temporarily (and drop them).
+delimiter ;//
+drop table t1;
diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test
new file mode 100644
index 00000000000..e5f35b19fa7
--- /dev/null
+++ b/mysql-test/t/sp-prelocking.test
@@ -0,0 +1,242 @@
+#
+# Tests of prelocking-free execution of stored procedures.
+# Currently two properties of prelocking-free SP execution are checked:
+# - It is possible to execute DDL statements in prelocking-free stored
+# procedure
+# - The same procedure can be called in prelocking-free mode and
+# in prelocked mode (from within a function).
+
+--disable_warnings
+drop database if exists mysqltest;
+drop table if exists t1, t2, t3, t4;
+drop procedure if exists sp1;
+drop procedure if exists sp2;
+drop procedure if exists sp3;
+drop procedure if exists sp4;
+drop function if exists f1;
+drop function if exists f2;
+drop function if exists f3;
+--enable_warnings
+
+# BUG#8072
+
+create database mysqltest;
+delimiter //;
+use mysqltest//
+create procedure sp1 ()
+begin
+ drop table if exists t1;
+ select 1 as "my-col";
+end;
+//
+delimiter ;//
+
+select database();
+call sp1();
+select database();
+
+use test;
+select database();
+call mysqltest.sp1();
+select database();
+
+drop procedure mysqltest.sp1;
+drop database mysqltest;
+
+# BUG#8766
+
+delimiter //;
+create procedure sp1()
+begin
+ create table t1 (a int);
+ insert into t1 values (10);
+end//
+
+create procedure sp2()
+begin
+ create table t2(a int);
+ insert into t2 values(1);
+ call sp1();
+end//
+
+create function f1() returns int
+begin
+ return (select max(a) from t1);
+end//
+
+create procedure sp3()
+begin
+ call sp1();
+ select 'func', f1();
+end//
+
+delimiter ;//
+
+call sp1();
+select 't1',a from t1;
+
+drop table t1;
+call sp2();
+select 't1',a from t1;
+select 't2',a from t2;
+drop table t1, t2;
+
+call sp3();
+select 't1',a from t1;
+
+drop table t1;
+
+drop procedure sp1;
+drop procedure sp2;
+drop procedure sp3;
+drop function f1;
+
+delimiter //;
+create procedure sp1()
+begin
+ create temporary table t2(a int);
+ insert into t2 select * from t1;
+end//
+
+create procedure sp2()
+begin
+ create temporary table t1 (a int);
+ insert into t1 values(1);
+ call sp1();
+ select 't1', a from t1;
+ select 't2', a from t2;
+ drop table t1;
+ drop table t2;
+end//
+
+delimiter ;//
+call sp2();
+
+drop procedure sp1;
+drop procedure sp2;
+
+# Miscelaneous tests
+create table t1 (a int);
+insert into t1 values(1),(2);
+create table t2 as select * from t1;
+create table t3 as select * from t1;
+create table t4 as select * from t1;
+delimiter //;
+create procedure sp1(a int)
+begin
+ select a;
+end //
+
+create function f1() returns int
+begin
+ return (select max(a) from t1);
+end //
+
+delimiter ;//
+
+CALL sp1(f1());
+
+#############
+delimiter //;
+create procedure sp2(a int)
+begin
+ select * from t3;
+ select a;
+end //
+
+create procedure sp3()
+begin
+ select * from t1;
+ call sp2(5);
+end //
+
+create procedure sp4()
+begin
+ select * from t2;
+ call sp3();
+end //
+
+delimiter ;//
+call sp4();
+
+drop procedure sp1;
+drop procedure sp2;
+drop procedure sp3;
+drop procedure sp4;
+drop function f1;
+
+# Test that prelocking state restoration works with cursors
+--disable_warnings
+drop view if exists v1;
+--enable_warnings
+delimiter //;
+
+create function f1(ab int) returns int
+begin
+ declare i int;
+ set i= (select max(a) from t1 where a < ab) ;
+ return i;
+end //
+
+create function f2(ab int) returns int
+begin
+ declare i int;
+ set i= (select max(a) from t2 where a < ab) ;
+ return i;
+end //
+
+create view v1 as
+ select t3.a as x, t4.a as y, f2(3) as z
+ from t3, t4 where t3.a = t4.a //
+
+create procedure sp1()
+begin
+ declare a int;
+ set a= (select f1(4) + count(*) A from t1, v1);
+end //
+
+
+create function f3() returns int
+begin
+ call sp1();
+ return 1;
+end //
+
+call sp1() //
+
+select f3() //
+select f3() //
+
+call sp1() //
+
+---------------
+drop procedure sp1//
+drop function f3//
+
+create procedure sp1()
+begin
+ declare x int;
+ declare c cursor for select f1(3) + count(*) from v1;
+ open c;
+ fetch c into x;
+end;//
+
+create function f3() returns int
+begin
+ call sp1();
+ return 1;
+end //
+
+call sp1() //
+call sp1() //
+
+select f3() //
+call sp1() //
+
+delimiter ;//
+drop table t1,t2,t3;
+drop function f1;
+drop function f2;
+drop function f3;
+drop procedure sp1;
+
diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test
new file mode 100644
index 00000000000..6f1332f80d5
--- /dev/null
+++ b/mysql-test/t/sp-security.test
@@ -0,0 +1,415 @@
+#
+# Testing SQL SECURITY of stored procedures
+#
+
+# Can't test with embedded server that doesn't support grants
+-- source include/not_embedded.inc
+
+connect (con1root,localhost,root,,);
+
+connection con1root;
+use test;
+
+# Create user user1 with no particular access rights
+grant usage on *.* to user1@localhost;
+flush privileges;
+
+--disable_warnings
+drop table if exists t1;
+drop database if exists db1_secret;
+--enable_warnings
+# Create our secret database
+create database db1_secret;
+
+# Can create a procedure in other db
+create procedure db1_secret.dummy() begin end;
+drop procedure db1_secret.dummy;
+
+use db1_secret;
+
+create table t1 ( u varchar(64), i int );
+
+# A test procedure and function
+create procedure stamp(i int)
+ insert into db1_secret.t1 values (user(), i);
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show procedure status like 'stamp';
+
+create function db() returns varchar(64) return database();
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show function status like 'db';
+
+# root can, of course
+call stamp(1);
+select * from t1;
+select db();
+
+grant execute on procedure db1_secret.stamp to user1@'%';
+grant execute on function db1_secret.db to user1@'%';
+grant execute on procedure db1_secret.stamp to ''@'%';
+grant execute on function db1_secret.db to ''@'%';
+
+connect (con2user1,localhost,user1,,);
+connect (con3anon,localhost,anon,,);
+
+
+#
+# User1 can
+#
+connection con2user1;
+
+# This should work...
+call db1_secret.stamp(2);
+select db1_secret.db();
+
+# ...but not this
+--error 1142
+select * from db1_secret.t1;
+
+# ...and not this
+--error 1044
+create procedure db1_secret.dummy() begin end;
+--error 1305
+drop procedure db1_secret.dummy;
+
+
+#
+# Anonymous can
+#
+connection con3anon;
+
+# This should work...
+call db1_secret.stamp(3);
+select db1_secret.db();
+
+# ...but not this
+--error 1142
+select * from db1_secret.t1;
+
+# ...and not this
+--error 1044
+create procedure db1_secret.dummy() begin end;
+--error 1305
+drop procedure db1_secret.dummy;
+
+
+#
+# Check it out
+#
+connection con1root;
+select * from t1;
+
+#
+# Change to invoker's rights
+#
+alter procedure stamp sql security invoker;
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show procedure status like 'stamp';
+
+alter function db sql security invoker;
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show function status like 'db';
+
+# root still can
+call stamp(4);
+select * from t1;
+select db();
+
+#
+# User1 cannot
+#
+connection con2user1;
+
+# This should not work
+--error 1044
+call db1_secret.stamp(5);
+--error 1044
+select db1_secret.db();
+
+#
+# Anonymous cannot
+#
+connection con3anon;
+
+# This should not work
+--error 1044
+call db1_secret.stamp(6);
+--error 1044
+select db1_secret.db();
+
+#
+# BUG#2777
+#
+
+connection con1root;
+--disable_warnings
+drop database if exists db2;
+--enable_warnings
+create database db2;
+
+use db2;
+
+create table t2 (s1 int);
+insert into t2 values (0);
+
+grant usage on db2.* to user1@localhost;
+grant select on db2.* to user1@localhost;
+grant usage on db2.* to user2@localhost;
+grant select,insert,update,delete,create routine on db2.* to user2@localhost;
+grant create routine on db2.* to user1@localhost;
+flush privileges;
+
+connection con2user1;
+use db2;
+
+create procedure p () insert into t2 values (1);
+
+# Check that this doesn't work.
+--error 1142
+call p();
+
+connect (con4user2,localhost,user2,,);
+
+connection con4user2;
+use db2;
+
+# This should not work, since p is executed with definer's (user1's) rights.
+--error 1370
+call p();
+select * from t2;
+
+create procedure q () insert into t2 values (2);
+
+call q();
+select * from t2;
+
+connection con1root;
+grant usage on procedure db2.q to user2@localhost with grant option;
+
+connection con4user2;
+grant execute on procedure db2.q to user1@localhost;
+
+connection con2user1;
+use db2;
+
+# This should work
+call q();
+select * from t2;
+
+
+#
+# BUG#6030: Stored procedure has no appropriate DROP privilege
+# (or ALTER for that matter)
+
+# still connection con2user1 in db2
+
+# This should work:
+alter procedure p modifies sql data;
+drop procedure p;
+
+# This should NOT work
+--error 1370
+alter procedure q modifies sql data;
+--error 1370
+drop procedure q;
+
+connection con1root;
+use db2;
+# But root always can
+alter procedure q modifies sql data;
+drop procedure q;
+
+
+# Clean up
+#Still connection con1root;
+disconnect con2user1;
+disconnect con3anon;
+disconnect con4user2;
+use test;
+select type,db,name from mysql.proc;
+drop database db1_secret;
+drop database db2;
+# Make sure the routines are gone
+select type,db,name from mysql.proc;
+# Get rid of the users
+delete from mysql.user where user='user1' or user='user2';
+# And any routine privileges
+delete from mysql.procs_priv where user='user1' or user='user2';
+
+#
+# Test the new security acls
+#
+grant usage on *.* to usera@localhost;
+grant usage on *.* to userb@localhost;
+grant usage on *.* to userc@localhost;
+create database sptest;
+create table t1 ( u varchar(64), i int );
+create procedure sptest.p1(i int) insert into test.t1 values (user(), i);
+grant insert on t1 to usera@localhost;
+grant execute on procedure sptest.p1 to usera@localhost;
+show grants for usera@localhost;
+grant execute on procedure sptest.p1 to userc@localhost with grant option;
+show grants for userc@localhost;
+
+connect (con2usera,localhost,usera,,);
+connect (con3userb,localhost,userb,,);
+connect (con4userc,localhost,userc,,);
+
+connection con2usera;
+call sptest.p1(1);
+--error 1370
+grant execute on procedure sptest.p1 to userb@localhost;
+--error 1370
+drop procedure sptest.p1;
+
+connection con3userb;
+--error 1370
+call sptest.p1(2);
+--error 1370
+grant execute on procedure sptest.p1 to userb@localhost;
+--error 1370
+drop procedure sptest.p1;
+
+connection con4userc;
+call sptest.p1(3);
+grant execute on procedure sptest.p1 to userb@localhost;
+--error 1370
+drop procedure sptest.p1;
+
+connection con3userb;
+call sptest.p1(4);
+--error 1370
+grant execute on procedure sptest.p1 to userb@localhost;
+--error 1370
+drop procedure sptest.p1;
+
+connection con1root;
+select * from t1;
+
+grant all privileges on procedure sptest.p1 to userc@localhost;
+show grants for userc@localhost;
+show grants for userb@localhost;
+
+connection con4userc;
+revoke all privileges on procedure sptest.p1 from userb@localhost;
+
+connection con1root;
+show grants for userb@localhost;
+
+#cleanup
+disconnect con4userc;
+disconnect con3userb;
+disconnect con2usera;
+use test;
+drop database sptest;
+delete from mysql.user where user='usera' or user='userb' or user='userc';
+delete from mysql.procs_priv where user='usera' or user='userb' or user='userc';
+
+#
+# BUG#9503: reseting correct parameters of thread after error in SP function
+#
+connect (root,localhost,root,,test);
+connection root;
+
+--disable_warnings
+drop function if exists bug_9503;
+--enable_warnings
+delimiter //;
+create database mysqltest//
+use mysqltest//
+create table t1 (s1 int)//
+grant select on t1 to user1@localhost//
+create function bug_9503 () returns int sql security invoker begin declare v int;
+select min(s1) into v from t1; return v; end//
+delimiter ;//
+
+connect (user1,localhost,user1,,test);
+connection user1;
+use mysqltest;
+-- error 1370
+select bug_9503();
+
+connection root;
+grant execute on function bug_9503 to user1@localhost;
+
+connection user1;
+do 1;
+use test;
+
+connection root;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost;
+drop function bug_9503;
+use test;
+drop database mysqltest;
+
+#
+# correct value from current_user() in function run from "security definer"
+# (BUG#7291)
+#
+connection con1root;
+use test;
+
+select current_user();
+select user();
+create procedure bug7291_0 () sql security invoker select current_user(), user();
+create procedure bug7291_1 () sql security definer call bug7291_0();
+create procedure bug7291_2 () sql security invoker call bug7291_0();
+grant execute on procedure bug7291_0 to user1@localhost;
+grant execute on procedure bug7291_1 to user1@localhost;
+grant execute on procedure bug7291_2 to user1@localhost;
+
+connect (user1,localhost,user1,,);
+connection user1;
+
+call bug7291_2();
+call bug7291_1();
+
+connection con1root;
+drop procedure bug7291_1;
+drop procedure bug7291_2;
+drop procedure bug7291_0;
+disconnect user1;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost;
+drop user user1@localhost;
+
+#
+# Bug #12318: Wrong error message when accessing an inaccessible stored
+# procedure in another database when the current database is
+# information_schema.
+#
+
+--disable_warnings
+drop database if exists mysqltest_1;
+--enable_warnings
+
+create database mysqltest_1;
+delimiter //;
+create procedure mysqltest_1.p1()
+begin
+ select 1 from dual;
+end//
+delimiter ;//
+
+grant usage on *.* to mysqltest_1@localhost;
+
+connect (n1,localhost,mysqltest_1,,information_schema,$MASTER_MYPORT,$MASTER_MYSOCK);
+connection n1;
+--error 1370
+call mysqltest_1.p1();
+disconnect n1;
+# Test also without a current database
+connect (n2,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,$MASTER_MYSOCK);
+connection n2;
+--error 1370
+call mysqltest_1.p1();
+disconnect n2;
+
+connection default;
+
+drop procedure mysqltest_1.p1;
+drop database mysqltest_1;
+
+revoke usage on *.* from mysqltest_1@localhost;
+drop user mysqltest_1@localhost;
+
+# End of 5.0 bugs.
diff --git a/mysql-test/t/sp-threads.test b/mysql-test/t/sp-threads.test
new file mode 100644
index 00000000000..70c1efb1f0b
--- /dev/null
+++ b/mysql-test/t/sp-threads.test
@@ -0,0 +1,183 @@
+#
+# Testing stored procedures with multiple connections,
+# except security/privilege tests, they go to sp-security.test
+#
+
+connect (con1root,localhost,root,,);
+connect (con2root,localhost,root,,);
+connect (con3root,localhost,root,,);
+
+connection con1root;
+use test;
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (s1 int, s2 int, s3 int);
+
+delimiter //;
+create procedure bug4934()
+begin
+ insert into t1 values (1,0,1);
+end//
+delimiter ;//
+
+
+connection con2root;
+use test;
+
+call bug4934();
+select * from t1;
+
+
+connection con1root;
+
+drop table t1;
+create table t1 (s1 int, s2 int, s3 int);
+
+drop procedure bug4934;
+delimiter //;
+create procedure bug4934()
+begin
+end//
+delimiter ;//
+
+
+connection con2root;
+
+select * from t1;
+call bug4934();
+select * from t1;
+
+connection con1root;
+
+drop table t1;
+drop procedure bug4934;
+
+
+#
+# BUG #9486 "Can't perform multi-update in stored procedure"
+#
+--disable_warnings
+drop procedure if exists bug9486;
+drop table if exists t1, t2;
+--enable_warnings
+create table t1 (id1 int, val int);
+create table t2 (id2 int);
+
+create procedure bug9486()
+ update t1, t2 set val= 1 where id1=id2;
+call bug9486();
+# Let us check that SP invocation requires write lock for t2.
+connection con2root;
+lock tables t2 write;
+connection con1root;
+send call bug9486();
+connection con2root;
+--sleep 2
+# There should be call statement in locked state.
+--replace_column 1 # 3 localhost 6 #
+show processlist;
+unlock tables;
+connection con1root;
+reap;
+
+drop procedure bug9486;
+drop table t1, t2;
+
+#
+# BUG#11158: Can't perform multi-delete in stored procedure
+#
+--disable_warnings
+drop procedure if exists bug11158;
+--enable_warnings
+create procedure bug11158() delete t1 from t1, t2 where t1.id = t2.id;
+create table t1 (id int, j int);
+insert into t1 values (1, 1), (2, 2);
+create table t2 (id int);
+insert into t2 values (1);
+# Procedure should work and cause proper effect (delete only first row)
+call bug11158();
+select * from t1;
+# Also let us test that we obtain only read (and thus non exclusive) lock
+# for table from which we are not going to delete rows.
+connection con2root;
+lock tables t2 read;
+connection con1root;
+call bug11158();
+connection con2root;
+unlock tables;
+connection con1root;
+# Clean-up
+drop procedure bug11158;
+drop table t1, t2;
+
+#
+# BUG#11554: Server crashes on statement indirectly using non-cached function
+#
+--disable_warnings
+drop function if exists bug11554;
+drop view if exists v1;
+--enable_warnings
+create table t1 (i int);
+create function bug11554 () returns int return 1;
+create view v1 as select bug11554() as f;
+connection con2root;
+# This should not crash server
+insert into t1 (select f from v1);
+# Clean-up
+connection con1root;
+drop function bug11554;
+drop table t1;
+drop view v1;
+
+
+# BUG#12228
+--disable_warnings
+drop procedure if exists p1;
+drop procedure if exists p2;
+--enable_warnings
+
+connection con1root;
+delimiter |;
+create table t1 (s1 int)|
+create procedure p1() select * from t1|
+create procedure p2()
+begin
+ insert into t1 values (1);
+ call p1();
+ select * from t1;
+end|
+delimiter ;|
+
+connection con2root;
+use test;
+lock table t1 write;
+
+connection con1root;
+send call p2();
+
+connection con3root;
+use test;
+drop procedure p1;
+create procedure p1() select * from t1;
+
+connection con2root;
+unlock tables;
+
+connection con1root;
+# Crash will be here if we hit BUG#12228
+reap;
+
+drop procedure p1;
+drop procedure p2;
+drop table t1;
+
+#
+# BUG#NNNN: New bug synopsis
+#
+#--disable_warnings
+#drop procedure if exists bugNNNN;
+#--enable_warnings
+#create procedure bugNNNN...
+
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
new file mode 100644
index 00000000000..b6a8eb6518a
--- /dev/null
+++ b/mysql-test/t/sp.test
@@ -0,0 +1,4221 @@
+#
+# Basic stored PROCEDURE tests
+#
+# Please keep this file free of --error cases and other
+# things that will not run in a single debugged mysqld
+# process (e.g. master-slave things).
+#
+# Test cases for bugs are added at the end. See template there.
+#
+# Tests that require --error go into sp-error.test
+# Tests that require inndb go into sp_trans.test
+# Tests that check privilege and security issues go to sp-security.test.
+# Tests that require multiple connections, except security/privilege tests,
+# go to sp-thread.
+# Tests that uses 'goto' to into sp-goto.test (currently disabled)
+
+use test;
+
+# Test tables
+#
+# t1 and t2 are reused throughout the file, and dropped at the end.
+# t3 and up are created and dropped when needed.
+#
+--disable_warnings
+drop table if exists t1,t2,t3,t4;
+--enable_warnings
+create table t1 (
+ id char(16) not null default '',
+ data int not null
+);
+create table t2 (
+ s char(16),
+ i int,
+ d double
+);
+
+
+# Single statement, no params.
+--disable_warnings
+drop procedure if exists foo42;
+--enable_warnings
+create procedure foo42()
+ insert into test.t1 values ("foo", 42);
+
+call foo42();
+select * from t1;
+delete from t1;
+drop procedure foo42;
+
+
+# Single statement, two IN params.
+--disable_warnings
+drop procedure if exists bar;
+--enable_warnings
+create procedure bar(x char(16), y int)
+ insert into test.t1 values (x, y);
+
+call bar("bar", 666);
+select * from t1;
+delete from t1;
+# Don't drop procedure yet...
+
+
+# Now for multiple statements...
+delimiter |;
+
+# Empty statement
+--disable_warnings
+drop procedure if exists empty|
+--enable_warnings
+create procedure empty()
+begin
+end|
+
+call empty()|
+drop procedure empty|
+
+# Scope test. This is legal (warnings might be possible in the future,
+# but for the time being, we just accept it).
+--disable_warnings
+drop procedure if exists scope|
+--enable_warnings
+create procedure scope(a int, b float)
+begin
+ declare b int;
+ declare c float;
+
+ begin
+ declare c int;
+ end;
+end|
+
+drop procedure scope|
+
+# Two statements.
+--disable_warnings
+drop procedure if exists two|
+--enable_warnings
+create procedure two(x1 char(16), x2 char(16), y int)
+begin
+ insert into test.t1 values (x1, y);
+ insert into test.t1 values (x2, y);
+end|
+
+call two("one", "two", 3)|
+select * from t1|
+delete from t1|
+drop procedure two|
+
+
+# Simple test of local variables and SET.
+--disable_warnings
+drop procedure if exists locset|
+--enable_warnings
+create procedure locset(x char(16), y int)
+begin
+ declare z1, z2 int;
+ set z1 = y;
+ set z2 = z1+2;
+ insert into test.t1 values (x, z2);
+end|
+
+call locset("locset", 19)|
+select * from t1|
+delete from t1|
+drop procedure locset|
+
+
+# In some contexts local variables are not recognized
+# (and in some, you have to qualify the identifier).
+--disable_warnings
+drop procedure if exists setcontext|
+--enable_warnings
+create procedure setcontext()
+begin
+ declare data int default 2;
+
+ insert into t1 (id, data) values ("foo", 1);
+ replace t1 set data = data, id = "bar";
+ update t1 set id = "kaka", data = 3 where t1.data = data;
+end|
+
+call setcontext()|
+select * from t1|
+delete from t1|
+drop procedure setcontext|
+
+
+# Set things to null
+create table t3 ( d date, i int, f double, s varchar(32) )|
+
+--disable_warnings
+drop procedure if exists nullset|
+--enable_warnings
+create procedure nullset()
+begin
+ declare ld date;
+ declare li int;
+ declare lf double;
+ declare ls varchar(32);
+
+ set ld = null, li = null, lf = null, ls = null;
+ insert into t3 values (ld, li, lf, ls);
+
+ insert into t3 (i, f, s) values ((ld is null), 1, "ld is null"),
+ ((li is null), 1, "li is null"),
+ ((li = 0), null, "li = 0"),
+ ((lf is null), 1, "lf is null"),
+ ((lf = 0), null, "lf = 0"),
+ ((ls is null), 1, "ls is null");
+end|
+
+call nullset()|
+select * from t3|
+drop table t3|
+drop procedure nullset|
+
+
+# The peculiar (non-standard) mixture of variables types in SET.
+--disable_warnings
+drop procedure if exists mixset|
+--enable_warnings
+create procedure mixset(x char(16), y int)
+begin
+ declare z int;
+
+ set @z = y, z = 666, max_join_size = 100;
+ insert into test.t1 values (x, z);
+end|
+
+call mixset("mixset", 19)|
+show variables like 'max_join_size'|
+select id,data,@z from t1|
+delete from t1|
+drop procedure mixset|
+
+
+# Multiple CALL statements, one with OUT parameter.
+--disable_warnings
+drop procedure if exists zip|
+--enable_warnings
+create procedure zip(x char(16), y int)
+begin
+ declare z int;
+ call zap(y, z);
+ call bar(x, z);
+end|
+
+# SET local variables and OUT parameter.
+--disable_warnings
+drop procedure if exists zap|
+--enable_warnings
+create procedure zap(x int, out y int)
+begin
+ declare z int;
+ set z = x+1, y = z;
+end|
+
+call zip("zip", 99)|
+select * from t1|
+delete from t1|
+drop procedure zip|
+drop procedure bar|
+
+# Top-level OUT parameter
+call zap(7, @zap)|
+select @zap|
+
+drop procedure zap|
+
+
+# "Deep" calls...
+--disable_warnings
+drop procedure if exists c1|
+--enable_warnings
+create procedure c1(x int)
+ call c2("c", x)|
+--disable_warnings
+drop procedure if exists c2|
+--enable_warnings
+create procedure c2(s char(16), x int)
+ call c3(x, s)|
+--disable_warnings
+drop procedure if exists c3|
+--enable_warnings
+create procedure c3(x int, s char(16))
+ call c4("level", x, s)|
+--disable_warnings
+drop procedure if exists c4|
+--enable_warnings
+create procedure c4(l char(8), x int, s char(16))
+ insert into t1 values (concat(l,s), x)|
+
+call c1(42)|
+select * from t1|
+delete from t1|
+drop procedure c1|
+drop procedure c2|
+drop procedure c3|
+drop procedure c4|
+
+# INOUT test
+--disable_warnings
+drop procedure if exists iotest|
+--enable_warnings
+create procedure iotest(x1 char(16), x2 char(16), y int)
+begin
+ call inc2(x2, y);
+ insert into test.t1 values (x1, y);
+end|
+
+--disable_warnings
+drop procedure if exists inc2|
+--enable_warnings
+create procedure inc2(x char(16), y int)
+begin
+ call inc(y);
+ insert into test.t1 values (x, y);
+end|
+
+--disable_warnings
+drop procedure if exists inc|
+--enable_warnings
+create procedure inc(inout io int)
+ set io = io + 1|
+
+call iotest("io1", "io2", 1)|
+select * from t1|
+delete from t1|
+drop procedure iotest|
+drop procedure inc2|
+
+# Propagating top-level @-vars
+--disable_warnings
+drop procedure if exists incr|
+--enable_warnings
+create procedure incr(inout x int)
+ call inc(x)|
+
+# Before
+select @zap|
+call incr(@zap)|
+# After
+select @zap|
+
+drop procedure inc|
+drop procedure incr|
+
+# Call-by-value test
+# The expected result is:
+# ("cbv2", 4)
+# ("cbv1", 4711)
+--disable_warnings
+drop procedure if exists cbv1|
+--enable_warnings
+create procedure cbv1()
+begin
+ declare y int default 3;
+
+ call cbv2(y+1, y);
+ insert into test.t1 values ("cbv1", y);
+end|
+
+--disable_warnings
+drop procedure if exists cbv2|
+--enable_warnings
+create procedure cbv2(y1 int, inout y2 int)
+begin
+ set y2 = 4711;
+ insert into test.t1 values ("cbv2", y1);
+end|
+
+call cbv1()|
+select * from t1|
+delete from t1|
+drop procedure cbv1|
+drop procedure cbv2|
+
+
+# Subselect arguments
+
+insert into t2 values ("a", 1, 1.1), ("b", 2, 1.2), ("c", 3, 1.3)|
+
+--disable_warnings
+drop procedure if exists sub1|
+--enable_warnings
+create procedure sub1(id char(16), x int)
+ insert into test.t1 values (id, x)|
+
+--disable_warnings
+drop procedure if exists sub2|
+--enable_warnings
+create procedure sub2(id char(16))
+begin
+ declare x int;
+ set x = (select sum(t.i) from test.t2 t);
+ insert into test.t1 values (id, x);
+end|
+
+--disable_warnings
+drop procedure if exists sub3|
+--enable_warnings
+create function sub3(i int) returns int
+ return i+1|
+
+call sub1("sub1a", (select 7))|
+call sub1("sub1b", (select max(i) from t2))|
+call sub1("sub1c", (select i,d from t2 limit 1))|
+call sub1("sub1d", (select 1 from (select 1) a))|
+call sub2("sub2")|
+select * from t1|
+select sub3((select max(i) from t2))|
+drop procedure sub1|
+drop procedure sub2|
+drop function sub3|
+delete from t1|
+delete from t2|
+
+# Basic tests of the flow control constructs
+
+# Just test on 'x'...
+--disable_warnings
+drop procedure if exists a0|
+--enable_warnings
+create procedure a0(x int)
+while x do
+ set x = x-1;
+ insert into test.t1 values ("a0", x);
+end while|
+
+call a0(3)|
+select * from t1|
+delete from t1|
+drop procedure a0|
+
+
+# The same, but with a more traditional test.
+--disable_warnings
+drop procedure if exists a|
+--enable_warnings
+create procedure a(x int)
+while x > 0 do
+ set x = x-1;
+ insert into test.t1 values ("a", x);
+end while|
+
+call a(3)|
+select * from t1|
+delete from t1|
+drop procedure a|
+
+
+# REPEAT
+--disable_warnings
+drop procedure if exists b|
+--enable_warnings
+create procedure b(x int)
+repeat
+ insert into test.t1 values (repeat("b",3), x);
+ set x = x-1;
+until x = 0 end repeat|
+
+call b(3)|
+select * from t1|
+delete from t1|
+drop procedure b|
+
+
+# Check that repeat isn't parsed the wrong way
+--disable_warnings
+drop procedure if exists b2|
+--enable_warnings
+create procedure b2(x int)
+repeat(select 1 into outfile 'b2');
+ insert into test.t1 values (repeat("b2",3), x);
+ set x = x-1;
+until x = 0 end repeat|
+
+# We don't actually want to call it.
+drop procedure b2|
+
+
+# Labelled WHILE with ITERATE (pointless really)
+--disable_warnings
+drop procedure if exists c|
+--enable_warnings
+create procedure c(x int)
+hmm: while x > 0 do
+ insert into test.t1 values ("c", x);
+ set x = x-1;
+ iterate hmm;
+ insert into test.t1 values ("x", x);
+end while hmm|
+
+call c(3)|
+select * from t1|
+delete from t1|
+drop procedure c|
+
+
+# Labelled WHILE with LEAVE
+--disable_warnings
+drop procedure if exists d|
+--enable_warnings
+create procedure d(x int)
+hmm: while x > 0 do
+ insert into test.t1 values ("d", x);
+ set x = x-1;
+ leave hmm;
+ insert into test.t1 values ("x", x);
+end while|
+
+call d(3)|
+select * from t1|
+delete from t1|
+drop procedure d|
+
+
+# LOOP, with simple IF statement
+--disable_warnings
+drop procedure if exists e|
+--enable_warnings
+create procedure e(x int)
+foo: loop
+ if x = 0 then
+ leave foo;
+ end if;
+ insert into test.t1 values ("e", x);
+ set x = x-1;
+end loop foo|
+
+call e(3)|
+select * from t1|
+delete from t1|
+drop procedure e|
+
+
+# A full IF statement
+--disable_warnings
+drop procedure if exists f|
+--enable_warnings
+create procedure f(x int)
+if x < 0 then
+ insert into test.t1 values ("f", 0);
+elseif x = 0 then
+ insert into test.t1 values ("f", 1);
+else
+ insert into test.t1 values ("f", 2);
+end if|
+
+call f(-2)|
+call f(0)|
+call f(4)|
+select * from t1|
+delete from t1|
+drop procedure f|
+
+
+# This form of CASE is really just syntactic sugar for IF-ELSEIF-...
+--disable_warnings
+drop procedure if exists g|
+--enable_warnings
+create procedure g(x int)
+case
+when x < 0 then
+ insert into test.t1 values ("g", 0);
+when x = 0 then
+ insert into test.t1 values ("g", 1);
+else
+ insert into test.t1 values ("g", 2);
+end case|
+
+call g(-42)|
+call g(0)|
+call g(1)|
+select * from t1|
+delete from t1|
+drop procedure g|
+
+
+# The "simple CASE"
+--disable_warnings
+drop procedure if exists h|
+--enable_warnings
+create procedure h(x int)
+case x
+when 0 then
+ insert into test.t1 values ("h0", x);
+when 1 then
+ insert into test.t1 values ("h1", x);
+else
+ insert into test.t1 values ("h?", x);
+end case|
+
+call h(0)|
+call h(1)|
+call h(17)|
+select * from t1|
+delete from t1|
+drop procedure h|
+
+
+# It's actually possible to LEAVE a BEGIN-END block
+--disable_warnings
+drop procedure if exists i|
+--enable_warnings
+create procedure i(x int)
+foo:
+begin
+ if x = 0 then
+ leave foo;
+ end if;
+ insert into test.t1 values ("i", x);
+end foo|
+
+call i(0)|
+call i(3)|
+select * from t1|
+delete from t1|
+drop procedure i|
+
+
+# SELECT with one of more result set sent back to the clinet
+insert into t1 values ("foo", 3), ("bar", 19)|
+insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
+
+--disable_warnings
+drop procedure if exists sel1|
+--enable_warnings
+create procedure sel1()
+begin
+ select * from t1;
+end|
+
+call sel1()|
+drop procedure sel1|
+
+--disable_warnings
+drop procedure if exists sel2|
+--enable_warnings
+create procedure sel2()
+begin
+ select * from t1;
+ select * from t2;
+end|
+
+call sel2()|
+drop procedure sel2|
+delete from t1|
+delete from t2|
+
+# SELECT INTO local variables
+--disable_warnings
+drop procedure if exists into_test|
+--enable_warnings
+create procedure into_test(x char(16), y int)
+begin
+ insert into test.t1 values (x, y);
+ select id,data into x,y from test.t1 limit 1;
+ insert into test.t1 values (concat(x, "2"), y+2);
+end|
+
+call into_test("into", 100)|
+select * from t1|
+delete from t1|
+drop procedure into_test|
+
+
+# SELECT INTO with a mix of local and global variables
+--disable_warnings
+drop procedure if exists into_tes2|
+--enable_warnings
+create procedure into_test2(x char(16), y int)
+begin
+ insert into test.t1 values (x, y);
+ select id,data into x,@z from test.t1 limit 1;
+ insert into test.t1 values (concat(x, "2"), y+2);
+end|
+
+call into_test2("into", 100)|
+select id,data,@z from t1|
+delete from t1|
+drop procedure into_test2|
+
+
+# SELECT * INTO ... (bug test)
+--disable_warnings
+drop procedure if exists into_test3|
+--enable_warnings
+create procedure into_test3()
+begin
+ declare x char(16);
+ declare y int;
+
+ select * into x,y from test.t1 limit 1;
+ insert into test.t2 values (x, y, 0.0);
+end|
+
+insert into t1 values ("into3", 19)|
+# Two call needed for bug test
+call into_test3()|
+call into_test3()|
+select * from t2|
+delete from t1|
+delete from t2|
+drop procedure into_test3|
+
+
+# SELECT INTO with no data is a warning ("no data", which we will
+# not see normally). When not caught, execution proceeds.
+--disable_warnings
+drop procedure if exists into_test4|
+--enable_warnings
+create procedure into_test4()
+begin
+ declare x int;
+
+ select data into x from test.t1 limit 1;
+ insert into test.t3 values ("into4", x);
+end|
+
+delete from t1|
+create table t3 ( s char(16), d int)|
+call into_test4()|
+select * from t3|
+insert into t1 values ("i4", 77)|
+call into_test4()|
+select * from t3|
+delete from t1|
+drop table t3|
+drop procedure into_test4|
+
+
+# These two (and the two procedures above) caused an assert() to fail in
+# sql_base.cc:lock_tables() at some point.
+--disable_warnings
+drop procedure if exists into_outfile|
+--enable_warnings
+create procedure into_outfile(x char(16), y int)
+begin
+ insert into test.t1 values (x, y);
+ select * into outfile "/tmp/spout" from test.t1;
+ insert into test.t1 values (concat(x, "2"), y+2);
+end|
+
+system rm -f /tmp/spout|
+call into_outfile("ofile", 1)|
+system rm -f /tmp/spout|
+delete from t1|
+drop procedure into_outfile|
+
+--disable_warnings
+drop procedure if exists into_dumpfile|
+--enable_warnings
+create procedure into_dumpfile(x char(16), y int)
+begin
+ insert into test.t1 values (x, y);
+ select * into dumpfile "/tmp/spdump" from test.t1 limit 1;
+ insert into test.t1 values (concat(x, "2"), y+2);
+end|
+
+system rm -f /tmp/spdump|
+call into_dumpfile("dfile", 1)|
+system rm -f /tmp/spdump|
+delete from t1|
+drop procedure into_dumpfile|
+
+--disable_warnings
+drop procedure if exists create_select|
+--enable_warnings
+create procedure create_select(x char(16), y int)
+begin
+ insert into test.t1 values (x, y);
+ create temporary table test.t3 select * from test.t1;
+ insert into test.t3 values (concat(x, "2"), y+2);
+end|
+
+call create_select("cs", 90)|
+select * from t1, t3|
+drop table t3|
+delete from t1|
+drop procedure create_select|
+
+
+# A minimal, constant FUNCTION.
+--disable_warnings
+drop function if exists e|
+--enable_warnings
+create function e() returns double
+ return 2.7182818284590452354|
+
+set @e = e()|
+select e(), @e|
+
+# A minimal function with one argument
+--disable_warnings
+drop function if exists inc|
+--enable_warnings
+create function inc(i int) returns int
+ return i+1|
+
+select inc(1), inc(99), inc(-71)|
+
+# A minimal function with two arguments
+--disable_warnings
+drop function if exists mul|
+--enable_warnings
+create function mul(x int, y int) returns int
+ return x*y|
+
+select mul(1,1), mul(3,5), mul(4711, 666)|
+
+# A minimal string function
+--disable_warnings
+drop function if exists append|
+--enable_warnings
+create function append(s1 char(8), s2 char(8)) returns char(16)
+ return concat(s1, s2)|
+
+select append("foo", "bar")|
+
+# A function with flow control
+--disable_warnings
+drop function if exists fac|
+--enable_warnings
+create function fac(n int unsigned) returns bigint unsigned
+begin
+ declare f bigint unsigned default 1;
+
+ while n > 1 do
+ set f = f * n;
+ set n = n - 1;
+ end while;
+ return f;
+end|
+
+select fac(1), fac(2), fac(5), fac(10)|
+
+# Nested calls
+--disable_warnings
+drop function if exists fun|
+--enable_warnings
+create function fun(d double, i int, u int unsigned) returns double
+ return mul(inc(i), fac(u)) / e()|
+
+select fun(2.3, 3, 5)|
+
+
+# Various function calls in differen statements
+
+insert into t2 values (append("xxx", "yyy"), mul(4,3), e())|
+insert into t2 values (append("a", "b"), mul(2,mul(3,4)), fun(1.7, 4, 6))|
+
+# Disable PS because double's give a bit different values
+--disable_ps_protocol
+select * from t2 where s = append("a", "b")|
+select * from t2 where i = mul(4,3) or i = mul(mul(3,4),2)|
+select * from t2 where d = e()|
+select * from t2|
+--enable_ps_protocol
+delete from t2|
+
+drop function e|
+drop function inc|
+drop function mul|
+drop function append|
+drop function fun|
+
+
+#
+# CONDITIONs and HANDLERs
+#
+
+--disable_warnings
+drop procedure if exists hndlr1|
+--enable_warnings
+create procedure hndlr1(val int)
+begin
+ declare x int default 0;
+ declare foo condition for 1136;
+ declare bar condition for sqlstate '42S98'; # Just for testing syntax
+ declare zip condition for sqlstate value '42S99'; # Just for testing syntax
+ declare continue handler for foo set x = 1;
+
+ insert into test.t1 values ("hndlr1", val, 2); # Too many values
+ if (x) then
+ insert into test.t1 values ("hndlr1", val); # This instead then
+ end if;
+end|
+
+call hndlr1(42)|
+select * from t1|
+delete from t1|
+drop procedure hndlr1|
+
+--disable_warnings
+drop procedure if exists hndlr2|
+--enable_warnings
+create procedure hndlr2(val int)
+begin
+ declare x int default 0;
+
+ begin
+ declare exit handler for sqlstate '21S01' set x = 1;
+
+ insert into test.t1 values ("hndlr2", val, 2); # Too many values
+ end;
+
+ insert into test.t1 values ("hndlr2", x);
+end|
+
+call hndlr2(42)|
+select * from t1|
+delete from t1|
+drop procedure hndlr2|
+
+
+--disable_warnings
+drop procedure if exists hndlr3|
+--enable_warnings
+create procedure hndlr3(val int)
+begin
+ declare x int default 0;
+ declare continue handler for sqlexception # Any error
+ begin
+ declare z int;
+
+ set z = 2 * val;
+ set x = 1;
+ end;
+
+ if val < 10 then
+ begin
+ declare y int;
+
+ set y = val + 10;
+ insert into test.t1 values ("hndlr3", y, 2); # Too many values
+ if x then
+ insert into test.t1 values ("hndlr3", y);
+ end if;
+ end;
+ end if;
+end|
+
+call hndlr3(3)|
+select * from t1|
+delete from t1|
+drop procedure hndlr3|
+
+
+# Variables might be uninitialized when using handlers
+# (Otherwise the compiler can detect if a variable is not set, but
+# not in this case.)
+create table t3 ( id char(16), data int )|
+
+--disable_warnings
+drop procedure if exists hndlr4|
+--enable_warnings
+create procedure hndlr4()
+begin
+ declare x int default 0;
+ declare val int; # No default
+ declare continue handler for sqlstate '02000' set x=1;
+
+ select data into val from test.t3 where id='z' limit 1; # No hits
+
+ insert into test.t3 values ('z', val);
+end|
+
+call hndlr4()|
+select * from t3|
+drop table t3|
+drop procedure hndlr4|
+
+
+#
+# Cursors
+#
+--disable_warnings
+drop procedure if exists cur1|
+--enable_warnings
+create procedure cur1()
+begin
+ declare a char(16);
+ declare b int;
+ declare c double;
+ declare done int default 0;
+ declare c cursor for select * from test.t2;
+ declare continue handler for sqlstate '02000' set done = 1;
+
+ open c;
+ repeat
+ fetch c into a, b, c;
+ if not done then
+ insert into test.t1 values (a, b+c);
+ end if;
+ until done end repeat;
+ close c;
+end|
+
+insert into t2 values ("foo", 42, -1.9), ("bar", 3, 12.1), ("zap", 666, -3.14)|
+call cur1()|
+select * from t1|
+drop procedure cur1|
+
+create table t3 ( s char(16), i int )|
+
+--disable_warnings
+drop procedure if exists cur2|
+--enable_warnings
+create procedure cur2()
+begin
+ declare done int default 0;
+ declare c1 cursor for select id,data from test.t1;
+ declare c2 cursor for select i from test.t2;
+ declare continue handler for sqlstate '02000' set done = 1;
+
+ open c1;
+ open c2;
+ repeat
+ begin
+ declare a char(16);
+ declare b,c int;
+
+ fetch from c1 into a, b;
+ fetch next from c2 into c;
+ if not done then
+ if b < c then
+ insert into test.t3 values (a, b);
+ else
+ insert into test.t3 values (a, c);
+ end if;
+ end if;
+ end;
+ until done end repeat;
+ close c1;
+ close c2;
+end|
+
+call cur2()|
+select * from t3|
+delete from t1|
+delete from t2|
+drop table t3|
+drop procedure cur2|
+
+
+# The few characteristics we parse
+--disable_warnings
+drop procedure if exists chistics|
+--enable_warnings
+create procedure chistics()
+ language sql
+ modifies sql data
+ not deterministic
+ sql security definer
+ comment 'Characteristics procedure test'
+ insert into t1 values ("chistics", 1)|
+
+show create procedure chistics|
+# Call it, just to make sure.
+call chistics()|
+select * from t1|
+delete from t1|
+alter procedure chistics sql security invoker|
+show create procedure chistics|
+drop procedure chistics|
+
+--disable_warnings
+drop function if exists chistics|
+--enable_warnings
+create function chistics() returns int
+ language sql
+ deterministic
+ sql security invoker
+ comment 'Characteristics procedure test'
+ return 42|
+
+show create function chistics|
+# Call it, just to make sure.
+select chistics()|
+alter function chistics
+ no sql
+ comment 'Characteristics function test'|
+show create function chistics|
+drop function chistics|
+
+
+# Check mode settings
+insert into t1 values ("foo", 1), ("bar", 2), ("zip", 3)|
+
+set @@sql_mode = 'ANSI'|
+delimiter $|
+--disable_warnings
+drop procedure if exists modes$
+--enable_warnings
+create procedure modes(out c1 int, out c2 int)
+begin
+ declare done int default 0;
+ declare x int;
+ declare c cursor for select data from t1;
+ declare continue handler for sqlstate '02000' set done = 1;
+
+ select 1 || 2 into c1;
+ set c2 = 0;
+ open c;
+ repeat
+ fetch c into x;
+ if not done then
+ set c2 = c2 + 1;
+ end if;
+ until done end repeat;
+ close c;
+end$
+delimiter |$
+set @@sql_mode = ''|
+
+set sql_select_limit = 1|
+call modes(@c1, @c2)|
+set sql_select_limit = default|
+
+select @c1, @c2|
+delete from t1|
+drop procedure modes|
+
+
+# Check that dropping a database without routines works.
+# (Dropping with routines is tested in sp-security.test)
+# First an empty db.
+create database sp_db1|
+drop database sp_db1|
+
+# Again, with a table.
+create database sp_db2|
+use sp_db2|
+# Just put something in here...
+create table t3 ( s char(4), t int )|
+insert into t3 values ("abcd", 42), ("dcba", 666)|
+use test|
+drop database sp_db2|
+
+# And yet again, with just a procedure.
+create database sp_db3|
+use sp_db3|
+--disable_warnings
+drop procedure if exists dummy|
+--enable_warnings
+create procedure dummy(out x int)
+ set x = 42|
+use test|
+drop database sp_db3|
+# Check that it's gone
+select type,db,name from mysql.proc where db = 'sp_db3'|
+
+
+# ROW_COUNT() function after a CALL
+# We test the other cases here too, although it's not strictly SP specific
+--disable_warnings
+drop procedure if exists rc|
+--enable_warnings
+create procedure rc()
+begin
+ delete from t1;
+ insert into t1 values ("a", 1), ("b", 2), ("c", 3);
+end|
+
+call rc()|
+select row_count()|
+--disable_ps_protocol
+update t1 set data=42 where id = "b";
+select row_count()|
+--enable_ps_protocol
+delete from t1|
+select row_count()|
+delete from t1|
+select row_count()|
+select * from t1|
+select row_count()|
+drop procedure rc|
+
+
+#
+# Let us test how well new locking scheme works.
+#
+
+# Let us prepare playground
+--disable_warnings
+drop function if exists f0|
+drop function if exists f1|
+drop function if exists f2|
+drop function if exists f3|
+drop function if exists f4|
+drop function if exists f5|
+drop function if exists f6|
+drop function if exists f7|
+drop function if exists f8|
+drop view if exists v0|
+drop view if exists v1|
+drop view if exists v2|
+--enable_warnings
+delete from t1|
+delete from t2|
+insert into t1 values ("a", 1), ("b", 2) |
+insert into t2 values ("a", 1, 1.0), ("b", 2, 2.0), ("c", 3, 3.0) |
+
+# Test the simplest function using tables
+create function f1() returns int
+ return (select sum(data) from t1)|
+select f1()|
+# This should work too (and give 2 rows as result)
+select id, f1() from t1|
+
+# Function which uses two instances of table simultaneously
+create function f2() returns int
+ return (select data from t1 where data <= (select sum(data) from t1) limit 1)|
+select f2()|
+select id, f2() from t1|
+
+# Function which uses the same table twice in different queries
+create function f3() returns int
+begin
+ declare n int;
+ declare m int;
+ set n:= (select min(data) from t1);
+ set m:= (select max(data) from t1);
+ return n < m;
+end|
+select f3()|
+select id, f3() from t1|
+
+# Calling two functions using same table
+select f1(), f3()|
+select id, f1(), f3() from t1|
+
+# Function which uses two different tables
+create function f4() returns double
+ return (select d from t1, t2 where t1.data = t2.i and t1.id= "b")|
+select f4()|
+select s, f4() from t2|
+
+# Recursive functions which due to this recursion require simultaneous
+# access to several instance of the same table won't work
+create function f5(i int) returns int
+begin
+ if i <= 0 then
+ return 0;
+ elseif i = 1 then
+ return (select count(*) from t1 where data = i);
+ else
+ return (select count(*) + f5( i - 1) from t1 where data = i);
+ end if;
+end|
+select f5(1)|
+# This should generate an error about insuficient number of tables locked
+# Now this crash server
+--disable_parsing # until bug#11394 fix
+--error 1100
+select f5(2)|
+# But now it simply miserably fails because we are trying to use the same
+# lex on the next iteration :/ It should generate some error too...
+select f5(3)|
+--enable_parsing
+
+# OTOH this should work
+create function f6() returns int
+begin
+ declare n int;
+ set n:= f1();
+ return (select count(*) from t1 where data <= f7() and data <= n);
+end|
+create function f7() returns int
+ return (select sum(data) from t1 where data <= f1())|
+select f6()|
+select id, f6() from t1|
+
+# TODO Test temporary table handling
+
+#
+# Let us test how new locking work with views
+#
+# The most trivial view
+create view v1 (a) as select f1()|
+select * from v1|
+select id, a from t1, v1|
+select * from v1, v1 as v|
+# A bit more complex construction
+create view v2 (a) as select a*10 from v1|
+select * from v2|
+select id, a from t1, v2|
+select * from v1, v2|
+
+# Nice example where the same view is used on
+# on different expression levels
+create function f8 () returns int
+ return (select count(*) from v2)|
+
+select *, f8() from v1|
+
+# Let us test what will happen if function is missing
+drop function f1|
+--error 1356
+select * from v1|
+
+# And what will happen if we have recursion which involves
+# views and functions ?
+create function f1() returns int
+ return (select sum(data) from t1) + (select sum(data) from v1)|
+# This queries will crash server because we can't use LEX in
+# reenterable fashion yet. Patch disabling recursion will heal this.
+--disable_parsing
+select f1()|
+select * from v1|
+select * from v2|
+--enable_parsing
+# Back to the normal cases
+drop function f1|
+create function f1() returns int
+ return (select sum(data) from t1)|
+
+# Let us also test some weird cases where no real tables is used
+create function f0() returns int
+ return (select * from (select 100) as r)|
+select f0()|
+select *, f0() from (select 1) as t|
+create view v0 as select f0()|
+select * from v0|
+select *, f0() from v0|
+
+#
+# Let us test how well prelocking works with explicit LOCK TABLES.
+#
+# Nowdays we have to lock mysql.proc to be able to read SP definitions.
+# But Monty was going to fix this.
+lock tables t1 read, t1 as t11 read, mysql.proc read|
+# These should work well
+select f3()|
+select id, f3() from t1 as t11|
+# Degenerate cases work too :)
+select f0()|
+select * from v0|
+select *, f0() from v0, (select 123) as d1|
+# But these should not !
+--error 1100
+select id, f3() from t1|
+--error 1100
+select f4()|
+unlock tables|
+
+# Let us test how LOCK TABLES which implicitly depends on functions
+# works
+lock tables v2 read, mysql.proc read|
+select * from v2|
+select * from v1|
+# These should not work as we have too little instances of tables locked
+--error 1100
+select * from v1, t1|
+--error 1100
+select f4()|
+unlock tables|
+
+
+# Cleanup
+drop function f0|
+drop function f1|
+drop function f2|
+drop function f3|
+drop function f4|
+drop function f5|
+drop function f6|
+drop function f7|
+drop function f8|
+drop view v0|
+drop view v1|
+drop view v2|
+delete from t1 |
+delete from t2 |
+
+# End of non-bug tests
+
+
+#
+# Some "real" examples
+#
+
+# fac
+
+--disable_warnings
+drop table if exists fac|
+--enable_warnings
+create table fac (n int unsigned not null primary key, f bigint unsigned)|
+
+--disable_warnings
+drop procedure if exists ifac|
+--enable_warnings
+create procedure ifac(n int unsigned)
+begin
+ declare i int unsigned default 1;
+
+ if n > 20 then
+ set n = 20; # bigint overflow otherwise
+ end if;
+ while i <= n do
+ begin
+ insert into test.fac values (i, fac(i));
+ set i = i + 1;
+ end;
+ end while;
+end|
+
+call ifac(20)|
+select * from fac|
+drop table fac|
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show function status like '%f%'|
+drop procedure ifac|
+drop function fac|
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show function status like '%f%'|
+
+
+# primes
+
+--disable_warnings
+drop table if exists primes|
+--enable_warnings
+
+create table primes (
+ i int unsigned not null primary key,
+ p bigint unsigned not null
+)|
+
+insert into primes values
+ ( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13),
+ ( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31),
+ (10, 37), (11, 41), (12, 43), (13, 47), (14, 53),
+ (15, 59), (16, 61), (17, 67), (18, 71), (19, 73),
+ (20, 79), (21, 83), (22, 89), (23, 97), (24, 101),
+ (25, 103), (26, 107), (27, 109), (28, 113), (29, 127),
+ (30, 131), (31, 137), (32, 139), (33, 149), (34, 151),
+ (35, 157), (36, 163), (37, 167), (38, 173), (39, 179),
+ (40, 181), (41, 191), (42, 193), (43, 197), (44, 199)|
+
+--disable_warnings
+drop procedure if exists opp|
+--enable_warnings
+create procedure opp(n bigint unsigned, out pp bool)
+begin
+ declare r double;
+ declare b, s bigint unsigned default 0;
+
+ set r = sqrt(n);
+
+ again:
+ loop
+ if s = 45 then
+ set b = b+200, s = 0;
+ else
+ begin
+ declare p bigint unsigned;
+
+ select t.p into p from test.primes t where t.i = s;
+ if b+p > r then
+ set pp = 1;
+ leave again;
+ end if;
+ if mod(n, b+p) = 0 then
+ set pp = 0;
+ leave again;
+ end if;
+ set s = s+1;
+ end;
+ end if;
+ end loop;
+end|
+
+--disable_warnings
+drop procedure if exists ip|
+--enable_warnings
+create procedure ip(m int unsigned)
+begin
+ declare p bigint unsigned;
+ declare i int unsigned;
+
+ set i=45, p=201;
+
+ while i < m do
+ begin
+ declare pp bool default 0;
+
+ call opp(p, pp);
+ if pp then
+ insert into test.primes values (i, p);
+ set i = i+1;
+ end if;
+ set p = p+2;
+ end;
+ end while;
+end|
+show create procedure opp|
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show procedure status like '%p%'|
+
+# This isn't the fastest way in the world to compute prime numbers, so
+# don't be too ambitious. ;-)
+call ip(200)|
+# We don't want to select the entire table here, just pick a few
+# examples.
+# The expected result is:
+# i p
+# --- ----
+# 45 211
+# 100 557
+# 199 1229
+select * from primes where i=45 or i=100 or i=199|
+drop table primes|
+drop procedure opp|
+drop procedure ip|
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show procedure status like '%p%'|
+
+
+# Fibonacci, for recursion test. (Yet Another Numerical series :)
+#
+# This part of test is disabled until we implement support for
+# recursive stored procedures.
+--disable_parsing
+--disable_warnings
+drop table if exists fib|
+--enable_warnings
+create table fib ( f bigint unsigned not null )|
+
+# We deliberately do it the awkward way, fetching the last two
+# values from the table, in order to exercise various statements
+# and table accesses at each turn.
+--disable_warnings
+drop procedure if exists fib|
+--enable_warnings
+create procedure fib(n int unsigned)
+begin
+ if n > 1 then
+ begin
+ declare x, y bigint unsigned;
+ declare c cursor for select f from fib order by f desc limit 2;
+
+ open c;
+ fetch c into y;
+ fetch c into x;
+ close c;
+ insert into fib values (x+y);
+ call fib(n-1);
+ end;
+ end if;
+end|
+
+# Minimum test: recursion of 3 levels
+
+insert into fib values (0), (1)|
+
+call fib(3)|
+
+select * from fib order by f asc|
+
+delete from fib|
+
+# Original test: 20 levels (may run into memory limits!)
+
+insert into fib values (0), (1)|
+
+call fib(20)|
+
+select * from fib order by f asc|
+drop table fib|
+drop procedure fib|
+--enable_parsing
+
+#
+# Comment & suid
+#
+
+--disable_warnings
+drop procedure if exists bar|
+--enable_warnings
+create procedure bar(x char(16), y int)
+ comment "111111111111" sql security invoker
+ insert into test.t1 values (x, y)|
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show procedure status like 'bar'|
+alter procedure bar comment "2222222222" sql security definer|
+alter procedure bar comment "3333333333"|
+alter procedure bar|
+show create procedure bar|
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+show procedure status like 'bar'|
+drop procedure bar|
+
+#
+# rexecution
+#
+--disable_warnings
+drop procedure if exists p1|
+--enable_warnings
+create procedure p1 ()
+ select (select s1 from t3) from t3|
+
+create table t3 (s1 int)|
+
+call p1()|
+insert into t3 values (1)|
+call p1()|
+drop procedure p1|
+drop table t3|
+
+#
+# backticks
+#
+--disable_warnings
+drop function if exists foo|
+--enable_warnings
+create function `foo` () returns int
+ return 5|
+select `foo` ()|
+drop function `foo`|
+
+#
+# Implicit LOCK/UNLOCK TABLES for table access in functions
+#
+
+--disable_warning
+drop function if exists t1max|
+--enable_warnings
+create function t1max() returns int
+begin
+ declare x int;
+ select max(data) into x from t1;
+ return x;
+end|
+
+insert into t1 values ("foo", 3), ("bar", 2), ("zip", 5), ("zap", 1)|
+select t1max()|
+drop function t1max|
+
+create table t3 (
+ v char(16) not null primary key,
+ c int unsigned not null
+)|
+
+create function getcount(s char(16)) returns int
+begin
+ declare x int;
+
+ select count(*) into x from t3 where v = s;
+ if x = 0 then
+ insert into t3 values (s, 1);
+ else
+ update t3 set c = c+1 where v = s;
+ end if;
+ return x;
+end|
+
+select * from t1 where data = getcount("bar")|
+select * from t3|
+select getcount("zip")|
+select getcount("zip")|
+select * from t3|
+select getcount(id) from t1 where data = 3|
+select getcount(id) from t1 where data = 5|
+select * from t3|
+drop table t3|
+drop function getcount|
+
+
+#
+# Test cases for old bugs
+#
+
+#
+# BUG#822
+#
+--disable_warnings
+drop procedure if exists bug822|
+--enable_warnings
+create procedure bug822(a_id char(16), a_data int)
+begin
+ declare n int;
+ select count(*) into n from t1 where id = a_id and data = a_data;
+ if n = 0 then
+ insert into t1 (id, data) values (a_id, a_data);
+ end if;
+end|
+
+delete from t1|
+call bug822('foo', 42)|
+call bug822('foo', 42)|
+call bug822('bar', 666)|
+select * from t1|
+delete from t1|
+drop procedure bug822|
+
+#
+# BUG#1495
+#
+--disable_warnings
+drop procedure if exists bug1495|
+--enable_warnings
+create procedure bug1495()
+begin
+ declare x int;
+
+ select data into x from t1 order by id limit 1;
+ if x > 10 then
+ insert into t1 values ("less", x-10);
+ else
+ insert into t1 values ("more", x+10);
+ end if;
+end|
+
+insert into t1 values ('foo', 12)|
+call bug1495()|
+delete from t1 where id='foo'|
+insert into t1 values ('bar', 7)|
+call bug1495()|
+delete from t1 where id='bar'|
+select * from t1|
+delete from t1|
+drop procedure bug1495|
+
+#
+# BUG#1547
+#
+--disable_warnings
+drop procedure if exists bug1547|
+--enable_warnings
+create procedure bug1547(s char(16))
+begin
+ declare x int;
+
+ select data into x from t1 where s = id limit 1;
+ if x > 10 then
+ insert into t1 values ("less", x-10);
+ else
+ insert into t1 values ("more", x+10);
+ end if;
+end|
+
+insert into t1 values ("foo", 12), ("bar", 7)|
+call bug1547("foo")|
+call bug1547("bar")|
+select * from t1|
+delete from t1|
+drop procedure bug1547|
+
+#
+# BUG#1656
+#
+--disable_warnings
+drop table if exists t70|
+--enable_warnings
+create table t70 (s1 int,s2 int)|
+insert into t70 values (1,2)|
+
+--disable_warnings
+drop procedure if exists bug1656|
+--enable_warnings
+create procedure bug1656(out p1 int, out p2 int)
+ select * into p1, p1 from t70|
+
+call bug1656(@1, @2)|
+select @1, @2|
+drop table t70|
+drop procedure bug1656|
+
+#
+# BUG#1862
+#
+create table t3(a int)|
+
+--disable_warnings
+drop procedure if exists bug1862|
+--enable_warnings
+create procedure bug1862()
+begin
+ insert into t3 values(2);
+ flush tables;
+end|
+
+call bug1862()|
+# the second call caused a segmentation
+call bug1862()|
+select * from t3|
+drop table t3|
+drop procedure bug1862|
+
+#
+# BUG#1874
+#
+--disable_warnings
+drop procedure if exists bug1874|
+--enable_warnings
+create procedure bug1874()
+begin
+ declare x int;
+ declare y double;
+ select max(data) into x from t1;
+ insert into t2 values ("max", x, 0);
+ select min(data) into x from t1;
+ insert into t2 values ("min", x, 0);
+ select sum(data) into x from t1;
+ insert into t2 values ("sum", x, 0);
+ select avg(data) into y from t1;
+ insert into t2 values ("avg", 0, y);
+end|
+
+insert into t1 (data) values (3), (1), (5), (9), (4)|
+call bug1874()|
+select * from t2|
+delete from t1|
+delete from t2|
+drop procedure bug1874|
+
+#
+# BUG#2260
+#
+--disable_warnings
+drop procedure if exists bug2260|
+--enable_warnings
+create procedure bug2260()
+begin
+ declare v1 int;
+ declare c1 cursor for select data from t1;
+ declare continue handler for not found set @x2 = 1;
+
+ open c1;
+ fetch c1 into v1;
+ set @x2 = 2;
+ close c1;
+end|
+
+call bug2260()|
+select @x2|
+drop procedure bug2260|
+
+#
+# BUG#2267
+#
+# NOTE: This test case will be fixed as soon as Monty
+# will allow to open mysql.proc table under LOCK TABLES
+# without mentioning in lock list.
+#
+# FIXME: Other solution would be to use preopened proc table
+# instead of opening it anew.
+#
+--disable_parsing
+--disable_warnings
+drop procedure if exists bug2267_1|
+--enable_warnings
+create procedure bug2267_1()
+begin
+ show procedure status;
+end|
+
+--disable_warnings
+drop procedure if exists bug2267_2|
+--enable_warnings
+create procedure bug2267_2()
+begin
+ show function status;
+end|
+
+--disable_warnings
+drop procedure if exists bug2267_3|
+--enable_warnings
+create procedure bug2267_3()
+begin
+ show create procedure bug2267_1;
+end|
+
+--disable_warnings
+drop procedure if exists bug2267_4|
+--enable_warnings
+create procedure bug2267_4()
+begin
+ show create function fac;
+end|
+
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+call bug2267_1()|
+--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
+call bug2267_2()|
+call bug2267_3()|
+call bug2267_4()|
+
+drop procedure bug2267_1|
+drop procedure bug2267_2|
+drop procedure bug2267_3|
+drop procedure bug2267_4|
+--enable_parsing
+
+#
+# BUG#2227
+#
+--disable_warnings
+drop procedure if exists bug2227|
+--enable_warnings
+create procedure bug2227(x int)
+begin
+ declare y float default 2.6;
+ declare z char(16) default "zzz";
+
+ select 1.3, x, y, 42, z;
+end|
+
+call bug2227(9)|
+drop procedure bug2227|
+
+#
+# BUG#2614
+#
+# QQ The second insert doesn't work with temporary tables (it was an
+# QQ ordinary table before we changed the locking scheme). It results
+# QQ in an error: 1137: Can't reopen table: 't3'
+# QQ which is a known limit with temporary tables.
+# QQ For this reason we can't run this test any more (i.e., if we modify
+# QQ it, it's no longer a test case for the bug), but we keep it here
+# QQ anyway, for tracability.
+--disable_parsing
+--disable_warnings
+drop procedure if exists bug2614|
+--enable_warnings
+create procedure bug2614()
+begin
+ drop temporary table if exists t3;
+ create temporary table t3 (id int default '0' not null);
+ insert into t3 select 12;
+ insert into t3 select * from t3;
+end|
+
+--disable_warnings
+call bug2614()|
+--enable_warnings
+call bug2614()|
+drop temporary table t3|
+drop procedure bug2614|
+--enable_parsing
+
+#
+# BUG#2674
+#
+--disable_warnings
+drop function if exists bug2674|
+--enable_warnings
+create function bug2674() returns int
+ return @@sort_buffer_size|
+
+set @osbs = @@sort_buffer_size|
+set @@sort_buffer_size = 262000|
+select bug2674()|
+drop function bug2674|
+set @@sort_buffer_size = @osbs|
+
+#
+# BUG#3259
+#
+--disable_warnings
+drop procedure if exists bug3259_1 |
+--enable_warnings
+create procedure bug3259_1 () begin end|
+--disable_warnings
+drop procedure if exists BUG3259_2 |
+--enable_warnings
+create procedure BUG3259_2 () begin end|
+--disable_warnings
+drop procedure if exists Bug3259_3 |
+--enable_warnings
+create procedure Bug3259_3 () begin end|
+
+call BUG3259_1()|
+call BUG3259_1()|
+call bug3259_2()|
+call Bug3259_2()|
+call bug3259_3()|
+call bUG3259_3()|
+
+drop procedure bUg3259_1|
+drop procedure BuG3259_2|
+drop procedure BUG3259_3|
+
+#
+# BUG#2772
+#
+--disable_warnings
+drop function if exists bug2772|
+--enable_warnings
+create function bug2772() returns char(10) character set latin2
+ return 'a'|
+
+select bug2772()|
+drop function bug2772|
+
+#
+# BUG#2776
+#
+--disable_warnings
+drop procedure if exists bug2776_1|
+--enable_warnings
+create procedure bug2776_1(out x int)
+begin
+ declare v int;
+
+ set v = default;
+ set x = v;
+end|
+
+--disable_warnings
+drop procedure if exists bug2776_2|
+--enable_warnings
+create procedure bug2776_2(out x int)
+begin
+ declare v int default 42;
+
+ set v = default;
+ set x = v;
+end|
+
+set @x = 1|
+call bug2776_1(@x)|
+select @x|
+call bug2776_2(@x)|
+select @x|
+drop procedure bug2776_1|
+drop procedure bug2776_2|
+
+#
+# BUG#2780
+#
+create table t3 (s1 smallint)|
+
+insert into t3 values (123456789012)|
+
+--disable_warnings
+drop procedure if exists bug2780|
+--enable_warnings
+create procedure bug2780()
+begin
+ declare exit handler for sqlwarning set @x = 1;
+
+ set @x = 0;
+ insert into t3 values (123456789012);
+ insert into t3 values (0);
+end|
+
+call bug2780()|
+select @x|
+select * from t3|
+
+drop procedure bug2780|
+drop table t3|
+
+#
+# BUG#1863
+#
+create table t3 (content varchar(10) )|
+insert into t3 values ("test1")|
+insert into t3 values ("test2")|
+create table t4 (f1 int, rc int, t3 int)|
+
+--disable_warnings
+drop procedure if exists bug1863|
+--enable_warnings
+create procedure bug1863(in1 int)
+begin
+
+ declare ind int default 0;
+ declare t1 int;
+ declare t2 int;
+ declare t3 int;
+
+ declare rc int default 0;
+ declare continue handler for 1065 set rc = 1;
+
+ drop temporary table if exists temp_t1;
+ create temporary table temp_t1 (
+ f1 int auto_increment, f2 varchar(20), primary key (f1)
+ );
+
+ insert into temp_t1 (f2) select content from t3;
+
+ select f2 into t3 from temp_t1 where f1 = 10;
+
+ if (rc) then
+ insert into t4 values (1, rc, t3);
+ end if;
+
+ insert into t4 values (2, rc, t3);
+
+end|
+
+call bug1863(10)|
+call bug1863(10)|
+select * from t4|
+
+drop procedure bug1863|
+drop temporary table temp_t1;
+drop table t3, t4|
+
+#
+# BUG#2656
+#
+
+create table t3 (
+ OrderID int not null,
+ MarketID int,
+ primary key (OrderID)
+)|
+
+create table t4 (
+ MarketID int not null,
+ Market varchar(60),
+ Status char(1),
+ primary key (MarketID)
+)|
+
+insert t3 (OrderID,MarketID) values (1,1)|
+insert t3 (OrderID,MarketID) values (2,2)|
+insert t4 (MarketID,Market,Status) values (1,"MarketID One","A")|
+insert t4 (MarketID,Market,Status) values (2,"MarketID Two","A")|
+
+--disable_warnings
+drop procedure if exists bug2656_1|
+--enable_warnings
+create procedure bug2656_1()
+begin
+ select
+ m.Market
+ from t4 m JOIN t3 o
+ ON o.MarketID != 1 and o.MarketID = m.MarketID;
+end |
+
+--disable_warnings
+drop procedure if exists bug2656_2|
+--enable_warnings
+create procedure bug2656_2()
+begin
+ select
+ m.Market
+ from
+ t4 m, t3 o
+ where
+ m.MarketID != 1 and m.MarketID = o.MarketID;
+
+end |
+
+call bug2656_1()|
+call bug2656_1()|
+call bug2656_2()|
+call bug2656_2()|
+drop procedure bug2656_1|
+drop procedure bug2656_2|
+drop table t3, t4|
+
+
+#
+# BUG#3426
+#
+--disable_warnings
+drop procedure if exists bug3426|
+--enable_warnings
+create procedure bug3426(in_time int unsigned, out x int)
+begin
+ if in_time is null then
+ set @stamped_time=10;
+ set x=1;
+ else
+ set @stamped_time=in_time;
+ set x=2;
+ end if;
+end|
+
+call bug3426(1000, @i)|
+select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
+call bug3426(NULL, @i)|
+select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
+# Clear SP cache
+alter procedure bug3426 sql security invoker|
+call bug3426(NULL, @i)|
+select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
+call bug3426(1000, @i)|
+select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time|
+
+drop procedure bug3426|
+
+#
+# BUG#3448
+#
+--disable_warnings
+create table t3 (
+ a int primary key,
+ ach char(1)
+) engine = innodb|
+
+create table t4 (
+ b int primary key ,
+ bch char(1)
+) engine = innodb|
+--enable_warnings
+
+insert into t3 values (1 , 'aCh1' ) , ('2' , 'aCh2')|
+insert into t4 values (1 , 'bCh1' )|
+
+--disable_warnings
+drop procedure if exists bug3448|
+--enable_warnings
+create procedure bug3448()
+ select * from t3 inner join t4 on t3.a = t4.b|
+
+select * from t3 inner join t4 on t3.a = t4.b|
+call bug3448()|
+call bug3448()|
+
+drop procedure bug3448|
+drop table t3, t4|
+
+
+#
+# BUG#3734
+#
+create table t3 (
+ id int unsigned auto_increment not null primary key,
+ title VARCHAR(200),
+ body text,
+ fulltext (title,body)
+)|
+
+insert into t3 (title,body) values
+ ('MySQL Tutorial','DBMS stands for DataBase ...'),
+ ('How To Use MySQL Well','After you went through a ...'),
+ ('Optimizing MySQL','In this tutorial we will show ...'),
+ ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
+ ('MySQL vs. YourSQL','In the following database comparison ...'),
+ ('MySQL Security','When configured properly, MySQL ...')|
+
+--disable_warnings
+drop procedure if exists bug3734 |
+--enable_warnings
+create procedure bug3734 (param1 varchar(100))
+ select * from t3 where match (title,body) against (param1)|
+
+call bug3734('database')|
+call bug3734('Security')|
+
+drop procedure bug3734|
+drop table t3|
+
+#
+# BUG#3863
+#
+--disable_warnings
+drop procedure if exists bug3863|
+--enable_warnings
+create procedure bug3863()
+begin
+ set @a = 0;
+ while @a < 5 do
+ set @a = @a + 1;
+ end while;
+end|
+
+call bug3863()|
+select @a|
+call bug3863()|
+select @a|
+
+drop procedure bug3863|
+
+#
+# BUG#2460
+#
+
+create table t3 (
+ id int(10) unsigned not null default 0,
+ rid int(10) unsigned not null default 0,
+ msg text not null,
+ primary key (id),
+ unique key rid (rid, id)
+)|
+
+--disable_warnings
+drop procedure if exists bug2460_1|
+--enable_warnings
+create procedure bug2460_1(in v int)
+begin
+ ( select n0.id from t3 as n0 where n0.id = v )
+ union
+ ( select n0.id from t3 as n0, t3 as n1
+ where n0.id = n1.rid and n1.id = v )
+ union
+ ( select n0.id from t3 as n0, t3 as n1, t3 as n2
+ where n0.id = n1.rid and n1.id = n2.rid and n2.id = v );
+end|
+
+call bug2460_1(2)|
+call bug2460_1(2)|
+insert into t3 values (1, 1, 'foo'), (2, 1, 'bar'), (3, 1, 'zip zap')|
+call bug2460_1(2)|
+call bug2460_1(2)|
+
+--disable_warnings
+drop procedure if exists bug2460_2|
+--enable_warnings
+create procedure bug2460_2()
+begin
+ drop table if exists t3;
+ create temporary table t3 (s1 int);
+ insert into t3 select 1 union select 1;
+end|
+
+call bug2460_2()|
+call bug2460_2()|
+select * from t3|
+
+drop procedure bug2460_1|
+drop procedure bug2460_2|
+drop table t3|
+
+
+#
+# BUG#2564
+#
+set @@sql_mode = ''|
+--disable_warnings
+drop procedure if exists bug2564_1|
+--enable_warnings
+create procedure bug2564_1()
+ comment 'Joe''s procedure'
+ insert into `t1` values ("foo", 1)|
+
+set @@sql_mode = 'ANSI_QUOTES'|
+--disable_warnings
+drop procedure if exists bug2564_2|
+--enable_warnings
+create procedure bug2564_2()
+ insert into "t1" values ('foo', 1)|
+
+delimiter $|
+set @@sql_mode = ''$
+--disable_warnings
+drop function if exists bug2564_3$
+--enable_warnings
+create function bug2564_3(x int, y int) returns int
+ return x || y$
+
+set @@sql_mode = 'ANSI'$
+--disable_warnings
+drop function if exists bug2564_4$
+--enable_warnings
+create function bug2564_4(x int, y int) returns int
+ return x || y$
+delimiter |$
+
+set @@sql_mode = ''|
+show create procedure bug2564_1|
+show create procedure bug2564_2|
+show create function bug2564_3|
+show create function bug2564_4|
+
+drop procedure bug2564_1|
+drop procedure bug2564_2|
+drop function bug2564_3|
+drop function bug2564_4|
+
+#
+# BUG#3132
+#
+--disable_warnings
+drop function if exists bug3132|
+--enable_warnings
+create function bug3132(s char(20)) returns char(50)
+ return concat('Hello, ', s, '!')|
+
+select bug3132('Bob') union all select bug3132('Judy')|
+drop function bug3132|
+
+#
+# BUG#3843
+#
+--disable_warnings
+drop procedure if exists bug3843|
+--enable_warnings
+create procedure bug3843()
+ analyze table t1|
+
+# Testing for packets out of order
+call bug3843()|
+call bug3843()|
+select 1+2|
+
+drop procedure bug3843|
+
+#
+# BUG#3368
+#
+create table t3 ( s1 char(10) )|
+insert into t3 values ('a'), ('b')|
+
+--disable_warnings
+drop procedure if exists bug3368|
+--enable_warnings
+create procedure bug3368(v char(10))
+begin
+ select group_concat(v) from t3;
+end|
+
+call bug3368('x')|
+call bug3368('yz')|
+drop procedure bug3368|
+drop table t3|
+
+#
+# BUG#4579
+#
+create table t3 (f1 int, f2 int)|
+insert into t3 values (1,1)|
+
+--disable_warnings
+drop procedure if exists bug4579_1|
+--enable_warnings
+create procedure bug4579_1 ()
+begin
+ declare sf1 int;
+
+ select f1 into sf1 from t3 where f1=1 and f2=1;
+ update t3 set f2 = f2 + 1 where f1=1 and f2=1;
+ call bug4579_2();
+end|
+
+--disable_warnings
+drop procedure if exists bug4579_2|
+--enable_warnings
+create procedure bug4579_2 ()
+begin
+end|
+
+call bug4579_1()|
+call bug4579_1()|
+call bug4579_1()|
+
+drop procedure bug4579_1|
+drop procedure bug4579_2|
+drop table t3|
+
+#
+# BUG#2773: Function's data type ignored in stored procedures
+#
+--disable_warnings
+drop procedure if exists bug2773|
+--enable_warnings
+
+create function bug2773() returns int return null|
+create table t3 as select bug2773()|
+show create table t3|
+drop table t3|
+drop function bug2773|
+
+#
+# BUG#3788: Stored procedure packet error
+#
+--disable_warnings
+drop procedure if exists bug3788|
+--enable_warnings
+
+create function bug3788() returns date return cast("2005-03-04" as date)|
+select bug3788()|
+drop function bug3788|
+
+create function bug3788() returns binary(5) return 5|
+select bug3788()|
+drop function bug3788|
+
+
+#
+# BUG#4726
+#
+create table t3 (f1 int, f2 int, f3 int)|
+insert into t3 values (1,1,1)|
+
+--disable_warnings
+drop procedure if exists bug4726|
+--enable_warnings
+create procedure bug4726()
+begin
+ declare tmp_o_id INT;
+ declare tmp_d_id INT default 1;
+
+ while tmp_d_id <= 2 do
+ begin
+ select f1 into tmp_o_id from t3 where f2=1 and f3=1;
+ set tmp_d_id = tmp_d_id + 1;
+ end;
+ end while;
+end|
+
+call bug4726()|
+call bug4726()|
+call bug4726()|
+
+drop procedure bug4726|
+drop table t3|
+
+#
+# BUG#4318
+#
+
+--disable_parsing # Don't know if HANDLER commands can work with SPs, or at all..
+create table t3 (s1 int)|
+insert into t3 values (3), (4)|
+
+--disable_warnings
+drop procedure if exists bug4318|
+--enable_warnings
+create procedure bug4318()
+ handler t3 read next|
+
+handler t3 open|
+# Expect no results, as tables are closed, but there shouldn't be any errors
+call bug4318()|
+call bug4318()|
+handler t3 close|
+
+drop procedure bug4318|
+drop table t3|
+--enable_parsing
+
+#
+# BUG#4902: Stored procedure with SHOW WARNINGS leads to packet error
+#
+# Added tests for most other show commands we could find too.
+# (Skipping those already tested, and the ones depending on optional handlers.)
+#
+# Note: This will return a large number of results of different formats,
+# which makes it impossible to filter with --replace_column.
+# It's possible that some of these are not deterministic across
+# platforms. If so, just remove the offending command.
+#
+--disable_warnings
+drop procedure if exists bug4902|
+--enable_warnings
+create procedure bug4902()
+begin
+ show charset like 'foo';
+ show collation like 'foo';
+ show column types;
+ show create table t1;
+ show create database test;
+ show databases like 'foo';
+ show errors;
+ show columns from t1;
+ show grants for 'root'@'localhost';
+ show keys from t1;
+ show open tables like 'foo';
+ show privileges;
+ show status like 'foo';
+ show tables like 'foo';
+ show variables like 'foo';
+ show warnings;
+end|
+--disable_parsing
+show binlog events;
+show storage engines;
+show master status;
+show slave hosts;
+show slave status;
+--enable_parsing
+
+call bug4902()|
+call bug4902()|
+
+drop procedure bug4902|
+
+# We need separate SP for SHOW PROCESSLIST since we want use replace_column
+--disable_warnings
+drop procedure if exists bug4902_2|
+--enable_warnings
+create procedure bug4902_2()
+begin
+ show processlist;
+end|
+--replace_column 1 # 6 # 3 localhost
+call bug4902_2()|
+--replace_column 1 # 6 # 3 localhost
+call bug4902_2()|
+drop procedure bug4902_2|
+
+#
+# BUG#4904
+#
+--disable_warnings
+drop procedure if exists bug4904|
+--enable_warnings
+create procedure bug4904()
+begin
+ declare continue handler for sqlstate 'HY000' begin end;
+
+ create table t2 as select * from t3;
+end|
+
+-- error 1146
+call bug4904()|
+
+drop procedure bug4904|
+
+create table t3 (s1 char character set latin1, s2 char character set latin2)|
+
+--disable_warnings
+drop procedure if exists bug4904|
+--enable_warnings
+create procedure bug4904 ()
+begin
+ declare continue handler for sqlstate 'HY000' begin end;
+
+ select s1 from t3 union select s2 from t3;
+end|
+
+call bug4904()|
+
+drop procedure bug4904|
+drop table t3|
+
+#
+# BUG#336
+#
+--disable_warnings
+drop procedure if exists bug336|
+--enable_warnings
+create procedure bug336(out y int)
+begin
+ declare x int;
+ set x = (select sum(t.data) from test.t1 t);
+ set y = x;
+end|
+
+insert into t1 values ("a", 2), ("b", 3)|
+call bug336(@y)|
+select @y|
+delete from t1|
+drop procedure bug336|
+
+#
+# BUG#3157
+#
+--disable_warnings
+drop procedure if exists bug3157|
+--enable_warnings
+create procedure bug3157()
+begin
+ if exists(select * from t1) then
+ set @n= @n + 1;
+ end if;
+ if (select count(*) from t1) then
+ set @n= @n + 1;
+ end if;
+end|
+
+set @n = 0|
+insert into t1 values ("a", 1)|
+call bug3157()|
+select @n|
+delete from t1|
+drop procedure bug3157|
+
+#
+# BUG#5251: mysql changes creation time of a procedure/function when altering
+#
+--disable_warnings
+drop procedure if exists bug5251|
+--enable_warnings
+create procedure bug5251()
+begin
+end|
+
+select created into @c1 from mysql.proc
+ where db='test' and name='bug5251'|
+--sleep 2
+alter procedure bug5251 comment 'foobar'|
+select count(*) from mysql.proc
+ where db='test' and name='bug5251' and created = @c1|
+
+drop procedure bug5251|
+
+#
+# BUG#5279: Stored procedure packets out of order if CHECKSUM TABLE
+#
+--disable_warnings
+drop procedure if exists bug5251|
+--enable_warnings
+create procedure bug5251()
+ checksum table t1|
+
+call bug5251()|
+call bug5251()|
+drop procedure bug5251|
+
+#
+# BUG#5287: Stored procedure crash if leave outside loop
+#
+--disable_warnings
+drop procedure if exists bug5287|
+--enable_warnings
+create procedure bug5287(param1 int)
+label1:
+ begin
+ declare c cursor for select 5;
+
+ loop
+ if param1 >= 0 then
+ leave label1;
+ end if;
+ end loop;
+end|
+call bug5287(1)|
+drop procedure bug5287|
+
+
+#
+# BUG#5307: Stored procedure allows statement after BEGIN ... END
+#
+--disable_warnings
+drop procedure if exists bug5307|
+--enable_warnings
+create procedure bug5307()
+begin
+end; set @x = 3|
+
+call bug5307()|
+select @x|
+drop procedure bug5307|
+
+#
+# BUG#5258: Stored procedure modified date is 0000-00-00
+# (This was a design flaw)
+--disable_warnings
+drop procedure if exists bug5258|
+--enable_warnings
+create procedure bug5258()
+begin
+end|
+
+--disable_warnings
+drop procedure if exists bug5258_aux|
+--enable_warnings
+create procedure bug5258_aux()
+begin
+ declare c, m char(19);
+
+ select created,modified into c,m from mysql.proc where name = 'bug5258';
+ if c = m then
+ select 'Ok';
+ else
+ select c, m;
+ end if;
+end|
+
+call bug5258_aux()|
+
+drop procedure bug5258|
+drop procedure bug5258_aux|
+
+#
+# BUG#4487: Stored procedure connection aborted if uninitialized char
+#
+--disable_warnings
+drop function if exists bug4487|
+--enable_warnings
+create function bug4487() returns char
+begin
+ declare v char;
+ return v;
+end|
+
+select bug4487()|
+drop function bug4487|
+
+
+#
+# BUG#4941: Stored procedure crash fetching null value into variable.
+#
+--disable_warnings
+drop procedure if exists bug4941|
+--enable_warnings
+--disable_warnings
+drop procedure if exists bug4941|
+--enable_warnings
+create procedure bug4941(out x int)
+begin
+ declare c cursor for select i from t2 limit 1;
+ open c;
+ fetch c into x;
+ close c;
+end|
+
+insert into t2 values (null, null, null)|
+set @x = 42|
+call bug4941(@x)|
+select @x|
+delete from t1|
+drop procedure bug4941|
+
+
+#
+# BUG#3583: query cache doesn't work for stored procedures
+#
+--disable_warnings
+drop procedure if exists bug3583|
+--enable_warnings
+--disable_warnings
+drop procedure if exists bug3583|
+--enable_warnings
+create procedure bug3583()
+begin
+ declare c int;
+
+ select * from t1;
+ select count(*) into c from t1;
+ select c;
+end|
+
+insert into t1 values ("x", 3), ("y", 5)|
+set @x = @@query_cache_size|
+set global query_cache_size = 10*1024*1024|
+
+flush status|
+flush query cache|
+show status like 'Qcache_hits'|
+call bug3583()|
+show status like 'Qcache_hits'|
+call bug3583()|
+call bug3583()|
+show status like 'Qcache_hits'|
+
+set global query_cache_size = @x|
+flush status|
+flush query cache|
+delete from t1|
+drop procedure bug3583|
+
+#
+# BUG#4905: Stored procedure doesn't clear for "Rows affected"
+#
+--disable_warnings
+drop procedure if exists bug4905|
+--enable_warnings
+
+create table t3 (s1 int,primary key (s1))|
+
+--disable_warnings
+drop procedure if exists bug4905|
+--enable_warnings
+create procedure bug4905()
+begin
+ declare v int;
+ declare continue handler for sqlstate '23000' set v = 5;
+
+ insert into t3 values (1);
+end|
+
+call bug4905()|
+select row_count()|
+call bug4905()|
+select row_count()|
+call bug4905()|
+select row_count()|
+select * from t3|
+
+drop procedure bug4905|
+drop table t3|
+
+#
+# BUG#6022: Stored procedure shutdown problem with self-calling function.
+#
+
+--disable_parsing # until we implement support for recursive stored functions.
+--disable_warnings
+drop function if exists bug6022|
+--enable_warnings
+
+--disable_warnings
+drop function if exists bug6022|
+--enable_warnings
+create function bug6022(x int) returns int
+begin
+ if x < 0 then
+ return 0;
+ else
+ return bug6022(x-1);
+ end if;
+end|
+
+select bug6022(5)|
+drop function bug6022|
+--enable_parsing
+
+#
+# BUG#6029: Stored procedure specific handlers should have priority
+#
+--disable_warnings
+drop procedure if exists bug6029|
+--enable_warnings
+
+--disable_warnings
+drop procedure if exists bug6029|
+--enable_warnings
+create procedure bug6029()
+begin
+ declare exit handler for 1136 select '1136';
+ declare exit handler for sqlstate '23000' select 'sqlstate 23000';
+ declare continue handler for sqlexception select 'sqlexception';
+
+ insert into t3 values (1);
+ insert into t3 values (1,2);
+end|
+
+create table t3 (s1 int, primary key (s1))|
+insert into t3 values (1)|
+call bug6029()|
+delete from t3|
+call bug6029()|
+
+drop procedure bug6029|
+drop table t3|
+
+#
+# BUG#8540: Local variable overrides an alias
+#
+--disable_warnings
+drop procedure if exists bug8540|
+--enable_warnings
+
+create procedure bug8540()
+begin
+ declare x int default 1;
+ select x as y, x+0 as z;
+end|
+
+call bug8540()|
+drop procedure bug8540|
+
+#
+# BUG#6642: Stored procedure crash if expression with set function
+#
+create table t3 (s1 int)|
+
+--disable_warnings
+drop procedure if exists bug6642|
+--enable_warnings
+
+create procedure bug6642()
+ select abs(count(s1)) from t3|
+
+call bug6642()|
+call bug6642()|
+drop procedure bug6642|
+
+#
+# BUG#7013: Stored procedure crash if group by ... with rollup
+#
+insert into t3 values (0),(1)|
+--disable_warnings
+drop procedure if exists bug7013|
+--enable_warnings
+create procedure bug7013()
+ select s1,count(s1) from t3 group by s1 with rollup|
+call bug7013()|
+call bug7013()|
+drop procedure bug7013|
+
+#
+# BUG#7743: 'Lost connection to MySQL server during query' on Stored Procedure
+#
+--disable_warnings
+drop table if exists t4|
+--enable_warnings
+create table t4 (
+ a mediumint(8) unsigned not null auto_increment,
+ b smallint(5) unsigned not null,
+ c char(32) not null,
+ primary key (a)
+) engine=myisam default charset=latin1|
+insert into t4 values (1, 2, 'oneword')|
+insert into t4 values (2, 2, 'anotherword')|
+
+--disable_warnings
+drop procedure if exists bug7743|
+--enable_warnings
+create procedure bug7743 ( searchstring char(28) )
+begin
+ declare var mediumint(8) unsigned;
+ select a into var from t4 where b = 2 and c = binary searchstring limit 1;
+ select var;
+end|
+
+call bug7743("oneword")|
+call bug7743("OneWord")|
+call bug7743("anotherword")|
+call bug7743("AnotherWord")|
+drop procedure bug7743|
+drop table t4|
+
+#
+# BUG#7992: SELECT .. INTO variable .. within Stored Procedure crashes
+# the server
+#
+delete from t3|
+insert into t3 values(1)|
+drop procedure if exists bug7992_1|
+drop procedure if exists bug7992_2|
+create procedure bug7992_1()
+begin
+ declare i int;
+ select max(s1)+1 into i from t3;
+end|
+create procedure bug7992_2()
+ insert into t3 (s1) select max(t4.s1)+1 from t3 as t4|
+
+call bug7992_1()|
+call bug7992_1()|
+call bug7992_2()|
+call bug7992_2()|
+
+drop procedure bug7992_1|
+drop procedure bug7992_2|
+drop table t3|
+
+#
+# BUG#8116: calling simple stored procedure twice in a row results
+# in server crash
+#
+create table t3 ( userid bigint(20) not null default 0 )|
+
+--disable_warnings
+drop procedure if exists bug8116|
+--enable_warnings
+create procedure bug8116(in _userid int)
+ select * from t3 where userid = _userid|
+
+call bug8116(42)|
+call bug8116(42)|
+drop procedure bug8116|
+drop table t3|
+
+#
+# BUG#6857: current_time() in STORED PROCEDURES
+#
+--disable_warnings
+drop procedure if exists bug6857|
+--enable_warnings
+create procedure bug6857(counter int)
+begin
+ declare t0, t1 int;
+ declare plus bool default 0;
+
+ set t0 = current_time();
+ while counter > 0 do
+ set counter = counter - 1;
+ end while;
+ set t1 = current_time();
+ if t1 > t0 then
+ set plus = 1;
+ end if;
+ select plus;
+end|
+
+# QQ: This is currently disabled. Not only does it slow down a normal test
+# run, it makes running with valgrind (or similar tools) extremely
+# painful.
+# Make sure this takes at least one second on all machines in all builds.
+# 30000 makes it about 3 seconds on an old 1.1GHz linux.
+#call bug6857(300000)|
+
+drop procedure bug6857|
+
+#
+# BUG#8757: Stored Procedures: Scope of Begin and End Statements do not
+# work properly.
+--disable_warnings
+drop procedure if exists bug8757|
+--enable_warnings
+create procedure bug8757()
+begin
+ declare x int;
+ declare c1 cursor for select data from t1 limit 1;
+
+ begin
+ declare y int;
+ declare c2 cursor for select i from t2 limit 1;
+
+ open c2;
+ fetch c2 into y;
+ close c2;
+ select 2,y;
+ end;
+ open c1;
+ fetch c1 into x;
+ close c1;
+ select 1,x;
+end|
+
+delete from t1|
+delete from t2|
+insert into t1 values ("x", 1)|
+insert into t2 values ("y", 2, 0.0)|
+
+call bug8757()|
+
+delete from t1|
+delete from t2|
+drop procedure bug8757|
+
+
+#
+# BUG#8762: Stored Procedures: Inconsistent behavior
+# of DROP PROCEDURE IF EXISTS statement.
+--disable_warnings
+drop procedure if exists bug8762|
+--enable_warnings
+# Doesn't exist
+drop procedure if exists bug8762; create procedure bug8762() begin end|
+# Does exist
+drop procedure if exists bug8762; create procedure bug8762() begin end|
+drop procedure bug8762|
+
+
+#
+# BUG#5240: Stored procedure crash if function has cursor declaration
+#
+--disable_warnings
+drop function if exists bug5240|
+--enable_warnings
+create function bug5240 () returns int
+begin
+ declare x int;
+ declare c cursor for select data from t1 limit 1;
+
+ open c;
+ fetch c into x;
+ close c;
+ return x;
+end|
+
+delete from t1|
+insert into t1 values ("answer", 42)|
+select id, bug5240() from t1|
+drop function bug5240|
+
+#
+# BUG#5278: Stored procedure packets out of order if SET PASSWORD.
+#
+--disable_warnings
+drop function if exists bug5278|
+--enable_warnings
+create function bug5278 () returns char
+begin
+ SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
+ return 'okay';
+end|
+
+--error 1133
+select bug5278()|
+--error 1133
+select bug5278()|
+drop function bug5278|
+
+#
+# BUG#7992: rolling back temporary Item tree changes in SP
+#
+--disable_warnings
+drop procedure if exists p1|
+--enable_warnings
+create table t3(id int)|
+insert into t3 values(1)|
+create procedure bug7992()
+begin
+ declare i int;
+ select max(id)+1 into i from t3;
+end|
+
+call bug7992()|
+call bug7992()|
+drop procedure bug7992|
+drop table t3|
+delimiter ;|
+
+#
+# BUG#8849: problem with insert statement with table alias's
+#
+# Rolling back changes to AND/OR structure of ON and WHERE clauses in SP
+#
+
+delimiter |;
+create table t3 (
+ lpitnumber int(11) default null,
+ lrecordtype int(11) default null
+)|
+
+create table t4 (
+ lbsiid int(11) not null default '0',
+ ltradingmodeid int(11) not null default '0',
+ ltradingareaid int(11) not null default '0',
+ csellingprice decimal(19,4) default null,
+ primary key (lbsiid,ltradingmodeid,ltradingareaid)
+)|
+
+create table t5 (
+ lbsiid int(11) not null default '0',
+ ltradingareaid int(11) not null default '0',
+ primary key (lbsiid,ltradingareaid)
+)|
+
+--disable_warnings
+drop procedure if exists bug8849|
+--enable_warnings
+create procedure bug8849()
+begin
+ insert into t5
+ (
+ t5.lbsiid,
+ t5.ltradingareaid
+ )
+ select distinct t3.lpitnumber, t4.ltradingareaid
+ from
+ t4 join t3 on
+ t3.lpitnumber = t4.lbsiid
+ and t3.lrecordtype = 1
+ left join t4 as price01 on
+ price01.lbsiid = t4.lbsiid and
+ price01.ltradingmodeid = 1 and
+ t4.ltradingareaid = price01.ltradingareaid;
+end|
+
+call bug8849()|
+call bug8849()|
+call bug8849()|
+drop procedure bug8849|
+drop tables t3,t4,t5|
+
+#
+# BUG#8937: Stored Procedure: AVG() works as SUM() in SELECT ... INTO statement
+#
+--disable_warnings
+drop procedure if exists bug8937|
+--enable_warnings
+create procedure bug8937()
+begin
+ declare s,x,y,z int;
+ declare a float;
+
+ select sum(data),avg(data),min(data),max(data) into s,x,y,z from t1;
+ select s,x,y,z;
+ select avg(data) into a from t1;
+ select a;
+end|
+
+delete from t1|
+insert into t1 (data) values (1), (2), (3), (4), (6)|
+call bug8937()|
+
+drop procedure bug8937|
+delete from t1|
+
+
+#
+# BUG#6900: Stored procedure inner handler ignored
+# BUG#9074: STORED PROC: The scope of every handler declared is not
+# properly applied
+#
+--disable_warnings
+drop procedure if exists bug6900|
+drop procedure if exists bug9074|
+drop procedure if exists bug6900_9074|
+--enable_warnings
+
+create table t3 (w char unique, x char)|
+insert into t3 values ('a', 'b')|
+
+create procedure bug6900()
+begin
+ declare exit handler for sqlexception select '1';
+
+ begin
+ declare exit handler for sqlexception select '2';
+
+ insert into t3 values ('x', 'y', 'z');
+ end;
+end|
+
+create procedure bug9074()
+begin
+ declare x1, x2, x3, x4, x5, x6 int default 0;
+
+ begin
+ declare continue handler for sqlstate '23000' set x5 = 1;
+
+ insert into t3 values ('a', 'b');
+ set x6 = 1;
+ end;
+
+ begin1_label:
+ begin
+ declare continue handler for sqlstate '23000' set x1 = 1;
+
+ insert into t3 values ('a', 'b');
+ set x2 = 1;
+
+ begin2_label:
+ begin
+ declare exit handler for sqlstate '23000' set x3 = 1;
+
+ set x4= 1;
+ insert into t3 values ('a','b');
+ set x4= 0;
+ end begin2_label;
+ end begin1_label;
+
+ select x1, x2, x3, x4, x5, x6;
+end|
+
+create procedure bug6900_9074(z int)
+begin
+ declare exit handler for sqlstate '23000' select '23000';
+
+ begin
+ declare exit handler for sqlexception select 'sqlexception';
+
+ if z = 1 then
+ insert into t3 values ('a', 'b');
+ else
+ insert into t3 values ('x', 'y', 'z');
+ end if;
+ end;
+end|
+
+call bug6900()|
+call bug9074()|
+call bug6900_9074(0)|
+call bug6900_9074(1)|
+
+drop procedure bug6900|
+drop procedure bug9074|
+drop procedure bug6900_9074|
+drop table t3|
+
+
+#
+# BUG#7185: Stored procedure crash if identifier is AVG
+#
+--disable_warnings
+drop procedure if exists avg|
+--enable_warnings
+create procedure avg ()
+begin
+end|
+
+call avg ()|
+drop procedure avg|
+
+
+#
+# BUG#6129: Stored procedure won't display @@sql_mode value
+#
+--disable_warnings
+drop procedure if exists bug6129|
+--enable_warnings
+set @old_mode= @@sql_mode;
+set @@sql_mode= "ERROR_FOR_DIVISION_BY_ZERO";
+create procedure bug6129()
+ select @@sql_mode|
+call bug6129()|
+set @@sql_mode= "NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO"|
+call bug6129()|
+set @@sql_mode= "NO_ZERO_IN_DATE"|
+call bug6129()|
+set @@sql_mode=@old_mode;
+
+drop procedure bug6129|
+
+
+#
+# BUG#9856: Stored procedures: crash if handler for sqlexception, not found
+#
+--disable_warnings
+drop procedure if exists bug9856|
+--enable_warnings
+create procedure bug9856()
+begin
+ declare v int;
+ declare c cursor for select data from t1;
+ declare exit handler for sqlexception, not found select '16';
+
+ open c;
+ fetch c into v;
+ select v;
+end|
+
+delete from t1|
+call bug9856()|
+call bug9856()|
+drop procedure bug9856|
+
+
+#
+# BUG##9674: Stored Procs: Using declared vars in algebric operation causes
+# system crash.
+#
+--disable_warnings
+drop procedure if exists bug9674_1|
+drop procedure if exists bug9674_2|
+--enable_warnings
+create procedure bug9674_1(out arg int)
+begin
+ declare temp_in1 int default 0;
+ declare temp_fl1 int default 0;
+
+ set temp_in1 = 100;
+ set temp_fl1 = temp_in1/10;
+ set arg = temp_fl1;
+end|
+
+create procedure bug9674_2()
+begin
+ declare v int default 100;
+
+ select v/10;
+end|
+
+call bug9674_1(@sptmp)|
+call bug9674_1(@sptmp)|
+select @sptmp|
+call bug9674_2()|
+call bug9674_2()|
+drop procedure bug9674_1|
+drop procedure bug9674_2|
+
+
+#
+# BUG#9598: stored procedure call within stored procedure overwrites IN variable
+#
+--disable_warnings
+drop procedure if exists bug9598_1|
+drop procedure if exists bug9598_2|
+--enable_warnings
+create procedure bug9598_1(in var_1 char(16),
+ out var_2 integer, out var_3 integer)
+begin
+ set var_2 = 50;
+ set var_3 = 60;
+end|
+
+create procedure bug9598_2(in v1 char(16),
+ in v2 integer,
+ in v3 integer,
+ in v4 integer,
+ in v5 integer)
+begin
+ select v1,v2,v3,v4,v5;
+ call bug9598_1(v1,@tmp1,@tmp2);
+ select v1,v2,v3,v4,v5;
+end|
+
+call bug9598_2('Test',2,3,4,5)|
+select @tmp1, @tmp2|
+
+drop procedure bug9598_1|
+drop procedure bug9598_2|
+
+
+#
+# BUG#9902: Crash with simple stored function using user defined variables
+#
+--disable_warnings
+drop procedure if exists bug9902|
+--enable_warnings
+create function bug9902() returns int(11)
+begin
+ set @x = @x + 1;
+ return @x;
+end|
+
+set @qcs1 = @@query_cache_size|
+set global query_cache_size = 100000|
+set @x = 1|
+insert into t1 values ("qc", 42)|
+select bug9902() from t1|
+select bug9902() from t1|
+select @x|
+
+set global query_cache_size = @qcs1|
+delete from t1|
+drop function bug9902|
+
+
+#
+# BUG#9102: Stored proccedures: function which returns blob causes crash
+#
+--disable_warnings
+drop function if exists bug9102|
+--enable_warnings
+create function bug9102() returns blob return 'a'|
+select bug9102()|
+drop function bug9102|
+
+
+#
+# BUG#7648: Stored procedure crash when invoking a function that returns a bit
+#
+--disable_warnings
+drop function if exists bug7648|
+--enable_warnings
+create function bug7648() returns bit(8) return 'a'|
+select bug7648()|
+drop function bug7648|
+
+
+#
+# BUG#9775: crash if create function that returns enum or set
+#
+--disable_warnings
+drop function if exists bug9775|
+--enable_warnings
+create function bug9775(v1 char(1)) returns enum('a','b') return v1|
+select bug9775('a'),bug9775('b'),bug9775('c')|
+drop function bug9775|
+create function bug9775(v1 int) returns enum('a','b') return v1|
+select bug9775(1),bug9775(2),bug9775(3)|
+drop function bug9775|
+
+create function bug9775(v1 char(1)) returns set('a','b') return v1|
+select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')|
+drop function bug9775|
+create function bug9775(v1 int) returns set('a','b') return v1|
+select bug9775(1),bug9775(2),bug9775(3),bug9775(4)|
+drop function bug9775|
+
+
+#
+# BUG#8861: If Return is a YEAR data type, value is not shown in year format
+#
+--disable_warnings
+drop function if exists bug8861|
+--enable_warnings
+create function bug8861(v1 int) returns year return v1|
+select bug8861(05)|
+set @x = bug8861(05)|
+select @x|
+drop function bug8861|
+
+
+#
+# BUG#9004: Inconsistent behaviour of SP re. warnings
+#
+--disable_warnings
+drop procedure if exists bug9004_1|
+drop procedure if exists bug9004_2|
+--enable_warnings
+create procedure bug9004_1(x char(16))
+begin
+ insert into t1 values (x, 42);
+ insert into t1 values (x, 17);
+end|
+create procedure bug9004_2(x char(16))
+ call bug9004_1(x)|
+
+# Truncation warnings expected...
+call bug9004_1('12345678901234567')|
+call bug9004_2('12345678901234567890')|
+
+delete from t1|
+drop procedure bug9004_1|
+drop procedure bug9004_2|
+
+#
+# BUG#7293: Stored procedure crash with soundex
+#
+--disable_warnings
+drop procedure if exists bug7293|
+--enable_warnings
+insert into t1 values ('secret', 0)|
+create procedure bug7293(p1 varchar(100))
+begin
+ if exists (select id from t1 where soundex(p1)=soundex(id)) then
+ select 'yes';
+ end if;
+end;|
+call bug7293('secret')|
+call bug7293 ('secrete')|
+drop procedure bug7293|
+delete from t1|
+
+
+#
+# BUG#9841: Unexpected read lock when trying to update a view in a
+# stored procedure
+#
+--disable_warnings
+drop procedure if exists bug9841|
+drop view if exists v1|
+--enable_warnings
+
+create view v1 as select * from t1, t2 where id = s|
+create procedure bug9841 ()
+ update v1 set data = 10|
+call bug9841()|
+
+drop view v1|
+drop procedure bug9841|
+
+
+#
+# BUG#5963 subqueries in SET/IF
+#
+--disable_warnings
+drop procedure if exists bug5963|
+--enable_warnings
+
+create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;|
+create table t3 (s1 int)|
+insert into t3 values (5)|
+call bug5963_1()|
+call bug5963_1()|
+drop procedure bug5963_1|
+drop table t3|
+
+create procedure bug5963_2 (cfk_value int)
+begin
+ if cfk_value in (select cpk from t3) then
+ set @x = 5;
+ end if;
+ end;
+|
+create table t3 (cpk int)|
+insert into t3 values (1)|
+call bug5963_2(1)|
+call bug5963_2(1)|
+drop procedure bug5963_2|
+drop table t3|
+
+
+#
+# BUG#9559: Functions: Numeric Operations using -ve value gives incorrect
+# results.
+#
+--disable_warnings
+drop function if exists bug9559|
+--enable_warnings
+create function bug9559()
+ returns int
+begin
+ set @y = -6/2;
+ return @y;
+end|
+
+select bug9559()|
+
+drop function bug9559|
+
+
+#
+# BUG#10961: Stored procedures: crash if select * from dual
+#
+--disable_warnings
+drop procedure if exists bug10961|
+--enable_warnings
+# "select * from dual" results in an error, so the cursor will not open
+create procedure bug10961()
+begin
+ declare v char;
+ declare x int;
+ declare c cursor for select * from dual;
+ declare continue handler for sqlexception select x;
+
+ set x = 1;
+ open c;
+ set x = 2;
+ fetch c into v;
+ set x = 3;
+ close c;
+end|
+
+call bug10961()|
+call bug10961()|
+
+drop procedure bug10961|
+
+#
+# BUG #6866: Second call of a stored procedure using a view with on expressions
+#
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS bug6866|
+--enable_warnings
+
+DROP VIEW IF EXISTS tv|
+DROP TABLE IF EXISTS tt1,tt2,tt3|
+
+CREATE TABLE tt1 (a1 int, a2 int, a3 int, data varchar(10))|
+CREATE TABLE tt2 (a2 int, data2 varchar(10))|
+CREATE TABLE tt3 (a3 int, data3 varchar(10))|
+
+INSERT INTO tt1 VALUES (1, 1, 4, 'xx')|
+
+INSERT INTO tt2 VALUES (1, 'a')|
+INSERT INTO tt2 VALUES (2, 'b')|
+INSERT INTO tt2 VALUES (3, 'c')|
+
+INSERT INTO tt3 VALUES (4, 'd')|
+INSERT INTO tt3 VALUES (5, 'e')|
+INSERT INTO tt3 VALUES (6, 'f')|
+
+CREATE VIEW tv AS
+SELECT tt1.*, tt2.data2, tt3.data3
+ FROM tt1 INNER JOIN tt2 ON tt1.a2 = tt2.a2
+ LEFT JOIN tt3 ON tt1.a3 = tt3.a3
+ ORDER BY tt1.a1, tt2.a2, tt3.a3|
+
+CREATE PROCEDURE bug6866 (_a1 int)
+BEGIN
+SELECT * FROM tv WHERE a1 = _a1;
+END|
+
+CALL bug6866(1)|
+CALL bug6866(1)|
+CALL bug6866(1)|
+
+DROP PROCEDURE bug6866;
+
+DROP VIEW tv|
+DROP TABLE tt1, tt2, tt3|
+
+#
+# BUG#10136: items cleunup
+#
+--disable_warnings
+DROP PROCEDURE IF EXISTS bug10136|
+--enable_warnings
+create table t3 ( name char(5) not null primary key, val float not null)|
+insert into t3 values ('aaaaa', 1), ('bbbbb', 2), ('ccccc', 3)|
+create procedure bug10136()
+begin
+ declare done int default 3;
+
+ repeat
+ select * from t3;
+ set done = done - 1;
+ until done <= 0 end repeat;
+
+end|
+call bug10136()|
+call bug10136()|
+call bug10136()|
+drop procedure bug10136|
+drop table t3|
+
+#
+# BUG#11529: crash server after use stored procedure
+#
+--disable_warnings
+drop procedure if exists bug11529|
+--enable_warnings
+create procedure bug11529()
+begin
+ declare c cursor for select id, data from t1 where data in (10,13);
+
+ open c;
+ begin
+ declare vid char(16);
+ declare vdata int;
+ declare exit handler for not found begin end;
+
+ while true do
+ fetch c into vid, vdata;
+ end while;
+ end;
+ close c;
+end|
+
+insert into t1 values
+ ('Name1', 10),
+ ('Name2', 11),
+ ('Name3', 12),
+ ('Name4', 13),
+ ('Name5', 14)|
+
+call bug11529()|
+call bug11529()|
+delete from t1|
+drop procedure bug11529|
+
+
+#
+# BUG#6063: Stored procedure labels are subject to restrictions (partial)
+# BUG#7088: Stored procedures: labels won't work if character set is utf8
+#
+--disable_warnings
+drop procedure if exists bug6063|
+drop procedure if exists bug7088_1|
+drop procedure if exists bug7088_2|
+--enable_warnings
+
+--disable_parsing # temporarily disabled until Bar fixes BUG#11986
+create procedure bug6063()
+ lâbel: begin end|
+call bug6063()|
+# QQ Known bug: this will not show the label correctly.
+show create procedure bug6063|
+
+set character set utf8|
+create procedure bug7088_1()
+ label1: begin end label1|
+create procedure bug7088_2()
+ läbel1: begin end|
+call bug7088_1()|
+call bug7088_2()|
+set character set default|
+show create procedure bug7088_1|
+show create procedure bug7088_2|
+
+drop procedure bug6063|
+drop procedure bug7088_1|
+drop procedure bug7088_2|
+--enable_parsing
+
+#
+# BUG#9565: "Wrong locking in stored procedure if a sub-sequent procedure
+# is called".
+#
+--disable_warnings
+drop procedure if exists bug9565_sub|
+drop procedure if exists bug9565|
+--enable_warnings
+create procedure bug9565_sub()
+begin
+ select * from t1;
+end|
+create procedure bug9565()
+begin
+ insert into t1 values ("one", 1);
+ call bug9565_sub();
+end|
+call bug9565()|
+delete from t1|
+drop procedure bug9565_sub|
+drop procedure bug9565|
+
+
+#
+# BUG#9538: SProc: Creation fails if we try to SET system variable
+# using @@var_name in proc
+#
+--disable_warnings
+drop procedure if exists bug9538|
+--enable_warnings
+create procedure bug9538()
+ set @@sort_buffer_size = 1000000|
+
+set @x = @@sort_buffer_size|
+set @@sort_buffer_size = 2000000|
+select @@sort_buffer_size|
+call bug9538()|
+select @@sort_buffer_size|
+set @@sort_buffer_size = @x|
+
+drop procedure bug9538|
+
+
+#
+# BUG#8692: Cursor fetch of empty string
+#
+--disable_warnings
+drop procedure if exists bug8692|
+--enable_warnings
+create table t3 (c1 varchar(5), c2 char(5), c3 enum('one','two'), c4 text, c5 blob, c6 char(5), c7 varchar(5))|
+insert into t3 values ('', '', '', '', '', '', NULL)|
+
+create procedure bug8692()
+begin
+ declare v1 VARCHAR(10);
+ declare v2 VARCHAR(10);
+ declare v3 VARCHAR(10);
+ declare v4 VARCHAR(10);
+ declare v5 VARCHAR(10);
+ declare v6 VARCHAR(10);
+ declare v7 VARCHAR(10);
+ declare c8692 cursor for select c1,c2,c3,c4,c5,c6,c7 from t3;
+ open c8692;
+ fetch c8692 into v1,v2,v3,v4,v5,v6,v7;
+ select v1, v2, v3, v4, v5, v6, v7;
+end|
+
+call bug8692()|
+drop procedure bug8692|
+drop table t3|
+
+#
+# Bug#10055 "Using stored function with information_schema causes empty
+# result set"
+#
+--disable_warnings
+drop function if exists bug10055|
+--enable_warnings
+create function bug10055(v char(255)) returns char(255) return lower(v)|
+# This select should not crash server and should return all fields in t1
+select t.column_name, bug10055(t.column_name)
+from information_schema.columns as t
+where t.table_schema = 'test' and t.table_name = 't1'|
+drop function bug10055|
+
+#
+# Bug #12297 "SP crashes the server if data inserted inside a lon loop"
+# The test for memleak bug, so actually there is no way to test it
+# from the suite. The test below could be used to check SP memory
+# consumption by passing large input parameter.
+#
+
+--disable_warnings
+drop procedure if exists bug12297|
+--enable_warnings
+
+create procedure bug12297(lim int)
+begin
+ set @x = 0;
+ repeat
+ insert into t1(id,data)
+ values('aa', @x);
+ set @x = @x + 1;
+ until @x >= lim
+ end repeat;
+end|
+
+call bug12297(10)|
+drop procedure bug12297|
+
+#
+# Bug #11247 "Stored procedures: Function calls in long loops leak memory"
+# One more memleak bug test. One could use this test to check that the memory
+# isn't leaking by increasing the input value for p_bug11247.
+#
+
+--disable_warnings
+drop function if exists f_bug11247|
+drop procedure if exists p_bug11247|
+--enable_warnings
+
+create function f_bug11247(param int)
+ returns int
+return param + 1|
+
+create procedure p_bug11247(lim int)
+begin
+ declare v int default 0;
+
+ while v < lim do
+ set v= f_bug11247(v);
+ end while;
+end|
+
+call p_bug11247(10)|
+drop function f_bug11247|
+drop procedure p_bug11247|
+#
+# BUG#12168: "'DECLARE CONTINUE HANDLER FOR NOT FOUND ...' in conditional
+# handled incorrectly"
+#
+--disable_warnings
+drop procedure if exists bug12168|
+drop table if exists t3, t4|
+--enable_warnings
+
+create table t3 (a int)|
+insert into t3 values (1),(2),(3),(4)|
+
+create table t4 (a int)|
+
+create procedure bug12168(arg1 char(1))
+begin
+ declare b, c integer;
+ if arg1 = 'a' then
+ begin
+ declare c1 cursor for select a from t3 where a % 2;
+ declare continue handler for not found set b = 1;
+ set b = 0;
+ open c1;
+ c1_repeat: repeat
+ fetch c1 into c;
+ if (b = 1) then
+ leave c1_repeat;
+ end if;
+
+ insert into t4 values (c);
+ until b = 1
+ end repeat;
+ end;
+ end if;
+ if arg1 = 'b' then
+ begin
+ declare c2 cursor for select a from t3 where not a % 2;
+ declare continue handler for not found set b = 1;
+ set b = 0;
+ open c2;
+ c2_repeat: repeat
+ fetch c2 into c;
+ if (b = 1) then
+ leave c2_repeat;
+ end if;
+
+ insert into t4 values (c);
+ until b = 1
+ end repeat;
+ end;
+ end if;
+end|
+
+call bug12168('a')|
+select * from t4|
+truncate t4|
+call bug12168('b')|
+select * from t4|
+truncate t4|
+call bug12168('a')|
+select * from t4|
+truncate t4|
+call bug12168('b')|
+select * from t4|
+truncate t4|
+drop table t3, t4|
+drop procedure if exists bug12168|
+
+#
+# Bug #11333 "Stored Procedure: Memory blow up on repeated SELECT ... INTO
+# query"
+# One more memleak bug. Use the test to check memory consumption.
+#
+
+--disable_warnings
+drop table if exists t3|
+drop procedure if exists bug11333|
+--enable_warnings
+
+create table t3 (c1 char(128))|
+
+insert into t3 values
+ ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')|
+
+
+create procedure bug11333(i int)
+begin
+ declare tmp varchar(128);
+ set @x = 0;
+ repeat
+ select c1 into tmp from t3
+ where c1 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
+ set @x = @x + 1;
+ until @x >= i
+ end repeat;
+end|
+
+call bug11333(10)|
+
+drop procedure bug11333|
+drop table t3|
+
+#
+# BUG#9048: Creating a function with char binary IN parameter fails
+#
+--disable_warnings
+drop function if exists bug9048|
+--enable_warnings
+create function bug9048(f1 char binary) returns char binary
+begin
+ set f1= concat( 'hello', f1 );
+ return f1;
+end|
+drop function bug9048|
+
+#
+# Bug #12849 Stored Procedure: Crash on procedure call with CHAR type
+# 'INOUT' parameter
+#
+
+--disable_warnings
+drop procedure if exists bug12849_1|
+--enable_warnings
+create procedure bug12849_1(inout x char) select x into x|
+set @var='a'|
+call bug12849_1(@var)|
+select @var|
+drop procedure bug12849_1|
+
+--disable_warnings
+drop procedure if exists bug12849_2|
+--enable_warnings
+create procedure bug12849_2(inout foo varchar(15))
+begin
+select concat(foo, foo) INTO foo;
+end|
+set @var='abcd'|
+call bug12849_2(@var)|
+select @var|
+drop procedure bug12849_2|
+
+#
+# BUG#13133: Local variables in stored procedures are not initialized correctly.
+#
+--disable_warnings
+drop procedure if exists bug131333|
+drop function if exists bug131333|
+--enable_warnings
+create procedure bug131333()
+begin
+ begin
+ declare a int;
+
+ select a;
+ set a = 1;
+ select a;
+ end;
+ begin
+ declare b int;
+
+ select b;
+ end;
+end|
+
+create function bug131333()
+ returns int
+begin
+ begin
+ declare a int;
+
+ set a = 1;
+ end;
+ begin
+ declare b int;
+
+ return b;
+ end;
+end|
+
+call bug131333()|
+select bug131333()|
+
+drop procedure bug131333|
+drop function bug131333|
+
+#
+# BUG#12379: PROCEDURE with HANDLER calling FUNCTION with error get
+# strange result
+#
+--disable_warnings
+drop function if exists bug12379|
+drop procedure if exists bug12379_1|
+drop procedure if exists bug12379_2|
+drop procedure if exists bug12379_3|
+drop table if exists t3|
+--enable_warnings
+
+create table t3 (c1 char(1) primary key not null)|
+
+create function bug12379()
+ returns integer
+begin
+ insert into t3 values('X');
+ insert into t3 values('X');
+ return 0;
+end|
+
+create procedure bug12379_1()
+begin
+ declare exit handler for sqlexception select 42;
+
+ select bug12379();
+END|
+create procedure bug12379_2()
+begin
+ declare exit handler for sqlexception begin end;
+
+ select bug12379();
+end|
+create procedure bug12379_3()
+begin
+ select bug12379();
+end|
+
+--error 1062
+select bug12379()|
+select 1|
+call bug12379_1()|
+select 2|
+call bug12379_2()|
+select 3|
+--error 1062
+call bug12379_3()|
+select 4|
+
+drop function bug12379|
+drop procedure bug12379_1|
+drop procedure bug12379_2|
+drop procedure bug12379_3|
+drop table t3|
+
+#
+# Bug #13124 Stored Procedure using SELECT INTO crashes server
+#
+
+--disable_warnings
+drop procedure if exists bug13124|
+--enable_warnings
+create procedure bug13124()
+begin
+ declare y integer;
+ set @x=y;
+end|
+call bug13124()|
+drop procedure bug13124|
+
+#
+# Bug #12979 Stored procedures: crash if inout decimal parameter
+#
+
+# check NULL inout parameters processing
+
+--disable_warnings
+drop procedure if exists bug12979_1|
+--enable_warnings
+create procedure bug12979_1(inout d decimal(5)) set d = d / 2|
+set @bug12979_user_var = NULL|
+call bug12979_1(@bug12979_user_var)|
+drop procedure bug12979_1|
+
+# check NULL local variables processing
+
+--disable_warnings
+drop procedure if exists bug12979_2|
+--enable_warnings
+create procedure bug12979_2()
+begin
+declare internal_var decimal(5);
+set internal_var= internal_var / 2;
+select internal_var;
+end|
+call bug12979_2()|
+drop procedure bug12979_2|
+
+
+#
+# BUG#NNNN: New bug synopsis
+#
+#--disable_warnings
+#drop procedure if exists bugNNNN|
+#--enable_warnings
+#create procedure bugNNNN...
+
+# Add bugs above this line. Use existing tables t1 and t2 when
+# practical, or create table t3, t4 etc temporarily (and drop them).
+delimiter ;|
+drop table t1,t2;
diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test
new file mode 100644
index 00000000000..82e1cd2f1c9
--- /dev/null
+++ b/mysql-test/t/sp_trans.test
@@ -0,0 +1,186 @@
+#
+# tests that require InnoDB...
+#
+
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+delimiter |;
+
+#
+# BUG#8850: Truncate table in a stored procedure locks the tables
+#
+--disable_warnings
+drop procedure if exists bug8850|
+--enable_warnings
+create table t1 (a int) engine=innodb|
+create procedure bug8850()
+begin
+ truncate table t1; insert t1 values (1); rollback;
+end|
+
+set autocommit=0|
+insert t1 values (2)|
+call bug8850()|
+commit|
+select * from t1|
+
+call bug8850()|
+set autocommit=1|
+select * from t1|
+drop table t1|
+drop procedure bug8850|
+
+
+#
+# BUG#10015: Crash in InnoDB if stored routines are used
+# (crash happens in auto-commit mode)
+#
+--disable_warnings
+drop function if exists bug10015_1|
+drop function if exists bug10015_2|
+drop function if exists bug10015_3|
+drop function if exists bug10015_4|
+drop function if exists bug10015_5|
+drop function if exists bug10015_6|
+drop function if exists bug10015_7|
+drop procedure if exists bug10015_8|
+--enable_warnings
+create table t1 (id int) engine=innodb|
+create table t2 (id int primary key, j int) engine=innodb|
+insert into t1 values (1),(2),(3)|
+create function bug10015_1() returns int return (select count(*) from t1)|
+select *, bug10015_1() from t1|
+drop function bug10015_1|
+# Test couple of a bit more complex cases
+create function bug10015_2() returns int
+ begin
+ declare i, s int;
+ set i:= (select min(id) from t1);
+ set s:= (select max(id) from t1);
+ return (s - i);
+ end|
+select *, bug10015_2() from t1|
+drop function bug10015_2|
+create function bug10015_3() returns int
+ return (select max(a.id - b.id) from t1 as a, t1 as b where a.id >= b.id)|
+select *, bug10015_3() from t1|
+drop function bug10015_3|
+create function bug10015_4(i int) returns int
+ begin
+ declare m int;
+ set m:= (select max(id) from t2);
+ insert into t2 values (i, m);
+ return m;
+ end|
+select *, bug10015_4(id) from t1|
+select * from t2|
+drop function bug10015_4|
+# Now let us test how statement rollback works
+# This function will cause the whole stmt to be rolled back,
+# there should not be any traces left.
+create function bug10015_5(i int) returns int
+ begin
+ if (i = 5) then
+ insert into t2 values (1, 0);
+ end if;
+ return i;
+ end|
+--error 1062
+insert into t1 values (bug10015_5(4)), (bug10015_5(5))|
+select * from t1|
+drop function bug10015_5|
+# Thanks to error-handler this function should not cause rollback
+# of statement calling it. But insert statement in it should be
+# rolled back completely and don't leave any traces in t2.
+# Unfortunately we can't implement such behavior in 5.0, so it
+# is something to be fixed in later 5.* releases (TODO).
+create function bug10015_6(i int) returns int
+ begin
+ declare continue handler for sqlexception set @error_in_func:= 1;
+ if (i = 5) then
+ insert into t2 values (4, 0), (1, 0);
+ end if;
+ return i;
+ end|
+set @error_in_func:= 0|
+insert into t1 values (bug10015_6(5)), (bug10015_6(6))|
+select @error_in_func|
+select * from t1|
+select * from t2|
+drop function bug10015_6|
+# Let us test that we don't allow any statements causing transaction
+# commit in stored functions (we test only most interesting cases here).
+# Cases which can be caught at creation time:
+--error 1422
+create function bug10015_7() returns int
+ begin
+ alter table t1 add k int;
+ return 1;
+ end|
+--error 1422
+create function bug10015_7() returns int
+ begin
+ start transaction;
+ return 1;
+ end|
+--error 1422
+create function bug10015_7() returns int
+ begin
+ drop table t1;
+ return 1;
+ end|
+# It should be OK to drop temporary table.
+create function bug10015_7() returns int
+ begin
+ drop temporary table t1;
+ return 1;
+ end|
+drop function bug10015_7|
+--error 1422
+create function bug10015_7() returns int
+ begin
+ commit;
+ return 1;
+ end|
+# Now let us test cases which we can catch only at run-time:
+create function bug10015_7() returns int
+ begin
+ call bug10015_8();
+ return 1;
+ end|
+create procedure bug10015_8() alter table t1 add k int|
+--error 1422
+select *, bug10015_7() from t1|
+drop procedure bug10015_8|
+create procedure bug10015_8() start transaction|
+--error 1422
+select *, bug10015_7() from t1|
+drop procedure bug10015_8|
+# Again it is OK to drop temporary table
+# We are surpressing warnings since they are not essential
+create procedure bug10015_8() drop temporary table if exists t1_temp|
+--disable_warnings
+select *, bug10015_7() from t1|
+--enable_warnings
+drop procedure bug10015_8|
+create procedure bug10015_8() commit|
+--error 1422
+select *, bug10015_7() from t1|
+drop procedure bug10015_8|
+drop function bug10015_7|
+drop table t1, t2|
+
+
+#
+# BUG#NNNN: New bug synopsis
+#
+#--disable_warnings
+#drop procedure if exists bugNNNN|
+#--enable_warnings
+#create procedure bugNNNN...
+
+delimiter ;|
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index 4a5a136f54a..10db520cd12 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -87,3 +87,159 @@ drop table t1 ;
set @@SQL_MODE=NULL;
# End of 4.1 tests
+
+#
+# test for
+# WL 1941 "NO_C_ESCAPES sql_mode"
+#
+# an sql_mode to disable \n, \r, \b, etc escapes in string literals. actually, to
+# disable special meaning of backslash completely. It's not in the SQL standard
+# and it causes some R/3 tests to fail.
+#
+
+SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE='';
+show local variables like 'SQL_MODE';
+
+CREATE TABLE t1 (p int not null auto_increment, a varchar(20), primary key(p));
+INSERT t1 (a) VALUES
+('\\'),
+('\n'),
+('\b'),
+('\r'),
+('\t'),
+('\x'),
+('\a'),
+('\aa'),
+('\\a'),
+('\\aa'),
+('_'),
+('\_'),
+('\\_'),
+('\\\_'),
+('\\\\_'),
+('%'),
+('\%'),
+('\\%'),
+('\\\%'),
+('\\\\%')
+;
+
+SELECT p, hex(a) FROM t1;
+
+delete from t1 where a in ('\n','\r','\t', '\b');
+
+select
+ masks.p,
+ masks.a as mask,
+ examples.a as example
+from
+ t1 as masks
+ left join t1 as examples on examples.a LIKE masks.a
+order by masks.p, example;
+
+DROP TABLE t1;
+
+SET @@SQL_MODE='NO_BACKSLASH_ESCAPES';
+show local variables like 'SQL_MODE';
+
+CREATE TABLE t1 (p int not null auto_increment, a varchar(20), primary key(p));
+INSERT t1 (a) VALUES
+('\\'),
+('\n'),
+('\b'),
+('\r'),
+('\t'),
+('\x'),
+('\a'),
+('\aa'),
+('\\a'),
+('\\aa'),
+('_'),
+('\_'),
+('\\_'),
+('\\\_'),
+('\\\\_'),
+('%'),
+('\%'),
+('\\%'),
+('\\\%'),
+('\\\\%')
+;
+
+SELECT p, hex(a) FROM t1;
+
+delete from t1 where a in ('\n','\r','\t', '\b');
+
+select
+ masks.p,
+ masks.a as mask,
+ examples.a as example
+from
+ t1 as masks
+ left join t1 as examples on examples.a LIKE masks.a
+order by masks.p, example;
+
+DROP TABLE t1;
+
+# Bug #6368: Make sure backslashes mixed with doubled quotes are handled
+# correctly in NO_BACKSLASH_ESCAPES mode
+SET @@SQL_MODE='NO_BACKSLASH_ESCAPES';
+SELECT 'a\\b', 'a\\\"b', 'a''\\b', 'a''\\\"b';
+SELECT "a\\b", "a\\\'b", "a""\\b", "a""\\\'b";
+
+SET @@SQL_MODE='';
+SELECT 'a\\b', 'a\\\"b', 'a''\\b', 'a''\\\"b';
+SELECT "a\\b", "a\\\'b", "a""\\b", "a""\\\'b";
+
+#
+# Bug#6877: MySQL should give an error if the requested table type
+# is not available
+#
+
+set session sql_mode = 'NO_ENGINE_SUBSTITUTION';
+--error 1289
+create table t1 (a int) engine=isam;
+--error 1146
+show create table t1;
+drop table if exists t1;
+
+# for comparison, lets see the warnings...
+set session sql_mode = '';
+create table t1 (a int) engine=isam;
+show create table t1;
+drop table t1;
+
+#
+# Bug #6903: ANSI_QUOTES does not come into play with SHOW CREATE FUNCTION
+# or PROCEDURE because it displays the SQL_MODE used to create the routine.
+#
+SET @@SQL_MODE='';
+create function `foo` () returns int return 5;
+show create function `foo`;
+SET @@SQL_MODE='ANSI_QUOTES';
+show create function `foo`;
+drop function `foo`;
+
+create function `foo` () returns int return 5;
+show create function `foo`;
+SET @@SQL_MODE='';
+show create function `foo`;
+drop function `foo`;
+
+#
+# Bug #6903: ANSI_QUOTES should have effect for SHOW CREATE VIEW (Bug #6903)
+#
+SET @@SQL_MODE='';
+create table t1 (a int);
+create table t2 (a int);
+create view v1 as select a from t1;
+show create view v1;
+SET @@SQL_MODE='ANSI_QUOTES';
+show create view v1;
+# Test a view with a subselect, which will get shown incorrectly without
+# thd->lex->view_prepare_mode set properly.
+create view v2 as select a from t2 where a in (select a from v1);
+drop view v2, v1;
+drop table t1, t2;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test
new file mode 100644
index 00000000000..d3b36cbc2a8
--- /dev/null
+++ b/mysql-test/t/strict.test
@@ -0,0 +1,1147 @@
+# Testing of "strict" mode
+
+-- source include/have_innodb.inc
+
+set @org_mode=@@sql_mode;
+set @@sql_mode='ansi,traditional';
+select @@sql_mode;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+# Test INSERT with DATE
+
+CREATE TABLE t1 (col1 date);
+INSERT INTO t1 VALUES('2004-01-01'),('0000-10-31'),('2004-02-29');
+
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid date value>
+--error 1292
+INSERT INTO t1 VALUES('2004-0-31');
+--error 1292
+INSERT INTO t1 VALUES('2004-01-02'),('2004-0-31');
+--error 1292
+INSERT INTO t1 VALUES('2004-10-0');
+--error 1292
+INSERT INTO t1 VALUES('2004-09-31');
+--error 1292
+INSERT INTO t1 VALUES('2004-10-32');
+--error 1292
+INSERT INTO t1 VALUES('2003-02-29');
+--error 1292
+INSERT INTO t1 VALUES('2004-13-15');
+--error 1292
+INSERT INTO t1 VALUES('0000-00-00');
+# Standard says we should return SQLSTATE 22018
+--error 1292
+INSERT INTO t1 VALUES ('59');
+
+# Test the different related modes
+set @@sql_mode='STRICT_ALL_TABLES';
+INSERT INTO t1 VALUES('2004-01-03'),('2004-0-31');
+set @@sql_mode='STRICT_ALL_TABLES,NO_ZERO_IN_DATE';
+--error 1292
+INSERT INTO t1 VALUES('2004-0-30');
+--error 1292
+INSERT INTO t1 VALUES('2004-01-04'),('2004-0-31'),('2004-01-05');
+INSERT INTO t1 VALUES('0000-00-00');
+INSERT IGNORE INTO t1 VALUES('2004-0-29');
+set @@sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';
+--error 1292
+INSERT INTO t1 VALUES('0000-00-00');
+INSERT IGNORE INTO t1 VALUES('0000-00-00');
+INSERT INTO t1 VALUES ('2004-0-30');
+--error 1292
+INSERT INTO t1 VALUES ('2004-2-30');
+set @@sql_mode='STRICT_ALL_TABLES,ALLOW_INVALID_DATES';
+INSERT INTO t1 VALUES ('2004-2-30');
+set @@sql_mode='ansi,traditional';
+INSERT IGNORE INTO t1 VALUES('2004-02-29'),('2004-13-15'),('0000-00-00');
+
+select * from t1;
+drop table t1;
+
+# Test difference in behaviour with InnoDB and MyISAM tables
+
+set @@sql_mode='strict_trans_tables';
+CREATE TABLE t1 (col1 date) engine=myisam;
+--error 1292
+INSERT INTO t1 VALUES('2004-13-31'),('2004-1-1');
+INSERT INTO t1 VALUES ('2004-1-2'), ('2004-13-31'),('2004-1-3');
+INSERT IGNORE INTO t1 VALUES('2004-13-31'),('2004-1-4');
+--error 1292
+INSERT INTO t1 VALUES ('2003-02-29');
+INSERT ignore INTO t1 VALUES('2003-02-30');
+set @@sql_mode='STRICT_ALL_TABLES,ALLOW_INVALID_DATES';
+INSERT ignore INTO t1 VALUES('2003-02-31');
+select * from t1;
+drop table t1;
+
+set @@sql_mode='strict_trans_tables';
+CREATE TABLE t1 (col1 date) engine=innodb;
+--error 1292
+INSERT INTO t1 VALUES('2004-13-31'),('2004-1-1');
+--error 1292
+INSERT INTO t1 VALUES ('2004-1-2'), ('2004-13-31'),('2004-1-3');
+INSERT IGNORE INTO t1 VALUES('2004-13-31'),('2004-1-4');
+--error 1292
+INSERT INTO t1 VALUES ('2003-02-29');
+INSERT ignore INTO t1 VALUES('2003-02-30');
+set @@sql_mode='STRICT_ALL_TABLES,ALLOW_INVALID_DATES';
+INSERT ignore INTO t1 VALUES('2003-02-31');
+select * from t1;
+drop table t1;
+set @@sql_mode='ansi,traditional';
+
+# Test INSERT with DATETIME
+
+CREATE TABLE t1 (col1 datetime);
+INSERT INTO t1 VALUES('2004-10-31 15:30:00'),('0000-10-31 15:30:00'),('2004-02-29 15:30:00');
+
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid datetime value>
+--error 1292
+INSERT INTO t1 VALUES('2004-0-31 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-10-0 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-09-31 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-10-32 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2003-02-29 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-13-15 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('0000-00-00 15:30:00');
+# Standard says we should return SQLSTATE 22018
+--error 1292
+INSERT INTO t1 VALUES ('59');
+select * from t1;
+drop table t1;
+
+# Test INSERT with TIMESTAMP
+
+CREATE TABLE t1 (col1 timestamp);
+INSERT INTO t1 VALUES('2004-10-31 15:30:00'),('2004-02-29 15:30:00');
+
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid datetime value>
+# Standard says we should return ok, but we can't as this is out of range
+--error 1292
+INSERT INTO t1 VALUES('0000-10-31 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-0-31 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-10-0 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-09-31 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-10-32 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2003-02-29 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-13-15 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-02-29 25:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-02-29 15:65:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-02-29 15:31:61');
+--error 1292
+INSERT INTO t1 VALUES('0000-00-00 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('0000-00-00 00:00:00');
+INSERT IGNORE INTO t1 VALUES('0000-00-00 00:00:00');
+# Standard says we should return SQLSTATE 22018
+--error 1292
+INSERT INTO t1 VALUES ('59');
+
+set @@sql_mode='STRICT_ALL_TABLES,ALLOW_INVALID_DATES';
+--error 1292
+INSERT INTO t1 VALUES('2004-0-31 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-10-0 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-10-32 15:30:00');
+--error 1292
+INSERT INTO t1 VALUES('2004-02-30 15:30:04');
+INSERT INTO t1 VALUES('0000-00-00 00:00:00');
+set @@sql_mode='STRICT_ALL_TABLES,NO_ZERO_IN_DATE';
+INSERT INTO t1 VALUES('0000-00-00 00:00:00');
+set @@sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';
+--error 1292
+INSERT INTO t1 VALUES('0000-00-00 00:00:00');
+set @@sql_mode='ansi,traditional';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
+#### Test INSERT with STR_TO_DATE into DATE/DATETIME/TIMESTAMP
+
+CREATE TABLE t1 (col1 date, col2 datetime, col3 timestamp);
+
+INSERT INTO t1 (col1) VALUES (STR_TO_DATE('15.10.2004','%d.%m.%Y'));
+INSERT INTO t1 (col2) VALUES (STR_TO_DATE('15.10.2004 10.15','%d.%m.%Y %H.%i'));
+INSERT INTO t1 (col3) VALUES (STR_TO_DATE('15.10.2004 10.15','%d.%m.%Y %H.%i'));
+
+## Test INSERT with STR_TO_DATE into DATE
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid date value>
+
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('31.10.0000 15.30','%d.%m.%Y %H.%i'));
+
+--error 1292
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('31.0.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('0.10.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('31.9.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1411
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('29.02.2003 15.30','%d.%m.%Y %H.%i'));
+--error 1411
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('15.13.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col1) VALUES(STR_TO_DATE('00.00.0000','%d.%m.%Y'));
+
+## Test INSERT with STR_TO_DATE into DATETIME
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid datetime value>
+
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('31.10.0000 15.30','%d.%m.%Y %H.%i'));
+
+--error 1292
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('31.0.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('0.10.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('31.9.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1411
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('29.02.2003 15.30','%d.%m.%Y %H.%i'));
+--error 1411
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('15.13.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col2) VALUES(STR_TO_DATE('00.00.0000','%d.%m.%Y'));
+
+## Test INSERT with STR_TO_DATE into TIMESTAMP
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid datetime value>
+
+--error 1292
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('31.10.0000 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('31.0.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('0.10.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('31.9.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1411
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('29.02.2003 15.30','%d.%m.%Y %H.%i'));
+--error 1411
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('15.13.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1292
+INSERT INTO t1 (col3) VALUES(STR_TO_DATE('00.00.0000','%d.%m.%Y'));
+
+drop table t1;
+
+
+#### Test INSERT with CAST AS DATE/DATETIME into DATE/DATETIME/TIMESTAMP
+
+CREATE TABLE t1 (col1 date, col2 datetime, col3 timestamp);
+
+INSERT INTO t1 (col1) VALUES (CAST('2004-10-15' AS DATE));
+INSERT INTO t1 (col2) VALUES (CAST('2004-10-15 10:15' AS DATETIME));
+INSERT INTO t1 (col3) VALUES (CAST('2004-10-15 10:15' AS DATETIME));
+
+
+## Test INSERT with CAST AS DATE into DATE
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid date value>
+INSERT INTO t1 (col1) VALUES(CAST('0000-10-31' AS DATE));
+
+--error 1292
+INSERT INTO t1 (col1) VALUES(CAST('2004-10-0' AS DATE));
+--error 1292
+INSERT INTO t1 (col1) VALUES(CAST('2004-0-10' AS DATE));
+
+# deactivated because of Bug#8294
+# Bug#8294 Traditional: Misleading error message for invalid CAST to DATE
+# --error 1292
+# INSERT INTO t1 (col1) VALUES(CAST('2004-9-31' AS DATE));
+# --error 1292
+# INSERT INTO t1 (col1) VALUES(CAST('2004-10-32' AS DATE));
+# --error 1292
+# INSERT INTO t1 (col1) VALUES(CAST('2003-02-29' AS DATE));
+# --error 1292
+# INSERT INTO t1 (col1) VALUES(CAST('2004-13-15' AS DATE));
+
+# deactivated because of Bug#6145
+# Bug#6145: Traditional: CONVERT and CAST should reject zero DATE values
+--error 1292
+INSERT INTO t1 (col1) VALUES(CAST('0000-00-00' AS DATE));
+
+## Test INSERT with CAST AS DATETIME into DATETIME
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid datetime value>
+INSERT INTO t1 (col2) VALUES(CAST('0000-10-31 15:30' AS DATETIME));
+
+--error 1292
+INSERT INTO t1 (col2) VALUES(CAST('2004-10-0 15:30' AS DATETIME));
+--error 1292
+INSERT INTO t1 (col2) VALUES(CAST('2004-0-10 15:30' AS DATETIME));
+
+# deactivated because of Bug#8294
+# Bug#8294 Traditional: Misleading error message for invalid CAST to DATE
+#--error 1292
+#INSERT INTO t1 (col2) VALUES(CAST('2004-9-31 15:30' AS DATETIME));
+#--error 1292
+#INSERT INTO t1 (col2) VALUES(CAST('2004-10-32 15:30' AS DATETIME));
+#--error 1292
+#INSERT INTO t1 (col2) VALUES(CAST('2003-02-29 15:30' AS DATETIME));
+#--error 1292
+#INSERT INTO t1 (col2) VALUES(CAST('2004-13-15 15:30' AS DATETIME));
+
+# Bug#6145: Traditional: CONVERT and CAST should reject zero DATE values
+--error 1292
+INSERT INTO t1 (col2) VALUES(CAST('0000-00-00' AS DATETIME));
+
+## Test INSERT with CAST AS DATETIME into TIMESTAMP
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid datetime value>
+--error 1292
+INSERT INTO t1 (col3) VALUES(CAST('0000-10-31 15:30' AS DATETIME));
+-- should return OK
+-- We accept this to be a failure
+
+--error 1292
+INSERT INTO t1 (col3) VALUES(CAST('2004-10-0 15:30' AS DATETIME));
+--error 1292
+INSERT INTO t1 (col3) VALUES(CAST('2004-0-10 15:30' AS DATETIME));
+-- should return SQLSTATE 22007 <invalid datetime value>
+
+# deactivated because of Bug#8294
+# Bug#8294 Traditional: Misleading error message for invalid CAST to DATE
+#--error 1292
+#INSERT INTO t1 (col3) VALUES(CAST('2004-9-31 15:30' AS DATETIME));
+#--error 1292
+#INSERT INTO t1 (col3) VALUES(CAST('2004-10-32 15:30' AS DATETIME));
+#--error 1292
+#INSERT INTO t1 (col3) VALUES(CAST('2003-02-29 15:30' AS DATETIME));
+#--error 1292
+#INSERT INTO t1 (col3) VALUES(CAST('2004-13-15 15:30' AS DATETIME));
+
+# Bug#6145: Traditional: CONVERT and CAST should reject zero DATE values
+--error 1292
+INSERT INTO t1 (col3) VALUES(CAST('0000-00-00' AS DATETIME));
+
+drop table t1;
+
+
+#### Test INSERT with CONVERT to DATE/DATETIME into DATE/DATETIME/TIMESTAMP
+
+CREATE TABLE t1 (col1 date, col2 datetime, col3 timestamp);
+
+INSERT INTO t1 (col1) VALUES (CONVERT('2004-10-15',DATE));
+INSERT INTO t1 (col2) VALUES (CONVERT('2004-10-15 10:15',DATETIME));
+INSERT INTO t1 (col3) VALUES (CONVERT('2004-10-15 10:15',DATETIME));
+
+
+## Test INSERT with CONVERT to DATE into DATE
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid date value>
+INSERT INTO t1 (col1) VALUES(CONVERT('0000-10-31' , DATE));
+
+--error 1292
+INSERT INTO t1 (col1) VALUES(CONVERT('2004-10-0' , DATE));
+--error 1292
+INSERT INTO t1 (col1) VALUES(CONVERT('2004-0-10' , DATE));
+
+# deactivated because of Bug#8294
+# Bug#8294 Traditional: Misleading error message for invalid CAST to DATE
+#--error 1292
+#INSERT INTO t1 (col1) VALUES(CONVERT('2004-9-31' , DATE));
+#--error 1292
+#INSERT INTO t1 (col1) VALUES(CONVERT('2004-10-32' , DATE));
+#--error 1292
+#INSERT INTO t1 (col1) VALUES(CONVERT('2003-02-29' , DATE));
+#--error 1292
+#INSERT INTO t1 (col1) VALUES(CONVERT('2004-13-15',DATE));
+
+# Bug#6145: Traditional: CONVERT and CAST should reject zero DATE values
+--error 1292
+INSERT INTO t1 (col1) VALUES(CONVERT('0000-00-00',DATE));
+
+## Test INSERT with CONVERT to DATETIME into DATETIME
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid datetime value>
+INSERT INTO t1 (col2) VALUES(CONVERT('0000-10-31 15:30',DATETIME));
+
+--error 1292
+INSERT INTO t1 (col2) VALUES(CONVERT('2004-10-0 15:30',DATETIME));
+--error 1292
+INSERT INTO t1 (col2) VALUES(CONVERT('2004-0-10 15:30',DATETIME));
+
+# deactivated because of Bug#8294
+# Bug#8294 Traditional: Misleading error message for invalid CAST to DATE
+#--error 1292
+#INSERT INTO t1 (col2) VALUES(CONVERT('2004-9-31 15:30',DATETIME));
+#--error 1292
+#INSERT INTO t1 (col2) VALUES(CONVERT('2004-10-32 15:30',DATETIME));
+#--error 1292
+#INSERT INTO t1 (col2) VALUES(CONVERT('2003-02-29 15:30',DATETIME));
+#--error 1292
+#INSERT INTO t1 (col2) VALUES(CONVERT('2004-13-15 15:30',DATETIME));
+
+# Bug#6145: Traditional: CONVERT and CAST should reject zero DATE values
+--error 1292
+INSERT INTO t1 (col2) VALUES(CONVERT('0000-00-00',DATETIME));
+
+## Test INSERT with CONVERT to DATETIME into DATETIME
+# All test cases expected to fail should return
+# SQLSTATE 22007 <invalid datetime value>
+--error 1292
+INSERT INTO t1 (col3) VALUES(CONVERT('0000-10-31 15:30',DATETIME));
+-- should return OK
+-- We accept this to be a failure
+
+--error 1292
+INSERT INTO t1 (col3) VALUES(CONVERT('2004-10-0 15:30',DATETIME));
+--error 1292
+INSERT INTO t1 (col3) VALUES(CONVERT('2004-0-10 15:30',DATETIME));
+
+# deactivated because of Bug#8294
+# Bug#8294 Traditional: Misleading error message for invalid CAST to DATE
+#--error 1292
+#INSERT INTO t1 (col3) VALUES(CONVERT('2004-9-31 15:30',DATETIME));
+#--error 1292
+#INSERT INTO t1 (col3) VALUES(CONVERT('2004-10-32 15:30',DATETIME));
+#--error 1292
+#INSERT INTO t1 (col3) VALUES(CONVERT('2003-02-29 15:30',DATETIME));
+#--error 1292
+#INSERT INTO t1 (col3) VALUES(CONVERT('2004-13-15 15:30',DATETIME));
+
+# Bug#6145: Traditional: CONVERT and CAST should reject zero DATE values
+--error 1292
+INSERT INTO t1 (col3) VALUES(CONVERT('0000-00-00',DATETIME));
+
+drop table t1;
+
+
+# Test INSERT with TINYINT
+
+CREATE TABLE t1(col1 TINYINT, col2 TINYINT UNSIGNED);
+INSERT INTO t1 VALUES(-128,0),(0,0),(127,255),('-128','0'),('0','0'),('127','255'),(-128.0,0.0),(0.0,0.0),(127.0,255.0);
+# Test that we restored the mode checking properly after an ok query
+SELECT MOD(col1,0) FROM t1 WHERE col1 > 0 LIMIT 2;
+-- error 1264
+INSERT INTO t1 (col1) VALUES(-129);
+-- error 1264
+INSERT INTO t1 (col1) VALUES(128);
+-- error 1264
+INSERT INTO t1 (col2) VALUES(-1);
+-- error 1264
+INSERT INTO t1 (col2) VALUES(256);
+-- error 1264
+INSERT INTO t1 (col1) VALUES('-129');
+-- error 1264
+INSERT INTO t1 (col1) VALUES('128');
+-- error 1264
+INSERT INTO t1 (col2) VALUES('-1');
+-- error 1264
+INSERT INTO t1 (col2) VALUES('256');
+-- error 1264
+INSERT INTO t1 (col1) VALUES(128.0);
+-- error 1264
+INSERT INTO t1 (col2) VALUES(-1.0);
+-- error 1264
+INSERT INTO t1 (col2) VALUES(256.0);
+SELECT MOD(col1,0) FROM t1 WHERE col1 > 0 LIMIT 1;
+--error 1264
+UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
+--error 1264
+UPDATE t1 SET col2=col2 + 50 WHERE col2 > 0;
+--error 1365
+UPDATE t1 SET col1=col1 / 0 WHERE col1 > 0;
+set @@sql_mode='ERROR_FOR_DIVISION_BY_ZERO';
+INSERT INTO t1 values (1/0,1/0);
+set @@sql_mode='ansi,traditional';
+SELECT MOD(col1,0) FROM t1 WHERE col1 > 0 LIMIT 2;
+# Should return SQLSTATE 22018 invalid character value for cast
+--error 1366
+INSERT INTO t1 (col1) VALUES ('');
+--error 1366
+INSERT INTO t1 (col1) VALUES ('a59b');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('1a');
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+INSERT IGNORE INTO t1 values (1/0,1/0);
+set @@sql_mode='ansi';
+INSERT INTO t1 values (1/0,1/0);
+set @@sql_mode='ansi,traditional';
+INSERT IGNORE INTO t1 VALUES('-129','-1'),('128','256');
+INSERT IGNORE INTO t1 VALUES(-129.0,-1.0),(128.0,256.0);
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test INSERT with SMALLINT
+
+CREATE TABLE t1(col1 SMALLINT, col2 SMALLINT UNSIGNED);
+INSERT INTO t1 VALUES(-32768,0),(0,0),(32767,65535),('-32768','0'),('32767','65535'),(-32768.0,0.0),(32767.0,65535.0);
+
+--error 1264
+INSERT INTO t1 (col1) VALUES(-32769);
+--error 1264
+INSERT INTO t1 (col1) VALUES(32768);
+--error 1264
+INSERT INTO t1 (col2) VALUES(-1);
+--error 1264
+INSERT INTO t1 (col2) VALUES(65536);
+--error 1264
+INSERT INTO t1 (col1) VALUES('-32769');
+--error 1264
+INSERT INTO t1 (col1) VALUES('32768');
+--error 1264
+INSERT INTO t1 (col2) VALUES('-1');
+--error 1264
+INSERT INTO t1 (col2) VALUES('65536');
+--error 1264
+INSERT INTO t1 (col1) VALUES(-32769.0);
+--error 1264
+INSERT INTO t1 (col1) VALUES(32768.0);
+--error 1264
+INSERT INTO t1 (col2) VALUES(-1.0);
+--error 1264
+INSERT INTO t1 (col2) VALUES(65536.0);
+--error 1264
+UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
+--error 1264
+UPDATE t1 SET col2 = col2 + 50 WHERE col2 > 0;
+--error 1365
+UPDATE t1 SET col1 = col1 / 0 WHERE col1 > 0;
+--error 1365
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+--error 1366
+INSERT INTO t1 (col1) VALUES ('');
+--error 1366
+INSERT INTO t1 (col1) VALUES ('a59b');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('1a');
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+INSERT IGNORE INTO t1 values (1/0,1/0);
+INSERT IGNORE INTO t1 VALUES(-32769,-1),(32768,65536);
+INSERT IGNORE INTO t1 VALUES('-32769','-1'),('32768','65536');
+INSERT IGNORE INTO t1 VALUES(-32769,-1.0),(32768.0,65536.0);
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test INSERT with MEDIUMINT
+
+CREATE TABLE t1 (col1 MEDIUMINT, col2 MEDIUMINT UNSIGNED);
+INSERT INTO t1 VALUES(-8388608,0),(0,0),(8388607,16777215),('-8388608','0'),('8388607','16777215'),(-8388608.0,0.0),(8388607.0,16777215.0);
+--error 1264
+INSERT INTO t1 (col1) VALUES(-8388609);
+--error 1264
+INSERT INTO t1 (col1) VALUES(8388608);
+--error 1264
+INSERT INTO t1 (col2) VALUES(-1);
+--error 1264
+INSERT INTO t1 (col2) VALUES(16777216);
+--error 1264
+INSERT INTO t1 (col1) VALUES('-8388609');
+--error 1264
+INSERT INTO t1 (col1) VALUES('8388608');
+--error 1264
+INSERT INTO t1 (col2) VALUES('-1');
+--error 1264
+INSERT INTO t1 (col2) VALUES('16777216');
+--error 1264
+INSERT INTO t1 (col1) VALUES(-8388609.0);
+--error 1264
+INSERT INTO t1 (col1) VALUES(8388608.0);
+--error 1264
+INSERT INTO t1 (col2) VALUES(-1.0);
+--error 1264
+INSERT INTO t1 (col2) VALUES(16777216.0);
+
+--error 1264
+UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
+--error 1264
+UPDATE t1 SET col2 = col2 + 50 WHERE col2 > 0;
+--error 1365
+UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
+--error 1365
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+--error 1366
+INSERT INTO t1 (col1) VALUES ('');
+--error 1366
+INSERT INTO t1 (col1) VALUES ('a59b');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('1a');
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+INSERT IGNORE INTO t1 values (1/0,1/0);
+INSERT IGNORE INTO t1 VALUES(-8388609,-1),(8388608,16777216);
+INSERT IGNORE INTO t1 VALUES('-8388609','-1'),('8388608','16777216');
+INSERT IGNORE INTO t1 VALUES(-8388609.0,-1.0),(8388608.0,16777216.0);
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test INSERT with INT
+
+CREATE TABLE t1 (col1 INT, col2 INT UNSIGNED);
+INSERT INTO t1 VALUES(-2147483648,0),(0,0),(2147483647,4294967295),('-2147483648','0'),('2147483647','4294967295'),(-2147483648.0,0.0),(2147483647.0,4294967295.0);
+--error 1264
+INSERT INTO t1 (col1) VALUES(-2147483649);
+--error 1264
+INSERT INTO t1 (col1) VALUES(2147643648);
+--error 1264
+INSERT INTO t1 (col2) VALUES(-1);
+--error 1264
+INSERT INTO t1 (col2) VALUES(4294967296);
+--error 1264
+INSERT INTO t1 (col1) VALUES('-2147483649');
+--error 1264
+INSERT INTO t1 (col1) VALUES('2147643648');
+--error 1264
+INSERT INTO t1 (col2) VALUES('-1');
+--error 1264
+INSERT INTO t1 (col2) VALUES('4294967296');
+--error 1264
+INSERT INTO t1 (col1) VALUES(-2147483649.0);
+--error 1264
+INSERT INTO t1 (col1) VALUES(2147643648.0);
+--error 1264
+INSERT INTO t1 (col2) VALUES(-1.0);
+--error 1264
+INSERT INTO t1 (col2) VALUES(4294967296.0);
+
+--error 1264
+UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
+--error 1264
+UPDATE t1 SET col2 =col2 + 50 WHERE col2 > 0;
+--error 1365
+UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
+--error 1365
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+--error 1264
+INSERT INTO t1 (col1) VALUES ('');
+--error 1264
+INSERT INTO t1 (col1) VALUES ('a59b');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('1a');
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+INSERT IGNORE INTO t1 values (1/0,1/0);
+INSERT IGNORE INTO t1 values (-2147483649, -1),(2147643648,4294967296);
+INSERT IGNORE INTO t1 values ('-2147483649', '-1'),('2147643648','4294967296');
+INSERT IGNORE INTO t1 values (-2147483649.0, -1.0),(2147643648.0,4294967296.0);
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test INSERT with BIGINT
+# Note that this doesn't behave 100 % to standard as we rotate
+# integers when it's too big/small (just like C)
+
+CREATE TABLE t1 (col1 BIGINT, col2 BIGINT UNSIGNED);
+INSERT INTO t1 VALUES(-9223372036854775808,0),(0,0),(9223372036854775807,18446744073709551615);
+INSERT INTO t1 VALUES('-9223372036854775808','0'),('9223372036854775807','18446744073709551615');
+INSERT INTO t1 VALUES(-9223372036854774000.0,0.0),(9223372036854775700.0,1844674407370954000.0);
+
+--error 1264
+INSERT INTO t1 (col1) VALUES(-9223372036854775809);
+--error 1264
+INSERT INTO t1 (col1) VALUES(9223372036854775808);
+--error 1264
+INSERT INTO t1 (col2) VALUES(-1);
+
+--error 1264
+INSERT INTO t1 (col2) VALUES(18446744073709551616);
+--error 1264
+INSERT INTO t1 (col1) VALUES('-9223372036854775809');
+--error 1264
+INSERT INTO t1 (col1) VALUES('9223372036854775808');
+--error 1264
+INSERT INTO t1 (col2) VALUES('-1');
+--error 1264
+INSERT INTO t1 (col2) VALUES('18446744073709551616');
+
+# Note that the following two double numbers are slighty bigger than max/min
+# bigint becasue of rounding errors when converting it to bigint
+--error 1264
+INSERT INTO t1 (col1) VALUES(-9223372036854785809.0);
+--error 1264
+INSERT INTO t1 (col1) VALUES(9223372036854785808.0);
+--error 1264
+INSERT INTO t1 (col2) VALUES(-1.0);
+--error 1264
+INSERT INTO t1 (col2) VALUES(18446744073709551616.0);
+
+# The following doesn't give an error as it's done in integer context
+# UPDATE t1 SET col1=col1 - 5000 WHERE col1 < 0;
+# UPDATE t1 SET col2 =col2 + 5000 WHERE col2 > 0;
+
+--error 1365
+UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
+--error 1365
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+--error 1264
+INSERT INTO t1 (col1) VALUES ('');
+--error 1264
+INSERT INTO t1 (col1) VALUES ('a59b');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('1a');
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+INSERT IGNORE INTO t1 values (1/0,1/0);
+INSERT IGNORE INTO t1 VALUES(-9223372036854775809,-1),(9223372036854775808,18446744073709551616);
+INSERT IGNORE INTO t1 VALUES('-9223372036854775809','-1'),('9223372036854775808','18446744073709551616');
+INSERT IGNORE INTO t1 VALUES(-9223372036854785809.0,-1.0),(9223372036854785808.0,18446744073709551616.0);
+UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test INSERT with NUMERIC
+
+CREATE TABLE t1 (col1 NUMERIC(4,2));
+INSERT INTO t1 VALUES (10.55),(10.5555),(0),(-10.55),(-10.5555),(11),(1e+01);
+-- Note that the +/-10.5555 is inserted as +/-10.55, not +/-10.56 !
+INSERT INTO t1 VALUES ('10.55'),('10.5555'),('-10.55'),('-10.5555'),('11'),('1e+01');
+
+-- The 2 following inserts should generate a warning, but doesn't yet
+-- because NUMERIC works like DECIMAL
+--error 1264
+INSERT INTO t1 VALUES (101.55);
+--error 1264
+INSERT INTO t1 VALUES (101);
+--error 1264
+INSERT INTO t1 VALUES (-101.55);
+--error 1264
+INSERT INTO t1 VALUES (1010.55);
+--error 1264
+INSERT INTO t1 VALUES (1010);
+-- The 2 following inserts should generate a warning, but doesn't yet
+-- because NUMERIC works like DECIMAL
+--error 1264
+INSERT INTO t1 VALUES ('101.55');
+--error 1264
+INSERT INTO t1 VALUES ('101');
+--error 1264
+INSERT INTO t1 VALUES ('-101.55');
+--error 1264
+INSERT INTO t1 VALUES ('-1010.55');
+--error 1264
+INSERT INTO t1 VALUES ('-100E+1');
+--error 1366
+INSERT INTO t1 VALUES ('-100E');
+--error 1264
+UPDATE t1 SET col1 =col1 * 50000 WHERE col1 =11;
+--error 1365
+UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
+--error 1365
+UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
+#--error 1265
+--error 1366
+INSERT INTO t1 (col1) VALUES ('');
+#--error 1265
+--error 1366
+INSERT INTO t1 (col1) VALUES ('a59b');
+--error 1366
+INSERT INTO t1 (col1) VALUES ('1a');
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+INSERT IGNORE INTO t1 values (1/0);
+INSERT IGNORE INTO t1 VALUES(1000),(-1000);
+INSERT IGNORE INTO t1 VALUES('1000'),('-1000');
+INSERT IGNORE INTO t1 VALUES(1000.0),(-1000.0);
+UPDATE IGNORE t1 SET col1=1/NULL where col1=0;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test INSERT with FLOAT
+
+CREATE TABLE t1 (col1 FLOAT, col2 FLOAT UNSIGNED);
+INSERT INTO t1 VALUES (-1.1E-37,0),(+3.4E+38,+3.4E+38);
+INSERT INTO t1 VALUES ('-1.1E-37',0),('+3.4E+38','+3.4E+38');
+# We don't give warnings for underflow
+INSERT INTO t1 (col1) VALUES (3E-46);
+--error 1264
+INSERT INTO t1 (col1) VALUES (+3.4E+39);
+--error 1264
+INSERT INTO t1 (col2) VALUES (-1.1E-3);
+--error 1264
+INSERT INTO t1 (col1) VALUES ('+3.4E+39');
+--error 1264
+INSERT INTO t1 (col2) VALUES ('-1.1E-3');
+--error 1264
+UPDATE t1 SET col1 =col1 * 5000 WHERE col1 > 0;
+--error 1365
+UPDATE t1 SET col2 =col2 / 0 WHERE col2 > 0;
+--error 1365
+UPDATE t1 SET col2= MOD(col2,0) WHERE col2 > 0;
+--error 1265
+INSERT INTO t1 (col1) VALUES ('');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('a59b');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('1a');
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+INSERT IGNORE INTO t1 (col1) VALUES (1/0);
+INSERT IGNORE INTO t1 VALUES (+3.4E+39,-3.4E+39);
+INSERT IGNORE INTO t1 VALUES ('+3.4E+39','-3.4E+39');
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test INSERT with DOUBLE
+
+CREATE TABLE t1 (col1 DOUBLE PRECISION, col2 DOUBLE PRECISION UNSIGNED);
+INSERT INTO t1 VALUES (-2.2E-307,0),(2E-307,0),(+1.7E+308,+1.7E+308);
+INSERT INTO t1 VALUES ('-2.2E-307',0),('-2E-307',0),('+1.7E+308','+1.7E+308');
+# We don't give warnings for underflow
+INSERT INTO t1 (col1) VALUES (-2.2E-330);
+--error 1367,1264
+INSERT INTO t1 (col1) VALUES (+1.7E+309);
+--error 1264
+INSERT INTO t1 (col2) VALUES (-1.1E-3);
+--error 1264
+INSERT INTO t1 (col1) VALUES ('+1.8E+309');
+--error 1264
+INSERT INTO t1 (col2) VALUES ('-1.2E-3');
+--error 1264
+UPDATE t1 SET col1 =col1 * 5000 WHERE col1 > 0;
+--error 1365
+UPDATE t1 SET col2 =col2 / 0 WHERE col2 > 0;
+--error 1365
+UPDATE t1 SET col2= MOD(col2,0) WHERE col2 > 0;
+--error 1265
+INSERT INTO t1 (col1) VALUES ('');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('a59b');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('1a');
+INSERT IGNORE INTO t1 (col1) VALUES ('2a');
+INSERT IGNORE INTO t1 (col1) values (1/0);
+--error 1367
+INSERT IGNORE INTO t1 VALUES (+1.9E+309,-1.9E+309);
+INSERT IGNORE INTO t1 VALUES ('+2.0E+309','-2.0E+309');
+# stupid...
+--replace_result -0 0 1.7976931348623e+308 1.79769313486232e+308
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Testing INSERT with CHAR/VARCHAR
+
+CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
+INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
+--error 1406
+INSERT INTO t1 (col1) VALUES ('hellobob');
+--error 1406
+INSERT INTO t1 (col2) VALUES ('hellobob');
+INSERT INTO t1 (col2) VALUES ('hello ');
+--error 1406
+UPDATE t1 SET col1 ='hellobob' WHERE col1 ='he';
+--error 1406
+UPDATE t1 SET col2 ='hellobob' WHERE col2 ='he';
+INSERT IGNORE INTO t1 VALUES ('hellobob', 'hellobob');
+UPDATE IGNORE t1 SET col2 ='hellotrudy' WHERE col2 ='he';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Testing INSERT with ENUM
+
+CREATE TABLE t1 (col1 enum('red','blue','green'));
+INSERT INTO t1 VALUES ('red'),('blue'),('green');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('yellow');
+--error 1265
+INSERT INTO t1 (col1) VALUES ('redd');
+--error 1265
+INSERT INTO t1 VALUES ('');
+--error 1265
+UPDATE t1 SET col1 ='yellow' WHERE col1 ='green';
+INSERT IGNORE INTO t1 VALUES ('yellow');
+UPDATE IGNORE t1 SET col1 ='yellow' WHERE col1 ='blue';
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Testing of insert of NULL in not NULL column
+
+CREATE TABLE t1 (col1 INT NOT NULL, col2 CHAR(5) NOT NULL, col3 DATE NOT NULL);
+INSERT INTO t1 VALUES (100, 'hello', '2004-08-20');
+INSERT INTO t1 (col1,col2,col3) VALUES (101, 'hell2', '2004-08-21');
+--error 1048
+INSERT INTO t1 (col1,col2,col3) VALUES (NULL, '', '2004-01-01');
+--error 1048
+INSERT INTO t1 (col1,col2,col3) VALUES (102, NULL, '2004-01-01');
+--error 1048
+INSERT INTO t1 VALUES (103,'',NULL);
+--error 1263
+UPDATE t1 SET col1=NULL WHERE col1 =100;
+--error 1263
+UPDATE t1 SET col2 =NULL WHERE col2 ='hello';
+--error 1263
+UPDATE t1 SET col2 =NULL where col3 IS NOT NULL;
+INSERT IGNORE INTO t1 values (NULL,NULL,NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Testing of default values
+
+CREATE TABLE t1 (col1 INT NOT NULL default 99, col2 CHAR(6) NOT NULL);
+SHOW CREATE TABLE t1;
+INSERT INTO t1 VALUES (1, 'hello');
+INSERT INTO t1 (col2) VALUES ('hello2');
+--error 1048
+INSERT INTO t1 (col2) VALUES (NULL);
+--error 1364
+INSERT INTO t1 (col1) VALUES (2);
+--error 1364
+INSERT INTO t1 VALUES(default(col1),default(col2));
+--error 1364
+INSERT INTO t1 (col1) SELECT 1;
+--error 1263
+INSERT INTO t1 SELECT 1,NULL;
+INSERT IGNORE INTO t1 values (NULL,NULL);
+INSERT IGNORE INTO t1 (col1) values (3);
+INSERT IGNORE INTO t1 () values ();
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Bug #9029 Traditional: Wrong SQLSTATE returned for string truncation
+#
+
+set sql_mode='traditional';
+create table t1 (charcol char(255), varcharcol varchar(255),
+binarycol binary(255), varbinarycol varbinary(255), tinytextcol tinytext,
+tinyblobcol tinyblob);
+--error 1406
+insert into t1 (charcol) values (repeat('x',256));
+--error 1406
+insert into t1 (varcharcol) values (repeat('x',256));
+--error 1406
+insert into t1 (binarycol) values (repeat('x',256));
+--error 1406
+insert into t1 (varbinarycol) values (repeat('x',256));
+--error 1406
+insert into t1 (tinytextcol) values (repeat('x',256));
+--error 1406
+insert into t1 (tinyblobcol) values (repeat('x',256));
+select * from t1;
+drop table t1;
+
+#
+# Bug #5902: STR_TO_DATE() didn't give errors in traditional mode
+#
+
+set sql_mode='traditional';
+create table t1 (col1 datetime);
+--error 1292
+insert into t1 values(STR_TO_DATE('31.10.2004 15.30 abc','%d.%m.%Y %H.%i'));
+--error 1411
+insert into t1 values(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+--error 1411
+insert into t1 values(STR_TO_DATE('2004.12.12 22:22:33 AM','%Y.%m.%d %r'));
+--error 1411
+insert into t1 values(STR_TO_DATE('2004.12.12 abc','%Y.%m.%d %T'));
+set sql_mode='';
+insert into t1 values(STR_TO_DATE('31.10.2004 15.30 abc','%d.%m.%Y %H.%i'));
+insert into t1 values(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
+insert into t1 values(STR_TO_DATE('2004.12.12 22:22:33 AM','%Y.%m.%d %r'));
+insert into t1 values(STR_TO_DATE('2004.12.12 abc','%Y.%m.%d %T'));
+
+# Some correct values, just to test the functions
+insert into t1 values(STR_TO_DATE('31.10.2004 15.30','%d.%m.%Y %H.%i'));
+insert into t1 values(STR_TO_DATE('2004.12.12 11:22:33 AM','%Y.%m.%d %r'));
+insert into t1 values(STR_TO_DATE('2004.12.12 10:22:59','%Y.%m.%d %T'));
+
+select * from t1;
+
+# Check that select don't abort even in strict mode (for now)
+set sql_mode='traditional';
+
+--disable_ps_warnings
+select count(*) from t1 where STR_TO_DATE('2004.12.12 10:22:61','%Y.%m.%d %T') IS NULL;
+--enable_ps_warnings
+
+drop table t1;
+
+#
+# Check insert with wrong CAST() (Bug #5912)
+#
+
+create table t1 (col1 char(3), col2 integer);
+--error 1292
+insert into t1 (col1) values (cast(1000 as char(3)));
+--error 1292
+insert into t1 (col1) values (cast(1000E+0 as char(3)));
+--error 1292
+insert into t1 (col1) values (cast(1000.0 as char(3)));
+--error 1292
+insert into t1 (col2) values (cast('abc' as signed integer));
+--error 1292
+insert into t1 (col2) values (10E+0 + 'a');
+--error 1292
+insert into t1 (col2) values (cast('10a' as unsigned integer));
+insert into t1 (col2) values (cast('10' as unsigned integer));
+insert into t1 (col2) values (cast('10' as signed integer));
+insert into t1 (col2) values (10E+0 + '0 ');
+select * from t1;
+drop table t1;
+
+#
+# Zero dates using numbers was not checked properly (Bug #5933 & #6145)
+#
+
+create table t1 (col1 date, col2 datetime, col3 timestamp);
+--error 1292
+insert into t1 values (0,0,0);
+--error 1292
+insert into t1 values (0.0,0.0,0.0);
+--error 1292
+insert into t1 (col1) values (convert('0000-00-00',date));
+--error 1292
+insert into t1 (col1) values (cast('0000-00-00' as date));
+
+set sql_mode='no_zero_date';
+insert into t1 values (0,0,0);
+insert into t1 values (0.0,0.0,0.0);
+drop table t1;
+set sql_mode='traditional';
+create table t1 (col1 date);
+insert ignore into t1 values ('0000-00-00');
+--error 1292
+insert into t1 select * from t1;
+insert ignore into t1 values ('0000-00-00');
+insert ignore into t1 (col1) values (cast('0000-00-00' as date));
+--error 1292
+insert into t1 select * from t1;
+--error 1292
+alter table t1 modify col1 datetime;
+alter ignore table t1 modify col1 datetime;
+--error 1292
+insert into t1 select * from t1;
+select * from t1;
+drop table t1;
+
+#
+# Test of inserting an invalid value via a stored procedure (Bug #5907)
+#
+create table t1 (col1 tinyint);
+drop procedure if exists t1;
+delimiter |;
+create procedure t1 () begin declare exit handler for sqlexception
+select'a'; insert into t1 values (200); end;|
+delimiter ;|
+call t1();
+select * from t1;
+drop procedure t1;
+drop table t1;
+
+#
+# Restore mode
+#
+set sql_mode=@org_mode;
+
+# Test fields with no default value that are NOT NULL (Bug #5986)
+SET @@sql_mode = 'traditional';
+CREATE TABLE t1 (i int not null);
+--error 1364
+INSERT INTO t1 VALUES ();
+--error 1364
+INSERT INTO t1 VALUES (DEFAULT);
+--error 1364
+INSERT INTO t1 VALUES (DEFAULT(i));
+ALTER TABLE t1 ADD j int;
+--error 1364
+INSERT INTO t1 SET j = 1;
+--error 1364
+INSERT INTO t1 SET j = 1, i = DEFAULT;
+--error 1364
+INSERT INTO t1 SET j = 1, i = DEFAULT(i);
+--error 1364
+INSERT INTO t1 VALUES (DEFAULT,1);
+DROP TABLE t1;
+SET @@sql_mode = '';
+CREATE TABLE t1 (i int not null);
+INSERT INTO t1 VALUES ();
+INSERT INTO t1 VALUES (DEFAULT);
+# DEFAULT(i) is an error even with the default sql_mode
+--error 1364
+INSERT INTO t1 VALUES (DEFAULT(i));
+ALTER TABLE t1 ADD j int;
+INSERT INTO t1 SET j = 1;
+INSERT INTO t1 SET j = 1, i = DEFAULT;
+--error 1364
+INSERT INTO t1 SET j = 1, i = DEFAULT(i);
+INSERT INTO t1 VALUES (DEFAULT,1);
+DROP TABLE t1;
+
+#
+# Bugs #8295 and #8296: varchar and varbinary conversion
+#
+
+set @@sql_mode='traditional';
+--error 1074
+create table t1(a varchar(65537));
+--error 1074
+create table t1(a varbinary(65537));
+
+#
+# Bug #9881: problem with altering table
+#
+
+set @@sql_mode='traditional';
+create table t1(a int, b date not null);
+alter table t1 modify a bigint unsigned not null;
+show create table t1;
+drop table t1;
+
+#
+# Bug #5906: handle invalid date due to conversion
+#
+set @@sql_mode='traditional';
+create table t1 (d date);
+--error 1292
+insert into t1 values ('2000-10-00');
+--error 1292
+insert into t1 values (1000);
+insert into t1 values ('2000-10-01');
+--error 1292
+update t1 set d = 1100;
+select * from t1;
+drop table t1;
+
+#
+# Bug #11964: alter table with timestamp field
+#
+
+set @@sql_mode='traditional';
+create table t1(a int, b timestamp);
+alter table t1 add primary key(a);
+show create table t1;
+drop table t1;
+create table t1(a int, b timestamp default 20050102030405);
+alter table t1 add primary key(a);
+show create table t1;
+drop table t1;
+
+#
+# BIT fields
+#
+
+set @@sql_mode='traditional';
+create table t1(a bit(2));
+--error 1406
+insert into t1 values(b'101');
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 3d21456ee45..5020902009d 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -46,9 +46,9 @@ SELECT ROW(1,2,3) > (SELECT 1,2,1);
SELECT ROW(1,2,3) = (SELECT 1,2,NULL);
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
-SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
+SELECT (SELECT 1.5,2,'a') = ROW('1.5b',2,'b');
SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
-SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,'2','a');
SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
-- error 1241
@@ -352,7 +352,9 @@ INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
select * from t1;
INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2;
select * from t1;
+# After this, only data based on old t1 records should have been added.
INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
+select * from t1;
-- error 1054
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
@@ -507,6 +509,9 @@ select ROW(1, 1, 'a') IN (select b,a,c from t1 where c='b' or c='a');
select ROW(1, 1, 'a') IN (select b,a,c from t1 limit 2);
drop table t1;
+#
+# DO & SET
+#
create table t1 (a int);
insert into t1 values (1);
do @a:=(SELECT a from t1);
@@ -691,7 +696,7 @@ CREATE TABLE `t1` (
INSERT INTO t1 VALUES (1);
UPDATE t1 SET i=i+(SELECT MAX(i) FROM (SELECT 1) t) WHERE i=(SELECT MAX(i));
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
--- error 1109
+-- error 1054
UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t);
select * from t1;
drop table t1;
@@ -1000,7 +1005,7 @@ create table t2 (s1 int);
select * from t1 where (select count(*) from t2 where t1.s2) = 1;
-- error 1054
select * from t1 where (select count(*) from t2 group by t1.s2) = 1;
--- error 1109
+-- error 1054
select count(*) from t2 group by t1.s2;
drop table t1, t2;
@@ -1128,7 +1133,9 @@ CREATE TABLE t2 (id INT);
INSERT INTO t1 VALUES (1), (2);
INSERT INTO t2 VALUES (1);
SELECT t1.id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id);
+SELECT id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id);
SELECT t1.id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id) ORDER BY t1.id;
+SELECT id, ( SELECT COUNT(t.id) FROM t2 AS t WHERE t.id = t1.id ) AS c FROM t1 LEFT JOIN t2 USING (id) ORDER BY id;
DROP TABLE t1,t2;
#
@@ -1815,3 +1822,144 @@ SELECT * FROM t1
DROP TABLE t1,t2,t3;
# End of 4.1 tests
+
+#
+#decimal-related tests
+#
+create table t1 (df decimal(5,1));
+insert into t1 values(1.1);
+insert into t1 values(2.2);
+
+select * from t1 where df <= all (select avg(df) from t1 group by df);
+select * from t1 where df >= all (select avg(df) from t1 group by df);
+drop table t1;
+
+create table t1 (df decimal(5,1));
+insert into t1 values(1.1);
+select 1.1 * exists(select * from t1);
+drop table t1;
+
+CREATE TABLE t1 (
+ grp int(11) default NULL,
+ a decimal(10,2) default NULL);
+
+insert into t1 values (1, 1), (2, 2), (2, 3), (3, 4), (3, 5), (3, 6), (NULL, NULL);
+select * from t1;
+select min(a) from t1 group by grp;
+drop table t1;
+
+#
+# Test for bug #9338: lame substitution of c1 instead of c2
+#
+
+CREATE table t1 ( c1 integer );
+INSERT INTO t1 VALUES ( 1 );
+INSERT INTO t1 VALUES ( 2 );
+INSERT INTO t1 VALUES ( 3 );
+
+CREATE TABLE t2 ( c2 integer );
+INSERT INTO t2 VALUES ( 1 );
+INSERT INTO t2 VALUES ( 4 );
+INSERT INTO t2 VALUES ( 5 );
+
+SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2 WHERE c2 IN (1);
+
+SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2
+ WHERE c2 IN ( SELECT c2 FROM t2 WHERE c2 IN ( 1 ) );
+
+DROP TABLE t1,t2;
+
+#
+# Test for bug #9516: wrong evaluation of not_null_tables attribute in SQ
+#
+CREATE TABLE t1 ( c1 integer );
+INSERT INTO t1 VALUES ( 1 );
+INSERT INTO t1 VALUES ( 2 );
+INSERT INTO t1 VALUES ( 3 );
+INSERT INTO t1 VALUES ( 6 );
+
+CREATE TABLE t2 ( c2 integer );
+INSERT INTO t2 VALUES ( 1 );
+INSERT INTO t2 VALUES ( 4 );
+INSERT INTO t2 VALUES ( 5 );
+INSERT INTO t2 VALUES ( 6 );
+
+CREATE TABLE t3 ( c3 integer );
+INSERT INTO t3 VALUES ( 7 );
+INSERT INTO t3 VALUES ( 8 );
+
+SELECT c1,c2 FROM t1 LEFT JOIN t2 ON c1 = c2
+ WHERE EXISTS (SELECT c3 FROM t3 WHERE c2 IS NULL );
+
+DROP TABLE t1,t2,t3;
+
+#
+# Item_int_with_ref check (BUG#10020)
+#
+CREATE TABLE `t1` (
+ `itemid` bigint(20) unsigned NOT NULL auto_increment,
+ `sessionid` bigint(20) unsigned default NULL,
+ `time` int(10) unsigned NOT NULL default '0',
+ `type` set('A','D','E','F','G','I','L','N','U') collate latin1_general_ci NOT
+NULL default '',
+ `data` text collate latin1_general_ci NOT NULL,
+ PRIMARY KEY (`itemid`)
+) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+INSERT INTO `t1` VALUES (1, 1, 1, 'D', '');
+CREATE TABLE `t2` (
+ `sessionid` bigint(20) unsigned NOT NULL auto_increment,
+ `pid` int(10) unsigned NOT NULL default '0',
+ `date` int(10) unsigned NOT NULL default '0',
+ `ip` varchar(15) collate latin1_general_ci NOT NULL default '',
+ PRIMARY KEY (`sessionid`)
+) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+INSERT INTO `t2` VALUES (1, 1, 1, '10.10.10.1');
+SELECT s.ip, count( e.itemid ) FROM `t1` e JOIN t2 s ON s.sessionid = e.sessionid WHERE e.sessionid = ( SELECT sessionid FROM t2 ORDER BY sessionid DESC LIMIT 1 ) GROUP BY s.ip HAVING count( e.itemid ) >0 LIMIT 0 , 30;
+drop tables t1,t2;
+
+#
+# Correct building of equal fields list (do not include outer
+# fields) (BUG#6384)
+#
+CREATE TABLE t1 (EMPNUM CHAR(3));
+CREATE TABLE t2 (EMPNUM CHAR(3) );
+INSERT INTO t1 VALUES ('E1'),('E2');
+INSERT INTO t2 VALUES ('E1');
+DELETE FROM t1
+WHERE t1.EMPNUM NOT IN
+ (SELECT t2.EMPNUM
+ FROM t2
+ WHERE t1.EMPNUM = t2.EMPNUM);
+select * from t1;
+DROP TABLE t1,t2;
+
+#
+# Test for bug #11487: range access in a subquery
+#
+
+CREATE TABLE t1(select_id BIGINT, values_id BIGINT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TABLE t2 (select_id BIGINT, values_id BIGINT,
+ PRIMARY KEY(select_id,values_id));
+INSERT INTO t2 VALUES (0, 1), (0, 2), (0, 3), (1, 5);
+
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+ WHERE select_id IN (1, 0));
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+ WHERE select_id BETWEEN 0 AND 1);
+SELECT values_id FROM t1
+WHERE values_id IN (SELECT values_id FROM t2
+ WHERE select_id = 0 OR select_id = 1);
+
+DROP TABLE t1, t2;
+
+# BUG#11821 : Select from subselect using aggregate function on an enum
+# segfaults:
+create table t1 (fld enum('0','1'));
+insert into t1 values ('1');
+select * from (select max(fld) from t1) as foo;
+drop table t1;
+
+
diff --git a/mysql-test/t/sum_distinct-big.test b/mysql-test/t/sum_distinct-big.test
new file mode 100644
index 00000000000..0859f4b3d89
--- /dev/null
+++ b/mysql-test/t/sum_distinct-big.test
@@ -0,0 +1,67 @@
+#
+# Various tests for SUM(DISTINCT ...)
+#
+
+--source include/big_test.inc
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+#
+# Test the case when distinct values doesn't fit in memory and
+# filesort is used (see uniques.cc:merge_walk)
+#
+
+CREATE TABLE t1 (id INTEGER);
+CREATE TABLE t2 (id INTEGER);
+
+INSERT INTO t1 (id) VALUES (1), (1), (1),(1);
+INSERT INTO t1 (id) SELECT id FROM t1; /* 8 */
+INSERT INTO t1 (id) SELECT id FROM t1; /* 12 */
+INSERT INTO t1 (id) SELECT id FROM t1; /* 16 */
+INSERT INTO t1 (id) SELECT id FROM t1; /* 20 */
+INSERT INTO t1 (id) SELECT id FROM t1; /* 24 */
+INSERT INTO t1 SELECT id+1 FROM t1;
+INSERT INTO t1 SELECT id+2 FROM t1;
+INSERT INTO t1 SELECT id+4 FROM t1;
+INSERT INTO t1 SELECT id+8 FROM t1;
+INSERT INTO t1 SELECT id+16 FROM t1;
+INSERT INTO t1 SELECT id+32 FROM t1;
+INSERT INTO t1 SELECT id+64 FROM t1;
+INSERT INTO t1 SELECT id+128 FROM t1;
+INSERT INTO t1 SELECT id+256 FROM t1;
+INSERT INTO t1 SELECT id+512 FROM t1;
+
+# Just test that AVG(DISTINCT) is there
+SELECT AVG(DISTINCT id) FROM t1 GROUP BY id % 13;
+SELECT SUM(DISTINCT id)/COUNT(DISTINCT id) FROM t1 GROUP BY id % 13;
+
+INSERT INTO t1 SELECT id+1024 FROM t1;
+INSERT INTO t1 SELECT id+2048 FROM t1;
+INSERT INTO t1 SELECT id+4096 FROM t1;
+INSERT INTO t1 SELECT id+8192 FROM t1;
+INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand();
+
+# SELECT '++++++++++++++++++++++++++++++++++++++++++++++++++';
+
+SELECT SUM(DISTINCT id) sm FROM t1;
+SELECT SUM(DISTINCT id) sm FROM t2;
+SELECT SUM(DISTINCT id) sm FROM t1 group by id % 13;
+
+# this limit for max_heap_table_size is set to force testing the case, when
+# all distinct sum values can not fit in memory and must be stored in a
+# temporary table
+
+SET max_heap_table_size=16384;
+
+# to check that max_heap_table_size was actually set (hard limit for minimum
+# max_heap_table_size is set in mysqld.cc):
+
+SHOW variables LIKE 'max_heap_table_size';
+
+SELECT SUM(DISTINCT id) sm FROM t1;
+SELECT SUM(DISTINCT id) sm FROM t2;
+SELECT SUM(DISTINCT id) sm FROM t1 GROUP BY id % 13;
+
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/t/sum_distinct.test b/mysql-test/t/sum_distinct.test
new file mode 100644
index 00000000000..c58155a8e25
--- /dev/null
+++ b/mysql-test/t/sum_distinct.test
@@ -0,0 +1,95 @@
+#
+# Various tests for SUM(DISTINCT ...)
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+CREATE TABLE t1 (
+ id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ gender CHAR(1),
+ name VARCHAR(20)
+);
+
+# According to ANSI SQL, SUM(DISTINCT ...) should return NULL for empty
+# record set
+
+SELECT SUM(DISTINCT LENGTH(name)) s1 FROM t1;
+
+# According to ANSI SQL, SUM(DISTINCT ...) should return NULL for records sets
+# entirely consisting of NULLs
+
+INSERT INTO t1 (gender, name) VALUES (NULL, NULL);
+INSERT INTO t1 (gender, name) VALUES (NULL, NULL);
+INSERT INTO t1 (gender, name) VALUES (NULL, NULL);
+
+SELECT SUM(DISTINCT LENGTH(name)) s1 FROM t1;
+
+
+# Filling table with t1
+
+INSERT INTO t1 (gender, name) VALUES ('F', 'Helen'), ('F', 'Anastasia'),
+('F', 'Katherine'), ('F', 'Margo'), ('F', 'Magdalene'), ('F', 'Mary');
+
+CREATE TABLE t2 SELECT name FROM t1;
+
+SELECT (SELECT SUM(DISTINCT LENGTH(name)) FROM t1) FROM t2;
+
+DROP TABLE t2;
+
+INSERT INTO t1 (gender, name) VALUES ('F', 'Eva'), ('F', 'Sofia'),
+('F', 'Sara'), ('F', 'Golda'), ('F', 'Toba'), ('F', 'Victory'),
+('F', 'Faina'), ('F', 'Miriam'), ('F', 'Beki'), ('F', 'America'),
+('F', 'Susan'), ('F', 'Glory'), ('F', 'Priscilla'), ('F', 'Rosmary'),
+('F', 'Rose'), ('F', 'Margareth'), ('F', 'Elizabeth'), ('F', 'Meredith'),
+('F', 'Julie'), ('F', 'Xenia'), ('F', 'Zena'), ('F', 'Olga'),
+('F', 'Brunhilda'), ('F', 'Nataly'), ('F', 'Lara'), ('F', 'Svetlana'),
+('F', 'Grethem'), ('F', 'Irene');
+
+SELECT
+ SUM(DISTINCT LENGTH(name)) s1,
+ SUM(DISTINCT SUBSTRING(NAME, 1, 3)) s2,
+ SUM(DISTINCT LENGTH(SUBSTRING(name, 1, 4))) s3
+FROM t1;
+
+SELECT
+ SUM(DISTINCT LENGTH(g1.name)) s1,
+ SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2,
+ SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3
+FROM t1 g1, t1 g2, t1 g3;
+
+SELECT
+ SUM(DISTINCT LENGTH(g1.name)) s1,
+ SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2,
+ SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3
+FROM t1 g1, t1 g2, t1 g3 GROUP BY LENGTH(SUBSTRING(g3.name, 5, 10));
+
+# here we explicitly request summing through temporary table (so
+# Item_sum_sum_distinct::copy_or_same() is called)
+
+SELECT SQL_BUFFER_RESULT
+ SUM(DISTINCT LENGTH(name)) s1,
+ SUM(DISTINCT SUBSTRING(NAME, 1, 3)) s2,
+ SUM(DISTINCT LENGTH(SUBSTRING(name, 1, 4))) s3
+FROM t1;
+
+SELECT SQL_BUFFER_RESULT
+ SUM(DISTINCT LENGTH(g1.name)) s1,
+ SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2,
+ SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3
+FROM t1 g1, t1 g2, t1 g3 GROUP BY LENGTH(SUBSTRING(g3.name, 5, 10));
+
+# this test demonstrates that strings are automatically converted to numbers
+# before summing
+
+SET @l=1;
+UPDATE t1 SET name=CONCAT(name, @l:=@l+1);
+
+SELECT SUM(DISTINCT RIGHT(name, 1)) FROM t1;
+
+# this is a test case for ordinary t1
+
+SELECT SUM(DISTINCT id) FROM t1;
+SELECT SUM(DISTINCT id % 11) FROM t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
index 85ad04aa556..b7a7e83d569 100644
--- a/mysql-test/t/symlink.test
+++ b/mysql-test/t/symlink.test
@@ -49,6 +49,7 @@ check table t9;
optimize table t9;
repair table t9;
alter table t9 add column c int not null;
+
--replace_result $MYSQL_TEST_DIR TEST_DIR
show create table t9;
@@ -64,6 +65,9 @@ drop table t1;
# Note that we are using the above table t9 here!
#
+--replace_result $MYSQL_TEST_DIR TEST_DIR
+SHOW CREATE TABLE t9;
+
disable_query_log;
--error 1103,1103
create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="tmp";
@@ -78,9 +82,11 @@ create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, p
--error 1103,1103
create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path";
---error 1,1
+# Should fail becasue the file t9.MYI already exist in 'run'
+--error 1,1,1105
eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="$MYSQL_TEST_DIR/var/run";
+# Should fail becasue the file t9.MYD already exist in 'tmp'
--error 1,1
eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="$MYSQL_TEST_DIR/var/tmp";
enable_query_log;
diff --git a/mysql-test/t/synchronization.test b/mysql-test/t/synchronization.test
index ec7c7dd6545..c7696195ee0 100644
--- a/mysql-test/t/synchronization.test
+++ b/mysql-test/t/synchronization.test
@@ -1,7 +1,12 @@
#
-# Test for Bug #2385 CREATE TABLE LIKE lacks locking on source and destination table
+# Test for Bug #2385 CREATE TABLE LIKE lacks locking on source and destination
+# table
#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
diff --git a/mysql-test/t/system_mysql_db.test b/mysql-test/t/system_mysql_db.test
index 0892af77fb2..27c17da2731 100644
--- a/mysql-test/t/system_mysql_db.test
+++ b/mysql-test/t/system_mysql_db.test
@@ -2,6 +2,11 @@
# This test must examine integrity of system database "mysql"
#
+# First delete some tables maybe left over from previous tests
+--disable_warnings
+drop table if exists t1,t1aa,t2aa;
+--enable_warnings
+
-- disable_query_log
use mysql;
-- enable_query_log
diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test
index dc3047a8564..4621b2f50ef 100644
--- a/mysql-test/t/system_mysql_db_fix.test
+++ b/mysql-test/t/system_mysql_db_fix.test
@@ -4,6 +4,14 @@
#
# This is the test for mysql_fix_privilege_tables
#
+# Note: If this test fails, don't be confused about the errors reported
+# by mysql-test-run; This shows warnings from generated by
+# mysql_fix_system_tables which should be ignored.
+# Instead, concentrate on the errors in r/system_mysql_db.reject
+
+--disable_warnings
+drop table if exists t1,t1aa,t2aa;
+--enable_warnings
-- disable_result_log
-- disable_query_log
@@ -77,7 +85,7 @@ INSERT INTO user VALUES ('localhost','', '','N','N','N','N','N','N','N','N','
-- disable_query_log
-DROP TABLE db, host, user, func, tables_priv, columns_priv, help_category, help_keyword, help_relation, help_topic, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type;
+DROP TABLE db, host, user, func, tables_priv, columns_priv, procs_priv, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type;
-- enable_query_log
diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test
index 309855d0b2d..9a7678ed712 100644
--- a/mysql-test/t/temp_table.test
+++ b/mysql-test/t/temp_table.test
@@ -90,6 +90,20 @@ select * from t1 group by d;
show status like "created_tmp%tables";
drop table t1;
+# Fix for BUG#8921: Check that temporary table is ingored by view commands.
+create temporary table t1 as select 'This is temp. table' A;
+create view t1 as select 'This is view' A;
+select * from t1;
+show create table t1;
+show create view t1;
+drop view t1;
+select * from t1;
+create view t1 as select 'This is view again' A;
+select * from t1;
+drop table t1;
+select * from t1;
+drop view t1;
+
# Bug #8497: tmpdir with extra slashes would cause failures
#
create table t1 (a int, b int, index(a), index(b));
diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test
index 523249a3a2c..069c19341e4 100644
--- a/mysql-test/t/timezone2.test
+++ b/mysql-test/t/timezone2.test
@@ -48,6 +48,11 @@ 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');
+# Values around and in spring time-gap
+insert into t1 (i, ts) values
+ (unix_timestamp(20030330015959),20030330015959),
+ (unix_timestamp(20030330023000),20030330023000),
+ (unix_timestamp(20030330030000),20030330030000);
# Normal value with DST
insert into t1 (i, ts) values
(unix_timestamp('2003-05-01 00:00:00'),'2003-05-01 00:00:00');
@@ -200,7 +205,7 @@ select convert_tz(ts, @@time_zone, 'Japan') from t1;
drop table t1;
#
-# Test for bug #7705 "CONVERT_TZ() crashes with subquery/WHERE on index
+# Test for bug #7705 "CONVERT_TZ() crashes with subquery/WHERE on index
# column". Queries in which one of time zone arguments of CONVERT_TZ() is
# determined as constant only at val() stage (not at fix_fields() stage),
# should not crash server.
diff --git a/mysql-test/t/timezone_grant.test b/mysql-test/t/timezone_grant.test
index d02901b162b..f94d86eb266 100644
--- a/mysql-test/t/timezone_grant.test
+++ b/mysql-test/t/timezone_grant.test
@@ -28,9 +28,9 @@ select convert_tz(b, 'Europe/Moscow', 'UTC') from t1;
update t1, t2 set t1.b = convert_tz('2004-10-21 19:00:00', 'Europe/Moscow', 'UTC')
where t1.a = t2.c and t2.d = (select max(d) from t2);
# But still these two statements should not work:
---error 1044
+--error 1142
select * from mysql.time_zone_name;
---error 1044
+--error 1142
select Name, convert_tz('2004-10-21 19:00:00', Name, 'UTC') from mysql.time_zone_name;
#
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
new file mode 100644
index 00000000000..cd79eb82ace
--- /dev/null
+++ b/mysql-test/t/trigger.test
@@ -0,0 +1,877 @@
+#
+# Basic triggers test
+#
+
+--disable_warnings
+drop table if exists t1, t2, t3;
+drop view if exists v1;
+drop database if exists mysqltest;
+drop function if exists f1;
+drop procedure if exists p1;
+--enable_warnings
+
+# Create additional connections used through test
+connect (addconroot1, localhost, root,,);
+connect (addconroot2, localhost, root,,);
+connection default;
+
+create table t1 (i int);
+
+# let us test some very simple trigger
+create trigger trg before insert on t1 for each row set @a:=1;
+set @a:=0;
+select @a;
+insert into t1 values (1);
+select @a;
+drop trigger trg;
+
+# let us test simple trigger reading some values
+create trigger trg before insert on t1 for each row set @a:=new.i;
+insert into t1 values (123);
+select @a;
+drop trigger trg;
+
+drop table t1;
+
+# Let us test before insert trigger
+# Such triggers can be used for setting complex default values
+create table t1 (i int not null, j int);
+delimiter |;
+create trigger trg before insert on t1 for each row
+begin
+ if isnull(new.j) then
+ set new.j:= new.i * 10;
+ end if;
+end|
+insert into t1 (i) values (1)|
+insert into t1 (i,j) values (2, 3)|
+select * from t1|
+drop trigger trg|
+drop table t1|
+delimiter ;|
+
+# After insert trigger
+# Useful for aggregating data
+create table t1 (i int not null primary key);
+create trigger trg after insert on t1 for each row
+ set @a:= if(@a,concat(@a, ":", new.i), new.i);
+set @a:="";
+insert into t1 values (2),(3),(4),(5);
+select @a;
+drop trigger trg;
+drop table t1;
+
+# PS doesn't work with multi-row statements
+--disable_ps_protocol
+# Before update trigger
+# (In future we will achieve this via proper error handling in triggers)
+create table t1 (aid int not null primary key, balance int not null default 0);
+insert into t1 values (1, 1000), (2,3000);
+delimiter |;
+create trigger trg before update on t1 for each row
+begin
+ declare loc_err varchar(255);
+ if abs(new.balance - old.balance) > 1000 then
+ set new.balance:= old.balance;
+ set loc_err := concat("Too big change for aid = ", new.aid);
+ set @update_failed:= if(@update_failed, concat(@a, ":", loc_err), loc_err);
+ end if;
+end|
+set @update_failed:=""|
+update t1 set balance=1500|
+select @update_failed;
+select * from t1|
+drop trigger trg|
+drop table t1|
+delimiter ;|
+--enable_ps_protocol
+
+# After update trigger
+create table t1 (i int);
+insert into t1 values (1),(2),(3),(4);
+create trigger trg after update on t1 for each row
+ set @total_change:=@total_change + new.i - old.i;
+set @total_change:=0;
+update t1 set i=3;
+select @total_change;
+drop trigger trg;
+drop table t1;
+
+# Before delete trigger
+# This can be used for aggregation too :)
+create table t1 (i int);
+insert into t1 values (1),(2),(3),(4);
+create trigger trg before delete on t1 for each row
+ set @del_sum:= @del_sum + old.i;
+set @del_sum:= 0;
+delete from t1 where i <= 3;
+select @del_sum;
+drop trigger trg;
+drop table t1;
+
+# After delete trigger.
+# Just run out of imagination.
+create table t1 (i int);
+insert into t1 values (1),(2),(3),(4);
+create trigger trg after delete on t1 for each row set @del:= 1;
+set @del:= 0;
+delete from t1 where i <> 0;
+select @del;
+drop trigger trg;
+drop table t1;
+
+# Several triggers on one table
+create table t1 (i int, j int);
+
+delimiter |;
+create trigger trg1 before insert on t1 for each row
+begin
+ if new.j > 10 then
+ set new.j := 10;
+ end if;
+end|
+create trigger trg2 before update on t1 for each row
+begin
+ if old.i % 2 = 0 then
+ set new.j := -1;
+ end if;
+end|
+create trigger trg3 after update on t1 for each row
+begin
+ if new.j = -1 then
+ set @fired:= "Yes";
+ end if;
+end|
+delimiter ;|
+set @fired:="";
+insert into t1 values (1,2),(2,3),(3,14);
+select @fired;
+select * from t1;
+update t1 set j= 20;
+select @fired;
+select * from t1;
+
+drop trigger trg1;
+drop trigger trg2;
+drop trigger trg3;
+drop table t1;
+
+
+# Let us test how triggers work for special forms of INSERT such as
+# REPLACE and INSERT ... ON DUPLICATE KEY UPDATE
+create table t1 (id int not null primary key, data int);
+create trigger t1_bi before insert on t1 for each row
+ set @log:= concat(@log, "(BEFORE_INSERT: new=(id=", new.id, ", data=", new.data,"))");
+create trigger t1_ai after insert on t1 for each row
+ set @log:= concat(@log, "(AFTER_INSERT: new=(id=", new.id, ", data=", new.data,"))");
+create trigger t1_bu before update on t1 for each row
+ set @log:= concat(@log, "(BEFORE_UPDATE: old=(id=", old.id, ", data=", old.data,
+ ") new=(id=", new.id, ", data=", new.data,"))");
+create trigger t1_au after update on t1 for each row
+ set @log:= concat(@log, "(AFTER_UPDATE: old=(id=", old.id, ", data=", old.data,
+ ") new=(id=", new.id, ", data=", new.data,"))");
+create trigger t1_bd before delete on t1 for each row
+ set @log:= concat(@log, "(BEFORE_DELETE: old=(id=", old.id, ", data=", old.data,"))");
+create trigger t1_ad after delete on t1 for each row
+ set @log:= concat(@log, "(AFTER_DELETE: old=(id=", old.id, ", data=", old.data,"))");
+# Simple INSERT - both triggers should be called
+set @log:= "";
+insert into t1 values (1, 1);
+select @log;
+# INSERT IGNORE for already existing key - only before trigger should fire
+set @log:= "";
+insert ignore t1 values (1, 2);
+select @log;
+# REPLACE: before insert trigger should be called for both records,
+# but then for first one update will be executed (and both update
+# triggers should fire). For second after insert trigger will be
+# called as for usual insert
+set @log:= "";
+replace t1 values (1, 3), (2, 2);
+select @log;
+# Now let us change table in such way that REPLACE on won't be executed
+# using update.
+alter table t1 add ts timestamp default now();
+set @log:= "";
+# This REPLACE should be executed via DELETE and INSERT so proper
+# triggers should be invoked.
+replace t1 (id, data) values (1, 4);
+select @log;
+# Finally let us test INSERT ... ON DUPLICATE KEY UPDATE ...
+set @log:= "";
+insert into t1 (id, data) values (1, 5), (3, 3) on duplicate key update data= data + 2;
+select @log;
+
+# This also drops associated triggers
+drop table t1;
+
+
+#
+# Let us test triggers which access other tables.
+#
+# Trivial trigger which inserts data into another table
+create table t1 (id int primary key, data varchar(10), fk int);
+create table t2 (event varchar(100));
+create table t3 (id int primary key);
+create trigger t1_ai after insert on t1 for each row
+ insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "'"));
+insert into t1 (id, data) values (1, "one"), (2, "two");
+select * from t1;
+select * from t2;
+drop trigger t1_ai;
+# Trigger which uses couple of tables (and partially emulates FK constraint)
+delimiter |;
+create trigger t1_bi before insert on t1 for each row
+begin
+ if exists (select id from t3 where id=new.fk) then
+ insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "' fk=", new.fk));
+ else
+ insert into t2 values (concat("INSERT INTO t1 FAILED id=", new.id, " data='", new.data, "' fk=", new.fk));
+ set new.id= NULL;
+ end if;
+end|
+delimiter ;|
+insert into t3 values (1);
+--error 1048
+insert into t1 values (4, "four", 1), (5, "five", 2);
+select * from t1;
+select * from t2;
+drop table t1, t2, t3;
+# Trigger which invokes function
+create table t1 (id int primary key, data varchar(10));
+create table t2 (seq int);
+insert into t2 values (10);
+create function f1 () returns int return (select max(seq) from t2);
+delimiter |;
+create trigger t1_bi before insert on t1 for each row
+begin
+ if new.id > f1() then
+ set new.id:= f1();
+ end if;
+end|
+delimiter ;|
+insert into t1 values (1, "first");
+insert into t1 values (f1(), "max");
+select * from t1;
+drop table t1, t2;
+drop function f1;
+# Trigger which forces invocation of another trigger
+# (emulation of FK on delete cascade policy)
+create table t1 (id int primary key, fk_t2 int);
+create table t2 (id int primary key, fk_t3 int);
+create table t3 (id int primary key);
+insert into t1 values (1,1), (2,1), (3,2);
+insert into t2 values (1,1), (2,2);
+insert into t3 values (1), (2);
+create trigger t3_ad after delete on t3 for each row
+ delete from t2 where fk_t3=old.id;
+create trigger t2_ad after delete on t2 for each row
+ delete from t1 where fk_t2=old.id;
+delete from t3 where id = 1;
+select * from t1 left join (t2 left join t3 on t2.fk_t3 = t3.id) on t1.fk_t2 = t2.id;
+drop table t1, t2, t3;
+# Trigger which assigns value selected from table to field of row
+# being inserted/updated.
+create table t1 (id int primary key, copy int);
+create table t2 (id int primary key, data int);
+insert into t2 values (1,1), (2,2);
+create trigger t1_bi before insert on t1 for each row
+ set new.copy= (select data from t2 where id = new.id);
+create trigger t1_bu before update on t1 for each row
+ set new.copy= (select data from t2 where id = new.id);
+insert into t1 values (1,3), (2,4), (3,3);
+update t1 set copy= 1 where id = 2;
+select * from t1;
+drop table t1, t2;
+
+#
+# Test of wrong column specifiers in triggers
+#
+create table t1 (i int);
+create table t3 (i int);
+
+--error 1363
+create trigger trg before insert on t1 for each row set @a:= old.i;
+--error 1363
+create trigger trg before delete on t1 for each row set @a:= new.i;
+--error 1362
+create trigger trg before update on t1 for each row set old.i:=1;
+--error 1363
+create trigger trg before delete on t1 for each row set new.i:=1;
+--error 1362
+create trigger trg after update on t1 for each row set new.i:=1;
+--error 1054
+create trigger trg before update on t1 for each row set new.j:=1;
+--error 1054
+create trigger trg before update on t1 for each row set @a:=old.j;
+
+
+#
+# Let us test various trigger creation errors
+# Also quickly test table namespace (bug#5892/6182)
+#
+--error 1146
+create trigger trg before insert on t2 for each row set @a:=1;
+
+create trigger trg before insert on t1 for each row set @a:=1;
+--error 1359
+create trigger trg after insert on t1 for each row set @a:=1;
+--error 1359
+create trigger trg2 before insert on t1 for each row set @a:=1;
+--error 1359
+create trigger trg before insert on t3 for each row set @a:=1;
+create trigger trg2 before insert on t3 for each row set @a:=1;
+drop trigger trg2;
+drop trigger trg;
+
+--error 1360
+drop trigger trg;
+
+create view v1 as select * from t1;
+--error 1347
+create trigger trg before insert on v1 for each row set @a:=1;
+drop view v1;
+
+drop table t1;
+drop table t3;
+
+create temporary table t1 (i int);
+--error 1361
+create trigger trg before insert on t1 for each row set @a:=1;
+drop table t1;
+
+
+
+#
+# Tests for various trigger-related bugs
+#
+
+# Test for bug #5887 "Triggers with string literals cause errors".
+# New .FRM parser was not handling escaped strings properly.
+create table t1 (x1col char);
+create trigger tx1 before insert on t1 for each row set new.x1col = 'x';
+insert into t1 values ('y');
+drop trigger tx1;
+drop table t1;
+
+#
+# Test for bug #5890 "Triggers fail for DELETE without WHERE".
+# If we are going to delete all rows in table but DELETE triggers exist
+# we should perform row-by-row deletion instead of using optimized
+# delete_all_rows() method.
+#
+create table t1 (i int) engine=myisam;
+insert into t1 values (1), (2);
+create trigger trg1 before delete on t1 for each row set @del_before:= @del_before + old.i;
+create trigger trg2 after delete on t1 for each row set @del_after:= @del_after + old.i;
+set @del_before:=0, @del_after:= 0;
+delete from t1;
+select @del_before, @del_after;
+drop trigger trg1;
+drop trigger trg2;
+drop table t1;
+
+# Test for bug #5859 "DROP TABLE does not drop triggers". Trigger should not
+# magically reappear when we recreate dropped table.
+create table t1 (a int);
+create trigger trg1 before insert on t1 for each row set new.a= 10;
+drop table t1;
+create table t1 (a int);
+insert into t1 values ();
+select * from t1;
+drop table t1;
+
+# Test for bug #6559 "DROP DATABASE forgets to drop triggers".
+create database mysqltest;
+use mysqltest;
+create table t1 (i int);
+create trigger trg1 before insert on t1 for each row set @a:= 1;
+# This should succeed
+drop database mysqltest;
+use test;
+
+# Test for bug #8791
+# "Triggers: Allowed to create triggers on a subject table in a different DB".
+create database mysqltest;
+create table mysqltest.t1 (i int);
+--error ER_TRG_IN_WRONG_SCHEMA
+create trigger trg1 before insert on mysqltest.t1 for each row set @a:= 1;
+use mysqltest;
+--error ER_TRG_IN_WRONG_SCHEMA
+create trigger test.trg1 before insert on t1 for each row set @a:= 1;
+drop database mysqltest;
+use test;
+
+
+# Test for bug #5860 "Multi-table UPDATE does not activate update triggers"
+# We will also test how delete triggers wor for multi-table DELETE.
+create table t1 (i int, j int default 10, k int not null, key (k));
+create table t2 (i int);
+insert into t1 (i, k) values (1, 1);
+insert into t2 values (1);
+create trigger trg1 before update on t1 for each row set @a:= @a + new.j - old.j;
+create trigger trg2 after update on t1 for each row set @b:= "Fired";
+set @a:= 0, @b:= "";
+# Check that trigger works in case of update on the fly
+update t1, t2 set j = j + 10 where t1.i = t2.i;
+select @a, @b;
+insert into t1 values (2, 13, 2);
+insert into t2 values (2);
+set @a:= 0, @b:= "";
+# And now let us check that triggers work in case of multi-update which
+# is done through temporary tables...
+update t1, t2 set j = j + 15 where t1.i = t2.i and t1.k >= 2;
+select @a, @b;
+# Let us test delete triggers for multi-delete now.
+# We create triggers for both tables because we want test how they
+# work in both on-the-fly and via-temp-tables cases.
+create trigger trg3 before delete on t1 for each row set @c:= @c + old.j;
+create trigger trg4 before delete on t2 for each row set @d:= @d + old.i;
+create trigger trg5 after delete on t1 for each row set @e:= "After delete t1 fired";
+create trigger trg6 after delete on t2 for each row set @f:= "After delete t2 fired";
+set @c:= 0, @d:= 0, @e:= "", @f:= "";
+delete t1, t2 from t1, t2 where t1.i = t2.i;
+select @c, @d, @e, @f;
+# This also will drop triggers
+drop table t1, t2;
+
+# Test for bug #6812 "Triggers are not activated for INSERT ... SELECT".
+# (We also check the fact that trigger modifies some field does not affect
+# value of next record inserted).
+delimiter |;
+create table t1 (i int, j int default 10)|
+create table t2 (i int)|
+insert into t2 values (1), (2)|
+create trigger trg1 before insert on t1 for each row
+begin
+ if new.i = 1 then
+ set new.j := 1;
+ end if;
+end|
+create trigger trg2 after insert on t1 for each row set @a:= 1|
+set @a:= 0|
+insert into t1 (i) select * from t2|
+select * from t1|
+select @a|
+# This also will drop triggers
+drop table t1, t2|
+delimiter ;|
+
+# Test for bug #8755 "Trigger is not activated by LOAD DATA"
+create table t1 (i int, j int, k int);
+create trigger trg1 before insert on t1 for each row set new.k = new.i;
+create trigger trg2 after insert on t1 for each row set @b:= "Fired";
+set @b:="";
+# Test triggers with file with separators
+load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, i);
+select *, @b from t1;
+set @b:="";
+# Test triggers with fixed size row file
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, j);
+select *, @b from t1;
+# This also will drop triggers
+drop table t1;
+
+# Test for bug #5894 "Triggers with altered tables cause corrupt databases"
+# Also tests basic error handling for various kinds of triggers.
+create table t1 (i int, at int, k int, key(k)) engine=myisam;
+create table t2 (i int);
+insert into t1 values (1, 1, 1);
+# We need at least 3 elements in t2 to test multi-update properly
+insert into t2 values (1), (2), (3);
+# Create and then break "after" triggers
+create trigger ai after insert on t1 for each row set @a:= new.at;
+create trigger au after update on t1 for each row set @a:= new.at;
+create trigger ad after delete on t1 for each row set @a:= old.at;
+alter table t1 drop column at;
+# We still should be able select data from tables.
+select * from t1;
+# The following statements changing t1 should fail, but still cause
+# their main effect. This is because operation on the table row is
+# executed before "after" trigger and its effect cannot be rolled back
+# when whole statement fails, because t1 is MyISAM table.
+--error 1054
+insert into t1 values (2, 1);
+select * from t1;
+--error 1054
+update t1 set k = 2 where i = 2;
+select * from t1;
+--error 1054
+delete from t1 where i = 2;
+select * from t1;
+# Should fail and insert only 1 row
+--error 1054
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, k);
+select * from t1;
+--error 1054
+insert into t1 select 3, 3;
+select * from t1;
+# Multi-update working on the fly, again it will update only
+# one row even if more matches
+--error 1054
+update t1, t2 set k = k + 10 where t1.i = t2.i;
+select * from t1;
+# The same for multi-update via temp table
+--error 1054
+update t1, t2 set k = k + 10 where t1.i = t2.i and k < 3;
+select * from t1;
+# Multi-delete on the fly
+--error 1054
+delete t1, t2 from t1 straight_join t2 where t1.i = t2.i;
+select * from t1;
+# And via temporary storage
+--error 1054
+delete t2, t1 from t2 straight_join t1 where t1.i = t2.i;
+select * from t1;
+# Prepare table for testing of REPLACE and INSERT ... ON DUPLICATE KEY UPDATE
+alter table t1 add primary key (i);
+--error 1054
+insert into t1 values (3, 4) on duplicate key update k= k + 10;
+select * from t1;
+--error 1054
+replace into t1 values (3, 3);
+select * from t1;
+# Change table in such way that REPLACE will delete row
+alter table t1 add ts timestamp default now();
+--error 1054
+replace into t1 (i, k) values (3, 13);
+select * from t1;
+# Also drops all triggers
+drop table t1, t2;
+
+create table t1 (i int, bt int, k int, key(k)) engine=myisam;
+create table t2 (i int);
+insert into t1 values (1, 1, 1), (2, 2, 2);
+insert into t2 values (1), (2), (3);
+# Create and then break "before" triggers
+create trigger bi before insert on t1 for each row set @a:= new.bt;
+create trigger bu before update on t1 for each row set @a:= new.bt;
+create trigger bd before delete on t1 for each row set @a:= old.bt;
+alter table t1 drop column bt;
+# The following statements changing t1 should fail and should not
+# cause any effect on table, since "before" trigger is executed
+# before operation on the table row.
+--error 1054
+insert into t1 values (3, 3);
+select * from t1;
+--error 1054
+update t1 set i = 2;
+select * from t1;
+--error 1054
+delete from t1;
+select * from t1;
+--error 1054
+load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, k);
+select * from t1;
+--error 1054
+insert into t1 select 3, 3;
+select * from t1;
+# Both types of multi-update (on the fly and via temp table)
+--error 1054
+update t1, t2 set k = k + 10 where t1.i = t2.i;
+select * from t1;
+--error 1054
+update t1, t2 set k = k + 10 where t1.i = t2.i and k < 2;
+select * from t1;
+# Both types of multi-delete
+--error 1054
+delete t1, t2 from t1 straight_join t2 where t1.i = t2.i;
+select * from t1;
+--error 1054
+delete t2, t1 from t2 straight_join t1 where t1.i = t2.i;
+select * from t1;
+# Let us test REPLACE/INSERT ... ON DUPLICATE KEY UPDATE.
+# To test properly code-paths different from those that are used
+# in ordinary INSERT we need to drop "before insert" trigger.
+alter table t1 add primary key (i);
+drop trigger bi;
+--error 1054
+insert into t1 values (2, 4) on duplicate key update k= k + 10;
+select * from t1;
+--error 1054
+replace into t1 values (2, 4);
+select * from t1;
+# Change table in such way that REPLACE will delete row
+alter table t1 add ts timestamp default now();
+--error 1054
+replace into t1 (i, k) values (2, 11);
+select * from t1;
+# Also drops all triggers
+drop table t1, t2;
+
+# Test for bug #5893 "Triggers with dropped functions cause crashes"
+# Appropriate error should be reported instead of crash.
+# Also test for bug #11889 "Server crashes when dropping trigger
+# using stored routine".
+--disable_warnings
+drop function if exists bug5893;
+--enable_warnings
+create table t1 (col1 int, col2 int);
+insert into t1 values (1, 2);
+create function bug5893 () returns int return 5;
+create trigger t1_bu before update on t1 for each row set new.col1= bug5893();
+drop function bug5893;
+--error 1305
+update t1 set col2 = 4;
+# This should not crash server too.
+drop trigger t1_bu;
+drop table t1;
+
+#
+# storing and restoring parsing modes for triggers (BUG#5891)
+#
+set sql_mode='ansi';
+create table t1 ("t1 column" int);
+create trigger t1_bi before insert on t1 for each row set new."t1 column" = 5;
+set sql_mode="";
+insert into t1 values (0);
+# create trigger with different sql_mode
+create trigger t1_af after insert on t1 for each row set @a=10;
+insert into t1 values (0);
+select * from t1;
+select @a;
+--replace_column 6 #
+show triggers;
+drop table t1;
+# check that rigger preserve sql_mode during execution
+set sql_mode="traditional";
+create table t1 (a date);
+-- error 1292
+insert into t1 values ('2004-01-00');
+set sql_mode="";
+create trigger t1_bi before insert on t1 for each row set new.a = '2004-01-00';
+set sql_mode="traditional";
+insert into t1 values ('2004-01-01');
+select * from t1;
+set sql_mode=default;
+show create table t1;
+--replace_column 6 #
+show triggers;
+drop table t1;
+
+# Test for bug #12280 "Triggers: crash if flush tables"
+# FLUSH TABLES and FLUSH PRIVILEGES should be disallowed inside
+# of functions and triggers.
+create table t1 (id int);
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+create trigger t1_ai after insert on t1 for each row flush tables;
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+create trigger t1_ai after insert on t1 for each row flush privileges;
+create procedure p1() flush tables;
+create trigger t1_ai after insert on t1 for each row call p1();
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+insert into t1 values (0);
+drop procedure p1;
+create procedure p1() flush privileges;
+--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
+insert into t1 values (0);
+drop procedure p1;
+drop table t1;
+
+# Test for bug #11973 "SELECT .. INTO var_name; in trigger cause
+# crash on update"
+
+create table t1 (id int, data int, username varchar(16));
+insert into t1 (id, data) values (1, 0);
+delimiter |;
+create trigger t1_whoupdated before update on t1 for each row
+begin
+ declare user varchar(32);
+ declare i int;
+ select user() into user;
+ set NEW.username = user;
+ select count(*) from ((select 1) union (select 2)) as d1 into i;
+end|
+delimiter ;|
+update t1 set data = 1;
+
+connection addconroot1;
+update t1 set data = 2;
+
+connection default;
+drop table t1;
+
+#
+# #11587 Trigger causes lost connection error
+#
+
+create table t1 (c1 int, c2 datetime);
+delimiter |;
+--error ER_SP_NO_RETSET
+create trigger tr1 before insert on t1 for each row
+begin
+ set new.c2= '2004-04-01';
+ select 'hello';
+end|
+delimiter ;|
+
+insert into t1 (c1) values (1),(2),(3);
+select * from t1;
+
+--disable_warnings
+drop procedure if exists bug11587;
+--enable_warnings
+
+delimiter |;
+create procedure bug11587(x char(16))
+begin
+ select "hello";
+ select "hello again";
+end|
+
+create trigger tr1 before insert on t1 for each row
+begin
+ call bug11587();
+ set new.c2= '2004-04-02';
+end|
+delimiter ;|
+
+--error ER_SP_NO_RETSET
+insert into t1 (c1) values (4),(5),(6);
+select * from t1;
+
+drop procedure bug11587;
+drop table t1;
+
+# Test for bug #11896 "Partial locking in case of recursive trigger
+# definitions". Recursion in triggers should not be allowed.
+# We also should not allow to change tables which are used in
+# statements invoking this trigger.
+create table t1 (f1 integer);
+create table t2 (f2 integer);
+create trigger t1_ai after insert on t1
+ for each row insert into t2 values (new.f1+1);
+create trigger t2_ai after insert on t2
+ for each row insert into t1 values (new.f2+1);
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+insert into t1 values (1);
+select * from t1;
+select * from t2;
+drop trigger t1_ai;
+drop trigger t2_ai;
+create trigger t1_bu before update on t1
+ for each row insert into t1 values (2);
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+update t1 set f1= 10;
+select * from t1;
+drop trigger t1_bu;
+create trigger t1_bu before update on t1
+ for each row delete from t1 where f1=new.f1;
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+update t1 set f1= 10;
+select * from t1;
+drop trigger t1_bu;
+# This should work tough
+create trigger t1_bi before insert on t1
+ for each row set new.f1=(select sum(f1) from t1);
+insert into t1 values (3);
+select * from t1;
+drop trigger t1_bi;
+drop tables t1, t2;
+
+# Tests for bug #12704 "Server crashes during trigger execution".
+# If we run DML statements and CREATE TRIGGER statements concurrently
+# it may happen that trigger will be created while DML statement is
+# waiting for table lock. In this case we have to reopen tables and
+# recalculate prelocking set.
+# Unfortunately these tests rely on the order in which tables are locked
+# by statement so they are non determenistic and are disabled.
+--disable_parsing
+create table t1 (id int);
+create table t2 (id int);
+create table t3 (id int);
+create function f1() returns int return (select max(id)+2 from t2);
+create view v1 as select f1() as f;
+
+# Let us check that we notice trigger at all
+connection addconroot1;
+lock tables t2 write;
+connection default;
+send insert into t1 values ((select max(id) from t2)), (2);
+--sleep 1
+connection addconroot2;
+create trigger t1_trg before insert on t1 for each row set NEW.id:= 1;
+connection addconroot1;
+unlock tables;
+connection default;
+reap;
+select * from t1;
+
+# Check that we properly calculate new prelocking set
+insert into t2 values (3);
+connection addconroot1;
+lock tables t2 write;
+connection default;
+send insert into t1 values ((select max(id) from t2)), (4);
+--sleep 1
+connection addconroot2;
+drop trigger t1_trg;
+create trigger t1_trg before insert on t1 for each row
+ insert into t3 values (new.id);
+connection addconroot1;
+unlock tables;
+connection default;
+reap;
+select * from t1;
+select * from t3;
+
+# We should be able to do this even if fancy views are involved
+connection addconroot1;
+lock tables t2 write;
+connection default;
+send insert into t1 values ((select max(f) from v1)), (6);
+--sleep 1
+connection addconroot2;
+drop trigger t1_trg;
+create trigger t1_trg before insert on t1 for each row
+ insert into t3 values (new.id + 100);
+connection addconroot1;
+unlock tables;
+connection default;
+reap;
+select * from t1;
+select * from t3;
+
+# This also should work for multi-update
+# Let us drop trigger to demonstrate that prelocking set is really
+# rebuilt
+drop trigger t1_trg;
+connection addconroot1;
+lock tables t2 write;
+connection default;
+send update t1, t2 set t1.id=10 where t1.id=t2.id;
+--sleep 1
+connection addconroot2;
+create trigger t1_trg before update on t1 for each row
+ insert into t3 values (new.id);
+connection addconroot1;
+unlock tables;
+connection default;
+reap;
+select * from t1;
+select * from t3;
+
+# And even for multi-update converted from ordinary update thanks to view
+drop view v1;
+drop trigger t1_trg;
+create view v1 as select t1.id as id1 from t1, t2 where t1.id= t2.id;
+insert into t2 values (10);
+connection addconroot1;
+lock tables t2 write;
+connection default;
+send update v1 set id1= 11;
+--sleep 1
+connection addconroot2;
+create trigger t1_trg before update on t1 for each row
+ insert into t3 values (new.id + 100);
+connection addconroot1;
+unlock tables;
+connection default;
+reap;
+select * from t1;
+select * from t3;
+
+drop function f1;
+drop view v1;
+drop table t1, t2, t3;
+--enable_parsing
diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test
new file mode 100644
index 00000000000..6906cfc2808
--- /dev/null
+++ b/mysql-test/t/type_bit.test
@@ -0,0 +1,226 @@
+#
+# testing of the BIT column type
+#
+
+select 0 + b'1';
+select 0 + b'0';
+select 0 + b'000001';
+select 0 + b'000011';
+select 0 + b'000101';
+select 0 + b'000000';
+select 0 + b'10000000';
+select 0 + b'11111111';
+select 0 + b'10000001';
+select 0 + b'1000000000000000';
+select 0 + b'1111111111111111';
+select 0 + b'1000000000000001';
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+--error 1439
+create table t1 (a bit(65));
+
+create table t1 (a bit(0));
+show create table t1;
+drop table t1;
+
+create table t1 (a bit(64));
+insert into t1 values
+(b'1111111111111111111111111111111111111111111111111111111111111111'),
+(b'1000000000000000000000000000000000000000000000000000000000000000'),
+(b'0000000000000000000000000000000000000000000000000000000000000001'),
+(b'1010101010101010101010101010101010101010101010101010101010101010'),
+(b'0101010101010101010101010101010101010101010101010101010101010101');
+select hex(a) from t1;
+drop table t1;
+
+create table t1 (a bit);
+insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001');
+select hex(a) from t1;
+--error 1062
+alter table t1 add unique (a);
+drop table t1;
+
+create table t1 (a bit(2));
+insert into t1 values (b'00'), (b'01'), (b'10'), (b'100');
+select a+0 from t1;
+alter table t1 add key (a);
+explain select a+0 from t1;
+select a+0 from t1;
+drop table t1;
+
+create table t1 (a bit(7), b bit(9), key(a, b));
+insert into t1 values
+(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177),
+(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380),
+(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36),
+(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499),
+(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403),
+(44, 307), (68, 454), (57, 135);
+explain select a+0 from t1;
+select a+0 from t1;
+explain select b+0 from t1;
+select b+0 from t1;
+explain select a+0, b+0 from t1;
+select a+0, b+0 from t1;
+explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+set @@max_length_for_sort_data=0;
+select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+select hex(min(a)) from t1;
+select hex(min(b)) from t1;
+select hex(min(a)), hex(max(a)), hex(min(b)), hex(max(b)) from t1;
+drop table t1;
+
+create table t1 (a int not null, b bit, c bit(9), key(a, b, c));
+insert into t1 values
+(4, NULL, 1), (4, 0, 3), (2, 1, 4), (1, 1, 100), (4, 0, 23), (4, 0, 54),
+(56, 0, 22), (4, 1, 100), (23, 0, 1), (4, 0, 34);
+select a+0, b+0, c+0 from t1;
+select hex(min(b)) from t1 where a = 4;
+select hex(min(c)) from t1 where a = 4 and b = 0;
+select hex(max(b)) from t1;
+select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2;
+select a+0, b+0, c+0 from t1 where a = 4 and b = 1;
+select a+0, b+0, c+0 from t1 where a = 4 and b = 1 and c=100;
+select a+0, b+0, c+0 from t1 order by b desc;
+select a+0, b+0, c+0 from t1 order by c;
+drop table t1;
+
+create table t1(a bit(2), b bit(2));
+insert into t1 (a) values (0x01), (0x03), (0x02);
+update t1 set b= concat(a);
+select a+0, b+0 from t1;
+drop table t1;
+
+# Some magic numbers
+
+create table t1 (a bit(7), key(a));
+insert into t1 values (44), (57);
+select a+0 from t1;
+drop table t1;
+
+#
+# Test conversion to and from strings
+#
+create table t1 (a bit(3), b bit(12));
+insert into t1 values (7,(1<<12)-2), (0x01,0x01ff);
+select hex(a),hex(b) from t1;
+select hex(concat(a)),hex(concat(b)) from t1;
+drop table t1;
+
+#
+# Bug #9571: problem with primary key creation
+#
+
+create table t1(a int, b bit not null);
+alter table t1 add primary key (a);
+drop table t1;
+
+#
+# myisam <-> heap
+#
+
+create table t1 (a bit(19), b bit(5));
+insert into t1 values (1000, 10), (3, 8), (200, 6), (2303, 2), (12345, 4), (1, 0);
+select a+0, b+0 from t1;
+alter table t1 engine=heap;
+select a+0, b+0 from t1;
+alter table t1 add key(a, b);
+select a+0, b+0 from t1;
+alter table t1 engine=myisam;
+select a+0, b+0 from t1;
+create table t2 engine=heap select * from t1;
+select a+0, b+0 from t2;
+drop table t1;
+create table t1 select * from t2;
+select a+0, b+0 from t1;
+drop table t1, t2;
+
+#
+# Bug #10179: problem with NULLs and default values
+#
+
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+ g bit(1) NOT NULL default 1, h char(1) default 'a');
+insert into t1 set a=1;
+select hex(g), h from t1;
+drop table t1;
+
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+ g bit(1) NOT NULL default 1);
+insert into t1 set a=1;
+select hex(g) from t1;
+drop table t1;
+
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+ h char(1) default 'a') engine=myisam;
+insert into t1 set a=1;
+select h from t1;
+drop table t1;
+
+#
+# Bug #10539
+#
+
+create table t1 (a bit(8)) engine=heap;
+insert into t1 values ('1111100000');
+select a+0 from t1;
+drop table t1;
+
+#
+# Bug #11091: union
+#
+
+create table t1 (a bit(7));
+insert into t1 values (120), (0), (111);
+select a+0 from t1 union select a+0 from t1;
+select a+0 from t1 union select NULL;
+select NULL union select a+0 from t1;
+create table t2 select a from t1 union select a from t1;
+select a+0 from t2;
+show create table t2;
+drop table t1, t2;
+
+#
+# Bug #11572: view
+#
+
+create table t1 (id1 int(11), b1 bit(1));
+create table t2 (id2 int(11), b2 bit(1));
+insert into t1 values (1, 1), (2, 0), (3, 1);
+insert into t2 values (2, 1), (3, 0), (4, 0);
+create algorithm=undefined view v1 as
+ select b1+0, b2+0 from t1, t2 where id1 = id2 and b1 = 0
+ union
+ select b1+0, b2+0 from t1, t2 where id1 = id2 and b2 = 1;
+select * from v1;
+drop table t1, t2;
+drop view v1;
+
+#
+# Bug #10617: bulk-insert
+#
+
+create table t1(a bit(4));
+insert into t1(a) values (1), (2), (5), (4), (3);
+insert into t1 select * from t1;
+select a+0 from t1;
+drop table t1;
+
+#
+# join
+#
+
+create table t1 (a1 int(11), b1 bit(2));
+create table t2 (a2 int(11), b2 bit(2));
+insert into t1 values (1, 1), (2, 0), (3, 1), (4, 2);
+insert into t2 values (2, 1), (3, 0), (4, 1), (5, 2);
+select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2;
+select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2 order by a1;
+select a1, a2, b1+0, b2+0 from t1 join t2 on b1 = b2;
+select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1;
diff --git a/mysql-test/t/type_bit_innodb.test b/mysql-test/t/type_bit_innodb.test
new file mode 100644
index 00000000000..ec433f40a88
--- /dev/null
+++ b/mysql-test/t/type_bit_innodb.test
@@ -0,0 +1,135 @@
+--source include/have_innodb.inc
+#
+# testing of the BIT column type
+#
+
+select 0 + b'1';
+select 0 + b'0';
+select 0 + b'000001';
+select 0 + b'000011';
+select 0 + b'000101';
+select 0 + b'000000';
+select 0 + b'10000000';
+select 0 + b'11111111';
+select 0 + b'10000001';
+select 0 + b'1000000000000000';
+select 0 + b'1111111111111111';
+select 0 + b'1000000000000001';
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+--error 1439
+create table t1 (a bit(65)) engine=innodb;
+
+create table t1 (a bit(0)) engine=innodb;
+show create table t1;
+drop table t1;
+
+create table t1 (a bit(64)) engine=innodb;
+insert into t1 values
+(b'1111111111111111111111111111111111111111111111111111111111111111'),
+(b'1000000000000000000000000000000000000000000000000000000000000000'),
+(b'0000000000000000000000000000000000000000000000000000000000000001'),
+(b'1010101010101010101010101010101010101010101010101010101010101010'),
+(b'0101010101010101010101010101010101010101010101010101010101010101');
+select hex(a) from t1;
+drop table t1;
+
+create table t1 (a bit) engine=innodb;
+insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001');
+select hex(a) from t1;
+--error 1062
+alter table t1 add unique (a);
+drop table t1;
+
+create table t1 (a bit(2)) engine=innodb;
+insert into t1 values (b'00'), (b'01'), (b'10'), (b'100');
+select a+0 from t1;
+alter table t1 add key (a);
+explain select a+0 from t1;
+select a+0 from t1;
+drop table t1;
+
+create table t1 (a bit(7), b bit(9), key(a, b)) engine=innodb;
+insert into t1 values
+(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177),
+(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380),
+(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36),
+(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499),
+(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403),
+(44, 307), (68, 454), (57, 135);
+explain select a+0 from t1;
+select a+0 from t1;
+explain select b+0 from t1;
+select b+0 from t1;
+explain select a+0, b+0 from t1;
+select a+0, b+0 from t1;
+explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+set @@max_length_for_sort_data=0;
+select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
+select hex(min(a)) from t1;
+select hex(min(b)) from t1;
+select hex(min(a)), hex(max(a)), hex(min(b)), hex(max(b)) from t1;
+drop table t1;
+
+create table t1 (a int not null, b bit, c bit(9), key(a, b, c)) engine=innodb;
+insert into t1 values
+(4, NULL, 1), (4, 0, 3), (2, 1, 4), (1, 1, 100), (4, 0, 23), (4, 0, 54),
+(56, 0, 22), (4, 1, 100), (23, 0, 1), (4, 0, 34);
+select a+0, b+0, c+0 from t1;
+select hex(min(b)) from t1 where a = 4;
+select hex(min(c)) from t1 where a = 4 and b = 0;
+select hex(max(b)) from t1;
+select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2;
+select a+0, b+0, c+0 from t1 where a = 4 and b = 1;
+select a+0, b+0, c+0 from t1 where a = 4 and b = 1 and c=100;
+select a+0, b+0, c+0 from t1 order by b desc;
+select a+0, b+0, c+0 from t1 order by c;
+drop table t1;
+
+create table t1(a bit(2), b bit(2)) engine=innodb;
+insert into t1 (a) values (0x01), (0x03), (0x02);
+update t1 set b= concat(a);
+select a+0, b+0 from t1;
+drop table t1;
+
+# Some magic numbers
+
+create table t1 (a bit(7), key(a)) engine=innodb;
+insert into t1 values (44), (57);
+select a+0 from t1;
+drop table t1;
+
+#
+# Test conversion to and from strings
+#
+create table t1 (a bit(3), b bit(12)) engine=innodb;
+insert into t1 values (7,(1<<12)-2), (0x01,0x01ff);
+select hex(a),hex(b) from t1;
+select hex(concat(a)),hex(concat(b)) from t1;
+drop table t1;
+
+#
+# Bug #9571: problem with primary key creation
+#
+
+create table t1(a int, b bit not null) engine=innodb;
+alter table t1 add primary key (a);
+drop table t1;
+
+#
+# altering tables
+#
+
+create table t1 (a bit, b bit(10)) engine=innodb;
+show create table t1;
+alter table t1 engine=heap;
+show create table t1;
+alter table t1 engine=innodb;
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test
index 2ac55da7442..1ec5c600296 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -17,13 +17,13 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7;
CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000));
show columns from t1;
# PS doesn't give errors on prepare yet
---disable_ps_protocol
-CREATE TABLE t2 (a char(257), b varbinary(70000), c varchar(70000000));
---enable_ps_protocol
+CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
+CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
show columns from t2;
create table t3 (a long, b long byte);
show create TABLE t3;
-drop table t1,t2,t3
+show create TABLE t4;
+drop table t1,t2,t3,t4;
#
# Check errors with blob
@@ -31,6 +31,10 @@ drop table t1,t2,t3
--error 1074
CREATE TABLE t1 (a char(257) default "hello");
+--error 1074
+CREATE TABLE t2 (a char(256));
+--error 1074
+CREATE TABLE t1 (a varchar(70000) default "hello");
--error 1101
CREATE TABLE t2 (a blob default "hello");
@@ -300,7 +304,7 @@ drop table t1;
# Bug when blob is updated
#
-create table t1 (id integer auto_increment unique,imagem LONGBLOB not null);
+create table t1 (id integer auto_increment unique,imagem LONGBLOB not null default '');
insert into t1 (id) values (1);
# We have to clean up the path in the results for safe comparison
--replace_result $MYSQL_TEST_DIR ../..
@@ -326,10 +330,16 @@ drop table t1;
#
# Test blob's with end space (Bug #1651)
+# This is a bit changed since we now have true varchar
#
create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20)));
+--error 1062
insert into t1 (txt) values ('Chevy'), ('Chevy ');
+--error 1062
+insert into t1 (txt) values ('Chevy'), ('CHEVY');
+alter table t1 drop index txt_index, add index txt_index (txt(20));
+insert into t1 (txt) values ('Chevy ');
select * from t1 where txt='Chevy';
select * from t1 where txt='Chevy ';
select * from t1 where txt='Chevy ' or txt='Chevy';
@@ -350,7 +360,7 @@ select * from t1 where txt > 'Chevy';
select * from t1 where txt >= 'Chevy';
drop table t1;
-create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20)));
+create table t1 (id integer primary key auto_increment, txt text, index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL;
explain select * from t1 where txt='Chevy' or txt is NULL;
@@ -385,3 +395,12 @@ select max(i) from t1 where c = '';
drop table t1;
# End of 4.1 tests
+
+#
+# Bug#11657: Creation of secondary index fails
+#
+create table t1 (a int, b int, c tinyblob, d int, e int);
+alter table t1 add primary key (a,b,c(255),d);
+alter table t1 add key (a,b,d,e);
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index a6fd99e8c9a..44032fde46f 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -1,7 +1,7 @@
# bug in decimal() with negative numbers by kaido@tradenet.ee
--disable_warnings
-DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t1, t2;
--enable_warnings
SET SQL_WARNINGS=1;
@@ -165,6 +165,8 @@ 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");
insert into t1 values ("1e+1000"),("1e-1000"),("-1e+1000");
+insert into t1 values ("1e+4294967296"),("1e-4294967296");
+insert into t1 values ("1e+18446744073709551615"),("1e+18446744073709551616"),("1e-9223372036854775807"),("1e-9223372036854775809");
insert into t1 values ("123.4e"),("123.4e+2"),("123.4e-2"),("123e1"),("123e+0");
select * from t1;
drop table t1;
@@ -201,6 +203,7 @@ insert into t1 values (+111111111.11),(111111111.11),(-11111111.11);
insert into t1 values (-111111111.11),(+1111111111.11),(1111111111.11);
insert into t1 values (1e+100),(1e-100),(-1e+100);
insert into t1 values (123.4e0),(123.4e+2),(123.4e-2),(123e1),(123e+0);
+insert into t1 values (MID("987",1,2)),("987 "),("987.6e+2 ");
select * from t1;
drop table t1;
@@ -244,9 +247,8 @@ 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));
+--error 1427
CREATE TABLE t1 (a_dec DECIMAL(0,11));
-SHOW CREATE TABLE t1;
-DROP TABLE t1;
#
# Zero prepend overflow bug
@@ -267,3 +269,100 @@ select * from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Test for BUG#8397: decimal type in subselects (Item_cache_decimal)
+#
+CREATE TABLE t1
+(EMPNUM CHAR(3) NOT NULL,
+HOURS DECIMAL(5));
+CREATE TABLE t2
+(EMPNUM CHAR(3) NOT NULL,
+HOURS BIGINT);
+
+INSERT INTO t1 VALUES ('E1',40);
+INSERT INTO t1 VALUES ('E8',NULL);
+INSERT INTO t2 VALUES ('E1',40);
+
+SELECT EMPNUM FROM t1 WHERE HOURS IN (SELECT HOURS FROM t2);
+SELECT EMPNUM FROM t1 WHERE HOURS IN (SELECT HOURS FROM t1);
+
+DROP TABLE t1,t2;
+
+#
+# Test limits of decimal
+#
+create table t1 (d decimal(64,0));
+insert into t1 values (1);
+select * from t1;
+drop table t1;
+create table t1 (d decimal(5));
+show create table t1;
+drop table t1;
+create table t1 (d decimal);
+show create table t1;
+drop table t1;
+--error 1426
+create table t1 (d decimal(66,0));
+
+#
+# Test example from manual
+#
+
+CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2));
+INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
+(2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
+(2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
+(4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
+(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
+(6, 0.00, 0.00), (6, -51.40, 0.00);
+
+SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1 GROUP BY i HAVING a <> b;
+SELECT i, ROUND(SUM(d1), 2) AS a, ROUND(SUM(d2), 2) AS b FROM t1 GROUP BY i
+HAVING a <> b;
+drop table t1;
+
+#
+# A test case for Bug#4956 "strange result, insert into longtext, parameter
+# with numeric value": ensure that conversion is done identically no matter
+# where the input data comes from.
+#
+create table t1 (c1 varchar(100), c2 longtext);
+insert into t1 set c1= 'non PS, 1.0 as constant', c2=1.0;
+prepare stmt from "insert into t1 set c1='PS, 1.0 as constant ', c2=1.0";
+execute stmt;
+set @a=1.0;
+insert into t1 set c1='non PS, 1.0 in parameter', c2=@a;
+prepare stmt from "insert into t1 set c1='PS, 1.0 in parameter ', c2=?";
+execute stmt using @a;
+select * from t1;
+deallocate prepare stmt;
+drop table t1;
+
+#
+# A test case for Bug#5673 "Rounding problem in 4.0.21 inserting decimal
+# value into a char field": this is a regression bug in 4.0 tree caused by
+# a fix for some other decimal conversion issue. The patch never was
+# approved to get into 4.0 (maybe because it was considered too intrusive)
+#
+
+create table t1 (
+ strippedproductid char(15) not null default '',
+ zlevelprice decimal(10,2) default null,
+ primary key (strippedproductid)
+);
+
+create table t2 (
+ productid char(15) not null default '',
+ zlevelprice char(21) default null,
+ primary key (productid)
+);
+
+insert into t1 values ('002trans','49.99');
+insert into t1 values ('003trans','39.98');
+insert into t1 values ('004trans','31.18');
+
+insert INTO t2 SELECT * FROM t1;
+
+select * from t2;
+drop table t1, t2;
diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test
index 2d4a90911a1..c0f1854d5b2 100644
--- a/mysql-test/t/type_float.test
+++ b/mysql-test/t/type_float.test
@@ -67,7 +67,7 @@ drop table t1;
# FLOAT/DOUBLE/DECIMAL handling
#
-create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6));
+create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(7,6));
# We mask out Privileges column because it differs for embedded server
--replace_column 8 #
show full columns from t1;
@@ -79,11 +79,8 @@ select a from t1 order by a;
select min(a) from t1;
drop table t1;
+--error 1425
create table t1 (a float(200,100), b double(200,100));
-insert t1 values (1.0, 2.0);
-select * from t1;
-show create table t1;
-drop table t1;
#
# float in a char(1) field
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
new file mode 100644
index 00000000000..3f04aa931d2
--- /dev/null
+++ b/mysql-test/t/type_newdecimal.test
@@ -0,0 +1,1046 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+#
+# constant IN function test
+#
+select 1.1 IN (1.0, 1.2);
+select 1.1 IN (1.0, 1.2, 1.1, 1.4, 0.5);
+select 1.1 IN (1.0, 1.2, NULL, 1.4, 0.5);
+select 0.5 IN (1.0, 1.2, NULL, 1.4, 0.5);
+select 1 IN (1.11, 1.2, 1.1, 1.4, 1, 0.5);
+select 1 IN (1.11, 1.2, 1.1, 1.4, NULL, 0.5);
+
+#
+# case function test
+#
+select case 1.0 when 0.1 then "a" when 1.0 then "b" else "c" END;
+select case 0.1 when 0.1 then "a" when 1.0 then "b" else "c" END;
+select case 1 when 0.1 then "a" when 1.0 then "b" else "c" END;
+select case 1.0 when 0.1 then "a" when 1 then "b" else "c" END;
+select case 1.001 when 0.1 then "a" when 1 then "b" else "c" END;
+
+#
+# non constant IN test
+#
+create table t1 (a decimal(6,3));
+insert into t1 values (1.0), (NULL), (0.1);
+select * from t1;
+select 0.1 in (1.0, 1.2, 1.1, a, 1.4, 0.5) from t1;
+drop table t1;
+
+#
+# if function test
+#
+create table t1 select if(1, 1.1, 1.2), if(0, 1.1, 1.2), if(0.1, 1.1, 1.2), if(0, 1, 1.1), if(0, NULL, 1.2), if(1, 0.22e1, 1.1), if(1E0, 1.1, 1.2);
+select * from t1;
+show create table t1;
+drop table t1;
+
+#
+# NULLIF
+#
+create table t1 select nullif(1.1, 1.1), nullif(1.1, 1.2), nullif(1.1, 0.11e1), nullif(1.0, 1), nullif(1, 1.0), nullif(1, 1.1);
+select * from t1;
+show create table t1;
+drop table t1;
+
+#
+# saving in decimal field with overflow
+#
+
+create table t1 (a decimal(4,2));
+insert into t1 value (10000), (1.1e10), ("11111"), (100000.1);
+insert into t1 value (-10000), (-1.1e10), ("-11111"), (-100000.1);
+select a from t1;
+drop table t1;
+create table t1 (a decimal(4,2) unsigned);
+insert into t1 value (10000), (1.1e10), ("11111"), (100000.1);
+insert into t1 value (-10000), (-1.1e10), ("-11111"), (-100000.1);
+select a from t1;
+drop table t1;
+
+
+#
+# saving in field with overflow from decimal
+#
+create table t1 (a bigint);
+insert into t1 values (18446744073709551615.0);
+insert into t1 values (9223372036854775808.0);
+insert into t1 values (-18446744073709551615.0);
+select * from t1;
+drop table t1;
+create table t1 (a bigint unsigned);
+insert into t1 values (18446744073709551615.0);
+insert into t1 values (9223372036854775808.0);
+insert into t1 values (9999999999999999999999999.000);
+insert into t1 values (-1.0);
+select * from t1;
+drop table t1;
+create table t1 (a tinyint);
+insert into t1 values (18446744073709551615.0);
+insert into t1 values (9223372036854775808.0);
+select * from t1;
+drop table t1;
+
+#
+# test that functions create decimal fields
+#
+create table t1 select round(15.4,-1), truncate(-5678.123451,-3), abs(-1.1), -(-1.1);
+show create table t1;
+drop table t1;
+
+#
+# Trydy's tests
+#
+set session sql_mode='traditional';
+select 1e10/0e0;
+create table wl1612 (col1 int, col2 decimal(38,10), col3 numeric(38,10));
+insert into wl1612 values(1,12345678901234567890.1234567890,12345678901234567890.1234567890);
+select * from wl1612;
+insert into wl1612 values(2,01234567890123456789.0123456789,01234567890123456789.0123456789);
+select * from wl1612 where col1=2;
+insert into wl1612 values(3,1234567890123456789012345678.0123456789,1234567890123456789012345678.0123456789);
+select * from wl1612 where col1=3;
+
+select col1/0 from wl1612;
+select col2/0 from wl1612;
+select col3/0 from wl1612;
+
+insert into wl1612 values(5,5000.0005,5000.0005);
+insert into wl1612 values(6,5000.0005,5000.0005);
+select sum(col2),sum(col3) from wl1612;
+#select avg(col2),avg(col3) from wl1612;
+
+insert into wl1612 values(7,500000.000005,500000.000005);
+insert into wl1612 values(8,500000.000005,500000.000005);
+select sum(col2),sum(col3) from wl1612 where col1>4;
+#select avg(col2),avg(col3) from wl1612 where col1>4;
+
+#insert into wl1612 (col1,col2) values(9,123456789012345678901234567890);
+#insert into wl1612 (col1,col3) values(9,123456789012345678901234567890);
+
+insert into wl1612 (col1, col2) values(9,1.01234567891);
+insert into wl1612 (col1, col2) values(10,1.01234567894);
+insert into wl1612 (col1, col2) values(11,1.01234567895);
+insert into wl1612 (col1, col2) values(12,1.01234567896);
+select col1,col2 from wl1612 where col1>8;
+
+insert into wl1612 (col1, col3) values(13,1.01234567891);
+insert into wl1612 (col1, col3) values(14,1.01234567894);
+insert into wl1612 (col1, col3) values(15,1.01234567895);
+insert into wl1612 (col1, col3) values(16,1.01234567896);
+select col1,col3 from wl1612 where col1>12;
+
+select col1 from wl1612 where col1>4 and col2=1.01234567891;
+#-- should return 0 rows
+#
+select col1 from wl1612 where col1>4 and col2=1.0123456789;
+#-- should return col1 values 9 & 10
+#
+select col1 from wl1612 where col1>4 and col2<>1.0123456789;
+#-- should return col1 values 5,6,7,8,11,12
+#
+select col1 from wl1612 where col1>4 and col2<1.0123456789;
+#-- should return 0 rows
+#
+select col1 from wl1612 where col1>4 and col2<=1.0123456789;
+#-- should return col1 values 9 & 10
+#
+select col1 from wl1612 where col1>4 and col2>1.0123456789;
+#-- should return col1 values 5,6,7,8,11,12
+#
+select col1 from wl1612 where col1>4 and col2>=1.0123456789;
+#-- should return col1 values 5,6,7,8,910,11,12
+#
+#select col1, col2 from wl1612 where col1=11 or col1=12;
+select col1 from wl1612 where col1>4 and col2=1.012345679;
+#-- should return col1 values 11,12
+#
+select col1 from wl1612 where col1>4 and col2<>1.012345679;
+#-- should return col1 values 5,6,7,8,9,10
+#
+select col1 from wl1612 where col1>4 and col3=1.01234567891;
+#-- should return 0 rows
+#
+select col1 from wl1612 where col1>4 and col3=1.0123456789;
+#-- should return col1 values 13,14
+#
+select col1 from wl1612 where col1>4 and col3<>1.0123456789;
+#-- should return col1 values 5,6,7,8,15,16
+#
+select col1 from wl1612 where col1>4 and col3<1.0123456789;
+#-- should return 0 rows
+#
+select col1 from wl1612 where col1>4 and col3<=1.0123456789;
+#-- should return col1 values 13,14
+#
+select col1 from wl1612 where col1>4 and col3>1.0123456789;
+#-- should return col1 values 5,6,7,8,15,16
+#
+select col1 from wl1612 where col1>4 and col3>=1.0123456789;
+#-- should return col1 values 5,6,7,8,13,14,15,16
+#
+select col1 from wl1612 where col1>4 and col3=1.012345679;
+#-- should return col1 values 15,16
+#
+select col1 from wl1612 where col1>4 and col3<>1.012345679;
+#-- should return col1 values 5,6,7,8,13,14
+#
+drop table wl1612;
+#
+select 1/3;
+#
+select 0.8=0.7+0.1;
+#-- should return 1 (true)
+#
+select 0.7+0.1;
+#
+create table wl1612_1 (col1 int);
+insert into wl1612_1 values(10);
+#
+select * from wl1612_1 where 0.8=0.7+0.1;
+#--should return 1 row (col1=10)
+#
+select 0.07+0.07 from wl1612_1;
+#
+select 0.07-0.07 from wl1612_1;
+#
+select 0.07*0.07 from wl1612_1;
+#
+select 0.07/0.07 from wl1612_1;
+#
+drop table wl1612_1;
+#
+create table wl1612_2 (col1 decimal(10,2), col2 numeric(10,2));
+insert into wl1612_2 values(1,1);
+insert into wl1612_2 values(+1,+1);
+insert into wl1612_2 values(+01,+01);
+insert into wl1612_2 values(+001,+001);
+#
+select col1,count(*) from wl1612_2 group by col1;
+#
+select col2,count(*) from wl1612_2 group by col2;
+#
+drop table wl1612_2;
+#
+create table wl1612_3 (col1 decimal(10,2), col2 numeric(10,2));
+insert into wl1612_3 values('1','1');
+insert into wl1612_3 values('+1','+1');
+#
+insert into wl1612_3 values('+01','+01');
+insert into wl1612_3 values('+001','+001');
+#
+select col1,count(*) from wl1612_3 group by col1;
+#
+select col2,count(*) from wl1612_3 group by col2;
+#
+drop table wl1612_3;
+#
+select mod(234,10) ;
+#-- should return 4
+#
+select mod(234.567,10.555);
+#-- should return 2.357
+#
+select mod(-234.567,10.555);
+#-- should return -2.357
+#
+select mod(234.567,-10.555);
+#-- should return 2.357
+#
+select round(15.1);
+#-- should return 15
+#
+select round(15.4);
+#-- should return 15
+#
+select round(15.5);
+#-- should return 16
+#
+select round(15.6);
+#-- should return 16
+#
+select round(15.9);
+#-- should return 16
+#
+select round(-15.1);
+#-- should return -15
+#
+select round(-15.4);
+#-- should return -15
+#
+select round(-15.5);
+#-- should return -16
+#
+select round(-15.6);
+#-- should return -16
+#
+select round(-15.9);
+#-- should return -16
+#
+select round(15.1,1);
+#-- should return 15.1
+#
+select round(15.4,1);
+#-- should return 15.4
+#
+select round(15.5,1);
+#-- should return 15.5
+#
+select round(15.6,1);
+#-- should return 15.6
+#
+select round(15.9,1);
+#-- should return 15.9
+#
+select round(-15.1,1);
+#-- should return -15.1
+#
+select round(-15.4,1);
+#-- should return -15.4
+#
+select round(-15.5,1);
+#-- should return -15.5
+#
+select round(-15.6,1);
+#-- should return -15.6
+#
+select round(-15.9,1);
+#-- should return -15.9
+#
+select round(15.1,0);
+#-- should return 15
+#
+select round(15.4,0);
+#-- should return 15
+#
+select round(15.5,0);
+#-- should return 16
+#
+select round(15.6,0);
+#-- should return 16
+#
+select round(15.9,0);
+#-- should return 16
+#
+select round(-15.1,0);
+#-- should return -15
+#
+select round(-15.4,0);
+#-- should return -15
+#
+select round(-15.5,0);
+#-- should return -16
+#
+select round(-15.6,0);
+#-- should return -16
+#
+select round(-15.9,0);
+#-- should return -16
+#
+select round(15.1,-1);
+#-- should return 20
+#
+select round(15.4,-1);
+#-- should return 20
+#
+select round(15.5,-1);
+#-- should return 20
+#
+select round(15.6,-1);
+#-- should return 20
+#
+select round(15.9,-1);
+#-- should return 20
+#
+select round(-15.1,-1);
+#-- should return -20
+#
+select round(-15.4,-1);
+#-- should return -20
+#
+select round(-15.5,-1);
+#-- should return -20
+#
+select round(-15.6,-1);
+#-- should return -20
+#
+select round(-15.91,-1);
+#-- should return -20
+#
+select truncate(5678.123451,0);
+#-- should return 5678
+#
+select truncate(5678.123451,1);
+#-- should return 5678.1
+#
+select truncate(5678.123451,2);
+#-- should return 5678.12
+#
+select truncate(5678.123451,3);
+#-- should return 5678.123
+#
+select truncate(5678.123451,4);
+#-- should return 5678.1234
+#
+select truncate(5678.123451,5);
+#-- should return 5678.12345
+#
+select truncate(5678.123451,6);
+#-- should return 5678.123451
+#
+select truncate(5678.123451,-1);
+#-- should return 5670
+#
+select truncate(5678.123451,-2);
+#-- should return 5600
+#
+select truncate(5678.123451,-3);
+#-- should return 5000
+#
+select truncate(5678.123451,-4);
+#-- should return 0
+#
+select truncate(-5678.123451,0);
+#-- should return -5678
+#
+select truncate(-5678.123451,1);
+#-- should return -5678.1
+#
+select truncate(-5678.123451,2);
+#-- should return -5678.12
+#
+select truncate(-5678.123451,3);
+#-- should return -5678.123
+#
+select truncate(-5678.123451,4);
+#-- should return -5678.1234
+#
+select truncate(-5678.123451,5);
+#-- should return -5678.12345
+#
+select truncate(-5678.123451,6);
+#-- should return -5678.123451
+#
+select truncate(-5678.123451,-1);
+#-- should return -5670
+#
+select truncate(-5678.123451,-2);
+#-- should return -5600
+#
+select truncate(-5678.123451,-3);
+#-- should return -5000
+#
+select truncate(-5678.123451,-4);
+#-- should return 0
+#
+#drop table if exists wl1612_4;
+create table wl1612_4 (col1 int, col2 decimal(30,25), col3 numeric(30,25));
+#
+insert into wl1612_4 values(1,0.0123456789012345678912345,0.0123456789012345678912345);
+#
+select col2/9999999999 from wl1612_4 where col1=1;
+#
+select col3/9999999999 from wl1612_4 where col1=1;
+#
+select 9999999999/col2 from wl1612_4 where col1=1;
+#
+select 9999999999/col3 from wl1612_4 where col1=1;
+#
+select col2*9999999999 from wl1612_4 where col1=1;
+#
+select col3*9999999999 from wl1612_4 where col1=1;
+#
+insert into wl1612_4 values(2,55555.0123456789012345678912345,55555.0123456789012345678912345);
+#
+select col2/9999999999 from wl1612_4 where col1=2;
+#
+select col3/9999999999 from wl1612_4 where col1=2;
+#
+select 9999999999/col2 from wl1612_4 where col1=2;
+#
+select 9999999999/col3 from wl1612_4 where col1=2;
+#
+select col2*9999999999 from wl1612_4 where col1=2;
+#
+select col3*9999999999 from wl1612_4 where col1=2;
+#
+drop table wl1612_4;
+#
+#
+#
+#
+#-- Additional tests for WL#1612 Precision math
+#
+#-- 1. Comparisons should show that a number is
+#-- exactly equal to its value as displayed.
+#
+set sql_mode='';
+#
+select 23.4 + (-41.7), 23.4 - (41.7) = -18.3;
+#
+select -18.3=-18.3;
+#
+select 18.3=18.3;
+#
+select -18.3=18.3;
+#
+select 0.8 = 0.7 + 0.1;
+#
+#-- 2. Adding (one millionth) one million times should be the same as
+#-- adding 1. So a stored procedure with many iterations will show if
+#-- small errors accumulate.
+#
+#drop procedure p1;
+#
+delimiter //;
+#
+create procedure p1 () begin
+ declare v1, v2, v3, v4 decimal(16,12); declare v5 int;
+ set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0;
+ while v5 < 100000 do
+ set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1;
+ end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;//
+#
+call p1()//
+#-- should return
+# -- v1=1.0000001
+# -- v2=1.999999900000
+# -- v3=1.0000001
+# -- v4=1.999999900000
+#
+delimiter ;//
+#
+drop procedure p1;
+#
+#-- 3. It should be possible to define a column
+#-- with up to 38 digits precision either before
+#-- or after the decimal point. Any number which
+#-- is inserted, if it's within the range, should
+#-- be exactly the same as the number that gets
+#-- selected.
+#
+drop table if exists t1;
+#
+create table t1 (col1 decimal(38));
+#
+insert into t1 values (12345678901234567890123456789012345678);
+#
+select * from t1;
+#-- should return:
+#+----------------------------------------+
+#| col1 |
+#+----------------------------------------+
+#| 12345678901234567890123456789012345678 |
+#+----------------------------------------+
+#
+#drop table t1;
+#
+#create table t1 (col1 decimal(38,38));
+#
+#insert into t1 values (.12345678901234567890123456789012345678);
+#
+#select * from t1;
+#-- should return:
+#+------------------------------------------+
+#| col1 |
+#+------------------------------------------+
+#| 0.12345678901234567890123456789012345678 |
+#+------------------------------------------+
+#
+drop table t1;
+#
+create table t1 (col1 decimal(31,30));
+#
+insert into t1 values (0.00000000001);
+#
+select * from t1;
+#-- should return:
+#+---------------+
+#|col1 |
+#+---------------+
+#| 0.00000000001 |
+#+---------------+
+#
+drop table t1;
+#
+#-- 4. The usual arithmetic operators / * + - should work.
+#
+#select 77777777777777777777777777777777777777 / 7777777777777777777777777777777777777 = 10;
+#-- should return 0 (false).
+#
+select 7777777777777777777777777777777777777 * 10;
+#-- should return 77777777777777777777777777777777777770
+#
+select .7777777777777777777777777777777777777 *
+ 1000000000000000000;
+#-- should return 777777777777777777.7777777777777777777
+#
+select .7777777777777777777777777777777777777 - 0.1;
+#-- should return .6777777777777777777777777777777777777
+#
+select .343434343434343434 + .343434343434343434;
+#-- should return .686868686868686868
+#
+#-- 5. All arithmetic functions mentioned in the
+#MySQL Reference Manual should work.
+#
+select abs(9999999999999999999999);
+#-- should return 9999999999999999999999
+#
+select abs(-9999999999999999999999);
+#-- should return 9999999999999999999999
+#
+select ceiling(999999999999999999);
+select ceiling(99999999999999999999);
+#-- should return 99999999999999999999
+#
+select ceiling(9.9999999999999999999);
+#-- should return 10
+#
+select ceiling(-9.9999999999999999999);
+#-- should return 9
+#
+select floor(999999999999999999);
+select floor(9999999999999999999999);
+#-- should return 9999999999999999999999
+#
+select floor(9.999999999999999999999);
+#-- should return 9
+#
+select floor(-9.999999999999999999999);
+#-- should return -10
+#
+select floor(-999999999999999999999.999);
+select ceiling(999999999999999999999.999);
+#
+#
+select 99999999999999999999999999999999999999 mod 3;
+#-- should return 0
+#
+select round(99999999999999999.999);
+#-- should return 100000000000000000
+#
+select round(-99999999999999999.999);
+#-- should return -100000000000000000
+#
+select round(99999999999999999.999,3);
+#-- should return 100000000000000000.000
+#
+select round(-99999999999999999.999,3);
+#-- should return -100000000000000000.000
+#
+select truncate(99999999999999999999999999999999999999,31);
+#-- should return 99999999999999999999999999999999999999.000
+#
+select truncate(99.999999999999999999999999999999999999,31);
+#-- should return 99.9999999999999999999999999999999
+#
+select truncate(99999999999999999999999999999999999999,-31);
+-- should return 90000000000000000000000000000000
+#
+#-- 6. Set functions (AVG, SUM, COUNT) should work.
+#
+#drop table if exists t1;
+#
+#delimiter //
+#
+#create procedure p1 () begin
+# declare v1 int default 1; declare v2 decimal(0,38) default 0;
+# create table t1 (col1 decimal(0,38));
+# while v1 <= 10000 do
+# insert into t1 values (-v2);
+# set v2 = v2 + 0.00000000000000000000000000000000000001;
+# set v1 = v1 + 1;
+# end while;
+# select avg(col1),sum(col1),count(col1) from t1; end;//
+#
+#call p1()//
+#-- should return
+# -- avg(col1)=0.00000000000000000000000000000000000001 added 10,000 times, then divided by 10,000
+# -- sum(col1)=0.00000000000000000000000000000000000001 added 10,000 times
+#
+# -- count(col1)=10000
+#
+#delimiter ;//
+#
+#drop procedure p1;
+#drop table t1;
+#
+#-- 7. When I say DECIMAL(x) I should be able to store x digits.
+#-- If I can't, there should be an error at CREATE time.
+#
+#drop table if exists t1;
+#
+#create table t1 (col1 decimal(254));
+#-- should return SQLSTATE 22003 numeric value out of range
+#
+#-- 8. When I say DECIMAL(x,y) there should be no silent change of precision or scale.
+#
+#drop table if exists t1;
+#
+#create table t1 (col1 decimal(0,38));
+#
+#show create table t1;
+#-- should return:
+#+-------+--------------------------------+
+#| Table | Create Table |
+#+-------+--------------------------------+
+#| t9 | CREATE TABLE `t1` ( |
+#|`s1` decimal(0,38) default NULL |
+#| ) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+#+-------+--------------------------------+
+#
+#drop table t1;
+#
+#-- 9. From WL#1612 "The future" point 2.:
+#-- The standard requires that we treat numbers like "0.5" as
+#-- DECIMAL or NUMERIC, not as floating-point.
+#
+#drop table if exists t1;
+#
+#
+create table t1 as select 0.5;
+#
+show create table t1;
+#-- should return:
+#+-------+-----------------------------------+
+#| Table | Create Table |
+#+-------+-----------------------------------+
+#| t7 | CREATE TABLE `t1` ( |
+#| `0.5` decimal(3,1) NOT NULL default '0.0' |
+#| ) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+#+-------+-----------------------------------+
+#
+drop table t1;
+#
+#-- 10. From WL#1612, "The future", point 3.: We have to start rounding correctly.
+#
+select round(1.5),round(2.5);
+#-- should return:
+#+------------+------------+
+#| round(1.5) | round(2.5) |
+#+------------+------------+
+#| 2 | 3 |
+#+------------+------------+
+#
+#-- 11. From WL#1612, "The future", point 4.: "select 0.07 * 0.07;" should return 0.0049, not 0.00.
+#-- If operand#1 has scale X and operand#2 has scale Y, then result should have scale (X+Y).
+#
+select 0.07 * 0.07;
+#-- should return 0.0049
+#
+#-- 12. From WL#1612, "The future", point 5.: Division by zero is an error.
+#
+set sql_mode='traditional';
+#
+select 1E-500 = 0;
+#-- should return 1 (true).
+#
+select 1 / 1E-500;
+#
+#-- should return SQLSTATE 22012 division by zero.
+#
+select 1 / 0;
+#-- should return SQLSTATE 22012 division by zero.
+#
+#+-------+
+#| 1 / 0 |
+#+-------+
+#| NULL |
+#+-------+
+#1 row in set, 1 warning (0.00 sec)
+#
+#-- 13. From WL#1612 "The future" point 6.: Overflow is an error.
+#
+#set sql_mode='';
+#
+#select 1E300 * 1E300;
+#-- should return SQLSTATE 22003 numeric value out of range
+#
+#select 18446744073709551615 + 1;
+#-- should return SQLSTATE 22003 numeric value out of range
+#
+#-- 14. From WL#1612 "The future" point 7.:
+#-- If s1 is INTEGER and s2 is DECIMAL, then
+#-- "create table tk7 as select avg(s1),avg(s2) from tk;"
+#-- should not create a table with "double(17,4)" data types.
+#-- The result of AVG must still be exact numeric, with a
+#-- scale the same or greater than the operand's scale.
+#-- The result of SUM must still be exact numeric, with
+#-- a scale the same as the operand's scale.
+#
+#drop table if exists t1;
+#drop table if exists t2;
+#
+#create table t1 (col1 int, col2 decimal(5));
+#
+#create table t2 as select avg(col1),avg(col2) from t1;
+#
+#
+#show create table t2;
+#-- should return:
+#+-------+---------------------------------+
+#| Table | Create Table |
+#+-------+---------------------------------+
+#| t2 | CREATE TABLE `t2` ( |
+#| `avg(col1)` decimal(17,4) default NULL, |
+#| `avg(col2)` decimal(17,5) default NULL |
+#| ) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+#+-------+---------------------------------+
+#
+#drop table t2;
+#drop table t1;
+#
+#-- 15. From WL#1612 "The future" point 8.: Stop storing leading "+" signs and leading "0"s.
+#
+#drop table if exists t1;
+#
+#create table t1 (col1 decimal(5,2),col2 decimal(5) zerofill, col3 decimal(3,1));
+#
+#insert into t1 values (1,1,1);
+#
+#select col1 from t1 union select col2 from t1 union select col3 from t1;
+#
+#drop table t1;
+#
+#-- 16. From WL#1612, The future" point 9.:
+#-- Accept the data type and precision and scale as the user
+#-- asks, or return an error, but don't change to something else.
+#
+#drop table if exists t1;
+#
+#create table t1 (col1 numeric(4,2));
+#
+#show create table t1;
+#
+#drop table t1;
+#
+#-- 17. The scripts in the following bugs should work:
+#
+
+#BUG#559 Maximum precision for DECIMAL column ...
+#BUG#1499 INSERT/UPDATE into decimal field rounding problem
+#BUG#1845 Not correctly recognising value for decimal field
+#BUG#2493 Round function doesn't work correctly
+#BUG#2649 round(0.5) gives 0 (should be 1)
+#BUG#3612 impicite rounding of VARCHARS during aritchmetic operations...
+#BUG#3722 SELECT fails for certain values in Double(255,10) column.
+#BUG#4485 Floating point conversions are inconsistent
+#BUG#4891 MATH
+#BUG#5931 Out-of-range values are accepted
+#BUG#6048 Stored procedure causes operating system reboot
+#BUG#6053 DOUBLE PRECISION literal
+
+-- 18. Tests from 'traditional' mode tests
+#
+set sql_mode='ansi,traditional';
+#
+CREATE TABLE Sow6_2f (col1 NUMERIC(4,2));
+#-- should return OK
+INSERT INTO Sow6_2f VALUES (10.55);
+#-- should return OK
+INSERT INTO Sow6_2f VALUES (10.5555);
+#-- should return OK
+INSERT INTO Sow6_2f VALUES (-10.55);
+#-- should return OK
+INSERT INTO Sow6_2f VALUES (-10.5555);
+#-- should return OK
+INSERT INTO Sow6_2f VALUES (11);
+#-- should return OK
+-- error 1264
+INSERT INTO Sow6_2f VALUES (101.55);
+#-- should return SQLSTATE 22003 numeric value out of range
+-- error 1264
+UPDATE Sow6_2f SET col1 = col1 * 50 WHERE col1 = 11;
+#-- should return SQLSTATE 22003 numeric value out of range
+-- error 1365
+UPDATE Sow6_2f SET col1 = col1 / 0 WHERE col1 > 0;
+#-- should return SQLSTATE 22012 division by zero
+SELECT MOD(col1,0) FROM Sow6_2f;
+#-- should return SQLSTATE 22012 division by zero
+-- error 1366
+INSERT INTO Sow6_2f VALUES ('a59b');
+#-- should return SQLSTATE 22018 invalid character value for cast
+drop table Sow6_2f;
+
+#
+# bug#9501
+#
+select 10.3330000000000/12.34500000;
+
+#
+# Bug #10404
+#
+
+set sql_mode='';
+select 0/0;
+
+#
+# bug #9546
+#
+--disable_ps_protocol
+select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 as x;
+select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x;
+--enable_ps_protocol
+#
+# Bug #10004
+#
+select 0.190287977636363637 + 0.040372670 * 0 - 0;
+#
+# Bug #9527
+#
+select -0.123 * 0;
+
+#
+# Bug #10232
+#
+
+CREATE TABLE t1 (f1 DECIMAL (12,9), f2 DECIMAL(2,2));
+INSERT INTO t1 VALUES (10.5, 0);
+UPDATE t1 SET f1 = 4.5;
+SELECT * FROM t1;
+DROP TABLE t1;
+CREATE TABLE t1 (f1 DECIMAL (64,20), f2 DECIMAL(2,2));
+INSERT INTO t1 VALUES (9999999999999999999999999999999999, 0);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Bug #10599: problem with NULL
+#
+
+select abs(10/0);
+select abs(NULL);
+
+#
+# Bug #9894 (negative to unsigned column)
+#
+set @@sql_mode='traditional';
+create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (22) unsigned);
+--error 1264
+insert into t1 values(1,-1,-1);
+drop table t1;
+create table t1 (col1 decimal(5,2), col2 numeric(5,2));
+--error 1264
+insert into t1 values (999.999,999.999);
+--error 1264
+insert into t1 values (-999.999,-999.999);
+select * from t1;
+drop table t1;
+set sql_mode='';
+
+#
+# Bug #8425 (insufficient precision of the division)
+#
+set @sav_dpi= @@div_precision_increment;
+set @@div_precision_increment=15;
+create table t1 (col1 int, col2 decimal(30,25), col3 numeric(30,25));
+insert into t1 values (1,0.0123456789012345678912345,0.0123456789012345678912345);
+select col2/9999999999 from t1 where col1=1;
+select 9999999999/col2 from t1 where col1=1;
+select 77777777/7777777;
+drop table t1;
+set div_precision_increment= @sav_dpi;
+
+#
+# Bug #10896 (0.00 > -0.00)
+#
+create table t1 (a decimal(4,2));
+insert into t1 values (0.00);
+select * from t1 where a > -0.00;
+select * from t1 where a = -0.00;
+drop table t1;
+
+#
+# Bug #11215: a problem with LONGLONG_MIN
+#
+
+create table t1 (col1 bigint default -9223372036854775808);
+insert into t1 values (default);
+select * from t1;
+drop table t1;
+
+#
+# Bug #10891 (converting to decimal crashes server)
+#
+select cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15));
+
+#
+# Bug #11708 (conversion to decimal fails in decimal part)
+#
+select ln(14000) c1, convert(ln(14000),decimal(2,3)) c2, cast(ln(14000) as decimal(2,3)) c3;
+
+#
+# Bug #8449 (Silent column changes)
+#
+--error 1426
+create table t1 (sl decimal(70,30));
+--error 1425
+create table t1 (sl decimal(32,31));
+--error 1425
+create table t1 (sl decimal(0,38));
+--error 1427
+create table t1 (sl decimal(0,30));
+create table t1 (sl decimal(5, 5));
+show create table t1;
+drop table t1;
+# Test limits
+create table t1 (sl decimal(65, 30));
+show create table t1;
+drop table t1;
+
+#
+# Bug 11557 (DEFAULT values rounded improperly
+#
+create table t1 (
+ f1 decimal unsigned not null default 17.49,
+ f2 decimal unsigned not null default 17.68,
+ f3 decimal unsigned not null default 99.2,
+ f4 decimal unsigned not null default 99.7,
+ f5 decimal unsigned not null default 104.49,
+ f6 decimal unsigned not null default 199.91,
+ f7 decimal unsigned not null default 999.9,
+ f8 decimal unsigned not null default 9999.99);
+insert into t1 (f1) values (1);
+select * from t1;
+drop table t1;
+
+#
+# Bug 12173 (show create table fails)
+#
+create table t1 (
+ f0 decimal (30,30) zerofill not null DEFAULT 0,
+ f1 decimal (0,0) zerofill not null default 0);
+show create table t1;
+drop table t1;
+
+#
+# Bug 12938 (arithmetic loop's zero)
+#
+--disable-warnings
+drop procedure if exists wg2;
+--enable-warnings
+delimiter //;
+create procedure wg2()
+begin
+ declare v int default 1;
+ declare tdec decimal(5) default 0;
+ while v <= 9 do set tdec =tdec * 10;
+ select v, tdec;
+ set v = v + 1;
+ end while;
+end//
+
+call wg2()//
+
+delimiter ;//
+drop procedure wg2;
+
+#
+# Bug #12979 Stored procedures: crash if inout decimal parameter
+# (not a SP bug in fact)
+#
+
+select cast(@non_existing_user_var/2 as DECIMAL);
diff --git a/mysql-test/t/type_ranges.test b/mysql-test/t/type_ranges.test
index 945d3577046..03ee91f14d8 100644
--- a/mysql-test/t/type_ranges.test
+++ b/mysql-test/t/type_ranges.test
@@ -28,10 +28,10 @@ CREATE TABLE t1 (
date_time datetime,
blob_col blob,
tinyblob_col tinyblob,
- mediumblob_col mediumblob not null,
- longblob_col longblob not null,
- options enum('one','two','tree') not null,
- flags set('one','two','tree') not null,
+ mediumblob_col mediumblob not null default '',
+ longblob_col longblob not null default '',
+ options enum('one','two','tree') not null ,
+ flags set('one','two','tree') not null default '',
PRIMARY KEY (auto),
KEY (utiny),
KEY (tiny),
@@ -71,7 +71,7 @@ ALTER TABLE t1
add new_field char(10) default "new" not null,
change blob_col new_blob_col varchar(20),
change date_field date_field char(10),
-alter column string set default "new default",
+alter column string set default "newdefault",
alter short drop default,
DROP INDEX utiny,
DROP INDEX ushort,
@@ -132,11 +132,11 @@ select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and not (t1.string<=>t2.
drop table t2;
-create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, "a" as t2, repeat("a",256) as t3, binary repeat("b",256) as t4 from t1;
+create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
# We mask out the Privileges column because it differs with embedded server
--replace_column 8 #
show full columns from t2;
-select * from t2;
+select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
drop table t1,t2;
create table t1 (c int);
@@ -158,12 +158,19 @@ create table t2 ( id integer unsigned not null primary key );
insert into t1 values (1), (2);
insert into t2 values (1);
select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
+select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id);
create table t3 (id_A integer unsigned not null, id_B integer unsigned null );
insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
select * from t3;
+delete from t3;
+insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id);
+select * from t3;
drop table t3;
create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id );
select * from t3;
+drop table t3;
+create table t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id);
+select * from t3;
drop table t1,t2,t3;
# End of 4.1 tests
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 81c547c32f6..f96beedbebc 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -29,6 +29,8 @@ INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00");
SELECT stamp FROM t1 WHERE id="myKey";
UPDATE t1 SET value="my value" WHERE id="myKey";
SELECT stamp FROM t1 WHERE id="myKey";
+UPDATE t1 SET id="myKey" WHERE value="my value";
+SELECT stamp FROM t1 WHERE id="myKey";
drop table t1;
create table t1 (a timestamp);
diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test
new file mode 100644
index 00000000000..1a3a93018a4
--- /dev/null
+++ b/mysql-test/t/type_varchar.test
@@ -0,0 +1,132 @@
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+create table t1 (v varchar(30), c char(3), e enum('abc','def','ghi'), t text);
+system cp std_data/vchar.frm var/master-data/test/;
+truncate table vchar;
+show create table t1;
+show create table vchar;
+insert into t1 values ('abc', 'de', 'ghi', 'jkl');
+insert into t1 values ('abc ', 'de ', 'ghi', 'jkl ');
+insert into t1 values ('abc ', 'd ', 'ghi', 'jkl ');
+insert into vchar values ('abc', 'de', 'ghi', 'jkl');
+insert into vchar values ('abc ', 'de ', 'ghi', 'jkl ');
+insert into vchar values ('abc ', 'd ', 'ghi', 'jkl ');
+select length(v),length(c),length(e),length(t) from t1;
+select length(v),length(c),length(e),length(t) from vchar;
+alter table vchar add i int;
+show create table vchar;
+select length(v),length(c),length(e),length(t) from vchar;
+drop table t1, vchar;
+create table t1 (v varchar(20));
+insert into t1 values('a ');
+select v='a' from t1;
+select binary v='a' from t1;
+select binary v='a ' from t1;
+insert into t1 values('a');
+--error 1062
+alter table t1 add primary key (v);
+drop table t1;
+create table t1 (v varbinary(20));
+insert into t1 values('a');
+insert into t1 values('a ');
+alter table t1 add primary key (v);
+drop table t1;
+
+#
+# Test with varchar of lengths 254,255,256,258 & 258 to ensure we don't
+# have any problems with varchar with one or two byte length_bytes
+#
+
+create table t1 (v varchar(254), index (v));
+insert into t1 values ("This is a test ");
+insert into t1 values ("Some sample data");
+insert into t1 values (" garbage ");
+insert into t1 values (" This is a test ");
+insert into t1 values ("This is a test");
+insert into t1 values ("Hello world");
+insert into t1 values ("Foo bar");
+insert into t1 values ("This is a test");
+insert into t1 values ("MySQL varchar test");
+insert into t1 values ("test MySQL varchar");
+insert into t1 values ("This is a long string to have some random length data included");
+insert into t1 values ("Short string");
+insert into t1 values ("VSS");
+insert into t1 values ("Some samples");
+insert into t1 values ("Bar foo");
+insert into t1 values ("Bye");
+let $i= 255;
+let $j= 5;
+while ($j)
+{
+ select * from t1 where v like 'This is a test' order by v;
+ select * from t1 where v='This is a test' order by v;
+ select * from t1 where v like 'S%' order by v;
+ explain select * from t1 where v like 'This is a test' order by v;
+ explain select * from t1 where v='This is a test' order by v;
+ explain select * from t1 where v like 'S%' order by v;
+ eval alter table t1 change v v varchar($i);
+ inc $i;
+ dec $j;
+}
+let $i= 258;
+let $j= 6;
+while ($j)
+{
+ select * from t1 where v like 'This is a test' order by v;
+ select * from t1 where v='This is a test' order by v;
+ select * from t1 where v like 'S%' order by v;
+ explain select * from t1 where v like 'This is a test' order by v;
+ explain select * from t1 where v='This is a test' order by v;
+ explain select * from t1 where v like 'S%' order by v;
+ eval alter table t1 change v v varchar($i);
+ dec $i;
+ dec $j;
+}
+alter table t1 change v v varchar(254), drop key v;
+
+# Test with length(varchar) > 256 and key < 256 (to ensure things works with
+# different kind of packing
+
+alter table t1 change v v varchar(300), add key (v(10));
+select * from t1 where v like 'This is a test' order by v;
+select * from t1 where v='This is a test' order by v;
+select * from t1 where v like 'S%' order by v;
+explain select * from t1 where v like 'This is a test' order by v;
+explain select * from t1 where v='This is a test' order by v;
+explain select * from t1 where v like 'S%' order by v;
+drop table t1;
+
+#
+# bug#9339 - meaningless Field_varstring::get_key_image
+#
+create table t1 (pkcol varchar(16), othercol varchar(16), primary key (pkcol));
+insert into t1 values ('test', 'something');
+update t1 set othercol='somethingelse' where pkcol='test';
+select * from t1;
+drop table t1;
+
+#
+# Bug #9489: problems with key handling
+#
+
+create table t1 (a int, b varchar(12));
+insert into t1 values (1, 'A'), (22, NULL);
+create table t2 (a int);
+insert into t2 values (22), (22);
+select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a
+ group by t1.b, t1.a;
+drop table t1, t2;
+
+#
+# Bug #10543: convert varchar with index to text
+#
+create table t1 (f1 varchar(65500));
+create index index1 on t1(f1(10));
+show create table t1;
+alter table t1 modify f1 varchar(255);
+show create table t1;
+alter table t1 modify f1 tinytext;
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 6acccaeafd5..d4b0c1746af 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -5,9 +5,6 @@
--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6;
--enable_warnings
-# PS doesn't work correctly with found_rows: to be fixed
---disable_ps_protocol
-
CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
@@ -30,9 +27,12 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b;
explain extended (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
+# PS doesn't work correctly with found_rows: to be fixed
+--disable_ps_protocol
select found_rows();
select sql_calc_found_rows a,b from t1 union all select a,b from t2 limit 2;
select found_rows();
+--enable_ps_protocol
#
# Test some error conditions with UNION
@@ -210,15 +210,27 @@ insert into t2 values (3),(4),(5);
# Test global limits
(SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2) LIMIT 1;
+# PS doesn't work correctly with found_rows: to be fixed
+--disable_ps_protocol
select found_rows();
+--enable_ps_protocol
(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2) LIMIT 2;
+# PS doesn't work correctly with found_rows: to be fixed
+--disable_ps_protocol
select found_rows();
+--enable_ps_protocol
# Test cases where found_rows() should return number of returned rows
(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2);
+# PS doesn't work correctly with found_rows: to be fixed
+--disable_ps_protocol
select found_rows();
+--enable_ps_protocol
(SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1);
+# PS doesn't work correctly with found_rows: to be fixed
+--disable_ps_protocol
select found_rows();
+--enable_ps_protocol
# This used to work in 4.0 but not anymore in 4.1
--error 1064
(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1;
@@ -226,9 +238,15 @@ select found_rows();
# In these case found_rows() should work
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2;
+# PS doesn't work correctly with found_rows: to be fixed
+--disable_ps_protocol
select found_rows();
+--disable_ps_protocol
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2;
+# PS doesn't work correctly with found_rows: to be fixed
+--disable_ps_protocol
select found_rows();
+--disable_ps_protocol
# The following examples will not be exact
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2;
@@ -258,7 +276,7 @@ create temporary table t1 select a from t1 union select a from t2;
drop temporary table t1;
--error 1093
create table t1 select a from t1 union select a from t2;
---error 1109
+--error 1054
select a from t1 union select a from t2 order by t2.a;
drop table t1,t2;
@@ -744,6 +762,18 @@ show columns from t2;
drop table t2, t1;
#
+# Test that union with VARCHAR produces dynamic row tables
+#
+
+create table t1 (a varchar(5));
+create table t2 select * from t1 union select 'abcdefghijkl';
+show create table t2;
+select row_format from information_schema.TABLES where table_schema="test" and table_name="t2";
+alter table t2 ROW_FORMAT=fixed;
+show create table t2;
+drop table t1,t2;
+
+#
# correct conversion long string to TEXT (BUG#10025)
#
CREATE TABLE t1 (a mediumtext);
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index e4e751862f1..dd6c36d8414 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -31,7 +31,7 @@ CREATE TABLE t1
clicks int(10) unsigned DEFAULT '0' NOT NULL,
iclicks int(10) unsigned DEFAULT '0' NOT NULL,
uclicks int(10) unsigned DEFAULT '0' NOT NULL,
- ts timestamp(14),
+ ts timestamp,
PRIMARY KEY (place_id,ts)
);
@@ -52,7 +52,7 @@ CREATE TABLE t1 (
replyto varchar(255) NOT NULL default '',
subject varchar(100) NOT NULL default '',
timestamp int(10) unsigned NOT NULL default '0',
- tstamp timestamp(14) NOT NULL,
+ tstamp timestamp NOT NULL,
status int(3) NOT NULL default '0',
type varchar(15) NOT NULL default '',
assignment int(10) unsigned NOT NULL default '0',
diff --git a/mysql-test/t/user_limits.test b/mysql-test/t/user_limits.test
new file mode 100644
index 00000000000..af0f6545ac4
--- /dev/null
+++ b/mysql-test/t/user_limits.test
@@ -0,0 +1,169 @@
+#
+# Test behavior of various per-account limits (aka quotas)
+#
+
+# Requires privileges to be enabled
+-- source include/not_embedded.inc
+
+# Prepare play-ground
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (i int);
+# Just be sure that nothing will bother us
+delete from mysql.user where user like 'mysqltest\_%';
+delete from mysql.db where user like 'mysqltest\_%';
+delete from mysql.tables_priv where user like 'mysqltest\_%';
+delete from mysql.columns_priv where user like 'mysqltest\_%';
+flush privileges;
+
+# Limits doesn't work with prepared statements (yet)
+--disable_ps_protocol
+
+# Test of MAX_QUERIES_PER_HOUR limit
+grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 2;
+# This ensures that counters are reset and makes test scheduling independent
+flush user_resources;
+connect (mqph, localhost, mysqltest_1,,);
+connection mqph;
+select * from t1;
+select * from t1;
+--error 1226
+select * from t1;
+connect (mqph2, localhost, mysqltest_1,,);
+connection mqph2;
+--error 1226
+select * from t1;
+# cleanup
+connection default;
+drop user mysqltest_1@localhost;
+disconnect mqph;
+disconnect mqph2;
+
+# Test of MAX_UPDATES_PER_HOUR limit
+grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 2;
+flush user_resources;
+connect (muph, localhost, mysqltest_1,,);
+connection muph;
+select * from t1;
+select * from t1;
+select * from t1;
+delete from t1;
+delete from t1;
+--error 1226
+delete from t1;
+select * from t1;
+connect (muph2, localhost, mysqltest_1,,);
+connection muph2;
+--error 1226
+delete from t1;
+select * from t1;
+# Cleanup
+connection default;
+drop user mysqltest_1@localhost;
+disconnect muph;
+disconnect muph2;
+
+# Test of MAX_CONNECTIONS_PER_HOUR limit
+grant usage on *.* to mysqltest_1@localhost with max_connections_per_hour 2;
+flush user_resources;
+connect (mcph1, localhost, mysqltest_1,,);
+connection mcph1;
+select * from t1;
+connect (mcph2, localhost, mysqltest_1,,);
+connection mcph2;
+select * from t1;
+--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
+--error 1226
+connect (mcph3, localhost, mysqltest_1,,);
+# Old connection is still ok
+select * from t1;
+# Let us try to close old connections and try again. This will also test that
+# counters are not thrown away if there are no connections for this user.
+disconnect mcph1;
+disconnect mcph2;
+--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
+--error 1226
+connect (mcph3, localhost, mysqltest_1,,);
+# Cleanup
+connection default;
+drop user mysqltest_1@localhost;
+
+# Test of MAX_USER_CONNECTIONS limit
+# We need this to reset internal mqh_used variable
+flush privileges;
+grant usage on *.* to mysqltest_1@localhost with max_user_connections 2;
+flush user_resources;
+connect (muc1, localhost, mysqltest_1,,);
+connection muc1;
+select * from t1;
+connect (muc2, localhost, mysqltest_1,,);
+connection muc2;
+select * from t1;
+--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
+--error 1226
+connect (muc3, localhost, mysqltest_1,,);
+# Closing of one of connections should help
+disconnect muc1;
+connect (muc3, localhost, mysqltest_1,,);
+select * from t1;
+# Changing of limit should also help (and immediately)
+connection default;
+grant usage on *.* to mysqltest_1@localhost with max_user_connections 3;
+flush user_resources;
+connect (muc4, localhost, mysqltest_1,,);
+connection muc4;
+select * from t1;
+--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
+--error 1226
+connect (muc5, localhost, mysqltest_1,,);
+# Clean up
+connection default;
+disconnect muc2;
+disconnect muc3;
+disconnect muc4;
+drop user mysqltest_1@localhost;
+
+# Now let us test interaction between global and per-account
+# max_user_connections limits
+select @@session.max_user_connections, @@global.max_user_connections;
+# Local max_user_connections variable can't be set directly
+# since this limit is per-account
+--error 1229
+set session max_user_connections= 2;
+# But it is ok to set global max_user_connections
+set global max_user_connections= 2;
+select @@session.max_user_connections, @@global.max_user_connections;
+# Let us check that global limit works
+grant usage on *.* to mysqltest_1@localhost;
+flush user_resources;
+connect (muca1, localhost, mysqltest_1,,);
+connection muca1;
+select @@session.max_user_connections, @@global.max_user_connections;
+connect (muca2, localhost, mysqltest_1,,);
+connection muca2;
+select * from t1;
+--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
+--error 1203
+connect (muca3, localhost, mysqltest_1,,);
+# Now we are testing that per-account limit prevails over gloabl limit
+connection default;
+grant usage on *.* to mysqltest_1@localhost with max_user_connections 3;
+flush user_resources;
+connect (muca3, localhost, mysqltest_1,,);
+connection muca3;
+select @@session.max_user_connections, @@global.max_user_connections;
+--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
+--error 1226
+connect (muca4, localhost, mysqltest_1,,);
+# Cleanup
+connection default;
+disconnect muca1;
+disconnect muca2;
+disconnect muca3;
+set global max_user_connections= 0;
+drop user mysqltest_1@localhost;
+--enable_ps_protocol
+
+# Final cleanup
+drop table t1;
diff --git a/mysql-test/t/user_var-binlog.test b/mysql-test/t/user_var-binlog.test
index 6373a1cc426..004154339b2 100644
--- a/mysql-test/t/user_var-binlog.test
+++ b/mysql-test/t/user_var-binlog.test
@@ -10,7 +10,7 @@ INSERT INTO t1 VALUES(@`a b`);
set @var1= "';aaa";
SET @var2=char(ascii('a'));
insert into t1 values (@var1),(@var2);
-show binlog events from 79;
+show binlog events from 98;
# more important than SHOW BINLOG EVENTS, mysqlbinlog (where we
# absolutely need variables names to be quoted and strings to be
# escaped).
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 7691a574a2a..e3b5b4ef33e 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -20,6 +20,7 @@ insert into t2 select distinct i from t1;
select * from t2;
select distinct t2.i,@vv1:=if(sv1.i,1,0),@vv2:=if(sv2.i,1,0),@vv3:=if(sv3.i,1,0), @vv1+@vv2+@vv3 from t2 left join t1 as sv1 on sv1.i=t2.i and sv1.v=1 left join t1 as sv2 on sv2.i=t2.i and sv2.v=2 left join t1 as sv3 on sv3.i=t2.i and sv3.v=3;
explain select * from t1 where i=@vv1;
+select @vv1,i,v from t1 where i=@vv1;
explain select * from t1 where @vv1:=@vv1+1 and i=@vv1;
explain select @vv1:=i from t1 where i=@vv1;
explain select * from t1 where i=@vv1;
@@ -117,7 +118,7 @@ select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4);
#
--error 1064
set session @honk=99;
---error 1105
+--error 1382
set one_shot @honk=99;
#
@@ -142,3 +143,29 @@ select @@global.version;
select @@session.VERSION;
# End of 4.1 tests
+
+#
+# Bug #6598: problem with cast(NULL as signed integer);
+#
+
+set @first_var= NULL;
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
+set @first_var= cast(NULL as signed integer);
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
+set @first_var= NULL;
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
+set @first_var= concat(NULL);
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
+set @first_var=1;
+set @first_var= cast(NULL as CHAR);
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index a8844070207..afd0fe23805 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -5,8 +5,20 @@
drop table if exists t1,t2;
--enable_warnings
-set @`test`=1,@TEST=3,@select=2,@t5=1.23456;
-select @test,@`select`,@TEST,@not_used;
+# case insensitivity tests (new in 5.0)
+set @`test`=1;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+set @TEST=2;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+set @"tEST"=3;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+set @`TeST`=4;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+select @`teST`:=5;
+select @test, @`test`, @TEST, @`TEST`, @"teSt";
+
+set @select=2,@t5=1.23456;
+select @`select`,@not_used;
set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL;
--replace_result e-0 e- e+0 e+
select @test_int,@test_double,@test_string,@test_string2,@select;
@@ -60,16 +72,19 @@ explain extended select @@IDENTITY,last_insert_id(), @@identity;
set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON";
-set global concurrent_insert=ON;
+set global concurrent_insert=2;
show variables like 'concurrent_insert';
set global concurrent_insert=1;
show variables like 'concurrent_insert';
set global concurrent_insert=0;
show variables like 'concurrent_insert';
-set global concurrent_insert=OFF;
-show variables like 'concurrent_insert';
set global concurrent_insert=DEFAULT;
-show variables like 'concurrent_insert';
+select @@concurrent_insert;
+
+set global timed_mutexes=ON;
+show variables like 'timed_mutexes';
+set global timed_mutexes=0;
+show variables like 'timed_mutexes';
set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="MERGE";
show local variables like 'storage_engine';
@@ -163,8 +178,6 @@ set @@global.sql_auto_is_null=1;
select @@global.sql_auto_is_null;
--error 1229
set myisam_max_sort_file_size=100;
---error 1229
-set myisam_max_extra_sort_file_size=100;
--error 1231
set @@SQL_WARNINGS=NULL;
@@ -211,9 +224,6 @@ set max_tmp_tables=100;
set global max_user_connections=100;
select @@max_user_connections;
set global max_write_lock_count=100;
-set global myisam_max_extra_sort_file_size=100;
-select @@myisam_max_extra_sort_file_size;
-set global myisam_max_sort_file_size=100;
set myisam_sort_buffer_size=100;
set net_buffer_length=100;
set net_read_timeout=100;
@@ -355,8 +365,8 @@ show create table t1;
drop table t1;
#
# What types and widths have variables?
-set @arg00= 8, @arg01= 8.8, @arg02= 'a string';
-create table t1 as select @arg00 as c1, @arg01 as c2, @arg02 as c3;
+set @arg00= 8, @arg01= 8.8, @arg02= 'a string', @arg03= 0.2e0;
+create table t1 as select @arg00 as c1, @arg01 as c2, @arg02 as c3, @arg03 as c4;
show create table t1;
drop table t1;
@@ -391,8 +401,46 @@ set names latin1;
# End of 4.1 tests
#
+# Bug#6282 Packet error with SELECT INTO
+#
+
+create table t1 (a int);
+select a into @x from t1;
+show warnings;
+drop table t1;
+
+#
+# Bug #10339: read only variables.
+#
+
+--error 1238
+set @@warning_count=1;
+--error 1238
+set @@global.error_count=1;
+
+#
+# Bug #10351: Setting ulong variable to > MAX_ULONG fails on 32-bit platform
+#
+
+set @@max_heap_table_size= 4294967296;
+select @@max_heap_table_size > 0;
+set global max_heap_table_size= 4294967296;
+select @@max_heap_table_size > 0;
+set @@max_heap_table_size= 4294967296;
+select @@max_heap_table_size > 0;
+
+#
# Bug #9613: @@have_innodb
#
--replace_column 1 #
select @@have_innodb;
+
+#
+# Bug #11775 Variable character_set_system does not exist (sometimes)
+#
+select @@character_set_system;
+--error 1238
+set global character_set_system = latin1;
+--error 1238
+set @@global.version_compile_os='234';
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
new file mode 100644
index 00000000000..72bec0c4873
--- /dev/null
+++ b/mysql-test/t/view.test
@@ -0,0 +1,2139 @@
+--disable_warnings
+drop table if exists t1,t2,t9,`t1a``b`,v1,v2,v3,v4,v5,v6;
+drop view if exists t1,t2,`t1a``b`,v1,v2,v3,v4,v5,v6;
+drop database if exists mysqltest;
+--enable_warnings
+use test;
+
+#
+# some basic test of views and its functionality
+#
+
+# create view on nonexistent table
+-- error 1146
+create view v1 (c,d) as select a,b from t1;
+
+create temporary table t1 (a int, b int);
+# view on temporary table
+-- error 1352
+create view v1 (c) as select b+1 from t1;
+drop table t1;
+
+create table t1 (a int, b int);
+insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
+
+# view with variable
+-- error 1351
+create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
+
+# simple view
+create view v1 (c) as select b+1 from t1;
+select c from v1;
+
+# temporary table should not hide table of view
+create temporary table t1 (a int, b int);
+# this is empty
+select * from t1;
+# but this based on normal t1
+select c from v1;
+show create table v1;
+show create view v1;
+-- error 1347
+show create view t1;
+drop table t1;
+
+# try to use fields from underlying table
+-- error 1054
+select a from v1;
+-- error 1054
+select v1.a from v1;
+-- error 1054
+select b from v1;
+-- error 1054
+select v1.b from v1;
+
+# view with different algorithms (explain output differs)
+explain extended select c from v1;
+create algorithm=temptable view v2 (c) as select b+1 from t1;
+show create view v2;
+select c from v2;
+explain extended select c from v2;
+
+# try to use underlying table fields in VIEW creation process
+-- error 1054
+create view v3 (c) as select a+1 from v1;
+-- error 1054
+create view v3 (c) as select b+1 from v1;
+
+
+# VIEW on VIEW test with mixing different algorithms on different order
+create view v3 (c) as select c+1 from v1;
+select c from v3;
+explain extended select c from v3;
+create algorithm=temptable view v4 (c) as select c+1 from v2;
+select c from v4;
+explain extended select c from v4;
+create view v5 (c) as select c+1 from v2;
+select c from v5;
+explain extended select c from v5;
+create algorithm=temptable view v6 (c) as select c+1 from v1;
+select c from v6;
+explain extended select c from v6;
+
+# show table/table status test
+show tables;
+show full tables;
+--replace_column 8 # 12 # 13 #
+show table status;
+
+drop view v1,v2,v3,v4,v5,v6;
+
+#
+# alter/create view test
+#
+
+# view with subqueries of different types
+create view v1 (c,d,e,f) as select a,b,
+a in (select a+2 from t1), a = all (select a from t1) from t1;
+create view v2 as select c, d from v1;
+select * from v1;
+select * from v2;
+
+# try to create VIEW with name of existing VIEW
+-- error 1050
+create view v1 (c,d,e,f) as select a,b, a in (select a+2 from t1), a = all (select a from t1) from t1;
+
+# 'or replace' should work in this case
+create or replace view v1 (c,d,e,f) as select a,b, a in (select a+2 from t1), a = all (select a from t1) from t1;
+
+# try to ALTER unexisting VIEW
+drop view v2;
+-- error 1146
+alter view v2 as select c, d from v1;
+
+# 'or replace' on unexisting view
+create or replace view v2 as select c, d from v1;
+
+# alter view on existing view
+alter view v1 (c,d) as select a,max(b) from t1 group by a;
+
+# check that created view works
+select * from v1;
+select * from v2;
+
+# try to drop nonexistent VIEW
+-- error 1051
+drop view v100;
+
+# try to drop table with DROP VIEW
+-- error 1347
+drop view t1;
+
+# try to drop VIEW with DROP TABLE
+-- error 1051
+drop table v1;
+
+# try to drop table with DROP VIEW
+
+drop view v1,v2;
+drop table t1;
+
+#
+# outer left join with merged views
+#
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+
+create view v1 (a) as select a+1 from t1;
+create view v2 (a) as select a-1 from t1;
+
+--disable_parsing # WL #2486 should enable these tests
+select * from t1 natural left join v1;
+select * from v2 natural left join t1;
+select * from v2 natural left join v1;
+--enable_parsing
+
+drop view v1, v2;
+drop table t1;
+
+
+#
+# DISTINCT option for VIEW
+#
+create table t1 (a int);
+insert into t1 values (1), (2), (3), (1), (2), (3);
+create view v1 as select distinct a from t1;
+select * from v1;
+explain select * from v1;
+select * from t1;
+drop view v1;
+drop table t1;
+
+#
+# syntax compatibility
+#
+create table t1 (a int);
+-- error 1368
+create view v1 as select distinct a from t1 WITH CHECK OPTION;
+create view v1 as select a from t1 WITH CHECK OPTION;
+create view v2 as select a from t1 WITH CASCADED CHECK OPTION;
+create view v3 as select a from t1 WITH LOCAL CHECK OPTION;
+drop view v3 RESTRICT;
+drop view v2 CASCADE;
+drop view v1;
+drop table t1;
+
+#
+# aliases
+#
+create table t1 (a int, b int);
+insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
+create view v1 (c) as select b+1 from t1;
+select test.c from v1 test;
+create algorithm=temptable view v2 (c) as select b+1 from t1;
+select test.c from v2 test;
+select test1.* from v1 test1, v2 test2 where test1.c=test2.c;
+select test2.* from v1 test1, v2 test2 where test1.c=test2.c;
+drop table t1;
+drop view v1,v2;
+
+#
+# LIMIT clause test
+#
+create table t1 (a int);
+insert into t1 values (1), (2), (3), (4);
+create view v1 as select a+1 from t1 order by 1 desc limit 2;
+select * from v1;
+explain select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# CREATE ... SELECT view test
+#
+create table t1 (a int);
+insert into t1 values (1), (2), (3), (4);
+create view v1 as select a+1 from t1;
+create table t2 select * from v1;
+show columns from t2;
+select * from t2;
+drop view v1;
+drop table t1,t2;
+
+#
+# simple view + simple update
+#
+create table t1 (a int, b int, primary key(a));
+insert into t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
+create view v1 (a,c) as select a, b+1 from t1;
+create algorithm=temptable view v2 (a,c) as select a, b+1 from t1;
+# try to update expression
+-- error 1348
+update v1 set c=a+c;
+# try to update VIEW with forced TEMPORARY TABLE algorithm
+-- error 1288
+update v2 set a=a+c;
+# updatable field of updateable view
+update v1 set a=a+c;
+select * from v1;
+select * from t1;
+drop table t1;
+drop view v1,v2;
+
+#
+# simple view + simple multi-update
+#
+create table t1 (a int, b int, primary key(a));
+insert into t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
+create table t2 (x int);
+insert into t2 values (10), (20);
+create view v1 (a,c) as select a, b+1 from t1;
+create algorithm=temptable view v2 (a,c) as select a, b+1 from t1;
+# try to update expression
+-- error 1348
+update t2,v1 set v1.c=v1.a+v1.c where t2.x=v1.a;
+# try to update VIEW with forced TEMPORARY TABLE algorithm
+-- error 1288
+update t2,v2 set v2.a=v2.v2.a+c where t2.x=v2.a;
+# updatable field of updateable view
+update t2,v1 set v1.a=v1.a+v1.c where t2.x=v1.a;
+select * from v1;
+select * from t1;
+drop table t1,t2;
+drop view v1,v2;
+
+#
+# MERGE VIEW with WHERE clause
+#
+create table t1 (a int, b int, primary key(b));
+insert into t1 values (1,20), (2,30), (3,40), (4,50), (5,100);
+create view v1 (c) as select b from t1 where a<3;
+# simple select and explaint to be sure that it is MERGE
+select * from v1;
+explain extended select * from v1;
+# update test
+update v1 set c=c+1;
+select * from t1;
+# join of such VIEWs test
+create view v2 (c) as select b from t1 where a>=3;
+select * from v1, v2;
+drop view v1, v2;
+drop table t1;
+
+#
+# simple view + simple delete
+#
+create table t1 (a int, b int, primary key(a));
+insert into t1 values (1,2), (2,3), (3,4), (4,5), (5,10);
+create view v1 (a,c) as select a, b+1 from t1;
+create algorithm=temptable view v2 (a,c) as select a, b+1 from t1;
+# try to update VIEW with forced TEMPORARY TABLE algorithm
+-- error 1288
+delete from v2 where c < 4;
+# updatable field of updateable view
+delete from v1 where c < 4;
+select * from v1;
+select * from t1;
+drop table t1;
+drop view v1,v2;
+
+#
+# simple view + simple multi-delete
+#
+create table t1 (a int, b int, primary key(a));
+insert into t1 values (1,2), (2,3), (3,4), (4,5), (5,10);
+create table t2 (x int);
+insert into t2 values (1), (2), (3), (4);
+create view v1 (a,c) as select a, b+1 from t1;
+create algorithm=temptable view v2 (a,c) as select a, b+1 from t1;
+# try to update VIEW with forced TEMPORARY TABLE algorithm
+-- error 1288
+delete v2 from t2,v2 where t2.x=v2.a;
+# updatable field of updateable view
+delete v1 from t2,v1 where t2.x=v1.a;
+select * from v1;
+select * from t1;
+drop table t1,t2;
+drop view v1,v2;
+
+#
+# key presence check
+#
+create table t1 (a int, b int, c int, primary key(a,b));
+insert into t1 values (10,2,-1), (20,3,-2), (30,4,-3), (40,5,-4), (50,10,-5);
+create view v1 (x,y) as select a, b from t1;
+create view v2 (x,y) as select a, c from t1;
+set updatable_views_with_limit=NO;
+update v1 set x=x+1;
+update v2 set x=x+1;
+update v1 set x=x+1 limit 1;
+-- error 1288
+update v2 set x=x+1 limit 1;
+set updatable_views_with_limit=YES;
+update v1 set x=x+1 limit 1;
+update v2 set x=x+1 limit 1;
+set updatable_views_with_limit=DEFAULT;
+show variables like "updatable_views_with_limit";
+select * from t1;
+drop table t1;
+drop view v1,v2;
+
+#
+# simple insert
+#
+create table t1 (a int, b int, c int, primary key(a,b));
+insert into t1 values (10,2,-1), (20,3,-2);
+create view v1 (x,y,z) as select c, b, a from t1;
+create view v2 (x,y) as select b, a from t1;
+create view v3 (x,y,z) as select b, a, b from t1;
+create view v4 (x,y,z) as select c+1, b, a from t1;
+create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1;
+# try insert to VIEW with fields duplicate
+-- error 1288
+insert into v3 values (-60,4,30);
+# try insert to VIEW with expression in SELECT list
+-- error 1288
+insert into v4 values (-60,4,30);
+# try insert to VIEW using temporary table algorithm
+-- error 1288
+insert into v5 values (-60,4,30);
+insert into v1 values (-60,4,30);
+insert into v1 (z,y,x) values (50,6,-100);
+insert into v2 values (5,40);
+select * from t1;
+drop table t1;
+drop view v1,v2,v3,v4,v5;
+
+#
+# insert ... select
+#
+create table t1 (a int, b int, c int, primary key(a,b));
+insert into t1 values (10,2,-1), (20,3,-2);
+create table t2 (a int, b int, c int, primary key(a,b));
+insert into t2 values (30,4,-60);
+create view v1 (x,y,z) as select c, b, a from t1;
+create view v2 (x,y) as select b, a from t1;
+create view v3 (x,y,z) as select b, a, b from t1;
+create view v4 (x,y,z) as select c+1, b, a from t1;
+create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1;
+# try insert to VIEW with fields duplicate
+-- error 1288
+insert into v3 select c, b, a from t2;
+# try insert to VIEW with expression in SELECT list
+-- error 1288
+insert into v4 select c, b, a from t2;
+# try insert to VIEW using temporary table algorithm
+-- error 1288
+insert into v5 select c, b, a from t2;
+insert into v1 select c, b, a from t2;
+insert into v1 (z,y,x) select a+20,b+2,-100 from t2;
+insert into v2 select b+1, a+10 from t2;
+select * from t1;
+drop table t1, t2;
+drop view v1,v2,v3,v4,v5;
+
+#
+# outer join based on VIEW with WHERE clause
+#
+create table t1 (a int, primary key(a));
+insert into t1 values (1), (2), (3);
+create view v1 (x) as select a from t1 where a > 1;
+select t1.a, v1.x from t1 left join v1 on (t1.a= v1.x);
+drop table t1;
+drop view v1;
+
+#
+# merging WHERE condition on VIEW on VIEW
+#
+create table t1 (a int, primary key(a));
+insert into t1 values (1), (2), (3), (200);
+create view v1 (x) as select a from t1 where a > 1;
+create view v2 (y) as select x from v1 where x < 100;
+select * from v2;
+drop table t1;
+drop view v1,v2;
+
+#
+# VIEW on non-updatable view
+#
+create table t1 (a int, primary key(a));
+insert into t1 values (1), (2), (3), (200);
+create ALGORITHM=TEMPTABLE view v1 (x) as select a from t1;
+create view v2 (y) as select x from v1;
+-- error 1288
+update v2 set y=10 where y=2;
+drop table t1;
+drop view v1,v2;
+
+#
+# auto_increment field out of VIEW
+#
+create table t1 (a int not null auto_increment, b int not null, primary key(a), unique(b));
+create view v1 (x) as select b from t1;
+insert into v1 values (1);
+select last_insert_id();
+insert into t1 (b) values (2);
+select last_insert_id();
+select * from t1;
+drop view v1;
+drop table t1;
+
+#
+# VIEW fields quoting
+#
+set sql_mode='ansi';
+create table t1 ("a*b" int);
+create view v1 as select "a*b" from t1;
+show create view v1;
+drop view v1;
+drop table t1;
+set sql_mode=default;
+
+#
+# VIEW without tables
+#
+create table t1 (t_column int);
+create view v1 as select 'a';
+select * from v1, t1;
+drop view v1;
+drop table t1;
+
+#
+# quote mark inside table name
+#
+create table `t1a``b` (col1 char(2));
+create view v1 as select * from `t1a``b`;
+select * from v1;
+describe v1;
+drop view v1;
+drop table `t1a``b`;
+
+#
+# Changing of underlying table
+#
+create table t1 (col1 char(5),col2 char(5));
+create view v1 as select * from t1;
+drop table t1;
+create table t1 (col1 char(5),newcol2 char(5));
+-- error 1356
+insert into v1 values('a','aa');
+drop table t1;
+-- error 1356
+select * from v1;
+drop view v1;
+
+#
+# check of duplication of column names
+#
+-- error 1060
+create view v1 (a,a) as select 'a','a';
+
+#
+# SP variables inside view test
+#
+--disable_warnings
+drop procedure if exists p1;
+--enable_warnings
+delimiter //;
+create procedure p1 () begin declare v int; create view v1 as select v; end;//
+delimiter ;//
+-- error 1351
+call p1();
+drop procedure p1;
+
+#
+# updatablity should be transitive
+#
+create table t1 (col1 int,col2 char(22));
+insert into t1 values(5,'Hello, world of views');
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+update v2 set col2='Hello, view world';
+select * from t1;
+drop view v2, v1;
+drop table t1;
+
+#
+# check 'use index' on view with temporary table
+#
+create table t1 (a int, b int);
+create view v1 as select a, sum(b) from t1 group by a;
+-- error 1072
+select b from v1 use index (some_index) where b=1;
+drop view v1;
+drop table t1;
+
+#
+# using VIEW fields several times in query resolved via temporary tables
+#
+create table t1 (col1 char(5),col2 char(5));
+create view v1 (col1,col2) as select col1,col2 from t1;
+insert into v1 values('s1','p1'),('s1','p2'),('s1','p3'),('s1','p4'),('s2','p1'),('s3','p2'),('s4','p4');
+select distinct first.col2 from t1 first where first.col2 in (select second.col2 from t1 second where second.col1<>first.col1);
+select distinct first.col2 from v1 first where first.col2 in (select second.col2 from t1 second where second.col1<>first.col1);
+drop view v1;
+drop table t1;
+
+#
+# Test of view updatability in prepared statement
+#
+create table t1 (a int);
+create view v1 as select a from t1;
+insert into t1 values (1);
+
+#update
+SET @v0 = '2';
+PREPARE stmt FROM 'UPDATE v1 SET a = ?';
+EXECUTE stmt USING @v0;
+DEALLOCATE PREPARE stmt;
+
+#insert without field list
+SET @v0 = '3';
+PREPARE stmt FROM 'insert into v1 values (?)';
+EXECUTE stmt USING @v0;
+DEALLOCATE PREPARE stmt;
+
+#insert with field list
+SET @v0 = '4';
+PREPARE stmt FROM 'insert into v1 (a) values (?)';
+EXECUTE stmt USING @v0;
+DEALLOCATE PREPARE stmt;
+
+select * from t1;
+
+drop view v1;
+drop table t1;
+
+#
+# error on preparation
+#
+-- error 1096
+CREATE VIEW v02 AS SELECT * FROM DUAL;
+SHOW TABLES;
+
+#
+# EXISTS with UNION VIEW
+#
+CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2);
+select * from v1;
+drop view v1;
+
+#
+# using VIEW where table is required
+#
+create table t1 (col1 int,col2 char(22));
+create view v1 as select * from t1;
+-- error 1347
+create index i1 on v1 (col1);
+drop view v1;
+drop table t1;
+
+#
+# connection_id(), pi(), current_user(), version() representation test
+#
+CREATE VIEW v1 (f1,f2,f3,f4) AS SELECT connection_id(), pi(), current_user(), version();
+SHOW CREATE VIEW v1;
+drop view v1;
+
+#
+# VIEW built over UNION
+#
+create table t1 (s1 int);
+create table t2 (s2 int);
+insert into t1 values (1), (2);
+insert into t2 values (2), (3);
+create view v1 as select * from t1,t2 union all select * from t1,t2;
+select * from v1;
+drop view v1;
+drop tables t1, t2;
+
+#
+# Aggregate functions in view list
+#
+create table t1 (col1 int);
+insert into t1 values (1);
+create view v1 as select count(*) from t1;
+insert into t1 values (null);
+select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# Showing VIEW with VIEWs in subquery
+#
+create table t1 (a int);
+create table t2 (a int);
+create view v1 as select a from t1;
+create view v2 as select a from t2 where a in (select a from v1);
+show create view v2;
+drop view v2, v1;
+drop table t1, t2;
+
+#
+# SHOW VIEW view with name with spaces
+#
+CREATE VIEW `v 1` AS select 5 AS `5`;
+show create view `v 1`;
+drop view `v 1`;
+
+#
+# Removing database with .frm archives
+#
+create database mysqltest;
+create table mysqltest.t1 (a int, b int);
+create view mysqltest.v1 as select a from mysqltest.t1;
+alter view mysqltest.v1 as select b from mysqltest.t1;
+alter view mysqltest.v1 as select a from mysqltest.t1;
+drop database mysqltest;
+
+#
+# VIEW with full text
+#
+CREATE TABLE t1 (c1 int not null auto_increment primary key, c2 varchar(20), fulltext(c2));
+insert into t1 (c2) VALUES ('real Beer'),('Water'),('Kossu'),('Coca-Cola'),('Vodka'),('Wine'),('almost real Beer');
+select * from t1 WHERE match (c2) against ('Beer');
+CREATE VIEW v1 AS SELECT * from t1 WHERE match (c2) against ('Beer');
+select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# distinct in temporary table with a VIEW
+#
+create table t1 (a int);
+insert into t1 values (1),(1),(2),(2),(3),(3);
+create view v1 as select a from t1;
+select distinct a from v1;
+select distinct a from v1 limit 2;
+select distinct a from t1 limit 2;
+prepare stmt1 from "select distinct a from v1 limit 2";
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+
+#
+# aggregate function of aggregate function
+#
+create table t1 (tg_column bigint);
+create view v1 as select count(tg_column) as vg_column from t1;
+select avg(vg_column) from v1;
+drop view v1;
+drop table t1;
+
+#
+# VIEW of VIEW with column renaming
+#
+create table t1 (col1 bigint not null, primary key (col1));
+create table t2 (col1 bigint not null, key (col1));
+create view v1 as select * from t1;
+create view v2 as select * from t2;
+insert into v1 values (1);
+insert into v2 values (1);
+create view v3 (a,b) as select v1.col1 as a, v2.col1 as b from v1, v2 where v1.col1 = v2.col1;
+select * from v3;
+show create view v3;
+drop view v3, v2, v1;
+drop table t2, t1;
+
+#
+# VIEW based on functions with complex names
+#
+create function `f``1` () returns int return 5;
+create view v1 as select test.`f``1` ();
+show create view v1;
+select * from v1;
+drop view v1;
+drop function `f``1`;
+
+#
+# tested problem when function name length close to ALIGN_SIZE
+#
+create function x () returns int return 5;
+create view v1 as select x ();
+select * from v1;
+drop view v1;
+drop function x;
+
+#
+# VIEW with collation
+#
+create table t2 (col1 char collate latin1_german2_ci);
+create view v2 as select col1 collate latin1_german1_ci from t2;
+show create view v2;
+show create view v2;
+drop view v2;
+drop table t2;
+
+#
+# order by refers on integer field
+#
+create table t1 (a int);
+insert into t1 values (1), (2);
+create view v1 as select 5 from t1 order by 1;
+select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# VIEW over dropped function
+#
+create function x1 () returns int return 5;
+create table t1 (s1 int);
+create view v1 as select x1() from t1;
+drop function x1;
+-- error 1356
+select * from v1;
+--replace_column 8 # 12 # 13 #
+show table status;
+drop view v1;
+drop table t1;
+
+#
+# VIEW with floating point (long number) as column
+#
+create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1;
+show create view v1;
+drop view v1;
+
+#
+# VIEWs with national characters
+#
+create table tü (cü char);
+create view vü as select cü from tü;
+insert into vü values ('ü');
+select * from vü;
+drop view vü;
+drop table tü;
+
+#
+# problem with used_tables() of outer reference resolved in VIEW
+#
+create table t1 (a int, b int);
+insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
+create view v1(c) as select a+1 from t1 where b >= 4;
+select c from v1 where exists (select * from t1 where a=2 and b=c);
+drop view v1;
+drop table t1;
+
+#
+# view with cast operation
+#
+create view v1 as select cast(1 as char(3));
+show create view v1;
+select * from v1;
+drop view v1;
+
+#
+# renaming views
+#
+create table t1 (a int);
+create view v1 as select a from t1;
+create database seconddb;
+-- error 1450
+rename table v1 to seconddb.v1;
+rename table v1 to v2;
+drop table t1;
+drop view v2;
+drop database seconddb;
+
+#
+# bug handling from VIEWs
+#
+create view v1 as select 'a',1;
+create view v2 as select * from v1 union all select * from v1;
+create view v3 as select * from v2 where 1 = (select `1` from v2);
+create view v4 as select * from v3;
+-- error 1242
+select * from v4;
+drop view v4, v3, v2, v1;
+
+#
+# VIEW over SELECT with prohibited clauses
+#
+-- error 1350
+create view v1 as select 5 into @w;
+-- error 1350
+create view v1 as select 5 into outfile 'ttt';
+create table t1 (a int);
+-- error 1350
+create view v1 as select a from t1 procedure analyse();
+drop table t1;
+
+#
+# INSERT into VIEW with ON DUPLICATE
+#
+create table t1 (s1 int, primary key (s1));
+create view v1 as select * from t1;
+insert into v1 values (1) on duplicate key update s1 = 7;
+insert into v1 values (1) on duplicate key update s1 = 7;
+select * from t1;
+drop view v1;
+drop table t1;
+
+#
+# test of updating and fetching from the same table check
+#
+create table t1 (col1 int);
+create table t2 (col1 int);
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+create view v3 as select v2.col1 from v2,t2 where v2.col1 = t2.col1;
+-- error 1443
+update v2 set col1 = (select max(col1) from v1);
+-- error 1443
+update v2 set col1 = (select max(col1) from t1);
+-- error 1093
+update v2 set col1 = (select max(col1) from v2);
+-- error 1443
+update v2,t2 set v2.col1 = (select max(col1) from v1) where v2.col1 = t2.col1;
+-- error 1443
+update t1,t2 set t1.col1 = (select max(col1) from v1) where t1.col1 = t2.col1;
+-- error 1093
+update v1,t2 set v1.col1 = (select max(col1) from v1) where v1.col1 = t2.col1;
+-- error 1443
+update t2,v2 set v2.col1 = (select max(col1) from v1) where v2.col1 = t2.col1;
+-- error 1443
+update t2,t1 set t1.col1 = (select max(col1) from v1) where t1.col1 = t2.col1;
+-- error 1443
+update t2,v1 set v1.col1 = (select max(col1) from v1) where v1.col1 = t2.col1;
+-- error 1443
+update v2,t2 set v2.col1 = (select max(col1) from t1) where v2.col1 = t2.col1;
+-- error 1093
+update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
+-- error 1443
+update v1,t2 set v1.col1 = (select max(col1) from t1) where v1.col1 = t2.col1;
+-- error 1093
+update t2,v2 set v2.col1 = (select max(col1) from t1) where v2.col1 = t2.col1;
+-- error 1093
+update t2,t1 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
+-- error 1093
+update t2,v1 set v1.col1 = (select max(col1) from t1) where v1.col1 = t2.col1;
+-- error 1093
+update v2,t2 set v2.col1 = (select max(col1) from v2) where v2.col1 = t2.col1;
+-- error 1443
+update t1,t2 set t1.col1 = (select max(col1) from v2) where t1.col1 = t2.col1;
+-- error 1443
+update v1,t2 set v1.col1 = (select max(col1) from v2) where v1.col1 = t2.col1;
+-- error 1443
+update t2,v2 set v2.col1 = (select max(col1) from v2) where v2.col1 = t2.col1;
+-- error 1443
+update t2,t1 set t1.col1 = (select max(col1) from v2) where t1.col1 = t2.col1;
+-- error 1443
+update t2,v1 set v1.col1 = (select max(col1) from v2) where v1.col1 = t2.col1;
+-- error 1443
+update v3 set v3.col1 = (select max(col1) from v1);
+-- error 1443
+update v3 set v3.col1 = (select max(col1) from t1);
+-- error 1443
+update v3 set v3.col1 = (select max(col1) from v2);
+-- error 1093
+update v3 set v3.col1 = (select max(col1) from v3);
+-- error 1443
+delete from v2 where col1 = (select max(col1) from v1);
+-- error 1443
+delete from v2 where col1 = (select max(col1) from t1);
+-- error 1093
+delete from v2 where col1 = (select max(col1) from v2);
+-- error 1443
+delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1;
+-- error 1443
+delete t1 from t1,t2 where (select max(col1) from v1) > 0 and t1.col1 = t2.col1;
+-- error 1093
+delete v1 from v1,t2 where (select max(col1) from v1) > 0 and v1.col1 = t2.col1;
+-- error 1443
+delete v2 from v2,t2 where (select max(col1) from t1) > 0 and v2.col1 = t2.col1;
+-- error 1093
+delete t1 from t1,t2 where (select max(col1) from t1) > 0 and t1.col1 = t2.col1;
+-- error 1443
+delete v1 from v1,t2 where (select max(col1) from t1) > 0 and v1.col1 = t2.col1;
+-- error 1093
+delete v2 from v2,t2 where (select max(col1) from v2) > 0 and v2.col1 = t2.col1;
+-- error 1443
+delete t1 from t1,t2 where (select max(col1) from v2) > 0 and t1.col1 = t2.col1;
+-- error 1443
+delete v1 from v1,t2 where (select max(col1) from v2) > 0 and v1.col1 = t2.col1;
+-- error 1443
+insert into v2 values ((select max(col1) from v1));
+-- error 1443
+insert into t1 values ((select max(col1) from v1));
+-- error 1443
+insert into v2 values ((select max(col1) from v1));
+-- error 1443
+insert into v2 values ((select max(col1) from t1));
+-- error 1093
+insert into t1 values ((select max(col1) from t1));
+-- error 1443
+insert into v2 values ((select max(col1) from t1));
+-- error 1093
+insert into v2 values ((select max(col1) from v2));
+-- error 1443
+insert into t1 values ((select max(col1) from v2));
+-- error 1093
+insert into v2 values ((select max(col1) from v2));
+-- error 1443
+insert into v3 (col1) values ((select max(col1) from v1));
+-- error 1443
+insert into v3 (col1) values ((select max(col1) from t1));
+-- error 1443
+insert into v3 (col1) values ((select max(col1) from v2));
+#check with TZ tables in list
+-- error 1443
+insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from v2));
+insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from t2));
+-- error 1048
+insert into mysql.time_zone values ('', (select CONVERT_TZ('20050101000000','UTC','MET') from t2));
+# temporary table algorithm view should be equal to subquery in the from clause
+create algorithm=temptable view v4 as select * from t1;
+insert into t1 values (1),(2),(3);
+insert into t1 (col1) values ((select max(col1) from v4));
+select * from t1;
+
+drop view v4,v3,v2,v1;
+drop table t1,t2;
+
+#
+# HANDLER with VIEW
+#
+create table t1 (s1 int);
+create view v1 as select * from t1;
+-- error 1347
+handler v1 open as xx;
+drop view v1;
+drop table t1;
+
+#
+# view with WHERE in nested join
+#
+create table t1(a int);
+insert into t1 values (0), (1), (2), (3);
+create table t2 (a int);
+insert into t2 select a from t1 where a > 1;
+create view v1 as select a from t1 where a > 1;
+select * from t1 left join (t2 as t, v1) on v1.a=t1.a;
+select * from t1 left join (t2 as t, t2) on t2.a=t1.a;
+drop view v1;
+drop table t1, t2;
+
+#
+# Collation with view update
+#
+create table t1 (s1 char);
+create view v1 as select s1 collate latin1_german1_ci as s1 from t1;
+insert into v1 values ('a');
+select * from v1;
+update v1 set s1='b';
+select * from v1;
+update v1,t1 set v1.s1='c' where t1.s1=v1.s1;
+select * from v1;
+prepare stmt1 from "update v1,t1 set v1.s1=? where t1.s1=v1.s1";
+set @arg='d';
+execute stmt1 using @arg;
+select * from v1;
+set @arg='e';
+execute stmt1 using @arg;
+select * from v1;
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+
+#
+# test view with LOCK TABLES (work around)
+#
+create table t1 (a int);
+create table t2 (a int);
+create view v1 as select * from t1;
+lock tables t1 read, v1 read;
+select * from v1;
+-- error 1100
+select * from t2;
+drop view v1;
+drop table t1, t2;
+
+#
+# WITH CHECK OPTION insert/update test
+#
+create table t1 (a int);
+create view v1 as select * from t1 where a < 2 with check option;
+# simple insert
+insert into v1 values(1);
+-- error 1369
+insert into v1 values(3);
+# simple insert with ignore
+insert ignore into v1 values (2),(3),(0);
+select * from t1;
+# prepare data for next check
+delete from t1;
+# INSERT SELECT test
+insert into v1 SELECT 1;
+-- error 1369
+insert into v1 SELECT 3;
+# prepare data for next check
+create table t2 (a int);
+insert into t2 values (2),(3),(0);
+# INSERT SELECT with ignore test
+insert ignore into v1 SELECT a from t2;
+select * from t1;
+#simple UPDATE test
+update v1 set a=-1 where a=0;
+-- error 1369
+update v1 set a=2 where a=1;
+select * from t1;
+# prepare data for next check
+update v1 set a=0 where a=0;
+insert into t2 values (1);
+# multiupdate test
+update v1,t2 set v1.a=v1.a-1 where v1.a=t2.a;
+select * from t1;
+# prepare data for next check
+update v1 set a=a+1;
+# multiupdate with ignore test
+update ignore v1,t2 set v1.a=v1.a+1 where v1.a=t2.a;
+select * from t1;
+
+drop view v1;
+drop table t1, t2;
+
+#
+# CASCADED/LOCAL CHECK OPTION test
+#
+create table t1 (a int);
+create view v1 as select * from t1 where a < 2 with check option;
+create view v2 as select * from v1 where a > 0 with local check option;
+create view v3 as select * from v1 where a > 0 with cascaded check option;
+insert into v2 values (1);
+insert into v3 values (1);
+-- error 1369
+insert into v2 values (0);
+-- error 1369
+insert into v3 values (0);
+insert into v2 values (2);
+-- error 1369
+insert into v3 values (2);
+select * from t1;
+drop view v3,v2,v1;
+drop table t1;
+
+#
+# CHECK OPTION with INSERT ... ON DUPLICATE KEY UPDATE
+#
+create table t1 (a int, primary key (a));
+create view v1 as select * from t1 where a < 2 with check option;
+insert into v1 values (1) on duplicate key update a=2;
+-- error 1369
+insert into v1 values (1) on duplicate key update a=2;
+insert ignore into v1 values (1) on duplicate key update a=2;
+select * from t1;
+drop view v1;
+drop table t1;
+
+#
+# check cyclic referencing protection on altering view
+#
+create table t1 (s1 int);
+create view v1 as select * from t1;
+create view v2 as select * from v1;
+-- error 1146
+alter view v1 as select * from v2;
+-- error 1146
+alter view v1 as select * from v1;
+-- error 1146
+create or replace view v1 as select * from v2;
+-- error 1146
+create or replace view v1 as select * from v1;
+drop view v2,v1;
+drop table t1;
+
+#
+# check altering differ options
+#
+create table t1 (a int);
+create view v1 as select * from t1;
+show create view v1;
+alter algorithm=undefined view v1 as select * from t1 with check option;
+show create view v1;
+alter algorithm=merge view v1 as select * from t1 with cascaded check option;
+show create view v1;
+alter algorithm=temptable view v1 as select * from t1;
+show create view v1;
+drop view v1;
+drop table t1;
+
+#
+# updating view with subquery in the WHERE clause
+#
+create table t1 (s1 int);
+create table t2 (s1 int);
+create view v2 as select * from t2 where s1 in (select s1 from t1);
+insert into v2 values (5);
+insert into t1 values (5);
+select * from v2;
+update v2 set s1 = 0;
+select * from v2;
+select * from t2;
+# check it with check option
+alter view v2 as select * from t2 where s1 in (select s1 from t1) with check option;
+insert into v2 values (5);
+-- error 1369
+update v2 set s1 = 1;
+insert into t1 values (1);
+update v2 set s1 = 1;
+select * from v2;
+select * from t2;
+# scheck how VIEWs with subqueries work with prepared statements
+prepare stmt1 from "select * from v2;";
+execute stmt1;
+insert into t1 values (0);
+execute stmt1;
+deallocate prepare stmt1;
+drop view v2;
+drop table t1, t2;
+
+#
+# test of substring_index with view
+#
+create table t1 (t time);
+create view v1 as select substring_index(t,':',2) as t from t1;
+insert into t1 (t) values ('12:24:10');
+select substring_index(t,':',2) from t1;
+select substring_index(t,':',2) from v1;
+drop view v1;
+drop table t1;
+
+#
+# test of cascaded check option for whiew without WHERE clause
+#
+create table t1 (s1 tinyint);
+create view v1 as select * from t1 where s1 <> 0 with local check option;
+create view v2 as select * from v1 with cascaded check option;
+-- error 1369
+insert into v2 values (0);
+drop view v2, v1;
+drop table t1;
+
+#
+# inserting single value with check option failed always get error
+#
+create table t1 (s1 int);
+create view v1 as select * from t1 where s1 < 5 with check option;
+#single value
+-- error 1369
+insert ignore into v1 values (6);
+#several values
+insert ignore into v1 values (6),(3);
+select * from t1;
+drop view v1;
+drop table t1;
+
+#
+# changing value by trigger and CHECK OPTION
+#
+create table t1 (s1 tinyint);
+create trigger t1_bi before insert on t1 for each row set new.s1 = 500;
+create view v1 as select * from t1 where s1 <> 127 with check option;
+-- error 1369
+insert into v1 values (0);
+select * from v1;
+select * from t1;
+drop trigger t1_bi;
+drop view v1;
+drop table t1;
+
+#
+# CASCADED should be used for all underlaying VIEWs
+#
+create table t1 (s1 tinyint);
+create view v1 as select * from t1 where s1 <> 0;
+create view v2 as select * from v1 where s1 <> 1 with cascaded check option;
+-- error 1369
+insert into v2 values (0);
+select * from v2;
+select * from t1;
+drop view v2, v1;
+drop table t1;
+
+#
+# LOAD DATA with view and CHECK OPTION
+#
+# fixed length fields
+create table t1 (a int, b char(10));
+create view v1 as select * from t1 where a != 0 with check option;
+-- error 1369
+load data infile '../../std_data/loaddata3.dat' into table v1 fields terminated by '' enclosed by '' ignore 1 lines;
+select * from t1;
+select * from v1;
+delete from t1;
+load data infile '../../std_data/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines;
+select * from t1;
+select * from v1;
+drop view v1;
+drop table t1;
+# variable length fields
+create table t1 (a text, b text);
+create view v1 as select * from t1 where a <> 'Field A' with check option;
+-- error 1369
+load data infile '../../std_data/loaddata2.dat' into table v1 fields terminated by ',' enclosed by '''';
+select concat('|',a,'|'), concat('|',b,'|') from t1;
+select concat('|',a,'|'), concat('|',b,'|') from v1;
+delete from t1;
+load data infile '../../std_data/loaddata2.dat' ignore into table v1 fields terminated by ',' enclosed by '''';
+select concat('|',a,'|'), concat('|',b,'|') from t1;
+select concat('|',a,'|'), concat('|',b,'|') from v1;
+drop view v1;
+drop table t1;
+
+#
+# Trys update table from which we select using views and subqueries
+#
+create table t1 (s1 smallint);
+create view v1 as select * from t1 where 20 < (select (s1) from t1);
+-- error 1288
+insert into v1 values (30);
+create view v2 as select * from t1;
+create view v3 as select * from t1 where 20 < (select (s1) from v2);
+-- error 1288
+insert into v3 values (30);
+create view v4 as select * from v2 where 20 < (select (s1) from t1);
+-- error 1288
+insert into v4 values (30);
+drop view v4, v3, v2, v1;
+drop table t1;
+
+#
+# CHECK TABLE with VIEW
+#
+create table t1 (a int);
+create view v1 as select * from t1;
+check table t1,v1;
+check table v1,t1;
+drop table t1;
+check table v1;
+drop view v1;
+
+#
+# merge of VIEW with several tables
+#
+create table t1 (a int);
+create table t2 (a int);
+create table t3 (a int);
+insert into t1 values (1), (2), (3);
+insert into t2 values (1), (3);
+insert into t3 values (1), (2), (4);
+# view over tables
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1 left join t2 on (t1.a=t2.a);
+select * from t3 left join v3 on (t3.a = v3.a);
+explain extended select * from t3 left join v3 on (t3.a = v3.a);
+# view over views
+create view v1 (a) as select a from t1;
+create view v2 (a) as select a from t2;
+create view v4 (a,b) as select v1.a as a, v2.a as b from v1 left join v2 on (v1.a=v2.a);
+select * from t3 left join v4 on (t3.a = v4.a);
+explain extended select * from t3 left join v4 on (t3.a = v4.a);
+# PS with view over views
+prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop view v4,v3,v2,v1;
+drop tables t1,t2,t3;
+
+#
+# updating of join view
+#
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a));
+insert into t1 values (1,100), (2,200);
+insert into t2 values (1), (3);
+# legal view for update
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+update v3 set a= 10 where a=1;
+select * from t1;
+select * from t2;
+# view without primary key
+create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
+set updatable_views_with_limit=NO;
+-- error 1288
+update v2 set a= 10 where a=200 limit 1;
+set updatable_views_with_limit=DEFAULT;
+# just view selects
+select * from v3;
+select * from v2;
+# prepare statement with updating join view
+set @a= 10;
+set @b= 100;
+prepare stmt1 from "update v3 set a= ? where a=?";
+execute stmt1 using @a,@b;
+select * from v3;
+set @a= 300;
+set @b= 10;
+execute stmt1 using @a,@b;
+select * from v3;
+deallocate prepare stmt1;
+drop view v3,v2;
+drop tables t1,t2;
+
+#
+# inserting/deleting join view
+#
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a), b int);
+insert into t2 values (1000, 2000);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+# inserting into join view without field list
+-- error 1394
+insert into v3 values (1,2);
+-- error 1394
+insert into v3 select * from t2;
+# inserting in several tables of join view
+-- error 1393
+insert into v3(a,b) values (1,2);
+-- error 1393
+insert into v3(a,b) select * from t2;
+# correct inserts into join view
+insert into v3(a) values (1);
+insert into v3(b) values (10);
+insert into v3(a) select a from t2;
+insert into v3(b) select b from t2;
+insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a);
+select * from t1;
+select * from t2;
+# try delete from join view
+-- error 1395
+delete from v3;
+-- error 1395
+delete v3,t1 from v3,t1;
+-- error 1395
+delete t1,v3 from t1,v3;
+# delete from t1 just to reduce result set size
+delete from t1;
+# prepare statement with insert join view
+prepare stmt1 from "insert into v3(a) values (?);";
+set @a= 100;
+execute stmt1 using @a;
+set @a= 300;
+execute stmt1 using @a;
+deallocate prepare stmt1;
+prepare stmt1 from "insert into v3(a) select ?;";
+set @a= 101;
+execute stmt1 using @a;
+set @a= 301;
+execute stmt1 using @a;
+deallocate prepare stmt1;
+select * from v3;
+
+drop view v3;
+drop tables t1,t2;
+
+#
+# View field names should be case insensitive
+#
+create table t1(f1 int);
+create view v1 as select f1 from t1;
+select * from v1 where F1 = 1;
+drop view v1;
+drop table t1;
+
+#
+# Resolving view fields in subqueries in VIEW (Bug #6394)
+#
+create table t1(c1 int);
+create table t2(c2 int);
+insert into t1 values (1),(2),(3);
+insert into t2 values (1);
+SELECT c1 FROM t1 WHERE c1 IN (SELECT c2 FROM t2);
+SELECT c1 FROM t1 WHERE EXISTS (SELECT c2 FROM t2 WHERE c2 = c1);
+create view v1 as SELECT c1 FROM t1 WHERE c1 IN (SELECT c2 FROM t2);
+create view v2 as SELECT c1 FROM t1 WHERE EXISTS (SELECT c2 FROM t2 WHERE c2 = c1);
+select * from v1;
+select * from v2;
+select * from (select c1 from v2) X;
+drop view v2, v1;
+drop table t1, t2;
+
+#
+# view over other view setup (BUG#7433)
+#
+CREATE TABLE t1 (C1 INT, C2 INT);
+CREATE TABLE t2 (C2 INT);
+CREATE VIEW v1 AS SELECT C2 FROM t2;
+CREATE VIEW v2 AS SELECT C1 FROM t1 LEFT OUTER JOIN v1 USING (C2);
+SELECT * FROM v2;
+drop view v2, v1;
+drop table t1, t2;
+
+#
+# view and group_concat() (BUG#7116)
+#
+create table t1 (col1 char(5),col2 int,col3 int);
+insert into t1 values ('one',10,25), ('two',10,50), ('two',10,50), ('one',20,25), ('one',30,25);
+create view v1 as select * from t1;
+select col1,group_concat(col2,col3) from t1 group by col1;
+select col1,group_concat(col2,col3) from v1 group by col1;
+drop view v1;
+drop table t1;
+
+#
+# Item_ref resolved as view field (BUG#6894)
+#
+create table t1 (s1 int, s2 char);
+create view v1 as select s1, s2 from t1;
+-- error 1054
+select s2 from v1 vq1 where 2 = (select count(*) from v1 vq2 having vq1.s2 = vq2.s2);
+select s2 from v1 vq1 where 2 = (select count(*) aa from v1 vq2 having vq1.s2 = aa);
+drop view v1;
+drop table t1;
+
+#
+# Test case for bug #9398 CREATE TABLE with SELECT from a multi-table view
+#
+CREATE TABLE t1 (a1 int);
+CREATE TABLE t2 (a2 int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+INSERT INTO t2 VALUES (1), (2), (3);
+CREATE VIEW v1(a,b) AS SELECT a1,a2 FROM t1 JOIN t2 ON a1=a2 WHERE a1>1;
+
+SELECT * FROM v1;
+CREATE TABLE t3 SELECT * FROM v1;
+SELECT * FROM t3;
+
+DROP VIEW v1;
+DROP TABLE t1,t2,t3;
+
+#
+# Test for BUG#8703 "insert into table select from view crashes"
+#
+create table t1 (a int);
+create table t2 like t1;
+create table t3 like t1;
+create view v1 as select t1.a x, t2.a y from t1 join t2 where t1.a=t2.a;
+insert into t3 select x from v1;
+insert into t2 select x from v1;
+drop view v1;
+drop table t1,t2,t3;
+
+#
+# Test for BUG #6106: query over a view using subquery for the underlying table
+#
+
+CREATE TABLE t1 (col1 int PRIMARY KEY, col2 varchar(10));
+INSERT INTO t1 VALUES(1,'trudy');
+INSERT INTO t1 VALUES(2,'peter');
+INSERT INTO t1 VALUES(3,'sanja');
+INSERT INTO t1 VALUES(4,'monty');
+INSERT INTO t1 VALUES(5,'david');
+INSERT INTO t1 VALUES(6,'kent');
+INSERT INTO t1 VALUES(7,'carsten');
+INSERT INTO t1 VALUES(8,'ranger');
+INSERT INTO t1 VALUES(10,'matt');
+CREATE TABLE t2 (col1 int, col2 int, col3 char(1));
+INSERT INTO t2 VALUES (1,1,'y');
+INSERT INTO t2 VALUES (1,2,'y');
+INSERT INTO t2 VALUES (2,1,'n');
+INSERT INTO t2 VALUES (3,1,'n');
+INSERT INTO t2 VALUES (4,1,'y');
+INSERT INTO t2 VALUES (4,2,'n');
+INSERT INTO t2 VALUES (4,3,'n');
+INSERT INTO t2 VALUES (6,1,'n');
+INSERT INTO t2 VALUES (8,1,'y');
+
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+SELECT a.col1,a.col2,b.col2,b.col3
+ FROM t1 a LEFT JOIN t2 b ON a.col1=b.col1
+ WHERE b.col2 IS NULL OR
+ b.col2=(SELECT MAX(col2) FROM t2 b WHERE b.col1=a.col1);
+
+SELECT a.col1,a.col2,b.col2,b.col3
+ FROM v1 a LEFT JOIN t2 b ON a.col1=b.col1
+ WHERE b.col2 IS NULL OR
+ b.col2=(SELECT MAX(col2) FROM t2 b WHERE b.col1=a.col1);
+
+CREATE VIEW v2 AS SELECT * FROM t2;
+
+SELECT a.col1,a.col2,b.col2,b.col3
+ FROM v2 b RIGHT JOIN v1 a ON a.col1=b.col1
+ WHERE b.col2 IS NULL OR
+ b.col2=(SELECT MAX(col2) FROM v2 b WHERE b.col1=a.col1);
+
+# Tests from the report for bug #6107
+
+SELECT a.col1,a.col2,b.col2,b.col3
+ FROM v2 b RIGHT JOIN v1 a ON a.col1=b.col1
+ WHERE a.col1 IN (1,5,9) AND
+ (b.col2 IS NULL OR
+ b.col2=(SELECT MAX(col2) FROM v2 b WHERE b.col1=a.col1));
+
+CREATE VIEW v3 AS SELECT * FROM t1 WHERE col1 IN (1,5,9);
+
+SELECT a.col1,a.col2,b.col2,b.col3
+ FROM v2 b RIGHT JOIN v3 a ON a.col1=b.col1
+ WHERE b.col2 IS NULL OR
+ b.col2=(SELECT MAX(col2) FROM v2 b WHERE b.col1=a.col1);
+
+DROP VIEW v1,v2,v3;
+DROP TABLE t1,t2;
+
+#
+# BUG#8490 Select from views containing subqueries causes server to hang
+# forever.
+#
+create table t1 as select 1 A union select 2 union select 3;
+create table t2 as select * from t1;
+create view v1 as select * from t1 where a in (select * from t2);
+select * from v1 A, v1 B where A.a = B.a;
+create table t3 as select a a,a b from t2;
+create view v2 as select * from t3 where
+ a in (select * from t1) or b in (select * from t2);
+select * from v2 A, v2 B where A.a = B.b;
+drop view v1, v2;
+drop table t1, t2, t3;
+
+#
+# Test case for bug #8528: select from view over multi-table view
+#
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+INSERT INTO t2 VALUES (4), (2);
+
+CREATE VIEW v1 AS SELECT * FROM t1,t2 WHERE t1.a=t2.b;
+SELECT * FROM v1;
+CREATE VIEW v2 AS SELECT * FROM v1;
+SELECT * FROM v2;
+
+DROP VIEW v2,v1;
+
+DROP TABLE t1, t2;
+#
+# Correct restoring view name in SP table locking BUG#9758
+#
+create table t1 (a int);
+create view v1 as select sum(a) from t1 group by a;
+delimiter //;
+create procedure p1()
+begin
+select * from v1;
+end//
+delimiter ;//
+call p1();
+call p1();
+drop procedure p1;
+drop view v1;
+drop table t1;
+
+#
+# Bug#7422 "order by" doesn't work
+#
+CREATE TABLE t1(a char(2) primary key, b char(2));
+CREATE TABLE t2(a char(2), b char(2), index i(a));
+INSERT INTO t1 VALUES ('a','1'), ('b','2');
+INSERT INTO t2 VALUES ('a','5'), ('a','6'), ('b','5'), ('b','6');
+CREATE VIEW v1 AS
+ SELECT t1.b as c, t2.b as d FROM t1,t2 WHERE t1.a=t2.a;
+SELECT d, c FROM v1 ORDER BY d,c;
+DROP VIEW v1;
+DROP TABLE t1, t2;
+#
+# using sum(distinct ) & avg(distinct ) in views (BUG#7015)
+#
+create table t1 (s1 int);
+create view v1 as select sum(distinct s1) from t1;
+select * from v1;
+drop view v1;
+create view v1 as select avg(distinct s1) from t1;
+select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# using cast(... as decimal) in views (BUG#11387);
+#
+create view v1 as select cast(1 as decimal);
+select * from v1;
+drop view v1;
+
+#
+# Bug#11298 insert into select from VIEW produces incorrect result when
+# using ORDER BY
+create table t1(f1 int);
+create table t2(f2 int);
+insert into t1 values(1),(2),(3);
+insert into t2 values(1),(2),(3);
+create view v1 as select * from t1,t2 where f1=f2;
+create table t3 (f1 int, f2 int);
+insert into t3 select * from v1 order by 1;
+select * from t3;
+drop view v1;
+drop table t1,t2,t3;
+
+#
+# Generation unique names for columns, and correct names check (BUG#7448)
+#
+# names with ' and \
+create view v1 as select '\\','\\shazam';
+select * from v1;
+drop view v1;
+create view v1 as select '\'','\shazam';
+select * from v1;
+drop view v1;
+# autogenerated names differ by case only
+create view v1 as select 'k','K';
+select * from v1;
+drop view v1;
+create table t1 (s1 int);
+# same autogenerated names
+create view v1 as select s1, 's1' from t1;
+select * from v1;
+drop view v1;
+create view v1 as select 's1', s1 from t1;
+select * from v1;
+drop view v1;
+# set name as one of expected autogenerated
+create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
+select * from v1;
+drop view v1;
+create view v1 as select 1 as My_exp_s1, 's1', s1 from t1;
+select * from v1;
+drop view v1;
+# set name conflict with autogenerated names
+create view v1 as select 1 as s1, 's1', 's1' from t1;
+select * from v1;
+drop view v1;
+create view v1 as select 's1', 's1', 1 as s1 from t1;
+select * from v1;
+drop view v1;
+# underlying field name conflict with autogenerated names
+create view v1 as select s1, 's1', 's1' from t1;
+select * from v1;
+drop view v1;
+create view v1 as select 's1', 's1', s1 from t1;
+select * from v1;
+drop view v1;
+# underlying field name conflict with set name
+-- error 1060
+create view v1 as select 1 as s1, 's1', s1 from t1;
+-- error 1060
+create view v1 as select 's1', s1, 1 as s1 from t1;
+drop table t1;
+# set names differ by case only
+-- error 1060
+create view v1(k, K) as select 1,2;
+
+#
+# using time_format in view (BUG#7521)
+#
+create view v1 as SELECT TIME_FORMAT(SEC_TO_TIME(3600),'%H:%i') as t;
+select * from v1;
+drop view v1;
+
+#
+# evaluation constant functions in WHERE (BUG#4663)
+#
+create table t1 (a timestamp default now());
+create table t2 (b timestamp default now());
+create view v1 as select a,b,t1.a < now() from t1,t2 where t1.a < now();
+SHOW CREATE VIEW v1;
+drop view v1;
+drop table t1, t2;
+CREATE TABLE t1 ( a varchar(50) );
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE a = CURRENT_USER();
+SHOW CREATE VIEW v1;
+DROP VIEW v1;
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE a = VERSION();
+SHOW CREATE VIEW v1;
+DROP VIEW v1;
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE a = DATABASE();
+SHOW CREATE VIEW v1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# checking views after some view with error (BUG#11337)
+#
+CREATE TABLE t1 (col1 time);
+CREATE TABLE t2 (col1 time);
+CREATE VIEW v1 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1;
+CREATE VIEW v2 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2;
+CREATE VIEW v3 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1;
+CREATE VIEW v4 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2;
+CREATE VIEW v5 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1;
+CREATE VIEW v6 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2;
+DROP TABLE t1;
+CHECK TABLE v1, v2, v3, v4, v5, v6;
+drop view v1, v2, v3, v4, v5, v6;
+drop table t2;
+
+--disable_warnings
+drop function if exists f1;
+drop function if exists f2;
+--enable_warnings
+CREATE TABLE t1 (col1 time);
+CREATE TABLE t2 (col1 time);
+CREATE TABLE t3 (col1 time);
+create function f1 () returns int return (select max(col1) from t1);
+create function f2 () returns int return (select max(col1) from t2);
+CREATE VIEW v1 AS SELECT f1() FROM t3;
+CREATE VIEW v2 AS SELECT f2() FROM t3;
+CREATE VIEW v3 AS SELECT f1() FROM t3;
+CREATE VIEW v4 AS SELECT f2() FROM t3;
+CREATE VIEW v5 AS SELECT f1() FROM t3;
+CREATE VIEW v6 AS SELECT f2() FROM t3;
+drop function f1;
+CHECK TABLE v1, v2, v3, v4, v5, v6;
+create function f1 () returns int return (select max(col1) from t1);
+DROP TABLE t1;
+# following will show underlying table until BUG#11555 fix
+CHECK TABLE v1, v2, v3, v4, v5, v6;
+drop function f1;
+drop function f2;
+drop view v1, v2, v3, v4, v5, v6;
+drop table t2,t3;
+
+#
+# bug #11325 Wrong date comparison in views
+#
+create table t1 (f1 date);
+insert into t1 values ('2005-01-01'),('2005-02-02');
+create view v1 as select * from t1;
+select * from v1 where f1='2005.02.02';
+select * from v1 where '2005.02.02'=f1;
+drop view v1;
+drop table t1;
+
+#
+# using encrypt & substring_index in view (BUG#7024)
+#
+CREATE VIEW v1 AS SELECT ENCRYPT("dhgdhgd");
+disable_result_log;
+SELECT * FROM v1;
+enable_result_log;
+drop view v1;
+CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1);
+SELECT * FROM v1;
+drop view v1;
+
+#
+# hide underlying tables names in case of imposibility to update (BUG#10773)
+#
+create table t1 (f59 int, f60 int, f61 int);
+insert into t1 values (19,41,32);
+create view v1 as select f59, f60 from t1 where f59 in
+ (select f59 from t1);
+-- error 1288
+update v1 set f60=2345;
+-- error 1443
+update t1 set f60=(select max(f60) from v1);
+drop view v1;
+drop table t1;
+
+#
+# Using var_samp with view (BUG#10651)
+#
+create table t1 (s1 int);
+create view v1 as select var_samp(s1) from t1;
+show create view v1;
+drop view v1;
+drop table t1;
+
+#
+# Correct inserting data check (absence of default value) for view
+# underlying tables (BUG#6443)
+#
+set sql_mode='strict_all_tables';
+CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
+CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
+CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
+-- error 1364
+INSERT INTO t1 (col1) VALUES(12);
+-- error 1423
+INSERT INTO v1 (vcol1) VALUES(12);
+-- error 1423
+INSERT INTO v2 (vcol1) VALUES(12);
+set sql_mode=default;
+drop view v2,v1;
+drop table t1;
+
+#
+# Bug#11399 Use an alias in a select statement on a view
+#
+create table t1 (f1 int);
+insert into t1 values (1);
+create view v1 as select f1 from t1;
+select f1 as alias from v1;
+drop view v1;
+drop table t1;
+
+#
+# Test for bug #6120: SP cache to be invalidated when altering a view
+#
+
+CREATE TABLE t1 (s1 int, s2 int);
+INSERT INTO t1 VALUES (1,2);
+CREATE VIEW v1 AS SELECT s2 AS s1, s1 AS s2 FROM t1;
+SELECT * FROM v1;
+CREATE PROCEDURE p1 () SELECT * FROM v1;
+CALL p1();
+ALTER VIEW v1 AS SELECT s1 AS s1, s2 AS s2 FROM t1;
+CALL p1();
+DROP VIEW v1;
+CREATE VIEW v1 AS SELECT s2 AS s1, s1 AS s2 FROM t1;
+CALL p1();
+
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# Test for bug #11709 View was ordered by wrong column
+#
+create table t1 (f1 int, f2 int);
+create view v1 as select f1 as f3, f2 as f1 from t1;
+insert into t1 values (1,3),(2,1),(3,2);
+select * from v1 order by f1;
+drop view v1;
+drop table t1;
+
+#
+# Test for bug #11771: wrong query_id in SELECT * FROM <view>
+#
+CREATE TABLE t1 (f1 char) ENGINE = innodb;
+INSERT INTO t1 VALUES ('A');
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+INSERT INTO t1 VALUES('B');
+SELECT * FROM v1;
+SELECT * FROM t1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# opening table in correct locking mode (BUG#9597)
+#
+CREATE TABLE t1 ( bug_table_seq INTEGER NOT NULL);
+CREATE OR REPLACE VIEW v1 AS SELECT * from t1;
+DROP PROCEDURE IF EXISTS p1;
+delimiter //;
+CREATE PROCEDURE p1 ( )
+BEGIN
+ DO (SELECT @next := IFNULL(max(bug_table_seq),0) + 1 FROM v1);
+ INSERT INTO t1 VALUES (1);
+END //
+delimiter ;//
+CALL p1();
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# Bug #11335 View redefines column types
+#
+create table t1 (f1 tinyint(1), f2 char(1), f3 varchar(1), f4 geometry, f5 datetime);
+create view v1 as select * from t1;
+desc v1;
+drop view v1;
+drop table t1;
+
+#
+# Bug #11760 Typo in Item_func_add_time::print() results in NULLs returned
+# subtime() in view
+create table t1(f1 datetime);
+insert into t1 values('2005.01.01 12:0:0');
+create view v1 as select f1, subtime(f1, '1:1:1') as sb from t1;
+select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# Test for bug #11412: query over a multitable view with GROUP_CONCAT
+#
+CREATE TABLE t1 (
+ aid int PRIMARY KEY,
+ fn varchar(20) NOT NULL,
+ ln varchar(20) NOT NULL
+);
+CREATE TABLE t2 (
+ aid int NOT NULL,
+ pid int NOT NULL
+);
+INSERT INTO t1 VALUES(1,'a','b'), (2,'c','d');
+INSERT INTO t2 values (1,1), (2,1), (2,2);
+
+CREATE VIEW v1 AS SELECT t1.*,t2.pid FROM t1,t2 WHERE t1.aid = t2.aid;
+
+SELECT pid,GROUP_CONCAT(CONCAT(fn,' ',ln) ORDER BY 1) FROM t1,t2
+ WHERE t1.aid = t2.aid GROUP BY pid;
+SELECT pid,GROUP_CONCAT(CONCAT(fn,' ',ln) ORDER BY 1) FROM v1 GROUP BY pid;
+
+DROP VIEW v1;
+DROP TABLE t1,t2;
+
+#
+# Test for bug #12382: SELECT * FROM view after INSERT command
+#
+
+CREATE TABLE t1 (id int PRIMARY KEY, f varchar(255));
+CREATE VIEW v1 AS SELECT id, f FROM t1 WHERE id <= 2;
+INSERT INTO t1 VALUES (2, 'foo2');
+INSERT INTO t1 VALUES (1, 'foo1');
+
+SELECT * FROM v1;
+SELECT * FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+#
+# Test for bug #12470: crash for a simple select from a view defined
+# as a join over 5 tables
+
+CREATE TABLE t1 (pk int PRIMARY KEY, b int);
+CREATE TABLE t2 (pk int PRIMARY KEY, fk int, INDEX idx(fk));
+CREATE TABLE t3 (pk int PRIMARY KEY, fk int, INDEX idx(fk));
+CREATE TABLE t4 (pk int PRIMARY KEY, fk int, INDEX idx(fk));
+CREATE TABLE t5 (pk int PRIMARY KEY, fk int, INDEX idx(fk));
+CREATE VIEW v1 AS
+ SELECT t1.pk as a FROM t1,t2,t3,t4,t5
+ WHERE t1.b IS NULL AND
+ t1.pk=t2.fk AND t2.pk=t3.fk AND t3.pk=t4.fk AND t4.pk=t5.fk;
+
+SELECT a FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1,t2,t3,t4,t5;
+
+#
+# Bug #12298 Typo in function name results in erroneous view being created.
+#
+create view v1 as select timestampdiff(day,'1997-01-01 00:00:00','1997-01-02 00:00:00') as f1;
+select * from v1;
+drop view v1;
+
+#
+# repeatable CREATE VIEW statement BUG#12468
+#
+create table t1(a int);
+create procedure p1() create view v1 as select * from t1;
+drop table t1;
+-- error 1146
+call p1();
+-- error 1146
+call p1();
+drop procedure p1;
+
+#
+# Bug #10624 Views with multiple UNION and UNION ALL produce incorrect results
+#
+create table t1 (f1 int);
+create table t2 (f1 int);
+insert into t1 values (1);
+insert into t2 values (2);
+create view v1 as select * from t1 union select * from t2 union all select * from t2;
+select * from v1;
+drop view v1;
+drop table t1,t2;
+#
+# Test for bug #10970: view referring a temporary table indirectly
+#
+
+CREATE TEMPORARY TABLE t1 (a int);
+CREATE FUNCTION f1 () RETURNS int RETURN (SELECT COUNT(*) FROM t1);
+-- error 1352
+CREATE VIEW v1 AS SELECT f1();
+
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+#
+# BUG #12533 (crash on DESCRIBE <view> after renaming base table column)
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+--enable_warnings
+
+CREATE TABLE t1 (f4 CHAR(5));
+CREATE VIEW v1 AS SELECT * FROM t1;
+DESCRIBE v1;
+
+ALTER TABLE t1 CHANGE COLUMN f4 f4x CHAR(5);
+--error 1356
+DESCRIBE v1;
+DROP TABLE t1;
+DROP VIEW v1;
+
+#
+# Bug #12489 wrongly printed strcmp() function results in creation of broken
+# view
+create table t1 (f1 char);
+create view v1 as select strcmp(f1,'a') from t1;
+select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# Bug #12922 if(sum(),...) with group from view returns wrong results
+#
+create table t1 (f1 int, f2 int,f3 int);
+insert into t1 values (1,10,20),(2,0,0);
+create view v1 as select * from t1;
+select if(sum(f1)>1,f2,f3) from v1 group by f1;
+drop view v1;
+drop table t1;
+# BUG#12941
+#
+create table t1 (
+ r_object_id char(16) NOT NULL,
+ group_name varchar(32) NOT NULL
+) engine = InnoDB;
+
+create table t2 (
+ r_object_id char(16) NOT NULL,
+ i_position int(11) NOT NULL,
+ users_names varchar(32) default NULL
+) Engine = InnoDB;
+
+create view v1 as select r_object_id, group_name from t1;
+create view v2 as select r_object_id, i_position, users_names from t2;
+
+create unique index r_object_id on t1(r_object_id);
+create index group_name on t1(group_name);
+create unique index r_object_id_i_position on t2(r_object_id,i_position);
+create index users_names on t2(users_names);
+
+insert into t1 values('120001a080000542','tstgroup1');
+insert into t2 values('120001a080000542',-1, 'guser01');
+insert into t2 values('120001a080000542',-2, 'guser02');
+
+select v1.r_object_id, v2.users_names from v1, v2
+where (v1.group_name='tstgroup1') and v2.r_object_id=v1.r_object_id
+order by users_names;
+
+drop view v1, v2;
+drop table t1, t2;
+
+#
+# DEFINER information check
+#
+-- error ER_NO_VIEW_USER
+create definer=some_user@__% sql security invoker view v1 as select 1;
+create definer=some_user@localhost sql security invoker view v1 as select 1;
+show create view v1;
+drop view v1;
+
+#
+# Bug #6808 - Views: CREATE VIEW v ... FROM t AS v fails
+#
+
+create table t1 (s1 int);
+create view abc as select * from t1 as abc;
+drop table t1;
+drop view abc;
+
+#
+# Bug #12993 View column rename broken in subselect
+#
+create table t1(f1 char(1));
+create view v1 as select * from t1;
+select * from (select f1 as f2 from v1) v where v.f2='a';
+drop view v1;
+drop table t1;
+
+#
+# Bug #11416 Server crash if using a view that uses function convert_tz
+#
+create view v1 as SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
+select * from v1;
+drop view v1;
+
+#
+# Bugs #12963, #13000: wrong creation of VIEW with DAYNAME, DAYOFWEEK, and WEEKDAY
+#
+
+CREATE TABLE t1 (date DATE NOT NULL);
+INSERT INTO t1 VALUES ('2005-09-06');
+
+CREATE VIEW v1 AS SELECT DAYNAME(date) FROM t1;
+SHOW CREATE VIEW v1;
+
+CREATE VIEW v2 AS SELECT DAYOFWEEK(date) FROM t1;
+SHOW CREATE VIEW v2;
+
+CREATE VIEW v3 AS SELECT WEEKDAY(date) FROM t1;
+SHOW CREATE VIEW v3;
+
+SELECT DAYNAME('2005-09-06');
+SELECT DAYNAME(date) FROM t1;
+SELECT * FROM v1;
+
+SELECT DAYOFWEEK('2005-09-06');
+SELECT DAYOFWEEK(date) FROM t1;
+SELECT * FROM v2;
+
+SELECT WEEKDAY('2005-09-06');
+SELECT WEEKDAY(date) FROM t1;
+SELECT * FROM v3;
+
+DROP TABLE t1;
+DROP VIEW v1, v2, v3;
diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test
new file mode 100644
index 00000000000..ea93345e894
--- /dev/null
+++ b/mysql-test/t/view_grant.test
@@ -0,0 +1,408 @@
+# Can't test with embedded server
+-- source include/not_embedded.inc
+
+# simple test of grants
+grant create view on test.* to test@localhost;
+show grants for test@localhost;
+revoke create view on test.* from test@localhost;
+show grants for test@localhost;
+
+# grant create view test
+#
+connect (root,localhost,root,,test);
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+create table mysqltest.t1 (a int, b int);
+create table mysqltest.t2 (a int, b int);
+
+grant select on mysqltest.t1 to mysqltest_1@localhost;
+grant create view,select on test.* to mysqltest_1@localhost;
+
+connect (user1,localhost,mysqltest_1,,test);
+connection user1;
+
+-- error ER_VIEW_OTHER_USER
+create definer=root@localhost view v1 as select * from mysqltest.t1;
+create view v1 as select * from mysqltest.t1;
+# try to modify view without DROP privilege on it
+-- error 1142
+alter view v1 as select * from mysqltest.t1;
+-- error 1142
+create or replace view v1 as select * from mysqltest.t1;
+# no CRETE VIEW privilege
+-- error 1142
+create view mysqltest.v2 as select * from mysqltest.t1;
+# no SELECT privilege
+-- error 1142
+create view v2 as select * from mysqltest.t2;
+
+connection root;
+# check view definer information
+show create view v1;
+
+grant create view,drop,select on test.* to mysqltest_1@localhost;
+
+connection user1;
+# following 'use' command is workaround of bug #9582 and should be removed
+# when that bug will be fixed
+use test;
+alter view v1 as select * from mysqltest.t1;
+create or replace view v1 as select * from mysqltest.t1;
+
+connection root;
+revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
+revoke all privileges on test.* from mysqltest_1@localhost;
+
+drop database mysqltest;
+drop view test.v1;
+
+#
+# grants per columns
+#
+# MERGE algorithm
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+create table mysqltest.t1 (a int, b int);
+create view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1;
+grant select (c) on mysqltest.v1 to mysqltest_1@localhost;
+
+connection user1;
+select c from mysqltest.v1;
+# there are no privileges on column 'd'
+-- error 1143
+select d from mysqltest.v1;
+
+connection root;
+revoke all privileges on mysqltest.v1 from mysqltest_1@localhost;
+delete from mysql.user where user='mysqltest_1';
+drop database mysqltest;
+
+# TEMPORARY TABLE algorithm
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+create table mysqltest.t1 (a int, b int);
+create algorithm=temptable view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1;
+grant select (c) on mysqltest.v1 to mysqltest_1@localhost;
+
+connection user1;
+select c from mysqltest.v1;
+# there are no privileges on column 'd'
+-- error 1143
+select d from mysqltest.v1;
+
+connection root;
+revoke all privileges on mysqltest.v1 from mysqltest_1@localhost;
+delete from mysql.user where user='mysqltest_1';
+drop database mysqltest;
+
+#
+# EXPLAIN rights
+#
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+#prepare views and tables
+create table mysqltest.t1 (a int, b int);
+create table mysqltest.t2 (a int, b int);
+create view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1;
+create algorithm=temptable view mysqltest.v2 (c,d) as select a+1,b+1 from mysqltest.t1;
+create view mysqltest.v3 (c,d) as select a+1,b+1 from mysqltest.t2;
+create algorithm=temptable view mysqltest.v4 (c,d) as select a+1,b+1 from mysqltest.t2;
+grant select on mysqltest.v1 to mysqltest_1@localhost;
+grant select on mysqltest.v2 to mysqltest_1@localhost;
+grant select on mysqltest.v3 to mysqltest_1@localhost;
+grant select on mysqltest.v4 to mysqltest_1@localhost;
+
+connection user1;
+# all selects works
+select c from mysqltest.v1;
+select c from mysqltest.v2;
+select c from mysqltest.v3;
+select c from mysqltest.v4;
+# test of show coluns
+show columns from mysqltest.v1;
+show columns from mysqltest.v2;
+# but explain/show do not
+-- error 1345
+explain select c from mysqltest.v1;
+-- error 1142
+show create view mysqltest.v1;
+-- error 1345
+explain select c from mysqltest.v2;
+-- error 1142
+show create view mysqltest.v2;
+-- error 1345
+explain select c from mysqltest.v3;
+-- error 1142
+show create view mysqltest.v3;
+-- error 1345
+explain select c from mysqltest.v4;
+-- error 1142
+show create view mysqltest.v4;
+
+# allow to see one of underlying table
+connection root;
+grant select on mysqltest.t1 to mysqltest_1@localhost;
+connection user1;
+# EXPLAIN of view on above table works
+explain select c from mysqltest.v1;
+-- error 1142
+show create view mysqltest.v1;
+explain select c from mysqltest.v2;
+-- error 1142
+show create view mysqltest.v2;
+# but other EXPLAINs do not
+-- error 1345
+explain select c from mysqltest.v3;
+-- error 1142
+show create view mysqltest.v3;
+-- error 1345
+explain select c from mysqltest.v4;
+-- error 1142
+show create view mysqltest.v4;
+
+# allow to see any view in mysqltest database
+connection root;
+grant show view on mysqltest.* to mysqltest_1@localhost;
+connection user1;
+explain select c from mysqltest.v1;
+show create view mysqltest.v1;
+explain select c from mysqltest.v2;
+show create view mysqltest.v2;
+explain select c from mysqltest.v3;
+show create view mysqltest.v3;
+explain select c from mysqltest.v4;
+show create view mysqltest.v4;
+
+connection root;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+delete from mysql.user where user='mysqltest_1';
+drop database mysqltest;
+
+#
+# UPDATE privileges on VIEW columns and whole VIEW
+#
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+create table mysqltest.t1 (a int, b int, primary key(a));
+insert into mysqltest.t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
+create table mysqltest.t2 (x int);
+insert into mysqltest.t2 values (3), (4), (5), (6);
+create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1;
+create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1;
+create view mysqltest.v3 (a,c) as select a, b+1 from mysqltest.t1;
+
+grant update (a) on mysqltest.v2 to mysqltest_1@localhost;
+grant update on mysqltest.v1 to mysqltest_1@localhost;
+grant select on mysqltest.* to mysqltest_1@localhost;
+
+connection user1;
+use mysqltest;
+# update with rights on VIEW column
+update t2,v1 set v1.a=v1.a+v1.c where t2.x=v1.c;
+select * from t1;
+update v1 set a=a+c;
+select * from t1;
+# update with rights on whole VIEW
+update t2,v2 set v2.a=v2.a+v2.c where t2.x=v2.c;
+select * from t1;
+update v2 set a=a+c;
+select * from t1;
+# no rights on column
+-- error 1143
+update t2,v2 set v2.c=v2.a+v2.c where t2.x=v2.c;
+-- error 1143
+update v2 set c=a+c;
+# no rights for view
+-- error 1142
+update t2,v3 set v3.a=v3.a+v3.c where t2.x=v3.c;
+-- error 1142
+update v3 set a=a+c;
+
+use test;
+connection root;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
+drop database mysqltest;
+
+#
+# DELETE privileges on VIEW
+#
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+create table mysqltest.t1 (a int, b int, primary key(a));
+insert into mysqltest.t1 values (1,2), (2,3), (3,4), (4,5), (5,10);
+create table mysqltest.t2 (x int);
+insert into mysqltest.t2 values (3), (4), (5), (6);
+create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1;
+create view mysqltest.v2 (a,c) as select a, b+1 from mysqltest.t1;
+
+grant delete on mysqltest.v1 to mysqltest_1@localhost;
+grant select on mysqltest.* to mysqltest_1@localhost;
+
+connection user1;
+use mysqltest;
+# update with rights on VIEW column
+delete from v1 where c < 4;
+select * from t1;
+delete v1 from t2,v1 where t2.x=v1.c;
+select * from t1;
+# no rights for view
+-- error 1142
+delete v2 from t2,v2 where t2.x=v2.c;
+-- error 1142
+delete from v2 where c < 4;
+
+use test;
+connection root;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
+drop database mysqltest;
+
+#
+# insert privileges on VIEW
+#
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+create table mysqltest.t1 (a int, b int, primary key(a));
+insert into mysqltest.t1 values (1,2), (2,3);
+create table mysqltest.t2 (x int, y int);
+insert into mysqltest.t2 values (3,4);
+create view mysqltest.v1 (a,c) as select a, b from mysqltest.t1;
+create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1;
+
+grant insert on mysqltest.v1 to mysqltest_1@localhost;
+grant select on mysqltest.* to mysqltest_1@localhost;
+
+connection user1;
+use mysqltest;
+# update with rights on VIEW column
+insert into v1 values (5,6);
+select * from t1;
+insert into v1 select x,y from t2;
+select * from t1;
+# no rights for view
+-- error 1142
+insert into v2 values (5,6);
+-- error 1142
+insert into v2 select x,y from t2;
+
+use test;
+connection root;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
+drop database mysqltest;
+
+#
+# test of CREATE VIEW privileges if we have limited privileges
+#
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+create table mysqltest.t1 (a int, b int);
+create table mysqltest.t2 (a int, b int);
+
+grant update on mysqltest.t1 to mysqltest_1@localhost;
+grant update(b) on mysqltest.t2 to mysqltest_1@localhost;
+grant create view,update on test.* to mysqltest_1@localhost;
+
+connection user1;
+
+create view v1 as select * from mysqltest.t1;
+create view v2 as select b from mysqltest.t2;
+# There are not rights on mysqltest.v1
+-- error 1142
+create view mysqltest.v1 as select * from mysqltest.t1;
+# There are not any rights on mysqltest.t2.a
+-- error 1143
+create view v3 as select a from mysqltest.t2;
+
+# give CREATE VIEW privileges (without any privileges for result column)
+connection root;
+create table mysqltest.v3 (b int);
+grant create view on mysqltest.v3 to mysqltest_1@localhost;
+drop table mysqltest.v3;
+connection user1;
+create view mysqltest.v3 as select b from mysqltest.t2;
+
+# give UPDATE privileges
+connection root;
+grant create view, update on mysqltest.v3 to mysqltest_1@localhost;
+drop view mysqltest.v3;
+connection user1;
+create view mysqltest.v3 as select b from mysqltest.t2;
+
+# give UPDATE and INSERT privilege (to get more privileges then underlying
+# table)
+connection root;
+grant create view, update, insert on mysqltest.v3 to mysqltest_1@localhost;
+drop view mysqltest.v3;
+connection user1;
+-- error 1143
+create view mysqltest.v3 as select b from mysqltest.t2;
+
+
+# If we would get more privileges on VIEW then we have on
+# underlying tables => creation prohibited
+connection root;
+create table mysqltest.v3 (b int);
+grant select(b) on mysqltest.v3 to mysqltest_1@localhost;
+drop table mysqltest.v3;
+connection user1;
+-- error 1143
+create view mysqltest.v3 as select b from mysqltest.t2;
+
+# Expression need select privileges
+-- error 1143
+create view v4 as select b+1 from mysqltest.t2;
+
+connection root;
+grant create view,update,select on test.* to mysqltest_1@localhost;
+connection user1;
+-- error 1143
+create view v4 as select b+1 from mysqltest.t2;
+
+connection root;
+grant update,select(b) on mysqltest.t2 to mysqltest_1@localhost;
+connection user1;
+create view v4 as select b+1 from mysqltest.t2;
+
+connection root;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
+drop database mysqltest;
+drop view v1,v2,v4;
+
+#
+# user with global DB privileges
+#
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+create table mysqltest.t1 (a int);
+grant all privileges on mysqltest.* to mysqltest_1@localhost;
+
+connection user1;
+use mysqltest;
+create view v1 as select * from t1;
+
+connection root;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+drop database mysqltest;
+
diff --git a/mysql-test/t/view_query_cache.test b/mysql-test/t/view_query_cache.test
new file mode 100644
index 00000000000..bca111a5ed1
--- /dev/null
+++ b/mysql-test/t/view_query_cache.test
@@ -0,0 +1,87 @@
+-- source include/have_query_cache.inc
+#
+# QUERY CACHE options for VIEWs
+#
+--disable_warnings
+drop table if exists t1,t2,v1,v2,v3;
+drop view if exists t1,t2,v1,v2,v3;
+--enable_warnings
+
+set GLOBAL query_cache_size=1355776;
+flush status;
+create table t1 (a int, b int);
+
+# queries with following views should not be in query cache
+create view v1 (c,d) as select sql_no_cache a,b from t1;
+create view v2 (c,d) as select a+rand(),b from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from v1;
+select * from v2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from v1;
+select * from v2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop view v1,v2;
+
+# SQL_CACHE option
+set query_cache_type=demand;
+flush status;
+# query with view will be cached, but direct acess to table will not
+create view v1 (c,d) as select sql_cache a,b from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from v1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from v1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+drop view v1;
+set query_cache_type=default;
+
+drop table t1;
+
+#
+# invalidation of view
+#
+create table t1 (a int);
+insert into t1 values (1), (2), (3);
+create view v1 as select a from t1 where a > 1;
+select * from v1;
+alter view v1 as select a from t1 where a > 2;
+select * from v1;
+drop view v1;
+-- error 1146
+select * from v1;
+drop table t1;
+
+#
+# join view with QC
+#
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a), b int);
+insert into t2 values (1000, 2000);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+select * from v3;
+drop view v3;
+drop table t1, t2;
+
+set GLOBAL query_cache_size=default;
diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test
index 4bc8a338a35..f6ae7cdaf30 100644
--- a/mysql-test/t/warnings.test
+++ b/mysql-test/t/warnings.test
@@ -39,9 +39,8 @@ show warnings limit 1;
drop database if exists not_exists_db;
show count(*) warnings;
create table t1(id int);
-# PS doesn't give warnings on prepare
---disable_ps_protocol
create table if not exists t1(id int);
+--disable_ps_protocol
select @@warning_count;
--enable_ps_protocol
drop table t1;
@@ -122,12 +121,9 @@ drop table t1;
# Test for deprecated TYPE= syntax
#
-# PS doesn't give warnings on prepare
---disable_ps_protocol
create table t1 (id int) type=heap;
alter table t1 type=myisam;
drop table t1;
---enable_ps_protocol
#
# Test for deprecated table_type variable
diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test
new file mode 100644
index 00000000000..1347fd05415
--- /dev/null
+++ b/mysql-test/t/xa.test
@@ -0,0 +1,62 @@
+#
+# WL#1756
+#
+-- source include/have_innodb.inc
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1 (a int) engine=innodb;
+xa start 'test1';
+insert t1 values (10);
+xa end 'test1';
+xa prepare 'test1';
+xa rollback 'test1';
+select * from t1;
+
+xa start 'test2';
+--error 1399
+xa start 'test-bad';
+insert t1 values (20);
+--error 1399
+xa prepare 'test2';
+xa end 'test2';
+xa prepare 'test2';
+xa commit 'test2';
+select * from t1;
+
+xa start 'testa','testb';
+insert t1 values (30);
+xa end 'testa','testb';
+
+connect (con1,localhost,,,);
+connection con1;
+
+--error 1440
+xa start 'testa','testb';
+
+# gtrid [ , bqual [ , formatID ] ]
+xa start 0x7465737462, 0x2030405060, 0xb;
+insert t1 values (40);
+xa end 'testb',' 0@P`',11;
+xa prepare 'testb',0x2030405060,11;
+
+xa recover;
+
+# uncomment the line below when binlog will be able to prepare
+#disconnect con1;
+connection default;
+
+xa prepare 'testa','testb';
+
+xa recover;
+
+--error 1397
+xa commit 'testb',0x2030405060,11;
+xa rollback 'testa','testb';
+
+--error 1064
+xa start 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
+
+select * from t1;
+drop table t1;
+
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
new file mode 100644
index 00000000000..26f3477140b
--- /dev/null
+++ b/mysql-test/valgrind.supp
@@ -0,0 +1,134 @@
+#
+# Suppress some common (not fatal) errors in system libraries found by valgrind
+#
+
+#
+# Pthread doesn't free all thread specific memory before program exists
+#
+{
+ pthread allocate_tls memory loss
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ fun:allocate_stack
+ fun:pthread_create@@GLIBC_2.1
+}
+
+{
+ pthread allocate_dtv memory loss
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls_storage
+ fun:__GI__dl_allocate_tls
+ fun:pthread_create
+}
+
+{
+ pthread allocate_dtv memory loss second
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls
+ fun:pthread_create*
+}
+
+{
+ pthread allocate_dtv memory loss second
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls
+ fun:pthread_create*
+}
+
+{
+ pthread memalign memory loss
+ Memcheck:Leak
+ fun:memalign
+ fun:_dl_allocate_tls_storage
+ fun:__GI__dl_allocate_tls
+ fun:pthread_create
+}
+
+{
+ pthread strstr uninit
+ Memcheck:Cond
+ fun:strstr
+ obj:/lib/tls/libpthread.so.*
+ obj:/lib/tls/libpthread.so.*
+ fun:call_init
+ fun:_dl_init
+ obj:/lib/ld-*.so
+}
+
+{
+ pthread strstr uninit
+ Memcheck:Cond
+ fun:strstr
+ obj:/lib/tls/libpthread.so.*
+ obj:/lib/tls/libpthread.so.*
+ fun:call_init
+ fun:_dl_init
+ obj:/lib/ld-*.so
+}
+
+{
+ pthread errno
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ fun:dlsym
+ fun:__errno_location
+}
+
+
+#
+# Warnings in libz becasue it works with aligned memory(?)
+#
+
+{
+ libz tr_flush_block
+ Memcheck:Cond
+ fun:_tr_flush_block
+ fun:deflate_slow
+ fun:deflate
+ fun:do_flush
+ fun:gzclose
+}
+
+{
+ libz tr_flush_block2
+ Memcheck:Cond
+ fun:_tr_flush_block
+ fun:deflate_slow
+ fun:deflate
+ fun:compress2
+}
+
+{
+ libz longest_match
+ Memcheck:Cond
+ fun:longest_match
+ fun:deflate_slow
+ fun:deflate
+ fun:do_flush
+}
+
+{
+ libz longest_match2
+ Memcheck:Cond
+ fun:longest_match
+ fun:deflate_slow
+ fun:deflate
+ fun:compress2
+}
+
+{
+ libz deflate
+ Memcheck:Cond
+ obj:/usr/lib/libz.so.*
+ obj:/usr/lib/libz.so.*
+ fun:deflate
+ fun:compress2
+}
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index a80df810c1c..9c58c18cf59 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -17,8 +17,7 @@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
-INCLUDES = @MT_INCLUDES@ \
- @ZLIB_INCLUDES@ -I$(top_builddir)/include \
+INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \
-I$(top_srcdir)/include -I$(srcdir)
pkglib_LIBRARIES = libmysys.a
LDADD = libmysys.a ../dbug/libdbug.a \
@@ -27,7 +26,7 @@ noinst_HEADERS = mysys_priv.h my_static.h \
my_os2cond.c my_os2dirsrch.c my_os2dirsrch.h \
my_os2dlfcn.c my_os2file64.c my_os2mutex.c \
my_os2thread.c my_os2tls.c
-libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
+libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
mf_path.c mf_loadpath.c my_file.c \
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c \
@@ -46,19 +45,20 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
ptr_cmp.c mf_radix.c queues.c \
tree.c list.c hash.c array.c string.c typelib.c \
my_copy.c my_append.c my_lib.c \
- my_delete.c my_rename.c my_redel.c my_tempnam.c \
+ my_delete.c my_rename.c my_redel.c \
my_chsize.c my_lread.c my_lwrite.c my_clock.c \
my_quick.c my_lockmem.c my_static.c \
my_sync.c my_getopt.c my_mkdir.c \
- default.c my_compress.c checksum.c raid.cc \
+ default_modify.c default.c \
+ my_compress.c checksum.c raid.cc \
my_net.c my_semaphore.c my_port.c my_sleep.c \
charset.c charset-def.c my_bitmap.c my_bit.c md5.c \
my_gethostbyname.c rijndael.c my_aes.c sha1.c \
- my_handler.c my_netware.c my_windac.c my_access.c
+ my_handler.c my_netware.c my_largepage.c \
+ my_windac.c my_access.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
-noinst_PROGRAMS = charset2html @THREAD_LPROGRAMS@
# test_dir_DEPENDENCIES= $(LIBRARIES)
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
@@ -68,6 +68,8 @@ DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
+ -DDEFAULT_HOME_ENV=MYSQL_HOME \
+ -DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
@DEFS@
libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@
@@ -106,9 +108,6 @@ test_dir$(EXEEXT): test_dir.c $(LIBRARIES)
test_charset$(EXEEXT): test_charset.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS)
-charset2html$(EXEEXT): charset2html.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $(srcdir)/charset2html.c $(LDADD) $(LIBS)
-
testhash$(EXEEXT): testhash.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS)
diff --git a/mysys/charset-def.c b/mysys/charset-def.c
index 1fa87b715a8..5b30d1ee135 100644
--- a/mysys/charset-def.c
+++ b/mysys/charset-def.c
@@ -42,6 +42,7 @@ extern CHARSET_INFO my_charset_ucs2_slovak_uca_ci;
extern CHARSET_INFO my_charset_ucs2_spanish2_uca_ci;
extern CHARSET_INFO my_charset_ucs2_roman_uca_ci;
extern CHARSET_INFO my_charset_ucs2_persian_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_esperanto_uca_ci;
#endif
#ifdef HAVE_CHARSET_utf8
@@ -62,6 +63,7 @@ extern CHARSET_INFO my_charset_utf8_slovak_uca_ci;
extern CHARSET_INFO my_charset_utf8_spanish2_uca_ci;
extern CHARSET_INFO my_charset_utf8_roman_uca_ci;
extern CHARSET_INFO my_charset_utf8_persian_uca_ci;
+extern CHARSET_INFO my_charset_utf8_esperanto_uca_ci;
#ifdef HAVE_UTF8_GENERAL_CS
extern CHARSET_INFO my_charset_utf8_general_cs;
#endif
@@ -97,6 +99,11 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
add_compiled_collation(&my_charset_latin2_czech_ci);
#endif
+#ifdef HAVE_CHARSET_eucjpms
+ add_compiled_collation(&my_charset_eucjpms_japanese_ci);
+ add_compiled_collation(&my_charset_eucjpms_bin);
+#endif
+
#ifdef HAVE_CHARSET_euckr
add_compiled_collation(&my_charset_euckr_korean_ci);
add_compiled_collation(&my_charset_euckr_bin);
@@ -143,6 +150,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
add_compiled_collation(&my_charset_ucs2_spanish2_uca_ci);
add_compiled_collation(&my_charset_ucs2_roman_uca_ci);
add_compiled_collation(&my_charset_ucs2_persian_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci);
#endif
#endif
@@ -175,6 +183,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
add_compiled_collation(&my_charset_utf8_spanish2_uca_ci);
add_compiled_collation(&my_charset_utf8_roman_uca_ci);
add_compiled_collation(&my_charset_utf8_persian_uca_ci);
+ add_compiled_collation(&my_charset_utf8_esperanto_uca_ci);
#endif
#endif
diff --git a/mysys/charset.c b/mysys/charset.c
index 3a39fce9437..e61d08cbc33 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -97,7 +97,7 @@ static my_bool init_state_maps(CHARSET_INFO *cs)
/* Special handling of hex and binary strings */
state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) MY_LEX_IDENT_OR_HEX;
- state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) MY_LEX_IDENT_OR_BIN;
+ state_map[(uchar)'b']= state_map[(uchar)'B']= (uchar) MY_LEX_IDENT_OR_BIN;
state_map[(uchar)'n']= state_map[(uchar)'N']= (uchar) MY_LEX_IDENT_OR_NCHAR;
return 0;
}
@@ -549,10 +549,10 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_PRINT("enter",("name: '%s'", cs_name));
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
-
+
cs_number= get_charset_number(cs_name, cs_flags);
cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
-
+
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN];
@@ -564,21 +564,54 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
}
-ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
+/*
+ Escape string with backslashes (\)
+
+ SYNOPSIS
+ escape_string_for_mysql()
+ charset_info Charset of the strings
+ to Buffer for escaped string
+ to_length Length of destination buffer, or 0
+ from The string to escape
+ length The length of the string to escape
+
+ DESCRIPTION
+ This escapes the contents of a string by adding backslashes before special
+ characters, and turning others into specific escape sequences, such as
+ turning newlines into \n and null bytes into \0.
+
+ NOTE
+ To maintain compatibility with the old C API, to_length may be 0 to mean
+ "big enough"
+
+ RETURN VALUES
+ ~0 The escaped string did not fit in the to buffer
+ >=0 The length of the escaped string
+*/
+
+ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
const char *from, ulong length)
{
const char *to_start= to;
- const char *end;
+ const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
+ my_bool overflow= FALSE;
#ifdef USE_MB
my_bool use_mb_flag= use_mb(charset_info);
#endif
- for (end= from + length; from != end; from++)
+ for (end= from + length; from < end; from++)
{
+ char escape= 0;
#ifdef USE_MB
- int l;
- if (use_mb_flag && (l= my_ismbchar(charset_info, from, end)))
+ int tmp_length;
+ if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
{
- while (l--)
+ if (to + tmp_length > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ while (tmp_length--)
*to++= *from++;
from--;
continue;
@@ -594,48 +627,55 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
multi-byte character into a valid one. For example, 0xbf27 is not
a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \)
*/
- if (use_mb_flag && (l= my_mbcharlen(charset_info, *from)) > 1)
- {
- *to++= '\\';
- *to++= *from;
- continue;
- }
+ if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1)
+ escape= *from;
+ else
#endif
switch (*from) {
case 0: /* Must be escaped for 'mysql' */
- *to++= '\\';
- *to++= '0';
+ escape= '0';
break;
case '\n': /* Must be escaped for logs */
- *to++= '\\';
- *to++= 'n';
+ escape= 'n';
break;
case '\r':
- *to++= '\\';
- *to++= 'r';
+ escape= 'r';
break;
case '\\':
- *to++= '\\';
- *to++= '\\';
+ escape= '\\';
break;
case '\'':
- *to++= '\\';
- *to++= '\'';
+ escape= '\'';
break;
case '"': /* Better safe than sorry */
- *to++= '\\';
- *to++= '"';
+ escape= '"';
break;
case '\032': /* This gives problems on Win32 */
- *to++= '\\';
- *to++= 'Z';
+ escape= 'Z';
break;
- default:
+ }
+ if (escape)
+ {
+ if (to + 2 > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ *to++= '\\';
+ *to++= escape;
+ }
+ else
+ {
+ if (to + 1 > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
*to++= *from;
}
}
*to= 0;
- return (ulong) (to - to_start);
+ return overflow ? (ulong)~0 : (ulong) (to - to_start);
}
@@ -663,3 +703,84 @@ CHARSET_INFO *fs_character_set()
return fs_cset_cache;
}
#endif
+
+/*
+ Escape apostrophes by doubling them up
+
+ SYNOPSIS
+ escape_quotes_for_mysql()
+ charset_info Charset of the strings
+ to Buffer for escaped string
+ to_length Length of destination buffer, or 0
+ from The string to escape
+ length The length of the string to escape
+
+ DESCRIPTION
+ This escapes the contents of a string by doubling up any apostrophes that
+ it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
+ effect on the server.
+
+ NOTE
+ To be consistent with escape_string_for_mysql(), to_length may be 0 to
+ mean "big enough"
+
+ RETURN VALUES
+ ~0 The escaped string did not fit in the to buffer
+ >=0 The length of the escaped string
+*/
+
+ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
+ const char *from, ulong length)
+{
+ const char *to_start= to;
+ const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
+ my_bool overflow= FALSE;
+#ifdef USE_MB
+ my_bool use_mb_flag= use_mb(charset_info);
+#endif
+ for (end= from + length; from < end; from++)
+ {
+#ifdef USE_MB
+ int tmp_length;
+ if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
+ {
+ if (to + tmp_length > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ while (tmp_length--)
+ *to++= *from++;
+ from--;
+ continue;
+ }
+ /*
+ We don't have the same issue here with a non-multi-byte character being
+ turned into a multi-byte character by the addition of an escaping
+ character, because we are only escaping the ' character with itself.
+ */
+#endif
+ if (*from == '\'')
+ {
+ if (to + 2 > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ *to++= '\'';
+ *to++= '\'';
+ }
+ else
+ {
+ if (to + 1 > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ *to++= *from;
+ }
+ }
+ *to= 0;
+ return overflow ? (ulong)~0 : (ulong) (to - to_start);
+}
diff --git a/mysys/default.c b/mysys/default.c
index 9510cfb3464..bca3ec0fed3 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -30,81 +30,297 @@
--no-defaults ; no options are read.
--defaults-file=full-path-to-default-file ; Only this file will be read.
--defaults-extra-file=full-path-to-default-file ; Read this file before ~/
- --print-defaults ; Print the modified command line and exit
+ --defaults-group-suffix ; Also read groups with concat(group, suffix)
+ --print-defaults ; Print the modified command line and exit
****************************************************************************/
#include "mysys_priv.h"
#include "m_string.h"
#include "m_ctype.h"
#include <my_dir.h>
+#ifdef __WIN__
+#include <winbase.h>
+#endif
+const char *defaults_group_suffix=0;
char *defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
-const char *default_directories[]= {
-#ifdef __WIN__
-"C:/",
-#elif defined(__NETWARE__)
-"sys:/etc/",
-#else
-"/etc/",
-#endif
-#ifdef DATADIR
-DATADIR,
-#endif
-"", /* Place for defaults_extra_dir */
-#if !defined(__WIN__) && !defined(__NETWARE__)
-"~/",
-#endif
-NullS,
-};
+#define MAX_DEFAULT_DIRS 6
+const char *default_directories[MAX_DEFAULT_DIRS + 1];
#ifdef __WIN__
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
+#define NEWLINE "\r\n"
+static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN],
+ config_dir[FN_REFLEN];
#else
static const char *f_extensions[]= { ".cnf", 0 };
+#define NEWLINE "\n"
#endif
-static int search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
- const char *dir, const char *config_file,
- TYPELIB *group);
+static int handle_default_option(void *in_ctx, const char *group_name,
+ const char *option);
+
+/*
+ This structure defines the context that we pass to callback
+ function 'handle_default_option' used in search_default_file
+ to process each option. This context is used if search_default_file
+ was called from load_defaults.
+*/
+
+struct handle_option_ctx
+{
+ MEM_ROOT *alloc;
+ DYNAMIC_ARRAY *args;
+ TYPELIB *group;
+};
-static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
+static int search_default_file(Process_option_func func, void *func_ctx,
+ const char *dir, const char *config_file);
+static int search_default_file_with_ext(Process_option_func func,
+ void *func_ctx,
const char *dir, const char *ext,
- const char *config_file,
- TYPELIB *group, int recursion_level);
+ const char *config_file, int recursion_level);
+static void init_default_directories();
static char *remove_end_comment(char *ptr);
/*
- Gets --defaults-file and --defaults-extra-file options from command line.
+ Process config files in default directories.
+
+ SYNOPSIS
+ my_search_option_files()
+ conf_file Basename for configuration file to search for.
+ If this is a path, then only this file is read.
+ argc Pointer to argc of original program
+ argv Pointer to argv of original program
+ args_used Pointer to variable for storing the number of
+ arguments used.
+ func Pointer to the function to process options
+ func_ctx It's context. Usually it is the structure to
+ store additional options.
+ DESCRIPTION
+ Process the default options from argc & argv
+ Read through each found config file looks and calls 'func' to process
+ each option.
+
+ NOTES
+ --defaults-group-suffix is only processed if we are called from
+ load_defaults().
+
+
+ RETURN
+ 0 ok
+ 1 given cinf_file doesn't exist
+
+ The global variable 'defaults_group_suffix' is updated with value for
+ --defaults_group_suffix
+*/
+
+int my_search_option_files(const char *conf_file, int *argc, char ***argv,
+ uint *args_used, Process_option_func func,
+ void *func_ctx)
+{
+ const char **dirs, *forced_default_file, *forced_extra_defaults;
+ int error= 0;
+ DBUG_ENTER("my_search_option_files");
+
+ /* Check if we want to force the use a specific default file */
+ *args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used,
+ (char **) &forced_default_file,
+ (char **) &forced_extra_defaults,
+ (char **) &defaults_group_suffix);
+
+ if (! defaults_group_suffix)
+ defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
+
+ if (forced_extra_defaults)
+ defaults_extra_file= forced_extra_defaults;
+
+ /*
+ We can only handle 'defaults-group-suffix' if we are called from
+ load_defaults() as otherwise we can't know the type of 'func_ctx'
+ */
+
+ if (defaults_group_suffix && func == handle_default_option)
+ {
+ /* Handle --defaults-group-suffix= */
+ uint i;
+ const char **extra_groups;
+ const uint instance_len= strlen(defaults_group_suffix);
+ struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx;
+ char *ptr;
+ TYPELIB *group= ctx->group;
+
+ if (!(extra_groups=
+ (const char**)alloc_root(ctx->alloc,
+ (2*group->count+1)*sizeof(char*))))
+ goto err;
+
+ for (i= 0; i < group->count; i++)
+ {
+ uint len;
+ extra_groups[i]= group->type_names[i]; /** copy group */
+
+ len= strlen(extra_groups[i]);
+ if (!(ptr= alloc_root(ctx->alloc, len+instance_len+1)))
+ goto err;
+
+ extra_groups[i+group->count]= ptr;
+
+ /** Construct new group */
+ memcpy(ptr, extra_groups[i], len);
+ memcpy(ptr+len, defaults_group_suffix, instance_len+1);
+ }
+
+ group->count*= 2;
+ group->type_names= extra_groups;
+ group->type_names[group->count]= 0;
+ }
+
+ if (forced_default_file)
+ {
+ if ((error= search_default_file_with_ext(func, func_ctx, "", "",
+ forced_default_file, 0)) < 0)
+ goto err;
+ if (error > 0)
+ {
+ fprintf(stderr, "Could not open required defaults file: %s\n",
+ forced_default_file);
+ goto err;
+ }
+ }
+ else if (dirname_length(conf_file))
+ {
+ if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0)
+ goto err;
+ }
+ else
+ {
+ for (dirs= default_directories ; *dirs; dirs++)
+ {
+ if (**dirs)
+ {
+ if (search_default_file(func, func_ctx, *dirs, conf_file) < 0)
+ goto err;
+ }
+ else if (defaults_extra_file)
+ {
+ if ((error= search_default_file_with_ext(func, func_ctx, "", "",
+ defaults_extra_file, 0)) < 0)
+ goto err; /* Fatal error */
+ if (error > 0)
+ {
+ fprintf(stderr, "Could not open required defaults file: %s\n",
+ defaults_extra_file);
+ goto err;
+ }
+ }
+ }
+ }
+
+ DBUG_RETURN(error);
+
+err:
+ fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
+ exit(1);
+ return 0; /* Keep compiler happy */
+}
+
+
+/*
+ The option handler for load_defaults.
SYNOPSIS
- get_defaults_files()
+ handle_deault_option()
+ in_ctx Handler context. In this case it is a
+ handle_option_ctx structure.
+ group_name The name of the group the option belongs to.
+ option The very option to be processed. It is already
+ prepared to be used in argv (has -- prefix)
+
+ DESCRIPTION
+ This handler checks whether a group is one of the listed and adds an option
+ to the array if yes. Some other handler can record, for instance, all
+ groups and their options, not knowing in advance the names and amount of
+ groups.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+static int handle_default_option(void *in_ctx, const char *group_name,
+ const char *option)
+{
+ char *tmp;
+ struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
+
+ if (find_type((char *)group_name, ctx->group, 3))
+ {
+ if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1)))
+ return 1;
+ if (insert_dynamic(ctx->args, (gptr) &tmp))
+ return 1;
+ strmov(tmp, option);
+ }
+
+ return 0;
+}
+
+
+/*
+ Gets options from the command line
+
+ SYNOPSIS
+ get_defaults_options()
argc Pointer to argc of original program
argv Pointer to argv of original program
defaults --defaults-file option
extra_defaults --defaults-extra-file option
RETURN
- defaults and extra_defaults will be set to appropriate items
- of argv array, or to NULL if there are no such options
+ # Number of arguments used from *argv
+ defaults and extra_defaults will be set to option of the appropriate
+ items of argv array, or to NULL if there are no such options
*/
-void get_defaults_files(int argc, char **argv,
- char **defaults, char **extra_defaults)
+int get_defaults_options(int argc, char **argv,
+ char **defaults,
+ char **extra_defaults,
+ char **group_suffix)
{
- *defaults=0;
- *extra_defaults=0;
- if (argc >= 2)
+ int org_argc= argc, prev_argc= 0;
+ *defaults= *extra_defaults= *group_suffix= 0;
+
+ while (argc >= 2 && argc != prev_argc)
{
- if (is_prefix(argv[1],"--defaults-file="))
- *defaults= argv[1];
- else if (is_prefix(argv[1],"--defaults-extra-file="))
- *extra_defaults= argv[1];
+ /* Skip program name or previously handled argument */
+ argv++;
+ prev_argc= argc; /* To check if we found */
+ if (!*defaults && is_prefix(*argv,"--defaults-file="))
+ {
+ *defaults= *argv + sizeof("--defaults-file=")-1;
+ argc--;
+ continue;
+ }
+ if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file="))
+ {
+ *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
+ argc--;
+ continue;
+ }
+ if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
+ {
+ *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
+ argc--;
+ continue;
+ }
}
+ return org_argc - argc;
}
@@ -136,7 +352,6 @@ void get_defaults_files(int argc, char **argv,
RETURN
0 ok
1 The given conf_file didn't exists
- 2 The given conf_file was not a normal readable file
*/
@@ -144,17 +359,21 @@ int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
{
DYNAMIC_ARRAY args;
- const char **dirs, *forced_default_file, *forced_extra_defaults;
TYPELIB group;
- my_bool found_print_defaults=0;
- uint args_used=0;
+ my_bool found_print_defaults= 0;
+ uint args_used= 0;
int error= 0;
MEM_ROOT alloc;
- char *ptr, **res;
-
+ char *ptr,**res;
+ struct handle_option_ctx ctx;
DBUG_ENTER("load_defaults");
+ init_default_directories();
init_alloc_root(&alloc,512,0);
+ /*
+ Check if the user doesn't want any default option processing
+ --no-defaults is always the first option
+ */
if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
{
/* remove the --no-defaults argument and return only the other arguments */
@@ -173,76 +392,22 @@ int load_defaults(const char *conf_file, const char **groups,
DBUG_RETURN(0);
}
- get_defaults_files(*argc, *argv,
- (char **)&forced_default_file,
- (char **)&forced_extra_defaults);
- if (forced_default_file)
- forced_default_file= strchr(forced_default_file,'=')+1;
- if (forced_extra_defaults)
- defaults_extra_file= strchr(forced_extra_defaults,'=')+1;
-
- args_used+= (forced_default_file ? 1 : 0) + (forced_extra_defaults ? 1 : 0);
-
group.count=0;
group.name= "defaults";
group.type_names= groups;
+
for (; *groups ; groups++)
group.count++;
if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
goto err;
- if (forced_default_file)
- {
- if ((error= search_default_file_with_ext(&args, &alloc, "", "",
- forced_default_file,
- &group, 0)) < 0)
- goto err;
- if (error > 0)
- {
- fprintf(stderr, "Could not open required defaults file: %s\n",
- forced_default_file);
- goto err;
- }
- }
- else if (dirname_length(conf_file))
- {
- if ((error= search_default_file(&args, &alloc, NullS, conf_file,
- &group)) < 0)
- goto err;
- }
- else
- {
-#ifdef __WIN__
- char system_dir[FN_REFLEN];
- GetWindowsDirectory(system_dir,sizeof(system_dir));
- if ((search_default_file(&args, &alloc, system_dir, conf_file, &group)))
- goto err;
-#endif
-#if defined(__EMX__) || defined(OS2)
- {
- const char *etc;
- if ((etc= getenv("ETC")) &&
- (search_default_file(&args, &alloc, etc, conf_file,
- &group)) < 0)
- goto err;
- }
-#endif
- for (dirs=default_directories ; *dirs; dirs++)
- {
- if (**dirs)
- {
- if (search_default_file(&args, &alloc, *dirs, conf_file,
- &group) < 0)
- goto err;
- }
- else if (defaults_extra_file)
- {
- if (search_default_file(&args, &alloc, NullS, defaults_extra_file,
- &group) < 0)
- goto err; /* Fatal error */
- }
- }
- }
+
+ ctx.alloc= &alloc;
+ ctx.args= &args;
+ ctx.group= &group;
+
+ error= my_search_option_files(conf_file, argc, argv, &args_used,
+ handle_default_option, (void *) &ctx);
/*
Here error contains <> 0 only if we have a fully specified conf_file
or a forced default file
@@ -255,11 +420,14 @@ 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*));
- /* Skip --defaults-file and --defaults-extra-file */
+ /* Skip --defaults-xxx options */
(*argc)-= args_used;
(*argv)+= args_used;
- /* Check if we wan't to see the new argument list */
+ /*
+ Check if we wan't to see the new argument list
+ This options must always be the last of the default options
+ */
if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
{
found_print_defaults=1;
@@ -302,17 +470,22 @@ void free_defaults(char **argv)
}
-static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
+static int search_default_file(Process_option_func opt_handler,
+ void *handler_ctx,
const char *dir,
- const char *config_file, TYPELIB *group)
+ const char *config_file)
{
char **ext;
+ const char *empty_list[]= { "", 0 };
+ my_bool have_ext= fn_ext(config_file)[0] != 0;
+ const char **exts_to_use= have_ext ? empty_list : f_extensions;
- for (ext= (char**) f_extensions; *ext; *ext++)
+ for (ext= (char**) exts_to_use; *ext; *ext++)
{
int error;
- if ((error= search_default_file_with_ext(args, alloc, dir, *ext,
- config_file, group, 0)) < 0)
+ if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
+ dir, *ext,
+ config_file, 0)) < 0)
return error;
}
return 0;
@@ -374,8 +547,10 @@ static char *get_argument(const char *keyword, uint kwlen,
SYNOPSIS
search_default_file_with_ext()
- args Store pointer to found options here
- alloc Allocate strings in this object
+ opt_handler Option handler function. It is used to process
+ every separate option.
+ handler_ctx Pointer to the structure to store actual
+ parameters of the function.
dir directory to read
ext Extension for configuration file
config_file Name of configuration file
@@ -387,21 +562,23 @@ static char *get_argument(const char *keyword, uint kwlen,
0 Success
-1 Fatal error, abort
1 File not found (Warning)
- 2 File is not a regular file (Warning)
*/
-static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
- const char *dir, const char *ext,
- const char *config_file,
- TYPELIB *group, int recursion_level)
+static int search_default_file_with_ext(Process_option_func opt_handler,
+ void *handler_ctx,
+ const char *dir,
+ const char *ext,
+ const char *config_file,
+ int recursion_level)
{
- char name[FN_REFLEN + 10], buff[4096], *ptr, *end, *value, *tmp, **tmp_ext;
+ char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
+ char *value, option[4096], tmp[FN_REFLEN];
static const char includedir_keyword[]= "includedir";
static const char include_keyword[]= "include";
const int max_recursion_level= 10;
FILE *fp;
- uint line= 0;
- my_bool read_values= 0, found_group= 0;
+ uint line=0;
+ my_bool found_group=0;
uint i;
MY_DIR *search_dir;
FILEINFO *search_file;
@@ -433,14 +610,14 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
if ((stat_info.st_mode & S_IWOTH) &&
(stat_info.st_mode & S_IFMT) == S_IFREG)
{
- fprintf(stderr, "warning: World-writable config file %s is ignored\n",
+ fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n",
name);
return 0;
}
}
#endif
- if (!(fp= my_fopen(fn_format(name, name, "", "", 4), O_RDONLY, MYF(0))))
- return 0; /* Ignore wrong files */
+ if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
+ return 1; /* Ignore wrong files */
while (fgets(buff, sizeof(buff) - 1, fp))
{
@@ -499,14 +676,10 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
if (*tmp_ext)
{
- if (!(tmp= alloc_root(alloc, 2 + strlen(search_file->name)
- + strlen(ptr))))
- goto err;
-
fn_format(tmp, search_file->name, ptr, "",
MY_UNPACK_FILENAME | MY_SAFE_PATH);
- search_default_file_with_ext(args, alloc, "", "", tmp, group,
+ search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
recursion_level + 1);
}
}
@@ -521,7 +694,7 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
name, line)))
goto err;
- search_default_file_with_ext(args, alloc, "", "", ptr, group,
+ search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
recursion_level + 1);
}
@@ -540,7 +713,8 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;/* Remove end space */
end[0]=0;
- read_values=find_type(ptr,group,3) > 0;
+
+ strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096));
continue;
}
if (!found_group)
@@ -550,19 +724,17 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
name,line);
goto err;
}
- if (!read_values)
- continue;
+
+
end= remove_end_comment(ptr);
if ((value= strchr(ptr, '=')))
end= value; /* Option without argument */
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
if (!value)
{
- if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3)))
- goto err;
- strmake(strmov(tmp,"--"),ptr,(uint) (end-ptr));
- if (insert_dynamic(args,(gptr) &tmp))
- goto err;
+ strmake(strmov(option,"--"),ptr,(uint) (end-ptr));
+ if (opt_handler(handler_ctx, curr_gr, option))
+ goto err;
}
else
{
@@ -584,12 +756,7 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
value++;
value_end--;
}
- if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 +
- (uint) (value_end-value)+1)))
- goto err;
- if (insert_dynamic(args,(gptr) &tmp))
- goto err;
- ptr=strnmov(strmov(tmp,"--"),ptr,(uint) (end-ptr));
+ ptr=strnmov(strmov(option,"--"),ptr,(uint) (end-ptr));
*ptr++= '=';
for ( ; value != value_end; value++)
@@ -631,6 +798,8 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
*ptr++= *value;
}
*ptr=0;
+ if (opt_handler(handler_ctx, curr_gr, option))
+ goto err;
}
}
my_fclose(fp,MYF(0));
@@ -669,44 +838,24 @@ static char *remove_end_comment(char *ptr)
#include <help_start.h>
-void print_defaults(const char *conf_file, const char **groups)
+void my_print_default_files(const char *conf_file)
{
-#ifdef __WIN__
+ const char *empty_list[]= { "", 0 };
my_bool have_ext= fn_ext(conf_file)[0] != 0;
-#endif
+ const char **exts_to_use= have_ext ? empty_list : f_extensions;
char name[FN_REFLEN], **ext;
const char **dirs;
+ init_default_directories();
puts("\nDefault options are read from the following files in the given order:");
if (dirname_length(conf_file))
fputs(conf_file,stdout);
else
{
-#ifdef __WIN__
- GetWindowsDirectory(name,sizeof(name));
- if (!have_ext)
- {
- for (ext= (char**) f_extensions; *ext; *ext++)
- printf("%s\\%s%s ", name, conf_file, *ext);
- }
- else
- printf("%s\\%s ", name, conf_file);
-#endif
-#if defined(__EMX__) || defined(OS2)
- {
- const char *etc;
-
- if ((etc= getenv("ETC")))
- {
- for (ext= (char**) f_extensions; *ext; *ext++)
- printf("%s\\%s%s ", etc, conf_file, *ext);
- }
- }
-#endif
for (dirs=default_directories ; *dirs; dirs++)
{
- for (ext= (char**) f_extensions; *ext; *ext++)
+ for (ext= (char**) exts_to_use; *ext; *ext++)
{
const char *pos;
char *end;
@@ -725,12 +874,30 @@ void print_defaults(const char *conf_file, const char **groups)
}
puts("");
}
+}
+
+void print_defaults(const char *conf_file, const char **groups)
+{
+ const char **groups_save= groups;
+ my_print_default_files(conf_file);
+
fputs("The following groups are read:",stdout);
for ( ; *groups ; groups++)
{
fputc(' ',stdout);
fputs(*groups,stdout);
}
+
+ if (defaults_group_suffix)
+ {
+ groups= groups_save;
+ for ( ; *groups ; groups++)
+ {
+ fputc(' ',stdout);
+ fputs(*groups,stdout);
+ fputs(defaults_group_suffix,stdout);
+ }
+ }
puts("\nThe following options may be given as the first argument:\n\
--print-defaults Print the program argument list and exit\n\
--no-defaults Don't read default options from any options file\n\
@@ -739,3 +906,136 @@ void print_defaults(const char *conf_file, const char **groups)
}
#include <help_end.h>
+
+
+#ifdef __WIN__
+/*
+ This wrapper for GetSystemWindowsDirectory() will dynamically bind to the
+ function if it is available, emulate it on NT4 Terminal Server by stripping
+ the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just
+ return GetSystemDirectory().
+ */
+
+typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT);
+
+static uint my_get_system_windows_directory(char *buffer, uint size)
+{
+ uint count;
+ GET_SYSTEM_WINDOWS_DIRECTORY
+ func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY)
+ GetProcAddress(GetModuleHandle("kernel32.dll"),
+ "GetSystemWindowsDirectoryA");
+
+ if (func_ptr)
+ return func_ptr(buffer, size);
+
+ /*
+ Windows NT 4.0 Terminal Server Edition:
+ To retrieve the shared Windows directory, call GetSystemDirectory and
+ trim the "System32" element from the end of the returned path.
+ */
+ count= GetSystemDirectory(buffer, size);
+ if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0)
+ {
+ count-= 8;
+ buffer[count] = '\0';
+ }
+ return count;
+}
+#endif
+
+
+/*
+ Create the list of default directories.
+
+ On Microsoft Windows, this is:
+ 1. C:/
+ 2. GetWindowsDirectory()
+ 3. GetSystemWindowsDirectory()
+ 4. getenv(DEFAULT_HOME_ENV)
+ 5. Directory above where the executable is located
+ 6. ""
+
+ On Novell NetWare, this is:
+ 1. sys:/etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. ""
+
+ On OS/2, this is:
+ 1. getenv(ETC)
+ 2. /etc/
+ 3. getenv(DEFAULT_HOME_ENV)
+ 4. ""
+ 5. "~/"
+
+ Everywhere else, this is:
+ 1. /etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. ""
+ 4. "~/"
+
+ */
+
+static void init_default_directories()
+{
+ const char *env, **ptr= default_directories;
+
+#ifdef __WIN__
+ *ptr++= "C:/";
+
+ if (GetWindowsDirectory(system_dir,sizeof(system_dir)))
+ *ptr++= (char*)&system_dir;
+ if (my_get_system_windows_directory(shared_system_dir,
+ sizeof(shared_system_dir)) &&
+ strcmp(system_dir, shared_system_dir))
+ *ptr++= (char *)&shared_system_dir;
+
+#elif defined(__NETWARE__)
+ *ptr++= "sys:/etc/";
+#else
+#if defined(__EMX__) || defined(OS2)
+ if ((env= getenv("ETC")))
+ *ptr++= env;
+#endif
+ *ptr++= "/etc/";
+#endif
+ if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
+ *ptr++= env;
+ *ptr++= ""; /* Place for defaults_extra_file */
+#if !defined(__WIN__) && !defined(__NETWARE__)
+ *ptr++= "~/";;
+#elif defined(__WIN__)
+ if (GetModuleFileName(NULL, config_dir, sizeof(config_dir)))
+ {
+ char *last= NULL, *end= strend(config_dir);
+ /*
+ Look for the second-to-last \ in the filename, but hang on
+ to a pointer after the last \ in case we're in the root of
+ a drive.
+ */
+ for ( ; end > config_dir; end--)
+ {
+ if (*end == FN_LIBCHAR)
+ {
+ if (last)
+ {
+ if (end != config_dir)
+ {
+ /* Keep the last '\' as this works both with D:\ and a directory */
+ end[1]= 0;
+ }
+ else
+ {
+ /* No parent directory (strange). Use current dir + '\' */
+ last[1]= 0;
+ }
+ break;
+ }
+ last= end;
+ }
+ }
+ *ptr++= (char *)&config_dir;
+ }
+#endif
+ *ptr= 0; /* end marker */
+}
diff --git a/mysys/default_modify.c b/mysys/default_modify.c
new file mode 100644
index 00000000000..de03d783c68
--- /dev/null
+++ b/mysys/default_modify.c
@@ -0,0 +1,228 @@
+/* Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "my_global.h"
+#include "mysys_priv.h"
+#include "m_string.h"
+#include <my_dir.h>
+
+#define BUFF_SIZE 1024
+#define RESERVE 1024 /* Extend buffer with this extent */
+
+#ifdef __WIN__
+#define NEWLINE "\r\n"
+#define NEWLINE_LEN 2
+#else
+#define NEWLINE "\n"
+#define NEWLINE_LEN 1
+#endif
+
+static char *add_option(char *dst, const char *option_value,
+ const char *option, int remove_option);
+
+
+/*
+ Add/remove option to the option file section.
+
+ SYNOPSYS
+ modify_defaults_file()
+ file_location The location of configuration file to edit
+ option option to look for
+ option value The value of the option we would like to set
+ section_name the name of the section
+ remove_option This is true if we want to remove the option.
+ False otherwise.
+ IMPLEMENTATION
+ We open the option file first, then read the file line-by-line,
+ looking for the section we need. At the same time we put these lines
+ into a buffer. Then we look for the option within this section and
+ change/remove it. In the end we get a buffer with modified version of the
+ file. Then we write it to the file, truncate it if needed and close it.
+ Note that there is a small time gap, when the file is incomplete,
+ and this theoretically might introduce a problem.
+
+ RETURN
+ 0 - ok
+ 1 - some error has occured. Probably due to the lack of resourses
+ 2 - cannot open the file
+*/
+
+int modify_defaults_file(const char *file_location, const char *option,
+ const char *option_value,
+ const char *section_name, int remove_option)
+{
+ FILE *cnf_file;
+ MY_STAT file_stat;
+ char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer;
+ uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size;
+ my_bool in_section= FALSE, opt_applied= 0;
+ uint reserve_extended;
+ uint new_opt_len;
+ int reserve_occupied= 0;
+ DBUG_ENTER("modify_defaults_file");
+
+ if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0))))
+ DBUG_RETURN(2);
+
+ /* my_fstat doesn't use the flag parameter */
+ if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
+ goto malloc_err;
+
+ opt_len= (uint) strlen(option);
+ optval_len= (uint) strlen(option_value);
+
+ new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN;
+
+ /* calculate the size of the buffer we need */
+ reserve_extended= (opt_len +
+ 1 + /* For '=' char */
+ optval_len + /* Option value len */
+ NEWLINE_LEN + /* Space for newline */
+ RESERVE); /* Some additional space */
+
+ buffer_size= (file_stat.st_size +
+ 1); /* The ending zero */
+
+ /*
+ Reserve space to read the contents of the file and some more
+ for the option we want to add.
+ */
+ if (!(file_buffer= (char*) my_malloc(buffer_size + reserve_extended,
+ MYF(MY_WME))))
+ goto malloc_err;
+
+ sect_len= (uint) strlen(section_name);
+
+ for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); )
+ {
+ /* Skip over whitespaces */
+ for (src_ptr= linebuff; my_isspace(&my_charset_latin1, *src_ptr);
+ src_ptr++)
+ {}
+
+ if (!*src_ptr) /* Empty line */
+ {
+ nr_newlines++;
+ continue;
+ }
+
+ /* correct the option */
+ if (in_section && !strncmp(src_ptr, option, opt_len) &&
+ (*(src_ptr + opt_len) == '=' ||
+ my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) ||
+ *(src_ptr + opt_len) == '\0'))
+ {
+ char *old_src_ptr= src_ptr;
+ src_ptr= strend(src_ptr+ opt_len); /* Find the end of the line */
+
+ /* could be negative */
+ reserve_occupied+= (int) new_opt_len - (int) (src_ptr - old_src_ptr);
+ if (reserve_occupied >= (int) reserve_extended)
+ {
+ reserve_extended= (uint) reserve_occupied + RESERVE;
+ if (!(file_buffer= (char*) my_realloc(file_buffer, buffer_size +
+ reserve_extended,
+ MYF(MY_WME|MY_FREE_ON_ERROR))))
+ goto malloc_err;
+ }
+ opt_applied= 1;
+ dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
+ }
+ else
+ {
+ /* If going to new group and we have option to apply, do it now */
+ if (in_section && !opt_applied && *src_ptr == '[')
+ {
+ dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
+ opt_applied= 1; /* set the flag to do write() later */
+ reserve_occupied= new_opt_len+ opt_len + 1 + NEWLINE_LEN;
+ }
+
+ for (; nr_newlines; nr_newlines--)
+ dst_ptr= strmov(dst_ptr, NEWLINE);
+ dst_ptr= strmov(dst_ptr, linebuff);
+ }
+ /* Look for a section */
+ if (*src_ptr == '[')
+ {
+ /* Copy the line to the buffer */
+ if (!strncmp(++src_ptr, section_name, sect_len))
+ {
+ src_ptr+= sect_len;
+ /* Skip over whitespaces. They are allowed after section name */
+ for (; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++)
+ {}
+
+ if (*src_ptr != ']')
+ continue; /* Missing closing parenthesis. Assume this was no group */
+ in_section= TRUE;
+ }
+ else
+ in_section= FALSE; /* mark that this section is of no interest to us */
+ }
+ }
+ /* File ended. */
+ if (!opt_applied && !remove_option && in_section)
+ {
+ /* New option still remains to apply at the end */
+ if (*(dst_ptr - 1) != '\n')
+ dst_ptr= strmov(dst_ptr, NEWLINE);
+ dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
+ opt_applied= 1;
+ }
+ for (; nr_newlines; nr_newlines--)
+ dst_ptr= strmov(dst_ptr, NEWLINE);
+
+ if (opt_applied)
+ {
+ /* Don't write the file if there are no changes to be made */
+ if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
+ MYF(MY_WME)) ||
+ my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
+ my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer),
+ MYF(MY_NABP)))
+ goto err;
+ }
+ if (my_fclose(cnf_file, MYF(MY_WME)))
+ goto err;
+
+ my_free(file_buffer, MYF(0));
+ DBUG_RETURN(0);
+
+err:
+ my_free(file_buffer, MYF(0));
+malloc_err:
+ my_fclose(cnf_file, MYF(0));
+ DBUG_RETURN(1); /* out of resources */
+}
+
+
+static char *add_option(char *dst, const char *option_value,
+ const char *option, int remove_option)
+{
+ if (!remove_option)
+ {
+ dst= strmov(dst, option);
+ if (*option_value)
+ {
+ *dst++= '=';
+ dst= strmov(dst, option_value);
+ }
+ /* add a newline */
+ dst= strmov(dst, NEWLINE);
+ }
+ return dst;
+}
diff --git a/mysys/errors.c b/mysys/errors.c
index 05436c9a212..4472b7173fa 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -21,7 +21,6 @@
const char * NEAR globerrs[GLOBERRS]=
{
- "File '%s' not found (Errcode: %d)",
"Can't create/write to file '%s' (Errcode: %d)",
"Error reading file '%s' (Errcode: %d)",
"Error writing file '%s' (Errcode: %d)",
@@ -50,20 +49,18 @@ const char * NEAR globerrs[GLOBERRS]=
"Error on realpath() on '%s' (Error %d)",
"Can't sync file '%s' to disk (Errcode: %d)",
"Collation '%s' is not a compiled collation and is not specified in the '%s' file",
+ "File '%s' not found (Errcode: %d)",
};
void init_glob_errs(void)
{
- my_errmsg[GLOB] = & globerrs[0];
-} /* init_glob_errs */
+ /* This is now done statically. */
+}
#else
void init_glob_errs()
{
- my_errmsg[GLOB] = & globerrs[0];
-
- EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)";
EE(EE_CANTCREATEFILE) = "Can't create/write to file '%s' (Errcode: %d)";
EE(EE_READ) = "Error reading file '%s' (Errcode: %d)";
EE(EE_WRITE) = "Error writing file '%s' (Errcode: %d)";
@@ -91,5 +88,6 @@ void init_glob_errs()
EE(EE_REALPATH)= "Error on realpath() on '%s' (Error %d)";
EE(EE_SYNC)= "Can't sync file '%s' to disk (Errcode: %d)";
EE(EE_UNKNOWN_COLLATION)= "Collation '%s' is not a compiled collation and is not specified in the %s file";
+ EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)";
}
#endif
diff --git a/mysys/hash.c b/mysys/hash.c
index ffebdf76144..45cf7d5ff1d 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -103,7 +103,7 @@ static inline void hash_free_elements(HASH *hash)
hash_free()
hash the hash to delete elements of
- NOTES: Hash can't be reused wuthing calling hash_init again.
+ NOTES: Hash can't be reused without calling hash_init again.
*/
void hash_free(HASH *hash)
@@ -277,9 +277,8 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink)
record being compared against.
RETURN
- < 0 key of record < key
= 0 key of record == key
- > 0 key of record > key
+ != 0 key of record != key
*/
static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length)
diff --git a/mysys/list.c b/mysys/list.c
index 480c1080a45..0e55c9399f5 100644
--- a/mysys/list.c
+++ b/mysys/list.c
@@ -28,7 +28,7 @@
LIST *list_add(LIST *root, LIST *element)
{
DBUG_ENTER("list_add");
- DBUG_PRINT("enter",("root: 0x%lx element: %lx", root, element));
+ DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", root, element));
if (root)
{
if (root->prev) /* If add in mid of list */
diff --git a/mysys/mf_format.c b/mysys/mf_format.c
index d1ca1108d02..0fec9d27b1d 100644
--- a/mysys/mf_format.c
+++ b/mysys/mf_format.c
@@ -54,6 +54,8 @@ my_string fn_format(my_string to, const char *name, const char *dir,
pack_dirname(dev,dev); /* Put in ./.. and ~/.. */
if (flag & MY_UNPACK_FILENAME)
(void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */
+ if (flag & MY_UNIX_PATH)
+ to_unix_path(dev); /* Fix to MySQL representation */
if ((pos= (char*) strchr(name,FN_EXTCHAR)) != NullS)
{
if ((flag & MY_REPLACE_EXT) == 0) /* If we should keep old ext */
diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c
index 189d43e782a..8998da8aefa 100644
--- a/mysys/mf_getdate.c
+++ b/mysys/mf_getdate.c
@@ -19,11 +19,20 @@
#include "mysys_priv.h"
#include <m_string.h>
- /*
- If flag & 1 Return date and time
- If flag & 2 Return short date format YYMMDD
- if flag & 4 Return time in HHMMDD format.
- */
+/*
+ get date as string
+
+ SYNOPSIS
+ get_date()
+ to - string where date will be written
+ flag - format of date:
+ If flag & GETDATE_TIME Return date and time
+ If flag & GETDATE_SHORT_DATE Return short date format YYMMDD
+ If flag & GETDATE_HHMMSSTIME Return time in HHMMDD format.
+ If flag & GETDATE_GMT Date/time in GMT
+ If flag & GETDATE_FIXEDLENGTH Return fixed length date/time
+ date - for conversion
+*/
void get_date(register my_string to, int flag, time_t date)
@@ -36,27 +45,36 @@ void get_date(register my_string to, int flag, time_t date)
skr=date ? (time_t) date : time((time_t*) 0);
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
- localtime_r(&skr,&tm_tmp);
+ if (flag & GETDATE_GMT)
+ localtime_r(&skr,&tm_tmp);
+ else
+ gmtime_r(&skr,&tm_tmp);
start_time= &tm_tmp;
#else
- start_time=localtime(&skr);
+ if (flag & GETDATE_GMT)
+ start_time= localtime(&skr);
+ else
+ start_time= gmtime(&skr);
#endif
- if (flag & 2)
+ if (flag & GETDATE_SHORT_DATE)
sprintf(to,"%02d%02d%02d",
start_time->tm_year % 100,
start_time->tm_mon+1,
start_time->tm_mday);
else
- sprintf(to,"%d-%02d-%02d",
+ sprintf(to, ((flag & GETDATE_FIXEDLENGTH) ?
+ "%4d-%02d-%02d" : "%d-%02d-%02d"),
start_time->tm_year+1900,
start_time->tm_mon+1,
start_time->tm_mday);
- if (flag & 1)
- sprintf(strend(to)," %2d:%02d:%02d",
+ if (flag & GETDATE_DATE_TIME)
+ sprintf(strend(to),
+ ((flag & GETDATE_FIXEDLENGTH) ?
+ " %02d:%02d:%02d" : " %2d:%02d:%02d"),
start_time->tm_hour,
start_time->tm_min,
start_time->tm_sec);
- else if (flag & 4)
+ else if (flag & GETDATE_HHMMSSTIME)
sprintf(strend(to),"%02d%02d%02d",
start_time->tm_hour,
start_time->tm_min,
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index d80de3101be..b000af19aa0 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -27,7 +27,7 @@
also info->read_pos is set to info->read_end.
If called through open_cached_file(), then the temporary file will
only be created if a write exeeds the file buffer or if one calls
- flush_io_cache().
+ my_b_flush_io_cache().
If one uses SEQ_READ_APPEND, then two buffers are allocated, one for
reading and another for writing. Reads are first done from disk and
@@ -43,7 +43,7 @@ TODO:
each time the write buffer gets full and it's written to disk, we will
always do a disk read to read a part of the buffer from disk to the
read buffer.
- This should be fixed so that when we do a flush_io_cache() and
+ This should be fixed so that when we do a my_b_flush_io_cache() and
we have been reading the write buffer, we should transfer the rest of the
write buffer to the read buffer before we start to reuse it.
*/
@@ -171,7 +171,7 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
info->arg = 0;
info->alloced_buffer = 0;
info->buffer=0;
- info->seek_not_done= test(file >= 0);
+ info->seek_not_done= test(file >= 0 && seek_offset != my_tell(file, MYF(0)));
info->disk_writes= 0;
#ifdef THREAD
info->share=0;
@@ -184,8 +184,10 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
{ /* Assume file isn't growing */
if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
{
- /* Calculate end of file to not allocate to big buffers */
+ /* Calculate end of file to avoid allocating oversized buffers */
end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0));
+ /* Need to reset seek_not_done now that we just did a seek. */
+ info->seek_not_done= end_of_file == seek_offset ? 0 : 1;
if (end_of_file < seek_offset)
end_of_file=seek_offset;
/* Trim cache size if the file is very small */
@@ -360,7 +362,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
if (info->type == WRITE_CACHE && type == READ_CACHE)
info->end_of_file=my_b_tell(info);
/* flush cache if we want to reuse it */
- if (!clear_cache && flush_io_cache(info))
+ if (!clear_cache && my_b_flush_io_cache(info,1))
DBUG_RETURN(1);
info->pos_in_file=seek_offset;
/* Better to do always do a seek */
@@ -599,7 +601,7 @@ int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count)
info->error= info->share->active->error;
info->read_end= info->share->active->read_end;
info->pos_in_file= info->share->active->pos_in_file;
- len= (info->error == -1 ? -1 : info->read_end-info->buffer);
+ len= (int) (info->error == -1 ? -1 : info->read_end-info->buffer);
}
info->read_pos=info->buffer;
info->seek_not_done=0;
@@ -969,7 +971,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
Buffer+=rest_length;
Count-=rest_length;
info->write_pos+=rest_length;
- if (flush_io_cache(info))
+ if (my_b_flush_io_cache(info,1))
return 1;
if (Count >= IO_SIZE)
{ /* Fill first intern buffer */
@@ -1212,6 +1214,7 @@ int end_io_cache(IO_CACHE *info)
int error=0;
IO_CACHE_CALLBACK pre_close;
DBUG_ENTER("end_io_cache");
+ DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info));
#ifdef THREAD
/*
@@ -1221,7 +1224,7 @@ int end_io_cache(IO_CACHE *info)
*/
if (info->share)
{
- pthread_cond_destroy (&info->share->cond);
+ pthread_cond_destroy(&info->share->cond);
pthread_mutex_destroy(&info->share->mutex);
info->share=0;
}
@@ -1236,7 +1239,7 @@ int end_io_cache(IO_CACHE *info)
{
info->alloced_buffer=0;
if (info->file != -1) /* File doesn't exist */
- error=flush_io_cache(info);
+ error= my_b_flush_io_cache(info,1);
my_free((gptr) info->buffer,MYF(MY_WME));
info->buffer=info->read_pos=(byte*) 0;
}
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 3755bcdb53d..1f3db84304e 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -65,6 +65,13 @@ my_off_t my_b_append_tell(IO_CACHE* info)
return res;
}
+my_off_t my_b_safe_tell(IO_CACHE *info)
+{
+ if (unlikely(info->type == SEQ_READ_APPEND))
+ return my_b_append_tell(info);
+ return my_b_tell(info);
+}
+
/*
Make next read happen at the given position
For write cache, make next write happen at the given position
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index ca683f16415..a86b6a2f1f4 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -347,8 +347,8 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
blocks--;
/* Allocate memory for cache page buffers */
if ((keycache->block_mem=
- my_malloc_lock((ulong) blocks * keycache->key_cache_block_size,
- MYF(0))))
+ my_large_malloc((ulong) blocks * keycache->key_cache_block_size,
+ MYF(MY_WME))))
{
/*
Allocate memory for blocks, hash_links and hash entries;
@@ -357,7 +357,7 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
if ((keycache->block_root= (BLOCK_LINK*) my_malloc((uint) length,
MYF(0))))
break;
- my_free_lock(keycache->block_mem, MYF(0));
+ my_large_free(keycache->block_mem, MYF(0));
keycache->block_mem= 0;
}
if (blocks < 8)
@@ -428,7 +428,7 @@ err:
keycache->blocks= 0;
if (keycache->block_mem)
{
- my_free_lock((gptr) keycache->block_mem, MYF(0));
+ my_large_free((gptr) keycache->block_mem, MYF(0));
keycache->block_mem= NULL;
}
if (keycache->block_root)
@@ -622,7 +622,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
{
if (keycache->block_mem)
{
- my_free_lock((gptr) keycache->block_mem, MYF(0));
+ my_large_free((gptr) keycache->block_mem, MYF(0));
keycache->block_mem= NULL;
my_free((gptr) keycache->block_root, MYF(0));
keycache->block_root= NULL;
@@ -2192,7 +2192,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
{
int error;
int last_errno= 0;
- uint count= end-cache;
+ uint count= (uint) (end-cache);
/* Don't lock the cache during the flush */
keycache_pthread_mutex_unlock(&keycache->cache_lock);
diff --git a/mysys/my_access.c b/mysys/my_access.c
index 237312b5c9b..99e7a28914d 100644
--- a/mysys/my_access.c
+++ b/mysys/my_access.c
@@ -44,7 +44,7 @@ int my_access(const char *path, int amode)
result= GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo);
if (! result ||
- (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & F_OK))
+ (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & W_OK))
{
my_errno= errno= EACCES;
return -1;
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index d52a8efeed2..fd5a4908572 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -39,10 +39,11 @@
DESCRIPTION
This function prepares memory root for further use, sets initial size of
chunk for memory allocation and pre-allocates first block if specified.
- Altough error can happen during execution of this function if pre_alloc_size
- is non-0 it won't be reported. Instead it will be reported as error in first
- alloc_root() on this memory root.
+ Altough error can happen during execution of this function if
+ pre_alloc_size is non-0 it won't be reported. Instead it will be
+ reported as error in first alloc_root() on this memory root.
*/
+
void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused)))
{
@@ -71,6 +72,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
DBUG_VOID_RETURN;
}
+
/*
SYNOPSIS
reset_root_defaults()
@@ -86,7 +88,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
reuse one of existing blocks as prealloc block, or malloc new one of
requested size. If no blocks can be reused, all unused blocks are freed
before allocation.
- */
+*/
void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused)))
@@ -166,7 +168,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
gptr point;
reg1 USED_MEM *next= 0;
reg2 USED_MEM **prev;
-
+ DBUG_ENTER("alloc_root");
+ DBUG_PRINT("enter",("root: 0x%lx", mem_root));
DBUG_ASSERT(alloc_root_inited(mem_root));
Size= ALIGN_SIZE(Size);
@@ -213,15 +216,12 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
mem_root->used= next;
mem_root->first_block_usage= 0;
}
- return(point);
+ DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point));
+ DBUG_RETURN(point);
#endif
}
-#ifdef SAFEMALLOC
-#define TRASH(X) bfill(((char*)(X) + ((X)->size-(X)->left)), (X)->left, 0xa5)
-#else
-#define TRASH /* no-op */
-#endif
+#define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left)
/* Mark all data in blocks free for reusage */
@@ -235,7 +235,7 @@ static inline void mark_blocks_free(MEM_ROOT* root)
for (next= root->free; next; next= *(last= &next->next))
{
next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
- TRASH(next);
+ TRASH_MEM(next);
}
/* Combine the free and the used list */
@@ -245,7 +245,7 @@ static inline void mark_blocks_free(MEM_ROOT* root)
for (; next; next= next->next)
{
next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
- TRASH(next);
+ TRASH_MEM(next);
}
/* Now everything is set; Indicate that nothing is used anymore */
@@ -257,6 +257,20 @@ static inline void mark_blocks_free(MEM_ROOT* root)
/*
Deallocate everything used by alloc_root or just move
used blocks to free list if called with MY_USED_TO_FREE
+
+ SYNOPSIS
+ free_root()
+ root Memory root
+ MyFlags Flags for what should be freed:
+
+ MY_MARK_BLOCKS_FREED Don't free blocks, just mark them free
+ MY_KEEP_PREALLOC If this is not set, then free also the
+ preallocated block
+
+ NOTES
+ One can call this function either with root block initialised with
+ init_alloc_root() or with a bzero()-ed block.
+ It's also safe to call this multiple times with the same mem_root.
*/
void free_root(MEM_ROOT *root, myf MyFlags)
@@ -292,7 +306,7 @@ void free_root(MEM_ROOT *root, myf MyFlags)
{
root->free=root->pre_alloc;
root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
- TRASH(root->pre_alloc);
+ TRASH_MEM(root->pre_alloc);
root->free->next=0;
}
root->block_num= 4;
@@ -328,7 +342,7 @@ void set_prealloc_root(MEM_ROOT *root, char *ptr)
char *strdup_root(MEM_ROOT *root,const char *str)
{
- return strmake_root(root, str, strlen(str));
+ return strmake_root(root, str, (uint) strlen(str));
}
char *strmake_root(MEM_ROOT *root,const char *str, uint len)
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
index 55dd72f5f76..01c9b5ea68d 100644
--- a/mysys/my_bit.c
+++ b/mysys/my_bit.c
@@ -71,3 +71,8 @@ uint my_count_bits(ulonglong v)
#endif
}
+uint my_count_bits_ushort(ushort v)
+{
+ return nbits[v];
+}
+
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index f0d3339535d..4a917fc8287 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -29,6 +29,9 @@
* bitmap_intersect() is an exception :)
(for for Bitmap::intersect(ulonglong map2buff))
+ If THREAD is defined all bitmap operations except bitmap_init/bitmap_free
+ are thread-safe.
+
TODO:
Make assembler THREAD safe versions of these using test-and-set instructions
*/
@@ -37,7 +40,7 @@
#include <my_bitmap.h>
#include <m_string.h>
-static inline void bitmap_lock(MY_BITMAP* map)
+static inline void bitmap_lock(MY_BITMAP *map)
{
#ifdef THREAD
if (map->mutex)
@@ -45,7 +48,7 @@ static inline void bitmap_lock(MY_BITMAP* map)
#endif
}
-static inline void bitmap_unlock(MY_BITMAP* map)
+static inline void bitmap_unlock(MY_BITMAP *map)
{
#ifdef THREAD
if (map->mutex)
@@ -106,6 +109,52 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
}
+/*
+ test if bit already set and set it if it was not (thread unsafe method)
+
+ SYNOPSIS
+ bitmap_fast_test_and_set()
+ MAP bit map struct
+ BIT bit number
+
+ RETURN
+ 0 bit was not set
+ !=0 bit was set
+*/
+
+my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit)
+{
+ uchar *byte= map->bitmap + (bitmap_bit / 8);
+ uchar bit= 1 << ((bitmap_bit) & 7);
+ uchar res= (*byte) & bit;
+ *byte|= bit;
+ return res;
+}
+
+
+/*
+ test if bit already set and set it if it was not (thread safe method)
+
+ SYNOPSIS
+ bitmap_fast_test_and_set()
+ map bit map struct
+ bitmap_bit bit number
+
+ RETURN
+ 0 bit was not set
+ !=0 bit was set
+*/
+
+my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit)
+{
+ my_bool res;
+ DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
+ bitmap_lock(map);
+ res= bitmap_fast_test_and_set(map, bitmap_bit);
+ bitmap_unlock(map);
+ return res;
+}
+
uint bitmap_set_next(MY_BITMAP *map)
{
uchar *bitmap=map->bitmap;
@@ -290,6 +339,37 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
}
+/*
+ Set/clear all bits above a bit.
+
+ SYNOPSIS
+ bitmap_set_above()
+ map RETURN The bitmap to change.
+ from_byte The bitmap buffer byte offset to start with.
+ use_bit The bit value (1/0) to use for all upper bits.
+
+ NOTE
+ You can only set/clear full bytes.
+ The function is meant for the situation that you copy a smaller bitmap
+ to a bigger bitmap. Bitmap lengths are always multiple of eigth (the
+ size of a byte). Using 'from_byte' saves multiplication and division
+ by eight during parameter passing.
+
+ RETURN
+ void
+*/
+
+void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit)
+{
+ uchar use_byte= use_bit ? 0xff : 0;
+ uchar *to= map->bitmap + from_byte;
+ uchar *end= map->bitmap + map->bitmap_size;
+
+ while (to < end)
+ *to++= use_byte;
+}
+
+
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
{
uchar *to=map->bitmap, *from=map2->bitmap, *end;
@@ -327,3 +407,66 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
bitmap_unlock(map);
}
+
+/*
+ SYNOPSIS
+ bitmap_bits_set()
+ map
+ RETURN
+ Number of set bits in the bitmap.
+*/
+
+uint bitmap_bits_set(const MY_BITMAP *map)
+{
+ uchar *m= map->bitmap;
+ uchar *end= m + map->bitmap_size;
+ uint res= 0;
+
+ DBUG_ASSERT(map->bitmap);
+ bitmap_lock((MY_BITMAP *)map);
+ while (m < end)
+ {
+ res+= my_count_bits_ushort(*m++);
+ }
+ bitmap_unlock((MY_BITMAP *)map);
+ return res;
+}
+
+
+/*
+ SYNOPSIS
+ bitmap_get_first()
+ map
+ RETURN
+ Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set.
+*/
+
+uint bitmap_get_first(const MY_BITMAP *map)
+{
+ uchar *bitmap=map->bitmap;
+ uint bit_found = MY_BIT_NONE;
+ uint bitmap_size=map->bitmap_size*8;
+ uint i;
+
+ DBUG_ASSERT(map->bitmap);
+ bitmap_lock((MY_BITMAP *)map);
+ for (i=0; i < bitmap_size ; i++, bitmap++)
+ {
+ if (*bitmap != 0xff)
+ { /* Found slot with free bit */
+ uint b;
+ for (b=0; ; b++)
+ {
+ if (!(*bitmap & (1 << b)))
+ {
+ bit_found = (i*8)+b;
+ break;
+ }
+ }
+ break; /* Found bit */
+ }
+ }
+ bitmap_unlock((MY_BITMAP *)map);
+ return bit_found;
+}
+
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index cf26428d65f..9760de29a08 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -30,7 +30,9 @@
MyFlags Flags
DESCRIPTION
- my_chsize() truncates file if shorter else fill with the filler character
+ my_chsize() truncates file if shorter else fill with the filler character.
+ The function also changes the file pointer. Usually it points to the end
+ of the file after execution.
RETURN VALUE
0 Ok
@@ -48,9 +50,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));
if (oldsize > newlength)
+ {
#if defined(HAVE_SETFILEPOINTER)
/* This is for the moment only true on windows */
- {
long is_success;
HANDLE win_file= (HANDLE) _get_osfhandle(fd);
long length_low, length_high;
@@ -63,35 +65,29 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_RETURN(0);
my_errno= GetLastError();
goto err;
- }
#elif defined(HAVE_FTRUNCATE)
- {
if (ftruncate(fd, (off_t) newlength))
{
my_errno= errno;
goto err;
}
DBUG_RETURN(0);
- }
#elif defined(HAVE_CHSIZE)
- {
if (chsize(fd, (off_t) newlength))
{
my_errno=errno;
goto err;
}
DBUG_RETURN(0);
- }
#else
- {
/*
Fill space between requested length and true length with 'filler'
We should never come here on any modern machine
*/
VOID(my_seek(fd, newlength, MY_SEEK_SET, MYF(MY_WME+MY_FAE)));
swap_variables(my_off_t, newlength, oldsize);
- }
#endif
+ }
/* Full file with 'filler' until it's as big as requested */
bfill(buff, IO_SIZE, filler);
diff --git a/mysys/my_copy.c b/mysys/my_copy.c
index 03f3feb54d3..072492172e3 100644
--- a/mysys/my_copy.c
+++ b/mysys/my_copy.c
@@ -16,7 +16,7 @@
#define USES_TYPES /* sys/types is included */
#include "mysys_priv.h"
-#include <sys/stat.h>
+#include <my_dir.h> /* for stat */
#include <m_string.h>
#if defined(HAVE_UTIME_H)
#include <utime.h>
@@ -53,26 +53,28 @@ struct utimbuf {
int my_copy(const char *from, const char *to, myf MyFlags)
{
uint Count;
- int new_file_stat, create_flag;
+ my_bool new_file_stat; /* 1 if we could stat "to" */
+ int create_flag;
File from_file,to_file;
char buff[IO_SIZE];
- struct stat stat_buff,new_stat_buff;
+ MY_STAT stat_buff,new_stat_buff;
DBUG_ENTER("my_copy");
DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags));
from_file=to_file= -1;
- new_file_stat=0;
+ LINT_INIT(new_file_stat);
+ DBUG_ASSERT(!(MyFlags & (MY_FNABP | MY_NABP))); /* for my_read/my_write */
if (MyFlags & MY_HOLD_ORIGINAL_MODES) /* Copy stat if possible */
- new_file_stat=stat((char*) to, &new_stat_buff);
+ new_file_stat= test(my_stat((char*) to, &new_stat_buff, MYF(0)));
if ((from_file=my_open(from,O_RDONLY | O_SHARE,MyFlags)) >= 0)
{
- if (stat(from,&stat_buff))
+ if (!my_stat(from, &stat_buff, MyFlags))
{
my_errno=errno;
goto err;
}
- if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat)
+ if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat)
stat_buff=new_stat_buff;
create_flag= (MyFlags & MY_DONT_OVERWRITE_FILE) ? O_EXCL : O_TRUNC;
@@ -91,7 +93,7 @@ int my_copy(const char *from, const char *to, myf MyFlags)
/* Copy modes if possible */
- if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat)
+ if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat)
DBUG_RETURN(0); /* File copyed but not stat */
VOID(chmod(to, stat_buff.st_mode & 07777)); /* Copy modes */
#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 8a377f63c7e..0c18bbf6e8b 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -22,10 +22,40 @@
/* Define some external variables for error handling */
-const char ** NEAR my_errmsg[MAXMAPS]={0,0,0,0};
+/*
+ WARNING!
+ my_error family functions have to be used according following rules:
+ - if message have not parameters use my_message(ER_CODE, ER(ER_CODE), MYF(N))
+ - if message registered use my_error(ER_CODE, MYF(N), ...).
+ - With some special text of errror message use:
+ my_printf_error(ER_CODE, format, MYF(N), ...)
+*/
+
char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
/*
+ Message texts are registered into a linked list of 'my_err_head' structs.
+ Each struct contains (1.) an array of pointers to C character strings with
+ '\0' termination, (2.) the error number for the first message in the array
+ (array index 0) and (3.) the error number for the last message in the array
+ (array index (last - first)).
+ The array may contain gaps with NULL pointers and pointers to empty strings.
+ Both kinds of gaps will be translated to "Unknown error %d.", if my_error()
+ is called with a respective error number.
+ The list of header structs is sorted in increasing order of error numbers.
+ Negative error numbers are allowed. Overlap of error numbers is not allowed.
+ Not registered error numbers will be translated to "Unknown error %d.".
+*/
+static struct my_err_head
+{
+ struct my_err_head *meh_next; /* chain link */
+ const char **meh_errmsgs; /* error messages array */
+ int meh_first; /* error number matching array slot 0 */
+ int meh_last; /* error number matching last slot */
+} my_errmsgs_globerrs = {NULL, globerrs, EE_ERROR_FIRST, EE_ERROR_LAST};
+static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs;
+
+/*
Error message to user
SYNOPSIS
@@ -33,115 +63,42 @@ 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.
+ RETURN
+ What (*error_handler_hook)() returns:
+ 0 OK
*/
-int my_error(int nr,myf MyFlags, ...)
+int my_error(int nr, myf MyFlags, ...)
{
- va_list ap;
- uint olen, plen;
- reg1 const char *tpos;
- reg2 char *endpos;
- char * par;
- char ebuff[ERRMSGSIZE+20];
- int prec_chars; /* output precision */
- my_bool prec_supplied;
+ const char *format;
+ struct my_err_head *meh_p;
+ va_list args;
+ char ebuff[ERRMSGSIZE + 20];
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));
- if (nr / ERRMOD == GLOB && my_errmsg[GLOB] == 0)
- init_glob_errs();
+ /* Search for the error messages array, which could contain the message. */
+ for (meh_p= my_errmsgs_list; meh_p; meh_p= meh_p->meh_next)
+ if (nr <= meh_p->meh_last)
+ break;
- olen=(uint) strlen(tpos=my_errmsg[nr / ERRMOD][nr % ERRMOD]);
- endpos=ebuff;
+#ifdef SHARED_LIBRARY
+ if ((meh_p == &my_errmsgs_globerrs) && ! globerrs[0])
+ init_glob_errs();
+#endif
- while (*tpos)
+ /* get the error message string. Default, if NULL or empty string (""). */
+ if (! (format= (meh_p && (nr >= meh_p->meh_first)) ?
+ meh_p->meh_errmsgs[nr - meh_p->meh_first] : NULL) || ! *format)
+ (void) my_snprintf (ebuff, sizeof(ebuff), "Unknown error %d", nr);
+ else
{
- if (tpos[0] != '%')
- {
- *endpos++= *tpos++; /* Copy ordinary char */
- continue;
- }
- if (*++tpos == '%') /* test if %% */
- {
- olen--;
- }
- else
- {
- /*
- 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);
- if (prec_supplied && prec_chars > 0)
- plen= min((uint)prec_chars, plen);
- if (olen + plen < ERRMSGSIZE+2) /* Replace if possible */
- {
- 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);
- if (*tpos == 'd')
- plen= (uint) (int10_to_str((long) iarg, endpos, -10) - endpos);
- else
- plen= (uint) (int10_to_str((long) (uint) iarg, endpos, 10) - endpos);
- if (olen + plen < ERRMSGSIZE+2) /* Replace parameter if possible */
- {
- endpos+= plen;
- tpos++;
- olen+= plen-2;
- continue;
- }
- }
- }
- *endpos++= '%'; /* % used as % or unknown code */
+ va_start(args,MyFlags);
+ (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
+ va_end(args);
}
- *endpos= '\0'; /* End of errmessage */
- va_end(ap);
DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags));
}
@@ -160,11 +117,14 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
+ DBUG_ENTER("my_printf_error");
+ DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s",
+ error, MyFlags, errno, format));
va_start(args,MyFlags);
- (void) vsprintf (ebuff,format,args);
+ (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
va_end(args);
- return (*error_handler_hook)(error, ebuff, MyFlags);
+ DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags));
}
/*
@@ -181,3 +141,109 @@ int my_message(uint error, const char *str, register myf MyFlags)
{
return (*error_handler_hook)(error, str, MyFlags);
}
+
+
+/*
+ Register error messages for use with my_error().
+
+ SYNOPSIS
+ my_error_register()
+ errmsgs array of pointers to error messages
+ first error number of first message in the array
+ last error number of last message in the array
+
+ DESCRIPTION
+ The pointer array is expected to contain addresses to NUL-terminated
+ C character strings. The array contains (last - first + 1) pointers.
+ NULL pointers and empty strings ("") are allowed. These will be mapped to
+ "Unknown error" when my_error() is called with a matching error number.
+ This function registers the error numbers 'first' to 'last'.
+ No overlapping with previously registered error numbers is allowed.
+
+ RETURN
+ 0 OK
+ != 0 Error
+*/
+
+int my_error_register(const char **errmsgs, int first, int last)
+{
+ struct my_err_head *meh_p;
+ struct my_err_head **search_meh_pp;
+
+ /* Allocate a new header structure. */
+ if (! (meh_p= (struct my_err_head*) my_malloc(sizeof(struct my_err_head),
+ MYF(MY_WME))))
+ return 1;
+ meh_p->meh_errmsgs= errmsgs;
+ meh_p->meh_first= first;
+ meh_p->meh_last= last;
+
+ /* Search for the right position in the list. */
+ for (search_meh_pp= &my_errmsgs_list;
+ *search_meh_pp;
+ search_meh_pp= &(*search_meh_pp)->meh_next)
+ {
+ if ((*search_meh_pp)->meh_last > first)
+ break;
+ }
+
+ /* Error numbers must be unique. No overlapping is allowed. */
+ if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last))
+ return 1;
+
+ /* Insert header into the chain. */
+ meh_p->meh_next= *search_meh_pp;
+ *search_meh_pp= meh_p;
+ return 0;
+}
+
+
+/*
+ Unregister formerly registered error messages.
+
+ SYNOPSIS
+ my_error_unregister()
+ first error number of first message
+ last error number of last message
+
+ DESCRIPTION
+ This function unregisters the error numbers 'first' to 'last'.
+ These must have been previously registered by my_error_register().
+ 'first' and 'last' must exactly match the registration.
+ If a matching registration is present, the header is removed from the
+ list and the pointer to the error messages pointers array is returned.
+ Otherwise, NULL is returned.
+
+ RETURN
+ non-NULL OK, returns address of error messages pointers array.
+ NULL Error, no such number range registered.
+*/
+
+const char **my_error_unregister(int first, int last)
+{
+ struct my_err_head *meh_p;
+ struct my_err_head **search_meh_pp;
+ const char **errmsgs;
+
+ /* Search for the registration in the list. */
+ for (search_meh_pp= &my_errmsgs_list;
+ *search_meh_pp;
+ search_meh_pp= &(*search_meh_pp)->meh_next)
+ {
+ if (((*search_meh_pp)->meh_first == first) &&
+ ((*search_meh_pp)->meh_last == last))
+ break;
+ }
+ if (! *search_meh_pp)
+ return NULL;
+
+ /* Remove header from the chain. */
+ meh_p= *search_meh_pp;
+ *search_meh_pp= meh_p->meh_next;
+
+ /* Save the return value and free the header. */
+ errmsgs= meh_p->meh_errmsgs;
+ my_free((gptr) meh_p, MYF(0));
+
+ return errmsgs;
+}
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 53e46932167..e9e20fe4024 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -180,7 +180,7 @@ int handle_options(int *argc, char ***argv,
}
opt_str= check_struct_option(cur_arg, key_name);
optend= strcend(opt_str, '=');
- length= optend - opt_str;
+ length= (uint) (optend - opt_str);
if (*optend == '=')
optend++;
else
@@ -205,7 +205,8 @@ int handle_options(int *argc, char ***argv,
{
if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
special_opt_prefix_lengths[i]) &&
- opt_str[special_opt_prefix_lengths[i]] == '-')
+ (opt_str[special_opt_prefix_lengths[i]] == '-' ||
+ opt_str[special_opt_prefix_lengths[i]] == '_'))
{
/*
We were called with a special prefix, we can reuse opt_found
@@ -322,7 +323,7 @@ int handle_options(int *argc, char ***argv,
return EXIT_NO_ARGUMENT_ALLOWED;
}
value= optp->var_type & GET_ASK_ADDR ?
- (*getopt_get_addr)(key_name, strlen(key_name), optp) : optp->value;
+ (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp) : optp->value;
if (optp->arg_type == NO_ARG)
{
@@ -341,11 +342,23 @@ int handle_options(int *argc, char ***argv,
--enable-'option-name'.
*optend was set to '0' if one used --disable-option
*/
- my_bool tmp= (my_bool) (!optend || *optend == '1');
- *((my_bool*) value)= tmp;
(*argc)--;
+ if (!optend || *optend == '1' ||
+ !my_strcasecmp(&my_charset_latin1, optend, "true"))
+ *((my_bool*) value)= (my_bool) 1;
+ else if (*optend == '0' ||
+ !my_strcasecmp(&my_charset_latin1, optend, "false"))
+ *((my_bool*) value)= (my_bool) 0;
+ else
+ {
+ my_getopt_error_reporter(WARNING_LEVEL,
+ "%s: ignoring option '--%s' due to \
+invalid value '%s'\n",
+ my_progname, optp->name, optend);
+ continue;
+ }
get_one_option(optp->id, optp,
- tmp ? (char*) "1" : disabled_my_option);
+ value ? (char*) "1" : disabled_my_option);
continue;
}
argument= optend;
@@ -518,7 +531,7 @@ static char *check_struct_option(char *cur_arg, char *key_name)
*/
if (end - ptr > 1)
{
- uint len= ptr - cur_arg;
+ uint len= (uint) (ptr - cur_arg);
set_if_smaller(len, FN_REFLEN-1);
strmake(key_name, cur_arg, len);
return ++ptr;
@@ -832,7 +845,7 @@ void my_print_help(const struct my_option *options)
if (strlen(optp->name))
{
printf("--%s", optp->name);
- col+= 2 + strlen(optp->name);
+ col+= 2 + (uint) strlen(optp->name);
if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
(optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
{
@@ -903,7 +916,7 @@ void my_print_variables(const struct my_option *options)
if (value)
{
printf("%s", optp->name);
- length= strlen(optp->name);
+ length= (uint) strlen(optp->name);
for (; length < name_space; length++)
putchar(' ');
switch ((optp->var_type & GET_TYPE_MASK)) {
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 5ee181ca78e..e14bd7529f9 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -21,11 +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 (skip_end_space)
+ if (!part_key)
return charset_info->coll->strnncollsp(charset_info, a, a_length,
- b, b_length);
+ b, b_length, (my_bool)!skip_end_space);
return charset_info->coll->strnncoll(charset_info, a, a_length,
- b, b_length, part_key);
+ b, b_length, part_key);
}
@@ -178,6 +178,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
}
break;
case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_BIT:
if (keyseg->flag & HA_SPACE_PACK)
{
int a_length,b_length,pack_length;
@@ -206,13 +207,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
b+=length;
}
break;
- case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
{
- int a_length,full_a_length,b_length,full_b_length,pack_length;
+ int a_length,b_length,pack_length;
get_key_length(a_length,a);
get_key_pack_length(b_length,pack_length,b);
- full_a_length= a_length;
- full_b_length= b_length;
next_key_length=key_length-b_length-pack_length;
if (piks &&
@@ -221,14 +221,17 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
next_key_length <= 0),
(my_bool) ((nextflag & (SEARCH_FIND |
SEARCH_UPDATE)) ==
- SEARCH_FIND))))
+ SEARCH_FIND &&
+ ! (keyseg->flag &
+ HA_END_SPACE_ARE_EQUAL)))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+= full_a_length;
- b+= full_b_length;
+ a+= a_length;
+ b+= b_length;
break;
}
break;
- case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_VARBINARY1:
+ case HA_KEYTYPE_VARBINARY2:
{
int a_length,b_length,pack_length;
get_key_length(a_length,a);
diff --git a/mysys/my_init.c b/mysys/my_init.c
index bee485c3bed..abb1ad27f7b 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -96,7 +96,7 @@ my_bool my_init(void)
#endif
{
DBUG_ENTER("my_init");
- DBUG_PROCESS(my_progname ? my_progname : (char*) "unknown");
+ DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown"));
if (!home_dir)
{ /* Don't initialize twice */
my_win_init();
@@ -395,7 +395,7 @@ static void netware_init()
}
/* Parse program name and change to base format */
- name= my_progname;
+ name= (char*) my_progname;
for (; *name; name++)
{
if (*name == '\\')
diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c
new file mode 100644
index 00000000000..0639c360b46
--- /dev/null
+++ b/mysys/my_largepage.c
@@ -0,0 +1,167 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysys_priv.h"
+
+#ifdef HAVE_LARGE_PAGES
+
+#ifdef HAVE_SYS_IPC_H
+#include <sys/ipc.h>
+#endif
+
+#ifdef HAVE_SYS_SHM_H
+#include <sys/shm.h>
+#endif
+
+static uint my_get_large_page_size_int(void);
+static gptr my_large_malloc_int(uint size, myf my_flags);
+static my_bool my_large_free_int(gptr ptr, myf my_flags);
+
+/* Gets the size of large pages from the OS */
+
+uint my_get_large_page_size(void)
+{
+ uint size;
+ DBUG_ENTER("my_get_large_page_size");
+
+ if (!(size = my_get_large_page_size_int()))
+ fprintf(stderr, "Warning: Failed to determine large page size\n");
+
+ DBUG_RETURN(size);
+}
+
+/*
+ General large pages allocator.
+ Tries to allocate memory from large pages pool and falls back to
+ my_malloc_lock() in case of failure
+*/
+
+gptr my_large_malloc(uint size, myf my_flags)
+{
+ gptr ptr;
+ DBUG_ENTER("my_large_malloc");
+
+ if (my_use_large_pages && my_large_page_size)
+ {
+ if ((ptr = my_large_malloc_int(size, my_flags)) != NULL)
+ DBUG_RETURN(ptr);
+ if (my_flags & MY_WME)
+ fprintf(stderr, "Warning: Using conventional memory pool\n");
+ }
+
+ DBUG_RETURN(my_malloc_lock(size, my_flags));
+}
+
+/*
+ General large pages deallocator.
+ Tries to deallocate memory as if it was from large pages pool and falls back
+ to my_free_lock() in case of failure
+ */
+
+void my_large_free(gptr ptr, myf my_flags __attribute__((unused)))
+{
+ DBUG_ENTER("my_large_free");
+
+ /*
+ my_large_free_int() can only fail if ptr was not allocated with
+ my_large_malloc_int(), i.e. my_malloc_lock() was used so we should free it
+ with my_free_lock()
+ */
+ if (!my_use_large_pages || !my_large_page_size ||
+ !my_large_free_int(ptr, my_flags))
+ my_free_lock(ptr, my_flags);
+
+ DBUG_VOID_RETURN;
+}
+
+#ifdef HUGETLB_USE_PROC_MEMINFO
+/* Linux-specific function to determine the size of large pages */
+
+uint my_get_large_page_size_int(void)
+{
+ FILE *f;
+ uint size = 0;
+ char buf[256];
+ DBUG_ENTER("my_get_large_page_size_int");
+
+ if (!(f = my_fopen("/proc/meminfo", O_RDONLY, MYF(MY_WME))))
+ goto finish;
+
+ while (fgets(buf, sizeof(buf), f))
+ if (sscanf(buf, "Hugepagesize: %u kB", &size))
+ break;
+
+ my_fclose(f, MYF(MY_WME));
+
+finish:
+ DBUG_RETURN(size * 1024);
+}
+#endif /* HUGETLB_USE_PROC_MEMINFO */
+
+#if HAVE_DECL_SHM_HUGETLB
+/* Linux-specific large pages allocator */
+
+gptr my_large_malloc_int(uint size, myf my_flags)
+{
+ int shmid;
+ gptr ptr;
+ struct shmid_ds buf;
+ DBUG_ENTER("my_large_malloc_int");
+
+ /* Align block size to my_large_page_size */
+ size = ((size - 1) & ~(my_large_page_size - 1)) + my_large_page_size;
+
+ shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
+ if (shmid < 0)
+ {
+ if (my_flags & MY_WME)
+ fprintf(stderr,
+ "Warning: Failed to allocate %d bytes from HugeTLB memory."
+ " errno %d\n", size, errno);
+
+ DBUG_RETURN(NULL);
+ }
+
+ ptr = shmat(shmid, NULL, 0);
+ if (ptr == (void *)-1)
+ {
+ if (my_flags& MY_WME)
+ fprintf(stderr, "Warning: Failed to attach shared memory segment,"
+ " errno %d\n", errno);
+ shmctl(shmid, IPC_RMID, &buf);
+
+ DBUG_RETURN(NULL);
+ }
+
+ /*
+ Remove the shared memory segment so that it will be automatically freed
+ after memory is detached or process exits
+ */
+ shmctl(shmid, IPC_RMID, &buf);
+
+ DBUG_RETURN(ptr);
+}
+
+/* Linux-specific large pages deallocator */
+
+my_bool my_large_free_int(byte *ptr, myf my_flags __attribute__((unused)))
+{
+ DBUG_ENTER("my_large_free_int");
+ DBUG_RETURN(shmdt(ptr) == 0);
+}
+#endif /* HAVE_DECL_SHM_HUGETLB */
+
+#endif /* HAVE_LARGE_PAGES */
diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c
new file mode 100644
index 00000000000..21bfddae46c
--- /dev/null
+++ b/mysys/my_mmap.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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 "mysys_priv.h"
+
+#ifdef HAVE_SYS_MMAN_H
+
+/*
+ system msync() only syncs mmap'ed area to fs cache.
+ fsync() is required to really sync to disc
+*/
+int my_msync(int fd, void *addr, size_t len, int flags)
+{
+ msync(addr, len, flags);
+ return my_sync(fd, MYF(0));
+}
+
+#elif defined(__WIN__)
+
+static SECURITY_ATTRIBUTES mmap_security_attributes=
+ {sizeof(SECURITY_ATTRIBUTES), 0, TRUE};
+
+int my_getpagesize(void)
+{
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwPageSize;
+}
+
+void *my_mmap(void *addr, size_t len, int prot,
+ int flags, int fd, my_off_t offset)
+{
+ DWORD flProtect=0;
+ HANDLE hFileMap;
+ LPVOID ptr;
+ HANDLE hFile= (HANDLE)_get_osfhandle(fd);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return MAP_FAILED;
+
+ flProtect|=SEC_COMMIT;
+
+ hFileMap=CreateFileMapping(hFile, &mmap_security_attributes,
+ PAGE_READWRITE, 0, (DWORD) len, NULL);
+ if (hFileMap == 0)
+ return MAP_FAILED;
+
+ ptr=MapViewOfFile(hFileMap,
+ flags & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ,
+ (DWORD)(offset >> 32), (DWORD)offset, len);
+
+ /*
+ MSDN explicitly states that it's possible to close File Mapping Object
+ even when a view is not unmapped - then the object will be held open
+ implicitly until unmap, as every view stores internally a handler of
+ a corresponding File Mapping Object
+ */
+ CloseHandle(hFileMap);
+
+ if (ptr)
+ return ptr;
+
+ return MAP_FAILED;
+}
+
+int my_munmap(void *addr, size_t len)
+{
+ return UnmapViewOfFile(addr) ? 0 : -1;
+}
+
+int my_msync(int fd, void *addr, size_t len, int flags)
+{
+ return FlushViewOfFile(addr, len) ? 0 : -1;
+}
+
+#else
+#warning "no mmap!"
+#endif
+
diff --git a/mysys/my_new.cc b/mysys/my_new.cc
index 14423c3afd5..66f3a14eeb4 100644
--- a/mysys/my_new.cc
+++ b/mysys/my_new.cc
@@ -45,5 +45,14 @@ void operator delete[] (void *ptr) throw ()
free(ptr);
}
+C_MODE_START
+
+int __cxa_pure_virtual() {
+ assert("Pure virtual method called." == "Aborted");
+ return 0;
+}
+
+C_MODE_END
+
#endif /* USE_MYSYS_NEW */
diff --git a/mysys/my_once.c b/mysys/my_once.c
index a4201810b03..ab5fcc51c0e 100644
--- a/mysys/my_once.c
+++ b/mysys/my_once.c
@@ -81,7 +81,7 @@ gptr my_once_alloc(unsigned int Size, myf MyFlags)
char *my_once_strdup(const char *src,myf myflags)
{
- uint len=strlen(src)+1;
+ uint len= (uint) strlen(src)+1;
char *dst=my_once_alloc(len, myflags);
if (dst)
memcpy(dst, src, len);
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 7cf40b57403..69d63c49554 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -79,7 +79,7 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
my_close()
fd File sescriptor
myf Special Flags
-
+
*/
int my_close(File fd, myf MyFlags)
@@ -89,7 +89,12 @@ int my_close(File fd, myf MyFlags)
DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
- if ((err = close(fd)))
+ do
+ {
+ err= close(fd);
+ } while (err == -1 && errno == EINTR);
+
+ if (err)
{
DBUG_PRINT("error",("Got error %d on close",err));
my_errno=errno;
diff --git a/mysys/my_os2cond.c b/mysys/my_os2cond.c
index e23afb89e66..83a03d62046 100644
--- a/mysys/my_os2cond.c
+++ b/mysys/my_os2cond.c
@@ -100,7 +100,7 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
rc = DosWaitEventSem(cond->semaphore, timeout);
if (rc != 0)
- rval = ETIME;
+ rval= ETIMEDOUT;
if (mutex) pthread_mutex_lock(mutex);
diff --git a/mysys/my_static.c b/mysys/my_static.c
index 5f034555156..8448afdc158 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -25,8 +25,11 @@
#include "my_alarm.h"
#endif
+my_bool timed_mutexes= 0;
+
/* from my_init */
-my_string home_dir=0,my_progname=0;
+my_string home_dir=0;
+const char *my_progname=0;
char NEAR curr_dir[FN_REFLEN]= {0},
NEAR home_dir_buff[FN_REFLEN]= {0};
ulong my_stream_opened=0,my_file_opened=0, my_tmp_file_created=0;
@@ -61,6 +64,12 @@ const char *soundex_map= "01230120022455012623010202";
USED_MEM* my_once_root_block=0; /* pointer to first block */
uint my_once_extra=ONCE_ALLOC_INIT; /* Memory to alloc / block */
+ /* from my_largepage.c */
+#ifdef HAVE_LARGE_PAGES
+my_bool my_use_large_pages= 0;
+uint my_large_page_size= 0;
+#endif
+
/* from my_tempnam */
#if !defined(HAVE_TEMPNAM) || defined(HPUX11)
int _my_tempnam_used=0;
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index 317ca039346..c557324b52c 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -27,7 +27,14 @@
my_flags Flags (now only MY_WME is supported)
NOTE
- If file system supports its, only file data is synced, not inode date
+ If file system supports its, only file data is synced, not inode data.
+
+ MY_IGNORE_BADFD is useful when fd is "volatile" - not protected by a
+ mutex. In this case by the time of fsync(), fd may be already closed by
+ another thread, or even reassigned to a different file. With this flag -
+ MY_IGNORE_BADFD - such a situation will not be considered an error.
+ (which is correct behaviour, if we know that the other thread synced the
+ file before closing)
RETURN
0 ok
@@ -40,21 +47,30 @@ int my_sync(File fd, myf my_flags)
DBUG_ENTER("my_sync");
DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags));
+ do
+ {
#if defined(HAVE_FDATASYNC)
- res= fdatasync(fd);
+ res= fdatasync(fd);
#elif defined(HAVE_FSYNC)
- res=fsync(fd);
+ res= fsync(fd);
#elif defined(__WIN__)
res= _commit(fd);
#else
- res= 0; /* No sync (strange OS) */
+ res= 0; /* No sync (strange OS) */
#endif
+ } while (res == -1 && errno == EINTR);
+
if (res)
{
- if (!(my_errno= errno))
- my_errno= -1; /* Unknown error */
- if (my_flags & MY_WME)
+ int er= errno;
+ if (!(my_errno= er))
+ my_errno= -1; /* Unknown error */
+ if ((my_flags & MY_IGNORE_BADFD) &&
+ (er == EBADF || er == EINVAL || er == EROFS))
+ res= 0;
+ else if (my_flags & MY_WME)
my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno);
}
DBUG_RETURN(res);
-} /* my_read */
+} /* my_sync */
+
diff --git a/mysys/my_tempnam.c b/mysys/my_tempnam.c
deleted file mode 100644
index 9f765298fb6..00000000000
--- a/mysys/my_tempnam.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Copyright (C) 2000 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 function is only used by some old ISAM code.
- When we remove ISAM support from MySQL, we should also delete this file
-
- One should instead use the functions in mf_tempfile.c
-*/
-
-#include "mysys_priv.h"
-#include <m_string.h>
-
-/* HPUX 11.0 doesn't allow us to change the environ pointer */
-#ifdef HPUX11
-#undef HAVE_TEMPNAM
-#endif
-
-#include "my_static.h"
-#include "mysys_err.h"
-
-#define TMP_EXT ".tmp" /* Extension of tempfile */
-#if ! defined(P_tmpdir)
-#define P_tmpdir ""
-#endif
-
-#ifdef HAVE_TEMPNAM
-#if !defined( MSDOS) && !defined(OS2) && !defined(__NETWARE__)
-extern char **environ;
-#endif
-#endif
-
-/* Make a uniq temp file name by using dir and adding something after
- pfx to make name uniq. Name is made by adding a uniq 8 length-string and
- TMP_EXT after pfx.
- Returns pointer to malloced area for filename. Should be freed by
- free().
- The name should be uniq, but it isn't checked if it file allready exists.
- Uses tempnam() if function exist on system.
- This function fixes that if dir is given it's used. For example
- MSDOS tempnam() uses always TMP environment-variable if it exists.
-*/
- /* ARGSUSED */
-
-my_string my_tempnam(const char *dir, const char *pfx,
- myf MyFlags __attribute__((unused)))
-{
-#ifdef _MSC_VER
- char temp[FN_REFLEN],*end,*res,**old_env,*temp_env[1];
- old_env=environ;
- if (dir)
- {
- end=strend(dir)-1;
- if (!dir[0])
- { /* Change empty string to current dir */
- temp[0]= FN_CURLIB;
- temp[1]= 0;
- dir=temp;
- }
- else if (*end == FN_DEVCHAR)
- { /* Get current dir for drive */
- _fullpath(temp,dir,FN_REFLEN);
- dir=temp;
- }
- else if (*end == FN_LIBCHAR && dir < end && end[-1] != FN_DEVCHAR)
- {
- strmake(temp,dir,(uint) (end-dir)); /* Copy and remove last '\' */
- dir=temp;
- }
- environ=temp_env; /* Force use of dir (dir not checked) */
- temp_env[0]=0;
- }
- res=tempnam((char*) dir,(my_string) pfx);
- environ=old_env;
- return res;
-#else
-#ifdef __ZTC__
- if (!dir)
- { /* If empty test first if TMP can be used */
- dir=getenv("TMP");
- }
- return tempnam((char*) dir,(my_string) pfx); /* Use stand. dir with prefix */
-#else
-#ifdef HAVE_TEMPNAM
- char temp[2],*res,**old_env,*temp_env[1];
-
- if (dir && !dir[0])
- { /* Change empty string to current dir */
- temp[0]= FN_CURLIB;
- temp[1]= 0;
- dir=temp;
- }
-#ifdef OS2
- /* changing environ variable doesn't work with VACPP */
- char buffer[256], *end;
- buffer[sizeof[buffer)-1]= 0;
- end= strxnmov(buffer, sizeof(buffer)-1, (char*) "TMP=", dir, NullS);
- /* remove ending backslash */
- if (end[-1] == '\\')
- end[-1]= 0;
- putenv(buffer);
-#elif !defined(__NETWARE__)
- old_env=(char**)environ;
- if (dir)
- { /* Don't use TMPDIR if dir is given */
- /*
- The following strange cast is required because the IBM compiler on AIX
- doesn't allow us to cast the value of environ.
- The cast of environ is needed as some systems doesn't allow us to
- update environ with a char ** pointer. (const mismatch)
- */
- (*(char***) &environ)=(char**) temp_env;
- temp_env[0]=0;
- }
-#endif
- res=tempnam((char*) dir,(my_string) pfx); /* Use stand. dir with prefix */
-#if !defined(OS2) && !defined(__NETWARE__)
- (*(char***) &environ)=(char**) old_env;
-#endif
- if (!res)
- DBUG_PRINT("error",("Got error: %d from tempnam",errno));
- return res;
-#else
- register long uniq;
- register int length;
- my_string pos,end_pos;
- DBUG_ENTER("my_tempnam");
- /* Make a uniq nummber */
- pthread_mutex_lock(&THR_LOCK_open);
- uniq= ((long) getpid() << 20) + (long) _my_tempnam_used++ ;
- pthread_mutex_unlock(&THR_LOCK_open);
- if (!dir && !(dir=getenv("TMPDIR"))) /* Use this if possibly */
- dir=P_tmpdir; /* Use system default */
- length=strlen(dir)+strlen(pfx)+1;
-
- DBUG_PRINT("test",("mallocing %d byte",length+8+sizeof(TMP_EXT)+1));
- if (!(pos=(char*) malloc(length+8+sizeof(TMP_EXT)+1)))
- {
- if (MyFlags & MY_FAE+MY_WME)
- my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),
- length+8+sizeof(TMP_EXT)+1);
- DBUG_RETURN(NullS);
- }
- end_pos=strmov(pos,dir);
- if (end_pos != pos && end_pos[-1] != FN_LIBCHAR)
- *end_pos++=FN_LIBCHAR;
- end_pos=strmov(end_pos,pfx);
-
- for (length=0 ; length < 8 && uniq ; length++)
- {
- *end_pos++= _dig_vec_upper[(int) (uniq & 31)];
- uniq >>= 5;
- }
- VOID(strmov(end_pos,TMP_EXT));
- DBUG_PRINT("exit",("tempnam: '%s'",pos));
- DBUG_RETURN(pos);
-#endif /* HAVE_TEMPNAM */
-#endif /* __ZTC__ */
-#endif /* _MSC_VER */
-} /* my_tempnam */
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 878e1f6bfc6..4d23d01cd82 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -67,12 +67,11 @@ my_bool my_thread_global_init(void)
/*
Set mutex type to "fast" a.k.a "adaptive"
- The mutex kind determines what happens if a thread attempts to lock
- a mutex it already owns with pthread_mutex_lock(3). If the mutex
- is of the ``fast'' kind, pthread_mutex_lock(3) simply suspends
- the calling thread forever. If the mutex is of the ``error checking''
- kind, pthread_mutex_lock(3) returns immediately with the error
- code EDEADLK.
+ In this case the thread may steal the mutex from some other thread
+ that is waiting for the same mutex. This will save us some
+ context switches but may cause a thread to 'starve forever' while
+ waiting for the mutex (not likely if the code within the mutex is
+ short).
*/
pthread_mutexattr_init(&my_fast_mutexattr);
pthread_mutexattr_settype(&my_fast_mutexattr,
diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c
index 5fc7ccab4fa..57778574bb6 100644
--- a/mysys/ptr_cmp.c
+++ b/mysys/ptr_cmp.c
@@ -21,6 +21,7 @@
*/
#include "mysys_priv.h"
+#include <myisampack.h>
static int ptr_compare(uint *compare_length, uchar **a, uchar **b);
static int ptr_compare_0(uint *compare_length, uchar **a, uchar **b);
@@ -152,3 +153,41 @@ static int ptr_compare_3(uint *compare_length,uchar **a, uchar **b)
}
return (0);
}
+
+void my_store_ptr(byte *buff, uint pack_length, my_off_t pos)
+{
+ switch (pack_length) {
+#if SIZEOF_OFF_T > 4
+ case 8: mi_int8store(buff,pos); break;
+ case 7: mi_int7store(buff,pos); break;
+ case 6: mi_int6store(buff,pos); break;
+ case 5: mi_int5store(buff,pos); break;
+#endif
+ case 4: mi_int4store(buff,pos); break;
+ case 3: mi_int3store(buff,pos); break;
+ case 2: mi_int2store(buff,pos); break;
+ case 1: buff[0]= (uchar) pos; break;
+ default: DBUG_ASSERT(0);
+ }
+ return;
+}
+
+my_off_t my_get_ptr(byte *ptr, uint pack_length)
+{
+ my_off_t pos;
+ switch (pack_length) {
+#if SIZEOF_OFF_T > 4
+ case 8: pos= (my_off_t) mi_uint8korr(ptr); break;
+ case 7: pos= (my_off_t) mi_uint7korr(ptr); break;
+ case 6: pos= (my_off_t) mi_uint6korr(ptr); break;
+ case 5: pos= (my_off_t) mi_uint5korr(ptr); break;
+#endif
+ case 4: pos= (my_off_t) mi_uint4korr(ptr); break;
+ case 3: pos= (my_off_t) mi_uint3korr(ptr); break;
+ case 2: pos= (my_off_t) mi_uint2korr(ptr); break;
+ case 1: pos= (my_off_t) mi_uint2korr(ptr); break;
+ default: DBUG_ASSERT(0);
+ }
+ return pos;
+}
+
diff --git a/mysys/raid.cc b/mysys/raid.cc
index 62587c438ca..29819a878c4 100644
--- a/mysys/raid.cc
+++ b/mysys/raid.cc
@@ -185,7 +185,7 @@ extern "C" {
uint my_raid_write(File fd,const byte *Buffer, uint Count, myf MyFlags)
{
DBUG_ENTER("my_raid_write");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
+ DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
fd, Buffer, Count, MyFlags));
if (is_raid(fd))
{
@@ -198,7 +198,7 @@ extern "C" {
uint my_raid_read(File fd, byte *Buffer, uint Count, myf MyFlags)
{
DBUG_ENTER("my_raid_read");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
+ DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
fd, Buffer, Count, MyFlags));
if (is_raid(fd))
{
@@ -212,8 +212,9 @@ extern "C" {
myf MyFlags)
{
DBUG_ENTER("my_raid_pread");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d",
- Filedes, Buffer, Count, offset, MyFlags));
+ DBUG_PRINT("enter",
+ ("Fd: %d Buffer: 0x%lx Count: %u offset: %u MyFlags: %d",
+ Filedes, Buffer, Count, offset, MyFlags));
if (is_raid(Filedes))
{
assert(offset != MY_FILEPOS_ERROR);
@@ -231,8 +232,9 @@ extern "C" {
my_off_t offset, myf MyFlags)
{
DBUG_ENTER("my_raid_pwrite");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d",
- Filedes, Buffer, Count, offset, MyFlags));
+ DBUG_PRINT("enter",
+ ("Fd: %d Buffer: 0x %lx Count: %u offset: %u MyFlags: %d",
+ Filedes, Buffer, Count, offset, MyFlags));
if (is_raid(Filedes))
{
assert(offset != MY_FILEPOS_ERROR);
diff --git a/mysys/string.c b/mysys/string.c
index ea747bc9847..dfd42d137dd 100644
--- a/mysys/string.c
+++ b/mysys/string.c
@@ -91,7 +91,7 @@ my_bool dynstr_realloc(DYNAMIC_STRING *str, ulong additional_size)
my_bool dynstr_append(DYNAMIC_STRING *str, const char *append)
{
- return dynstr_append_mem(str,append,strlen(append));
+ return dynstr_append_mem(str,append,(uint) strlen(append));
}
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index d6443539216..41266d61b0a 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -84,6 +84,7 @@ multiple read locks.
my_bool thr_lock_inited=0;
ulong locks_immediate = 0L, locks_waited = 0L;
+ulong table_lock_wait_timeout;
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
/* The following constants are only for debug output */
@@ -109,25 +110,32 @@ my_bool init_thr_lock()
return 0;
}
+static inline my_bool
+thr_lock_owner_equal(THR_LOCK_OWNER *rhs, THR_LOCK_OWNER *lhs)
+{
+ return rhs == lhs;
+}
+
+
#ifdef EXTRA_DEBUG
#define MAX_FOUND_ERRORS 10 /* Report 10 first errors */
static uint found_errors=0;
static int check_lock(struct st_lock_list *list, const char* lock_type,
- const char *where, my_bool same_thread, bool no_cond)
+ const char *where, my_bool same_owner, bool no_cond)
{
THR_LOCK_DATA *data,**prev;
uint count=0;
- pthread_t first_thread;
- LINT_INIT(first_thread);
+ THR_LOCK_OWNER *first_owner;
+ LINT_INIT(first_owner);
prev= &list->data;
if (list->data)
{
enum thr_lock_type last_lock_type=list->data->type;
- if (same_thread && list->data)
- first_thread=list->data->thread;
+ if (same_owner && list->data)
+ first_owner= list->data->owner;
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
{
if (data->type != last_lock_type)
@@ -139,7 +147,8 @@ static int check_lock(struct st_lock_list *list, const char* lock_type,
count, lock_type, where);
return 1;
}
- if (same_thread && ! pthread_equal(data->thread,first_thread) &&
+ if (same_owner &&
+ !thr_lock_owner_equal(data->owner, first_owner) &&
last_lock_type != TL_WRITE_ALLOW_WRITE)
{
fprintf(stderr,
@@ -255,8 +264,8 @@ static void check_locks(THR_LOCK *lock, const char *where,
}
if (lock->read.data)
{
- if (!pthread_equal(lock->write.data->thread,
- lock->read.data->thread) &&
+ if (!thr_lock_owner_equal(lock->write.data->owner,
+ lock->read.data->owner) &&
((lock->write.data->type > TL_WRITE_DELAYED &&
lock->write.data->type != TL_WRITE_ONLY) ||
((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT ||
@@ -330,24 +339,32 @@ void thr_lock_delete(THR_LOCK *lock)
DBUG_VOID_RETURN;
}
+
+void thr_lock_info_init(THR_LOCK_INFO *info)
+{
+ info->thread= pthread_self();
+ info->thread_id= my_thread_id(); /* for debugging */
+ info->n_cursors= 0;
+}
+
/* Initialize a lock instance */
void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, void *param)
{
data->lock=lock;
data->type=TL_UNLOCK;
- data->thread=pthread_self();
- data->thread_id=my_thread_id(); /* for debugging */
+ data->owner= 0; /* no owner yet */
data->status_param=param;
data->cond=0;
}
-static inline my_bool have_old_read_lock(THR_LOCK_DATA *data,pthread_t thread)
+static inline my_bool
+have_old_read_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner)
{
for ( ; data ; data=data->next)
{
- if ((pthread_equal(data->thread,thread)))
+ if (thr_lock_owner_equal(data->owner, owner))
return 1; /* Already locked by thread */
}
return 0;
@@ -365,12 +382,15 @@ static inline my_bool have_specific_lock(THR_LOCK_DATA *data,
}
-static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
- my_bool in_wait_list)
+static enum enum_thr_lock_result
+wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
+ my_bool in_wait_list)
{
- pthread_cond_t *cond=get_cond();
- struct st_my_thread_var *thread_var=my_thread_var;
- int result;
+ struct st_my_thread_var *thread_var= my_thread_var;
+ pthread_cond_t *cond= &thread_var->suspend;
+ struct timespec wait_timeout;
+ enum enum_thr_lock_result result= THR_LOCK_ABORTED;
+ my_bool can_deadlock= test(data->owner->info->n_cursors);
if (!in_wait_list)
{
@@ -382,34 +402,55 @@ static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
/* Set up control struct to allow others to abort locks */
thread_var->current_mutex= &data->lock->mutex;
thread_var->current_cond= cond;
+ data->cond= cond;
- data->cond=cond;
+ if (can_deadlock)
+ set_timespec(wait_timeout, table_lock_wait_timeout);
while (!thread_var->abort || in_wait_list)
{
- pthread_cond_wait(cond,&data->lock->mutex);
- if (data->cond != cond)
+ int rc= can_deadlock ? pthread_cond_timedwait(cond, &data->lock->mutex,
+ &wait_timeout) :
+ pthread_cond_wait(cond, &data->lock->mutex);
+ /*
+ We must break the wait if one of the following occurs:
+ - the connection has been aborted (!thread_var->abort), but
+ this is not a delayed insert thread (in_wait_list). For a delayed
+ insert thread the proper action at shutdown is, apparently, to
+ acquire the lock and complete the insert.
+ - the lock has been granted (data->cond is set to NULL by the granter),
+ or the waiting has been aborted (additionally data->type is set to
+ TL_UNLOCK).
+ - the wait has timed out (rc == ETIMEDOUT)
+ Order of checks below is important to not report about timeout
+ if the predicate is true.
+ */
+ if (data->cond == 0)
+ break;
+ if (rc == ETIMEDOUT)
+ {
+ result= THR_LOCK_WAIT_TIMEOUT;
break;
+ }
}
if (data->cond || data->type == TL_UNLOCK)
{
- if (data->cond) /* aborted */
+ if (data->cond) /* aborted or timed out */
{
if (((*data->prev)=data->next)) /* remove from wait-list */
data->next->prev= data->prev;
else
wait->last=data->prev;
+ data->type= TL_UNLOCK; /* No lock */
}
- data->type=TL_UNLOCK; /* No lock */
- result=1; /* Didn't get lock */
check_locks(data->lock,"failed wait_for_lock",0);
}
else
{
- result=0;
+ result= THR_LOCK_SUCCESS;
statistic_increment(locks_waited, &THR_LOCK_lock);
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
check_locks(data->lock,"got wait_for_lock",0);
}
pthread_mutex_unlock(&data->lock->mutex);
@@ -423,20 +464,24 @@ static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
}
-int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
+enum enum_thr_lock_result
+thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
+ enum thr_lock_type lock_type)
{
THR_LOCK *lock=data->lock;
- int result=0;
+ enum enum_thr_lock_result result= THR_LOCK_SUCCESS;
+ struct st_lock_list *wait_queue;
+ THR_LOCK_DATA *lock_owner;
DBUG_ENTER("thr_lock");
data->next=0;
data->cond=0; /* safety */
data->type=lock_type;
- data->thread=pthread_self(); /* Must be reset ! */
- data->thread_id=my_thread_id(); /* Must be reset ! */
+ data->owner= owner; /* Must be reset ! */
VOID(pthread_mutex_lock(&lock->mutex));
DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx type: %d",
- data,data->thread_id,lock,(int) lock_type));
+ data, data->owner->info->thread_id,
+ lock, (int) lock_type));
check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ?
"enter read_lock" : "enter write_lock",0);
if ((int) lock_type <= (int) TL_READ_NO_INSERT)
@@ -454,8 +499,8 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
*/
DBUG_PRINT("lock",("write locked by thread: %ld",
- lock->write.data->thread_id));
- if (pthread_equal(data->thread,lock->write.data->thread) ||
+ lock->write.data->owner->info->thread_id));
+ if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
(lock->write.data->type <= TL_WRITE_DELAYED &&
(((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) ||
(lock->write.data->type != TL_WRITE_CONCURRENT_INSERT &&
@@ -464,11 +509,11 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
(*lock->read.last)=data; /* Add to running FIFO */
data->prev=lock->read.last;
lock->read.last= &data->next;
- if ((int) lock_type == (int) TL_READ_NO_INSERT)
+ if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count++;
check_locks(lock,"read lock with old write lock",0);
if (lock->get_status)
- (*lock->get_status)(data->status_param);
+ (*lock->get_status)(data->status_param, 0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
@@ -476,28 +521,32 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
{
/* We are not allowed to get a READ lock in this case */
data->type=TL_UNLOCK;
- result=1; /* Can't wait for this one */
+ result= THR_LOCK_ABORTED; /* Can't wait for this one */
goto end;
}
}
else if (!lock->write_wait.data ||
lock->write_wait.data->type <= TL_WRITE_LOW_PRIORITY ||
lock_type == TL_READ_HIGH_PRIORITY ||
- have_old_read_lock(lock->read.data,data->thread))
+ have_old_read_lock(lock->read.data, data->owner))
{ /* No important write-locks */
(*lock->read.last)=data; /* Add to running FIFO */
data->prev=lock->read.last;
lock->read.last= &data->next;
if (lock->get_status)
- (*lock->get_status)(data->status_param);
- if ((int) lock_type == (int) TL_READ_NO_INSERT)
+ (*lock->get_status)(data->status_param, 0);
+ if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count++;
check_locks(lock,"read lock with no write locks",0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
- /* Can't get lock yet; Wait for it */
- DBUG_RETURN(wait_for_lock(&lock->read_wait,data,0));
+ /*
+ We're here if there is an active write lock or no write
+ lock but a high priority write waiting in the write_wait queue.
+ In the latter case we should yield the lock to the writer.
+ */
+ wait_queue= &lock->read_wait;
}
else /* Request for WRITE lock */
{
@@ -506,7 +555,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
if (lock->write.data && lock->write.data->type == TL_WRITE_ONLY)
{
data->type=TL_UNLOCK;
- result=1; /* Can't wait for this one */
+ result= THR_LOCK_ABORTED; /* Can't wait for this one */
goto end;
}
/*
@@ -523,8 +572,10 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
data->prev=lock->write_wait.last;
lock->write_wait.last= &data->next;
data->cond=get_cond();
- if (lock->get_status)
- (*lock->get_status)(data->status_param);
+ /*
+ We don't have to do get_status here as we will do it when we change
+ the delayed lock to a real write lock
+ */
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
@@ -538,7 +589,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
{
/* We are not allowed to get a lock in this case */
data->type=TL_UNLOCK;
- result=1; /* Can't wait for this one */
+ result= THR_LOCK_ABORTED; /* Can't wait for this one */
goto end;
}
@@ -547,7 +598,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
TL_WRITE_ALLOW_WRITE, TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED in
the same thread, but this will never happen within MySQL.
*/
- if (pthread_equal(data->thread,lock->write.data->thread) ||
+ if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
(lock_type == TL_WRITE_ALLOW_WRITE &&
!lock->write_wait.data &&
lock->write.data->type == TL_WRITE_ALLOW_WRITE))
@@ -565,12 +616,12 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
lock->write.last= &data->next;
check_locks(lock,"second write lock",0);
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
DBUG_PRINT("lock",("write locked by thread: %ld",
- lock->write.data->thread_id));
+ lock->write.data->owner->info->thread_id));
}
else
{
@@ -578,9 +629,16 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
(ulong) lock->write_wait.data));
if (!lock->write_wait.data)
{ /* no scheduled write locks */
- if (lock_type == TL_WRITE_CONCURRENT_INSERT &&
- (*lock->check_status)(data->status_param))
- data->type=lock_type= thr_upgraded_concurrent_insert_lock;
+ my_bool concurrent_insert= 0;
+ if (lock_type == TL_WRITE_CONCURRENT_INSERT)
+ {
+ concurrent_insert= 1;
+ if ((*lock->check_status)(data->status_param))
+ {
+ concurrent_insert= 0;
+ data->type=lock_type= thr_upgraded_concurrent_insert_lock;
+ }
+ }
if (!lock->read.data ||
(lock_type <= TL_WRITE_DELAYED &&
@@ -592,17 +650,31 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
data->prev=lock->write.last;
lock->write.last= &data->next;
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, concurrent_insert);
check_locks(lock,"only write lock",0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
}
DBUG_PRINT("lock",("write locked by thread: %ld, type: %ld",
- lock->read.data->thread_id,data->type));
+ lock->read.data->owner->info->thread_id, data->type));
}
- DBUG_RETURN(wait_for_lock(&lock->write_wait,data,0));
+ wait_queue= &lock->write_wait;
}
+ /*
+ Try to detect a trivial deadlock when using cursors: attempt to
+ lock a table that is already locked by an open cursor within the
+ same connection. lock_owner can be zero if we succumbed to a high
+ priority writer in the write_wait queue.
+ */
+ lock_owner= lock->read.data ? lock->read.data : lock->write.data;
+ if (lock_owner && lock_owner->owner->info == owner->info)
+ {
+ result= THR_LOCK_DEADLOCK;
+ goto end;
+ }
+ /* Can't get lock yet; Wait for it */
+ DBUG_RETURN(wait_for_lock(wait_queue, data, 0));
end:
pthread_mutex_unlock(&lock->mutex);
DBUG_RETURN(result);
@@ -647,7 +719,7 @@ static inline void free_all_read_locks(THR_LOCK *lock,
lock->read_no_write_count++;
}
DBUG_PRINT("lock",("giving read lock to thread: %ld",
- data->thread_id));
+ data->owner->info->thread_id));
data->cond=0; /* Mark thread free */
VOID(pthread_cond_signal(cond));
} while ((data=data->next));
@@ -665,7 +737,7 @@ void thr_unlock(THR_LOCK_DATA *data)
enum thr_lock_type lock_type=data->type;
DBUG_ENTER("thr_unlock");
DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx",
- data,data->thread_id,lock));
+ data, data->owner->info->thread_id, lock));
pthread_mutex_lock(&lock->mutex);
check_locks(lock,"start of release lock",0);
@@ -675,8 +747,10 @@ void thr_unlock(THR_LOCK_DATA *data)
lock->read.last=data->prev;
else if (lock_type == TL_WRITE_DELAYED && data->cond)
{
- /* This only happens in extreme circumstances when a
- write delayed lock that is waiting for a lock */
+ /*
+ This only happens in extreme circumstances when a
+ write delayed lock that is waiting for a lock
+ */
lock->write_wait.last=data->prev; /* Put it on wait queue */
}
else
@@ -723,7 +797,7 @@ void thr_unlock(THR_LOCK_DATA *data)
(*lock->check_status)(data->status_param))
data->type=TL_WRITE; /* Upgrade lock */
DBUG_PRINT("lock",("giving write lock of type %d to thread: %ld",
- data->type,data->thread_id));
+ data->type, data->owner->info->thread_id));
{
pthread_cond_t *cond=data->cond;
data->cond=0; /* Mark thread free */
@@ -831,7 +905,8 @@ static void sort_locks(THR_LOCK_DATA **data,uint count)
}
-int thr_multi_lock(THR_LOCK_DATA **data,uint count)
+enum enum_thr_lock_result
+thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner)
{
THR_LOCK_DATA **pos,**end;
DBUG_ENTER("thr_multi_lock");
@@ -841,10 +916,11 @@ int thr_multi_lock(THR_LOCK_DATA **data,uint count)
/* lock everything */
for (pos=data,end=data+count; pos < end ; pos++)
{
- if (thr_lock(*pos,(*pos)->type))
+ enum enum_thr_lock_result result= thr_lock(*pos, owner, (*pos)->type);
+ if (result != THR_LOCK_SUCCESS)
{ /* Aborted */
thr_multi_unlock(data,(uint) (pos-data));
- DBUG_RETURN(1);
+ DBUG_RETURN(result);
}
#ifdef MAIN
printf("Thread: %s Got lock: 0x%lx type: %d\n",my_thread_name(),
@@ -898,7 +974,7 @@ int thr_multi_lock(THR_LOCK_DATA **data,uint count)
} while (pos != data);
}
#endif
- DBUG_RETURN(0);
+ DBUG_RETURN(THR_LOCK_SUCCESS);
}
/* free all locks */
@@ -921,7 +997,7 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
else
{
DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: %ld lock: 0x%lx",
- *pos,(*pos)->thread_id,(*pos)->lock));
+ *pos, (*pos)->owner->info->thread_id, (*pos)->lock));
}
}
DBUG_VOID_RETURN;
@@ -941,6 +1017,7 @@ void thr_abort_locks(THR_LOCK *lock)
for (data=lock->read_wait.data; data ; data=data->next)
{
data->type=TL_UNLOCK; /* Mark killed */
+ /* It's safe to signal the cond first: we're still holding the mutex. */
pthread_cond_signal(data->cond);
data->cond=0; /* Removed from list */
}
@@ -975,10 +1052,11 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread)
pthread_mutex_lock(&lock->mutex);
for (data= lock->read_wait.data; data ; data= data->next)
{
- if (pthread_equal(thread, data->thread))
+ if (pthread_equal(thread, data->owner->info->thread))
{
DBUG_PRINT("info",("Aborting read-wait lock"));
data->type= TL_UNLOCK; /* Mark killed */
+ /* It's safe to signal the cond first: we're still holding the mutex. */
found= TRUE;
pthread_cond_signal(data->cond);
data->cond= 0; /* Removed from list */
@@ -991,7 +1069,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread)
}
for (data= lock->write_wait.data; data ; data= data->next)
{
- if (pthread_equal(thread, data->thread))
+ if (pthread_equal(thread, data->owner->info->thread))
{
DBUG_PRINT("info",("Aborting write-wait lock"));
data->type= TL_UNLOCK;
@@ -1034,7 +1112,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
if (!lock->read.data) /* No read locks */
{ /* We have the lock */
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
pthread_mutex_unlock(&lock->mutex);
DBUG_RETURN(0);
}
@@ -1109,7 +1187,8 @@ static void thr_print_lock(const char* name,struct st_lock_list *list)
prev= &list->data;
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
{
- printf("0x%lx (%lu:%d); ",(ulong) data,data->thread_id,(int) data->type);
+ printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->info->thread_id,
+ (int) data->type);
if (data->prev != prev)
printf("\nWarning: prev didn't point at previous lock\n");
prev= &data->next;
@@ -1223,7 +1302,8 @@ static ulong sum=0;
/* The following functions is for WRITE_CONCURRENT_INSERT */
-static void test_get_status(void* param __attribute__((unused)))
+static void test_get_status(void* param __attribute__((unused)),
+ int concurrent_insert __attribute__((unused)))
{
}
@@ -1242,11 +1322,16 @@ static void *test_thread(void *arg)
{
int i,j,param=*((int*) arg);
THR_LOCK_DATA data[MAX_LOCK_COUNT];
+ THR_LOCK_OWNER owner;
+ THR_LOCK_INFO lock_info;
THR_LOCK_DATA *multi_locks[MAX_LOCK_COUNT];
my_thread_init();
printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout);
+
+ thr_lock_info_init(&lock_info);
+ thr_lock_owner_init(&owner, &lock_info);
for (i=0; i < lock_counts[param] ; i++)
thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL);
for (j=1 ; j < 10 ; j++) /* try locking 10 times */
@@ -1256,7 +1341,7 @@ static void *test_thread(void *arg)
multi_locks[i]= &data[i];
data[i].type= tests[param][i].lock_type;
}
- thr_multi_lock(multi_locks,lock_counts[param]);
+ thr_multi_lock(multi_locks, lock_counts[param], &owner);
pthread_mutex_lock(&LOCK_thread_count);
{
int tmp=rand() & 7; /* Do something from 0-2 sec */
diff --git a/mysys/tree.c b/mysys/tree.c
index bec1ec680f1..1780913961e 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -263,6 +263,9 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
if (tree->flag & TREE_NO_DUPS)
return(NULL);
element->count++;
+ /* Avoid a wrap over of the count. */
+ if (! element->count)
+ element->count--;
}
DBUG_EXECUTE("check_tree", test_rb_tree(tree->root););
return element;
diff --git a/ndb/Makefile.am b/ndb/Makefile.am
index 32c821383e6..3aac54b38ee 100644
--- a/ndb/Makefile.am
+++ b/ndb/Makefile.am
@@ -1,12 +1,13 @@
SUBDIRS = src tools . include @ndb_opt_subdirs@
DIST_SUBDIRS = src tools include test docs
-EXTRA_DIST = config
+EXTRA_DIST = config ndbapi-examples
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`
+ -rm -rf `find $(distdir)/ndbapi-examples -name '*.o'`
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" != "." -a "$$subdir" != "include"; then \
files="`find $$subdir -name '*\.h'` `find $$subdir -name '*\.hpp'`"; \
diff --git a/ndb/docs/Makefile.am b/ndb/docs/Makefile.am
index 1399ce3b6a5..afa91857771 100644
--- a/ndb/docs/Makefile.am
+++ b/ndb/docs/Makefile.am
@@ -1,18 +1,19 @@
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
+all: do-check-html ndbapidoc-html mgmapidoc-html
+all-pdf: do-check-pdf ndbapidoc-pdf mgmapidoc-pdf
DOXYTMP = .doxytmp
DOXYOUT = .doxyout
NDB_RELEASE = @NDB_VERSION_MAJOR@.@NDB_VERSION_MINOR@.@NDB_VERSION_BUILD@-@NDB_VERSION_STATUS@
-clean:
+clean-local:
rm -rf ndbapi.pdf ndbapi.html mgmapi.pdf mgmapi.html
rm -rf $(DOXYTMP) $(DOXYOUT)
-do-check:
+do-check-html:
@set -x; \
if test @PERL@ = no ; then \
echo "Perl needed to make docs"; \
@@ -21,7 +22,9 @@ do-check:
if test @DOXYGEN@ = no ; then \
echo "Doxygen needed to make docs"; \
exit 1; \
- fi; \
+ fi;
+
+do-check-pdf: do-check-html
if test @PDFLATEX@ = no ; then \
echo "Pdflatex needed to make docs"; \
exit 1; \
@@ -30,26 +33,30 @@ do-check:
echo "Makeindex needed to make docs"; \
exit 1; \
fi;
+
###
#
# NDB API Programmer's Guide
#
-ndbapidoc: ndbapi.pdf
+ndbapidoc-html: ndbapi.html
+ndbapidoc-pdf: ndbapi.pdf
-ndbapi.pdf: $(noinst_HEADERS)
+ndbapi.html: $(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); \
+ @CP@ $(top_srcdir)/ndb/ndbapi-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"; \
+ @PERL@ $(DOXYDIR)/postdoxy.pl $(DOXYOUT)/ndbapi.latex "MySQL Cluster NDB API Programmer Guide"; \
(cd $(DOXYOUT) && \
- find ndbapi.html -print | cpio -pdm ..); \
+ find ndbapi.html -print | cpio -pdm ..);
+
+ndbapi.pdf: ndbapi.html
(cd $(DOXYOUT)/ndbapi.latex && \
@PDFLATEX@ refman.tex && @MAKEINDEX@ refman && @PDFLATEX@ refman.tex && \
cp -p refman.pdf ../../ndbapi.pdf);
@@ -58,9 +65,10 @@ ndbapi.pdf: $(noinst_HEADERS)
#
# MGM API Guide
#
-mgmapidoc: mgmapi.pdf
+mgmapidoc-html: mgmapi.html
+mgmapidoc-pdf: mgmapi.pdf
-mgmapi.pdf: $(noinst_HEADERS)
+mgmapi.html: $(noinst_HEADERS)
@set -x; \
export NDB_RELEASE=$(NDB_RELEASE); \
@RM@ -f mgmapi.pdf mgmapi.html; \
@@ -70,9 +78,11 @@ mgmapi.pdf: $(noinst_HEADERS)
@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"; \
+ @PERL@ $(DOXYDIR)/postdoxy.pl $(DOXYOUT)/mgmapi.latex "MySQL Cluster MGM API Guide"; \
(cd $(DOXYOUT) && \
- find mgmapi.html -print | cpio -pdm ..); \
+ find mgmapi.html -print | cpio -pdm ..);
+
+mgmapi.pdf: mgmapi.html
(cd $(DOXYOUT)/mgmapi.latex && \
@PDFLATEX@ refman.tex && @MAKEINDEX@ refman && @PDFLATEX@ refman.tex && \
cp -p refman.pdf ../../mgmapi.pdf);
diff --git a/ndb/docs/doxygen/Doxyfile.mgmapi b/ndb/docs/doxygen/Doxyfile.mgmapi
index 4287b37fd97..1e743dcb60e 100644
--- a/ndb/docs/doxygen/Doxyfile.mgmapi
+++ b/ndb/docs/doxygen/Doxyfile.mgmapi
@@ -59,7 +59,7 @@ EXTRACT_PRIVATE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
-EXTRACT_STATIC = NO
+EXTRACT_STATIC = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
@@ -146,7 +146,7 @@ HIDE_SCOPE_NAMES = NO
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
-VERBATIM_HEADERS = YES
+VERBATIM_HEADERS = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
@@ -190,7 +190,7 @@ DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
-TAB_SIZE = 8
+TAB_SIZE = 2
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
@@ -245,7 +245,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
-SHOW_USED_FILES = YES
+SHOW_USED_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
@@ -447,7 +447,7 @@ HTML_STYLESHEET =
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
-HTML_ALIGN_MEMBERS = YES
+HTML_ALIGN_MEMBERS = NO
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
@@ -477,7 +477,7 @@ TOC_EXPAND = NO
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
-DISABLE_INDEX = NO
+DISABLE_INDEX = YES
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
@@ -688,7 +688,8 @@ INCLUDE_FILE_PATTERNS =
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed.
-PREDEFINED = DOXYGEN_SHOULD_SKIP_DEPRECATED \
+PREDEFINED = DOXYGEN_FIX \
+ DOXYGEN_SHOULD_SKIP_DEPRECATED \
DOXYGEN_SHOULD_SKIP_INTERNAL \
protected=private
diff --git a/ndb/docs/doxygen/Doxyfile.ndb b/ndb/docs/doxygen/Doxyfile.ndb
index d43a66323f8..3986a7cd17f 100644
--- a/ndb/docs/doxygen/Doxyfile.ndb
+++ b/ndb/docs/doxygen/Doxyfile.ndb
@@ -14,6 +14,8 @@
# General configuration options
#---------------------------------------------------------------------------
+DETAILS_AT_TOP = YES
+
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
@@ -52,7 +54,7 @@ EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
-EXTRACT_PRIVATE = YES
+EXTRACT_PRIVATE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
@@ -105,7 +107,7 @@ ALWAYS_DETAILED_SEC = NO
# ordinary class members. Constructors, destructors and assignment operators of
# the base classes will not be shown.
-INLINE_INHERITED_MEMB = NO
+INLINE_INHERITED_MEMB = YES
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
@@ -157,13 +159,13 @@ HIDE_SCOPE_NAMES = NO
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
-VERBATIM_HEADERS = YES
+VERBATIM_HEADERS = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
# of that file.
-SHOW_INCLUDE_FILES = YES
+SHOW_INCLUDE_FILES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
@@ -201,7 +203,7 @@ DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
-TAB_SIZE = 8
+TAB_SIZE = 2
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
@@ -256,7 +258,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
-SHOW_USED_FILES = YES
+SHOW_USED_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
@@ -485,7 +487,7 @@ HTML_STYLESHEET =
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
-HTML_ALIGN_MEMBERS = YES
+HTML_ALIGN_MEMBERS = NO
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
@@ -515,7 +517,7 @@ TOC_EXPAND = NO
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
-DISABLE_INDEX = NO
+DISABLE_INDEX = YES
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
@@ -794,21 +796,21 @@ PERL_PATH = /usr/bin/perl
# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
# recommended to install and use dot, since it yield more powerful graphs.
-CLASS_DIAGRAMS = YES
+CLASS_DIAGRAMS = NO
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
-HAVE_DOT = YES
+HAVE_DOT = NO
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
-CLASS_GRAPH = YES
+CLASS_GRAPH = NO
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
@@ -820,7 +822,7 @@ COLLABORATION_GRAPH = YES
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
-TEMPLATE_RELATIONS = YES
+TEMPLATE_RELATIONS = NO
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
diff --git a/ndb/docs/doxygen/Doxyfile.ndbapi b/ndb/docs/doxygen/Doxyfile.ndbapi
index 61d58d4fea3..da610148468 100644
--- a/ndb/docs/doxygen/Doxyfile.ndbapi
+++ b/ndb/docs/doxygen/Doxyfile.ndbapi
@@ -13,8 +13,8 @@
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
-DETAILS_AT_TOP = yes
-HIDE_FRIEND_COMPOUNDS = yes
+DETAILS_AT_TOP = YES
+HIDE_FRIEND_COMPOUNDS = YES
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
@@ -59,7 +59,7 @@ EXTRACT_PRIVATE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
-EXTRACT_STATIC = NO
+EXTRACT_STATIC = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
@@ -146,7 +146,7 @@ HIDE_SCOPE_NAMES = NO
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
-VERBATIM_HEADERS = YES
+VERBATIM_HEADERS = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
@@ -190,7 +190,7 @@ DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
-TAB_SIZE = 8
+TAB_SIZE = 2
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
@@ -245,7 +245,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
-SHOW_USED_FILES = YES
+SHOW_USED_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
@@ -447,7 +447,7 @@ HTML_STYLESHEET =
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
-HTML_ALIGN_MEMBERS = YES
+HTML_ALIGN_MEMBERS = NO
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
@@ -477,7 +477,7 @@ TOC_EXPAND = NO
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
-DISABLE_INDEX = NO
+DISABLE_INDEX = YES
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
diff --git a/ndb/docs/doxygen/Doxyfile.odbc b/ndb/docs/doxygen/Doxyfile.odbc
index 93e052d5b9d..262513852b7 100644
--- a/ndb/docs/doxygen/Doxyfile.odbc
+++ b/ndb/docs/doxygen/Doxyfile.odbc
@@ -14,6 +14,8 @@
# General configuration options
#---------------------------------------------------------------------------
+DETAILS_AT_TOP = YES
+
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
@@ -52,7 +54,7 @@ EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
-EXTRACT_PRIVATE = YES
+EXTRACT_PRIVATE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
@@ -157,7 +159,7 @@ HIDE_SCOPE_NAMES = NO
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
-VERBATIM_HEADERS = YES
+VERBATIM_HEADERS = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
@@ -201,7 +203,7 @@ DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
-TAB_SIZE = 8
+TAB_SIZE = 2
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
@@ -256,7 +258,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
-SHOW_USED_FILES = YES
+SHOW_USED_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
@@ -469,7 +471,7 @@ HTML_STYLESHEET =
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
-HTML_ALIGN_MEMBERS = YES
+HTML_ALIGN_MEMBERS = NO
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
@@ -499,7 +501,7 @@ TOC_EXPAND = NO
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
-DISABLE_INDEX = NO
+DISABLE_INDEX = YES
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
diff --git a/ndb/docs/doxygen/Doxyfile.test b/ndb/docs/doxygen/Doxyfile.test
index 34ee21873ff..801c82cf380 100644
--- a/ndb/docs/doxygen/Doxyfile.test
+++ b/ndb/docs/doxygen/Doxyfile.test
@@ -14,6 +14,8 @@
# General configuration options
#---------------------------------------------------------------------------
+DETAILS_AT_TOP = YES
+
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
@@ -52,7 +54,7 @@ EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
-EXTRACT_PRIVATE = YES
+EXTRACT_PRIVATE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
@@ -157,7 +159,7 @@ HIDE_SCOPE_NAMES = NO
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
-VERBATIM_HEADERS = YES
+VERBATIM_HEADERS = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put list of the files that are included by a file in the documentation
@@ -201,7 +203,7 @@ DISTRIBUTE_GROUP_DOC = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
-TAB_SIZE = 8
+TAB_SIZE = 2
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
@@ -256,7 +258,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
-SHOW_USED_FILES = YES
+SHOW_USED_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
@@ -469,7 +471,7 @@ HTML_STYLESHEET =
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
-HTML_ALIGN_MEMBERS = YES
+HTML_ALIGN_MEMBERS = NO
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
@@ -499,7 +501,7 @@ TOC_EXPAND = NO
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
-DISABLE_INDEX = NO
+DISABLE_INDEX = YES
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
diff --git a/ndb/docs/doxygen/predoxy.pl b/ndb/docs/doxygen/predoxy.pl
index 8dad1d964d0..3994054dcf6 100755
--- a/ndb/docs/doxygen/predoxy.pl
+++ b/ndb/docs/doxygen/predoxy.pl
@@ -18,7 +18,7 @@ print OUTFILE<<EOT;
<center>
EOT
print OUTFILE "Documentation generated " . localtime() .
- " from NDB Cluster source files.";
+ " from mysql source files.";
print OUTFILE<<EOT;
<br>
&copy; 2003-2004
diff --git a/ndb/examples/configurations/demos.tar b/ndb/examples/configurations/demos.tar
deleted file mode 100644
index d8cae90ec5b..00000000000
--- a/ndb/examples/configurations/demos.tar
+++ /dev/null
Binary files differ
diff --git a/ndb/examples/ndbapi_async_example/Makefile b/ndb/examples/ndbapi_async_example/Makefile
deleted file mode 100644
index f30398f9587..00000000000
--- a/ndb/examples/ndbapi_async_example/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
--include .defs.mk
-#NDB_OS = OS_YOU_ARE_RUNNING_ON
-#NDB_OS = LINUX
-#You need to set the NDB_OS variable here (LINUX, SOLARIS, MACOSX)
-TARGET = ndbapi_async
-SRCS = ndbapi_async.cpp
-OBJS = ndbapi_async.o
-CC = g++
-CFLAGS = -c -Wall -fno-rtti -D$(NDB_OS)
-DEBUG =
-LFLAGS = -Wall
-INCLUDE_DIR = ../../include
-LIB_DIR = ../../lib
-ifeq ($(NDB_OS), SOLARIS)
-# Here is the definition of system libraries necessary for Solaris 7
-SYS_LIB = -lpthread -lsocket -lnsl -lrt
-endif
-ifeq ($(NDB_OS), LINUX)
-# Here is the definition of system libraries necessary for Linux 2.4
-SYS_LIB = -lpthread
-endif
-ifeq ($(NDB_OS), MACOSX)
-# Here is the definition of system libraries necessary for Mac OS X
-SYS_LIB =
-endif
-
-$(TARGET): $(OBJS)
- $(CC) $(LFLAGS) -L$(LIB_DIR) -lNDB_API $(OBJS) $(SYS_LIB) -o $(TARGET)
-
-$(TARGET).o: $(SRCS)
- $(CC) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
-
-clean:
- rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_example1/Makefile b/ndb/examples/ndbapi_example1/Makefile
deleted file mode 100644
index eb0142ce673..00000000000
--- a/ndb/examples/ndbapi_example1/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
--include .defs.mk
-#NDB_OS = OS_YOU_ARE_RUNNING_ON
-#You need to set the NDB_OS variable here
-TARGET = ndbapi_example1
-SRCS = ndbapi_example1.cpp
-OBJS = ndbapi_example1.o
-CXX = g++
-CFLAGS = -c -Wall -fno-rtti -fno-exceptions
-DEBUG =
-LFLAGS = -Wall
-INCLUDE_DIR = ../../include
-LIB_DIR = ../../lib
-ifeq ($(NDB_OS), SOLARIS)
-# Here is the definition of system libraries necessary for Solaris 7
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), LINUX)
-# Here is the definition of system libraries necessary for Linux 2.4
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), MACOSX)
-# Here is the definition of system libraries necessary for Mac OS X
-SYS_LIB =
-endif
-
-$(TARGET): $(OBJS)
- $(CXX) $(LFLAGS) -L$(LIB_DIR) $(OBJS) -lNDB_API $(SYS_LIB) -o $(TARGET)
-
-$(TARGET).o: $(SRCS)
- $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
-
-clean:
- rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_example1/ndbapi_example1.cpp b/ndb/examples/ndbapi_example1/ndbapi_example1.cpp
deleted file mode 100644
index 03a84aa249b..00000000000
--- a/ndb/examples/ndbapi_example1/ndbapi_example1.cpp
+++ /dev/null
@@ -1,194 +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 */
-
-//
-// ndbapi_example1.cpp: Using synchronous transactions in NDB API
-//
-// Correct output from this program is:
-//
-// ATTR1 ATTR2
-// 0 10
-// 1 1
-// 2 12
-// Detected that deleted tuple doesn't exist!
-// 4 14
-// 5 5
-// 6 16
-// 7 7
-// 8 18
-// 9 9
-
-#include <NdbApi.hpp>
-
-// Used for cout
-#include <stdio.h>
-#include <iostream>
-
-#define APIERROR(error) \
- { std::cout << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
- << error.code << ", msg: " << error.message << "." << std::endl; \
- exit(-1); }
-
-int main()
-{
- ndb_init();
- Ndb* myNdb = new Ndb( "TEST_DB_1" ); // Object representing the database
- NdbDictionary::Table myTable;
- NdbDictionary::Column myColumn;
-
- NdbConnection *myConnection; // For other transactions
- NdbOperation *myOperation; // For other operations
- NdbRecAttr *myRecAttr; // Result of reading attribute value
-
- /********************************************
- * Initialize NDB and wait until it's ready *
- ********************************************/
- if (myNdb->init() == -1) {
- APIERROR(myNdb->getNdbError());
- exit(-1);
- }
-
- if (myNdb->waitUntilReady(30) != 0) {
- std::cout << "NDB was not ready within 30 secs." << std::endl;
- exit(-1);
- }
-
- NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
-
- /*********************************************************
- * Create a table named MYTABLENAME if it does not exist *
- *********************************************************/
- if (myDict->getTable("MYTABLENAME") != NULL) {
- std::cout << "NDB already has example table: MYTABLENAME." << std::endl;
- exit(-1);
- }
-
- myTable.setName("MYTABLENAME");
-
- myColumn.setName("ATTR1");
- myColumn.setType(NdbDictionary::Column::Unsigned);
- myColumn.setLength(1);
- myColumn.setPrimaryKey(true);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
- myColumn.setName("ATTR2");
- myColumn.setType(NdbDictionary::Column::Unsigned);
- myColumn.setLength(1);
- myColumn.setPrimaryKey(false);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
- if (myDict->createTable(myTable) == -1)
- APIERROR(myDict->getNdbError());
-
- /**************************************************************************
- * Using 5 transactions, insert 10 tuples in table: (0,0),(1,1),...,(9,9) *
- **************************************************************************/
- for (int i = 0; i < 5; i++) {
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
- if (myOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myOperation->insertTuple();
- myOperation->equal("ATTR1", i);
- myOperation->setValue("ATTR2", i);
-
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
- if (myOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myOperation->insertTuple();
- myOperation->equal("ATTR1", i+5);
- myOperation->setValue("ATTR2", i+5);
-
- if (myConnection->execute( Commit ) == -1)
- APIERROR(myConnection->getNdbError());
-
- myNdb->closeTransaction(myConnection);
- }
-
- /*****************************************************************
- * Update the second attribute in half of the tuples (adding 10) *
- *****************************************************************/
- for (int i = 0; i < 10; i+=2) {
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
- if (myOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myOperation->updateTuple();
- myOperation->equal( "ATTR1", i );
- myOperation->setValue( "ATTR2", i+10);
-
- if( myConnection->execute( Commit ) == -1 )
- APIERROR(myConnection->getNdbError());
-
- myNdb->closeTransaction(myConnection);
- }
-
- /*************************************************
- * Delete one tuple (the one with primary key 3) *
- *************************************************/
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
- if (myOperation == NULL)
- APIERROR(myConnection->getNdbError());
-
- myOperation->deleteTuple();
- myOperation->equal( "ATTR1", 3 );
-
- if (myConnection->execute(Commit) == -1)
- APIERROR(myConnection->getNdbError());
-
- myNdb->closeTransaction(myConnection);
-
- /*****************************
- * Read and print all tuples *
- *****************************/
- std::cout << "ATTR1 ATTR2" << std::endl;
-
- for (int i = 0; i < 10; i++) {
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
- if (myOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myOperation->readTuple();
- myOperation->equal("ATTR1", i);
-
- myRecAttr = myOperation->getValue("ATTR2", NULL);
- if (myRecAttr == NULL) APIERROR(myConnection->getNdbError());
-
- if(myConnection->execute( Commit ) == -1)
- if (i == 3) {
- std::cout << "Detected that deleted tuple doesn't exist!" << std::endl;
- } else {
- APIERROR(myConnection->getNdbError());
- }
-
- if (i != 3) {
- printf(" %2d %2d\n", i, myRecAttr->u_32_value());
- }
- myNdb->closeTransaction(myConnection);
- }
- delete myNdb;
-}
diff --git a/ndb/examples/ndbapi_example2/Makefile b/ndb/examples/ndbapi_example2/Makefile
deleted file mode 100644
index 17b2b1528fc..00000000000
--- a/ndb/examples/ndbapi_example2/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
--include .defs.mk
-#NDB_OS = OS_YOU_ARE_RUNNING_ON
-#You need to set the NDB_OS variable here
-TARGET = ndbapi_example2
-SRCS = ndbapi_example2.cpp
-OBJS = ndbapi_example2.o
-CXX = g++
-CFLAGS = -c -Wall -fno-rtti -fno-exceptions
-DEBUG =
-LFLAGS = -Wall
-INCLUDE_DIR = ../../include
-LIB_DIR = ../../lib
-ifeq ($(NDB_OS), SOLARIS)
-# Here is the definition of system libraries necessary for Solaris 7
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), LINUX)
-# Here is the definition of system libraries necessary for Linux 2.4
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), MACOSX)
-# Here is the definition of system libraries necessary for Mac OS X
-SYS_LIB =
-endif
-
-$(TARGET): $(OBJS)
- $(CXX) $(LFLAGS) -L$(LIB_DIR) $(OBJS) -lNDB_API $(SYS_LIB) -o $(TARGET)
-
-$(TARGET).o: $(SRCS)
- $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
-
-clean:
- rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_example3/Makefile b/ndb/examples/ndbapi_example3/Makefile
deleted file mode 100644
index bd6f0182aa4..00000000000
--- a/ndb/examples/ndbapi_example3/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
--include .defs.mk
-#NDB_OS = OS_YOU_ARE_RUNNING_ON
-#You need to set the NDB_OS variable here
-TARGET = ndbapi_example3
-SRCS = ndbapi_example3.cpp
-OBJS = ndbapi_example3.o
-CXX = g++
-CFLAGS = -c -Wall -fno-rtti -fno-exceptions
-DEBUG =
-LFLAGS = -Wall
-INCLUDE_DIR = ../../include
-LIB_DIR = ../../lib
-ifeq ($(NDB_OS), SOLARIS)
-# Here is the definition of system libraries necessary for Solaris 7
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), LINUX)
-# Here is the definition of system libraries necessary for Linux 2.4
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), MACOSX)
-# Here is the definition of system libraries necessary for Mac OS X
-SYS_LIB =
-endif
-
-$(TARGET): $(OBJS)
- $(CXX) $(LFLAGS) -L$(LIB_DIR) $(OBJS) -lNDB_API $(SYS_LIB) -o $(TARGET)
-
-$(TARGET).o: $(SRCS)
- $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
-
-clean:
- rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_example4/Makefile b/ndb/examples/ndbapi_example4/Makefile
deleted file mode 100644
index b0ce852d347..00000000000
--- a/ndb/examples/ndbapi_example4/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
--include .defs.mk
-#NDB_OS = OS_YOU_ARE_RUNNING_ON
-#You need to set the NDB_OS variable here
-TARGET = ndbapi_example4
-SRCS = ndbapi_example4.cpp
-OBJS = ndbapi_example4.o
-CXX = g++
-CFLAGS = -c -Wall -fno-rtti -fno-exceptions
-DEBUG =
-LFLAGS = -Wall
-INCLUDE_DIR = ../../include
-LIB_DIR = ../../lib
-ifeq ($(NDB_OS), SOLARIS)
-# Here is the definition of system libraries necessary for Solaris 7
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), LINUX)
-# Here is the definition of system libraries necessary for Linux 2.4
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), MACOSX)
-# Here is the definition of system libraries necessary for Mac OS X
-SYS_LIB =
-endif
-
-$(TARGET): $(OBJS)
- $(CXX) $(LFLAGS) -L$(LIB_DIR) $(OBJS) -lNDB_API $(SYS_LIB) -o $(TARGET)
-
-$(TARGET).o: $(SRCS)
- $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
-
-clean:
- rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_example4/ndbapi_example4.cpp b/ndb/examples/ndbapi_example4/ndbapi_example4.cpp
deleted file mode 100644
index fcb770d49e9..00000000000
--- a/ndb/examples/ndbapi_example4/ndbapi_example4.cpp
+++ /dev/null
@@ -1,253 +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 */
-
-//
-// ndbapi_example4.cpp: Using secondary indexes in NDB API
-//
-// Correct output from this program is:
-//
-// ATTR1 ATTR2
-// 0 10
-// 1 1
-// 2 12
-// Detected that deleted tuple doesn't exist!
-// 4 14
-// 5 5
-// 6 16
-// 7 7
-// 8 18
-// 9 9
-
-#include <NdbApi.hpp>
-
-// Used for cout
-#include <stdio.h>
-#include <iostream>
-
-#define APIERROR(error) \
- { std::cout << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
- << error.code << ", msg: " << error.message << "." << std::endl; \
- exit(-1); }
-
-int main()
-{
- ndb_init();
- Ndb* myNdb = new Ndb( "TEST_DB_1" ); // Object representing the database
- NdbDictionary::Table myTable;
- NdbDictionary::Column myColumn;
- NdbDictionary::Index myIndex;
-
- NdbConnection *myConnection; // For transactions
- NdbOperation *myOperation; // For primary key operations
- NdbIndexOperation *myIndexOperation; // For index operations
- NdbRecAttr *myRecAttr; // Result of reading attribute value
-
- /********************************************
- * Initialize NDB and wait until it's ready *
- ********************************************/
- if (myNdb->init() == -1) {
- APIERROR(myNdb->getNdbError());
- exit(-1);
- }
-
- if (myNdb->waitUntilReady(30) != 0) {
- std::cout << "NDB was not ready within 30 secs." << std::endl;
- exit(-1);
- }
-
- /*********************************************************
- * Create a table named MYTABLENAME if it does not exist *
- *********************************************************/
- NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
- if (myDict->getTable("MYTABLENAME") != NULL) {
- std::cout << "NDB already has example table: MYTABLENAME." << std::endl;
- exit(-1);
- }
-
- myTable.setName("MYTABLENAME");
-
- myColumn.setName("ATTR1");
- myColumn.setType(NdbDictionary::Column::Unsigned);
- myColumn.setLength(1);
- myColumn.setPrimaryKey(true);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
- myColumn.setName("ATTR2");
- myColumn.setType(NdbDictionary::Column::Unsigned);
- myColumn.setLength(1);
- myColumn.setPrimaryKey(false);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
- if (myDict->createTable(myTable) == -1)
- APIERROR(myDict->getNdbError());
-
-
- /**********************************************************
- * Create an index named MYINDEXNAME if it does not exist *
- **********************************************************/
- if (myDict->getIndex("MYINDEXNAME", "MYTABLENAME") != NULL) {
- std::cout << "NDB already has example index: MYINDEXNAME." << std::endl;
- exit(-1);
- }
-
- myIndex.setName("MYINDEXNAME");
- myIndex.setTable("MYTABLENAME");
- myIndex.setType(NdbDictionary::Index::UniqueHashIndex);
- const char* attr_arr[] = {"ATTR2"};
- myIndex.addIndexColumns(1, attr_arr);
-
- if (myDict->createIndex(myIndex) == -1)
- APIERROR(myDict->getNdbError());
-
-
- /**************************************************************************
- * Using 5 transactions, insert 10 tuples in table: (0,0),(1,1),...,(9,9) *
- **************************************************************************/
- for (int i = 0; i < 5; i++) {
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
- if (myOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myOperation->insertTuple();
- myOperation->equal("ATTR1", i);
- myOperation->setValue("ATTR2", i);
-
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
- if (myOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myOperation->insertTuple();
- myOperation->equal("ATTR1", i+5);
- myOperation->setValue("ATTR2", i+5);
-
- if (myConnection->execute( Commit ) == -1)
- APIERROR(myConnection->getNdbError());
-
- myNdb->closeTransaction(myConnection);
- }
-
- /*****************************************
- * Read and print all tuples using index *
- *****************************************/
- std::cout << "ATTR1 ATTR2" << std::endl;
-
- for (int i = 0; i < 10; i++) {
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myIndexOperation = myConnection->getNdbIndexOperation("MYINDEXNAME",
- "MYTABLENAME");
- if (myIndexOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myIndexOperation->readTuple();
- myIndexOperation->equal("ATTR2", i);
-
- myRecAttr = myIndexOperation->getValue("ATTR1", NULL);
- if (myRecAttr == NULL) APIERROR(myConnection->getNdbError());
-
- if(myConnection->execute( Commit ) != -1)
- printf(" %2d %2d\n", myRecAttr->u_32_value(), i);
- }
- myNdb->closeTransaction(myConnection);
-
- /*****************************************************************
- * Update the second attribute in half of the tuples (adding 10) *
- *****************************************************************/
- for (int i = 0; i < 10; i+=2) {
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myIndexOperation = myConnection->getNdbIndexOperation("MYINDEXNAME",
- "MYTABLENAME");
- if (myIndexOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myIndexOperation->updateTuple();
- myIndexOperation->equal( "ATTR2", i );
- myIndexOperation->setValue( "ATTR2", i+10);
-
- if( myConnection->execute( Commit ) == -1 )
- APIERROR(myConnection->getNdbError());
-
- myNdb->closeTransaction(myConnection);
- }
-
- /*************************************************
- * Delete one tuple (the one with primary key 3) *
- *************************************************/
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myIndexOperation = myConnection->getNdbIndexOperation("MYINDEXNAME",
- "MYTABLENAME");
- if (myIndexOperation == NULL)
- APIERROR(myConnection->getNdbError());
-
- myIndexOperation->deleteTuple();
- myIndexOperation->equal( "ATTR2", 3 );
-
- if (myConnection->execute(Commit) == -1)
- APIERROR(myConnection->getNdbError());
-
- myNdb->closeTransaction(myConnection);
-
- /*****************************
- * Read and print all tuples *
- *****************************/
- std::cout << "ATTR1 ATTR2" << std::endl;
-
- for (int i = 0; i < 10; i++) {
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
- if (myOperation == NULL) APIERROR(myConnection->getNdbError());
-
- myOperation->readTuple();
- myOperation->equal("ATTR1", i);
-
- myRecAttr = myOperation->getValue("ATTR2", NULL);
- if (myRecAttr == NULL) APIERROR(myConnection->getNdbError());
-
- if(myConnection->execute( Commit ) == -1)
- if (i == 3) {
- std::cout << "Detected that deleted tuple doesn't exist!" << std::endl;
- } else {
- APIERROR(myConnection->getNdbError());
- }
-
- if (i != 3) {
- printf(" %2d %2d\n", i, myRecAttr->u_32_value());
- }
- myNdb->closeTransaction(myConnection);
- }
-
- /**************
- * Drop index *
- **************/
- if (myDict->dropIndex("MYINDEXNAME", "MYTABLENAME") == -1)
- APIERROR(myDict->getNdbError());
-
- /**************
- * Drop table *
- **************/
- if (myDict->dropTable("MYTABLENAME") == -1)
- APIERROR(myDict->getNdbError());
-
- delete myNdb;
-}
diff --git a/ndb/examples/ndbapi_example5/Makefile b/ndb/examples/ndbapi_example5/Makefile
deleted file mode 100644
index e2e3f06374a..00000000000
--- a/ndb/examples/ndbapi_example5/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
--include .defs.mk
-#NDB_OS = OS_YOU_ARE_RUNNING_ON
-#You need to set the NDB_OS variable here
-TARGET = ndbapi_example5
-SRCS = ndbapi_example5.cpp
-OBJS = ndbapi_example5.o
-CXX = g++
-CFLAGS = -c -Wall -fno-rtti -fno-exceptions
-DEBUG =
-LFLAGS = -Wall
-INCLUDE_DIR = ../../include
-LIB_DIR = ../../lib
-ifeq ($(NDB_OS), SOLARIS)
-# Here is the definition of system libraries necessary for Solaris 7
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), LINUX)
-# Here is the definition of system libraries necessary for Linux 2.4
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), MACOSX)
-# Here is the definition of system libraries necessary for Mac OS X
-SYS_LIB =
-endif
-
-$(TARGET): $(OBJS)
- $(CXX) $(LFLAGS) -L$(LIB_DIR) $(OBJS) -lNDB_API $(SYS_LIB) -o $(TARGET)
-
-$(TARGET).o: $(SRCS)
- $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
-
-clean:
- rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_scan_example/Makefile b/ndb/examples/ndbapi_scan_example/Makefile
deleted file mode 100644
index d7f08af4647..00000000000
--- a/ndb/examples/ndbapi_scan_example/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
--include .defs.mk
-#NDB_OS = OS_YOU_ARE_RUNNING_ON
-#You need to set the NDB_OS variable here (LINUX, SOLARIS, MACOSX)
-#NDB_OS = LINUX
-
-TARGET = ndbapi_scan
-SRCS = ndbapi_scan.cpp
-OBJS = ndbapi_scan.o
-CC = g++
-CFLAGS = -c -Wall -fno-rtti
-DEBUG =
-LFLAGS = -Wall
-INCLUDE_DIR = ../../include
-LIB_DIR = ../../lib
-ifeq ($(NDB_OS), SOLARIS)
-# Here is the definition of system libraries necessary for Solaris 7
-SYS_LIB = -lpthread -lsocket -lnsl -lrt
-endif
-ifeq ($(NDB_OS), LINUX)
-# Here is the definition of system libraries necessary for Linux 2.4
-SYS_LIB = -lpthread
-endif
-ifeq ($(NDB_OS), MACOSX)
-# Here is the definition of system libraries necessary for Mac OS X
-SYS_LIB =
-endif
-
-$(TARGET): $(OBJS)
- $(CC) $(LFLAGS) -L$(LIB_DIR) -lNDB_API $(OBJS) $(SYS_LIB) -o $(TARGET)
-
-$(TARGET).o: $(SRCS)
- $(CC) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
-
-clean:
- rm -f *.o $(TARGET)
diff --git a/ndb/examples/select_all/Makefile b/ndb/examples/select_all/Makefile
deleted file mode 100644
index 2bec205fa99..00000000000
--- a/ndb/examples/select_all/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
--include .defs.mk
-#NDB_OS = OS_YOU_ARE_RUNNING_ON
-#You need to set the NDB_OS variable here
-TARGET = select_all
-SRCS = select_all.cpp
-OBJS = select_all.o
-CXX = g++
-CFLAGS = -c -Wall -fno-rtti -fno-exceptions
-DEBUG =
-LFLAGS = -Wall
-INCLUDE_DIR = ../../include
-LIB_DIR = ../../lib
-ifeq ($(NDB_OS), SOLARIS)
-# Here is the definition of system libraries necessary for Solaris 7
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), LINUX)
-# Here is the definition of system libraries necessary for Linux 2.4
-SYS_LIB =
-endif
-ifeq ($(NDB_OS), MACOSX)
-# Here is the definition of system libraries necessary for Mac OS X
-SYS_LIB =
-endif
-
-$(TARGET): $(OBJS)
- $(CXX) $(LFLAGS) -L$(LIB_DIR) $(OBJS) -lNDB_API $(SYS_LIB) -o $(TARGET)
-
-$(TARGET).o: $(SRCS)
- $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
-
-clean:
- rm -f *.o $(TARGET)
diff --git a/ndb/examples/select_all/select_all.cpp b/ndb/examples/select_all/select_all.cpp
deleted file mode 100644
index 24bb1214bd2..00000000000
--- a/ndb/examples/select_all/select_all.cpp
+++ /dev/null
@@ -1,259 +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 */
-
-//
-// select_all.cpp: Prints all rows of a table
-//
-// Usage: select_all <table_name>+
-
-#include <NdbApi.hpp>
-
-// Used for cout
-#include <iostream>
-using namespace std;
-#include <stdio.h>
-#include <string.h>
-
-#define APIERROR(error) \
- { cout << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
- << error.code << ", msg: " << error.message << "." << endl; \
- exit(-1); }
-
-void usage(const char* prg) {
- cout << "Usage: " << prg << " <table name>" << endl;
- cout << "Prints all rows of table named <table name>" << endl;
- exit(0);
-}
-
-/*****************************************************************************
- *************************** Result Set Container ****************************
- *****************************************************************************/
-
-/*
- * Container of NdbRecAttr objects.
- * (NdbRecAttr objects are database rows read by a scan operation.)
- */
-class ResultSetContainer {
-public:
- /**
- * Initialize ResultSetContainer object for table named <tableName>
- * - Allocates memory
- * - Fetches attribute names from NDB Cluster
- */
- void init(NdbDictionary::Dictionary* dict, const char* tableName);
-
- /**
- * Get no of attributes for stored NdbRecAttr objects
- */
- int getNoOfAttributes() const;
-
- /**
- * Get NdbRecAttr object no i
- */
- NdbRecAttr* & getAttrStore(int i);
-
- /**
- * Get attribute name of attribute no i
- */
- const char* getAttrName(int i) const;
-
- /**
- * Print header of rows
- */
- void header() const;
-
-private:
- int m_cols; // No of attributes for stored NdbRecAttr objects
- char **m_names; // Names of attributes
- NdbRecAttr **m_data; // The actual stored NdbRecAttr objects
-};
-
-void ResultSetContainer::init(NdbDictionary::Dictionary * dict,
- const char* tableName)
-{
- // Get Table object from NDB (this contains metadata about all tables)
- const NdbDictionary::Table * tab = dict->getTable(tableName);
-
- // Get table id of the table we are interested in
- if (tab == 0) APIERROR(dict->getNdbError()); // E.g. table didn't exist
-
- // Get no of attributes and allocate memory
- m_cols = tab->getNoOfColumns();
- m_names = new char* [m_cols];
- m_data = new NdbRecAttr* [m_cols];
-
- // Store all attribute names for the table
- for (int i = 0; i < m_cols; i++) {
- m_names[i] = new char[255];
- BaseString::snprintf(m_names[i], 255, "%s", tab->getColumn(i)->getName());
- }
-}
-
-int ResultSetContainer::getNoOfAttributes() const {return m_cols;}
-NdbRecAttr*& ResultSetContainer::getAttrStore(int i) {return m_data[i];}
-const char* ResultSetContainer::getAttrName(int i) const {return m_names[i];}
-
-/*****************************************************************************
- ********************************** MAIN ***********************************
- *****************************************************************************/
-
-int main(int argc, const char** argv)
-{
- ndb_init();
- Ndb* myNdb = new Ndb("ndbapi_example4"); // Object representing the database
- NdbConnection* myNdbConnection; // For transactions
- NdbOperation* myNdbOperation; // For operations
- int check;
-
- if (argc != 2) {
- usage(argv[0]);
- exit(0);
- }
- const char* tableName = argv[1];
-
- /*******************************************
- * Initialize NDB and wait until its ready *
- *******************************************/
- if (myNdb->init() == -1) {
- APIERROR(myNdb->getNdbError());
- exit(-1);
- }
-
- if (myNdb->waitUntilReady(30) != 0) {
- cout << "NDB was not ready within 30 secs." << endl;
- exit(-1);
- }
-
- /***************************
- * Define and execute scan *
- ***************************/
- cout << "Select * from " << tableName << endl;
-
- ResultSetContainer * container = new ResultSetContainer;
- container->init(myNdb->getDictionary(), tableName);
-
- myNdbConnection = myNdb->startTransaction();
- if (myNdbConnection == NULL) APIERROR(myNdb->getNdbError());
-
- myNdbOperation = myNdbConnection->getNdbOperation(tableName);
- if (myNdbOperation == NULL) APIERROR(myNdbConnection->getNdbError());
-
- // Define the operation to be an 'openScanRead' operation.
- check = myNdbOperation->openScanRead(1);
- if (check == -1) APIERROR(myNdbConnection->getNdbError());
-
- // Set interpreted program to just be the single instruction
- // 'interpret_exit_ok'. (This approves all rows of the table.)
- if (myNdbOperation->interpret_exit_ok() == -1)
- APIERROR(myNdbConnection->getNdbError());
-
- // Get all attribute values of the row
- for(int i = 0; i < container->getNoOfAttributes(); i++){
- if((container->getAttrStore(i) =
- myNdbOperation->getValue(container->getAttrName(i))) == 0)
- APIERROR(myNdbConnection->getNdbError());
- }
-
- // Execute scan operation
- check = myNdbConnection->executeScan();
- if (check == -1) APIERROR(myNdbConnection->getNdbError());
-
- /****************
- * Print header *
- ****************/
- for (int i = 0; i < container->getNoOfAttributes(); i++)
- cout << container->getAttrName(i) << "\t";
-
- cout << endl;
- for (int i = 0; i < container->getNoOfAttributes(); i++) {
- for (int j = strlen(container->getAttrName(i)); j > 0; j--)
- cout << "-";
- cout << "\t";
- }
- cout << "\n";
-
- /**************
- * Scan table *
- **************/
- int eof;
- int rows = 0;
-
- // Print all rows of table
- while ((eof = myNdbConnection->nextScanResult()) == 0) {
- rows++;
-
- for (int i = 0; i < container->getNoOfAttributes(); i++) {
- if (container->getAttrStore(i)->isNULL()) {
- cout << "NULL";
- } else {
-
- // Element size of value (No of bits per element in attribute value)
- const int size = container->getAttrStore(i)->attrSize();
-
- // No of elements in an array attribute (Is 1 if non-array attribute)
- const int aSize = container->getAttrStore(i)->arraySize();
-
- switch(container->getAttrStore(i)->attrType()){
- case UnSigned:
- switch(size) {
- case 8: cout << container->getAttrStore(i)->u_64_value(); break;
- case 4: cout << container->getAttrStore(i)->u_32_value(); break;
- case 2: cout << container->getAttrStore(i)->u_short_value(); break;
- case 1: cout << (unsigned) container->getAttrStore(i)->u_char_value();
- break;
- default: cout << "Unknown size" << endl;
- }
- break;
-
- case Signed:
- switch(size) {
- case 8: cout << container->getAttrStore(i)->int64_value(); break;
- case 4: cout << container->getAttrStore(i)->int32_value(); break;
- case 2: cout << container->getAttrStore(i)->short_value(); break;
- case 1: cout << (int) container->getAttrStore(i)->char_value(); break;
- default: cout << "Unknown size" << endl;
- }
- break;
-
- case String:
- {
- char* buf = new char[aSize+1];
- memcpy(buf, container->getAttrStore(i)->aRef(), aSize);
- buf[aSize] = 0;
- cout << buf;
- delete [] buf;
- }
- break;
-
- case Float:
- cout << container->getAttrStore(i)->float_value();
- break;
-
- default:
- cout << "Unknown";
- break;
- }
- }
- cout << "\t";
- }
- cout << endl;
- }
- if (eof == -1) APIERROR(myNdbConnection->getNdbError());
-
- myNdb->closeTransaction(myNdbConnection);
-
- cout << "Selected " << rows << " rows." << endl;
-}
diff --git a/ndb/include/Makefile.am b/ndb/include/Makefile.am
index ef4e9552566..10f297492e9 100644
--- a/ndb/include/Makefile.am
+++ b/ndb/include/Makefile.am
@@ -2,6 +2,7 @@
include $(top_srcdir)/ndb/config/common.mk.am
ndbinclude_HEADERS = \
+ndb_constants.h \
ndb_init.h \
ndb_types.h \
ndb_version.h
@@ -11,8 +12,7 @@ ndbapi/ndbapi_limits.h \
ndbapi/ndb_opt_defaults.h \
ndbapi/Ndb.hpp \
ndbapi/NdbApi.hpp \
-ndbapi/NdbConnection.hpp \
-ndbapi/NdbCursorOperation.hpp \
+ndbapi/NdbTransaction.hpp \
ndbapi/NdbDictionary.hpp \
ndbapi/NdbError.hpp \
ndbapi/NdbEventOperation.hpp \
@@ -23,7 +23,6 @@ ndbapi/NdbBlob.hpp \
ndbapi/NdbPool.hpp \
ndbapi/NdbRecAttr.hpp \
ndbapi/NdbReceiver.hpp \
-ndbapi/NdbResultSet.hpp \
ndbapi/NdbScanFilter.hpp \
ndbapi/NdbScanOperation.hpp \
ndbapi/NdbIndexScanOperation.hpp \
@@ -33,7 +32,8 @@ mgmapiinclude_HEADERS = \
mgmapi/mgmapi.h \
mgmapi/mgmapi_debug.h \
mgmapi/mgmapi_config_parameters.h \
-mgmapi/mgmapi_config_parameters_debug.h
+mgmapi/mgmapi_config_parameters_debug.h \
+mgmapi/ndb_logevent.h
noinst_HEADERS = \
ndb_global.h \
@@ -46,3 +46,6 @@ dist-hook:
-rm -rf `find $(distdir) -type d -name SCCS`
windoze-dsp:
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/ndb/include/debugger/EventLogger.hpp b/ndb/include/debugger/EventLogger.hpp
index ddf21b79f5f..6308cf25465 100644
--- a/ndb/include/debugger/EventLogger.hpp
+++ b/ndb/include/debugger/EventLogger.hpp
@@ -17,12 +17,12 @@
#ifndef EVENTLOGGER_H
#define EVENTLOGGER_H
-#include <Logger.hpp>
-#include <FileLogHandler.hpp>
-#include <GrepError.hpp>
-#include <kernel_types.h>
+#include <logger/Logger.hpp>
+#include <logger/FileLogHandler.hpp>
+#include "GrepError.hpp"
+#include <kernel/kernel_types.h>
#include <kernel/LogLevel.hpp>
-#include <signaldata/EventReport.hpp>
+#include <kernel/signaldata/EventReport.hpp>
class EventLoggerBase {
public:
@@ -39,11 +39,14 @@ public:
* threshold - is in range [0-15]
* severity - DEBUG to ALERT (Type of log message)
*/
+ typedef void (* EventTextFunction)(char *,size_t,const Uint32*);
+
struct EventRepLogLevelMatrix {
- EventReport::EventType eventType;
- LogLevel::EventCategory eventCategory;
- Uint32 threshold;
- Logger::LoggerLevel severity;
+ Ndb_logevent_type eventType;
+ LogLevel::EventCategory eventCategory;
+ Uint32 threshold;
+ Logger::LoggerLevel severity;
+ EventTextFunction textF;
};
static const EventRepLogLevelMatrix matrix[];
@@ -51,7 +54,8 @@ public:
static int event_lookup(int eventType,
LogLevel::EventCategory &cat,
Uint32 &threshold,
- Logger::LoggerLevel &severity);
+ Logger::LoggerLevel &severity,
+ EventTextFunction &textF);
};
/**
@@ -130,17 +134,18 @@ public:
* @param nodeId the node id of event origin.
*/
virtual void log(int, const Uint32*, NodeId = 0,const class LogLevel * = 0);
+
/**
* Returns the event text for the specified event report type.
*
- * @param type the event type.
+ * @param textF print function for the event
* @param theData the event data.
* @param nodeId a node id.
* @return the event report text.
*/
static const char* getText(char * dst, size_t dst_len,
- int type,
+ EventTextFunction textF,
const Uint32* theData, NodeId nodeId = 0);
/**
diff --git a/ndb/include/debugger/SignalLoggerManager.hpp b/ndb/include/debugger/SignalLoggerManager.hpp
index 742bf7d294e..d212329bf78 100644
--- a/ndb/include/debugger/SignalLoggerManager.hpp
+++ b/ndb/include/debugger/SignalLoggerManager.hpp
@@ -87,7 +87,7 @@ public:
/**
* Generic messages in the signal log
*/
- void log(BlockNumber bno, const char * msg);
+ void log(BlockNumber bno, const char * msg, ...);
/**
* LogModes
diff --git a/ndb/include/kernel/AttributeDescriptor.hpp b/ndb/include/kernel/AttributeDescriptor.hpp
index 071d45e2607..2fe7c9f0973 100644
--- a/ndb/include/kernel/AttributeDescriptor.hpp
+++ b/ndb/include/kernel/AttributeDescriptor.hpp
@@ -19,54 +19,49 @@
class AttributeDescriptor {
friend class Dbdict;
+ friend class Dbtc;
+ friend class Dbacc;
friend class Dbtup;
friend class Dbtux;
-
+ friend class SimulatedBlock;
+
private:
static void setType(Uint32 &, Uint32 type);
static void setSize(Uint32 &, Uint32 size);
static void setArray(Uint32 &, Uint32 arraySize);
- static void setOriginal(Uint32 &, Uint32 original);
static void setNullable(Uint32 &, Uint32 nullable);
- static void setDGroup(Uint32 &, Uint32 dgroup);
static void setDKey(Uint32 &, Uint32 dkey);
static void setPrimaryKey(Uint32 &, Uint32 dkey);
- static void setStoredInTup(Uint32 &, Uint32 storedInTup);
static void setDynamic(Uint32 &, Uint32 dynamicInd);
static Uint32 getType(const Uint32 &);
static Uint32 getSize(const Uint32 &);
+ static Uint32 getSizeInBytes(const Uint32 &);
static Uint32 getSizeInWords(const Uint32 &);
static Uint32 getArrayType(const Uint32 &);
static Uint32 getArraySize(const Uint32 &);
- static Uint32 getOriginal(const Uint32 &);
static Uint32 getNullable(const Uint32 &);
- static Uint32 getDGroup(const Uint32 &);
static Uint32 getDKey(const Uint32 &);
static Uint32 getPrimaryKey(const Uint32 &);
- static Uint32 getStoredInTup(const Uint32 &);
static Uint32 getDynamic(const Uint32 &);
};
/**
*
* a = Array type - 2 Bits -> Max 3 (Bit 0-1)
- * t = Attribute type - 2 Bits -> Max 3 (Bit 2-3)
- * s = Attribute size - 3 Bits -> Max 7 (Bit 4-6)
- * o = Original attribute - 1 Bit 7
- * n = Nullable - 1 Bit 8
- * ? = Stored in tup - 1 Bit 9
- * d = Disk based - 1 Bit 10
- * g = Distribution Group Ind- 1 Bit 11
- * k = Distribution Key Ind - 1 Bit 12
- * r = Distribution group sz - 1 Bit 13
+ * t = Attribute type - 5 Bits -> Max 31 (Bit 2-6)
+ * s = Attribute size - 3 Bits -> Max 7 (Bit 8-10)
+ * d = Disk based - 1 Bit 11
+ * n = Nullable - 1 Bit 12
+ * k = Distribution Key Ind - 1 Bit 13
* p = Primary key attribute - 1 Bit 14
* y = Dynamic attribute - 1 Bit 15
* z = Array size - 16 Bits -> Max 65535 (Bit 16-31)
*
* 1111111111222222222233
* 01234567890123456789012345678901
- * aattsss n dgkrpyzzzzzzzzzzzzzzzz
+ * aattttt sssdnkpyzzzzzzzzzzzzzzzz
+ * aattsss n d k pyzzzzzzzzzzzzzzzz [ old format ]
*
*/
@@ -74,21 +69,17 @@ private:
#define AD_ARRAY_TYPE_MASK (3)
#define AD_TYPE_SHIFT (2)
-#define AD_TYPE_MASK (3)
+#define AD_TYPE_MASK (31)
-#define AD_SIZE_SHIFT (4)
+#define AD_SIZE_SHIFT (8)
#define AD_SIZE_MASK (7)
+#define AD_SIZE_IN_BYTES_SHIFT (3)
#define AD_SIZE_IN_WORDS_OFFSET (31)
#define AD_SIZE_IN_WORDS_SHIFT (5)
-#define AD_ORIGINAL_SHIFT (8)
-#define AD_NULLABLE_SHIFT (8)
-#define AD_TUP_STORED_SHIFT (9)
-
-#define AD_DISTR_GROUP_SHIFT (11)
-#define AD_DISTR_KEY_SHIFT (12)
-#define AD_DISTR_GROUP_SZ (13)
+#define AD_NULLABLE_SHIFT (12)
+#define AD_DISTR_KEY_SHIFT (13)
#define AD_PRIMARY_KEY (14)
#define AD_DYNAMIC (15)
@@ -130,20 +121,6 @@ AttributeDescriptor::setNullable(Uint32 & desc, Uint32 nullable){
inline
void
-AttributeDescriptor::setOriginal(Uint32 & desc, Uint32 original){
- ASSERT_BOOL(original, "AttributeDescriptor::setOriginal");
- desc |= (original << AD_ORIGINAL_SHIFT);
-}
-
-inline
-void
-AttributeDescriptor::setDGroup(Uint32 & desc, Uint32 dgroup){
- ASSERT_BOOL(dgroup, "AttributeDescriptor::setDGroup");
- desc |= (dgroup << AD_DISTR_GROUP_SHIFT);
-}
-
-inline
-void
AttributeDescriptor::setDKey(Uint32 & desc, Uint32 dkey){
ASSERT_BOOL(dkey, "AttributeDescriptor::setDKey");
desc |= (dkey << AD_DISTR_KEY_SHIFT);
@@ -158,13 +135,6 @@ AttributeDescriptor::setPrimaryKey(Uint32 & desc, Uint32 dkey){
inline
void
-AttributeDescriptor::setStoredInTup(Uint32 & desc, Uint32 storedInTup){
- ASSERT_BOOL(storedInTup, "AttributeDescriptor::setStoredInTup");
- desc |= (storedInTup << AD_TUP_STORED_SHIFT);
-}
-
-inline
-void
AttributeDescriptor::setDynamic(Uint32 & desc, Uint32 dynamic){
ASSERT_BOOL(dynamic, "AttributeDescriptor::setDynamic");
desc |= (dynamic << AD_DYNAMIC);
@@ -187,6 +157,13 @@ AttributeDescriptor::getSize(const Uint32 & desc){
inline
Uint32
+AttributeDescriptor::getSizeInBytes(const Uint32 & desc){
+ return (getArraySize(desc) << getSize(desc))
+ >> AD_SIZE_IN_BYTES_SHIFT;
+}
+
+inline
+Uint32
AttributeDescriptor::getSizeInWords(const Uint32 & desc){
return ((getArraySize(desc) << getSize(desc))
+ AD_SIZE_IN_WORDS_OFFSET)
@@ -213,18 +190,6 @@ AttributeDescriptor::getNullable(const Uint32 & desc){
inline
Uint32
-AttributeDescriptor::getOriginal(const Uint32 & desc){
- return (desc >> AD_ORIGINAL_SHIFT) & 1;
-}
-
-inline
-Uint32
-AttributeDescriptor::getDGroup(const Uint32 & desc){
- return (desc >> AD_DISTR_GROUP_SHIFT) & 1;
-}
-
-inline
-Uint32
AttributeDescriptor::getDKey(const Uint32 & desc){
return (desc >> AD_DISTR_KEY_SHIFT) & 1;
}
@@ -241,10 +206,4 @@ AttributeDescriptor::getDynamic(const Uint32 & desc){
return (desc >> AD_DYNAMIC) & 1;
}
-inline
-Uint32
-AttributeDescriptor::getStoredInTup(const Uint32 & desc){
- return (desc >> AD_TUP_STORED_SHIFT) & 1;
-}
-
#endif
diff --git a/ndb/include/kernel/AttributeHeader.hpp b/ndb/include/kernel/AttributeHeader.hpp
index ed9085301be..3cb432067eb 100644
--- a/ndb/include/kernel/AttributeHeader.hpp
+++ b/ndb/include/kernel/AttributeHeader.hpp
@@ -33,10 +33,14 @@ public:
* Psuedo columns
*/
STATIC_CONST( PSUEDO = 0x8000 );
- STATIC_CONST( FRAGMENT = 0xFFFE );
- STATIC_CONST( ROW_COUNT = 0xFFFD );
- STATIC_CONST( COMMIT_COUNT = 0xFFFC );
+ STATIC_CONST( FRAGMENT = 0xFFFE ); // Read fragment no
+ STATIC_CONST( ROW_COUNT = 0xFFFD ); // Read row count (committed)
+ STATIC_CONST( COMMIT_COUNT = 0xFFFC ); // Read commit count
+ STATIC_CONST( RANGE_NO = 0xFFFB ); // Read range no (when batched ranges)
+ STATIC_CONST( ROW_SIZE = 0xFFFA );
+ STATIC_CONST( FRAGMENT_MEMORY= 0xFFF9 );
+
/** Initialize AttributeHeader at location aHeaderPtr */
static AttributeHeader& init(void* aHeaderPtr, Uint32 anAttributeId,
Uint32 aDataSize);
diff --git a/ndb/include/kernel/AttributeList.hpp b/ndb/include/kernel/AttributeList.hpp
index 7c6f71df3d2..70b178c6c79 100644
--- a/ndb/include/kernel/AttributeList.hpp
+++ b/ndb/include/kernel/AttributeList.hpp
@@ -17,6 +17,8 @@
#ifndef ATTRIBUTE_LIST_HPP
#define ATTRIBUTE_LIST_HPP
+#include "ndb_limits.h"
+
/**
* Masks and lists used by index and trigger. Must be plain old Uint32 data.
* XXX depends on other headers XXX move to some common file
diff --git a/ndb/include/kernel/LogLevel.hpp b/ndb/include/kernel/LogLevel.hpp
index 3c2f349e0e1..60dcd36ab56 100644
--- a/ndb/include/kernel/LogLevel.hpp
+++ b/ndb/include/kernel/LogLevel.hpp
@@ -57,7 +57,7 @@ public:
llInfo = CFG_LOGLEVEL_INFO - CFG_MIN_LOGLEVEL,
llWarning = CFG_LOGLEVEL_WARNING - CFG_MIN_LOGLEVEL,
llError = CFG_LOGLEVEL_ERROR - CFG_MIN_LOGLEVEL,
- llGrep = CFG_LOGLEVEL_GREP - CFG_MIN_LOGLEVEL,
+ llCongestion = CFG_LOGLEVEL_CONGESTION - CFG_MIN_LOGLEVEL,
llDebug = CFG_LOGLEVEL_DEBUG - CFG_MIN_LOGLEVEL
,llBackup = CFG_LOGLEVEL_BACKUP - CFG_MIN_LOGLEVEL
};
@@ -147,7 +147,7 @@ LogLevel::set_max(const LogLevel & org){
return * this;
}
-#include <signaldata/EventSubscribeReq.hpp>
+#include "signaldata/EventSubscribeReq.hpp"
inline
LogLevel&
diff --git a/ndb/include/kernel/NodeInfo.hpp b/ndb/include/kernel/NodeInfo.hpp
index 5377f001949..622185323a3 100644
--- a/ndb/include/kernel/NodeInfo.hpp
+++ b/ndb/include/kernel/NodeInfo.hpp
@@ -41,6 +41,7 @@ public:
Uint32 m_type; ///< Node type
Uint32 m_connectCount; ///< No of times connected
bool m_connected; ///< Node is connected
+ Uint32 m_heartbeat_cnt; ///< Missed heartbeats
friend NdbOut & operator<<(NdbOut&, const NodeInfo&);
};
@@ -52,6 +53,7 @@ NodeInfo::NodeInfo(){
m_signalVersion = 0;
m_type = INVALID;
m_connectCount = 0;
+ m_heartbeat_cnt= 0;
}
inline
diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h
index 48a56c019bb..e60153e60ec 100644
--- a/ndb/include/kernel/ndb_limits.h
+++ b/ndb/include/kernel/ndb_limits.h
@@ -17,6 +17,8 @@
#ifndef NDB_LIMITS_H
#define NDB_LIMITS_H
+#include <mysql.h>
+
#define RNIL 0xffffff00
/**
@@ -50,17 +52,17 @@
**/
#define MAX_TUPLES_PER_PAGE 8191
#define MAX_TUPLES_BITS 13 /* 13 bits = 8191 tuples per page */
-/*#define MAX_NO_OF_TUPLEKEY 16 Not currently used */
-#define MAX_TABLES 1600
+#define MAX_TABLES 20320 /* SchemaFile.hpp */
#define MAX_TAB_NAME_SIZE 128
-#define MAX_ATTR_NAME_SIZE 32
+#define MAX_ATTR_NAME_SIZE NAME_LEN /* From mysql_com.h */
#define MAX_ATTR_DEFAULT_VALUE_SIZE 128
#define MAX_ATTRIBUTES_IN_TABLE 128
#define MAX_ATTRIBUTES_IN_INDEX 32
#define MAX_TUPLE_SIZE_IN_WORDS 2013
-#define MAX_FIXED_KEY_LENGTH_IN_WORDS 8
#define MAX_KEY_SIZE_IN_WORDS 1023
#define MAX_FRM_DATA_SIZE 6000
+#define MAX_NULL_BITS 4096
+#define MAX_FRAGMENT_DATA_BYTES (4+(2 * 8 * MAX_REPLICAS * MAX_NDB_NODES))
#define MIN_ATTRBUF ((MAX_ATTRIBUTES_IN_TABLE/24) + 1)
/*
@@ -118,6 +120,11 @@
#define NDB_BLOB_HEAD_SIZE 2 /* sizeof(NdbBlob::Head) >> 2 */
/*
+ * Character sets.
+ */
+#define MAX_XFRM_MULTIPLY 8 /* max expansion when normalizing */
+
+/*
* Long signals
*/
#define NDB_SECTION_SEGMENT_SZ 60
diff --git a/ndb/include/kernel/signaldata/AccScan.hpp b/ndb/include/kernel/signaldata/AccScan.hpp
index eab1c3262fc..d94d4da8cca 100644
--- a/ndb/include/kernel/signaldata/AccScan.hpp
+++ b/ndb/include/kernel/signaldata/AccScan.hpp
@@ -34,6 +34,7 @@ class AccScanReq {
*/
friend class Dbacc;
friend class Dbtux;
+ friend class Dbtup;
public:
STATIC_CONST( SignalLength = 8 );
@@ -51,30 +52,29 @@ private:
* Previously there where also a scan type
*/
static Uint32 getLockMode(const Uint32 & requestInfo);
- static Uint32 getKeyinfoFlag(const Uint32 & requestInfo);
static Uint32 getReadCommittedFlag(const Uint32 & requestInfo);
+ static Uint32 getDescendingFlag(const Uint32 & requestInfo);
static void setLockMode(Uint32 & requestInfo, Uint32 lockMode);
- static void setKeyinfoFlag(Uint32 & requestInfo, Uint32 keyinfo);
static void setReadCommittedFlag(Uint32 & requestInfo, Uint32 readCommitted);
+ static void setDescendingFlag(Uint32 & requestInfo, Uint32 descending);
};
/**
* Request Info
*
* l = Lock Mode - 1 Bit 2
- * k = Keyinfo - 1 Bit 4
* h = Read Committed - 1 Bit 5
+ * z = Descending (TUX) - 1 Bit 6
*
* 1111111111222222222233
* 01234567890123456789012345678901
- * l kh
+ * l hz
*/
#define AS_LOCK_MODE_SHIFT (2)
#define AS_LOCK_MODE_MASK (1)
-
-#define AS_KEYINFO_SHIFT (4)
#define AS_READ_COMMITTED_SHIFT (5)
+#define AS_DESCENDING_SHIFT (6)
inline
Uint32
@@ -84,14 +84,14 @@ AccScanReq::getLockMode(const Uint32 & requestInfo){
inline
Uint32
-AccScanReq::getKeyinfoFlag(const Uint32 & requestInfo){
- return (requestInfo >> AS_KEYINFO_SHIFT) & 1;
+AccScanReq::getReadCommittedFlag(const Uint32 & requestInfo){
+ return (requestInfo >> AS_READ_COMMITTED_SHIFT) & 1;
}
inline
Uint32
-AccScanReq::getReadCommittedFlag(const Uint32 & requestInfo){
- return (requestInfo >> AS_READ_COMMITTED_SHIFT) & 1;
+AccScanReq::getDescendingFlag(const Uint32 & requestInfo){
+ return (requestInfo >> AS_DESCENDING_SHIFT) & 1;
}
inline
@@ -103,16 +103,16 @@ AccScanReq::setLockMode(UintR & requestInfo, UintR val){
inline
void
-AccScanReq::setKeyinfoFlag(UintR & requestInfo, UintR val){
- ASSERT_BOOL(val, "AccScanReq::setKeyinfoFlag");
- requestInfo |= (val << AS_KEYINFO_SHIFT);
+AccScanReq::setReadCommittedFlag(UintR & requestInfo, UintR val){
+ ASSERT_BOOL(val, "AccScanReq::setReadCommittedFlag");
+ requestInfo |= (val << AS_READ_COMMITTED_SHIFT);
}
inline
void
-AccScanReq::setReadCommittedFlag(UintR & requestInfo, UintR val){
- ASSERT_BOOL(val, "AccScanReq::setReadCommittedFlag");
- requestInfo |= (val << AS_READ_COMMITTED_SHIFT);
+AccScanReq::setDescendingFlag(UintR & requestInfo, UintR val){
+ ASSERT_BOOL(val, "AccScanReq::setDescendingFlag");
+ requestInfo |= (val << AS_DESCENDING_SHIFT);
}
class AccScanConf {
@@ -121,6 +121,7 @@ class AccScanConf {
*/
friend class Dbacc;
friend class Dbtux;
+ friend class Dbtup;
/**
* Reciver(s)
@@ -149,6 +150,7 @@ private:
class AccCheckScan {
friend class Dbacc;
friend class Dbtux;
+ friend class Dbtup;
friend class Dblqh;
enum {
ZCHECK_LCP_STOP = 0,
diff --git a/ndb/include/kernel/signaldata/CreateEvnt.hpp b/ndb/include/kernel/signaldata/CreateEvnt.hpp
index e911fa36ce6..8712ce8890c 100644
--- a/ndb/include/kernel/signaldata/CreateEvnt.hpp
+++ b/ndb/include/kernel/signaldata/CreateEvnt.hpp
@@ -17,6 +17,7 @@
#ifndef CREATE_EVNT_HPP
#define CREATE_EVNT_HPP
+#include <ndberror.h>
#include "SignalData.hpp"
#include <NodeBitmask.hpp>
#include <signaldata/DictTabInfo.hpp>
@@ -101,7 +102,7 @@ public:
Busy = 701,
NotMaster = 702,
SeizeError = 703,
- EventNotFound = 4238,
+ EventNotFound = 4710,
EventNameTooLong = 4241,
TooManyEvents = 4242,
BadRequestType = 4247,
@@ -363,12 +364,10 @@ struct CreateEvntRef {
Busy = 701,
NotMaster = 702,
SeizeError = 703,
- EventNotFound = 4238,
- EventExists = 4239,
- EventNameTooLong = 4241,
- TooManyEvents = 4242,
- // EventExists = 4244,
- AttributeNotStored = 4245,
+ TooManyEvents = 4707,
+ EventNameTooLong = 4708,
+ EventNameExists = 746,
+ EventNotFound = 4731,
AttributeNullable = 4246,
BadRequestType = 4247,
InvalidName = 4248,
@@ -376,7 +375,7 @@ struct CreateEvntRef {
InvalidEventType = 4250,
NotUnique = 4251,
AllocationError = 4252,
- CreateEventTableFailed = 4253,
+ CreateEventTableFailed = 4711,
InvalidAttributeOrder = 4255,
Temporary = 0x1 << 16
};
diff --git a/ndb/include/kernel/signaldata/CreateIndx.hpp b/ndb/include/kernel/signaldata/CreateIndx.hpp
index 5563f80a555..a9dc653f349 100644
--- a/ndb/include/kernel/signaldata/CreateIndx.hpp
+++ b/ndb/include/kernel/signaldata/CreateIndx.hpp
@@ -198,7 +198,6 @@ public:
IndexNameTooLong = 4241,
TooManyIndexes = 4242,
IndexExists = 4244,
- AttributeNotStored = 4245,
AttributeNullable = 4246,
BadRequestType = 4247,
InvalidName = 4248,
@@ -207,7 +206,7 @@ public:
NotUnique = 4251,
AllocationError = 4252,
CreateIndexTableFailed = 4253,
- InvalidAttributeOrder = 4255
+ DuplicateAttributes = 4258
};
CreateIndxConf m_conf;
diff --git a/ndb/include/kernel/signaldata/CreateTable.hpp b/ndb/include/kernel/signaldata/CreateTable.hpp
index 67e510d2ed0..481b323fdb0 100644
--- a/ndb/include/kernel/signaldata/CreateTable.hpp
+++ b/ndb/include/kernel/signaldata/CreateTable.hpp
@@ -86,6 +86,7 @@ public:
NoMoreAttributeRecords = 708,
AttributeNameTwice = 720,
TableAlreadyExist = 721,
+ InvalidArraySize = 736,
ArraySizeTooBig = 737,
RecordTooBig = 738,
InvalidPrimaryKeySize = 739,
diff --git a/ndb/include/kernel/signaldata/DictTabInfo.hpp b/ndb/include/kernel/signaldata/DictTabInfo.hpp
index 48c24125ae4..bc4817f0cf3 100644
--- a/ndb/include/kernel/signaldata/DictTabInfo.hpp
+++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp
@@ -24,6 +24,28 @@
#include <trigger_definitions.h>
#include <NdbSqlUtil.hpp>
+#ifndef my_decimal_h
+
+// sql/my_decimal.h requires many more sql/*.h new to ndb
+// for now, copy the bit we need TODO proper fix
+
+#define DECIMAL_MAX_LENGTH ((8 * 9) - 8)
+
+#ifndef NOT_FIXED_DEC
+#define NOT_FIXED_DEC 31
+#endif
+
+C_MODE_START
+extern int decimal_bin_size(int, int);
+C_MODE_END
+
+inline int my_decimal_get_binary_size(uint precision, uint scale)
+{
+ return decimal_bin_size((int)precision, (int)scale);
+}
+
+#endif
+
#define DTIMAP(x, y, z) \
{ DictTabInfo::y, offsetof(x, z), SimpleProperties::Uint32Value, 0, (~0), 0 }
@@ -85,10 +107,6 @@ public:
MaxLoadFactor = 11, //Default 80
KeyLength = 12, //Default 1 (No of words in primary key)
FragmentTypeVal = 13, //Default AllNodesSmallTable
- TableStorageVal = 14, //Default StorageType::MainMemory
- ScanOptimised = 15, //Default updateOptimised
- FragmentKeyTypeVal = 16, //Default PrimaryKey
- SecondTableId = 17, //Mandatory between DICT's otherwise not allowed
TableTypeVal = 18, //Default TableType::UserTable
PrimaryTable = 19, //Mandatory for index otherwise RNIL
PrimaryTableId = 20, //ditto
@@ -100,21 +118,20 @@ public:
FrmLen = 26,
FrmData = 27,
FragmentCount = 128, // No of fragments in table (!fragment replicas)
+ FragmentDataLen = 129,
+ FragmentData = 130, // CREATE_FRAGMENTATION reply
TableEnd = 999,
AttributeName = 1000, // String, Mandatory
AttributeId = 1001, //Mandatory between DICT's otherwise not allowed
- AttributeType = 1002, //Default UnSignedType
+ AttributeType = 1002, //for osu 4.1->5.0.x
AttributeSize = 1003, //Default DictTabInfo::a32Bit
AttributeArraySize = 1005, //Default 1
AttributeKeyFlag = 1006, //Default noKey
AttributeStorage = 1007, //Default MainMemory
AttributeNullableFlag = 1008, //Default NotNullable
- AttributeDGroup = 1009, //Default NotDGroup
AttributeDKey = 1010, //Default NotDKey
- AttributeStoredInd = 1011, //Default NotStored
- AttributeGroup = 1012, //Default 0
- AttributeExtType = 1013, //Default 0 (undefined)
+ AttributeExtType = 1013, //Default ExtUnsigned
AttributeExtPrecision = 1014, //Default 0
AttributeExtScale = 1015, //Default 0
AttributeExtLength = 1016, //Default 0
@@ -127,12 +144,7 @@ public:
// have a default value. Thus the default values are part of the protocol.
// ----------------------------------------------------------------------
- // FragmentKeyType constants
- enum FragmentKeyType {
- PrimaryKey = 0,
- DistributionKey = 1,
- DistributionGroup = 2
- };
+
// FragmentType constants
enum FragmentType {
@@ -142,12 +154,6 @@ public:
SingleFragment = 3
};
- // TableStorage AND AttributeStorage constants
- enum StorageType {
- MainMemory = 0,
- DiskMemory = 1
- };
-
// TableType constants + objects
enum TableType {
UndefTableType = 0,
@@ -220,40 +226,18 @@ public:
StorePermanent = 2
};
- // ScanOptimised constants
- STATIC_CONST( updateOptimised = 0 );
- STATIC_CONST( scanOptimised = 1 );
-
- // AttributeType constants
- STATIC_CONST( SignedType = 0 );
- STATIC_CONST( UnSignedType = 1 );
- STATIC_CONST( FloatingPointType = 2 );
- STATIC_CONST( StringType = 3 );
-
// AttributeSize constants
+ STATIC_CONST( aBit = 0 );
STATIC_CONST( an8Bit = 3 );
STATIC_CONST( a16Bit = 4 );
STATIC_CONST( a32Bit = 5 );
STATIC_CONST( a64Bit = 6 );
STATIC_CONST( a128Bit = 7 );
-
- // AttributeDGroup constants
- STATIC_CONST( NotDGroup = 0 );
- STATIC_CONST( DGroup = 1 );
-
- // AttributeDKey constants
- STATIC_CONST( NotDKey = 0 );
- STATIC_CONST( DKey = 1 );
-
- // AttributeStoredInd constants
- STATIC_CONST( NotStored = 0 );
- STATIC_CONST( Stored = 1 );
-
+
// Table data interpretation
struct Table {
char TableName[MAX_TAB_NAME_SIZE];
Uint32 TableId;
- Uint32 SecondTableId;
char PrimaryTable[MAX_TAB_NAME_SIZE]; // Only used when "index"
Uint32 PrimaryTableId;
Uint32 TableLoggedFlag;
@@ -267,8 +251,6 @@ public:
Uint32 KeyLength;
Uint32 FragmentType;
Uint32 TableStorage;
- Uint32 ScanOptimised;
- Uint32 FragmentKeyType;
Uint32 TableType;
Uint32 TableVersion;
Uint32 IndexState;
@@ -279,7 +261,9 @@ public:
Uint32 FrmLen;
char FrmData[MAX_FRM_DATA_SIZE];
Uint32 FragmentCount;
-
+ Uint32 FragmentDataLen;
+ Uint16 FragmentData[(MAX_FRAGMENT_DATA_BYTES+1)/2];
+
void init();
};
@@ -305,6 +289,8 @@ public:
ExtDouble = NdbSqlUtil::Type::Double,
ExtOlddecimal = NdbSqlUtil::Type::Olddecimal,
ExtOlddecimalunsigned = NdbSqlUtil::Type::Olddecimalunsigned,
+ ExtDecimal = NdbSqlUtil::Type::Decimal,
+ ExtDecimalunsigned = NdbSqlUtil::Type::Decimalunsigned,
ExtChar = NdbSqlUtil::Type::Char,
ExtVarchar = NdbSqlUtil::Type::Varchar,
ExtBinary = NdbSqlUtil::Type::Binary,
@@ -313,6 +299,9 @@ public:
ExtDate = NdbSqlUtil::Type::Date,
ExtBlob = NdbSqlUtil::Type::Blob,
ExtText = NdbSqlUtil::Type::Text,
+ ExtBit = NdbSqlUtil::Type::Bit,
+ ExtLongvarchar = NdbSqlUtil::Type::Longvarchar,
+ ExtLongvarbinary = NdbSqlUtil::Type::Longvarbinary,
ExtTime = NdbSqlUtil::Type::Time,
ExtYear = NdbSqlUtil::Type::Year,
ExtTimestamp = NdbSqlUtil::Type::Timestamp
@@ -322,16 +311,12 @@ public:
struct Attribute {
char AttributeName[MAX_TAB_NAME_SIZE];
Uint32 AttributeId;
- Uint32 AttributeType;
+ Uint32 AttributeType; // for osu 4.1->5.0.x
Uint32 AttributeSize;
Uint32 AttributeArraySize;
Uint32 AttributeKeyFlag;
- Uint32 AttributeStorage;
Uint32 AttributeNullableFlag;
- Uint32 AttributeDGroup;
Uint32 AttributeDKey;
- Uint32 AttributeStoredInd;
- Uint32 AttributeGroup;
Uint32 AttributeExtType;
Uint32 AttributeExtPrecision;
Uint32 AttributeExtScale;
@@ -347,132 +332,125 @@ public:
return ((1 << AttributeSize) * AttributeArraySize + 31) >> 5;
}
- // translate to old kernel types and sizes
+ // compute old-sty|e attribute size and array size
inline bool
translateExtType() {
switch (AttributeExtType) {
case DictTabInfo::ExtUndefined:
- break;
+ return false;
case DictTabInfo::ExtTinyint:
- AttributeType = DictTabInfo::SignedType;
- AttributeSize = DictTabInfo::an8Bit;
- AttributeArraySize = AttributeExtLength;
- return true;
case DictTabInfo::ExtTinyunsigned:
- AttributeType = DictTabInfo::UnSignedType;
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtSmallint:
- AttributeType = DictTabInfo::SignedType;
- AttributeSize = DictTabInfo::a16Bit;
- AttributeArraySize = AttributeExtLength;
- return true;
case DictTabInfo::ExtSmallunsigned:
- AttributeType = DictTabInfo::UnSignedType;
AttributeSize = DictTabInfo::a16Bit;
AttributeArraySize = AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtMediumint:
- AttributeType = DictTabInfo::SignedType;
- AttributeSize = DictTabInfo::an8Bit;
- AttributeArraySize = 3 * AttributeExtLength;
- return true;
case DictTabInfo::ExtMediumunsigned:
- AttributeType = DictTabInfo::UnSignedType;
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 3 * AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtInt:
- AttributeType = DictTabInfo::SignedType;
- AttributeSize = DictTabInfo::a32Bit;
- AttributeArraySize = AttributeExtLength;
- return true;
case DictTabInfo::ExtUnsigned:
- AttributeType = DictTabInfo::UnSignedType;
AttributeSize = DictTabInfo::a32Bit;
AttributeArraySize = AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtBigint:
- AttributeType = DictTabInfo::SignedType;
- AttributeSize = DictTabInfo::a64Bit;
- AttributeArraySize = AttributeExtLength;
- return true;
case DictTabInfo::ExtBigunsigned:
- AttributeType = DictTabInfo::UnSignedType;
AttributeSize = DictTabInfo::a64Bit;
AttributeArraySize = AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtFloat:
- AttributeType = DictTabInfo::FloatingPointType;
AttributeSize = DictTabInfo::a32Bit;
AttributeArraySize = AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtDouble:
- AttributeType = DictTabInfo::FloatingPointType;
AttributeSize = DictTabInfo::a64Bit;
AttributeArraySize = AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtOlddecimal:
- AttributeType = DictTabInfo::StringType;
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize =
(1 + AttributeExtPrecision + (int(AttributeExtScale) > 0)) *
AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtOlddecimalunsigned:
- AttributeType = DictTabInfo::StringType;
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize =
(0 + AttributeExtPrecision + (int(AttributeExtScale) > 0)) *
AttributeExtLength;
- return true;
+ break;
+ case DictTabInfo::ExtDecimal:
+ case DictTabInfo::ExtDecimalunsigned:
+ {
+ // copy from Field_new_decimal ctor
+ uint precision = AttributeExtPrecision;
+ uint scale = AttributeExtScale;
+ if (precision > DECIMAL_MAX_LENGTH || scale >= NOT_FIXED_DEC)
+ precision = DECIMAL_MAX_LENGTH;
+ uint bin_size = my_decimal_get_binary_size(precision, scale);
+ AttributeSize = DictTabInfo::an8Bit;
+ AttributeArraySize = bin_size * AttributeExtLength;
+ }
+ break;
case DictTabInfo::ExtChar:
case DictTabInfo::ExtBinary:
- AttributeType = DictTabInfo::StringType;
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtVarchar:
case DictTabInfo::ExtVarbinary:
- AttributeType = DictTabInfo::StringType;
+ if (AttributeExtLength > 0xff)
+ return false;
AttributeSize = DictTabInfo::an8Bit;
- AttributeArraySize = AttributeExtLength + 2;
- return true;
+ AttributeArraySize = AttributeExtLength + 1;
+ break;
case DictTabInfo::ExtDatetime:
- AttributeType = DictTabInfo::StringType;
+ // to fix
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 8 * AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtDate:
- AttributeType = DictTabInfo::StringType;
+ // to fix
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 3 * AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtBlob:
case DictTabInfo::ExtText:
- AttributeType = DictTabInfo::StringType;
AttributeSize = DictTabInfo::an8Bit;
- // head + inline part [ attr precision lower half ]
+ // head + inline part (length in precision lower half)
AttributeArraySize = (NDB_BLOB_HEAD_SIZE << 2) + (AttributeExtPrecision & 0xFFFF);
- return true;
+ break;
+ case DictTabInfo::ExtBit:
+ AttributeSize = DictTabInfo::aBit;
+ AttributeArraySize = AttributeExtLength;
+ break;
+ case DictTabInfo::ExtLongvarchar:
+ case DictTabInfo::ExtLongvarbinary:
+ if (AttributeExtLength > 0xffff)
+ return false;
+ AttributeSize = DictTabInfo::an8Bit;
+ AttributeArraySize = AttributeExtLength + 2;
+ break;
case DictTabInfo::ExtTime:
- AttributeType = DictTabInfo::StringType;
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 3 * AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtYear:
- AttributeType = DictTabInfo::StringType;
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 1 * AttributeExtLength;
- return true;
+ break;
case DictTabInfo::ExtTimestamp:
- AttributeType = DictTabInfo::StringType;
AttributeSize = DictTabInfo::an8Bit;
AttributeArraySize = 4 * AttributeExtLength;
- return true;
+ break;
+ default:
+ return false;
};
- return false;
+ return true;
}
inline void print(FILE *out) {
@@ -483,9 +461,7 @@ public:
fprintf(out, "AttributeKeyFlag = %d\n", AttributeKeyFlag);
fprintf(out, "AttributeStorage = %d\n", AttributeStorage);
fprintf(out, "AttributeNullableFlag = %d\n", AttributeNullableFlag);
- fprintf(out, "AttributeDGroup = %d\n", AttributeDGroup);
fprintf(out, "AttributeDKey = %d\n", AttributeDKey);
- fprintf(out, "AttributeStoredInd = %d\n", AttributeStoredInd);
fprintf(out, "AttributeGroup = %d\n", AttributeGroup);
fprintf(out, "AttributeAutoIncrement = %d\n", AttributeAutoIncrement);
fprintf(out, "AttributeExtType = %d\n", AttributeExtType);
@@ -519,6 +495,22 @@ private:
*/
Uint32 tabInfoData[DataLength];
+
+public:
+ enum Depricated
+ {
+ AttributeDGroup = 1009, //Default NotDGroup
+ AttributeStoredInd = 1011, //Default NotStored
+ SecondTableId = 17, //Mandatory between DICT's otherwise not allowed
+ FragmentKeyTypeVal = 16 //Default PrimaryKey
+ };
+
+ enum Unimplemented
+ {
+ TableStorageVal = 14, //Default StorageType::MainMemory
+ ScanOptimised = 15, //Default updateOptimised
+ AttributeGroup = 1012 //Default 0
+ };
};
#endif
diff --git a/ndb/include/kernel/signaldata/EventReport.hpp b/ndb/include/kernel/signaldata/EventReport.hpp
index 1ad6e1bf7ac..9822a0539cf 100644
--- a/ndb/include/kernel/signaldata/EventReport.hpp
+++ b/ndb/include/kernel/signaldata/EventReport.hpp
@@ -17,6 +17,7 @@
#ifndef SD_EVENT_REPORT_H
#define SD_EVENT_REPORT_H
+#include <ndb_logevent.h>
#include "SignalData.hpp"
/**
@@ -67,98 +68,21 @@ public:
4) Add SentHeartbeat in EventLogger::getText()
*/
- enum EventType {
- // CONNECTION
- Connected = 0,
- Disconnected = 1,
- CommunicationClosed = 2,
- CommunicationOpened = 3,
- ConnectedApiVersion = 51,
- // CHECKPOINT
- GlobalCheckpointStarted = 4,
- GlobalCheckpointCompleted = 5,
- LocalCheckpointStarted = 6,
- LocalCheckpointCompleted = 7,
- LCPStoppedInCalcKeepGci = 8,
- LCPFragmentCompleted = 9,
- // STARTUP
- NDBStartStarted = 10,
- NDBStartCompleted = 11,
- STTORRYRecieved = 12,
- StartPhaseCompleted = 13,
- CM_REGCONF = 14,
- CM_REGREF = 15,
- FIND_NEIGHBOURS = 16,
- NDBStopStarted = 17,
- NDBStopAborted = 18,
- StartREDOLog = 19,
- StartLog = 20,
- UNDORecordsExecuted = 21,
-
- // NODERESTART
- NR_CopyDict = 22,
- NR_CopyDistr = 23,
- NR_CopyFragsStarted = 24,
- NR_CopyFragDone = 25,
- NR_CopyFragsCompleted = 26,
-
- // NODEFAIL
- NodeFailCompleted = 27,
- NODE_FAILREP = 28,
- ArbitState = 29,
- ArbitResult = 30,
- GCP_TakeoverStarted = 31,
- GCP_TakeoverCompleted = 32,
- LCP_TakeoverStarted = 33,
- LCP_TakeoverCompleted = 34,
-
- // STATISTIC
- TransReportCounters = 35,
- OperationReportCounters = 36,
- TableCreated = 37,
- UndoLogBlocked = 38,
- JobStatistic = 39,
- SendBytesStatistic = 40,
- ReceiveBytesStatistic = 41,
- MemoryUsage = 50,
-
- // ERROR
- TransporterError = 42,
- TransporterWarning = 43,
- MissedHeartbeat = 44,
- DeadDueToHeartbeat = 45,
- WarningEvent = 46,
- // INFO
- SentHeartbeat = 47,
- CreateLogBytes = 48,
- InfoEvent = 49,
-
- //GREP
- GrepSubscriptionInfo = 52,
- GrepSubscriptionAlert = 53,
-
- //BACKUP
- BackupStarted = 54,
- BackupFailedToStart = 55,
- BackupCompleted = 56,
- BackupAborted = 57
- };
-
- void setEventType(EventType type);
- EventType getEventType() const;
+ void setEventType(Ndb_logevent_type type);
+ Ndb_logevent_type getEventType() const;
UintR eventType; // DATA 0
};
inline
void
-EventReport::setEventType(EventType type){
+EventReport::setEventType(Ndb_logevent_type type){
eventType = (UintR) type;
}
inline
-EventReport::EventType
+Ndb_logevent_type
EventReport::getEventType() const {
- return (EventType)eventType;
+ return (Ndb_logevent_type)eventType;
}
#endif
diff --git a/ndb/include/kernel/signaldata/GetTabInfo.hpp b/ndb/include/kernel/signaldata/GetTabInfo.hpp
index cb6e38872d3..6b223cab119 100644
--- a/ndb/include/kernel/signaldata/GetTabInfo.hpp
+++ b/ndb/include/kernel/signaldata/GetTabInfo.hpp
@@ -39,23 +39,16 @@ class GetTabInfoReq {
friend bool printGET_TABINFO_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public:
STATIC_CONST( SignalLength = 5 );
- // STATIC_CONST( MaxTableNameLengthInWords = 20 );
public:
- Uint32 senderData;
+ Uint32 senderData;
Uint32 senderRef;
-
- /**
- * 0 = request by id, 1 = request by name
- */
- Uint32 requestType;
-
+ Uint32 requestType; // Bitmask of GetTabInfoReq::RequestType
union {
- Uint32 tableId;
+ Uint32 tableId;
Uint32 tableNameLen;
};
Uint32 unused; // This is located here so that Req & Ref have the same format
- // Uint32 tableName[MaxTableNameLengthInWords];
-
+
enum RequestType {
RequestById = 0,
RequestByName = 1,
@@ -79,22 +72,21 @@ class GetTabInfoRef {
friend bool printGET_TABINFO_REF(FILE *, const Uint32 *, Uint32, Uint16);
public:
STATIC_CONST( SignalLength = 5 );
-
public:
- Uint32 senderData;
+ Uint32 senderData;
Uint32 senderRef;
- Uint32 requestType; // 0 = request by id, 1 = request by name
+ Uint32 requestType; // Bitmask of GetTabInfoReq::RequestType
union {
- Uint32 tableId;
+ Uint32 tableId;
Uint32 tableNameLen;
};
- Uint32 errorCode;
+ Uint32 errorCode;
enum ErrorCode {
- InvalidTableId = 709,
+ InvalidTableId = 709,
TableNotDefined = 723,
TableNameTooLong = 702,
- Busy = 701
+ Busy = 701
};
};
@@ -114,10 +106,10 @@ class GetTabInfoConf {
friend bool printGET_TABINFO_CONF(FILE *, const Uint32 *, Uint32, Uint16);
public:
STATIC_CONST( SignalLength = 4 );
-
+
SECTION( DICT_TAB_INFO = 0 );
public:
- Uint32 senderData;
+ Uint32 senderData;
Uint32 tableId;
Uint32 gci; // For table
Uint32 totalLen; // In words
diff --git a/ndb/include/kernel/signaldata/NextScan.hpp b/ndb/include/kernel/signaldata/NextScan.hpp
index 3a1882f94e8..a502a89108c 100644
--- a/ndb/include/kernel/signaldata/NextScan.hpp
+++ b/ndb/include/kernel/signaldata/NextScan.hpp
@@ -23,6 +23,7 @@ class NextScanReq {
friend class Dblqh;
friend class Dbacc;
friend class Dbtux;
+ friend class Dbtup;
public:
// two sets of defs picked from lqh/acc
enum ScanFlag {
@@ -50,6 +51,7 @@ private:
class NextScanConf {
friend class Dbacc;
friend class Dbtux;
+ friend class Dbtup;
friend class Dblqh;
public:
// length is less if no keyinfo or no next result
diff --git a/ndb/include/kernel/signaldata/ScanFrag.hpp b/ndb/include/kernel/signaldata/ScanFrag.hpp
index 41ea569c45d..f21a3eef7ac 100644
--- a/ndb/include/kernel/signaldata/ScanFrag.hpp
+++ b/ndb/include/kernel/signaldata/ScanFrag.hpp
@@ -56,6 +56,8 @@ public:
static Uint32 getKeyinfoFlag(const Uint32 & requestInfo);
static Uint32 getReadCommittedFlag(const Uint32 & requestInfo);
static Uint32 getRangeScanFlag(const Uint32 & requestInfo);
+ static Uint32 getDescendingFlag(const Uint32 & requestInfo);
+ static Uint32 getTupScanFlag(const Uint32 & requestInfo);
static Uint32 getAttrLen(const Uint32 & requestInfo);
static Uint32 getScanPrio(const Uint32 & requestInfo);
@@ -64,6 +66,8 @@ public:
static void setKeyinfoFlag(Uint32 & requestInfo, Uint32 keyinfo);
static void setReadCommittedFlag(Uint32 & requestInfo, Uint32 readCommitted);
static void setRangeScanFlag(Uint32 & requestInfo, Uint32 rangeScan);
+ static void setDescendingFlag(Uint32 & requestInfo, Uint32 descending);
+ static void setTupScanFlag(Uint32 & requestInfo, Uint32 tupScan);
static void setAttrLen(Uint32 & requestInfo, Uint32 attrLen);
static void setScanPrio(Uint32& requestInfo, Uint32 prio);
};
@@ -197,11 +201,13 @@ public:
* k = Keyinfo - 1 Bit 8
* r = read committed - 1 Bit 9
* x = range scan - 1 Bit 6
+ * z = descending - 1 Bit 10
+ * t = tup scan -1 Bit 11 (implies x=z=0)
* p = Scan prio - 4 Bits (12-15) -> max 15
*
* 1111111111222222222233
* 01234567890123456789012345678901
- * lxhkr ppppaaaaaaaaaaaaaaaa
+ * lxhkrztppppaaaaaaaaaaaaaaaa
*/
#define SF_LOCK_MODE_SHIFT (5)
#define SF_LOCK_MODE_MASK (1)
@@ -210,6 +216,8 @@ public:
#define SF_KEYINFO_SHIFT (8)
#define SF_READ_COMMITTED_SHIFT (9)
#define SF_RANGE_SCAN_SHIFT (6)
+#define SF_DESCENDING_SHIFT (10)
+#define SF_TUP_SCAN_SHIFT (11)
#define SF_ATTR_LEN_SHIFT (16)
#define SF_ATTR_LEN_MASK (65535)
@@ -243,6 +251,18 @@ ScanFragReq::getRangeScanFlag(const Uint32 & requestInfo){
inline
Uint32
+ScanFragReq::getDescendingFlag(const Uint32 & requestInfo){
+ return (requestInfo >> SF_DESCENDING_SHIFT) & 1;
+}
+
+inline
+Uint32
+ScanFragReq::getTupScanFlag(const Uint32 & requestInfo){
+ return (requestInfo >> SF_TUP_SCAN_SHIFT) & 1;
+}
+
+inline
+Uint32
ScanFragReq::getReadCommittedFlag(const Uint32 & requestInfo){
return (requestInfo >> SF_READ_COMMITTED_SHIFT) & 1;
}
@@ -303,6 +323,20 @@ ScanFragReq::setRangeScanFlag(UintR & requestInfo, UintR val){
inline
void
+ScanFragReq::setDescendingFlag(UintR & requestInfo, UintR val){
+ ASSERT_BOOL(val, "ScanFragReq::setDescendingFlag");
+ requestInfo |= (val << SF_DESCENDING_SHIFT);
+}
+
+inline
+void
+ScanFragReq::setTupScanFlag(UintR & requestInfo, UintR val){
+ ASSERT_BOOL(val, "ScanFragReq::setTupScanFlag");
+ requestInfo |= (val << SF_TUP_SCAN_SHIFT);
+}
+
+inline
+void
ScanFragReq::setAttrLen(UintR & requestInfo, UintR val){
ASSERT_MAX(val, SF_ATTR_LEN_MASK, "ScanFragReq::setAttrLen");
requestInfo |= (val << SF_ATTR_LEN_SHIFT);
diff --git a/ndb/include/kernel/signaldata/ScanTab.hpp b/ndb/include/kernel/signaldata/ScanTab.hpp
index 2029b16197e..8cb282270ff 100644
--- a/ndb/include/kernel/signaldata/ScanTab.hpp
+++ b/ndb/include/kernel/signaldata/ScanTab.hpp
@@ -33,8 +33,9 @@ class ScanTabReq {
/**
* Sender(s)
*/
- friend class NdbConnection;
- friend class NdbScanOperation;
+ friend class NdbTransaction;
+ friend class NdbScanOperation;
+ friend class NdbIndexScanOperation;
/**
* For printing
@@ -65,7 +66,12 @@ private:
UintR buddyConPtr; // DATA 8
UintR batch_byte_size; // DATA 9
UintR first_batch_size; // DATA 10
-
+
+ /**
+ * Optional
+ */
+ Uint32 distributionKey;
+
/**
* Get:ers for requestInfo
*/
@@ -74,8 +80,11 @@ private:
static Uint8 getHoldLockFlag(const UintR & requestInfo);
static Uint8 getReadCommittedFlag(const UintR & requestInfo);
static Uint8 getRangeScanFlag(const UintR & requestInfo);
+ static Uint8 getDescendingFlag(const UintR & requestInfo);
+ static Uint8 getTupScanFlag(const UintR & requestInfo);
static Uint8 getKeyinfoFlag(const UintR & requestInfo);
static Uint16 getScanBatch(const UintR & requestInfo);
+ static Uint8 getDistributionKeyFlag(const UintR & requestInfo);
/**
* Set:ers for requestInfo
@@ -86,8 +95,11 @@ private:
static void setHoldLockFlag(UintR & requestInfo, Uint32 flag);
static void setReadCommittedFlag(UintR & requestInfo, Uint32 flag);
static void setRangeScanFlag(UintR & requestInfo, Uint32 flag);
+ static void setDescendingFlag(UintR & requestInfo, Uint32 flag);
+ static void setTupScanFlag(UintR & requestInfo, Uint32 flag);
static void setKeyinfoFlag(UintR & requestInfo, Uint32 flag);
static void setScanBatch(Uint32& requestInfo, Uint32 sz);
+ static void setDistributionKeyFlag(Uint32& requestInfo, Uint32 flag);
};
/**
@@ -98,12 +110,15 @@ private:
h = Hold lock mode - 1 Bit 10
c = Read Committed - 1 Bit 11
k = Keyinfo - 1 Bit 12
+ t = Tup scan - 1 Bit 13
+ z = Descending (TUX) - 1 Bit 14
x = Range Scan (TUX) - 1 Bit 15
b = Scan batch - 10 Bit 16-25 (max 1023)
+ d = Distribution key flag
1111111111222222222233
01234567890123456789012345678901
- ppppppppl hck xbbbbbbbbbb
+ ppppppppl hcktzxbbbbbbbbbb
*/
#define PARALLELL_SHIFT (0)
@@ -124,9 +139,17 @@ private:
#define RANGE_SCAN_SHIFT (15)
#define RANGE_SCAN_MASK (1)
+#define DESCENDING_SHIFT (14)
+#define DESCENDING_MASK (1)
+
+#define TUP_SCAN_SHIFT (13)
+#define TUP_SCAN_MASK (1)
+
#define SCAN_BATCH_SHIFT (16)
#define SCAN_BATCH_MASK (1023)
+#define SCAN_DISTR_KEY_SHIFT (26)
+
inline
Uint8
ScanTabReq::getParallelism(const UintR & requestInfo){
@@ -158,6 +181,18 @@ ScanTabReq::getRangeScanFlag(const UintR & requestInfo){
}
inline
+Uint8
+ScanTabReq::getDescendingFlag(const UintR & requestInfo){
+ return (Uint8)((requestInfo >> DESCENDING_SHIFT) & DESCENDING_MASK);
+}
+
+inline
+Uint8
+ScanTabReq::getTupScanFlag(const UintR & requestInfo){
+ return (Uint8)((requestInfo >> TUP_SCAN_SHIFT) & TUP_SCAN_MASK);
+}
+
+inline
Uint16
ScanTabReq::getScanBatch(const Uint32 & requestInfo){
return (Uint16)((requestInfo >> SCAN_BATCH_SHIFT) & SCAN_BATCH_MASK);
@@ -205,6 +240,20 @@ ScanTabReq::setRangeScanFlag(UintR & requestInfo, Uint32 flag){
}
inline
+void
+ScanTabReq::setDescendingFlag(UintR & requestInfo, Uint32 flag){
+ ASSERT_BOOL(flag, "ScanTabReq::setDescendingFlag");
+ requestInfo |= (flag << DESCENDING_SHIFT);
+}
+
+inline
+void
+ScanTabReq::setTupScanFlag(UintR & requestInfo, Uint32 flag){
+ ASSERT_BOOL(flag, "ScanTabReq::setTupScanFlag");
+ requestInfo |= (flag << TUP_SCAN_SHIFT);
+}
+
+inline
void
ScanTabReq::setScanBatch(Uint32 & requestInfo, Uint32 flag){
ASSERT_MAX(flag, SCAN_BATCH_MASK, "ScanTabReq::setScanBatch");
@@ -225,6 +274,18 @@ ScanTabReq::setKeyinfoFlag(UintR & requestInfo, Uint32 flag){
requestInfo |= (flag << KEYINFO_SHIFT);
}
+inline
+Uint8
+ScanTabReq::getDistributionKeyFlag(const UintR & requestInfo){
+ return (Uint8)((requestInfo >> SCAN_DISTR_KEY_SHIFT) & 1);
+}
+
+inline
+void
+ScanTabReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){
+ ASSERT_BOOL(flag, "ScanTabReq::setKeyinfoFlag");
+ requestInfo |= (flag << SCAN_DISTR_KEY_SHIFT);
+}
/**
*
@@ -235,7 +296,7 @@ class ScanTabConf {
/**
* Reciver(s)
*/
- friend class NdbConnection; // Reciver
+ friend class NdbTransaction; // Reciver
/**
* Sender(s)
@@ -303,7 +364,7 @@ class ScanTabRef {
/**
* Reciver(s)
*/
- friend class NdbConnection; // Reciver
+ friend class NdbTransaction; // Reciver
/**
* Sender(s)
diff --git a/ndb/include/kernel/signaldata/SignalData.hpp b/ndb/include/kernel/signaldata/SignalData.hpp
index b0cfbc1540c..0591a85d6e6 100644
--- a/ndb/include/kernel/signaldata/SignalData.hpp
+++ b/ndb/include/kernel/signaldata/SignalData.hpp
@@ -18,8 +18,8 @@
#define SIGNAL_DATA_H
#include <ndb_global.h>
-#include <ndb_limits.h>
-#include <kernel_types.h>
+#include <kernel/ndb_limits.h>
+#include <kernel/kernel_types.h>
#include <BaseString.hpp>
#define ASSERT_BOOL(flag, message) assert(flag<=1)
@@ -177,9 +177,16 @@ GSN_PRINT_SIGNATURE(printFAIL_REP);
GSN_PRINT_SIGNATURE(printDISCONNECT_REP);
GSN_PRINT_SIGNATURE(printSUB_CREATE_REQ);
GSN_PRINT_SIGNATURE(printSUB_CREATE_CONF);
+GSN_PRINT_SIGNATURE(printSUB_CREATE_REF);
+GSN_PRINT_SIGNATURE(printSUB_REMOVE_REQ);
+GSN_PRINT_SIGNATURE(printSUB_REMOVE_CONF);
+GSN_PRINT_SIGNATURE(printSUB_REMOVE_REF);
GSN_PRINT_SIGNATURE(printSUB_START_REQ);
GSN_PRINT_SIGNATURE(printSUB_START_REF);
GSN_PRINT_SIGNATURE(printSUB_START_CONF);
+GSN_PRINT_SIGNATURE(printSUB_STOP_REQ);
+GSN_PRINT_SIGNATURE(printSUB_STOP_REF);
+GSN_PRINT_SIGNATURE(printSUB_STOP_CONF);
GSN_PRINT_SIGNATURE(printSUB_SYNC_REQ);
GSN_PRINT_SIGNATURE(printSUB_SYNC_REF);
GSN_PRINT_SIGNATURE(printSUB_SYNC_CONF);
diff --git a/ndb/include/kernel/signaldata/SumaImpl.hpp b/ndb/include/kernel/signaldata/SumaImpl.hpp
index 89ade067dcd..75fb65e1ad2 100644
--- a/ndb/include/kernel/signaldata/SumaImpl.hpp
+++ b/ndb/include/kernel/signaldata/SumaImpl.hpp
@@ -592,11 +592,11 @@ public:
Uint32 subscriptionId;
Uint32 subscriptionKey;
- Uint32 err;
union { // Haven't decide what to call it
Uint32 senderData;
Uint32 subscriberData;
};
+ Uint32 err;
};
class SumaStartMe {
diff --git a/ndb/include/kernel/signaldata/TcCommit.hpp b/ndb/include/kernel/signaldata/TcCommit.hpp
index b7f3fbbb361..dcbca0cb6f2 100644
--- a/ndb/include/kernel/signaldata/TcCommit.hpp
+++ b/ndb/include/kernel/signaldata/TcCommit.hpp
@@ -33,10 +33,10 @@ class TcCommitConf {
* Reciver(s)
*/
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
public:
- STATIC_CONST( SignalLength = 3 );
+ STATIC_CONST( SignalLength = 4 );
private:
/**
@@ -49,6 +49,7 @@ private:
Uint32 transId1;
Uint32 transId2;
+ Uint32 gci;
};
class TcCommitRef {
@@ -60,7 +61,7 @@ class TcCommitRef {
/**
* Reciver(s)
*/
- friend class NdbConnection;
+ friend class NdbTransaction;
public:
STATIC_CONST( SignalLength = 4 );
diff --git a/ndb/include/kernel/signaldata/TcHbRep.hpp b/ndb/include/kernel/signaldata/TcHbRep.hpp
index 58ab015917a..7e701b510f9 100644
--- a/ndb/include/kernel/signaldata/TcHbRep.hpp
+++ b/ndb/include/kernel/signaldata/TcHbRep.hpp
@@ -36,7 +36,7 @@ class TcHbRep {
/**
* Sender(s)
*/
- friend class NdbConnection;
+ friend class NdbTransaction;
/**
* For printing
diff --git a/ndb/include/kernel/signaldata/TcIndx.hpp b/ndb/include/kernel/signaldata/TcIndx.hpp
index 764d4e9fcd7..c5e7d2489ba 100644
--- a/ndb/include/kernel/signaldata/TcIndx.hpp
+++ b/ndb/include/kernel/signaldata/TcIndx.hpp
@@ -18,379 +18,7 @@
#define TC_INDX_H
#include "SignalData.hpp"
-
-class TcIndxReq {
- /**
- * Reciver(s)
- */
- friend class Dbtc; // Reciver
-
- /**
- * Sender(s)
- */
- friend class NdbIndexOperation;
-
- /**
- * For printing
- */
- friend bool printTCINDXREQ(FILE *, const Uint32 *, Uint32, Uint16);
-
-public:
- /**
- * Length of signal
- */
- STATIC_CONST( StaticLength = 8 );
- STATIC_CONST( SignalLength = 25 );
- STATIC_CONST( MaxKeyInfo = 8 );
- STATIC_CONST( MaxAttrInfo = 5 );
-
-private:
-
- enum CommitType {
- CommitIfFailFree = 0,
- TryCommit = 1,
- CommitAsMuchAsPossible = 2
- };
-
- /**
- * DATA VARIABLES
- */
-//-------------------------------------------------------------
-// Unconditional part. First 8 words
-//-------------------------------------------------------------
- UintR apiConnectPtr; // DATA 0
- UintR senderData; // DATA 1
- UintR attrLen; // DATA 2 (including API Version)
- UintR indexId; // DATA 3
- UintR requestInfo; // DATA 4
- UintR indexSchemaVersion; // DATA 5
- UintR transId1; // DATA 6
- UintR transId2; // DATA 7
-//-------------------------------------------------------------
-// Conditional part. Those four words will be sent only if their
-// indicator is set.
-//-------------------------------------------------------------
- UintR scanInfo; // DATA 8
- UintR distrGroupHashValue; // DATA 9
- UintR distributionKeySize; // DATA 10
- UintR storedProcId; // DATA 11
-
-//-------------------------------------------------------------
-// Variable sized key and attrinfo part. Those will be placed to
-// pack the signal in an appropriate manner.
-//-------------------------------------------------------------
- UintR keyInfo[MaxKeyInfo]; // DATA 12 - 19
- UintR attrInfo[MaxAttrInfo]; // DATA 20 - 24
-
- static Uint8 getAPIVersion(const UintR & attrLen);
-
- /**
- * Get:ers for requestInfo
- */
- static Uint8 getCommitFlag(const UintR & requestInfo);
- static Uint8 getCommitType(const UintR & requestInfo);
- static Uint8 getStartFlag(const UintR & requestInfo);
- static Uint8 getSimpleFlag(const UintR & requestInfo);
- static Uint8 getDirtyFlag(const UintR & requestInfo);
- static Uint8 getInterpretedFlag(const UintR & requestInfo);
- static Uint8 getDistributionGroupFlag(const UintR & requestInfo);
- static Uint8 getDistributionGroupTypeFlag(const UintR & requestInfo);
- static Uint8 getDistributionKeyFlag(const UintR & requestInfo);
- static Uint8 getScanIndFlag(const UintR & requestInfo);
-
- static Uint8 getOperationType(const UintR & requestInfo);
-
- static Uint16 getIndexLength(const UintR & requestInfo);
- static Uint8 getAIInTcIndxReq(const UintR & requestInfo);
-
- /**
- * Get:ers for scanInfo
- */
-
- static void setAPIVersion(UintR & attrLen, Uint16 apiVersion);
-
- /**
- * Set:ers for requestInfo
- */
- static void clearRequestInfo(UintR & requestInfo);
- static void setCommitType(UintR & requestInfo, Uint32 type);
- static void setCommitFlag(UintR & requestInfo, Uint32 flag);
- static void setStartFlag(UintR & requestInfo, Uint32 flag);
- static void setSimpleFlag(UintR & requestInfo, Uint32 flag);
- static void setDirtyFlag(UintR & requestInfo, Uint32 flag);
- static void setInterpretedFlag(UintR & requestInfo, Uint32 flag);
- static void setDistributionGroupFlag(UintR & requestInfo, Uint32 flag);
- static void setDistributionGroupTypeFlag(UintR & requestInfo, Uint32 flag);
- static void setDistributionKeyFlag(UintR & requestInfo, Uint32 flag);
- static void setScanIndFlag(UintR & requestInfo, Uint32 flag);
-
- static void setOperationType(UintR & requestInfo, Uint32 type);
-
- static void setIndexLength(UintR & requestInfo, Uint32 len);
- static void setAIInTcIndxReq(UintR & requestInfo, Uint32 len);
-
- /**
- * Set:ers for scanInfo
- */
-
-};
-
-#define API_VER_NO_SHIFT (16)
-#define API_VER_NO_MASK (65535)
-
-/**
- * Request Info
- *
- a = Attr Info in TCINDXREQ - 3 Bits -> Max 7 (Bit 16-18)
- b = Distribution Key Ind - 1 Bit 2
- c = Commit Indicator - 1 Bit 4
- d = Dirty Indicator - 1 Bit 0
- e = Scan Indicator - 1 Bit 14
- g = Distribution Group Ind - 1 Bit 1
- i = Interpreted Indicator - 1 Bit 15
- k = Index lengt - 12 Bits -> Max 4095 (Bit 20 - 31)
- o = Operation Type - 3 Bits -> Max 7 (Bit 5-7)
- p = Simple Indicator - 1 Bit 8
- s = Start Indicator - 1 Bit 11
- t = Distribution GroupType - 1 Bit 3
- y = Commit Type - 2 Bit 12-13
- x = Last Op in execute - 1 Bit 19
-
- 1111111111222222222233
- 01234567890123456789012345678901
- dgbtcooop syyeiaaa-kkkkkkkkkkkk
-*/
-
-#define COMMIT_SHIFT (4)
-#define START_SHIFT (11)
-#define SIMPLE_SHIFT (8)
-#define DIRTY_SHIFT (0)
-#define INTERPRETED_SHIFT (15)
-#define DISTR_GROUP_SHIFT (1)
-#define DISTR_GROUP_TYPE_SHIFT (3)
-#define DISTR_KEY_SHIFT (2)
-#define SCAN_SHIFT (14)
-
-#define OPERATION_SHIFT (5)
-#define OPERATION_MASK (7)
-
-#define AINFO_SHIFT (16)
-#define AINFO_MASK (7)
-
-#define INDEX_LEN_SHIFT (20)
-#define INDEX_LEN_MASK (4095)
-
-#define COMMIT_TYPE_SHIFT (12)
-#define COMMIT_TYPE_MASK (3)
-
-#define LAST_OP_IN_EXEC_SHIFT (19)
-
-/**
- * Scan Info
- *
-
-
- 1111111111222222222233
- 01234567890123456789012345678901
-
-*/
-
-inline
-Uint8
-TcIndxReq::getCommitFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> COMMIT_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getCommitType(const UintR & requestInfo){
- return (Uint8)((requestInfo >> COMMIT_TYPE_SHIFT) & COMMIT_TYPE_MASK);
-}
-
-inline
-Uint8
-TcIndxReq::getStartFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> START_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getSimpleFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> SIMPLE_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDirtyFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> DIRTY_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getInterpretedFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> INTERPRETED_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionGroupFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> DISTR_GROUP_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionGroupTypeFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> DISTR_GROUP_TYPE_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionKeyFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> DISTR_KEY_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getScanIndFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> SCAN_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getOperationType(const UintR & requestInfo){
- return (Uint8)((requestInfo >> OPERATION_SHIFT) & OPERATION_MASK);
-}
-
-inline
-Uint16
-TcIndxReq::getIndexLength(const UintR & requestInfo){
- return (Uint16)((requestInfo >> INDEX_LEN_SHIFT) & INDEX_LEN_MASK);
-}
-
-inline
-Uint8
-TcIndxReq::getAIInTcIndxReq(const UintR & requestInfo){
- return (Uint8)((requestInfo >> AINFO_SHIFT) & AINFO_MASK);
-}
-
-inline
-void
-TcIndxReq::clearRequestInfo(UintR & requestInfo){
- requestInfo = 0;
-}
-
-inline
-void
-TcIndxReq::setCommitType(UintR & requestInfo, Uint32 type){
- ASSERT_MAX(type, COMMIT_TYPE_MASK, "TcIndxReq::setCommitType");
- requestInfo |= (type << COMMIT_TYPE_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setCommitFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setCommitFlag");
- requestInfo &= ~(1 << COMMIT_SHIFT);
- requestInfo |= (flag << COMMIT_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setStartFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setStartFlag");
- requestInfo &= ~(1 << START_SHIFT);
- requestInfo |= (flag << START_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setSimpleFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setSimpleFlag");
- requestInfo &= ~(1 << SIMPLE_SHIFT);
- requestInfo |= (flag << SIMPLE_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setDirtyFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setDirtyFlag");
- requestInfo &= ~(1 << DIRTY_SHIFT);
- requestInfo |= (flag << DIRTY_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setInterpretedFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setInterpretedFlag");
- requestInfo &= ~(1 << INTERPRETED_SHIFT);
- requestInfo |= (flag << INTERPRETED_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setDistributionGroupTypeFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setDistributionGroupTypeFlag");
- requestInfo &= ~(1 << DISTR_GROUP_TYPE_SHIFT);
- requestInfo |= (flag << DISTR_GROUP_TYPE_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setDistributionGroupFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setDistributionGroupFlag");
- requestInfo &= ~(1 << DISTR_GROUP_SHIFT);
- requestInfo |= (flag << DISTR_GROUP_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setDistributionKeyFlag");
- requestInfo &= ~(1 << DISTR_KEY_SHIFT);
- requestInfo |= (flag << DISTR_KEY_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setScanIndFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setScanIndFlag");
- requestInfo &= ~(1 << SCAN_SHIFT);
- requestInfo |= (flag << SCAN_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setOperationType(UintR & requestInfo, Uint32 type){
- ASSERT_MAX(type, OPERATION_MASK, "TcIndxReq::setOperationType");
- requestInfo |= (type << OPERATION_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setIndexLength(UintR & requestInfo, Uint32 len){
- ASSERT_MAX(len, INDEX_LEN_MASK, "TcIndxReq::setKeyLength");
- requestInfo |= (len << INDEX_LEN_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setAIInTcIndxReq(UintR & requestInfo, Uint32 len){
- ASSERT_MAX(len, AINFO_MASK, "TcIndxReq::setAIInTcIndxReq");
- requestInfo |= (len << AINFO_SHIFT);
-}
-
-inline
-Uint8
-TcIndxReq::getAPIVersion(const UintR & anAttrLen){
- return (Uint16)((anAttrLen >> API_VER_NO_SHIFT) & API_VER_NO_MASK);
-}
-
-inline
-void
-TcIndxReq::setAPIVersion(UintR & anAttrLen, Uint16 apiVersion){
-// ASSERT_MAX(apiVersion, API_VER_NO_MASK, "TcIndxReq::setAPIVersion");
- anAttrLen |= (apiVersion << API_VER_NO_SHIFT);
-}
+#include "TcKeyReq.hpp"
class TcIndxConf {
@@ -398,7 +26,7 @@ class TcIndxConf {
* Reciver(s)
*/
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
/**
* Sender(s)
@@ -495,34 +123,4 @@ TcIndxConf::setMarkerFlag(Uint32 & confInfo, Uint32 flag){
confInfo |= (flag << 17);
}
-class TcIndxRef {
-
- /**
- * Reciver(s)
- */
- friend class NdbIndexOperation;
-
- /**
- * Sender(s)
- */
- friend class Dbtc;
-
- /**
- * For printing
- */
- friend bool printTCINDXREF(FILE *, const Uint32 *, Uint32, Uint16);
-
-public:
- /**
- * Length of signal
- */
-public:
- STATIC_CONST( SignalLength = 4 );
-
-private:
- Uint32 connectPtr;
- Uint32 transId[2];
- Uint32 errorCode;
-};
-
#endif
diff --git a/ndb/include/kernel/signaldata/TcKeyConf.hpp b/ndb/include/kernel/signaldata/TcKeyConf.hpp
index 277872b990b..c23e94951dc 100644
--- a/ndb/include/kernel/signaldata/TcKeyConf.hpp
+++ b/ndb/include/kernel/signaldata/TcKeyConf.hpp
@@ -27,7 +27,7 @@ class TcKeyConf {
* Reciver(s)
*/
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class Ndbcntr;
friend class DbUtil;
diff --git a/ndb/include/kernel/signaldata/TcKeyFailConf.hpp b/ndb/include/kernel/signaldata/TcKeyFailConf.hpp
index d8207b63262..7c0a766df40 100644
--- a/ndb/include/kernel/signaldata/TcKeyFailConf.hpp
+++ b/ndb/include/kernel/signaldata/TcKeyFailConf.hpp
@@ -33,7 +33,7 @@ class TcKeyFailConf {
* Reciver(s)
*/
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
public:
STATIC_CONST( SignalLength = 3 );
diff --git a/ndb/include/kernel/signaldata/TcKeyReq.hpp b/ndb/include/kernel/signaldata/TcKeyReq.hpp
index 9e42f2a70d5..d7c11ca773c 100644
--- a/ndb/include/kernel/signaldata/TcKeyReq.hpp
+++ b/ndb/include/kernel/signaldata/TcKeyReq.hpp
@@ -142,7 +142,7 @@ private:
* Get:ers for scanInfo
*/
static Uint8 getTakeOverScanFlag(const UintR & scanInfo);
- static Uint16 getTakeOverScanNode(const UintR & scanInfo);
+ static Uint16 getTakeOverScanFragment(const UintR & scanInfo);
static Uint32 getTakeOverScanInfo(const UintR & scanInfo);
@@ -171,7 +171,7 @@ private:
* Set:ers for scanInfo
*/
static void setTakeOverScanFlag(UintR & scanInfo, Uint8 flag);
- static void setTakeOverScanNode(UintR & scanInfo, Uint16 node);
+ static void setTakeOverScanFragment(UintR & scanInfo, Uint16 fragment);
static void setTakeOverScanInfo(UintR & scanInfo, Uint32 aScanInfo);
};
@@ -238,8 +238,8 @@ private:
#define TAKE_OVER_SHIFT (0)
-#define TAKE_OVER_NODE_SHIFT (20)
-#define TAKE_OVER_NODE_MASK (4095)
+#define TAKE_OVER_FRAG_SHIFT (20)
+#define TAKE_OVER_FRAG_MASK (4095)
#define SCAN_INFO_SHIFT (1)
#define SCAN_INFO_MASK (262143)
@@ -485,8 +485,8 @@ TcKeyReq::getTakeOverScanFlag(const UintR & scanInfo){
inline
Uint16
-TcKeyReq::getTakeOverScanNode(const UintR & scanInfo){
- return (Uint16)((scanInfo >> TAKE_OVER_NODE_SHIFT) & TAKE_OVER_NODE_MASK);
+TcKeyReq::getTakeOverScanFragment(const UintR & scanInfo){
+ return (Uint16)((scanInfo >> TAKE_OVER_FRAG_SHIFT) & TAKE_OVER_FRAG_MASK);
}
inline
@@ -505,9 +505,9 @@ TcKeyReq::setTakeOverScanFlag(UintR & scanInfo, Uint8 flag){
inline
void
-TcKeyReq::setTakeOverScanNode(UintR & scanInfo, Uint16 node){
+TcKeyReq::setTakeOverScanFragment(UintR & scanInfo, Uint16 node){
// ASSERT_MAX(node, TAKE_OVER_NODE_MASK, "TcKeyReq::setTakeOverScanNode");
- scanInfo |= (node << TAKE_OVER_NODE_SHIFT);
+ scanInfo |= (node << TAKE_OVER_FRAG_SHIFT);
}
inline
diff --git a/ndb/include/kernel/signaldata/TcRollbackRep.hpp b/ndb/include/kernel/signaldata/TcRollbackRep.hpp
index b00731a04a6..febbd4f86b1 100644
--- a/ndb/include/kernel/signaldata/TcRollbackRep.hpp
+++ b/ndb/include/kernel/signaldata/TcRollbackRep.hpp
@@ -23,7 +23,7 @@ class TcRollbackRep {
/**
* Sender(s)
*/
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class DbUtil;
/**
diff --git a/ndb/include/kernel/signaldata/TransIdAI.hpp b/ndb/include/kernel/signaldata/TransIdAI.hpp
index 4df7bf2a126..5beaf6eba4b 100755
--- a/ndb/include/kernel/signaldata/TransIdAI.hpp
+++ b/ndb/include/kernel/signaldata/TransIdAI.hpp
@@ -28,7 +28,7 @@ class TransIdAI {
/**
* Receiver(s)
*/
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class Dbtc;
friend class Dbutil;
friend class Dblqh;
diff --git a/ndb/include/kernel/signaldata/TupFrag.hpp b/ndb/include/kernel/signaldata/TupFrag.hpp
index c132b19c50a..8acb3d28bd6 100644
--- a/ndb/include/kernel/signaldata/TupFrag.hpp
+++ b/ndb/include/kernel/signaldata/TupFrag.hpp
@@ -104,9 +104,9 @@ public:
STATIC_CONST( SignalLength = 2 );
enum ErrorCode {
NoError = 0,
- InvalidRequest = 800,
- NoFreeFragment = 604,
- NoFreeAttributes = 827
+ InvalidRequest = 903,
+ NoFreeFragment = 904,
+ NoFreeAttributes = 905
};
private:
Uint32 userPtr;
@@ -145,7 +145,8 @@ public:
STATIC_CONST( SignalLength = 2 );
enum ErrorCode {
NoError = 0,
- InvalidCharset = 743
+ InvalidCharset = 743,
+ TooManyBitsUsed = 831
};
private:
Uint32 userPtr;
@@ -185,9 +186,9 @@ public:
STATIC_CONST( SignalLength = 2 );
enum ErrorCode {
NoError = 0,
- InvalidAttributeType = 742,
- InvalidCharset = 743,
- InvalidNodeSize = 832
+ InvalidAttributeType = 906,
+ InvalidCharset = 907,
+ InvalidNodeSize = 908
};
private:
Uint32 userPtr;
diff --git a/ndb/include/kernel/signaldata/TuxBound.hpp b/ndb/include/kernel/signaldata/TuxBound.hpp
index 87ce3c3c098..7e12897407b 100644
--- a/ndb/include/kernel/signaldata/TuxBound.hpp
+++ b/ndb/include/kernel/signaldata/TuxBound.hpp
@@ -34,7 +34,9 @@ public:
enum ErrorCode {
InvalidAttrInfo = 4110,
InvalidBounds = 4259,
- OutOfBuffers = 873
+ OutOfBuffers = 873,
+ InvalidCharFormat = 744,
+ TooMuchAttrInfo = 823
};
STATIC_CONST( SignalLength = 3 );
private:
@@ -50,6 +52,8 @@ private:
* Number of words of bound info included after fixed signal data.
*/
Uint32 boundAiLength;
+
+ Uint32 data[1];
};
#endif
diff --git a/ndb/include/kernel/trigger_definitions.h b/ndb/include/kernel/trigger_definitions.h
index 7ce74877de4..11410654a15 100644
--- a/ndb/include/kernel/trigger_definitions.h
+++ b/ndb/include/kernel/trigger_definitions.h
@@ -56,6 +56,7 @@ struct TriggerActionTime {
};
struct TriggerEvent {
+ /** TableEvent must match 1 << TriggerEvent */
enum Value {
TE_INSERT = 0,
TE_DELETE = 1,
diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h
index 26b9dc65947..924d65c2847 100644
--- a/ndb/include/mgmapi/mgmapi.h
+++ b/ndb/include/mgmapi/mgmapi.h
@@ -18,31 +18,121 @@
#define MGMAPI_H
/**
- * @mainpage NDB Cluster Management API
+ * @mainpage MySQL Cluster Management API
*
- * The NDB Cluster Management API (MGM API) is a C API
- * that is used to:
- * - Start/stop database nodes (DB nodes)
- * - Start/stop NDB Cluster backups
- * - Control the NDB Cluster log
- * - Other administrative tasks
+ * The MySQL Cluster Management API (MGM API) is a C language API
+ * that is used for:
+ * - Starting and stopping database nodes (ndbd processes)
+ * - Starting and stopping Cluster backups
+ * - Controlling the NDB Cluster log
+ * - Performing other administrative tasks
*
- * @section General Concepts
+ * @section secMgmApiGeneral General Concepts
*
- * Each MGM API function needs a management server handle
- * (of type Mgm_C_Api::NdbMgmHandle).
- * This handle is initally is created by calling the
- * function ndb_mgm_create_handle().
+ * Each MGM API function needs a management server handle
+ * of type @ref NdbMgmHandle.
+ * This handle is created by calling the function
+ * function ndb_mgm_create_handle() and freed by calling
+ * ndb_mgm_destroy_handle().
*
- * A function can return:
- * -# An integer value.
- * If it returns -1 then this indicates an error, and then
- * -# A pointer value. If it returns NULL then check the latest error.
- * If it didn't return NULL, then a "something" is returned.
- * This "something" has to be free:ed by the user of the MGM API.
+ * A function can return any of the following:
+ * -# An integer value, with
+ * a value of <b>-1</b> indicating an error.
+ * -# A non-constant pointer value. A <var>NULL</var> value indicates an error;
+ * otherwise, the return value must be freed
+ * by the programmer
+ * -# A constant pointer value, with a <var>NULL</var> value indicating an error.
+ * The returned value should <em>not</em> be freed.
*
- * If there are an error, then the get latest error functions
- * can be used to check what the error was.
+ * Error conditions can be identified by using the appropriate
+ * error-reporting functions ndb_mgm_get_latest_error() and
+ * @ref ndb_mgm_error.
+ *
+ * Here is an example using the MGM API (without error handling for brevity's sake).
+ * @code
+ * NdbMgmHandle handle= ndb_mgm_create_handle();
+ * ndb_mgm_connect(handle,0,0,0);
+ * struct ndb_mgm_cluster_state *state= ndb_mgm_get_status(handle);
+ * for(int i=0; i < state->no_of_nodes; i++)
+ * {
+ * struct ndb_mgm_node_state *node_state= &state->node_states[i];
+ * printf("node with ID=%d ", node_state->node_id);
+ * if(node_state->version != 0)
+ * printf("connected\n");
+ * else
+ * printf("not connected\n");
+ * }
+ * free((void*)state);
+ * ndb_mgm_destroy_handle(&handle);
+ * @endcode
+ *
+ * @section secLogEvents Log Events
+ *
+ * The database nodes and management server(s) regularly and on specific
+ * occations report on various log events that occurs in the cluster. These
+ * log events are written to the cluster log. Optionally a mgmapi client
+ * may listen to these events by using the method ndb_mgm_listen_event().
+ * Each log event belongs to a category, @ref ndb_mgm_event_category, and
+ * has a severity, @ref ndb_mgm_event_severity, associated with it. Each
+ * log event also has a level (0-15) associated with it.
+ *
+ * Which log events that come out is controlled with ndb_mgm_listen_event(),
+ * ndb_mgm_set_clusterlog_loglevel(), and
+ * ndb_mgm_set_clusterlog_severity_filter().
+ *
+ * Below is an example of how to listen to events related to backup.
+ *
+ * @code
+ * int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 };
+ * int fd = ndb_mgm_listen_event(handle, filter);
+ * @endcode
+ *
+ *
+ * @section secSLogEvents Structured Log Events
+ *
+ * The following steps are involved:
+ * - Create a NdbEventLogHandle using ndb_mgm_create_logevent_handle()
+ * - Wait and store log events using ndb_logevent_get_next()
+ * - The log event data is available in the struct ndb_logevent. The
+ * data which is specific to a particular event is stored in a union
+ * between structs so use ndb_logevent::type to decide which struct
+ * is valid.
+ *
+ * Sample code for listening to Backup related events. The availaable log
+ * events are listed in @ref ndb_logevent.h
+ *
+ * @code
+ * int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 };
+ * NdbEventLogHandle le_handle= ndb_mgm_create_logevent_handle(handle, filter);
+ * struct ndb_logevent le;
+ * int r= ndb_logevent_get_next(le_handle,&le,0);
+ * if (r < 0) error
+ * else if (r == 0) no event
+ *
+ * switch (le.type)
+ * {
+ * case NDB_LE_BackupStarted:
+ * ... le.BackupStarted.starting_node;
+ * ... le.BackupStarted.backup_id;
+ * break;
+ * case NDB_LE_BackupFailedToStart:
+ * ... le.BackupFailedToStart.error;
+ * break;
+ * case NDB_LE_BackupCompleted:
+ * ... le.BackupCompleted.stop_gci;
+ * break;
+ * case NDB_LE_BackupAborted:
+ * ... le.BackupStarted.backup_id;
+ * break;
+ * default:
+ * break;
+ * }
+ * @endcode
+ */
+
+/*
+ * @page ndb_logevent.h ndb_logevent.h
+ * @include ndb_logevent.h
*/
/** @addtogroup MGM_C_API
@@ -51,6 +141,7 @@
#include <stdio.h>
#include <ndb_types.h>
+#include "ndb_logevent.h"
#include "mgmapi_config_parameters.h"
#ifdef __cplusplus
@@ -66,82 +157,116 @@ extern "C" {
* NDB Cluster node types
*/
enum ndb_mgm_node_type {
- NDB_MGM_NODE_TYPE_UNKNOWN = -1, /*< Node type not known*/
- NDB_MGM_NODE_TYPE_API = NODE_TYPE_API,/*< An application node (API)*/
- NDB_MGM_NODE_TYPE_NDB = NODE_TYPE_DB, /*< A database node (DB)*/
- NDB_MGM_NODE_TYPE_MGM = NODE_TYPE_MGM,/*< A mgmt server node (MGM)*/
- NDB_MGM_NODE_TYPE_REP = NODE_TYPE_REP,/*< A replication node */
-
- NDB_MGM_NODE_TYPE_MIN = 0, /*< Min valid value*/
- NDB_MGM_NODE_TYPE_MAX = 3 /*< Max valid value*/
+ NDB_MGM_NODE_TYPE_UNKNOWN = -1 /** Node type not known*/
+ ,NDB_MGM_NODE_TYPE_API /** An application (NdbApi) node */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = NODE_TYPE_API
+#endif
+ ,NDB_MGM_NODE_TYPE_NDB /** A database node */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = NODE_TYPE_DB
+#endif
+ ,NDB_MGM_NODE_TYPE_MGM /** A management server node */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = NODE_TYPE_MGM
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ,NDB_MGM_NODE_TYPE_REP = NODE_TYPE_REP /** A replication node */
+ ,NDB_MGM_NODE_TYPE_MIN = 0 /** Min valid value*/
+ ,NDB_MGM_NODE_TYPE_MAX = 3 /** Max valid value*/
+#endif
};
/**
* Database node status
*/
enum ndb_mgm_node_status {
- NDB_MGM_NODE_STATUS_UNKNOWN = 0, /*< Node status not known*/
- NDB_MGM_NODE_STATUS_NO_CONTACT = 1, /*< No contact with node*/
- NDB_MGM_NODE_STATUS_NOT_STARTED = 2, /*< Has not run starting protocol*/
- NDB_MGM_NODE_STATUS_STARTING = 3, /*< Is running starting protocol*/
- NDB_MGM_NODE_STATUS_STARTED = 4, /*< Running*/
- NDB_MGM_NODE_STATUS_SHUTTING_DOWN = 5, /*< Is shutting down*/
- NDB_MGM_NODE_STATUS_RESTARTING = 6, /*< Is restarting*/
- NDB_MGM_NODE_STATUS_SINGLEUSER = 7, /*< Maintenance mode*/
- NDB_MGM_NODE_STATUS_RESUME = 8, /*< Resume mode*/
-
- NDB_MGM_NODE_STATUS_MIN = 0, /*< Min valid value*/
- NDB_MGM_NODE_STATUS_MAX = 6 /*< Max valid value*/
+ /** Node status not known*/
+ NDB_MGM_NODE_STATUS_UNKNOWN = 0,
+ /** No contact with node*/
+ NDB_MGM_NODE_STATUS_NO_CONTACT = 1,
+ /** Has not run starting protocol*/
+ NDB_MGM_NODE_STATUS_NOT_STARTED = 2,
+ /** Is running starting protocol*/
+ NDB_MGM_NODE_STATUS_STARTING = 3,
+ /** Running*/
+ NDB_MGM_NODE_STATUS_STARTED = 4,
+ /** Is shutting down*/
+ NDB_MGM_NODE_STATUS_SHUTTING_DOWN = 5,
+ /** Is restarting*/
+ NDB_MGM_NODE_STATUS_RESTARTING = 6,
+ /** Maintenance mode*/
+ NDB_MGM_NODE_STATUS_SINGLEUSER = 7,
+ /** Resume mode*/
+ NDB_MGM_NODE_STATUS_RESUME = 8,
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** Min valid value*/
+ NDB_MGM_NODE_STATUS_MIN = 0,
+ /** Max valid value*/
+ NDB_MGM_NODE_STATUS_MAX = 8
+#endif
};
/**
* Error codes
*/
enum ndb_mgm_error {
+ /** Not an error */
NDB_MGM_NO_ERROR = 0,
/* Request for service errors */
+ /** Supplied connectstring is illegal */
NDB_MGM_ILLEGAL_CONNECT_STRING = 1001,
- NDB_MGM_ILLEGAL_PORT_NUMBER = 1002,
- NDB_MGM_ILLEGAL_SOCKET = 1003,
- NDB_MGM_ILLEGAL_IP_ADDRESS = 1004,
+ /** Supplied NdbMgmHandle is illegal */
NDB_MGM_ILLEGAL_SERVER_HANDLE = 1005,
+ /** Illegal reply from server */
NDB_MGM_ILLEGAL_SERVER_REPLY = 1006,
+ /** Illegal number of nodes */
NDB_MGM_ILLEGAL_NUMBER_OF_NODES = 1007,
+ /** Illegal node status */
NDB_MGM_ILLEGAL_NODE_STATUS = 1008,
+ /** Memory allocation error */
NDB_MGM_OUT_OF_MEMORY = 1009,
+ /** Management server not connected */
NDB_MGM_SERVER_NOT_CONNECTED = 1010,
+ /** Could not connect to socker */
NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011,
/* Service errors - Start/Stop Node or System */
+ /** Start failed */
NDB_MGM_START_FAILED = 2001,
+ /** Stop failed */
NDB_MGM_STOP_FAILED = 2002,
+ /** Restart failed */
NDB_MGM_RESTART_FAILED = 2003,
/* Service errors - Backup */
+ /** Unable to start backup */
NDB_MGM_COULD_NOT_START_BACKUP = 3001,
+ /** Unable to abort backup */
NDB_MGM_COULD_NOT_ABORT_BACKUP = 3002,
/* Service errors - Single User Mode */
+ /** Unable to enter single user mode */
NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE = 4001,
+ /** Unable to exit single user mode */
NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE = 4002,
/* Usage errors */
+ /** Usage error */
NDB_MGM_USAGE_ERROR = 5001
};
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
struct Ndb_Mgm_Error_Msg {
enum ndb_mgm_error code;
- const char * msg;
+ const char * msg;
};
-
const struct Ndb_Mgm_Error_Msg ndb_mgm_error_msgs[] = {
{ NDB_MGM_NO_ERROR, "No error" },
+ /* Request for service errors */
{ NDB_MGM_ILLEGAL_CONNECT_STRING, "Illegal connect string" },
- { NDB_MGM_ILLEGAL_PORT_NUMBER, "Illegal port number" },
- { NDB_MGM_ILLEGAL_SOCKET, "Illegal socket" },
- { NDB_MGM_ILLEGAL_IP_ADDRESS, "Illegal IP address" },
{ NDB_MGM_ILLEGAL_SERVER_HANDLE, "Illegal server handle" },
{ NDB_MGM_ILLEGAL_SERVER_REPLY, "Illegal reply from server" },
{ NDB_MGM_ILLEGAL_NUMBER_OF_NODES, "Illegal number of nodes" },
@@ -158,77 +283,102 @@ extern "C" {
/* Service errors - Backup */
{ NDB_MGM_COULD_NOT_START_BACKUP, "Could not start backup" },
{ NDB_MGM_COULD_NOT_ABORT_BACKUP, "Could not abort backup" },
-
+
/* Service errors - Single User Mode */
- { NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE,
+ { NDB_MGM_COULD_NOT_ENTER_SINGLE_USER_MODE,
"Could not enter single user mode" },
- { NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE,
+ { NDB_MGM_COULD_NOT_EXIT_SINGLE_USER_MODE,
"Could not exit single user mode" },
/* Usage errors */
{ NDB_MGM_USAGE_ERROR,
"Usage error" }
};
-
- const int ndb_mgm_noOfErrorMsgs =
+ const int ndb_mgm_noOfErrorMsgs =
sizeof(ndb_mgm_error_msgs)/sizeof(struct Ndb_Mgm_Error_Msg);
+#endif
/**
- * Structure returned by ndb_mgm_get_status
+ * Status of a node in the cluster.
+ *
+ * Sub-structure in enum ndb_mgm_cluster_state
+ * returned by ndb_mgm_get_status().
+ *
+ * @note <var>node_status</var>, <var>start_phase</var>,
+ * <var>dynamic_id</var>
+ * and <var>node_group</var> are relevant only for database nodes,
+ * i.e. <var>node_type</var> == @ref NDB_MGM_NODE_TYPE_NDB.
*/
struct ndb_mgm_node_state {
- int node_id; /*< NDB Cluster node id*/
- enum ndb_mgm_node_type node_type; /*< Type of NDB Cluster node*/
- enum ndb_mgm_node_status node_status; /*< State of node*/
- int start_phase; /*< Start phase.
- *< @note Start phase is only
- *< valid if
- *< node_type is
- *< NDB_MGM_NODE_TYPE_NDB and
- *< node_status is
- *< NDB_MGM_NODE_STATUS_STARTING
- */
- int dynamic_id; /*< Id for heartbeats and
- *< master take-over
- *< (only valid for DB nodes)
- */
- 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
- */
- char connect_address[sizeof("000.000.000.000")+1];
+ /** NDB Cluster node ID*/
+ int node_id;
+ /** Type of NDB Cluster node*/
+ enum ndb_mgm_node_type node_type;
+ /** State of node*/
+ enum ndb_mgm_node_status node_status;
+ /** Start phase.
+ *
+ * @note Start phase is only valid if the <var>node_type</var> is
+ * NDB_MGM_NODE_TYPE_NDB and the <var>node_status</var> is
+ * NDB_MGM_NODE_STATUS_STARTING
+ */
+ int start_phase;
+ /** ID for heartbeats and master take-over (only valid for DB nodes)
+ */
+ int dynamic_id;
+ /** Node group of node (only valid for DB nodes)*/
+ int node_group;
+ /** Internal version number*/
+ int version;
+ /** Number of times node has connected or disconnected to the
+ * management server
+ */
+ int connect_count;
+ /** IP address of node when it connected to the management server.
+ * @note This value will be empty if the management server has restarted
+ * since the node last connected.
+ */
+ char connect_address[
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ sizeof("000.000.000.000")+1
+#endif
+ ];
};
/**
- * Cluster status
+ * State of all nodes in the cluster; returned from
+ * ndb_mgm_get_status()
*/
struct ndb_mgm_cluster_state {
- int no_of_nodes; /*< No of entries in the
- *< node_states array
- */
- struct ndb_mgm_node_state /*< An array with node_states*/
- node_states[1];
- const char *hostname;
+ /** Number of entries in the node_states array */
+ int no_of_nodes;
+ /** An array with node_states*/
+ struct ndb_mgm_node_state node_states[
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ 1
+#endif
+ ];
};
/**
- * Default reply from the server
+ * Default reply from the server (reserved for future use)
*/
struct ndb_mgm_reply {
- int return_code; /*< 0 if successful,
- *< otherwise error code.
- */
- char message[256]; /*< Error or reply message.*/
+ /** 0 if successful, otherwise error code. */
+ int return_code;
+ /** Error or reply message.*/
+ char message[256];
};
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Default information types
*/
enum ndb_mgm_info {
- NDB_MGM_INFO_CLUSTER, /*< ?*/
- NDB_MGM_INFO_CLUSTERLOG /*< Cluster log*/
+ /** ?*/
+ NDB_MGM_INFO_CLUSTER,
+ /** Cluster log*/
+ NDB_MGM_INFO_CLUSTERLOG
};
/**
@@ -236,86 +386,26 @@ extern "C" {
* (Used only in the development of NDB Cluster.)
*/
enum ndb_mgm_signal_log_mode {
- NDB_MGM_SIGNAL_LOG_MODE_IN, /*< Log receiving signals */
- NDB_MGM_SIGNAL_LOG_MODE_OUT, /*< Log sending signals*/
- NDB_MGM_SIGNAL_LOG_MODE_INOUT, /*< Log both sending/receiving*/
- NDB_MGM_SIGNAL_LOG_MODE_OFF /*< Log off*/
+ /** Log receiving signals */
+ NDB_MGM_SIGNAL_LOG_MODE_IN,
+ /** Log sending signals*/
+ NDB_MGM_SIGNAL_LOG_MODE_OUT,
+ /** Log both sending/receiving*/
+ NDB_MGM_SIGNAL_LOG_MODE_INOUT,
+ /** Log off*/
+ NDB_MGM_SIGNAL_LOG_MODE_OFF
};
+#endif
- /**
- * Log severities (used to filter the cluster log)
- */
- enum ndb_mgm_clusterlog_level {
- NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL = -1,
- /* must range from 0 and up, indexes into an array */
- NDB_MGM_CLUSTERLOG_ON = 0, /*< Cluster log on*/
- NDB_MGM_CLUSTERLOG_DEBUG = 1, /*< Used in NDB Cluster
- *< developement
- */
- NDB_MGM_CLUSTERLOG_INFO = 2, /*< Informational messages*/
- NDB_MGM_CLUSTERLOG_WARNING = 3, /*< Conditions that are not
- *< error condition, but
- *< might require handling
- */
- NDB_MGM_CLUSTERLOG_ERROR = 4, /*< Conditions that should be
- *< corrected
- */
- NDB_MGM_CLUSTERLOG_CRITICAL = 5, /*< Critical conditions, like
- *< device errors or out of
- *< resources
- */
- NDB_MGM_CLUSTERLOG_ALERT = 6, /*< A condition that should be
- *< corrected immediately,
- *< such as a corrupted system
- */
- /* must be next number, works as bound in loop */
- NDB_MGM_CLUSTERLOG_ALL = 7 /*< All severities */
- };
-
- /**
- * Log categories
- */
- enum ndb_mgm_event_category {
- /**
- * Invalid
- */
- NDB_MGM_ILLEGAL_EVENT_CATEGORY = -1,
- /**
- * Events during all kinds of startups
- */
- NDB_MGM_EVENT_CATEGORY_STARTUP = CFG_LOGLEVEL_STARTUP,
-
- /**
- * Events during shutdown
- */
- NDB_MGM_EVENT_CATEGORY_SHUTDOWN = CFG_LOGLEVEL_SHUTDOWN,
-
- /**
- * Transaction statistics (Job level, TCP/IP speed)
- */
- NDB_MGM_EVENT_CATEGORY_STATISTIC = CFG_LOGLEVEL_STATISTICS,
- NDB_MGM_EVENT_CATEGORY_CHECKPOINT = CFG_LOGLEVEL_CHECKPOINT,
- NDB_MGM_EVENT_CATEGORY_NODE_RESTART = CFG_LOGLEVEL_NODERESTART,
- NDB_MGM_EVENT_CATEGORY_CONNECTION = CFG_LOGLEVEL_CONNECTION,
- NDB_MGM_EVENT_CATEGORY_DEBUG = CFG_LOGLEVEL_DEBUG,
- NDB_MGM_EVENT_CATEGORY_INFO = CFG_LOGLEVEL_INFO,
- NDB_MGM_EVENT_CATEGORY_WARNING = CFG_LOGLEVEL_WARNING,
- NDB_MGM_EVENT_CATEGORY_ERROR = CFG_LOGLEVEL_ERROR,
- NDB_MGM_EVENT_CATEGORY_GREP = CFG_LOGLEVEL_GREP,
- NDB_MGM_EVENT_CATEGORY_BACKUP = CFG_LOGLEVEL_BACKUP,
-
- NDB_MGM_MIN_EVENT_CATEGORY = CFG_MIN_LOGLEVEL,
- NDB_MGM_MAX_EVENT_CATEGORY = CFG_MAX_LOGLEVEL
- };
-
/***************************************************************************/
- /**
+ /**
* @name Functions: Error Handling
* @{
*/
/**
- * Get latest error associated with a management server handle
+ * Get the most recent error associated with the management server whose handle
+ * is used as the value of <var>handle</var>.
*
* @param handle Management handle
* @return Latest error code
@@ -323,7 +413,7 @@ extern "C" {
int ndb_mgm_get_latest_error(const NdbMgmHandle handle);
/**
- * Get latest main error message associated with a handle
+ * Get the most recent general error message associated with a handle
*
* @param handle Management handle.
* @return Latest error message
@@ -331,9 +421,9 @@ extern "C" {
const char * ndb_mgm_get_latest_error_msg(const NdbMgmHandle handle);
/**
- * Get latest error description associated with a handle
+ * Get the most recent error description associated with a handle
*
- * The error description gives some additional information to
+ * The error description gives some additional information regarding
* the error message.
*
* @param handle Management handle.
@@ -343,11 +433,11 @@ extern "C" {
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
- * Get latest internal source code error line associated with a handle
+ * Get the most recent internal source code error line associated with a handle
*
* @param handle Management handle.
* @return Latest internal source code line of latest error
- * @deprecated
+ * @deprecated
*/
int ndb_mgm_get_latest_error_line(const NdbMgmHandle handle);
#endif
@@ -359,26 +449,48 @@ extern "C" {
/** @} *********************************************************************/
- /**
+ /**
* @name Functions: Create/Destroy Management Server Handles
* @{
*/
- /**
- * Create a handle to a management server
+ /**
+ * Create a handle to a management server.
*
* @return A management handle<br>
- * or NULL if no management handle could be created.
+ * or <var>NULL</var> if no management handle could be created.
*/
NdbMgmHandle ndb_mgm_create_handle();
-
- /**
- * Set connecst string to management server
+
+ /**
+ * Destroy a management server handle.
+ *
+ * @param handle Management handle
+ */
+ void ndb_mgm_destroy_handle(NdbMgmHandle * handle);
+
+ /** @} *********************************************************************/
+ /**
+ * @name Functions: Connect/Disconnect Management Server
+ * @{
+ */
+
+ /**
+ * Sets the connectstring for a management server
*
* @param handle Management handle
- * @param connect_string Connect string to the management server,
+ * @param connect_string Connect string to the management server,
*
* @return -1 on error.
+ *
+ * @code
+ * <connectstring> := [<nodeid-specification>,]<host-specification>[,<host-specification>]
+ * <nodeid-specification> := nodeid=<id>
+ * <host-specification> := <host>[:<port>]
+ * <id> is an integer greater than 0 identifying a node in config.ini
+ * <port> is an integer referring to a regular unix port
+ * <host> is a string containing a valid network host address
+ * @endcode
*/
int ndb_mgm_set_connectstring(NdbMgmHandle handle,
const char *connect_string);
@@ -390,43 +502,88 @@ extern "C" {
const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
/**
- * Destroy a management server handle
+ * Gets the connectstring used for a connection
*
- * @param handle Management handle
- */
- void ndb_mgm_destroy_handle(NdbMgmHandle * handle);
-
- /** @} *********************************************************************/
- /**
- * @name Functions: Connect/Disconnect Management Server
- * @{
+ * @note This function returns the default connectstring if no call to
+ * ndb_mgm_set_connectstring() has been performed. Also, the
+ * returned connectstring may be formatted differently.
+ *
+ * @param handle Management handle
+ * @param buf Buffer to hold result
+ * @param buf_sz Size of buffer.
+ *
+ * @return connectstring (same as <var>buf</var>)
*/
+ const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
/**
- * Connect to a management server
+ * Connects to a management server. Connectstring is set by
+ * ndb_mgm_set_connectstring().
*
* @param handle Management handle.
+ * @param no_retries Number of retries to connect
+ * (0 means connect once).
+ * @param retry_delay_in_seconds
+ * How long to wait until retry is performed.
+ * @param verbose Make printout regarding connect retries.
+ *
* @return -1 on error.
*/
int ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
int retry_delay_in_seconds, int verbose);
-
/**
- * Disconnect from a management server
+ * Return true if connected.
+ *
+ * @param handle Management handle
+ * @return 0 if not connected, non-zero if connected.
+ */
+ int ndb_mgm_is_connected(NdbMgmHandle handle);
+
+ /**
+ * Disconnects from a management server
*
* @param handle Management handle.
* @return -1 on error.
*/
int ndb_mgm_disconnect(NdbMgmHandle handle);
-
+
+ /**
+ * Gets connection node ID
+ *
+ * @param handle Management handle
+ *
+ * @return Node ID; 0 indicates that no node ID has been
+ * specified
+ */
+ int ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle);
+
+ /**
+ * Gets connection port
+ *
+ * @param handle Management handle
+ *
+ * @return port
+ */
+ int ndb_mgm_get_connected_port(NdbMgmHandle handle);
+
+ /**
+ * Gets connection host
+ *
+ * @param handle Management handle
+ *
+ * @return hostname
+ */
+ const char *ndb_mgm_get_connected_host(NdbMgmHandle handle);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/** @} *********************************************************************/
- /**
- * @name Functions: Convert between different data formats
+ /**
+ * @name Functions: Used to convert between different data formats
* @{
*/
/**
- * Convert a string to a ndb_mgm_node_type
+ * Converts a string to an <var>ndb_mgm_node_type</var> value
*
* @param type Node type as string.
* @return NDB_MGM_NODE_TYPE_UNKNOWN if invalid string.
@@ -434,23 +591,24 @@ extern "C" {
enum ndb_mgm_node_type ndb_mgm_match_node_type(const char * type);
/**
- * Convert an ndb_mgm_node_type to a string
+ * Converts an ndb_mgm_node_type to a string
*
* @param type Node type.
- * @return NULL if invalid id.
+ * @return <var>NULL</var> if invalid ID.
*/
const char * ndb_mgm_get_node_type_string(enum ndb_mgm_node_type type);
/**
- * Convert an ndb_mgm_node_type to a alias string
+ * Converts an ndb_mgm_node_type to a alias string
*
* @param type Node type.
- * @return NULL if invalid id.
+ * @return <var>NULL</var> if the ID is invalid.
*/
- const char * ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type, const char **str);
+ const char * ndb_mgm_get_node_type_alias_string(enum ndb_mgm_node_type type,
+ const char **str);
/**
- * Convert a string to a ndb_mgm_node_status
+ * Converts a string to a <var>ndb_mgm_node_status</var> value
*
* @param status NDB node status string.
* @return NDB_MGM_NODE_STATUS_UNKNOWN if invalid string.
@@ -458,67 +616,72 @@ extern "C" {
enum ndb_mgm_node_status ndb_mgm_match_node_status(const char * status);
/**
- * Convert an id to a string
+ * Converts an ID to a string
*
* @param status NDB node status.
- * @return NULL if invalid id.
+ * @return <var>NULL</var> if invalid ID.
*/
const char * ndb_mgm_get_node_status_string(enum ndb_mgm_node_status status);
+ const char * ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity);
ndb_mgm_event_category ndb_mgm_match_event_category(const char *);
const char * ndb_mgm_get_event_category_string(enum ndb_mgm_event_category);
+#endif
/** @} *********************************************************************/
- /**
- * @name Functions: State of cluster
+ /**
+ * @name Functions: Cluster status
* @{
*/
/**
- * Get status of the nodes in an NDB Cluster
+ * Gets status of the nodes in an NDB Cluster
*
- * Note the caller must free the pointer returned.
+ * @note The caller must free the pointer returned by this function.
*
* @param handle Management handle.
- * @return Cluster state (or NULL on error).
+ *
+ * @return Cluster state (or <var>NULL</var> on error).
*/
struct ndb_mgm_cluster_state * ndb_mgm_get_status(NdbMgmHandle handle);
/** @} *********************************************************************/
- /**
- * @name Functions: Start/stop nodes
+ /**
+ * @name Functions: Start/stop nodes
* @{
*/
/**
- * Stop database nodes
+ * Stops database nodes
*
* @param handle Management handle.
- * @param no_of_nodes no of database nodes<br>
- * 0 - means all database nodes in cluster<br>
- * n - Means stop n node(s) specified in the
+ * @param no_of_nodes Number of database nodes to be stopped<br>
+ * 0: All database nodes in cluster<br>
+ * n: Stop the <var>n</var> node(s) specified in the
* array node_list
- * @param node_list List of node ids of database nodes to be stopped
- * @return No of nodes stopped (or -1 on error)
+ * @param node_list List of node IDs for database nodes to be stopped
+ *
+ * @return Number of nodes stopped (-1 on error)
*
- * @note The function is equivalent
- * to ndb_mgm_stop2(handle, no_of_nodes, node_list, 0)
+ * @note This function is equivalent
+ * to calling ndb_mgm_stop2(handle, no_of_nodes, node_list, 0)
*/
- int ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes,
+ int ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes,
const int * node_list);
/**
- * Stop database nodes
+ * Stops database nodes
*
* @param handle Management handle.
- * @param no_of_nodes No of database nodes<br>
- * 0 - means all database nodes in cluster<br>
- * n - Means stop n node(s) specified in
+ * @param no_of_nodes Number of database nodes to stop<br>
+ * 0: All database nodes in cluster<br>
+ * n: Stop the <var>n</var> node(s) specified in
* the array node_list
- * @param node_list List of node ids of database nodes to be stopped
- * @param abort Don't perform gracefull stop,
- * but rather stop immediatly
- * @return No of nodes stopped (or -1 on error).
+ * @param node_list List of node IDs of database nodes to be stopped
+ * @param abort Don't perform graceful stop,
+ * but rather stop immediately
+ *
+ * @return Number of nodes stopped (-1 on error).
*/
int ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes,
const int * node_list, int abort);
@@ -527,123 +690,142 @@ extern "C" {
* Restart database nodes
*
* @param handle Management handle.
- * @param no_of_nodes No of database nodes<br>
- * 0 - means all database nodes in cluster<br>
- * n - Means stop n node(s) specified in the
+ * @param no_of_nodes Number of database nodes to restart<br>
+ * 0: All database nodes in cluster<br>
+ * n: Restart the <var>n</var> node(s) specified in the
* array node_list
- * @param node_list List of node ids of database nodes to be stopped
- * @return No of nodes stopped (or -1 on error).
+ * @param node_list List of node IDs of database nodes to be restarted
+ *
+ * @return Number of nodes restarted (-1 on error).
*
- * @note The function is equivalent to
+ * @note This function is equivalent to calling
* ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
*/
- int ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes,
+ int ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes,
const int * node_list);
/**
* Restart database nodes
*
* @param handle Management handle.
- * @param no_of_nodes No of database nodes<br>
- * 0 - means all database nodes in cluster<br>
- * n - Means stop n node(s) specified in the
+ * @param no_of_nodes Number of database nodes to be restarted:<br>
+ * 0: Restart all database nodes in the cluster<br>
+ * n: Restart the <var>n</var> node(s) specified in the
* array node_list
- * @param node_list List of node ids of database nodes to be stopped
- * @param initial Remove filesystem from node(s) restarting
- * @param nostart Don't actually start node(s) but leave them
+ * @param node_list List of node IDs of database nodes to be restarted
+ * @param initial Remove filesystem from restarting node(s)
+ * @param nostart Don't actually start node(s) but leave them
* waiting for start command
- * @param abort Don't perform gracefull restart,
- * but rather restart immediatly
- * @return No of nodes stopped (or -1 on error).
+ * @param abort Don't perform graceful restart,
+ * but rather restart immediately
+ *
+ * @return Number of nodes stopped (-1 on error).
*/
int ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes,
const int * node_list, int initial,
int nostart, int abort);
-
+
/**
* Start database nodes
*
* @param handle Management handle.
- * @param no_of_nodes No of database nodes<br>
- * 0 - means all database nodes in cluster<br>
- * n - Means start n node(s) specified in
+ * @param no_of_nodes Number of database nodes to be started<br>
+ * 0: Start all database nodes in the cluster<br>
+ * n: Start the <var>n</var> node(s) specified in
* the array node_list
- * @param node_list List of node ids of database nodes to be started
- * @return No of nodes started (or -1 on error).
+ * @param node_list List of node IDs of database nodes to be started
+ *
+ * @return Number of nodes actually started (-1 on error).
*
- * @note The nodes to start must have been started with nostart(-n)
+ * @note The nodes to be started must have been started with nostart(-n)
* argument.
- * This means that the database node binary is started and
- * waiting for a START management command which will
- * actually start the database node functionality
+ * This means that the database node binary is started and
+ * waiting for a START management command which will
+ * actually enable the database node
*/
int ndb_mgm_start(NdbMgmHandle handle,
int no_of_nodes,
const int * node_list);
/** @} *********************************************************************/
- /**
- * @name Functions: Logging and Statistics
+ /**
+ * @name Functions: Controlling Clusterlog output
* @{
*/
/**
- * Filter cluster log
+ * Filter cluster log severities
*
* @param handle NDB management handle.
- * @param level A cluster log level to filter.
- * @param enable set 1=enable 0=disable
+ * @param severity A cluster log severity to filter.
+ * @param enable set 1=enable o 0=disable
* @param reply Reply message.
+ *
* @return -1 on error.
*/
- int ndb_mgm_filter_clusterlog(NdbMgmHandle handle,
- enum ndb_mgm_clusterlog_level level,
- int enable,
- struct ndb_mgm_reply* reply);
-
+ int ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,
+ enum ndb_mgm_event_severity severity,
+ int enable,
+ struct ndb_mgm_reply* reply);
/**
- * Get log filter
- *
+ * Get clusterlog severity filter
+ *
* @param handle NDB management handle
- * @return A vector of seven elements,
+ *
+ * @return A vector of seven elements,
* where each element contains
- * 1 if a severity is enabled and 0 if not.
- * A severity is stored at position
- * ndb_mgm_clusterlog_level,
+ * 1 if a severity indicator is enabled and 0 if not.
+ * A severity level is stored at position
+ * ndb_mgm_clusterlog_level;
* for example the "error" level is stored in position
- * [NDB_MGM_CLUSTERLOG_ERROR-1].
- * The first element in the vector signals
- * whether the clusterlog
+ * [NDB_MGM_EVENT_SEVERITY_ERROR].
+ * The first element [NDB_MGM_EVENT_SEVERITY_ON] in
+ * the vector signals
+ * whether the cluster log
* is disabled or enabled.
*/
- unsigned int *ndb_mgm_get_logfilter(NdbMgmHandle handle);
+ const unsigned int *ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle);
/**
* Set log category and levels for the cluster log
*
* @param handle NDB management handle.
- * @param nodeId Node id.
+ * @param nodeId Node ID.
* @param category Event category.
* @param level Log level (0-15).
* @param reply Reply message.
* @return -1 on error.
*/
- int ndb_mgm_set_loglevel_clusterlog(NdbMgmHandle handle,
+ int ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle,
int nodeId,
enum ndb_mgm_event_category category,
int level,
struct ndb_mgm_reply* reply);
- ndb_mgm_clusterlog_level
- ndb_mgm_match_clusterlog_level(const char * name);
- const char *
- ndb_mgm_get_clusterlog_level_string(enum ndb_mgm_clusterlog_level level);
+ /** @} *********************************************************************/
+ /**
+ * @name Functions: Listening to log events
+ * @{
+ */
+
+ /**
+ * Listen to log events. They are read from the return file descriptor
+ * and the format is textual, and the same as in the cluster log.
+ *
+ * @param handle NDB management handle.
+ * @param filter pairs of { level, ndb_mgm_event_category } that will be
+ * pushed to fd, level=0 ends list.
+ *
+ * @return fd filedescriptor to read events from
+ */
+ int ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[]);
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Set log category and levels for the Node
*
* @param handle NDB management handle.
- * @param nodeId Node id.
+ * @param nodeId Node ID.
* @param category Event category.
* @param level Log level (0-15).
* @param reply Reply message.
@@ -664,9 +846,68 @@ extern "C" {
*/
int ndb_mgm_get_stat_port(NdbMgmHandle handle,
struct ndb_mgm_reply* reply);
+#endif
+
+ /**
+ * The NdbLogEventHandle
+ */
+ typedef struct ndb_logevent_handle * NdbLogEventHandle;
+
+ /**
+ * Listen to log events.
+ *
+ * @param handle NDB management handle.
+ * @param filter pairs of { level, ndb_mgm_event_category } that will be
+ * pushed to fd, level=0 ends list.
+ *
+ * @return NdbLogEventHandle
+ */
+ NdbLogEventHandle ndb_mgm_create_logevent_handle(NdbMgmHandle,
+ const int filter[]);
+ void ndb_mgm_destroy_logevent_handle(NdbLogEventHandle*);
+
+ /**
+ * Retrieve filedescriptor from NdbLogEventHandle. May be used in
+ * e.g. an application select() statement.
+ *
+ * @note Do not attemt to read from it, it will corrupt the parsing.
+ *
+ * @return filedescriptor, -1 on failure.
+ */
+ int ndb_logevent_get_fd(const NdbLogEventHandle);
+
+ /**
+ * Attempt to retrieve next log event and will fill in the supplied
+ * struct dst
+ *
+ * @param dst Pointer to struct to fill in event information
+ * @param timeout_in_milliseconds Timeout for waiting for event
+ *
+ * @return >0 if event exists, 0 no event (timed out), or -1 on error.
+ *
+ * @note Return value <=0 will leave dst untouched
+ */
+ int ndb_logevent_get_next(const NdbLogEventHandle,
+ struct ndb_logevent *dst,
+ unsigned timeout_in_milliseconds);
+
+ /**
+ * Retrieve laterst error code
+ *
+ * @return error code
+ */
+ int ndb_logevent_get_latest_error(const NdbLogEventHandle);
+
+ /**
+ * Retrieve laterst error message
+ *
+ * @return error message
+ */
+ const char *ndb_logevent_get_latest_error_msg(const NdbLogEventHandle);
+
/** @} *********************************************************************/
- /**
+ /**
* @name Functions: Backup
* @{
*/
@@ -674,13 +915,15 @@ extern "C" {
/**
* Start backup
*
- * @param handle NDB management handle.
- * @param wait_completed 0=don't wait for confirmation
- 1=wait for backup started
- 2=wait for backup completed
- * @param backup_id Backup id is returned from function.
- * @param reply Reply message.
- * @return -1 on error.
+ * @param handle NDB management handle.
+ * @param wait_completed 0: Don't wait for confirmation<br>
+ * 1: Wait for backup to be started<br>
+ * 2: Wait for backup to be completed
+ * @param backup_id Backup ID is returned from function.
+ * @param reply Reply message.
+ * @return -1 on error.
+ * @note backup_id will not be returned if
+ * wait_completed == 0
*/
int ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed,
unsigned int* backup_id,
@@ -690,7 +933,7 @@ extern "C" {
* Abort backup
*
* @param handle NDB management handle.
- * @param backup_id Backup Id.
+ * @param backup_id Backup ID.
* @param reply Reply message.
* @return -1 on error.
*/
@@ -699,48 +942,49 @@ extern "C" {
/** @} *********************************************************************/
- /**
+ /**
* @name Functions: Single User Mode
* @{
*/
/**
- * Enter Single user mode
+ * Enter Single user mode
*
* @param handle NDB management handle.
- * @param nodeId Node Id of the single user node
+ * @param nodeId Node ID of the single user node
* @param reply Reply message.
* @return -1 on error.
*/
int ndb_mgm_enter_single_user(NdbMgmHandle handle, unsigned int nodeId,
struct ndb_mgm_reply* reply);
-
+
/**
- * Exit Single user mode
+ * Exit Single user mode
*
* @param handle NDB management handle.
- * @param nodeId Node Id of the single user node
* @param reply Reply message.
+ *
* @return -1 on error.
*/
- int ndb_mgm_exit_single_user(NdbMgmHandle handle,
+ int ndb_mgm_exit_single_user(NdbMgmHandle handle,
struct ndb_mgm_reply* reply);
-
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** @} *********************************************************************/
/**
- * Listen event
- *
- * @param filter pairs of { level, category } that will be
- * pushed to fd, level=0 ends lists
- * @return fd which events will be pushed to
+ * @name Configuration handling
+ * @{
*/
- int ndb_mgm_listen_event(NdbMgmHandle handle, int filter[]);
-
+
/**
* Get configuration
* @param handle NDB management handle.
* @param version Version of configuration, 0 means latest
- * @see MAKE_VERSION
- * @Note the caller must call ndb_mgm_detroy_configuration
+ * (Currently this is the only supported value for this parameter)
+ *
+ * @return configuration
+ *
+ * @note The caller is responsible for calling ndb_mgm_destroy_configuration()
*/
struct ndb_mgm_configuration * ndb_mgm_get_configuration(NdbMgmHandle handle,
unsigned version);
@@ -748,6 +992,13 @@ extern "C" {
int ndb_mgm_alloc_nodeid(NdbMgmHandle handle,
unsigned version, int nodetype);
+
+
+ /**
+ * Get the node id of the mgm server we're connected to
+ */
+ Uint32 ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle);
+
/**
* Config iterator
*/
@@ -756,14 +1007,14 @@ extern "C" {
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 ndb_mgm_find(ndb_mgm_configuration_iterator*,
int param, unsigned value);
-
- int ndb_mgm_get_int_parameter(const ndb_mgm_configuration_iterator*,
+
+ 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, Uint64 * value);
@@ -771,6 +1022,38 @@ extern "C" {
int param, const char ** value);
int ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **);
int ndb_mgm_check_connection(NdbMgmHandle handle);
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ enum ndb_mgm_clusterlog_level {
+ NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL = -1,
+ NDB_MGM_CLUSTERLOG_ON = 0,
+ NDB_MGM_CLUSTERLOG_DEBUG = 1,
+ NDB_MGM_CLUSTERLOG_INFO = 2,
+ NDB_MGM_CLUSTERLOG_WARNING = 3,
+ NDB_MGM_CLUSTERLOG_ERROR = 4,
+ NDB_MGM_CLUSTERLOG_CRITICAL = 5,
+ NDB_MGM_CLUSTERLOG_ALERT = 6,
+ NDB_MGM_CLUSTERLOG_ALL = 7
+ };
+ inline
+ int ndb_mgm_filter_clusterlog(NdbMgmHandle h,
+ enum ndb_mgm_clusterlog_level s,
+ int e, struct ndb_mgm_reply* r)
+ { return ndb_mgm_set_clusterlog_severity_filter(h,(ndb_mgm_event_severity)s,
+ e,r); }
+
+ inline
+ const unsigned int *ndb_mgm_get_logfilter(NdbMgmHandle h)
+ { return ndb_mgm_get_clusterlog_severity_filter(h); }
+
+ inline
+ int ndb_mgm_set_loglevel_clusterlog(NdbMgmHandle h, int n,
+ enum ndb_mgm_event_category c,
+ int l, struct ndb_mgm_reply* r)
+ { return ndb_mgm_set_clusterlog_loglevel(h,n,c,l,r); }
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/ndb/include/mgmapi/mgmapi_config_parameters.h b/ndb/include/mgmapi/mgmapi_config_parameters.h
index 2e3b47eb42e..8f95e159b38 100644
--- a/ndb/include/mgmapi/mgmapi_config_parameters.h
+++ b/ndb/include/mgmapi/mgmapi_config_parameters.h
@@ -99,7 +99,7 @@
#define CFG_LOGLEVEL_INFO 256
#define CFG_LOGLEVEL_WARNING 257
#define CFG_LOGLEVEL_ERROR 258
-#define CFG_LOGLEVEL_GREP 259
+#define CFG_LOGLEVEL_CONGESTION 259
#define CFG_LOGLEVEL_DEBUG 260
#define CFG_LOGLEVEL_BACKUP 261
#define CFG_MAX_LOGLEVEL 261
diff --git a/ndb/include/mgmapi/mgmapi_debug.h b/ndb/include/mgmapi/mgmapi_debug.h
index 1c562cd164f..e86d9d4b768 100644
--- a/ndb/include/mgmapi/mgmapi_debug.h
+++ b/ndb/include/mgmapi/mgmapi_debug.h
@@ -131,6 +131,7 @@ extern "C" {
int param,
const char * value,
struct ndb_mgm_reply* reply);
+
#ifdef __cplusplus
}
#endif
diff --git a/ndb/include/mgmapi/ndb_logevent.h b/ndb/include/mgmapi/ndb_logevent.h
new file mode 100644
index 00000000000..d5744b0fffe
--- /dev/null
+++ b/ndb/include/mgmapi/ndb_logevent.h
@@ -0,0 +1,618 @@
+/* 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 NDB_LOGEVENT_H
+#define NDB_LOGEVENT_H
+
+/** @addtogroup MGM_C_API
+ * @{
+ */
+
+#include "mgmapi_config_parameters.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * Available log events grouped by @ref ndb_mgm_event_category
+ */
+
+ enum Ndb_logevent_type {
+
+ NDB_LE_ILLEGAL_TYPE = -1,
+
+ /** NDB_MGM_EVENT_CATEGORY_CONNECTION */
+ NDB_LE_Connected = 0,
+ /** NDB_MGM_EVENT_CATEGORY_CONNECTION */
+ NDB_LE_Disconnected = 1,
+ /** NDB_MGM_EVENT_CATEGORY_CONNECTION */
+ NDB_LE_CommunicationClosed = 2,
+ /** NDB_MGM_EVENT_CATEGORY_CONNECTION */
+ NDB_LE_CommunicationOpened = 3,
+ /** NDB_MGM_EVENT_CATEGORY_CONNECTION */
+ NDB_LE_ConnectedApiVersion = 51,
+
+ /** NDB_MGM_EVENT_CATEGORY_CHECKPOINT */
+ NDB_LE_GlobalCheckpointStarted = 4,
+ /** NDB_MGM_EVENT_CATEGORY_CHECKPOINT */
+ NDB_LE_GlobalCheckpointCompleted = 5,
+ /** NDB_MGM_EVENT_CATEGORY_CHECKPOINT */
+ NDB_LE_LocalCheckpointStarted = 6,
+ /** NDB_MGM_EVENT_CATEGORY_CHECKPOINT */
+ NDB_LE_LocalCheckpointCompleted = 7,
+ /** NDB_MGM_EVENT_CATEGORY_CHECKPOINT */
+ NDB_LE_LCPStoppedInCalcKeepGci = 8,
+ /** NDB_MGM_EVENT_CATEGORY_CHECKPOINT */
+ NDB_LE_LCPFragmentCompleted = 9,
+
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_NDBStartStarted = 10,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_NDBStartCompleted = 11,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_STTORRYRecieved = 12,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_StartPhaseCompleted = 13,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_CM_REGCONF = 14,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_CM_REGREF = 15,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_FIND_NEIGHBOURS = 16,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_NDBStopStarted = 17,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_NDBStopAborted = 18,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_StartREDOLog = 19,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_StartLog = 20,
+ /** NDB_MGM_EVENT_CATEGORY_STARTUP */
+ NDB_LE_UNDORecordsExecuted = 21,
+
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_NR_CopyDict = 22,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_NR_CopyDistr = 23,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_NR_CopyFragsStarted = 24,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_NR_CopyFragDone = 25,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_NR_CopyFragsCompleted = 26,
+
+ /* NODEFAIL */
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_NodeFailCompleted = 27,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_NODE_FAILREP = 28,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_ArbitState = 29,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_ArbitResult = 30,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_GCP_TakeoverStarted = 31,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_GCP_TakeoverCompleted = 32,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_LCP_TakeoverStarted = 33,
+ /** NDB_MGM_EVENT_CATEGORY_NODE_RESTART */
+ NDB_LE_LCP_TakeoverCompleted = 34,
+
+ /** NDB_MGM_EVENT_CATEGORY_STATISTIC */
+ NDB_LE_TransReportCounters = 35,
+ /** NDB_MGM_EVENT_CATEGORY_STATISTIC */
+ NDB_LE_OperationReportCounters = 36,
+ /** NDB_MGM_EVENT_CATEGORY_STATISTIC */
+ NDB_LE_TableCreated = 37,
+ /** NDB_MGM_EVENT_CATEGORY_STATISTIC */
+ NDB_LE_UndoLogBlocked = 38,
+ /** NDB_MGM_EVENT_CATEGORY_STATISTIC */
+ NDB_LE_JobStatistic = 39,
+ /** NDB_MGM_EVENT_CATEGORY_STATISTIC */
+ NDB_LE_SendBytesStatistic = 40,
+ /** NDB_MGM_EVENT_CATEGORY_STATISTIC */
+ NDB_LE_ReceiveBytesStatistic = 41,
+ /** NDB_MGM_EVENT_CATEGORY_STATISTIC */
+ NDB_LE_MemoryUsage = 50,
+
+ /** NDB_MGM_EVENT_CATEGORY_ERROR */
+ NDB_LE_TransporterError = 42,
+ /** NDB_MGM_EVENT_CATEGORY_ERROR */
+ NDB_LE_TransporterWarning = 43,
+ /** NDB_MGM_EVENT_CATEGORY_ERROR */
+ NDB_LE_MissedHeartbeat = 44,
+ /** NDB_MGM_EVENT_CATEGORY_ERROR */
+ NDB_LE_DeadDueToHeartbeat = 45,
+ /** NDB_MGM_EVENT_CATEGORY_ERROR */
+ NDB_LE_WarningEvent = 46,
+
+ /** NDB_MGM_EVENT_CATEGORY_INFO */
+ NDB_LE_SentHeartbeat = 47,
+ /** NDB_MGM_EVENT_CATEGORY_INFO */
+ NDB_LE_CreateLogBytes = 48,
+ /** NDB_MGM_EVENT_CATEGORY_INFO */
+ NDB_LE_InfoEvent = 49,
+
+ /* GREP */
+ NDB_LE_GrepSubscriptionInfo = 52,
+ NDB_LE_GrepSubscriptionAlert = 53,
+
+ /** NDB_MGM_EVENT_CATEGORY_BACKUP */
+ NDB_LE_BackupStarted = 54,
+ /** NDB_MGM_EVENT_CATEGORY_BACKUP */
+ NDB_LE_BackupFailedToStart = 55,
+ /** NDB_MGM_EVENT_CATEGORY_BACKUP */
+ NDB_LE_BackupCompleted = 56,
+ /** NDB_MGM_EVENT_CATEGORY_BACKUP */
+ NDB_LE_BackupAborted = 57
+ };
+
+ /**
+ * Log event severities (used to filter the cluster log,
+ * ndb_mgm_set_clusterlog_severity_filter(), and filter listening to events
+ * ndb_mgm_listen_event())
+ */
+ enum ndb_mgm_event_severity {
+ NDB_MGM_ILLEGAL_EVENT_SEVERITY = -1,
+ /* Must be a nonnegative integer (used for array indexing) */
+ /** Cluster log on */
+ NDB_MGM_EVENT_SEVERITY_ON = 0,
+ /** Used in NDB Cluster developement */
+ NDB_MGM_EVENT_SEVERITY_DEBUG = 1,
+ /** Informational messages*/
+ NDB_MGM_EVENT_SEVERITY_INFO = 2,
+ /** Conditions that are not error condition, but might require handling.
+ */
+ NDB_MGM_EVENT_SEVERITY_WARNING = 3,
+ /** Conditions that, while not fatal, should be corrected. */
+ NDB_MGM_EVENT_SEVERITY_ERROR = 4,
+ /** Critical conditions, like device errors or out of resources */
+ NDB_MGM_EVENT_SEVERITY_CRITICAL = 5,
+ /** A condition that should be corrected immediately,
+ * such as a corrupted system
+ */
+ NDB_MGM_EVENT_SEVERITY_ALERT = 6,
+ /* must be next number, works as bound in loop */
+ /** All severities */
+ NDB_MGM_EVENT_SEVERITY_ALL = 7
+ };
+
+ /**
+ * Log event categories, used to set filter level on the log events using
+ * ndb_mgm_set_clusterlog_loglevel() and ndb_mgm_listen_event()
+ */
+ enum ndb_mgm_event_category {
+ /**
+ * Invalid log event category
+ */
+ NDB_MGM_ILLEGAL_EVENT_CATEGORY = -1,
+ /**
+ * Log events during all kinds of startups
+ */
+ NDB_MGM_EVENT_CATEGORY_STARTUP = CFG_LOGLEVEL_STARTUP,
+ /**
+ * Log events during shutdown
+ */
+ NDB_MGM_EVENT_CATEGORY_SHUTDOWN = CFG_LOGLEVEL_SHUTDOWN,
+ /**
+ * Statistics log events
+ */
+ NDB_MGM_EVENT_CATEGORY_STATISTIC = CFG_LOGLEVEL_STATISTICS,
+ /**
+ * Log events related to checkpoints
+ */
+ NDB_MGM_EVENT_CATEGORY_CHECKPOINT = CFG_LOGLEVEL_CHECKPOINT,
+ /**
+ * Log events during node restart
+ */
+ NDB_MGM_EVENT_CATEGORY_NODE_RESTART = CFG_LOGLEVEL_NODERESTART,
+ /**
+ * Log events related to connections between cluster nodes
+ */
+ NDB_MGM_EVENT_CATEGORY_CONNECTION = CFG_LOGLEVEL_CONNECTION,
+ /**
+ * Backup related log events
+ */
+ NDB_MGM_EVENT_CATEGORY_BACKUP = CFG_LOGLEVEL_BACKUP,
+ /**
+ * Congestion related log events
+ */
+ NDB_MGM_EVENT_CATEGORY_CONGESTION = CFG_LOGLEVEL_CONGESTION,
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * Loglevel debug
+ */
+ NDB_MGM_EVENT_CATEGORY_DEBUG = CFG_LOGLEVEL_DEBUG,
+#endif
+ /**
+ * Uncategorized log events (severity info)
+ */
+ NDB_MGM_EVENT_CATEGORY_INFO = CFG_LOGLEVEL_INFO,
+ /**
+ * Uncategorized log events (severity warning or higher)
+ */
+ NDB_MGM_EVENT_CATEGORY_ERROR = CFG_LOGLEVEL_ERROR,
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ NDB_MGM_MIN_EVENT_CATEGORY = CFG_MIN_LOGLEVEL,
+ NDB_MGM_MAX_EVENT_CATEGORY = CFG_MAX_LOGLEVEL
+#endif
+ };
+
+ /**
+ * Structure to store and retrieve log event information.
+ * @see @ref secSLogEvents
+ */
+ struct ndb_logevent {
+ /** NdbLogEventHandle (to be used for comparing only)
+ * set in ndb_logevent_get_next()
+ */
+ void *handle;
+
+ /** Which event */
+ enum Ndb_logevent_type type;
+
+ /** Time when log event was registred at the management server */
+ unsigned time;
+
+ /** Category of log event */
+ enum ndb_mgm_event_category category;
+
+ /** Severity of log event */
+ enum ndb_mgm_event_severity severity;
+
+ /** Level (0-15) of log event */
+ unsigned level;
+
+ /** Node ID of the node that reported the log event */
+ unsigned source_nodeid;
+
+ /** Union of log event specific data. Use @ref type to decide
+ * which struct to use
+ */
+ union {
+ /* CONNECT */
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ } Connected;
+
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ } Disconnected;
+
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ } CommunicationClosed;
+
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ } CommunicationOpened;
+
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ unsigned version;
+ } ConnectedApiVersion;
+
+ /* CHECKPOINT */
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned gci;
+ } GlobalCheckpointStarted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned gci;
+ } GlobalCheckpointCompleted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned lci;
+ unsigned keep_gci;
+ unsigned restore_gci;
+ } LocalCheckpointStarted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned lci;
+ } LocalCheckpointCompleted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned data;
+ } LCPStoppedInCalcKeepGci;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ unsigned table_id;
+ unsigned fragment_id;
+ } LCPFragmentCompleted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned acc_count;
+ unsigned tup_count;
+ } UndoLogBlocked;
+
+ /* STARTUP */
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned version;
+ } NDBStartStarted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned version;
+ } NDBStartCompleted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ } STTORRYRecieved;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned phase;
+ unsigned starttype;
+ } StartPhaseCompleted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned own_id;
+ unsigned president_id;
+ unsigned dynamic_id;
+ } CM_REGCONF;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned own_id;
+ unsigned other_id;
+ unsigned cause;
+ } CM_REGREF;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned own_id;
+ unsigned left_id;
+ unsigned right_id;
+ unsigned dynamic_id;
+ } FIND_NEIGHBOURS;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned stoptype;
+ } NDBStopStarted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ } NDBStopAborted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ unsigned keep_gci;
+ unsigned completed_gci;
+ unsigned restorable_gci;
+ } StartREDOLog;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned log_part;
+ unsigned start_mb;
+ unsigned stop_mb;
+ unsigned gci;
+ } StartLog;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned block;
+ unsigned data1;
+ unsigned data2;
+ unsigned data3;
+ unsigned data4;
+ unsigned data5;
+ unsigned data6;
+ unsigned data7;
+ unsigned data8;
+ unsigned data9;
+ unsigned data10;
+ } UNDORecordsExecuted;
+
+ /* NODERESTART */
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ } NR_CopyDict;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ } NR_CopyDistr;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned dest_node;
+ } NR_CopyFragsStarted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned dest_node;
+ unsigned table_id;
+ unsigned fragment_id;
+ } NR_CopyFragDone;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned dest_node;
+ } NR_CopyFragsCompleted;
+
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned block; /* 0 = all */
+ unsigned failed_node;
+ unsigned completing_node; /* 0 = all */
+ } NodeFailCompleted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned failed_node;
+ unsigned failure_state;
+ } NODE_FAILREP;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned code; /* code & state << 16 */
+ unsigned arbit_node;
+ unsigned ticket_0;
+ unsigned ticket_1;
+ /* TODO */
+ } ArbitState;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned code; /* code & state << 16 */
+ unsigned arbit_node;
+ unsigned ticket_0;
+ unsigned ticket_1;
+ /* TODO */
+ } ArbitResult;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ } GCP_TakeoverStarted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ } GCP_TakeoverCompleted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ } LCP_TakeoverStarted;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned state;
+ } LCP_TakeoverCompleted;
+
+ /* STATISTIC */
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned trans_count;
+ unsigned commit_count;
+ unsigned read_count;
+ unsigned simple_read_count;
+ unsigned write_count;
+ unsigned attrinfo_count;
+ unsigned conc_op_count;
+ unsigned abort_count;
+ unsigned scan_count;
+ unsigned range_scan_count;
+ } TransReportCounters;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned ops;
+ } OperationReportCounters;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned table_id;
+ } TableCreated;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned mean_loop_count;
+ } JobStatistic;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned to_node;
+ unsigned mean_sent_bytes;
+ } SendBytesStatistic;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned from_node;
+ unsigned mean_received_bytes;
+ } ReceiveBytesStatistic;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ int gth;
+ unsigned page_size_kb;
+ unsigned pages_used;
+ unsigned pages_total;
+ unsigned block;
+ } MemoryUsage;
+
+ /* ERROR */
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned to_node;
+ unsigned code;
+ } TransporterError;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned to_node;
+ unsigned code;
+ } TransporterWarning;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ unsigned count;
+ } MissedHeartbeat;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ } DeadDueToHeartbeat;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ /* TODO */
+ } WarningEvent;
+
+ /* INFO */
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ } SentHeartbeat;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ unsigned node;
+ } CreateLogBytes;
+ /** Log event specific data for for corresponding NDB_LE_ log event */
+ struct {
+ /* TODO */
+ } InfoEvent;
+
+ /** Log event data for @ref NDB_LE_BackupStarted */
+ struct {
+ unsigned starting_node;
+ unsigned backup_id;
+ } BackupStarted;
+ /** Log event data @ref NDB_LE_BackupFailedToStart */
+ struct {
+ unsigned starting_node;
+ unsigned error;
+ } BackupFailedToStart;
+ /** Log event data @ref NDB_LE_BackupCompleted */
+ struct {
+ unsigned starting_node;
+ unsigned backup_id;
+ unsigned start_gci;
+ unsigned stop_gci;
+ unsigned n_records;
+ unsigned n_log_records;
+ unsigned n_bytes;
+ unsigned n_log_bytes;
+ } BackupCompleted;
+ /** Log event data @ref NDB_LE_BackupAborted */
+ struct {
+ unsigned starting_node;
+ unsigned backup_id;
+ unsigned error;
+ } BackupAborted;
+#ifndef DOXYGEN_FIX
+ };
+#else
+ } <union>;
+#endif
+ };
+
+enum ndb_logevent_handle_error {
+ NDB_LEH_NO_ERROR,
+ NDB_LEH_READ_ERROR,
+ NDB_LEH_MISSING_EVENT_SPECIFIER,
+ NDB_LEH_UNKNOWN_EVENT_TYPE,
+ NDB_LEH_UNKNOWN_EVENT_VARIABLE,
+ NDB_LEH_INTERNAL_ERROR
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif
diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp
index be6d656e1a5..c0b877af07d 100644
--- a/ndb/include/mgmcommon/ConfigRetriever.hpp
+++ b/ndb/include/mgmcommon/ConfigRetriever.hpp
@@ -32,6 +32,7 @@ public:
~ConfigRetriever();
int do_connect(int no_retries, int retry_delay_in_seconds, int verbose);
+ int disconnect();
/**
* Get configuration for current node.
@@ -75,6 +76,8 @@ public:
Uint32 get_mgmd_port() const;
const char *get_mgmd_host() const;
const char *get_connectstring(char *buf, int buf_sz) const;
+ NdbMgmHandle get_mgmHandle() { return m_handle; };
+ NdbMgmHandle* get_mgmHandlePtr() { return &m_handle; };
Uint32 get_configuration_nodeid() const;
private:
diff --git a/ndb/include/ndb_constants.h b/ndb/include/ndb_constants.h
new file mode 100644
index 00000000000..c292880749b
--- /dev/null
+++ b/ndb/include/ndb_constants.h
@@ -0,0 +1,72 @@
+/* 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 ndb_constants.h
+ *
+ * Constants common to NDB API and NDB kernel.
+ * Changing the values makes database upgrade impossible.
+ *
+ * New or removed definitions must be replicated to
+ * NdbDictionary.hpp and NdbSqlUtil.hpp.
+ *
+ * Not for use by application programs.
+ * Use the enums provided by NdbDictionary instead.
+ */
+
+#ifndef NDB_CONSTANTS_H
+#define NDB_CONSTANTS_H
+
+/*
+ * Data type constants.
+ */
+
+#define NDB_TYPE_UNDEFINED 0
+
+#define NDB_TYPE_TINYINT 1
+#define NDB_TYPE_TINYUNSIGNED 2
+#define NDB_TYPE_SMALLINT 3
+#define NDB_TYPE_SMALLUNSIGNED 4
+#define NDB_TYPE_MEDIUMINT 5
+#define NDB_TYPE_MEDIUMUNSIGNED 6
+#define NDB_TYPE_INT 7
+#define NDB_TYPE_UNSIGNED 8
+#define NDB_TYPE_BIGINT 9
+#define NDB_TYPE_BIGUNSIGNED 10
+#define NDB_TYPE_FLOAT 11
+#define NDB_TYPE_DOUBLE 12
+#define NDB_TYPE_OLDDECIMAL 13
+#define NDB_TYPE_CHAR 14
+#define NDB_TYPE_VARCHAR 15
+#define NDB_TYPE_BINARY 16
+#define NDB_TYPE_VARBINARY 17
+#define NDB_TYPE_DATETIME 18
+#define NDB_TYPE_DATE 19
+#define NDB_TYPE_BLOB 20
+#define NDB_TYPE_TEXT 21
+#define NDB_TYPE_BIT 22
+#define NDB_TYPE_LONGVARCHAR 23
+#define NDB_TYPE_LONGVARBINARY 24
+#define NDB_TYPE_TIME 25
+#define NDB_TYPE_YEAR 26
+#define NDB_TYPE_TIMESTAMP 27
+#define NDB_TYPE_OLDDECIMALUNSIGNED 28
+#define NDB_TYPE_DECIMAL 29
+#define NDB_TYPE_DECIMALUNSIGNED 30
+
+#define NDB_TYPE_MAX 31
+
+#endif
diff --git a/ndb/include/ndb_global.h.in b/ndb/include/ndb_global.h.in
index eadd5e37b9b..43f90e1f8b5 100644
--- a/ndb/include/ndb_global.h.in
+++ b/ndb/include/ndb_global.h.in
@@ -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 */
-#ifndef NDBGLOBAL_H
-#define NDBGLOBAL_H
+#ifndef NDB_GLOBAL_H
+#define NDB_GLOBAL_H
#include <ndb_types.h>
@@ -31,45 +31,22 @@
#define HAVE_STRCASECMP
#define strcasecmp _strcmpi
#pragma warning(disable: 4503 4786)
-typedef unsigned __int64 Uint64;
-typedef signed __int64 Int64;
#else
#undef NDB_WIN32
#define DIR_SEPARATOR "/"
-typedef unsigned long long Uint64;
-typedef signed long long Int64;
#endif
#include <my_global.h>
-typedef signed char Int8;
-typedef unsigned char Uint8;
-typedef signed short Int16;
-typedef unsigned short Uint16;
-typedef signed int Int32;
-typedef unsigned int Uint32;
-
-typedef unsigned int UintR;
-
-#ifdef __SIZE_TYPE__
-typedef __SIZE_TYPE__ UintPtr;
-#elif SIZEOF_CHARP == 4
-typedef Uint32 UintPtr;
-#elif SIZEOF_CHARP == 8
-typedef Uint64 UintPtr;
-#else
-#error "Unknown size of (char *)"
-#endif
-
-#if ! (SIZEOF_CHAR == 1)
+#if ! (NDB_SIZEOF_CHAR == SIZEOF_CHAR)
#error "Invalid define for Uint8"
#endif
-#if ! (SIZEOF_INT == 4)
+#if ! (NDB_SIZEOF_INT == SIZEOF_INT)
#error "Invalid define for Uint32"
#endif
-#if ! (SIZEOF_LONG_LONG == 8)
+#if ! (NDB_SIZEOF_LONG_LONG == SIZEOF_LONG_LONG)
#error "Invalid define for Uint64"
#endif
diff --git a/ndb/include/ndb_types.h.in b/ndb/include/ndb_types.h.in
new file mode 100644
index 00000000000..2a5d576ffea
--- /dev/null
+++ b/ndb/include/ndb_types.h.in
@@ -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 */
+
+/**
+ * @file ndb_types.h
+ */
+
+#ifndef NDB_TYPES_H
+#define NDB_TYPES_H
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(_WIN64)
+#define NDB_SIZEOF_CHARP SIZEOF_CHARP
+#define NDB_SIZEOF_CHAR SIZEOF_CHAR
+#define NDB_SIZEOF_SHORT 2
+#define NDB_SIZEOF_INT SIZEOF_INT
+#define NDB_SIZEOF_LONG SIZEOF_LONG
+#define NDB_SIZEOF_LONG_LONG SIZEOF_LONG_LONG
+typedef unsigned __int64 Uint64;
+typedef signed __int64 Int64;
+#else
+#define NDB_SIZEOF_CHARP @NDB_SIZEOF_CHARP@
+#define NDB_SIZEOF_CHAR @NDB_SIZEOF_CHAR@
+#define NDB_SIZEOF_INT @NDB_SIZEOF_INT@
+#define NDB_SIZEOF_SHORT @NDB_SIZEOF_SHORT@
+#define NDB_SIZEOF_LONG @NDB_SIZEOF_LONG@
+#define NDB_SIZEOF_LONG_LONG @NDB_SIZEOF_LONG_LONG@
+typedef unsigned long long Uint64;
+typedef signed long long Int64;
+#endif
+
+typedef signed char Int8;
+typedef unsigned char Uint8;
+typedef signed short Int16;
+typedef unsigned short Uint16;
+typedef signed int Int32;
+typedef unsigned int Uint32;
+
+typedef unsigned int UintR;
+
+#ifdef __SIZE_TYPE__
+ typedef __SIZE_TYPE__ UintPtr;
+#elif NDB_SIZEOF_CHARP == 4
+ typedef Uint32 UintPtr;
+#elif NDB_SIZEOF_CHARP == 8
+ typedef Uint64 UintPtr;
+#else
+ #error "Unknown size of (char *)"
+#endif
+
+#if ! (NDB_SIZEOF_CHAR == 1)
+#error "Invalid define for Uint8"
+#endif
+
+#if ! (NDB_SIZEOF_SHORT == 2)
+#error "Invalid define for Uint16"
+#endif
+
+#if ! (NDB_SIZEOF_INT == 4)
+#error "Invalid define for Uint32"
+#endif
+
+#if ! (NDB_SIZEOF_LONG_LONG == 8)
+#error "Invalid define for Uint64"
+#endif
+
+#include "ndb_constants.h"
+
+#endif
diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp
index 766409d64e2..db2212075e8 100644
--- a/ndb/include/ndbapi/Ndb.hpp
+++ b/ndb/include/ndbapi/Ndb.hpp
@@ -17,245 +17,700 @@
/**
@mainpage NDB API Programmers' Guide
- This guide assumes a basic familiarity with NDB Cluster concepts.
- Some of the fundamental ones are described in section @ref secConcepts.
-
- The <em>NDB API</em> is an NDB Cluster application interface
- that implements both synchronous and asynchronous transactions.
+ This guide assumes a basic familiarity with MySQL Cluster concepts found
+ on http://dev.mysql.com/doc/mysql/en/NDBCluster.html .
+ Some of the fundamental ones are also described in section @ref secConcepts.
+
+ The NDB API is a MySQL Cluster application interface
+ that implements transactions.
The NDB API consists of the following fundamental classes:
- - Ndb is the main class representing the database,
- - NdbConnection represents a transaction,
- - NdbOperation represents a transaction operation using primary key,
- - NdbIndexOperation represents a transaction operation using a secondary
- index,
- - NdbRecAttr represents the value of an attribute, and
+ - Ndb_cluster_connection, representing a connection to a cluster,
+ - Ndb is the main class, representing a connection to a database,
+ - NdbTransaction represents a transaction,
+ - NdbOperation represents an operation using a primary key,
+ - NdbScanOperation represents an operation performing a full table scan.
+ - NdbIndexOperation represents an operation using a unique hash index,
+ - NdbIndexScanOperation represents an operation performing a scan using
+ an ordered index,
+ - NdbRecAttr represents an attribute value
- NdbDictionary represents meta information about tables and attributes.
- - NdbError represents an error condition
- There are also some auxiliary classes.
+
+ In addition, the NDB API defines a structure NdbError, which contains the
+ specification for an error.
+
+ It is also possible to receive "events" triggered when data in the database in changed.
+ This is done through the NdbEventOperation class.
+
+ There are also some auxiliary classes, which are listed in the class hierarchy.
The main structure of an application program is as follows:
- -# Construct and initialize Ndb object(s).
- -# Define and execute (synchronous or asynchronous) transactions.
- -# Delete Ndb objects
-
- The main structure of a transaction is as follows:
- -# Start transaction
- -# Add and define operations (associated with the transaction)
- -# Execute transaction
-
- The execute can be of two different types,
- <em>Commit</em> or <em>NoCommit</em>.
- (The execute can also be divided into three
- steps: prepare, send, and poll to get asynchronous
- transactions. More about this later.)
-
- If the execute is of type NoCommit,
- then the application program executes part of a transaction,
- but without committing the transaction.
- After a NoCommit type of execute, the program can continue
+ -# Connect to a cluster using the Ndb_cluster_connection
+ object.
+ -# Initiate a database connection by constructing and initialising one or more Ndb objects.
+ -# Define and execute transactions using the NdbTransaction class.
+ -# Delete Ndb objects.
+ -# Terminate the connection to the cluster (terminate instance of Ndb_cluster_connection).
+
+ The procedure for using transactions is as follows:
+ -# Start transaction (instantiate an NdbTransaction object)
+ -# Add and define operations associated with the transaction using instances of one or more of the
+ NdbOperation, NdbScanOperation, NdbIndexOperation, and NdbIndexScanOperation classes
+ -# Execute transaction (call NdbTransaction::execute())
+
+ The operation can be of two different types,
+ <var>Commit</var> or <var>NoCommit</var>.
+ If the operation is of type <var>NoCommit</var>,
+ then the application program executes the operation part of a transaction,
+ but without actually committing the transaction.
+ After executing a <var>NoCommit</var> operation, the program can continue
to add and define more operations to the transaction
for later execution.
- If the execute is of type Commit, then the transaction is
- committed and no further adding and defining of operations
- is allowed.
-
+ If the operation is of type <var>Commit</var>, then the transaction is
+ immediately committed. The transaction <em>must</em> be closed after it has been
+ commited (event if commit fails), and no further addition or definition of
+ operations for this transaction is allowed.
@section secSync Synchronous Transactions
- Synchronous transactions are defined and executed in the following way.
+ Synchronous transactions are defined and executed as follows:
- -# Start (create) transaction (the transaction will be
- referred to by an NdbConnection object,
- typically created by Ndb::startTransaction).
- At this step the transaction is being defined.
- It is not yet sent to the NDB kernel.
- -# Add and define operations to the transaction
- (using NdbConnection::getNdbOperation and
- methods from class NdbOperation).
- The transaction is still not sent to the NDB kernel.
- -# Execute the transaction (using NdbConnection::execute).
- -# Close the transaction (using Ndb::closeTransaction).
+ -# Start (create) the transaction, which is
+ referenced by an NdbTransaction object
+ (typically created using Ndb::startTransaction()).
+ At this point, the transaction is only being defined,
+ and is not yet sent to the NDB kernel.
+ -# Define operations and add them to the transaction, using one or more of
+ - NdbTransaction::getNdbOperation()
+ - NdbTransaction::getNdbScanOperation()
+ - NdbTransaction::getNdbIndexOperation()
+ - NdbTransaction::getNdbIndexScanOperation()
+ along with the appropriate methods of the respective NdbOperation class
+ (or one possiblt one or more of its subclasses).
+ Note that the transaction has still not yet been sent to the NDB kernel.
+ -# Execute the transaction, using the NdbTransaction::execute() method.
+ -# Close the transaction (call Ndb::closeTransaction()).
- See example program in section @ref ndbapi_example1.cpp.
+ For an example of this process, see the program listing in
+ @ref ndbapi_simple.cpp.
To execute several parallel synchronous transactions, one can either
- use multiple Ndb objects in several threads or start multiple
- applications programs.
- Another way to execute several parallel transactions is to use
- asynchronous transactions.
-
-
+ use multiple Ndb objects in several threads, or start multiple
+ application programs.
+
@section secNdbOperations Operations
- Each transaction (NdbConnection object) consist of a list of
- operations (NdbOperation or NdbIndexOperation objects.
- NdbIndexOperation is used for accessing tables through secondary indexes).
- Operations are of two different kinds:
- -# standard operations, and
- -# interpreted program operations.
+ A NdbTransaction consists of a list of operations, each of which is represented
+ by an instance of NdbOperation, NdbScanOperation, NdbIndexOperation, or
+ NdbIndexScanOperation.
- <h3>Standard Operations</h3>
- After the operation is created using NdbConnection::getNdbOperation
- (or NdbConnection::getNdbIndexOperation),
- it is defined in the following three steps:
- -# Defining standard operation type
- (e.g. using NdbOperation::readTuple)
- -# Specifying search conditions
- (e.g. using NdbOperation::equal)
- -# Specify attribute actions
- (e.g. using NdbOperation::getValue)
-
- Example code (using an NdbOperation):
+ <h3>Single row operations</h3>
+ After the operation is created using NdbTransaction::getNdbOperation()
+ (or NdbTransaction::getNdbIndexOperation()), it is defined in the following
+ three steps:
+ -# Define the standard operation type, using NdbOperation::readTuple()
+ -# Specify search conditions, using NdbOperation::equal()
+ -# Specify attribute actions, using NdbOperation::getValue()
+
+ Here are two brief examples illustrating this process. For the sake of
+ brevity, we omit error handling.
+
+ This first example uses an NdbOperation:
@code
- MyOperation = MyConnection->getNdbOperation("MYTABLENAME"); // 1. Create
- if (MyOperation == NULL) APIERROR(MyConnection->getNdbError());
+ // 1. Retrieve table object
+ myTable= myDict->getTable("MYTABLENAME");
+
+ // 2. Create
+ myOperation= myTransaction->getNdbOperation(myTable);
- MyOperation->readTuple(); // 2. Define type of operation
- MyOperation->equal("ATTR1", i); // 3. Specify Search Conditions
+ // 3. Define type of operation and lock mode
+ myOperation->readTuple(NdbOperation::LM_Read);
+
+ // 4. Specify Search Conditions
+ myOperation->equal("ATTR1", i);
- MyRecAttr = MyOperation->getValue("ATTR2", NULL); // 4. Attribute Actions
- if (MyRecAttr == NULL) APIERROR(MyConnection->getNdbError());
+ // 5. Attribute Actions
+ myRecAttr= myOperation->getValue("ATTR2", NULL);
@endcode
- For more examples, see @ref ndbapi_example1.cpp and @ref ndbapi_example2.cpp.
+ For additional examples of this sort, see @ref ndbapi_simple.cpp.
- Example code using an NdbIndexOperation:
+ The second example uses an NdbIndexOperation:
@code
- MyOperation = // 1. Create
- MyConnection->getNdbIndexOperation("MYINDEX", "MYTABLENAME");
- if (MyOperation == NULL) APIERROR(MyConnection->getNdbError());
+ // 1. Retrieve index object
+ myIndex= myDict->getIndex("MYINDEX", "MYTABLENAME");
+
+ // 2. Create
+ myOperation= myTransaction->getNdbIndexOperation(myIndex);
+
+ // 3. Define type of operation and lock mode
+ myOperation->readTuple(NdbOperation::LM_Read);
- MyOperation->readTuple(); // 2. Define type of operation
- MyOperation->equal("ATTR1", i); // 3. Specify Search Conditions
+ // 4. Specify Search Conditions
+ myOperation->equal("ATTR1", i);
- MyRecAttr = MyOperation->getValue("ATTR2", NULL); // 4. Attribute Actions
- if (MyRecAttr == NULL) APIERROR(MyConnection->getNdbError());
+ // 5. Attribute Actions
+ myRecAttr = myOperation->getValue("ATTR2", NULL);
@endcode
- For more examples, see @ref ndbapi_example4.cpp.
+ Another example of this second type can be found in
+ @ref ndbapi_simple_index.cpp.
+ We will now discuss in somewhat greater detail each step involved in the
+ creation and use of synchronous transactions.
- <h4>Step 1: Define Standard Operation Type</h4>
- The following types of standard operations exist:
- -# NdbOperation::insertTuple :
+ <h4>Step 1: Define single row operation type</h4>
+ The following operation types are supported:
+ -# NdbOperation::insertTuple() :
inserts a non-existing tuple
- -# NdbOperation::writeTuple :
+ -# NdbOperation::writeTuple() :
updates an existing tuple if is exists,
otherwise inserts a new tuple
- -# NdbOperation::updateTuple :
+ -# NdbOperation::updateTuple() :
updates an existing tuple
- -# NdbOperation::deleteTuple :
+ -# NdbOperation::deleteTuple() :
deletes an existing tuple
- -# NdbOperation::readTuple :
- reads an existing tuple
- -# NdbOperation::readTupleExclusive :
- reads an existing tuple using an exclusive lock
- -# NdbOperation::simpleRead :
- reads an existing tuple (using shared read lock),
- but releases lock immediately after read
- -# NdbOperation::committedRead :
- reads committed tuple
- -# NdbOperation::dirtyUpdate :
- updates an existing tuple, but releases lock immediately
- after read (uses dirty lock)
- -# NdbOperation::dirtyWrite :
- updates or writes a tuple, but releases lock immediately
- after read (uses dirty lock)
+ -# NdbOperation::readTuple() :
+ reads an existing tuple with specified lock mode
All of these operations operate on the unique tuple key.
(When NdbIndexOperation is used then all of these operations
- operate on a defined secondary index.)
-
-
- Some comments:
- - NdbOperation::simpleRead and
- NdbOperation::committedRead can execute on the same transaction
- as the above operations but will release its locks immediately
- after reading the tuple.
- NdbOperation::simpleRead will always read the latest version
- of the tuple.
- Thus it will wait until it can acquire a shared read lock on
- the tuple.
- NdbOperation::committedRead will read the latest committed
- version of the tuple.
- <br>
- Both NdbOperation::simpleRead and NdbOperation::committedRead
- are examples of consistent reads which are not repeatable.
- All reads read the latest version if updates were made by the same
- transaction.
- Errors on simple read are only reported by the NdbOperation object.
- These error codes are not transferred to the NdbConnection object.
- - NdbOperation::dirtyUpdate and NdbOperation::dirtyWrite
- will execute in the same transaction
- but will release the lock immediately after updating the
- tuple.
- It will wait on the lock until it can acquire an exclusive
- write lock.
- In a replicated version of NDB Cluster NdbOperation::dirtyUpdate
- can lead to inconsistency between the replicas.
- Examples of when it could be used is
- to update statistical counters on tuples which are "hot-spots".
+ operate on a defined unique hash index.)
@note If you want to define multiple operations within the same transaction,
- then you need to call NdbConnection::getNdbOperation
- (or NdbConnection::getNdbIndexOperation) for each
- operation.
-
+ then you need to call NdbTransaction::getNdbOperation() or
+ NdbTransaction::getNdbIndexOperation() for each operation.
<h4>Step 2: Specify Search Conditions</h4>
- The search condition is used to select tuples.
- (In the current NdbIndexOperation implementation
- this means setting the value of
- the secondary index attributes of the wanted tuple.)
-
- If a tuple identity is used, then NdbOperation::setTupleId
- is used to define the search key when inserting new tuples.
- Otherwise, NdbOperation::equal is used.
-
- For NdbOperation::insertTuple it is also allowed to define the
- search key by using NdbOperation::setValue.
- The NDB API will automatically detect that it is
- supposed to use NdbOperation::equal instead.
- For NdbOperation::insertTuple it is not necessary to use
- NdbOperation::setValue on key attributes before other attributes.
-
+ The search condition is used to select tuples. Search conditions are set using NdbOperation::equal().
<h4>Step 3: Specify Attribute Actions</h4>
- Now it is time to define which attributes should be read or updated.
- Deletes can neither read nor set values, read can only read values and
- updates can only set values.
- Normally the attribute is defined by its name but it is
- also possible to use the attribute identity to define the
+ Next, it is necessary to determine which attributes should be read or updated.
+ It is important to remember that:
+ - Deletes can neither read nor set values, but only delete them
+ - Reads can only read values
+ - Updates can only set values
+ Normally the attribute is identified by name, but it is
+ also possible to use the attribute's identity to determine the
attribute.
- The mapping from name to identity is performed by the Table object.
- NdbIndexOperation::getValue returns an NdbRecAttr object
+ NdbOperation::getValue() returns an NdbRecAttr object
containing the read value.
- To get the value, there is actually two methods.
- The application can either
+ To obtain the actual value, one of two methods can be used;
+ the application can either
- use its own memory (passed through a pointer aValue) to
- NdbIndexOperation::getValue, or
+ NdbOperation::getValue(), or
- receive the attribute value in an NdbRecAttr object allocated
by the NDB API.
- The NdbRecAttr object is released when Ndb::closeTransaction
+ The NdbRecAttr object is released when Ndb::closeTransaction()
is called.
- Thus, the application can not reference this object after
- Ndb::closeTransaction have been called.
- The result of reading data from an NdbRecAttr object before
- calling NdbConnection::execute is undefined.
+ Thus, the application cannot reference this object following
+ any subsequent call to Ndb::closeTransaction().
+ Attempting to read data from an NdbRecAttr object before
+ calling NdbTransaction::execute() yields an undefined result.
+
+
+ @subsection secScan Scan Operations
+
+ Scans are roughly the equivalent of SQL cursors, providing a means to
+ preform high-speed row processing. A scan can be performed
+ on either a table (using @ref NdbScanOperation) or
+ an ordered index (by means of an @ref NdbIndexScanOperation).
+
+ Scan operations are characterised by the following:
+ - They can perform only reads (shared, exclusive or dirty)
+ - They can potentially work with multiple rows
+ - They can be used to update or delete multiple rows
+ - They can operate on several nodes in parallel
+
+ After the operation is created using NdbTransaction::getNdbScanOperation()
+ (or NdbTransaction::getNdbIndexScanOperation()),
+ it is carried out in the following three steps:
+ -# Define the standard operation type, using NdbScanOperation::readTuples()
+ -# Specify search conditions, using @ref NdbScanFilter and/or
+ @ref NdbIndexScanOperation::setBound()
+ -# Specify attribute actions, using NdbOperation::getValue()
+ -# Executing the transaction, using NdbTransaction::execute()
+ -# Traversing the result set by means of succssive calls to
+ NdbScanOperation::nextResult()
+
+ Here are two brief examples illustrating this process. Once again, in order
+ to keep things relatively short and simple, we will forego any error handling.
+
+ This first example performs a table scan, using an NdbScanOperation:
+ @code
+ // 1. Retrieve table object
+ myTable= myDict->getTable("MYTABLENAME");
+
+ // 2. Create
+ myOperation= myTransaction->getNdbScanOperation(myTable);
+
+ // 3. Define type of operation and lock mode
+ myOperation->readTuples(NdbOperation::LM_Read);
+
+ // 4. Specify Search Conditions
+ NdbScanFilter sf(myOperation);
+ sf.begin(NdbScanFilter::OR);
+ sf.eq(0, i); // Return rows with column 0 equal to i or
+ sf.eq(1, i+1); // column 1 equal to (i+1)
+ sf.end();
+
+ // 5. Attribute Actions
+ myRecAttr= myOperation->getValue("ATTR2", NULL);
+ @endcode
+
+ Our second example uses an NdbIndexScanOperation to perform an index scan:
+ @code
+ // 1. Retrieve index object
+ myIndex= myDict->getIndex("MYORDEREDINDEX", "MYTABLENAME");
+
+ // 2. Create
+ myOperation= myTransaction->getNdbIndexScanOperation(myIndex);
+ // 3. Define type of operation and lock mode
+ myOperation->readTuples(NdbOperation::LM_Read);
+ // 4. Specify Search Conditions
+ // All rows with ATTR1 between i and (i+1)
+ myOperation->setBound("ATTR1", NdbIndexScanOperation::BoundGE, i);
+ myOperation->setBound("ATTR1", NdbIndexScanOperation::BoundLE, i+1);
+
+ // 5. Attribute Actions
+ myRecAttr = MyOperation->getValue("ATTR2", NULL);
+ @endcode
+
+ Some additional discussion of each step required to perform a scan follows:
+
+ <h4>Step 1: Define Scan Operation Type</h4>
+ It is important to remember that only a single operation is supported for each scan operation
+ (@ref NdbScanOperation::readTuples() or @ref NdbIndexScanOperation::readTuples()).
+
+ @note If you want to define multiple scan operations within the same
+ transaction, then you need to call
+ NdbTransaction::getNdbScanOperation() or
+ NdbTransaction::getNdbIndexScanOperation() separately for <b>each</b> operation.
+
+ <h4>Step 2: Specify Search Conditions</h4>
+ The search condition is used to select tuples.
+ If no search condition is specified, the scan will return all rows
+ in the table.
+
+ The search condition can be an @ref NdbScanFilter (which can be used on both
+ @ref NdbScanOperation and @ref NdbIndexScanOperation) or bounds which
+ can only be used on index scans (@ref NdbIndexScanOperation::setBound()).
+ An index scan can use both NdbScanFilter and bounds.
+
+ @note When NdbScanFilter is used, each row is examined, whether or not it is
+ actually returned. However, when using bounds, only rows within the bounds will be examined.
+
+ <h4>Step 3: Specify Attribute Actions</h4>
+
+ Next, it is necessary to define which attributes should be read.
+ As with transaction attributes, scan attributes are defined by name but it is
+ also possible to use the attributes' identities to define attributes.
+
+ As previously discussed (see @ref secSync), the value read is returned as
+ an NdbRecAttr object by the NdbOperation::getValue() method.
+
+ <h3>Using Scan to Update/Delete</h3>
+ Scanning can also be used to update or delete rows.
+ This is performed by
+ -# Scanning using exclusive locks (using NdbOperation::LM_Exclusive)
+ -# When iterating through the result set, for each row optionally calling
+ either NdbScanOperation::updateCurrentTuple() or
+ NdbScanOperation::deleteCurrentTuple()
+ -# (If performing NdbScanOperation::updateCurrentTuple():)
+ Setting new values for records simply by using @ref NdbOperation::setValue().
+ NdbOperation::equal() should <em>not</em> be called in such cases, as the primary
+ key is retrieved from the scan.
+
+ @note The actual update or delete will not be performed until the next
+ call to NdbTransaction::execute(), just as with single row operations.
+ NdbTransaction::execute() also must be called before any locks are released;
+ see @ref secScanLocks for more information.
+
+ <h4>Features Specific to Index Scans</h4>
+
+ When performing an index scan, it is possible to
+ scan only a subset of a table using @ref NdbIndexScanOperation::setBound().
+ In addition, result sets can be sorted in either ascending or descending order, using
+ @ref NdbIndexScanOperation::readTuples(). Note that rows are returned unordered
+ by default, that is, unless <var>sorted</var> is set to <b>true</b>.
+ It is also important to note that, when using NdbIndexScanOperation::BoundEQ
+ on a partition key, only fragments containing rows will actually be scanned.
+
+ @note When performing a sorted scan, any value passed as the
+ NdbIndexScanOperation::readTuples() method's <code>parallel</code> argument
+ will be ignored and maximum parallelism will be used instead. In other words, all
+ fragments which it is possible to scan will be scanned simultaneously and in parallel
+ in such cases.
+
+ @subsection secScanLocks Lock handling with scans
+
+ Performing scans on either a tables or an index has the potential
+ return a great many records; however, Ndb will lock only a predetermined
+ number of rows per fragment at a time.
+ How many rows will be locked per fragment is controlled by the
+ <var>batch</var> parameter passed to NdbScanOperation::readTuples().
+
+ In order to allow the application to handle how locks are released,
+ NdbScanOperation::nextResult() has a Boolean parameter <var>fetch_allow</var>.
+ If NdbScanOperation::nextResult() is called with <var>fetch_allow</var> equal to
+ <b>false</b>, then no locks may be released as result of the function call.
+ Otherwise the locks for the current batch may be released.
+
+ This next example shows a scan delete that handle locks in an efficient manner.
+ For the sake of brevity, we omit error-handling.
+ @code
+ int check;
+
+ // Outer loop for each batch of rows
+ while((check = MyScanOperation->nextResult(true)) == 0)
+ {
+ do
+ {
+ // Inner loop for each row within batch
+ MyScanOperation->deleteCurrentTuple();
+ } while((check = MyScanOperation->nextResult(false)) == 0);
+
+ // When no more rows in batch, exeute all defined deletes
+ MyTransaction->execute(NoCommit);
+ }
+ @endcode
+
+ See @ref ndbapi_scan.cpp for a more complete example of a scan.
+
+ @section secError Error Handling
+
+ Errors can occur either when operations making up a transaction are being
+ defined, or when the transaction is actually being executed. Catching and
+ handling either sort of error requires testing the value returned by
+ NdbTransaction::execute(), and then, if an error is indicated (that is,
+ if this value is equal to -1), using the following two methods in order to
+ identify the error's type and location:
+
+ - NdbTransaction::getNdbErrorOperation() returns a reference to the
+ operation causing the most recent error.
+ - NdbTransaction::getNdbErrorLine() yields the method number of the
+ erroneous method in the operation.
+
+ This short example illustrates how to detect an error and to use these
+ two methods to identify it:
+
+ @code
+ theTransaction = theNdb->startTransaction();
+ theOperation = theTransaction->getNdbOperation("TEST_TABLE");
+ if (theOperation == NULL) goto error;
+ theOperation->readTuple(NdbOperation::LM_Read);
+ theOperation->setValue("ATTR_1", at1);
+ theOperation->setValue("ATTR_2", at1); // Error occurs here
+ theOperation->setValue("ATTR_3", at1);
+ theOperation->setValue("ATTR_4", at1);
+
+ if (theTransaction->execute(Commit) == -1) {
+ errorLine = theTransaction->getNdbErrorLine();
+ errorOperation = theTransaction->getNdbErrorOperation();
+ }
+ @endcode
+
+ Here <code>errorLine</code> will be 3, as the error occurred in the
+ third method called on the NdbOperation object (in this case,
+ <code>theOperation</code>); if the result of
+ NdbTransaction::getNdbErrorLine() is 0, this means that the error
+ occurred when the operations were executed. In this example,
+ <code>errorOperation</code> will be a pointer to the <code>theOperation</code>
+ object. The NdbTransaction::getNdbError() method returns an NdbError
+ object providing information about the error.
+
+ @note Transactions are <b>not</b> automatically closed when an error occurs. Call
+ Ndb::closeTransaction() to close the transaction.
+
+ One recommended way to handle a transaction failure
+ (i.e. an error is reported) is to:
+ -# Rollback transaction (call NdbTransaction::execute() with a special parameter)
+ -# Close transaction (call NdbTransaction::closeTransaction())
+ -# If the error was temporary, attempt to restart the transaction
+
+ Several errors can occur when a transaction contains multiple
+ operations which are simultaneously executed.
+ In this case the application has to go through all operations
+ and query their NdbError objects to find out what really happened.
+
+ It is also important to note that errors can occur even when a commit is
+ reported as successful. In order to handle such situations, the NDB API
+ provides an additional NdbTransaction::commitStatus() method to check the
+ transactions's commit status.
+
+******************************************************************************/
+
+/**
+ * @page ndbapi_simple.cpp ndbapi_simple.cpp
+ * @include ndbapi_simple.cpp
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ * @page ndbapi_async.cpp ndbapi_async.cpp
+ * @include ndbapi_async.cpp
+ */
+/**
+ * @page ndbapi_async1.cpp ndbapi_async1.cpp
+ * @include ndbapi_async1.cpp
+ */
+#endif
+
+/**
+ * @page ndbapi_retries.cpp ndbapi_retries.cpp
+ * @include ndbapi_retries.cpp
+ */
+
+/**
+ * @page ndbapi_simple_index.cpp ndbapi_simple_index.cpp
+ * @include ndbapi_simple_index.cpp
+ */
+
+/**
+ * @page ndbapi_scan.cpp ndbapi_scan.cpp
+ * @include ndbapi_scan.cpp
+ */
+/**
+ * @page ndbapi_event.cpp ndbapi_event.cpp
+ * @include ndbapi_event.cpp
+ */
+
+
+/**
+ @page secAdapt Adaptive Send Algorithm
+
+ At the time of "sending" a transaction
+ (using NdbTransaction::execute()), the transactions
+ are in reality <em>not</em> immediately transfered to the NDB Kernel.
+ Instead, the "sent" transactions are only kept in a
+ special send list (buffer) in the Ndb object to which they belong.
+ The adaptive send algorithm decides when transactions should
+ actually be transferred to the NDB kernel.
+
+ The NDB API is designed as a multi-threaded interface and so
+ it is often desirable to transfer database operations from more than
+ one thread at a time.
+ The NDB API keeps track of which Ndb objects are active in transferring
+ information to the NDB kernel and the expected amount of threads to
+ interact with the NDB kernel.
+ Note that a given instance of Ndb should be used in at most one thread;
+ different threads should <em>not</em> use the same Ndb object.
+
+ There are four conditions leading to the transfer of database
+ operations from Ndb object buffers to the NDB kernel:
+ -# The NDB Transporter (TCP/IP, OSE, SCI or shared memory)
+ decides that a buffer is full and sends it off.
+ The buffer size is implementation-dependent and
+ may change between MySQL Cluster releases.
+ On TCP/IP the buffer size is usually around 64 KB;
+ on OSE/Delta it is usually less than 2000 bytes.
+ Since each Ndb object provides a single buffer per storage node,
+ the notion of a "full" buffer is local to this storage node.
+ -# The accumulation of statistical data on transferred information
+ may force sending of buffers to all storage nodes.
+ -# Every 10 ms, a special transmission thread checks whether or not
+ any send activity has occurred. If not, then the thread will
+ force transmission to all nodes.
+ This means that 20 ms is the maximum time database operations
+ are kept waiting before being sent off. The 10-millisecond limit
+ is likely to become a configuration parameter in
+ future releases of MySQL Cluster; however, for checks that
+ are more frequent than each 10 ms,
+ additional support from the operating system is required.
+ -# For methods that are affected by the adaptive send alorithm
+ (such as NdbTransaction::execute()), there is a <var>force</var>
+ parameter
+ that overrides its default behaviour in this regard and forces
+ immediate transmission to all nodes. See the inidvidual NDB API class
+ listings for more information.
+
+ @note The conditions listed above are subject to change in future releases
+ of MySQL Cluster.
+*/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+
+ For each of these "sent" transactions, there are three
+ possible states:
+ -# Waiting to be transferred to NDB Kernel.
+ -# Has been transferred to the NDB Kernel and is currently
+ being processed.
+ -# Has been transferred to the NDB Kernel and has
+ finished processing.
+ Now it is waiting for a call to a poll method.
+ (When the poll method is invoked,
+ then the transaction callback method will be executed.)
+
+ The poll method invoked (either Ndb::pollNdb() or Ndb::sendPollNdb())
+ will return when:
+ -# at least 'minNoOfEventsToWakeup' of the transactions
+ in the send list have transitioned to state 3 as described above, and
+ -# all of these transactions have executed their callback methods.
+*/
+#endif
+
+/**
+ @page secConcepts MySQL Cluster Concepts
+
+ The <em>NDB Kernel</em> is the collection of storage nodes
+ belonging to a MySQL Cluster.
+ The application programmer can for most purposes view the
+ set of all storage nodes as a single entity.
+ Each storage node is made up of three main components:
+ - TC : The transaction co-ordinator
+ - ACC : Index storage component
+ - TUP : Data storage component
+
+ When an application program executes a transaction,
+ it connects to one transaction co-ordinator on one storage node.
+ Usually, the programmer does not need to specify which TC should be used,
+ but in some cases when performance is important, the programmer can
+ provide "hints" to use a certain TC.
+ (If the node with the desired transaction co-ordinator is down, then another TC will
+ automatically take over the work.)
+
+ Every storage node has an ACC and a TUP which store
+ the indexes and data portions of the database table fragment.
+ Even though one TC is responsible for the transaction,
+ several ACCs and TUPs on other storage nodes might be involved in the
+ execution of the transaction.
+
+
+ @section secNdbKernelConnection Selecting a Transaction Co-ordinator
+
+ The default method is to select the transaction co-ordinator (TC) determined to be
+ the "closest" storage node, using a heuristic for proximity based on
+ the type of transporter connection. In order of closest to most distant, these are
+ - SCI
+ - SHM
+ - TCP/IP (localhost)
+ - TCP/IP (remote host)
+ If there are several connections available with the same proximity, they will each be
+ selected in a round robin fashion for every transaction. Optionally
+ one may set the method for TC selection to round-robin mode, where each new set of
+ transactions is placed on the next DB node. The pool of connections from which this
+ selection is made consists of all available connections.
+
+ As noted previously, the application programmer can provide hints to the NDB API as to
+ which transaction co-ordinator it should use. This is done by
+ providing a <em>table</em> and <em>partition key</em>
+ (usually the primary key).
+ By using the primary key as the partition key,
+ the transaction will be placed on the node where the primary replica
+ of that record resides.
+ Note that this is only a hint; the system can be
+ reconfigured at any time, in which case the NDB API will choose a transaction
+ co-ordinator without using the hint.
+ For more information, see NdbDictionary::Column::getPartitionKey() and
+ Ndb::startTransaction(). The application programmer can specify
+ the partition key from SQL by using the construct,
+ <code>CREATE TABLE ... ENGINE=NDB PARTITION BY KEY (<var>attribute-list</var>);</code>.
+
+
+ @section secRecordStruct NDB Record Structure
+ The NDB Cluster engine used by MySQL Cluster is a relational database engine
+ storing records in tables just as with any other RDBMS.
+ Table rows represent records as tuples of relational data.
+ When a new table is created, its attribute schema is specified for the table as a whole,
+ and thus each record of the table has the same structure. Again, this is typical
+ of relational databases, and NDB is no different in this regard.
+
+
+ @subsection secKeys Primary Keys
+ Each record has from 1 up to 32 attributes which belong
+ to the primary key of the table.
+
+ @section secTrans Transactions
+
+ Transactions are committed first to main memory,
+ and then to disk after a global checkpoint (GCP) is issued.
+ Since all data is (in most NDB Cluster configurations)
+ synchronously replicated and stored on multiple NDB nodes,
+ the system can still handle processor failures without loss
+ of data.
+ However, in the case of a system failure (e.g. the whole system goes down),
+ then all (committed or not) transactions occurring since the latest GCP are lost.
+
+
+ @subsection secConcur Concurrency Control
+ NDB Cluster uses pessimistic concurrency control based on locking.
+ If a requested lock (implicit and depending on database operation)
+ cannot be attained within a specified time,
+ then a timeout error occurs.
+
+ Concurrent transactions as requested by parallel application programs and
+ thread-based applications can sometimes deadlock when they try to access
+ the same information simultaneously.
+ Thus, applications need to be written in a manner so that timeout errors
+ occurring due to such deadlocks are handled gracefully. This generally
+ means that the transaction encountering a timeout should be rolled back
+ and restarted.
+
+
+ @section secHint Hints and Performance
+
+ Placing the transaction co-ordinator in close proximity
+ to the actual data used in the transaction can in many cases
+ improve performance significantly. This is particularly true for
+ systems using TCP/IP. For example, a Solaris system using a single 500 MHz processor
+ has a cost model for TCP/IP communication which can be represented by the formula
+
+ <code>[30 microseconds] + ([100 nanoseconds] * [<var>number of bytes</var>])</code>
+
+ This means that if we can ensure that we use "popular" links we increase
+ buffering and thus drastically reduce the communication cost.
+ The same system using SCI has a different cost model:
+
+ <code>[5 microseconds] + ([10 nanoseconds] * [<var>number of bytes</var>])</code>
+
+ Thus, the efficiency of an SCI system is much less dependent on selection of
+ transaction co-ordinators.
+ Typically, TCP/IP systems spend 30-60% of their working time on communication,
+ whereas for SCI systems this figure is closer to 5-10%.
+ Thus, employing SCI for data transport means that less care from the NDB API
+ programmer is required and greater scalability can be achieved, even for
+ applications using data from many different parts of the database.
+
+ A simple example is an application that uses many simple updates where
+ a transaction needs to update one record.
+ This record has a 32 bit primary key,
+ which is also the partition key.
+ Then the keyData will be the address of the integer
+ of the primary key and keyLen will be 4.
+*/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ (A transaction's execution can also be divided into three
+ steps: prepare, send, and poll. This allows us to perform asynchronous
+ transactions. More about this later.)
+*/
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ Another way to execute several parallel transactions is to use
+ asynchronous transactions.
+*/
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
+ Operations are of two different kinds:
+ -# standard operations, and
+ -# interpreted program operations.
+*/
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
<h3>Interpreted Program Operations</h3>
The following types of interpreted program operations exist:
-# NdbOperation::interpretedUpdateTuple :
updates a tuple using an interpreted program
-# NdbOperation::interpretedDeleteTuple :
delete a tuple using an interpreted program
- -# NdbOperation::openScanRead :
- scans a table with read lock on each tuple
- -# NdbOperation::openScanExclusive :
- scans a table with exclusive update lock on each tuple
The operations interpretedUpdateTuple and interpretedDeleteTuple both
work using the unique tuple key.
@@ -306,124 +761,10 @@
There might be zero NdbOperation::getValue calls.
-# The fifth step is possible subroutine definitions using
NdbOperation::def_subroutine and NdbOperation::ret_sub.
-
-
- @subsection secScan Scanning
- The most common use of interpreted programs is for scanning
- tables. Scanning is a search of all tuples in a table.
- Tuples which satisfy conditions (a search filter)
- stated in the interpreted program
- are sent to the application.
-
- Reasons for using scan transactions include
- need to use a search key different from the primary key
- and any secondary index.
- Or that the query needs to access so many tuples so that
- it is more efficient to scan the entire table.
-
- Scanning can also be used to update information.
- The scanning transaction itself is however
- not allowed to update any tuples.
- To do updates via scanning transactions, the tuples
- need to be handed over to another transaction which is
- executing the actual update.
-
- Even though a scan operation is part of a transaction,
- the scan transaction is not a normal transaction.
- The locks are <em>not</em> kept throughout the entire
- scan transaction, since this would imply non-optimal performance.
- <em>
- A transaction containing a scan operation can only
- contain that operation.
- No other operations are allowed in the same transaction.
- </em>
-
- The NdbOperation::openScanRead operation
- only sets a temporary read lock while
- reading the tuple.
- The tuple lock is released already when the
- result of the read reaches the application.
- The NdbOperation::openScanExclusive operation sets an
- exclusive lock on the tuple
- and sends the result to the application.
- Thus when the application reads the data it is still
- locked with the exclusive lock.
-
- If the application desires to update the tuple it may transfer
- the tuple to another transaction which updates the tuple.
- The updating transaction can consist of a combination of tuples
- received from the scan and normal operations.
-
- For transferred operations it is not necessary to provide the
- primary key. It is part of the transfer.
- You only need to give the operation type and the
- actions to perform on the tuple.
-
- The scan transaction starts like a usual transaction,
- but is of the following form:
- -# Start transaction
- -# Get NdbOperation for the table to be scanned
- -# Set the operation type using NdbOperation::openScanRead or
- NdbOperation::openScanExclusive
- -# Search conditions are defined by an interpreted program
- (setValue and write_attr are not allowed, since scan transactions
- are only allowed to read information).
- The instruction interpret_exit_nok does in this case
- not abort the transaction, it only skips the tuple and
- proceeds with the next.
- The skipped tuple will not be reported to the application.
- -# Call NdbConnection::executeScan to define (and start) the scan.
- -# Call NdbConnection::nextScanResult to proceed with next tuple.
- When calling NdbConnection::nextScanResult, the lock on any
- previous tuples are released.
- <br>
- If the tuple should be updated then it must be transferred over
- to another updating transaction.
- This is performed by calling
- NdbOperation::takeOverForUpdate or takeOverForDelete on
- the scanning transactions NdbOperation object with the updating
- transactions NdbConnection object as parameter.
- <p>
- If NdbOperation::takeOverFor* returns NULL then the
- operation was not successful, otherwise it returns a reference
- to the NdbOperation which the updating transaction has received
- -# Use Ndb::closeTransaction as usual to close the transaction.
- This can be performed even if there are more tuples to scan.
-
- See also example program in section @ref select_all.cpp.
-
- However, a new scan api is under development, using NdbScanOperation
- and NdbScanFilter. NdbScanFilter makes it easier to define a search
- criteria and is recommended instead of using Interpreted Programs.
-
- The scan transaction starts like a usual transaction,
- but is of the following form:
- -# Start transaction
- -# Get NdbScanOperation for the table to be scanned
- -# NdbScanOperation::readTuplesExclusive returns a handle to a
- NdbResultSet.
- -# Search conditions are defined by NdbScanFilter
- -# Call NdbConnection::execute(NoCommit) to start the scan.
- -# Call NdbResultSet::nextResult to proceed with next tuple.
- When calling NdbResultSet::nextResult(false), the lock on any
- previous tuples are released and the next tuple cached in the API
- is fetched.
- <br>
- If the tuple should be updated then define a new update operation
- (NdbOperation) using NdbResultSet::updateTuple().
- The new update operation can the be used to modify the tuple.
- When nextResult(false) returns != 0, then no more tuples
- are cached in the API. Updated tuples is now commit using
- NdbConnection::execute(Commit).
- After the commit, more tuples are fetched from NDB using
- nextResult(true).
- -# Use Ndb::closeTransaction as usual to close the transaction.
- This can be performed even if there are more tuples to scan.
-
- See the scan example program in @ref ndbapi_scan.cppn for example
- usage of the new scan api.
-
-
+*/
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
<h3>Interpreted Programs</h3>
Interpretation programs are executed in a
register-based virtual machine.
@@ -494,8 +835,11 @@
The parameter used by NdbOperation::def_subroutine
should match the automatic numbering to make it easier to
debug the interpreted program.
+*/
+#endif
-
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
@section secAsync Asynchronous Transactions
The asynchronous interface is used to increase the speed of
transaction executing by better utilizing the connection
@@ -508,7 +852,7 @@
chunks of data are sent when actually sending and thus decreasing
the operating system overhead.
- The synchronous call to NdbConnection::execute
+ The synchronous call to NdbTransaction::execute
normally performs three main steps:<br>
-# <b>Prepare</b>
Check transaction status
@@ -520,7 +864,7 @@
-# <b>Poll</b>
Wait for response from NDB kernel.
- The asynchronous method NdbConnection::executeAsynchPrepare
+ The asynchronous method NdbTransaction::executeAsynchPrepare
only perform step 1.
(The abort part in step 1 is only prepared for. The actual
aborting of the transaction is performed in a later step.)
@@ -531,11 +875,11 @@
synchronous transactions)
-# Add and define operations (also as in the synchronous case)
-# <b>Prepare</b> transactions
- (using NdbConnection::executeAsynchPrepare or
- NdbConnection::executeAsynch)
+ (using NdbTransaction::executeAsynchPrepare or
+ NdbTransaction::executeAsynch)
-# <b>Send</b> transactions to NDB Kernel
(using Ndb::sendPreparedTransactions,
- NdbConnection::executeAsynch, or Ndb::sendPollNdb)
+ NdbTransaction::executeAsynch, or Ndb::sendPollNdb)
-# <b>Poll</b> NDB kernel to find completed transactions
(using Ndb::pollNdb or Ndb::sendPollNdb)
-# Close transactions (same way as for the synchronous transactions)
@@ -546,24 +890,24 @@
- (Prepare-Send-Poll). This is the one-step variant provided
by synchronous transactions.
- (Prepare-Send)-Poll. This is the two-step variant using
- NdbConnection::executeAsynch and Ndb::pollNdb.
+ NdbTransaction::executeAsynch and Ndb::pollNdb.
- Prepare-(Send-Poll). This is the two-step variant using
- NdbConnection::executeAsynchPrepare and Ndb::sendPollNdb.
+ NdbTransaction::executeAsynchPrepare and Ndb::sendPollNdb.
- Prepare-Send-Poll. This is the three-step variant using
- NdbConnection::executeAsynchPrepare, Ndb::sendPreparedTransactions, and
+ NdbTransaction::executeAsynchPrepare, Ndb::sendPreparedTransactions, and
Ndb::pollNdb.
Transactions first has to be prepared by using method
- NdbConnection::executeAsynchPrepare or NdbConnection::executeAsynch.
+ NdbTransaction::executeAsynchPrepare or NdbTransaction::executeAsynch.
The difference between these is that
- NdbConnection::executeAsynch also sends the transaction to
+ NdbTransaction::executeAsynch also sends the transaction to
the NDB kernel.
One of the arguments to these methods is a callback method.
The callback method is executed during polling (item 5 above).
- Note that NdbConnection::executeAsynchPrepare does not
+ Note that NdbTransaction::executeAsynchPrepare does not
send the transaction to the NDB kernel. When using
- NdbConnection::executeAsynchPrepare, you either have to call
+ NdbTransaction::executeAsynchPrepare, you either have to call
Ndb::sendPreparedTransactions or Ndb::sendPollNdb to send the
database operations.
(Ndb::sendPollNdb also polls Ndb for completed transactions.)
@@ -583,276 +927,34 @@
The poll method returns the number of transactions that
have finished processing and executed their callback methods.
-
+
@note When an asynchronous transaction has been started and sent to
the NDB kernel, it is not allowed to execute any methods on
objects belonging to this transaction until the transaction
callback method have been executed.
(The transaction is stated and sent by either
- NdbConnection::executeAsynch or through the combination of
- NdbConnection::executeAsynchPrepare and either
+ NdbTransaction::executeAsynch or through the combination of
+ NdbTransaction::executeAsynchPrepare and either
Ndb::sendPreparedTransactions or Ndb::sendPollNdb).
- More about how transactions are send the NDB Kernel is
+ More about how transactions are sent the NDB Kernel is
available in section @ref secAdapt.
-
-
- @section secError Error Handling
-
- Errors can occur when
- -# operations are being defined, or when the
- -# transaction is being executed.
-
- One recommended way to handle a transaction failure
- (i.e. an error is reported) is to:
- -# Rollback transaction (NdbConnection::execute with a special parameter)
- -# Close transaction
- -# Restart transaction (if the error was temporary)
-
- @note Transaction are not automatically closed when an error occur.
-
- Several errors can occur when a transaction holds multiple
- operations which are simultaneously executed.
- In this case the application has to go through the operation
- objects and query for their NdbError objects to find out what really
- happened.
-
- NdbConnection::getNdbErrorOperation returns a reference to the
- operation causing the latest error.
- NdbConnection::getNdbErrorLine delivers the method number of the
- erroneous method in the operation.
-
- @code
- theConnection = theNdb->startTransaction();
- theOperation = theConnection->getNdbOperation("TEST_TABLE");
- if (theOperation == NULL) goto error;
- theOperation->readTuple();
- theOperation->setValue("ATTR_1", at1);
- theOperation->setValue("ATTR_2", at1); //Here an error occurs
- theOperation->setValue("ATTR_3", at1);
- theOperation->setValue("ATTR_4", at1);
-
- if (theConnection->execute(Commit) == -1) {
- errorLine = theConnection->getNdbErrorLine();
- errorOperation = theConnection->getNdbErrorOperation();
- @endcode
-
- Here errorLine will be 3 as the error occurred in the third method
- on the operation object.
- Getting errorLine == 0 means that the error occurred when executing the
- operations.
- Here errorOperation will be a pointer to the theOperation object.
- NdbConnection::getNdbError will return the NdbError object
- including holding information about the error.
-
- Since errors could have occurred even when a commit was reported,
- there is also a special method, NdbConnection::commitStatus,
- to check the commit status of the transaction.
-
-*******************************************************************************/
-
-/**
- * @page ndbapi_example1.cpp ndbapi_example1.cpp
- * @include ndbapi_example1.cpp
- */
-
-/**
- * @page ndbapi_example2.cpp ndbapi_example2.cpp
- * @include ndbapi_example2.cpp
- */
-
-/**
- * @page ndbapi_example3.cpp ndbapi_example3.cpp
- * @include ndbapi_example3.cpp
- */
-
-/**
- * @page ndbapi_example4.cpp ndbapi_example4.cpp
- * @include ndbapi_example4.cpp
- */
-
-/**
- * @page select_all.cpp select_all.cpp
- * @include select_all.cpp
- */
-
-/**
- * @page ndbapi_async.cpp ndbapi_async.cpp
- * @include ndbapi_async.cpp
- */
-
-/**
- * @page ndbapi_scan.cpp ndbapi_scan.cpp
- * @include ndbapi_scan.cpp
- */
-
-
-/**
- @page secAdapt Adaptive Send Algorithm
-
- At the time of "sending" the transaction
- (using NdbConnection::execute, NdbConnection::executeAsynch,
- Ndb::sendPreparedTransactions, or Ndb::sendPollNdb), the transactions
- are in reality <em>not</em> immediately transfered to the NDB Kernel.
- Instead, the "sent" transactions are only kept in a
- special send list (buffer) in the Ndb object to which they belong.
- The adaptive send algorithm decides when transactions should
- be transfered to the NDB kernel.
-
- For each of these "sent" transactions, there are three
- possible states:
- -# Waiting to be transfered to NDB Kernel.
- -# Has been transfered to the NDB Kernel and is currently
- being processed.
- -# Has been transfered to the NDB Kernel and has
- finished processing.
- Now it is waiting for a call to a poll method.
- (When the poll method is invoked,
- then the transaction callback method will be executed.)
-
- The poll method invoked (either Ndb::pollNdb or Ndb::sendPollNdb)
- will return when:
- -# at least 'minNoOfEventsToWakeup' of the transactions
- in the send list have transitioned to state 3 as described above, and
- -# all of these transactions have executed their callback methods.
-
-
- Since the NDB API is designed as a multi-threaded interface,
- it is desirable to transfer database operations from more than
- one thread at a time.
- The NDB API keeps track of which Ndb objects are active in transfering
- information to the NDB kernel and the expected amount of threads to
- interact with the NDB kernel.
- Note that an Ndb object should be used in at most one thread.
- Two different threads should <em>not</em> use the same Ndb object.
-
- There are four reasons leading to transfering of database
- operations:
- -# The NDB Transporter (TCP/IP, OSE, SCI or shared memory)
- decides that a buffer is full and sends it off.
- The buffer size is implementation dependent and
- might change between NDB Cluster releases.
- On TCP/IP the buffer size is usually around 64 kByte and
- on OSE/Delta it is usually less than 2000 bytes.
- In each Ndb object there is one buffer per DB node,
- so this criteria of a full buffer is only
- local to the connection to one DB node.
- -# Statistical information on the transfered information
- may force sending of buffers to all DB nodes.
- -# Every 10 ms a special send-thread checks whether
- any send activity has occurred. If not, then the thread will
- force sending to all nodes.
- This means that 20 ms is the maximum time database operations
- are waiting before being sent off. The 10 millisecond limit
- is likely to become a configuration parameter in
- later releases of NDB Cluster.
- However, to support faster than 10 ms checks,
- there has to be support from the operating system.
- -# When calling NdbConnection::execute synchronously or calling any
- of the poll-methods, there is a force parameter that overrides the
- adaptive algorithm and forces the send to all nodes.
-
- @note The times mentioned above are examples. These might
- change in later releases of NDB Cluster.
*/
-
-/**
- @page secConcepts NDB Cluster Concepts
-
- The <em>NDB Kernel</em> is the collection of database (DB) nodes
- belonging to an NDB Cluster.
- The application programmer can for most purposes view the
- set of all DB nodes as one entity.
- Each DB node has three main components:
- - TC : The transaction coordinator
- - ACC : The index storage
- - TUP : The data storage
-
- When the application program executes a transaction,
- it connects to one TC on one DB node.
- Usually, the programmer does not need to specify which TC to use,
- but some cases when performance is important,
- transactions can be hinted to use a certain TC.
- (If the node with the TC is down, then another TC will
- automatically take over the work.)
-
- Every DB node has an ACC and a TUP which stores
- the index and the data part of the database.
- Even though one TC is responsible for the transaction,
- several ACCs and TUPs on other DB nodes might be involved in the
- execution of the transaction.
-
-
- @section secNdbKernelConnection Selecting Transaction Coordinator
- The default method is round robin,
- where each new set of transactions
- is placed on the next DB node.
- The application chooses a TC for a number of transactions
- and then lets the next TC (on the next DB node) carry out
- the next set of transactions.
-
- The application programmer can however hint the NDB API which
- transaction coordinator to use
- by providing a <em>distribution key</em> (usually the primary key).
- By using the primary key as distribution key,
- the transaction will be placed on the node where the primary replica
- of that record resides.
- Note that this is only a hint, the system can be
- reconfigured and then the NDB API will choose a transaction
- coordinator without using the hint.
- For more information, see NdbDictionary::Column::setDistributionKey.
+#endif
- @section secRecordStruct Record Structure
- NDB Cluster is a relational database with tables of records.
- Table rows represent tuples of relational data stored as records.
- When created, the attribute schema of the table is specified,
- and thus each record of the table has the same schema.
+/**
-
- @subsection secKeys Tuple Keys
- Each record has from zero up to four attributes which belong
- to the primary key of the table.
- If no attribute belongs to the primary key, then
- the NDB Cluster creates an attribute named <em>NDB$TID</em>
- which stores a tuple identity.
- The <em>tuple key</em> of a table is thus either
- the primary key attributes or the special NDB$TID attribute.
-
+ Put this back when real array ops are supported
+ i.e. get/setValue("kalle[3]");
@subsection secArrays Array Attributes
- A table attribute in NDB Cluster can be of <em>array type</em>.
- This means that the attribute consists of an array of
- <em>elements</em>. The <em>attribute size</em> is the size
- of one element of the array (expressed in bits) and the
- <em>array size</em> is the number of elements of the array.
-
-
- @section secTrans Transactions
+ A table attribute in NDB Cluster can be of type <var>Array</var>,
+ meaning that the attribute consists of an ordered sequence of
+ elements. In such cases, <var>attribute size</var> is the size
+ (expressed in bits) of any one element making up the array; the
+ <var>array size</var> is the number of elements in the array.
- Transactions are committed to main memory,
- and are committed to disk after a global checkpoint, GCP.
- Since all data is (in most NDB Cluster configurations)
- synchronously replicated and stored on multiple NDB nodes,
- the system can still handle processor failures without loss
- of data.
- However, in the case of a system failure (e.g. the whole system goes down),
- then all (committed or not) transactions after the latest GCP are lost.
-
-
- @subsection secConcur Concurrency Control
- NDB Cluster uses pessimistic concurrency control based on locking.
- If a requested lock (implicit and depending on database operation)
- cannot be attained within a specified time,
- then a timeout error occurs.
-
- Concurrent transactions (parallel application programs, thread-based
- applications, or applications with asynchronous transactions)
- sometimes deadlock when they try to access the same information.
- Applications need to be programmed so that timeout errors
- occurring due to deadlocks are handled. This generally
- means that the transaction encountering timeout
- should be rolled back and restarted.
*/
#ifndef Ndb_H
@@ -870,7 +972,7 @@ class NdbEventOperationImpl;
class NdbScanOperation;
class NdbIndexScanOperation;
class NdbIndexOperation;
-class NdbConnection;
+class NdbTransaction;
class NdbApiSignal;
class NdbRecAttr;
class NdbLabel;
@@ -897,10 +999,6 @@ typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
#define WAITFOR_RESPONSE_TIMEOUT 120000 // Milliseconds
#endif
-#define NDB_MAX_INTERNAL_TABLE_LENGTH NDB_MAX_DATABASE_NAME_SIZE + \
- NDB_MAX_SCHEMA_NAME_SIZE + \
- NDB_MAX_TAB_NAME_SIZE*2
-
/**
* @class Ndb
* @brief Represents the NDB kernel and is the main class of the NDB API.
@@ -928,6 +1026,11 @@ typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
* Semaphores, mutexes and so forth are easy ways of issuing memory
* barriers without having to bother about the memory barrier concept.
*
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+// to be documented later
+/*
* If one Ndb object is used to handle parallel transactions through the
* asynchronous programming interface, please read the notes regarding
* asynchronous transactions (Section @ref secAsync).
@@ -938,12 +1041,15 @@ typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
* asynchronous transaction or the methods for
* synchronous transactions but not both.
*/
+#endif
+
class Ndb
{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbReceiver;
friend class NdbOperation;
friend class NdbEventOperationImpl;
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class Table;
friend class NdbApiSignal;
friend class NdbIndexOperation;
@@ -952,6 +1058,7 @@ class Ndb
friend class NdbDictionaryImpl;
friend class NdbDictInterface;
friend class NdbBlob;
+#endif
public:
/**
@@ -959,29 +1066,26 @@ public:
* @{
*/
/**
- * The starting point of your application code is to create an
- * Ndb object.
- * This object represents the NDB kernel and is the main
- * object used in interaction with the NDB kernel.
+ * The Ndb object represents a connection to a database.
*
- * @param aCatalogName is the name of the catalog you want to use.
- * @note The catalog name provides a name space for the tables and
+ * @note The init() method must be called before the Ndb object may actually be used.
+ *
+ * @param ndb_cluster_connection is a connection to the cluster containing
+ * the database to be used
+ * @param aCatalogName is the name of the catalog to be used.
+ * @note The catalog name provides a namespace for the tables and
* indexes created in any connection from the Ndb object.
* @param aSchemaName is the name of the schema you
- * want to use. It is optional and defaults to the "def" schema.
- * @note The schema name provides an additional name space
+ * want to use.
+ * @note The schema name provides an additional namespace
* for the tables and indexes created in a given catalog.
- * @note The methods get/setDatabaseName and get/setDatabaseSchemaName
- * are equivalent to get/setCatalogName and get/setSchemaName.
- * The get/setDatabaseName and get/setDatabaseSchemaName are
- * deprecated.
*/
- Ndb(const char* aCatalogName = "", const char* aSchemaName = "def");
Ndb(Ndb_cluster_connection *ndb_cluster_connection,
const char* aCatalogName = "", const char* aSchemaName = "def");
~Ndb();
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* The current catalog name can be fetched by getCatalogName.
*
@@ -1009,7 +1113,7 @@ public:
* @param aSchemaName is the new name of the current schema
*/
void setSchemaName(const char * aSchemaName);
-
+#endif
/**
* The current database name can be fetched by getDatabaseName.
@@ -1040,22 +1144,21 @@ public:
void setDatabaseSchemaName(const char * aDatabaseSchemaName);
/**
- * Before anything else it is necessary to initialize (start)
- * the Ndb object.
+ * Initializes the Ndb object
*
* @param maxNoOfTransactions
* Maximum number of parallel
- * NdbConnection objects that should be handled by the Ndb object.
- * A value larger than 1024 will be downgraded to 1024.
- * This means that one Ndb object can handle at most 1024 parallel
- * transactions.
- * @return 0 if successful, -1 otherwise.
+ * NdbTransaction objects that can be handled by the Ndb object.
+ * Maximum value is 1024.
+ *
+ * @note each scan or index scan operation uses one extra
+ * NdbTransaction object
*
- * @note The internal implementation multiplies this value
- * with 3.
+ * @return 0 if successful, -1 otherwise.
*/
int init(int maxNoOfTransactions = 4);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Wait for Ndb object to successfully set-up connections to
* the NDB kernel.
@@ -1068,8 +1171,8 @@ public:
* @return 0: Ndb is ready and timeout has not occurred.<br>
* -1: Timeout has expired
*/
-
int waitUntilReady(int timeout = 60);
+#endif
/** @} *********************************************************************/
@@ -1079,30 +1182,55 @@ public:
*/
/**
- * Query the database for schema information
- * (without performing any transaction).
+ * Get an object for retrieving or manipulating database schema information
+ *
+ * @note this object operates outside any transaction
*
* @return Object containing meta information about all tables
* in NDB Cluster.
*/
class NdbDictionary::Dictionary* getDictionary() const;
+
+ /** @} *********************************************************************/
+
+ /**
+ * @name Event subscriptions
+ * @{
+ */
+
+ /**
+ * Create a subcription to an event defined in the database
+ *
+ * @param eventName
+ * unique identifier of the event
+ * @param bufferLength
+ * circular buffer size for storing event data
+ *
+ * @return Object representing an event, NULL on failure
+ */
NdbEventOperation* createEventOperation(const char* eventName,
const int bufferLength);
- int dropEventOperation(NdbEventOperation*);
- void monitorEvent(NdbEventOperation *, NdbEventCallback, void*);
- int pollEvents(int aMillisecondNumber);
+ /**
+ * Drop a subscription to an event
+ *
+ * @param eventOp
+ * Event operation
+ *
+ * @return 0 on success
+ */
+ int dropEventOperation(NdbEventOperation* eventOp);
/**
- * Get the application node identity.
+ * Wait for an event to occur. Will return as soon as an event
+ * is detected on any of the created events.
*
- * Each node (DB nodes, Applications, and Management Servers)
- * has its own node identity in the NDB Cluster.
- * See documentation for the management server configuration file.
+ * @param aMillisecondNumber
+ * maximum time to wait
*
- * @return Node id of this application.
+ * @return the number of events that has occured, -1 on failure
*/
- int getNodeId();
+ int pollEvents(int aMillisecondNumber);
/** @} *********************************************************************/
@@ -1112,79 +1240,33 @@ public:
*/
/**
- * This method returns an NdbConnection which caters for the transaction.
- * When the transaction is completed it must be closed.
- * The Ndb::closeTransaction also return the NdbConnection object
- * and all other memory related to the transaction.
- * Failure to close the transaction will lead to memory leakage.
- * The transaction must be closed independent of its outcome, i.e.
- * even if there is an error.
- *
- * NDB API can be hinted to select a particular transaction coordinator.
- * The default method is round robin where each set of new transactions
- * is placed on the next NDB kernel node.
- * By providing a distribution key (usually the primary key
- * of the mostly used table of the transaction) for a record
- * the transaction will be placed on the node where the primary replica
- * of that record resides.
- * Note that this is only a hint, the system can
- * be under reconfiguration and then the NDB API
- * will use select the transaction coordinator without using
- * this hint.
- *
- * Placing the transaction coordinator close
- * to the actual data used in the transaction can in many cases
- * improve performance significantly. This is particularly true for
- * systems using TCP/IP. A system using Solaris and a 500 MHz processor
- * has a cost model for TCP/IP communication which is:
- *
- * 30 microseconds + (100 nanoseconds * no of Bytes)
- *
- * This means that if we can ensure that we use "popular" links we increase
- * buffering and thus drastically reduce the communication cost.
- * Systems using SCI has a different cost model which is:
+ * Start a transaction
*
- * 5 microseconds + (10 nanoseconds * no of Bytes)
+ * @note When the transaction is completed it must be closed using
+ * Ndb::closeTransaction or NdbTransaction::close.
+ * The transaction must be closed independent of its outcome, i.e.
+ * even if there is an error.
*
- * Thus SCI systems are much less dependent on selection of
- * transaction coordinators.
- * Typically TCP/IP systems spend 30-60% of the time during communication,
- * whereas SCI systems typically spend 5-10% of the time during
- * communication.
- * Thus SCI means that less care from the NDB API programmer is
- * needed and great scalability can be achieved even for applications using
- * data from many parts of the database.
- *
- * A simple example is an application that uses many simple updates where
- * a transaction needs to update one record.
- * This record has a 32 bit primary key,
- * which is also the distribution key.
- * Then the keyData will be the address of the integer
- * of the primary key and keyLen will be 4.
- *
- * @note Transaction priorities are not yet supported.
- *
- * @param prio The priority of the transaction.<br>
- * Priority 0 is the highest priority and is used
- * for short transactions with requirements on low delay.<br>
- * Priority 1 is a medium priority for short transactions.
- * <br>
- * Priority 2 is a medium priority for long transactions.<br>
- * Priority 3 is a low priority for long transactions.<br>
- * <em>This parameter is not currently used,
- * and can be set to any value</em>
- * @param keyData Pointer to distribution key
- * @param keyLen Length of distribution key expressed in bytes
+ * @param table Pointer to table object used for deciding
+ * which node to run the Transaction Coordinator on
+ * @param keyData Pointer to partition key corresponding to
+ * <var>table</var>
+ * @param keyLen Length of partition key expressed in bytes
*
- * @return NdbConnection object, or NULL if method failed.
+ * @return NdbTransaction object, or NULL on failure.
*/
- NdbConnection* startTransaction(Uint32 prio = 0,
- const char * keyData = 0,
- Uint32 keyLen = 0);
+ NdbTransaction* startTransaction(const NdbDictionary::Table *table= 0,
+ const char *keyData = 0,
+ Uint32 keyLen = 0);
/**
- * When a transactions is completed, the transaction has to be closed.
+ * Close a transaction.
*
+ * @note should be called after the transaction has completed, irrespective
+ * of success or failure
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
* @note It is not allowed to call Ndb::closeTransaction after sending the
* transaction asynchronously with either
* Ndb::sendPreparedTransactions or
@@ -1194,11 +1276,13 @@ public:
* has completed before calling Ndb::closeTransaction).
* If the transaction is not committed it will be aborted.
*/
- void closeTransaction(NdbConnection* aConnection);
-
+#endif
+ void closeTransaction(NdbTransaction*);
/** @} *********************************************************************/
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ // to be documented later
/**
* @name Asynchronous Transactions
* @{
@@ -1209,11 +1293,10 @@ public:
* Will return as soon as at least 'minNoOfEventsToWakeUp'
* of them have completed, or the maximum time given as timeout has passed.
*
- * @param aMillisecondNumber Maximum time to wait for transactions
- * to complete.
- * Polling without wait is achieved by setting the
- * timer to zero.
- * Time is expressed in milliseconds.
+ * @param aMillisecondNumber
+ * Maximum time to wait for transactions to complete. Polling
+ * without wait is achieved by setting the timer to zero.
+ * Time is expressed in milliseconds.
* @param minNoOfEventsToWakeup Minimum number of transactions
* which has to wake up before the poll-call will return.
* If minNoOfEventsToWakeup is
@@ -1275,9 +1358,9 @@ public:
int sendPollNdb(int aMillisecondNumber = WAITFOR_RESPONSE_TIMEOUT,
int minNoOfEventsToWakeup = 1,
int forceSend = 0);
-
/** @} *********************************************************************/
-
+#endif
+
/**
* @name Error Handling
* @{
@@ -1286,7 +1369,7 @@ public:
/**
* Get the NdbError object
*
- * The NdbError object is valid until you call a new NDB API method.
+ * @note The NdbError object is valid until a new NDB API method is called.
*/
const NdbError & getNdbError() const;
@@ -1298,37 +1381,29 @@ public:
const NdbError & getNdbError(int errorCode);
+ /** @} *********************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
- * setConnectString
- * @param connectString - the connectString has the following format:
- * @code
- * "nodeid=<ID>;host=host://<HOSTNAME>:<PORT>;
- * host=host://<HOSTNAME2>:<PORT>;..."
- * @endcode
- * or
- * @code
- * "nodeid=<ID>;host=<HOSTNAME>:<PORT>;host=<HOSTNAME2>:<PORT>;..."
- * @endcode
+ * Get the application node identity.
+ *
+ * @return Node id of this application.
*/
- static void setConnectString(const char * connectString);
+ int getNodeId();
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)
+ 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)
};
/**
@@ -1347,9 +1422,7 @@ public:
* on type of tampering.
*/
int NdbTamper(TamperType aAction, int aNode);
-#endif
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Return a unique tuple id for a table. The id sequence is
* ascending but may contain gaps.
@@ -1379,12 +1452,10 @@ public:
bool increase);
bool setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase);
Uint64 opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op);
-#endif
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
*/
- NdbConnection* hupp( NdbConnection* );
+ NdbTransaction* hupp( NdbTransaction* );
Uint32 getReference() const { return theMyRef;}
#endif
@@ -1399,11 +1470,11 @@ private:
void connected(Uint32 block_reference);
- NdbConnection* startTransactionLocal(Uint32 aPrio, Uint32 aFragmentId);
+ NdbTransaction* startTransactionLocal(Uint32 aPrio, Uint32 aFragmentId);
// Connect the connection object to the Database.
int NDB_connect(Uint32 tNode);
- NdbConnection* doConnect(Uint32 nodeId);
+ NdbTransaction* doConnect(Uint32 nodeId);
void doDisconnect();
NdbReceiver* getNdbScanRec();// Get a NdbScanReceiver from idle list
@@ -1435,8 +1506,8 @@ private:
void check_send_timeout();
void remove_sent_list(Uint32);
- Uint32 insert_completed_list(NdbConnection*);
- Uint32 insert_sent_list(NdbConnection*);
+ Uint32 insert_completed_list(NdbTransaction*);
+ Uint32 insert_sent_list(NdbTransaction*);
// Handle a received signal. Used by both
// synchronous and asynchronous interface
@@ -1476,20 +1547,20 @@ private:
void freeNdbScanRec(); // Free the first idle NdbScanRec obj
void freeNdbBlob(); // Free the first etc
- NdbConnection* getNdbCon(); // Get a connection from idle list
+ NdbTransaction* getNdbCon(); // Get a connection from idle list
/**
- * Get a connected NdbConnection to nodeId
+ * Get a connected NdbTransaction to nodeId
* Returns NULL if none found
*/
- NdbConnection* getConnectedNdbConnection(Uint32 nodeId);
+ NdbTransaction* getConnectedNdbTransaction(Uint32 nodeId);
// Release and disconnect from DBTC a connection
// and seize it to theConIdleList
- void releaseConnectToNdb (NdbConnection* aConnectConnection);
+ void releaseConnectToNdb (NdbTransaction*);
// Release a connection to idle list
- void releaseNdbCon (NdbConnection* aConnection);
+ void releaseNdbCon (NdbTransaction*);
int checkInitState(); // Check that we are initialized
void report_node_failure(Uint32 node_id); // Report Failed node
@@ -1499,28 +1570,30 @@ private:
int NDB_connect(); // Perform connect towards NDB Kernel
- // Release arrays of NdbConnection pointers
+ // Release arrays of NdbTransaction pointers
void releaseTransactionArrays();
- Uint32 pollCompleted(NdbConnection** aCopyArray);
+ Uint32 pollCompleted(NdbTransaction** aCopyArray);
void sendPrepTrans(int forceSend);
- void reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfComplTrans);
+ void reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfComplTrans);
void waitCompletedTransactions(int milliSecs, int noOfEventsToWaitFor);
- void completedTransaction(NdbConnection* aTransaction);
- void completedScanTransaction(NdbConnection* aTransaction);
+ void completedTransaction(NdbTransaction* aTransaction);
+ void completedScanTransaction(NdbTransaction* aTransaction);
void abortTransactionsAfterNodeFailure(Uint16 aNodeId);
static
- const char * externalizeTableName(const char * internalTableName, bool fullyQualifiedNames);
+ const char * externalizeTableName(const char * internalTableName,
+ bool fullyQualifiedNames);
const char * externalizeTableName(const char * internalTableName);
- const char * internalizeTableName(const char * externalTableName);
+ const BaseString internalize_table_name(const char * external_name) const;
static
- const char * externalizeIndexName(const char * internalIndexName, bool fullyQualifiedNames);
+ const char * externalizeIndexName(const char * internalIndexName,
+ bool fullyQualifiedNames);
const char * externalizeIndexName(const char * internalIndexName);
- const char * internalizeIndexName(const NdbTableImpl * table,
- const char * externalIndexName);
+ const BaseString internalize_index_name(const NdbTableImpl * table,
+ const char * external_name) const;
static
const BaseString getDatabaseFromInternalName(const char * internalName);
@@ -1529,21 +1602,21 @@ private:
void* int2void (Uint32 val);
NdbReceiver* void2rec (void* val);
- NdbConnection* void2con (void* val);
+ NdbTransaction* void2con (void* val);
NdbOperation* void2rec_op (void* val);
NdbIndexOperation* void2rec_iop (void* val);
/******************************************************************************
* These are the private variables in this class.
*****************************************************************************/
- NdbConnection** thePreparedTransactionsArray;
- NdbConnection** theSentTransactionsArray;
- NdbConnection** theCompletedTransactionsArray;
+ NdbTransaction** thePreparedTransactionsArray;
+ NdbTransaction** theSentTransactionsArray;
+ NdbTransaction** theCompletedTransactionsArray;
Uint32 theNoOfPreparedTransactions;
Uint32 theNoOfSentTransactions;
Uint32 theNoOfCompletedTransactions;
- Uint32 theNoOfAllocatedTransactions;
+ Uint32 theRemainingStartTransactions;
Uint32 theMaxNoOfTransactions;
Uint32 theMinNoOfEventsToWakeUp;
@@ -1551,32 +1624,27 @@ private:
bool fullyQualifiedNames;
- // Ndb database name.
- char theDataBase[NDB_MAX_DATABASE_NAME_SIZE];
- // Ndb database schema name.
- char theDataBaseSchema[NDB_MAX_SCHEMA_NAME_SIZE];
- char prefixName[NDB_MAX_INTERNAL_TABLE_LENGTH];
- char * prefixEnd;
+
class NdbImpl * theImpl;
class NdbDictionaryImpl* theDictionary;
class NdbGlobalEventBufferHandle* theGlobalEventBufferHandle;
- NdbConnection* theConIdleList; // First connection in idle list.
+ NdbTransaction* theConIdleList; // First connection in idle list.
NdbOperation* theOpIdleList; // First operation in the idle list.
NdbIndexScanOperation* theScanOpIdleList; // First scan operation in the idle list.
NdbIndexOperation* theIndexOpIdleList; // First index operation in the idle list.
- NdbConnection* theTransactionList;
- NdbConnection** theConnectionArray;
+ NdbTransaction* theTransactionList;
+ NdbTransaction** theConnectionArray;
NdbRecAttr* theRecAttrIdleList;
NdbApiSignal* theSignalIdleList; // First signal in idlelist.
NdbLabel* theLabelList; // First label descriptor in list
NdbBranch* theBranchList; // First branch descriptor in list
NdbSubroutine* theSubroutineList; // First subroutine descriptor in
NdbCall* theCallList; // First call descriptor in list
- NdbReceiver* theScanList;
+ NdbReceiver* theScanList;
NdbBlob* theNdbBlobIdleList;
Uint32 theMyRef; // My block reference
diff --git a/ndb/include/ndbapi/NdbApi.hpp b/ndb/include/ndbapi/NdbApi.hpp
index ae7025f560a..aed4d5efbd7 100644
--- a/ndb/include/ndbapi/NdbApi.hpp
+++ b/ndb/include/ndbapi/NdbApi.hpp
@@ -21,14 +21,13 @@
#include "ndb_cluster_connection.hpp"
#include "ndbapi_limits.h"
#include "Ndb.hpp"
-#include "NdbConnection.hpp"
+#include "NdbTransaction.hpp"
#include "NdbOperation.hpp"
#include "NdbScanOperation.hpp"
#include "NdbIndexOperation.hpp"
#include "NdbIndexScanOperation.hpp"
#include "NdbScanFilter.hpp"
#include "NdbRecAttr.hpp"
-#include "NdbResultSet.hpp"
#include "NdbDictionary.hpp"
#include "NdbEventOperation.hpp"
#include "NdbPool.hpp"
diff --git a/ndb/include/ndbapi/NdbBlob.hpp b/ndb/include/ndbapi/NdbBlob.hpp
index b145c69b04b..271287b765c 100644
--- a/ndb/include/ndbapi/NdbBlob.hpp
+++ b/ndb/include/ndbapi/NdbBlob.hpp
@@ -19,11 +19,11 @@
#include <ndb_types.h>
#include <NdbDictionary.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbError.hpp>
class Ndb;
-class NdbConnection;
+class NdbTransaction;
class NdbOperation;
class NdbRecAttr;
class NdbTableImpl;
@@ -67,7 +67,7 @@ class NdbColumnImpl;
* cases NdbBlob is forced to do implicit executes. To avoid this,
* operate on complete blob parts.
*
- * Use NdbConnection::executePendingBlobOps to flush your reads and
+ * Use NdbTransaction::executePendingBlobOps to flush your reads and
* writes. It avoids execute penalty if nothing is pending. It is not
* needed after execute (obviously) or after next scan result.
*
@@ -88,8 +88,13 @@ class NdbColumnImpl;
* - lock mode vs allowed operation is not checked
* - too many pending blob ops can blow up i/o buffers
* - table and its blob part tables are not created atomically
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+/**
* - there is no support for an asynchronous interface
*/
+#endif
+
class NdbBlob {
public:
/**
@@ -102,6 +107,9 @@ public:
Closed = 3,
Invalid = 9
};
+ /**
+ * Get the state of a NdbBlob object.
+ */
State getState();
/**
* Inline blob header.
@@ -111,7 +119,7 @@ public:
};
/**
* Prepare to read blob value. The value is available after execute.
- * Use getNull to check for NULL and getLength to get the real length
+ * Use getNull() 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.
*/
@@ -124,10 +132,10 @@ public:
*/
int setValue(const void* data, Uint32 bytes);
/**
- * Callback for setActiveHook. Invoked immediately when the prepared
- * operation has been executed (but not committed). Any getValue or
- * setValue is done first. The blob handle is active so readData or
- * writeData etc can be used to manipulate blob value. A user-defined
+ * Callback for setActiveHook(). Invoked immediately when the prepared
+ * operation has been executed (but not committed). Any getValue() or
+ * setValue() is done first. The blob handle is active so readData or
+ * writeData() etc can be used to manipulate blob value. A user-defined
* argument is passed along. Returns non-zero on error.
*/
typedef int ActiveHook(NdbBlob* me, void* arg);
@@ -190,19 +198,26 @@ public:
const NdbError& getNdbError() const;
/**
* Return info about all blobs in this operation.
+ *
+ * Get first blob in list.
*/
- // Get first blob in list
NdbBlob* blobsFirstBlob();
- // Get next blob in list after this one
+ /**
+ * Return info about all blobs in this operation.
+ *
+ * Get next blob in list. Initialize with blobsFirstBlob().
+ */
NdbBlob* blobsNextBlob();
private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class NdbOperation;
friend class NdbScanOperation;
friend class NdbDictionaryImpl;
friend class NdbResultSet; // atNextResult
+#endif
// state
State theState;
void setState(State newState);
@@ -211,7 +226,7 @@ private:
static void getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c);
// ndb api stuff
Ndb* theNdb;
- NdbConnection* theNdbCon;
+ NdbTransaction* theNdbCon;
NdbOperation* theNdbOp;
const NdbTableImpl* theTable;
const NdbTableImpl* theAccessTable;
@@ -301,15 +316,15 @@ private:
// callbacks
int invokeActiveHook();
// blob handle maintenance
- int atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn);
- int preExecute(ExecType anExecType, bool& batch);
- int postExecute(ExecType anExecType);
+ int atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn);
+ int preExecute(NdbTransaction::ExecType anExecType, bool& batch);
+ int postExecute(NdbTransaction::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);
+ void setErrorCode(NdbTransaction* aCon, bool invalidFlag = true);
#ifdef VM_TRACE
int getOperationType() const;
friend class NdbOut& operator<<(NdbOut&, const NdbBlob&);
diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp
index a541cd5190e..69ce6616ca1 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -14,18 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbDictionary.hpp
- * Include:
- * Link:
- * Author: Jonas Oreland
- * Date: 2003-05-14
- * Version: 0.1
- * Description: Data dictionary support
- * Documentation:
- * Adjust: 2003-05-14 Jonas Oreland First version.
- ****************************************************************************/
-
#ifndef NdbDictionary_H
#define NdbDictionary_H
@@ -39,11 +27,17 @@ typedef struct charset_info_st CHARSET_INFO;
* @class NdbDictionary
* @brief Data dictionary class
*
- * This class supports all schema data definition and enquiry such as:
- * -# Creating tables (Dictionary::createTable) and table columns
- * -# Dropping tables (Dictionary::dropTable)
- * -# Creating secondary indexes (Dictionary::createIndex)
- * -# Dropping secondary indexes (Dictionary::dropIndex)
+ * The preferred and supported way to create and drop tables and indexes
+ * in ndb is through the
+ * MySQL Server (see MySQL reference Manual, section MySQL Cluster).
+ *
+ * Tables and indexes that are created directly through the
+ * NdbDictionary class
+ * can not be viewed from the MySQL Server.
+ * Dropping indexes directly via the NdbApi will cause inconsistencies
+ * if they were originally created from a MySQL Cluster.
+ *
+ * This class supports schema data enquiries such as:
* -# Enquiries about tables
* (Dictionary::getTable, Table::getNoOfColumns,
* Table::getPrimaryKey, and Table::getNoOfPrimaryKeys)
@@ -51,12 +45,19 @@ typedef struct charset_info_st CHARSET_INFO;
* (Dictionary::getIndex, Index::getNoOfColumns,
* and Index::getColumn)
*
- * NdbDictionary has several help (inner) classes:
+ * This class supports schema data definition such as:
+ * -# Creating tables (Dictionary::createTable) and table columns
+ * -# Dropping tables (Dictionary::dropTable)
+ * -# Creating secondary indexes (Dictionary::createIndex)
+ * -# Dropping secondary indexes (Dictionary::dropIndex)
+ *
+ * NdbDictionary has several help (inner) classes to support this:
+ * -# NdbDictionary::Dictionary the dictionary handling dictionary objects
* -# NdbDictionary::Table for creating tables
* -# NdbDictionary::Column for creating table columns
* -# NdbDictionary::Index for creating secondary indexes
- *
- * See @ref ndbapi_example4.cpp for details of usage.
+ *
+ * See @ref ndbapi_simple_index.cpp for details of usage.
*/
class NdbDictionary {
public:
@@ -101,8 +102,6 @@ public:
SystemTable = 1, ///< System table
UserTable = 2, ///< User table (may be temporary)
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
HashIndexTrigger = 7, ///< Index maintenance, internal
IndexTrigger = 8, ///< Index maintenance, internal
@@ -156,14 +155,20 @@ public:
/**
* @class Column
- * @brief Represents an column in an NDB Cluster table
+ * @brief Represents a column in an NDB Cluster table
*
- * Each column has a type. The type of a column is determind by a number
+ * Each column has a type. The type of a column is determined by a number
* of type specifiers.
* The type specifiers are:
* - Builtin type
* - Array length or max length
- * - Precision and scale
+ * - Precision and scale (not used yet)
+ * - Character set for string types
+ * - Inline and part sizes for blobs
+ *
+ * Types in general correspond to MySQL types and their variants.
+ * Data formats are same as in MySQL. NDB API provides no support for
+ * constructing such formats. NDB kernel checks them however.
*/
class Column {
public:
@@ -171,78 +176,56 @@ public:
* The builtin column types
*/
enum Type {
- Undefined=0,///< Undefined
- Tinyint, ///< 8 bit. 1 byte signed integer, can be used in array
- Tinyunsigned, ///< 8 bit. 1 byte unsigned integer, can be used in array
- Smallint, ///< 16 bit. 2 byte signed integer, can be used in array
- Smallunsigned, ///< 16 bit. 2 byte unsigned integer, can be used in array
- Mediumint, ///< 24 bit. 3 byte signed integer, can be used in array
- Mediumunsigned,///< 24 bit. 3 byte unsigned integer, can be used in array
- Int, ///< 32 bit. 4 byte signed integer, can be used in array
- Unsigned, ///< 32 bit. 4 byte unsigned integer, can be used in array
- Bigint, ///< 64 bit. 8 byte signed integer, can be used in array
- Bigunsigned, ///< 64 Bit. 8 byte signed integer, can be used in array
- Float, ///< 32-bit float. 4 bytes float, can be used in array
- Double, ///< 64-bit float. 8 byte float, can be used in array
- Olddecimal, ///< MySQL < 5.0 signed decimal, Precision, Scale
- Char, ///< Len. A fixed array of 1-byte chars
- Varchar, ///< Max len
- Binary, ///< Len
- Varbinary, ///< Max len
- Datetime, ///< Precision down to 1 sec (sizeof(Datetime) == 8 bytes )
- Date, ///< Precision down to 1 day(sizeof(Date) == 4 bytes )
- Blob, ///< Binary large object (see NdbBlob)
- Text, ///< Text blob
- Time = 25, ///< Time without date
- Year = 26, ///< Year 1901-2155 (1 byte)
- Timestamp = 27, ///< Unix time
- Olddecimalunsigned = 28
+ Undefined = NDB_TYPE_UNDEFINED, ///< Undefined
+ Tinyint = NDB_TYPE_TINYINT, ///< 8 bit. 1 byte signed integer, can be used in array
+ Tinyunsigned = NDB_TYPE_TINYUNSIGNED, ///< 8 bit. 1 byte unsigned integer, can be used in array
+ Smallint = NDB_TYPE_SMALLINT, ///< 16 bit. 2 byte signed integer, can be used in array
+ Smallunsigned = NDB_TYPE_SMALLUNSIGNED, ///< 16 bit. 2 byte unsigned integer, can be used in array
+ Mediumint = NDB_TYPE_MEDIUMINT, ///< 24 bit. 3 byte signed integer, can be used in array
+ Mediumunsigned = NDB_TYPE_MEDIUMUNSIGNED,///< 24 bit. 3 byte unsigned integer, can be used in array
+ Int = NDB_TYPE_INT, ///< 32 bit. 4 byte signed integer, can be used in array
+ Unsigned = NDB_TYPE_UNSIGNED, ///< 32 bit. 4 byte unsigned integer, can be used in array
+ Bigint = NDB_TYPE_BIGINT, ///< 64 bit. 8 byte signed integer, can be used in array
+ Bigunsigned = NDB_TYPE_BIGUNSIGNED, ///< 64 Bit. 8 byte signed integer, can be used in array
+ Float = NDB_TYPE_FLOAT, ///< 32-bit float. 4 bytes float, can be used in array
+ Double = NDB_TYPE_DOUBLE, ///< 64-bit float. 8 byte float, can be used in array
+ Olddecimal = NDB_TYPE_OLDDECIMAL, ///< MySQL < 5.0 signed decimal, Precision, Scale
+ Olddecimalunsigned = NDB_TYPE_OLDDECIMALUNSIGNED,
+ Decimal = NDB_TYPE_DECIMAL, ///< MySQL >= 5.0 signed decimal, Precision, Scale
+ Decimalunsigned = NDB_TYPE_DECIMALUNSIGNED,
+ Char = NDB_TYPE_CHAR, ///< Len. A fixed array of 1-byte chars
+ Varchar = NDB_TYPE_VARCHAR, ///< Length bytes: 1, Max: 255
+ Binary = NDB_TYPE_BINARY, ///< Len
+ Varbinary = NDB_TYPE_VARBINARY, ///< Length bytes: 1, Max: 255
+ Datetime = NDB_TYPE_DATETIME, ///< Precision down to 1 sec (sizeof(Datetime) == 8 bytes )
+ Date = NDB_TYPE_DATE, ///< Precision down to 1 day(sizeof(Date) == 4 bytes )
+ Blob = NDB_TYPE_BLOB, ///< Binary large object (see NdbBlob)
+ Text = NDB_TYPE_TEXT, ///< Text blob
+ Bit = NDB_TYPE_BIT, ///< Bit, length specifies no of bits
+ Longvarchar = NDB_TYPE_LONGVARCHAR, ///< Length bytes: 2, little-endian
+ Longvarbinary = NDB_TYPE_LONGVARBINARY, ///< Length bytes: 2, little-endian
+ Time = NDB_TYPE_TIME, ///< Time without date
+ Year = NDB_TYPE_YEAR, ///< Year 1901-2155 (1 byte)
+ Timestamp = NDB_TYPE_TIMESTAMP ///< Unix time
};
/**
* @name General
* @{
*/
- /**
- * Constructor
- * @param name Name of column
- */
- Column(const char * name = "");
- /**
- * Copy constructor
- * @param column Column to be copied
- */
- Column(const Column& column);
- ~Column();
/**
- * Set name of column
- * @param name Name of the column
- */
- void setName(const char * name);
-
- /**
* Get name of column
* @return Name of the column
*/
const char* getName() const;
/**
- * Set whether column is nullable or not
- */
- void setNullable(bool);
-
- /**
* Get if the column is nullable or not
*/
bool getNullable() const;
/**
- * Set that column is part of primary key
- */
- void setPrimaryKey(bool);
-
- /**
* Check if column is part of primary key
*/
bool getPrimaryKey() const;
@@ -259,92 +242,62 @@ public:
*/
bool equal(const Column& column) const;
+
/** @} *******************************************************************/
/**
- * @name Type Specifiers
+ * @name Get Type Specifiers
* @{
*/
/**
- * Set type of column
- * @param type Type of column
- *
- * @note setType resets <em>all</em> column attributes
- * to (type dependent) defaults and should be the first
- * method to call. Default type is Unsigned.
- */
- void setType(Type type);
-
- /**
* Get type of column
*/
Type getType() const;
/**
- * Set precision of column.
- * @note Only applicable for decimal types
- */
- void setPrecision(int);
-
- /**
* Get precision of column.
* @note Only applicable for decimal types
*/
int getPrecision() const;
/**
- * Set scale of column.
- * @note Only applicable for decimal types
- */
- void setScale(int);
-
- /**
* Get scale of column.
* @note Only applicable for decimal types
*/
int getScale() const;
/**
- * Set length for column
- * Array length for column or max length for variable length arrays.
- */
- void setLength(int length);
-
- /**
* Get length for column
* Array length for column or max length for variable length arrays.
*/
int getLength() const;
/**
- * For Char or Varchar or Text, set or get MySQL CHARSET_INFO. This
+ * For Char or Varchar or Text, get MySQL CHARSET_INFO. This
* specifies both character set and collation. See get_charset()
* etc in MySQL. (The cs is not "const" in MySQL).
*/
- void setCharset(CHARSET_INFO* cs);
CHARSET_INFO* getCharset() const;
+
/**
- * For blob, set or get "inline size" i.e. number of initial bytes
+ * For blob, 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);
int getInlineSize() const;
/**
- * For blob, set or get "part size" i.e. number of bytes to store in
+ * For blob, get "part size" i.e. number of bytes to store in
* each tuple of the "blob table". Can be set to zero to omit parts
* and to allow only inline bytes ("tinyblob").
*/
- void setPartSize(int size);
int getPartSize() const;
/**
* 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);
int getStripeSize() const;
/**
@@ -353,64 +306,162 @@ public:
int getSize() const;
/**
- * Set distribution key
+ * Check if column is part of partition key
*
- * A <em>distribution key</em> is a set of attributes which are used
+ * A <em>partition key</em> is a set of attributes which are used
* to distribute the tuples onto the NDB nodes.
- * The distribution key uses the NDB Cluster hashing function.
+ * The partition key uses the NDB Cluster hashing function.
*
* An example where this is useful is TPC-C where it might be
- * good to use the warehouse id and district id as the distribution key.
+ * good to use the warehouse id and district id as the partition key.
* This would place all data for a specific district and warehouse
* in the same database node.
*
* Locally in the fragments the full primary key
* will still be used with the hashing algorithm.
*
- * @param enable If set to true, then the column will be part of
- * the distribution key.
+ * @return true then the column is part of
+ * the partition key.
+ */
+ bool getPartitionKey() const;
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ inline bool getDistributionKey() const { return getPartitionKey(); };
+#endif
+
+ /** @} *******************************************************************/
+
+
+ /**
+ * @name Column creation
+ * @{
+ *
+ * These operations should normally not be performed in an NbdApi program
+ * as results will not be visable in the MySQL Server
+ *
*/
- void setDistributionKey(bool enable);
/**
- * Check if column is part of distribution key
- * @see setDistributionKey
+ * Constructor
+ * @param name Name of column
*/
- bool getDistributionKey() const;
- /** @} *******************************************************************/
+ Column(const char * name = "");
+ /**
+ * Copy constructor
+ * @param column Column to be copied
+ */
+ Column(const Column& column);
+ ~Column();
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
- void setTupleKey(bool);
- bool getTupleKey() const;
-
- void setDistributionGroup(bool, int bits = 16);
- bool getDistributionGroup() const;
- int getDistributionGroupBits() const;
-
- void setIndexOnlyStorage(bool);
- bool getIndexOnlyStorage() const;
+ /**
+ * Set name of column
+ * @param name Name of the column
+ */
+ void setName(const char * name);
- const Table * getBlobTable() const;
+ /**
+ * Set whether column is nullable or not
+ */
+ void setNullable(bool);
+
+ /**
+ * Set that column is part of primary key
+ */
+ void setPrimaryKey(bool);
+
+ /**
+ * Set type of column
+ * @param type Type of column
+ *
+ * @note setType resets <em>all</em> column attributes
+ * to (type dependent) defaults and should be the first
+ * method to call. Default type is Unsigned.
+ */
+ void setType(Type type);
+
+ /**
+ * Set precision of column.
+ * @note Only applicable for decimal types
+ */
+ void setPrecision(int);
+
+ /**
+ * Set scale of column.
+ * @note Only applicable for decimal types
+ */
+ void setScale(int);
+
+ /**
+ * Set length for column
+ * Array length for column or max length for variable length arrays.
+ */
+ void setLength(int length);
+
+ /**
+ * For Char or Varchar or Text, get MySQL CHARSET_INFO. This
+ * specifies both character set and collation. See get_charset()
+ * etc in MySQL. (The cs is not "const" in MySQL).
+ */
+ void setCharset(CHARSET_INFO* cs);
+
+ /**
+ * For blob, 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);
+
+ /**
+ * For blob, get "part size" i.e. number of bytes to store in
+ * each tuple of the "blob table". Can be set to zero to omit parts
+ * and to allow only inline bytes ("tinyblob").
+ */
+ void setPartSize(int size);
+
+ /**
+ * For blob, get "stripe size" i.e. number of consecutive
+ * <em>parts</em> to store in each node group.
+ */
+ void setStripeSize(int size);
/**
- * @name ODBC Specific methods
- * @{
+ * Set partition key
+ * @see getPartitionKey
+ *
+ * @param enable If set to true, then the column will be part of
+ * the partition key.
*/
- void setAutoIncrement(bool);
+ void setPartitionKey(bool enable);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ inline void setDistributionKey(bool enable)
+ { setPartitionKey(enable); };
+#endif
+
+ /** @} *******************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const Table * getBlobTable() const;
+
+ void setAutoIncrement(bool);
bool getAutoIncrement() const;
void setAutoIncrementInitialValue(Uint64 val);
void setDefaultValue(const char*);
const char* getDefaultValue() const;
- /** @} *******************************************************************/
static const Column * FRAGMENT;
+ static const Column * FRAGMENT_MEMORY;
static const Column * ROW_COUNT;
static const Column * COMMIT_COUNT;
+ static const Column * ROW_SIZE;
+ static const Column * RANGE_NO;
+
+ int getSizeInBytes() const;
#endif
private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbRecAttr;
friend class NdbColumnImpl;
+#endif
class NdbColumnImpl & m_impl;
Column(NdbColumnImpl&);
Column& operator=(const Column&);
@@ -448,30 +499,6 @@ public:
* @name General
* @{
*/
- /**
- * Constructor
- * @param name Name of table
- */
- Table(const char * name = "");
-
- /**
- * Copy constructor
- * @param table Table to be copied
- */
- Table(const Table& table);
- virtual ~Table();
-
- /**
- * Assignment operator, deep copy
- * @param table Table to be copied
- */
- Table& operator=(const Table&);
-
- /**
- * Name of table
- * @param name Name of table
- */
- void setName(const char * name);
/**
* Get table name
@@ -484,12 +511,6 @@ public:
int getTableId() const;
/**
- * Add a column definition to a table
- * @note creates a copy
- */
- void addColumn(const Column &);
-
- /**
* Get column definition via name.
* @return null if none existing name
*/
@@ -530,17 +551,7 @@ public:
* The default value is true and indicates a normal table
* with full checkpointing and logging activated.
*/
- void setLogging(bool);
-
- /**
- * @see NdbDictionary::Table::setLogging.
- */
bool getLogging() const;
-
- /**
- * Set fragmentation type
- */
- void setFragmentType(FragmentType);
/**
* Get fragmentation type
@@ -548,13 +559,6 @@ public:
FragmentType getFragmentType() const;
/**
- * Set KValue (Hash parameter.)
- * Only allowed value is 6.
- * Later implementations might add flexibility in this parameter.
- */
- void setKValue(int kValue);
-
- /**
* Get KValue (Hash parameter.)
* Only allowed value is 6.
* Later implementations might add flexibility in this parameter.
@@ -562,15 +566,6 @@ public:
int getKValue() const;
/**
- * Set MinLoadFactor (Hash parameter.)
- * This value specifies the load factor when starting to shrink
- * the hash table.
- * It must be smaller than MaxLoadFactor.
- * Both these factors are given in percentage.
- */
- void setMinLoadFactor(int);
-
- /**
* Get MinLoadFactor (Hash parameter.)
* This value specifies the load factor when starting to shrink
* the hash table.
@@ -580,16 +575,6 @@ public:
int getMinLoadFactor() const;
/**
- * Set MaxLoadFactor (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.
- * A lower figure will store less information in each container and thus
- * find the key faster but consume more memory.
- */
- void setMaxLoadFactor(int);
-
- /**
* Get MaxLoadFactor (Hash parameter.)
* This value specifies the load factor when starting to split
* the containers in the local hash tables.
@@ -631,15 +616,83 @@ public:
const void* getFrmData() const;
Uint32 getFrmLength() const;
+ /** @} *******************************************************************/
+
+ /**
+ * @name Table creation
+ * @{
+ *
+ * These methods should normally not be used in an application as
+ * the result is not accessible from the MySQL Server
+ *
+ */
+
/**
- * Set frm file to store with this table
- */
- void setFrm(const void* data, Uint32 len);
+ * Constructor
+ * @param name Name of table
+ */
+ Table(const char * name = "");
+ /**
+ * Copy constructor
+ * @param table Table to be copied
+ */
+ Table(const Table& table);
+ virtual ~Table();
+
/**
- * Set table object type
+ * Assignment operator, deep copy
+ * @param table Table to be copied
*/
- void setObjectType(Object::Type type);
+ Table& operator=(const Table& table);
+
+ /**
+ * Name of table
+ * @param name Name of table
+ */
+ void setName(const char * name);
+
+ /**
+ * Add a column definition to a table
+ * @note creates a copy
+ */
+ void addColumn(const Column &);
+
+ /**
+ * @see NdbDictionary::Table::getLogging.
+ */
+ void setLogging(bool);
+
+ /**
+ * Set fragmentation type
+ */
+ void setFragmentType(FragmentType);
+
+ /**
+ * Set KValue (Hash parameter.)
+ * Only allowed value is 6.
+ * Later implementations might add flexibility in this parameter.
+ */
+ void setKValue(int kValue);
+
+ /**
+ * Set MinLoadFactor (Hash parameter.)
+ * This value specifies the load factor when starting to shrink
+ * the hash table.
+ * It must be smaller than MaxLoadFactor.
+ * Both these factors are given in percentage.
+ */
+ void setMinLoadFactor(int);
+
+ /**
+ * Set MaxLoadFactor (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.
+ * A lower figure will store less information in each container and thus
+ * find the key faster but consume more memory.
+ */
+ void setMaxLoadFactor(int);
/**
* Get table object type
@@ -656,18 +709,32 @@ public:
*/
virtual int getObjectVersion() const;
+ /**
+ * Set frm file to store with this table
+ */
+ void setFrm(const void* data, Uint32 len);
+
+ /**
+ * Set table object type
+ */
+ void setObjectType(Object::Type type);
+
/** @} *******************************************************************/
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
void setStoredTable(bool x) { setLogging(x); }
bool getStoredTable() const { return getLogging(); }
int getRowSizeInBytes() const ;
int createTableInDb(Ndb*, bool existingEqualIsOk = true) const ;
+
+ int getReplicaCount() const ;
#endif
private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbTableImpl;
+#endif
class NdbTableImpl & m_impl;
Table(NdbTableImpl&);
};
@@ -678,29 +745,18 @@ public:
*/
class Index : public Object {
public:
- /**
- * Constructor
- * @param name Name of index
+
+ /**
+ * @name Getting Index properties
+ * @{
*/
- Index(const char * name = "");
- virtual ~Index();
/**
- * Set the name of an index
- */
- void setName(const char * name);
-
- /**
* Get the name of an index
*/
const char * getName() const;
/**
- * Define the name of the table to be indexed
- */
- void setTable(const char * name);
-
- /**
* Get the name of the table being indexed
*/
const char * getTable() const;
@@ -710,22 +766,89 @@ public:
*/
unsigned getNoOfColumns() const;
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Get the number of columns in the index
* Depricated, use getNoOfColumns instead.
*/
int getNoOfIndexColumns() const;
+#endif
/**
* Get a specific column in the index
*/
const Column * getColumn(unsigned no) const ;
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Get a specific column name in the index
* Depricated, use getColumn instead.
*/
const char * getIndexColumn(int no) const ;
+#endif
+
+ /**
+ * Represents type of index
+ */
+ enum Type {
+ Undefined = 0, ///< Undefined object type (initial value)
+ UniqueHashIndex = 3, ///< Unique un-ordered hash index
+ ///< (only one currently supported)
+ OrderedIndex = 6 ///< Non-unique ordered index
+ };
+
+ /**
+ * Get index type of the index
+ */
+ Type getType() const;
+
+ /**
+ * Check if index is set to be stored on disk
+ *
+ * @return if true then logging id enabled
+ *
+ * @note Non-logged indexes are rebuilt at system restart.
+ * @note Ordered index does not currently support logging.
+ */
+ bool getLogging() const;
+
+ /**
+ * Get object status
+ */
+ virtual Object::Status getObjectStatus() const;
+
+ /**
+ * Get object version
+ */
+ virtual int getObjectVersion() const;
+
+ /** @} *******************************************************************/
+
+ /**
+ * @name Index creation
+ * @{
+ *
+ * These methods should normally not be used in an application as
+ * the result will not be visible from the MySQL Server
+ *
+ */
+
+ /**
+ * Constructor
+ * @param name Name of index
+ */
+ Index(const char * name = "");
+ virtual ~Index();
+
+ /**
+ * Set the name of an index
+ */
+ void setName(const char * name);
+
+ /**
+ * Define the name of the table to be indexed
+ */
+ void setTable(const char * name);
/**
* Add a column to the index definition
@@ -741,6 +864,7 @@ public:
*/
void addColumnName(const char * name);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Add a column name to the index definition
* Note that the order of indexes will be in
@@ -748,6 +872,7 @@ public:
* Depricated, use addColumnName instead.
*/
void addIndexColumn(const char * name);
+#endif
/**
* Add several column names to the index definition
@@ -756,6 +881,7 @@ public:
*/
void addColumnNames(unsigned noOfNames, const char ** names);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Add several column names to the index definition
* Note that the order of indexes will be in
@@ -763,18 +889,7 @@ public:
* Depricated, use addColumnNames instead.
*/
void addIndexColumns(int noOfNames, const char ** names);
-
- /**
- * Represents type of index
- */
- enum Type {
- Undefined = 0, ///< Undefined object type (initial value)
- UniqueHashIndex = 3, ///< Unique un-ordered hash index
- ///< (only one currently supported)
- HashIndex = 4, ///< Non-unique un-ordered hash index
- UniqueOrderedIndex = 5, ///< Unique ordered index
- OrderedIndex = 6 ///< Non-unique ordered index
- };
+#endif
/**
* Set index type of the index
@@ -782,47 +897,25 @@ public:
void setType(Type type);
/**
- * Get index type of the index
- */
- Type getType() const;
-
- /**
* Enable/Disable index storage on disk
*
* @param enable If enable is set to true, then logging becomes enabled
*
- * @see NdbDictionary::Table::setLogging
- *
- * @note Non-logged indexes are rebuilt at system restart.
- * @note Ordered index does not currently support logging.
+ * @see NdbDictionary::Index::getLogging
*/
void setLogging(bool enable);
- /**
- * Check if index is set to be stored on disk
- *
- * @see NdbDictionary::Index::setLogging
- */
- bool getLogging() const;
-
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
void setStoredIndex(bool x) { setLogging(x); }
bool getStoredIndex() const { return getLogging(); }
#endif
- /**
- * Get object status
- */
- virtual Object::Status getObjectStatus() const;
-
- /**
- * Get object version
- */
- virtual int getObjectVersion() const;
+ /** @} *******************************************************************/
private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbIndexImpl;
-
+#endif
class NdbIndexImpl & m_impl;
Index(NdbIndexImpl&);
};
@@ -833,35 +926,137 @@ public:
*/
class Event : public Object {
public:
- enum TableEvent { TE_INSERT=1, TE_DELETE=2, TE_UPDATE=4, TE_ALL=7 };
+ /**
+ * Specifies the type of database operations an Event listens to
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** TableEvent must match 1 << TriggerEvent */
+#endif
+ enum TableEvent {
+ TE_INSERT=1, ///< Insert event on table
+ TE_DELETE=2, ///< Delete event on table
+ TE_UPDATE=4, ///< Update event on table
+ TE_ALL=7 ///< Any/all event on table (not relevant when
+ ///< events are received)
+ };
+ /**
+ * Specifies the durability of an event
+ * (future version may supply other types)
+ */
enum EventDurability {
- ED_UNDEFINED = 0,
+ ED_UNDEFINED
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 0
+#endif
#if 0 // not supported
- ED_SESSION = 1,
+ ,ED_SESSION = 1,
// Only this API can use it
// and it's deleted after api has disconnected or ndb has restarted
- ED_TEMPORARY = 2,
+ ED_TEMPORARY = 2
// All API's can use it,
// But's its removed when ndb is restarted
-#endif
- ED_PERMANENT = 3
- // All API's can use it,
- // It's still defined after a restart
+#endif
+ ,ED_PERMANENT ///< All API's can use it.
+ ///< It's still defined after a cluster system restart
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 3
+#endif
};
-
+
+ /**
+ * Constructor
+ * @param name Name of event
+ */
Event(const char *name);
+ /**
+ * Constructor
+ * @param name Name of event
+ * @param table Reference retrieved from NdbDictionary
+ */
+ Event(const char *name, const NdbDictionary::Table& table);
virtual ~Event();
- void setName(const char *);
- void setTable(const char *);
- void addTableEvent(const TableEvent);
- void setDurability(const EventDurability);
+ /**
+ * Set unique identifier for the event
+ */
+ void setName(const char *name);
+ /**
+ * Get unique identifier for the event
+ */
+ const char *getName() const;
+ /**
+ * Define table on which events should be detected
+ *
+ * @note calling this method will default to detection
+ * of events on all columns. Calling subsequent
+ * addEventColumn calls will override this.
+ *
+ * @param table reference retrieved from NdbDictionary
+ */
+ void setTable(const NdbDictionary::Table& table);
+ /**
+ * Set table for which events should be detected
+ *
+ * @note preferred way is using setTable(const NdbDictionary::Table&)
+ * or constructor with table object parameter
+ */
+ void setTable(const char *tableName);
+ /**
+ * Get table name for events
+ *
+ * @return table name
+ */
+ const char* getTableName() const;
+ /**
+ * Add type of event that should be detected
+ */
+ void addTableEvent(const TableEvent te);
+ /**
+ * Set durability of the event
+ */
+ void setDurability(EventDurability);
+ /**
+ * Get durability of the event
+ */
+ EventDurability getDurability() const;
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
void addColumn(const Column &c);
+#endif
+ /**
+ * Add a column on which events should be detected
+ *
+ * @param attrId Column id
+ *
+ * @note errors will mot be detected until createEvent() is called
+ */
void addEventColumn(unsigned attrId);
+ /**
+ * Add a column on which events should be detected
+ *
+ * @param columnName Column name
+ *
+ * @note errors will not be detected until createEvent() is called
+ */
void addEventColumn(const char * columnName);
+ /**
+ * Add several columns on which events should be detected
+ *
+ * @param n Number of columns
+ * @param columnNames Column names
+ *
+ * @note errors will mot be detected until
+ * NdbDictionary::Dictionary::createEvent() is called
+ */
void addEventColumns(int n, const char ** columnNames);
/**
+ * Get no of columns defined in an Event
+ *
+ * @return Number of columns, -1 on error
+ */
+ int getNoOfEventColumns() const;
+
+ /**
* Get object status
*/
virtual Object::Status getObjectStatus() const;
@@ -871,11 +1066,15 @@ public:
*/
virtual int getObjectVersion() const;
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
void print();
+#endif
private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbEventImpl;
friend class NdbEventOperationImpl;
+#endif
class NdbEventImpl & m_impl;
Event(NdbEventImpl&);
};
@@ -938,8 +1137,17 @@ public:
/**
* Fetch list of all objects, optionally restricted to given type.
+ *
+ * @param list List of objects returned in the dictionary
+ * @param type Restrict returned list to only contain objects of
+ * this type
+ *
+ * @return -1 if error.
+ *
*/
int listObjects(List & list, Object::Type type = Object::TypeUndefined);
+ int listObjects(List & list,
+ Object::Type type = Object::TypeUndefined) const;
/**
* Get the latest error
@@ -949,24 +1157,87 @@ public:
const struct NdbError & getNdbError() const;
/** @} *******************************************************************/
+
+ /**
+ * @name Retrieving references to Tables and Indexes
+ * @{
+ */
+
+ /**
+ * Get table with given name, NULL if undefined
+ * @param name Name of table to get
+ * @return table if successful otherwise NULL.
+ */
+ const Table * getTable(const char * name) const;
+
+ /**
+ * Get index with given name, NULL if undefined
+ * @param indexName Name of index to get.
+ * @param tableName Name of table that index belongs to.
+ * @return index if successful, otherwise 0.
+ */
+ const Index * getIndex(const char * indexName,
+ const char * tableName) const;
+
+ /**
+ * Fetch list of indexes of given table.
+ * @param list Reference to list where to store the listed indexes
+ * @param tableName Name of table that index belongs to.
+ * @return 0 if successful, otherwise -1
+ */
+ int listIndexes(List & list, const char * tableName);
+ int listIndexes(List & list, const char * tableName) const;
+
+ /** @} *******************************************************************/
+ /**
+ * @name Events
+ * @{
+ */
+
+ /**
+ * Create event given defined Event instance
+ * @param event Event to create
+ * @return 0 if successful otherwise -1.
+ */
+ int createEvent(const Event &event);
+
+ /**
+ * Drop event with given name
+ * @param eventName Name of event to drop.
+ * @return 0 if successful otherwise -1.
+ */
+ int dropEvent(const char * eventName);
+
+ /**
+ * Get event with given name.
+ * @param eventName Name of event to get.
+ * @return an Event if successful, otherwise NULL.
+ */
+ const Event * getEvent(const char * eventName);
+
+ /** @} *******************************************************************/
+
/**
- * @name Tables
+ * @name Table creation
* @{
+ *
+ * These methods should normally not be used in an application as
+ * the result will not be visible from the MySQL Server
*/
/**
* Create defined table given defined Table instance
- * @param Table Table to create
+ * @param table Table to create
* @return 0 if successful otherwise -1.
*/
- int createTable(const Table &);
+ int createTable(const Table &table);
/**
* Drop table given retrieved Table instance
- * @param Table Table to drop
+ * @param table Table to drop
* @return 0 if successful otherwise -1.
*/
- int dropTable(Table &);
+ int dropTable(Table & table);
/**
* Drop table given table name
@@ -975,23 +1246,16 @@ public:
*/
int dropTable(const char * name);
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Alter defined table given defined Table instance
- * @param Table Table to alter
+ * @param table Table to alter
* @return -2 (incompatible version) <br>
* -1 general error <br>
* 0 success
*/
- int alterTable(const Table &);
-
- /**
- * Get table with given name, NULL if undefined
- * @param name Name of table to get
- * @return table if successful otherwise NULL.
- */
- const Table * getTable(const char * name);
+ int alterTable(const Table &table);
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Invalidate cached table object
* @param name Name of table to invalidate
@@ -1000,24 +1264,31 @@ public:
#endif
/**
- * Remove table/index from local cache
+ * Remove table from local cache
*/
void removeCachedTable(const char * table);
+ /**
+ * Remove index from local cache
+ */
void removeCachedIndex(const char * index, const char * table);
/** @} *******************************************************************/
/**
- * @name Indexes
+ * @name Index creation
* @{
+ *
+ * These methods should normally not be used in an application as
+ * the result will not be visible from the MySQL Server
+ *
*/
/**
* Create index given defined Index instance
- * @param Index to create
+ * @param index Index to create
* @return 0 if successful otherwise -1.
*/
- int createIndex(const Index &);
+ int createIndex(const Index &index);
/**
* Drop index with given name
@@ -1028,15 +1299,6 @@ public:
int dropIndex(const char * indexName,
const char * tableName);
- /**
- * Get index with given name, NULL if undefined
- * @param indexName Name of index to get.
- * @param tableName Name of table that index belongs to.
- * @return index if successful, otherwise 0.
- */
- const Index * getIndex(const char * indexName,
- const char * tableName);
-
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Invalidate cached index object
@@ -1045,58 +1307,27 @@ public:
const char * tableName);
#endif
- /**
- * Fetch list of indexes of given table.
- * @param list Reference to list where to store the listed indexes
- * @param tableName Name of table that index belongs to.
- * @return 0 if successful, otherwise -1
- */
- int listIndexes(List & list, const char * tableName);
-
/** @} *******************************************************************/
- /**
- * @name Events
- * @{
- */
-
- /**
- * Create event given defined Event instance
- * @param Event to create
- * @return 0 if successful otherwise -1.
- */
- int createEvent(const Event &);
- /**
- * Drop event with given name
- * @param eventName Name of event to drop.
- * @return 0 if successful otherwise -1.
- */
- int dropEvent(const char * eventName);
-
- /**
- * Get event with given name.
- * @param eventName Name of event to get.
- * @return an Event if successful, otherwise NULL.
- */
- const Event * getEvent(const char * eventName);
-
- /** @} *******************************************************************/
-
protected:
Dictionary(Ndb & ndb);
~Dictionary();
private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbDictionaryImpl;
friend class UtilTransactions;
friend class NdbBlob;
+#endif
class NdbDictionaryImpl & m_impl;
Dictionary(NdbDictionaryImpl&);
const Table * getIndexTable(const char * indexName,
- const char * tableName);
+ const char * tableName) const;
public:
- const Table * getTable(const char * name, void **data);
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const Table * getTable(const char * name, void **data) const;
void set_local_table_data_size(unsigned sz);
+#endif
};
};
diff --git a/ndb/include/ndbapi/NdbError.hpp b/ndb/include/ndbapi/NdbError.hpp
index 8cde2a8cf38..f67b3c4ccaa 100644
--- a/ndb/include/ndbapi/NdbError.hpp
+++ b/ndb/include/ndbapi/NdbError.hpp
@@ -41,7 +41,7 @@
* The <em>error messages</em> and <em>error details</em> may
* change without notice.
*
- * For example of use, see @ref ndbapi_example3.cpp.
+ * For example of use, see @ref ndbapi_retries.cpp.
*/
struct NdbError {
/**
@@ -168,7 +168,12 @@ struct NdbError {
/**
* Node shutdown
*/
- NodeShutdown = ndberror_cl_node_shutdown
+ NodeShutdown = ndberror_cl_node_shutdown,
+
+ /**
+ * Schema object already exists
+ */
+ SchemaObjectExists = ndberror_cl_schema_object_already_exists
};
/**
@@ -199,6 +204,7 @@ struct NdbError {
*/
char * details;
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
NdbError(){
status = UnknownResult;
classification = NoError;
@@ -222,6 +228,7 @@ struct NdbError {
ndberror.details = details;
return ndberror;
}
+#endif
};
class NdbOut& operator <<(class NdbOut&, const NdbError &);
diff --git a/ndb/include/ndbapi/NdbEventOperation.hpp b/ndb/include/ndbapi/NdbEventOperation.hpp
index 056e9a58c74..55ee96b3144 100644
--- a/ndb/include/ndbapi/NdbEventOperation.hpp
+++ b/ndb/include/ndbapi/NdbEventOperation.hpp
@@ -14,19 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbEventOperation.hpp
- * Include:
- * Link:
- * Author: Tomas Ulin MySQL AB
- * Date: 2003-11-21
- * Version: 0.1
- * Description: Event support
- * Documentation:
- * Adjust: 2003-11-21 Tomas Ulin First version.
- * Adjust: 2003-12-11 Tomas Ulin Alpha Release.
- ****************************************************************************/
-
#ifndef NdbEventOperation_H
#define NdbEventOperation_H
@@ -37,80 +24,79 @@ class NdbEventOperationImpl;
* @class NdbEventOperation
* @brief Class of operations for getting change events from database.
*
- * An NdbEventOperation object is instantiated by
- * NdbEventOperation *Ndb::createEventOperation(const char *eventName,
- * int bufferLength)
- *
- * Prior to that an event must have been created in the Database through
- * int NdbDictionary::createEvent(NdbDictionary::Event)
- *
- * bufferLength indicates size of circular buffer to store event info as
- * they occur.
+ * Brief description on how to work with events:
*
- * The instance is removed by Ndb::dropEventOperation(NdbEventOperation*)
+ * - An event, represented by an NdbDictionary::Event, i created in the
+ * Database through
+ * NdbDictionary::Dictionary::createEvent() (note that this can be done
+ * by any application or thread and not necessarily by the "listener")
+ * - To listen to events, an NdbEventOperation object is instantiated by
+ * Ndb::createEventOperation()
+ * - execute() starts the event flow. Use Ndb::pollEvents() to wait
+ * for an event to occur. Use next() to iterate
+ * through the events that have occured.
+ * - The instance is removed by Ndb::dropEventOperation()
*
* For more info see:
- * ndbapi_example5.cpp
- * Ndb.hpp
- * NdbDictionary.hpp
+ * @ref ndbapi_event.cpp
*
* Known limitations:
*
- * Maximum number of active NdbEventOperations are now set at compile time.
+ * - Maximum number of active NdbEventOperations are now set at compile time.
* Today 100. This will become a configuration parameter later.
- *
- * Maximum number of NdbEventOperations tied to same event are maximum 16
+ * - Maximum number of NdbEventOperations tied to same event are maximum 16
* per process.
*
* Known issues:
*
- * When several NdbEventOperation s are tied to the same event in the same
+ * - When several NdbEventOperation's are tied to the same event in the same
* process they will share the circular buffer. The BufferLength will then
* be the same for all and decided by the first NdbEventOperation
* instantiation. Just make sure to instantiate the "largest" one first.
- *
- * Today all events INSERT/DELETE/UPDATE and all changed attributes are
+ * - Today all events INSERT/DELETE/UPDATE and all changed attributes are
* sent to the API, even if only specific attributes have been specified.
* These are however hidden from the user and only relevant data is shown
- * after next(). However false exits from pollEvents() may occur and thus
- * the subsequent next() will return zero, since there was no available
- * data. Just do pollEvents() again. Will be fixed in later versions.
- *
- * Event code does not check table schema version. Make sure to drop events
+ * after next().
+ * - "False" exits from Ndb::pollEvents() may occur and thus
+ * the subsequent next() will return zero,
+ * since there was no available data. Just do Ndb::pollEvents() again.
+ * - Event code does not check table schema version. Make sure to drop events
* after table is dropped. Will be fixed in later
* versions.
- *
- * On a replicated system one will receive each event 2 times, one for each
- * replica. If a node fails events will not be received twice anymore
- * for data in corresponding fragment. Will be optimized in later versions.
- *
- * If a nodefailiure has occured not all events will be recieved
+ * - If a node failure has occured not all events will be recieved
* anymore. Drop NdbEventOperation and Create again after nodes are up
* again. Will be fixed in later versions.
*
* Test status:
- * Tests have been run on 1-node and 2-node systems
*
- * Known bugs:
- *
- * None, except if we can call some of the "isses" above bugs
+ * - Tests have been run on 1-node and 2-node systems
*
* Useful API programs:
*
- * select_all -d sys 'NDB$EVENTS_0'
- * Will show contents in the system table containing created events.
+ * - ndb_select_all -d sys 'NDB$EVENTS_0'
+ * shows contents in the system table containing created events.
*
+ * @note this is an inteface to viewing events that is subject to change
*/
class NdbEventOperation {
public:
- enum State {CREATED,EXECUTING,ERROR};
-
+ /**
+ * State of the NdbEventOperation object
+ */
+ enum State {
+ EO_CREATED, ///< Created but execute() not called
+ EO_EXECUTING, ///< execute() called
+ EO_ERROR ///< An error has occurred. Object unusable.
+ };
+ /**
+ * Retrieve current state of the NdbEventOperation object
+ */
State getState();
/**
* Activates the NdbEventOperation to start receiving events. The
* changed attribute values may be retrieved after next() has returned
- * a value greater than zero. The getValue() methods below must be called
+ * a value greater than zero. The getValue() methods must be called
* prior to execute().
*
* @return 0 if successful otherwise -1.
@@ -132,21 +118,21 @@ public:
* aligned appropriately. The buffer is used directly
* (avoiding a copy penalty) only if it is aligned on a
* 4-byte boundary and the attribute size in bytes
- * (i.e. NdbRecAttr::attrSize times NdbRecAttr::arraySize is
+ * (i.e. NdbRecAttr::attrSize() times NdbRecAttr::arraySize() is
* a multiple of 4).
*
- * @note There are two versions, NdbOperation::getValue and
- * NdbOperation::getPreValue for retrieving the current and
+ * @note There are two versions, getValue() and
+ * getPreValue() for retrieving the current and
* previous value repectively.
*
* @note This method does not fetch the attribute value from
* the database! The NdbRecAttr object returned by this method
* is <em>not</em> readable/printable before the
- * NdbEventConnection::execute has been made and
- * NdbEventConnection::next has returned a value greater than
+ * execute() has been made and
+ * next() has returned a value greater than
* zero. If a specific attribute has not changed the corresponding
* NdbRecAttr will be in state UNDEFINED. This is checked by
- * NdbRecAttr::isNull which then returns -1.
+ * NdbRecAttr::isNULL() which then returns -1.
*
* @param anAttrName Attribute name
* @param aValue If this is non-NULL, then the attribute value
@@ -158,19 +144,24 @@ public:
* (indicating error).
*/
NdbRecAttr *getValue(const char *anAttrName, char *aValue = 0);
+ /**
+ * See getValue().
+ */
NdbRecAttr *getPreValue(const char *anAttrName, char *aValue = 0);
/**
* Retrieves event resultset if available, inserted into the NdbRecAttrs
* specified in getValue() and getPreValue(). To avoid polling for
- * a resultset, one can use Ndb::pollEvents(int millisecond_timeout)
+ * a resultset, one can use Ndb::pollEvents()
* which will wait on a mutex until an event occurs or the specified
* timeout occurs.
*
- * @return >=0 if successful otherwise -1. Return value inicates number
+ * @return >=0 if successful otherwise -1. Return value indicates number
* of available events. By sending pOverRun one may query for buffer
* overflow and *pOverRun will indicate the number of events that have
* overwritten.
+ *
+ * @return number of available events, -1 on failure
*/
int next(int *pOverRun=0);
@@ -182,18 +173,47 @@ public:
/**
* Query for occured event type.
- * NdbDictionary::Event::{TE_INSERT,TE_UPDATE,TE_DELETE}
- * Only valid after next() has returned value >= 0
+ *
+ * @note Only valid after next() has been called and returned value >= 0
+ *
+ * @return type of event
*/
NdbDictionary::Event::TableEvent getEventType();
+ /**
+ * Retrieve the GCI of the latest retrieved event
+ *
+ * @return GCI number
+ */
Uint32 getGCI();
+
+ /**
+ * Retrieve the complete GCI in the cluster (not necessarily
+ * associated with an event)
+ *
+ * @return GCI number
+ */
Uint32 getLatestGCI();
+
+ /**
+ * Get the latest error
+ *
+ * @return Error object.
+ */
+ const struct NdbError & getNdbError() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /*
+ *
+ */
void print();
+#endif
private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbEventOperationImpl;
friend class Ndb;
+#endif
NdbEventOperation(Ndb *theNdb, const char* eventName,int bufferLength);
~NdbEventOperation();
static int wait(void *p, int aMillisecondNumber);
diff --git a/ndb/include/ndbapi/NdbIndexOperation.hpp b/ndb/include/ndbapi/NdbIndexOperation.hpp
index 1472f1b249e..3de6835238e 100644
--- a/ndb/include/ndbapi/NdbIndexOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexOperation.hpp
@@ -14,18 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbIndexOperation.hpp
- * Include:
- * Link:
- * Author: Martin Sköld
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Secondary index support
- * Documentation:
- * Adjust: 2002-04-01 Martin Sköld First version.
- ****************************************************************************/
-
#ifndef NdbIndexOperation_H
#define NdbIndexOperation_H
@@ -40,8 +28,10 @@ class NdbResultSet;
*/
class NdbIndexOperation : public NdbOperation
{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
+#endif
public:
/**
@@ -54,16 +44,17 @@ public:
/**
* Define the NdbIndexOperation to be a standard operation of type readTuple.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* reads a tuple.
*
* @return 0 if successful otherwise -1.
*/
int readTuple(LockMode);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Define the NdbIndexOperation to be a standard operation of type readTuple.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* reads a tuple.
*
* @return 0 if successful otherwise -1.
@@ -73,7 +64,7 @@ public:
/**
* Define the NdbIndexOperation to be a standard operation of type
* readTupleExclusive.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* read a tuple using an exclusive lock.
*
* @return 0 if successful otherwise -1.
@@ -82,7 +73,7 @@ public:
/**
* Define the NdbIndexOperation to be a standard operation of type simpleRead.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* reads an existing tuple (using shared read lock),
* but releases lock immediately after read.
*
@@ -101,7 +92,7 @@ public:
/**
* Define the NdbOperation to be a standard operation of type committedRead.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* read latest committed value of the record.
*
* This means that if another transaction is updating the
@@ -113,7 +104,6 @@ public:
*/
int dirtyRead();
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
int committedRead();
#endif
@@ -121,7 +111,7 @@ public:
* Define the NdbIndexOperation to be a standard operation of type
* updateTuple.
*
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* updates a tuple in the table.
*
* @return 0 if successful otherwise -1.
@@ -132,24 +122,27 @@ public:
* Define the NdbIndexOperation to be a standard operation of type
* deleteTuple.
*
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* deletes a tuple.
*
* @return 0 if successful otherwise -1.
*/
int deleteTuple();
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Define the NdbIndexOperation to be a standard operation of type
* dirtyUpdate.
*
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* updates without two-phase commit.
*
* @return 0 if successful otherwise -1.
*/
int dirtyUpdate();
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/** @} *********************************************************************/
/**
* @name Define Interpreted Program Operation
@@ -169,6 +162,7 @@ public:
* @return 0 if successful otherwise -1.
*/
int interpretedDeleteTuple();
+#endif
/** @} *********************************************************************/
@@ -176,30 +170,17 @@ private:
NdbIndexOperation(Ndb* aNdb);
~NdbIndexOperation();
- void closeScan();
-
int receiveTCINDXREF(NdbApiSignal* aSignal);
- // Overloaded method from NdbOperation
- void setLastFlag(NdbApiSignal* signal, Uint32 lastFlag);
-
- // Overloaded methods from NdbCursorOperation
- int executeCursor(int ProcessorId);
-
// Overloaded methods from NdbCursorOperation
int indxInit(const class NdbIndexImpl* anIndex,
const class NdbTableImpl* aTable,
- NdbConnection* myConnection);
+ NdbTransaction*);
- int equal_impl(const class NdbColumnImpl*, const char* aValue, Uint32 len);
int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId);
// Private attributes
const NdbIndexImpl* m_theIndex;
- const NdbTableImpl* m_thePrimaryTable;
- 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
};
#endif
diff --git a/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
index a3388f62f58..0a31f228921 100644
--- a/ndb/include/ndbapi/NdbIndexScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
@@ -24,36 +24,51 @@
* @brief Class of scan operations for use to scan ordered index
*/
class NdbIndexScanOperation : public NdbScanOperation {
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class NdbResultSet;
friend class NdbOperation;
friend class NdbScanOperation;
+#endif
+
public:
/**
- * readTuples returns a NdbResultSet where tuples are stored.
- * Tuples are not stored in NdbResultSet until execute(NoCommit)
- * has been executed and nextResult has been called.
+ * readTuples using ordered index
+ *
+ * @param lock_mode Lock mode
+ * @param scan_flags see @ref ScanFlag
+ * @param parallel No of fragments to scan in parallel (0=max)
+ */
+ virtual int readTuples(LockMode lock_mode = LM_Read,
+ Uint32 scan_flags = 0, Uint32 parallel = 0);
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * readTuples using ordered index
*
- * @param parallel Scan parallelism
+ * @param lock_mode Lock mode
* @param batch No of rows to fetch from each fragment at a time
- * @param LockMode Scan lock handling
+ * @param parallel No of fragments to scan in parallel
* @param order_by Order result set in index order
- * @returns NdbResultSet.
+ * @param order_desc Order descending, ignored unless order_by
+ * @param read_range_no Enable reading of range no using @ref get_range_no
+ * @returns 0 for success and -1 for failure
* @see NdbScanOperation::readTuples
*/
- NdbResultSet* readTuples(LockMode = LM_Read,
- Uint32 batch = 0,
- Uint32 parallel = 0,
- bool order_by = false);
-
- inline NdbResultSet* readTuples(int parallell){
- return readTuples(LM_Read, 0, parallell, false);
- }
-
- inline NdbResultSet* readTuplesExclusive(int parallell = 0){
- return readTuples(LM_Exclusive, 0, parallell, false);
+ inline int readTuples(LockMode lock_mode,
+ Uint32 batch,
+ Uint32 parallel,
+ bool order_by,
+ bool order_desc = false,
+ bool read_range_no = false) {
+ Uint32 scan_flags =
+ (SF_OrderBy & -(Int32)order_by) |
+ (SF_Descending & -(Int32)order_desc) |
+ (SF_ReadRangeNo & -(Int32)read_range_no);
+ return readTuples(lock_mode, scan_flags, parallel);
}
+#endif
/**
* Type of ordered index key bound. The values (0-4) will not change
@@ -76,7 +91,7 @@ public:
*
* For equality, it is better to use BoundEQ instead of the equivalent
* pair of BoundLE and BoundGE. This is especially true when table
- * distribution key is an initial part of the index key.
+ * partition key is an initial part of the index key.
*
* The sets of lower and upper bounds must be on initial sequences of
* index keys. All but possibly the last bound must be non-strict.
@@ -93,15 +108,14 @@ public:
* An index stores also all-NULL keys. Doing index scan with empty
* bound set returns all table tuples.
*
- * @param attrName Attribute name, alternatively:
- * @param anAttrId Index column id (starting from 0)
+ * @param attr Attribute name, alternatively:
* @param type Type of bound
* @param value Pointer to bound value, 0 for NULL
* @param len Value length in bytes.
* Fixed per datatype and can be omitted
* @return 0 if successful otherwise -1
*/
- int setBound(const char* attr, int type, const void* aValue, Uint32 len = 0);
+ int setBound(const char* attr, int type, const void* value, Uint32 len = 0);
/**
* Define bound on index key in range scan using index column id.
@@ -114,8 +128,27 @@ public:
* sent on next execute
*/
int reset_bounds(bool forceSend = false);
+
+ /**
+ * Marks end of a bound,
+ * used when batching index reads (multiple ranges)
+ */
+ int end_of_bound(Uint32 range_no);
+
+ /**
+ * Return range no for current row
+ */
+ int get_range_no();
+ /**
+ * Is current scan sorted
+ */
bool getSorted() const { return m_ordered; }
+
+ /**
+ * Is current scan sorted descending
+ */
+ bool getDescending() const { return m_descending; }
private:
NdbIndexScanOperation(Ndb* aNdb);
virtual ~NdbIndexScanOperation();
@@ -132,6 +165,9 @@ private:
int compare(Uint32 key, Uint32 cols, const NdbReceiver*, const NdbReceiver*);
Uint32 m_sort_columns;
+
+ Uint32 m_this_bound_start;
+ Uint32 * m_first_bound_word;
};
#endif
diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp
index 46d4ddab0f5..fca610772cc 100644
--- a/ndb/include/ndbapi/NdbOperation.hpp
+++ b/ndb/include/ndbapi/NdbOperation.hpp
@@ -27,7 +27,7 @@ class Ndb;
class NdbApiSignal;
class NdbRecAttr;
class NdbOperation;
-class NdbConnection;
+class NdbTransaction;
class NdbColumnImpl;
class NdbBlob;
@@ -37,14 +37,17 @@ class NdbBlob;
*/
class NdbOperation
{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class NdbScanOperation;
friend class NdbScanReceiver;
friend class NdbScanFilter;
friend class NdbScanFilterImpl;
friend class NdbReceiver;
friend class NdbBlob;
+#endif
+
public:
/**
* @name Define Standard Operation Type
@@ -56,17 +59,24 @@ public:
*/
enum LockMode {
- LM_Read = 0,
- LM_Exclusive = 1,
- LM_CommittedRead = 2,
+ LM_Read ///< Read with shared lock
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 0
+#endif
+ ,LM_Exclusive ///< Read with exclusive lock
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 1
+#endif
+ ,LM_CommittedRead ///< Ignore locks, read last committed value
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = 2,
LM_Dirty = 2
#endif
};
/**
* Define the NdbOperation to be a standard operation of type insertTuple.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* adds a new tuple to the table.
*
* @return 0 if successful otherwise -1.
@@ -75,7 +85,7 @@ public:
/**
* Define the NdbOperation to be a standard operation of type updateTuple.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* updates a tuple in the table.
*
* @return 0 if successful otherwise -1.
@@ -84,7 +94,7 @@ public:
/**
* Define the NdbOperation to be a standard operation of type writeTuple.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* writes a tuple to the table.
* If the tuple exists, it updates it, otherwise an insert takes place.
*
@@ -94,7 +104,7 @@ public:
/**
* Define the NdbOperation to be a standard operation of type deleteTuple.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* delete a tuple.
*
* @return 0 if successful otherwise -1.
@@ -103,16 +113,17 @@ public:
/**
* Define the NdbOperation to be a standard operation of type readTuple.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* reads a tuple.
*
* @return 0 if successful otherwise -1.
*/
virtual int readTuple(LockMode);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Define the NdbOperation to be a standard operation of type readTuple.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* reads a tuple.
*
* @return 0 if successful otherwise -1.
@@ -122,7 +133,7 @@ public:
/**
* Define the NdbOperation to be a standard operation of type
* readTupleExclusive.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* read a tuple using an exclusive lock.
*
* @return 0 if successful otherwise -1.
@@ -132,7 +143,7 @@ public:
/**
* Define the NdbOperation to be a standard operation of type
* simpleRead.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* reads an existing tuple (using shared read lock),
* but releases lock immediately after read.
*
@@ -149,10 +160,9 @@ public:
*/
virtual int simpleRead();
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* Define the NdbOperation to be a standard operation of type committedRead.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* read latest committed value of the record.
*
* This means that if another transaction is updating the
@@ -165,11 +175,10 @@ public:
* @depricated
*/
virtual int dirtyRead();
-#endif
/**
* Define the NdbOperation to be a standard operation of type committedRead.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* read latest committed value of the record.
*
* This means that if another transaction is updating the
@@ -183,7 +192,7 @@ public:
/**
* Define the NdbOperation to be a standard operation of type dirtyUpdate.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* updates without two-phase commit.
*
* @return 0 if successful otherwise -1.
@@ -192,13 +201,15 @@ public:
/**
* Define the NdbOperation to be a standard operation of type dirtyWrite.
- * When calling NdbConnection::execute, this operation
+ * When calling NdbTransaction::execute, this operation
* writes without two-phase commit.
*
* @return 0 if successful otherwise -1.
*/
virtual int dirtyWrite();
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/** @} *********************************************************************/
/**
* @name Define Interpreted Program Operation Type
@@ -218,6 +229,7 @@ public:
* @return 0 if successful otherwise -1.
*/
virtual int interpretedDeleteTuple();
+#endif
/** @} *********************************************************************/
@@ -232,10 +244,13 @@ public:
* use several equals (then all of them must be satisfied for the
* tuple to be selected).
*
- * @note There are 10 versions of NdbOperation::equal with
+ * @note For insertTuple() it is also allowed to define the
+ * search key by using setValue().
+ *
+ * @note There are 10 versions of equal() with
* slightly different parameters.
*
- * @note When using NdbOperation::equal with a string (char *) as
+ * @note When using equal() with a string (char *) as
* second argument, the string needs to be padded with
* zeros in the following sense:
* @code
@@ -243,6 +258,8 @@ public:
* strncpy(buf, str, sizeof(buf));
* NdbOperation->equal("Attr1", buf);
* @endcode
+ *
+ *
*
* @param anAttrName Attribute name
* @param aValue Attribute value.
@@ -260,21 +277,6 @@ public:
int equal(Uint32 anAttrId, Int64 aValue);
int equal(Uint32 anAttrId, Uint64 aValue);
- /**
- * Generate a tuple id and set it as search argument.
- *
- * The Tuple id has NDB$TID as attribute name and 0 as attribute id.
- *
- * The generated tuple id is returned by the method.
- * If zero is returned there is an error.
- *
- * This is mostly used for tables without any primary key
- * attributes.
- *
- * @return Generated tuple id if successful, otherwise 0.
- */
- Uint64 setTupleId();
-
/** @} *********************************************************************/
/**
* @name Specify Attribute Actions for Operations
@@ -301,7 +303,7 @@ public:
* @note This method does not fetch the attribute value from
* the database! The NdbRecAttr object returned by this method
* is <em>not</em> readable/printable before the
- * transaction has been executed with NdbConnection::execute.
+ * transaction has been executed with NdbTransaction::execute.
*
* @param anAttrName Attribute name
* @param aValue If this is non-NULL, then the attribute value
@@ -338,6 +340,12 @@ public:
* then the API will assume that the pointer
* is correct and not bother with checking it.
*
+ * @note For insertTuple() the NDB API will automatically detect that
+ * it is supposed to use equal() instead.
+ *
+ * @note For insertTuple() it is not necessary to use
+ * setValue() on key attributes before other attributes.
+ *
* @note There are 14 versions of NdbOperation::setValue with
* slightly different parameters.
*
@@ -374,6 +382,7 @@ public:
virtual NdbBlob* getBlobHandle(const char* anAttrName);
virtual NdbBlob* getBlobHandle(Uint32 anAttrId);
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/** @} *********************************************************************/
/**
* @name Specify Interpreted Program Instructions
@@ -586,21 +595,21 @@ public:
* @param Label label to jump to
* @return -1 if unsuccessful
*/
- int branch_col_eq(Uint32 ColId, const char * val, Uint32 len,
+ int branch_col_eq(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label);
- int branch_col_ne(Uint32 ColId, const char * val, Uint32 len,
+ int branch_col_ne(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label);
- int branch_col_lt(Uint32 ColId, const char * val, Uint32 len,
+ int branch_col_lt(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label);
- int branch_col_le(Uint32 ColId, const char * val, Uint32 len,
+ int branch_col_le(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label);
- int branch_col_gt(Uint32 ColId, const char * val, Uint32 len,
+ int branch_col_gt(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label);
- int branch_col_ge(Uint32 ColId, const char * val, Uint32 len,
+ int branch_col_ge(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label);
- int branch_col_like(Uint32 ColId, const char *, Uint32 len,
+ int branch_col_like(Uint32 ColId, const void *, Uint32 len,
bool nopad, Uint32 Label);
- int branch_col_notlike(Uint32 ColId, const char *, Uint32 len,
+ int branch_col_notlike(Uint32 ColId, const void *, Uint32 len,
bool nopad, Uint32 Label);
/**
@@ -672,6 +681,7 @@ public:
* @return -1 if unsuccessful.
*/
int ret_sub();
+#endif
/** @} *********************************************************************/
@@ -699,8 +709,14 @@ public:
*/
const char* getTableName() const;
+ /**
+ * Get table object for this operation
+ */
+ const NdbDictionary::Table * getTable() const;
+
/** @} *********************************************************************/
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Type of operation
*/
@@ -716,9 +732,26 @@ public:
NotDefined2, ///< Internal for debugging
NotDefined ///< Internal for debugging
};
+#endif
+ /**
+ * Return lock mode for operation
+ */
LockMode getLockMode() const { return theLockMode; }
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ void setAbortOption(Int8 ao) { m_abortOption = ao; }
+
+ /**
+ * Set/get partition key
+ */
+ void setPartitionId(Uint32 id);
+ void setPartitionHash(Uint32 key);
+ void setPartitionHash(const Uint64 *, Uint32 len);
+ Uint32 getPartitionId() const;
+#endif
+protected:
+ int handle_distribution_key(const Uint64 *, Uint32 len);
protected:
/******************************************************************************
* These are the methods used to create and delete the NdbOperation objects.
@@ -733,14 +766,20 @@ protected:
//--------------------------------------------------------------
// Initialise after allocating operation to a transaction
//--------------------------------------------------------------
- int init(const class NdbTableImpl*, NdbConnection* aCon);
+ int init(const class NdbTableImpl*, NdbTransaction* aCon);
void initInterpreter();
void next(NdbOperation*); // Set next pointer
-
NdbOperation* next(); // Get next pointer
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const NdbOperation* next() const;
+ const NdbRecAttr* getFirstRecAttr() const;
+#endif
+protected:
- enum OperationStatus{
+ enum OperationStatus
+ {
Init,
OperationDefined,
TupleKeyDefined,
@@ -761,7 +800,7 @@ protected:
void Status(OperationStatus); // Set the status information
- void NdbCon(NdbConnection*); // Set reference to connection
+ void NdbCon(NdbTransaction*); // Set reference to connection
// object.
virtual void release(); // Release all operations
@@ -798,7 +837,7 @@ protected:
virtual int equal_impl(const NdbColumnImpl*,const char* aValue, Uint32 len);
virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char* aValue = 0);
int setValue(const NdbColumnImpl* anAttrObject, const char* aValue, Uint32 len);
- NdbBlob* getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* anAttrObject);
+ NdbBlob* getBlobHandle(NdbTransaction* 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);
@@ -806,17 +845,16 @@ protected:
int read_attr(const NdbColumnImpl* anAttrObject, Uint32 RegDest);
int write_attr(const NdbColumnImpl* anAttrObject, Uint32 RegSource);
int branch_reg_reg(Uint32 type, Uint32, Uint32, Uint32);
- int branch_col(Uint32 type, Uint32, const char *, Uint32, bool, Uint32 Label);
+ int branch_col(Uint32 type, Uint32, const void *, Uint32, bool, Uint32 Label);
int branch_col_null(Uint32 type, Uint32 col, Uint32 Label);
// Handle ATTRINFO signals
- int insertATTRINFO(Uint32 aData);
- int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
-
- int insertKEYINFO(const char* aValue,
- Uint32 aStartPosition,
- Uint32 aKeyLenInByte,
- Uint32 anAttrBitsInLastWord);
+ int insertATTRINFO(Uint32 aData);
+ int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
+
+ int insertKEYINFO(const char* aValue,
+ Uint32 aStartPosition,
+ Uint32 aKeyLenInByte);
virtual void setErrorCode(int aErrorCode);
virtual void setErrorCodeAbort(int aErrorCode);
@@ -848,16 +886,20 @@ protected:
int theErrorLine; // Error line
Ndb* theNdb; // Point back to the Ndb object.
- NdbConnection* theNdbCon; // Point back to the connection object.
+ NdbTransaction* theNdbCon; // Point back to the connection object.
NdbOperation* theNext; // Next pointer to operation.
- NdbApiSignal* theTCREQ; // The TC[KEY/INDX]REQ signal object
+
+ union {
+ NdbApiSignal* theTCREQ; // The TC[KEY/INDX]REQ signal object
+ NdbApiSignal* theSCAN_TABREQ;
+ };
+
NdbApiSignal* theFirstATTRINFO; // The first ATTRINFO signal object
NdbApiSignal* theCurrentATTRINFO; // The current ATTRINFO signal object
Uint32 theTotalCurrAI_Len; // The total number of attribute info
// words currently defined
Uint32 theAI_LenInCurrAI; // The number of words defined in the
// current ATTRINFO signal
- NdbApiSignal* theFirstKEYINFO; // The first KEYINFO signal object
NdbApiSignal* theLastKEYINFO; // The first KEYINFO signal object
class NdbLabel* theFirstLabel;
@@ -874,8 +916,8 @@ protected:
Uint32* theKEYINFOptr; // Pointer to where to write KEYINFO
Uint32* theATTRINFOptr; // Pointer to where to write ATTRINFO
- const class NdbTableImpl* m_currentTable; // The current table
- const class NdbTableImpl* m_accessTable;
+ const class NdbTableImpl* m_currentTable; // The current table
+ const class NdbTableImpl* m_accessTable; // Index table (== current for pk)
// Set to TRUE when a tuple key attribute has been defined.
Uint32 theTupleKeyDefined[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY][3];
@@ -883,18 +925,18 @@ protected:
Uint32 theTotalNrOfKeyWordInSignal; // The total number of
// keyword in signal.
- Uint32 theTupKeyLen; // Length of the tuple key in words
- Uint32 theNoOfTupKeyDefined; // The number of tuple key attributes
- // currently defined
- OperationType theOperationType; // Read Request, Update Req......
-
+ Uint32 theTupKeyLen; // Length of the tuple key in words
+ // left until done
+ Uint8 theNoOfTupKeyLeft; // The number of tuple key attributes
+ OperationType theOperationType; // Read Request, Update Req......
+
LockMode theLockMode; // Can be set to WRITE if read operation
OperationStatus theStatus; // The status of the operation.
+
Uint32 theMagicNumber; // Magic number to verify that object
// is correct
Uint32 theScanInfo; // Scan info bits (take over flag etc)
- Uint32 theDistrKeySize; // Distribution Key size if used
- Uint32 theDistributionGroup; // Distribution Group if used
+ Uint32 theDistributionKey; // Distribution Key size if used
Uint32 theSubroutineSize; // Size of subroutines for interpretation
Uint32 theInitialReadSize; // Size of initial reads for interpretation
@@ -902,14 +944,12 @@ protected:
Uint32 theFinalUpdateSize; // Size of final updates for interpretation
Uint32 theFinalReadSize; // Size of final reads for interpretation
- Uint8 theStartIndicator; // Indicator of whether start operation
- Uint8 theCommitIndicator; // Indicator of whether commit operation
- Uint8 theSimpleIndicator; // Indicator of whether simple operation
- Uint8 theDirtyIndicator; // Indicator of whether dirty operation
- Uint8 theInterpretIndicator; // Indicator of whether interpreted operation
- Uint8 theDistrGroupIndicator; // Indicates whether distribution grp is used
- Uint8 theDistrGroupType; // Type of distribution group used
- Uint8 theDistrKeyIndicator; // Indicates whether distr. key is used
+ Uint8 theStartIndicator; // Indicator of whether start operation
+ Uint8 theCommitIndicator; // Indicator of whether commit operation
+ Uint8 theSimpleIndicator; // Indicator of whether simple operation
+ Uint8 theDirtyIndicator; // Indicator of whether dirty operation
+ Uint8 theInterpretIndicator; // Indicator of whether interpreted operation
+ Int8 theDistrKeyIndicator_; // Indicates whether distr. key is used
Uint16 m_tcReqGSN;
Uint16 m_keyInfoGSN;
@@ -931,6 +971,7 @@ protected:
#include <stdlib.h>
#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
inline
int
@@ -985,6 +1026,20 @@ NdbOperation::next()
return theNext;
}
+inline
+const NdbOperation*
+NdbOperation::next() const
+{
+ return theNext;
+}
+
+inline
+const NdbRecAttr*
+NdbOperation::getFirstRecAttr() const
+{
+ return theReceiver.theFirstRecAttr;
+}
+
/******************************************************************************
OperationStatus Status();
@@ -1014,14 +1069,14 @@ NdbOperation::Status( OperationStatus aStatus )
}
/******************************************************************************
-void NdbCon(NdbConnection* aNdbCon);
+void NdbCon(NdbTransaction* aNdbCon);
-Parameters: aNdbCon: Pointers to NdbConnection object.
+Parameters: aNdbCon: Pointers to NdbTransaction object.
Remark: Set the reference to the connection in the operation object.
******************************************************************************/
inline
void
-NdbOperation::NdbCon(NdbConnection* aNdbCon)
+NdbOperation::NdbCon(NdbTransaction* aNdbCon)
{
theNdbCon = aNdbCon;
}
@@ -1166,4 +1221,6 @@ NdbOperation::setValue(Uint32 anAttrId, double aPar)
return setValue(anAttrId, (const char*)&aPar, (Uint32)8);
}
+#endif // doxygen
+
#endif
diff --git a/ndb/include/ndbapi/NdbRecAttr.hpp b/ndb/include/ndbapi/NdbRecAttr.hpp
index 05635a99385..50de4f3277e 100644
--- a/ndb/include/ndbapi/NdbRecAttr.hpp
+++ b/ndb/include/ndbapi/NdbRecAttr.hpp
@@ -34,23 +34,22 @@ class NdbOperation;
* MyRecAttr = MyOperation->getValue("ATTR2", NULL);
* if (MyRecAttr == NULL) goto error;
*
- * if (MyConnection->execute(Commit) == -1) goto error;
+ * if (MyTransaction->execute(Commit) == -1) goto error;
*
* ndbout << MyRecAttr->u_32_value();
* @endcode
* For more examples, see
- * @ref ndbapi_example1.cpp and
- * @ref ndbapi_example2.cpp.
+ * @ref ndbapi_simple.cpp.
*
* @note The NdbRecAttr object is instantiated with its value when
- * NdbConnection::execute is called. Before this, the value is
+ * NdbTransaction::execute is called. Before this, the value is
* undefined. (NdbRecAttr::isNULL can be used to check
* if the value is defined or not.)
* This means that an NdbRecAttr object only has valid information
- * between the time of calling NdbConnection::execute and
+ * between the time of calling NdbTransaction::execute and
* the time of Ndb::closeTransaction.
* The value of the null indicator is -1 until the
- * NdbConnection::execute method have been called.
+ * NdbTransaction::execute method have been called.
*
* For simple types, there are methods which directly getting the value
* from the NdbRecAttr object.
@@ -72,12 +71,14 @@ class NdbOperation;
*/
class NdbRecAttr
{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbOperation;
friend class NdbIndexScanOperation;
friend class NdbEventOperationImpl;
friend class NdbReceiver;
friend class Ndb;
friend class NdbOut& operator<<(class NdbOut&, const class AttributeS&);
+#endif
public:
/**
@@ -124,7 +125,7 @@ public:
* Check if attribute value is NULL.
*
* @return -1 = Not defined (Failure or
- * NdbConnection::execute not yet called).<br>
+ * NdbTransaction::execute not yet called).<br>
* 0 = Attribute value is defined, but not equal to NULL.<br>
* 1 = Attribute value is defined and equal to NULL.
*/
@@ -241,18 +242,24 @@ public:
* i.e. objects that has been cloned.
*/
~NdbRecAttr();
+
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const NdbRecAttr* next() const;
+#endif
private:
NdbRecAttr();
Uint32 attrId() const; /* Get attribute id */
bool setNULL(); /* Set NULL indicator */
+ void setUNDEFINED(); /* Set UNDEFINED indicator */
bool receive_data(const Uint32*, Uint32);
void release(); /* Release memory if allocated */
void init(); /* Initialise object when allocated */
void next(NdbRecAttr* aRecAttr);
- NdbRecAttr* next() const;
+ NdbRecAttr* next();
int setup(const class NdbDictionary::Column* col, char* aValue);
int setup(const class NdbColumnImpl* anAttrInfo, char* aValue);
@@ -275,6 +282,8 @@ private:
const NdbDictionary::Column* m_column;
};
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
inline
NdbDictionary::Column::Type
NdbRecAttr::getType() const {
@@ -373,6 +382,13 @@ NdbRecAttr::next(NdbRecAttr* aRecAttr)
inline
NdbRecAttr*
+NdbRecAttr::next()
+{
+ return theNext;
+}
+
+inline
+const NdbRecAttr*
NdbRecAttr::next() const
{
return theNext;
@@ -408,6 +424,13 @@ NdbRecAttr::setNULL()
}
inline
+void
+NdbRecAttr::setUNDEFINED()
+{
+ theNULLind = -1;
+}
+
+inline
int
NdbRecAttr::isNULL() const
{
@@ -416,5 +439,7 @@ NdbRecAttr::isNULL() const
class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &);
+#endif // ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
#endif
diff --git a/ndb/include/ndbapi/NdbReceiver.hpp b/ndb/include/ndbapi/NdbReceiver.hpp
index af624f69bd3..ff6debc7fd3 100644
--- a/ndb/include/ndbapi/NdbReceiver.hpp
+++ b/ndb/include/ndbapi/NdbReceiver.hpp
@@ -21,7 +21,7 @@
#include <ndb_types.h>
class Ndb;
-class NdbConnection;
+class NdbTransaction;
class NdbReceiver
{
@@ -30,7 +30,7 @@ class NdbReceiver
friend class NdbScanOperation;
friend class NdbIndexOperation;
friend class NdbIndexScanOperation;
- friend class NdbConnection;
+ friend class NdbTransaction;
public:
enum ReceiverType { NDB_UNINITIALIZED,
NDB_OPERATION = 1,
@@ -51,7 +51,7 @@ public:
return m_type;
}
- inline NdbConnection * getTransaction();
+ inline NdbTransaction * getTransaction();
void* getOwner(){
return m_owner;
}
@@ -67,7 +67,7 @@ private:
Ndb* m_ndb;
Uint32 m_id;
Uint32 m_tcPtrI;
- Uint32 m_key_info;
+ Uint32 m_hidden_count;
ReceiverType m_type;
void* m_owner;
NdbReceiver* m_next;
@@ -76,7 +76,7 @@ private:
* At setup
*/
class NdbRecAttr * getValue(const class NdbColumnImpl*, char * user_dst_ptr);
- void do_get_value(NdbReceiver*, Uint32 rows, Uint32 key_size);
+ void do_get_value(NdbReceiver*, Uint32 rows, Uint32 key_size, Uint32 range);
void prepareSend();
void calculate_batch_size(Uint32, Uint32, Uint32&, Uint32&, Uint32&);
@@ -97,7 +97,7 @@ private:
Uint32 m_received_result_length;
bool nextResult() const { return m_current_row < m_result_rows; }
- void copyout(NdbReceiver&);
+ NdbRecAttr* copyout(NdbReceiver&);
};
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -146,5 +146,5 @@ NdbReceiver::execSCANOPCONF(Uint32 tcPtrI, Uint32 len, Uint32 rows){
return (tmp == len ? 1 : 0);
}
-#endif
+#endif // DOXYGEN_SHOULD_SKIP_INTERNAL
#endif
diff --git a/ndb/include/ndbapi/NdbResultSet.hpp b/ndb/include/ndbapi/NdbResultSet.hpp
deleted file mode 100644
index dc0288a380c..00000000000
--- a/ndb/include/ndbapi/NdbResultSet.hpp
+++ /dev/null
@@ -1,162 +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: NdbResultSet.hpp
- * Include:
- * Link:
- * Author: Martin Sköld
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Cursor class
- * Documentation:
- * Adjust: 2002-04-01 Martin Sköld First version.
- ****************************************************************************/
-
-#ifndef NdbResultSet_H
-#define NdbResultSet_H
-
-
-#include <NdbScanOperation.hpp>
-
-/**
- * @class NdbResultSet
- * @brief NdbResultSet contains a NdbScanOperation.
- */
-class NdbResultSet
-{
- friend class NdbScanOperation;
-
-public:
-
- /**
- * Get the next tuple in a scan transaction.
- *
- * After each call to NdbResult::nextResult
- * the buffers and NdbRecAttr objects defined in
- * NdbOperation::getValue are updated with values
- * from the scanned tuple.
- *
- * @param fetchAllowed If set to false, then fetching is disabled
- *
- * The NDB API will contact the NDB Kernel for more tuples
- * when necessary to do so unless you set the fetchAllowed
- * to false.
- * This will force NDB to process any records it
- * already has in it's caches. When there are no more cached
- * records it will return 2. You must then call nextResult
- * with fetchAllowed = true in order to contact NDB for more
- * records.
- *
- * fetchAllowed = false is useful when you want to update or
- * delete all the records fetched in one transaction(This will save a
- * lot of round trip time and make updates or deletes of scanned
- * records a lot faster).
- * While nextResult(false)
- * returns 0 take over the record to another transaction. When
- * nextResult(false) returns 2 you must execute and commit the other
- * transaction. This will cause the locks to be transferred to the
- * other transaction, updates or deletes will be made and then the
- * locks will be released.
- * After that, call nextResult(true) which will fetch new records and
- * cache them in the NdbApi.
- *
- * @note If you don't take over the records to another transaction the
- * locks on those records will be released the next time NDB Kernel
- * is contacted for more records.
- *
- * @note Please contact for examples of efficient scan
- * updates and deletes.
- *
- * @note See ndb/examples/ndbapi_scan_example for usage.
- *
- * @return
- * - -1: if unsuccessful,<br>
- * - 0: if another tuple was received, and<br>
- * - 1: if there are no more tuples to scan.
- * - 2: if there are no more cached records in NdbApi
- */
- int nextResult(bool fetchAllowed = true, bool forceSend = false);
-
- /**
- * Close result set (scan)
- */
- void close(bool forceSend = false);
-
- /**
- * Restart
- */
- int restart(bool forceSend = false);
-
- /**
- * Transfer scan operation to an updating transaction. Use this function
- * when a scan has found a record that you want to update.
- * 1. Start a new transaction.
- * 2. Call the function takeOverForUpdate using your new transaction
- * as parameter, all the properties of the found record will be copied
- * to the new transaction.
- * 3. When you execute the new transaction, the lock held by the scan will
- * be transferred to the new transaction(it's taken over).
- *
- * @note You must have started the scan with openScanExclusive
- * to be able to update the found tuple.
- *
- * @param updateTrans the update transaction connection.
- * @return an NdbOperation or NULL.
- */
- NdbOperation* updateTuple();
- NdbOperation* updateTuple(NdbConnection* updateTrans);
-
- /**
- * Transfer scan operation to a deleting transaction. Use this function
- * when a scan has found a record that you want to delete.
- * 1. Start a new transaction.
- * 2. Call the function takeOverForDelete using your new transaction
- * as parameter, all the properties of the found record will be copied
- * to the new transaction.
- * 3. When you execute the new transaction, the lock held by the scan will
- * be transferred to the new transaction(its taken over).
- *
- * @note You must have started the scan with openScanExclusive
- * to be able to delete the found tuple.
- *
- * @param deleteTrans the delete transaction connection.
- * @return an NdbOperation or NULL.
- */
- int deleteTuple();
- int deleteTuple(NdbConnection* takeOverTransaction);
-
- /**
- * Get underlying operation
- */
- NdbOperation* getOperation();
-private:
- NdbResultSet(NdbScanOperation*);
-
- ~NdbResultSet();
-
- void init();
-
- NdbScanOperation* m_operation;
-};
-
-inline
-NdbOperation*
-NdbResultSet::getOperation(){
- return m_operation;
-}
-
-#endif
diff --git a/ndb/include/ndbapi/NdbScanFilter.hpp b/ndb/include/ndbapi/NdbScanFilter.hpp
index 9f8a01b1059..b5457bab99b 100644
--- a/ndb/include/ndbapi/NdbScanFilter.hpp
+++ b/ndb/include/ndbapi/NdbScanFilter.hpp
@@ -45,7 +45,19 @@ public:
NAND = 3, ///< NOT (x1 AND x2 AND x3)
NOR = 4 ///< NOT (x1 OR x2 OR x3)
};
-
+
+ enum BinaryCondition
+ {
+ COND_LE = 0, ///< lower bound
+ COND_LT = 1, ///< lower bound, strict
+ COND_GE = 2, ///< upper bound
+ COND_GT = 3, ///< upper bound, strict
+ COND_EQ = 4, ///< equality
+ COND_NE = 5, ///< not equal
+ COND_LIKE = 6, ///< like
+ COND_NOT_LIKE = 7 ///< not like
+ };
+
/**
* @name Grouping
* @{
@@ -74,7 +86,12 @@ public:
* <i>Explanation missing</i>
*/
int isfalse();
-
+
+ /**
+ * Compare column <b>ColId</b> with <b>val</b>
+ */
+ int cmp(BinaryCondition cond, int ColId, const void *val, Uint32 len = 0);
+
/**
* @name Integer Comparators
* @{
@@ -82,80 +99,61 @@ public:
/** Compare column value with integer for equal
* ®return 0 if successful, -1 otherwize
*/
- int eq(int ColId, Uint32 value);
+ int eq(int ColId, Uint32 value) { return cmp(COND_EQ, ColId, &value, 4);}
+
/** Compare column value with integer for not equal.
* ®return 0 if successful, -1 otherwize
*/
- int ne(int ColId, Uint32 value);
+ int ne(int ColId, Uint32 value) { return cmp(COND_NE, ColId, &value, 4);}
/** Compare column value with integer for less than.
* ®return 0 if successful, -1 otherwize
*/
- int lt(int ColId, Uint32 value);
+ int lt(int ColId, Uint32 value) { return cmp(COND_LT, ColId, &value, 4);}
/** Compare column value with integer for less than or equal.
* ®return 0 if successful, -1 otherwize
*/
- int le(int ColId, Uint32 value);
+ int le(int ColId, Uint32 value) { return cmp(COND_LE, ColId, &value, 4);}
/** Compare column value with integer for greater than.
* ®return 0 if successful, -1 otherwize
*/
- int gt(int ColId, Uint32 value);
+ int gt(int ColId, Uint32 value) { return cmp(COND_GT, ColId, &value, 4);}
/** Compare column value with integer for greater than or equal.
* ®return 0 if successful, -1 otherwize
*/
- int ge(int ColId, Uint32 value);
+ int ge(int ColId, Uint32 value) { return cmp(COND_GE, ColId, &value, 4);}
/** Compare column value with integer for equal. 64-bit.
* ®return 0 if successful, -1 otherwize
*/
- int eq(int ColId, Uint64 value);
+ int eq(int ColId, Uint64 value) { return cmp(COND_EQ, ColId, &value, 8);}
/** Compare column value with integer for not equal. 64-bit.
* ®return 0 if successful, -1 otherwize
*/
- int ne(int ColId, Uint64 value);
+ int ne(int ColId, Uint64 value) { return cmp(COND_NE, ColId, &value, 8);}
/** Compare column value with integer for less than. 64-bit.
* ®return 0 if successful, -1 otherwize
*/
- int lt(int ColId, Uint64 value);
+ int lt(int ColId, Uint64 value) { return cmp(COND_LT, ColId, &value, 8);}
/** Compare column value with integer for less than or equal. 64-bit.
* ®return 0 if successful, -1 otherwize
*/
- int le(int ColId, Uint64 value);
+ int le(int ColId, Uint64 value) { return cmp(COND_LE, ColId, &value, 8);}
/** Compare column value with integer for greater than. 64-bit.
* ®return 0 if successful, -1 otherwize
*/
- int gt(int ColId, Uint64 value);
+ int gt(int ColId, Uint64 value) { return cmp(COND_GT, ColId, &value, 8);}
/** Compare column value with integer for greater than or equal. 64-bit.
* ®return 0 if successful, -1 otherwize
*/
- int ge(int ColId, Uint64 value);
+ int ge(int ColId, Uint64 value) { return cmp(COND_GE, ColId, &value, 8);}
/** @} *********************************************************************/
/** Check if column value is NULL */
int isnull(int ColId);
/** Check if column value is non-NULL */
int isnotnull(int ColId);
-
- /**
- * @name String Comparators
- * @{
- */
- /**
- * Compare string against a Char or Varchar column.
- *
- * By default Char comparison blank-pads both sides to common length.
- * Varchar comparison does not blank-pad.
- *
- * The extra <i>nopad</i> argument can be used to
- * force non-padded comparison for a Char column.
- * ®return 0 if successful, -1 otherwize
- */
- int eq(int ColId, const char * val, Uint32 len, bool nopad=false);
- int ne(int ColId, const char * val, Uint32 len, bool nopad=false);
- int lt(int ColId, const char * val, Uint32 len, bool nopad=false);
- int le(int ColId, const char * val, Uint32 len, bool nopad=false);
- int gt(int ColId, const char * val, Uint32 len, bool nopad=false);
- int ge(int ColId, const char * val, Uint32 len, bool nopad=false);
-
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Like comparison operator.
* ®return 0 if successful, -1 otherwize
@@ -167,9 +165,12 @@ public:
*/
int notlike(int ColId, const char * val, Uint32 len, bool nopad=false);
/** @} *********************************************************************/
+#endif
private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbScanFilterImpl;
+#endif
class NdbScanFilterImpl & m_impl;
NdbScanFilter& operator=(const NdbScanFilter&); ///< Defined not implemented
};
diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp
index f6e68dd4abe..bf8f362cefc 100644
--- a/ndb/include/ndbapi/NdbScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -14,18 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbScanOperation.hpp
- * Include:
- * Link:
- * Author: Martin Sköld
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Table scan support
- * Documentation:
- * Adjust: 2002-04-01 Martin Sköld First version.
- ****************************************************************************/
-
#ifndef NdbScanOperation_H
#define NdbScanOperation_H
@@ -39,68 +27,169 @@ class NdbResultSet;
* @brief Class of scan operations for use in transactions.
*/
class NdbScanOperation : public NdbOperation {
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class Ndb;
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class NdbResultSet;
friend class NdbOperation;
friend class NdbBlob;
+#endif
+
public:
/**
- * Type of cursor
+ * Scan flags. OR-ed together and passed as second argument to
+ * readTuples.
*/
- enum CursorType {
- NoCursor = 0,
- ScanCursor = 1,
- IndexCursor = 2
+ enum ScanFlag {
+ SF_TupScan = (1 << 16), // scan TUP - only LM_CommittedRead
+ SF_OrderBy = (1 << 24), // index scan in order
+ SF_Descending = (2 << 24), // index scan in descending order
+ SF_ReadRangeNo = (4 << 24) // enable @ref get_range_no
};
/**
- * Type of cursor
- */
- CursorType get_cursor_type() const;
+ * readTuples
+ *
+ * @param lock_mode Lock mode
+ * @param scan_flags see @ref ScanFlag
+ * @param parallel No of fragments to scan in parallel (0=max)
+ */
+ virtual
+ int readTuples(LockMode lock_mode = LM_Read,
+ Uint32 scan_flags = 0, Uint32 parallel = 0);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
- * readTuples returns a NdbResultSet where tuples are stored.
- * Tuples are not stored in NdbResultSet until execute(NoCommit)
- * has been executed and nextResult has been called.
+ * readTuples
*
- * @param parallel Scan parallelism
+ * @param lock_mode Lock mode
* @param batch No of rows to fetch from each fragment at a time
- * @param LockMode Scan lock handling
- * @returns NdbResultSet.
+ * @param parallel No of fragments to scan in parallell
* @note specifying 0 for batch and parallall means max performance
*/
- NdbResultSet* readTuples(LockMode = LM_Read,
- Uint32 batch = 0, Uint32 parallel = 0);
+#ifdef ndb_readtuples_impossible_overload
+ int readTuples(LockMode lock_mode = LM_Read,
+ Uint32 batch = 0, Uint32 parallel = 0);
+#endif
- inline NdbResultSet* readTuples(int parallell){
+ inline int readTuples(int parallell){
return readTuples(LM_Read, 0, parallell);
}
- inline NdbResultSet* readTuplesExclusive(int parallell = 0){
+ inline int readTuplesExclusive(int parallell = 0){
return readTuples(LM_Exclusive, 0, parallell);
}
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
NdbBlob* getBlobHandle(const char* anAttrName);
NdbBlob* getBlobHandle(Uint32 anAttrId);
+#endif
-protected:
- CursorType m_cursor_type;
+ /**
+ * Get the next tuple in a scan transaction.
+ *
+ * After each call to nextResult
+ * the buffers and NdbRecAttr objects defined in
+ * NdbOperation::getValue are updated with values
+ * from the scanned tuple.
+ *
+ * @param fetchAllowed If set to false, then fetching is disabled
+ * @param forceSend If true send will occur immediately (see @ref secAdapt)
+ *
+ * The NDB API will contact the NDB Kernel for more tuples
+ * when necessary to do so unless you set the fetchAllowed
+ * to false.
+ * This will force NDB to process any records it
+ * already has in it's caches. When there are no more cached
+ * records it will return 2. You must then call nextResult
+ * with fetchAllowed = true in order to contact NDB for more
+ * records.
+ *
+ * fetchAllowed = false is useful when you want to update or
+ * delete all the records fetched in one transaction(This will save a
+ * lot of round trip time and make updates or deletes of scanned
+ * records a lot faster).
+ * While nextResult(false)
+ * returns 0 take over the record to another transaction. When
+ * nextResult(false) returns 2 you must execute and commit the other
+ * transaction. This will cause the locks to be transferred to the
+ * other transaction, updates or deletes will be made and then the
+ * locks will be released.
+ * After that, call nextResult(true) which will fetch new records and
+ * cache them in the NdbApi.
+ *
+ * @note If you don't take over the records to another transaction the
+ * locks on those records will be released the next time NDB Kernel
+ * is contacted for more records.
+ *
+ * @note Please contact for examples of efficient scan
+ * updates and deletes.
+ *
+ * @note See ndb/examples/ndbapi_scan_example for usage.
+ *
+ * @return
+ * - -1: if unsuccessful,<br>
+ * - 0: if another tuple was received, and<br>
+ * - 1: if there are no more tuples to scan.
+ * - 2: if there are no more cached records in NdbApi
+ */
+ int nextResult(bool fetchAllowed = true, bool forceSend = false);
+
+ /**
+ * Close scan
+ */
+ void close(bool forceSend = false, bool releaseOp = false);
+
+ /**
+ * Update current tuple
+ *
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* updateCurrentTuple();
+ /**
+ * Update current tuple
+ *
+ * @param updateTrans Transaction that should perform the update
+ *
+ * @return an NdbOperation or NULL.
+ */
+ NdbOperation* updateCurrentTuple(NdbTransaction* updateTrans);
+ /**
+ * Delete current tuple
+ * @return 0 on success or -1 on failure
+ */
+ int deleteCurrentTuple();
+ /**
+ * Delete current tuple
+ *
+ * @param takeOverTransaction Transaction that should perform the delete
+ *
+ * @return 0 on success or -1 on failure
+ */
+ int deleteCurrentTuple(NdbTransaction* takeOverTransaction);
+
+ /**
+ * Restart scan with exactly the same
+ * getValues and search conditions
+ */
+ int restart(bool forceSend = false);
+
+protected:
NdbScanOperation(Ndb* aNdb);
virtual ~NdbScanOperation();
- int nextResult(bool fetchAllowed = true, bool forceSend = false);
+ int nextResultImpl(bool fetchAllowed = true, bool forceSend = false);
virtual void release();
- void closeScan(bool forceSend = false, bool releaseOp = false);
int close_impl(class TransporterFacade*, bool forceSend = false);
// Overloaded methods from NdbCursorOperation
int executeCursor(int ProcessorId);
// Overloaded private methods from NdbOperation
- int init(const NdbTableImpl* tab, NdbConnection* myConnection);
+ int init(const NdbTableImpl* tab, NdbTransaction*);
int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId);
int doSend(int ProcessorId);
void checkForceSend(bool forceSend);
@@ -108,14 +197,11 @@ protected:
virtual void setErrorCode(int aErrorCode);
virtual void setErrorCodeAbort(int aErrorCode);
- NdbResultSet * m_resultSet;
- NdbResultSet* getResultSet();
- NdbConnection *m_transConnection;
+ NdbTransaction *m_transConnection;
// Scan related variables
Uint32 theParallelism;
Uint32 m_keyInfo;
- NdbApiSignal* theSCAN_TABREQ;
int getFirstATTRINFOScan();
int doSendScan(int ProcessorId);
@@ -154,17 +240,41 @@ protected:
void execCLOSE_SCAN_REP();
int getKeyFromKEYINFO20(Uint32* data, unsigned size);
- NdbOperation* takeOverScanOp(OperationType opType, NdbConnection*);
+ NdbOperation* takeOverScanOp(OperationType opType, NdbTransaction*);
- Uint32 m_ordered;
-
- int restart(bool forceSend = false);
+ bool m_ordered;
+ bool m_descending;
+ Uint32 m_read_range_no;
+ NdbRecAttr *m_curr_row; // Pointer to last returned row
};
inline
-NdbScanOperation::CursorType
-NdbScanOperation::get_cursor_type() const {
- return m_cursor_type;
+NdbOperation*
+NdbScanOperation::updateCurrentTuple(){
+ return updateCurrentTuple(m_transConnection);
+}
+
+inline
+NdbOperation*
+NdbScanOperation::updateCurrentTuple(NdbTransaction* takeOverTrans){
+ return takeOverScanOp(NdbOperation::UpdateRequest,
+ takeOverTrans);
+}
+
+inline
+int
+NdbScanOperation::deleteCurrentTuple(){
+ return deleteCurrentTuple(m_transConnection);
+}
+
+inline
+int
+NdbScanOperation::deleteCurrentTuple(NdbTransaction * takeOverTrans){
+ void * res = takeOverScanOp(NdbOperation::DeleteRequest,
+ takeOverTrans);
+ if(res == 0)
+ return -1;
+ return 0;
}
#endif
diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbTransaction.hpp
index 2ab6f7d6f64..2e102b104d8 100644
--- a/ndb/include/ndbapi/NdbConnection.hpp
+++ b/ndb/include/ndbapi/NdbTransaction.hpp
@@ -14,14 +14,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifndef NdbConnection_H
-#define NdbConnection_H
+#ifndef NdbTransaction_H
+#define NdbTransaction_H
#include <ndb_types.h>
#include <NdbError.hpp>
#include <NdbDictionary.hpp>
-class NdbConnection;
+class NdbTransaction;
class NdbOperation;
class NdbScanOperation;
class NdbIndexScanOperation;
@@ -30,106 +30,81 @@ class NdbApiSignal;
class Ndb;
class NdbBlob;
-
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+// to be documented later
/**
* NdbAsynchCallback functions are used when executing asynchronous
- * transactions (using NdbConnection::executeAsynchPrepare, or
- * NdbConnection::executeAsynch).
+ * transactions (using NdbTransaction::executeAsynchPrepare, or
+ * NdbTransaction::executeAsynch).
* The functions are called when the execute has finished.
* See @ref secAsync for more information.
*/
-typedef void (* NdbAsynchCallback)(int, NdbConnection*, void*);
+typedef void (* NdbAsynchCallback)(int, NdbTransaction*, void*);
+#endif
-/**
- * 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
- AO_IgnoreError = 2 ///< Transaction continues on failed operation
+enum AbortOption {
+ CommitIfFailFree= 0,
+ TryCommit= 0,
+ AbortOnError= 0,
+ CommitAsMuchAsPossible= 2,
+ AO_IgnoreError= 2
};
-
-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
+ NoExecTypeDef = -1,
+ Prepare,
+ NoCommit,
+ Commit,
+ Rollback
};
-
+#endif
/**
- * @class NdbConnection
+ * @class NdbTransaction
* @brief Represents a transaction.
*
- * A transaction (represented by an NdbConnection object)
- * belongs to an Ndb object and is typically created using
- * Ndb::startTransaction.
+ * A transaction (represented by an NdbTransaction object)
+ * belongs to an Ndb object and is created using
+ * Ndb::startTransaction().
* A transaction consists of a list of operations
- * (represented by NdbOperation objects).
+ * (represented by NdbOperation, NdbScanOperation, NdbIndexOperation,
+ * and NdbIndexScanOperation objects).
* Each operation access exactly one table.
*
- * After getting the NdbConnection object,
- * the first step is to get (allocate) an operation given the table name.
+ * After getting the NdbTransaction object,
+ * the first step is to get (allocate) an operation given the table name using
+ * one of the methods getNdbOperation(), getNdbScanOperation(),
+ * getNdbIndexOperation(), or getNdbIndexScanOperation().
* Then the operation is defined.
- * Several operations can be defined in parallel on the same
- * NdbConnection object.
- * When all operations are defined, the NdbConnection::execute
- * method sends them to the NDB kernel for execution.
+ * Several operations can be defined on the same
+ * NdbTransaction object, they will in that case be executed in parallell.
+ * When all operations are defined, the execute()
+ * method sends them to the NDB kernel for execution.
*
- * The NdbConnection::execute method returns when the NDB kernel has
+ * The execute() method returns when the NDB kernel has
* completed execution of all operations defined before the call to
- * NdbConnection::execute.
- * All allocated operations should be properly defined
- * before calling NdbConnection::execute.
+ * execute(). All allocated operations should be properly defined
+ * before calling execute().
*
- * A call to NdbConnection::execute uses one out of three types of execution:
- * -# ExecType::NoCommit Executes operations without committing them.
- * -# ExecType::Commit Executes remaining operation and commits the
+ * A call to execute() uses one out of three types of execution:
+ * -# NdbTransaction::NoCommit Executes operations without committing them.
+ * -# NdbTransaction::Commit Executes remaining operation and commits the
* complete transaction
- * -# ExecType::Rollback Rollbacks the entire transaction.
+ * -# NdbTransaction::Rollback Rollbacks the entire transaction.
*
- * NdbConnection::execute is equipped with an extra error handling parameter
+ * execute() is equipped with an extra error handling parameter.
* There are two alternatives:
- * -# AbortOption::AbortOnError (default).
+ * -# NdbTransaction::AbortOnError (default).
* The transaction is aborted if there are any error during the
* execution
- * -# AbortOption::IgnoreError
+ * -# NdbTransaction::AO_IgnoreError
* Continue execution of transaction even if operation fails
*
- * NdbConnection::execute can sometimes indicate an error
- * (return with -1) while the error code on the NdbConnection is 0.
- * This is an indication that one of the operations found a record
- * problem. The transaction is still ok and can continue as usual.
- * The NdbConnection::execute returns -1 together with error code
- * on NdbConnection object equal to 0 always means that an
- * operation was not successful but that the total transaction was OK.
- * By checking error codes on the individual operations it is possible
- * to find out which operation was not successful.
- *
- * NdbConnection::executeScan is used to setup a scan in the NDB kernel
- * after it has been defined.
- * NdbConnection::nextScanResult is used to iterate through the
- * scanned tuples.
- * After each call to NdbConnection::nextScanResult, the pointers
- * of NdbRecAttr objects defined in the NdbOperation::getValue
- * operations are updated with the values of the new the scanned tuple.
*/
/* FUTURE IMPLEMENTATION:
* Later a prepare mode will be added when Ndb supports Prepare-To-Commit
- * The NdbConnection can deliver the Transaction Id of the transaction.
+ * The NdbTransaction can deliver the Transaction Id of the transaction.
* After committing a transaction it is also possible to retrieve the
* global transaction checkpoint which the transaction was put in.
*
@@ -148,24 +123,66 @@ enum ExecType {
* not known the table of the tuple. As long as the table is
* derived from the known base class everything is ok.
* It is not possible to provide any primary key since it is
- * already supplied with the call to NdbConnection::getNdbOperation.
+ * already supplied with the call to NdbTransaction::getNdbOperation.
* -# The third method is used when a scanned tuple is to be transferred to
* another transaction. In this case it is not possible to define the
* primary key since it came along from the scanned tuple.
*
*/
-class NdbConnection
+
+class NdbTransaction
{
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class Ndb;
friend class NdbOperation;
friend class NdbScanOperation;
friend class NdbIndexOperation;
friend class NdbIndexScanOperation;
friend class NdbBlob;
-
+#endif
+
public:
/**
+ * Commit type of transaction
+ */
+ enum AbortOption {
+ AbortOnError= ///< Abort transaction on failed operation
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ::AbortOnError
+#endif
+ ,AO_IgnoreError= ///< Transaction continues on failed operation
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ::AO_IgnoreError
+#endif
+ };
+
+ /**
+ * Execution type of transaction
+ */
+ enum ExecType {
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ NoExecTypeDef=
+ ::NoExecTypeDef, ///< Erroneous type (Used for debugging only)
+ Prepare= ::Prepare, ///< <i>Missing explanation</i>
+#endif
+ NoCommit= ///< Execute the transaction as far as it has
+ ///< been defined, but do not yet commit it
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ::NoCommit
+#endif
+ ,Commit= ///< Execute and try to commit the transaction
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ ::Commit
+#endif
+ ,Rollback ///< Rollback transaction
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ = ::Rollback
+#endif
+ };
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
* Get an NdbOperation for a table.
* Note that the operation has to be defined before it is executed.
*
@@ -176,41 +193,100 @@ public:
* @return Pointer to an NdbOperation object if successful, otherwise NULL.
*/
NdbOperation* getNdbOperation(const char* aTableName);
+#endif
/**
+ * Get an NdbOperation for a table.
+ * Note that the operation has to be defined before it is executed.
+ *
+ * @note All operations within the same transaction need to
+ * be initialized with this method.
+ *
+ * @param aTable
+ * A table object (fetched by NdbDictionary::Dictionary::getTable)
+ * @return Pointer to an NdbOperation object if successful, otherwise NULL.
+ */
+ NdbOperation* getNdbOperation(const NdbDictionary::Table * aTable);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
* Get an operation from NdbScanOperation idlelist and
- * get the NdbConnection object which
+ * get the NdbTransaction object which
* was fetched by startTransaction pointing to this operation.
*
- * @param aTableName a table name.
+ * @param aTableName The table name.
* @return pointer to an NdbOperation object if successful, otherwise NULL
*/
NdbScanOperation* getNdbScanOperation(const char* aTableName);
+#endif
/**
* Get an operation from NdbScanOperation idlelist and
- * get the NdbConnection object which
+ * get the NdbTransaction object which
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param aTable
+ * A table object (fetched by NdbDictionary::Dictionary::getTable)
+ * @return pointer to an NdbOperation object if successful, otherwise NULL
+ */
+ NdbScanOperation* getNdbScanOperation(const NdbDictionary::Table * aTable);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
+ * Get an operation from NdbIndexScanOperation idlelist and
+ * get the NdbTransaction object which
* was fetched by startTransaction pointing to this operation.
*
* @param anIndexName The index name.
- * @param aTableName a table name.
+ * @param aTableName The table name.
* @return pointer to an NdbOperation object if successful, otherwise NULL
*/
NdbIndexScanOperation* getNdbIndexScanOperation(const char* anIndexName,
const char* aTableName);
+ NdbIndexScanOperation* getNdbIndexScanOperation
+ (const NdbDictionary::Index *anIndex, const NdbDictionary::Table *aTable);
+#endif
/**
+ * Get an operation from NdbIndexScanOperation idlelist and
+ * get the NdbTransaction object which
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param anIndex
+ An index object (fetched by NdbDictionary::Dictionary::getIndex).
+ * @return pointer to an NdbOperation object if successful, otherwise NULL
+ */
+ NdbIndexScanOperation* getNdbIndexScanOperation
+ (const NdbDictionary::Index *anIndex);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
* Get an operation from NdbIndexOperation idlelist and
- * get the NdbConnection object that
+ * get the NdbTransaction object that
* was fetched by startTransaction pointing to this operation.
*
- * @param indexName An index name (as created by createIndex).
- * @param tableName A table name.
+ * @param anIndexName The index name (as created by createIndex).
+ * @param aTableName The table name.
* @return Pointer to an NdbIndexOperation object if
* successful, otherwise NULL
*/
- NdbIndexOperation* getNdbIndexOperation(const char* indexName,
- const char* tableName);
+ NdbIndexOperation* getNdbIndexOperation(const char* anIndexName,
+ const char* aTableName);
+ NdbIndexOperation* getNdbIndexOperation(const NdbDictionary::Index *anIndex,
+ const NdbDictionary::Table *aTable);
+#endif
+
+ /**
+ * Get an operation from NdbIndexOperation idlelist and
+ * get the NdbTransaction object that
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param anIndex
+ * An index object (fetched by NdbDictionary::Dictionary::getIndex).
+ * @return Pointer to an NdbIndexOperation object if
+ * successful, otherwise NULL
+ */
+ NdbIndexOperation* getNdbIndexOperation(const NdbDictionary::Index *anIndex);
/**
* @name Execute Transaction
@@ -238,10 +314,18 @@ public:
* the send.
* @return 0 if successful otherwise -1.
*/
- int execute(ExecType execType,
+ int execute(ExecType execType,
AbortOption abortOption = AbortOnError,
int force = 0 );
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ int execute(::ExecType execType,
+ ::AbortOption abortOption = ::AbortOnError,
+ int force = 0 )
+ { return execute ((ExecType)execType,(AbortOption)abortOption,force); }
+#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ // to be documented later
/**
* Prepare an asynchronous transaction.
*
@@ -255,7 +339,7 @@ public:
* ExecType::Rollback rollbacks the entire transaction.
* @param callback A callback method. This method gets
* called when the transaction has been
- * executed. See @ref ndbapi_example2.cpp
+ * executed. See @ref ndbapi_async1.cpp
* for an example on how to specify and use
* a callback method.
* @param anyObject A void pointer. This pointer is forwarded to the
@@ -269,15 +353,23 @@ public:
NdbAsynchCallback callback,
void* anyObject,
AbortOption abortOption = AbortOnError);
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ void executeAsynchPrepare(::ExecType execType,
+ NdbAsynchCallback callback,
+ void* anyObject,
+ ::AbortOption abortOption = ::AbortOnError)
+ { executeAsynchPrepare((ExecType)execType, callback, anyObject,
+ (AbortOption)abortOption); }
+#endif
/**
* Prepare and send an asynchronous transaction.
*
* This method perform the same action as
- * NdbConnection::executeAsynchPrepare
+ * NdbTransaction::executeAsynchPrepare
* but also sends the operations to the NDB kernel.
*
- * See NdbConnection::executeAsynchPrepare for information
+ * See NdbTransaction::executeAsynchPrepare for information
* about the parameters of this method.
*
* See @ref secAsync for more information on
@@ -287,7 +379,15 @@ public:
NdbAsynchCallback aCallback,
void* anyObject,
AbortOption abortOption = AbortOnError);
-
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ void executeAsynch(::ExecType aTypeOfExec,
+ NdbAsynchCallback aCallback,
+ void* anyObject,
+ ::AbortOption abortOption= ::AbortOnError)
+ { executeAsynch((ExecType)aTypeOfExec, aCallback, anyObject,
+ (AbortOption)abortOption); }
+#endif
+#endif
/**
* Refresh
* Update timeout counter of this transaction
@@ -302,25 +402,39 @@ public:
/**
* Close transaction
- * @note It is not allowed to call NdbConnection::close after sending the
+ *
+ * @note Equivalent to to calling Ndb::closeTransaction()
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /**
+ * @note It is not allowed to call NdbTransaction::close after sending the
* transaction asynchronously before the callback method has
* been called.
* (The application should keep track of the number of
* outstanding transactions and wait until all of them
- * has completed before calling NdbConnection::close).
+ * has completed before calling NdbTransaction::close).
* If the transaction is not committed it will be aborted.
*/
+#endif
void close();
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
* Restart transaction
*
* Once a transaction has been completed successfully
* it can be started again wo/ calling closeTransaction/startTransaction
*
- * Note this method also releases completed operations
+ * @note This method also releases completed operations
+ *
+ * @note This method does not close open scans,
+ * c.f. NdbScanOperation::close()
+ *
+ * @note This method can only be called _directly_ after commit
+ * and only if commit is successful
*/
int restart();
+#endif
/** @} *********************************************************************/
@@ -347,23 +461,20 @@ public:
* (This is because no updates are performed in scan transactions.)
*
* @return GCI of transaction or -1 if GCI is not available.
- * (Note that there has to be an NdbConnection::execute call
+ * (Note that there has to be an NdbTransaction::execute call
* with Ndb::Commit for the GCI to be available.)
*/
- int getGCI();
+ int getGCI();
/**
* Get transaction identity.
*
* @return Transaction id.
*/
- Uint64 getTransactionId();
+ Uint64 getTransactionId();
/**
- * Returns the commit status of the transaction.
- *
- * @return The commit status of the transaction, i.e. one of
- * { NotStarted, Started, TimeOut, Committed, Aborted, NeedAbort }
+ * The commit status of the transaction.
*/
enum CommitStatusType {
NotStarted, ///< Transaction not yet started
@@ -373,6 +484,11 @@ public:
NeedAbort ///< <i>Missing explanation</i>
};
+ /**
+ * Get the commit status of the transaction.
+ *
+ * @return The commit status of the transaction
+ */
CommitStatusType commitStatus();
/** @} *********************************************************************/
@@ -391,10 +507,10 @@ public:
/**
* Get the latest NdbOperation which had an error.
- * This method is used on the NdbConnection object to find the
+ * This method is used on the NdbTransaction object to find the
* NdbOperation causing an error.
* To find more information about the
- * actual error, use method NdbOperation::getNdbError
+ * actual error, use method NdbOperation::getNdbError()
* on the returned NdbOperation object.
*
* @return The NdbOperation causing the latest error.
@@ -413,9 +529,9 @@ public:
*
* This method should only be used <em>after</em> a transaction
* has been executed.
- * - NdbConnection::getNextCompletedOperation(NULL) returns the
+ * - NdbTransaction::getNextCompletedOperation(NULL) returns the
* first NdbOperation object.
- * - NdbConnection::getNextCompletedOperation(op) returns the
+ * - NdbTransaction::getNextCompletedOperation(op) returns the
* NdbOperation object defined after the NdbOperation "op".
*
* This method is typically used to fetch all NdbOperation:s of
@@ -430,6 +546,10 @@ public:
*/
const NdbOperation * getNextCompletedOperation(const NdbOperation * op)const;
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ const NdbOperation* getFirstDefinedOperation()const{return theFirstOpInList;}
+ const NdbOperation* getLastDefinedOperation()const{return theLastOpInList;}
+
/** @} *********************************************************************/
/**
@@ -441,16 +561,12 @@ public:
*/
int executePendingBlobOps(Uint8 flags = 0xFF);
- // Fast path calls for MySQL ha_ndbcluster
- NdbOperation* getNdbOperation(const NdbDictionary::Table * table);
- NdbIndexOperation* getNdbIndexOperation(const NdbDictionary::Index *,
- const NdbDictionary::Table * table);
- NdbScanOperation* getNdbScanOperation(const NdbDictionary::Table * table);
- NdbIndexScanOperation* getNdbIndexScanOperation(const NdbDictionary::Index * index,
- const NdbDictionary::Table * table);
+ /**
+ * Get nodeId of TC for this transaction
+ */
+ Uint32 getConnectedNodeId(); // Get Connected node id
+#endif
- Uint32 getConnectedNodeId(); // Get Connected node id
-
private:
/**
* Release completed operations
@@ -466,9 +582,9 @@ private:
* These are the create and delete methods of this class. *
**************************************************************************/
- NdbConnection(Ndb* aNdb);
+ NdbTransaction(Ndb* aNdb);
- ~NdbConnection();
+ ~NdbTransaction();
void init(); // Initialize connection object for new transaction
@@ -487,8 +603,8 @@ private:
int getTC_ConnectPtr(); // Gets TC Connect pointer
void setBuddyConPtr(Uint32); // Sets Buddy Con Ptr
Uint32 getBuddyConPtr(); // Gets Buddy Con Ptr
- NdbConnection* next(); // Returns the next pointer
- void next(NdbConnection*); // Sets the next pointer
+ NdbTransaction* next(); // Returns the next pointer
+ void next(NdbTransaction*); // Sets the next pointer
enum ConStatusType {
NotConnected,
@@ -600,7 +716,7 @@ private:
NdbOperation* theErrorOperation; // The NdbOperation where the error occurred
Ndb* theNdb; // Pointer to Ndb object
- NdbConnection* theNext; // Next pointer. Used in idle list.
+ NdbTransaction* theNext; // Next pointer. Used in idle list.
NdbOperation* theFirstOpInList; // First operation in defining list.
NdbOperation* theLastOpInList; // Last operation in defining list.
@@ -693,16 +809,18 @@ private:
friend class HugoOperations;
};
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
inline
Uint32
-NdbConnection::get_send_size()
+NdbTransaction::get_send_size()
{
return 0;
}
inline
void
-NdbConnection::set_send_size(Uint32 send_size)
+NdbTransaction::set_send_size(Uint32 send_size)
{
return;
}
@@ -713,7 +831,7 @@ NdbConnection::set_send_size(Uint32 send_size)
inline
int
-NdbConnection::checkMagicNumber()
+NdbTransaction::checkMagicNumber()
{
if (theMagicNumber == 0x37412619)
return 0;
@@ -727,7 +845,7 @@ NdbConnection::checkMagicNumber()
inline
bool
-NdbConnection::checkState_TransId(const Uint32 * transId) const {
+NdbTransaction::checkState_TransId(const Uint32 * transId) const {
const Uint32 tTmp1 = transId[0];
const Uint32 tTmp2 = transId[1];
Uint64 tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
@@ -742,14 +860,14 @@ Remark: Set the transaction identity.
************************************************************************************************/
inline
void
-NdbConnection::setTransactionId(Uint64 aTransactionId)
+NdbTransaction::setTransactionId(Uint64 aTransactionId)
{
theTransactionId = aTransactionId;
}
inline
void
-NdbConnection::setConnectedNodeId(Uint32 aNode, Uint32 aSequenceNo)
+NdbTransaction::setConnectedNodeId(Uint32 aNode, Uint32 aSequenceNo)
{
theDBnode = aNode;
theNodeSequence = aSequenceNo;
@@ -762,7 +880,7 @@ Remark: Get Connected node id.
******************************************************************************/
inline
Uint32
-NdbConnection::getConnectedNodeId()
+NdbTransaction::getConnectedNodeId()
{
return theDBnode;
}
@@ -774,7 +892,7 @@ Remark: Set my block refrerence.
******************************************************************************/
inline
void
-NdbConnection::setMyBlockReference(int aBlockRef)
+NdbTransaction::setMyBlockReference(int aBlockRef)
{
theMyRef = aBlockRef;
}
@@ -786,7 +904,7 @@ Remark: Sets TC Connect pointer.
******************************************************************************/
inline
void
-NdbConnection::setTC_ConnectPtr(Uint32 aTCConPtr)
+NdbTransaction::setTC_ConnectPtr(Uint32 aTCConPtr)
{
theTCConPtr = aTCConPtr;
}
@@ -799,61 +917,61 @@ Remark: Gets TC Connect pointer.
******************************************************************************/
inline
int
-NdbConnection::getTC_ConnectPtr()
+NdbTransaction::getTC_ConnectPtr()
{
return theTCConPtr;
}
inline
void
-NdbConnection::setBuddyConPtr(Uint32 aBuddyConPtr)
+NdbTransaction::setBuddyConPtr(Uint32 aBuddyConPtr)
{
theBuddyConPtr = aBuddyConPtr;
}
inline
-Uint32 NdbConnection::getBuddyConPtr()
+Uint32 NdbTransaction::getBuddyConPtr()
{
return theBuddyConPtr;
}
/******************************************************************************
-NdbConnection* next();
+NdbTransaction* next();
inline
void
-NdbConnection::setBuddyConPtr(Uint32 aBuddyConPtr)
+NdbTransaction::setBuddyConPtr(Uint32 aBuddyConPtr)
{
theBuddyConPtr = aBuddyConPtr;
}
inline
-Uint32 NdbConnection::getBuddyConPtr()
+Uint32 NdbTransaction::getBuddyConPtr()
{
return theBuddyConPtr;
}
-Return Value: Return next pointer to NdbConnection object.
+Return Value: Return next pointer to NdbTransaction object.
Remark: Get the next pointer.
******************************************************************************/
inline
-NdbConnection*
-NdbConnection::next()
+NdbTransaction*
+NdbTransaction::next()
{
return theNext;
}
/******************************************************************************
-void next(NdbConnection aConnection);
+void next(NdbTransaction aTransaction);
-Parameters: aConnection: The connection object.
+Parameters: aTransaction: The connection object.
Remark: Sets the next pointer.
******************************************************************************/
inline
void
-NdbConnection::next(NdbConnection* aConnection)
+NdbTransaction::next(NdbTransaction* aTransaction)
{
- theNext = aConnection;
+ theNext = aTransaction;
}
/******************************************************************************
@@ -864,8 +982,8 @@ Parameters: aStatus: The status.
Remark: Sets Connect status.
******************************************************************************/
inline
-NdbConnection::ConStatusType
-NdbConnection::Status()
+NdbTransaction::ConStatusType
+NdbTransaction::Status()
{
return theStatus;
}
@@ -878,7 +996,7 @@ Remark: Sets Connect status.
******************************************************************************/
inline
void
-NdbConnection::Status( ConStatusType aStatus )
+NdbTransaction::Status( ConStatusType aStatus )
{
theStatus = aStatus;
}
@@ -891,7 +1009,7 @@ Remark: Set global checkpoint identity of the transaction
******************************************************************************/
inline
void
-NdbConnection::setGCI(int aGlobalCheckpointId)
+NdbTransaction::setGCI(int aGlobalCheckpointId)
{
theGlobalCheckpointId = aGlobalCheckpointId;
}
@@ -903,7 +1021,7 @@ Remark: An operation was sent with success that expects a response.
******************************************************************************/
inline
void
-NdbConnection::OpSent()
+NdbTransaction::OpSent()
{
theNoOfOpSent++;
}
@@ -914,7 +1032,7 @@ void executePendingBlobOps();
#include <stdlib.h>
inline
int
-NdbConnection::executePendingBlobOps(Uint8 flags)
+NdbTransaction::executePendingBlobOps(Uint8 flags)
{
if (thePendingBlobOps & flags) {
// not executeNoBlobs because there can be new ops with blobs
@@ -925,8 +1043,12 @@ NdbConnection::executePendingBlobOps(Uint8 flags)
inline
Uint32
-NdbConnection::ptr2int(){
+NdbTransaction::ptr2int(){
return theId;
}
+typedef NdbTransaction NdbConnection;
+
+#endif // ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
#endif
diff --git a/ndb/include/ndbapi/ndb_cluster_connection.hpp b/ndb/include/ndbapi/ndb_cluster_connection.hpp
index 0e559700716..97db76563aa 100644
--- a/ndb/include/ndbapi/ndb_cluster_connection.hpp
+++ b/ndb/include/ndbapi/ndb_cluster_connection.hpp
@@ -20,39 +20,42 @@
/**
* @class Ndb_cluster_connection
- * @brief Represents a connection to a cluster of storage nodes
+ * @brief Represents a connection to a cluster of storage nodes.
*
- * Always start your application program by creating a
- * Ndb_cluster_connection object. Your application should contain
- * only one Ndb_cluster_connection. Your application connects to
- * a cluster management server when method connect() is called.
- * With the method wait_until_ready() it is possible to wait
- * for the connection to one or several storage nodes.
+ * Any NDB application program should begin with the creation of a
+ * single Ndb_cluster_connection object, and should make use of one
+ * and only one Ndb_cluster_connection. The application connects to
+ * a cluster management server when this object's connect() method is called.
+ * By using the wait_until_ready() method it is possible to wait
+ * for the connection to reach one or more storage nodes.
*/
class Ndb_cluster_connection {
public:
/**
* Create a connection to a cluster of storage nodes
*
- * @param specify the connectstring for where to find the
- * management server
+ * @param connectstring The connectstring for where to find the
+ * management server
*/
- Ndb_cluster_connection(const char * connect_string = 0);
+ Ndb_cluster_connection(const char * connectstring = 0);
~Ndb_cluster_connection();
/**
* Connect to a cluster management server
*
- * @param no_retries specifies the number of retries to perform
- * if the connect fails, negative number results in infinite
- * number of retries
+ * @param no_retries specifies the number of retries to attempt
+ * in the event of connection failure; a negative value
+ * will result in the attempt to connect being repeated
+ * indefinitely
+ *
* @param retry_delay_in_seconds specifies how often retries should
* be performed
- * @param verbose specifies if the method should print progess
*
- * @return 0 if success,
- * 1 if retriable error,
- * -1 if non-retriable error
+ * @param verbose specifies if the method should print a report of its progess
+ *
+ * @return 0 = success,
+ * 1 = recoverable error,
+ * -1 = non-recoverable error
*/
int connect(int no_retries=0, int retry_delay_in_seconds=1, int verbose=0);
@@ -61,15 +64,15 @@ public:
#endif
/**
- * Wait until one or several storage nodes are connected
+ * Wait until the requested connection with one or more storage nodes is successful
*
- * @param time_out_for_first_alive number of seconds to wait until
- * first alive node is detected
- * @param timeout_after_first_alive number of seconds to wait after
- * first alive node is detected
+ * @param timeout_for_first_alive Number of seconds to wait until
+ * first live node is detected
+ * @param timeout_after_first_alive Number of seconds to wait after
+ * first live node is detected
*
- * @return 0 all nodes alive,
- * > 0 at least one node alive,
+ * @return = 0 all nodes live,
+ * > 0 at least one node live,
* < 0 error
*/
int wait_until_ready(int timeout_for_first_alive,
@@ -83,6 +86,7 @@ public:
void set_optimized_node_selection(int val);
unsigned no_db_nodes();
+ unsigned node_id();
#endif
private:
diff --git a/ndb/include/ndbapi/ndb_opt_defaults.h b/ndb/include/ndbapi/ndb_opt_defaults.h
index 63b673ed60d..d03a9dcc36f 100644
--- a/ndb/include/ndbapi/ndb_opt_defaults.h
+++ b/ndb/include/ndbapi/ndb_opt_defaults.h
@@ -17,11 +17,7 @@
#ifndef NDB_OPT_DEFAULTS_H
#define NDB_OPT_DEFAULTS_H
-#ifdef SIGRTMIN
-#define OPT_NDB_SHM_SIGNUM_DEFAULT SIGRTMIN+2
-#else
#define OPT_NDB_SHM_SIGNUM_DEFAULT 0
-#endif
#define OPT_NDB_SHM_DEFAULT 0
#endif
diff --git a/ndb/include/ndbapi/ndbapi_limits.h b/ndb/include/ndbapi/ndbapi_limits.h
index d1cb135b39d..5c4db71b747 100644
--- a/ndb/include/ndbapi/ndbapi_limits.h
+++ b/ndb/include/ndbapi/ndbapi_limits.h
@@ -19,10 +19,6 @@
#define NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY 32
#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_ATTRIBUTES_IN_TABLE 128
#define NDB_MAX_TUPLE_SIZE_IN_WORDS 2013
diff --git a/ndb/include/ndbapi/ndberror.h b/ndb/include/ndbapi/ndberror.h
index ceb1881a4cc..2225f68f08d 100644
--- a/ndb/include/ndbapi/ndberror.h
+++ b/ndb/include/ndbapi/ndberror.h
@@ -21,6 +21,8 @@
extern "C" {
#endif
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+
typedef enum
{
ndberror_st_success = 0,
@@ -47,7 +49,8 @@ typedef enum
ndberror_cl_function_not_implemented = 13,
ndberror_cl_unknown_error_code = 14,
ndberror_cl_node_shutdown = 15,
- ndberror_cl_configuration = 16
+ ndberror_cl_configuration = 16,
+ ndberror_cl_schema_object_already_exists = 17
} ndberror_classification_enum;
@@ -92,6 +95,8 @@ const char *ndberror_classification_message(ndberror_classification);
void ndberror_update(ndberror_struct *);
int ndb_error_string(int err_no, char *str, unsigned int size);
+#endif /* doxygen skip internal*/
+
#ifdef __cplusplus
}
#endif
diff --git a/ndb/include/portlib/NdbTCP.h b/ndb/include/portlib/NdbTCP.h
index 308a3833ffd..9ed5b5e7f96 100644
--- a/ndb/include/portlib/NdbTCP.h
+++ b/ndb/include/portlib/NdbTCP.h
@@ -95,6 +95,8 @@ int Ndb_getInAddr(struct in_addr * dst, const char *address);
int NDB_CLOSE_SOCKET(int fd);
#endif
+int Ndb_check_socket_hup(NDB_SOCKET_TYPE sock);
+
#ifdef __cplusplus
}
#endif
diff --git a/ndb/include/transporter/TransporterCallback.hpp b/ndb/include/transporter/TransporterCallback.hpp
index 9f910f31728..f2432edd394 100644
--- a/ndb/include/transporter/TransporterCallback.hpp
+++ b/ndb/include/transporter/TransporterCallback.hpp
@@ -341,5 +341,8 @@ enum TransporterError {
*/
void
reportError(void * callbackObj, NodeId nodeId, TransporterError errorCode);
+
+void
+transporter_recv_from(void* callbackObj, NodeId node);
#endif
diff --git a/ndb/include/transporter/TransporterDefinitions.hpp b/ndb/include/transporter/TransporterDefinitions.hpp
index d4763ba4c37..e9c5ffa2c80 100644
--- a/ndb/include/transporter/TransporterDefinitions.hpp
+++ b/ndb/include/transporter/TransporterDefinitions.hpp
@@ -49,74 +49,50 @@ enum SendStatus {
const Uint32 MAX_MESSAGE_SIZE = (12+4+4+(4*25)+(3*4)+4*4096);
/**
- * TCP Transporter Configuration
+ * TransporterConfiguration
+ *
+ * used for setting up a transporter. the union member specific is for
+ * information specific to a transporter type.
*/
-struct TCP_TransporterConfiguration {
- Uint32 port;
+struct TransporterConfiguration {
+ Int32 s_port; // negative port number implies dynamic port
const char *remoteHostName;
const char *localHostName;
NodeId remoteNodeId;
NodeId localNodeId;
- Uint32 sendBufferSize; // Size of SendBuffer of priority B
- Uint32 maxReceiveSize; // Maximum no of bytes to receive
+ NodeId serverNodeId;
bool checksum;
bool signalId;
-};
-
-/**
- * SHM Transporter Configuration
- */
-struct SHM_TransporterConfiguration {
- Uint32 port;
- const char *remoteHostName;
- const char *localHostName;
- NodeId remoteNodeId;
- NodeId localNodeId;
- bool checksum;
- bool signalId;
-
- Uint32 shmKey;
- Uint32 shmSize;
- int signum;
-};
-
-/**
- * OSE Transporter Configuration
- */
-struct OSE_TransporterConfiguration {
- const char *remoteHostName;
- const char *localHostName;
- NodeId remoteNodeId;
- NodeId localNodeId;
- bool checksum;
- bool signalId;
-
- Uint32 prioASignalSize;
- Uint32 prioBSignalSize;
- Uint32 receiveBufferSize; // In number of signals
-};
-
-/**
- * SCI Transporter Configuration
- */
-struct SCI_TransporterConfiguration {
- const char *remoteHostName;
- const char *localHostName;
- Uint32 port;
- Uint32 sendLimit; // Packet size
- Uint32 bufferSize; // Buffer size
-
- Uint32 nLocalAdapters; // 1 or 2, the number of adapters on local host
-
- Uint32 remoteSciNodeId0; // SCInodeId for adapter 1
- Uint32 remoteSciNodeId1; // SCInodeId for adapter 2
-
- NodeId localNodeId; // Local node Id
- NodeId remoteNodeId; // Remote node Id
-
- bool checksum;
- bool signalId;
-
+ bool isMgmConnection; // is a mgm connection, requires transforming
+
+ union { // Transporter specific configuration information
+
+ struct {
+ Uint32 sendBufferSize; // Size of SendBuffer of priority B
+ Uint32 maxReceiveSize; // Maximum no of bytes to receive
+ } tcp;
+
+ struct {
+ Uint32 shmKey;
+ Uint32 shmSize;
+ int signum;
+ } shm;
+
+ struct {
+ Uint32 prioASignalSize;
+ Uint32 prioBSignalSize;
+ } ose;
+
+ struct {
+ Uint32 sendLimit; // Packet size
+ Uint32 bufferSize; // Buffer size
+
+ Uint32 nLocalAdapters; // 1 or 2, the number of adapters on local host
+
+ Uint32 remoteSciNodeId0; // SCInodeId for adapter 1
+ Uint32 remoteSciNodeId1; // SCInodeId for adapter 2
+ } sci;
+ };
};
struct SignalHeader {
diff --git a/ndb/include/transporter/TransporterRegistry.hpp b/ndb/include/transporter/TransporterRegistry.hpp
index 410f3e1dc12..0bb9733e8c4 100644
--- a/ndb/include/transporter/TransporterRegistry.hpp
+++ b/ndb/include/transporter/TransporterRegistry.hpp
@@ -30,9 +30,12 @@
#include "TransporterDefinitions.hpp"
#include <SocketServer.hpp>
+#include <SocketClient.hpp>
#include <NdbTCP.h>
+#include <mgmapi/mgmapi.h>
+
// A transporter is always in an IOState.
// NoHalt is used initially and as long as it is no restrictions on
// sending or receiving.
@@ -97,7 +100,15 @@ public:
TransporterRegistry(void * callback = 0 ,
unsigned maxTransporters = MAX_NTRANSPORTERS,
unsigned sizeOfLongSignalMemory = 100);
-
+
+ /**
+ * this handle will be used in the client connect thread
+ * to fetch information on dynamic ports. The old handle
+ * (if set) is destroyed, and this is destroyed by the destructor
+ */
+ void set_mgm_handle(NdbMgmHandle h);
+ NdbMgmHandle get_mgm_handle(void) { return m_mgm_handle; };
+
bool init(NodeId localNodeId);
/**
@@ -105,6 +116,20 @@ public:
*/
bool connect_server(NDB_SOCKET_TYPE sockfd);
+ bool connect_client(NdbMgmHandle *h);
+
+ /**
+ * Given a SocketClient, creates a NdbMgmHandle, turns it into a transporter
+ * and returns the socket.
+ */
+ NDB_SOCKET_TYPE connect_ndb_mgmd(SocketClient *sc);
+
+ /**
+ * Given a connected NdbMgmHandle, turns it into a transporter
+ * and returns the socket.
+ */
+ NDB_SOCKET_TYPE connect_ndb_mgmd(NdbMgmHandle *h);
+
/**
* Remove all transporters
*/
@@ -174,10 +199,10 @@ public:
* started, startServer is called. A transporter of the selected kind
* is created and it is put in the transporter arrays.
*/
- bool createTransporter(struct TCP_TransporterConfiguration * config);
- bool createTransporter(struct SCI_TransporterConfiguration * config);
- bool createTransporter(struct SHM_TransporterConfiguration * config);
- bool createTransporter(struct OSE_TransporterConfiguration * config);
+ bool createTCPTransporter(struct TransporterConfiguration * config);
+ bool createSCITransporter(struct TransporterConfiguration * config);
+ bool createSHMTransporter(struct TransporterConfiguration * config);
+ bool createOSETransporter(struct TransporterConfiguration * config);
/**
* Get free buffer space
@@ -233,11 +258,16 @@ public:
class Transporter_interface {
public:
- unsigned short m_service_port;
+ NodeId m_remote_nodeId;
+ int m_s_service_port; // signed port number
const char *m_interface;
};
Vector<Transporter_interface> m_transporter_interface;
- void add_transporter_interface(const char *interf, unsigned short port);
+ void add_transporter_interface(NodeId remoteNodeId, const char *interf,
+ int s_port); // signed port. <0 is dynamic
+ Transporter* get_transporter(NodeId nodeId);
+ NodeId get_localNodeId() { return localNodeId; };
+
struct in_addr get_connect_address(NodeId node_id) const;
protected:
@@ -245,6 +275,8 @@ protected:
private:
void * callbackObj;
+ NdbMgmHandle m_mgm_handle;
+
struct NdbThread *m_start_clients_thread;
bool m_run_start_clients_thread;
diff --git a/ndb/include/util/Base64.hpp b/ndb/include/util/Base64.hpp
index 1156636eec8..f4b11ad9214 100644
--- a/ndb/include/util/Base64.hpp
+++ b/ndb/include/util/Base64.hpp
@@ -21,6 +21,7 @@
#include <BaseString.hpp>
int base64_encode(const UtilBuffer &src, BaseString &dst);
+int base64_encode(const void * s, size_t src_len, BaseString &dst);
int base64_decode(const BaseString &src, UtilBuffer &dst);
int base64_decode(const char * s, size_t len, UtilBuffer &dst);
diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp
index 19aa604e4a1..ade57a5ee57 100644
--- a/ndb/include/util/Bitmask.hpp
+++ b/ndb/include/util/Bitmask.hpp
@@ -131,10 +131,26 @@ public:
static void setField(unsigned size, Uint32 data[],
unsigned pos, unsigned len, Uint32 val);
+
+ /**
+ * getField - Get bitfield at given position and length
+ */
+ static void getField(unsigned size, const Uint32 data[],
+ unsigned pos, unsigned len, Uint32 dst[]);
+
+ /**
+ * setField - Set bitfield at given position and length
+ */
+ static void setField(unsigned size, Uint32 data[],
+ unsigned pos, unsigned len, const Uint32 src[]);
+
/**
* getText - Return as hex-digits (only for debug routines).
*/
static char* getText(unsigned size, const Uint32 data[], char* buf);
+private:
+ static void getFieldImpl(const Uint32 data[], unsigned, unsigned, Uint32 []);
+ static void setFieldImpl(Uint32 data[], unsigned, unsigned, const Uint32 []);
};
inline bool
@@ -794,4 +810,45 @@ public:
Bitmask() { this->clear();}
};
+inline void
+BitmaskImpl::getField(unsigned size, const Uint32 src[],
+ unsigned pos, unsigned len, Uint32 dst[])
+{
+ assert(pos + len < (size << 5));
+
+ src += (pos >> 5);
+ Uint32 offset = pos & 31;
+ * dst = (* src >> offset) & (len >= 32 ? ~0 : (1 << len) - 1);
+
+ if(offset + len <= 32)
+ {
+ return;
+ }
+ Uint32 used = (32 - offset);
+ assert(len > used);
+ getFieldImpl(src+1, used & 31, len-used, dst+(used >> 5));
+}
+
+inline void
+BitmaskImpl::setField(unsigned size, Uint32 dst[],
+ unsigned pos, unsigned len, const Uint32 src[])
+{
+ assert(pos + len < (size << 5));
+
+ dst += (pos >> 5);
+ Uint32 offset = pos & 31;
+ Uint32 mask = (len >= 32 ? ~0 : (1 << len) - 1) << offset;
+
+ * dst = (* dst & ~mask) | ((*src << offset) & mask);
+
+ if(offset + len <= 32)
+ {
+ return;
+ }
+ Uint32 used = (32 - offset);
+ assert(len > used);
+ setFieldImpl(dst+1, used & 31, len-used, src+(used >> 5));
+}
+
+
#endif
diff --git a/ndb/include/util/NdbSqlUtil.hpp b/ndb/include/util/NdbSqlUtil.hpp
index 5b27bd4e0c4..3e98dcd1805 100644
--- a/ndb/include/util/NdbSqlUtil.hpp
+++ b/ndb/include/util/NdbSqlUtil.hpp
@@ -20,34 +20,41 @@
#include <ndb_global.h>
#include <kernel/ndb_limits.h>
+struct charset_info_st;
+typedef struct charset_info_st CHARSET_INFO;
+
class NdbSqlUtil {
public:
/**
- * Compare strings, optionally with padded semantics. Returns
- * negative (less), zero (equal), or positive (greater).
- */
- static int char_compare(const char* s1, unsigned n1,
- const char* s2, unsigned n2, bool padded);
-
- /**
- * Like operator, optionally with padded semantics. Returns true or
- * false.
+ * Compare attribute values. Returns -1, 0, +1 for less, equal,
+ * greater, respectively. Parameters are pointers to values and their
+ * lengths in bytes. The lengths can differ.
+ *
+ * First value is a full value but second value can be partial. If
+ * the partial value is not enough to determine the result, CmpUnknown
+ * will be returned. A shorter second value is not necessarily
+ * partial. Partial values are allowed only for types where prefix
+ * comparison is possible (basically, binary strings).
+ *
+ * First parameter is a pointer to type specific extra info. Char
+ * types receive CHARSET_INFO in it.
+ *
+ * If a value cannot be parsed, it compares like NULL i.e. less than
+ * any valid value.
*/
- static bool char_like(const char* s1, unsigned n1,
- const char* s2, unsigned n2, bool padded);
+ typedef int Cmp(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full);
/**
- * Compare kernel attribute values. Returns -1, 0, +1 for less,
- * equal, greater, respectively. Parameters are pointers to values,
- * full attribute size in words, and size of available data in words.
- * There is also pointer to type specific extra info. Char types
- * receive CHARSET_INFO in it.
+ * Prototype for "like" comparison. Defined for string types. Second
+ * argument must have same type-specific format. Returns 0 on match,
+ * +1 on no match, and -1 on bad data.
+ *
+ * Uses default special chars ( \ % _ ).
*
- * If available size is less than full size, CmpUnknown may be
- * returned. If a value cannot be parsed, it compares like NULL i.e.
- * less than any valid value.
+ * TODO convert special chars to the cs so that ucs2 etc works
+ * TODO allow user-defined escape ( \ )
*/
- typedef int Cmp(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size);
+ typedef int Like(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2);
enum CmpResult {
CmpLess = -1,
@@ -56,41 +63,43 @@ public:
CmpUnknown = 2 // insufficient partial data
};
- /**
- * Kernel data types. Must match m_typeList in NdbSqlUtil.cpp.
- * Now also must match types in NdbDictionary.
- */
struct Type {
enum Enum {
- Undefined = 0, // Undefined
- Tinyint, // 8 bit
- Tinyunsigned, // 8 bit
- Smallint, // 16 bit
- Smallunsigned, // 16 bit
- Mediumint, // 24 bit
- Mediumunsigned, // 24 bit
- Int, // 32 bit
- Unsigned, // 32 bit
- Bigint, // 64 bit
- Bigunsigned, // 64 Bit
- Float, // 32-bit float
- Double, // 64-bit float
- Olddecimal, // Precision, Scale
- Char, // Len
- Varchar, // Max len
- Binary, // Len
- Varbinary, // Max len
- Datetime, // Precision down to 1 sec (size 8 bytes)
- Date, // Precision down to 1 day (size 4 bytes)
- Blob, // Blob
- Text, // Text blob
- Time = 25, // Time without date
- Year = 26, // Year (size 1 byte)
- Timestamp = 27, // Unix seconds (uint32)
- Olddecimalunsigned = 28
+ Undefined = NDB_TYPE_UNDEFINED,
+ Tinyint = NDB_TYPE_TINYINT,
+ Tinyunsigned = NDB_TYPE_TINYUNSIGNED,
+ Smallint = NDB_TYPE_SMALLINT,
+ Smallunsigned = NDB_TYPE_SMALLUNSIGNED,
+ Mediumint = NDB_TYPE_MEDIUMINT,
+ Mediumunsigned = NDB_TYPE_MEDIUMUNSIGNED,
+ Int = NDB_TYPE_INT,
+ Unsigned = NDB_TYPE_UNSIGNED,
+ Bigint = NDB_TYPE_BIGINT,
+ Bigunsigned = NDB_TYPE_BIGUNSIGNED,
+ Float = NDB_TYPE_FLOAT,
+ Double = NDB_TYPE_DOUBLE,
+ Olddecimal = NDB_TYPE_OLDDECIMAL,
+ Char = NDB_TYPE_CHAR,
+ Varchar = NDB_TYPE_VARCHAR,
+ Binary = NDB_TYPE_BINARY,
+ Varbinary = NDB_TYPE_VARBINARY,
+ Datetime = NDB_TYPE_DATETIME,
+ Date = NDB_TYPE_DATE,
+ Blob = NDB_TYPE_BLOB,
+ Text = NDB_TYPE_TEXT,
+ Bit = NDB_TYPE_BIT,
+ Longvarchar = NDB_TYPE_LONGVARCHAR,
+ Longvarbinary = NDB_TYPE_LONGVARBINARY,
+ Time = NDB_TYPE_TIME,
+ Year = NDB_TYPE_YEAR,
+ Timestamp = NDB_TYPE_TIMESTAMP,
+ Olddecimalunsigned = NDB_TYPE_OLDDECIMALUNSIGNED,
+ Decimal = NDB_TYPE_DECIMAL,
+ Decimalunsigned = NDB_TYPE_DECIMALUNSIGNED
};
- Enum m_typeId;
+ Enum m_typeId; // redundant
Cmp* m_cmp; // comparison method
+ Like* m_like; // "like" comparison method
};
/**
@@ -99,16 +108,30 @@ public:
static const Type& getType(Uint32 typeId);
/**
- * Get type by id but replace char type by corresponding binary type.
+ * Get the normalized type used in hashing and key comparisons.
+ * Maps all string types to Binary. This includes Var* strings
+ * because strxfrm result is padded to fixed (maximum) length.
*/
static const Type& getTypeBinary(Uint32 typeId);
/**
* Check character set.
*/
- static bool usable_in_pk(Uint32 typeId, const void* cs);
- static bool usable_in_hash_index(Uint32 typeId, const void* cs);
- static bool usable_in_ordered_index(Uint32 typeId, const void* cs);
+ static bool usable_in_pk(Uint32 typeId, const void* info);
+ static bool usable_in_hash_index(Uint32 typeId, const void* info);
+ static bool usable_in_ordered_index(Uint32 typeId, const void* info);
+
+ /**
+ * Get number of length bytes and length from variable length string.
+ * Returns false on error (invalid data). For other types returns
+ * zero length bytes and the fixed attribute length.
+ */
+ static bool get_var_length(Uint32 typeId, const void* p, unsigned attrlen, Uint32& lb, Uint32& len);
+
+ /**
+ * Temporary workaround for bug#7284.
+ */
+ static int strnxfrm_bug7284(CHARSET_INFO* cs, unsigned char* dst, unsigned dstLen, const unsigned char*src, unsigned srcLen);
/**
* Compare decimal numbers.
@@ -144,10 +167,22 @@ private:
static Cmp cmpDate;
static Cmp cmpBlob;
static Cmp cmpText;
+ static Cmp cmpBit;
+ static Cmp cmpLongvarchar;
+ static Cmp cmpLongvarbinary;
static Cmp cmpTime;
static Cmp cmpYear;
static Cmp cmpTimestamp;
static Cmp cmpOlddecimalunsigned;
+ static Cmp cmpDecimal;
+ static Cmp cmpDecimalunsigned;
+ //
+ static Like likeChar;
+ static Like likeBinary;
+ static Like likeVarchar;
+ static Like likeVarbinary;
+ static Like likeLongvarchar;
+ static Like likeLongvarbinary;
};
#endif
diff --git a/ndb/include/util/SimpleProperties.hpp b/ndb/include/util/SimpleProperties.hpp
index 356f3406f38..438426fb62b 100644
--- a/ndb/include/util/SimpleProperties.hpp
+++ b/ndb/include/util/SimpleProperties.hpp
@@ -172,6 +172,8 @@ public:
virtual bool reset() = 0;
virtual bool putWord(Uint32 val) = 0;
virtual bool putWords(const Uint32 * src, Uint32 len) = 0;
+ private:
+ bool add(const char* value, int len);
};
};
@@ -211,7 +213,7 @@ private:
};
/**
- * Writer for linear memory
+ * Writer for UtilBuffer
*/
class UtilBufferWriter : public SimpleProperties::Writer {
public:
diff --git a/ndb/include/util/SocketClient.hpp b/ndb/include/util/SocketClient.hpp
index de9a081464a..bf1ad7d45d6 100644
--- a/ndb/include/util/SocketClient.hpp
+++ b/ndb/include/util/SocketClient.hpp
@@ -31,6 +31,12 @@ public:
SocketClient(const char *server_name, unsigned short port, SocketAuthenticator *sa = 0);
~SocketClient();
bool init();
+ void set_port(unsigned short port) {
+ m_port = port;
+ m_servaddr.sin_port = htons(m_port);
+ };
+ unsigned short get_port() { return m_port; };
+ char *get_server_name() { return m_server_name; };
NDB_SOCKET_TYPE connect();
bool close();
};
diff --git a/ndb/include/util/SocketServer.hpp b/ndb/include/util/SocketServer.hpp
index ee2dd31c41f..4c37e63adf0 100644
--- a/ndb/include/util/SocketServer.hpp
+++ b/ndb/include/util/SocketServer.hpp
@@ -89,7 +89,7 @@ public:
* bind & listen
* Returns false if no success
*/
- bool setup(Service *, unsigned short port, const char * pinterface = 0);
+ bool setup(Service *, unsigned short *port, const char * pinterface = 0);
/**
* start/stop the server
diff --git a/ndb/include/util/Vector.hpp b/ndb/include/util/Vector.hpp
index f60817dab67..480dddf8243 100644
--- a/ndb/include/util/Vector.hpp
+++ b/ndb/include/util/Vector.hpp
@@ -61,6 +61,10 @@ Vector<T>::Vector(int i){
template<class T>
Vector<T>::~Vector(){
delete[] m_items;
+ // safety for placement new usage
+ m_items = 0;
+ m_size = 0;
+ m_arraySize = 0;
}
template<class T>
@@ -174,6 +178,10 @@ MutexVector<T>::MutexVector(int i){
template<class T>
MutexVector<T>::~MutexVector(){
delete[] m_items;
+ // safety for placement new usage
+ m_items = 0;
+ m_size = 0;
+ m_arraySize = 0;
}
template<class T>
diff --git a/ndb/include/util/md5_hash.hpp b/ndb/include/util/md5_hash.hpp
index 4c3cf239881..b79dce3b5a9 100644
--- a/ndb/include/util/md5_hash.hpp
+++ b/ndb/include/util/md5_hash.hpp
@@ -20,6 +20,15 @@
#include <ndb_types.h>
// External declaration of hash function
-Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words);
+void md5_hash(Uint32 result[4], const Uint64* keybuf, Uint32 no_of_32_words);
+
+inline
+Uint32
+md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
+{
+ Uint32 result[4];
+ md5_hash(result, keybuf, no_of_32_words);
+ return result[0];
+}
#endif
diff --git a/ndb/include/util/ndb_opts.h b/ndb/include/util/ndb_opts.h
index 462d9996582..787c32f06fd 100644
--- a/ndb/include/util/ndb_opts.h
+++ b/ndb/include/util/ndb_opts.h
@@ -25,12 +25,21 @@
#include <ndb_opt_defaults.h>
#define NDB_STD_OPTS_VARS \
-const char *opt_connect_str= 0;\
my_bool opt_ndb_optimized_node_selection
+int opt_ndb_nodeid;
bool opt_endinfo= 0;
my_bool opt_ndb_shm;
my_bool opt_core;
+const char *opt_ndb_connectstring= 0;
+const char *opt_connect_str= 0;
+const char *opt_ndb_mgmd= 0;
+char opt_ndb_constrbuf[1024];
+unsigned opt_ndb_constrbuf_len= 0;
+
+#ifndef DBUG_OFF
+const char *opt_debug= 0;
+#endif
#define OPT_NDB_CONNECTSTRING 'c'
#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
@@ -50,8 +59,17 @@ my_bool opt_core;
"Set connect string for connecting to ndb_mgmd. " \
"Syntax: \"[nodeid=<id>;][host=]<hostname>[:<port>]\". " \
"Overides specifying entries in NDB_CONNECTSTRING and Ndb.cfg", \
- (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, \
+ (gptr*) &opt_ndb_connectstring, (gptr*) &opt_ndb_connectstring, \
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
+ { "ndb-mgmd-host", OPT_NDB_MGMD, \
+ "Set host and port for connecting to ndb_mgmd. " \
+ "Syntax: <hostname>[:<port>].", \
+ (gptr*) &opt_ndb_mgmd, (gptr*) &opt_ndb_mgmd, 0, \
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
+ { "ndb-nodeid", OPT_NDB_NODEID, \
+ "Set node id for this node.", \
+ (gptr*) &opt_ndb_nodeid, (gptr*) &opt_ndb_nodeid, 0, \
+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
{ "ndb-shm", OPT_NDB_SHM,\
"Allow optimizing using shared memory connections when available",\
(gptr*) &opt_ndb_shm, (gptr*) &opt_ndb_shm, 0,\
@@ -62,8 +80,8 @@ my_bool opt_core;
(gptr*) &opt_ndb_optimized_node_selection, 0,\
GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},\
{ "connect-string", OPT_NDB_CONNECTSTRING, "same as --ndb-connectstring",\
- (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0,\
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
+ (gptr*) &opt_ndb_connectstring, (gptr*) &opt_ndb_connectstring, \
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
{ "core-file", OPT_WANT_CORE, "Write core on errors.",\
(gptr*) &opt_core, (gptr*) &opt_core, 0,\
GET_BOOL, NO_ARG, OPT_WANT_CORE_DEFAULT, 0, 0, 0, 0, 0}
@@ -71,7 +89,8 @@ my_bool opt_core;
#ifndef DBUG_OFF
#define NDB_STD_OPTS(prog_name) \
{ "debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", \
- 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, \
+ (gptr*) &opt_debug, (gptr*) &opt_debug, \
+ 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, \
NDB_STD_OPTS_COMMON
#else
#define NDB_STD_OPTS(prog_name) NDB_STD_OPTS_COMMON
@@ -90,22 +109,30 @@ enum ndb_std_options {
OPT_NDB_SHM_SIGNUM,
OPT_NDB_OPTIMIZED_NODE_SELECTION,
OPT_WANT_CORE,
+ OPT_NDB_MGMD,
+ OPT_NDB_NODEID,
NDB_STD_OPTIONS_LAST /* should always be last in this enum */
};
static my_bool
ndb_std_get_one_option(int optid,
const struct my_option *opt __attribute__((unused)),
- const char *argument)
+ char *argument)
{
switch (optid) {
+#ifndef DBUG_OFF
case '#':
- if (argument)
+ if (opt_debug)
{
- DBUG_PUSH(argument);
+ DBUG_PUSH(opt_debug);
+ }
+ else
+ {
+ DBUG_PUSH("d:t");
}
opt_endinfo= 1;
break;
+#endif
case 'V':
ndb_std_print_version();
exit(0);
@@ -122,6 +149,29 @@ ndb_std_get_one_option(int optid,
#endif
}
break;
+ case OPT_NDB_MGMD:
+ case OPT_NDB_NODEID:
+ {
+ int len= my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len,
+ sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len,
+ "%s%s%s",opt_ndb_constrbuf_len > 0 ? ",":"",
+ optid == OPT_NDB_NODEID ? "nodeid=" : "",
+ argument);
+ opt_ndb_constrbuf_len+= len;
+ }
+ /* fall through to add the connectstring to the end
+ * and set opt_ndbcluster_connectstring
+ */
+ case OPT_NDB_CONNECTSTRING:
+ if (opt_ndb_connectstring && opt_ndb_connectstring[0])
+ my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len,
+ sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len,
+ "%s%s", opt_ndb_constrbuf_len > 0 ? ",":"",
+ opt_ndb_connectstring);
+ else
+ opt_ndb_constrbuf[opt_ndb_constrbuf_len]= 0;
+ opt_connect_str= opt_ndb_constrbuf;
+ break;
}
return 0;
}
diff --git a/ndb/examples/Makefile b/ndb/ndbapi-examples/Makefile
index 0294632e23d..965dc3ec29f 100644
--- a/ndb/examples/Makefile
+++ b/ndb/ndbapi-examples/Makefile
@@ -1,12 +1,11 @@
--include .defs.mk
-
-#ifneq ($(C++),)
-#OPTS = CC=$(CC) CXX=$(C++)
-#endif
-
-# XXX ndbapi_example4 commented out until fixed
-BIN_DIRS := ndbapi_example1 ndbapi_example2 ndbapi_example3 $(ndbapi_example4) \
- ndbapi_example5 select_all
+BIN_DIRS := ndbapi_simple_example \
+ ndbapi_async_example \
+ ndbapi_async_example1 \
+ ndbapi_retries_example \
+ ndbapi_simple_index_example \
+ ndbapi_event_example \
+ ndbapi_scan_example \
+ mgmapi_logevent_example
bins: $(patsubst %, _bins_%, $(BIN_DIRS))
@@ -24,4 +23,3 @@ clean_dep: clean
cleanall: clean
tidy: clean
distclean: clean
-
diff --git a/ndb/ndbapi-examples/mgmapi_logevent_example/Makefile b/ndb/ndbapi-examples/mgmapi_logevent_example/Makefile
new file mode 100644
index 00000000000..c1ca32dfe17
--- /dev/null
+++ b/ndb/ndbapi-examples/mgmapi_logevent_example/Makefile
@@ -0,0 +1,23 @@
+TARGET = mgmapi_logevent
+SRCS = $(TARGET).cpp
+OBJS = $(TARGET).o
+CXX = g++
+CFLAGS = -c -Wall -fno-rtti -fno-exceptions
+CXXFLAGS =
+DEBUG =
+LFLAGS = -Wall
+TOP_SRCDIR = ../../..
+INCLUDE_DIR = $(TOP_SRCDIR)
+LIB_DIR = -L$(TOP_SRCDIR)/ndb/src/.libs \
+ -L$(TOP_SRCDIR)/libmysql_r/.libs \
+ -L$(TOP_SRCDIR)/mysys
+SYS_LIB =
+
+$(TARGET): $(OBJS)
+ $(CXX) $(CXXFLAGS) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lz $(SYS_LIB) -o $(TARGET)
+
+$(TARGET).o: $(SRCS)
+ $(CXX) $(CFLAGS) -I$(INCLUDE_DIR)/include -I$(INCLUDE_DIR)/ndb/include -I$(INCLUDE_DIR)/ndb/include/mgmapi -I$(INCLUDE_DIR)/ndb/include/ndbapi $(SRCS)
+
+clean:
+ rm -f *.o $(TARGET)
diff --git a/ndb/ndbapi-examples/mgmapi_logevent_example/mgmapi_logevent.cpp b/ndb/ndbapi-examples/mgmapi_logevent_example/mgmapi_logevent.cpp
new file mode 100644
index 00000000000..5ec1fba6314
--- /dev/null
+++ b/ndb/ndbapi-examples/mgmapi_logevent_example/mgmapi_logevent.cpp
@@ -0,0 +1,140 @@
+/* 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 <mysql.h>
+#include <ndbapi/NdbApi.hpp>
+#include <mgmapi.h>
+#include <stdio.h>
+
+/*
+ * export LD_LIBRARY_PATH=../../../libmysql_r/.libs:../../../ndb/src/.libs
+ */
+
+#define MGMERROR(h) \
+{ \
+ fprintf(stderr, "code: %d msg: %s\n", \
+ ndb_mgm_get_latest_error(h), \
+ ndb_mgm_get_latest_error_msg(h)); \
+ exit(-1); \
+}
+
+#define LOGEVENTERROR(h) \
+{ \
+ fprintf(stderr, "code: %d msg: %s\n", \
+ ndb_logevent_get_latest_error(h), \
+ ndb_logevent_get_latest_error_msg(h)); \
+ exit(-1); \
+}
+
+int main()
+{
+ NdbMgmHandle h;
+ NdbLogEventHandle le;
+ int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP,
+ 15, NDB_MGM_EVENT_CATEGORY_CONNECTION,
+ 15, NDB_MGM_EVENT_CATEGORY_NODE_RESTART,
+ 15, NDB_MGM_EVENT_CATEGORY_STARTUP,
+ 15, NDB_MGM_EVENT_CATEGORY_ERROR,
+ 0 };
+ struct ndb_logevent event;
+
+ ndb_init();
+
+ h= ndb_mgm_create_handle();
+ if ( h == 0)
+ {
+ printf("Unable to create handle\n");
+ exit(-1);
+ }
+ if (ndb_mgm_connect(h,0,0,0)) MGMERROR(h);
+
+ le= ndb_mgm_create_logevent_handle(h, filter);
+ if ( le == 0 ) MGMERROR(h);
+
+ while (1)
+ {
+ int timeout= 5000;
+ int r= ndb_logevent_get_next(le,&event,timeout);
+ if (r == 0)
+ printf("No event within %d milliseconds\n", timeout);
+ else if (r < 0)
+ LOGEVENTERROR(le)
+ else
+ {
+ switch (event.type) {
+ case NDB_LE_BackupStarted:
+ printf("Node %d: BackupStarted\n", event.source_nodeid);
+ printf(" Starting node ID: %d\n", event.BackupStarted.starting_node);
+ printf(" Backup ID: %d\n", event.BackupStarted.backup_id);
+ break;
+ case NDB_LE_BackupCompleted:
+ printf("Node %d: BackupCompleted\n", event.source_nodeid);
+ printf(" Backup ID: %d\n", event.BackupStarted.backup_id);
+ break;
+ case NDB_LE_BackupAborted:
+ printf("Node %d: BackupAborted\n", event.source_nodeid);
+ break;
+ case NDB_LE_BackupFailedToStart:
+ printf("Node %d: BackupFailedToStart\n", event.source_nodeid);
+ break;
+
+ case NDB_LE_NodeFailCompleted:
+ printf("Node %d: NodeFailCompleted\n", event.source_nodeid);
+ break;
+ case NDB_LE_ArbitResult:
+ printf("Node %d: ArbitResult\n", event.source_nodeid);
+ printf(" code %d, arbit_node %d\n",
+ event.ArbitResult.code & 0xffff,
+ event.ArbitResult.arbit_node);
+ break;
+ case NDB_LE_DeadDueToHeartbeat:
+ printf("Node %d: DeadDueToHeartbeat\n", event.source_nodeid);
+ printf(" node %d\n", event.DeadDueToHeartbeat.node);
+ break;
+
+ case NDB_LE_Connected:
+ printf("Node %d: Connected\n", event.source_nodeid);
+ printf(" node %d\n", event.Connected.node);
+ break;
+ case NDB_LE_Disconnected:
+ printf("Node %d: Disconnected\n", event.source_nodeid);
+ printf(" node %d\n", event.Disconnected.node);
+ break;
+ case NDB_LE_NDBStartCompleted:
+ printf("Node %d: StartCompleted\n", event.source_nodeid);
+ printf(" version %d.%d.%d\n",
+ event.NDBStartCompleted.version >> 16 & 0xff,
+ event.NDBStartCompleted.version >> 8 & 0xff,
+ event.NDBStartCompleted.version >> 0 & 0xff);
+ break;
+ case NDB_LE_ArbitState:
+ printf("Node %d: ArbitState\n", event.source_nodeid);
+ printf(" code %d, arbit_node %d\n",
+ event.ArbitState.code & 0xffff,
+ event.ArbitResult.arbit_node);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ ndb_mgm_destroy_logevent_handle(&le);
+ ndb_mgm_destroy_handle(&h);
+ ndb_end(0);
+ return 0;
+}
diff --git a/ndb/ndbapi-examples/ndbapi_async_example/Makefile b/ndb/ndbapi-examples/ndbapi_async_example/Makefile
new file mode 100644
index 00000000000..55e4a13343f
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_async_example/Makefile
@@ -0,0 +1,23 @@
+TARGET = ndbapi_async
+SRCS = $(TARGET).cpp
+OBJS = $(TARGET).o
+CXX = g++
+CFLAGS = -g -c -Wall -fno-rtti -fno-exceptions
+CXXFLAGS = -g
+DEBUG =
+LFLAGS = -Wall
+TOP_SRCDIR = ../../..
+INCLUDE_DIR = $(TOP_SRCDIR)
+LIB_DIR = -L$(TOP_SRCDIR)/ndb/src/.libs \
+ -L$(TOP_SRCDIR)/libmysql_r/.libs \
+ -L$(TOP_SRCDIR)/mysys -L$(TOP_SRCDIR)/strings
+SYS_LIB =
+
+$(TARGET): $(OBJS)
+ $(CXX) $(CXXFLAGS) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET)
+
+$(TARGET).o: $(SRCS)
+ $(CXX) $(CFLAGS) -I$(INCLUDE_DIR)/include -I$(INCLUDE_DIR)/extra -I$(INCLUDE_DIR)/ndb/include -I$(INCLUDE_DIR)/ndb/include/ndbapi $(SRCS)
+
+clean:
+ rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_async_example/ndbapi_async.cpp b/ndb/ndbapi-examples/ndbapi_async_example/ndbapi_async.cpp
index 76ce1a8efe3..aa745f4d28d 100644
--- a/ndb/examples/ndbapi_async_example/ndbapi_async.cpp
+++ b/ndb/ndbapi-examples/ndbapi_async_example/ndbapi_async.cpp
@@ -24,10 +24,12 @@
*
* Classes and methods in NDBAPI used in this example:
*
+ * Ndb_cluster_connection
+ * connect()
+ * wait_until_ready()
+ *
* Ndb
* init()
- * waitUntilRead()
- * getDictionary()
* startTransaction()
* closeTransaction()
* sendPollNdb()
@@ -38,23 +40,6 @@
* executeAsynchPrepare()
* getNdbError()
*
- * NdbDictionary::Dictionary
- * getTable()
- * dropTable()
- * createTable()
- * getNdbError()
- *
- * NdbDictionary::Column
- * setName()
- * setType()
- * setLength()
- * setPrimaryKey()
- * setNullable()
- *
- * NdbDictionary::Table
- * setName()
- * addColumn()
- *
* NdbOperation
* insertTuple()
* equal()
@@ -63,33 +48,37 @@
*/
-#include <ndb_global.h>
-
+#include <mysql.h>
+#include <mysqld_error.h>
#include <NdbApi.hpp>
-#include <NdbScanFilter.hpp>
+
#include <iostream> // Used for cout
/**
* Helper sleep function
*/
-int
+static void
milliSleep(int milliseconds){
- int result = 0;
- struct timespec sleeptime;
+ struct timeval sleeptime;
sleeptime.tv_sec = milliseconds / 1000;
- sleeptime.tv_nsec = (milliseconds - (sleeptime.tv_sec * 1000)) * 1000000;
- result = nanosleep(&sleeptime, NULL);
- return result;
+ sleeptime.tv_usec = (milliseconds - (sleeptime.tv_sec * 1000)) * 1000000;
+ select(0, 0, 0, 0, &sleeptime);
}
+
/**
* error printout macro
*/
-#define APIERROR(error) \
- { std::cout << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
- << error.code << ", msg: " << error.message << "." << std::endl; \
- exit(-1); }
-
+#define PRINT_ERROR(code,msg) \
+ std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
+ << ", code: " << code \
+ << ", msg: " << msg << "." << std::endl
+#define MYSQLERROR(mysql) { \
+ PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
+ exit(-1); }
+#define APIERROR(error) { \
+ PRINT_ERROR(error.code,error.message); \
+ exit(-1); }
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
@@ -106,10 +95,10 @@ typedef struct {
} async_callback_t;
/**
- * Structure used in "free list" to a NdbConnection
+ * Structure used in "free list" to a NdbTransaction
*/
typedef struct {
- NdbConnection* conn;
+ NdbTransaction* conn;
int used;
} transaction_t;
@@ -132,7 +121,7 @@ int populate(Ndb * myNdb, int data, async_callback_t * cbData);
/**
* Error handler.
*/
-bool asynchErrorHandler(NdbConnection * trans, Ndb* ndb);
+bool asynchErrorHandler(NdbTransaction * trans, Ndb* ndb);
/**
* Exit function
@@ -155,9 +144,6 @@ int create_table(Ndb * myNdb);
int tempErrors = 0;
int permErrors = 0;
-/**
- * Helper function for callback(...)
- */
void
closeTransaction(Ndb * ndb , async_callback_t * cb)
{
@@ -171,7 +157,7 @@ closeTransaction(Ndb * ndb , async_callback_t * cb)
* Callback executed when transaction has return from NDB
*/
static void
-callback(int result, NdbConnection* trans, void* aObject)
+callback(int result, NdbTransaction* trans, void* aObject)
{
async_callback_t * cbData = (async_callback_t *)aObject;
if (result<0)
@@ -207,61 +193,26 @@ callback(int result, NdbConnection* trans, void* aObject)
/**
* Create table "GARAGE"
*/
-int create_table(Ndb * myNdb)
+int create_table(MYSQL &mysql)
{
- NdbDictionary::Table myTable;
- NdbDictionary::Column myColumn;
-
- NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
-
- /*********************************************************
- * Create a table named GARAGE if it does not exist *
- *********************************************************/
- if (myDict->getTable("GARAGE") != NULL)
+ while (mysql_query(&mysql,
+ "CREATE TABLE"
+ " GARAGE"
+ " (REG_NO INT UNSIGNED NOT NULL,"
+ " BRAND CHAR(20) NOT NULL,"
+ " COLOR CHAR(20) NOT NULL,"
+ " PRIMARY KEY USING HASH (REG_NO))"
+ " ENGINE=NDB"))
{
- std::cout << "NDB already has example table: GARAGE. "
+ if (mysql_errno(&mysql) != ER_TABLE_EXISTS_ERROR)
+ MYSQLERROR(mysql);
+ std::cout << "MySQL Cluster already has example table: GARAGE. "
<< "Dropping it..." << std::endl;
- if(myDict->dropTable("GARAGE") == -1)
- {
- std::cout << "Failed to drop: GARAGE." << std::endl;
- exit(1);
- }
- }
-
- myTable.setName("GARAGE");
-
-/**
- * Column REG_NO
- */
- myColumn.setName("REG_NO");
- myColumn.setType(NdbDictionary::Column::Unsigned);
- myColumn.setLength(1);
- myColumn.setPrimaryKey(true);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
-/**
- * Column BRAND
- */
- myColumn.setName("BRAND");
- myColumn.setType(NdbDictionary::Column::Char);
- myColumn.setLength(20);
- myColumn.setPrimaryKey(false);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
-/**
- * Column COLOR
- */
- myColumn.setName("COLOR");
- myColumn.setType(NdbDictionary::Column::Char);
- myColumn.setLength(20);
- myColumn.setPrimaryKey(false);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
- if (myDict->createTable(myTable) == -1) {
- APIERROR(myDict->getNdbError());
+ /**************
+ * Drop table *
+ **************/
+ if (mysql_query(&mysql, "DROP TABLE GARAGE"))
+ MYSQLERROR(mysql);
}
return 1;
}
@@ -276,7 +227,7 @@ void asynchExitHandler(Ndb * m_ndb)
/* returns true if is recoverable (temporary),
* false if it is an error that is permanent.
*/
-bool asynchErrorHandler(NdbConnection * trans, Ndb* ndb)
+bool asynchErrorHandler(NdbTransaction * trans, Ndb* ndb)
{
NdbError error = trans->getNdbError();
switch(error.status)
@@ -339,6 +290,10 @@ int populate(Ndb * myNdb, int data, async_callback_t * cbData)
{
NdbOperation* myNdbOperation; // For operations
+ const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
async_callback_t * cb;
int retries = 0;
@@ -395,8 +350,7 @@ int populate(Ndb * myNdb, int data, async_callback_t * cbData)
}
asynchExitHandler(myNdb);
}
- // Error check. If error, then maybe table GARAGE is not in database
- myNdbOperation = transaction[current].conn->getNdbOperation("GARAGE");
+ myNdbOperation = transaction[current].conn->getNdbOperation(myTable);
if (myNdbOperation == NULL)
{
if (asynchErrorHandler(transaction[current].conn, myNdb))
@@ -426,7 +380,7 @@ int populate(Ndb * myNdb, int data, async_callback_t * cbData)
}
/*Prepare transaction (the transaction is NOT yet sent to NDB)*/
- transaction[current].conn->executeAsynchPrepare(Commit,
+ transaction[current].conn->executeAsynchPrepare(NdbTransaction::Commit,
&callback,
cb);
/**
@@ -455,22 +409,48 @@ int populate(Ndb * myNdb, int data, async_callback_t * cbData)
int main()
{
ndb_init();
- Ndb* myNdb = new Ndb( "TEST_DB" ); // Object representing the database
-
- /*******************************************
- * Initialize NDB and wait until its ready *
- *******************************************/
- if (myNdb->init(1024) == -1) { // Set max 1024 parallel transactions
- APIERROR(myNdb->getNdbError());
+ MYSQL mysql;
+
+ /**************************************************************
+ * Connect to mysql server and create table *
+ **************************************************************/
+ {
+ if ( !mysql_init(&mysql) ) {
+ std::cout << "mysql_init failed\n";
+ exit(-1);
+ }
+ if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
+ 3306, "/tmp/mysql.sock", 0) )
+ MYSQLERROR(mysql);
+
+ mysql_query(&mysql, "CREATE DATABASE TEST_DB");
+ if (mysql_query(&mysql, "USE TEST_DB") != 0) MYSQLERROR(mysql);
+
+ create_table(mysql);
}
- if (myNdb->waitUntilReady(30) != 0) {
- std::cout << "NDB was not ready within 30 secs." << std::endl;
+ /**************************************************************
+ * Connect to ndb cluster *
+ **************************************************************/
+ Ndb_cluster_connection cluster_connection;
+ if (cluster_connection.connect(4, 5, 1))
+ {
+ std::cout << "Unable to connect to cluster within 30 secs." << std::endl;
exit(-1);
}
- create_table(myNdb);
+ // Optionally connect and wait for the storage nodes (ndbd's)
+ if (cluster_connection.wait_until_ready(30,0) < 0)
+ {
+ std::cout << "Cluster was not ready within 30 secs.\n";
+ exit(-1);
+ }
+
+ Ndb* myNdb = new Ndb( &cluster_connection,
+ "TEST_DB" ); // Object representing the database
+ if (myNdb->init(1024) == -1) { // Set max 1024 parallel transactions
+ APIERROR(myNdb->getNdbError());
+ }
-
/**
* Initialise transaction array
*/
diff --git a/ndb/examples/ndbapi_async_example/readme.txt b/ndb/ndbapi-examples/ndbapi_async_example/readme.txt
index 47cb4bf9ffa..47cb4bf9ffa 100644
--- a/ndb/examples/ndbapi_async_example/readme.txt
+++ b/ndb/ndbapi-examples/ndbapi_async_example/readme.txt
diff --git a/ndb/ndbapi-examples/ndbapi_async_example1/Makefile b/ndb/ndbapi-examples/ndbapi_async_example1/Makefile
new file mode 100644
index 00000000000..7f6ea0b4d25
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_async_example1/Makefile
@@ -0,0 +1,21 @@
+TARGET = ndbapi_async1
+SRCS = ndbapi_async1.cpp
+OBJS = ndbapi_async1.o
+CXX = g++
+CFLAGS = -c -Wall -fno-rtti -fno-exceptions
+DEBUG =
+LFLAGS = -Wall
+INCLUDE_DIR = ../../include
+LIB_DIR = -L../../src/.libs \
+ -L../../../libmysql_r/.libs \
+ -L../../../mysys -L../../../strings
+SYS_LIB =
+
+$(TARGET): $(OBJS)
+ $(CXX) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET)
+
+$(TARGET).o: $(SRCS)
+ $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
+
+clean:
+ rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_example2/ndbapi_example2.cpp b/ndb/ndbapi-examples/ndbapi_async_example1/ndbapi_async1.cpp
index 95a7bae66b8..e8bc19e267b 100644
--- a/ndb/examples/ndbapi_example2/ndbapi_example2.cpp
+++ b/ndb/ndbapi-examples/ndbapi_async_example1/ndbapi_async1.cpp
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
//
-// ndbapi_example2.cpp: Using asynchronous transactions in NDB API
+// ndbapi_async1.cpp: Using asynchronous transactions in NDB API
//
// Execute ndbapi_example1 to create the table "MYTABLENAME"
// before executing this program.
@@ -35,46 +35,75 @@
<< error.code << ", msg: " << error.message << "." << std::endl; \
exit(-1); }
-static void callback(int result, NdbConnection* NdbObject, void* aObject);
+static void callback(int result, NdbTransaction* NdbObject, void* aObject);
int main()
{
ndb_init();
- Ndb* myNdb = new Ndb( "TEST_DB_2" ); // Object representing the database
- NdbConnection* myNdbConnection[2]; // For transactions
+ Ndb_cluster_connection *cluster_connection=
+ new Ndb_cluster_connection(); // Object representing the cluster
+
+ if (cluster_connection->wait_until_ready(30,30))
+ {
+ std::cout << "Cluster was not ready within 30 secs." << std::endl;
+ exit(-1);
+ }
+
+ int r= cluster_connection->connect(5 /* retries */,
+ 3 /* delay between retries */,
+ 1 /* verbose */);
+ if (r > 0)
+ {
+ std::cout
+ << "Cluster connect failed, possibly resolved with more retries.\n";
+ exit(-1);
+ }
+ else if (r < 0)
+ {
+ std::cout
+ << "Cluster connect failed.\n";
+ exit(-1);
+ }
+
+ if (cluster_connection->wait_until_ready(30,30))
+ {
+ std::cout << "Cluster was not ready within 30 secs." << std::endl;
+ exit(-1);
+ }
+
+ Ndb* myNdb = new Ndb( cluster_connection,
+ "TEST_DB_2" ); // Object representing the database
+
+ NdbTransaction* myNdbTransaction[2]; // For transactions
NdbOperation* myNdbOperation; // For operations
- /*******************************************
- * Initialize NDB and wait until its ready *
- *******************************************/
if (myNdb->init(2) == -1) { // Want two parallel insert transactions
APIERROR(myNdb->getNdbError());
exit(-1);
}
- if (myNdb->waitUntilReady(30) != 0) {
- std::cout << "NDB was not ready within 30 secs." << std::endl;
- exit(-1);
- }
-
/******************************************************
* Insert (we do two insert transactions in parallel) *
******************************************************/
+ const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
for (int i = 0; i < 2; i++) {
- myNdbConnection[i] = myNdb->startTransaction();
- if (myNdbConnection[i] == NULL) APIERROR(myNdb->getNdbError());
+ myNdbTransaction[i] = myNdb->startTransaction();
+ if (myNdbTransaction[i] == NULL) APIERROR(myNdb->getNdbError());
- myNdbOperation = myNdbConnection[i]->getNdbOperation("MYTABLENAME");
- // Error check. If error, then maybe table MYTABLENAME is not in database
- if (myNdbOperation == NULL) APIERROR(myNdbConnection[i]->getNdbError());
+ myNdbOperation = myNdbTransaction[i]->getNdbOperation(myTable);
+ if (myNdbOperation == NULL) APIERROR(myNdbTransaction[i]->getNdbError());
myNdbOperation->insertTuple();
myNdbOperation->equal("ATTR1", 20 + i);
myNdbOperation->setValue("ATTR2", 20 + i);
// Prepare transaction (the transaction is NOT yet sent to NDB)
- myNdbConnection[i]->executeAsynchPrepare(Commit, &callback, NULL);
+ myNdbTransaction[i]->executeAsynchPrepare(NdbTransaction::Commit,
+ &callback, NULL);
}
// Send all transactions to NDB
@@ -85,9 +114,13 @@ int main()
// Close all transactions
for (int i = 0; i < 2; i++)
- myNdb->closeTransaction(myNdbConnection[i]);
+ myNdb->closeTransaction(myNdbTransaction[i]);
delete myNdb;
+ delete cluster_connection;
+
+ ndb_end(0);
+ return 0;
}
/*
@@ -95,12 +128,12 @@ int main()
*
* (This function must have three arguments:
* - The result of the transaction,
- * - The NdbConnection object, and
+ * - The NdbTransaction object, and
* - A pointer to an arbitrary object.)
*/
static void
-callback(int result, NdbConnection* myTrans, void* aObject)
+callback(int result, NdbTransaction* myTrans, void* aObject)
{
if (result == -1) {
std::cout << "Poll error: " << std::endl;
diff --git a/ndb/ndbapi-examples/ndbapi_event_example/Makefile b/ndb/ndbapi-examples/ndbapi_event_example/Makefile
new file mode 100644
index 00000000000..12e109c654f
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_event_example/Makefile
@@ -0,0 +1,23 @@
+TARGET = ndbapi_event
+SRCS = ndbapi_event.cpp
+OBJS = ndbapi_event.o
+CXX = g++
+CFLAGS = -c -Wall -fno-rtti -fno-exceptions
+CXXFLAGS =
+DEBUG =
+LFLAGS = -Wall
+TOP_SRCDIR = ../../..
+INCLUDE_DIR = $(TOP_SRCDIR)/ndb/include
+LIB_DIR = -L$(TOP_SRCDIR)/ndb/src/.libs \
+ -L$(TOP_SRCDIR)/libmysql_r/.libs \
+ -L$(TOP_SRCDIR)/mysys -L$(TOP_SRCDIR)/strings
+SYS_LIB =
+
+$(TARGET): $(OBJS)
+ $(CXX) $(CXXFLAGS) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET)
+
+$(TARGET).o: $(SRCS)
+ $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
+
+clean:
+ rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_example5/ndbapi_example5.cpp b/ndb/ndbapi-examples/ndbapi_event_example/ndbapi_event.cpp
index 77f74e7bb63..286f6fafbab 100644
--- a/ndb/examples/ndbapi_example5/ndbapi_example5.cpp
+++ b/ndb/ndbapi-examples/ndbapi_event_example/ndbapi_event.cpp
@@ -15,11 +15,41 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/**
- * ndbapi_example5.cpp: Using API level events in NDB API
+ * ndbapi_event.cpp: Using API level events in NDB API
+ *
+ * Classes and methods used in this example:
+ *
+ * Ndb_cluster_connection
+ * connect()
+ * wait_until_ready()
+ *
+ * Ndb
+ * init()
+ * getDictionary()
+ * createEventOperation()
+ * dropEventOperation()
+ * pollEvents()
+ *
+ * NdbDictionary
+ * createEvent()
+ * dropEvent()
+ *
+ * NdbDictionary::Event
+ * setTable()
+ * addTableEvent()
+ * addEventColumn()
+ *
+ * NdbEventOperation
+ * getValue()
+ * getPreValue()
+ * execute()
+ * next()
+ * isConsistent()
+ * getEventType()
+ *
*/
#include <NdbApi.hpp>
-#include <NdbEventOperation.hpp>
// Used for cout
#include <stdio.h>
@@ -33,19 +63,20 @@
* another process (e.g. flexBench -l 0 -stdtables).
* We want to monitor what happens with columns COL0, COL2, COL11
*
- * or together with the mysqlcluster client;
+ * or together with the mysql client;
*
- * shell> mysqlcluster -u root
+ * shell> mysql -u root
* mysql> create database TEST_DB;
* mysql> use TEST_DB;
- * mysql> create table TAB0 (COL0 int primary key, COL1 int, COL11 int);
+ * mysql> create table TAB0 (COL0 int primary key, COL1 int, COL11 int) engine=ndb;
*
- * In another window start ndbapi_example5, wait until properly started
+ * In another window start ndbapi_event, wait until properly started
*
- * mysql> insert into TAB0 values (1,2,3);
- * mysql> insert into TAB0 values (2,2,3);
- * mysql> insert into TAB0 values (3,2,9);
- * mysql>
+ insert into TAB0 values (1,2,3);
+ insert into TAB0 values (2,2,3);
+ insert into TAB0 values (3,2,9);
+ update TAB0 set COL1=10 where COL0=1;
+ delete from TAB0 where COL0=1;
*
* you should see the data popping up in the example window
*
@@ -56,45 +87,69 @@
<< error.code << ", msg: " << error.message << "." << std::endl; \
exit(-1); }
-Ndb* myCreateNdb();
int myCreateEvent(Ndb* myNdb,
const char *eventName,
const char *eventTableName,
- const char **eventComlumnName,
- const int noEventComlumnName);
+ const char **eventColumnName,
+ const int noEventColumnName);
int main()
{
ndb_init();
- Ndb* myNdb = myCreateNdb();
- NdbDictionary::Dictionary *myDict;
- const char *eventName = "CHNG_IN_TAB0";
- const char *eventTableName = "TAB0";
- const int noEventColumnName = 3;
- const char *eventColumnName[noEventColumnName] =
+ Ndb_cluster_connection *cluster_connection=
+ new Ndb_cluster_connection(); // Object representing the cluster
+
+ int r= cluster_connection->connect(5 /* retries */,
+ 3 /* delay between retries */,
+ 1 /* verbose */);
+ if (r > 0)
+ {
+ std::cout
+ << "Cluster connect failed, possibly resolved with more retries.\n";
+ exit(-1);
+ }
+ else if (r < 0)
+ {
+ std::cout
+ << "Cluster connect failed.\n";
+ exit(-1);
+ }
+
+ if (cluster_connection->wait_until_ready(30,30))
+ {
+ std::cout << "Cluster was not ready within 30 secs." << std::endl;
+ exit(-1);
+ }
+
+ Ndb* myNdb= new Ndb(cluster_connection,
+ "TEST_DB"); // Object representing the database
+
+ if (myNdb->init() == -1) APIERROR(myNdb->getNdbError());
+
+ const char *eventName= "CHNG_IN_TAB0";
+ const char *eventTableName= "TAB0";
+ const int noEventColumnName= 3;
+ const char *eventColumnName[noEventColumnName]=
{"COL0",
"COL1",
"COL11"};
- myDict = myNdb->getDictionary();
-
// Create events
myCreateEvent(myNdb,
eventName,
eventTableName,
eventColumnName,
noEventColumnName);
- int j = 0;
+
+ int j= 0;
while (j < 5) {
// Start "transaction" for handling events
NdbEventOperation* op;
printf("create EventOperation\n");
- if ((op = myNdb->createEventOperation(eventName,100)) == NULL) {
- printf("Event operation creation failed\n");
- exit(-1);
- }
+ if ((op = myNdb->createEventOperation(eventName,100)) == NULL)
+ APIERROR(myNdb->getNdbError());
printf("get values\n");
NdbRecAttr* recAttr[noEventColumnName];
@@ -107,23 +162,21 @@ int main()
// set up the callbacks
printf("execute\n");
- if (op->execute()) { // This starts changes to "start flowing"
- printf("operationd execution failed\n");
- exit(-1);
- }
-
- int i = 0;
+ // This starts changes to "start flowing"
+ if (op->execute())
+ APIERROR(op->getNdbError());
+ int i= 0;
while(i < 40) {
- //printf("now waiting for event...\n");
- int r = myNdb->pollEvents(1000); // wait for event or 1000 ms
- if (r>0) {
- //printf("got data! %d\n", r);
+ // printf("now waiting for event...\n");
+ int r= myNdb->pollEvents(1000); // wait for event or 1000 ms
+ if (r > 0) {
+ // printf("got data! %d\n", r);
int overrun;
while (op->next(&overrun) > 0) {
i++;
if (!op->isConsistent())
- printf("A node failiure has occured and events might be missing\n");
+ printf("A node failure has occured and events might be missing\n");
switch (op->getEventType()) {
case NdbDictionary::Event::TE_INSERT:
printf("%u INSERT: ", i);
@@ -134,6 +187,8 @@ int main()
case NdbDictionary::Event::TE_UPDATE:
printf("%u UPDATE: ", i);
break;
+ default:
+ abort(); // should not happen
}
printf("overrun %u pk %u: ", overrun, recAttr[0]->u_32_value());
for (int i = 1; i < noEventColumnName; i++) {
@@ -145,7 +200,7 @@ int main()
printf("NULL");
}
if (recAttrPre[i]->isNULL() >= 0) { // we have a value
- printf(" post[%u]=", i);
+ printf(" pre[%u]=", i);
if (recAttrPre[i]->isNULL() == 0) // we have a non-null value
printf("%u", recAttrPre[i]->u_32_value());
else // we have a null value
@@ -157,75 +212,58 @@ int main()
} else
;//printf("timed out\n");
}
- // don't want to listen to eventsanymore
- myNdb->dropEventOperation(op);
+ // don't want to listen to events anymore
+ if (myNdb->dropEventOperation(op)) APIERROR(myNdb->getNdbError());
j++;
}
- myDict->dropEvent(eventName); // remove event from database
-
- delete myNdb;
-}
-
-Ndb* myCreateNdb()
-{
- Ndb* myNdb = new Ndb("TEST_DB");
-
- /********************************************
- * Initialize NDB and wait until it's ready *
- ********************************************/
- if (myNdb->init() == -1) {
- APIERROR(myNdb->getNdbError());
- exit(-1);
- }
-
- if (myNdb->waitUntilReady(30) != 0) {
- std::cout << "NDB was not ready within 30 secs." << std::endl;
- exit(-1);
+ {
+ NdbDictionary::Dictionary *myDict = myNdb->getDictionary();
+ if (!myDict) APIERROR(myNdb->getNdbError());
+ // remove event from database
+ if (myDict->dropEvent(eventName)) APIERROR(myDict->getNdbError());
}
- return myNdb;
+ delete myNdb;
+ delete cluster_connection;
+ ndb_end(0);
+ return 0;
}
int myCreateEvent(Ndb* myNdb,
const char *eventName,
const char *eventTableName,
- const char **eventColumnName,
- const int noEventColumnName)
+ const char **eventColumnNames,
+ const int noEventColumnNames)
{
- NdbDictionary::Dictionary *myDict = myNdb->getDictionary();
+ NdbDictionary::Dictionary *myDict= myNdb->getDictionary();
+ if (!myDict) APIERROR(myNdb->getNdbError());
- if (!myDict) {
- printf("Event Creation failedDictionary not found");
- exit(-1);
- }
+ const NdbDictionary::Table *table= myDict->getTable(eventTableName);
+ if (!table) APIERROR(myDict->getNdbError());
- NdbDictionary::Event myEvent(eventName);
- myEvent.setTable(eventTableName);
+ NdbDictionary::Event myEvent(eventName, *table);
myEvent.addTableEvent(NdbDictionary::Event::TE_ALL);
// myEvent.addTableEvent(NdbDictionary::Event::TE_INSERT);
// myEvent.addTableEvent(NdbDictionary::Event::TE_UPDATE);
// myEvent.addTableEvent(NdbDictionary::Event::TE_DELETE);
- for (int i = 0; i < noEventColumnName; i++)
- myEvent.addEventColumn(eventColumnName[i]);
+ myEvent.addEventColumns(noEventColumnNames, eventColumnNames);
- int res = myDict->createEvent(myEvent); // Add event to database
-
- if (res == 0)
+ // Add event to database
+ if (myDict->createEvent(myEvent) == 0)
myEvent.print();
- else {
- printf("Event creation failed\n");
- printf("trying drop Event, maybe event exists\n");
- res = myDict->dropEvent(eventName);
- if (res)
- exit(-1);
+ else if (myDict->getNdbError().classification ==
+ NdbError::SchemaObjectExists) {
+ printf("Event creation failed, event exists\n");
+ printf("dropping Event...\n");
+ if (myDict->dropEvent(eventName)) APIERROR(myDict->getNdbError());
// try again
- res = myDict->createEvent(myEvent); // Add event to database
- if (res)
- exit(-1);
- }
+ // Add event to database
+ if ( myDict->createEvent(myEvent)) APIERROR(myDict->getNdbError());
+ } else
+ APIERROR(myDict->getNdbError());
- return res;
+ return 0;
}
diff --git a/ndb/ndbapi-examples/ndbapi_retries_example/Makefile b/ndb/ndbapi-examples/ndbapi_retries_example/Makefile
new file mode 100644
index 00000000000..829a7009031
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_retries_example/Makefile
@@ -0,0 +1,21 @@
+TARGET = ndbapi_retries
+SRCS = ndbapi_retries.cpp
+OBJS = ndbapi_retries.o
+CXX = g++
+CFLAGS = -c -Wall -fno-rtti -fno-exceptions
+DEBUG =
+LFLAGS = -Wall
+INCLUDE_DIR = ../../include
+LIB_DIR = -L../../src/.libs \
+ -L../../../libmysql_r/.libs \
+ -L../../../mysys -L../../../strings
+SYS_LIB =
+
+$(TARGET): $(OBJS)
+ $(CXX) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET)
+
+$(TARGET).o: $(SRCS)
+ $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS)
+
+clean:
+ rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_example3/ndbapi_example3.cpp b/ndb/ndbapi-examples/ndbapi_retries_example/ndbapi_retries.cpp
index 91d9ff122ba..8c29fe31446 100644
--- a/ndb/examples/ndbapi_example3/ndbapi_example3.cpp
+++ b/ndb/ndbapi-examples/ndbapi_retries_example/ndbapi_retries.cpp
@@ -15,14 +15,14 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
//
-// ndbapi_example3.cpp: Error handling and transaction retries
+// ndbapi_retries.cpp: Error handling and transaction retries
//
-// Execute ndbapi_example1 to create the table "MYTABLENAME"
+// Execute ndbapi_simple to create the table "MYTABLENAME"
// before executing this program.
//
// There are many ways to program using the NDB API. In this example
// we execute two inserts in the same transaction using
-// NdbConnection::Ndbexecute(NoCommit).
+// NdbConnection::execute(NoCommit).
//
// Transaction failing is handled by re-executing the transaction
// in case of non-permanent transaction errors.
@@ -52,28 +52,28 @@
}
//
-// CONERROR prints all error info regarding an NdbConnection
+// TRANSERROR prints all error info regarding an NdbTransaction
//
-#define CONERROR(ndbConnection) \
- { NdbError error = ndbConnection->getNdbError(); \
- std::cout << "CON ERROR: " << error.code << " " << error.message \
+#define TRANSERROR(ndbTransaction) \
+ { NdbError error = ndbTransaction->getNdbError(); \
+ std::cout << "TRANS ERROR: " << error.code << " " << error.message \
<< std::endl \
<< " " << "Status: " << error.status \
<< ", Classification: " << error.classification << std::endl \
<< " " << "File: " << __FILE__ \
<< " (Line: " << __LINE__ << ")" << std::endl \
; \
- printTransactionError(ndbConnection); \
+ printTransactionError(ndbTransaction); \
}
-void printTransactionError(NdbConnection *ndbConnection) {
+void printTransactionError(NdbTransaction *ndbTransaction) {
const NdbOperation *ndbOp = NULL;
int i=0;
/****************************************************************
* Print NdbError object of every operations in the transaction *
****************************************************************/
- while ((ndbOp = ndbConnection->getNextCompletedOperation(ndbOp)) != NULL) {
+ while ((ndbOp = ndbTransaction->getNextCompletedOperation(ndbOp)) != NULL) {
NdbError error = ndbOp->getNdbError();
std::cout << " OPERATION " << i+1 << ": "
<< error.code << " " << error.message << std::endl
@@ -86,15 +86,17 @@ void printTransactionError(NdbConnection *ndbConnection) {
//
// Example insert
-// @param myNdb Ndb object representing NDB Cluster
-// @param myConnection NdbConnection used for transaction
-// @param error NdbError object returned in case of errors
+// @param myNdb Ndb object representing NDB Cluster
+// @param myTransaction NdbTransaction used for transaction
+// @param myTable Table to insert into
+// @param error NdbError object returned in case of errors
// @return -1 in case of failures, 0 otherwise
//
-int insert(int transactionId, NdbConnection* myConnection) {
+int insert(int transactionId, NdbTransaction* myTransaction,
+ const NdbDictionary::Table *myTable) {
NdbOperation *myOperation; // For other operations
- myOperation = myConnection->getNdbOperation("MYTABLENAME");
+ myOperation = myTransaction->getNdbOperation(myTable);
if (myOperation == NULL) return -1;
if (myOperation->insertTuple() ||
@@ -104,7 +106,7 @@ int insert(int transactionId, NdbConnection* myConnection) {
exit(-1);
}
- return myConnection->execute(NoCommit);
+ return myTransaction->execute(NdbTransaction::NoCommit);
}
@@ -113,10 +115,11 @@ int insert(int transactionId, NdbConnection* myConnection) {
// if there are temporary errors (e.g. the NDB Cluster is overloaded).
// @return -1 failure, 1 success
//
-int executeInsertTransaction(int transactionId, Ndb* myNdb) {
+int executeInsertTransaction(int transactionId, Ndb* myNdb,
+ const NdbDictionary::Table *myTable) {
int result = 0; // No result yet
int noOfRetriesLeft = 10;
- NdbConnection *myConnection; // For other transactions
+ NdbTransaction *myTransaction; // For other transactions
NdbError ndberror;
while (noOfRetriesLeft > 0 && !result) {
@@ -124,16 +127,16 @@ int executeInsertTransaction(int transactionId, Ndb* myNdb) {
/*********************************
* Start and execute transaction *
*********************************/
- myConnection = myNdb->startTransaction();
- if (myConnection == NULL) {
+ myTransaction = myNdb->startTransaction();
+ if (myTransaction == NULL) {
APIERROR(myNdb->getNdbError());
ndberror = myNdb->getNdbError();
result = -1; // Failure
- } else if (insert(transactionId, myConnection) ||
- insert(10000+transactionId, myConnection) ||
- myConnection->execute(Commit)) {
- CONERROR(myConnection);
- ndberror = myConnection->getNdbError();
+ } else if (insert(transactionId, myTransaction, myTable) ||
+ insert(10000+transactionId, myTransaction, myTable) ||
+ myTransaction->execute(NdbTransaction::Commit)) {
+ TRANSERROR(myTransaction);
+ ndberror = myTransaction->getNdbError();
result = -1; // Failure
} else {
result = 1; // Success
@@ -164,8 +167,8 @@ int executeInsertTransaction(int transactionId, Ndb* myNdb) {
/*********************
* Close transaction *
*********************/
- if (myConnection != NULL) {
- myNdb->closeTransaction(myConnection);
+ if (myTransaction != NULL) {
+ myNdb->closeTransaction(myTransaction);
}
}
@@ -177,27 +180,57 @@ int executeInsertTransaction(int transactionId, Ndb* myNdb) {
int main()
{
ndb_init();
- Ndb* myNdb = new Ndb( "TEST_DB_1" ); // Object representing the database
+
+ Ndb_cluster_connection *cluster_connection=
+ new Ndb_cluster_connection(); // Object representing the cluster
+
+ int r= cluster_connection->connect(5 /* retries */,
+ 3 /* delay between retries */,
+ 1 /* verbose */);
+ if (r > 0)
+ {
+ std::cout
+ << "Cluster connect failed, possibly resolved with more retries.\n";
+ exit(-1);
+ }
+ else if (r < 0)
+ {
+ std::cout
+ << "Cluster connect failed.\n";
+ exit(-1);
+ }
+
+ if (cluster_connection->wait_until_ready(30,30))
+ {
+ std::cout << "Cluster was not ready within 30 secs." << std::endl;
+ exit(-1);
+ }
+
+ Ndb* myNdb= new Ndb( cluster_connection,
+ "TEST_DB_1" ); // Object representing the database
- /*******************************************
- * Initialize NDB and wait until its ready *
- *******************************************/
- if (myNdb->init() == -1) {
+ if (myNdb->init() == -1) {
APIERROR(myNdb->getNdbError());
exit(-1);
}
- if (myNdb->waitUntilReady(30) != 0) {
- std::cout << "NDB was not ready within 30 secs." << std::endl;
- exit(-1);
+ const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
+ if (myTable == NULL)
+ {
+ APIERROR(myDict->getNdbError());
+ return -1;
}
-
/************************************
* Execute some insert transactions *
************************************/
for (int i = 10000; i < 20000; i++) {
- executeInsertTransaction(i, myNdb);
+ executeInsertTransaction(i, myNdb, myTable);
}
delete myNdb;
+ delete cluster_connection;
+
+ ndb_end(0);
+ return 0;
}
diff --git a/ndb/ndbapi-examples/ndbapi_scan_example/Makefile b/ndb/ndbapi-examples/ndbapi_scan_example/Makefile
new file mode 100644
index 00000000000..31886b02bf1
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_scan_example/Makefile
@@ -0,0 +1,23 @@
+TARGET = ndbapi_scan
+SRCS = $(TARGET).cpp
+OBJS = $(TARGET).o
+CXX = g++
+CFLAGS = -g -c -Wall -fno-rtti -fno-exceptions
+CXXFLAGS = -g
+DEBUG =
+LFLAGS = -Wall
+TOP_SRCDIR = ../../..
+INCLUDE_DIR = $(TOP_SRCDIR)
+LIB_DIR = -L$(TOP_SRCDIR)/ndb/src/.libs \
+ -L$(TOP_SRCDIR)/libmysql_r/.libs \
+ -L$(TOP_SRCDIR)/mysys -L$(TOP_SRCDIR)/strings
+SYS_LIB =
+
+$(TARGET): $(OBJS)
+ $(CXX) $(CXXFLAGS) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET)
+
+$(TARGET).o: $(SRCS)
+ $(CXX) $(CFLAGS) -I$(INCLUDE_DIR)/include -I$(INCLUDE_DIR)/extra -I$(INCLUDE_DIR)/ndb/include -I$(INCLUDE_DIR)/ndb/include/ndbapi $(SRCS)
+
+clean:
+ rm -f *.o $(TARGET)
diff --git a/ndb/examples/ndbapi_scan_example/ndbapi_scan.cpp b/ndb/ndbapi-examples/ndbapi_scan_example/ndbapi_scan.cpp
index 22641bc5b57..69ffd99b8ca 100644
--- a/ndb/examples/ndbapi_scan_example/ndbapi_scan.cpp
+++ b/ndb/ndbapi-examples/ndbapi_scan_example/ndbapi_scan.cpp
@@ -24,171 +24,118 @@
*
* Classes and methods used in this example:
*
+ * Ndb_cluster_connection
+ * connect()
+ * wait_until_ready()
+ *
* Ndb
* init()
- * waitUntilRead()
* getDictionary()
* startTransaction()
* closeTransaction()
- * sendPreparedTransactions()
- * pollNdb()
*
- * NdbConnection
- * getNdbOperation()
- * executeAsynchPrepare()
- * getNdbError()
- * executeScan()
- * nextScanResult()
+ * NdbTransaction
+ * getNdbScanOperation()
+ * execute()
+ *
+ * NdbScanOperation
+ * getValue()
+ * readTuples()
+ * nextResult()
+ * deleteCurrentTuple()
+ * updateCurrentTuple()
*
- * NdbDictionary::Dictionary
+ * const NdbDictionary::Dictionary
* getTable()
- * dropTable()
- * createTable()
*
- * NdbDictionary::Column
- * setName()
- * setType()
- * setLength()
- * setPrimaryKey()
- * setNullable()
+ * const NdbDictionary::Table
+ * getColumn()
*
- * NdbDictionary::Table
- * setName()
- * addColumn()
+ * const NdbDictionary::Column
+ * getLength()
*
* NdbOperation
* insertTuple()
* equal()
* setValue()
- * openScanRead()
- * openScanExclusive()
- *
- * NdbRecAttr
- * aRef()
- * u_32_value()
- *
- * NdbResultSet
- * nextResult()
- * deleteTuple()
- * updateTuple()
- *
- * NdbScanOperation
- * getValue()
- * readTuplesExclusive()
*
* NdbScanFilter
* begin()
* eq()
* end()
*
- *
*/
-#include <ndb_global.h>
-
+#include <mysql.h>
+#include <mysqld_error.h>
#include <NdbApi.hpp>
-#include <NdbScanFilter.hpp>
// Used for cout
#include <iostream>
+#include <stdio.h>
/**
* Helper sleep function
*/
-int
+static void
milliSleep(int milliseconds){
- int result = 0;
- struct timespec sleeptime;
+ struct timeval sleeptime;
sleeptime.tv_sec = milliseconds / 1000;
- sleeptime.tv_nsec = (milliseconds - (sleeptime.tv_sec * 1000)) * 1000000;
- result = nanosleep(&sleeptime, NULL);
- return result;
+ sleeptime.tv_usec = (milliseconds - (sleeptime.tv_sec * 1000)) * 1000000;
+ select(0, 0, 0, 0, &sleeptime);
}
/**
* Helper sleep function
*/
-#define APIERROR(error) \
- { std::cout << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
- << error.code << ", msg: " << error.message << "." << std::endl; \
- exit(-1); }
-
-/*
- * 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* myTrans, void* aObject)
+#define PRINT_ERROR(code,msg) \
+ std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
+ << ", code: " << code \
+ << ", msg: " << msg << "." << std::endl
+#define MYSQLERROR(mysql) { \
+ PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
+ exit(-1); }
+#define APIERROR(error) { \
+ PRINT_ERROR(error.code,error.message); \
+ exit(-1); }
+
+struct Car
{
- if (result == -1) {
- std::cout << "In callback: " << std::endl;
- /**
- * Put error checking code here (see ndb_async_example)
- */
- APIERROR(myTrans->getNdbError());
- } else {
- /**
- * Ok!
- */
- return;
- }
-}
+ /**
+ * Note memset, so that entire char-fields are cleared
+ * as all 20 bytes are significant (as type is char)
+ */
+ Car() { memset(this, 0, sizeof(* this)); }
+
+ unsigned int reg_no;
+ char brand[20];
+ char color[20];
+};
/**
* Function to create table
*/
-int create_table(Ndb * myNdb)
+int create_table(MYSQL &mysql)
{
- NdbDictionary::Table myTable;
- NdbDictionary::Column myColumn;
-
- NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
-
- /*********************************************************
- * Create a table named GARAGE if it does not exist *
- *********************************************************/
- if (myDict->getTable("GARAGE") != NULL) {
- std::cout << "NDB already has example table: GARAGE. "
+ while (mysql_query(&mysql,
+ "CREATE TABLE"
+ " GARAGE"
+ " (REG_NO INT UNSIGNED NOT NULL,"
+ " BRAND CHAR(20) NOT NULL,"
+ " COLOR CHAR(20) NOT NULL,"
+ " PRIMARY KEY USING HASH (REG_NO))"
+ " ENGINE=NDB"))
+ {
+ if (mysql_errno(&mysql) != ER_TABLE_EXISTS_ERROR)
+ MYSQLERROR(mysql);
+ std::cout << "MySQL Cluster already has example table: GARAGE. "
<< "Dropping it..." << std::endl;
- if(myDict->dropTable("GARAGE") == -1)
- {
- std::cout << "Failed to drop: GARAGE." << std::endl;
- exit(1);
- }
- }
-
- myTable.setName("GARAGE");
-
- myColumn.setName("REG_NO");
- myColumn.setType(NdbDictionary::Column::Unsigned);
- myColumn.setLength(1);
- myColumn.setPrimaryKey(true);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
- myColumn.setName("BRAND");
- myColumn.setType(NdbDictionary::Column::Char);
- myColumn.setLength(20);
- myColumn.setPrimaryKey(false);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
-
- myColumn.setName("COLOR");
- myColumn.setType(NdbDictionary::Column::Char);
- myColumn.setLength(20);
- myColumn.setPrimaryKey(false);
- myColumn.setNullable(false);
- myTable.addColumn(myColumn);
-
- if (myDict->createTable(myTable) == -1) {
- APIERROR(myDict->getNdbError());
- return -1;
+ /**************
+ * Drop table *
+ **************/
+ if (mysql_query(&mysql, "DROP TABLE GARAGE"))
+ MYSQLERROR(mysql);
}
return 1;
}
@@ -196,93 +143,71 @@ int create_table(Ndb * myNdb)
int populate(Ndb * myNdb)
{
- NdbConnection* myNdbConnection[15]; // For transactions
- NdbOperation* myNdbOperation; // For operations
- /******************************************************
- * Insert (we do 15 insert transactions in parallel) *
- ******************************************************/
+ int i;
+ Car cars[15];
+
+ const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+
/**
* Five blue mercedes
*/
- for (int i = 0; i < 5; i++)
+ for (i = 0; i < 5; i++)
{
- myNdbConnection[i] = myNdb->startTransaction();
- if (myNdbConnection[i] == NULL)
- APIERROR(myNdb->getNdbError());
- myNdbOperation = myNdbConnection[i]->getNdbOperation("GARAGE");
- // Error check. If error, then maybe table GARAGE is not in database
- if (myNdbOperation == NULL)
- APIERROR(myNdbConnection[i]->getNdbError());
- myNdbOperation->insertTuple();
- myNdbOperation->equal("REG_NO", i);
- myNdbOperation->setValue("BRAND", "Mercedes");
- myNdbOperation->setValue("COLOR", "Blue");
- // Prepare transaction (the transaction is NOT yet sent to NDB)
- myNdbConnection[i]->executeAsynchPrepare(Commit, &callback, NULL);
+ cars[i].reg_no = i;
+ sprintf(cars[i].brand, "Mercedes");
+ sprintf(cars[i].color, "Blue");
}
-
/**
* Five black bmw
*/
- for (int i = 5; i < 10; i++)
+ for (i = 5; i < 10; i++)
{
- myNdbConnection[i] = myNdb->startTransaction();
- if (myNdbConnection[i] == NULL)
- APIERROR(myNdb->getNdbError());
- myNdbOperation = myNdbConnection[i]->getNdbOperation("GARAGE");
- // Error check. If error, then maybe table MYTABLENAME is not in database
- if (myNdbOperation == NULL)
- APIERROR(myNdbConnection[i]->getNdbError());
- myNdbOperation->insertTuple();
- myNdbOperation->equal("REG_NO", i);
- myNdbOperation->setValue("BRAND", "BMW");
- myNdbOperation->setValue("COLOR", "Black");
- // Prepare transaction (the transaction is NOT yet sent to NDB)
- myNdbConnection[i]->executeAsynchPrepare(Commit, &callback, NULL);
+ cars[i].reg_no = i;
+ sprintf(cars[i].brand, "BMW");
+ sprintf(cars[i].color, "Black");
}
/**
* Five pink toyotas
*/
- for (int i = 10; i < 15; i++) {
- myNdbConnection[i] = myNdb->startTransaction();
- if (myNdbConnection[i] == NULL) APIERROR(myNdb->getNdbError());
- myNdbOperation = myNdbConnection[i]->getNdbOperation("GARAGE");
- // Error check. If error, then maybe table MYTABLENAME is not in database
- if (myNdbOperation == NULL) APIERROR(myNdbConnection[i]->getNdbError());
+ for (i = 10; i < 15; i++)
+ {
+ cars[i].reg_no = i;
+ sprintf(cars[i].brand, "Toyota");
+ sprintf(cars[i].color, "Pink");
+ }
+
+ NdbTransaction* myTrans = myNdb->startTransaction();
+ if (myTrans == NULL)
+ APIERROR(myNdb->getNdbError());
+
+ for (i = 0; i < 15; i++)
+ {
+ NdbOperation* myNdbOperation = myTrans->getNdbOperation(myTable);
+ if (myNdbOperation == NULL)
+ APIERROR(myTrans->getNdbError());
myNdbOperation->insertTuple();
- myNdbOperation->equal("REG_NO", i);
- myNdbOperation->setValue("BRAND", "Toyota");
- myNdbOperation->setValue("COLOR", "Pink");
- // Prepare transaction (the transaction is NOT yet sent to NDB)
- myNdbConnection[i]->executeAsynchPrepare(Commit, &callback, NULL);
+ myNdbOperation->equal("REG_NO", cars[i].reg_no);
+ myNdbOperation->setValue("BRAND", cars[i].brand);
+ myNdbOperation->setValue("COLOR", cars[i].color);
}
- // Send all transactions to NDB
- myNdb->sendPreparedTransactions(0);
- // Poll all transactions
- myNdb->pollNdb(3000, 0);
-
- // it is also possible to use sendPollNdb instead of
- // myNdb->sendPreparedTransactions(0); and myNdb->pollNdb(3000, 15); above.
- // myNdb->sendPollNdb(3000,0);
- // Note! Neither sendPollNdb or pollNdb returs until all 15 callbacks have
- // executed.
-
- // Close all transactions. It is also possible to close transactions
- // in the callback.
- for (int i = 0; i < 15; i++)
- myNdb->closeTransaction(myNdbConnection[i]);
- return 1;
+ int check = myTrans->execute(NdbTransaction::Commit);
+
+ myTrans->close();
+
+ return check != -1;
}
int scan_delete(Ndb* myNdb,
- int parallelism,
int column,
- int column_len,
const char * color)
-
+
{
// Scan all records exclusive and delete
@@ -292,9 +217,15 @@ int scan_delete(Ndb* myNdb,
int deletedRows = 0;
int check;
NdbError err;
- NdbConnection *myTrans;
+ NdbTransaction *myTrans;
NdbScanOperation *myScanOp;
+ const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+
/**
* Loop as long as :
* retryMax not reached
@@ -331,7 +262,7 @@ int scan_delete(Ndb* myNdb,
/**
* Get a scan operation.
*/
- myScanOp = myTrans->getNdbScanOperation("GARAGE");
+ myScanOp = myTrans->getNdbScanOperation(myTable);
if (myScanOp == NULL)
{
std::cout << myTrans->getNdbError().message << std::endl;
@@ -342,20 +273,20 @@ int scan_delete(Ndb* myNdb,
/**
* Define a result set for the scan.
*/
- NdbResultSet * rs = myScanOp->readTuplesExclusive(parallelism);
- if( rs == 0 ) {
+ if(myScanOp->readTuples(NdbOperation::LM_Exclusive) != 0)
+ {
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
return -1;
}
-
+
/**
* Use NdbScanFilter to define a search critera
*/
NdbScanFilter filter(myScanOp) ;
if(filter.begin(NdbScanFilter::AND) < 0 ||
- filter.eq(column, color, column_len, false) <0||
- filter.end() <0)
+ filter.cmp(NdbScanFilter::COND_EQ, column, color) < 0 ||
+ filter.end() < 0)
{
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
@@ -365,7 +296,7 @@ int scan_delete(Ndb* myNdb,
/**
* Start scan (NoCommit since we are only reading at this stage);
*/
- if(myTrans->execute(NoCommit) != 0){
+ if(myTrans->execute(NdbTransaction::NoCommit) != 0){
err = myTrans->getNdbError();
if(err.status == NdbError::TemporaryError){
std::cout << myTrans->getNdbError().message << std::endl;
@@ -384,9 +315,11 @@ int scan_delete(Ndb* myNdb,
* start of loop: nextResult(true) means that "parallelism" number of
* rows are fetched from NDB and cached in NDBAPI
*/
- while((check = rs->nextResult(true)) == 0){
- do {
- if (rs->deleteTuple() != 0){
+ while((check = myScanOp->nextResult(true)) == 0){
+ do
+ {
+ if (myScanOp->deleteCurrentTuple() != 0)
+ {
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
return -1;
@@ -398,21 +331,32 @@ int scan_delete(Ndb* myNdb,
* cached in the NDBAPI are modified before
* fetching more rows from NDB.
*/
- } while((check = rs->nextResult(false)) == 0);
+ } while((check = myScanOp->nextResult(false)) == 0);
/**
* Commit when all cached tuple have been marked for deletion
*/
- if(check != -1){
- check = myTrans->execute(Commit);
- myTrans->releaseCompletedOperations();
+ if(check != -1)
+ {
+ check = myTrans->execute(NdbTransaction::Commit);
+ }
+
+ if(check == -1)
+ {
+ /**
+ * Create a new transaction, while keeping scan open
+ */
+ check = myTrans->restart();
}
+
/**
* Check for errors
*/
err = myTrans->getNdbError();
- if(check == -1){
- if(err.status == NdbError::TemporaryError){
+ if(check == -1)
+ {
+ if(err.status == NdbError::TemporaryError)
+ {
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
milliSleep(50);
@@ -426,10 +370,10 @@ int scan_delete(Ndb* myNdb,
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
return 0;
-
-
}
- if(myTrans!=0) {
+
+ if(myTrans!=0)
+ {
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
}
@@ -438,10 +382,7 @@ int scan_delete(Ndb* myNdb,
int scan_update(Ndb* myNdb,
- int parallelism,
- int column_len,
int update_column,
- const char * column_name,
const char * before_color,
const char * after_color)
@@ -454,9 +395,15 @@ int scan_update(Ndb* myNdb,
int updatedRows = 0;
int check;
NdbError err;
- NdbConnection *myTrans;
+ NdbTransaction *myTrans;
NdbScanOperation *myScanOp;
+ const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+
/**
* Loop as long as :
* retryMax not reached
@@ -494,7 +441,7 @@ int scan_update(Ndb* myNdb,
/**
* Get a scan operation.
*/
- myScanOp = myTrans->getNdbScanOperation("GARAGE");
+ myScanOp = myTrans->getNdbScanOperation(myTable);
if (myScanOp == NULL)
{
std::cout << myTrans->getNdbError().message << std::endl;
@@ -505,8 +452,8 @@ int scan_update(Ndb* myNdb,
/**
* Define a result set for the scan.
*/
- NdbResultSet * rs = myScanOp->readTuplesExclusive(parallelism);
- if( rs == 0 ) {
+ if( myScanOp->readTuples(NdbOperation::LM_Exclusive) )
+ {
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
return -1;
@@ -517,7 +464,7 @@ int scan_update(Ndb* myNdb,
*/
NdbScanFilter filter(myScanOp) ;
if(filter.begin(NdbScanFilter::AND) < 0 ||
- filter.eq(update_column, before_color, column_len, false) <0||
+ filter.cmp(NdbScanFilter::COND_EQ, update_column, before_color) <0||
filter.end() <0)
{
std::cout << myTrans->getNdbError().message << std::endl;
@@ -528,7 +475,8 @@ int scan_update(Ndb* myNdb,
/**
* Start scan (NoCommit since we are only reading at this stage);
*/
- if(myTrans->execute(NoCommit) != 0){
+ if(myTrans->execute(NdbTransaction::NoCommit) != 0)
+ {
err = myTrans->getNdbError();
if(err.status == NdbError::TemporaryError){
std::cout << myTrans->getNdbError().message << std::endl;
@@ -541,49 +489,49 @@ int scan_update(Ndb* myNdb,
return -1;
}
- /**
- * Define an update operation
- */
- NdbOperation * myUpdateOp;
- /**
- * start of loop: nextResult(true) means that "parallelism" number of
- * rows are fetched from NDB and cached in NDBAPI
- */
- while((check = rs->nextResult(true)) == 0){
+ /**
+ * start of loop: nextResult(true) means that "parallelism" number of
+ * rows are fetched from NDB and cached in NDBAPI
+ */
+ while((check = myScanOp->nextResult(true)) == 0){
do {
/**
* Get update operation
*/
- myUpdateOp = rs->updateTuple();
- if (myUpdateOp == 0){
+ NdbOperation * myUpdateOp = myScanOp->updateCurrentTuple();
+ if (myUpdateOp == 0)
+ {
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
return -1;
}
updatedRows++;
+
/**
* do the update
*/
- myUpdateOp->setValue(update_column,after_color);
+ myUpdateOp->setValue(update_column, after_color);
/**
* nextResult(false) means that the records
* cached in the NDBAPI are modified before
* fetching more rows from NDB.
*/
- } while((check = rs->nextResult(false)) == 0);
+ } while((check = myScanOp->nextResult(false)) == 0);
/**
- * Commit when all cached tuple have been updated
+ * NoCommit when all cached tuple have been updated
*/
- if(check != -1){
- check = myTrans->execute(Commit);
- myTrans->releaseCompletedOperations();
+ if(check != -1)
+ {
+ check = myTrans->execute(NdbTransaction::NoCommit);
}
+
/**
* Check for errors
*/
err = myTrans->getNdbError();
- if(check == -1){
+ if(check == -1)
+ {
if(err.status == NdbError::TemporaryError){
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
@@ -595,13 +543,28 @@ int scan_update(Ndb* myNdb,
* End of loop
*/
}
+
+ /**
+ * Commit all prepared operations
+ */
+ if(myTrans->execute(NdbTransaction::Commit) == -1)
+ {
+ if(err.status == NdbError::TemporaryError){
+ std::cout << myTrans->getNdbError().message << std::endl;
+ myNdb->closeTransaction(myTrans);
+ milliSleep(50);
+ continue;
+ }
+ }
+
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
- return 0;
-
-
+ return 0;
}
- if(myTrans!=0) {
+
+
+ if(myTrans!=0)
+ {
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
}
@@ -610,9 +573,7 @@ int scan_update(Ndb* myNdb,
-int scan_print(Ndb * myNdb, int parallelism,
- int column_len_brand,
- int column_len_color)
+int scan_print(Ndb * myNdb)
{
// Scan all records exclusive and update
// them one by one
@@ -621,13 +582,19 @@ int scan_print(Ndb * myNdb, int parallelism,
int fetchedRows = 0;
int check;
NdbError err;
- NdbConnection *myTrans;
+ NdbTransaction *myTrans;
NdbScanOperation *myScanOp;
/* Result of reading attribute value, three columns:
REG_NO, BRAND, and COLOR
*/
NdbRecAttr * myRecAttr[3];
+ const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("GARAGE");
+
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+
/**
* Loop as long as :
* retryMax not reached
@@ -665,7 +632,7 @@ int scan_print(Ndb * myNdb, int parallelism,
* Define a scan operation.
* NDBAPI.
*/
- myScanOp = myTrans->getNdbScanOperation("GARAGE");
+ myScanOp = myTrans->getNdbScanOperation(myTable);
if (myScanOp == NULL)
{
std::cout << myTrans->getNdbError().message << std::endl;
@@ -674,10 +641,10 @@ int scan_print(Ndb * myNdb, int parallelism,
}
/**
- * Define a result set for the scan.
- */
- NdbResultSet * rs = myScanOp->readTuplesExclusive(parallelism);
- if( rs == 0 ) {
+ * Read without locks, without being placed in lock queue
+ */
+ if( myScanOp->readTuples(NdbOperation::LM_CommittedRead) == -1)
+ {
std::cout << myTrans->getNdbError().message << std::endl;
myNdb->closeTransaction(myTrans);
return -1;
@@ -701,7 +668,7 @@ int scan_print(Ndb * myNdb, int parallelism,
/**
* Start scan (NoCommit since we are only reading at this stage);
*/
- if(myTrans->execute(NoCommit) != 0){
+ if(myTrans->execute(NdbTransaction::NoCommit) != 0){
err = myTrans->getNdbError();
if(err.status == NdbError::TemporaryError){
std::cout << myTrans->getNdbError().message << std::endl;
@@ -719,7 +686,7 @@ int scan_print(Ndb * myNdb, int parallelism,
* start of loop: nextResult(true) means that "parallelism" number of
* rows are fetched from NDB and cached in NDBAPI
*/
- while((check = rs->nextResult(true)) == 0){
+ while((check = myScanOp->nextResult(true)) == 0){
do {
fetchedRows++;
@@ -727,28 +694,23 @@ int scan_print(Ndb * myNdb, int parallelism,
* print REG_NO unsigned int
*/
std::cout << myRecAttr[0]->u_32_value() << "\t";
- char * buf_brand = new char[column_len_brand+1];
- char * buf_color = new char[column_len_color+1];
+
/**
* print BRAND character string
*/
- memcpy(buf_brand, myRecAttr[1]->aRef(), column_len_brand);
- buf_brand[column_len_brand] = 0;
- std::cout << buf_brand << "\t";
- delete [] buf_brand;
+ std::cout << myRecAttr[1]->aRef() << "\t";
+
/**
* print COLOR character string
*/
- memcpy(buf_color, myRecAttr[2]->aRef(), column_len_color);
- buf_brand[column_len_color] = 0;
- std::cout << buf_color << std::endl;
- delete [] buf_color;
+ std::cout << myRecAttr[2]->aRef() << std::endl;
+
/**
* nextResult(false) means that the records
* cached in the NDBAPI are modified before
* fetching more rows from NDB.
*/
- } while((check = rs->nextResult(false)) == 0);
+ } while((check = myScanOp->nextResult(false)) == 0);
}
myNdb->closeTransaction(myTrans);
@@ -762,55 +724,102 @@ int scan_print(Ndb * myNdb, int parallelism,
int main()
{
ndb_init();
- Ndb* myNdb = new Ndb( "TEST_DB" ); // Object representing the database
+ MYSQL mysql;
-
-
- /*******************************************
- * Initialize NDB and wait until its ready *
- *******************************************/
- if (myNdb->init(1024) == -1) { // Set max 1024 parallel transactions
- APIERROR(myNdb->getNdbError());
+ /**************************************************************
+ * Connect to mysql server and create table *
+ **************************************************************/
+ {
+ if ( !mysql_init(&mysql) ) {
+ std::cout << "mysql_init failed\n";
+ exit(-1);
+ }
+ if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
+ 3306, "/tmp/mysql.sock", 0) )
+ MYSQLERROR(mysql);
+
+ mysql_query(&mysql, "CREATE DATABASE TEST_DB");
+ if (mysql_query(&mysql, "USE TEST_DB") != 0) MYSQLERROR(mysql);
+
+ create_table(mysql);
+ }
+
+ /**************************************************************
+ * Connect to ndb cluster *
+ **************************************************************/
+
+ Ndb_cluster_connection cluster_connection;
+ if (cluster_connection.connect(4, 5, 1))
+ {
+ std::cout << "Unable to connect to cluster within 30 secs." << std::endl;
+ exit(-1);
+ }
+ // Optionally connect and wait for the storage nodes (ndbd's)
+ if (cluster_connection.wait_until_ready(30,0) < 0)
+ {
+ std::cout << "Cluster was not ready within 30 secs.\n";
exit(-1);
}
- if (myNdb->waitUntilReady(30) != 0) {
- std::cout << "NDB was not ready within 30 secs." << std::endl;
+ Ndb myNdb(&cluster_connection,"TEST_DB");
+ if (myNdb.init(1024) == -1) { // Set max 1024 parallel transactions
+ APIERROR(myNdb.getNdbError());
exit(-1);
}
- create_table(myNdb);
-
- NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
- int column_color = myDict->getTable("GARAGE")->getColumn("COLOR")->getColumnNo();
- int column_len_color =
- myDict->getTable("GARAGE")->getColumn("COLOR")->getLength();
- int column_len_brand =
- myDict->getTable("GARAGE")->getColumn("BRAND")->getLength();
- int parallelism = 16;
-
- if(populate(myNdb) > 0)
- std::cout << "populate: Success!" << std::endl;
+ /*******************************************
+ * Check table definition *
+ *******************************************/
+ int column_color;
+ {
+ const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
+ const NdbDictionary::Table *t= myDict->getTable("GARAGE");
+
+ Car car;
+ if (t->getColumn("COLOR")->getLength() != sizeof(car.color) ||
+ t->getColumn("BRAND")->getLength() != sizeof(car.brand))
+ {
+ std::cout << "Wrong table definition" << std::endl;
+ exit(-1);
+ }
+ column_color= t->getColumn("COLOR")->getColumnNo();
+ }
- if(scan_print(myNdb, parallelism, column_len_brand, column_len_color) > 0)
+ if(populate(&myNdb) > 0)
+ std::cout << "populate: Success!" << std::endl;
+
+ if(scan_print(&myNdb) > 0)
std::cout << "scan_print: Success!" << std::endl << std::endl;
std::cout << "Going to delete all pink cars!" << std::endl;
- if(scan_delete(myNdb, parallelism, column_color,
- column_len_color, "Pink") > 0)
- std::cout << "scan_delete: Success!" << std::endl << std::endl;
+
+ {
+ /**
+ * Note! color needs to be of exact the same size as column defined
+ */
+ Car tmp;
+ sprintf(tmp.color, "Pink");
+ if(scan_delete(&myNdb, column_color, tmp.color) > 0)
+ std::cout << "scan_delete: Success!" << std::endl << std::endl;
+ }
- if(scan_print(myNdb, parallelism, column_len_brand, column_len_color) > 0)
+ if(scan_print(&myNdb) > 0)
std::cout << "scan_print: Success!" << std::endl << std::endl;
- std::cout << "Going to update all blue cars to black cars!" << std::endl;
- if(scan_update(myNdb, parallelism, column_len_color, column_color,
- "COLOR", "Blue", "Black") > 0)
{
- std::cout << "scan_update: Success!" << std::endl << std::endl;
+ /**
+ * Note! color1 & 2 need to be of exact the same size as column defined
+ */
+ Car tmp1, tmp2;
+ sprintf(tmp1.color, "Blue");
+ sprintf(tmp2.color, "Black");
+ std::cout << "Going to update all " << tmp1.color
+ << " cars to " << tmp2.color << " cars!" << std::endl;
+ if(scan_update(&myNdb, column_color, tmp1.color, tmp2.color) > 0)
+ std::cout << "scan_update: Success!" << std::endl << std::endl;
}
- if(scan_print(myNdb, parallelism, column_len_brand, column_len_color) > 0)
+ if(scan_print(&myNdb) > 0)
std::cout << "scan_print: Success!" << std::endl << std::endl;
- delete myNdb;
+ return 0;
}
diff --git a/ndb/examples/ndbapi_scan_example/readme.txt b/ndb/ndbapi-examples/ndbapi_scan_example/readme.txt
index 47cb4bf9ffa..47cb4bf9ffa 100644
--- a/ndb/examples/ndbapi_scan_example/readme.txt
+++ b/ndb/ndbapi-examples/ndbapi_scan_example/readme.txt
diff --git a/ndb/ndbapi-examples/ndbapi_simple_example/Makefile b/ndb/ndbapi-examples/ndbapi_simple_example/Makefile
new file mode 100644
index 00000000000..0a59584fb66
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_simple_example/Makefile
@@ -0,0 +1,23 @@
+TARGET = ndbapi_simple
+SRCS = $(TARGET).cpp
+OBJS = $(TARGET).o
+CXX = g++
+CFLAGS = -c -Wall -fno-rtti -fno-exceptions
+CXXFLAGS =
+DEBUG =
+LFLAGS = -Wall
+TOP_SRCDIR = ../../..
+INCLUDE_DIR = $(TOP_SRCDIR)
+LIB_DIR = -L$(TOP_SRCDIR)/ndb/src/.libs \
+ -L$(TOP_SRCDIR)/libmysql_r/.libs \
+ -L$(TOP_SRCDIR)/mysys -L$(TOP_SRCDIR)/strings
+SYS_LIB =
+
+$(TARGET): $(OBJS)
+ $(CXX) $(CXXFLAGS) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET)
+
+$(TARGET).o: $(SRCS)
+ $(CXX) $(CFLAGS) -I$(INCLUDE_DIR)/include -I$(INCLUDE_DIR)/ndb/include -I$(INCLUDE_DIR)/ndb/include/ndbapi $(SRCS)
+
+clean:
+ rm -f *.o $(TARGET)
diff --git a/ndb/ndbapi-examples/ndbapi_simple_example/ndbapi_simple.cpp b/ndb/ndbapi-examples/ndbapi_simple_example/ndbapi_simple.cpp
new file mode 100644
index 00000000000..152d4fa44af
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_simple_example/ndbapi_simple.cpp
@@ -0,0 +1,278 @@
+/* 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 */
+
+/*
+ * ndbapi_simple.cpp: Using synchronous transactions in NDB API
+ *
+ * Correct output from this program is:
+ *
+ * ATTR1 ATTR2
+ * 0 10
+ * 1 1
+ * 2 12
+ * Detected that deleted tuple doesn't exist!
+ * 4 14
+ * 5 5
+ * 6 16
+ * 7 7
+ * 8 18
+ * 9 9
+ *
+ */
+
+#include <mysql.h>
+#include <NdbApi.hpp>
+// Used for cout
+#include <stdio.h>
+#include <iostream>
+
+static void run_application(MYSQL &, Ndb_cluster_connection &);
+
+#define PRINT_ERROR(code,msg) \
+ std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
+ << ", code: " << code \
+ << ", msg: " << msg << "." << std::endl
+#define MYSQLERROR(mysql) { \
+ PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
+ exit(-1); }
+#define APIERROR(error) { \
+ PRINT_ERROR(error.code,error.message); \
+ exit(-1); }
+
+int main()
+{
+ // ndb_init must be called first
+ ndb_init();
+
+ // connect to mysql server and cluster and run application
+ {
+ // Object representing the cluster
+ Ndb_cluster_connection cluster_connection;
+
+ // Connect to cluster management server (ndb_mgmd)
+ if (cluster_connection.connect(4 /* retries */,
+ 5 /* delay between retries */,
+ 1 /* verbose */))
+ {
+ std::cout << "Cluster management server was not ready within 30 secs.\n";
+ exit(-1);
+ }
+
+ // Optionally connect and wait for the storage nodes (ndbd's)
+ if (cluster_connection.wait_until_ready(30,0) < 0)
+ {
+ std::cout << "Cluster was not ready within 30 secs.\n";
+ exit(-1);
+ }
+
+ // connect to mysql server
+ MYSQL mysql;
+ if ( !mysql_init(&mysql) ) {
+ std::cout << "mysql_init failed\n";
+ exit(-1);
+ }
+ if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
+ 3306, "/tmp/mysql.sock", 0) )
+ MYSQLERROR(mysql);
+
+ // run the application code
+ run_application(mysql, cluster_connection);
+ }
+
+ ndb_end(0);
+
+ std::cout << "\nTo drop created table use:\n"
+ << "echo \"drop table MYTABLENAME\" | mysql TEST_DB_1 -u root\n";
+
+ return 0;
+}
+
+static void create_table(MYSQL &);
+static void do_insert(Ndb &);
+static void do_update(Ndb &);
+static void do_delete(Ndb &);
+static void do_read(Ndb &);
+
+static void run_application(MYSQL &mysql,
+ Ndb_cluster_connection &cluster_connection)
+{
+ /********************************************
+ * Connect to database via mysql-c *
+ ********************************************/
+ mysql_query(&mysql, "CREATE DATABASE TEST_DB_1");
+ if (mysql_query(&mysql, "USE TEST_DB_1") != 0) MYSQLERROR(mysql);
+ create_table(mysql);
+
+ /********************************************
+ * Connect to database via NdbApi *
+ ********************************************/
+ // Object representing the database
+ Ndb myNdb( &cluster_connection, "TEST_DB_1" );
+ if (myNdb.init()) APIERROR(myNdb.getNdbError());
+
+ /*
+ * Do different operations on database
+ */
+ do_insert(myNdb);
+ do_update(myNdb);
+ do_delete(myNdb);
+ do_read(myNdb);
+}
+
+/*********************************************************
+ * Create a table named MYTABLENAME if it does not exist *
+ *********************************************************/
+static void create_table(MYSQL &mysql)
+{
+ if (mysql_query(&mysql,
+ "CREATE TABLE"
+ " MYTABLENAME"
+ " (ATTR1 INT UNSIGNED NOT NULL PRIMARY KEY,"
+ " ATTR2 INT UNSIGNED NOT NULL)"
+ " ENGINE=NDB"))
+ MYSQLERROR(mysql);
+}
+
+/**************************************************************************
+ * Using 5 transactions, insert 10 tuples in table: (0,0),(1,1),...,(9,9) *
+ **************************************************************************/
+static void do_insert(Ndb &myNdb)
+{
+ const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
+
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+
+ for (int i = 0; i < 5; i++) {
+ NdbTransaction *myTransaction= myNdb.startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
+
+ NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myOperation->insertTuple();
+ myOperation->equal("ATTR1", i);
+ myOperation->setValue("ATTR2", i);
+
+ myOperation= myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myOperation->insertTuple();
+ myOperation->equal("ATTR1", i+5);
+ myOperation->setValue("ATTR2", i+5);
+
+ if (myTransaction->execute( NdbTransaction::Commit ) == -1)
+ APIERROR(myTransaction->getNdbError());
+
+ myNdb.closeTransaction(myTransaction);
+ }
+}
+
+/*****************************************************************
+ * Update the second attribute in half of the tuples (adding 10) *
+ *****************************************************************/
+static void do_update(Ndb &myNdb)
+{
+ const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
+
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+
+ for (int i = 0; i < 10; i+=2) {
+ NdbTransaction *myTransaction= myNdb.startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
+
+ NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myOperation->updateTuple();
+ myOperation->equal( "ATTR1", i );
+ myOperation->setValue( "ATTR2", i+10);
+
+ if( myTransaction->execute( NdbTransaction::Commit ) == -1 )
+ APIERROR(myTransaction->getNdbError());
+
+ myNdb.closeTransaction(myTransaction);
+ }
+}
+
+/*************************************************
+ * Delete one tuple (the one with primary key 3) *
+ *************************************************/
+static void do_delete(Ndb &myNdb)
+{
+ const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
+
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+
+ NdbTransaction *myTransaction= myNdb.startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
+
+ NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myOperation->deleteTuple();
+ myOperation->equal( "ATTR1", 3 );
+
+ if (myTransaction->execute(NdbTransaction::Commit) == -1)
+ APIERROR(myTransaction->getNdbError());
+
+ myNdb.closeTransaction(myTransaction);
+}
+
+/*****************************
+ * Read and print all tuples *
+ *****************************/
+static void do_read(Ndb &myNdb)
+{
+ const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
+
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+
+ std::cout << "ATTR1 ATTR2" << std::endl;
+
+ for (int i = 0; i < 10; i++) {
+ NdbTransaction *myTransaction= myNdb.startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
+
+ NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myOperation->readTuple(NdbOperation::LM_Read);
+ myOperation->equal("ATTR1", i);
+
+ NdbRecAttr *myRecAttr= myOperation->getValue("ATTR2", NULL);
+ if (myRecAttr == NULL) APIERROR(myTransaction->getNdbError());
+
+ if(myTransaction->execute( NdbTransaction::Commit ) == -1)
+ if (i == 3) {
+ std::cout << "Detected that deleted tuple doesn't exist!" << std::endl;
+ } else {
+ APIERROR(myTransaction->getNdbError());
+ }
+
+ if (i != 3) {
+ printf(" %2d %2d\n", i, myRecAttr->u_32_value());
+ }
+ myNdb.closeTransaction(myTransaction);
+ }
+}
diff --git a/ndb/ndbapi-examples/ndbapi_simple_index_example/Makefile b/ndb/ndbapi-examples/ndbapi_simple_index_example/Makefile
new file mode 100644
index 00000000000..d4356055935
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_simple_index_example/Makefile
@@ -0,0 +1,23 @@
+TARGET = ndbapi_simple_index
+SRCS = $(TARGET).cpp
+OBJS = $(TARGET).o
+CXX = g++
+CFLAGS = -c -Wall -fno-rtti -fno-exceptions
+CXXFLAGS =
+DEBUG =
+LFLAGS = -Wall
+TOP_SRCDIR = ../../..
+INCLUDE_DIR = $(TOP_SRCDIR)
+LIB_DIR = -L$(TOP_SRCDIR)/ndb/src/.libs \
+ -L$(TOP_SRCDIR)/libmysql_r/.libs \
+ -L$(TOP_SRCDIR)/mysys -L$(TOP_SRCDIR)/strings
+SYS_LIB =
+
+$(TARGET): $(OBJS)
+ $(CXX) $(CXXFLAGS) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET)
+
+$(TARGET).o: $(SRCS)
+ $(CXX) $(CFLAGS) -I$(INCLUDE_DIR)/include -I$(INCLUDE_DIR)/ndb/include -I$(INCLUDE_DIR)/ndb/include/ndbapi $(SRCS)
+
+clean:
+ rm -f *.o $(TARGET)
diff --git a/ndb/ndbapi-examples/ndbapi_simple_index_example/ndbapi_simple_index.cpp b/ndb/ndbapi-examples/ndbapi_simple_index_example/ndbapi_simple_index.cpp
new file mode 100644
index 00000000000..5afaf6078d1
--- /dev/null
+++ b/ndb/ndbapi-examples/ndbapi_simple_index_example/ndbapi_simple_index.cpp
@@ -0,0 +1,254 @@
+/* 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 */
+
+//
+// ndbapi_simple_index.cpp: Using secondary indexes in NDB API
+//
+// Correct output from this program is:
+//
+// ATTR1 ATTR2
+// 0 10
+// 1 1
+// 2 12
+// Detected that deleted tuple doesn't exist!
+// 4 14
+// 5 5
+// 6 16
+// 7 7
+// 8 18
+// 9 9
+
+#include <mysql.h>
+#include <NdbApi.hpp>
+
+// Used for cout
+#include <stdio.h>
+#include <iostream>
+
+#define PRINT_ERROR(code,msg) \
+ std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
+ << ", code: " << code \
+ << ", msg: " << msg << "." << std::endl
+#define MYSQLERROR(mysql) { \
+ PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
+ exit(-1); }
+#define APIERROR(error) { \
+ PRINT_ERROR(error.code,error.message); \
+ exit(-1); }
+
+int main()
+{
+ ndb_init();
+ MYSQL mysql;
+
+ /**************************************************************
+ * Connect to mysql server and create table *
+ **************************************************************/
+ {
+ if ( !mysql_init(&mysql) ) {
+ std::cout << "mysql_init failed\n";
+ exit(-1);
+ }
+ if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
+ 3306, "/tmp/mysql.sock", 0) )
+ MYSQLERROR(mysql);
+
+ mysql_query(&mysql, "CREATE DATABASE TEST_DB_1");
+ if (mysql_query(&mysql, "USE TEST_DB_1") != 0) MYSQLERROR(mysql);
+
+ if (mysql_query(&mysql,
+ "CREATE TABLE"
+ " MYTABLENAME"
+ " (ATTR1 INT UNSIGNED,"
+ " ATTR2 INT UNSIGNED NOT NULL,"
+ " PRIMARY KEY USING HASH (ATTR1),"
+ " UNIQUE MYINDEXNAME USING HASH (ATTR2))"
+ " ENGINE=NDB"))
+ MYSQLERROR(mysql);
+ }
+
+ /**************************************************************
+ * Connect to ndb cluster *
+ **************************************************************/
+
+ Ndb_cluster_connection *cluster_connection=
+ new Ndb_cluster_connection(); // Object representing the cluster
+
+ if (cluster_connection->connect(5,3,1))
+ {
+ std::cout << "Connect to cluster management server failed.\n";
+ exit(-1);
+ }
+
+ if (cluster_connection->wait_until_ready(30,30))
+ {
+ std::cout << "Cluster was not ready within 30 secs.\n";
+ exit(-1);
+ }
+
+ Ndb* myNdb = new Ndb( cluster_connection,
+ "TEST_DB_1" ); // Object representing the database
+ if (myNdb->init() == -1) {
+ APIERROR(myNdb->getNdbError());
+ exit(-1);
+ }
+
+ const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+ const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
+ if (myTable == NULL)
+ APIERROR(myDict->getNdbError());
+ const NdbDictionary::Index *myIndex= myDict->getIndex("MYINDEXNAME","MYTABLENAME");
+ if (myIndex == NULL)
+ APIERROR(myDict->getNdbError());
+
+ /**************************************************************************
+ * Using 5 transactions, insert 10 tuples in table: (0,0),(1,1),...,(9,9) *
+ **************************************************************************/
+ for (int i = 0; i < 5; i++) {
+ NdbTransaction *myTransaction= myNdb->startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb->getNdbError());
+
+ NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myOperation->insertTuple();
+ myOperation->equal("ATTR1", i);
+ myOperation->setValue("ATTR2", i);
+
+ myOperation = myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myOperation->insertTuple();
+ myOperation->equal("ATTR1", i+5);
+ myOperation->setValue("ATTR2", i+5);
+
+ if (myTransaction->execute( NdbTransaction::Commit ) == -1)
+ APIERROR(myTransaction->getNdbError());
+
+ myNdb->closeTransaction(myTransaction);
+ }
+
+ /*****************************************
+ * Read and print all tuples using index *
+ *****************************************/
+ std::cout << "ATTR1 ATTR2" << std::endl;
+
+ for (int i = 0; i < 10; i++) {
+ NdbTransaction *myTransaction= myNdb->startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb->getNdbError());
+
+ NdbIndexOperation *myIndexOperation=
+ myTransaction->getNdbIndexOperation(myIndex);
+ if (myIndexOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myIndexOperation->readTuple(NdbOperation::LM_Read);
+ myIndexOperation->equal("ATTR2", i);
+
+ NdbRecAttr *myRecAttr= myIndexOperation->getValue("ATTR1", NULL);
+ if (myRecAttr == NULL) APIERROR(myTransaction->getNdbError());
+
+ if(myTransaction->execute( NdbTransaction::Commit ) != -1)
+ printf(" %2d %2d\n", myRecAttr->u_32_value(), i);
+
+ myNdb->closeTransaction(myTransaction);
+ }
+
+ /*****************************************************************
+ * Update the second attribute in half of the tuples (adding 10) *
+ *****************************************************************/
+ for (int i = 0; i < 10; i+=2) {
+ NdbTransaction *myTransaction= myNdb->startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb->getNdbError());
+
+ NdbIndexOperation *myIndexOperation=
+ myTransaction->getNdbIndexOperation(myIndex);
+ if (myIndexOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myIndexOperation->updateTuple();
+ myIndexOperation->equal( "ATTR2", i );
+ myIndexOperation->setValue( "ATTR2", i+10);
+
+ if( myTransaction->execute( NdbTransaction::Commit ) == -1 )
+ APIERROR(myTransaction->getNdbError());
+
+ myNdb->closeTransaction(myTransaction);
+ }
+
+ /*************************************************
+ * Delete one tuple (the one with primary key 3) *
+ *************************************************/
+ {
+ NdbTransaction *myTransaction= myNdb->startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb->getNdbError());
+
+ NdbIndexOperation *myIndexOperation=
+ myTransaction->getNdbIndexOperation(myIndex);
+ if (myIndexOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myIndexOperation->deleteTuple();
+ myIndexOperation->equal( "ATTR2", 3 );
+
+ if (myTransaction->execute(NdbTransaction::Commit) == -1)
+ APIERROR(myTransaction->getNdbError());
+
+ myNdb->closeTransaction(myTransaction);
+ }
+
+ /*****************************
+ * Read and print all tuples *
+ *****************************/
+ {
+ std::cout << "ATTR1 ATTR2" << std::endl;
+
+ for (int i = 0; i < 10; i++) {
+ NdbTransaction *myTransaction= myNdb->startTransaction();
+ if (myTransaction == NULL) APIERROR(myNdb->getNdbError());
+
+ NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
+ if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
+
+ myOperation->readTuple(NdbOperation::LM_Read);
+ myOperation->equal("ATTR1", i);
+
+ NdbRecAttr *myRecAttr= myOperation->getValue("ATTR2", NULL);
+ if (myRecAttr == NULL) APIERROR(myTransaction->getNdbError());
+
+ if(myTransaction->execute( NdbTransaction::Commit ) == -1)
+ if (i == 3) {
+ std::cout << "Detected that deleted tuple doesn't exist!\n";
+ } else {
+ APIERROR(myTransaction->getNdbError());
+ }
+
+ if (i != 3) {
+ printf(" %2d %2d\n", i, myRecAttr->u_32_value());
+ }
+ myNdb->closeTransaction(myTransaction);
+ }
+ }
+
+ /**************
+ * Drop table *
+ **************/
+ if (mysql_query(&mysql, "DROP TABLE MYTABLENAME"))
+ MYSQLERROR(mysql);
+
+ delete myNdb;
+ delete cluster_connection;
+
+ ndb_end(0);
+ return 0;
+}
diff --git a/ndb/src/Makefile.am b/ndb/src/Makefile.am
index eb1cf1c6543..d35790a2e43 100644
--- a/ndb/src/Makefile.am
+++ b/ndb/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = common mgmapi ndbapi . kernel mgmsrv mgmclient cw
+SUBDIRS = common mgmapi ndbapi . kernel mgmclient mgmsrv cw
include $(top_srcdir)/ndb/config/common.mk.am
diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp
index f7cef644c64..d18b0feb1ad 100644
--- a/ndb/src/common/debugger/EventLogger.cpp
+++ b/ndb/src/common/debugger/EventLogger.cpp
@@ -33,1283 +33,699 @@ EventLoggerBase::~EventLoggerBase()
}
-/**
- * This matrix defines which event should be printed when
- *
- * threshold - is in range [0-15]
- * severity - DEBUG to ALERT (Type of log message)
- */
-const EventLoggerBase::EventRepLogLevelMatrix EventLoggerBase::matrix[] = {
- // CONNECTION
- { EventReport::Connected, LogLevel::llConnection, 8, Logger::LL_INFO },
- { EventReport::Disconnected, LogLevel::llConnection, 8, Logger::LL_ALERT },
- { EventReport::CommunicationClosed, LogLevel::llConnection, 8, Logger::LL_INFO },
- { EventReport::CommunicationOpened, LogLevel::llConnection, 8, Logger::LL_INFO },
- { EventReport::ConnectedApiVersion, LogLevel::llConnection, 8, Logger::LL_INFO },
- // CHECKPOINT
- { EventReport::GlobalCheckpointStarted, LogLevel::llCheckpoint, 9, Logger::LL_INFO },
- { EventReport::GlobalCheckpointCompleted,LogLevel::llCheckpoint,10, Logger::LL_INFO },
- { EventReport::LocalCheckpointStarted, LogLevel::llCheckpoint, 7, Logger::LL_INFO },
- { EventReport::LocalCheckpointCompleted,LogLevel::llCheckpoint, 8, Logger::LL_INFO },
- { EventReport::LCPStoppedInCalcKeepGci, LogLevel::llCheckpoint, 0, Logger::LL_ALERT },
- { EventReport::LCPFragmentCompleted, LogLevel::llCheckpoint, 11, Logger::LL_INFO },
- { EventReport::UndoLogBlocked, LogLevel::llCheckpoint, 7, Logger::LL_INFO },
+#define QQQQ char *m_text, size_t m_text_len, const Uint32* theData
- // STARTUP
- { EventReport::NDBStartStarted, LogLevel::llStartUp, 1, Logger::LL_INFO },
- { EventReport::NDBStartCompleted, LogLevel::llStartUp, 1, Logger::LL_INFO },
- { EventReport::STTORRYRecieved, LogLevel::llStartUp,15, Logger::LL_INFO },
- { EventReport::StartPhaseCompleted, LogLevel::llStartUp, 4, Logger::LL_INFO },
- { EventReport::CM_REGCONF, LogLevel::llStartUp, 3, Logger::LL_INFO },
- { EventReport::CM_REGREF, LogLevel::llStartUp, 8, Logger::LL_INFO },
- { EventReport::FIND_NEIGHBOURS, LogLevel::llStartUp, 8, Logger::LL_INFO },
- { EventReport::NDBStopStarted, LogLevel::llStartUp, 1, Logger::LL_INFO },
- { EventReport::NDBStopAborted, LogLevel::llStartUp, 1, Logger::LL_INFO },
- { EventReport::StartREDOLog, LogLevel::llStartUp, 10, Logger::LL_INFO },
- { EventReport::StartLog, LogLevel::llStartUp, 10, Logger::LL_INFO },
- { EventReport::UNDORecordsExecuted, LogLevel::llStartUp, 15, Logger::LL_INFO },
-
- // NODERESTART
- { EventReport::NR_CopyDict, LogLevel::llNodeRestart, 8, Logger::LL_INFO },
- { EventReport::NR_CopyDistr, LogLevel::llNodeRestart, 8, Logger::LL_INFO },
- { EventReport::NR_CopyFragsStarted, LogLevel::llNodeRestart, 8, Logger::LL_INFO },
- { EventReport::NR_CopyFragDone, LogLevel::llNodeRestart, 10, Logger::LL_INFO },
- { EventReport::NR_CopyFragsCompleted, LogLevel::llNodeRestart, 8, Logger::LL_INFO },
-
- { EventReport::NodeFailCompleted, LogLevel::llNodeRestart, 8, Logger::LL_ALERT},
- { EventReport::NODE_FAILREP, LogLevel::llNodeRestart, 8, Logger::LL_ALERT},
- { EventReport::ArbitState, LogLevel::llNodeRestart, 6, Logger::LL_INFO },
- { EventReport::ArbitResult, LogLevel::llNodeRestart, 2, Logger::LL_ALERT},
- { EventReport::GCP_TakeoverStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO },
- { EventReport::GCP_TakeoverCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO },
- { EventReport::LCP_TakeoverStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO },
- { EventReport::LCP_TakeoverCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO },
-
- // STATISTIC
- { EventReport::TransReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO },
- { EventReport::OperationReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO },
- { EventReport::TableCreated, LogLevel::llStatistic, 7, Logger::LL_INFO },
- { EventReport::JobStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO },
- { EventReport::SendBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO },
- { EventReport::ReceiveBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO },
- { EventReport::MemoryUsage, LogLevel::llStatistic, 5, Logger::LL_INFO },
-
- // ERROR
- { EventReport::TransporterError, LogLevel::llError, 2, Logger::LL_ERROR },
- { EventReport::TransporterWarning, LogLevel::llError, 8, Logger::LL_WARNING },
- { EventReport::MissedHeartbeat, LogLevel::llError, 8, Logger::LL_WARNING },
- { EventReport::DeadDueToHeartbeat, LogLevel::llError, 8, Logger::LL_ALERT },
- { EventReport::WarningEvent, LogLevel::llError, 2, Logger::LL_WARNING },
- // INFO
- { EventReport::SentHeartbeat, LogLevel::llInfo, 12, Logger::LL_INFO },
- { EventReport::CreateLogBytes, LogLevel::llInfo, 11, Logger::LL_INFO },
- { EventReport::InfoEvent, LogLevel::llInfo, 2, Logger::LL_INFO },
-
- //Global replication
- { EventReport::GrepSubscriptionInfo, LogLevel::llGrep, 7, Logger::LL_INFO},
- { EventReport::GrepSubscriptionAlert, LogLevel::llGrep, 7, Logger::LL_ALERT},
-
- // Backup
- { EventReport::BackupStarted, LogLevel::llBackup, 7, Logger::LL_INFO },
- { EventReport::BackupCompleted, LogLevel::llBackup, 7, Logger::LL_INFO },
- { EventReport::BackupFailedToStart, LogLevel::llBackup, 7, Logger::LL_ALERT},
- { EventReport::BackupAborted, LogLevel::llBackup, 7, Logger::LL_ALERT }
-};
-
-const Uint32 EventLoggerBase::matrixSize = sizeof(EventLoggerBase::matrix)/
- sizeof(EventRepLogLevelMatrix);
-
-const char*
-EventLogger::getText(char * m_text, size_t m_text_len,
- int type,
- const Uint32* theData, NodeId nodeId)
-{
- // TODO: Change the switch implementation...
- char theNodeId[32];
- if (nodeId != 0){
- BaseString::snprintf(theNodeId, 32, "Node %u: ", nodeId);
- } else {
- theNodeId[0] = 0;
- }
-
- EventReport::EventType eventType = (EventReport::EventType)type;
- switch (eventType){
- case EventReport::Connected:
- BaseString::snprintf(m_text, m_text_len,
- "%sNode %u Connected",
- theNodeId,
- theData[1]);
- break;
- case EventReport::ConnectedApiVersion:
- BaseString::snprintf(m_text, m_text_len,
- "%sNode %u: API version %d.%d.%d",
- theNodeId,
- theData[1],
- getMajor(theData[2]),
- getMinor(theData[2]),
- getBuild(theData[2]));
- break;
- case EventReport::Disconnected:
- BaseString::snprintf(m_text, m_text_len,
- "%sNode %u Disconnected",
- theNodeId,
- theData[1]);
- break;
- case EventReport::CommunicationClosed:
- //-----------------------------------------------------------------------
- // REPORT communication to node closed.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sCommunication to Node %u closed",
- theNodeId,
- theData[1]);
- break;
- case EventReport::CommunicationOpened:
- //-----------------------------------------------------------------------
- // REPORT communication to node opened.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sCommunication to Node %u opened",
- theNodeId,
- theData[1]);
- break;
- case EventReport::NDBStartStarted:
- //-----------------------------------------------------------------------
- // Start of NDB has been initiated.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sStart initiated (version %d.%d.%d)",
- theNodeId ,
- getMajor(theData[1]),
- getMinor(theData[1]),
- getBuild(theData[1]));
- break;
- case EventReport::NDBStopStarted:
- BaseString::snprintf(m_text, m_text_len,
- "%s%s shutdown initiated",
- theNodeId,
- (theData[1] == 1 ? "Cluster" : "Node"));
- break;
- case EventReport::NDBStopAborted:
- BaseString::snprintf(m_text, m_text_len,
- "%sNode shutdown aborted",
- theNodeId);
- break;
- case EventReport::NDBStartCompleted:
- //-----------------------------------------------------------------------
- // Start of NDB has been completed.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sStarted (version %d.%d.%d)",
- theNodeId ,
- getMajor(theData[1]),
- getMinor(theData[1]),
- getBuild(theData[1]));
-
- break;
- case EventReport::STTORRYRecieved:
- //-----------------------------------------------------------------------
- // STTORRY recevied after restart finished.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sSTTORRY received after restart finished",
- theNodeId);
- break;
- case EventReport::StartPhaseCompleted:{
- //-----------------------------------------------------------------------
- // REPORT Start phase completed.
- //-----------------------------------------------------------------------
- const char * type = "<Unknown>";
- switch((NodeState::StartType)theData[2]){
- case NodeState::ST_INITIAL_START:
- type = "(initial start)";
- break;
- case NodeState::ST_SYSTEM_RESTART:
- type = "(system restart)";
- break;
- case NodeState::ST_NODE_RESTART:
- type = "(node restart)";
- break;
- case NodeState::ST_INITIAL_NODE_RESTART:
- type = "(initial node restart)";
- break;
- case NodeState::ST_ILLEGAL_TYPE:
- type = "";
- break;
- default:{
- BaseString::snprintf(m_text, m_text_len,
- "%sStart phase %u completed (unknown = %d)",
- theNodeId,
- theData[1],
- theData[2]);
- return m_text;
- }
- }
- BaseString::snprintf(m_text, m_text_len,
- "%sStart phase %u completed %s",
- theNodeId,
- theData[1],
- type);
- return m_text;
- break;
- }
- case EventReport::CM_REGCONF:
- BaseString::snprintf(m_text, m_text_len,
- "%sCM_REGCONF president = %u, own Node = %u, our dynamic id = %u"
- ,
- theNodeId,
- theData[2],
- theData[1],
- theData[3]);
- break;
- case EventReport::CM_REGREF:
- {
- const char* line = "";
- switch (theData[3]) {
- case 0:
- line = "Busy";
- break;
- case 1:
- line = "Election with wait = false";
- break;
- case 2:
- line = "Election with wait = false";
- break;
- case 3:
- line = "Not president";
- break;
- case 4:
- line = "Election without selecting new candidate";
- break;
- default:
- line = "No such cause";
- break;
- }//switch
-
- BaseString::snprintf(m_text, m_text_len,
- "%sCM_REGREF from Node %u to our Node %u. Cause = %s",
- theNodeId,
- theData[2],
- theData[1],
- line);
- }
- break;
- case EventReport::FIND_NEIGHBOURS:
- //-----------------------------------------------------------------------
- // REPORT Node Restart copied a fragment.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sWe are Node %u with dynamic ID %u, our left neighbour "
- "is Node %u, our right is Node %u",
- theNodeId,
- theData[1],
- theData[4],
- theData[2],
- theData[3]);
- break;
- case EventReport::NodeFailCompleted:
- //-----------------------------------------------------------------------
- // REPORT Node failure phase completed.
- //-----------------------------------------------------------------------
- if (theData[1] == 0)
- {
- if (theData[3] != 0) {
- BaseString::snprintf(m_text, m_text_len,
- "%sNode %u completed failure of Node %u",
- theNodeId,
- theData[3],
- theData[2]);
- } else {
- BaseString::snprintf(m_text, m_text_len,
- "%sAll nodes completed failure of Node %u",
- theNodeId,
- theData[2]);
- }//if
- } else {
- const char* line = "";
- if (theData[1] == DBTC){
- line = "DBTC";
- }else if (theData[1] == DBDICT){
- line = "DBDICT";
- }else if (theData[1] == DBDIH){
- line = "DBDIH";
- }else if (theData[1] == DBLQH){
- line = "DBLQH";
- }
-
- BaseString::snprintf(m_text, m_text_len,
- "%sNode failure of %u %s completed",
- theNodeId,
- theData[2],
- line);
- }
- break;
- case EventReport::NODE_FAILREP:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode %u has failed. The Node state at failure "
- "was %u",
- theNodeId,
- theData[1],
- theData[2]);
-
- break;
- case EventReport::ArbitState:
- //-----------------------------------------------------------------------
- // REPORT arbitrator found or lost.
- //-----------------------------------------------------------------------
- { const ArbitSignalData* sd = (ArbitSignalData*)theData;
- char ticketText[ArbitTicket::TextLength + 1];
- char errText[ArbitCode::ErrTextLength + 1];
- const unsigned code = sd->code & 0xFFFF;
- const unsigned state = sd->code >> 16;
- switch (code) {
- case ArbitCode::ThreadStart:
- BaseString::snprintf(m_text, m_text_len,
- "%sPresident restarts arbitration thread [state=%u]",
- theNodeId, state);
- break;
- case ArbitCode::PrepPart2:
- sd->ticket.getText(ticketText, sizeof(ticketText));
- BaseString::snprintf(m_text, m_text_len,
- "%sPrepare arbitrator node %u [ticket=%s]",
- theNodeId, sd->node, ticketText);
- break;
- case ArbitCode::PrepAtrun:
- sd->ticket.getText(ticketText, sizeof(ticketText));
- BaseString::snprintf(m_text, m_text_len,
- "%sReceive arbitrator node %u [ticket=%s]",
- theNodeId, sd->node, ticketText);
- break;
- case ArbitCode::ApiStart:
- sd->ticket.getText(ticketText, sizeof(ticketText));
- BaseString::snprintf(m_text, m_text_len,
- "%sStarted arbitrator node %u [ticket=%s]",
- theNodeId, sd->node, ticketText);
- break;
- case ArbitCode::ApiFail:
- BaseString::snprintf(m_text, m_text_len,
- "%sLost arbitrator node %u - process failure [state=%u]",
- theNodeId, sd->node, state);
- break;
- case ArbitCode::ApiExit:
- BaseString::snprintf(m_text, m_text_len,
- "%sLost arbitrator node %u - process exit [state=%u]",
- theNodeId, sd->node, state);
- break;
- default:
- ArbitCode::getErrText(code, errText, sizeof(errText));
- BaseString::snprintf(m_text, m_text_len,
- "%sLost arbitrator node %u - %s [state=%u]",
- theNodeId, sd->node, errText, state);
- break;
- }
- }
- break;
- case EventReport::ArbitResult:
- //-----------------------------------------------------------------------
- // REPORT arbitration result (the failures may not reach us).
- //-----------------------------------------------------------------------
- { const ArbitSignalData* sd = (ArbitSignalData*)theData;
- char errText[ArbitCode::ErrTextLength + 1];
- const unsigned code = sd->code & 0xFFFF;
- const unsigned state = sd->code >> 16;
- switch (code) {
- case ArbitCode::LoseNodes:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration check lost - less than 1/2 nodes left",
- theNodeId);
- break;
- case ArbitCode::WinNodes:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration check won - all node groups and more than 1/2 nodes left",
- theNodeId);
- break;
- case ArbitCode::WinGroups:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration check won - node group majority",
- theNodeId);
- break;
- case ArbitCode::LoseGroups:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration check lost - missing node group",
- theNodeId);
- break;
- case ArbitCode::Partitioning:
- BaseString::snprintf(m_text, m_text_len,
- "%sNetwork partitioning - arbitration required",
- theNodeId);
- break;
- case ArbitCode::WinChoose:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration won - positive reply from node %u",
- theNodeId, sd->node);
- break;
- case ArbitCode::LoseChoose:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration lost - negative reply from node %u",
- theNodeId, sd->node);
- break;
- case ArbitCode::LoseNorun:
- BaseString::snprintf(m_text, m_text_len,
- "%sNetwork partitioning - no arbitrator available",
- theNodeId);
- break;
- case ArbitCode::LoseNocfg:
- BaseString::snprintf(m_text, m_text_len,
- "%sNetwork partitioning - no arbitrator configured",
- theNodeId);
- break;
- default:
- ArbitCode::getErrText(code, errText, sizeof(errText));
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration failure - %s [state=%u]",
- theNodeId, errText, state);
- break;
- }
- }
+void getTextConnected(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u Connected",
+ theData[1]);
+}
+void getTextConnectedApiVersion(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u: API version %d.%d.%d",
+ theData[1],
+ getMajor(theData[2]),
+ getMinor(theData[2]),
+ getBuild(theData[2]));
+}
+void getTextDisconnected(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u Disconnected",
+ theData[1]);
+}
+void getTextCommunicationClosed(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT communication to node closed.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Communication to Node %u closed",
+ theData[1]);
+}
+void getTextCommunicationOpened(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT communication to node opened.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Communication to Node %u opened",
+ theData[1]);
+}
+void getTextNDBStartStarted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // Start of NDB has been initiated.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Start initiated (version %d.%d.%d)",
+ getMajor(theData[1]),
+ getMinor(theData[1]),
+ getBuild(theData[1]));
+}
+void getTextNDBStopStarted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "%s shutdown initiated",
+ (theData[1] == 1 ? "Cluster" : "Node"));
+}
+void getTextNDBStopAborted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node shutdown aborted");
+}
+void getTextNDBStartCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // Start of NDB has been completed.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Started (version %d.%d.%d)",
+ getMajor(theData[1]),
+ getMinor(theData[1]),
+ getBuild(theData[1]));
+}
+void getTextSTTORRYRecieved(QQQQ) {
+ //-----------------------------------------------------------------------
+ // STTORRY recevied after restart finished.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "STTORRY received after restart finished");
+}
+void getTextStartPhaseCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Start phase completed.
+ //-----------------------------------------------------------------------
+ const char *type = "<Unknown>";
+ switch((NodeState::StartType)theData[2]){
+ case NodeState::ST_INITIAL_START:
+ type = "(initial start)";
break;
- case EventReport::GlobalCheckpointStarted:
- //-----------------------------------------------------------------------
- // This event reports that a global checkpoint has been started and this
- // node is the master of this global checkpoint.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sGlobal checkpoint %u started",
- theNodeId,
- theData[1]);
+ case NodeState::ST_SYSTEM_RESTART:
+ type = "(system restart)";
break;
- case EventReport::GlobalCheckpointCompleted:
- //-----------------------------------------------------------------------
- // This event reports that a global checkpoint has been completed on this
- // node and the node is the master of this global checkpoint.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sGlobal checkpoint %u completed",
- theNodeId,
- theData[1]);
+ case NodeState::ST_NODE_RESTART:
+ type = "(node restart)";
break;
- case EventReport::LocalCheckpointStarted:
- //-----------------------------------------------------------------------
- // This event reports that a local checkpoint has been started and this
- // node is the master of this local checkpoint.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLocal checkpoint %u started. "
- "Keep GCI = %u oldest restorable GCI = %u",
- theNodeId,
- theData[1],
- theData[2],
- theData[3]);
+ case NodeState::ST_INITIAL_NODE_RESTART:
+ type = "(initial node restart)";
break;
- case EventReport::LocalCheckpointCompleted:
- //-----------------------------------------------------------------------
- // This event reports that a local checkpoint has been completed on this
- // node and the node is the master of this local checkpoint.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLocal checkpoint %u completed",
- theNodeId,
- theData[1]);
+ case NodeState::ST_ILLEGAL_TYPE:
+ type = "";
break;
- case EventReport::TableCreated:
- //-----------------------------------------------------------------------
- // This event reports that a table has been created.
- //-----------------------------------------------------------------------
+ default:
BaseString::snprintf(m_text, m_text_len,
- "%sTable with ID = %u created",
- theNodeId,
- theData[1]);
- break;
- case EventReport::LCPStoppedInCalcKeepGci:
- if (theData[1] == 0)
- BaseString::snprintf(m_text, m_text_len,
- "%sLocal Checkpoint stopped in CALCULATED_KEEP_GCI",
- theNodeId);
- break;
- case EventReport::NR_CopyDict:
- //-----------------------------------------------------------------------
- // REPORT Node Restart completed copy of dictionary information.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode restart completed copy of dictionary information",
- theNodeId);
- break;
- case EventReport::NR_CopyDistr:
- //-----------------------------------------------------------------------
- // REPORT Node Restart completed copy of distribution information.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode restart completed copy of distribution information",
- theNodeId);
- break;
- case EventReport::NR_CopyFragsStarted:
- //-----------------------------------------------------------------------
- // REPORT Node Restart is starting to copy the fragments.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode restart starting to copy the fragments "
- "to Node %u",
- theNodeId,
- theData[1]);
- break;
- case EventReport::NR_CopyFragDone:
- //-----------------------------------------------------------------------
- // REPORT Node Restart copied a fragment.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sTable ID = %u, fragment ID = %u have been copied "
- "to Node %u",
- theNodeId,
- theData[2],
- theData[3],
- theData[1]);
- break;
- case EventReport::NR_CopyFragsCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode restart completed copying the fragments "
- "to Node %u",
- theNodeId,
- theData[1]);
- break;
- case EventReport::LCPFragmentCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sTable ID = %u, fragment ID = %u has completed LCP "
- "on Node %u maxGciStarted: %d maxGciCompleted: %d",
- theNodeId,
- theData[2],
- theData[3],
- theData[1],
- theData[4],
- theData[5]);
+ "Start phase %u completed (unknown = %d)",
+ theData[1],
+ theData[2]);
+ return;
+ }
+ BaseString::snprintf(m_text, m_text_len,
+ "Start phase %u completed %s",
+ theData[1],
+ type);
+}
+void getTextCM_REGCONF(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "CM_REGCONF president = %u, own Node = %u, our dynamic id = %u",
+ theData[2],
+ theData[1],
+ theData[3]);
+}
+void getTextCM_REGREF(QQQQ) {
+ const char* line = "";
+ switch (theData[3]) {
+ case 0:
+ line = "Busy";
break;
- case EventReport::TransReportCounters:
- // -------------------------------------------------------------------
- // Report information about transaction activity once per 10 seconds.
- // -------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sTrans. Count = %u, Commit Count = %u, "
- "Read Count = %u, Simple Read Count = %u,\n"
- "Write Count = %u, AttrInfo Count = %u, "
- "Concurrent Operations = %u, Abort Count = %u\n"
- " Scans: %u Range scans: %u",
- theNodeId,
- theData[1],
- theData[2],
- theData[3],
- theData[4],
- theData[5],
- theData[6],
- theData[7],
- theData[8],
- theData[9],
- theData[10]);
+ case 1:
+ line = "Election with wait = false";
break;
- case EventReport::OperationReportCounters:
- BaseString::snprintf(m_text, m_text_len,
- "%sOperations=%u",
- theNodeId,
- theData[1]);
+ case 2:
+ line = "Election with wait = false";
break;
- case EventReport::UndoLogBlocked:
- //-----------------------------------------------------------------------
- // REPORT Undo Logging blocked due to buffer near to overflow.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sACC Blocked %u and TUP Blocked %u times last second",
- theNodeId,
- theData[1],
- theData[2]);
- break;
- case EventReport::TransporterError:
- case EventReport::TransporterWarning:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sTransporter to node %d reported error 0x%x",
- theNodeId,
- theData[1],
- theData[2]);
- break;
- case EventReport::MissedHeartbeat:
- //-----------------------------------------------------------------------
- // REPORT Undo Logging blocked due to buffer near to overflow.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode %d missed heartbeat %d",
- theNodeId,
- theData[1],
- theData[2]);
- break;
- case EventReport::DeadDueToHeartbeat:
- //-----------------------------------------------------------------------
- // REPORT Undo Logging blocked due to buffer near to overflow.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode %d declared dead due to missed heartbeat",
- theNodeId,
- theData[1]);
- break;
- case EventReport::JobStatistic:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sMean loop Counter in doJob last 8192 times = %u",
- theNodeId,
- theData[1]);
+ case 3:
+ line = "Not president";
break;
- case EventReport::SendBytesStatistic:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sMean send size to Node = %d last 4096 sends = %u bytes",
- theNodeId,
- theData[1],
- theData[2]);
+ case 4:
+ line = "Election without selecting new candidate";
break;
- case EventReport::ReceiveBytesStatistic:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sMean receive size to Node = %d last 4096 sends = %u bytes",
- theNodeId,
- theData[1],
- theData[2]);
- break;
- case EventReport::SentHeartbeat:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode Sent Heartbeat to node = %d",
- theNodeId,
- theData[1]);
- break;
- case EventReport::CreateLogBytes:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLog part %u, log file %u, MB %u",
- theNodeId,
- theData[1],
- theData[2],
- theData[3]);
- break;
- case EventReport::StartLog:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLog part %u, start MB %u, stop MB %u, last GCI, log exec %u",
- theNodeId,
- theData[1],
- theData[2],
- theData[3],
- theData[4]);
- break;
- case EventReport::StartREDOLog:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode: %d StartLog: [GCI Keep: %d LastCompleted: %d NewestRestorable: %d]",
- theNodeId,
- theData[1],
- theData[2],
- theData[3],
- theData[4]);
- break;
- case EventReport::UNDORecordsExecuted:{
- const char* line = "";
- if (theData[1] == DBTUP){
- line = "DBTUP";
- }else if (theData[1] == DBACC){
- line = "DBACC";
- }
-
- BaseString::snprintf(m_text,
- m_text_len,
- "%s UNDO %s %d [%d %d %d %d %d %d %d %d %d]",
- theNodeId,
- line,
- theData[2],
- theData[3],
- theData[4],
- theData[5],
- theData[6],
- theData[7],
- theData[8],
- theData[9],
- theData[10],
- theData[11]);
- }
- break;
- case EventReport::InfoEvent:
- BaseString::snprintf(m_text,
- m_text_len,
- "%s%s",
- theNodeId,
- (char *)&theData[1]);
- break;
- case EventReport::WarningEvent:
- BaseString::snprintf(m_text,
- m_text_len,
- "%s%s",
- theNodeId,
- (char *)&theData[1]);
- break;
- case EventReport::GCP_TakeoverStarted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sGCP Take over started", theNodeId);
- break;
- case EventReport::GCP_TakeoverCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sGCP Take over completed", theNodeId);
- break;
- case EventReport::LCP_TakeoverStarted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLCP Take over started", theNodeId);
- break;
- case EventReport::LCP_TakeoverCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLCP Take over completed (state = %d)",
- theNodeId, theData[1]);
- break;
- case EventReport::MemoryUsage:{
- const int gth = theData[1];
- const int size = theData[2];
- const int used = theData[3];
- const int total = theData[4];
- const int block = theData[5];
- const int percent = (used*100)/total;
-
- BaseString::snprintf(m_text, m_text_len,
- "%s%s usage %s %d%s(%d %dK pages of total %d)",
- theNodeId,
- (block==DBACC ? "Index" : (block == DBTUP ?"Data":"<unknown>")),
- (gth == 0 ? "is" : (gth > 0 ? "increased to" : "decreased to")),
- percent, "%",
- used, size/1024, total
- );
+ default:
+ line = "No such cause";
break;
- }
- case EventReport::GrepSubscriptionInfo :
- {
- GrepEvent::Subscription event = (GrepEvent::Subscription)theData[1];
- switch(event) {
- case GrepEvent::GrepSS_CreateSubIdConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Created subscription id"
- " (subId=%d,SubKey=%d)"
- " Return code: %d.",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepPS_CreateSubIdConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: Created subscription id"
- " (subId=%d,SubKey=%d)"
- " Return code: %d.",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepSS_SubCreateConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- const int nodegrp = theData[5];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Created subscription using"
- " (subId=%d,SubKey=%d)"
- " in primary system. Primary system has %d nodegroup(s)."
- " Return code: %d",
- subId,
- subKey,
- nodegrp,
- err);
- break;
- }
- case GrepEvent::GrepPS_SubCreateConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: All participants have created "
- "subscriptions"
- " using (subId=%d,SubKey=%d)."
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepSS_SubStartMetaConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Logging started on meta data changes."
- " using (subId=%d,SubKey=%d)"
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepPS_SubStartMetaConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: All participants have started "
- "logging meta data"
- " changes on the subscription subId=%d,SubKey=%d) "
- "(N.I yet)."
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepSS_SubStartDataConf: {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Logging started on table data changes "
- " using (subId=%d,SubKey=%d)"
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepPS_SubStartDataConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: All participants have started logging "
- "table data changes on the subscription "
- "subId=%d,SubKey=%d)."
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepPS_SubSyncMetaConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: All participants have started "
- " synchronization on meta data (META SCAN) using "
- "(subId=%d,SubKey=%d)."
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepSS_SubSyncMetaConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Synchronization started (META SCAN) on "
- " meta data using (subId=%d,SubKey=%d)"
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepPS_SubSyncDataConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: All participants have started "
- "synchronization "
- " on table data (DATA SCAN) using (subId=%d,SubKey=%d)."
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepSS_SubSyncDataConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- const int gci = theData[5];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Synchronization started (DATA SCAN) on "
- "table data using (subId=%d,SubKey=%d). GCI = %d"
- " Return code: %d",
- subId,
- subKey,
- gci,
- err);
- break;
- }
- case GrepEvent::GrepPS_SubRemoveConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
+ }//switch
+
+ BaseString::snprintf(m_text, m_text_len,
+ "CM_REGREF from Node %u to our Node %u. Cause = %s",
+ theData[2],
+ theData[1],
+ line);
+}
+void getTextFIND_NEIGHBOURS(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart copied a fragment.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "We are Node %u with dynamic ID %u, our left neighbour "
+ "is Node %u, our right is Node %u",
+ theData[1],
+ theData[4],
+ theData[2],
+ theData[3]);
+}
+void getTextNodeFailCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node failure phase completed.
+ //-----------------------------------------------------------------------
+ if (theData[1] == 0)
+ {
+ if (theData[3] != 0) {
BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: All participants have removed "
- "subscription (subId=%d,SubKey=%d). I have cleaned "
- "up resources I've used."
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- case GrepEvent::GrepSS_SubRemoveConf:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
+ "Node %u completed failure of Node %u",
+ theData[3],
+ theData[2]);
+ } else {
BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Removed subscription "
- "(subId=%d,SubKey=%d)"
- " Return code: %d",
- subId,
- subKey,
- err);
- break;
- }
- default:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sUnknown GrepSubscriptonInfo event: %d",
- theNodeId,
- theData[1]);
+ "All nodes completed failure of Node %u",
+ theData[2]);
+ }//if
+ } else {
+ const char* line = "";
+ if (theData[1] == DBTC){
+ line = "DBTC";
+ }else if (theData[1] == DBDICT){
+ line = "DBDICT";
+ }else if (theData[1] == DBDIH){
+ line = "DBDIH";
+ }else if (theData[1] == DBLQH){
+ line = "DBLQH";
}
- break;
+ BaseString::snprintf(m_text, m_text_len,
+ "Node failure of %u %s completed",
+ theData[2],
+ line);
}
-
- case EventReport::GrepSubscriptionAlert :
+}
+void getTextNODE_FAILREP(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u has failed. The Node state at failure "
+ "was %u",
+ theData[1],
+ theData[2]);
+}
+void getTextArbitState(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT arbitrator found or lost.
+ //-----------------------------------------------------------------------
{
- GrepEvent::Subscription event = (GrepEvent::Subscription)theData[1];
- switch(event)
- {
- case GrepEvent::GrepSS_CreateSubIdRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord:Error code: %d Error message: %s"
- " (subId=%d,SubKey=%d)",
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err),
- subId,
- subKey);
+ const ArbitSignalData* sd = (ArbitSignalData*)theData;
+ char ticketText[ArbitTicket::TextLength + 1];
+ char errText[ArbitCode::ErrTextLength + 1];
+ const unsigned code = sd->code & 0xFFFF;
+ const unsigned state = sd->code >> 16;
+ switch (code) {
+ case ArbitCode::ThreadStart:
+ BaseString::snprintf(m_text, m_text_len,
+ "President restarts arbitration thread [state=%u]",
+ state);
+ break;
+ case ArbitCode::PrepPart2:
+ sd->ticket.getText(ticketText, sizeof(ticketText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Prepare arbitrator node %u [ticket=%s]",
+ sd->node, ticketText);
+ break;
+ case ArbitCode::PrepAtrun:
+ sd->ticket.getText(ticketText, sizeof(ticketText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Receive arbitrator node %u [ticket=%s]",
+ sd->node, ticketText);
+ break;
+ case ArbitCode::ApiStart:
+ sd->ticket.getText(ticketText, sizeof(ticketText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Started arbitrator node %u [ticket=%s]",
+ sd->node, ticketText);
+ break;
+ case ArbitCode::ApiFail:
+ BaseString::snprintf(m_text, m_text_len,
+ "Lost arbitrator node %u - process failure [state=%u]",
+ sd->node, state);
+ break;
+ case ArbitCode::ApiExit:
+ BaseString::snprintf(m_text, m_text_len,
+ "Lost arbitrator node %u - process exit [state=%u]",
+ sd->node, state);
break;
- }
- case GrepEvent::GrepSS_SubCreateRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: FAILED to Created subscription using"
- " (subId=%d,SubKey=%d)in primary system."
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepSS_SubStartMetaRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Logging failed to start on meta "
- "data changes."
- " using (subId=%d,SubKey=%d)"
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepSS_SubStartDataRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Logging FAILED to start on table data "
- " changes using (subId=%d,SubKey=%d)"
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepSS_SubSyncMetaRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Synchronization FAILED (META SCAN) on "
- " meta data using (subId=%d,SubKey=%d)"
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepSS_SubSyncDataRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- const int gci = theData[5];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Synchronization FAILED (DATA SCAN) on "
- "table data using (subId=%d,SubKey=%d). GCI = %d"
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- gci,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepSS_SubRemoveRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::SSCoord: Failed to remove subscription "
- "(subId=%d,SubKey=%d). "
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err)
- );
- break;
- }
-
- case GrepEvent::GrepPS_CreateSubIdRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: Error code: %d Error Message: %s"
- " (subId=%d,SubKey=%d)",
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err),
- subId,
- subKey);
- break;
- }
- case GrepEvent::GrepPS_SubCreateRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: FAILED to Created subscription using"
- " (subId=%d,SubKey=%d)in primary system."
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepPS_SubStartMetaRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: Logging failed to start on meta "
- "data changes."
- " using (subId=%d,SubKey=%d)"
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepPS_SubStartDataRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: Logging FAILED to start on table data "
- " changes using (subId=%d,SubKey=%d)"
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepPS_SubSyncMetaRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: Synchronization FAILED (META SCAN) on "
- " meta data using (subId=%d,SubKey=%d)"
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::GrepPS_SubSyncDataRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- const int gci = theData[5];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: Synchronization FAILED (DATA SCAN) on "
- "table data using (subId=%d,SubKey=%d). GCI = %d. "
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- gci,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
+ default:
+ ArbitCode::getErrText(code, errText, sizeof(errText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Lost arbitrator node %u - %s [state=%u]",
+ sd->node, errText, state);
break;
}
- case GrepEvent::GrepPS_SubRemoveRef:
- {
- const int subId = theData[2];
- const int subKey = theData[3];
- const int err = theData[4];
- BaseString::snprintf(m_text, m_text_len,
- "Grep::PSCoord: Failed to remove subscription "
- "(subId=%d,SubKey=%d)."
- " Error code: %d Error Message: %s",
- subId,
- subKey,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
- break;
- }
- case GrepEvent::Rep_Disconnect:
- {
- const int err = theData[4];
- const int nodeId = theData[5];
- BaseString::snprintf(m_text, m_text_len,
- "Rep: Node %d."
- " Error code: %d Error Message: %s",
- nodeId,
- err,
- GrepError::getErrorDesc((GrepError::GE_Code)err));
+ }
+}
+
+void getTextArbitResult(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT arbitration result (the failures may not reach us).
+ //-----------------------------------------------------------------------
+ {
+ const ArbitSignalData* sd = (ArbitSignalData*)theData;
+ char errText[ArbitCode::ErrTextLength + 1];
+ const unsigned code = sd->code & 0xFFFF;
+ const unsigned state = sd->code >> 16;
+ switch (code) {
+ case ArbitCode::LoseNodes:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration check lost - less than 1/2 nodes left");
+ break;
+ case ArbitCode::WinNodes:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration check won - all node groups and more than 1/2 nodes left");
+ break;
+ case ArbitCode::WinGroups:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration check won - node group majority");
+ break;
+ case ArbitCode::LoseGroups:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration check lost - missing node group");
+ break;
+ case ArbitCode::Partitioning:
+ BaseString::snprintf(m_text, m_text_len,
+ "Network partitioning - arbitration required");
+ break;
+ case ArbitCode::WinChoose:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration won - positive reply from node %u",
+ sd->node);
+ break;
+ case ArbitCode::LoseChoose:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration lost - negative reply from node %u",
+ sd->node);
+ break;
+ case ArbitCode::LoseNorun:
+ BaseString::snprintf(m_text, m_text_len,
+ "Network partitioning - no arbitrator available");
+ break;
+ case ArbitCode::LoseNocfg:
+ BaseString::snprintf(m_text, m_text_len,
+ "Network partitioning - no arbitrator configured");
break;
- }
-
-
default:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sUnknown GrepSubscriptionAlert event: %d",
- theNodeId,
- theData[1]);
- break;
+ ArbitCode::getErrText(code, errText, sizeof(errText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration failure - %s [state=%u]",
+ errText, state);
+ break;
}
- break;
}
-
- case EventReport::BackupStarted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sBackup %d started from node %d",
- theNodeId, theData[2], refToNode(theData[1]));
- break;
- case EventReport::BackupFailedToStart:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sBackup request from %d failed to start. Error: %d",
- theNodeId, refToNode(theData[1]), theData[2]);
- break;
- case EventReport::BackupCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sBackup %u started from node %u completed\n"
- " StartGCP: %u StopGCP: %u\n"
- " #Records: %u #LogRecords: %u\n"
- " Data: %u bytes Log: %u bytes",
- theNodeId, theData[2], refToNode(theData[1]),
- theData[3], theData[4], theData[6], theData[8],
- theData[5], theData[7]);
- break;
- case EventReport::BackupAborted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sBackup %d started from %d has been aborted. Error: %d",
- theNodeId,
- theData[2],
- refToNode(theData[1]),
- theData[3]);
- break;
- default:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sUnknown event: %d",
- theNodeId,
- theData[0]);
-
+}
+void getTextGlobalCheckpointStarted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a global checkpoint has been started and this
+ // node is the master of this global checkpoint.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Global checkpoint %u started",
+ theData[1]);
+}
+void getTextGlobalCheckpointCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a global checkpoint has been completed on this
+ // node and the node is the master of this global checkpoint.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Global checkpoint %u completed",
+ theData[1]);
+}
+void getTextLocalCheckpointStarted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a local checkpoint has been started and this
+ // node is the master of this local checkpoint.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Local checkpoint %u started. "
+ "Keep GCI = %u oldest restorable GCI = %u",
+ theData[1],
+ theData[2],
+ theData[3]);
+}
+void getTextLocalCheckpointCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a local checkpoint has been completed on this
+ // node and the node is the master of this local checkpoint.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Local checkpoint %u completed",
+ theData[1]);
+}
+void getTextTableCreated(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a table has been created.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Table with ID = %u created",
+ theData[1]);
+}
+/* STRANGE */
+void getTextLCPStoppedInCalcKeepGci(QQQQ) {
+ if (theData[1] == 0)
+ BaseString::snprintf(m_text, m_text_len,
+ "Local Checkpoint stopped in CALCULATED_KEEP_GCI");
+}
+void getTextNR_CopyDict(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart completed copy of dictionary information.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node restart completed copy of dictionary information");
+}
+void getTextNR_CopyDistr(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart completed copy of distribution information.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node restart completed copy of distribution information");
+}
+void getTextNR_CopyFragsStarted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart is starting to copy the fragments.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node restart starting to copy the fragments "
+ "to Node %u",
+ theData[1]);
+}
+void getTextNR_CopyFragDone(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart copied a fragment.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Table ID = %u, fragment ID = %u have been copied "
+ "to Node %u",
+ theData[2],
+ theData[3],
+ theData[1]);
+}
+void getTextNR_CopyFragsCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node restart completed copying the fragments "
+ "to Node %u",
+ theData[1]);
+}
+void getTextLCPFragmentCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Table ID = %u, fragment ID = %u has completed LCP "
+ "on Node %u maxGciStarted: %d maxGciCompleted: %d",
+ theData[2],
+ theData[3],
+ theData[1],
+ theData[4],
+ theData[5]);
+}
+void getTextTransReportCounters(QQQQ) {
+ // -------------------------------------------------------------------
+ // Report information about transaction activity once per 10 seconds.
+ // -------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Trans. Count = %u, Commit Count = %u, "
+ "Read Count = %u, Simple Read Count = %u,\n"
+ "Write Count = %u, AttrInfo Count = %u, "
+ "Concurrent Operations = %u, Abort Count = %u\n"
+ " Scans: %u Range scans: %u",
+ theData[1],
+ theData[2],
+ theData[3],
+ theData[4],
+ theData[5],
+ theData[6],
+ theData[7],
+ theData[8],
+ theData[9],
+ theData[10]);
+}
+void getTextOperationReportCounters(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Operations=%u",
+ theData[1]);
+}
+void getTextUndoLogBlocked(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Undo Logging blocked due to buffer near to overflow.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "ACC Blocked %u and TUP Blocked %u times last second",
+ theData[1],
+ theData[2]);
+}
+void getTextTransporterError(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Transporter to node %d reported error 0x%x",
+ theData[1],
+ theData[2]);
+}
+void getTextTransporterWarning(QQQQ) {
+ getTextTransporterError(m_text, m_text_len, theData);
+}
+void getTextMissedHeartbeat(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Undo Logging blocked due to buffer near to overflow.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %d missed heartbeat %d",
+ theData[1],
+ theData[2]);
+}
+void getTextDeadDueToHeartbeat(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Undo Logging blocked due to buffer near to overflow.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %d declared dead due to missed heartbeat",
+ theData[1]);
+}
+void getTextJobStatistic(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Mean loop Counter in doJob last 8192 times = %u",
+ theData[1]);
+}
+void getTextSendBytesStatistic(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Mean send size to Node = %d last 4096 sends = %u bytes",
+ theData[1],
+ theData[2]);
+}
+void getTextReceiveBytesStatistic(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Mean receive size to Node = %d last 4096 sends = %u bytes",
+ theData[1],
+ theData[2]);
+}
+void getTextSentHeartbeat(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node Sent Heartbeat to node = %d",
+ theData[1]);
+}
+void getTextCreateLogBytes(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Log part %u, log file %u, MB %u",
+ theData[1],
+ theData[2],
+ theData[3]);
+}
+void getTextStartLog(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Log part %u, start MB %u, stop MB %u, last GCI, log exec %u",
+ theData[1],
+ theData[2],
+ theData[3],
+ theData[4]);
+}
+void getTextStartREDOLog(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node: %d StartLog: [GCI Keep: %d LastCompleted: %d NewestRestorable: %d]",
+ theData[1],
+ theData[2],
+ theData[3],
+ theData[4]);
+}
+void getTextUNDORecordsExecuted(QQQQ) {
+ const char* line = "";
+ if (theData[1] == DBTUP){
+ line = "DBTUP";
+ }else if (theData[1] == DBACC){
+ line = "DBACC";
}
- return m_text;
+
+ BaseString::snprintf(m_text, m_text_len,
+ " UNDO %s %d [%d %d %d %d %d %d %d %d %d]",
+ line,
+ theData[2],
+ theData[3],
+ theData[4],
+ theData[5],
+ theData[6],
+ theData[7],
+ theData[8],
+ theData[9],
+ theData[10],
+ theData[11]);
+}
+void getTextInfoEvent(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, (char *)&theData[1]);
+}
+void getTextWarningEvent(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, (char *)&theData[1]);
+}
+void getTextGCP_TakeoverStarted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, "GCP Take over started");
+}
+void getTextGCP_TakeoverCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, "GCP Take over completed");
+}
+void getTextLCP_TakeoverStarted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, "LCP Take over started");
+}
+void getTextLCP_TakeoverCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "LCP Take over completed (state = %d)",
+ theData[1]);
+}
+void getTextMemoryUsage(QQQQ) {
+ const int gth = theData[1];
+ const int size = theData[2];
+ const int used = theData[3];
+ const int total = theData[4];
+ const int block = theData[5];
+ const int percent = (used*100)/total;
+
+ BaseString::snprintf(m_text, m_text_len,
+ "%s usage %s %d%s(%d %dK pages of total %d)",
+ (block==DBACC ? "Index" : (block == DBTUP ?"Data":"<unknown>")),
+ (gth == 0 ? "is" : (gth > 0 ? "increased to" : "decreased to")),
+ percent, "%",
+ used, size/1024, total
+ );
+}
+
+void getTextBackupStarted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Backup %d started from node %d",
+ theData[2], refToNode(theData[1]));
+}
+void getTextBackupFailedToStart(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Backup request from %d failed to start. Error: %d",
+ refToNode(theData[1]), theData[2]);
+}
+void getTextBackupCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Backup %u started from node %u completed\n"
+ " StartGCP: %u StopGCP: %u\n"
+ " #Records: %u #LogRecords: %u\n"
+ " Data: %u bytes Log: %u bytes",
+ theData[2], refToNode(theData[1]),
+ theData[3], theData[4], theData[6], theData[8],
+ theData[5], theData[7]);
+}
+void getTextBackupAborted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Backup %d started from %d has been aborted. Error: %d",
+ theData[2],
+ refToNode(theData[1]),
+ theData[3]);
}
+#if 0
+BaseString::snprintf(m_text,
+ m_text_len,
+ "Unknown event: %d",
+ theData[0]);
+#endif
+
+/**
+ * This matrix defines which event should be printed when
+ *
+ * threshold - is in range [0-15]
+ * severity - DEBUG to ALERT (Type of log message)
+ */
+
+#define ROW(a,b,c,d) \
+{ NDB_LE_ ## a, b, c, d, getText ## a}
+
+const EventLoggerBase::EventRepLogLevelMatrix EventLoggerBase::matrix[] = {
+ // CONNECTION
+ ROW(Connected, LogLevel::llConnection, 8, Logger::LL_INFO ),
+ ROW(Disconnected, LogLevel::llConnection, 8, Logger::LL_ALERT ),
+ ROW(CommunicationClosed, LogLevel::llConnection, 8, Logger::LL_INFO ),
+ ROW(CommunicationOpened, LogLevel::llConnection, 8, Logger::LL_INFO ),
+ ROW(ConnectedApiVersion, LogLevel::llConnection, 8, Logger::LL_INFO ),
+ // CHECKPOINT
+ ROW(GlobalCheckpointStarted, LogLevel::llCheckpoint, 9, Logger::LL_INFO ),
+ ROW(GlobalCheckpointCompleted,LogLevel::llCheckpoint,10, Logger::LL_INFO ),
+ ROW(LocalCheckpointStarted, LogLevel::llCheckpoint, 7, Logger::LL_INFO ),
+ ROW(LocalCheckpointCompleted,LogLevel::llCheckpoint, 8, Logger::LL_INFO ),
+ ROW(LCPStoppedInCalcKeepGci, LogLevel::llCheckpoint, 0, Logger::LL_ALERT ),
+ ROW(LCPFragmentCompleted, LogLevel::llCheckpoint, 11, Logger::LL_INFO ),
+ ROW(UndoLogBlocked, LogLevel::llCheckpoint, 7, Logger::LL_INFO ),
+
+ // STARTUP
+ ROW(NDBStartStarted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(NDBStartCompleted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(STTORRYRecieved, LogLevel::llStartUp, 15, Logger::LL_INFO ),
+ ROW(StartPhaseCompleted, LogLevel::llStartUp, 4, Logger::LL_INFO ),
+ ROW(CM_REGCONF, LogLevel::llStartUp, 3, Logger::LL_INFO ),
+ ROW(CM_REGREF, LogLevel::llStartUp, 8, Logger::LL_INFO ),
+ ROW(FIND_NEIGHBOURS, LogLevel::llStartUp, 8, Logger::LL_INFO ),
+ ROW(NDBStopStarted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(NDBStopAborted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(StartREDOLog, LogLevel::llStartUp, 10, Logger::LL_INFO ),
+ ROW(StartLog, LogLevel::llStartUp, 10, Logger::LL_INFO ),
+ ROW(UNDORecordsExecuted, LogLevel::llStartUp, 15, Logger::LL_INFO ),
+
+ // NODERESTART
+ ROW(NR_CopyDict, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+ ROW(NR_CopyDistr, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+ ROW(NR_CopyFragsStarted, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+ ROW(NR_CopyFragDone, LogLevel::llNodeRestart,10, Logger::LL_INFO ),
+ ROW(NR_CopyFragsCompleted, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+
+ ROW(NodeFailCompleted, LogLevel::llNodeRestart, 8, Logger::LL_ALERT),
+ ROW(NODE_FAILREP, LogLevel::llNodeRestart, 8, Logger::LL_ALERT),
+ ROW(ArbitState, LogLevel::llNodeRestart, 6, Logger::LL_INFO ),
+ ROW(ArbitResult, LogLevel::llNodeRestart, 2, Logger::LL_ALERT),
+ ROW(GCP_TakeoverStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+ ROW(GCP_TakeoverCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+ ROW(LCP_TakeoverStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+ ROW(LCP_TakeoverCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+
+ // STATISTIC
+ ROW(TransReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO ),
+ ROW(OperationReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO ),
+ ROW(TableCreated, LogLevel::llStatistic, 7, Logger::LL_INFO ),
+ ROW(JobStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ),
+ ROW(SendBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ),
+ ROW(ReceiveBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ),
+ ROW(MemoryUsage, LogLevel::llStatistic, 5, Logger::LL_INFO ),
+
+ // ERROR
+ ROW(TransporterError, LogLevel::llError, 2, Logger::LL_ERROR ),
+ ROW(TransporterWarning, LogLevel::llError, 8, Logger::LL_WARNING ),
+ ROW(MissedHeartbeat, LogLevel::llError, 8, Logger::LL_WARNING ),
+ ROW(DeadDueToHeartbeat, LogLevel::llError, 8, Logger::LL_ALERT ),
+ ROW(WarningEvent, LogLevel::llError, 2, Logger::LL_WARNING ),
+ // INFO
+ ROW(SentHeartbeat, LogLevel::llInfo, 12, Logger::LL_INFO ),
+ ROW(CreateLogBytes, LogLevel::llInfo, 11, Logger::LL_INFO ),
+ ROW(InfoEvent, LogLevel::llInfo, 2, Logger::LL_INFO ),
+
+ // Backup
+ ROW(BackupStarted, LogLevel::llBackup, 7, Logger::LL_INFO ),
+ ROW(BackupCompleted, LogLevel::llBackup, 7, Logger::LL_INFO ),
+ ROW(BackupFailedToStart, LogLevel::llBackup, 7, Logger::LL_ALERT),
+ ROW(BackupAborted, LogLevel::llBackup, 7, Logger::LL_ALERT )
+};
+
+const Uint32 EventLoggerBase::matrixSize=
+sizeof(EventLoggerBase::matrix)/sizeof(EventRepLogLevelMatrix);
+
EventLogger::EventLogger() : m_filterLevel(15)
{
setCategory("EventLogger");
@@ -1348,19 +764,37 @@ int
EventLoggerBase::event_lookup(int eventType,
LogLevel::EventCategory &cat,
Uint32 &threshold,
- Logger::LoggerLevel &severity)
+ Logger::LoggerLevel &severity,
+ EventTextFunction &textF)
{
for(unsigned i = 0; i<EventLoggerBase::matrixSize; i++){
if(EventLoggerBase::matrix[i].eventType == eventType){
cat = EventLoggerBase::matrix[i].eventCategory;
threshold = EventLoggerBase::matrix[i].threshold;
severity = EventLoggerBase::matrix[i].severity;
+ textF= EventLoggerBase::matrix[i].textF;
return 0;
}
}
return 1;
}
+const char*
+EventLogger::getText(char * dst, size_t dst_len,
+ EventTextFunction textF,
+ const Uint32* theData, NodeId nodeId )
+{
+ int pos= 0;
+ if (nodeId != 0)
+ {
+ BaseString::snprintf(dst, dst_len, "Node %u: ", nodeId);
+ pos= strlen(dst);
+ }
+ if (dst_len-pos > 0)
+ textF(dst+pos,dst_len-pos,theData);
+ return dst;
+}
+
void
EventLogger::log(int eventType, const Uint32* theData, NodeId nodeId,
const LogLevel* ll)
@@ -1368,52 +802,43 @@ EventLogger::log(int eventType, const Uint32* theData, NodeId nodeId,
Uint32 threshold = 0;
Logger::LoggerLevel severity = Logger::LL_WARNING;
LogLevel::EventCategory cat= LogLevel::llInvalid;
+ EventTextFunction textF;
DBUG_ENTER("EventLogger::log");
DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId));
- if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity))
+ if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity,textF))
DBUG_VOID_RETURN;
Uint32 set = ll?ll->getLogLevel(cat) : m_logLevel.getLogLevel(cat);
DBUG_PRINT("info",("threshold=%d, set=%d", threshold, set));
if (ll)
DBUG_PRINT("info",("m_logLevel.getLogLevel=%d", m_logLevel.getLogLevel(cat)));
+
if (threshold <= set){
+ getText(m_text,sizeof(m_text),textF,theData,nodeId);
+
switch (severity){
case Logger::LL_ALERT:
- alert(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ alert(m_text);
break;
-
case Logger::LL_CRITICAL:
- critical(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ critical(m_text);
break;
-
case Logger::LL_WARNING:
- warning(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ warning(m_text);
break;
-
case Logger::LL_ERROR:
- error(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ error(m_text);
break;
-
case Logger::LL_INFO:
- info(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ info(m_text);
break;
-
case Logger::LL_DEBUG:
- debug(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ debug(m_text);
break;
-
default:
- info(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ info(m_text);
break;
}
} // if (..
diff --git a/ndb/src/common/debugger/SignalLoggerManager.cpp b/ndb/src/common/debugger/SignalLoggerManager.cpp
index d642ed09a68..d8710d2058f 100644
--- a/ndb/src/common/debugger/SignalLoggerManager.cpp
+++ b/ndb/src/common/debugger/SignalLoggerManager.cpp
@@ -383,7 +383,7 @@ SignalLoggerManager::sendSignalWithDelay(Uint32 delayInMilliSeconds,
* Generic messages in the signal log
*/
void
-SignalLoggerManager::log(BlockNumber bno, const char * msg)
+SignalLoggerManager::log(BlockNumber bno, const char * msg, ...)
{
// Normalise blocknumber for use in logModes array
const BlockNumber bno2 = bno - MIN_BLOCK_NO;
@@ -391,7 +391,12 @@ SignalLoggerManager::log(BlockNumber bno, const char * msg)
if(outputStream != 0 &&
logModes[bno2] != LogOff){
- fprintf(outputStream, "%s: %s\n", getBlockName(bno, "API"), msg);
+ va_list ap;
+ va_start(ap, msg);
+ fprintf(outputStream, "%s: ", getBlockName(bno, "API"));
+ vfprintf(outputStream, msg, ap);
+ fprintf(outputStream, "\n");
+ va_end(ap);
}
}
diff --git a/ndb/src/common/debugger/signaldata/DictTabInfo.cpp b/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
index c6165532ddb..43c129347c0 100644
--- a/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
+++ b/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
@@ -23,7 +23,6 @@ SimpleProperties::SP2StructMapping
DictTabInfo::TableMapping[] = {
DTIMAPS(Table, TableName, TableName, 0, MAX_TAB_NAME_SIZE),
DTIMAP(Table, TableId, TableId),
- DTIMAP(Table, SecondTableId, SecondTableId),
DTIMAPS(Table, PrimaryTable, PrimaryTable, 0, MAX_TAB_NAME_SIZE),
DTIMAP(Table, PrimaryTableId, PrimaryTableId),
DTIMAP2(Table, TableLoggedFlag, TableLoggedFlag, 0, 1),
@@ -32,8 +31,6 @@ DictTabInfo::TableMapping[] = {
DTIMAP2(Table, MaxLoadFactor, MaxLoadFactor, 25, 110),
DTIMAP2(Table, FragmentTypeVal, FragmentType, 0, 3),
DTIMAP2(Table, TableStorageVal, TableStorage, 0, 0),
- DTIMAP2(Table, ScanOptimised, ScanOptimised, 0, 0),
- DTIMAP2(Table, FragmentKeyTypeVal, FragmentKeyType, 0, 2),
DTIMAP2(Table, TableTypeVal, TableType, 1, 3),
DTIMAP(Table, NoOfKeyAttr, NoOfKeyAttr),
DTIMAP2(Table, NoOfAttributes, NoOfAttributes, 1, MAX_ATTRIBUTES_IN_TABLE),
@@ -49,6 +46,8 @@ DictTabInfo::TableMapping[] = {
DTIMAP2(Table, FrmLen, FrmLen, 0, MAX_FRM_DATA_SIZE),
DTIMAPB(Table, FrmData, FrmData, 0, MAX_FRM_DATA_SIZE, FrmLen),
DTIMAP(Table, FragmentCount, FragmentCount),
+ DTIMAP2(Table, FragmentDataLen, FragmentDataLen, 0, MAX_FRAGMENT_DATA_BYTES),
+ DTIMAPB(Table, FragmentData, FragmentData, 0, MAX_FRAGMENT_DATA_BYTES, FragmentDataLen),
DTIBREAK(AttributeName)
};
@@ -62,16 +61,12 @@ SimpleProperties::SP2StructMapping
DictTabInfo::AttributeMapping[] = {
DTIMAPS(Attribute, AttributeName, AttributeName, 0, MAX_ATTR_NAME_SIZE),
DTIMAP(Attribute, AttributeId, AttributeId),
- DTIMAP2(Attribute, AttributeType, AttributeType, 0, 3),
+ DTIMAP(Attribute, AttributeType, AttributeType),
DTIMAP2(Attribute, AttributeSize, AttributeSize, 3, 7),
DTIMAP2(Attribute, AttributeArraySize, AttributeArraySize, 0, 65535),
DTIMAP2(Attribute, AttributeKeyFlag, AttributeKeyFlag, 0, 1),
- DTIMAP2(Attribute, AttributeStorage, AttributeStorage, 0, 0),
DTIMAP2(Attribute, AttributeNullableFlag, AttributeNullableFlag, 0, 1),
- DTIMAP2(Attribute, AttributeDGroup, AttributeDGroup, 0, 1),
DTIMAP2(Attribute, AttributeDKey, AttributeDKey, 0, 1),
- DTIMAP2(Attribute, AttributeStoredInd, AttributeStoredInd, 0, 1),
- DTIMAP2(Attribute, AttributeGroup, AttributeGroup, 0, 0),
DTIMAP(Attribute, AttributeExtType, AttributeExtType),
DTIMAP(Attribute, AttributeExtPrecision, AttributeExtPrecision),
DTIMAP(Attribute, AttributeExtScale, AttributeExtScale),
@@ -104,7 +99,6 @@ void
DictTabInfo::Table::init(){
memset(TableName, 0, sizeof(TableName));//TableName[0] = 0;
TableId = ~0;
- SecondTableId = ~0;
memset(PrimaryTable, 0, sizeof(PrimaryTable));//PrimaryTable[0] = 0; // Only used when "index"
PrimaryTableId = RNIL;
TableLoggedFlag = 1;
@@ -118,8 +112,6 @@ DictTabInfo::Table::init(){
KeyLength = 0;
FragmentType = DictTabInfo::AllNodesSmallTable;
TableStorage = 0;
- ScanOptimised = 0;
- FragmentKeyType = DictTabInfo::PrimaryKey;
TableType = DictTabInfo::UndefTableType;
TableVersion = 0;
IndexState = ~0;
@@ -130,23 +122,21 @@ DictTabInfo::Table::init(){
FrmLen = 0;
memset(FrmData, 0, sizeof(FrmData));
FragmentCount = 0;
+ FragmentDataLen = 0;
+ memset(FragmentData, 0, sizeof(FragmentData));
}
void
DictTabInfo::Attribute::init(){
memset(AttributeName, 0, sizeof(AttributeName));//AttributeName[0] = 0;
AttributeId = 0;
- AttributeType = DictTabInfo::UnSignedType;
+ AttributeType = ~0, // deprecated
AttributeSize = DictTabInfo::a32Bit;
AttributeArraySize = 1;
AttributeKeyFlag = 0;
- AttributeStorage = 1;
AttributeNullableFlag = 0;
- AttributeDGroup = 0;
AttributeDKey = 0;
- AttributeStoredInd = 1;
- AttributeGroup = 0;
- AttributeExtType = 0,
+ AttributeExtType = DictTabInfo::ExtUnsigned,
AttributeExtPrecision = 0,
AttributeExtScale = 0,
AttributeExtLength = 0,
diff --git a/ndb/src/common/debugger/signaldata/ScanTab.cpp b/ndb/src/common/debugger/signaldata/ScanTab.cpp
index 0755ee0a856..d78beb4740a 100644
--- a/ndb/src/common/debugger/signaldata/ScanTab.cpp
+++ b/ndb/src/common/debugger/signaldata/ScanTab.cpp
@@ -30,20 +30,26 @@ printSCANTABREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
fprintf(output, " apiConnectPtr: H\'%.8x",
sig->apiConnectPtr);
fprintf(output, " requestInfo: H\'%.8x:\n", requestInfo);
- fprintf(output, " Parallellism: %u, Batch: %u LockMode: %u, Keyinfo: %u Holdlock: %u, RangeScan: %u ReadCommitted: %u\n",
+ fprintf(output, " Parallellism: %u Batch: %u LockMode: %u Keyinfo: %u Holdlock: %u RangeScan: %u Descending: %u TupScan: %u\n ReadCommitted: %u DistributionKeyFlag: %u",
sig->getParallelism(requestInfo),
sig->getScanBatch(requestInfo),
sig->getLockMode(requestInfo),
sig->getKeyinfoFlag(requestInfo),
sig->getHoldLockFlag(requestInfo),
sig->getRangeScanFlag(requestInfo),
- sig->getReadCommittedFlag(requestInfo));
+ sig->getDescendingFlag(requestInfo),
+ sig->getTupScanFlag(requestInfo),
+ sig->getReadCommittedFlag(requestInfo),
+ sig->getDistributionKeyFlag(requestInfo));
+
+ if(sig->getDistributionKeyFlag(requestInfo))
+ fprintf(output, " DKey: %x", sig->distributionKey);
Uint32 keyLen = (sig->attrLenKeyLen >> 16);
Uint32 attrLen = (sig->attrLenKeyLen & 0xFFFF);
fprintf(output, " attrLen: %d, keyLen: %d tableId: %d, tableSchemaVer: %d\n",
attrLen, keyLen, sig->tableId, sig->tableSchemaVersion);
-
+
fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x) storedProcId: H\'%.8x\n",
sig->transId1, sig->transId2, sig->storedProcId);
fprintf(output, " batch_byte_size: %d, first_batch_size: %d\n",
diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index bd1dff074f9..34cae9f618f 100644
--- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -27,6 +27,7 @@
const NameFunctionPair
SignalDataPrintFunctions[] = {
{ GSN_TCKEYREQ, printTCKEYREQ },
+ { GSN_TCINDXREQ, printTCKEYREQ },
{ GSN_TCKEYCONF, printTCKEYCONF },
{ GSN_TCKEYREF, printTCKEYREF },
{ GSN_LQHKEYREQ, printLQHKEYREQ },
@@ -82,14 +83,10 @@ SignalDataPrintFunctions[] = {
{ GSN_ALTER_INDX_REQ, printALTER_INDX_REQ },
{ GSN_ALTER_INDX_CONF, printALTER_INDX_CONF },
{ GSN_ALTER_INDX_REF, printALTER_INDX_REF },
- { GSN_TCINDXREQ, printTCINDXREQ },
{ GSN_TCINDXCONF, printTCINDXCONF },
{ GSN_TCINDXREF, printTCINDXREF },
{ GSN_INDXKEYINFO, printINDXKEYINFO },
{ GSN_INDXATTRINFO, printINDXATTRINFO },
- //{ GSN_TCINDXNEXTREQ, printTCINDXNEXTREQ },
- //{ GSN_TCINDEXNEXTCONF, printTCINDEXNEXTCONF },
- //{ GSN_TCINDEXNEXREF, printTCINDEXNEXREF },
{ GSN_FSAPPENDREQ, printFSAPPENDREQ },
{ GSN_BACKUP_REQ, printBACKUP_REQ },
{ GSN_BACKUP_DATA, printBACKUP_DATA },
@@ -154,11 +151,17 @@ SignalDataPrintFunctions[] = {
{ GSN_DISCONNECT_REP, printDISCONNECT_REP },
{ GSN_SUB_CREATE_REQ, printSUB_CREATE_REQ },
- //{ GSN_SUB_CREATE_REF, printSUB_CREATE_REF },
+ { GSN_SUB_CREATE_REF, printSUB_CREATE_REF },
{ GSN_SUB_CREATE_CONF, printSUB_CREATE_CONF },
+ { GSN_SUB_REMOVE_REQ, printSUB_REMOVE_REQ },
+ { GSN_SUB_REMOVE_REF, printSUB_REMOVE_REF },
+ { GSN_SUB_REMOVE_CONF, printSUB_REMOVE_CONF },
{ GSN_SUB_START_REQ, printSUB_START_REQ },
{ GSN_SUB_START_REF, printSUB_START_REF },
{ GSN_SUB_START_CONF, printSUB_START_CONF },
+ { GSN_SUB_STOP_REQ, printSUB_STOP_REQ },
+ { GSN_SUB_STOP_REF, printSUB_STOP_REF },
+ { GSN_SUB_STOP_CONF, printSUB_STOP_CONF },
{ GSN_SUB_SYNC_REQ, printSUB_SYNC_REQ },
{ GSN_SUB_SYNC_REF, printSUB_SYNC_REF },
{ GSN_SUB_SYNC_CONF, printSUB_SYNC_CONF },
diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 9228e305677..984d28819c0 100644
--- a/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -578,6 +578,9 @@ const GsnName SignalNames [] = {
,{ GSN_SUB_CREATE_REQ, "SUB_CREATE_REQ" }
,{ GSN_SUB_CREATE_REF, "SUB_CREATE_REF" }
,{ GSN_SUB_CREATE_CONF, "SUB_CREATE_CONF" }
+ ,{ GSN_SUB_REMOVE_REQ, "SUB_REMOVE_REQ" }
+ ,{ GSN_SUB_REMOVE_REF, "SUB_REMOVE_REF" }
+ ,{ GSN_SUB_REMOVE_CONF, "SUB_REMOVE_CONF" }
,{ GSN_SUB_START_REQ, "SUB_START_REQ" }
,{ GSN_SUB_START_REF, "SUB_START_REF" }
,{ GSN_SUB_START_CONF, "SUB_START_CONF" }
diff --git a/ndb/src/common/debugger/signaldata/SumaImpl.cpp b/ndb/src/common/debugger/signaldata/SumaImpl.cpp
index 558842ed2ba..e50a3040fe3 100644
--- a/ndb/src/common/debugger/signaldata/SumaImpl.cpp
+++ b/ndb/src/common/debugger/signaldata/SumaImpl.cpp
@@ -40,12 +40,55 @@ printSUB_CREATE_CONF(FILE * output, const Uint32 * theData,
}
bool
+printSUB_CREATE_REF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const SubCreateRef * const sig = (SubCreateRef *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ return false;
+}
+
+bool
+printSUB_REMOVE_REQ(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo)
+{
+ const SubRemoveReq * const sig = (SubRemoveReq *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ return false;
+}
+
+bool
+printSUB_REMOVE_CONF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo)
+{
+ const SubRemoveConf * const sig = (SubRemoveConf *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ return false;
+}
+
+bool
+printSUB_REMOVE_REF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo)
+{
+ const SubRemoveRef * const sig = (SubRemoveRef *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ fprintf(output, " err: %x\n", sig->err);
+ return false;
+}
+
+bool
printSUB_START_REQ(FILE * output, const Uint32 * theData,
Uint32 len, Uint16 receiverBlockNo) {
const SubStartReq * const sig = (SubStartReq *)theData;
fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
- fprintf(output, " startPart: %x\n", sig->part);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
return false;
}
@@ -73,6 +116,37 @@ printSUB_START_CONF(FILE * output, const Uint32 * theData,
}
bool
+printSUB_STOP_REQ(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const SubStopReq * const sig = (SubStopReq *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ return false;
+}
+
+bool
+printSUB_STOP_REF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const SubStopRef * const sig = (SubStopRef *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ fprintf(output, " err: %x\n", sig->err);
+ return false;
+}
+
+bool
+printSUB_STOP_CONF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const SubStopConf * const sig = (SubStopConf *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ return false;
+}
+
+bool
printSUB_SYNC_REQ(FILE * output, const Uint32 * theData,
Uint32 len, Uint16 receiverBlockNo) {
const SubSyncReq * const sig = (SubSyncReq *)theData;
diff --git a/ndb/src/common/debugger/signaldata/TcIndx.cpp b/ndb/src/common/debugger/signaldata/TcIndx.cpp
index 6bfa29eff15..b0578f5b646 100644
--- a/ndb/src/common/debugger/signaldata/TcIndx.cpp
+++ b/ndb/src/common/debugger/signaldata/TcIndx.cpp
@@ -18,91 +18,6 @@
#include <signaldata/TcKeyReq.hpp>
#include <BlockNumbers.h>
-bool
-printTCINDXREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
-
- const TcIndxReq * const sig = (TcIndxReq *) theData;
-
- UintR requestInfo = sig->requestInfo;
- UintR scanInfo = sig->scanInfo;
-
- fprintf(output, " apiConnectPtr: H\'%.8x, senderData: H\'%.8x\n",
- sig->apiConnectPtr, sig->senderData);
-
- fprintf(output, " Operation: %s, Flags: ",
- sig->getOperationType(requestInfo) == ZREAD ? "Read" :
- sig->getOperationType(requestInfo) == ZREAD_EX ? "Read-Ex" :
- sig->getOperationType(requestInfo) == ZUPDATE ? "Update" :
- sig->getOperationType(requestInfo) == ZINSERT ? "Insert" :
- sig->getOperationType(requestInfo) == ZDELETE ? "Delete" :
- sig->getOperationType(requestInfo) == ZWRITE ? "Write" :
- "Unknown");
-
- {
- if(sig->getDirtyFlag(requestInfo)){
- fprintf(output, "Dirty ");
- }
- if(sig->getStartFlag(requestInfo)){
- fprintf(output, "Start ");
- }
- if (TcKeyReq::getExecuteFlag(sig->requestInfo)) {
- fprintf(output, "Execute ");
- }
- if(sig->getCommitFlag(requestInfo)){
- fprintf(output, "Commit, Type = ");
- UintR TcommitType = sig->getCommitType(requestInfo);
- if (TcommitType == TcIndxReq::CommitIfFailFree) {
- fprintf(output, "FailFree ");
- } else if (TcommitType == TcIndxReq::TryCommit) {
- fprintf(output, "TryCommit ");
- } else if (TcommitType == TcIndxReq::CommitAsMuchAsPossible) {
- fprintf(output, "Always ");
- }//if
- }
- if(sig->getSimpleFlag(requestInfo)){
- fprintf(output, "Simple ");
- }
- if(sig->getInterpretedFlag(requestInfo)){
- fprintf(output, "Interpreted ");
- }
- if(sig->getDistributionGroupFlag(requestInfo)){
- fprintf(output, "DGroup = %d ", sig->distrGroupHashValue);
- }
- if(sig->getDistributionKeyFlag(sig->requestInfo)){
- fprintf(output, "DKey = %d ", sig->distributionKeySize);
- }
- fprintf(output, "\n");
- }
-
- const int indexLen = sig->getIndexLength(requestInfo);
- const int attrInThis = sig->getAIInTcIndxReq(requestInfo);
- fprintf(output,
- " indexLen: %d, attrLen: %d, AI in this: %d, indexId: %d, "
- "indexSchemaVer: %d, API Ver: %d\n",
- indexLen, sig->attrLen, attrInThis,
- sig->indexId, sig->indexSchemaVersion, sig->getAPIVersion(scanInfo));
-
- fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x)\n -- Variable Data --\n",
- sig->transId1, sig->transId2);
-
- Uint32 restLen = (len - 8);
- const Uint32 * rest = &sig->scanInfo;
- while(restLen >= 7){
- fprintf(output,
- " H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n",
- rest[0], rest[1], rest[2], rest[3],
- rest[4], rest[5], rest[6]);
- restLen -= 7;
- rest += 7;
- }
- if(restLen > 0){
- for(Uint32 i = 0; i<restLen; i++)
- fprintf(output, " H\'%.8x", rest[i]);
- fprintf(output, "\n");
- }
-
- return true;
-}
bool
printTCINDXCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
diff --git a/ndb/src/common/debugger/signaldata/TcKeyReq.cpp b/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
index 7304872ff9c..3918bd5db26 100644
--- a/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
+++ b/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
@@ -68,11 +68,8 @@ printTCKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiver
if(sig->getInterpretedFlag(requestInfo)){
fprintf(output, "Interpreted ");
}
- if(sig->getDistributionGroupFlag(requestInfo)){
- fprintf(output, "DGroup = %d ", sig->distrGroupHashValue);
- }
if(sig->getDistributionKeyFlag(sig->requestInfo)){
- fprintf(output, "DKey = %d ", sig->distributionKeySize);
+ fprintf(output, " d-key");
}
fprintf(output, "\n");
}
diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index b870bc67aa3..b3d0221fedb 100644
--- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -112,6 +112,12 @@ ConfigRetriever::do_connect(int no_retries,
0 : -1;
}
+int
+ConfigRetriever::disconnect()
+{
+ return ndb_mgm_disconnect(m_handle);
+}
+
//****************************************************************************
//****************************************************************************
//****************************************************************************
diff --git a/ndb/src/common/mgmcommon/IPCConfig.cpp b/ndb/src/common/mgmcommon/IPCConfig.cpp
index 8cf5e6e8d45..f935f8ffab4 100644
--- a/ndb/src/common/mgmcommon/IPCConfig.cpp
+++ b/ndb/src/common/mgmcommon/IPCConfig.cpp
@@ -111,178 +111,6 @@ IPCConfig::addRemoteNodeId(NodeId nodeId){
}
/**
- * Returns no of transporters configured
- */
-int
-IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry)
-{
- DBUG_ENTER("IPCConfig::configureTransporters");
-
- int noOfTransportersCreated = 0;
-
- Uint32 noOfConnections;
- if(!props->get("NoOfConnections", &noOfConnections)) return -1;
-
- for (Uint32 i = 0; i < noOfConnections; i++){
- const Properties * tmp;
- Uint32 nodeId1, nodeId2;
- const char * host1;
- const char * host2;
-
- if(!props->get("Connection", i, &tmp)) continue;
- if(!tmp->get("NodeId1", &nodeId1)) continue;
- if(!tmp->get("NodeId2", &nodeId2)) continue;
- if(nodeId1 != the_ownId && nodeId2 != the_ownId) continue;
-
- Uint32 sendSignalId;
- Uint32 compression;
- Uint32 checksum;
- if(!tmp->get("SendSignalId", &sendSignalId)) continue;
- if(!tmp->get("Checksum", &checksum)) continue;
-
- const char * type;
- if(!tmp->get("Type", &type)) continue;
-
- if(strcmp("SHM", type) == 0){
- SHM_TransporterConfiguration conf;
- conf.localNodeId = the_ownId;
- conf.remoteNodeId = (nodeId1 != the_ownId ? nodeId1 : nodeId2);
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!tmp->get("ShmKey", &conf.shmKey)) continue;
- if(!tmp->get("ShmSize", &conf.shmSize)) continue;
-
- if(!theTransporterRegistry->createTransporter(&conf)){
- ndbout << "Failed to create SHM Transporter from: "
- << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
- continue;
- } else {
- noOfTransportersCreated++;
- continue;
- }
-
- } else if(strcmp("SCI", type) == 0){
- SCI_TransporterConfiguration conf;
- conf.localNodeId = the_ownId;
- conf.remoteNodeId = (nodeId1 != the_ownId ? nodeId1 : nodeId2);
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!tmp->get("SendLimit", &conf.sendLimit)) continue;
- if(!tmp->get("SharedBufferSize", &conf.bufferSize)) continue;
-
- if(the_ownId == nodeId1){
- if(!tmp->get("Node1_NoOfAdapters", &conf.nLocalAdapters)) continue;
- if(!tmp->get("Node2_Adapter", 0, &conf.remoteSciNodeId0)) continue;
-
- if(conf.nLocalAdapters > 1){
- if(!tmp->get("Node2_Adapter", 1, &conf.remoteSciNodeId1)) continue;
- }
- } else {
- if(!tmp->get("Node2_NoOfAdapters", &conf.nLocalAdapters)) continue;
- if(!tmp->get("Node1_Adapter", 0, &conf.remoteSciNodeId0)) continue;
-
- if(conf.nLocalAdapters > 1){
- if(!tmp->get("Node1_Adapter", 1, &conf.remoteSciNodeId1)) continue;
- }
- }
-
- if(!theTransporterRegistry->createTransporter(&conf)){
- ndbout << "Failed to create SCI Transporter from: "
- << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
- continue;
- } else {
- noOfTransportersCreated++;
- continue;
- }
- }
-
- if(!tmp->get("HostName1", &host1)) continue;
- if(!tmp->get("HostName2", &host2)) continue;
-
- Uint32 ownNodeId;
- Uint32 remoteNodeId;
- const char * ownHostName;
- const char * remoteHostName;
-
- if(nodeId1 == the_ownId){
- ownNodeId = nodeId1;
- ownHostName = host1;
- remoteNodeId = nodeId2;
- remoteHostName = host2;
- } else if(nodeId2 == the_ownId){
- ownNodeId = nodeId2;
- ownHostName = host2;
- remoteNodeId = nodeId1;
- remoteHostName = host1;
- } else {
- continue;
- }
-
- if(strcmp("TCP", type) == 0){
- TCP_TransporterConfiguration conf;
-
- if(!tmp->get("PortNumber", &conf.port)) continue;
- if(!tmp->get("SendBufferSize", &conf.sendBufferSize)) continue;
- if(!tmp->get("MaxReceiveSize", &conf.maxReceiveSize)) continue;
-
- const char * proxy;
- if (tmp->get("Proxy", &proxy)) {
- if (strlen(proxy) > 0 && nodeId2 == the_ownId) {
- // TODO handle host:port
- conf.port = atoi(proxy);
- }
- }
- conf.sendBufferSize *= MAX_MESSAGE_SIZE;
- conf.maxReceiveSize *= MAX_MESSAGE_SIZE;
-
- conf.remoteHostName = remoteHostName;
- conf.localHostName = ownHostName;
- conf.remoteNodeId = remoteNodeId;
- conf.localNodeId = ownNodeId;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!theTransporterRegistry->createTransporter(&conf)){
- ndbout << "Failed to create TCP Transporter from: "
- << ownNodeId << " to: " << remoteNodeId << endl;
- } else {
- noOfTransportersCreated++;
- }
-
- } else if(strcmp("OSE", type) == 0){
-
- OSE_TransporterConfiguration conf;
-
- if(!tmp->get("PrioASignalSize", &conf.prioASignalSize))
- continue;
- if(!tmp->get("PrioBSignalSize", &conf.prioBSignalSize))
- continue;
- if(!tmp->get("ReceiveArraySize", &conf.receiveBufferSize))
- continue;
-
- conf.remoteHostName = remoteHostName;
- conf.localHostName = ownHostName;
- conf.remoteNodeId = remoteNodeId;
- conf.localNodeId = ownNodeId;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!theTransporterRegistry->createTransporter(&conf)){
- ndbout << "Failed to create OSE Transporter from: "
- << ownNodeId << " to: " << remoteNodeId << endl;
- } else {
- noOfTransportersCreated++;
- }
- } else {
- continue;
- }
- }
- DBUG_RETURN(noOfTransportersCreated);
-}
-
-/**
* Supply a nodeId,
* and get next higher node id
* Returns false if none found
@@ -338,8 +166,39 @@ Uint32
IPCConfig::configureTransporters(Uint32 nodeId,
const class ndb_mgm_configuration & config,
class TransporterRegistry & tr){
+ TransporterConfiguration conf;
+
DBUG_ENTER("IPCConfig::configureTransporters");
+ /**
+ * Iterate over all MGM's an construct a connectstring
+ * create mgm_handle and give it to the Transporter Registry
+ */
+ {
+ const char *separator= "";
+ BaseString connect_string;
+ ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
+ for(iter.first(); iter.valid(); iter.next())
+ {
+ Uint32 type;
+ if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
+ if(type != NODE_TYPE_MGM) continue;
+ const char* hostname;
+ Uint32 port;
+ if(iter.get(CFG_NODE_HOST, &hostname)) continue;
+ if( strlen(hostname) == 0 ) continue;
+ if(iter.get(CFG_MGM_PORT, &port)) continue;
+ connect_string.appfmt("%s%s:%u",separator,hostname,port);
+ separator= ",";
+ }
+ NdbMgmHandle h= ndb_mgm_create_handle();
+ if ( h && connect_string.length() > 0 )
+ {
+ ndb_mgm_set_connectstring(h,connect_string.c_str());
+ tr.set_mgm_handle(h);
+ }
+ }
+
Uint32 noOfTransportersCreated= 0;
ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);
@@ -371,32 +230,66 @@ IPCConfig::configureTransporters(Uint32 nodeId,
Uint32 server_port= 0;
if(iter.get(CFG_CONNECTION_SERVER_PORT, &server_port)) break;
- if (nodeId <= nodeId1 && nodeId <= nodeId2) {
- tr.add_transporter_interface(localHostName, server_port);
+
+ /*
+ We check the node type. MGM node becomes server.
+ */
+ Uint32 node1type, node2type;
+ ndb_mgm_configuration_iterator node1iter(config, CFG_SECTION_NODE);
+ ndb_mgm_configuration_iterator node2iter(config, CFG_SECTION_NODE);
+ node1iter.find(CFG_NODE_ID,nodeId1);
+ node2iter.find(CFG_NODE_ID,nodeId2);
+ node1iter.get(CFG_TYPE_OF_SECTION,&node1type);
+ node2iter.get(CFG_TYPE_OF_SECTION,&node2type);
+
+ conf.serverNodeId= (nodeId1 < nodeId2)? nodeId1:nodeId2;
+
+ conf.isMgmConnection= false;
+ if(node2type==NODE_TYPE_MGM)
+ {
+ conf.isMgmConnection= true;
+ conf.serverNodeId= nodeId2;
}
+ else if(node1type==NODE_TYPE_MGM)
+ {
+ conf.isMgmConnection= true;
+ conf.serverNodeId= nodeId1;
+ }
+ else if (nodeId == conf.serverNodeId) {
+ tr.add_transporter_interface(remoteNodeId, localHostName, server_port);
+ }
+
DBUG_PRINT("info", ("Transporter between this node %d and node %d using port %d, signalId %d, checksum %d",
nodeId, remoteNodeId, server_port, sendSignalId, checksum));
+ /*
+ This may be a dynamic port. It depends on when we're getting
+ our configuration. If we've been restarted, we'll be getting
+ a configuration with our old dynamic port in it, hence the number
+ here is negative (and we try the old port number first).
+
+ On a first-run, server_port will be zero (with dynamic ports)
+
+ If we're not using dynamic ports, we don't do anything.
+ */
+
+ conf.localNodeId = nodeId;
+ conf.remoteNodeId = remoteNodeId;
+ conf.checksum = checksum;
+ conf.signalId = sendSignalId;
+ conf.s_port = server_port;
+ conf.localHostName = localHostName;
+ conf.remoteHostName = remoteHostName;
+
switch(type){
- case CONNECTION_TYPE_SHM:{
- SHM_TransporterConfiguration conf;
- conf.localNodeId = nodeId;
- conf.remoteNodeId = remoteNodeId;
- 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;
- {
- Uint32 tmp;
- if(iter.get(CFG_SHM_SIGNUM, &tmp)) break;
- conf.signum= tmp;
- }
+ case CONNECTION_TYPE_SHM:
+ if(iter.get(CFG_SHM_KEY, &conf.shm.shmKey)) break;
+ if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shm.shmSize)) break;
- conf.port= server_port;
- conf.localHostName = localHostName;
- conf.remoteHostName = remoteHostName;
+ Uint32 tmp;
+ if(iter.get(CFG_SHM_SIGNUM, &tmp)) break;
+ conf.shm.signum= tmp;
- if(!tr.createTransporter(&conf)){
+ if(!tr.createSHMTransporter(&conf)){
DBUG_PRINT("error", ("Failed to create SHM Transporter from %d to %d",
conf.localNodeId, conf.remoteNodeId));
ndbout << "Failed to create SHM Transporter from: "
@@ -404,112 +297,90 @@ IPCConfig::configureTransporters(Uint32 nodeId,
} else {
noOfTransportersCreated++;
}
- DBUG_PRINT("info", ("Created SHM Transporter using shmkey %d, buf size = %d",
- conf.shmKey, conf.shmSize));
+ DBUG_PRINT("info", ("Created SHM Transporter using shmkey %d, "
+ "buf size = %d", conf.shm.shmKey, conf.shm.shmSize));
+
break;
- }
- case CONNECTION_TYPE_SCI:{
- SCI_TransporterConfiguration conf;
- conf.localNodeId = nodeId;
- conf.remoteNodeId = remoteNodeId;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
- conf.port= server_port;
-
- conf.localHostName = localHostName;
- conf.remoteHostName = remoteHostName;
- if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sendLimit)) break;
- if(iter.get(CFG_SCI_BUFFER_MEM, &conf.bufferSize)) break;
+ case CONNECTION_TYPE_SCI:
+ if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sci.sendLimit)) break;
+ if(iter.get(CFG_SCI_BUFFER_MEM, &conf.sci.bufferSize)) break;
if (nodeId == nodeId1) {
- if(iter.get(CFG_SCI_HOST2_ID_0, &conf.remoteSciNodeId0)) break;
- if(iter.get(CFG_SCI_HOST2_ID_1, &conf.remoteSciNodeId1)) break;
+ if(iter.get(CFG_SCI_HOST2_ID_0, &conf.sci.remoteSciNodeId0)) break;
+ if(iter.get(CFG_SCI_HOST2_ID_1, &conf.sci.remoteSciNodeId1)) break;
} else {
- if(iter.get(CFG_SCI_HOST1_ID_0, &conf.remoteSciNodeId0)) break;
- if(iter.get(CFG_SCI_HOST1_ID_1, &conf.remoteSciNodeId1)) break;
+ if(iter.get(CFG_SCI_HOST1_ID_0, &conf.sci.remoteSciNodeId0)) break;
+ if(iter.get(CFG_SCI_HOST1_ID_1, &conf.sci.remoteSciNodeId1)) break;
}
- if (conf.remoteSciNodeId1 == 0) {
- conf.nLocalAdapters = 1;
+ if (conf.sci.remoteSciNodeId1 == 0) {
+ conf.sci.nLocalAdapters = 1;
} else {
- conf.nLocalAdapters = 2;
+ conf.sci.nLocalAdapters = 2;
}
- if(!tr.createTransporter(&conf)){
+ if(!tr.createSCITransporter(&conf)){
DBUG_PRINT("error", ("Failed to create SCI Transporter from %d to %d",
conf.localNodeId, conf.remoteNodeId));
ndbout << "Failed to create SCI Transporter from: "
<< conf.localNodeId << " to: " << conf.remoteNodeId << endl;
} else {
- DBUG_PRINT("info", ("Created SCI Transporter: Adapters = %d, remote SCI node id %d",
- conf.nLocalAdapters, conf.remoteSciNodeId0));
- DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, buf size = %d",
- conf.localHostName, conf.remoteHostName, conf.sendLimit, conf.bufferSize));
- if (conf.nLocalAdapters > 1) {
- DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, second remote SCI node id = %d",
- conf.remoteSciNodeId1));
+ DBUG_PRINT("info", ("Created SCI Transporter: Adapters = %d, "
+ "remote SCI node id %d",
+ conf.sci.nLocalAdapters, conf.sci.remoteSciNodeId0));
+ DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, "
+ "buf size = %d", conf.localHostName,
+ conf.remoteHostName, conf.sci.sendLimit,
+ conf.sci.bufferSize));
+ if (conf.sci.nLocalAdapters > 1) {
+ DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, "
+ "second remote SCI node id = %d",
+ conf.sci.remoteSciNodeId1));
}
noOfTransportersCreated++;
continue;
}
- }
- case CONNECTION_TYPE_TCP:{
- TCP_TransporterConfiguration conf;
-
- if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.sendBufferSize)) break;
- if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.maxReceiveSize)) break;
+ break;
+
+ case CONNECTION_TYPE_TCP:
+ if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.tcp.sendBufferSize)) break;
+ if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.tcp.maxReceiveSize)) break;
- conf.port= server_port;
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.s_port = atoi(proxy);
}
}
- conf.localNodeId = nodeId;
- conf.remoteNodeId = remoteNodeId;
- conf.localHostName = localHostName;
- conf.remoteHostName = remoteHostName;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!tr.createTransporter(&conf)){
+ if(!tr.createTCPTransporter(&conf)){
ndbout << "Failed to create TCP Transporter from: "
<< nodeId << " to: " << remoteNodeId << endl;
} else {
noOfTransportersCreated++;
}
- DBUG_PRINT("info", ("Created TCP Transporter: sendBufferSize = %d, maxReceiveSize = %d",
- conf.sendBufferSize, conf.maxReceiveSize));
+ DBUG_PRINT("info", ("Created TCP Transporter: sendBufferSize = %d, "
+ "maxReceiveSize = %d", conf.tcp.sendBufferSize,
+ conf.tcp.maxReceiveSize));
break;
- case CONNECTION_TYPE_OSE:{
- OSE_TransporterConfiguration conf;
-
- 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 = localHostName;
- conf.remoteHostName = remoteHostName;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
+ case CONNECTION_TYPE_OSE:
+ if(iter.get(CFG_OSE_PRIO_A_SIZE, &conf.ose.prioASignalSize)) break;
+ if(iter.get(CFG_OSE_PRIO_B_SIZE, &conf.ose.prioBSignalSize)) break;
- if(!tr.createTransporter(&conf)){
+ if(!tr.createOSETransporter(&conf)){
ndbout << "Failed to create OSE Transporter from: "
<< nodeId << " to: " << remoteNodeId << endl;
} else {
noOfTransportersCreated++;
}
- }
+ break;
+
default:
ndbout << "Unknown transporter type from: " << nodeId <<
" to: " << remoteNodeId << endl;
break;
- }
- }
- }
+ } // switch
+ } // for
+
DBUG_RETURN(noOfTransportersCreated);
}
diff --git a/ndb/src/common/portlib/NdbTCP.cpp b/ndb/src/common/portlib/NdbTCP.cpp
index c7b9d33c5f6..41471548b7e 100644
--- a/ndb/src/common/portlib/NdbTCP.cpp
+++ b/ndb/src/common/portlib/NdbTCP.cpp
@@ -83,3 +83,50 @@ Ndb_getInAddr(struct in_addr * dst, const char *address) {
return -1;
}
#endif
+
+int Ndb_check_socket_hup(NDB_SOCKET_TYPE sock)
+{
+#ifdef HAVE_POLL
+ struct pollfd pfd[1];
+ int r;
+
+ pfd[0].fd= sock;
+ pfd[0].events= POLLHUP | POLLIN | POLLOUT | POLLNVAL;
+ pfd[0].revents= 0;
+ r= poll(pfd,1,0);
+ if(pfd[0].revents & (POLLHUP|POLLERR))
+ return 1;
+
+ return 0;
+#else /* HAVE_POLL */
+ fd_set readfds, writefds, errorfds;
+ struct timeval tv= {0,0};
+ int s_err;
+ int s_err_size= sizeof(s_err);
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&errorfds);
+
+ FD_SET(sock, &readfds);
+ FD_SET(sock, &writefds);
+ FD_SET(sock, &errorfds);
+
+ if(select(1, &readfds, &writefds, &errorfds, &tv)<0)
+ return 1;
+
+ if(FD_ISSET(sock,&errorfds))
+ return 1;
+
+ s_err=0;
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
+ return(1);
+
+ if (s_err)
+ { /* getsockopt could succeed */
+ return(1); /* but return an error... */
+ }
+
+ return 0;
+#endif /* HAVE_POLL */
+}
diff --git a/ndb/src/common/portlib/gcc.cpp b/ndb/src/common/portlib/gcc.cpp
index 66aa4812dc6..4e49d787d3c 100644
--- a/ndb/src/common/portlib/gcc.cpp
+++ b/ndb/src/common/portlib/gcc.cpp
@@ -2,6 +2,6 @@
/**
* GCC linking problem...
*/
-#ifdef DEFINE_CXA_PURE_VIRTUAL
+#if 0
extern "C" { int __cxa_pure_virtual() { return 0;} }
#endif
diff --git a/ndb/src/common/portlib/win32/NdbTCP.c b/ndb/src/common/portlib/win32/NdbTCP.c
index b936cd2db6c..5d6c0ae5c7d 100644
--- a/ndb/src/common/portlib/win32/NdbTCP.c
+++ b/ndb/src/common/portlib/win32/NdbTCP.c
@@ -37,3 +37,35 @@ Ndb_getInAddr(struct in_addr * dst, const char *address)
return -1;
}
+int Ndb_check_socket_hup(NDB_SOCKET_TYPE sock)
+{
+ fd_set readfds, writefds, errorfds;
+ struct timeval tv= {0,0};
+ int s_err;
+ int s_err_size= sizeof(s_err);
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&errorfds);
+
+ FD_SET(sock, &readfds);
+ FD_SET(sock, &writefds);
+ FD_SET(sock, &errorfds);
+
+ if(select(1, &readfds, &writefds, &errorfds, &tv)==SOCKET_ERROR)
+ return 1;
+
+ if(FD_ISSET(sock,&errorfds))
+ return 1;
+
+ s_err=0;
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
+ return(1);
+
+ if (s_err)
+ { /* getsockopt could succeed */
+ return(1); /* but return an error... */
+ }
+
+ return 0;
+}
diff --git a/ndb/src/common/transporter/Makefile.am b/ndb/src/common/transporter/Makefile.am
index b902012e56d..4c277097a91 100644
--- a/ndb/src/common/transporter/Makefile.am
+++ b/ndb/src/common/transporter/Makefile.am
@@ -13,7 +13,7 @@ EXTRA_libtransporter_la_SOURCES = SHM_Transporter.cpp SHM_Transporter.unix.cpp S
libtransporter_la_LIBADD = @ndb_transporter_opt_objs@
libtransporter_la_DEPENDENCIES = @ndb_transporter_opt_objs@
-INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/include/debugger -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/include/transporter @NDB_SCI_INCLUDES@
+INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/src/mgmapi -I$(top_srcdir)/ndb/include/debugger -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/include/transporter @NDB_SCI_INCLUDES@
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_util.mk.am
diff --git a/ndb/src/common/transporter/OSE_Transporter.cpp b/ndb/src/common/transporter/OSE_Transporter.cpp
index a52862a80e5..ad67791fc0c 100644
--- a/ndb/src/common/transporter/OSE_Transporter.cpp
+++ b/ndb/src/common/transporter/OSE_Transporter.cpp
@@ -32,6 +32,7 @@ OSE_Transporter::OSE_Transporter(int _prioASignalSize,
NodeId localNodeId,
const char * lHostName,
NodeId remoteNodeId,
+ NodeId serverNodeId,
const char * rHostName,
int byteorder,
bool compression,
@@ -40,6 +41,7 @@ OSE_Transporter::OSE_Transporter(int _prioASignalSize,
Uint32 reportFreq) :
Transporter(localNodeId,
remoteNodeId,
+ serverNodeId,
byteorder,
compression,
checksum,
diff --git a/ndb/src/common/transporter/OSE_Transporter.hpp b/ndb/src/common/transporter/OSE_Transporter.hpp
index 4fd06130477..898352366ba 100644
--- a/ndb/src/common/transporter/OSE_Transporter.hpp
+++ b/ndb/src/common/transporter/OSE_Transporter.hpp
@@ -48,6 +48,7 @@ public:
NodeId localNodeId,
const char * lHostName,
NodeId remoteNodeId,
+ NodeId serverNodeId,
const char * rHostName,
int byteorder,
bool compression,
diff --git a/ndb/src/common/transporter/Packer.cpp b/ndb/src/common/transporter/Packer.cpp
index 9eba335330d..bcfac8417bb 100644
--- a/ndb/src/common/transporter/Packer.cpp
+++ b/ndb/src/common/transporter/Packer.cpp
@@ -93,6 +93,7 @@ TransporterRegistry::unpack(Uint32 * readPtr,
signalHeader.theSendersSignalId = * signalData;
signalData ++;
}//if
+ signalHeader.theSignalId= ~0;
Uint32 * sectionPtr = signalData + signalHeader.theLength;
Uint32 * sectionData = sectionPtr + signalHeader.m_noOfSections;
diff --git a/ndb/src/common/transporter/SCI_Transporter.cpp b/ndb/src/common/transporter/SCI_Transporter.cpp
index 47722939098..1fe276249e5 100644
--- a/ndb/src/common/transporter/SCI_Transporter.cpp
+++ b/ndb/src/common/transporter/SCI_Transporter.cpp
@@ -34,19 +34,21 @@ SCI_Transporter::SCI_Transporter(TransporterRegistry &t_reg,
const char *lHostName,
const char *rHostName,
int r_port,
+ bool isMgmConnection,
Uint32 packetSize,
Uint32 bufferSize,
Uint32 nAdapters,
Uint16 remoteSciNodeId0,
Uint16 remoteSciNodeId1,
NodeId _localNodeId,
- NodeId _remoteNodeId,
+ NodeId _remoteNodeId,
+ NodeId serverNodeId,
bool chksm,
bool signalId,
Uint32 reportFreq) :
Transporter(t_reg, tt_SCI_TRANSPORTER,
- lHostName, rHostName, r_port, _localNodeId,
- _remoteNodeId, 0, false, chksm, signalId)
+ lHostName, rHostName, r_port, isMgmConnection, _localNodeId,
+ _remoteNodeId, serverNodeId, 0, false, chksm, signalId)
{
DBUG_ENTER("SCI_Transporter::SCI_Transporter");
m_PacketSize = (packetSize + 3)/4 ;
diff --git a/ndb/src/common/transporter/SCI_Transporter.hpp b/ndb/src/common/transporter/SCI_Transporter.hpp
index e62c142e1b9..cb42e437118 100644
--- a/ndb/src/common/transporter/SCI_Transporter.hpp
+++ b/ndb/src/common/transporter/SCI_Transporter.hpp
@@ -140,13 +140,15 @@ private:
const char *local_host,
const char *remote_host,
int port,
+ bool isMgmConnection,
Uint32 packetSize,
Uint32 bufferSize,
Uint32 nAdapters,
Uint16 remoteSciNodeId0,
Uint16 remoteSciNodeId1,
NodeId localNodeID,
- NodeId remoteNodeID,
+ NodeId remoteNodeID,
+ NodeId serverNodeId,
bool checksum,
bool signalId,
Uint32 reportFreq = 4096);
diff --git a/ndb/src/common/transporter/SHM_Transporter.cpp b/ndb/src/common/transporter/SHM_Transporter.cpp
index 4d7f46d7723..a225988d37f 100644
--- a/ndb/src/common/transporter/SHM_Transporter.cpp
+++ b/ndb/src/common/transporter/SHM_Transporter.cpp
@@ -32,14 +32,17 @@ SHM_Transporter::SHM_Transporter(TransporterRegistry &t_reg,
const char *lHostName,
const char *rHostName,
int r_port,
+ bool isMgmConnection,
NodeId lNodeId,
- NodeId rNodeId,
+ NodeId rNodeId,
+ NodeId serverNodeId,
bool checksum,
bool signalId,
key_t _shmKey,
Uint32 _shmSize) :
Transporter(t_reg, tt_SHM_TRANSPORTER,
- lHostName, rHostName, r_port, lNodeId, rNodeId,
+ lHostName, rHostName, r_port, isMgmConnection,
+ lNodeId, rNodeId, serverNodeId,
0, false, checksum, signalId),
shmKey(_shmKey),
shmSize(_shmSize)
diff --git a/ndb/src/common/transporter/SHM_Transporter.hpp b/ndb/src/common/transporter/SHM_Transporter.hpp
index 7079e12a924..e7a76225471 100644
--- a/ndb/src/common/transporter/SHM_Transporter.hpp
+++ b/ndb/src/common/transporter/SHM_Transporter.hpp
@@ -36,8 +36,10 @@ public:
const char *lHostName,
const char *rHostName,
int r_port,
+ bool isMgmConnection,
NodeId lNodeId,
- NodeId rNodeId,
+ NodeId rNodeId,
+ NodeId serverNodeId,
bool checksum,
bool signalId,
key_t shmKey,
diff --git a/ndb/src/common/transporter/TCP_Transporter.cpp b/ndb/src/common/transporter/TCP_Transporter.cpp
index 5003d90a4b4..5db12d3985c 100644
--- a/ndb/src/common/transporter/TCP_Transporter.cpp
+++ b/ndb/src/common/transporter/TCP_Transporter.cpp
@@ -68,12 +68,15 @@ TCP_Transporter::TCP_Transporter(TransporterRegistry &t_reg,
const char *lHostName,
const char *rHostName,
int r_port,
+ bool isMgmConnection,
NodeId lNodeId,
NodeId rNodeId,
+ NodeId serverNodeId,
bool chksm, bool signalId,
Uint32 _reportFreq) :
Transporter(t_reg, tt_TCP_TRANSPORTER,
- lHostName, rHostName, r_port, lNodeId, rNodeId,
+ lHostName, rHostName, r_port, isMgmConnection,
+ lNodeId, rNodeId, serverNodeId,
0, false, chksm, signalId),
m_sendBuffer(sendBufSize)
{
diff --git a/ndb/src/common/transporter/TCP_Transporter.hpp b/ndb/src/common/transporter/TCP_Transporter.hpp
index 151ec261506..df4149531b4 100644
--- a/ndb/src/common/transporter/TCP_Transporter.hpp
+++ b/ndb/src/common/transporter/TCP_Transporter.hpp
@@ -49,9 +49,11 @@ private:
int sendBufferSize, int maxReceiveSize,
const char *lHostName,
const char *rHostName,
- int r_port,
+ int r_port,
+ bool isMgmConnection,
NodeId lHostId,
NodeId rHostId,
+ NodeId serverNodeId,
bool checksum, bool signalId,
Uint32 reportFreq = 4096);
diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp
index 328ce2816de..377fabe27ab 100644
--- a/ndb/src/common/transporter/Transporter.cpp
+++ b/ndb/src/common/transporter/Transporter.cpp
@@ -31,13 +31,15 @@ Transporter::Transporter(TransporterRegistry &t_reg,
TransporterType _type,
const char *lHostName,
const char *rHostName,
- int r_port,
+ int s_port,
+ bool _isMgmConnection,
NodeId lNodeId,
- NodeId rNodeId,
+ NodeId rNodeId,
+ NodeId serverNodeId,
int _byteorder,
bool _compression, bool _checksum, bool _signalId)
- : m_r_port(r_port), remoteNodeId(rNodeId), localNodeId(lNodeId),
- isServer(lNodeId < rNodeId),
+ : m_s_port(s_port), remoteNodeId(rNodeId), localNodeId(lNodeId),
+ isServer(lNodeId==serverNodeId), isMgmConnection(_isMgmConnection),
m_packer(_signalId, _checksum),
m_type(_type),
m_transporter_registry(t_reg)
@@ -61,10 +63,10 @@ Transporter::Transporter(TransporterRegistry &t_reg,
if (strlen(lHostName) > 0)
Ndb_getInAddr(&localHostAddress, lHostName);
- DBUG_PRINT("info",("rId=%d lId=%d isServer=%d rHost=%s lHost=%s r_port=%d",
+ DBUG_PRINT("info",("rId=%d lId=%d isServer=%d rHost=%s lHost=%s s_port=%d",
remoteNodeId, localNodeId, isServer,
remoteHostName, localHostName,
- r_port));
+ s_port));
byteOrder = _byteorder;
compressionUsed = _compression;
@@ -75,10 +77,13 @@ Transporter::Transporter(TransporterRegistry &t_reg,
m_timeOutMillis = 1000;
m_connect_address.s_addr= 0;
+ if(s_port<0)
+ s_port= -s_port; // was dynamic
+
if (isServer)
m_socket_client= 0;
else
- m_socket_client= new SocketClient(remoteHostName, r_port,
+ m_socket_client= new SocketClient(remoteHostName, s_port,
new SocketAuthSimple("ndbd",
"ndbd passwd"));
DBUG_VOID_RETURN;
@@ -117,22 +122,42 @@ Transporter::connect_server(NDB_SOCKET_TYPE sockfd) {
bool
Transporter::connect_client() {
+ NDB_SOCKET_TYPE sockfd;
+
if(m_connected)
return true;
- NDB_SOCKET_TYPE sockfd = m_socket_client->connect();
-
+
+ if(isMgmConnection)
+ sockfd= m_transporter_registry.connect_ndb_mgmd(m_socket_client);
+ else
+ sockfd= m_socket_client->connect();
+
+ return connect_client(sockfd);
+}
+
+bool
+Transporter::connect_client(NDB_SOCKET_TYPE sockfd) {
+
+ if(m_connected)
+ return true;
+
if (sockfd == NDB_INVALID_SOCKET)
return false;
DBUG_ENTER("Transporter::connect_client");
+ DBUG_PRINT("info",("port %d isMgmConnection=%d",m_s_port,isMgmConnection));
+
+ SocketOutputStream s_output(sockfd);
+ SocketInputStream s_input(sockfd);
+
// send info about own id
// send info about own transporter type
- SocketOutputStream s_output(sockfd);
+
s_output.println("%d %d", localNodeId, m_type);
// get remote id
int nodeId, remote_transporter_type= -1;
- SocketInputStream s_input(sockfd);
+
char buf[256];
if (s_input.gets(buf, 256) == 0) {
NDB_CLOSE_SOCKET(sockfd);
diff --git a/ndb/src/common/transporter/Transporter.hpp b/ndb/src/common/transporter/Transporter.hpp
index 5f3f8063723..c9f4e9bda42 100644
--- a/ndb/src/common/transporter/Transporter.hpp
+++ b/ndb/src/common/transporter/Transporter.hpp
@@ -44,6 +44,7 @@ public:
* Use isConnected() to check status
*/
bool connect_client();
+ bool connect_client(NDB_SOCKET_TYPE sockfd);
bool connect_server(NDB_SOCKET_TYPE socket);
/**
@@ -69,6 +70,22 @@ public:
*/
NodeId getLocalNodeId() const;
+ /**
+ * Get port we're connecting to (signed)
+ */
+ int get_s_port() { return m_s_port; };
+
+ /**
+ * Set port to connect to (signed)
+ */
+ void set_s_port(int port) {
+ m_s_port = port;
+ if(port<0)
+ port= -port;
+ if(m_socket_client)
+ m_socket_client->set_port(port);
+ };
+
virtual Uint32 get_free_buffer() const = 0;
protected:
@@ -76,9 +93,11 @@ protected:
TransporterType,
const char *lHostName,
const char *rHostName,
- int r_port,
+ int s_port,
+ bool isMgmConnection,
NodeId lNodeId,
- NodeId rNodeId,
+ NodeId rNodeId,
+ NodeId serverNodeId,
int byteorder,
bool compression,
bool checksum,
@@ -104,7 +123,7 @@ protected:
struct in_addr remoteHostAddress;
struct in_addr localHostAddress;
- const unsigned int m_r_port;
+ int m_s_port;
const NodeId remoteNodeId;
const NodeId localNodeId;
@@ -121,6 +140,12 @@ protected:
private:
+ /**
+ * means that we transform an MGM connection into
+ * a transporter connection
+ */
+ bool isMgmConnection;
+
SocketClient *m_socket_client;
struct in_addr m_connect_address;
diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp
index 3f190d16264..3937f1fc98b 100644
--- a/ndb/src/common/transporter/TransporterRegistry.cpp
+++ b/ndb/src/common/transporter/TransporterRegistry.cpp
@@ -48,6 +48,10 @@ extern int g_ndb_shm_signum;
#include <InputStream.hpp>
#include <OutputStream.hpp>
+#include <mgmapi/mgmapi.h>
+#include <mgmapi_internal.h>
+#include <mgmapi/mgmapi_debug.h>
+
#include <EventLogger.hpp>
extern EventLogger g_eventLogger;
@@ -83,6 +87,7 @@ TransporterRegistry::TransporterRegistry(void * callback,
nodeIdSpecified = false;
maxTransporters = _maxTransporters;
sendCounter = 1;
+ m_mgm_handle= 0;
callbackObj=callback;
@@ -119,6 +124,27 @@ TransporterRegistry::TransporterRegistry(void * callback,
DBUG_VOID_RETURN;
}
+void TransporterRegistry::set_mgm_handle(NdbMgmHandle h)
+{
+ DBUG_ENTER("TransporterRegistry::set_mgm_handle");
+ if (m_mgm_handle)
+ ndb_mgm_destroy_handle(&m_mgm_handle);
+ m_mgm_handle= h;
+#ifndef DBUG_OFF
+ if (h)
+ {
+ char buf[256];
+ DBUG_PRINT("info",("handle set with connectstring: %s",
+ ndb_mgm_get_connectstring(h,buf, sizeof(buf))));
+ }
+ else
+ {
+ DBUG_PRINT("info",("handle set to NULL"));
+ }
+#endif
+ DBUG_VOID_RETURN;
+}
+
TransporterRegistry::~TransporterRegistry()
{
DBUG_ENTER("TransporterRegistry::~TransporterRegistry");
@@ -141,6 +167,8 @@ TransporterRegistry::~TransporterRegistry()
theOSEReceiver = 0;
}
#endif
+ if (m_mgm_handle)
+ ndb_mgm_destroy_handle(&m_mgm_handle);
DBUG_VOID_RETURN;
}
@@ -258,7 +286,7 @@ TransporterRegistry::connect_server(NDB_SOCKET_TYPE sockfd)
}
bool
-TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) {
+TransporterRegistry::createTCPTransporter(TransporterConfiguration *config) {
#ifdef NDB_TCP_TRANSPORTER
if(!nodeIdSpecified){
@@ -272,13 +300,15 @@ TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) {
return false;
TCP_Transporter * t = new TCP_Transporter(*this,
- config->sendBufferSize,
- config->maxReceiveSize,
+ config->tcp.sendBufferSize,
+ config->tcp.maxReceiveSize,
config->localHostName,
config->remoteHostName,
- config->port,
+ config->s_port,
+ config->isMgmConnection,
localNodeId,
config->remoteNodeId,
+ config->serverNodeId,
config->checksum,
config->signalId);
if (t == NULL)
@@ -307,7 +337,7 @@ TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) {
}
bool
-TransporterRegistry::createTransporter(OSE_TransporterConfiguration *conf) {
+TransporterRegistry::createOSETransporter(TransporterConfiguration *conf) {
#ifdef NDB_OSE_TRANSPORTER
if(!nodeIdSpecified){
@@ -326,11 +356,12 @@ TransporterRegistry::createTransporter(OSE_TransporterConfiguration *conf) {
localNodeId);
}
- OSE_Transporter * t = new OSE_Transporter(conf->prioASignalSize,
- conf->prioBSignalSize,
+ OSE_Transporter * t = new OSE_Transporter(conf->ose.prioASignalSize,
+ conf->ose.prioBSignalSize,
localNodeId,
conf->localHostName,
conf->remoteNodeId,
+ conf->serverNodeId,
conf->remoteHostName,
conf->checksum,
conf->signalId);
@@ -356,7 +387,7 @@ TransporterRegistry::createTransporter(OSE_TransporterConfiguration *conf) {
}
bool
-TransporterRegistry::createTransporter(SCI_TransporterConfiguration *config) {
+TransporterRegistry::createSCITransporter(TransporterConfiguration *config) {
#ifdef NDB_SCI_TRANSPORTER
if(!SCI_Transporter::initSCI())
@@ -375,14 +406,16 @@ TransporterRegistry::createTransporter(SCI_TransporterConfiguration *config) {
SCI_Transporter * t = new SCI_Transporter(*this,
config->localHostName,
config->remoteHostName,
- config->port,
- config->sendLimit,
- config->bufferSize,
- config->nLocalAdapters,
- config->remoteSciNodeId0,
- config->remoteSciNodeId1,
+ config->s_port,
+ config->isMgmConnection,
+ config->sci.sendLimit,
+ config->sci.bufferSize,
+ config->sci.nLocalAdapters,
+ config->sci.remoteSciNodeId0,
+ config->sci.remoteSciNodeId1,
localNodeId,
config->remoteNodeId,
+ config->serverNodeId,
config->checksum,
config->signalId);
@@ -407,7 +440,7 @@ TransporterRegistry::createTransporter(SCI_TransporterConfiguration *config) {
}
bool
-TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
+TransporterRegistry::createSHMTransporter(TransporterConfiguration *config) {
DBUG_ENTER("TransporterRegistry::createTransporter SHM");
#ifdef NDB_SHM_TRANSPORTER
if(!nodeIdSpecified){
@@ -418,7 +451,7 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
return false;
if (!g_ndb_shm_signum) {
- g_ndb_shm_signum= config->signum;
+ g_ndb_shm_signum= config->shm.signum;
DBUG_PRINT("info",("Block signum %d",g_ndb_shm_signum));
/**
* Make sure to block g_ndb_shm_signum
@@ -430,7 +463,7 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
pthread_sigmask(SIG_BLOCK, &mask, 0);
}
- if(config->signum != g_ndb_shm_signum)
+ if(config->shm.signum != g_ndb_shm_signum)
return false;
if(theTransporters[config->remoteNodeId] != NULL)
@@ -439,13 +472,15 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
SHM_Transporter * t = new SHM_Transporter(*this,
config->localHostName,
config->remoteHostName,
- config->port,
+ config->s_port,
+ config->isMgmConnection,
localNodeId,
config->remoteNodeId,
+ config->serverNodeId,
config->checksum,
config->signalId,
- config->shmKey,
- config->shmSize
+ config->shm.shmKey,
+ config->shm.shmSize
);
if (t == NULL)
return false;
@@ -883,6 +918,7 @@ TransporterRegistry::performReceive()
NodeId remoteNodeId;
Uint32 * readPtr;
Uint32 sz = theOSEReceiver->getReceiveData(&remoteNodeId, &readPtr);
+ transporter_recv_from(callbackObj, remoteNodeId);
Uint32 szUsed = unpack(readPtr,
sz,
remoteNodeId,
@@ -918,6 +954,7 @@ TransporterRegistry::performReceive()
{
Uint32 * ptr;
Uint32 sz = t->getReceiveData(&ptr);
+ transporter_recv_from(callbackObj, nodeId);
Uint32 szUsed = unpack(ptr, sz, nodeId, ioStates[nodeId]);
t->updateReceiveDataPtr(szUsed);
}
@@ -941,6 +978,7 @@ TransporterRegistry::performReceive()
{
Uint32 * readPtr, * eodPtr;
t->getReceivePtr(&readPtr, &eodPtr);
+ transporter_recv_from(callbackObj, nodeId);
Uint32 *newPtr = unpack(readPtr, eodPtr, nodeId, ioStates[nodeId]);
t->updateReceivePtr(newPtr);
}
@@ -958,6 +996,7 @@ TransporterRegistry::performReceive()
{
Uint32 * readPtr, * eodPtr;
t->getReceivePtr(&readPtr, &eodPtr);
+ transporter_recv_from(callbackObj, nodeId);
Uint32 *newPtr = unpack(readPtr, eodPtr, nodeId, ioStates[nodeId]);
t->updateReceivePtr(newPtr);
}
@@ -1149,7 +1188,10 @@ TransporterRegistry::do_connect(NodeId node_id)
case DISCONNECTING:
break;
}
+ DBUG_ENTER("TransporterRegistry::do_connect");
+ DBUG_PRINT("info",("performStates[%d]=CONNECTING",node_id));
curr_state= CONNECTING;
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::do_disconnect(NodeId node_id)
@@ -1165,21 +1207,30 @@ TransporterRegistry::do_disconnect(NodeId node_id)
case DISCONNECTING:
return;
}
+ DBUG_ENTER("TransporterRegistry::do_disconnect");
+ DBUG_PRINT("info",("performStates[%d]=DISCONNECTING",node_id));
curr_state= DISCONNECTING;
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::report_connect(NodeId node_id)
{
+ DBUG_ENTER("TransporterRegistry::report_connect");
+ DBUG_PRINT("info",("performStates[%d]=CONNECTED",node_id));
performStates[node_id] = CONNECTED;
reportConnect(callbackObj, node_id);
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::report_disconnect(NodeId node_id, int errnum)
{
+ DBUG_ENTER("TransporterRegistry::report_disconnect");
+ DBUG_PRINT("info",("performStates[%d]=DISCONNECTED",node_id));
performStates[node_id] = DISCONNECTED;
reportDisconnect(callbackObj, node_id, errnum);
+ DBUG_VOID_RETURN;
}
void
@@ -1224,8 +1275,67 @@ TransporterRegistry::start_clients_thread()
const NodeId nodeId = t->getRemoteNodeId();
switch(performStates[nodeId]){
case CONNECTING:
- if(!t->isConnected() && !t->isServer)
- t->connect_client();
+ if(!t->isConnected() && !t->isServer) {
+ bool connected= false;
+ /**
+ * First, we try to connect (if we have a port number).
+ */
+ if (t->get_s_port())
+ connected= t->connect_client();
+
+ /**
+ * If dynamic, get the port for connecting from the management server
+ */
+ if( !connected && t->get_s_port() <= 0) { // Port is dynamic
+ int server_port= 0;
+ struct ndb_mgm_reply mgm_reply;
+
+ if(!ndb_mgm_is_connected(m_mgm_handle))
+ ndb_mgm_connect(m_mgm_handle, 0, 0, 0);
+
+ if(ndb_mgm_is_connected(m_mgm_handle))
+ {
+ int res=
+ ndb_mgm_get_connection_int_parameter(m_mgm_handle,
+ t->getRemoteNodeId(),
+ t->getLocalNodeId(),
+ CFG_CONNECTION_SERVER_PORT,
+ &server_port,
+ &mgm_reply);
+ DBUG_PRINT("info",("Got dynamic port %d for %d -> %d (ret: %d)",
+ server_port,t->getRemoteNodeId(),
+ t->getLocalNodeId(),res));
+ if( res >= 0 )
+ {
+ /**
+ * Server_port == 0 just means that that a mgmt server
+ * has not received a new port yet. Keep the old.
+ */
+ if (server_port)
+ t->set_s_port(server_port);
+ }
+ else if(ndb_mgm_is_connected(m_mgm_handle))
+ {
+ ndbout_c("Failed to get dynamic port to connect to: %d", res);
+ ndb_mgm_disconnect(m_mgm_handle);
+ }
+ else
+ {
+ ndbout_c("Management server closed connection early. "
+ "It is probably being shut down (or has crashed). "
+ "We will retry the connection.");
+ }
+ }
+ /** else
+ * We will not be able to get a new port unless
+ * the m_mgm_handle is connected. Note that not
+ * being connected is an ok state, just continue
+ * until it is able to connect. Continue using the
+ * old port until we can connect again and get a
+ * new port.
+ */
+ }
+ }
break;
case DISCONNECTING:
if(t->isConnected())
@@ -1261,24 +1371,26 @@ TransporterRegistry::stop_clients()
if (m_start_clients_thread) {
m_run_start_clients_thread= false;
void* status;
- int r= NdbThread_WaitFor(m_start_clients_thread, &status);
+ NdbThread_WaitFor(m_start_clients_thread, &status);
NdbThread_Destroy(&m_start_clients_thread);
}
return true;
}
void
-TransporterRegistry::add_transporter_interface(const char *interf, unsigned short port)
+TransporterRegistry::add_transporter_interface(NodeId remoteNodeId,
+ const char *interf,
+ int s_port)
{
DBUG_ENTER("TransporterRegistry::add_transporter_interface");
- DBUG_PRINT("enter",("interface=%s, port= %d", interf, port));
+ DBUG_PRINT("enter",("interface=%s, s_port= %d", interf, s_port));
if (interf && strlen(interf) == 0)
interf= 0;
for (unsigned i= 0; i < m_transporter_interface.size(); i++)
{
Transporter_interface &tmp= m_transporter_interface[i];
- if (port != tmp.m_service_port)
+ if (s_port != tmp.m_s_service_port || tmp.m_s_service_port==0)
continue;
if (interf != 0 && tmp.m_interface != 0 &&
strcmp(interf, tmp.m_interface) == 0)
@@ -1291,7 +1403,8 @@ TransporterRegistry::add_transporter_interface(const char *interf, unsigned shor
}
}
Transporter_interface t;
- t.m_service_port= port;
+ t.m_remote_nodeId= remoteNodeId;
+ t.m_s_service_port= s_port;
t.m_interface= interf;
m_transporter_interface.push_back(t);
DBUG_PRINT("exit",("interface and port added"));
@@ -1301,34 +1414,50 @@ TransporterRegistry::add_transporter_interface(const char *interf, unsigned shor
bool
TransporterRegistry::start_service(SocketServer& socket_server)
{
+ struct ndb_mgm_reply mgm_reply;
+
+ DBUG_ENTER("TransporterRegistry::start_service");
if (m_transporter_interface.size() > 0 && !nodeIdSpecified)
{
ndbout_c("TransporterRegistry::startReceiving: localNodeId not specified");
- return false;
+ DBUG_RETURN(false);
}
for (unsigned i= 0; i < m_transporter_interface.size(); i++)
{
Transporter_interface &t= m_transporter_interface[i];
- if (t.m_service_port == 0)
- {
- continue;
- }
+
+ unsigned short port= (unsigned short)t.m_s_service_port;
+ if(t.m_s_service_port<0)
+ port= -t.m_s_service_port; // is a dynamic port
TransporterService *transporter_service =
new TransporterService(new SocketAuthSimple("ndbd", "ndbd passwd"));
if(!socket_server.setup(transporter_service,
- t.m_service_port, t.m_interface))
+ &port, t.m_interface))
{
- ndbout_c("Unable to setup transporter service port: %s:%d!\n"
- "Please check if the port is already used,\n"
- "(perhaps the node is already running)",
- t.m_interface ? t.m_interface : "*", t.m_service_port);
- delete transporter_service;
- return false;
+ DBUG_PRINT("info", ("Trying new port"));
+ port= 0;
+ if(t.m_s_service_port>0
+ || !socket_server.setup(transporter_service,
+ &port, t.m_interface))
+ {
+ /*
+ * If it wasn't a dynamically allocated port, or
+ * our attempts at getting a new dynamic port failed
+ */
+ ndbout_c("Unable to setup transporter service port: %s:%d!\n"
+ "Please check if the port is already used,\n"
+ "(perhaps the node is already running)",
+ t.m_interface ? t.m_interface : "*", t.m_s_service_port);
+ delete transporter_service;
+ DBUG_RETURN(false);
+ }
}
+ t.m_s_service_port= (t.m_s_service_port<=0)?-port:port; // -`ve if dynamic
+ DBUG_PRINT("info", ("t.m_s_service_port = %d",t.m_s_service_port));
transporter_service->setTransporterRegistry(this);
}
- return true;
+ DBUG_RETURN(true);
}
#ifdef NDB_SHM_TRANSPORTER
@@ -1380,12 +1509,7 @@ TransporterRegistry::startReceiving()
DBUG_PRINT("error",("Install failed"));
g_eventLogger.error("Failed to install signal handler for"
" SHM transporter errno: %d (%s)", errno,
-#ifdef HAVE_STRERROR
- strerror(errno)
-#else
- ""
-#endif
- );
+ strerror(errno));
}
}
#endif // NDB_SHM_TRANSPORTER
@@ -1443,4 +1567,107 @@ NdbOut & operator <<(NdbOut & out, SignalHeader & sh){
return out;
}
+Transporter*
+TransporterRegistry::get_transporter(NodeId nodeId) {
+ return theTransporters[nodeId];
+}
+
+bool TransporterRegistry::connect_client(NdbMgmHandle *h)
+{
+ DBUG_ENTER("TransporterRegistry::connect_client(NdbMgmHandle)");
+
+ Uint32 mgm_nodeid= ndb_mgm_get_mgmd_nodeid(*h);
+
+ if(!mgm_nodeid)
+ {
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ return false;
+ }
+ Transporter * t = theTransporters[mgm_nodeid];
+ if (!t)
+ {
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ return false;
+ }
+ DBUG_RETURN(t->connect_client(connect_ndb_mgmd(h)));
+}
+
+/**
+ * Given a connected NdbMgmHandle, turns it into a transporter
+ * and returns the socket.
+ */
+NDB_SOCKET_TYPE TransporterRegistry::connect_ndb_mgmd(NdbMgmHandle *h)
+{
+ struct ndb_mgm_reply mgm_reply;
+
+ if ( h==NULL || *h == NULL )
+ {
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ return NDB_INVALID_SOCKET;
+ }
+
+ for(unsigned int i=0;i < m_transporter_interface.size();i++)
+ if (m_transporter_interface[i].m_s_service_port < 0
+ && ndb_mgm_set_connection_int_parameter(*h,
+ get_localNodeId(),
+ m_transporter_interface[i].m_remote_nodeId,
+ CFG_CONNECTION_SERVER_PORT,
+ m_transporter_interface[i].m_s_service_port,
+ &mgm_reply) < 0)
+ {
+ ndbout_c("Error: %s: %d",
+ ndb_mgm_get_latest_error_desc(*h),
+ ndb_mgm_get_latest_error(*h));
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ ndb_mgm_destroy_handle(h);
+ return NDB_INVALID_SOCKET;
+ }
+
+ /**
+ * convert_to_transporter also disposes of the handle (i.e. we don't leak
+ * memory here.
+ */
+ NDB_SOCKET_TYPE sockfd= ndb_mgm_convert_to_transporter(h);
+ if ( sockfd == NDB_INVALID_SOCKET)
+ {
+ ndbout_c("Error: %s: %d",
+ ndb_mgm_get_latest_error_desc(*h),
+ ndb_mgm_get_latest_error(*h));
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ ndb_mgm_destroy_handle(h);
+ }
+ return sockfd;
+}
+
+/**
+ * Given a SocketClient, creates a NdbMgmHandle, turns it into a transporter
+ * and returns the socket.
+ */
+NDB_SOCKET_TYPE TransporterRegistry::connect_ndb_mgmd(SocketClient *sc)
+{
+ NdbMgmHandle h= ndb_mgm_create_handle();
+
+ if ( h == NULL )
+ {
+ return NDB_INVALID_SOCKET;
+ }
+
+ /**
+ * Set connectstring
+ */
+ {
+ BaseString cs;
+ cs.assfmt("%s:%u",sc->get_server_name(),sc->get_port());
+ ndb_mgm_set_connectstring(h, cs.c_str());
+ }
+
+ if(ndb_mgm_connect(h, 0, 0, 0)<0)
+ {
+ ndb_mgm_destroy_handle(&h);
+ return NDB_INVALID_SOCKET;
+ }
+
+ return connect_ndb_mgmd(&h);
+}
+
template class Vector<TransporterRegistry::Transporter_interface>;
diff --git a/ndb/src/common/util/Base64.cpp b/ndb/src/common/util/Base64.cpp
index f7a490d427d..3db911f481f 100644
--- a/ndb/src/common/util/Base64.cpp
+++ b/ndb/src/common/util/Base64.cpp
@@ -22,17 +22,22 @@ static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789+/";
int
-base64_encode(const UtilBuffer &src, BaseString &dst) {
- const unsigned char *s = (const unsigned char *)src.get_data();
+base64_encode(const UtilBuffer &src, BaseString &dst)
+{
+ return base64_encode(src.get_data(), src.length(), dst);
+}
+
+int
+base64_encode(const void * _s, size_t src_len, BaseString &dst) {
+ const unsigned char * s = (const unsigned char*)_s;
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');
}
-
+
unsigned c;
c = s[i++];
c <<= 8;
diff --git a/ndb/src/common/util/Bitmask.cpp b/ndb/src/common/util/Bitmask.cpp
new file mode 100644
index 00000000000..0aa39a37204
--- /dev/null
+++ b/ndb/src/common/util/Bitmask.cpp
@@ -0,0 +1,351 @@
+#include <Bitmask.hpp>
+#include <NdbOut.hpp>
+
+static
+void print(const Uint32 src[], Uint32 len, Uint32 pos = 0)
+{
+ printf("b'");
+ for(unsigned i = 0; i<len; i++)
+ {
+ if(BitmaskImpl::get((pos + len + 31) >> 5, src, i+pos))
+ printf("1");
+ else
+ printf("0");
+ if((i & 31) == 31)
+ printf(" ");
+ }
+}
+
+#ifndef __TEST_BITMASK__
+
+void
+BitmaskImpl::getFieldImpl(const Uint32 src[],
+ unsigned shiftL, unsigned len, Uint32 dst[])
+{
+ assert(shiftL < 32);
+
+ unsigned shiftR = 32 - shiftL;
+ unsigned undefined = shiftL ? ~0 : 0;
+
+ * dst = shiftL ? * dst : 0;
+
+ while(len >= 32)
+ {
+ * dst++ |= (* src) << shiftL;
+ * dst = ((* src++) >> shiftR) & undefined;
+ len -= 32;
+ }
+
+ if(len < shiftR)
+ {
+ * dst |= ((* src) & ((1 << len) - 1)) << shiftL;
+ }
+ else
+ {
+ * dst++ |= ((* src) << shiftL);
+ * dst = ((* src) >> shiftR) & ((1 << (len - shiftR)) - 1) & undefined;
+ }
+}
+
+void
+BitmaskImpl::setFieldImpl(Uint32 dst[],
+ unsigned shiftL, unsigned len, const Uint32 src[])
+{
+ /**
+ *
+ * abcd ef00
+ * 00ab cdef
+ */
+ assert(shiftL < 32);
+ unsigned shiftR = 32 - shiftL;
+ unsigned undefined = shiftL ? ~0 : 0;
+ while(len >= 32)
+ {
+ * dst = (* src++) >> shiftL;
+ * dst++ |= ((* src) << shiftR) & undefined;
+ len -= 32;
+ }
+
+ Uint32 mask = ((1 << len) -1);
+ * dst = (* dst & ~mask);
+ if(len < shiftR)
+ {
+ * dst |= ((* src++) >> shiftL) & mask;
+ }
+ else
+ {
+ * dst |= ((* src++) >> shiftL);
+ * dst |= ((* src) & ((1 << (len - shiftR)) - 1)) << shiftR ;
+ }
+}
+#else
+
+#define DEBUG 0
+#include <Vector.hpp>
+static void do_test(int bitmask_size);
+
+int
+main(int argc, char** argv)
+{
+ int loops = argc > 1 ? atoi(argv[1]) : 1000;
+ int max_size = argc > 2 ? atoi(argv[2]) : 1000;
+
+
+ for(int i = 0; i<loops; i++)
+ do_test(1 + (rand() % max_size));
+}
+
+struct Alloc
+{
+ Uint32 pos;
+ Uint32 size;
+ Vector<Uint32> data;
+};
+
+static void require(bool b)
+{
+ if(!b) abort();
+}
+
+static
+bool cmp(const Uint32 b1[], const Uint32 b2[], Uint32 len)
+{
+ Uint32 sz32 = (len + 31) >> 5;
+ for(int i = 0; i<len; i++)
+ {
+ if(BitmaskImpl::get(sz32, b1, i) ^ BitmaskImpl::get(sz32, b2, i))
+ return false;
+ }
+ return true;
+}
+
+
+static int val_pos = 0;
+static int val[] = { 384, 241, 32,
+ 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0,
+ 241 };
+
+static int lrand()
+{
+#if 0
+ return val[val_pos++];
+#else
+ return rand();
+#endif
+}
+
+static
+void rand(Uint32 dst[], Uint32 len)
+{
+ for(int i = 0; i<len; i++)
+ BitmaskImpl::set((len + 31) >> 5, dst, i, (lrand() % 1000) > 500);
+}
+
+static
+void simple(int pos, int size)
+{
+ ndbout_c("simple pos: %d size: %d", pos, size);
+ Vector<Uint32> _mask;
+ Vector<Uint32> _src;
+ Vector<Uint32> _dst;
+ Uint32 sz32 = (size + pos + 32) >> 5;
+ const Uint32 sz = 4 * sz32;
+
+ Uint32 zero = 0;
+ _mask.fill(sz32+1, zero);
+ _src.fill(sz32+1, zero);
+ _dst.fill(sz32+1, zero);
+
+ Uint32 * src = _src.getBase();
+ Uint32 * dst = _dst.getBase();
+ Uint32 * mask = _mask.getBase();
+
+ memset(src, 0x0, sz);
+ memset(dst, 0x0, sz);
+ memset(mask, 0xFF, sz);
+ rand(src, size);
+ BitmaskImpl::setField(sz32, mask, pos, size, src);
+ BitmaskImpl::getField(sz32, mask, pos, size, dst);
+ printf("src: "); print(src, size+31); printf("\n");
+ printf("msk: "); print(mask, (sz32 << 5) + 31); printf("\n");
+ printf("dst: "); print(dst, size+31); printf("\n");
+ require(cmp(src, dst, size+31));
+};
+
+static
+void simple2(int size, int loops)
+{
+ ndbout_c("simple2 %d - ", size);
+ Vector<Uint32> _mask;
+ Vector<Uint32> _src;
+ Vector<Uint32> _dst;
+
+ Uint32 sz32 = (size + 32) >> 5;
+ Uint32 sz = sz32 << 2;
+
+ Uint32 zero = 0;
+ _mask.fill(sz32+1, zero);
+ _src.fill(sz32+1, zero);
+ _dst.fill(sz32+1, zero);
+
+ Uint32 * src = _src.getBase();
+ Uint32 * dst = _dst.getBase();
+ Uint32 * mask = _mask.getBase();
+
+ Vector<Uint32> save;
+ for(int i = 0; i<loops; i++)
+ {
+ memset(mask, 0xFF, sz);
+ memset(dst, 0xFF, sz);
+ int len;
+ int pos = 0;
+ while(pos+1 < size)
+ {
+ memset(src, 0xFF, sz);
+ while(!(len = rand() % (size - pos)));
+ BitmaskImpl::setField(sz32, mask, pos, len, src);
+ if(memcmp(dst, mask, sz))
+ {
+ ndbout_c("pos: %d len: %d", pos, len);
+ print(mask, size);
+ abort();
+ }
+ printf("[ %d %d ]", pos, len);
+ save.push_back(pos);
+ save.push_back(len);
+ pos += len;
+ }
+
+ for(int j = 0; j<save.size(); )
+ {
+ pos = save[j++];
+ len = save[j++];
+ memset(src, 0xFF, sz);
+ BitmaskImpl::getField(sz32, mask, pos, len, src);
+ if(memcmp(dst, src, sz))
+ {
+ ndbout_c("pos: %d len: %d", pos, len);
+ printf("src: "); print(src, size); printf("\n");
+ printf("dst: "); print(dst, size); printf("\n");
+ printf("msk: "); print(mask, size); printf("\n");
+ abort();
+ }
+ }
+ ndbout_c("");
+ }
+}
+
+static void
+do_test(int bitmask_size)
+{
+#if 1
+ simple(rand() % 33, (rand() % 63)+1);
+//#else
+ Vector<Alloc> alloc_list;
+ bitmask_size = (bitmask_size + 31) & ~31;
+ Uint32 sz32 = (bitmask_size >> 5);
+ Vector<Uint32> alloc_mask;
+ Vector<Uint32> test_mask;
+
+ ndbout_c("Testing bitmask of size %d", bitmask_size);
+ Uint32 zero = 0;
+ alloc_mask.fill(sz32, zero);
+ test_mask.fill(sz32, zero);
+
+ for(int i = 0; i<5000; i++)
+ {
+ Vector<Uint32> tmp;
+ tmp.fill(sz32, zero);
+
+ int pos = lrand() % (bitmask_size - 1);
+ int free = 0;
+ if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos))
+ {
+ // Bit was allocated
+ // 1) Look up allocation
+ // 2) Check data
+ // 3) free it
+ size_t j;
+ int min, max;
+ for(j = 0; j<alloc_list.size(); j++)
+ {
+ min = alloc_list[j].pos;
+ max = min + alloc_list[j].size;
+ if(pos >= min && pos < max)
+ {
+ break;
+ }
+ }
+ require(pos >= min && pos < max);
+ BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min,
+ tmp.getBase());
+ if(DEBUG)
+ {
+ printf("freeing [ %d %d ]", min, max);
+ printf("- mask: ");
+ print(tmp.getBase(), max - min);
+
+ printf(" save: ");
+ size_t k;
+ Alloc& a = alloc_list[j];
+ for(k = 0; k<a.data.size(); k++)
+ printf("%.8x ", a.data[k]);
+ printf("\n");
+ }
+ int bytes = (max - min + 7) >> 3;
+ if(!cmp(tmp.getBase(), alloc_list[j].data.getBase(), max - min))
+ {
+ abort();
+ }
+ while(min < max)
+ BitmaskImpl::clear(sz32, alloc_mask.getBase(), min++);
+ alloc_list.erase(j);
+ }
+ else
+ {
+ Vector<Uint32> tmp;
+ tmp.fill(sz32, zero);
+
+ // Bit was free
+ // 1) Check how much space is avaiable
+ // 2) Create new allocation of lrandom size
+ // 3) Fill data with lrandom data
+ // 4) Update alloc mask
+ while(pos+free < bitmask_size &&
+ !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free))
+ free++;
+
+ Uint32 sz =
+ (free <= 64 && ((lrand() % 100) > 80)) ? free : (lrand() % free);
+ sz = sz ? sz : 1;
+ sz = pos + sz == bitmask_size ? sz - 1 : sz;
+ Alloc a;
+ a.pos = pos;
+ a.size = sz;
+ a.data.fill(((sz+31)>> 5)-1, zero);
+ if(DEBUG)
+ printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz);
+ for(size_t j = 0; j<sz; j++)
+ {
+ BitmaskImpl::set(sz32, alloc_mask.getBase(), pos+j);
+ if((lrand() % 1000) > 500)
+ BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j);
+ }
+ if(DEBUG)
+ {
+ printf("- mask: ");
+ print(a.data.getBase(), sz);
+ printf("\n");
+ }
+ BitmaskImpl::setField(sz32, test_mask.getBase(), pos, sz,
+ a.data.getBase());
+ alloc_list.push_back(a);
+ }
+ }
+#endif
+}
+
+template class Vector<Alloc>;
+template class Vector<Uint32>;
+
+#endif
diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am
index a62c8186174..2719d14ee92 100644
--- a/ndb/src/common/util/Makefile.am
+++ b/ndb/src/common/util/Makefile.am
@@ -9,7 +9,24 @@ libgeneral_la_SOURCES = \
NdbSqlUtil.cpp new.cpp \
uucode.c random.c version.c \
strdup.c \
- ConfigValues.cpp ndb_init.c basestring_vsnprintf.c
+ ConfigValues.cpp ndb_init.c basestring_vsnprintf.c \
+ Bitmask.cpp
+
+EXTRA_PROGRAMS = testBitmask
+testBitmask_SOURCES = testBitmask.cpp
+testBitmask_LDFLAGS = @ndb_bin_am_ldflags@ \
+ $(top_builddir)/ndb/src/libndbclient.la \
+ $(top_builddir)/dbug/libdbug.a \
+ $(top_builddir)/mysys/libmysys.a \
+ $(top_builddir)/strings/libmystrings.a
+
+testBitmask.cpp : Bitmask.cpp
+ rm -f testBitmask.cpp
+ @LN_CP_F@ Bitmask.cpp testBitmask.cpp
+
+testBitmask.o: $(testBitmask_SOURCES)
+ $(CXXCOMPILE) -c $(INCLUDES) -D__TEST_BITMASK__ $<
+
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_util.mk.am
diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp
index c4114ad5ffa..09e150dbacf 100644
--- a/ndb/src/common/util/NdbSqlUtil.cpp
+++ b/ndb/src/common/util/NdbSqlUtil.cpp
@@ -15,182 +15,169 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <NdbSqlUtil.hpp>
+#include <NdbOut.hpp>
+#include <my_sys.h>
-int
-NdbSqlUtil::char_compare(const char* s1, unsigned n1,
- const char* s2, unsigned n2, bool padded)
-{
- int c1 = 0;
- int c2 = 0;
- unsigned i = 0;
- while (i < n1 || i < n2) {
- c1 = i < n1 ? s1[i] : padded ? 0x20 : 0;
- c2 = i < n2 ? s2[i] : padded ? 0x20 : 0;
- if (c1 != c2)
- break;
- i++;
- }
- return c1 - c2;
-}
-
-bool
-NdbSqlUtil::char_like(const char* s1, unsigned n1,
- const char* s2, unsigned n2, bool padded)
-{
- int c1 = 0;
- int c2 = 0;
- unsigned i1 = 0;
- unsigned i2 = 0;
- while (i1 < n1 || i2 < n2) {
- c1 = i1 < n1 ? s1[i1] : padded ? 0x20 : 0;
- c2 = i2 < n2 ? s2[i2] : padded ? 0x20 : 0;
- if (c2 == '%') {
- while (i2 + 1 < n2 && s2[i2 + 1] == '%') {
- i2++;
- }
- unsigned m = 0;
- while (m <= n1 - i1) {
- if (char_like(s1 + i1 + m, n1 -i1 - m,
- s2 + i2 + 1, n2 - i2 - 1, padded))
- return true;
- m++;
- }
- return false;
- }
- if (c2 == '_') {
- if (c1 == 0)
- return false;
- } else {
- if (c1 != c2)
- return false;
- }
- i1++;
- i2++;
- }
- return i1 == n2 && i2 == n2;
-}
-
-/**
- * Data types.
+/*
+ * Data types. The entries must be in the numerical order.
*/
const NdbSqlUtil::Type
NdbSqlUtil::m_typeList[] = {
{ // 0
Type::Undefined,
+ NULL,
NULL
},
{ // 1
Type::Tinyint,
- cmpTinyint
+ cmpTinyint,
+ NULL
},
{ // 2
Type::Tinyunsigned,
- cmpTinyunsigned
+ cmpTinyunsigned,
+ NULL
},
{ // 3
Type::Smallint,
- cmpSmallint
+ cmpSmallint,
+ NULL
},
{ // 4
Type::Smallunsigned,
- cmpSmallunsigned
+ cmpSmallunsigned,
+ NULL
},
{ // 5
Type::Mediumint,
- cmpMediumint
+ cmpMediumint,
+ NULL
},
{ // 6
Type::Mediumunsigned,
- cmpMediumunsigned
+ cmpMediumunsigned,
+ NULL
},
{ // 7
Type::Int,
- cmpInt
+ cmpInt,
+ NULL
},
{ // 8
Type::Unsigned,
- cmpUnsigned
+ cmpUnsigned,
+ NULL
},
{ // 9
Type::Bigint,
- cmpBigint
+ cmpBigint,
+ NULL
},
{ // 10
Type::Bigunsigned,
- cmpBigunsigned
+ cmpBigunsigned,
+ NULL
},
{ // 11
Type::Float,
- cmpFloat
+ cmpFloat,
+ NULL
},
{ // 12
Type::Double,
- cmpDouble
+ cmpDouble,
+ NULL
},
{ // 13
Type::Olddecimal,
- cmpOlddecimal
+ cmpOlddecimal,
+ NULL
},
{ // 14
Type::Char,
- cmpChar
+ cmpChar,
+ likeChar
},
{ // 15
Type::Varchar,
- cmpVarchar
+ cmpVarchar,
+ likeVarchar
},
{ // 16
Type::Binary,
- cmpBinary
+ cmpBinary,
+ likeBinary
},
{ // 17
Type::Varbinary,
- cmpVarbinary
+ cmpVarbinary,
+ likeVarbinary
},
{ // 18
Type::Datetime,
- cmpDatetime
+ cmpDatetime,
+ NULL
},
{ // 19
Type::Date,
- cmpDate
+ cmpDate,
+ NULL
},
{ // 20
Type::Blob,
- cmpBlob
+ NULL,
+ NULL
},
{ // 21
Type::Text,
- cmpText
+ NULL,
+ NULL
},
{ // 22
- Type::Undefined, // 5.0 Bit
+ Type::Bit,
+ NULL,
NULL
},
{ // 23
- Type::Undefined, // 5.0 Longvarchar
- NULL
+ Type::Longvarchar,
+ cmpLongvarchar,
+ likeLongvarchar
},
{ // 24
- Type::Undefined, // 5.0 Longvarbinary
- NULL
+ Type::Longvarbinary,
+ cmpLongvarbinary,
+ likeLongvarbinary
},
{ // 25
Type::Time,
- cmpTime
+ cmpTime,
+ NULL
},
{ // 26
Type::Year,
- cmpYear
+ cmpYear,
+ NULL
},
{ // 27
Type::Timestamp,
- cmpTimestamp
+ cmpTimestamp,
+ NULL
},
{ // 28
Type::Olddecimalunsigned,
- cmpOlddecimalunsigned
+ cmpOlddecimalunsigned,
+ NULL
+ },
+ { // 29
+ Type::Decimal,
+ cmpDecimal,
+ NULL
+ },
+ { // 30
+ Type::Decimalunsigned,
+ cmpDecimalunsigned,
+ NULL
}
};
@@ -209,10 +196,12 @@ NdbSqlUtil::getTypeBinary(Uint32 typeId)
{
switch (typeId) {
case Type::Char:
- typeId = Type::Binary;
- break;
case Type::Varchar:
- typeId = Type::Varbinary;
+ case Type::Binary:
+ case Type::Varbinary:
+ case Type::Longvarchar:
+ case Type::Longvarbinary:
+ typeId = Type::Binary;
break;
case Type::Text:
typeId = Type::Blob;
@@ -223,194 +212,211 @@ NdbSqlUtil::getTypeBinary(Uint32 typeId)
return getType(typeId);
}
-// compare
+/*
+ * Comparison functions.
+ */
int
-NdbSqlUtil::cmpTinyint(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpTinyint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Int8 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Int8)) {
+ Int8 v1, v2;
+ memcpy(&v1, p1, sizeof(Int8));
+ memcpy(&v2, p2, sizeof(Int8));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpTinyunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpTinyunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Uint8 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint8)) {
+ Uint8 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint8));
+ memcpy(&v2, p2, sizeof(Uint8));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpSmallint(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpSmallint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Int16 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Int16)) {
+ Int16 v1, v2;
+ memcpy(&v1, p1, sizeof(Int16));
+ memcpy(&v2, p2, sizeof(Int16));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpSmallunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpSmallunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Uint16 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint16)) {
+ Uint16 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint16));
+ memcpy(&v2, p2, sizeof(Uint16));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpMediumint(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpMediumint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- Int32 v1 = sint3korr(u1.v);
- Int32 v2 = sint3korr(u2.v);
- if (v1 < v2)
- return -1;
- if (v1 > v2)
- return +1;
- return 0;
+ if (n2 >= 3) {
+ Int32 v1, v2;
+ v1 = sint3korr((const uchar*)p1);
+ v2 = sint3korr((const uchar*)p2);
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpMediumunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpMediumunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- Uint32 v1 = uint3korr(u1.v);
- Uint32 v2 = uint3korr(u2.v);
- if (v1 < v2)
- return -1;
- if (v1 > v2)
- return +1;
- return 0;
+ if (n2 >= 3) {
+ Uint32 v1, v2;
+ v1 = uint3korr((const uchar*)p1);
+ v2 = uint3korr((const uchar*)p2);
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpInt(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpInt(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Int32 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Int32)) {
+ Int32 v1, v2;
+ memcpy(&v1, p1, sizeof(Int32));
+ memcpy(&v2, p2, sizeof(Int32));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpUnsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpUnsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Uint32 v; } u1, u2;
- u1.v = p1[0];
- u2.v = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint32)) {
+ Uint32 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint32));
+ memcpy(&v2, p2, sizeof(Uint32));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpBigint(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpBigint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (size >= 2) {
- union { Uint32 p[2]; Int64 v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
+ if (n2 >= sizeof(Int64)) {
+ Int64 v1, v2;
+ memcpy(&v1, p1, sizeof(Int64));
+ memcpy(&v2, p2, sizeof(Int64));
+ if (v1 < v2)
return -1;
- if (u1.v > u2.v)
+ if (v1 > v2)
return +1;
return 0;
}
+ assert(! full);
return CmpUnknown;
}
int
-NdbSqlUtil::cmpBigunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpBigunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (size >= 2) {
- union { Uint32 p[2]; Uint64 v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
+ if (n2 >= sizeof(Uint64)) {
+ Uint64 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint64));
+ memcpy(&v2, p2, sizeof(Uint64));
+ if (v1 < v2)
return -1;
- if (u1.v > u2.v)
+ if (v1 > v2)
return +1;
return 0;
}
+ assert(! full);
return CmpUnknown;
}
int
-NdbSqlUtil::cmpFloat(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpFloat(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; float v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- // no format check
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(float)) {
+ float v1, v2;
+ memcpy(&v1, p1, sizeof(float));
+ memcpy(&v2, p2, sizeof(float));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpDouble(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpDouble(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (size >= 2) {
- union { Uint32 p[2]; double v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- // no format check
- if (u1.v < u2.v)
+ if (n2 >= sizeof(double)) {
+ double v1, v2;
+ memcpy(&v1, p1, sizeof(double));
+ memcpy(&v2, p2, sizeof(double));
+ if (v1 < v2)
return -1;
- if (u1.v > u2.v)
+ if (v1 > v2)
return +1;
return 0;
}
+ assert(! full);
return CmpUnknown;
}
@@ -440,266 +446,428 @@ NdbSqlUtil::cmp_olddecimal(const uchar* s1, const uchar* s2, unsigned n)
}
int
-NdbSqlUtil::cmpOlddecimal(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpOlddecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (full == size) {
- union { const Uint32* p; const uchar* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- return cmp_olddecimal(u1.v, u2.v, full << 2);
+ if (full) {
+ assert(n1 == n2);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ return cmp_olddecimal(v1, v2, n1);
}
return CmpUnknown;
}
int
-NdbSqlUtil::cmpOlddecimalunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpOlddecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (full == size) {
- union { const Uint32* p; const uchar* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- return cmp_olddecimal(u1.v, u2.v, full << 2);
+ if (full) {
+ assert(n1 == n2);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ return cmp_olddecimal(v1, v2, n1);
}
return CmpUnknown;
}
int
-NdbSqlUtil::cmpChar(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpDecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // compare as binary strings
+ unsigned n = (n1 <= n2 ? n1 : n2);
+ int k = memcmp(v1, v2, n);
+ if (k == 0) {
+ k = (full ? n1 : n) - n2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
+}
+
+int
+NdbSqlUtil::cmpDecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // compare as binary strings
+ unsigned n = (n1 <= n2 ? n1 : n2);
+ int k = memcmp(v1, v2, n);
+ if (k == 0) {
+ k = (full ? n1 : n) - n2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
+}
+
+int
+NdbSqlUtil::cmpChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
// collation does not work on prefix for some charsets
- assert(full == size && size > 0);
- /*
- * Char is blank-padded to length and null-padded to word size.
- */
- union { const Uint32* p; const uchar* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
+ assert(full);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
// not const in MySQL
CHARSET_INFO* cs = (CHARSET_INFO*)(info);
- // length in bytes including null padding to Uint32
- uint l1 = (full << 2);
- int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1);
+ // compare with space padding
+ int k = (*cs->coll->strnncollsp)(cs, v1, n1, v2, n2, false);
return k < 0 ? -1 : k > 0 ? +1 : 0;
}
int
-NdbSqlUtil::cmpVarchar(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- /*
- * Varchar is not allowed to contain a null byte and the value is
- * null-padded. Therefore comparison does not need to use the length.
- *
- * Not used before MySQL 5.0. Format is likely to change. Handle
- * only binary collation for now.
- */
- union { const Uint32* p; const char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- // skip length in first 2 bytes
- int k = strncmp(u1.v + 2, u2.v + 2, (size << 2) - 2);
- return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+ const unsigned lb = 1;
+ // collation does not work on prefix for some charsets
+ assert(full && n1 >= lb && n2 >= lb);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = *v1;
+ unsigned m2 = *v2;
+ if (m1 <= n1 - lb && m2 <= n2 - lb) {
+ CHARSET_INFO* cs = (CHARSET_INFO*)(info);
+ // compare with space padding
+ int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
+ return k < 0 ? -1 : k > 0 ? +1 : 0;
+ }
+ // treat bad data as NULL
+ if (m1 > n1 - lb && m2 <= n2 - lb)
+ return -1;
+ if (m1 <= n1 - lb && m2 > n2 - lb)
+ return +1;
+ return 0;
}
int
-NdbSqlUtil::cmpBinary(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
-{
- assert(full >= size && size > 0);
- /*
- * Binary data of full length. Compare bytewise.
- */
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- int k = memcmp(u1.v, u2.v, size << 2);
- return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+NdbSqlUtil::cmpBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // compare as binary strings
+ unsigned n = (n1 <= n2 ? n1 : n2);
+ int k = memcmp(v1, v2, n);
+ if (k == 0) {
+ k = (full ? n1 : n) - n2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
}
int
-NdbSqlUtil::cmpVarbinary(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
-{
- assert(full >= size && size > 0);
- /*
- * Binary data of variable length padded with nulls. The comparison
- * does not need to use the length.
- *
- * Not used before MySQL 5.0. Format is likely to change.
- */
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- // skip length in first 2 bytes
- int k = memcmp(u1.v + 2, u2.v + 2, (size << 2) - 2);
- return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+NdbSqlUtil::cmpVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const unsigned lb = 1;
+ if (n2 >= lb) {
+ assert(n1 >= lb);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = *v1;
+ unsigned m2 = *v2;
+ if (m1 <= n1 - lb && m2 <= n2 - lb) {
+ // compare as binary strings
+ unsigned m = (m1 <= m2 ? m1 : m2);
+ int k = memcmp(v1 + lb, v2 + lb, m);
+ if (k == 0) {
+ k = (full ? m1 : m) - m2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
+ }
+ // treat bad data as NULL
+ if (m1 > n1 - lb && m2 <= n2 - lb)
+ return -1;
+ if (m1 <= n1 - lb && m2 > n2 - lb)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpDatetime(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpDatetime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (size >= 2) {
- union { Uint32 p[2]; Int64 v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
+ if (n2 >= sizeof(Int64)) {
+ Int64 v1, v2;
+ memcpy(&v1, p1, sizeof(Int64));
+ memcpy(&v2, p2, sizeof(Int64));
+ if (v1 < v2)
return -1;
- if (u1.v > u2.v)
+ if (v1 > v2)
return +1;
return 0;
}
+ assert(! full);
return CmpUnknown;
}
int
-NdbSqlUtil::cmpDate(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
#ifdef ndb_date_is_4_byte_native_int
- assert(full >= size && size > 0);
- union { Uint32 p[2]; Int32 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Int32)) {
+ Int32 v1, v2;
+ memcpy(&v1, p1, sizeof(Int32));
+ memcpy(&v2, p2, sizeof(Int32));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
#else
- assert(full >= size && size > 0);
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
#ifdef ndb_date_sol9x86_cc_xO3_madness
- // from Field_newdate::val_int
- Uint64 j1 = uint3korr(u1.v);
- Uint64 j2 = uint3korr(u2.v);
- j1 = (j1 % 32L)+(j1 / 32L % 16L)*100L + (j1/(16L*32L))*10000L;
- j2 = (j2 % 32L)+(j2 / 32L % 16L)*100L + (j2/(16L*32L))*10000L;
- if (j1 < j2)
- return -1;
- if (j1 > j2)
- return +1;
- return 0;
+ if (n2 >= 3) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // from Field_newdate::val_int
+ Uint64 j1 = uint3korr(v1);
+ Uint64 j2 = uint3korr(v2);
+ j1 = (j1 % 32L)+(j1 / 32L % 16L)*100L + (j1/(16L*32L))*10000L;
+ j2 = (j2 % 32L)+(j2 / 32L % 16L)*100L + (j2/(16L*32L))*10000L;
+ if (j1 < j2)
+ return -1;
+ if (j1 > j2)
+ return +1;
+ return 0;
+ }
#else
- uint j1 = uint3korr(u1.v);
- uint j2 = uint3korr(u2.v);
- uint d1 = (j1 & 31);
- uint d2 = (j2 & 31);
- j1 = (j1 >> 5);
- j2 = (j2 >> 5);
- uint m1 = (j1 & 15);
- uint m2 = (j2 & 15);
- j1 = (j1 >> 4);
- j2 = (j2 >> 4);
- uint y1 = j1;
- uint y2 = j2;
- if (y1 < y2)
- return -1;
- if (y1 > y2)
- return +1;
- if (m1 < m2)
- return -1;
- if (m1 > m2)
- return +1;
- if (d1 < d2)
- return -1;
- if (d1 > d2)
- return +1;
- return 0;
+ if (n2 >= 3) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ uint j1 = uint3korr(v1);
+ uint j2 = uint3korr(v2);
+ uint d1 = (j1 & 31);
+ uint d2 = (j2 & 31);
+ j1 = (j1 >> 5);
+ j2 = (j2 >> 5);
+ uint m1 = (j1 & 15);
+ uint m2 = (j2 & 15);
+ j1 = (j1 >> 4);
+ j2 = (j2 >> 4);
+ uint y1 = j1;
+ uint y2 = j2;
+ if (y1 < y2)
+ return -1;
+ if (y1 > y2)
+ return +1;
+ if (m1 < m2)
+ return -1;
+ if (m1 > m2)
+ return +1;
+ if (d1 < d2)
+ return -1;
+ if (d1 > d2)
+ return +1;
+ return 0;
+ }
#endif
#endif
+ assert(! full);
+ return CmpUnknown;
}
+// not supported
int
-NdbSqlUtil::cmpBlob(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpBlob(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- /*
- * Blob comparison is on the inline bytes (null padded).
- */
- const unsigned head = NDB_BLOB_HEAD_SIZE;
- // skip blob head
- if (size >= head + 1) {
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1 + head;
- u2.p = p2 + head;
- int k = memcmp(u1.v, u2.v, (size - head) << 2);
- return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+ assert(false);
+ return 0;
+}
+
+// not supported
+int
+NdbSqlUtil::cmpText(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ assert(false);
+ return 0;
+}
+
+int
+NdbSqlUtil::cmpTime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ if (n2 >= 3) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // from Field_time::val_int
+ Int32 j1 = sint3korr(v1);
+ Int32 j2 = sint3korr(v2);
+ if (j1 < j2)
+ return -1;
+ if (j1 > j2)
+ return +1;
+ return 0;
}
+ assert(! full);
return CmpUnknown;
}
+// not yet
+int
+NdbSqlUtil::cmpBit(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ assert(false);
+ return 0;
+}
+
int
-NdbSqlUtil::cmpText(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
+ const unsigned lb = 2;
// collation does not work on prefix for some charsets
- assert(full == size && size > 0);
- /*
- * Text comparison is on the inline bytes (blank padded). Currently
- * not supported for multi-byte charsets.
- */
- const unsigned head = NDB_BLOB_HEAD_SIZE;
- // skip blob head
- if (size >= head + 1) {
- union { const Uint32* p; const uchar* v; } u1, u2;
- u1.p = p1 + head;
- u2.p = p2 + head;
- // not const in MySQL
+ assert(full && n1 >= lb && n2 >= lb);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = uint2korr(v1);
+ unsigned m2 = uint2korr(v2);
+ if (m1 <= n1 - lb && m2 <= n2 - lb) {
CHARSET_INFO* cs = (CHARSET_INFO*)(info);
- // length in bytes including null padding to Uint32
- uint l1 = (full << 2);
- int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1);
+ // compare with space padding
+ int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
return k < 0 ? -1 : k > 0 ? +1 : 0;
}
+ // treat bad data as NULL
+ if (m1 > n1 - lb && m2 <= n2 - lb)
+ return -1;
+ if (m1 <= n1 - lb && m2 > n2 - lb)
+ return +1;
+ return 0;
+}
+
+int
+NdbSqlUtil::cmpLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const unsigned lb = 2;
+ if (n2 >= lb) {
+ assert(n1 >= lb);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = uint2korr(v1);
+ unsigned m2 = uint2korr(v2);
+ if (m1 <= n1 - lb && m2 <= n2 - lb) {
+ // compare as binary strings
+ unsigned m = (m1 <= m2 ? m1 : m2);
+ int k = memcmp(v1 + lb, v2 + lb, m);
+ if (k == 0) {
+ k = (full ? m1 : m) - m2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
+ }
+ // treat bad data as NULL
+ if (m1 > n1 - lb && m2 <= n2 - lb)
+ return -1;
+ if (m1 <= n1 - lb && m2 > n2 - lb)
+ return +1;
+ return 0;
+ }
+ assert(! full);
return CmpUnknown;
}
int
-NdbSqlUtil::cmpTime(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpYear(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- // from Field_time::val_int
- Int32 j1 = sint3korr(u1.v);
- Int32 j2 = sint3korr(u2.v);
- if (j1 < j2)
- return -1;
- if (j1 > j2)
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint8)) {
+ Uint8 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint8));
+ memcpy(&v2, p2, sizeof(Uint8));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpYear(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpTimestamp(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- if (u1.v[0] < u2.v[0])
- return -1;
- if (u1.v[0] > u2.v[0])
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint32)) {
+ Uint32 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint32));
+ memcpy(&v2, p2, sizeof(Uint32));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
+// like
+
+static const int ndb_wild_prefix = '\\';
+static const int ndb_wild_one = '_';
+static const int ndb_wild_many = '%';
+
int
-NdbSqlUtil::cmpTimestamp(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::likeChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Uint32 v; } u1, u2;
- u1.v = p1[0];
- u2.v = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ const char* v1 = (const char*)p1;
+ const char* v2 = (const char*)p2;
+ CHARSET_INFO* cs = (CHARSET_INFO*)(info);
+ int k = (cs->coll->wildcmp)(cs, v1, v1 + n1, v2, v2 + n2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
+ return k == 0 ? 0 : +1;
+}
+
+int
+NdbSqlUtil::likeBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ assert(info == 0);
+ return likeChar(&my_charset_bin, p1, n1, p2, n2);
+}
+
+int
+NdbSqlUtil::likeVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ const unsigned lb = 1;
+ if (n1 >= lb && n2 >= lb) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = *v1;
+ unsigned m2 = *v2;
+ if (lb + m1 <= n1 && lb + m2 <= n2) {
+ const char* w1 = (const char*)v1 + lb;
+ const char* w2 = (const char*)v2 + lb;
+ CHARSET_INFO* cs = (CHARSET_INFO*)(info);
+ int k = (cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
+ return k == 0 ? 0 : +1;
+ }
+ }
+ return -1;
+}
+
+int
+NdbSqlUtil::likeVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ assert(info == 0);
+ return likeVarchar(&my_charset_bin, p1, n1, p2, n2);
+}
+
+int
+NdbSqlUtil::likeLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ const unsigned lb = 2;
+ if (n1 >= lb && n2 >= lb) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = uint2korr(v1);
+ unsigned m2 = uint2korr(v2);
+ if (lb + m1 <= n1 && lb + m2 <= n2) {
+ const char* w1 = (const char*)v1 + lb;
+ const char* w2 = (const char*)v2 + lb;
+ CHARSET_INFO* cs = (CHARSET_INFO*)(info);
+ int k = (cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
+ return k == 0 ? 0 : +1;
+ }
+ }
+ return -1;
+}
+
+int
+NdbSqlUtil::likeLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ assert(info == 0);
+ return likeLongvarchar(&my_charset_bin, p1, n1, p2, n2);
}
// check charset
@@ -709,9 +877,9 @@ NdbSqlUtil::usable_in_pk(Uint32 typeId, const void* info)
{
const Type& type = getType(typeId);
switch (type.m_typeId) {
- case Type::Undefined:
- break;
case Type::Char:
+ case Type::Varchar:
+ case Type::Longvarchar:
{
const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
return
@@ -719,13 +887,13 @@ NdbSqlUtil::usable_in_pk(Uint32 typeId, const void* info)
cs->cset != 0 &&
cs->coll != 0 &&
cs->coll->strnxfrm != 0 &&
- cs->strxfrm_multiply <= 1; // current limitation
+ cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY;
}
break;
- case Type::Varchar:
- return true; // Varchar not used via MySQL
+ case Type::Undefined:
case Type::Blob:
case Type::Text:
+ case Type::Bit:
break;
default:
return true;
@@ -743,10 +911,12 @@ bool
NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info)
{
const Type& type = getType(typeId);
+ if (type.m_cmp == NULL)
+ return false;
switch (type.m_typeId) {
- case Type::Undefined:
- break;
case Type::Char:
+ case Type::Varchar:
+ case Type::Longvarchar:
{
const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
return
@@ -755,23 +925,13 @@ NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info)
cs->coll != 0 &&
cs->coll->strnxfrm != 0 &&
cs->coll->strnncollsp != 0 &&
- cs->strxfrm_multiply <= 1; // current limitation
+ cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY;
}
break;
- case Type::Varchar:
- return true; // Varchar not used via MySQL
+ case Type::Undefined:
+ case Type::Blob:
case Type::Text:
- {
- const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
- return
- cs != 0 &&
- cs->mbmaxlen == 1 && // extra limitation
- cs->cset != 0 &&
- cs->coll != 0 &&
- cs->coll->strnxfrm != 0 &&
- cs->coll->strnncollsp != 0 &&
- cs->strxfrm_multiply <= 1; // current limitation
- }
+ case Type::Bit: // can be fixed
break;
default:
return true;
@@ -779,68 +939,69 @@ NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info)
return false;
}
-#ifdef NDB_SQL_UTIL_TEST
-
-#include <NdbTick.h>
-#include <NdbOut.hpp>
+// utilities
-struct Testcase {
- int op; // 1=compare 2=like
- int res;
- const char* s1;
- const char* s2;
- int pad;
-};
-const Testcase testcase[] = {
- { 2, 1, "abc", "abc", 0 },
- { 2, 1, "abc", "abc%", 0 },
- { 2, 1, "abcdef", "abc%", 0 },
- { 2, 1, "abcdefabcdefabcdef", "abc%", 0 },
- { 2, 1, "abcdefabcdefabcdef", "abc%f", 0 },
- { 2, 0, "abcdefabcdefabcdef", "abc%z", 0 },
- { 2, 1, "abcdefabcdefabcdef", "%f", 0 },
- { 2, 1, "abcdef", "a%b%c%d%e%f", 0 },
- { 0, 0, 0, 0 }
-};
-
-int
-main(int argc, char** argv)
-{
- ndb_init(); // for charsets
- unsigned count = argc > 1 ? atoi(argv[1]) : 1000000;
- ndbout_c("count = %u", count);
- assert(count != 0);
- for (const Testcase* t = testcase; t->s1 != 0; t++) {
- ndbout_c("%d = '%s' %s '%s' pad=%d",
- t->res, t->s1, t->op == 1 ? "comp" : "like", t->s2);
- NDB_TICKS x1 = NdbTick_CurrentMillisecond();
- unsigned n1 = strlen(t->s1);
- unsigned n2 = strlen(t->s2);
- for (unsigned i = 0; i < count; i++) {
- if (t->op == 1) {
- int res = NdbSqlUtil::char_compare(t->s1, n1, t->s2, n2, t->pad);
- assert(res == t->res);
- continue;
- }
- if (t->op == 2) {
- int res = NdbSqlUtil::char_like(t->s1, n1, t->s2, n2, t->pad);
- assert(res == t->res);
- continue;
- }
- assert(false);
+bool
+NdbSqlUtil::get_var_length(Uint32 typeId, const void* p, unsigned attrlen, Uint32& lb, Uint32& len)
+{
+ const unsigned char* const src = (const unsigned char*)p;
+ switch (typeId) {
+ case NdbSqlUtil::Type::Varchar:
+ case NdbSqlUtil::Type::Varbinary:
+ lb = 1;
+ if (attrlen >= lb) {
+ len = src[0];
+ if (attrlen >= lb + len)
+ return true;
}
- NDB_TICKS x2 = NdbTick_CurrentMillisecond();
- if (x2 < x1)
- x2 = x1;
- double usec = 1000000.0 * double(x2 - x1) / double(count);
- ndbout_c("time %.0f usec per call", usec);
- }
- // quick check
- for (unsigned i = 0; i < sizeof(m_typeList) / sizeof(m_typeList[0]); i++) {
- const NdbSqlUtil::Type& t = m_typeList[i];
- assert(t.m_typeId == i);
+ break;
+ case NdbSqlUtil::Type::Longvarchar:
+ case NdbSqlUtil::Type::Longvarbinary:
+ lb = 2;
+ if (attrlen >= lb) {
+ len = src[0] + (src[1] << 8);
+ if (attrlen >= lb + len)
+ return true;
+ }
+ break;
+ default:
+ lb = 0;
+ len = attrlen;
+ return true;
+ break;
}
- return 0;
+ return false;
}
+// workaround
+
+int
+NdbSqlUtil::strnxfrm_bug7284(CHARSET_INFO* cs, unsigned char* dst, unsigned dstLen, const unsigned char*src, unsigned srcLen)
+{
+ unsigned char nsp[20]; // native space char
+ unsigned char xsp[20]; // strxfrm-ed space char
+#ifdef VM_TRACE
+ memset(nsp, 0x1f, sizeof(nsp));
+ memset(xsp, 0x1f, sizeof(xsp));
#endif
+ // convert from unicode codepoint for space
+ int n1 = (*cs->cset->wc_mb)(cs, (my_wc_t)0x20, nsp, nsp + sizeof(nsp));
+ if (n1 <= 0)
+ return -1;
+ // strxfrm to binary
+ int n2 = (*cs->coll->strnxfrm)(cs, xsp, sizeof(xsp), nsp, n1);
+ if (n2 <= 0)
+ return -1;
+ // XXX bug workaround - strnxfrm may not write full string
+ memset(dst, 0x0, dstLen);
+ // strxfrm argument string - returns no error indication
+ int n3 = (*cs->coll->strnxfrm)(cs, dst, dstLen, src, srcLen);
+ // pad with strxfrm-ed space chars
+ int n4 = n3;
+ while (n4 < (int)dstLen) {
+ dst[n4] = xsp[(n4 - n3) % n2];
+ n4++;
+ }
+ // no check for partial last
+ return dstLen;
+}
diff --git a/ndb/src/common/util/SimpleProperties.cpp b/ndb/src/common/util/SimpleProperties.cpp
index 00c440fcb4e..c25aaea491a 100644
--- a/ndb/src/common/util/SimpleProperties.cpp
+++ b/ndb/src/common/util/SimpleProperties.cpp
@@ -37,6 +37,28 @@ SimpleProperties::Writer::add(Uint16 key, Uint32 value){
}
bool
+SimpleProperties::Writer::add(const char * value, int len){
+ const Uint32 valLen = (len + 3) / 4;
+
+ if ((len % 4) == 0)
+ return putWords((Uint32*)value, valLen);
+
+ const Uint32 putLen= valLen - 1;
+ if (!putWords((Uint32*)value, putLen))
+ return false;
+
+ // Special handling of last bytes
+ union {
+ Uint32 lastWord;
+ char lastBytes[4];
+ };
+ memcpy(lastBytes,
+ value + putLen*4,
+ len - putLen*4);
+ return putWord(lastWord);
+}
+
+bool
SimpleProperties::Writer::add(Uint16 key, const char * value){
Uint32 head = StringValue;
head <<= 16;
@@ -46,9 +68,9 @@ SimpleProperties::Writer::add(Uint16 key, const char * value){
Uint32 strLen = strlen(value) + 1; // Including NULL-byte
if(!putWord(htonl(strLen)))
return false;
-
- const Uint32 valLen = (strLen + 3) / 4;
- return putWords((Uint32*)value, valLen);
+
+ return add(value, (int)strLen);
+
}
bool
@@ -60,9 +82,8 @@ SimpleProperties::Writer::add(Uint16 key, const void* value, int len){
return false;
if(!putWord(htonl(len)))
return false;
-
- const Uint32 valLen = (len + 3) / 4;
- return putWords((Uint32*)value, valLen);
+
+ return add((const char*)value, len);
}
SimpleProperties::Reader::Reader(){
@@ -392,6 +413,7 @@ UtilBufferWriter::putWords(const Uint32 * src, Uint32 len){
return (m_buf.append(src, 4 * len) == 0);
}
+
Uint32
UtilBufferWriter::getWordsUsed() const { return m_buf.length() / 4;}
diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp
index db5c03f925a..15dca2d96b1 100644
--- a/ndb/src/common/util/SocketServer.cpp
+++ b/ndb/src/common/util/SocketServer.cpp
@@ -84,15 +84,15 @@ SocketServer::tryBind(unsigned short port, const char * intface) {
bool
SocketServer::setup(SocketServer::Service * service,
- unsigned short port,
+ unsigned short * port,
const char * intface){
DBUG_ENTER("SocketServer::setup");
- DBUG_PRINT("enter",("interface=%s, port=%d", intface, port));
+ DBUG_PRINT("enter",("interface=%s, port=%u", intface, *port));
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(port);
+ servaddr.sin_port = htons(*port);
if(intface != 0){
if(Ndb_getInAddr(&servaddr.sin_addr, intface))
@@ -123,7 +123,17 @@ SocketServer::setup(SocketServer::Service * service,
NDB_CLOSE_SOCKET(sock);
DBUG_RETURN(false);
}
-
+
+ /* Get the port we bound to */
+ SOCKET_SIZE_TYPE sock_len = sizeof(servaddr);
+ if(getsockname(sock,(struct sockaddr*)&servaddr,&sock_len)<0) {
+ ndbout_c("An error occurred while trying to find out what"
+ " port we bound to. Error: %s",strerror(errno));
+ NDB_CLOSE_SOCKET(sock);
+ DBUG_RETURN(false);
+ }
+
+ DBUG_PRINT("info",("bound to %u",ntohs(servaddr.sin_port)));
if (listen(sock, m_maxSessions) == -1){
DBUG_PRINT("error",("listen() - %d - %s",
errno, strerror(errno)));
@@ -135,6 +145,9 @@ SocketServer::setup(SocketServer::Service * service,
i.m_socket = sock;
i.m_service = service;
m_services.push_back(i);
+
+ *port = ntohs(servaddr.sin_port);
+
DBUG_RETURN(true);
}
@@ -314,11 +327,18 @@ sessionThread_C(void* _sc){
return 0;
}
- if(!si->m_stop){
- si->m_stopped = false;
- si->runSession();
- } else {
- NDB_CLOSE_SOCKET(si->m_socket);
+ /**
+ * may have m_stopped set if we're transforming a mgm
+ * connection into a transporter connection.
+ */
+ if(!si->m_stopped)
+ {
+ if(!si->m_stop){
+ si->m_stopped = false;
+ si->runSession();
+ } else {
+ NDB_CLOSE_SOCKET(si->m_socket);
+ }
}
si->m_stopped = true;
diff --git a/ndb/src/common/util/md5_hash.cpp b/ndb/src/common/util/md5_hash.cpp
index 068843183ac..d4eedbc40fb 100644
--- a/ndb/src/common/util/md5_hash.cpp
+++ b/ndb/src/common/util/md5_hash.cpp
@@ -75,7 +75,7 @@ void byteReverse(unsigned char *buf, unsigned longs)
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
-void MD5Transform(Uint32 buf[4], Uint32 const in[16])
+static void MD5Transform(Uint32 buf[4], Uint32 const in[16])
{
register Uint32 a, b, c, d;
@@ -162,13 +162,13 @@ void MD5Transform(Uint32 buf[4], Uint32 const in[16])
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
-Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
+void md5_hash(Uint32 result[4], const Uint64* keybuf, Uint32 no_of_32_words)
{
-/*
- * This is the external interface of the module
- * It is assumed that keybuf is placed on 8 byte
- * alignment.
- */
+ /**
+ * This is the external interface of the module
+ * It is assumed that keybuf is placed on 8 byte
+ * alignment.
+ */
Uint32 i;
Uint32 buf[4];
Uint64 transform64_buf[8];
@@ -230,6 +230,10 @@ Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
byteReverse((unsigned char *)transform32_buf, 16);
MD5Transform(buf, transform32_buf);
}
- return buf[0];
+
+ result[0] = buf[0];
+ result[1] = buf[1];
+ result[2] = buf[2];
+ result[3] = buf[3];
}
diff --git a/ndb/src/common/util/new.cpp b/ndb/src/common/util/new.cpp
index 901f74bf979..643800f1582 100644
--- a/ndb/src/common/util/new.cpp
+++ b/ndb/src/common/util/new.cpp
@@ -6,7 +6,7 @@ extern "C" {
void (* ndb_new_handler)() = 0;
}
-#ifdef USE_MYSYS_NEW
+#if 0
void *operator new (size_t sz)
{
diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c
index 51cf8082a62..8076db576c2 100644
--- a/ndb/src/common/util/version.c
+++ b/ndb/src/common/util/version.c
@@ -92,6 +92,8 @@ void ndbSetOwnVersion() {}
#ifndef TEST_VERSION
struct NdbUpGradeCompatible ndbCompatibleTable_full[] = {
+ { MAKE_VERSION(5,0,NDB_VERSION_BUILD), MAKE_VERSION(5,0,12), UG_Range},
+ { MAKE_VERSION(5,0,11), MAKE_VERSION(5,0,2), UG_Range},
{ MAKE_VERSION(4,1,NDB_VERSION_BUILD), MAKE_VERSION(4,1,15), UG_Range },
{ MAKE_VERSION(4,1,14), MAKE_VERSION(4,1,10), UG_Range },
{ MAKE_VERSION(4,1,10), MAKE_VERSION(4,1,9), UG_Exact },
@@ -101,6 +103,8 @@ struct NdbUpGradeCompatible ndbCompatibleTable_full[] = {
};
struct NdbUpGradeCompatible ndbCompatibleTable_upgrade[] = {
+ { MAKE_VERSION(5,0,12), MAKE_VERSION(5,0,11), UG_Exact },
+ { MAKE_VERSION(5,0,2), MAKE_VERSION(4,1,8), UG_Exact },
{ MAKE_VERSION(4,1,15), MAKE_VERSION(4,1,14), UG_Exact },
{ MAKE_VERSION(3,5,4), MAKE_VERSION(3,5,3), UG_Exact },
{ 0, 0, UG_Null }
diff --git a/ndb/src/cw/cpcd/APIService.cpp b/ndb/src/cw/cpcd/APIService.cpp
index b009f0c0fc4..e7a2092c15d 100644
--- a/ndb/src/cw/cpcd/APIService.cpp
+++ b/ndb/src/cw/cpcd/APIService.cpp
@@ -136,6 +136,8 @@ ParserRow<CPCDAPISession> commands[] =
CPCD_ARG("id", Int, Mandatory, "Id of process"),
CPCD_CMD("list processes", &CPCDAPISession::listProcesses, ""),
+
+ CPCD_CMD("show version", &CPCDAPISession::showVersion, ""),
CPCD_END()
};
@@ -359,6 +361,7 @@ CPCDAPISession::listProcesses(Parser_t::Context & /* unused */,
m_output->println("stdout: %s", p->m_stdout.c_str());
m_output->println("stderr: %s", p->m_stderr.c_str());
m_output->println("ulimit: %s", p->m_ulimit.c_str());
+ m_output->println("shutdown: %s", p->m_shutdown_options.c_str());
switch(p->m_status){
case STOPPED:
m_output->println("status: stopped");
@@ -384,4 +387,16 @@ CPCDAPISession::listProcesses(Parser_t::Context & /* unused */,
m_cpcd.m_processes.unlock();
}
+void
+CPCDAPISession::showVersion(Parser_t::Context & /* unused */,
+ const class Properties & args){
+ Uint32 id;
+ CPCD::RequestStatus rs;
+
+ m_output->println("show version");
+ m_output->println("compile time: %s %s", __DATE__, __TIME__);
+
+ m_output->println("");
+}
+
template class Vector<ParserRow<CPCDAPISession> const*>;
diff --git a/ndb/src/cw/cpcd/APIService.hpp b/ndb/src/cw/cpcd/APIService.hpp
index ef988785f89..3586d64187e 100644
--- a/ndb/src/cw/cpcd/APIService.hpp
+++ b/ndb/src/cw/cpcd/APIService.hpp
@@ -49,6 +49,7 @@ public:
void stopProcess(Parser_t::Context & ctx, const class Properties & args);
void showProcess(Parser_t::Context & ctx, const class Properties & args);
void listProcesses(Parser_t::Context & ctx, const class Properties & args);
+ void showVersion(Parser_t::Context & ctx, const class Properties & args);
};
class CPCDAPIService : public SocketServer::Service {
diff --git a/ndb/src/cw/cpcd/main.cpp b/ndb/src/cw/cpcd/main.cpp
index ba877095a04..c320f07ef04 100644
--- a/ndb/src/cw/cpcd/main.cpp
+++ b/ndb/src/cw/cpcd/main.cpp
@@ -138,7 +138,8 @@ int main(int argc, char** argv){
SocketServer * ss = new SocketServer();
CPCDAPIService * serv = new CPCDAPIService(cpcd);
- if(!ss->setup(serv, port)){
+ unsigned short real_port= port; // correct type
+ if(!ss->setup(serv, &real_port)){
logger.critical("Cannot setup server: %s", strerror(errno));
sleep(1);
delete ss;
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index 791df915d66..1a72537a77e 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -4,13 +4,13 @@ Next NDBFS 2000
Next DBACC 3002
Next DBTUP 4013
Next DBLQH 5042
-Next DBDICT 6006
+Next DBDICT 6007
Next DBDIH 7174
Next DBTC 8037
Next CMVMI 9000
Next BACKUP 10022
Next DBUTIL 11002
-Next DBTUX 12007
+Next DBTUX 12008
Next SUMA 13001
TESTING NODE FAILURE, ARBITRATION
@@ -196,6 +196,8 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out.
8048: Make TC not choose own node for simple/dirty read
5041: Crash is receiving simple read from other TC on different node
+8050: Send TCKEYREF is operation is non local
+
ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC
-------------------------------------------------
8040:
@@ -411,6 +413,7 @@ Drop Table/Index:
8034: Fail next index create in TC
8035: Fail next trigger drop in TC
8036: Fail next index drop in TC
+6006: Crash participant in create index
System Restart:
---------------
@@ -442,6 +445,7 @@ Test routing of signals:
Ordered index:
--------------
+12007: Make next alloc node fail with no memory error
Dbdict:
-------
diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp
index ec5c7a5d588..063e36a775f 100644
--- a/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -955,7 +955,7 @@ Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
}
if(errorCode != BackupRef::IAmNotMaster){
- signal->theData[0] = EventReport::BackupFailedToStart;
+ signal->theData[0] = NDB_LE_BackupFailedToStart;
signal->theData[1] = senderRef;
signal->theData[2] = errorCode;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -1214,7 +1214,7 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
BackupConf::SignalLength, JBB);
}
- signal->theData[0] = EventReport::BackupStarted;
+ signal->theData[0] = NDB_LE_BackupStarted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3);
@@ -2110,7 +2110,7 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
BackupCompleteRep::SignalLength, JBB);
}
- signal->theData[0] = EventReport::BackupCompleted;
+ signal->theData[0] = NDB_LE_BackupCompleted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
signal->theData[3] = ptr.p->startGCP;
@@ -2155,7 +2155,7 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
BackupAbortRep::SignalLength, JBB);
}
- signal->theData[0] = EventReport::BackupAborted;
+ signal->theData[0] = NDB_LE_BackupAborted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
signal->theData[3] = ptr.p->errorCode;
@@ -2884,8 +2884,6 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
/**
* Initialize table object
*/
- tabPtr.p->frag_mask = RNIL;
-
tabPtr.p->schemaVersion = tmpTab.TableVersion;
tabPtr.p->noOfAttributes = tmpTab.NoOfAttributes;
tabPtr.p->noOfNull = 0;
@@ -2978,7 +2976,6 @@ Backup::execDI_FCOUNTCONF(Signal* signal)
ndbrequire(findTable(ptr, tabPtr, tableId));
ndbrequire(tabPtr.p->fragments.seize(fragCount) != false);
- tabPtr.p->frag_mask = calculate_frag_mask(fragCount);
for(Uint32 i = 0; i<fragCount; i++) {
jam();
FragmentPtr fragPtr;
@@ -3795,15 +3792,6 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr)
* Slave functionallity: Perform logging
*
****************************************************************************/
-Uint32
-Backup::calculate_frag_mask(Uint32 count)
-{
- Uint32 mask = 1;
- while (mask < count) mask <<= 1;
- mask -= 1;
- return mask;
-}
-
void
Backup::execBACKUP_TRIG_REQ(Signal* signal)
{
@@ -3820,14 +3808,6 @@ Backup::execBACKUP_TRIG_REQ(Signal* signal)
jamEntry();
c_triggerPool.getPtr(trigPtr, trigger_id);
c_tablePool.getPtr(tabPtr, trigPtr.p->tab_ptr_i);
- frag_id = frag_id & tabPtr.p->frag_mask;
- /*
- At the moment the fragment identity known by TUP is the
- actual fragment id but with possibly an extra bit set.
- This is due to that ACC splits the fragment. Thus fragment id 5 can
- here be either 5 or 13. Thus masking with 2 ** n - 1 where number of
- fragments <= 2 ** n will always provide a correct fragment id.
- */
tabPtr.p->fragments.getPtr(fragPtr, frag_id);
if (fragPtr.p->node != getOwnNodeId()) {
jam();
diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp
index f3d180b9467..67b53d3eccd 100644
--- a/ndb/src/kernel/blocks/backup/Backup.hpp
+++ b/ndb/src/kernel/blocks/backup/Backup.hpp
@@ -195,7 +195,6 @@ public:
Uint32 tableId;
Uint32 schemaVersion;
- Uint32 frag_mask;
Uint32 tableType;
Uint32 noOfNull;
Uint32 noOfAttributes;
@@ -527,8 +526,6 @@ public:
ArrayPool<Node> c_nodePool;
ArrayPool<TriggerRecord> c_triggerPool;
- Uint32 calculate_frag_mask(Uint32);
-
void checkFile(Signal*, BackupFilePtr);
void checkScan(Signal*, BackupFilePtr);
void fragmentCompleted(Signal*, BackupFilePtr);
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
index 7659ee1145d..6f6aee6a7f7 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
@@ -188,7 +188,7 @@ void Cmvmi::execEVENT_REP(Signal* signal)
// to the graphical management interface.
//-----------------------------------------------------------------------
EventReport * const eventReport = (EventReport *)&signal->theData[0];
- EventReport::EventType eventType = eventReport->getEventType();
+ Ndb_logevent_type eventType = eventReport->getEventType();
jamEntry();
@@ -198,7 +198,8 @@ void Cmvmi::execEVENT_REP(Signal* signal)
Uint32 threshold;
LogLevel::EventCategory eventCategory;
Logger::LoggerLevel severity;
- if (EventLoggerBase::event_lookup(eventType,eventCategory,threshold,severity))
+ EventLoggerBase::EventTextFunction textF;
+ if (EventLoggerBase::event_lookup(eventType,eventCategory,threshold,severity,textF))
return;
SubscriberPtr ptr;
@@ -362,7 +363,7 @@ void Cmvmi::execCLOSE_COMREQ(Signal* signal)
//-----------------------------------------------------
// Report that the connection to the node is closed
//-----------------------------------------------------
- signal->theData[0] = EventReport::CommunicationClosed;
+ signal->theData[0] = NDB_LE_CommunicationClosed;
signal->theData[1] = i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -396,7 +397,7 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal)
//-----------------------------------------------------
// Report that the connection to the node is opened
//-----------------------------------------------------
- signal->theData[0] = EventReport::CommunicationOpened;
+ signal->theData[0] = NDB_LE_CommunicationOpened;
signal->theData[1] = tStartingNode;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
//-----------------------------------------------------
@@ -408,7 +409,7 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal)
globalTransporterRegistry.do_connect(i);
globalTransporterRegistry.setIOState(i, HaltIO);
- signal->theData[0] = EventReport::CommunicationOpened;
+ signal->theData[0] = NDB_LE_CommunicationOpened;
signal->theData[1] = i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
}
@@ -433,7 +434,7 @@ void Cmvmi::execENABLE_COMORD(Signal* signal)
//-----------------------------------------------------
// Report that the version of the node
//-----------------------------------------------------
- signal->theData[0] = EventReport::ConnectedApiVersion;
+ signal->theData[0] = NDB_LE_ConnectedApiVersion;
signal->theData[1] = tStartingNode;
signal->theData[2] = getNodeInfo(tStartingNode).m_version;
@@ -475,7 +476,7 @@ void Cmvmi::execDISCONNECT_REP(Signal *signal)
cancelSubscription(hostId);
- signal->theData[0] = EventReport::Disconnected;
+ signal->theData[0] = NDB_LE_Disconnected;
signal->theData[1] = hostId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
}
@@ -525,7 +526,7 @@ void Cmvmi::execCONNECT_REP(Signal *signal){
//------------------------------------------
// Also report this event to the Event handler
//------------------------------------------
- signal->theData[0] = EventReport::Connected;
+ signal->theData[0] = NDB_LE_Connected;
signal->theData[1] = hostId;
signal->header.theLength = 2;
diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
index ea866aafff9..1da6c56b0e3 100644
--- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
@@ -22,6 +22,9 @@
#include <pc.hpp>
#include <SimulatedBlock.hpp>
+// primary key is stored in TUP
+#include <Dbtup.hpp>
+
#ifdef DBACC_C
// Debug Macros
#define dbgWord32(ptr, ind, val)
@@ -98,7 +101,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZPOS_PREV_PAGE 11
#define ZNORMAL_PAGE_TYPE 0
#define ZOVERFLOW_PAGE_TYPE 1
-#define ZLONG_PAGE_TYPE 2
#define ZDEFAULT_LIST 3
#define ZWORDS_IN_PAGE 2048
/* --------------------------------------------------------------------------------- */
@@ -132,16 +134,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZPAGEZERO_NODETYPE 33
#define ZPAGEZERO_SLACK_CHECK 34
/* --------------------------------------------------------------------------------- */
-/* CONSTANTS FOR THE LONG KEY PAGES */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-// Maximum number of elements in long key page = (ZWORDS_IN_PAGE - ZHEAD_SIZE) /
-// (MinKeySize + IndexSize) = (2048 - 32) / (8 + 1) = 224. MinKeySize is actually 9
-// because 8 is the largest normal key size.
-#define ZMAX_NO_OF_LONGKEYS_IN_PAGE 225
-#define ZMAX_LONG_KEY_ARRAY_INDEX 3
-#define ZACTIVE_LONG_KEY_LEN 1
-/* --------------------------------------------------------------------------------- */
/* CONSTANTS IN ALPHABETICAL ORDER */
/* --------------------------------------------------------------------------------- */
#define ZADDFRAG 0
@@ -392,49 +384,6 @@ enum State {
// Records
-
-//----------------------------------------------------------------------------------
-// LONGKEY PAGE RECORD
-//
-// A long key page consist of a header part, a key data part and an index part. The
-// page starts with a header of size HEAD_SIZE. As you can see below, not every word
-// in the header is used. After the header comes the data part, where the actual
-// keys are stored. A key is always inserted after the existing keys in the data
-// part. If we have a fragmented data part and a new key doesn't fit after the
-// existing keys we reorganize the keys. The index part starts at the end of the
-// page and grows towards the end of the data part. This means that the limit
-// between the data part and the index part is floating. Each inserted key have a
-// word in the index part that describes size and position of the key in the data
-// part. The free indexes in the index part are single linked.
-//----------------------------------------------------------------------------------
- union LongKeyPage {
- struct {
- Uint32 pageId; // ZPOS_PAGE_ID 0
- Uint32 b;
- // The number of keys in page.
- Uint32 noOfElements; // ZPOS_NO_ELEM_IN_PAGE 2
- Uint32 d;
- Uint32 e;
- // The free area in the data part of page.
- Uint32 freeArea; // ZPOS_FREE_AREA_IN_PAGE 5
- // The index position, which defines the limit between the data and the index part.
- Uint32 highestIndex; // ZPOS_LAST_INDEX 6
- // The position where to insert the actual key in the data part.
- Uint32 insertPos; // ZPOS_INSERT_INDEX 7
- // Position in a page array where the pages are stored in a double linked list.
- // Based on the free area in the page. Values 0 to 3.
- Uint32 pageArrayPos; // ZPOS_ARRAY_POS 8
- // Next free position in the index part.
- Uint32 nextFreeIndex; // ZPOS_NEXT_FREE_INDEX 9
- // Next page in the double linked list.
- Uint32 nextPage; // ZPOS_NEXT_PAGE 10
- // Previous page in the double linked list.
- Uint32 prevPage; // ZPOS_PREV_PAGE 11
- } header;
- // This is kept to keep the logic and to make changes to a minimum.
- Uint32 word32[2048];
- };
-
/* --------------------------------------------------------------------------------- */
/* UNDO HEADER RECORD */
/* --------------------------------------------------------------------------------- */
@@ -444,9 +393,7 @@ enum State {
ZPAGE_INFO = 0,
ZOVER_PAGE_INFO = 1,
ZOP_INFO = 2,
- ZUNDO_INSERT_LONG_KEY = 3,
- ZUNDO_DELETE_LONG_KEY = 4,
- ZNO_UNDORECORD_TYPES = 5
+ ZNO_UNDORECORD_TYPES = 3
};
UintR tableId;
UintR rootFragId;
@@ -660,10 +607,10 @@ struct Fragmentrec {
//-----------------------------------------------------------------------------
// elementLength: Length of element in bucket and overflow pages
-// keyLength: Length of key (== 0 if long key or variable key length)
+// keyLength: Length of key
//-----------------------------------------------------------------------------
Uint8 elementLength;
- Uint8 keyLength;
+ Uint16 keyLength;
//-----------------------------------------------------------------------------
// This flag is used to avoid sending a big number of expand or shrink signals
@@ -689,6 +636,11 @@ struct Fragmentrec {
//-----------------------------------------------------------------------------
Uint8 nodetype;
Uint8 stopQueOp;
+
+//-----------------------------------------------------------------------------
+// flag to avoid accessing table record if no char attributes
+//-----------------------------------------------------------------------------
+ Uint8 hasCharAttr;
};
typedef Ptr<Fragmentrec> FragmentrecPtr;
@@ -771,6 +723,7 @@ struct Operationrec {
State transactionstate;
Uint16 elementContainer;
Uint16 tupkeylen;
+ Uint32 xfrmtupkeylen;
Uint32 userblockref;
Uint32 scanBits;
Uint8 elementIsDisappeared;
@@ -783,7 +736,7 @@ struct Operationrec {
Uint8 dirtyRead;
Uint8 commitDeleteCheckFlag;
Uint8 isAccLockReq;
- Uint32 nextOpList;
+ Uint8 isUndoLogReq;
}; /* p2c: size = 168 bytes */
typedef Ptr<Operationrec> OperationrecPtr;
@@ -914,6 +867,9 @@ public:
Dbacc(const class Configuration &);
virtual ~Dbacc();
+ // pointer to TUP instance in this thread
+ Dbtup* c_tup;
+
private:
BLOCK_DEFINES(Dbacc);
@@ -972,10 +928,8 @@ private:
void initFragGeneral(FragmentrecPtr);
void verifyFragCorrect(FragmentrecPtr regFragPtr);
void sendFSREMOVEREQ(Signal* signal, Uint32 tableId);
- void sendDROP_TABFILECONF(Signal* signal, TabrecPtr tabPtr);
void releaseFragResources(Signal* signal, Uint32 fragIndex);
void releaseRootFragRecord(Signal* signal, RootfragmentrecPtr rootPtr);
- void sendREL_TABMEMCONF(Signal* signal, TabrecPtr tabPtr);
void releaseRootFragResources(Signal* signal, Uint32 tableId);
void releaseDirResources(Signal* signal,
Uint32 fragIndex,
@@ -1051,7 +1005,6 @@ private:
void releaseScanRec(Signal* signal);
bool searchScanContainer(Signal* signal);
void sendNextScanConf(Signal* signal);
- void sendScaninfo(Signal* signal);
void setlock(Signal* signal);
void takeOutActiveScanOp(Signal* signal);
void takeOutScanLockQueue(Uint32 scanRecIndex);
@@ -1063,15 +1016,8 @@ private:
void increaselistcont(Signal* signal);
void seizeLeftlist(Signal* signal);
void seizeRightlist(Signal* signal);
- void allocLongOverflowPage(Signal* signal);
- void allocSpecificLongOverflowPage(Signal* signal);
- void getLongKeyPage(Signal* signal);
- void initLongOverpage(Signal* signal);
- void storeLongKeys(Signal* signal);
- void storeLongKeysAtPos(Signal* signal);
- void reorgLongPage(Signal* signal);
+ Uint32 readTablePk(Uint32 localkey1);
void getElement(Signal* signal);
- void searchLongKey(Signal* signal, bool verify);
void getdirindex(Signal* signal);
void commitdelete(Signal* signal, bool systemRestart);
void deleteElement(Signal* signal);
@@ -1079,15 +1025,6 @@ private:
void releaseLeftlist(Signal* signal);
void releaseRightlist(Signal* signal);
void checkoverfreelist(Signal* signal);
- void deleteLongKey(Signal* signal);
- void removeFromPageArrayList(Signal* signal);
- void insertPageArrayList(Signal* signal);
- void checkPageArrayList(Signal* signal, const char *);
- void checkPageB4Insert(Uint32, const char *);
- void checkPageB4Remove(Uint32, const char *);
- void checkIndexInLongKeyPage(Uint32, const char *);
- void printoutInfoAndShutdown(LongKeyPage *);
- void releaseLongPage(Signal* signal);
void abortOperation(Signal* signal);
void accAbortReqLab(Signal* signal, bool sendConf);
void commitOperation(Signal* signal);
@@ -1105,7 +1042,6 @@ private:
void initLcpConnRec(Signal* signal);
void initOverpage(Signal* signal);
void initPage(Signal* signal);
- void initPageZero(Signal* signal);
void initRootfragrec(Signal* signal);
void putOpInFragWaitQue(Signal* signal);
void putOverflowRecInFrag(Signal* signal);
@@ -1159,8 +1095,6 @@ private:
void refaccConnectLab(Signal* signal);
void srReadOverPagesLab(Signal* signal);
void releaseScanLab(Signal* signal);
- void exeoperationLab(Signal* signal);
- void saveKeyDataLab(Signal* signal);
void lcpOpenUndofileConfLab(Signal* signal);
void srFsOpenConfLab(Signal* signal);
void checkSyncUndoPagesLab(Signal* signal);
@@ -1172,13 +1106,12 @@ private:
void srReadPagesLab(Signal* signal);
void srDoUndoLab(Signal* signal);
void ndbrestart1Lab(Signal* signal);
- void initialiseRecordsLab(Signal* signal, Uint32 returnRef, Uint32 retData);
+ void initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data);
void srReadPagesAllocLab(Signal* signal);
void checkNextBucketLab(Signal* signal);
void endsavepageLab(Signal* signal);
void saveZeroPageLab(Signal* signal);
void srAllocPage0011Lab(Signal* signal);
- void allocscanrecLab(Signal* signal);
void sendLcpFragidconfLab(Signal* signal);
void savepagesLab(Signal* signal);
void saveOverPagesLab(Signal* signal);
@@ -1192,6 +1125,8 @@ private:
void lcp_write_op_to_undolog(Signal* signal);
void reenable_expand_after_redo_log_exection_complete(Signal*);
+ // charsets
+ void xfrmKeyData(Signal* signal);
// Initialisation
void initData();
@@ -1281,8 +1216,6 @@ private:
/* --------------------------------------------------------------------------------- */
Page8 *page8;
/* 8 KB PAGE */
- Page8Ptr aslpPageptr;
- Page8Ptr alpPageptr;
Page8Ptr ancPageptr;
Page8Ptr colPageptr;
Page8Ptr ccoPageptr;
@@ -1293,29 +1226,17 @@ private:
Page8Ptr gdiPageptr;
Page8Ptr gePageptr;
Page8Ptr gflPageptr;
- Page8Ptr glkPageptr;
Page8Ptr idrPageptr;
Page8Ptr ilcPageptr;
- Page8Ptr iloPageptr;
Page8Ptr inpPageptr;
Page8Ptr iopPageptr;
- Page8Ptr ipzPageptr;
Page8Ptr lastPageptr;
Page8Ptr lastPrevpageptr;
Page8Ptr lcnPageptr;
Page8Ptr lcnCopyPageptr;
Page8Ptr lupPageptr;
- Page8Ptr dlkPageptr;
- Page8Ptr ipaPagePtr;
Page8Ptr priPageptr;
Page8Ptr pwiPageptr;
- Page8Ptr rfpPageptr;
- Page8Ptr relpPageptr;
- Page8Ptr rlopPageptr;
- Page8Ptr slkPageptr;
- Page8Ptr slkCopyPageptr;
- Page8Ptr slkapPageptr;
- Page8Ptr slkapCopyPageptr;
Page8Ptr ciPageidptr;
Page8Ptr gsePageidptr;
Page8Ptr isoPageptr;
@@ -1329,7 +1250,6 @@ private:
Page8Ptr ropPageptr;
Page8Ptr rpPageptr;
Page8Ptr slPageptr;
- Page8Ptr slpPageptr;
Page8Ptr spPageptr;
Uint32 cfirstfreepage;
Uint32 cfreepage;
@@ -1347,7 +1267,6 @@ private:
/* --------------------------------------------------------------------------------- */
Rootfragmentrec *rootfragmentrec;
RootfragmentrecPtr rootfragrecptr;
- RootfragmentrecPtr tmprootfrgptr;
Uint32 crootfragmentsize;
Uint32 cfirstfreerootfrag;
/* --------------------------------------------------------------------------------- */
@@ -1380,7 +1299,6 @@ private:
Uint32 tpriElementptr;
Uint32 tgseElementptr;
Uint32 tgseContainerptr;
- Uint32 tiloIndex;
Uint32 trlHead;
Uint32 trlRelCon;
Uint32 trlNextused;
@@ -1389,20 +1307,12 @@ private:
Uint32 tlupElemIndex;
Uint32 tlupIndex;
Uint32 tlupForward;
- Uint32 tslkPageIndex;
- Uint32 tslkKeyLen;
- Uint32 tslkapKeyLen;
- Uint32 tslkapPageIndex;
- Uint32 tipaArrayPos;
- Uint32 trfpArrayPos;
- Uint32 tdlkLogicalPageIndex;
Uint32 tancNext;
Uint32 tancBufType;
Uint32 tancContainerptr;
Uint32 tancPageindex;
Uint32 tancPageid;
Uint32 tidrResult;
- Uint32 tidrKeyLen;
Uint32 tidrElemhead;
Uint32 tidrForward;
Uint32 tidrPageindex;
@@ -1420,15 +1330,11 @@ private:
Uint32 tdelForward;
Uint32 tiopPageId;
Uint32 tipPageId;
- Uint32 ttupKeyLength;
Uint32 tgeLocked;
Uint32 tgeResult;
Uint32 tgeContainerptr;
Uint32 tgeElementptr;
Uint32 tgeForward;
- Uint32 tslcResult;
- Uint32 tslcPagedir;
- Uint32 tslcPageIndex;
Uint32 tundoElemIndex;
Uint32 texpReceivedBucket;
Uint32 texpDirInd;
@@ -1453,7 +1359,6 @@ private:
Uint32 tscanFlag;
Uint32 theadundoindex;
Uint32 tgflBufType;
- Uint32 thashvalue;
Uint32 tgseIsforward;
Uint32 tsscIsforward;
Uint32 trscIsforward;
@@ -1462,21 +1367,10 @@ private:
Uint32 tisoIsforward;
Uint32 tgseIsLocked;
Uint32 tsscIsLocked;
- Uint32 tkey1;
- Uint32 tkey2;
- Uint32 tkey3;
- Uint32 tkey4;
Uint32 tkeylen;
- Uint32 tkSize;
- Uint32 tlhfragbits;
- Uint32 tlhdirbits;
- Uint32 tlocalkeylen;
- Uint32 tmaxloadfactor;
- Uint32 tminloadfactor;
Uint32 tmp;
Uint32 tmpP;
Uint32 tmpP2;
- Uint32 taslpDirIndex;
Uint32 tmp1;
Uint32 tmp2;
Uint32 tgflPageindex;
@@ -1490,9 +1384,6 @@ private:
Uint32 trsbPageindex;
Uint32 tnciPageindex;
Uint32 tlastPrevconptr;
- Uint32 treqinfo;
- Uint32 transactionid1;
- Uint32 transactionid2;
Uint32 tresult;
Uint32 tslUpdateHeader;
Uint32 tuserptr;
@@ -1505,15 +1396,12 @@ private:
Uint32 tgdiPageindex;
Uint32 tiopIndex;
Uint32 tnciTmp;
- Uint32 tlenKeyinfo;
Uint32 tullIndex;
Uint32 turlIndex;
Uint32 tlfrTmp1;
Uint32 tlfrTmp2;
- Uint32 tudqeIndex;
Uint32 tscanTrid1;
Uint32 tscanTrid2;
- Uint32 taccscanTmp;
Uint16 clastUndoPageIdWritten;
Uint32 cactiveCheckpId;
@@ -1557,10 +1445,13 @@ private:
Uint32 cexcPrevpageindex;
Uint32 cexcPrevforward;
Uint32 clocalkey[32];
+ union {
Uint32 ckeys[2048];
+ Uint64 ckeys_align;
+ };
Uint32 c_errorInsert3000_TableId;
- Uint32 cSrUndoRecords[5];
+ Uint32 cSrUndoRecords[UndoHeader::ZNO_UNDORECORD_TYPES];
};
#endif
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
index c98c072cc89..d03f3b55d6a 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
@@ -133,7 +133,8 @@ void Dbacc::initRecords()
}//Dbacc::initRecords()
Dbacc::Dbacc(const class Configuration & conf):
- SimulatedBlock(DBACC, conf)
+ SimulatedBlock(DBACC, conf),
+ c_tup(0)
{
Uint32 log_page_size= 0;
BLOCK_CONSTRUCTOR(Dbacc);
@@ -197,6 +198,80 @@ Dbacc::Dbacc(const class Configuration & conf):
addRecSignal(GSN_SET_VAR_REQ, &Dbacc::execSET_VAR_REQ);
initData();
+
+#ifdef VM_TRACE
+ {
+ void* tmp[] = { &expDirRangePtr,
+ &gnsDirRangePtr,
+ &newDirRangePtr,
+ &rdDirRangePtr,
+ &nciOverflowrangeptr,
+ &expDirptr,
+ &rdDirptr,
+ &sdDirptr,
+ &nciOverflowDirptr,
+ &fragrecptr,
+ &fsConnectptr,
+ &fsOpptr,
+ &lcpConnectptr,
+ &operationRecPtr,
+ &idrOperationRecPtr,
+ &copyInOperPtr,
+ &copyOperPtr,
+ &mlpqOperPtr,
+ &queOperPtr,
+ &readWriteOpPtr,
+ &iopOverflowRecPtr,
+ &tfoOverflowRecPtr,
+ &porOverflowRecPtr,
+ &priOverflowRecPtr,
+ &rorOverflowRecPtr,
+ &sorOverflowRecPtr,
+ &troOverflowRecPtr,
+ &ancPageptr,
+ &colPageptr,
+ &ccoPageptr,
+ &datapageptr,
+ &delPageptr,
+ &excPageptr,
+ &expPageptr,
+ &gdiPageptr,
+ &gePageptr,
+ &gflPageptr,
+ &idrPageptr,
+ &ilcPageptr,
+ &inpPageptr,
+ &iopPageptr,
+ &lastPageptr,
+ &lastPrevpageptr,
+ &lcnPageptr,
+ &lcnCopyPageptr,
+ &lupPageptr,
+ &priPageptr,
+ &pwiPageptr,
+ &ciPageidptr,
+ &gsePageidptr,
+ &isoPageptr,
+ &nciPageidptr,
+ &rsbPageidptr,
+ &rscPageidptr,
+ &slPageidptr,
+ &sscPageidptr,
+ &rlPageptr,
+ &rlpPageptr,
+ &ropPageptr,
+ &rpPageptr,
+ &slPageptr,
+ &spPageptr,
+ &rootfragrecptr,
+ &scanPtr,
+ &srVersionPtr,
+ &tabptr,
+ &undopageptr
+ };
+ init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0]));
+ }
+#endif
}//Dbacc::Dbacc()
Dbacc::~Dbacc()
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index a3880e2df1d..f4b084c42fb 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -16,6 +16,7 @@
#define DBACC_C
#include "Dbacc.hpp"
+#include <my_sys.h>
#include <AttributeHeader.hpp>
#include <signaldata/AccFrag.hpp>
@@ -27,6 +28,8 @@
#include <signaldata/FsRemoveReq.hpp>
#include <signaldata/DropTab.hpp>
#include <signaldata/DumpStateOrd.hpp>
+#include <KeyDescriptor.hpp>
+
// TO_DO_RONM is a label for comments on what needs to be improved in future versions
// when more time is given.
@@ -532,7 +535,14 @@ void Dbacc::execNDB_STTOR(Signal* signal)
void Dbacc::execSTTOR(Signal* signal)
{
jamEntry();
- // tstartphase = signal->theData[1];
+ Uint32 tstartphase = signal->theData[1];
+ switch (tstartphase) {
+ case 1:
+ jam();
+ c_tup = (Dbtup*)globalData.getBlock(DBTUP);
+ ndbrequire(c_tup != 0);
+ break;
+ }
tuserblockref = signal->theData[3];
csignalkey = signal->theData[6];
sttorrysignalLab(signal);
@@ -1037,7 +1047,7 @@ void Dbacc::execACCFRAGREQ(Signal* signal)
// config mismatch - do not crash if release compiled
if (tabptr.i >= ctablesize) {
jam();
- addFragRefuse(signal, 800);
+ addFragRefuse(signal, 640);
return;
}
#endif
@@ -1119,8 +1129,8 @@ void Dbacc::execACCFRAGREQ(Signal* signal)
Uint32 userPtr = req->userPtr;
BlockReference retRef = req->userRef;
rootfragrecptr.p->rootState = ACTIVEROOT;
- AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
+ AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
conf->userPtr = userPtr;
conf->rootFragPtr = rootfragrecptr.i;
conf->fragId[0] = rootfragrecptr.p->fragmentid[0];
@@ -1144,6 +1154,7 @@ void Dbacc::addFragRefuse(Signal* signal, Uint32 errorCode)
return;
}//Dbacc::addFragRefuseEarly()
+
void
Dbacc::execDROP_TAB_REQ(Signal* signal){
jamEntry();
@@ -1503,6 +1514,7 @@ void Dbacc::initOpRec(Signal* signal)
operationRecPtr.p->hashValue = signal->theData[3];
operationRecPtr.p->tupkeylen = signal->theData[4];
+ operationRecPtr.p->xfrmtupkeylen = signal->theData[4];
operationRecPtr.p->transId1 = signal->theData[5];
operationRecPtr.p->transId2 = signal->theData[6];
operationRecPtr.p->transactionstate = ACTIVE;
@@ -1541,6 +1553,9 @@ void Dbacc::initOpRec(Signal* signal)
// bit to mark lock operation
operationRecPtr.p->isAccLockReq = (Treqinfo >> 31) & 0x1;
+
+ // undo log is not run via ACCKEYREQ
+ operationRecPtr.p->isUndoLogReq = 0;
}//Dbacc::initOpRec()
/* --------------------------------------------------------------------------------- */
@@ -1614,6 +1629,10 @@ void Dbacc::execACCKEYREQ(Signal* signal)
ndbrequire(operationRecPtr.p->transactionstate == IDLE);
initOpRec(signal);
+ // normalize key if any char attr
+ if (! operationRecPtr.p->isAccLockReq && fragrecptr.p->hasCharAttr)
+ xfrmKeyData(signal);
+
/*---------------------------------------------------------------*/
/* */
/* WE WILL USE THE HASH VALUE TO LOOK UP THE PROPER MEMORY */
@@ -1713,6 +1732,19 @@ void Dbacc::execACCKEYREQ(Signal* signal)
return;
}//Dbacc::execACCKEYREQ()
+void
+Dbacc::xfrmKeyData(Signal* signal)
+{
+ Uint32 table = fragrecptr.p->myTableId;
+ Uint32 dst[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
+ Uint32* src = &signal->theData[7];
+ Uint32 len = xfrm_key(table, src, dst, sizeof(dst) >> 2, keyPartLen);
+ ndbrequire(len); // 0 means error
+ memcpy(src, dst, len << 2);
+ operationRecPtr.p->xfrmtupkeylen = len;
+}
+
void Dbacc::accIsLockedLab(Signal* signal)
{
ndbrequire(csystemRestart == ZFALSE);
@@ -1786,8 +1818,6 @@ void Dbacc::insertExistElemLab(Signal* signal)
/* --------------------------------------------------------------------------------- */
void Dbacc::insertelementLab(Signal* signal)
{
- Uint32 tinsKeyLen;
-
if (fragrecptr.p->createLcp == ZTRUE) {
if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_OPERATION) {
jam();
@@ -1805,46 +1835,9 @@ void Dbacc::insertelementLab(Signal* signal)
}//if
}//if
if (fragrecptr.p->keyLength != operationRecPtr.p->tupkeylen) {
+ // historical
ndbrequire(fragrecptr.p->keyLength == 0);
}//if
- if (fragrecptr.p->keyLength != 0) {
- ndbrequire(operationRecPtr.p->tupkeylen <= 8);
- for (Uint32 i = 0; i < operationRecPtr.p->tupkeylen; i++) {
- jam();
- ckeys[i] = signal->theData[i + 7];
- }//for
- tinsKeyLen = operationRecPtr.p->tupkeylen;
- } else {
- jam();
- seizePage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- acckeyref1Lab(signal, tresult);
- return;
- }//if
- operationRecPtr.p->keyinfoPage = spPageptr.i;
- for (Uint32 i = 0; i < signal->theData[4]; i++) {
- spPageptr.p->word32[i] = signal->theData[i + 7];
- }//for
-
- getLongKeyPage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- acckeyref1Lab(signal, tresult);
- return;
- }//if
- slkPageptr = glkPageptr;
- slkCopyPageptr.i = operationRecPtr.p->keyinfoPage;
- ptrCheckGuard(slkCopyPageptr, cpagesize, page8);
- tslkKeyLen = operationRecPtr.p->tupkeylen;
- storeLongKeys(signal);
- ckeys[0] = (slkPageptr.p->word32[ZPOS_PAGE_ID] << 10) + tslkPageIndex;
- tinsKeyLen = ZACTIVE_LONG_KEY_LEN;
- rpPageptr.i = operationRecPtr.p->keyinfoPage;
- ptrCheckGuard(rpPageptr, cpagesize, page8);
- releasePage(signal);
- operationRecPtr.p->keyinfoPage = RNIL;
- }//if
signal->theData[0] = operationRecPtr.p->userptr;
Uint32 blockNo = refToBlock(operationRecPtr.p->userblockref);
@@ -1868,7 +1861,6 @@ void Dbacc::insertelementLab(Signal* signal)
idrPageptr = gdiPageptr;
tidrPageindex = tgdiPageindex;
tidrForward = ZTRUE;
- tidrKeyLen = tinsKeyLen;
idrOperationRecPtr = operationRecPtr;
clocalkey[0] = localKey;
operationRecPtr.p->localdata[0] = localKey;
@@ -2314,14 +2306,14 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
operationRecPtr.p->transactionstate = IDLE;
operationRecPtr.p->operation = ZUNDEFINED_OP;
if(Toperation != ZREAD){
+ rootfragrecptr.i = fragrecptr.p->myroot;
+ ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
rootfragrecptr.p->m_commit_count++;
if (Toperation != ZINSERT) {
if (Toperation != ZDELETE) {
return;
} else {
jam();
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
rootfragrecptr.p->noOfElements--;
fragrecptr.p->slack += operationRecPtr.p->insertDeleteLen;
if (fragrecptr.p->slack > fragrecptr.p->slackCheck) {
@@ -2341,8 +2333,6 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
}//if
} else {
jam(); /* EXPAND PROCESS HANDLING */
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
rootfragrecptr.p->noOfElements++;
fragrecptr.p->slack -= operationRecPtr.p->insertDeleteLen;
if (fragrecptr.p->slack >= (1u << 31)) {
@@ -2460,6 +2450,7 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
signal->theData[4] = 1; // fake primKeyLen
signal->theData[5] = req->transId1;
signal->theData[6] = req->transId2;
+ // enter local key in place of PK
signal->theData[7] = req->tupAddr;
EXECUTE_DIRECT(DBACC, GSN_ACCKEYREQ, signal, 8);
// translate the result
@@ -2484,26 +2475,6 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
*sig = *req;
return;
}
- operationRecPtr.i = req->accOpPtr;
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (fragrecptr.p->keyLength == 0 &&
- // should test some state variable
- operationRecPtr.p->elementPage != RNIL) {
- jam();
- // re-compute long key vars
- Page8Ptr tPageptr;
- tPageptr.i = operationRecPtr.p->elementPage;
- ptrCheckGuard(tPageptr, cpagesize, page8);
- Uint32 tKeyptr =
- operationRecPtr.p->elementPointer +
- operationRecPtr.p->elementIsforward *
- (ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen);
- tslcPageIndex = tPageptr.p->word32[tKeyptr] & 0x3ff;
- tslcPagedir = tPageptr.p->word32[tKeyptr] >> 10;
- searchLongKey(signal, false);
- }
if (lockOp == AccLockReq::Unlock) {
jam();
// do unlock via ACC_COMMITREQ (immediate)
@@ -2857,14 +2828,6 @@ void Dbacc::insertContainer(Signal* signal)
idrPageptr.p->word32[tidrIndex] = clocalkey[tidrInputIndex]; /* INSERTS LOCALKEY */
tidrIndex += tidrForward;
}//for
- guard26 = tidrKeyLen - 1;
- arrGuard(guard26, 8);
- for (tidrInputIndex = 0; tidrInputIndex <= guard26; tidrInputIndex++) {
- dbgWord32(idrPageptr, tidrIndex, ckeys[tidrInputIndex]);
- arrGuard(tidrIndex, 2048);
- idrPageptr.p->word32[tidrIndex] = ckeys[tidrInputIndex]; /* INSERTS TUPLE KEY */
- tidrIndex += tidrForward;
- }//for
tidrContLen = idrPageptr.p->word32[tidrContainerptr] << 6;
tidrContLen = tidrContLen >> 6;
dbgWord32(idrPageptr, tidrContainerptr, (tidrContainerlen << 26) | tidrContLen);
@@ -3198,1215 +3161,6 @@ void Dbacc::seizeRightlist(Signal* signal)
increaselistcont(signal);
}//Dbacc::seizeRightlist()
-
-//---------------------------------------------------------------------------------
-// ALLOC_SPECIFIC_LONG_OVERFLOW_PAGE
-//
-// DESCRIPTION: ALLOCATES A LONG OVER FLOW PAGE AND PUTS IT IN A SPECIFIED
-// DIRINDEX. THIS IS TO SUPPORT AN UNDO_DELETE AFTER AN
-// UNDO_INSERT ON THE SAME LONG KEY IN A LCP.
-// UNDO_INSERT ONLY HAVE A REFERENCE TO THE KEY AND TO MAKE
-// IT POSSIBLE TO DELETE THE KEY, THE REFERENCE MUST BE
-// ACCURATE, WHICH MEANS THE KEY MUST BE SAVED ON THE SAME
-// PLACE IT WAS DELETED FROM.
-//---------------------------------------------------------------------------------
-void Dbacc::allocSpecificLongOverflowPage(Signal* signal)
-{
- DirRangePtr aloDirRangePtr;
- DirectoryarrayPtr aloOverflowDirptr;
-
- if ((cfirstfreepage == RNIL) &&
- (cfreepage >= cpagesize)) {
- jam();
- zpagesize_error("Dbacc::allocSpecificLongOverflowPage");
- tresult = ZPAGESIZE_ERROR;
- return;
- }
-
- if ((cfirstfreedir == RNIL) &&
- (cdirarraysize <= cdirmemory)) {
- jam();
- tresult = ZDIRSIZE_ERROR;
- return;
- }
-
- tmpP = taslpDirIndex;
- aloDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(aloDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
-
- if (aloDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- jam();
- seizeDirectory(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }
- aloDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- } else {
- jam();
- sdDirptr.i = RNIL;
- ptrNull(sdDirptr);
- }
-
- aloOverflowDirptr.i = aloDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(aloOverflowDirptr, cdirarraysize, directoryarray);
- seizePage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }//if
-
- if (aloOverflowDirptr.p->pagep[tmpP] != RNIL) {
- jam();
- sendSystemerror(signal);
- return;
- }
-
- aloOverflowDirptr.p->pagep[tmpP] = spPageptr.i;
- iloPageptr.p = spPageptr.p;
- iloPageptr.i = spPageptr.i;
- tiloIndex = taslpDirIndex;
- initLongOverpage(signal);
- aslpPageptr.i = spPageptr.i;
- aslpPageptr.p = spPageptr.p;
-}//Dbacc::allocSpecificLongOverflowPage
-
-/* --------------------------------------------------------------------------------- */
-/* ALLOC_LONG_OVERFLOW_PAGE */
-/* DESCRIPTION: */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::allocLongOverflowPage(Signal* signal)
-{
- DirRangePtr aloDirRangePtr;
- DirectoryarrayPtr aloOverflowDirptr;
- OverflowRecordPtr aloOverflowRecPtr;
- Uint32 taloIndex;
-
- if ((cfirstfreepage == RNIL) &&
- (cfreepage >= cpagesize)) {
- jam();
- zpagesize_error("Dbacc::allocLongOverflowPage");
- tresult = ZPAGESIZE_ERROR;
- return;
- }//if
- if ((cfirstfreedir == RNIL) &&
- (cdirarraysize <= cdirmemory)) {
- jam();
- tresult = ZDIRSIZE_ERROR;
- return;
- }//if
- if (fragrecptr.p->firstFreeDirindexRec != RNIL) {
- jam();
- aloOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
- ptrCheckGuard(aloOverflowRecPtr, coverflowrecsize, overflowRecord);
- troOverflowRecPtr.p = aloOverflowRecPtr.p;
- takeRecOutOfFreeOverdir(signal);
- taloIndex = aloOverflowRecPtr.p->dirindex;
- rorOverflowRecPtr = aloOverflowRecPtr;
- releaseOverflowRec(signal);
- } else {
- jam();
- taloIndex = fragrecptr.p->lastOverIndex;
- fragrecptr.p->lastOverIndex++;
- }//if
- tmpP = taloIndex;
- aloDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(aloDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- if (aloDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- jam();
- seizeDirectory(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- aloDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- } else {
- jam();
- sdDirptr.i = RNIL;
- ptrNull(sdDirptr);
- }//if
- aloOverflowDirptr.i = aloDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(aloOverflowDirptr, cdirarraysize, directoryarray);
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- aloOverflowDirptr.p->pagep[tmpP] = spPageptr.i;
- iloPageptr = spPageptr;
- tiloIndex = taloIndex;
- initLongOverpage(signal);
- alpPageptr = spPageptr;
- ipaPagePtr = spPageptr;
- tipaArrayPos = 3;
- insertPageArrayList(signal);
-}//Dbacc::allocLongOverflowPage()
-
-/* --------------------------------------------------------------------------------- */
-/* GET_LONG_KEY_PAGE */
-/* DESCRIPTION: SEARCH FOR A FREE OVERFLOW PAGE TO STORE A LONG KEY. */
-/* LONG_KEY_PAGE_PTR IS RETURNED. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::getLongKeyPage(Signal* signal)
-{
- LongKeyPage *glkPage;
-
- jam();
-
- Uint32 tglkLongIndex = 0;
-
- ndbrequire(operationRecPtr.p->tupkeylen <= ZWORDS_IN_PAGE - ZHEAD_SIZE);
-
- // Do not look in longKeyPageArray[tglkLongIndex] where the pages are to small.
- if(operationRecPtr.p->tupkeylen < 128) {
- jam();
- tglkLongIndex = 0;
- } else {
- jam();
- tglkLongIndex = (operationRecPtr.p->tupkeylen - 128) / 512;
- }//if
-
- // Go through the longKeyPageArray and search for a page.
- for (; tglkLongIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; tglkLongIndex++) {
- jam();
- glkPageptr.i = fragrecptr.p->longKeyPageArray[tglkLongIndex];
-
- if (glkPageptr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(glkPageptr, cpagesize, page8);
- glkPage = (LongKeyPage *) &glkPageptr.p->word32[0];
-
- // Check page if there is enough memory available. Accept only page
- // with free_area > tupkeylen, this leaves at least one word for eventually
- // an increase in the index area.
- if (glkPage->header.freeArea > operationRecPtr.p->tupkeylen){
- // The page found is OK
- jam();
- return;
- } else {
- // Not enough space in page, look in the next page if not RNIL,
- // otherwise continue with for-loop.
- jam();
- glkPageptr.i = glkPage->header.nextPage;
- }
- }//do
- while (glkPageptr.i != RNIL);
- }//if
- }//for
-
- // No page with enough space was available, allocate a new page!
- jam();
- allocLongOverflowPage(signal);
- glkPageptr = alpPageptr;
-}//Dbacc::getLongKeyPage()
-
-/* --------------------------------------------------------------------------------- */
-/* INIT_LONG_OVERPAGE */
-/* INPUT. ILO_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */
-/* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
-/* ACCORDING TO LH3 AND PAGE STRUCTOR DISACRIPTION OF NDBACC BLOCK */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initLongOverpage(Signal* signal)
-{
- iloPageptr.p->word32[ZPOS_PAGE_ID] = tiloIndex;
- iloPageptr.p->word32[ZPOS_PAGE_TYPE] = ZLONG_PAGE_TYPE << ZPOS_PAGE_TYPE_BIT;
- iloPageptr.p->word32[ZPOS_NO_ELEM_IN_PAGE] = 0;
- iloPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- iloPageptr.p->word32[ZPOS_FREE_AREA_IN_PAGE] = ZWORDS_IN_PAGE - ZHEAD_SIZE;
- iloPageptr.p->word32[ZPOS_LAST_INDEX] = 0;
- iloPageptr.p->word32[ZPOS_INSERT_INDEX] = ZHEAD_SIZE;
- iloPageptr.p->word32[ZPOS_ARRAY_POS] = ZDEFAULT_LIST;
- iloPageptr.p->word32[ZPOS_NEXT_FREE_INDEX] = 0;
- iloPageptr.p->word32[ZPOS_NEXT_PAGE] = RNIL;
- iloPageptr.p->word32[ZPOS_PREV_PAGE] = RNIL;
- iloPageptr.p->word32[12] = 0;
- iloPageptr.p->word32[13] = 0;
- iloPageptr.p->word32[14] = 0;
- iloPageptr.p->word32[15] = 0;
- // Initialize free indexes
- for (int i = 1; i < (ZWORDS_IN_PAGE - ZHEAD_SIZE); i++)
- iloPageptr.p->word32[ZWORDS_IN_PAGE - i] = i + 1;
-}//Dbacc::initLongOverpage()
-
-//---------------------------------------------------------------------------------
-// STORE_LONG_KEYS_AT_POS
-//
-// INPUT: SLKAP_PAGEPTR
-// SLKAP_COPY_PAGEPTR
-// TSLKAP_KEY_LEN
-// TSLKAP_PAGE_INDEX
-//
-// DESCRIPTION: A LONG ELEMENT IS STORED ON A LONG_KEY_PAGE AT A
-// SPECIFIC POSITION. THIS FUNCTION IS USED BY UNDO_DELETE.
-//---------------------------------------------------------------------------------
-void Dbacc::storeLongKeysAtPos(Signal* signal)
-{
- Uint32 tslkapHighestIndex;
- Uint32 tslkapLastSize;
- Uint32 tslkapInsertIndex;
- Uint32 tslkapIndexIncreaseSize;
- Uint32 tslkapTmp;
-
- LongKeyPage *slkapPage;
-
- jam();
- slkapPage = (LongKeyPage *) &slkapPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(slkapPageptr.i, "storeLongKeysAtPos");
-#endif
-
- // if (csystemRestart != ZTRUE) {
- if (cundoLogActive != ZTRUE) {
- //-------------------------------------------------------------
- // This function is only allowed to be called during
- // undolog execution.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- if (slkapPage->word32[ZWORDS_IN_PAGE - tslkapPageIndex] >> 16 != 0 ) {
- //-------------------------------------------------------------
- // The index should be empty, we have a serious problem.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- //-------------------------------------------------------------
- // Calculate some variables to use later.
- //-------------------------------------------------------------
- tslkapHighestIndex = slkapPage->header.highestIndex;
- tslkapPageIndex > tslkapHighestIndex ?
- tslkapIndexIncreaseSize = tslkapPageIndex - tslkapHighestIndex :
- tslkapIndexIncreaseSize = 0;
-
- slkapPage->header.highestIndex += tslkapIndexIncreaseSize;
-
- if ((slkapPage->header.freeArea - tslkapIndexIncreaseSize)
- < tslkapKeyLen) {
- //-------------------------------------------------------------
- // Not enough area in the page, a serious problem.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- //-------------------------------------------------------------
- // Fix the free index list. We might put in a key in the
- // middle of the list, so we must fix the free list and the
- // free index pointers.
- //-------------------------------------------------------------
- slkapPage->header.nextFreeIndex = 0;
-
- for (Uint32 i = tslkapHighestIndex + tslkapIndexIncreaseSize; i > 0; i--) {
- if (i == tslkapPageIndex) {
- // The key index shall not be in the free list.
- continue;
- }
-
- if (slkapPage->word32[ZWORDS_IN_PAGE - i] >> 16 == 0 ) {
- // Go through all empty indexes.
- slkapPage->word32[ZWORDS_IN_PAGE - i] = slkapPage->header.nextFreeIndex;
- arrGuard(i, 2048);
- slkapPage->header.nextFreeIndex = i;
- }
- }
-
- //-------------------------------------------------------------
- // Decrement the free area in page according to the above
- // increase in index size.
- //-------------------------------------------------------------
- slkapPage->header.freeArea -= tslkapIndexIncreaseSize;
-
- tslkapLastSize = ZWORDS_IN_PAGE - slkapPage->header.highestIndex
- - slkapPage->header.insertPos;
-
- //-------------------------------------------------------------
- // Check if we have to reorganize the page.
- //-------------------------------------------------------------
- if (tslkapLastSize >= tslkapKeyLen) {
- jam();
- } else {
- jam();
- relpPageptr.p = slkapPageptr.p;
- reorgLongPage(signal);
- }
-
- //-------------------------------------------------------------
- // Insert the key and update page attributes.
- //-------------------------------------------------------------
- jam();
- // Increase the number of element in the page.
- slkapPage->header.noOfElements++;
- jam();
- // Put in the key reference into the index. The reference
- // consists of key length and insert position.
- arrGuard(ZWORDS_IN_PAGE - tslkapPageIndex, 2048);
- slkapPage->word32[ZWORDS_IN_PAGE - tslkapPageIndex] =
- slkapPage->header.insertPos | (tslkapKeyLen << 16);
- jam();
- // Increase the key insert position.
- tslkapInsertIndex = slkapPage->header.insertPos;
- slkapPage->header.insertPos += tslkapKeyLen;
- jam();
- // Decrease the free area.
- slkapPage->header.freeArea -= tslkapKeyLen;
- jam();
-
- // Update pageArrayPos. insertPageArrayList() called from execACC_OVER_REC
- // needs this value.
- if (slkapPage->header.freeArea < 128) {
- jam();
- slkapPage->header.pageArrayPos = 4;
- } else {
- jam();
- slkapPage->header.pageArrayPos = (slkapPage->header.freeArea - 128) / 512;
- }//if
-
- // Store the actual key at the insert position.
- Uint32 guard27 = tslkapKeyLen - 1;
- arrGuard(guard27 + tslkapInsertIndex, 2048);
- for (tslkapTmp = 0; tslkapTmp <= guard27; tslkapTmp++) {
- jam();
- slkapPage->word32[tslkapTmp + tslkapInsertIndex] = slkapCopyPageptr.p->word32[tslkapTmp];
- }//for
-}//Dbacc::storeLongKeysAtPos
-
-/* --------------------------------------------------------------------------------- */
-/* STORE_LONG_KEYS */
-/* INPUT: SLK_PAGEPTR */
-/* SLK_COPY_PAGEPTR */
-/* TSLK_KEY_LEN */
-/* OUTPUT: TSLK_PAGE_INDEX */
-/* */
-/* DESCRIPTION: A LONG ELEMENT IS STORED ON A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::storeLongKeys(Signal* signal)
-{
- Uint32 tslkLastSize;
- Uint32 tslkInsertIndex;
- Uint32 tslkArrayPos;
- Uint32 tslkTmp;
- Uint32 guard27;
- LongKeyPage *slkPage;
-
- jam();
- slkPage = (LongKeyPage *) &slkPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(slkPageptr.i, "storeLongKeys1");
-#endif
-
- // Accept only page with free_area > tupkeylen, this leaves at least
- // one word for eventually an increase in the index area.
- ndbrequire(slkPage->header.freeArea > tslkKeyLen);
-
- dbgWord32(slkPageptr, ZPOS_LAST_INDEX, slkPage->header.highestIndex);
- dbgWord32(slkPageptr, ZPOS_INSERT_INDEX, slkPage->header.insertPos);
-
- tslkLastSize = ZWORDS_IN_PAGE - slkPage->header.highestIndex - slkPage->header.insertPos;
-
- if (tslkLastSize > operationRecPtr.p->tupkeylen) {
- // WE DO NOT NEED TO REORGANIZE THE PAGE TO INSERT THE NEW KEY. IT FITS INTO THE
- // SIZE REMAINING AT THE END.
- jam();
- } else {
- // THE KEY FITS INTO THE PAGE BUT ONLY AFTER REORGANISING THE PAGE.
- jam();
- relpPageptr.p = slkPageptr.p;
- reorgLongPage(signal);
- }//if
-
- if (slkPage->header.nextFreeIndex == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE INDEX HAS NO EMPTY SLOTS. WE MUST EXTEND THE PAGE INDEX BY ONE NEW SLOT.*/
- /* --------------------------------------------------------------------------------- */
- tslkPageIndex = slkPage->header.highestIndex + 1;
- } else {
- jam();
- tslkPageIndex = slkPage->header.nextFreeIndex;
- }//if
-
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* ON LONG PAGES WE USE A PHYSIOLOGICAL LOGGING SCHEME. THIS MEANS THAT WE ONLY NEED*/
- /* TO SPECIFY WHICH INDEX TO DELETE IN ORDER TO UNDO THE CHANGES WE DO. THE */
- /* POSSIBLE REORGANISATION DO NOT CHANGE THE LOGICAL LAYOUT OF THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- datapageptr.p = slkPageptr.p;
- cundoElemIndex = tslkPageIndex;
- cundoinfolength = 0;
- undoWritingProcess(signal);
- }//if
-
- if (slkPage->header.nextFreeIndex == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE INDEX HAS NO EMPTY SLOTS. WE MUST EXTEND THE PAGE INDEX BY ONE NEW SLOT.*/
- /* --------------------------------------------------------------------------------- */
- dbgWord32(slkPageptr, ZPOS_LAST_INDEX, slkPage->header.highestIndex + 1);
- slkPage->header.highestIndex++;
- ndbrequire(slkPage->header.insertPos < (ZWORDS_IN_PAGE - slkPage->header.highestIndex));
- // Reset index. We have already checked that we can increase "highestIndex" value
- // without overwriting the data part.
- slkPage->word32[ZWORDS_IN_PAGE - slkPage->header.highestIndex] = 0;
- dbgWord32(slkPageptr, ZPOS_FREE_AREA_IN_PAGE, slkPage->header.freeArea - 1);
- slkPage->header.freeArea--;
- } else {
- jam();
- dbgWord32(slkPageptr, ZPOS_NEXT_FREE_INDEX, slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex]);
- arrGuard(ZWORDS_IN_PAGE - tslkPageIndex, 2048);
- arrGuard(slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex], 2048);
-
- slkPage->header.nextFreeIndex = slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex];
- if(slkPage->header.nextFreeIndex > slkPage->header.highestIndex){
- slkPage->header.nextFreeIndex = 0;
- dbgWord32(slkPageptr, ZPOS_NEXT_FREE_INDEX, slkPage->header.nextFreeIndex);
- }
- }//if
-
- dbgWord32(slkPageptr, ZWORDS_IN_PAGE - tslkPageIndex, tslkKeyLen);
- dbgWord32(slkPageptr, ZWORDS_IN_PAGE - tslkPageIndex, slkPage->header.insertPos);
- arrGuard(ZWORDS_IN_PAGE - tslkPageIndex, 2048);
- slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex] =
- slkPage->header.insertPos | (tslkKeyLen << 16);
-
- dbgWord32(slkPageptr, ZPOS_INSERT_INDEX, slkPage->header.insertPos);
- tslkInsertIndex = slkPage->header.insertPos;
- slkPage->header.insertPos += tslkKeyLen;
-
- dbgWord32(slkPageptr, ZPOS_FREE_AREA_IN_PAGE, slkPage->header.freeArea - tslkKeyLen);
- slkPage->header.freeArea = slkPage->header.freeArea - tslkKeyLen;
- if (slkPage->header.freeArea < 128) {
- jam();
- tslkArrayPos = 4;
- } else {
- jam();
- tslkArrayPos = (slkPage->header.freeArea - 128) / 512;
- }//if
-
- if (tslkArrayPos != slkPage->header.pageArrayPos) {
- jam();
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE ONLY HANDLE THE LISTS WHEN WE ARE NOT IN A SYSTEM RESTART. */
- /* --------------------------------------------------------------------------------- */
- rfpPageptr = slkPageptr;
- trfpArrayPos = slkPage->header.pageArrayPos;
- removeFromPageArrayList(signal);
- ipaPagePtr = slkPageptr;
- tipaArrayPos = tslkArrayPos;
- slkPage->header.pageArrayPos = tipaArrayPos;
- if (tslkArrayPos != 4) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE WILL STILL BE ON ONE OF THE FREE LISTS SINCE AT LEAST 128 * 4 */
- /* BYTES OF FREE SPACE REMAINS ON THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- insertPageArrayList(signal);
- }//if
- } else {
- // This should never happen. Should use storeLongKeysAtPos() instead when executing
- // undolog.
- ndbrequire(false);
- }
- }//if
- /* --------------------------------------------------------------------------------- */
- /* INCREASE THE NUMBER OF ELEMENTS IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(slkPageptr, ZPOS_NO_ELEM_IN_PAGE, slkPage->header.noOfElements + 1);
- slkPage->header.noOfElements++;
-
- guard27 = tslkKeyLen - 1;
- arrGuard(guard27 + tslkInsertIndex, 2048);
- for (tslkTmp = 0; tslkTmp <= guard27; tslkTmp++) {
- dbgWord32(slkPageptr, tslkTmp + tslkInsertIndex, slkCopyPageptr.p->word32[tslkTmp]);
- slkPage->word32[tslkTmp + tslkInsertIndex] = slkCopyPageptr.p->word32[tslkTmp];
- }//for
-
- // Used by abortoperation() in case of an abort.
- operationRecPtr.p->longPagePtr = slkPageptr.i;
-
- // This is for an eventual LCP start in the middle of this locked operation.
- operationRecPtr.p->longKeyPageIndex = tslkPageIndex;
-
-#ifdef VM_TRACE
- if (cundoLogActive != ZTRUE) checkPageArrayList(signal, "storeLongKeys");
- checkIndexInLongKeyPage(slkPageptr.i, "storeLongKeys2");
-#endif
-
-}//Dbacc::storeLongKeys()
-
-/* --------------------------------------------------------------------------------- */
-/* REORGANIZE THE PAGE BY COPYING IT TEMPORARILY TO A NEW AREA AND THEN SIMPLY */
-/* PUTTING THE OBJECTS BACK ON THE PAGE IN THE SAME ORDER AS THEY ARE PLACED IN THE */
-/* INDEX. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::reorgLongPage(Signal* signal)
-{
- Uint32 indexStartPos;
- Uint32 pagePos;
- Uint32 pagePos2;
- Uint32 indexNo;
- Uint32 insertPos;
- Uint32 indexValue;
- Uint32 keyLength;
- Uint32 keyPos;
- Uint32 keyEndPos;
- LongKeyPage *reOrgPage;
-
- ptrGuard(relpPageptr);
- reOrgPage = (LongKeyPage *) &relpPageptr.p->word32[0];
-
- dbgWord32(relpPageptr, ZPOS_LAST_INDEX, reOrgPage->header.highestIndex);
- indexStartPos = ZWORDS_IN_PAGE - reOrgPage->header.highestIndex;
-
- // Copy key data part of page to a temporary page.
- for (pagePos = ZHEAD_SIZE; pagePos < indexStartPos; pagePos++) {
- jam();
- arrGuard(pagePos, 2048);
- ckeys[pagePos] = reOrgPage->word32[pagePos];
- }//for
-
- insertPos = ZHEAD_SIZE;
-
- // Walk through all the indexes.
- for (indexNo = 1; indexNo <= reOrgPage->header.highestIndex; indexNo++) {
- jam();
- arrGuard(ZWORDS_IN_PAGE - indexNo, 2048);
- dbgWord32(relpPageptr, ZWORDS_IN_PAGE - indexNo, reOrgPage->word32[ZWORDS_IN_PAGE - indexNo]);
- indexValue = reOrgPage->word32[ZWORDS_IN_PAGE - indexNo];
-
- if ((indexValue >> 16) != 0) {
- // The index contains a reference to a key.
- jam();
- keyPos = indexValue & 0xffff;
- keyLength = indexValue >> 16;
- dbgWord32(relpPageptr, ZWORDS_IN_PAGE - indexNo, insertPos + (keyLength << 16));
- arrGuard(ZWORDS_IN_PAGE - indexNo, 2048);
-
- // Refresh the index data with the new key start position in the data part.
- reOrgPage->word32[ZWORDS_IN_PAGE - indexNo] = insertPos + (keyLength << 16);
- keyEndPos = keyPos + keyLength;
- arrGuard(keyEndPos, 2048);
-
- // Copy the key from the temporary page
- // to the insert position at original page.
- for (pagePos2 = keyPos; pagePos2 < keyEndPos; pagePos2++, insertPos++) {
- jam();
- dbgWord32(relpPageptr, insertPos, ckeys[pagePos2]);
- arrGuard(insertPos, 2048);
- arrGuard(pagePos2, 2048);
- reOrgPage->word32[insertPos] = ckeys[pagePos2];
- }//for
- }//if
- }//for
- dbgWord32(relpPageptr, ZPOS_INSERT_INDEX, insertPos);
- reOrgPage->header.insertPos = insertPos;
-}//Dbacc::reorgLongPage()
-
-
-/* --------------------------------------------------------------------------------- */
-/* DELETE_LONG_KEY */
-/* INPUT: DLK_PAGEPTR PAGE POINTER OF DELETED KEY OBJECT */
-/* TDLK_LOGICAL_PAGE_INDEX LOGICAL PAGE INDEX OF DELETED KEY OBJECT */
-/* */
-/* DESCRIPTION: DELETE AN ELEMENT OF A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::deleteLongKey(Signal* signal)
-{
- Uint32 tdlkLastIndex;
- Uint32 tdlkNextPosition;
- Uint32 tdlkFreeArea;
- Uint32 tdlkArrayPos;
- Uint32 tdlkOldArrayPos;
- LongKeyPage *dlkPage;
-
- jam();
- dlkPage = (LongKeyPage *) &dlkPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(dlkPageptr.i, "deleteLongKey1");
-#endif
-
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] >> 16);
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] & 0xffff);
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
-
- const Uint32 tdlkIndexValue = dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex];
- const Uint32 tdlkKeyLen = tdlkIndexValue >> 16;
- const Uint32 tdlkPhysPageIndex = tdlkIndexValue & 0xffff;
-
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE LOG THE DELETE LONG KEY BY LOGGING THE DELETED KEY AND ITS LOGICAL INDEX.*/
- /* --------------------------------------------------------------------------------- */
- datapageptr.p = dlkPageptr.p;
- cundoElemIndex = tdlkLogicalPageIndex;
- cundoinfolength = tdlkKeyLen;
- undoWritingProcess(signal);
- }//if
- /* --------------------------------------------------------------------------------- */
- /* DECREASE THE NUMBER OF ELEMENTS IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_NO_ELEM_IN_PAGE, dlkPage->header.noOfElements - 1);
- dlkPage->header.noOfElements--;
-
- arrGuard(dlkPage->header.noOfElements, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
-
- /* --------------------------------------------------------------------------------- */
- /* INCREASE THE FREE AREA IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_FREE_AREA_IN_PAGE, dlkPage->header.freeArea + tdlkKeyLen);
- dbgWord32(dlkPageptr, ZPOS_LAST_INDEX, dlkPage->header.highestIndex);
-
- dlkPage->header.freeArea += tdlkKeyLen;
-
- if (dlkPage->header.noOfElements == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE IS NOW EMPTY, WE CAN RELEASE IT. */
- /* --------------------------------------------------------------------------------- */
- if (dlkPage->header.freeArea !=
- (ZWORDS_IN_PAGE - ZHEAD_SIZE - dlkPage->header.highestIndex )) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* SOME AREA IN THE PAGE IS STILL LEFT BUT NO ELEMENTS, INCONSISTENT */
- /* --------------------------------------------------------------------------------- */
- sendSystemerror(signal);
- }//if
- /* --------------------------------------------------------------------------------- */
- /* WE REMOVE THE PAGE FROM THE LIST OF FREE LONG PAGES. THERE IS NO RISK THAT IT */
- /* DID NOT BELONG TO ANY SINCE IT IS NOT ALLOWED TO HAVE THAT LARGE KEYS. */
- /* --------------------------------------------------------------------------------- */
-
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WHEN DELETING KEYS DURING SYSTEM RESTART WE NEED NOT UPDATE THE LISTS. */
- /* --------------------------------------------------------------------------------- */
- // REMOVEFROMLIST is done by releaseLongPage(). EDTJAMO.
- // rfpPageptr = dlkPageptr;
- // trfpArrayPos = dlkPage->header.pageArrayPos;
- // removeFromPageArrayList(signal, "deleteLongKey");
- rlopPageptr = dlkPageptr;
- releaseLongPage(signal);
- return;
- } else {
- // Must remove reference to the removed key, otherwise left in index. EDTJAMO.
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
- arrGuard(tdlkLogicalPageIndex, 2048);
-
- tdlkNextPosition = dlkPage->header.nextFreeIndex;
- dlkPage->header.nextFreeIndex = tdlkLogicalPageIndex;
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, tdlkNextPosition);
- dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] = tdlkNextPosition;
- }
- } else {
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE IS NOT EMPTY SO WE WILL REMOVE THE KEY OBJECT AND UPDATE THE */
- /* HEADER INFORMATION AND PLACE THE PAGE IN THE PROPER PAGE LIST. */
- /* --------------------------------------------------------------------------------- */
- tdlkLastIndex = dlkPage->header.highestIndex;
- arrGuard(ZWORDS_IN_PAGE - tdlkLastIndex, 2048);
- if (tdlkLastIndex == tdlkLogicalPageIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE DELETE THE LAST PAGE INDEX SO WE NEED TO UPDATE THE VALUE. WE MOVE */
- /* BACKWARDS UNTIL WE EITHER FIND A USED INDEX OR THAT WE COME TO INDEX ZERO. */
- /* --------------------------------------------------------------------------------- */
- tdlkLastIndex--;
- while( (tdlkLastIndex > 1) &&
- (dlkPage->word32[ZWORDS_IN_PAGE - tdlkLastIndex] >> 16) == 0 ) {
- jam();
- tdlkLastIndex--;
- }
- //-----------------------------------------------------
- // Reorganize the rest of the index. Set up the free
- // list and the free index.
- //-----------------------------------------------------
- UintR dlkTmp = tdlkLastIndex;
- dlkPage->header.nextFreeIndex = 0;
- while( dlkTmp > 0) {
- if ( (dlkPage->word32[ZWORDS_IN_PAGE - dlkTmp] >> 16) == 0 ) {
- jam();
- dlkPage->word32[ZWORDS_IN_PAGE - dlkTmp] = dlkPage->header.nextFreeIndex;
- arrGuard(dlkTmp, 2048);
- dlkPage->header.nextFreeIndex = dlkTmp;
- }
- dlkTmp--;
- }
- //-----------------------------------------------------
- // Update free area in page and last index.
- //-----------------------------------------------------
- dbgWord32(dlkPageptr, ZPOS_LAST_INDEX, tdlkLastIndex);
- dlkPage->header.highestIndex = tdlkLastIndex;
- dlkPage->header.freeArea = tdlkLogicalPageIndex +
- dlkPage->header.freeArea - tdlkLastIndex;
- tdlkNextPosition = 0;
- } else {
- if (dlkPage->header.highestIndex > tdlkLogicalPageIndex) {
- jam();
- tdlkNextPosition = dlkPage->header.nextFreeIndex;
- dbgWord32(dlkPageptr, ZPOS_NEXT_FREE_INDEX, tdlkLogicalPageIndex);
- arrGuard(tdlkLogicalPageIndex, 2048);
- dlkPage->header.nextFreeIndex = tdlkLogicalPageIndex;
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* LOGICAL PAGE INDEX LARGER THAN LARGEST INDEX, INCONSISTENT. */
- /* --------------------------------------------------------------------------------- */
- sendSystemerror(signal);
- return; // Just to keep compiler happy
- }//if
- }//if
- /* --------------------------------------------------------------------------------- */
- /* WE INSERT ZERO INTO THE LENGTH PART TO INDICATE A FREE INDEX POSITION. */
- /* WE INSERT A POINTER TO THE NEXT FREE INDEX TO AS TO PUT IT INTO A FREE */
- /* LIST OF INDEX POSITIONS. WE ONLY DO SO IF IT WAS NOT THE LAST INDEX. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, tdlkNextPosition);
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
- dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] = tdlkNextPosition;
- if (dlkPage->header.insertPos == (tdlkPhysPageIndex + tdlkKeyLen)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THIS ENTRY IS THE LAST ON THE PAGE SO WE WILL UPDATE THE INSERT INDEX */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_INSERT_INDEX, tdlkPhysPageIndex);
- dlkPage->header.insertPos = tdlkPhysPageIndex;
- }//if
- }//if
- dbgWord32(dlkPageptr, ZPOS_FREE_AREA_IN_PAGE, dlkPage->header.freeArea);
- tdlkFreeArea = dlkPage->header.freeArea;
- ndbrequire(tdlkFreeArea <= (ZWORDS_IN_PAGE - ZHEAD_SIZE));
- if (tdlkFreeArea < 128) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* FREE AREA IS STILL LESS THAN 128 WORDS SO IT SHOULD NOT BE PLACED IN ANY OF THE */
- /* FREE LISTS. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_ARRAY_POS, dlkPage->header.pageArrayPos);
- ndbrequire(dlkPage->header.pageArrayPos == 4);
- } else {
- jam();
- // Calculate an eventually new arraypos.
- dbgWord32(dlkPageptr, 0, (tdlkFreeArea - 128) / 512);
- tdlkArrayPos = (tdlkFreeArea - 128) / 512;
-
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WHEN DELETING KEYS DURING SYSTEM RESTART WE NEED NOT UPDATE THE LISTS. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_ARRAY_POS, dlkPage->header.pageArrayPos);
- tdlkOldArrayPos = dlkPage->header.pageArrayPos;
- if (tdlkArrayPos != tdlkOldArrayPos) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE NEW MEMORY AREA HAS ENABLED THE PAGE TO MOVE TO A NEW FREE PAGE LIST */
- /* --------------------------------------------------------------------------------- */
- rfpPageptr = dlkPageptr;
- trfpArrayPos = tdlkOldArrayPos;
- if (tdlkOldArrayPos != 4) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THERE WAS A FREE PAGE LIST TO REMOVE THE PAGE FROM. IF FREE SPACE IS LESS THAN */
- /* 128 BYTES THEN IT IS NOT ON ANY FREE LIST. */
- /* --------------------------------------------------------------------------------- */
- removeFromPageArrayList(signal);
- }//if
- dlkPage->header.pageArrayPos = tdlkArrayPos;
- ipaPagePtr = dlkPageptr;
- tipaArrayPos = tdlkArrayPos;
- insertPageArrayList(signal);
- }//if
- } else {
- // Update pageArrayPos. We are in a SR, executing undolog, insertPageArrayList() called
- // from execACC_OVER_REC needs this value later.
- dlkPage->header.pageArrayPos = tdlkArrayPos;
- }
- }//if
-#ifdef VM_TRACE
- if (cundoLogActive != ZTRUE) checkPageArrayList(signal, "deleteLongKey");
- checkIndexInLongKeyPage(dlkPageptr.i, "deleteLongKey2");
-#endif
-}//Dbacc::deleteLongKey()
-
-
-void Dbacc::checkIndexInLongKeyPage(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- LongKeyPage *page;
- Uint32 indexNo;
- Uint32 indexValue;
- Uint32 keyLength;
- Uint32 keyPos;
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- // Check the header variables.
- if (page->header.nextFreeIndex > 2048 ||
- page->header.highestIndex > 2048 ||
- page->header.insertPos > 2048 ||
- page->header.freeArea > 2048 ||
- page->header.noOfElements > 225) {
- ndbout << " ERROR in checkIndexInLongKeyPage, called from " << calledFrom << endl
- << " pagePtr.i = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Walk through all the indexes.
- for (indexNo = 1; indexNo <= page->header.highestIndex; indexNo++) {
- jam();
- indexValue = page->word32[ZWORDS_IN_PAGE - indexNo];
-
- if ((indexValue >> 16) == 0) {
- ; // key length is 0, means no key reference at this position in index.
- } else {
- // The index contains a reference to a key.
- jam();
- keyPos = indexValue & 0xffff;
- keyLength = indexValue >> 16;
- if (keyPos >= ZWORDS_IN_PAGE || keyLength >= ZWORDS_IN_PAGE) {
- jam();
- ndbout << " ERROR in checkIndexInLongKeyPage, called from " << calledFrom << endl
- << " keyPos = " << keyPos << endl
- << " keyLength = " << keyLength << endl
- << " page->header.noOfElements = " << page->header.noOfElements << endl
- << " page->header.freeArea = " << page->header.freeArea << endl
- << " indexNo = " << indexNo << endl
- << " page->header.highestIndex = " << page->header.highestIndex << endl;
- ndbrequire(false);
- }
- }
- }
-}//Dbacc::checkIndexInLongKeyPage
-
-
-/* --------------------------------------------------------------------------------- */
-/* REMOVE A PAGE FROM THE PAGE ARRAY LIST. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::removeFromPageArrayList(Signal* signal)
-{
- Page8Ptr rfpPrevPageptr;
- Page8Ptr rfpNextPageptr;
- LongKeyPage *page;
- LongKeyPage *prevPage;
- LongKeyPage *nextPage;
-
- jam();
-
-#ifdef VM_TRACE
- checkPageB4Remove(rfpPageptr.i, "removeFromPageArrayList");
-#endif
-
- page = (LongKeyPage *) &rfpPageptr.p->word32[0];
-
- if (page->header.prevPage == RNIL) {
- jam();
- arrGuard(trfpArrayPos, 4);
- // This page was first in list, remove reference
- // to this page from the start of the list.
- ndbrequire(fragrecptr.p->longKeyPageArray[trfpArrayPos] == rfpPageptr.i);
- fragrecptr.p->longKeyPageArray[trfpArrayPos] = page->header.nextPage;
- } else {
- jam();
- rfpPrevPageptr.i = page->header.prevPage;
- ptrCheckGuard(rfpPrevPageptr, cpagesize, page8);
- prevPage = (LongKeyPage *) &rfpPrevPageptr.p->word32[0];
- // This page wasn't first in list, remove reference
- // to this page from the previous page.
- ndbrequire(prevPage->header.nextPage == rfpPageptr.i);
- prevPage->header.nextPage = page->header.nextPage;
- }//if
-
- if (page->header.nextPage != RNIL) {
- jam();
- rfpNextPageptr.i = page->header.nextPage;
- ptrCheckGuard(rfpNextPageptr, cpagesize, page8);
- nextPage = (LongKeyPage *) &rfpNextPageptr.p->word32[0];
- // This page wasn't last in list, remove reference
- // to this page from the next page.
- ndbrequire(nextPage->header.prevPage == rfpPageptr.i);
- nextPage->header.prevPage = page->header.prevPage;
- // Remove reference to next page in list.
- page->header.nextPage = RNIL;
- }//if
-
- // This couldn't be set until now.
- // Remove reference to previous page in list.
- page->header.prevPage = RNIL;
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "removeFromPageArrayList");
-#endif
-}//Dbacc::removeFromPageArrayList()
-
-/* --------------------------------------------------------------------------------- */
-/* INSERT A PAGE INTO THE PAGE ARRAY LIST. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::insertPageArrayList(Signal* signal)
-{
- Page8Ptr ipaNextPagePtr;
- LongKeyPage *page;
- LongKeyPage *nextPage;
-
- jam();
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "insertPageArrayList1");
- checkPageB4Insert(ipaPagePtr.i, "insertPageArrayList1");
-#endif
-
- page = (LongKeyPage *) &ipaPagePtr.p->word32[0];
-
- arrGuard(tipaArrayPos, 4);
-
- if (fragrecptr.p->longKeyPageArray[tipaArrayPos] != RNIL) {
- jam();
- ipaNextPagePtr.i = fragrecptr.p->longKeyPageArray[tipaArrayPos];
- ptrCheckGuard(ipaNextPagePtr, cpagesize, page8);
- nextPage = (LongKeyPage *) &ipaNextPagePtr.p->word32[0];
-
- // A page already existed in the list, add reference
- // to this page in the next page.
- nextPage->header.prevPage = ipaPagePtr.i;
- }//if
-
- page->header.prevPage = RNIL;
- page->header.nextPage = fragrecptr.p->longKeyPageArray[tipaArrayPos];
- page->header.pageArrayPos = tipaArrayPos;
-
- fragrecptr.p->longKeyPageArray[tipaArrayPos] = ipaPagePtr.i;
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "insertPageArrayList2");
-#endif
-}//Dbacc::insertPageArrayList()
-
-// --------------------------------------------------------------------------------- */
-// Check the page array list.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageArrayList(Signal* signal, const char *calledFrom)
-{
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- LongKeyPage *page;
- Uint32 prevPage;
-
- // Go through the longKeyPageArray and search for a page.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
- prevPage = RNIL;
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- if ((page->header.freeArea >= 128) &&
- (((page->header.freeArea - 128) / 512) == page->header.pageArrayPos) &&
- (pageArrayIndex == page->header.pageArrayPos) &&
- (page->header.prevPage == prevPage)) {
- // The page found is OK, test next page.
- prevPage = pagePtr.i;
- pagePtr.i = page->header.nextPage;
- jam();
- } else {
- jam();
- ndbout << " ERROR in checkPageArrayList, called from " << calledFrom << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " prevPage = " << prevPage << endl
- << " pageArrayIndex = " << pageArrayIndex << endl;
- printoutInfoAndShutdown(page);
- }
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-}//Dbacc::checkPageArrayList()
-
-// --------------------------------------------------------------------------------- */
-// Check the page to put into the pageArrayList.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageB4Insert(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- LongKeyPage *page;
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- if ((page->header.nextPage != RNIL) ||
- (page->header.prevPage != RNIL)) {
- jam();
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " page->header.nextPage = " << page->header.nextPage << endl
- << " page->header.prevPage = " << page->header.prevPage << endl;
- ndbrequire(false);
- }
-
- // Page should not be inserted in list if free area is less than 512 byte.
- if (page->header.freeArea < 128) {
- jam();
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " Page has to little free area to be in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " tipaArrayPos = " << tipaArrayPos << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Check if position in list is correct
- if ((((page->header.freeArea - 128) / 512) != page->header.pageArrayPos) ||
- (page->header.pageArrayPos != tipaArrayPos)) {
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " Incorrect position in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " tipaArrayPos = " << tipaArrayPos << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Check if page is already in list.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- if (pagePtr.i == pageId) {
- jam();
- ndbout << "ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << "Page exists already in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl;
- printoutInfoAndShutdown(page);
- }
- pagePtr.i = page->header.nextPage;
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-}//Dbacc::checkPageB4Insert()
-
-// --------------------------------------------------------------------------------- */
-// Check the page to remove from the pageArrayList.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageB4Remove(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- Uint32 noOfOccurrence = 0;
- Uint32 noOfPagesInList = 0;
- LongKeyPage *page;
-
- LongKeyPage *prevPage;
- LongKeyPage *nextPage;
- Page8Ptr rfpPrevPageptr;
- Page8Ptr rfpNextPageptr;
-
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- // Check that page is in list.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- noOfPagesInList++;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- if (pagePtr.i == pageId) {
- // Check the consistent in list.
- if (page->header.prevPage != RNIL) {
- rfpPrevPageptr.i = page->header.prevPage;
- ptrCheckGuard(rfpPrevPageptr, cpagesize, page8);
- prevPage = (LongKeyPage *) &rfpPrevPageptr.p->word32[0];
- if (prevPage->header.nextPage != pageId) {
- ndbout << "ERROR: inconsistent in checkPageB4Remove, called from " << calledFrom << endl
- << "prevPage->header.nextPage = " << prevPage->header.nextPage << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
- }
- // Check the consistent in list.
- if (page->header.nextPage != RNIL) {
- rfpNextPageptr.i = page->header.nextPage;
- ptrCheckGuard(rfpNextPageptr, cpagesize, page8);
- nextPage = (LongKeyPage *) &rfpNextPageptr.p->word32[0];
- if (nextPage->header.prevPage != pageId) {
- ndbout << "ERROR: inconsistent in checkPageB4Remove, called from " << calledFrom << endl
- << "nextPage->header.prevPage = " << nextPage->header.prevPage << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
- }
- jam();
- noOfOccurrence++;
- }
- pagePtr.i = page->header.nextPage;
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-
- if (noOfOccurrence != 1) {
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- ndbout << "ERROR in checkPageB4Remove, called from " << calledFrom << endl
- << "Page occur " << noOfOccurrence << " times in list" << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
-}//Dbacc::checkPageB4Remove()
-
-
-// --------------------------------------------------------------------------------- */
-// Printout an error message and shutdown node.
-// --------------------------------------------------------------------------------- */
-void Dbacc::printoutInfoAndShutdown(LongKeyPage *page) {
- ndbout << " page->header.pageArrayPos = " << page->header.pageArrayPos << endl
- << " ((page->header.freeArea - 128) / 512) = "
- << ((page->header.freeArea - 128) / 512) << endl
- << " page->header.freeArea = " << page->header.freeArea << endl
- << " page->header.noOfElements = " << page->header.noOfElements << endl
- << " page->header.nextPage = " << page->header.nextPage << endl
- << " page->header.prevPage = " << page->header.prevPage << endl
- << " page->header.nextFreeIndex = " << page->header.nextFreeIndex << endl
- << " page->header.insertPos = " << page->header.insertPos << endl
- << " page->header.highestIndex = " << page->header.highestIndex << endl
- << " page->header.pageId = " << page->header.pageId << endl;
- ndbrequire(false);
-}//Dbacc::printoutInfoAndShutdown()
-
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
@@ -4419,7 +3173,7 @@ void Dbacc::printoutInfoAndShutdown(LongKeyPage *page) {
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* */
-/* MODULE: READ */
+/* MODULE: GET_ELEMENT */
/* THE FOLLOWING SUBROUTINES ARE ONLY USED BY GET_ELEMENT AND */
/* GETDIRINDEX. THIS ROUTINE IS THE SOLE INTERFACE TO GET ELEMENTS */
/* FROM THE INDEX. CURRENT USERS ARE ALL REQUESTS AND EXECUTE UNDO LOG */
@@ -4480,6 +3234,21 @@ void Dbacc::getdirindex(Signal* signal)
ptrCheckGuard(gdiPageptr, cpagesize, page8);
}//Dbacc::getdirindex()
+Uint32
+Dbacc::readTablePk(Uint32 localkey1)
+{
+ Uint32 tableId = fragrecptr.p->myTableId;
+ Uint32 fragId = fragrecptr.p->myfid;
+ Uint32 fragPageId = localkey1 >> MAX_TUPLES_BITS;
+ Uint32 pageIndex = localkey1 & ((1 << MAX_TUPLES_BITS ) - 1);
+#ifdef VM_TRACE
+ memset(ckeys, 0x1f, (fragrecptr.p->keyLength * MAX_XFRM_MULTIPLY) << 2);
+#endif
+ int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, ckeys, true);
+ ndbrequire(ret > 0);
+ return ret;
+}
+
/* --------------------------------------------------------------------------------- */
/* GET_ELEMENT */
/* INPUT: */
@@ -4521,7 +3290,6 @@ void Dbacc::getElement(Signal* signal)
Uint32 tgeNextptrtype;
register Uint32 tgeKeyptr;
register Uint32 tgeRemLen;
- register Uint32 tgeCompareLen;
register Uint32 TelemLen = fragrecptr.p->elementLength;
register Uint32* Tkeydata = (Uint32*)&signal->theData[7];
@@ -4529,20 +3297,15 @@ void Dbacc::getElement(Signal* signal)
tgePageindex = tgdiPageindex;
gePageptr = gdiPageptr;
tgeResult = ZFALSE;
- tgeCompareLen = fragrecptr.p->keyLength;
- const Uint32 isAccLockReq = operationRecPtr.p->isAccLockReq;
- if (isAccLockReq) {
- jam();
- tgeCompareLen = 0;
- }
+ /*
+ * The value seached is
+ * - table key for ACCKEYREQ, stored in TUP
+ * - local key (1 word) for ACC_LOCKREQ and UNDO, stored in ACC
+ */
+ const bool searchLocalKey =
+ operationRecPtr.p->isAccLockReq || operationRecPtr.p->isUndoLogReq;
- // We can handle keylength up to 8, but not more (0 means dynamic)
- if (tgeCompareLen >= 9) {
- ACCKEY_error(2); return;
- }//if
- if (TelemLen < 3) {
- ACCKEY_error(3); return;
- }//if
+ ndbrequire(TelemLen == ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen);
tgeNextptrtype = ZLEFT;
tgeLocked = 0;
@@ -4573,7 +3336,7 @@ void Dbacc::getElement(Signal* signal)
} else {
ACCKEY_error(6); return;
}//if
- if (tgeRemLen >= TelemLen) {
+ if (tgeRemLen >= ZCON_HEAD_SIZE + TelemLen) {
if (tgeRemLen > ZBUF_SIZE) {
ACCKEY_error(7); return;
}//if
@@ -4581,151 +3344,46 @@ void Dbacc::getElement(Signal* signal)
// There is at least one element in this container. Check if it is the element
// searched for.
/* --------------------------------------------------------------------------------- */
- if (tgeCompareLen != 0) {
- /* --------------------------------------------------------------------------------- */
- /* THIS PART IS USED TO SEARCH FOR KEYS WITH FIXED SIZE. THE LOOP TAKES CARE */
- /* OF SEARCHING THROUGH ALL ELEMENTS IN ONE CONTAINER. */
- /* --------------------------------------------------------------------------------- */
- do {
- register Uint32 TdataIndex = 0;
- register Uint32 TgeIndex = 0;
+ do {
+ tgeElementHeader = gePageptr.p->word32[tgeElementptr];
+ tgeRemLen = tgeRemLen - TelemLen;
+ Uint32 hashValuePart;
+ if (ElementHeader::getLocked(tgeElementHeader)) {
jam();
- tgeRemLen = tgeRemLen - TelemLen;
- do {
- if (gePageptr.p->word32[tgeKeyptr + TgeIndex] != Tkeydata[TdataIndex]) {
- goto compare_next;
- }//if
- TdataIndex++;
- TgeIndex += tgeForward;
- } while (TdataIndex < tgeCompareLen);
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */
- /* --------------------------------------------------------------------------------- */
+ geTmpOperationRecPtr.i = ElementHeader::getOpPtrI(tgeElementHeader);
+ ptrCheckGuard(geTmpOperationRecPtr, coprecsize, operationrec);
+ hashValuePart = geTmpOperationRecPtr.p->hashvaluePart;
+ } else {
jam();
-#if __ia64 == 1
-#if __INTEL_COMPILER == 810
- // prevents SIGSEGV under icc -O1
- ndb_acc_ia64_icc810_dummy_func();
-#endif
-#endif
- tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]);
- tgeResult = ZTRUE;
- TdataIndex = tgeElementptr + tgeForward;
- TgeIndex = TdataIndex + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TdataIndex];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TgeIndex];
- return;
- /* --------------------------------------------------------------------------------- */
- /* COMPARE NEXT ELEMENT */
- /* --------------------------------------------------------------------------------- */
- compare_next:
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeKeyptr = tgeKeyptr + tgeElemStep;
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- } else if (! isAccLockReq) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THIS PART IS USED TO SEARCH FOR KEYS WITH VARIABLE LENGTH OR FIXED LENGTH */
- /* GREATER THAN 32 BYTES. IN THIS CASE THE KEY PART IS STORED IN A SPECIAL */
- /* LONG PAGE PART AND THE HASH INDEX CONTAINS A REFERENCE TO THERE PLUS A */
- /* PART OF THE HASH VALUE. */
- /* --------------------------------------------------------------------------------- */
- do {
- tgeElementHeader = gePageptr.p->word32[tgeElementptr];
- tgeRemLen = tgeRemLen - TelemLen;
- Uint32 hashValuePart;
- if (ElementHeader::getLocked(tgeElementHeader)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* IN THIS CASE THE HASH VALUE PART OF THE ELEMENT HEADER IS STORED IN THE */
- /* OPERATION THAT OWNS THE LOCK. IN THIS CASE WE MIGHT AS WELL GO AHEAD AND */
- /* CHECK THE KEY IN THE LONG PAGE. */
- /* --------------------------------------------------------------------------------- */
- geTmpOperationRecPtr.i =
- ElementHeader::getOpPtrI(tgeElementHeader);
- ptrCheckGuard(geTmpOperationRecPtr, coprecsize, operationrec);
- hashValuePart = geTmpOperationRecPtr.p->hashvaluePart;
+ hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
+ }
+ if (hashValuePart == opHashValuePart) {
+ jam();
+ Uint32 localkey1 = gePageptr.p->word32[tgeElementptr + tgeForward];
+ Uint32 localkey2 = 0;
+ bool found;
+ if (! searchLocalKey) {
+ Uint32 len = readTablePk(localkey1);
+ found = (len == operationRecPtr.p->xfrmtupkeylen) &&
+ (memcmp(Tkeydata, ckeys, len << 2) == 0);
} else {
jam();
- /* --------------------------------------------------------------------------------- */
- /* IN THIS CASE THE HASH VALUE PART CAN BE CHECKED TO SEE IF THE HASH VALUE */
- /* GIVES US A REASON TO CONTINUE CHECKING THE FULL KEY. */
- /* --------------------------------------------------------------------------------- */
- hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
- }//if
-
- if (hashValuePart == opHashValuePart) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* IF THE HASH VALUES ARE EQUAL THEN XOR-ING THEM WILL GIVE THE RESULT 0. */
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND A KEY WITH IDENTICAL HASH VALUE. MOST LIKELY WE HAVE FOUND THE*/
- /* ELEMENT BUT FIRST WE NEED TO PERFORM A KEY COMPARISON. */
- /* --------------------------------------------------------------------------------- */
- tslcPageIndex = gePageptr.p->word32[tgeKeyptr] & 0x3ff;
- tslcPagedir = gePageptr.p->word32[tgeKeyptr] >> 10;
- searchLongKey(signal, true);
- if (tslcResult == ZTRUE) {
- register Uint32 TlocData1, TlocData2;
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */
- /* --------------------------------------------------------------------------------- */
- tgeLocked = ElementHeader::getLocked(tgeElementHeader);
- tgeResult = ZTRUE;
- TlocData1 = tgeElementptr + tgeForward;
- TlocData2 = TlocData1 + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TlocData1];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TlocData2];
- return;
- }//if
+ found = (localkey1 == Tkeydata[0]);
}
- /* --------------------------------------------------------------------------------- */
- /* COMPARE NEXT ELEMENT */
- /* --------------------------------------------------------------------------------- */
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeKeyptr = tgeKeyptr + tgeElemStep;
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* Search for local key in a lock request */
- /* --------------------------------------------------------------------------------- */
- do {
- tgeRemLen = tgeRemLen - TelemLen;
- // position of local key word 1
- Uint32 TdataIndex = tgeElementptr + tgeForward;
- // XXX assume localkeylen is 1
- if (gePageptr.p->word32[TdataIndex] == Tkeydata[0]) {
+ if (found) {
jam();
- tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]);
+ tgeLocked = ElementHeader::getLocked(tgeElementHeader);
tgeResult = ZTRUE;
- // position of local key word 2
- Uint32 TgeIndex = TdataIndex + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TdataIndex];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TgeIndex];
-
- if (fragrecptr.p->keyLength == 0) {
- // set up long key variables in operation record
- tslcPageIndex = gePageptr.p->word32[tgeKeyptr] & 0x3ff;
- tslcPagedir = gePageptr.p->word32[tgeKeyptr] >> 10;
- // no verification since we have no key data
- searchLongKey(signal, false);
- }
+ operationRecPtr.p->localdata[0] = localkey1;
+ operationRecPtr.p->localdata[1] = localkey2;
return;
- }//if
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- }//if
+ }
+ }
+ if (tgeRemLen <= ZCON_HEAD_SIZE) {
+ break;
+ }
+ tgeElementptr = tgeElementptr + tgeElemStep;
+ } while (true);
}//if
if (tgeRemLen != ZCON_HEAD_SIZE) {
ACCKEY_error(8); return;
@@ -4756,71 +3414,6 @@ void Dbacc::getElement(Signal* signal)
}//Dbacc::getElement()
/* --------------------------------------------------------------------------------- */
-/* SEARCH_LONG_KEY */
-/* INPUT: */
-/* TSLC_PAGEDIR PAGE DIRECTORY OF LONG PAGE */
-/* TSLC_PAGE_INDEX PAGE INDEX IN LONG PAGE */
-/* GE_OPERATION_REC_PTR */
-/* OUTPUT: */
-/* TSLC_RESULT */
-/* DESCRIPTION: SEARCH FOR AN ELEMENT IN A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::searchLongKey(Signal* signal, bool verify)
-{
- DirRangePtr slcOverflowrangeptr;
- DirectoryarrayPtr slcOverflowDirptr;
- Page8Ptr slcPageptr;
- Uint32 tslcIndexValue;
- Uint32 tslcStartIndex;
- Uint32 tslcIndex;
- Uint32 guard30;
- Uint32* Tkeydata = (Uint32*)&signal->theData[7];
-
-
- slcOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(slcOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tslcPagedir >> 8), 256);
- slcOverflowDirptr.i = slcOverflowrangeptr.p->dirArray[tslcPagedir >> 8];
- ptrCheckGuard(slcOverflowDirptr, cdirarraysize, directoryarray);
-
- // dbgWord32(slcOverflowDirptr, (int) (tslcPagedir & 0xff), slcOverflowDirptr.p->pagep[tslcPagedir & 0xff]);
-
- slcPageptr.i = slcOverflowDirptr.p->pagep[tslcPagedir & 0xff];
- ptrCheckGuard(slcPageptr, cpagesize, page8);
- arrGuard(ZWORDS_IN_PAGE - tslcPageIndex, 2048);
- dbgWord32(slcPageptr, ZWORDS_IN_PAGE - tslcPageIndex, (int)slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex] & 0xffff);
- dbgWord32(slcPageptr, ZWORDS_IN_PAGE - tslcPageIndex, slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex] >> 16);
- tslcIndexValue = slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex];
- if (verify) {
- if ((tslcIndexValue >> 16) != operationRecPtr.p->tupkeylen) {
- jam();
- tslcResult = ZFALSE;
- return;
- }//if
- }
- tslcStartIndex = tslcIndexValue & 0xffff;
- guard30 = operationRecPtr.p->tupkeylen - 1;
- arrGuard(guard30, 2048);
- arrGuard(guard30 + tslcStartIndex, 2048);
- if (verify) {
- for (tslcIndex = 0; tslcIndex <= guard30; tslcIndex++) {
- dbgWord32(slcPageptr, tslcIndex + tslcStartIndex, slcPageptr.p->word32[tslcIndex + tslcStartIndex]);
- if (slcPageptr.p->word32[tslcIndex + tslcStartIndex] != Tkeydata[tslcIndex]) {
- jam();
- tslcResult = ZFALSE;
- return;
- }//if
- }//for
- }
- jam();
- tslcResult = ZTRUE;
- operationRecPtr.p->longPagePtr = slcPageptr.i;
- operationRecPtr.p->longKeyPageIndex = tslcPageIndex;
- arrGuard(tslcPageIndex, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
- arrGuard(slcPageptr.i, cpagesize);
-}//Dbacc::searchLongKey()
-
-/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* */
@@ -4863,13 +3456,6 @@ void Dbacc::commitdelete(Signal* signal, bool systemRestart)
EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 4);
jamEntry();
}//if
- if (fragrecptr.p->keyLength == 0) {
- jam();
- tdlkLogicalPageIndex = operationRecPtr.p->longKeyPageIndex;
- dlkPageptr.i = operationRecPtr.p->longPagePtr;
- ptrCheckGuard(dlkPageptr, cpagesize, page8);
- deleteLongKey(signal);
- }//if
getdirindex(signal);
tlastPageindex = tgdiPageindex;
lastPageptr.i = gdiPageptr.i;
@@ -5428,50 +4014,6 @@ void Dbacc::checkoverfreelist(Signal* signal)
}//if
}//Dbacc::checkoverfreelist()
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_LONG_PAGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseLongPage(Signal* signal)
-{
- DirRangePtr rlpOverflowrangeptr;
- DirectoryarrayPtr rlpOverflowDirptr;
- Uint32 trlpTmp1;
- Uint32 trlpTmp2;
- Uint32 trlpTmp3;
-
- jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = rlopPageptr.p->word32[ZPOS_PAGE_ID];
- sorOverflowRecPtr.p->overpage = RNIL;
- priOverflowRecPtr = sorOverflowRecPtr;
- putRecInFreeOverdir(signal);
- trlpTmp1 = sorOverflowRecPtr.p->dirindex;
- rlpOverflowrangeptr.i = fragrecptr.p->overflowdir;
- trlpTmp2 = trlpTmp1 >> 8;
- trlpTmp3 = trlpTmp1 & 0xff;
- ptrCheckGuard(rlpOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard(trlpTmp2, 256);
- rlpOverflowDirptr.i = rlpOverflowrangeptr.p->dirArray[trlpTmp2];
- ptrCheckGuard(rlpOverflowDirptr, cdirarraysize, directoryarray);
- rlpOverflowDirptr.p->pagep[trlpTmp3] = RNIL;
-
- if (cundoLogActive != ZTRUE) {
- // Remove from page array.
- trfpArrayPos = rlopPageptr.p->word32[ZPOS_ARRAY_POS];
- rfpPageptr = rlopPageptr;
- removeFromPageArrayList(signal);
- }
-
- // Reset page header
- iloPageptr = rlopPageptr;
- tiloIndex = rlopPageptr.p->word32[ZPOS_PAGE_ID];
- initLongOverpage(signal);
-
- rpPageptr = rlopPageptr;
- releasePage(signal);
-}//Dbacc::releaseLongPage()
-
-
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
@@ -6162,16 +4704,16 @@ Uint32 Dbacc::executeNextOperation(Signal* signal)
else if(operationRecPtr.p->operation == ZWRITE)
{
jam();
- operationRecPtr.p->operation = ZINSERT;
+ operationRecPtr.p->operation = ZUPDATE;
if (operationRecPtr.p->prevParallelQue != RNIL) {
OperationrecPtr prevOpPtr;
jam();
prevOpPtr.i = operationRecPtr.p->prevParallelQue;
ptrCheckGuard(prevOpPtr, coprecsize, operationrec);
- if (prevOpPtr.p->operation != ZDELETE)
+ if (prevOpPtr.p->operation == ZDELETE)
{
jam();
- operationRecPtr.p->operation = ZUPDATE;
+ operationRecPtr.p->operation = ZINSERT;
}
}
}
@@ -6779,14 +5321,8 @@ void Dbacc::expandcontainer(Signal* signal)
Uint32 texcHashvalue;
Uint32 texcTmp;
Uint32 texcIndex;
- Uint32 texpKeyLen;
Uint32 guard20;
- texpKeyLen = fragrecptr.p->keyLength;
- if (texpKeyLen == 0) {
- jam();
- texpKeyLen = ZACTIVE_LONG_KEY_LEN;
- }//if
cexcPrevpageptr = RNIL;
cexcPrevconptr = 0;
cexcForward = ZTRUE;
@@ -6873,18 +5409,10 @@ void Dbacc::expandcontainer(Signal* signal)
clocalkey[texcIndex] = excPageptr.p->word32[texcTmp];
texcTmp = texcTmp + cexcForward;
}//for
- guard20 = texpKeyLen - 1;
- for (texcIndex = 0; texcIndex <= guard20; texcIndex++) {
- arrGuard(texcIndex, 2048);
- arrGuard(texcTmp, 2048);
- ckeys[texcIndex] = excPageptr.p->word32[texcTmp];
- texcTmp = texcTmp + cexcForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = texpKeyLen;
insertElement(signal);
fragrecptr.p->expReceiveIndex = tidrPageindex;
fragrecptr.p->expReceivePageptr = idrPageptr.i;
@@ -6966,17 +5494,10 @@ void Dbacc::expandcontainer(Signal* signal)
clocalkey[texcIndex] = lastPageptr.p->word32[texcTmp];
texcTmp = texcTmp + tlastForward;
}//for
- for (texcIndex = 0; texcIndex < texpKeyLen; texcIndex++) {
- arrGuard(texcIndex, 2048);
- arrGuard(texcTmp, 2048);
- ckeys[texcIndex] = lastPageptr.p->word32[texcTmp];
- texcTmp = texcTmp + tlastForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = texpKeyLen;
insertElement(signal);
fragrecptr.p->expReceiveIndex = tidrPageindex;
fragrecptr.p->expReceivePageptr = idrPageptr.i;
@@ -7457,18 +5978,12 @@ void Dbacc::shrinkcontainer(Signal* signal)
Uint32 tshrElementptr;
Uint32 tshrRemLen;
Uint32 tshrInc;
- Uint32 tshrKeyLen;
Uint32 tshrTmp;
Uint32 tshrIndex;
Uint32 guard21;
tshrRemLen = cexcContainerlen - ZCON_HEAD_SIZE;
- tshrKeyLen = fragrecptr.p->keyLength;
- if (tshrKeyLen == 0) {
- jam();
- tshrKeyLen = ZACTIVE_LONG_KEY_LEN;
- }//if
- tshrInc = (ZELEM_HEAD_SIZE + tshrKeyLen) + fragrecptr.p->localkeylen;
+ tshrInc = fragrecptr.p->elementLength;
if (cexcForward == ZTRUE) {
jam();
tshrElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
@@ -7517,18 +6032,10 @@ void Dbacc::shrinkcontainer(Signal* signal)
clocalkey[tshrIndex] = excPageptr.p->word32[tshrTmp];
tshrTmp = tshrTmp + cexcForward;
}//for
- guard21 = tshrKeyLen - 1;
- for (tshrIndex = 0; tshrIndex <= guard21; tshrIndex++) {
- arrGuard(tshrIndex, 2048);
- arrGuard(tshrTmp, 2048);
- ckeys[tshrIndex] = excPageptr.p->word32[tshrTmp];
- tshrTmp = tshrTmp + cexcForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = tshrKeyLen;
insertElement(signal);
/* --------------------------------------------------------------------------------- */
/* TAKE CARE OF RESULT FROM INSERT_ELEMENT. */
@@ -8256,14 +6763,6 @@ void Dbacc::saveOverPagesLab(Signal* signal)
jam();
ropPageptr = sopPageptr;
releaseOverpage(signal);
- } else if (((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) ==
- ZLONG_PAGE_TYPE) {
- //----------------------------------------------------------------------
- // The long key page is empty, release it.
- //----------------------------------------------------------------------
- jam();
- rlopPageptr = sopPageptr;
- releaseLongPage(signal);
} else {
jam();
sendSystemerror(signal);
@@ -8655,66 +7154,63 @@ void Dbacc::lcpCopyPage(Signal* signal)
}//for
}//for
tlcnChecksum = Tchs;
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZLONG_PAGE_TYPE) {
- jam();
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
- jam();
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
- /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
- /* HEADER OF 2 WORDS. */
- /*-----------------------------------------------------------------*/
- tlcnConIndex = ZHEAD_SIZE;
- tlupForward = 1;
- for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- lcpUpdatePage(signal);
- tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
- }//for
- }//if
+ if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
+ jam();
/*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
+ /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
+ /* HEADER OF 2 WORDS. */
/*-----------------------------------------------------------------*/
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlcnConIndex = ZHEAD_SIZE;
+ tlupForward = 1;
+ for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
tlupIndex = tlcnConIndex;
tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- tlupForward = 1;
lcpUpdatePage(signal);
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- sendSystemerror(signal);
- return;
- }//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
- /*-----------------------------------------------------------------*/
- tlupForward = cminusOne;
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex - 1;
- lcpUpdatePage(signal);
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- sendSystemerror(signal);
- return;
- }//if
+ tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
+ }//for
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
+ tlupForward = 1;
+ lcpUpdatePage(signal);
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ sendSystemerror(signal);
+ return;
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlupForward = cminusOne;
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex - 1;
+ lcpUpdatePage(signal);
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ sendSystemerror(signal);
+ return;
}//if
lcnCopyPageptr.p->word32[ZPOS_CHECKSUM] = tlcnChecksum;
}//Dbacc::lcpCopyPage()
@@ -8775,78 +7271,75 @@ void Dbacc::srCheckPage(Signal* signal)
Uint32 tlcnIndex;
lupPageptr.p = lcnCopyPageptr.p;
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZLONG_PAGE_TYPE) {
- jam();
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
- jam();
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
- /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
- /* HEADER OF 2 WORDS. */
- /*-----------------------------------------------------------------*/
- tlcnConIndex = ZHEAD_SIZE;
- tlupForward = 1;
- for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
- }//for
- }//if
+ if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
+ jam();
/*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
+ /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
+ /* HEADER OF 2 WORDS. */
/*-----------------------------------------------------------------*/
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlcnConIndex = ZHEAD_SIZE;
+ tlupForward = 1;
+ for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
tlupIndex = tlcnConIndex;
tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- tlupForward = 1;
srCheckContainer(signal);
if (tresult != 0) {
jam();
return;
}//if
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
+ tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
+ }//for
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
+ tlupForward = 1;
+ srCheckContainer(signal);
+ if (tresult != 0) {
jam();
- tresult = 4;
return;
}//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
- /*-----------------------------------------------------------------*/
- tlupForward = cminusOne;
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex - 1;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ tresult = 4;
+ return;
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlupForward = cminusOne;
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex - 1;
+ srCheckContainer(signal);
+ if (tresult != 0) {
jam();
- tresult = 4;
return;
}//if
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ tresult = 4;
+ return;
}//if
}//Dbacc::srCheckPage()
@@ -9030,50 +7523,14 @@ void Dbacc::undoWritingProcess(Signal* signal)
writeUndoDataInfo(signal);
checkUndoPages(signal);
}//if
- } else if (tpageType != ZLONG_PAGE_TYPE) {
+ } else {
jam();
/* --------------------------------------------------------------------------- */
/* ONLY PAGE INFO AND OVERFLOW PAGE INFO CAN BE LOGGED BY THIS ROUTINE. A */
/* SERIOUS ERROR. */
/* --------------------------------------------------------------------------- */
sendSystemerror(signal);
- } else {
- /* --------------------------------------------------------------------------------- */
- /* THIS LOG RECORD IS GENERATED ON A LONG KEY PAGE. THESE PAGES USE LOGICAL */
- /* LOGGING. */
- /* --------------------------------------------------------------------------------- */
- if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW PAGES SINCE THE */
- /* START OF THE LOCAL CHECKPOINT. WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID*/
- /* NOT EXIST AT START OF LCP. */
- /* --------------------------------------------------------------------------------- */
- /*empty*/;
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* LOGICAL LOGGING OF LONG KEY PAGES CAN EITHER BE UNDO OF AN INSERT OR UNDO */
- /* OF A DELETE KEY. UNDO OF DELETE NEEDS TO LOG THE KEY TO BE REINSERTED WHILE */
- /* UNDO OF INSERT ONLY NEEDS TO LOG THE INDEX TO BE DELETED. */
- /* --------------------------------------------------------------------------------- */
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- if (cundoinfolength == 0) {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_INSERT_LONG_KEY);
- } else {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_DELETE_LONG_KEY);
- arrGuard(ZWORDS_IN_PAGE - cundoElemIndex, 2048);
- tundoElemIndex = datapageptr.p->word32[ZWORDS_IN_PAGE - cundoElemIndex] & 0xffff;
- writeUndoDataInfo(signal);
- }//if
- checkUndoPages(signal);
- }//if
- }//if
+ }
} else {
if (fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) {
jam();
@@ -9108,46 +7565,7 @@ void Dbacc::undoWritingProcess(Signal* signal)
checkUndoPages(signal);
}//if
}//if
- } else if (tpageType == ZLONG_PAGE_TYPE) {
- if (tactivePageDir < fragrecptr.p->lcpDirIndex) {
- jam();
- // -------------------------------------------------------------
- // THIS PAGE HAS ALREADY BEEN WRITTEN IN THE LOCAL CHECKPOINT.
- // -------------------------------------------------------------
- } else {
- if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) {
- jam();
- // -------------------------------------------------------------
- // OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW
- // PAGES SINCE THE START OF THE LOCAL CHECKPOINT. WE NEED NOT
- // LOG ANY UPDATES OF PAGES THAT DID NOT EXIST AT START OF LCP.
- // -------------------------------------------------------------
- } else {
- jam();
- // -------------------------------------------------------------
- // LOGICAL LOGGING OF LONG KEY PAGES CAN EITHER BE UNDO OF AN
- // INSERT OR UNDO OF A DELETE KEY. UNDO OF DELETE NEEDS TO LOG
- // THE KEY TO BE REINSERTED WHILE UNDO OF INSERT ONLY NEEDS TO
- // LOG THE INDEX TO BE DELETED.
- // -------------------------------------------------------------
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- if (cundoinfolength == 0) {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_INSERT_LONG_KEY);
- } else {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_DELETE_LONG_KEY);
- arrGuard(ZWORDS_IN_PAGE - cundoElemIndex, 2048);
- tundoElemIndex = datapageptr.p->word32[ZWORDS_IN_PAGE - cundoElemIndex] & 0xffff;
- writeUndoDataInfo(signal);
- }//if
- checkUndoPages(signal);
- }//if
- }//if
- }//if
+ }
}//if
}//if
}//Dbacc::undoWritingProcess()
@@ -9200,8 +7618,9 @@ void Dbacc::writeUndoHeader(Signal* signal,
(UndoHeader *) &undopageptr.p->undoword[theadundoindex];
undoHeaderPtr->tableId = rootfragrecptr.p->mytabptr;
- undoHeaderPtr->rootFragId = rootfragrecptr.p->fragmentid[0];
+ undoHeaderPtr->rootFragId = rootfragrecptr.p->fragmentid[0] >> 1;
undoHeaderPtr->localFragId = fragrecptr.p->myfid;
+ ndbrequire((undoHeaderPtr->localFragId >> 1) == undoHeaderPtr->rootFragId);
Uint32 Ttmp = cundoinfolength;
Ttmp = (Ttmp << 4) + pageType;
Ttmp = Ttmp << 14;
@@ -9231,52 +7650,16 @@ void Dbacc::writeUndoOpInfo(Signal* signal)
undopageptr.p->undoword[tundoindex + 1] = operationRecPtr.p->hashValue;
undopageptr.p->undoword[tundoindex + 2] = operationRecPtr.p->tupkeylen;
tundoindex = tundoindex + 3;
- if (fragrecptr.p->keyLength != 0) {
- // Fixed size keys
- jam();
- locPageptr.i = operationRecPtr.p->elementPage;
- ptrCheckGuard(locPageptr, cpagesize, page8);
- Uint32 Tforward = operationRecPtr.p->elementIsforward;
- Uint32 TelemPtr = operationRecPtr.p->elementPointer;
- TelemPtr += Tforward;
- TelemPtr += Tforward;
- //---------------------------------------------------------------------------------
- // Now the pointer is at the start of the key part of the element. Now copy from there
- // to the UNDO log.
- //---------------------------------------------------------------------------------
- Uint32 keyLen = operationRecPtr.p->tupkeylen;
- ndbrequire(keyLen <= 8);
- arrGuard(tundoindex+keyLen, 8192);
- for (Uint32 twuoiIndex = 0; twuoiIndex < keyLen; twuoiIndex++) {
- jam();
- arrGuard(TelemPtr, 2048);
- undopageptr.p->undoword[tundoindex] = locPageptr.p->word32[TelemPtr];
- tundoindex++;
- TelemPtr += Tforward;
- }//for
- cundoinfolength = ZOP_HEAD_INFO_LN + operationRecPtr.p->tupkeylen;
- } else {
- // Long keys
- jam();
-
- arrGuard(operationRecPtr.p->longKeyPageIndex, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
- locPageptr.i = operationRecPtr.p->longPagePtr;
- ptrCheckGuard(locPageptr, cpagesize, page8);
-
- Uint32 indexValue =
- locPageptr.p->word32[ZWORDS_IN_PAGE - operationRecPtr.p->longKeyPageIndex];
- Uint32 keyLen = indexValue >> 16;
- Uint32 physPageIndex = indexValue & 0xffff;
- ndbrequire(keyLen == operationRecPtr.p->tupkeylen);
-
- arrGuard(tundoindex+keyLen, 8192);
- arrGuard(physPageIndex+keyLen, 2048);
- for (Uint32 i = 0; i < keyLen; i++){
- undopageptr.p->undoword[tundoindex + i] = locPageptr.p->word32[physPageIndex+i];
- }
- tundoindex = tundoindex + keyLen;
- cundoinfolength = ZOP_HEAD_INFO_LN + keyLen;
- }//if
+ // log localkey1
+ locPageptr.i = operationRecPtr.p->elementPage;
+ ptrCheckGuard(locPageptr, cpagesize, page8);
+ Uint32 Tforward = operationRecPtr.p->elementIsforward;
+ Uint32 TelemPtr = operationRecPtr.p->elementPointer;
+ TelemPtr += Tforward; // ZELEM_HEAD_SIZE
+ arrGuard(tundoindex+1, 8192);
+ undopageptr.p->undoword[tundoindex] = locPageptr.p->word32[TelemPtr];
+ tundoindex++;
+ cundoinfolength = ZOP_HEAD_INFO_LN + 1;
}//Dbacc::writeUndoOpInfo()
/* --------------------------------------------------------------------------------- */
@@ -9460,7 +7843,7 @@ void Dbacc::initFragAdd(Signal* signal,
}//if
regFragPtr.p->fragState = ACTIVEFRAG;
// NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ
- regFragPtr.p->myfid = (rootFragIndex << (lhFragBits - 1)) | req->fragId;
+ regFragPtr.p->myfid = (req->fragId << 1) | rootFragIndex;
regFragPtr.p->myroot = rootIndex;
regFragPtr.p->myTableId = req->tableId;
ndbrequire(req->kValue == 6);
@@ -9488,17 +7871,16 @@ void Dbacc::initFragAdd(Signal* signal,
regFragPtr.p->dirsize = 1;
regFragPtr.p->loadingFlag = ZFALSE;
regFragPtr.p->keyLength = req->keyLength;
- if (req->keyLength == 0) {
- jam();
- regFragPtr.p->elementLength = (1 + ZELEM_HEAD_SIZE) + regFragPtr.p->localkeylen;
- } else {
- jam();
- regFragPtr.p->elementLength = (ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen) + regFragPtr.p->keyLength;
- }//if
+ ndbrequire(req->keyLength != 0);
+ regFragPtr.p->elementLength = ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen;
Uint32 Tmp1 = (regFragPtr.p->maxp + 1) + regFragPtr.p->p;
Uint32 Tmp2 = regFragPtr.p->maxloadfactor - regFragPtr.p->minloadfactor;
Tmp2 = Tmp1 * Tmp2;
regFragPtr.p->slackCheck = Tmp2;
+
+ Uint32 hasCharAttr = g_key_descriptor_pool.getPtr(req->tableId)->hasCharAttr;
+ regFragPtr.p->hasCharAttr = hasCharAttr;
+
}//Dbacc::initFragAdd()
void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
@@ -9518,6 +7900,7 @@ void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
regFragPtr.p->activeDataPage = 0;
regFragPtr.p->createLcp = ZFALSE;
regFragPtr.p->stopQueOp = ZFALSE;
+ regFragPtr.p->hasCharAttr = ZFALSE;
regFragPtr.p->nextAllocPage = 0;
regFragPtr.p->nrWaitWriteUndoExit = 0;
regFragPtr.p->lastUndoIsStored = ZFALSE;
@@ -10103,7 +8486,7 @@ void Dbacc::startUndoLab(Signal* signal)
}//for
// Send report of how many undo log records where executed
- signal->theData[0] = EventReport::UNDORecordsExecuted;
+ signal->theData[0] = NDB_LE_UNDORecordsExecuted;
signal->theData[1] = DBACC; // From block
signal->theData[2] = 0; // Total records executed
for (int i = 0; i < 10; i++){
@@ -10296,6 +8679,7 @@ void Dbacc::srDoUndoLab(Signal* signal)
// ROOT FRAGMENT ID
tfid = undoHeaderPtr->rootFragId;
+ ndbrequire((undoHeaderPtr->localFragId >> 1) == undoHeaderPtr->rootFragId);
if (!getrootfragmentrec(signal, rootfragrecptr, tfid)) {
jam();
/*---------------------------------------------------------------------*/
@@ -10305,7 +8689,10 @@ void Dbacc::srDoUndoLab(Signal* signal)
creadyUndoaddress = cprevUndoaddress;
// PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS
cprevUndoaddress = undoHeaderPtr->prevUndoAddress;
- undoNext2Lab(signal);
+ undoNext2Lab(signal);
+#ifdef VM_TRACE
+ ndbout_c("ignoring root fid %d", (int)tfid);
+#endif
return;
}//if
/*-----------------------------------------------------------------------*/
@@ -10415,103 +8802,6 @@ void Dbacc::srDoUndoLab(Signal* signal)
break;
}
- case UndoHeader::ZUNDO_INSERT_LONG_KEY:{
- jam();
- /*---------------------------------------------------------------------*/
- /* WE WILL UNDO AN INSERT OF A LONG KEY. THIS IS PERFORMED BY DELETING */
- /* THE LONG KEY. */
- /*---------------------------------------------------------------------*/
- souDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- arrGuard(tmpP2, 256);
- ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange);
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(souDirptr, cdirarraysize, directoryarray);
- dlkPageptr.i = souDirptr.p->pagep[tmpP];
- ptrCheckGuard(dlkPageptr, cpagesize, page8);
- tdlkLogicalPageIndex = tundoPageindex;
- deleteLongKey(signal);
- break;
- }
-
- case UndoHeader::ZUNDO_DELETE_LONG_KEY: {
- jam();
- /*----------------------------------------------------------------------*/
- /* WE WILL UNDO DELETE OF A LONG KEY. THIS IS PERFORMED BY INSERTING */
- /* IT AGAIN. */
- /*----------------------------------------------------------------------*/
- souDirRangePtr.i = fragrecptr.p->overflowdir;
- taslpDirIndex = tmpP;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
-
- if(souDirptr.i == RNIL) {
- //----------------------------------------------------------------
- // Allocate a directory.
- //----------------------------------------------------------------
- jam();
- seizeDirectory(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }
- souDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
- }
-
- ptrCheckGuard(souDirptr, cdirarraysize, directoryarray);
- slkapPageptr.i = souDirptr.p->pagep[tmpP];
-
- if(slkapPageptr.i == RNIL) {
- //----------------------------------------------------------------
- // The delete operation was probably the last on the page and the
- // page was released and not written down to disk. We need to
- // allocate a page and put it in the same dirindex as it was in
- // before it was released.
- // This is because an eventual UNDO_INSERT on the same key in the
- // same LCP must be able to find the key and it has only the
- // dirindex to go on, the key itself is not saved on disk in a
- // UNDO_INSERT.
- //----------------------------------------------------------------
- jam();
- allocSpecificLongOverflowPage(signal);
- slkapPageptr.i = aslpPageptr.i;
- }
-
- ptrCheckGuard(slkapPageptr, cpagesize, page8);
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
-
- slkapCopyPageptr = spPageptr;
- ndbrequire(cundoinfolength <= 2048);
-
- for (Uint32 tmp = 0; tmp < cundoinfolength; tmp++) {
- dbgWord32(slkapCopyPageptr, tmp, undopageptr.p->undoword[tmpindex]);
- slkapCopyPageptr.p->word32[tmp] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- }//for
- jam();
- //----------------------------------------------------------------
- // We must store the key at the same place it was deleted from.
- // This is because an eventual UNDO_INSERT on the same key in the
- // same LCP must be able to find the key and it has only the index
- // information stored on disk to go on, the key itself is not
- // saved on disk in an UNDO_INSERT.
- //----------------------------------------------------------------
- tslkapKeyLen = cundoinfolength;
- tslkapPageIndex = tundoPageindex;
- storeLongKeysAtPos(signal);
-
- rpPageptr = slkapCopyPageptr;
- releasePage(signal);
- break;
- }
-
case UndoHeader::ZOP_INFO: {
jam();
/*---------------------------------------------------------------------*/
@@ -10550,6 +8840,7 @@ void Dbacc::srDoUndoLab(Signal* signal)
operationRecPtr.p->longKeyPageIndex = RNIL;
operationRecPtr.p->scanRecPtr = RNIL;
operationRecPtr.p->isAccLockReq = ZFALSE;
+ operationRecPtr.p->isUndoLogReq = ZTRUE;
// Read operation values from undo page
operationRecPtr.p->operation = undopageptr.p->undoword[tmpindex];
@@ -10559,17 +8850,15 @@ void Dbacc::srDoUndoLab(Signal* signal)
const Uint32 tkeylen = undopageptr.p->undoword[tmpindex];
tmpindex++;
operationRecPtr.p->tupkeylen = tkeylen;
+ operationRecPtr.p->xfrmtupkeylen = 0; // not used
operationRecPtr.p->fragptr = fragrecptr.i;
- ndbrequire((fragrecptr.p->keyLength == 0) ||
- ((fragrecptr.p->keyLength != 0) &&
- (fragrecptr.p->keyLength == tkeylen)));
+ ndbrequire(fragrecptr.p->keyLength != 0 &&
+ fragrecptr.p->keyLength == tkeylen);
- // Read keydata from undo page
- for (Uint32 tmp = 0; tmp < tkeylen; tmp++) {
- signal->theData[7+tmp] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- }//for
+ // Read localkey1 from undo page
+ signal->theData[7 + 0] = undopageptr.p->undoword[tmpindex];
+ tmpindex = tmpindex + 1;
arrGuard((tmpindex - 1), 8192);
getElement(signal);
if (tgeResult != ZTRUE) {
@@ -10752,43 +9041,25 @@ void Dbacc::execACC_OVER_REC(Signal* signal)
ptrCheckGuard(pnoPageidptr, cpagesize, page8);
tpnoPageType = pnoPageidptr.p->word32[ZPOS_PAGE_TYPE];
tpnoPageType = (tpnoPageType >> ZPOS_PAGE_TYPE_BIT) & 3;
- if (tpnoPageType == ZLONG_PAGE_TYPE) {
+ if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
jam();
- // This is to clean the list parameters.
- pnoPageidptr.p->word32[ZPOS_PREV_PAGE] = RNIL;
- pnoPageidptr.p->word32[ZPOS_NEXT_PAGE] = RNIL;
- if (pnoPageidptr.p->word32[ZPOS_ARRAY_POS] != 4) {
- jam();
- /*---------------------------------------------------------------------------*/
- /* THE PAGE WAS A LONG PAGE AND IT BELONGED TO A FREE LIST. PUT IT INTO ONE */
- /* OF THE FREE LIST THEN. */
- /*---------------------------------------------------------------------------*/
- // Insert page!
- ipaPagePtr = pnoPageidptr;
- tipaArrayPos = pnoPageidptr.p->word32[ZPOS_ARRAY_POS];
- insertPageArrayList(signal);
- }//if
+ dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, RNIL);
+ pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
+ ndbrequire(pnoPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage);
} else {
- if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
- jam();
- dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, RNIL);
- pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- ndbrequire(pnoPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage);
- } else {
+ jam();
+ seizeOverRec(signal);
+ sorOverflowRecPtr.p->dirindex = pnoPageidptr.p->word32[ZPOS_PAGE_ID];
+ ndbrequire(sorOverflowRecPtr.p->dirindex == fragrecptr.p->nextAllocPage);
+ dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
+ pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
+ sorOverflowRecPtr.p->overpage = pnoPageidptr.i;
+ porOverflowRecPtr = sorOverflowRecPtr;
+ putOverflowRecInFrag(signal);
+ if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0) {
jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = pnoPageidptr.p->word32[ZPOS_PAGE_ID];
- ndbrequire(sorOverflowRecPtr.p->dirindex == fragrecptr.p->nextAllocPage);
- dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
- pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
- sorOverflowRecPtr.p->overpage = pnoPageidptr.i;
- porOverflowRecPtr = sorOverflowRecPtr;
- putOverflowRecInFrag(signal);
- if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0) {
- jam();
- ropPageptr = pnoPageidptr;
- releaseOverpage(signal);
- }//if
+ ropPageptr = pnoPageidptr;
+ releaseOverpage(signal);
}//if
}//if
}//if
@@ -10863,7 +9134,6 @@ void Dbacc::execACC_SCANREQ(Signal* signal)
rootfragrecptr.p->scan[i] = scanPtr.i;
scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
scanPtr.p->scanLockMode = AccScanReq::getLockMode(tscanFlag);
- scanPtr.p->scanKeyinfoFlag = AccScanReq::getKeyinfoFlag(tscanFlag);
scanPtr.p->scanReadCommittedFlag = AccScanReq::getReadCommittedFlag(tscanFlag);
/* TWELVE BITS OF THE ELEMENT HEAD ARE SCAN */
@@ -11611,11 +9881,6 @@ void Dbacc::initScanOpRec(Signal* signal)
Uint32 tisoTmp;
Uint32 tisoLocalPtr;
Uint32 guard24;
- Uint32 tisoPageIndex;
- Uint32 tisoPagedir;
- DirRangePtr tisoOverflowrangeptr;
- DirectoryarrayPtr tisoOverflowDirptr;
- Page8Ptr tisoPageptr;
scanPtr.p->scanOpsAllocated++;
@@ -11644,6 +9909,7 @@ void Dbacc::initScanOpRec(Signal* signal)
operationRecPtr.p->elementPointer = tisoElementptr;
operationRecPtr.p->elementPage = isoPageptr.i;
operationRecPtr.p->isAccLockReq = ZFALSE;
+ operationRecPtr.p->isUndoLogReq = ZFALSE;
tisoLocalPtr = tisoElementptr + tisoIsforward;
guard24 = fragrecptr.p->localkeylen - 1;
for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) {
@@ -11654,40 +9920,8 @@ void Dbacc::initScanOpRec(Signal* signal)
}//for
arrGuard(tisoLocalPtr, 2048);
operationRecPtr.p->keydata[0] = isoPageptr.p->word32[tisoLocalPtr];
- if (fragrecptr.p->keyLength != 0) {
- jam();
- operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
- guard24 = fragrecptr.p->keyLength - 1;
- for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) {
- arrGuard(tisoTmp, 8);
- arrGuard(tisoLocalPtr, 2048);
- operationRecPtr.p->keydata[tisoTmp] = isoPageptr.p->word32[tisoLocalPtr];
- tisoLocalPtr = tisoLocalPtr + tisoIsforward;
- }//for
- } else {
- // Long key handling. Put the long key reference in the operation records.
- tisoPageIndex = operationRecPtr.p->keydata[0] & 0x3ff;
- arrGuard(ZWORDS_IN_PAGE - tisoPageIndex, 2048);
-
- tisoPagedir = operationRecPtr.p->keydata[0] >> 10;
- arrGuard((tisoPagedir >> 8), 256);
-
- tisoOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(tisoOverflowrangeptr, cdirrangesize, dirRange);
-
- tisoOverflowDirptr.i = tisoOverflowrangeptr.p->dirArray[tisoPagedir >> 8];
- ptrCheckGuard(tisoOverflowDirptr, cdirarraysize, directoryarray);
-
- tisoPageptr.i = tisoOverflowDirptr.p->pagep[tisoPagedir & 0xff];
- ptrCheckGuard(tisoPageptr, cpagesize, page8);
-
- operationRecPtr.p->longPagePtr = tisoPageptr.i;
- operationRecPtr.p->longKeyPageIndex = tisoPageIndex;
-
- // Read length of key from page
- Uint32 tmp = tisoPageptr.p->word32[ZWORDS_IN_PAGE - tisoPageIndex];
- operationRecPtr.p->tupkeylen = tmp >> 16;
- }
+ operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
+ operationRecPtr.p->xfrmtupkeylen = 0; // not used
}//Dbacc::initScanOpRec()
/* --------------------------------------------------------------------------------- */
@@ -11882,21 +10116,15 @@ void Dbacc::releaseScanContainer(Signal* signal)
Uint32 trscElemlens;
Uint32 trscElemlen;
- if (trscContainerlen < 5) {
+ if (trscContainerlen < 4) {
if (trscContainerlen != ZCON_HEAD_SIZE) {
jam();
sendSystemerror(signal);
}//if
- return; /* 3 IS THE MINIMUM SIZE OF THE ELEMENT */
- }//if
- trscElemlens = trscContainerlen - 2;
- if (fragrecptr.p->keyLength != 0) {
- jam();
- trscElemlen = (1 + fragrecptr.p->keyLength) + fragrecptr.p->localkeylen; /* LENGTH OF THE ELEMENT */
- } else {
- jam();
- trscElemlen = (1 + ZACTIVE_LONG_KEY_LEN) + fragrecptr.p->localkeylen; /* LENGTH OF THE ELEMENT */
+ return; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
}//if
+ trscElemlens = trscContainerlen - ZCON_HEAD_SIZE;
+ trscElemlen = fragrecptr.p->elementLength;
if (trscIsforward == 1) {
jam();
trscElementptr = trscContainerptr + ZCON_HEAD_SIZE;
@@ -11923,7 +10151,7 @@ void Dbacc::releaseScanContainer(Signal* signal)
}//if
trscElemlens = trscElemlens - trscElemlen;
trscElementptr = trscElementptr + trscElemStep;
- } while (trscElemlens > 2);
+ } while (trscElemlens > 1);
if (trscElemlens != 0) {
jam();
sendSystemerror(signal);
@@ -11982,19 +10210,12 @@ bool Dbacc::searchScanContainer(Signal* signal)
Uint32 tsscElemlen;
Uint32 tsscElemStep;
- if (tsscContainerlen < 5) {
+ if (tsscContainerlen < 4) {
jam();
- return false; /* 3 IS THE MINIMUM SIZE OF THE ELEMENT */
+ return false; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
}//if
tsscElemlens = tsscContainerlen - ZCON_HEAD_SIZE;
- if (fragrecptr.p->keyLength == 0) {
- jam();
- tsscElemlen = (ZELEM_HEAD_SIZE + ZACTIVE_LONG_KEY_LEN) + fragrecptr.p->localkeylen;
- } else {
- jam();
- /* LENGTH OF THE ELEMENT */
- tsscElemlen = (ZELEM_HEAD_SIZE + fragrecptr.p->keyLength) + fragrecptr.p->localkeylen;
- }//if
+ tsscElemlen = fragrecptr.p->elementLength;
/* LENGTH OF THE ELEMENT */
if (tsscIsforward == 1) {
jam();
@@ -12032,7 +10253,7 @@ bool Dbacc::searchScanContainer(Signal* signal)
/* THE ELEMENT IS ALREADY SENT. */
/* SEARCH FOR NEXT ONE */
tsscElemlens = tsscElemlens - tsscElemlen;
- if (tsscElemlens > 2) {
+ if (tsscElemlens > 1) {
jam();
tsscElementptr = tsscElementptr + tsscElemStep;
goto SCANELEMENTLOOP001;
@@ -12047,172 +10268,20 @@ void Dbacc::sendNextScanConf(Signal* signal)
{
scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter;
Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
- if (!scanPtr.p->scanKeyinfoFlag){
- jam();
- /** ---------------------------------------------------------------------
- * LQH WILL NOT HAVE ANY USE OF THE TUPLE KEY LENGTH IN THIS CASE AND
- * SO WE DO NOT PROVIDE IT. IN THIS CASE THESE VALUES ARE UNDEFINED.
- * ---------------------------------------------------------------------- */
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = operationRecPtr.p->localdata[0];
- signal->theData[4] = operationRecPtr.p->localdata[1];
- signal->theData[5] = fragrecptr.p->localkeylen;
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 6);
- return;
- }//if
-
- if (fragrecptr.p->keyLength != 0) {
- jam();
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = operationRecPtr.p->localdata[0];
- signal->theData[4] = operationRecPtr.p->localdata[1];
- signal->theData[5] = fragrecptr.p->localkeylen;
- signal->theData[6] = fragrecptr.p->keyLength;
- signal->theData[7] = operationRecPtr.p->keydata[0];
- signal->theData[8] = operationRecPtr.p->keydata[1];
- signal->theData[9] = operationRecPtr.p->keydata[2];
- signal->theData[10] = operationRecPtr.p->keydata[3];
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 11);
- if (fragrecptr.p->keyLength > ZKEYINKEYREQ) {
- jam();
- /* = 4 */
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = fragrecptr.p->keyLength - ZKEYINKEYREQ;
- signal->theData[4] = operationRecPtr.p->keydata[4];
- signal->theData[5] = operationRecPtr.p->keydata[5];
- signal->theData[6] = operationRecPtr.p->keydata[6];
- signal->theData[7] = operationRecPtr.p->keydata[7];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO, signal, 8);
- return;
- }//if
- } else {
- jam();
- sendScaninfo(signal);
- return;
- }//if
-}//Dbacc::sendNextScanConf()
-
-/* --------------------------------------------------------------------------------- */
-/* SEND_SCANINFO */
-/* DESCRIPTION: SCAN AN ELEMENT OF A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::sendScaninfo(Signal* signal)
-{
- DirRangePtr ssiOverflowrangeptr;
- DirectoryarrayPtr ssiOverflowDirptr;
- Page8Ptr ssiPageptr;
- Uint32 tssiPageIndex;
- Uint32 tssiPagedir;
- Uint32 tssiKeyLen;
- Uint32 tssiStartIndex;
- Uint32 tssiIndexValue;
- Uint32 tssiTmp;
-
- Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
-
- tssiPageIndex = operationRecPtr.p->keydata[0] & 0x3ff;
- tssiPagedir = operationRecPtr.p->keydata[0] >> 10;
- ssiOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(ssiOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tssiPagedir >> 8), 256);
- ssiOverflowDirptr.i = ssiOverflowrangeptr.p->dirArray[tssiPagedir >> 8];
- ptrCheckGuard(ssiOverflowDirptr, cdirarraysize, directoryarray);
- ssiPageptr.i = ssiOverflowDirptr.p->pagep[tssiPagedir & 0xff];
- ptrCheckGuard(ssiPageptr, cpagesize, page8);
- arrGuard(ZWORDS_IN_PAGE - tssiPageIndex, 2048);
- tssiIndexValue = ssiPageptr.p->word32[ZWORDS_IN_PAGE - tssiPageIndex];
- tssiStartIndex = tssiIndexValue & 0xffff;
- tssiKeyLen = tssiIndexValue >> 16;
+ jam();
+ /** ---------------------------------------------------------------------
+ * LQH WILL NOT HAVE ANY USE OF THE TUPLE KEY LENGTH IN THIS CASE AND
+ * SO WE DO NOT PROVIDE IT. IN THIS CASE THESE VALUES ARE UNDEFINED.
+ * ---------------------------------------------------------------------- */
signal->theData[0] = scanPtr.p->scanUserptr;
signal->theData[1] = operationRecPtr.i;
signal->theData[2] = operationRecPtr.p->fid;
signal->theData[3] = operationRecPtr.p->localdata[0];
signal->theData[4] = operationRecPtr.p->localdata[1];
signal->theData[5] = fragrecptr.p->localkeylen;
- signal->theData[6] = tssiKeyLen;
- arrGuard(tssiStartIndex + 3, 2048);
- signal->theData[7] = ssiPageptr.p->word32[tssiStartIndex];
- signal->theData[8] = ssiPageptr.p->word32[tssiStartIndex + 1];
- signal->theData[9] = ssiPageptr.p->word32[tssiStartIndex + 2];
- signal->theData[10] = ssiPageptr.p->word32[tssiStartIndex + 3];
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 11);
- if (tssiKeyLen > 4) {
- tssiKeyLen = tssiKeyLen - 4;
- tssiStartIndex = tssiStartIndex + 4;
- SSI_LOOP_10:
- jamEntry();
- if (tssiKeyLen > ZMAXSCANSIGNALLEN) {
- jam();
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = ZMAXSCANSIGNALLEN;
- arrGuard(tssiStartIndex + 19, 2048);
- signal->theData[4] = ssiPageptr.p->word32[tssiStartIndex];
- signal->theData[5] = ssiPageptr.p->word32[tssiStartIndex + 1];
- signal->theData[6] = ssiPageptr.p->word32[tssiStartIndex + 2];
- signal->theData[7] = ssiPageptr.p->word32[tssiStartIndex + 3];
- signal->theData[8] = ssiPageptr.p->word32[tssiStartIndex + 4];
- signal->theData[9] = ssiPageptr.p->word32[tssiStartIndex + 5];
- signal->theData[10] = ssiPageptr.p->word32[tssiStartIndex + 6];
- signal->theData[11] = ssiPageptr.p->word32[tssiStartIndex + 7];
- signal->theData[12] = ssiPageptr.p->word32[tssiStartIndex + 8];
- signal->theData[13] = ssiPageptr.p->word32[tssiStartIndex + 9];
- signal->theData[14] = ssiPageptr.p->word32[tssiStartIndex + 10];
- signal->theData[15] = ssiPageptr.p->word32[tssiStartIndex + 11];
- signal->theData[16] = ssiPageptr.p->word32[tssiStartIndex + 12];
- signal->theData[17] = ssiPageptr.p->word32[tssiStartIndex + 13];
- signal->theData[18] = ssiPageptr.p->word32[tssiStartIndex + 14];
- signal->theData[19] = ssiPageptr.p->word32[tssiStartIndex + 15];
- signal->theData[20] = ssiPageptr.p->word32[tssiStartIndex + 16];
- signal->theData[21] = ssiPageptr.p->word32[tssiStartIndex + 17];
- signal->theData[22] = ssiPageptr.p->word32[tssiStartIndex + 18];
- signal->theData[23] = ssiPageptr.p->word32[tssiStartIndex + 19];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO24, signal, 24);
- tssiStartIndex = tssiStartIndex + ZMAXSCANSIGNALLEN;
- tssiKeyLen = tssiKeyLen - ZMAXSCANSIGNALLEN;
- goto SSI_LOOP_10;
- } else {
- jam();
- ndbrequire((tssiStartIndex + tssiKeyLen) <= 2048);
- for (tssiTmp = 0; tssiTmp < tssiKeyLen; tssiTmp++) {
- ckeys[tssiTmp] = ssiPageptr.p->word32[tssiStartIndex + tssiTmp];
- }//for
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- /* LOCAL FRAGMENT IDENTITY */
- signal->theData[3] = tssiKeyLen;
- signal->theData[4] = ckeys[0];
- signal->theData[5] = ckeys[1];
- signal->theData[6] = ckeys[2];
- signal->theData[7] = ckeys[3];
- signal->theData[8] = ckeys[4];
- signal->theData[9] = ckeys[5];
- signal->theData[10] = ckeys[6];
- signal->theData[11] = ckeys[7];
- signal->theData[12] = ckeys[8];
- signal->theData[13] = ckeys[9];
- signal->theData[14] = ckeys[10];
- signal->theData[15] = ckeys[11];
- signal->theData[16] = ckeys[12];
- signal->theData[17] = ckeys[13];
- signal->theData[18] = ckeys[14];
- signal->theData[19] = ckeys[15];
- signal->theData[20] = ckeys[16];
- signal->theData[21] = ckeys[17];
- signal->theData[22] = ckeys[18];
- signal->theData[23] = ckeys[19];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO24, signal, 24);
- }//if
- }//if
-}//Dbacc::sendScaninfo()
+ EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 6);
+ return;
+}//Dbacc::sendNextScanConf()
/*---------------------------------------------------------------------------
* sendScanHbRep
@@ -13265,7 +11334,7 @@ void Dbacc::takeRecOutOfFreeOverpage(Signal* signal)
void
Dbacc::reportMemoryUsage(Signal* signal, int gth){
- signal->theData[0] = EventReport::MemoryUsage;
+ signal->theData[0] = NDB_LE_MemoryUsage;
signal->theData[1] = gth;
signal->theData[2] = sizeof(* rpPageptr.p);
signal->theData[3] = cnoOfAllocatedPages;
@@ -13315,13 +11384,12 @@ Dbacc::execDUMP_STATE_ORD(Signal* signal)
scanPtr.p->minBucketIndexToRescan,
scanPtr.p->maxBucketIndexToRescan);
infoEvent(" scanBucketState=%d, scanLockHeld=%d, userBlockRef=%d, "
- "scanMask=%d scanLockMode=%d, keyInfoFlag=%d",
+ "scanMask=%d scanLockMode=%d",
scanPtr.p->scanBucketState,
scanPtr.p->scanLockHeld,
scanPtr.p->scanUserblockref,
scanPtr.p->scanMask,
- scanPtr.p->scanLockMode,
- scanPtr.p->scanKeyinfoFlag);
+ scanPtr.p->scanLockMode);
return;
}
diff --git a/ndb/src/kernel/blocks/dbacc/Makefile.am b/ndb/src/kernel/blocks/dbacc/Makefile.am
index e44524c3edd..ca1b1efac37 100644
--- a/ndb/src/kernel/blocks/dbacc/Makefile.am
+++ b/ndb/src/kernel/blocks/dbacc/Makefile.am
@@ -3,6 +3,8 @@ noinst_LIBRARIES = libdbacc.a
libdbacc_a_SOURCES = DbaccInit.cpp DbaccMain.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
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 90f4ac73411..05c5d5d5198 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -27,6 +27,7 @@
#include <SectionReader.hpp>
#include <SimpleProperties.hpp>
#include <AttributeHeader.hpp>
+#include <KeyDescriptor.hpp>
#include <signaldata/DictSchemaInfo.hpp>
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/DropTabFile.hpp>
@@ -228,7 +229,7 @@ void Dbdict::packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId)
8 * ZSIZE_OF_PAGES_IN_WORDS);
w.first();
- packTableIntoPagesImpl(w, tablePtr);
+ packTableIntoPagesImpl(w, tablePtr, signal);
Uint32 wordsOfTable = w.getWordsUsed();
Uint32 pagesUsed =
@@ -257,7 +258,8 @@ void Dbdict::packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId)
void
Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
- TableRecordPtr tablePtr){
+ TableRecordPtr tablePtr,
+ Signal* signal){
w.add(DictTabInfo::TableName, tablePtr.p->tableName);
w.add(DictTabInfo::TableId, tablePtr.i);
@@ -278,9 +280,32 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor);
w.add(DictTabInfo::TableKValue, tablePtr.p->kValue);
w.add(DictTabInfo::FragmentTypeVal, tablePtr.p->fragmentType);
- w.add(DictTabInfo::FragmentKeyTypeVal, tablePtr.p->fragmentKeyType);
w.add(DictTabInfo::TableTypeVal, tablePtr.p->tableType);
- w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
+
+ if(!signal)
+ {
+ w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
+ }
+ else
+ {
+ Uint32 * theData = signal->getDataPtrSend();
+ CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
+ req->senderRef = 0;
+ req->senderData = RNIL;
+ req->fragmentationType = tablePtr.p->fragmentType;
+ req->noOfFragments = 0;
+ req->fragmentNode = 0;
+ req->primaryTableId = tablePtr.i;
+ EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
+ CreateFragmentationReq::SignalLength);
+ if(signal->theData[0] == 0)
+ {
+ Uint16 *data = (Uint16*)&signal->theData[25];
+ Uint32 count = 2 + data[0] * data[1];
+ w.add(DictTabInfo::FragmentDataLen, 2*count);
+ w.add(DictTabInfo::FragmentData, data, 2*count);
+ }
+ }
if (tablePtr.p->primaryTableId != RNIL){
TableRecordPtr primTab;
@@ -311,18 +336,14 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
const Uint32 attrSize = AttributeDescriptor::getSize(desc);
const Uint32 arraySize = AttributeDescriptor::getArraySize(desc);
const Uint32 nullable = AttributeDescriptor::getNullable(desc);
- const Uint32 DGroup = AttributeDescriptor::getDGroup(desc);
const Uint32 DKey = AttributeDescriptor::getDKey(desc);
- const Uint32 attrStoredInd = AttributeDescriptor::getStoredInTup(desc);
- w.add(DictTabInfo::AttributeType, attrType);
+ // AttributeType deprecated
w.add(DictTabInfo::AttributeSize, attrSize);
w.add(DictTabInfo::AttributeArraySize, arraySize);
w.add(DictTabInfo::AttributeNullableFlag, nullable);
- w.add(DictTabInfo::AttributeDGroup, DGroup);
w.add(DictTabInfo::AttributeDKey, DKey);
- w.add(DictTabInfo::AttributeStoredInd, attrStoredInd);
- w.add(DictTabInfo::AttributeExtType, attrPtr.p->extType);
+ w.add(DictTabInfo::AttributeExtType, attrType);
w.add(DictTabInfo::AttributeExtPrecision, attrPtr.p->extPrecision);
w.add(DictTabInfo::AttributeExtScale, attrPtr.p->extScale);
w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
@@ -370,7 +391,7 @@ void Dbdict::execFSCLOSECONF(Signal* signal)
closeWriteTableConf(signal, fsPtr);
break;
case FsConnectRecord::OPEN_READ_SCHEMA2:
- openSchemaFile(signal, 1, fsPtr.i, false);
+ openSchemaFile(signal, 1, fsPtr.i, false, false);
break;
default:
jamLine((fsPtr.p->fsState & 0xFFF));
@@ -631,7 +652,7 @@ void Dbdict::writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZALLOCATE;
+ fsRWReq->varIndex = ZBAT_TABLE_FILE;
fsRWReq->numberOfPages = c_writeTableRecord.noOfPages;
fsRWReq->data.arrayOfPages.varIndex = c_writeTableRecord.pageId;
fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
@@ -708,7 +729,7 @@ void Dbdict::readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZALLOCATE;
+ fsRWReq->varIndex = ZBAT_TABLE_FILE;
fsRWReq->numberOfPages = c_readTableRecord.noOfPages;
fsRWReq->data.arrayOfPages.varIndex = c_readTableRecord.pageId;
fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
@@ -774,11 +795,9 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
SchemaFile::TableEntry* te, Callback* callback){
jam();
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
-
ndbrequire(tableId < c_tableRecordPool.getSize());
- SchemaFile::TableEntry * tableEntry = getTableEntry(pagePtr.p, tableId);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
SchemaFile::TableState newState =
(SchemaFile::TableState)te->m_tableState;
@@ -825,12 +844,15 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
ndbrequire(ok);
* tableEntry = * te;
- computeChecksum((SchemaFile*)pagePtr.p);
+ computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.newFile = false;
+ c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
+ c_writeSchemaRecord.noOfPages = 1;
c_writeSchemaRecord.m_callback = * callback;
startWriteSchemaFile(signal);
@@ -841,14 +863,15 @@ void Dbdict::startWriteSchemaFile(Signal* signal)
FsConnectRecordPtr fsPtr;
c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
- openSchemaFile(signal, 0, fsPtr.i, true);
+ openSchemaFile(signal, 0, fsPtr.i, true, c_writeSchemaRecord.newFile);
c_writeSchemaRecord.noOfSchemaFilesHandled = 0;
}//Dbdict::startWriteSchemaFile()
void Dbdict::openSchemaFile(Signal* signal,
Uint32 fileNo,
Uint32 fsConPtr,
- bool writeFlag)
+ bool writeFlag,
+ bool newFile)
{
FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
fsOpenReq->userReference = reference();
@@ -857,9 +880,11 @@ void Dbdict::openSchemaFile(Signal* signal,
jam();
fsOpenReq->fileFlags =
FsOpenReq::OM_WRITEONLY |
- FsOpenReq::OM_TRUNCATE |
- FsOpenReq::OM_CREATE |
FsOpenReq::OM_SYNC;
+ if (newFile)
+ fsOpenReq->fileFlags |=
+ FsOpenReq::OM_TRUNCATE |
+ FsOpenReq::OM_CREATE;
} else {
jam();
fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
@@ -884,6 +909,12 @@ void Dbdict::writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
{
FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
+ // check write record
+ WriteSchemaRecord & wr = c_writeSchemaRecord;
+ ndbrequire(wr.pageId == (wr.pageId != 0) * NDB_SF_MAX_PAGES);
+ ndbrequire(wr.noOfPages != 0);
+ ndbrequire(wr.firstPage + wr.noOfPages <= NDB_SF_MAX_PAGES);
+
fsRWReq->filePointer = filePtr;
fsRWReq->userReference = reference();
fsRWReq->userPointer = fsConPtr;
@@ -891,11 +922,11 @@ void Dbdict::writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZALLOCATE;
- fsRWReq->numberOfPages = 1;
-// Write from memory page
- fsRWReq->data.arrayOfPages.varIndex = c_writeSchemaRecord.pageId;
- fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
+ fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
+ fsRWReq->numberOfPages = wr.noOfPages;
+ // Write from memory page
+ fsRWReq->data.arrayOfPages.varIndex = wr.pageId + wr.firstPage;
+ fsRWReq->data.arrayOfPages.fileOffset = wr.firstPage;
sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
}//writeSchemaFile()
@@ -925,7 +956,7 @@ void Dbdict::closeWriteSchemaConf(Signal* signal,
if (c_writeSchemaRecord.noOfSchemaFilesHandled < 2) {
jam();
fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
- openSchemaFile(signal, 1, fsPtr.i, true);
+ openSchemaFile(signal, 1, fsPtr.i, true, c_writeSchemaRecord.newFile);
return;
}
ndbrequire(c_writeSchemaRecord.noOfSchemaFilesHandled == 2);
@@ -943,20 +974,26 @@ void Dbdict::startReadSchemaFile(Signal* signal)
FsConnectRecordPtr fsPtr;
c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA1;
- openSchemaFile(signal, 0, fsPtr.i, false);
+ openSchemaFile(signal, 0, fsPtr.i, false, false);
}//Dbdict::startReadSchemaFile()
void Dbdict::openReadSchemaRef(Signal* signal,
FsConnectRecordPtr fsPtr)
{
fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
- openSchemaFile(signal, 1, fsPtr.i, false);
+ openSchemaFile(signal, 1, fsPtr.i, false, false);
}//Dbdict::openReadSchemaRef()
void Dbdict::readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
{
FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
+ // check read record
+ ReadSchemaRecord & rr = c_readSchemaRecord;
+ ndbrequire(rr.pageId == (rr.pageId != 0) * NDB_SF_MAX_PAGES);
+ ndbrequire(rr.noOfPages != 0);
+ ndbrequire(rr.firstPage + rr.noOfPages <= NDB_SF_MAX_PAGES);
+
fsRWReq->filePointer = filePtr;
fsRWReq->userReference = reference();
fsRWReq->userPointer = fsConPtr;
@@ -964,10 +1001,10 @@ void Dbdict::readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZALLOCATE;
- fsRWReq->numberOfPages = 1;
- fsRWReq->data.arrayOfPages.varIndex = c_readSchemaRecord.pageId;
- fsRWReq->data.arrayOfPages.fileOffset = 0;
+ fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
+ fsRWReq->numberOfPages = rr.noOfPages;
+ fsRWReq->data.arrayOfPages.varIndex = rr.pageId + rr.firstPage;
+ fsRWReq->data.arrayOfPages.fileOffset = rr.firstPage;
sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
}//readSchemaFile()
@@ -985,20 +1022,61 @@ void Dbdict::readSchemaConf(Signal* signal,
jam();
crashInd = true;
}//if
- PageRecordPtr tmpPagePtr;
- c_pageRecordArray.getPtr(tmpPagePtr, c_readSchemaRecord.pageId);
- Uint32 sz = ZSIZE_OF_PAGES_IN_WORDS;
- Uint32 chk = computeChecksum((const Uint32*)tmpPagePtr.p, sz);
+ ReadSchemaRecord & rr = c_readSchemaRecord;
+ XSchemaFile * xsf = &c_schemaFile[rr.pageId != 0];
- ndbrequire((chk == 0) || !crashInd);
+ if (rr.schemaReadState == ReadSchemaRecord::INITIAL_READ_HEAD) {
+ jam();
+ ndbrequire(rr.firstPage == 0);
+ SchemaFile * sf = &xsf->schemaPage[0];
+ Uint32 noOfPages;
+ if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) {
+ jam();
+ const Uint32 pageSize_old = 32 * 1024;
+ noOfPages = pageSize_old / NDB_SF_PAGE_SIZE - 1;
+ } else {
+ noOfPages = sf->FileSize / NDB_SF_PAGE_SIZE - 1;
+ }
+ rr.schemaReadState = ReadSchemaRecord::INITIAL_READ;
+ if (noOfPages != 0) {
+ rr.firstPage = 1;
+ rr.noOfPages = noOfPages;
+ readSchemaFile(signal, fsPtr.p->filePtr, fsPtr.i);
+ return;
+ }
+ }
+
+ SchemaFile * sf0 = &xsf->schemaPage[0];
+ xsf->noOfPages = sf0->FileSize / NDB_SF_PAGE_SIZE;
- if (chk != 0){
+ if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6 &&
+ ! convertSchemaFileTo_5_0_6(xsf)) {
jam();
+ ndbrequire(! crashInd);
ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
readSchemaRef(signal, fsPtr);
return;
- }//if
+ }
+
+ for (Uint32 n = 0; n < xsf->noOfPages; n++) {
+ SchemaFile * sf = &xsf->schemaPage[n];
+ bool ok =
+ memcmp(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic)) == 0 &&
+ sf->FileSize != 0 &&
+ sf->FileSize % NDB_SF_PAGE_SIZE == 0 &&
+ sf->FileSize == sf0->FileSize &&
+ sf->PageNumber == n &&
+ computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS) == 0;
+ ndbrequire(ok || !crashInd);
+ if (! ok) {
+ jam();
+ ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
+ readSchemaRef(signal, fsPtr);
+ return;
+ }
+ }
+
fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_SCHEMA;
closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
return;
@@ -1025,7 +1103,27 @@ void Dbdict::closeReadSchemaConf(Signal* signal,
switch(state) {
case ReadSchemaRecord::INITIAL_READ :
jam();
- sendNDB_STTORRY(signal);
+ {
+ // write back both copies
+
+ ndbrequire(c_writeSchemaRecord.inUse == false);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0 ];
+ Uint32 noOfPages =
+ (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1) /
+ NDB_SF_PAGE_ENTRIES;
+ resizeSchemaFile(xsf, noOfPages);
+
+ c_writeSchemaRecord.inUse = true;
+ c_writeSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
+ c_writeSchemaRecord.newFile = true;
+ c_writeSchemaRecord.firstPage = 0;
+ c_writeSchemaRecord.noOfPages = xsf->noOfPages;
+
+ c_writeSchemaRecord.m_callback.m_callbackFunction =
+ safe_cast(&Dbdict::initSchemaFile_conf);
+
+ startWriteSchemaFile(signal);
+ }
break;
default :
@@ -1035,6 +1133,54 @@ void Dbdict::closeReadSchemaConf(Signal* signal,
}//switch
}//Dbdict::closeReadSchemaConf()
+bool
+Dbdict::convertSchemaFileTo_5_0_6(XSchemaFile * xsf)
+{
+ const Uint32 pageSize_old = 32 * 1024;
+ Uint32 page_old[pageSize_old >> 2];
+ SchemaFile * sf_old = (SchemaFile *)page_old;
+
+ if (xsf->noOfPages * NDB_SF_PAGE_SIZE != pageSize_old)
+ return false;
+ SchemaFile * sf0 = &xsf->schemaPage[0];
+ memcpy(sf_old, sf0, pageSize_old);
+
+ // init max number new pages needed
+ xsf->noOfPages = (sf_old->NoOfTableEntries + NDB_SF_PAGE_ENTRIES - 1) /
+ NDB_SF_PAGE_ENTRIES;
+ initSchemaFile(xsf, 0, xsf->noOfPages, true);
+
+ Uint32 noOfPages = 1;
+ Uint32 n, i, j;
+ for (n = 0; n < xsf->noOfPages; n++) {
+ jam();
+ for (i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
+ j = n * NDB_SF_PAGE_ENTRIES + i;
+ if (j >= sf_old->NoOfTableEntries)
+ continue;
+ const SchemaFile::TableEntry_old & te_old = sf_old->TableEntries_old[j];
+ if (te_old.m_tableState == SchemaFile::INIT ||
+ te_old.m_tableState == SchemaFile::DROP_TABLE_COMMITTED ||
+ te_old.m_noOfPages == 0)
+ continue;
+ SchemaFile * sf = &xsf->schemaPage[n];
+ SchemaFile::TableEntry & te = sf->TableEntries[i];
+ te.m_tableState = te_old.m_tableState;
+ te.m_tableVersion = te_old.m_tableVersion;
+ te.m_tableType = te_old.m_tableType;
+ te.m_info_words = te_old.m_noOfPages * ZSIZE_OF_PAGES_IN_WORDS -
+ ZPAGE_HEADER_SIZE;
+ te.m_gcp = te_old.m_gcp;
+ if (noOfPages < n)
+ noOfPages = n;
+ }
+ }
+ xsf->noOfPages = noOfPages;
+ initSchemaFile(xsf, 0, xsf->noOfPages, false);
+
+ return true;
+}
+
/* **************************************************************** */
/* ---------------------------------------------------------------- */
/* MODULE: INITIALISATION MODULE ------------------------- */
@@ -1306,6 +1452,7 @@ void Dbdict::initRetrieveRecord(Signal* signal, Uint32 i, Uint32 returnCode)
void Dbdict::initSchemaRecord()
{
c_schemaRecord.schemaPage = RNIL;
+ c_schemaRecord.oldSchemaPage = RNIL;
}//Dbdict::initSchemaRecord()
void Dbdict::initRestartRecord()
@@ -1327,10 +1474,10 @@ void Dbdict::initNodeRecords()
void Dbdict::initPageRecords()
{
- c_schemaRecord.schemaPage = ZMAX_PAGES_OF_TABLE_DEFINITION;
- c_schemaRecord.oldSchemaPage = ZMAX_PAGES_OF_TABLE_DEFINITION + 1;
- c_retrieveRecord.retrievePage = ZMAX_PAGES_OF_TABLE_DEFINITION + 2;
- ndbrequire(ZNUMBER_OF_PAGES >= (2 * ZMAX_PAGES_OF_TABLE_DEFINITION + 2));
+ c_retrieveRecord.retrievePage = ZMAX_PAGES_OF_TABLE_DEFINITION;
+ ndbrequire(ZNUMBER_OF_PAGES >= (ZMAX_PAGES_OF_TABLE_DEFINITION + 1));
+ c_schemaRecord.schemaPage = 0;
+ c_schemaRecord.oldSchemaPage = NDB_SF_MAX_PAGES;
}//Dbdict::initPageRecords()
void Dbdict::initTableRecords()
@@ -1360,9 +1507,7 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
tablePtr.p->tableVersion = (Uint32)-1;
tablePtr.p->tabState = TableRecord::NOT_DEFINED;
tablePtr.p->tabReturnState = TableRecord::TRS_IDLE;
- tablePtr.p->storageType = DictTabInfo::MainMemory;
tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable;
- tablePtr.p->fragmentKeyType = DictTabInfo::PrimaryKey;
memset(tablePtr.p->tableName, 0, sizeof(tablePtr.p->tableName));
tablePtr.p->gciTableCreated = 0;
tablePtr.p->noOfAttributes = ZNIL;
@@ -1599,8 +1744,10 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
c_fsConnectRecordPool.setSize(ZFS_CONNECT_SIZE);
c_nodes.setSize(MAX_NODES);
c_pageRecordArray.setSize(ZNUMBER_OF_PAGES);
+ c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES);
c_tableRecordPool.setSize(tablerecSize);
c_tableRecordHash.setSize(tablerecSize);
+ g_key_descriptor_pool.setSize(tablerecSize);
c_triggerRecordPool.setSize(c_maxNoOfTriggers);
c_triggerRecordHash.setSize(c_maxNoOfTriggers);
c_opRecordPool.setSize(256); // XXX need config params
@@ -1617,12 +1764,23 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
c_opCreateTrigger.setSize(8);
c_opDropTrigger.setSize(8);
c_opAlterTrigger.setSize(8);
+
+ // Initialize schema file copies
+ c_schemaFile[0].schemaPage =
+ (SchemaFile*)c_schemaPageRecordArray.getPtr(0 * NDB_SF_MAX_PAGES);
+ c_schemaFile[0].noOfPages = 0;
+ c_schemaFile[1].schemaPage =
+ (SchemaFile*)c_schemaPageRecordArray.getPtr(1 * NDB_SF_MAX_PAGES);
+ c_schemaFile[1].noOfPages = 0;
// Initialize BAT for interface to file system
- PageRecordPtr pageRecPtr;
- c_pageRecordArray.getPtr(pageRecPtr, 0);
NewVARIABLE* bat = allocateBat(2);
- bat[1].WA = &pageRecPtr.p->word[0];
+ bat[0].WA = &c_schemaPageRecordArray.getPtr(0)->word[0];
+ bat[0].nrr = 2 * NDB_SF_MAX_PAGES;
+ bat[0].ClusterSize = NDB_SF_PAGE_SIZE;
+ bat[0].bits.q = NDB_SF_PAGE_SIZE_IN_WORDS_LOG2;
+ bat[0].bits.v = 5; // 32 bits per element
+ bat[1].WA = &c_pageRecordArray.getPtr(0)->word[0];
bat[1].nrr = ZNUMBER_OF_PAGES;
bat[1].ClusterSize = ZSIZE_OF_PAGES_IN_WORDS * 4;
bat[1].bits.q = ZLOG_SIZE_OF_PAGES_IN_WORDS; // 2**13 = 8192 elements
@@ -1767,16 +1925,23 @@ void Dbdict::execHOT_SPAREREP(Signal* signal)
void Dbdict::initSchemaFile(Signal* signal)
{
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
- SchemaFile * schemaFile = (SchemaFile *)pagePtr.p;
- initSchemaFile(schemaFile, 4 * ZSIZE_OF_PAGES_IN_WORDS);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ xsf->noOfPages = (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1)
+ / NDB_SF_PAGE_ENTRIES;
+ initSchemaFile(xsf, 0, xsf->noOfPages, true);
+ // init alt copy too for INR
+ XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
+ oldxsf->noOfPages = xsf->noOfPages;
+ memcpy(&oldxsf->schemaPage[0], &xsf->schemaPage[0], xsf->schemaPage[0].FileSize);
if (c_initialStart || c_initialNodeRestart) {
jam();
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.newFile = true;
+ c_writeSchemaRecord.firstPage = 0;
+ c_writeSchemaRecord.noOfPages = xsf->noOfPages;
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::initSchemaFile_conf);
@@ -1786,7 +1951,9 @@ void Dbdict::initSchemaFile(Signal* signal)
jam();
ndbrequire(c_readSchemaRecord.schemaReadState == ReadSchemaRecord::IDLE);
c_readSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
- c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ;
+ c_readSchemaRecord.firstPage = 0;
+ c_readSchemaRecord.noOfPages = 1;
+ c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ_HEAD;
startReadSchemaFile(signal);
} else {
ndbrequire(false);
@@ -1925,7 +2092,7 @@ void Dbdict::execDICTSTARTREQ(Signal* signal)
safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete);
c_restartRecord.activeTable = 0;
- c_schemaRecord.schemaPage = c_schemaRecord.oldSchemaPage;
+ c_schemaRecord.schemaPage = c_schemaRecord.oldSchemaPage; // ugly
checkSchemaStatus(signal);
}//execDICTSTARTREQ()
@@ -1934,15 +2101,13 @@ Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
Uint32 callbackData,
Uint32 returnCode){
- c_schemaRecord.schemaPage = ZMAX_PAGES_OF_TABLE_DEFINITION;
+ c_schemaRecord.schemaPage = 0; // ugly
+ XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
+ ndbrequire(oldxsf->noOfPages != 0);
LinearSectionPtr ptr[3];
-
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.oldSchemaPage);
-
- ptr[0].p = &pagePtr.p->word[0];
- ptr[0].sz = ZSIZE_OF_PAGES_IN_WORDS;
+ ptr[0].p = (Uint32*)&oldxsf->schemaPage[0];
+ ptr[0].sz = oldxsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
c_sendSchemaRecord.m_SCHEMAINFO_Counter = c_aliveNodes;
NodeReceiverGroup rg(DBDICT, c_aliveNodes);
@@ -1958,10 +2123,10 @@ Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
1,
c);
- PageRecordPtr newPagePtr;
- c_pageRecordArray.getPtr(newPagePtr, c_schemaRecord.schemaPage);
- memcpy(&newPagePtr.p->word[0], &pagePtr.p->word[0],
- 4 * ZSIZE_OF_PAGES_IN_WORDS);
+ XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ newxsf->noOfPages = oldxsf->noOfPages;
+ memcpy(&newxsf->schemaPage[0], &oldxsf->schemaPage[0],
+ oldxsf->noOfPages * NDB_SF_PAGE_SIZE);
signal->theData[0] = getOwnNodeId();
sendSignal(reference(), GSN_SCHEMA_INFOCONF, signal, 1, JBB);
@@ -1978,11 +2143,11 @@ Dbdict::execGET_SCHEMA_INFOREQ(Signal* signal){
LinearSectionPtr ptr[3];
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ ndbrequire(xsf->noOfPages != 0);
- ptr[0].p = &pagePtr.p->word[0];
- ptr[0].sz = ZSIZE_OF_PAGES_IN_WORDS;
+ ptr[0].p = (Uint32*)&xsf->schemaPage[0];
+ ptr[0].sz = xsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
Callback c = { safe_cast(&Dbdict::sendSchemaComplete), 0 };
sendFragmentedSignal(ref,
@@ -2024,12 +2189,22 @@ void Dbdict::execSCHEMA_INFO(Signal* signal)
SegmentedSectionPtr schemaDataPtr;
signal->getSection(schemaDataPtr, 0);
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
- copy(&pagePtr.p->word[0], schemaDataPtr);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ ndbrequire(schemaDataPtr.sz % NDB_SF_PAGE_SIZE_IN_WORDS == 0);
+ xsf->noOfPages = schemaDataPtr.sz / NDB_SF_PAGE_SIZE_IN_WORDS;
+ copy((Uint32*)&xsf->schemaPage[0], schemaDataPtr);
releaseSections(signal);
+
+ SchemaFile * sf0 = &xsf->schemaPage[0];
+ if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6) {
+ bool ok = convertSchemaFileTo_5_0_6(xsf);
+ ndbrequire(ok);
+ }
- validateChecksum((SchemaFile*)pagePtr.p);
+ validateChecksum(xsf);
+
+ XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
+ resizeSchemaFile(xsf, oldxsf->noOfPages);
ndbrequire(signal->getSendersBlockRef() != reference());
@@ -2054,7 +2229,11 @@ Dbdict::restart_checkSchemaStatusComplete(Signal * signal,
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.newFile = true;
+ c_writeSchemaRecord.firstPage = 0;
+ c_writeSchemaRecord.noOfPages = xsf->noOfPages;
c_writeSchemaRecord.m_callback.m_callbackData = 0;
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::restart_writeSchemaConf);
@@ -2103,20 +2282,18 @@ void Dbdict::execSCHEMA_INFOCONF(Signal* signal)
void Dbdict::checkSchemaStatus(Signal* signal)
{
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
+ XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
+ ndbrequire(newxsf->noOfPages == oldxsf->noOfPages);
+ const Uint32 noOfEntries = newxsf->noOfPages * NDB_SF_PAGE_ENTRIES;
- PageRecordPtr oldPagePtr;
- c_pageRecordArray.getPtr(oldPagePtr, c_schemaRecord.oldSchemaPage);
-
- for (; c_restartRecord.activeTable < MAX_TABLES;
+ for (; c_restartRecord.activeTable < noOfEntries;
c_restartRecord.activeTable++) {
jam();
Uint32 tableId = c_restartRecord.activeTable;
- SchemaFile::TableEntry *newEntry = getTableEntry(pagePtr.p, tableId);
- SchemaFile::TableEntry *oldEntry = getTableEntry(oldPagePtr.p, tableId,
- true);
+ SchemaFile::TableEntry *newEntry = getTableEntry(newxsf, tableId);
+ SchemaFile::TableEntry *oldEntry = getTableEntry(oldxsf, tableId);
SchemaFile::TableState schemaState =
(SchemaFile::TableState)newEntry->m_tableState;
SchemaFile::TableState oldSchemaState =
@@ -2247,7 +2424,7 @@ void Dbdict::checkSchemaStatus(Signal* signal)
return;
}//if
}
- ndbrequire(ok);
+ ndbrequire(ok);
break;
}
case SchemaFile::DROP_TABLE_STARTED:
@@ -2350,7 +2527,8 @@ Dbdict::restartCreateTab(Signal* signal, Uint32 tableId,
if(file && !ERROR_INSERTED(6002)){
jam();
- c_readTableRecord.noOfPages = te->m_noOfPages;
+ c_readTableRecord.noOfPages =
+ DIV(te->m_info_words + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
c_readTableRecord.pageId = 0;
c_readTableRecord.m_callback.m_callbackData = createTabPtr.p->key;
c_readTableRecord.m_callback.m_callbackFunction =
@@ -3244,8 +3422,8 @@ Dbdict::execALTER_TAB_REQ(Signal * signal)
tabEntry.m_tableType = tablePtr.p->tableType;
tabEntry.m_tableState = SchemaFile::ALTER_TABLE_COMMITTED;
tabEntry.m_gcp = gci;
- tabEntry.m_noOfPages =
- DIV(tabInfoPtr.sz + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
+ tabEntry.m_info_words = tabInfoPtr.sz;
+ memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
Callback callback;
callback.m_callbackData = senderData;
@@ -3776,9 +3954,8 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
/**
* Update table version
*/
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
- SchemaFile::TableEntry * tabEntry = getTableEntry(pagePtr.p, tabPtr.i);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tabEntry = getTableEntry(xsf, tabPtr.i);
tabPtr.p->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion);
@@ -4084,8 +4261,8 @@ Dbdict::createTab_prepare(Signal* signal, CreateTabReq * req){
tabEntry.m_tableType = tabPtr.p->tableType;
tabEntry.m_tableState = SchemaFile::ADD_STARTED;
tabEntry.m_gcp = gci;
- tabEntry.m_noOfPages =
- DIV(tabInfoPtr.sz + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
+ tabEntry.m_info_words = tabInfoPtr.sz;
+ memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
Callback callback;
callback.m_callbackData = createTabPtr.p->key;
@@ -4248,14 +4425,14 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
req->maxLoadFactor = tabPtr.p->maxLoadFactor;
req->minLoadFactor = tabPtr.p->minLoadFactor;
req->kValue = tabPtr.p->kValue;
- req->lh3DistrBits = lhDistrBits;
- req->lh3PageBits = lhPageBits;
+ req->lh3DistrBits = 0; //lhDistrBits;
+ req->lh3PageBits = 0; //lhPageBits;
req->noOfAttributes = tabPtr.p->noOfAttributes;
- req->noOfNullAttributes = tabPtr.p->noOfNullAttr;
+ req->noOfNullAttributes = tabPtr.p->noOfNullBits;
req->noOfPagesToPreAllocate = 0;
req->schemaVersion = tabPtr.p->tableVersion;
Uint32 keyLen = tabPtr.p->tupKeyLength;
- req->keyLength = keyLen > 8 ? 0 : keyLen; // Put this into ACC instead
+ req->keyLength = keyLen; // wl-2066 no more "long keys"
req->nextLCP = lcpNo;
req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
@@ -4271,6 +4448,44 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal,
LqhFragReq::SignalLength, JBB);
}
+
+ /**
+ * Create KeyDescriptor
+ */
+ KeyDescriptor* desc= g_key_descriptor_pool.getPtr(tabPtr.i);
+ new (desc) KeyDescriptor();
+
+ Uint32 key = 0;
+ Uint32 tAttr = tabPtr.p->firstAttribute;
+ while (tAttr != RNIL)
+ {
+ jam();
+ AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
+ if (aRec->tupleKey)
+ {
+ desc->noOfKeyAttr ++;
+ desc->keyAttr[key].attributeDescriptor = aRec->attributeDescriptor;
+
+ Uint32 csNumber = (aRec->extPrecision >> 16);
+ if(csNumber)
+ {
+ desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
+ ndbrequire(all_charsets[csNumber]);
+ desc->hasCharAttr = 1;
+ }
+ else
+ {
+ desc->keyAttr[key].charsetInfo = 0;
+ }
+ if(AttributeDescriptor::getDKey(aRec->attributeDescriptor))
+ {
+ desc->noOfDistrKeys ++;
+ }
+ key++;
+ }
+ tAttr = aRec->nextAttrInTable;
+ }
+ ndbrequire(key == tabPtr.p->noOfPrimkey);
}
void
@@ -4322,7 +4537,7 @@ Dbdict::sendLQHADDATTRREQ(Signal* signal,
LqhAddAttrReq::Entry& entry = req->attributes[i];
entry.attrId = attrPtr.p->attributeId;
entry.attrDescriptor = attrPtr.p->attributeDescriptor;
- entry.extTypeInfo = attrPtr.p->extType;
+ entry.extTypeInfo = 0;
// charset number passed to TUP, TUX in upper half
entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
if (tabPtr.p->isIndex()) {
@@ -4464,10 +4679,12 @@ Dbdict::execTAB_COMMITCONF(Signal* signal){
signal->theData[3] = reference();
signal->theData[4] = (Uint32)tabPtr.p->tableType;
signal->theData[5] = createTabPtr.p->key;
- sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 6, JBB);
+ signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
+
+ sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB);
return;
}
-
+
ndbrequire(false);
}
@@ -4520,8 +4737,8 @@ Dbdict::createTab_commit(Signal * signal, CreateTabReq * req){
tabEntry.m_tableType = tabPtr.p->tableType;
tabEntry.m_tableState = SchemaFile::TABLE_ADD_COMMITTED;
tabEntry.m_gcp = tabPtr.p->gciTableCreated;
- tabEntry.m_noOfPages =
- DIV(tabPtr.p->packedSize + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
+ tabEntry.m_info_words = tabPtr.p->packedSize;
+ memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
Callback callback;
callback.m_callbackData = createTabPtr.p->key;
@@ -4622,10 +4839,9 @@ Dbdict::createTab_dropComplete(Signal* signal,
c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
releaseTableObject(tabPtr.i);
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
- SchemaFile::TableEntry * tableEntry = getTableEntry(pagePtr.p, tabPtr.i);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tabPtr.i);
tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
//@todo check error
@@ -4823,7 +5039,6 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
tablePtr.p->minLoadFactor = tableDesc.MinLoadFactor;
tablePtr.p->maxLoadFactor = tableDesc.MaxLoadFactor;
tablePtr.p->fragmentType = (DictTabInfo::FragmentType)tableDesc.FragmentType;
- tablePtr.p->fragmentKeyType = (DictTabInfo::FragmentKeyType)tableDesc.FragmentKeyType;
tablePtr.p->tableType = (DictTabInfo::TableType)tableDesc.TableType;
tablePtr.p->kValue = tableDesc.TableKValue;
tablePtr.p->fragmentCount = tableDesc.FragmentCount;
@@ -4872,6 +5087,7 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
Uint32 keyLength = 0;
Uint32 attrCount = tablePtr.p->noOfAttributes;
Uint32 nullCount = 0;
+ Uint32 nullBits = 0;
Uint32 noOfCharsets = 0;
Uint16 charsets[128];
Uint32 recordLength = 0;
@@ -4924,19 +5140,24 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
attrPtr.p->attributeId = attrDesc.AttributeId;
attrPtr.p->tupleKey = (keyCount + 1) * attrDesc.AttributeKeyFlag;
- attrPtr.p->extType = attrDesc.AttributeExtType;
attrPtr.p->extPrecision = attrDesc.AttributeExtPrecision;
attrPtr.p->extScale = attrDesc.AttributeExtScale;
attrPtr.p->extLength = attrDesc.AttributeExtLength;
// charset in upper half of precision
unsigned csNumber = (attrPtr.p->extPrecision >> 16);
if (csNumber != 0) {
+ /*
+ * A new charset is first accessed here on this node.
+ * TODO use separate thread (e.g. via NDBFS) if need to load from file
+ */
CHARSET_INFO* cs = get_charset(csNumber, MYF(0));
if (cs == NULL) {
parseP->errorCode = CreateTableRef::InvalidCharset;
parseP->errorLine = __LINE__;
return;
}
+ // XXX should be done somewhere in mysql
+ all_charsets[cs->number] = cs;
unsigned i = 0;
while (i < noOfCharsets) {
if (charsets[i] == csNumber)
@@ -4954,9 +5175,7 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
}
}
- /**
- * Ignore incoming old-style type and recompute it.
- */
+ // compute attribute size and array size
bool translateOk = attrDesc.translateExtType();
tabRequire(translateOk, CreateTableRef::Inconsistency);
@@ -4969,15 +5188,12 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
}
Uint32 desc = 0;
- AttributeDescriptor::setType(desc, attrDesc.AttributeType);
+ AttributeDescriptor::setType(desc, attrDesc.AttributeExtType);
AttributeDescriptor::setSize(desc, attrDesc.AttributeSize);
AttributeDescriptor::setArray(desc, attrDesc.AttributeArraySize);
AttributeDescriptor::setNullable(desc, attrDesc.AttributeNullableFlag);
- AttributeDescriptor::setDGroup(desc, attrDesc.AttributeDGroup);
AttributeDescriptor::setDKey(desc, attrDesc.AttributeDKey);
AttributeDescriptor::setPrimaryKey(desc, attrDesc.AttributeKeyFlag);
-
- AttributeDescriptor::setStoredInTup(desc, attrDesc.AttributeStoredInd);
attrPtr.p->attributeDescriptor = desc;
attrPtr.p->autoIncrement = attrDesc.AttributeAutoIncrement;
strcpy(attrPtr.p->defaultValue, attrDesc.AttributeDefaultValue);
@@ -4989,7 +5205,25 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
nullCount += attrDesc.AttributeNullableFlag;
const Uint32 aSz = (1 << attrDesc.AttributeSize);
- const Uint32 sz = ((aSz * attrDesc.AttributeArraySize) + 31) >> 5;
+ Uint32 sz;
+ if(aSz != 1)
+ {
+ sz = ((aSz * attrDesc.AttributeArraySize) + 31) >> 5;
+ }
+ else
+ {
+ sz = 0;
+ nullBits += attrDesc.AttributeArraySize;
+ }
+
+ if(attrDesc.AttributeArraySize == 0)
+ {
+ parseP->errorCode = CreateTableRef::InvalidArraySize;
+ parseP->status = status;
+ parseP->errorKey = it.getKey();
+ parseP->errorLine = __LINE__;
+ return;
+ }
recordLength += sz;
if(attrDesc.AttributeKeyFlag){
@@ -5018,6 +5252,7 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
tablePtr.p->noOfNullAttr = nullCount;
tablePtr.p->noOfCharsets = noOfCharsets;
tablePtr.p->tupKeyLength = keyLength;
+ tablePtr.p->noOfNullBits = nullCount + nullBits;
tabRequire(recordLength<= MAX_TUPLE_SIZE_IN_WORDS,
CreateTableRef::RecordTooBig);
@@ -5480,21 +5715,22 @@ Dbdict::execPREP_DROP_TAB_REQ(Signal* signal){
/**
* Modify schema
*/
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
-
- SchemaFile::TableEntry * tableEntry = getTableEntry(pagePtr.p, tablePtr.i);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tablePtr.i);
SchemaFile::TableState tabState =
(SchemaFile::TableState)tableEntry->m_tableState;
ndbrequire(tabState == SchemaFile::TABLE_ADD_COMMITTED ||
tabState == SchemaFile::ALTER_TABLE_COMMITTED);
tableEntry->m_tableState = SchemaFile::DROP_TABLE_STARTED;
- computeChecksum((SchemaFile*)pagePtr.p);
+ computeChecksum(xsf, tablePtr.i / NDB_SF_PAGE_ENTRIES);
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.newFile = false;
+ c_writeSchemaRecord.firstPage = tablePtr.i / NDB_SF_PAGE_ENTRIES;
+ c_writeSchemaRecord.noOfPages = 1;
c_writeSchemaRecord.m_callback.m_callbackData = dropTabPtr.p->key;
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::prepDropTab_writeSchemaConf);
@@ -5655,20 +5891,20 @@ Dbdict::dropTab_complete(Signal* signal,
/**
* Write to schema file
*/
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
-
- SchemaFile::TableEntry * tableEntry = getTableEntry(pagePtr.p, tableId);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
SchemaFile::TableState tabState =
(SchemaFile::TableState)tableEntry->m_tableState;
ndbrequire(tabState == SchemaFile::DROP_TABLE_STARTED);
tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
- computeChecksum((SchemaFile*)pagePtr.p);
+ computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
+ c_writeSchemaRecord.noOfPages = 1;
c_writeSchemaRecord.m_callback.m_callbackData = dropTabPtr.p->key;
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::dropTab_writeSchemaConf);
@@ -5852,7 +6088,10 @@ void Dbdict::sendGET_TABLEID_REF(Signal* signal,
void Dbdict::execGET_TABINFOREQ(Signal* signal)
{
jamEntry();
- if(!assembleFragments(signal)) { return; }
+ if(!assembleFragments(signal))
+ {
+ return;
+ }
GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
@@ -6437,11 +6676,15 @@ void
Dbdict::createIndex_slavePrepare(Signal* signal, OpCreateIndexPtr opPtr)
{
jam();
+ if (ERROR_INSERTED(6006) && ! opPtr.p->m_isMaster) {
+ ndbrequire(false);
+ }
}
void
Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
{
+ Uint32 attrid_map[MAX_ATTRIBUTES_IN_INDEX];
Uint32 k;
jam();
const CreateIndxReq* const req = &opPtr.p->m_request;
@@ -6511,39 +6754,49 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
// tree node size in words (make configurable later)
indexPtr.p->tupKeyLength = MAX_TTREE_NODE_SIZE;
}
- // hash index attributes must currently be in table order
- Uint32 prevAttrId = RNIL;
+
+ AttributeMask mask;
+ mask.clear();
for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
jam();
- bool found = false;
- for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
- AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
- tAttr = aRec->nextAttrInTable;
- if (aRec->attributeId != opPtr.p->m_attrList.id[k])
+ unsigned current_id= opPtr.p->m_attrList.id[k];
+ AttributeRecord* aRec= NULL;
+ Uint32 tAttr= tablePtr.p->firstAttribute;
+ for (; tAttr != RNIL; tAttr= aRec->nextAttrInTable)
+ {
+ aRec = c_attributeRecordPool.getPtr(tAttr);
+ if (aRec->attributeId != current_id)
continue;
jam();
- found = true;
- const Uint32 a = aRec->attributeDescriptor;
- if (indexPtr.p->isHashIndex()) {
- const Uint32 s1 = AttributeDescriptor::getSize(a);
- const Uint32 s2 = AttributeDescriptor::getArraySize(a);
- indexPtr.p->tupKeyLength += ((1 << s1) * s2 + 31) >> 5;
- }
+ break;
}
- if (! found) {
+ if (tAttr == RNIL) {
jam();
opPtr.p->m_errorCode = CreateIndxRef::BadRequestType;
opPtr.p->m_errorLine = __LINE__;
return;
}
- if (indexPtr.p->isHashIndex() &&
- k > 0 && prevAttrId >= opPtr.p->m_attrList.id[k]) {
+ if (mask.get(current_id))
+ {
jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidAttributeOrder;
+ opPtr.p->m_errorCode = CreateIndxRef::DuplicateAttributes;
opPtr.p->m_errorLine = __LINE__;
return;
}
- prevAttrId = opPtr.p->m_attrList.id[k];
+ mask.set(current_id);
+
+ const Uint32 a = aRec->attributeDescriptor;
+ unsigned kk= k;
+ if (indexPtr.p->isHashIndex()) {
+ const Uint32 s1 = AttributeDescriptor::getSize(a);
+ const Uint32 s2 = AttributeDescriptor::getArraySize(a);
+ indexPtr.p->tupKeyLength += ((1 << s1) * s2 + 31) >> 5;
+ // reorder the attributes according to the tableid order
+ // for unque indexes
+ for (; kk > 0 && current_id < attrid_map[kk-1]>>16; kk--)
+ attrid_map[kk]= attrid_map[kk-1];
+ }
+ attrid_map[kk]= k | (current_id << 16);
}
indexPtr.p->noOfPrimkey = indexPtr.p->noOfAttributes;
// plus concatenated primary table key attribute
@@ -6564,15 +6817,21 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
AttributeRecordPtr aRecPtr;
c_attributeRecordPool.getPtr(aRecPtr, tablePtr.p->firstAttribute);
for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
+ // insert the attributes in the order decided above in attrid_map
+ // k is new order, current_id is in previous order
+ // ToDo: make sure "current_id" is stored with the table and
+ // passed up to NdbDictionary
+ unsigned current_id= opPtr.p->m_attrList.id[attrid_map[k] & 0xffff];
jam();
for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
tAttr = aRec->nextAttrInTable;
- if (aRec->attributeId != opPtr.p->m_attrList.id[k])
+ if (aRec->attributeId != current_id)
continue;
jam();
const Uint32 a = aRec->attributeDescriptor;
bool isNullable = AttributeDescriptor::getNullable(a);
+ Uint32 attrType = AttributeDescriptor::getType(a);
w.add(DictTabInfo::AttributeName, aRec->attributeName);
w.add(DictTabInfo::AttributeId, k);
if (indexPtr.p->isHashIndex()) {
@@ -6583,9 +6842,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)isNullable);
}
- w.add(DictTabInfo::AttributeStoredInd, (Uint32)DictTabInfo::Stored);
- // ext type overrides
- w.add(DictTabInfo::AttributeExtType, aRec->extType);
+ w.add(DictTabInfo::AttributeExtType, attrType);
w.add(DictTabInfo::AttributeExtPrecision, aRec->extPrecision);
w.add(DictTabInfo::AttributeExtScale, aRec->extScale);
w.add(DictTabInfo::AttributeExtLength, aRec->extLength);
@@ -6598,9 +6855,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
w.add(DictTabInfo::AttributeName, "NDB$PK");
w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
- w.add(DictTabInfo::AttributeStoredInd, (Uint32)DictTabInfo::Stored);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
- // ext type overrides
w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength);
w.add(DictTabInfo::AttributeEnd, (Uint32)true);
@@ -6611,9 +6866,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
w.add(DictTabInfo::AttributeName, "NDB$TNODE");
w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
- w.add(DictTabInfo::AttributeStoredInd, (Uint32)DictTabInfo::Stored);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
- // ext type overrides
w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
w.add(DictTabInfo::AttributeExtLength, indexPtr.p->tupKeyLength);
w.add(DictTabInfo::AttributeEnd, (Uint32)true);
@@ -8023,7 +8276,7 @@ void Dbdict::createEventUTIL_EXECUTE(Signal *signal,
break;
case ZALREADYEXIST:
jam();
- evntRecPtr.p->m_errorCode = CreateEvntRef::EventExists;
+ evntRecPtr.p->m_errorCode = CreateEvntRef::EventNameExists;
break;
default:
jam();
@@ -9627,7 +9880,7 @@ Dbdict::alterIndex_toDropTc(Signal* signal, OpAlterIndexPtr opPtr)
// broken index allowed if force
if (! (indexPtr.p->indexLocal & TableRecord::IL_CREATED_TC)) {
jam();
- ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
+ ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterIndex_sendReply(signal, opPtr, false);
return;
}
@@ -11684,7 +11937,7 @@ Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
// broken trigger allowed if force
if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_TC)) {
jam();
- ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
+ ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterTrigger_sendReply(signal, opPtr, false);
return;
}
@@ -11694,7 +11947,7 @@ Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
// broken trigger allowed if force
if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_LQH)) {
jam();
- ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
+ ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterTrigger_sendReply(signal, opPtr, false);
return;
}
@@ -11913,36 +12166,75 @@ Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
/* **************************************************************** */
void
-Dbdict::initSchemaFile(SchemaFile * sf, Uint32 fileSz){
- memcpy(sf->Magic, "NDBSCHMA", sizeof(sf->Magic));
- sf->ByteOrder = 0x12345678;
- sf->NdbVersion = NDB_VERSION;
- sf->FileSize = fileSz;
- sf->CheckSum = 0;
-
- Uint32 headSz = (sizeof(SchemaFile)-sizeof(SchemaFile::TableEntry));
- Uint32 noEntries = (fileSz - headSz) / sizeof(SchemaFile::TableEntry);
- Uint32 slack = (fileSz - headSz) - noEntries * sizeof(SchemaFile::TableEntry);
-
- ndbrequire(noEntries > MAX_TABLES);
+Dbdict::initSchemaFile(XSchemaFile * xsf, Uint32 firstPage, Uint32 lastPage,
+ bool initEntries)
+{
+ ndbrequire(lastPage <= xsf->noOfPages);
+ for (Uint32 n = firstPage; n < lastPage; n++) {
+ SchemaFile * sf = &xsf->schemaPage[n];
+ if (initEntries)
+ memset(sf, 0, NDB_SF_PAGE_SIZE);
+
+ Uint32 ndb_version = NDB_VERSION;
+ if (ndb_version < NDB_SF_VERSION_5_0_6)
+ ndb_version = NDB_SF_VERSION_5_0_6;
- sf->NoOfTableEntries = noEntries;
- memset(sf->TableEntries, 0, noEntries*sizeof(SchemaFile::TableEntry));
- memset(&(sf->TableEntries[noEntries]), 0, slack);
- computeChecksum(sf);
+ memcpy(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic));
+ sf->ByteOrder = 0x12345678;
+ sf->NdbVersion = ndb_version;
+ sf->FileSize = xsf->noOfPages * NDB_SF_PAGE_SIZE;
+ sf->PageNumber = n;
+ sf->CheckSum = 0;
+ sf->NoOfTableEntries = NDB_SF_PAGE_ENTRIES;
+
+ computeChecksum(xsf, n);
+ }
}
void
-Dbdict::computeChecksum(SchemaFile * sf){
+Dbdict::resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages)
+{
+ ndbrequire(noOfPages <= NDB_SF_MAX_PAGES);
+ if (xsf->noOfPages < noOfPages) {
+ jam();
+ Uint32 firstPage = xsf->noOfPages;
+ xsf->noOfPages = noOfPages;
+ initSchemaFile(xsf, 0, firstPage, false);
+ initSchemaFile(xsf, firstPage, xsf->noOfPages, true);
+ }
+ if (xsf->noOfPages > noOfPages) {
+ jam();
+ Uint32 tableId = noOfPages * NDB_SF_PAGE_ENTRIES;
+ while (tableId < xsf->noOfPages * NDB_SF_PAGE_ENTRIES) {
+ SchemaFile::TableEntry * te = getTableEntry(xsf, tableId);
+ if (te->m_tableState != SchemaFile::INIT &&
+ te->m_tableState != SchemaFile::DROP_TABLE_COMMITTED) {
+ ndbrequire(false);
+ }
+ tableId++;
+ }
+ xsf->noOfPages = noOfPages;
+ initSchemaFile(xsf, 0, xsf->noOfPages, false);
+ }
+}
+
+void
+Dbdict::computeChecksum(XSchemaFile * xsf, Uint32 pageNo){
+ SchemaFile * sf = &xsf->schemaPage[pageNo];
sf->CheckSum = 0;
- sf->CheckSum = computeChecksum((const Uint32*)sf, sf->FileSize/4);
+ sf->CheckSum = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
}
bool
-Dbdict::validateChecksum(const SchemaFile * sf){
+Dbdict::validateChecksum(const XSchemaFile * xsf){
- Uint32 c = computeChecksum((const Uint32*)sf, sf->FileSize/4);
- return c == 0;
+ for (Uint32 n = 0; n < xsf->noOfPages; n++) {
+ SchemaFile * sf = &xsf->schemaPage[n];
+ Uint32 c = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
+ if ( c != 0)
+ return false;
+ }
+ return true;
}
Uint32
@@ -11954,11 +12246,14 @@ Dbdict::computeChecksum(const Uint32 * src, Uint32 len){
}
SchemaFile::TableEntry *
-Dbdict::getTableEntry(void * p, Uint32 tableId, bool allowTooBig){
- SchemaFile * sf = (SchemaFile*)p;
-
- ndbrequire(allowTooBig || tableId < sf->NoOfTableEntries);
- return &sf->TableEntries[tableId];
+Dbdict::getTableEntry(XSchemaFile * xsf, Uint32 tableId)
+{
+ Uint32 n = tableId / NDB_SF_PAGE_ENTRIES;
+ Uint32 i = tableId % NDB_SF_PAGE_ENTRIES;
+ ndbrequire(n < xsf->noOfPages);
+
+ SchemaFile * sf = &xsf->schemaPage[n];
+ return &sf->TableEntries[i];
}
// global metadata support
@@ -12063,3 +12358,5 @@ Dbdict::getMetaAttribute(MetaData::Attribute& attr, const MetaData::Table& table
new (&attr) MetaData::Attribute(*attrPtr.p);
return 0;
}
+
+CArray<KeyDescriptor> g_key_descriptor_pool;
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index bcee4a52b6a..6b78fb86534 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -78,7 +78,8 @@
/*--------------------------------------------------------------*/
// Page constants
/*--------------------------------------------------------------*/
-#define ZALLOCATE 1 //Variable number of page for NDBFS
+#define ZBAT_SCHEMA_FILE 0 //Variable number of page for NDBFS
+#define ZBAT_TABLE_FILE 1 //Variable number of page for NDBFS
#define ZPAGE_HEADER_SIZE 32
#define ZPOS_PAGE_SIZE 16
#define ZPOS_CHECKSUM 17
@@ -92,7 +93,7 @@
#define ZSIZE_OF_PAGES_IN_WORDS 8192
#define ZLOG_SIZE_OF_PAGES_IN_WORDS 13
#define ZMAX_PAGES_OF_TABLE_DEFINITION 8
-#define ZNUMBER_OF_PAGES (2 * ZMAX_PAGES_OF_TABLE_DEFINITION + 2)
+#define ZNUMBER_OF_PAGES (ZMAX_PAGES_OF_TABLE_DEFINITION + 1)
#define ZNO_OF_FRAGRECORD 5
/*--------------------------------------------------------------*/
@@ -212,7 +213,9 @@ public:
IL_CREATED_TC = 1 << 0 // created in TC
};
Uint32 indexLocal;
-
+
+ Uint32 noOfNullBits;
+
inline bool equal(TableRecord & rec) const {
return strcmp(tableName, rec.tableName) == 0;
}
@@ -426,6 +429,12 @@ public:
typedef Ptr<PageRecord> PageRecordPtr;
CArray<PageRecord> c_pageRecordArray;
+ struct SchemaPageRecord {
+ Uint32 word[NDB_SF_PAGE_SIZE_IN_WORDS];
+ };
+
+ CArray<SchemaPageRecord> c_schemaPageRecordArray;
+
/**
* A page for create index table signal.
*/
@@ -653,16 +662,20 @@ private:
struct ReadSchemaRecord {
/** Page Id of schema page */
Uint32 pageId;
+ /** First page to read */
+ Uint32 firstPage;
+ /** Number of pages to read */
+ Uint32 noOfPages;
/** State, indicates from where it was called */
enum SchemaReadState {
IDLE = 0,
- INITIAL_READ = 1
+ INITIAL_READ_HEAD = 1,
+ INITIAL_READ = 2
};
SchemaReadState schemaReadState;
};
ReadSchemaRecord c_readSchemaRecord;
-private:
/**
* This record stores all the state needed
* when a schema file is being written to disk
@@ -670,6 +683,12 @@ private:
struct WriteSchemaRecord {
/** Page Id of schema page */
Uint32 pageId;
+ /** Rewrite entire file */
+ Uint32 newFile;
+ /** First page to write */
+ Uint32 firstPage;
+ /** Number of pages to write */
+ Uint32 noOfPages;
/** Schema Files Handled, local state variable */
Uint32 noOfSchemaFilesHandled;
@@ -750,21 +769,33 @@ private:
* Word 4: Currently zero
****************************************************************************/
struct SchemaRecord {
- /** Schema page */
+ /** Schema file first page (0) */
Uint32 schemaPage;
- /** Old Schema page (used at node restart) */
+ /** Old Schema file first page (used at node restart) */
Uint32 oldSchemaPage;
Callback m_callback;
};
SchemaRecord c_schemaRecord;
- void initSchemaFile(SchemaFile *, Uint32 sz);
- void computeChecksum(SchemaFile *);
- bool validateChecksum(const SchemaFile *);
- SchemaFile::TableEntry * getTableEntry(void * buf, Uint32 tableId,
- bool allowTooBig = false);
+ /*
+ * Schema file, list of schema pages. Use an array until a pool
+ * exists and NDBFS interface can use it.
+ */
+ struct XSchemaFile {
+ SchemaFile* schemaPage;
+ Uint32 noOfPages;
+ };
+ // 0-normal 1-old
+ XSchemaFile c_schemaFile[2];
+
+ void initSchemaFile(XSchemaFile *, Uint32 firstPage, Uint32 lastPage,
+ bool initEntries);
+ void resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages);
+ void computeChecksum(XSchemaFile *, Uint32 pageNo);
+ bool validateChecksum(const XSchemaFile *);
+ SchemaFile::TableEntry * getTableEntry(XSchemaFile *, Uint32 tableId);
Uint32 computeChecksum(const Uint32 * src, Uint32 len);
@@ -1713,7 +1744,8 @@ private:
bool getNewAttributeRecord(TableRecordPtr tablePtr,
AttributeRecordPtr & attrPtr);
void packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId);
- void packTableIntoPagesImpl(SimpleProperties::Writer &, TableRecordPtr);
+ void packTableIntoPagesImpl(SimpleProperties::Writer &, TableRecordPtr,
+ Signal* signal= 0);
void sendGET_TABINFOREQ(Signal* signal,
Uint32 tableId);
@@ -1761,7 +1793,8 @@ private:
void openSchemaFile(Signal* signal,
Uint32 fileNo,
Uint32 fsPtr,
- bool writeFlag);
+ bool writeFlag,
+ bool newFile);
void writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
void writeSchemaConf(Signal* signal,
FsConnectRecordPtr fsPtr);
@@ -1803,6 +1836,7 @@ private:
void readSchemaRef(Signal* signal, FsConnectRecordPtr fsPtr);
void closeReadSchemaConf(Signal* signal,
FsConnectRecordPtr fsPtr);
+ bool convertSchemaFileTo_5_0_6(XSchemaFile*);
/* ------------------------------------------------------------ */
// Get table definitions
diff --git a/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp b/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp
index 7c3223d3d14..0226991a073 100644
--- a/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp
+++ b/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp
@@ -18,16 +18,35 @@
#define DBDICT_SCHEMA_FILE_HPP
#include <ndb_types.h>
+#include <ndb_version.h>
#include <string.h>
+#define NDB_SF_MAGIC "NDBSCHMA"
+
+// page size 4k
+#define NDB_SF_PAGE_SIZE_IN_WORDS_LOG2 10
+#define NDB_SF_PAGE_SIZE_IN_WORDS (1 << NDB_SF_PAGE_SIZE_IN_WORDS_LOG2)
+#define NDB_SF_PAGE_SIZE (NDB_SF_PAGE_SIZE_IN_WORDS << 2)
+
+// 4k = (1 + 127) * 32
+#define NDB_SF_PAGE_ENTRIES 127
+
+// 160 pages = 20320 objects
+#define NDB_SF_MAX_PAGES 160
+
+// versions where format changed
+#define NDB_SF_VERSION_5_0_6 MAKE_VERSION(5, 0, 6)
+
+// One page in schema file.
struct SchemaFile {
+ // header size 32 bytes
char Magic[8];
Uint32 ByteOrder;
Uint32 NdbVersion;
Uint32 FileSize; // In bytes
- Uint32 Unused;
-
- Uint32 CheckSum;
+ Uint32 PageNumber;
+ Uint32 CheckSum; // Of this page
+ Uint32 NoOfTableEntries; // On this page (NDB_SF_PAGE_ENTRIES)
enum TableState {
INIT = 0,
@@ -38,20 +57,33 @@ struct SchemaFile {
ALTER_TABLE_COMMITTED = 5
};
+ // entry size 32 bytes
struct TableEntry {
Uint32 m_tableState;
Uint32 m_tableVersion;
Uint32 m_tableType;
- Uint32 m_noOfPages;
+ Uint32 m_info_words;
Uint32 m_gcp;
+ Uint32 m_unused[3];
bool operator==(const TableEntry& o) const {
return memcmp(this, &o, sizeof(* this))== 0;
}
};
+
+ // pre-5.0.6
+ struct TableEntry_old {
+ Uint32 m_tableState;
+ Uint32 m_tableVersion;
+ Uint32 m_tableType;
+ Uint32 m_noOfPages;
+ Uint32 m_gcp;
+ };
- Uint32 NoOfTableEntries;
- TableEntry TableEntries[1];
+ union {
+ TableEntry TableEntries[NDB_SF_PAGE_ENTRIES];
+ TableEntry_old TableEntries_old[1];
+ };
};
#endif
diff --git a/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp b/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
index 3e944485e1c..9858744a61d 100644
--- a/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
+++ b/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
@@ -1,7 +1,10 @@
#if 0
make -f Makefile -f - printSchemaFile <<'_eof_'
-printSchemaFile: printSchemaFile.cpp
+printSchemaFile: printSchemaFile.cpp SchemaFile.hpp
$(CXXCOMPILE) -o $@ $@.cpp -L../../../common/util/.libs -lgeneral
+ifneq ($(MYSQL_HOME),)
+ ln -sf `pwd`/$@ $(MYSQL_HOME)/bin/$@
+endif
_eof_
exit $?
#endif
@@ -24,19 +27,28 @@ exit $?
#include <ndb_global.h>
+#include <ndb_version.h>
#include <NdbMain.h>
#include <NdbOut.hpp>
#include <SchemaFile.hpp>
-void
-usage(const char * prg){
- ndbout << "Usage " << prg
- << " P0.SchemaLog" << endl;
+static const char* progname = 0;
+static bool allflag = false;
+static bool checkonly = false;
+static int xitcode = 0;
+
+static void
+usage()
+{
+ ndbout << "Usage " << progname
+ << " [-ac]"
+ << " P0.SchemaLog" << endl;
}
-void
-fill(const char * buf, int mod){
+static void
+fill(const char * buf, int mod)
+{
int len = strlen(buf)+1;
ndbout << buf << " ";
while((len % mod) != 0){
@@ -45,19 +57,34 @@ fill(const char * buf, int mod){
}
}
-void
-print(const char * filename, const SchemaFile * file){
- ndbout << "----- Schemafile: " << filename << " -----" << endl;
- ndbout_c("Magic: %.*s ByteOrder: %.8x NdbVersion: %d FileSize: %d",
- sizeof(file->Magic), file->Magic,
- file->ByteOrder,
- file->NdbVersion,
- file->FileSize);
-
- for(Uint32 i = 0; i<file->NoOfTableEntries; i++){
- SchemaFile::TableEntry te = file->TableEntries[i];
- if(te.m_tableState != SchemaFile::INIT){
- ndbout << "Table " << i << ": State = " << te.m_tableState
+static void
+print_head(const char * filename, const SchemaFile * sf)
+{
+ if (! checkonly) {
+ ndbout << "----- Schemafile: " << filename << " -----" << endl;
+ ndbout_c("Magic: %.*s ByteOrder: %.8x NdbVersion: %d.%d.%d FileSize: %d",
+ sizeof(sf->Magic),
+ sf->Magic,
+ sf->ByteOrder,
+ sf->NdbVersion >> 16,
+ (sf->NdbVersion >> 8) & 0xFF,
+ sf->NdbVersion & 0xFF,
+ sf->FileSize);
+ }
+}
+
+static void
+print_old(const char * filename, const SchemaFile * sf)
+{
+ print_head(filename, sf);
+
+ for (Uint32 i = 0; i < sf->NoOfTableEntries; i++) {
+ SchemaFile::TableEntry_old te = sf->TableEntries_old[i];
+ if (allflag ||
+ (te.m_tableState != SchemaFile::INIT &&
+ te.m_tableState != SchemaFile::DROP_TABLE_COMMITTED)) {
+ ndbout << "Table " << i << ":"
+ << " State = " << te.m_tableState
<< " version = " << table_version_major(te.m_tableVersion) <<
<< "(" << table_version_minor(te.m_tableVersion) << ")"
<< " type = " << te.m_tableType
@@ -67,47 +94,114 @@ print(const char * filename, const SchemaFile * file){
}
}
-NDB_COMMAND(printSchemafile,
- "printSchemafile", "printSchemafile", "Prints a schemafile", 16384){
- if(argc < 2){
- usage(argv[0]);
- return 0;
- }
+static void
+print(const char * filename, const SchemaFile * xsf, Uint32 sz)
+{
+ int retcode = 0;
- const char * filename = argv[1];
+ print_head(filename, xsf);
- struct stat sbuf;
- const int res = stat(filename, &sbuf);
- if(res != 0){
- ndbout << "Could not find file: \"" << filename << "\"" << endl;
- return 0;
+ assert(sizeof(SchemaFile) == NDB_SF_PAGE_SIZE);
+ if (xsf->FileSize != sz || xsf->FileSize % NDB_SF_PAGE_SIZE != 0) {
+ ndbout << "***** invalid FileSize " << xsf->FileSize << endl;
+ retcode = 1;
}
- const Uint32 bytes = sbuf.st_size;
-
- Uint32 * buf = new Uint32[bytes/4+1];
-
- FILE * f = fopen(filename, "rb");
- if(f == 0){
- ndbout << "Failed to open file" << endl;
- delete [] buf;
- return 0;
+ Uint32 noOfPages = xsf->FileSize / NDB_SF_PAGE_SIZE;
+ for (Uint32 n = 0; n < noOfPages; n++) {
+ if (! checkonly) {
+ ndbout << "----- Page: " << n << " (" << noOfPages << ") -----" << endl;
+ }
+ const SchemaFile * sf = &xsf[n];
+ if (sf->FileSize != xsf->FileSize) {
+ ndbout << "***** page " << n << " FileSize changed to " << sf->FileSize << "!=" << xsf->FileSize << endl;
+ retcode = 1;
+ }
+ Uint32 cs = 0;
+ for (Uint32 j = 0; j < NDB_SF_PAGE_SIZE_IN_WORDS; j++)
+ cs ^= ((const Uint32*)sf)[j];
+ if (cs != 0) {
+ ndbout << "***** page " << n << " invalid CheckSum" << endl;
+ retcode = 1;
+ }
+ if (sf->NoOfTableEntries != NDB_SF_PAGE_ENTRIES) {
+ ndbout << "***** page " << n << " invalid NoOfTableEntries " << sf->NoOfTableEntries << endl;
+ retcode = 1;
+ }
+ for (Uint32 i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
+ SchemaFile::TableEntry te = sf->TableEntries[i];
+ Uint32 j = n * NDB_SF_PAGE_ENTRIES + i;
+ if (allflag ||
+ (te.m_tableState != SchemaFile::INIT &&
+ te.m_tableState != SchemaFile::DROP_TABLE_COMMITTED)) {
+ if (! checkonly)
+ ndbout << "Table " << j << ":"
+ << " State = " << te.m_tableState
+ << " version = " << te.m_tableVersion
+ << " type = " << te.m_tableType
+ << " noOfWords = " << te.m_info_words
+ << " gcp: " << te.m_gcp << endl;
+ }
+ if (te.m_unused[0] != 0 || te.m_unused[1] != 0 || te.m_unused[2] != 0) {
+ ndbout << "***** entry " << j << " garbage in m_unused[3]" << endl;
+ retcode = 1;
+ }
+ }
}
- Uint32 sz = fread(buf, 1, bytes, f);
- fclose(f);
- if(sz != bytes){
- ndbout << "Failure while reading file" << endl;
- delete [] buf;
- return 0;
+
+ if (retcode != 0)
+ xitcode = 1;
+ else if (checkonly)
+ ndbout << "ok: " << filename << endl;
+}
+
+NDB_COMMAND(printSchemafile,
+ "printSchemafile", "printSchemafile", "Prints a schemafile", 16384)
+{
+ progname = argv[0];
+
+ while (argv[1][0] == '-') {
+ if (strchr(argv[1], 'a') != 0)
+ allflag = true;
+ if (strchr(argv[1], 'c') != 0)
+ checkonly = true;
+ argc--, argv++;
}
-
- print(filename, (SchemaFile *)&buf[0]);
- Uint32 chk = 0, i;
- for (i = 0; i < bytes/4; i++)
- chk ^= buf[i];
- if (chk != 0)
- ndbout << "Invalid checksum!" << endl;
+ while (argc > 1) {
+ const char * filename = argv[1];
+ argc--, argv++;
+
+ struct stat sbuf;
+ const int res = stat(filename, &sbuf);
+ if (res != 0) {
+ ndbout << "Could not find file: \"" << filename << "\"" << endl;
+ return 1;
+ }
+ const Uint32 bytes = sbuf.st_size;
+
+ Uint32 * buf = new Uint32[bytes/4+1];
+
+ FILE * f = fopen(filename, "rb");
+ if (f == 0) {
+ ndbout << "Failed to open file" << endl;
+ delete [] buf;
+ return 1;
+ }
+ Uint32 sz = fread(buf, 1, bytes, f);
+ fclose(f);
+ if (sz != bytes) {
+ ndbout << "Failure while reading file" << endl;
+ delete [] buf;
+ return 1;
+ }
+
+ SchemaFile* sf = (SchemaFile *)&buf[0];
+ if (sf->NdbVersion < NDB_SF_VERSION_5_0_6)
+ print_old(filename, sf);
+ else
+ print(filename, sf, sz);
+ delete [] buf;
+ }
- delete [] buf;
- return 0;
+ return xitcode;
}
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index ca066b588e7..72051777959 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -247,7 +247,7 @@ void Dbdih::sendSTART_RECREQ(Signal* signal, Uint32 nodeId)
req->newestGci = SYSFILE->newestRestorableGCI;
sendSignal(ref, GSN_START_RECREQ, signal, StartRecReq::SignalLength, JBB);
- signal->theData[0] = EventReport::StartREDOLog;
+ signal->theData[0] = NDB_LE_StartREDOLog;
signal->theData[1] = nodeId;
signal->theData[2] = SYSFILE->keepGCI;
signal->theData[3] = SYSFILE->lastCompletedGCI[nodeId];
@@ -1815,7 +1815,7 @@ void Dbdih::nodeDictStartConfLab(Signal* signal)
/*-----------------------------------------------------------------*/
// Report that node restart has completed copy of dictionary.
/*-----------------------------------------------------------------*/
- signal->theData[0] = EventReport::NR_CopyDict;
+ signal->theData[0] = NDB_LE_NR_CopyDict;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
}//Dbdih::nodeDictStartConfLab()
@@ -1836,7 +1836,7 @@ void Dbdih::gcpBlockedLab(Signal* signal)
/*-----------------------------------------------------------------*/
// Report that node restart has completed copy of distribution info.
/*-----------------------------------------------------------------*/
- signal->theData[0] = EventReport::NR_CopyDistr;
+ signal->theData[0] = NDB_LE_NR_CopyDistr;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
/**
@@ -1989,7 +1989,7 @@ void Dbdih::execSTART_COPYREQ(Signal* signal)
/*-------------------------------------------------------------------------*/
// REPORT Copy process of node restart is now about to start up.
/*-------------------------------------------------------------------------*/
- signal->theData[0] = EventReport::NR_CopyFragsStarted;
+ signal->theData[0] = NDB_LE_NR_CopyFragsStarted;
signal->theData[1] = startNodeId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -2954,7 +2954,7 @@ void Dbdih::execCREATE_FRAGCONF(Signal* signal)
/* --------------------------------------------------------------------- */
// REPORT that copy of fragment has been completed.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NR_CopyFragDone;
+ signal->theData[0] = NDB_LE_NR_CopyFragDone;
signal->theData[1] = takeOverPtr.p->toStartingNode;
signal->theData[2] = tabPtr.i;
signal->theData[3] = takeOverPtr.p->toCurrentFragid;
@@ -3192,7 +3192,7 @@ Dbdih::switchPrimaryMutex_locked(Signal* signal, Uint32 toPtrI, Uint32 retVal){
void Dbdih::toCopyCompletedLab(Signal * signal, TakeOverRecordPtr takeOverPtr)
{
- signal->theData[0] = EventReport::NR_CopyFragsCompleted;
+ signal->theData[0] = NDB_LE_NR_CopyFragsCompleted;
signal->theData[1] = takeOverPtr.p->toStartingNode;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -4477,7 +4477,7 @@ void Dbdih::startGcpMasterTakeOver(Signal* signal, Uint32 oldMasterId){
sendLoopMacro(MASTER_GCPREQ, sendMASTER_GCPREQ);
cgcpMasterTakeOverState = GMTOS_INITIAL;
- signal->theData[0] = EventReport::GCP_TakeoverStarted;
+ signal->theData[0] = NDB_LE_GCP_TakeoverStarted;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
setLocalNodefailHandling(signal, oldMasterId, NF_GCP_TAKE_OVER);
@@ -4986,7 +4986,7 @@ void Dbdih::MASTER_GCPhandling(Signal* signal, Uint32 failedNodeId)
break;
}//switch
- signal->theData[0] = EventReport::GCP_TakeoverCompleted;
+ signal->theData[0] = NDB_LE_GCP_TakeoverCompleted;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
/*--------------------------------------------------*/
@@ -5419,7 +5419,7 @@ Dbdih::checkEmptyLcpComplete(Signal *signal){
if(isMaster()){
jam();
- signal->theData[0] = EventReport::LCP_TakeoverStarted;
+ signal->theData[0] = NDB_LE_LCP_TakeoverStarted;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
signal->theData[0] = 7012;
@@ -5891,7 +5891,7 @@ void Dbdih::MASTER_LCPhandling(Signal* signal, Uint32 failedNodeId)
ndbrequire(false);
break;
}//switch
- signal->theData[0] = EventReport::LCP_TakeoverCompleted;
+ signal->theData[0] = NDB_LE_LCP_TakeoverCompleted;
signal->theData[1] = c_lcpMasterTakeOverState.state;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -5926,7 +5926,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* -------------------------------------------------------------------- */
// Report the event that DBTC completed node failure handling.
/* -------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = DBTC;
signal->theData[2] = failedNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -5939,7 +5939,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* --------------------------------------------------------------------- */
// Report the event that DBDICT completed node failure handling.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = DBDICT;
signal->theData[2] = failedNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -5952,7 +5952,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* --------------------------------------------------------------------- */
// Report the event that DBDIH completed node failure handling.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = DBDIH;
signal->theData[2] = failedNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -5965,7 +5965,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* --------------------------------------------------------------------- */
// Report the event that DBDIH completed node failure handling.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = DBLQH;
signal->theData[2] = failedNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -6000,7 +6000,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* -------------------------------------------------------------------- */
// Report the event that nodeId has completed node failure handling.
/* -------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = 0;
signal->theData[2] = failedNodePtr.i;
signal->theData[3] = nodeId;
@@ -6073,7 +6073,7 @@ void Dbdih::nodeFailCompletedCheckLab(Signal* signal,
/* ---------------------------------------------------------------------- */
// Report the event that all nodes completed node failure handling.
/* ---------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = 0;
signal->theData[2] = failedNodePtr.i;
signal->theData[3] = 0;
@@ -6228,9 +6228,12 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
if (primaryTableId == RNIL) {
if(fragmentNode == 0){
jam();
- // needs to be fixed for single fragment tables
- NGPtr.i = 0; //c_nextNodeGroup;
- c_nextNodeGroup = (NGPtr.i + 1 == cnoOfNodeGroups ? 0 : NGPtr.i + 1);
+ NGPtr.i = 0;
+ if(noOfFragments < csystemnodes)
+ {
+ NGPtr.i = c_nextNodeGroup;
+ c_nextNodeGroup = (NGPtr.i + 1 == cnoOfNodeGroups ? 0 : NGPtr.i + 1);
+ }
} else if(! (fragmentNode < MAX_NDB_NODES)) {
jam();
err = CreateFragmentationRef::InvalidNodeId;
@@ -6283,33 +6286,28 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
}
}
- //@todo use section writer
Uint32 count = 2;
- Uint32 fragments[2 + 8*MAX_REPLICAS*MAX_NDB_NODES];
- Uint32 next_replica_node[MAX_NDB_NODES];
- memset(next_replica_node,0,sizeof(next_replica_node));
+ Uint16 *fragments = (Uint16*)(signal->theData+25);
if (primaryTableId == RNIL) {
jam();
+ Uint8 next_replica_node[MAX_NDB_NODES];
+ memset(next_replica_node,0,sizeof(next_replica_node));
for(Uint32 fragNo = 0; fragNo<noOfFragments; fragNo++){
jam();
ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
-
- Uint32 ind = next_replica_node[NGPtr.i];
const Uint32 max = NGPtr.p->nodeCount;
-
- //-------------------------------------------------------------------
- // We make an extra step to ensure that the primary replicas are
- // spread among the nodes.
- //-------------------------------------------------------------------
- next_replica_node[NGPtr.i] = (ind + 1 >= max ? 0 : ind + 1);
-
- for(Uint32 replicaNo = 0; replicaNo<noOfReplicas; replicaNo++){
+
+ Uint32 tmp= next_replica_node[NGPtr.i];
+ for(Uint32 replicaNo = 0; replicaNo<noOfReplicas; replicaNo++)
+ {
jam();
- const Uint32 nodeId = NGPtr.p->nodesInGroup[ind++];
+ const Uint32 nodeId = NGPtr.p->nodesInGroup[tmp++];
fragments[count++] = nodeId;
- ind = (ind == max ? 0 : ind);
+ tmp = (tmp >= max ? 0 : tmp);
}
-
+ tmp++;
+ next_replica_node[NGPtr.i]= (tmp >= max ? 0 : tmp);
+
/**
* Next node group for next fragment
*/
@@ -6358,26 +6356,42 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
fragments[0] = noOfReplicas;
fragments[1] = noOfFragments;
- LinearSectionPtr ptr[3];
- ptr[0].p = &fragments[0];
- ptr[0].sz = count;
- sendSignal(senderRef,
- GSN_CREATE_FRAGMENTATION_CONF,
- signal,
- CreateFragmentationConf::SignalLength,
- JBB,
- ptr,
- 1);
+ if(senderRef != 0)
+ {
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)&fragments[0];
+ ptr[0].sz = (count + 1) / 2;
+ sendSignal(senderRef,
+ GSN_CREATE_FRAGMENTATION_CONF,
+ signal,
+ CreateFragmentationConf::SignalLength,
+ JBB,
+ ptr,
+ 1);
+ }
+ else
+ {
+ // Execute direct
+ signal->theData[0] = 0;
+ }
return;
} while(false);
-
- CreateFragmentationRef * const ref =
- (CreateFragmentationRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->errorCode = err;
- sendSignal(senderRef, GSN_CREATE_FRAGMENTATION_REF, signal,
- CreateFragmentationRef::SignalLength, JBB);
+
+ if(senderRef != 0)
+ {
+ CreateFragmentationRef * const ref =
+ (CreateFragmentationRef*)signal->getDataPtrSend();
+ ref->senderRef = reference();
+ ref->senderData = senderData;
+ ref->errorCode = err;
+ sendSignal(senderRef, GSN_CREATE_FRAGMENTATION_REF, signal,
+ CreateFragmentationRef::SignalLength, JBB);
+ }
+ else
+ {
+ // Execute direct
+ signal->theData[0] = err;
+ }
}
void Dbdih::execDIADDTABREQ(Signal* signal)
@@ -6445,12 +6459,15 @@ void Dbdih::execDIADDTABREQ(Signal* signal)
tabPtr.p->method = TabRecord::HASH;
tabPtr.p->kvalue = req->kValue;
- Uint32 fragments[2 + 8*MAX_REPLICAS*MAX_NDB_NODES];
+ union {
+ Uint16 fragments[2 + MAX_FRAG_PER_NODE*MAX_REPLICAS*MAX_NDB_NODES];
+ Uint32 align;
+ };
SegmentedSectionPtr fragDataPtr;
signal->getSection(fragDataPtr, DiAddTabReq::FRAGMENTATION);
- copy(fragments, fragDataPtr);
+ copy((Uint32*)fragments, fragDataPtr);
releaseSections(signal);
-
+
const Uint32 noReplicas = fragments[0];
const Uint32 noFragments = fragments[1];
@@ -6459,6 +6476,7 @@ void Dbdih::execDIADDTABREQ(Signal* signal)
ndbrequire(noReplicas == cnoReplicas); // Only allowed
if (ERROR_INSERTED(7173)) {
+ CLEAR_ERROR_INSERT_VALUE;
addtabrefuseLab(signal, connectPtr, ZREPLERROR1);
return;
}
@@ -6878,8 +6896,7 @@ void Dbdih::execDIGETNODESREQ(Signal* signal)
TabRecord* regTabDesc = tabRecord;
jamEntry();
ptrCheckGuard(tabPtr, ttabFileSize, regTabDesc);
- hashValue = hashValue >> tabPtr.p->kvalue;
- Uint32 fragId = tabPtr.p->mask & hashValue;
+ Uint32 fragId = hashValue & tabPtr.p->mask;
ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
if (fragId < tabPtr.p->hashpointer) {
jam();
@@ -7240,7 +7257,7 @@ void Dbdih::startGcpLab(Signal* signal, Uint32 aWaitTime)
/***************************************************************************/
// Report the event that a global checkpoint has started.
/***************************************************************************/
- signal->theData[0] = EventReport::GlobalCheckpointStarted; //Event type
+ signal->theData[0] = NDB_LE_GlobalCheckpointStarted; //Event type
signal->theData[1] = cnewgcp;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -7485,6 +7502,22 @@ void Dbdih::execDIHNDBTAMPER(Signal* signal)
#ifdef ERROR_INSERT
case 5:
jam();
+ if(tuserpointer == 0)
+ {
+ jam();
+ signal->theData[0] = 0;
+ sendSignal(QMGR_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(NDBCNTR_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(NDBFS_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBACC_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBTUP_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBLQH_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBDICT_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBDIH_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBTC_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(CMVMI_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ return;
+ }
/*----------------------------------------------------------------------*/
// Insert errors.
/*----------------------------------------------------------------------*/
@@ -7703,7 +7736,7 @@ void Dbdih::execCOPY_GCICONF(Signal* signal)
// Report the event that a global checkpoint has completed.
/************************************************************************/
signal->setTrace(0);
- signal->theData[0] = EventReport::GlobalCheckpointCompleted; //Event type
+ signal->theData[0] = NDB_LE_GlobalCheckpointCompleted; //Event type
signal->theData[1] = coldgcp;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -9206,7 +9239,7 @@ void Dbdih::execTCGETOPSIZECONF(Signal* signal)
ndbrequire(((int)c_lcpState.oldestRestorableGci) > 0);
if (ERROR_INSERTED(7011)) {
- signal->theData[0] = EventReport::LCPStoppedInCalcKeepGci;
+ signal->theData[0] = NDB_LE_LCPStoppedInCalcKeepGci;
signal->theData[1] = 0;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
return;
@@ -9292,7 +9325,7 @@ void Dbdih::storeNewLcpIdLab(Signal* signal)
/***************************************************************************/
// Report the event that a local checkpoint has started.
/***************************************************************************/
- signal->theData[0] = EventReport::LocalCheckpointStarted; //Event type
+ signal->theData[0] = NDB_LE_LocalCheckpointStarted; //Event type
signal->theData[1] = SYSFILE->latestLCP_ID + 1;
signal->theData[2] = c_lcpState.keepGci;
signal->theData[3] = c_lcpState.oldestRestorableGci;
@@ -9672,7 +9705,7 @@ void Dbdih::execLCP_FRAG_REP(Signal* signal)
/* --------------------------------------------------------------------- */
// REPORT that local checkpoint have completed this fragment.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::LCPFragmentCompleted;
+ signal->theData[0] = NDB_LE_LCPFragmentCompleted;
signal->theData[1] = nodeId;
signal->theData[2] = tableId;
signal->theData[3] = fragId;
@@ -10123,7 +10156,7 @@ void Dbdih::allNodesLcpCompletedLab(Signal* signal)
/***************************************************************************/
// Report the event that a local checkpoint has completed.
/***************************************************************************/
- signal->theData[0] = EventReport::LocalCheckpointCompleted; //Event type
+ signal->theData[0] = NDB_LE_LocalCheckpointCompleted; //Event type
signal->theData[1] = SYSFILE->latestLCP_ID;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -10280,7 +10313,87 @@ void Dbdih::tableCloseLab(Signal* signal, FileRecordPtr filePtr)
* GCP stop detected,
* send SYSTEM_ERROR to all other alive nodes
*/
-void Dbdih::crashSystemAtGcpStop(Signal* signal){
+void Dbdih::crashSystemAtGcpStop(Signal* signal)
+{
+ switch(cgcpStatus){
+ case GCP_NODE_FINISHED:
+ {
+ /**
+ * We're waiting for a GCP save conf
+ */
+ ndbrequire(!c_GCP_SAVEREQ_Counter.done());
+ NodeReceiverGroup rg(DBLQH, c_GCP_SAVEREQ_Counter);
+ signal->theData[0] = 2305;
+ sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
+
+ infoEvent("Detected GCP stop...sending kill to %s",
+ c_GCP_SAVEREQ_Counter.getText());
+ ndbout_c("Detected GCP stop...sending kill to %s",
+ c_GCP_SAVEREQ_Counter.getText());
+ return;
+ }
+ case GCP_SAVE_LQH_FINISHED:
+ ndbout_c("m_copyReason: %d m_waiting: %d",
+ c_copyGCIMaster.m_copyReason,
+ c_copyGCIMaster.m_waiting);
+ break;
+ }
+
+ ndbout_c("c_copyGCISlave: sender{Data, Ref} %d %x reason: %d nextWord: %d",
+ c_copyGCISlave.m_senderData,
+ c_copyGCISlave.m_senderRef,
+ c_copyGCISlave.m_copyReason,
+ c_copyGCISlave.m_expectedNextWord);
+
+ FileRecordPtr file0Ptr;
+ file0Ptr.i = crestartInfoFile[0];
+ ptrCheckGuard(file0Ptr, cfileFileSize, fileRecord);
+ FileRecordPtr file1Ptr;
+ file1Ptr.i = crestartInfoFile[1];
+ ptrCheckGuard(file1Ptr, cfileFileSize, fileRecord);
+
+ ndbout_c("file[0] status: %d type: %d reqStatus: %d file1: %d %d %d",
+ file0Ptr.p->fileStatus, file0Ptr.p->fileType, file0Ptr.p->reqStatus,
+ file1Ptr.p->fileStatus, file1Ptr.p->fileType, file1Ptr.p->reqStatus
+ );
+
+ signal->theData[0] = 404;
+ signal->theData[1] = file0Ptr.p->fileRef;
+ EXECUTE_DIRECT(NDBFS, GSN_DUMP_STATE_ORD, signal, 2);
+
+ signal->theData[0] = 404;
+ signal->theData[1] = file1Ptr.p->fileRef;
+ EXECUTE_DIRECT(NDBFS, GSN_DUMP_STATE_ORD, signal, 2);
+
+ ndbout_c("c_COPY_GCIREQ_Counter = %s",
+ c_COPY_GCIREQ_Counter.getText());
+ ndbout_c("c_COPY_TABREQ_Counter = %s",
+ c_COPY_TABREQ_Counter.getText());
+ ndbout_c("c_CREATE_FRAGREQ_Counter = %s",
+ c_CREATE_FRAGREQ_Counter.getText());
+ ndbout_c("c_DIH_SWITCH_REPLICA_REQ_Counter = %s",
+ c_DIH_SWITCH_REPLICA_REQ_Counter.getText());
+ ndbout_c("c_EMPTY_LCP_REQ_Counter = %s",c_EMPTY_LCP_REQ_Counter.getText());
+ ndbout_c("c_END_TOREQ_Counter = %s", c_END_TOREQ_Counter.getText());
+ ndbout_c("c_GCP_COMMIT_Counter = %s", c_GCP_COMMIT_Counter.getText());
+ ndbout_c("c_GCP_PREPARE_Counter = %s", c_GCP_PREPARE_Counter.getText());
+ ndbout_c("c_GCP_SAVEREQ_Counter = %s", c_GCP_SAVEREQ_Counter.getText());
+ ndbout_c("c_INCL_NODEREQ_Counter = %s", c_INCL_NODEREQ_Counter.getText());
+ ndbout_c("c_MASTER_GCPREQ_Counter = %s",
+ c_MASTER_GCPREQ_Counter.getText());
+ ndbout_c("c_MASTER_LCPREQ_Counter = %s",
+ c_MASTER_LCPREQ_Counter.getText());
+ ndbout_c("c_START_INFOREQ_Counter = %s",
+ c_START_INFOREQ_Counter.getText());
+ ndbout_c("c_START_RECREQ_Counter = %s", c_START_RECREQ_Counter.getText());
+ ndbout_c("c_START_TOREQ_Counter = %s", c_START_TOREQ_Counter.getText());
+ ndbout_c("c_STOP_ME_REQ_Counter = %s", c_STOP_ME_REQ_Counter.getText());
+ ndbout_c("c_TC_CLOPSIZEREQ_Counter = %s",
+ c_TC_CLOPSIZEREQ_Counter.getText());
+ ndbout_c("c_TCGETOPSIZEREQ_Counter = %s",
+ c_TCGETOPSIZEREQ_Counter.getText());
+ ndbout_c("c_UPDATE_TOREQ_Counter = %s", c_UPDATE_TOREQ_Counter.getText());
+
NodeRecordPtr nodePtr;
for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
jam();
@@ -11452,7 +11565,6 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
NodeRecordPtr mngNodeptr;
Uint32 tmngNode;
Uint32 tmngNodeGroup;
- Uint32 tmngReplica;
Uint32 tmngLimit;
Uint32 i;
@@ -11461,7 +11573,6 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
* TO NODE GROUP ZNIL
*-----------------------------------------------------------------------*/
tmngNodeGroup = 0;
- tmngReplica = 0;
tmngLimit = csystemnodes - cnoHotSpare;
ndbrequire(tmngLimit < MAX_NDB_NODES);
for (i = 0; i < tmngLimit; i++) {
@@ -11473,13 +11584,11 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
mngNodeptr.p->nodeGroup = tmngNodeGroup;
NGPtr.i = tmngNodeGroup;
ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- arrGuard(tmngReplica, MAX_REPLICAS);
- NGPtr.p->nodesInGroup[tmngReplica] = mngNodeptr.i;
- tmngReplica++;
- if (tmngReplica == cnoReplicas) {
+ arrGuard(NGPtr.p->nodeCount, MAX_REPLICAS);
+ NGPtr.p->nodesInGroup[NGPtr.p->nodeCount++] = mngNodeptr.i;
+ if (NGPtr.p->nodeCount == cnoReplicas) {
jam();
tmngNodeGroup++;
- tmngReplica = 0;
}//if
}//for
cnoOfNodeGroups = tmngNodeGroup;
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index 951d1e90251..81fd61520cf 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -29,6 +29,9 @@
#include <signaldata/LqhTransConf.hpp>
#include <signaldata/LqhFrag.hpp>
+// primary key is stored in TUP
+#include <../dbtup/Dbtup.hpp>
+
#ifdef DBLQH_C
// Constants
/* ------------------------------------------------------------------------- */
@@ -511,9 +514,7 @@ public:
WAIT_DELETE_STORED_PROC_ID_COPY = 6,
WAIT_ACC_COPY = 7,
WAIT_ACC_SCAN = 8,
- WAIT_SCAN_KEYINFO = 9,
WAIT_SCAN_NEXTREQ = 10,
- WAIT_COPY_KEYINFO = 11,
WAIT_CLOSE_SCAN = 12,
WAIT_CLOSE_COPY = 13,
WAIT_RELEASE_LOCK = 14,
@@ -575,6 +576,9 @@ public:
NodeId scanNodeId;
Uint16 scanReleaseCounter;
Uint16 scanNumber;
+
+ // scan source block ACC TUX TUP
+ BlockReference scanBlockref;
Uint8 scanCompletedStatus;
Uint8 scanFlag;
@@ -582,6 +586,8 @@ public:
Uint8 scanLockMode;
Uint8 readCommitted;
Uint8 rangeScan;
+ Uint8 descending;
+ Uint8 tupScan;
Uint8 scanTcWaiting;
Uint8 scanKeyinfoFlag;
Uint8 m_last_row;
@@ -878,10 +884,6 @@ public:
*/
Uint8 fragDistributionKey;
/**
- * Used to calculate which local fragment to use.
- */
- Uint8 hashCheckBit;
- /**
* The identity of the next local checkpoint this fragment
* should perform.
*/
@@ -2021,8 +2023,10 @@ public:
BlockReference tcTuxBlockref;
BlockReference tcTupBlockref;
Uint32 commitAckMarker;
- UintR noFiredTriggers;
-
+ union {
+ Uint32 m_scan_curr_range_no;
+ UintR noFiredTriggers;
+ };
Uint16 errorCode;
Uint16 logStartPageIndex;
Uint16 logStartPageNo;
@@ -2044,6 +2048,7 @@ public:
Uint8 opExec;
Uint8 operation;
Uint8 reclenAiLqhkey;
+ Uint8 m_offset_current_keybuf;
Uint8 replicaType;
Uint8 simpleRead;
Uint8 seqNoReplica;
@@ -2147,8 +2152,6 @@ private:
void execACC_SCANREF(Signal* signal);
void execNEXT_SCANCONF(Signal* signal);
void execNEXT_SCANREF(Signal* signal);
- void execACC_SCAN_INFO(Signal* signal);
- void execACC_SCAN_INFO24(Signal* signal);
void execACC_TO_REF(Signal* signal);
void execSTORED_PROCCONF(Signal* signal);
void execSTORED_PROCREF(Signal* signal);
@@ -2238,7 +2241,7 @@ private:
void LQHKEY_abort(Signal* signal, int errortype);
void LQHKEY_error(Signal* signal, int errortype);
void nextRecordCopy(Signal* signal);
- void calculateHash(Signal* signal);
+ Uint32 calculateHash(Uint32 tableId, const Uint32* src);
void continueAfterCheckLcpStopBlocked(Signal* signal);
void checkLcpStopBlockedLab(Signal* signal);
void sendCommittedTc(Signal* signal, BlockReference atcBlockref);
@@ -2266,7 +2269,7 @@ private:
void finishScanrec(Signal* signal);
void releaseScanrec(Signal* signal);
void seizeScanrec(Signal* signal);
- void sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *);
+ Uint32 sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *);
void sendScanFragConf(Signal* signal, Uint32 scanCompleted);
void initCopyrec(Signal* signal);
void initCopyTc(Signal* signal);
@@ -2396,6 +2399,8 @@ private:
void seizeAttrinbuf(Signal* signal);
Uint32 seize_attrinbuf();
Uint32 release_attrinbuf(Uint32);
+ Uint32 copy_bounds(Uint32 * dst, TcConnectionrec*);
+
void seizeFragmentrec(Signal* signal);
void seizePageRef(Signal* signal);
void seizeTcrec();
@@ -2444,7 +2449,6 @@ private:
void localCommitLab(Signal* signal);
void abortErrorLab(Signal* signal);
void continueAfterReceivingAllAiLab(Signal* signal);
- void sendScanFragRefLateLab(Signal* signal);
void abortStateHandlerLab(Signal* signal);
void writeAttrinfoLab(Signal* signal);
void scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
@@ -2511,7 +2515,7 @@ private:
void nextScanConfScanLab(Signal* signal);
void nextScanConfCopyLab(Signal* signal);
void continueScanNextReqLab(Signal* signal);
- bool keyinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
+ void keyinfoLab(const Uint32 * src, const Uint32 * end);
void copySendTupkeyReqLab(Signal* signal);
void storedProcConfScanLab(Signal* signal);
void storedProcConfCopyLab(Signal* signal);
@@ -2567,7 +2571,6 @@ private:
void accScanConfScanLab(Signal* signal);
void accScanConfCopyLab(Signal* signal);
void scanLockReleasedLab(Signal* signal);
- void accScanInfoEnterLab(Signal* signal, Uint32* dataPtr, Uint32 length);
void openSrFourthNextLab(Signal* signal);
void closingInitLab(Signal* signal);
void closeExecSrCompletedLab(Signal* signal);
@@ -2582,6 +2585,8 @@ private:
void initData();
void initRecords();
+ Dbtup* c_tup;
+ Uint32 readPrimaryKeys(ScanRecord*, TcConnectionrec*, Uint32 * dst);
// ----------------------------------------------------------------
// These are variables handling the records. For most records one
// pointer to the array of structs, one pointer-struct, a file size
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
index f9dd63e782d..04400f75255 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
@@ -273,8 +273,6 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_ACC_SCANREF, &Dblqh::execACC_SCANREF);
addRecSignal(GSN_NEXT_SCANCONF, &Dblqh::execNEXT_SCANCONF);
addRecSignal(GSN_NEXT_SCANREF, &Dblqh::execNEXT_SCANREF);
- addRecSignal(GSN_ACC_SCAN_INFO, &Dblqh::execACC_SCAN_INFO);
- addRecSignal(GSN_ACC_SCAN_INFO24, &Dblqh::execACC_SCAN_INFO24);
addRecSignal(GSN_STORED_PROCCONF, &Dblqh::execSTORED_PROCCONF);
addRecSignal(GSN_STORED_PROCREF, &Dblqh::execSTORED_PROCREF);
addRecSignal(GSN_COPY_FRAGREQ, &Dblqh::execCOPY_FRAGREQ);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index b6178227d31..365c28f1229 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -55,6 +55,7 @@
#include <signaldata/AlterTab.hpp>
#include <signaldata/LCP.hpp>
+#include <KeyDescriptor.hpp>
// Use DEBUG to print messages that should be
// seen only when we debug the product
@@ -169,6 +170,8 @@ void Dblqh::execTUP_COM_UNBLOCK(Signal* signal)
/* ------------------------------------------------------------------------- */
void Dblqh::systemError(Signal* signal)
{
+ signal->theData[0] = 2304;
+ execDUMP_STATE_ORD(signal);
progError(0, 0);
}//Dblqh::systemError()
@@ -420,7 +423,7 @@ void Dblqh::execCONTINUEB(Signal* signal)
// Report information about transaction activity once per second.
/* --------------------------------------------------------------------- */
if (signal->theData[1] == 0) {
- signal->theData[0] = EventReport::OperationReportCounters;
+ signal->theData[0] = NDB_LE_OperationReportCounters;
signal->theData[1] = c_Counters.operations;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
}//if
@@ -490,6 +493,8 @@ void Dblqh::execSTTOR(Signal* signal)
jam();
cstartPhase = tstartPhase;
sttorStartphase1Lab(signal);
+ c_tup = (Dbtup*)globalData.getBlock(DBTUP);
+ ndbrequire(c_tup != 0);
return;
break;
default:
@@ -1087,8 +1092,8 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
if (DictTabInfo::isOrderedIndex(tableType)) {
jam();
// NOTE: next 2 lines stolen from ACC
- addfragptr.p->fragid1 = (0 << tlhstar) | fragId;
- addfragptr.p->fragid2 = (1 << tlhstar) | fragId;
+ addfragptr.p->fragid1 = (fragId << 1) | 0;
+ addfragptr.p->fragid2 = (fragId << 1) | 1;
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
sendAddFragReq(signal);
return;
@@ -1108,7 +1113,6 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
Uint32 fragId2 = signal->theData[3];
Uint32 accFragPtr1 = signal->theData[4];
Uint32 accFragPtr2 = signal->theData[5];
- Uint32 hashCheckBit = signal->theData[6];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
@@ -1119,7 +1123,6 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
fragptr.p->accFragptr[0] = accFragPtr1;
fragptr.p->accFragptr[1] = accFragPtr2;
- fragptr.p->hashCheckBit = hashCheckBit;
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
sendAddFragReq(signal);
@@ -1277,7 +1280,7 @@ Dblqh::sendAddFragReq(Signal* signal)
tuxreq->noOfAttr = addfragptr.p->noOfAttr - 1; /* skip NDB$TNODE */
tuxreq->fragId =
addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUX
- ? addfragptr.p->fragid1 : addfragptr.p->fragid2;
+ ? addfragptr.p->fragid1: addfragptr.p->fragid2;
tuxreq->fragOff = addfragptr.p->lh3DistrBits;
tuxreq->tableType = addfragptr.p->tableType;
tuxreq->primaryTableId = addfragptr.p->primaryTableId;
@@ -2075,7 +2078,7 @@ void Dblqh::execTIME_SIGNAL(Signal* signal)
if ((cCounterAccCommitBlocked > 0) ||
(cCounterTupCommitBlocked > 0)) {
jam();
- signal->theData[0] = EventReport::UndoLogBlocked;
+ signal->theData[0] = NDB_LE_UndoLogBlocked;
signal->theData[1] = cCounterTupCommitBlocked;
signal->theData[2] = cCounterAccCommitBlocked;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -2619,12 +2622,20 @@ Dblqh::execREAD_PSUEDO_REQ(Signal* signal){
regTcPtr.i = signal->theData[0];
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr.p->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
-
- signal->theData[0] = regFragptr.p->accFragptr[regTcPtr.p->localFragptr];
- EXECUTE_DIRECT(DBACC, GSN_READ_PSUEDO_REQ, signal, 2);
+ if(signal->theData[1] != AttributeHeader::RANGE_NO)
+ {
+ jam();
+ FragrecordPtr regFragptr;
+ regFragptr.i = regTcPtr.p->fragmentptr;
+ ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+
+ signal->theData[0] = regFragptr.p->accFragptr[regTcPtr.p->localFragptr];
+ EXECUTE_DIRECT(DBACC, GSN_READ_PSUEDO_REQ, signal, 2);
+ }
+ else
+ {
+ signal->theData[0] = regTcPtr.p->m_scan_curr_range_no;
+ }
}
/* ************>> */
@@ -2639,11 +2650,11 @@ void Dblqh::execTUPKEYCONF(Signal* signal)
jamEntry();
tcConnectptr.i = tcIndex;
ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
- if (tcConnectptr.p->seqNoReplica == 0) // Primary replica
- tcConnectptr.p->noFiredTriggers = tupKeyConf->noFiredTriggers;
switch (tcConnectptr.p->transactionState) {
case TcConnectionrec::WAIT_TUP:
jam();
+ if (tcConnectptr.p->seqNoReplica == 0) // Primary replica
+ tcConnectptr.p->noFiredTriggers = tupKeyConf->noFiredTriggers;
tupkeyConfLab(signal);
break;
case TcConnectionrec::COPY_TUPKEY:
@@ -3525,7 +3536,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
LQHKEY_error(signal, 6);
return;
}//if
- regTcPtr->localFragptr = (regTcPtr->hashValue >> fragptr.p->hashCheckBit) & 1;
+ regTcPtr->localFragptr = regTcPtr->hashValue & 1;
Uint8 TcopyType = fragptr.p->fragCopy;
tfragDistKey = fragptr.p->fragDistributionKey;
if (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION) {
@@ -6835,49 +6846,6 @@ Dblqh::scanMarkers(Signal* signal,
* ALL TUPLES IN THE FRAGMENT. TUP PERFORMS THE NECESSARY SEARCH CONDITIONS
* TO ENSURE THAT ONLY VALID TUPLES ARE RETURNED TO THE APPLICATION.
* ------------------------------------------------------------------------- */
-
-void Dblqh::execACC_SCAN_INFO(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- c_scanRecordPool.getPtr(scanptr);
- Uint32 length = signal->theData[3];
- ndbrequire(length <= 4);
- accScanInfoEnterLab(signal, &signal->theData[4], length);
-}//Dblqh::execACC_SCAN_INFO()
-
-
-void Dblqh::execACC_SCAN_INFO24(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- c_scanRecordPool.getPtr(scanptr);
- Uint32 length = signal->theData[3];
- ndbrequire(length <= 20);
- accScanInfoEnterLab(signal, &signal->theData[4], length);
-}//Dblqh::execACC_SCAN_INFO24()
-
-void Dblqh::accScanInfoEnterLab(Signal* signal,
- Uint32* dataPtr,
- Uint32 length)
-{
- ndbrequire(length != 0);
- if (scanptr.p->scanState == ScanRecord::WAIT_SCAN_KEYINFO) {
- jam();
- if (keyinfoLab(signal, dataPtr, length)) {
- jam();
- nextScanConfLoopLab(signal);
- }//if
- } else {
- ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_COPY_KEYINFO);
- jam();
- if (keyinfoLab(signal, dataPtr, length)) {
- jam();
- copySendTupkeyReqLab(signal);
- }//if
- }//if
-}//Dblqh::accScanInfoEnterLab()
-
/* *************** */
/* ACC_SCANCONF > */
/* *************** */
@@ -7007,6 +6975,7 @@ void Dblqh::execSTORED_PROCREF(Signal* signal)
switch (scanptr.p->scanState) {
case ScanRecord::WAIT_STORED_PROC_SCAN:
jam();
+ scanptr.p->scanCompletedStatus = ZTRUE;
scanptr.p->scanStoredProcId = signal->theData[2];
tcConnectptr.p->errorCode = errorCode;
closeScanLab(signal);
@@ -7212,10 +7181,7 @@ void Dblqh::continueScanReleaseAfterBlockedLab(Signal* signal)
scanptr.p->scanReleaseCounter -1,
false);
signal->theData[2] = NextScanReq::ZSCAN_COMMIT;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
}//Dblqh::continueScanReleaseAfterBlockedLab()
/* -------------------------------------------------------------------------
@@ -7243,7 +7209,6 @@ void Dblqh::closeScanRequestLab(Signal* signal)
jam();
tupScanCloseConfLab(signal);
break;
- case ScanRecord::WAIT_SCAN_KEYINFO:
case ScanRecord::WAIT_NEXT_SCAN:
jam();
/* -------------------------------------------------------------------
@@ -7307,6 +7272,7 @@ void Dblqh::closeScanRequestLab(Signal* signal)
* WE ARE STILL WAITING FOR THE ATTRIBUTE INFORMATION THAT
* OBVIOUSLY WILL NOT ARRIVE. WE CAN QUIT IMMEDIATELY HERE.
* --------------------------------------------------------------------- */
+ //XXX jonas this have to be wrong...
releaseOprec(signal);
if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
jam();
@@ -7528,6 +7494,7 @@ void Dblqh::execSCAN_FRAGREQ(Signal* signal)
const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
const Uint8 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
const Uint8 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
+ const Uint8 tupScan = ScanFragReq::getTupScanFlag(reqinfo);
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
if(tabptr.p->tableStatus != Tablerec::TABLE_DEFINED){
@@ -7672,18 +7639,13 @@ void Dblqh::continueAfterReceivingAllAiLab(Signal* signal)
req->fragmentNo = tcConnectptr.p->fragmentid;
req->requestInfo = 0;
AccScanReq::setLockMode(req->requestInfo, scanptr.p->scanLockMode);
- AccScanReq::setKeyinfoFlag(req->requestInfo, scanptr.p->scanKeyinfoFlag);
AccScanReq::setReadCommittedFlag(req->requestInfo, scanptr.p->readCommitted);
+ AccScanReq::setDescendingFlag(req->requestInfo, scanptr.p->descending);
req->transId1 = tcConnectptr.p->transid[0];
req->transId2 = tcConnectptr.p->transid[1];
req->savePointId = tcConnectptr.p->savePointId;
- // always use if-stmt to switch (instead of setting a "scan block ref")
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_ACC_SCANREQ, signal,
- AccScanReq::SignalLength, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_ACC_SCANREQ, signal,
- AccScanReq::SignalLength, JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal,
+ AccScanReq::SignalLength, JBB);
}//Dblqh::continueAfterReceivingAllAiLab()
void Dblqh::scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
@@ -7777,11 +7739,6 @@ void Dblqh::execSCAN_HBREP(Signal* signal)
}
}
-void Dblqh::sendScanFragRefLateLab(Signal* signal)
-{
-}//Dblqh::sendScanFragRefLateLab()
-
-
void Dblqh::accScanConfScanLab(Signal* signal)
{
AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
@@ -7800,17 +7757,15 @@ void Dblqh::accScanConfScanLab(Signal* signal)
return;
}//if
scanptr.p->scanAccPtr = accScanConf->accPtr;
- Uint32 boundAiLength = tcConnectptr.p->primKeyLen - 4;
if (scanptr.p->rangeScan) {
jam();
- TuxBoundInfo* const req = (TuxBoundInfo*)signal->getDataPtrSend();
+ TuxBoundInfo* req = (TuxBoundInfo*)signal->getDataPtrSend();
req->errorCode = RNIL;
req->tuxScanPtrI = scanptr.p->scanAccPtr;
- req->boundAiLength = boundAiLength;
- if(boundAiLength > 0)
- sendKeyinfoAcc(signal, TuxBoundInfo::SignalLength);
- EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO,
- signal, TuxBoundInfo::SignalLength + boundAiLength);
+ Uint32 len = req->boundAiLength = copy_bounds(req->data, tcConnectptr.p);
+ EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO, signal,
+ TuxBoundInfo::SignalLength + len);
+
jamEntry();
if (req->errorCode != 0) {
jam();
@@ -7822,35 +7777,176 @@ void Dblqh::accScanConfScanLab(Signal* signal)
tcConnectptr.p->errorCode = req->errorCode;
}
}
- scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
- signal->theData[0] = tcConnectptr.p->tupConnectrec;
- signal->theData[1] = tcConnectptr.p->tableref;
- signal->theData[2] = scanptr.p->scanSchemaVersion;
- signal->theData[3] = ZSTORED_PROC_SCAN;
-
- signal->theData[4] = scanptr.p->scanAiLength;
- sendSignal(tcConnectptr.p->tcTupBlockref,
- GSN_STORED_PROCREQ, signal, 5, JBB);
- signal->theData[0] = tcConnectptr.p->tupConnectrec;
- AttrbufPtr regAttrinbufptr;
- regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
- while (regAttrinbufptr.i != RNIL) {
- ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
+ scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
+ if(scanptr.p->scanStoredProcId == RNIL)
+ {
jam();
- Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
- ndbrequire(dataLen != 0);
- // first 3 words already set in STORED_PROCREQ
- MEMCOPY_NO_WORDS(&signal->theData[3],
- &regAttrinbufptr.p->attrbuf[0],
- dataLen);
+ signal->theData[0] = tcConnectptr.p->tupConnectrec;
+ signal->theData[1] = tcConnectptr.p->tableref;
+ signal->theData[2] = scanptr.p->scanSchemaVersion;
+ signal->theData[3] = ZSTORED_PROC_SCAN;
+
+ signal->theData[4] = scanptr.p->scanAiLength;
sendSignal(tcConnectptr.p->tcTupBlockref,
- GSN_ATTRINFO, signal, dataLen + 3, JBB);
- regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
- }//while
- releaseOprec(signal);
+ GSN_STORED_PROCREQ, signal, 5, JBB);
+
+ signal->theData[0] = tcConnectptr.p->tupConnectrec;
+ AttrbufPtr regAttrinbufptr;
+ Uint32 firstAttr = regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
+ while (regAttrinbufptr.i != RNIL) {
+ ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
+ jam();
+ Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
+ ndbrequire(dataLen != 0);
+ // first 3 words already set in STORED_PROCREQ
+ MEMCOPY_NO_WORDS(&signal->theData[3],
+ &regAttrinbufptr.p->attrbuf[0],
+ dataLen);
+ sendSignal(tcConnectptr.p->tcTupBlockref,
+ GSN_ATTRINFO, signal, dataLen + 3, JBB);
+ regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
+ c_no_attrinbuf_recs++;
+ }//while
+
+ /**
+ * Release attr info
+ */
+ if(firstAttr != RNIL)
+ {
+ regAttrinbufptr.p->attrbuf[ZINBUF_NEXT] = cfirstfreeAttrinbuf;
+ cfirstfreeAttrinbuf = firstAttr;
+ tcConnectptr.p->firstAttrinbuf = tcConnectptr.p->lastAttrinbuf = RNIL;
+ }
+ }
+ else
+ {
+ jam();
+ storedProcConfScanLab(signal);
+ }
}//Dblqh::accScanConfScanLab()
+#define print_buf(s,idx,len) {\
+ printf(s); Uint32 t2=len; DatabufPtr t3; t3.i = idx; \
+ while(t3.i != RNIL && t2-- > 0){\
+ ptrCheckGuard(t3, cdatabufFileSize, databuf);\
+ printf("%d ", t3.i); t3.i= t3.p->nextDatabuf;\
+ } printf("\n"); }
+
+Uint32
+Dblqh::copy_bounds(Uint32 * dst, TcConnectionrec* tcPtrP)
+{
+ /**
+ * copy_bounds handles multiple bounds by
+ * in the 16 upper bits of the first words (used to specify bound type)
+ * setting the length of this specific bound
+ *
+ */
+
+ DatabufPtr regDatabufptr;
+ Uint32 left = 4 - tcPtrP->m_offset_current_keybuf; // left in buf
+ Uint32 totalLen = tcPtrP->primKeyLen - 4;
+ regDatabufptr.i = tcPtrP->firstTupkeybuf;
+
+ ndbassert(tcPtrP->primKeyLen >= 4);
+ ndbassert(tcPtrP->m_offset_current_keybuf < 4);
+ ndbassert(!(totalLen == 0 && regDatabufptr.i != RNIL));
+ ndbassert(!(totalLen != 0 && regDatabufptr.i == RNIL));
+
+ if(totalLen)
+ {
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ Uint32 sig0 = regDatabufptr.p->data[0];
+ Uint32 sig1 = regDatabufptr.p->data[1];
+ Uint32 sig2 = regDatabufptr.p->data[2];
+ Uint32 sig3 = regDatabufptr.p->data[3];
+
+ switch(left){
+ case 4:
+ * dst++ = sig0;
+ case 3:
+ * dst++ = sig1;
+ case 2:
+ * dst++ = sig2;
+ case 1:
+ * dst++ = sig3;
+ }
+
+ Uint32 first = (* (dst - left)); // First word in range
+
+ // Length of this range
+ Uint8 offset;
+ const Uint32 len = (first >> 16) ? (first >> 16) : totalLen;
+ tcPtrP->m_scan_curr_range_no = (first & 0xFFF0) >> 4;
+ (* (dst - left)) = (first & 0xF); // Remove length & range no
+
+ if(len < left)
+ {
+ offset = len;
+ }
+ else
+ {
+ Databuf * lastP;
+ left = (len - left);
+ regDatabufptr.i = regDatabufptr.p->nextDatabuf;
+
+ while(left >= 4)
+ {
+ left -= 4;
+ lastP = regDatabufptr.p;
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ sig0 = regDatabufptr.p->data[0];
+ sig1 = regDatabufptr.p->data[1];
+ sig2 = regDatabufptr.p->data[2];
+ sig3 = regDatabufptr.p->data[3];
+ regDatabufptr.i = regDatabufptr.p->nextDatabuf;
+
+ * dst++ = sig0;
+ * dst++ = sig1;
+ * dst++ = sig2;
+ * dst++ = sig3;
+ }
+
+ if(left > 0)
+ {
+ lastP = regDatabufptr.p;
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ sig0 = regDatabufptr.p->data[0];
+ sig1 = regDatabufptr.p->data[1];
+ sig2 = regDatabufptr.p->data[2];
+ sig3 = regDatabufptr.p->data[3];
+ * dst++ = sig0;
+ * dst++ = sig1;
+ * dst++ = sig2;
+ * dst++ = sig3;
+ }
+ else
+ {
+ lastP = regDatabufptr.p;
+ }
+ offset = left & 3;
+ lastP->nextDatabuf = cfirstfreeDatabuf;
+ cfirstfreeDatabuf = tcPtrP->firstTupkeybuf;
+ ndbassert(cfirstfreeDatabuf != RNIL);
+ }
+
+ if(len == totalLen && regDatabufptr.i != RNIL)
+ {
+ regDatabufptr.p->nextDatabuf = cfirstfreeDatabuf;
+ cfirstfreeDatabuf = regDatabufptr.i;
+ tcPtrP->lastTupkeybuf = regDatabufptr.i = RNIL;
+ ndbassert(cfirstfreeDatabuf != RNIL);
+ }
+
+ tcPtrP->m_offset_current_keybuf = offset;
+ tcPtrP->firstTupkeybuf = regDatabufptr.i;
+ tcPtrP->primKeyLen = 4 + totalLen - len;
+
+ return len;
+ }
+ return totalLen;
+}
+
/* -------------------------------------------------------------------------
* ENTER STORED_PROCCONF WITH
* TC_CONNECTPTR,
@@ -7901,14 +7997,10 @@ void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal)
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
- init_acc_ptr_list(scanptr.p);
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = RNIL;
signal->theData[2] = NextScanReq::ZSCAN_NEXT;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
return;
}//Dblqh::continueFirstScanAfterBlockedLab()
@@ -7978,10 +8070,8 @@ void Dblqh::continueAfterCheckLcpStopBlocked(Signal* signal)
c_scanRecordPool.getPtr(scanptr);
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
- if (! scanptr.p->rangeScan)
- EXECUTE_DIRECT(DBACC, GSN_ACC_CHECK_SCAN, signal, 2);
- else
- EXECUTE_DIRECT(DBTUX, GSN_ACC_CHECK_SCAN, signal, 2);
+ EXECUTE_DIRECT(refToBlock(scanptr.p->scanBlockref), GSN_ACC_CHECK_SCAN,
+ signal, 2);
}//Dblqh::continueAfterCheckLcpStopBlocked()
/* -------------------------------------------------------------------------
@@ -8029,7 +8119,10 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
if (scanptr.p->m_curr_batch_size_rows > 0) {
jam();
- scanptr.p->scanCompletedStatus = ZTRUE;
+
+ if((tcConnectptr.p->primKeyLen - 4) == 0)
+ scanptr.p->scanCompletedStatus = ZTRUE;
+
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
sendScanFragConf(signal, ZFALSE);
return;
@@ -8068,12 +8161,8 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref,
- GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref,
- GSN_ACC_CHECK_SCAN, signal, 2, JBB);
+ sendSignal(scanptr.p->scanBlockref,
+ GSN_ACC_CHECK_SCAN, signal, 2, JBB);
return;
}//if
jam();
@@ -8084,22 +8173,6 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
scanptr.p->scanLocalref[0] = nextScanConf->localKey[0];
scanptr.p->scanLocalref[1] = nextScanConf->localKey[1];
scanptr.p->scanLocalFragid = nextScanConf->fragId;
- if (scanptr.p->scanKeyinfoFlag) {
- jam();
- tcConnectptr.p->primKeyLen = nextScanConf->keyLength;
- seizeTupkeybuf(signal);
- databufptr.p->data[0] = nextScanConf->key[0];
- databufptr.p->data[1] = nextScanConf->key[1];
- databufptr.p->data[2] = nextScanConf->key[2];
- databufptr.p->data[3] = nextScanConf->key[3];
- if (nextScanConf->keyLength > 4) {
- jam();
- tcConnectptr.p->save1 = 4;
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_KEYINFO;
- return;
- }//if
- }//if
- jam();
nextScanConfLoopLab(signal);
}//Dblqh::nextScanConfScanLab()
@@ -8111,7 +8184,6 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
if (scanptr.p->scanCompletedStatus == ZTRUE) {
jam();
releaseActiveFrag(signal);
- releaseOprec(signal);
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
jam();
@@ -8133,13 +8205,7 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
if (! scanptr.p->rangeScan) {
tableRef = tcConnectptr.p->tableref;
- if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[1];
- }//if
+ tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
} else {
jam();
// for ordered index use primary table
@@ -8147,13 +8213,7 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
tFragPtr.i = fragptr.p->tableFragptr;
ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
tableRef = tFragPtr.p->tabRef;
- if (tFragPtr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = tFragPtr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = tFragPtr.p->tupFragptr[1];
- }//if
+ tupFragPtr = tFragPtr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
}
{
jam();
@@ -8188,33 +8248,46 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
* -------------------------------------------------------------------------
* PRECONDITION: SCAN_STATE = WAIT_SCAN_KEYINFO
* ------------------------------------------------------------------------- */
-bool Dblqh::keyinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
+void
+Dblqh::keyinfoLab(const Uint32 * src, const Uint32 * end)
{
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- Uint32 index = 0;
do {
jam();
- seizeTupkeybuf(signal);
- databufptr.p->data[0] = dataPtr[index];
- databufptr.p->data[1] = dataPtr[index + 1];
- databufptr.p->data[2] = dataPtr[index + 2];
- databufptr.p->data[3] = dataPtr[index + 3];
- index += 4;
- tcConnectptr.p->save1 = tcConnectptr.p->save1 + 4;
- if (tcConnectptr.p->save1 >= tcConnectptr.p->primKeyLen) {
- jam();
- return true;
- }//if
- if (index >= length) {
- jam();
- return false;
- }//if
- } while (index < 20);
- ndbrequire(false);
- return false;
+ seizeTupkeybuf(0);
+ databufptr.p->data[0] = * src ++;
+ databufptr.p->data[1] = * src ++;
+ databufptr.p->data[2] = * src ++;
+ databufptr.p->data[3] = * src ++;
+ } while (src < end);
}//Dblqh::keyinfoLab()
+Uint32
+Dblqh::readPrimaryKeys(ScanRecord *scanP, TcConnectionrec *tcConP, Uint32 *dst)
+{
+ Uint32 tableId = tcConP->tableref;
+ Uint32 fragId = scanP->scanLocalFragid;
+ Uint32 fragPageId = scanP->scanLocalref[0];
+ Uint32 pageIndex = scanP->scanLocalref[1];
+
+ if(scanP->rangeScan)
+ {
+ jam();
+ // for ordered index use primary table
+ FragrecordPtr tFragPtr;
+ tFragPtr.i = fragptr.p->tableFragptr;
+ ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+ tableId = tFragPtr.p->tabRef;
+ }
+
+ int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, dst, false);
+ if(0)
+ ndbout_c("readPrimaryKeys(table: %d fragment: %d [ %d %d ] -> %d",
+ tableId, fragId, fragPageId, pageIndex, ret);
+ ndbassert(ret > 0);
+
+ return ret;
+}
+
/* -------------------------------------------------------------------------
* ENTER TUPKEYCONF
* -------------------------------------------------------------------------
@@ -8234,7 +8307,6 @@ void Dblqh::scanTupkeyConfLab(Signal* signal)
/* ---------------------------------------------------------------------
* STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
* --------------------------------------------------------------------- */
- releaseOprec(signal);
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
jam();
@@ -8248,10 +8320,8 @@ void Dblqh::scanTupkeyConfLab(Signal* signal)
}//if
if (scanptr.p->scanKeyinfoFlag) {
jam();
- sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
- releaseOprec(signal);
-
- tdata4 += tcConnectptr.p->primKeyLen;// Inform API about keyinfo len aswell
+ // Inform API about keyinfo len aswell
+ tdata4 += sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
}//if
ndbrequire(scanptr.p->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
scanptr.p->m_curr_batch_size_bytes+= tdata4;
@@ -8335,10 +8405,7 @@ void Dblqh::continueScanAfterBlockedLab(Signal* signal)
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = accOpPtr;
signal->theData[2] = scanptr.p->scanFlag;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3,JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3,JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
}//Dblqh::continueScanAfterBlockedLab()
/* -------------------------------------------------------------------------
@@ -8353,7 +8420,6 @@ void Dblqh::scanTupkeyRefLab(Signal* signal)
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
scanptr.i = tcConnectptr.p->tcScanRec;
releaseActiveFrag(signal);
- releaseOprec(signal);
c_scanRecordPool.getPtr(scanptr);
if (scanptr.p->scanCompletedStatus == ZTRUE) {
/* ---------------------------------------------------------------------
@@ -8461,10 +8527,7 @@ void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = RNIL;
signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
}//Dblqh::continueCloseScanAfterBlockedLab()
/* -------------------------------------------------------------------------
@@ -8475,8 +8538,18 @@ void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
void Dblqh::accScanCloseConfLab(Signal* signal)
{
tcConnectptr.i = scanptr.p->scanTcrec;
- scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
+
+ if((tcConnectptr.p->primKeyLen - 4) > 0 &&
+ scanptr.p->scanCompletedStatus != ZTRUE)
+ {
+ jam();
+ releaseActiveFrag(signal);
+ continueAfterReceivingAllAiLab(signal);
+ return;
+ }
+
+ scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
signal->theData[0] = tcConnectptr.p->tupConnectrec;
signal->theData[1] = tcConnectptr.p->tableref;
signal->theData[2] = scanptr.p->scanSchemaVersion;
@@ -8538,7 +8611,9 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
const Uint32 scanLockHold = ScanFragReq::getHoldLockFlag(reqinfo);
const Uint32 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
const Uint32 readCommitted = ScanFragReq::getReadCommittedFlag(reqinfo);
- const Uint32 idx = ScanFragReq::getRangeScanFlag(reqinfo);
+ const Uint32 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
+ const Uint32 descending = ScanFragReq::getDescendingFlag(reqinfo);
+ const Uint32 tupScan = ScanFragReq::getTupScanFlag(reqinfo);
const Uint32 attrLen = ScanFragReq::getAttrLen(reqinfo);
const Uint32 scanPrio = ScanFragReq::getScanPrio(reqinfo);
@@ -8556,10 +8631,19 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
scanptr.p->m_max_batch_size_rows = max_rows;
scanptr.p->m_max_batch_size_bytes = max_bytes;
+ if (! rangeScan && ! tupScan)
+ scanptr.p->scanBlockref = tcConnectptr.p->tcAccBlockref;
+ else if (! tupScan)
+ scanptr.p->scanBlockref = tcConnectptr.p->tcTuxBlockref;
+ else
+ scanptr.p->scanBlockref = tcConnectptr.p->tcTupBlockref;
+
scanptr.p->scanErrorCounter = 0;
scanptr.p->scanLockMode = scanLockMode;
scanptr.p->readCommitted = readCommitted;
- scanptr.p->rangeScan = idx;
+ scanptr.p->rangeScan = rangeScan;
+ scanptr.p->descending = descending;
+ scanptr.p->tupScan = tupScan;
scanptr.p->scanState = ScanRecord::SCAN_FREE;
scanptr.p->scanFlag = ZFALSE;
scanptr.p->scanLocalref[0] = 0;
@@ -8569,6 +8653,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
scanptr.p->scanNumber = ~0;
scanptr.p->scanApiOpPtr = scanFragReq->clientOpPtr;
scanptr.p->m_last_row = 0;
+ scanptr.p->scanStoredProcId = RNIL;
if (max_rows == 0 || (max_bytes > 0 && max_rows > max_bytes)){
jam();
@@ -8590,8 +8675,8 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
* !idx uses 1 - (MAX_PARALLEL_SCANS_PER_FRAG - 1) = 1-11
* idx uses from MAX_PARALLEL_SCANS_PER_FRAG - MAX = 12-42)
*/
- Uint32 start = (idx ? MAX_PARALLEL_SCANS_PER_FRAG : 1 );
- Uint32 stop = (idx ? MAX_PARALLEL_INDEX_SCANS_PER_FRAG : MAX_PARALLEL_SCANS_PER_FRAG - 1);
+ Uint32 start = (rangeScan || tupScan ? MAX_PARALLEL_SCANS_PER_FRAG : 1 );
+ Uint32 stop = (rangeScan || tupScan ? MAX_PARALLEL_INDEX_SCANS_PER_FRAG : MAX_PARALLEL_SCANS_PER_FRAG - 1);
stop += start;
Uint32 free = tFragPtr.p->m_scanNumberMask.find(start);
@@ -8627,7 +8712,8 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
#ifdef TRACE_SCAN_TAKEOVER
ndbout_c("adding (%d %d) table: %d fragId: %d frag.i: %d tableFragptr: %d",
scanptr.p->scanNumber, scanptr.p->fragPtrI,
- tabptr.i, scanFragReq->fragmentNo, fragptr.i, fragptr.p->tableFragptr);
+ tabptr.i, scanFragReq->fragmentNoKeyLen & 0xFFFF,
+ fragptr.i, fragptr.p->tableFragptr);
#endif
c_scanTakeOverHash.add(scanptr);
}
@@ -8663,6 +8749,8 @@ void Dblqh::initScanTc(Signal* signal,
tcConnectptr.p->operation = ZREAD;
tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
tcConnectptr.p->commitAckMarker = RNIL;
+ tcConnectptr.p->m_offset_current_keybuf = 0;
+ tcConnectptr.p->m_scan_curr_range_no = 0;
tabptr.p->usageCount++;
}//Dblqh::initScanTc()
@@ -8777,23 +8865,17 @@ void Dblqh::releaseScanrec(Signal* signal)
* ------- SEND KEYINFO20 TO API -------
*
* ------------------------------------------------------------------------ */
-void Dblqh::sendKeyinfo20(Signal* signal,
- ScanRecord * scanP,
- TcConnectionrec * tcConP)
+Uint32 Dblqh::sendKeyinfo20(Signal* signal,
+ ScanRecord * scanP,
+ TcConnectionrec * tcConP)
{
ndbrequire(scanP->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0];
- DatabufPtr TdataBuf;
- TdataBuf.i = tcConP->firstTupkeybuf;
- Uint32 keyLen = tcConP->primKeyLen;
- const Uint32 dataBufSz = cdatabufFileSize;
-
/**
* Note that this code requires signal->theData to be big enough for
* a entire key
*/
- ndbrequire(keyLen * 4 <= sizeof(signal->theData));
const BlockReference ref = scanP->scanApiBlockref;
const Uint32 scanOp = scanP->m_curr_batch_size_rows;
const Uint32 nodeId = refToNode(ref);
@@ -8806,24 +8888,12 @@ void Dblqh::sendKeyinfo20(Signal* signal,
Uint32 * dst = keyInfo->keyData;
dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength;
- /**
- * Copy keydata from data buffer into signal
- *
- */
- for(Uint32 i = 0; i < keyLen; i += 4){
- ptrCheckGuard(TdataBuf, dataBufSz, databuf);
- * dst++ = TdataBuf.p->data[0];
- * dst++ = TdataBuf.p->data[1];
- * dst++ = TdataBuf.p->data[2];
- * dst++ = TdataBuf.p->data[3];
- TdataBuf.i = TdataBuf.p->nextDatabuf;
- }
-
+ Uint32 keyLen = readPrimaryKeys(scanP, tcConP, dst);
+ Uint32 fragId = tcConP->fragmentid;
keyInfo->clientOpPtr = scanP->scanApiOpPtr;
keyInfo->keyLen = keyLen;
- keyInfo->scanInfo_Node = KeyInfo20::setScanInfo(scanOp,
- scanP->scanNumber)+
- (getOwnNodeId() << 20);
+ keyInfo->scanInfo_Node =
+ KeyInfo20::setScanInfo(scanOp, scanP->scanNumber) + (fragId << 20);
keyInfo->transId1 = tcConP->transid[0];
keyInfo->transId2 = tcConP->transid[1];
@@ -8846,7 +8916,7 @@ void Dblqh::sendKeyinfo20(Signal* signal,
MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
sendSignal(ref, GSN_KEYINFO20, signal,
KeyInfo20::HeaderLength+keyLen, JBB);
- return;
+ return keyLen;
}
LinearSectionPtr ptr[3];
@@ -8854,13 +8924,13 @@ void Dblqh::sendKeyinfo20(Signal* signal,
ptr[0].sz = keyLen;
sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength,
JBB, ptr, 1);
- return;
+ return keyLen;
}
EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal,
KeyInfo20::HeaderLength + keyLen);
jamEntry();
- return;
+ return keyLen;
}
/**
@@ -8886,7 +8956,7 @@ void Dblqh::sendKeyinfo20(Signal* signal,
keyInfo->keyData[keyLen] = ref;
sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
KeyInfo20::HeaderLength+keyLen+1, JBB);
- return;
+ return keyLen;
}
keyInfo->keyData[0] = ref;
@@ -8895,7 +8965,7 @@ void Dblqh::sendKeyinfo20(Signal* signal,
ptr[0].sz = keyLen;
sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
KeyInfo20::HeaderLength+1, JBB, ptr, 1);
- return;
+ return keyLen;
}
/* ------------------------------------------------------------------------
@@ -8944,44 +9014,17 @@ void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
/* FRAGMENT TO A NEW REPLICA OF THE FRAGMENT. IT DOES ALSO SHUT DOWN ALL */
/* CONNECTIONS TO THE FAILED NODE. */
/*---------------------------------------------------------------------------*/
-void Dblqh::calculateHash(Signal* signal)
-{
- DatabufPtr locDatabufptr;
- UintR Ti;
- UintR Tdata0;
- UintR Tdata1;
- UintR Tdata2;
- UintR Tdata3;
- UintR* Tdata32;
- Uint64 Tdata[512];
-
- Tdata32 = (UintR*)&Tdata[0];
-
- Tdata0 = tcConnectptr.p->tupkeyData[0];
- Tdata1 = tcConnectptr.p->tupkeyData[1];
- Tdata2 = tcConnectptr.p->tupkeyData[2];
- Tdata3 = tcConnectptr.p->tupkeyData[3];
- Tdata32[0] = Tdata0;
- Tdata32[1] = Tdata1;
- Tdata32[2] = Tdata2;
- Tdata32[3] = Tdata3;
- locDatabufptr.i = tcConnectptr.p->firstTupkeybuf;
- Ti = 4;
- while (locDatabufptr.i != RNIL) {
- ptrCheckGuard(locDatabufptr, cdatabufFileSize, databuf);
- Tdata0 = locDatabufptr.p->data[0];
- Tdata1 = locDatabufptr.p->data[1];
- Tdata2 = locDatabufptr.p->data[2];
- Tdata3 = locDatabufptr.p->data[3];
- Tdata32[Ti ] = Tdata0;
- Tdata32[Ti + 1] = Tdata1;
- Tdata32[Ti + 2] = Tdata2;
- Tdata32[Ti + 3] = Tdata3;
- locDatabufptr.i = locDatabufptr.p->nextDatabuf;
- Ti += 4;
- }//while
- tcConnectptr.p->hashValue =
- md5_hash((Uint64*)&Tdata32[0], (UintR)tcConnectptr.p->primKeyLen);
+Uint32
+Dblqh::calculateHash(Uint32 tableId, const Uint32* src)
+{
+ jam();
+ Uint64 Tmp[(MAX_KEY_SIZE_IN_WORDS*MAX_XFRM_MULTIPLY) >> 1];
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
+ Uint32 keyLen = xfrm_key(tableId, src, (Uint32*)Tmp, sizeof(Tmp) >> 2,
+ keyPartLen);
+ ndbrequire(keyLen);
+
+ return md5_hash(Tmp, keyLen);
}//Dblqh::calculateHash()
/* *************************************** */
@@ -9033,6 +9076,7 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
/* ------------------------------------------------------------------------- */
scanptr.p->m_max_batch_size_rows = 0;
scanptr.p->rangeScan = 0;
+ scanptr.p->tupScan = 0;
seizeTcrec();
/**
@@ -9051,6 +9095,7 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
scanptr.p->scanKeyinfoFlag = 0; // Don't put into hash
scanptr.p->fragPtrI = fragptr.i;
fragptr.p->m_scanNumberMask.clear(NR_ScanNo);
+ scanptr.p->scanBlockref = DBACC_REF;
initScanTc(signal,
0,
@@ -9071,7 +9116,6 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
req->fragmentNo = fragId;
req->requestInfo = 0;
AccScanReq::setLockMode(req->requestInfo, 0);
- AccScanReq::setKeyinfoFlag(req->requestInfo, 1);
AccScanReq::setReadCommittedFlag(req->requestInfo, 0);
req->transId1 = tcConnectptr.p->transid[0];
req->transId2 = tcConnectptr.p->transid[1];
@@ -9224,12 +9268,6 @@ void Dblqh::nextScanConfCopyLab(Signal* signal)
set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
initCopyTc(signal);
- if (tcConnectptr.p->primKeyLen > 4) {
- jam();
- tcConnectptr.p->save1 = 4;
- scanptr.p->scanState = ScanRecord::WAIT_COPY_KEYINFO;
- return;
- }//if
copySendTupkeyReqLab(signal);
return;
}//Dblqh::nextScanConfCopyLab()
@@ -9245,13 +9283,7 @@ void Dblqh::copySendTupkeyReqLab(Signal* signal)
scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
fragptr.i = tcConnectptr.p->fragmentptr;
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[1];
- }//if
+ tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
{
TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
@@ -9326,9 +9358,10 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
UintR readLength = tupKeyConf->readLength;
-
+ Uint32 tableId = tcConnectptr.p->tableref;
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
+ ScanRecord* scanP = scanptr.p;
releaseActiveFrag(signal);
if (tcConnectptr.p->errorCode != 0) {
jam();
@@ -9343,9 +9376,30 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
closeCopyLab(signal);
return;
}//if
+ TcConnectionrec * tcConP = tcConnectptr.p;
tcConnectptr.p->totSendlenAi = readLength;
tcConnectptr.p->connectState = TcConnectionrec::COPY_CONNECTED;
- calculateHash(signal);
+
+ // Read primary keys (used to get here via scan keyinfo)
+ Uint32* tmp = signal->getDataPtrSend()+24;
+ Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
+
+ // Calculate hash (no need to linearies key)
+ if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
+ {
+ tcConnectptr.p->hashValue = calculateHash(tableId, tmp);
+ }
+ else
+ {
+ tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len);
+ }
+
+ // Move into databuffer to make packLqhkeyreqLab happy
+ memcpy(tcConP->tupkeyData, tmp, 4*4);
+ if(len > 4)
+ keyinfoLab(tmp+4, tmp + len);
+ LqhKeyReq::setKeyLen(tcConP->reqinfo, len);
+
/*---------------------------------------------------------------------------*/
// To avoid using up to many operation records in ACC we will increase the
// constant to ensure that we never send more than 40 records at a time.
@@ -9356,7 +9410,7 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
// records to ensure that node recovery does not fail because of simultaneous
// scanning.
/*---------------------------------------------------------------------------*/
- UintR TnoOfWords = readLength + tcConnectptr.p->primKeyLen;
+ UintR TnoOfWords = readLength + len;
TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
@@ -9678,7 +9732,6 @@ void Dblqh::closeCopyRequestLab(Signal* signal)
scanptr.p->scanErrorCounter++;
switch (scanptr.p->scanState) {
case ScanRecord::WAIT_TUPKEY_COPY:
- case ScanRecord::WAIT_COPY_KEYINFO:
case ScanRecord::WAIT_NEXT_SCAN_COPY:
jam();
/*---------------------------------------------------------------------------*/
@@ -9909,11 +9962,6 @@ void Dblqh::execCOPY_STATEREQ(Signal* signal)
void Dblqh::initCopyTc(Signal* signal)
{
const NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
- tcConnectptr.p->primKeyLen = nextScanConf->keyLength;
- tcConnectptr.p->tupkeyData[0] = nextScanConf->key[0];
- tcConnectptr.p->tupkeyData[1] = nextScanConf->key[1];
- tcConnectptr.p->tupkeyData[2] = nextScanConf->key[2];
- tcConnectptr.p->tupkeyData[3] = nextScanConf->key[3];
scanptr.p->scanLocalref[0] = nextScanConf->localKey[0];
scanptr.p->scanLocalref[1] = nextScanConf->localKey[1];
scanptr.p->scanLocalFragid = nextScanConf->fragId;
@@ -9922,7 +9970,6 @@ void Dblqh::initCopyTc(Signal* signal)
tcConnectptr.p->opExec = 0; /* NOT INTERPRETED MODE */
tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
Uint32 reqinfo = 0;
- LqhKeyReq::setKeyLen(reqinfo, nextScanConf->keyLength);
LqhKeyReq::setLockType(reqinfo, ZINSERT);
LqhKeyReq::setDirtyFlag(reqinfo, 1);
LqhKeyReq::setSimpleFlag(reqinfo, 1);
@@ -12462,6 +12509,22 @@ void Dblqh::lastWriteInFileLab(Signal* signal)
void Dblqh::writePageZeroLab(Signal* signal)
{
+ if (false && logPartPtr.p->logPartState == LogPartRecord::FILE_CHANGE_PROBLEM)
+ {
+ if (logPartPtr.p->firstLogQueue == RNIL)
+ {
+ jam();
+ logPartPtr.p->logPartState = LogPartRecord::IDLE;
+ ndbout_c("resetting logPartState to IDLE");
+ }
+ else
+ {
+ jam();
+ logPartPtr.p->logPartState = LogPartRecord::ACTIVE;
+ ndbout_c("resetting logPartState to ACTIVE");
+ }
+ }
+
logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
/*---------------------------------------------------------------------------*/
/* IT COULD HAVE ARRIVED PAGE WRITES TO THE CURRENT FILE WHILE WE WERE */
@@ -13425,7 +13488,6 @@ void Dblqh::execSR_FRAGIDCONF(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
fragptr.p->accFragptr[0] = srFragidConf->fragPtr[0];
fragptr.p->accFragptr[1] = srFragidConf->fragPtr[1];
- fragptr.p->hashCheckBit = srFragidConf->hashCheckBit;
Uint32 noLocFrag = srFragidConf->noLocFrag;
ndbrequire(noLocFrag == 2);
Uint32 fragid[2];
@@ -15528,6 +15590,7 @@ void Dblqh::warningHandlerLab(Signal* signal)
void Dblqh::systemErrorLab(Signal* signal)
{
+ systemError(signal);
progError(0, 0);
/*************************************************************************>*/
/* WE WANT TO INVOKE AN IMMEDIATE ERROR HERE SO WE GET THAT BY */
@@ -18402,8 +18465,65 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
return;
}
+ Uint32 arg= dumpState->args[0];
+ if(arg == 2304 || arg == 2305)
+ {
+ jam();
+ Uint32 i;
+ GcpRecordPtr gcp; gcp.i = RNIL;
+ for(i = 0; i<4; i++)
+ {
+ logPartPtr.i = i;
+ ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
+ ndbout_c("LP %d state: %d WW_Gci: %d gcprec: %d flq: %d currfile: %d tailFileNo: %d logTailMbyte: %d",
+ i,
+ logPartPtr.p->logPartState,
+ logPartPtr.p->waitWriteGciLog,
+ logPartPtr.p->gcprec,
+ logPartPtr.p->firstLogQueue,
+ logPartPtr.p->currentLogfile,
+ logPartPtr.p->logTailFileNo,
+ logPartPtr.p->logTailMbyte);
+
+ if(gcp.i == RNIL && logPartPtr.p->gcprec != RNIL)
+ gcp.i = logPartPtr.p->gcprec;
+ LogFileRecordPtr logFilePtr;
+ Uint32 first= logFilePtr.i= logPartPtr.p->firstLogfile;
+ do
+ {
+ ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
+ ndbout_c(" file %d(%d) FileChangeState: %d logFileStatus: %d currentMbyte: %d currentFilepage",
+ logFilePtr.p->fileNo,
+ logFilePtr.i,
+ logFilePtr.p->fileChangeState,
+ logFilePtr.p->logFileStatus,
+ logFilePtr.p->currentMbyte,
+ logFilePtr.p->currentFilepage);
+ logFilePtr.i = logFilePtr.p->nextLogFile;
+ } while(logFilePtr.i != first);
+ }
+
+ if(gcp.i != RNIL)
+ {
+ ptrCheckGuard(gcp, cgcprecFileSize, gcpRecord);
+ for(i = 0; i<4; i++)
+ {
+ ndbout_c(" GCP %d file: %d state: %d sync: %d page: %d word: %d",
+ i, gcp.p->gcpFilePtr[i], gcp.p->gcpLogPartState[i],
+ gcp.p->gcpSyncReady[i],
+ gcp.p->gcpPageNo[i],
+ gcp.p->gcpWordNo[i]);
+ }
+ }
+ if(arg== 2305)
+ {
+ progError(__LINE__, ERR_SYSTEM_ERROR,
+ "Shutting down node due to failed handling of GCP_SAVEREQ");
+
+ }
+ }
}//Dblqh::execDUMP_STATE_ORD()
void Dblqh::execSET_VAR_REQ(Signal* signal)
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index 61afef30b43..bf9f421a0e3 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -561,7 +561,7 @@ public:
Uint32 expectedTransIdAI;
AttributeBuffer transIdAI; // For accumulating TransId_AI
- TcIndxReq tcIndxReq;
+ TcKeyReq tcIndxReq;
UintR connectionIndex;
UintR indexReadTcConnect; //
@@ -871,11 +871,11 @@ public:
UintR hashValue; /* THE HASH VALUE USED TO LOCATE FRAGMENT */
Uint8 distributionKeyIndicator;
- Uint8 distributionGroupIndicator;
- Uint8 distributionGroupType;
+ Uint8 m_special_hash; // collation or distribution key
+ Uint8 unused2;
Uint8 lenAiInTckeyreq; /* LENGTH OF ATTRIBUTE INFORMATION IN TCKEYREQ */
- Uint8 distributionKey;
+ Uint8 fragmentDistributionKey; /* DIH generation no */
/**
* EXECUTION MODE OF OPERATION
@@ -899,16 +899,16 @@ public:
// Second 16 byte cache line in second 64 byte cache
// line. Diverse use.
//---------------------------------------------------
- UintR distributionGroup;
+ UintR distributionKey;
UintR nextCacheRec;
- UintR distributionKeySize;
+ UintR unused3;
Uint32 scanInfo;
//---------------------------------------------------
// Third 16 byte cache line in second 64
// byte cache line. Diverse use.
//---------------------------------------------------
- Uint32 scanNode;
+ Uint32 unused4;
Uint32 scanTakeOverInd;
UintR firstKeybuf; /* POINTER THE LINKED LIST OF KEY BUFFERS */
UintR lastKeybuf; /* VARIABLE POINTING TO THE LAST KEY BUFFER */
@@ -946,6 +946,7 @@ public:
typedef Ptr<HostRecord> HostRecordPtr;
/* *********** TABLE RECORD ********************************************* */
+
/********************************************************/
/* THIS RECORD CONTAINS THE CURRENT SCHEMA VERSION OF */
/* ALL TABLES IN THE SYSTEM. */
@@ -956,14 +957,18 @@ public:
Uint8 dropping;
Uint8 tableType;
Uint8 storedTable;
+
+ Uint8 noOfKeyAttr;
+ Uint8 hasCharAttr;
+ Uint8 noOfDistrKeys;
bool checkTable(Uint32 schemaVersion) const {
return enabled && !dropping &&
(table_version_major(schemaVersion) == table_version_major(currentSchemaVersion));
}
-
+
Uint32 getErrorCode(Uint32 schemaVersion) const;
-
+
struct DropTable {
Uint32 senderRef;
Uint32 senderData;
@@ -1142,7 +1147,7 @@ public:
Uint32 nextScan;
// Length of expected attribute information
- Uint32 scanAiLength;
+ union { Uint32 scanAiLength; Uint32 m_booked_fragments_count; };
Uint32 scanKeyLen;
@@ -1411,6 +1416,10 @@ private:
void gcpTcfinished(Signal* signal);
void handleGcp(Signal* signal);
void hash(Signal* signal);
+ bool handle_special_hash(Uint32 dstHash[4],
+ Uint32* src, Uint32 srcLen,
+ Uint32 tabPtrI, bool distr);
+
void initApiConnect(Signal* signal);
void initApiConnectRec(Signal* signal,
ApiConnectRecord * const regApiPtr,
@@ -1663,7 +1672,7 @@ private:
c_scan_count = c_range_scan_count = 0;
}
Uint32 report(Signal* signal){
- signal->theData[0] = EventReport::TransReportCounters;
+ signal->theData[0] = NDB_LE_TransReportCounters;
signal->theData[1] = ctransCount;
signal->theData[2] = ccommitCount;
signal->theData[3] = creadCount;
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 04b40dafcb5..e61ec45b18d 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -20,6 +20,7 @@
#include "md5_hash.hpp"
#include <RefConvert.hpp>
#include <ndb_limits.h>
+#include <my_sys.h>
#include <signaldata/EventReport.hpp>
#include <signaldata/TcKeyReq.hpp>
@@ -63,6 +64,9 @@
#include <signaldata/PackedSignal.hpp>
#include <AttributeHeader.hpp>
#include <signaldata/DictTabInfo.hpp>
+#include <AttributeDescriptor.hpp>
+#include <SectionReader.hpp>
+#include <KeyDescriptor.hpp>
#include <NdbOut.hpp>
#include <DebuggerNames.hpp>
@@ -313,6 +317,10 @@ void Dbtc::execREAD_NODESREF(Signal* signal)
void Dbtc::execTC_SCHVERREQ(Signal* signal)
{
jamEntry();
+ if (! assembleFragments(signal)) {
+ jam();
+ return;
+ }
tabptr.i = signal->theData[0];
ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
tabptr.p->currentSchemaVersion = signal->theData[1];
@@ -320,10 +328,18 @@ void Dbtc::execTC_SCHVERREQ(Signal* signal)
BlockReference retRef = signal->theData[3];
tabptr.p->tableType = (Uint8)signal->theData[4];
BlockReference retPtr = signal->theData[5];
+ Uint32 noOfKeyAttr = signal->theData[6];
+ ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
+
+ const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
+ ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
ndbrequire(tabptr.p->enabled == false);
tabptr.p->enabled = true;
tabptr.p->dropping = false;
+ tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
+ tabptr.p->hasCharAttr = desc->hasCharAttr;
+ tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
signal->theData[0] = tabptr.i;
signal->theData[1] = retPtr;
@@ -2224,11 +2240,10 @@ void Dbtc::hash(Signal* signal)
UintR Tdata2;
UintR Tdata3;
UintR* Tdata32;
- Uint64 Tdata[512];
-
+
CacheRecord * const regCachePtr = cachePtr.p;
- Tdata32 = (UintR*)&Tdata[0];
-
+ Tdata32 = signal->theData;
+
Tdata0 = regCachePtr->keydata[0];
Tdata1 = regCachePtr->keydata[1];
Tdata2 = regCachePtr->keydata[2];
@@ -2254,31 +2269,71 @@ void Dbtc::hash(Signal* signal)
ti += 4;
}//while
}//if
- UintR ThashValue;
- UintR TdistrHashValue;
- ThashValue = md5_hash((Uint64*)&Tdata32[0], (UintR)regCachePtr->keylen);
- if (regCachePtr->distributionGroupIndicator == 1) {
- if (regCachePtr->distributionGroupType == 1) {
- jam();
- TdistrHashValue = (regCachePtr->distributionGroup << 6);
- } else {
- jam();
- Tdata32[0] = regCachePtr->distributionGroup;
- TdistrHashValue = md5_hash((Uint64*)&Tdata32[0], (UintR)1);
- }//if
- } else if (regCachePtr->distributionKeyIndicator == 1) {
+ UintR keylen = (UintR)regCachePtr->keylen;
+ Uint32 distKey = regCachePtr->distributionKeyIndicator;
+
+ Uint32 tmp[4];
+ if(!regCachePtr->m_special_hash)
+ {
+ md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
+ }
+ else
+ {
+ handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
+ }
+
+ thashValue = tmp[0];
+ if (distKey){
jam();
- TdistrHashValue = md5_hash((Uint64*)&Tdata32[0],
- (UintR)regCachePtr->distributionKeySize);
+ tdistrHashValue = regCachePtr->distributionKey;
} else {
jam();
- TdistrHashValue = ThashValue;
+ tdistrHashValue = tmp[1];
}//if
- thashValue = ThashValue;
- tdistrHashValue = TdistrHashValue;
}//Dbtc::hash()
+bool
+Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen,
+ Uint32 tabPtrI,
+ bool distr)
+{
+ Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
+ const TableRecord* tabPtrP = &tableRecord[tabPtrI];
+ const bool hasCharAttr = tabPtrP->hasCharAttr;
+ const bool hasDistKeys = tabPtrP->noOfDistrKeys > 0;
+
+ Uint32 *dst = (Uint32*)Tmp;
+ Uint32 dstPos = 0;
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
+ Uint32 * keyPartLenPtr;
+ if(hasCharAttr)
+ {
+ keyPartLenPtr = keyPartLen;
+ dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr);
+ ndbrequire(dstPos);
+ }
+ else
+ {
+ dst = src;
+ dstPos = srcLen;
+ keyPartLenPtr = 0;
+ }
+
+ md5_hash(dstHash, (Uint64*)dst, dstPos);
+
+ if(distr && hasDistKeys)
+ {
+ jam();
+
+ Uint32 tmp[4];
+ Uint32 len = create_distr_key(tabPtrI, dst, keyPartLenPtr);
+ md5_hash(tmp, (Uint64*)dst, len);
+ dstHash[1] = tmp[1];
+ }
+ return true; // success
+}
+
/*
INIT_API_CONNECT_REC
---------------------------
@@ -2670,18 +2725,13 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint8 TSimpleFlag = tcKeyReq->getSimpleFlag(Treqinfo);
Uint8 TDirtyFlag = tcKeyReq->getDirtyFlag(Treqinfo);
Uint8 TInterpretedFlag = tcKeyReq->getInterpretedFlag(Treqinfo);
- Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo);
- Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo);
Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo);
Uint8 TexecuteFlag = TexecFlag;
regCachePtr->opSimple = TSimpleFlag;
regCachePtr->opExec = TInterpretedFlag;
regTcPtr->dirtyOp = TDirtyFlag;
-
- regCachePtr->distributionGroupIndicator = TDistrGroupFlag;
- regCachePtr->distributionGroupType = TDistrGroupTypeFlag;
- regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
+ regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
//-------------------------------------------------------------
// The next step is to read the upto three conditional words.
@@ -2690,17 +2740,14 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
{
Uint32 TDistrGHIndex = tcKeyReq->getScanIndFlag(Treqinfo);
- Uint32 TDistrKeyIndex = TDistrGHIndex + TDistrGroupFlag;
+ Uint32 TDistrKeyIndex = TDistrGHIndex;
- Uint32 TscanNode = tcKeyReq->getTakeOverScanNode(TOptionalDataPtr[0]);
Uint32 TscanInfo = tcKeyReq->getTakeOverScanInfo(TOptionalDataPtr[0]);
regCachePtr->scanTakeOverInd = TDistrGHIndex;
- regCachePtr->scanNode = TscanNode;
regCachePtr->scanInfo = TscanInfo;
- regCachePtr->distributionGroup = TOptionalDataPtr[TDistrGHIndex];
- regCachePtr->distributionKeySize = TOptionalDataPtr[TDistrKeyIndex];
+ regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
}
@@ -2734,7 +2781,8 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regCachePtr->keylen = TkeyLength;
regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
regCachePtr->currReclenAi = titcLenAiInTckeyreq;
-
+ regCachePtr->m_special_hash =
+ localTabptr.p->hasCharAttr | (localTabptr.p->noOfDistrKeys > 0);
Tdata1 = TAIDataPtr[0];
Tdata2 = TAIDataPtr[1];
Tdata3 = TAIDataPtr[2];
@@ -2937,6 +2985,15 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
execDIGETNODESREF(signal);
return;
}
+
+ if(ERROR_INSERTED(8050) && signal->theData[3] != getOwnNodeId())
+ {
+ ndbassert(false);
+ signal->theData[1] = 626;
+ execDIGETNODESREF(signal);
+ return;
+ }
+
/****************>>*/
/* DIGETNODESCONF >*/
/* ***************>*/
@@ -2961,7 +3018,7 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
tnoOfBackup = tnodeinfo & 3;
tnoOfStandby = (tnodeinfo >> 8) & 3;
- regCachePtr->distributionKey = (tnodeinfo >> 16) & 255;
+ regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
if (Toperation == ZREAD) {
if (Tdirty == 1) {
jam();
@@ -3051,8 +3108,6 @@ void Dbtc::attrinfoDihReceivedLab(Signal* signal)
CacheRecord * const regCachePtr = cachePtr.p;
TcConnectRecord * const regTcPtr = tcConnectptr.p;
Uint16 Tnode = regTcPtr->tcNodedata[0];
- Uint16 TscanTakeOverInd = regCachePtr->scanTakeOverInd;
- Uint16 TscanNode = regCachePtr->scanNode;
TableRecordPtr localTabptr;
localTabptr.i = regCachePtr->tableref;
@@ -3065,11 +3120,6 @@ void Dbtc::attrinfoDihReceivedLab(Signal* signal)
TCKEY_abort(signal, 58);
return;
}
- if ((TscanTakeOverInd == 1) &&
- (Tnode != TscanNode)) {
- TCKEY_abort(signal, 15);
- return;
- }//if
arrGuard(Tnode, MAX_NDB_NODES);
packLqhkeyreq(signal, calcLqhBlockRef(Tnode));
}//Dbtc::attrinfoDihReceivedLab()
@@ -3131,7 +3181,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
/* ---------------------------------------------------------------------- */
// Bit16 == 0 since StoredProcedures are not yet supported.
/* ---------------------------------------------------------------------- */
- LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->distributionKey);
+ LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
Tdata10 = 0;
@@ -4539,8 +4589,9 @@ void Dbtc::sendApiCommit(Signal* signal)
}
commitConf->transId1 = regApiPtr->transid[0];
commitConf->transId2 = regApiPtr->transid[1];
-
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal, 3, JBB);
+ commitConf->gci = regApiPtr->globalcheckpointid;
+ sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
+ TcCommitConf::SignalLength, JBB);
} else if (regApiPtr->returnsignal == RS_NO_RETURN) {
jam();
} else {
@@ -5233,8 +5284,9 @@ void Dbtc::execTC_COMMITREQ(Signal* signal)
commitConf->apiConnectPtr = apiConnectPtr;
commitConf->transId1 = transId1;
commitConf->transId2 = transId2;
-
- sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal, 3, JBB);
+ commitConf->gci = 0;
+ sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
+ TcCommitConf::SignalLength, JBB);
regApiPtr->returnsignal = RS_NO_RETURN;
releaseAbortResources(signal);
@@ -8490,7 +8542,7 @@ void Dbtc::systemErrorLab(Signal* signal)
void Dbtc::execSCAN_TABREQ(Signal* signal)
{
const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
- const Uint32 reqinfo = scanTabReq->requestInfo;
+ const Uint32 ri = scanTabReq->requestInfo;
const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
@@ -8500,8 +8552,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
Uint32 currSavePointId = 0;
- Uint32 scanConcurrency = scanTabReq->getParallelism(reqinfo);
- Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(reqinfo);
+ Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
+ Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
Uint32 scanParallel = scanConcurrency;
Uint32 errCode;
ScanRecordPtr scanptr;
@@ -8585,6 +8637,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
seizeCacheRecord(signal);
cachePtr.p->keylen = keyLen;
cachePtr.p->save1 = 0;
+ cachePtr.p->distributionKey = scanTabReq->distributionKey;
+ cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
scanptr = seizeScanrec(signal);
ndbrequire(transP->apiScanRec == RNIL);
@@ -8671,6 +8725,7 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
UintR scanParallel,
UintR noOprecPerFrag)
{
+ const UintR ri = scanTabReq->requestInfo;
scanptr.p->scanTcrec = tcConnectptr.i;
scanptr.p->scanApiRec = apiConnectptr.i;
scanptr.p->scanAiLength = scanTabReq->attrLenKeyLen & 0xFFFF;
@@ -8683,12 +8738,13 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
scanptr.p->batch_size_rows = noOprecPerFrag;
Uint32 tmp = 0;
- const UintR ri = scanTabReq->requestInfo;
ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
+ ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
+ ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
ScanFragReq::setAttrLen(tmp, scanTabReq->attrLenKeyLen & 0xFFFF);
scanptr.p->scanRequestInfo = tmp;
@@ -8798,14 +8854,43 @@ void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
return;
}
+ scanptr.p->scanNextFragId = 0;
+ scanptr.p->m_booked_fragments_count= 0;
scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
- /*************************************************
- * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
- * WE MUST FIRST GET THE NUMBER OF FRAGMENTS IN THE TABLE.
- ***************************************************/
- signal->theData[0] = tcConnectptr.p->dihConnectptr;
- signal->theData[1] = scanptr.p->scanTableref;
- sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
+
+ if(!cachePtr.p->distributionKeyIndicator)
+ {
+ jam();
+ /*************************************************
+ * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
+ * WE MUST FIRST GET THE NUMBER OF FRAGMENTS IN THE TABLE.
+ ***************************************************/
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = scanptr.p->scanTableref;
+ sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
+ }
+ else
+ {
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = tabPtr.i;
+ signal->theData[2] = cachePtr.p->distributionKey;
+ EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
+ UintR TerrorIndicator = signal->theData[0];
+ jamEntry();
+ if (TerrorIndicator != 0) {
+ signal->theData[0] = tcConnectptr.i;
+ //signal->theData[1] Contains error
+ execDI_FCOUNTREF(signal);
+ return;
+ }
+
+ UintR Tdata1 = signal->theData[1];
+ scanptr.p->scanNextFragId = Tdata1;
+
+ signal->theData[0] = tcConnectptr.i;
+ signal->theData[1] = 1; // Frag count
+ execDI_FCOUNTCONF(signal);
+ }
return;
}//Dbtc::diFcountReqLab()
@@ -8822,7 +8907,7 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
{
jamEntry();
tcConnectptr.i = signal->theData[0];
- const UintR tfragCount = signal->theData[1];
+ Uint32 tfragCount = signal->theData[1];
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
apiConnectptr.i = tcConnectptr.p->apiConnect;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -8856,24 +8941,17 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
return;
}
- if(scanptr.p->scanParallel > tfragCount){
- jam();
- abortScanLab(signal, scanptr, ZTOO_HIGH_CONCURRENCY_ERROR);
- return;
- }
-
scanptr.p->scanParallel = tfragCount;
scanptr.p->scanNoFrag = tfragCount;
- scanptr.p->scanNextFragId = 0;
scanptr.p->scanState = ScanRecord::RUNNING;
setApiConTimer(apiConnectptr.i, 0, __LINE__);
updateBuddyTimer(apiConnectptr);
ScanFragRecPtr ptr;
- ScanFragList list(c_scan_frag_pool,
- scanptr.p->m_running_scan_frags);
- for (list.first(ptr); !ptr.isNull(); list.next(ptr)){
+ ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ for (list.first(ptr); !ptr.isNull() && tfragCount;
+ list.next(ptr), tfragCount--){
jam();
ptr.p->lqhBlockref = 0;
@@ -8888,6 +8966,22 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
signal->theData[3] = ptr.p->scanFragId;
sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
}//for
+
+ ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
+ for (; !ptr.isNull();)
+ {
+ ptr.p->m_ops = 0;
+ ptr.p->m_totalLen = 0;
+ ptr.p->m_scan_frag_conf_status = 1;
+ ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
+ ptr.p->stopFragTimer();
+
+ ScanFragRecPtr tmp = ptr;
+ list.next(ptr);
+ list.remove(tmp);
+ queued.add(tmp);
+ scanptr.p->m_queued_count++;
+ }
}//Dbtc::execDI_FCOUNTCONF()
/******************************************************
@@ -9238,7 +9332,7 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
}
if(noCompletedOps == 0 && status != 0 &&
- scanptr.p->scanNextFragId < scanptr.p->scanNoFrag){
+ scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
/**
* Start on next fragment
*/
@@ -9408,6 +9502,9 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal)
*/
jam();
ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
+ jam();
+ ndbassert(scanptr.p->m_booked_fragments_count);
+ scanptr.p->m_booked_fragments_count--;
scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
tcConnectptr.i = scanptr.p->scanTcrec;
@@ -9649,8 +9746,9 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
jam();
ops += 21;
}
-
- Uint32 left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
+
+ int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
+ Uint32 booked = scanPtr.p->m_booked_fragments_count;
ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
@@ -9666,8 +9764,10 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
ScanFragRecPtr curr = ptr; // Remove while iterating...
queued.next(ptr);
- bool done = curr.p->m_scan_frag_conf_status && --left;
-
+ bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
+ if(curr.p->m_scan_frag_conf_status)
+ booked++;
+
* ops++ = curr.p->m_apiPtr;
* ops++ = done ? RNIL : curr.i;
* ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
@@ -9685,8 +9785,10 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
}
}
+ scanPtr.p->m_booked_fragments_count = booked;
if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
- scanPtr.p->m_running_scan_frags.isEmpty()){
+ scanPtr.p->m_running_scan_frags.isEmpty())
+ {
conf->requestInfo = op_count | ScanTabConf::EndOfData;
releaseScanResources(scanPtr);
}
@@ -9998,6 +10100,9 @@ void Dbtc::initTable(Signal* signal)
tabptr.p->tableType = 0;
tabptr.p->enabled = false;
tabptr.p->dropping = false;
+ tabptr.p->noOfKeyAttr = 0;
+ tabptr.p->hasCharAttr = 0;
+ tabptr.p->noOfDistrKeys = 0;
}//for
}//Dbtc::initTable()
@@ -11144,7 +11249,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
{
jamEntry();
- TcIndxReq * const tcIndxReq = (TcIndxReq *)signal->getDataPtr();
+ TcKeyReq * const tcIndxReq = (TcKeyReq *)signal->getDataPtr();
const UintR TapiIndex = tcIndxReq->apiConnectPtr;
Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
@@ -11195,7 +11300,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
// If operation is readTupleExclusive or updateTuple then read index
// table with exclusive lock
- Uint32 indexLength = TcIndxReq::getIndexLength(tcIndxRequestInfo);
+ Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
Uint32 attrLength = tcIndxReq->attrLen;
indexOp->expectedKeyInfo = indexLength;
Uint32 includedIndexLength = MIN(indexLength, indexBufSize);
@@ -11500,14 +11605,14 @@ void Dbtc::execTCKEYCONF(Signal* signal)
case(IOS_NOOP): {
jam();
// Should never happen, abort
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
case(IOS_INDEX_ACCESS): {
@@ -11519,14 +11624,14 @@ void Dbtc::execTCKEYCONF(Signal* signal)
case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
jam();
// Double TCKEYCONF, should never happen, abort
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
@@ -11612,8 +11717,8 @@ void Dbtc::execTCKEYREF(Signal* signal)
// Send TCINDXREF
jam();
- TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
ndbassert(regApiPtr->noIndexOp);
regApiPtr->noIndexOp--; // Decrease count
@@ -11622,7 +11727,7 @@ void Dbtc::execTCKEYREF(Signal* signal)
tcIndxRef->transId[1] = tcKeyRef->transId[1];
tcIndxRef->errorCode = tcKeyRef->errorCode;
sendSignal(regApiPtr->ndbapiBlockref,
- GSN_TCINDXREF, signal, TcIndxRef::SignalLength, JBB);
+ GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
return;
}
}
@@ -11689,14 +11794,14 @@ void Dbtc::execTRANSID_AI(Signal* signal)
signal->getLength() - TransIdAI::HeaderLength)) {
jam();
// Failed to allocate space for TransIdAI
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4000;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
@@ -11704,14 +11809,14 @@ void Dbtc::execTRANSID_AI(Signal* signal)
case(IOS_NOOP): {
jam();
// Should never happen, abort
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
break;
}
@@ -11732,14 +11837,14 @@ void Dbtc::execTRANSID_AI(Signal* signal)
#endif
/*
// Too many TRANSID_AI
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
*/
break;
}
@@ -11757,14 +11862,14 @@ void Dbtc::execTRANSID_AI(Signal* signal)
case(IOS_INDEX_OPERATION): {
// Should never receive TRANSID_AI in this state!!
jam();
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
}
@@ -11807,24 +11912,24 @@ void Dbtc::readIndexTable(Signal* signal,
(Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
// Find index table
- if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.indexId)) == NULL) {
+ if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
jam();
// Failed to find index record
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4000;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
tcKeyReq->transId1 = transId1;
tcKeyReq->transId2 = transId2;
tcKeyReq->tableId = indexData->indexId;
tcKeyLength += MIN(keyLength, keyBufSize);
- tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.indexSchemaVersion;
+ tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
TcKeyReq::setOperationType(tcKeyRequestInfo,
opType == ZREAD ? ZREAD : ZREAD_EX);
TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
@@ -11916,7 +12021,7 @@ void Dbtc::executeIndexOperation(Signal* signal,
Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
Uint32 attrBufSize = 5;
Uint32 dataPos = 0;
- TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
+ TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
Uint32 * dataPtr = &tcKeyReq->scanInfo;
Uint32 tcKeyLength = TcKeyReq::StaticLength;
@@ -11927,17 +12032,17 @@ void Dbtc::executeIndexOperation(Signal* signal,
bool moreKeyData = indexOp->transIdAI.first(aiIter);
// Find index table
- if ((indexData = c_theIndexes.getPtr(tcIndxReq->indexId)) == NULL) {
+ if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
jam();
// Failed to find index record
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
// Find schema version of primary table
diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
index dffafc1ab66..cf3c6056d65 100644
--- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -64,6 +64,7 @@
// DbtupSystemRestart.cpp 26000
// DbtupIndex.cpp 28000
// DbtupDebug.cpp 30000
+// DbtupScan.cpp 32000
//------------------------------------------------------------------
/*
@@ -207,6 +208,8 @@
#define ZTUPLE_DELETED_ERROR 626
#define ZINSERT_ERROR 630
+#define ZINVALID_CHAR_FORMAT 744
+
/* SOME WORD POSITIONS OF FIELDS IN SOME HEADERS */
#define ZPAGE_STATE_POS 0 /* POSITION OF PAGE STATE */
@@ -500,7 +503,8 @@ struct Fragoperrec {
Uint32 tableidFrag;
Uint32 fragPointer;
Uint32 attributeCount;
- Uint32 freeNullBit;
+ Uint32 currNullBit;
+ Uint32 noOfNullBits;
Uint32 noOfNewAttrCount;
Uint32 charsetIndex;
BlockReference lqhBlockrefFrag;
@@ -508,6 +512,49 @@ struct Fragoperrec {
};
typedef Ptr<Fragoperrec> FragoperrecPtr;
+ // Position for use by scan
+ struct PagePos {
+ Uint32 m_fragId; // "base" fragment id
+ Uint32 m_fragBit; // two fragments in 5.0
+ Uint32 m_pageId;
+ Uint32 m_tupleNo;
+ bool m_match;
+ };
+
+ // Tup scan op (compare Dbtux::ScanOp)
+ struct ScanOp {
+ enum {
+ Undef = 0,
+ First = 1, // before first entry
+ Locked = 4, // at current entry (no lock needed)
+ Next = 5, // looking for next extry
+ Last = 6, // after last entry
+ Invalid = 9 // cannot return REF to LQH currently
+ };
+ Uint16 m_state;
+ Uint16 m_lockwait; // unused
+ Uint32 m_userPtr; // scanptr.i in LQH
+ Uint32 m_userRef;
+ Uint32 m_tableId;
+ Uint32 m_fragId; // "base" fragment id
+ Uint32 m_fragPtrI[2];
+ Uint32 m_transId1;
+ Uint32 m_transId2;
+ PagePos m_scanPos;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+ typedef Ptr<ScanOp> ScanOpPtr;
+ ArrayPool<ScanOp> c_scanOpPool;
+
+ void scanFirst(Signal* signal, ScanOpPtr scanPtr);
+ void scanNext(Signal* signal, ScanOpPtr scanPtr);
+ void scanClose(Signal* signal, ScanOpPtr scanPtr);
+ void releaseScanOp(ScanOpPtr& scanPtr);
+
struct Fragrecord {
Uint32 nextStartRange;
Uint32 currentPageRange;
@@ -529,6 +576,9 @@ struct Fragrecord {
Uint32 fragTableId;
Uint32 fragmentId;
Uint32 nextfreefrag;
+
+ DLList<ScanOp> m_scanList;
+ Fragrecord(ArrayPool<ScanOp> & scanOpPool) : m_scanList(scanOpPool) {}
};
typedef Ptr<Fragrecord> FragrecordPtr;
@@ -1019,7 +1069,14 @@ public:
* for md5 summing and when returning keyinfo. Returns number of
* words or negative (-terrorCode) on error.
*/
- int tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut);
+ int tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut, bool xfrmFlag);
+
+ /*
+ * ACC reads primary key without headers into an array of words. At
+ * this point in ACC deconstruction, ACC still uses logical references
+ * to fragment and tuple.
+ */
+ int accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag);
/*
* TUX checks if tuple is visible to scan.
@@ -1069,6 +1126,11 @@ private:
void buildIndex(Signal* signal, Uint32 buildPtrI);
void buildIndexReply(Signal* signal, const BuildIndexRec* buildRec);
+ // Tup scan
+ void execACC_SCANREQ(Signal* signal);
+ void execNEXT_SCANREQ(Signal* signal);
+ void execACC_CHECK_SCAN(Signal* signal);
+
//------------------------------------------------------------------
//------------------------------------------------------------------
// Methods to handle execution of TUPKEYREQ + ATTRINFO.
@@ -1618,19 +1680,11 @@ private:
Uint32 attrDescriptor,
Uint32 attrDes2);
-// *****************************************************************
-// Read char routines optionally (tXfrmFlag) apply strxfrm
-// *****************************************************************
-
- bool readCharNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
- bool readCharNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool readBitsNULLable(Uint32* outBuffer, AttributeHeader*, Uint32, Uint32);
+ bool updateBitsNULLable(Uint32* inBuffer, Uint32, Uint32);
+ bool readBitsNotNULL(Uint32* outBuffer, AttributeHeader*, Uint32, Uint32);
+ bool updateBitsNotNULL(Uint32* inBuffer, Uint32, Uint32);
//------------------------------------------------------------------
//------------------------------------------------------------------
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
index 808cfd33696..8c43de52a75 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
@@ -68,7 +68,7 @@ struct Chunk {
void
Dbtup::reportMemoryUsage(Signal* signal, int incDec){
- signal->theData[0] = EventReport::MemoryUsage;
+ signal->theData[0] = NDB_LE_MemoryUsage;
signal->theData[1] = incDec;
signal->theData[2] = sizeof(Page);
signal->theData[3] = cnoOfAllocatedPages;
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 8e3ca6528c2..761f959acdc 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -858,6 +858,8 @@ void Dbtup::sendTUPKEYCONF(Signal* signal,
return;
}//Dbtup::sendTUPKEYCONF()
+#define MAX_READ (sizeof(signal->theData) > MAX_MESSAGE_SIZE ? MAX_MESSAGE_SIZE : sizeof(signal->theData))
+
/* ---------------------------------------------------------------- */
/* ----------------------------- READ ---------------------------- */
/* ---------------------------------------------------------------- */
@@ -878,7 +880,7 @@ int Dbtup::handleReadReq(Signal* signal,
}//if
Uint32 * dst = &signal->theData[25];
- Uint32 dstLen = (sizeof(signal->theData) / 4) - 25;
+ Uint32 dstLen = (MAX_READ / 4) - 25;
const Uint32 node = refToNode(sendBref);
if(node != 0 && node != getOwnNodeId()) {
;
@@ -888,7 +890,7 @@ int Dbtup::handleReadReq(Signal* signal,
* execute direct
*/
dst = &signal->theData[3];
- dstLen = (sizeof(signal->theData) / 4) - 3;
+ dstLen = (MAX_READ / 4) - 3;
}
if (regOperPtr->interpretedExec != 1) {
@@ -1228,7 +1230,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
const BlockReference sendBref = regOperPtr->recBlockref;
Uint32 * dst = &signal->theData[25];
- Uint32 dstLen = (sizeof(signal->theData) / 4) - 25;
+ Uint32 dstLen = (MAX_READ / 4) - 25;
const Uint32 node = refToNode(sendBref);
if(node != 0 && node != getOwnNodeId()) {
;
@@ -1238,7 +1240,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
* execute direct
*/
dst = &signal->theData[3];
- dstLen = (sizeof(signal->theData) / 4) - 3;
+ dstLen = (MAX_READ / 4) - 3;
}
RtotalLen = RinitReadLen;
@@ -1538,13 +1540,8 @@ int Dbtup::interpreterNextLab(Signal* signal,
// Calculate the number of words of this attribute.
// We allow writes into arrays as long as they fit into the 64 bit
// register size.
- //TEST_MR See to that TattrNoOfWords can be
- // read faster from attribute description.
/* --------------------------------------------------------------- */
- Uint32 TarraySize = (TattrDesc1 >> 16);
- Uint32 TattrLogLen = (TattrDesc1 >> 4) & 0xf;
- Uint32 TattrNoOfBits = TarraySize << TattrLogLen;
- Uint32 TattrNoOfWords = (TattrNoOfBits + 31) >> 5;
+ Uint32 TattrNoOfWords = AttributeDescriptor::getSizeInWords(TattrDesc1);
Uint32 Toptype = operPtr.p->optype;
Uint32 TdataForUpdate[3];
@@ -1821,9 +1818,6 @@ int Dbtup::interpreterNextLab(Signal* signal,
case Interpreter::BRANCH_ATTR_OP_ARG:{
jam();
Uint32 cond = Interpreter::getBinaryCondition(theInstruction);
- Uint32 diff = Interpreter::getArrayLengthDiff(theInstruction);
- Uint32 vchr = Interpreter::isVarchar(theInstruction);
- Uint32 nopad =Interpreter::isNopad(theInstruction);
Uint32 ins2 = TcurrentProgram[TprogramCounter];
Uint32 attrId = Interpreter::getBranchCol_AttrId(ins2) << 16;
Uint32 argLen = Interpreter::getBranchCol_Len(ins2);
@@ -1842,84 +1836,93 @@ int Dbtup::interpreterNextLab(Signal* signal,
}
tmpHabitant = attrId;
}
-
- AttributeHeader ah(tmpArea[0]);
+ // get type
+ attrId >>= 16;
+ Uint32 TattrDescrIndex = tabptr.p->tabDescriptor +
+ (attrId << ZAD_LOG_SIZE);
+ Uint32 TattrDesc1 = tableDescriptor[TattrDescrIndex].tabDescr;
+ Uint32 TattrDesc2 = tableDescriptor[TattrDescrIndex+1].tabDescr;
+ Uint32 typeId = AttributeDescriptor::getType(TattrDesc1);
+ void * cs = 0;
+ if(AttributeOffset::getCharsetFlag(TattrDesc2))
+ {
+ Uint32 pos = AttributeOffset::getCharsetPos(TattrDesc2);
+ cs = tabptr.p->charsetArray[pos];
+ }
+ const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getType(typeId);
+
+ // get data
+ AttributeHeader ah(tmpArea[0]);
const char* s1 = (char*)&tmpArea[1];
const char* s2 = (char*)&TcurrentProgram[TprogramCounter+1];
- Uint32 attrLen = (4 * ah.getDataSize()) - diff;
- if (vchr) {
-#if NDB_VERSION_MAJOR >= 3
- bool vok = false;
- if (attrLen >= 2) {
- Uint32 vlen = (s1[0] << 8) | s1[1]; // big-endian
- s1 += 2;
- attrLen -= 2;
- if (attrLen >= vlen) {
- attrLen = vlen;
- vok = true;
- }
+ // fixed length in 5.0
+ Uint32 attrLen = AttributeDescriptor::getSizeInBytes(TattrDesc1);
+
+ bool r1_null = ah.isNULL();
+ bool r2_null = argLen == 0;
+ int res1;
+ if (cond != Interpreter::LIKE &&
+ cond != Interpreter::NOT_LIKE) {
+ if (r1_null || r2_null) {
+ // NULL==NULL and NULL<not-NULL
+ res1 = r1_null && r2_null ? 0 : r1_null ? -1 : 1;
+ } else {
+ res1 = (*sqlType.m_cmp)(cs, s1, attrLen, s2, argLen, true);
}
- if (!vok) {
- terrorCode = ZREGISTER_INIT_ERROR;
- tupkeyErrorLab(signal);
- return -1;
- }
-#else
- Uint32 tmp;
- if (attrLen >= 2) {
- unsigned char* ss = (unsigned char*)&s1[attrLen - 2];
- tmp = (ss[0] << 8) | ss[1];
- if (tmp <= attrLen - 2)
- attrLen = tmp;
+ } else {
+ if (r1_null || r2_null) {
+ // NULL like NULL is true (has no practical use)
+ res1 = r1_null && r2_null ? 0 : -1;
+ } else {
+ res1 = (*sqlType.m_like)(cs, s1, attrLen, s2, argLen);
}
- // XXX handle bad data
-#endif
}
- bool res = false;
+ int res = 0;
switch ((Interpreter::BinaryCondition)cond) {
case Interpreter::EQ:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) == 0;
+ res = (res1 == 0);
break;
case Interpreter::NE:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) != 0;
+ res = (res1 != 0);
break;
// note the condition is backwards
case Interpreter::LT:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) > 0;
+ res = (res1 > 0);
break;
case Interpreter::LE:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) >= 0;
+ res = (res1 >= 0);
break;
case Interpreter::GT:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) < 0;
+ res = (res1 < 0);
break;
case Interpreter::GE:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) <= 0;
+ res = (res1 <= 0);
break;
case Interpreter::LIKE:
- res = NdbSqlUtil::char_like(s1, attrLen, s2, argLen, !nopad);
+ res = (res1 == 0);
break;
case Interpreter::NOT_LIKE:
- res = ! NdbSqlUtil::char_like(s1, attrLen, s2, argLen, !nopad);
+ res = (res1 == 1);
break;
- // XXX handle invalid value
+ // XXX handle invalid value
}
#ifdef TRACE_INTERPRETER
- ndbout_c("cond=%u diff=%d vc=%d nopad=%d attr(%d) = >%.*s<(%d) str=>%.*s<(%d) -> res = %d",
- cond, diff, vchr, nopad,
- attrId >> 16, attrLen, s1, attrLen, argLen, s2, argLen, res);
+ ndbout_c("cond=%u attr(%d)='%.*s'(%d) str='%.*s'(%d) res1=%d res=%d",
+ cond, attrId >> 16,
+ attrLen, s1, attrLen, argLen, s2, argLen, res1, res);
#endif
if (res)
TprogramCounter = brancher(theInstruction, TprogramCounter);
- else {
- Uint32 tmp = (Interpreter::mod4(argLen) >> 2) + 1;
+ else
+ {
+ Uint32 tmp = ((argLen + 3) >> 2) + 1;
TprogramCounter += tmp;
}
break;
}
-
+
case Interpreter::BRANCH_ATTR_EQ_NULL:{
jam();
Uint32 ins2 = TcurrentProgram[TprogramCounter];
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
index af516d53a24..52ac96bc5d3 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
@@ -137,6 +137,11 @@ Dbtup::Dbtup(const class Configuration & conf)
// Ordered index related
addRecSignal(GSN_BUILDINDXREQ, &Dbtup::execBUILDINDXREQ);
+ // Tup scan
+ addRecSignal(GSN_ACC_SCANREQ, &Dbtup::execACC_SCANREQ);
+ addRecSignal(GSN_NEXT_SCANREQ, &Dbtup::execNEXT_SCANREQ);
+ addRecSignal(GSN_ACC_CHECK_SCAN, &Dbtup::execACC_CHECK_SCAN);
+
initData();
}//Dbtup::Dbtup()
@@ -622,6 +627,10 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
c_buildIndexPool.setSize(c_noOfBuildIndexRec);
c_triggerPool.setSize(noOfTriggers);
+ Uint32 nScanOp; // use TUX config for now
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
+ c_scanOpPool.setSize(nScanOp);
+
initRecords();
czero = 0;
cminusOne = czero - 1;
@@ -644,6 +653,8 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
void Dbtup::initRecords()
{
+ unsigned i;
+
// Records with dynamic sizes
attrbufrec = (Attrbufrec*)allocRecord("Attrbufrec",
sizeof(Attrbufrec),
@@ -665,6 +676,11 @@ void Dbtup::initRecords()
fragrecord = (Fragrecord*)allocRecord("Fragrecord",
sizeof(Fragrecord),
cnoOfFragrec);
+
+ for (i = 0; i<cnoOfFragrec; i++) {
+ void * p = &fragrecord[i];
+ new (p) Fragrecord(c_scanOpPool);
+ }
hostBuffer = (HostBuffer*)allocRecord("HostBuffer",
sizeof(HostBuffer),
@@ -702,7 +718,7 @@ void Dbtup::initRecords()
sizeof(Tablerec),
cnoOfTablerec);
- for(unsigned i = 0; i<cnoOfTablerec; i++) {
+ for (i = 0; i<cnoOfTablerec; i++) {
void * p = &tablerec[i];
new (p) Tablerec(c_triggerPool);
}
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
index 5a8642c4d2e..ab6e0642e11 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
@@ -173,7 +173,7 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tu
}
int
-Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut)
+Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut, bool xfrmFlag)
{
ljamEntry();
// use own variables instead of globals
@@ -200,8 +200,7 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* data
operPtr.i = RNIL;
operPtr.p = NULL;
// do it
- int ret = readAttributes(pagePtr.p, pageOffset, attrIds,
- numAttrs, dataOut, ZNIL, true);
+ int ret = readAttributes(pagePtr.p, pageOffset, attrIds, numAttrs, dataOut, ZNIL, xfrmFlag);
// restore globals
tabptr = tabptr_old;
fragptr = fragptr_old;
@@ -229,6 +228,27 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* data
return ret;
}
+int
+Dbtup::accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag)
+{
+ ljamEntry();
+ // get table
+ TablerecPtr tablePtr;
+ tablePtr.i = tableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ // get fragment
+ FragrecordPtr fragPtr;
+ getFragmentrec(fragPtr, fragId, tablePtr.p);
+ // get real page id and tuple offset
+ PagePtr pagePtr;
+ Uint32 pageId = getRealpid(fragPtr.p, fragPageId);
+ ndbrequire((pageIndex & 0x1) == 0);
+ Uint32 pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize;
+ // use TUX routine - optimize later
+ int ret = tuxReadPk(fragPtr.i, pageId, pageOffset, dataOut, xfrmFlag);
+ return ret;
+}
+
bool
Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId)
{
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
index c6e33bdc92b..bacba2a880c 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
@@ -96,9 +96,10 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
fragOperPtr.p->fragidFrag = fragId;
fragOperPtr.p->tableidFrag = regTabPtr.i;
fragOperPtr.p->attributeCount = noOfAttributes;
- fragOperPtr.p->freeNullBit = noOfNullAttr;
+ fragOperPtr.p->noOfNullBits = noOfNullAttr;
fragOperPtr.p->noOfNewAttrCount = noOfNewAttr;
fragOperPtr.p->charsetIndex = 0;
+ fragOperPtr.p->currNullBit = 0;
ndbrequire(reqinfo == ZADDFRAG);
@@ -287,8 +288,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
Uint32 attrId = signal->theData[2];
Uint32 attrDescriptor = signal->theData[3];
- // DICT sends extended type (ignored) and charset number
- Uint32 extType = (signal->theData[4] & 0xFF);
+ // DICT sends charset number in upper half
Uint32 csNumber = (signal->theData[4] >> 16);
regTabPtr.i = fragOperPtr.p->tableidFrag;
@@ -309,13 +309,13 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
Uint32 firstTabDesIndex = regTabPtr.p->tabDescriptor + (attrId * ZAD_SIZE);
setTabDescrWord(firstTabDesIndex, attrDescriptor);
Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
- Uint32 nullBitPos = 0; /* Default pos for NOT NULL attributes */
+ Uint32 nullBitPos = fragOperPtr.p->currNullBit;
+ Uint32 bitCount = 0;
+
if (AttributeDescriptor::getNullable(attrDescriptor)) {
if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
- ljam(); /* NULL ATTR */
- fragOperPtr.p->freeNullBit--; /* STORE NULL BIT POSTITION */
- nullBitPos = fragOperPtr.p->freeNullBit;
- ndbrequire(fragOperPtr.p->freeNullBit < ZNIL); /* Check not below zero */
+ ljam(); /* NULL ATTR */
+ fragOperPtr.p->currNullBit++;
}//if
} else {
ljam();
@@ -331,27 +331,40 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
case 2:
{
ljam();
- Uint32 bitsUsed = AttributeDescriptor::getArraySize(attrDescriptor) * (1 << attrLen);
- regTabPtr.p->tupheadsize += ((bitsUsed + 31) >> 5);
- break;
+ if(attrLen != 0)
+ {
+ ljam();
+ Uint32 bitsUsed =
+ AttributeDescriptor::getArraySize(attrDescriptor) * (1 << attrLen);
+ regTabPtr.p->tupheadsize += ((bitsUsed + 31) >> 5);
+ break;
+ }
+ else
+ {
+ ljam();
+ bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ fragOperPtr.p->currNullBit += bitCount;
+ break;
+ }
}
default:
ndbrequire(false);
break;
}//switch
+ if(nullBitPos + bitCount + 1 >= MAX_NULL_BITS)
+ {
+ terrorCode = TupAddAttrRef::TooManyBitsUsed;
+ addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
+ return;
+ }
AttributeOffset::setOffset(attrDes2, attributePos);
AttributeOffset::setNullFlagPos(attrDes2, nullBitPos);
} else {
ndbrequire(false);
}//if
if (csNumber != 0) {
- CHARSET_INFO* cs = get_charset(csNumber, MYF(0));
- if (cs == NULL) {
- ljam();
- terrorCode = TupAddAttrRef::InvalidCharset;
- addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
- return;
- }
+ CHARSET_INFO* cs = all_charsets[csNumber];
+ ndbrequire(cs != NULL);
Uint32 i = 0;
while (i < fragOperPtr.p->charsetIndex) {
ljam();
@@ -375,7 +388,9 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return;
}//if
- if (lastAttr && (fragOperPtr.p->freeNullBit != 0)) {
+ if (lastAttr &&
+ (fragOperPtr.p->currNullBit != fragOperPtr.p->noOfNullBits))
+ {
ljam();
terrorCode = ZINCONSISTENT_NULL_ATTRIBUTE_COUNT;
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
index cbb165c3eb1..3170d23499a 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
@@ -40,7 +40,11 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
if ((AttributeDescriptor::getArrayType(attrDescriptor) == ZNON_ARRAY) ||
(AttributeDescriptor::getArrayType(attrDescriptor) == ZFIXED_ARRAY)) {
if (!AttributeDescriptor::getNullable(attrDescriptor)) {
- if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1) {
+ if (AttributeDescriptor::getSize(attrDescriptor) == 0){
+ ljam();
+ regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNotNULL;
+ regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNotNULL;
+ } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1){
ljam();
regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHOneWordNotNULL;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHOneWordNotNULL;
@@ -55,13 +59,18 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
} else {
ndbrequire(false);
}//if
- // replace read function of char attribute
+ // replace functions for char attribute
if (AttributeOffset::getCharsetFlag(attrOffset)) {
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readCharNotNULL;
+ regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNotNULL;
+ regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNotNULL;
}
} else {
- if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1) {
+ if (AttributeDescriptor::getSize(attrDescriptor) == 0){
+ ljam();
+ regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNULLable;
+ regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNULLable;
+ } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1){
ljam();
regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHOneWordNULLable;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
@@ -78,10 +87,11 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHZeroWordNULLable;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
}//if
- // replace read function of char attribute
+ // replace functions for char attribute
if (AttributeOffset::getCharsetFlag(attrOffset)) {
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readCharNULLable;
+ regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNULLable;
+ regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
}
}//if
} else if (AttributeDescriptor::getArrayType(attrDescriptor) == ZVAR_ARRAY) {
@@ -329,25 +339,68 @@ Dbtup::readFixedSizeTHManyWordNotNULL(Uint32* outBuffer,
Uint32 attrDes2)
{
Uint32 indexBuf = tOutBufIndex;
+ Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
Uint32 readOffset = AttributeOffset::getOffset(attrDes2);
Uint32 attrNoOfWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 newIndexBuf = indexBuf + attrNoOfWords;
Uint32 maxRead = tMaxRead;
ndbrequire((readOffset + attrNoOfWords - 1) < tCheckOffset);
- if (newIndexBuf <= maxRead) {
- ljam();
- ahOut->setDataSize(attrNoOfWords);
- MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
- &tTupleHeader[readOffset],
- attrNoOfWords);
- tOutBufIndex = newIndexBuf;
- return true;
+ if (! charsetFlag || ! tXfrmFlag) {
+ Uint32 newIndexBuf = indexBuf + attrNoOfWords;
+ if (newIndexBuf <= maxRead) {
+ ljam();
+ ahOut->setDataSize(attrNoOfWords);
+ MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
+ &tTupleHeader[readOffset],
+ attrNoOfWords);
+ tOutBufIndex = newIndexBuf;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ }//if
} else {
ljam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }//if
+ Tablerec* regTabPtr = tabptr.p;
+ Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
+ uchar* dstPtr = (uchar*)&outBuffer[indexBuf];
+ const uchar* srcPtr = (uchar*)&tTupleHeader[readOffset];
+ Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
+ ndbrequire(i < regTabPtr->noOfCharsets);
+ CHARSET_INFO* cs = regTabPtr->charsetArray[i];
+ Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ if (ok) {
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ // see comment in DbtcMain.cpp
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ Uint32 maxIndexBuf = indexBuf + (dstLen >> 2);
+ if (maxIndexBuf <= maxRead) {
+ ljam();
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ ndbrequire(n != -1);
+ while ((n & 3) != 0) {
+ dstPtr[n++] = 0;
+ }
+ Uint32 dstWords = (n >> 2);
+ ahOut->setDataSize(dstWords);
+ Uint32 newIndexBuf = indexBuf + dstWords;
+ ndbrequire(newIndexBuf <= maxRead);
+ tOutBufIndex = newIndexBuf;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ }
+ } else {
+ ljam();
+ terrorCode = ZTUPLE_CORRUPTED_ERROR;
+ }
+ }
+ return false;
}//Dbtup::readFixedSizeTHManyWordNotNULL()
bool
@@ -394,7 +447,6 @@ Dbtup::readFixedSizeTHManyWordNULLable(Uint32* outBuffer,
Uint32 attrDescriptor,
Uint32 attrDes2)
{
-ljam();
if (!nullFlagCheck(attrDes2)) {
ljam();
return readFixedSizeTHManyWordNotNULL(outBuffer,
@@ -555,74 +607,6 @@ Dbtup::readDynSmallVarSize(Uint32* outBuffer,
return false;
}//Dbtup::readDynSmallVarSize()
-
-bool
-Dbtup::readCharNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- Uint32 indexBuf = tOutBufIndex;
- Uint32 readOffset = AttributeOffset::getOffset(attrDes2);
- Uint32 attrNoOfWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 newIndexBuf = indexBuf + attrNoOfWords;
- Uint32 maxRead = tMaxRead;
-
- ndbrequire((readOffset + attrNoOfWords - 1) < tCheckOffset);
- if (newIndexBuf <= maxRead) {
- ljam();
- ahOut->setDataSize(attrNoOfWords);
- if (! tXfrmFlag) {
- MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
- &tTupleHeader[readOffset],
- attrNoOfWords);
- } else {
- ljam();
- Tablerec* regTabPtr = tabptr.p;
- Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
- ndbrequire(i < tabptr.p->noOfCharsets);
- // not const in MySQL
- CHARSET_INFO* cs = tabptr.p->charsetArray[i];
- // XXX should strip Uint32 null padding
- const unsigned nBytes = attrNoOfWords << 2;
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)&outBuffer[indexBuf],
- nBytes,
- (const uchar*)&tTupleHeader[readOffset],
- nBytes);
- // pad with ascii spaces
- while (n < nBytes)
- ((uchar*)&outBuffer[indexBuf])[n++] = 0x20;
- }
- tOutBufIndex = newIndexBuf;
- return true;
- } else {
- ljam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }
-}
-
-bool
-Dbtup::readCharNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- if (!nullFlagCheck(attrDes2)) {
- ljam();
- return readCharNotNULL(outBuffer,
- ahOut,
- attrDescriptor,
- attrDes2);
- } else {
- ljam();
- ahOut->setNULL();
- return true;
- }
-}
-
/* ---------------------------------------------------------------------- */
/* THIS ROUTINE IS USED TO UPDATE A NUMBER OF ATTRIBUTES. IT IS */
/* USED BY THE INSERT ROUTINE, THE UPDATE ROUTINE AND IT CAN BE */
@@ -810,6 +794,7 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
Uint32 indexBuf = tInBufIndex;
Uint32 inBufLen = tInBufLen;
Uint32 updateOffset = AttributeOffset::getOffset(attrDes2);
+ Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
AttributeHeader ahIn(inBuffer[indexBuf]);
Uint32 nullIndicator = ahIn.isNULL();
Uint32 noOfWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
@@ -819,6 +804,31 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
if (newIndex <= inBufLen) {
if (!nullIndicator) {
ljam();
+ if (charsetFlag) {
+ ljam();
+ Tablerec* regTabPtr = tabptr.p;
+ Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
+ Uint32 bytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
+ Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
+ ndbrequire(i < regTabPtr->noOfCharsets);
+ // not const in MySQL
+ CHARSET_INFO* cs = regTabPtr->charsetArray[i];
+ int not_used;
+ const char* ssrc = (const char*)&inBuffer[tInBufIndex + 1];
+ Uint32 lb, len;
+ if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
+ ljam();
+ terrorCode = ZINVALID_CHAR_FORMAT;
+ return false;
+ }
+ // fast fix bug#7340
+ if (typeId != NDB_TYPE_TEXT &&
+ (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL, &not_used) != len) {
+ ljam();
+ terrorCode = ZINVALID_CHAR_FORMAT;
+ return false;
+ }
+ }
tInBufIndex = newIndex;
MEMCOPY_NO_WORDS(&tTupleHeader[updateOffset],
&inBuffer[indexBuf + 1],
@@ -990,18 +1000,187 @@ Dbtup::read_psuedo(Uint32 attrId, Uint32* outBuffer){
Signal * signal = (Signal*)&tmp;
switch(attrId){
case AttributeHeader::FRAGMENT:
- * outBuffer = operPtr.p->fragId;
+ * outBuffer = operPtr.p->fragId >> 1; // remove "hash" bit
+ return 1;
+ case AttributeHeader::FRAGMENT_MEMORY:
+ {
+ Uint64 tmp= fragptr.p->noOfPages;
+ tmp*= 32768;
+ memcpy(outBuffer,&tmp,8);
+ }
+ return 2;
+ case AttributeHeader::ROW_SIZE:
+ * outBuffer = tabptr.p->tupheadsize << 2;
return 1;
case AttributeHeader::ROW_COUNT:
case AttributeHeader::COMMIT_COUNT:
signal->theData[0] = operPtr.p->userpointer;
signal->theData[1] = attrId;
-
+
EXECUTE_DIRECT(DBLQH, GSN_READ_PSUEDO_REQ, signal, 2);
outBuffer[0] = signal->theData[0];
outBuffer[1] = signal->theData[1];
return 2;
+ case AttributeHeader::RANGE_NO:
+ signal->theData[0] = operPtr.p->userpointer;
+ signal->theData[1] = attrId;
+
+ EXECUTE_DIRECT(DBLQH, GSN_READ_PSUEDO_REQ, signal, 2);
+ outBuffer[0] = signal->theData[0];
+ return 1;
default:
return 0;
}
}
+
+bool
+Dbtup::readBitsNotNULL(Uint32* outBuffer,
+ AttributeHeader* ahOut,
+ Uint32 attrDescriptor,
+ Uint32 attrDes2)
+{
+ Tablerec* const regTabPtr = tabptr.p;
+ Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ Uint32 indexBuf = tOutBufIndex;
+ Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
+ Uint32 maxRead = tMaxRead;
+
+ if (newIndexBuf <= maxRead) {
+ ljam();
+ ahOut->setDataSize((bitCount + 31) >> 5);
+ tOutBufIndex = newIndexBuf;
+
+ BitmaskImpl::getField(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos,
+ bitCount,
+ outBuffer+indexBuf);
+
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ return false;
+ }//if
+}
+
+bool
+Dbtup::readBitsNULLable(Uint32* outBuffer,
+ AttributeHeader* ahOut,
+ Uint32 attrDescriptor,
+ Uint32 attrDes2)
+{
+ Tablerec* const regTabPtr = tabptr.p;
+ Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+
+ Uint32 indexBuf = tOutBufIndex;
+ Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
+ Uint32 maxRead = tMaxRead;
+
+ if(BitmaskImpl::get(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos))
+ {
+ ljam();
+ ahOut->setNULL();
+ return true;
+ }
+
+
+ if (newIndexBuf <= maxRead) {
+ ljam();
+ ahOut->setDataSize((bitCount + 31) >> 5);
+ tOutBufIndex = newIndexBuf;
+ BitmaskImpl::getField(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos+1,
+ bitCount,
+ outBuffer+indexBuf);
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ return false;
+ }//if
+}
+
+bool
+Dbtup::updateBitsNotNULL(Uint32* inBuffer,
+ Uint32 attrDescriptor,
+ Uint32 attrDes2)
+{
+ Tablerec* const regTabPtr = tabptr.p;
+ Uint32 indexBuf = tInBufIndex;
+ Uint32 inBufLen = tInBufLen;
+ AttributeHeader ahIn(inBuffer[indexBuf]);
+ Uint32 nullIndicator = ahIn.isNULL();
+ Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
+
+ if (newIndex <= inBufLen) {
+ if (!nullIndicator) {
+ BitmaskImpl::setField(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos,
+ bitCount,
+ inBuffer+indexBuf+1);
+ tInBufIndex = newIndex;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZNOT_NULL_ATTR;
+ return false;
+ }//if
+ } else {
+ ljam();
+ terrorCode = ZAI_INCONSISTENCY_ERROR;
+ return false;
+ }//if
+ return true;
+}
+
+bool
+Dbtup::updateBitsNULLable(Uint32* inBuffer,
+ Uint32 attrDescriptor,
+ Uint32 attrDes2)
+{
+ Tablerec* const regTabPtr = tabptr.p;
+ AttributeHeader ahIn(inBuffer[tInBufIndex]);
+ Uint32 indexBuf = tInBufIndex;
+ Uint32 nullIndicator = ahIn.isNULL();
+ Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+
+ if (!nullIndicator) {
+ BitmaskImpl::clear(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos);
+ BitmaskImpl::setField(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos+1,
+ bitCount,
+ inBuffer+indexBuf+1);
+
+ Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
+ tInBufIndex = newIndex;
+ return true;
+ } else {
+ Uint32 newIndex = tInBufIndex + 1;
+ if (newIndex <= tInBufLen) {
+ ljam();
+ BitmaskImpl::set(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos);
+
+ tInBufIndex = newIndex;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZAI_INCONSISTENCY_ERROR;
+ return false;
+ }//if
+ }//if
+}
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp b/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
new file mode 100644
index 00000000000..396404faa8c
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
@@ -0,0 +1,315 @@
+/* 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 */
+
+#define DBTUP_C
+#include "Dbtup.hpp"
+#include <signaldata/AccScan.hpp>
+#include <signaldata/NextScan.hpp>
+
+#undef jam
+#undef jamEntry
+#define jam() { jamLine(32000 + __LINE__); }
+#define jamEntry() { jamEntryLine(32000 + __LINE__); }
+
+void
+Dbtup::execACC_SCANREQ(Signal* signal)
+{
+ jamEntry();
+ const AccScanReq reqCopy = *(const AccScanReq*)signal->getDataPtr();
+ const AccScanReq* const req = &reqCopy;
+ ScanOpPtr scanPtr;
+ scanPtr.i = RNIL;
+ do {
+ // find table and fragments
+ TablerecPtr tablePtr;
+ tablePtr.i = req->tableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ FragrecordPtr fragPtr[2];
+ Uint32 fragId = req->fragmentNo << 1;
+ fragPtr[0].i = fragPtr[1].i = RNIL;
+ getFragmentrec(fragPtr[0], fragId | 0, tablePtr.p);
+ getFragmentrec(fragPtr[1], fragId | 1, tablePtr.p);
+ ndbrequire(fragPtr[0].i != RNIL && fragPtr[1].i != RNIL);
+ Fragrecord& frag = *fragPtr[0].p;
+ // seize from pool and link to per-fragment list
+ if (! frag.m_scanList.seize(scanPtr)) {
+ jam();
+ break;
+ }
+ new (scanPtr.p) ScanOp();
+ ScanOp& scan = *scanPtr.p;
+ scan.m_state = ScanOp::First;
+ scan.m_userPtr = req->senderData;
+ scan.m_userRef = req->senderRef;
+ scan.m_tableId = tablePtr.i;
+ scan.m_fragId = frag.fragmentId;
+ scan.m_fragPtrI[0] = fragPtr[0].i;
+ scan.m_fragPtrI[1] = fragPtr[1].i;
+ scan.m_transId1 = req->transId1;
+ scan.m_transId2 = req->transId2;
+ // conf
+ AccScanConf* const conf = (AccScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = req->senderData;
+ conf->accPtr = scanPtr.i;
+ conf->flag = AccScanConf::ZNOT_EMPTY_FRAGMENT;
+ sendSignal(req->senderRef, GSN_ACC_SCANCONF, signal,
+ AccScanConf::SignalLength, JBB);
+ return;
+ } while (0);
+ if (scanPtr.i != RNIL) {
+ jam();
+ releaseScanOp(scanPtr);
+ }
+ // LQH does not handle REF
+ signal->theData[0] = 0x313;
+ sendSignal(req->senderRef, GSN_ACC_SCANREF, signal, 1, JBB);
+}
+
+void
+Dbtup::execNEXT_SCANREQ(Signal* signal)
+{
+ jamEntry();
+ const NextScanReq reqCopy = *(const NextScanReq*)signal->getDataPtr();
+ const NextScanReq* const req = &reqCopy;
+ ScanOpPtr scanPtr;
+ c_scanOpPool.getPtr(scanPtr, req->accPtr);
+ ScanOp& scan = *scanPtr.p;
+ FragrecordPtr fragPtr;
+ fragPtr.i = scan.m_fragPtrI[0];
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ Fragrecord& frag = *fragPtr.p;
+ switch (req->scanFlag) {
+ case NextScanReq::ZSCAN_NEXT:
+ jam();
+ break;
+ case NextScanReq::ZSCAN_NEXT_COMMIT:
+ jam();
+ break;
+ case NextScanReq::ZSCAN_COMMIT:
+ jam();
+ {
+ NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = scan.m_userPtr;
+ unsigned signalLength = 1;
+ sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
+ signal, signalLength, JBB);
+ return;
+ }
+ break;
+ case NextScanReq::ZSCAN_CLOSE:
+ jam();
+ scanClose(signal, scanPtr);
+ return;
+ case NextScanReq::ZSCAN_NEXT_ABORT:
+ jam();
+ default:
+ jam();
+ ndbrequire(false);
+ break;
+ }
+ // start looking for next scan result
+ AccCheckScan* checkReq = (AccCheckScan*)signal->getDataPtrSend();
+ checkReq->accPtr = scanPtr.i;
+ checkReq->checkLcpStop = AccCheckScan::ZNOT_CHECK_LCP_STOP;
+ EXECUTE_DIRECT(DBTUP, GSN_ACC_CHECK_SCAN, signal, AccCheckScan::SignalLength);
+ jamEntry();
+}
+
+void
+Dbtup::execACC_CHECK_SCAN(Signal* signal)
+{
+ jamEntry();
+ const AccCheckScan reqCopy = *(const AccCheckScan*)signal->getDataPtr();
+ const AccCheckScan* const req = &reqCopy;
+ ScanOpPtr scanPtr;
+ c_scanOpPool.getPtr(scanPtr, req->accPtr);
+ ScanOp& scan = *scanPtr.p;
+ FragrecordPtr fragPtr;
+ fragPtr.i = scan.m_fragPtrI[0];
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ Fragrecord& frag = *fragPtr.p;
+ if (req->checkLcpStop == AccCheckScan::ZCHECK_LCP_STOP) {
+ jam();
+ signal->theData[0] = scan.m_userPtr;
+ signal->theData[1] = true;
+ EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
+ jamEntry();
+ return;
+ }
+ if (scan.m_state == ScanOp::First) {
+ jam();
+ scanFirst(signal, scanPtr);
+ }
+ if (scan.m_state == ScanOp::Next) {
+ jam();
+ scanNext(signal, scanPtr);
+ }
+ if (scan.m_state == ScanOp::Locked) {
+ jam();
+ const PagePos& pos = scan.m_scanPos;
+ NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = scan.m_userPtr;
+ conf->accOperationPtr = (Uint32)-1; // no lock returned
+ conf->fragId = frag.fragmentId | pos.m_fragBit;
+ conf->localKey[0] = (pos.m_pageId << MAX_TUPLES_BITS) |
+ (pos.m_tupleNo << 1);
+ conf->localKey[1] = 0;
+ conf->localKeyLength = 1;
+ unsigned signalLength = 6;
+ Uint32 blockNo = refToBlock(scan.m_userRef);
+ EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
+ jamEntry();
+ // next time look for next entry
+ scan.m_state = ScanOp::Next;
+ return;
+ }
+ if (scan.m_state == ScanOp::Last ||
+ scan.m_state == ScanOp::Invalid) {
+ jam();
+ NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = scan.m_userPtr;
+ conf->accOperationPtr = RNIL;
+ conf->fragId = RNIL;
+ unsigned signalLength = 3;
+ sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
+ signal, signalLength, JBB);
+ return;
+ }
+ ndbrequire(false);
+}
+
+void
+Dbtup::scanFirst(Signal* signal, ScanOpPtr scanPtr)
+{
+ ScanOp& scan = *scanPtr.p;
+ // set to first fragment, first page, first tuple
+ PagePos& pos = scan.m_scanPos;
+ pos.m_fragId = scan.m_fragId;
+ pos.m_fragBit = 0;
+ pos.m_pageId = 0;
+ pos.m_tupleNo = 0;
+ // just before
+ pos.m_match = false;
+ // let scanNext() do the work
+ scan.m_state = ScanOp::Next;
+}
+
+// TODO optimize this + index build
+void
+Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr)
+{
+ ScanOp& scan = *scanPtr.p;
+ PagePos& pos = scan.m_scanPos;
+ TablerecPtr tablePtr;
+ tablePtr.i = scan.m_tableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ while (true) {
+ // TODO time-slice here after X loops
+ jam();
+ // get fragment
+ if (pos.m_fragBit == 2) {
+ jam();
+ scan.m_state = ScanOp::Last;
+ break;
+ }
+ ndbrequire(pos.m_fragBit <= 1);
+ FragrecordPtr fragPtr;
+ fragPtr.i = scan.m_fragPtrI[pos.m_fragBit];
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ Fragrecord& frag = *fragPtr.p;
+ // get page
+ PagePtr pagePtr;
+ if (pos.m_pageId >= frag.noOfPages) {
+ jam();
+ pos.m_fragBit++;
+ pos.m_pageId = 0;
+ pos.m_tupleNo = 0;
+ pos.m_match = false;
+ continue;
+ }
+ Uint32 realPageId = getRealpid(fragPtr.p, pos.m_pageId);
+ pagePtr.i = realPageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, page);
+ const Uint32 pageState = pagePtr.p->pageWord[ZPAGE_STATE_POS];
+ if (pageState != ZTH_MM_FREE &&
+ pageState != ZTH_MM_FULL) {
+ jam();
+ pos.m_pageId++;
+ pos.m_tupleNo = 0;
+ pos.m_match = false;
+ continue;
+ }
+ // get next tuple
+ if (pos.m_match)
+ pos.m_tupleNo++;
+ pos.m_match = true;
+ const Uint32 tupheadsize = tablePtr.p->tupheadsize;
+ Uint32 pageOffset = ZPAGE_HEADER_SIZE + pos.m_tupleNo * tupheadsize;
+ if (pageOffset + tupheadsize > ZWORDS_ON_PAGE) {
+ jam();
+ pos.m_pageId++;
+ pos.m_tupleNo = 0;
+ pos.m_match = false;
+ continue;
+ }
+ // skip over free tuple
+ bool isFree = false;
+ if (pageState == ZTH_MM_FREE) {
+ jam();
+ if ((pagePtr.p->pageWord[pageOffset] >> 16) == tupheadsize) {
+ Uint32 nextTuple = pagePtr.p->pageWord[ZFREELIST_HEADER_POS] >> 16;
+ while (nextTuple != 0) {
+ jam();
+ if (nextTuple == pageOffset) {
+ jam();
+ isFree = true;
+ break;
+ }
+ nextTuple = pagePtr.p->pageWord[nextTuple] & 0xffff;
+ }
+ }
+ }
+ if (isFree) {
+ jam();
+ continue;
+ }
+ // TODO check for operation and return latest in own tx
+ scan.m_state = ScanOp::Locked;
+ break;
+ }
+}
+
+void
+Dbtup::scanClose(Signal* signal, ScanOpPtr scanPtr)
+{
+ NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = scanPtr.p->m_userPtr;
+ conf->accOperationPtr = RNIL;
+ conf->fragId = RNIL;
+ unsigned signalLength = 3;
+ sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
+ signal, signalLength, JBB);
+ releaseScanOp(scanPtr);
+}
+
+void
+Dbtup::releaseScanOp(ScanOpPtr& scanPtr)
+{
+ FragrecordPtr fragPtr;
+ fragPtr.i = scanPtr.p->m_fragPtrI[0];
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ fragPtr.p->m_scanList.release(scanPtr);
+}
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp b/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
index ed835dc057a..33d63e8ce49 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
@@ -418,7 +418,7 @@ void Dbtup::xlcRestartCompletedLab(Signal* signal)
{
cnoOfLocalLogInfo = 0;
- signal->theData[0] = EventReport::UNDORecordsExecuted;
+ signal->theData[0] = NDB_LE_UNDORecordsExecuted;
signal->theData[1] = DBTUP; // From block
signal->theData[2] = 0; // Total records executed
for (int i = 0; i < 10; i++) {
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
index 0acfd390360..6652464dc0f 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
@@ -607,7 +607,7 @@ void Dbtup::executeTrigger(Signal* signal,
for everybody else.
*/
signal->theData[0] = trigPtr->triggerId;
- signal->theData[1] = regOperPtr->fragId;
+ signal->theData[1] = regOperPtr->fragId >> 1; // send "real" frag id
EXECUTE_DIRECT(BACKUP, GSN_BACKUP_TRIG_REQ, signal, 2);
ljamEntry();
if (signal->theData[0] == 0) {
@@ -757,7 +757,7 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
regTabPtr->noOfKeyAttr,
keyBuffer,
ZATTR_BUFFER_SIZE,
- true);
+ false);
ndbrequire(ret != -1);
noPrimKey= ret;
@@ -800,7 +800,7 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
numAttrsToRead,
mainBuffer,
ZATTR_BUFFER_SIZE,
- true);
+ false);
ndbrequire(ret != -1);
noMainWords= ret;
} else {
@@ -826,7 +826,7 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
numAttrsToRead,
copyBuffer,
ZATTR_BUFFER_SIZE,
- true);
+ false);
ndbrequire(ret != -1);
noCopyWords = ret;
diff --git a/ndb/src/kernel/blocks/dbtup/Makefile.am b/ndb/src/kernel/blocks/dbtup/Makefile.am
index e51410e6be3..2d14ad41025 100644
--- a/ndb/src/kernel/blocks/dbtup/Makefile.am
+++ b/ndb/src/kernel/blocks/dbtup/Makefile.am
@@ -18,6 +18,7 @@ libdbtup_a_SOURCES = \
DbtupGen.cpp \
DbtupSystemRestart.cpp \
DbtupIndex.cpp \
+ DbtupScan.cpp \
DbtupDebug.cpp
include $(top_srcdir)/ndb/config/common.mk.am
diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
index 3d78fccb780..d4a44b9e641 100644
--- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -404,7 +404,7 @@ private:
Uint32 m_accLockOp;
Uint8 m_readCommitted; // no locking
Uint8 m_lockMode;
- Uint8 m_keyInfo;
+ Uint8 m_descending;
ScanBound m_boundMin;
ScanBound m_boundMax;
ScanBound* m_bound[2]; // pointers to above 2
@@ -447,7 +447,7 @@ private:
State m_state;
DictTabInfo::TableType m_tableType;
Uint32 m_tableId;
- Uint16 m_fragOff; // offset for duplicate fragId bits
+ Uint16 unused;
Uint16 m_numFrags;
Uint32 m_fragId[MaxIndexFragments];
Uint32 m_fragPtrI[MaxIndexFragments];
@@ -473,7 +473,7 @@ private:
struct Frag {
Uint32 m_tableId; // copy from index level
Uint32 m_indexId;
- Uint16 m_fragOff;
+ Uint16 unused;
Uint16 m_fragId;
Uint32 m_descPage; // copy from index level
Uint16 m_descOff;
@@ -637,7 +637,7 @@ private:
void execACCKEYREF(Signal* signal);
void execACC_ABORTCONF(Signal* signal);
void scanFirst(ScanOpPtr scanPtr);
- void scanNext(ScanOpPtr scanPtr);
+ void scanNext(ScanOpPtr scanPtr, bool fromMaintReq);
bool scanVisible(ScanOpPtr scanPtr, TreeEnt ent);
void scanClose(Signal* signal, ScanOpPtr scanPtr);
void addAccLockOp(ScanOp& scan, Uint32 accLockOp);
@@ -649,7 +649,9 @@ private:
*/
void searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
void searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
- void searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
+ void searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, bool descending, TreePos& treePos);
+ void searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
+ void searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
/*
* DbtuxCmp.cpp
@@ -1028,7 +1030,7 @@ Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
m_accLockOp(RNIL),
m_readCommitted(0),
m_lockMode(0),
- m_keyInfo(0),
+ m_descending(0),
m_boundMin(scanBoundPool),
m_boundMax(scanBoundPool),
m_scanPos(),
@@ -1072,7 +1074,6 @@ inline
Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
m_tableId(RNIL),
m_indexId(RNIL),
- m_fragOff(ZNIL),
m_fragId(ZNIL),
m_descPage(RNIL),
m_descOff(0),
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
index ddab77b97b5..cf815b14c1a 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
@@ -18,24 +18,26 @@
#include "Dbtux.hpp"
/*
- * Search key vs node prefix or entry
+ * Search key vs node prefix or entry.
*
* The comparison starts at given attribute position. The position is
* updated by number of equal initial attributes found. The entry data
* may be partial in which case CmpUnknown may be returned.
+ *
+ * The attributes are normalized and have variable size given in words.
*/
int
Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, ConstData entryData, unsigned maxlen)
{
const unsigned numAttrs = frag.m_numAttrs;
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
- // number of words of attribute data left
- unsigned len2 = maxlen;
// skip to right position in search key only
for (unsigned i = 0; i < start; i++) {
jam();
searchKey += AttributeHeaderSize + searchKey.ah().getDataSize();
}
+ // number of words of entry data left
+ unsigned len2 = maxlen;
int ret = 0;
while (start < numAttrs) {
if (len2 <= AttributeHeaderSize) {
@@ -47,18 +49,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, Cons
if (! searchKey.ah().isNULL()) {
if (! entryData.ah().isNULL()) {
jam();
- // current attribute
+ // verify attribute id
const DescAttr& descAttr = descEnt.m_descAttr[start];
- // full data size
- const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
- ndbrequire(size1 != 0 && size1 == entryData.ah().getDataSize());
- const unsigned size2 = min(size1, len2);
+ ndbrequire(searchKey.ah().getAttributeId() == descAttr.m_primaryAttrId);
+ ndbrequire(entryData.ah().getAttributeId() == descAttr.m_primaryAttrId);
+ // sizes
+ const unsigned size1 = searchKey.ah().getDataSize();
+ const unsigned size2 = min(entryData.ah().getDataSize(), len2);
len2 -= size2;
// compare
NdbSqlUtil::Cmp* const cmp = c_sqlCmp[start];
const Uint32* const p1 = &searchKey[AttributeHeaderSize];
const Uint32* const p2 = &entryData[AttributeHeaderSize];
- ret = (*cmp)(0, p1, p2, size1, size2);
+ const bool full = (maxlen == MaxAttrDataSize);
+ ret = (*cmp)(0, p1, size1 << 2, p2, size2 << 2, full);
if (ret != 0) {
jam();
break;
@@ -99,18 +103,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, Cons
*
* Following example illustrates this. We are at (a=2, b=3).
*
- * dir bounds strict return
+ * idir bounds strict return
* 0 a >= 2 and b >= 3 no -1
* 0 a >= 2 and b > 3 yes +1
* 1 a <= 2 and b <= 3 no +1
* 1 a <= 2 and b < 3 yes -1
+ *
+ * The attributes are normalized and have variable size given in words.
*/
int
-Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen)
+Dbtux::cmpScanBound(const Frag& frag, unsigned idir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen)
{
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
// direction 0-lower 1-upper
- ndbrequire(dir <= 1);
+ ndbrequire(idir <= 1);
// number of words of data left
unsigned len2 = maxlen;
// in case of no bounds, init last type to something non-strict
@@ -127,21 +133,21 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigne
if (! boundInfo.ah().isNULL()) {
if (! entryData.ah().isNULL()) {
jam();
- // current attribute
- const unsigned index = boundInfo.ah().getAttributeId();
+ // verify attribute id
+ const Uint32 index = boundInfo.ah().getAttributeId();
ndbrequire(index < frag.m_numAttrs);
const DescAttr& descAttr = descEnt.m_descAttr[index];
ndbrequire(entryData.ah().getAttributeId() == descAttr.m_primaryAttrId);
- // full data size
+ // sizes
const unsigned size1 = boundInfo.ah().getDataSize();
- ndbrequire(size1 != 0 && size1 == entryData.ah().getDataSize());
- const unsigned size2 = min(size1, len2);
+ const unsigned size2 = min(entryData.ah().getDataSize(), len2);
len2 -= size2;
// compare
NdbSqlUtil::Cmp* const cmp = c_sqlCmp[index];
const Uint32* const p1 = &boundInfo[AttributeHeaderSize];
const Uint32* const p2 = &entryData[AttributeHeaderSize];
- int ret = (*cmp)(0, p1, p2, size1, size2);
+ const bool full = (maxlen == MaxAttrDataSize);
+ int ret = (*cmp)(0, p1, size1 << 2, p2, size2 << 2, full);
if (ret != 0) {
jam();
return ret;
@@ -165,5 +171,5 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigne
}
// all attributes were equal
const int strict = (type & 0x1);
- return (dir == 0 ? (strict == 0 ? -1 : +1) : (strict == 0 ? +1 : -1));
+ return (idir == 0 ? (strict == 0 ? -1 : +1) : (strict == 0 ? +1 : -1));
}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index 1e1b0d1d5b6..ed29dc57915 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -340,14 +340,14 @@ operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
out << " [savePointId " << dec << scan.m_savePointId << "]";
out << " [accLockOp " << hex << scan.m_accLockOp << "]";
out << " [accLockOps";
- for (unsigned i = 0; i < Dbtux::MaxAccLockOps; i++) {
+ for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
if (scan.m_accLockOps[i] != RNIL)
out << " " << hex << scan.m_accLockOps[i];
}
out << "]";
out << " [readCommitted " << dec << scan.m_readCommitted << "]";
out << " [lockMode " << dec << scan.m_lockMode << "]";
- out << " [keyInfo " << dec << scan.m_keyInfo << "]";
+ out << " [descending " << dec << scan.m_descending << "]";
out << " [pos " << scan.m_scanPos << "]";
out << " [ent " << scan.m_scanEnt << "]";
for (unsigned i = 0; i <= 1; i++) {
@@ -370,7 +370,6 @@ operator<<(NdbOut& out, const Dbtux::Index& index)
{
out << "[Index " << hex << &index;
out << " [tableId " << dec << index.m_tableId << "]";
- out << " [fragOff " << dec << index.m_fragOff << "]";
out << " [numFrags " << dec << index.m_numFrags << "]";
for (unsigned i = 0; i < index.m_numFrags; i++) {
out << " [frag " << dec << i << " ";
@@ -393,7 +392,6 @@ operator<<(NdbOut& out, const Dbtux::Frag& frag)
out << "[Frag " << hex << &frag;
out << " [tableId " << dec << frag.m_tableId << "]";
out << " [indexId " << dec << frag.m_indexId << "]";
- out << " [fragOff " << dec << frag.m_fragOff << "]";
out << " [fragId " << dec << frag.m_fragId << "]";
out << " [descPage " << hex << frag.m_descPage << "]";
out << " [descOff " << dec << frag.m_descOff << "]";
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
index 8990d6c86b6..5640fdf2899 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
@@ -217,6 +217,7 @@ Dbtux::setKeyAttrs(const Frag& frag)
const unsigned numAttrs = frag.m_numAttrs;
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
for (unsigned i = 0; i < numAttrs; i++) {
+ jam();
const DescAttr& descAttr = descEnt.m_descAttr[i];
Uint32 size = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
// set attr id and fixed size
@@ -244,6 +245,26 @@ Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData)
jamEntry();
// TODO handle error
ndbrequire(ret > 0);
+#ifdef VM_TRACE
+ if (debugFlags & (DebugMaint | DebugScan)) {
+ debugOut << "readKeyAttrs:" << endl;
+ ConstData data = keyData;
+ Uint32 totalSize = 0;
+ for (Uint32 i = start; i < frag.m_numAttrs; i++) {
+ Uint32 attrId = data.ah().getAttributeId();
+ Uint32 dataSize = data.ah().getDataSize();
+ debugOut << i << " attrId=" << attrId << " size=" << dataSize;
+ data += 1;
+ for (Uint32 j = 0; j < dataSize; j++) {
+ debugOut << " " << hex << data[0];
+ data += 1;
+ }
+ debugOut << endl;
+ totalSize += 1 + dataSize;
+ }
+ ndbassert((int)totalSize == ret);
+ }
+#endif
}
void
@@ -251,7 +272,7 @@ Dbtux::readTablePk(const Frag& frag, TreeEnt ent, Data pkData, unsigned& pkSize)
{
const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
const TupLoc tupLoc = ent.m_tupLoc;
- int ret = c_tup->tuxReadPk(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), pkData);
+ int ret = c_tup->tuxReadPk(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), pkData, true);
jamEntry();
// TODO handle error
ndbrequire(ret > 0);
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index 30afb51e7d7..4b568badc67 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -57,9 +57,8 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
c_indexPool.getPtr(indexPtr, req->indexId);
ndbrequire(indexPtr.p->m_tableId == req->tableId);
// get base fragment id and extra bits
- const Uint32 fragOff = indexPtr.p->m_fragOff;
- const Uint32 fragId = req->fragId & ((1 << fragOff) - 1);
- const Uint32 fragBit = req->fragId >> fragOff;
+ const Uint32 fragId = req->fragId & ~1;
+ const Uint32 fragBit = req->fragId & 1;
// get the fragment
FragPtr fragPtr;
fragPtr.i = RNIL;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
index b7526593a08..93c4a583624 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
@@ -16,6 +16,7 @@
#define DBTUX_META_CPP
#include "Dbtux.hpp"
+#include <my_sys.h>
/*
* Create index.
@@ -84,7 +85,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
new (fragPtr.p) Frag(c_scanOpPool);
fragPtr.p->m_tableId = req->primaryTableId;
fragPtr.p->m_indexId = req->tableId;
- fragPtr.p->m_fragOff = req->fragOff;
fragPtr.p->m_fragId = req->fragId;
fragPtr.p->m_numAttrs = req->noOfAttr;
fragPtr.p->m_storeNullKey = true; // not yet configurable
@@ -112,7 +112,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
indexPtr.p->m_state = Index::Defining;
indexPtr.p->m_tableType = (DictTabInfo::TableType)req->tableType;
indexPtr.p->m_tableId = req->primaryTableId;
- indexPtr.p->m_fragOff = req->fragOff;
indexPtr.p->m_numAttrs = req->noOfAttr;
indexPtr.p->m_storeNullKey = true; // not yet configurable
// allocate attribute descriptors
@@ -128,7 +127,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
indexPtr.p->m_state == Index::Defining &&
indexPtr.p->m_tableType == (DictTabInfo::TableType)req->tableType &&
indexPtr.p->m_tableId == req->primaryTableId &&
- indexPtr.p->m_fragOff == req->fragOff &&
indexPtr.p->m_numAttrs == req->noOfAttr);
}
// copy metadata address to each fragment
@@ -203,7 +201,7 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
DescAttr& descAttr = descEnt.m_descAttr[attrId];
descAttr.m_attrDesc = req->attrDescriptor;
descAttr.m_primaryAttrId = req->primaryAttrId;
- descAttr.m_typeId = req->extTypeInfo & 0xFF;
+ descAttr.m_typeId = AttributeDescriptor::getType(req->attrDescriptor);
descAttr.m_charset = (req->extTypeInfo >> 16);
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
@@ -218,17 +216,15 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
errorCode = TuxAddAttrRef::InvalidAttributeType;
break;
}
-#ifdef dbtux_uses_charset
if (descAttr.m_charset != 0) {
- CHARSET_INFO *cs = get_charset(descAttr.m_charset, MYF(0));
- // here use the non-binary type
+ CHARSET_INFO *cs = all_charsets[descAttr.m_charset];
+ ndbrequire(cs != 0);
if (! NdbSqlUtil::usable_in_ordered_index(descAttr.m_typeId, cs)) {
jam();
errorCode = TuxAddAttrRef::InvalidCharset;
break;
}
}
-#endif
const bool lastAttr = (indexPtr.p->m_numAttrs == fragOpPtr.p->m_numAttrsRecvd);
if (ERROR_INSERTED(12003) && fragOpPtr.p->m_fragNo == 0 && attrId == 0 ||
ERROR_INSERTED(12004) && fragOpPtr.p->m_fragNo == 0 && lastAttr ||
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
index 9f9d4cb68e3..68a3e78ce9e 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
@@ -502,7 +502,7 @@ Dbtux::moveScanList(NodeHandle& node, unsigned pos)
debugOut << "At pos=" << pos << " " << node << endl;
}
#endif
- scanNext(scanPtr);
+ scanNext(scanPtr, true);
ndbrequire(! (scanPos.m_loc == node.m_loc && scanPos.m_pos == pos));
}
scanPtr.i = nextPtrI;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index 8677ae741b3..a61b7c1f5ca 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -16,6 +16,7 @@
#define DBTUX_SCAN_CPP
#include "Dbtux.hpp"
+#include <my_sys.h>
void
Dbtux::execACC_SCANREQ(Signal* signal)
@@ -34,7 +35,7 @@ Dbtux::execACC_SCANREQ(Signal* signal)
fragPtr.i = RNIL;
for (unsigned i = 0; i < indexPtr.p->m_numFrags; i++) {
jam();
- if (indexPtr.p->m_fragId[i] == req->fragmentNo) {
+ if (indexPtr.p->m_fragId[i] == req->fragmentNo << 1) {
jam();
c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
break;
@@ -43,7 +44,6 @@ Dbtux::execACC_SCANREQ(Signal* signal)
ndbrequire(fragPtr.i != RNIL);
Frag& frag = *fragPtr.p;
// 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 == NullTupLoc) {
@@ -74,18 +74,18 @@ Dbtux::execACC_SCANREQ(Signal* signal)
scanPtr.p->m_savePointId = req->savePointId;
scanPtr.p->m_readCommitted = AccScanReq::getReadCommittedFlag(req->requestInfo);
scanPtr.p->m_lockMode = AccScanReq::getLockMode(req->requestInfo);
- scanPtr.p->m_keyInfo = AccScanReq::getKeyinfoFlag(req->requestInfo);
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Seize scan " << scanPtr.i << " " << *scanPtr.p << endl;
- }
-#endif
+ scanPtr.p->m_descending = AccScanReq::getDescendingFlag(req->requestInfo);
/*
* readCommitted lockMode keyInfo
* 1 0 0 - read committed (no lock)
* 0 0 0 - read latest (read lock)
* 0 1 1 - read exclusive (write lock)
*/
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Seize scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ }
+#endif
// conf
AccScanConf* const conf = (AccScanConf*)signal->getDataPtrSend();
conf->scanPtr = req->senderData;
@@ -114,50 +114,100 @@ Dbtux::execACC_SCANREQ(Signal* signal)
* keys and that all but possibly last bound is non-strict.
*
* Finally save the sets of lower and upper bounds (i.e. start key and
- * end key). Full bound type (< 4) is included but only the strict bit
- * is used since lower and upper have now been separated.
+ * end key). Full bound type is included but only the strict bit is
+ * used since lower and upper have now been separated.
*/
void
Dbtux::execTUX_BOUND_INFO(Signal* signal)
{
jamEntry();
- struct BoundInfo {
- int type;
- unsigned offset;
- unsigned size;
- };
- TuxBoundInfo* const sig = (TuxBoundInfo*)signal->getDataPtrSend();
- const TuxBoundInfo reqCopy = *(const TuxBoundInfo*)sig;
- const TuxBoundInfo* const req = &reqCopy;
// get records
+ TuxBoundInfo* const sig = (TuxBoundInfo*)signal->getDataPtrSend();
+ const TuxBoundInfo* const req = (const TuxBoundInfo*)sig;
ScanOp& scan = *c_scanOpPool.getPtr(req->tuxScanPtrI);
- Index& index = *c_indexPool.getPtr(scan.m_indexId);
- // collect lower and upper bounds
+ const Index& index = *c_indexPool.getPtr(scan.m_indexId);
+ const DescEnt& descEnt = getDescEnt(index.m_descPage, index.m_descOff);
+ // collect normalized lower and upper bounds
+ struct BoundInfo {
+ int type2; // with EQ -> LE/GE
+ Uint32 offset; // offset in xfrmData
+ Uint32 size;
+ };
BoundInfo boundInfo[2][MaxIndexAttributes];
+ const unsigned dstSize = 1024 * MAX_XFRM_MULTIPLY;
+ Uint32 xfrmData[dstSize];
+ Uint32 dstPos = 0;
// largest attrId seen plus one
Uint32 maxAttrId[2] = { 0, 0 };
- unsigned offset = 0;
- const Uint32* const data = (Uint32*)sig + TuxBoundInfo::SignalLength;
// walk through entries
+ const Uint32* const data = (Uint32*)sig + TuxBoundInfo::SignalLength;
+ Uint32 offset = 0;
while (offset + 2 <= req->boundAiLength) {
jam();
const unsigned type = data[offset];
- if (type > 4) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
- return;
- }
const AttributeHeader* ah = (const AttributeHeader*)&data[offset + 1];
const Uint32 attrId = ah->getAttributeId();
const Uint32 dataSize = ah->getDataSize();
- if (attrId >= index.m_numAttrs) {
+ if (type > 4 || attrId >= index.m_numAttrs || dstPos + 2 + dataSize > dstSize) {
jam();
scan.m_state = ScanOp::Invalid;
sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
return;
}
+ // copy header
+ xfrmData[dstPos + 0] = data[offset + 0];
+ xfrmData[dstPos + 1] = data[offset + 1];
+ // copy bound value
+ Uint32 dstWords = 0;
+ if (! ah->isNULL()) {
+ jam();
+ const DescAttr& descAttr = descEnt.m_descAttr[attrId];
+ Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(descAttr.m_attrDesc);
+ Uint32 srcWords = (srcBytes + 3) / 4;
+ if (srcWords != dataSize) {
+ jam();
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
+ return;
+ }
+ uchar* dstPtr = (uchar*)&xfrmData[dstPos + 2];
+ const uchar* srcPtr = (const uchar*)&data[offset + 2];
+ if (descAttr.m_charset == 0) {
+ memcpy(dstPtr, srcPtr, srcWords << 2);
+ dstWords = srcWords;
+ } else {
+ jam();
+ Uint32 typeId = descAttr.m_typeId;
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ if (! ok) {
+ jam();
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::InvalidCharFormat;
+ return;
+ }
+ CHARSET_INFO* cs = all_charsets[descAttr.m_charset];
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ // see comment in DbtcMain.cpp
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ if (dstLen > ((dstSize - dstPos) << 2)) {
+ jam();
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::TooMuchAttrInfo;
+ return;
+ }
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ ndbrequire(n != -1);
+ while ((n & 3) != 0) {
+ dstPtr[n++] = 0;
+ }
+ dstWords = n / 4;
+ }
+ }
for (unsigned j = 0; j <= 1; j++) {
+ jam();
// check if lower/upper bit matches
const unsigned luBit = (j << 1);
if ((type & 0x2) != luBit && type != 4)
@@ -166,29 +216,35 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
const unsigned type2 = (type & 0x1) | luBit;
// fill in any gap
while (maxAttrId[j] <= attrId) {
+ jam();
BoundInfo& b = boundInfo[j][maxAttrId[j]++];
- b.type = -1;
+ b.type2 = -1;
}
BoundInfo& b = boundInfo[j][attrId];
- if (b.type != -1) {
- // compare with previous bound
- if (b.type != (int)type2 ||
- b.size != 2 + dataSize ||
- memcmp(&data[b.offset + 2], &data[offset + 2], dataSize << 2) != 0) {
+ if (b.type2 != -1) {
+ // compare with previously defined bound
+ if (b.type2 != (int)type2 ||
+ b.size != 2 + dstWords ||
+ memcmp(&xfrmData[b.offset + 2], &xfrmData[dstPos + 2], dstWords << 2) != 0) {
jam();
scan.m_state = ScanOp::Invalid;
sig->errorCode = TuxBoundInfo::InvalidBounds;
return;
}
} else {
+ // fix length
+ AttributeHeader* ah = (AttributeHeader*)&xfrmData[dstPos + 1];
+ ah->setDataSize(dstWords);
// enter new bound
- b.type = type2;
- b.offset = offset;
- b.size = 2 + dataSize;
+ jam();
+ b.type2 = type2;
+ b.offset = dstPos;
+ b.size = 2 + dstWords;
}
}
// jump to next
offset += 2 + dataSize;
+ dstPos += 2 + dstWords;
}
if (offset != req->boundAiLength) {
jam();
@@ -202,13 +258,13 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
jam();
const BoundInfo& b = boundInfo[j][i];
// check for gap or strict bound before last
- if (b.type == -1 || (i + 1 < maxAttrId[j] && (b.type & 0x1))) {
+ if (b.type2 == -1 || (i + 1 < maxAttrId[j] && (b.type2 & 0x1))) {
jam();
scan.m_state = ScanOp::Invalid;
sig->errorCode = TuxBoundInfo::InvalidBounds;
return;
}
- bool ok = scan.m_bound[j]->append(&data[b.offset], b.size);
+ bool ok = scan.m_bound[j]->append(&xfrmData[b.offset], b.size);
if (! ok) {
jam();
scan.m_state = ScanOp::Invalid;
@@ -354,7 +410,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = RNIL; // no tuple returned
- conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ conf->fragId = frag.m_fragId | ent.m_fragBit;
unsigned signalLength = 3;
// if TC has ordered scan close, it will be detected here
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
@@ -374,7 +430,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
if (scan.m_state == ScanOp::Next) {
jam();
// look for next
- scanNext(scanPtr);
+ scanNext(scanPtr, false);
}
// for reading tuple key in Current or Locked state
Data pkData = c_dataBuffer;
@@ -397,7 +453,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
lockReq->userPtr = scanPtr.i;
lockReq->userRef = reference();
lockReq->tableId = scan.m_tableId;
- lockReq->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ lockReq->fragId = frag.m_fragId | ent.m_fragBit;
lockReq->fragPtrI = frag.m_accTableFragPtrI[ent.m_fragBit];
const Uint32* const buf32 = static_cast<Uint32*>(pkData);
const Uint64* const buf64 = reinterpret_cast<const Uint64*>(buf32);
@@ -474,13 +530,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
jam();
// read keys if not already done (uses signal)
const TreeEnt ent = scan.m_scanEnt;
- if (scan.m_keyInfo) {
- jam();
- if (pkSize == 0) {
- jam();
- readTablePk(frag, ent, pkData, pkSize);
- }
- }
// conf signal
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
@@ -496,21 +545,12 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
accLockOp = (Uint32)-1;
}
conf->accOperationPtr = accLockOp;
- conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ conf->fragId = frag.m_fragId | ent.m_fragBit;
conf->localKey[0] = getTupAddr(frag, ent);
conf->localKey[1] = 0;
conf->localKeyLength = 1;
unsigned signalLength = 6;
// add key info
- if (scan.m_keyInfo) {
- jam();
- conf->keyLength = pkSize;
- // piggy-back first 4 words of key data
- for (unsigned i = 0; i < 4; i++) {
- conf->key[i] = i < pkSize ? pkData[i] : 0;
- }
- signalLength = 11;
- }
if (! scan.m_readCommitted) {
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
@@ -518,24 +558,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
Uint32 blockNo = refToBlock(scan.m_userRef);
EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
}
- // send rest of key data
- if (scan.m_keyInfo && pkSize > 4) {
- unsigned total = 4;
- while (total < pkSize) {
- jam();
- unsigned length = pkSize - total;
- if (length > 20)
- length = 20;
- signal->theData[0] = scan.m_userPtr;
- signal->theData[1] = 0;
- signal->theData[2] = 0;
- signal->theData[3] = length;
- memcpy(&signal->theData[4], &pkData[total], length << 2);
- sendSignal(scan.m_userRef, GSN_ACC_SCAN_INFO24,
- signal, 4 + length, JBB);
- total += length;
- }
- }
// next time look for next entry
scan.m_state = ScanOp::Next;
return;
@@ -687,8 +709,10 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
TreeHead& tree = frag.m_tree;
// set up index keys for this operation
setKeyAttrs(frag);
- // unpack lower bound into c_dataBuffer
- const ScanBound& bound = *scan.m_bound[0];
+ // scan direction 0, 1
+ const unsigned idir = scan.m_descending;
+ // unpack start key into c_dataBuffer
+ const ScanBound& bound = *scan.m_bound[idir];
ScanBoundIterator iter;
bound.first(iter);
for (unsigned j = 0; j < bound.getSize(); j++) {
@@ -696,11 +720,10 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
c_dataBuffer[j] = *iter.data;
bound.next(iter);
}
- // search for scan start position
TreePos treePos;
- searchToScan(frag, c_dataBuffer, scan.m_boundCnt[0], treePos);
+ searchToScan(frag, c_dataBuffer, scan.m_boundCnt[idir], scan.m_descending, treePos);
if (treePos.m_loc == NullTupLoc) {
- // empty tree
+ // empty result set
jam();
scan.m_state = ScanOp::Last;
return;
@@ -718,7 +741,8 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
* Move to next entry. The scan is already linked to some node. When
* we leave, if an entry was found, it will be linked to a possibly
* different node. The scan has a position, and a direction which tells
- * from where we came to this position. This is one of:
+ * from where we came to this position. This is one of (all comments
+ * are in terms of ascending scan):
*
* 0 - up from left child (scan this node next)
* 1 - up from right child (proceed to parent)
@@ -730,7 +754,7 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
* re-organizations need not worry about scan direction.
*/
void
-Dbtux::scanNext(ScanOpPtr scanPtr)
+Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
{
ScanOp& scan = *scanPtr.p;
Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
@@ -743,8 +767,11 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
ndbrequire(scan.m_state != ScanOp::Locked);
// set up index keys for this operation
setKeyAttrs(frag);
- // unpack upper bound into c_dataBuffer
- const ScanBound& bound = *scan.m_bound[1];
+ // scan direction
+ const unsigned idir = scan.m_descending; // 0, 1
+ const int jdir = 1 - 2 * (int)idir; // 1, -1
+ // unpack end key into c_dataBuffer
+ const ScanBound& bound = *scan.m_bound[1 - idir];
ScanBoundIterator iter;
bound.first(iter);
for (unsigned j = 0; j < bound.getSize(); j++) {
@@ -764,6 +791,11 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
TreeEnt ent;
while (true) {
jam();
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Scan next pos " << pos << " " << node << endl;
+ }
+#endif
if (pos.m_dir == 2) {
// coming up from root ends the scan
jam();
@@ -778,7 +810,7 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
if (pos.m_dir == 4) {
// coming down from parent proceed to left child
jam();
- TupLoc loc = node.getLink(0);
+ TupLoc loc = node.getLink(idir);
if (loc != NullTupLoc) {
jam();
pos.m_loc = loc;
@@ -786,34 +818,42 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
continue;
}
// pretend we came from left child
- pos.m_dir = 0;
+ pos.m_dir = idir;
+ }
+ const unsigned occup = node.getOccup();
+ if (occup == 0) {
+ jam();
+ ndbrequire(fromMaintReq);
+ // move back to parent - see comment in treeRemoveInner
+ pos.m_loc = node.getLink(2);
+ pos.m_dir = node.getSide();
+ continue;
}
- if (pos.m_dir == 0) {
+ if (pos.m_dir == idir) {
// coming up from left child scan current node
jam();
- pos.m_pos = 0;
+ pos.m_pos = idir == 0 ? 0 : occup - 1;
pos.m_match = false;
pos.m_dir = 3;
}
if (pos.m_dir == 3) {
// within node
jam();
- unsigned occup = node.getOccup();
- ndbrequire(occup >= 1);
// advance position
if (! pos.m_match)
pos.m_match = true;
else
- pos.m_pos++;
+ // becomes ZNIL (which is > occup) if 0 and scan descending
+ pos.m_pos += jdir;
if (pos.m_pos < occup) {
jam();
ent = node.getEnt(pos.m_pos);
pos.m_dir = 3; // unchanged
// read and compare all attributes
readKeyAttrs(frag, ent, 0, c_entryKey);
- int ret = cmpScanBound(frag, 1, c_dataBuffer, scan.m_boundCnt[1], c_entryKey);
+ int ret = cmpScanBound(frag, 1 - idir, c_dataBuffer, scan.m_boundCnt[1 - idir], c_entryKey);
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- if (ret < 0) {
+ if (jdir * ret < 0) {
jam();
// hit upper bound of single range scan
pos.m_loc = NullTupLoc;
@@ -830,7 +870,7 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
break;
}
// after node proceed to right child
- TupLoc loc = node.getLink(1);
+ TupLoc loc = node.getLink(1 - idir);
if (loc != NullTupLoc) {
jam();
pos.m_loc = loc;
@@ -838,9 +878,9 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
continue;
}
// pretend we came from right child
- pos.m_dir = 1;
+ pos.m_dir = 1 - idir;
}
- if (pos.m_dir == 1) {
+ if (pos.m_dir == 1 - idir) {
// coming up from right child proceed to parent
jam();
pos.m_loc = node.getLink(2);
@@ -890,7 +930,7 @@ Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent)
const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
Uint32 fragBit = ent.m_fragBit;
Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[fragBit];
- Uint32 fragId = frag.m_fragId | (fragBit << frag.m_fragOff);
+ Uint32 fragId = frag.m_fragId | fragBit;
Uint32 tupAddr = getTupAddr(frag, ent);
Uint32 tupVersion = ent.m_tupVersion;
// check for same tuple twice in row
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
index 7057d74c3ad..b0e2a664bfd 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
@@ -253,22 +253,33 @@ Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePo
/*
* Search for scan start position.
*
- * Similar to searchToAdd.
+ * Similar to searchToAdd. The routines differ somewhat depending on
+ * scan direction and are done by separate methods.
*/
void
-Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
+Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, bool descending, TreePos& treePos)
{
const TreeHead& tree = frag.m_tree;
- NodeHandle currNode(frag);
- currNode.m_loc = tree.m_root;
- if (currNode.m_loc == NullTupLoc) {
- // empty tree
- jam();
- treePos.m_match = false;
+ if (tree.m_root != NullTupLoc) {
+ if (! descending)
+ searchToScanAscending(frag, boundInfo, boundCount, treePos);
+ else
+ searchToScanDescending(frag, boundInfo, boundCount, treePos);
return;
}
+ // empty tree
+}
+
+void
+Dbtux::searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
+{
+ const TreeHead& tree = frag.m_tree;
+ NodeHandle currNode(frag);
+ currNode.m_loc = tree.m_root;
NodeHandle glbNode(frag); // potential g.l.b of final node
NodeHandle bottomNode(frag);
+ // always before entry
+ treePos.m_match = false;
while (true) {
jam();
selectNode(currNode, currNode.m_loc);
@@ -283,6 +294,7 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
}
if (ret < 0) {
+ // bound is left of this node
jam();
const TupLoc loc = currNode.getLink(0);
if (loc != NullTupLoc) {
@@ -300,11 +312,11 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
// start scanning this node
treePos.m_loc = currNode.m_loc;
treePos.m_pos = 0;
- treePos.m_match = false;
treePos.m_dir = 3;
return;
}
} else if (ret > 0) {
+ // bound is at or right of this node
jam();
const TupLoc loc = currNode.getLink(1);
if (loc != NullTupLoc) {
@@ -316,7 +328,7 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
continue;
}
} else {
- ndbassert(false);
+ ndbrequire(false);
}
break;
}
@@ -328,20 +340,19 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
if (ret < 0) {
- // start scanning from current entry
+ // found first entry satisfying the bound
treePos.m_loc = currNode.m_loc;
treePos.m_pos = j;
- treePos.m_match = false;
treePos.m_dir = 3;
return;
}
}
+ // bound is to right of this node
if (! bottomNode.isNull()) {
jam();
// start scanning the l.u.b
treePos.m_loc = bottomNode.m_loc;
treePos.m_pos = 0;
- treePos.m_match = false;
treePos.m_dir = 3;
return;
}
@@ -349,3 +360,90 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
treePos.m_loc = currNode.m_loc;
treePos.m_dir = 1;
}
+
+void
+Dbtux::searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
+{
+ const TreeHead& tree = frag.m_tree;
+ NodeHandle currNode(frag);
+ currNode.m_loc = tree.m_root;
+ NodeHandle glbNode(frag); // potential g.l.b of final node
+ NodeHandle bottomNode(frag);
+ // always before entry
+ treePos.m_match = false;
+ while (true) {
+ jam();
+ selectNode(currNode, currNode.m_loc);
+ int ret;
+ // compare prefix
+ ret = cmpScanBound(frag, 1, boundInfo, boundCount, currNode.getPref(), tree.m_prefSize);
+ if (ret == NdbSqlUtil::CmpUnknown) {
+ jam();
+ // read and compare all attributes
+ readKeyAttrs(frag, currNode.getMinMax(0), 0, c_entryKey);
+ ret = cmpScanBound(frag, 1, boundInfo, boundCount, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ }
+ if (ret < 0) {
+ // bound is left of this node
+ jam();
+ const TupLoc loc = currNode.getLink(0);
+ if (loc != NullTupLoc) {
+ jam();
+ // continue to left subtree
+ currNode.m_loc = loc;
+ continue;
+ }
+ if (! glbNode.isNull()) {
+ jam();
+ // move up to the g.l.b but remember the bottom node
+ bottomNode = currNode;
+ currNode = glbNode;
+ } else {
+ // empty result set
+ return;
+ }
+ } else if (ret > 0) {
+ // bound is at or right of this node
+ jam();
+ const TupLoc loc = currNode.getLink(1);
+ if (loc != NullTupLoc) {
+ jam();
+ // save potential g.l.b
+ glbNode = currNode;
+ // continue to right subtree
+ currNode.m_loc = loc;
+ continue;
+ }
+ } else {
+ ndbrequire(false);
+ }
+ break;
+ }
+ for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) {
+ jam();
+ int ret;
+ // read and compare attributes
+ readKeyAttrs(frag, currNode.getEnt(j), 0, c_entryKey);
+ ret = cmpScanBound(frag, 1, boundInfo, boundCount, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ if (ret < 0) {
+ if (j > 0) {
+ // start scanning from previous entry
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = j - 1;
+ treePos.m_dir = 3;
+ return;
+ }
+ // start scanning upwards (pretend we came from left child)
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = 0;
+ treePos.m_dir = 0;
+ return;
+ }
+ }
+ // start scanning this node
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = currNode.getOccup() - 1;
+ treePos.m_dir = 3;
+}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
index b9e3b593a00..5107a8d8e31 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
@@ -226,6 +226,9 @@ Dbtux::treeRemoveInner(Frag& frag, NodeHandle lubNode, unsigned pos)
// borrow max entry from semi/leaf
Uint32 scanList = RNIL;
nodePopDown(glbNode, glbNode.getOccup() - 1, ent, &scanList);
+ // g.l.b may be empty now
+ // a descending scan may try to enter the empty g.l.b
+ // we prevent this in scanNext
nodePopUp(lubNode, pos, ent, scanList);
if (glbNode.getLink(0) != NullTupLoc) {
jam();
diff --git a/ndb/src/kernel/blocks/dbtux/Times.txt b/ndb/src/kernel/blocks/dbtux/Times.txt
index 1e6d0a0a329..68120084846 100644
--- a/ndb/src/kernel/blocks/dbtux/Times.txt
+++ b/ndb/src/kernel/blocks/dbtux/Times.txt
@@ -138,6 +138,14 @@ before mc02/c 5 ms 13 ms 126 pct
after mc02/c 5 ms 10 ms 70 pct
mc02/d 178 ms 242 ms 69 pct
-[ prelim preformance fix for max batch size 16 -> 992 ]
+[ prelim performance fix for max batch size 16 -> 992 ]
+
+wl-2066 mc02/c 5 ms 10 ms 87 pct
+before mc02/d 140 ms 237 ms 69 pct
+
+wl-2066 mc02/c 5 ms 10 ms 69 pct
+after mc02/d 150 ms 229 ms 52 pct
+
+[ wl-2066 = remove ACC storage, use TUX test to see effect ]
vim: set et:
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 071a85c96da..97b16f1dbc4 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -1458,7 +1458,7 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal)
while(!allFailed.isclear()){
nodeId = allFailed.find(nodeId + 1);
allFailed.clear(nodeId);
- signal->theData[0] = EventReport::NODE_FAILREP;
+ signal->theData[0] = NDB_LE_NODE_FAILREP;
signal->theData[1] = nodeId;
signal->theData[2] = 0;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -1574,13 +1574,9 @@ void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
ndbassert(column.pos == i);
w.add(DictTabInfo::AttributeName, column.name);
w.add(DictTabInfo::AttributeId, (Uint32)column.pos);
- //w.add(DictTabInfo::AttributeType, DictTabInfo::UnSignedType);
- //w.add(DictTabInfo::AttributeSize, DictTabInfo::a32Bit);
- //w.add(DictTabInfo::AttributeArraySize, 1);
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)column.keyFlag);
//w.add(DictTabInfo::AttributeStorage, (Uint32)DictTabInfo::MainMemory);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)column.nullable);
- // ext type overrides
w.add(DictTabInfo::AttributeExtType, (Uint32)column.type);
w.add(DictTabInfo::AttributeExtLength, (Uint32)column.length);
w.add(DictTabInfo::AttributeEnd, (Uint32)true);
@@ -2044,7 +2040,7 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
}
}
- signal->theData[0] = EventReport::NDBStopStarted;
+ signal->theData[0] = NDB_LE_NDBStopStarted;
signal->theData[1] = StopReq::getSystemStop(c_stopRec.stopReq.requestInfo) ? 1 : 0;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -2133,7 +2129,7 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){
cntr.updateNodeState(signal, newState);
- signal->theData[0] = EventReport::NDBStopAborted;
+ signal->theData[0] = NDB_LE_NDBStopAborted;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
return false;
@@ -2411,7 +2407,7 @@ Ndbcntr::execFSREMOVECONF(Signal* signal){
}
void Ndbcntr::Missra::execSTART_ORD(Signal* signal){
- signal->theData[0] = EventReport::NDBStartStarted;
+ signal->theData[0] = NDB_LE_NDBStartStarted;
signal->theData[1] = NDB_VERSION;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -2541,14 +2537,14 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){
* At least one wanted this start phase, report it
*/
jam();
- signal->theData[0] = EventReport::StartPhaseCompleted;
+ signal->theData[0] = NDB_LE_StartPhaseCompleted;
signal->theData[1] = currentStartPhase;
signal->theData[2] = cntr.ctypeOfStart;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
}
}
- signal->theData[0] = EventReport::NDBStartCompleted;
+ signal->theData[0] = NDB_LE_NDBStartCompleted;
signal->theData[1] = NDB_VERSION;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index c0ffa722f1c..45073b63a5d 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -96,6 +96,7 @@ AsyncFile::AsyncFile() :
theReportTo(0),
theMemoryChannelPtr(NULL)
{
+ m_current_request= m_last_request= 0;
}
void
@@ -177,6 +178,7 @@ AsyncFile::run()
endReq();
return;
}//if
+ m_current_request= request;
switch (request->action) {
case Request:: open:
openReq(request);
@@ -226,6 +228,8 @@ AsyncFile::run()
abort();
break;
}//switch
+ m_last_request= request;
+ m_current_request= 0;
// No need to signal as ndbfs only uses tryRead
theReportTo->writeChannelNoSignal(request);
@@ -1033,3 +1037,60 @@ void printErrorAndFlags(Uint32 used_flags) {
}
#endif
+
+NdbOut&
+operator<<(NdbOut& out, const Request& req)
+{
+ out << "[ Request: file: " << hex << req.file
+ << " userRef: " << hex << req.theUserReference
+ << " userData: " << dec << req.theUserPointer
+ << " theFilePointer: " << req.theFilePointer
+ << " action: ";
+ switch(req.action){
+ case Request::open:
+ out << "open";
+ break;
+ case Request::close:
+ out << "close";
+ break;
+ case Request::closeRemove:
+ out << "closeRemove";
+ break;
+ case Request::read: // Allways leave readv directly after
+ out << "read";
+ break;
+ case Request::readv:
+ out << "readv";
+ break;
+ case Request::write:// Allways leave writev directly after
+ out << "write";
+ break;
+ case Request::writev:
+ out << "writev";
+ break;
+ case Request::writeSync:// Allways leave writevSync directly after
+ out << "writeSync";
+ break;
+ // writeSync because SimblockAsyncFileSystem depends on it
+ case Request::writevSync:
+ out << "writevSync";
+ break;
+ case Request::sync:
+ out << "sync";
+ break;
+ case Request::end:
+ out << "end";
+ break;
+ case Request::append:
+ out << "append";
+ break;
+ case Request::rmrf:
+ out << "rmrf";
+ break;
+ default:
+ out << (Uint32)req.action;
+ break;
+ }
+ out << " ]";
+ return out;
+}
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
index 2176c93c5d5..997bf40fe2a 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
@@ -160,6 +160,7 @@ public:
Uint32 theTrace;
};
+NdbOut& operator <<(NdbOut&, const Request&);
inline
void
@@ -173,6 +174,7 @@ Request::set(BlockReference userReference,
class AsyncFile
{
+ friend class Ndbfs;
public:
AsyncFile();
~AsyncFile();
@@ -188,6 +190,7 @@ public:
bool isOpen();
Filename theFileName;
+ Request *m_current_request, *m_last_request;
private:
void openReq(Request *request);
diff --git a/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp b/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp
index 349cccdbcb4..460ad3f614a 100644
--- a/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp
@@ -68,7 +68,7 @@ class CircularIndex
{
public:
inline CircularIndex( int start= 0,int size=256 );
- operator int ();
+ operator int () const;
CircularIndex& operator ++ ();
friend int full( const CircularIndex& write, const CircularIndex& read );
friend int empty( const CircularIndex& write, const CircularIndex& read );
@@ -77,7 +77,7 @@ private:
int theIndex;
};
-inline CircularIndex::operator int ()
+inline CircularIndex::operator int () const
{
return theIndex;
}
diff --git a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
index 6bb9684f3ca..9037bbad765 100644
--- a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
@@ -97,8 +97,20 @@ private:
NdbMutex* theMutexPtr;
NdbCondition* theConditionPtr;
+ template<class U>
+ friend NdbOut& operator<<(NdbOut& out, const MemoryChannel<U> & chn);
};
+template <class T>
+NdbOut& operator<<(NdbOut& out, const MemoryChannel<T> & chn)
+{
+ NdbMutex_Lock(chn.theMutexPtr);
+ out << "[ theSize: " << chn.theSize
+ << " theReadIndex: " << (int)chn.theReadIndex
+ << " theWriteIndex: " << (int)chn.theWriteIndex << " ]";
+ NdbMutex_Unlock(chn.theMutexPtr);
+ return out;
+}
template <class T> MemoryChannel<T>::MemoryChannel( int size):
theSize(size),
diff --git a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
index 6f848d7fe16..d6b19c8f872 100644
--- a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
@@ -1006,6 +1006,30 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal)
}
return;
}
+
+ if(signal->theData[0] == 404)
+ {
+ ndbrequire(signal->getLength() == 2);
+ Uint32 file= signal->theData[1];
+ AsyncFile* openFile = theOpenFiles.find(file);
+ ndbrequire(openFile);
+ ndbout_c("File: %s %p", openFile->theFileName.c_str(), openFile);
+ Request* curr = openFile->m_current_request;
+ Request* last = openFile->m_last_request;
+ if(curr)
+ ndbout << "Current request: " << *curr << endl;
+ if(last)
+ ndbout << "Last request: " << *last << endl;
+
+ ndbout << "theReportTo " << *openFile->theReportTo << endl;
+ ndbout << "theMemoryChannelPtr" << *openFile->theMemoryChannelPtr << endl;
+
+ ndbout << "All files: " << endl;
+ for (unsigned i = 0; i < theFiles.size(); i++){
+ AsyncFile* file = theFiles[i];
+ ndbout_c("%2d (0x%x): %s", i,file, file->isOpen()?"OPEN":"CLOSED");
+ }
+ }
}//Ndbfs::execDUMP_STATE_ORD()
@@ -1016,3 +1040,4 @@ template class Vector<AsyncFile*>;
template class Vector<OpenFiles::OpenFileItem>;
template class MemoryChannel<Request>;
template class Pool<Request>;
+template NdbOut& operator<<(NdbOut&, const MemoryChannel<Request>&);
diff --git a/ndb/src/kernel/blocks/qmgr/Qmgr.hpp b/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
index f6fafdae594..f84fae02fc4 100644
--- a/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
+++ b/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
@@ -118,8 +118,7 @@ public:
struct NodeRec {
UintR ndynamicId;
Phase phase;
- UintR alarmCount;
-
+
QmgrState sendPrepFailReqStatus;
QmgrState sendCommitFailReqStatus;
QmgrState sendPresToStatus;
@@ -304,7 +303,7 @@ private:
void stateArbitChoose(Signal* signal);
void stateArbitCrash(Signal* signal);
void computeArbitNdbMask(NodeBitmask& aMask);
- void reportArbitEvent(Signal* signal, EventReport::EventType type);
+ void reportArbitEvent(Signal* signal, Ndb_logevent_type type);
// Initialisation
void initData();
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp b/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
index 43d8f0971ed..4061455092d 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
@@ -35,6 +35,9 @@ void Qmgr::initData()
Uint32 hbDBAPI = 500;
setHbApiDelay(hbDBAPI);
+
+ c_connectedNodes.clear();
+ c_connectedNodes.set(getOwnNodeId());
}//Qmgr::initData()
void Qmgr::initRecords()
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index 3770edff947..7052e0da98a 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -67,7 +67,7 @@ void Qmgr::execCM_HEARTBEAT(Signal* signal)
jamEntry();
hbNodePtr.i = signal->theData[0];
ptrCheckGuard(hbNodePtr, MAX_NDB_NODES, nodeRec);
- hbNodePtr.p->alarmCount = 0;
+ setNodeInfo(hbNodePtr.i).m_heartbeat_cnt= 0;
return;
}//Qmgr::execCM_HEARTBEAT()
@@ -609,7 +609,7 @@ void Qmgr::execCM_REGCONF(Signal* signal)
// Send this as an EVENT REPORT to inform about hearing about
// other NDB node proclaiming to be president.
/*--------------------------------------------------------------*/
- signal->theData[0] = EventReport::CM_REGCONF;
+ signal->theData[0] = NDB_LE_CM_REGCONF;
signal->theData[1] = getOwnNodeId();
signal->theData[2] = cpresident;
signal->theData[3] = TdynamicId;
@@ -735,7 +735,7 @@ void Qmgr::execCM_REGREF(Signal* signal)
// Send this as an EVENT REPORT to inform about hearing about
// other NDB node proclaiming not to be president.
/*--------------------------------------------------------------*/
- signal->theData[0] = EventReport::CM_REGREF;
+ signal->theData[0] = NDB_LE_CM_REGREF;
signal->theData[1] = getOwnNodeId();
signal->theData[2] = TaddNodeno;
//-----------------------------------------
@@ -1041,7 +1041,7 @@ void Qmgr::execCM_ADD(Signal* signal)
jam();
ndbrequire(addNodePtr.p->phase == ZSTARTING);
addNodePtr.p->phase = ZRUNNING;
- addNodePtr.p->alarmCount = 0;
+ setNodeInfo(addNodePtr.i).m_heartbeat_cnt= 0;
c_clusterNodes.set(addNodePtr.i);
findNeighbours(signal);
@@ -1079,7 +1079,7 @@ Qmgr::joinedCluster(Signal* signal, NodeRecPtr nodePtr){
* NODES IN THE CLUSTER.
*/
nodePtr.p->phase = ZRUNNING;
- nodePtr.p->alarmCount = 0;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
findNeighbours(signal);
c_clusterNodes.set(nodePtr.i);
c_start.reset();
@@ -1300,11 +1300,11 @@ void Qmgr::findNeighbours(Signal* signal)
*---------------------------------------------------------------------*/
fnNodePtr.i = cneighbourl;
ptrCheckGuard(fnNodePtr, MAX_NDB_NODES, nodeRec);
- fnNodePtr.p->alarmCount = 0;
+ setNodeInfo(fnNodePtr.i).m_heartbeat_cnt= 0;
}//if
}//if
- signal->theData[0] = EventReport::FIND_NEIGHBOURS;
+ signal->theData[0] = NDB_LE_FIND_NEIGHBOURS;
signal->theData[1] = getOwnNodeId();
signal->theData[2] = cneighbourl;
signal->theData[3] = cneighbourh;
@@ -1348,8 +1348,8 @@ void Qmgr::initData(Signal* signal)
} else {
nodePtr.p->phase = ZAPI_INACTIVE;
}
-
- nodePtr.p->alarmCount = 0;
+
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
nodePtr.p->sendPrepFailReqStatus = Q_NOT_ACTIVE;
nodePtr.p->sendCommitFailReqStatus = Q_NOT_ACTIVE;
nodePtr.p->sendPresToStatus = Q_NOT_ACTIVE;
@@ -1530,7 +1530,7 @@ void Qmgr::sendHeartbeat(Signal* signal)
sendSignal(localNodePtr.p->blockRef, GSN_CM_HEARTBEAT, signal, 1, JBA);
#ifdef VM_TRACE
- signal->theData[0] = EventReport::SentHeartbeat;
+ signal->theData[0] = NDB_LE_SentHeartbeat;
signal->theData[1] = localNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
#endif
@@ -1551,24 +1551,24 @@ void Qmgr::checkHeartbeat(Signal* signal)
}//if
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- nodePtr.p->alarmCount ++;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt++;
ndbrequire(nodePtr.p->phase == ZRUNNING);
ndbrequire(getNodeInfo(nodePtr.i).m_type == NodeInfo::DB);
- if(nodePtr.p->alarmCount > 2){
- signal->theData[0] = EventReport::MissedHeartbeat;
+ if(getNodeInfo(nodePtr.i).m_heartbeat_cnt > 2){
+ signal->theData[0] = NDB_LE_MissedHeartbeat;
signal->theData[1] = nodePtr.i;
- signal->theData[2] = nodePtr.p->alarmCount - 1;
+ signal->theData[2] = getNodeInfo(nodePtr.i).m_heartbeat_cnt - 1;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
}
- if (nodePtr.p->alarmCount > 4) {
+ if (getNodeInfo(nodePtr.i).m_heartbeat_cnt > 4) {
jam();
/**----------------------------------------------------------------------
* OUR LEFT NEIGHBOUR HAVE KEPT QUIET FOR THREE CONSECUTIVE HEARTBEAT
* PERIODS. THUS WE DECLARE HIM DOWN.
*----------------------------------------------------------------------*/
- signal->theData[0] = EventReport::DeadDueToHeartbeat;
+ signal->theData[0] = NDB_LE_DeadDueToHeartbeat;
signal->theData[1] = nodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -1594,16 +1594,16 @@ void Qmgr::apiHbHandlingLab(Signal* signal)
if (TnodePtr.p->phase == ZAPI_ACTIVE){
jam();
- TnodePtr.p->alarmCount ++;
+ setNodeInfo(TnodePtr.i).m_heartbeat_cnt++;
- if(TnodePtr.p->alarmCount > 2){
- signal->theData[0] = EventReport::MissedHeartbeat;
+ if(getNodeInfo(TnodePtr.i).m_heartbeat_cnt > 2){
+ signal->theData[0] = NDB_LE_MissedHeartbeat;
signal->theData[1] = nodeId;
- signal->theData[2] = TnodePtr.p->alarmCount - 1;
+ signal->theData[2] = getNodeInfo(TnodePtr.i).m_heartbeat_cnt - 1;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
}
- if (TnodePtr.p->alarmCount > 4) {
+ if (getNodeInfo(TnodePtr.i).m_heartbeat_cnt > 4) {
jam();
/*------------------------------------------------------------------*/
/* THE API NODE HAS NOT SENT ANY HEARTBEAT FOR THREE SECONDS.
@@ -1612,7 +1612,7 @@ void Qmgr::apiHbHandlingLab(Signal* signal)
/*------------------------------------------------------------------*/
/* We call node_failed to release all connections for this api node */
/*------------------------------------------------------------------*/
- signal->theData[0] = EventReport::DeadDueToHeartbeat;
+ signal->theData[0] = NDB_LE_DeadDueToHeartbeat;
signal->theData[1] = nodeId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -1635,16 +1635,17 @@ void Qmgr::checkStartInterface(Signal* signal)
ptrAss(nodePtr, nodeRec);
if (nodePtr.p->phase == ZFAIL_CLOSING) {
jam();
- nodePtr.p->alarmCount = nodePtr.p->alarmCount + 1;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt++;
if (c_connectedNodes.get(nodePtr.i)){
jam();
/*-------------------------------------------------------------------*/
// We need to ensure that the connection is not restored until it has
// been disconnected for at least three seconds.
/*-------------------------------------------------------------------*/
- nodePtr.p->alarmCount = 0;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
}//if
- if ((nodePtr.p->alarmCount > 3) && (nodePtr.p->failState == NORMAL)) {
+ if ((getNodeInfo(nodePtr.i).m_heartbeat_cnt > 3)
+ && (nodePtr.p->failState == NORMAL)) {
/**------------------------------------------------------------------
* WE HAVE DISCONNECTED THREE SECONDS AGO. WE ARE NOW READY TO
* CONNECT AGAIN AND ACCEPT NEW REGISTRATIONS FROM THIS NODE.
@@ -1660,18 +1661,18 @@ void Qmgr::checkStartInterface(Signal* signal)
nodePtr.p->phase = ZINIT;
}//if
- nodePtr.p->alarmCount = 0;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
signal->theData[0] = 0;
signal->theData[1] = nodePtr.i;
sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 2, JBA);
} else {
- if(((nodePtr.p->alarmCount + 1) % 60) == 0){
+ if(((getNodeInfo(nodePtr.i).m_heartbeat_cnt + 1) % 60) == 0){
char buf[100];
BaseString::snprintf(buf, sizeof(buf),
"Failure handling of node %d has not completed in %d min."
" - state = %d",
nodePtr.i,
- (nodePtr.p->alarmCount + 1)/60,
+ (getNodeInfo(nodePtr.i).m_heartbeat_cnt + 1)/60,
nodePtr.p->failState);
warningEvent(buf);
}
@@ -1709,7 +1710,7 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo)
* WE ONLY NEED TO SET PARAMETERS TO ENABLE A NEW CONNECTION IN A FEW
* SECONDS.
*-------------------------------------------------------------------------*/
- failedNodePtr.p->alarmCount = 0;
+ setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
@@ -1862,7 +1863,7 @@ void Qmgr::node_failed(Signal* signal, Uint16 aFailedNode)
/*---------------------------------------------------------------------*/
failedNodePtr.p->failState = NORMAL;
failedNodePtr.p->phase = ZFAIL_CLOSING;
- failedNodePtr.p->alarmCount = 0;
+ setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
CloseComReqConf * const closeCom =
(CloseComReqConf *)&signal->theData[0];
@@ -1956,8 +1957,8 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
}
setNodeInfo(apiNodePtr.i).m_version = version;
-
- apiNodePtr.p->alarmCount = 0;
+
+ setNodeInfo(apiNodePtr.i).m_heartbeat_cnt= 0;
ApiRegConf * const apiRegConf = (ApiRegConf *)&signal->theData[0];
apiRegConf->qmgrRef = reference();
@@ -2475,7 +2476,7 @@ void Qmgr::execCOMMIT_FAILREQ(Signal* signal)
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
nodePtr.p->phase = ZFAIL_CLOSING;
nodePtr.p->failState = WAITING_FOR_NDB_FAILCONF;
- nodePtr.p->alarmCount = 0;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
c_clusterNodes.clear(nodePtr.i);
}//for
/*----------------------------------------------------------------------*/
@@ -2733,7 +2734,7 @@ void Qmgr::failReport(Signal* signal,
failedNodePtr.p->sendPrepFailReqStatus = Q_NOT_ACTIVE;
failedNodePtr.p->sendCommitFailReqStatus = Q_NOT_ACTIVE;
failedNodePtr.p->sendPresToStatus = Q_NOT_ACTIVE;
- failedNodePtr.p->alarmCount = 0;
+ setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
if (aSendFailRep == ZTRUE) {
jam();
if (failedNodePtr.i != getOwnNodeId()) {
@@ -3057,7 +3058,7 @@ Qmgr::handleArbitApiFail(Signal* signal, Uint16 nodeId)
jam();
return;
}
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
arbitRec.node = 0;
switch (arbitRec.state) {
case ARBIT_NULL: // should not happen
@@ -3228,7 +3229,7 @@ Qmgr::handleArbitCheck(Signal* signal)
arbitRec.newstate = true;
break;
}
- reportArbitEvent(signal, EventReport::ArbitResult);
+ reportArbitEvent(signal, NDB_LE_ArbitResult);
switch (arbitRec.state) {
default:
jam();
@@ -3255,7 +3256,7 @@ Qmgr::startArbitThread(Signal* signal)
jam();
ndbrequire(cpresident == getOwnNodeId());
arbitRec.code = ArbitCode::ThreadStart;
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
signal->theData[1] = ++arbitRec.thread;
runArbitThread(signal);
}
@@ -3499,7 +3500,7 @@ Qmgr::execARBIT_PREPREQ(Signal* signal)
arbitRec.node = sd->node;
arbitRec.ticket = sd->ticket;
arbitRec.code = sd->code;
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
arbitRec.state = ARBIT_RUN;
arbitRec.newstate = true;
if (sd->code == ArbitCode::PrepAtrun) {
@@ -3586,7 +3587,7 @@ Qmgr::stateArbitStart(Signal* signal)
}
if (arbitRec.recvCount) {
jam();
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
if (arbitRec.code == ArbitCode::ApiStart) {
jam();
arbitRec.state = ARBIT_RUN;
@@ -3600,7 +3601,7 @@ Qmgr::stateArbitStart(Signal* signal)
if (arbitRec.getTimediff() > getArbitTimeout()) {
jam();
arbitRec.code = ArbitCode::ErrTimeout;
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
arbitRec.state = ARBIT_INIT;
arbitRec.newstate = true;
return;
@@ -3707,7 +3708,7 @@ Qmgr::stateArbitChoose(Signal* signal)
}
if (arbitRec.recvCount) {
jam();
- reportArbitEvent(signal, EventReport::ArbitResult);
+ reportArbitEvent(signal, NDB_LE_ArbitResult);
if (arbitRec.code == ArbitCode::WinChoose) {
jam();
sendCommitFailReq(signal); // start commit of failed nodes
@@ -3723,7 +3724,7 @@ Qmgr::stateArbitChoose(Signal* signal)
if (arbitRec.getTimediff() > getArbitTimeout()) {
jam();
arbitRec.code = ArbitCode::ErrTimeout;
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
arbitRec.state = ARBIT_CRASH;
arbitRec.newstate = true;
stateArbitCrash(signal); // do it at once
@@ -3824,7 +3825,7 @@ Qmgr::computeArbitNdbMask(NodeBitmask& aMask)
* where sender (word 0) is event type.
*/
void
-Qmgr::reportArbitEvent(Signal* signal, EventReport::EventType type)
+Qmgr::reportArbitEvent(Signal* signal, Ndb_logevent_type type)
{
ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
sd->sender = type;
diff --git a/ndb/src/kernel/blocks/suma/Suma.cpp b/ndb/src/kernel/blocks/suma/Suma.cpp
index 84a59f440d9..c4225ad2a4c 100644
--- a/ndb/src/kernel/blocks/suma/Suma.cpp
+++ b/ndb/src/kernel/blocks/suma/Suma.cpp
@@ -50,6 +50,17 @@
//#define EVENT_DEBUG
//#define EVENT_PH3_DEBUG
//#define EVENT_DEBUG2
+#if 0
+#undef DBUG_ENTER
+#undef DBUG_PRINT
+#undef DBUG_RETURN
+#undef DBUG_VOID_RETURN
+
+#define DBUG_ENTER(a) {ndbout_c("%s:%d >%s", __FILE__, __LINE__, a);}
+#define DBUG_PRINT(a,b) {ndbout << __FILE__ << ":" << __LINE__ << " " << a << ": "; ndbout_c b ;}
+#define DBUG_RETURN(a) { ndbout_c("%s:%d <", __FILE__, __LINE__); return(a); }
+#define DBUG_VOID_RETURN { ndbout_c("%s:%d <", __FILE__, __LINE__); return; }
+#endif
/**
* @todo:
@@ -112,15 +123,12 @@ Suma::getNodeGroupMembers(Signal* signal) {
void
Suma::execSTTOR(Signal* signal) {
jamEntry();
-
+
+ DBUG_ENTER("Suma::execSTTOR");
const Uint32 startphase = signal->theData[1];
const Uint32 typeOfStart = signal->theData[7];
-#ifdef NODEFAIL_DEBUG
- ndbout_c ("SUMA::execSTTOR startphase = %u, typeOfStart = %u",
- startphase, typeOfStart);
-
-#endif
+ DBUG_PRINT("info",("startphase = %u, typeOfStart = %u", startphase, typeOfStart));
if(startphase == 1){
jam();
@@ -155,7 +163,7 @@ Suma::execSTTOR(Signal* signal) {
g_subPtrI = subPtr.i;
// sendSTTORRY(signal);
#endif
- return;
+ DBUG_VOID_RETURN;
}
if(startphase == 5) {
@@ -178,9 +186,7 @@ Suma::execSTTOR(Signal* signal) {
for( int i = 0; i < NO_OF_BUCKETS; i++) {
if (getResponsibleSumaNodeId(i) == refToNode(reference())) {
// I'm running this bucket
-#ifdef EVENT_DEBUG
- ndbout_c("bucket %u set to true", i);
-#endif
+ DBUG_PRINT("info",("bucket %u set to true", i));
c_buckets[i].active = true;
}
}
@@ -190,32 +196,31 @@ Suma::execSTTOR(Signal* signal) {
c_masterNodeId == getOwnNodeId()) {
jam();
createSequence(signal);
- return;
+ DBUG_VOID_RETURN;
}//if
}//if
sendSTTORRY(signal);
- return;
+ DBUG_VOID_RETURN;
}
void
Suma::createSequence(Signal* signal)
{
jam();
+ DBUG_ENTER("Suma::createSequence");
UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtrSend();
req->senderData = RNIL;
req->sequenceId = SUMA_SEQUENCE;
req->requestType = UtilSequenceReq::Create;
-#ifdef DEBUG_SUMA_SEQUENCE
- ndbout_c("SUMA: Create sequence");
-#endif
sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
signal, UtilSequenceReq::SignalLength, JBB);
// execUTIL_SEQUENCE_CONF will call createSequenceReply()
+ DBUG_VOID_RETURN;
}
void
@@ -338,6 +343,7 @@ SumaParticipant::execCONTINUEB(Signal* signal)
void Suma::execAPI_FAILREQ(Signal* signal)
{
jamEntry();
+ DBUG_ENTER("Suma::execAPI_FAILREQ");
Uint32 failedApiNode = signal->theData[0];
//BlockReference retRef = signal->theData[1];
@@ -348,11 +354,13 @@ void Suma::execAPI_FAILREQ(Signal* signal)
jam();
c_failedApiNodes.clear(failedApiNode);
}
+ DBUG_VOID_RETURN;
}//execAPI_FAILREQ()
bool
SumaParticipant::removeSubscribersOnNode(Signal *signal, Uint32 nodeId)
{
+ DBUG_ENTER("SumaParticipant::removeSubscribersOnNode");
bool found = false;
SubscriberPtr i_subbPtr;
@@ -372,20 +380,15 @@ SumaParticipant::removeSubscribersOnNode(Signal *signal, Uint32 nodeId)
jam();
sendSubStopReq(signal);
}
- return found;
+ DBUG_RETURN(found);
}
void
-SumaParticipant::sendSubStopReq(Signal *signal){
+SumaParticipant::sendSubStopReq(Signal *signal, bool unlock){
+ DBUG_ENTER("SumaParticipant::sendSubStopReq");
static bool remove_lock = false;
jam();
- if(remove_lock) {
- jam();
- return;
- }
- remove_lock = true;
-
SubscriberPtr subbPtr;
c_removeDataSubscribers.first(subbPtr);
if (subbPtr.isNull()){
@@ -398,9 +401,15 @@ SumaParticipant::sendSubStopReq(Signal *signal){
c_failedApiNodes.clear();
remove_lock = false;
- return;
+ DBUG_VOID_RETURN;
}
+ if(remove_lock && !unlock) {
+ jam();
+ DBUG_VOID_RETURN;
+ }
+ remove_lock = true;
+
SubscriptionPtr subPtr;
c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
@@ -414,11 +423,13 @@ SumaParticipant::sendSubStopReq(Signal *signal){
req->part = SubscriptionData::TableData;
sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
+ DBUG_VOID_RETURN;
}
void
SumaParticipant::execSUB_STOP_CONF(Signal* signal){
jamEntry();
+ DBUG_ENTER("SumaParticipant::execSUB_STOP_CONF");
SubStopConf * const conf = (SubStopConf*)signal->getDataPtr();
@@ -444,12 +455,15 @@ SumaParticipant::execSUB_STOP_CONF(Signal* signal){
}
}
- sendSubStopReq(signal);
+ sendSubStopReq(signal,true);
+ DBUG_VOID_RETURN;
}
void
SumaParticipant::execSUB_STOP_REF(Signal* signal){
jamEntry();
+ DBUG_ENTER("SumaParticipant::execSUB_STOP_REF");
+
SubStopRef * const ref = (SubStopRef*)signal->getDataPtr();
Uint32 subscriptionId = ref->subscriptionId;
@@ -471,11 +485,14 @@ SumaParticipant::execSUB_STOP_REF(Signal* signal){
req->part = part;
sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
+
+ DBUG_VOID_RETURN;
}
void
Suma::execNODE_FAILREP(Signal* signal){
jamEntry();
+ DBUG_ENTER("Suma::execNODE_FAILREP");
NodeFailRep * const rep = (NodeFailRep*)signal->getDataPtr();
@@ -541,6 +558,7 @@ Suma::execNODE_FAILREP(Signal* signal){
c_aliveNodes.clear(nodePtr.p->nodeId); // this has to be done after the loop above
}
}
+ DBUG_VOID_RETURN;
}
void
@@ -610,6 +628,19 @@ Suma::execSIGNAL_DROPPED_REP(Signal* signal){
*
*/
+static unsigned
+count_subscribers(const DLList<SumaParticipant::Subscriber> &subs)
+{
+ unsigned n= 0;
+ SumaParticipant::SubscriberPtr i_subbPtr;
+ subs.first(i_subbPtr);
+ while(!i_subbPtr.isNull()){
+ n++;
+ subs.next(i_subbPtr);
+ }
+ return n;
+}
+
void
Suma::execDUMP_STATE_ORD(Signal* signal){
jamEntry();
@@ -664,6 +695,15 @@ Suma::execDUMP_STATE_ORD(Signal* signal){
infoEvent("Suma: c_dataBufferPool size: %d free: %d",
c_dataBufferPool.getSize(),
c_dataBufferPool.getNoOfFree());
+
+ infoEvent("Suma: c_metaSubscribers count: %d",
+ count_subscribers(c_metaSubscribers));
+ infoEvent("Suma: c_dataSubscribers count: %d",
+ count_subscribers(c_dataSubscribers));
+ infoEvent("Suma: c_prepDataSubscribers count: %d",
+ count_subscribers(c_prepDataSubscribers));
+ infoEvent("Suma: c_removeDataSubscribers count: %d",
+ count_subscribers(c_removeDataSubscribers));
}
}
@@ -812,16 +852,14 @@ Suma::execUTIL_SEQUENCE_CONF(Signal* signal)
{
jamEntry();
+ DBUG_ENTER("Suma::execUTIL_SEQUENCE_CONF");
CRASH_INSERTION(13002);
UtilSequenceConf * conf = (UtilSequenceConf*)signal->getDataPtr();
-#ifdef DEBUG_SUMA_SEQUENCE
- ndbout_c("SUMA: Create sequence conf");
-#endif
if(conf->requestType == UtilSequenceReq::Create) {
jam();
createSequenceReply(signal, conf, NULL);
- return;
+ DBUG_VOID_RETURN;
}
Uint64 subId;
@@ -841,18 +879,21 @@ Suma::execUTIL_SEQUENCE_CONF(Signal* signal)
CreateSubscriptionIdConf::SignalLength, JBB);
c_subscriberPool.release(subbPtr);
+
+ DBUG_VOID_RETURN;
}
void
Suma::execUTIL_SEQUENCE_REF(Signal* signal)
{
jamEntry();
+ DBUG_ENTER("Suma::execUTIL_SEQUENCE_REF");
UtilSequenceRef * ref = (UtilSequenceRef*)signal->getDataPtr();
if(ref->requestType == UtilSequenceReq::Create) {
jam();
createSequenceReply(signal, NULL, ref);
- return;
+ DBUG_VOID_RETURN;
}
Uint32 subData = ref->senderData;
@@ -861,7 +902,7 @@ Suma::execUTIL_SEQUENCE_REF(Signal* signal)
c_subscriberPool.getPtr(subbPtr,subData);
sendSubIdRef(signal, GrepError::SEQUENCE_ERROR);
c_subscriberPool.release(subbPtr);
- return;
+ DBUG_VOID_RETURN;
}//execUTIL_SEQUENCE_REF()
@@ -1429,7 +1470,7 @@ SumaParticipant::execDIGETPRIMCONF(Signal* signal){
void
SumaParticipant::execCREATE_TRIG_CONF(Signal* signal){
jamEntry();
-
+ DBUG_ENTER("SumaParticipant::execCREATE_TRIG_CONF");
CRASH_INSERTION(13009);
CreateTrigConf * const conf = (CreateTrigConf*)signal->getDataPtr();
@@ -1442,6 +1483,7 @@ SumaParticipant::execCREATE_TRIG_CONF(Signal* signal){
* dodido
* @todo: I (Johan) dont know what to do here. Jonas, what do you mean?
*/
+ DBUG_VOID_RETURN;
}
void
@@ -1453,7 +1495,7 @@ SumaParticipant::execCREATE_TRIG_REF(Signal* signal){
void
SumaParticipant::execDROP_TRIG_CONF(Signal* signal){
jamEntry();
-
+ DBUG_ENTER("SumaParticipant::execDROP_TRIG_CONF");
CRASH_INSERTION(13010);
DropTrigConf * const conf = (DropTrigConf*)signal->getDataPtr();
@@ -1461,17 +1503,19 @@ SumaParticipant::execDROP_TRIG_CONF(Signal* signal){
const Uint32 senderData = conf->getConnectionPtr();
SyncRecord* tmp = c_syncPool.getPtr(senderData);
tmp->runDROP_TRIG_CONF(signal);
+ DBUG_VOID_RETURN;
}
void
SumaParticipant::execDROP_TRIG_REF(Signal* signal){
jamEntry();
-
+ DBUG_ENTER("SumaParticipant::execDROP_TRIG_CONF");
DropTrigRef * const ref = (DropTrigRef*)signal->getDataPtr();
const Uint32 senderData = ref->getConnectionPtr();
SyncRecord* tmp = c_syncPool.getPtr(senderData);
tmp->runDROP_TRIG_CONF(signal);
+ DBUG_VOID_RETURN;
}
/*************************************************************************
@@ -2055,9 +2099,7 @@ SumaParticipant::execSCAN_HBREP(Signal* signal){
void
SumaParticipant::execSUB_START_REQ(Signal* signal){
jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUB_START_REQ");
-#endif
+ DBUG_ENTER("SumaParticipant::execSUB_START_REQ");
CRASH_INSERTION(13013);
@@ -2067,7 +2109,7 @@ SumaParticipant::execSUB_START_REQ(Signal* signal){
if (RtoI(signal->getSendersBlockRef(), false) == RNIL) {
jam();
sendSubStartRef(signal, /** Error Code */ 0, true);
- return;
+ DBUG_VOID_RETURN;
}
// only allow other Suma's in the nodegroup to come through for restart purposes
}
@@ -2088,7 +2130,7 @@ SumaParticipant::execSUB_START_REQ(Signal* signal){
if(!c_subscriptions.find(subPtr, key)){
jam();
sendSubStartRef(signal, /** Error Code */ 0);
- return;
+ DBUG_VOID_RETURN;
}
Ptr<SyncRecord> syncPtr;
@@ -2099,7 +2141,7 @@ SumaParticipant::execSUB_START_REQ(Signal* signal){
ndbout_c("Locked");
#endif
sendSubStartRef(signal, /** Error Code */ 0, true);
- return;
+ DBUG_VOID_RETURN;
}
syncPtr.p->m_locked = true;
@@ -2108,7 +2150,7 @@ SumaParticipant::execSUB_START_REQ(Signal* signal){
jam();
syncPtr.p->m_locked = false;
sendSubStartRef(signal, /** Error Code */ 0);
- return;
+ DBUG_VOID_RETURN;
}
Uint32 type = subPtr.p->m_subscriptionType;
@@ -2176,6 +2218,7 @@ SumaParticipant::execSUB_START_REQ(Signal* signal){
break;
}
ndbrequire(ok);
+ DBUG_VOID_RETURN;
}
void
@@ -2800,7 +2843,7 @@ SumaParticipant::decideWhoToSend(Uint32 nBucket, Uint32 gci){
void
SumaParticipant::execFIRE_TRIG_ORD(Signal* signal){
jamEntry();
-
+ DBUG_ENTER("SumaParticipant::execFIRE_TRIG_ORD");
CRASH_INSERTION(13016);
FireTrigOrd* const trg = (FireTrigOrd*)signal->getDataPtr();
const Uint32 trigId = trg->getTriggerId();
@@ -2928,6 +2971,7 @@ SumaParticipant::execFIRE_TRIG_ORD(Signal* signal){
}
}
#endif
+ DBUG_PRINT("info",("GSN_SUB_TABLE_DATA to node %d", refToNode(ref)));
sendSignal(ref, GSN_SUB_TABLE_DATA, signal,
SubTableData::SignalLength, JBB, ptr, nptr);
data->logType = tmp;
@@ -2961,6 +3005,8 @@ SumaParticipant::execFIRE_TRIG_ORD(Signal* signal){
*/
f_bufferLock = 0;
b_bufferLock = 0;
+
+ DBUG_VOID_RETURN;
}
void
@@ -3209,6 +3255,7 @@ bool SumaParticipant::FailoverBuffer::nodeFailRep()
void
SumaParticipant::execSUB_STOP_REQ(Signal* signal){
jamEntry();
+ DBUG_ENTER("SumaParticipant::execSUB_STOP_REQ");
CRASH_INSERTION(13019);
@@ -3238,7 +3285,7 @@ SumaParticipant::execSUB_STOP_REQ(Signal* signal){
SubStopConf::SignalLength, JBB);
removeSubscribersOnNode(signal, refToNode(subscriberRef));
- return;
+ DBUG_VOID_RETURN;
}
if(!c_subscriptions.find(subPtr, key)){
@@ -3264,7 +3311,7 @@ SumaParticipant::execSUB_STOP_REQ(Signal* signal){
for (;!subbPtr.isNull(); c_dataSubscribers.next(subbPtr)){
jam();
if (subbPtr.p->m_subPtrI == subPtr.i &&
- subbPtr.p->m_subscriberRef == subscriberRef &&
+ refToNode(subbPtr.p->m_subscriberRef) == refToNode(subscriberRef) &&
subbPtr.p->m_subscriberData == subscriberData){
// ndbout_c("STOP_REQ: before c_dataSubscribers.release");
jam();
@@ -3279,7 +3326,7 @@ SumaParticipant::execSUB_STOP_REQ(Signal* signal){
if (!found) {
jam();
sendSubStopRef(signal, GrepError::SUBSCRIBER_NOT_FOUND);
- return;
+ DBUG_VOID_RETURN;
}
}
@@ -3292,11 +3339,12 @@ SumaParticipant::execSUB_STOP_REQ(Signal* signal){
if (syncPtr.p->m_locked) {
jam();
sendSubStopRef(signal, /** Error Code */ 0, true);
- return;
+ DBUG_VOID_RETURN;
}
syncPtr.p->m_locked = true;
syncPtr.p->startDropTrigger(signal);
+ DBUG_VOID_RETURN;
}
void
@@ -3492,6 +3540,8 @@ SumaParticipant::sendSubRemoveRef(Signal* signal, const SubRemoveReq& req,
jam();
SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend();
ref->senderRef = reference();
+ ref->subscriptionId = req.subscriptionId;
+ ref->subscriptionKey = req.subscriptionKey;
ref->senderData = req.senderData;
ref->err = errCode;
if (temporary)
diff --git a/ndb/src/kernel/blocks/suma/Suma.hpp b/ndb/src/kernel/blocks/suma/Suma.hpp
index 08987fa9420..65869f44423 100644
--- a/ndb/src/kernel/blocks/suma/Suma.hpp
+++ b/ndb/src/kernel/blocks/suma/Suma.hpp
@@ -376,7 +376,7 @@ public:
void sendSubStartComplete(Signal*, SubscriberPtr, Uint32,
SubscriptionData::Part);
void sendSubStopComplete(Signal*, SubscriberPtr);
- void sendSubStopReq(Signal* signal);
+ void sendSubStopReq(Signal* signal, bool unlock= false);
void completeSubRemoveReq(Signal* signal, SubscriptionPtr subPtr);
diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp
index d9953b920d2..bec9c8b28f4 100644
--- a/ndb/src/kernel/main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -19,6 +19,7 @@
#include <ndb_version.h>
#include "Configuration.hpp"
+#include <ConfigRetriever.hpp>
#include <TransporterRegistry.hpp>
#include "vm/SimBlockList.hpp"
@@ -36,6 +37,8 @@
#include <NdbAutoPtr.hpp>
+#include <mgmapi_debug.h>
+
#if defined NDB_SOLARIS // ok
#include <sys/processor.h> // For system informatio
#endif
@@ -96,7 +99,7 @@ int main(int argc, char** argv)
return 1;
}
}
-
+
#ifndef NDB_WIN32
signal(SIGUSR1, handler_sigusr1);
@@ -106,6 +109,12 @@ int main(int argc, char** argv)
*/
catchsigs(true);
+ /**
+ * We no longer need the mgm connection in this process
+ * (as we are the angel, not ndb)
+ */
+ theConfig->closeConfiguration();
+
int status = 0;
while(waitpid(child, &status, 0) != child);
if(WIFEXITED(status)){
@@ -214,6 +223,13 @@ int main(int argc, char** argv)
exit(-1);
}
+ // Re-use the mgm handle as a transporter
+ if(!globalTransporterRegistry.connect_client(
+ theConfig->get_config_retriever()->get_mgmHandlePtr()))
+ ERROR_SET(fatal, ERR_INVALID_CONFIG,
+ "Connection to mgmd terminated before setup was complete",
+ "StopOnError missing");
+
if (!globalTransporterRegistry.start_clients()){
ndbout_c("globalTransporterRegistry.start_clients() failed");
exit(-1);
diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp
index de78a4e927c..650d914035f 100644
--- a/ndb/src/kernel/vm/Configuration.cpp
+++ b/ndb/src/kernel/vm/Configuration.cpp
@@ -88,13 +88,6 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt,
- argument ? argument : "d:t:O,/tmp/ndbd.trace");
-}
bool
Configuration::init(int argc, char** argv)
@@ -103,7 +96,11 @@ Configuration::init(int argc, char** argv)
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndbd.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
exit(ho_error);
if (_no_daemon) {
@@ -156,6 +153,7 @@ Configuration::Configuration()
_daemonMode = false;
m_config_retriever= 0;
m_clusterConfig= 0;
+ m_clusterConfigIter= 0;
}
Configuration::~Configuration(){
@@ -191,7 +189,6 @@ Configuration::fetch_configuration(){
}
m_mgmd_port= 0;
- m_mgmd_host= 0;
m_config_retriever= new ConfigRetriever(getConnectString(),
NDB_VERSION, NODE_TYPE_DB);
@@ -213,7 +210,7 @@ Configuration::fetch_configuration(){
}
m_mgmd_port= m_config_retriever->get_mgmd_port();
- m_mgmd_host= m_config_retriever->get_mgmd_host();
+ m_mgmd_host.assign(m_config_retriever->get_mgmd_host());
ConfigRetriever &cr= *m_config_retriever;
@@ -372,6 +369,8 @@ Configuration::setupConfiguration(){
ConfigValues* cf = ConfigValuesFactory::extractCurrentSection(iter.m_config);
+ if(m_clusterConfigIter)
+ ndb_mgm_destroy_iterator(m_clusterConfigIter);
m_clusterConfigIter = ndb_mgm_create_configuration_iterator
(p, CFG_SECTION_NODE);
diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp
index acf0e163a84..6ca6d9a1f17 100644
--- a/ndb/src/kernel/vm/Configuration.hpp
+++ b/ndb/src/kernel/vm/Configuration.hpp
@@ -17,6 +17,7 @@
#ifndef Configuration_H
#define Configuration_H
+#include <util/BaseString.hpp>
#include <mgmapi.h>
#include <ndb_types.h>
@@ -67,7 +68,8 @@ public:
const ndb_mgm_configuration_iterator * getOwnConfigIterator() const;
Uint32 get_mgmd_port() const {return m_mgmd_port;};
- const char *get_mgmd_host() const {return m_mgmd_host;};
+ const char *get_mgmd_host() const {return m_mgmd_host.c_str();};
+ ConfigRetriever* get_config_retriever() { return m_config_retriever; };
class LogLevel * m_logLevel;
private:
@@ -98,7 +100,7 @@ private:
bool _initialStart;
char * _connectString;
Uint32 m_mgmd_port;
- const char *m_mgmd_host;
+ BaseString m_mgmd_host;
bool _daemonMode;
void calcSizeAlt(class ConfigValues * );
diff --git a/ndb/src/kernel/vm/FastScheduler.cpp b/ndb/src/kernel/vm/FastScheduler.cpp
index d0b7af27463..a2d806571fe 100644
--- a/ndb/src/kernel/vm/FastScheduler.cpp
+++ b/ndb/src/kernel/vm/FastScheduler.cpp
@@ -487,7 +487,7 @@ FastScheduler::reportDoJobStatistics(Uint32 tMeanLoopCount) {
Signal signal;
memset(&signal.header, 0, sizeof(signal.header));
- signal.theData[0] = EventReport::JobStatistic;
+ signal.theData[0] = NDB_LE_JobStatistic;
signal.theData[1] = tMeanLoopCount;
memset(&signal.header, 0, sizeof(SignalHeader));
diff --git a/ndb/include/ndbapi/NdbCursorOperation.hpp b/ndb/src/kernel/vm/KeyDescriptor.hpp
index e7eeb54ba2d..456d64ce1d8 100644
--- a/ndb/include/ndbapi/NdbCursorOperation.hpp
+++ b/ndb/src/kernel/vm/KeyDescriptor.hpp
@@ -14,7 +14,28 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifndef NdbCursorOperation_H
-#define NdbCursorOperation_H
+#ifndef KEY_DESCRIPTOR_HPP
+#define KEY_DESCRIPTOR_HPP
+
+#include <ndb_types.h>
+#include <ndb_limits.h>
+#include "CArray.hpp"
+
+struct KeyDescriptor
+{
+ KeyDescriptor () { noOfKeyAttr = hasCharAttr = noOfDistrKeys = 0; }
+
+ Uint8 noOfKeyAttr;
+ Uint8 hasCharAttr;
+ Uint8 noOfDistrKeys;
+ Uint8 unused;
+ struct KeyAttr
+ {
+ Uint32 attributeDescriptor;
+ CHARSET_INFO* charsetInfo;
+ } keyAttr[MAX_ATTRIBUTES_IN_INDEX];
+};
+
+extern CArray<KeyDescriptor> g_key_descriptor_pool;
#endif
diff --git a/ndb/src/kernel/vm/MetaData.hpp b/ndb/src/kernel/vm/MetaData.hpp
index 11e262664c1..1000114a421 100644
--- a/ndb/src/kernel/vm/MetaData.hpp
+++ b/ndb/src/kernel/vm/MetaData.hpp
@@ -86,15 +86,9 @@ public:
/* Primary table of index otherwise RNIL */
Uint32 primaryTableId;
- /* Type of storage (memory/disk, not used) */
- DictTabInfo::StorageType storageType;
-
/* Type of fragmentation (small/medium/large) */
DictTabInfo::FragmentType fragmentType;
- /* Key type of fragmentation (pk/dist key/dist group) */
- DictTabInfo::FragmentKeyType fragmentKeyType;
-
/* Global checkpoint identity when table created */
Uint32 gciTableCreated;
@@ -166,7 +160,6 @@ public:
Uint32 attributeDescriptor;
/* Extended attributes */
- Uint32 extType;
Uint32 extPrecision;
Uint32 extScale;
Uint32 extLength;
diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp
index 9b52ac65331..57a4032e40b 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -743,7 +743,7 @@ SimulatedBlock::infoEvent(const char * msg, ...) const {
return;
Uint32 theData[25];
- theData[0] = EventReport::InfoEvent;
+ theData[0] = NDB_LE_InfoEvent;
char * buf = (char *)&(theData[1]);
va_list ap;
@@ -784,7 +784,7 @@ SimulatedBlock::warningEvent(const char * msg, ...) const {
return;
Uint32 theData[25];
- theData[0] = EventReport::WarningEvent;
+ theData[0] = NDB_LE_WarningEvent;
char * buf = (char *)&(theData[1]);
va_list ap;
@@ -1865,3 +1865,118 @@ SimulatedBlock::init_globals_list(void ** tmp, size_t cnt){
}
#endif
+
+#include "KeyDescriptor.hpp"
+
+Uint32
+SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
+ Uint32 *dst, Uint32 dstSize,
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const
+{
+ const KeyDescriptor * desc = g_key_descriptor_pool.getPtr(tab);
+ const Uint32 noOfKeyAttr = desc->noOfKeyAttr;
+
+ Uint32 i = 0;
+ Uint32 srcPos = 0;
+ Uint32 dstPos = 0;
+ while (i < noOfKeyAttr)
+ {
+ const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i];
+
+ Uint32 srcBytes =
+ AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor);
+ Uint32 srcWords = (srcBytes + 3) / 4;
+ Uint32 dstWords = ~0;
+ uchar* dstPtr = (uchar*)&dst[dstPos];
+ const uchar* srcPtr = (const uchar*)&src[srcPos];
+ CHARSET_INFO* cs = keyAttr.charsetInfo;
+
+ if (cs == NULL)
+ {
+ jam();
+ memcpy(dstPtr, srcPtr, srcWords << 2);
+ dstWords = srcWords;
+ }
+ else
+ {
+ jam();
+ Uint32 typeId =
+ AttributeDescriptor::getType(keyAttr.attributeDescriptor);
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ ndbrequire(ok);
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ /*
+ * Varchar is really Char. End spaces do not matter. To get
+ * same hash we blank-pad to maximum length via strnxfrm.
+ * TODO use MySQL charset-aware hash function instead
+ */
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ ndbrequire(n != -1);
+ while ((n & 3) != 0)
+ {
+ dstPtr[n++] = 0;
+ }
+ dstWords = (n >> 2);
+ }
+ dstPos += dstWords;
+ srcPos += srcWords;
+ keyPartLen[i++] = dstWords;
+ }
+
+ return dstPos;
+}
+
+Uint32
+SimulatedBlock::create_distr_key(Uint32 tableId,
+ Uint32 *data,
+ const Uint32
+ keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const
+{
+ const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tableId);
+ const Uint32 noOfKeyAttr = desc->noOfKeyAttr;
+ Uint32 noOfDistrKeys = desc->noOfDistrKeys;
+
+ Uint32 *src = data;
+ Uint32 *dst = data;
+ Uint32 i = 0;
+ Uint32 dstPos = 0;
+
+ if(keyPartLen)
+ {
+ while (i < noOfKeyAttr && noOfDistrKeys)
+ {
+ Uint32 attr = desc->keyAttr[i].attributeDescriptor;
+ Uint32 len = keyPartLen[i];
+ if(AttributeDescriptor::getDKey(attr))
+ {
+ noOfDistrKeys--;
+ memmove(dst+dstPos, src, len << 2);
+ dstPos += len;
+ }
+ src += len;
+ i++;
+ }
+ }
+ else
+ {
+ while (i < noOfKeyAttr && noOfDistrKeys)
+ {
+ Uint32 attr = desc->keyAttr[i].attributeDescriptor;
+ Uint32 len = AttributeDescriptor::getSizeInWords(attr);
+ if(AttributeDescriptor::getDKey(attr))
+ {
+ noOfDistrKeys--;
+ memmove(dst+dstPos, src, len << 2);
+ dstPos += len;
+ }
+ src += len;
+ i++;
+ }
+ }
+ return dstPos;
+}
diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp
index 81b4fe7413e..bba92ca7c31 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -20,11 +20,13 @@
#include <NdbTick.h>
#include <kernel_types.h>
#include <ndb_version.h>
+#include <ndb_limits.h>
#include "VMSignal.hpp"
#include <RefConvert.hpp>
#include <BlockNumbers.h>
#include <GlobalSignalNumbers.h>
+
#include "pc.hpp"
#include <NodeInfo.hpp>
#include <NodeState.hpp>
@@ -385,6 +387,24 @@ protected:
*/
const NodeInfo & getNodeInfo(NodeId nodeId) const;
NodeInfo & setNodeInfo(NodeId);
+
+ /**********************
+ * Xfrm stuff
+ */
+
+ /**
+ * @return length
+ */
+ Uint32 xfrm_key(Uint32 tab, const Uint32* src,
+ Uint32 *dst, Uint32 dstLen,
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const;
+
+ /**
+ *
+ */
+ Uint32 create_distr_key(Uint32 tableId,
+ Uint32 *data,
+ const Uint32 keyPaLen[MAX_ATTRIBUTES_IN_INDEX])const;
private:
NewVARIABLE* NewVarRef; /* New Base Address Table for block */
diff --git a/ndb/src/kernel/vm/SuperPool.cpp b/ndb/src/kernel/vm/SuperPool.cpp
new file mode 100644
index 00000000000..65e5dd99629
--- /dev/null
+++ b/ndb/src/kernel/vm/SuperPool.cpp
@@ -0,0 +1,442 @@
+/* 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 "SuperPool.hpp"
+
+// SuperPool
+
+SuperPool::SuperPool(Uint32 pageSize, Uint32 pageBits) :
+ m_pageSize(SP_ALIGN_SIZE(pageSize, SP_ALIGN)),
+ m_pageBits(pageBits),
+ m_memRoot(0),
+ m_pageEnt(0),
+ m_typeCheck(0),
+ m_typeSeq(0),
+ m_pageList(),
+ m_totalSize(0),
+ m_initSize(0),
+ m_incrSize(0),
+ m_maxSize(0)
+{
+ assert(5 <= pageBits <= 30);
+}
+
+bool
+SuperPool::init()
+{
+ return true;
+}
+
+SuperPool::~SuperPool()
+{
+}
+
+SuperPool::PageEnt::PageEnt() :
+ m_pageType(0),
+ m_freeRecI(RNIL),
+ m_useCount(0),
+ m_nextPageI(RNIL),
+ m_prevPageI(RNIL)
+{
+}
+
+SuperPool::PageList::PageList() :
+ m_headPageI(RNIL),
+ m_tailPageI(RNIL),
+ m_pageCount(0)
+{
+}
+
+SuperPool::PageList::PageList(PtrI pageI) :
+ m_headPageI(pageI),
+ m_tailPageI(pageI),
+ m_pageCount(1)
+{
+}
+
+SuperPool::RecInfo::RecInfo(Uint32 recType, Uint32 recSize) :
+ m_recType(recType),
+ m_recSize(recSize),
+ m_maxUseCount(0),
+ m_currPageI(RNIL),
+ m_currFreeRecI(RNIL),
+ m_currUseCount(0),
+ m_totalUseCount(0),
+ m_totalRecCount(0),
+ m_freeList(),
+ m_activeList(),
+ m_fullList()
+{
+}
+
+SuperPool::PtrI
+SuperPool::getPageI(void* pageP)
+{
+ const Uint32 pageSize = m_pageSize;
+ const Uint32 pageBits = m_pageBits;
+ const Uint32 recBits = 32 - pageBits;
+ void* const memRoot = m_memRoot;
+ assert(pageP == SP_ALIGN_PTR(pageP, memRoot, pageSize));
+ my_ptrdiff_t ipL = ((Uint8*)pageP - (Uint8*)memRoot) / pageSize;
+ Int32 ip = (Int32)ipL;
+ Int32 lim = 1 << (pageBits - 1);
+ assert(ip == ipL && -lim <= ip && ip < lim && ip != -1);
+ PtrI pageI = ip << recBits;
+ assert(pageP == getPageP(pageI));
+ return pageI;
+}
+
+void
+SuperPool::movePages(PageList& pl1, PageList& pl2)
+{
+ const Uint32 recBits = 32 - m_pageBits;
+ if (pl1.m_pageCount != 0) {
+ if (pl2.m_pageCount != 0) {
+ PtrI pageI1 = pl1.m_tailPageI;
+ PtrI pageI2 = pl2.m_headPageI;
+ PageEnt& pe1 = getPageEnt(pageI1);
+ PageEnt& pe2 = getPageEnt(pageI2);
+ pe1.m_nextPageI = pageI2;
+ pe2.m_prevPageI = pageI1;
+ pl1.m_pageCount += pl2.m_pageCount;
+ }
+ } else {
+ pl1 = pl2;
+ }
+ pl2.m_headPageI = pl2.m_tailPageI = RNIL;
+ pl2.m_pageCount = 0;
+}
+
+void
+SuperPool::addHeadPage(PageList& pl, PtrI pageI)
+{
+ PageList pl2(pageI);
+ movePages(pl2, pl);
+ pl = pl2;
+}
+
+void
+SuperPool::addTailPage(PageList& pl, PtrI pageI)
+{
+ PageList pl2(pageI);
+ movePages(pl, pl2);
+}
+
+void
+SuperPool::removePage(PageList& pl, PtrI pageI)
+{
+ PageEnt& pe = getPageEnt(pageI);
+ PtrI pageI1 = pe.m_prevPageI;
+ PtrI pageI2 = pe.m_nextPageI;
+ if (pageI1 != RNIL) {
+ PageEnt& pe1 = getPageEnt(pageI1);
+ pe1.m_nextPageI = pageI2;
+ if (pageI2 != RNIL) {
+ PageEnt& pe2 = getPageEnt(pageI2);
+ pe2.m_prevPageI = pageI1;
+ } else {
+ pl.m_tailPageI = pageI1;
+ }
+ } else {
+ if (pageI2 != RNIL) {
+ PageEnt& pe2 = getPageEnt(pageI2);
+ pe2.m_prevPageI = pageI1;
+ pl.m_headPageI = pageI2;
+ } else {
+ pl.m_headPageI = pl.m_tailPageI = RNIL;
+ }
+ }
+ pe.m_prevPageI = pe.m_nextPageI = RNIL;
+ assert(pl.m_pageCount != 0);
+ pl.m_pageCount--;
+}
+
+void
+SuperPool::setCurrPage(RecInfo& ri, PtrI newPageI)
+{
+ PtrI oldPageI = ri.m_currPageI;
+ if (oldPageI != RNIL) {
+ // copy from cache
+ PageEnt& pe = getPageEnt(oldPageI);
+ pe.m_freeRecI = ri.m_currFreeRecI;
+ pe.m_useCount = ri.m_currUseCount;
+ // add to right list according to "pp2" policy
+ if (pe.m_useCount == 0) {
+ pe.m_pageType = 0;
+ addHeadPage(m_pageList, oldPageI);
+ ri.m_totalRecCount -= ri.m_maxUseCount;
+ } else if (pe.m_useCount < ri.m_maxUseCount) {
+ addHeadPage(ri.m_activeList, oldPageI);
+ } else {
+ addHeadPage(ri.m_fullList, oldPageI);
+ }
+ }
+ if (newPageI != RNIL) {
+ PageEnt& pe = getPageEnt(newPageI);
+ // copy to cache
+ ri.m_currPageI = newPageI;
+ ri.m_currFreeRecI = pe.m_freeRecI;
+ ri.m_currUseCount = pe.m_useCount;
+ // remove from right list
+ if (pe.m_useCount == 0) {
+ removePage(ri.m_freeList, newPageI);
+ } else if (pe.m_useCount < ri.m_maxUseCount) {
+ removePage(ri.m_activeList, newPageI);
+ } else {
+ removePage(ri.m_fullList, newPageI);
+ }
+ } else {
+ ri.m_currPageI = RNIL;
+ ri.m_currFreeRecI = RNIL;
+ ri.m_currUseCount = 0;
+ }
+}
+
+bool
+SuperPool::getAvailPage(RecInfo& ri)
+{
+ PtrI pageI;
+ if ((pageI = ri.m_activeList.m_headPageI) != RNIL ||
+ (pageI = ri.m_freeList.m_headPageI) != RNIL ||
+ (pageI = getFreePage(ri)) != RNIL) {
+ setCurrPage(ri, pageI);
+ return true;
+ }
+ return false;
+}
+
+SuperPool::PtrI
+SuperPool::getFreePage(RecInfo& ri)
+{
+ PtrI pageI;
+ if (m_pageList.m_pageCount != 0) {
+ pageI = m_pageList.m_headPageI;
+ removePage(m_pageList, pageI);
+ } else {
+ pageI = getNewPage();
+ if (pageI == RNIL)
+ return RNIL;
+ }
+ void* pageP = getPageP(pageI);
+ // set up free record list
+ Uint32 maxUseCount = ri.m_maxUseCount;
+ Uint32 recSize = ri.m_recSize;
+ void* recP = (Uint8*)pageP;
+ Uint32 irNext = 1;
+ while (irNext < maxUseCount) {
+ *(Uint32*)recP = pageI | irNext;
+ recP = (Uint8*)recP + recSize;
+ irNext++;
+ }
+ *(Uint32*)recP = RNIL;
+ // add to total record count
+ ri.m_totalRecCount += maxUseCount;
+ // set up new page entry
+ PageEnt& pe = getPageEnt(pageI);
+ new (&pe) PageEnt();
+ pe.m_pageType = ri.m_recType;
+ pe.m_freeRecI = pageI | 0;
+ pe.m_useCount = 0;
+ // set type check bits
+ setCheckBits(pageI, ri.m_recType);
+ // add to record pool free list
+ addHeadPage(ri.m_freeList, pageI);
+ return pageI;
+}
+
+void
+SuperPool::setSizes(size_t initSize, size_t incrSize, size_t maxSize)
+{
+ const Uint32 pageSize = m_pageSize;
+ m_initSize = SP_ALIGN_SIZE(initSize, pageSize);
+ m_incrSize = SP_ALIGN_SIZE(incrSize, pageSize);
+ m_maxSize = SP_ALIGN_SIZE(maxSize, pageSize);
+}
+
+void
+SuperPool::verify(RecInfo& ri)
+{
+ PageList* plList[3] = { &ri.m_freeList, &ri.m_activeList, &ri.m_fullList };
+ for (int i = 0; i < 3; i++) {
+ PageList& pl = *plList[i];
+ unsigned count = 0;
+ PtrI pageI = pl.m_headPageI;
+ while (pageI != RNIL) {
+ PageEnt& pe = getPageEnt(pageI);
+ PtrI pageI1 = pe.m_prevPageI;
+ PtrI pageI2 = pe.m_nextPageI;
+ if (count == 0) {
+ assert(pageI1 == RNIL);
+ } else {
+ assert(pageI1 != RNIL);
+ PageEnt& pe1 = getPageEnt(pageI1);
+ assert(pe1.m_nextPageI == pageI);
+ if (pageI2 != RNIL) {
+ PageEnt& pe2 = getPageEnt(pageI2);
+ assert(pe2.m_prevPageI == pageI);
+ }
+ }
+ pageI = pageI2;
+ count++;
+ }
+ assert(pl.m_pageCount == count);
+ }
+}
+
+// HeapPool
+
+HeapPool::HeapPool(Uint32 pageSize, Uint32 pageBits) :
+ SuperPool(pageSize, pageBits),
+ m_areaHead(),
+ m_currArea(&m_areaHead),
+ m_lastArea(&m_areaHead),
+ m_mallocPart(4)
+{
+}
+
+bool
+HeapPool::init()
+{
+ const Uint32 pageBits = m_pageBits;
+ if (! SuperPool::init())
+ return false;;
+ // allocate page entry array
+ Uint32 peBytes = (1 << pageBits) * sizeof(PageEnt);
+ m_pageEnt = static_cast<PageEnt*>(malloc(peBytes));
+ if (m_pageEnt == 0)
+ return false;
+ memset(m_pageEnt, 0, peBytes);
+ // allocate type check array
+ Uint32 tcWords = 1 << (pageBits - (5 - SP_CHECK_LOG2));
+ m_typeCheck = static_cast<Uint32*>(malloc(tcWords << 2));
+ if (m_typeCheck == 0)
+ return false;
+ memset(m_typeCheck, 0, tcWords << 2);
+ // allocate initial data
+ assert(m_totalSize == 0);
+ if (! allocMoreData(m_initSize))
+ return false;
+ return true;
+}
+
+HeapPool::~HeapPool()
+{
+ free(m_pageEnt);
+ free(m_typeCheck);
+ Area* ap;
+ while ((ap = m_areaHead.m_nextArea) != 0) {
+ m_areaHead.m_nextArea = ap->m_nextArea;
+ free(ap->m_memory);
+ free(ap);
+ }
+}
+
+HeapPool::Area::Area() :
+ m_nextArea(0),
+ m_firstPageI(RNIL),
+ m_currPage(0),
+ m_numPages(0),
+ m_memory(0)
+{
+}
+
+SuperPool::PtrI
+HeapPool::getNewPage()
+{
+ const Uint32 pageSize = m_pageSize;
+ const Uint32 pageBits = m_pageBits;
+ const Uint32 recBits= 32 - pageBits;
+ Area* ap = m_currArea;
+ if (ap->m_currPage == ap->m_numPages) {
+ // area is used up
+ if (ap->m_nextArea == 0) {
+ // todo dynamic increase
+ assert(m_incrSize == 0);
+ return RNIL;
+ }
+ ap = m_currArea = ap->m_nextArea;
+ }
+ assert(ap->m_currPage < ap->m_numPages);
+ PtrI pageI = ap->m_firstPageI;
+ Int32 ip = (Int32)pageI >> recBits;
+ ip += ap->m_currPage;
+ pageI = ip << recBits;
+ ap->m_currPage++;
+ return pageI;
+}
+
+bool
+HeapPool::allocMoreData(size_t size)
+{
+ const Uint32 pageSize = m_pageSize;
+ const Uint32 pageBits = m_pageBits;
+ const Uint32 recBits = 32 - pageBits;
+ const Uint32 incrSize = m_incrSize;
+ const Uint32 incrPages = incrSize / pageSize;
+ const Uint32 mallocPart = m_mallocPart;
+ size = SP_ALIGN_SIZE(size, pageSize);
+ if (incrSize != 0)
+ size = SP_ALIGN_SIZE(size, incrSize);
+ Uint32 needPages = size / pageSize;
+ while (needPages != 0) {
+ Uint32 wantPages = needPages;
+ if (incrPages != 0 && wantPages > incrPages)
+ wantPages = incrPages;
+ Uint32 tryPages = 0;
+ void* p1 = 0;
+ for (Uint32 i = mallocPart; i > 0 && p1 == 0; i--) {
+ // one page is usually wasted due to alignment to memory root
+ tryPages = ((wantPages + 1) * i) / mallocPart;
+ if (tryPages < 2)
+ break;
+ p1 = malloc(pageSize * tryPages);
+ }
+ if (p1 == 0)
+ return false;
+ if (m_memRoot == 0) {
+ // set memory root at first "big" alloc
+ // assume malloc header makes later ip = -1 impossible
+ m_memRoot = p1;
+ }
+ void* p2 = SP_ALIGN_PTR(p1, m_memRoot, pageSize);
+ Uint32 numPages = tryPages - (p1 != p2);
+ my_ptrdiff_t ipL = ((Uint8*)p2 - (Uint8*)m_memRoot) / pageSize;
+ Int32 ip = (Int32)ipL;
+ Int32 lim = 1 << (pageBits - 1);
+ if (! (ip == ipL && -lim <= ip && ip + numPages < lim)) {
+ free(p1);
+ return false;
+ }
+ assert(ip != -1);
+ PtrI pageI = ip << recBits;
+ needPages = (needPages >= numPages ? needPages - numPages : 0);
+ m_totalSize += numPages * pageSize;
+ // allocate new area
+ Area* ap = static_cast<Area*>(malloc(sizeof(Area)));
+ if (ap == 0) {
+ free(p1);
+ return false;
+ }
+ new (ap) Area();
+ ap->m_firstPageI = pageI;
+ ap->m_numPages = numPages;
+ ap->m_memory = p1;
+ m_lastArea->m_nextArea = ap;
+ m_lastArea = ap;
+ }
+ return true;
+}
diff --git a/ndb/src/kernel/vm/SuperPool.hpp b/ndb/src/kernel/vm/SuperPool.hpp
new file mode 100644
index 00000000000..157c75aa0d5
--- /dev/null
+++ b/ndb/src/kernel/vm/SuperPool.hpp
@@ -0,0 +1,561 @@
+/* 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 SUPER_POOL_HPP
+#define SUPER_POOL_HPP
+
+#include <ndb_global.h>
+
+#include <pc.hpp>
+#include <ErrorReporter.hpp>
+
+#define NDB_SP_VERIFY_LEVEL 1
+
+/*
+ * SuperPool - super pool for record pools (abstract class)
+ *
+ * Documents SuperPool and RecordPool<T>.
+ *
+ * GENERAL
+ *
+ * A "super pool" is a shared pool of pages of fixed size. A "record
+ * pool" is a pool of records of fixed size. One super pool instance is
+ * used by any number of record pools to allocate their memory.
+ * A special case is a "page pool" where a record is a simple page,
+ * possibly smaller than super pool page.
+ *
+ * A record pool allocates memory in pages. Thus each used page is
+ * associated with one record pool and one record type. The records on
+ * a page form an array starting at start of page. Thus each record has
+ * an index within the page. Any last partial record which does not fit
+ * on the page is disregarded.
+ *
+ * I-VALUE
+ *
+ * The old "i-p" principle is kept. A reference to a super pool page or
+ * record is stored as an "i-value" from which the record pointer "p" is
+ * computed. In super pool the i-value is a Uint32 with two parts:
+ *
+ * - "ip" index of page within super pool (high pageBits)
+ * - "ir" index of record within page (low recBits)
+ *
+ * The translation between "ip" and page address is described in next
+ * section. Once page address is known, the record address is found
+ * from "ir" in the obvious way.
+ *
+ * The main advantage with i-value is that it can be verified. The
+ * level of verification depends on compile type (release, debug).
+ *
+ * - "v0" minimal sanity check
+ * - "v1" check record type matches page type, see below
+ * - "v2" check record is in use (not yet implemented)
+ *
+ * Another advantage of a 32-bit i-value is that it extends the space of
+ * 32-bit addressable records on a 64-bit platform.
+ *
+ * RNIL is 0xffffff00 and indicates NULL i-value. To avoid hitting RNIL
+ * it is required that pageBits <= 30 and that the maximum value of the
+ * range (2^pageBits-1) is not used.
+ *
+ * MEMORY ROOT
+ *
+ * This super pool requires a "memory root" i.e. a memory address such
+ * that the index of a page "ip" satisfies
+ *
+ * page address = memory root + (signed)ip * page size
+ *
+ * This is possible on most platforms, provided that the memory root and
+ * all pages are either on the heap or on the stack, in order to keep
+ * the size of "ip" reasonably small.
+ *
+ * The cast (signed)ip is done as integer of pageBits bits. "ip" has
+ * same sign bit as i-value "i" so (signed)ip = (Int32)i >> recBits.
+ * The RNIL restriction can be expressed as (signed)ip != -1.
+ *
+ * PAGE ENTRIES
+ *
+ * Each super pool page has a "page entry". It contains:
+ *
+ * - page type
+ * - i-value of first free record on page
+ * - page use count, to see if page can be freed
+ * - pointers (as i-values) to next and previous page in list
+ *
+ * Page entry cannot be stored on the page itself since this prevents
+ * aligning pages to OS block size and the use of BATs (don't ask) for
+ * page pools in NDB. For now the implementation provides an array of
+ * page entries with place for all (2^pageBits) entries.
+ *
+ * PAGE TYPE
+ *
+ * Page type is (in principle) unique to the record pool using the super
+ * pool. It is assigned in record pool constructor. Page type zero
+ * means that the page is free i.e. not allocated to a record pool.
+ *
+ * Each "i-p" conversion checks ("v1") that the record belongs to same
+ * pool as the page. This check is much more common than page or record
+ * allocation. To make it cache effective, there is a separate array of
+ * reduced "type bits" (computed from real type).
+ *
+ * FREE LISTS
+ *
+ * A record is either used or on the free list of the record pool.
+ * A page has a use count i.e. number of used records. When use count
+ * drops to zero the page can be returned to the super pool. This is
+ * not necessarily done at once, or ever.
+ *
+ * To make freeing pages feasible, the record pool free list has two
+ * levels. There are available pages (some free) and a singly linked
+ * free list within the page. A page allocated to record pool is on one
+ * of 4 lists:
+ *
+ * - free page list (all free, available)
+ * - active page list (some free, some used, available)
+ * - full page list (none free)
+ * - current page (list of 1), see below
+ *
+ * Some usage types (temporary pools) may never free records. They pay
+ * a small penalty for the extra overhead.
+ *
+ * RECORD POOL
+ *
+ * A pool of records which allocates its memory from a super pool
+ * instance specified in the constructor. There are 3 basic operations:
+ *
+ * - getPtr - translate i-value to pointer-to-record p
+ * - seize - allocate record
+ * - release - free record
+ *
+ * CURRENT PAGE
+ *
+ * getPtr is a fast computation which does not touch the page. For
+ * seize and release there is an optimization:
+ *
+ * Define "current page" as page of latest seize or release. Its page
+ * entry is cached under record pool instance. The page is removed from
+ * its normal list. Seize and release on current page are fast and
+ * avoid touching the page. The current page is used until
+ *
+ * - seize and current page is full
+ * - release and the page is not current page
+ *
+ * Then the real page entry is updated and the page is added to the
+ * appropriate list, and a new page is made current.
+ *
+ * PAGE POLICY
+ *
+ * Allocating new page to record pool is expensive. Therefore record
+ * pool should not always return empty pages to super pool. There are
+ * two trivial policies, each with problems:
+ *
+ * - "pp1" never return empty page to super pool
+ * - "pp2" always return empty page to super pool
+ *
+ * This implementation uses "pp2" for now. A real policy is implemented
+ * in next version.
+ *
+ * OPEN ISSUES AND LIMITATIONS
+ *
+ * - smarter (virtual) placement of check bits & page entries
+ * - should getPtr etc be inlined? (too much code)
+ * - real page policy
+ * - other implementations (only HeapPool is done)
+ * - super pool list of all record pools, for statistics etc
+ * - access by multiple threads is not supported
+ */
+
+// align size
+#define SP_ALIGN_SIZE(sz, al) \
+ (((sz) + (al) - 1) & ~((al) - 1))
+
+// align pointer relative to base
+#define SP_ALIGN_PTR(p, base, al) \
+ (void*)((Uint8*)(base) + SP_ALIGN_SIZE((Uint8*)(p) - (Uint8*)(base), (al)))
+
+class SuperPool {
+public:
+ // Type of i-value, used to reference both pages and records. Page
+ // index "ip" occupies the high bits. The i-value of a page is same
+ // as i-value of record 0 on the page.
+ typedef Uint32 PtrI;
+
+ // Size and address alignment given as number of bytes (power of 2).
+ STATIC_CONST( SP_ALIGN = 8 );
+
+ // Page entry. Current|y allocated as array of (2^pageBits).
+ struct PageEnt {
+ PageEnt();
+ Uint32 m_pageType;
+ Uint32 m_freeRecI;
+ Uint32 m_useCount;
+ PtrI m_nextPageI;
+ PtrI m_prevPageI;
+ };
+
+ // Number of bits for cache effective type check given as log of 2.
+ // Example: 2 means 4 bits and uses 32k for 2g of 32k pages.
+ STATIC_CONST( SP_CHECK_LOG2 = 2 );
+
+ // Doubly-linked list of pages. There is one free list in super pool
+ // and free, active, full list in each record pool.
+ struct PageList {
+ PageList();
+ PageList(PtrI pageI);
+ PtrI m_headPageI;
+ PtrI m_tailPageI;
+ Uint32 m_pageCount;
+ };
+
+ // Record pool information. Each record pool instance contains one.
+ struct RecInfo {
+ RecInfo(Uint32 recType, Uint32 recSize);
+ const Uint32 m_recType;
+ const Uint32 m_recSize;
+ Uint32 m_maxUseCount; // could be computed
+ Uint32 m_currPageI; // current page
+ Uint32 m_currFreeRecI;
+ Uint32 m_currUseCount;
+ Uint32 m_totalUseCount; // total per pool
+ Uint32 m_totalRecCount;
+ PageList m_freeList;
+ PageList m_activeList;
+ PageList m_fullList;
+ };
+
+ // Constructor. Gives page size in bytes (excluding page header) and
+ // number of bits to use for page index "ip" in i-value.
+ SuperPool(Uint32 pageSize, Uint32 pageBits);
+
+ // Initialize. Must be called after setting sizes or other parameters
+ // and before the pool is used.
+ virtual bool init();
+
+ // Destructor.
+ virtual ~SuperPool() = 0;
+
+ // Translate i-value to page entry.
+ PageEnt& getPageEnt(PtrI pageI);
+
+ // Translate i-value to page address.
+ void* getPageP(PtrI pageI);
+
+ // Translate page address to i-value (unused).
+ PtrI getPageI(void* pageP);
+
+ // Given type, return non-zero reduced type check bits.
+ Uint32 makeCheckBits(Uint32 type);
+
+ // Get type check bits from type check array.
+ Uint32 getCheckBits(PtrI pageI);
+
+ // Set type check bits in type check array.
+ void setCheckBits(PtrI pageI, Uint32 type);
+
+ // Translate i-value to record address.
+ void* getRecP(PtrI recI, RecInfo& ri);
+
+ // Move all pages from second list to end of first list.
+ void movePages(PageList& pl1, PageList& pl2);
+
+ // Add page to beginning of page list.
+ void addHeadPage(PageList& pl, PtrI pageI);
+
+ // Add page to end of page list.
+ void addTailPage(PageList& pl, PtrI pageI);
+
+ // Remove any page from page list.
+ void removePage(PageList& pl, PtrI pageI);
+
+ // Set current page. Previous current page is updated and added to
+ // appropriate list.
+ void setCurrPage(RecInfo& ri, PtrI pageI);
+
+ // Get page with some free records and make it current. Takes head of
+ // active or free list, or else gets free page from super pool.
+ bool getAvailPage(RecInfo& ri);
+
+ // Get free page from super pool and add it to record pool free list.
+ // This is an expensive subroutine of getAvailPage().
+ PtrI getFreePage(RecInfo& ri);
+
+ // Get new free page from the implementation.
+ virtual PtrI getNewPage() = 0;
+
+ // Set 3 size parameters, rounded to page size. If called before
+ // init() then init() allocates the initial size.
+ void setSizes(size_t initSize = 0, size_t incrSize = 0, size_t maxSize = 0);
+
+ const Uint32 m_pageSize;
+ const Uint32 m_pageBits;
+ // implementation must set up these pointers
+ void* m_memRoot;
+ PageEnt* m_pageEnt;
+ Uint32* m_typeCheck;
+ Uint32 m_typeSeq;
+ PageList m_pageList;
+ size_t m_totalSize;
+ size_t m_initSize;
+ size_t m_incrSize;
+ size_t m_maxSize;
+
+ // Debugging.
+ void verify(RecInfo& ri);
+};
+
+inline SuperPool::PageEnt&
+SuperPool::getPageEnt(PtrI pageI)
+{
+ Uint32 ip = pageI >> (32 - m_pageBits);
+ return m_pageEnt[ip];
+}
+
+inline void*
+SuperPool::getPageP(PtrI ptrI)
+{
+ Int32 ip = (Int32)ptrI >> (32 - m_pageBits);
+ my_ptrdiff_t sz = m_pageSize;
+ void* pageP = (Uint8*)m_memRoot + ip * sz;
+ return pageP;
+}
+
+inline Uint32
+SuperPool::makeCheckBits(Uint32 type)
+{
+ Uint32 shift = 1 << SP_CHECK_LOG2;
+ Uint32 mask = (1 << shift) - 1;
+ return 1 + type % mask;
+}
+
+inline Uint32
+SuperPool::getCheckBits(PtrI pageI)
+{
+ Uint32 ip = pageI >> (32 - m_pageBits);
+ Uint32 xp = ip >> (5 - SP_CHECK_LOG2);
+ Uint32 yp = ip & (1 << (5 - SP_CHECK_LOG2)) - 1;
+ Uint32& w = m_typeCheck[xp];
+ Uint32 shift = 1 << SP_CHECK_LOG2;
+ Uint32 mask = (1 << shift) - 1;
+ // get
+ Uint32 bits = (w >> yp * shift) & mask;
+ return bits;
+}
+
+inline void
+SuperPool::setCheckBits(PtrI pageI, Uint32 type)
+{
+ Uint32 ip = pageI >> (32 - m_pageBits);
+ Uint32 xp = ip >> (5 - SP_CHECK_LOG2);
+ Uint32 yp = ip & (1 << (5 - SP_CHECK_LOG2)) - 1;
+ Uint32& w = m_typeCheck[xp];
+ Uint32 shift = 1 << SP_CHECK_LOG2;
+ Uint32 mask = (1 << shift) - 1;
+ // set
+ Uint32 bits = makeCheckBits(type);
+ w &= ~(mask << yp * shift);
+ w |= (bits << yp * shift);
+}
+
+inline void*
+SuperPool::getRecP(PtrI ptrI, RecInfo& ri)
+{
+ const Uint32 recMask = (1 << (32 - m_pageBits)) - 1;
+ PtrI pageI = ptrI & ~recMask;
+#if NDB_SP_VERIFY_LEVEL >= 1
+ Uint32 bits1 = getCheckBits(pageI);
+ Uint32 bits2 = makeCheckBits(ri.m_recType);
+ assert(bits1 == bits2);
+#endif
+ void* pageP = getPageP(pageI);
+ Uint32 ir = ptrI & recMask;
+ void* recP = (Uint8*)pageP + ir * ri.m_recSize;
+ return recP;
+}
+
+/*
+ * HeapPool - SuperPool on heap (concrete class)
+ *
+ * A super pool based on malloc with memory root on the heap. This
+ * pool type has 2 realistic uses:
+ *
+ * - a small pool with only initial malloc and pageBits set to match
+ * - the big pool from which all heap allocations are done
+ *
+ * A "smart" malloc may break "ip" limit by using different VM areas for
+ * different sized requests. For this reason malloc is done in units of
+ * increment size if possible. Memory root is set to start of first
+ * malloc.
+ */
+
+class HeapPool : public SuperPool {
+public:
+ // Describes malloc area. The areas are kept in singly linked list.
+ // There is a list head and pointers to current and last area.
+ struct Area {
+ Area();
+ Area* m_nextArea;
+ PtrI m_firstPageI;
+ Uint32 m_currPage;
+ Uint32 m_numPages;
+ void* m_memory;
+ };
+
+ // Constructor.
+ HeapPool(Uint32 pageSize, Uint32 pageBits);
+
+ // Initialize.
+ virtual bool init();
+
+ // Destructor.
+ virtual ~HeapPool();
+
+ // Use malloc to allocate more.
+ bool allocMoreData(size_t size);
+
+ // Get new page from current area.
+ virtual PtrI getNewPage();
+
+ // List of malloc areas.
+ Area m_areaHead;
+ Area* m_currArea;
+ Area* m_lastArea;
+
+ // Fraction of malloc size to try if cannot get all in one.
+ Uint32 m_mallocPart;
+};
+
+/*
+ * RecordPool - record pool using one super pool instance (template)
+ *
+ * Documented under SuperPool. Satisfies ArrayPool interface.
+ */
+
+template <class T>
+class RecordPool {
+public:
+ // Constructor.
+ RecordPool(SuperPool& superPool);
+
+ // Destructor.
+ ~RecordPool();
+
+ // Update pointer ptr.p according to i-value ptr.i.
+ void getPtr(Ptr<T>& ptr);
+
+ // Allocate record from the pool.
+ bool seize(Ptr<T>& ptr);
+
+ // Return record to the pool.
+ void release(Ptr<T>& ptr);
+
+ // todo variants of basic methods
+
+ // Return all pages to super pool. The force flag is required if
+ // there are any used records.
+ void free(bool force);
+
+ SuperPool& m_superPool;
+ SuperPool::RecInfo m_recInfo;
+};
+
+template <class T>
+inline
+RecordPool<T>::RecordPool(SuperPool& superPool) :
+ m_superPool(superPool),
+ m_recInfo(1 + superPool.m_typeSeq++, sizeof(T))
+{
+ SuperPool::RecInfo& ri = m_recInfo;
+ assert(sizeof(T) == SP_ALIGN_SIZE(sizeof(T), sizeof(Uint32)));
+ Uint32 maxUseCount = superPool.m_pageSize / sizeof(T);
+ Uint32 sizeLimit = 1 << (32 - superPool.m_pageBits);
+ if (maxUseCount >= sizeLimit)
+ maxUseCount = sizeLimit;
+ ri.m_maxUseCount = maxUseCount;
+}
+
+template <class T>
+inline
+RecordPool<T>::~RecordPool()
+{
+ free(true);
+}
+
+template <class T>
+inline void
+RecordPool<T>::getPtr(Ptr<T>& ptr)
+{
+ void* recP = m_superPool.getRecP(ptr.i, m_recInfo);
+ ptr.p = static_cast<T*>(recP);
+}
+
+template <class T>
+inline bool
+RecordPool<T>::seize(Ptr<T>& ptr)
+{
+ SuperPool& sp = m_superPool;
+ SuperPool::RecInfo& ri = m_recInfo;
+ if (ri.m_currFreeRecI != RNIL || sp.getAvailPage(ri)) {
+ SuperPool::PtrI recI = ri.m_currFreeRecI;
+ void* recP = sp.getRecP(recI, ri);
+ ri.m_currFreeRecI = *(Uint32*)recP;
+ Uint32 useCount = ri.m_currUseCount;
+ assert(useCount < ri.m_maxUseCount);
+ ri.m_currUseCount = useCount + 1;
+ ri.m_totalUseCount++;
+ ptr.i = recI;
+ ptr.p = static_cast<T*>(recP);
+ return true;
+ }
+ return false;
+}
+
+template <class T>
+inline void
+RecordPool<T>::release(Ptr<T>& ptr)
+{
+ SuperPool& sp = m_superPool;
+ SuperPool::RecInfo& ri = m_recInfo;
+ const Uint32 recMask = (1 << (32 - sp.m_pageBits)) - 1;
+ SuperPool::PtrI recI = ptr.i;
+ SuperPool::PtrI pageI = recI & ~recMask;
+ if (pageI != ri.m_currPageI) {
+ sp.setCurrPage(ri, pageI);
+ }
+ void* recP = sp.getRecP(recI, ri);
+ *(Uint32*)recP = ri.m_currFreeRecI;
+ ri.m_currFreeRecI = recI;
+ Uint32 useCount = ri.m_currUseCount;
+ assert(useCount != 0);
+ ri.m_currUseCount = useCount - 1;
+ ri.m_totalUseCount--;
+ ptr.i = RNIL;
+ ptr.p = 0;
+}
+
+template <class T>
+inline void
+RecordPool<T>::free(bool force)
+{
+ SuperPool& sp = m_superPool;
+ SuperPool::RecInfo& ri = m_recInfo;
+ sp.setCurrPage(ri, RNIL);
+ assert(force || ri.m_totalUseCount == 0);
+ sp.movePages(sp.m_pageList, ri.m_freeList);
+ sp.movePages(sp.m_pageList, ri.m_activeList);
+ sp.movePages(sp.m_pageList, ri.m_fullList);
+ ri.m_totalRecCount = 0;
+}
+
+#endif
diff --git a/ndb/src/kernel/vm/TransporterCallback.cpp b/ndb/src/kernel/vm/TransporterCallback.cpp
index ba929b7ea7a..e5322edaecc 100644
--- a/ndb/src/kernel/vm/TransporterCallback.cpp
+++ b/ndb/src/kernel/vm/TransporterCallback.cpp
@@ -33,6 +33,7 @@
#include <NdbOut.hpp>
#include "DataBuffer.hpp"
+
/**
* The instance
*/
@@ -337,9 +338,9 @@ reportError(void * callbackObj, NodeId nodeId, TransporterError errorCode){
if(errorCode & 0x8000)
- signal.theData[0] = EventReport::TransporterError;
+ signal.theData[0] = NDB_LE_TransporterError;
else
- signal.theData[0] = EventReport::TransporterWarning;
+ signal.theData[0] = NDB_LE_TransporterWarning;
signal.theData[1] = nodeId;
signal.theData[2] = errorCode;
@@ -363,7 +364,7 @@ reportSendLen(void * callbackObj,
signal.header.theLength = 3;
signal.header.theSendersSignalId = 0;
signal.header.theSendersBlockRef = numberToRef(0, globalData.ownId);
- signal.theData[0] = EventReport::SendBytesStatistic;
+ signal.theData[0] = NDB_LE_SendBytesStatistic;
signal.theData[1] = nodeId;
signal.theData[2] = (bytes/count);
globalScheduler.execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
@@ -382,7 +383,7 @@ reportReceiveLen(void * callbackObj,
signal.header.theLength = 3;
signal.header.theSendersSignalId = 0;
signal.header.theSendersBlockRef = numberToRef(0, globalData.ownId);
- signal.theData[0] = EventReport::ReceiveBytesStatistic;
+ signal.theData[0] = NDB_LE_ReceiveBytesStatistic;
signal.theData[1] = nodeId;
signal.theData[2] = (bytes/count);
globalScheduler.execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
@@ -452,3 +453,8 @@ SignalLoggerManager::printSegmentedSection(FILE * output,
putc('\n', output);
}
+void
+transporter_recv_from(void * callbackObj, NodeId nodeId){
+ globalData.m_nodeInfo[nodeId].m_heartbeat_cnt= 0;
+ return;
+}
diff --git a/ndb/src/kernel/vm/VMSignal.hpp b/ndb/src/kernel/vm/VMSignal.hpp
index 9111ee7949c..45543c5d174 100644
--- a/ndb/src/kernel/vm/VMSignal.hpp
+++ b/ndb/src/kernel/vm/VMSignal.hpp
@@ -78,10 +78,16 @@ public:
#define VMS_DATA_SIZE \
(MAX_ATTRIBUTES_IN_TABLE + MAX_TUPLE_SIZE_IN_WORDS + MAX_KEY_SIZE_IN_WORDS)
+#if VMS_DATA_SIZE > 8192
+#error "VMSignal buffer is too small"
+#endif
+
SignalHeader header; // 28 bytes
SegmentedSectionPtr m_sectionPtr[3];
- Uint32 theData[25+VMS_DATA_SIZE]; // 2048 32-bit words -> 8K Bytes
-
+ union {
+ Uint32 theData[8192]; // 8192 32-bit words -> 32K Bytes
+ Uint64 dummyAlign;
+ };
void garbage_register();
};
diff --git a/ndb/src/kernel/vm/testSuperPool.cpp b/ndb/src/kernel/vm/testSuperPool.cpp
new file mode 100644
index 00000000000..194b3a43fa0
--- /dev/null
+++ b/ndb/src/kernel/vm/testSuperPool.cpp
@@ -0,0 +1,220 @@
+#if 0
+make -f Makefile -f - testSuperPool <<'_eof_'
+testSuperPool: testSuperPool.cpp libkernel.a
+ $(CXXCOMPILE) -o $@ $@.cpp libkernel.a -L../../common/util/.libs -lgeneral
+_eof_
+exit $?
+#endif
+
+/* 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 "SuperPool.hpp"
+#include <NdbOut.hpp>
+
+template <Uint32 sz>
+struct A {
+ Uint32 a[sz];
+ void fill() {
+ Uint32 c = 0;
+ for (Uint32 i = 0; i + 1 < sz; i++) {
+ a[i] = random();
+ c = (c << 1) ^ a[i];
+ }
+ a[sz - 1] = c;
+ }
+ void check() {
+ Uint32 c = 0;
+ for (Uint32 i = 0; i + 1 < sz; i++) {
+ c = (c << 1) ^ a[i];
+ }
+ assert(a[sz - 1] == c);
+ }
+};
+
+static Uint32
+urandom(Uint32 n)
+{
+ return (Uint32)random() % n;
+}
+
+static Uint32
+random_coprime(Uint32 n)
+{
+ Uint32 prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 };
+ Uint32 count = sizeof(prime) / sizeof(prime[0]);
+ while (1) {
+ Uint32 i = urandom(count);
+ if (n % prime[i] != 0)
+ return prime[i];
+ }
+}
+
+static int
+cmpPtrI(const void* a, const void* b)
+{
+ Ptr<const void> u = *(Ptr<const void>*)a;
+ Ptr<const void> v = *(Ptr<const void>*)b;
+ return u.i < v.i ? -1 : u.i > v.i ? +1 : 0;
+}
+
+static int
+cmpPtrP(const void* a, const void* b)
+{
+ Ptr<const void> u = *(Ptr<const void>*)a;
+ Ptr<const void> v = *(Ptr<const void>*)b;
+ return u.p < v.p ? -1 : u.p > v.p ? +1 : 0;
+}
+
+static Uint32 loopcount = 3;
+
+template <Uint32 sz>
+void
+sp_test(SuperPool& sp)
+{
+ typedef A<sz> T;
+ RecordPool<T> rp(sp);
+ SuperPool::RecInfo& ri = rp.m_recInfo;
+ Uint32 pageCount = sp.m_totalSize / sp.m_pageSize;
+ Uint32 perPage = rp.m_recInfo.m_maxUseCount;
+ Uint32 perPool = perPage * pageCount;
+ ndbout << "pages=" << pageCount << " perpage=" << perPage << " perpool=" << perPool << endl;
+ Ptr<T>* ptrList = new Ptr<T> [perPool];
+ memset(ptrList, 0x1f, perPool * sizeof(Ptr<T>));
+ Uint32 loop;
+ for (loop = 0; loop < loopcount; loop++) {
+ ndbout << "loop " << loop << endl;
+ Uint32 i, j;
+ // seize all
+ ndbout << "seize all" << endl;
+ for (i = 0; i < perPool + 1; i++) {
+ j = i;
+ sp.verify(ri);
+ Ptr<T> ptr1 = { 0, RNIL };
+ if (! rp.seize(ptr1))
+ break;
+ // write value
+ ptr1.p->fill();
+ ptr1.p->check();
+ // verify getPtr
+ Ptr<T> ptr2 = { 0, ptr1.i };
+ rp.getPtr(ptr2);
+ assert(ptr1.i == ptr2.i && ptr1.p == ptr2.p);
+ // save
+ ptrList[j] = ptr1;
+ }
+ assert(i == perPool);
+ assert(ri.m_totalUseCount == perPool && ri.m_totalRecCount == perPool);
+ sp.verify(ri);
+ // check duplicates
+ {
+ Ptr<T>* ptrList2 = new Ptr<T> [perPool];
+ memcpy(ptrList2, ptrList, perPool * sizeof(Ptr<T>));
+ qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrI);
+ for (i = 1; i < perPool; i++)
+ assert(ptrList2[i - 1].i != ptrList2[i].i);
+ qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrP);
+ for (i = 1; i < perPool; i++)
+ assert(ptrList2[i - 1].p != ptrList2[i].p);
+ delete [] ptrList2;
+ }
+ // release all in various orders
+ ndbout << "release all" << endl;
+ Uint32 coprime = random_coprime(perPool);
+ for (i = 0; i < perPool; i++) {
+ sp.verify(ri);
+ switch (loop % 3) {
+ case 0: // ascending
+ j = i;
+ break;
+ case 1: // descending
+ j = perPool - 1 - i;
+ break;
+ case 2: // pseudo-random
+ j = (coprime * i) % perPool;
+ break;
+ }
+ Ptr<T>& ptr = ptrList[j];
+ assert(ptr.i != RNIL && ptr.p != 0);
+ ptr.p->check();
+ rp.release(ptr);
+ assert(ptr.i == RNIL && ptr.p == 0);
+ }
+ sp.setCurrPage(ri, RNIL);
+ assert(ri.m_totalUseCount == 0 && ri.m_totalRecCount == 0);
+ sp.verify(ri);
+ // seize/release at random
+ ndbout << "seize/release at random" << endl;
+ for (i = 0; i < loopcount * perPool; i++) {
+ j = urandom(perPool);
+ Ptr<T>& ptr = ptrList[j];
+ if (ptr.i == RNIL) {
+ rp.seize(ptr);
+ ptr.p->fill();
+ } else {
+ ptr.p->check();
+ rp.release(ptr);
+ }
+ }
+ ndbout << "used " << ri.m_totalUseCount << endl;
+ sp.verify(ri);
+ // release all
+ ndbout << "release all" << endl;
+ for (i = 0; i < perPool; i++) {
+ j = i;
+ Ptr<T>& ptr = ptrList[j];
+ if (ptr.i != RNIL) {
+ ptr.p->check();
+ rp.release(ptr);
+ }
+ }
+ sp.setCurrPage(ri, RNIL);
+ assert(ri.m_totalUseCount == 0 && ri.m_totalRecCount == 0);
+ sp.verify(ri);
+ }
+ // done
+ delete [] ptrList;
+}
+
+static Uint32 pageCount = 99;
+static Uint32 pageSize = 32768;
+static Uint32 pageBits = 15;
+
+const Uint32 sz1 = 3, sz2 = 4, sz3 = 53, sz4 = 424, sz5 = 5353;
+
+template void sp_test<sz1>(SuperPool& sp);
+template void sp_test<sz2>(SuperPool& sp);
+template void sp_test<sz3>(SuperPool& sp);
+template void sp_test<sz4>(SuperPool& sp);
+template void sp_test<sz5>(SuperPool& sp);
+
+int
+main()
+{
+ HeapPool sp(pageSize, pageBits);
+ sp.setSizes(pageCount * pageSize);
+ if (! sp.init())
+ assert(false);
+ Uint16 s = (Uint16)getpid();
+ srandom(s);
+ ndbout << "rand " << s << endl;
+ sp_test<sz1>(sp);
+ sp_test<sz2>(sp);
+ sp_test<sz3>(sp);
+ sp_test<sz4>(sp);
+ sp_test<sz5>(sp);
+ return 0;
+}
diff --git a/ndb/src/mgmapi/LocalConfig.cpp b/ndb/src/mgmapi/LocalConfig.cpp
index 0265f982df3..75ad8b40a1f 100644
--- a/ndb/src/mgmapi/LocalConfig.cpp
+++ b/ndb/src/mgmapi/LocalConfig.cpp
@@ -27,7 +27,9 @@ LocalConfig::LocalConfig(){
bool
LocalConfig::init(const char *connectString,
- const char *fileName) {
+ const char *fileName)
+{
+ DBUG_ENTER("LocalConfig::init");
/**
* Escalation:
* 1. Check connectString
@@ -38,21 +40,25 @@ LocalConfig::init(const char *connectString,
* 6. Check defaultConnectString
*/
+ _ownNodeId= 0;
+
//1. Check connectString
if(connectString != 0 && connectString[0] != 0){
if(readConnectString(connectString, "connect string")){
- return true;
- }
- return false;
+ if (ids.size())
+ DBUG_RETURN(true);
+ // only nodeid given, continue to find hosts
+ } else
+ DBUG_RETURN(false);
}
//2. Check given filename
if (fileName && strlen(fileName) > 0) {
bool fopenError;
if(readFile(fileName, fopenError)){
- return true;
+ DBUG_RETURN(true);
}
- return false;
+ DBUG_RETURN(false);
}
//3. Check environment variable
@@ -60,9 +66,9 @@ LocalConfig::init(const char *connectString,
if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) &&
strlen(buf) != 0){
if(readConnectString(buf, "NDB_CONNECTSTRING")){
- return true;
+ DBUG_RETURN(true);
}
- return false;
+ DBUG_RETURN(false);
}
//4. Check Ndb.cfg in NDB_HOME
@@ -71,9 +77,9 @@ LocalConfig::init(const char *connectString,
char *buf= NdbConfig_NdbCfgName(1 /*true*/);
NdbAutoPtr<char> tmp_aptr(buf);
if(readFile(buf, fopenError))
- return true;
+ DBUG_RETURN(true);
if (!fopenError)
- return false;
+ DBUG_RETURN(false);
}
//5. Check Ndb.cfg in cwd
@@ -82,9 +88,9 @@ LocalConfig::init(const char *connectString,
char *buf= NdbConfig_NdbCfgName(0 /*false*/);
NdbAutoPtr<char> tmp_aptr(buf);
if(readFile(buf, fopenError))
- return true;
+ DBUG_RETURN(true);
if (!fopenError)
- return false;
+ DBUG_RETURN(false);
}
//7. Check
@@ -92,12 +98,12 @@ LocalConfig::init(const char *connectString,
char buf[256];
BaseString::snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_PORT);
if(readConnectString(buf, "default connect string"))
- return true;
+ DBUG_RETURN(true);
}
setError(0, "");
- return false;
+ DBUG_RETURN(false);
}
LocalConfig::~LocalConfig(){
@@ -142,6 +148,7 @@ const char *nodeIdTokens[] = {
const char *hostNameTokens[] = {
"host://%[^:]:%i",
"host=%[^:]:%i",
+ "mgmd=%[^:]:%i",
"%[^:^=^ ]:%i",
"%s %i",
0
@@ -207,36 +214,22 @@ LocalConfig::parseString(const char * connectString, BaseString &err){
char * copy = strdup(connectString);
NdbAutoPtr<char> tmp_aptr(copy);
- bool b_nodeId = false;
- bool found_other = false;
-
for (char *tok = strtok_r(copy,";,",&for_strtok); tok != 0;
tok = strtok_r(NULL, ";,", &for_strtok)) {
if (tok[0] == '#') continue;
- if (!b_nodeId) // only one nodeid definition allowed
- if (b_nodeId = parseNodeId(tok))
+ if (!_ownNodeId) // only one nodeid definition allowed
+ if (parseNodeId(tok))
continue;
- if (found_other = parseHostName(tok))
+ if (parseHostName(tok))
continue;
- if (found_other = parseFileName(tok))
+ if (parseFileName(tok))
continue;
err.assfmt("Unexpected entry: \"%s\"", tok);
return false;
}
- if (b_nodeId && !found_other)
- {
- BaseString tmp;
- tmp.assfmt("host=localhost:%s", NDB_PORT);
- if(parseHostName(tmp.c_str()))
- return true;
-
- err.appfmt("Missing host/file name extry in \"%s\"", connectString);
- return false;
- }
-
return true;
}
diff --git a/ndb/src/mgmapi/Makefile.am b/ndb/src/mgmapi/Makefile.am
index 2f2fb407e46..db730bf8c89 100644
--- a/ndb/src/mgmapi/Makefile.am
+++ b/ndb/src/mgmapi/Makefile.am
@@ -1,7 +1,7 @@
noinst_LTLIBRARIES = libmgmapi.la
-libmgmapi_la_SOURCES = mgmapi.cpp mgmapi_configuration.cpp LocalConfig.cpp
+libmgmapi_la_SOURCES = mgmapi.cpp ndb_logevent.cpp mgmapi_configuration.cpp LocalConfig.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index 06b534ac0ca..8263e8cbc93 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -22,8 +22,9 @@
#include <NdbSleep.h>
#include <NdbTCP.h>
-#include "mgmapi.h"
-#include "mgmapi_debug.h"
+#include <mgmapi.h>
+#include <mgmapi_internal.h>
+#include <mgmapi_debug.h>
#include "mgmapi_configuration.hpp"
#include <socket_io.h>
@@ -153,7 +154,7 @@ ndb_mgm_create_handle()
h->socket = NDB_INVALID_SOCKET;
h->read_timeout = 50000;
h->write_timeout = 100;
- h->cfg_i = 0;
+ h->cfg_i = -1;
h->errstream = stdout;
strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
@@ -165,7 +166,7 @@ ndb_mgm_create_handle()
h->logfile = 0;
#endif
- DBUG_PRINT("exit",("ret: %lx", h));
+ DBUG_PRINT("info", ("handle=0x%x", (UintPtr)h));
DBUG_RETURN(h);
}
@@ -173,6 +174,8 @@ extern "C"
int
ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
{
+ DBUG_ENTER("ndb_mgm_set_connectstring");
+ DBUG_PRINT("info", ("handle=0x%x", (UintPtr)handle));
handle->cfg.~LocalConfig();
new (&(handle->cfg)) LocalConfig;
if (!handle->cfg.init(mgmsrv, 0) ||
@@ -180,12 +183,12 @@ ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
{
handle->cfg.~LocalConfig();
new (&(handle->cfg)) LocalConfig;
- handle->cfg.init(0, 0); /* reset the LocalCongig */
+ handle->cfg.init(0, 0); /* reset the LocalConfig */
SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, "");
- return -1;
+ DBUG_RETURN(-1);
}
- handle->cfg_i= 0;
- return 0;
+ handle->cfg_i= -1;
+ DBUG_RETURN(0);
}
/**
@@ -197,9 +200,12 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
{
DBUG_ENTER("ndb_mgm_destroy_handle");
if(!handle)
- return;
- DBUG_PRINT("enter",("*handle: %lx", *handle));
-
+ DBUG_VOID_RETURN;
+ DBUG_PRINT("info", ("handle=0x%x", (UintPtr)(* handle)));
+ /**
+ * important! only disconnect if connected
+ * other code relies on this
+ */
if((* handle)->connected){
ndb_mgm_disconnect(* handle);
}
@@ -307,8 +313,11 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
out.println("%s: %s", name, val_s.c_str());
break;
case PropertiesType_Properties:
+ DBUG_PRINT("info",("Ignoring PropertiesType_Properties."));
/* Ignore */
break;
+ default:
+ DBUG_PRINT("info",("Ignoring PropertiesType: %d.",t));
}
}
#ifdef MGMAPI_LOG
@@ -324,17 +333,23 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
ParserDummy session(handle->socket);
Parser_t parser(command_reply, in, true, true, true);
-#if 1
const Properties* p = parser.parse(ctx, session);
if (p == NULL){
- /**
- * Print some info about why the parser returns NULL
- */
- DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
- ctx.m_status, ctx.m_currentToken));
- //ndbout << " status=" << ctx.m_status << ", curr="
- //<< ctx.m_currentToken << endl;
- }
+ if(!ndb_mgm_is_connected(handle)) {
+ return NULL;
+ }
+ else
+ {
+ /**
+ * Print some info about why the parser returns NULL
+ */
+ fprintf(handle->errstream,
+ "Error in mgm protocol parser. cmd: >%s< status: %d curr: %d\n",
+ cmd, (Uint32)ctx.m_status, ctx.m_currentToken);
+ DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
+ ctx.m_status, ctx.m_currentToken));
+ }
+ }
#ifdef MGMAPI_LOG
else {
/**
@@ -344,9 +359,26 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
}
#endif
DBUG_RETURN(p);
-#else
- DBUG_RETURN(parser.parse(ctx, session));
-#endif
+}
+
+/**
+ * Returns true if connected
+ */
+extern "C"
+int ndb_mgm_is_connected(NdbMgmHandle handle)
+{
+ if(!handle)
+ return 0;
+
+ if(handle->connected)
+ {
+ if(Ndb_check_socket_hup(handle->socket))
+ {
+ handle->connected= 0;
+ NDB_CLOSE_SOCKET(handle->socket);
+ }
+ }
+ return handle->connected;
}
/**
@@ -360,6 +392,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_connect");
CHECK_HANDLE(handle, -1);
+ DBUG_ENTER("ndb_mgm_connect");
#ifdef MGMAPI_LOG
/**
* Open the log file
@@ -389,6 +422,13 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
}
if (sockfd != NDB_INVALID_SOCKET)
break;
+#ifndef DBUG_OFF
+ {
+ char buf[1024];
+ DBUG_PRINT("info",("Unable to connect with connect string: %s",
+ cfg.makeConnectString(buf,sizeof(buf))));
+ }
+#endif
if (verbose > 0) {
char buf[1024];
fprintf(handle->errstream, "Unable to connect with connect string: %s\n",
@@ -402,7 +442,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
cfg.makeConnectString(buf,sizeof(buf)));
if (verbose == -2)
fprintf(handle->errstream, ", failed.\n");
- return -1;
+ DBUG_RETURN(-1);
}
if (verbose == -1) {
fprintf(handle->errstream, "Retrying every %d seconds",
@@ -433,7 +473,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
handle->socket = sockfd;
handle->connected = 1;
- return 0;
+ DBUG_RETURN(0);
}
/**
@@ -651,7 +691,6 @@ ndb_mgm_get_status(NdbMgmHandle handle)
malloc(sizeof(ndb_mgm_cluster_state)+
noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#")));
- state->hostname= 0;
state->no_of_nodes= noOfNodes;
ndb_mgm_node_state * ptr = &state->node_states[0];
int nodeId = 0;
@@ -944,67 +983,68 @@ ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list)
return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
}
-static const char *clusterlog_level_names[]=
+static const char *clusterlog_severity_names[]=
{ "enabled", "debug", "info", "warning", "error", "critical", "alert" };
-struct ndb_mgm_clusterlog_levels
+struct ndb_mgm_event_severities
{
const char* name;
- enum ndb_mgm_clusterlog_level level;
-} clusterlog_levels[] = {
- { clusterlog_level_names[0], NDB_MGM_CLUSTERLOG_ON },
- { clusterlog_level_names[1], NDB_MGM_CLUSTERLOG_DEBUG },
- { clusterlog_level_names[2], NDB_MGM_CLUSTERLOG_INFO },
- { clusterlog_level_names[3], NDB_MGM_CLUSTERLOG_WARNING },
- { clusterlog_level_names[4], NDB_MGM_CLUSTERLOG_ERROR },
- { clusterlog_level_names[5], NDB_MGM_CLUSTERLOG_CRITICAL },
- { clusterlog_level_names[6], NDB_MGM_CLUSTERLOG_ALERT },
- { "all", NDB_MGM_CLUSTERLOG_ALL },
- { 0, NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL },
+ enum ndb_mgm_event_severity severity;
+} clusterlog_severities[] = {
+ { clusterlog_severity_names[0], NDB_MGM_EVENT_SEVERITY_ON },
+ { clusterlog_severity_names[1], NDB_MGM_EVENT_SEVERITY_DEBUG },
+ { clusterlog_severity_names[2], NDB_MGM_EVENT_SEVERITY_INFO },
+ { clusterlog_severity_names[3], NDB_MGM_EVENT_SEVERITY_WARNING },
+ { clusterlog_severity_names[4], NDB_MGM_EVENT_SEVERITY_ERROR },
+ { clusterlog_severity_names[5], NDB_MGM_EVENT_SEVERITY_CRITICAL },
+ { clusterlog_severity_names[6], NDB_MGM_EVENT_SEVERITY_ALERT },
+ { "all", NDB_MGM_EVENT_SEVERITY_ALL },
+ { 0, NDB_MGM_ILLEGAL_EVENT_SEVERITY },
};
extern "C"
-ndb_mgm_clusterlog_level
-ndb_mgm_match_clusterlog_level(const char * name)
+ndb_mgm_event_severity
+ndb_mgm_match_event_severity(const char * name)
{
if(name == 0)
- return NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
+ return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
- for(int i = 0; clusterlog_levels[i].name !=0 ; i++)
- if(strcasecmp(name, clusterlog_levels[i].name) == 0)
- return clusterlog_levels[i].level;
+ for(int i = 0; clusterlog_severities[i].name !=0 ; i++)
+ if(strcasecmp(name, clusterlog_severities[i].name) == 0)
+ return clusterlog_severities[i].severity;
- return NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
+ return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
}
extern "C"
const char *
-ndb_mgm_get_clusterlog_level_string(enum ndb_mgm_clusterlog_level level)
+ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity)
{
- int i= (int)level;
- if (i >= 0 && i < (int)NDB_MGM_CLUSTERLOG_ALL)
- return clusterlog_level_names[i];
- for(i = (int)NDB_MGM_CLUSTERLOG_ALL; clusterlog_levels[i].name != 0; i++)
- if(clusterlog_levels[i].level == level)
- return clusterlog_levels[i].name;
+ int i= (int)severity;
+ if (i >= 0 && i < (int)NDB_MGM_EVENT_SEVERITY_ALL)
+ return clusterlog_severity_names[i];
+ for(i = (int)NDB_MGM_EVENT_SEVERITY_ALL; clusterlog_severities[i].name != 0; i++)
+ if(clusterlog_severities[i].severity == severity)
+ return clusterlog_severities[i].name;
return 0;
}
extern "C"
-unsigned int *
-ndb_mgm_get_logfilter(NdbMgmHandle handle)
+const unsigned int *
+ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle)
{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_logfilter");
- static Uint32 enabled[(int)NDB_MGM_CLUSTERLOG_ALL] = {0,0,0,0,0,0,0};
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
+ static unsigned int enabled[(int)NDB_MGM_EVENT_SEVERITY_ALL]=
+ {0,0,0,0,0,0,0};
const ParserRow<ParserDummy> getinfo_reply[] = {
MGM_CMD("clusterlog", NULL, ""),
- MGM_ARG(clusterlog_level_names[0], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[1], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[2], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[3], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[4], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[5], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[6], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""),
};
CHECK_HANDLE(handle, NULL);
CHECK_CONNECTED(handle, NULL);
@@ -1014,20 +1054,21 @@ ndb_mgm_get_logfilter(NdbMgmHandle handle)
reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
CHECK_REPLY(reply, NULL);
- for(int i=0; i < (int)NDB_MGM_CLUSTERLOG_ALL; i++) {
- reply->get(clusterlog_level_names[i], &enabled[i]);
+ for(int i=0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) {
+ reply->get(clusterlog_severity_names[i], &enabled[i]);
}
return enabled;
}
extern "C"
int
-ndb_mgm_filter_clusterlog(NdbMgmHandle handle,
- enum ndb_mgm_clusterlog_level level,
- int enable,
- struct ndb_mgm_reply* /*reply*/)
+ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,
+ enum ndb_mgm_event_severity severity,
+ int enable,
+ struct ndb_mgm_reply* /*reply*/)
{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_filter_clusterlog");
+ SET_ERROR(handle, NDB_MGM_NO_ERROR,
+ "Executing: ndb_mgm_set_clusterlog_severity_filter");
const ParserRow<ParserDummy> filter_reply[] = {
MGM_CMD("set logfilter reply", NULL, ""),
MGM_ARG("result", String, Mandatory, "Error message"),
@@ -1038,7 +1079,7 @@ ndb_mgm_filter_clusterlog(NdbMgmHandle handle,
CHECK_CONNECTED(handle, -1);
Properties args;
- args.put("level", level);
+ args.put("level", severity);
args.put("enable", enable);
const Properties *reply;
@@ -1074,8 +1115,8 @@ struct ndb_mgm_event_categories
{ "DEBUG", NDB_MGM_EVENT_CATEGORY_DEBUG },
{ "INFO", NDB_MGM_EVENT_CATEGORY_INFO },
{ "ERROR", NDB_MGM_EVENT_CATEGORY_ERROR },
- { "GREP", NDB_MGM_EVENT_CATEGORY_GREP },
{ "BACKUP", NDB_MGM_EVENT_CATEGORY_BACKUP },
+ { "CONGESTION", NDB_MGM_EVENT_CATEGORY_CONGESTION },
{ 0, NDB_MGM_ILLEGAL_EVENT_CATEGORY }
};
@@ -1107,13 +1148,13 @@ ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)
extern "C"
int
-ndb_mgm_set_loglevel_clusterlog(NdbMgmHandle handle, int nodeId,
+ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId,
enum ndb_mgm_event_category cat,
int level,
struct ndb_mgm_reply* /*reply*/)
{
SET_ERROR(handle, NDB_MGM_NO_ERROR,
- "Executing: ndb_mgm_set_loglevel_clusterlog");
+ "Executing: ndb_mgm_set_clusterlog_loglevel");
const ParserRow<ParserDummy> clusterlog_reply[] = {
MGM_CMD("set cluster loglevel reply", NULL, ""),
MGM_ARG("result", String, Mandatory, "Error message"),
@@ -1132,7 +1173,7 @@ ndb_mgm_set_loglevel_clusterlog(NdbMgmHandle handle, int nodeId,
"set cluster loglevel", &args);
CHECK_REPLY(reply, -1);
- DBUG_ENTER("ndb_mgm_set_loglevel_clusterlog");
+ DBUG_ENTER("ndb_mgm_set_clusterlog_loglevel");
DBUG_PRINT("enter",("node=%d, category=%d, level=%d", nodeId, cat, level));
BaseString result;
@@ -1182,9 +1223,9 @@ ndb_mgm_set_loglevel_node(NdbMgmHandle handle, int nodeId,
return 0;
}
-extern "C"
int
-ndb_mgm_listen_event(NdbMgmHandle handle, int filter[])
+ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[],
+ int parsable)
{
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_listen_event");
const ParserRow<ParserDummy> stat_reply[] = {
@@ -1206,6 +1247,9 @@ ndb_mgm_listen_event(NdbMgmHandle handle, int filter[])
}
Properties args;
+
+ if (parsable)
+ args.put("parsable", parsable);
{
BaseString tmp;
for(int i = 0; filter[i] != 0; i += 2){
@@ -1222,11 +1266,21 @@ ndb_mgm_listen_event(NdbMgmHandle handle, int filter[])
handle->socket = tmp;
- CHECK_REPLY(reply, -1);
+ if(reply == NULL) {
+ close(sockfd);
+ CHECK_REPLY(reply, -1);
+ }
return sockfd;
}
extern "C"
+int
+ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[])
+{
+ return ndb_mgm_listen_event_internal(handle,filter,0);
+}
+
+extern "C"
int
ndb_mgm_get_stat_port(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
{
@@ -1770,13 +1824,19 @@ ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)
extern "C"
int ndb_mgm_get_connected_port(NdbMgmHandle handle)
{
- return handle->cfg.ids[handle->cfg_i].port;
+ if (handle->cfg_i >= 0)
+ return handle->cfg.ids[handle->cfg_i].port;
+ else
+ return 0;
}
extern "C"
const char *ndb_mgm_get_connected_host(NdbMgmHandle handle)
{
- return handle->cfg.ids[handle->cfg_i].name.c_str();
+ if (handle->cfg_i >= 0)
+ return handle->cfg.ids[handle->cfg_i].name.c_str();
+ else
+ return 0;
}
extern "C"
@@ -1890,9 +1950,9 @@ ndb_mgm_set_int_parameter(NdbMgmHandle handle,
CHECK_CONNECTED(handle, 0);
Properties args;
- args.put("node: ", node);
- args.put("param: ", param);
- args.put("value: ", value);
+ args.put("node", node);
+ args.put("param", param);
+ args.put("value", value);
const ParserRow<ParserDummy> reply[]= {
MGM_CMD("set parameter reply", NULL, ""),
@@ -1929,9 +1989,9 @@ ndb_mgm_set_int64_parameter(NdbMgmHandle handle,
CHECK_CONNECTED(handle, 0);
Properties args;
- args.put("node: ", node);
- args.put("param: ", param);
- args.put("value: ", value);
+ args.put("node", node);
+ args.put("param", param);
+ args.put("value", value);
const ParserRow<ParserDummy> reply[]= {
MGM_CMD("set parameter reply", NULL, ""),
@@ -1972,9 +2032,9 @@ ndb_mgm_set_string_parameter(NdbMgmHandle handle,
CHECK_CONNECTED(handle, 0);
Properties args;
- args.put("node: ", node);
- args.put("parameter: ", param);
- args.put("value: ", value);
+ args.put("node", node);
+ args.put("parameter", param);
+ args.put("value", value);
const ParserRow<ParserDummy> reply[]= {
MGM_CMD("set parameter reply", NULL, ""),
@@ -2080,4 +2140,146 @@ ndb_mgm_check_connection_error:
return -1;
}
+extern "C"
+int
+ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,
+ int node1,
+ int node2,
+ int param,
+ int value,
+ struct ndb_mgm_reply* mgmreply){
+ DBUG_ENTER("ndb_mgm_set_connection_int_parameter");
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+ args.put("node1", node1);
+ args.put("node2", node2);
+ args.put("param", param);
+ args.put("value", (Uint32)value);
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("set connection parameter reply", NULL, ""),
+ MGM_ARG("message", String, Mandatory, "Error Message"),
+ MGM_ARG("result", String, Mandatory, "Status Result"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop= ndb_mgm_call(handle, reply, "set connection parameter", &args);
+ CHECK_REPLY(prop, -1);
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ fprintf(handle->errstream, "ERROR Message: %s\n", buf);
+ break;
+ }
+ res= 0;
+ } while(0);
+
+ delete prop;
+ DBUG_RETURN(res);
+}
+
+extern "C"
+int
+ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,
+ int node1,
+ int node2,
+ int param,
+ int *value,
+ struct ndb_mgm_reply* mgmreply){
+ DBUG_ENTER("ndb_mgm_get_connection_int_parameter");
+ CHECK_HANDLE(handle, -1);
+ CHECK_CONNECTED(handle, -2);
+
+ Properties args;
+ args.put("node1", node1);
+ args.put("node2", node2);
+ args.put("param", param);
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("get connection parameter reply", NULL, ""),
+ MGM_ARG("value", Int, Mandatory, "Current Value"),
+ MGM_ARG("result", String, Mandatory, "Result"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop = ndb_mgm_call(handle, reply, "get connection parameter", &args);
+ CHECK_REPLY(prop, -3);
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ fprintf(handle->errstream, "ERROR Message: %s\n", buf);
+ break;
+ }
+ res= 0;
+ } while(0);
+
+ if(!prop->get("value",(Uint32*)value)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ res = -4;
+ }
+
+ delete prop;
+ DBUG_RETURN(res);
+}
+
+extern "C"
+NDB_SOCKET_TYPE
+ndb_mgm_convert_to_transporter(NdbMgmHandle *handle)
+{
+ NDB_SOCKET_TYPE s;
+
+ CHECK_HANDLE((*handle), NDB_INVALID_SOCKET);
+ CHECK_CONNECTED((*handle), NDB_INVALID_SOCKET);
+
+ (*handle)->connected= 0; // we pretend we're disconnected
+ s= (*handle)->socket;
+
+ SocketOutputStream s_output(s);
+ s_output.println("transporter connect");
+ s_output.println("");
+
+ ndb_mgm_destroy_handle(handle); // set connected=0, so won't disconnect
+
+ return s;
+}
+
+extern "C"
+Uint32
+ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle)
+{
+ Uint32 nodeid=0;
+
+ DBUG_ENTER("ndb_mgm_get_mgmd_nodeid");
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("get mgmd nodeid reply", NULL, ""),
+ MGM_ARG("nodeid", Int, Mandatory, "Node ID"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop = ndb_mgm_call(handle, reply, "get mgmd nodeid", &args);
+ CHECK_REPLY(prop, 0);
+
+ if(!prop->get("nodeid",&nodeid)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+
+ delete prop;
+ DBUG_RETURN(nodeid);
+}
+
template class Vector<const ParserRow<ParserDummy>*>;
diff --git a/ndb/src/mgmapi/mgmapi_configuration.hpp b/ndb/src/mgmapi/mgmapi_configuration.hpp
index 9e94b3311bf..7d60a4842a1 100644
--- a/ndb/src/mgmapi/mgmapi_configuration.hpp
+++ b/ndb/src/mgmapi/mgmapi_configuration.hpp
@@ -1,3 +1,19 @@
+/* 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 MGMAPI_CONFIGURATION_HPP
#define MGMAPI_CONFIGURATION_HPP
diff --git a/ndb/src/mgmapi/mgmapi_internal.h b/ndb/src/mgmapi/mgmapi_internal.h
new file mode 100644
index 00000000000..90f93129f2a
--- /dev/null
+++ b/ndb/src/mgmapi/mgmapi_internal.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef MGMAPI_INTERNAL_H
+#define MGMAPI_INTERNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <NdbTCP.h>
+
+ /**
+ * Set an integer parameter for a connection
+ *
+ * @param handle the NDB management handle.
+ * @param node1 the node1 id
+ * @param node2 the node2 id
+ * @param param the parameter (e.g. CFG_CONNECTION_SERVER_PORT)
+ * @param value what to set it to
+ * @param reply from ndb_mgmd
+ */
+ int ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,
+ int node1,
+ int node2,
+ int param,
+ int value,
+ struct ndb_mgm_reply* reply);
+
+ /**
+ * Get an integer parameter for a connection
+ *
+ * @param handle the NDB management handle.
+ * @param node1 the node1 id
+ * @param node2 the node2 id
+ * @param param the parameter (e.g. CFG_CONNECTION_SERVER_PORT)
+ * @param value where to store the retreived value. In the case of
+ * error, value is not changed.
+ * @param reply from ndb_mgmd
+ * @return 0 on success. < 0 on error.
+ */
+ int ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,
+ int node1,
+ int node2,
+ int param,
+ int *value,
+ struct ndb_mgm_reply* reply);
+
+ /**
+ * Convert connection to transporter
+ * @param handle NDB management handle.
+ *
+ * @return socket
+ *
+ * @note the socket is now able to be used as a transporter connection
+ */
+ NDB_SOCKET_TYPE ndb_mgm_convert_to_transporter(NdbMgmHandle *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/ndb/src/mgmapi/ndb_logevent.cpp b/ndb/src/mgmapi/ndb_logevent.cpp
new file mode 100644
index 00000000000..27e7c1f36f5
--- /dev/null
+++ b/ndb/src/mgmapi/ndb_logevent.cpp
@@ -0,0 +1,501 @@
+/* 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 <my_sys.h>
+#include <mgmapi.h>
+
+#include <NdbOut.hpp>
+#include <Properties.hpp>
+#include <socket_io.h>
+#include <InputStream.hpp>
+
+#include <debugger/EventLogger.hpp>
+
+#include "ndb_logevent.hpp"
+
+extern
+int ndb_mgm_listen_event_internal(NdbMgmHandle, const int filter[], int);
+
+struct ndb_logevent_error_msg {
+ enum ndb_logevent_handle_error code;
+ const char *msg;
+};
+
+struct ndb_logevent_error_msg ndb_logevent_error_messages[]= {
+ { NDB_LEH_READ_ERROR, "Read error" },
+ { NDB_LEH_MISSING_EVENT_SPECIFIER, "Missing event specifier" },
+ { NDB_LEH_UNKNOWN_EVENT_VARIABLE, "Unknown event variable" },
+ { NDB_LEH_UNKNOWN_EVENT_TYPE, "Unknown event type" },
+ { NDB_LEH_INTERNAL_ERROR, "Unknown internal error" },
+ { NDB_LEH_NO_ERROR,0}
+};
+
+struct ndb_logevent_handle {
+ NDB_SOCKET_TYPE socket;
+ enum ndb_logevent_handle_error m_error;
+};
+
+extern "C"
+NdbLogEventHandle
+ndb_mgm_create_logevent_handle(NdbMgmHandle mh,
+ const int filter[])
+{
+ int fd= ndb_mgm_listen_event_internal(mh, filter, 1);
+
+ if (fd == -1)
+ return 0;
+
+ NdbLogEventHandle h=
+ (NdbLogEventHandle)my_malloc(sizeof(ndb_logevent_handle),MYF(MY_WME));
+
+ h->socket= fd;
+
+ return h;
+}
+
+extern "C"
+void ndb_mgm_destroy_logevent_handle(NdbLogEventHandle * h)
+{
+ if( !h )
+ return;
+
+ if ( *h )
+ close((*h)->socket);
+
+ my_free((char*)* h,MYF(MY_ALLOW_ZERO_PTR));
+ * h = 0;
+}
+
+#define ROW(a,b,c,d) \
+{ NDB_LE_ ## a, b, c, 0, offsetof(struct ndb_logevent, a.d), \
+ sizeof(((struct ndb_logevent *)0)->a.d) }
+
+#define ROW_FN(a,b,c,d,e) \
+{ NDB_LE_ ## a, b, c, e, offsetof(struct ndb_logevent, a.d), \
+ sizeof(((struct ndb_logevent *)0)->a.d) }
+
+static int ref_to_node(int ref){
+ return ref & 0xFFFF;
+}
+
+struct Ndb_logevent_body_row ndb_logevent_body[]= {
+
+ // Connection
+ ROW( Connected, "node", 1, node),
+
+ ROW( Disconnected, "node", 1, node),
+
+ ROW( CommunicationClosed, "node", 1, node),
+
+ ROW( CommunicationOpened, "node", 1, node),
+
+ ROW( ConnectedApiVersion, "node", 1, node),
+ ROW( ConnectedApiVersion, "version", 2, version),
+
+ /* CHECKPOINT */
+
+ ROW( GlobalCheckpointStarted, "gci", 1, gci),
+
+ ROW( GlobalCheckpointCompleted, "gci", 1, gci),
+
+ ROW( LocalCheckpointStarted, "lci", 1, lci),
+ ROW( LocalCheckpointStarted, "keep_gci", 2, keep_gci),
+ ROW( LocalCheckpointStarted, "restore_gci", 3, restore_gci),
+
+ ROW( LocalCheckpointCompleted, "lci", 1, lci),
+
+ ROW( LCPStoppedInCalcKeepGci, "data", 1, data),
+
+ ROW( LCPFragmentCompleted, "node", 1, node),
+ ROW( LCPFragmentCompleted, "table_id", 2, table_id),
+ ROW( LCPFragmentCompleted, "fragment_id", 3, fragment_id),
+
+ ROW( UndoLogBlocked, "acc_count", 1, acc_count),
+ ROW( UndoLogBlocked, "tup_count", 2, tup_count),
+
+ /* STARTUP */
+ ROW( NDBStartStarted, "version", 1, version),
+
+ ROW( NDBStartCompleted, "version", 1, version),
+
+// ROW( STTORRYRecieved),
+
+ ROW( StartPhaseCompleted, "phase", 1, phase),
+ ROW( StartPhaseCompleted, "starttype", 2, starttype),
+
+ ROW( CM_REGCONF, "own_id", 1, own_id),
+ ROW( CM_REGCONF, "president_id", 2, president_id),
+ ROW( CM_REGCONF, "dynamic_id", 3, dynamic_id),
+
+ ROW( CM_REGREF, "own_id", 1, own_id),
+ ROW( CM_REGREF, "other_id", 2, other_id),
+ ROW( CM_REGREF, "cause", 3, cause),
+
+ ROW( FIND_NEIGHBOURS, "own_id", 1, own_id),
+ ROW( FIND_NEIGHBOURS, "left_id", 3, left_id),
+ ROW( FIND_NEIGHBOURS, "right_id", 3, right_id),
+ ROW( FIND_NEIGHBOURS, "dynamic_id", 4, dynamic_id),
+
+ ROW( NDBStopStarted, "stoptype", 1, stoptype),
+
+// ROW( NDBStopAborted),
+
+ ROW( StartREDOLog, "node", 1, node),
+ ROW( StartREDOLog, "keep_gci", 2, keep_gci),
+ ROW( StartREDOLog, "completed_gci", 3, completed_gci),
+ ROW( StartREDOLog, "restorable_gci", 4, restorable_gci),
+
+ ROW( StartLog, "log_part", 1, log_part),
+ ROW( StartLog, "start_mb", 2, start_mb),
+ ROW( StartLog, "stop_mb", 3, stop_mb),
+ ROW( StartLog, "gci", 4, gci),
+
+ ROW( UNDORecordsExecuted, "block", 1, block),
+ ROW( UNDORecordsExecuted, "data1", 2, data1),
+ ROW( UNDORecordsExecuted, "data2", 3, data2),
+ ROW( UNDORecordsExecuted, "data3", 4, data3),
+ ROW( UNDORecordsExecuted, "data4", 5, data4),
+ ROW( UNDORecordsExecuted, "data5", 6, data5),
+ ROW( UNDORecordsExecuted, "data6", 7, data6),
+ ROW( UNDORecordsExecuted, "data7", 8, data7),
+ ROW( UNDORecordsExecuted, "data8", 9, data8),
+ ROW( UNDORecordsExecuted, "data9", 10, data9),
+ ROW( UNDORecordsExecuted, "data10", 11, data10),
+
+ /* NODERESTART */
+// ROW( NR_CopyDict),
+
+// ROW( NR_CopyDistr),
+
+ ROW( NR_CopyFragsStarted, "dest_node", 1, dest_node),
+
+ ROW( NR_CopyFragDone, "dest_node", 1, dest_node),
+ ROW( NR_CopyFragDone, "table_id", 2, table_id),
+ ROW( NR_CopyFragDone, "fragment_id", 3, fragment_id),
+
+ ROW( NR_CopyFragsCompleted, "dest_node", 1, dest_node),
+
+ ROW( NodeFailCompleted, "block", 1, block), /* 0 = all */
+ ROW( NodeFailCompleted, "failed_node", 2, failed_node),
+ ROW( NodeFailCompleted, "completing_node", 3, completing_node), /* 0 = all */
+
+ ROW( NODE_FAILREP, "failed_node", 1, failed_node),
+ ROW( NODE_FAILREP, "failure_state", 2, failure_state),
+
+ /* TODO */
+ ROW( ArbitState, "code", 1, code),
+ ROW( ArbitState, "arbit_node", 2, arbit_node),
+ ROW( ArbitState, "ticket_0", 3, ticket_0),
+ ROW( ArbitState, "ticket_1", 4, ticket_1),
+
+ /* TODO */
+ ROW( ArbitResult, "code", 1, code),
+ ROW( ArbitResult, "arbit_node", 2, arbit_node),
+ ROW( ArbitResult, "ticket_0", 3, ticket_0),
+ ROW( ArbitResult, "ticket_1", 4, ticket_1),
+
+// ROW( GCP_TakeoverStarted),
+
+// ROW( GCP_TakeoverCompleted),
+
+// ROW( LCP_TakeoverStarted),
+
+ ROW( LCP_TakeoverCompleted, "state", 1, state),
+
+ /* STATISTIC */
+ ROW( TransReportCounters, "trans_count", 1, trans_count),
+ ROW( TransReportCounters, "commit_count", 2, commit_count),
+ ROW( TransReportCounters, "read_count", 3, read_count),
+ ROW( TransReportCounters, "simple_read_count", 4, simple_read_count),
+ ROW( TransReportCounters, "write_count", 5, write_count),
+ ROW( TransReportCounters, "attrinfo_count", 6, attrinfo_count),
+ ROW( TransReportCounters, "conc_op_count", 7, conc_op_count),
+ ROW( TransReportCounters, "abort_count", 8, abort_count),
+ ROW( TransReportCounters, "scan_count", 9, scan_count),
+ ROW( TransReportCounters, "range_scan_count", 10, range_scan_count),
+
+ ROW( OperationReportCounters, "ops", 1, ops),
+
+ ROW( TableCreated, "table_id", 1, table_id),
+
+ ROW( JobStatistic, "mean_loop_count", 1, mean_loop_count),
+
+ ROW( SendBytesStatistic, "to_node", 1, to_node),
+ ROW( SendBytesStatistic, "mean_sent_bytes", 2, mean_sent_bytes),
+
+ ROW( ReceiveBytesStatistic, "from_node", 1, from_node),
+ ROW( ReceiveBytesStatistic, "mean_received_bytes", 2, mean_received_bytes),
+
+ ROW( MemoryUsage, "gth", 1, gth),
+ ROW( MemoryUsage, "page_size_kb", 2, page_size_kb),
+ ROW( MemoryUsage, "pages_used", 3, pages_used),
+ ROW( MemoryUsage, "pages_total", 4, pages_total),
+ ROW( MemoryUsage, "block", 5, block),
+
+ /* ERROR */
+ ROW( TransporterError, "to_node", 1, to_node),
+ ROW( TransporterError, "code", 2, code),
+
+ ROW( TransporterWarning, "to_node", 1, to_node),
+ ROW( TransporterWarning, "code", 2, code),
+
+ ROW( MissedHeartbeat, "node", 1, node),
+ ROW( MissedHeartbeat, "count", 2, count),
+
+ ROW( DeadDueToHeartbeat, "node", 1, node),
+
+ /* TODO */
+// ROW( WarningEvent),
+
+ /* INFO */
+ ROW( SentHeartbeat, "node", 1, node),
+
+ ROW( CreateLogBytes, "node", 1, node),
+
+ /* TODO */
+// ROW( InfoEvent),
+
+ // Backup
+ ROW_FN( BackupStarted, "starting_node", 1, starting_node, ref_to_node),
+ ROW( BackupStarted, "backup_id", 2, backup_id),
+
+ ROW_FN(BackupFailedToStart,"starting_node",1, starting_node, ref_to_node),
+ ROW( BackupFailedToStart, "error", 2, error),
+
+ ROW_FN( BackupCompleted, "starting_node", 1, starting_node, ref_to_node),
+ ROW( BackupCompleted, "backup_id", 2, backup_id),
+ ROW( BackupCompleted, "start_gci", 3, start_gci),
+ ROW( BackupCompleted, "stop_gci", 4, stop_gci),
+ ROW( BackupCompleted, "n_bytes", 5, n_bytes),
+ ROW( BackupCompleted, "n_records", 6, n_records),
+ ROW( BackupCompleted, "n_log_bytes", 7, n_log_bytes),
+ ROW( BackupCompleted, "n_log_records", 8, n_log_records),
+
+ ROW_FN( BackupAborted, "starting_node", 1, starting_node, ref_to_node),
+ ROW( BackupAborted, "backup_id", 2, backup_id),
+ ROW( BackupAborted, "error", 3, error),
+
+ { NDB_LE_ILLEGAL_TYPE, 0, 0, 0, 0, 0}
+};
+
+struct Ndb_logevent_header_row {
+ const char *token; // token to use for text transfer
+ int offset; // offset into struct ndb_logevent
+ int size;
+};
+
+#define ROW2(a,b) \
+{ a, offsetof(struct ndb_logevent, b), \
+ sizeof(((struct ndb_logevent *)0)->b) }
+
+struct Ndb_logevent_header_row ndb_logevent_header[]= {
+ ROW2( "type", type),
+ ROW2( "time", time),
+ ROW2( "source_nodeid", source_nodeid),
+ { 0, 0, 0 }
+};
+
+static int
+insert_row(const char * pair, Properties & p){
+ BaseString tmp(pair);
+
+ tmp.trim(" \t\n\r");
+ Vector<BaseString> split;
+ tmp.split(split, ":=", 2);
+ if(split.size() != 2)
+ return -1;
+ p.put(split[0].trim().c_str(), split[1].trim().c_str());
+
+ return 0;
+}
+
+static
+int memcpy_atoi(void *dst, const char *str, int sz)
+{
+ switch (sz)
+ {
+ case 1:
+ {
+ Int8 val= atoi(str);
+ memcpy(dst,&val,sz);
+ return 0;
+ }
+ case 2:
+ {
+ Int16 val= atoi(str);
+ memcpy(dst,&val,sz);
+ return 0;
+ }
+ case 4:
+ {
+ Int32 val= atoi(str);
+ memcpy(dst,&val,sz);
+ return 0;
+ }
+ case 8:
+ {
+ Int64 val= atoi(str);
+ memcpy(dst,&val,sz);
+ return 0;
+ }
+ default:
+ {
+ return -1;
+ }
+ }
+}
+
+extern "C"
+int ndb_logevent_get_next(const NdbLogEventHandle h,
+ struct ndb_logevent *dst,
+ unsigned timeout_in_milliseconds)
+{
+ SocketInputStream in(h->socket, timeout_in_milliseconds);
+
+ Properties p;
+ char buf[256];
+
+ struct timeval start_time;
+ gettimeofday(&start_time, 0);
+
+ /* header */
+ while (1) {
+ if (in.gets(buf,sizeof(buf)) == 0)
+ {
+ h->m_error= NDB_LEH_READ_ERROR;
+ return -1;
+ }
+ if ( buf[0] == 0 )
+ {
+ // timed out
+ return 0;
+ }
+ if ( strcmp("log event reply\n", buf) == 0 )
+ break;
+
+ if ( strcmp("<PING>\n", buf) )
+ ndbout_c("skipped: %s", buf);
+
+ struct timeval now;
+ gettimeofday(&now, 0);
+ unsigned elapsed_ms= (now.tv_sec-start_time.tv_sec)*1000 +
+ ((signed int)now.tv_usec-(signed int)start_time.tv_usec)/1000;
+
+ if (elapsed_ms >= timeout_in_milliseconds)
+ {
+ // timed out
+ return 0;
+ }
+
+ new (&in) SocketInputStream(h->socket, timeout_in_milliseconds-elapsed_ms);
+ }
+
+ /* read name-value pairs into properties object */
+ while (1)
+ {
+ if (in.gets(buf,sizeof(buf)) == 0)
+ {
+ h->m_error= NDB_LEH_READ_ERROR;
+ return -1;
+ }
+ if ( buf[0] == 0 )
+ {
+ // timed out
+ return 0;
+ }
+ if ( buf[0] == '\n' )
+ {
+ break;
+ }
+ if (insert_row(buf,p))
+ {
+ h->m_error= NDB_LEH_READ_ERROR;
+ return -1;
+ }
+ }
+
+ int i;
+ const char *val;
+
+ dst->type= (enum Ndb_logevent_type)-1;
+ /* fill in header info from p*/
+ for (i= 0; ndb_logevent_header[i].token; i++)
+ {
+ if ( p.get(ndb_logevent_header[i].token, &val) == 0 )
+ {
+ ndbout_c("missing: %s\n", ndb_logevent_header[i].token);
+ h->m_error= NDB_LEH_MISSING_EVENT_SPECIFIER;
+ return -1;
+ }
+ if ( memcpy_atoi((char *)dst+ndb_logevent_header[i].offset, val,
+ ndb_logevent_header[i].size) )
+ {
+ h->m_error= NDB_LEH_INTERNAL_ERROR;
+ return -1;
+ }
+ }
+
+ Uint32 level;
+ LogLevel::EventCategory category;
+ Logger::LoggerLevel severity;
+ EventLoggerBase::EventTextFunction text_fn;
+
+ /* fill in rest of header info event_lookup */
+ if (EventLoggerBase::event_lookup(dst->type,category,level,severity,text_fn))
+ {
+ ndbout_c("unknown type: %d\n", dst->type);
+ h->m_error= NDB_LEH_UNKNOWN_EVENT_TYPE;
+ return -1;
+ }
+ dst->category= (enum ndb_mgm_event_category)category;
+ dst->severity= (enum ndb_mgm_event_severity)severity;
+ dst->level= level;
+
+ /* fill in header info from p */
+ for (i= 0; ndb_logevent_body[i].token; i++)
+ {
+ if ( ndb_logevent_body[i].type != dst->type )
+ continue;
+ if ( p.get(ndb_logevent_body[i].token, &val) == 0 )
+ {
+ h->m_error= NDB_LEH_UNKNOWN_EVENT_VARIABLE;
+ return -1;
+ }
+ if ( memcpy_atoi((char *)dst+ndb_logevent_body[i].offset, val,
+ ndb_logevent_body[i].size) )
+ {
+ h->m_error= NDB_LEH_INTERNAL_ERROR;
+ return -1;
+ }
+ }
+ return 1;
+}
+
+extern "C"
+int ndb_logevent_get_latest_error(const NdbLogEventHandle h)
+{
+ return h->m_error;
+}
+
+extern "C"
+const char *ndb_logevent_get_latest_error_msg(const NdbLogEventHandle h)
+{
+ for (int i= 0; ndb_logevent_error_messages[i].msg; i++)
+ if (ndb_logevent_error_messages[i].code == h->m_error)
+ return ndb_logevent_error_messages[i].msg;
+ return "<unknown error msg>";
+}
diff --git a/isam/changed.c b/ndb/src/mgmapi/ndb_logevent.hpp
index b8132538b86..cb1a0e388e5 100644
--- a/isam/changed.c
+++ b/ndb/src/mgmapi/ndb_logevent.hpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* 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
@@ -14,22 +14,21 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Check if somebody has changed table since last check. */
+#ifndef NDB_LOGEVENT_HPP
+#define NDB_LOGEVENT_HPP
-#include "isamdef.h"
+#include <ndb_logevent.h>
- /* Return 0 if table isn't changed */
+struct Ndb_logevent_body_row {
+ enum Ndb_logevent_type type; // type
+ const char *token; // token to use for text transfer
+ int index; // index into theData array
+ int (*index_fn)(int); // conversion function on the data array[index]
+ int offset; // offset into struct ndb_logevent
+ int size; // offset into struct ndb_logevent
+};
+
+extern
+struct Ndb_logevent_body_row ndb_logevent_body[];
-int nisam_is_changed(N_INFO *info)
-{
- int result;
- DBUG_ENTER("nisam_is_changed");
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
- VOID(_nisam_writeinfo(info,0));
#endif
- result=(int) info->data_changed;
- info->data_changed=0;
- DBUG_PRINT("exit",("result: %d",result));
- DBUG_RETURN(result);
-}
diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp
index 124c5c18748..b4bbb3531ad 100644
--- a/ndb/src/mgmclient/CommandInterpreter.cpp
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp
@@ -389,7 +389,7 @@ CommandInterpreter::CommandInterpreter(const char *_host,int verbose)
}
m_mgmsrv2 = ndb_mgm_create_handle();
if(m_mgmsrv2 == NULL) {
- ndbout_c("Cannot create handle to management server.");
+ ndbout_c("Cannot create 2:nd handle to management server.");
exit(-1);
}
if (ndb_mgm_set_connectstring(m_mgmsrv, _host))
@@ -496,11 +496,13 @@ CommandInterpreter::connect()
{
const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
- if(!ndb_mgm_set_connectstring(m_mgmsrv2,
- BaseString(host).appfmt(":%d",port).c_str())
- &&
+ BaseString constr;
+ constr.assfmt("%s:%d",host,port);
+ if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) &&
!ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1))
{
+ DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d",
+ host, port));
assert(m_event_thread == 0);
assert(do_event_thread == 0);
do_event_thread= 0;
@@ -511,6 +513,7 @@ CommandInterpreter::connect()
NDB_THREAD_PRIO_LOW);
if (m_event_thread != 0)
{
+ DBUG_PRINT("info",("Thread created ok, waiting for started..."));
int iter= 1000; // try for 30 seconds
while(do_event_thread == 0 &&
iter-- > 0)
@@ -537,11 +540,18 @@ CommandInterpreter::connect()
}
else
{
+ DBUG_PRINT("warning",
+ ("Could not do 2:nd connect to mgmtserver for event listening"));
+ DBUG_PRINT("info", ("code: %d, msg: %s",
+ ndb_mgm_get_latest_error(m_mgmsrv2),
+ ndb_mgm_get_latest_error_msg(m_mgmsrv2)));
printf("Warning, event connect failed, degraded printouts as result\n");
+ printf("code: %d, msg: %s\n",
+ ndb_mgm_get_latest_error(m_mgmsrv2),
+ ndb_mgm_get_latest_error_msg(m_mgmsrv2));
}
m_connected= true;
- DBUG_PRINT("info",("Connected to Management Server at: %s:%d",
- host,port));
+ DBUG_PRINT("info",("Connected to Management Server at: %s:%d", host, port));
if (m_verbose)
{
printf("Connected to Management Server at: %s:%d\n",
@@ -1268,7 +1278,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
DBUG_VOID_RETURN;
}
- enum ndb_mgm_clusterlog_level severity = NDB_MGM_CLUSTERLOG_ALL;
+ enum ndb_mgm_event_severity severity = NDB_MGM_EVENT_SEVERITY_ALL;
char * tmpString = my_strdup(parameters,MYF(MY_WME));
My_auto_ptr<char> ap1(tmpString);
@@ -1276,7 +1286,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
char * item = strtok_r(tmpString, " ", &tmpPtr);
int enable;
- Uint32 *enabled = ndb_mgm_get_logfilter(m_mgmsrv);
+ const unsigned int *enabled= ndb_mgm_get_logfilter(m_mgmsrv);
if(enabled == NULL) {
ndbout << "Couldn't get status" << endl;
printError();
@@ -1298,8 +1308,8 @@ CommandInterpreter::executeClusterLog(char* parameters)
printf("enabled[%d] = %d\n", i, enabled[i]);
#endif
ndbout << "Severities enabled: ";
- for(i = 1; i < (int)NDB_MGM_CLUSTERLOG_ALL; i++) {
- const char *str= ndb_mgm_get_clusterlog_level_string((ndb_mgm_clusterlog_level)i);
+ for(i = 1; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) {
+ const char *str= ndb_mgm_get_event_severity_string((ndb_mgm_event_severity)i);
if (str == 0)
{
DBUG_ASSERT(false);
@@ -1333,8 +1343,10 @@ CommandInterpreter::executeClusterLog(char* parameters)
int res_enable;
item = strtok_r(NULL, " ", &tmpPtr);
if (item == NULL) {
- res_enable= ndb_mgm_filter_clusterlog(m_mgmsrv,
- NDB_MGM_CLUSTERLOG_ON, enable, NULL);
+ res_enable=
+ ndb_mgm_set_clusterlog_severity_filter(m_mgmsrv,
+ NDB_MGM_EVENT_SEVERITY_ON,
+ enable, NULL);
if (res_enable < 0)
{
ndbout << "Couldn't set filter" << endl;
@@ -1346,32 +1358,33 @@ CommandInterpreter::executeClusterLog(char* parameters)
}
do {
- severity= NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
+ severity= NDB_MGM_ILLEGAL_EVENT_SEVERITY;
if (strcasecmp(item, "ALL") == 0) {
- severity = NDB_MGM_CLUSTERLOG_ALL;
+ severity = NDB_MGM_EVENT_SEVERITY_ALL;
} else if (strcasecmp(item, "ALERT") == 0) {
- severity = NDB_MGM_CLUSTERLOG_ALERT;
+ severity = NDB_MGM_EVENT_SEVERITY_ALERT;
} else if (strcasecmp(item, "CRITICAL") == 0) {
- severity = NDB_MGM_CLUSTERLOG_CRITICAL;
+ severity = NDB_MGM_EVENT_SEVERITY_CRITICAL;
} else if (strcasecmp(item, "ERROR") == 0) {
- severity = NDB_MGM_CLUSTERLOG_ERROR;
+ severity = NDB_MGM_EVENT_SEVERITY_ERROR;
} else if (strcasecmp(item, "WARNING") == 0) {
- severity = NDB_MGM_CLUSTERLOG_WARNING;
+ severity = NDB_MGM_EVENT_SEVERITY_WARNING;
} else if (strcasecmp(item, "INFO") == 0) {
- severity = NDB_MGM_CLUSTERLOG_INFO;
+ severity = NDB_MGM_EVENT_SEVERITY_INFO;
} else if (strcasecmp(item, "DEBUG") == 0) {
- severity = NDB_MGM_CLUSTERLOG_DEBUG;
+ severity = NDB_MGM_EVENT_SEVERITY_DEBUG;
} else if (strcasecmp(item, "OFF") == 0 ||
strcasecmp(item, "ON") == 0) {
if (enable < 0) // only makes sense with toggle
- severity = NDB_MGM_CLUSTERLOG_ON;
+ severity = NDB_MGM_EVENT_SEVERITY_ON;
}
- if (severity == NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL) {
+ if (severity == NDB_MGM_ILLEGAL_EVENT_SEVERITY) {
ndbout << "Invalid severity level: " << item << endl;
DBUG_VOID_RETURN;
}
- res_enable = ndb_mgm_filter_clusterlog(m_mgmsrv, severity, enable, NULL);
+ res_enable= ndb_mgm_set_clusterlog_severity_filter(m_mgmsrv, severity,
+ enable, NULL);
if (res_enable < 0)
{
ndbout << "Couldn't set filter" << endl;
diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp
index 9128df4f978..ba5d0308f1f 100644
--- a/ndb/src/mgmclient/main.cpp
+++ b/ndb/src/mgmclient/main.cpp
@@ -90,13 +90,6 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_mgm.trace");
-}
static int
read_and_execute(int _try_reconnect)
@@ -139,7 +132,11 @@ int main(int argc, char** argv){
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_mgm.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
exit(ho_error);
char buf[MAXHOSTNAMELEN+10];
diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp
deleted file mode 100644
index 686155415d5..00000000000
--- a/ndb/src/mgmsrv/CommandInterpreter.cpp
+++ /dev/null
@@ -1,345 +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 "CommandInterpreter.hpp"
-
-#include <string.h>
-#include <ctype.h>
-
-#include "MgmtSrvr.hpp"
-#include "MgmtErrorReporter.hpp"
-#include <NdbOut.hpp>
-#include "convertStrToInt.hpp"
-#include <EventLogger.hpp>
-#include <signaldata/SetLogLevelOrd.hpp>
-#include "ConfigInfo.hpp"
-
-#include <version.h>
-#include <m_string.h>
-
-//******************************************************************************
-//******************************************************************************
-CommandInterpreter::CommandInterpreter(MgmtSrvr& mgmtSrvr) :
- _mgmtSrvr(mgmtSrvr) {
-}
-
-
-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;
-}
-
-class AutoPtr {
-public:
- AutoPtr(void * ptr) : m_ptr(ptr) {}
- ~AutoPtr() { free(m_ptr);}
-private:
- void * m_ptr;
-};
-
-const char *CommandInterpreter::get_error_text(int err_no)
-{
- return _mgmtSrvr.getErrorText(err_no, m_err_str, sizeof(m_err_str));
-}
-
-//*****************************************************************************
-//*****************************************************************************
-int CommandInterpreter::readAndExecute() {
-
- char* _line = readline_gets();
- char * line;
- if(_line == NULL) {
- ndbout << endl;
- return true;
- }
-
- line = strdup(_line);
-
- AutoPtr ptr(line);
-
- if (emptyString(line)) {
- return true;
- }
-
- for (unsigned int i = 0; i < strlen(line); ++i) {
- line[i] = toupper(line[i]);
- }
-
- // if there is anything in the line proceed
- char* firstToken = strtok(line, " ");
- char* allAfterFirstToken = strtok(NULL, "\0");
-
- if (strcmp(firstToken, "ALL") == 0) {
- analyseAfterFirstToken(-1, allAfterFirstToken);
- }
- else if(strcmp(firstToken, "QUIT") == 0 ||
- strcmp(firstToken, "EXIT") == 0 ||
- strcmp(firstToken, "BYE") == 0){
- return false;
- } else {
- // First token should be a digit, process ID
-
- int processId;
- if (! convert(firstToken, processId)) {
- ndbout << "Invalid command: " << _line << "." << endl;
- return true;
- }
- if (processId < 0) {
- ndbout << "Invalid process ID: " << firstToken << "." << endl;
- return true;
- }
-
- analyseAfterFirstToken(processId, allAfterFirstToken);
-
- } // else
- return true;
-}
-
-
-static const CommandInterpreter::CommandFunctionPair commands[] = {
- { "TRACE", &CommandInterpreter::executeTrace }
- ,{ "LOGIN", &CommandInterpreter::executeLogIn }
- ,{ "LOGOUT", &CommandInterpreter::executeLogOut }
- ,{ "LOGOFF", &CommandInterpreter::executeLogOff }
-};
-
-
-//*****************************************************************************
-//*****************************************************************************
-void
-CommandInterpreter::analyseAfterFirstToken(int processId,
- char* allAfterFirstToken) {
-
- if (emptyString(allAfterFirstToken)) {
- if (processId == -1) {
- ndbout << "Expected a command after ALL." << endl;
- }
- else {
- ndbout << "Expected a command after process ID." << endl;
- }
- return;
- }
-
-
- char* secondToken = strtok(allAfterFirstToken, " ");
- char* allAfterSecondToken = strtok(NULL, "\0");
-
- const int tmpSize = sizeof(commands)/sizeof(CommandFunctionPair);
- ExecuteFunction fun = 0;
- const char * command = 0;
- for(int i = 0; i<tmpSize; i++){
- if(strcmp(secondToken, commands[i].command) == 0){
- fun = commands[i].executeFunction;
- command = commands[i].command;
- break;
- }
- }
-
- if(fun == 0){
- ndbout << "Invalid command: " << secondToken << "." << endl;
- return;
- }
-
- if(processId == -1){
- executeForAll(command, fun, allAfterSecondToken);
- } else {
- ndbout << "Executing " << command << " on node: "
- << processId << endl << endl;
- (this->*fun)(processId, allAfterSecondToken, false);
- ndbout << endl;
- }
-}
-
-void
-CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun,
- const char * allAfterSecondToken){
-
- NodeId nodeId = 0;
- while(_mgmtSrvr.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
- ndbout << "Executing " << cmd << " on node: "
- << nodeId << endl << endl;
- (this->*fun)(nodeId, allAfterSecondToken, true);
- ndbout << endl;
- }
-}
-
-//*****************************************************************************
-//*****************************************************************************
-bool CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
- Vector<BaseString>& blocks) {
-
- // Parse: [BLOCK = {ALL|<blockName>+}]
-
- if (emptyString(allAfterLog)) {
- return true;
- }
-
- // Copy allAfterLog since strtok will modify it
- char* newAllAfterLog = strdup(allAfterLog);
- char* firstTokenAfterLog = strtok(newAllAfterLog, " ");
- for (unsigned int i = 0; i < strlen(firstTokenAfterLog); ++i) {
- firstTokenAfterLog[i] = toupper(firstTokenAfterLog[i]);
- }
-
- if (strcmp(firstTokenAfterLog, "BLOCK") != 0) {
- ndbout << "Unexpected value: " << firstTokenAfterLog
- << ". Expected BLOCK." << endl;
- free(newAllAfterLog);
- return false;
- }
-
- char* allAfterFirstToken = strtok(NULL, "\0");
- if (emptyString(allAfterFirstToken)) {
- ndbout << "Expected =." << endl;
- free(newAllAfterLog);
- return false;
- }
-
- char* secondTokenAfterLog = strtok(allAfterFirstToken, " ");
- if (strcmp(secondTokenAfterLog, "=") != 0) {
- ndbout << "Unexpected value: " << secondTokenAfterLog
- << ". Expected =." << endl;
- free(newAllAfterLog);
- return false;
- }
-
- char* blockName = strtok(NULL, " ");
- bool all = false;
- if (blockName != NULL && (strcmp(blockName, "ALL") == 0)) {
- all = true;
- }
- while (blockName != NULL) {
- blocks.push_back(BaseString(blockName));
- blockName = strtok(NULL, " ");
- }
-
- if (blocks.size() == 0) {
- ndbout << "No block specified." << endl;
- free(newAllAfterLog);
- return false;
- }
- if (blocks.size() > 1 && all) {
- // More than "ALL" specified
- ndbout << "Nothing expected after ALL." << endl;
- free(newAllAfterLog);
- return false;
- }
-
- free(newAllAfterLog);
- return true;
-}
-
-void CommandInterpreter::executeLogIn(int processId,
- const char* parameters, bool all) {
-
- (void)all; // Don't want compiler warning
-
- Vector<BaseString> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::In, blocks);
- if (result != 0) {
- ndbout << get_error_text(result) << endl;
- }
-}
-
-//******************************************************************************
-//******************************************************************************
-void CommandInterpreter::executeLogOut(int processId,
- const char* parameters, bool all) {
-
- (void)all; // Don't want compiler warning
-
- Vector<BaseString> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
-
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Out, blocks);
- if (result != 0) {
- ndbout << get_error_text(result) << endl;
- }
-
-}
-
-
-//******************************************************************************
-//******************************************************************************
-void CommandInterpreter::executeLogOff(int processId,
- const char* parameters, bool all) {
-
- (void)all; // Don't want compiler warning
-
- Vector<BaseString> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
-
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Off, blocks);
- if (result != 0) {
- ndbout << get_error_text(result) << endl;
- }
-
-}
-
-void CommandInterpreter::executeTrace(int processId,
- const char* parameters, bool all) {
-
- (void)all; // Don't want compiler warning
-
- if (emptyString(parameters)) {
- ndbout << "Missing trace number." << endl;
- return;
- }
-
- char* newpar = strdup(parameters);
- char* firstParameter = strtok(newpar, " ");
-
-
- int traceNo;
- if (! convert(firstParameter, traceNo)) {
- ndbout << "Expected an integer." << endl;
- free(newpar);
- return;
- }
-
- char* allAfterFirstParameter = strtok(NULL, "\0");
-
- if (! emptyString(allAfterFirstParameter)) {
- ndbout << "Nothing expected after trace number." << endl;
- free(newpar);
- return;
- }
-
- int result = _mgmtSrvr.setTraceNo(processId, traceNo);
- if (result != 0) {
- ndbout << get_error_text(result) << endl;
- }
- free(newpar);
-}
diff --git a/ndb/src/mgmsrv/CommandInterpreter.hpp b/ndb/src/mgmsrv/CommandInterpreter.hpp
deleted file mode 100644
index 6b67d1a5a5f..00000000000
--- a/ndb/src/mgmsrv/CommandInterpreter.hpp
+++ /dev/null
@@ -1,92 +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 CommandInterpreter_H
-#define CommandInterpreter_H
-
-#include <ndb_global.h>
-#include <Vector.hpp>
-#include <BaseString.hpp>
-
-class MgmtSrvr;
-
-class CommandInterpreter {
-public:
- CommandInterpreter(MgmtSrvr& mgmtSrvr);
- int readAndExecute();
-
-private:
- char m_err_str[1024];
- const char *get_error_text(int err_no);
-
- char *readline_gets ()
- {
- static char linebuffer[254];
- static char *line_read = (char *)NULL;
-
- /* If the buffer has already been allocated, return the memory
- to the free pool. */
- if (line_read)
- {
- free (line_read);
- line_read = (char *)NULL;
- }
-
- /* Get a line from the user. */
- fputs("ndb_mgmd> ", stdout);
- linebuffer[sizeof(linebuffer)-1]=0;
- line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
- if (line_read == linebuffer) {
- char *q=linebuffer;
- while (*q > 31) q++;
- *q=0;
- line_read= strdup(linebuffer);
- }
- return (line_read);
- }
-
- void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
- bool parseBlockSpecification(const char* allAfterLog,
- Vector<BaseString>& blocks);
-
-public:
- void executeTrace(int processId, const char* parameters, bool all);
- void executeLogIn(int processId, const char* parameters, bool all);
- void executeLogOut(int processId, const char* parameters, bool all);
- void executeLogOff(int processId, const char* parameters, bool all);
-
-public:
- typedef void (CommandInterpreter::* ExecuteFunction)(int processId,
- const char * param,
- bool all);
-
- struct CommandFunctionPair {
- const char * command;
- ExecuteFunction executeFunction;
- };
-private:
- /**
- *
- */
- void executeForAll(const char * cmd, ExecuteFunction fun, const char * param);
-
- /**
- * Management server to use when executing commands
- */
- MgmtSrvr& _mgmtSrvr;
-};
-
-#endif // CommandInterpreter_H
diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp
index 36a72dcb975..4e96047e54d 100644
--- a/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -1097,6 +1097,18 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
"15" },
{
+ CFG_LOGLEVEL_CONGESTION,
+ "LogLevelCongestion",
+ DB_TOKEN,
+ "Congestion info printed on stdout",
+ ConfigInfo::CI_USED,
+ false,
+ ConfigInfo::CI_INT,
+ "0",
+ "0",
+ "15" },
+
+ {
CFG_LOGLEVEL_ERROR,
"LogLevelError",
DB_TOKEN,
@@ -3082,8 +3094,8 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
const Properties * node;
require(ctx.m_config->get("Node", id1, &node));
+
BaseString hostname(hostName1);
- // require(node->get("HostName", hostname));
if (hostname.c_str()[0] == 0) {
ctx.reportError("Hostname required on nodeid %d since it will "
@@ -3092,29 +3104,51 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
}
Uint32 port= 0;
- if (!node->get("ServerPort", &port) &&
- !ctx.m_userProperties.get("ServerPort_", id1, &port)) {
- Uint32 adder= 0;
- {
- BaseString server_port_adder(hostname);
- server_port_adder.append("_ServerPortAdder");
- ctx.m_userProperties.get(server_port_adder.c_str(), &adder);
- ctx.m_userProperties.put(server_port_adder.c_str(), adder+1, true);
- }
+ const char * type1;
+ const char * type2;
+ const Properties * node2;
+
+ node->get("Type", &type1);
+ ctx.m_config->get("Node", id2, &node2);
+ node2->get("Type", &type2);
+
+ if(strcmp(type1, MGM_TOKEN)==0)
+ node->get("PortNumber",&port);
+ else if(strcmp(type2, MGM_TOKEN)==0)
+ node2->get("PortNumber",&port);
+ if (!port &&
+ !node->get("ServerPort", &port) &&
+ !ctx.m_userProperties.get("ServerPort_", id1, &port))
+ {
Uint32 base= 0;
- if (!ctx.m_userProperties.get("ServerPortBase", &base)){
- if(!(ctx.m_userDefaults &&
+ /*
+ * If the connection doesn't involve an mgm server,
+ * and a default port number has been set, behave the old
+ * way of allocating port numbers for transporters.
+ */
+ if(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base))
+ {
+ Uint32 adder= 0;
+ {
+ BaseString server_port_adder(hostname);
+ server_port_adder.append("_ServerPortAdder");
+ ctx.m_userProperties.get(server_port_adder.c_str(), &adder);
+ ctx.m_userProperties.put(server_port_adder.c_str(), adder+1, true);
+ }
+
+ if (!ctx.m_userProperties.get("ServerPortBase", &base)){
+ if(!(ctx.m_userDefaults &&
ctx.m_userDefaults->get("PortNumber", &base)) &&
- !ctx.m_systemDefaults->get("PortNumber", &base)) {
- base= strtoll(NDB_TCP_BASE_PORT,0,0);
- // ctx.reportError("Cannot retrieve base port number");
- // return false;
+ !ctx.m_systemDefaults->get("PortNumber", &base)) {
+ base= strtoll(NDB_TCP_BASE_PORT,0,0);
+ }
+ ctx.m_userProperties.put("ServerPortBase", base);
}
- ctx.m_userProperties.put("ServerPortBase", base);
+
+ port= base + adder;
+ ctx.m_userProperties.put("ServerPort_", id1, port);
}
- port= base + adder;
- ctx.m_userProperties.put("ServerPort_", id1, port);
}
if(ctx.m_currentSection->contains("PortNumber")) {
@@ -3127,6 +3161,7 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
{
ctx.m_currentSection->put("PortNumber", port);
}
+
DBUG_PRINT("info", ("connection %d-%d port %d host %s",
id1, id2, port, hostname.c_str()));
diff --git a/ndb/src/mgmsrv/Makefile.am b/ndb/src/mgmsrv/Makefile.am
index 50e0b6023ad..7fd3fa66b43 100644
--- a/ndb/src/mgmsrv/Makefile.am
+++ b/ndb/src/mgmsrv/Makefile.am
@@ -16,17 +16,20 @@ ndb_mgmd_SOURCES = \
MgmtSrvrConfig.cpp \
ConfigInfo.cpp \
InitConfigFileParser.cpp \
- Config.cpp \
- CommandInterpreter.cpp
+ Config.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/ndbapi \
-I$(top_srcdir)/ndb/src/mgmapi \
- -I$(top_srcdir)/ndb/src/common/mgmcommon
+ -I$(top_srcdir)/ndb/src/common/mgmcommon \
+ -I$(top_srcdir)/ndb/src/mgmclient
-LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \
+LDADD_LOC = $(top_srcdir)/ndb/src/mgmclient/CommandInterpreter.o \
+ $(top_builddir)/ndb/src/libndbclient.la \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@
+ $(top_builddir)/strings/libmystrings.a \
+ @readline_link@ \
+ @NDB_SCI_LIBS@ \
@TERMCAP_LIB@
DEFS_LOC = -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index 56c24e5f862..d946b4af4a7 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -205,16 +205,16 @@ MgmtSrvr::logLevelThreadRun()
void
MgmtSrvr::startEventLog()
{
+ NdbMutex_Lock(m_configMutex);
+
g_eventLogger.setCategory("MgmSrvr");
- 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 ;
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
+
+ if(iter.find(CFG_NODE_ID, _ownNodeId) != 0){
+ NdbMutex_Unlock(m_configMutex);
+ return;
}
const char * tmp;
@@ -222,10 +222,10 @@ MgmtSrvr::startEventLog()
char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId);
NdbAutoPtr<char> tmp_aptr(clusterLog);
- if(ndb_mgm_get_string_parameter(iter, CFG_LOG_DESTINATION, &tmp) == 0){
+ if(iter.get(CFG_LOG_DESTINATION, &tmp) == 0){
logdest.assign(tmp);
}
- ndb_mgm_destroy_iterator(iter);
+ NdbMutex_Unlock(m_configMutex);
if(logdest.length() == 0 || logdest == "") {
logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6",
@@ -359,42 +359,41 @@ MgmtSrvr::getNodeCount(enum ndb_mgm_node_type type) const
}
int
-MgmtSrvr::getPort() const {
- const Properties *mgmProps;
-
- ndb_mgm_configuration_iterator * iter =
- ndb_mgm_create_configuration_iterator(_config->m_configValues,
- CFG_SECTION_NODE);
- if(iter == 0)
+MgmtSrvr::getPort() const
+{
+ if(NdbMutex_Lock(m_configMutex))
return 0;
- if(ndb_mgm_find(iter, CFG_NODE_ID, getOwnNodeId()) != 0){
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
+
+ if(iter.find(CFG_NODE_ID, getOwnNodeId()) != 0){
ndbout << "Could not retrieve configuration for Node "
<< getOwnNodeId() << " in config file." << endl
<< "Have you set correct NodeId for this node?" << endl;
- ndb_mgm_destroy_iterator(iter);
+ NdbMutex_Unlock(m_configMutex);
return 0;
}
unsigned type;
- if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0 ||
+ if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0 ||
type != NODE_TYPE_MGM){
ndbout << "Local node id " << getOwnNodeId()
<< " is not defined as management server" << endl
<< "Have you set correct NodeId for this node?" << endl;
- ndb_mgm_destroy_iterator(iter);
+ NdbMutex_Unlock(m_configMutex);
return 0;
}
Uint32 port = 0;
- if(ndb_mgm_get_int_parameter(iter, CFG_MGM_PORT, &port) != 0){
+ if(iter.get(CFG_MGM_PORT, &port) != 0){
ndbout << "Could not find PortNumber in the configuration file." << endl;
- ndb_mgm_destroy_iterator(iter);
+ NdbMutex_Unlock(m_configMutex);
return 0;
}
- ndb_mgm_destroy_iterator(iter);
-
+ NdbMutex_Unlock(m_configMutex);
+
return port;
}
@@ -488,14 +487,14 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
{
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)){
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
+
+ for(iter.first(); iter.valid(); iter.next()){
unsigned type, id;
- if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0)
+ if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0)
continue;
- if(ndb_mgm_get_int_parameter(iter, CFG_NODE_ID, &id) != 0)
+ if(iter.get(CFG_NODE_ID, &id) != 0)
continue;
MGM_REQUIRE(id < MAX_NODES);
@@ -518,7 +517,6 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
break;
}
}
- ndb_mgm_destroy_iterator(iter);
}
_props = NULL;
@@ -594,7 +592,8 @@ MgmtSrvr::start(BaseString &error_string)
DBUG_RETURN(false);
}
}
- theFacade= TransporterFacade::theFacadeInstance= new TransporterFacade();
+ theFacade= TransporterFacade::theFacadeInstance
+ = new TransporterFacade();
if(theFacade == 0) {
DEBUG("MgmtSrvr.cpp: theFacade is NULL.");
@@ -622,7 +621,26 @@ MgmtSrvr::start(BaseString &error_string)
theFacade = 0;
DBUG_RETURN(false);
}
-
+
+ TransporterRegistry *reg = theFacade->get_registry();
+ for(unsigned int i=0;i<reg->m_transporter_interface.size();i++) {
+ BaseString msg;
+ DBUG_PRINT("info",("Setting dynamic port %d->%d : %d",
+ reg->get_localNodeId(),
+ reg->m_transporter_interface[i].m_remote_nodeId,
+ reg->m_transporter_interface[i].m_s_service_port
+ )
+ );
+ int res = setConnectionDbParameter((int)reg->get_localNodeId(),
+ (int)reg->m_transporter_interface[i]
+ .m_remote_nodeId,
+ (int)CFG_CONNECTION_SERVER_PORT,
+ reg->m_transporter_interface[i]
+ .m_s_service_port,
+ msg);
+ DBUG_PRINT("info",("Set result: %d: %s",res,msg.c_str()));
+ }
+
_ownReference = numberToRef(_blockNumber, _ownNodeId);
startEventLog();
@@ -1890,8 +1908,6 @@ void
MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
{
// The way of handling a received signal is taken from the Ndb class.
- int returnCode;
-
int gsn = signal->readSignalNumber();
switch (gsn) {
@@ -2022,9 +2038,9 @@ MgmtSrvr::handleStatus(NodeId nodeId, bool alive, bool nfComplete)
theData[1] = nodeId;
if (alive) {
m_started_nodes.push_back(nodeId);
- theData[0] = EventReport::Connected;
+ theData[0] = NDB_LE_Connected;
} else {
- theData[0] = EventReport::Disconnected;
+ theData[0] = NDB_LE_Disconnected;
if(nfComplete)
{
handleStopReply(nodeId, 0);
@@ -2104,10 +2120,7 @@ MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const
if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB)
{
const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i);
- if (node.connected)
- {
- connected_nodes.bitOR(node.m_state.m_connected_nodes);
- }
+ connected_nodes.bitOR(node.m_state.m_connected_nodes);
}
}
}
@@ -2149,8 +2162,13 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
int r_config_addr= -1;
unsigned type_c= 0;
+ if(NdbMutex_Lock(m_configMutex))
+ {
+ error_string.appfmt("unable to lock configuration mutex");
+ return false;
+ }
ndb_mgm_configuration_iterator
- iter(*(ndb_mgm_configuration *)_config->m_configValues, CFG_SECTION_NODE);
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
for(iter.first(); iter.valid(); iter.next()) {
unsigned tmp= 0;
if(iter.get(CFG_NODE_ID, &tmp)) require(false);
@@ -2217,6 +2235,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
"Suggest specifying node id in connectstring,\n"
"or specifying unique host names in config file.",
id_found, tmp);
+ NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(false);
}
if (config_hostname == 0) {
@@ -2229,6 +2248,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
}
id_found= tmp; // mgmt server matched, check for more matches
}
+ NdbMutex_Unlock(m_configMutex);
if (id_found)
{
@@ -2371,7 +2391,7 @@ MgmtSrvr::eventReport(NodeId nodeId, const Uint32 * theData)
{
const EventReport * const eventReport = (EventReport *)&theData[0];
- EventReport::EventType type = eventReport->getEventType();
+ Ndb_logevent_type type = eventReport->getEventType();
// Log event
g_eventLogger.log(type, theData, nodeId,
&m_event_listner[0].m_logLevel);
@@ -2622,13 +2642,18 @@ MgmtSrvr::Allocated_resources::get_nodeid() const
int
MgmtSrvr::setDbParameter(int node, int param, const char * value,
BaseString& msg){
+
+ if(NdbMutex_Lock(m_configMutex))
+ return -1;
+
/**
* Check parameter
*/
- ndb_mgm_configuration_iterator iter(* _config->m_configValues,
- CFG_SECTION_NODE);
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
if(iter.first() != 0){
msg.assign("Unable to find node section (iter.first())");
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
@@ -2636,16 +2661,19 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
if(node != 0){
if(iter.find(CFG_NODE_ID, node) != 0){
msg.assign("Unable to find node (iter.find())");
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
} else {
do {
if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
if(type == NODE_TYPE_DB)
@@ -2656,6 +2684,7 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
if(type != NODE_TYPE_DB){
msg.assfmt("Invalid node type or no such node (%d %d)",
type, NODE_TYPE_DB);
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
@@ -2681,6 +2710,7 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
break;
}
msg.assign("Could not get parameter");
+ NdbMutex_Unlock(m_configMutex);
return -1;
} while(0);
@@ -2718,9 +2748,144 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
} while(node == 0 && iter.next() == 0);
msg.assign("Success");
+ NdbMutex_Unlock(m_configMutex);
return 0;
}
+int
+MgmtSrvr::setConnectionDbParameter(int node1,
+ int node2,
+ int param,
+ int value,
+ BaseString& msg){
+ Uint32 current_value,new_value;
+
+ DBUG_ENTER("MgmtSrvr::setConnectionDbParameter");
+
+ if(NdbMutex_Lock(m_configMutex))
+ {
+ DBUG_RETURN(-1);
+ }
+
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
+
+ if(iter.first() != 0){
+ msg.assign("Unable to find connection section (iter.first())");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-1);
+ }
+
+ for(;iter.valid();iter.next()) {
+ Uint32 n1,n2;
+ iter.get(CFG_CONNECTION_NODE_1, &n1);
+ iter.get(CFG_CONNECTION_NODE_2, &n2);
+ if((n1 == (unsigned)node1 && n2 == (unsigned)node2)
+ || (n1 == (unsigned)node2 && n2 == (unsigned)node1))
+ break;
+ }
+ if(!iter.valid()) {
+ msg.assign("Unable to find connection between nodes");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-2);
+ }
+
+ if(iter.get(param, &current_value) != 0) {
+ msg.assign("Unable to get current value of parameter");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-3);
+ }
+
+ ConfigValues::Iterator i2(_config->m_configValues->m_config,
+ iter.m_config);
+
+ if(i2.set(param, (unsigned)value) == false) {
+ msg.assign("Unable to set new value of parameter");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-4);
+ }
+
+ if(iter.get(param, &new_value) != 0) {
+ msg.assign("Unable to get parameter after setting it.");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-5);
+ }
+
+ msg.assfmt("%u -> %u",current_value,new_value);
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(1);
+}
+
+
+int
+MgmtSrvr::getConnectionDbParameter(int node1,
+ int node2,
+ int param,
+ int *value,
+ BaseString& msg){
+ DBUG_ENTER("MgmtSrvr::getConnectionDbParameter");
+
+ if(NdbMutex_Lock(m_configMutex))
+ {
+ DBUG_RETURN(-1);
+ }
+
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
+
+ if(iter.first() != 0){
+ msg.assign("Unable to find connection section (iter.first())");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-1);
+ }
+
+ for(;iter.valid();iter.next()) {
+ Uint32 n1=0,n2=0;
+ iter.get(CFG_CONNECTION_NODE_1, &n1);
+ iter.get(CFG_CONNECTION_NODE_2, &n2);
+ if((n1 == (unsigned)node1 && n2 == (unsigned)node2)
+ || (n1 == (unsigned)node2 && n2 == (unsigned)node1))
+ break;
+ }
+ if(!iter.valid()) {
+ msg.assign("Unable to find connection between nodes");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-1);
+ }
+
+ if(iter.get(param, (Uint32*)value) != 0) {
+ msg.assign("Unable to get current value of parameter");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-1);
+ }
+
+ msg.assfmt("%d",*value);
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(1);
+}
+
+void MgmtSrvr::transporter_connect(NDB_SOCKET_TYPE sockfd)
+{
+ if (theFacade->get_registry()->connect_server(sockfd))
+ {
+ /**
+ * Force an update_connections() so that the
+ * ClusterMgr and TransporterFacade is up to date
+ * with the new connection.
+ * Important for correct node id reservation handling
+ */
+ NdbMutex_Lock(theFacade->theMutexPtr);
+ theFacade->get_registry()->update_connections();
+ NdbMutex_Unlock(theFacade->theMutexPtr);
+ }
+}
+
+int MgmtSrvr::set_connect_string(const char *str)
+{
+ return ndb_mgm_set_connectstring(m_config_retriever->get_mgmHandle(),str);
+}
+
+
template class Vector<SigMatch>;
#if __SUNPRO_CC != 0x560
template bool SignalQueue::waitFor<SigMatch>(Vector<SigMatch>&, SigMatch**, NdbApiSignal**, unsigned);
diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp
index f8c244a1bf1..de1af1286ff 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -49,6 +49,7 @@ class Ndb_mgmd_event_service : public EventLoggerBase
public:
struct Event_listener : public EventLoggerBase {
NDB_SOCKET_TYPE m_socket;
+ Uint32 m_parsable;
};
private:
@@ -508,7 +509,17 @@ public:
int getPort() const;
int setDbParameter(int node, int parameter, const char * value, BaseString&);
-
+ int setConnectionDbParameter(int node1, int node2, int param, int value,
+ BaseString& msg);
+ int getConnectionDbParameter(int node1, int node2, int param,
+ int *value, BaseString& msg);
+
+ int set_connect_string(const char *str);
+
+ void transporter_connect(NDB_SOCKET_TYPE sockfd);
+
+ ConfigRetriever *get_config_retriever() { return m_config_retriever; };
+
const char *get_connect_address(Uint32 node_id);
void get_connected_nodes(NodeBitmask &connected_nodes) const;
SocketServer *get_socket_server() { return m_socket_server; }
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 46bfb531b61..ed32ab9c963 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -31,6 +31,7 @@
#include <mgmapi_configuration.hpp>
#include <Vector.hpp>
#include "Services.hpp"
+#include "../mgmapi/ndb_logevent.hpp"
extern bool g_StopServer;
@@ -241,14 +242,32 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("parameter", String, Mandatory, "Parameter"),
MGM_ARG("value", String, Mandatory, "Value"),
+ MGM_CMD("set connection parameter",
+ &MgmApiSession::setConnectionParameter, ""),
+ MGM_ARG("node1", String, Mandatory, "Node1 ID"),
+ MGM_ARG("node2", String, Mandatory, "Node2 ID"),
+ MGM_ARG("param", String, Mandatory, "Parameter"),
+ MGM_ARG("value", String, Mandatory, "Value"),
+
+ MGM_CMD("get connection parameter",
+ &MgmApiSession::getConnectionParameter, ""),
+ MGM_ARG("node1", String, Mandatory, "Node1 ID"),
+ MGM_ARG("node2", String, Mandatory, "Node2 ID"),
+ MGM_ARG("param", String, Mandatory, "Parameter"),
+
MGM_CMD("listen event", &MgmApiSession::listen_event, ""),
MGM_ARG("node", Int, Optional, "Node"),
+ MGM_ARG("parsable", Int, Optional, "Parsable"),
MGM_ARG("filter", String, Mandatory, "Event category"),
MGM_CMD("purge stale sessions", &MgmApiSession::purge_stale_sessions, ""),
MGM_CMD("check connection", &MgmApiSession::check_connection, ""),
+ MGM_CMD("transporter connect", &MgmApiSession::transporter_connect, ""),
+
+ MGM_CMD("get mgmd nodeid", &MgmApiSession::get_mgmd_nodeid, ""),
+
MGM_END()
};
@@ -571,11 +590,13 @@ MgmApiSession::getConfig_common(Parser_t::Context &,
}
}
+ NdbMutex_Lock(m_mgmsrv.m_configMutex);
const ConfigValues * cfg = &conf->m_configValues->m_config;
const Uint32 size = cfg->getPackedSize();
UtilBuffer src;
cfg->pack(src);
+ NdbMutex_Unlock(m_mgmsrv.m_configMutex);
BaseString str;
int res = base64_encode(src, str);
@@ -666,7 +687,8 @@ MgmApiSession::startBackup(Parser<MgmApiSession>::Context &,
}
else{
m_output->println("result: Ok");
- m_output->println("id: %d", backupId);
+ if (completed)
+ m_output->println("id: %d", backupId);
}
m_output->println("");
DBUG_VOID_RETURN;
@@ -1187,13 +1209,13 @@ MgmApiSession::startAll(Parser<MgmApiSession>::Context &,
void
MgmApiSession::setLogFilter(Parser_t::Context &ctx,
const class Properties &args) {
- Uint32 level;
+ Uint32 severity;
Uint32 enable;
- args.get("level", &level);
+ args.get("level", &severity);
args.get("enable", &enable);
- int result = m_mgmsrv.setEventLogFilter(level, enable);
+ int result = m_mgmsrv.setEventLogFilter(severity, enable);
m_output->println("set logfilter reply");
m_output->println("result: %d", result);
@@ -1252,28 +1274,52 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId)
Uint32 threshold;
LogLevel::EventCategory cat;
Logger::LoggerLevel severity;
+ EventLoggerBase::EventTextFunction textF;
int i, n;
DBUG_ENTER("Ndb_mgmd_event_service::log");
DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId));
- if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity))
+ if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity,textF))
DBUG_VOID_RETURN;
char m_text[256];
- EventLogger::getText(m_text, sizeof(m_text), eventType, theData, nodeId);
+ EventLogger::getText(m_text, sizeof(m_text),
+ textF, theData, nodeId);
+
+ BaseString str("log event reply\n");
+ str.appfmt("type=%d\n", eventType);
+ str.appfmt("time=%d\n", 0);
+ str.appfmt("source_nodeid=%d\n", nodeId);
+ for (i= 0; ndb_logevent_body[i].token; i++)
+ {
+ if ( ndb_logevent_body[i].type != eventType)
+ continue;
+ int val= theData[ndb_logevent_body[i].index];
+ if (ndb_logevent_body[i].index_fn)
+ val= (*(ndb_logevent_body[i].index_fn))(val);
+ str.appfmt("%s=%d\n",ndb_logevent_body[i].token, val);
+ }
- Vector<NDB_SOCKET_TYPE> copy;
+ Vector<NDB_SOCKET_TYPE> copy;
m_clients.lock();
for(i = m_clients.size() - 1; i >= 0; i--)
{
if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat))
{
- int fd= m_clients[i].m_socket;
- if(fd != NDB_INVALID_SOCKET &&
- println_socket(fd, MAX_WRITE_TIMEOUT, m_text) == -1)
+ NDB_SOCKET_TYPE fd= m_clients[i].m_socket;
+ if(fd != NDB_INVALID_SOCKET)
{
- copy.push_back(fd);
- m_clients.erase(i, false);
+ int r;
+ if (m_clients[i].m_parsable)
+ r= println_socket(fd,
+ MAX_WRITE_TIMEOUT, str.c_str());
+ else
+ r= println_socket(fd,
+ MAX_WRITE_TIMEOUT, m_text);
+ if (r == -1) {
+ copy.push_back(fd);
+ m_clients.erase(i, false);
+ }
}
}
}
@@ -1392,17 +1438,64 @@ MgmApiSession::setParameter(Parser_t::Context &,
}
void
+MgmApiSession::setConnectionParameter(Parser_t::Context &ctx,
+ Properties const &args) {
+ BaseString node1, node2, param, value;
+ args.get("node1", node1);
+ args.get("node2", node2);
+ args.get("param", param);
+ args.get("value", value);
+
+ BaseString result;
+ int ret = m_mgmsrv.setConnectionDbParameter(atoi(node1.c_str()),
+ atoi(node2.c_str()),
+ atoi(param.c_str()),
+ atoi(value.c_str()),
+ result);
+
+ m_output->println("set connection parameter reply");
+ m_output->println("message: %s", result.c_str());
+ m_output->println("result: %s", (ret>0)?"Ok":"Failed");
+ m_output->println("");
+}
+
+void
+MgmApiSession::getConnectionParameter(Parser_t::Context &ctx,
+ Properties const &args) {
+ BaseString node1, node2, param;
+ int value = 0;
+
+ args.get("node1", node1);
+ args.get("node2", node2);
+ args.get("param", param);
+
+ BaseString result;
+ int ret = m_mgmsrv.getConnectionDbParameter(atoi(node1.c_str()),
+ atoi(node2.c_str()),
+ atoi(param.c_str()),
+ &value,
+ result);
+
+ m_output->println("get connection parameter reply");
+ m_output->println("value: %d", value);
+ m_output->println("result: %s", (ret>0)?"Ok":result.c_str());
+ m_output->println("");
+}
+
+void
MgmApiSession::listen_event(Parser<MgmApiSession>::Context & ctx,
Properties const & args) {
-
+ Uint32 parsable= 0;
BaseString node, param, value;
args.get("node", node);
args.get("filter", param);
+ args.get("parsable", &parsable);
int result = 0;
BaseString msg;
Ndb_mgmd_event_service::Event_listener le;
+ le.m_parsable = parsable;
le.m_socket = m_socket;
Vector<BaseString> list;
@@ -1509,6 +1602,25 @@ MgmApiSession::check_connection(Parser_t::Context &ctx,
m_output->println("");
}
+void
+MgmApiSession::transporter_connect(Parser_t::Context &ctx,
+ Properties const &args)
+{
+ m_mgmsrv.transporter_connect(m_socket);
+
+ m_stop= true;
+ m_stopped= true; // force a stop (no closing socket)
+ m_socket= NDB_INVALID_SOCKET; // so nobody closes it
+}
+
+void
+MgmApiSession::get_mgmd_nodeid(Parser_t::Context &ctx,
+ Properties const &args)
+{
+ m_output->println("get mgmd nodeid reply");
+ m_output->println("nodeid:%u",m_mgmsrv.getOwnNodeId());
+ m_output->println("");
+}
+
template class MutexVector<int>;
template class Vector<ParserRow<MgmApiSession> const*>;
-template class Vector<unsigned short>;
diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp
index 8627343b1cf..ff9008b05a8 100644
--- a/ndb/src/mgmsrv/Services.hpp
+++ b/ndb/src/mgmsrv/Services.hpp
@@ -88,10 +88,19 @@ public:
void configChange(Parser_t::Context &ctx, const class Properties &args);
void setParameter(Parser_t::Context &ctx, const class Properties &args);
+ void setConnectionParameter(Parser_t::Context &ctx,
+ const class Properties &args);
+ void getConnectionParameter(Parser_t::Context &ctx,
+ Properties const &args);
+
void listen_event(Parser_t::Context &ctx, const class Properties &args);
void purge_stale_sessions(Parser_t::Context &ctx, const class Properties &args);
void check_connection(Parser_t::Context &ctx, const class Properties &args);
+
+ void transporter_connect(Parser_t::Context &ctx, Properties const &args);
+
+ void get_mgmd_nodeid(Parser_t::Context &ctx, Properties const &args);
void repCommand(Parser_t::Context &ctx, const class Properties &args);
};
diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp
index 01845687ce1..ec20101493e 100644
--- a/ndb/src/mgmsrv/main.cpp
+++ b/ndb/src/mgmsrv/main.cpp
@@ -40,7 +40,7 @@
#if defined NDB_OSE || defined NDB_SOFTOSE
#include <efs.h>
#else
-#include "CommandInterpreter.hpp"
+#include <ndb_mgmclient.hpp>
#endif
#undef DEBUG
@@ -48,11 +48,55 @@
const char progname[] = "mgmtsrvr";
+// copied from mysql.cc to get readline
+extern "C" {
+#if defined( __WIN__) || defined(OS2)
+#include <conio.h>
+#elif !defined(__NETWARE__)
+#include <readline/readline.h>
+extern "C" int add_history(const char *command); /* From readline directory */
+#define HAVE_READLINE
+#endif
+}
+
+static int
+read_and_execute(Ndb_mgmclient* com, const char * prompt, int _try_reconnect)
+{
+ static char *line_read = (char *)NULL;
+
+ /* If the buffer has already been allocated, return the memory
+ to the free pool. */
+ if (line_read)
+ {
+ free (line_read);
+ line_read = (char *)NULL;
+ }
+#ifdef HAVE_READLINE
+ /* Get a line from the user. */
+ line_read = readline (prompt);
+ /* If the line has any text in it, save it on the history. */
+ if (line_read && *line_read)
+ add_history (line_read);
+#else
+ static char linebuffer[254];
+ fputs(prompt, stdout);
+ linebuffer[sizeof(linebuffer)-1]=0;
+ line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
+ if (line_read == linebuffer) {
+ char *q=linebuffer;
+ while (*q > 31) q++;
+ *q=0;
+ line_read= strdup(linebuffer);
+ }
+#endif
+ return com->execute(line_read,_try_reconnect);
+}
/**
* @struct MgmGlobals
* @brief Global Variables used in the management server
- ******************************************************************************/
+ *****************************************************************************/
+
/** Command line arguments */
static int opt_daemon; // NOT bool, bool need not be int
static int opt_non_interactive;
@@ -67,7 +111,7 @@ struct MgmGlobals {
NodeId localNodeId;
bool use_specific_ip;
char * interface_name;
- int port;
+ short unsigned int port;
/** The Mgmt Server */
MgmtSrvr * mgmObject;
@@ -98,13 +142,6 @@ enum ndb_mgmd_options {
};
NDB_STD_OPTS_VARS;
-#if NDB_VERSION_MAJOR <= 4
-#undef OPT_NDB_CONNECTSTRING
-#define OPT_NDB_CONNECTSTRING 1023
-#else
-
-#endif
-
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_mgmd"),
@@ -129,15 +166,9 @@ static struct my_option my_long_options[] =
"Don't run as daemon, but don't read from stdin",
(gptr*) &opt_non_interactive, (gptr*) &opt_non_interactive, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
-#if NDB_VERSION_MAJOR <= 4
- { "config-file", 'c',
- "-c provided for backwards compatability, will be removed in 5.0."
- " Use -f instead",
- (gptr*) &opt_config_filename, (gptr*) &opt_config_filename, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-#endif
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
+
static void short_usage_sub(void)
{
printf("Usage: %s [OPTIONS]\n", my_progname);
@@ -149,21 +180,6 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_mgmd.trace");
-#if NDB_VERSION_MAJOR <= 4
- switch (optid) {
- case 'c':
- printf("Warning: -c will be removed in 5.0, use -f instead\n");
- break;
- }
-#endif
- return 0;
-}
/*
* MAIN
@@ -188,7 +204,11 @@ int main(int argc, char** argv)
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_mgmd.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
exit(ho_error);
if (opt_interactive ||
@@ -244,7 +264,8 @@ int main(int argc, char** argv)
glob->interface_name = 0;
}
- if(!glob->socketServer->setup(mapi, glob->port, glob->interface_name)){
+ if(!glob->socketServer->setup(mapi, &glob->port, glob->interface_name))
+ {
ndbout_c("Unable to setup management port: %d!\n"
"Please check if the port is already used,\n"
"(perhaps a ndb_mgmd is already running),\n"
@@ -253,13 +274,35 @@ int main(int argc, char** argv)
delete mapi;
goto error_end;
}
-
+
+ /* Construct a fake connectstring to connect back to ourselves */
+ char connect_str[20];
+ if(!opt_connect_str) {
+ snprintf(connect_str,20,"localhost:%u",glob->mgmObject->getPort());
+ opt_connect_str= connect_str;
+ }
+ glob->mgmObject->set_connect_string(opt_connect_str);
+
if(!glob->mgmObject->check_start()){
ndbout_c("Unable to check start management server.");
ndbout_c("Probably caused by illegal initial configuration file.");
goto error_end;
}
+ /*
+ * Connect back to ourselves so we can use mgmapi to fetch
+ * config info
+ */
+ int mgm_connect_result;
+ mgm_connect_result = glob->mgmObject->get_config_retriever()->
+ do_connect(0,0,0);
+
+ if(mgm_connect_result<0) {
+ ndbout_c("Unable to connect to our own ndb_mgmd (Error %d)",
+ mgm_connect_result);
+ ndbout_c("This is probably a bug.");
+ }
+
if (opt_daemon) {
// Become a daemon
char *lockfile= NdbConfig_PidFileName(glob->localNodeId);
@@ -304,17 +347,23 @@ int main(int argc, char** argv)
#if ! defined NDB_OSE && ! defined NDB_SOFTOSE
if(opt_interactive) {
- CommandInterpreter com(* glob->mgmObject);
- while(com.readAndExecute());
+ BaseString con_str;
+ if(glob->interface_name)
+ con_str.appfmt("host=%s:%d", glob->interface_name, glob->port);
+ else
+ con_str.appfmt("localhost:%d", glob->port);
+ Ndb_mgmclient com(con_str.c_str(), 1);
+ while(g_StopServer != true && read_and_execute(&com, "ndb_mgm> ", 1));
} else
#endif
- {
- while(g_StopServer != true)
- NdbSleep_MilliSleep(500);
- }
+ {
+ while(g_StopServer != true)
+ NdbSleep_MilliSleep(500);
+ }
g_eventLogger.info("Shutting down server...");
glob->socketServer->stopServer();
+ glob->mgmObject->get_config_retriever()->disconnect();
glob->socketServer->stopSessions(true);
g_eventLogger.info("Shutdown complete");
the_end:
diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp
index 543bdf1155e..42b7c5b115d 100644
--- a/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/ndb/src/ndbapi/ClusterMgr.cpp
@@ -214,7 +214,7 @@ ClusterMgr::threadMain( ){
* It is now time to send a new Heartbeat
*/
if (theNode.hbCounter >= theNode.hbFrequency) {
- theNode.hbSent++;
+ theNode.m_info.m_heartbeat_cnt++;
theNode.hbCounter = 0;
}
@@ -231,7 +231,7 @@ ClusterMgr::threadMain( ){
theFacade.sendSignalUnCond(&signal, nodeId);
}//if
- if (theNode.hbSent == 4 && theNode.hbFrequency > 0){
+ if (theNode.m_info.m_heartbeat_cnt == 4 && theNode.hbFrequency > 0){
reportNodeFailed(i);
}//if
}
@@ -265,6 +265,7 @@ ClusterMgr::Node::Node()
: m_state(NodeState::SL_NOTHING) {
compatible = nfCompleteRep = true;
connected = defined = m_alive = false;
+ m_state.m_connected_nodes.clear();
}
/******************************************************************************
@@ -336,7 +337,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
node.compatible = ndbCompatible_api_ndb(NDB_VERSION,
node.m_info.m_version);
}
-
+
node.m_state = apiRegConf->nodeState;
if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED ||
node.m_state.startLevel == NodeState::SL_SINGLEUSER)){
@@ -344,7 +345,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
} else {
set_node_alive(node, false);
}//if
- node.hbSent = 0;
+ node.m_info.m_heartbeat_cnt = 0;
node.hbCounter = 0;
if (node.m_info.m_type != NodeInfo::REP) {
node.hbFrequency = (apiRegConf->apiHeartbeatFrequency * 10) - 50;
@@ -413,9 +414,15 @@ ClusterMgr::reportConnected(NodeId nodeId){
Node & theNode = theNodes[nodeId];
theNode.connected = true;
- theNode.hbSent = 0;
+ theNode.m_info.m_heartbeat_cnt = 0;
theNode.hbCounter = 0;
-
+
+ /**
+ * make sure the node itself is marked connected even
+ * if first API_REGCONF has not arrived
+ */
+ theNode.m_state.m_connected_nodes.set(nodeId);
+
if (theNode.m_info.m_type != NodeInfo::REP) {
theNode.hbFrequency = 0;
}
@@ -433,7 +440,9 @@ ClusterMgr::reportDisconnected(NodeId nodeId){
noOfConnectedNodes--;
theNodes[nodeId].connected = false;
- theNodes[nodeId].m_info.m_connectCount ++;
+
+ theNodes[nodeId].m_state.m_connected_nodes.clear();
+
reportNodeFailed(nodeId);
}
@@ -443,19 +452,23 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){
Node & theNode = theNodes[nodeId];
set_node_alive(theNode, false);
+ theNode.m_info.m_connectCount ++;
+
if(theNode.connected)
+ {
theFacade.doDisconnect(nodeId);
-
+ }
const bool report = (theNode.m_state.startLevel != NodeState::SL_NOTHING);
theNode.m_state.startLevel = NodeState::SL_NOTHING;
- if(report){
+ if(report)
+ {
theFacade.ReportNodeDead(nodeId);
- }
-
- theNode.nfCompleteRep = false;
+ }
- if(noOfAliveNodes == 0){
+ theNode.nfCompleteRep = false;
+ if(noOfAliveNodes == 0)
+ {
NFCompleteRep rep;
for(Uint32 i = 1; i<MAX_NODES; i++){
if(theNodes[i].defined && theNodes[i].nfCompleteRep == false){
diff --git a/ndb/src/ndbapi/ClusterMgr.hpp b/ndb/src/ndbapi/ClusterMgr.hpp
index d75b820e9cb..da8f16d6789 100644
--- a/ndb/src/ndbapi/ClusterMgr.hpp
+++ b/ndb/src/ndbapi/ClusterMgr.hpp
@@ -73,12 +73,12 @@ public:
*/
Uint32 hbFrequency; // Heartbeat frequence
Uint32 hbCounter; // # milliseconds passed since last hb sent
- Uint32 hbSent; // # heartbeats sent (without answer)
};
const Node & getNodeInfo(NodeId) const;
Uint32 getNoOfConnectedNodes() const;
-
+ void hb_received(NodeId);
+
private:
Uint32 noOfAliveNodes;
Uint32 noOfConnectedNodes;
@@ -128,6 +128,12 @@ ClusterMgr::getNoOfConnectedNodes() const {
return noOfConnectedNodes;
}
+inline
+void
+ClusterMgr::hb_received(NodeId nodeId) {
+ theNodes[nodeId].m_info.m_heartbeat_cnt= 0;
+}
+
/*****************************************************************************/
/**
diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp
index ca361e900b1..57d9b361522 100644
--- a/ndb/src/ndbapi/DictCache.cpp
+++ b/ndb/src/ndbapi/DictCache.cpp
@@ -83,11 +83,14 @@ LocalDictCache::drop(const char * name){
* Global cache
*/
GlobalDictCache::GlobalDictCache(){
+ DBUG_ENTER("GlobalDictCache::GlobalDictCache");
m_tableHash.createHashTable();
m_waitForTableCondition = NdbCondition_Create();
+ DBUG_VOID_RETURN;
}
GlobalDictCache::~GlobalDictCache(){
+ DBUG_ENTER("GlobalDictCache::~GlobalDictCache");
NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0);
while(curr != 0){
Vector<TableVersion> * vers = curr->theData;
@@ -97,20 +100,52 @@ GlobalDictCache::~GlobalDictCache(){
delete (* vers)[i].m_impl;
}
delete curr->theData;
+ curr->theData= NULL;
curr = m_tableHash.getNext(curr);
}
-
m_tableHash.releaseHashTable();
NdbCondition_Destroy(m_waitForTableCondition);
+ DBUG_VOID_RETURN;
}
-#include <NdbOut.hpp>
+void GlobalDictCache::printCache()
+{
+ DBUG_ENTER("GlobalDictCache::printCache");
+ NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0);
+ while(curr != 0){
+ DBUG_PRINT("curr", ("len: %d, hash: %d, lk: %d, str: %s",
+ curr->len, curr->hash, curr->localkey1, curr->str));
+ if (curr->theData){
+ Vector<TableVersion> * vers = curr->theData;
+ const unsigned sz = vers->size();
+ for(unsigned i = 0; i<sz ; i++){
+ TableVersion tv= (*vers)[i];
+ DBUG_PRINT(" ", ("vers[%d]: ver: %d, refCount: %d, status: %d",
+ sz, tv.m_version, tv.m_refCount, tv.m_status));
+ if(tv.m_impl != 0)
+ {
+ DBUG_PRINT(" ", ("m_impl: internalname: %s",
+ tv.m_impl->m_internalName.c_str()));
+ }
+ }
+ }
+ else
+ {
+ DBUG_PRINT(" ", ("NULL"));
+ }
+ curr = m_tableHash.getNext(curr);
+ }
+ DBUG_VOID_RETURN;
+}
-NdbTableImpl *
+NdbTableImpl *
GlobalDictCache::get(const char * name)
{
+ DBUG_ENTER("GlobalDictCache::get");
+ DBUG_PRINT("enter", ("name: %s", name));
+
const Uint32 len = strlen(name);
- Vector<TableVersion> * versions = 0;
+ Vector<TableVersion> * versions = 0;
versions = m_tableHash.getData(name, len);
if(versions == 0){
versions = new Vector<TableVersion>(2);
@@ -125,7 +160,7 @@ GlobalDictCache::get(const char * name)
switch(ver->m_status){
case OK:
ver->m_refCount++;
- return ver->m_impl;
+ DBUG_RETURN(ver->m_impl);
case DROPPED:
retreive = true; // Break loop
break;
@@ -144,24 +179,28 @@ GlobalDictCache::get(const char * name)
tmp.m_status = RETREIVING;
tmp.m_refCount = 1; // The one retreiving it
versions->push_back(tmp);
- return 0;
+ DBUG_RETURN(0);
}
NdbTableImpl *
GlobalDictCache::put(const char * name, NdbTableImpl * tab)
{
+ DBUG_ENTER("GlobalDictCache::put");
+ DBUG_PRINT("enter", ("name: %s, internal_name: %s",
+ name, tab ? tab->m_internalName.c_str() : "tab NULL"));
+
const Uint32 len = strlen(name);
Vector<TableVersion> * vers = m_tableHash.getData(name, len);
if(vers == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
const Uint32 sz = vers->size();
if(sz == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
@@ -176,7 +215,7 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab)
if(tab == 0)
{
- // No table found in db
+ DBUG_PRINT("info", ("No table found in db"));
vers->erase(sz - 1);
}
else if (ver.m_impl == 0) {
@@ -203,74 +242,84 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab)
abort();
}
NdbCondition_Broadcast(m_waitForTableCondition);
- return tab;
+ DBUG_RETURN(tab);
}
void
GlobalDictCache::drop(NdbTableImpl * tab)
{
+ DBUG_ENTER("GlobalDictCache::drop");
+ DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
+
unsigned i;
const Uint32 len = strlen(tab->m_internalName.c_str());
Vector<TableVersion> * vers =
m_tableHash.getData(tab->m_internalName.c_str(), len);
if(vers == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
const Uint32 sz = vers->size();
if(sz == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
-
+
for(i = 0; i < sz; i++){
TableVersion & ver = (* vers)[i];
if(ver.m_impl == tab){
- if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
+ if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
ver.m_version != tab->m_version){
- ndbout_c("Dropping with refCount=%d status=%d impl=%p",
- ver.m_refCount, ver.m_status, ver.m_impl);
+ DBUG_PRINT("info", ("Dropping with refCount=%d status=%d impl=%p",
+ ver.m_refCount, ver.m_status, ver.m_impl));
break;
}
-
+ DBUG_PRINT("info", ("Found table to drop, i: %d, name: %s",
+ i, ver.m_impl->m_internalName.c_str()));
ver.m_refCount--;
ver.m_status = DROPPED;
if(ver.m_refCount == 0){
+ DBUG_PRINT("info", ("refCount is zero, deleting m_impl"))
delete ver.m_impl;
vers->erase(i);
}
- return;
+ DBUG_VOID_RETURN;
}
}
-
+
for(i = 0; i<sz; i++){
TableVersion & ver = (* vers)[i];
- ndbout_c("%d: version: %d refCount: %d status: %d impl: %p",
- i, ver.m_version, ver.m_refCount, ver.m_status, ver.m_impl);
+ DBUG_PRINT("info", ("%d: version: %d refCount: %d status: %d impl: %p",
+ i, ver.m_version, ver.m_refCount,
+ ver.m_status, ver.m_impl));
}
abort();
}
void
-GlobalDictCache::release(NdbTableImpl * tab){
+GlobalDictCache::release(NdbTableImpl * tab)
+{
+ DBUG_ENTER("GlobalDictCache::release");
+ DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
+
unsigned i;
const Uint32 len = strlen(tab->m_internalName.c_str());
Vector<TableVersion> * vers =
m_tableHash.getData(tab->m_internalName.c_str(), len);
if(vers == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
const Uint32 sz = vers->size();
if(sz == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
@@ -279,20 +328,21 @@ GlobalDictCache::release(NdbTableImpl * tab){
if(ver.m_impl == tab){
if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
ver.m_version != tab->m_version){
- ndbout_c("Releasing with refCount=%d status=%d impl=%p",
- ver.m_refCount, ver.m_status, ver.m_impl);
+ DBUG_PRINT("info", ("Releasing with refCount=%d status=%d impl=%p",
+ ver.m_refCount, ver.m_status, ver.m_impl));
break;
}
ver.m_refCount--;
- return;
+ DBUG_VOID_RETURN;
}
}
for(i = 0; i<sz; i++){
TableVersion & ver = (* vers)[i];
- ndbout_c("%d: version: %d refCount: %d status: %d impl: %p",
- i, ver.m_version, ver.m_refCount, ver.m_status, ver.m_impl);
+ DBUG_PRINT("info", ("%d: version: %d refCount: %d status: %d impl: %p",
+ i, ver.m_version, ver.m_refCount,
+ ver.m_status, ver.m_impl));
}
abort();
diff --git a/ndb/src/ndbapi/DictCache.hpp b/ndb/src/ndbapi/DictCache.hpp
index 7f2ee457476..2df6a139542 100644
--- a/ndb/src/ndbapi/DictCache.hpp
+++ b/ndb/src/ndbapi/DictCache.hpp
@@ -79,6 +79,8 @@ public:
};
private:
+ void printCache();
+
struct TableVersion {
Uint32 m_version;
Uint32 m_refCount;
diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am
index 1ba80ef7d85..99b75ffbd53 100644
--- a/ndb/src/ndbapi/Makefile.am
+++ b/ndb/src/ndbapi/Makefile.am
@@ -14,15 +14,14 @@ libndbapi_la_SOURCES = \
Ndberr.cpp \
ndberror.c \
NdbErrorOut.cpp \
- NdbConnection.cpp \
- NdbConnectionScan.cpp \
+ NdbTransaction.cpp \
+ NdbTransactionScan.cpp \
NdbOperation.cpp \
NdbOperationSearch.cpp \
NdbOperationScan.cpp \
NdbOperationInt.cpp \
NdbOperationDefine.cpp \
NdbOperationExec.cpp \
- NdbResultSet.cpp \
NdbScanOperation.cpp NdbScanFilter.cpp \
NdbIndexOperation.cpp \
NdbEventOperation.cpp \
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index 1ae1030e463..7893aaae15c 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -27,7 +27,7 @@ Name: Ndb.cpp
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
#include <NdbOperation.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbEventOperation.hpp>
#include <NdbRecAttr.hpp>
#include <md5_hash.hpp>
@@ -43,11 +43,13 @@ void connect();
Connect to any node which has no connection at the moment.
****************************************************************************/
-NdbConnection* Ndb::doConnect(Uint32 tConNode)
+NdbTransaction* Ndb::doConnect(Uint32 tConNode)
{
Uint32 tNode;
Uint32 tAnyAlive = 0;
- int TretCode;
+ int TretCode= 0;
+
+ DBUG_ENTER("Ndb::doConnect");
if (tConNode != 0) {
TretCode = NDB_connect(tConNode);
@@ -55,7 +57,7 @@ NdbConnection* Ndb::doConnect(Uint32 tConNode)
//****************************************************************************
// We have connections now to the desired node. Return
//****************************************************************************
- return getConnectedNdbConnection(tConNode);
+ DBUG_RETURN(getConnectedNdbTransaction(tConNode));
} else if (TretCode != 0) {
tAnyAlive = 1;
}//if
@@ -78,10 +80,13 @@ NdbConnection* Ndb::doConnect(Uint32 tConNode)
//****************************************************************************
// We have connections now to the desired node. Return
//****************************************************************************
- return getConnectedNdbConnection(tNode);
+ DBUG_RETURN(getConnectedNdbTransaction(tNode));
} else if (TretCode != 0) {
tAnyAlive= 1;
}//if
+ DBUG_PRINT("info",("tried node %d, TretCode %d, error code %d, %s",
+ tNode, TretCode, getNdbError().code,
+ getNdbError().message));
}
}
else // just do a regular round robin
@@ -103,10 +108,11 @@ NdbConnection* Ndb::doConnect(Uint32 tConNode)
//****************************************************************************
// We have connections now to the desired node. Return
//****************************************************************************
- return getConnectedNdbConnection(tNode);
+ DBUG_RETURN(getConnectedNdbTransaction(tNode));
} else if (TretCode != 0) {
tAnyAlive= 1;
}//if
+ DBUG_PRINT("info",("tried node %d TretCode %d", tNode, TretCode));
} while (Tcount < tNoOfDbNodes);
}
//****************************************************************************
@@ -121,7 +127,7 @@ NdbConnection* Ndb::doConnect(Uint32 tConNode)
} else {
theError.code = 4009;
}//if
- return NULL;
+ DBUG_RETURN(NULL);
}
int
@@ -134,36 +140,38 @@ Ndb::NDB_connect(Uint32 tNode)
int tReturnCode;
TransporterFacade *tp = TransporterFacade::instance();
+ DBUG_ENTER("Ndb::NDB_connect");
+
bool nodeAvail = tp->get_node_alive(tNode);
if(nodeAvail == false){
- return 0;
+ DBUG_RETURN(0);
}
- NdbConnection * tConArray = theConnectionArray[tNode];
+ NdbTransaction * tConArray = theConnectionArray[tNode];
if (tConArray != NULL) {
- return 2;
+ DBUG_RETURN(2);
}
- NdbConnection * tNdbCon = getNdbCon(); // Get free connection object.
+ NdbTransaction * tNdbCon = getNdbCon(); // Get free connection object.
if (tNdbCon == NULL) {
- return 4;
+ DBUG_RETURN(4);
}//if
NdbApiSignal* tSignal = getSignal(); // Get signal object
if (tSignal == NULL) {
releaseNdbCon(tNdbCon);
- return 4;
+ DBUG_RETURN(4);
}//if
if (tSignal->setSignal(GSN_TCSEIZEREQ) == -1) {
releaseNdbCon(tNdbCon);
releaseSignal(tSignal);
- return 4;
+ DBUG_RETURN(4);
}//if
tSignal->setData(tNdbCon->ptr2int(), 1);
//************************************************
-// Set connection pointer as NdbConnection object
+// Set connection pointer as NdbTransaction object
//************************************************
tSignal->setData(theMyRef, 2); // Set my block reference
- tNdbCon->Status(NdbConnection::Connecting); // Set status to connecting
+ tNdbCon->Status(NdbTransaction::Connecting); // Set status to connecting
Uint32 nodeSequence;
{ // send and receive signal
Guard guard(tp->theMutexPtr);
@@ -182,34 +190,37 @@ Ndb::NDB_connect(Uint32 tNode)
tReturnCode = -1;
}//if
}
- if ((tReturnCode == 0) && (tNdbCon->Status() == NdbConnection::Connected)) {
+ if ((tReturnCode == 0) && (tNdbCon->Status() == NdbTransaction::Connected)) {
//************************************************
// Send and receive was successful
//************************************************
- NdbConnection* tPrevFirst = theConnectionArray[tNode];
+ NdbTransaction* tPrevFirst = theConnectionArray[tNode];
tNdbCon->setConnectedNodeId(tNode, nodeSequence);
tNdbCon->setMyBlockReference(theMyRef);
theConnectionArray[tNode] = tNdbCon;
tNdbCon->theNext = tPrevFirst;
- return 1;
+ DBUG_RETURN(1);
} else {
releaseNdbCon(tNdbCon);
//****************************************************************************
// Unsuccessful connect is indicated by 3.
//****************************************************************************
- return 3;
+ DBUG_PRINT("info",
+ ("unsuccessful connect tReturnCode %d, tNdbCon->Status() %d",
+ tReturnCode, tNdbCon->Status()));
+ DBUG_RETURN(3);
}//if
}//Ndb::NDB_connect()
-NdbConnection *
-Ndb::getConnectedNdbConnection(Uint32 nodeId){
- NdbConnection* next = theConnectionArray[nodeId];
+NdbTransaction *
+Ndb::getConnectedNdbTransaction(Uint32 nodeId){
+ NdbTransaction* next = theConnectionArray[nodeId];
theConnectionArray[nodeId] = next->theNext;
next->theNext = NULL;
return next;
-}//Ndb::getConnectedNdbConnection()
+}//Ndb::getConnectedNdbTransaction()
/*****************************************************************************
disconnect();
@@ -219,9 +230,10 @@ Remark: Disconnect all connections to the database.
void
Ndb::doDisconnect()
{
- DBUG_ENTER("Ndb::doDisconnect");
- NdbConnection* tNdbCon;
+ NdbTransaction* tNdbCon;
CHECK_STATUS_MACRO_VOID;
+ /* DBUG_ENTER must be after CHECK_STATUS_MACRO_VOID because of 'return' */
+ DBUG_ENTER("Ndb::doDisconnect");
Uint32 tNoOfDbNodes = theImpl->theNoOfDBnodes;
Uint8 *theDBnodes= theImpl->theDBnodes;
@@ -231,14 +243,14 @@ Ndb::doDisconnect()
Uint32 tNode = theDBnodes[i];
tNdbCon = theConnectionArray[tNode];
while (tNdbCon != NULL) {
- NdbConnection* tmpNdbCon = tNdbCon;
+ NdbTransaction* tmpNdbCon = tNdbCon;
tNdbCon = tNdbCon->theNext;
releaseConnectToNdb(tmpNdbCon);
}//while
}//for
tNdbCon = theTransactionList;
while (tNdbCon != NULL) {
- NdbConnection* tmpNdbCon = tNdbCon;
+ NdbTransaction* tmpNdbCon = tNdbCon;
tNdbCon = tNdbCon->theNext;
releaseConnectToNdb(tmpNdbCon);
}//while
@@ -292,34 +304,58 @@ Ndb::waitUntilReady(int timeout)
}
/*****************************************************************************
-NdbConnection* startTransaction();
+NdbTransaction* startTransaction();
Return Value: Returns a pointer to a connection object.
Return NULL otherwise.
Remark: Start transaction. Synchronous.
*****************************************************************************/
-NdbConnection*
-Ndb::startTransaction(Uint32 aPriority, const char * keyData, Uint32 keyLen)
+NdbTransaction*
+Ndb::startTransaction(const NdbDictionary::Table *table,
+ const char * keyData, Uint32 keyLen)
{
DBUG_ENTER("Ndb::startTransaction");
if (theInitState == Initialised) {
theError.code = 0;
checkFailedNode();
- /**
- * If the user supplied key data
- * We will make a qualified quess to which node is the primary for the
- * the fragment and contact that node
- */
+ /**
+ * If the user supplied key data
+ * We will make a qualified quess to which node is the primary for the
+ * the fragment and contact that node
+ */
Uint32 nodeId;
- if(keyData != 0) {
- nodeId = 0; // guess not supported
- // nodeId = m_ndb_cluster_connection->guess_primary_node(keyData, keyLen);
+ NdbTableImpl* impl;
+ if(table != 0 && keyData != 0 && (impl= &NdbTableImpl::getImpl(*table)))
+ {
+ Uint32 hashValue;
+ {
+ Uint32 buf[4];
+ if((UintPtr(keyData) & 7) == 0 && (keyLen & 3) == 0)
+ {
+ md5_hash(buf, (const Uint64*)keyData, keyLen >> 2);
+ }
+ else
+ {
+ Uint64 tmp[1000];
+ tmp[keyLen/8] = 0;
+ memcpy(tmp, keyData, keyLen);
+ md5_hash(buf, tmp, (keyLen+3) >> 2);
+ }
+ hashValue= buf[1];
+ }
+ const Uint16 *nodes;
+ Uint32 cnt= impl->get_nodes(hashValue, &nodes);
+ if(cnt)
+ nodeId= nodes[0];
+ else
+ nodeId= 0;
} else {
nodeId = 0;
}//if
+
{
- NdbConnection *trans= startTransactionLocal(aPriority, nodeId);
+ NdbTransaction *trans= startTransactionLocal(0, nodeId);
DBUG_PRINT("exit",("start trans: 0x%x transid: 0x%llx",
trans, trans ? trans->getTransactionId() : 0));
DBUG_RETURN(trans);
@@ -330,15 +366,15 @@ Ndb::startTransaction(Uint32 aPriority, const char * keyData, Uint32 keyLen)
}//Ndb::startTransaction()
/*****************************************************************************
-NdbConnection* hupp(NdbConnection* pBuddyTrans);
+NdbTransaction* hupp(NdbTransaction* pBuddyTrans);
Return Value: Returns a pointer to a connection object.
Connected to the same node as pBuddyTrans
and also using the same transction id
Remark: Start transaction. Synchronous.
*****************************************************************************/
-NdbConnection*
-Ndb::hupp(NdbConnection* pBuddyTrans)
+NdbTransaction*
+Ndb::hupp(NdbTransaction* pBuddyTrans)
{
DBUG_ENTER("Ndb::hupp");
@@ -354,7 +390,7 @@ Ndb::hupp(NdbConnection* pBuddyTrans)
checkFailedNode();
Uint32 nodeId = pBuddyTrans->getConnectedNodeId();
- NdbConnection* pCon = startTransactionLocal(aPriority, nodeId);
+ NdbTransaction* pCon = startTransactionLocal(aPriority, nodeId);
if(pCon == NULL)
DBUG_RETURN(NULL);
@@ -375,8 +411,7 @@ Ndb::hupp(NdbConnection* pBuddyTrans)
}//if
}//Ndb::hupp()
-
-NdbConnection*
+NdbTransaction*
Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
{
#ifdef VM_TRACE
@@ -390,13 +425,21 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
DBUG_ENTER("Ndb::startTransactionLocal");
DBUG_PRINT("enter", ("nodeid: %d", nodeId));
- NdbConnection* tConnection;
+ if(unlikely(theRemainingStartTransactions == 0))
+ {
+ theError.code = 4006;
+ DBUG_RETURN(0);
+ }
+
+ NdbTransaction* tConnection;
Uint64 tFirstTransId = theFirstTransId;
tConnection = doConnect(nodeId);
if (tConnection == NULL) {
DBUG_RETURN(NULL);
}//if
- NdbConnection* tConNext = theTransactionList;
+
+ theRemainingStartTransactions--;
+ NdbTransaction* tConNext = theTransactionList;
tConnection->init();
theTransactionList = tConnection; // into a transaction list.
tConnection->next(tConNext); // Add the active connection object
@@ -412,7 +455,7 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
theFirstTransId = tFirstTransId + 1;
}//if
#ifdef VM_TRACE
- if (tConnection->theListState != NdbConnection::NotInList) {
+ if (tConnection->theListState != NdbTransaction::NotInList) {
printState("startTransactionLocal %x", tConnection);
abort();
}
@@ -421,17 +464,17 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
}//Ndb::startTransactionLocal()
/*****************************************************************************
-void closeTransaction(NdbConnection* aConnection);
+void closeTransaction(NdbTransaction* aConnection);
Parameters: aConnection: the connection used in the transaction.
Remark: Close transaction by releasing the connection and all operations.
*****************************************************************************/
void
-Ndb::closeTransaction(NdbConnection* aConnection)
+Ndb::closeTransaction(NdbTransaction* aConnection)
{
DBUG_ENTER("Ndb::closeTransaction");
- NdbConnection* tCon;
- NdbConnection* tPreviousCon;
+ NdbTransaction* tCon;
+ NdbTransaction* tPreviousCon;
if (aConnection == NULL) {
//-----------------------------------------------------
@@ -446,6 +489,7 @@ Ndb::closeTransaction(NdbConnection* aConnection)
CHECK_STATUS_MACRO_VOID;
tCon = theTransactionList;
+ theRemainingStartTransactions++;
DBUG_PRINT("info",("close trans: 0x%x transid: 0x%llx",
aConnection, aConnection->getTransactionId()));
@@ -464,12 +508,12 @@ Ndb::closeTransaction(NdbConnection* aConnection)
if(aConnection->theError.code == 4008){
/**
- * When a SCAN timed-out, returning the NdbConnection leads
+ * When a SCAN timed-out, returning the NdbTransaction leads
* to reuse. And TC crashes when the API tries to reuse it to
* something else...
*/
#ifdef VM_TRACE
- printf("Scan timeout:ed NdbConnection-> "
+ printf("Scan timeout:ed NdbTransaction-> "
"not returning it-> memory leak\n");
#endif
DBUG_VOID_RETURN;
@@ -491,12 +535,12 @@ Ndb::closeTransaction(NdbConnection* aConnection)
if(aConnection->theError.code == 4008){
/**
- * Something timed-out, returning the NdbConnection leads
+ * Something timed-out, returning the NdbTransaction leads
* to reuse. And TC crashes when the API tries to reuse it to
* something else...
*/
#ifdef VM_TRACE
- printf("Con timeout:ed NdbConnection-> not returning it-> memory leak\n");
+ printf("Con timeout:ed NdbTransaction-> not returning it-> memory leak\n");
#endif
DBUG_VOID_RETURN;
}
@@ -535,7 +579,7 @@ Remark: Sends a signal to DIH.
int
Ndb::NdbTamper(TamperType aAction, int aNode)
{
- NdbConnection* tNdbConn;
+ NdbTransaction* tNdbConn;
NdbApiSignal tSignal(theMyRef);
int tNode;
int tAction;
@@ -577,7 +621,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(NdbConnection::Connecting); // Set status to connecting
+ tNdbConn->Status(NdbTransaction::Connecting); // Set status to connecting
TransporterFacade *tp = TransporterFacade::instance();
if (tAction == 3) {
tp->lock_mutex();
@@ -610,7 +654,7 @@ Ndb::NdbTamper(TamperType aAction, int aNode)
}//if
ret_code = sendRecSignal(tNode, WAIT_NDB_TAMPER, &tSignal, 0);
if (ret_code == 0) {
- if (tNdbConn->Status() != NdbConnection::Connected) {
+ if (tNdbConn->Status() != NdbTransaction::Connected) {
theRestartGCI = 0;
}//if
releaseNdbCon(tNdbConn);
@@ -716,16 +760,14 @@ Remark: Returns a new TupleId to the application.
The TupleId comes from SYSTAB_0 where SYSKEY_0 = TableId.
It is initialized to (TableId << 48) + 1 in NdbcntrMain.cpp.
****************************************************************************/
-#define DEBUG_TRACE(msg) \
-// ndbout << __FILE__ << " line: " << __LINE__ << " msg: " << msg << endl
-
Uint64
Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize)
{
DBUG_ENTER("getAutoIncrementValue");
- const char * internalTableName = internalizeTableName(aTableName);
+ BaseString internal_tabname(internalize_table_name(aTableName));
+
Ndb_local_table_info *info=
- theDictionary->get_local_table_info(internalTableName, false);
+ theDictionary->get_local_table_info(internal_tabname, false);
if (info == 0)
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl *table= info->m_table_impl;
@@ -777,7 +819,7 @@ Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize)
Uint64
Ndb::readAutoIncrementValue(const char* aTableName)
{
- DBUG_ENTER("readtAutoIncrementValue");
+ DBUG_ENTER("readAutoIncrementValue");
const NdbTableImpl* table = theDictionary->getTable(aTableName);
if (table == 0) {
theError= theDictionary->getNdbError();
@@ -791,7 +833,7 @@ Ndb::readAutoIncrementValue(const char* aTableName)
Uint64
Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable)
{
- DBUG_ENTER("readtAutoIncrementValue");
+ DBUG_ENTER("readAutoIncrementValue");
if (aTable == 0)
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
@@ -813,71 +855,73 @@ Ndb::readTupleIdFromNdb(Uint32 aTableId)
bool
Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase)
{
- DEBUG_TRACE("setAutoIncrementValue " << val);
- const char * internalTableName= internalizeTableName(aTableName);
+ DBUG_ENTER("setAutoIncrementValue");
+ BaseString internal_tabname(internalize_table_name(aTableName));
+
Ndb_local_table_info *info=
- theDictionary->get_local_table_info(internalTableName, false);
+ theDictionary->get_local_table_info(internal_tabname, false);
if (info == 0) {
theError= theDictionary->getNdbError();
- return false;
+ DBUG_RETURN(false);
}
const NdbTableImpl* table= info->m_table_impl;
- return setTupleIdInNdb(table->m_tableId, val, increase);
+ DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase));
}
bool
Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool increase)
{
- DEBUG_TRACE("setAutoIncrementValue " << val);
+ DBUG_ENTER("setAutoIncrementValue");
if (aTable == 0)
- return ~(Uint64)0;
+ DBUG_RETURN(~(Uint64)0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- return setTupleIdInNdb(table->m_tableId, val, increase);
+ DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase));
}
-bool
+bool
Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val, bool increase )
{
- DEBUG_TRACE("setTupleIdInNdb");
+ DBUG_ENTER("setTupleIdInNdb(const char*, ...)");
const NdbTableImpl* table = theDictionary->getTable(aTableName);
if (table == 0) {
theError= theDictionary->getNdbError();
- return false;
+ DBUG_RETURN(false);
}
- return setTupleIdInNdb(table->m_tableId, val, increase);
+ DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase));
}
bool
Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase )
{
- DEBUG_TRACE("setTupleIdInNdb");
+ DBUG_ENTER("setTupleIdInNdb(Uint32, ...)");
if (increase)
{
if (theFirstTupleId[aTableId] != theLastTupleId[aTableId])
{
// We have a cache sequence
if (val <= theFirstTupleId[aTableId]+1)
- return false;
+ DBUG_RETURN(false);
if (val <= theLastTupleId[aTableId])
{
theFirstTupleId[aTableId] = val - 1;
- return true;
+ DBUG_RETURN(true);
}
// else continue;
- }
- return (opTupleIdOnNdb(aTableId, val, 2) == val);
+ }
+ DBUG_RETURN((opTupleIdOnNdb(aTableId, val, 2) == val));
}
else
- return (opTupleIdOnNdb(aTableId, val, 1) == val);
+ DBUG_RETURN((opTupleIdOnNdb(aTableId, val, 1) == val));
}
Uint64
Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
{
- DEBUG_TRACE("opTupleIdOnNdb");
+ DBUG_ENTER("Ndb::opTupleIdOnNdb");
+ DBUG_PRINT("enter", ("table=%u value=%llu op=%u", aTableId, opValue, op));
- NdbConnection* tConnection;
- NdbOperation* tOperation;
+ NdbTransaction* tConnection;
+ NdbOperation* tOperation= 0; // Compiler warning if not initialized
Uint64 tValue;
NdbRecAttr* tRecAttrResult;
int result;
@@ -970,7 +1014,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
setDatabaseName(currentDb.c_str());
setDatabaseSchemaName(currentSchema.c_str());
- return ret;
+ DBUG_RETURN(ret);
error_handler:
theError.code = tConnection->theError.code;
@@ -980,7 +1024,11 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
setDatabaseName(currentDb.c_str());
setDatabaseSchemaName(currentSchema.c_str());
- return ~(Uint64)0;
+ DBUG_PRINT("error", ("ndb=%d con=%d op=%d",
+ theError.code,
+ tConnection ? tConnection->theError.code : -1,
+ tOperation ? tOperation->theError.code : -1));
+ DBUG_RETURN(~(Uint64)0);
}
Uint32
@@ -1002,39 +1050,31 @@ convertEndian(Uint32 Data)
}
const char * Ndb::getCatalogName() const
{
- return theDataBase;
+ return theImpl->m_dbname.c_str();
}
-
+
+
void Ndb::setCatalogName(const char * a_catalog_name)
{
- if (a_catalog_name) {
- BaseString::snprintf(theDataBase, sizeof(theDataBase), "%s",
- a_catalog_name ? a_catalog_name : "");
-
- int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
- theDataBase, table_name_separator,
- theDataBaseSchema, table_name_separator);
- prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
- sizeof(prefixName) - 1);
+ if (a_catalog_name)
+ {
+ theImpl->m_dbname.assign(a_catalog_name);
+ theImpl->update_prefix();
}
}
-
+
+
const char * Ndb::getSchemaName() const
{
- return theDataBaseSchema;
+ return theImpl->m_schemaname.c_str();
}
-
+
+
void Ndb::setSchemaName(const char * a_schema_name)
{
if (a_schema_name) {
- BaseString::snprintf(theDataBaseSchema, sizeof(theDataBase), "%s",
- a_schema_name ? a_schema_name : "");
-
- int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
- theDataBase, table_name_separator,
- theDataBaseSchema, table_name_separator);
- prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
- sizeof(prefixName) - 1);
+ theImpl->m_schemaname.assign(a_schema_name);
+ theImpl->update_prefix();
}
}
@@ -1111,35 +1151,63 @@ Ndb::externalizeIndexName(const char * internalIndexName)
return externalizeIndexName(internalIndexName, usingFullyQualifiedNames());
}
-const char *
-Ndb::internalizeTableName(const char * externalTableName)
+
+const BaseString
+Ndb::internalize_table_name(const char *external_name) const
{
- if (fullyQualifiedNames) {
- strncpy(prefixEnd, externalTableName, NDB_MAX_TAB_NAME_SIZE);
- return prefixName;
+ BaseString ret;
+ DBUG_ENTER("internalize_table_name");
+ DBUG_PRINT("enter", ("external_name: %s", external_name));
+
+ if (fullyQualifiedNames)
+ {
+ /* Internal table name format <db>/<schema>/<table>
+ <db>/<schema> is already available in m_prefix
+ so just concat the two strings
+ */
+ ret.assfmt("%s%s",
+ theImpl->m_prefix.c_str(),
+ external_name);
}
else
- return externalTableName;
+ ret.assign(external_name);
+
+ DBUG_PRINT("exit", ("internal_name: %s", ret.c_str()));
+ DBUG_RETURN(ret);
}
-
-const char *
-Ndb::internalizeIndexName(const NdbTableImpl * table,
- const char * externalIndexName)
+
+
+const BaseString
+Ndb::internalize_index_name(const NdbTableImpl * table,
+ const char * external_name) const
{
- if (fullyQualifiedNames) {
- char tableId[10];
- sprintf(tableId, "%d", table->m_tableId);
- Uint32 tabIdLen = strlen(tableId);
- strncpy(prefixEnd, tableId, tabIdLen);
- prefixEnd[tabIdLen] = table_name_separator;
- strncpy(prefixEnd + tabIdLen + 1,
- externalIndexName, NDB_MAX_TAB_NAME_SIZE);
- return prefixName;
+ BaseString ret;
+ DBUG_ENTER("internalize_index_name");
+ DBUG_PRINT("enter", ("external_name: %s, table_id: %d",
+ external_name, table ? table->m_tableId : ~0));
+ if (!table)
+ {
+ DBUG_PRINT("error", ("!table"));
+ return ret;
+ }
+
+ if (fullyQualifiedNames)
+ {
+ /* Internal index name format <db>/<schema>/<tabid>/<table> */
+ ret.assfmt("%s%d%c%s",
+ theImpl->m_prefix.c_str(),
+ table->m_tableId,
+ table_name_separator,
+ external_name);
}
else
- return externalIndexName;
+ ret.assign(external_name);
+
+ DBUG_PRINT("exit", ("internal_name: %s", ret.c_str()));
+ DBUG_RETURN(ret);
}
+
const BaseString
Ndb::getDatabaseFromInternalName(const char * internalName)
{
@@ -1182,7 +1250,14 @@ NdbEventOperation* Ndb::createEventOperation(const char* eventName,
tOp = new NdbEventOperation(this, eventName, bufferLength);
- if (tOp->getState() != NdbEventOperation::CREATED) {
+ if (tOp == 0)
+ {
+ theError.code= 4000;
+ return NULL;
+ }
+
+ if (tOp->getState() != NdbEventOperation::EO_CREATED) {
+ theError.code= tOp->getNdbError().code;
delete tOp;
tOp = NULL;
}
@@ -1218,7 +1293,7 @@ Ndb::pollEvents(int aMillisecondNumber)
extern NdbMutex *ndb_print_state_mutex;
static bool
-checkdups(NdbConnection** list, unsigned no)
+checkdups(NdbTransaction** list, unsigned no)
{
for (unsigned i = 0; i < no; i++)
for (unsigned j = i + 1; j < no; j++)
@@ -1243,7 +1318,7 @@ Ndb::printState(const char* fmt, ...)
#endif
ndbout << endl;
for (unsigned n = 0; n < MAX_NDB_NODES; n++) {
- NdbConnection* con = theConnectionArray[n];
+ NdbTransaction* con = theConnectionArray[n];
if (con != 0) {
ndbout << "conn " << n << ":" << endl;
while (con != 0) {
diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp
index a1d34896968..b1671e593e1 100644
--- a/ndb/src/ndbapi/NdbApiSignal.cpp
+++ b/ndb/src/ndbapi/NdbApiSignal.cpp
@@ -213,7 +213,7 @@ NdbApiSignal::setSignal(int aNdbSignalType)
theTrace = TestOrd::TraceAPI;
theReceiversBlockNumber = DBTC;
theVerId_signalNumber = GSN_TCINDXREQ;
- theLength = TcIndxReq::SignalLength;
+ theLength = TcKeyReq::SignalLength;
}
break;
diff --git a/ndb/src/ndbapi/NdbApiSignal.hpp b/ndb/src/ndbapi/NdbApiSignal.hpp
index 52c3be2256c..353c575d420 100644
--- a/ndb/src/ndbapi/NdbApiSignal.hpp
+++ b/ndb/src/ndbapi/NdbApiSignal.hpp
@@ -93,7 +93,7 @@ private:
void setDataPtr(Uint32 *);
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class NdbScanReceiver;
friend class Table;
void copyFrom(const NdbApiSignal * src);
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
index f72361b86ac..d06d6b4ef4d 100644
--- a/ndb/src/ndbapi/NdbBlob.cpp
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -16,7 +16,7 @@
#include <Ndb.hpp>
#include <NdbDictionaryImpl.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include <NdbIndexOperation.hpp>
#include <NdbRecAttr.hpp>
@@ -24,34 +24,6 @@
#include "NdbBlobImpl.hpp"
#include <NdbScanOperation.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; \
- static char* prefix = "BLOB"; \
- const char* cname = theColumn == NULL ? "-" : theColumn->m_name.c_str(); \
- ndbout << prefix << " " << hex << (void*)this << " " << cname; \
- ndbout << " " << dec << __LINE__ << " " << x << " " << *this << endl; \
- } while (0)
-
-static char*
-ndb_blob_debug(const Uint32* data, unsigned size)
-{
- static char buf[200]; // MT irrelevant
- buf[0] = 0;
- for (unsigned i = 0; i < size; i++) {
- unsigned n = strlen(buf);
- if (n + 10 < sizeof(buf))
- sprintf(buf + n, "%*s%08x", i != 0, "", data[i]);
- }
- return buf;
-}
-
-#else
-#define DBG(x)
-#endif
-
/*
* Reading index table directly (as a table) is faster but there are
* bugs or limitations. Keep the code and make possible to choose.
@@ -63,8 +35,10 @@ static const bool g_ndb_blob_ok_to_read_index_table = false;
inline void
NdbBlob::setState(State newState)
{
- DBG("setState " << newState);
+ DBUG_ENTER("NdbBlob::setState");
+ DBUG_PRINT("info", ("this=%p newState=%u", this, newState));
theState = newState;
+ DBUG_VOID_RETURN;
}
// define blob table
@@ -100,8 +74,8 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm
bt.setFragmentType(t->getFragmentType());
{ NdbDictionary::Column bc("PK");
bc.setType(NdbDictionary::Column::Unsigned);
- assert(t->m_sizeOfKeysInWords != 0);
- bc.setLength(t->m_sizeOfKeysInWords);
+ assert(t->m_keyLenInWords != 0);
+ bc.setLength(t->m_keyLenInWords);
bc.setPrimaryKey(true);
bc.setDistributionKey(true);
bt.addColumn(bc);
@@ -319,9 +293,9 @@ NdbBlob::getDistKey(Uint32 part)
int
NdbBlob::getTableKeyValue(NdbOperation* anOp)
{
+ DBUG_ENTER("NdbBlob::getTableKeyValue");
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);
@@ -329,7 +303,7 @@ NdbBlob::getTableKeyValue(NdbOperation* anOp)
unsigned len = c->m_attrSize * c->m_arraySize;
if (anOp->getValue_impl(c, (char*)&data[pos]) == NULL) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
// odd bytes receive no data and must be zeroed
while (len % 4 != 0) {
@@ -340,14 +314,15 @@ NdbBlob::getTableKeyValue(NdbOperation* anOp)
}
}
assert(pos == theKeyBuf.size / 4);
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setTableKeyValue(NdbOperation* anOp)
{
+ DBUG_ENTER("NdbBlob::setTableKeyValue");
+ DBUG_DUMP("info", theKeyBuf.data, 4 * theTable->m_keyLenInWords);
const Uint32* data = (const Uint32*)theKeyBuf.data;
- DBG("setTableKeyValue key=" << ndb_blob_debug(data, theTable->m_sizeOfKeysInWords));
const unsigned columns = theTable->m_columns.size();
unsigned pos = 0;
for (unsigned i = 0; i < columns; i++) {
@@ -357,20 +332,21 @@ NdbBlob::setTableKeyValue(NdbOperation* anOp)
unsigned len = c->m_attrSize * c->m_arraySize;
if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
pos += (len + 3) / 4;
}
}
assert(pos == theKeyBuf.size / 4);
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setAccessKeyValue(NdbOperation* anOp)
{
+ DBUG_ENTER("NdbBlob::setAccessKeyValue");
+ DBUG_DUMP("info", theAccessKeyBuf.data, 4 * theAccessTable->m_keyLenInWords);
const Uint32* data = (const Uint32*)theAccessKeyBuf.data;
- DBG("setAccessKeyValue key=" << ndb_blob_debug(data, theAccessTable->m_sizeOfKeysInWords));
const unsigned columns = theAccessTable->m_columns.size();
unsigned pos = 0;
for (unsigned i = 0; i < columns; i++) {
@@ -380,57 +356,60 @@ NdbBlob::setAccessKeyValue(NdbOperation* anOp)
unsigned len = c->m_attrSize * c->m_arraySize;
if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
pos += (len + 3) / 4;
}
}
assert(pos == theAccessKeyBuf.size / 4);
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setPartKeyValue(NdbOperation* anOp, Uint32 part)
{
+ DBUG_ENTER("NdbBlob::setPartKeyValue");
+ DBUG_PRINT("info", ("dist=%u part=%u key=", getDistKey(part), part));
+ DBUG_DUMP("info", theKeyBuf.data, 4 * theTable->m_keyLenInWords);
Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
- DBG("setPartKeyValue dist=" << getDistKey(part) << " part=" << part << " key=" << ndb_blob_debug(data, size));
+ unsigned size = theTable->m_keyLenInWords;
// TODO use attr ids after compatibility with 4.1.7 not needed
if (anOp->equal("PK", theKeyBuf.data) == -1 ||
anOp->equal("DIST", getDistKey(part)) == -1 ||
anOp->equal("PART", part) == -1) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::getHeadInlineValue(NdbOperation* anOp)
{
- DBG("getHeadInlineValue");
+ DBUG_ENTER("NdbBlob::getHeadInlineValue");
theHeadInlineRecAttr = anOp->getValue_impl(theColumn, theHeadInlineBuf.data);
if (theHeadInlineRecAttr == NULL) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
void
NdbBlob::getHeadFromRecAttr()
{
+ DBUG_ENTER("NdbBlob::getHeadFromRecAttr");
assert(theHeadInlineRecAttr != NULL);
theNullFlag = theHeadInlineRecAttr->isNULL();
assert(theNullFlag != -1);
theLength = ! theNullFlag ? theHead->length : 0;
- DBG("getHeadFromRecAttr [out]");
+ DBUG_VOID_RETURN;
}
int
NdbBlob::setHeadInlineValue(NdbOperation* anOp)
{
- DBG("setHeadInlineValue");
+ DBUG_ENTER("NdbBlob::setHeadInlineValue");
theHead->length = theLength;
if (theLength < theInlineSize)
memset(theInlineData + theLength, 0, theInlineSize - theLength);
@@ -438,10 +417,10 @@ NdbBlob::setHeadInlineValue(NdbOperation* anOp)
const char* aValue = theNullFlag ? 0 : theHeadInlineBuf.data;
if (anOp->setValue(theColumn, aValue, theHeadInlineBuf.size) == -1) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
theHeadInlineUpdateFlag = false;
- return 0;
+ DBUG_RETURN(0);
}
// getValue/setValue
@@ -449,40 +428,42 @@ NdbBlob::setHeadInlineValue(NdbOperation* anOp)
int
NdbBlob::getValue(void* data, Uint32 bytes)
{
- DBG("getValue data=" << hex << data << " bytes=" << dec << bytes);
+ DBUG_ENTER("NdbBlob::getValue");
+ DBUG_PRINT("info", ("data=%p bytes=%u", data, bytes));
if (theGetFlag || theState != Prepared) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
if (! isReadOp() && ! isScanOp()) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
if (data == NULL && bytes != 0) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
theGetFlag = true;
theGetBuf = static_cast<char*>(data);
theGetSetBytes = bytes;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setValue(const void* data, Uint32 bytes)
{
- DBG("setValue data=" << hex << data << " bytes=" << dec << bytes);
+ DBUG_ENTER("NdbBlob::setValue");
+ DBUG_PRINT("info", ("data=%p bytes=%u", data, bytes));
if (theSetFlag || theState != Prepared) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
if (! isInsertOp() && ! isUpdateOp() && ! isWriteOp()) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
if (data == NULL && bytes != 0) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
theSetFlag = true;
theSetBuf = static_cast<const char*>(data);
@@ -495,15 +476,15 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
n = theInlineSize;
assert(thePos == 0);
if (writeDataPrivate(theSetBuf, n) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
theNullFlag = true;
theLength = 0;
}
if (setHeadInlineValue(theNdbOp) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
// activation hook
@@ -511,14 +492,15 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
int
NdbBlob::setActiveHook(ActiveHook activeHook, void* arg)
{
- DBG("setActiveHook hook=" << hex << (void*)activeHook << " arg=" << hex << arg);
+ DBUG_ENTER("NdbBlob::setActiveHook");
+ DBUG_PRINT("info", ("hook=%p arg=%p", (void*)activeHook, arg));
if (theState != Prepared) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
theActiveHook = activeHook;
theActiveHookArg = arg;
- return 0;
+ DBUG_RETURN(0);
}
// misc operations
@@ -526,63 +508,64 @@ NdbBlob::setActiveHook(ActiveHook activeHook, void* arg)
int
NdbBlob::getNull(bool& isNull)
{
- DBG("getNull");
+ DBUG_ENTER("NdbBlob::getNull");
if (theState == Prepared && theSetFlag) {
isNull = (theSetBuf == NULL);
- return 0;
+ DBUG_RETURN(0);
}
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
isNull = theNullFlag;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setNull()
{
- DBG("setNull");
+ DBUG_ENTER("NdbBlob::setNull");
if (theNullFlag == -1) {
if (theState == Prepared) {
- return setValue(0, 0);
+ DBUG_RETURN(setValue(0, 0));
}
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
if (theNullFlag)
- return 0;
+ DBUG_RETURN(0);
if (deleteParts(0, getPartCount()) == -1)
- return -1;
+ DBUG_RETURN(-1);
theNullFlag = true;
theLength = 0;
theHeadInlineUpdateFlag = true;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::getLength(Uint64& len)
{
- DBG("getLength");
+ DBUG_ENTER("NdbBlob::getLength");
if (theState == Prepared && theSetFlag) {
len = theGetSetBytes;
- return 0;
+ DBUG_RETURN(0);
}
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
len = theLength;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::truncate(Uint64 length)
{
- DBG("truncate [in] length=" << length);
+ DBUG_ENTER("NdbBlob::truncate");
+ DBUG_PRINT("info", ("length=%llu", length));
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
if (theLength > length) {
if (length > theInlineSize) {
@@ -590,46 +573,46 @@ NdbBlob::truncate(Uint64 length)
Uint32 part2 = getPartNumber(theLength - 1);
assert(part2 >= part1);
if (part2 > part1 && deleteParts(part1 + 1, part2 - part1) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
if (deleteParts(0, getPartCount()) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
theLength = length;
theHeadInlineUpdateFlag = true;
if (thePos > length)
thePos = length;
}
- DBG("truncate [out]");
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::getPos(Uint64& pos)
{
- DBG("getPos");
+ DBUG_ENTER("NdbBlob::getPos");
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
pos = thePos;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setPos(Uint64 pos)
{
- DBG("setPos pos=" << pos);
+ DBUG_ENTER("NdbBlob::setPos");
+ DBUG_PRINT("info", ("pos=%llu", pos));
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
if (pos > theLength) {
setErrorCode(NdbBlobImpl::ErrSeek);
- return -1;
+ DBUG_RETURN(-1);
}
thePos = pos;
- return 0;
+ DBUG_RETURN(0);
}
// read/write
@@ -648,7 +631,8 @@ NdbBlob::readData(void* data, Uint32& bytes)
int
NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
{
- DBG("readData [in] bytes=" << bytes);
+ DBUG_ENTER("NdbBlob::readDataPrivate");
+ DBUG_PRINT("info", ("bytes=%u", bytes));
assert(thePos <= theLength);
Uint64 pos = thePos;
if (bytes > theLength - pos)
@@ -668,20 +652,20 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
}
if (len > 0 && thePartSize == 0) {
setErrorCode(NdbBlobImpl::ErrSeek);
- return -1;
+ DBUG_RETURN(-1);
}
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);
+ DBUG_PRINT("info", ("partial first block pos=%llu len=%u", pos, len));
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
// need result now
if (executePendingBlobReads() == -1)
- return -1;
+ DBUG_RETURN(-1);
Uint32 n = thePartSize - off;
if (n > len)
n = len;
@@ -698,7 +682,7 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
Uint32 part = (pos - theInlineSize) / thePartSize;
Uint32 count = len / thePartSize;
if (readParts(buf, part, count) == -1)
- return -1;
+ DBUG_RETURN(-1);
Uint32 n = thePartSize * count;
pos += n;
buf += n;
@@ -707,14 +691,14 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
}
if (len > 0) {
// partial last block
- DBG("partial last block pos=" << pos << " len=" << len);
+ DBUG_PRINT("info", ("partial last block pos=%llu len=%u", pos, len));
assert((pos - theInlineSize) % thePartSize == 0 && len < thePartSize);
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
// need result now
if (executePendingBlobReads() == -1)
- return -1;
+ DBUG_RETURN(-1);
memcpy(buf, thePartBuf.data, len);
Uint32 n = len;
pos += n;
@@ -724,8 +708,7 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
assert(len == 0);
thePos = pos;
assert(thePos <= theLength);
- DBG("readData [out]");
- return 0;
+ DBUG_RETURN(0);
}
int
@@ -742,7 +725,8 @@ NdbBlob::writeData(const void* data, Uint32 bytes)
int
NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
{
- DBG("writeData [in] bytes=" << bytes);
+ DBUG_ENTER("NdbBlob::writeDataPrivate");
+ DBUG_PRINT("info", ("bytes=%u", bytes));
assert(thePos <= theLength);
Uint64 pos = thePos;
Uint32 len = bytes;
@@ -766,23 +750,23 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
}
if (len > 0 && thePartSize == 0) {
setErrorCode(NdbBlobImpl::ErrSeek);
- return -1;
+ DBUG_RETURN(-1);
}
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);
+ DBUG_PRINT("info", ("partial first block pos=%llu len=%u", pos, len));
// flush writes to guarantee correct read
if (executePendingBlobWrites() == -1)
- return -1;
+ DBUG_RETURN(-1);
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
// need result now
if (executePendingBlobReads() == -1)
- return -1;
+ DBUG_RETURN(-1);
Uint32 n = thePartSize - off;
if (n > len) {
memset(thePartBuf.data + off + len, theFillChar, n - len);
@@ -790,7 +774,7 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
}
memcpy(thePartBuf.data + off, buf, n);
if (updateParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
pos += n;
buf += n;
len -= n;
@@ -805,10 +789,10 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
for (unsigned i = 0; i < count; i++) {
if (part + i < getPartCount()) {
if (updateParts(buf, part + i, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
if (insertParts(buf, part + i, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
Uint32 n = thePartSize;
pos += n;
@@ -819,30 +803,30 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
}
if (len > 0) {
// partial last block
- DBG("partial last block pos=" << pos << " len=" << len);
+ DBUG_PRINT("info", ("partial last block pos=%llu len=%u", pos, len));
assert((pos - theInlineSize) % thePartSize == 0 && len < thePartSize);
Uint32 part = (pos - theInlineSize) / thePartSize;
if (theLength > pos + len) {
// flush writes to guarantee correct read
if (executePendingBlobWrites() == -1)
- return -1;
+ DBUG_RETURN(-1);
if (readParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
// need result now
if (executePendingBlobReads() == -1)
- return -1;
+ DBUG_RETURN(-1);
memcpy(thePartBuf.data, buf, len);
if (updateParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_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;
+ DBUG_RETURN(-1);
} else {
if (insertParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
Uint32 n = len;
@@ -857,14 +841,14 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
}
thePos = pos;
assert(thePos <= theLength);
- DBG("writeData [out]");
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
{
- DBG("readParts [in] part=" << part << " count=" << count);
+ DBUG_ENTER("NdbBlob::readParts");
+ DBUG_PRINT("info", ("part=%u count=%u", part, count));
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -873,21 +857,22 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
setPartKeyValue(tOp, part + n) == -1 ||
tOp->getValue((Uint32)3, buf) == NULL) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
{
- DBG("insertParts [in] part=" << part << " count=" << count);
+ DBUG_ENTER("NdbBlob::insertParts");
+ DBUG_PRINT("info", ("part=%u count=%u", part, count));
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -896,21 +881,22 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
setPartKeyValue(tOp, part + n) == -1 ||
tOp->setValue((Uint32)3, buf) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
{
- DBG("updateParts [in] part=" << part << " count=" << count);
+ DBUG_ENTER("NdbBlob::updateParts");
+ DBUG_PRINT("info", ("part=%u count=%u", part, count));
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -919,21 +905,22 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
setPartKeyValue(tOp, part + n) == -1 ||
tOp->setValue((Uint32)3, buf) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::deleteParts(Uint32 part, Uint32 count)
{
- DBG("deleteParts [in] part=" << part << " count=" << count);
+ DBUG_ENTER("NdbBlob::deleteParts");
+ DBUG_PRINT("info", ("part=%u count=%u", part, count));
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -941,14 +928,14 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
tOp->deleteTuple() == -1 ||
setPartKeyValue(tOp, part + n) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
n++;
thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
}
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -958,7 +945,8 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
int
NdbBlob::deletePartsUnknown(Uint32 part)
{
- DBG("deletePartsUnknown [in] part=" << part << " count=all");
+ DBUG_ENTER("NdbBlob::deletePartsUnknown");
+ DBUG_PRINT("info", ("part=%u count=all", part));
static const unsigned maxbat = 256;
static const unsigned minbat = 1;
unsigned bat = minbat;
@@ -974,26 +962,25 @@ NdbBlob::deletePartsUnknown(Uint32 part)
tOp->deleteTuple() == -1 ||
setPartKeyValue(tOp, part + count + n) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AO_IgnoreError;
+ tOp->m_abortOption= NdbTransaction::AO_IgnoreError;
n++;
}
- DBG("deletePartsUnknown: executeNoBlobs [in] bat=" << bat);
- if (theNdbCon->executeNoBlobs(NoCommit) == -1)
- return -1;
- DBG("deletePartsUnknown: executeNoBlobs [out]");
+ DBUG_PRINT("info", ("bat=%u", bat));
+ if (theNdbCon->executeNoBlobs(NdbTransaction::NoCommit) == -1)
+ DBUG_RETURN(-1);
n = 0;
while (n < bat) {
NdbOperation* tOp = tOpList[n];
if (tOp->theError.code != 0) {
if (tOp->theError.code != 626) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
// first non-existent part
- DBG("deletePartsUnknown [out] count=" << count);
- return 0;
+ DBUG_PRINT("info", ("count=%u", count));
+ DBUG_RETURN(0);
}
n++;
count++;
@@ -1009,31 +996,29 @@ NdbBlob::deletePartsUnknown(Uint32 part)
int
NdbBlob::executePendingBlobReads()
{
+ DBUG_ENTER("NdbBlob::executePendingBlobReads");
Uint8 flags = (1 << NdbOperation::ReadRequest);
if (thePendingBlobOps & flags) {
- DBG("executePendingBlobReads: executeNoBlobs [in]");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1)
- return -1;
- DBG("executePendingBlobReads: executeNoBlobs [out]");
+ if (theNdbCon->executeNoBlobs(NdbTransaction::NoCommit) == -1)
+ DBUG_RETURN(-1);
thePendingBlobOps = 0;
theNdbCon->thePendingBlobOps = 0;
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::executePendingBlobWrites()
{
+ DBUG_ENTER("NdbBlob::executePendingBlobWrites");
Uint8 flags = 0xFF & ~(1 << NdbOperation::ReadRequest);
if (thePendingBlobOps & flags) {
- DBG("executePendingBlobWrites: executeNoBlobs [in]");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1)
- return -1;
- DBG("executePendingBlobWrites: executeNoBlobs [out]");
+ if (theNdbCon->executeNoBlobs(NdbTransaction::NoCommit) == -1)
+ DBUG_RETURN(-1);
thePendingBlobOps = 0;
theNdbCon->thePendingBlobOps = 0;
}
- return 0;
+ DBUG_RETURN(0);
}
// callbacks
@@ -1041,15 +1026,14 @@ NdbBlob::executePendingBlobWrites()
int
NdbBlob::invokeActiveHook()
{
- DBG("invokeActiveHook [in]");
+ DBUG_ENTER("NdbBlob::invokeActiveHook");
assert(theState == Active && theActiveHook != NULL);
int ret = (*theActiveHook)(this, theActiveHookArg);
- DBG("invokeActiveHook [out] ret=" << ret);
if (ret != 0) {
// no error is set on blob level
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
// blob handle maintenance
@@ -1060,8 +1044,10 @@ NdbBlob::invokeActiveHook()
* data. For read operation adds read of head+inline.
*/
int
-NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn)
+NdbBlob::atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn)
{
+ DBUG_ENTER("NdbBlob::atPrepare");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p", this, anOp, aCon));
assert(theState == Idle);
// ndb api stuff
theNdb = anOp->theNdb;
@@ -1070,7 +1056,6 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
theTable = anOp->m_currentTable;
theAccessTable = anOp->m_accessTable;
theColumn = aColumn;
- DBG("atPrepare [in]");
NdbDictionary::Column::Type partType = NdbDictionary::Column::Undefined;
switch (theColumn->getType()) {
case NdbDictionary::Column::Blob:
@@ -1083,7 +1068,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
break;
default:
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
// sizes
theInlineSize = theColumn->getInlineSize();
@@ -1101,13 +1086,13 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
bc->getType() != partType ||
bc->getLength() != (int)thePartSize) {
setErrorCode(NdbBlobImpl::ErrTable);
- return -1;
+ DBUG_RETURN(-1);
}
theBlobTable = &NdbTableImpl::getImpl(*bt);
}
// buffers
- theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2);
- theAccessKeyBuf.alloc(theAccessTable->m_sizeOfKeysInWords << 2);
+ theKeyBuf.alloc(theTable->m_keyLenInWords << 2);
+ theAccessKeyBuf.alloc(theAccessTable->m_keyLenInWords << 2);
theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize);
theHeadInlineCopyBuf.alloc(sizeof(Head) + theInlineSize);
thePartBuf.alloc(thePartSize);
@@ -1119,25 +1104,25 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
if (isTableOp()) {
// get table key
Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
+ unsigned size = theTable->m_keyLenInWords;
if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isIndexOp()) {
// get index key
Uint32* data = (Uint32*)theAccessKeyBuf.data;
- unsigned size = theAccessTable->m_sizeOfKeysInWords;
+ unsigned size = theAccessTable->m_keyLenInWords;
if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isReadOp()) {
// add read of head+inline in this op
if (getHeadInlineValue(theNdbOp) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
if (isInsertOp()) {
// becomes NULL unless set before execute
@@ -1155,16 +1140,15 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
if (isScanOp()) {
// add read of head+inline in this op
if (getHeadInlineValue(theNdbOp) == -1)
- return -1;
+ DBUG_RETURN(-1);
supportedOp = true;
}
if (! supportedOp) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
setState(Prepared);
- DBG("atPrepare [out]");
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -1175,11 +1159,12 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
* back after postExecute.
*/
int
-NdbBlob::preExecute(ExecType anExecType, bool& batch)
+NdbBlob::preExecute(NdbTransaction::ExecType anExecType, bool& batch)
{
- DBG("preExecute [in]");
+ DBUG_ENTER("NdbBlob::preExecute");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p", this, theNdbOp, theNdbCon));
if (theState == Invalid)
- return -1;
+ DBUG_RETURN(-1);
assert(theState == Prepared);
// handle different operation types
assert(isKeyOp());
@@ -1197,7 +1182,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
Uint32 bytes = theGetSetBytes - theInlineSize;
assert(thePos == theInlineSize);
if (writeDataPrivate(buf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (theHeadInlineUpdateFlag) {
// add an operation to update head+inline
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
@@ -1206,9 +1191,9 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setTableKeyValue(tOp) == -1 ||
setHeadInlineValue(tOp) == -1) {
setErrorCode(NdbBlobImpl::ErrAbort);
- return -1;
+ DBUG_RETURN(-1);
}
- DBG("add op to update head+inline");
+ DBUG_PRINT("info", ("add op to update head+inline"));
}
}
}
@@ -1221,15 +1206,15 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setTableKeyValue(tOp) == -1 ||
getHeadInlineValue(tOp) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
if (isWriteOp()) {
- tOp->m_abortOption = AO_IgnoreError;
+ tOp->m_abortOption = NdbTransaction::AO_IgnoreError;
}
theHeadInlineReadOp = tOp;
// execute immediately
batch = true;
- DBG("add op before to read head+inline");
+ DBUG_PRINT("info", ("add op before to read head+inline"));
}
}
if (isIndexOp()) {
@@ -1245,7 +1230,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setAccessKeyValue(tOp) == -1 ||
tOp->getValue(pkAttrId, theKeyBuf.data) == NULL) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
} else {
NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
@@ -1254,11 +1239,11 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setAccessKeyValue(tOp) == -1 ||
getTableKeyValue(tOp) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
}
}
- DBG("added op before to read table key");
+ DBUG_PRINT("info", ("added op before to read table key"));
if (isUpdateOp() || isDeleteOp()) {
// add op before this one to read head+inline via index
NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
@@ -1267,15 +1252,15 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setAccessKeyValue(tOp) == -1 ||
getHeadInlineValue(tOp) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
if (isWriteOp()) {
- tOp->m_abortOption = AO_IgnoreError;
+ tOp->m_abortOption = NdbTransaction::AO_IgnoreError;
}
theHeadInlineReadOp = tOp;
// execute immediately
batch = true;
- DBG("added index op before to read head+inline");
+ DBUG_PRINT("info", ("added index op before to read head+inline"));
}
if (isWriteOp()) {
// XXX until IgnoreError fixed for index op
@@ -1293,10 +1278,10 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
n = theInlineSize;
assert(thePos == 0);
if (writeDataPrivate(theSetBuf, n) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
if (setHeadInlineValue(theNdbOp) == -1)
- return -1;
+ DBUG_RETURN(-1);
// the read op before us may overwrite
theHeadInlineCopyBuf.copyfrom(theHeadInlineBuf);
}
@@ -1305,8 +1290,8 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
// need blob head for callback
batch = true;
}
- DBG("preExecute [out] batch=" << batch);
- return 0;
+ DBUG_PRINT("info", ("batch=%u", batch));
+ DBUG_RETURN(0);
}
/*
@@ -1316,18 +1301,19 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
* any remaining prepared operations.
*/
int
-NdbBlob::postExecute(ExecType anExecType)
+NdbBlob::postExecute(NdbTransaction::ExecType anExecType)
{
- DBG("postExecute [in] type=" << anExecType);
+ DBUG_ENTER("NdbBlob::postExecute");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p anExecType=%u", this, theNdbOp, theNdbCon, anExecType));
if (theState == Invalid)
- return -1;
+ DBUG_RETURN(-1);
if (theState == Active) {
- setState(anExecType == NoCommit ? Active : Closed);
- DBG("postExecute [skip]");
- return 0;
+ setState(anExecType == NdbTransaction::NoCommit ? Active : Closed);
+ DBUG_PRINT("info", ("skip active"));
+ DBUG_RETURN(0);
}
assert(theState == Prepared);
- setState(anExecType == NoCommit ? Active : Closed);
+ setState(anExecType == NdbTransaction::NoCommit ? Active : Closed);
assert(isKeyOp());
if (isIndexOp()) {
NdbBlob* tFirstBlob = theNdbOp->theBlobList;
@@ -1340,42 +1326,43 @@ NdbBlob::postExecute(ExecType anExecType)
if (isReadOp()) {
getHeadFromRecAttr();
if (setPos(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (theGetFlag) {
assert(theGetSetBytes == 0 || theGetBuf != 0);
- assert(theGetSetBytes <= theInlineSize || anExecType == NoCommit);
+ assert(theGetSetBytes <= theInlineSize ||
+ anExecType == NdbTransaction::NoCommit);
Uint32 bytes = theGetSetBytes;
if (readDataPrivate(theGetBuf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isUpdateOp()) {
- assert(anExecType == NoCommit);
+ assert(anExecType == NdbTransaction::NoCommit);
getHeadFromRecAttr();
if (theSetFlag) {
// setValue overwrites everything
if (theSetBuf != NULL) {
if (truncate(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
assert(thePos == 0);
if (writeDataPrivate(theSetBuf, theGetSetBytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
if (setNull() == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
}
if (isWriteOp() && isTableOp()) {
- assert(anExecType == NoCommit);
+ assert(anExecType == NdbTransaction::NoCommit);
if (theHeadInlineReadOp->theError.code == 0) {
int tNullFlag = theNullFlag;
Uint64 tLength = theLength;
Uint64 tPos = thePos;
getHeadFromRecAttr();
- DBG("tuple found");
+ DBUG_PRINT("info", ("tuple found"));
if (truncate(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
// restore previous head+inline
theHeadInlineBuf.copyfrom(theHeadInlineCopyBuf);
theNullFlag = tNullFlag;
@@ -1384,16 +1371,16 @@ NdbBlob::postExecute(ExecType anExecType)
} else {
if (theHeadInlineReadOp->theError.code != 626) {
setErrorCode(theHeadInlineReadOp);
- return -1;
+ DBUG_RETURN(-1);
}
- DBG("tuple not found");
+ DBUG_PRINT("info", ("tuple not found"));
/*
* Read found no tuple but it is possible that a tuple was
* created after the read by another transaction. Delete all
* blob parts which may exist.
*/
if (deletePartsUnknown(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
if (theSetFlag && theGetSetBytes > theInlineSize) {
assert(theSetBuf != NULL);
@@ -1401,48 +1388,47 @@ NdbBlob::postExecute(ExecType anExecType)
Uint32 bytes = theGetSetBytes - theInlineSize;
assert(thePos == theInlineSize);
if (writeDataPrivate(buf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isWriteOp() && isIndexOp()) {
// XXX until IgnoreError fixed for index op
if (deletePartsUnknown(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (theSetFlag && theGetSetBytes > theInlineSize) {
assert(theSetBuf != NULL);
const char* buf = theSetBuf + theInlineSize;
Uint32 bytes = theGetSetBytes - theInlineSize;
assert(thePos == theInlineSize);
if (writeDataPrivate(buf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isDeleteOp()) {
- assert(anExecType == NoCommit);
+ assert(anExecType == NdbTransaction::NoCommit);
getHeadFromRecAttr();
if (deleteParts(0, getPartCount()) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
- setState(anExecType == NoCommit ? Active : Closed);
+ setState(anExecType == NdbTransaction::NoCommit ? Active : Closed);
// activation callback
if (theActiveHook != NULL) {
if (invokeActiveHook() == -1)
- return -1;
+ DBUG_RETURN(-1);
}
- if (anExecType == NoCommit && theHeadInlineUpdateFlag) {
+ if (anExecType == NdbTransaction::NoCommit && theHeadInlineUpdateFlag) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
if (tOp == NULL ||
tOp->updateTuple() == -1 ||
setTableKeyValue(tOp) == -1 ||
setHeadInlineValue(tOp) == -1) {
setErrorCode(NdbBlobImpl::ErrAbort);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
- DBG("added op to update head+inline");
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
+ DBUG_PRINT("info", ("added op to update head+inline"));
}
- DBG("postExecute [out]");
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -1452,9 +1438,10 @@ NdbBlob::postExecute(ExecType anExecType)
int
NdbBlob::preCommit()
{
- DBG("preCommit [in]");
+ DBUG_ENTER("NdbBlob::preCommit");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p", this, theNdbOp, theNdbCon));
if (theState == Invalid)
- return -1;
+ DBUG_RETURN(-1);
assert(theState == Active);
assert(isKeyOp());
if (isInsertOp() || isUpdateOp() || isWriteOp()) {
@@ -1466,14 +1453,13 @@ NdbBlob::preCommit()
setTableKeyValue(tOp) == -1 ||
setHeadInlineValue(tOp) == -1) {
setErrorCode(NdbBlobImpl::ErrAbort);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
- DBG("added op to update head+inline");
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
+ DBUG_PRINT("info", ("added op to update head+inline"));
}
}
- DBG("preCommit [out]");
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -1482,35 +1468,35 @@ NdbBlob::preCommit()
int
NdbBlob::atNextResult()
{
- DBG("atNextResult [in]");
+ DBUG_ENTER("NdbBlob::atNextResult");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p", this, theNdbOp, theNdbCon));
if (theState == Invalid)
- return -1;
+ DBUG_RETURN(-1);
assert(isScanOp());
// get primary key
{ Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
+ unsigned size = theTable->m_keyLenInWords;
if (((NdbScanOperation*)theNdbOp)->getKeyFromKEYINFO20(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
}
getHeadFromRecAttr();
if (setPos(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (theGetFlag) {
assert(theGetSetBytes == 0 || theGetBuf != 0);
Uint32 bytes = theGetSetBytes;
if (readDataPrivate(theGetBuf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
setState(Active);
// activation callback
if (theActiveHook != NULL) {
if (invokeActiveHook() == -1)
- return -1;
+ DBUG_RETURN(-1);
}
- DBG("atNextResult [out]");
- return 0;
+ DBUG_RETURN(0);
}
// misc
@@ -1526,13 +1512,15 @@ NdbBlob::getColumn()
void
NdbBlob::setErrorCode(int anErrorCode, bool invalidFlag)
{
- DBG("setErrorCode code=" << anErrorCode);
+ DBUG_ENTER("NdbBlob::setErrorCode");
+ DBUG_PRINT("info", ("this=%p code=%u", this, anErrorCode));
theError.code = anErrorCode;
// conditionally copy error to operation level
if (theNdbOp != NULL && theNdbOp->theError.code == 0)
theNdbOp->setErrorCode(theError.code);
if (invalidFlag)
setState(Invalid);
+ DBUG_VOID_RETURN;
}
void
@@ -1551,7 +1539,7 @@ NdbBlob::setErrorCode(NdbOperation* anOp, bool invalidFlag)
}
void
-NdbBlob::setErrorCode(NdbConnection* aCon, bool invalidFlag)
+NdbBlob::setErrorCode(NdbTransaction* aCon, bool invalidFlag)
{
int code = 0;
if (theNdbCon != NULL && (code = theNdbCon->theError.code) != 0)
diff --git a/ndb/src/ndbapi/NdbCursorOperation.cpp b/ndb/src/ndbapi/NdbCursorOperation.cpp
deleted file mode 100644
index a9f84c4c110..00000000000
--- a/ndb/src/ndbapi/NdbCursorOperation.cpp
+++ /dev/null
@@ -1,51 +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: NdbCursorOperation.cpp
- * Include:
- * Link:
- * Author: UABMASD Martin Sköld INN/V Alzato
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Cursor support
- * Documentation:
- * Adjust: 2002-04-01 UABMASD First version.
- ****************************************************************************/
-
-#include <NdbCursorOperation.hpp>
-#include <NdbResultSet.hpp>
-
-NdbCursorOperation::NdbCursorOperation(Ndb* aNdb) :
-{
-}
-
-NdbCursorOperation::~NdbCursorOperation()
-{
- if (m_resultSet)
- delete m_resultSet;
-}
-
-void NdbCursorOperation::cursInit()
-{
- // Initialize result set
-}
-
-NdbResultSet* NdbCursorOperation::getResultSet()
-{
-}
-
-
diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp
index 00db5704949..79b6fb4c0e8 100644
--- a/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/ndb/src/ndbapi/NdbDictionary.cpp
@@ -176,52 +176,16 @@ NdbDictionary::Column::getPrimaryKey() const {
return m_impl.m_pk;
}
-void
-NdbDictionary::Column::setTupleKey(bool val){
- m_impl.m_tupleKey = val;
-}
-
-bool
-NdbDictionary::Column::getTupleKey() const {
- return m_impl.m_tupleKey;
-}
-
void
-NdbDictionary::Column::setDistributionKey(bool val){
+NdbDictionary::Column::setPartitionKey(bool val){
m_impl.m_distributionKey = val;
}
bool
-NdbDictionary::Column::getDistributionKey() const{
+NdbDictionary::Column::getPartitionKey() const{
return m_impl.m_distributionKey;
}
-void
-NdbDictionary::Column::setDistributionGroup(bool val, int bits){
- m_impl.m_distributionGroup = val;
- m_impl.m_distributionGroupBits = bits;
-}
-
-bool
-NdbDictionary::Column::getDistributionGroup() const {
- return m_impl.m_distributionGroup;
-}
-
-int
-NdbDictionary::Column::getDistributionGroupBits() const{
- return m_impl.m_distributionGroupBits;
-}
-
-void
-NdbDictionary::Column::setIndexOnlyStorage(bool val){
- m_impl.m_indexOnly = val;
-}
-
-bool
-NdbDictionary::Column::getIndexOnlyStorage() const {
- return m_impl.m_indexOnly;
-}
-
const NdbDictionary::Table *
NdbDictionary::Column::getBlobTable() const {
NdbTableImpl * t = m_impl.m_blobTable;
@@ -267,6 +231,12 @@ NdbDictionary::Column::equal(const NdbDictionary::Column & col) const {
return m_impl.equal(col.m_impl);
}
+int
+NdbDictionary::Column::getSizeInBytes() const
+{
+ return m_impl.m_attrSize * m_impl.m_arraySize;
+}
+
/*****************************************************************
* Table facade
*/
@@ -462,13 +432,17 @@ NdbDictionary::Table::getRowSizeInBytes() const {
int sz = 0;
for(int i = 0; i<getNoOfColumns(); i++){
const NdbDictionary::Column * c = getColumn(i);
- const NdbColumnImpl & col = NdbColumnImpl::getImpl(* c);
- sz += (((col.m_attrSize * col.m_arraySize) + 3) / 4);
+ sz += (c->getSizeInBytes()+ 3) / 4;
}
return sz * 4;
}
int
+NdbDictionary::Table::getReplicaCount() const {
+ return m_impl.m_replicaCount;
+}
+
+int
NdbDictionary::Table::createTableInDb(Ndb* pNdb, bool equalOk) const {
const NdbDictionary::Table * pTab =
pNdb->getDictionary()->getTable(getName());
@@ -621,6 +595,13 @@ NdbDictionary::Event::Event(const char * name)
setName(name);
}
+NdbDictionary::Event::Event(const char * name, const Table& table)
+ : m_impl(* new NdbEventImpl(* this))
+{
+ setName(name);
+ setTable(table);
+}
+
NdbDictionary::Event::Event(NdbEventImpl & impl)
: m_impl(impl)
{
@@ -640,12 +621,30 @@ NdbDictionary::Event::setName(const char * name)
m_impl.setName(name);
}
+const char *
+NdbDictionary::Event::getName() const
+{
+ return m_impl.getName();
+}
+
+void
+NdbDictionary::Event::setTable(const Table& table)
+{
+ m_impl.setTable(table);
+}
+
void
NdbDictionary::Event::setTable(const char * table)
{
m_impl.setTable(table);
}
+const char*
+NdbDictionary::Event::getTableName() const
+{
+ return m_impl.getTableName();
+}
+
void
NdbDictionary::Event::addTableEvent(const TableEvent t)
{
@@ -653,11 +652,17 @@ NdbDictionary::Event::addTableEvent(const TableEvent t)
}
void
-NdbDictionary::Event::setDurability(const EventDurability d)
+NdbDictionary::Event::setDurability(EventDurability d)
{
m_impl.setDurability(d);
}
+NdbDictionary::Event::EventDurability
+NdbDictionary::Event::getDurability() const
+{
+ return m_impl.getDurability();
+}
+
void
NdbDictionary::Event::addColumn(const Column & c){
NdbColumnImpl* col = new NdbColumnImpl;
@@ -685,6 +690,11 @@ NdbDictionary::Event::addEventColumns(int n, const char ** names)
addEventColumn(names[i]);
}
+int NdbDictionary::Event::getNoOfEventColumns() const
+{
+ return m_impl.getNoOfEventColumns();
+}
+
NdbDictionary::Object::Status
NdbDictionary::Event::getObjectStatus() const
{
@@ -742,7 +752,8 @@ NdbDictionary::Dictionary::alterTable(const Table & t){
}
const NdbDictionary::Table *
-NdbDictionary::Dictionary::getTable(const char * name, void **data){
+NdbDictionary::Dictionary::getTable(const char * name, void **data) const
+{
NdbTableImpl * t = m_impl.getTable(name, data);
if(t)
return t->m_facade;
@@ -755,15 +766,18 @@ void NdbDictionary::Dictionary::set_local_table_data_size(unsigned sz)
}
const NdbDictionary::Table *
-NdbDictionary::Dictionary::getTable(const char * name){
+NdbDictionary::Dictionary::getTable(const char * name) const
+{
return getTable(name, 0);
}
void
NdbDictionary::Dictionary::invalidateTable(const char * name){
+ DBUG_ENTER("NdbDictionaryImpl::invalidateTable");
NdbTableImpl * t = m_impl.getTable(name);
if(t)
m_impl.invalidateObject(* t);
+ DBUG_VOID_RETURN;
}
void
@@ -788,7 +802,7 @@ NdbDictionary::Dictionary::dropIndex(const char * indexName,
const NdbDictionary::Index *
NdbDictionary::Dictionary::getIndex(const char * indexName,
- const char * tableName)
+ const char * tableName) const
{
NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
if(i)
@@ -799,11 +813,13 @@ NdbDictionary::Dictionary::getIndex(const char * indexName,
void
NdbDictionary::Dictionary::invalidateIndex(const char * indexName,
const char * tableName){
+ DBUG_ENTER("NdbDictionaryImpl::invalidateIndex");
NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
if(i) {
assert(i->m_table != 0);
m_impl.invalidateObject(* i->m_table);
}
+ DBUG_VOID_RETURN;
}
void
@@ -818,7 +834,7 @@ NdbDictionary::Dictionary::removeCachedIndex(const char * indexName,
const NdbDictionary::Table *
NdbDictionary::Dictionary::getIndexTable(const char * indexName,
- const char * tableName)
+ const char * tableName) const
{
NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
NdbTableImpl * t = m_impl.getTable(tableName);
@@ -858,6 +874,12 @@ NdbDictionary::Dictionary::listObjects(List& list, Object::Type type)
}
int
+NdbDictionary::Dictionary::listObjects(List& list, Object::Type type) const
+{
+ return m_impl.listObjects(list, type);
+}
+
+int
NdbDictionary::Dictionary::listIndexes(List& list, const char * tableName)
{
const NdbDictionary::Table* tab= getTable(tableName);
@@ -868,6 +890,18 @@ NdbDictionary::Dictionary::listIndexes(List& list, const char * tableName)
return m_impl.listIndexes(list, tab->getTableId());
}
+int
+NdbDictionary::Dictionary::listIndexes(List& list,
+ const char * tableName) const
+{
+ const NdbDictionary::Table* tab= getTable(tableName);
+ if(tab == 0)
+ {
+ return -1;
+ }
+ return m_impl.listIndexes(list, tab->getTableId());
+}
+
const struct NdbError &
NdbDictionary::Dictionary::getNdbError() const {
return m_impl.getNdbError();
@@ -924,6 +958,12 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
case NdbDictionary::Column::Olddecimalunsigned:
out << "Olddecimalunsigned(" << col.getPrecision() << "," << col.getScale() << ")";
break;
+ case NdbDictionary::Column::Decimal:
+ out << "Decimal(" << col.getPrecision() << "," << col.getScale() << ")";
+ break;
+ case NdbDictionary::Column::Decimalunsigned:
+ out << "Decimalunsigned(" << col.getPrecision() << "," << col.getScale() << ")";
+ break;
case NdbDictionary::Column::Char:
out << "Char(" << col.getLength() << ";" << csname << ")";
break;
@@ -962,10 +1002,37 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
case NdbDictionary::Column::Undefined:
out << "Undefined";
break;
+ case NdbDictionary::Column::Bit:
+ out << "Bit(" << col.getLength() << ")";
+ break;
+ case NdbDictionary::Column::Longvarchar:
+ out << "Longvarchar(" << col.getLength() << ";" << csname << ")";
+ break;
+ case NdbDictionary::Column::Longvarbinary:
+ out << "Longvarbinary(" << col.getLength() << ")";
+ break;
default:
out << "Type" << (Uint32)col.getType();
break;
}
+ // show unusual (non-MySQL) array size
+ if (col.getLength() != 1) {
+ switch (col.getType()) {
+ case NdbDictionary::Column::Char:
+ case NdbDictionary::Column::Varchar:
+ case NdbDictionary::Column::Binary:
+ case NdbDictionary::Column::Varbinary:
+ case NdbDictionary::Column::Blob:
+ case NdbDictionary::Column::Text:
+ case NdbDictionary::Column::Bit:
+ case NdbDictionary::Column::Longvarchar:
+ case NdbDictionary::Column::Longvarbinary:
+ break;
+ default:
+ out << " [" << col.getLength() << "]";
+ break;
+ }
+ }
if (col.getPrimaryKey())
out << " PRIMARY KEY";
else if (! col.getNullable())
@@ -973,13 +1040,15 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
else
out << " NULL";
- if (col.getDistributionKey())
+ if(col.getDistributionKey())
out << " DISTRIBUTION KEY";
-
+
return out;
}
const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0;
+const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_MEMORY = 0;
const NdbDictionary::Column * NdbDictionary::Column::ROW_COUNT = 0;
const NdbDictionary::Column * NdbDictionary::Column::COMMIT_COUNT = 0;
-
+const NdbDictionary::Column * NdbDictionary::Column::ROW_SIZE = 0;
+const NdbDictionary::Column * NdbDictionary::Column::RANGE_NO = 0;
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index 8b1847502d9..8f37c9fe4a0 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -70,16 +70,11 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col)
m_scale = col.m_scale;
m_length = col.m_length;
m_pk = col.m_pk;
- m_tupleKey = col.m_tupleKey;
m_distributionKey = col.m_distributionKey;
- m_distributionGroup = col.m_distributionGroup;
- m_distributionGroupBits = col.m_distributionGroupBits;
m_nullable = col.m_nullable;
- m_indexOnly = col.m_indexOnly;
m_autoIncrement = col.m_autoIncrement;
m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
m_defaultValue = col.m_defaultValue;
- m_attrType = col.m_attrType;
m_attrSize = col.m_attrSize;
m_arraySize = col.m_arraySize;
m_keyInfoPos = col.m_keyInfoPos;
@@ -116,6 +111,8 @@ NdbColumnImpl::init(Type t)
break;
case Olddecimal:
case Olddecimalunsigned:
+ case Decimal:
+ case Decimalunsigned:
m_precision = 10;
m_scale = 0;
m_length = 1;
@@ -157,17 +154,32 @@ NdbColumnImpl::init(Type t)
m_length = 1;
m_cs = NULL;
break;
+ case Bit:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1;
+ m_cs = NULL;
+ break;
+ case Longvarchar:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1; // legal
+ m_cs = default_cs;
+ break;
+ case Longvarbinary:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1; // legal
+ m_cs = NULL;
+ break;
+ default:
case Undefined:
assert(false);
break;
}
m_pk = false;
m_nullable = false;
- m_tupleKey = false;
- m_indexOnly = false;
m_distributionKey = false;
- m_distributionGroup = false;
- m_distributionGroupBits = 8;
m_keyInfoPos = 0;
// next 2 are set at run time
m_attrSize = 0;
@@ -184,50 +196,40 @@ NdbColumnImpl::~NdbColumnImpl()
bool
NdbColumnImpl::equal(const NdbColumnImpl& col) const
{
+ DBUG_ENTER("NdbColumnImpl::equal");
if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
- return false;
+ DBUG_RETURN(false);
}
if(m_type != col.m_type){
- return false;
+ DBUG_RETURN(false);
}
if(m_pk != col.m_pk){
- return false;
+ DBUG_RETURN(false);
}
if(m_nullable != col.m_nullable){
- return false;
+ DBUG_RETURN(false);
}
+#ifdef ndb_dictionary_dkey_fixed
if(m_pk){
- if(m_tupleKey != col.m_tupleKey){
- return false;
- }
- if(m_indexOnly != col.m_indexOnly){
- return false;
- }
if(m_distributionKey != col.m_distributionKey){
- return false;
- }
- if(m_distributionGroup != col.m_distributionGroup){
- return false;
- }
- if(m_distributionGroup &&
- (m_distributionGroupBits != col.m_distributionGroupBits)){
- return false;
+ DBUG_RETURN(false);
}
}
+#endif
if (m_precision != col.m_precision ||
m_scale != col.m_scale ||
m_length != col.m_length ||
m_cs != col.m_cs) {
- return false;
+ DBUG_RETURN(false);
}
if (m_autoIncrement != col.m_autoIncrement){
- return false;
+ DBUG_RETURN(false);
}
if(strcmp(m_defaultValue.c_str(), col.m_defaultValue.c_str()) != 0){
- return false;
+ DBUG_RETURN(false);
}
- return true;
+ DBUG_RETURN(true);
}
NdbDictionary::Column *
@@ -239,6 +241,11 @@ NdbColumnImpl::create_psuedo(const char * name){
col->m_impl.m_attrId = AttributeHeader::FRAGMENT;
col->m_impl.m_attrSize = 4;
col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$FRAGMENT_MEMORY")){
+ col->setType(NdbDictionary::Column::Bigunsigned);
+ col->m_impl.m_attrId = AttributeHeader::FRAGMENT_MEMORY;
+ col->m_impl.m_attrSize = 8;
+ col->m_impl.m_arraySize = 1;
} else if(!strcmp(name, "NDB$ROW_COUNT")){
col->setType(NdbDictionary::Column::Bigunsigned);
col->m_impl.m_attrId = AttributeHeader::ROW_COUNT;
@@ -249,6 +256,16 @@ NdbColumnImpl::create_psuedo(const char * name){
col->m_impl.m_attrId = AttributeHeader::COMMIT_COUNT;
col->m_impl.m_attrSize = 8;
col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$ROW_SIZE")){
+ col->setType(NdbDictionary::Column::Unsigned);
+ col->m_impl.m_attrId = AttributeHeader::ROW_SIZE;
+ col->m_impl.m_attrSize = 4;
+ col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$RANGE_NO")){
+ col->setType(NdbDictionary::Column::Unsigned);
+ col->m_impl.m_attrId = AttributeHeader::RANGE_NO;
+ col->m_impl.m_attrSize = 4;
+ col->m_impl.m_arraySize = 1;
} else {
abort();
}
@@ -283,69 +300,86 @@ NdbTableImpl::~NdbTableImpl()
void
NdbTableImpl::init(){
- clearNewProperties();
+ m_changeMask= 0;
+ m_tableId= RNIL;
m_frm.clear();
- m_fragmentType = NdbDictionary::Object::FragAllSmall;
- m_logging = true;
- m_kvalue = 6;
- m_minLoadFactor = 78;
- m_maxLoadFactor = 80;
-
- m_index = 0;
- m_indexType = NdbDictionary::Index::Undefined;
-
- m_noOfKeys = 0;
- m_fragmentCount = 0;
- m_sizeOfKeysInWords = 0;
- m_noOfBlobs = 0;
+ m_fragmentType= NdbDictionary::Object::FragAllSmall;
+ m_hashValueMask= 0;
+ m_hashpointerValue= 0;
+ m_logging= true;
+ m_kvalue= 6;
+ m_minLoadFactor= 78;
+ m_maxLoadFactor= 80;
+ m_keyLenInWords= 0;
+ m_fragmentCount= 0;
+ m_dictionary= NULL;
+ m_index= NULL;
+ m_indexType= NdbDictionary::Index::Undefined;
+ m_noOfKeys= 0;
+ m_noOfDistributionKeys= 0;
+ m_noOfBlobs= 0;
+ m_replicaCount= 0;
}
bool
NdbTableImpl::equal(const NdbTableImpl& obj) const
{
+ DBUG_ENTER("NdbTableImpl::equal");
if ((m_internalName.c_str() == NULL) ||
(strcmp(m_internalName.c_str(), "") == 0) ||
(obj.m_internalName.c_str() == NULL) ||
(strcmp(obj.m_internalName.c_str(), "") == 0)) {
// Shallow equal
if(strcmp(getName(), obj.getName()) != 0){
- return false;
+ DBUG_PRINT("info",("name %s != %s",getName(),obj.getName()));
+ DBUG_RETURN(false);
}
} else
// Deep equal
if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0){
- return false;
+ {
+ DBUG_PRINT("info",("m_internalName %s != %s",
+ m_internalName.c_str(),obj.m_internalName.c_str()));
+ DBUG_RETURN(false);
+ }
}
if(m_fragmentType != obj.m_fragmentType){
- return false;
+ DBUG_PRINT("info",("m_fragmentType %d != %d",m_fragmentType,obj.m_fragmentType));
+ DBUG_RETURN(false);
}
if(m_columns.size() != obj.m_columns.size()){
- return false;
+ DBUG_PRINT("info",("m_columns.size %d != %d",m_columns.size(),obj.m_columns.size()));
+ DBUG_RETURN(false);
}
for(unsigned i = 0; i<obj.m_columns.size(); i++){
if(!m_columns[i]->equal(* obj.m_columns[i])){
- return false;
+ DBUG_PRINT("info",("m_columns [%d] != [%d]",i,i));
+ DBUG_RETURN(false);
}
}
if(m_logging != obj.m_logging){
- return false;
+ DBUG_PRINT("info",("m_logging %d != %d",m_logging,obj.m_logging));
+ DBUG_RETURN(false);
}
if(m_kvalue != obj.m_kvalue){
- return false;
+ DBUG_PRINT("info",("m_kvalue %d != %d",m_kvalue,obj.m_kvalue));
+ DBUG_RETURN(false);
}
if(m_minLoadFactor != obj.m_minLoadFactor){
- return false;
+ DBUG_PRINT("info",("m_minLoadFactor %d != %d",m_minLoadFactor,obj.m_minLoadFactor));
+ DBUG_RETURN(false);
}
if(m_maxLoadFactor != obj.m_maxLoadFactor){
- return false;
+ DBUG_PRINT("info",("m_maxLoadFactor %d != %d",m_maxLoadFactor,obj.m_maxLoadFactor));
+ DBUG_RETURN(false);
}
- return true;
+ DBUG_RETURN(true);
}
void
@@ -375,8 +409,9 @@ NdbTableImpl::assign(const NdbTableImpl& org)
delete m_index;
m_index = org.m_index;
+ m_noOfDistributionKeys = org.m_noOfDistributionKeys;
m_noOfKeys = org.m_noOfKeys;
- m_sizeOfKeysInWords = org.m_sizeOfKeysInWords;
+ m_keyLenInWords = org.m_keyLenInWords;
m_noOfBlobs = org.m_noOfBlobs;
m_version = org.m_version;
@@ -397,19 +432,6 @@ NdbTableImpl::getName() const
return m_newExternalName.c_str();
}
-void NdbTableImpl::clearNewProperties()
-{
- m_newExternalName.assign("");
- m_changeMask = 0;
-}
-
-void NdbTableImpl::copyNewProperties()
-{
- if (!m_newExternalName.empty()) {
- m_externalName.assign(m_newExternalName);
- AlterTableReq::setNameFlag(m_changeMask, true);
- }
-}
void
NdbTableImpl::buildColumnHash(){
@@ -477,6 +499,26 @@ NdbTableImpl::buildColumnHash(){
}
#endif
}
+
+Uint32
+NdbTableImpl::get_nodes(Uint32 hashValue, const Uint16 ** nodes) const
+{
+ if(m_replicaCount > 0)
+ {
+ Uint32 fragmentId = hashValue & m_hashValueMask;
+ if(fragmentId < m_hashpointerValue)
+ {
+ fragmentId = hashValue & ((m_hashValueMask << 1) + 1);
+ }
+ Uint32 pos = fragmentId * m_replicaCount;
+ if(pos + m_replicaCount <= m_fragments.size())
+ {
+ * nodes = m_fragments.getBase()+pos;
+ return m_replicaCount;
+ }
+ }
+ return 0;
+}
/**
* NdbIndexImpl
@@ -486,14 +528,22 @@ NdbIndexImpl::NdbIndexImpl() :
NdbDictionary::Index(* this),
m_facade(this)
{
- m_logging = true;
+ init();
}
NdbIndexImpl::NdbIndexImpl(NdbDictionary::Index & f) :
NdbDictionary::Index(* this),
m_facade(&f)
{
- m_logging = true;
+ init();
+}
+
+void NdbIndexImpl::init()
+{
+ m_indexId= RNIL;
+ m_type= NdbDictionary::Index::Undefined;
+ m_logging= true;
+ m_table= NULL;
}
NdbIndexImpl::~NdbIndexImpl(){
@@ -538,20 +588,26 @@ NdbEventImpl::NdbEventImpl() :
NdbDictionary::Event(* this),
m_facade(this)
{
- mi_type = 0;
- m_dur = NdbDictionary::Event::ED_UNDEFINED;
- eventOp = NULL;
- m_tableImpl = NULL;
+ init();
}
NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
NdbDictionary::Event(* this),
m_facade(&f)
{
- mi_type = 0;
- m_dur = NdbDictionary::Event::ED_UNDEFINED;
- eventOp = NULL;
- m_tableImpl = NULL;
+ init();
+}
+
+void NdbEventImpl::init()
+{
+ m_eventId= RNIL;
+ m_eventKey= RNIL;
+ m_tableId= RNIL;
+ mi_type= 0;
+ m_dur= NdbDictionary::Event::ED_UNDEFINED;
+ m_tableImpl= NULL;
+ m_bufferId= RNIL;
+ eventOp= NULL;
}
NdbEventImpl::~NdbEventImpl()
@@ -565,24 +621,30 @@ void NdbEventImpl::setName(const char * name)
m_externalName.assign(name);
}
+const char *NdbEventImpl::getName() const
+{
+ return m_externalName.c_str();
+}
+
+void
+NdbEventImpl::setTable(const NdbDictionary::Table& table)
+{
+ m_tableImpl= &NdbTableImpl::getImpl(table);
+ m_tableName.assign(m_tableImpl->getName());
+}
+
void
NdbEventImpl::setTable(const char * table)
{
m_tableName.assign(table);
}
-const char *
-NdbEventImpl::getTable() const
+const char *
+NdbEventImpl::getTableName() const
{
return m_tableName.c_str();
}
-const char *
-NdbEventImpl::getName() const
-{
- return m_externalName.c_str();
-}
-
void
NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t = NdbDictionary::Event::TE_ALL)
{
@@ -595,11 +657,22 @@ NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t = NdbDicti
}
void
-NdbEventImpl::setDurability(const NdbDictionary::Event::EventDurability d)
+NdbEventImpl::setDurability(NdbDictionary::Event::EventDurability d)
{
m_dur = d;
}
+NdbDictionary::Event::EventDurability
+NdbEventImpl::getDurability() const
+{
+ return m_dur;
+}
+
+int NdbEventImpl::getNoOfEventColumns() const
+{
+ return m_attrIds.size() + m_columns.size();
+}
+
/**
* NdbDictionaryImpl
*/
@@ -643,11 +716,17 @@ NdbDictionaryImpl::~NdbDictionaryImpl()
m_globalHash->lock();
if(--f_dictionary_count == 0){
delete NdbDictionary::Column::FRAGMENT;
+ delete NdbDictionary::Column::FRAGMENT_MEMORY;
delete NdbDictionary::Column::ROW_COUNT;
delete NdbDictionary::Column::COMMIT_COUNT;
+ delete NdbDictionary::Column::ROW_SIZE;
+ delete NdbDictionary::Column::RANGE_NO;
NdbDictionary::Column::FRAGMENT= 0;
+ NdbDictionary::Column::FRAGMENT_MEMORY= 0;
NdbDictionary::Column::ROW_COUNT= 0;
NdbDictionary::Column::COMMIT_COUNT= 0;
+ NdbDictionary::Column::ROW_SIZE= 0;
+ NdbDictionary::Column::RANGE_NO= 0;
}
m_globalHash->unlock();
} else {
@@ -656,19 +735,19 @@ NdbDictionaryImpl::~NdbDictionaryImpl()
}
Ndb_local_table_info *
-NdbDictionaryImpl::fetchGlobalTableImpl(const char * internalTableName)
+NdbDictionaryImpl::fetchGlobalTableImpl(const BaseString& internalTableName)
{
NdbTableImpl *impl;
m_globalHash->lock();
- impl = m_globalHash->get(internalTableName);
+ impl = m_globalHash->get(internalTableName.c_str());
m_globalHash->unlock();
if (impl == 0){
impl = m_receiver.getTable(internalTableName,
m_ndb.usingFullyQualifiedNames());
m_globalHash->lock();
- m_globalHash->put(internalTableName, impl);
+ m_globalHash->put(internalTableName.c_str(), impl);
m_globalHash->unlock();
if(impl == 0){
@@ -679,7 +758,7 @@ NdbDictionaryImpl::fetchGlobalTableImpl(const char * internalTableName)
Ndb_local_table_info *info=
Ndb_local_table_info::create(impl, m_local_table_data_size);
- m_localHash.put(internalTableName, info);
+ m_localHash.put(internalTableName.c_str(), info);
m_ndb.theFirstTupleId[impl->getTableId()] = ~0;
m_ndb.theLastTupleId[impl->getTableId()] = ~0;
@@ -710,10 +789,16 @@ NdbDictionaryImpl::setTransporter(class Ndb* ndb,
if(f_dictionary_count++ == 0){
NdbDictionary::Column::FRAGMENT=
NdbColumnImpl::create_psuedo("NDB$FRAGMENT");
+ NdbDictionary::Column::FRAGMENT_MEMORY=
+ NdbColumnImpl::create_psuedo("NDB$FRAGMENT_MEMORY");
NdbDictionary::Column::ROW_COUNT=
NdbColumnImpl::create_psuedo("NDB$ROW_COUNT");
NdbDictionary::Column::COMMIT_COUNT=
NdbColumnImpl::create_psuedo("NDB$COMMIT_COUNT");
+ NdbDictionary::Column::ROW_SIZE=
+ NdbColumnImpl::create_psuedo("NDB$ROW_SIZE");
+ NdbDictionary::Column::RANGE_NO=
+ NdbColumnImpl::create_psuedo("NDB$RANGE_NO");
}
m_globalHash->unlock();
return true;
@@ -721,14 +806,13 @@ NdbDictionaryImpl::setTransporter(class Ndb* ndb,
return false;
}
-NdbTableImpl *
-NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
+NdbTableImpl *
+NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
NdbTableImpl * table)
{
- const char * internalName =
- m_ndb.internalizeIndexName(table, index->getName());
-
- return getTable(m_ndb.externalizeTableName(internalName));
+ const BaseString internalName(
+ m_ndb.internalize_index_name(table, index->getName()));
+ return getTable(m_ndb.externalizeTableName(internalName.c_str()));
}
#if 0
@@ -745,7 +829,7 @@ NdbDictInterface::setTransporter(class TransporterFacade * tf)
execNodeStatus);
if ( m_blockNumber == -1 ) {
- m_error.code = 4105;
+ m_error.code= 4105;
return false; // no more free blocknumbers
}//if
Uint32 theNode = tf->ownId();
@@ -899,7 +983,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
aNodeId = m_transporter->get_an_alive_node();
}
if(aNodeId == 0){
- m_error.code = 4009;
+ m_error.code= 4009;
m_transporter->unlock_mutex();
DBUG_RETURN(-1);
}
@@ -926,7 +1010,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
}
}
- m_error.code = 0;
+ m_error.code= 0;
m_waiter.m_node = aNodeId;
m_waiter.m_state = wst;
@@ -960,7 +1044,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
for (int j=0; j < noerrcodes; j++)
if(m_error.code == errcodes[j]) {
doContinue = 1;
- continue;
+ break;
}
if (doContinue)
continue;
@@ -970,79 +1054,91 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
}
DBUG_RETURN(-1);
}
+#if 0
+/*
+ Get dictionary information for a table using table id as reference
-/*****************************************************************
- * get tab info
+ DESCRIPTION
+ Sends a GET_TABINFOREQ signal containing the table id
*/
-NdbTableImpl *
+NdbTableImpl *
NdbDictInterface::getTable(int tableId, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
- GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
-
+ GetTabInfoReq* const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
req->senderRef = m_reference;
req->senderData = 0;
- req->requestType =
+ req->requestType =
GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
req->tableId = tableId;
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
tSignal.theLength = GetTabInfoReq::SignalLength;
-
+
return getTable(&tSignal, 0, 0, fullyQualifiedNames);
}
+#endif
+
+
+/*
+ Get dictionary information for a table using table name as the reference
+
+ DESCRIPTION
+ Send GET_TABINFOREQ signal with the table name in the first
+ long section part
+*/
-NdbTableImpl *
-NdbDictInterface::getTable(const char * name, bool fullyQualifiedNames)
+NdbTableImpl *
+NdbDictInterface::getTable(const BaseString& name, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
- GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
-
- const Uint32 strLen = strlen(name) + 1; // NULL Terminated
- if(strLen > MAX_TAB_NAME_SIZE) {//sizeof(req->tableName)){
- m_error.code = 4307;
- return 0;
- }
+ GetTabInfoReq* const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
- // avoid alignment problem and memory overrun
- Uint32 name_buf[(MAX_TAB_NAME_SIZE + 3) / 4];
- strncpy((char*)name_buf, name, sizeof(name_buf)); // strncpy null-pads
- name = (char*)name_buf;
+ const Uint32 namelen= name.length() + 1; // NULL terminated
+ const Uint32 namelen_words= (namelen + 3) >> 2; // Size in words
- req->senderRef = m_reference;
- req->senderData = 0;
- req->requestType =
+ req->senderRef= m_reference;
+ req->senderData= 0;
+ req->requestType=
GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
- req->tableNameLen = strLen;
- tSignal.theReceiversBlockNumber = DBDICT;
- tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
- // tSignal.theLength = GetTabInfoReq::HeaderLength + ((strLen + 3) / 4);
- tSignal.theLength = GetTabInfoReq::SignalLength;
+ req->tableNameLen= namelen;
+ tSignal.theReceiversBlockNumber= DBDICT;
+ tSignal.theVerId_signalNumber= GSN_GET_TABINFOREQ;
+ tSignal.theLength= GetTabInfoReq::SignalLength;
+
+ // Copy name to m_buffer to get a word sized buffer
+ m_buffer.clear();
+ m_buffer.grow(namelen_words*4);
+ m_buffer.append(name.c_str(), namelen);
+
LinearSectionPtr ptr[1];
- ptr[0].p = (Uint32*)name;
- ptr[0].sz = (strLen + 3) / 4;
-
+ ptr[0].p= (Uint32*)m_buffer.get_data();
+ ptr[0].sz= namelen_words;
+
return getTable(&tSignal, ptr, 1, fullyQualifiedNames);
}
+
NdbTableImpl *
-NdbDictInterface::getTable(class NdbApiSignal * signal,
+NdbDictInterface::getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
Uint32 noOfSections, bool fullyQualifiedNames)
{
- //GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, signal->getDataPtrSend());
+ int errCodes[] = {GetTabInfoRef::Busy };
+
int r = dictSignal(signal,ptr,noOfSections,
0/*do not use masternode id*/,
100,
WAIT_GET_TAB_INFO_REQ,
WAITFOR_RESPONSE_TIMEOUT,
- NULL,0);
+ errCodes, 1);
if (r) return 0;
NdbTableImpl * rt = 0;
- m_error.code = parseTableInfo(&rt,
- (Uint32*)m_buffer.get_data(),
- m_buffer.length() / 4, fullyQualifiedNames);
+ m_error.code= parseTableInfo(&rt,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4, fullyQualifiedNames);
rt->buildColumnHash();
return rt;
}
@@ -1077,7 +1173,7 @@ NdbDictInterface::execGET_TABINFO_REF(NdbApiSignal * signal,
{
const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef, signal->getDataPtr());
- m_error.code = ref->errorCode;
+ m_error.code= ref->errorCode;
m_waiter.signal(NO_WAIT);
}
@@ -1133,8 +1229,6 @@ objectTypeMapping[] = {
{ DictTabInfo::SystemTable, NdbDictionary::Object::SystemTable },
{ DictTabInfo::UserTable, NdbDictionary::Object::UserTable },
{ DictTabInfo::UniqueHashIndex, NdbDictionary::Object::UniqueHashIndex },
- { DictTabInfo::HashIndex, NdbDictionary::Object::HashIndex },
- { DictTabInfo::UniqueOrderedIndex, NdbDictionary::Object::UniqueOrderedIndex },
{ DictTabInfo::OrderedIndex, NdbDictionary::Object::OrderedIndex },
{ DictTabInfo::HashIndexTrigger, NdbDictionary::Object::HashIndexTrigger },
{ DictTabInfo::IndexTrigger, NdbDictionary::Object::IndexTrigger },
@@ -1167,49 +1261,17 @@ static const
ApiKernelMapping
indexTypeMapping[] = {
{ DictTabInfo::UniqueHashIndex, NdbDictionary::Index::UniqueHashIndex },
- { DictTabInfo::HashIndex, NdbDictionary::Index::HashIndex },
- { DictTabInfo::UniqueOrderedIndex, NdbDictionary::Index::UniqueOrderedIndex},
{ DictTabInfo::OrderedIndex, NdbDictionary::Index::OrderedIndex },
{ -1, -1 }
};
-// TODO: remove, api-kernel type codes must match now
-static const
-ApiKernelMapping
-columnTypeMapping[] = {
- { DictTabInfo::ExtTinyint, NdbDictionary::Column::Tinyint },
- { DictTabInfo::ExtTinyunsigned, NdbDictionary::Column::Tinyunsigned },
- { DictTabInfo::ExtSmallint, NdbDictionary::Column::Smallint },
- { DictTabInfo::ExtSmallunsigned, NdbDictionary::Column::Smallunsigned },
- { DictTabInfo::ExtMediumint, NdbDictionary::Column::Mediumint },
- { DictTabInfo::ExtMediumunsigned, NdbDictionary::Column::Mediumunsigned },
- { DictTabInfo::ExtInt, NdbDictionary::Column::Int },
- { DictTabInfo::ExtUnsigned, NdbDictionary::Column::Unsigned },
- { DictTabInfo::ExtBigint, NdbDictionary::Column::Bigint },
- { DictTabInfo::ExtBigunsigned, NdbDictionary::Column::Bigunsigned },
- { DictTabInfo::ExtFloat, NdbDictionary::Column::Float },
- { DictTabInfo::ExtDouble, NdbDictionary::Column::Double },
- { DictTabInfo::ExtOlddecimal, NdbDictionary::Column::Olddecimal },
- { DictTabInfo::ExtOlddecimalunsigned, NdbDictionary::Column::Olddecimalunsigned },
- { DictTabInfo::ExtChar, NdbDictionary::Column::Char },
- { DictTabInfo::ExtVarchar, NdbDictionary::Column::Varchar },
- { DictTabInfo::ExtBinary, NdbDictionary::Column::Binary },
- { DictTabInfo::ExtVarbinary, NdbDictionary::Column::Varbinary },
- { DictTabInfo::ExtDatetime, NdbDictionary::Column::Datetime },
- { DictTabInfo::ExtDate, NdbDictionary::Column::Date },
- { DictTabInfo::ExtBlob, NdbDictionary::Column::Blob },
- { DictTabInfo::ExtText, NdbDictionary::Column::Text },
- { DictTabInfo::ExtTime, NdbDictionary::Column::Time },
- { DictTabInfo::ExtYear, NdbDictionary::Column::Year },
- { DictTabInfo::ExtTimestamp, NdbDictionary::Column::Timestamp },
- { -1, -1 }
-};
-
int
NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
const Uint32 * data, Uint32 len,
bool fullyQualifiedNames)
{
+ DBUG_ENTER("NdbDictInterface::parseTableInfo");
+
SimplePropertiesLinearReader it(data, len);
DictTabInfo::Table tableDesc; tableDesc.init();
SimpleProperties::UnpackStatus s;
@@ -1219,7 +1281,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
true, true);
if(s != SimpleProperties::Break){
- return 703;
+ DBUG_RETURN(703);
}
const char * internalName = tableDesc.TableName;
const char * externalName = Ndb::externalizeTableName(internalName, fullyQualifiedNames);
@@ -1242,7 +1304,6 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_kvalue = tableDesc.TableKValue;
impl->m_minLoadFactor = tableDesc.MinLoadFactor;
impl->m_maxLoadFactor = tableDesc.MaxLoadFactor;
- impl->m_fragmentCount = tableDesc.FragmentCount;
impl->m_indexType = (NdbDictionary::Index::Type)
getApiConstant(tableDesc.TableType,
@@ -1259,8 +1320,10 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
Uint32 keyInfoPos = 0;
Uint32 keyCount = 0;
Uint32 blobCount = 0;
+ Uint32 distKeys = 0;
- for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) {
+ Uint32 i;
+ for(i = 0; i < tableDesc.NoOfAttributes; i++) {
DictTabInfo::Attribute attrDesc; attrDesc.init();
s = SimpleProperties::unpack(it,
&attrDesc,
@@ -1269,21 +1332,19 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
true, true);
if(s != SimpleProperties::Break){
delete impl;
- return 703;
+ DBUG_RETURN(703);
}
NdbColumnImpl * col = new NdbColumnImpl();
col->m_attrId = attrDesc.AttributeId;
col->setName(attrDesc.AttributeName);
- col->m_type = (NdbDictionary::Column::Type)
- getApiConstant(attrDesc.AttributeExtType,
- columnTypeMapping,
- NdbDictionary::Column::Undefined);
- if (col->m_type == NdbDictionary::Column::Undefined) {
+
+ // check type and compute attribute size and array size
+ if (! attrDesc.translateExtType()) {
delete impl;
- return 703;
+ DBUG_RETURN(703);
}
- col->m_extType = attrDesc.AttributeExtType;
+ col->m_type = (NdbDictionary::Column::Type)attrDesc.AttributeExtType;
col->m_precision = (attrDesc.AttributeExtPrecision & 0xFFFF);
col->m_scale = attrDesc.AttributeExtScale;
col->m_length = attrDesc.AttributeExtLength;
@@ -1292,32 +1353,26 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
// charset is defined exactly for char types
if (col->getCharType() != (cs_number != 0)) {
delete impl;
- return 703;
+ DBUG_RETURN(703);
}
if (col->getCharType()) {
col->m_cs = get_charset(cs_number, MYF(0));
if (col->m_cs == NULL) {
delete impl;
- return 743;
+ DBUG_RETURN(743);
}
}
-
- // translate to old kernel types and sizes
- if (! attrDesc.translateExtType()) {
- delete impl;
- return 703;
- }
- col->m_attrType =attrDesc.AttributeType;
col->m_attrSize = (1 << attrDesc.AttributeSize) / 8;
col->m_arraySize = attrDesc.AttributeArraySize;
+ if(attrDesc.AttributeSize == 0)
+ {
+ col->m_attrSize = 4;
+ col->m_arraySize = (attrDesc.AttributeArraySize + 31) >> 5;
+ }
col->m_pk = attrDesc.AttributeKeyFlag;
- col->m_tupleKey = 0;
col->m_distributionKey = attrDesc.AttributeDKey;
- col->m_distributionGroup = attrDesc.AttributeDGroup;
- col->m_distributionGroupBits = 16;
col->m_nullable = attrDesc.AttributeNullableFlag;
- col->m_indexOnly = (attrDesc.AttributeStoredInd ? false : true);
col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false);
col->m_autoIncrementInitialValue = ~0;
col->m_defaultValue.assign(attrDesc.AttributeDefaultValue);
@@ -1326,6 +1381,9 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
col->m_keyInfoPos = keyInfoPos + 1;
keyInfoPos += ((col->m_attrSize * col->m_arraySize + 3) / 4);
keyCount++;
+
+ if(attrDesc.AttributeDKey)
+ distKeys++;
} else {
col->m_keyInfoPos = 0;
}
@@ -1336,7 +1394,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
if(impl->m_columns[attrDesc.AttributeId] != 0){
delete col;
delete impl;
- return 703;
+ DBUG_RETURN(703);
}
impl->m_columns[attrDesc.AttributeId] = col;
it.next();
@@ -1344,10 +1402,49 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_noOfKeys = keyCount;
impl->m_keyLenInWords = keyInfoPos;
- impl->m_sizeOfKeysInWords = keyInfoPos;
impl->m_noOfBlobs = blobCount;
+ impl->m_noOfDistributionKeys = distKeys;
+
+ if(tableDesc.FragmentDataLen > 0)
+ {
+ Uint32 replicaCount = tableDesc.FragmentData[0];
+ Uint32 fragCount = tableDesc.FragmentData[1];
+
+ impl->m_replicaCount = replicaCount;
+ impl->m_fragmentCount = fragCount;
+
+ for(i = 0; i<(fragCount*replicaCount); i++)
+ {
+ impl->m_fragments.push_back(tableDesc.FragmentData[i+2]);
+ }
+
+ Uint32 topBit = (1 << 31);
+ for(; topBit && !(fragCount & topBit); ){
+ topBit >>= 1;
+ }
+ impl->m_hashValueMask = topBit - 1;
+ impl->m_hashpointerValue = fragCount - (impl->m_hashValueMask + 1);
+ }
+ else
+ {
+ impl->m_fragmentCount = tableDesc.FragmentCount;
+ impl->m_replicaCount = 0;
+ impl->m_hashValueMask = 0;
+ impl->m_hashpointerValue = 0;
+ }
+
+ if(distKeys == 0)
+ {
+ for(i = 0; i < tableDesc.NoOfAttributes; i++)
+ {
+ if(impl->m_columns[i]->getPrimaryKey())
+ impl->m_columns[i]->m_distributionKey = true;
+ }
+ }
+
* ret = impl;
- return 0;
+
+ DBUG_RETURN(0);
}
/*****************************************************************
@@ -1362,15 +1459,15 @@ NdbDictionaryImpl::createTable(NdbTableImpl &t)
return 0;
// update table def from DICT
Ndb_local_table_info *info=
- get_local_table_info(t.m_internalName.c_str(),false);
+ get_local_table_info(t.m_internalName,false);
if (info == NULL) {
- m_error.code = 709;
+ m_error.code= 709;
return -1;
}
if (createBlobTables(*(info->m_table_impl)) != 0) {
int save_code = m_error.code;
(void)dropTable(t);
- m_error.code = save_code;
+ m_error.code= save_code;
return -1;
}
return 0;
@@ -1389,7 +1486,7 @@ NdbDictionaryImpl::createBlobTables(NdbTableImpl &t)
return -1;
// Save BLOB table handle
Ndb_local_table_info *info=
- get_local_table_info(bt.m_internalName.c_str(),false);
+ get_local_table_info(bt.m_internalName, false);
if (info == 0) {
return -1;
}
@@ -1433,10 +1530,8 @@ NdbDictInterface::createTable(Ndb & ndb,
int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
{
- BaseString internalName = impl.m_internalName;
+ BaseString internalName(impl.m_internalName);
const char * originalInternalName = internalName.c_str();
- BaseString externalName = impl.m_externalName;
- const char * originalExternalName = externalName.c_str();
DBUG_ENTER("NdbDictionaryImpl::alterTable");
Ndb_local_table_info * local = 0;
@@ -1474,47 +1569,54 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
DBUG_ENTER("NdbDictInterface::createOrAlterTable");
unsigned i;
if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
- m_error.code = 4317;
+ m_error.code= 4317;
DBUG_RETURN(-1);
}
unsigned sz = impl.m_columns.size();
if (sz > NDB_MAX_ATTRIBUTES_IN_TABLE){
- m_error.code = 4318;
+ m_error.code= 4318;
DBUG_RETURN(-1);
}
- impl.copyNewProperties();
+ if (!impl.m_newExternalName.empty()) {
+ impl.m_externalName.assign(impl.m_newExternalName);
+ AlterTableReq::setNameFlag(impl.m_changeMask, true);
+ }
+
//validate();
//aggregate();
- const char * internalName =
- ndb.internalizeTableName(impl.m_externalName.c_str());
+ const BaseString internalName(
+ ndb.internalize_table_name(impl.m_externalName.c_str()));
impl.m_internalName.assign(internalName);
UtilBufferWriter w(m_buffer);
DictTabInfo::Table tmpTab; tmpTab.init();
- BaseString::snprintf(tmpTab.TableName,
- sizeof(tmpTab.TableName),
- internalName);
+ BaseString::snprintf(tmpTab.TableName,
+ sizeof(tmpTab.TableName),
+ internalName.c_str());
bool haveAutoIncrement = false;
Uint64 autoIncrementValue = 0;
+ Uint32 distKeys= 0;
for(i = 0; i<sz; i++){
const NdbColumnImpl * col = impl.m_columns[i];
if(col == 0)
continue;
if (col->m_autoIncrement) {
if (haveAutoIncrement) {
- m_error.code = 4335;
+ m_error.code= 4335;
DBUG_RETURN(-1);
}
haveAutoIncrement = true;
autoIncrementValue = col->m_autoIncrementInitialValue;
- }
+ }
+ if (col->m_distributionKey)
+ distKeys++;
}
// Check max length of frm data
if (impl.m_frm.length() > MAX_FRM_DATA_SIZE){
- m_error.code = 1229;
+ m_error.code= 1229;
DBUG_RETURN(-1);
}
tmpTab.FrmLen = impl.m_frm.length();
@@ -1542,6 +1644,10 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
abort();
}
+ if (distKeys == impl.m_noOfKeys)
+ distKeys= 0;
+ impl.m_noOfDistributionKeys= distKeys;
+
for(i = 0; i<sz; i++){
const NdbColumnImpl * col = impl.m_columns[i];
if(col == 0)
@@ -1551,27 +1657,33 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
col->m_name.c_str());
tmpAttr.AttributeId = i;
- tmpAttr.AttributeKeyFlag = col->m_pk || col->m_tupleKey;
+ tmpAttr.AttributeKeyFlag = col->m_pk;
tmpAttr.AttributeNullableFlag = col->m_nullable;
- tmpAttr.AttributeStoredInd = (col->m_indexOnly ? 0 : 1);
- tmpAttr.AttributeDKey = col->m_distributionKey;
- tmpAttr.AttributeDGroup = col->m_distributionGroup;
-
- tmpAttr.AttributeExtType =
- getKernelConstant(col->m_type,
- columnTypeMapping,
- DictTabInfo::ExtUndefined);
+ tmpAttr.AttributeDKey = distKeys ? col->m_distributionKey : 0;
+
+ tmpAttr.AttributeExtType = (Uint32)col->m_type;
tmpAttr.AttributeExtPrecision = ((unsigned)col->m_precision & 0xFFFF);
tmpAttr.AttributeExtScale = col->m_scale;
tmpAttr.AttributeExtLength = col->m_length;
+
+ // check type and compute attribute size and array size
+ if (! tmpAttr.translateExtType()) {
+ m_error.code= 703;
+ DBUG_RETURN(-1);
+ }
// charset is defined exactly for char types
if (col->getCharType() != (col->m_cs != NULL)) {
- m_error.code = 703;
+ m_error.code= 703;
DBUG_RETURN(-1);
}
// primary key type check
if (col->m_pk && ! NdbSqlUtil::usable_in_pk(col->m_type, col->m_cs)) {
- m_error.code = 743;
+ m_error.code= (col->m_cs != 0 ? 743 : 739);
+ DBUG_RETURN(-1);
+ }
+ // distribution key not supported for Char attribute
+ if (distKeys && col->m_distributionKey && col->m_cs != NULL) {
+ m_error.code= 745;
DBUG_RETURN(-1);
}
// charset in upper half of precision
@@ -1579,9 +1691,6 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
tmpAttr.AttributeExtPrecision |= (col->m_cs->number << 16);
}
- // DICT will ignore and recompute this
- (void)tmpAttr.translateExtType();
-
tmpAttr.AttributeAutoIncrement = col->m_autoIncrement;
BaseString::snprintf(tmpAttr.AttributeDefaultValue,
sizeof(tmpAttr.AttributeDefaultValue),
@@ -1596,7 +1705,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
- LinearSectionPtr ptr[3];
+ LinearSectionPtr ptr[1];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = m_buffer.length() / 4;
int ret;
@@ -1632,7 +1741,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
autoIncrementValue)) {
if (ndb.theError.code == 0) {
- m_error.code = 4336;
+ m_error.code= 4336;
ndb.theError = m_error;
} else
m_error= ndb.theError;
@@ -1668,11 +1777,12 @@ void
NdbDictInterface::execCREATE_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
+#if 0
const CreateTableConf* const conf=
CAST_CONSTPTR(CreateTableConf, signal->getDataPtr());
Uint32 tableId= conf->tableId;
Uint32 tableVersion= conf->tableVersion;
-
+#endif
m_waiter.signal(NO_WAIT);
}
@@ -1682,7 +1792,7 @@ NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * signal,
{
const CreateTableRef* const ref=
CAST_CONSTPTR(CreateTableRef, signal->getDataPtr());
- m_error.code = ref->errorCode;
+ m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
@@ -1726,7 +1836,7 @@ NdbDictInterface::execALTER_TABLE_REF(NdbApiSignal * signal,
{
const AlterTableRef * const ref =
CAST_CONSTPTR(AlterTableRef, signal->getDataPtr());
- m_error.code = ref->errorCode;
+ m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
@@ -1741,20 +1851,20 @@ NdbDictionaryImpl::dropTable(const char * name)
DBUG_PRINT("enter",("name: %s", name));
NdbTableImpl * tab = getTable(name);
if(tab == 0){
- return -1;
+ DBUG_RETURN(-1);
}
int ret = dropTable(* tab);
// If table stored in cache is incompatible with the one in the kernel
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
- const char * internalTableName = m_ndb.internalizeTableName(name);
+ const BaseString internalTableName(m_ndb.internalize_table_name(name));
- DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName));
- m_localHash.drop(internalTableName);
+ DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName.c_str()));
+ m_localHash.drop(internalTableName.c_str());
m_globalHash->lock();
tab->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(tab);
- m_globalHash->unlock();
+ m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
}
@@ -1771,7 +1881,7 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
}
if (impl.m_indexType != NdbDictionary::Index::Undefined) {
- m_receiver.m_error.code = 1228;
+ m_receiver.m_error.code= 1228;
return -1;
}
@@ -1872,32 +1982,37 @@ void
NdbDictInterface::execDROP_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
+ DBUG_ENTER("NdbDictInterface::execDROP_TABLE_CONF");
//DropTableConf* const conf = CAST_CONSTPTR(DropTableConf, signal->getDataPtr());
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execDROP_TABLE_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
+ DBUG_ENTER("NdbDictInterface::execDROP_TABLE_REF");
const DropTableRef* const ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
- m_error.code = ref->errorCode;
+ m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
int
NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
{
const char * internalTableName = impl.m_internalName.c_str();
-
- m_localHash.drop(internalTableName);
+ DBUG_ENTER("NdbDictionaryImpl::invalidateObject");
+ DBUG_PRINT("enter", ("internal_name: %s", internalTableName));
+ m_localHash.drop(internalTableName);
m_globalHash->lock();
impl.m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(&impl);
m_globalHash->unlock();
- return 0;
+ DBUG_RETURN(0);
}
int
@@ -1916,8 +2031,8 @@ NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
* Get index info
*/
NdbIndexImpl*
-NdbDictionaryImpl::getIndexImpl(const char * externalName,
- const char * internalName)
+NdbDictionaryImpl::getIndexImpl(const char * externalName,
+ const BaseString& internalName)
{
Ndb_local_table_info * info = get_local_table_info(internalName,
false);
@@ -1938,7 +2053,7 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
m_error.code = 4243;
return 0;
}
-
+
/**
* Create index impl
*/
@@ -1957,7 +2072,7 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
int
NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
- const NdbTableImpl* tab,
+ NdbTableImpl* tab,
const NdbTableImpl* prim){
NdbIndexImpl *idx = new NdbIndexImpl();
idx->m_version = tab->m_version;
@@ -1965,22 +2080,49 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
idx->m_indexId = tab->m_tableId;
idx->m_externalName.assign(tab->getName());
idx->m_tableName.assign(prim->m_externalName);
- idx->m_type = tab->m_indexType;
+ NdbDictionary::Index::Type type = idx->m_type = tab->m_indexType;
idx->m_logging = tab->m_logging;
// skip last attribute (NDB$PK or NDB$TNODE)
- for(unsigned i = 0; i+1<tab->m_columns.size(); i++){
+
+ const Uint32 distKeys = prim->m_noOfDistributionKeys;
+ Uint32 keyCount = (distKeys ? distKeys : prim->m_noOfKeys);
+
+ unsigned i;
+ for(i = 0; i+1<tab->m_columns.size(); i++){
+ NdbColumnImpl* org = tab->m_columns[i];
+
NdbColumnImpl* col = new NdbColumnImpl;
// Copy column definition
- *col = *tab->m_columns[i];
+ *col = * org;
idx->m_columns.push_back(col);
+
/**
* reverse map
*/
- int key_id = prim->getColumn(col->getName())->getColumnNo();
+ const NdbColumnImpl* primCol = prim->getColumn(col->getName());
+ int key_id = primCol->getColumnNo();
int fill = -1;
idx->m_key_ids.fill(key_id, fill);
idx->m_key_ids[key_id] = i;
col->m_keyInfoPos = key_id;
+
+ if(type == NdbDictionary::Index::OrderedIndex &&
+ (primCol->m_distributionKey ||
+ (distKeys == 0 && primCol->getPrimaryKey())))
+ {
+ keyCount--;
+ org->m_distributionKey = 1;
+ }
+ }
+
+ if(keyCount == 0)
+ {
+ tab->m_noOfDistributionKeys = (distKeys ? distKeys : prim->m_noOfKeys);
+ }
+ else
+ {
+ for(i = 0; i+1<tab->m_columns.size(); i++)
+ tab->m_columns[i]->m_distributionKey = 0;
}
* dst = idx;
@@ -2016,12 +2158,11 @@ NdbDictInterface::createIndex(Ndb & ndb,
m_error.code = 4241;
return -1;
}
- const char * internalName =
- ndb.internalizeIndexName(&table, impl.getName());
-
+ const BaseString internalName(
+ ndb.internalize_index_name(&table, impl.getName()));
impl.m_internalName.assign(internalName);
- w.add(DictTabInfo::TableName, internalName);
+ w.add(DictTabInfo::TableName, internalName.c_str());
w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
NdbApiSignal tSignal(m_reference);
@@ -2059,10 +2200,6 @@ NdbDictInterface::createIndex(Ndb & ndb,
// Copy column definition
*impl.m_columns[i] = *col;
- if(col->m_pk && col->m_indexOnly){
- m_error.code = 4245;
- return -1;
- }
// index key type check
if (it == DictTabInfo::UniqueHashIndex &&
! NdbSqlUtil::usable_in_hash_index(col->m_type, col->m_cs) ||
@@ -2073,27 +2210,7 @@ NdbDictInterface::createIndex(Ndb & ndb,
}
attributeList.id[i] = col->m_attrId;
}
- if (it == DictTabInfo::UniqueHashIndex) {
- // Sort index attributes according to primary table (using insertion sort)
- for(i = 1; i < attributeList.sz; i++) {
- unsigned int temp = attributeList.id[i];
- unsigned int j = i;
- while((j > 0) && (attributeList.id[j - 1] > temp)) {
- attributeList.id[j] = attributeList.id[j - 1];
- j--;
- }
- attributeList.id[j] = temp;
- }
- // Check for illegal duplicate attributes
- for(i = 0; i<attributeList.sz; i++) {
- if ((i != (attributeList.sz - 1)) &&
- (attributeList.id[i] == attributeList.id[i+1])) {
- m_error.code = 4258;
- return -1;
- }
- }
- }
- LinearSectionPtr ptr[3];
+ LinearSectionPtr ptr[2];
ptr[0].p = (Uint32*)&attributeList;
ptr[0].sz = 1 + attributeList.sz;
ptr[1].p = (Uint32*)m_buffer.get_data();
@@ -2151,20 +2268,20 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
// If index stored in cache is incompatible with the one in the kernel
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
- const char * internalIndexName = (tableName)
+ const BaseString internalIndexName((tableName)
?
- m_ndb.internalizeIndexName(getTable(tableName), indexName)
+ m_ndb.internalize_index_name(getTable(tableName), indexName)
:
- m_ndb.internalizeTableName(indexName); // Index is also a table
-
- m_localHash.drop(internalIndexName);
+ m_ndb.internalize_table_name(indexName)); // Index is also a table
+
+ m_localHash.drop(internalIndexName.c_str());
m_globalHash->lock();
idx->m_table->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(idx->m_table);
- m_globalHash->unlock();
+ m_globalHash->unlock();
return dropIndex(indexName, tableName);
}
-
+
return ret;
}
@@ -2180,19 +2297,19 @@ NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
return -1;
}
- const char * internalIndexName = (tableName)
+ const BaseString internalIndexName((tableName)
?
- m_ndb.internalizeIndexName(getTable(tableName), indexName)
+ m_ndb.internalize_index_name(getTable(tableName), indexName)
:
- m_ndb.internalizeTableName(indexName); // Index is also a table
+ m_ndb.internalize_table_name(indexName)); // Index is also a table
if(impl.m_status == NdbDictionary::Object::New){
return dropIndex(indexName, tableName);
}
-
+
int ret = m_receiver.dropIndex(impl, *timpl);
if(ret == 0){
- m_localHash.drop(internalIndexName);
+ m_localHash.drop(internalIndexName.c_str());
m_globalHash->lock();
impl.m_table->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(impl.m_table);
@@ -2269,13 +2386,12 @@ int
NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
{
int i;
- NdbTableImpl* tab = getTable(evnt.getTable());
+ NdbTableImpl* tab = getTable(evnt.getTableName());
if(tab == 0){
- // m_error.code = 3249;
- ndbout_c(":createEvent: table %s not found", evnt.getTable());
#ifdef EVENT_DEBUG
- ndbout_c("NdbDictionaryImpl::createEvent: table not found: %s", evnt.getTable());
+ ndbout_c("NdbDictionaryImpl::createEvent: table not found: %s",
+ evnt.getTableName());
#endif
return -1;
}
@@ -2297,7 +2413,8 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
evnt.m_facade->addColumn(*(col_impl->m_facade));
} else {
ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
- evnt.getTable());
+ evnt.getTableName());
+ m_error.code= 4713;
return -1;
}
}
@@ -2316,7 +2433,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
const NdbColumnImpl* col =
table.getColumn(evnt.m_columns[i]->m_name.c_str());
if(col == 0){
- m_error.code = 4247;
+ m_error.code= 4247;
return -1;
}
// Copy column definition
@@ -2342,7 +2459,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
// Check for illegal duplicate attributes
for(i = 1; i<attributeList_sz; i++) {
if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) {
- m_error.code = 4258;
+ m_error.code= 4258;
return -1;
}
}
@@ -2390,17 +2507,21 @@ NdbDictInterface::createEvent(class Ndb & ndb,
const size_t len = strlen(evnt.m_externalName.c_str()) + 1;
if(len > MAX_TAB_NAME_SIZE) {
- m_error.code = 4241;
+ m_error.code= 4241;
return -1;
}
w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str());
if (getFlag == 0)
+ {
+ const BaseString internal_tabname(
+ ndb.internalize_table_name(evnt.m_tableName.c_str()));
w.add(SimpleProperties::StringValue,
- ndb.internalizeTableName(evnt.m_tableName.c_str()));
+ internal_tabname.c_str());
+ }
- LinearSectionPtr ptr[3];
+ LinearSectionPtr ptr[1];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = (m_buffer.length()+3) >> 2;
@@ -2463,6 +2584,7 @@ int
NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
NdbEventImpl & evnt)
{
+ DBUG_ENTER("NdbDictInterface::executeSubscribeEvent");
NdbApiSignal tSignal(m_reference);
// tSignal.theReceiversBlockNumber = SUMA;
tSignal.theReceiversBlockNumber = DBDICT;
@@ -2477,7 +2599,7 @@ NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
sumaStart->subscriberData = evnt.m_bufferId & 0xFF;
sumaStart->subscriberRef = m_reference;
- return executeSubscribeEvent(&tSignal, NULL);
+ DBUG_RETURN(executeSubscribeEvent(&tSignal, NULL));
}
int
@@ -2503,9 +2625,7 @@ int
NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
NdbEventImpl & evnt)
{
-#ifdef EVENT_DEBUG
- ndbout_c("SUB_STOP_REQ");
-#endif
+ DBUG_ENTER("NdbDictInterface::stopSubscribeEvent");
NdbApiSignal tSignal(m_reference);
// tSignal.theReceiversBlockNumber = SUMA;
@@ -2521,7 +2641,7 @@ NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
sumaStop->part = (Uint32) SubscriptionData::TableData;
sumaStop->subscriberRef = m_reference;
- return stopSubscribeEvent(&tSignal, NULL);
+ DBUG_RETURN(stopSubscribeEvent(&tSignal, NULL));
}
int
@@ -2555,8 +2675,8 @@ NdbDictionaryImpl::getEvent(const char * eventName)
}
// We only have the table name with internal name
- ev->setTable(m_ndb.externalizeTableName(ev->getTable()));
- ev->m_tableImpl = getTable(ev->getTable());
+ ev->setTable(m_ndb.externalizeTableName(ev->getTableName()));
+ ev->m_tableImpl = getTable(ev->getTableName());
// get the columns from the attrListBitmask
@@ -2581,7 +2701,7 @@ NdbDictionaryImpl::getEvent(const char * eventName)
#ifdef EVENT_DEBUG
ndbout_c("NdbDictionaryImpl::getEvent could not find column id %d", id);
#endif
- m_error.code = 4247;
+ m_error.code= 4247;
delete ev;
return NULL;
}
@@ -2599,9 +2719,8 @@ void
NdbDictInterface::execCREATE_EVNT_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#ifdef EVENT_DEBUG
- ndbout << "NdbDictionaryImpl.cpp: execCREATE_EVNT_CONF" << endl;
-#endif
+ DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_CONF");
+
m_buffer.clear();
unsigned int len = signal->getLength() << 2;
m_buffer.append((char *)&len, sizeof(len));
@@ -2611,118 +2730,123 @@ NdbDictInterface::execCREATE_EVNT_CONF(NdbApiSignal * signal,
m_buffer.append((char *)ptr[0].p, strlen((char *)ptr[0].p)+1);
}
+ const CreateEvntConf * const createEvntConf=
+ CAST_CONSTPTR(CreateEvntConf, signal->getDataPtr());
+
+ Uint32 subscriptionId = createEvntConf->getEventId();
+ Uint32 subscriptionKey = createEvntConf->getEventKey();
+
+ DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d",
+ subscriptionId,subscriptionKey));
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execCREATE_EVNT_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#ifdef EVENT_DEBUG
- ndbout << "NdbDictionaryImpl.cpp: execCREATE_EVNT_REF" << endl;
- ndbout << "Exiting" << endl;
- exit(-1);
-#endif
+ DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_REF");
- const CreateEvntRef* const ref = CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr());
- m_error.code = ref->getErrorCode();
-#ifdef EVENT_DEBUG
- ndbout_c("execCREATE_EVNT_REF");
- ndbout_c("ErrorCode %u", ref->getErrorCode());
- ndbout_c("Errorline %u", ref->getErrorLine());
- ndbout_c("ErrorNode %u", ref->getErrorNode());
-#endif
- m_waiter.signal(NO_WAIT);
+ const CreateEvntRef* const ref=
+ CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr());
+ m_error.code= ref->getErrorCode();
+ DBUG_PRINT("error",("error=%d,line=%d,node=%d",ref->getErrorCode(),
+ ref->getErrorLine(),ref->getErrorNode()));
+ m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execSUB_STOP_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#ifdef EVENT_DEBUG
- ndbout << "Got GSN_SUB_STOP_CONF" << endl;
-#endif
- // SubRemoveConf * const sumaRemoveConf = CAST_CONSTPTR(SubRemoveConf, signal->getDataPtr());
+ DBUG_ENTER("NdbDictInterface::execSUB_STOP_CONF");
+ const SubStopConf * const subStopConf=
+ CAST_CONSTPTR(SubStopConf, signal->getDataPtr());
- // Uint32 subscriptionId = sumaRemoveConf->subscriptionId;
- // Uint32 subscriptionKey = sumaRemoveConf->subscriptionKey;
- // Uint32 senderData = sumaRemoveConf->senderData;
+ Uint32 subscriptionId = subStopConf->subscriptionId;
+ Uint32 subscriptionKey = subStopConf->subscriptionKey;
+ Uint32 subscriberData = subStopConf->subscriberData;
+ DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
+ subscriptionId,subscriptionKey,subscriberData));
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execSUB_STOP_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#ifdef EVENT_DEBUG
- ndbout << "Got GSN_SUB_STOP_REF" << endl;
-#endif
- // SubRemoveConf * const sumaRemoveRef = CAST_CONSTPTR(SubRemoveRef, signal->getDataPtr());
+ DBUG_ENTER("NdbDictInterface::execSUB_STOP_REF");
+ const SubStopRef * const subStopRef=
+ CAST_CONSTPTR(SubStopRef, signal->getDataPtr());
- // Uint32 subscriptionId = sumaRemoveRef->subscriptionId;
- // Uint32 subscriptionKey = sumaRemoveRef->subscriptionKey;
- // Uint32 senderData = sumaRemoveRef->senderData;
+ Uint32 subscriptionId = subStopRef->subscriptionId;
+ Uint32 subscriptionKey = subStopRef->subscriptionKey;
+ Uint32 subscriberData = subStopRef->subscriberData;
+ m_error.code= subStopRef->errorCode;
- m_error.code = 1;
+ DBUG_PRINT("error",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d,error=%d",
+ subscriptionId,subscriptionKey,subscriberData,m_error.code));
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execSUB_START_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#ifdef EVENT_DEBUG
- ndbout << "Got GSN_SUB_START_CONF" << endl;
-#endif
- const SubStartConf * const sumaStartConf = CAST_CONSTPTR(SubStartConf, signal->getDataPtr());
+ DBUG_ENTER("NdbDictInterface::execSUB_START_CONF");
+ const SubStartConf * const subStartConf=
+ CAST_CONSTPTR(SubStartConf, signal->getDataPtr());
- // Uint32 subscriptionId = sumaStartConf->subscriptionId;
- // Uint32 subscriptionKey = sumaStartConf->subscriptionKey;
+ Uint32 subscriptionId = subStartConf->subscriptionId;
+ Uint32 subscriptionKey = subStartConf->subscriptionKey;
SubscriptionData::Part part =
- (SubscriptionData::Part)sumaStartConf->part;
- // Uint32 subscriberData = sumaStartConf->subscriberData;
+ (SubscriptionData::Part)subStartConf->part;
+ Uint32 subscriberData = subStartConf->subscriberData;
switch(part) {
case SubscriptionData::MetaData: {
-#ifdef EVENT_DEBUG
- ndbout << "SubscriptionData::MetaData" << endl;
-#endif
- m_error.code = 1;
+ DBUG_PRINT("error",("SubscriptionData::MetaData"));
+ m_error.code= 1;
break;
}
case SubscriptionData::TableData: {
-#ifdef EVENT_DEBUG
- ndbout << "SubscriptionData::TableData" << endl;
-#endif
+ DBUG_PRINT("info",("SubscriptionData::TableData"));
break;
}
default: {
-#ifdef EVENT_DEBUG
- ndbout_c("NdbDictInterface::execSUB_START_CONF wrong data");
-#endif
- m_error.code = 1;
+ DBUG_PRINT("error",("wrong data"));
+ m_error.code= 2;
break;
}
}
+ DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
+ subscriptionId,subscriptionKey,subscriberData));
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execSUB_START_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#ifdef EVENT_DEBUG
- ndbout << "Got GSN_SUB_START_REF" << endl;
-#endif
- m_error.code = 1;
- m_waiter.signal(NO_WAIT);
+ DBUG_ENTER("NdbDictInterface::execSUB_START_REF");
+ const SubStartRef * const subStartRef=
+ CAST_CONSTPTR(SubStartRef, signal->getDataPtr());
+ m_error.code= subStartRef->errorCode;
+ m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execSUB_GCP_COMPLETE_REP(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- const SubGcpCompleteRep * const rep = CAST_CONSTPTR(SubGcpCompleteRep, signal->getDataPtr());
+ const SubGcpCompleteRep * const rep=
+ CAST_CONSTPTR(SubGcpCompleteRep, signal->getDataPtr());
const Uint32 gci = rep->gci;
// const Uint32 senderRef = rep->senderRef;
@@ -2733,7 +2857,8 @@ NdbDictInterface::execSUB_GCP_COMPLETE_REP(NdbApiSignal * signal,
const Uint32 ref = signal->theSendersBlockRef;
NdbApiSignal tSignal(m_reference);
- SubGcpCompleteAcc * acc = CAST_PTR(SubGcpCompleteAcc, tSignal.getDataPtrSend());
+ SubGcpCompleteAcc * acc=
+ CAST_PTR(SubGcpCompleteAcc, tSignal.getDataPtrSend());
acc->rep = *rep;
@@ -2791,9 +2916,9 @@ NdbDictInterface::execSUB_TABLE_DATA(NdbApiSignal * signal,
int
NdbDictionaryImpl::dropEvent(const char * eventName)
{
- NdbEventImpl *ev = new NdbEventImpl();
+ NdbEventImpl *ev= new NdbEventImpl();
ev->setName(eventName);
- int ret = m_receiver.dropEvent(*ev);
+ int ret= m_receiver.dropEvent(*ev);
delete ev;
// printf("__________________RET %u\n", ret);
@@ -2842,31 +2967,25 @@ void
NdbDictInterface::execDROP_EVNT_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#ifdef EVENT_DEBUG
- ndbout << "NdbDictionaryImpl.cpp: execDROP_EVNT_CONF" << endl;
-#endif
-
+ DBUG_ENTER("NdbDictInterface::execDROP_EVNT_CONF");
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execDROP_EVNT_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#ifdef EVENT_DEBUG
- ndbout << "NdbDictionaryImpl.cpp: execDROP_EVNT_REF" << endl;
-#endif
- const DropEvntRef* const ref = CAST_CONSTPTR(DropEvntRef, signal->getDataPtr());
- m_error.code = ref->getErrorCode();
+ DBUG_ENTER("NdbDictInterface::execDROP_EVNT_REF");
+ const DropEvntRef* const ref=
+ CAST_CONSTPTR(DropEvntRef, signal->getDataPtr());
+ m_error.code= ref->getErrorCode();
-#if 0
- ndbout_c("execDROP_EVNT_REF");
- ndbout_c("ErrorCode %u", ref->getErrorCode());
- ndbout_c("Errorline %u", ref->getErrorLine());
- ndbout_c("ErrorNode %u", ref->getErrorNode());
-#endif
+ DBUG_PRINT("info",("ErrorCode=%u Errorline=%u ErrorNode=%u",
+ ref->getErrorCode(), ref->getErrorLine(), ref->getErrorNode()));
- m_waiter.signal(NO_WAIT);
+ m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
/*****************************************************************
@@ -2931,7 +3050,7 @@ NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
}
if (! ok) {
// bad signal data
- m_error.code = 4213;
+ m_error.code= 4213;
return -1;
}
list.count = count;
@@ -2953,8 +3072,6 @@ NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
BaseString schemaName;
BaseString objectName;
if ((element.type == NdbDictionary::Object::UniqueHashIndex) ||
- (element.type == NdbDictionary::Object::HashIndex) ||
- (element.type == NdbDictionary::Object::UniqueOrderedIndex) ||
(element.type == NdbDictionary::Object::OrderedIndex)) {
char * indexName = new char[n << 2];
memcpy(indexName, &data[pos], n << 2);
@@ -2999,7 +3116,7 @@ NdbDictInterface::listObjects(NdbApiSignal* signal)
m_transporter->lock_mutex();
Uint16 aNodeId = m_transporter->get_an_alive_node();
if (aNodeId == 0) {
- m_error.code = 4009;
+ m_error.code= 4009;
m_transporter->unlock_mutex();
return -1;
}
@@ -3007,7 +3124,7 @@ NdbDictInterface::listObjects(NdbApiSignal* signal)
m_transporter->unlock_mutex();
continue;
}
- m_error.code = 0;
+ m_error.code= 0;
m_waiter.m_node = aNodeId;
m_waiter.m_state = WAIT_LIST_TABLES_CONF;
m_waiter.wait(WAITFOR_RESPONSE_TIMEOUT);
@@ -3036,6 +3153,7 @@ NdbDictInterface::execLIST_TABLES_CONF(NdbApiSignal* signal,
}
template class Vector<int>;
+template class Vector<Uint16>;
template class Vector<Uint32>;
template class Vector<Vector<Uint32> >;
template class Vector<NdbTableImpl*>;
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index 602a2d6b6ca..754d0000718 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -19,7 +19,6 @@
#include <ndb_types.h>
#include <kernel_types.h>
-#include <ndb_limits.h>
#include <NdbError.hpp>
#include <BaseString.hpp>
#include <Vector.hpp>
@@ -63,12 +62,8 @@ public:
CHARSET_INFO * m_cs; // not const in MySQL
bool m_pk;
- bool m_tupleKey;
bool m_distributionKey;
- bool m_distributionGroup;
- int m_distributionGroupBits;
bool m_nullable;
- bool m_indexOnly;
bool m_autoIncrement;
Uint64 m_autoIncrementInitialValue;
BaseString m_defaultValue;
@@ -77,13 +72,13 @@ public:
/**
* Internal types and sizes, and aggregates
*/
- Uint32 m_attrType; // type outsize API and DICT
Uint32 m_attrSize; // element size (size when arraySize==1)
Uint32 m_arraySize; // length or length+2 for Var* types
Uint32 m_keyInfoPos;
- Uint32 m_extType; // used by restore (kernel type in versin v2x)
+ // TODO: use bits in attr desc 2
bool getInterpretableType() const ;
bool getCharType() const;
+ bool getStringType() const;
bool getBlobType() const;
/**
@@ -123,13 +118,20 @@ public:
Vector<Uint32> m_columnHash;
Vector<NdbColumnImpl *> m_columns;
void buildColumnHash();
-
+
+ /**
+ * Fragment info
+ */
+ Uint32 m_hashValueMask;
+ Uint32 m_hashpointerValue;
+ Vector<Uint16> m_fragments;
+
bool m_logging;
int m_kvalue;
int m_minLoadFactor;
int m_maxLoadFactor;
- int m_keyLenInWords;
- int m_fragmentCount;
+ Uint16 m_keyLenInWords;
+ Uint16 m_fragmentCount;
NdbDictionaryImpl * m_dictionary;
NdbIndexImpl * m_index;
@@ -147,21 +149,26 @@ public:
/**
* Aggregates
*/
- Uint32 m_noOfKeys;
- unsigned short m_sizeOfKeysInWords;
- unsigned short m_noOfBlobs;
+ Uint8 m_noOfKeys;
+ Uint8 m_noOfDistributionKeys;
+ Uint8 m_noOfBlobs;
+
+ Uint8 m_replicaCount;
/**
* Equality/assign
*/
bool equal(const NdbTableImpl&) const;
void assign(const NdbTableImpl&);
- void clearNewProperties();
- void copyNewProperties();
static NdbTableImpl & getImpl(NdbDictionary::Table & t);
static NdbTableImpl & getImpl(const NdbDictionary::Table & t);
NdbDictionary::Table * m_facade;
+
+ /**
+ * Return count
+ */
+ Uint32 get_nodes(Uint32 hashValue, const Uint16** nodes) const ;
};
class NdbIndexImpl : public NdbDictionary::Index, public NdbDictObjectImpl {
@@ -170,6 +177,7 @@ public:
NdbIndexImpl(NdbDictionary::Index &);
~NdbIndexImpl();
+ void init();
void setName(const char * name);
const char * getName() const;
void setTable(const char * table);
@@ -199,13 +207,17 @@ public:
NdbEventImpl(NdbDictionary::Event &);
~NdbEventImpl();
+ void init();
void setName(const char * name);
const char * getName() const;
+ void setTable(const NdbDictionary::Table& table);
void setTable(const char * table);
- const char * getTable() const;
+ const char * getTableName() const;
void addTableEvent(const NdbDictionary::Event::TableEvent t);
- void setDurability(const NdbDictionary::Event::EventDurability d);
+ void setDurability(NdbDictionary::Event::EventDurability d);
+ NdbDictionary::Event::EventDurability getDurability() const;
void addEventColumn(const NdbColumnImpl &c);
+ int getNoOfEventColumns() const;
void print() {
ndbout_c("NdbEventImpl: id=%d, key=%d",
@@ -296,8 +308,8 @@ public:
int listObjects(NdbDictionary::Dictionary::List& list, Uint32 requestData, bool fullyQualifiedNames);
int listObjects(NdbApiSignal* signal);
- NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames);
- NdbTableImpl * getTable(const char * name, bool fullyQualifiedNames);
+/* NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames); */
+ NdbTableImpl * getTable(const BaseString& name, bool fullyQualifiedNames);
NdbTableImpl * getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
Uint32 noOfSections, bool fullyQualifiedNames);
@@ -307,8 +319,8 @@ public:
bool fullyQualifiedNames);
static int create_index_obj_from_table(NdbIndexImpl ** dst,
- const NdbTableImpl*,
- const NdbTableImpl*);
+ NdbTableImpl* index_table,
+ const NdbTableImpl* primary_table);
NdbError & m_error;
private:
@@ -365,7 +377,7 @@ public:
bool setTransporter(class Ndb * ndb, class TransporterFacade * tf);
bool setTransporter(class TransporterFacade * tf);
-
+
int createTable(NdbTableImpl &t);
int createBlobTables(NdbTableImpl &);
int addBlobTables(NdbTableImpl &);
@@ -391,13 +403,12 @@ public:
int listObjects(List& list, NdbDictionary::Object::Type type);
int listIndexes(List& list, Uint32 indexId);
-
+
NdbTableImpl * getTable(const char * tableName, void **data= 0);
- Ndb_local_table_info * get_local_table_info(const char * internalName,
- bool do_add_blob_tables);
+ Ndb_local_table_info* get_local_table_info(
+ const BaseString& internalTableName, bool do_add_blob_tables);
NdbIndexImpl * getIndex(const char * indexName,
const char * tableName);
- NdbIndexImpl * getIndexImpl(const char * name, const char * internalName);
NdbEventImpl * getEvent(const char * eventName);
NdbEventImpl * getEventImpl(const char * internalName);
@@ -415,7 +426,9 @@ public:
NdbDictInterface m_receiver;
Ndb & m_ndb;
private:
- Ndb_local_table_info * fetchGlobalTableImpl(const char * internalName);
+ NdbIndexImpl * getIndexImpl(const char * name,
+ const BaseString& internalName);
+ Ndb_local_table_info * fetchGlobalTableImpl(const BaseString& internalName);
};
inline
@@ -454,7 +467,19 @@ bool
NdbColumnImpl::getCharType() const {
return (m_type == NdbDictionary::Column::Char ||
m_type == NdbDictionary::Column::Varchar ||
- m_type == NdbDictionary::Column::Text);
+ m_type == NdbDictionary::Column::Text ||
+ m_type == NdbDictionary::Column::Longvarchar);
+}
+
+inline
+bool
+NdbColumnImpl::getStringType() const {
+ return (m_type == NdbDictionary::Column::Char ||
+ m_type == NdbDictionary::Column::Varchar ||
+ m_type == NdbDictionary::Column::Longvarchar ||
+ m_type == NdbDictionary::Column::Binary ||
+ m_type == NdbDictionary::Column::Varbinary ||
+ m_type == NdbDictionary::Column::Longvarbinary);
}
inline
@@ -535,7 +560,7 @@ NdbTableImpl::getColumn(const char * name){
do {
if(hashValue == (tmp & 0xFFFE)){
NdbColumnImpl* col = cols[tmp >> 16];
- if(strcmp(name, col->m_name.c_str()) == 0){
+ if(strncmp(name, col->m_name.c_str(), col->m_name.length()) == 0){
return col;
}
}
@@ -611,26 +636,27 @@ NdbDictionaryImpl::getImpl(const NdbDictionary::Dictionary & t){
*/
inline
-NdbTableImpl *
-NdbDictionaryImpl::getTable(const char * tableName, void **data)
+NdbTableImpl *
+NdbDictionaryImpl::getTable(const char * table_name, void **data)
{
+ const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
Ndb_local_table_info *info=
- get_local_table_info(m_ndb.internalizeTableName(tableName), true);
- if (info == 0) {
+ get_local_table_info(internal_tabname, true);
+ if (info == 0)
return 0;
- }
- if (data) {
+
+ if (data)
*data= info->m_local_data;
- }
+
return info->m_table_impl;
}
inline
Ndb_local_table_info *
-NdbDictionaryImpl::get_local_table_info(const char * internalTableName,
+NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName,
bool do_add_blob_tables)
{
- Ndb_local_table_info *info= m_localHash.get(internalTableName);
+ Ndb_local_table_info *info= m_localHash.get(internalTableName.c_str());
if (info == 0) {
info= fetchGlobalTableImpl(internalTableName);
if (info == 0) {
@@ -645,34 +671,35 @@ NdbDictionaryImpl::get_local_table_info(const char * internalTableName,
inline
NdbIndexImpl *
-NdbDictionaryImpl::getIndex(const char * indexName,
- const char * tableName)
+NdbDictionaryImpl::getIndex(const char * index_name,
+ const char * table_name)
{
- if (tableName || m_ndb.usingFullyQualifiedNames()) {
- const char * internalIndexName = 0;
- if (tableName) {
- NdbTableImpl * t = getTable(tableName);
- if (t != 0)
- internalIndexName = m_ndb.internalizeIndexName(t, indexName);
- } else {
- internalIndexName =
- m_ndb.internalizeTableName(indexName); // Index is also a table
- }
- if (internalIndexName) {
- Ndb_local_table_info * info = get_local_table_info(internalIndexName,
- false);
- if (info) {
- NdbTableImpl * tab = info->m_table_impl;
+ if (table_name || m_ndb.usingFullyQualifiedNames())
+ {
+ const BaseString internal_indexname(
+ (table_name)
+ ?
+ m_ndb.internalize_index_name(getTable(table_name), index_name)
+ :
+ m_ndb.internalize_table_name(index_name)); // Index is also a table
+
+ if (internal_indexname.length())
+ {
+ Ndb_local_table_info * info=
+ get_local_table_info(internal_indexname, false);
+ if (info)
+ {
+ NdbTableImpl * tab= info->m_table_impl;
if (tab->m_index == 0)
- tab->m_index = getIndexImpl(indexName, internalIndexName);
+ tab->m_index= getIndexImpl(index_name, internal_indexname);
if (tab->m_index != 0)
- tab->m_index->m_table = tab;
+ tab->m_index->m_table= tab;
return tab->m_index;
}
}
}
- m_error.code = 4243;
+ m_error.code= 4243;
return 0;
}
diff --git a/ndb/src/ndbapi/NdbEventOperation.cpp b/ndb/src/ndbapi/NdbEventOperation.cpp
index d209293f8b0..e99cad918c5 100644
--- a/ndb/src/ndbapi/NdbEventOperation.cpp
+++ b/ndb/src/ndbapi/NdbEventOperation.cpp
@@ -15,23 +15,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbEventOperation.cpp
- * Include:
- * Link:
- * Author: Tomas Ulin MySQL AB
- * Date: 2003-11-21
- * Version: 0.1
- * Description: Event support
- * Documentation:
- * Adjust: 2003-11-21 Tomas Ulin First version.
- ****************************************************************************/
-
#include <Ndb.hpp>
-#include <signaldata/SumaImpl.hpp>
+#include <NdbError.hpp>
#include <portlib/NdbMem.h>
-#include <transporter/TransporterDefinitions.hpp>
-#include <NdbEventOperation.hpp>
#include "NdbEventOperationImpl.hpp"
#include "NdbDictionaryImpl.hpp"
@@ -123,3 +109,7 @@ NdbEventOperation::wait(void *p, int aMillisecondNumber)
NdbEventOperation::NdbEventOperation(NdbEventOperationImpl& impl)
: m_impl(impl) {}
+const struct NdbError &
+NdbEventOperation::getNdbError() const {
+ return m_impl.getNdbError();
+}
diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/ndb/src/ndbapi/NdbEventOperationImpl.cpp
index 87bbca5fc71..208525bfc15 100644
--- a/ndb/src/ndbapi/NdbEventOperationImpl.cpp
+++ b/ndb/src/ndbapi/NdbEventOperationImpl.cpp
@@ -55,14 +55,17 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
const char* eventName,
const int bufferLength)
: NdbEventOperation(*this), m_ndb(theNdb),
- m_state(ERROR), m_bufferL(bufferLength)
+ m_state(EO_ERROR), m_bufferL(bufferLength)
{
-
m_eventId = 0;
- theFirstRecAttrs[0] = NULL;
- theCurrentRecAttrs[0] = NULL;
- theFirstRecAttrs[1] = NULL;
- theCurrentRecAttrs[1] = NULL;
+ theFirstPkAttrs[0] = NULL;
+ theCurrentPkAttrs[0] = NULL;
+ theFirstPkAttrs[1] = NULL;
+ theCurrentPkAttrs[1] = NULL;
+ theFirstDataAttrs[0] = NULL;
+ theCurrentDataAttrs[0] = NULL;
+ theFirstDataAttrs[1] = NULL;
+ theCurrentDataAttrs[1] = NULL;
sdata = NULL;
ptr[0].p = NULL;
ptr[1].p = NULL;
@@ -71,16 +74,17 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
// we should lookup id in Dictionary, TODO
// also make sure we only have one listener on each event
- if (!m_ndb) { ndbout_c("m_ndb=NULL"); return; }
+ if (!m_ndb) abort();
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
- if (!myDict) { ndbout_c("getDictionary=NULL"); return; }
+ if (!myDict) { m_error.code= m_ndb->getNdbError().code; return; }
const NdbDictionary::Event *myEvnt = myDict->getEvent(eventName);
- if (!myEvnt) { ndbout_c("getEvent()=NULL"); return; }
+ if (!myEvnt) { m_error.code= myDict->getNdbError().code; return; }
m_eventImpl = &myEvnt->m_impl;
- if (!m_eventImpl) { ndbout_c("m_impl=NULL"); return; }
+
+ m_eventId = m_eventImpl->m_eventId;
m_bufferHandle = m_ndb->getGlobalEventBufferHandle();
if (m_bufferHandle->m_bufferL > 0)
@@ -88,25 +92,30 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
else
m_bufferHandle->m_bufferL = m_bufferL;
- m_state = CREATED;
+ m_state = EO_CREATED;
}
NdbEventOperationImpl::~NdbEventOperationImpl()
{
int i;
- if (sdata) NdbMem_Free(sdata);
- for (i=0 ; i<3; i++) {
- if (ptr[i].p) NdbMem_Free(ptr[i].p);
+ if (sdata) NdbMem_Free((char*)sdata);
+ for (i=0 ; i<2; i++) {
+ NdbRecAttr *p = theFirstPkAttrs[i];
+ while (p) {
+ NdbRecAttr *p_next = p->next();
+ m_ndb->releaseRecAttr(p);
+ p = p_next;
+ }
}
for (i=0 ; i<2; i++) {
- NdbRecAttr *p = theFirstRecAttrs[i];
+ NdbRecAttr *p = theFirstDataAttrs[i];
while (p) {
NdbRecAttr *p_next = p->next();
m_ndb->releaseRecAttr(p);
p = p_next;
}
}
- if (m_state == NdbEventOperation::EXECUTING) {
+ if (m_state == EO_EXECUTING) {
stop();
// m_bufferHandle->dropSubscribeEvent(m_bufferId);
; // We should send stop signal here
@@ -122,36 +131,50 @@ NdbEventOperationImpl::getState()
NdbRecAttr*
NdbEventOperationImpl::getValue(const char *colName, char *aValue, int n)
{
- if (m_state != NdbEventOperation::CREATED) {
+ DBUG_ENTER("NdbEventOperationImpl::getValue");
+ if (m_state != EO_CREATED) {
ndbout_c("NdbEventOperationImpl::getValue may only be called between instantiation and execute()");
- return NULL;
+ DBUG_RETURN(NULL);
}
NdbColumnImpl *tAttrInfo = m_eventImpl->m_tableImpl->getColumn(colName);
if (tAttrInfo == NULL) {
ndbout_c("NdbEventOperationImpl::getValue attribute %s not found",colName);
- return NULL;
+ DBUG_RETURN(NULL);
}
- return NdbEventOperationImpl::getValue(tAttrInfo, aValue, n);
+ DBUG_RETURN(NdbEventOperationImpl::getValue(tAttrInfo, aValue, n));
}
NdbRecAttr*
NdbEventOperationImpl::getValue(const NdbColumnImpl *tAttrInfo, char *aValue, int n)
{
+ DBUG_ENTER("NdbEventOperationImpl::getValue");
// Insert Attribute Id into ATTRINFO part.
- NdbRecAttr *&theFirstRecAttr = theFirstRecAttrs[n];
- NdbRecAttr *&theCurrentRecAttr = theCurrentRecAttrs[n];
-
+
+ NdbRecAttr **theFirstAttr;
+ NdbRecAttr **theCurrentAttr;
+
+ if (tAttrInfo->getPrimaryKey())
+ {
+ theFirstAttr = &theFirstPkAttrs[n];
+ theCurrentAttr = &theCurrentPkAttrs[n];
+ }
+ else
+ {
+ theFirstAttr = &theFirstDataAttrs[n];
+ theCurrentAttr = &theCurrentDataAttrs[n];
+ }
+
/************************************************************************
* Get a Receive Attribute object and link it into the operation object.
************************************************************************/
- NdbRecAttr *tRecAttr = m_ndb->getRecAttr();
- if (tRecAttr == NULL) {
+ NdbRecAttr *tAttr = m_ndb->getRecAttr();
+ if (tAttr == NULL) {
exit(-1);
//setErrorCodeAbort(4000);
- return NULL;
+ DBUG_RETURN(NULL);
}
/**********************************************************************
@@ -159,63 +182,65 @@ NdbEventOperationImpl::getValue(const NdbColumnImpl *tAttrInfo, char *aValue, in
* the RecAttr object
* Also set attribute size, array size and attribute type
********************************************************************/
- if (tRecAttr->setup(tAttrInfo, aValue)) {
+ if (tAttr->setup(tAttrInfo, aValue)) {
//setErrorCodeAbort(4000);
- m_ndb->releaseRecAttr(tRecAttr);
+ m_ndb->releaseRecAttr(tAttr);
exit(-1);
- return NULL;
+ DBUG_RETURN(NULL);
}
//theErrorLine++;
- tRecAttr->setNULL();
+ tAttr->setUNDEFINED();
// We want to keep the list sorted to make data insertion easier later
- if (theFirstRecAttr == NULL) {
- theFirstRecAttr = tRecAttr;
- theCurrentRecAttr = tRecAttr;
- tRecAttr->next(NULL);
+
+ if (*theFirstAttr == NULL) {
+ *theFirstAttr = tAttr;
+ *theCurrentAttr = tAttr;
+ tAttr->next(NULL);
} else {
Uint32 tAttrId = tAttrInfo->m_attrId;
- if (tAttrId > theCurrentRecAttr->attrId()) { // right order
- theCurrentRecAttr->next(tRecAttr);
- tRecAttr->next(NULL);
- theCurrentRecAttr = tRecAttr;
- } else if (theFirstRecAttr->next() == NULL || // only one in list
- theFirstRecAttr->attrId() > tAttrId) {// or first
- tRecAttr->next(theFirstRecAttr);
- theFirstRecAttr = tRecAttr;
+ if (tAttrId > (*theCurrentAttr)->attrId()) { // right order
+ (*theCurrentAttr)->next(tAttr);
+ tAttr->next(NULL);
+ *theCurrentAttr = tAttr;
+ } else if ((*theFirstAttr)->next() == NULL || // only one in list
+ (*theFirstAttr)->attrId() > tAttrId) {// or first
+ tAttr->next(*theFirstAttr);
+ *theFirstAttr = tAttr;
} else { // at least 2 in list and not first and not last
- NdbRecAttr *p = theFirstRecAttr;
+ NdbRecAttr *p = *theFirstAttr;
NdbRecAttr *p_next = p->next();
while (tAttrId > p_next->attrId()) {
p = p_next;
p_next = p->next();
}
if (tAttrId == p_next->attrId()) { // Using same attribute twice
- tRecAttr->release(); // do I need to do this?
- m_ndb->releaseRecAttr(tRecAttr);
+ tAttr->release(); // do I need to do this?
+ m_ndb->releaseRecAttr(tAttr);
exit(-1);
- return NULL;
+ DBUG_RETURN(NULL);
}
// this is it, between p and p_next
- p->next(tRecAttr);
- tRecAttr->next(p_next);
+ p->next(tAttr);
+ tAttr->next(p_next);
}
}
-
- return tRecAttr;
+ DBUG_RETURN(tAttr);
}
int
NdbEventOperationImpl::execute()
{
+ DBUG_ENTER("NdbEventOperationImpl::execute");
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
if (!myDict) {
- ndbout_c("NdbEventOperation::execute(): getDictionary=NULL");
- return 0;
+ m_error.code= m_ndb->getNdbError().code;
+ DBUG_RETURN(-1);
}
- if (theFirstRecAttrs[0] == NULL) { // defaults to get all
+ if (theFirstPkAttrs[0] == NULL &&
+ theFirstDataAttrs[0] == NULL) { // defaults to get all
}
@@ -223,13 +248,18 @@ NdbEventOperationImpl::execute()
int hasSubscriber;
- m_bufferId =
- m_bufferHandle->prepareAddSubscribeEvent(m_eventImpl->m_eventId,
- hasSubscriber /* return value */);
+ int r= m_bufferHandle->prepareAddSubscribeEvent(this,
+ hasSubscriber /*return value*/);
+ m_error.code= 4709;
+
+ if (r < 0)
+ {
+ DBUG_RETURN(-1);
+ }
- m_eventImpl->m_bufferId = m_bufferId;
+ m_eventImpl->m_bufferId = m_bufferId = (Uint32)r;
- int r = -1;
+ r = -1;
if (m_bufferId >= 0) {
// now we check if there's already a subscriber
@@ -241,30 +271,33 @@ NdbEventOperationImpl::execute()
if (r) {
//Error
m_bufferHandle->unprepareAddSubscribeEvent(m_bufferId);
- m_state = NdbEventOperation::ERROR;
+ m_state = EO_ERROR;
} else {
m_bufferHandle->addSubscribeEvent(m_bufferId, this);
- m_state = NdbEventOperation::EXECUTING;
+ m_state = EO_EXECUTING;
}
} else {
//Error
- m_state = NdbEventOperation::ERROR;
+ m_state = EO_ERROR;
}
- return r;
+ DBUG_RETURN(r);
}
int
NdbEventOperationImpl::stop()
{
- if (m_state != NdbEventOperation::EXECUTING)
- return -1;
+ DBUG_ENTER("NdbEventOperationImpl::stop");
+ if (m_state != EO_EXECUTING)
+ {
+ DBUG_RETURN(-1);
+ }
// ndbout_c("NdbEventOperation::stopping()");
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
if (!myDict) {
- ndbout_c("NdbEventOperation::stop(): getDictionary=NULL");
- return 0;
+ m_error.code= m_ndb->getNdbError().code;
+ DBUG_RETURN(-1);
}
NdbDictionaryImpl & myDictImpl = NdbDictionaryImpl::getImpl(*myDict);
@@ -275,8 +308,8 @@ NdbEventOperationImpl::stop()
hasSubscriber /* return value */);
if (ret < 0) {
- ndbout_c("prepareDropSubscribeEvent failed");
- return -1;
+ m_error.code= 4712;
+ DBUG_RETURN(-1);
}
// m_eventImpl->m_bufferId = m_bufferId;
@@ -293,17 +326,17 @@ NdbEventOperationImpl::stop()
if (r) {
//Error
m_bufferHandle->unprepareDropSubscribeEvent(m_bufferId);
- m_state = NdbEventOperation::ERROR;
+ m_error.code= myDictImpl.m_error.code;
+ m_state = EO_ERROR;
} else {
#ifdef EVENT_DEBUG
ndbout_c("NdbEventOperation::dropping()");
#endif
m_bufferHandle->dropSubscribeEvent(m_bufferId);
- m_state = NdbEventOperation::CREATED;
+ m_state = EO_CREATED;
}
-
- return r;
+ DBUG_RETURN(r);
}
bool
@@ -327,6 +360,7 @@ NdbEventOperationImpl::getLatestGCI()
int
NdbEventOperationImpl::next(int *pOverrun)
{
+ DBUG_ENTER("NdbEventOperationImpl::next");
int nr = 10000; // a high value
int tmpOverrun = 0;
int *ptmpOverrun;
@@ -343,7 +377,10 @@ NdbEventOperationImpl::next(int *pOverrun)
*pOverrun = tmpOverrun;
}
- if (r <= 0) return r; // no data
+ if (r <= 0)
+ {
+ DBUG_RETURN(r); // no data
+ }
if (r < nr) r = nr; else nr--; // we don't want to be stuck here forever
@@ -352,8 +389,13 @@ NdbEventOperationImpl::next(int *pOverrun)
#endif
// now move the data into the RecAttrs
- if ((theFirstRecAttrs[0] == NULL) &&
- (theFirstRecAttrs[1] == NULL)) return r;
+ if ((theFirstPkAttrs[0] == NULL) &&
+ (theFirstPkAttrs[1] == NULL) &&
+ (theFirstDataAttrs[0] == NULL) &&
+ (theFirstDataAttrs[1] == NULL))
+ {
+ DBUG_RETURN(r);
+ }
// no copying since no RecAttr's
@@ -364,20 +406,37 @@ NdbEventOperationImpl::next(int *pOverrun)
#ifdef EVENT_DEBUG
int i;
printf("after values sz=%u\n", ptr[1].sz);
- for (i=0; i < ptr[1].sz; i++)
+ for(i=0; i < (int)ptr[1].sz; i++)
printf ("H'%.8X ",ptr[1].p[i]);
printf("\n");
printf("before values sz=%u\n", ptr[2].sz);
- for (i=0; i < ptr[2].sz; i++)
+ for(i=0; i < (int)ptr[2].sz; i++)
printf ("H'%.8X ",ptr[2].p[i]);
printf("\n");
#endif
- NdbRecAttr *tWorkingRecAttr = theFirstRecAttrs[0];
-
// copy data into the RecAttr's
// we assume that the respective attribute lists are sorted
+ // first the pk's
+ {
+ NdbRecAttr *tAttr= theFirstPkAttrs[0];
+ while(tAttr)
+ {
+ assert(aAttrPtr < aAttrEndPtr);
+ unsigned tDataSz= AttributeHeader(*aAttrPtr).getDataSize();
+ assert(tAttr->attrId() ==
+ AttributeHeader(*aAttrPtr).getAttributeId());
+ assert(tAttr->receive_data(aDataPtr, tDataSz));
+ // next
+ aAttrPtr++;
+ aDataPtr+= tDataSz;
+ tAttr= tAttr->next();
+ }
+ }
+
+ NdbRecAttr *tWorkingRecAttr = theFirstDataAttrs[0];
+
Uint32 tRecAttrId;
Uint32 tAttrId;
Uint32 tDataSz;
@@ -389,7 +448,7 @@ NdbEventOperationImpl::next(int *pOverrun)
while (tAttrId > tRecAttrId) {
//printf("[%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
- tWorkingRecAttr->setNULL();
+ tWorkingRecAttr->setUNDEFINED();
tWorkingRecAttr = tWorkingRecAttr->next();
if (tWorkingRecAttr == NULL)
break;
@@ -401,32 +460,25 @@ NdbEventOperationImpl::next(int *pOverrun)
//printf("[%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
if (tAttrId == tRecAttrId) {
- if (!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey())
- hasSomeData++;
+ hasSomeData++;
//printf("set!\n");
- tWorkingRecAttr->receive_data(aDataPtr, tDataSz);
-
- // move forward, data has already moved forward
- aAttrPtr++;
- aDataPtr += tDataSz;
+ assert(tWorkingRecAttr->receive_data(aDataPtr, tDataSz));
tWorkingRecAttr = tWorkingRecAttr->next();
- } else {
- // move only attr forward
- aAttrPtr++;
- aDataPtr += tDataSz;
}
+ aAttrPtr++;
+ aDataPtr += tDataSz;
}
while (tWorkingRecAttr != NULL) {
tRecAttrId = tWorkingRecAttr->attrId();
//printf("set undefined [%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
- tWorkingRecAttr->setNULL();
+ tWorkingRecAttr->setUNDEFINED();
tWorkingRecAttr = tWorkingRecAttr->next();
}
- tWorkingRecAttr = theFirstRecAttrs[1];
+ tWorkingRecAttr = theFirstDataAttrs[1];
aDataPtr = ptr[2].p;
Uint32 *aDataEndPtr = aDataPtr + ptr[2].sz;
while ((aDataPtr < aDataEndPtr) && (tWorkingRecAttr != NULL)) {
@@ -435,7 +487,7 @@ NdbEventOperationImpl::next(int *pOverrun)
tDataSz = AttributeHeader(*aDataPtr).getDataSize();
aDataPtr++;
while (tAttrId > tRecAttrId) {
- tWorkingRecAttr->setNULL();
+ tWorkingRecAttr->setUNDEFINED();
tWorkingRecAttr = tWorkingRecAttr->next();
if (tWorkingRecAttr == NULL)
break;
@@ -444,27 +496,25 @@ NdbEventOperationImpl::next(int *pOverrun)
if (tWorkingRecAttr == NULL)
break;
if (tAttrId == tRecAttrId) {
- if (!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey())
- hasSomeData++;
+ assert(!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey());
+ hasSomeData++;
- tWorkingRecAttr->receive_data(aDataPtr, tDataSz);
- aDataPtr += tDataSz;
- // move forward, data+attr has already moved forward
+ assert(tWorkingRecAttr->receive_data(aDataPtr, tDataSz));
tWorkingRecAttr = tWorkingRecAttr->next();
- } else {
- // move only data+attr forward
- aDataPtr += tDataSz;
}
+ aDataPtr += tDataSz;
}
while (tWorkingRecAttr != NULL) {
- tWorkingRecAttr->setNULL();
+ tWorkingRecAttr->setUNDEFINED();
tWorkingRecAttr = tWorkingRecAttr->next();
}
if (hasSomeData)
- return r;
+ {
+ DBUG_RETURN(r);
+ }
}
- return 0;
+ DBUG_RETURN(0);
}
NdbDictionary::Event::TableEvent
@@ -487,10 +537,20 @@ NdbEventOperationImpl::getEventType()
void
NdbEventOperationImpl::print()
{
+ int i;
ndbout << "EventId " << m_eventId << "\n";
- for (int i = 0; i < 2; i++) {
- NdbRecAttr *p = theFirstRecAttrs[i];
+ for (i = 0; i < 2; i++) {
+ NdbRecAttr *p = theFirstPkAttrs[i];
+ ndbout << " %u " << i;
+ while (p) {
+ ndbout << " : " << p->attrId() << " = " << *p;
+ p = p->next();
+ }
+ ndbout << "\n";
+ }
+ for (i = 0; i < 2; i++) {
+ NdbRecAttr *p = theFirstDataAttrs[i];
ndbout << " %u " << i;
while (p) {
ndbout << " : " << p->attrId() << " = " << *p;
@@ -639,23 +699,28 @@ NdbGlobalEventBufferHandle::~NdbGlobalEventBufferHandle()
void
NdbGlobalEventBufferHandle::addBufferId(int bufferId)
{
+ DBUG_ENTER("NdbGlobalEventBufferHandle::addBufferId");
+ DBUG_PRINT("enter",("bufferId=%d",bufferId));
if (m_nids >= NDB_MAX_ACTIVE_EVENTS) {
ndbout_c("NdbGlobalEventBufferHandle::addBufferId error in paramerer setting");
exit(-1);
}
m_bufferIds[m_nids] = bufferId;
m_nids++;
+ DBUG_VOID_RETURN;
}
void
NdbGlobalEventBufferHandle::dropBufferId(int bufferId)
{
+ DBUG_ENTER("NdbGlobalEventBufferHandle::dropBufferId");
+ DBUG_PRINT("enter",("bufferId=%d",bufferId));
for (int i = 0; i < m_nids; i++)
if (m_bufferIds[i] == bufferId) {
m_nids--;
for (; i < m_nids; i++)
m_bufferIds[i] = m_bufferIds[i+1];
- return;
+ DBUG_VOID_RETURN;
}
ndbout_c("NdbGlobalEventBufferHandle::dropBufferId %d does not exist",
bufferId);
@@ -674,10 +739,11 @@ NdbGlobalEventBufferHandle::drop(NdbGlobalEventBufferHandle *handle)
}
*/
int
-NdbGlobalEventBufferHandle::prepareAddSubscribeEvent(Uint32 eventId,
- int& hasSubscriber)
+NdbGlobalEventBufferHandle::prepareAddSubscribeEvent
+(NdbEventOperationImpl *eventOp, int& hasSubscriber)
{
- ADD_DROP_LOCK_GUARDR(int,real_prepareAddSubscribeEvent(this, eventId, hasSubscriber));
+ ADD_DROP_LOCK_GUARDR(int,real_prepareAddSubscribeEvent(this, eventOp,
+ hasSubscriber));
}
void
NdbGlobalEventBufferHandle::addSubscribeEvent
@@ -830,57 +896,68 @@ NdbGlobalEventBuffer::~NdbGlobalEventBuffer()
// NdbMem_Deallocate(m_eventBufferIdToEventId);
}
void
-NdbGlobalEventBuffer::real_init (NdbGlobalEventBufferHandle *h,
+NdbGlobalEventBuffer::real_init (NdbGlobalEventBufferHandle *h,
int MAX_NUMBER_ACTIVE_EVENTS)
{
- if (m_handlers.size() == 0) { // First init
+ DBUG_ENTER("NdbGlobalEventBuffer::real_init");
+ DBUG_PRINT("enter",("m_handles.size()=%u %u", m_handlers.size(), h));
+ if (m_handlers.size() == 0)
+ { // First init
+ DBUG_PRINT("info",("first to come"));
m_max = MAX_NUMBER_ACTIVE_EVENTS;
m_buf = new BufItem[m_max];
- // (BufItem *)NdbMem_Allocate(m_max*sizeof(BufItem));
-
for (int i=0; i<m_max; i++) {
- m_buf[i].gId = 0;
+ m_buf[i].gId= 0;
}
}
+ assert(m_max == MAX_NUMBER_ACTIVE_EVENTS);
// TODO make sure we don't hit roof
- // m_handlers[m_nhandlers] = h;
m_handlers.push_back(h);
- // ndbout_c("NdbGlobalEventBuffer::real_init(), m_handles=%u %u", m_nhandlers, h);
+ DBUG_VOID_RETURN;
}
void
NdbGlobalEventBuffer::real_remove(NdbGlobalEventBufferHandle *h)
{
- // ndbout_c("NdbGlobalEventBuffer::real_init_remove(), m_handles=%u %u", m_nhandlers, h);
- for (Uint32 i=0 ; i < m_handlers.size(); i++) {
- // ndbout_c("%u %u %u", i, m_handlers[i], h);
- if (m_handlers[i] == h) {
+ DBUG_ENTER("NdbGlobalEventBuffer::real_remove");
+ DBUG_PRINT("enter",("m_handles.size()=%u %u", m_handlers.size(), h));
+ for (Uint32 i=0 ; i < m_handlers.size(); i++)
+ {
+ DBUG_PRINT("info",("m_handlers[%u] %u", i, m_handlers[i]));
+ if (m_handlers[i] == h)
+ {
m_handlers.erase(i);
- if (m_handlers.size() == 0) {
- // ndbout_c("last to go");
+ if (m_handlers.size() == 0)
+ {
+ DBUG_PRINT("info",("last to go"));
delete[] m_buf;
m_buf = NULL;
- // NdbMem_Free((char*)m_buf);
}
- return;
+ DBUG_VOID_RETURN;
}
}
- ndbout_c("NdbGlobalEventBuffer::real_init_remove() non-existing handle");
- exit(-1);
+ ndbout_c("NdbGlobalEventBuffer::real_remove() non-existing handle");
+ DBUG_PRINT("error",("non-existing handle"));
+ abort();
+ DBUG_VOID_RETURN;
}
-int
+int
NdbGlobalEventBuffer::real_prepareAddSubscribeEvent
-(NdbGlobalEventBufferHandle *aHandle, Uint32 eventId, int& hasSubscriber)
+(NdbGlobalEventBufferHandle *aHandle, NdbEventOperationImpl *eventOp,
+ int& hasSubscriber)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_prepareAddSubscribeEvent");
int i;
- int bufferId = -1;
+ int bufferId= -1;
+ Uint32 eventId= eventOp->m_eventId;
+ DBUG_PRINT("enter",("eventId: %u", eventId));
// add_drop_lock(); // only one thread can do add or drop at a time
// Find place where eventId already set
for (i=0; i<m_no; i++) {
if (m_buf[i].gId == eventId) {
- bufferId = i;
+ bufferId= i;
break;
}
}
@@ -888,53 +965,55 @@ NdbGlobalEventBuffer::real_prepareAddSubscribeEvent
// find space for new bufferId
for (i=0; i<m_no; i++) {
if (m_buf[i].gId == 0) {
- bufferId = i; // we found an empty spot
- break;
+ bufferId= i; // we found an empty spot
+ goto found_bufferId;
}
}
if (bufferId < 0 &&
m_no < m_max) {
// room for more so get that
- bufferId=m_no;
- m_buf[m_no].gId = 0;
+ bufferId= m_no;
+ m_buf[m_no].gId= 0;
m_no++;
} else {
- ndbout_c("prepareAddSubscribeEvent: Can't accept more subscribers");
- // add_drop_unlock();
- return -1;
+ // add_drop_unlock();
+ DBUG_PRINT("error",("Can't accept more subscribers:"
+ " bufferId=%d, m_no=%d, m_max=%d",
+ bufferId, m_no, m_max));
+ DBUG_RETURN(-1);
}
}
+found_bufferId:
- BufItem &b = m_buf[ID(bufferId)];
+ BufItem &b= m_buf[ID(bufferId)];
if (b.gId == 0) { // first subscriber needs some initialization
- bufferId = NO_ID(0, bufferId);
+ bufferId= NO_ID(0, bufferId);
- b.gId = eventId;
+ b.gId= eventId;
+ b.eventType= (Uint32)eventOp->m_eventImpl->mi_type;
- if ((b.p_buf_mutex = NdbMutex_Create()) == NULL) {
+ if ((b.p_buf_mutex= NdbMutex_Create()) == NULL) {
ndbout_c("NdbGlobalEventBuffer: NdbMutex_Create() failed");
- exit(-1);
+ abort();
}
- b.subs = 0;
- b.f = 0;
- b.sz = 0;
- b.max_sz = aHandle->m_bufferL;
- b.data =
+ b.subs= 0;
+ b.f= 0;
+ b.sz= 0;
+ b.max_sz= aHandle->m_bufferL;
+ b.data=
(BufItem::Data *)NdbMem_Allocate(b.max_sz*sizeof(BufItem::Data));
for (int i = 0; i < b.max_sz; i++) {
- b.data[i].sdata = NULL;
- b.data[i].ptr[0].p = NULL;
- b.data[i].ptr[1].p = NULL;
- b.data[i].ptr[2].p = NULL;
+ b.data[i].sdata= NULL;
+ b.data[i].ptr[0].p= NULL;
+ b.data[i].ptr[1].p= NULL;
+ b.data[i].ptr[2].p= NULL;
}
} else {
-#ifdef EVENT_DEBUG
- ndbout_c("NdbGlobalEventBuffer::prepareAddSubscribeEvent: TRYING handle one subscriber per event b.subs = %u", b.subs);
-#endif
-
+ DBUG_PRINT("info",
+ ("TRYING handle one subscriber per event b.subs=%u",b.subs));
int ni = -1;
for(int i=0; i < b.subs;i++) {
if (b.ps[i].theHandle == NULL) {
@@ -946,9 +1025,10 @@ NdbGlobalEventBuffer::real_prepareAddSubscribeEvent
if (b.subs < MAX_SUBSCRIBERS_PER_EVENT) {
ni = b.subs;
} else {
- ndbout_c("prepareAddSubscribeEvent: Can't accept more subscribers");
+ DBUG_PRINT("error",
+ ("Can't accept more subscribers: b.subs=%d",b.subs));
// add_drop_unlock();
- return -1;
+ DBUG_RETURN(-1);
}
}
bufferId = NO_ID(ni, bufferId);
@@ -969,23 +1049,25 @@ NdbGlobalEventBuffer::real_prepareAddSubscribeEvent
else
hasSubscriber = 0;
-#ifdef EVENT_DEBUG
- ndbout_c("prepareAddSubscribeEvent: handed out bufferId %d for eventId %d",
- bufferId, eventId);
-#endif
+ DBUG_PRINT("info",("handed out bufferId=%d for eventId=%d hasSubscriber=%d",
+ bufferId, eventId, hasSubscriber));
/* we now have a lock on the prepare so that no one can mess with this
* unlock comes in unprepareAddSubscribeEvent or addSubscribeEvent
*/
- return bufferId;
+ DBUG_RETURN(bufferId);
}
void
NdbGlobalEventBuffer::real_unprepareAddSubscribeEvent(int bufferId)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_unprepareAddSubscribeEvent");
BufItem &b = m_buf[ID(bufferId)];
int n = NO(bufferId);
+ DBUG_PRINT("enter", ("bufferId=%d,ID(bufferId)=%d,NO(bufferId)=%d",
+ bufferId, ID(bufferId), NO(bufferId)));
+
b.ps[n].theHandle = NULL;
// remove subscribers from the end,
@@ -998,10 +1080,8 @@ NdbGlobalEventBuffer::real_unprepareAddSubscribeEvent(int bufferId)
break;
if (b.subs == 0) {
-#ifdef EVENT_DEBUG
- ndbout_c("unprepareAddSubscribeEvent: no more subscribers left on eventId %d", b.gId);
-#endif
- b.gId = 0; // We don't have any subscribers, reuse BufItem
+ DBUG_PRINT("info",("no more subscribers left on eventId %d", b.gId));
+ b.gId= 0; // We don't have any subscribers, reuse BufItem
if (b.data) {
NdbMem_Free((void *)b.data);
b.data = NULL;
@@ -1012,12 +1092,14 @@ NdbGlobalEventBuffer::real_unprepareAddSubscribeEvent(int bufferId)
}
}
// add_drop_unlock();
+ DBUG_VOID_RETURN;
}
void
NdbGlobalEventBuffer::real_addSubscribeEvent(int bufferId,
void *ndbEventOperation)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_addSubscribeEvent");
BufItem &b = m_buf[ID(bufferId)];
int n = NO(bufferId);
@@ -1025,9 +1107,8 @@ NdbGlobalEventBuffer::real_addSubscribeEvent(int bufferId,
b.ps[n].theHandle->addBufferId(bufferId);
// add_drop_unlock();
-#ifdef EVENT_DEBUG
- ndbout_c("addSubscribeEvent:: added bufferId %d", bufferId);
-#endif
+ DBUG_PRINT("info",("added bufferId %d", bufferId));
+ DBUG_VOID_RETURN;
}
void
@@ -1040,6 +1121,7 @@ int
NdbGlobalEventBuffer::real_prepareDropSubscribeEvent(int bufferId,
int& hasSubscriber)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_prepareDropSubscribeEvent");
// add_drop_lock(); // only one thread can do add or drop at a time
BufItem &b = m_buf[ID(bufferId)];
@@ -1055,14 +1137,17 @@ NdbGlobalEventBuffer::real_prepareDropSubscribeEvent(int bufferId,
else if (n == 1)
hasSubscriber = 0;
else
- return -1;
+ {
+ DBUG_RETURN(-1);
+ }
- return 0;
+ DBUG_RETURN(0);
}
void
NdbGlobalEventBuffer::real_dropSubscribeEvent(int bufferId)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_dropSubscribeEvent");
// add_drop_lock(); // only one thread can do add-drop at a time
BufItem &b = m_buf[ID(bufferId)];
@@ -1078,6 +1163,7 @@ NdbGlobalEventBuffer::real_dropSubscribeEvent(int bufferId)
#ifdef EVENT_DEBUG
ndbout_c("dropSubscribeEvent:: dropped bufferId %d", bufferId);
#endif
+ DBUG_VOID_RETURN;
}
void
@@ -1100,10 +1186,13 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId,
const SubTableData * const sdata,
LinearSectionPtr ptr[3])
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_insertDataL");
BufItem &b = m_buf[ID(bufferId)];
#ifdef EVENT_DEBUG
int n = NO(bufferId);
#endif
+
+ if ( b.eventType & (1 << (Uint32)sdata->operation) )
{
if (b.subs) {
#ifdef EVENT_DEBUG
@@ -1112,7 +1201,9 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId,
// move front forward
if (copy_data_alloc(sdata, ptr,
b.data[b.f].sdata, b.data[b.f].ptr))
- return -1;
+ {
+ DBUG_RETURN(-1);
+ }
for (int i=0; i < b.subs; i++) {
NdbGlobalEventBuffer::BufItem::Ps &e = b.ps[i];
if (e.theHandle) { // active subscriber
@@ -1120,7 +1211,7 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId,
if (e.bufferempty == 0) {
e.overrun++; // another item has been overwritten
e.b++; // move next-to-read next since old item was overwritten
- if (e.b == b.max_sz) e.b = 0; // start from beginning
+ if (e.b == b.max_sz) e.b= 0; // start from beginning
}
}
e.bufferempty = 0;
@@ -1140,21 +1231,35 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId,
#endif
}
}
- return 0;
+ else
+ {
+#ifdef EVENT_DEBUG
+ ndbout_c("skipped");
+#endif
+ }
+
+ DBUG_RETURN(0);
}
int NdbGlobalEventBuffer::hasData(int bufferId) {
+ DBUG_ENTER("NdbGlobalEventBuffer::hasData");
BufItem &b = m_buf[ID(bufferId)];
int n = NO(bufferId);
NdbGlobalEventBuffer::BufItem::Ps &e = b.ps[n];
if(e.bufferempty)
- return 0;
+ {
+ DBUG_RETURN(0);
+ }
if (b.f <= e.b)
- return b.max_sz-e.b + b.f;
+ {
+ DBUG_RETURN(b.max_sz-e.b + b.f);
+ }
else
- return b.f-e.b;
+ {
+ DBUG_RETURN(b.f-e.b);
+ }
}
int NdbGlobalEventBuffer::real_getDataL(const int bufferId,
@@ -1162,6 +1267,7 @@ int NdbGlobalEventBuffer::real_getDataL(const int bufferId,
LinearSectionPtr ptr[3],
int *pOverrun)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_getDataL");
BufItem &b = m_buf[ID(bufferId)];
int n = NO(bufferId);
NdbGlobalEventBuffer::BufItem::Ps &e = b.ps[n];
@@ -1172,13 +1278,20 @@ int NdbGlobalEventBuffer::real_getDataL(const int bufferId,
}
if (e.bufferempty)
- return 0; // nothing to get
+ {
+ DBUG_RETURN(0); // nothing to get
+ }
+
+ DBUG_PRINT("info",("ID(bufferId) %d NO(bufferId) %d e.b %d",
+ ID(bufferId), NO(bufferId), e.b));
if (copy_data_alloc(b.data[e.b].sdata, b.data[e.b].ptr,
sdata, ptr))
- return -1;
+ {
+ DBUG_RETURN(-1);
+ }
- e.b++; if (e.b == b.max_sz) e.b = 0; // move next-to-read forward
+ e.b++; if (e.b == b.max_sz) e.b= 0; // move next-to-read forward
if (b.f == e.b) // back has cought up with front
e.bufferempty = 1;
@@ -1187,7 +1300,7 @@ int NdbGlobalEventBuffer::real_getDataL(const int bufferId,
ndbout_c("getting data from buffer %d with eventId %d", bufferId, b.gId);
#endif
- return hasData(bufferId)+1;
+ DBUG_RETURN(hasData(bufferId)+1);
}
int
NdbGlobalEventBuffer::copy_data_alloc(const SubTableData * const f_sdata,
@@ -1195,49 +1308,59 @@ NdbGlobalEventBuffer::copy_data_alloc(const SubTableData * const f_sdata,
SubTableData * &t_sdata,
LinearSectionPtr t_ptr[3])
{
- if (t_sdata == NULL) {
- t_sdata = (SubTableData *)NdbMem_Allocate(sizeof(SubTableData));
- }
+ DBUG_ENTER("NdbGlobalEventBuffer::copy_data_alloc");
+ unsigned sz4= (sizeof(SubTableData)+3)>>2;
+ Uint32 *ptr= (Uint32*)NdbMem_Allocate((sz4 +
+ f_ptr[0].sz +
+ f_ptr[1].sz +
+ f_ptr[2].sz) * sizeof(Uint32));
+ if (t_sdata)
+ NdbMem_Free((char*)t_sdata);
+ t_sdata= (SubTableData *)ptr;
memcpy(t_sdata,f_sdata,sizeof(SubTableData));
+ ptr+= sz4;
+
for (int i = 0; i < 3; i++) {
LinearSectionPtr & f_p = f_ptr[i];
LinearSectionPtr & t_p = t_ptr[i];
if (f_p.sz > 0) {
- if (t_p.p == NULL) {
- t_p.p = (Uint32 *)NdbMem_Allocate(sizeof(Uint32)*f_p.sz);
- } else if (t_p.sz != f_p.sz) {
- NdbMem_Free(t_p.p);
- t_p.p = (Uint32 *)NdbMem_Allocate(sizeof(Uint32)*f_p.sz);
- }
+ t_p.p= (Uint32 *)ptr;
memcpy(t_p.p, f_p.p, sizeof(Uint32)*f_p.sz);
- } else if (t_p.p != NULL) {
- NdbMem_Free(t_p.p);
- t_p.p = NULL;
+ ptr+= f_p.sz;
+ t_p.sz= f_p.sz;
+ } else {
+ t_p.p= NULL;
+ t_p.sz= 0;
}
- t_p.sz = f_p.sz;
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbGlobalEventBuffer::real_wait(NdbGlobalEventBufferHandle *h,
int aMillisecondNumber)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_wait");
// check if there are anything in any of the buffers
int i;
int n = 0;
for (i = 0; i < h->m_nids; i++)
n += hasData(h->m_bufferIds[i]);
- if (n) return n;
+ if (n)
+ {
+ DBUG_RETURN(n);
+ }
int r = NdbCondition_WaitTimeout(h->p_cond, ndb_global_event_buffer_mutex,
aMillisecondNumber);
if (r > 0)
- return -1;
+ {
+ DBUG_RETURN(-1);
+ }
n = 0;
for (i = 0; i < h->m_nids; i++)
n += hasData(h->m_bufferIds[i]);
- return n;
+ DBUG_RETURN(n);
}
template class Vector<NdbGlobalEventBufferHandle*>;
diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/ndb/src/ndbapi/NdbEventOperationImpl.hpp
index f67c998e639..96958979c76 100644
--- a/ndb/src/ndbapi/NdbEventOperationImpl.hpp
+++ b/ndb/src/ndbapi/NdbEventOperationImpl.hpp
@@ -14,21 +14,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbEventOperationImpl.hpp
- * Include:
- * Link:
- * Author: Tomas Ulin MySQL AB
- * Date: 2003-11-21
- * Version: 0.1
- * Description: Event support
- * Documentation:
- * Adjust: 2003-11-21 Tomas Ulin First version.
- ****************************************************************************/
-
#ifndef NdbEventOperationImpl_H
#define NdbEventOperationImpl_H
+#include <NdbEventOperation.hpp>
+#include <signaldata/SumaImpl.hpp>
+#include <transporter/TransporterDefinitions.hpp>
+
class NdbGlobalEventBufferHandle;
class NdbEventOperationImpl : public NdbEventOperation {
public:
@@ -61,12 +53,17 @@ public:
void print();
void printAll();
+ const NdbError & getNdbError() const;
+ NdbError m_error;
+
Ndb *m_ndb;
NdbEventImpl *m_eventImpl;
NdbGlobalEventBufferHandle *m_bufferHandle;
- NdbRecAttr *theFirstRecAttrs[2];
- NdbRecAttr *theCurrentRecAttrs[2];
+ NdbRecAttr *theFirstPkAttrs[2];
+ NdbRecAttr *theCurrentPkAttrs[2];
+ NdbRecAttr *theFirstDataAttrs[2];
+ NdbRecAttr *theCurrentDataAttrs[2];
NdbEventOperation::State m_state;
Uint32 m_eventId;
@@ -84,7 +81,7 @@ public:
//static NdbGlobalEventBufferHandle *init(int MAX_NUMBER_ACTIVE_EVENTS);
// returns bufferId 0-N if ok otherwise -1
- int prepareAddSubscribeEvent(Uint32 eventId, int& hasSubscriber);
+ int prepareAddSubscribeEvent(NdbEventOperationImpl *, int& hasSubscriber);
void unprepareAddSubscribeEvent(int bufferId);
void addSubscribeEvent(int bufferId,
NdbEventOperationImpl *ndbEventOperationImpl);
@@ -138,7 +135,8 @@ private:
int MAX_NUMBER_ACTIVE_EVENTS);
int real_prepareAddSubscribeEvent(NdbGlobalEventBufferHandle *h,
- Uint32 eventId, int& hasSubscriber);
+ NdbEventOperationImpl *,
+ int& hasSubscriber);
void real_unprepareAddSubscribeEvent(int bufferId);
void real_addSubscribeEvent(int bufferId, void *ndbEventOperation);
@@ -182,6 +180,7 @@ private:
// local mutex for each event/buffer
NdbMutex *p_buf_mutex;
Uint32 gId;
+ Uint32 eventType;
struct Data {
SubTableData *sdata;
LinearSectionPtr ptr[3];
diff --git a/ndb/src/ndbapi/NdbImpl.hpp b/ndb/src/ndbapi/NdbImpl.hpp
index 00a8ef19f3a..d73b8afe10c 100644
--- a/ndb/src/ndbapi/NdbImpl.hpp
+++ b/ndb/src/ndbapi/NdbImpl.hpp
@@ -59,6 +59,19 @@ public:
NdbWaiter theWaiter;
int m_optimized_node_selection;
+
+
+ BaseString m_dbname; // Database name
+ BaseString m_schemaname; // Schema name
+
+ BaseString m_prefix; // Buffer for preformatted internal name <db>/<schema>/
+
+ void update_prefix()
+ {
+ m_prefix.assfmt("%s%c%s%c", m_dbname.c_str(), table_name_separator,
+ m_schemaname.c_str(), table_name_separator);
+ }
+
};
#ifdef VM_TRACE
@@ -89,9 +102,9 @@ Ndb::void2rec(void* val){
}
inline
-NdbConnection *
+NdbTransaction *
Ndb::void2con(void* val){
- return (NdbConnection*)val;
+ return (NdbTransaction*)val;
}
inline
@@ -107,7 +120,7 @@ Ndb::void2rec_iop(void* val){
}
inline
-NdbConnection *
+NdbTransaction *
NdbReceiver::getTransaction(){
return ((NdbOperation*)m_owner)->theNdbCon;
}
diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp
index 39da9c5f5d0..4cedffed4a2 100644
--- a/ndb/src/ndbapi/NdbIndexOperation.cpp
+++ b/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -16,9 +16,8 @@
#include <ndb_global.h>
#include <NdbIndexOperation.hpp>
-#include <NdbResultSet.hpp>
#include <Ndb.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include "NdbApiSignal.hpp"
#include <AttributeHeader.hpp>
#include <signaldata/TcIndx.hpp>
@@ -28,9 +27,7 @@
NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) :
NdbOperation(aNdb),
- m_theIndex(NULL),
- m_theIndexLen(0),
- m_theNoOfIndexDefined(0)
+ m_theIndex(NULL)
{
m_tcReqGSN = GSN_TCINDXREQ;
m_attrInfoGSN = GSN_INDXATTRINFO;
@@ -56,7 +53,7 @@ NdbIndexOperation::~NdbIndexOperation()
int
NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
const NdbTableImpl * aTable,
- NdbConnection* myConnection)
+ NdbTransaction* myConnection)
{
NdbOperation::init(aTable, myConnection);
@@ -64,25 +61,13 @@ NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
case(NdbDictionary::Index::UniqueHashIndex):
break;
case(NdbDictionary::Index::Undefined):
- case(NdbDictionary::Index::HashIndex):
- case(NdbDictionary::Index::UniqueOrderedIndex):
case(NdbDictionary::Index::OrderedIndex):
setErrorCodeAbort(4003);
return -1;
}
m_theIndex = anIndex;
- m_thePrimaryTable = aTable;
m_accessTable = anIndex->m_table;
- m_theIndexLen = 0;
- m_theNoOfIndexDefined = 0;
- for (Uint32 i=0; i<NDB_MAX_ATTRIBUTES_IN_INDEX; i++)
- for (int j=0; j<3; j++)
- m_theIndexDefined[i][j] = false;
-
- TcIndxReq * const tcIndxReq = CAST_PTR(TcIndxReq, theTCREQ->getDataPtrSend());
- tcIndxReq->scanInfo = 0;
- theKEYINFOptr = &tcIndxReq->keyInfo[0];
- theATTRINFOptr = &tcIndxReq->attrInfo[0];
+ theNoOfTupKeyLeft = m_accessTable->getNoOfPrimaryKeys();
return 0;
}
@@ -179,312 +164,6 @@ int NdbIndexOperation::interpretedDeleteTuple()
return NdbOperation::interpretedDeleteTuple();
}
-int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
- const char* aValuePassed,
- Uint32 aVariableKeyLen)
-{
- register Uint32 tAttrId;
-
- Uint32 tData;
- Uint32 tKeyInfoPosition;
- const char* aValue = aValuePassed;
- Uint32 xfrmData[1024];
- Uint32 tempData[1024];
-
- if ((theStatus == OperationDefined) &&
- (aValue != NULL) &&
- (tAttrInfo != NULL )) {
- /************************************************************************
- * Start by checking that the attribute is an index key.
- * This value is also the word order in the tuple key of this
- * tuple key attribute.
- * Then check that this tuple key has not already been defined.
- * Finally check if all tuple key attributes have been defined. If
- * this is true then set Operation state to tuple key defined.
- ************************************************************************/
- tAttrId = tAttrInfo->m_attrId;
- tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
- Uint32 i = 0;
-
- // Check that the attribute is part if the index attributes
- // by checking if it is a primary key attribute of index table
- if (tAttrInfo->m_pk) {
- Uint32 tKeyDefined = theTupleKeyDefined[0][2];
- Uint32 tKeyAttrId = theTupleKeyDefined[0][0];
- do {
- if (tKeyDefined == false) {
- goto keyEntryFound;
- } else {
- if (tKeyAttrId != tAttrId) {
- /******************************************************************
- * We read the key defined variable in advance.
- * It could potentially read outside its area when
- * i = MAXNROFTUPLEKEY - 1,
- * it is not a problem as long as the variable
- * theTupleKeyDefined is defined
- * in the middle of the object.
- * Reading wrong data and not using it causes no problems.
- *****************************************************************/
- i++;
- tKeyAttrId = theTupleKeyDefined[i][0];
- tKeyDefined = theTupleKeyDefined[i][2];
- continue;
- } else {
- goto equal_error2;
- }//if
- }//if
- } while (i < NDB_MAX_ATTRIBUTES_IN_INDEX);
- goto equal_error2;
- } else {
- goto equal_error1;
- }
- /**************************************************************************
- * Now it is time to retrieve the tuple key data from the pointer supplied
- * by the application.
- * We have to retrieve the size of the attribute in words and bits.
- *************************************************************************/
- keyEntryFound:
- m_theIndexDefined[i][0] = tAttrId;
- m_theIndexDefined[i][1] = tKeyInfoPosition;
- m_theIndexDefined[i][2] = true;
-
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
- {
- /*************************************************************************
- * Check if the pointer of the value passed is aligned on a 4 byte
- * boundary. If so only assign the pointer to the internal variable
- * aValue. If it is not aligned then we start by copying the value to
- * tempData and use this as aValue instead.
- *************************************************************************/
- const int attributeSize = sizeInBytes;
- const int slack = sizeInBytes & 3;
- if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
- memcpy(&tempData[0], aValue, attributeSize);
- aValue = (char*)&tempData[0];
- if(slack != 0) {
- char * tmp = (char*)&tempData[0];
- memset(&tmp[attributeSize], 0, (4 - slack));
- }//if
- }//if
- }
- const char* aValueToWrite = aValue;
-
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- if (cs != 0) {
- // current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply <= 1);
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)xfrmData, sizeof(xfrmData),
- (const uchar*)aValue, sizeInBytes);
- while (n < sizeInBytes)
- ((uchar*)xfrmData)[n++] = 0x20;
- aValue = (char*)xfrmData;
- }
-
- Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
- Uint32 totalSizeInWords = (sizeInBytes + 3)/4;// Inc. bits in last word
- Uint32 sizeInWords = sizeInBytes / 4; // Exc. bits in last word
-
- if (true){ //tArraySize != 0) {
- Uint32 tIndexLen = m_theIndexLen;
-
- m_theIndexLen = tIndexLen + totalSizeInWords;
- if ((aVariableKeyLen == sizeInBytes) ||
- (aVariableKeyLen == 0)) {
- ;
- } else {
- goto equal_error3;
- }
- }
-#if 0
- else {
- /************************************************************************
- * The attribute is a variable array. We need to use the length parameter
- * to know the size of this attribute in the key information and
- * variable area. A key is however not allowed to be larger than 4
- * kBytes and this is checked for variable array attributes
- * used as keys.
- ***********************************************************************/
- Uint32 tMaxVariableKeyLenInWord = (MAXTUPLEKEYLENOFATTERIBUTEINWORD -
- tKeyInfoPosition);
- tAttrSizeInBits = aVariableKeyLen << 3;
- tAttrSizeInWords = tAttrSizeInBits >> 5;
- tAttrBitsInLastWord = tAttrSizeInBits - (tAttrSizeInWords << 5);
- tAttrLenInWords = ((tAttrSizeInBits + 31) >> 5);
- if (tAttrLenInWords > tMaxVariableKeyLenInWord) {
- setErrorCodeAbort(4207);
- return -1;
- }//if
- m_theIndexLen = m_theIndexLen + tAttrLenInWords;
- }//if
-#endif
- int tDistrKey = tAttrInfo->m_distributionKey;
- int tDistrGroup = tAttrInfo->m_distributionGroup;
- OperationType tOpType = theOperationType;
- if ((tDistrKey != 1) && (tDistrGroup != 1)) {
- ;
- } else if (tDistrKey == 1) {
- theDistrKeySize += totalSizeInWords;
- theDistrKeyIndicator = 1;
- } else {
- Uint32 TsizeInBytes = sizeInBytes;
- Uint32 TbyteOrderFix = 0;
- char* TcharByteOrderFix = (char*)&TbyteOrderFix;
- if (tAttrInfo->m_distributionGroupBits == 8) {
- char tFirstChar = aValue[TsizeInBytes - 2];
- char tSecondChar = aValue[TsizeInBytes - 2];
- TcharByteOrderFix[0] = tFirstChar;
- TcharByteOrderFix[1] = tSecondChar;
- TcharByteOrderFix[2] = 0x30;
- TcharByteOrderFix[3] = 0x30;
- theDistrGroupType = 0;
- } else {
- TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10)
- + (aValue[TsizeInBytes - 1] - 0x30);
- theDistrGroupType = 1;
- }//if
- theDistributionGroup = TbyteOrderFix;
- theDistrGroupIndicator = 1;
- }//if
- /**************************************************************************
- * If the operation is a write request and the attribute is stored then
- * we also set the value in the stored part through putting the
- * information in the INDXATTRINFO signals.
- *************************************************************************/
- if ((tOpType == WriteRequest)) {
- if (!tAttrInfo->m_indexOnly){
- int dummy_error;
- // invalid data can crash kernel
- if (cs != NULL &&
- (*cs->cset->well_formed_len)(cs,
- aValueToWrite,
- aValueToWrite + sizeInBytes,
- sizeInBytes,
- &dummy_error) != sizeInBytes)
- goto equal_error4;
- Uint32 ahValue;
- Uint32 sz = totalSizeInWords;
- /*
- * XXX should be linked in metadata but cannot now because
- * things can be defined in arbitrary order
- */
- const NdbColumnImpl* primaryCol = m_thePrimaryTable->getColumn(tAttrInfo->m_name.c_str());
- assert(primaryCol != NULL);
- AttributeHeader::init(&ahValue, primaryCol->m_attrId, sz);
- insertATTRINFO( ahValue );
- insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
- if (bitsInLastWord != 0) {
- tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
- tData = convertEndian(tData);
- tData = tData & ((1 << bitsInLastWord) - 1);
- tData = convertEndian(tData);
- insertATTRINFO( tData );
- }//if
- }//if
- }//if
- /**************************************************************************
- * Store the Key information in the TCINDXREQ and INDXKEYINFO signals.
- *************************************************************************/
- if (insertKEYINFO(aValue, tKeyInfoPosition,
- totalSizeInWords, bitsInLastWord) != -1) {
- /************************************************************************
- * Add one to number of tuple key attributes defined.
- * If all have been defined then set the operation state to indicate
- * that tuple key is defined.
- * Thereby no more search conditions are allowed in this version.
- ***********************************************************************/
- Uint32 tNoIndexDef = m_theNoOfIndexDefined;
- Uint32 tErrorLine = theErrorLine;
- int tNoIndexAttrs = m_theIndex->m_columns.size();
- unsigned char tInterpretInd = theInterpretIndicator;
- tNoIndexDef++;
- m_theNoOfIndexDefined = tNoIndexDef;
- tErrorLine++;
- theErrorLine = tErrorLine;
- if (int(tNoIndexDef) == tNoIndexAttrs) {
- if (tOpType == UpdateRequest) {
- if (tInterpretInd == 1) {
- theStatus = GetValue;
- } else {
- theStatus = SetValue;
- }//if
- return 0;
- } 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;
- return 0;
- } else {
- setErrorCodeAbort(4005);
- return -1;
- }//if
- }//if
- return 0;
- } else {
-
- return -1;
- }//if
- } else {
- if (theStatus != OperationDefined) {
- return -1;
- }//if
-
- if (aValue == NULL) {
- setErrorCodeAbort(4505);
- return -1;
- }//if
-
- if ( tAttrInfo == NULL ) {
- setErrorCodeAbort(4004);
- return -1;
- }//if
- }//if
- return -1;
-
- equal_error1:
- setErrorCodeAbort(4205);
- return -1;
-
- equal_error2:
- setErrorCodeAbort(4206);
- return -1;
-
- equal_error3:
- setErrorCodeAbort(4209);
- return -1;
-
- equal_error4:
- setErrorCodeAbort(744);
- return -1;
-}
-
-int NdbIndexOperation::executeCursor(int aProcessorId)
-{
- printf("NdbIndexOperation::executeCursor NYI\n");
- // NYI
- return -1;
-}
-void
-NdbIndexOperation::setLastFlag(NdbApiSignal* signal, Uint32 lastFlag)
-{
- TcIndxReq * const req = CAST_PTR(TcIndxReq, signal->getDataPtrSend());
- TcKeyReq::setExecuteFlag(req->requestInfo, lastFlag);
-}
-
int
NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
{
@@ -525,18 +204,18 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
// We start by filling in the first 8 unconditional words of the
// TCINDXREQ signal.
//-------------------------------------------------------------
- TcIndxReq * const tcIndxReq =
- CAST_PTR(TcIndxReq, theTCREQ->getDataPtrSend());
+ TcKeyReq * tcKeyReq =
+ CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
Uint32 tIndexId = m_theIndex->m_indexId;
Uint32 tSchemaVersion = m_theIndex->m_version;
- tcIndxReq->apiConnectPtr = aTC_ConnectPtr;
- tcIndxReq->senderData = ptr2int();
- tcIndxReq->attrLen = tTotalCurrAI_Len;
- tcIndxReq->indexId = tIndexId;
- tcIndxReq->indexSchemaVersion = tSchemaVersion;
+ tcKeyReq->apiConnectPtr = aTC_ConnectPtr;
+ tcKeyReq->senderData = ptr2int();
+ tcKeyReq->attrLen = tTotalCurrAI_Len;
+ tcKeyReq->tableId = tIndexId;
+ tcKeyReq->tableSchemaVersion = tSchemaVersion;
tTransId1 = (Uint32) aTransactionId;
tTransId2 = (Uint32) (aTransactionId >> 32);
@@ -564,59 +243,53 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
Uint8 tSimpleState = tReadInd & tSimpleAlt;
//theNdbCon->theSimpleState = tSimpleState;
- tcIndxReq->transId1 = tTransId1;
- tcIndxReq->transId2 = tTransId2;
+ tcKeyReq->transId1 = tTransId1;
+ tcKeyReq->transId2 = tTransId2;
tReqInfo = 0;
- if (tTotalCurrAI_Len <= TcIndxReq::MaxAttrInfo) {
- tcIndxReq->setAIInTcIndxReq(tReqInfo, tTotalCurrAI_Len);
+ if (tTotalCurrAI_Len <= TcKeyReq::MaxAttrInfo) {
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, tTotalCurrAI_Len);
} else {
- tcIndxReq->setAIInTcIndxReq(tReqInfo, TcIndxReq::MaxAttrInfo);
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, TcKeyReq::MaxAttrInfo);
}//if
- tcIndxReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
- tcIndxReq->setCommitFlag(tReqInfo, tCommitIndicator);
- tcIndxReq->setStartFlag(tReqInfo, tStartIndicator);
+ tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
+ tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
+ tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
const Uint8 tInterpretIndicator = theInterpretIndicator;
- tcIndxReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
+ tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
Uint8 tDirtyIndicator = theDirtyIndicator;
OperationType tOperationType = theOperationType;
- Uint32 tIndexLen = m_theIndexLen;
+ Uint32 tIndexLen = theTupKeyLen;
Uint8 abortOption = theNdbCon->m_abortOption;
- tcIndxReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
- tcIndxReq->setOperationType(tReqInfo, tOperationType);
- tcIndxReq->setIndexLength(tReqInfo, tIndexLen);
- tcIndxReq->setCommitType(tReqInfo, abortOption);
+ tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
+ tcKeyReq->setOperationType(tReqInfo, tOperationType);
+ tcKeyReq->setKeyLength(tReqInfo, tIndexLen);
+ tcKeyReq->setAbortOption(tReqInfo, abortOption);
- Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
- Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
- Uint8 tDistrGroupType = theDistrGroupType;
+ Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
Uint8 tScanIndicator = theScanInfo & 1;
- tcIndxReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
- tcIndxReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
- tcIndxReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
- tcIndxReq->setScanIndFlag(tReqInfo, tScanIndicator);
+ tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
+ tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
- tcIndxReq->requestInfo = tReqInfo;
+ tcKeyReq->requestInfo = tReqInfo;
//-------------------------------------------------------------
// The next step is to fill in the upto three conditional words.
//-------------------------------------------------------------
- Uint32* tOptionalDataPtr = &tcIndxReq->scanInfo;
+ Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
Uint32 tDistrGHIndex = tScanIndicator;
- Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+ Uint32 tDistrKeyIndex = tDistrGHIndex;
Uint32 tScanInfo = theScanInfo;
- Uint32 tDistributionGroup = theDistributionGroup;
- Uint32 tDistrKeySize = theDistrKeySize;
+ Uint32 tDistrKey = theDistributionKey;
tOptionalDataPtr[0] = tScanInfo;
- tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
- tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+ tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
//-------------------------------------------------------------
// The next is step is to compress the key data part of the
@@ -624,10 +297,10 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
//-------------------------------------------------------------
Uint32 tKeyIndex = tDistrKeyIndex + tDistrKeyIndicator;
Uint32* tKeyDataPtr = &tOptionalDataPtr[tKeyIndex];
- Uint32 Tdata1 = tcIndxReq->keyInfo[0];
- Uint32 Tdata2 = tcIndxReq->keyInfo[1];
- Uint32 Tdata3 = tcIndxReq->keyInfo[2];
- Uint32 Tdata4 = tcIndxReq->keyInfo[3];
+ Uint32 Tdata1 = tcKeyReq->keyInfo[0];
+ Uint32 Tdata2 = tcKeyReq->keyInfo[1];
+ Uint32 Tdata3 = tcKeyReq->keyInfo[2];
+ Uint32 Tdata4 = tcKeyReq->keyInfo[3];
Uint32 Tdata5;
tKeyDataPtr[0] = Tdata1;
@@ -635,10 +308,10 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
tKeyDataPtr[2] = Tdata3;
tKeyDataPtr[3] = Tdata4;
if (tIndexLen > 4) {
- Tdata1 = tcIndxReq->keyInfo[4];
- Tdata2 = tcIndxReq->keyInfo[5];
- Tdata3 = tcIndxReq->keyInfo[6];
- Tdata4 = tcIndxReq->keyInfo[7];
+ Tdata1 = tcKeyReq->keyInfo[4];
+ Tdata2 = tcKeyReq->keyInfo[5];
+ Tdata3 = tcKeyReq->keyInfo[6];
+ Tdata4 = tcKeyReq->keyInfo[7];
tKeyDataPtr[4] = Tdata1;
tKeyDataPtr[5] = Tdata2;
@@ -652,12 +325,12 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
//-------------------------------------------------------------
Uint32 tAttrInfoIndex;
- if (tIndexLen > TcIndxReq::MaxKeyInfo) {
+ if (tIndexLen > TcKeyReq::MaxKeyInfo) {
/**
* Set transid and TC connect ptr in the INDXKEYINFO signals
*/
- NdbApiSignal* tSignal = theFirstKEYINFO;
- Uint32 remainingKey = tIndexLen - TcIndxReq::MaxKeyInfo;
+ NdbApiSignal* tSignal = theTCREQ->next();
+ Uint32 remainingKey = tIndexLen - TcKeyReq::MaxKeyInfo;
do {
Uint32* tSigDataPtr = tSignal->getDataPtrSend();
@@ -678,7 +351,7 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
}
tSignal = tnextSignal;
} while (tSignal != NULL);
- tAttrInfoIndex = tKeyIndex + TcIndxReq::MaxKeyInfo;
+ tAttrInfoIndex = tKeyIndex + TcKeyReq::MaxKeyInfo;
} else {
tAttrInfoIndex = tKeyIndex + tIndexLen;
}//if
@@ -688,14 +361,14 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
// above.
//-------------------------------------------------------------
Uint32* tAIDataPtr = &tOptionalDataPtr[tAttrInfoIndex];
- Tdata1 = tcIndxReq->attrInfo[0];
- Tdata2 = tcIndxReq->attrInfo[1];
- Tdata3 = tcIndxReq->attrInfo[2];
- Tdata4 = tcIndxReq->attrInfo[3];
- Tdata5 = tcIndxReq->attrInfo[4];
-
- theTCREQ->setLength(tcIndxReq->getAIInTcIndxReq(tReqInfo) +
- tAttrInfoIndex + TcIndxReq::StaticLength);
+ Tdata1 = tcKeyReq->attrInfo[0];
+ Tdata2 = tcKeyReq->attrInfo[1];
+ Tdata3 = tcKeyReq->attrInfo[2];
+ Tdata4 = tcKeyReq->attrInfo[3];
+ Tdata5 = tcKeyReq->attrInfo[4];
+
+ theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) +
+ tAttrInfoIndex + TcKeyReq::StaticLength);
tAIDataPtr[0] = Tdata1;
tAIDataPtr[1] = Tdata2;
tAIDataPtr[2] = Tdata3;
@@ -724,11 +397,6 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
return 0;
}
-void NdbIndexOperation::closeScan()
-{
- printf("NdbIndexOperation::closeScan NYI\n");
-}
-
/***************************************************************************
int receiveTCINDXREF( NdbApiSignal* aSignal)
@@ -740,17 +408,5 @@ Remark: Handles the reception of the TCKEYREF signal.
int
NdbIndexOperation::receiveTCINDXREF( NdbApiSignal* aSignal)
{
- const TcIndxRef * const tcIndxRef = CAST_CONSTPTR(TcIndxRef, aSignal->getDataPtr());
-
- if (checkState_TransId(aSignal) == -1) {
- return -1;
- }//if
-
- theStatus = Finished;
-
- theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
- Uint32 errorCode = tcIndxRef->errorCode;
- theError.code = errorCode;
- theNdbCon->setOperationErrorCodeAbort(errorCode);
- return theNdbCon->OpCompleteFailure(theNdbCon->m_abortOption);
+ return receiveTCKEYREF(aSignal);
}//NdbIndexOperation::receiveTCINDXREF()
diff --git a/ndb/src/ndbapi/NdbLinHash.hpp b/ndb/src/ndbapi/NdbLinHash.hpp
index f245a261a04..05670534c95 100644
--- a/ndb/src/ndbapi/NdbLinHash.hpp
+++ b/ndb/src/ndbapi/NdbLinHash.hpp
@@ -192,7 +192,7 @@ template <class C>
inline
Int32
NdbLinHash<C>::insertKey( const char* str, Uint32 len, Uint32 lkey1, C* data )
-{
+{
const Uint32 hash = Hash(str, len);
int dir, seg;
getBucket(hash, &dir, &seg);
@@ -219,8 +219,9 @@ NdbLinHash<C>::insertKey( const char* str, Uint32 len, Uint32 lkey1, C* data )
chain->localkey1 = lkey1;
chain->next = 0;
chain->theData = data;
+ len++; // Null terminated
chain->str = new Uint32[((len + 3) >> 2)];
- memcpy( &chain->str[0], str, len );
+ memcpy( &chain->str[0], str, len);
if (oldChain != 0)
oldChain->next = chain;
else
diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp
index 88d8a000d50..c9143444908 100644
--- a/ndb/src/ndbapi/NdbOperation.cpp
+++ b/ndb/src/ndbapi/NdbOperation.cpp
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
#include "NdbRecAttr.hpp"
@@ -49,7 +49,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
theCurrentATTRINFO(NULL),
theTotalCurrAI_Len(0),
theAI_LenInCurrAI(0),
- theFirstKEYINFO(NULL),
theLastKEYINFO(NULL),
theFirstLabel(NULL),
@@ -68,13 +67,11 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
//theSchemaVersion(0),
theTotalNrOfKeyWordInSignal(8),
theTupKeyLen(0),
- theNoOfTupKeyDefined(0),
+ theNoOfTupKeyLeft(0),
theOperationType(NotDefined),
theStatus(Init),
theMagicNumber(0xFE11D0),
theScanInfo(0),
- theDistrKeySize(0),
- theDistributionGroup(0),
m_tcReqGSN(GSN_TCKEYREQ),
m_keyInfoGSN(GSN_KEYINFO),
m_attrInfoGSN(GSN_ATTRINFO),
@@ -131,7 +128,7 @@ NdbOperation::setErrorCodeAbort(int anErrorCode)
*****************************************************************************/
int
-NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
+NdbOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection){
NdbApiSignal* tSignal;
theStatus = Init;
theError.code = 0;
@@ -145,14 +142,11 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
theFirstATTRINFO = NULL;
theCurrentATTRINFO = NULL;
- theFirstKEYINFO = NULL;
theLastKEYINFO = NULL;
- theTupKeyLen = 0;
- theNoOfTupKeyDefined = 0;
- theDistrKeySize = 0;
- theDistributionGroup = 0;
+ theTupKeyLen = 0;
+ theNoOfTupKeyLeft = tab->getNoOfPrimaryKeys();
theTotalCurrAI_Len = 0;
theAI_LenInCurrAI = 0;
@@ -161,9 +155,7 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
theSimpleIndicator = 0;
theDirtyIndicator = 0;
theInterpretIndicator = 0;
- theDistrGroupIndicator= 0;
- theDistrGroupType = 0;
- theDistrKeyIndicator = 0;
+ theDistrKeyIndicator_ = 0;
theScanInfo = 0;
theTotalNrOfKeyWordInSignal = 8;
theMagicNumber = 0xABCDEF01;
@@ -210,11 +202,16 @@ NdbOperation::release()
NdbBlob* tBlob;
NdbBlob* tSaveBlob;
- if (theTCREQ != NULL)
+ tSignal = theTCREQ;
+ while (tSignal != NULL)
{
- theNdb->releaseSignal(theTCREQ);
- }
+ tSaveSignal = tSignal;
+ tSignal = tSignal->next();
+ theNdb->releaseSignal(tSaveSignal);
+ }
theTCREQ = NULL;
+ theLastKEYINFO = NULL;
+
tSignal = theFirstATTRINFO;
while (tSignal != NULL)
{
@@ -224,15 +221,7 @@ NdbOperation::release()
}
theFirstATTRINFO = NULL;
theCurrentATTRINFO = NULL;
- tSignal = theFirstKEYINFO;
- while (tSignal != NULL)
- {
- tSaveSignal = tSignal;
- tSignal = tSignal->next();
- theNdb->releaseSignal(tSaveSignal);
- }
- theFirstKEYINFO = NULL;
- theLastKEYINFO = NULL;
+
if (theInterpretIndicator == 1)
{
tBranch = theFirstBranch;
@@ -403,3 +392,9 @@ NdbOperation::getTableName() const
{
return m_currentTable->m_externalName.c_str();
}
+
+const NdbDictionary::Table*
+NdbOperation::getTable() const
+{
+ return m_currentTable;
+}
diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp
index dfc54133e6c..835e33dfb40 100644
--- a/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -14,28 +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 */
-
-/*****************************************************************************
- * Name: NdbOperationDefine.C
- * Include:
- * Link:
- * Author: UABMNST Mona Natterkvist UAB/B/SD
- * Date: 970829
- * Version: 0.1
- * Description: Interface between TIS and NDB
- * Documentation:
- * Adjust: 971022 UABMNST First version.
- *****************************************************************************/
-#include "NdbOperation.hpp"
+#include <ndb_global.h>
+#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
-#include "NdbConnection.hpp"
-#include "Ndb.hpp"
-#include "NdbRecAttr.hpp"
+#include <NdbTransaction.hpp>
+#include <Ndb.hpp>
+#include <NdbRecAttr.hpp>
#include "NdbUtil.hpp"
#include "NdbOut.hpp"
#include "NdbImpl.hpp"
#include <NdbIndexScanOperation.hpp>
-#include "NdbBlob.hpp"
+#include <NdbBlob.hpp>
#include <Interpreter.hpp>
@@ -48,7 +37,7 @@
int
NdbOperation::insertTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -68,7 +57,7 @@ NdbOperation::insertTuple()
int
NdbOperation::updateTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -88,7 +77,7 @@ NdbOperation::updateTuple()
int
NdbOperation::writeTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -128,7 +117,7 @@ NdbOperation::readTuple(NdbOperation::LockMode lm)
int
NdbOperation::readTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -149,7 +138,7 @@ NdbOperation::readTuple()
int
NdbOperation::deleteTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -170,7 +159,7 @@ NdbOperation::deleteTuple()
int
NdbOperation::readTupleExclusive()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -247,7 +236,7 @@ NdbOperation::committedRead()
int
NdbOperation::dirtyUpdate()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -270,7 +259,7 @@ NdbOperation::dirtyUpdate()
int
NdbOperation::dirtyWrite()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -293,7 +282,7 @@ NdbOperation::dirtyWrite()
int
NdbOperation::interpretedUpdateTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -316,7 +305,7 @@ NdbOperation::interpretedUpdateTuple()
int
NdbOperation::interpretedDeleteTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -350,7 +339,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
{
NdbRecAttr* tRecAttr;
if ((tAttrInfo != NULL) &&
- (!tAttrInfo->m_indexOnly) &&
(theStatus != Init)){
if (theStatus != GetValue) {
if (theInterpretIndicator == 1) {
@@ -398,10 +386,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
setErrorCodeAbort(4004);
return NULL;
}//if
- if (tAttrInfo->m_indexOnly){
- setErrorCodeAbort(4208);
- return NULL;
- }//if
}//if
setErrorCodeAbort(4200);
return NULL;
@@ -422,6 +406,14 @@ int
NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
const char* aValuePassed, Uint32 len)
{
+ DBUG_ENTER("NdbOperation::setValue");
+ DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
+ tAttrInfo->m_name.c_str(),
+ theOperationType,
+ aValuePassed, len));
+ if (aValuePassed != NULL)
+ DBUG_DUMP("value", (char*)aValuePassed, len);
+
int tReturnCode;
Uint32 tAttrId;
Uint32 tData;
@@ -437,7 +429,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
;
} else {
setErrorCodeAbort(4234);
- return -1;
+ DBUG_RETURN(-1);
}//if
} else {
if (tStatus == GetValue) {
@@ -448,7 +440,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
// to set values in the tuple by setValue.
//--------------------------------------------------------------------
if (insertATTRINFO(Interpreter::EXIT_OK) == -1){
- return -1;
+ DBUG_RETURN(-1);
}
theInterpretedSize = theTotalCurrAI_Len -
(theInitialReadSize + 5);
@@ -459,47 +451,47 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
// setValue used in the wrong context. Application coding error.
//-------------------------------------------------------------------
setErrorCodeAbort(4234); //Wrong error code
- return -1;
+ DBUG_RETURN(-1);
}//if
theStatus = SetValueInterpreted;
}//if
} else if (tOpType == InsertRequest) {
if ((theStatus != SetValue) && (theStatus != OperationDefined)) {
setErrorCodeAbort(4234);
- return -1;
+ DBUG_RETURN(-1);
}//if
} else if (tOpType == ReadRequest || tOpType == ReadExclusive) {
setErrorCodeAbort(4504);
- return -1;
+ DBUG_RETURN(-1);
} else if (tOpType == DeleteRequest) {
setErrorCodeAbort(4504);
- return -1;
+ DBUG_RETURN(-1);
} else if (tOpType == OpenScanRequest || tOpType == OpenRangeScanRequest) {
setErrorCodeAbort(4228);
- return -1;
+ DBUG_RETURN(-1);
} else {
//---------------------------------------------------------------------
// setValue with undefined operation type.
// Probably application coding error.
//---------------------------------------------------------------------
setErrorCodeAbort(4108);
- return -1;
+ DBUG_RETURN(-1);
}//if
if (tAttrInfo == NULL) {
setErrorCodeAbort(4004);
- return -1;
+ DBUG_RETURN(-1);
}//if
if (tAttrInfo->m_pk) {
if (theOperationType == InsertRequest) {
- return equal_impl(tAttrInfo, aValuePassed, len);
+ DBUG_RETURN(equal_impl(tAttrInfo, aValuePassed, len));
} else {
setErrorCodeAbort(4202);
- return -1;
+ DBUG_RETURN(-1);
}//if
}//if
if (len > 8000) {
setErrorCodeAbort(4216);
- return -1;
+ DBUG_RETURN(-1);
}//if
tAttrId = tAttrInfo->m_attrId;
@@ -512,33 +504,19 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
insertATTRINFO(ahValue);
// Insert Attribute Id with the value
// NULL into ATTRINFO part.
- return 0;
+ DBUG_RETURN(0);
} else {
/***********************************************************************
* Setting a NULL value on a NOT NULL attribute is not allowed.
**********************************************************************/
setErrorCodeAbort(4203);
- return -1;
+ DBUG_RETURN(-1);
}//if
}//if
// Insert Attribute Id into ATTRINFO part.
const Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- int dummy_error;
- // invalid data can crash kernel
- if (cs != NULL &&
- // fast fix bug#7340
- tAttrInfo->m_type != NdbDictionary::Column::Text &&
- (*cs->cset->well_formed_len)(cs,
- aValue,
- aValue + sizeInBytes,
- sizeInBytes,
- &dummy_error) != sizeInBytes) {
- setErrorCodeAbort(744);
- return -1;
- }
#if 0
tAttrSize = tAttrInfo->theAttrSize;
tArraySize = tAttrInfo->theArraySize;
@@ -552,7 +530,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
const Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
if (len != sizeInBytes && (len != 0)) {
setErrorCodeAbort(4209);
- return -1;
+ DBUG_RETURN(-1);
}//if
const Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Including bits in last word
const Uint32 sizeInWords = sizeInBytes / 4; // Excluding bits in last word
@@ -580,7 +558,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
tReturnCode = insertATTRINFOloop((Uint32*)aValue, sizeInWords);
if (tReturnCode == -1) {
- return tReturnCode;
+ DBUG_RETURN(tReturnCode);
}//if
if (bitsInLastWord != 0) {
tData = *(Uint32*)(aValue + sizeInWords*4);
@@ -589,15 +567,15 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
tData = convertEndian(tData);
tReturnCode = insertATTRINFO(tData);
if (tReturnCode == -1) {
- return tReturnCode;
+ DBUG_RETURN(tReturnCode);
}//if
}//if
theErrorLine++;
- return 0;
+ DBUG_RETURN(0);
}//NdbOperation::setValue()
NdbBlob*
-NdbOperation::getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* tAttrInfo)
+NdbOperation::getBlobHandle(NdbTransaction* aCon, const NdbColumnImpl* tAttrInfo)
{
NdbBlob* tBlob = theBlobList;
NdbBlob* tLastBlob = NULL;
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
index 48882a479b9..58a816e3c1a 100644
--- a/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -16,7 +16,7 @@
#include <ndb_global.h>
#include <NdbOperation.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include "NdbApiSignal.hpp"
#include <Ndb.hpp>
#include <NdbRecAttr.hpp>
@@ -65,7 +65,7 @@ NdbOperation::doSend(int aNodeId, Uint32 lastFlag)
if (tReturnCode == -1) {
return -1;
}
- NdbApiSignal *tSignal = theFirstKEYINFO;
+ NdbApiSignal *tSignal = theTCREQ->next();
while (tSignal != NULL) {
NdbApiSignal* tnextSignal = tSignal->next();
tReturnCode = tp->sendSignal(tSignal, aNodeId);
@@ -208,13 +208,9 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
abortOption = tSimpleIndicator ? AO_IgnoreError : abortOption;
tcKeyReq->setAbortOption(tReqInfo, abortOption);
- Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
- Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
- Uint8 tDistrGroupType = theDistrGroupType;
+ Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
Uint8 tScanIndicator = theScanInfo & 1;
- tcKeyReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
- tcKeyReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
@@ -225,15 +221,13 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
//-------------------------------------------------------------
Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
Uint32 tDistrGHIndex = tScanIndicator;
- Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+ Uint32 tDistrKeyIndex = tDistrGHIndex;
Uint32 tScanInfo = theScanInfo;
- Uint32 tDistributionGroup = theDistributionGroup;
- Uint32 tDistrKeySize = theDistrKeySize;
+ Uint32 tDistrKey = theDistributionKey;
tOptionalDataPtr[0] = tScanInfo;
- tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
- tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+ tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
//-------------------------------------------------------------
// The next is step is to compress the key data part of the
@@ -273,7 +267,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
/**
* Set transid, TC connect ptr and length in the KEYINFO signals
*/
- NdbApiSignal* tSignal = theFirstKEYINFO;
+ NdbApiSignal* tSignal = theTCREQ->next();
Uint32 remainingKey = tTupKeyLen - TcKeyReq::MaxKeyInfo;
do {
Uint32* tSigDataPtr = tSignal->getDataPtrSend();
@@ -555,10 +549,11 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal)
theStatus = Finished;
// blobs want this
if (m_abortOption != AO_IgnoreError)
- theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
-
+ {
+ theNdbCon->theReturnStatus = NdbTransaction::ReturnFailure;
+ }
theError.code = aSignal->readData(4);
- theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4), m_abortOption);
+ theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4), ao);
if(theOperationType != ReadRequest || !theSimpleIndicator) // not simple read
return theNdbCon->OpCompleteFailure(ao, m_abortOption != AO_IgnoreError);
diff --git a/ndb/src/ndbapi/NdbOperationInt.cpp b/ndb/src/ndbapi/NdbOperationInt.cpp
index ace90e35ca4..41e0cb1d140 100644
--- a/ndb/src/ndbapi/NdbOperationInt.cpp
+++ b/ndb/src/ndbapi/NdbOperationInt.cpp
@@ -14,13 +14,12 @@
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 <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <Ndb.hpp>
-#include "NdbRecAttr.hpp"
+#include <NdbRecAttr.hpp>
#include "NdbUtil.hpp"
#include "Interpreter.hpp"
#include <NdbIndexScanOperation.hpp>
@@ -84,7 +83,7 @@ NdbOperation::incCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -136,7 +135,7 @@ NdbOperation::write_attrCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -184,7 +183,7 @@ NdbOperation::read_attrCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -220,7 +219,7 @@ NdbOperation::initial_interpreterCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -246,7 +245,7 @@ NdbOperation::labelCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -266,7 +265,7 @@ NdbOperation::intermediate_interpreterCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -1012,33 +1011,56 @@ NdbOperation::insertCall(Uint32 aCall)
int
NdbOperation::branch_col(Uint32 type,
- Uint32 ColId, const char * val, Uint32 len,
+ Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
+ DBUG_ENTER("NdbOperation::branch_col");
+ DBUG_PRINT("enter", ("type=%u col=%u val=0x%x len=%u label=%u",
+ type, ColId, val, len, Label));
+ if (val != NULL)
+ DBUG_DUMP("value", (char*)val, len);
+
if (initial_interpreterCheck() == -1)
- return -1;
+ DBUG_RETURN(-1);
Interpreter::BinaryCondition c = (Interpreter::BinaryCondition)type;
-
- const NdbDictionary::Column * col =
+
+ const NdbColumnImpl * col =
m_currentTable->getColumn(ColId);
if(col == 0){
abort();
}
- Uint32 vc = col->getType() == NdbDictionary::Column::Varchar;
- Uint32 colLen = col->getLength() + 2 * vc;
- Uint32 al = (4 - (colLen & 3)) & 0x3;
-
- if (insertATTRINFO(Interpreter::BranchCol(c, al, vc, nopad)) == -1)
- return -1;
+ if (val == NULL)
+ len = 0;
+ else {
+ if (! col->getStringType()) {
+ // prevent assert in NdbSqlUtil on length error
+ Uint32 sizeInBytes = col->m_attrSize * col->m_arraySize;
+ if (len != 0 && len != sizeInBytes)
+ {
+ setErrorCodeAbort(4209);
+ DBUG_RETURN(-1);
+ }
+ len = sizeInBytes;
+ }
+ }
+
+ Uint32 tempData[2000];
+ if (((UintPtr)val & 3) != 0) {
+ memcpy(tempData, val, len);
+ val = tempData;
+ }
+
+ if (insertATTRINFO(Interpreter::BranchCol(c, 0, 0, false)) == -1)
+ DBUG_RETURN(-1);
if (insertBranch(Label) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (insertATTRINFO(Interpreter::BranchCol_2(ColId, len)))
- return -1;
+ DBUG_RETURN(-1);
Uint32 len2 = Interpreter::mod4(len);
if(len2 == len){
@@ -1049,64 +1071,64 @@ NdbOperation::branch_col(Uint32 type,
Uint32 tmp = 0;
for (Uint32 i = 0; i < len-len2; i++) {
char* p = (char*)&tmp;
- p[i] = val[len2+i];
+ p[i] = ((char*)val)[len2+i];
}
insertATTRINFO(tmp);
}
theErrorLine++;
- return 0;
+ DBUG_RETURN(0);
}
int
-NdbOperation::branch_col_eq(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_eq(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_eq %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::EQ, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_ne(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_ne(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_ne %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::NE, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_lt(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_lt(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_lt %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::LT, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_le(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_le(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_le %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::LE, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_gt(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_gt(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_gt %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::GT, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_ge(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_ge(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_ge %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::GE, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_like(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_like(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_like %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::LIKE, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_notlike(Uint32 ColId, const char * val, Uint32 len,
- bool nopad, Uint32 Label){
+NdbOperation::branch_col_notlike(Uint32 ColId, const void * val, Uint32 len,
+ bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_notlike %u %.*s(%u,%d) -> %u", ColId,len,val,len,nopad,Label));
return branch_col(Interpreter::NOT_LIKE, ColId, val, len, nopad, Label);
}
diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp
index 97b2393e5ed..06d8ddd412b 100644
--- a/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -31,14 +31,16 @@ Adjust: 971022 UABMNST First version.
#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <Ndb.hpp>
#include "NdbImpl.hpp"
#include <NdbOut.hpp>
#include <AttributeHeader.hpp>
#include <signaldata/TcKeyReq.hpp>
+#include <signaldata/KeyInfo.hpp>
#include "NdbDictionaryImpl.hpp"
+#include <md5_hash.hpp>
/******************************************************************************
CondIdType equal(const char* anAttrName, char* aValue, Uint32 aVarKeylen);
@@ -55,13 +57,20 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
const char* aValuePassed,
Uint32 aVariableKeyLen)
{
- register Uint32 tAttrId;
+ DBUG_ENTER("NdbOperation::equal_impl");
+ DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
+ tAttrInfo->m_name.c_str(),
+ theOperationType,
+ aValuePassed, aVariableKeyLen));
+ if (aValuePassed != NULL)
+ DBUG_DUMP("value", (char*)aValuePassed, aVariableKeyLen);
+ register Uint32 tAttrId;
+
Uint32 tData;
Uint32 tKeyInfoPosition;
const char* aValue = aValuePassed;
- Uint32 xfrmData[1024];
- Uint32 tempData[1024];
+ Uint64 tempData[512];
if ((theStatus == OperationDefined) &&
(aValue != NULL) &&
@@ -76,6 +85,8 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
*****************************************************************************/
tAttrId = tAttrInfo->m_attrId;
tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
+ bool tDistrKey = tAttrInfo->m_distributionKey;
+
Uint32 i = 0;
if (tAttrInfo->m_pk) {
Uint32 tKeyDefined = theTupleKeyDefined[0][2];
@@ -117,44 +128,29 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
theTupleKeyDefined[i][1] = tKeyInfoPosition;
theTupleKeyDefined[i][2] = true;
+ OperationType tOpType = theOperationType;
Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+
{
- /***************************************************************************
- * Check if the pointer of the value passed is aligned on a 4 byte
- * boundary. If so only assign the pointer to the internal variable
- * aValue. If it is not aligned then we start by copying the value to
- * tempData and use this as aValue instead.
- *****************************************************************************/
+ /************************************************************************
+ * Check if the pointer of the value passed is aligned on a 4 byte
+ * boundary. If so only assign the pointer to the internal variable
+ * aValue. If it is not aligned then we start by copying the value to
+ * tempData and use this as aValue instead.
+ ***********************************************************************/
const int attributeSize = sizeInBytes;
const int slack = sizeInBytes & 3;
-
- if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
+ const int align = UintPtr(aValue) & 7;
+
+ if (((align & 3) != 0) || (slack != 0) || (tDistrKey && (align != 0)))
+ {
+ ((Uint32*)tempData)[attributeSize >> 2] = 0;
memcpy(&tempData[0], aValue, attributeSize);
aValue = (char*)&tempData[0];
- if(slack != 0) {
- char * tmp = (char*)&tempData[0];
- memset(&tmp[attributeSize], 0, (4 - slack));
- }//if
}//if
}
- const char* aValueToWrite = aValue;
-
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- if (cs != 0) {
- // current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply <= 1);
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)xfrmData, sizeof(xfrmData),
- (const uchar*)aValue, sizeInBytes);
- while (n < sizeInBytes)
- ((uchar*)xfrmData)[n++] = 0x20;
- aValue = (char*)xfrmData;
- }
- Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Inc. bits in last word
- Uint32 sizeInWords = sizeInBytes / 4; // Exc. bits in last word
if (true){ //tArraySize != 0) {
Uint32 tTupKeyLen = theTupKeyLen;
@@ -190,93 +186,58 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
}//if
#endif
- int tDistrKey = tAttrInfo->m_distributionKey;
- int tDistrGroup = tAttrInfo->m_distributionGroup;
- OperationType tOpType = theOperationType;
- if ((tDistrKey != 1) && (tDistrGroup != 1)) {
- ;
- } else if (tDistrKey == 1) {
- theDistrKeySize += totalSizeInWords;
- theDistrKeyIndicator = 1;
- } else {
- Uint32 TsizeInBytes = sizeInBytes;
- Uint32 TbyteOrderFix = 0;
- char* TcharByteOrderFix = (char*)&TbyteOrderFix;
- if (tAttrInfo->m_distributionGroupBits == 8) {
- char tFirstChar = aValue[TsizeInBytes - 2];
- char tSecondChar = aValue[TsizeInBytes - 2];
- TcharByteOrderFix[0] = tFirstChar;
- TcharByteOrderFix[1] = tSecondChar;
- TcharByteOrderFix[2] = 0x30;
- TcharByteOrderFix[3] = 0x30;
- theDistrGroupType = 0;
- } else {
- TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10)
- + (aValue[TsizeInBytes - 1] - 0x30);
- theDistrGroupType = 1;
- }//if
- theDistributionGroup = TbyteOrderFix;
- theDistrGroupIndicator = 1;
- }//if
- /******************************************************************************
+ /**************************************************************************
* If the operation is an insert request and the attribute is stored then
* we also set the value in the stored part through putting the
* information in the ATTRINFO signals.
- *****************************************************************************/
+ *************************************************************************/
if ((tOpType == InsertRequest) ||
(tOpType == WriteRequest)) {
- if (!tAttrInfo->m_indexOnly){
- int dummy_error;
- // invalid data can crash kernel
- if (cs != NULL &&
- (*cs->cset->well_formed_len)(cs,
- aValueToWrite,
- aValueToWrite + sizeInBytes,
- sizeInBytes,
- &dummy_error) != sizeInBytes)
- goto equal_error4;
- Uint32 ahValue;
- const Uint32 sz = totalSizeInWords;
+ Uint32 ahValue;
+ const Uint32 sz = totalSizeInWords;
+
+ // XXX
+ if(m_accessTable == m_currentTable)
+ {
AttributeHeader::init(&ahValue, tAttrId, sz);
- insertATTRINFO( ahValue );
- insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
- if (bitsInLastWord != 0) {
- tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
- tData = convertEndian(tData);
- tData = tData & ((1 << bitsInLastWord) - 1);
- tData = convertEndian(tData);
- insertATTRINFO( tData );
- }//if
- }//if
+ }
+ else
+ {
+ assert(m_accessTable->m_index);
+ int attr_id_current_table =
+ m_accessTable->m_index->m_columns[tAttrId]->m_keyInfoPos;
+ AttributeHeader::init(&ahValue, attr_id_current_table, sz);
+ }
+
+ insertATTRINFO( ahValue );
+ insertATTRINFOloop((Uint32*)aValue, sz);
}//if
- /***************************************************************************
+ /**************************************************************************
* Store the Key information in the TCKEYREQ and KEYINFO signals.
- **************************************************************************/
- if (insertKEYINFO(aValue, tKeyInfoPosition,
- totalSizeInWords, bitsInLastWord) != -1) {
- /*************************************************************************
+ *************************************************************************/
+ if (insertKEYINFO(aValue, tKeyInfoPosition, totalSizeInWords) != -1) {
+ /************************************************************************
* Add one to number of tuple key attributes defined.
* If all have been defined then set the operation state to indicate
* that tuple key is defined.
* Thereby no more search conditions are allowed in this version.
- ************************************************************************/
- Uint32 tNoKeysDef = theNoOfTupKeyDefined;
+ ***********************************************************************/
+ Uint32 tNoKeysDef = theNoOfTupKeyLeft - 1;
Uint32 tErrorLine = theErrorLine;
- int tNoTableKeys = m_currentTable->m_noOfKeys;
unsigned char tInterpretInd = theInterpretIndicator;
- tNoKeysDef++;
- theNoOfTupKeyDefined = tNoKeysDef;
+ theNoOfTupKeyLeft = tNoKeysDef;
tErrorLine++;
theErrorLine = tErrorLine;
- if (int(tNoKeysDef) == tNoTableKeys) {
+
+ if (tNoKeysDef == 0) {
if (tOpType == UpdateRequest) {
if (tInterpretInd == 1) {
theStatus = GetValue;
} else {
theStatus = SetValue;
}//if
- return 0;
+ DBUG_RETURN(0);
} else if ((tOpType == ReadRequest) || (tOpType == DeleteRequest) ||
(tOpType == ReadExclusive)) {
theStatus = GetValue;
@@ -287,89 +248,62 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
assert(c != 0);
if (c->getBlobType()) {
if (getBlobHandle(theNdbCon, c) == NULL)
- return -1;
+ DBUG_RETURN(-1);
}
}
}
- return 0;
+ DBUG_RETURN(0);
} else if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) {
theStatus = SetValue;
- return 0;
+ DBUG_RETURN(0);
} else {
setErrorCodeAbort(4005);
- return -1;
+ DBUG_RETURN(-1);
}//if
+ DBUG_RETURN(0);
}//if
- return 0;
} else {
- return -1;
+ DBUG_RETURN(-1);
}//if
+ DBUG_RETURN(0);
}
-
+
if (aValue == NULL) {
// NULL value in primary key
setErrorCodeAbort(4505);
- return -1;
+ DBUG_RETURN(-1);
}//if
if ( tAttrInfo == NULL ) {
// Attribute name not found in table
setErrorCodeAbort(4004);
- return -1;
+ DBUG_RETURN(-1);
}//if
if (theStatus == GetValue || theStatus == SetValue){
// All pk's defined
setErrorCodeAbort(4225);
- return -1;
+ DBUG_RETURN(-1);
}//if
+
+ ndbout_c("theStatus: %d", theStatus);
// If we come here, set a general errorcode
// and exit
setErrorCodeAbort(4200);
- return -1;
+ DBUG_RETURN(-1);
equal_error1:
setErrorCodeAbort(4205);
- return -1;
+ DBUG_RETURN(-1);
equal_error2:
setErrorCodeAbort(4206);
- return -1;
+ DBUG_RETURN(-1);
equal_error3:
setErrorCodeAbort(4209);
- return -1;
-
- equal_error4:
- setErrorCodeAbort(744);
- return -1;
-}
-
-/******************************************************************************
- * Uint64 setTupleId( void )
- *
- * Return Value: Return > 0: OK
- * Return 0 : setTupleId failed
- * Parameters:
- * Remark:
- *****************************************************************************/
-Uint64
-NdbOperation::setTupleId()
-{
- if (theStatus != OperationDefined)
- {
- return 0;
- }
- Uint64 tTupleId = theNdb->getTupleIdFromNdb(m_currentTable->m_tableId);
- if (tTupleId == ~(Uint64)0){
- setErrorCodeAbort(theNdb->theError.code);
- return 0;
- }
- if (equal((Uint32)0, tTupleId) == -1)
- return 0;
-
- return tTupleId;
+ DBUG_RETURN(-1);
}
/******************************************************************************
@@ -389,8 +323,7 @@ NdbOperation::setTupleId()
int
NdbOperation::insertKEYINFO(const char* aValue,
register Uint32 aStartPosition,
- register Uint32 anAttrSizeInWords,
- register Uint32 anAttrBitsInLastWord)
+ register Uint32 anAttrSizeInWords)
{
NdbApiSignal* tSignal;
NdbApiSignal* tCurrentKEYINFO;
@@ -410,7 +343,7 @@ NdbOperation::insertKEYINFO(const char* aValue,
*****************************************************************************/
tEndPos = aStartPosition + anAttrSizeInWords - 1;
- if ((tEndPos < 9) && (anAttrBitsInLastWord == 0)) {
+ if ((tEndPos < 9)) {
register Uint32 tkeyData = *(Uint32*)aValue;
//TcKeyReq* tcKeyReq = CAST_PTR(TcKeyReq, tTCREQ->getDataPtrSend());
register Uint32* tDataPtr = (Uint32*)aValue;
@@ -451,10 +384,11 @@ NdbOperation::insertKEYINFO(const char* aValue,
setErrorCodeAbort(4001);
return -1;
}
- if (theFirstKEYINFO != NULL)
+ if (theTCREQ->next() != NULL)
theLastKEYINFO->next(tSignal);
else
- theFirstKEYINFO = tSignal;
+ theTCREQ->next(tSignal);
+
theLastKEYINFO = tSignal;
theLastKEYINFO->next(NULL);
theTotalNrOfKeyWordInSignal += 20;
@@ -467,7 +401,7 @@ NdbOperation::insertKEYINFO(const char* aValue,
* this is the first word in a KEYINFO signal. *
*****************************************************************************/
tPosition = aStartPosition;
- tCurrentKEYINFO = theFirstKEYINFO;
+ tCurrentKEYINFO = theTCREQ->next();
/*****************************************************************************
* Start by filling up Key information in the 8 words allocated in the *
@@ -520,39 +454,20 @@ NdbOperation::insertKEYINFO(const char* aValue,
} while (1);
LastWordLabel:
-
-/*****************************************************************************
- * There could be a last word that only contains partial data. This word*
- * will contain zeroes in the rest of the bits since the index expects *
- * a certain number of words and do not care for parts of words. *
- *****************************************************************************/
- if (anAttrBitsInLastWord != 0) {
- tData = *(Uint32*)(aValue + (anAttrSizeInWords - 1) * 4);
- tData = convertEndian(tData);
- tData = tData & ((1 << anAttrBitsInLastWord) - 1);
- tData = convertEndian(tData);
- if (tPosition > 8) {
- tCurrentKEYINFO->setData(tData, signalCounter);
- signalCounter++;
- } else {
- theTCREQ->setData(tData, (12 + tPosition));
- }//if
- }//if
-
return 0;
}
int
NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
{
- assert(m_accessTable != 0 && m_accessTable->m_sizeOfKeysInWords != 0);
- assert(m_accessTable->m_sizeOfKeysInWords == size);
+ assert(m_accessTable != 0 && m_accessTable->m_keyLenInWords != 0);
+ assert(m_accessTable->m_keyLenInWords == size);
unsigned pos = 0;
while (pos < 8 && pos < size) {
data[pos] = theKEYINFOptr[pos];
pos++;
}
- NdbApiSignal* tSignal = theFirstKEYINFO;
+ NdbApiSignal* tSignal = theTCREQ->next();
unsigned n = 0;
while (pos < size) {
if (n == 20) {
@@ -563,3 +478,115 @@ NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
}
return 0;
}
+
+int
+NdbOperation::handle_distribution_key(const Uint64* value, Uint32 len)
+{
+ if(theDistrKeyIndicator_ == 1 ||
+ (theNoOfTupKeyLeft > 0 && m_accessTable->m_noOfDistributionKeys > 1))
+ {
+ return 0;
+ }
+
+ if(m_accessTable->m_noOfDistributionKeys == 1)
+ {
+ setPartitionHash(value, len);
+ }
+ else if(theTCREQ->readSignalNumber() == GSN_TCKEYREQ)
+ {
+ // No support for combined distribution key and scan
+
+ /**
+ * Copy distribution key to linear memory
+ */
+ NdbColumnImpl* const * cols = m_accessTable->m_columns.getBase();
+ Uint32 len = 0;
+ Uint64 tmp[1000];
+
+ Uint32 chunk = 8;
+ Uint32* dst = (Uint32*)tmp;
+ NdbApiSignal* tSignal = theTCREQ;
+ Uint32* src = ((TcKeyReq*)tSignal->getDataPtrSend())->keyInfo;
+ if(tSignal->readSignalNumber() == GSN_SCAN_TABREQ)
+ {
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ chunk = KeyInfo::DataLength;
+ }
+
+ for(unsigned i = m_accessTable->m_columns.size(); i>0; cols++, i--)
+ {
+ if (!(* cols)->getPrimaryKey())
+ continue;
+
+ NdbColumnImpl* tAttrInfo = * cols;
+ Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ Uint32 currLen = (sizeInBytes + 3) >> 2;
+ if (tAttrInfo->getDistributionKey())
+ {
+ while (currLen >= chunk)
+ {
+ memcpy(dst, src, 4*chunk);
+ dst += chunk;
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ currLen -= chunk;
+ chunk = KeyInfo::DataLength;
+ }
+
+ memcpy(dst, src, 4*currLen);
+ dst += currLen;
+ src += currLen;
+ chunk -= currLen;
+ }
+ else
+ {
+ while (currLen >= chunk)
+ {
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ currLen -= chunk;
+ chunk = KeyInfo::DataLength;
+ }
+
+ src += currLen;
+ chunk -= currLen;
+ }
+ }
+ setPartitionHash(tmp, dst - (Uint32*)tmp);
+ }
+ return 0;
+}
+
+void
+NdbOperation::setPartitionHash(Uint32 value)
+{
+ union {
+ Uint32 tmp32;
+ Uint64 tmp64;
+ };
+
+ tmp32 = value;
+ setPartitionHash(&tmp64, 1);
+}
+
+void
+NdbOperation::setPartitionHash(const Uint64* value, Uint32 len)
+{
+ Uint32 buf[4];
+ md5_hash(buf, value, len);
+ setPartitionId(buf[1]);
+}
+
+void
+NdbOperation::setPartitionId(Uint32 value)
+{
+ theDistributionKey = value;
+ theDistrKeyIndicator_ = 1;
+}
+
+Uint32
+NdbOperation::getPartitionId() const
+{
+ return theDistributionKey;
+}
diff --git a/ndb/src/ndbapi/NdbPool.cpp b/ndb/src/ndbapi/NdbPool.cpp
index ba58520c1dc..a8263f564f1 100644
--- a/ndb/src/ndbapi/NdbPool.cpp
+++ b/ndb/src/ndbapi/NdbPool.cpp
@@ -21,14 +21,16 @@
static NdbPool* m_pool = 0;
bool
-create_instance(Uint32 max_ndb_objects,
+create_instance(Ndb_cluster_connection* cc,
+ Uint32 max_ndb_objects,
Uint32 no_conn_obj,
Uint32 init_no_ndb_objects)
{
if (m_pool != NULL) {
return false;
}
- m_pool = NdbPool::create_instance(max_ndb_objects,
+ m_pool = NdbPool::create_instance(cc,
+ max_ndb_objects,
no_conn_obj,
init_no_ndb_objects);
if (m_pool == NULL) {
diff --git a/ndb/src/ndbapi/NdbPoolImpl.cpp b/ndb/src/ndbapi/NdbPoolImpl.cpp
index 131edc74246..32e0a6f1410 100644
--- a/ndb/src/ndbapi/NdbPoolImpl.cpp
+++ b/ndb/src/ndbapi/NdbPoolImpl.cpp
@@ -20,7 +20,8 @@ NdbMutex *NdbPool::pool_mutex = NULL;
NdbPool *the_pool = NULL;
NdbPool*
-NdbPool::create_instance(Uint32 max_ndb_obj,
+NdbPool::create_instance(Ndb_cluster_connection* cc,
+ Uint32 max_ndb_obj,
Uint32 no_conn_obj,
Uint32 init_no_ndb_objects)
{
@@ -32,7 +33,7 @@ NdbPool::create_instance(Uint32 max_ndb_obj,
if (the_pool != NULL) {
a_pool = NULL;
} else {
- the_pool = new NdbPool(max_ndb_obj, no_conn_obj);
+ the_pool = new NdbPool(cc, max_ndb_obj, no_conn_obj);
if (!the_pool->init(init_no_ndb_objects)) {
delete the_pool;
the_pool = NULL;
@@ -76,7 +77,8 @@ NdbPool::initPoolMutex()
return ret_result;
}
-NdbPool::NdbPool(Uint32 max_no_objects,
+NdbPool::NdbPool(Ndb_cluster_connection* cc,
+ Uint32 max_no_objects,
Uint32 no_conn_objects)
{
if (no_conn_objects > 1024) {
@@ -101,6 +103,7 @@ NdbPool::NdbPool(Uint32 max_no_objects,
m_output_queue = 0;
m_input_queue = 0;
m_signal_count = 0;
+ m_cluster_connection = cc;
}
NdbPool::~NdbPool()
@@ -294,9 +297,9 @@ NdbPool::allocate_ndb(Uint32 &id,
return false;
}
if (a_schema_name) {
- a_ndb = new Ndb(a_schema_name, a_catalog_name);
+ a_ndb = new Ndb(m_cluster_connection, a_schema_name, a_catalog_name);
} else {
- a_ndb = new Ndb("");
+ a_ndb = new Ndb(m_cluster_connection, "");
}
if (a_ndb == NULL) {
return false;
diff --git a/ndb/src/ndbapi/NdbPoolImpl.hpp b/ndb/src/ndbapi/NdbPoolImpl.hpp
index af6cf4708cf..cd36f30e90b 100644
--- a/ndb/src/ndbapi/NdbPoolImpl.hpp
+++ b/ndb/src/ndbapi/NdbPoolImpl.hpp
@@ -92,7 +92,8 @@ class NdbPool {
Uint16 prev_db_object;
};
public:
- static NdbPool* create_instance(Uint32 max_ndb_objects = 240,
+ static NdbPool* create_instance(Ndb_cluster_connection*,
+ Uint32 max_ndb_objects = 240,
Uint32 no_conn_obj = 4,
Uint32 init_no_ndb_objects = 8);
static void drop_instance();
@@ -104,7 +105,8 @@ class NdbPool {
bool init(Uint32 initial_no_of_ndb_objects = 8);
void release_all();
static bool initPoolMutex();
- NdbPool(Uint32 max_no_of_ndb_objects, Uint32 no_conn_objects);
+ NdbPool(Ndb_cluster_connection*,
+ Uint32 max_no_of_ndb_objects, Uint32 no_conn_objects);
~NdbPool();
/*
We have three lists:
@@ -158,5 +160,7 @@ class NdbPool {
Uint16 m_input_queue;
Uint16 m_output_queue;
Uint16 m_signal_count;
+
+ Ndb_cluster_connection * m_cluster_connection;
};
#endif
diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp
index db83e9c5fcf..5e5306fc33a 100644
--- a/ndb/src/ndbapi/NdbRecAttr.cpp
+++ b/ndb/src/ndbapi/NdbRecAttr.cpp
@@ -15,17 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/************************************************************************************************
-Name: NdbRecAttr.C
-Include:
-Link:
-Author: UABRONM Mikael Ronström UAB/B/SD
-Date: 971206
-Version: 0.1
-Description: Interface between TIS and NDB
-Documentation:
-Adjust: 971206 UABRONM First version
-************************************************************************************************/
#include <ndb_global.h>
#include <NdbOut.hpp>
#include <NdbRecAttr.hpp>
@@ -148,6 +137,40 @@ NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
return false;
}
+static void
+ndbrecattr_print_string(NdbOut& out, const char *type,
+ const char *aref, unsigned sz)
+{
+ const unsigned char* ref = (const unsigned char*)aref;
+ int i, len, printable= 1;
+ // trailing zeroes are not printed
+ for (i=sz-1; i >= 0; i--)
+ if (ref[i] == 0) sz--;
+ else break;
+ if (sz == 0) return; // empty
+
+ for (len=0; len < (int)sz && ref[i] != 0; len++)
+ if (printable && !isprint((int)ref[i]))
+ printable= 0;
+
+ if (printable)
+ out.print("%.*s", len, ref);
+ else
+ {
+ out.print("0x");
+ for (i=0; i < len; i++)
+ out.print("%02X", (int)ref[i]);
+ }
+ if (len != (int)sz)
+ {
+ out.print("[");
+ for (i= len+1; ref[i] != 0; i++)
+ out.print("%u]",len-i);
+ assert((int)sz > i);
+ ndbrecattr_print_string(out,type,aref+i,sz-i);
+ }
+}
+
NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
{
if (r.isNULL())
@@ -171,6 +194,9 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
case NdbDictionary::Column::Bigunsigned:
out << r.u_64_value();
break;
+ case NdbDictionary::Column::Bit:
+ out << hex << "H'" << r.u_32_value() << dec;
+ break;
case NdbDictionary::Column::Unsigned:
out << r.u_32_value();
break;
@@ -192,17 +218,21 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
case NdbDictionary::Column::Tinyint:
out << (int) r.char_value();
break;
+ case NdbDictionary::Column::Binary:
+ ndbrecattr_print_string(out,"Binary",r.aRef(),r.arraySize());
+ j = r.arraySize();
+ break;
case NdbDictionary::Column::Char:
- out.print("%.*s", r.arraySize(), r.aRef());
+ ndbrecattr_print_string(out,"Char",r.aRef(),r.arraySize());
j = length;
break;
case NdbDictionary::Column::Varchar:
- {
- short len = ntohs(r.u_short_value());
- out.print("%.*s", len, r.aRef()+2);
- }
- j = length;
- break;
+ {
+ unsigned len = *(const unsigned char*)r.aRef();
+ ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len);
+ j = length;
+ }
+ break;
case NdbDictionary::Column::Float:
out << r.float_value();
break;
@@ -221,6 +251,10 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
out.print("%.*s", len, r.aRef());
}
break;
+ case NdbDictionary::Column::Decimal:
+ case NdbDictionary::Column::Decimalunsigned:
+ goto unknown; // TODO
+ break;
// for dates cut-and-paste from field.cc
case NdbDictionary::Column::Datetime:
{
@@ -323,6 +357,14 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
j = length;
}
break;
+ case NdbDictionary::Column::Longvarchar:
+ {
+ unsigned len = uint2korr(r.aRef());
+ ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len);
+ j = length;
+ }
+ break;
+ unknown:
default: /* no print functions for the rest, just print type */
out << (int) r.getType();
j = length;
diff --git a/ndb/src/ndbapi/NdbReceiver.cpp b/ndb/src/ndbapi/NdbReceiver.cpp
index cad247512b2..df16ae66915 100644
--- a/ndb/src/ndbapi/NdbReceiver.cpp
+++ b/ndb/src/ndbapi/NdbReceiver.cpp
@@ -20,7 +20,7 @@
#include "NdbDictionaryImpl.hpp"
#include <NdbRecAttr.hpp>
#include <AttributeHeader.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <TransporterFacade.hpp>
#include <signaldata/TcKeyConf.hpp>
@@ -140,7 +140,10 @@ NdbReceiver::calculate_batch_size(Uint32 key_size,
}
void
-NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
+NdbReceiver::do_get_value(NdbReceiver * org,
+ Uint32 rows,
+ Uint32 key_size,
+ Uint32 range_no){
if(rows > m_defined_rows){
delete[] m_rows;
m_defined_rows = rows;
@@ -155,7 +158,7 @@ NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
key.m_attrSize = 4;
key.m_nullable = true; // So that receive works w.r.t KEYINFO20
}
- m_key_info = key_size;
+ m_hidden_count = (key_size ? 1 : 0) + range_no ;
for(Uint32 i = 0; i<rows; i++){
NdbRecAttr * prev = theCurrentRecAttr;
@@ -167,6 +170,12 @@ NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
return ; // -1
}
+ if(range_no &&
+ !getValue(&NdbColumnImpl::getImpl(* NdbDictionary::Column::RANGE_NO),0))
+ {
+ abort();
+ }
+
NdbRecAttr* tRecAttr = org->theFirstRecAttr;
while(tRecAttr != 0){
if(getValue(&NdbColumnImpl::getImpl(*tRecAttr->m_column), (char*)0) != 0)
@@ -192,14 +201,14 @@ NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
return;
}
-void
+NdbRecAttr*
NdbReceiver::copyout(NdbReceiver & dstRec){
- NdbRecAttr* src = m_rows[m_current_row++];
- NdbRecAttr* dst = dstRec.theFirstRecAttr;
- Uint32 tmp = m_key_info;
- if(tmp > 0){
+ NdbRecAttr *src = m_rows[m_current_row++];
+ NdbRecAttr *dst = dstRec.theFirstRecAttr;
+ NdbRecAttr *start = src;
+ Uint32 tmp = m_hidden_count;
+ while(tmp--)
src = src->next();
- }
while(dst){
Uint32 len = ((src->theAttrSize * src->theArraySize)+3)/4;
@@ -207,6 +216,8 @@ NdbReceiver::copyout(NdbReceiver & dstRec){
src = src->next();
dst = dst->next();
}
+
+ return start;
}
int
diff --git a/ndb/src/ndbapi/NdbResultSet.cpp b/ndb/src/ndbapi/NdbResultSet.cpp
deleted file mode 100644
index 87b304126ba..00000000000
--- a/ndb/src/ndbapi/NdbResultSet.cpp
+++ /dev/null
@@ -1,103 +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: NdbResultSet.cpp
- * Include:
- * Link:
- * Author: UABMASD Martin Sköld INN/V Alzato
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Cursor class
- * Documentation:
- * Adjust: 2002-04-01 UABMASD First version.
- ****************************************************************************/
-
-#include <Ndb.hpp>
-#include <NdbConnection.hpp>
-#include <NdbResultSet.hpp>
-#include <NdbBlob.hpp>
-
-NdbResultSet::NdbResultSet(NdbScanOperation *owner)
-: m_operation(owner)
-{
-}
-
-NdbResultSet::~NdbResultSet()
-{
-}
-
-void NdbResultSet::init()
-{
-}
-
-int NdbResultSet::nextResult(bool fetchAllowed, bool forceSend)
-{
- int res;
- if ((res = m_operation->nextResult(fetchAllowed, forceSend)) == 0) {
- // handle blobs
- NdbBlob* tBlob = m_operation->theBlobList;
- while (tBlob != 0) {
- if (tBlob->atNextResult() == -1)
- return -1;
- tBlob = tBlob->theNext;
- }
- /*
- * Flush blob part ops on behalf of user because
- * - nextResult is analogous to execute(NoCommit)
- * - user is likely to want blob value before next execute
- */
- if (m_operation->m_transConnection->executePendingBlobOps() == -1)
- return -1;
- return 0;
- }
- return res;
-}
-
-void NdbResultSet::close(bool forceSend)
-{
- m_operation->closeScan(forceSend, true);
-}
-
-NdbOperation*
-NdbResultSet::updateTuple(){
- return updateTuple(m_operation->m_transConnection);
-}
-
-NdbOperation*
-NdbResultSet::updateTuple(NdbConnection* takeOverTrans){
- return m_operation->takeOverScanOp(NdbOperation::UpdateRequest,
- takeOverTrans);
-}
-
-int
-NdbResultSet::deleteTuple(){
- return deleteTuple(m_operation->m_transConnection);
-}
-
-int
-NdbResultSet::deleteTuple(NdbConnection * takeOverTrans){
- void * res = m_operation->takeOverScanOp(NdbOperation::DeleteRequest,
- takeOverTrans);
- if(res == 0)
- return -1;
- return 0;
-}
-
-int
-NdbResultSet::restart(bool forceSend){
- return m_operation->restart(forceSend);
-}
diff --git a/ndb/src/ndbapi/NdbScanFilter.cpp b/ndb/src/ndbapi/NdbScanFilter.cpp
index 0c851427ba5..b39fd10fe95 100644
--- a/ndb/src/ndbapi/NdbScanFilter.cpp
+++ b/ndb/src/ndbapi/NdbScanFilter.cpp
@@ -48,11 +48,8 @@ public:
int cond_col(Interpreter::UnaryCondition, Uint32 attrId);
- template<typename T>
- int cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, T value);
-
int cond_col_const(Interpreter::BinaryCondition, Uint32 attrId,
- const char * value, Uint32 len, bool nopad);
+ const void * value, Uint32 len);
};
const Uint32 LabelExit = ~0;
@@ -247,68 +244,7 @@ NdbScanFilter::isfalse(){
typedef int (NdbOperation:: * Branch1)(Uint32, Uint32 label);
-typedef int (NdbOperation:: * Branch2)(Uint32, Uint32, Uint32 label);
-typedef int (NdbOperation:: * StrBranch2)(Uint32, const char*,Uint32,bool,Uint32);
-
-struct tab {
- Branch2 m_branches[5];
-};
-
-static const tab table[] = {
- /**
- * EQ (AND, OR, NAND, NOR)
- */
- { { 0,
- &NdbOperation::branch_ne,
- &NdbOperation::branch_eq,
- &NdbOperation::branch_eq,
- &NdbOperation::branch_ne } }
-
- /**
- * NEQ
- */
- ,{ { 0,
- &NdbOperation::branch_eq,
- &NdbOperation::branch_ne,
- &NdbOperation::branch_ne,
- &NdbOperation::branch_eq } }
-
- /**
- * LT
- */
- ,{ { 0,
- &NdbOperation::branch_le,
- &NdbOperation::branch_gt,
- &NdbOperation::branch_gt,
- &NdbOperation::branch_le } }
-
- /**
- * LE
- */
- ,{ { 0,
- &NdbOperation::branch_lt,
- &NdbOperation::branch_ge,
- &NdbOperation::branch_ge,
- &NdbOperation::branch_lt } }
-
- /**
- * GT
- */
- ,{ { 0,
- &NdbOperation::branch_ge,
- &NdbOperation::branch_lt,
- &NdbOperation::branch_lt,
- &NdbOperation::branch_ge } }
-
- /**
- * GE
- */
- ,{ { 0,
- &NdbOperation::branch_gt,
- &NdbOperation::branch_le,
- &NdbOperation::branch_le,
- &NdbOperation::branch_gt } }
-};
+typedef int (NdbOperation:: * StrBranch2)(Uint32, const void*, Uint32, bool, Uint32);
struct tab2 {
Branch1 m_branches[5];
@@ -334,134 +270,9 @@ static const tab2 table2[] = {
&NdbOperation::branch_col_eq_null } }
};
-const int tab_sz = sizeof(table)/sizeof(table[0]);
const int tab2_sz = sizeof(table2)/sizeof(table2[0]);
int
-matchType(const NdbDictionary::Column * col){
- return 1;
-}
-
-template<typename T> int load_const(NdbOperation* op, T value, Uint32 reg);
-
-template<>
-int
-load_const(NdbOperation* op, Uint32 value, Uint32 reg){
- return op->load_const_u32(reg, value);
-}
-
-template<>
-int
-load_const(NdbOperation* op, Uint64 value, Uint32 reg){
- return op->load_const_u64(reg, value);
-}
-
-template<typename T>
-int
-NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op,
- Uint32 AttrId, T value){
-
- if(op < 0 || op >= tab_sz){
- m_operation->setErrorCodeAbort(4262);
- return -1;
- }
-
- if(m_current.m_group < NdbScanFilter::AND ||
- m_current.m_group > NdbScanFilter::NOR){
- m_operation->setErrorCodeAbort(4260);
- return -1;
- }
-
- Branch2 branch = table[op].m_branches[m_current.m_group];
- const NdbDictionary::Column * col =
- m_operation->m_currentTable->getColumn(AttrId);
-
- if(col == 0){
- m_operation->setErrorCodeAbort(4261);
- return -1;
- }
-
- if(!matchType(col)){
- /**
- * Code not reached
- */
- return -1;
- }
-
- if(m_latestAttrib != AttrId){
- m_operation->read_attr(&NdbColumnImpl::getImpl(* col), 4);
- m_latestAttrib = AttrId;
- }
-
- load_const<T>(m_operation, value, 5);
- (m_operation->* branch)(4, 5, m_current.m_ownLabel);
-
- return 0;
-}
-
-int
-NdbScanFilter::eq(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::EQ, AttrId, value);
-}
-
-int
-NdbScanFilter::ne(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::NE, AttrId, value);
-}
-
-int
-NdbScanFilter::lt(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::LT, AttrId, value);
-}
-
-int
-NdbScanFilter::le(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::LE, AttrId, value);
-}
-
-int
-NdbScanFilter::gt(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::GT, AttrId, value);
-}
-
-int
-NdbScanFilter::ge(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::GE, AttrId, value);
-}
-
-
-int
-NdbScanFilter::eq(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::EQ, AttrId, value);
-}
-
-int
-NdbScanFilter::ne(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::NE, AttrId, value);
-}
-
-int
-NdbScanFilter::lt(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::LT, AttrId, value);
-}
-
-int
-NdbScanFilter::le(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::LE, AttrId, value);
-}
-
-int
-NdbScanFilter::gt(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::GT, AttrId, value);
-}
-
-int
-NdbScanFilter::ge(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::GE, AttrId, value);
-}
-
-
-int
NdbScanFilterImpl::cond_col(Interpreter::UnaryCondition op, Uint32 AttrId){
if(op < 0 || op >= tab2_sz){
@@ -570,11 +381,10 @@ static const tab3 table3[] = {
const int tab3_sz = sizeof(table3)/sizeof(table3[0]);
-
int
NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op,
Uint32 AttrId,
- const char * value, Uint32 len, bool nopad){
+ const void * value, Uint32 len){
if(op < 0 || op >= tab3_sz){
m_operation->setErrorCodeAbort(4260);
return -1;
@@ -595,49 +405,35 @@ NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op,
return -1;
}
- (m_operation->* branch)(AttrId, value, len, nopad, m_current.m_ownLabel);
- return 0;
-}
-
-int
-NdbScanFilter::eq(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::EQ, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::ne(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::NE, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::lt(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::LT, ColId, val, len, nopad);
+ int ret = (m_operation->* branch)(AttrId, value, len, false, m_current.m_ownLabel);
+ return ret;
}
int
-NdbScanFilter::le(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::LE, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::gt(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::GT, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::ge(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::GE, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::like(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::LIKE, ColId, val, len, nopad);
-}
+NdbScanFilter::cmp(BinaryCondition cond, int ColId,
+ const void *val, Uint32 len)
+{
+ switch(cond){
+ case COND_LE:
+ return m_impl.cond_col_const(Interpreter::LE, ColId, val, len);
+ case COND_LT:
+ return m_impl.cond_col_const(Interpreter::LT, ColId, val, len);
+ case COND_GE:
+ return m_impl.cond_col_const(Interpreter::GE, ColId, val, len);
+ case COND_GT:
+ return m_impl.cond_col_const(Interpreter::GT, ColId, val, len);
+ case COND_EQ:
+ return m_impl.cond_col_const(Interpreter::EQ, ColId, val, len);
+ case COND_NE:
+ return m_impl.cond_col_const(Interpreter::NE, ColId, val, len);
+ case COND_LIKE:
+ return m_impl.cond_col_const(Interpreter::LIKE, ColId, val, len);
+ case COND_NOT_LIKE:
+ return m_impl.cond_col_const(Interpreter::NOT_LIKE, ColId, val, len);
+ }
+ return -1;
+}
-int
-NdbScanFilter::notlike(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::NOT_LIKE, ColId, val, len, nopad);
-}
#if 0
int
@@ -778,10 +574,4 @@ main(void){
#endif
template class Vector<NdbScanFilterImpl::State>;
-#if __SUNPRO_CC != 0x560
-#ifndef _FORTEC_
-template int NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, Uint32);
-template int NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, Uint64);
-#endif
-#endif
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index fc5a22cce17..e0a480e02f7 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -18,11 +18,11 @@
#include <Ndb.hpp>
#include <NdbScanOperation.hpp>
#include <NdbIndexScanOperation.hpp>
-#include <NdbConnection.hpp>
-#include <NdbResultSet.hpp>
+#include <NdbTransaction.hpp>
#include "NdbApiSignal.hpp"
#include <NdbOut.hpp>
#include "NdbDictionaryImpl.hpp"
+#include <NdbBlob.hpp>
#include <NdbRecAttr.hpp>
#include <NdbReceiver.hpp>
@@ -39,7 +39,6 @@
NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
NdbOperation(aNdb),
- m_resultSet(0),
m_transConnection(NULL)
{
theParallelism = 0;
@@ -60,24 +59,11 @@ NdbScanOperation::~NdbScanOperation()
theNdb->releaseNdbScanRec(m_receivers[i]);
}
delete[] m_array;
- if (m_resultSet)
- delete m_resultSet;
}
-NdbResultSet*
-NdbScanOperation::getResultSet()
-{
- if (!m_resultSet)
- m_resultSet = new NdbResultSet(this);
-
- return m_resultSet;
-}
-
-
-
void
NdbScanOperation::setErrorCode(int aErrorCode){
- NdbConnection* tmp = theNdbCon;
+ NdbTransaction* tmp = theNdbCon;
theNdbCon = m_transConnection;
NdbOperation::setErrorCode(aErrorCode);
theNdbCon = tmp;
@@ -85,7 +71,7 @@ NdbScanOperation::setErrorCode(int aErrorCode){
void
NdbScanOperation::setErrorCodeAbort(int aErrorCode){
- NdbConnection* tmp = theNdbCon;
+ NdbTransaction* tmp = theNdbCon;
theNdbCon = m_transConnection;
NdbOperation::setErrorCodeAbort(aErrorCode);
theNdbCon = tmp;
@@ -100,18 +86,21 @@ NdbScanOperation::setErrorCodeAbort(int aErrorCode){
* Remark: Initiates operation record after allocation.
*****************************************************************************/
int
-NdbScanOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection)
+NdbScanOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection)
{
m_transConnection = myConnection;
//NdbConnection* aScanConnection = theNdb->startTransaction(myConnection);
- NdbConnection* aScanConnection = theNdb->hupp(myConnection);
+ theNdb->theRemainingStartTransactions++; // will be checked in hupp...
+ NdbTransaction* aScanConnection = theNdb->hupp(myConnection);
if (!aScanConnection){
+ theNdb->theRemainingStartTransactions--;
setErrorCodeAbort(theNdb->getNdbError().code);
return -1;
}
// NOTE! The hupped trans becomes the owner of the operation
if(NdbOperation::init(tab, aScanConnection) != 0){
+ theNdb->theRemainingStartTransactions--;
return -1;
}
@@ -120,16 +109,17 @@ NdbScanOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection)
theStatus = GetValue;
theOperationType = OpenScanRequest;
theNdbCon->theMagicNumber = 0xFE11DF;
-
+ theNoOfTupKeyLeft = tab->m_noOfDistributionKeys;
+ m_read_range_no = 0;
return 0;
}
-NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
- Uint32 batch,
- Uint32 parallel)
+int
+NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
+ Uint32 scan_flags,
+ Uint32 parallel)
{
- m_ordered = 0;
-
+ m_ordered = m_descending = false;
Uint32 fragCount = m_currentTable->m_fragmentCount;
if (parallel > fragCount || parallel == 0) {
@@ -142,7 +132,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
// 3. theScanOp contains a NdbScanOperation
if (theNdbCon->theScanningOp != NULL){
setErrorCode(4605);
- return 0;
+ return -1;
}
theNdbCon->theScanningOp = this;
@@ -167,14 +157,14 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
break;
default:
setErrorCode(4003);
- return 0;
+ return -1;
}
m_keyInfo = lockExcl ? 1 : 0;
- bool range = false;
- if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex ||
- m_accessTable->m_indexType == NdbDictionary::Index::UniqueOrderedIndex){
+ bool rangeScan = false;
+ if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex)
+ {
if (m_currentTable == m_accessTable){
// Old way of scanning indexes, should not be allowed
m_currentTable = theNdb->theDictionary->
@@ -185,22 +175,27 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
// Modify operation state
theStatus = GetValue;
theOperationType = OpenRangeScanRequest;
- range = true;
+ rangeScan = true;
}
+
+ bool tupScan = (scan_flags & SF_TupScan);
+ if (tupScan && rangeScan)
+ tupScan = false;
theParallelism = parallel;
if(fix_receivers(parallel) == -1){
setErrorCodeAbort(4000);
- return 0;
+ return -1;
}
theSCAN_TABREQ = (!theSCAN_TABREQ ? theNdb->getSignal() : theSCAN_TABREQ);
if (theSCAN_TABREQ == NULL) {
setErrorCodeAbort(4000);
- return 0;
+ return -1;
}//if
+ theSCAN_TABREQ->setSignal(GSN_SCAN_TABREQ);
ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
req->apiConnectPtr = theNdbCon->theTCConPtr;
req->tableId = m_accessTable->m_tableId;
@@ -214,17 +209,19 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
ScanTabReq::setLockMode(reqInfo, lockExcl);
ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode);
ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted);
- ScanTabReq::setRangeScanFlag(reqInfo, range);
+ ScanTabReq::setRangeScanFlag(reqInfo, rangeScan);
+ ScanTabReq::setTupScanFlag(reqInfo, tupScan);
req->requestInfo = reqInfo;
Uint64 transId = theNdbCon->getTransactionId();
req->transId1 = (Uint32) transId;
req->transId2 = (Uint32) (transId >> 32);
- NdbApiSignal* tSignal =
- theFirstKEYINFO;
-
- theFirstKEYINFO = (tSignal ? tSignal : tSignal = theNdb->getSignal());
+ NdbApiSignal* tSignal = theSCAN_TABREQ->next();
+ if(!tSignal)
+ {
+ theSCAN_TABREQ->next(tSignal = theNdb->getSignal());
+ }
theLastKEYINFO = tSignal;
tSignal->setSignal(GSN_KEYINFO);
@@ -232,7 +229,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
theTotalNrOfKeyWordInSignal= 0;
getFirstATTRINFOScan();
- return getResultSet();
+ return 0;
}
int
@@ -356,65 +353,11 @@ NdbScanOperation::getFirstATTRINFOScan()
#define FAKE_PTR 2
#define API_PTR 3
-
-/*
- * After setBound() are done, move the accumulated ATTRINFO signals to
- * a separate list. Then continue with normal scan.
- */
-#if 0
-int
-NdbIndexScanOperation::saveBoundATTRINFO()
-{
- theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
- theBoundATTRINFO = theFirstATTRINFO;
- theTotalBoundAI_Len = theTotalCurrAI_Len;
- theTotalCurrAI_Len = 5;
- theBoundATTRINFO->setData(theTotalBoundAI_Len, 4);
- theBoundATTRINFO->setData(0, 5);
- theBoundATTRINFO->setData(0, 6);
- theBoundATTRINFO->setData(0, 7);
- theBoundATTRINFO->setData(0, 8);
- theStatus = GetValue;
-
- int res = getFirstATTRINFOScan();
-
- /**
- * Define each key with getValue (if ordered)
- * unless the one's with EqBound
- */
- if(!res && m_ordered){
-
- /**
- * If setBound EQ
- */
- Uint32 i = 0;
- while(theTupleKeyDefined[i][0] == SETBOUND_EQ)
- i++;
-
-
- Uint32 cnt = m_accessTable->getNoOfColumns() - 1;
- m_sort_columns = cnt - i;
- for(; i<cnt; i++){
- const NdbColumnImpl* key = m_accessTable->m_index->m_columns[i];
- const NdbColumnImpl* col = m_currentTable->getColumn(key->m_keyInfoPos);
- NdbRecAttr* tmp = NdbScanOperation::getValue_impl(col, (char*)-1);
- UintPtr newVal = UintPtr(tmp);
- theTupleKeyDefined[i][0] = FAKE_PTR;
- theTupleKeyDefined[i][1] = (newVal & 0xFFFFFFFF);
-#if (SIZEOF_CHARP == 8)
- theTupleKeyDefined[i][2] = (newVal >> 32);
-#endif
- }
- }
- return res;
-}
-#endif
-
#define WAITFOR_SCAN_TIMEOUT 120000
int
NdbScanOperation::executeCursor(int nodeId){
- NdbConnection * tCon = theNdbCon;
+ NdbTransaction * tCon = theNdbCon;
TransporterFacade* tp = TransporterFacade::instance();
Guard guard(tp->theMutexPtr);
@@ -448,7 +391,7 @@ NdbScanOperation::executeCursor(int nodeId){
TRACE_DEBUG("The node is stopping when attempting to start a scan");
setErrorCode(4030);
}//if
- tCon->theCommitStatus = NdbConnection::Aborted;
+ tCon->theCommitStatus = NdbTransaction::Aborted;
}//if
return -1;
}
@@ -456,6 +399,29 @@ NdbScanOperation::executeCursor(int nodeId){
int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
{
+ int res;
+ if ((res = nextResultImpl(fetchAllowed, forceSend)) == 0) {
+ // handle blobs
+ NdbBlob* tBlob = theBlobList;
+ while (tBlob != 0) {
+ if (tBlob->atNextResult() == -1)
+ return -1;
+ tBlob = tBlob->theNext;
+ }
+ /*
+ * Flush blob part ops on behalf of user because
+ * - nextResult is analogous to execute(NoCommit)
+ * - user is likely to want blob value before next execute
+ */
+ if (m_transConnection->executePendingBlobOps() == -1)
+ return -1;
+ return 0;
+ }
+ return res;
+}
+
+int NdbScanOperation::nextResultImpl(bool fetchAllowed, bool forceSend)
+{
if(m_ordered)
return ((NdbIndexScanOperation*)this)->next_result_ordered(fetchAllowed,
forceSend);
@@ -466,6 +432,7 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
int retVal = 2;
Uint32 idx = m_current_api_receiver;
Uint32 last = m_api_receivers_count;
+ m_curr_row = 0;
if(DEBUG_NEXT_RESULT)
ndbout_c("nextResult(%d) idx=%d last=%d", fetchAllowed, idx, last);
@@ -476,7 +443,7 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
for(; idx < last; idx++){
NdbReceiver* tRec = m_api_receivers[idx];
if(tRec->nextResult()){
- tRec->copyout(theReceiver);
+ m_curr_row = tRec->copyout(theReceiver);
retVal = 0;
break;
}
@@ -552,7 +519,7 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
for(; idx < last; idx++){
NdbReceiver* tRec = m_api_receivers[idx];
if(tRec->nextResult()){
- tRec->copyout(theReceiver);
+ m_curr_row = tRec->copyout(theReceiver);
retVal = 0;
break;
}
@@ -674,11 +641,17 @@ NdbScanOperation::doSend(int ProcessorId)
return 0;
}
-void NdbScanOperation::closeScan(bool forceSend, bool releaseOp)
+void NdbScanOperation::close(bool forceSend, bool releaseOp)
{
+ DBUG_ENTER("NdbScanOperation::close");
+ DBUG_PRINT("enter", ("this=%x tcon=%x con=%x force=%d release=%d",
+ (UintPtr)this,
+ (UintPtr)m_transConnection, (UintPtr)theNdbCon,
+ forceSend, releaseOp));
+
if(m_transConnection){
if(DEBUG_NEXT_RESULT)
- ndbout_c("closeScan() theError.code = %d "
+ ndbout_c("close() theError.code = %d "
"m_api_receivers_count = %d "
"m_conf_receivers_count = %d "
"m_sent_receivers_count = %d",
@@ -705,6 +678,8 @@ void NdbScanOperation::closeScan(bool forceSend, bool releaseOp)
tCon->theScanningOp = 0;
theNdb->closeTransaction(tCon);
+ theNdb->theRemainingStartTransactions--;
+ DBUG_VOID_RETURN;
}
void
@@ -716,17 +691,19 @@ NdbScanOperation::execCLOSE_SCAN_REP(){
void NdbScanOperation::release()
{
if(theNdbCon != 0 || m_transConnection != 0){
- closeScan();
+ close();
}
for(Uint32 i = 0; i<m_allocated_receivers; i++){
m_receivers[i]->release();
}
+
+ NdbOperation::release();
+
if(theSCAN_TABREQ)
{
theNdb->releaseSignal(theSCAN_TABREQ);
theSCAN_TABREQ = 0;
}
- NdbOperation::release();
}
/***************************************************************************
@@ -793,7 +770,9 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
req->requestInfo = reqInfo;
for(Uint32 i = 0; i<theParallelism; i++){
- m_receivers[i]->do_get_value(&theReceiver, batch_size, key_size);
+ m_receivers[i]->do_get_value(&theReceiver, batch_size,
+ key_size,
+ m_read_range_no);
}
return 0;
}
@@ -821,10 +800,6 @@ NdbScanOperation::doSendScan(int aProcessorId)
assert(theSCAN_TABREQ != NULL);
tSignal = theSCAN_TABREQ;
- if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) {
- setErrorCode(4001);
- return -1;
- }
Uint32 tupKeyLen = theTupKeyLen;
Uint32 len = theTotalNrOfKeyWordInSignal;
@@ -836,7 +811,12 @@ NdbScanOperation::doSendScan(int aProcessorId)
// we created the ATTRINFO signals after the SCAN_TABREQ signal.
ScanTabReq * const req = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend());
req->attrLenKeyLen = (tupKeyLen << 16) | theTotalCurrAI_Len;
-
+ Uint32 tmp = req->requestInfo;
+ ScanTabReq::setDistributionKeyFlag(tmp, theDistrKeyIndicator_);
+ req->distributionKey = theDistributionKey;
+ req->requestInfo = tmp;
+ tSignal->setLength(ScanTabReq::StaticLength + theDistrKeyIndicator_);
+
TransporterFacade *tp = TransporterFacade::instance();
LinearSectionPtr ptr[3];
ptr[0].p = m_prepared_receivers;
@@ -852,8 +832,8 @@ NdbScanOperation::doSendScan(int aProcessorId)
tSignal = theLastKEYINFO;
tSignal->setLength(KeyInfo::HeaderLength + theTotalNrOfKeyWordInSignal);
- assert(theFirstKEYINFO != NULL);
- tSignal = theFirstKEYINFO;
+ assert(theSCAN_TABREQ->next() != NULL);
+ tSignal = theSCAN_TABREQ->next();
NdbApiSignal* last;
do {
@@ -889,6 +869,7 @@ NdbScanOperation::doSendScan(int aProcessorId)
}
theStatus = WaitResponse;
+ m_curr_row = 0;
m_sent_receivers_count = theParallelism;
if(m_ordered)
{
@@ -900,9 +881,9 @@ NdbScanOperation::doSendScan(int aProcessorId)
}//NdbOperation::doSendScan()
/*****************************************************************************
- * NdbOperation* takeOverScanOp(NdbConnection* updateTrans);
+ * NdbOperation* takeOverScanOp(NdbTransaction* updateTrans);
*
- * Parameters: The update transactions NdbConnection pointer.
+ * Parameters: The update transactions NdbTransaction pointer.
* Return Value: A reference to the transferred operation object
* or NULL if no success.
* Remark: Take over the scanning transactions NdbOperation
@@ -912,8 +893,8 @@ NdbScanOperation::doSendScan(int aProcessorId)
*
* FUTURE IMPLEMENTATION: (This note was moved from header file.)
* In the future, it will even be possible to transfer
- * to a NdbConnection on another Ndb-object.
- * In this case the receiving NdbConnection-object must call
+ * to a NdbTransaction on another Ndb-object.
+ * In this case the receiving NdbTransaction-object must call
* a method receiveOpFromScan to actually receive the information.
* This means that the updating transactions can be placed
* in separate threads and thus increasing the parallelism during
@@ -922,16 +903,9 @@ NdbScanOperation::doSendScan(int aProcessorId)
int
NdbScanOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size)
{
- Uint32 idx = m_current_api_receiver;
- Uint32 last = m_api_receivers_count;
-
- Uint32 row;
- NdbReceiver * tRec;
- NdbRecAttr * tRecAttr;
- if(idx < last && (tRec = m_api_receivers[idx])
- && ((row = tRec->m_current_row) <= tRec->m_defined_rows)
- && (tRecAttr = tRec->m_rows[row-1])){
-
+ NdbRecAttr * tRecAttr = m_curr_row;
+ if(tRecAttr)
+ {
const Uint32 * src = (Uint32*)tRecAttr->aRef();
memcpy(data, src, 4*size);
return 0;
@@ -940,18 +914,12 @@ NdbScanOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size)
}
NdbOperation*
-NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
+NdbScanOperation::takeOverScanOp(OperationType opType, NdbTransaction* pTrans)
+{
- Uint32 idx = m_current_api_receiver;
- Uint32 last = m_api_receivers_count;
-
- Uint32 row;
- NdbReceiver * tRec;
- NdbRecAttr * tRecAttr;
- if(idx < last && (tRec = m_api_receivers[idx])
- && ((row = tRec->m_current_row) <= tRec->m_defined_rows)
- && (tRecAttr = tRec->m_rows[row-1])){
-
+ NdbRecAttr * tRecAttr = m_curr_row;
+ if(tRecAttr)
+ {
NdbOperation * newOp = pTrans->getNdbOperation(m_currentTable);
if (newOp == NULL){
return NULL;
@@ -970,13 +938,15 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
const Uint32 * src = (Uint32*)tRecAttr->aRef();
const Uint32 tScanInfo = src[len] & 0x3FFFF;
- const Uint32 tTakeOverNode = src[len] >> 20;
+ const Uint32 tTakeOverFragment = src[len] >> 20;
{
UintR scanInfo = 0;
TcKeyReq::setTakeOverScanFlag(scanInfo, 1);
- TcKeyReq::setTakeOverScanNode(scanInfo, tTakeOverNode);
+ TcKeyReq::setTakeOverScanFragment(scanInfo, tTakeOverFragment);
TcKeyReq::setTakeOverScanInfo(scanInfo, tScanInfo);
newOp->theScanInfo = scanInfo;
+ newOp->theDistrKeyIndicator_ = 1;
+ newOp->theDistributionKey = tTakeOverFragment;
}
// Copy the first 8 words of key info from KEYINF20 into TCKEYREQ
@@ -988,7 +958,7 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
if(i < len){
NdbApiSignal* tSignal = theNdb->getSignal();
- newOp->theFirstKEYINFO = tSignal;
+ newOp->theTCREQ->next(tSignal);
Uint32 left = len - i;
while(tSignal && left > KeyInfo::DataLength){
@@ -1123,37 +1093,28 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
Uint32 currLen = theTotalNrOfKeyWordInSignal;
Uint32 remaining = KeyInfo::DataLength - currLen;
Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ bool tDistrKey = tAttrInfo->m_distributionKey;
- // normalize char bound
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- Uint32 xfrmData[2000];
- if (cs != NULL && aValue != NULL) {
- // current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply <= 1);
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)xfrmData, sizeof(xfrmData),
- (const uchar*)aValue, sizeInBytes);
- while (n < sizeInBytes)
- ((uchar*)xfrmData)[n++] = 0x20;
- aValue = (char*)xfrmData;
- }
+ len = aValue != NULL ? sizeInBytes : 0;
if (len != sizeInBytes && (len != 0)) {
setErrorCodeAbort(4209);
return -1;
}
+
// insert attribute header
- len = aValue != NULL ? sizeInBytes : 0;
Uint32 tIndexAttrId = tAttrInfo->m_attrId;
Uint32 sizeInWords = (len + 3) / 4;
AttributeHeader ah(tIndexAttrId, sizeInWords);
const Uint32 ahValue = ah.m_value;
- const bool aligned = (UintPtr(aValue) & 3) == 0;
+ const Uint32 align = (UintPtr(aValue) & 7);
+ const bool aligned = (tDistrKey && type == BoundEQ) ?
+ (align == 0) : (align & 3) == 0;
+
const bool nobytes = (len & 0x3) == 0;
const Uint32 totalLen = 2 + sizeInWords;
Uint32 tupKeyLen = theTupKeyLen;
- if(remaining > totalLen && aligned && nobytes){
+ if(remaining > totalLen && aligned && nobytes){
Uint32 * dst = theKEYINFOptr + currLen;
* dst ++ = type;
* dst ++ = ahValue;
@@ -1161,12 +1122,12 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
theTotalNrOfKeyWordInSignal = currLen + totalLen;
} else {
if(!aligned || !nobytes){
- Uint32 tempData[2002];
+ Uint32 tempData[2000];
tempData[0] = type;
tempData[1] = ahValue;
+ tempData[2 + (len >> 2)] = 0;
memcpy(tempData+2, aValue, len);
- while ((len & 0x3) != 0)
- ((char*)&tempData[2])[len++] = 0;
+
insertBOUNDS(tempData, 2+sizeInWords);
} else {
Uint32 buf[2] = { type, ahValue };
@@ -1185,11 +1146,11 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
* so it's safe to use [tIndexAttrId]
* (instead of looping as is NdbOperation::equal_impl)
*/
- if(type == BoundEQ && !theTupleKeyDefined[tIndexAttrId][0]){
- theNoOfTupKeyDefined++;
- theTupleKeyDefined[tIndexAttrId][0] = SETBOUND_EQ;
+ if(type == BoundEQ && tDistrKey)
+ {
+ theNoOfTupKeyLeft--;
+ return handle_distribution_key((Uint64*)aValue, sizeInWords);
}
-
return 0;
} else {
setErrorCodeAbort(4228); // XXX wrong code
@@ -1237,14 +1198,31 @@ error:
return -1;
}
-NdbResultSet*
+int
NdbIndexScanOperation::readTuples(LockMode lm,
- Uint32 batch,
- Uint32 parallel,
- bool order_by){
- NdbResultSet * rs = NdbScanOperation::readTuples(lm, batch, 0);
- if(rs && order_by){
- m_ordered = 1;
+ Uint32 scan_flags,
+ Uint32 parallel)
+{
+ const bool order_by = scan_flags & SF_OrderBy;
+ const bool order_desc = scan_flags & SF_Descending;
+ const bool read_range_no = scan_flags & SF_ReadRangeNo;
+
+ int res = NdbScanOperation::readTuples(lm, scan_flags, 0);
+ if(!res && read_range_no)
+ {
+ m_read_range_no = 1;
+ Uint32 word = 0;
+ AttributeHeader::init(&word, AttributeHeader::RANGE_NO, 0);
+ if(insertATTRINFO(word) == -1)
+ res = -1;
+ }
+ if(!res && order_by){
+ m_ordered = true;
+ if (order_desc) {
+ m_descending = true;
+ ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
+ ScanTabReq::setDescendingFlag(req->requestInfo, true);
+ }
Uint32 cnt = m_accessTable->getNoOfColumns() - 1;
m_sort_columns = cnt; // -1 for NDB$NODE
m_current_api_receiver = m_sent_receivers_count;
@@ -1263,7 +1241,10 @@ NdbIndexScanOperation::readTuples(LockMode lm,
#endif
}
}
- return rs;
+ m_this_bound_start = 0;
+ m_first_bound_word = theKEYINFOptr;
+
+ return res;
}
void
@@ -1305,22 +1286,23 @@ NdbIndexScanOperation::compare(Uint32 skip, Uint32 cols,
r1 = (skip ? r1->next() : r1);
r2 = (skip ? r2->next() : r2);
-
+ const int jdir = 1 - 2 * (int)m_descending;
+ assert(jdir == 1 || jdir == -1);
while(cols > 0){
Uint32 * d1 = (Uint32*)r1->aRef();
Uint32 * d2 = (Uint32*)r2->aRef();
unsigned r1_null = r1->isNULL();
if((r1_null ^ (unsigned)r2->isNULL())){
- return (r1_null ? -1 : 1);
+ return (r1_null ? -1 : 1) * jdir;
}
const NdbColumnImpl & col = NdbColumnImpl::getImpl(* r1->m_column);
- Uint32 size = (r1->theAttrSize * r1->theArraySize + 3) / 4;
+ Uint32 len = r1->theAttrSize * r1->theArraySize;
if(!r1_null){
- const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getType(col.m_extType);
- int r = (*sqlType.m_cmp)(col.m_cs, d1, d2, size, size);
+ const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getType(col.m_type);
+ int r = (*sqlType.m_cmp)(col.m_cs, d1, len, d2, len, true);
if(r){
assert(r != NdbSqlUtil::CmpUnknown);
- return r;
+ return r * jdir;
}
}
cols--;
@@ -1334,6 +1316,7 @@ int
NdbIndexScanOperation::next_result_ordered(bool fetchAllowed,
bool forceSend){
+ m_curr_row = 0;
Uint32 u_idx = 0, u_last = 0;
Uint32 s_idx = m_current_api_receiver; // first sorted
Uint32 s_last = theParallelism; // last sorted
@@ -1407,7 +1390,7 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed,
s_idx, s_last);
- Uint32 cols = m_sort_columns;
+ Uint32 cols = m_sort_columns + m_read_range_no;
Uint32 skip = m_keyInfo;
while(u_idx < u_last){
u_last--;
@@ -1444,7 +1427,7 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed,
tRec = m_api_receivers[s_idx];
if(s_idx < s_last && tRec->nextResult()){
- tRec->copyout(theReceiver);
+ m_curr_row = tRec->copyout(theReceiver);
if(DEBUG_NEXT_RESULT) ndbout_c("return 0");
return 0;
}
@@ -1663,10 +1646,14 @@ NdbIndexScanOperation::reset_bounds(bool forceSend){
theError.code = 0;
reset_receivers(theParallelism, m_ordered);
- theLastKEYINFO = theFirstKEYINFO;
- theKEYINFOptr = ((KeyInfo*)theFirstKEYINFO->getDataPtrSend())->keyData;
+ theLastKEYINFO = theSCAN_TABREQ->next();
+ theKEYINFOptr = ((KeyInfo*)theLastKEYINFO->getDataPtrSend())->keyData;
theTupKeyLen = 0;
theTotalNrOfKeyWordInSignal = 0;
+ theNoOfTupKeyLeft = m_accessTable->m_noOfDistributionKeys;
+ theDistrKeyIndicator_ = 0;
+ m_this_bound_start = 0;
+ m_first_bound_word = theKEYINFOptr;
m_transConnection
->remove_list((NdbOperation*&)m_transConnection->m_firstExecutedScanOp,
this);
@@ -1675,3 +1662,33 @@ NdbIndexScanOperation::reset_bounds(bool forceSend){
}
return res;
}
+
+int
+NdbIndexScanOperation::end_of_bound(Uint32 no)
+{
+ if(no < (1 << 13)) // Only 12-bits no of ranges
+ {
+ Uint32 bound_head = * m_first_bound_word;
+ bound_head |= (theTupKeyLen - m_this_bound_start) << 16 | (no << 4);
+ * m_first_bound_word = bound_head;
+
+ m_first_bound_word = theKEYINFOptr + theTotalNrOfKeyWordInSignal;;
+ m_this_bound_start = theTupKeyLen;
+ return 0;
+ }
+ return -1;
+}
+
+int
+NdbIndexScanOperation::get_range_no()
+{
+ NdbRecAttr* tRecAttr = m_curr_row;
+ if(m_read_range_no && tRecAttr)
+ {
+ if(m_keyInfo)
+ tRecAttr = tRecAttr->next();
+ Uint32 ret = *(Uint32*)tRecAttr->aRef();
+ return ret;
+ }
+ return -1;
+}
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbTransaction.cpp
index c9e26f8ccaf..294012d780c 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbTransaction.cpp
@@ -16,7 +16,7 @@
#include <ndb_global.h>
#include <NdbOut.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include <NdbScanOperation.hpp>
#include <NdbIndexScanOperation.hpp>
@@ -25,7 +25,6 @@
#include "TransporterFacade.hpp"
#include "API.hpp"
#include "NdbBlob.hpp"
-#include <ndb_limits.h>
#include <signaldata/TcKeyConf.hpp>
#include <signaldata/TcIndx.hpp>
@@ -34,13 +33,13 @@
#include <signaldata/TcHbRep.hpp>
/*****************************************************************************
-NdbConnection( Ndb* aNdb );
+NdbTransaction( Ndb* aNdb );
Return Value: None
Parameters: aNdb: Pointers to the Ndb object
Remark: Creates a connection object.
*****************************************************************************/
-NdbConnection::NdbConnection( Ndb* aNdb ) :
+NdbTransaction::NdbTransaction( Ndb* aNdb ) :
theSendStatus(NotInit),
theCallbackFunction(NULL),
theCallbackObject(NULL),
@@ -89,19 +88,19 @@ NdbConnection::NdbConnection( Ndb* aNdb ) :
CHECK_SZ(m_db_nodes, NdbNodeBitmask::Size);
CHECK_SZ(m_failed_db_nodes, NdbNodeBitmask::Size);
-}//NdbConnection::NdbConnection()
+}//NdbTransaction::NdbTransaction()
/*****************************************************************************
-~NdbConnection();
+~NdbTransaction();
Remark: Deletes the connection object.
*****************************************************************************/
-NdbConnection::~NdbConnection()
+NdbTransaction::~NdbTransaction()
{
- DBUG_ENTER("NdbConnection::~NdbConnection");
+ DBUG_ENTER("NdbTransaction::~NdbTransaction");
theNdb->theImpl->theNdbObjectIdMap.unmap(theId, this);
DBUG_VOID_RETURN;
-}//NdbConnection::~NdbConnection()
+}//NdbTransaction::~NdbTransaction()
/*****************************************************************************
void init();
@@ -109,7 +108,7 @@ void init();
Remark: Initialise connection object for new transaction.
*****************************************************************************/
void
-NdbConnection::init()
+NdbTransaction::init()
{
theListState = NotInList;
theInUseState = true;
@@ -149,7 +148,7 @@ NdbConnection::init()
//
theBlobFlag = false;
thePendingBlobOps = 0;
-}//NdbConnection::init()
+}//NdbTransaction::init()
/*****************************************************************************
setOperationErrorCode(int error);
@@ -158,9 +157,9 @@ Remark: Sets an error code on the connection object from an
operation object.
*****************************************************************************/
void
-NdbConnection::setOperationErrorCode(int error)
+NdbTransaction::setOperationErrorCode(int error)
{
- DBUG_ENTER("NdbConnection::setOperationErrorCode");
+ DBUG_ENTER("NdbTransaction::setOperationErrorCode");
setErrorCode(error);
DBUG_VOID_RETURN;
}
@@ -172,9 +171,9 @@ Remark: Sets an error code on the connection object from an
operation object.
*****************************************************************************/
void
-NdbConnection::setOperationErrorCodeAbort(int error, int abortOption)
+NdbTransaction::setOperationErrorCodeAbort(int error, int abortOption)
{
- DBUG_ENTER("NdbConnection::setOperationErrorCodeAbort");
+ DBUG_ENTER("NdbTransaction::setOperationErrorCodeAbort");
if (abortOption == -1)
abortOption = m_abortOption;
if (theTransactionIsStarted == false) {
@@ -194,20 +193,20 @@ setErrorCode(int anErrorCode);
Remark: Sets an error indication on the connection object.
*****************************************************************************/
void
-NdbConnection::setErrorCode(int error)
+NdbTransaction::setErrorCode(int error)
{
- DBUG_ENTER("NdbConnection::setErrorCode");
+ DBUG_ENTER("NdbTransaction::setErrorCode");
DBUG_PRINT("enter", ("error: %d, theError.code: %d", error, theError.code));
if (theError.code == 0)
theError.code = error;
DBUG_VOID_RETURN;
-}//NdbConnection::setErrorCode()
+}//NdbTransaction::setErrorCode()
int
-NdbConnection::restart(){
- DBUG_ENTER("NdbConnection::restart");
+NdbTransaction::restart(){
+ DBUG_ENTER("NdbTransaction::restart");
if(theCompletionStatus == CompletedSuccess){
releaseCompletedOperations();
Uint64 tTransid = theNdb->theFirstTransId;
@@ -232,23 +231,8 @@ void handleExecuteCompletion(void);
Remark: Handle time-out on a transaction object.
*****************************************************************************/
void
-NdbConnection::handleExecuteCompletion()
+NdbTransaction::handleExecuteCompletion()
{
-
- if (theCompletionStatus == CompletedFailure) {
- NdbOperation* tOpTemp = theFirstExecOpInList;
- while (tOpTemp != NULL) {
-/*****************************************************************************
- * Ensure that all executing operations report failed for each
- * read attribute when failure occurs.
- * We do not want any operations to report both failure and
- * success on different read attributes.
- ****************************************************************************/
- tOpTemp->handleFailedAI_ElemLen();
- tOpTemp = tOpTemp->next();
- }//while
- theReturnStatus = ReturnFailure;
- }//if
/***************************************************************************
* Move the NdbOperation objects from the list of executing
* operations to list of completed
@@ -265,7 +249,7 @@ NdbConnection::handleExecuteCompletion()
}//if
theSendStatus = InitState;
return;
-}//NdbConnection::handleExecuteCompletion()
+}//NdbTransaction::handleExecuteCompletion()
/*****************************************************************************
int execute(ExecType aTypeOfExec, CommitType aTypeOfCommit, int forceSend);
@@ -276,12 +260,12 @@ Parameters : aTypeOfExec: Type of execute.
Remark: Initialise connection object for new transaction.
*****************************************************************************/
int
-NdbConnection::execute(ExecType aTypeOfExec,
+NdbTransaction::execute(ExecType aTypeOfExec,
AbortOption abortOption,
int forceSend)
{
NdbError savedError= theError;
- DBUG_ENTER("NdbConnection::execute");
+ DBUG_ENTER("NdbTransaction::execute");
DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d",
aTypeOfExec, abortOption));
@@ -432,11 +416,11 @@ NdbConnection::execute(ExecType aTypeOfExec,
}
int
-NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
+NdbTransaction::executeNoBlobs(ExecType aTypeOfExec,
AbortOption abortOption,
int forceSend)
{
- DBUG_ENTER("NdbConnection::executeNoBlobs");
+ DBUG_ENTER("NdbTransaction::executeNoBlobs");
DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d",
aTypeOfExec, abortOption));
@@ -445,7 +429,7 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
// since last execute or since beginning. If this works ok we will continue
// by calling the poll with wait method. This method will return when
// the NDB kernel has completed its task or when 10 seconds have passed.
-// The NdbConnectionCallBack-method will receive the return code of the
+// The NdbTransactionCallBack-method will receive the return code of the
// transaction. The normal methods of reading error codes still apply.
//------------------------------------------------------------------------
Ndb* tNdb = theNdb;
@@ -493,7 +477,7 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
}
thePendingBlobOps = 0;
DBUG_RETURN(0);
-}//NdbConnection::execute()
+}//NdbTransaction::execute()
/*****************************************************************************
void executeAsynchPrepare(ExecType aTypeOfExec,
@@ -511,12 +495,12 @@ Parameters : aTypeOfExec: Type of execute.
Remark: Prepare a part of a transaction in an asynchronous manner.
*****************************************************************************/
void
-NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
+NdbTransaction::executeAsynchPrepare( ExecType aTypeOfExec,
NdbAsynchCallback aCallback,
void* anyObject,
AbortOption abortOption)
{
- DBUG_ENTER("NdbConnection::executeAsynchPrepare");
+ DBUG_ENTER("NdbTransaction::executeAsynchPrepare");
DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: %x, anyObject: %x",
aTypeOfExec, aCallback, anyObject));
@@ -679,14 +663,14 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
NdbNodeBitmask::clear(m_db_nodes);
NdbNodeBitmask::clear(m_failed_db_nodes);
DBUG_VOID_RETURN;
-}//NdbConnection::executeAsynchPrepare()
+}//NdbTransaction::executeAsynchPrepare()
-void NdbConnection::close()
+void NdbTransaction::close()
{
theNdb->closeTransaction(this);
}
-int NdbConnection::refresh(){
+int NdbTransaction::refresh(){
return sendTC_HBREP();
}
@@ -698,7 +682,7 @@ Parameters : None.
Remark: Order NDB to refresh the timeout counter of the transaction.
******************************************************************************/
int
-NdbConnection::sendTC_HBREP() // Send a TC_HBREP signal;
+NdbTransaction::sendTC_HBREP() // Send a TC_HBREP signal;
{
NdbApiSignal* tSignal;
Ndb* tNdb = theNdb;
@@ -733,7 +717,7 @@ NdbConnection::sendTC_HBREP() // Send a TC_HBREP signal;
}
return 0;
-}//NdbConnection::sendTC_HBREP()
+}//NdbTransaction::sendTC_HBREP()
/*****************************************************************************
int doSend();
@@ -745,9 +729,9 @@ Remark: Send all operations belonging to this connection.
object from the prepared transactions array on the Ndb-object.
*****************************************************************************/
int
-NdbConnection::doSend()
+NdbTransaction::doSend()
{
- DBUG_ENTER("NdbConnection::doSend");
+ DBUG_ENTER("NdbTransaction::doSend");
/*
This method assumes that at least one operation have been defined. This
@@ -806,7 +790,7 @@ NdbConnection::doSend()
theTransactionIsStarted = false;
theCommitStatus = Aborted;
DBUG_RETURN(-1);
-}//NdbConnection::doSend()
+}//NdbTransaction::doSend()
/**************************************************************************
int sendROLLBACK();
@@ -816,7 +800,7 @@ Parameters : None.
Remark: Order NDB to rollback the transaction.
**************************************************************************/
int
-NdbConnection::sendROLLBACK() // Send a TCROLLBACKREQ signal;
+NdbTransaction::sendROLLBACK() // Send a TCROLLBACKREQ signal;
{
Ndb* tNdb = theNdb;
if ((theTransactionIsStarted == true) &&
@@ -860,7 +844,7 @@ NdbConnection::sendROLLBACK() // Send a TCROLLBACKREQ signal;
return 0;
;
}//if
-}//NdbConnection::sendROLLBACK()
+}//NdbTransaction::sendROLLBACK()
/***************************************************************************
int sendCOMMIT();
@@ -871,7 +855,7 @@ Parameters : None.
Remark: Order NDB to commit the transaction.
***************************************************************************/
int
-NdbConnection::sendCOMMIT() // Send a TC_COMMITREQ signal;
+NdbTransaction::sendCOMMIT() // Send a TC_COMMITREQ signal;
{
NdbApiSignal tSignal(theNdb->theMyRef);
Uint32 tTransId1, tTransId2;
@@ -893,7 +877,7 @@ NdbConnection::sendCOMMIT() // Send a TC_COMMITREQ signal;
} else {
return -1;
}//if
-}//NdbConnection::sendCOMMIT()
+}//NdbTransaction::sendCOMMIT()
/******************************************************************************
void release();
@@ -901,7 +885,7 @@ void release();
Remark: Release all operations.
******************************************************************************/
void
-NdbConnection::release(){
+NdbTransaction::release(){
releaseOperations();
if ( (theTransactionIsStarted == true) &&
((theCommitStatus != Committed) &&
@@ -920,10 +904,10 @@ NdbConnection::release(){
abort();
}
#endif
-}//NdbConnection::release()
+}//NdbTransaction::release()
void
-NdbConnection::releaseOps(NdbOperation* tOp){
+NdbTransaction::releaseOps(NdbOperation* tOp){
while (tOp != NULL) {
NdbOperation* tmp = tOp;
tOp->release();
@@ -938,7 +922,7 @@ void releaseOperations();
Remark: Release all operations.
******************************************************************************/
void
-NdbConnection::releaseOperations()
+NdbTransaction::releaseOperations()
{
// Release any open scans
releaseScanOperations(m_theFirstScanOperation);
@@ -958,15 +942,15 @@ NdbConnection::releaseOperations()
m_theFirstScanOperation = NULL;
m_theLastScanOperation = NULL;
m_firstExecutedScanOp = NULL;
-}//NdbConnection::releaseOperations()
+}//NdbTransaction::releaseOperations()
void
-NdbConnection::releaseCompletedOperations()
+NdbTransaction::releaseCompletedOperations()
{
releaseOps(theCompletedFirstOp);
theCompletedFirstOp = NULL;
theCompletedLastOp = NULL;
-}//NdbConnection::releaseOperations()
+}//NdbTransaction::releaseOperations()
/******************************************************************************
void releaseScanOperations();
@@ -975,7 +959,7 @@ Remark: Release all cursor operations.
(NdbScanOperation and NdbIndexOperation)
******************************************************************************/
void
-NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp)
+NdbTransaction::releaseScanOperations(NdbIndexScanOperation* cursorOp)
{
while(cursorOp != 0){
NdbIndexScanOperation* next = (NdbIndexScanOperation*)cursorOp->next();
@@ -983,7 +967,7 @@ NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp)
theNdb->releaseScanOperation(cursorOp);
cursorOp = next;
}
-}//NdbConnection::releaseScanOperations()
+}//NdbTransaction::releaseScanOperations()
/*****************************************************************************
void releaseExecutedScanOperation();
@@ -991,9 +975,9 @@ void releaseExecutedScanOperation();
Remark: Release scan op when hupp'ed trans closed (save memory)
******************************************************************************/
void
-NdbConnection::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
+NdbTransaction::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
{
- DBUG_ENTER("NdbConnection::releaseExecutedScanOperation");
+ DBUG_ENTER("NdbTransaction::releaseExecutedScanOperation");
DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp))
// here is one reason to make op lists doubly linked
@@ -1014,7 +998,7 @@ NdbConnection::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
}
}
DBUG_VOID_RETURN;
-}//NdbConnection::releaseExecutedScanOperation()
+}//NdbTransaction::releaseExecutedScanOperation()
/*****************************************************************************
NdbOperation* getNdbOperation(const char* aTableName);
@@ -1024,13 +1008,13 @@ Return Value Return a pointer to a NdbOperation object if getNdbOperation
Return NULL : In all other case.
Parameters: aTableName : Name of the database table.
Remark: Get an operation from NdbOperation idlelist and get the
- NdbConnection object
+ NdbTransaction object
who was fetch by startTransaction pointing to this operation
getOperation will set the theTableId in the NdbOperation object.
synchronous
******************************************************************************/
NdbOperation*
-NdbConnection::getNdbOperation(const char* aTableName)
+NdbTransaction::getNdbOperation(const char* aTableName)
{
if (theCommitStatus == Started){
NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
@@ -1045,7 +1029,7 @@ NdbConnection::getNdbOperation(const char* aTableName)
setOperationErrorCodeAbort(4114);
return NULL;
-}//NdbConnection::getNdbOperation()
+}//NdbTransaction::getNdbOperation()
/*****************************************************************************
NdbOperation* getNdbOperation(int aTableId);
@@ -1055,13 +1039,13 @@ Return Value Return a pointer to a NdbOperation object if getNdbOperation
Return NULL: In all other case.
Parameters: tableId : Id of the database table beeing deleted.
Remark: Get an operation from NdbOperation object idlelist and
- get the NdbConnection object who was fetch by
+ get the NdbTransaction object who was fetch by
startTransaction pointing to this operation
getOperation will set the theTableId in the NdbOperation
object, synchronous.
*****************************************************************************/
NdbOperation*
-NdbConnection::getNdbOperation(const NdbTableImpl * tab, NdbOperation* aNextOp)
+NdbTransaction::getNdbOperation(const NdbTableImpl * tab, NdbOperation* aNextOp)
{
NdbOperation* tOp;
@@ -1105,15 +1089,15 @@ NdbConnection::getNdbOperation(const NdbTableImpl * tab, NdbOperation* aNextOp)
getNdbOp_error1:
setOperationErrorCodeAbort(4000);
return NULL;
-}//NdbConnection::getNdbOperation()
+}//NdbTransaction::getNdbOperation()
-NdbOperation* NdbConnection::getNdbOperation(const NdbDictionary::Table * table)
+NdbOperation* NdbTransaction::getNdbOperation(const NdbDictionary::Table * table)
{
if (table)
return getNdbOperation(& NdbTableImpl::getImpl(*table));
else
return NULL;
-}//NdbConnection::getNdbOperation()
+}//NdbTransaction::getNdbOperation()
// NdbScanOperation
/*****************************************************************************
@@ -1122,12 +1106,12 @@ NdbScanOperation* getNdbScanOperation(const char* aTableName);
Return Value Return a pointer to a NdbScanOperation object if getNdbScanOperation was succesful.
Return NULL : In all other case.
Parameters: aTableName : Name of the database table.
-Remark: Get an operation from NdbScanOperation idlelist and get the NdbConnection object
+Remark: Get an operation from NdbScanOperation idlelist and get the NdbTransaction object
who was fetch by startTransaction pointing to this operation
getOperation will set the theTableId in the NdbOperation object.synchronous
******************************************************************************/
NdbScanOperation*
-NdbConnection::getNdbScanOperation(const char* aTableName)
+NdbTransaction::getNdbScanOperation(const char* aTableName)
{
if (theCommitStatus == Started){
NdbTableImpl* tab = theNdb->theDictionary->getTable(aTableName);
@@ -1141,78 +1125,104 @@ NdbConnection::getNdbScanOperation(const char* aTableName)
setOperationErrorCodeAbort(4114);
return NULL;
-}//NdbConnection::getNdbScanOperation()
+}//NdbTransaction::getNdbScanOperation()
/*****************************************************************************
-NdbScanOperation* getNdbScanOperation(const char* anIndexName, const char* aTableName);
+NdbScanOperation* getNdbIndexScanOperation(const char* anIndexName, const char* aTableName);
-Return Value Return a pointer to a NdbScanOperation object if getNdbScanOperation was succesful.
+Return Value Return a pointer to a NdbIndexScanOperation object if getNdbIndexScanOperation was succesful.
Return NULL : In all other case.
Parameters: anIndexName : Name of the index to use.
aTableName : Name of the database table.
-Remark: Get an operation from NdbScanOperation idlelist and get the NdbConnection object
+Remark: Get an operation from NdbIndexScanOperation idlelist and get the NdbTransaction object
who was fetch by startTransaction pointing to this operation
- getOperation will set the theTableId in the NdbOperation object.synchronous
+ getOperation will set the theTableId in the NdbIndexScanOperation object.synchronous
******************************************************************************/
NdbIndexScanOperation*
-NdbConnection::getNdbIndexScanOperation(const char* anIndexName,
+NdbTransaction::getNdbIndexScanOperation(const char* anIndexName,
const char* aTableName)
{
NdbIndexImpl* index =
theNdb->theDictionary->getIndex(anIndexName, aTableName);
+ if (index == 0)
+ {
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return 0;
+ }
NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
+ if (table == 0)
+ {
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return 0;
+ }
return getNdbIndexScanOperation(index, table);
}
NdbIndexScanOperation*
-NdbConnection::getNdbIndexScanOperation(const NdbIndexImpl* index,
+NdbTransaction::getNdbIndexScanOperation(const NdbIndexImpl* index,
const NdbTableImpl* table)
{
if (theCommitStatus == Started){
const NdbTableImpl * indexTable = index->getIndexTable();
if (indexTable != 0){
- NdbIndexScanOperation* tOp =
- getNdbScanOperation((NdbTableImpl *) indexTable);
+ NdbIndexScanOperation* tOp = getNdbScanOperation(indexTable);
if(tOp)
{
tOp->m_currentTable = table;
- tOp->m_cursor_type = NdbScanOperation::IndexCursor;
}
return tOp;
} else {
- setOperationErrorCodeAbort(theNdb->theError.code);
+ setOperationErrorCodeAbort(4271);
return NULL;
}//if
}
setOperationErrorCodeAbort(4114);
return NULL;
-}//NdbConnection::getNdbIndexScanOperation()
+}//NdbTransaction::getNdbIndexScanOperation()
NdbIndexScanOperation*
-NdbConnection::getNdbIndexScanOperation(const NdbDictionary::Index * index,
+NdbTransaction::getNdbIndexScanOperation(const NdbDictionary::Index * index)
+{
+ if (index)
+ {
+ const NdbDictionary::Table *table=
+ theNdb->theDictionary->getTable(index->getTable());
+
+ if (table)
+ return getNdbIndexScanOperation(index, table);
+
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return NULL;
+ }
+ setOperationErrorCodeAbort(4271);
+ return NULL;
+}
+
+NdbIndexScanOperation*
+NdbTransaction::getNdbIndexScanOperation(const NdbDictionary::Index * index,
const NdbDictionary::Table * table)
{
if (index && table)
return getNdbIndexScanOperation(& NdbIndexImpl::getImpl(*index),
& NdbTableImpl::getImpl(*table));
- else
- return NULL;
-}//NdbConnection::getNdbIndexScanOperation()
+ setOperationErrorCodeAbort(4271);
+ return NULL;
+}//NdbTransaction::getNdbIndexScanOperation()
/*****************************************************************************
NdbScanOperation* getNdbScanOperation(int aTableId);
-Return Value Return a pointer to a NdbOperation object if getNdbOperation was succesful.
+Return Value Return a pointer to a NdbScanOperation object if getNdbScanOperation was succesful.
Return NULL: In all other case.
Parameters: tableId : Id of the database table beeing deleted.
-Remark: Get an operation from NdbScanOperation object idlelist and get the NdbConnection
+Remark: Get an operation from NdbScanOperation object idlelist and get the NdbTransaction
object who was fetch by startTransaction pointing to this operation
- getOperation will set the theTableId in the NdbOperation object, synchronous.
+ getOperation will set the theTableId in the NdbScanOperation object, synchronous.
*****************************************************************************/
NdbIndexScanOperation*
-NdbConnection::getNdbScanOperation(const NdbTableImpl * tab)
+NdbTransaction::getNdbScanOperation(const NdbTableImpl * tab)
{
NdbIndexScanOperation* tOp;
@@ -1231,10 +1241,10 @@ NdbConnection::getNdbScanOperation(const NdbTableImpl * tab)
getNdbOp_error1:
setOperationErrorCodeAbort(4000);
return NULL;
-}//NdbConnection::getNdbScanOperation()
+}//NdbTransaction::getNdbScanOperation()
void
-NdbConnection::remove_list(NdbOperation*& list, NdbOperation* op){
+NdbTransaction::remove_list(NdbOperation*& list, NdbOperation* op){
NdbOperation* tmp= list;
if(tmp == op)
list = op->next();
@@ -1247,7 +1257,7 @@ NdbConnection::remove_list(NdbOperation*& list, NdbOperation* op){
}
void
-NdbConnection::define_scan_op(NdbIndexScanOperation * tOp){
+NdbTransaction::define_scan_op(NdbIndexScanOperation * tOp){
// Link scan operation into list of cursor operations
if (m_theLastScanOperation == NULL)
m_theFirstScanOperation = m_theLastScanOperation = tOp;
@@ -1259,13 +1269,13 @@ NdbConnection::define_scan_op(NdbIndexScanOperation * tOp){
}
NdbScanOperation*
-NdbConnection::getNdbScanOperation(const NdbDictionary::Table * table)
+NdbTransaction::getNdbScanOperation(const NdbDictionary::Table * table)
{
if (table)
return getNdbScanOperation(& NdbTableImpl::getImpl(*table));
else
return NULL;
-}//NdbConnection::getNdbScanOperation()
+}//NdbTransaction::getNdbScanOperation()
// IndexOperation
@@ -1273,21 +1283,39 @@ NdbConnection::getNdbScanOperation(const NdbDictionary::Table * table)
NdbIndexOperation* getNdbIndexOperation(const char* anIndexName,
const char* aTableName);
-Return Value Return a pointer to a NdbOperation object if getNdbScanOperation was succesful.
+Return Value Return a pointer to a NdbOperation object if getNdbIndexOperation was succesful.
Return NULL : In all other case.
Parameters: aTableName : Name of the database table.
-Remark: Get an operation from NdbScanOperation idlelist and get the NdbConnection object
- who was fetch by startTransaction pointing to this operation
- getOperation will set the theTableId in the NdbScanOperation object.synchronous
+Remark: Get an operation from NdbIndexOperation idlelist and get the NdbTransaction object
+ who was fetch by startTransaction pointing to this operation
+ getOperation will set the theTableId in the NdbIndexOperation object.synchronous
******************************************************************************/
NdbIndexOperation*
-NdbConnection::getNdbIndexOperation(const char* anIndexName,
+NdbTransaction::getNdbIndexOperation(const char* anIndexName,
const char* aTableName)
{
if (theCommitStatus == Started) {
NdbTableImpl * table = theNdb->theDictionary->getTable(aTableName);
- NdbIndexImpl * index = theNdb->theDictionary->getIndex(anIndexName,
- aTableName);
+ NdbIndexImpl * index;
+
+ if (table == 0)
+ {
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return NULL;
+ }
+
+ if (table->m_frm.get_data())
+ {
+ // This unique index is defined from SQL level
+ static const char* uniqueSuffix= "$unique";
+ BaseString uniqueIndexName(anIndexName);
+ uniqueIndexName.append(uniqueSuffix);
+ index = theNdb->theDictionary->getIndex(uniqueIndexName.c_str(),
+ aTableName);
+ }
+ else
+ index = theNdb->theDictionary->getIndex(anIndexName,
+ aTableName);
if(table != 0 && index != 0){
return getNdbIndexOperation(index, table);
}
@@ -1297,14 +1325,13 @@ NdbConnection::getNdbIndexOperation(const char* anIndexName,
return NULL;
}
- // table == 0
- setOperationErrorCodeAbort(theNdb->theError.code);
+ setOperationErrorCodeAbort(4243);
return NULL;
}
setOperationErrorCodeAbort(4114);
return 0;
-}//NdbConnection::getNdbIndexOperation()
+}//NdbTransaction::getNdbIndexOperation()
/*****************************************************************************
NdbIndexOperation* getNdbIndexOperation(int anIndexId, int aTableId);
@@ -1312,12 +1339,12 @@ NdbIndexOperation* getNdbIndexOperation(int anIndexId, int aTableId);
Return Value Return a pointer to a NdbIndexOperation object if getNdbIndexOperation was succesful.
Return NULL: In all other case.
Parameters: tableId : Id of the database table beeing deleted.
-Remark: Get an operation from NdbIndexOperation object idlelist and get the NdbConnection
+Remark: Get an operation from NdbIndexOperation object idlelist and get the NdbTransaction
object who was fetch by startTransaction pointing to this operation
getOperation will set the theTableId in the NdbIndexOperation object, synchronous.
*****************************************************************************/
NdbIndexOperation*
-NdbConnection::getNdbIndexOperation(const NdbIndexImpl * anIndex,
+NdbTransaction::getNdbIndexOperation(const NdbIndexImpl * anIndex,
const NdbTableImpl * aTable,
NdbOperation* aNextOp)
{
@@ -1358,18 +1385,37 @@ NdbConnection::getNdbIndexOperation(const NdbIndexImpl * anIndex,
getNdbOp_error1:
setOperationErrorCodeAbort(4000);
return NULL;
-}//NdbConnection::getNdbIndexOperation()
+}//NdbTransaction::getNdbIndexOperation()
NdbIndexOperation*
-NdbConnection::getNdbIndexOperation(const NdbDictionary::Index * index,
+NdbTransaction::getNdbIndexOperation(const NdbDictionary::Index * index)
+{
+ if (index)
+ {
+ const NdbDictionary::Table *table=
+ theNdb->theDictionary->getTable(index->getTable());
+
+ if (table)
+ return getNdbIndexOperation(index, table);
+
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return NULL;
+ }
+ setOperationErrorCodeAbort(4271);
+ return NULL;
+}
+
+NdbIndexOperation*
+NdbTransaction::getNdbIndexOperation(const NdbDictionary::Index * index,
const NdbDictionary::Table * table)
{
if (index && table)
return getNdbIndexOperation(& NdbIndexImpl::getImpl(*index),
& NdbTableImpl::getImpl(*table));
- else
- return NULL;
-}//NdbConnection::getNdbIndexOperation()
+
+ setOperationErrorCodeAbort(4271);
+ return NULL;
+}//NdbTransaction::getNdbIndexOperation()
/*******************************************************************************
@@ -1381,7 +1427,7 @@ Parameters: aSignal: The signal object pointer.
Remark: Sets theRestartGCI in the NDB object.
*******************************************************************************/
int
-NdbConnection::receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
+NdbTransaction::receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
{
if (theStatus != Connecting) {
return -1;
@@ -1390,7 +1436,7 @@ NdbConnection::receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
theStatus = Connected;
}//if
return 0;
-}//NdbConnection::receiveDIHNDBTAMPER()
+}//NdbTransaction::receiveDIHNDBTAMPER()
/*******************************************************************************
int receiveTCSEIZECONF(NdbApiSignal* aSignal);
@@ -1401,7 +1447,7 @@ Parameters: aSignal: The signal object pointer.
Remark: Sets TC Connect pointer at reception of TCSEIZECONF.
*******************************************************************************/
int
-NdbConnection::receiveTCSEIZECONF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCSEIZECONF(NdbApiSignal* aSignal)
{
if (theStatus != Connecting)
{
@@ -1412,7 +1458,7 @@ NdbConnection::receiveTCSEIZECONF(NdbApiSignal* aSignal)
theStatus = Connected;
}
return 0;
-}//NdbConnection::receiveTCSEIZECONF()
+}//NdbTransaction::receiveTCSEIZECONF()
/*******************************************************************************
int receiveTCSEIZEREF(NdbApiSignal* aSignal);
@@ -1423,18 +1469,22 @@ Parameters: aSignal: The signal object pointer.
Remark: Sets TC Connect pointer.
*******************************************************************************/
int
-NdbConnection::receiveTCSEIZEREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCSEIZEREF(NdbApiSignal* aSignal)
{
+ DBUG_ENTER("NdbTransaction::receiveTCSEIZEREF");
if (theStatus != Connecting)
{
- return -1;
+ DBUG_RETURN(-1);
} else
{
theStatus = ConnectFailure;
theNdb->theError.code = aSignal->readData(2);
- return 0;
+ DBUG_PRINT("info",("error code %d, %s",
+ theNdb->getNdbError().code,
+ theNdb->getNdbError().message));
+ DBUG_RETURN(0);
}
-}//NdbConnection::receiveTCSEIZEREF()
+}//NdbTransaction::receiveTCSEIZEREF()
/*******************************************************************************
int receiveTCRELEASECONF(NdbApiSignal* aSignal);
@@ -1445,7 +1495,7 @@ Parameters: aSignal: The signal object pointer.
Remark: DisConnect TC Connect pointer to NDBAPI.
*******************************************************************************/
int
-NdbConnection::receiveTCRELEASECONF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCRELEASECONF(NdbApiSignal* aSignal)
{
if (theStatus != DisConnecting)
{
@@ -1455,7 +1505,7 @@ NdbConnection::receiveTCRELEASECONF(NdbApiSignal* aSignal)
theStatus = NotConnected;
}
return 0;
-}//NdbConnection::receiveTCRELEASECONF()
+}//NdbTransaction::receiveTCRELEASECONF()
/*******************************************************************************
int receiveTCRELEASEREF(NdbApiSignal* aSignal);
@@ -1466,7 +1516,7 @@ Parameters: aSignal: The signal object pointer.
Remark: DisConnect TC Connect pointer to NDBAPI Failure.
*******************************************************************************/
int
-NdbConnection::receiveTCRELEASEREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCRELEASEREF(NdbApiSignal* aSignal)
{
if (theStatus != DisConnecting) {
return -1;
@@ -1475,7 +1525,7 @@ NdbConnection::receiveTCRELEASEREF(NdbApiSignal* aSignal)
theNdb->theError.code = aSignal->readData(2);
return 0;
}//if
-}//NdbConnection::receiveTCRELEASEREF()
+}//NdbTransaction::receiveTCRELEASEREF()
/******************************************************************************
int receiveTC_COMMITCONF(NdbApiSignal* aSignal);
@@ -1486,11 +1536,12 @@ Parameters: aSignal: The signal object pointer.
Remark:
******************************************************************************/
int
-NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf)
+NdbTransaction::receiveTC_COMMITCONF(const TcCommitConf * commitConf)
{
if(checkState_TransId(&commitConf->transId1)){
theCommitStatus = Committed;
theCompletionStatus = CompletedSuccess;
+ theGlobalCheckpointId = commitConf->gci;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1498,7 +1549,7 @@ NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf)
#endif
}
return -1;
-}//NdbConnection::receiveTC_COMMITCONF()
+}//NdbTransaction::receiveTC_COMMITCONF()
/******************************************************************************
int receiveTC_COMMITREF(NdbApiSignal* aSignal);
@@ -1509,13 +1560,14 @@ Parameters: aSignal: The signal object pointer.
Remark:
******************************************************************************/
int
-NdbConnection::receiveTC_COMMITREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTC_COMMITREF(NdbApiSignal* aSignal)
{
const TcCommitRef * ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr());
if(checkState_TransId(&ref->transId1)){
setOperationErrorCodeAbort(ref->errorCode);
theCommitStatus = Aborted;
theCompletionStatus = CompletedFailure;
+ theReturnStatus = ReturnFailure;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1524,7 +1576,7 @@ NdbConnection::receiveTC_COMMITREF(NdbApiSignal* aSignal)
}
return -1;
-}//NdbConnection::receiveTC_COMMITREF()
+}//NdbTransaction::receiveTC_COMMITREF()
/******************************************************************************
int receiveTCROLLBACKCONF(NdbApiSignal* aSignal);
@@ -1535,7 +1587,7 @@ Parameters: aSignal: The signal object pointer.
Remark:
******************************************************************************/
int
-NdbConnection::receiveTCROLLBACKCONF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCROLLBACKCONF(NdbApiSignal* aSignal)
{
if(checkState_TransId(aSignal->getDataPtr() + 1)){
theCommitStatus = Aborted;
@@ -1548,7 +1600,7 @@ NdbConnection::receiveTCROLLBACKCONF(NdbApiSignal* aSignal)
}
return -1;
-}//NdbConnection::receiveTCROLLBACKCONF()
+}//NdbTransaction::receiveTCROLLBACKCONF()
/*******************************************************************************
int receiveTCROLLBACKREF(NdbApiSignal* aSignal);
@@ -1559,12 +1611,13 @@ Parameters: aSignal: The signal object pointer.
Remark:
*******************************************************************************/
int
-NdbConnection::receiveTCROLLBACKREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCROLLBACKREF(NdbApiSignal* aSignal)
{
if(checkState_TransId(aSignal->getDataPtr() + 1)){
setOperationErrorCodeAbort(aSignal->readData(4));
theCommitStatus = Aborted;
theCompletionStatus = CompletedFailure;
+ theReturnStatus = ReturnFailure;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1573,7 +1626,7 @@ NdbConnection::receiveTCROLLBACKREF(NdbApiSignal* aSignal)
}
return -1;
-}//NdbConnection::receiveTCROLLBACKREF()
+}//NdbTransaction::receiveTCROLLBACKREF()
/*****************************************************************************
int receiveTCROLLBACKREP( NdbApiSignal* aSignal)
@@ -1585,7 +1638,7 @@ Parameters: aSignal: the signal object that contains the
Remark: Handles the reception of the ROLLBACKREP signal.
*****************************************************************************/
int
-NdbConnection::receiveTCROLLBACKREP( NdbApiSignal* aSignal)
+NdbTransaction::receiveTCROLLBACKREP( NdbApiSignal* aSignal)
{
/****************************************************************************
Check that we are expecting signals from this transaction and that it doesn't
@@ -1604,6 +1657,7 @@ transactions.
/**********************************************************************/
theCompletionStatus = CompletedFailure;
theCommitStatus = Aborted;
+ theReturnStatus = ReturnFailure;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1612,7 +1666,7 @@ transactions.
}
return -1;
-}//NdbConnection::receiveTCROLLBACKREP()
+}//NdbTransaction::receiveTCROLLBACKREP()
/*******************************************************************************
int receiveTCKEYCONF(NdbApiSignal* aSignal, Uint32 long_short_ind);
@@ -1623,7 +1677,7 @@ Parameters: aSignal: The signal object pointer.
Remark:
*******************************************************************************/
int
-NdbConnection::receiveTCKEYCONF(const TcKeyConf * keyConf, Uint32 aDataLength)
+NdbTransaction::receiveTCKEYCONF(const TcKeyConf * keyConf, Uint32 aDataLength)
{
NdbReceiver* tOp;
const Uint32 tTemp = keyConf->confInfo;
@@ -1652,6 +1706,7 @@ from other transactions.
done = 1;
tOp->setErrorCode(4119);
theCompletionStatus = CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
}
}
tNoComp += done;
@@ -1681,6 +1736,7 @@ from other transactions.
/**********************************************************************/
theError.code = 4011;
theCompletionStatus = CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
theCommitStatus = Aborted;
return 0;
}//if
@@ -1695,7 +1751,7 @@ from other transactions.
}
return -1;
-}//NdbConnection::receiveTCKEYCONF()
+}//NdbTransaction::receiveTCKEYCONF()
/*****************************************************************************
int receiveTCKEY_FAILCONF( NdbApiSignal* aSignal)
@@ -1707,7 +1763,7 @@ Parameters: aSignal: the signal object that contains the
Remark: Handles the reception of the TCKEY_FAILCONF signal.
*****************************************************************************/
int
-NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
+NdbTransaction::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
{
NdbOperation* tOp;
/*
@@ -1740,6 +1796,7 @@ NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
case NdbOperation::OpenScanRequest:
case NdbOperation::OpenRangeScanRequest:
theCompletionStatus = CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
setOperationErrorCodeAbort(4115);
tOp = NULL;
break;
@@ -1757,7 +1814,7 @@ NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
#endif
}
return -1;
-}//NdbConnection::receiveTCKEY_FAILCONF()
+}//NdbTransaction::receiveTCKEY_FAILCONF()
/*************************************************************************
int receiveTCKEY_FAILREF( NdbApiSignal* aSignal)
@@ -1769,7 +1826,7 @@ Parameters: aSignal: the signal object that contains the
Remark: Handles the reception of the TCKEY_FAILREF signal.
**************************************************************************/
int
-NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
{
/*
Check that we are expecting signals from this transaction and
@@ -1781,18 +1838,19 @@ NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
We received an indication of that this transaction was aborted due to a
node failure.
*/
- if (theSendStatus == NdbConnection::sendTC_ROLLBACK) {
+ if (theSendStatus == NdbTransaction::sendTC_ROLLBACK) {
/*
We were in the process of sending a rollback anyways. We will
report it as a success.
*/
- theCompletionStatus = NdbConnection::CompletedSuccess;
+ theCompletionStatus = NdbTransaction::CompletedSuccess;
} else {
- theCompletionStatus = NdbConnection::CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
theError.code = 4031;
}//if
theReleaseOnClose = true;
- theCommitStatus = NdbConnection::Aborted;
+ theCommitStatus = NdbTransaction::Aborted;
return 0;
} else {
#ifdef VM_TRACE
@@ -1800,7 +1858,7 @@ NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
#endif
}
return -1;
-}//NdbConnection::receiveTCKEY_FAILREF()
+}//NdbTransaction::receiveTCKEY_FAILREF()
/******************************************************************************
int receiveTCINDXCONF(NdbApiSignal* aSignal, Uint32 long_short_ind);
@@ -1811,7 +1869,7 @@ Parameters: aSignal: The signal object pointer.
Remark:
******************************************************************************/
int
-NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf,
+NdbTransaction::receiveTCINDXCONF(const TcIndxConf * indxConf,
Uint32 aDataLength)
{
if(checkState_TransId(&indxConf->transId1)){
@@ -1845,8 +1903,9 @@ NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf,
// no Commit flag set. This is clearly an anomaly.
/**********************************************************************/
theError.code = 4011;
- theCompletionStatus = NdbConnection::CompletedFailure;
- theCommitStatus = NdbConnection::Aborted;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
+ theCommitStatus = NdbTransaction::Aborted;
+ theReturnStatus = NdbTransaction::ReturnFailure;
return 0;
}//if
if (tNoComp >= tNoSent) {
@@ -1860,7 +1919,7 @@ NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf,
}
return -1;
-}//NdbConnection::receiveTCINDXCONF()
+}//NdbTransaction::receiveTCINDXCONF()
/*****************************************************************************
int receiveTCINDXREF( NdbApiSignal* aSignal)
@@ -1872,7 +1931,7 @@ Parameters: aSignal: the signal object that contains the
Remark: Handles the reception of the TCINDXREF signal.
*****************************************************************************/
int
-NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal)
+NdbTransaction::receiveTCINDXREF( NdbApiSignal* aSignal)
{
if(checkState_TransId(aSignal->getDataPtr()+1)){
theError.code = aSignal->readData(4); // Override any previous errors
@@ -1884,8 +1943,9 @@ NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal)
/* and we only need to report completion and return with the */
/* error code to the application. */
/**********************************************************************/
- theCompletionStatus = NdbConnection::CompletedFailure;
- theCommitStatus = NdbConnection::Aborted;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
+ theCommitStatus = NdbTransaction::Aborted;
+ theReturnStatus = NdbTransaction::ReturnFailure;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1894,7 +1954,7 @@ NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal)
}
return -1;
-}//NdbConnection::receiveTCINDXREF()
+}//NdbTransaction::receiveTCINDXREF()
/*******************************************************************************
int OpCompletedFailure();
@@ -1905,12 +1965,12 @@ Parameters: aErrorCode: The error code.
Remark: An operation was completed with failure.
*******************************************************************************/
int
-NdbConnection::OpCompleteFailure(Uint8 abortOption, bool setFailure)
+NdbTransaction::OpCompleteFailure(Uint8 abortOption, bool setFailure)
{
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
if (setFailure)
- theCompletionStatus = NdbConnection::CompletedFailure;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
tNoComp++;
theNoOfOpCompleted = tNoComp;
if (tNoComp == tNoSent) {
@@ -1935,7 +1995,7 @@ NdbConnection::OpCompleteFailure(Uint8 abortOption, bool setFailure)
} else {
return -1; // Continue waiting for more signals
}//if
-}//NdbConnection::OpCompleteFailure()
+}//NdbTransaction::OpCompleteFailure()
/******************************************************************************
int OpCompleteSuccess();
@@ -1945,7 +2005,7 @@ Return Value: Return 0 : OpCompleteSuccess was successful.
Remark: An operation was completed with success.
*******************************************************************************/
int
-NdbConnection::OpCompleteSuccess()
+NdbTransaction::OpCompleteSuccess()
{
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
@@ -1958,10 +2018,11 @@ NdbConnection::OpCompleteSuccess()
} else {
setOperationErrorCodeAbort(4113); // Too many operations,
// stop waiting for more
- theCompletionStatus = NdbConnection::CompletedFailure;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
return 0;
}//if
-}//NdbConnection::OpCompleteSuccess()
+}//NdbTransaction::OpCompleteSuccess()
/******************************************************************************
int getGCI();
@@ -1969,13 +2030,13 @@ NdbConnection::OpCompleteSuccess()
Remark: Get global checkpoint identity of the transaction
*******************************************************************************/
int
-NdbConnection::getGCI()
+NdbTransaction::getGCI()
{
- if (theCommitStatus == NdbConnection::Committed) {
+ if (theCommitStatus == NdbTransaction::Committed) {
return theGlobalCheckpointId;
}//if
return 0;
-}//NdbConnection::getGCI()
+}//NdbTransaction::getGCI()
/*******************************************************************************
Uint64 getTransactionId(void);
@@ -1983,31 +2044,31 @@ Uint64 getTransactionId(void);
Remark: Get the transaction identity.
*******************************************************************************/
Uint64
-NdbConnection::getTransactionId()
+NdbTransaction::getTransactionId()
{
return theTransactionId;
-}//NdbConnection::getTransactionId()
+}//NdbTransaction::getTransactionId()
-NdbConnection::CommitStatusType
-NdbConnection::commitStatus()
+NdbTransaction::CommitStatusType
+NdbTransaction::commitStatus()
{
return theCommitStatus;
-}//NdbConnection::commitStatus()
+}//NdbTransaction::commitStatus()
int
-NdbConnection::getNdbErrorLine()
+NdbTransaction::getNdbErrorLine()
{
return theErrorLine;
}
NdbOperation*
-NdbConnection::getNdbErrorOperation()
+NdbTransaction::getNdbErrorOperation()
{
return theErrorOperation;
-}//NdbConnection::getNdbErrorOperation()
+}//NdbTransaction::getNdbErrorOperation()
const NdbOperation *
-NdbConnection::getNextCompletedOperation(const NdbOperation * current) const {
+NdbTransaction::getNextCompletedOperation(const NdbOperation * current) const {
if(current == 0)
return theCompletedFirstOp;
return current->theNext;
@@ -2016,7 +2077,7 @@ NdbConnection::getNextCompletedOperation(const NdbOperation * current) const {
#ifdef VM_TRACE
#define CASE(x) case x: ndbout << " " << #x; break
void
-NdbConnection::printState()
+NdbTransaction::printState()
{
ndbout << "con=" << hex << this << dec;
ndbout << " node=" << getConnectedNodeId();
@@ -2069,7 +2130,7 @@ NdbConnection::printState()
#endif
int
-NdbConnection::report_node_failure(Uint32 id){
+NdbTransaction::report_node_failure(Uint32 id){
NdbNodeBitmask::set(m_failed_db_nodes, id);
if(!NdbNodeBitmask::get(m_db_nodes, id))
{
@@ -2088,22 +2149,28 @@ NdbConnection::report_node_failure(Uint32 id){
const Uint32 len = TcKeyConf::SimpleReadBit | id;
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
+ Uint32 count = 0;
while(tmp != 0)
{
if(tmp->theReceiver.m_expected_result_length == len &&
tmp->theReceiver.m_received_result_length == 0)
{
- tNoComp++;
+ count++;
tmp->theError.code = 4119;
}
tmp = tmp->next();
}
+ tNoComp += count;
theNoOfOpCompleted = tNoComp;
- if(tNoComp == tNoSent)
+ if(count)
{
- theError.code = 4119;
- theCompletionStatus = NdbConnection::CompletedFailure;
- return 1;
+ theReturnStatus = NdbTransaction::ReturnFailure;
+ if(tNoComp == tNoSent)
+ {
+ theError.code = 4119;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
+ return 1;
+ }
}
return 0;
}
diff --git a/ndb/src/ndbapi/NdbConnectionScan.cpp b/ndb/src/ndbapi/NdbTransactionScan.cpp
index b0c546c512a..4c507f6ab8c 100644
--- a/ndb/src/ndbapi/NdbConnectionScan.cpp
+++ b/ndb/src/ndbapi/NdbTransactionScan.cpp
@@ -15,22 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbConnectionScan.cpp
- * Include:
- * Link:
- * Author: UABRONM MikaelRonström UAB/M/MT
- * QABJKAM Jonas Kamf UAB/M/MT
- * Date: 2000-06-12
- * Version: 0.1
- * Description: Interface between Application and NDB
- * Documentation:
- * Adjust: 2000-06-12 UABRONM First version.
- ****************************************************************************/
#include <ndb_global.h>
#include <Ndb.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include <NdbScanOperation.hpp>
#include "NdbApiSignal.hpp"
@@ -52,7 +40,7 @@
*
****************************************************************************/
int
-NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){
+NdbTransaction::receiveSCAN_TABREF(NdbApiSignal* aSignal){
const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr());
if(checkState_TransId(&ref->transId1)){
@@ -93,7 +81,7 @@ NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){
*
*****************************************************************************/
int
-NdbConnection::receiveSCAN_TABCONF(NdbApiSignal* aSignal,
+NdbTransaction::receiveSCAN_TABCONF(NdbApiSignal* aSignal,
const Uint32 * ops, Uint32 len)
{
const ScanTabConf * conf = CAST_CONSTPTR(ScanTabConf, aSignal->getDataPtr());
diff --git a/ndb/src/ndbapi/Ndberr.cpp b/ndb/src/ndbapi/Ndberr.cpp
index a8b968da03f..b05818de6f1 100644
--- a/ndb/src/ndbapi/Ndberr.cpp
+++ b/ndb/src/ndbapi/Ndberr.cpp
@@ -19,9 +19,9 @@
#include "NdbImpl.hpp"
#include "NdbDictionaryImpl.hpp"
#include <NdbOperation.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbBlob.hpp>
-
+#include "NdbEventOperationImpl.hpp"
static void
update(const NdbError & _err){
@@ -55,7 +55,7 @@ NdbDictionaryImpl::getNdbError() const {
const
NdbError &
-NdbConnection::getNdbError() const {
+NdbTransaction::getNdbError() const {
update(theError);
return theError;
}
@@ -73,3 +73,10 @@ NdbBlob::getNdbError() const {
update(theError);
return theError;
}
+
+const
+NdbError &
+NdbEventOperationImpl::getNdbError() const {
+ update(m_error);
+ return m_error;
+}
diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp
index 1caebe436ef..fee6f0930ad 100644
--- a/ndb/src/ndbapi/Ndbif.cpp
+++ b/ndb/src/ndbapi/Ndbif.cpp
@@ -19,12 +19,12 @@
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
-#include "NdbOperation.hpp"
-#include "NdbIndexOperation.hpp"
-#include "NdbScanOperation.hpp"
-#include "NdbConnection.hpp"
-#include "NdbRecAttr.hpp"
-#include "NdbReceiver.hpp"
+#include <NdbTransaction.hpp>
+#include <NdbOperation.hpp>
+#include <NdbIndexOperation.hpp>
+#include <NdbScanOperation.hpp>
+#include <NdbRecAttr.hpp>
+#include <NdbReceiver.hpp>
#include "API.hpp"
#include <signaldata/TcCommit.hpp>
@@ -107,15 +107,13 @@ Ndb::init(int aMaxNoOfTransactions)
goto error_handler;
}
- tMaxNoOfTransactions = aMaxNoOfTransactions * 3;
- if (tMaxNoOfTransactions > 1024) {
- tMaxNoOfTransactions = 1024;
- }//if
+
+ tMaxNoOfTransactions = aMaxNoOfTransactions;
theMaxNoOfTransactions = tMaxNoOfTransactions;
-
- thePreparedTransactionsArray = new NdbConnection* [tMaxNoOfTransactions];
- theSentTransactionsArray = new NdbConnection* [tMaxNoOfTransactions];
- theCompletedTransactionsArray = new NdbConnection* [tMaxNoOfTransactions];
+ theRemainingStartTransactions= tMaxNoOfTransactions;
+ thePreparedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
+ theSentTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
+ theCompletedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
if ((thePreparedTransactionsArray == NULL) ||
(theSentTransactionsArray == NULL) ||
@@ -272,11 +270,11 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
{
Uint32 tNoSentTransactions = theNoOfSentTransactions;
for (int i = tNoSentTransactions - 1; i >= 0; i--) {
- NdbConnection* localCon = theSentTransactionsArray[i];
+ NdbTransaction* localCon = theSentTransactionsArray[i];
if (localCon->getConnectedNodeId() == aNodeId) {
- const NdbConnection::SendStatusType sendStatus = localCon->theSendStatus;
- if (sendStatus == NdbConnection::sendTC_OP ||
- sendStatus == NdbConnection::sendTC_COMMIT) {
+ const NdbTransaction::SendStatusType sendStatus = localCon->theSendStatus;
+ if (sendStatus == NdbTransaction::sendTC_OP ||
+ sendStatus == NdbTransaction::sendTC_COMMIT) {
/*
A transaction was interrupted in the prepare phase by a node
failure. Since the transaction was not found in the phase
@@ -284,13 +282,13 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
we report a normal node failure abort.
*/
localCon->setOperationErrorCodeAbort(4010);
- localCon->theCompletionStatus = NdbConnection::CompletedFailure;
- } else if (sendStatus == NdbConnection::sendTC_ROLLBACK) {
+ localCon->theCompletionStatus = NdbTransaction::CompletedFailure;
+ } else if (sendStatus == NdbTransaction::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 = NdbConnection::CompletedSuccess;
+ localCon->theCompletionStatus = NdbTransaction::CompletedSuccess;
} else {
#ifdef VM_TRACE
printState("abortTransactionsAfterNodeFailure %x", this);
@@ -302,7 +300,8 @@ 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 = NdbConnection::Aborted;
+ localCon->theReturnStatus = NdbTransaction::ReturnFailure;
+ localCon->theCommitStatus = NdbTransaction::Aborted;
localCon->theReleaseOnClose = true;
completedTransaction(localCon);
}
@@ -325,7 +324,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
{
NdbOperation* tOp;
NdbIndexOperation* tIndexOp;
- NdbConnection* tCon;
+ NdbTransaction* tCon;
int tReturnCode = -1;
const Uint32* tDataPtr = aSignal->getDataPtr();
const Uint32 tWaitState = theImpl->theWaiter.m_state;
@@ -355,14 +354,14 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_OP)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_OP)) {
tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen);
if (tReturnCode != -1) {
completedTransaction(tCon);
}//if
if(TcKeyConf::getMarkerFlag(keyConf->confInfo)){
- NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
+ NdbTransaction::sendTC_COMMIT_ACK(theCommitAckSignal,
keyConf->transId1,
keyConf->transId2,
aTCRef);
@@ -387,24 +386,24 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
com = tRec->execTRANSID_AI(tDataPtr + TransIdAI::HeaderLength,
tLen - TransIdAI::HeaderLength);
}
+
+ if(com == 0)
+ return;
- if(com == 1){
- switch(tRec->getType()){
- case NdbReceiver::NDB_OPERATION:
- case NdbReceiver::NDB_INDEX_OPERATION:
- if(tCon->OpCompleteSuccess() != -1){
- completedTransaction(tCon);
- return;
- }
- break;
- case NdbReceiver::NDB_SCANRECEIVER:
- tCon->theScanningOp->receiver_delivered(tRec);
- theImpl->theWaiter.m_state = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
- (Uint32) NO_WAIT : tWaitState);
- break;
- default:
- goto InvalidSignal;
+ switch(tRec->getType()){
+ case NdbReceiver::NDB_OPERATION:
+ case NdbReceiver::NDB_INDEX_OPERATION:
+ if(tCon->OpCompleteSuccess() != -1){
+ completedTransaction(tCon);
}
+ return;
+ case NdbReceiver::NDB_SCANRECEIVER:
+ tCon->theScanningOp->receiver_delivered(tRec);
+ theImpl->theWaiter.m_state = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
+ (Uint32) NO_WAIT : tWaitState);
+ break;
+ default:
+ goto InvalidSignal;
}
break;
} else {
@@ -426,8 +425,8 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber(false) == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
- (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
+ if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
+ (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -441,7 +440,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
#endif
}
if(tFirstData & 1){
- NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
+ NdbTransaction::sendTC_COMMIT_ACK(theCommitAckSignal,
failConf->transId1,
failConf->transId2,
aTCRef);
@@ -456,8 +455,8 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber(false) == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
- (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
+ if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
+ (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -482,7 +481,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber() == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
+ if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
tReturnCode = tOp->receiveTCKEYREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -505,14 +504,14 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTC_COMMITCONF(commitConf);
if (tReturnCode != -1) {
completedTransaction(tCon);
}//if
if(tFirstData & 1){
- NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
+ NdbTransaction::sendTC_COMMIT_ACK(theCommitAckSignal,
commitConf->transId1,
commitConf->transId2,
aTCRef);
@@ -530,7 +529,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTC_COMMITREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -545,7 +544,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCROLLBACKCONF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -560,7 +559,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCROLLBACKREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -797,7 +796,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
const BlockReference aTCRef = aSignal->theSendersBlockRef;
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_OP)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_OP)) {
tReturnCode = tCon->receiveTCINDXCONF(indxConf, tLen);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -805,7 +804,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
}//if
if(TcIndxConf::getMarkerFlag(indxConf->confInfo)){
- NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
+ NdbTransaction::sendTC_COMMIT_ACK(theCommitAckSignal,
indxConf->transId1,
indxConf->transId2,
aTCRef);
@@ -820,7 +819,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tIndexOp->checkMagicNumber() == 0) {
tCon = tIndexOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
+ if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
tReturnCode = tIndexOp->receiveTCINDXREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -861,7 +860,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
/*****************************************************************************
-void completedTransaction(NdbConnection* aCon);
+void completedTransaction(NdbTransaction* aCon);
Remark: One transaction has been completed.
Remove it from send array and put it into the completed
@@ -869,14 +868,14 @@ Remark: One transaction has been completed.
up a poller.
******************************************************************************/
void
-Ndb::completedTransaction(NdbConnection* aCon)
+Ndb::completedTransaction(NdbTransaction* aCon)
{
Uint32 tTransArrayIndex = aCon->theTransArrayIndex;
Uint32 tNoSentTransactions = theNoOfSentTransactions;
Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions;
- if ((tNoSentTransactions > 0) && (aCon->theListState == NdbConnection::InSendList) &&
+ if ((tNoSentTransactions > 0) && (aCon->theListState == NdbTransaction::InSendList) &&
(tTransArrayIndex < tNoSentTransactions)) {
- NdbConnection* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1];
+ NdbTransaction* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1];
theCompletedTransactionsArray[tNoCompletedTransactions] = aCon;
aCon->theTransArrayIndex = tNoCompletedTransactions;
@@ -888,7 +887,7 @@ Ndb::completedTransaction(NdbConnection* aCon)
theNoOfCompletedTransactions = tNoCompletedTransactions + 1;
theNoOfSentTransactions = tNoSentTransactions - 1;
- aCon->theListState = NdbConnection::InCompletedList;
+ aCon->theListState = NdbTransaction::InCompletedList;
aCon->handleExecuteCompletion();
if ((theMinNoOfEventsToWakeUp != 0) &&
(theNoOfCompletedTransactions >= theMinNoOfEventsToWakeUp)) {
@@ -909,12 +908,12 @@ Ndb::completedTransaction(NdbConnection* aCon)
}//Ndb::completedTransaction()
/*****************************************************************************
-void reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans);
+void reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans);
Remark: Call the callback methods of the completed transactions.
******************************************************************************/
void
-Ndb::reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans)
+Ndb::reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans)
{
Uint32 i;
if (aNoOfCompletedTrans > 0) {
@@ -923,7 +922,7 @@ Ndb::reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans)
NdbAsynchCallback aCallback = aCopyArray[i]->theCallbackFunction;
int tResult = 0;
if (aCallback != NULL) {
- if (aCopyArray[i]->theReturnStatus == NdbConnection::ReturnFailure) {
+ if (aCopyArray[i]->theReturnStatus == NdbTransaction::ReturnFailure) {
tResult = -1;
}//if
(*aCallback)(tResult, aCopyArray[i], anyObject);
@@ -933,13 +932,13 @@ Ndb::reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans)
}//Ndb::reportCallback()
/*****************************************************************************
-Uint32 pollCompleted(NdbConnection** aCopyArray);
+Uint32 pollCompleted(NdbTransaction** aCopyArray);
Remark: Transfer the data from the completed transaction to a local array.
This support is used by a number of the poll-methods.
******************************************************************************/
Uint32
-Ndb::pollCompleted(NdbConnection** aCopyArray)
+Ndb::pollCompleted(NdbTransaction** aCopyArray)
{
check_send_timeout();
Uint32 i;
@@ -947,13 +946,13 @@ Ndb::pollCompleted(NdbConnection** aCopyArray)
if (tNoCompletedTransactions > 0) {
for (i = 0; i < tNoCompletedTransactions; i++) {
aCopyArray[i] = theCompletedTransactionsArray[i];
- if (aCopyArray[i]->theListState != NdbConnection::InCompletedList) {
+ if (aCopyArray[i]->theListState != NdbTransaction::InCompletedList) {
ndbout << "pollCompleted error ";
ndbout << (int) aCopyArray[i]->theListState << endl;
abort();
}//if
theCompletedTransactionsArray[i] = NULL;
- aCopyArray[i]->theListState = NdbConnection::NotInList;
+ aCopyArray[i]->theListState = NdbTransaction::NotInList;
}//for
}//if
theNoOfCompletedTransactions = 0;
@@ -968,7 +967,7 @@ Ndb::check_send_timeout()
the_last_check_time = current_time;
Uint32 no_of_sent = theNoOfSentTransactions;
for (Uint32 i = 0; i < no_of_sent; i++) {
- NdbConnection* a_con = theSentTransactionsArray[i];
+ NdbTransaction* a_con = theSentTransactionsArray[i];
if ((current_time - a_con->theStartTransTime) >
WAITFOR_RESPONSE_TIMEOUT) {
#ifdef VM_TRACE
@@ -979,8 +978,8 @@ Ndb::check_send_timeout()
abort();
#endif
a_con->setOperationErrorCodeAbort(4012);
- a_con->theCommitStatus = NdbConnection::Aborted;
- a_con->theCompletionStatus = NdbConnection::CompletedFailure;
+ a_con->theCommitStatus = NdbTransaction::Aborted;
+ a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
a_con->handleExecuteCompletion();
remove_sent_list(i);
insert_completed_list(a_con);
@@ -996,7 +995,7 @@ Ndb::remove_sent_list(Uint32 list_index)
{
Uint32 last_index = theNoOfSentTransactions - 1;
if (list_index < last_index) {
- NdbConnection* t_con = theSentTransactionsArray[last_index];
+ NdbTransaction* t_con = theSentTransactionsArray[last_index];
theSentTransactionsArray[list_index] = t_con;
}//if
theNoOfSentTransactions = last_index;
@@ -1004,23 +1003,23 @@ Ndb::remove_sent_list(Uint32 list_index)
}
Uint32
-Ndb::insert_completed_list(NdbConnection* a_con)
+Ndb::insert_completed_list(NdbTransaction* a_con)
{
Uint32 no_of_comp = theNoOfCompletedTransactions;
theCompletedTransactionsArray[no_of_comp] = a_con;
theNoOfCompletedTransactions = no_of_comp + 1;
- a_con->theListState = NdbConnection::InCompletedList;
+ a_con->theListState = NdbTransaction::InCompletedList;
a_con->theTransArrayIndex = no_of_comp;
return no_of_comp;
}
Uint32
-Ndb::insert_sent_list(NdbConnection* a_con)
+Ndb::insert_sent_list(NdbTransaction* a_con)
{
Uint32 no_of_sent = theNoOfSentTransactions;
theSentTransactionsArray[no_of_sent] = a_con;
theNoOfSentTransactions = no_of_sent + 1;
- a_con->theListState = NdbConnection::InSendList;
+ a_con->theListState = NdbTransaction::InSendList;
a_con->theTransArrayIndex = no_of_sent;
return no_of_sent;
}
@@ -1052,16 +1051,16 @@ Ndb::sendPrepTrans(int forceSend)
TransporterFacade* tp = TransporterFacade::instance();
Uint32 no_of_prep_trans = theNoOfPreparedTransactions;
for (i = 0; i < no_of_prep_trans; i++) {
- NdbConnection * a_con = thePreparedTransactionsArray[i];
+ NdbTransaction * a_con = thePreparedTransactionsArray[i];
thePreparedTransactionsArray[i] = NULL;
Uint32 node_id = a_con->getConnectedNodeId();
if ((tp->getNodeSequence(node_id) == a_con->theNodeSequence) &&
tp->get_node_alive(node_id) ||
(tp->get_node_stopping(node_id) &&
- ((a_con->theSendStatus == NdbConnection::sendABORT) ||
- (a_con->theSendStatus == NdbConnection::sendABORTfail) ||
- (a_con->theSendStatus == NdbConnection::sendCOMMITstate) ||
- (a_con->theSendStatus == NdbConnection::sendCompleted)))) {
+ ((a_con->theSendStatus == NdbTransaction::sendABORT) ||
+ (a_con->theSendStatus == NdbTransaction::sendABORTfail) ||
+ (a_con->theSendStatus == NdbTransaction::sendCOMMITstate) ||
+ (a_con->theSendStatus == NdbTransaction::sendCompleted)))) {
/*
We will send if
1) Node is alive and sequences are correct OR
@@ -1093,13 +1092,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 == NdbConnection::sendOperations) {
+ if (a_con->theSendStatus == NdbTransaction::sendOperations) {
a_con->setOperationErrorCodeAbort(4021);
- a_con->theCommitStatus = NdbConnection::NeedAbort;
+ a_con->theCommitStatus = NdbTransaction::NeedAbort;
TRACE_DEBUG("Send buffer full and sendOperations");
} else {
a_con->setOperationErrorCodeAbort(4026);
- a_con->theCommitStatus = NdbConnection::Aborted;
+ a_con->theCommitStatus = NdbTransaction::Aborted;
TRACE_DEBUG("Send buffer full, set state to Aborted");
}//if
}//if
@@ -1116,7 +1115,7 @@ Ndb::sendPrepTrans(int forceSend)
*/
TRACE_DEBUG("Abort a transaction when stopping a node");
a_con->setOperationErrorCodeAbort(4023);
- a_con->theCommitStatus = NdbConnection::NeedAbort;
+ a_con->theCommitStatus = NdbTransaction::NeedAbort;
} else {
/*
The node is hard dead and we cannot continue. We will also release
@@ -1126,10 +1125,11 @@ Ndb::sendPrepTrans(int forceSend)
a_con->setOperationErrorCodeAbort(4025);
a_con->theReleaseOnClose = true;
a_con->theTransactionIsStarted = false;
- a_con->theCommitStatus = NdbConnection::Aborted;
+ a_con->theCommitStatus = NdbTransaction::Aborted;
}//if
}//if
- a_con->theCompletionStatus = NdbConnection::CompletedFailure;
+ a_con->theReturnStatus = NdbTransaction::ReturnFailure;
+ a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
a_con->handleExecuteCompletion();
insert_completed_list(a_con);
}//for
@@ -1203,7 +1203,7 @@ Remark: First send all prepared operations and then check if there are any
int
Ndb::sendPollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup, int forceSend)
{
- NdbConnection* tConArray[1024];
+ NdbTransaction* tConArray[1024];
Uint32 tNoCompletedTransactions;
//theCurrentConnectCounter = 0;
@@ -1236,7 +1236,7 @@ Remark: Check if there are any transactions already completed. Wait for not
int
Ndb::pollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup)
{
- NdbConnection* tConArray[1024];
+ NdbTransaction* tConArray[1024];
Uint32 tNoCompletedTransactions;
//theCurrentConnectCounter = 0;
@@ -1343,7 +1343,7 @@ Ndb::sendRecSignal(Uint16 node_id,
}//Ndb::sendRecSignal()
void
-NdbConnection::sendTC_COMMIT_ACK(NdbApiSignal * aSignal,
+NdbTransaction::sendTC_COMMIT_ACK(NdbApiSignal * aSignal,
Uint32 transId1, Uint32 transId2,
Uint32 aTCRef){
#ifdef MARKER_TRACE
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index cbb344d3680..44b315e4947 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -19,12 +19,12 @@
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
-#include "NdbOperation.hpp"
-#include "NdbConnection.hpp"
-#include "NdbRecAttr.hpp"
-#include "IPCConfig.hpp"
+#include <NdbOperation.hpp>
+#include <NdbTransaction.hpp>
+#include <NdbRecAttr.hpp>
+#include <IPCConfig.hpp>
#include "TransporterFacade.hpp"
-#include "ConfigRetriever.hpp"
+#include <ConfigRetriever.hpp>
#include <ndb_limits.h>
#include <NdbOut.hpp>
#include <NdbSleep.h>
@@ -34,48 +34,12 @@ class NdbGlobalEventBufferHandle;
NdbGlobalEventBufferHandle *NdbGlobalEventBuffer_init(int);
void NdbGlobalEventBuffer_drop(NdbGlobalEventBufferHandle *);
-/**
- * Static object for NDB
- */
-
-// only needed for backwards compatability, before ndb_cluster_connection
-static char *ndbConnectString = 0;
-static int theNoOfNdbObjects = 0;
-static Ndb_cluster_connection *global_ndb_cluster_connection= 0;
-
-
-/***************************************************************************
-Ndb(const char* aDataBase);
-
-Parameters: aDataBase : Name of the database.
-Remark: Connect to the database.
-***************************************************************************/
-Ndb::Ndb( const char* aDataBase , const char* aSchema)
- : theImpl(NULL)
-{
- DBUG_ENTER("Ndb::Ndb()");
- DBUG_PRINT("enter",("(old)Ndb::Ndb this=0x%x", this));
- if (theNoOfNdbObjects < 0)
- abort(); // old and new Ndb constructor used mixed
- theNoOfNdbObjects++;
- if (global_ndb_cluster_connection == 0) {
- global_ndb_cluster_connection= new Ndb_cluster_connection(ndbConnectString);
- global_ndb_cluster_connection->connect(12,5,1);
- }
- setup(global_ndb_cluster_connection, aDataBase, aSchema);
- DBUG_VOID_RETURN;
-}
-
Ndb::Ndb( Ndb_cluster_connection *ndb_cluster_connection,
const char* aDataBase , const char* aSchema)
: theImpl(NULL)
{
DBUG_ENTER("Ndb::Ndb()");
DBUG_PRINT("enter",("Ndb::Ndb this=0x%x", this));
- if (global_ndb_cluster_connection != 0 &&
- global_ndb_cluster_connection != ndb_cluster_connection)
- abort(); // old and new Ndb constructor used mixed
- theNoOfNdbObjects= -1;
setup(ndb_cluster_connection, aDataBase, aSchema);
DBUG_VOID_RETURN;
}
@@ -95,10 +59,9 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
theNoOfPreparedTransactions= 0;
theNoOfSentTransactions= 0;
theNoOfCompletedTransactions= 0;
- theNoOfAllocatedTransactions= 0;
+ theRemainingStartTransactions= 0;
theMaxNoOfTransactions= 0;
theMinNoOfEventsToWakeUp= 0;
- prefixEnd= NULL;
theConIdleList= NULL;
theOpIdleList= NULL;
theScanOpIdleList= NULL;
@@ -145,17 +108,10 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
theFirstTupleId[i] = 0;
theLastTupleId[i] = 0;
}//for
-
- BaseString::snprintf(theDataBase, sizeof(theDataBase), "%s",
- aDataBase ? aDataBase : "");
- BaseString::snprintf(theDataBaseSchema, sizeof(theDataBaseSchema), "%s",
- aSchema ? aSchema : "");
- int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
- theDataBase, table_name_separator,
- theDataBaseSchema, table_name_separator);
- prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
- sizeof(prefixName) - 1);
+ theImpl->m_dbname.assign(aDataBase);
+ theImpl->m_schemaname.assign(aSchema);
+ theImpl->update_prefix();
theImpl->theWaiter.m_mutex = TransporterFacade::instance()->theMutexPtr;
@@ -177,16 +133,6 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
}
-void Ndb::setConnectString(const char * connectString)
-{
- if (ndbConnectString != 0) {
- free(ndbConnectString);
- ndbConnectString = 0;
- }
- if (connectString)
- ndbConnectString = strdup(connectString);
-}
-
/*****************************************************************************
* ~Ndb();
*
@@ -241,19 +187,6 @@ Ndb::~Ndb()
delete theImpl;
- /**
- * This needs to be put after delete theImpl
- * as TransporterFacade::instance is delete by global_ndb_cluster_connection
- * and used by theImpl
- */
- if (global_ndb_cluster_connection != 0) {
- theNoOfNdbObjects--;
- if(theNoOfNdbObjects == 0){
- delete global_ndb_cluster_connection;
- global_ndb_cluster_connection= 0;
- }
- }//if
-
/**
* This sleep is to make sure that the transporter
* send thread will come in and send any
diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp
index 5902aa413dc..96d0f4d7de5 100644
--- a/ndb/src/ndbapi/Ndblist.cpp
+++ b/ndb/src/ndbapi/Ndblist.cpp
@@ -19,7 +19,6 @@
#include <NdbOperation.hpp>
#include <NdbIndexOperation.hpp>
#include <NdbIndexScanOperation.hpp>
-#include <NdbConnection.hpp>
#include "NdbApiSignal.hpp"
#include <NdbRecAttr.hpp>
#include "NdbUtil.hpp"
@@ -51,10 +50,10 @@ Ndb::checkFailedNode()
/**
* Release all connections in idle list (for node)
*/
- NdbConnection * tNdbCon = theConnectionArray[node_id];
+ NdbTransaction * tNdbCon = theConnectionArray[node_id];
theConnectionArray[node_id] = NULL;
while (tNdbCon != NULL) {
- NdbConnection* tempNdbCon = tNdbCon;
+ NdbTransaction* tempNdbCon = tNdbCon;
tNdbCon = tNdbCon->next();
releaseNdbCon(tempNdbCon);
}
@@ -71,14 +70,14 @@ Ndb::checkFailedNode()
* if createConIdleList was succesful
* Return -1: In all other case.
* Parameters: aNrOfCon : Number of connections offered to the application.
- * Remark: Create connection idlelist with NdbConnection objects.
+ * Remark: Create connection idlelist with NdbTransaction objects.
***************************************************************************/
int
Ndb::createConIdleList(int aNrOfCon)
{
for (int i = 0; i < aNrOfCon; i++)
{
- NdbConnection* tNdbCon = new NdbConnection(this);
+ NdbTransaction* tNdbCon = new NdbTransaction(this);
if (tNdbCon == NULL)
{
return -1;
@@ -92,9 +91,8 @@ Ndb::createConIdleList(int aNrOfCon)
tNdbCon->next(theConIdleList);
theConIdleList = tNdbCon;
}
- tNdbCon->Status(NdbConnection::NotConnected);
+ tNdbCon->Status(NdbTransaction::NotConnected);
}
- theNoOfAllocatedTransactions = aNrOfCon;
return aNrOfCon;
}
@@ -183,25 +181,19 @@ Ndb::getNdbCall()
}
/***************************************************************************
- * NdbConnection* getNdbCon();
+ * NdbTransaction* getNdbCon();
*
* Return Value: Return a connection if the getNdbCon was successful.
* Return NULL : In all other case.
* Remark: Get a connection from theConIdleList and return the object .
***************************************************************************/
-NdbConnection*
+NdbTransaction*
Ndb::getNdbCon()
{
- NdbConnection* tNdbCon;
+ NdbTransaction* tNdbCon;
if ( theConIdleList == NULL ) {
- if (theNoOfAllocatedTransactions < theMaxNoOfTransactions) {
- tNdbCon = new NdbConnection(this);
- if (tNdbCon == NULL) {
- return NULL;
- }//if
- theNoOfAllocatedTransactions++;
- } else {
- ndbout << "theNoOfAllocatedTransactions = " << theNoOfAllocatedTransactions << " theMaxNoOfTransactions = " << theMaxNoOfTransactions << endl;
+ tNdbCon = new NdbTransaction(this);
+ if (tNdbCon == NULL) {
return NULL;
}//if
tNdbCon->next(NULL);
@@ -467,13 +459,13 @@ Ndb::releaseNdbCall(NdbCall* aNdbCall)
}
/***************************************************************************
-void releaseNdbCon(NdbConnection* aNdbCon);
+void releaseNdbCon(NdbTransaction* aNdbCon);
-Parameters: aNdbCon: The NdbConnection object.
+Parameters: aNdbCon: The NdbTransaction object.
Remark: Add a Connection object into the signal idlelist.
***************************************************************************/
void
-Ndb::releaseNdbCon(NdbConnection* aNdbCon)
+Ndb::releaseNdbCon(NdbTransaction* aNdbCon)
{
aNdbCon->next(theConIdleList);
aNdbCon->theMagicNumber = 0xFE11DD;
@@ -551,10 +543,21 @@ Remark: Add a NdbScanOperation object into the signal idlelist.
void
Ndb::releaseScanOperation(NdbIndexScanOperation* aScanOperation)
{
+ DBUG_ENTER("Ndb::releaseScanOperation");
+ DBUG_PRINT("enter", ("op=%x", (UintPtr)aScanOperation));
+#ifdef ndb_release_check_dup
+ { NdbIndexScanOperation* tOp = theScanOpIdleList;
+ while (tOp != NULL) {
+ assert(tOp != aScanOperation);
+ tOp = (NdbIndexScanOperation*)tOp->theNext;
+ }
+ }
+#endif
aScanOperation->next(theScanOpIdleList);
aScanOperation->theNdbCon = NULL;
aScanOperation->theMagicNumber = 0xFE11D2;
theScanOpIdleList = aScanOperation;
+ DBUG_VOID_RETURN;
}
/***************************************************************************
@@ -703,7 +706,7 @@ Remark: Always release the first item in the free list
void
Ndb::freeNdbCon()
{
- NdbConnection* tNdbCon = theConIdleList;
+ NdbTransaction* tNdbCon = theConIdleList;
theConIdleList = theConIdleList->next();
delete tNdbCon;
}
@@ -772,14 +775,14 @@ Ndb::freeNdbBlob()
}
/****************************************************************************
-int releaseConnectToNdb(NdbConnection* aConnectConnection);
+int releaseConnectToNdb(NdbTransaction* aConnectConnection);
Return Value: -1 if error
Parameters: aConnectConnection : Seized schema connection to DBTC
Remark: Release and disconnect from DBTC a connection and seize it to theConIdleList.
*****************************************************************************/
void
-Ndb::releaseConnectToNdb(NdbConnection* a_con)
+Ndb::releaseConnectToNdb(NdbTransaction* a_con)
{
DBUG_ENTER("Ndb::releaseConnectToNdb");
NdbApiSignal tSignal(theMyRef);
@@ -797,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(NdbConnection::DisConnecting);
+ a_con->Status(NdbTransaction::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 b6fb2d6cded..802e0785988 100644
--- a/ndb/src/ndbapi/TransporterFacade.cpp
+++ b/ndb/src/ndbapi/TransporterFacade.cpp
@@ -127,6 +127,10 @@ reportDisconnect(void * callbackObj, NodeId nodeId, Uint32 error){
//TransporterFacade::instance()->reportDisconnected(nodeId);
}
+void
+transporter_recv_from(void * callbackObj, NodeId nodeId){
+ ((TransporterFacade*)(callbackObj))->hb_received(nodeId);
+}
/****************************************************************************
*
@@ -529,43 +533,32 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
iter.first();
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")) {
-#endif
- iter.first();
- if(iter.find(CFG_NODE_ID, nodeId)){
- TRP_DEBUG( "Node info missing from config." );
- DBUG_RETURN(false);
- }
-
- Uint32 rank = 0;
- if(!iter.get(CFG_NODE_ARBIT_RANK, &rank) && rank>0){
- theArbitMgr = new ArbitMgr(* this);
- theArbitMgr->setRank(rank);
- Uint32 delay = 0;
- iter.get(CFG_NODE_ARBIT_DELAY, &delay);
- theArbitMgr->setDelay(delay);
- }
- Uint32 scan_batch_size= 0;
- if (!iter.get(CFG_MAX_SCAN_BATCH_SIZE, &scan_batch_size)) {
- m_scan_batch_size= scan_batch_size;
- }
- Uint32 batch_byte_size= 0;
- if (!iter.get(CFG_BATCH_BYTE_SIZE, &batch_byte_size)) {
- m_batch_byte_size= batch_byte_size;
- }
- Uint32 batch_size= 0;
- if (!iter.get(CFG_BATCH_SIZE, &batch_size)) {
- m_batch_size= batch_size;
- }
-#if 0
+ iter.first();
+ if(iter.find(CFG_NODE_ID, nodeId)){
+ TRP_DEBUG( "Node info missing from config." );
+ DBUG_RETURN(false);
+ }
+
+ Uint32 rank = 0;
+ if(!iter.get(CFG_NODE_ARBIT_RANK, &rank) && rank>0){
+ theArbitMgr = new ArbitMgr(* this);
+ theArbitMgr->setRank(rank);
+ Uint32 delay = 0;
+ iter.get(CFG_NODE_ARBIT_DELAY, &delay);
+ theArbitMgr->setDelay(delay);
+ }
+ Uint32 scan_batch_size= 0;
+ if (!iter.get(CFG_MAX_SCAN_BATCH_SIZE, &scan_batch_size)) {
+ m_scan_batch_size= scan_batch_size;
+ }
+ Uint32 batch_byte_size= 0;
+ if (!iter.get(CFG_BATCH_BYTE_SIZE, &batch_byte_size)) {
+ m_batch_byte_size= batch_byte_size;
+ }
+ Uint32 batch_size= 0;
+ if (!iter.get(CFG_BATCH_SIZE, &batch_size)) {
+ m_batch_size= batch_size;
}
-#endif
if (!theTransporterRegistry->start_service(m_socket_server)){
ndbout_c("Unable to start theTransporterRegistry->start_service");
diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp
index 99edea846c1..fa070889dd9 100644
--- a/ndb/src/ndbapi/TransporterFacade.hpp
+++ b/ndb/src/ndbapi/TransporterFacade.hpp
@@ -24,6 +24,7 @@
#include <NdbMutex.h>
#include "DictCache.hpp"
#include <BlockNumbers.h>
+#include <mgmapi.h>
class ClusterMgr;
class ArbitMgr;
@@ -43,10 +44,6 @@ 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:
@@ -115,6 +112,11 @@ public:
Uint32 get_batch_byte_size();
Uint32 get_batch_size();
+ TransporterRegistry* get_registry() { return theTransporterRegistry;};
+
+ // heart beat received from a node (e.g. a signal came)
+ void hb_received(NodeId n);
+
private:
/**
* Send a signal unconditional of node status (used by ClusterMgr)
@@ -133,7 +135,7 @@ private:
bool isConnected(NodeId aNodeId);
void doStop();
-
+
TransporterRegistry* theTransporterRegistry;
SocketServer m_socket_server;
int sendPerformedLastInterval;
@@ -171,6 +173,10 @@ private:
* Block number handling
*/
public:
+ /**
+ * Max number of Ndb objects.
+ * (Ndb objects should not be shared by different threads.)
+ */
STATIC_CONST( MAX_NO_THREADS = 4711 );
private:
@@ -293,6 +299,12 @@ TransporterFacade::get_node_alive(NodeId n) const {
}
inline
+void
+TransporterFacade::hb_received(NodeId n) {
+ theClusterMgr->hb_received(n);
+}
+
+inline
bool
TransporterFacade::get_node_stopping(NodeId n) const {
const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n);
diff --git a/ndb/src/ndbapi/ndb_cluster_connection.cpp b/ndb/src/ndbapi/ndb_cluster_connection.cpp
index 4fcf4d08396..7625da609b0 100644
--- a/ndb/src/ndbapi/ndb_cluster_connection.cpp
+++ b/ndb/src/ndbapi/ndb_cluster_connection.cpp
@@ -28,7 +28,8 @@
#include <ndb_limits.h>
#include <ConfigRetriever.hpp>
#include <ndb_version.h>
-#include <Vector.hpp>
+#include <mgmapi_debug.h>
+#include <mgmapi_internal.h>
#include <md5_hash.hpp>
#include <EventLogger.hpp>
@@ -180,6 +181,12 @@ Ndb_cluster_connection::no_db_nodes()
return m_impl.m_all_nodes.size();
}
+unsigned
+Ndb_cluster_connection::node_id()
+{
+ return m_impl.m_transporter_facade->ownId();
+}
+
int
Ndb_cluster_connection::wait_until_ready(int timeout,
@@ -253,22 +260,16 @@ Ndb_cluster_connection_impl::Ndb_cluster_connection_impl(const char *
g_eventLogger.createConsoleHandler();
g_eventLogger.setCategory("NdbApi");
g_eventLogger.enable(Logger::LL_ON, Logger::LL_ERROR);
-
- m_transporter_facade=
- TransporterFacade::theFacadeInstance= new TransporterFacade();
m_connect_thread= 0;
m_connect_callback= 0;
if (ndb_global_event_buffer_mutex == NULL)
- {
ndb_global_event_buffer_mutex= NdbMutex_Create();
- }
+
#ifdef VM_TRACE
if (ndb_print_state_mutex == NULL)
- {
ndb_print_state_mutex= NdbMutex_Create();
- }
#endif
m_config_retriever=
new ConfigRetriever(connect_string, NDB_VERSION, NODE_TYPE_API);
@@ -280,13 +281,16 @@ Ndb_cluster_connection_impl::Ndb_cluster_connection_impl(const char *
m_config_retriever= 0;
}
+ m_transporter_facade=
+ TransporterFacade::theFacadeInstance=
+ new TransporterFacade();
+
DBUG_VOID_RETURN;
}
Ndb_cluster_connection_impl::~Ndb_cluster_connection_impl()
{
DBUG_ENTER("~Ndb_cluster_connection");
- DBUG_PRINT("enter",("~Ndb_cluster_connection this=0x%x", this));
TransporterFacade::stop_instance();
if (m_connect_thread)
{
@@ -304,10 +308,22 @@ Ndb_cluster_connection_impl::~Ndb_cluster_connection_impl()
TransporterFacade::theFacadeInstance= 0;
}
if (m_config_retriever)
+ {
delete m_config_retriever;
-
- // fragmentToNodeMap.release();
-
+ m_config_retriever= NULL;
+ }
+ if (ndb_global_event_buffer_mutex != NULL)
+ {
+ NdbMutex_Destroy(ndb_global_event_buffer_mutex);
+ ndb_global_event_buffer_mutex= NULL;
+ }
+#ifdef VM_TRACE
+ if (ndb_print_state_mutex != NULL)
+ {
+ NdbMutex_Destroy(ndb_print_state_mutex);
+ ndb_print_state_mutex= NULL;
+ }
+#endif
DBUG_VOID_RETURN;
}
@@ -465,6 +481,8 @@ Ndb_cluster_connection_impl::do_test()
int Ndb_cluster_connection::connect(int no_retries, int retry_delay_in_seconds,
int verbose)
{
+ struct ndb_mgm_reply mgm_reply;
+
DBUG_ENTER("Ndb_cluster_connection::connect");
const char* error = 0;
do {
@@ -482,10 +500,24 @@ int Ndb_cluster_connection::connect(int no_retries, int retry_delay_in_seconds,
ndb_mgm_configuration * props = m_impl.m_config_retriever->getConfig();
if(props == 0)
break;
- m_impl.m_transporter_facade->start_instance(nodeId, props);
+ m_impl.m_transporter_facade->start_instance(nodeId, props);
m_impl.init_nodes_vector(nodeId, *props);
+ for(unsigned i=0;
+ i<m_impl.m_transporter_facade->get_registry()->m_transporter_interface.size();
+ i++)
+ ndb_mgm_set_connection_int_parameter(m_impl.m_config_retriever->get_mgmHandle(),
+ nodeId,
+ m_impl.m_transporter_facade->get_registry()
+ ->m_transporter_interface[i]
+ .m_remote_nodeId,
+ CFG_CONNECTION_SERVER_PORT,
+ m_impl.m_transporter_facade->get_registry()
+ ->m_transporter_interface[i]
+ .m_s_service_port,
+ &mgm_reply);
+
ndb_mgm_destroy_configuration(props);
m_impl.m_transporter_facade->connected();
DBUG_RETURN(0);
@@ -522,110 +554,5 @@ void Ndb_cluster_connection_impl::connect_thread()
DBUG_VOID_RETURN;
}
-/*
- * Hint handling to select node
- * ToDo: fix this
- */
-
-void
-Ndb_cluster_connection_impl::FragmentToNodeMap::init(Uint32 noOfNodes,
- Uint8 nodeIds[])
-{
- kValue = 6;
- noOfFragments = 2 * noOfNodes;
-
- /**
- * Compute hashValueMask and hashpointerValue
- */
- {
- Uint32 topBit = (1 << 31);
- for(int i = 31; i>=0; i--){
- if((noOfFragments & topBit) != 0)
- break;
- topBit >>= 1;
- }
- hashValueMask = topBit - 1;
- hashpointerValue = noOfFragments - (hashValueMask + 1);
- }
-
- /**
- * This initialization depends on
- * the fact that:
- * primary node for fragment i = i % noOfNodes
- *
- * This algorithm should be implemented in Dbdih
- */
- {
- if (fragment2PrimaryNodeMap != 0)
- abort();
-
- fragment2PrimaryNodeMap = new Uint32[noOfFragments];
- Uint32 i;
- for(i = 0; i<noOfNodes; i++){
- fragment2PrimaryNodeMap[i] = nodeIds[i];
- }
-
- // Sort them (bubble sort)
- for(i = 0; i<noOfNodes-1; i++)
- for(Uint32 j = i+1; j<noOfNodes; j++)
- if(fragment2PrimaryNodeMap[i] > fragment2PrimaryNodeMap[j]){
- Uint32 tmp = fragment2PrimaryNodeMap[i];
- fragment2PrimaryNodeMap[i] = fragment2PrimaryNodeMap[j];
- fragment2PrimaryNodeMap[j] = tmp;
- }
-
- for(i = 0; i<noOfNodes; i++){
- fragment2PrimaryNodeMap[i+noOfNodes] = fragment2PrimaryNodeMap[i];
- }
- }
-}
-
-void
-Ndb_cluster_connection_impl::FragmentToNodeMap::release(){
- delete [] fragment2PrimaryNodeMap;
- fragment2PrimaryNodeMap = 0;
-}
-
-static const Uint32 MAX_KEY_LEN_64_WORDS = 4;
-Uint32
-Ndb_cluster_connection_impl::guess_primary_node(const char *keyData,
- Uint32 keyLen)
-{
- Uint64 tempData[MAX_KEY_LEN_64_WORDS];
-
- const Uint32 usedKeyLen = (keyLen + 3) >> 2; // In words
- const char * usedKeyData = 0;
-
- /**
- * If key data buffer is not aligned (on 64 bit boundary)
- * or key len is not a multiple of 4
- * Use temp data
- */
- if(((((UintPtr)keyData) & 7) == 0) && ((keyLen & 3) == 0)) {
- usedKeyData = keyData;
- } else {
- memcpy(&tempData[0], keyData, keyLen);
- const int slack = keyLen & 3;
- if(slack > 0) {
- memset(&((char *)&tempData[0])[keyLen], 0, (4 - slack));
- }//if
- usedKeyData = (char *)&tempData[0];
- }//if
-
- Uint32 hashValue = md5_hash((Uint64 *)usedKeyData, usedKeyLen);
-
- hashValue >>= fragmentToNodeMap.kValue;
-
- Uint32 fragmentId = hashValue &
- fragmentToNodeMap.hashValueMask;
-
- if(fragmentId < fragmentToNodeMap.hashpointerValue) {
- fragmentId = hashValue &
- ((fragmentToNodeMap.hashValueMask << 1) + 1);
- }//if
- return fragmentId;
-}
-
-
template class Vector<Ndb_cluster_connection_impl::Node>;
diff --git a/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp b/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
index 620eac296a3..05652f3316a 100644
--- a/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
+++ b/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
@@ -54,22 +54,6 @@ private:
friend class NdbImpl;
friend void* run_ndb_cluster_connection_connect_thread(void*);
friend class Ndb_cluster_connection;
-
- /**
- * Structure containing values for guessing primary node
- */
- struct FragmentToNodeMap {
- FragmentToNodeMap():
- fragment2PrimaryNodeMap(0) {};
- Uint32 kValue;
- Uint32 hashValueMask;
- Uint32 hashpointerValue;
- Uint32 noOfFragments;
- Uint32 *fragment2PrimaryNodeMap;
-
- void init(Uint32 noOfNodes, Uint8 nodeIds[]);
- void release();
- } fragmentToNodeMap;
struct Node
{
@@ -85,8 +69,6 @@ private:
Vector<Node> m_all_nodes;
void init_nodes_vector(Uint32 nodeid, const ndb_mgm_configuration &config);
- Uint32 guess_primary_node(const char * keyData, Uint32 keyLen);
-
void connect_thread();
TransporterFacade *m_transporter_facade;
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index 69fc47ff70c..3c3893c38ae 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -55,6 +55,8 @@ typedef struct ErrorBundle {
#define NI ndberror_cl_function_not_implemented
#define UE ndberror_cl_unknown_error_code
+#define OE ndberror_cl_schema_object_already_exists
+
static const char* empty_string = "";
/*
@@ -66,6 +68,7 @@ static const char* empty_string = "";
* 600 - ACC
* 700 - DICT
* 800 - TUP
+ * 900 - TUX
* 1200 - LQH
* 1300 - BACKUP
* 4000 - API
@@ -75,6 +78,7 @@ static const char* empty_string = "";
* 4400 - ""
* 4500 - ""
* 4600 - ""
+ * 4700 - "" Event
* 5000 - Management server
*/
@@ -174,11 +178,13 @@ ErrorBundle ErrorCodes[] = {
{ 623, IS, "623" },
{ 624, IS, "624" },
{ 625, IS, "Out of memory in Ndb Kernel, hash index part (increase IndexMemory)" },
- { 800, IS, "Too many ordered indexes (increase MaxNoOfOrderedIndexes)" },
+ { 640, IS, "Too many hash indexes (should not happen)" },
{ 826, IS, "Too many tables and attributes (increase MaxNoOfAttributes or MaxNoOfTables)" },
{ 827, IS, "Out of memory in Ndb Kernel, table data (increase DataMemory)" },
{ 902, IS, "Out of memory in Ndb Kernel, ordered index data (increase DataMemory)" },
- { 832, IS, "832" },
+ { 903, IS, "Too many ordered indexes (increase MaxNoOfOrderedIndexes)" },
+ { 904, IS, "Out of fragment records (increase MaxNoOfOrderedIndexes)" },
+ { 905, IS, "Out of attribute records (increase MaxNoOfAttributes)" },
/**
* TimeoutExpired
@@ -204,6 +210,7 @@ ErrorBundle ErrorCodes[] = {
* Internal errors
*/
{ 892, IE, "Inconsistent hash index. The index needs to be dropped and recreated" },
+ { 896, IE, "Tuple corrupted - wrong checksum or column data in invalid format" },
{ 901, IE, "Inconsistent ordered index. The index needs to be dropped and recreated" },
{ 202, IE, "202" },
{ 203, IE, "203" },
@@ -259,6 +266,7 @@ ErrorBundle ErrorCodes[] = {
* Application error
*/
{ 823, AE, "Too much attrinfo from application in tuple manager" },
+ { 831, AE, "Too many nullable/bitfields in table definition" },
{ 876, AE, "876" },
{ 877, AE, "877" },
{ 878, AE, "878" },
@@ -270,7 +278,7 @@ ErrorBundle ErrorCodes[] = {
{ 897, AE, "Update attempt of primary key via ndbcluster internal api (if this occurs via the MySQL server it is a bug, please report)" },
{ 4256, AE, "Must call Ndb::init() before this function" },
{ 4257, AE, "Tried to read too much - too many getValue calls" },
-
+
/**
* Scan application errors
*/
@@ -289,6 +297,30 @@ ErrorBundle ErrorCodes[] = {
{ 4232, AE, "Parallelism can only be between 1 and 240" },
{ 290, AE, "Scan not started or has been closed by kernel due to timeout" },
+ /**
+ * Event schema errors
+ */
+
+ { 4713, SE, "Column defined in event does not exist in table"},
+
+ /**
+ * Event application errors
+ */
+
+ { 4707, AE, "Too many event have been defined"},
+ { 4708, AE, "Event name is too long"},
+ { 4709, AE, "Can't accept more subscribers"},
+ { 746, OE, "Event name already exists"},
+ { 4710, AE, "Event not found"},
+ { 4711, AE, "Creation of event failed"},
+ { 4712, AE, "Stopped event operation does not exist. Already stopped?"},
+
+ /**
+ * Event internal errors
+ */
+
+ { 4731, IE, "Event not found"},
+
/**
* SchemaError
*/
@@ -299,17 +331,17 @@ ErrorBundle ErrorCodes[] = {
{ 707, SE, "No more table metadata records (increase MaxNoOfTables)" },
{ 708, SE, "No more attribute metadata records (increase MaxNoOfAttributes)" },
{ 709, SE, "No such table existed" },
- { 721, SE, "Table or index with given name already exists" },
+ { 721, OE, "Table or index with given name already exists" },
{ 723, SE, "No such table existed" },
- { 736, SE, "Wrong attribute size" },
+ { 736, SE, "Unsupported array size" },
{ 737, SE, "Attribute array size too big" },
{ 738, SE, "Record too big" },
{ 739, SE, "Unsupported primary key length" },
{ 740, SE, "Nullable primary key not supported" },
{ 741, SE, "Unsupported alter table" },
- { 742, SE, "Unsupported attribute type in index" },
{ 743, SE, "Unsupported character set in table or index" },
{ 744, SE, "Character string is invalid for given character set" },
+ { 745, SE, "Distribution key not supported for char attribute (use binary attribute)" },
{ 761, SE, "Unable to drop table as backup is in progress" },
{ 762, SE, "Unable to alter table as backup is in progress" },
{ 241, SE, "Invalid schema object version" },
@@ -317,6 +349,9 @@ ErrorBundle ErrorCodes[] = {
{ 284, SE, "Table not defined in transaction coordinator" },
{ 285, SE, "Unknown table error in transaction coordinator" },
{ 881, SE, "Unable to create table, out of data pages (increase DataMemory) " },
+ { 906, SE, "Unsupported attribute type in index" },
+ { 907, SE, "Unsupported character set in table or index" },
+ { 908, IS, "Invalid ordered index tree node size" },
{ 1225, SE, "Table not defined in local query handler" },
{ 1226, SE, "Table is being dropped" },
{ 1228, SE, "Cannot use drop table for drop index" },
@@ -461,8 +496,7 @@ ErrorBundle ErrorCodes[] = {
{ 4241, AE, "Index name too long" },
{ 4242, AE, "Too many indexes" },
{ 4243, AE, "Index not found" },
- { 4244, AE, "Index or table with given name already exists" },
- { 4245, AE, "Index attribute must be defined as stored, i.e. the StorageAttributeType must be defined as NormalStorageAttribute"},
+ { 4244, OE, "Index or table with given name already exists" },
{ 4247, AE, "Illegal index/trigger create/drop/alter request" },
{ 4248, AE, "Trigger/index name invalid" },
{ 4249, AE, "Invalid table" },
@@ -483,9 +517,10 @@ ErrorBundle ErrorCodes[] = {
{ 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" },
{ 4269, IE, "No connection to ndb management server" },
- { 4335, AE, "Only one autoincrement column allowed per table. Having a table without primary key uses an autoincremented hidden key, i.e. a table without a primary key can not have an autoincremented column" }
+ { 4270, IE, "Unknown blob error" },
+ { 4335, AE, "Only one autoincrement column allowed per table. Having a table without primary key uses an autoincremented hidden key, i.e. a table without a primary key can not have an autoincremented column" },
+ { 4271, AE, "Invalid index object, not retrieved via getIndex()" }
};
static
diff --git a/ndb/test/include/HugoCalculator.hpp b/ndb/test/include/HugoCalculator.hpp
index b782eb003a3..03de46cd7ea 100644
--- a/ndb/test/include/HugoCalculator.hpp
+++ b/ndb/test/include/HugoCalculator.hpp
@@ -31,14 +31,7 @@ class HugoCalculator {
public:
HugoCalculator(const NdbDictionary::Table& tab);
Int32 calcValue(int record, int attrib, int updates) const;
-#if 0
- U_Int32 calcValue(int record, int attrib, int updates) const;
- U_Int64 calcValue(int record, int attrib, int updates) const;
- Int64 calcValue(int record, int attrib, int updates) const;
- float calcValue(int record, int attrib, int updates) const;
- double calcValue(int record, int attrib, int updates) const;
-#endif
- const char* calcValue(int record, int attrib, int updates, char* buf) const;
+ const char* calcValue(int record, int attrib, int updates, char* buf, int len) const;
int verifyRowValues(NDBT_ResultRow* const pRow) const;
int getIdValue(NDBT_ResultRow* const pRow) const;
diff --git a/ndb/test/include/HugoOperations.hpp b/ndb/test/include/HugoOperations.hpp
index 34b2edc2ae8..82fd5529fa2 100644
--- a/ndb/test/include/HugoOperations.hpp
+++ b/ndb/test/include/HugoOperations.hpp
@@ -24,11 +24,14 @@
class HugoOperations : public UtilTransactions {
public:
- HugoOperations(const NdbDictionary::Table&);
+ HugoOperations(const NdbDictionary::Table&,
+ const NdbDictionary::Index* idx = 0);
+
~HugoOperations();
int startTransaction(Ndb*);
+ int setTransaction(NdbTransaction*);
int closeTransaction(Ndb*);
- NdbConnection* getTransaction();
+ NdbTransaction* getTransaction();
void refresh();
void setTransactionId(Uint64);
@@ -42,6 +45,10 @@ public:
int recordNo,
int numRecords = 1,
int updatesValue = 0);
+
+ int pkWritePartialRecord(Ndb*,
+ int recordNo,
+ int numRecords = 1);
int pkReadRecord(Ndb*,
int recordNo,
@@ -73,10 +80,13 @@ public:
int attrId,
int rowId,
int updateId);
+
int equalForAttr(NdbOperation*,
int attrId,
int rowId);
-
+
+ int setValues(NdbOperation*, int rowId, int updateId);
+
int verifyUpdatesValue(int updatesValue, int _numRows = 0);
int indexReadRecords(Ndb*, const char * idxName, int recordNo,
@@ -93,8 +103,11 @@ public:
NdbScanOperation::LM_CommittedRead,
int numRecords = 1);
+ NdbIndexScanOperation* pIndexScanOp;
- int execute_async(Ndb*, ExecType, AbortOption = AbortOnError);
+ NDBT_ResultRow& get_row(Uint32 idx) { return *rows[idx];}
+
+ int execute_async(Ndb*, NdbTransaction::ExecType, NdbTransaction::AbortOption = NdbTransaction::AbortOnError);
int wait_async(Ndb*, int timeout = -1);
protected:
@@ -106,16 +119,14 @@ protected:
Vector<BaseString> savedRecords;
- struct RsPair { NdbResultSet* m_result_set; int records; };
+ struct RsPair { NdbScanOperation* m_result_set; int records; };
Vector<RsPair> m_result_sets;
Vector<RsPair> m_executed_result_sets;
- NdbConnection* pTrans;
-
int m_async_reply;
int m_async_return;
- friend void HugoOperations_async_callback(int, NdbConnection*, void*);
- void callback(int res, NdbConnection*);
+ friend void HugoOperations_async_callback(int, NdbTransaction*, void*);
+ void callback(int res, NdbTransaction*);
};
#endif
diff --git a/ndb/test/include/HugoTransactions.hpp b/ndb/test/include/HugoTransactions.hpp
index b833f2ac629..5795bbc94c9 100644
--- a/ndb/test/include/HugoTransactions.hpp
+++ b/ndb/test/include/HugoTransactions.hpp
@@ -25,7 +25,8 @@
class HugoTransactions : public HugoOperations {
public:
- HugoTransactions(const NdbDictionary::Table&);
+ HugoTransactions(const NdbDictionary::Table&,
+ const NdbDictionary::Index* idx = 0);
~HugoTransactions();
int createEvent(Ndb*);
int eventOperation(Ndb*, void* stats,
@@ -41,7 +42,8 @@ public:
int records,
int abort = 0,
int parallelism = 0,
- NdbOperation::LockMode = NdbOperation::LM_Read);
+ NdbOperation::LockMode = NdbOperation::LM_Read,
+ int scan_flags = 0);
int scanReadRecords(Ndb*,
const NdbDictionary::Index*,
@@ -49,7 +51,7 @@ public:
int abort = 0,
int parallelism = 0,
NdbOperation::LockMode = NdbOperation::LM_Read,
- bool sorted = false);
+ int scan_flags = 0);
int pkReadRecords(Ndb*,
int records,
diff --git a/ndb/test/include/NDBT_Error.hpp b/ndb/test/include/NDBT_Error.hpp
index ef107072465..6775a107196 100644
--- a/ndb/test/include/NDBT_Error.hpp
+++ b/ndb/test/include/NDBT_Error.hpp
@@ -91,7 +91,11 @@ private:
; \
}
-#define ERR(error) ERR_OUT(g_err, error)
+#define ERR(error) \
+{ \
+ const NdbError &_error= (error); \
+ ERR_OUT(g_err, _error); \
+}
#define ERR_INFO(error) ERR_OUT(g_info, error)
#endif
diff --git a/ndb/test/include/NDBT_ResultRow.hpp b/ndb/test/include/NDBT_ResultRow.hpp
index 6072d0ea510..cbb5d7f6c6a 100644
--- a/ndb/test/include/NDBT_ResultRow.hpp
+++ b/ndb/test/include/NDBT_ResultRow.hpp
@@ -27,7 +27,7 @@ public:
const NdbRecAttr * attributeStore(int i) const ;
const NdbRecAttr * attributeStore(const char* name) const ;
- BaseString c_str();
+ BaseString c_str() const ;
NdbOut & header (NdbOut &) const;
friend NdbOut & operator << (NdbOut&, const NDBT_ResultRow &);
@@ -36,6 +36,11 @@ public:
* Make copy of NDBT_ResultRow
*/
NDBT_ResultRow * clone() const;
+
+ bool operator==(const NDBT_ResultRow&) const ;
+ bool operator!=(const NDBT_ResultRow& other) const {
+ return ! (*this == other);
+ }
private:
int cols;
diff --git a/ndb/test/include/NDBT_Tables.hpp b/ndb/test/include/NDBT_Tables.hpp
index aa78f7d4e2c..fb0df8aa35b 100644
--- a/ndb/test/include/NDBT_Tables.hpp
+++ b/ndb/test/include/NDBT_Tables.hpp
@@ -23,11 +23,13 @@
#include <NdbDictionary.hpp>
#include <NDBT_Table.hpp>
+typedef int (* NDBT_CreateTableHook)(Ndb*, NdbDictionary::Table&, int when);
+
class NDBT_Tables {
public:
-
+
static int createTable(Ndb* pNdb, const char* _name, bool _temp = false,
- bool existsOK = false);
+ bool existsOK = false, NDBT_CreateTableHook = 0);
static int createAllTables(Ndb* pNdb, bool _temp, bool existsOK = false);
static int createAllTables(Ndb* pNdb);
diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp
index bcaa0bf4d40..027ac356e0c 100644
--- a/ndb/test/include/NDBT_Test.hpp
+++ b/ndb/test/include/NDBT_Test.hpp
@@ -25,6 +25,7 @@
#include <NdbCondition.h>
#include <NdbTimer.hpp>
#include <Vector.hpp>
+#include <NdbApi.hpp>
#include <NdbDictionary.hpp>
class NDBT_Step;
@@ -34,7 +35,9 @@ class NDBT_TestCaseImpl1;
class NDBT_Context {
public:
- NDBT_Context();
+ Ndb_cluster_connection& m_cluster_connection;
+
+ NDBT_Context(Ndb_cluster_connection&);
~NDBT_Context();
const NdbDictionary::Table* getTab();
NDBT_TestSuite* getSuite();
@@ -121,7 +124,7 @@ public:
NDBT_TESTFUNC* pfunc);
virtual ~NDBT_Step() {}
int execute(NDBT_Context*);
- virtual int setUp() = 0;
+ virtual int setUp(Ndb_cluster_connection&) = 0;
virtual void tearDown() = 0;
void setContext(NDBT_Context*);
NDBT_Context* getContext();
@@ -143,7 +146,7 @@ public:
const char* pname,
NDBT_TESTFUNC* pfunc);
virtual ~NDBT_NdbApiStep() {}
- virtual int setUp();
+ virtual int setUp(Ndb_cluster_connection&);
virtual void tearDown();
Ndb* getNdb();
@@ -350,10 +353,13 @@ public:
int addTest(NDBT_TestCase* pTest);
private:
- int executeOne(const char* _tabname, const char* testname = NULL);
- int executeAll(const char* testname = NULL);
-
- void execute(Ndb*, const NdbDictionary::Table*, const char* testname = NULL);
+ int executeOne(Ndb_cluster_connection&,
+ const char* _tabname, const char* testname = NULL);
+ int executeAll(Ndb_cluster_connection&,
+ const char* testname = NULL);
+ void execute(Ndb_cluster_connection&,
+ Ndb*, const NdbDictionary::Table*, const char* testname = NULL);
+
int report(const char* _tcname = NULL);
int reportAllTables(const char* );
const char* name;
@@ -426,7 +432,7 @@ C##suitname():NDBT_TestSuite(#suitname){ \
pt->addTable(tableName, false);
#define NDBT_TESTSUITE_END(suitname) \
- } } ; C##suitname suitname;
+ } } ; C##suitname suitname
// Helper functions for retrieving variables from NDBT_Step
#define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
diff --git a/ndb/test/include/NdbSchemaOp.hpp b/ndb/test/include/NdbSchemaOp.hpp
index e8ab542b00a..1edbc155643 100644
--- a/ndb/test/include/NdbSchemaOp.hpp
+++ b/ndb/test/include/NdbSchemaOp.hpp
@@ -79,29 +79,6 @@
};
/**
- * 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 {
@@ -405,27 +382,7 @@ public:
* 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 aStType Obsolete since wl-2066
* @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
@@ -474,7 +431,7 @@ public:
AttrType aAttrType = UnSigned,
StorageMode aStorageMode = MMBased,
bool nullable = false,
- StorageAttributeType aStType= NormalStorageAttribute,
+ int aStType= 0, // obsolete
int aDistributionKey = 0,
int aDistributionGroup = 0,
int aDistributionGroupNoOfBits = 16,
@@ -491,7 +448,7 @@ public:
AttrType aAttrType,
StorageMode aStorageMode,
NullAttributeType aNullAttr,
- StorageAttributeType aStType = NormalStorageAttribute,
+ int aStType, // obsolete
int aDistributionKey = 0,
int aDistributionGroup = 0,
int aDistributionGroupNoOfBits = 16){
@@ -569,6 +526,8 @@ convertColumnTypeToAttrType(NdbDictionary::Column::Type _type)
case NdbDictionary::Column::Float:
case NdbDictionary::Column::Olddecimal:
case NdbDictionary::Column::Olddecimalunsigned:
+ case NdbDictionary::Column::Decimal:
+ case NdbDictionary::Column::Decimalunsigned:
case NdbDictionary::Column::Double:
return Float;
case NdbDictionary::Column::Char:
diff --git a/ndb/test/include/UtilTransactions.hpp b/ndb/test/include/UtilTransactions.hpp
index 23902f3b317..333f5d98328 100644
--- a/ndb/test/include/UtilTransactions.hpp
+++ b/ndb/test/include/UtilTransactions.hpp
@@ -23,15 +23,13 @@ typedef int (ReadCallBackFn)(NDBT_ResultRow*);
class UtilTransactions {
public:
- enum ScanLock {
- SL_Read = 0,
- SL_ReadHold = 1,
- SL_Exclusive = 2
- };
-
- UtilTransactions(const NdbDictionary::Table&);
- UtilTransactions(Ndb* ndb, const char * tableName);
-
+ UtilTransactions(const NdbDictionary::Table&,
+ const NdbDictionary::Index* idx = 0);
+ UtilTransactions(Ndb* ndb,
+ const char * tableName, const char * indexName = 0);
+
+ int closeTransaction(Ndb*);
+
int clearTable(Ndb*,
int records = 0,
int parallelism = 0);
@@ -70,6 +68,14 @@ public:
int copyTableData(Ndb*,
const char* destName);
+ /**
+ * Compare this table with other_table
+ *
+ * return 0 - on equality
+ * -1 - on error
+ * >0 - otherwise
+ */
+ int compare(Ndb*, const char * other_table, int flags);
private:
static int takeOverAndDeleteRecord(Ndb*,
@@ -114,6 +120,12 @@ private:
protected:
int m_defaultClearMethod;
const NdbDictionary::Table& tab;
+ const NdbDictionary::Index* idx;
+ NdbConnection* pTrans;
+
+ NdbOperation* getOperation(NdbConnection*,
+ NdbOperation::OperationType);
+ NdbScanOperation* getScanOperation(NdbConnection*);
};
#endif
diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am
index 7b4a96f5890..d83e9614eb5 100644
--- a/ndb/test/ndbapi/Makefile.am
+++ b/ndb/test/ndbapi/Makefile.am
@@ -31,7 +31,10 @@ testTimeout \
testTransactions \
testDeadlock \
test_event ndbapi_slow_select testReadPerf testLcp \
+testPartitioning \
+testBitfield \
DbCreate DbAsyncGenerator \
+test_event_multi_table \
testSRBank
#flexTimedAsynch
@@ -71,8 +74,11 @@ test_event_SOURCES = test_event.cpp
ndbapi_slow_select_SOURCES = slow_select.cpp
testReadPerf_SOURCES = testReadPerf.cpp
testLcp_SOURCES = testLcp.cpp
-DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
-DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
+testPartitioning_SOURCES = testPartitioning.cpp
+testBitfield_SOURCES = testBitfield.cpp
+DbCreate_SOURCES = bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
+DbAsyncGenerator_SOURCES = bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
+test_event_multi_table_SOURCES = test_event_multi_table.cpp
testSRBank_SOURCES = testSRBank.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
@@ -90,6 +96,8 @@ testSRBank_LDADD = bank/libbank.a $(LDADD)
# Don't update the files from bitkeeper
%::SCCS/s.%
+
+
windoze-dsp: flexBench.dsp testBasic.dsp testBlobs.dsp \
testScan.dsp
diff --git a/ndb/test/ndbapi/ScanFunctions.hpp b/ndb/test/ndbapi/ScanFunctions.hpp
index 6964f8c73a8..37389d9b7de 100644
--- a/ndb/test/ndbapi/ScanFunctions.hpp
+++ b/ndb/test/ndbapi/ScanFunctions.hpp
@@ -81,7 +81,6 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
int check;
NdbConnection *pTrans = 0;
NdbScanOperation *pOp = 0;
- NdbResultSet *rs = 0;
while (true){
if (retryAttempt >= retryMax){
@@ -111,12 +110,9 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
return NDBT_FAILED;
}
-
- rs = pOp->readTuples(exclusive ?
- NdbScanOperation::LM_Exclusive :
- NdbScanOperation::LM_Read);
-
- if( rs == 0 ) {
+ if( pOp->readTuples(exclusive ?
+ NdbScanOperation::LM_Exclusive :
+ NdbScanOperation::LM_Read) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -125,8 +121,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
if (action == OnlyOpenScanOnce){
// Call openScan one more time when it's already defined
- NdbResultSet* rs2 = pOp->readTuples(NdbScanOperation::LM_Read);
- if( rs2 == 0 ) {
+ if( pOp->readTuples(NdbScanOperation::LM_Read) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -168,7 +163,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
bool abortTrans = (action==CloseWithoutStop);
int eof;
int rows = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
while(eof == 0){
rows++;
@@ -178,7 +173,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
if (action != CloseWithoutStop){
// Test that we can closeTrans without stopScan
- rs->close();
+ pOp->close();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -201,7 +196,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
}
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
@@ -211,7 +206,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
// Be cruel, call nextScanResult after error
for(int i=0; i<10; i++){
- eof = rs->nextResult();
+ eof = pOp->nextResult();
if(eof == 0){
g_err << "nextScanResult returned eof = " << eof << endl
<< " That is an error when there are no more records" << endl;
@@ -241,7 +236,7 @@ ScanFunctions::scanReadFunctions(Ndb* pNdb,
if (action == NextScanWhenNoMore){
g_info << "Calling nextScanresult when there are no more records" << endl;
for(int i=0; i<10; i++){
- eof = rs->nextResult();
+ eof = pOp->nextResult();
if(eof == 0){
g_err << "nextScanResult returned eof = " << eof << endl
<< " That is an error when there are no more records" << endl;
diff --git a/ndb/test/ndbapi/ScanInterpretTest.hpp b/ndb/test/ndbapi/ScanInterpretTest.hpp
index e8a0d4b6dca..d4e9bbecc81 100644
--- a/ndb/test/ndbapi/ScanInterpretTest.hpp
+++ b/ndb/test/ndbapi/ScanInterpretTest.hpp
@@ -227,10 +227,7 @@ ScanInterpretTest::scanRead(Ndb* pNdb,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Read,
- 0, parallelism);
-
- if( rs == 0 ) {
+ if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -262,14 +259,14 @@ ScanInterpretTest::scanRead(Ndb* pNdb,
int rows = 0;
NdbConnection* pInsTrans;
- while((eof = rs->nextResult(true)) == 0){
+ while((eof = pOp->nextResult(true)) == 0){
do {
rows++;
if (addRowToInsert(pNdb, pTrans) != 0){
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
- } while((eof = rs->nextResult(false)) == 0);
+ } while((eof = pOp->nextResult(false)) == 0);
check = pTrans->execute(Commit);
if( check == -1 ) {
@@ -349,9 +346,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Read,
- 0, parallelism);
- if( rs == 0 ) {
+ if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -392,7 +387,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
NdbConnection* pExistTrans;
NdbConnection* pNoExistTrans;
- while((eof = rs->nextResult(true)) == 0){
+ while((eof = pOp->nextResult(true)) == 0){
pExistTrans = pNdb->startTransaction();
if (pExistTrans == NULL) {
const NdbError err = pNdb->getNdbError();
@@ -424,7 +419,7 @@ ScanInterpretTest::scanReadVerify(Ndb* pNdb,
return NDBT_FAILED;
}
}
- } while((eof = rs->nextResult(false)) == 0);
+ } while((eof = pOp->nextResult(false)) == 0);
// Execute the transaction containing reads of
diff --git a/ndb/test/ndbapi/bank/Bank.cpp b/ndb/test/ndbapi/bank/Bank.cpp
index 346442367fc..37224fdd055 100644
--- a/ndb/test/ndbapi/bank/Bank.cpp
+++ b/ndb/test/ndbapi/bank/Bank.cpp
@@ -19,8 +19,8 @@
#include <NdbSleep.h>
#include <UtilTransactions.hpp>
-Bank::Bank(bool _init):
- m_ndb("BANK"),
+Bank::Bank(Ndb_cluster_connection& con, bool _init):
+ m_ndb(&con, "BANK"),
m_maxAccount(-1),
m_initialized(false)
{
@@ -661,8 +661,7 @@ int Bank::findLastGL(Uint64 &lastTime){
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples();
- if( rs == 0 ) {
+ if( pOp->readTuples() ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -691,7 +690,7 @@ int Bank::findLastGL(Uint64 &lastTime){
int eof;
int rows = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
lastTime = 0;
while(eof == 0){
@@ -701,7 +700,7 @@ int Bank::findLastGL(Uint64 &lastTime){
if (t > lastTime)
lastTime = t;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -993,8 +992,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuplesExclusive();
- if( rs == 0 ) {
+ if( pOp->readTuplesExclusive()) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1045,7 +1043,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime,
int eof;
int rows = 0;
int rowsFound = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
while(eof == 0){
rows++;
@@ -1069,7 +1067,7 @@ int Bank::sumTransactionsForGL(const Uint64 glTime,
}
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
if ((rows % 100) == 0){
// "refresh" ownner transaction every 100th row
@@ -1153,8 +1151,7 @@ int Bank::performValidateGL(Uint64 glTime){
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples();
- if( rs == 0 ) {
+ if( pOp->readTuples() ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1233,7 +1230,7 @@ int Bank::performValidateGL(Uint64 glTime){
int rows = 0;
int countGlRecords = 0;
int result = NDBT_OK;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
while(eof == 0){
rows++;
@@ -1320,7 +1317,7 @@ int Bank::performValidateGL(Uint64 glTime){
}
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1417,8 +1414,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples();
- if( rs == 0 ) {
+ if( pOp->readTuples() ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1461,7 +1457,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType,
int eof;
int rows = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
oldest = 0;
while(eof == 0){
@@ -1475,7 +1471,7 @@ int Bank::getOldestPurgedGL(const Uint32 accountType,
if (t > oldest)
oldest = t;
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1509,8 +1505,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples();
- if( rs == 0 ) {
+ if( pOp->readTuples() ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1553,7 +1548,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest,
int eof;
int rows = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
oldest = (Uint64)-1;
found = false;
@@ -1570,7 +1565,7 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest,
accountTypeId = a;
}
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1606,8 +1601,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples();
- if( rs == 0 ) {
+ if( pOp->readTuples() ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1651,7 +1645,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
int eof;
int rows = 0;
int found = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
while(eof == 0){
rows++;
@@ -1667,7 +1661,7 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
<< " ti = " << ti << endl;
found++;
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -1850,8 +1844,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuplesExclusive();
- if( rs == 0 ) {
+ if( pOp->readTuplesExclusive() ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -1888,7 +1881,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
int eof;
int rows = 0;
int rowsFound = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
while(eof == 0){
rows++;
@@ -1898,7 +1891,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
if (a == accountType && t == glTime){
rowsFound++;
// One record found
- check = rs->deleteTuple(pTrans);
+ check = pOp->deleteCurrentTuple(pTrans);
if (check == -1){
ERR(m_ndb.getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -1913,7 +1906,7 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
return NDBT_FAILED;
}
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -2371,8 +2364,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuplesExclusive();
- if( rs == 0 ) {
+ if( pOp->readTuplesExclusive() ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -2407,7 +2399,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
}
int eof;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
while(eof == 0){
Uint32 b = balanceRec->u_32_value();
@@ -2419,7 +2411,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
// << ", sum="<< sumAccounts << endl;
// Take over the operation so that the lock is kept in db
- NdbOperation* pLockOp = rs->updateTuple(pTrans);
+ NdbOperation* pLockOp = pOp->updateCurrentTuple(pTrans);
if (pLockOp == NULL){
ERR(m_ndb.getNdbError());
m_ndb.closeTransaction(pScanTrans);
@@ -2445,7 +2437,7 @@ int Bank::getSumAccounts(Uint32 &sumAccounts,
return NDBT_FAILED;
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
diff --git a/ndb/test/ndbapi/bank/Bank.hpp b/ndb/test/ndbapi/bank/Bank.hpp
index 14e01df29d5..b80f02dae97 100644
--- a/ndb/test/ndbapi/bank/Bank.hpp
+++ b/ndb/test/ndbapi/bank/Bank.hpp
@@ -27,7 +27,7 @@
class Bank {
public:
- Bank(bool init = true);
+ Bank(Ndb_cluster_connection&, bool init = true);
int createAndLoadBank(bool overWrite, int num_accounts=10);
int dropBank();
diff --git a/ndb/test/ndbapi/bank/BankLoad.cpp b/ndb/test/ndbapi/bank/BankLoad.cpp
index 39dc8097115..34947019a51 100644
--- a/ndb/test/ndbapi/bank/BankLoad.cpp
+++ b/ndb/test/ndbapi/bank/BankLoad.cpp
@@ -321,7 +321,7 @@ int Bank::loadGl(){
m_ndb.closeTransaction(pTrans);
return NDBT_OK;
-};
+}
int Bank::getBalanceForAccountType(const Uint32 accountType,
@@ -342,8 +342,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType,
return NDBT_FAILED;
}
- NdbResultSet* rs = pOp->readTuples();
- if( rs == 0 ) {
+ if( pOp->readTuples() ) {
ERR(pScanTrans->getNdbError());
m_ndb.closeTransaction(pScanTrans);
return NDBT_FAILED;
@@ -379,7 +378,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType,
int eof;
int rows = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
while(eof == 0){
rows++;
@@ -391,7 +390,7 @@ int Bank::getBalanceForAccountType(const Uint32 accountType,
balance += b;
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
ERR(pScanTrans->getNdbError());
@@ -460,7 +459,7 @@ int Bank::loadAccountType(){
m_ndb.closeTransaction(pTrans);
return NDBT_OK;
-};
+}
/**
* Load ACCOUNT table
diff --git a/ndb/test/ndbapi/bank/bankCreator.cpp b/ndb/test/ndbapi/bank/bankCreator.cpp
index 301d8bda6d2..257255babc8 100644
--- a/ndb/test/ndbapi/bank/bankCreator.cpp
+++ b/ndb/test/ndbapi/bank/bankCreator.cpp
@@ -43,7 +43,13 @@ int main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Bank bank;
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Bank bank(con);
int overWriteExisting = true;
if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK)
return NDBT_ProgramExit(NDBT_FAILED);
diff --git a/ndb/test/ndbapi/bank/bankMakeGL.cpp b/ndb/test/ndbapi/bank/bankMakeGL.cpp
index 9e2762ed8ae..cf373481e3e 100644
--- a/ndb/test/ndbapi/bank/bankMakeGL.cpp
+++ b/ndb/test/ndbapi/bank/bankMakeGL.cpp
@@ -43,7 +43,13 @@ int main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Bank bank;
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Bank bank(con);
if (bank.performMakeGLs() != 0)
return NDBT_ProgramExit(NDBT_FAILED);
diff --git a/ndb/test/ndbapi/bank/bankSumAccounts.cpp b/ndb/test/ndbapi/bank/bankSumAccounts.cpp
index b576161b27b..034f70f8f95 100644
--- a/ndb/test/ndbapi/bank/bankSumAccounts.cpp
+++ b/ndb/test/ndbapi/bank/bankSumAccounts.cpp
@@ -43,7 +43,13 @@ int main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Bank bank;
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Bank bank(con);
if (bank.performSumAccounts() != 0)
return NDBT_ProgramExit(NDBT_FAILED);
diff --git a/ndb/test/ndbapi/bank/bankTimer.cpp b/ndb/test/ndbapi/bank/bankTimer.cpp
index 874afd9c21e..298f85e1e43 100644
--- a/ndb/test/ndbapi/bank/bankTimer.cpp
+++ b/ndb/test/ndbapi/bank/bankTimer.cpp
@@ -46,7 +46,13 @@ int main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Bank bank;
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Bank bank(con);
if (bank.performIncreaseTime(_wait) != 0)
return NDBT_ProgramExit(NDBT_FAILED);
diff --git a/ndb/test/ndbapi/bank/bankTransactionMaker.cpp b/ndb/test/ndbapi/bank/bankTransactionMaker.cpp
index e5ff9aeb918..f8e646b6553 100644
--- a/ndb/test/ndbapi/bank/bankTransactionMaker.cpp
+++ b/ndb/test/ndbapi/bank/bankTransactionMaker.cpp
@@ -46,7 +46,13 @@ int main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Bank bank;
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Bank bank(con);
if (bank.performTransactions(_wait) != 0)
return NDBT_ProgramExit(NDBT_FAILED);
diff --git a/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp b/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp
index cf298ecc8e3..0c268121d8a 100644
--- a/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp
+++ b/ndb/test/ndbapi/bank/bankValidateAllGLs.cpp
@@ -44,7 +44,13 @@ int main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Bank bank;
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Bank bank(con);
if (bank.performValidateAllGLs() != 0)
return NDBT_ProgramExit(NDBT_FAILED);
diff --git a/ndb/test/ndbapi/bank/testBank.cpp b/ndb/test/ndbapi/bank/testBank.cpp
index 3ef2799cd3c..6be66d528b1 100644
--- a/ndb/test/ndbapi/bank/testBank.cpp
+++ b/ndb/test/ndbapi/bank/testBank.cpp
@@ -32,7 +32,7 @@
#include "Bank.hpp"
int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int overWriteExisting = true;
if (bank.createAndLoadBank(overWriteExisting) != NDBT_OK)
return NDBT_FAILED;
@@ -40,7 +40,7 @@ int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int wait = 30; // Max seconds between each "day"
int yield = 1; // Loops before bank returns
@@ -51,7 +51,7 @@ int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int wait = 10; // Max ms between each transaction
int yield = 100; // Loops before bank returns
@@ -62,7 +62,7 @@ int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int yield = 20; // Loops before bank returns
int result = NDBT_OK;
@@ -76,7 +76,7 @@ int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int wait = 2000; // Max ms between each sum of accounts
int yield = 1; // Loops before bank returns
int result = NDBT_OK;
@@ -91,7 +91,7 @@ int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
}
int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
if (bank.dropBank() != NDBT_OK)
return NDBT_FAILED;
return NDBT_OK;
diff --git a/ndb/test/ndbapi/bench/userInterface.cpp b/ndb/test/ndbapi/bench/userInterface.cpp
index 683552c3133..35e88183230 100644
--- a/ndb/test/ndbapi/bench/userInterface.cpp
+++ b/ndb/test/ndbapi/bench/userInterface.cpp
@@ -173,7 +173,7 @@ create_table_server(Ndb * pNdb){
String,
MMBased,
NotNullAttribute,
- NormalStorageAttribute,
+ 0,
0,
1,
16);
@@ -376,7 +376,7 @@ create_table_subscriber(Ndb * pNdb){
String,
MMBased,
NotNullAttribute,
- NormalStorageAttribute,
+ 0,
0,
1,
16);
@@ -494,7 +494,7 @@ create_table_session(Ndb * pNdb){
String,
MMBased,
NotNullAttribute,
- NormalStorageAttribute,
+ 0,
0,
1,
16);
diff --git a/ndb/test/ndbapi/bench/userInterface.h b/ndb/test/ndbapi/bench/userInterface.h
index 9e3b6f8f2a5..bad61fcf171 100644
--- a/ndb/test/ndbapi/bench/userInterface.h
+++ b/ndb/test/ndbapi/bench/userInterface.h
@@ -101,7 +101,7 @@ extern "C" {
typedef struct {
struct Ndb_cluster_connection* pNCC;
struct Ndb * pNDB;
- struct NdbConnection * pCurrTrans;
+ struct NdbTransaction * pCurrTrans;
} UserHandle;
/***************************************************************
diff --git a/ndb/test/ndbapi/create_all_tabs.cpp b/ndb/test/ndbapi/create_all_tabs.cpp
index 97236b98b36..f06078d67a2 100644
--- a/ndb/test/ndbapi/create_all_tabs.cpp
+++ b/ndb/test/ndbapi/create_all_tabs.cpp
@@ -47,7 +47,12 @@ int main(int argc, const char** argv){
}
// Connect to Ndb
- Ndb MyNdb( "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/ndbapi/create_tab.cpp b/ndb/test/ndbapi/create_tab.cpp
index 283c83d30e0..b35c8655236 100644
--- a/ndb/test/ndbapi/create_tab.cpp
+++ b/ndb/test/ndbapi/create_tab.cpp
@@ -77,8 +77,12 @@ int main(int argc, const char** argv){
*/
// Connect to Ndb
- Ndb::setConnectString(_connectstr);
- Ndb MyNdb( "TEST_DB" );
+ Ndb_cluster_connection con(_connectstr);
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/ndbapi/drop_all_tabs.cpp b/ndb/test/ndbapi/drop_all_tabs.cpp
index c024a81a5e6..f12d750916e 100644
--- a/ndb/test/ndbapi/drop_all_tabs.cpp
+++ b/ndb/test/ndbapi/drop_all_tabs.cpp
@@ -40,7 +40,13 @@ int main(int argc, const char** argv){
}
// Connect to Ndb
- Ndb MyNdb( "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Ndb MyNdb(&con, "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/ndbapi/flexAsynch.cpp b/ndb/test/ndbapi/flexAsynch.cpp
index 4b87b2c70ed..8a7dbec1561 100644
--- a/ndb/test/ndbapi/flexAsynch.cpp
+++ b/ndb/test/ndbapi/flexAsynch.cpp
@@ -16,6 +16,7 @@
+#include <ndb_global.h>
#include "NdbApi.hpp"
#include <NdbSchemaCon.hpp>
#include <NdbMain.h>
@@ -143,6 +144,8 @@ tellThreads(StartType what)
ThreadStart[i] = what;
}
+static Ndb_cluster_connection *g_cluster_connection= 0;
+
NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
{
ndb_init();
@@ -200,7 +203,14 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
setAttrNames();
setTableNames();
- Ndb * pNdb = new Ndb("TEST_DB");
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ g_cluster_connection= &con;
+
+ Ndb * pNdb = new Ndb(g_cluster_connection, "TEST_DB");
pNdb->init();
tNodeId = pNdb->getNodeId();
@@ -225,7 +235,7 @@ NDB_COMMAND(flexAsynch, "flexAsynch", "flexAsynch", "flexAsynch", 65535)
* Create NDB objects. *
****************************************************************/
resetThreads();
- for (int i = 0; i < tNoOfThreads ; i++) {
+ for (i = 0; i < tNoOfThreads ; i++) {
pThreadData[i].ThreadNo = i
;
threadLife[i] = NdbThread_Create(threadLoop,
@@ -468,7 +478,7 @@ threadLoop(void* ThreadData)
StartType tType;
ThreadNdb* tabThread = (ThreadNdb*)ThreadData;
int threadNo = tabThread->ThreadNo;
- localNdb = new Ndb("TEST_DB");
+ localNdb = new Ndb(g_cluster_connection, "TEST_DB");
localNdb->init(1024);
localNdb->waitUntilReady(10000);
unsigned int threadBase = (threadNo << 16) + tNodeId ;
diff --git a/ndb/test/ndbapi/flexBench.cpp b/ndb/test/ndbapi/flexBench.cpp
index cc2bfb391da..abddecfdc40 100644
--- a/ndb/test/ndbapi/flexBench.cpp
+++ b/ndb/test/ndbapi/flexBench.cpp
@@ -49,6 +49,7 @@ Arguments:
* *************************************************** */
+#include <ndb_global.h>
#include "NdbApi.hpp"
#include <NdbMain.h>
@@ -279,6 +280,8 @@ tellThreads(ThreadData* pt, StartType what)
pt[i].threadStart = what;
}
+static Ndb_cluster_connection *g_cluster_connection= 0;
+
NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
{
ndb_init();
@@ -326,8 +329,16 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ g_cluster_connection= &con;
+
Ndb* pNdb;
- pNdb = new Ndb( "TEST_DB" );
+ pNdb = new Ndb(&con, "TEST_DB" );
pNdb->init();
tNodeId = pNdb->getNodeId();
@@ -605,7 +616,7 @@ static void* flexBenchThread(void* pArg)
attrValue = (int*)malloc(nReadBuffSize) ;
attrRefValue = (int*)malloc(nRefBuffSize) ;
pOps = (NdbOperation**)malloc(tNoOfTables*sizeof(NdbOperation*)) ;
- pNdb = new Ndb( "TEST_DB" );
+ pNdb = new Ndb(g_cluster_connection, "TEST_DB" );
if(!attrValue || !attrRefValue || !pOps || !pNdb){
// Check allocations to make sure we got all the memory we asked for
diff --git a/ndb/test/ndbapi/flexHammer.cpp b/ndb/test/ndbapi/flexHammer.cpp
index 13cd2d5e561..f254b1e5ccf 100644
--- a/ndb/test/ndbapi/flexHammer.cpp
+++ b/ndb/test/ndbapi/flexHammer.cpp
@@ -47,6 +47,7 @@ Revision history:
* *************************************************** */
+#include <ndb_global.h>
#include <NdbApi.hpp>
#include <NdbMain.h>
@@ -174,6 +175,8 @@ tellThreads(ThreadNdb* threadArrayP, const StartType what)
threadArrayP[i].threadStart = what;
} // for
} // tellThreads
+
+static Ndb_cluster_connection *g_cluster_connection= 0;
NDB_COMMAND(flexHammer, "flexHammer", "flexHammer", "flexHammer", 65535)
//main(int argc, const char** argv)
@@ -213,7 +216,13 @@ NDB_COMMAND(flexHammer, "flexHammer", "flexHammer", "flexHammer", 65535)
// NdbThread_SetConcurrencyLevel(tNoOfThreads + 2);
// Create and init Ndb object
- pMyNdb = new Ndb("TEST_DB");
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ g_cluster_connection= &con;
+ pMyNdb = new Ndb(g_cluster_connection, "TEST_DB");
pMyNdb->init();
// Wait for Ndb to become ready
@@ -345,7 +354,7 @@ flexHammerThread(void* pArg)
for (i = 0; i < MAXATTRSIZE; i++)
attrValue[i] = 0;
// Ndb object for each thread
- pMyNdb = new Ndb( "TEST_DB" );
+ pMyNdb = new Ndb(g_cluster_connection, "TEST_DB" );
pMyNdb->init();
if (pMyNdb->waitUntilReady(10000) != 0) {
// Error, NDB is not ready
diff --git a/ndb/test/ndbapi/flexTT.cpp b/ndb/test/ndbapi/flexTT.cpp
index 8d5be2bb399..7cd5ac8e3b4 100644
--- a/ndb/test/ndbapi/flexTT.cpp
+++ b/ndb/test/ndbapi/flexTT.cpp
@@ -169,6 +169,8 @@ tellThreads(StartType what)
ThreadStart[i] = what;
}
+static Ndb_cluster_connection *g_cluster_connection= 0;
+
NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535)
{
ndb_init();
@@ -226,7 +228,14 @@ NDB_COMMAND(flexTT, "flexTT", "flexTT", "flexTT", 65535)
setAttrNames();
setTableNames();
- Ndb * pNdb = new Ndb("TEST_DB");
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ g_cluster_connection= &con;
+
+ Ndb * pNdb = new Ndb(g_cluster_connection, "TEST_DB");
pNdb->init();
tNodeId = pNdb->getNodeId();
@@ -334,7 +343,7 @@ threadLoop(void* ThreadData)
void * mem = malloc(sizeof(TransNdb)*tNoOfParallelTrans);
TransNdb* pTransData = (TransNdb*)mem;
- localNdb = new Ndb("TEST_DB");
+ localNdb = new Ndb(g_cluster_connection, "TEST_DB");
localNdb->init(1024);
localNdb->waitUntilReady();
diff --git a/ndb/test/ndbapi/flex_bench_mysql.cpp b/ndb/test/ndbapi/flex_bench_mysql.cpp
index c15175bfb00..3efb7ee2094 100644
--- a/ndb/test/ndbapi/flex_bench_mysql.cpp
+++ b/ndb/test/ndbapi/flex_bench_mysql.cpp
@@ -397,6 +397,7 @@ NDB_COMMAND(flexBench, "flexBench", "flexBench", "flexbench", 65535)
ndbout << "Connect failed" <<endl;
returnValue = NDBT_FAILED;
}
+ mysql.reconnect= 1;
}
if(returnValue == NDBT_OK){
mysql_set_server_option(&mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON);
@@ -712,6 +713,7 @@ static void* flexBenchThread(void* pArg)
ndbout << "failed" << endl;
return 0;
}
+ mysql.reconnect= 1;
ndbout << "ok" << endl;
int r;
diff --git a/ndb/test/ndbapi/slow_select.cpp b/ndb/test/ndbapi/slow_select.cpp
index 625dbc34457..8d615fa5771 100644
--- a/ndb/test/ndbapi/slow_select.cpp
+++ b/ndb/test/ndbapi/slow_select.cpp
@@ -1,4 +1,5 @@
+#include <ndb_global.h>
#include <NdbApi.hpp>
#include <NdbOut.hpp>
#include <NdbTick.h>
@@ -8,18 +9,17 @@ S_Scan {
const char * m_table;
const char * m_index;
NdbIndexScanOperation * m_scan;
- NdbResultSet * m_result;
Uint32 metaid;
Uint32 match_count;
Uint32 row_count;
};
static S_Scan g_scans[] = {
- { "affiliatestometa", "ind_affiliatestometa", 0, 0, 0, 0, 0 },
- { "media", "metaid", 0, 0, 0, 0, 0 },
- { "meta", "PRIMARY", 0, 0, 0, 0, 0 },
- { "artiststometamap", "PRIMARY", 0, 0, 0, 0, 0 },
- { "subgenrestometamap", "metaid", 0, 0, 0, 0, 0 }
+ { "affiliatestometa", "ind_affiliatestometa", 0, 0, 0, 0 },
+ { "media", "metaid", 0, 0, 0, 0 },
+ { "meta", "PRIMARY", 0, 0, 0, 0 },
+ { "artiststometamap", "PRIMARY", 0, 0, 0, 0 },
+ { "subgenrestometamap", "metaid", 0, 0, 0, 0 }
};
#define require(x) if(!(x)) { ndbout << "LINE: " << __LINE__ << endl;abort(); }
@@ -37,7 +37,14 @@ static void lookup();
int
main(void){
ndb_init();
- Ndb g_ndb("test");
+
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return 1;
+ }
+
+ Ndb g_ndb(&con, "test");
g_ndb.init(1024);
require(g_ndb.waitUntilReady() == 0);
@@ -58,9 +65,8 @@ main(void){
g_scans[i].m_table);
NdbIndexScanOperation* scan = g_scans[i].m_scan;
require(scan);
- g_scans[i].m_result = scan->readTuples(NdbScanOperation::LM_CommittedRead,
- 0, 0, true);
- require(g_scans[i].m_result);
+ require(scan->readTuples(NdbScanOperation::LM_CommittedRead,
+ 0, 0, true) == 0);
}
require(!g_scans[0].m_scan->setBound((Uint32)0,
@@ -125,7 +131,7 @@ main(void){
//ndbout_c("%s - %d", g_scans[i].m_table, g_scans[i].metaid);
for(i = 0; i<prev_F_sz; i++){
- int res = F[i]->m_result->nextResult();
+ int res = F[i]->m_scan->nextResult();
if(res == -1)
abort();
diff --git a/ndb/test/ndbapi/testBackup.cpp b/ndb/test/ndbapi/testBackup.cpp
index 14198c250c7..1ab348e735f 100644
--- a/ndb/test/ndbapi/testBackup.cpp
+++ b/ndb/test/ndbapi/testBackup.cpp
@@ -271,7 +271,7 @@ int runDropTable(NDBT_Context* ctx, NDBT_Step* step){
#include "bank/Bank.hpp"
int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int overWriteExisting = true;
if (bank.createAndLoadBank(overWriteExisting, 10) != NDBT_OK)
return NDBT_FAILED;
@@ -279,7 +279,7 @@ int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int wait = 30; // Max seconds between each "day"
int yield = 1; // Loops before bank returns
@@ -290,7 +290,7 @@ int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int wait = 10; // Max ms between each transaction
int yield = 100; // Loops before bank returns
@@ -301,7 +301,7 @@ int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int yield = 20; // Loops before bank returns
int result = NDBT_OK;
@@ -315,7 +315,7 @@ int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int wait = 2000; // Max ms between each sum of accounts
int yield = 1; // Loops before bank returns
int result = NDBT_OK;
@@ -330,7 +330,7 @@ int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
}
int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
if (bank.dropBank() != NDBT_OK)
return NDBT_FAILED;
return NDBT_OK;
@@ -404,7 +404,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){
// To erase all tables from cache(s)
// To be removed, maybe replaced by ndb.invalidate();
{
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
if (bank.dropBank() != NDBT_OK){
result = NDBT_FAILED;
@@ -427,7 +427,7 @@ int runRestoreBankAndVerify(NDBT_Context* ctx, NDBT_Step* step){
ndbout << "Backup " << backupId << " restored" << endl;
// Let bank verify
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int wait = 0;
int yield = 1;
diff --git a/ndb/test/ndbapi/testBitfield.cpp b/ndb/test/ndbapi/testBitfield.cpp
new file mode 100644
index 00000000000..e26f495f5a4
--- /dev/null
+++ b/ndb/test/ndbapi/testBitfield.cpp
@@ -0,0 +1,198 @@
+
+#include <ndb_global.h>
+#include <ndb_opts.h>
+#include <NDBT.hpp>
+#include <NdbApi.hpp>
+#include <HugoTransactions.hpp>
+
+static const char* _dbname = "TEST_DB";
+static int g_loops = 7;
+
+static void usage()
+{
+ ndb_std_print_version();
+}
+#if 0
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ const char *argument)
+{
+ return ndb_std_get_one_option(optid, opt, argument ? argument :
+ "d:t:O,/tmp/testBitfield.trace");
+}
+#endif
+
+static const NdbDictionary::Table* create_random_table(Ndb*);
+static int transactions(Ndb*, const NdbDictionary::Table* tab);
+static int unique_indexes(Ndb*, const NdbDictionary::Table* tab);
+static int ordered_indexes(Ndb*, const NdbDictionary::Table* tab);
+static int node_restart(Ndb*, const NdbDictionary::Table* tab);
+static int system_restart(Ndb*, const NdbDictionary::Table* tab);
+
+int
+main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+ int ho_error;
+
+ argc--;
+ argv++;
+
+ Ndb_cluster_connection con(opt_connect_str);
+ if(con.connect(12, 5, 1))
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+
+ Ndb* pNdb;
+ pNdb = new Ndb(&con, _dbname);
+ pNdb->init();
+ while (pNdb->waitUntilReady() != 0);
+ int res = NDBT_FAILED;
+
+ NdbDictionary::Dictionary * dict = pNdb->getDictionary();
+
+ const NdbDictionary::Table* pTab = 0;
+ for (int i = 0; i < (argc ? argc : g_loops) ; i++)
+ {
+ res = NDBT_FAILED;
+ if(argc == 0)
+ {
+ pTab = create_random_table(pNdb);
+ }
+ else
+ {
+ dict->dropTable(argv[i]);
+ NDBT_Tables::createTable(pNdb, argv[i]);
+ pTab = dict->getTable(argv[i]);
+ }
+
+ if (pTab == 0)
+ {
+ ndbout << "Failed to create table" << endl;
+ ndbout << dict->getNdbError() << endl;
+ break;
+ }
+
+ if(transactions(pNdb, pTab))
+ break;
+
+ if(unique_indexes(pNdb, pTab))
+ break;
+
+ if(ordered_indexes(pNdb, pTab))
+ break;
+
+ if(node_restart(pNdb, pTab))
+ break;
+
+ if(system_restart(pNdb, pTab))
+ break;
+
+ dict->dropTable(pTab->getName());
+ res = NDBT_OK;
+ }
+
+ if(res != NDBT_OK && pTab)
+ {
+ dict->dropTable(pTab->getName());
+ }
+
+ delete pNdb;
+ return NDBT_ProgramExit(res);
+}
+
+static
+const NdbDictionary::Table*
+create_random_table(Ndb* pNdb)
+{
+ do {
+ NdbDictionary::Table tab;
+ Uint32 cols = 1 + (rand() % (NDB_MAX_ATTRIBUTES_IN_TABLE - 1));
+ Uint32 keys = NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY;
+ Uint32 length = 4090;
+ Uint32 key_size = NDB_MAX_KEYSIZE_IN_WORDS;
+
+ BaseString name;
+ name.assfmt("TAB_%d", rand() & 65535);
+ tab.setName(name.c_str());
+ for(int i = 0; i<cols && length > 2; i++)
+ {
+ NdbDictionary::Column col;
+ name.assfmt("COL_%d", i);
+ col.setName(name.c_str());
+ if(i == 0 || i == 1)
+ {
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setLength(1);
+ col.setNullable(false);
+ col.setPrimaryKey(i == 0);
+ tab.addColumn(col);
+ continue;
+ }
+
+ col.setType(NdbDictionary::Column::Bit);
+
+ Uint32 len = 1 + (rand() % (length - 1));
+ col.setLength(len); length -= len;
+ int nullable = (rand() >> 16) & 1;
+ col.setNullable(nullable); length -= nullable;
+ col.setPrimaryKey(false);
+ tab.addColumn(col);
+ }
+
+ pNdb->getDictionary()->dropTable(tab.getName());
+ if(pNdb->getDictionary()->createTable(tab) == 0)
+ {
+ ndbout << (NDBT_Table&)tab << endl;
+ return pNdb->getDictionary()->getTable(tab.getName());
+ }
+ } while(0);
+ return 0;
+}
+
+static
+int
+transactions(Ndb* pNdb, const NdbDictionary::Table* tab)
+{
+ int i = 0;
+ HugoTransactions trans(* tab);
+ i |= trans.loadTable(pNdb, 1000);
+ i |= trans.pkReadRecords(pNdb, 1000, 13);
+ i |= trans.scanReadRecords(pNdb, 1000, 25);
+ i |= trans.pkUpdateRecords(pNdb, 1000, 37);
+ i |= trans.scanUpdateRecords(pNdb, 1000, 25);
+ i |= trans.pkDelRecords(pNdb, 500, 23);
+ i |= trans.clearTable(pNdb);
+ return i;
+}
+
+static
+int
+unique_indexes(Ndb* pNdb, const NdbDictionary::Table* tab)
+{
+ return 0;
+}
+
+static
+int
+ordered_indexes(Ndb* pNdb, const NdbDictionary::Table* tab)
+{
+ return 0;
+}
+
+static
+int
+node_restart(Ndb* pNdb, const NdbDictionary::Table* tab)
+{
+ return 0;
+}
+
+static
+int
+system_restart(Ndb* pNdb, const NdbDictionary::Table* tab)
+{
+ return 0;
+}
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
index efbdceac5a6..a88d7d21820 100644
--- a/ndb/test/ndbapi/testBlobs.cpp
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -23,14 +23,13 @@
#include <NdbOut.hpp>
#include <NdbTest.hpp>
#include <NdbTick.h>
-#include <ndb/src/ndbapi/NdbBlobImpl.hpp>
struct Bcol {
bool m_nullable;
unsigned m_inline;
unsigned m_partsize;
unsigned m_stripe;
- char m_btname[NdbBlobImpl::BlobTableNameSize];
+ char m_btname[200];
Bcol(bool a, unsigned b, unsigned c, unsigned d) :
m_nullable(a),
m_inline(b),
@@ -741,10 +740,9 @@ verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists)
NdbRecAttr* ra_pk;
NdbRecAttr* ra_part;
NdbRecAttr* ra_data;
- NdbResultSet* rs;
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_ops = g_con->getNdbScanOperation(b.m_btname)) != 0);
- CHK((rs = g_ops->readTuples()) != 0);
+ CHK(g_ops->readTuples() == 0);
CHK((ra_pk = g_ops->getValue("PK")) != 0);
CHK((ra_part = g_ops->getValue("PART")) != 0);
CHK((ra_data = g_ops->getValue("DATA")) != 0);
@@ -758,7 +756,7 @@ verifyBlobTable(const Bcol& b, const Bval& v, Uint32 pk1, bool exists)
memset(seen, 0, partcount);
while (1) {
int ret;
- CHK((ret = rs->nextResult()) == 0 || ret == 1);
+ CHK((ret = g_ops->nextResult()) == 0 || ret == 1);
if (ret == 1)
break;
if (pk1 != ra_pk->u_32_value())
@@ -1106,14 +1104,13 @@ readScan(int style, bool idx)
DBG("--- " << "readScan" << (idx ? "Idx" : "") << " " << stylename[style] << " ---");
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->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0);
+ CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 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);
@@ -1129,7 +1126,7 @@ readScan(int style, bool idx)
int ret;
tup.m_pk1 = (Uint32)-1;
memset(tup.m_pk2, 'x', g_opt.m_pk2len);
- CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+ CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
DBG("readScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1);
@@ -1159,14 +1156,13 @@ updateScan(int style, bool idx)
DBG("--- " << "updateScan" << (idx ? "Idx" : "") << " " << stylename[style] << " ---");
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->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 0);
+ CHK(g_ops->readTuples(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);
@@ -1176,7 +1172,7 @@ updateScan(int style, bool idx)
int ret;
tup.m_pk1 = (Uint32)-1;
memset(tup.m_pk2, 'x', g_opt.m_pk2len);
- CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+ CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
DBG("updateScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1);
@@ -1185,7 +1181,7 @@ updateScan(int style, bool idx)
// calculate new blob values
calcBval(g_tups[k], false);
tup.copyfrom(g_tups[k]);
- CHK((g_opr = rs->updateTuple()) != 0);
+ CHK((g_opr = g_ops->updateCurrentTuple()) != 0);
CHK(getBlobHandles(g_opr) == 0);
if (style == 0) {
CHK(setBlobValue(tup) == 0);
@@ -1212,14 +1208,13 @@ deleteScan(bool idx)
{
DBG("--- " << "deleteScan" << (idx ? "Idx" : "") << " ---");
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->getNdbIndexScanOperation(g_opt.m_x2name, g_opt.m_tname)) != 0);
}
- CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Exclusive)) != 0);
+ CHK(g_ops->readTuples(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);
@@ -1229,11 +1224,11 @@ deleteScan(bool idx)
int ret;
tup.m_pk1 = (Uint32)-1;
memset(tup.m_pk2, 'x', g_opt.m_pk2len);
- CHK((ret = rs->nextResult()) == 0 || ret == 1);
+ CHK((ret = g_ops->nextResult()) == 0 || ret == 1);
if (ret == 1)
break;
DBG("deleteScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1);
- CHK(rs->deleteTuple() == 0);
+ CHK(g_ops->deleteCurrentTuple() == 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);
@@ -1611,12 +1606,11 @@ testperf()
// scan read char
{
DBG("--- scan read char ---");
- NdbResultSet* rs;
Uint32 a;
char b[20];
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0);
- CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0);
+ CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 0);
CHK(g_ops->getValue(cA, (char*)&a) != 0);
CHK(g_ops->getValue(cB, b) != 0);
CHK(g_con->execute(NoCommit) == 0);
@@ -1626,7 +1620,7 @@ testperf()
a = (Uint32)-1;
b[0] = 0;
int ret;
- CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+ CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
CHK(a < g_opt.m_rowsperf && strcmp(b, "b") == 0);
@@ -1641,12 +1635,11 @@ testperf()
// scan read text
{
DBG("--- read text ---");
- NdbResultSet* rs;
Uint32 a;
char c[20];
CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0);
- CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0);
+ CHK(g_ops->readTuples(NdbScanOperation::LM_Read) == 0);
CHK(g_ops->getValue(cA, (char*)&a) != 0);
CHK((g_bh1 = g_ops->getBlobHandle(cC)) != 0);
CHK(g_con->execute(NoCommit) == 0);
@@ -1656,7 +1649,7 @@ testperf()
a = (Uint32)-1;
c[0] = 0;
int ret;
- CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+ CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
Uint32 m = 20;
diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp
index 03d52252334..aaecb6ee61e 100644
--- a/ndb/test/ndbapi/testDataBuffers.cpp
+++ b/ndb/test/ndbapi/testDataBuffers.cpp
@@ -209,7 +209,7 @@ makeOff(int k)
}
static int
-testcase(int flag)
+testcase(Ndb_cluster_connection&cc, int flag)
{
ndbout << "--- case " << flag << " ---" << endl;
sprintf(tab, "TB%02d", flag);
@@ -254,7 +254,7 @@ testcase(int flag)
ndbout << "tab=" << tab << " cols=" << attrcnt
<< " size max=" << smax << " tot=" << stot << endl;
- ndb = new Ndb("TEST_DB");
+ ndb = new Ndb(&cc, "TEST_DB");
if (ndb->init() != 0)
return ndberror("init");
if (ndb->waitUntilReady(30) < 0)
@@ -443,9 +443,9 @@ testcase(int flag)
if ((con = ndb->startTransaction()) == 0)
return ndberror("startTransaction key=%d", key);
if ((op = sop = con->getNdbScanOperation(tab)) == 0)
- return ndberror("getNdbOperation key=%d", key);
- if ((rs = sop->readTuples(1)) == 0)
- return ndberror("openScanRead key=%d", key);
+ return ndberror("getNdbOperation key=%d", key);
+ if (sop->readTuples(1))
+ return ndberror("openScanRead key=%d", key);
{
col& c = ccol[0];
if (op->load_const_u32(1, key) < 0)
@@ -488,7 +488,7 @@ testcase(int flag)
if (con->execute(NoCommit) < 0)
return ndberror("executeScan key=%d", key);
int ret, cnt = 0;
- while ((ret = rs->nextResult()) == 0) {
+ while ((ret = sop->nextResult()) == 0) {
if (key != newkey)
return ndberror("unexpected key=%d newkey=%d", key, newkey);
for (i = 1; i < attrcnt; i++) {
@@ -606,10 +606,17 @@ NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuff
}
}
unsigned ok = true;
+
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1))
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
for (i = 1; 0 == loopcnt || i <= loopcnt; i++) {
ndbout << "=== loop " << i << " ===" << endl;
for (int flag = 0; flag < (1<<testbits); flag++) {
- if (testcase(flag) < 0) {
+ if (testcase(con, flag) < 0) {
ok = false;
if (! kontinue)
goto out;
diff --git a/ndb/test/ndbapi/testDeadlock.cpp b/ndb/test/ndbapi/testDeadlock.cpp
index eb985e815ac..0070a7ecc83 100644
--- a/ndb/test/ndbapi/testDeadlock.cpp
+++ b/ndb/test/ndbapi/testDeadlock.cpp
@@ -49,7 +49,7 @@ printusage()
static Opt g_opt;
static NdbMutex *ndbout_mutex= NULL;
-
+static Ndb_cluster_connection *g_cluster_connection= 0;
#define DBG(x) \
do { \
if (! g_opt.m_dbg) break; \
@@ -91,7 +91,6 @@ struct Thr {
NdbConnection* m_con;
NdbScanOperation* m_scanop;
NdbIndexScanOperation* m_indexscanop;
- NdbResultSet* m_rs;
//
Thr(int no);
~Thr();
@@ -136,7 +135,6 @@ Thr::Thr(int no)
m_con = 0;
m_scanop = 0;
m_indexscanop = 0;
- m_rs = 0;
}
Thr::~Thr()
@@ -219,7 +217,7 @@ Thr::exit()
static int
runstep_connect(Thr& thr)
{
- Ndb* ndb = thr.m_ndb = new Ndb("TEST_DB");
+ Ndb* ndb = thr.m_ndb = new Ndb(g_cluster_connection, "TEST_DB");
CHN(ndb, ndb->init() == 0);
CHN(ndb, ndb->waitUntilReady() == 0);
DBG(thr << " connected");
@@ -374,7 +372,7 @@ wl1822_tx2_scanXY(Thr& thr)
CHN(con, (scanop = thr.m_scanop = indexscanop = thr.m_indexscanop = con->getNdbIndexScanOperation(g_opt.m_xname, g_opt.m_tname)) != 0);
DBG("tx2 scan exclusive " << g_opt.m_xname);
}
- CHN(scanop, (rs = thr.m_rs = scanop->readTuplesExclusive(16)) != 0);
+ CHN(scanop, scanop->readTuplesExclusive(16) == 0);
CHN(scanop, scanop->getValue("A", (char*)&wl1822_bufA) != 0);
CHN(scanop, scanop->getValue("B", (char*)&wl1822_bufB) != 0);
CHN(con, con->execute(NoCommit) == 0);
@@ -383,7 +381,7 @@ wl1822_tx2_scanXY(Thr& thr)
DBG("before row " << row);
int ret;
wl1822_bufA = wl1822_bufB = ~0;
- CHN(con, (ret = rs->nextResult(true)) == 0);
+ CHN(con, (ret = scanop->nextResult(true)) == 0);
DBG("got row " << row << " a=" << wl1822_bufA << " b=" << wl1822_bufB);
CHK(wl1822_bufA == wl1822_valA[wl1822_r2k[row]]);
CHK(wl1822_bufB == wl1822_valB[wl1822_r2k[row]]);
@@ -419,14 +417,13 @@ wl1822_tx2_scanZ_close(Thr& thr)
Ndb* ndb = thr.m_ndb;
NdbConnection* con = thr.m_con;
NdbScanOperation* scanop = thr.m_scanop;
- NdbResultSet* rs = thr.m_rs;
- assert(ndb != 0 && con != 0 && scanop != 0 && rs != 0);
+ assert(ndb != 0 && con != 0 && scanop != 0);
unsigned row = 2;
while (true) {
DBG("before row " << row);
int ret;
wl1822_bufA = wl1822_bufB = ~0;
- CHN(con, (ret = rs->nextResult(true)) == 0 || ret == 1);
+ CHN(con, (ret = scanop->nextResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
DBG("got row " << row << " a=" << wl1822_bufA << " b=" << wl1822_bufB);
@@ -467,7 +464,7 @@ wl1822_main(char scantx)
// run the steps
for (unsigned i = 0; i < wl1822_stepcount; i++) {
DBG("step " << i << " start");
- for (int n = 0; n < thrcount; n++) {
+ for (n = 0; n < thrcount; n++) {
Thr& thr = *thrlist[n];
Runstep runstep = wl1822_step[i][n];
if (runstep != 0)
@@ -506,10 +503,18 @@ NDB_COMMAND(testOdbcDriver, "testDeadlock", "testDeadlock", "testDeadlock", 6553
printusage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ g_cluster_connection= &con;
+
if (
strchr(g_opt.m_scan, 't') != 0 && wl1822_main('t') == -1 ||
strchr(g_opt.m_scan, 'x') != 0 && wl1822_main('x') == -1
- ) {
+ ) {
return NDBT_ProgramExit(NDBT_FAILED);
}
return NDBT_ProgramExit(NDBT_OK);
diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp
index 5f88342705a..dd5846f0d62 100644
--- a/ndb/test/ndbapi/testDict.cpp
+++ b/ndb/test/ndbapi/testDict.cpp
@@ -125,6 +125,16 @@ int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
+int runDropTheTable(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ // Try to create table in db
+ pNdb->getDictionary()->dropTable(pTab->getName());
+
+ return NDBT_OK;
+}
+
int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
int result = NDBT_OK;
@@ -418,103 +428,99 @@ int runUseTableUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
}
-int runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step){
- int failures = 0;
+int
+runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step)
+{
char tabName[256];
int numTables = ctx->getProperty("tables", 1000);
Ndb* pNdb = GETNDB(step);
-
- for (int i = 0; i < numTables && failures < 5; i++){
+ NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+ int i = 0;
+ for (i = 0; i < numTables; i++) {
BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
-
- if (pNdb->waitUntilReady(30) != 0){
+ if (pNdb->waitUntilReady(30) != 0) {
// Db is not ready, return with failure
return NDBT_FAILED;
}
-
const NdbDictionary::Table* pTab = ctx->getTab();
- ndbout << "|- " << tabName << endl;
-
+ //ndbout << "|- " << tabName << endl;
// Set new name for T1
NdbDictionary::Table newTab(* pTab);
newTab.setName(tabName);
-
+ // Drop any old (or try to)
+ (void)pDic->dropTable(newTab.getName());
// Try to create table in db
- if (newTab.createTableInDb(pNdb) != 0){
- ndbout << tabName << " coult not be created"<< endl;
- failures++;
- continue;
+ if (newTab.createTableInDb(pNdb) != 0) {
+ ndbout << tabName << " could not be created: "
+ << pDic->getNdbError() << endl;
+ if (pDic->getNdbError().code == 707 ||
+ pDic->getNdbError().code == 708 ||
+ pDic->getNdbError().code == 826 ||
+ pDic->getNdbError().code == 827)
+ break;
+ 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;
- failures++;
- continue;
+ ndbout << tabName << " was not found in DB: "
+ << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
}
-
- if (pTab->equal(*pTab3) == false){
- ndbout << "It was not equal" << endl;
- failures++;
+ if (! newTab.equal(*pTab3)) {
+ ndbout << "It was not equal" << endl; abort();
+ return NDBT_FAILED;
}
-
- int records = 1000;
+ int records = ctx->getNumRecords();
HugoTransactions hugoTrans(*pTab3);
- if (hugoTrans.loadTable(pNdb, records) != 0){
+ 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;
- }
+ return NDBT_FAILED;
+ }
+ UtilTransactions utilTrans(*pTab3);
+ if (utilTrans.clearTable(pNdb, records, 64) != 0) {
+ ndbout << "It can NOT be cleared" << endl;
+ return NDBT_FAILED;
}
-
}
- if (pNdb->waitUntilReady(30) != 0){
+ if (pNdb->waitUntilReady(30) != 0) {
// Db is not ready, return with failure
return NDBT_FAILED;
}
+ ctx->setProperty("maxtables", i);
// HURRAAA!
return NDBT_OK;
}
-int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step){
- int result = NDBT_OK;
+int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step)
+{
char tabName[256];
- int numTables = ctx->getProperty("tables", 1000);
+ int numTables = ctx->getProperty("maxtables", (Uint32)0);
Ndb* pNdb = GETNDB(step);
-
- for (int i = 0; i < numTables; i++){
+ NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+ for (int i = 0; i < numTables; i++) {
BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
-
- if (pNdb->waitUntilReady(30) != 0){
+ 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;
+ if (pTab3 == NULL) {
+ ndbout << tabName << " was not found in DB: "
+ << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
}
-
-
// Try to drop table in db
- if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
- ndbout << tabName << " coult not be dropped"<< endl;
- result = NDBT_FAILED;
+ if (pDic->dropTable(pTab3->getName()) != 0) {
+ ndbout << tabName << " could not be dropped: "
+ << pDic->getNdbError() << endl;
+ return NDBT_FAILED;
}
-
}
- return result;
+ return NDBT_OK;
}
int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
@@ -524,13 +530,6 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* 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;
@@ -547,6 +546,7 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
if (newTab.createTableInDb(pNdb) != 0){
ndbout << newTab.getName() << " could not be created"
<< ", fragmentType = "<<fragTtype <<endl;
+ ndbout << pNdb->getDictionary()->getNdbError() << endl;
return NDBT_FAILED;
}
@@ -564,13 +564,17 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
result = NDBT_FAILED;
goto drop_the_tab;
}
-
+/**
+ This test does not work since fragmentation is
+ decided by the kernel, hence the fragementation
+ attribute on the column will differ
+
if (newTab.equal(*pTab3) == false){
ndbout << "It was not equal" << endl;
result = NDBT_FAILED;
goto drop_the_tab;
}
-
+*/
do {
HugoTransactions hugoTrans(*pTab3);
@@ -1005,10 +1009,10 @@ int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){
struct ErrorCodes { int error_id; bool crash;};
ErrorCodes
NF_codes[] = {
- {6003, true},
- {6004, true},
+ {6003, true}
+ ,{6004, true}
//,6005, true,
- {7173, false}
+ //{7173, false}
};
int
@@ -1027,17 +1031,6 @@ runNF1(NDBT_Context* ctx, NDBT_Step* step){
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]);
@@ -1060,7 +1053,7 @@ runNF1(NDBT_Context* ctx, NDBT_Step* step){
CHECK2(dict->createTable(* pTab) == 0,
"failed to create table");
-
+
if (crash) {
CHECK2(restarter.waitNodesNoStart(&nodeId, 1) == 0,
"waitNodesNoStart failed");
@@ -1084,9 +1077,6 @@ runNF1(NDBT_Context* ctx, NDBT_Step* step){
CHECK2(restarter.waitClusterStarted() == 0,
"waitClusterStarted failed");
}
-
- CHECK2(restarter.dumpStateOneNode(nodeId, &val, 1) == 0,
- "Failed to set LCP to min value");
}
}
}
@@ -1583,21 +1573,26 @@ TESTCASE("CreateTableWhenDbIsFull",
INITIALIZER(runFillTable);
INITIALIZER(runCreateTableWhenDbIsFull);
INITIALIZER(runDropTableWhenDbIsFull);
- FINALIZER(runClearTable);
+ FINALIZER(runDropTheTable);
}
TESTCASE("FragmentTypeSingle",
"Create the table with fragment type Single\n"){
- TC_PROPERTY("FragmentType", 1);
+ TC_PROPERTY("FragmentType", NdbDictionary::Table::FragSingle);
+ INITIALIZER(runTestFragmentTypes);
+}
+TESTCASE("FragmentTypeAllSmall",
+ "Create the table with fragment type AllSmall\n"){
+ TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllSmall);
INITIALIZER(runTestFragmentTypes);
}
-TESTCASE("FragmentTypeAll",
- "Create the table with fragment type All\n"){
- TC_PROPERTY("FragmentType", 2);
+TESTCASE("FragmentTypeAllMedium",
+ "Create the table with fragment type AllMedium\n"){
+ TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllMedium);
INITIALIZER(runTestFragmentTypes);
}
TESTCASE("FragmentTypeAllLarge",
"Create the table with fragment type AllLarge\n"){
- TC_PROPERTY("FragmentType", 3);
+ TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllLarge);
INITIALIZER(runTestFragmentTypes);
}
TESTCASE("TemporaryTables",
@@ -1609,7 +1604,7 @@ TESTCASE("CreateMaxTables",
"Create tables until db says that it can't create any more\n"){
TC_PROPERTY("tables", 1000);
INITIALIZER(runCreateMaxTables);
- FINALIZER(runDropMaxTables);
+ INITIALIZER(runDropMaxTables);
}
TESTCASE("PkSizes",
"Create tables with all different primary key sizes.\n"\
diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp
index d359f83257f..5785db232c4 100644
--- a/ndb/test/ndbapi/testIndex.cpp
+++ b/ndb/test/ndbapi/testIndex.cpp
@@ -1145,20 +1145,18 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){
pTrans = pNdb->startTransaction();
NdbScanOperation * sOp;
NdbOperation * uOp;
- NdbResultSet * rs;
int eof;
if(!pTrans) goto done;
sOp = pTrans->getNdbScanOperation(pTab->getName());
if(!sOp) goto done;
- rs = sOp->readTuples(NdbScanOperation::LM_Exclusive);
- if(!rs) goto done;
+ if(sOp->readTuples(NdbScanOperation::LM_Exclusive)) goto done;
if(pTrans->execute(NoCommit) == -1) goto done;
- while((eof = rs->nextResult(true)) == 0){
+ while((eof = sOp->nextResult(true)) == 0){
do {
- NdbOperation * uOp = rs->updateTuple();
+ NdbOperation * uOp = sOp->updateCurrentTuple();
if(uOp == 0) goto done;
uOp->setValue(colId, 0);
- } while((eof = rs->nextResult(false)) == 0);
+ } while((eof = sOp->nextResult(false)) == 0);
eof = pTrans->execute(Commit);
if(eof == -1) goto done;
}
@@ -1279,7 +1277,7 @@ TESTCASE("CreateLoadDrop_O",
TESTCASE("NFNR1",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("LoggedIndexes", (unsigned)0);
- //TC_PROPERTY("Threads", 2);
+ TC_PROPERTY("PauseThreads", 2);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(runLoadTable);
@@ -1294,6 +1292,7 @@ TESTCASE("NFNR1_O",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("OrderedIndex", 1);
TC_PROPERTY("LoggedIndexes", (unsigned)0);
+ TC_PROPERTY("PauseThreads", 2);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(runLoadTable);
@@ -1307,6 +1306,7 @@ TESTCASE("NFNR1_O",
TESTCASE("NFNR2",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("LoggedIndexes", (unsigned)0);
+ TC_PROPERTY("PauseThreads", 2);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(createPkIndex);
@@ -1323,6 +1323,7 @@ TESTCASE("NFNR2_O",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("OrderedIndex", 1);
TC_PROPERTY("LoggedIndexes", (unsigned)0);
+ TC_PROPERTY("PauseThreads", 1);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(createPkIndex);
@@ -1338,6 +1339,7 @@ TESTCASE("NFNR2_O",
TESTCASE("NFNR3",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("LoggedIndexes", (unsigned)0);
+ TC_PROPERTY("PauseThreads", 2);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(createPkIndex);
@@ -1353,6 +1355,7 @@ TESTCASE("NFNR3_O",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("OrderedIndex", 1);
TC_PROPERTY("LoggedIndexes", (unsigned)0);
+ TC_PROPERTY("PauseThreads", 2);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(createPkIndex);
@@ -1367,6 +1370,7 @@ TESTCASE("NFNR3_O",
TESTCASE("NFNR4",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("LoggedIndexes", (unsigned)0);
+ TC_PROPERTY("PauseThreads", 4);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(createPkIndex);
@@ -1385,6 +1389,7 @@ TESTCASE("NFNR4_O",
"Test that indexes are correctly maintained during node fail and node restart"){
TC_PROPERTY("OrderedIndex", 1);
TC_PROPERTY("LoggedIndexes", (unsigned)0);
+ TC_PROPERTY("PauseThreads", 4);
INITIALIZER(runClearTable);
INITIALIZER(createRandomIndex);
INITIALIZER(createPkIndex);
diff --git a/ndb/test/ndbapi/testLcp.cpp b/ndb/test/ndbapi/testLcp.cpp
index d11692db761..8bfc7ccf9b9 100644
--- a/ndb/test/ndbapi/testLcp.cpp
+++ b/ndb/test/ndbapi/testLcp.cpp
@@ -30,6 +30,7 @@ static CASE g_ops[] =
const size_t OP_COUNT = (sizeof(g_ops)/sizeof(g_ops[0]));
static Ndb* g_ndb = 0;
+static Ndb_cluster_connection *g_cluster_connection= 0;
static CASE* g_cases;
static HugoOperations* g_hugo_ops;
@@ -122,6 +123,7 @@ main(int argc, char ** argv){
static int init_ndb(int argc, char** argv)
{
+ ndb_init();
return 0;
}
@@ -132,7 +134,13 @@ static int parse_args(int argc, char** argv)
static int connect_ndb()
{
- g_ndb = new Ndb("TEST_DB");
+ g_cluster_connection = new Ndb_cluster_connection();
+ if(g_cluster_connection->connect(12, 5, 1) != 0)
+ {
+ return 1;
+ }
+
+ g_ndb = new Ndb(g_cluster_connection, "TEST_DB");
g_ndb->init();
if(g_ndb->waitUntilReady(30) == 0){
int args[] = { DumpStateOrd::DihMaxTimeBetweenLCP };
@@ -144,8 +152,10 @@ static int connect_ndb()
static int disconnect_ndb()
{
delete g_ndb;
+ delete g_cluster_connection;
g_ndb = 0;
g_table = 0;
+ g_cluster_connection= 0;
return 0;
}
diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp
index 3a06269f8dc..f456d852898 100644
--- a/ndb/test/ndbapi/testNdbApi.cpp
+++ b/ndb/test/ndbapi/testNdbApi.cpp
@@ -56,7 +56,7 @@ int runTestMaxNdb(NDBT_Context* ctx, NDBT_Step* step){
int init = 0;
do {
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
errors++;
@@ -108,7 +108,7 @@ int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){
int oldi = 0;
int result = NDBT_OK;
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -119,6 +119,9 @@ int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ if (pTab == 0) abort();
+
while (l < loops && result == NDBT_OK){
int errors = 0;
int maxErrors = 5;
@@ -131,39 +134,25 @@ int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){
NdbConnection* pCon;
- int type = i%4;
+ int type = i%2;
switch (type){
case 0:
pCon = pNdb->startTransaction();
break;
case 1:
- pCon = pNdb->startTransaction(2,
- "DATA",
- 4);
- break;
- case 2:
- ndbout_c("startTransactionDGroup not supported");
- abort();
- /*
- pCon = pNdb->startTransactionDGroup(1,
- "TEST",
- 0);
- */
- break;
- case 3:
- ndbout_c("startTransactionDGroup not supported");
- abort();
- /*
- pCon = pNdb->startTransactionDGroup(2,
- "TEST",
- 1);
- */
- break;
-
+ {
+ BaseString key;
+ key.appfmt("DATA-%d", i);
+ ndbout_c("%s", key.c_str());
+ pCon = pNdb->startTransaction(pTab,
+ key.c_str(),
+ key.length());
+ }
+ break;
default:
abort();
}
-
+
if (pCon == NULL){
ERR(pNdb->getNdbError());
errors++;
@@ -209,7 +198,7 @@ int runTestMaxOperations(NDBT_Context* ctx, NDBT_Step* step){
int maxOpsLimit = 1;
const NdbDictionary::Table* pTab = ctx->getTab();
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -281,7 +270,7 @@ int runTestGetValue(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
const NdbDictionary::Table* pTab = ctx->getTab();
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -381,7 +370,7 @@ int runTestEqual(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
const NdbDictionary::Table* pTab = ctx->getTab();
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -502,7 +491,7 @@ int runTestDeleteNdb(NDBT_Context* ctx, NDBT_Step* step){
// Create 5 ndb objects
for( int i = 0; i < 5; i++){
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
result = NDBT_FAILED;
@@ -583,7 +572,7 @@ int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
int runTestWaitUntilReady(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
// Forget about calling pNdb->init();
@@ -604,7 +593,7 @@ int runTestWaitUntilReady(NDBT_Context* ctx, NDBT_Step* step){
int runGetNdbOperationNoTab(NDBT_Context* ctx, NDBT_Step* step){
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -645,7 +634,7 @@ int runMissingOperation(NDBT_Context* ctx, NDBT_Step* step){
const NdbDictionary::Table* pTab = ctx->getTab();
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -695,7 +684,7 @@ int runMissingOperation(NDBT_Context* ctx, NDBT_Step* step){
int runGetValueInUpdate(NDBT_Context* ctx, NDBT_Step* step){
const NdbDictionary::Table* pTab = ctx->getTab();
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -761,7 +750,7 @@ int runUpdateWithoutValues(NDBT_Context* ctx, NDBT_Step* step){
HugoOperations hugoOps(*pTab);
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -807,13 +796,13 @@ int runUpdateWithoutValues(NDBT_Context* ctx, NDBT_Step* step){
// Dont' call any setValues
- // Execute should not work
+ // Execute should work
int check = pCon->execute(Commit);
if (check == 0){
ndbout << "execute worked" << endl;
- result = NDBT_FAILED;
} else {
ERR(pCon->getNdbError());
+ result = NDBT_FAILED;
}
pNdb->closeTransaction(pCon);
@@ -827,7 +816,7 @@ int runUpdateWithoutKeys(NDBT_Context* ctx, NDBT_Step* step){
const NdbDictionary::Table* pTab = ctx->getTab();
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -953,8 +942,7 @@ int runReadWithoutGetValue(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- NdbResultSet *rs;
- if ((rs = pOp->readTuples((NdbOperation::LockMode)lm)) == 0){
+ if ((pOp->readTuples((NdbOperation::LockMode)lm)) != 0){
pNdb->closeTransaction(pCon);
ERR(pOp->getNdbError());
return NDBT_FAILED;
@@ -973,7 +961,7 @@ int runReadWithoutGetValue(NDBT_Context* ctx, NDBT_Step* step){
}
int res;
- while((res = rs->nextResult()) == 0);
+ while((res = pOp->nextResult()) == 0);
pNdb->closeTransaction(pCon);
if(res != 1)
@@ -988,7 +976,7 @@ int runCheckGetNdbErrorOperation(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
const NdbDictionary::Table* pTab = ctx->getTab();
- Ndb* pNdb = new Ndb("TEST_DB");
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
@@ -1049,7 +1037,7 @@ int runCheckGetNdbErrorOperation(NDBT_Context* ctx, NDBT_Step* step){
return result;
}
-#define C2(x) { int _x= (x); if(_x == 0) return NDBT_FAILED; }
+#define C2(x) { int _x= (x); if(_x == 0){ ndbout << "line: " << __LINE__ << endl; return NDBT_FAILED;} }
int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
@@ -1058,7 +1046,6 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){
HugoOperations hugoOps(*pTab);
Ndb* pNdb = GETNDB(step);
-
C2(hugoOps.startTransaction(pNdb) == 0);
C2(hugoOps.pkInsertRecord(pNdb, 0, 1) == 0);
C2(hugoOps.execute_NoCommit(pNdb) == 0);
@@ -1101,7 +1088,7 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){
C2(hugoOps.execute_Commit(pNdb) == 0);
C2(hugoOps.closeTransaction(pNdb) == 0);
- Ndb ndb2("TEST_DB");
+ Ndb ndb2(&ctx->m_cluster_connection, "TEST_DB");
C2(ndb2.init() == 0);
C2(ndb2.waitUntilReady() == 0);
HugoOperations hugoOps2(*pTab);
@@ -1110,8 +1097,8 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){
C2(hugoOps.pkInsertRecord(pNdb, 0, 1) == 0);
C2(hugoOps.execute_NoCommit(pNdb) == 0);
C2(hugoOps2.startTransaction(&ndb2) == 0);
- C2(hugoOps2.pkWriteRecord(&ndb2, 0, 1) == 0);
- C2(hugoOps2.execute_async(&ndb2, NoCommit) == 0);
+ C2(hugoOps2.pkWritePartialRecord(&ndb2, 0) == 0);
+ C2(hugoOps2.execute_async(&ndb2, NdbTransaction::NoCommit) == 0);
C2(hugoOps.execute_Commit(pNdb) == 0);
C2(hugoOps2.wait_async(&ndb2) == 0);
C2(hugoOps.closeTransaction(pNdb) == 0);
@@ -1122,15 +1109,133 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){
C2(hugoOps.execute_NoCommit(pNdb) == 0);
C2(hugoOps2.startTransaction(&ndb2) == 0);
C2(hugoOps2.pkWriteRecord(&ndb2, 0, 1) == 0);
- C2(hugoOps2.execute_async(&ndb2, NoCommit) == 0);
+ C2(hugoOps2.execute_async(&ndb2, NdbTransaction::NoCommit) == 0);
C2(hugoOps.execute_Commit(pNdb) == 0);
C2(hugoOps2.wait_async(&ndb2) == 0);
+ C2(hugoOps2.execute_Commit(pNdb) == 0);
C2(hugoOps.closeTransaction(pNdb) == 0);
C2(hugoOps2.closeTransaction(&ndb2) == 0);
+ C2(hugoOps.startTransaction(pNdb) == 0);
+ C2(hugoOps.pkUpdateRecord(pNdb, 0, 1) == 0);
+ C2(hugoOps.execute_NoCommit(pNdb) == 0);
+ C2(hugoOps2.startTransaction(&ndb2) == 0);
+ C2(hugoOps2.pkWritePartialRecord(&ndb2, 0) == 0);
+ C2(hugoOps2.execute_async(&ndb2, NdbTransaction::NoCommit) == 0);
+ C2(hugoOps.execute_Commit(pNdb) == 0);
+ C2(hugoOps2.wait_async(&ndb2) == 0);
+ C2(hugoOps.closeTransaction(pNdb) == 0);
+ C2(hugoOps2.closeTransaction(&ndb2) == 0);
+
+ C2(hugoOps.startTransaction(pNdb) == 0);
+ C2(hugoOps.pkDeleteRecord(pNdb, 0, 1) == 0);
+ C2(hugoOps.execute_NoCommit(pNdb) == 0);
+ C2(hugoOps2.startTransaction(&ndb2) == 0);
+ C2(hugoOps2.pkWritePartialRecord(&ndb2, 0) == 0);
+ C2(hugoOps2.execute_async(&ndb2, NdbTransaction::NoCommit) == 0);
+ C2(hugoOps.execute_Commit(pNdb) == 0);
+ C2(hugoOps2.wait_async(&ndb2) != 0);
+ C2(hugoOps.closeTransaction(pNdb) == 0);
+ C2(hugoOps2.closeTransaction(&ndb2) == 0);
+
+ return result;
+}
+
+int runScan_4006(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ const Uint32 max= 5;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init(max)){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ Uint32 i;
+ Vector<NdbScanOperation*> scans;
+ for(i = 0; i<10*max; i++)
+ {
+ NdbScanOperation* pOp = pCon->getNdbScanOperation(pTab->getName());
+ if (pOp == NULL){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ if (pOp->readTuples() != 0){
+ pNdb->closeTransaction(pCon);
+ ERR(pOp->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+ scans.push_back(pOp);
+ }
+
+ // Dont' call any equal or setValues
+
+ // Execute should not work
+ int check = pCon->execute(NoCommit);
+ if (check == 0){
+ ndbout << "execute worked" << endl;
+ } else {
+ ERR(pCon->getNdbError());
+ }
+
+ for(i= 0; i<scans.size(); i++)
+ {
+ NdbScanOperation* pOp= scans[i];
+ while((check= pOp->nextResult()) == 0);
+ if(check != 1)
+ {
+ ERR(pOp->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+ }
+
+ pNdb->closeTransaction(pCon);
+
+ Vector<NdbConnection*> cons;
+ for(i= 0; i<10*max; i++)
+ {
+ pCon= pNdb->startTransaction();
+ if(pCon)
+ cons.push_back(pCon);
+ else
+ break;
+ }
+
+ for(i= 0; i<cons.size(); i++)
+ {
+ cons[i]->close();
+ }
+
+ if(cons.size() != max)
+ {
+ result= NDBT_FAILED;
+ }
+
+ delete pNdb;
+
return result;
}
+template class Vector<NdbScanOperation*>;
NDBT_TESTSUITE(testNdbApi);
@@ -1212,6 +1317,12 @@ TESTCASE("Bug_11133",
INITIALIZER(runBug_11133);
FINALIZER(runClearTable);
}
+TESTCASE("Scan_4006",
+ "Check that getNdbScanOperation does not get 4006\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runScan_4006);
+ FINALIZER(runClearTable);
+}
NDBT_TESTSUITE_END(testNdbApi);
int main(int argc, const char** argv){
diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp
index 9c25d715d07..6ef3da2d760 100644
--- a/ndb/test/ndbapi/testNodeRestart.cpp
+++ b/ndb/test/ndbapi/testNodeRestart.cpp
@@ -311,7 +311,7 @@ int runDirtyRead(NDBT_Context* ctx, NDBT_Step* step){
int id = i % restarter.getNumDbNodes();
int nodeId = restarter.getDbNodeId(id);
ndbout << "Restart node " << nodeId << endl;
- restarter.insertErrorInAllNodes(5041);
+ restarter.insertErrorInNode(nodeId, 5041);
restarter.insertErrorInAllNodes(8048 + (i & 1));
for(int j = 0; j<records; j++){
diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp
index 9f8da850ff4..942ee2ec966 100644
--- a/ndb/test/ndbapi/testOIBasic.cpp
+++ b/ndb/test/ndbapi/testOIBasic.cpp
@@ -28,7 +28,10 @@
#include <NdbCondition.h>
#include <NdbThread.h>
#include <NdbTick.h>
+#include <NdbSleep.h>
#include <my_sys.h>
+#include <NdbSqlUtil.hpp>
+#include <ndb_version.h>
// options
@@ -37,6 +40,7 @@ struct Opt {
unsigned m_batch;
const char* m_bound;
const char* m_case;
+ bool m_collsp;
bool m_core;
const char* m_csname;
CHARSET_INFO* m_cs;
@@ -52,20 +56,20 @@ struct Opt {
unsigned m_pctnull;
unsigned m_rows;
unsigned m_samples;
- unsigned m_scanbat;
unsigned m_scanpar;
unsigned m_scanstop;
- unsigned m_seed;
+ int m_seed;
unsigned m_subloop;
const char* m_table;
unsigned m_threads;
- int m_v;
+ int m_v; // int for lint
Opt() :
m_batch(32),
m_bound("01234"),
m_case(0),
+ m_collsp(false),
m_core(false),
- m_csname("latin1_bin"),
+ m_csname("random"),
m_cs(0),
m_die(0),
m_dups(false),
@@ -79,13 +83,12 @@ struct Opt {
m_pctnull(10),
m_rows(1000),
m_samples(0),
- m_scanbat(0),
m_scanpar(0),
m_scanstop(0),
- m_seed(0),
+ m_seed(-1),
m_subloop(4),
m_table(0),
- m_threads(10),
+ m_threads(4),
m_v(1) {
}
};
@@ -104,23 +107,23 @@ printhelp()
<< " -batch N pk operations in batch [" << d.m_batch << "]" << endl
<< " -bound xyz use only these bound types 0-4 [" << d.m_bound << "]" << endl
<< " -case abc only given test cases (letters a-z)" << endl
+ << " -collsp use strnncollsp instead of strnxfrm" << endl
<< " -core core dump on error [" << d.m_core << "]" << endl
- << " -csname S charset (collation) of non-pk char column [" << d.m_csname << "]" << endl
+ << " -csname S charset or collation [" << d.m_csname << "]" << endl
<< " -die nnn exit immediately on NDB error code nnn" << 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
+ << " -index xyz only given index numbers (digits 0-9)" << endl
<< " -loop N loop count full suite 0=forever [" << d.m_loop << "]" << endl
<< " -nologging create tables in no-logging mode" << endl
<< " -noverify skip index verifications" << endl
<< " -pctnull N pct NULL values in nullable column [" << d.m_pctnull << "]" << endl
<< " -rows N rows per thread [" << d.m_rows << "]" << endl
<< " -samples N samples for some timings (0=all) [" << d.m_samples << "]" << endl
- << " -scanbat N scan batch per fragment (ignored by ndb api) [" << d.m_scanbat << "]" << endl
<< " -scanpar N scan parallelism [" << d.m_scanpar << "]" << endl
- << " -seed N srandom seed 0=loop number[" << d.m_seed << "]" << endl
+ << " -seed N srandom seed 0=loop number -1=random [" << d.m_seed << "]" << endl
<< " -subloop N subtest loop count [" << d.m_subloop << "]" << endl
- << " -table xyz only given table numbers (digits 1-9)" << endl
+ << " -table xyz only given table numbers (digits 0-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
@@ -135,9 +138,84 @@ static const bool g_store_null_key = true;
// compare NULL like normal value (NULL < not NULL, NULL == NULL)
static const bool g_compare_null = true;
+static const char* hexstr = "0123456789abcdef";
+
+// random ints
+
+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;
+}
+
+static bool
+randompct(unsigned pct)
+{
+ if (pct == 0)
+ return false;
+ if (pct >= 100)
+ return true;
+ return urandom(100) < pct;
+}
+
+static unsigned
+random_coprime(unsigned n)
+{
+ unsigned prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 };
+ unsigned count = sizeof(prime) / sizeof(prime[0]);
+ if (n == 0)
+ return 0;
+ while (1) {
+ unsigned i = urandom(count);
+ if (n % prime[i] != 0)
+ return prime[i];
+ }
+}
+
+// random re-sequence of 0...(n-1)
+
+struct Rsq {
+ Rsq(unsigned n);
+ unsigned next();
+private:
+ unsigned m_n;
+ unsigned m_i;
+ unsigned m_start;
+ unsigned m_prime;
+};
+
+Rsq::Rsq(unsigned n)
+{
+ m_n = n;
+ m_i = 0;
+ m_start = urandom(n);
+ m_prime = random_coprime(n);
+}
+
+unsigned
+Rsq::next()
+{
+ assert(m_n != 0);
+ return (m_start + m_i++ * m_prime) % m_n;
+}
+
// log and error macros
-static NdbMutex *ndbout_mutex= NULL;
+static NdbMutex *ndbout_mutex = NULL;
static unsigned getthrno();
@@ -198,7 +276,7 @@ getthrstr()
return -1; \
} while (0)
-// method parameters base class
+// method parameters
class Thr;
class Con;
@@ -222,6 +300,8 @@ struct Par : public Opt {
// value calculation
unsigned m_range;
unsigned m_pctrange;
+ unsigned m_pctbrange;
+ int m_bdir;
// choice of key
bool m_randomkey;
// do verify after read
@@ -230,6 +310,11 @@ struct Par : public Opt {
bool m_deadlock;
// abort percentabge
unsigned m_abortpct;
+ NdbOperation::LockMode m_lockmode;
+ // scan options
+ bool m_tupscan;
+ bool m_ordered;
+ bool m_descending;
// timer location
Par(const Opt& opt) :
Opt(opt),
@@ -242,24 +327,30 @@ struct Par : public Opt {
m_slno(0),
m_totrows(m_threads * m_rows),
m_range(m_rows),
- m_pctrange(0),
+ m_pctrange(40),
+ m_pctbrange(80),
+ m_bdir(0),
m_randomkey(false),
m_verify(false),
m_deadlock(false),
- m_abortpct(0) {
+ m_abortpct(0),
+ m_lockmode(NdbOperation::LM_Read),
+ m_tupscan(false),
+ m_ordered(false),
+ m_descending(false) {
}
};
static bool
-usetable(unsigned i)
+usetable(Par par, unsigned i)
{
- return g_opt.m_table == 0 || strchr(g_opt.m_table, '1' + i) != 0;
+ return par.m_table == 0 || strchr(par.m_table, '0' + i) != 0;
}
static bool
-useindex(unsigned i)
+useindex(Par par, unsigned i)
{
- return g_opt.m_index == 0 || strchr(g_opt.m_index, '1' + i) != 0;
+ return par.m_index == 0 || strchr(par.m_index, '0' + i) != 0;
}
static unsigned
@@ -385,38 +476,285 @@ Lst::reset()
m_cnt = 0;
}
+// character sets
+
+static const unsigned maxcsnumber = 512;
+static const unsigned maxcharcount = 32;
+static const unsigned maxcharsize = 4;
+static const unsigned maxxmulsize = 8;
+
+// single mb char
+struct Chr {
+ unsigned char m_bytes[maxcharsize];
+ unsigned char m_xbytes[maxxmulsize * maxcharsize];
+ unsigned m_size;
+ Chr();
+};
+
+Chr::Chr()
+{
+ memset(m_bytes, 0, sizeof(m_bytes));
+ memset(m_xbytes, 0, sizeof(m_xbytes));
+ m_size = 0;
+}
+
+// charset and random valid chars to use
+struct Chs {
+ CHARSET_INFO* m_cs;
+ unsigned m_xmul;
+ Chr* m_chr;
+ Chs(CHARSET_INFO* cs);
+ ~Chs();
+};
+
+static NdbOut&
+operator<<(NdbOut& out, const Chs& chs);
+
+Chs::Chs(CHARSET_INFO* cs) :
+ m_cs(cs)
+{
+ m_xmul = m_cs->strxfrm_multiply;
+ if (m_xmul == 0)
+ m_xmul = 1;
+ assert(m_xmul <= maxxmulsize);
+ m_chr = new Chr [maxcharcount];
+ unsigned i = 0;
+ unsigned miss1 = 0;
+ unsigned miss2 = 0;
+ unsigned miss3 = 0;
+ unsigned miss4 = 0;
+ while (i < maxcharcount) {
+ unsigned char* bytes = m_chr[i].m_bytes;
+ unsigned char* xbytes = m_chr[i].m_xbytes;
+ unsigned& size = m_chr[i].m_size;
+ bool ok;
+ size = m_cs->mbminlen + urandom(m_cs->mbmaxlen - m_cs->mbminlen + 1);
+ assert(m_cs->mbminlen <= size && size <= m_cs->mbmaxlen);
+ // prefer longer chars
+ if (size == m_cs->mbminlen && m_cs->mbminlen < m_cs->mbmaxlen && urandom(5) != 0)
+ continue;
+ for (unsigned j = 0; j < size; j++) {
+ bytes[j] = urandom(256);
+ }
+ int not_used;
+ // check wellformed
+ const char* sbytes = (const char*)bytes;
+ if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + size, 1, &not_used) != size) {
+ miss1++;
+ continue;
+ }
+ // check no proper prefix wellformed
+ ok = true;
+ for (unsigned j = 1; j < size; j++) {
+ if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + j, 1, &not_used) == j) {
+ ok = false;
+ break;
+ }
+ }
+ if (! ok) {
+ miss2++;
+ continue;
+ }
+ // normalize
+ memset(xbytes, 0, sizeof(xbytes));
+ // currently returns buffer size always
+ int xlen = (*cs->coll->strnxfrm)(cs, xbytes, m_xmul * size, bytes, size);
+ // check we got something
+ ok = false;
+ for (unsigned j = 0; j < xlen; j++) {
+ if (xbytes[j] != 0) {
+ ok = true;
+ break;
+ }
+ }
+ if (! ok) {
+ miss3++;
+ continue;
+ }
+ // check for duplicate (before normalize)
+ ok = true;
+ for (unsigned j = 0; j < i; j++) {
+ const Chr& chr = m_chr[j];
+ if (chr.m_size == size && memcmp(chr.m_bytes, bytes, size) == 0) {
+ ok = false;
+ break;
+ }
+ }
+ if (! ok) {
+ miss4++;
+ continue;
+ }
+ i++;
+ }
+ bool disorder = true;
+ unsigned bubbles = 0;
+ while (disorder) {
+ disorder = false;
+ for (unsigned i = 1; i < maxcharcount; i++) {
+ unsigned len = sizeof(m_chr[i].m_xbytes);
+ if (memcmp(m_chr[i-1].m_xbytes, m_chr[i].m_xbytes, len) > 0) {
+ Chr chr = m_chr[i];
+ m_chr[i] = m_chr[i-1];
+ m_chr[i-1] = chr;
+ disorder = true;
+ bubbles++;
+ }
+ }
+ }
+ LL3("inited charset " << *this << " miss=" << miss1 << "," << miss2 << "," << miss3 << "," << miss4 << " bubbles=" << bubbles);
+}
+
+Chs::~Chs()
+{
+ delete [] m_chr;
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const Chs& chs)
+{
+ CHARSET_INFO* cs = chs.m_cs;
+ out << cs->name << "[" << cs->mbminlen << "-" << cs->mbmaxlen << "," << chs.m_xmul << "]";
+ return out;
+}
+
+static Chs* cslist[maxcsnumber];
+
+static void
+resetcslist()
+{
+ for (unsigned i = 0; i < maxcsnumber; i++) {
+ delete cslist[i];
+ cslist[i] = 0;
+ }
+}
+
+static Chs*
+getcs(Par par)
+{
+ CHARSET_INFO* cs;
+ if (par.m_cs != 0) {
+ cs = par.m_cs;
+ } else {
+ while (1) {
+ unsigned n = urandom(maxcsnumber);
+ cs = get_charset(n, MYF(0));
+ if (cs != 0) {
+ // prefer complex charsets
+ if (cs->mbmaxlen != 1 || urandom(5) == 0)
+ break;
+ }
+ }
+ }
+ if (cslist[cs->number] == 0)
+ cslist[cs->number] = new Chs(cs);
+ return cslist[cs->number];
+}
+
// tables and indexes
// Col - table column
struct Col {
+ enum Type {
+ Unsigned = NdbDictionary::Column::Unsigned,
+ Char = NdbDictionary::Column::Char,
+ Varchar = NdbDictionary::Column::Varchar,
+ Longvarchar = NdbDictionary::Column::Longvarchar
+ };
+ const class Tab& m_tab;
unsigned m_num;
const char* m_name;
bool m_pk;
- NdbDictionary::Column::Type m_type;
+ Type m_type;
unsigned m_length;
+ unsigned m_bytelength; // multiplied by char width
+ unsigned m_attrsize; // base type size
+ unsigned m_headsize; // length bytes
+ unsigned m_bytesize; // full value size
bool m_nullable;
- void verify(const void* addr) const;
+ const Chs* m_chs;
+ Col(const class Tab& tab, unsigned num, const char* name, bool pk, Type type, unsigned length, bool nullable, const Chs* chs);
+ ~Col();
+ bool equal(const Col& col2) const;
+ void wellformed(const void* addr) const;
};
+Col::Col(const class Tab& tab, unsigned num, const char* name, bool pk, Type type, unsigned length, bool nullable, const Chs* chs) :
+ m_tab(tab),
+ m_num(num),
+ m_name(strcpy(new char [strlen(name) + 1], name)),
+ m_pk(pk),
+ m_type(type),
+ m_length(length),
+ m_bytelength(length * (chs == 0 ? 1 : chs->m_cs->mbmaxlen)),
+ m_attrsize(
+ type == Unsigned ? sizeof(Uint32) :
+ type == Char ? sizeof(char) :
+ type == Varchar ? sizeof(char) :
+ type == Longvarchar ? sizeof(char) : ~0),
+ m_headsize(
+ type == Unsigned ? 0 :
+ type == Char ? 0 :
+ type == Varchar ? 1 :
+ type == Longvarchar ? 2 : ~0),
+ m_bytesize(m_headsize + m_attrsize * m_bytelength),
+ m_nullable(nullable),
+ m_chs(chs)
+{
+ // fix long varchar
+ if (type == Varchar && m_bytelength > 255) {
+ m_type = Longvarchar;
+ m_headsize += 1;
+ m_bytesize += 1;
+ }
+}
+
+Col::~Col()
+{
+ delete [] m_name;
+}
+
+bool
+Col::equal(const Col& col2) const
+{
+ return m_type == col2.m_type && m_length == col2.m_length && m_chs == col2.m_chs;
+}
+
void
-Col::verify(const void* addr) const
+Col::wellformed(const void* addr) const
{
switch (m_type) {
- case NdbDictionary::Column::Unsigned:
+ case Col::Unsigned:
break;
- case NdbDictionary::Column::Varchar:
+ case Col::Char:
{
- const unsigned char* p = (const unsigned char*)addr;
- unsigned n = (p[0] << 8) | p[1];
- assert(n <= m_length);
- unsigned i;
- for (i = 0; i < n; i++) {
- assert(p[2 + i] != 0);
- }
- for (i = n; i < m_length; i++) {
- assert(p[2 + i] == 0);
- }
+ CHARSET_INFO* cs = m_chs->m_cs;
+ const char* src = (const char*)addr;
+ unsigned len = m_bytelength;
+ int not_used;
+ assert((*cs->cset->well_formed_len)(cs, src, src + len, 0xffff, &not_used) == len);
+ }
+ break;
+ case Col::Varchar:
+ {
+ CHARSET_INFO* cs = m_chs->m_cs;
+ const unsigned char* src = (const unsigned char*)addr;
+ const char* ssrc = (const char*)src;
+ unsigned len = src[0];
+ int not_used;
+ assert(len <= m_bytelength);
+ assert((*cs->cset->well_formed_len)(cs, ssrc + 1, ssrc + 1 + len, 0xffff, &not_used) == len);
+ }
+ break;
+ case Col::Longvarchar:
+ {
+ CHARSET_INFO* cs = m_chs->m_cs;
+ const unsigned char* src = (const unsigned char*)addr;
+ const char* ssrc = (const char*)src;
+ unsigned len = src[0] + (src[1] << 8);
+ int not_used;
+ assert(len <= m_bytelength);
+ assert((*cs->cset->well_formed_len)(cs, ssrc + 2, ssrc + 2 + len, 0xffff, &not_used) == len);
}
break;
default:
@@ -428,14 +766,28 @@ Col::verify(const void* addr) const
static NdbOut&
operator<<(NdbOut& out, const Col& col)
{
- out << "col " << col.m_num;
- out << " " << col.m_name;
+ out << "col[" << col.m_num << "] " << col.m_name;
switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
+ case Col::Unsigned:
out << " unsigned";
break;
- case NdbDictionary::Column::Varchar:
- out << " varchar(" << col.m_length << ")";
+ case Col::Char:
+ {
+ CHARSET_INFO* cs = col.m_chs->m_cs;
+ out << " char(" << col.m_length << "*" << cs->mbmaxlen << ";" << cs->name << ")";
+ }
+ break;
+ case Col::Varchar:
+ {
+ CHARSET_INFO* cs = col.m_chs->m_cs;
+ out << " varchar(" << col.m_length << "*" << cs->mbmaxlen << ";" << cs->name << ")";
+ }
+ break;
+ case Col::Longvarchar:
+ {
+ CHARSET_INFO* cs = col.m_chs->m_cs;
+ out << " longvarchar(" << col.m_length << "*" << cs->mbmaxlen << ";" << cs->name << ")";
+ }
break;
default:
out << "type" << (int)col.m_type;
@@ -450,25 +802,84 @@ operator<<(NdbOut& out, const Col& col)
// ICol - index column
struct ICol {
+ const class ITab& m_itab;
unsigned m_num;
- struct Col m_col;
+ const Col& m_col;
+ ICol(const class ITab& itab, unsigned num, const Col& col);
+ ~ICol();
};
+ICol::ICol(const class ITab& itab, unsigned num, const Col& col) :
+ m_itab(itab),
+ m_num(num),
+ m_col(col)
+{
+}
+
+ICol::~ICol()
+{
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const ICol& icol)
+{
+ out << "icol[" << icol.m_num << "] " << icol.m_col;
+ return out;
+}
+
// ITab - index
struct ITab {
+ enum Type {
+ OrderedIndex = NdbDictionary::Index::OrderedIndex,
+ UniqueHashIndex = NdbDictionary::Index::UniqueHashIndex
+ };
+ const class Tab& m_tab;
const char* m_name;
+ Type m_type;
unsigned m_icols;
- const ICol* m_icol;
+ const ICol** m_icol;
+ unsigned m_colmask;
+ ITab(const class Tab& tab, const char* name, Type type, unsigned icols);
+ ~ITab();
+ void icoladd(unsigned k, const ICol* icolptr);
};
+ITab::ITab(const class Tab& tab, const char* name, Type type, unsigned icols) :
+ m_tab(tab),
+ m_name(strcpy(new char [strlen(name) + 1], name)),
+ m_type(type),
+ m_icols(icols),
+ m_icol(new const ICol* [icols + 1]),
+ m_colmask(0)
+{
+ for (unsigned k = 0; k <= m_icols; k++)
+ m_icol[k] = 0;
+}
+
+ITab::~ITab()
+{
+ delete [] m_name;
+ for (unsigned i = 0; i < m_icols; i++)
+ delete m_icol[i];
+ delete [] m_icol;
+}
+
+void
+ITab::icoladd(unsigned k, const ICol* icolptr)
+{
+ assert(k == icolptr->m_num && k < m_icols && m_icol[k] == 0);
+ m_icol[k] = icolptr;
+ m_colmask |= (1 << icolptr->m_col.m_num);
+}
+
static NdbOut&
operator<<(NdbOut& out, const ITab& itab)
{
- out << "itab " << itab.m_name << " " << itab.m_icols;
+ out << "itab " << itab.m_name << " icols=" << itab.m_icols;
for (unsigned k = 0; k < itab.m_icols; k++) {
- out << endl;
- out << "icol " << k << " " << itab.m_icol[k].m_col;
+ const ICol& icol = *itab.m_icol[k];
+ out << endl << icol;
}
return out;
}
@@ -478,200 +889,298 @@ operator<<(NdbOut& out, const ITab& itab)
struct Tab {
const char* m_name;
unsigned m_cols;
- const Col* m_col;
+ const Col** m_col;
unsigned m_itabs;
- const ITab* m_itab;
+ const ITab** m_itab;
+ // pk must contain an Unsigned column
+ unsigned m_keycol;
+ void coladd(unsigned k, Col* colptr);
+ void itabadd(unsigned j, ITab* itab);
+ Tab(const char* name, unsigned cols, unsigned itabs, unsigned keycol);
+ ~Tab();
};
+Tab::Tab(const char* name, unsigned cols, unsigned itabs, unsigned keycol) :
+ m_name(strcpy(new char [strlen(name) + 1], name)),
+ m_cols(cols),
+ m_col(new const Col* [cols + 1]),
+ m_itabs(itabs),
+ m_itab(new const ITab* [itabs + 1]),
+ m_keycol(keycol)
+{
+ for (unsigned k = 0; k <= cols; k++)
+ m_col[k] = 0;
+ for (unsigned j = 0; j <= itabs; j++)
+ m_itab[j] = 0;
+}
+
+Tab::~Tab()
+{
+ delete [] m_name;
+ for (unsigned i = 0; i < m_cols; i++)
+ delete m_col[i];
+ delete [] m_col;
+ for (unsigned i = 0; i < m_itabs; i++)
+ delete m_itab[i];
+ delete [] m_itab;
+}
+
+void
+Tab::coladd(unsigned k, Col* colptr)
+{
+ assert(k == colptr->m_num && k < m_cols && m_col[k] == 0);
+ m_col[k] = colptr;
+}
+
+void
+Tab::itabadd(unsigned j, ITab* itabptr)
+{
+ assert(j < m_itabs && m_itab[j] == 0);
+ m_itab[j] = itabptr;
+}
+
static NdbOut&
operator<<(NdbOut& out, const Tab& tab)
{
- out << "tab " << tab.m_name << " " << tab.m_cols;
+ out << "tab " << tab.m_name << " cols=" << tab.m_cols;
for (unsigned k = 0; k < tab.m_cols; k++) {
- out << endl;
- out << tab.m_col[k];
+ const Col& col = *tab.m_col[k];
+ out << endl << col;
}
for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
+ if (tab.m_itab[i] == 0)
continue;
- out << endl;
- out << tab.m_itab[i];
+ const ITab& itab = *tab.m_itab[i];
+ out << endl << itab;
}
return out;
}
-// tt1 + tt1x1 tt1x2 tt1x3 tt1x4 tt1x5
-
-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 }
-};
+// make table structs
-static const ICol
-tt1x1col[] = {
- { 0, tt1col[0] }
-};
-
-static const ICol
-tt1x2col[] = {
- { 0, tt1col[1] }
-};
-
-static const ICol
-tt1x3col[] = {
- { 0, tt1col[1] },
- { 1, tt1col[2] }
-};
-
-static const ICol
-tt1x4col[] = {
- { 0, tt1col[3] },
- { 1, tt1col[2] },
- { 2, tt1col[1] }
-};
-
-static const ICol
-tt1x5col[] = {
- { 0, tt1col[1] },
- { 1, tt1col[4] },
- { 2, tt1col[2] },
- { 3, tt1col[3] }
-};
-
-static const ITab
-tt1x1 = {
- "TT1X1", 1, tt1x1col
-};
-
-static const ITab
-tt1x2 = {
- "TT1X2", 1, tt1x2col
-};
-
-static const ITab
-tt1x3 = {
- "TT1X3", 2, tt1x3col
-};
+static const Tab** tablist = 0;
+static unsigned tabcount = 0;
-static const ITab
-tt1x4 = {
- "TT1X4", 3, tt1x4col
-};
-
-static const ITab
-tt1x5 = {
- "TT1X5", 4, tt1x5col
-};
-
-static const ITab
-tt1itab[] = {
- tt1x1,
- tt1x2,
- tt1x3,
- tt1x4,
- tt1x5
-};
-
-static const Tab
-tt1 = {
- "TT1", 5, tt1col, 5, tt1itab
-};
-
-// tt2 + tt2x1 tt2x2 tt2x3 tt2x4 tt2x5
-
-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[0] }
-};
-
-static const ICol
-tt2x2col[] = {
- { 0, tt2col[1] },
- { 1, tt2col[2] }
-};
-
-static const ICol
-tt2x3col[] = {
- { 0, tt2col[2] },
- { 1, tt2col[1] }
-};
-
-static const ICol
-tt2x4col[] = {
- { 0, tt2col[3] },
- { 1, tt2col[4] }
-};
-
-static const ICol
-tt2x5col[] = {
- { 0, tt2col[4] },
- { 1, tt2col[3] },
- { 2, tt2col[2] },
- { 3, tt2col[1] }
-};
-
-static const ITab
-tt2x1 = {
- "TT2X1", 1, tt2x1col
-};
-
-static const ITab
-tt2x2 = {
- "TT2X2", 2, tt2x2col
-};
-
-static const ITab
-tt2x3 = {
- "TT2X3", 2, tt2x3col
-};
-
-static const ITab
-tt2x4 = {
- "TT2X4", 2, tt2x4col
-};
-
-static const ITab
-tt2x5 = {
- "TT2X5", 4, tt2x5col
-};
-
-static const ITab
-tt2itab[] = {
- tt2x1,
- tt2x2,
- tt2x3,
- tt2x4,
- tt2x5
-};
-
-static const Tab
-tt2 = {
- "TT2", 5, tt2col, 5, tt2itab
-};
-
-// all tables
-
-static const Tab
-tablist[] = {
- tt1,
- tt2
-};
+static void
+verifytables()
+{
+ for (unsigned j = 0; j < tabcount; j++) {
+ const Tab* t = tablist[j];
+ if (t == 0)
+ continue;
+ assert(t->m_cols != 0 && t->m_col != 0);
+ for (unsigned k = 0; k < t->m_cols; k++) {
+ const Col* c = t->m_col[k];
+ assert(c != 0 && c->m_num == k);
+ assert(! (c->m_pk && c->m_nullable));
+ }
+ assert(t->m_col[t->m_cols] == 0);
+ {
+ assert(t->m_keycol < t->m_cols);
+ const Col* c = t->m_col[t->m_keycol];
+ assert(c->m_pk && c->m_type == Col::Unsigned);
+ }
+ assert(t->m_itabs != 0 && t->m_itab != 0);
+ for (unsigned i = 0; i < t->m_itabs; i++) {
+ const ITab* x = t->m_itab[i];
+ if (x == 0)
+ continue;
+ assert(x != 0 && x->m_icols != 0 && x->m_icol != 0);
+ for (unsigned k = 0; k < x->m_icols; k++) {
+ const ICol* c = x->m_icol[k];
+ assert(c != 0 && c->m_num == k && c->m_col.m_num < t->m_cols);
+ if (x->m_type == ITab::UniqueHashIndex) {
+ assert(! c->m_col.m_nullable);
+ }
+ }
+ }
+ assert(t->m_itab[t->m_itabs] == 0);
+ }
+}
-static const unsigned
-tabcount = sizeof(tablist) / sizeof(tablist[0]);
+static void
+makebuiltintables(Par par)
+{
+ LL2("makebuiltintables");
+ resetcslist();
+ tabcount = 3;
+ if (tablist == 0) {
+ tablist = new const Tab* [tabcount];
+ for (unsigned j = 0; j < tabcount; j++) {
+ tablist[j] = 0;
+ }
+ } else {
+ for (unsigned j = 0; j < tabcount; j++) {
+ delete tablist[j];
+ tablist[j] = 0;
+ }
+ }
+ // ti0 - basic
+ if (usetable(par, 0)) {
+ Tab* t = new Tab("ti0", 5, 7, 0);
+ // name - pk - type - length - nullable - cs
+ t->coladd(0, new Col(*t, 0, "a", 1, Col::Unsigned, 1, 0, 0));
+ t->coladd(1, new Col(*t, 1, "b", 0, Col::Unsigned, 1, 1, 0));
+ t->coladd(2, new Col(*t, 2, "c", 0, Col::Unsigned, 1, 0, 0));
+ t->coladd(3, new Col(*t, 3, "d", 0, Col::Unsigned, 1, 1, 0));
+ t->coladd(4, new Col(*t, 4, "e", 0, Col::Unsigned, 1, 0, 0));
+ if (useindex(par, 0)) {
+ // a
+ ITab* x = new ITab(*t, "ti0x0", ITab::OrderedIndex, 1);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[0]));
+ t->itabadd(0, x);
+ }
+ if (useindex(par, 1)) {
+ // b
+ ITab* x = new ITab(*t, "ti0x1", ITab::OrderedIndex, 1);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[1]));
+ t->itabadd(1, x);
+ }
+ if (useindex(par, 2)) {
+ // b, c
+ ITab* x = new ITab(*t, "ti0x2", ITab::OrderedIndex, 2);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[1]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[2]));
+ t->itabadd(2, x);
+ }
+ if (useindex(par, 3)) {
+ // b, e, c, d
+ ITab* x = new ITab(*t, "ti0x3", ITab::OrderedIndex, 4);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[1]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[4]));
+ x->icoladd(2, new ICol(*x, 2, *t->m_col[2]));
+ x->icoladd(3, new ICol(*x, 3, *t->m_col[3]));
+ t->itabadd(3, x);
+ }
+ if (useindex(par, 4)) {
+ // a, c
+ ITab* x = new ITab(*t, "ti0z4", ITab::UniqueHashIndex, 2);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[0]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[2]));
+ t->itabadd(4, x);
+ }
+ if (useindex(par, 5)) {
+ // a, e
+ ITab* x = new ITab(*t, "ti0z5", ITab::UniqueHashIndex, 2);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[0]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[4]));
+ t->itabadd(5, x);
+ }
+ tablist[0] = t;
+ }
+ // ti1 - simple char fields
+ if (usetable(par, 1)) {
+ Tab* t = new Tab("ti1", 5, 7, 1);
+ // name - pk - type - length - nullable - cs
+ t->coladd(0, new Col(*t, 0, "a", 0, Col::Unsigned, 1, 0, 0));
+ t->coladd(1, new Col(*t, 1, "b", 1, Col::Unsigned, 1, 0, 0));
+ t->coladd(2, new Col(*t, 2, "c", 0, Col::Varchar, 20, 0, getcs(par)));
+ t->coladd(3, new Col(*t, 3, "d", 0, Col::Char, 5, 0, getcs(par)));
+ t->coladd(4, new Col(*t, 4, "e", 0, Col::Longvarchar, 5, 1, getcs(par)));
+ if (useindex(par, 0)) {
+ // b
+ ITab* x = new ITab(*t, "ti1x0", ITab::OrderedIndex, 1);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[1]));
+ t->itabadd(0, x);
+ }
+ if (useindex(par, 1)) {
+ // c, a
+ ITab* x = new ITab(*t, "ti1x1", ITab::OrderedIndex, 2);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[2]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[0]));
+ t->itabadd(1, x);
+ }
+ if (useindex(par, 2)) {
+ // d
+ ITab* x = new ITab(*t, "ti1x2", ITab::OrderedIndex, 1);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[3]));
+ t->itabadd(2, x);
+ }
+ if (useindex(par, 3)) {
+ // e, d, c, b
+ ITab* x = new ITab(*t, "ti1x3", ITab::OrderedIndex, 4);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[4]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[3]));
+ x->icoladd(2, new ICol(*x, 2, *t->m_col[2]));
+ x->icoladd(3, new ICol(*x, 3, *t->m_col[1]));
+ t->itabadd(3, x);
+ }
+ if (useindex(par, 4)) {
+ // a, b
+ ITab* x = new ITab(*t, "ti1z4", ITab::UniqueHashIndex, 2);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[0]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[1]));
+ t->itabadd(4, x);
+ }
+ if (useindex(par, 5)) {
+ // b, c, d
+ ITab* x = new ITab(*t, "ti1z5", ITab::UniqueHashIndex, 3);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[1]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[2]));
+ x->icoladd(2, new ICol(*x, 2, *t->m_col[3]));
+ t->itabadd(5, x);
+ }
+ tablist[1] = t;
+ }
+ // ti2 - complex char fields
+ if (usetable(par, 2)) {
+ Tab* t = new Tab("ti2", 5, 7, 2);
+ // name - pk - type - length - nullable - cs
+ t->coladd(0, new Col(*t, 0, "a", 1, Col::Char, 31, 0, getcs(par)));
+ t->coladd(1, new Col(*t, 1, "b", 0, Col::Char, 4, 1, getcs(par)));
+ t->coladd(2, new Col(*t, 2, "c", 1, Col::Unsigned, 1, 0, 0));
+ t->coladd(3, new Col(*t, 3, "d", 1, Col::Varchar, 128, 0, getcs(par)));
+ t->coladd(4, new Col(*t, 4, "e", 0, Col::Varchar, 7, 0, getcs(par)));
+ if (useindex(par, 0)) {
+ // a, c, d
+ ITab* x = new ITab(*t, "ti2x0", ITab::OrderedIndex, 3);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[0]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[2]));
+ x->icoladd(2, new ICol(*x, 2, *t->m_col[3]));
+ t->itabadd(0, x);
+ }
+ if (useindex(par, 1)) {
+ // e, d, c, b, a
+ ITab* x = new ITab(*t, "ti2x1", ITab::OrderedIndex, 5);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[4]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[3]));
+ x->icoladd(2, new ICol(*x, 2, *t->m_col[2]));
+ x->icoladd(3, new ICol(*x, 3, *t->m_col[1]));
+ x->icoladd(4, new ICol(*x, 4, *t->m_col[0]));
+ t->itabadd(1, x);
+ }
+ if (useindex(par, 2)) {
+ // d
+ ITab* x = new ITab(*t, "ti2x2", ITab::OrderedIndex, 1);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[3]));
+ t->itabadd(2, x);
+ }
+ if (useindex(par, 3)) {
+ // b
+ ITab* x = new ITab(*t, "ti2x3", ITab::OrderedIndex, 1);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[1]));
+ t->itabadd(3, x);
+ }
+ if (useindex(par, 4)) {
+ // a, c
+ ITab* x = new ITab(*t, "ti2z4", ITab::UniqueHashIndex, 2);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[0]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[2]));
+ t->itabadd(4, x);
+ }
+ if (useindex(par, 5)) {
+ // a, c, d, e
+ ITab* x = new ITab(*t, "ti2z5", ITab::UniqueHashIndex, 4);
+ x->icoladd(0, new ICol(*x, 0, *t->m_col[0]));
+ x->icoladd(1, new ICol(*x, 1, *t->m_col[2]));
+ x->icoladd(2, new ICol(*x, 2, *t->m_col[3]));
+ x->icoladd(3, new ICol(*x, 3, *t->m_col[4]));
+ t->itabadd(5, x);
+ }
+ tablist[2] = t;
+ }
+ verifytables();
+}
// connections
@@ -682,16 +1191,18 @@ struct Con {
NdbDictionary::Dictionary* m_dic;
NdbConnection* m_tx;
NdbOperation* m_op;
+ NdbIndexOperation* m_indexop;
NdbScanOperation* m_scanop;
NdbIndexScanOperation* m_indexscanop;
- NdbResultSet* m_resultset;
+ NdbScanFilter* m_scanfilter;
enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive };
ScanMode m_scanmode;
enum ErrType { ErrNone = 0, ErrDeadlock, ErrNospace, ErrOther };
ErrType m_errtype;
Con() :
- m_ndb(0), m_dic(0), m_tx(0), m_op(0),
- m_scanop(0), m_indexscanop(0), m_resultset(0), m_scanmode(ScanNo), m_errtype(ErrNone) {}
+ m_ndb(0), m_dic(0), m_tx(0), m_op(0), m_indexop(0),
+ m_scanop(0), m_indexscanop(0), m_scanfilter(0),
+ m_scanmode(ScanNo), m_errtype(ErrNone) {}
~Con() {
if (m_tx != 0)
closeTransaction();
@@ -701,16 +1212,23 @@ struct Con {
void disconnect();
int startTransaction();
int getNdbOperation(const Tab& tab);
+ int getNdbIndexOperation1(const ITab& itab, const Tab& tab);
+ int getNdbIndexOperation(const ITab& itab, const Tab& tab);
int getNdbScanOperation(const Tab& tab);
- int getNdbScanOperation(const ITab& itab, const Tab& tab);
+ int getNdbIndexScanOperation1(const ITab& itab, const Tab& tab);
+ int getNdbIndexScanOperation(const ITab& itab, const Tab& tab);
+ int getNdbScanFilter();
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 beginFilter(int group);
+ int endFilter();
+ int setFilter(int num, int cond, const void* value, unsigned len);
int execute(ExecType t);
int execute(ExecType t, bool& deadlock, bool& nospace);
- int openScanRead(unsigned scanbat, unsigned scanpar);
- int openScanExclusive(unsigned scanbat, unsigned scanpar);
+ int readTuples(Par par);
+ int readIndexTuples(Par par);
int executeScan();
int nextScanResult(bool fetchAllowed);
int nextScanResult(bool fetchAllowed, bool& deadlock);
@@ -765,6 +1283,28 @@ Con::getNdbOperation(const Tab& tab)
}
int
+Con::getNdbIndexOperation1(const ITab& itab, const Tab& tab)
+{
+ assert(m_tx != 0);
+ CHKCON((m_op = m_indexop = m_tx->getNdbIndexOperation(itab.m_name, tab.m_name)) != 0, *this);
+ return 0;
+}
+
+int
+Con::getNdbIndexOperation(const ITab& itab, const Tab& tab)
+{
+ assert(m_tx != 0);
+ unsigned tries = 0;
+ while (1) {
+ if (getNdbIndexOperation1(itab, tab) == 0)
+ break;
+ CHK(++tries < 10);
+ NdbSleep_MilliSleep(100);
+ }
+ return 0;
+}
+
+int
Con::getNdbScanOperation(const Tab& tab)
{
assert(m_tx != 0);
@@ -773,7 +1313,7 @@ Con::getNdbScanOperation(const Tab& tab)
}
int
-Con::getNdbScanOperation(const ITab& itab, const Tab& tab)
+Con::getNdbIndexScanOperation1(const ITab& itab, const Tab& tab)
{
assert(m_tx != 0);
CHKCON((m_op = m_scanop = m_indexscanop = m_tx->getNdbIndexScanOperation(itab.m_name, tab.m_name)) != 0, *this);
@@ -781,6 +1321,29 @@ Con::getNdbScanOperation(const ITab& itab, const Tab& tab)
}
int
+Con::getNdbIndexScanOperation(const ITab& itab, const Tab& tab)
+{
+ assert(m_tx != 0);
+ unsigned tries = 0;
+ while (1) {
+ if (getNdbIndexScanOperation1(itab, tab) == 0)
+ break;
+ CHK(++tries < 10);
+ NdbSleep_MilliSleep(100);
+ }
+ return 0;
+}
+
+int
+Con::getNdbScanFilter()
+{
+ assert(m_tx != 0 && m_scanop != 0);
+ delete m_scanfilter;
+ m_scanfilter = new NdbScanFilter(m_scanop);
+ return 0;
+}
+
+int
Con::equal(int num, const char* addr)
{
assert(m_tx != 0 && m_op != 0);
@@ -807,12 +1370,36 @@ Con::setValue(int num, const char* addr)
int
Con::setBound(int num, int type, const void* value)
{
- assert(m_tx != 0 && m_op != 0);
+ assert(m_tx != 0 && m_indexscanop != 0);
CHKCON(m_indexscanop->setBound(num, type, value) == 0, *this);
return 0;
}
int
+Con::beginFilter(int group)
+{
+ assert(m_tx != 0 && m_scanfilter != 0);
+ CHKCON(m_scanfilter->begin((NdbScanFilter::Group)group) == 0, *this);
+ return 0;
+}
+
+int
+Con::endFilter()
+{
+ assert(m_tx != 0 && m_scanfilter != 0);
+ CHKCON(m_scanfilter->end() == 0, *this);
+ return 0;
+}
+
+int
+Con::setFilter(int num, int cond, const void* value, unsigned len)
+{
+ assert(m_tx != 0 && m_scanfilter != 0);
+ CHKCON(m_scanfilter->cmp((NdbScanFilter::BinaryCondition)cond, num, value, len) == 0, *this);
+ return 0;
+}
+
+int
Con::execute(ExecType t)
{
assert(m_tx != 0);
@@ -841,20 +1428,21 @@ Con::execute(ExecType t, bool& deadlock, bool& nospace)
}
int
-Con::openScanRead(unsigned scanbat, unsigned scanpar)
+Con::readTuples(Par par)
{
- assert(m_tx != 0 && m_op != 0);
- NdbOperation::LockMode lm = NdbOperation::LM_Read;
- CHKCON((m_resultset = m_scanop->readTuples(lm, scanbat, scanpar)) != 0, *this);
+ assert(m_tx != 0 && m_scanop != 0);
+ int scan_flags = 0;
+ if (par.m_tupscan)
+ scan_flags |= NdbScanOperation::SF_TupScan;
+ CHKCON(m_scanop->readTuples(par.m_lockmode, scan_flags, par.m_scanpar) == 0, *this);
return 0;
}
int
-Con::openScanExclusive(unsigned scanbat, unsigned scanpar)
+Con::readIndexTuples(Par par)
{
- assert(m_tx != 0 && m_op != 0);
- NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
- CHKCON((m_resultset = m_scanop->readTuples(lm, scanbat, scanpar)) != 0, *this);
+ assert(m_tx != 0 && m_indexscanop != 0);
+ CHKCON(m_indexscanop->readTuples(par.m_lockmode, 0, par.m_scanpar, par.m_ordered, par.m_descending) == 0, *this);
return 0;
}
@@ -869,8 +1457,8 @@ int
Con::nextScanResult(bool fetchAllowed)
{
int ret;
- assert(m_resultset != 0);
- CHKCON((ret = m_resultset->nextResult(fetchAllowed)) != -1, *this);
+ assert(m_scanop != 0);
+ CHKCON((ret = m_scanop->nextResult(fetchAllowed)) != -1, *this);
assert(ret == 0 || ret == 1 || (! fetchAllowed && ret == 2));
return ret;
}
@@ -895,7 +1483,7 @@ int
Con::updateScanTuple(Con& con2)
{
assert(con2.m_tx != 0);
- CHKCON((con2.m_op = m_resultset->updateTuple(con2.m_tx)) != 0, *this);
+ CHKCON((con2.m_op = m_scanop->updateCurrentTuple(con2.m_tx)) != 0, *this);
return 0;
}
@@ -903,16 +1491,16 @@ int
Con::deleteScanTuple(Con& con2)
{
assert(con2.m_tx != 0);
- CHKCON(m_resultset->deleteTuple(con2.m_tx) == 0, *this);
+ CHKCON(m_scanop->deleteCurrentTuple(con2.m_tx) == 0, *this);
return 0;
}
void
Con::closeScan()
{
- assert(m_resultset != 0);
- m_resultset->close();
- m_scanop = 0, m_indexscanop = 0, m_resultset = 0;
+ assert(m_scanop != 0);
+ m_scanop->close();
+ m_scanop = 0, m_indexscanop = 0;
}
@@ -922,7 +1510,7 @@ Con::closeTransaction()
assert(m_ndb != 0 && m_tx != 0);
m_ndb->closeTransaction(m_tx);
m_tx = 0, m_op = 0;
- m_scanop = 0, m_indexscanop = 0, m_resultset = 0;
+ m_scanop = 0, m_indexscanop = 0;
}
void
@@ -945,7 +1533,8 @@ Con::printerror(NdbOut& out)
if ((code = m_tx->getNdbError().code) != 0) {
LL0(++any << " con: error " << m_tx->getNdbError());
die += (code == g_opt.m_die);
- if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499)
+ // 631 is new, occurs only on 4 db nodes, needs to be checked out
+ if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499 || code == 631)
m_errtype = ErrDeadlock;
if (code == 826 || code == 827 || code == 902)
m_errtype = ErrNospace;
@@ -983,9 +1572,9 @@ invalidateindex(Par par)
Con& con = par.con();
const Tab& tab = par.tab();
for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
+ if (tab.m_itab[i] == 0)
continue;
- const ITab& itab = tab.m_itab[i];
+ const ITab& itab = *tab.m_itab[i];
invalidateindex(par, itab);
}
return 0;
@@ -1033,16 +1622,14 @@ createtable(Par par)
t.setLogging(false);
}
for (unsigned k = 0; k < tab.m_cols; k++) {
- const Col& col = tab.m_col[k];
+ const Col& col = *tab.m_col[k];
NdbDictionary::Column c(col.m_name);
- c.setType(col.m_type);
- c.setLength(col.m_length);
+ c.setType((NdbDictionary::Column::Type)col.m_type);
+ c.setLength(col.m_bytelength); // for char NDB API uses length in bytes
c.setPrimaryKey(col.m_pk);
c.setNullable(col.m_nullable);
- if (c.getCharset()) { // test if char type
- if (! col.m_pk)
- c.setCharset(par.m_cs);
- }
+ if (col.m_chs != 0)
+ c.setCharset(col.m_chs->m_cs);
t.addColumn(c);
}
con.m_dic = con.m_ndb->getDictionary();
@@ -1073,9 +1660,9 @@ dropindex(Par par)
{
const Tab& tab = par.tab();
for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
+ if (tab.m_itab[i] == 0)
continue;
- const ITab& itab = tab.m_itab[i];
+ const ITab& itab = *tab.m_itab[i];
CHK(dropindex(par, itab) == 0);
}
return 0;
@@ -1090,10 +1677,13 @@ createindex(Par par, const ITab& itab)
LL4(itab);
NdbDictionary::Index x(itab.m_name);
x.setTable(tab.m_name);
- x.setType(NdbDictionary::Index::OrderedIndex);
- x.setLogging(false);
+ x.setType((NdbDictionary::Index::Type)itab.m_type);
+ if (par.m_nologging || itab.m_type == ITab::OrderedIndex) {
+ x.setLogging(false);
+ }
for (unsigned k = 0; k < itab.m_icols; k++) {
- const Col& col = itab.m_icol[k].m_col;
+ const ICol& icol = *itab.m_icol[k];
+ const Col& col = icol.m_col;
x.addColumnName(col.m_name);
}
con.m_dic = con.m_ndb->getDictionary();
@@ -1107,9 +1697,9 @@ createindex(Par par)
{
const Tab& tab = par.tab();
for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
+ if (tab.m_itab[i] == 0)
continue;
- const ITab& itab = tab.m_itab[i];
+ const ITab& itab = *tab.m_itab[i];
CHK(createindex(par, itab) == 0);
}
return 0;
@@ -1117,43 +1707,15 @@ createindex(Par par)
// 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;
-}
-
-static bool
-randompct(unsigned pct)
-{
- if (pct == 0)
- return false;
- if (pct >= 100)
- return true;
- return urandom(100) < pct;
-}
-
// Val - typed column value
struct Val {
const Col& m_col;
union {
Uint32 m_uint32;
- char* m_varchar;
+ unsigned char* m_char;
+ unsigned char* m_varchar;
+ unsigned char* m_longvarchar;
};
Val(const Col& col);
~Val();
@@ -1161,10 +1723,17 @@ struct Val {
void copy(const void* addr);
const void* dataaddr() const;
bool m_null;
+ int equal(Par par) const;
+ int equal(Par par, const ICol& icol) const;
int setval(Par par) const;
void calc(Par par, unsigned i);
- int verify(const Val& val2) const;
- int cmp(const Val& val2) const;
+ void calckey(Par par, unsigned i);
+ void calckeychars(Par par, unsigned i, unsigned& n, unsigned char* buf);
+ void calcnokey(Par par);
+ void calcnokeychars(Par par, unsigned& n, unsigned char* buf);
+ int verify(Par par, const Val& val2) const;
+ int cmp(Par par, const Val& val2) const;
+ int cmpchars(Par par, const unsigned char* buf1, unsigned len1, const unsigned char* buf2, unsigned len2) const;
private:
Val& operator=(const Val& val2);
};
@@ -1176,10 +1745,16 @@ Val::Val(const Col& col) :
m_col(col)
{
switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
+ case Col::Unsigned:
break;
- case NdbDictionary::Column::Varchar:
- m_varchar = new char [2 + col.m_length];
+ case Col::Char:
+ m_char = new unsigned char [col.m_bytelength];
+ break;
+ case Col::Varchar:
+ m_varchar = new unsigned char [1 + col.m_bytelength];
+ break;
+ case Col::Longvarchar:
+ m_longvarchar = new unsigned char [2 + col.m_bytelength];
break;
default:
assert(false);
@@ -1191,11 +1766,17 @@ Val::~Val()
{
const Col& col = m_col;
switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
+ case Col::Unsigned:
break;
- case NdbDictionary::Column::Varchar:
+ case Col::Char:
+ delete [] m_char;
+ break;
+ case Col::Varchar:
delete [] m_varchar;
break;
+ case Col::Longvarchar:
+ delete [] m_longvarchar;
+ break;
default:
assert(false);
break;
@@ -1220,11 +1801,17 @@ Val::copy(const void* addr)
{
const Col& col = m_col;
switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
+ case Col::Unsigned:
m_uint32 = *(const Uint32*)addr;
break;
- case NdbDictionary::Column::Varchar:
- memcpy(m_varchar, addr, 2 + col.m_length);
+ case Col::Char:
+ memcpy(m_char, addr, col.m_bytelength);
+ break;
+ case Col::Varchar:
+ memcpy(m_varchar, addr, 1 + col.m_bytelength);
+ break;
+ case Col::Longvarchar:
+ memcpy(m_longvarchar, addr, 2 + col.m_bytelength);
break;
default:
assert(false);
@@ -1238,10 +1825,14 @@ Val::dataaddr() const
{
const Col& col = m_col;
switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
+ case Col::Unsigned:
return &m_uint32;
- case NdbDictionary::Column::Varchar:
+ case Col::Char:
+ return m_char;
+ case Col::Varchar:
return m_varchar;
+ case Col::Longvarchar:
+ return m_longvarchar;
default:
break;
}
@@ -1250,18 +1841,37 @@ Val::dataaddr() const
}
int
-Val::setval(Par par) const
+Val::equal(Par par) const
{
Con& con = par.con();
const Col& col = m_col;
+ assert(col.m_pk && ! m_null);
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);
+ LL5("equal [" << col << "] " << *this);
+ CHK(con.equal(col.m_num, addr) == 0);
+ return 0;
+}
+
+int
+Val::equal(Par par, const ICol& icol) const
+{
+ Con& con = par.con();
+ assert(! m_null);
+ const char* addr = (const char*)dataaddr();
+ LL5("equal [" << icol << "] " << *this);
+ CHK(con.equal(icol.m_num, addr) == 0);
+ return 0;
+}
+
+int
+Val::setval(Par par) const
+{
+ Con& con = par.con();
+ const Col& col = m_col;
+ assert(! col.m_pk);
+ const char* addr = ! m_null ? (const char*)dataaddr() : 0;
+ LL5("setval [" << col << "] " << *this);
+ CHK(con.setValue(col.m_num, addr) == 0);
return 0;
}
@@ -1269,58 +1879,170 @@ void
Val::calc(Par par, unsigned i)
{
const Col& col = m_col;
+ col.m_pk ? calckey(par, i) : calcnokey(par);
+ if (! m_null)
+ col.wellformed(dataaddr());
+}
+
+void
+Val::calckey(Par par, unsigned i)
+{
+ const Col& col = m_col;
m_null = false;
- if (col.m_pk) {
+ switch (col.m_type) {
+ case Col::Unsigned:
m_uint32 = i;
- return;
+ break;
+ case Col::Char:
+ {
+ const Chs* chs = col.m_chs;
+ CHARSET_INFO* cs = chs->m_cs;
+ unsigned n = 0;
+ calckeychars(par, i, n, m_char);
+ // extend by appropriate space
+ (*cs->cset->fill)(cs, (char*)&m_char[n], col.m_bytelength - n, 0x20);
+ }
+ break;
+ case Col::Varchar:
+ {
+ unsigned n = 0;
+ calckeychars(par, i, n, m_varchar + 1);
+ // set length and pad with nulls
+ m_varchar[0] = n;
+ memset(&m_varchar[1 + n], 0, col.m_bytelength - n);
+ }
+ break;
+ case Col::Longvarchar:
+ {
+ unsigned n = 0;
+ calckeychars(par, i, n, m_longvarchar + 2);
+ // set length and pad with nulls
+ m_longvarchar[0] = (n & 0xff);
+ m_longvarchar[1] = (n >> 8);
+ memset(&m_longvarchar[2 + n], 0, col.m_bytelength - n);
+ }
+ break;
+ default:
+ assert(false);
+ break;
}
+}
+
+void
+Val::calckeychars(Par par, unsigned i, unsigned& n, unsigned char* buf)
+{
+ const Col& col = m_col;
+ const Chs* chs = col.m_chs;
+ CHARSET_INFO* cs = chs->m_cs;
+ n = 0;
+ unsigned len = 0;
+ while (len < col.m_length) {
+ if (i % (1 + n) == 0) {
+ break;
+ }
+ const Chr& chr = chs->m_chr[i % maxcharcount];
+ assert(n + chr.m_size <= col.m_bytelength);
+ memcpy(buf + n, chr.m_bytes, chr.m_size);
+ n += chr.m_size;
+ len++;
+ }
+}
+
+void
+Val::calcnokey(Par par)
+{
+ const Col& col = m_col;
+ m_null = false;
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);
+ int r = irandom((par.m_pctrange * par.m_range) / 100);
+ if (par.m_bdir != 0 && urandom(10) != 0) {
+ if (r < 0 && par.m_bdir > 0 || r > 0 && par.m_bdir < 0)
+ r = -r;
+ }
+ unsigned v = par.m_range + r;
switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
+ case Col::Unsigned:
m_uint32 = v;
break;
- case NdbDictionary::Column::Varchar:
+ case Col::Char:
{
+ const Chs* chs = col.m_chs;
+ CHARSET_INFO* cs = chs->m_cs;
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;
- }
+ calcnokeychars(par, n, m_char);
+ // extend by appropriate space
+ (*cs->cset->fill)(cs, (char*)&m_char[n], col.m_bytelength - n, 0x20);
+ }
+ break;
+ case Col::Varchar:
+ {
+ unsigned n = 0;
+ calcnokeychars(par, n, m_varchar + 1);
+ // set length and pad with nulls
+ m_varchar[0] = n;
+ memset(&m_varchar[1 + n], 0, col.m_bytelength - n);
+ }
+ break;
+ case Col::Longvarchar:
+ {
+ unsigned n = 0;
+ calcnokeychars(par, n, m_longvarchar + 2);
+ // set length and pad with nulls
+ m_longvarchar[0] = (n & 0xff);
+ m_longvarchar[1] = (n >> 8);
+ memset(&m_longvarchar[2 + n], 0, col.m_bytelength - n);
}
break;
default:
assert(false);
break;
}
- // verify format
- col.verify(dataaddr());
+}
+
+void
+Val::calcnokeychars(Par par, unsigned& n, unsigned char* buf)
+{
+ const Col& col = m_col;
+ const Chs* chs = col.m_chs;
+ CHARSET_INFO* cs = chs->m_cs;
+ n = 0;
+ unsigned len = 0;
+ while (len < col.m_length) {
+ if (urandom(1 + col.m_bytelength) == 0) {
+ break;
+ }
+ unsigned half = maxcharcount / 2;
+ int r = irandom((par.m_pctrange * half) / 100);
+ if (par.m_bdir != 0 && urandom(10) != 0) {
+ if (r < 0 && par.m_bdir > 0 || r > 0 && par.m_bdir < 0)
+ r = -r;
+ }
+ unsigned i = half + r;
+ assert(i < maxcharcount);
+ const Chr& chr = chs->m_chr[i];
+ assert(n + chr.m_size <= col.m_bytelength);
+ memcpy(buf + n, chr.m_bytes, chr.m_size);
+ n += chr.m_size;
+ len++;
+ }
}
int
-Val::verify(const Val& val2) const
+Val::verify(Par par, const Val& val2) const
{
- CHK(cmp(val2) == 0);
+ CHK(cmp(par, val2) == 0);
return 0;
}
int
-Val::cmp(const Val& val2) const
+Val::cmp(Par par, 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);
+ assert(col.equal(col2));
if (m_null || val2.m_null) {
if (! m_null)
return +1;
@@ -1329,18 +2051,39 @@ Val::cmp(const Val& val2) const
return 0;
}
// verify data formats
- col.verify(dataaddr());
- col.verify(val2.dataaddr());
+ col.wellformed(dataaddr());
+ col.wellformed(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);
+ case Col::Unsigned:
+ {
+ if (m_uint32 < val2.m_uint32)
+ return -1;
+ if (m_uint32 > val2.m_uint32)
+ return +1;
+ return 0;
+ }
+ break;
+ case Col::Char:
+ {
+ unsigned len = col.m_bytelength;
+ return cmpchars(par, m_char, len, val2.m_char, len);
+ }
+ break;
+ case Col::Varchar:
+ {
+ unsigned len1 = m_varchar[0];
+ unsigned len2 = val2.m_varchar[0];
+ return cmpchars(par, m_varchar + 1, len1, val2.m_varchar + 1, len2);
+ }
+ break;
+ case Col::Longvarchar:
+ {
+ unsigned len1 = m_longvarchar[0] + (m_longvarchar[1] << 8);
+ unsigned len2 = val2.m_longvarchar[0] + (val2.m_longvarchar[1] << 8);
+ return cmpchars(par, m_longvarchar + 2, len1, val2.m_longvarchar + 2, len2);
+ }
+ break;
default:
break;
}
@@ -1348,6 +2091,56 @@ Val::cmp(const Val& val2) const
return 0;
}
+int
+Val::cmpchars(Par par, const unsigned char* buf1, unsigned len1, const unsigned char* buf2, unsigned len2) const
+{
+ const Col& col = m_col;
+ const Chs* chs = col.m_chs;
+ CHARSET_INFO* cs = chs->m_cs;
+ int k;
+ if (! par.m_collsp) {
+ unsigned char x1[maxxmulsize * 8000];
+ unsigned char x2[maxxmulsize * 8000];
+ // make strxfrm pad both to same length
+ unsigned len = maxxmulsize * col.m_bytelength;
+ int n1 = NdbSqlUtil::strnxfrm_bug7284(cs, x1, chs->m_xmul * len, buf1, len1);
+ int n2 = NdbSqlUtil::strnxfrm_bug7284(cs, x2, chs->m_xmul * len, buf2, len2);
+ assert(n1 != -1 && n1 == n2);
+ k = memcmp(x1, x2, n1);
+ } else {
+ k = (*cs->coll->strnncollsp)(cs, buf1, len1, buf2, len2, false);
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : 0;
+}
+
+static void
+printstring(NdbOut& out, const unsigned char* str, unsigned len, bool showlen)
+{
+ char buf[4 * 8000];
+ char *p = buf;
+ *p++ = '[';
+ if (showlen) {
+ sprintf(p, "%u:", len);
+ p += strlen(p);
+ }
+ for (unsigned i = 0; i < len; i++) {
+ unsigned char c = str[i];
+ if (c == '\\') {
+ *p++ = '\\';
+ *p++ = c;
+ } else if (0x20 <= c && c < 0x7e) {
+ *p++ = c;
+ } else {
+ *p++ = '\\';
+ *p++ = hexstr[c >> 4];
+ *p++ = hexstr[c & 15];
+ }
+ }
+ *p++ = ']';
+ *p = 0;
+ out << buf;
+}
+
static NdbOut&
operator<<(NdbOut& out, const Val& val)
{
@@ -1357,16 +2150,25 @@ operator<<(NdbOut& out, const Val& val)
return out;
}
switch (col.m_type) {
- case NdbDictionary::Column::Unsigned:
+ case Col::Unsigned:
out << val.m_uint32;
break;
- case NdbDictionary::Column::Varchar:
+ case Col::Char:
+ {
+ unsigned len = col.m_bytelength;
+ printstring(out, val.m_char, len, false);
+ }
+ break;
+ case Col::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;
+ unsigned len = val.m_varchar[0];
+ printstring(out, val.m_varchar + 1, len, true);
+ }
+ break;
+ case Col::Longvarchar:
+ {
+ unsigned len = val.m_longvarchar[0] + (val.m_longvarchar[1] << 8);
+ printstring(out, val.m_longvarchar + 2, len, true);
}
break;
default:
@@ -1383,19 +2185,25 @@ struct Row {
const Tab& m_tab;
Val** m_val;
bool m_exist;
- enum Op { NoOp = 0, ReadOp, InsOp, UpdOp, DelOp };
+ enum Op { NoOp = 0, ReadOp = 1, InsOp = 2, UpdOp = 4, DelOp = 8, AnyOp = 15 };
Op m_pending;
+ Row* m_dbrow; // copy of db row before update
Row(const Tab& tab);
~Row();
void copy(const Row& row2);
- void calc(Par par, unsigned i);
- int verify(const Row& row2) const;
+ void calc(Par par, unsigned i, unsigned mask = 0);
+ const Row& dbrow() const;
+ int verify(Par par, const Row& row2) const;
int insrow(Par par);
int updrow(Par par);
+ int updrow(Par par, const ITab& itab);
int delrow(Par par);
+ int delrow(Par par, const ITab& itab);
int selrow(Par par);
+ int selrow(Par par, const ITab& itab);
int setrow(Par par);
- int cmp(const Row& row2) const;
+ int cmp(Par par, const Row& row2) const;
+ int cmp(Par par, const Row& row2, const ITab& itab) const;
private:
Row& operator=(const Row& row2);
};
@@ -1405,11 +2213,12 @@ Row::Row(const 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];
+ const Col& col = *tab.m_col[k];
m_val[k] = new Val(col);
}
m_exist = false;
m_pending = NoOp;
+ m_dbrow = 0;
}
Row::~Row()
@@ -1419,6 +2228,7 @@ Row::~Row()
delete m_val[k];
}
delete [] m_val;
+ delete m_dbrow;
}
void
@@ -1431,27 +2241,49 @@ Row::copy(const Row& row2)
const Val& val2 = *row2.m_val[k];
val.copy(val2);
}
+ m_exist = row2.m_exist;
+ m_pending = row2.m_pending;
+ if (row2.m_dbrow == 0) {
+ m_dbrow = 0;
+ } else {
+ assert(row2.m_dbrow->m_dbrow == 0);
+ if (m_dbrow == 0)
+ m_dbrow = new Row(tab);
+ m_dbrow->copy(*row2.m_dbrow);
+ }
}
void
-Row::calc(Par par, unsigned i)
+Row::calc(Par par, unsigned i, unsigned mask)
{
const Tab& tab = m_tab;
for (unsigned k = 0; k < tab.m_cols; k++) {
- Val& val = *m_val[k];
- val.calc(par, i);
+ if (! (mask & (1 << k))) {
+ Val& val = *m_val[k];
+ val.calc(par, i);
+ }
}
}
+const Row&
+Row::dbrow() const
+{
+ if (m_dbrow == 0)
+ return *this;
+ assert(m_pending == Row::UpdOp || m_pending == Row::DelOp);
+ return *m_dbrow;
+}
+
int
-Row::verify(const Row& row2) const
+Row::verify(Par par, const Row& row2) const
{
const Tab& tab = m_tab;
- assert(&tab == &row2.m_tab && m_exist && row2.m_exist);
+ const Row& row1 = *this;
+ assert(&row1.m_tab == &row2.m_tab && row1.m_exist && row2.m_exist);
for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
+ const Val& val1 = *row1.m_val[k];
const Val& val2 = *row2.m_val[k];
- CHK(val.verify(val2) == 0);
+ CHK(val1.verify(par, val2) == 0);
}
return 0;
}
@@ -1464,9 +2296,21 @@ Row::insrow(Par par)
assert(! m_exist);
CHK(con.getNdbOperation(tab) == 0);
CHKCON(con.m_op->insertTuple() == 0, con);
+ Rsq rsq1(tab.m_cols);
for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- CHK(val.setval(par) == 0);
+ unsigned k2 = rsq1.next();
+ const Val& val = *m_val[k2];
+ const Col& col = val.m_col;
+ if (col.m_pk)
+ CHK(val.equal(par) == 0);
+ }
+ Rsq rsq2(tab.m_cols);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ unsigned k2 = rsq2.next();
+ const Val& val = *m_val[k2];
+ const Col& col = val.m_col;
+ if (! col.m_pk)
+ CHK(val.setval(par) == 0);
}
m_pending = InsOp;
return 0;
@@ -1480,9 +2324,51 @@ Row::updrow(Par par)
assert(m_exist);
CHK(con.getNdbOperation(tab) == 0);
CHKCON(con.m_op->updateTuple() == 0, con);
+ Rsq rsq1(tab.m_cols);
for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
- CHK(val.setval(par) == 0);
+ unsigned k2 = rsq1.next();
+ const Val& val = *m_val[k2];
+ const Col& col = val.m_col;
+ if (col.m_pk)
+ CHK(val.equal(par) == 0);
+ }
+ Rsq rsq2(tab.m_cols);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ unsigned k2 = rsq2.next();
+ const Val& val = *m_val[k2];
+ const Col& col = val.m_col;
+ if (! col.m_pk)
+ CHK(val.setval(par) == 0);
+ }
+ m_pending = UpdOp;
+ return 0;
+}
+
+int
+Row::updrow(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
+ assert(m_exist);
+ CHK(con.getNdbIndexOperation(itab, tab) == 0);
+ CHKCON(con.m_op->updateTuple() == 0, con);
+ Rsq rsq1(itab.m_icols);
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ unsigned k2 = rsq1.next();
+ const ICol& icol = *itab.m_icol[k2];
+ const Col& col = icol.m_col;
+ unsigned m = col.m_num;
+ const Val& val = *m_val[m];
+ CHK(val.equal(par, icol) == 0);
+ }
+ Rsq rsq2(tab.m_cols);
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ unsigned k2 = rsq2.next();
+ const Val& val = *m_val[k2];
+ const Col& col = val.m_col;
+ if (! col.m_pk)
+ CHK(val.setval(par) == 0);
}
m_pending = UpdOp;
return 0;
@@ -1496,11 +2382,35 @@ Row::delrow(Par par)
assert(m_exist);
CHK(con.getNdbOperation(m_tab) == 0);
CHKCON(con.m_op->deleteTuple() == 0, con);
+ Rsq rsq1(tab.m_cols);
for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
+ unsigned k2 = rsq1.next();
+ const Val& val = *m_val[k2];
const Col& col = val.m_col;
if (col.m_pk)
- CHK(val.setval(par) == 0);
+ CHK(val.equal(par) == 0);
+ }
+ m_pending = DelOp;
+ return 0;
+}
+
+int
+Row::delrow(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
+ assert(m_exist);
+ CHK(con.getNdbIndexOperation(itab, tab) == 0);
+ CHKCON(con.m_op->deleteTuple() == 0, con);
+ Rsq rsq1(itab.m_icols);
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ unsigned k2 = rsq1.next();
+ const ICol& icol = *itab.m_icol[k2];
+ const Col& col = icol.m_col;
+ unsigned m = col.m_num;
+ const Val& val = *m_val[m];
+ CHK(val.equal(par, icol) == 0);
}
m_pending = DelOp;
return 0;
@@ -1513,11 +2423,33 @@ Row::selrow(Par par)
const Tab& tab = m_tab;
CHK(con.getNdbOperation(m_tab) == 0);
CHKCON(con.m_op->readTuple() == 0, con);
+ Rsq rsq1(tab.m_cols);
for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
+ unsigned k2 = rsq1.next();
+ const Val& val = *m_val[k2];
const Col& col = val.m_col;
if (col.m_pk)
- CHK(val.setval(par) == 0);
+ CHK(val.equal(par) == 0);
+ }
+ return 0;
+}
+
+int
+Row::selrow(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ const Tab& tab = m_tab;
+ assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
+ CHK(con.getNdbIndexOperation(itab, tab) == 0);
+ CHKCON(con.m_op->readTuple() == 0, con);
+ Rsq rsq1(itab.m_icols);
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ unsigned k2 = rsq1.next();
+ const ICol& icol = *itab.m_icol[k2];
+ const Col& col = icol.m_col;
+ unsigned m = col.m_num;
+ const Val& val = *m_val[m];
+ CHK(val.equal(par, icol) == 0);
}
return 0;
}
@@ -1527,8 +2459,10 @@ Row::setrow(Par par)
{
Con& con = par.con();
const Tab& tab = m_tab;
+ Rsq rsq1(tab.m_cols);
for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val = *m_val[k];
+ unsigned k2 = rsq1.next();
+ const Val& val = *m_val[k2];
const Col& col = val.m_col;
if (! col.m_pk)
CHK(val.setval(par) == 0);
@@ -1538,7 +2472,7 @@ Row::setrow(Par par)
}
int
-Row::cmp(const Row& row2) const
+Row::cmp(Par par, const Row& row2) const
{
const Tab& tab = m_tab;
assert(&tab == &row2.m_tab);
@@ -1546,13 +2480,47 @@ Row::cmp(const Row& row2) const
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)
+ if ((c = val.cmp(par, val2)) != 0)
+ break;
+ }
+ return c;
+}
+
+int
+Row::cmp(Par par, const Row& row2, const ITab& itab) const
+{
+ const Tab& tab = m_tab;
+ int c = 0;
+ for (unsigned i = 0; i < itab.m_icols; i++) {
+ const ICol& icol = *itab.m_icol[i];
+ const Col& col = icol.m_col;
+ unsigned k = col.m_num;
+ assert(k < tab.m_cols);
+ const Val& val = *m_val[k];
+ const Val& val2 = *row2.m_val[k];
+ if ((c = val.cmp(par, val2)) != 0)
break;
}
return c;
}
static NdbOut&
+operator<<(NdbOut& out, const Row::Op op)
+{
+ if (op == Row::NoOp)
+ out << "NoOp";
+ else if (op == Row::InsOp)
+ out << "InsOp";
+ else if (op == Row::UpdOp)
+ out << "UpdOp";
+ else if (op == Row::DelOp)
+ out << "DelOp";
+ else
+ out << op;
+ return out;
+}
+
+static NdbOut&
operator<<(NdbOut& out, const Row& row)
{
const Tab& tab = row.m_tab;
@@ -1561,10 +2529,21 @@ operator<<(NdbOut& out, const Row& row)
out << " ";
out << *row.m_val[i];
}
- out << " [exist=" << row.m_exist;
+ out << " exist=" << row.m_exist;
if (row.m_pending)
out << " pending=" << row.m_pending;
- out << "]";
+ if (row.m_dbrow != 0)
+ out << " [dbrow=" << *row.m_dbrow << "]";
+ return out;
+}
+
+static NdbOut&
+operator<<(NdbOut& out, const Row* rowptr)
+{
+ if (rowptr == 0)
+ out << "null";
+ else
+ out << *rowptr;
return out;
}
@@ -1574,38 +2553,47 @@ struct Set {
const Tab& m_tab;
unsigned m_rows;
Row** m_row;
- Row** m_saverow;
+ unsigned* m_rowkey; // maps row number (from 0) in scan to tuple key
Row* m_keyrow;
NdbRecAttr** m_rec;
Set(const Tab& tab, unsigned rows);
~Set();
void reset();
unsigned count() const;
- // row methods
+ // old and new values
bool exist(unsigned i) const;
- Row::Op pending(unsigned i) const;
+ void dbsave(unsigned i);
+ void calc(Par par, unsigned i, unsigned mask = 0);
+ bool pending(unsigned i, unsigned mask) const;
void notpending(unsigned i, ExecType et = Commit);
void notpending(const Lst& lst, ExecType et = Commit);
- void calc(Par par, unsigned i);
+ void dbdiscard(unsigned i);
+ void dbdiscard(const Lst& lst);
+ const Row& dbrow(unsigned i) const;
+ // operations
int insrow(Par par, unsigned i);
int updrow(Par par, unsigned i);
+ int updrow(Par par, const ITab& itab, unsigned i);
int delrow(Par par, unsigned i);
- int selrow(Par par, unsigned i);
+ int delrow(Par par, const ITab& itab, unsigned i);
+ int selrow(Par par, const Row& keyrow);
+ int selrow(Par par, const ITab& itab, const Row& keyrow);
+ // set and get
+ void setkey(Par par, const Row& keyrow);
+ void setkey(Par par, const ITab& itab, const Row& keyrow);
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();
+ int putval(unsigned i, bool force, unsigned n = ~0);
+ // verify
+ int verify(Par par, const Set& set2) const;
+ int verifyorder(Par par, const ITab& itab, bool descending) const;
// protect structure
NdbMutex* m_mutex;
- void lock() {
+ void lock() const {
NdbMutex_Lock(m_mutex);
}
- void unlock() {
+ void unlock() const {
NdbMutex_Unlock(m_mutex);
}
private:
@@ -1621,7 +2609,11 @@ Set::Set(const Tab& tab, unsigned rows) :
// allocate on need to save space
m_row[i] = 0;
}
- m_saverow = 0;
+ m_rowkey = new unsigned [m_rows];
+ for (unsigned n = 0; n < m_rows; n++) {
+ // initialize to null
+ m_rowkey[n] = ~0;
+ }
m_keyrow = new Row(tab);
m_rec = new NdbRecAttr* [tab.m_cols];
for (unsigned k = 0; k < tab.m_cols; k++) {
@@ -1635,11 +2627,9 @@ 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_rowkey;
delete m_keyrow;
delete [] m_rec;
NdbMutex_Destroy(m_mutex);
@@ -1670,6 +2660,8 @@ Set::count() const
return count;
}
+// old and new values
+
bool
Set::exist(unsigned i) const
{
@@ -1679,27 +2671,97 @@ Set::exist(unsigned i) const
return m_row[i]->m_exist;
}
-Row::Op
-Set::pending(unsigned i) const
+void
+Set::dbsave(unsigned i)
{
- assert(i < m_rows);
- if (m_row[i] == 0) // not allocated => not pending
- return Row::NoOp;
- return m_row[i]->m_pending;
+ const Tab& tab = m_tab;
+ assert(i < m_rows && m_row[i] != 0);
+ Row& row = *m_row[i];
+ LL5("dbsave " << i << ": " << row);
+ assert(row.m_exist && ! row.m_pending && row.m_dbrow == 0);
+ // could swap pointers but making copy is safer
+ Row* rowptr = new Row(tab);
+ rowptr->copy(row);
+ row.m_dbrow = rowptr;
}
void
-Set::calc(Par par, unsigned i)
+Set::calc(Par par, unsigned i, unsigned mask)
{
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_pctrange = 40;
- row.calc(par, i);
+ row.calc(par, i, mask);
+}
+
+bool
+Set::pending(unsigned i, unsigned mask) const
+{
+ assert(i < m_rows);
+ if (m_row[i] == 0) // not allocated => not pending
+ return Row::NoOp;
+ return m_row[i]->m_pending & mask;
+}
+
+void
+Set::notpending(unsigned i, ExecType et)
+{
+ assert(m_row[i] != 0);
+ Row& row = *m_row[i];
+ if (et == Commit) {
+ if (row.m_pending == Row::InsOp)
+ row.m_exist = true;
+ if (row.m_pending == Row::DelOp)
+ row.m_exist = false;
+ } else {
+ if (row.m_pending == Row::InsOp)
+ row.m_exist = false;
+ if (row.m_pending == Row::DelOp)
+ row.m_exist = true;
+ }
+ row.m_pending = Row::NoOp;
+}
+
+void
+Set::notpending(const Lst& lst, ExecType et)
+{
+ for (unsigned j = 0; j < lst.m_cnt; j++) {
+ unsigned i = lst.m_arr[j];
+ notpending(i, et);
+ }
+}
+
+void
+Set::dbdiscard(unsigned i)
+{
+ assert(m_row[i] != 0);
+ Row& row = *m_row[i];
+ LL5("dbdiscard " << i << ": " << row);
+ assert(row.m_dbrow != 0);
+ delete row.m_dbrow;
+ row.m_dbrow = 0;
}
+const Row&
+Set::dbrow(unsigned i) const
+{
+ assert(m_row[i] != 0);
+ Row& row = *m_row[i];
+ return row.dbrow();
+}
+
+void
+Set::dbdiscard(const Lst& lst)
+{
+ for (unsigned j = 0; j < lst.m_cnt; j++) {
+ unsigned i = lst.m_arr[j];
+ dbdiscard(i);
+ }
+}
+
+// operations
+
int
Set::insrow(Par par, unsigned i)
{
@@ -1719,6 +2781,15 @@ Set::updrow(Par par, unsigned i)
}
int
+Set::updrow(Par par, const ITab& itab, unsigned i)
+{
+ assert(m_row[i] != 0);
+ Row& row = *m_row[i];
+ CHK(row.updrow(par, itab) == 0);
+ return 0;
+}
+
+int
Set::delrow(Par par, unsigned i)
{
assert(m_row[i] != 0);
@@ -1728,16 +2799,68 @@ Set::delrow(Par par, unsigned i)
}
int
-Set::selrow(Par par, unsigned i)
+Set::delrow(Par par, const ITab& itab, unsigned i)
+{
+ assert(m_row[i] != 0);
+ Row& row = *m_row[i];
+ CHK(row.delrow(par, itab) == 0);
+ return 0;
+}
+
+int
+Set::selrow(Par par, const Row& keyrow)
{
Con& con = par.con();
- m_keyrow->calc(par, i);
+ const Tab& tab = par.tab();
+ setkey(par, keyrow);
+ LL5("selrow " << tab.m_name << ": keyrow: " << keyrow);
CHK(m_keyrow->selrow(par) == 0);
CHK(getval(par) == 0);
return 0;
}
int
+Set::selrow(Par par, const ITab& itab, const Row& keyrow)
+{
+ Con& con = par.con();
+ setkey(par, itab, keyrow);
+ LL5("selrow " << itab.m_name << ": keyrow: " << keyrow);
+ CHK(m_keyrow->selrow(par, itab) == 0);
+ CHK(getval(par) == 0);
+ return 0;
+}
+
+// set and get
+
+void
+Set::setkey(Par par, const Row& keyrow)
+{
+ const Tab& tab = m_tab;
+ for (unsigned k = 0; k < tab.m_cols; k++) {
+ const Col& col = *tab.m_col[k];
+ if (col.m_pk) {
+ Val& val1 = *m_keyrow->m_val[k];
+ const Val& val2 = *keyrow.dbrow().m_val[k];
+ val1.copy(val2);
+ }
+ }
+}
+
+void
+Set::setkey(Par par, const ITab& itab, const Row& keyrow)
+{
+ const Tab& tab = m_tab;
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ const ICol& icol = *itab.m_icol[k];
+ const Col& col = icol.m_col;
+ unsigned m = col.m_num;
+ Val& val1 = *m_keyrow->m_val[m];
+ const Val& val2 = *keyrow.dbrow().m_val[m];
+ val1.copy(val2);
+ }
+}
+
+int
Set::setrow(Par par, unsigned i)
{
Con& con = par.con();
@@ -1751,8 +2874,10 @@ Set::getval(Par par)
{
Con& con = par.con();
const Tab& tab = m_tab;
+ Rsq rsq1(tab.m_cols);
for (unsigned k = 0; k < tab.m_cols; k++) {
- CHK(con.getValue(k, m_rec[k]) == 0);
+ unsigned k2 = rsq1.next();
+ CHK(con.getValue(k2, m_rec[k2]) == 0);
}
return 0;
}
@@ -1760,16 +2885,18 @@ Set::getval(Par par)
int
Set::getkey(Par par, unsigned* i)
{
- assert(m_rec[0] != 0);
- const char* aRef0 = m_rec[0]->aRef();
- Uint32 key = *(const Uint32*)aRef0;
+ const Tab& tab = m_tab;
+ unsigned k = tab.m_keycol;
+ assert(m_rec[k] != 0);
+ const char* aRef = m_rec[k]->aRef();
+ Uint32 key = *(const Uint32*)aRef;
CHK(key < m_rows);
*i = key;
return 0;
}
int
-Set::putval(unsigned i, bool force)
+Set::putval(unsigned i, bool force, unsigned n)
{
const Tab& tab = m_tab;
if (m_row[i] == 0)
@@ -1790,82 +2917,53 @@ Set::putval(unsigned i, bool force)
}
if (! row.m_exist)
row.m_exist = true;
+ if (n != ~0)
+ m_rowkey[n] = i;
return 0;
}
-void
-Set::notpending(unsigned i, ExecType et)
-{
- assert(m_row[i] != 0);
- Row& row = *m_row[i];
- if (et == Commit) {
- if (row.m_pending == Row::InsOp)
- row.m_exist = true;
- if (row.m_pending == Row::DelOp)
- row.m_exist = false;
- } else {
- if (row.m_pending == Row::InsOp)
- row.m_exist = false;
- if (row.m_pending == Row::DelOp)
- row.m_exist = true;
- }
- row.m_pending = Row::NoOp;
-}
-
-void
-Set::notpending(const Lst& lst, ExecType et)
-{
- for (unsigned j = 0; j < lst.m_cnt; j++) {
- unsigned i = lst.m_arr[j];
- notpending(i, et);
- }
-}
-
int
-Set::verify(const Set& set2) const
+Set::verify(Par par, const Set& set2) const
{
- const Tab& tab = m_tab;
- assert(&tab == &set2.m_tab && m_rows == set2.m_rows);
+ assert(&m_tab == &set2.m_tab && m_rows == set2.m_rows);
+ LL4("verify set1 count=" << count() << " vs set2 count=" << set2.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);
+ bool ok = true;
+ if (exist(i) != set2.exist(i)) {
+ ok = false;
+ } else if (exist(i)) {
+ if (dbrow(i).verify(par, set2.dbrow(i)) != 0)
+ ok = false;
+ }
+ if (! ok) {
+ LL1("verify failed: key=" << i << " row1=" << m_row[i] << " row2=" << set2.m_row[i]);
+ CHK(0 == 1);
+ }
}
return 0;
}
-void
-Set::savepoint()
+int
+Set::verifyorder(Par par, const ITab& itab, bool descending) const
{
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]);
- }
+ for (unsigned n = 0; n < m_rows; n++) {
+ unsigned i2 = m_rowkey[n];
+ if (i2 == ~0)
+ break;
+ if (n == 0)
+ continue;
+ unsigned i1 = m_rowkey[n - 1];
+ assert(i1 < m_rows && i2 < m_rows);
+ const Row& row1 = *m_row[i1];
+ const Row& row2 = *m_row[i2];
+ assert(row1.m_exist && row2.m_exist);
+ if (! descending)
+ CHK(row1.cmp(par, row2, itab) <= 0);
+ else
+ CHK(row1.cmp(par, row2, itab) >= 0);
}
-}
-
-void
-Set::commit()
-{
- delete [] m_saverow;
- m_saverow = 0;
-}
-
-void
-Set::rollback()
-{
- assert(m_saverow != 0);
- m_row = m_saverow;
- m_saverow = 0;
+ return 0;
}
static NdbOut&
@@ -1887,6 +2985,7 @@ struct BVal : public Val {
int m_type;
BVal(const ICol& icol);
int setbnd(Par par) const;
+ int setflt(Par par) const;
};
BVal::BVal(const ICol& icol) :
@@ -1906,16 +3005,37 @@ BVal::setbnd(Par par) const
return 0;
}
+int
+BVal::setflt(Par par) const
+{
+ static unsigned index_bound_to_filter_bound[5] = {
+ NdbScanFilter::COND_GE,
+ NdbScanFilter::COND_GT,
+ NdbScanFilter::COND_LE,
+ NdbScanFilter::COND_LT,
+ NdbScanFilter::COND_EQ
+ };
+ Con& con = par.con();
+ assert(g_compare_null || ! m_null);
+ const char* addr = ! m_null ? (const char*)dataaddr() : 0;
+ const ICol& icol = m_icol;
+ const Col& col = icol.m_col;
+ unsigned length = col.m_bytesize;
+ unsigned cond = index_bound_to_filter_bound[m_type];
+ CHK(con.setFilter(col.m_num, cond, addr, length) == 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;
+ out << "type=" << bval.m_type;
+ out << " icol=" << icol.m_num;
+ out << " col=" << col.m_num << "," << col.m_name;
+ out << " value=" << val;
return out;
}
@@ -1933,7 +3053,8 @@ struct BSet {
void calc(Par par);
void calcpk(Par par, unsigned i);
int setbnd(Par par) const;
- void filter(const Set& set, Set& set2) const;
+ int setflt(Par par) const;
+ void filter(Par par, const Set& set, Set& set2) const;
};
BSet::BSet(const Tab& tab, const ITab& itab, unsigned rows) :
@@ -1967,12 +3088,15 @@ void
BSet::calc(Par par)
{
const ITab& itab = m_itab;
+ par.m_pctrange = par.m_pctbrange;
reset();
for (unsigned k = 0; k < itab.m_icols; k++) {
- const ICol& icol = itab.m_icol[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)
+ if (m_bvals == 0 && urandom(100) == 0)
+ return;
+ if (m_bvals != 0 && urandom(3) == 0)
return;
assert(m_bvals < m_alloc);
BVal& bval = *new BVal(icol);
@@ -1991,17 +3115,19 @@ BSet::calc(Par par)
bval.m_type = 4;
if (k + 1 < itab.m_icols)
bval.m_type = 4;
- // value generation parammeters
if (! g_compare_null)
par.m_pctnull = 0;
- par.m_pctrange = 50; // bit higher
+ if (bval.m_type == 0 || bval.m_type == 1)
+ par.m_bdir = -1;
+ if (bval.m_type == 2 || bval.m_type == 3)
+ par.m_bdir = +1;
do {
- bval.calc(par, 0);
+ bval.calcnokey(par);
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)
+ if (bv1.cmp(par, bv2) > 0 && urandom(100) != 0)
continue;
}
} while (0);
@@ -2018,7 +3144,7 @@ BSet::calcpk(Par par, unsigned i)
const ITab& itab = m_itab;
reset();
for (unsigned k = 0; k < itab.m_icols; k++) {
- const ICol& icol = itab.m_icol[k];
+ const ICol& icol = *itab.m_icol[k];
const Col& col = icol.m_col;
assert(col.m_pk);
assert(m_bvals < m_alloc);
@@ -2033,26 +3159,48 @@ int
BSet::setbnd(Par par) const
{
if (m_bvals != 0) {
- unsigned p1 = urandom(m_bvals);
- unsigned p2 = 10009; // prime
- // random order
+ Rsq rsq1(m_bvals);
for (unsigned j = 0; j < m_bvals; j++) {
- unsigned k = p1 + p2 * j;
- const BVal& bval = *m_bval[k % m_bvals];
+ unsigned j2 = rsq1.next();
+ const BVal& bval = *m_bval[j2];
CHK(bval.setbnd(par) == 0);
}
// duplicate
if (urandom(5) == 0) {
- unsigned k = urandom(m_bvals);
- const BVal& bval = *m_bval[k];
+ unsigned j3 = urandom(m_bvals);
+ const BVal& bval = *m_bval[j3];
CHK(bval.setbnd(par) == 0);
}
}
return 0;
}
+int
+BSet::setflt(Par par) const
+{
+ Con& con = par.con();
+ CHK(con.getNdbScanFilter() == 0);
+ CHK(con.beginFilter(NdbScanFilter::AND) == 0);
+ if (m_bvals != 0) {
+ Rsq rsq1(m_bvals);
+ for (unsigned j = 0; j < m_bvals; j++) {
+ unsigned j2 = rsq1.next();
+ const BVal& bval = *m_bval[j2];
+ CHK(bval.setflt(par) == 0);
+ }
+ // duplicate
+ if (urandom(5) == 0) {
+ unsigned j3 = urandom(m_bvals);
+ const BVal& bval = *m_bval[j3];
+ CHK(bval.setflt(par) == 0);
+ }
+ }
+ CHK(con.endFilter() == 0);
+ return 0;
+}
+
void
-BSet::filter(const Set& set, Set& set2) const
+BSet::filter(Par par, const Set& set, Set& set2) const
{
const Tab& tab = m_tab;
const ITab& itab = m_itab;
@@ -2061,11 +3209,13 @@ BSet::filter(const Set& set, Set& set2) const
for (unsigned i = 0; i < set.m_rows; i++) {
if (! set.exist(i))
continue;
- const Row& row = *set.m_row[i];
+ set.lock();
+ const Row& row = set.dbrow(i);
+ set.unlock();
if (! g_store_null_key) {
bool ok1 = false;
for (unsigned k = 0; k < itab.m_icols; k++) {
- const ICol& icol = itab.m_icol[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) {
@@ -2082,7 +3232,8 @@ BSet::filter(const Set& set, Set& set2) const
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);
+ int ret = bval.cmp(par, val);
+ LL5("cmp: ret=" << ret << " " << bval << " vs " << val);
if (bval.m_type == 0)
ok2 = (ret <= 0);
else if (bval.m_type == 1)
@@ -2106,7 +3257,6 @@ BSet::filter(const Set& set, Set& set2) const
Row& row2 = *set2.m_row[i];
assert(! row2.m_exist);
row2.copy(row);
- row2.m_exist = true;
}
}
@@ -2115,9 +3265,8 @@ 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;
+ out << " [bound " << j << ": " << bval << "]";
}
return out;
}
@@ -2128,15 +3277,16 @@ static int
pkinsert(Par par)
{
Con& con = par.con();
+ const Tab& tab = par.tab();
Set& set = par.set();
- LL3("pkinsert");
+ LL3("pkinsert " << tab.m_name);
CHK(con.startTransaction() == 0);
Lst lst;
for (unsigned j = 0; j < par.m_rows; j++) {
unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows);
unsigned i = thrrow(par, j2);
set.lock();
- if (set.exist(i) || set.pending(i)) {
+ if (set.exist(i) || set.pending(i, Row::AnyOp)) {
set.unlock();
continue;
}
@@ -2152,7 +3302,7 @@ pkinsert(Par par)
CHK(con.execute(et, deadlock, nospace) == 0);
con.closeTransaction();
if (deadlock) {
- LL1("pkinsert: stop on deadlock");
+ LL1("pkinsert: stop on deadlock [at 1]");
return 0;
}
if (nospace) {
@@ -2173,7 +3323,7 @@ pkinsert(Par par)
CHK(con.execute(et, deadlock, nospace) == 0);
con.closeTransaction();
if (deadlock) {
- LL1("pkinsert: stop on deadlock");
+ LL1("pkinsert: stop on deadlock [at 2]");
return 0;
}
if (nospace) {
@@ -2187,14 +3337,15 @@ pkinsert(Par par)
}
con.closeTransaction();
return 0;
-};
+}
static int
pkupdate(Par par)
{
Con& con = par.con();
+ const Tab& tab = par.tab();
Set& set = par.set();
- LL3("pkupdate");
+ LL3("pkupdate " << tab.m_name);
CHK(con.startTransaction() == 0);
Lst lst;
bool deadlock = false;
@@ -2203,10 +3354,11 @@ pkupdate(Par par)
unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows);
unsigned i = thrrow(par, j2);
set.lock();
- if (! set.exist(i) || set.pending(i)) {
+ if (! set.exist(i) || set.pending(i, Row::AnyOp)) {
set.unlock();
continue;
}
+ set.dbsave(i);
set.calc(par, i);
CHK(set.updrow(par, i) == 0);
set.unlock();
@@ -2218,16 +3370,17 @@ pkupdate(Par par)
ExecType et = randompct(par.m_abortpct) ? Rollback : Commit;
CHK(con.execute(et, deadlock, nospace) == 0);
if (deadlock) {
- LL1("pkupdate: stop on deadlock");
+ LL1("pkupdate: stop on deadlock [at 1]");
break;
}
if (nospace) {
- LL1("pkupdate: cnt=" << j << " stop on nospace");
+ LL1("pkupdate: cnt=" << j << " stop on nospace [at 1]");
break;
}
con.closeTransaction();
set.lock();
set.notpending(lst, et);
+ set.dbdiscard(lst);
set.unlock();
lst.reset();
CHK(con.startTransaction() == 0);
@@ -2239,25 +3392,27 @@ pkupdate(Par par)
ExecType et = randompct(par.m_abortpct) ? Rollback : Commit;
CHK(con.execute(et, deadlock, nospace) == 0);
if (deadlock) {
- LL1("pkupdate: stop on deadlock");
+ LL1("pkupdate: stop on deadlock [at 2]");
} else if (nospace) {
- LL1("pkupdate: end: stop on nospace");
+ LL1("pkupdate: end: stop on nospace [at 2]");
} else {
set.lock();
set.notpending(lst, et);
+ set.dbdiscard(lst);
set.unlock();
}
}
con.closeTransaction();
return 0;
-};
+}
static int
pkdelete(Par par)
{
Con& con = par.con();
+ const Tab& tab = par.tab();
Set& set = par.set();
- LL3("pkdelete");
+ LL3("pkdelete " << tab.m_name);
CHK(con.startTransaction() == 0);
Lst lst;
bool deadlock = false;
@@ -2266,7 +3421,7 @@ pkdelete(Par par)
unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows);
unsigned i = thrrow(par, j2);
set.lock();
- if (! set.exist(i) || set.pending(i)) {
+ if (! set.exist(i) || set.pending(i, Row::AnyOp)) {
set.unlock();
continue;
}
@@ -2280,7 +3435,7 @@ pkdelete(Par par)
ExecType et = randompct(par.m_abortpct) ? Rollback : Commit;
CHK(con.execute(et, deadlock, nospace) == 0);
if (deadlock) {
- LL1("pkdelete: stop on deadlock");
+ LL1("pkdelete: stop on deadlock [at 1]");
break;
}
con.closeTransaction();
@@ -2297,7 +3452,7 @@ pkdelete(Par par)
ExecType et = randompct(par.m_abortpct) ? Rollback : Commit;
CHK(con.execute(et, deadlock, nospace) == 0);
if (deadlock) {
- LL1("pkdelete: stop on deadlock");
+ LL1("pkdelete: stop on deadlock [at 2]");
} else {
set.lock();
set.notpending(lst, et);
@@ -2306,7 +3461,7 @@ pkdelete(Par par)
}
con.closeTransaction();
return 0;
-};
+}
static int
pkread(Par par)
@@ -2314,19 +3469,19 @@ pkread(Par par)
Con& con = par.con();
const Tab& tab = par.tab();
Set& set = par.set();
- LL3((par.m_verify ? "pkverify " : "pkread ") << tab.m_name);
+ LL3("pkread " << tab.m_name << " verify=" << par.m_verify);
// expected
const Set& set1 = set;
Set set2(tab, set.m_rows);
for (unsigned i = 0; i < set.m_rows; i++) {
set.lock();
- if (! set.exist(i) || set.pending(i)) {
+ if (! set.exist(i)) {
set.unlock();
continue;
}
set.unlock();
CHK(con.startTransaction() == 0);
- CHK(set2.selrow(par, i) == 0);
+ CHK(set2.selrow(par, *set1.m_row[i]) == 0);
CHK(con.execute(Commit) == 0);
unsigned i2 = (unsigned)-1;
CHK(set2.getkey(par, &i2) == 0 && i == i2);
@@ -2335,7 +3490,7 @@ pkread(Par par)
con.closeTransaction();
}
if (par.m_verify)
- CHK(set1.verify(set2) == 0);
+ CHK(set1.verify(par, set2) == 0);
return 0;
}
@@ -2364,6 +3519,148 @@ pkreadfast(Par par, unsigned count)
return 0;
}
+// hash index operations
+
+static int
+hashindexupdate(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ Set& set = par.set();
+ LL3("hashindexupdate " << itab.m_name);
+ CHK(con.startTransaction() == 0);
+ Lst lst;
+ bool deadlock = false;
+ bool nospace = false;
+ for (unsigned j = 0; j < par.m_rows; j++) {
+ unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows);
+ unsigned i = thrrow(par, j2);
+ set.lock();
+ if (! set.exist(i) || set.pending(i, Row::AnyOp)) {
+ set.unlock();
+ continue;
+ }
+ set.dbsave(i);
+ // index key columns are not re-calculated
+ set.calc(par, i, itab.m_colmask);
+ CHK(set.updrow(par, itab, i) == 0);
+ set.unlock();
+ LL4("hashindexupdate " << i << ": " << *set.m_row[i]);
+ lst.push(i);
+ if (lst.cnt() == par.m_batch) {
+ deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock, nospace) == 0);
+ if (deadlock) {
+ LL1("hashindexupdate: stop on deadlock [at 1]");
+ break;
+ }
+ con.closeTransaction();
+ set.lock();
+ set.notpending(lst);
+ set.dbdiscard(lst);
+ set.unlock();
+ lst.reset();
+ CHK(con.startTransaction() == 0);
+ }
+ }
+ if (! deadlock && lst.cnt() != 0) {
+ deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock, nospace) == 0);
+ if (deadlock) {
+ LL1("hashindexupdate: stop on deadlock [at 2]");
+ } else {
+ set.lock();
+ set.notpending(lst);
+ set.dbdiscard(lst);
+ set.unlock();
+ }
+ }
+ con.closeTransaction();
+ return 0;
+}
+
+static int
+hashindexdelete(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ Set& set = par.set();
+ LL3("hashindexdelete " << itab.m_name);
+ CHK(con.startTransaction() == 0);
+ Lst lst;
+ bool deadlock = false;
+ bool nospace = false;
+ for (unsigned j = 0; j < par.m_rows; j++) {
+ unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows);
+ unsigned i = thrrow(par, j2);
+ set.lock();
+ if (! set.exist(i) || set.pending(i, Row::AnyOp)) {
+ set.unlock();
+ continue;
+ }
+ CHK(set.delrow(par, itab, i) == 0);
+ set.unlock();
+ LL4("hashindexdelete " << i << ": " << *set.m_row[i]);
+ lst.push(i);
+ if (lst.cnt() == par.m_batch) {
+ deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock, nospace) == 0);
+ if (deadlock) {
+ LL1("hashindexdelete: stop on deadlock [at 1]");
+ break;
+ }
+ con.closeTransaction();
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ lst.reset();
+ CHK(con.startTransaction() == 0);
+ }
+ }
+ if (! deadlock && lst.cnt() != 0) {
+ deadlock = par.m_deadlock;
+ CHK(con.execute(Commit, deadlock, nospace) == 0);
+ if (deadlock) {
+ LL1("hashindexdelete: stop on deadlock [at 2]");
+ } else {
+ set.lock();
+ set.notpending(lst);
+ set.unlock();
+ }
+ }
+ con.closeTransaction();
+ return 0;
+}
+
+static int
+hashindexread(Par par, const ITab& itab)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ Set& set = par.set();
+ LL3("hashindexread " << itab.m_name << " verify=" << par.m_verify);
+ // expected
+ const Set& set1 = set;
+ Set set2(tab, set.m_rows);
+ for (unsigned i = 0; i < set.m_rows; i++) {
+ set.lock();
+ if (! set.exist(i)) {
+ set.unlock();
+ continue;
+ }
+ set.unlock();
+ CHK(con.startTransaction() == 0);
+ CHK(set2.selrow(par, itab, *set1.m_row[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.count() << ": " << *set2.m_row[i]);
+ con.closeTransaction();
+ }
+ if (par.m_verify)
+ CHK(set1.verify(par, set2) == 0);
+ return 0;
+}
+
// scan read
static int
@@ -2374,26 +3671,35 @@ scanreadtable(Par par)
const Set& set = par.set();
// expected
const Set& set1 = set;
- LL3((par.m_verify ? "scanverify " : "scanread ") << tab.m_name);
+ LL3("scanread " << tab.m_name << " lockmode=" << par.m_lockmode << " tupscan=" << par.m_tupscan << " expect=" << set1.count() << " verify=" << par.m_verify);
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(tab) == 0);
- CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0);
+ CHK(con.readTuples(par) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
+ unsigned n = 0;
+ bool deadlock = false;
while (1) {
int ret;
- CHK((ret = con.nextScanResult(true)) == 0 || ret == 1);
+ deadlock = par.m_deadlock;
+ CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1);
if (ret == 1)
break;
+ if (deadlock) {
+ LL1("scanreadtable: stop on deadlock");
+ break;
+ }
unsigned i = (unsigned)-1;
CHK(set2.getkey(par, &i) == 0);
- CHK(set2.putval(i, false) == 0);
- LL4("row " << set2.count() << ": " << *set2.m_row[i]);
+ CHK(set2.putval(i, false, n) == 0);
+ LL4("row " << n << ": " << *set2.m_row[i]);
+ n++;
}
con.closeTransaction();
if (par.m_verify)
- CHK(set1.verify(set2) == 0);
+ CHK(set1.verify(par, set2) == 0);
+ LL3("scanread " << tab.m_name << " done rows=" << n);
return 0;
}
@@ -2406,7 +3712,7 @@ scanreadtablefast(Par par, unsigned countcheck)
LL3("scanfast " << tab.m_name);
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(tab) == 0);
- CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0);
+ CHK(con.readTuples(par) == 0);
// get 1st column
NdbRecAttr* rec;
CHK(con.getValue((Uint32)0, rec) == 0);
@@ -2425,37 +3731,60 @@ scanreadtablefast(Par par, unsigned countcheck)
}
static int
-scanreadindex(Par par, const ITab& itab, const BSet& bset)
+scanreadindex(Par par, const ITab& itab, BSet& bset, bool calc)
{
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);
+ if (calc) {
+ while (true) {
+ bset.calc(par);
+ bset.filter(par, set, set1);
+ unsigned n = set1.count();
+ // prefer proper subset
+ if (0 < n && n < set.m_rows)
+ break;
+ if (urandom(3) == 0)
+ break;
+ set1.reset();
+ }
+ } else {
+ bset.filter(par, set, set1);
+ }
+ LL3("scanread " << itab.m_name << " " << bset << " lockmode=" << par.m_lockmode << " expect=" << set1.count() << " verify=" << par.m_verify << " ordered=" << par.m_ordered << " descending=" << par.m_descending);
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
- CHK(con.getNdbScanOperation(itab, tab) == 0);
- CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0);
+ CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
+ CHK(con.readIndexTuples(par) == 0);
CHK(bset.setbnd(par) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
+ unsigned n = 0;
+ bool deadlock = false;
while (1) {
int ret;
- CHK((ret = con.nextScanResult(true)) == 0 || ret == 1);
+ deadlock = par.m_deadlock;
+ CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1);
if (ret == 1)
break;
+ if (deadlock) {
+ LL1("scanreadindex: stop on deadlock");
+ 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.count() << ": " << *set2.m_row[i]);
+ CHK(set2.putval(i, par.m_dups, n) == 0);
+ LL4("key " << i << " row " << n << ": " << *set2.m_row[i]);
+ n++;
}
con.closeTransaction();
- if (par.m_verify)
- CHK(set1.verify(set2) == 0);
+ if (par.m_verify) {
+ CHK(set1.verify(par, set2) == 0);
+ if (par.m_ordered)
+ CHK(set2.verifyorder(par, itab, par.m_descending) == 0);
+ }
+ LL3("scanread " << itab.m_name << " done rows=" << n);
return 0;
}
@@ -2465,11 +3794,11 @@ scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countche
Con& con = par.con();
const Tab& tab = par.tab();
const Set& set = par.set();
- LL3("scanfast " << itab.m_name << " bounds=" << bset.m_bvals);
+ LL3("scanfast " << itab.m_name << " " << bset);
LL4(bset);
CHK(con.startTransaction() == 0);
- CHK(con.getNdbScanOperation(itab, tab) == 0);
- CHK(con.openScanRead(par.m_scanbat, par.m_scanpar) == 0);
+ CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
+ CHK(con.readIndexTuples(par) == 0);
CHK(bset.setbnd(par) == 0);
// get 1st column
NdbRecAttr* rec;
@@ -2489,13 +3818,71 @@ scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countche
}
static int
+scanreadfilter(Par par, const ITab& itab, BSet& bset, bool calc)
+{
+ Con& con = par.con();
+ const Tab& tab = par.tab();
+ const Set& set = par.set();
+ Set set1(tab, set.m_rows);
+ if (calc) {
+ while (true) {
+ bset.calc(par);
+ bset.filter(par, set, set1);
+ unsigned n = set1.count();
+ // prefer proper subset
+ if (0 < n && n < set.m_rows)
+ break;
+ if (urandom(3) == 0)
+ break;
+ set1.reset();
+ }
+ } else {
+ bset.filter(par, set, set1);
+ }
+ LL3("scanfilter " << itab.m_name << " " << bset << " lockmode=" << par.m_lockmode << " expect=" << set1.count() << " verify=" << par.m_verify);
+ Set set2(tab, set.m_rows);
+ CHK(con.startTransaction() == 0);
+ CHK(con.getNdbScanOperation(tab) == 0);
+ CHK(con.readTuples(par) == 0);
+ CHK(bset.setflt(par) == 0);
+ set2.getval(par);
+ CHK(con.executeScan() == 0);
+ unsigned n = 0;
+ bool deadlock = false;
+ while (1) {
+ int ret;
+ deadlock = par.m_deadlock;
+ CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ if (deadlock) {
+ LL1("scanfilter: stop on deadlock");
+ break;
+ }
+ unsigned i = (unsigned)-1;
+ CHK(set2.getkey(par, &i) == 0);
+ CHK(set2.putval(i, par.m_dups, n) == 0);
+ LL4("key " << i << " row " << n << ": " << *set2.m_row[i]);
+ n++;
+ }
+ con.closeTransaction();
+ if (par.m_verify) {
+ CHK(set1.verify(par, set2) == 0);
+ }
+ LL3("scanfilter " << itab.m_name << " done rows=" << n);
+ return 0;
+}
+
+static int
scanreadindex(Par par, const ITab& itab)
{
const Tab& tab = par.tab();
for (unsigned i = 0; i < par.m_subsubloop; i++) {
- BSet bset(tab, itab, par.m_rows);
- bset.calc(par);
- CHK(scanreadindex(par, itab, bset) == 0);
+ if (itab.m_type == ITab::OrderedIndex) {
+ BSet bset(tab, itab, par.m_rows);
+ CHK(scanreadfilter(par, itab, bset, true) == 0);
+ CHK(scanreadindex(par, itab, bset, true) == 0);
+ }
}
return 0;
}
@@ -2505,10 +3892,14 @@ scanreadindex(Par par)
{
const Tab& tab = par.tab();
for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
+ if (tab.m_itab[i] == 0)
continue;
- const ITab& itab = tab.m_itab[i];
- CHK(scanreadindex(par, itab) == 0);
+ const ITab& itab = *tab.m_itab[i];
+ if (itab.m_type == ITab::OrderedIndex) {
+ CHK(scanreadindex(par, itab) == 0);
+ } else {
+ CHK(hashindexread(par, itab) == 0);
+ }
}
return 0;
}
@@ -2516,8 +3907,7 @@ scanreadindex(Par par)
static int
scanreadall(Par par)
{
- if (par.m_no < 11)
- CHK(scanreadtable(par) == 0);
+ CHK(scanreadtable(par) == 0);
CHK(scanreadindex(par) == 0);
return 0;
}
@@ -2537,7 +3927,7 @@ static int
timescanpkindex(Par par)
{
const Tab& tab = par.tab();
- const ITab& itab = tab.m_itab[0]; // 1st index is on PK
+ const ITab& itab = *tab.m_itab[0]; // 1st index is on PK
BSet bset(tab, itab, par.m_rows);
par.tmr().on();
CHK(scanreadindexfast(par, itab, bset, par.m_totrows) == 0);
@@ -2561,7 +3951,7 @@ static int
timepkreadindex(Par par)
{
const Tab& tab = par.tab();
- const ITab& itab = tab.m_itab[0]; // 1st index is on PK
+ const ITab& itab = *tab.m_itab[0]; // 1st index is on PK
BSet bset(tab, itab, par.m_rows);
unsigned count = par.m_samples;
if (count == 0)
@@ -2586,9 +3976,10 @@ scanupdatetable(Par par)
Set& set = par.set();
LL3("scan update " << tab.m_name);
Set set2(tab, set.m_rows);
+ par.m_lockmode = NdbOperation::LM_Exclusive;
CHK(con.startTransaction() == 0);
CHK(con.getNdbScanOperation(tab) == 0);
- CHK(con.openScanExclusive(par.m_scanbat, par.m_scanpar) == 0);
+ CHK(con.readTuples(par) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
unsigned count = 0;
@@ -2598,6 +3989,7 @@ scanupdatetable(Par par)
CHK(con2.startTransaction() == 0);
Lst lst;
bool deadlock = false;
+ bool nospace = false;
while (1) {
int ret;
deadlock = par.m_deadlock;
@@ -2605,7 +3997,7 @@ scanupdatetable(Par par)
if (ret == 1)
break;
if (deadlock) {
- LL1("scanupdatetable: stop on deadlock");
+ LL1("scanupdatetable: stop on deadlock [at 1]");
break;
}
if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) {
@@ -2617,13 +4009,14 @@ scanupdatetable(Par par)
CHK(set2.getkey(par, &i) == 0);
const Row& row = *set.m_row[i];
set.lock();
- if (! set.exist(i) || set.pending(i)) {
+ if (! set.exist(i) || set.pending(i, Row::AnyOp)) {
LL4("scan update " << tab.m_name << ": skip: " << row);
} else {
CHKTRY(set2.putval(i, false) == 0, set.unlock());
CHKTRY(con.updateScanTuple(con2) == 0, set.unlock());
Par par2 = par;
par2.m_con = &con2;
+ set.dbsave(i);
set.calc(par, i);
CHKTRY(set.setrow(par2, i) == 0, set.unlock());
LL4("scan update " << tab.m_name << ": " << row);
@@ -2631,10 +4024,16 @@ scanupdatetable(Par par)
}
set.unlock();
if (lst.cnt() == par.m_batch) {
- CHK(con2.execute(Commit) == 0);
+ deadlock = par.m_deadlock;
+ CHK(con2.execute(Commit, deadlock, nospace) == 0);
+ if (deadlock) {
+ LL1("scanupdatetable: stop on deadlock [at 2]");
+ goto out;
+ }
con2.closeTransaction();
set.lock();
set.notpending(lst);
+ set.dbdiscard(lst);
set.unlock();
count += lst.cnt();
lst.reset();
@@ -2642,10 +4041,16 @@ scanupdatetable(Par par)
}
CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2);
if (ret == 2 && lst.cnt() != 0) {
- CHK(con2.execute(Commit) == 0);
+ deadlock = par.m_deadlock;
+ CHK(con2.execute(Commit, deadlock, nospace) == 0);
+ if (deadlock) {
+ LL1("scanupdatetable: stop on deadlock [at 3]");
+ goto out;
+ }
con2.closeTransaction();
set.lock();
set.notpending(lst);
+ set.dbdiscard(lst);
set.unlock();
count += lst.cnt();
lst.reset();
@@ -2655,6 +4060,7 @@ scanupdatetable(Par par)
if (ret == 1)
break;
}
+out:
con2.closeTransaction();
LL3("scan update " << tab.m_name << " rows updated=" << count);
con.closeTransaction();
@@ -2669,9 +4075,10 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
Set& set = par.set();
LL3("scan update " << itab.m_name);
Set set2(tab, set.m_rows);
+ par.m_lockmode = NdbOperation::LM_Exclusive;
CHK(con.startTransaction() == 0);
- CHK(con.getNdbScanOperation(itab, tab) == 0);
- CHK(con.openScanExclusive(par.m_scanbat, par.m_scanpar) == 0);
+ CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
+ CHK(con.readTuples(par) == 0);
CHK(bset.setbnd(par) == 0);
set2.getval(par);
CHK(con.executeScan() == 0);
@@ -2682,6 +4089,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
CHK(con2.startTransaction() == 0);
Lst lst;
bool deadlock = false;
+ bool nospace = false;
while (1) {
int ret;
deadlock = par.m_deadlock;
@@ -2689,7 +4097,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
if (ret == 1)
break;
if (deadlock) {
- LL1("scanupdateindex: stop on deadlock");
+ LL1("scanupdateindex: stop on deadlock [at 1]");
break;
}
if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) {
@@ -2701,13 +4109,14 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
CHK(set2.getkey(par, &i) == 0);
const Row& row = *set.m_row[i];
set.lock();
- if (! set.exist(i) || set.pending(i)) {
+ if (! set.exist(i) || set.pending(i, Row::AnyOp)) {
LL4("scan update " << itab.m_name << ": skip: " << row);
} else {
CHKTRY(set2.putval(i, par.m_dups) == 0, set.unlock());
CHKTRY(con.updateScanTuple(con2) == 0, set.unlock());
Par par2 = par;
par2.m_con = &con2;
+ set.dbsave(i);
set.calc(par, i);
CHKTRY(set.setrow(par2, i) == 0, set.unlock());
LL4("scan update " << itab.m_name << ": " << row);
@@ -2715,10 +4124,16 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
}
set.unlock();
if (lst.cnt() == par.m_batch) {
- CHK(con2.execute(Commit) == 0);
+ deadlock = par.m_deadlock;
+ CHK(con2.execute(Commit, deadlock, nospace) == 0);
+ if (deadlock) {
+ LL1("scanupdateindex: stop on deadlock [at 2]");
+ goto out;
+ }
con2.closeTransaction();
set.lock();
set.notpending(lst);
+ set.dbdiscard(lst);
set.unlock();
count += lst.cnt();
lst.reset();
@@ -2726,10 +4141,16 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
}
CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2);
if (ret == 2 && lst.cnt() != 0) {
- CHK(con2.execute(Commit) == 0);
+ deadlock = par.m_deadlock;
+ CHK(con2.execute(Commit, deadlock, nospace) == 0);
+ if (deadlock) {
+ LL1("scanupdateindex: stop on deadlock [at 3]");
+ goto out;
+ }
con2.closeTransaction();
set.lock();
set.notpending(lst);
+ set.dbdiscard(lst);
set.unlock();
count += lst.cnt();
lst.reset();
@@ -2737,6 +4158,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
}
} while (ret == 0);
}
+out:
con2.closeTransaction();
LL3("scan update " << itab.m_name << " rows updated=" << count);
con.closeTransaction();
@@ -2748,9 +4170,13 @@ scanupdateindex(Par par, const ITab& itab)
{
const Tab& tab = par.tab();
for (unsigned i = 0; i < par.m_subsubloop; i++) {
- BSet bset(tab, itab, par.m_rows);
- bset.calc(par);
- CHK(scanupdateindex(par, itab, bset) == 0);
+ if (itab.m_type == ITab::OrderedIndex) {
+ BSet bset(tab, itab, par.m_rows);
+ bset.calc(par);
+ CHK(scanupdateindex(par, itab, bset) == 0);
+ } else {
+ CHK(hashindexupdate(par, itab) == 0);
+ }
}
return 0;
}
@@ -2760,9 +4186,9 @@ scanupdateindex(Par par)
{
const Tab& tab = par.tab();
for (unsigned i = 0; i < tab.m_itabs; i++) {
- if (! useindex(i))
+ if (tab.m_itab[i] == 0)
continue;
- const ITab& itab = tab.m_itab[i];
+ const ITab& itab = *tab.m_itab[i];
CHK(scanupdateindex(par, itab) == 0);
}
return 0;
@@ -2788,6 +4214,7 @@ readverify(Par par)
LL2("skip verify in this version"); // implement in 5.0 version
par.m_verify = false;
}
+ par.m_lockmode = NdbOperation::LM_CommittedRead;
CHK(pkread(par) == 0);
CHK(scanreadall(par) == 0);
return 0;
@@ -2799,43 +4226,106 @@ readverifyfull(Par par)
if (par.m_noverify)
return 0;
par.m_verify = true;
- if (par.m_no == 0)
+ if (par.m_abortpct != 0) {
+ LL2("skip verify in this version"); // implement in 5.0 version
+ par.m_verify = false;
+ }
+ par.m_lockmode = NdbOperation::LM_CommittedRead;
+ const Tab& tab = par.tab();
+ if (par.m_no == 0) {
+ // thread 0 scans table
CHK(scanreadtable(par) == 0);
- else {
- const Tab& tab = par.tab();
- unsigned i = par.m_no;
- if (i <= tab.m_itabs && useindex(i)) {
- const ITab& itab = tab.m_itab[i - 1];
+ // once more via tup scan
+ par.m_tupscan = true;
+ if (NDB_VERSION < MAKE_VERSION(5, 1, 0)) //TODO
+ CHK(scanreadtable(par) == 0);
+ }
+ // each thread scans different indexes
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ if (i % par.m_threads != par.m_no)
+ continue;
+ if (tab.m_itab[i] == 0)
+ continue;
+ const ITab& itab = *tab.m_itab[i];
+ if (itab.m_type == ITab::OrderedIndex) {
BSet bset(tab, itab, par.m_rows);
- CHK(scanreadindex(par, itab, bset) == 0);
+ CHK(scanreadindex(par, itab, bset, false) == 0);
+ } else {
+ CHK(hashindexread(par, itab) == 0);
}
}
return 0;
}
static int
+readverifyindex(Par par)
+{
+ if (par.m_noverify)
+ return 0;
+ par.m_verify = true;
+ par.m_lockmode = NdbOperation::LM_CommittedRead;
+ unsigned sel = urandom(10);
+ if (sel < 9) {
+ par.m_ordered = true;
+ par.m_descending = (sel < 5);
+ }
+ CHK(scanreadindex(par) == 0);
+ return 0;
+}
+
+static int
pkops(Par par)
{
+ const Tab& tab = par.tab();
par.m_randomkey = true;
for (unsigned i = 0; i < par.m_subsubloop; i++) {
+ unsigned j = 0;
+ while (j < tab.m_itabs) {
+ if (tab.m_itab[j] != 0) {
+ const ITab& itab = *tab.m_itab[j];
+ if (itab.m_type == ITab::UniqueHashIndex && urandom(5) == 0)
+ break;
+ }
+ j++;
+ }
unsigned sel = urandom(10);
if (par.m_slno % 2 == 0) {
// favor insert
if (sel < 8) {
CHK(pkinsert(par) == 0);
} else if (sel < 9) {
- CHK(pkupdate(par) == 0);
+ if (j == tab.m_itabs)
+ CHK(pkupdate(par) == 0);
+ else {
+ const ITab& itab = *tab.m_itab[j];
+ CHK(hashindexupdate(par, itab) == 0);
+ }
} else {
- CHK(pkdelete(par) == 0);
+ if (j == tab.m_itabs)
+ CHK(pkdelete(par) == 0);
+ else {
+ const ITab& itab = *tab.m_itab[j];
+ CHK(hashindexdelete(par, itab) == 0);
+ }
}
} else {
// favor delete
if (sel < 1) {
CHK(pkinsert(par) == 0);
} else if (sel < 2) {
- CHK(pkupdate(par) == 0);
+ if (j == tab.m_itabs)
+ CHK(pkupdate(par) == 0);
+ else {
+ const ITab& itab = *tab.m_itab[j];
+ CHK(hashindexupdate(par, itab) == 0);
+ }
} else {
- CHK(pkdelete(par) == 0);
+ if (j == tab.m_itabs)
+ CHK(pkdelete(par) == 0);
+ else {
+ const ITab& itab = *tab.m_itab[j];
+ CHK(hashindexdelete(par, itab) == 0);
+ }
}
}
}
@@ -2846,6 +4336,7 @@ static int
pkupdatescanread(Par par)
{
par.m_dups = true;
+ par.m_deadlock = true;
unsigned sel = urandom(10);
if (sel < 5) {
CHK(pkupdate(par) == 0);
@@ -2854,6 +4345,10 @@ pkupdatescanread(Par par)
CHK(scanreadtable(par) == 0);
} else {
par.m_verify = false;
+ if (sel < 8) {
+ par.m_ordered = true;
+ par.m_descending = (sel < 7);
+ }
CHK(scanreadindex(par) == 0);
}
return 0;
@@ -2873,6 +4368,10 @@ mixedoperations(Par par)
} else if (sel < 6) {
CHK(scanupdatetable(par) == 0);
} else {
+ if (sel < 8) {
+ par.m_ordered = true;
+ par.m_descending = (sel < 7);
+ }
CHK(scanupdateindex(par) == 0);
}
return 0;
@@ -3134,6 +4633,24 @@ tbuild(Par par)
}
static int
+tindexscan(Par par)
+{
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, readverifyfull, MT);
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL4("subloop " << par.m_slno);
+ RUNSTEP(par, readverifyindex, MT);
+ }
+ return 0;
+}
+
+
+static int
tpkops(Par par)
{
RUNSTEP(par, droptable, ST);
@@ -3266,6 +4783,10 @@ ttimemaint(Par par)
static int
ttimescan(Par par)
{
+ if (par.tab().m_itab[0] == 0) {
+ LL1("ttimescan - no index 0, skipped");
+ return 0;
+ }
Tmr t1, t2;
RUNSTEP(par, droptable, ST);
RUNSTEP(par, createtable, ST);
@@ -3288,6 +4809,10 @@ ttimescan(Par par)
static int
ttimepkread(Par par)
{
+ if (par.tab().m_itab[0] == 0) {
+ LL1("ttimescan - no index 0, skipped");
+ return 0;
+ }
Tmr t1, t2;
RUNSTEP(par, droptable, ST);
RUNSTEP(par, createtable, ST);
@@ -3328,7 +4853,7 @@ struct TCase {
static const TCase
tcaselist[] = {
TCase("a", tbuild, "index build"),
- // "b" in 5.0
+ TCase("b", tindexscan, "index scans"),
TCase("c", tpkops, "pk operations"),
TCase("d", tpkopsread, "pk operations and scan reads"),
TCase("e", tmixedops, "pk operations and scan operations"),
@@ -3357,13 +4882,32 @@ printcases()
static void
printtables()
{
- ndbout << "tables and indexes (X1 is on table PK):" << endl;
+ Par par(g_opt);
+ makebuiltintables(par);
+ ndbout << "tables and indexes (x=ordered z=hash x0=on pk):" << endl;
for (unsigned j = 0; j < tabcount; j++) {
- const Tab& tab = tablist[j];
- ndbout << " " << tab.m_name;
+ if (tablist[j] == 0)
+ continue;
+ const Tab& tab = *tablist[j];
+ const char* tname = tab.m_name;
+ ndbout << " " << tname;
for (unsigned i = 0; i < tab.m_itabs; i++) {
- const ITab& itab = tab.m_itab[i];
- ndbout << " " << itab.m_name;
+ if (tab.m_itab[i] == 0)
+ continue;
+ const ITab& itab = *tab.m_itab[i];
+ const char* iname = itab.m_name;
+ if (strncmp(tname, iname, strlen(tname)) == 0)
+ iname += strlen(tname);
+ ndbout << " " << iname;
+ ndbout << "(";
+ for (unsigned k = 0; k < itab.m_icols; k++) {
+ if (k != 0)
+ ndbout << ",";
+ const ICol& icol = *itab.m_icol[k];
+ const Col& col = icol.m_col;
+ ndbout << col.m_name;
+ }
+ ndbout << ")";
}
ndbout << endl;
}
@@ -3373,15 +4917,29 @@ static int
runtest(Par par)
{
LL1("start");
- if (par.m_seed != 0)
+ if (par.m_seed == -1) {
+ // good enough for daily run
+ unsigned short seed = (getpid() ^ time(0));
+ LL1("random seed: " << seed);
+ srandom((unsigned)seed);
+ } else if (par.m_seed != 0) {
+ LL1("random seed: " << par.m_seed);
srandom(par.m_seed);
+ } else {
+ LL1("random seed: loop number");
+ }
+ // cs
assert(par.m_csname != 0);
- CHARSET_INFO* cs;
- CHK((cs = get_charset_by_name(par.m_csname, MYF(0))) != 0 || (cs = get_charset_by_csname(par.m_csname, MY_CS_PRIMARY, MYF(0))) != 0);
- par.m_cs = cs;
+ if (strcmp(par.m_csname, "random") != 0) {
+ CHARSET_INFO* cs;
+ CHK((cs = get_charset_by_name(par.m_csname, MYF(0))) != 0 || (cs = get_charset_by_csname(par.m_csname, MY_CS_PRIMARY, MYF(0))) != 0);
+ par.m_cs = cs;
+ }
+ // con
Con con;
CHK(con.connect() == 0);
par.m_con = &con;
+ // threads
g_thrlist = new Thr* [par.m_threads];
unsigned n;
for (n = 0; n < par.m_threads; n++) {
@@ -3400,16 +4958,18 @@ runtest(Par par)
const TCase& tcase = tcaselist[i];
if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0)
continue;
+ makebuiltintables(par);
LL1("case " << tcase.m_name << " - " << tcase.m_desc);
for (unsigned j = 0; j < tabcount; j++) {
- if (! usetable(j))
+ if (tablist[j] == 0)
continue;
- const Tab& tab = tablist[j];
+ const Tab& tab = *tablist[j];
par.m_tab = &tab;
- delete par.m_set;
par.m_set = new Set(tab, par.m_totrows);
LL1("table " << tab.m_name);
CHK(tcase.m_func(par) == 0);
+ delete par.m_set;
+ par.m_set = 0;
}
}
}
@@ -3433,7 +4993,7 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
{
ndb_init();
if (ndbout_mutex == NULL)
- ndbout_mutex= NdbMutex_Create();
+ ndbout_mutex = NdbMutex_Create();
while (++argv, --argc > 0) {
const char* arg = argv[0];
if (*arg != '-') {
@@ -3461,6 +5021,10 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
continue;
}
}
+ if (strcmp(arg, "-collsp") == 0) {
+ g_opt.m_collsp = true;
+ continue;
+ }
if (strcmp(arg, "-core") == 0) {
g_opt.m_core = true;
continue;
@@ -3539,12 +5103,6 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
continue;
}
}
- if (strcmp(arg, "-scanbat") == 0) {
- if (++argv, --argc > 0) {
- g_opt.m_scanbat = atoi(argv[0]);
- continue;
- }
- }
if (strcmp(arg, "-scanpar") == 0) {
if (++argv, --argc > 0) {
g_opt.m_scanpar = atoi(argv[0]);
@@ -3572,7 +5130,8 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
if (strcmp(arg, "-threads") == 0) {
if (++argv, --argc > 0) {
g_opt.m_threads = atoi(argv[0]);
- continue;
+ if (1 <= g_opt.m_threads)
+ continue;
}
}
if (strcmp(arg, "-v") == 0) {
@@ -3589,7 +5148,7 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
printhelp();
goto wrongargs;
}
- ndbout << "testOIBasic: unknown option " << arg;
+ ndbout << "testOIBasic: bad or unknown option " << arg;
goto usage;
}
{
@@ -3600,7 +5159,6 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
delete g_ncc;
g_ncc = 0;
}
- // always exit with NDBT code
ok:
return NDBT_ProgramExit(NDBT_OK);
failed:
diff --git a/ndb/test/ndbapi/testPartitioning.cpp b/ndb/test/ndbapi/testPartitioning.cpp
new file mode 100644
index 00000000000..9d67c27354b
--- /dev/null
+++ b/ndb/test/ndbapi/testPartitioning.cpp
@@ -0,0 +1,430 @@
+/* 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>
+
+#define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
+
+static Uint32 max_dks = 0;
+
+static
+int
+run_drop_table(NDBT_Context* ctx, NDBT_Step* step)
+{
+ NdbDictionary::Dictionary* dict = GETNDB(step)->getDictionary();
+ dict->dropTable(ctx->getTab()->getName());
+ return 0;
+}
+
+static
+int
+add_distribution_key(Ndb*, NdbDictionary::Table& tab, int when)
+{
+ switch(when){
+ case 0: // Before
+ break;
+ case 1: // After
+ return 0;
+ default:
+ return 0;
+ }
+
+ int keys = tab.getNoOfPrimaryKeys();
+ int dks = (2 * keys + 2) / 3; dks = (dks > max_dks ? max_dks : dks);
+ int cnt = 0;
+
+ for(unsigned i = 0; i<tab.getNoOfColumns(); i++)
+ if(tab.getColumn(i)->getPrimaryKey() &&
+ tab.getColumn(i)->getCharset() != 0)
+ keys--;
+
+ Uint32 max = NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY - tab.getNoOfPrimaryKeys();
+
+ if(max_dks < max)
+ max = max_dks;
+
+ if(keys <= 1 && max > 0)
+ {
+ dks = 1 + (rand() % max);
+ ndbout_c("%s pks: %d dks: %d", tab.getName(), keys, dks);
+ while(dks--)
+ {
+ NdbDictionary::Column col;
+ BaseString name;
+ name.assfmt("PK_DK_%d", dks);
+ col.setName(name.c_str());
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setLength(1);
+ col.setNullable(false);
+ col.setPrimaryKey(true);
+ col.setDistributionKey(true);
+ tab.addColumn(col);
+ }
+ }
+ else
+ {
+ for(unsigned i = 0; i<tab.getNoOfColumns(); i++)
+ {
+ NdbDictionary::Column* col = tab.getColumn(i);
+ if(col->getPrimaryKey() && col->getCharset() == 0)
+ {
+ if(dks >= keys || (rand() % 100) > 50)
+ {
+ col->setDistributionKey(true);
+ dks--;
+ }
+ keys--;
+ }
+ }
+ }
+ ndbout << (NDBT_Table&)tab << endl;
+
+ return 0;
+}
+
+static int
+run_create_table(NDBT_Context* ctx, NDBT_Step* step)
+{
+ max_dks = ctx->getProperty("distributionkey", (unsigned)0);
+
+ if(NDBT_Tables::createTable(GETNDB(step),
+ ctx->getTab()->getName(),
+ false, false,
+ max_dks?add_distribution_key:0) == NDBT_OK)
+ {
+ return NDBT_OK;
+ }
+
+ if(GETNDB(step)->getDictionary()->getNdbError().code == 745)
+ return NDBT_OK;
+
+ return NDBT_FAILED;
+}
+
+static int
+run_create_pk_index(NDBT_Context* ctx, NDBT_Step* step){
+ bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0);
+
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table *pTab =
+ pNdb->getDictionary()->getTable(ctx->getTab()->getName());
+
+ if(!pTab)
+ return NDBT_OK;
+
+ bool logged = ctx->getProperty("LoggedIndexes", orderedIndex ? 0 : 1);
+
+ BaseString name;
+ name.assfmt("IND_%s_PK_%c", pTab->getName(), orderedIndex ? 'O' : 'U');
+
+ // Create index
+ if (orderedIndex)
+ ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "ordered index "
+ << name.c_str() << " (";
+ else
+ ndbout << "Creating " << ((logged)?"logged ": "temporary ") << "unique index "
+ << name.c_str() << " (";
+
+ NdbDictionary::Index pIdx(name.c_str());
+ pIdx.setTable(pTab->getName());
+ if (orderedIndex)
+ pIdx.setType(NdbDictionary::Index::OrderedIndex);
+ else
+ pIdx.setType(NdbDictionary::Index::UniqueHashIndex);
+ for (int c = 0; c< pTab->getNoOfColumns(); c++){
+ const NdbDictionary::Column * col = pTab->getColumn(c);
+ if(col->getPrimaryKey()){
+ pIdx.addIndexColumn(col->getName());
+ ndbout << col->getName() <<" ";
+ }
+ }
+
+ pIdx.setStoredIndex(logged);
+ ndbout << ") ";
+ if (pNdb->getDictionary()->createIndex(pIdx) != 0){
+ ndbout << "FAILED!" << endl;
+ const NdbError err = pNdb->getDictionary()->getNdbError();
+ ERR(err);
+ return NDBT_FAILED;
+ }
+
+ ndbout << "OK!" << endl;
+ return NDBT_OK;
+}
+
+static int run_create_pk_index_drop(NDBT_Context* ctx, NDBT_Step* step){
+ bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0);
+
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table *pTab =
+ pNdb->getDictionary()->getTable(ctx->getTab()->getName());
+
+ if(!pTab)
+ return NDBT_OK;
+
+ BaseString name;
+ name.assfmt("IND_%s_PK_%c", pTab->getName(), orderedIndex ? 'O' : 'U');
+
+ ndbout << "Dropping index " << name.c_str() << " ";
+ if (pNdb->getDictionary()->dropIndex(name.c_str(), pTab->getName()) != 0){
+ ndbout << "FAILED!" << endl;
+ ERR(pNdb->getDictionary()->getNdbError());
+ return NDBT_FAILED;
+ } else {
+ ndbout << "OK!" << endl;
+ }
+
+ return NDBT_OK;
+}
+
+static int
+run_tests(Ndb* p_ndb, HugoTransactions& hugoTrans, int records)
+{
+ if (hugoTrans.loadTable(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.pkReadRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.pkUpdateRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.pkDelRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if (hugoTrans.loadTable(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.scanUpdateRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ Uint32 abort = 23;
+ for(Uint32 j = 0; j<5; j++){
+ Uint32 parallelism = (j == 1 ? 1 : j * 3);
+ ndbout_c("parallelism: %d", parallelism);
+ if (hugoTrans.scanReadRecords(p_ndb, records, abort, parallelism,
+ NdbOperation::LM_Read) != 0)
+ {
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.scanReadRecords(p_ndb, records, abort, parallelism,
+ NdbOperation::LM_Exclusive) != 0)
+ {
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.scanReadRecords(p_ndb, records, abort, parallelism,
+ NdbOperation::LM_CommittedRead) != 0)
+ {
+ return NDBT_FAILED;
+ }
+ }
+
+ if(hugoTrans.clearTable(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ return 0;
+}
+
+static int
+run_pk_dk(NDBT_Context* ctx, NDBT_Step* step)
+{
+ Ndb* p_ndb = GETNDB(step);
+ int records = ctx->getNumRecords();
+ const NdbDictionary::Table *tab =
+ p_ndb->getDictionary()->getTable(ctx->getTab()->getName());
+
+ if(!tab)
+ return NDBT_OK;
+
+ HugoTransactions hugoTrans(*tab);
+
+ return run_tests(p_ndb, hugoTrans, records);
+}
+
+int
+run_index_dk(NDBT_Context* ctx, NDBT_Step* step)
+{
+ Ndb* p_ndb = GETNDB(step);
+ int records = ctx->getNumRecords();
+ const NdbDictionary::Table *pTab =
+ p_ndb->getDictionary()->getTable(ctx->getTab()->getName());
+
+ if(!pTab)
+ return NDBT_OK;
+
+ bool orderedIndex = ctx->getProperty("OrderedIndex", (unsigned)0);
+
+ BaseString name;
+ name.assfmt("IND_%s_PK_%c", pTab->getName(), orderedIndex ? 'O' : 'U');
+
+ const NdbDictionary::Index * idx =
+ p_ndb->getDictionary()->getIndex(name.c_str(), pTab->getName());
+
+ if(!idx)
+ {
+ ndbout << "Failed to retreive index: " << name.c_str() << endl;
+ return NDBT_FAILED;
+ }
+
+ HugoTransactions hugoTrans(*pTab, idx);
+
+ return run_tests(p_ndb, hugoTrans, records);
+}
+
+static int
+run_startHint(NDBT_Context* ctx, NDBT_Step* step)
+{
+ Ndb* p_ndb = GETNDB(step);
+ int records = ctx->getNumRecords();
+ const NdbDictionary::Table *tab =
+ p_ndb->getDictionary()->getTable(ctx->getTab()->getName());
+
+ if(!tab)
+ return NDBT_OK;
+
+ HugoTransactions hugoTrans(*tab);
+ if (hugoTrans.loadTable(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ NdbRestarter restarter;
+ if(restarter.insertErrorInAllNodes(8050) != 0)
+ return NDBT_FAILED;
+
+ HugoCalculator dummy(*tab);
+ int result = NDBT_OK;
+ for(int i = 0; i<records && result == NDBT_OK; i++)
+ {
+ char buffer[8000];
+ char* start= buffer + (rand() & 7);
+ char* pos= start;
+
+ for(int j = 0; j<tab->getNoOfColumns(); j++)
+ {
+ if(tab->getColumn(j)->getPartitionKey())
+ {
+ ndbout_c(tab->getColumn(j)->getName());
+ int sz = tab->getColumn(j)->getSizeInBytes();
+ int aligned_size = 4 * ((sz + 3) >> 2);
+ memset(pos, 0, aligned_size);
+ dummy.calcValue(i, j, 0, pos, sz);
+ pos += aligned_size;
+ }
+ }
+ // Now we have the pk
+ NdbTransaction* pTrans= p_ndb->startTransaction(tab, start,(pos - start));
+ HugoOperations ops(*tab);
+ ops.setTransaction(pTrans);
+ if(ops.pkReadRecord(p_ndb, i, 1) != NDBT_OK)
+ {
+ result = NDBT_FAILED;
+ break;
+ }
+
+ if(ops.execute_Commit(p_ndb) != 0)
+ {
+ result = NDBT_FAILED;
+ break;
+ }
+
+ ops.closeTransaction(p_ndb);
+ }
+ restarter.insertErrorInAllNodes(0);
+ return result;
+}
+
+
+NDBT_TESTSUITE(testPartitioning);
+TESTCASE("pk_dk",
+ "Primary key operations with distribution key")
+{
+ TC_PROPERTY("distributionkey", ~0);
+ INITIALIZER(run_drop_table);
+ INITIALIZER(run_create_table);
+ INITIALIZER(run_pk_dk);
+ INITIALIZER(run_drop_table);
+}
+TESTCASE("hash_index_dk",
+ "Unique index operatations with distribution key")
+{
+ TC_PROPERTY("distributionkey", ~0);
+ TC_PROPERTY("OrderedIndex", (unsigned)0);
+ INITIALIZER(run_drop_table);
+ INITIALIZER(run_create_table);
+ INITIALIZER(run_create_pk_index);
+ INITIALIZER(run_index_dk);
+ INITIALIZER(run_create_pk_index_drop);
+ INITIALIZER(run_drop_table);
+}
+TESTCASE("ordered_index_dk",
+ "Ordered index operatations with distribution key")
+{
+ TC_PROPERTY("distributionkey", (unsigned)1);
+ TC_PROPERTY("OrderedIndex", (unsigned)1);
+ INITIALIZER(run_drop_table);
+ INITIALIZER(run_create_table);
+ INITIALIZER(run_create_pk_index);
+ INITIALIZER(run_index_dk);
+ INITIALIZER(run_create_pk_index_drop);
+ INITIALIZER(run_drop_table);
+}
+TESTCASE("startTransactionHint",
+ "Test startTransactionHint wo/ distribution key")
+{
+ TC_PROPERTY("distributionkey", (unsigned)0);
+ INITIALIZER(run_drop_table);
+ INITIALIZER(run_create_table);
+ INITIALIZER(run_startHint);
+ INITIALIZER(run_drop_table);
+}
+TESTCASE("startTransactionHint_dk",
+ "Test startTransactionHint with distribution key")
+{
+ TC_PROPERTY("distributionkey", (unsigned)~0);
+ INITIALIZER(run_drop_table);
+ INITIALIZER(run_create_table);
+ INITIALIZER(run_startHint);
+ INITIALIZER(run_drop_table);
+}
+NDBT_TESTSUITE_END(testPartitioning);
+
+int main(int argc, const char** argv){
+ ndb_init();
+ testPartitioning.setCreateTable(false);
+ return testPartitioning.execute(argc, argv);
+}
+
+
+
diff --git a/ndb/test/ndbapi/testReadPerf.cpp b/ndb/test/ndbapi/testReadPerf.cpp
index 3adcb5a2d9b..ba5f3c4232d 100644
--- a/ndb/test/ndbapi/testReadPerf.cpp
+++ b/ndb/test/ndbapi/testReadPerf.cpp
@@ -119,7 +119,13 @@ main(int argc, const char** argv){
myRandom48Init(NdbTick_CurrentMillisecond());
memset(g_times, 0, sizeof(g_times));
- g_ndb = new Ndb("TEST_DB");
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1))
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ g_ndb = new Ndb(&con, "TEST_DB");
if(g_ndb->init() != 0){
g_err << "init() failed" << endl;
goto error;
@@ -266,7 +272,6 @@ run_read(){
NdbScanOperation * pSp;
NdbIndexOperation * pUp;
NdbIndexScanOperation * pIp;
- NdbResultSet * rs = (NdbResultSet*)~0;
Uint32 start_row = rand() % (rows - range);
Uint32 stop_row = start_row + range;
@@ -319,27 +324,27 @@ run_read(){
}
break;
case 4:
- pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
- rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
+ pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
+ pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
check = pIp->setBound(pk, NdbIndexScanOperation::BoundEQ, &start_row);
break;
case 5:
- pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
- rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
+ pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
+ pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
start_row = stop_row;
break;
case 6:
- pOp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
- rs = pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0, true);
+ pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
+ pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0, true);
check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
start_row = stop_row;
break;
case 7:
pOp = pSp = pTrans->getNdbScanOperation(g_table);
- rs = pSp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
+ pSp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
NdbScanFilter filter(pOp) ;
filter.begin(NdbScanFilter::AND);
filter.ge(pk, start_row);
@@ -355,7 +360,6 @@ run_read(){
ndbout << pTrans->getNdbError() << endl;
}
assert(check == 0);
- assert(rs);
for(int j = 0; j<g_tab->getNoOfColumns(); j++){
res = pOp->getValue(j);
@@ -368,7 +372,7 @@ run_read(){
}
assert(check == 0);
if(g_paramters[P_OPER].value >= 4){
- while((check = rs->nextResult(true)) == 0){
+ while((check = pSp->nextResult(true)) == 0){
cnt++;
}
@@ -377,13 +381,13 @@ run_read(){
return -1;
}
assert(check == 1);
- rs->close();
+ pSp->close();
}
}
assert(g_paramters[P_OPER].value < 4 || (cnt == range));
-
+
pTrans->close();
-
+
stop = NdbTick_CurrentMillisecond();
g_times[g_paramters[P_OPER].value] += (stop - start1);
return 0;
diff --git a/ndb/test/ndbapi/testSRBank.cpp b/ndb/test/ndbapi/testSRBank.cpp
index 5677f551da6..6d57724f4c6 100644
--- a/ndb/test/ndbapi/testSRBank.cpp
+++ b/ndb/test/ndbapi/testSRBank.cpp
@@ -23,7 +23,7 @@
#include "bank/Bank.hpp"
int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int overWriteExisting = true;
if (bank.createAndLoadBank(overWriteExisting, 10) != NDBT_OK)
return NDBT_FAILED;
@@ -43,7 +43,7 @@ int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
ctx->incProperty("ThreadCount");
while (!ctx->isTestStopped())
{
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
if(bank.performIncreaseTime(wait, yield) == NDBT_FAILED)
break;
@@ -63,7 +63,7 @@ int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
ctx->incProperty("ThreadCount");
while (!ctx->isTestStopped())
{
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
if(bank.performTransactions(0, 1) == NDBT_FAILED)
break;
@@ -83,7 +83,7 @@ int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
ctx->incProperty("ThreadCount");
while (ctx->isTestStopped() == false)
{
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
if (bank.performMakeGLs(yield) != NDBT_OK)
{
@@ -102,7 +102,7 @@ int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
}
int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
int wait = 2000; // Max ms between each sum of accounts
int yield = 1; // Loops before bank returns
int result = NDBT_OK;
@@ -160,7 +160,7 @@ int runSR(NDBT_Context* ctx, NDBT_Step* step)
{
int wait = 0;
int yield = 1;
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
if (bank.performSumAccounts(wait, yield) != 0)
{
ndbout << "bank.performSumAccounts FAILED" << endl;
@@ -183,7 +183,7 @@ int runSR(NDBT_Context* ctx, NDBT_Step* step)
}
int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
- Bank bank;
+ Bank bank(ctx->m_cluster_connection);
if (bank.dropBank() != NDBT_OK)
return NDBT_FAILED;
return NDBT_OK;
diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp
index f1018d29846..2802f1c950e 100644
--- a/ndb/test/ndbapi/testScan.cpp
+++ b/ndb/test/ndbapi/testScan.cpp
@@ -316,11 +316,16 @@ int runScanReadIndex(NDBT_Context* ctx, NDBT_Step* step){
while (pIdx && i<loops && !ctx->isTestStopped()) {
g_info << i << ": ";
bool sort = (rand() % 100) > 50 ? true : false;
+ bool desc = (rand() % 100) > 50 ? true : false;
+ desc = false; // random causes too many deadlocks
+ int scan_flags =
+ (NdbScanOperation::SF_OrderBy & -(int)sort) |
+ (NdbScanOperation::SF_Descending & -(int)desc);
NdbOperation::LockMode lm = (NdbOperation::LockMode)(rand() % 3);
if (hugoTrans.scanReadRecords(GETNDB(step), pIdx,
records, abort, parallelism,
lm,
- sort) != 0){
+ scan_flags) != 0){
return NDBT_FAILED;
}
i++;
@@ -333,6 +338,8 @@ int runScanReadCommitted(NDBT_Context* ctx, NDBT_Step* step){
int records = ctx->getNumRecords();
int parallelism = ctx->getProperty("Parallelism", 240);
int abort = ctx->getProperty("AbortProb", 5);
+ bool tupScan = ctx->getProperty("TupScan");
+ int scan_flags = (NdbScanOperation::SF_TupScan & -(int)tupScan);
int i = 0;
HugoTransactions hugoTrans(*ctx->getTab());
@@ -340,7 +347,8 @@ int runScanReadCommitted(NDBT_Context* ctx, NDBT_Step* step){
g_info << i << ": ";
if (hugoTrans.scanReadRecords(GETNDB(step), records,
abort, parallelism,
- NdbOperation::LM_CommittedRead) != 0){
+ NdbOperation::LM_CommittedRead,
+ scan_flags) != 0){
return NDBT_FAILED;
}
i++;
@@ -1013,8 +1021,7 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
- NdbResultSet* rs = pOp->readTuples();
- if( rs == 0 ) {
+ if( pOp->readTuples() ) {
ERR(pCon->getNdbError());
return NDBT_FAILED;
}
@@ -1042,7 +1049,7 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){
int res;
int row = 0;
- while(row < record && (res = rs->nextResult()) == 0) {
+ while(row < record && (res = pOp->nextResult()) == 0) {
if(calc.verifyRowValues(&tmpRow) != 0){
abort();
return NDBT_FAILED;
@@ -1055,14 +1062,14 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_FAILED;
}
g_info << " restarting" << endl;
- if((res = rs->restart()) != 0){
+ if((res = pOp->restart()) != 0){
ERR(pCon->getNdbError());
abort();
return NDBT_FAILED;
}
row = 0;
- while((res = rs->nextResult()) == 0) {
+ while((res = pOp->nextResult()) == 0) {
if(calc.verifyRowValues(&tmpRow) != 0){
abort();
return NDBT_FAILED;
@@ -1080,6 +1087,44 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){
}
+int
+runScanParallelism(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops() + 3;
+ int records = ctx->getNumRecords();
+ int abort = ctx->getProperty("AbortProb", 15);
+
+ Uint32 fib[] = { 1, 2 };
+ Uint32 parallelism = 0; // start with 0
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops && !ctx->isTestStopped()) {
+ g_info << i << ": ";
+
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism,
+ NdbOperation::LM_Read) != 0){
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism,
+ NdbOperation::LM_Exclusive) != 0){
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism,
+ NdbOperation::LM_CommittedRead) != 0){
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.scanUpdateRecords(GETNDB(step), records, abort, parallelism)
+ != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ parallelism = fib[0];
+ Uint32 next = fib[0] + fib[1];
+ fib[0] = fib[1];
+ fib[1] = next;
+ }
+ return NDBT_OK;
+}
+
NDBT_TESTSUITE(testScan);
TESTCASE("ScanRead",
"Verify scan requirement: It should be possible "\
@@ -1113,6 +1158,18 @@ TESTCASE("ScanReadCommitted240",
"downgraded to the maximum parallelism value for the current config)"){
INITIALIZER(runLoadTable);
TC_PROPERTY("Parallelism", 240);
+ TC_PROPERTY("TupScan", (Uint32)0);
+ STEP(runScanReadCommitted);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanTupReadCommitted240",
+ "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). "\
+ "Scans TUP pages directly without using ACC."){
+ INITIALIZER(runLoadTable);
+ TC_PROPERTY("Parallelism", 240);
+ TC_PROPERTY("TupScan", 1);
STEP(runScanReadCommitted);
FINALIZER(runClearTable);
}
@@ -1540,6 +1597,12 @@ TESTCASE("ScanRestart",
STEP(runScanRestart);
FINALIZER(runClearTable);
}
+TESTCASE("ScanParallelism",
+ "Test scan with different parallelism"){
+ INITIALIZER(runLoadTable);
+ STEP(runScanParallelism);
+ FINALIZER(runClearTable);
+}
NDBT_TESTSUITE_END(testScan);
int main(int argc, const char** argv){
diff --git a/ndb/test/ndbapi/testScanPerf.cpp b/ndb/test/ndbapi/testScanPerf.cpp
index 45f0468bc70..a730136c3af 100644
--- a/ndb/test/ndbapi/testScanPerf.cpp
+++ b/ndb/test/ndbapi/testScanPerf.cpp
@@ -38,10 +38,10 @@ struct Parameter {
#define P_ROWS 7
#define P_LOOPS 8
#define P_CREATE 9
-#define P_LOAD 10
#define P_RESET 11
+#define P_MULTI 12
-#define P_MAX 12
+#define P_MAX 13
static
Parameter
@@ -57,7 +57,8 @@ g_paramters[] = {
{ "iterations", 3, 1, ~0 },
{ "create_drop", 1, 0, 1 },
{ "data", 1, 0, 1 },
- { "q-reset bounds", 0, 1, 0 }
+ { "q-reset bounds", 0, 1, 0 },
+ { "multi read range", 1000, 1, ~0 }
};
static Ndb* g_ndb = 0;
@@ -67,10 +68,7 @@ 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){
@@ -101,7 +99,13 @@ main(int argc, const char** argv){
myRandom48Init(NdbTick_CurrentMillisecond());
- g_ndb = new Ndb("TEST_DB");
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1))
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ g_ndb = new Ndb(&con, "TEST_DB");
if(g_ndb->init() != 0){
g_err << "init() failed" << endl;
goto error;
@@ -117,14 +121,8 @@ main(int argc, const char** argv){
BaseString::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;
@@ -139,6 +137,7 @@ create_table(){
NdbDictionary::Dictionary* dict = g_ndb->getDictionary();
assert(dict);
if(g_paramters[P_CREATE].value){
+ g_ndb->getDictionary()->dropTable(g_tablename);
const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_tablename);
assert(pTab);
NdbDictionary::Table copy = * pTab;
@@ -167,46 +166,18 @@ create_table(){
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;
+ if(g_paramters[P_CREATE].value)
+ {
+ 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;
}
@@ -227,13 +198,12 @@ run_scan(){
Uint32 tot = g_paramters[P_ROWS].value;
- if(g_paramters[P_BOUND].value == 2 || g_paramters[P_FILT].value == 2)
+ if(g_paramters[P_BOUND].value >= 2 || g_paramters[P_FILT].value == 2)
iter *= g_paramters[P_ROWS].value;
NdbScanOperation * pOp = 0;
NdbIndexScanOperation * pIOp = 0;
NdbConnection * pTrans = 0;
- NdbResultSet * rs = 0;
int check = 0;
for(int i = 0; i<iter; i++){
@@ -246,7 +216,7 @@ run_scan(){
}
int par = g_paramters[P_PARRA].value;
- int bat = g_paramters[P_BATCH].value;
+ int bat = 0; // g_paramters[P_BATCH].value;
NdbScanOperation::LockMode lm;
switch(g_paramters[P_LOCK].value){
case 0:
@@ -265,13 +235,13 @@ run_scan(){
if(g_paramters[P_ACCESS].value == 0){
pOp = pTrans->getNdbScanOperation(g_tablename);
assert(pOp);
- rs = pOp->readTuples(lm, bat, par);
+ pOp->readTuples(lm, bat, par);
} else {
if(g_paramters[P_RESET].value == 0 || pIOp == 0)
{
pOp= pIOp= pTrans->getNdbIndexScanOperation(g_indexname, g_tablename);
bool ord = g_paramters[P_ACCESS].value == 2;
- rs = pIOp->readTuples(lm, bat, par, ord);
+ pIOp->readTuples(lm, bat, par, ord);
}
else
{
@@ -294,14 +264,26 @@ run_scan(){
#else
pIOp->setBound((Uint32)0, NdbIndexScanOperation::BoundEQ, &row);
#endif
+ if(g_paramters[P_RESET].value == 2)
+ goto execute;
+ break;
+ }
+ case 3: { // read multi
+ int multi = g_paramters[P_MULTI].value;
+ int tot = g_paramters[P_ROWS].value;
+ for(; multi > 0 && i < iter; --multi, i++)
+ {
+ int row = rand() % tot;
+ pIOp->setBound((Uint32)0, NdbIndexScanOperation::BoundEQ, &row);
+ pIOp->end_of_bound(i);
+ }
+ if(g_paramters[P_RESET].value == 2)
+ goto execute;
break;
}
}
- if(g_paramters[P_RESET].value == 2)
- goto execute;
}
assert(pOp);
- assert(rs);
switch(g_paramters[P_FILT].value){
case 0: // All
@@ -337,15 +319,18 @@ run_scan(){
for(int i = 0; i<g_table->getNoOfColumns(); i++){
pOp->getValue(i);
}
+
+ if(g_paramters[P_RESET].value == 1)
+ g_paramters[P_RESET].value = 2;
execute:
int rows = 0;
check = pTrans->execute(NoCommit);
assert(check == 0);
int fetch = g_paramters[P_FETCH].value;
- while((check = rs->nextResult(true)) == 0){
+ while((check = pOp->nextResult(true)) == 0){
do {
rows++;
- } while(!fetch && ((check = rs->nextResult(false)) == 0));
+ } while(!fetch && ((check = pOp->nextResult(false)) == 0));
if(check == -1){
err(pTrans->getNdbError());
return -1;
diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp
index 71c11b25859..b02751ec819 100644
--- a/ndb/test/ndbapi/testTimeout.cpp
+++ b/ndb/test/ndbapi/testTimeout.cpp
@@ -87,47 +87,6 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
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();
-
- int timeout = ctx->getProperty("TransactionInactiveTimeout",TIMEOUT);
-
- int minSleep = (int)(timeout * 1.5);
- int maxSleep = timeout * 2;
- ndbout << "TransactionInactiveTimeout="<< timeout
- << ", 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) == 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 runTimeoutTrans2(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
int loops = ctx->getNumLoops();
@@ -407,27 +366,6 @@ TESTCASE("DontTimeoutTransaction5",
FINALIZER(resetTransactionTimeout);
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);
- INITIALIZER(setTransactionTimeout);
- STEPS(runTimeoutTrans, 1);
- FINALIZER(resetTransactionTimeout);
- 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);
- INITIALIZER(setTransactionTimeout);
- STEPS(runTimeoutTrans, 5);
- FINALIZER(resetTransactionTimeout);
- FINALIZER(runClearTable);
-}
TESTCASE("TimeoutRandTransaction",
"Test that the transaction does timeout "\
"if we sleep during the transaction. Use a sleep "\
diff --git a/ndb/test/ndbapi/test_event.cpp b/ndb/test/ndbapi/test_event.cpp
index cb2793e42b9..2df50f21e43 100644
--- a/ndb/test/ndbapi/test_event.cpp
+++ b/ndb/test/ndbapi/test_event.cpp
@@ -14,11 +14,11 @@
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 "TestNdbEventOperation.hpp"
+#include <NDBT_Test.hpp>
+#include <NDBT_ReturnCodes.h>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <TestNdbEventOperation.hpp>
#define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
@@ -32,6 +32,69 @@ int runCreateEvent(NDBT_Context* ctx, NDBT_Step* step)
return NDBT_OK;
}
+int runCreateShadowTable(NDBT_Context* ctx, NDBT_Step* step)
+{
+ const NdbDictionary::Table *table= ctx->getTab();
+ char buf[1024];
+ sprintf(buf, "%s_SHADOW", table->getName());
+
+ GETNDB(step)->getDictionary()->dropTable(buf);
+ if (GETNDB(step)->getDictionary()->getTable(buf))
+ {
+ g_err << "unsucessful drop of " << buf << endl;
+ return NDBT_FAILED;
+ }
+
+ NdbDictionary::Table table_shadow(*table);
+ table_shadow.setName(buf);
+ GETNDB(step)->getDictionary()->createTable(table_shadow);
+ if (GETNDB(step)->getDictionary()->getTable(buf))
+ return NDBT_OK;
+
+ g_err << "unsucessful create of " << buf << endl;
+ return NDBT_FAILED;
+}
+
+int runCreateDropEventOperation(NDBT_Context* ctx, NDBT_Step* step)
+{
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ EventOperationStats stats;
+
+ Ndb *pNdb=GETNDB(step);
+ const NdbDictionary::Table& tab= *ctx->getTab();
+ NdbEventOperation *pOp;
+ char eventName[1024];
+ sprintf(eventName,"%s_EVENT",tab.getName());
+ int noEventColumnName = tab.getNoOfColumns();
+
+ for (int i= 0; i < loops; i++)
+ {
+#if 1
+ if (hugoTrans.eventOperation(GETNDB(step), (void*)&stats, 0) != 0){
+ return NDBT_FAILED;
+ }
+#else
+ g_info << "create EventOperation\n";
+ pOp = pNdb->createEventOperation(eventName, 100);
+ if ( pOp == NULL ) {
+ g_err << "Event operation creation failed\n";
+ return NDBT_FAILED;
+ }
+
+ g_info << "dropping event operation" << endl;
+ int res = pNdb->dropEventOperation(pOp);
+ if (res != 0) {
+ g_err << "operation execution failed\n";
+ return NDBT_FAILED;
+ }
+#endif
+ }
+
+ return NDBT_OK;
+}
+
int theThreadIdCounter = 0;
int runEventOperation(NDBT_Context* ctx, NDBT_Step* step)
@@ -43,7 +106,7 @@ int runEventOperation(NDBT_Context* ctx, NDBT_Step* step)
EventOperationStats stats;
- g_info << "***** Id " << tId << endl;
+ g_info << "***** start Id " << tId << endl;
// sleep(tId);
@@ -62,12 +125,13 @@ int runEventOperation(NDBT_Context* ctx, NDBT_Step* step)
ret = NDBT_FAILED;
if (ret == NDBT_FAILED) {
- ndbout << "n_inserts = " << stats.n_inserts << endl;
- ndbout << "n_deletes = " << stats.n_deletes << endl;
- ndbout << "n_updates = " << stats.n_updates << endl;
- ndbout << "n_consecutive = " << stats.n_consecutive << endl;
- ndbout << "n_duplicates = " << stats.n_duplicates << endl;
- ndbout << "n_inconsistent_gcis = " << stats.n_inconsistent_gcis << endl;
+ g_info << "***** end Id " << tId << endl;
+ ndbout_c("n_inserts = %d (%d)", stats.n_inserts, records);
+ ndbout_c("n_deletes = %d (%d)", stats.n_deletes, records);
+ ndbout_c("n_updates = %d (%d)", stats.n_updates, records);
+ ndbout_c("n_consecutive = %d (%d)", stats.n_consecutive, 3);
+ ndbout_c("n_duplicates = %d (%d)", stats.n_duplicates, 0);
+ ndbout_c("n_inconsistent_gcis = %d (%d)", stats.n_inconsistent_gcis, 0);
}
return ret;
@@ -94,6 +158,36 @@ int runEventLoad(NDBT_Context* ctx, NDBT_Step* step)
return NDBT_OK;
}
+int runEventMixedLoad(NDBT_Context* ctx, NDBT_Step* step)
+{
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ sleep(5);
+
+ if (hugoTrans.loadTable(GETNDB(step), 3*records, 1, true, 1) != 0){
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.pkDelRecords(GETNDB(step), 3*records, 1, true, 1) != 0){
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.loadTable(GETNDB(step), records, 1, true, 1) != 0){
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){
+ return NDBT_FAILED;
+ }
+ if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
int runDropEvent(NDBT_Context* ctx, NDBT_Step* step)
{
HugoTransactions hugoTrans(*ctx->getTab());
@@ -105,6 +199,246 @@ int runDropEvent(NDBT_Context* ctx, NDBT_Step* step)
return NDBT_OK;
}
+int runVerify(NDBT_Context* ctx, NDBT_Step* step)
+{
+ int records = ctx->getNumRecords();
+ const NdbDictionary::Table * table= ctx->getTab();
+ char buf[1024];
+
+ sprintf(buf, "%s_SHADOW", table->getName());
+
+ HugoTransactions hugoTrans(*table);
+ if (hugoTrans.compare(GETNDB(step), buf, 0))
+ {
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+int runEventApplier(NDBT_Context* ctx, NDBT_Step* step)
+{
+ DBUG_ENTER("runEventApplier");
+
+ int records = ctx->getNumRecords();
+ int loops = ctx->getNumLoops();
+ const NdbDictionary::Table * table= ctx->getTab();
+ char buf[1024];
+
+ sprintf(buf, "%s_SHADOW", table->getName());
+ const NdbDictionary::Table * table_shadow;
+ if ((table_shadow = GETNDB(step)->getDictionary()->getTable(buf)) == 0)
+ {
+ g_err << "Unable to get table " << buf << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+
+ sprintf(buf, "%s_EVENT", table->getName());
+ NdbEventOperation *pOp;
+ pOp = GETNDB(step)->createEventOperation(buf, 10*records);
+ if ( pOp == NULL ) {
+ g_err << "Event operation creation failed on %s" << buf << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+
+ int i;
+ int n_columns= table->getNoOfColumns();
+ NdbRecAttr* recAttr[1024];
+ NdbRecAttr* recAttrPre[1024];
+ for (i = 0; i < n_columns; i++) {
+ recAttr[i] = pOp->getValue(table->getColumn(i)->getName());
+ recAttrPre[i] = pOp->getPreValue(table->getColumn(i)->getName());
+ }
+
+ if (pOp->execute()) { // This starts changes to "start flowing"
+ g_err << "execute operation execution failed: \n";
+ g_err << pOp->getNdbError().code << " "
+ << pOp->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+
+ int r= 0;
+ int res;
+ while (r < 10*records){
+ //printf("now waiting for event...\n");
+ res= GETNDB(step)->pollEvents(1000); // wait for event or 1000 ms
+ if (res <= 0)
+ {
+ ndbout_c("********************");
+ continue;
+ }
+
+ //printf("got data! %d\n", r);
+ int overrun= 0;
+ while (pOp->next(&overrun) > 0)
+ {
+ if (overrun)
+ {
+ g_err << "buffer overrun\n";
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ r++;
+
+ Uint32 gci= pOp->getGCI();
+
+ if (!pOp->isConsistent()) {
+ g_err << "A node failure has occured and events might be missing\n";
+ DBUG_RETURN(NDBT_FAILED);
+ }
+
+ int noRetries= 0;
+ do
+ {
+ NdbTransaction *trans= GETNDB(step)->startTransaction();
+ if (trans == 0)
+ {
+ g_err << "startTransaction failed "
+ << GETNDB(step)->getNdbError().code << " "
+ << GETNDB(step)->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+
+ NdbOperation *op= trans->getNdbOperation(table_shadow);
+ if (op == 0)
+ {
+ g_err << "getNdbOperation failed "
+ << trans->getNdbError().code << " "
+ << trans->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+
+ switch (pOp->getEventType()) {
+ case NdbDictionary::Event::TE_INSERT:
+ if (op->insertTuple())
+ {
+ g_err << "insertTuple "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ break;
+ case NdbDictionary::Event::TE_DELETE:
+ if (op->deleteTuple())
+ {
+ g_err << "deleteTuple "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ break;
+ case NdbDictionary::Event::TE_UPDATE:
+ if (op->updateTuple())
+ {
+ g_err << "updateTuple "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ break;
+ default:
+ abort();
+ }
+
+ for (i= 0; i < n_columns; i++)
+ {
+ if (recAttr[i]->isNULL())
+ {
+ if (table->getColumn(i)->getPrimaryKey())
+ {
+ g_err << "internal error: primary key isNull()="
+ << recAttr[i]->isNULL() << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ switch (pOp->getEventType()) {
+ case NdbDictionary::Event::TE_INSERT:
+ if (recAttr[i]->isNULL() < 0)
+ {
+ g_err << "internal error: missing value for insert\n";
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ break;
+ case NdbDictionary::Event::TE_DELETE:
+ break;
+ case NdbDictionary::Event::TE_UPDATE:
+ break;
+ default:
+ abort();
+ }
+ }
+ if (table->getColumn(i)->getPrimaryKey() &&
+ op->equal(i,recAttr[i]->aRef()))
+ {
+ g_err << "equal " << i << " "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ }
+
+ switch (pOp->getEventType()) {
+ case NdbDictionary::Event::TE_INSERT:
+ for (i= 0; i < n_columns; i++)
+ {
+ if (!table->getColumn(i)->getPrimaryKey() &&
+ op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef()))
+ {
+ g_err << "setValue(insert) " << i << " "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ }
+ break;
+ case NdbDictionary::Event::TE_DELETE:
+ break;
+ case NdbDictionary::Event::TE_UPDATE:
+ for (i= 0; i < n_columns; i++)
+ {
+ if (!table->getColumn(i)->getPrimaryKey() &&
+ recAttr[i]->isNULL() >= 0 &&
+ op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef()))
+ {
+ g_err << "setValue(update) " << i << " "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ }
+ break;
+ case NdbDictionary::Event::TE_ALL:
+ abort();
+ }
+ if (trans->execute(Commit) == 0)
+ {
+ trans->close();
+ // everything ok
+ break;
+ }
+ if (noRetries++ == 10 ||
+ trans->getNdbError().status != NdbError::TemporaryError)
+ {
+ g_err << "execute " << r << " failed "
+ << trans->getNdbError().code << " "
+ << trans->getNdbError().message << endl;
+ trans->close();
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ trans->close();
+ NdbSleep_MilliSleep(100); // sleep before retying
+ } while(1);
+ }
+ }
+
+ if (GETNDB(step)->dropEventOperation(pOp)) {
+ g_err << "dropEventOperation execution failed "
+ << GETNDB(step)->getNdbError().code << " "
+ << GETNDB(step)->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+
+ DBUG_RETURN(NDBT_OK);
+}
+
// INITIALIZER(runInsert);
// STEP(runPkRead);
// VERIFIER(runVerifyInsert);
@@ -116,25 +450,37 @@ TESTCASE("BasicEventOperation",
"NOTE! No errors are allowed!" ){
INITIALIZER(runCreateEvent);
STEP(runEventOperation);
- STEP(runEventOperation);
- STEP(runEventOperation);
- STEP(runEventOperation);
STEP(runEventLoad);
FINALIZER(runDropEvent);
}
-NDBT_TESTSUITE_END(test_event);
-
-#if 0
-NDBT_TESTSUITE(test_event);
+TESTCASE("CreateDropEventOperation",
+ "Verify that we can Create and Drop many times"
+ "NOTE! No errors are allowed!" ){
+ INITIALIZER(runCreateEvent);
+ STEP(runCreateDropEventOperation);
+ FINALIZER(runDropEvent);
+}
TESTCASE("ParallellEventOperation",
- "Verify that we can listen to Events in Parallell"
+ "Verify that we can listen to Events in parallell"
"NOTE! No errors are allowed!" ){
- INITIALIZER(runCreateAllEvent);
+ INITIALIZER(runCreateEvent);
+ STEP(runEventOperation);
STEP(runEventOperation);
+ STEP(runEventLoad);
+ FINALIZER(runDropEvent);
+}
+TESTCASE("EventOperationApplier",
+ "Verify that if we apply the data we get from event "
+ "operation is the same as the original table"
+ "NOTE! No errors are allowed!" ){
+ INITIALIZER(runCreateEvent);
+ INITIALIZER(runCreateShadowTable);
+ STEP(runEventApplier);
+ STEP(runEventMixedLoad);
FINALIZER(runDropEvent);
+ FINALIZER(runVerify);
}
NDBT_TESTSUITE_END(test_event);
-#endif
int main(int argc, const char** argv){
ndb_init();
diff --git a/ndb/test/ndbapi/test_event_multi_table.cpp b/ndb/test/ndbapi/test_event_multi_table.cpp
new file mode 100644
index 00000000000..f16504029fa
--- /dev/null
+++ b/ndb/test/ndbapi/test_event_multi_table.cpp
@@ -0,0 +1,487 @@
+/* Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+#include <ndb_opts.h>
+#include <NDBT_Test.hpp>
+#include <NDBT_ReturnCodes.h>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <TestNdbEventOperation.hpp>
+
+static void usage()
+{
+ ndb_std_print_version();
+}
+
+static int start_transaction(Ndb *ndb, Vector<HugoOperations*> &ops)
+{
+ if (ops[0]->startTransaction(ndb) != NDBT_OK)
+ return -1;
+ NdbTransaction * t= ops[0]->getTransaction();
+ for (int i= ops.size()-1; i > 0; i--)
+ {
+ ops[i]->setTransaction(t);
+ }
+ return 0;
+}
+
+static int close_transaction(Ndb *ndb, Vector<HugoOperations*> &ops)
+{
+ if (ops[0]->closeTransaction(ndb) != NDBT_OK)
+ return -1;
+ for (int i= ops.size()-1; i > 0; i--)
+ {
+ ops[i]->setTransaction(NULL);
+ }
+ return 0;
+}
+
+static int execute_commit(Ndb *ndb, Vector<HugoOperations*> &ops)
+{
+ if (ops[0]->execute_Commit(ndb) != NDBT_OK)
+ return -1;
+ return 0;
+}
+
+static int copy_events(Ndb *ndb,
+ Vector<NdbEventOperation *> &ops,
+ Vector<const NdbDictionary::Table *> &tabs,
+ Vector<Vector<NdbRecAttr *> > &values)
+{
+ DBUG_ENTER("copy_events");
+ int r= 0;
+ while (1)
+ {
+ int res= ndb->pollEvents(1000); // wait for event or 1000 ms
+ DBUG_PRINT("info", ("pollEvents res=%d", r));
+ if (res <= 0)
+ {
+ break;
+ }
+ for (unsigned i_ops= 0; i_ops < ops.size(); i_ops++)
+ {
+ NdbEventOperation *pOp= ops[i_ops];
+ const NdbDictionary::Table *table= tabs[i_ops];
+ Vector<NdbRecAttr *> &recAttr= values[i_ops];
+
+ int overrun= 0;
+ unsigned i;
+ unsigned n_columns= table->getNoOfColumns();
+ while (pOp->next(&overrun) > 0)
+ {
+ if (overrun)
+ {
+ g_err << "buffer overrun\n";
+ DBUG_RETURN(-1);
+ }
+ r++;
+
+ Uint32 gci= pOp->getGCI();
+
+ if (!pOp->isConsistent()) {
+ g_err << "A node failure has occured and events might be missing\n";
+ DBUG_RETURN(-1);
+ }
+
+ int noRetries= 0;
+ do
+ {
+ NdbTransaction *trans= ndb->startTransaction();
+ if (trans == 0)
+ {
+ g_err << "startTransaction failed "
+ << ndb->getNdbError().code << " "
+ << ndb->getNdbError().message << endl;
+ DBUG_RETURN(-1);
+ }
+
+ NdbOperation *op= trans->getNdbOperation(table);
+ if (op == 0)
+ {
+ g_err << "getNdbOperation failed "
+ << trans->getNdbError().code << " "
+ << trans->getNdbError().message << endl;
+ DBUG_RETURN(-1);
+ }
+
+ switch (pOp->getEventType()) {
+ case NdbDictionary::Event::TE_INSERT:
+ if (op->insertTuple())
+ {
+ g_err << "insertTuple "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(-1);
+ }
+ break;
+ case NdbDictionary::Event::TE_DELETE:
+ if (op->deleteTuple())
+ {
+ g_err << "deleteTuple "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(-1);
+ }
+ break;
+ case NdbDictionary::Event::TE_UPDATE:
+ if (op->updateTuple())
+ {
+ g_err << "updateTuple "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(-1);
+ }
+ break;
+ default:
+ abort();
+ }
+
+ for (i= 0; i < n_columns; i++)
+ {
+ if (recAttr[i]->isNULL())
+ {
+ if (table->getColumn(i)->getPrimaryKey())
+ {
+ g_err << "internal error: primary key isNull()="
+ << recAttr[i]->isNULL() << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ switch (pOp->getEventType()) {
+ case NdbDictionary::Event::TE_INSERT:
+ if (recAttr[i]->isNULL() < 0)
+ {
+ g_err << "internal error: missing value for insert\n";
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ break;
+ case NdbDictionary::Event::TE_DELETE:
+ break;
+ case NdbDictionary::Event::TE_UPDATE:
+ break;
+ default:
+ abort();
+ }
+ }
+ if (table->getColumn(i)->getPrimaryKey() &&
+ op->equal(i,recAttr[i]->aRef()))
+ {
+ g_err << "equal " << i << " "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ }
+
+ switch (pOp->getEventType()) {
+ case NdbDictionary::Event::TE_INSERT:
+ for (i= 0; i < n_columns; i++)
+ {
+ if (!table->getColumn(i)->getPrimaryKey() &&
+ op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef()))
+ {
+ g_err << "setValue(insert) " << i << " "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(-1);
+ }
+ }
+ break;
+ case NdbDictionary::Event::TE_DELETE:
+ break;
+ case NdbDictionary::Event::TE_UPDATE:
+ for (i= 0; i < n_columns; i++)
+ {
+ if (!table->getColumn(i)->getPrimaryKey() &&
+ recAttr[i]->isNULL() >= 0 &&
+ op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef()))
+ {
+ g_err << "setValue(update) " << i << " "
+ << op->getNdbError().code << " "
+ << op->getNdbError().message << endl;
+ DBUG_RETURN(NDBT_FAILED);
+ }
+ }
+ break;
+ case NdbDictionary::Event::TE_ALL:
+ abort();
+ }
+ if (trans->execute(Commit) == 0)
+ {
+ trans->close();
+ // everything ok
+ break;
+ }
+ if (noRetries++ == 10 ||
+ trans->getNdbError().status != NdbError::TemporaryError)
+ {
+ g_err << "execute " << r << " failed "
+ << trans->getNdbError().code << " "
+ << trans->getNdbError().message << endl;
+ trans->close();
+ DBUG_RETURN(-1);
+ }
+ trans->close();
+ NdbSleep_MilliSleep(100); // sleep before retying
+ } while(1);
+ }
+ }
+ }
+ DBUG_RETURN(r);
+}
+
+static int verify_copy(Ndb *ndb,
+ Vector<const NdbDictionary::Table *> &tabs1,
+ Vector<const NdbDictionary::Table *> &tabs2)
+{
+ for (unsigned i= 0; i < tabs1.size(); i++)
+ if (tabs1[i])
+ {
+ HugoTransactions hugoTrans(*tabs1[i]);
+ if (hugoTrans.compare(ndb, tabs2[i]->getName(), 0))
+ return -1;
+ }
+ return 0;
+}
+
+NDB_STD_OPTS_VARS;
+
+static const char* _dbname = "TEST_DB";
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS(""),
+ { "database", 'd', "Name of database table is in",
+ (gptr*) &_dbname, (gptr*) &_dbname, 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}
+};
+
+int
+main(int argc, char** argv)
+{
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+
+ int ho_error;
+#ifndef DBUG_OFF
+ opt_debug= "d:t:F:L";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+
+ DBUG_ENTER("main");
+ Ndb_cluster_connection con(opt_connect_str);
+ if(con.connect(12, 5, 1))
+ {
+ DBUG_RETURN(NDBT_ProgramExit(NDBT_FAILED));
+ }
+
+
+ Ndb ndb(&con,_dbname);
+ ndb.init();
+ while (ndb.waitUntilReady() != 0);
+
+ NdbDictionary::Dictionary * dict = ndb.getDictionary();
+ int no_error= 1;
+ int i;
+
+ // create all tables
+ Vector<const NdbDictionary::Table*> pTabs;
+ for (i= 0; no_error && argc; argc--, i++)
+ {
+ dict->dropTable(argv[i]);
+ NDBT_Tables::createTable(&ndb, argv[i]);
+ const NdbDictionary::Table *pTab= dict->getTable(argv[i]);
+ if (pTab == 0)
+ {
+ ndbout << "Failed to create table" << endl;
+ ndbout << dict->getNdbError() << endl;
+ no_error= 0;
+ break;
+ }
+ pTabs.push_back(pTab);
+ }
+ pTabs.push_back(NULL);
+
+ // create an event for each table
+ for (i= 0; no_error && pTabs[i]; i++)
+ {
+ HugoTransactions ht(*pTabs[i]);
+ if (ht.createEvent(&ndb)){
+ no_error= 0;
+ break;
+ }
+ }
+
+ // create an event operation for each event
+ Vector<NdbEventOperation *> pOps;
+ for (i= 0; no_error && pTabs[i]; i++)
+ {
+ char buf[1024];
+ sprintf(buf, "%s_EVENT", pTabs[i]->getName());
+ NdbEventOperation *pOp= ndb.createEventOperation(buf, 1000);
+ if ( pOp == NULL )
+ {
+ no_error= 0;
+ break;
+ }
+ pOps.push_back(pOp);
+ }
+
+ // get storage for each event operation
+ Vector<Vector<NdbRecAttr*> > values;
+ Vector<Vector<NdbRecAttr*> > pre_values;
+ for (i= 0; no_error && pTabs[i]; i++)
+ {
+ int n_columns= pTabs[i]->getNoOfColumns();
+ Vector<NdbRecAttr*> tmp_a;
+ Vector<NdbRecAttr*> tmp_b;
+ for (int j = 0; j < n_columns; j++) {
+ tmp_a.push_back(pOps[i]->getValue(pTabs[i]->getColumn(j)->getName()));
+ tmp_b.push_back(pOps[i]->getPreValue(pTabs[i]->getColumn(j)->getName()));
+ }
+ values.push_back(tmp_a);
+ pre_values.push_back(tmp_b);
+ }
+
+ // start receiving events
+ for (i= 0; no_error && pTabs[i]; i++)
+ {
+ if ( pOps[i]->execute() )
+ {
+ no_error= 0;
+ break;
+ }
+ }
+
+ // create a "shadow" table for each table
+ Vector<const NdbDictionary::Table*> pShadowTabs;
+ for (i= 0; no_error && pTabs[i]; i++)
+ {
+ char buf[1024];
+ sprintf(buf, "%s_SHADOW", pTabs[i]->getName());
+
+ dict->dropTable(buf);
+ if (dict->getTable(buf))
+ {
+ no_error= 0;
+ break;
+ }
+
+ NdbDictionary::Table table_shadow(*pTabs[i]);
+ table_shadow.setName(buf);
+ dict->createTable(table_shadow);
+ pShadowTabs.push_back(dict->getTable(buf));
+ if (!pShadowTabs[i])
+ {
+ no_error= 0;
+ break;
+ }
+ }
+
+ // create a hugo operation per table
+ Vector<HugoOperations *> hugo_ops;
+ for (i= 0; no_error && pTabs[i]; i++)
+ {
+ hugo_ops.push_back(new HugoOperations(*pTabs[i]));
+ }
+
+ sleep(5);
+
+ // insert 3 records per table
+ do {
+ if (start_transaction(&ndb, hugo_ops))
+ {
+ no_error= 0;
+ break;
+ }
+ for (i= 0; no_error && pTabs[i]; i++)
+ {
+ hugo_ops[i]->pkInsertRecord(&ndb, 0, 3);
+ }
+ if (execute_commit(&ndb, hugo_ops))
+ {
+ no_error= 0;
+ break;
+ }
+ if(close_transaction(&ndb, hugo_ops))
+ {
+ no_error= 0;
+ break;
+ }
+ } while(0);
+
+ // copy events and verify
+ do {
+ if (copy_events(&ndb, pOps, pShadowTabs, values) < 0)
+ {
+ no_error= 0;
+ break;
+ }
+ if (verify_copy(&ndb, pTabs, pShadowTabs))
+ {
+ no_error= 0;
+ break;
+ }
+ } while (0);
+
+ // update 2 records in first table
+ do {
+ if (start_transaction(&ndb, hugo_ops))
+ {
+ no_error= 0;
+ break;
+ }
+
+ hugo_ops[0]->pkUpdateRecord(&ndb, 2);
+
+ if (execute_commit(&ndb, hugo_ops))
+ {
+ no_error= 0;
+ break;
+ }
+ if(close_transaction(&ndb, hugo_ops))
+ {
+ no_error= 0;
+ break;
+ }
+ } while(0);
+
+ // copy events and verify
+ do {
+ if (copy_events(&ndb, pOps, pShadowTabs, values) < 0)
+ {
+ no_error= 0;
+ break;
+ }
+ if (verify_copy(&ndb, pTabs, pShadowTabs))
+ {
+ no_error= 0;
+ break;
+ }
+ } while (0);
+
+ if (no_error)
+ DBUG_RETURN(NDBT_ProgramExit(NDBT_OK));
+ DBUG_RETURN(NDBT_ProgramExit(NDBT_FAILED));
+}
+
+template class Vector<HugoOperations *>;
+template class Vector<NdbEventOperation *>;
+template class Vector<NdbRecAttr*>;
+template class Vector<Vector<NdbRecAttr*> >;
diff --git a/ndb/test/run-test/16node-tests.txt b/ndb/test/run-test/16node-tests.txt
new file mode 100644
index 00000000000..11ade56c28c
--- /dev/null
+++ b/ndb/test/run-test/16node-tests.txt
@@ -0,0 +1,733 @@
+# 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 T13
+
+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
+
+max-time: 500
+cmd: testTimeout
+args: 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: 500
+cmd: testScan
+args: -n ScanRead488O -l 10 T6
+
+max-time: 1000
+cmd: testScan
+args: -n ScanRead488_Mixed -l 10 T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanRead488Timeout -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: 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
+
+max-time: 500
+cmd: testScan
+args: -n InsertDelete T1 T6
+
+max-time: 500
+cmd: testScan
+args: -n CheckAfterTerror T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanReadWhileNodeIsDown T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanRestart T1
+
+max-time: 500
+cmd: testScan
+args: -n ScanParallelism
+
+#
+# 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 FragmentTypeAllSmall 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: 150000
+cmd: testOperations
+args:
+
+max-time: 15000
+cmd: testTransactions
+args:
+
+max-time: 1500
+cmd: testRestartGci
+args: T6
+
+max-time: 600
+cmd: testBlobs
+args:
+
+max-time: 5000
+cmd: testOIBasic
+args:
+
+max-time: 2500
+cmd: testBitfield
+args:
+
+max-time: 2500
+cmd: testPartitioning
+args:
+
+max-time: 25000
+cmd: atrt-mysql-test-run
+args: --force
+
+#
+# INDEX
+#
+max-time: 1500
+cmd: testIndex
+args: -n CreateAll T1 T6 T13
+
+#-m 7200 1: testIndex -n InsertDeleteGentle T7
+max-time: 3600
+cmd: testIndex
+args: -n InsertDelete T1 T10
+
+#-m 3600 1: testIndex -n CreateLoadDropGentle T7
+max-time: 3600
+cmd: testIndex
+args: -n CreateLoadDrop T1 T10
+
+#
+# BACKUP
+#
+max-time: 600
+cmd: atrt-testBackup
+args: -n BackupOne T1 T6 T3 I3
+
+#
+#
+# SYSTEM RESTARTS
+#
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR3 T6
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR4 T6
+
+#
+# NODE RESTARTS
+#
+max-time: 2500
+cmd: testNodeRestart
+args: -n NoLoad T6
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n MixedPkRead T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -l 1 -n MixedPkReadPkUpdate
+
+max-time: 2500
+cmd: testNodeRestart
+args: -l 1 -n MixedReadUpdateScan
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n CommittedRead T1
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n FullDb T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartRandomNode T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartRandomNodeError T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartRandomNodeInitial T6 T13
+
+max-time: 3600
+cmd: testNodeRestart
+args: -l 1 -n RestartNFDuringNR T6 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartMasterNodeError T6 T8 T13
+
+max-time: 3600
+cmd: testNodeRestart
+args: -n RestartNodeDuringLCP T6
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n TwoNodeFailure T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n TwoMasterNodeFailure T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n FiftyPercentFail T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartAllNodes T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartAllNodesAbort T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n RestartAllNodesError9999 T6 T8 T13
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n FiftyPercentStopAndWait T6 T8 T13
+
+#max-time: 500
+#cmd: testNodeRestart
+#args: -n StopOnError T1
+#
+#
+max-time: 2500
+cmd: testIndex
+args: -n NFNR1 T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR2 T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR3 T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n BuildDuring T6
+
+max-time: 2500
+cmd: testIndex
+args: -l 2 -n SR1 T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR1_O T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR2_O T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n NFNR3_O T6 T13
+
+max-time: 2500
+cmd: testIndex
+args: -n BuildDuring_O T6
+
+max-time: 2500
+cmd: testIndex
+args: -l 2 -n SR1_O T6 T13
+
+max-time: 500
+cmd: testIndex
+args: -n MixedTransaction T1
+
+max-time: 2500
+cmd: testDict
+args: -n NF1 T1 T6 T13
+
+#
+max-time: 1500
+cmd: testSystemRestart
+args: -l 1 -n SR6 T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -l 1 -n SR7 T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -l 1 -n SR8 T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -l 1 -n SR9 T1
+
+#
+max-time: 2500
+cmd: test_event
+args: -n BasicEventOperation T1 T6
+
+#
+#
+# SYSTEM RESTARTS
+#
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR1 T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR1 T6
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR1 T7
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR1 T8
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR2 T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR2 T6
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR2 T7
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_UNDO T1
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_UNDO T6
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_UNDO T7
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR_UNDO T8
+
+# OLD FLEX
+max-time: 500
+cmd: flexBench
+args: -c 25 -t 10
+
+max-time: 500
+cmd: flexHammer
+args: -r 5 -t 32
+
diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am
index cf08542ae97..60d64a7697f 100644
--- a/ndb/test/run-test/Makefile.am
+++ b/ndb/test/run-test/Makefile.am
@@ -6,7 +6,7 @@ include $(top_srcdir)/ndb/config/type_util.mk.am
include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am
test_PROGRAMS = atrt
-test_DATA=daily-basic-tests.txt daily-devel-tests.txt \
+test_DATA=daily-basic-tests.txt daily-devel-tests.txt 16node-tests.txt \
conf-daily-basic-ndbmaster.txt \
conf-daily-basic-shark.txt \
conf-daily-devel-ndbmaster.txt \
diff --git a/ndb/test/run-test/basic.txt b/ndb/test/run-test/basic.txt
index a952320db08..ec9e21359e5 100644
--- a/ndb/test/run-test/basic.txt
+++ b/ndb/test/run-test/basic.txt
@@ -374,7 +374,7 @@ args: -n FragmentTypeSingle T1
max-time: 1500
cmd: testDict
-args: -n FragmentTypeAll T1 T6 T7 T8
+args: -n FragmentTypeAllSmall T1 T6 T7 T8
max-time: 1500
cmd: testDict
diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt
index fc04664564f..8b44594a9b5 100644
--- a/ndb/test/run-test/daily-basic-tests.txt
+++ b/ndb/test/run-test/daily-basic-tests.txt
@@ -75,7 +75,7 @@ max-time: 500
cmd: testBasic
args: -n PkInsert
-max-time: 600
+max-time: 660
cmd: testBasic
args: -n UpdateAndRead
@@ -207,34 +207,9 @@ max-time: 500
cmd: testBasic
args: -n MassiveRollback2 T1 T6 T13
-#-m 500 1: testBasic -n ReadConsistency T6
-max-time: 500
-cmd: testTimeout
-args: -n DontTimeoutTransaction T1
-
-max-time: 500
-cmd: testTimeout
-args: -n DontTimeoutTransaction5 T1
-
-max-time: 500
-cmd: testTimeout
-args: -n TimeoutTransaction T1
-
-max-time: 500
-cmd: testTimeout
-args: -n TimeoutTransaction5 T1
-
-max-time: 500
-cmd: testTimeout
-args: -n BuddyTransNoTimeout T1
-
max-time: 500
cmd: testTimeout
-args: -n BuddyTransNoTimeout5 T1
-
-max-time: 500
-cmd: testTimeout
-args: -n TimeoutRandTransaction T1
+args: T1
# SCAN TESTS
#
@@ -434,14 +409,9 @@ max-time: 500
cmd: testScan
args: -l 100 -n Scan-bug8262 T7
-# OLD FLEX
max-time: 500
-cmd: flexBench
-args: -c 25 -t 10
-
-max-time: 500
-cmd: flexHammer
-args: -r 5 -t 32
+cmd: testScan
+args: -n ScanParallelism
#
# DICT TESTS
@@ -475,7 +445,7 @@ args: -n FragmentTypeSingle T1
max-time: 1500
cmd: testDict
-args: -n FragmentTypeAll T1 T6 T7 T8
+args: -n FragmentTypeAllSmall T1 T6 T7 T8
max-time: 1500
cmd: testDict
@@ -554,6 +524,10 @@ max-time: 500
cmd: testNdbApi
args: -n Bug_11133 T1
+max-time: 500
+cmd: testNdbApi
+args: -n Scan_4006 T1
+
#max-time: 500
#cmd: testInterpreter
#args: T1
@@ -562,7 +536,7 @@ max-time: 150000
cmd: testOperations
args:
-max-time: 150000
+max-time: 15000
cmd: testTransactions
args:
@@ -574,10 +548,18 @@ max-time: 600
cmd: testBlobs
args:
-max-time: 2500
+max-time: 5000
cmd: testOIBasic
args:
+max-time: 2500
+cmd: testBitfield
+args:
+
+max-time: 2500
+cmd: testPartitioning
+args:
+
#
#
# SYSTEM RESTARTS
@@ -625,3 +607,42 @@ args: -n SR_UNDO T7
max-time: 1500
cmd: testSystemRestart
args: -n SR_UNDO T8
+
+# OLD FLEX
+max-time: 500
+cmd: flexBench
+args: -c 25 -t 10
+
+max-time: 500
+cmd: flexHammer
+args: -r 5 -t 32
+
+max-time: 300
+cmd: DbCreate
+args:
+
+max-time: 180
+cmd: DbAsyncGenerator
+args: -time 60 -p 1
+type: bench
+
+max-time: 180
+cmd: DbAsyncGenerator
+args: -time 60 -p 25
+type: bench
+
+max-time: 180
+cmd: DbAsyncGenerator
+args: -time 60 -p 100
+type: bench
+
+max-time: 180
+cmd: DbAsyncGenerator
+args: -time 60 -p 200
+type: bench
+
+max-time: 180
+cmd: DbAsyncGenerator
+args: -time 60 -p 1 -proc 25
+type: bench
+
diff --git a/ndb/test/run-test/daily-devel-tests.txt b/ndb/test/run-test/daily-devel-tests.txt
index 9812ec2ceaa..20f54e031e5 100644
--- a/ndb/test/run-test/daily-devel-tests.txt
+++ b/ndb/test/run-test/daily-devel-tests.txt
@@ -206,34 +206,5 @@ args: -l 1 -n SR9 T1
#
max-time: 2500
cmd: test_event
-args: -n BasicEventOperation T1 T6
-
-max-time: 300
-cmd: DbCreate
-args:
-
-max-time: 180
-cmd: DbAsyncGenerator
-args: -time 60 -p 1
-type: bench
-
-max-time: 180
-cmd: DbAsyncGenerator
-args: -time 60 -p 25
-type: bench
-
-max-time: 180
-cmd: DbAsyncGenerator
-args: -time 60 -p 100
-type: bench
-
-max-time: 180
-cmd: DbAsyncGenerator
-args: -time 60 -p 200
-type: bench
-
-max-time: 180
-cmd: DbAsyncGenerator
-args: -time 60 -p 1 -proc 25
-type: bench
+args: -n EventOperationApplier
diff --git a/ndb/test/src/HugoAsynchTransactions.cpp b/ndb/test/src/HugoAsynchTransactions.cpp
index f75293f5a14..5d2eb451c0b 100644
--- a/ndb/test/src/HugoAsynchTransactions.cpp
+++ b/ndb/test/src/HugoAsynchTransactions.cpp
@@ -17,11 +17,12 @@
#include <NdbSleep.h>
#include <HugoAsynchTransactions.hpp>
-HugoAsynchTransactions::HugoAsynchTransactions(const NdbDictionary::Table& _tab):
- HugoTransactions(_tab),
- transactionsCompleted(0),
- numTransactions(0),
- transactions(NULL){
+HugoAsynchTransactions::HugoAsynchTransactions(const NdbDictionary::Table& _t)
+ : HugoTransactions(_t),
+ transactionsCompleted(0),
+ numTransactions(0),
+ transactions(NULL)
+{
}
HugoAsynchTransactions::~HugoAsynchTransactions(){
diff --git a/ndb/test/src/HugoCalculator.cpp b/ndb/test/src/HugoCalculator.cpp
index 62c35c54a7a..8e01f6442bb 100644
--- a/ndb/test/src/HugoCalculator.cpp
+++ b/ndb/test/src/HugoCalculator.cpp
@@ -14,8 +14,26 @@
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 "HugoCalculator.hpp"
#include <NDBT.hpp>
+#include <Base64.hpp>
+
+static
+Uint32
+myRand(Uint64 * seed)
+{
+ const Uint64 mul= 0x5deece66dull;
+ const Uint64 add= 0xb;
+ Uint64 loc_result = *seed * mul + add;
+
+ * seed= loc_result;
+ return loc_result >> 1;
+}
+
+static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
/* *************************************************************
* HugoCalculator
@@ -40,7 +58,8 @@ HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) {
// The "number of updates" column for this table is found in the last column
for (i=m_tab.getNoOfColumns()-1; i>=0; i--){
const NdbDictionary::Column* attr = m_tab.getColumn(i);
- if (attr->getType() == NdbDictionary::Column::Unsigned){
+ if (attr->getType() == NdbDictionary::Column::Unsigned &&
+ !attr->getPrimaryKey()){
m_updatesCol = i;
break;
}
@@ -51,29 +70,18 @@ HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) {
#endif
// Check that idCol is not conflicting with updatesCol
assert(m_idCol != m_updatesCol && m_idCol != -1 && m_updatesCol != -1);
-};
+}
Int32
HugoCalculator::calcValue(int record,
int attrib,
int updates) const {
- const NdbDictionary::Column* attr = m_tab.getColumn(attrib);
- // If this is the "id" column
- if (attrib == m_idCol)
- return record;
-
- // If this is the update column
- if (attrib == m_updatesCol)
- return updates;
-
-
- Int32 val;
- if (attr->getPrimaryKey())
- val = record + attrib;
- else
- val = record + attrib + updates;
- return val;
-};
+
+ Int32 i;
+ calcValue(record, attrib, updates, (char*)&i, sizeof(i));
+
+ return i;
+}
#if 0
HugoCalculator::U_Int32 calcValue(int record, int attrib, int updates) const;
HugoCalculator::U_Int64 calcValue(int record, int attrib, int updates) const;
@@ -81,49 +89,121 @@ HugoCalculator::Int64 calcValue(int record, int attrib, int updates) const;
HugoCalculator::float calcValue(int record, int attrib, int updates) const;
HugoCalculator::double calcValue(int record, int attrib, int updates) const;
#endif
+
const char*
HugoCalculator::calcValue(int record,
int attrib,
int updates,
- char* buf) const {
- const char a[26] = {"UAWBORCTDPEFQGNYHISJMKXLZ"};
+ char* buf,
+ int len) const {
+ Uint64 seed;
const NdbDictionary::Column* attr = m_tab.getColumn(attrib);
- int val = calcValue(record, attrib, updates);
-
- int len;
- if (attr->getPrimaryKey()){
- // Create a string where val is printed as chars in the beginning
- // of the string, then fill with other chars
- // The string length is set to the same size as the attribute
- len = attr->getLength();
- BaseString::snprintf(buf, len, "%d", val);
- for(int i=strlen(buf); i < len; i++)
- buf[i] = a[((val^i)%25)];
- } else{
+ Uint32 val;
+ do
+ {
+ if (attrib == m_idCol)
+ {
+ val= record;
+ memcpy(buf, &val, 4);
+ return buf;
+ }
- // Fill buf with some pattern so that we can detect
- // anomalies in the area that we don't fill with chars
- int i;
- for (i = 0; i<attr->getLength(); i++)
- buf[i] = ((i+2) % 255);
+ // If this is the update column
+ if (attrib == m_updatesCol)
+ {
+ val= updates;
+ memcpy(buf, &val, 4);
+ return buf;
+ }
+
+ if (attr->getPrimaryKey())
+ {
+ seed = record + attrib;
+ }
+ else
+ {
+ seed = record + attrib + updates;
+ }
+ } while (0);
+
+ val = myRand(&seed);
+
+ if(attr->getNullable() && (((val >> 16) & 255) > 220))
+ return NULL;
+
+ int pos= 0;
+ switch(attr->getType()){
+ case NdbDictionary::Column::Tinyint:
+ case NdbDictionary::Column::Tinyunsigned:
+ case NdbDictionary::Column::Smallint:
+ case NdbDictionary::Column::Smallunsigned:
+ case NdbDictionary::Column::Mediumint:
+ case NdbDictionary::Column::Mediumunsigned:
+ case NdbDictionary::Column::Int:
+ case NdbDictionary::Column::Unsigned:
+ case NdbDictionary::Column::Bigint:
+ case NdbDictionary::Column::Bigunsigned:
+ case NdbDictionary::Column::Float:
+ case NdbDictionary::Column::Double:
+ case NdbDictionary::Column::Olddecimal:
+ case NdbDictionary::Column::Olddecimalunsigned:
+ case NdbDictionary::Column::Decimal:
+ case NdbDictionary::Column::Decimalunsigned:
+ case NdbDictionary::Column::Binary:
+ case NdbDictionary::Column::Datetime:
+ case NdbDictionary::Column::Time:
+ case NdbDictionary::Column::Date:
+ case NdbDictionary::Column::Bit:
+ while (len > 4)
+ {
+ memcpy(buf+pos, &val, 4);
+ pos += 4;
+ len -= 4;
+ val= myRand(&seed);
+ }
- // Calculate length of the string to create. We want the string
- // length to be varied between max and min of this attribute.
-
- len = val % (attr->getLength() + 1);
- // If len == 0 return NULL if this is a nullable attribute
- if (len == 0){
- if(attr->getNullable() == true)
- return NULL;
- else
- len++;
+ memcpy(buf+pos, &val, len);
+ if(attr->getType() == NdbDictionary::Column::Bit)
+ {
+ Uint32 bits= attr->getLength();
+ Uint32 tmp = bits >> 5;
+ Uint32 size = bits & 31;
+ ((Uint32*)buf)[tmp] &= ((1 << size) - 1);
}
- for(i=0; i < len; i++)
- buf[i] = a[((val^i)%25)];
- buf[len] = 0;
+ break;
+ case NdbDictionary::Column::Varbinary:
+ case NdbDictionary::Column::Varchar:
+ case NdbDictionary::Column::Text:
+ case NdbDictionary::Column::Char:
+ case NdbDictionary::Column::Longvarchar:
+ case NdbDictionary::Column::Longvarbinary:
+ {
+ char* ptr= (char*)&val;
+ while(len >= 4)
+ {
+ len -= 4;
+ buf[pos++] = base64_table[ptr[0] & 0x3f];
+ buf[pos++] = base64_table[ptr[1] & 0x3f];
+ buf[pos++] = base64_table[ptr[2] & 0x3f];
+ buf[pos++] = base64_table[ptr[3] & 0x3f];
+ val= myRand(&seed);
+ }
+
+ for(; len; len--, pos++)
+ buf[pos] = base64_table[ptr[len] & 0x3f];
+
+ pos--;
+ break;
}
+ case NdbDictionary::Column::Blob:
+ case NdbDictionary::Column::Undefined:
+ abort();
+ break;
+ }
+
+
return buf;
-};
+}
int
HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{
@@ -131,104 +211,48 @@ HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{
id = pRow->attributeStore(m_idCol)->u_32_value();
updates = pRow->attributeStore(m_updatesCol)->u_32_value();
-
+ int result = 0;
+
// Check the values of each column
for (int i = 0; i<m_tab.getNoOfColumns(); i++){
if (i != m_updatesCol && id != m_idCol) {
-
const NdbDictionary::Column* attr = m_tab.getColumn(i);
- switch (attr->getType()){
- case NdbDictionary::Column::Char:
- case NdbDictionary::Column::Varchar:
- case NdbDictionary::Column::Binary:
- case NdbDictionary::Column::Varbinary:{
- int result = 0;
- char* buf = new char[attr->getLength()+1];
- const char* res = calcValue(id, i, updates, buf);
- if (res == NULL){
- if (!pRow->attributeStore(i)->isNULL()){
- g_err << "|- NULL ERROR: expected a NULL but the column was not null" << endl;
- g_err << "|- The row: \"" << (*pRow) << "\"" << endl;
- result = -1;
- }
- } else{
- if (memcmp(res, pRow->attributeStore(i)->aRef(), pRow->attributeStore(i)->arraySize()) != 0){
- // if (memcmp(res, pRow->attributeStore(i)->aRef(), pRow->attributeStore(i)->getLength()) != 0){
- g_err << "arraySize(): "
- << pRow->attributeStore(i)->arraySize()
- << ", NdbDict::Column::getLength(): " << attr->getLength()
- << endl;
- const char* buf2 = pRow->attributeStore(i)->aRef();
- for (Uint32 j = 0; j < pRow->attributeStore(i)->arraySize(); j++)
+ Uint32 len = attr->getSizeInBytes();
+ char buf[8000];
+ const char* res = calcValue(id, i, updates, buf, len);
+ if (res == NULL){
+ if (!pRow->attributeStore(i)->isNULL()){
+ g_err << "|- NULL ERROR: expected a NULL but the column was not null" << endl;
+ g_err << "|- The row: \"" << (*pRow) << "\"" << endl;
+ result = -1;
+ }
+ } else{
+ if (memcmp(res, pRow->attributeStore(i)->aRef(), len) != 0){
+ g_err << "Column: " << attr->getName() << endl;
+ const char* buf2 = pRow->attributeStore(i)->aRef();
+ for (Uint32 j = 0; j < len; j++)
+ {
+ g_err << j << ":" << hex << (Uint32)(Uint8)buf[j] << "[" << hex << (Uint32)(Uint8)buf2[j] << "]";
+ if (buf[j] != buf2[j])
{
- g_err << j << ":" << buf[j] << "[" << buf2[j] << "]";
- if (buf[j] != buf2[j])
- {
- g_err << "==>Match failed!";
- }
- g_err << endl;
+ g_err << "==>Match failed!";
}
g_err << endl;
- g_err << "|- Invalid data found in attribute " << i << ": \""
- << pRow->attributeStore(i)->aRef()
- << "\" != \"" << res << "\"" << endl
- << "Length of expected=" << (unsigned)strlen(res) << endl
- << "Lenght of read="
- << (unsigned)strlen(pRow->attributeStore(i)->aRef()) << endl;
- g_err << "|- The row: \"" << (* pRow) << "\"" << endl;
- result = -1;
}
- }
- delete []buf;
- if (result != 0)
- return result;
- }
- break;
- case NdbDictionary::Column::Int:
- case NdbDictionary::Column::Unsigned:{
- Int32 cval = calcValue(id, i, updates);
- Int32 val = pRow->attributeStore(i)->int32_value();
- if (val != cval){
- g_err << "|- Invalid data found: \"" << val << "\" != \""
- << cval << "\"" << endl;
- g_err << "|- The row: \"" << (* pRow) << "\"" << endl;
- return -1;
- }
- break;
- }
- case NdbDictionary::Column::Bigint:
- case NdbDictionary::Column::Bigunsigned:{
- Uint64 cval = calcValue(id, i, updates);
- Uint64 val = pRow->attributeStore(i)->u_64_value();
- if (val != cval){
- g_err << "|- Invalid data found: \"" << val << "\" != \""
- << cval << "\""
- << endl;
+ g_err << endl;
+ g_err << "|- Invalid data found in attribute " << i << ": \""
+ << pRow->attributeStore(i)->aRef()
+ << "\" != \"" << res << "\"" << endl
+ << "Length of expected=" << (unsigned)strlen(res) << endl
+ << "Lenght of read="
+ << (unsigned)strlen(pRow->attributeStore(i)->aRef()) << endl;
g_err << "|- The row: \"" << (* pRow) << "\"" << endl;
- return -1;
+ result = -1;
}
}
- break;
- case NdbDictionary::Column::Float:{
- float cval = calcValue(id, i, updates);
- float val = pRow->attributeStore(i)->float_value();
- if (val != cval){
- g_err << "|- Invalid data found: \"" << val << "\" != \""
- << cval << "\"" << endl;
- g_err << "|- The row: \"" << (* pRow) << "\"" << endl;
- return -1;
- }
- }
- break;
- case NdbDictionary::Column::Undefined:
- default:
- assert(false);
- break;
- }
-
}
}
- return 0;
+ return result;
}
int
diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp
index 6b1a1ca395b..f2e54971766 100644
--- a/ndb/test/src/HugoOperations.cpp
+++ b/ndb/test/src/HugoOperations.cpp
@@ -31,6 +31,19 @@ int HugoOperations::startTransaction(Ndb* pNdb){
return NDBT_OK;
}
+int HugoOperations::setTransaction(NdbTransaction* new_trans){
+
+ if (pTrans != NULL){
+ ndbout << "HugoOperations::startTransaction, pTrans != NULL" << endl;
+ return NDBT_FAILED;
+ }
+ pTrans = new_trans;
+ if (pTrans == NULL) {
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
void
HugoOperations::setTransactionId(Uint64 id){
if (pTrans != NULL){
@@ -40,11 +53,7 @@ HugoOperations::setTransactionId(Uint64 id){
int HugoOperations::closeTransaction(Ndb* pNdb){
- if (pTrans != NULL){
- pNdb->closeTransaction(pTrans);
- pTrans = NULL;
- }
- pTrans = NULL;
+ UtilTransactions::closeTransaction(pNdb);
m_result_sets.clear();
m_executed_result_sets.clear();
@@ -63,8 +72,16 @@ int HugoOperations::pkReadRecord(Ndb* pNdb,
int a;
allocRows(numRecords);
int check;
+
+ NdbOperation* pOp = 0;
+ pIndexScanOp = 0;
+
for(int r=0; r < numRecords; r++){
- NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());
+
+ if(pOp == 0)
+ {
+ pOp = getOperation(pTrans, NdbOperation::ReadRequest);
+ }
if (pOp == NULL) {
ERR(pTrans->getNdbError());
return NDBT_FAILED;
@@ -73,13 +90,16 @@ int HugoOperations::pkReadRecord(Ndb* pNdb,
rand_lock_mode:
switch(lm){
case NdbOperation::LM_Read:
- check = pOp->readTuple();
- break;
case NdbOperation::LM_Exclusive:
- check = pOp->readTupleExclusive();
- break;
case NdbOperation::LM_CommittedRead:
- check = pOp->dirtyRead();
+ if(idx && idx->getType() == NdbDictionary::Index::OrderedIndex &&
+ pIndexScanOp == 0)
+ {
+ pIndexScanOp = ((NdbIndexScanOperation*)pOp);
+ check = pIndexScanOp->readTuples(lm);
+ }
+ else
+ check = pOp->readTuple(lm);
break;
default:
lm = (NdbOperation::LockMode)((rand() >> 16) & 3);
@@ -100,15 +120,22 @@ rand_lock_mode:
}
}
}
+
+ if(pIndexScanOp)
+ pIndexScanOp->end_of_bound(r);
- // Define attributes to read
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if((rows[r]->attributeStore(a) =
- pOp->getValue(tab.getColumn(a)->getName())) == 0) {
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
- }
+ if(r == 0 || pIndexScanOp == 0)
+ {
+ // Define attributes to read
+ for(a = 0; a<tab.getNoOfColumns(); a++){
+ if((rows[r]->attributeStore(a) =
+ pOp->getValue(tab.getColumn(a)->getName())) == 0) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+ }
+ }
+ pOp = pIndexScanOp;
}
return NDBT_OK;
}
@@ -121,7 +148,7 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb,
allocRows(numRecords);
int check;
for(int r=0; r < numRecords; r++){
- NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());
+ NdbOperation* pOp = getOperation(pTrans, NdbOperation::UpdateRequest);
if (pOp == NULL) {
ERR(pTrans->getNdbError());
return NDBT_FAILED;
@@ -133,26 +160,37 @@ int HugoOperations::pkUpdateRecord(Ndb* pNdb,
return NDBT_FAILED;
}
- // Define primary keys
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pOp, a, r+recordNo) != 0){
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
+ if(setValues(pOp, r+recordNo, updatesValue) != NDBT_OK)
+ {
+ return NDBT_FAILED;
+ }
+ }
+ return NDBT_OK;
+}
+
+int
+HugoOperations::setValues(NdbOperation* pOp, int rowId, int updateId)
+{
+ // Define primary keys
+ int a;
+ for(a = 0; a<tab.getNoOfColumns(); a++){
+ if (tab.getColumn(a)->getPrimaryKey() == true){
+ if(equalForAttr(pOp, a, rowId) != 0){
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
}
}
-
- // Define attributes to update
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == false){
- if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
+ }
+
+ for(a = 0; a<tab.getNoOfColumns(); a++){
+ if (tab.getColumn(a)->getPrimaryKey() == false){
+ if(setValueForAttr(pOp, a, rowId, updateId ) != 0){
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
}
- }
+ }
}
+
return NDBT_OK;
}
@@ -163,7 +201,7 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb,
int a, check;
for(int r=0; r < numRecords; r++){
- NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());
+ NdbOperation* pOp = getOperation(pTrans, NdbOperation::InsertRequest);
if (pOp == NULL) {
ERR(pTrans->getNdbError());
return NDBT_FAILED;
@@ -175,25 +213,10 @@ int HugoOperations::pkInsertRecord(Ndb* pNdb,
return NDBT_FAILED;
}
- // Define primary keys
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pOp, a, r+recordNo) != 0){
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
- }
+ if(setValues(pOp, r+recordNo, updatesValue) != NDBT_OK)
+ {
+ return NDBT_FAILED;
}
-
- // Define attributes to update
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == false){
- if(setValueForAttr(pOp, a, recordNo+r, updatesValue ) != 0){
- ERR(pTrans->getNdbError());
- return NDBT_FAILED;
- }
- }
- }
}
return NDBT_OK;
}
@@ -240,9 +263,9 @@ int HugoOperations::pkWriteRecord(Ndb* pNdb,
return NDBT_OK;
}
-int HugoOperations::pkDeleteRecord(Ndb* pNdb,
- int recordNo,
- int numRecords){
+int HugoOperations::pkWritePartialRecord(Ndb* pNdb,
+ int recordNo,
+ int numRecords){
int a, check;
for(int r=0; r < numRecords; r++){
@@ -252,7 +275,7 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb,
return NDBT_FAILED;
}
- check = pOp->deleteTuple();
+ check = pOp->writeTuple();
if( check == -1 ) {
ERR(pTrans->getNdbError());
return NDBT_FAILED;
@@ -270,65 +293,37 @@ int HugoOperations::pkDeleteRecord(Ndb* pNdb,
}
return NDBT_OK;
}
-#if 0
-NdbResultSet*
-HugoOperations::scanReadRecords(Ndb* pNdb, ScanLock lock){
-
- NDBT_ResultRow * m_tmpRow = new NDBT_ResultRow(tab);
-
- NdbScanOperation* pOp = pTrans->getNdbScanOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- return 0;
- }
-
- int check = 0;
- NdbResultSet * rs = 0;
- switch(lock){
- case SL_ReadHold:
- rs = pOp->readTuples(NdbScanOperation::LM_Read, 1, 1);
- break;
- case SL_Exclusive:
- rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 1, 1);
- break;
- case SL_Read:
- default:
- rs = pOp->readTuples(NdbScanOperation::LM_Dirty, 1, 1);
- }
-
- if( rs == 0) {
- ERR(pTrans->getNdbError());
- return 0;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- return 0;
- }
+int HugoOperations::pkDeleteRecord(Ndb* pNdb,
+ int recordNo,
+ int numRecords){
- // Define attributes to read
- for(int a = 0; a<tab.getNoOfColumns(); a++){
- if((m_tmpRow->attributeStore(a) =
- pOp->getValue(tab.getColumn(a)->getName())) == 0) {
+ int a, check;
+ for(int r=0; r < numRecords; r++){
+ NdbOperation* pOp = getOperation(pTrans, NdbOperation::DeleteRequest);
+ if (pOp == NULL) {
ERR(pTrans->getNdbError());
- return 0;
+ return NDBT_FAILED;
+ }
+
+ check = pOp->deleteTuple();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ // Define primary keys
+ for(a = 0; a<tab.getNoOfColumns(); a++){
+ if (tab.getColumn(a)->getPrimaryKey() == true){
+ if(equalForAttr(pOp, a, r+recordNo) != 0){
+ ERR(pTrans->getNdbError());
+ return NDBT_FAILED;
+ }
+ }
}
- }
- return rs;
-}
-
-int
-HugoOperations::readTuples(NdbResultSet* rs){
- int res = 0;
- while((res = rs->nextResult()) == 0){
}
- if(res != 1)
- return NDBT_FAILED;
return NDBT_OK;
}
-#endif
int HugoOperations::execute_Commit(Ndb* pNdb,
AbortOption eao){
@@ -353,7 +348,7 @@ int HugoOperations::execute_Commit(Ndb* pNdb,
m_executed_result_sets.push_back(m_result_sets[i]);
int rows = m_result_sets[i].records;
- NdbResultSet* rs = m_result_sets[i].m_result_set;
+ NdbScanOperation* rs = m_result_sets[i].m_result_set;
int res = rs->nextResult();
switch(res){
case 1:
@@ -402,7 +397,7 @@ int HugoOperations::execute_NoCommit(Ndb* pNdb, AbortOption eao){
m_executed_result_sets.push_back(m_result_sets[i]);
int rows = m_result_sets[i].records;
- NdbResultSet* rs = m_result_sets[i].m_result_set;
+ NdbScanOperation* rs = m_result_sets[i].m_result_set;
int res = rs->nextResult();
switch(res){
case 1:
@@ -441,21 +436,29 @@ int HugoOperations::execute_Rollback(Ndb* pNdb){
}
void
-HugoOperations_async_callback(int res, NdbConnection* pCon, void* ho)
+HugoOperations_async_callback(int res, NdbTransaction* pCon, void* ho)
{
((HugoOperations*)ho)->callback(res, pCon);
}
void
-HugoOperations::callback(int res, NdbConnection* pCon)
+HugoOperations::callback(int res, NdbTransaction* pCon)
{
assert(pCon == pTrans);
m_async_reply= 1;
- m_async_return= res;
+ if(res)
+ {
+ m_async_return = pCon->getNdbError().code;
+ }
+ else
+ {
+ m_async_return = 0;
+ }
}
int
-HugoOperations::execute_async(Ndb* pNdb, ExecType et, AbortOption eao){
+HugoOperations::execute_async(Ndb* pNdb, NdbTransaction::ExecType et,
+ NdbTransaction::AbortOption eao){
m_async_reply= 0;
pTrans->executeAsynchPrepare(et,
@@ -475,16 +478,18 @@ HugoOperations::wait_async(Ndb* pNdb, int timeout)
if(m_async_reply)
{
+ if(m_async_return)
+ ndbout << "ERROR: " << pNdb->getNdbError(m_async_return) << endl;
return m_async_return;
}
ndbout_c("wait returned nothing...");
return -1;
}
-HugoOperations::HugoOperations(const NdbDictionary::Table& _tab):
- UtilTransactions(_tab),
- calc(_tab),
- pTrans(NULL)
+HugoOperations::HugoOperations(const NdbDictionary::Table& _tab,
+ const NdbDictionary::Index* idx):
+ UtilTransactions(_tab, idx),
+ calc(_tab)
{
}
@@ -501,101 +506,32 @@ HugoOperations::~HugoOperations(){
int HugoOperations::equalForAttr(NdbOperation* pOp,
int attrId,
int rowId){
- int check = 0;
+ int check = -1;
const NdbDictionary::Column* attr = tab.getColumn(attrId);
if (attr->getPrimaryKey() == false){
g_info << "Can't call equalForAttr on non PK attribute" << endl;
return NDBT_FAILED;
}
- switch (attr->getType()){
- case NdbDictionary::Column::Char:
- case NdbDictionary::Column::Varchar:
- case NdbDictionary::Column::Binary:
- case NdbDictionary::Column::Varbinary:{
- char buf[8000];
- memset(buf, 0, sizeof(buf));
- check = pOp->equal( attr->getName(), calc.calcValue(rowId, attrId, 0, buf));
- break;
- }
- case NdbDictionary::Column::Int:
- check = pOp->equal( attr->getName(), (Int32)calc.calcValue(rowId, attrId, 0));
- break;
- case NdbDictionary::Column::Unsigned:
- check = pOp->equal( attr->getName(), (Uint32)calc.calcValue(rowId, attrId, 0));
- break;
- case NdbDictionary::Column::Bigint:
- check = pOp->equal( attr->getName(), (Int64)calc.calcValue(rowId, attrId, 0));
- break;
- case NdbDictionary::Column::Bigunsigned:
- check = pOp->equal( attr->getName(), (Uint64)calc.calcValue(rowId, attrId, 0));
- break;
- case NdbDictionary::Column::Float:
- g_info << "Float not allowed as PK value" << endl;
- check = -1;
- break;
-
- default:
- g_info << "default" << endl;
- check = -1;
- break;
- }
- return check;
+ int len = attr->getSizeInBytes();
+ char buf[8000];
+ memset(buf, 0, sizeof(buf));
+ return pOp->equal( attr->getName(),
+ calc.calcValue(rowId, attrId, 0, buf, len));
}
int HugoOperations::setValueForAttr(NdbOperation* pOp,
int attrId,
int rowId,
int updateId){
- int check = 0;
+ int check = -1;
const NdbDictionary::Column* attr = tab.getColumn(attrId);
-
- if (attr->getTupleKey()){
- // Don't set values for TupleId PKs
- return check;
- }
- switch (attr->getType()){
- case NdbDictionary::Column::Char:
- case NdbDictionary::Column::Varchar:
- case NdbDictionary::Column::Binary:
- case NdbDictionary::Column::Varbinary:{
- char buf[8000];
- check = pOp->setValue( attr->getName(),
- calc.calcValue(rowId, attrId, updateId, buf));
- break;
- }
- case NdbDictionary::Column::Int:{
- Int32 val = calc.calcValue(rowId, attrId, updateId);
- check = pOp->setValue( attr->getName(), val);
- }
- break;
- case NdbDictionary::Column::Bigint:{
- Int64 val = calc.calcValue(rowId, attrId, updateId);
- check = pOp->setValue( attr->getName(),
- val);
- }
- break;
- case NdbDictionary::Column::Unsigned:{
- Uint32 val = calc.calcValue(rowId, attrId, updateId);
- check = pOp->setValue( attr->getName(), val);
- }
- break;
- case NdbDictionary::Column::Bigunsigned:{
- Uint64 val = calc.calcValue(rowId, attrId, updateId);
- check = pOp->setValue( attr->getName(),
- val);
- }
- break;
- case NdbDictionary::Column::Float:
- check = pOp->setValue( attr->getName(),
- (float)calc.calcValue(rowId, attrId, updateId));
- break;
- default:
- check = -1;
- break;
- }
- return check;
+ int len = attr->getSizeInBytes();
+ char buf[8000];
+ memset(buf, 0, sizeof(buf));
+ return pOp->setValue( attr->getName(),
+ calc.calcValue(rowId, attrId, updateId, buf, len));
}
int
@@ -611,7 +547,7 @@ HugoOperations::verifyUpdatesValue(int updatesValue, int _numRows){
result = NDBT_FAILED;
continue;
}
-
+
if(calc.getUpdatesValue(rows[i]) != updatesValue){
result = NDBT_FAILED;
g_err << "Invalid updates value for row " << i << endl
@@ -621,7 +557,7 @@ HugoOperations::verifyUpdatesValue(int updatesValue, int _numRows){
continue;
}
}
-
+
if(_numRows == 0){
g_err << "No rows -> Invalid updates value" << endl;
return NDBT_FAILED;
@@ -631,14 +567,12 @@ HugoOperations::verifyUpdatesValue(int updatesValue, int _numRows){
}
void HugoOperations::allocRows(int _numRows){
- deallocRows();
-
if(_numRows <= 0){
g_info << "Illegal value for num rows : " << _numRows << endl;
abort();
}
- for(int b=0; b<_numRows; b++){
+ for(int b=rows.size(); b<_numRows; b++){
rows.push_back(new NDBT_ResultRow(tab));
}
}
@@ -694,7 +628,7 @@ int HugoOperations::compareRecordToCopy(int numRecords ){
void
HugoOperations::refresh() {
- NdbConnection* t = getTransaction();
+ NdbTransaction * t = getTransaction();
if(t)
t->refresh();
}
@@ -799,12 +733,10 @@ HugoOperations::scanReadRecords(Ndb* pNdb, NdbScanOperation::LockMode lm,
if(!pOp)
return -1;
- NdbResultSet * rs = pOp->readTuples(lm, 1, 1);
-
- if(!rs){
+ if(pOp->readTuples(lm, 0, 1)){
return -1;
}
-
+
for(int a = 0; a<tab.getNoOfColumns(); a++){
if((rows[0]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
@@ -812,8 +744,8 @@ HugoOperations::scanReadRecords(Ndb* pNdb, NdbScanOperation::LockMode lm,
return NDBT_FAILED;
}
}
-
- RsPair p = {rs, records};
+
+ RsPair p = {pOp, records};
m_result_sets.push_back(p);
return 0;
diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp
index 5d5b2fa99df..3260b921985 100644
--- a/ndb/test/src/HugoTransactions.cpp
+++ b/ndb/test/src/HugoTransactions.cpp
@@ -18,8 +18,9 @@
#include <NdbSleep.h>
-HugoTransactions::HugoTransactions(const NdbDictionary::Table& _tab):
- HugoOperations(_tab),
+HugoTransactions::HugoTransactions(const NdbDictionary::Table& _tab,
+ const NdbDictionary::Index* idx):
+ HugoOperations(_tab, idx),
row(_tab){
m_defaultScanUpdateMethod = 3;
@@ -34,7 +35,8 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
int records,
int abortPercent,
int parallelism,
- NdbOperation::LockMode lm)
+ NdbOperation::LockMode lm,
+ int scan_flags)
{
int retryAttempt = 0;
@@ -64,17 +66,14 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbScanOperation(tab.getName());
+ pOp = getScanOperation(pTrans);
if (pOp == NULL) {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
return NDBT_FAILED;
}
- NdbResultSet * rs;
- rs = pOp ->readTuples(lm);
-
- if( rs == 0 ) {
+ if( pOp ->readTuples(lm, scan_flags, parallelism) ) {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
return NDBT_FAILED;
@@ -123,7 +122,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
int eof;
int rows = 0;
- while((eof = rs->nextResult(true)) == 0){
+ while((eof = pOp->nextResult(true)) == 0){
rows++;
if (calc.verifyRowValues(&row) != 0){
closeTransaction(pNdb);
@@ -133,7 +132,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
if (abortCount == rows && abortTrans == true){
ndbout << "Scan is aborted" << endl;
g_info << "Scan is aborted" << endl;
- rs->close();
+ pOp->close();
if( check == -1 ) {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
@@ -189,7 +188,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
int abortPercent,
int parallelism,
NdbOperation::LockMode lm,
- bool sorted)
+ int scan_flags)
{
int retryAttempt = 0;
@@ -226,10 +225,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- NdbResultSet * rs;
- rs = pOp ->readTuples(lm, 0, parallelism, sorted);
-
- if( rs == 0 ) {
+ if( pOp ->readTuples(lm, scan_flags, parallelism) ) {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
return NDBT_FAILED;
@@ -278,7 +274,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
int eof;
int rows = 0;
- while((eof = rs->nextResult(true)) == 0){
+ while((eof = pOp->nextResult(true)) == 0){
rows++;
if (calc.verifyRowValues(&row) != 0){
closeTransaction(pNdb);
@@ -288,7 +284,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
if (abortCount == rows && abortTrans == true){
ndbout << "Scan is aborted" << endl;
g_info << "Scan is aborted" << endl;
- rs->close();
+ pOp->close();
if( check == -1 ) {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
@@ -361,161 +357,7 @@ HugoTransactions::scanUpdateRecords1(Ndb* pNdb,
int records,
int abortPercent,
int parallelism){
-#if 1
return scanUpdateRecords3(pNdb, records, abortPercent, 1);
-#else
- int retryAttempt = 0;
- const int retryMax = 100;
- int check, a;
- NdbOperation *pOp;
-
-
- while (true){
-
- if (retryAttempt >= retryMax){
- g_info << "ERROR: has retried this operation " << retryAttempt
- << " times, failing!" << endl;
- return NDBT_FAILED;
- }
-
- pTrans = pNdb->startTransaction();
- if (pTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanExclusive(parallelism);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- // Read all attributes from this table
- for(a=0; a<tab.getNoOfColumns(); a++){
- if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
-
- check = pTrans->executeScan();
- if( check == -1 ) {
- const NdbError err = pTrans->getNdbError();
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- closeTransaction(pNdb);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- // Abort after 1-100 or 1-records rows
- int ranVal = rand();
- int abortCount = ranVal % (records == 0 ? 100 : records);
- bool abortTrans = false;
- if (abort > 0){
- // Abort if abortCount is less then abortPercent
- if (abortCount < abortPercent)
- abortTrans = true;
- }
-
-
- int eof;
- int rows = 0;
-
- eof = pTrans->nextScanResult();
- while(eof == 0){
- rows++;
-
- if (abortCount == rows && abortTrans == true){
- g_info << "Scan is aborted" << endl;
- // This scan should be aborted
- check = pTrans->stopScan();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- closeTransaction(pNdb);
- return NDBT_OK;
- }
- int res = takeOverAndUpdateRecord(pNdb, pOp);
- if(res == RESTART_SCAN){
- eof = -2;
- continue;
- }
- if (res != 0){
- closeTransaction(pNdb);
- return res;
- }
-
- eof = pTrans->nextScanResult();
- }
- if (eof == -1) {
- const NdbError err = pTrans->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- switch (err.code){
- case 488:
- case 245:
- case 490:
- // Too many active scans, no limit on number of retry attempts
- break;
- default:
- retryAttempt++;
- }
- continue;
- }
- ERR(err);
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- if(eof == -2){
- closeTransaction(pNdb);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
-
- closeTransaction(pNdb);
-
- g_info << rows << " rows have been updated" << endl;
- return NDBT_OK;
- }
- return NDBT_FAILED;
-#endif
}
// Scan all records exclusive and update
@@ -527,166 +369,7 @@ HugoTransactions::scanUpdateRecords2(Ndb* pNdb,
int records,
int abortPercent,
int parallelism){
-#if 1
return scanUpdateRecords3(pNdb, records, abortPercent, parallelism);
-#else
- int retryAttempt = 0;
- const int retryMax = 100;
- int check, a;
- NdbOperation *pOp;
-
-
- while (true){
-
- if (retryAttempt >= retryMax){
- g_info << "ERROR: has retried this operation " << retryAttempt
- << " times, failing!" << endl;
- return NDBT_FAILED;
- }
-
- pTrans = pNdb->startTransaction();
- if (pTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanExclusive(parallelism);
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- // Read all attributes from this table
- for(a=0; a<tab.getNoOfColumns(); a++){
- if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
-
- check = pTrans->executeScan();
- if( check == -1 ) {
- const NdbError err = pTrans->getNdbError();
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- closeTransaction(pNdb);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- // Abort after 1-100 or 1-records rows
- int ranVal = rand();
- int abortCount = ranVal % (records == 0 ? 100 : records);
- bool abortTrans = false;
- if (abort > 0){
- // Abort if abortCount is less then abortPercent
- if (abortCount < abortPercent)
- abortTrans = true;
- }
-
- int eof;
- int rows = 0;
-
- while((eof = pTrans->nextScanResult(true)) == 0){
- pUpTrans = pNdb->startTransaction();
- if (pUpTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- return NDBT_FAILED;
- }
- do {
- rows++;
- if (addRowToUpdate(pNdb, pUpTrans, pOp) != 0){
- pNdb->closeTransaction(pUpTrans);
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- } while((eof = pTrans->nextScanResult(false)) == 0);
-
- if (abortCount == rows && abortTrans == true){
- g_info << "Scan is aborted" << endl;
- // This scan should be aborted
- check = pTrans->stopScan();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- pNdb->closeTransaction(pUpTrans);
- return NDBT_FAILED;
- }
-
- closeTransaction(pNdb);
- pNdb->closeTransaction(pUpTrans);
- return NDBT_OK;
- }
-
- check = pUpTrans->execute(Commit);
- if( check == -1 ) {
- const NdbError err = pUpTrans->getNdbError();
- ERR(err);
- pNdb->closeTransaction(pUpTrans);
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- pNdb->closeTransaction(pUpTrans);
- }
- if (eof == -1) {
- const NdbError err = pTrans->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- closeTransaction(pNdb);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- closeTransaction(pNdb);
-
- g_info << rows << " rows have been updated" << endl;
- return NDBT_OK;
- }
- return NDBT_FAILED;
-#endif
}
int
@@ -719,15 +402,14 @@ restart:
return NDBT_FAILED;
}
- pOp = pTrans->getNdbScanOperation(tab.getName());
+ pOp = getScanOperation(pTrans);
if (pOp == NULL) {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
return NDBT_FAILED;
}
- NdbResultSet *rs = pOp->readTuplesExclusive(parallelism);
- if( rs == 0 ) {
+ if( pOp->readTuplesExclusive(parallelism) ) {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
return NDBT_FAILED;
@@ -765,10 +447,10 @@ restart:
}
int rows = 0;
- while((check = rs->nextResult(true)) == 0){
+ while((check = pOp->nextResult(true)) == 0){
do {
rows++;
- NdbOperation* pUp = rs->updateTuple();
+ NdbOperation* pUp = pOp->updateCurrentTuple();
if(pUp == 0){
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
@@ -792,7 +474,7 @@ restart:
closeTransaction(pNdb);
return NDBT_OK;
}
- } while((check = rs->nextResult(false)) == 0);
+ } while((check = pOp->nextResult(false)) == 0);
if(check != -1){
check = pTrans->execute(Commit);
@@ -858,7 +540,11 @@ HugoTransactions::loadTable(Ndb* pNdb,
g_info << "|- Inserting records..." << endl;
for (int c=0 ; c<records ; ){
- bool closeTrans;
+ bool closeTrans = true;
+
+ if(c + batch > records)
+ batch = records - c;
+
if (retryAttempt >= retryMax){
g_info << "Record " << c << " could not be inserted, has retried "
<< retryAttempt << " times " << endl;
@@ -887,30 +573,11 @@ HugoTransactions::loadTable(Ndb* pNdb,
}
}
- for(int b = 0; b < batch && c+b<records; b++){
-
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- // Set a calculated value for each attribute in this table
- for (a = 0; a<tab.getNoOfColumns(); a++){
- if(setValueForAttr(pOp, a, c+b, 0 ) != 0){
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
+ if(pkInsertRecord(pNdb, c, batch) != NDBT_OK)
+ {
+ ERR(pTrans->getNdbError());
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
}
// Execute the transaction and insert the record
@@ -976,6 +643,9 @@ HugoTransactions::loadTable(Ndb* pNdb,
c = c+batch;
retryAttempt = 0;
}
+
+ if(pTrans)
+ closeTransaction(pNdb);
return NDBT_OK;
}
@@ -986,8 +656,20 @@ HugoTransactions::fillTable(Ndb* pNdb,
int retryAttempt = 0;
int retryMax = 5;
NdbOperation *pOp;
+
+ const int org = batch;
+ const int cols = tab.getNoOfColumns();
+ const int brow = tab.getRowSizeInBytes();
+ const int bytes = 12 + brow + 4 * cols;
+ batch = (batch * 256); // -> 512 -> 65536k per commit
+ batch = batch/bytes; //
+ batch = batch == 0 ? 1 : batch;
+
+ if(batch != org){
+ g_info << "batch = " << org << " rowsize = " << bytes
+ << " -> rows/commit = " << batch << endl;
+ }
- g_info << "|- Inserting records..." << endl;
for (int c=0 ; ; ){
if (retryAttempt >= retryMax){
@@ -1012,30 +694,11 @@ HugoTransactions::fillTable(Ndb* pNdb,
return NDBT_FAILED;
}
- for(b = 0; b < batch; b++){
-
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->insertTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- // Set a calculated value for each attribute in this table
- for (a = 0; a<tab.getNoOfColumns(); a++){
- if(setValueForAttr(pOp, a, c+b, 0 ) != 0){
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
+ if(pkInsertRecord(pNdb, c, batch) != NDBT_OK)
+ {
+ ERR(pTrans->getNdbError());
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
}
// Execute the transaction and insert the record
@@ -1113,7 +776,9 @@ HugoTransactions::createEvent(Ndb* pNdb){
NdbDictionary::Dictionary *myDict = pNdb->getDictionary();
if (!myDict) {
- printf("Event Creation failedDictionary not found");
+ g_err << "Dictionary not found "
+ << pNdb->getNdbError().code << " "
+ << pNdb->getNdbError().message << endl;
return NDBT_FAILED;
}
@@ -1134,21 +799,33 @@ HugoTransactions::createEvent(Ndb* pNdb){
if (res == 0)
myEvent.print();
- else {
- g_info << "Event creation failed\n";
- g_info << "trying drop Event, maybe event exists\n";
+ else if (myDict->getNdbError().classification ==
+ NdbError::SchemaObjectExists)
+ {
+ g_info << "Event creation failed event exists\n";
res = myDict->dropEvent(eventName);
if (res) {
- g_err << "failed to drop event\n";
+ g_err << "Failed to drop event: "
+ << myDict->getNdbError().code << " : "
+ << myDict->getNdbError().message << endl;
return NDBT_FAILED;
}
// try again
res = myDict->createEvent(myEvent); // Add event to database
if (res) {
- g_err << "failed to create event\n";
+ g_err << "Failed to create event (1): "
+ << myDict->getNdbError().code << " : "
+ << myDict->getNdbError().message << endl;
return NDBT_FAILED;
}
}
+ else
+ {
+ g_err << "Failed to create event (2): "
+ << myDict->getNdbError().code << " : "
+ << myDict->getNdbError().message << endl;
+ return NDBT_FAILED;
+ }
return NDBT_OK;
}
@@ -1164,6 +841,7 @@ struct receivedEvent {
};
int XXXXX = 0;
+
int
HugoTransactions::eventOperation(Ndb* pNdb, void* pstats,
int records) {
@@ -1234,7 +912,9 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats,
// set up the callbacks
g_info << function << "execute\n";
if (pOp->execute()) { // This starts changes to "start flowing"
- g_err << function << "operation execution failed\n";
+ g_err << function << "operation execution failed: \n";
+ g_err << pOp->getNdbError().code << " "
+ << pOp->getNdbError().message << endl;
return NDBT_FAILED;
}
@@ -1362,36 +1042,36 @@ HugoTransactions::eventOperation(Ndb* pNdb, void* pstats,
stats.n_duplicates += recDeleteEvent[i].count-1;
}
}
-
+
return NDBT_OK;
}
int
HugoTransactions::pkReadRecords(Ndb* pNdb,
int records,
- int batchsize,
+ int batch,
NdbOperation::LockMode lm){
int reads = 0;
int r = 0;
int retryAttempt = 0;
const int retryMax = 100;
int check, a;
- NdbOperation *pOp;
- if (batchsize == 0) {
- g_info << "ERROR: Argument batchsize == 0 in pkReadRecords(). Not allowed." << endl;
+ if (batch == 0) {
+ g_info << "ERROR: Argument batch == 0 in pkReadRecords(). Not allowed." << endl;
return NDBT_FAILED;
}
- allocRows(batchsize);
-
while (r < records){
+ if(r + batch > records)
+ batch = records - r;
+
if (retryAttempt >= retryMax){
g_info << "ERROR: has retried this operation " << retryAttempt
<< " times, failing!" << endl;
return NDBT_FAILED;
}
-
+
pTrans = pNdb->startTransaction();
if (pTrans == NULL) {
const NdbError err = pNdb->getNdbError();
@@ -1405,64 +1085,18 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
ERR(err);
return NDBT_FAILED;
}
-
- for(int b=0; (b<batchsize) && (r+b < records); b++){
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- rand_lock_mode:
- switch(lm){
- case NdbOperation::LM_Read:
- check = pOp->readTuple();
- break;
- case NdbOperation::LM_Exclusive:
- check = pOp->readTupleExclusive();
- break;
- case NdbOperation::LM_CommittedRead:
- check = pOp->dirtyRead();
- break;
- default:
- lm = (NdbOperation::LockMode)((rand() >> 16) & 3);
- goto rand_lock_mode;
- }
-
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- // Define primary keys
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pOp, a, r+b) != 0){
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
- }
-
- // Define attributes to read
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if((rows[b]->attributeStore(a) =
- pOp->getValue(tab.getColumn(a)->getName())) == 0) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
-
+ if(pkReadRecord(pNdb, r, batch, lm) != NDBT_OK)
+ {
+ ERR(pTrans->getNdbError());
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
}
-
+
check = pTrans->execute(Commit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
-
+
if (err.status == NdbError::TemporaryError){
ERR(err);
closeTransaction(pNdb);
@@ -1481,19 +1115,48 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
closeTransaction(pNdb);
return NDBT_FAILED;
}
- } else{
- for (int b=0; (b<batchsize) && (r+b<records); b++){
- if (calc.verifyRowValues(rows[b]) != 0){
+ } else {
+ if(pIndexScanOp)
+ {
+ int rows_found = 0;
+ while((check = pIndexScanOp->nextResult()) == 0)
+ {
+ rows_found++;
+ if (calc.verifyRowValues(rows[0]) != 0){
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
+ }
+ }
+ if(check != 1 || rows_found > batch)
+ {
closeTransaction(pNdb);
return NDBT_FAILED;
}
- reads++;
- r++;
+ else if(rows_found < batch)
+ {
+ if(batch == 1){
+ g_info << r << ": not found" << endl; abort(); }
+ else
+ g_info << "Found " << rows_found << " of "
+ << batch << " rows" << endl;
+ }
+ r += batch;
+ reads += rows_found;
+ }
+ else
+ {
+ for (int b=0; (b<batch) && (r+b<records); b++){
+ if (calc.verifyRowValues(rows[b]) != 0){
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
+ }
+ reads++;
+ r++;
+ }
}
}
-
+
closeTransaction(pNdb);
-
}
deallocRows();
g_info << reads << " records read" << endl;
@@ -1518,6 +1181,8 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
g_info << "|- Updating records (batch=" << batch << ")..." << endl;
while (r < records){
+ if(r + batch > records)
+ batch = records - r;
if (retryAttempt >= retryMax){
g_info << "ERROR: has retried this operation " << retryAttempt
@@ -1542,43 +1207,13 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(b = 0; b<batch && (r+b) < records; b++){
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->readTupleExclusive();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- // Define primary keys
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pOp, a, r+b) != 0){
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
- }
-
- // Define attributes to read
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if((rows[b]->attributeStore(a) =
- pOp->getValue(tab.getColumn(a)->getName())) == 0) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
+ if(pkReadRecord(pNdb, r, batch, NdbOperation::LM_Exclusive) != NDBT_OK)
+ {
+ ERR(pTrans->getNdbError());
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
}
-
+
check = pTrans->execute(NoCommit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
@@ -1594,52 +1229,62 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
closeTransaction(pNdb);
return NDBT_FAILED;
}
-
- for(b = 0; b<batch && (b+r)<records; b++){
- if (calc.verifyRowValues(rows[b]) != 0){
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- int updates = calc.getUpdatesValue(rows[b]) + 1;
-
- NdbOperation* pUpdOp;
- pUpdOp = pTrans->getNdbOperation(tab.getName());
- if (pUpdOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pUpdOp->updateTuple();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pUpdOp, a, r+b) != 0){
- ERR(pTrans->getNdbError());
+
+ if(pIndexScanOp)
+ {
+ int rows_found = 0;
+ while((check = pIndexScanOp->nextResult(true)) == 0)
+ {
+ do {
+
+ if (calc.verifyRowValues(rows[0]) != 0){
closeTransaction(pNdb);
return NDBT_FAILED;
}
- }
- }
-
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == false){
- if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){
+
+ int updates = calc.getUpdatesValue(rows[0]) + 1;
+
+ if(pkUpdateRecord(pNdb, r+rows_found, 1, updates) != NDBT_OK)
+ {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
return NDBT_FAILED;
}
+ rows_found++;
+ } while((check = pIndexScanOp->nextResult(false)) == 0);
+
+ if(check != 2)
+ break;
+ if((check = pTrans->execute(NoCommit)) != 0)
+ break;
+ }
+ if(check != 1 || rows_found != batch)
+ {
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
+ }
+ }
+ else
+ {
+ for(b = 0; b<batch && (b+r)<records; b++)
+ {
+ if (calc.verifyRowValues(rows[b]) != 0)
+ {
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
+ }
+
+ int updates = calc.getUpdatesValue(rows[b]) + 1;
+
+ if(pkUpdateRecord(pNdb, r+b, 1, updates) != NDBT_OK)
+ {
+ ERR(pTrans->getNdbError());
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
}
}
+ check = pTrans->execute(Commit);
}
-
- check = pTrans->execute(Commit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
@@ -1658,13 +1303,12 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
else{
updated += batch;
}
-
-
+
closeTransaction(pNdb);
-
+
r += batch; // Read next record
}
-
+
deallocRows();
g_info << "|- " << updated << " records updated" << endl;
return NDBT_OK;
@@ -1713,7 +1357,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
if( check == -1 ) {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
- return NDBT_FAILED;
+ return NDBT_FAILED;
}
// Define primary keys
@@ -1861,6 +1505,8 @@ HugoTransactions::pkDelRecords(Ndb* pNdb,
g_info << "|- Deleting records..." << endl;
while (r < records){
+ if(r + batch > records)
+ batch = records - r;
if (retryAttempt >= retryMax){
g_info << "ERROR: has retried this operation " << retryAttempt
@@ -1885,30 +1531,13 @@ HugoTransactions::pkDelRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->deleteTuple();
- if( check == -1 ) {
+ if(pkDeleteRecord(pNdb, r, batch) != NDBT_OK)
+ {
ERR(pTrans->getNdbError());
closeTransaction(pNdb);
return NDBT_FAILED;
}
- // Define primary keys
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pOp, a, r) != 0){
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
- }
check = pTrans->execute(Commit);
if( check == -1) {
const NdbError err = pTrans->getNdbError();
@@ -1946,11 +1575,11 @@ HugoTransactions::pkDelRecords(Ndb* pNdb,
}
}
else {
- deleted++;
+ deleted += batch;
}
closeTransaction(pNdb);
-
- r++; // Read next record
+
+ r += batch; // Read next record
}
@@ -1972,6 +1601,7 @@ HugoTransactions::lockRecords(Ndb* pNdb,
const int retryMax = 100;
int check, a, b;
NdbOperation *pOp;
+ NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
// Calculate how many records to lock in each batch
if (percentToLock <= 0)
@@ -1984,6 +1614,9 @@ HugoTransactions::lockRecords(Ndb* pNdb,
allocRows(lockBatch);
while (r < records){
+ if(r + lockBatch > records)
+ lockBatch = records - r;
+
g_info << "|- Locking " << lockBatch << " records..." << endl;
if (retryAttempt >= retryMax){
@@ -2006,42 +1639,13 @@ HugoTransactions::lockRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(b = 0; (b<lockBatch) && (r+b < records); b++){
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- check = pOp->readTupleExclusive();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
-
- // Define primary keys
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey() == true){
- if(equalForAttr(pOp, a, r+b) != 0){
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
- }
-
- // Define attributes to read
- for(a = 0; a<tab.getNoOfColumns(); a++){
- if((rows[b]->attributeStore(a) =
- pOp->getValue(tab.getColumn(a)->getName())) == 0) {
- ERR(pTrans->getNdbError());
- closeTransaction(pNdb);
- return NDBT_FAILED;
- }
- }
+ if(pkReadRecord(pNdb, r, lockBatch, lm) != NDBT_OK)
+ {
+ ERR(pTrans->getNdbError());
+ closeTransaction(pNdb);
+ return NDBT_FAILED;
}
+
// NoCommit lockTime times with 100 millis interval
int sleepInterval = 50;
int lockCount = lockTime / sleepInterval;
@@ -2099,8 +1703,7 @@ HugoTransactions::lockRecords(Ndb* pNdb,
}
closeTransaction(pNdb);
-
-
+
}
deallocRows();
g_info << "|- Record locking completed" << endl;
@@ -2111,7 +1714,7 @@ int
HugoTransactions::indexReadRecords(Ndb* pNdb,
const char * idxName,
int records,
- int batchsize){
+ int batch){
int reads = 0;
int r = 0;
int retryAttempt = 0;
@@ -2119,24 +1722,23 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
int check, a;
NdbOperation *pOp;
NdbIndexScanOperation *sOp;
- NdbResultSet * rs;
const NdbDictionary::Index* pIndex
= pNdb->getDictionary()->getIndex(idxName, tab.getName());
const bool ordered = (pIndex->getType()==NdbDictionary::Index::OrderedIndex);
- if (batchsize == 0) {
- g_info << "ERROR: Argument batchsize == 0 in indexReadRecords(). "
+ if (batch == 0) {
+ g_info << "ERROR: Argument batch == 0 in indexReadRecords(). "
<< "Not allowed." << endl;
return NDBT_FAILED;
}
if (ordered) {
- batchsize = 1;
+ batch = 1;
}
- allocRows(batchsize);
+ allocRows(batch);
while (r < records){
if (retryAttempt >= retryMax){
@@ -2159,7 +1761,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(int b=0; (b<batchsize) && (r+b < records); b++){
+ for(int b=0; (b<batch) && (r+b < records); b++){
if(!ordered){
pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
if (pOp == NULL) {
@@ -2175,9 +1777,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
closeTransaction(pNdb);
return NDBT_FAILED;
}
-
- check = 0;
- rs = sOp->readTuples();
+ check = sOp->readTuples();
}
if( check == -1 ) {
@@ -2209,7 +1809,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
}
check = pTrans->execute(Commit);
- check = (check == -1 ? -1 : !ordered ? check : rs->nextResult(true));
+ check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true));
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
@@ -2232,7 +1832,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
} else{
- for (int b=0; (b<batchsize) && (r+b<records); b++){
+ for (int b=0; (b<batch) && (r+b<records); b++){
if (calc.verifyRowValues(rows[b]) != 0){
closeTransaction(pNdb);
return NDBT_FAILED;
@@ -2240,7 +1840,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
reads++;
r++;
}
- if(ordered && rs->nextResult(true) == 0){
+ if(ordered && sOp->nextResult(true) == 0){
ndbout << "Error when comparing records "
<< " - index op next_result to many" << endl;
closeTransaction(pNdb);
@@ -2260,7 +1860,7 @@ int
HugoTransactions::indexUpdateRecords(Ndb* pNdb,
const char * idxName,
int records,
- int batchsize){
+ int batch){
int updated = 0;
int r = 0;
@@ -2269,17 +1869,16 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
int check, a, b;
NdbOperation *pOp;
NdbScanOperation * sOp;
- NdbResultSet * rs;
const NdbDictionary::Index* pIndex
= pNdb->getDictionary()->getIndex(idxName, tab.getName());
const bool ordered = (pIndex->getType()==NdbDictionary::Index::OrderedIndex);
if (ordered){
- batchsize = 1;
+ batch = 1;
}
- allocRows(batchsize);
+ allocRows(batch);
while (r < records){
if (retryAttempt >= retryMax){
@@ -2302,7 +1901,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- for(b = 0; b<batchsize && (b+r)<records; b++){
+ for(b = 0; b<batch && (b+r)<records; b++){
if(!ordered){
pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
if (pOp == NULL) {
@@ -2326,7 +1925,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
}
check = 0;
- rs = sOp->readTuplesExclusive();
+ sOp->readTuplesExclusive();
}
// Define primary keys
@@ -2352,7 +1951,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
}
check = pTrans->execute(NoCommit);
- check = (check == -1 ? -1 : !ordered ? check : rs->nextResult(true));
+ check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true));
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
ERR(err);
@@ -2367,12 +1966,12 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
}
if(ordered && check != 0){
- g_err << "Row: " << r << " not found!!" << endl;
+ g_err << check << " - Row: " << r << " not found!!" << endl;
closeTransaction(pNdb);
return NDBT_FAILED;
}
- for(b = 0; b<batchsize && (b+r)<records; b++){
+ for(b = 0; b<batch && (b+r)<records; b++){
if (calc.verifyRowValues(rows[b]) != 0){
closeTransaction(pNdb);
return NDBT_FAILED;
@@ -2385,7 +1984,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
pUpdOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
check = (pUpdOp == 0 ? -1 : pUpdOp->updateTuple());
} else {
- pUpdOp = rs->updateTuple();
+ pUpdOp = sOp->updateCurrentTuple();
}
if (pUpdOp == NULL) {
@@ -2437,12 +2036,12 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
ndbout << "r = " << r << endl;
return NDBT_FAILED;
} else {
- updated += batchsize;
+ updated += batch;
}
closeTransaction(pNdb);
- r+= batchsize; // Read next record
+ r+= batch; // Read next record
}
g_info << "|- " << updated << " records updated" << endl;
diff --git a/ndb/test/src/NDBT_ResultRow.cpp b/ndb/test/src/NDBT_ResultRow.cpp
index 11554b4a9b3..ab8d7b07ea1 100644
--- a/ndb/test/src/NDBT_ResultRow.cpp
+++ b/ndb/test/src/NDBT_ResultRow.cpp
@@ -84,7 +84,7 @@ NDBT_ResultRow::header (NdbOut & out) const {
return out;
}
-BaseString NDBT_ResultRow::c_str() {
+BaseString NDBT_ResultRow::c_str() const {
BaseString str;
@@ -137,3 +137,10 @@ NDBT_ResultRow::clone () const {
return row;
}
+
+bool
+NDBT_ResultRow::operator==(const NDBT_ResultRow& other) const
+{
+ // quick and dirty
+ return c_str() == other.c_str();
+}
diff --git a/ndb/test/src/NDBT_Tables.cpp b/ndb/test/src/NDBT_Tables.cpp
index ff6db3e892c..5a5fecd85c1 100644
--- a/ndb/test/src/NDBT_Tables.cpp
+++ b/ndb/test/src/NDBT_Tables.cpp
@@ -48,7 +48,7 @@ const
NDBT_Attribute T2Attribs[] = {
NDBT_Attribute("KOL1", NdbDictionary::Column::Bigunsigned, 1, true),
NDBT_Attribute("KOL2", NdbDictionary::Column::Unsigned),
- NDBT_Attribute("KOL3", NdbDictionary::Column::Unsigned),
+ NDBT_Attribute("KOL3", NdbDictionary::Column::Bit, 23),
NDBT_Attribute("KOL4", NdbDictionary::Column::Unsigned,
1, false, true), // Nullable
NDBT_Attribute("KOL5", NdbDictionary::Column::Unsigned)
@@ -820,21 +820,25 @@ NDBT_Tables::createAllTables(Ndb* pNdb){
int
NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp,
- bool existsOk){
+ bool existsOk, NDBT_CreateTableHook f){
const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name);
if (tab == NULL){
ndbout << "Could not create table " << _name
<< ", it doesn't exist in list of tables "\
- "that NDBT_Tables can create!" << endl;
+ "that NDBT_Tables can create!" << endl;
return NDBT_WRONGARGS;
}
-
+
int r = 0;
do {
NdbDictionary::Table tmpTab(* tab);
tmpTab.setStoredTable(_temp ? 0 : 1);
-
+ if(f != 0 && f(pNdb, tmpTab, 0))
+ {
+ ndbout << "Failed to create table" << endl;
+ return NDBT_FAILED;
+ }
r = pNdb->getDictionary()->createTable(tmpTab);
if(r == -1){
if(!existsOk){
@@ -883,6 +887,11 @@ NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp,
}
}
}
+ if(f != 0 && f(pNdb, tmpTab, 1))
+ {
+ ndbout << "Failed to create table" << endl;
+ return NDBT_FAILED;
+ }
} while(false);
return r;
diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp
index 6355c21c997..8fecf56531f 100644
--- a/ndb/test/src/NDBT_Test.cpp
+++ b/ndb/test/src/NDBT_Test.cpp
@@ -15,6 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <my_pthread.h>
#include "NDBT.hpp"
#include "NDBT_Test.hpp"
@@ -26,7 +27,9 @@
// No verbose outxput
-NDBT_Context::NDBT_Context(){
+NDBT_Context::NDBT_Context(Ndb_cluster_connection& con)
+ : m_cluster_connection(con)
+{
tab = NULL;
suite = NULL;
testcase = NULL;
@@ -248,7 +251,7 @@ int NDBT_Step::execute(NDBT_Context* ctx) {
g_info << " |- " << name << " started [" << ctx->suite->getDate() << "]"
<< endl;
- result = setUp();
+ result = setUp(ctx->m_cluster_connection);
if (result != NDBT_OK){
return result;
}
@@ -288,10 +291,10 @@ NDBT_NdbApiStep::NDBT_NdbApiStep(NDBT_TestCase* ptest,
int
-NDBT_NdbApiStep::setUp(){
- ndb = new Ndb( "TEST_DB" );
+NDBT_NdbApiStep::setUp(Ndb_cluster_connection& con){
+ ndb = new Ndb(&con, "TEST_DB" );
ndb->init(1024);
-
+
int result = ndb->waitUntilReady(300); // 5 minutes
if (result != 0){
g_err << name << ": Ndb was not ready" << endl;
@@ -624,8 +627,7 @@ int NDBT_TestCase::execute(NDBT_Context* ctx){
<< endl;
}
return res;
-};
-
+}
void NDBT_TestCase::startTimer(NDBT_Context* ctx){
timer.doStart();
@@ -757,14 +759,15 @@ int NDBT_TestSuite::addTest(NDBT_TestCase* pTest){
return 0;
}
-int NDBT_TestSuite::executeAll(const char* _testname){
+int NDBT_TestSuite::executeAll(Ndb_cluster_connection& con,
+ const char* _testname){
if(tests.size() == 0)
return NDBT_FAILED;
- Ndb ndb("TEST_DB");
+ Ndb ndb(&con, "TEST_DB");
ndb.init(1024);
- int result = ndb.waitUntilReady(300); // 5 minutes
+ int result = ndb.waitUntilReady(500); // 5 minutes
if (result != 0){
g_err << name <<": Ndb was not ready" << endl;
return NDBT_FAILED;
@@ -777,18 +780,19 @@ int NDBT_TestSuite::executeAll(const char* _testname){
for (int t=0; t < NDBT_Tables::getNumTables(); t++){
const NdbDictionary::Table* ptab = NDBT_Tables::getTable(t);
ndbout << "|- " << ptab->getName() << endl;
- execute(&ndb, ptab, _testname);
+ execute(con, &ndb, ptab, _testname);
}
testSuiteTimer.doStop();
return reportAllTables(_testname);
}
int
-NDBT_TestSuite::executeOne(const char* _tabname, const char* _testname){
+NDBT_TestSuite::executeOne(Ndb_cluster_connection& con,
+ const char* _tabname, const char* _testname){
if(tests.size() == 0)
return NDBT_FAILED;
- Ndb ndb("TEST_DB");
+ Ndb ndb(&con, "TEST_DB");
ndb.init(1024);
int result = ndb.waitUntilReady(300); // 5 minutes
@@ -805,7 +809,7 @@ NDBT_TestSuite::executeOne(const char* _tabname, const char* _testname){
ndbout << "|- " << ptab->getName() << endl;
- execute(&ndb, ptab, _testname);
+ execute(con, &ndb, ptab, _testname);
if (numTestsFail > 0){
return NDBT_FAILED;
@@ -814,7 +818,8 @@ NDBT_TestSuite::executeOne(const char* _tabname, const char* _testname){
}
}
-void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab,
+void NDBT_TestSuite::execute(Ndb_cluster_connection& con,
+ Ndb* ndb, const NdbDictionary::Table* pTab,
const char* _testname){
int result;
@@ -856,14 +861,14 @@ void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab,
pTab2 = pTab;
}
- ctx = new NDBT_Context();
+ ctx = new NDBT_Context(con);
ctx->setTab(pTab2);
ctx->setNumRecords(records);
ctx->setNumLoops(loops);
if(remote_mgm != NULL)
ctx->setRemoteMgm(remote_mgm);
ctx->setSuite(this);
-
+
result = tests[t]->execute(ctx);
tests[t]->saveTestResult(pTab, result);
if (result != NDBT_OK)
@@ -1035,14 +1040,19 @@ int NDBT_TestSuite::execute(int argc, const char** argv){
loops = _loops;
timer = _timer;
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1))
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
if(optind == argc){
// No table specified
- res = executeAll(_testname);
+ res = executeAll(con, _testname);
} else {
testSuiteTimer.doStart();
- Ndb ndb("TEST_DB"); ndb.init();
for(int i = optind; i<argc; i++){
- executeOne(argv[i], _testname);
+ executeOne(con, argv[i], _testname);
}
testSuiteTimer.doStop();
res = report(_testname);
diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp
index 1e56db83c11..9f65fe6b3bc 100644
--- a/ndb/test/src/NdbBackup.cpp
+++ b/ndb/test/src/NdbBackup.cpp
@@ -345,7 +345,7 @@ NdbBackup::NF(NdbRestarter& _restarter, int *NFDuringBackup_codes, const int sz,
}
return NDBT_OK;
-};
+}
int
FailS_codes[] = {
diff --git a/ndb/test/src/NdbRestarts.cpp b/ndb/test/src/NdbRestarts.cpp
index 607e48c4126..c0f31af84ce 100644
--- a/ndb/test/src/NdbRestarts.cpp
+++ b/ndb/test/src/NdbRestarts.cpp
@@ -213,7 +213,7 @@ NdbRestarts::NdbRestart::NdbRestart(const char* _name,
m_restartFunc = _func;
m_numRequiredNodes = _requiredNodes;
// m_arg1 = arg1;
-};
+}
int NdbRestarts::getNumRestarts(){
@@ -367,7 +367,7 @@ int restartRandomNodeGraceful(NdbRestarter& _restarter,
"Could not restart node "<<nodeId);
return NDBT_OK;
-};
+}
int restartRandomNodeAbort(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -382,7 +382,7 @@ int restartRandomNodeAbort(NdbRestarter& _restarter,
"Could not restart node "<<nodeId);
return NDBT_OK;
-};
+}
int restartRandomNodeError(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -397,7 +397,7 @@ int restartRandomNodeError(NdbRestarter& _restarter,
"Could not restart node "<<nodeId);
return NDBT_OK;
-};
+}
int restartMasterNodeError(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -410,7 +410,7 @@ int restartMasterNodeError(NdbRestarter& _restarter,
"Could not restart node "<<nodeId);
return NDBT_OK;
-};
+}
int restartRandomNodeInitial(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -425,7 +425,7 @@ int restartRandomNodeInitial(NdbRestarter& _restarter,
"Could not restart node "<<nodeId);
return NDBT_OK;
-};
+}
int twoNodeFailure(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -453,7 +453,7 @@ int twoNodeFailure(NdbRestarter& _restarter,
"Could not restart node "<< nodeId);
return NDBT_OK;
-};
+}
int twoMasterNodeFailure(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -478,7 +478,7 @@ int twoMasterNodeFailure(NdbRestarter& _restarter,
"Could not restart node "<< nodeId);
return NDBT_OK;
-};
+}
int get50PercentOfNodes(NdbRestarter& restarter,
int * _nodes){
@@ -519,7 +519,7 @@ int fiftyPercentFail(NdbRestarter& _restarter,
"Could not start all nodes");
return NDBT_OK;
-};
+}
int restartAllNodesGracfeul(NdbRestarter& _restarter,
@@ -533,7 +533,7 @@ int restartAllNodesGracfeul(NdbRestarter& _restarter,
return NDBT_OK;
-};
+}
int restartAllNodesAbort(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -545,7 +545,7 @@ int restartAllNodesAbort(NdbRestarter& _restarter,
"Could not restart all nodes");
return NDBT_OK;
-};
+}
int restartAllNodesError9999(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -557,7 +557,7 @@ int restartAllNodesError9999(NdbRestarter& _restarter,
"Could not restart all nodes ");
return NDBT_OK;
-};
+}
int fiftyPercentStopAndWait(NdbRestarter& _restarter,
const NdbRestarts::NdbRestart* _restart){
@@ -590,7 +590,7 @@ int fiftyPercentStopAndWait(NdbRestarter& _restarter,
g_info << _restart->m_name << endl;
return NDBT_OK;
-};
+}
int
NFDuringNR_codes[] = {
@@ -713,7 +713,7 @@ int restartNFDuringNR(NdbRestarter& _restarter,
}
return NDBT_OK;
-};
+}
int
NRDuringLCP_Master_codes[] = {
@@ -864,7 +864,7 @@ int stopOnError(NdbRestarter& _restarter,
} while (false);
return NDBT_OK;
-};
+}
int getRandomNodeId(NdbRestarter& _restarter) {
myRandom48Init(NdbTick_CurrentMillisecond());
diff --git a/ndb/test/src/NdbSchemaOp.cpp b/ndb/test/src/NdbSchemaOp.cpp
index a296094ea9d..4281ceb02c8 100644
--- a/ndb/test/src/NdbSchemaOp.cpp
+++ b/ndb/test/src/NdbSchemaOp.cpp
@@ -113,7 +113,7 @@ NdbSchemaOp::createAttribute( const char* anAttrName,
AttrType anAttrType,
StorageMode aStorageMode,
bool nullable,
- StorageAttributeType aStorageAttr,
+ int aStorageAttr,
int aDistributionKeyFlag,
int aDistributionGroupFlag,
int aDistributionGroupNoOfBits,
@@ -158,7 +158,6 @@ NdbSchemaOp::createAttribute( const char* anAttrName,
col.setPrimaryKey(false);
col.setDistributionKey(aDistributionKeyFlag);
- col.setDistributionGroup(aDistributionGroupFlag,aDistributionGroupNoOfBits);
col.setAutoIncrement(aAutoIncrement);
col.setDefaultValue(aDefaultValue != 0 ? aDefaultValue : "");
diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp
index 92073143d34..31c323045ed 100644
--- a/ndb/test/src/UtilTransactions.cpp
+++ b/ndb/test/src/UtilTransactions.cpp
@@ -20,13 +20,20 @@
#define VERBOSE 0
-UtilTransactions::UtilTransactions(const NdbDictionary::Table& _tab):
- tab(_tab){
+UtilTransactions::UtilTransactions(const NdbDictionary::Table& _tab,
+ const NdbDictionary::Index* _idx):
+ tab(_tab), idx(_idx), pTrans(0)
+{
m_defaultClearMethod = 3;
}
-UtilTransactions::UtilTransactions(Ndb* ndb, const char * name) :
- tab(* ndb->getDictionary()->getTable(name)){
+UtilTransactions::UtilTransactions(Ndb* ndb,
+ const char * name,
+ const char * index) :
+ tab(* ndb->getDictionary()->getTable(name)),
+ idx(index ? ndb->getDictionary()->getIndex(index, name) : 0),
+ pTrans(0)
+{
m_defaultClearMethod = 3;
}
@@ -51,313 +58,29 @@ UtilTransactions::clearTable(Ndb* pNdb,
int
UtilTransactions::clearTable1(Ndb* pNdb,
int records,
- int parallelism){
-#if 1
+ int parallelism)
+{
return clearTable3(pNdb, records, 1);
-#else
- // Scan all records exclusive and delete
- // them one by one
- 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->startTransaction();
- if (pTrans == NULL) {
- NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- RETURN_FAIL(err);
- }
-
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- NdbError err = pNdb->getNdbError();
- ERR(err);
- pNdb->closeTransaction(pTrans);
- RETURN_FAIL(err);
- }
-
- check = pOp->openScanExclusive(parallelism);
- if( check == -1 ) {
- NdbError err = pNdb->getNdbError();
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- RETURN_FAIL(err);
- }
-
- check = pOp->interpret_exit_ok();
- if( check == -1 ) {
- NdbError err = pNdb->getNdbError();
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- RETURN_FAIL(err);
- }
-#if 0
- // It's not necessary to read and PK's
- // Information about the PK's are sent in
- // KEYINFO20 signals anyway and used by takeOverScan
-
- // Read the primary keys from this table
- for(int a=0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey()){
- if(pOp->getValue(tab.getColumn(a)->getName()) == NULL){
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- RETURN_FAIL(err);
- }
- }
- }
-#endif
-
- check = pTrans->executeScan();
- if( check == -1 ) {
- NdbError err = pTrans->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- pNdb->closeTransaction(pTrans);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- pNdb->closeTransaction(pTrans);
- RETURN_FAIL(err);
- }
-
- int eof;
- int rows = 0;
-
- eof = pTrans->nextScanResult();
- while(eof == 0){
- rows++;
-
- int res = takeOverAndDeleteRecord(pNdb, pOp);
- if(res == RESTART_SCAN){
- eof = -2;
- continue;
- }
-
- if (res != 0){
- NdbError err = pNdb->getNdbError(res);
- pNdb->closeTransaction(pTrans);
- RETURN_FAIL(err);
- }
-
- eof = pTrans->nextScanResult();
- }
-
- if (eof == -1) {
- const NdbError err = pTrans->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- pNdb->closeTransaction(pTrans);
- NdbSleep_MilliSleep(50);
- // If error = 488 there should be no limit on number of retry attempts
- if (err.code != 488)
- retryAttempt++;
- continue;
- }
- ERR(err);
- pNdb->closeTransaction(pTrans);
- RETURN_FAIL(err);
- }
-
- if(eof == -2){
- pNdb->closeTransaction(pTrans);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
-
- pNdb->closeTransaction(pTrans);
-
- g_info << rows << " deleted" << endl;
-
- return NDBT_OK;
- }
- return NDBT_FAILED;
-#endif
}
int
UtilTransactions::clearTable2(Ndb* pNdb,
- int records,
- int parallelism){
-#if 1
+ int records,
+ int parallelism)
+{
return clearTable3(pNdb, records, parallelism);
-#else
- // Scan all records exclusive and delete
- // them one by one
- int retryAttempt = 0;
- const int retryMax = 10;
- int deletedRows = 0;
- 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->startTransaction();
- if (pTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
- ERR(err);
- return NDBT_FAILED;
- }
-
- pOp = pTrans->getNdbOperation(tab.getName());
- if (pOp == NULL) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- check = pOp->openScanExclusive(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;
- }
-#if 0
- // It's not necessary to read any PK's
- // Information about the PK's are sent in
- // KEYINFO20 signals anyway and used by takeOverScan
-
- // Read the primary keys from this table
- for(int a=0; a<tab.getNoOfColumns(); a++){
- if (tab.getColumn(a)->getPrimaryKey()){
- if(pOp->getValue(tab.getColumn(a)->getName()) == NULL){
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return -1;
- }
- }
- }
-#endif
-
- check = pTrans->executeScan();
- if( check == -1 ) {
- ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- int eof;
- NdbConnection* pDelTrans;
-
- while((eof = pTrans->nextScanResult(true)) == 0){
- pDelTrans = pNdb->startTransaction();
- if (pDelTrans == NULL) {
- const NdbError err = pNdb->getNdbError();
-#if 0
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- NdbSleep_MilliSleep(50);
- retryAttempt++;
- continue;
- }
-#endif
- ERR(err);
- pNdb->closeTransaction(pDelTrans);
- return NDBT_FAILED;
- }
- do {
- deletedRows++;
- if (addRowToDelete(pNdb, pDelTrans, pOp) != 0){
- pNdb->closeTransaction(pDelTrans);
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- } while((eof = pTrans->nextScanResult(false)) == 0);
-
- check = pDelTrans->execute(Commit);
- if( check == -1 ) {
- const NdbError err = pDelTrans->getNdbError();
- ERR(err);
- pNdb->closeTransaction(pDelTrans);
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
- pNdb->closeTransaction(pDelTrans);
-
- }
- if (eof == -1) {
- const NdbError err = pTrans->getNdbError();
-
- if (err.status == NdbError::TemporaryError){
- ERR(err);
- pNdb->closeTransaction(pTrans);
- NdbSleep_MilliSleep(50);
- // If error = 488 there should be no limit on number of retry attempts
- if (err.code != 488)
- retryAttempt++;
- continue;
- }
- ERR(err);
- pNdb->closeTransaction(pTrans);
- return NDBT_FAILED;
- }
-
- pNdb->closeTransaction(pTrans);
-
- g_info << deletedRows << " rows deleted" << endl;
-
- return NDBT_OK;
- }
- return NDBT_FAILED;
-#endif
}
int
UtilTransactions::clearTable3(Ndb* pNdb,
- int records,
- int parallelism){
+ int records,
+ 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;
@@ -380,13 +103,13 @@ UtilTransactions::clearTable3(Ndb* pNdb,
}
goto failed;
}
-
- pOp = pTrans->getNdbScanOperation(tab.getName());
+
+ pOp = getScanOperation(pTrans);
if (pOp == NULL) {
err = pTrans->getNdbError();
if(err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
par = 1;
goto restart;
@@ -394,8 +117,7 @@ UtilTransactions::clearTable3(Ndb* pNdb,
goto failed;
}
- NdbResultSet * rs = pOp->readTuplesExclusive(par);
- if( rs == 0 ) {
+ if( pOp->readTuplesExclusive(par) ) {
err = pTrans->getNdbError();
goto failed;
}
@@ -404,20 +126,20 @@ UtilTransactions::clearTable3(Ndb* pNdb,
err = pTrans->getNdbError();
if(err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
continue;
}
goto failed;
}
- while((check = rs->nextResult(true)) == 0){
+ while((check = pOp->nextResult(true)) == 0){
do {
- if (rs->deleteTuple() != 0){
+ if (pOp->deleteCurrentTuple() != 0){
goto failed;
}
deletedRows++;
- } while((check = rs->nextResult(false)) == 0);
+ } while((check = pOp->nextResult(false)) == 0);
if(check != -1){
check = pTrans->execute(Commit);
@@ -428,7 +150,7 @@ UtilTransactions::clearTable3(Ndb* pNdb,
if(check == -1){
if(err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
par = 1;
goto restart;
@@ -440,20 +162,20 @@ UtilTransactions::clearTable3(Ndb* pNdb,
err = pTrans->getNdbError();
if(err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
par = 1;
goto restart;
}
goto failed;
}
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_OK;
}
return NDBT_FAILED;
failed:
- if(pTrans != 0) pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
ERR(err);
return (err.code != 0 ? err.code : NDBT_FAILED);
}
@@ -468,7 +190,6 @@ UtilTransactions::copyTableData(Ndb* pNdb,
int insertedRows = 0;
int parallelism = 240;
int check;
- NdbConnection *pTrans;
NdbScanOperation *pOp;
NDBT_ResultRow row(tab);
@@ -498,22 +219,20 @@ UtilTransactions::copyTableData(Ndb* pNdb,
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- NdbResultSet* rs = pOp->readTuples(NdbScanOperation::LM_Read,
- parallelism);
- if( check == -1 ) {
+ if( pOp->readTuples(NdbScanOperation::LM_Read, parallelism) ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pOp->interpret_exit_ok();
if( check == -1 ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -522,7 +241,7 @@ UtilTransactions::copyTableData(Ndb* pNdb,
if ((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@@ -530,26 +249,26 @@ UtilTransactions::copyTableData(Ndb* pNdb,
check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
int eof;
- while((eof = rs->nextResult(true)) == 0){
+ while((eof = pOp->nextResult(true)) == 0){
do {
insertedRows++;
if (addRowToInsert(pNdb, pTrans, row, destName) != 0){
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- } while((eof = rs->nextResult(false)) == 0);
+ } while((eof = pOp->nextResult(false)) == 0);
check = pTrans->execute(Commit);
pTrans->restart();
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@@ -558,7 +277,7 @@ UtilTransactions::copyTableData(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
// If error = 488 there should be no limit on number of retry attempts
if (err.code != 488)
@@ -566,11 +285,11 @@ UtilTransactions::copyTableData(Ndb* pNdb,
continue;
}
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
g_info << insertedRows << " rows copied" << endl;
@@ -628,7 +347,6 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
int retryAttempt = 0;
const int retryMax = 100;
int check;
- NdbConnection *pTrans;
NdbScanOperation *pOp;
NDBT_ResultRow row(tab);
@@ -654,10 +372,10 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbScanOperation(tab.getName());
+ pOp = getScanOperation(pTrans);
if (pOp == NULL) {
const NdbError err = pNdb->getNdbError();
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
if (err.status == NdbError::TemporaryError){
ERR(err);
@@ -669,17 +387,16 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples(lm, 0, parallelism);
- if( rs == 0 ) {
+ if( pOp->readTuples(lm, 0, parallelism) ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pOp->interpret_exit_ok();
if( check == -1 ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -691,7 +408,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
if ((row.attributeStore(attrib_list[a]) =
pOp->getValue(tab.getColumn(attrib_list[a])->getName())) == 0) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@@ -704,13 +421,13 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -718,7 +435,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
int rows = 0;
- while((eof = rs->nextResult()) == 0){
+ while((eof = pOp->nextResult()) == 0){
rows++;
// Call callback for each record returned
@@ -730,17 +447,17 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
g_info << rows << " rows have been read" << endl;
if (records != 0 && rows != records){
g_info << "Check expected number of records failed" << endl
@@ -766,37 +483,26 @@ UtilTransactions::selectCount(Ndb* pNdb,
int check;
NdbScanOperation *pOp;
+ if(!pTrans)
+ pTrans = pNdb->startTransaction();
+
while (true){
+
if (retryAttempt >= retryMax){
g_info << "ERROR: has retried this operation " << retryAttempt
<< " times, failing!" << endl;
return NDBT_FAILED;
}
- if(!pTrans)
- pTrans = pNdb->startTransaction();
-
- if(!pTrans)
- {
- const NdbError err = pNdb->getNdbError();
-
- if (err.status == NdbError::TemporaryError)
- continue;
- return NDBT_FAILED;
- }
-
- pOp = pTrans->getNdbScanOperation(tab.getName());
+ pOp = getScanOperation(pTrans);
if (pOp == NULL) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- pTrans = 0;
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples(lm);
- if( rs == 0) {
+ if( pOp->readTuples(lm) ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- pTrans = 0;
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -809,8 +515,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
check = pOp->interpret_exit_ok();
if( check == -1 ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- pTrans = 0;
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@@ -819,8 +524,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
- pTrans = 0;
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -828,27 +532,24 @@ UtilTransactions::selectCount(Ndb* pNdb,
int rows = 0;
- while((eof = rs->nextResult()) == 0){
+ while((eof = pOp->nextResult()) == 0){
rows++;
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
if (err.status == NdbError::TemporaryError){
- pNdb->closeTransaction(pTrans);
- pTrans = 0;
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
- pNdb->closeTransaction(pTrans);
- pTrans = 0;
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- pNdb->closeTransaction(pTrans);
- pTrans = 0;
+ closeTransaction(pNdb);
if (count_rows != NULL){
*count_rows = rows;
@@ -922,14 +623,13 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
int retryAttempt = 0;
const int retryMax = 100;
int check;
- NdbConnection *pTrans;
NdbScanOperation *pOp;
NDBT_ResultRow row(tab);
parallelism = 1;
while (true){
-
+restart:
if (retryAttempt >= retryMax){
g_info << "ERROR: has retried this operation " << retryAttempt
<< " times, failing!" << endl;
@@ -953,7 +653,7 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
const NdbError err = pNdb->getNdbError();
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
ERR(err);
if (err.status == NdbError::TemporaryError){
@@ -964,23 +664,23 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
return NDBT_FAILED;
}
- NdbResultSet* rs;
+ int rs;
if(transactional){
rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism);
} else {
rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallelism);
}
- if( rs == 0 ) {
+ if( rs != 0 ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pOp->interpret_exit_ok();
if( check == -1 ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -989,7 +689,7 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
if ((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@@ -1000,13 +700,13 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -1014,17 +714,32 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
int rows = 0;
- while((eof = rs->nextResult()) == 0){
+ while((eof = pOp->nextResult()) == 0){
rows++;
// ndbout << row.c_str().c_str() << endl;
-
if (readRowFromTableAndIndex(pNdb,
pTrans,
pIndex,
row) != NDBT_OK){
- pNdb->closeTransaction(pTrans);
+
+ while((eof= pOp->nextResult(false)) == 0);
+ if(eof == 2)
+ eof = pOp->nextResult(true); // this should give -1
+ if(eof == -1)
+ {
+ const NdbError err = pTrans->getNdbError();
+
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ closeTransaction(pNdb);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ goto restart;
+ }
+ }
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@@ -1033,18 +748,17 @@ UtilTransactions::scanAndCompareUniqueIndex(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
- rows--;
continue;
}
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_OK;
}
@@ -1062,7 +776,6 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
const int retryMax = 100;
int check, a;
NdbConnection *pTrans1=NULL;
- NdbResultSet *cursor= NULL;
NdbOperation *pOp;
int return_code= NDBT_FAILED;
@@ -1112,7 +825,6 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
check = pOp->readTuple();
if( check == -1 ) {
ERR(pTrans1->getNdbError());
- pNdb->closeTransaction(pTrans1);
goto close_all;
}
@@ -1190,7 +902,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
if (pIndexOp) {
not_ok = pIndexOp->readTuple() == -1;
} else {
- not_ok = (cursor= pScanOp->readTuples()) == 0;
+ not_ok = pScanOp->readTuples();
}
if( not_ok ) {
@@ -1244,7 +956,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
#if VERBOSE
printf("\n");
#endif
-
+ scanTrans->refresh();
check = pTrans1->execute(Commit);
if( check == -1 ) {
const NdbError err = pTrans1->getNdbError();
@@ -1267,7 +979,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
*/
if(!null_found){
if (pScanOp) {
- if (cursor->nextResult() != 0){
+ if (pScanOp->nextResult() != 0){
const NdbError err = pTrans1->getNdbError();
ERR(err);
ndbout << "Error when comparing records - index op next_result missing" << endl;
@@ -1282,7 +994,7 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
goto close_all;
}
if (pScanOp) {
- if (cursor->nextResult() == 0){
+ if (pScanOp->nextResult() == 0){
ndbout << "Error when comparing records - index op next_result to many" << endl;
ndbout << "row: " << row.c_str().c_str() << endl;
goto close_all;
@@ -1294,8 +1006,6 @@ UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
}
close_all:
- if (cursor)
- cursor->close();
if (pTrans1)
pNdb->closeTransaction(pTrans1);
@@ -1311,10 +1021,8 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
int retryAttempt = 0;
const int retryMax = 100;
int check;
- NdbConnection *pTrans;
NdbScanOperation *pOp;
NdbIndexScanOperation * iop = 0;
- NdbResultSet* cursor= 0;
NDBT_ResultRow scanRow(tab);
NDBT_ResultRow pkRow(tab);
@@ -1349,23 +1057,20 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- NdbResultSet*
- rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism);
-
- if( rs == 0 ) {
+ if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pOp->interpret_exit_ok();
if( check == -1 ) {
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -1380,19 +1085,19 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
int eof;
int rows = 0;
- while(check == 0 && (eof = rs->nextResult()) == 0){
+ while(check == 0 && (eof = pOp->nextResult()) == 0){
rows++;
bool null_found= false;
@@ -1417,10 +1122,11 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
if(!iop && (iop= pTrans->getNdbIndexScanOperation(indexName,
tab.getName())))
{
- cursor= iop->readTuples(NdbScanOperation::LM_CommittedRead,
- parallelism);
+ if(iop->readTuples(NdbScanOperation::LM_CommittedRead,
+ parallelism))
+ goto error;
iop->interpret_exit_ok();
- if(!cursor || get_values(iop, indexRow))
+ if(get_values(iop, indexRow))
goto error;
}
else if(!iop || iop->reset_bounds())
@@ -1440,17 +1146,17 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
g_err << "Error when comapring records" << endl;
g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl;
g_err << " pkRow: \n" << pkRow.c_str().c_str() << endl;
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
if(!null_found)
{
- if((res= cursor->nextResult()) != 0){
+ if((res= iop->nextResult()) != 0){
g_err << "Failed to find row using index: " << res << endl;
ERR(pTrans->getNdbError());
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
@@ -1458,14 +1164,14 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
g_err << "Error when comapring records" << endl;
g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl;
g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl;
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- if(cursor->nextResult() == 0){
+ if(iop->nextResult() == 0){
g_err << "Found extra row!!" << endl;
g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl;
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@@ -1478,18 +1184,18 @@ UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
iop = 0;
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
rows--;
continue;
}
ERR(err);
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_FAILED;
}
- pNdb->closeTransaction(pTrans);
+ closeTransaction(pNdb);
return NDBT_OK;
}
@@ -1537,3 +1243,218 @@ UtilTransactions::equal(const NdbDictionary::Table* pTable,
}
return 0;
}
+
+NdbScanOperation*
+UtilTransactions::getScanOperation(NdbConnection* pTrans)
+{
+ return (NdbScanOperation*)
+ getOperation(pTrans, NdbOperation::OpenScanRequest);
+}
+
+NdbOperation*
+UtilTransactions::getOperation(NdbConnection* pTrans,
+ NdbOperation::OperationType type)
+{
+ switch(type){
+ case NdbOperation::ReadRequest:
+ case NdbOperation::ReadExclusive:
+ if(idx)
+ {
+ switch(idx->getType()){
+ case NdbDictionary::Index::UniqueHashIndex:
+ return pTrans->getNdbIndexOperation(idx->getName(), tab.getName());
+ case NdbDictionary::Index::OrderedIndex:
+ return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName());
+ }
+ }
+ case NdbOperation::InsertRequest:
+ case NdbOperation::WriteRequest:
+ return pTrans->getNdbOperation(tab.getName());
+ case NdbOperation::UpdateRequest:
+ case NdbOperation::DeleteRequest:
+ if(idx)
+ {
+ switch(idx->getType()){
+ case NdbDictionary::Index::UniqueHashIndex:
+ return pTrans->getNdbIndexOperation(idx->getName(), tab.getName());
+ }
+ }
+ return pTrans->getNdbOperation(tab.getName());
+ case NdbOperation::OpenScanRequest:
+ if(idx)
+ {
+ switch(idx->getType()){
+ case NdbDictionary::Index::OrderedIndex:
+ return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName());
+ }
+ }
+ return pTrans->getNdbScanOperation(tab.getName());
+ case NdbOperation::OpenRangeScanRequest:
+ if(idx)
+ {
+ switch(idx->getType()){
+ case NdbDictionary::Index::OrderedIndex:
+ return pTrans->getNdbIndexScanOperation(idx->getName(), tab.getName());
+ }
+ }
+ return 0;
+ }
+}
+
+#include <HugoOperations.hpp>
+
+int
+UtilTransactions::closeTransaction(Ndb* pNdb)
+{
+ if (pTrans != NULL){
+ pNdb->closeTransaction(pTrans);
+ pTrans = NULL;
+ }
+ return 0;
+}
+
+int
+UtilTransactions::compare(Ndb* pNdb, const char* tab_name2, int flags){
+
+
+ NdbError err;
+ int return_code= -1, row_count= 0;
+ int retryAttempt = 0, retryMax = 10;
+
+ HugoCalculator calc(tab);
+ NDBT_ResultRow row(tab);
+ const NdbDictionary::Table* tmp= pNdb->getDictionary()->getTable(tab_name2);
+ if(tmp == 0)
+ {
+ g_err << "Unable to lookup table: " << tab_name2
+ << endl << pNdb->getDictionary()->getNdbError() << endl;
+ return -1;
+ }
+ const NdbDictionary::Table& tab2= *tmp;
+
+ HugoOperations cmp(tab2);
+ UtilTransactions count(tab2);
+
+ while (true){
+
+ if (retryAttempt++ >= retryMax){
+ g_info << "ERROR: has retried this operation " << retryAttempt
+ << " times, failing!" << endl;
+ return -1;
+ }
+
+ NdbScanOperation *pOp= 0;
+ pTrans = pNdb->startTransaction();
+ if (pTrans == NULL) {
+ err = pNdb->getNdbError();
+ goto error;
+ }
+
+ pOp= pTrans->getNdbScanOperation(tab.getName());
+ if (pOp == NULL) {
+ ERR(err= pTrans->getNdbError());
+ goto error;
+ }
+
+ if( pOp->readTuples(NdbScanOperation::LM_Read) ) {
+ ERR(err= pTrans->getNdbError());
+ goto error;
+ }
+
+ if( pOp->interpret_exit_ok() == -1 ) {
+ ERR(err= pTrans->getNdbError());
+ goto error;
+ }
+
+ // Read all attributes
+ {
+ for (int a = 0; a < tab.getNoOfColumns(); a++){
+ if ((row.attributeStore(a) =
+ pOp->getValue(tab.getColumn(a)->getName())) == 0) {
+ ERR(err= pTrans->getNdbError());
+ goto error;
+ }
+ }
+ }
+
+ if( pTrans->execute(NoCommit) == -1 ) {
+ ERR(err= pTrans->getNdbError());
+ goto error;
+ }
+
+ {
+ int eof;
+ while((eof = pOp->nextResult(true)) == 0)
+ {
+ do {
+ row_count++;
+ if(cmp.startTransaction(pNdb) != NDBT_OK)
+ {
+ ERR(err= pNdb->getNdbError());
+ goto error;
+ }
+ int rowNo= calc.getIdValue(&row);
+ if(cmp.pkReadRecord(pNdb, rowNo, 1) != NDBT_OK)
+ {
+ ERR(err= cmp.getTransaction()->getNdbError());
+ goto error;
+ }
+ if(cmp.execute_Commit(pNdb) != NDBT_OK)
+ {
+ ERR(err= cmp.getTransaction()->getNdbError());
+ goto error;
+ }
+ if(row != cmp.get_row(0))
+ {
+ g_err << "COMPARE FAILED" << endl;
+ g_err << row << endl;
+ g_err << cmp.get_row(0) << endl;
+ return_code= 1;
+ goto close;
+ }
+ retryAttempt= 0;
+ cmp.closeTransaction(pNdb);
+ } while((eof = pOp->nextResult(false)) == 0);
+ }
+ if (eof == -1)
+ {
+ err = pTrans->getNdbError();
+ goto error;
+ }
+ }
+
+ pTrans->close(); pTrans= 0;
+
+ g_info << row_count << " rows compared" << endl;
+ {
+ int row_count2;
+ if(count.selectCount(pNdb, 0, &row_count2) != NDBT_OK)
+ {
+ g_err << "Failed to count rows in tab_name2" << endl;
+ return -1;
+ }
+
+ g_info << row_count2 << " rows in tab_name2" << endl;
+ return (row_count == row_count2 ? 0 : 1);
+ }
+error:
+ if(err.status == NdbError::TemporaryError)
+ {
+ NdbSleep_MilliSleep(50);
+ if(pTrans != 0)
+ {
+ pTrans->close();
+ pTrans= 0;
+ }
+ if(cmp.getTransaction())
+ cmp.closeTransaction(pNdb);
+ continue;
+ }
+ break;
+ }
+
+close:
+ if(pTrans != 0) pTrans->close();
+
+ return return_code;
+}
diff --git a/ndb/test/tools/Makefile.am b/ndb/test/tools/Makefile.am
index a6a013bb263..873136e254d 100644
--- a/ndb/test/tools/Makefile.am
+++ b/ndb/test/tools/Makefile.am
@@ -1,9 +1,8 @@
-ndbtest_PROGRAMS = hugoCalculator hugoLoad hugoFill hugoLockRecords hugoPkDelete hugoPkRead hugoPkReadRecord hugoPkUpdate hugoScanRead hugoScanUpdate restart verify_index copy_tab create_index ndb_cpcc
+ndbtest_PROGRAMS = 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
diff --git a/ndb/test/tools/copy_tab.cpp b/ndb/test/tools/copy_tab.cpp
index 30141acaa78..97370b170ef 100644
--- a/ndb/test/tools/copy_tab.cpp
+++ b/ndb/test/tools/copy_tab.cpp
@@ -56,9 +56,12 @@ int main(int argc, const char** argv){
_tabname = argv[optind];
_to_tabname = argv[optind+1];
- if (_connectstr)
- Ndb::setConnectString(_connectstr);
- Ndb MyNdb(_dbname);
+ Ndb_cluster_connection con(_connectstr);
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con,_dbname);
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
return NDBT_ProgramExit(NDBT_FAILED);
diff --git a/ndb/test/tools/create_index.cpp b/ndb/test/tools/create_index.cpp
index 6e4c5377f4a..9f9c26aa0da 100644
--- a/ndb/test/tools/create_index.cpp
+++ b/ndb/test/tools/create_index.cpp
@@ -53,8 +53,13 @@ main(int argc, const char** argv){
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
- Ndb MyNdb(_dbname);
+ Ndb MyNdb(&con, _dbname);
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
return NDBT_ProgramExit(NDBT_FAILED);
diff --git a/ndb/test/tools/hugoFill.cpp b/ndb/test/tools/hugoFill.cpp
index 6253bd1bb12..6408b2987f9 100644
--- a/ndb/test/tools/hugoFill.cpp
+++ b/ndb/test/tools/hugoFill.cpp
@@ -51,7 +51,12 @@ int main(int argc, const char** argv){
_tabname = argv[optind];
// Connect to Ndb
- Ndb MyNdb( "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/tools/hugoLoad.cpp b/ndb/test/tools/hugoLoad.cpp
index 3a0bba07df3..1a229169650 100644
--- a/ndb/test/tools/hugoLoad.cpp
+++ b/ndb/test/tools/hugoLoad.cpp
@@ -56,7 +56,12 @@ int main(int argc, const char** argv){
_tabname = argv[optind];
// Connect to Ndb
- Ndb MyNdb( db ? db : "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb( &con, db ? db : "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/tools/hugoLockRecords.cpp b/ndb/test/tools/hugoLockRecords.cpp
index 629408d401d..c0d0b9f9c5a 100644
--- a/ndb/test/tools/hugoLockRecords.cpp
+++ b/ndb/test/tools/hugoLockRecords.cpp
@@ -59,7 +59,12 @@ int main(int argc, const char** argv){
_tabname = argv[optind];
// Connect to Ndb
- Ndb MyNdb( "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/tools/hugoPkDelete.cpp b/ndb/test/tools/hugoPkDelete.cpp
index 78a90ebcb46..84e7ded0add 100644
--- a/ndb/test/tools/hugoPkDelete.cpp
+++ b/ndb/test/tools/hugoPkDelete.cpp
@@ -55,7 +55,12 @@ int main(int argc, const char** argv){
_tabname = argv[optind];
// Connect to Ndb
- Ndb MyNdb( "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/tools/hugoPkRead.cpp b/ndb/test/tools/hugoPkRead.cpp
index cf08b137e8e..e3702dc5ca1 100644
--- a/ndb/test/tools/hugoPkRead.cpp
+++ b/ndb/test/tools/hugoPkRead.cpp
@@ -60,7 +60,12 @@ int main(int argc, const char** argv){
// Connect to Ndb
- Ndb MyNdb( "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/tools/hugoPkReadRecord.cpp b/ndb/test/tools/hugoPkReadRecord.cpp
index 38b7cae2bf4..c60a994c7d4 100644
--- a/ndb/test/tools/hugoPkReadRecord.cpp
+++ b/ndb/test/tools/hugoPkReadRecord.cpp
@@ -62,7 +62,12 @@ int main(int argc, const char** argv)
<< "Row: " << _row << ", PrimaryKey: " << _primaryKey
<< endl;
- Ndb* ndb = new Ndb("TEST_DB");
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb* ndb = new Ndb(&con, "TEST_DB");
if (ndb->init() == 0 && ndb->waitUntilReady(30) == 0)
{
NdbConnection* conn = ndb->startTransaction();
diff --git a/ndb/test/tools/hugoPkUpdate.cpp b/ndb/test/tools/hugoPkUpdate.cpp
index ccbbccfc523..7d46ae95c29 100644
--- a/ndb/test/tools/hugoPkUpdate.cpp
+++ b/ndb/test/tools/hugoPkUpdate.cpp
@@ -58,7 +58,12 @@ int main(int argc, const char** argv){
_tabname = argv[optind];
// Connect to Ndb
- Ndb MyNdb( db ? db : "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb( &con, db ? db : "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/tools/hugoScanRead.cpp b/ndb/test/tools/hugoScanRead.cpp
index 4cd428f44c6..a345bb88d0e 100644
--- a/ndb/test/tools/hugoScanRead.cpp
+++ b/ndb/test/tools/hugoScanRead.cpp
@@ -62,7 +62,12 @@ int main(int argc, const char** argv){
_tabname = argv[optind];
// Connect to Ndb
- Ndb MyNdb( db ? db : "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb( &con, db ? db : "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
@@ -86,8 +91,7 @@ int main(int argc, const char** argv){
if(!pIdx)
ndbout << " Index " << argv[optind+1] << " not found" << endl;
else
- if(pIdx->getType() != NdbDictionary::Index::UniqueOrderedIndex &&
- pIdx->getType() != NdbDictionary::Index::OrderedIndex)
+ if(pIdx->getType() != NdbDictionary::Index::OrderedIndex)
{
ndbout << " Index " << argv[optind+1] << " is not scannable" << endl;
pIdx = 0;
diff --git a/ndb/test/tools/hugoScanUpdate.cpp b/ndb/test/tools/hugoScanUpdate.cpp
index 8fe84779c6b..6960fa44b96 100644
--- a/ndb/test/tools/hugoScanUpdate.cpp
+++ b/ndb/test/tools/hugoScanUpdate.cpp
@@ -59,7 +59,12 @@ int main(int argc, const char** argv){
_tabname = argv[optind];
// Connect to Ndb
- Ndb MyNdb( db ? db : "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb( &con, db ? db : "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/test/tools/verify_index.cpp b/ndb/test/tools/verify_index.cpp
index 6c8e304e1a1..acc97af883b 100644
--- a/ndb/test/tools/verify_index.cpp
+++ b/ndb/test/tools/verify_index.cpp
@@ -53,7 +53,12 @@ int main(int argc, const char** argv){
_indexname = argv[optind+1];
// Connect to Ndb
- Ndb MyNdb( "TEST_DB" );
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, "TEST_DB" );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
diff --git a/ndb/tools/Makefile.am b/ndb/tools/Makefile.am
index 795441380a8..17b71f7e33c 100644
--- a/ndb/tools/Makefile.am
+++ b/ndb/tools/Makefile.am
@@ -30,12 +30,14 @@ ndb_restore_SOURCES = restore/restore_main.cpp \
restore/consumer.cpp \
restore/consumer_restore.cpp \
restore/consumer_printer.cpp \
- restore/Restore.cpp $(tools_common_sources)
+ restore/Restore.cpp \
+ ../test/src/NDBT_ResultRow.cpp $(tools_common_sources)
ndb_config_SOURCES = ndb_config.cpp \
../src/mgmsrv/Config.cpp \
../src/mgmsrv/ConfigInfo.cpp \
../src/mgmsrv/InitConfigFileParser.cpp
+
ndb_config_CXXFLAGS = -I$(top_srcdir)/ndb/src/mgmapi \
-I$(top_srcdir)/ndb/src/mgmsrv \
-I$(top_srcdir)/ndb/include/mgmcommon \
diff --git a/ndb/tools/delete_all.cpp b/ndb/tools/delete_all.cpp
index 21e0c2ac089..2c395a67900 100644
--- a/ndb/tools/delete_all.cpp
+++ b/ndb/tools/delete_all.cpp
@@ -44,35 +44,37 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_delete_all.trace");
-}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_delete_all.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
- Ndb::setConnectString(opt_connect_str);
- // Connect to Ndb
- Ndb MyNdb(_dbname);
+ Ndb_cluster_connection con(opt_connect_str);
+ if(con.connect(12, 5, 1) != 0)
+ {
+ ndbout << "Unable to connect to management server." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ if (con.wait_until_ready(30,0) < 0)
+ {
+ ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, _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 = 0; i<argc; i++){
@@ -99,7 +101,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism)
const int retryMax = 10;
int deletedRows = 0;
int check;
- NdbConnection *pTrans;
+ NdbTransaction *pTrans;
NdbScanOperation *pOp;
NdbError err;
@@ -128,12 +130,11 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism)
goto failed;
}
- NdbResultSet * rs = pOp->readTuplesExclusive(par);
- if( rs == 0 ) {
+ if( pOp->readTuples(NdbOperation::LM_Exclusive,par) ) {
goto failed;
}
- if(pTrans->execute(NoCommit) != 0){
+ if(pTrans->execute(NdbTransaction::NoCommit) != 0){
err = pTrans->getNdbError();
if(err.status == NdbError::TemporaryError){
ERR(err);
@@ -144,16 +145,16 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism)
goto failed;
}
- while((check = rs->nextResult(true)) == 0){
+ while((check = pOp->nextResult(true)) == 0){
do {
- if (rs->deleteTuple() != 0){
+ if (pOp->deleteCurrentTuple() != 0){
goto failed;
}
deletedRows++;
- } while((check = rs->nextResult(false)) == 0);
+ } while((check = pOp->nextResult(false)) == 0);
if(check != -1){
- check = pTrans->execute(Commit);
+ check = pTrans->execute(NdbTransaction::Commit);
pTrans->restart();
}
diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp
index aac47c9042c..be0f6942db5 100644
--- a/ndb/tools/desc.cpp
+++ b/ndb/tools/desc.cpp
@@ -44,35 +44,38 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_desc.trace");
-}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_desc.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
- Ndb::setConnectString(opt_connect_str);
-
- Ndb* pMyNdb;
- pMyNdb = new Ndb(_dbname);
- pMyNdb->init();
-
- ndbout << "Waiting...";
- while (pMyNdb->waitUntilReady() != 0) {
- ndbout << "...";
+ Ndb_cluster_connection con(opt_connect_str);
+ if(con.connect(12, 5, 1) != 0)
+ {
+ ndbout << "Unable to connect to management server." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ if (con.wait_until_ready(30,0) < 0)
+ {
+ ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
}
- ndbout << endl;
- NdbDictionary::Dictionary * dict = pMyNdb->getDictionary();
+ Ndb MyNdb(&con, _dbname);
+ if(MyNdb.init() != 0){
+ ERR(MyNdb.getNdbError());
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ const NdbDictionary::Dictionary * dict= MyNdb.getDictionary();
for (int i = 0; i < argc; i++) {
NDBT_Table* pTab = (NDBT_Table*)dict->getTable(argv[i]);
if (pTab != 0){
@@ -112,6 +115,5 @@ int main(int argc, char** argv){
ndbout << argv[i] << ": " << dict->getNdbError() << endl;
}
- delete pMyNdb;
return NDBT_ProgramExit(NDBT_OK);
}
diff --git a/ndb/tools/drop_index.cpp b/ndb/tools/drop_index.cpp
index 69c8345fdb6..24116f22784 100644
--- a/ndb/tools/drop_index.cpp
+++ b/ndb/tools/drop_index.cpp
@@ -41,37 +41,40 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_drop_index.trace");
-}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ "d:t:O,/tmp/ndb_drop_index.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
if (argc < 1) {
usage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Ndb::setConnectString(opt_connect_str);
- // Connect to Ndb
- Ndb MyNdb(_dbname);
+ Ndb_cluster_connection con(opt_connect_str);
+ if(con.connect(12, 5, 1) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ if (con.wait_until_ready(30,3) < 0)
+ {
+ ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Ndb MyNdb(&con, _dbname );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
return NDBT_ProgramExit(NDBT_FAILED);
}
- while(MyNdb.waitUntilReady() != 0)
- ndbout << "Waiting for ndb to become ready..." << endl;
-
int res = 0;
for(int i = 0; i+1<argc; i += 2){
ndbout << "Dropping index " << argv[i] << "/" << argv[i+1] << "...";
diff --git a/ndb/tools/drop_tab.cpp b/ndb/tools/drop_tab.cpp
index 091db5cc4b7..991e1505486 100644
--- a/ndb/tools/drop_tab.cpp
+++ b/ndb/tools/drop_tab.cpp
@@ -41,36 +41,41 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_drop_table.trace");
-}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ "d:t:O,/tmp/ndb_drop_table.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
if (argc < 1) {
usage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Ndb::setConnectString(opt_connect_str);
- Ndb MyNdb(_dbname);
+ Ndb_cluster_connection con(opt_connect_str);
+ if(con.connect(12, 5, 1) != 0)
+ {
+ ndbout << "Unable to connect to management server." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ if (con.wait_until_ready(30,3) < 0)
+ {
+ ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+
+ Ndb MyNdb(&con, _dbname );
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
return NDBT_ProgramExit(NDBT_FAILED);
}
- while(MyNdb.waitUntilReady() != 0)
- ndbout << "Waiting for ndb to become ready..." << endl;
-
int res = 0;
for(int i = 0; i<argc; i++){
ndbout << "Dropping table " << argv[i] << "...";
diff --git a/ndb/tools/listTables.cpp b/ndb/tools/listTables.cpp
index eb0c1c53c2d..fa078f7d351 100644
--- a/ndb/tools/listTables.cpp
+++ b/ndb/tools/listTables.cpp
@@ -29,7 +29,7 @@
static Ndb_cluster_connection *ndb_cluster_connection= 0;
static Ndb* ndb = 0;
-static NdbDictionary::Dictionary* dic = 0;
+static const NdbDictionary::Dictionary * dic = 0;
static int _unqualified = 0;
static void
@@ -199,13 +199,6 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_show_tables.trace");
-}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
@@ -213,22 +206,29 @@ int main(int argc, char** argv){
const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_show_tables.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
_tabname = argv[0];
ndb_cluster_connection = new Ndb_cluster_connection(opt_connect_str);
if (ndb_cluster_connection->connect(12,5,1))
- fatal("unable to connect");
+ fatal("Unable to connect to management server.");
+ if (ndb_cluster_connection->wait_until_ready(30,0) < 0)
+ fatal("Cluster nodes not ready in 30 seconds.");
+
ndb = new Ndb(ndb_cluster_connection, _dbname);
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);
}
+ delete ndb;
+ delete ndb_cluster_connection;
return NDBT_ProgramExit(NDBT_OK);
}
diff --git a/ndb/tools/ndb_test_platform.cpp b/ndb/tools/ndb_test_platform.cpp
index 72dd146dacd..88f21b31d58 100644
--- a/ndb/tools/ndb_test_platform.cpp
+++ b/ndb/tools/ndb_test_platform.cpp
@@ -33,14 +33,14 @@ int test_snprintf(const char * fmt, int buf_sz, int result)
if(ret < 0)
{
printf("BaseString::snprint returns %d with size=%d and strlen(fmt)=%d\n",
- ret, buf_sz, strlen(fmt));
+ ret, buf_sz, (int) strlen(fmt));
return -1;
}
if(ret+1 == buf_sz)
{
printf("BaseString::snprint truncates returns %d with size=%d and strlen(fmt)=%d\n",
- ret, buf_sz, strlen(fmt));
+ ret, buf_sz, (int) strlen(fmt));
return -1;
}
@@ -87,7 +87,7 @@ main(void)
if (sizeof(UintPtr) != sizeof(Uint32*))
{
printf("sizeof(UintPtr)=%d != sizeof(Uint32*)=%d\n",
- sizeof(UintPtr), sizeof(Uint32*));
+ (int) sizeof(UintPtr), (int) sizeof(Uint32*));
return -1;
}
diff --git a/ndb/tools/restore/Restore.cpp b/ndb/tools/restore/Restore.cpp
index 26bc08c63a9..60fbf7f8ceb 100644
--- a/ndb/tools/restore/Restore.cpp
+++ b/ndb/tools/restore/Restore.cpp
@@ -646,7 +646,7 @@ bool RestoreDataIterator::readFragmentHeader(int & ret)
}
info << "_____________________________________________________" << endl
- << "Restoring data in table: " << m_currentTable->getTableName()
+ << "Processing data in table: " << m_currentTable->getTableName()
<< "(" << Header.TableId << ") fragment "
<< Header.FragmentNo << endl;
@@ -925,19 +925,12 @@ operator<<(NdbOut& ndbout, const LogEntry& logE)
return ndbout;
}
+#include <NDBT.hpp>
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() << ": "
- << (Uint32) desc->m_column->getType();
- ndbout << " key: " << (Uint32) desc->m_column->getPrimaryKey();
- ndbout << " array: " << desc->arraySize;
- ndbout << " size: " << desc->size << endl;
- } // for
+
+ ndbout << (* (NDBT_Table*)table.m_dictTable) << endl;
return ndbout;
}
diff --git a/ndb/tools/restore/consumer.cpp b/ndb/tools/restore/consumer.cpp
index ecbdbbf8f4e..b130c4998d5 100644
--- a/ndb/tools/restore/consumer.cpp
+++ b/ndb/tools/restore/consumer.cpp
@@ -45,9 +45,11 @@ BackupConsumer::create_table_string(const TableS & table,
pos += sprintf(buf+pos, "%s", "float");
break;
case NdbDictionary::Column::Olddecimal:
+ case NdbDictionary::Column::Decimal:
pos += sprintf(buf+pos, "%s", "decimal");
break;
case NdbDictionary::Column::Olddecimalunsigned:
+ case NdbDictionary::Column::Decimalunsigned:
pos += sprintf(buf+pos, "%s", "decimal unsigned");
break;
case NdbDictionary::Column::Char:
diff --git a/ndb/tools/restore/consumer_printer.hpp b/ndb/tools/restore/consumer_printer.hpp
index 7cbc924e364..e47bc56f874 100644
--- a/ndb/tools/restore/consumer_printer.hpp
+++ b/ndb/tools/restore/consumer_printer.hpp
@@ -29,6 +29,8 @@ public:
m_print_log = false;
m_print_data = false;
m_print_meta = false;
+ m_logCount = 0;
+ m_dataCount = 0;
}
virtual bool table(const TableS &);
diff --git a/ndb/tools/restore/consumer_restore.cpp b/ndb/tools/restore/consumer_restore.cpp
index 70ea7460d78..5786bdac697 100644
--- a/ndb/tools/restore/consumer_restore.cpp
+++ b/ndb/tools/restore/consumer_restore.cpp
@@ -24,8 +24,9 @@ extern FilteredNdbOut err;
extern FilteredNdbOut info;
extern FilteredNdbOut debug;
-static void callback(int, NdbConnection*, void*);
+static void callback(int, NdbTransaction*, void*);
+extern const char * g_connect_string;
bool
BackupRestore::init()
{
@@ -34,7 +35,13 @@ BackupRestore::init()
if (!m_restore && !m_restore_meta)
return true;
- m_ndb = new Ndb();
+ m_cluster_connection = new Ndb_cluster_connection(g_connect_string);
+ if(m_cluster_connection->connect(12, 5, 1) != 0)
+ {
+ return -1;
+ }
+
+ m_ndb = new Ndb(m_cluster_connection);
if (m_ndb == NULL)
return false;
@@ -80,6 +87,12 @@ void BackupRestore::release()
delete [] m_callback;
m_callback= 0;
}
+
+ if (m_cluster_connection)
+ {
+ delete m_cluster_connection;
+ m_cluster_connection= 0;
+ }
}
BackupRestore::~BackupRestore()
@@ -204,7 +217,7 @@ BackupRestore::endOfTables(){
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
for(size_t i = 0; i<m_indexes.size(); i++){
- const NdbTableImpl & indtab = NdbTableImpl::getImpl(* m_indexes[i]);
+ NdbTableImpl & indtab = NdbTableImpl::getImpl(* m_indexes[i]);
BaseString tmp(indtab.m_primaryTable.c_str());
Vector<BaseString> split;
@@ -364,7 +377,8 @@ void BackupRestore::tuple_a(restore_callback_t *cb)
}
// Prepare transaction (the transaction is NOT yet sent to NDB)
- cb->connection->executeAsynchPrepare(Commit, &callback, cb);
+ cb->connection->executeAsynchPrepare(NdbTransaction::Commit,
+ &callback, cb);
m_transactions++;
return;
}
@@ -494,7 +508,7 @@ BackupRestore::logEntry(const LogEntry & tup)
if (!m_restore)
return;
- NdbConnection * trans = m_ndb->startTransaction();
+ NdbTransaction * trans = m_ndb->startTransaction();
if (trans == NULL)
{
// Deep shit, TODO: handle the error
@@ -564,7 +578,7 @@ BackupRestore::logEntry(const LogEntry & tup)
} // if
}
- const int ret = trans->execute(Commit);
+ const int ret = trans->execute(NdbTransaction::Commit);
if (ret != 0)
{
// Both insert update and delete can fail during log running
@@ -612,12 +626,12 @@ BackupRestore::endOfLogEntrys()
*
* (This function must have three arguments:
* - The result of the transaction,
- * - The NdbConnection object, and
+ * - The NdbTransaction object, and
* - A pointer to an arbitrary object.)
*/
static void
-callback(int result, NdbConnection* trans, void* aObject)
+callback(int result, NdbTransaction* trans, void* aObject)
{
restore_callback_t *cb = (restore_callback_t *)aObject;
(cb->restore)->cback(result, cb);
@@ -631,7 +645,7 @@ BackupRestore::tuple(const TupleS & tup)
return;
while (1)
{
- NdbConnection * trans = m_ndb->startTransaction();
+ NdbTransaction * trans = m_ndb->startTransaction();
if (trans == NULL)
{
// Deep shit, TODO: handle the error
@@ -682,7 +696,7 @@ BackupRestore::tuple(const TupleS & tup)
else
op->setValue(i, dataPtr, length);
}
- int ret = trans->execute(Commit);
+ int ret = trans->execute(NdbTransaction::Commit);
if (ret != 0)
{
ndbout << "execute failed: ";
diff --git a/ndb/tools/restore/consumer_restore.hpp b/ndb/tools/restore/consumer_restore.hpp
index df219cd4412..1bf6d89a912 100644
--- a/ndb/tools/restore/consumer_restore.hpp
+++ b/ndb/tools/restore/consumer_restore.hpp
@@ -22,7 +22,7 @@
struct restore_callback_t {
class BackupRestore *restore;
class TupleS tup;
- class NdbConnection *connection;
+ class NdbTransaction *connection;
int retries;
int error_code;
restore_callback_t *next;
@@ -35,6 +35,7 @@ public:
BackupRestore(Uint32 parallelism=1)
{
m_ndb = 0;
+ m_cluster_connection = 0;
m_logCount = m_dataCount = 0;
m_restore = false;
m_restore_meta = false;
@@ -62,6 +63,7 @@ public:
virtual bool finalize_table(const TableS &);
void connectToMysql();
Ndb * m_ndb;
+ Ndb_cluster_connection * m_cluster_connection;
bool m_restore;
bool m_restore_meta;
Uint32 m_logCount;
diff --git a/ndb/tools/restore/consumer_restorem.cpp b/ndb/tools/restore/consumer_restorem.cpp
index 6a9ec07148a..56179a60ab0 100644
--- a/ndb/tools/restore/consumer_restorem.cpp
+++ b/ndb/tools/restore/consumer_restorem.cpp
@@ -21,8 +21,8 @@ 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);
+static bool asynchErrorHandler(NdbTransaction * trans, Ndb * ndb);
+static void callback(int result, NdbTransaction* trans, void* aObject);
bool
BackupRestore::init()
@@ -80,6 +80,7 @@ BackupRestore::init()
ndbout_c("Connect failed: %s", mysql_error(&mysql));
returnValue = false;
}
+ mysql.reconnect= 1;
ndbout << "Connected to MySQL!!!" <<endl;
}
@@ -370,7 +371,7 @@ BackupRestore::tuple(const TupleS & tup)
return;
while (1)
{
- NdbConnection * trans = m_ndb->startTransaction();
+ NdbTransaction * trans = m_ndb->startTransaction();
if (trans == NULL)
{
// Deep shit, TODO: handle the error
@@ -459,7 +460,7 @@ BackupRestore::logEntry(const LogEntry & tup)
if (!m_restore)
return;
- NdbConnection * trans = m_ndb->startTransaction();
+ NdbTransaction * trans = m_ndb->startTransaction();
if (trans == NULL)
{
// Deep shit, TODO: handle the error
@@ -550,7 +551,7 @@ BackupRestore::endOfLogEntrys()
*
******************************************/
static void restoreCallback(int result, // Result for transaction
- NdbConnection *object, // Transaction object
+ NdbTransaction *object, // Transaction object
void *anything) // Not used
{
static Uint32 counter = 0;
@@ -592,12 +593,12 @@ static void restoreCallback(int result, // Result for transaction
*
* (This function must have three arguments:
* - The result of the transaction,
- * - The NdbConnection object, and
+ * - The NdbTransaction object, and
* - A pointer to an arbitrary object.)
*/
static void
-callback(int result, NdbConnection* trans, void* aObject)
+callback(int result, NdbTransaction* trans, void* aObject)
{
restore_callback_t *cb = (restore_callback_t *)aObject;
(cb->restore)->cback(result, cb);
@@ -609,7 +610,7 @@ callback(int result, NdbConnection* trans, void* aObject)
* false if it is an error that generates an abort.
*/
static
-bool asynchErrorHandler(NdbConnection * trans, Ndb* ndb)
+bool asynchErrorHandler(NdbTransaction * trans, Ndb* ndb)
{
NdbError error = trans->getNdbError();
ndb->closeTransaction(trans);
diff --git a/ndb/tools/restore/restore_main.cpp b/ndb/tools/restore/restore_main.cpp
index d786dffe89e..af7c751fb67 100644
--- a/ndb/tools/restore/restore_main.cpp
+++ b/ndb/tools/restore/restore_main.cpp
@@ -110,8 +110,10 @@ static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
- ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_restore.trace");
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_restore.trace";
+#endif
+ ndb_std_get_one_option(optid, opt, argument);
switch (optid) {
case 'n':
if (ga_nodeId == 0)
@@ -227,6 +229,7 @@ free_data_callback()
g_consumers[i]->tuple_free();
}
+const char * g_connect_string = 0;
static void exitHandler(int code)
{
NDBT_ProgramExit(code);
@@ -246,7 +249,7 @@ main(int argc, char** argv)
exitHandler(NDBT_FAILED);
}
- Ndb::setConnectString(opt_connect_str);
+ g_connect_string = opt_connect_str;
/**
* we must always load meta data, even if we will only print it to stdout
@@ -324,7 +327,7 @@ main(int argc, char** argv)
if (ga_restore || ga_print)
{
- if (ga_restore)
+ if(_restore_data || _print_data)
{
RestoreDataIterator dataIter(metaData, &free_data_callback);
@@ -371,7 +374,10 @@ main(int argc, char** argv)
for (i= 0; i < g_consumers.size(); i++)
g_consumers[i]->endOfTuples();
+ }
+ if(_restore_data || _print_log)
+ {
RestoreLogIterator logIter(metaData);
if (!logIter.readHeader())
{
@@ -395,6 +401,10 @@ main(int argc, char** argv)
logIter.validateFooter(); //not implemented
for (i= 0; i < g_consumers.size(); i++)
g_consumers[i]->endOfLogEntrys();
+ }
+
+ if(_restore_data)
+ {
for(i = 0; i<metaData.getNoOfTables(); i++)
{
if (checkSysTable(metaData[i]->getTableName()))
diff --git a/ndb/tools/select_all.cpp b/ndb/tools/select_all.cpp
index 23fd2290349..baa18db1ebd 100644
--- a/ndb/tools/select_all.cpp
+++ b/ndb/tools/select_all.cpp
@@ -24,7 +24,6 @@
#include <NdbMain.h>
#include <NDBT.hpp>
#include <NdbSleep.h>
-#include <NdbScanFilter.hpp>
int scanReadRecords(Ndb*,
const NdbDictionary::Table*,
@@ -34,14 +33,15 @@ int scanReadRecords(Ndb*,
bool headers,
bool useHexFormat,
char delim,
- bool orderby);
+ bool orderby,
+ bool descending);
NDB_STD_OPTS_VARS;
static const char* _dbname = "TEST_DB";
static const char* _delimiter = "\t";
static int _unqualified, _header, _parallelism, _useHexFormat, _lock,
- _order;
+ _order, _descending;
static struct my_option my_long_options[] =
{
@@ -58,6 +58,9 @@ static struct my_option my_long_options[] =
{ "order", 'o', "Sort resultset according to index",
(gptr*) &_order, (gptr*) &_order, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "descending", 'z', "Sort descending (requires order flag)",
+ (gptr*) &_descending, (gptr*) &_descending, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ "header", 'h', "Print header",
(gptr*) &_header, (gptr*) &_header, 0,
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
@@ -82,13 +85,6 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_select_all.trace");
-}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
@@ -96,26 +92,35 @@ int main(int argc, char** argv){
load_defaults("my",load_default_groups,&argc,&argv);
const char* _tabname;
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_select_all.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
if ((_tabname = argv[0]) == 0) {
usage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Ndb::setConnectString(opt_connect_str);
- // Connect to Ndb
- Ndb MyNdb(_dbname);
+ Ndb_cluster_connection con(opt_connect_str);
+ if(con.connect(12, 5, 1) != 0)
+ {
+ ndbout << "Unable to connect to management server." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ if (con.wait_until_ready(30,0) < 0)
+ {
+ ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, _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
const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname);
const NdbDictionary::Index * pIdx = 0;
@@ -138,6 +143,11 @@ int main(int argc, char** argv){
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+ if (_descending && ! _order) {
+ ndbout << " Descending flag given without order flag" << endl;
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
if (scanReadRecords(&MyNdb,
pTab,
pIdx,
@@ -145,7 +155,7 @@ int main(int argc, char** argv){
_lock,
_header,
_useHexFormat,
- (char)*_delimiter, _order) != 0){
+ (char)*_delimiter, _order, _descending) != 0){
return NDBT_ProgramExit(NDBT_FAILED);
}
@@ -160,12 +170,12 @@ int scanReadRecords(Ndb* pNdb,
int _lock,
bool headers,
bool useHexFormat,
- char delimiter, bool order){
+ char delimiter, bool order, bool descending){
int retryAttempt = 0;
const int retryMax = 100;
int check;
- NdbConnection *pTrans;
+ NdbTransaction *pTrans;
NdbScanOperation *pOp;
NdbIndexScanOperation * pIOp= 0;
@@ -202,7 +212,7 @@ int scanReadRecords(Ndb* pNdb,
return -1;
}
- NdbResultSet * rs;
+ int rs;
switch(_lock + (3 * order)){
case 1:
rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallel);
@@ -212,20 +222,20 @@ int scanReadRecords(Ndb* pNdb,
break;
case 3:
rs = pIOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel,
- true);
+ true, descending);
break;
case 4:
- rs = pIOp->readTuples(NdbScanOperation::LM_Read, 0, parallel, true);
+ rs = pIOp->readTuples(NdbScanOperation::LM_Read, 0, parallel, true, descending);
break;
case 5:
- rs = pIOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel, true);
+ rs = pIOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel, true, descending);
break;
case 0:
default:
rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel);
break;
}
- if( rs == 0 ){
+ if( rs != 0 ){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return -1;
@@ -291,7 +301,7 @@ int scanReadRecords(Ndb* pNdb,
}
}
- check = pTrans->execute(NoCommit);
+ check = pTrans->execute(NdbTransaction::NoCommit);
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
@@ -311,7 +321,7 @@ int scanReadRecords(Ndb* pNdb,
int eof;
int rows = 0;
- eof = rs->nextResult();
+ eof = pOp->nextResult();
while(eof == 0){
rows++;
@@ -322,7 +332,7 @@ int scanReadRecords(Ndb* pNdb,
ndbout << (*row) << endl;
}
- eof = rs->nextResult();
+ eof = pOp->nextResult();
}
if (eof == -1) {
const NdbError err = pTrans->getNdbError();
diff --git a/ndb/tools/select_count.cpp b/ndb/tools/select_count.cpp
index a9a3e71da67..6fa3c77f15a 100644
--- a/ndb/tools/select_count.cpp
+++ b/ndb/tools/select_count.cpp
@@ -30,7 +30,7 @@ static int
select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
int parallelism,
int* count_rows,
- UtilTransactions::ScanLock lock);
+ NdbOperation::LockMode lock);
NDB_STD_OPTS_VARS;
@@ -60,39 +60,41 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_select_count.trace");
-}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_select_count.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
if (argc < 1) {
usage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- Ndb::setConnectString(opt_connect_str);
- // Connect to Ndb
- Ndb MyNdb(_dbname);
+ Ndb_cluster_connection con(opt_connect_str);
+ if(con.connect(12, 5, 1) != 0)
+ {
+ ndbout << "Unable to connect to management server." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ if (con.wait_until_ready(30,0) < 0)
+ {
+ ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ Ndb MyNdb(&con, _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 = 0; i<argc; i++){
// Check if table exists in db
const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]);
@@ -103,7 +105,7 @@ int main(int argc, char** argv){
int rows = 0;
if (select_count(&MyNdb, pTab, _parallelism, &rows,
- (UtilTransactions::ScanLock)_lock) != 0){
+ (NdbOperation::LockMode)_lock) != 0){
return NDBT_ProgramExit(NDBT_FAILED);
}
@@ -116,12 +118,12 @@ int
select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
int parallelism,
int* count_rows,
- UtilTransactions::ScanLock lock){
+ NdbOperation::LockMode lock){
int retryAttempt = 0;
const int retryMax = 100;
int check;
- NdbConnection *pTrans;
+ NdbTransaction *pTrans;
NdbScanOperation *pOp;
while (true){
@@ -151,8 +153,7 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Dirty);
- if( rs == 0 ) {
+ if( pOp->readTuples(NdbScanOperation::LM_Dirty) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
@@ -167,9 +168,10 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
}
Uint64 tmp;
+ Uint32 row_size;
pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&tmp);
-
- check = pTrans->execute(NoCommit);
+ pOp->getValue(NdbDictionary::Column::ROW_SIZE, (char*)&row_size);
+ check = pTrans->execute(NdbTransaction::NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -178,7 +180,7 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
Uint64 row_count = 0;
int eof;
- while((eof = rs->nextResult(true)) == 0){
+ while((eof = pOp->nextResult(true)) == 0){
row_count += tmp;
}
diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp
index cc6a21428c8..db90bd8bd90 100644
--- a/ndb/tools/waiter.cpp
+++ b/ndb/tools/waiter.cpp
@@ -60,24 +60,19 @@ static void usage()
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_drop_table.trace");
-}
-
int main(int argc, char** argv){
NDB_INIT(argv[0]);
const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
const char* _hostName = NULL;
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_waiter.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
- char buf[255];
_hostName = argv[0];
if (_hostName == 0)
diff --git a/netware/BUILD/compile-linux-tools b/netware/BUILD/compile-linux-tools
index 70f07be649e..c85fced5739 100755
--- a/netware/BUILD/compile-linux-tools
+++ b/netware/BUILD/compile-linux-tools
@@ -30,14 +30,16 @@ rm -f */*.linux
# build tools only
make clean all-local
+
+# Create mysql_version.h which was deleted my previous step
+./config.status include/mysql_version.h
+
(cd dbug; make libdbug.a)
(cd strings; make libmystrings.a)
(cd mysys; make libmysys.a)
(cd heap; make libheap.a)
(cd vio; make libvio.a)
(cd regex; make libregex.a)
-(cd isam; make libnisam.a)
-(cd merge; make libmerge.a)
(cd myisam; make libmyisam.a)
(cd myisammrg; make libmyisammrg.a)
(cd extra; make comp_err)
@@ -58,3 +60,5 @@ cp libmysql_r/conf_to_src libmysql_r/conf_to_src.linux
cp sql/gen_lex_hash sql/gen_lex_hash.linux
cp strings/conf_to_src strings/conf_to_src.linux
+# Delete mysql_version.h
+rm -f include/mysql_version.h
diff --git a/netware/BUILD/compile-netware-END b/netware/BUILD/compile-netware-END
index 2bd59f97114..60ef428b2a9 100755
--- a/netware/BUILD/compile-netware-END
+++ b/netware/BUILD/compile-netware-END
@@ -22,6 +22,11 @@ rm -rf Makefile.in.bk
# run auto tools
. $path/compile-AUTOTOOLS
+# For NetWare there is no comp_err but comp_err.linux
+sed -e "s/comp_err/comp_err.linux/g" extra/Makefile.am > extra/Makefile.am.$$
+sed -e "s/replace comp_err.linux/replace comp_err/g" extra/Makefile.am.$$ > extra/Makefile.am
+rm extra/Makefile.am.$$
+
# configure
./configure $base_configs $extra_configs
diff --git a/netware/BUILD/compile-netware-START b/netware/BUILD/compile-netware-START
index 7eef192a907..9918ead87c5 100755
--- a/netware/BUILD/compile-netware-START
+++ b/netware/BUILD/compile-netware-START
@@ -22,5 +22,7 @@ base_configs=" \
--enable-local-infile \
--with-extra-charsets=all \
--prefix=N:/mysql \
+ --without-mysqlmanager \
+ --without-man \
"
diff --git a/netware/BUILD/mwenv b/netware/BUILD/mwenv
index 0acfd3aaf8f..7f89a8faf7f 100755
--- a/netware/BUILD/mwenv
+++ b/netware/BUILD/mwenv
@@ -6,7 +6,7 @@
# the default is "F:/mydev"
export MYDEV="F:/mydev"
-export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.1.4;$MYDEV"
+export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.1.4;$MYDEV/mysql-VERSION/include;$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"
@@ -19,9 +19,9 @@ export AR='mwldnlm'
export AR_FLAGS='-type library -o'
export AS='mwasmnlm'
export CC='mwccnlm -gccincludes'
-export CFLAGS='-O3 -align 8 -proc 686 -relax_pointers -dialect c'
+export CFLAGS='-enum int -O3 -align 8 -proc 686 -relax_pointers -dialect c'
export CXX='mwccnlm -gccincludes'
-export CXXFLAGS='-O3 -align 8 -proc 686 -relax_pointers -dialect c++ -bool on -wchar_t on -D_WCHAR_T'
+export CXXFLAGS='-enum int -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=:
diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap
index 2bd7150ec0d..48ff2a49667 100755
--- a/netware/BUILD/nwbootstrap
+++ b/netware/BUILD/nwbootstrap
@@ -171,10 +171,10 @@ do
rm $file.org
done
-# create the libmysql.imp file in netware folder from libmysql/libmysql.def file
+# create the libmysql.imp file in netware folder from libmysql/libmysql.def
+# file
echo "generating llibmysql.imp file..."
awk 'BEGIN{x=0;} END{printf("\n");} x==1 {printf(" %s",$1); x++; next} x>1 {printf(",\n %s", $1);next} /EXPORTS/{x=1}' libmysql/libmysql.def > netware/libmysql.imp
-
# build linux tools
echo "compiling linux tools..."
./netware/BUILD/compile-linux-tools
diff --git a/netware/Makefile.am b/netware/Makefile.am
index aeb93d1575d..be59efd1deb 100644
--- a/netware/Makefile.am
+++ b/netware/Makefile.am
@@ -32,8 +32,6 @@ netware_build_files = client/mysql.def client/mysqladmin.def \
extra/mysql_install.def extra/my_print_defaults.def \
extra/perror.def extra/replace.def \
extra/resolveip.def extra/comp_err.def \
- isam/isamchk.def \
- isam/isamlog.def isam/pack_isam.def \
libmysqld/libmysqld.def myisam/myisamchk.def \
myisam/myisamlog.def myisam/myisampack.def \
sql/mysqld.def extra/mysql_waitpid.def \
@@ -48,7 +46,7 @@ link_sources:
done;
else
EXTRA_DIST= comp_err.def init_db.sql install_test_db.ncf \
- isamchk.def isamlog.def libmysql.def libmysql.imp \
+ 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 \
@@ -58,7 +56,7 @@ EXTRA_DIST= comp_err.def init_db.sql install_test_db.ncf \
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 \
+ mysqlshow.def mysqltest.def perror.def \
replace.def resolve_stack_dump.def resolveip.def test_db.sql \
static_init_db.sql \
BUILD/apply-patch BUILD/compile-AUTOTOOLS \
diff --git a/netware/my_manage.c b/netware/my_manage.c
index 29514837837..d5032da2208 100644
--- a/netware/my_manage.c
+++ b/netware/my_manage.c
@@ -73,7 +73,7 @@ void init_args(arg_list_t *al)
Add an argument to a list.
******************************************************************************/
-void add_arg(arg_list_t *al, char *format, ...)
+void add_arg(arg_list_t *al, const char *format, ...)
{
va_list ap;
char temp[PATH_MAX];
@@ -439,7 +439,7 @@ void del_tree(char *dir)
removef()
******************************************************************************/
-int removef(char *format, ...)
+int removef(const char *format, ...)
{
va_list ap;
char path[PATH_MAX];
diff --git a/netware/my_manage.h b/netware/my_manage.h
index ada02378ee4..480eefbe55a 100644
--- a/netware/my_manage.h
+++ b/netware/my_manage.h
@@ -26,17 +26,41 @@
******************************************************************************/
#include <stdlib.h>
+#ifndef __WIN__
#include <unistd.h>
+#endif
/******************************************************************************
macros
******************************************************************************/
+#ifdef __WIN__
+#define PATH_MAX _MAX_PATH
+#define NAME_MAX _MAX_FNAME
+#define kill(A,B) TerminateProcess((HANDLE)A,0)
+#define NOT_NEED_PID 0
+#define MASTER_PID 1
+#define SLAVE_PID 2
+#define mysqld_timeout 60000
+
+intptr_t master_server;
+intptr_t slave_server;
+int pid_mode;
+bool run_server;
+char win_args[1024];
+bool skip_first_param;
+#endif
+
#define ARG_BUF 10
#define TRY_MAX 5
+#ifdef __NETWARE__
+#define strstr(A,B) strindex(A,B)
+#endif
+
+
/******************************************************************************
structures
@@ -53,6 +77,8 @@ typedef struct
} arg_list_t;
+
+typedef int pid_t;
/******************************************************************************
global variables
@@ -66,7 +92,7 @@ typedef struct
******************************************************************************/
void init_args(arg_list_t *);
-void add_arg(arg_list_t *, char *, ...);
+void add_arg(arg_list_t *, const char *, ...);
void free_args(arg_list_t *);
int sleep_until_file_exists(char *);
@@ -80,8 +106,12 @@ pid_t get_server_pid(char *);
void kill_server(pid_t pid);
void del_tree(char *);
-int removef(char *, ...);
+int removef(const char *, ...);
void get_basedir(char *, char *);
+char mysqladmin_file[PATH_MAX];
+
#endif /* _MY_MANAGE */
+
+
diff --git a/netware/my_print_defaults.def b/netware/my_print_defaults.def
index 826981256b5..d88c5adf4cc 100644
--- a/netware/my_print_defaults.def
+++ b/netware/my_print_defaults.def
@@ -4,7 +4,8 @@
MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Print Defaults Tool"
-VERSION 4, 0
+VERSION 5, 0, 8
+STACKSIZE 32767
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c
index 849828210f2..7ca242178ff 100644
--- a/netware/mysql_test_run.c
+++ b/netware/mysql_test_run.c
@@ -27,6 +27,7 @@
#include "my_manage.h"
#ifdef __NETWARE__
#define strindex(a,b) ((char*)strindex(a,b))
+#define strstr(a,b) ((char*)strstr(a,b))
#endif
/******************************************************************************
@@ -347,6 +348,7 @@ void start_master()
add_arg(&al, "--character-sets-dir=%s", char_dir);
add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
add_arg(&al, "--language=%s", lang_dir);
+ add_arg(&al, "--log-bin-trust-routine-creators");
#ifdef DEBUG //only for debug builds
add_arg(&al, "--debug");
#endif
@@ -520,6 +522,7 @@ void start_slave()
add_arg(&al, "--master-retry-count=10");
add_arg(&al, "-O");
add_arg(&al, "slave_net_timeout=10");
+ add_arg(&al, "--log-bin-trust-routine-creators");
#ifdef DEBUG //only for debug builds
add_arg(&al, "--debug");
#endif
@@ -941,7 +944,7 @@ void run_test(char *test)
// increment total
++total_test;
}
- else if (err == 2)
+ else if (err == 62)
{
// skip
rstr = TEST_SKIP;
@@ -1166,6 +1169,10 @@ void setup(char *file)
setenv("MYSQL_TCP_PORT", "3306", 1);
snprintf(file_path, PATH_MAX*2, "%s/mysql_client_test --no-defaults --testcase--user=root --port=%u ", bin_dir, master_port);
setenv("MYSQL_CLIENT_TEST",file_path,1);
+ snprintf(file_path, PATH_MAX*2, "%s/mysql --no-defaults --user=root --port=%u ", bin_dir, master_port);
+ setenv("MYSQL",file_path,1);
+ snprintf(file_path, PATH_MAX*2, "%s/mysqlshow --no-defaults --user=root --port=%u", bin_dir, master_port);
+ setenv("MYSQL_SHOW",file_path,1);
}
/******************************************************************************
diff --git a/netware/mysqladmin.def b/netware/mysqladmin.def
index cfab4f4c23d..e7f2d90bf9e 100644
--- a/netware/mysqladmin.def
+++ b/netware/mysqladmin.def
@@ -6,6 +6,7 @@ SCREENNAME "MySQL Admin[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Admin Tool"
VERSION 4, 0
+STACKSIZE 32767
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqld_safe.c b/netware/mysqld_safe.c
index a307b52bb7e..3a1672fdf61 100644
--- a/netware/mysqld_safe.c
+++ b/netware/mysqld_safe.c
@@ -666,7 +666,6 @@ void mysql_start(int argc, char *argv[])
if (!strnicmp(argv[i], private_options[j], strlen(private_options[j])))
{
skip= TRUE;
- consoleprintf("The argument skipped is %s\n", argv[i]);
break;
}
}
@@ -674,7 +673,6 @@ void mysql_start(int argc, char *argv[])
if (!skip)
{
add_arg(&al, "%s", argv[i]);
- consoleprintf("The final argument is %s\n", argv[i]);
}
}
// spawn
diff --git a/os2/ChangeLog.os2 b/os2/ChangeLog.os2
index 7957906ad7d..18356b840ed 100644
--- a/os2/ChangeLog.os2
+++ b/os2/ChangeLog.os2
@@ -1,5 +1,8 @@
+2005/01/01
+ - removed references to ISAM and MERGE
+
2002/05/02
- now libinit is automatically called on client dll startup
diff --git a/os2/MySQL-Source.icc b/os2/MySQL-Source.icc
index f4ac881c90e..de0ac75ec9c 100644
--- a/os2/MySQL-Source.icc
+++ b/os2/MySQL-Source.icc
@@ -84,8 +84,6 @@ group sql =
"..\\sql\\field_conv.cc",
"..\\sql\\filesort.cc",
"..\\sql\\ha_heap.cc",
- "..\\sql\\ha_isam.cc",
- "..\\sql\\ha_isammrg.cc",
"..\\sql\\ha_myisam.cc",
"..\\sql\\ha_myisammrg.cc",
"..\\sql\\handler.cc",
@@ -151,21 +149,6 @@ group sql =
"..\\sql\\unireg.cc",
"..\\sql\\violite.c"
-group isam =
- "..\\isam\\changed.c", "..\\isam\\close.c",
- "..\\isam\\create.c", "..\\isam\\delete.c", "..\\isam\\extra.c",
- "..\\isam\\info.c", "..\\isam\\log.c", "..\\isam\\open.c",
- "..\\isam\\panic.c", "..\\isam\\range.c",
- "..\\isam\\rfirst.c", "..\\isam\\rkey.c", "..\\isam\\rlast.c",
- "..\\isam\\rnext.c", "..\\isam\\rprev.c", "..\\isam\\rrnd.c",
- "..\\isam\\rsame.c", "..\\isam\\rsamepos.c",
- "..\\isam\\static.c", "..\\isam\\update.c",
- "..\\isam\\write.c", "..\\isam\\_cache.c",
- "..\\isam\\_dbug.c", "..\\isam\\_dynrec.c",
- "..\\isam\\_key.c", "..\\isam\\_locking.c",
- "..\\isam\\_packrec.c", "..\\isam\\_page.c",
- "..\\isam\\_search.c", "..\\isam\\_statrec.c"
-
group strings =
"..\\strings\\bchange.c",
"..\\strings\\bmove.c",
@@ -214,13 +197,6 @@ group strings =
"..\\heap\\hp_write.c", "..\\heap\\_check.c", "..\\heap\\_rectest.c"
- group merge = "..\\merge\\close.c", "..\\merge\\create.c", "..\\merge\\delete.c",
- "..\\merge\\extra.c", "..\\merge\\info.c", "..\\merge\\open.c",
- "..\\merge\\panic.c", "..\\merge\\rrnd.c", "..\\merge\\rsame.c",
- "..\\merge\\static.c", "..\\merge\\update.c",
- "..\\merge\\_locking.c"
-
-
group myisammrg = "..\\myisammrg\\myrg_close.c",
"..\\myisammrg\\myrg_create.c", "..\\myisammrg\\myrg_delete.c",
"..\\myisammrg\\myrg_extra.c", "..\\myisammrg\\myrg_info.c",
diff --git a/os2/MySQL-Sql.icc b/os2/MySQL-Sql.icc
index c1256d5e39e..7c8c61fe7de 100644
--- a/os2/MySQL-Sql.icc
+++ b/os2/MySQL-Sql.icc
@@ -30,8 +30,6 @@ option ProjectOptions = MySQLOptions
source type('cpp') dbug
}
source type('cpp') heap
- source type('cpp') isam
- source type('cpp') merge
source type('cpp') myisam
source type('cpp') myisammrg
source type('cpp') my_sys
diff --git a/os2/MySQL-Util.icc b/os2/MySQL-Util.icc
index 36fd499e520..8eaee41b6a2 100644
--- a/os2/MySQL-Util.icc
+++ b/os2/MySQL-Util.icc
@@ -25,10 +25,8 @@ option ProjectOptions = MySQLOptions
source type('cpp') dbug
}
source type('cpp') heap
- source type('cpp') merge
source type('cpp') myisam
source type('cpp') myisammrg
- source type('cpp') isam
source type('cpp') my_sys
source type('cpp') my_sys_cli
source type('cpp') my_sys_sql
@@ -89,16 +87,6 @@ option ProjectOptions = MySQLOptions
source type('cpp') "..\\sql\\gen_lex_hash.cc"
}
- target "..\\bin\\test\\is_test1.exe"
- {
- // target source files
- source type('cpp') "..\\isam\\test1.c"
- }
- target "..\\bin\\test\\is_test2.exe"
- {
- // target source files
- source type('cpp') "..\\isam\\test2.c"
- }
target "..\\bin\\test\\mi_test1.exe"
{
// target source files
diff --git a/regex/Makefile.am b/regex/Makefile.am
index bcba6818b1b..3b161287d36 100644
--- a/regex/Makefile.am
+++ b/regex/Makefile.am
@@ -15,8 +15,7 @@
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
noinst_LIBRARIES = libregex.a
LDADD= libregex.a $(top_builddir)/strings/libmystrings.a
noinst_HEADERS = cclass.h cname.h regex2.h utils.h engine.c regex.h
diff --git a/regex/engine.c b/regex/engine.c
index 6734560b9bf..c4c4efe7e2f 100644
--- a/regex/engine.c
+++ b/regex/engine.c
@@ -256,7 +256,7 @@ sopno stopst;
register char *ssp; /* start of string matched by subsubRE */
register char *sep; /* end of string matched by subsubRE */
register char *oldssp; /* previous ssp */
- register char *dp;
+ register char *dp; /* used in debug mode to check asserts */
AT("diss", start, stop, startst, stopst);
sp = start;
diff --git a/regex/main.c b/regex/main.c
index 29abca6d9a2..8fe16d74eee 100644
--- a/regex/main.c
+++ b/regex/main.c
@@ -78,7 +78,7 @@ char *argv[];
if (err) {
len = regerror(err, &re, erbuf, sizeof(erbuf));
fprintf(stderr, "error %s, %d/%d `%s'\n",
- eprint(err), len, (int) sizeof(erbuf), erbuf);
+ eprint(err), (int) len, (int) sizeof(erbuf), erbuf);
exit(status);
}
regprint(&re, stdout);
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 27b42314273..2f6dd8c52e5 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -90,7 +90,7 @@ CLEANFILES = @server_scripts@ \
make_win_binary_distribution \
mysql_create_system_tables
-SUPERCLEANFILES = mysqlbug
+DISTCLEANFILES = mysqlbug
# We want the right version and configure comand line in mysqlbug
mysqlbug: ${top_builddir}/config.status mysqlbug.sh
diff --git a/scripts/fill_func_tables.sh b/scripts/fill_func_tables.sh
index 459afee2fe1..203c730dd9a 100644
--- a/scripts/fill_func_tables.sh
+++ b/scripts/fill_func_tables.sh
@@ -131,8 +131,8 @@ print "USE mysql_help;\n";
print "DROP TABLE IF EXISTS function;\n";
print "CREATE TABLE function (";
print " func_id int unsigned not null auto_increment,";
-print " name varchar(64) not null,";
-print " url varchar(128) not null,";
+print " name char(64) not null,";
+print " url char(128) not null,";
print " description text not null,";
print " example text not null,";
print " min_args tinyint not null,";
@@ -145,8 +145,8 @@ print ") type=myisam;\n\n";
print "DROP TABLE IF EXISTS function_category_name;\n";
print "CREATE TABLE function_category_name (";
print " cat_id smallint unsigned not null auto_increment,";
-print " name varchar(64) not null,";
-print " url varchar(128) not null,";
+print " name char(64) not null,";
+print " url char(128) not null,";
print " date_created datetime not null,";
print " last_modified timestamp not null,";
print " primary key (cat_id)";
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index 3b8cc1ca12a..fbdbd998138 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -40,6 +40,8 @@ parse_arguments() {
parse_arguments "$@"
+
+
#make
# This should really be integrated with automake and not duplicate the
@@ -95,14 +97,14 @@ do
fi
done
-# Non platform-specific bin dir files:
+# Non platform-specific bin files:
BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \
extra/resolveip$BS extra/my_print_defaults$BS \
extra/resolve_stack_dump$BS extra/mysql_waitpid$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/mysql_tzinfo_to_sql$BS \
+ server-tools/instance-manager/mysqlmanager$BS \
client/mysql$BS client/mysqlshow$BS client/mysqladmin$BS \
client/mysqldump$BS client/mysqlimport$BS \
client/mysqltest$BS client/mysqlcheck$BS \
@@ -112,23 +114,23 @@ BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \
libmysqld/examples/mysqltest_embedded$BS \
";
-# Platform-specific bin dir files:
+# Platform-specific bin files:
if [ $BASE_SYSTEM = "netware" ] ; then
BIN_FILES="$BIN_FILES \
netware/mysqld_safe$BS netware/mysql_install_db$BS \
netware/init_db.sql netware/test_db.sql netware/mysql_explain_log$BS \
- netware/mysqlhotcopy$BS netware/libmysql$BS netware/init_secure_db.sql
+ netware/mysqlhotcopy$BS netware/libmysql$BS netware/init_secure_db.sql \
";
+# For all other platforms:
else
- # For all other platforms:
BIN_FILES="$BIN_FILES \
- client/mysqlmanagerc \
- client/mysqlmanager-pwgen tools/mysqlmanager \
+ client/mysqltestmanagerc \
+ client/mysqltestmanager-pwgen tools/mysqltestmanager \
client/.libs/mysql client/.libs/mysqlshow client/.libs/mysqladmin \
client/.libs/mysqldump client/.libs/mysqlimport \
client/.libs/mysqltest client/.libs/mysqlcheck \
- client/.libs/mysqlbinlog client/.libs/mysqlmanagerc \
- client/.libs/mysqlmanager-pwgen tools/.libs/mysqlmanager \
+ client/.libs/mysqlbinlog client/.libs/mysqltestmanagerc \
+ client/.libs/mysqltestmanager-pwgen tools/.libs/mysqltestmanager \
tests/.libs/mysql_client_test \
libmysqld/examples/.libs/mysql_client_test_embedded \
libmysqld/examples/.libs/mysqltest_embedded \
@@ -207,6 +209,7 @@ rm -f $MYSQL_SHARE/Makefile* $MYSQL_SHARE/*/*.OLD
for i in mysql-test/mysql-test-run mysql-test/install_test_db \
mysql-test/mysql-test-run.pl mysql-test/README \
+ mysql-test/valgrind.supp \
netware/mysql_test_run.nlm netware/install_test_db.ncf
do
if [ -f $i ]
@@ -218,16 +221,21 @@ done
$CP mysql-test/lib/*.pl $BASE/mysql-test/lib
$CP mysql-test/lib/*.sql $BASE/mysql-test/lib
$CP mysql-test/include/*.inc $BASE/mysql-test/include
-$CP mysql-test/std_data/*.dat mysql-test/std_data/*.*001 $BASE/mysql-test/std_data
-$CP mysql-test/std_data/des_key_file $BASE/mysql-test/std_data
-$CP mysql-test/t/*test mysql-test/t/*.opt mysql-test/t/*.slave-mi mysql-test/t/*.sh $BASE/mysql-test/t
-$CP mysql-test/r/*result mysql-test/r/*.require $BASE/mysql-test/r
+$CP mysql-test/t/*.def $BASE/mysql-test/t
+$CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \
+ mysql-test/std_data/*.pem mysql-test/std_data/Moscow_leap \
+ mysql-test/std_data/des_key_file mysql-test/std_data/*.*001 \
+ $BASE/mysql-test/std_data
+$CP mysql-test/t/*.test mysql-test/t/*.disabled mysql-test/t/*.opt \
+ mysql-test/t/*.slave-mi mysql-test/t/*.sh mysql-test/t/*.sql $BASE/mysql-test/t
+$CP mysql-test/r/*.result mysql-test/r/*.require \
+ $BASE/mysql-test/r
if [ $BASE_SYSTEM != "netware" ] ; then
chmod a+x $BASE/bin/*
$CP scripts/* $BASE/bin
$BASE/bin/replace \@localstatedir\@ ./data \@bindir\@ ./bin \@scriptdir\@ ./bin \@libexecdir\@ ./bin \@sbindir\@ ./bin \@prefix\@ . \@HOSTNAME\@ @HOSTNAME@ \@pkgdatadir\@ ./support-files < $SOURCE/scripts/mysql_install_db.sh > $BASE/scripts/mysql_install_db
- $BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \@MYSQLD_USER\@ root \@localstatedir\@ /usr/local/mysql/data \@HOSTNAME\@ @HOSTNAME@ < $SOURCE/support-files/mysql.server.sh > $BASE/support-files/mysql.server
+ $BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \@sbindir\@ ./bin \@libexecdir\@ ./bin \@MYSQLD_USER\@ @MYSQLD_USER@ \@localstatedir\@ /usr/local/mysql/data \@HOSTNAME\@ @HOSTNAME@ < $SOURCE/support-files/mysql.server.sh > $BASE/support-files/mysql.server
$BASE/bin/replace /my/gnu/bin/hostname /bin/hostname -- $BASE/bin/mysqld_safe
mv $BASE/support-files/binary-configure $BASE/configure
chmod a+x $BASE/bin/* $BASE/scripts/* $BASE/support-files/mysql-* $BASE/support-files/mysql.server $BASE/configure
@@ -245,10 +253,8 @@ rm -f $BASE/bin/Makefile* $BASE/bin/*.in $BASE/bin/*.sh $BASE/bin/mysql_install_
if [ $BASE_SYSTEM = "netware" ] ; then
echo "CREATE DATABASE mysql;" > $BASE/bin/init_db.sql
echo "CREATE DATABASE test;" >> $BASE/bin/init_db.sql
- sh ./scripts/mysql_create_system_tables.sh real "" "%" 0 >> $BASE/bin/init_db.sql
- sh ./scripts/mysql_create_system_tables.sh test "" "%" 0 > $BASE/bin/test_db.sql
-# cp ./netware/static_init_db.sql ./netware/init_db.sql
-# ./scripts/fill_help_tables < ./Docs/manual.texi >> ./netware/init_db.sql
+ sh ./scripts/mysql_create_system_tables.sh real >> $BASE/bin/init_db.sql
+ sh ./scripts/mysql_create_system_tables.sh test > $BASE/bin/test_db.sql
fi
#
@@ -268,7 +274,9 @@ fi
# Make safe_mysqld a symlink to mysqld_safe for backwards portability
# To be removed in MySQL 4.1
-(cd $BASE/bin ; ln -s mysqld_safe safe_mysqld )
+if [ $BASE_SYSTEM != "netware" ] ; then
+ (cd $BASE/bin ; ln -s mysqld_safe safe_mysqld )
+fi
# Clean up if we did this from a bk tree
if [ -d $BASE/sql-bench/SCCS ] ; then
@@ -288,6 +296,22 @@ if [ x$NDBCLUSTER = x1 ]; then
rm -rf $BASE/ndb-stage
fi
+# Remove vendor from $system
+system=`echo $system | sed -e 's/[a-z]*-\(.*\)/\1/g'`
+
+# Map OS names to "our" OS names (eg. darwin6.8 -> osx10.2)
+system=`echo $system | sed -e 's/darwin6.*/osx10.2/g'`
+system=`echo $system | sed -e 's/darwin7.*/osx10.3/g'`
+system=`echo $system | sed -e 's/darwin8.*/osx10.4/g'`
+system=`echo $system | sed -e 's/\(aix4.3\).*/\1/g'`
+system=`echo $system | sed -e 's/\(aix5.1\).*/\1/g'`
+system=`echo $system | sed -e 's/\(aix5.2\).*/\1/g'`
+system=`echo $system | sed -e 's/\(aix5.3\).*/\1/g'`
+system=`echo $system | sed -e 's/osf5.1b/tru64/g'`
+system=`echo $system | sed -e 's/linux-gnu/linux/g'`
+system=`echo $system | sed -e 's/solaris2.\([0-9]*\)/solaris\1/g'`
+system=`echo $system | sed -e 's/sco3.2v\(.*\)/openserver\1/g'`
+
# Use the override --machine if present
if [ -n "$MACHINE" ] ; then
machine=$MACHINE
diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh
index 71d61b7a02d..e75dec55e82 100644
--- a/scripts/make_win_src_distribution.sh
+++ b/scripts/make_win_src_distribution.sh
@@ -199,11 +199,10 @@ copy_dir_files()
print_debug "Creating directory '$arg'"
mkdir $BASE/$arg
fi
- for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp *.dsp \
- README INSTALL* LICENSE *.inc *.test *.result \
- *.pem Moscow_leap des_key_file *.dat *.000001 \
- *.require *.opt
-
+ for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp *.dsp *.dsw \
+ README INSTALL* LICENSE AUTHORS NEWS ChangeLog \
+ *.inc *.test *.result *.pem Moscow_leap des_key_file \
+ *.vcproj *.sln *.dat *.000001 *.require *.opt
do
if [ -f $i ]
then
@@ -234,6 +233,7 @@ copy_dir_dirs() {
find $arg -type d \
-and -not -path \*SCCS\* \
-and -not -path \*.deps\* \
+ -and -not -path \*.libs\* \
-and -not -path \*autom4te.cache -print
)|(
while read v
@@ -249,8 +249,8 @@ copy_dir_dirs() {
# Input directories to be copied
#
-for i in client dbug extra heap include isam \
- libmysql libmysqld merge myisam \
+for i in client dbug extra heap include \
+ libmysql libmysqld myisam \
myisammrg mysys regex sql strings sql-common sql/examples \
tools vio zlib
do
@@ -266,7 +266,7 @@ make -C $SOURCE/ndb windoze
# Input directories to be copied recursively
#
-for i in bdb innobase ndb
+for i in bdb innobase ndb extra/yassl server-tools
do
copy_dir_dirs $i
done
@@ -298,6 +298,8 @@ do
fi
done
+cp extra/sql_state.h extra/mysqld_error.h $BASE/include
+
#
# support files
#
@@ -326,6 +328,8 @@ do
$CP -R $i $BASE/$i
fi
fi
+ # But remove object files from destination
+ find $BASE/$i -type f -name \*.o | xargs rm -f
done
#
@@ -339,7 +343,9 @@ mv $BASE/sql/sql_yacc.cpp-new $BASE/sql/sql_yacc.cpp
# Search the tree for plain text files and adapt the line end marker
#
find $BASE \( -name "*.dsp" -o -name "*.dsw" -o -name "*.cnf" -o -name "*.ini" \
- -o -name COPYING -o -name ChangeLog -o -name EXCEPTIONS-CLIENT -o -name "INSTALL*" -o -name LICENSE -o -name "README*" \) -type f -print \
+ -o -name COPYING -o -name ChangeLog -o -name EXCEPTIONS-CLIENT \
+ -o -name "INSTALL*" -o -name LICENSE -o -name "README*" \
+ -o -name "*.vcproj" -o -name "*.sln" \) -type f -print \
| while read v
do
unix_to_dos $v
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index 4c642423879..383f8b80dc8 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -41,6 +41,7 @@ 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="" c_pp=""
# Check for old tables
if test ! -f $mdata/db.frm
@@ -66,14 +67,19 @@ then
c_d="$c_d Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_d="$c_d Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_d="$c_d Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_d="$c_d Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_d="$c_d Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_d="$c_d Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_d="$c_d Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_d="$c_d Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_d="$c_d PRIMARY KEY Host (Host,Db,User),"
c_d="$c_d KEY User (User)"
c_d="$c_d ) engine=MyISAM"
c_d="$c_d CHARACTER SET utf8 COLLATE utf8_bin"
c_d="$c_d comment='Database privileges';"
- i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');
- INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');"
+ i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N');
+ INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N');"
fi
if test ! -f $mdata/host.frm
@@ -97,6 +103,11 @@ then
c_h="$c_h Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_h="$c_h Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_h="$c_h Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_h="$c_h PRIMARY KEY Host (Host,Db)"
c_h="$c_h ) engine=MyISAM"
c_h="$c_h CHARACTER SET utf8 COLLATE utf8_bin"
@@ -134,6 +145,11 @@ then
c_u="$c_u Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_u="$c_u Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_u="$c_u Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL,"
c_u="$c_u ssl_cipher BLOB NOT NULL,"
c_u="$c_u x509_issuer BLOB NOT NULL,"
@@ -141,6 +157,7 @@ then
c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL,"
c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL,"
c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL,"
+ c_u="$c_u max_user_connections int(11) unsigned DEFAULT 0 NOT NULL,"
c_u="$c_u PRIMARY KEY Host (Host,User)"
c_u="$c_u ) engine=MyISAM"
c_u="$c_u CHARACTER SET utf8 COLLATE utf8_bin"
@@ -148,22 +165,22 @@ then
if test "$1" = "test"
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);
- 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);
- REPLACE INTO user VALUES ('127.0.0.1','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);
+ 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','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+ 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','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+ REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
INSERT INTO user (host,user) values ('localhost','');
INSERT INTO user (host,user) values ('$hostname','');"
else
- 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);"
+ 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','Y','Y','Y','Y','Y','','','','',0,0,0,0);"
if test "$windows" = "0"
then
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 VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
INSERT INTO user (host,user) values ('$hostname','');
INSERT INTO user (host,user) values ('localhost','');"
else
i_u="$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);"
+ 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','Y','','','','',0,0,0);"
fi
fi
fi
@@ -198,7 +215,7 @@ then
c_t="$c_t Table_name char(64) binary DEFAULT '' NOT NULL,"
c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL,"
c_t="$c_t Timestamp timestamp(14),"
- c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL,"
+ c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL,"
c_t="$c_t Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL,"
c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name),"
c_t="$c_t KEY Grantor (Grantor)"
@@ -227,6 +244,28 @@ then
c_c="$c_c comment='Column privileges';"
fi
+if test ! -f $mdata/procs_priv.frm
+then
+ if test "$1" = "verbose" ; then
+ echo "Preparing procs_priv table" 1>&2;
+ fi
+
+ c_pp="$c_pp CREATE TABLE procs_priv ("
+ c_pp="$c_pp Host char(60) binary DEFAULT '' NOT NULL,"
+ c_pp="$c_pp Db char(64) binary DEFAULT '' NOT NULL,"
+ c_pp="$c_pp User char(16) binary DEFAULT '' NOT NULL,"
+ c_pp="$c_pp Routine_name char(64) binary DEFAULT '' NOT NULL,"
+ c_pp="$c_pp Routine_type enum('FUNCTION','PROCEDURE') NOT NULL,"
+ c_pp="$c_pp Grantor char(77) DEFAULT '' NOT NULL,"
+ c_pp="$c_pp Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL,"
+ c_pp="$c_pp Timestamp timestamp(14),"
+ c_pp="$c_pp PRIMARY KEY (Host,Db,User,Routine_name,Routine_type),"
+ c_pp="$c_pp KEY Grantor (Grantor)"
+ c_pp="$c_pp ) engine=MyISAM"
+ c_pp="$c_pp CHARACTER SET utf8 COLLATE utf8_bin"
+ c_pp="$c_pp comment='Procedure privileges';"
+fi
+
if test ! -f $mdata/help_topic.frm
then
if test "$1" = "verbose" ; then
@@ -235,11 +274,11 @@ then
c_ht="$c_ht CREATE TABLE help_topic ("
c_ht="$c_ht help_topic_id int unsigned not null,"
- c_ht="$c_ht name varchar(64) not null,"
+ c_ht="$c_ht name char(64) not null,"
c_ht="$c_ht help_category_id smallint unsigned not null,"
c_ht="$c_ht description text not null,"
c_ht="$c_ht example text not null,"
- c_ht="$c_ht url varchar(128) not null,"
+ c_ht="$c_ht url char(128) not null,"
c_ht="$c_ht primary key (help_topic_id),"
c_ht="$c_ht unique index (name)"
c_ht="$c_ht ) engine=MyISAM"
@@ -257,9 +296,9 @@ then
c_hc="$c_hc CREATE TABLE help_category ("
c_hc="$c_hc help_category_id smallint unsigned not null,"
- c_hc="$c_hc name varchar(64) not null,"
+ c_hc="$c_hc name char(64) not null,"
c_hc="$c_hc parent_category_id smallint unsigned null,"
- c_hc="$c_hc url varchar(128) not null,"
+ c_hc="$c_hc url char(128) not null,"
c_hc="$c_hc primary key (help_category_id),"
c_hc="$c_hc unique index (name)"
c_hc="$c_hc ) engine=MyISAM"
@@ -275,7 +314,7 @@ then
c_hk="$c_hk CREATE TABLE help_keyword ("
c_hk="$c_hk help_keyword_id int unsigned not null,"
- c_hk="$c_hk name varchar(64) not null,"
+ c_hk="$c_hk name char(64) not null,"
c_hk="$c_hk primary key (help_keyword_id),"
c_hk="$c_hk unique index (name)"
c_hk="$c_hk ) engine=MyISAM"
@@ -627,6 +666,66 @@ then
fi
fi
+if test ! -f $mdata/proc.frm
+then
+ c_p="$c_p CREATE TABLE proc ("
+ c_p="$c_p db char(64) collate utf8_bin DEFAULT '' NOT NULL,"
+ c_p="$c_p name char(64) DEFAULT '' NOT NULL,"
+ c_p="$c_p type enum('FUNCTION','PROCEDURE') NOT NULL,"
+ c_p="$c_p specific_name char(64) DEFAULT '' NOT NULL,"
+ c_p="$c_p language enum('SQL') DEFAULT 'SQL' NOT NULL,"
+ c_p="$c_p sql_data_access enum('CONTAINS_SQL',"
+ c_p="$c_p 'NO_SQL',"
+ c_p="$c_p 'READS_SQL_DATA',"
+ c_p="$c_p 'MODIFIES_SQL_DATA'"
+ c_p="$c_p ) DEFAULT 'CONTAINS_SQL' NOT NULL,"
+ c_p="$c_p is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,"
+ c_p="$c_p security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL,"
+ c_p="$c_p param_list blob DEFAULT '' NOT NULL,"
+ c_p="$c_p returns char(64) DEFAULT '' NOT NULL,"
+ c_p="$c_p body longblob DEFAULT '' NOT NULL,"
+ c_p="$c_p definer char(77) collate utf8_bin DEFAULT '' NOT NULL,"
+ c_p="$c_p created timestamp,"
+ c_p="$c_p modified timestamp,"
+ c_p="$c_p sql_mode set("
+ c_p="$c_p 'REAL_AS_FLOAT',"
+ c_p="$c_p 'PIPES_AS_CONCAT',"
+ c_p="$c_p 'ANSI_QUOTES',"
+ c_p="$c_p 'IGNORE_SPACE',"
+ c_p="$c_p 'NOT_USED',"
+ c_p="$c_p 'ONLY_FULL_GROUP_BY',"
+ c_p="$c_p 'NO_UNSIGNED_SUBTRACTION',"
+ c_p="$c_p 'NO_DIR_IN_CREATE',"
+ c_p="$c_p 'POSTGRESQL',"
+ c_p="$c_p 'ORACLE',"
+ c_p="$c_p 'MSSQL',"
+ c_p="$c_p 'DB2',"
+ c_p="$c_p 'MAXDB',"
+ c_p="$c_p 'NO_KEY_OPTIONS',"
+ c_p="$c_p 'NO_TABLE_OPTIONS',"
+ c_p="$c_p 'NO_FIELD_OPTIONS',"
+ c_p="$c_p 'MYSQL323',"
+ c_p="$c_p 'MYSQL40',"
+ c_p="$c_p 'ANSI',"
+ c_p="$c_p 'NO_AUTO_VALUE_ON_ZERO',"
+ c_p="$c_p 'NO_BACKSLASH_ESCAPES',"
+ c_p="$c_p 'STRICT_TRANS_TABLES',"
+ c_p="$c_p 'STRICT_ALL_TABLES',"
+ c_p="$c_p 'NO_ZERO_IN_DATE',"
+ c_p="$c_p 'NO_ZERO_DATE',"
+ c_p="$c_p 'INVALID_DATES',"
+ c_p="$c_p 'ERROR_FOR_DIVISION_BY_ZERO',"
+ c_p="$c_p 'TRADITIONAL',"
+ c_p="$c_p 'NO_AUTO_CREATE_USER',"
+ c_p="$c_p 'HIGH_NOT_PRECEDENCE'"
+ c_p="$c_p ) DEFAULT '' NOT NULL,"
+ c_p="$c_p comment char(64) collate utf8_bin DEFAULT '' NOT NULL,"
+ c_p="$c_p PRIMARY KEY (db,name,type)"
+ c_p="$c_p ) engine=MyISAM"
+ c_p="$c_p character set utf8"
+ c_p="$c_p comment='Stored Procedures';"
+fi
+
cat << END_OF_DATA
use mysql;
set table_type=myisam;
@@ -660,5 +759,9 @@ $c_tztt
$i_tztt
$c_tzls
$i_tzls
+
+$c_p
+$c_pp
+
END_OF_DATA
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 56807a81d7c..d080b68b268 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -7,13 +7,14 @@ password=""
host="localhost"
user="root"
sql_only=0
-basedir=""
+basedir="@prefix@"
verbose=0
args=""
port=""
socket=""
database="mysql"
bindir=""
+pkgdatadir="@pkgdatadir@"
print_defaults_bindir="."
file=mysql_fix_privilege_tables.sql
@@ -89,34 +90,23 @@ done
parse_arguments `$print_defaults $defaults mysql_install_db mysql_fix_privilege_tables`
parse_arguments PICK-ARGS-FROM-ARGV "$@"
-if test -z "$basedir"
+if test -z "$password"
then
- basedir=@prefix@
- if test -z "$bindir"
- then
- bindir=@bindir@
- fi
- execdir=@libexecdir@
- pkgdatadir=@pkgdatadir@
-else
- if test -z "$bindir"
- then
- bindir="$basedir/bin"
- fi
- if test -x "$basedir/libexec/mysqld"
- then
- execdir="$basedir/libexec"
- elif test -x "@libexecdir@/mysqld"
- then
- execdir="@libexecdir@"
- else
- execdir="$basedir/bin"
- fi
+ password=$old_style_password
fi
-if test -z "$password"
+# Find where 'mysql' command is located
+
+if test -z "$bindir"
then
- password=$old_style_password
+ for i in @bindir@ $basedir/bin client
+ do
+ if test -f $i/mysql
+ then
+ bindir=$i
+ break
+ fi
+ done
fi
cmd="$bindir/mysql --no-defaults --force --user=$user --host=$host"
@@ -138,7 +128,7 @@ fi
# 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
+ $basedir/scripts $pkgdatadir . ./scripts
do
if test -f $i/$file
then
@@ -167,7 +157,8 @@ s_echo "This script updates all the mysql privilege tables to be usable by"
s_echo "MySQL 4.0 and above."
s_echo ""
s_echo "This is needed if you want to use the new GRANT functions,"
-s_echo "CREATE AGGREGATE FUNCTION, or the more secure passwords in 4.1"
+s_echo "CREATE AGGREGATE FUNCTION, stored procedures, or"
+s_echo "more secure passwords in 4.1"
s_echo ""
if test $verbose = 1
@@ -189,7 +180,7 @@ then
s_echo "done"
else
s_echo "Got a failure from command:"
- s_echo "$cmd"
+ s_echo "cat $sql_file | $cmd"
s_echo "Please check the above output and try again."
if test $verbose = 0
then
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index 0d7d32fd6a9..45f3b8533b5 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -9,7 +9,7 @@
-- this sql script.
-- On windows you should do 'mysql --force mysql < mysql_fix_privilege_tables.sql'
-set table_type=MyISAM;
+set storage_engine=MyISAM;
CREATE TABLE IF NOT EXISTS func (
name char(64) binary DEFAULT '' NOT NULL,
@@ -64,13 +64,20 @@ CREATE TABLE IF NOT EXISTS tables_priv (
ALTER TABLE tables_priv
modify Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
modify Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL;
+ALTER TABLE procs_priv ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
+ALTER TABLE procs_priv
+ modify Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL;
+ALTER TABLE procs_priv
+ add Routine_type enum('FUNCTION','PROCEDURE') COLLATE utf8_general_ci NOT NULL AFTER Routine_name;
+ALTER TABLE procs_priv
+ modify Timestamp timestamp(14) AFTER Proc_priv;
CREATE TABLE IF NOT EXISTS columns_priv (
Host char(60) DEFAULT '' NOT NULL,
- Db char(60) DEFAULT '' NOT NULL,
+ Db char(64) DEFAULT '' NOT NULL,
User char(16) DEFAULT '' NOT NULL,
- Table_name char(60) DEFAULT '' NOT NULL,
- Column_name char(59) DEFAULT '' NOT NULL,
+ Table_name char(64) DEFAULT '' NOT NULL,
+ Column_name char(64) DEFAULT '' NOT NULL,
Timestamp timestamp(14),
Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
PRIMARY KEY (Host,Db,User,Table_name,Column_name)
@@ -118,9 +125,9 @@ UPDATE user SET Show_db_priv= Select_priv, Super_priv=Process_priv, Execute_priv
-- for some users.
ALTER TABLE user
-ADD max_questions int(11) NOT NULL AFTER x509_subject,
-ADD max_updates int(11) unsigned NOT NULL AFTER max_questions,
-ADD max_connections int(11) unsigned NOT NULL AFTER max_updates;
+ADD max_questions int(11) NOT NULL DEFAULT 0 AFTER x509_subject,
+ADD max_updates int(11) unsigned NOT NULL DEFAULT 0 AFTER max_questions,
+ADD max_connections int(11) unsigned NOT NULL DEFAULT 0 AFTER max_updates;
--
@@ -134,12 +141,8 @@ ALTER TABLE host
ADD Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
ADD Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL;
-alter table db change Db Db char(64) binary DEFAULT '' NOT NULL;
-alter table host change Db Db char(64) binary DEFAULT '' NOT NULL;
alter table user change max_questions max_questions int(11) unsigned DEFAULT 0 NOT NULL;
-alter table tables_priv change Db Db char(64) binary DEFAULT '' NOT NULL, change Host Host char(60) binary DEFAULT '' NOT NULL, change User User char(16) binary DEFAULT '' NOT NULL, change Table_name Table_name char(64) binary DEFAULT '' NOT NULL;
alter table tables_priv add KEY Grantor (Grantor);
-alter table columns_priv change Db Db char(64) binary DEFAULT '' NOT NULL, change Host Host char(60) binary DEFAULT '' NOT NULL, change User User char(16) binary DEFAULT '' NOT NULL, change Table_name Table_name char(64) binary DEFAULT '' NOT NULL, change Column_name Column_name char(64) binary DEFAULT '' NOT NULL;
alter table db comment='Database privileges';
alter table host comment='Host privileges; Merged with database privileges';
@@ -238,8 +241,98 @@ ALTER TABLE tables_priv
MODIFY Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL;
#
+# Detect whether we had Create_view_priv
+#
+SET @hadCreateViewPriv:=0;
+SELECT @hadCreateViewPriv:=1 FROM user WHERE Create_view_priv LIKE '%';
+
+#
+# Create VIEWs privileges (v5.0)
+#
+ALTER TABLE db ADD Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Lock_tables_priv;
+ALTER TABLE host ADD Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Lock_tables_priv;
+ALTER TABLE user ADD Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Repl_client_priv;
+
+#
+# Show VIEWs privileges (v5.0)
+#
+ALTER TABLE db ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv;
+ALTER TABLE host ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv;
+ALTER TABLE user ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv;
+
+#
+# Show/Create views table privileges (v5.0)
+#
+ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL;
+
+#
+# Assign create/show view privileges to people who have create provileges
+#
+UPDATE user SET Create_view_priv=Create_priv, Show_view_priv=Create_priv where user<>"" AND @hadCreateViewPriv = 0;
+
+#
+#
+#
+SET @hadCreateRoutinePriv:=0;
+SELECT @hadCreateRoutinePriv:=1 FROM user WHERE Create_routine_priv LIKE '%';
+
+#
+# Create PROCEDUREs privileges (v5.0)
+#
+ALTER TABLE db ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv;
+ALTER TABLE host ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv;
+ALTER TABLE user ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv;
+
+#
+# Alter PROCEDUREs privileges (v5.0)
+#
+ALTER TABLE db ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv;
+ALTER TABLE host ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv;
+ALTER TABLE user ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv;
+
+ALTER TABLE db ADD Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv;
+ALTER TABLE host ADD Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv;
+
+#
+# Assign create/alter routine privileges to people who have create privileges
+#
+UPDATE user SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv where user<>"" AND @hadCreateRoutinePriv = 0;
+UPDATE db SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv, Execute_priv=Select_priv where user<>"" AND @hadCreateRoutinePriv = 0;
+UPDATE host SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv, Execute_priv=Select_priv where @hadCreateRoutinePriv = 0;
+
+#
+# Add max_user_connections resource limit
+#
+ALTER TABLE user ADD max_user_connections int(11) unsigned DEFAULT '0' NOT NULL AFTER max_connections;
+
+#
+# user.Create_user_priv
+#
+
+SET @hadCreateUserPriv:=0;
+SELECT @hadCreateUserPriv:=1 FROM user WHERE Create_user_priv LIKE '%';
+
+ALTER TABLE user ADD Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv;
+UPDATE user LEFT JOIN db USING (Host,User) SET Create_user_priv='Y'
+ WHERE @hadCreateUserPriv = 0 AND
+ (user.Grant_priv = 'Y' OR db.Grant_priv = 'Y');
+
+#
# Create some possible missing tables
#
+CREATE TABLE IF NOT EXISTS procs_priv (
+Host char(60) binary DEFAULT '' NOT NULL,
+Db char(64) binary DEFAULT '' NOT NULL,
+User char(16) binary DEFAULT '' NOT NULL,
+Routine_name char(64) binary DEFAULT '' NOT NULL,
+Routine_type enum('FUNCTION','PROCEDURE') NOT NULL,
+Grantor char(77) DEFAULT '' NOT NULL,
+Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
+Timestamp timestamp(14),
+PRIMARY KEY (Host,Db,User,Routine_name,Routine_type),
+KEY Grantor (Grantor)
+) CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
+
CREATE TABLE IF NOT EXISTS help_topic (
help_topic_id int unsigned not null,
name varchar(64) not null,
@@ -313,3 +406,118 @@ Correction int signed NOT NULL,
PRIMARY KEY TranTime (Transition_time)
) CHARACTER SET utf8 comment='Leap seconds information for time zones';
+
+#
+# Create proc table if it doesn't exists
+#
+
+CREATE TABLE IF NOT EXISTS proc (
+ db char(64) collate utf8_bin DEFAULT '' NOT NULL,
+ name char(64) DEFAULT '' NOT NULL,
+ type enum('FUNCTION','PROCEDURE') NOT NULL,
+ specific_name char(64) DEFAULT '' NOT NULL,
+ language enum('SQL') DEFAULT 'SQL' NOT NULL,
+ sql_data_access enum('CONTAINS_SQL',
+ 'NO_SQL',
+ 'READS_SQL_DATA',
+ 'MODIFIES_SQL_DATA'
+ ) DEFAULT 'CONTAINS_SQL' NOT NULL,
+ is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,
+ security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL,
+ param_list blob DEFAULT '' NOT NULL,
+ returns char(64) DEFAULT '' NOT NULL,
+ body longblob DEFAULT '' NOT NULL,
+ definer char(77) collate utf8_bin DEFAULT '' NOT NULL,
+ created timestamp,
+ modified timestamp,
+ sql_mode set(
+ 'REAL_AS_FLOAT',
+ 'PIPES_AS_CONCAT',
+ 'ANSI_QUOTES',
+ 'IGNORE_SPACE',
+ 'NOT_USED',
+ 'ONLY_FULL_GROUP_BY',
+ 'NO_UNSIGNED_SUBTRACTION',
+ 'NO_DIR_IN_CREATE',
+ 'POSTGRESQL',
+ 'ORACLE',
+ 'MSSQL',
+ 'DB2',
+ 'MAXDB',
+ 'NO_KEY_OPTIONS',
+ 'NO_TABLE_OPTIONS',
+ 'NO_FIELD_OPTIONS',
+ 'MYSQL323',
+ 'MYSQL40',
+ 'ANSI',
+ 'NO_AUTO_VALUE_ON_ZERO',
+ 'NO_BACKSLASH_ESCAPES',
+ 'STRICT_TRANS_TABLES',
+ 'STRICT_ALL_TABLES',
+ 'NO_ZERO_IN_DATE',
+ 'NO_ZERO_DATE',
+ 'INVALID_DATES',
+ 'ERROR_FOR_DIVISION_BY_ZERO',
+ 'TRADITIONAL',
+ 'NO_AUTO_CREATE_USER',
+ 'HIGH_NOT_PRECEDENCE'
+ ) DEFAULT '' NOT NULL,
+ comment char(64) collate utf8_bin DEFAULT '' NOT NULL,
+ PRIMARY KEY (db,name,type)
+) engine=MyISAM
+ character set utf8
+ comment='Stored Procedures';
+
+# Correct the name fields to not binary, and expand sql_data_access
+ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL,
+ MODIFY specific_name char(64) DEFAULT '' NOT NULL,
+ MODIFY sql_data_access
+ enum('CONTAINS_SQL',
+ 'NO_SQL',
+ 'READS_SQL_DATA',
+ 'MODIFIES_SQL_DATA'
+ ) DEFAULT 'CONTAINS_SQL' NOT NULL,
+ MODIFY body longblob DEFAULT '' NOT NULL,
+ MODIFY sql_mode
+ set('REAL_AS_FLOAT',
+ 'PIPES_AS_CONCAT',
+ 'ANSI_QUOTES',
+ 'IGNORE_SPACE',
+ 'NOT_USED',
+ 'ONLY_FULL_GROUP_BY',
+ 'NO_UNSIGNED_SUBTRACTION',
+ 'NO_DIR_IN_CREATE',
+ 'POSTGRESQL',
+ 'ORACLE',
+ 'MSSQL',
+ 'DB2',
+ 'MAXDB',
+ 'NO_KEY_OPTIONS',
+ 'NO_TABLE_OPTIONS',
+ 'NO_FIELD_OPTIONS',
+ 'MYSQL323',
+ 'MYSQL40',
+ 'ANSI',
+ 'NO_AUTO_VALUE_ON_ZERO',
+ 'NO_BACKSLASH_ESCAPES',
+ 'STRICT_TRANS_TABLES',
+ 'STRICT_ALL_TABLES',
+ 'NO_ZERO_IN_DATE',
+ 'NO_ZERO_DATE',
+ 'INVALID_DATES',
+ 'ERROR_FOR_DIVISION_BY_ZERO',
+ 'TRADITIONAL',
+ 'NO_AUTO_CREATE_USER',
+ 'HIGH_NOT_PRECEDENCE'
+ ) DEFAULT '' NOT NULL,
+ DEFAULT CHARACTER SET utf8;
+
+# Correct the character set and collation
+ALTER TABLE proc CONVERT TO CHARACTER SET utf8;
+# Reset some fields after the conversion
+ALTER TABLE proc MODIFY db
+ char(64) collate utf8_bin DEFAULT '' NOT NULL,
+ MODIFY definer
+ char(77) collate utf8_bin DEFAULT '' NOT NULL,
+ MODIFY comment
+ char(64) collate utf8_bin DEFAULT '' NOT NULL;
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index 8dd95da11e3..33db1eae82a 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -3,7 +3,7 @@
# For a more info consult the file COPYRIGHT distributed with this file.
# This scripts creates the privilege tables db, host, user, tables_priv,
-# columns_priv in the mysql database, as well as the func table.
+# columns_priv, procs_priv in the mysql database, as well as the func table.
#
# All unrecognized arguments to this script are passed to mysqld.
diff --git a/scripts/mysql_tableinfo.sh b/scripts/mysql_tableinfo.sh
index f5083a776c6..2ed7e381fa3 100644
--- a/scripts/mysql_tableinfo.sh
+++ b/scripts/mysql_tableinfo.sh
@@ -6,6 +6,14 @@ use DBI;
=head1 NAME
+WARNING: MySQL versions 5.0 and above feature the INFORMATION_SCHEMA
+pseudo-database which contains always up-to-date metadata information
+about all tables. So instead of using this script one can now
+simply query the INFORMATION_SCHEMA.SCHEMATA, INFORMATION_SCHEMA.TABLES,
+INFORMATION_SCHEMA.COLUMNS, INFORMATION_SCHEMA.STATISTICS pseudo-tables.
+Please see the MySQL manual for more information about INFORMATION_SCHEMA.
+This script will be removed from the MySQL distribution in version 5.1.
+
mysql_tableinfo - creates and populates information tables with
the output of SHOW DATABASES, SHOW TABLES (or SHOW TABLE STATUS),
SHOW COLUMNS and SHOW INDEX.
@@ -62,6 +70,19 @@ GetOptions( \%opt,
"quiet|q",
) or usage("Invalid option");
+if (!$opt{'quiet'})
+ {
+ print <<EOF
+WARNING: MySQL versions 5.0 and above feature the INFORMATION_SCHEMA
+pseudo-database which contains always up-to-date metadata information
+about all tables. So instead of using this script one can now
+simply query the INFORMATION_SCHEMA.SCHEMATA, INFORMATION_SCHEMA.TABLES,
+INFORMATION_SCHEMA.COLUMNS, INFORMATION_SCHEMA.STATISTICS pseudo-tables.
+Please see the MySQL manual for more information about INFORMATION_SCHEMA.
+This script will be removed from the MySQL distribution in version 5.1.
+EOF
+ }
+
if ($opt{'help'}) {usage();}
my ($db_to_write,$db_like_wild,$tbl_like_wild);
@@ -104,7 +125,7 @@ $tbl_like_wild=$dbh->quote($tbl_like_wild);
if (!$opt{'quiet'})
{
- print "\n!! This program is doing to do:\n\n";
+ print "\n!! This program is going to do:\n\n";
print "**DROP** TABLE ...\n" if ($opt{'clear'} or $opt{'clear-only'});
print "**DELETE** FROM ... WHERE `Database` LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild
**INSERT** INTO ...
@@ -456,17 +477,14 @@ UNIX domain socket to use when connecting to server
=head1 WARRANTY
-This software is free and comes without warranty of any kind. You
-should never trust backup software without studying the code yourself.
-Study the code inside this script and only rely on it if I<you> believe
-that it does the right thing for you.
+This software is free and comes without warranty of any kind.
Patches adding bug fixes, documentation and new features are welcome.
=head1 TO DO
-Use extended inserts to be faster (for servers with many databases
-or tables). But to do that, must care about net-buffer-length.
+Nothing: starting from MySQL 5.0, this program is replaced by the
+INFORMATION_SCHEMA pseudo-database.
=head1 AUTHOR
diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh
index 7fff4cbb731..098cd894916 100644
--- a/scripts/mysqld_multi.sh
+++ b/scripts/mysqld_multi.sh
@@ -4,7 +4,7 @@ use Getopt::Long;
use POSIX qw(strftime);
$|=1;
-$VER="2.11";
+$VER="2.14";
$opt_config_file = undef();
$opt_example = 0;
@@ -37,13 +37,13 @@ main();
sub main
{
- my ($flag_exit);
+ my $flag_exit= 0;
if (!defined(my_which(my_print_defaults)))
{
# We can't throw out yet, since --version, --help, or --example may
# have been given
- print "WARNING! my_print_defaults command not found!\n";
+ print "WARNING: my_print_defaults command not found.\n";
print "Please make sure you have this command available and\n";
print "in your path. The command is available from the latest\n";
print "MySQL distribution.\n";
@@ -66,6 +66,11 @@ sub main
else
{
$opt_config_file= $1;
+ if (!($opt_config_file =~ m/\//))
+ {
+ # No path. Use current working directory
+ $opt_config_file= "./" . $opt_config_file;
+ }
}
}
}
@@ -76,10 +81,18 @@ sub main
chop @defops;
splice @ARGV, 0, 0, @defops;
}
- GetOptions("help","example","version","mysqld=s","mysqladmin=s",
- "config-file=s","user=s","password=s","log=s","no-log","tcp-ip",
- "silent","verbose")
- || die "Wrong option! See $my_progname --help for detailed information!\n";
+ if (!GetOptions("help","example","version","mysqld=s","mysqladmin=s",
+ "config-file=s","user=s","password=s","log=s","no-log",
+ "tcp-ip", "silent","verbose"))
+ {
+ $flag_exit= 1;
+ }
+ if (defined($opt_config_file) && !($opt_config_file =~ m/\//))
+ {
+ # No path. Use current working directory
+ $opt_config_file= "./" . $opt_config_file;
+ }
+ usage() if ($opt_help);
if ($opt_verbose && $opt_silent)
{
@@ -95,15 +108,14 @@ sub main
exit(0);
}
example() if ($opt_example);
- usage() if ($opt_help);
if ($flag_exit)
{
- print "Error with an option, see $my_progname --help for more info!\n";
+ print "Error with an option, see $my_progname --help for more info.\n";
exit(1);
}
if (!defined(my_which(my_print_defaults)))
{
- print "ABORT: Can't find command 'my_print_defaults'!\n";
+ print "ABORT: Can't find command 'my_print_defaults'.\n";
print "This command is available from the latest MySQL\n";
print "distribution. Please make sure you have the command\n";
print "in your PATH.\n";
@@ -157,6 +169,31 @@ sub main
}
####
+#### Quote option argument. Add double quotes around the argument
+#### and escape the following: $, \, "
+#### This function is needed, because my_print_defaults drops possible
+#### quotes, single or double, from in front of an argument and from
+#### the end.
+####
+
+sub quote_opt_arg
+{
+ my ($option)= @_;
+
+ if ($option =~ m/(\-\-[a-zA-Z0-9\_\-]+)=(.*)/)
+ {
+ $option= $1;
+ $arg= $2;
+ $arg=~ s/\\/\\\\/g; # Escape escape character first to avoid doubling.
+ $arg=~ s/\$/\\\$/g;
+ $arg=~ s/\"/\\\"/g;
+ $arg= "\"" . $arg . "\"";
+ $option= $option . "=" . $arg;
+ }
+ return $option;
+}
+
+####
#### Init log file. Check for appropriate place for log file, in the following
#### order my_print_defaults mysqld datadir, @datadir@, /var/log, /tmp
####
@@ -289,10 +326,9 @@ sub start_mysqlds()
}
else
{
- # we single-quote the argument, but first convert single-quotes to
- # '"'"' so they are passed through correctly
- $options[$j]=~ s/'/'"'"'/g;
- $tmp.= " '$options[$j]'";
+ $options[$j]=~ s/;/\\;/g;
+ $options[$j]= quote_opt_arg($options[$j]);
+ $tmp.= " $options[$j]";
}
}
if ($opt_verbose && $com =~ m/\/safe_mysqld$/ && !$info_sent)
@@ -437,6 +473,16 @@ sub find_groups
{
$data[$i] = $line;
}
+ if (defined($ENV{MYSQL_HOME}) && -f "$ENV{MYSQL_HOME}/my.cnf" &&
+ -r "$ENV{MYSQL_HOME}/my.cnf")
+ {
+ open(MY_CNF, "<$ENV{MYSQL_HOME}/my.cnf") && (@tmp=<MY_CNF>) &&
+ close(MY_CNF);
+ }
+ for (; ($line = shift @tmp); $i++)
+ {
+ $data[$i] = $line;
+ }
if (-f "$homedir/.my.cnf" && -r "$homedir/.my.cnf")
{
open(MY_CNF, "<$homedir/.my.cnf") && (@tmp=<MY_CNF>) && close(MY_CNF);
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index d6585f4a552..873aff251db 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -23,6 +23,29 @@ case "$1" in
;;
esac
+usage () {
+ cat <<EOF
+Usage: $0 [OPTIONS]
+ --no-defaults Don't read the system defaults file
+ --defaults-file=FILE Use the specified defaults file
+ --defaults-extra-file=FILE Also use defaults from the specified file
+ --ledir=DIRECTORY Look for mysqld in the specified directory
+ --log-error=FILE Log errors to the specified log file
+ --open-files-limit=LIMIT Limit the number of open files
+ --core-file-size=LIMIT Limit core files to the specified size
+ --timezone=TZ Set the system timezone
+ --mysqld=FILE Use the specified file as mysqld
+ --mysqld-version=VERSION Use "mysqld-VERSION" as mysqld
+ --nice=NICE Set the scheduling priority of mysqld
+ --skip-kill-mysqld Don't try to kill stray mysqld processes
+
+All other options are passed to the mysqld program.
+
+EOF
+ exit 1
+}
+
+
parse_arguments() {
# We only need to pass arguments through to the server if we don't
# handle them here. So, we collect unrecognized options (passed on
@@ -52,11 +75,7 @@ parse_arguments() {
# mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])!
--ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;;
- # err-log should be removed in 5.0
- --err-log=*) err_log=`echo "$arg" | sed -e "s;--err-log=;;"` ;;
--log-error=*) err_log=`echo "$arg" | sed -e "s;--log-error=;;"` ;;
- # QQ The --open-files should be removed in 5.0
- --open-files=*) open_files=`echo "$arg" | sed -e "s;--open-files=;;"` ;;
--open-files-limit=*) open_files=`echo "$arg" | sed -e "s;--open-files-limit=;;"` ;;
--core-file-size=*) core_file_size=`echo "$arg" | sed -e "s;--core-file-size=;;"` ;;
--timezone=*) TZ=`echo "$arg" | sed -e "s;--timezone=;;"` ; export TZ; ;;
@@ -71,6 +90,9 @@ parse_arguments() {
fi
;;
--nice=*) niceness=`echo "$arg" | sed -e "s;--nice=;;"` ;;
+ --help)
+ usage
+ ;;
*)
if test -n "$pick_args"
then
@@ -114,7 +136,7 @@ fi
if test -d $MY_BASEDIR_VERSION/data/mysql
then
DATADIR=$MY_BASEDIR_VERSION/data
- if test -z "$defaults"
+ if test -z "$defaults" -a -r "$DATADIR/my.cnf"
then
defaults="--defaults-extra-file=$DATADIR/my.cnf"
fi
@@ -127,6 +149,28 @@ else
DATADIR=@localstatedir@
fi
+if test -z "$MYSQL_HOME"
+then
+ if test -r "$MY_BASEDIR_VERSION/my.cnf" && test -r "$DATADIR/my.cnf"
+ then
+ echo "WARNING: Found two instances of my.cnf -"
+ echo "$MY_BASEDIR_VERSION/my.cnf and"
+ echo "$DATADIR/my.cnf"
+ echo "IGNORING $DATADIR/my.cnf"
+ echo
+ MYSQL_HOME=$MY_BASEDIR_VERSION
+ elif test -r "$DATADIR/my.cnf"
+ then
+ echo "WARNING: Found $DATADIR/my.cnf"
+ echo "Datadir is deprecated place for my.cnf, please move it to $MY_BASEDIR_VERSION"
+ echo
+ MYSQL_HOME=$DATADIR
+ else
+ MYSQL_HOME=$MY_BASEDIR_VERSION
+ fi
+fi
+export MYSQL_HOME
+
user=@MYSQLD_USER@
niceness=0
diff --git a/server-tools/Makefile.am b/server-tools/Makefile.am
new file mode 100644
index 00000000000..ed316b9ac38
--- /dev/null
+++ b/server-tools/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS= instance-manager
diff --git a/server-tools/instance-manager/IMService.cpp b/server-tools/instance-manager/IMService.cpp
new file mode 100644
index 00000000000..b7ea8e7eb81
--- /dev/null
+++ b/server-tools/instance-manager/IMService.cpp
@@ -0,0 +1,82 @@
+#include <windows.h>
+#include <signal.h>
+#include "log.h"
+#include "options.h"
+#include "IMService.h"
+#include "manager.h"
+
+IMService::IMService(void)
+{
+ serviceName= "MySqlManager";
+ displayName= "MySQL Manager";
+ username= NULL;
+ password= NULL;
+}
+
+IMService::~IMService(void)
+{
+}
+
+void IMService::Stop()
+{
+ ReportStatus(SERVICE_STOP_PENDING);
+
+ // stop the IM work
+ raise(SIGTERM);
+}
+
+void IMService::Run(DWORD argc, LPTSTR *argv)
+{
+ // report to the SCM that we're about to start
+ ReportStatus((DWORD)SERVICE_START_PENDING);
+
+ Options o;
+ o.load(argc, argv);
+
+ // init goes here
+ ReportStatus((DWORD)SERVICE_RUNNING);
+
+ // wait for main loop to terminate
+ manager(o);
+ o.cleanup();
+}
+
+void IMService::Log(const char *msg)
+{
+ log_info(msg);
+}
+
+int HandleServiceOptions(Options options)
+{
+ int ret_val= 0;
+
+ IMService winService;
+
+ if (options.install_as_service)
+ {
+ if (winService.IsInstalled())
+ log_info("Service is already installed");
+ else if (winService.Install())
+ log_info("Service installed successfully");
+ else
+ {
+ log_info("Service failed to install");
+ ret_val= 1;
+ }
+ }
+ else if (options.remove_service)
+ {
+ if (! winService.IsInstalled())
+ log_info("Service is not installed");
+ else if (winService.Remove())
+ log_info("Service removed successfully");
+ else
+ {
+ log_info("Service failed to remove");
+ ret_val= 1;
+ }
+ }
+ else
+ ret_val= !winService.Init();
+ return ret_val;
+}
diff --git a/server-tools/instance-manager/IMService.h b/server-tools/instance-manager/IMService.h
new file mode 100644
index 00000000000..cad38bebdaf
--- /dev/null
+++ b/server-tools/instance-manager/IMService.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "windowsservice.h"
+
+class IMService : public WindowsService
+{
+public:
+ IMService(void);
+ ~IMService(void);
+
+protected:
+ void Log(const char *msg);
+ void Stop();
+ void Run(DWORD argc, LPTSTR *argv);
+};
diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am
new file mode 100644
index 00000000000..b872adca09d
--- /dev/null
+++ b/server-tools/instance-manager/Makefile.am
@@ -0,0 +1,95 @@
+# 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
+
+INCLUDES= @ZLIB_INCLUDES@ -I$(top_srcdir)/include \
+ $(openssl_includes) -I$(top_builddir)/include
+
+DEFS= -DMYSQL_INSTANCE_MANAGER -DMYSQL_SERVER
+
+# As all autoconf variables depend from ${prefix} and being resolved only when
+# make is run, we can not put these defines to a header file (e.g. to
+# default_options.h, generated from default_options.h.in)
+# See automake/autoconf docs for details
+
+noinst_LIBRARIES= liboptions.a libnet.a
+
+liboptions_a_CXXFLAGS= $(CXXFLAGS) \
+ -DDEFAULT_PID_FILE_NAME="$(localstatedir)/mysqlmanager.pid" \
+ -DDEFAULT_LOG_FILE_NAME="$(localstatedir)/mysqlmanager.log" \
+ -DDEFAULT_SOCKET_FILE_NAME="/tmp/mysqlmanager.sock" \
+ -DDEFAULT_PASSWORD_FILE_NAME="$(sysconfdir)/mysqlmanager.passwd" \
+ -DDEFAULT_MYSQLD_PATH="$(libexecdir)/mysqld$(EXEEXT)" \
+ -DDEFAULT_MONITORING_INTERVAL="20" \
+ -DDEFAULT_PORT="2273" \
+ -DDEFAULT_CONFIG_FILE="/etc/my.cnf" \
+ -DPROTOCOL_VERSION=@PROTOCOL_VERSION@
+
+liboptions_a_SOURCES= options.h options.cc priv.h priv.cc
+liboptions_a_LIBADD= $(top_builddir)/libmysql/get_password.$(OBJEXT)
+
+# MySQL sometimes uses symlinks to reuse code
+# All symlinked files are grouped in libnet.a
+
+nodist_libnet_a_SOURCES= net_serv.cc client_settings.h
+libnet_a_LIBADD= $(top_builddir)/sql/password.$(OBJEXT) \
+ $(top_builddir)/sql/pack.$(OBJEXT) \
+ $(top_builddir)/sql/sql_state.$(OBJEXT) \
+ $(top_builddir)/sql/mini_client_errors.$(OBJEXT)\
+ $(top_builddir)/sql/client.$(OBJEXT)
+
+CLEANFILES= net_serv.cc client_settings.h
+
+net_serv.cc:
+ rm -f $(srcdir)/net_serv.cc
+ @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc $(srcdir)/net_serv.cc
+
+client_settings.h:
+ rm -f $(srcdir)/client_settings.h
+ @LN_CP_F@ $(top_srcdir)/sql/client_settings.h $(srcdir)/client_settings.h
+
+libexec_PROGRAMS= mysqlmanager
+
+mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \
+ manager.h manager.cc log.h log.cc \
+ thread_registry.h thread_registry.cc \
+ listener.h listener.cc protocol.h protocol.cc \
+ mysql_connection.h mysql_connection.cc \
+ user_map.h user_map.cc \
+ messages.h messages.cc \
+ commands.h commands.cc \
+ instance.h instance.cc \
+ instance_map.h instance_map.cc\
+ instance_options.h instance_options.cc \
+ buffer.h buffer.cc parse.cc parse.h \
+ guardian.cc guardian.h \
+ parse_output.cc parse_output.h \
+ mysql_manager_error.h \
+ portability.h
+
+mysqlmanager_LDADD= liboptions.a \
+ libnet.a \
+ $(top_builddir)/vio/libvio.a \
+ $(top_builddir)/mysys/libmysys.a \
+ $(top_builddir)/strings/libmystrings.a \
+ $(top_builddir)/dbug/libdbug.a \
+ @openssl_libs@ @ZLIB_LIBS@
+
+
+tags:
+ ctags -R *.h *.cc
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/server-tools/instance-manager/README b/server-tools/instance-manager/README
new file mode 100644
index 00000000000..ac799775003
--- /dev/null
+++ b/server-tools/instance-manager/README
@@ -0,0 +1,11 @@
+Instance Manager - manage MySQL instances locally and remotely.
+
+File description:
+ mysqlmanager.cc - entry point to the manager, main,
+ options.{h,cc} - handle startup options
+ manager.{h,cc} - manager process
+ mysql_connection.{h,cc} - handle one connection with mysql client.
+
+See also instance manager architecture description in mysqlmanager.cc.
+
+
diff --git a/server-tools/instance-manager/WindowsService.cpp b/server-tools/instance-manager/WindowsService.cpp
new file mode 100644
index 00000000000..192045b7a4c
--- /dev/null
+++ b/server-tools/instance-manager/WindowsService.cpp
@@ -0,0 +1,203 @@
+#include <windows.h>
+#include <assert.h>
+#include ".\windowsservice.h"
+
+static WindowsService *gService;
+
+WindowsService::WindowsService(void) :
+ statusCheckpoint(0),
+ serviceName(NULL),
+ inited(false),
+ dwAcceptedControls(SERVICE_ACCEPT_STOP),
+ debugging(false)
+{
+ gService= this;
+ status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
+ status.dwServiceSpecificExitCode= 0;
+}
+
+WindowsService::~WindowsService(void)
+{
+}
+
+BOOL WindowsService::Install()
+{
+ bool ret_val= false;
+ SC_HANDLE newService;
+ SC_HANDLE scm;
+
+ if (IsInstalled()) return true;
+
+ // determine the name of the currently executing file
+ char szFilePath[_MAX_PATH];
+ GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
+
+ // open a connection to the SCM
+ if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
+ return false;
+
+ newService= CreateService(scm, serviceName, displayName,
+ SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
+ szFilePath, NULL, NULL, NULL, username,
+ password);
+
+ if (newService)
+ {
+ CloseServiceHandle(newService);
+ ret_val= true;
+ }
+
+ CloseServiceHandle(scm);
+ return ret_val;
+}
+
+BOOL WindowsService::Init()
+{
+ assert(serviceName != NULL);
+
+ if (inited) return true;
+
+ SERVICE_TABLE_ENTRY stb[] =
+ {
+ { (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
+ { NULL, NULL }
+ };
+ inited= true;
+ return StartServiceCtrlDispatcher(stb); //register with the Service Manager
+}
+
+BOOL WindowsService::Remove()
+{
+ bool ret_val= false;
+
+ if (! IsInstalled())
+ return true;
+
+ // open a connection to the SCM
+ SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
+ if (! scm)
+ return false;
+
+ SC_HANDLE service= OpenService(scm, serviceName, DELETE);
+ if (service)
+ {
+ if (DeleteService(service))
+ ret_val= true;
+ DWORD dw= ::GetLastError();
+ CloseServiceHandle(service);
+ }
+
+ CloseServiceHandle(scm);
+ return ret_val;
+}
+
+BOOL WindowsService::IsInstalled()
+{
+ BOOL ret_val= FALSE;
+
+ SC_HANDLE scm= ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+ SC_HANDLE serv_handle= ::OpenService(scm, serviceName, SERVICE_QUERY_STATUS);
+
+ ret_val= serv_handle != NULL;
+
+ ::CloseServiceHandle(serv_handle);
+ ::CloseServiceHandle(scm);
+
+ return ret_val;
+}
+
+void WindowsService::SetAcceptedControls(DWORD acceptedControls)
+{
+ dwAcceptedControls= acceptedControls;
+}
+
+
+BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint,
+ DWORD dwError)
+{
+ if(debugging) return TRUE;
+
+ if(currentState == SERVICE_START_PENDING)
+ status.dwControlsAccepted= 0;
+ else
+ status.dwControlsAccepted= dwAcceptedControls;
+
+ status.dwCurrentState= currentState;
+ status.dwWin32ExitCode= dwError != 0 ?
+ ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR;
+ status.dwWaitHint= waitHint;
+ status.dwServiceSpecificExitCode= dwError;
+
+ if(currentState == SERVICE_RUNNING || currentState == SERVICE_STOPPED)
+ {
+ status.dwCheckPoint= 0;
+ statusCheckpoint= 0;
+ }
+ else
+ status.dwCheckPoint= ++statusCheckpoint;
+
+ // Report the status of the service to the service control manager.
+ BOOL result= SetServiceStatus(statusHandle, &status);
+ if (!result)
+ Log("ReportStatus failed");
+
+ return result;
+}
+
+void WindowsService::RegisterAndRun(DWORD argc, LPTSTR *argv)
+{
+ statusHandle= ::RegisterServiceCtrlHandler(serviceName, ControlHandler);
+ if (statusHandle && ReportStatus(SERVICE_START_PENDING))
+ Run(argc, argv);
+ ReportStatus(SERVICE_STOPPED);
+}
+
+void WindowsService::HandleControlCode(DWORD opcode)
+{
+ // Handle the requested control code.
+ switch(opcode) {
+ case SERVICE_CONTROL_STOP:
+ // Stop the service.
+ status.dwCurrentState= SERVICE_STOP_PENDING;
+ Stop();
+ break;
+
+ case SERVICE_CONTROL_PAUSE:
+ status.dwCurrentState= SERVICE_PAUSE_PENDING;
+ Pause();
+ break;
+
+ case SERVICE_CONTROL_CONTINUE:
+ status.dwCurrentState= SERVICE_CONTINUE_PENDING;
+ Continue();
+ break;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ Shutdown();
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ ReportStatus(status.dwCurrentState);
+ break;
+
+ default:
+ // invalid control code
+ break;
+ }
+}
+
+void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
+{
+ assert(gService != NULL);
+
+ // register our service control handler:
+ gService->RegisterAndRun(argc, argv);
+}
+
+void WINAPI WindowsService::ControlHandler(DWORD opcode)
+{
+ assert(gService != NULL);
+
+ return gService->HandleControlCode(opcode);
+}
diff --git a/server-tools/instance-manager/WindowsService.h b/server-tools/instance-manager/WindowsService.h
new file mode 100644
index 00000000000..1a034ce1351
--- /dev/null
+++ b/server-tools/instance-manager/WindowsService.h
@@ -0,0 +1,43 @@
+#pragma once
+
+class WindowsService
+{
+protected:
+ bool inited;
+ const char *serviceName;
+ const char *displayName;
+ const char *username;
+ const char *password;
+ SERVICE_STATUS_HANDLE statusHandle;
+ DWORD statusCheckpoint;
+ SERVICE_STATUS status;
+ DWORD dwAcceptedControls;
+ bool debugging;
+
+public:
+ WindowsService(void);
+ ~WindowsService(void);
+
+ BOOL Install();
+ BOOL Remove();
+ BOOL Init();
+ BOOL IsInstalled();
+ void SetAcceptedControls(DWORD acceptedControls);
+ void Debug(bool debugFlag) { debugging= debugFlag; }
+
+public:
+ static void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
+ static void WINAPI ControlHandler(DWORD CtrlType);
+
+protected:
+ virtual void Run(DWORD argc, LPTSTR *argv)= 0;
+ virtual void Stop() {}
+ virtual void Shutdown() {}
+ virtual void Pause() {}
+ virtual void Continue() {}
+ virtual void Log(const char *msg) {}
+
+ BOOL ReportStatus(DWORD currentStatus, DWORD waitHint= 3000, DWORD dwError=0);
+ void HandleControlCode(DWORD opcode);
+ void RegisterAndRun(DWORD argc, LPTSTR *argv);
+};
diff --git a/server-tools/instance-manager/buffer.cc b/server-tools/instance-manager/buffer.cc
new file mode 100644
index 00000000000..26df401c3c5
--- /dev/null
+++ b/server-tools/instance-manager/buffer.cc
@@ -0,0 +1,109 @@
+/* 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 implementation
+#endif
+
+#include "buffer.h"
+#include <m_string.h>
+
+
+/*
+ Puts the given string to the buffer.
+
+ SYNOPSYS
+ append()
+ position start position in the buffer
+ string string to be put in the buffer
+ len_arg the length of the string. This way we can avoid some
+ strlens.
+
+ DESCRIPTION
+
+ The method puts a string into the buffer, starting from position .
+ In the case when the buffer is too small it reallocs the buffer. The
+ total size of the buffer is restricted with 16.
+
+ RETURN
+ 0 - ok
+ 1 - got an error in reserve()
+*/
+
+int Buffer::append(uint position, const char *string, uint len_arg)
+{
+ if (reserve(position, len_arg))
+ return 1;
+
+ strnmov(buffer + position, string, len_arg);
+ return 0;
+}
+
+
+/*
+ Checks whether the current buffer size is ok to put a string of the length
+ "len_arg" starting from "position" and reallocs it if no.
+
+ SYNOPSYS
+ reserve()
+ position the number starting byte on the buffer to store a buffer
+ len_arg the length of the string.
+
+ DESCRIPTION
+
+ The method checks whether it is possible to put a string of the "len_arg"
+ length into the buffer, starting from "position" byte. In the case when the
+ buffer is too small it reallocs the buffer. The total size of the buffer is
+ restricted with 16 Mb.
+
+ RETURN
+ 0 - ok
+ 1 - realloc error or we have come to the 16Mb barrier
+*/
+
+int Buffer::reserve(uint position, uint len_arg)
+{
+ if (position + len_arg >= MAX_BUFFER_SIZE)
+ goto err;
+
+ if (position + len_arg >= buffer_size)
+ {
+ buffer= (char*) my_realloc(buffer,
+ min(MAX_BUFFER_SIZE,
+ max((uint) (buffer_size*1.5),
+ position + len_arg)), MYF(0));
+ if (!(buffer))
+ goto err;
+ buffer_size= (uint) (buffer_size*1.5);
+ }
+ return 0;
+
+err:
+ error= 1;
+ return 1;
+}
+
+
+int Buffer::get_size()
+{
+ return buffer_size;
+}
+
+
+int Buffer::is_error()
+{
+ return error;
+}
diff --git a/server-tools/instance-manager/buffer.h b/server-tools/instance-manager/buffer.h
new file mode 100644
index 00000000000..e63d725f508
--- /dev/null
+++ b/server-tools/instance-manager/buffer.h
@@ -0,0 +1,66 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_BUFFER_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_BUFFER_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include <my_sys.h>
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+/*
+ This class is a simple implementation of the buffer of varying size.
+ It is used to store MySQL client-server protocol packets. This is why
+ the maximum buffer size if 16Mb. (See internals manual section
+ 7. MySQL Client/Server Protocol)
+*/
+
+class Buffer
+{
+private:
+ enum { BUFFER_INITIAL_SIZE= 4096 };
+ /* maximum buffer size is 16Mb */
+ enum { MAX_BUFFER_SIZE= 16777216 };
+ size_t buffer_size;
+ /* Error flag. Triggered if we get an error of some kind */
+ int error;
+public:
+ Buffer(size_t buffer_size_arg= BUFFER_INITIAL_SIZE)
+ :buffer_size(buffer_size_arg), error(0)
+ {
+ /*
+ As append() will invokes realloc() anyway, it's ok if malloc returns 0
+ */
+ if (!(buffer= (char*) my_malloc(buffer_size, MYF(0))))
+ buffer_size= 0;
+ }
+
+ ~Buffer()
+ {
+ my_free(buffer, MYF(0));
+ }
+
+public:
+ char *buffer;
+ int get_size();
+ int is_error();
+ int append(uint position, const char *string, uint len_arg);
+ int reserve(uint position, uint len_arg);
+};
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_BUFFER_H */
diff --git a/ndb/include/ndb_types.h b/server-tools/instance-manager/command.cc
index 6cf9bb40d7f..73dd49ef8b8 100644
--- a/ndb/include/ndb_types.h
+++ b/server-tools/instance-manager/command.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* 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
@@ -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 */
-/**
- * @file ndb_types.h
- */
+#ifdef __GNUC__
+#pragma implementation
+#endif
-#ifndef NDB_TYPES_H
-#define NDB_TYPES_H
+#include "command.h"
-#include "ndb_global.h"
-#endif
+Command::Command(Instance_map *instance_map_arg)
+ :instance_map(instance_map_arg)
+{}
+
+Command::~Command()
+{}
+
diff --git a/server-tools/instance-manager/command.h b/server-tools/instance-manager/command.h
new file mode 100644
index 00000000000..8ae4e33b92f
--- /dev/null
+++ b/server-tools/instance-manager/command.h
@@ -0,0 +1,47 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_COMMAND_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_COMMAND_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include <my_global.h>
+
+/* Class responsible for allocation of im commands. */
+
+class Instance_map;
+
+/*
+ Command - entry point for any command.
+ GangOf4: 'Command' design pattern
+*/
+
+class Command
+{
+public:
+ Command(Instance_map *instance_map_arg= 0);
+ virtual ~Command();
+
+ /* method of executing: */
+ virtual int execute(struct st_net *net, ulong connection_id) = 0;
+
+protected:
+ Instance_map *instance_map;
+};
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMAND_H */
diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc
new file mode 100644
index 00000000000..1cf888eab45
--- /dev/null
+++ b/server-tools/instance-manager/commands.cc
@@ -0,0 +1,794 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "commands.h"
+
+#include "instance_map.h"
+#include "messages.h"
+#include "mysqld_error.h"
+#include "mysql_manager_error.h"
+#include "protocol.h"
+#include "buffer.h"
+#include "options.h"
+
+#include <m_string.h>
+#include <mysql.h>
+#include <my_dir.h>
+
+
+/*
+ Add a string to a buffer
+
+ SYNOPSYS
+ put_to_buff()
+ buff buffer to add the string
+ str string to add
+ uint offset in the buff to add a string
+
+ DESCRIPTION
+
+ Function to add a string to the buffer. It is different from
+ store_to_protocol_packet, which is used in the protocol.cc. The last
+ one also stores the length of the string in a special way.
+ This is required for MySQL client/server protocol support only.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+
+static inline int put_to_buff(Buffer *buff, const char *str, uint *position)
+{
+ uint len= strlen(str);
+ if (buff->append(*position, str, len))
+ return 1;
+
+ *position+= len;
+ return 0;
+}
+
+
+/* implementation for Show_instances: */
+
+
+/*
+ The method sends a list of instances in the instance map to the client.
+
+ SYNOPSYS
+ Show_instances::execute()
+ net The network connection to the client.
+ connection_id Client connection ID
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Show_instances::execute(struct st_net *net, ulong connection_id)
+{
+ Buffer send_buff; /* buffer for packets */
+ LIST name, status;
+ NAME_WITH_LENGTH name_field, status_field;
+ LIST *field_list;
+ uint position=0;
+
+ name_field.name= (char*) "instance_name";
+ name_field.length= DEFAULT_FIELD_LENGTH;
+ name.data= &name_field;
+ status_field.name= (char*) "status";
+ status_field.length= DEFAULT_FIELD_LENGTH;
+ status.data= &status_field;
+ field_list= list_add(NULL, &status);
+ field_list= list_add(field_list, &name);
+
+ send_fields(net, field_list);
+
+ {
+ Instance *instance;
+ Instance_map::Iterator iterator(instance_map);
+
+ instance_map->lock();
+ while ((instance= iterator.next()))
+ {
+ position= 0;
+ store_to_protocol_packet(&send_buff, instance->options.instance_name,
+ &position);
+ if (instance->is_running())
+ store_to_protocol_packet(&send_buff, (char*) "online", &position);
+ else
+ store_to_protocol_packet(&send_buff, (char*) "offline", &position);
+ if (my_net_write(net, send_buff.buffer, (uint) position))
+ goto err;
+ }
+ instance_map->unlock();
+ }
+ if (send_eof(net))
+ goto err;
+ if (net_flush(net))
+ goto err;
+
+ return 0;
+err:
+ return ER_OUT_OF_RESOURCES;
+}
+
+
+/* implementation for Flush_instances: */
+
+int Flush_instances::execute(struct st_net *net, ulong connection_id)
+{
+ if (instance_map->flush_instances() ||
+ net_send_ok(net, connection_id, NULL))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+/* implementation for Show_instance_status: */
+
+Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
+ const char *name, uint len)
+ :Command(instance_map_arg)
+{
+ Instance *instance;
+
+ /* we make a search here, since we don't want to store the name */
+ if ((instance= instance_map->find(name, len)))
+ instance_name= instance->options.instance_name;
+ else
+ instance_name= NULL;
+}
+
+
+/*
+ The method sends a table with a status of requested instance to the client.
+
+ SYNOPSYS
+ Show_instance_status::do_command()
+ net The network connection to the client.
+ instance_name The name of the instance.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+
+int Show_instance_status::execute(struct st_net *net,
+ ulong connection_id)
+{
+ enum { MAX_VERSION_LENGTH= 40 };
+ Buffer send_buff; /* buffer for packets */
+ LIST name, status, version;
+ LIST *field_list;
+ NAME_WITH_LENGTH name_field, status_field, version_field;
+ uint position=0;
+
+ if (!instance_name)
+ return ER_BAD_INSTANCE_NAME;
+
+ /* create list of the fileds to be passed to send_fields */
+ name_field.name= (char*) "instance_name";
+ name_field.length= DEFAULT_FIELD_LENGTH;
+ name.data= &name_field;
+ status_field.name= (char*) "status";
+ status_field.length= DEFAULT_FIELD_LENGTH;
+ status.data= &status_field;
+ version_field.name= (char*) "version";
+ version_field.length= MAX_VERSION_LENGTH;
+ version.data= &version_field;
+ field_list= list_add(NULL, &version);
+ field_list= list_add(field_list, &status);
+ field_list= list_add(field_list, &name);
+
+ send_fields(net, field_list);
+
+ {
+ Instance *instance;
+
+ store_to_protocol_packet(&send_buff, (char*) instance_name, &position);
+ if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
+ goto err;
+ if (instance->is_running())
+ store_to_protocol_packet(&send_buff, (char*) "online", &position);
+ else
+ store_to_protocol_packet(&send_buff, (char*) "offline", &position);
+
+ if (instance->options.mysqld_version)
+ store_to_protocol_packet(&send_buff, instance->options.mysqld_version,
+ &position);
+ else
+ store_to_protocol_packet(&send_buff, (char*) "unknown", &position);
+
+
+ if (send_buff.is_error() ||
+ my_net_write(net, send_buff.buffer, (uint) position))
+ goto err;
+ }
+
+ if (send_eof(net) || net_flush(net))
+ goto err;
+
+ return 0;
+
+err:
+ return ER_OUT_OF_RESOURCES;
+}
+
+
+/* Implementation for Show_instance_options */
+
+Show_instance_options::Show_instance_options(Instance_map *instance_map_arg,
+ const char *name, uint len):
+ Command(instance_map_arg)
+{
+ Instance *instance;
+
+ /* we make a search here, since we don't want to store the name */
+ if ((instance= instance_map->find(name, len)))
+ instance_name= instance->options.instance_name;
+ else
+ instance_name= NULL;
+}
+
+
+int Show_instance_options::execute(struct st_net *net, ulong connection_id)
+{
+ Buffer send_buff; /* buffer for packets */
+ LIST name, option;
+ LIST *field_list;
+ NAME_WITH_LENGTH name_field, option_field;
+ uint position=0;
+
+ if (!instance_name)
+ return ER_BAD_INSTANCE_NAME;
+
+ /* create list of the fileds to be passed to send_fields */
+ name_field.name= (char*) "option_name";
+ name_field.length= DEFAULT_FIELD_LENGTH;
+ name.data= &name_field;
+ option_field.name= (char*) "value";
+ option_field.length= DEFAULT_FIELD_LENGTH;
+ option.data= &option_field;
+ field_list= list_add(NULL, &option);
+ field_list= list_add(field_list, &name);
+
+ send_fields(net, field_list);
+
+ {
+ Instance *instance;
+
+ if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
+ goto err;
+ store_to_protocol_packet(&send_buff, (char*) "instance_name", &position);
+ store_to_protocol_packet(&send_buff, (char*) instance_name, &position);
+ if (my_net_write(net, send_buff.buffer, (uint) position))
+ goto err;
+ if ((instance->options.mysqld_path))
+ {
+ position= 0;
+ store_to_protocol_packet(&send_buff, (char*) "mysqld-path", &position);
+ store_to_protocol_packet(&send_buff,
+ (char*) instance->options.mysqld_path,
+ &position);
+ if (send_buff.is_error() ||
+ my_net_write(net, send_buff.buffer, (uint) position))
+ goto err;
+ }
+
+ if ((instance->options.nonguarded))
+ {
+ position= 0;
+ store_to_protocol_packet(&send_buff, (char*) "nonguarded", &position);
+ store_to_protocol_packet(&send_buff, "", &position);
+ if (send_buff.is_error() ||
+ my_net_write(net, send_buff.buffer, (uint) position))
+ goto err;
+ }
+
+ /* loop through the options stored in DYNAMIC_ARRAY */
+ for (uint i= 0; i < instance->options.options_array.elements; i++)
+ {
+ char *tmp_option, *option_value;
+ get_dynamic(&(instance->options.options_array), (gptr) &tmp_option, i);
+ option_value= strchr(tmp_option, '=');
+ /* split the option string into two parts if it has a value */
+
+ position= 0;
+ if (option_value != NULL)
+ {
+ *option_value= 0;
+ store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
+ store_to_protocol_packet(&send_buff, option_value + 1, &position);
+ /* join name and the value into the same option again */
+ *option_value= '=';
+ }
+ else
+ {
+ store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
+ store_to_protocol_packet(&send_buff, "", &position);
+ }
+
+ if (send_buff.is_error() ||
+ my_net_write(net, send_buff.buffer, (uint) position))
+ goto err;
+ }
+ }
+
+ if (send_eof(net) || net_flush(net))
+ goto err;
+
+ return 0;
+
+err:
+ return ER_OUT_OF_RESOURCES;
+}
+
+
+/* Implementation for Start_instance */
+
+Start_instance::Start_instance(Instance_map *instance_map_arg,
+ const char *name, uint len)
+ :Command(instance_map_arg)
+{
+ /* we make a search here, since we don't want to store the name */
+ if ((instance= instance_map->find(name, len)))
+ instance_name= instance->options.instance_name;
+}
+
+
+int Start_instance::execute(struct st_net *net, ulong connection_id)
+{
+ uint err_code;
+ if (instance == 0)
+ return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
+ else
+ {
+ if ((err_code= instance->start()))
+ return err_code;
+
+ if (!(instance->options.nonguarded))
+ instance_map->guardian->guard(instance);
+
+ net_send_ok(net, connection_id, "Instance started");
+ return 0;
+ }
+}
+
+
+/* implementation for Show_instance_log: */
+
+Show_instance_log::Show_instance_log(Instance_map *instance_map_arg,
+ const char *name, uint len,
+ Log_type log_type_arg,
+ const char *size_arg,
+ const char *offset_arg)
+ :Command(instance_map_arg)
+{
+ Instance *instance;
+
+ if (offset_arg != NULL)
+ offset= atoi(offset_arg);
+ else
+ offset= 0;
+ size= atoi(size_arg);
+ log_type= log_type_arg;
+
+ /* we make a search here, since we don't want to store the name */
+ if ((instance= instance_map->find(name, len)))
+ instance_name= instance->options.instance_name;
+ else
+ instance_name= NULL;
+}
+
+
+
+/*
+ Open the logfile, read requested part of the log and send the info
+ to the client.
+
+ SYNOPSYS
+ Show_instance_log::execute()
+ net The network connection to the client.
+ connection_id Client connection ID
+
+ DESCRIPTION
+
+ Send a table with the content of the log requested. The function also
+ deals with errro handling, to be verbose.
+
+ RETURN
+ ER_OFFSET_ERROR We were requested to read negative number of bytes
+ from the log
+ ER_NO_SUCH_LOG The kind log being read is not enabled in the instance
+ ER_GUESS_LOGFILE IM wasn't able to figure out the log placement, while
+ it is enabled. Probably user should specify the path
+ to the logfile explicitly.
+ ER_OPEN_LOGFILE Cannot open the logfile
+ ER_READ_FILE Cannot read the logfile
+ ER_OUT_OF_RESOURCES We weren't able to allocate some resources
+*/
+
+int Show_instance_log::execute(struct st_net *net, ulong connection_id)
+{
+ Buffer send_buff; /* buffer for packets */
+ LIST name;
+ LIST *field_list;
+ NAME_WITH_LENGTH name_field;
+ uint position= 0;
+
+ /* create list of the fileds to be passed to send_fields */
+ name_field.name= (char*) "Log";
+ name_field.length= DEFAULT_FIELD_LENGTH;
+ name.data= &name_field;
+ field_list= list_add(NULL, &name);
+
+ if (!instance_name)
+ return ER_BAD_INSTANCE_NAME;
+
+ /* cannot read negative number of bytes */
+ if (offset > size)
+ return ER_OFFSET_ERROR;
+
+ send_fields(net, field_list);
+
+ {
+ Instance *instance;
+ const char *logpath;
+ File fd;
+
+ if ((instance= instance_map->find(instance_name,
+ strlen(instance_name))) == NULL)
+ goto err;
+
+ logpath= instance->options.logs[log_type];
+
+ /* Instance has no such log */
+ if (logpath == NULL)
+ return ER_NO_SUCH_LOG;
+
+ if (*logpath == '\0')
+ return ER_GUESS_LOGFILE;
+
+
+ if ((fd= my_open(logpath, O_RDONLY | O_BINARY, MYF(MY_WME))) >= 0)
+ {
+ size_t buff_size;
+ int read_len;
+ /* calculate buffer size */
+ MY_STAT file_stat;
+ Buffer read_buff;
+
+ /* my_fstat doesn't use the flag parameter */
+ if (my_fstat(fd, &file_stat, MYF(0)))
+ goto err;
+
+ buff_size= (size - offset);
+
+ read_buff.reserve(0, buff_size);
+
+ /* read in one chunk */
+ read_len= my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0));
+
+ if ((read_len= my_read(fd, (byte*) read_buff.buffer,
+ buff_size, MYF(0))) < 0)
+ return ER_READ_FILE;
+ store_to_protocol_packet(&send_buff, read_buff.buffer,
+ &position, read_len);
+ close(fd);
+ }
+ else
+ return ER_OPEN_LOGFILE;
+
+ if (my_net_write(net, send_buff.buffer, (uint) position))
+ goto err;
+ }
+
+ if (send_eof(net) || net_flush(net))
+ goto err;
+
+ return 0;
+
+err:
+ return ER_OUT_OF_RESOURCES;
+}
+
+
+/* implementation for Show_instance_log_files: */
+
+Show_instance_log_files::Show_instance_log_files
+ (Instance_map *instance_map_arg, const char *name, uint len)
+ :Command(instance_map_arg)
+{
+ Instance *instance;
+
+ /* we make a search here, since we don't want to store the name */
+ if ((instance= instance_map->find(name, len)))
+ instance_name= instance->options.instance_name;
+ else
+ instance_name= NULL;
+}
+
+
+/*
+ The method sends a table with a list of log files
+ used by the instance.
+
+ SYNOPSYS
+ Show_instance_log_files::execute()
+ net The network connection to the client.
+ connection_id The ID of the client connection
+
+ RETURN
+ ER_BAD_INSTANCE_NAME The instance name specified is not valid
+ ER_OUT_OF_RESOURCES some error occured
+ 0 - ok
+*/
+
+int Show_instance_log_files::execute(struct st_net *net, ulong connection_id)
+{
+ Buffer send_buff; /* buffer for packets */
+ LIST name, path, size;
+ LIST *field_list;
+ NAME_WITH_LENGTH name_field, path_field, size_field;
+ uint position= 0;
+
+ if (!instance_name)
+ return ER_BAD_INSTANCE_NAME;
+
+ /* create list of the fileds to be passed to send_fields */
+ name_field.name= (char*) "Logfile";
+ name_field.length= DEFAULT_FIELD_LENGTH;
+ name.data= &name_field;
+ path_field.name= (char*) "Path";
+ path_field.length= DEFAULT_FIELD_LENGTH;
+ path.data= &path_field;
+ size_field.name= (char*) "File size";
+ size_field.length= DEFAULT_FIELD_LENGTH;
+ size.data= &size_field;
+ field_list= list_add(NULL, &size);
+ field_list= list_add(field_list, &path);
+ field_list= list_add(field_list, &name);
+
+ send_fields(net, field_list);
+
+ Instance *instance;
+
+ if ((instance= instance_map->
+ find(instance_name, strlen(instance_name))) == NULL)
+ goto err;
+
+ {
+ /*
+ We have alike structure in instance_options.cc. We use such to be able
+ to loop through the options, which we need to handle in some common way.
+ */
+ struct log_files_st
+ {
+ const char *name;
+ const char *value;
+ } logs[]=
+ {
+ {"ERROR LOG", instance->options.logs[IM_LOG_ERROR]},
+ {"GENERAL LOG", instance->options.logs[IM_LOG_GENERAL]},
+ {"SLOW LOG", instance->options.logs[IM_LOG_SLOW]},
+ {NULL, NULL}
+ };
+ struct log_files_st *log_files;
+
+ for (log_files= logs; log_files->name; log_files++)
+ {
+ if (log_files->value != NULL)
+ {
+ struct stat file_stat;
+ /*
+ Save some more space for the log file names. In fact all
+ we need is srtlen("GENERAL_LOG") + 1
+ */
+ enum { LOG_NAME_BUFFER_SIZE= 20 };
+ char buff[LOG_NAME_BUFFER_SIZE];
+
+ position= 0;
+ /* store the type of the log in the send buffer */
+ store_to_protocol_packet(&send_buff, log_files->name, &position);
+ if (stat(log_files->value, &file_stat))
+ {
+ store_to_protocol_packet(&send_buff, "", &position);
+ store_to_protocol_packet(&send_buff, (char*) "0", &position);
+ }
+ else if (MY_S_ISREG(file_stat.st_mode))
+ {
+ store_to_protocol_packet(&send_buff,
+ (char*) log_files->value,
+ &position);
+ int10_to_str(file_stat.st_size, buff, 10);
+ store_to_protocol_packet(&send_buff, (char*) buff, &position);
+ }
+
+ if (my_net_write(net, send_buff.buffer, (uint) position))
+ goto err;
+ }
+ }
+ }
+
+ if (send_eof(net) || net_flush(net))
+ goto err;
+
+ return 0;
+
+err:
+ return ER_OUT_OF_RESOURCES;
+}
+
+
+/* implementation for SET instance_name.option=option_value: */
+
+Set_option::Set_option(Instance_map *instance_map_arg,
+ const char *name, uint len,
+ const char *option_arg, uint option_len_arg,
+ const char *option_value_arg, uint option_value_len_arg)
+ :Command(instance_map_arg)
+{
+ Instance *instance;
+
+ /* we make a search here, since we don't want to store the name */
+ if ((instance= instance_map->find(name, len)))
+ {
+ instance_name= instance->options.instance_name;
+
+ /* add prefix for add_option */
+ if ((option_len_arg < MAX_OPTION_LEN - 1) ||
+ (option_value_len_arg < MAX_OPTION_LEN - 1))
+ {
+ strmake(option, option_arg, option_len_arg);
+ strmake(option_value, option_value_arg, option_value_len_arg);
+ }
+ else
+ {
+ option[0]= 0;
+ option_value[0]= 0;
+ }
+ instance_name_len= len;
+ }
+ else
+ {
+ instance_name= NULL;
+ instance_name_len= 0;
+ }
+}
+
+
+/*
+ The method sends a table with a list of log files
+ used by the instance.
+
+ SYNOPSYS
+ Set_option::correct_file()
+ skip Skip the option, being searched while writing the result file.
+ That is, to delete it.
+
+ DESCRIPTION
+
+ Correct the option file. The "skip" option is used to remove the found
+ option.
+
+ RETURN
+ ER_OUT_OF_RESOURCES out of resources
+ ER_ACCESS_OPTION_FILE Cannot access the option file
+ 0 - ok
+*/
+
+int Set_option::correct_file(int skip)
+{
+ int error;
+ const static int mysys_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
+ ER_ACCESS_OPTION_FILE };
+
+ error= modify_defaults_file(Options::config_file, option,
+ option_value, instance_name, skip);
+ DBUG_ASSERT(error >= 0 && error <= 2);
+
+ return mysys_to_im_error[error];
+}
+
+
+/*
+ The method sets an option in the the default config file (/etc/my.cnf).
+
+ SYNOPSYS
+ Set_option::do_command()
+ net The network connection to the client.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Set_option::do_command(struct st_net *net)
+{
+ int error;
+
+ /* we must hold the instance_map mutex while changing config file */
+ instance_map->lock();
+ error= correct_file(FALSE);
+ instance_map->unlock();
+
+ return error;
+}
+
+
+int Set_option::execute(struct st_net *net, ulong connection_id)
+{
+ if (instance_name != NULL)
+ {
+ int val;
+
+ val= do_command(net);
+
+ if (val == 0)
+ net_send_ok(net, connection_id, NULL);
+
+ return val;
+ }
+
+ return ER_BAD_INSTANCE_NAME;
+}
+
+
+/* the only function from Unset_option we need to Implement */
+
+int Unset_option::do_command(struct st_net *net)
+{
+ return correct_file(TRUE);
+}
+
+
+/* Implementation for Stop_instance: */
+
+Stop_instance::Stop_instance(Instance_map *instance_map_arg,
+ const char *name, uint len)
+ :Command(instance_map_arg)
+{
+ /* we make a search here, since we don't want to store the name */
+ if ((instance= instance_map->find(name, len)))
+ instance_name= instance->options.instance_name;
+}
+
+
+int Stop_instance::execute(struct st_net *net, ulong connection_id)
+{
+ uint err_code;
+
+ if (instance == 0)
+ return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
+
+ if (!(instance->options.nonguarded))
+ instance_map->guardian->stop_guard(instance);
+
+ if ((err_code= instance->stop()))
+ return err_code;
+
+ net_send_ok(net, connection_id, NULL);
+ return 0;
+}
+
+
+int Syntax_error::execute(struct st_net *net, ulong connection_id)
+{
+ return ER_SYNTAX_ERROR;
+}
diff --git a/server-tools/instance-manager/commands.h b/server-tools/instance-manager/commands.h
new file mode 100644
index 00000000000..bfd38d34889
--- /dev/null
+++ b/server-tools/instance-manager/commands.h
@@ -0,0 +1,215 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "command.h"
+#include "instance.h"
+#include "parse.h"
+
+/*
+ Print all instances of this instance manager.
+ Grammar: SHOW ISTANCES
+*/
+
+class Show_instances : public Command
+{
+public:
+ Show_instances(Instance_map *instance_map_arg): Command(instance_map_arg)
+ {}
+
+ int execute(struct st_net *net, ulong connection_id);
+};
+
+
+/*
+ Reread configuration file and refresh instance map.
+ Grammar: FLUSH INSTANCES
+*/
+
+class Flush_instances : public Command
+{
+public:
+ Flush_instances(Instance_map *instance_map_arg): Command(instance_map_arg)
+ {}
+
+ int execute(struct st_net *net, ulong connection_id);
+};
+
+
+/*
+ Print status of an instance.
+ Grammar: SHOW ISTANCE STATUS <instance_name>
+*/
+
+class Show_instance_status : public Command
+{
+public:
+
+ Show_instance_status(Instance_map *instance_map_arg,
+ const char *name, uint len);
+ int execute(struct st_net *net, ulong connection_id);
+ const char *instance_name;
+};
+
+
+/*
+ Print options if chosen instance.
+ Grammar: SHOW INSTANCE OPTIONS <instance_name>
+*/
+
+class Show_instance_options : public Command
+{
+public:
+
+ Show_instance_options(Instance_map *instance_map_arg,
+ const char *name, uint len);
+
+ int execute(struct st_net *net, ulong connection_id);
+ const char *instance_name;
+};
+
+
+/*
+ Start an instance.
+ Grammar: START INSTANCE <instance_name>
+*/
+
+class Start_instance : public Command
+{
+public:
+ Start_instance(Instance_map *instance_map_arg, const char *name, uint len);
+
+ int execute(struct st_net *net, ulong connection_id);
+ const char *instance_name;
+ Instance *instance;
+};
+
+
+/*
+ Stop an instance.
+ Grammar: STOP INSTANCE <instance_name>
+*/
+
+class Stop_instance : public Command
+{
+public:
+ Stop_instance(Instance_map *instance_map_arg, const char *name, uint len);
+
+ Instance *instance;
+ int execute(struct st_net *net, ulong connection_id);
+ const char *instance_name;
+};
+
+
+/*
+ Print requested part of the log
+ Grammar:
+ SHOW <instance_name> log {ERROR | SLOW | GENERAL} size[, offset_from_end]
+*/
+
+class Show_instance_log : public Command
+{
+public:
+
+ Show_instance_log(Instance_map *instance_map_arg, const char *name,
+ uint len, Log_type log_type_arg, const char *size_arg,
+ const char *offset_arg);
+ int execute(struct st_net *net, ulong connection_id);
+ Log_type log_type;
+ const char *instance_name;
+ uint size;
+ uint offset;
+};
+
+
+/*
+ Shows the list of the log files, used by an instance.
+ Grammar: SHOW <instance_name> LOG FILES
+*/
+
+class Show_instance_log_files : public Command
+{
+public:
+
+ Show_instance_log_files(Instance_map *instance_map_arg,
+ const char *name, uint len);
+ int execute(struct st_net *net, ulong connection_id);
+ const char *instance_name;
+ const char *option;
+};
+
+
+/*
+ Syntax error command. This command is issued if parser reported a syntax
+ error. We need it to distinguish the parse error and the situation when
+ parser internal error occured. E.g. parsing failed because we hadn't had
+ enought memory. In the latter case parse_command() should return an error.
+*/
+
+class Syntax_error : public Command
+{
+public:
+ int execute(struct st_net *net, ulong connection_id);
+};
+
+/*
+ Set an option for the instance.
+ Grammar: SET instance_name.option=option_value
+*/
+
+class Set_option : public Command
+{
+public:
+ Set_option(Instance_map *instance_map_arg, const char *name, uint len,
+ const char *option_arg, uint option_len,
+ const char *option_value_arg, uint option_value_len);
+ /*
+ the following function is virtual to let Unset_option to use
+ */
+ virtual int do_command(struct st_net *net);
+ int execute(struct st_net *net, ulong connection_id);
+protected:
+ int correct_file(int skip);
+public:
+ const char *instance_name;
+ uint instance_name_len;
+ /* buffer for the option */
+ enum { MAX_OPTION_LEN= 1024 };
+ char option[MAX_OPTION_LEN];
+ char option_value[MAX_OPTION_LEN];
+};
+
+
+/*
+ Remove option of the instance from config file
+ Grammar: UNSET instance_name.option
+*/
+
+class Unset_option: public Set_option
+{
+public:
+ Unset_option(Instance_map *instance_map_arg, const char *name, uint len,
+ const char *option_arg, uint option_len,
+ const char *option_value_arg, uint option_value_len):
+ Set_option(instance_map_arg, name, len, option_arg, option_len,
+ option_value_arg, option_value_len)
+ {}
+ int do_command(struct st_net *net);
+};
+
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */
diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc
new file mode 100644
index 00000000000..17f4204185a
--- /dev/null
+++ b/server-tools/instance-manager/guardian.cc
@@ -0,0 +1,439 @@
+/* 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 implementation
+#endif
+
+#include "guardian.h"
+
+#include "instance_map.h"
+#include "instance.h"
+#include "mysql_manager_error.h"
+#include "log.h"
+#include "portability.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <signal.h>
+
+
+
+C_MODE_START
+
+pthread_handler_decl(guardian, arg)
+{
+ Guardian_thread *guardian_thread= (Guardian_thread *) arg;
+ guardian_thread->run();
+ return 0;
+}
+
+C_MODE_END
+
+
+Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg,
+ Instance_map *instance_map_arg,
+ uint monitoring_interval_arg) :
+ Guardian_thread_args(thread_registry_arg, instance_map_arg,
+ monitoring_interval_arg),
+ thread_info(pthread_self()), guarded_instances(0)
+{
+ pthread_mutex_init(&LOCK_guardian, 0);
+ pthread_cond_init(&COND_guardian, 0);
+ shutdown_requested= FALSE;
+ stopped= FALSE;
+ init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
+}
+
+
+Guardian_thread::~Guardian_thread()
+{
+ /* delay guardian destruction to the moment when no one needs it */
+ pthread_mutex_lock(&LOCK_guardian);
+ free_root(&alloc, MYF(0));
+ pthread_mutex_unlock(&LOCK_guardian);
+ pthread_mutex_destroy(&LOCK_guardian);
+ pthread_cond_destroy(&COND_guardian);
+}
+
+
+void Guardian_thread::request_shutdown(bool stop_instances_arg)
+{
+ pthread_mutex_lock(&LOCK_guardian);
+ /* stop instances or just clean up Guardian repository */
+ stop_instances(stop_instances_arg);
+ shutdown_requested= TRUE;
+ pthread_mutex_unlock(&LOCK_guardian);
+}
+
+
+void Guardian_thread::process_instance(Instance *instance,
+ GUARD_NODE *current_node,
+ LIST **guarded_instances,
+ LIST *node)
+{
+ uint waitchild= (uint) Instance::DEFAULT_SHUTDOWN_DELAY;
+ /* The amount of times, Guardian attempts to restart an instance */
+ int restart_retry= 100;
+ time_t current_time= time(NULL);
+
+ if (current_node->state == STOPPING)
+ {
+ /* this brach is executed during shutdown */
+ if (instance->options.shutdown_delay_val)
+ waitchild= instance->options.shutdown_delay_val;
+
+ /* this returns true if and only if an instance was stopped for sure */
+ if (instance->is_crashed())
+ *guarded_instances= list_delete(*guarded_instances, node);
+ else if ( (uint) (current_time - current_node->last_checked) > waitchild)
+ {
+ instance->kill_instance(SIGKILL);
+ /*
+ Later we do node= node->next. This is ok, as we are only removing
+ the node from the list. The pointer to the next one is still valid.
+ */
+ *guarded_instances= list_delete(*guarded_instances, node);
+ }
+
+ return;
+ }
+
+ if (instance->is_running())
+ {
+ /* clear status fields */
+ current_node->restart_counter= 0;
+ current_node->crash_moment= 0;
+ current_node->state= STARTED;
+ }
+ else
+ {
+ switch (current_node->state) {
+ case NOT_STARTED:
+ instance->start();
+ current_node->last_checked= current_time;
+ log_info("guardian: starting instance %s",
+ instance->options.instance_name);
+ current_node->state= STARTING;
+ break;
+ case STARTED: /* fallthrough */
+ case STARTING: /* let the instance start or crash */
+ if (instance->is_crashed())
+ {
+ current_node->crash_moment= current_time;
+ current_node->last_checked= current_time;
+ current_node->state= JUST_CRASHED;
+ /* fallthrough -- restart an instance immediately */
+ }
+ else
+ break;
+ case JUST_CRASHED:
+ if (current_time - current_node->crash_moment <= 2)
+ {
+ instance->start();
+ log_info("guardian: starting instance %s",
+ instance->options.instance_name);
+ }
+ else
+ current_node->state= CRASHED;
+ break;
+ case CRASHED: /* just regular restarts */
+ if (current_time - current_node->last_checked >
+ monitoring_interval)
+ {
+ if ((current_node->restart_counter < restart_retry))
+ {
+ instance->start();
+ current_node->last_checked= current_time;
+ current_node->restart_counter++;
+ log_info("guardian: restarting instance %s",
+ instance->options.instance_name);
+ }
+ else
+ current_node->state= CRASHED_AND_ABANDONED;
+ }
+ break;
+ case CRASHED_AND_ABANDONED:
+ break; /* do nothing */
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+}
+
+
+/*
+ Run guardian thread
+
+ SYNOPSYS
+ run()
+
+ DESCRIPTION
+
+ Check for all guarded instances and restart them if needed. If everything
+ is fine go and sleep for some time.
+*/
+
+void Guardian_thread::run()
+{
+ Instance *instance;
+ LIST *node;
+ struct timespec timeout;
+
+ thread_registry.register_thread(&thread_info);
+
+ my_thread_init();
+ pthread_mutex_lock(&LOCK_guardian);
+
+ /* loop, until all instances were shut down at the end */
+ while (!(shutdown_requested && (guarded_instances == NULL)))
+ {
+ node= guarded_instances;
+
+ while (node != NULL)
+ {
+ struct timespec timeout;
+
+ GUARD_NODE *current_node= (GUARD_NODE *) node->data;
+ instance= ((GUARD_NODE *) node->data)->instance;
+ process_instance(instance, current_node, &guarded_instances, node);
+
+ node= node->next;
+ }
+ timeout.tv_sec= time(NULL) + monitoring_interval;
+ timeout.tv_nsec= 0;
+
+ /* check the loop predicate before sleeping */
+ if (!(shutdown_requested && (!(guarded_instances))))
+ thread_registry.cond_timedwait(&thread_info, &COND_guardian,
+ &LOCK_guardian, &timeout);
+ }
+
+ stopped= TRUE;
+ pthread_mutex_unlock(&LOCK_guardian);
+ /* now, when the Guardian is stopped we can stop the IM */
+ thread_registry.unregister_thread(&thread_info);
+ thread_registry.request_shutdown();
+ my_thread_end();
+}
+
+
+int Guardian_thread::is_stopped()
+{
+ int var;
+ pthread_mutex_lock(&LOCK_guardian);
+ var= stopped;
+ pthread_mutex_unlock(&LOCK_guardian);
+ return var;
+}
+
+
+/*
+ Initialize the list of guarded instances: loop through the Instance_map and
+ add all of the instances, which don't have 'nonguarded' option specified.
+
+ SYNOPSYS
+ Guardian_thread::init()
+
+ NOTE: One should always lock guardian before calling this routine.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Guardian_thread::init()
+{
+ Instance *instance;
+ Instance_map::Iterator iterator(instance_map);
+
+ instance_map->lock();
+ /* clear the list of guarded instances */
+ free_root(&alloc, MYF(0));
+ init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
+ guarded_instances= NULL;
+
+ while ((instance= iterator.next()))
+ {
+ if (!(instance->options.nonguarded))
+ if (guard(instance, TRUE)) /* do not lock guardian */
+ {
+ instance_map->unlock();
+ return 1;
+ }
+ }
+
+ instance_map->unlock();
+ return 0;
+}
+
+
+/*
+ Add instance to the Guardian list
+
+ SYNOPSYS
+ guard()
+ instance the instance to be guarded
+ nolock whether we prefer do not lock Guardian here,
+ but use external locking instead
+
+ DESCRIPTION
+
+ The instance is added to the guarded instances list. Usually guard() is
+ called after we start an instance.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Guardian_thread::guard(Instance *instance, bool nolock)
+{
+ LIST *node;
+ GUARD_NODE *content;
+
+ node= (LIST *) alloc_root(&alloc, sizeof(LIST));
+ content= (GUARD_NODE *) alloc_root(&alloc, sizeof(GUARD_NODE));
+
+ if ((!(node)) || (!(content)))
+ return 1;
+ /* we store the pointers to instances from the instance_map's MEM_ROOT */
+ content->instance= instance;
+ content->restart_counter= 0;
+ content->crash_moment= 0;
+ content->state= NOT_STARTED;
+ node->data= (void*) content;
+
+ if (nolock)
+ guarded_instances= list_add(guarded_instances, node);
+ else
+ {
+ pthread_mutex_lock(&LOCK_guardian);
+ guarded_instances= list_add(guarded_instances, node);
+ pthread_mutex_unlock(&LOCK_guardian);
+ }
+
+ return 0;
+}
+
+
+/*
+ TODO: perhaps it would make sense to create a pool of the LIST nodeents
+ and give them upon request. Now we are loosing a bit of memory when
+ guarded instance was stopped and then restarted (since we cannot free just
+ a piece of the MEM_ROOT).
+*/
+
+int Guardian_thread::stop_guard(Instance *instance)
+{
+ LIST *node;
+
+ pthread_mutex_lock(&LOCK_guardian);
+ node= guarded_instances;
+
+ while (node != NULL)
+ {
+ /*
+ We compare only pointers, as we always use pointers from the
+ instance_map's MEM_ROOT.
+ */
+ if (((GUARD_NODE *) node->data)->instance == instance)
+ {
+ guarded_instances= list_delete(guarded_instances, node);
+ pthread_mutex_unlock(&LOCK_guardian);
+ return 0;
+ }
+ else
+ node= node->next;
+ }
+ pthread_mutex_unlock(&LOCK_guardian);
+ /* if there is nothing to delete it is also fine */
+ return 0;
+}
+
+/*
+ An internal method which is called at shutdown to unregister instances and
+ attempt to stop them if requested.
+
+ SYNOPSYS
+ stop_instances()
+ stop_instances_arg whether we should stop instances at shutdown
+
+ DESCRIPTION
+ Loops through the guarded_instances list and prepares them for shutdown.
+ If stop_instances was requested, we need to issue a stop command and change
+ the state accordingly. Otherwise we simply delete an entry.
+
+ NOTE
+ Guardian object should be locked by the calling function.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Guardian_thread::stop_instances(bool stop_instances_arg)
+{
+ LIST *node;
+ node= guarded_instances;
+ while (node != NULL)
+ {
+ if (!stop_instances_arg)
+ {
+ /* just forget about an instance */
+ guarded_instances= list_delete(guarded_instances, node);
+ /*
+ This should still work fine, as we have only removed the
+ node from the list. The pointer to the next one is still valid
+ */
+ node= node->next;
+ }
+ else
+ {
+ GUARD_NODE *current_node= (GUARD_NODE *) node->data;
+ /*
+ If instance is running or was running (and now probably hanging),
+ request stop.
+ */
+ if (current_node->instance->is_running() ||
+ (current_node->state == STARTED))
+ {
+ current_node->state= STOPPING;
+ current_node->last_checked= time(NULL);
+ }
+ else
+ /* otherwise remove it from the list */
+ guarded_instances= list_delete(guarded_instances, node);
+ /* But try to kill it anyway. Just in case */
+ current_node->instance->kill_instance(SIGTERM);
+ node= node->next;
+ }
+ }
+ return 0;
+}
+
+
+void Guardian_thread::lock()
+{
+ pthread_mutex_lock(&LOCK_guardian);
+}
+
+
+void Guardian_thread::unlock()
+{
+ pthread_mutex_unlock(&LOCK_guardian);
+}
diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h
new file mode 100644
index 00000000000..758c4a3f3bc
--- /dev/null
+++ b/server-tools/instance-manager/guardian.h
@@ -0,0 +1,127 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include "thread_registry.h"
+
+#include <my_sys.h>
+#include <my_list.h>
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+class Instance;
+class Instance_map;
+class Thread_registry;
+struct GUARD_NODE;
+
+C_MODE_START
+
+pthread_handler_decl(guardian, arg);
+
+C_MODE_END
+
+struct Guardian_thread_args
+{
+ Thread_registry &thread_registry;
+ Instance_map *instance_map;
+ int monitoring_interval;
+
+ Guardian_thread_args(Thread_registry &thread_registry_arg,
+ Instance_map *instance_map_arg,
+ uint monitoring_interval_arg) :
+ thread_registry(thread_registry_arg),
+ instance_map(instance_map_arg),
+ monitoring_interval(monitoring_interval_arg)
+ {}
+};
+
+
+/*
+ The guardian thread is responsible for monitoring and restarting of guarded
+ instances.
+*/
+
+class Guardian_thread: public Guardian_thread_args
+{
+public:
+ /* states of an instance */
+ enum enum_instance_state { NOT_STARTED= 1, STARTING, STARTED, JUST_CRASHED,
+ CRASHED, CRASHED_AND_ABANDONED, STOPPING };
+
+ /*
+ The Guardian list node structure. Guardian utilizes it to store
+ guarded instances plus some additional info.
+ */
+
+ struct GUARD_NODE
+ {
+ Instance *instance;
+ /* state of an instance (i.e. STARTED, CRASHED, etc.) */
+ enum_instance_state state;
+ /* the amount of attemts to restart instance (cleaned up at success) */
+ int restart_counter;
+ /* triggered at a crash */
+ time_t crash_moment;
+ /* General time field. Used to provide timeouts (at shutdown and restart) */
+ time_t last_checked;
+ };
+
+
+ Guardian_thread(Thread_registry &thread_registry_arg,
+ Instance_map *instance_map_arg,
+ uint monitoring_interval_arg);
+ ~Guardian_thread();
+ /* Main funtion of the thread */
+ void run();
+ /* Initialize or refresh the list of guarded instances */
+ int init();
+ /* Request guardian shutdown. Stop instances if needed */
+ void request_shutdown(bool stop_instances);
+ /* Start instance protection */
+ int guard(Instance *instance, bool nolock= FALSE);
+ /* Stop instance protection */
+ int stop_guard(Instance *instance);
+ /* Returns true if guardian thread is stopped */
+ int is_stopped();
+ void lock();
+ void unlock();
+
+public:
+ pthread_cond_t COND_guardian;
+
+private:
+ /* Prepares Guardian shutdown. Stops instances is needed */
+ int stop_instances(bool stop_instances_arg);
+ /* check instance state and act accordingly */
+ void process_instance(Instance *instance, GUARD_NODE *current_node,
+ LIST **guarded_instances, LIST *elem);
+ int stopped;
+
+private:
+ pthread_mutex_t LOCK_guardian;
+ Thread_info thread_info;
+ LIST *guarded_instances;
+ MEM_ROOT alloc;
+ enum { MEM_ROOT_BLOCK_SIZE= 512 };
+ /* this variable is set to TRUE when we want to stop Guardian thread */
+ bool shutdown_requested;
+};
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H */
diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc
new file mode 100644
index 00000000000..5e1c3d2ea9f
--- /dev/null
+++ b/server-tools/instance-manager/instance.cc
@@ -0,0 +1,594 @@
+/* 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 implementation
+#endif
+
+#include "instance.h"
+
+#include "mysql_manager_error.h"
+#include "log.h"
+#include "instance_map.h"
+#include "priv.h"
+#include "portability.h"
+#ifndef __WIN__
+#include <sys/wait.h>
+#endif
+#include <my_sys.h>
+#include <signal.h>
+#include <m_string.h>
+#include <mysql.h>
+
+
+static void start_and_monitor_instance(Instance_options *old_instance_options,
+ Instance_map *instance_map);
+
+#ifndef __WIN__
+typedef pid_t My_process_info;
+#else
+typedef PROCESS_INFORMATION My_process_info;
+#endif
+
+C_MODE_START
+
+/*
+ Proxy thread is a simple way to avoid all pitfalls of the threads
+ implementation in the OS (e.g. LinuxThreads). With such a thread we
+ don't have to process SIGCHLD, which is a tricky business if we want
+ to do it in a portable way.
+*/
+
+pthread_handler_decl(proxy, arg)
+{
+ Instance *instance= (Instance *) arg;
+ start_and_monitor_instance(&instance->options,
+ instance->get_map());
+ return 0;
+}
+
+C_MODE_END
+
+
+/*
+ Wait for an instance
+
+ SYNOPSYS
+ wait_process()
+ pi Pointer to the process information structure
+ (platform-dependent).
+
+ RETURN
+ 0 - Success
+ 1 - Error
+*/
+
+#ifndef __WIN__
+static int wait_process(My_process_info *pi)
+{
+ /*
+ Here we wait for the child created. This process differs for systems
+ running LinuxThreads and POSIX Threads compliant systems. This is because
+ according to POSIX we could wait() for a child in any thread of the
+ process. While LinuxThreads require that wait() is called by the thread,
+ which created the child.
+ On the other hand we could not expect mysqld to return the pid, we
+ got in from fork(), to wait4() fucntion when running on LinuxThreads.
+ This is because MySQL shutdown thread is not the one, which was created
+ by our fork() call.
+ So basically we have two options: whether the wait() call returns only in
+ the creator thread, but we cannot use waitpid() since we have no idea
+ which pid we should wait for (in fact it should be the pid of shutdown
+ thread, but we don't know this one). Or we could use waitpid(), but
+ couldn't use wait(), because it could return in any wait() in the program.
+ */
+ if (linuxthreads)
+ wait(NULL); /* LinuxThreads were detected */
+ else
+ waitpid(*pi, NULL, 0);
+
+ return 0;
+}
+#else
+static int wait_process(My_process_info *pi)
+{
+ /* Wait until child process exits. */
+ WaitForSingleObject(pi->hProcess, INFINITE);
+
+ DWORD exitcode;
+ ::GetExitCodeProcess(pi->hProcess, &exitcode);
+
+ /* Close process and thread handles. */
+ CloseHandle(pi->hProcess);
+ CloseHandle(pi->hThread);
+
+ /*
+ GetExitCodeProces returns zero on failure. We should revert this value
+ to report an error.
+ */
+ return (!exitcode);
+}
+#endif
+
+
+/*
+ Launch an instance
+
+ SYNOPSYS
+ start_process()
+ instance_options Pointer to the options of the instance to be
+ launched.
+ pi Pointer to the process information structure
+ (platform-dependent).
+
+ RETURN
+ 0 - Success
+ 1 - Cannot create an instance
+*/
+
+#ifndef __WIN__
+static int start_process(Instance_options *instance_options,
+ My_process_info *pi)
+{
+ *pi= fork();
+
+ switch (*pi) {
+ case 0:
+ execv(instance_options->mysqld_path, instance_options->argv);
+ /* exec never returns */
+ exit(1);
+ case 1:
+ log_info("cannot fork() to start instance %s",
+ instance_options->instance_name);
+ return 1;
+ }
+ return 0;
+}
+#else
+static int start_process(Instance_options *instance_options,
+ My_process_info *pi)
+{
+ STARTUPINFO si;
+
+ ZeroMemory(&si, sizeof(STARTUPINFO));
+ si.cb= sizeof(STARTUPINFO);
+ ZeroMemory(pi, sizeof(PROCESS_INFORMATION));
+
+ int cmdlen= 0;
+ for (int i= 0; instance_options->argv[i] != 0; i++)
+ cmdlen+= strlen(instance_options->argv[i]) + 3;
+ cmdlen++; /* make room for the null */
+
+ char *cmdline= new char[cmdlen];
+ if (cmdline == NULL)
+ return 1;
+
+ for (int i= 0; instance_options->argv[i] != 0; i++)
+ {
+ strcat(cmdline, "\"");
+ strcat(cmdline, instance_options->argv[i]);
+ strcat(cmdline, "\" ");
+ }
+
+ /* Start the child process */
+ BOOL result=
+ CreateProcess(NULL, /* Put it all in cmdline */
+ cmdline, /* Command line */
+ NULL, /* Process handle not inheritable */
+ NULL, /* Thread handle not inheritable */
+ FALSE, /* Set handle inheritance to FALSE */
+ 0, /* No creation flags */
+ NULL, /* Use parent's environment block */
+ NULL, /* Use parent's starting directory */
+ &si, /* Pointer to STARTUPINFO structure */
+ pi); /* Pointer to PROCESS_INFORMATION structure */
+ delete cmdline;
+
+ return (!result);
+}
+#endif
+
+/*
+ Fork child, exec an instance and monitor it.
+
+ SYNOPSYS
+ start_and_monitor_instance()
+ old_instance_options Pointer to the options of the instance to be
+ launched. This info is likely to become obsolete
+ when function returns from wait_process()
+ instance_map Pointer to the instance_map. We use it to protect
+ the instance from deletion, while we are working
+ with it.
+
+ DESCRIPTION
+ Fork a child, then exec and monitor it. When the child is dead,
+ find appropriate instance (for this purpose we save its name),
+ set appropriate flags and wake all threads waiting for instance
+ to stop.
+
+ RETURN
+ Function returns no value
+*/
+
+static void start_and_monitor_instance(Instance_options *old_instance_options,
+ Instance_map *instance_map)
+{
+ enum { MAX_INSTANCE_NAME_LEN= 512 };
+ char instance_name_buff[MAX_INSTANCE_NAME_LEN];
+ uint instance_name_len;
+ Instance *current_instance;
+ My_process_info process_info;
+
+ /*
+ Lock instance map to guarantee that no instances are deleted during
+ strmake() and execv() calls.
+ */
+ instance_map->lock();
+
+ /*
+ Save the instance name in the case if Instance object we
+ are using is destroyed. (E.g. by "FLUSH INSTANCES")
+ */
+ strmake(instance_name_buff, old_instance_options->instance_name,
+ MAX_INSTANCE_NAME_LEN - 1);
+ instance_name_len= old_instance_options->instance_name_len;
+
+ log_info("starting instance %s", instance_name_buff);
+
+ if (start_process(old_instance_options, &process_info))
+ return; /* error is logged */
+
+ /* allow users to delete instances */
+ instance_map->unlock();
+
+ /* don't check for return value */
+ wait_process(&process_info);
+
+ current_instance= instance_map->find(instance_name_buff, instance_name_len);
+
+ if (current_instance)
+ current_instance->set_crash_flag_n_wake_all();
+
+ return;
+}
+
+
+Instance_map *Instance::get_map()
+{
+ return instance_map;
+}
+
+
+void Instance::remove_pid()
+{
+ int pid;
+ if ((pid= options.get_pid()) != 0) /* check the pidfile */
+ if (options.unlink_pidfile()) /* remove stalled pidfile */
+ log_error("cannot remove pidfile for instance %i, this might be \
+ since IM lacks permmissions or hasn't found the pidifle",
+ options.instance_name);
+}
+
+
+/*
+ The method starts an instance.
+
+ SYNOPSYS
+ start()
+
+ RETURN
+ 0 ok
+ ER_CANNOT_START_INSTANCE Cannot start instance
+ ER_INSTANCE_ALREADY_STARTED The instance on the specified port/socket
+ is already started
+*/
+
+int Instance::start()
+{
+ /* clear crash flag */
+ pthread_mutex_lock(&LOCK_instance);
+ crashed= 0;
+ pthread_mutex_unlock(&LOCK_instance);
+
+
+ if (!is_running())
+ {
+ remove_pid();
+
+ /*
+ No need to monitor this thread in the Thread_registry, as all
+ instances are to be stopped during shutdown.
+ */
+ pthread_t proxy_thd_id;
+ pthread_attr_t proxy_thd_attr;
+ int rc;
+
+ pthread_attr_init(&proxy_thd_attr);
+ pthread_attr_setdetachstate(&proxy_thd_attr, PTHREAD_CREATE_DETACHED);
+ rc= pthread_create(&proxy_thd_id, &proxy_thd_attr, proxy,
+ this);
+ pthread_attr_destroy(&proxy_thd_attr);
+ if (rc)
+ {
+ log_error("Instance::start(): pthread_create(proxy) failed");
+ return ER_CANNOT_START_INSTANCE;
+ }
+
+ return 0;
+ }
+
+ /* the instance is started already */
+ return ER_INSTANCE_ALREADY_STARTED;
+}
+
+/*
+ The method sets the crash flag and wakes all waiters on
+ COND_instance_stopped and COND_guardian
+
+ SYNOPSYS
+ set_crash_flag_n_wake_all()
+
+ DESCRIPTION
+ The method is called when an instance is crashed or terminated.
+ In the former case it might indicate that guardian probably should
+ restart it.
+
+ RETURN
+ Function returns no value
+*/
+
+void Instance::set_crash_flag_n_wake_all()
+{
+ /* set instance state to crashed */
+ pthread_mutex_lock(&LOCK_instance);
+ crashed= 1;
+ pthread_mutex_unlock(&LOCK_instance);
+
+ /*
+ Wake connection threads waiting for an instance to stop. This
+ is needed if a user issued command to stop an instance via
+ mysql connection. This is not the case if Guardian stop the thread.
+ */
+ pthread_cond_signal(&COND_instance_stopped);
+ /* wake guardian */
+ pthread_cond_signal(&instance_map->guardian->COND_guardian);
+}
+
+
+
+Instance::Instance(): crashed(0)
+{
+ pthread_mutex_init(&LOCK_instance, 0);
+ pthread_cond_init(&COND_instance_stopped, 0);
+}
+
+
+Instance::~Instance()
+{
+ pthread_cond_destroy(&COND_instance_stopped);
+ pthread_mutex_destroy(&LOCK_instance);
+}
+
+
+int Instance::is_crashed()
+{
+ int val;
+ pthread_mutex_lock(&LOCK_instance);
+ val= crashed;
+ pthread_mutex_unlock(&LOCK_instance);
+ return val;
+}
+
+
+bool Instance::is_running()
+{
+ MYSQL mysql;
+ uint port= 0;
+ const char *socket= NULL;
+ static const char *password= "check_connection";
+ static const char *username= "MySQL_Instance_Manager";
+ static const char *access_denied_message= "Access denied for user";
+ bool return_val;
+
+ if (options.mysqld_port)
+ port= options.mysqld_port_val;
+
+ if (options.mysqld_socket)
+ socket= strchr(options.mysqld_socket, '=') + 1;
+
+ pthread_mutex_lock(&LOCK_instance);
+
+ mysql_init(&mysql);
+ /* try to connect to a server with a fake username/password pair */
+ if (mysql_real_connect(&mysql, LOCAL_HOST, username,
+ password,
+ NullS, port,
+ socket, 0))
+ {
+ /*
+ We have successfully connected to the server using fake
+ username/password. Write a warning to the logfile.
+ */
+ log_info("The Instance Manager was able to log into you server \
+ with faked compiled-in password while checking server status. \
+ Looks like something is wrong.");
+ pthread_mutex_unlock(&LOCK_instance);
+ return_val= TRUE; /* server is alive */
+ }
+ else
+ return_val= test(!strncmp(access_denied_message, mysql_error(&mysql),
+ sizeof(access_denied_message) - 1));
+
+ mysql_close(&mysql);
+ pthread_mutex_unlock(&LOCK_instance);
+
+ return return_val;
+}
+
+
+/*
+ Stop an instance.
+
+ SYNOPSYS
+ stop()
+
+ RETURN:
+ 0 ok
+ ER_INSTANCE_IS_NOT_STARTED Looks like the instance it is not started
+ ER_STOP_INSTANCE mysql_shutdown reported an error
+*/
+
+int Instance::stop()
+{
+ struct timespec timeout;
+ uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
+
+ if (options.shutdown_delay_val)
+ waitchild= options.shutdown_delay_val;
+
+ kill_instance(SIGTERM);
+ /* sleep on condition to wait for SIGCHLD */
+
+ timeout.tv_sec= time(NULL) + waitchild;
+ timeout.tv_nsec= 0;
+ if (pthread_mutex_lock(&LOCK_instance))
+ goto err;
+
+ while (options.get_pid() != 0) /* while server isn't stopped */
+ {
+ int status;
+
+ status= pthread_cond_timedwait(&COND_instance_stopped,
+ &LOCK_instance,
+ &timeout);
+ if (status == ETIMEDOUT)
+ break;
+ }
+
+ pthread_mutex_unlock(&LOCK_instance);
+
+ kill_instance(SIGKILL);
+
+ return 0;
+
+ return ER_INSTANCE_IS_NOT_STARTED;
+err:
+ return ER_STOP_INSTANCE;
+}
+
+#ifdef __WIN__
+
+BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
+{
+ DWORD dwTID, dwCode, dwErr= 0;
+ HANDLE hProcessDup= INVALID_HANDLE_VALUE;
+ HANDLE hRT= NULL;
+ HINSTANCE hKernel= GetModuleHandle("Kernel32");
+ BOOL bSuccess= FALSE;
+
+ BOOL bDup= DuplicateHandle(GetCurrentProcess(),
+ hProcess, GetCurrentProcess(), &hProcessDup,
+ PROCESS_ALL_ACCESS, FALSE, 0);
+
+ // Detect the special case where the process is
+ // already dead...
+ if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) &&
+ (dwCode == STILL_ACTIVE))
+ {
+ FARPROC pfnExitProc;
+
+ pfnExitProc= GetProcAddress(hKernel, "ExitProcess");
+
+ hRT= CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0,
+ (LPTHREAD_START_ROUTINE)pfnExitProc,
+ (PVOID)uExitCode, 0, &dwTID);
+
+ if (hRT == NULL)
+ dwErr= GetLastError();
+ }
+ else
+ dwErr= ERROR_PROCESS_ABORTED;
+
+ if (hRT)
+ {
+ // Must wait process to terminate to
+ // guarantee that it has exited...
+ WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE);
+
+ CloseHandle(hRT);
+ bSuccess= TRUE;
+ }
+
+ if (bDup)
+ CloseHandle(hProcessDup);
+
+ if (!bSuccess)
+ SetLastError(dwErr);
+
+ return bSuccess;
+}
+
+int kill(pid_t pid, int signum)
+{
+ HANDLE processhandle= ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
+ if (signum == SIGTERM)
+ ::SafeTerminateProcess(processhandle, 0);
+ else
+ ::TerminateProcess(processhandle, -1);
+ return 0;
+}
+#endif
+
+void Instance::kill_instance(int signum)
+{
+ pid_t pid;
+ /* if there are no pid, everything seems to be fine */
+ if ((pid= options.get_pid()) != 0) /* get pid from pidfile */
+ {
+ /*
+ If we cannot kill mysqld, then it has propably crashed.
+ Let us try to remove staled pidfile and return successfully
+ as mysqld is probably stopped.
+ */
+ if (!kill(pid, signum))
+ options.unlink_pidfile();
+ else if (signum == SIGKILL) /* really killed instance with SIGKILL */
+ log_error("The instance %s is being stopped forsibly. Normally \
+ it should not happed. Probably the instance has been \
+ hanging. You should also check your IM setup",
+ options.instance_name);
+ }
+ return;
+}
+
+/*
+ We execute this function to initialize instance parameters.
+ Return value: 0 - ok. 1 - unable to init DYNAMIC_ARRAY.
+*/
+
+int Instance::init(const char *name_arg)
+{
+ return options.init(name_arg);
+}
+
+
+int Instance::complete_initialization(Instance_map *instance_map_arg,
+ const char *mysqld_path,
+ uint instance_type)
+{
+ instance_map= instance_map_arg;
+ return options.complete_initialization(mysqld_path, instance_type);
+}
diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h
new file mode 100644
index 00000000000..003cbca8cef
--- /dev/null
+++ b/server-tools/instance-manager/instance.h
@@ -0,0 +1,69 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include "instance_options.h"
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+class Instance_map;
+
+class Instance
+{
+public:
+ Instance();
+
+ ~Instance();
+ int init(const char *name);
+ int complete_initialization(Instance_map *instance_map_arg,
+ const char *mysqld_path, uint instance_type);
+
+ bool is_running();
+ int start();
+ int stop();
+ /* send a signal to the instance */
+ void kill_instance(int signo);
+ int is_crashed();
+ void set_crash_flag_n_wake_all();
+ Instance_map *get_map();
+
+public:
+ enum { DEFAULT_SHUTDOWN_DELAY= 35 };
+ Instance_options options;
+
+private:
+ int crashed;
+ /*
+ Mutex protecting the instance. Currently we use it to avoid the
+ double start of the instance. This happens when the instance is starting
+ and we issue the start command once more.
+ */
+ pthread_mutex_t LOCK_instance;
+ /*
+ This condition variable is used to wake threads waiting for instance to
+ stop in Instance::stop()
+ */
+ pthread_cond_t COND_instance_stopped;
+ Instance_map *instance_map;
+
+ void remove_pid();
+};
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H */
diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc
new file mode 100644
index 00000000000..b3a207ae79f
--- /dev/null
+++ b/server-tools/instance-manager/instance_map.cc
@@ -0,0 +1,270 @@
+/* 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 implementation
+#endif
+
+#include "instance_map.h"
+
+#include "buffer.h"
+#include "instance.h"
+#include "log.h"
+#include "options.h"
+
+#include <m_ctype.h>
+#include <mysql_com.h>
+#include <m_string.h>
+
+/*
+ Note: As we are going to suppost different types of connections,
+ we shouldn't have connection-specific functions. To avoid it we could
+ put such functions to the Command-derived class instead.
+ The command could be easily constructed for a specific connection if
+ we would provide a special factory for each connection.
+*/
+
+C_MODE_START
+
+/* Procedure needed for HASH initialization */
+
+static byte* get_instance_key(const byte* u, uint* len,
+ my_bool __attribute__((unused)) t)
+{
+ const Instance *instance= (const Instance *) u;
+ *len= instance->options.instance_name_len;
+ return (byte *) instance->options.instance_name;
+}
+
+static void delete_instance(void *u)
+{
+ Instance *instance= (Instance *) u;
+ delete instance;
+}
+
+/*
+ The option handler to pass to the process_default_option_files finction.
+
+ SYNOPSYS
+ process_option()
+ ctx Handler context. Here it is an instance_map structure.
+ group_name The name of the group the option belongs to.
+ option The very option to be processed. It is already
+ prepared to be used in argv (has -- prefix)
+
+ DESCRIPTION
+
+ This handler checks whether a group is an instance group and adds
+ an option to the appropriate instance class. If this is the first
+ occurence of an instance name, we'll also create the instance
+ with such name and add it to the instance map.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+static int process_option(void *ctx, const char *group, const char *option)
+{
+ Instance_map *map= NULL;
+ Instance *instance= NULL;
+ static const char prefix[]= { 'm', 'y', 's', 'q', 'l', 'd' };
+
+ map = (Instance_map*) ctx;
+ if (strncmp(group, prefix, sizeof prefix) == 0 &&
+ ((my_isdigit(default_charset_info, group[sizeof prefix]))
+ || group[sizeof(prefix)] == '\0'))
+ {
+ if ((instance= map->find(group, strlen(group))) == NULL)
+ {
+ if ((instance= new Instance) == 0)
+ goto err;
+ if (instance->init(group) || map->add_instance(instance))
+ goto err_instance;
+ }
+
+ if (instance->options.add_option(option))
+ goto err; /* the instance'll be deleted when we destroy the map */
+ }
+
+ return 0;
+
+err_instance:
+ delete instance;
+err:
+ return 1;
+}
+
+C_MODE_END
+
+
+Instance_map::Instance_map(const char *default_mysqld_path_arg):
+mysqld_path(default_mysqld_path_arg)
+{
+ pthread_mutex_init(&LOCK_instance_map, 0);
+}
+
+
+int Instance_map::init()
+{
+ return hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
+ get_instance_key, delete_instance, 0);
+}
+
+Instance_map::~Instance_map()
+{
+ pthread_mutex_lock(&LOCK_instance_map);
+ hash_free(&hash);
+ pthread_mutex_unlock(&LOCK_instance_map);
+ pthread_mutex_destroy(&LOCK_instance_map);
+}
+
+
+void Instance_map::lock()
+{
+ pthread_mutex_lock(&LOCK_instance_map);
+}
+
+
+void Instance_map::unlock()
+{
+ pthread_mutex_unlock(&LOCK_instance_map);
+}
+
+
+int Instance_map::flush_instances()
+{
+ int rc;
+
+ guardian->lock();
+ pthread_mutex_lock(&LOCK_instance_map);
+ hash_free(&hash);
+ hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
+ get_instance_key, delete_instance, 0);
+ pthread_mutex_unlock(&LOCK_instance_map);
+ rc= load();
+ guardian->init();
+ guardian->unlock();
+ return rc;
+}
+
+
+int Instance_map::add_instance(Instance *instance)
+{
+ return my_hash_insert(&hash, (byte *) instance);
+}
+
+
+Instance *
+Instance_map::find(const char *name, uint name_len)
+{
+ Instance *instance;
+ pthread_mutex_lock(&LOCK_instance_map);
+ instance= (Instance *) hash_search(&hash, (byte *) name, name_len);
+ pthread_mutex_unlock(&LOCK_instance_map);
+ return instance;
+}
+
+
+int Instance_map::complete_initialization()
+{
+ Instance *instance;
+ uint i= 0;
+
+
+ if (hash.records == 0) /* no instances found */
+ {
+ if ((instance= new Instance) == 0)
+ goto err;
+
+ if (instance->init("mysqld") || add_instance(instance))
+ goto err_instance;
+
+
+ /*
+ After an instance have been added to the instance_map,
+ hash_free should handle it's deletion => goto err, not
+ err_instance.
+ */
+ if (instance->complete_initialization(this, mysqld_path,
+ DEFAULT_SINGLE_INSTANCE))
+ goto err;
+ }
+ else
+ while (i < hash.records)
+ {
+ instance= (Instance *) hash_element(&hash, i);
+ if (instance->complete_initialization(this, mysqld_path, USUAL_INSTANCE))
+ goto err;
+ i++;
+ }
+
+ return 0;
+err_instance:
+ delete instance;
+err:
+ return 1;
+}
+
+
+/* load options from config files and create appropriate instance structures */
+
+int Instance_map::load()
+{
+ int argc= 1;
+ /* this is a dummy variable for search_option_files() */
+ uint args_used= 0;
+ const char *argv_options[3];
+ char **argv= (char **) &argv_options;
+
+
+ /* the name of the program may be orbitrary here in fact */
+ argv_options[0]= "mysqlmanager";
+ argv_options[1]= '\0';
+
+ /*
+ If the routine failed, we'll simply fallback to defaults in
+ complete_initialization().
+ */
+ if (my_search_option_files(Options::config_file, &argc,
+ (char ***) &argv, &args_used,
+ process_option, (void*) this))
+ log_info("Falling back to compiled-in defaults");
+
+ if (complete_initialization())
+ return 1;
+
+ return 0;
+}
+
+
+/*--- Implementaton of the Instance map iterator class ---*/
+
+
+void Instance_map::Iterator::go_to_first()
+{
+ current_instance=0;
+}
+
+
+Instance *Instance_map::Iterator::next()
+{
+ if (current_instance < instance_map->hash.records)
+ return (Instance *) hash_element(&instance_map->hash, current_instance++);
+
+ return NULL;
+}
+
diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h
new file mode 100644
index 00000000000..47037e0d433
--- /dev/null
+++ b/server-tools/instance-manager/instance_map.h
@@ -0,0 +1,87 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+
+#include "protocol.h"
+#include "guardian.h"
+
+#include <my_sys.h>
+#include <hash.h>
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+class Instance;
+extern int load_all_groups(char ***groups, const char *filename);
+extern void free_groups(char **groups);
+
+
+/*
+ Instance_map - stores all existing instances
+*/
+
+class Instance_map
+{
+public:
+ /* Instance_map iterator */
+ class Iterator
+ {
+ private:
+ uint current_instance;
+ Instance_map *instance_map;
+ public:
+ Iterator(Instance_map *instance_map_arg) :
+ current_instance(0), instance_map(instance_map_arg)
+ {}
+
+ void go_to_first();
+ Instance *next();
+ };
+ friend class Iterator;
+public:
+ /* returns a pointer to the instance or NULL, if there is no such instance */
+ Instance *find(const char *name, uint name_len);
+
+ int flush_instances();
+ void lock();
+ void unlock();
+ int init();
+
+ Instance_map(const char *default_mysqld_path_arg);
+ ~Instance_map();
+
+ /* loads options from config files */
+ int load();
+ /* adds instance to internal hash */
+ int add_instance(Instance *instance);
+ /* inits instances argv's after all options have been loaded */
+ int complete_initialization();
+
+public:
+ const char *mysqld_path;
+ Guardian_thread *guardian;
+
+private:
+ enum { START_HASH_SIZE = 16 };
+ pthread_mutex_t LOCK_instance_map;
+ HASH hash;
+};
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */
diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc
new file mode 100644
index 00000000000..70950a91015
--- /dev/null
+++ b/server-tools/instance-manager/instance_options.cc
@@ -0,0 +1,537 @@
+/* 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 implementation
+#endif
+
+#include "instance_options.h"
+
+#include "parse_output.h"
+#include "buffer.h"
+
+#include <my_sys.h>
+#include <signal.h>
+#include <m_string.h>
+
+#ifdef __WIN__
+#define NEWLINE_LEN 2
+#else
+#define NEWLINE_LEN 1
+#endif
+
+
+/* Create "mysqld ..." command in the buffer */
+
+static inline int create_mysqld_command(Buffer *buf,
+ const char *mysqld_path_str,
+ uint mysqld_path_len,
+ const char *option,
+ uint option_len)
+{
+ int position= 0;
+
+ if (buf->get_size()) /* malloc succeeded */
+ {
+#ifdef __WIN__
+ buf->append(position, "\"", 1);
+ position++;
+#endif
+ buf->append(position, mysqld_path_str, mysqld_path_len);
+ position+= mysqld_path_len;
+#ifdef __WIN__
+ buf->append(position, "\"", 1);
+ position++;
+#endif
+ /* here the '\0' character is copied from the option string */
+ buf->append(position, option, option_len);
+
+ return buf->is_error();
+ }
+ return 1;
+}
+
+
+/*
+ Get compiled-in value of default_option
+
+ SYNOPSYS
+ get_default_option()
+ result buffer to put found value
+ result_len buffer size
+ option_name the name of the option, prefixed with "--"
+
+ DESCRIPTION
+
+ Get compile-in value of requested option from server
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+
+int Instance_options::get_default_option(char *result, size_t result_len,
+ const char *option_name)
+{
+ int rc= 1;
+ char verbose_option[]= " --no-defaults --verbose --help";
+
+ /* reserve space fot the path + option + final '\0' */
+ Buffer cmd(mysqld_path_len + sizeof(verbose_option));
+
+ if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len,
+ verbose_option, sizeof(verbose_option)))
+ goto err;
+
+ /* +2 eats first "--" from the option string (E.g. "--datadir") */
+ rc= parse_output_and_get_value(cmd.buffer, option_name + 2,
+ result, result_len, GET_VALUE);
+err:
+ return rc;
+}
+
+
+/*
+ Fill mysqld_version option (used at initialization stage)
+
+ SYNOPSYS
+ fill_instance_version()
+
+ DESCRIPTION
+
+ Get mysqld version string from "mysqld --version" output.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Instance_options::fill_instance_version()
+{
+ enum { MAX_VERSION_STRING_LENGTH= 160 };
+ char result[MAX_VERSION_STRING_LENGTH];
+ char version_option[]= " --no-defaults --version";
+ int rc= 1;
+ Buffer cmd(mysqld_path_len + sizeof(version_option));
+
+ if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len,
+ version_option, sizeof(version_option)))
+ goto err;
+
+ bzero(result, MAX_VERSION_STRING_LENGTH);
+
+ rc= parse_output_and_get_value(cmd.buffer, mysqld_path,
+ result, MAX_VERSION_STRING_LENGTH,
+ GET_LINE);
+
+ if (*result != '\0')
+ {
+ /* chop the newline from the end of the version string */
+ result[strlen(result) - NEWLINE_LEN]= '\0';
+ mysqld_version= strdup_root(&alloc, result);
+ }
+err:
+ return rc;
+}
+
+
+/*
+ Fill various log options
+
+ SYNOPSYS
+ fill_log_options()
+
+ DESCRIPTION
+
+ Compute paths to enabled log files. If the path is not specified in the
+ instance explicitly (I.e. log=/home/user/mysql.log), we try to guess the
+ file name and placement.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Instance_options::fill_log_options()
+{
+ Buffer buff;
+ uint position= 0;
+ char **tmp_argv= argv;
+ enum { MAX_LOG_OPTION_LENGTH= 256 };
+ char datadir[MAX_LOG_OPTION_LENGTH];
+ char hostname[MAX_LOG_OPTION_LENGTH];
+ uint hostname_length;
+ struct log_files_st
+ {
+ const char *name;
+ uint length;
+ char **value;
+ const char *default_suffix;
+ } logs_st[]=
+ {
+ {"--log-error", 11, &(logs[IM_LOG_ERROR]), ".err"},
+ {"--log", 5, &(logs[IM_LOG_GENERAL]), ".log"},
+ {"--log-slow-queries", 18, &(logs[IM_LOG_SLOW]), "-slow.log"},
+ {NULL, 0, NULL, NULL}
+ };
+ struct log_files_st *log_files;
+
+ /* compute hostname and datadir for the instance */
+ if (mysqld_datadir == NULL)
+ {
+ if (get_default_option(datadir, MAX_LOG_OPTION_LENGTH, "--datadir"))
+ goto err;
+ }
+ else
+ {
+ /* below is safe, as --datadir always has a value */
+ strmake(datadir,
+ strchr(mysqld_datadir, '=') + 1, MAX_LOG_OPTION_LENGTH - 1);
+ }
+
+ if (gethostname(hostname,sizeof(hostname)-1) < 0)
+ strmov(hostname, "mysql");
+
+ hostname[MAX_LOG_OPTION_LENGTH - 1]= 0; /* Safety */
+ hostname_length= strlen(hostname);
+
+
+ for (log_files= logs_st; log_files->name; log_files++)
+ {
+ for (int i=0; (argv[i] != 0); i++)
+ {
+ if (!strncmp(argv[i], log_files->name, log_files->length))
+ {
+ /*
+ This is really log_files->name option if and only if it is followed
+ by '=', '\0' or space character. This way we can distinguish such
+ options as '--log' and '--log-bin'. This is checked in the following
+ two statements.
+ */
+ if (argv[i][log_files->length] == '\0' ||
+ my_isspace(default_charset_info, argv[i][log_files->length]))
+ {
+ char full_name[MAX_LOG_OPTION_LENGTH];
+
+ fn_format(full_name, hostname, datadir, "",
+ MY_UNPACK_FILENAME | MY_SAFE_PATH);
+
+
+ if ((MAX_LOG_OPTION_LENGTH - strlen(full_name)) <=
+ strlen(log_files->default_suffix))
+ goto err;
+
+ strmov(full_name + strlen(full_name), log_files->default_suffix);
+
+ /*
+ If there were specified two identical logfiles options,
+ we would loose some memory in MEM_ROOT here. However
+ this situation is not typical.
+ */
+ *(log_files->value)= strdup_root(&alloc, full_name);
+ }
+
+ if (argv[i][log_files->length] == '=')
+ {
+ char full_name[MAX_LOG_OPTION_LENGTH];
+
+ fn_format(full_name, argv[i] +log_files->length + 1,
+ datadir, "", MY_UNPACK_FILENAME | MY_SAFE_PATH);
+
+ if (!(*(log_files->value)= strdup_root(&alloc, full_name)))
+ goto err;
+ }
+ }
+ }
+ }
+
+ return 0;
+err:
+ return 1;
+}
+
+
+/*
+ Get the full pid file name with path
+
+ SYNOPSYS
+ get_pid_filaname()
+ result buffer to sotre the pidfile value
+
+ IMPLEMENTATION
+ Get the data directory, then get the pid filename
+ (which is always set for an instance), then load the
+ full path with my_load_path(). It takes into account
+ whether it is already an absolute path or it should be
+ prefixed with the datadir and so on.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Instance_options::get_pid_filename(char *result)
+{
+ const char *pid_file= mysqld_pid_file;
+ char datadir[MAX_PATH_LEN];
+
+ if (mysqld_datadir == NULL)
+ {
+ /* we might get an error here if we have wrong path to the mysqld binary */
+ if (get_default_option(datadir, sizeof(datadir), "--datadir"))
+ return 1;
+ }
+ else
+ strxnmov(datadir, MAX_PATH_LEN - 1, strchr(mysqld_datadir, '=') + 1,
+ "/", NullS);
+
+ DBUG_ASSERT(mysqld_pid_file);
+ pid_file= strchr(pid_file, '=') + 1;
+
+ /* get the full path to the pidfile */
+ my_load_path(result, pid_file, datadir);
+ return 0;
+}
+
+
+int Instance_options::unlink_pidfile()
+{
+ return unlink(pid_file_with_path);
+}
+
+
+pid_t Instance_options::get_pid()
+{
+ FILE *pid_file_stream;
+
+ /* get the pid */
+ if ((pid_file_stream= my_fopen(pid_file_with_path,
+ O_RDONLY | O_BINARY, MYF(0))) != NULL)
+ {
+ pid_t pid;
+
+ fscanf(pid_file_stream, "%i", &pid);
+ my_fclose(pid_file_stream, MYF(0));
+ return pid;
+ }
+ return 0;
+}
+
+
+int Instance_options::complete_initialization(const char *default_path,
+ uint instance_type)
+{
+ const char *tmp;
+
+ if (!mysqld_path && !(mysqld_path= strdup_root(&alloc, default_path)))
+ goto err;
+
+ mysqld_path_len= strlen(mysqld_path);
+
+ if (mysqld_port)
+ mysqld_port_val= atoi(strchr(mysqld_port, '=') + 1);
+
+ if (shutdown_delay)
+ shutdown_delay_val= atoi(shutdown_delay);
+
+ if (!(tmp= strdup_root(&alloc, "--no-defaults")))
+ goto err;
+
+ if (!(mysqld_pid_file))
+ {
+ char pidfilename[MAX_PATH_LEN];
+ char hostname[MAX_PATH_LEN];
+
+ /*
+ If we created only one istance [mysqld], because no config. files were
+ found, we would like to model mysqld pid file values.
+ */
+ if (!gethostname(hostname, sizeof(hostname) - 1))
+ {
+ if (instance_type & DEFAULT_SINGLE_INSTANCE)
+ strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", hostname,
+ ".pid", NullS);
+ else
+ strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name,
+ "-", hostname, ".pid", NullS);
+ }
+ else
+ {
+ if (instance_type & DEFAULT_SINGLE_INSTANCE)
+ strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", "mysql",
+ ".pid", NullS);
+ else
+ strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name,
+ ".pid", NullS);
+ }
+
+ add_option(pidfilename);
+ }
+
+ if (get_pid_filename(pid_file_with_path))
+ goto err;
+
+ /* we need to reserve space for the final zero + possible default options */
+ if (!(argv= (char**)
+ alloc_root(&alloc, (options_array.elements + 1
+ + MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
+ goto err;
+
+ /* the path must be first in the argv */
+ if (add_to_argv(mysqld_path))
+ goto err;
+
+ if (add_to_argv(tmp))
+ goto err;
+
+ memcpy((gptr) (argv + filled_default_options), options_array.buffer,
+ options_array.elements*sizeof(char*));
+ argv[filled_default_options + options_array.elements]= 0;
+
+ if (fill_log_options() || fill_instance_version())
+ goto err;
+
+ return 0;
+
+err:
+ return 1;
+}
+
+
+/*
+ Assigns given value to the appropriate option from the class.
+
+ SYNOPSYS
+ add_option()
+ option string with the option prefixed by --
+
+ DESCRIPTION
+
+ The method is called from the option handling routine.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+int Instance_options::add_option(const char* option)
+{
+ char *tmp;
+ enum { SAVE_VALUE= 1, SAVE_WHOLE, SAVE_WHOLE_AND_ADD };
+ struct selected_options_st
+ {
+ const char *name;
+ uint length;
+ const char **value;
+ uint type;
+ } options[]=
+ {
+ {"--socket=", 9, &mysqld_socket, SAVE_WHOLE_AND_ADD},
+ {"--port=", 7, &mysqld_port, SAVE_WHOLE_AND_ADD},
+ {"--datadir=", 10, &mysqld_datadir, SAVE_WHOLE_AND_ADD},
+ {"--bind-address=", 15, &mysqld_bind_address, SAVE_WHOLE_AND_ADD},
+ {"--pid-file=", 11, &mysqld_pid_file, SAVE_WHOLE_AND_ADD},
+ {"--mysqld-path=", 14, &mysqld_path, SAVE_VALUE},
+ {"--nonguarded", 9, &nonguarded, SAVE_WHOLE},
+ {"--shutdown_delay", 9, &shutdown_delay, SAVE_VALUE},
+ {NULL, 0, NULL, 0}
+ };
+ struct selected_options_st *selected_options;
+
+ if (!(tmp= strdup_root(&alloc, option)))
+ goto err;
+
+ for (selected_options= options; selected_options->name; selected_options++)
+ {
+ if (strncmp(tmp, selected_options->name, selected_options->length) == 0)
+ switch (selected_options->type) {
+ case SAVE_WHOLE_AND_ADD:
+ *(selected_options->value)= tmp;
+ insert_dynamic(&options_array,(gptr) &tmp);
+ return 0;
+ case SAVE_VALUE:
+ *(selected_options->value)= strchr(tmp, '=') + 1;
+ return 0;
+ case SAVE_WHOLE:
+ *(selected_options->value)= tmp;
+ return 0;
+ defaut:
+ break;
+ }
+ }
+
+ /* if we haven't returned earlier we should just save the option */
+ insert_dynamic(&options_array,(gptr) &tmp);
+
+ return 0;
+
+err:
+ return 1;
+}
+
+
+int Instance_options::add_to_argv(const char* option)
+{
+ DBUG_ASSERT(filled_default_options < MAX_NUMBER_OF_DEFAULT_OPTIONS);
+
+ if (option)
+ argv[filled_default_options++]= (char*) option;
+ return 0;
+}
+
+
+/* function for debug purposes */
+void Instance_options::print_argv()
+{
+ int i;
+ printf("printing out an instance %s argv:\n", instance_name);
+ for (i=0; argv[i] != NULL; i++)
+ printf("argv: %s\n", argv[i]);
+}
+
+
+/*
+ We execute this function to initialize some options.
+ Return value: 0 - ok. 1 - unable to allocate memory.
+*/
+
+int Instance_options::init(const char *instance_name_arg)
+{
+ instance_name_len= strlen(instance_name_arg);
+
+ init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
+
+ if (my_init_dynamic_array(&options_array, sizeof(char*), 0, 32))
+ goto err;
+
+ if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg,
+ instance_name_len)))
+ goto err;
+
+ return 0;
+
+err:
+ return 1;
+}
+
+
+Instance_options::~Instance_options()
+{
+ free_root(&alloc, MYF(0));
+ delete_dynamic(&options_array);
+}
+
diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h
new file mode 100644
index 00000000000..dc62d277a43
--- /dev/null
+++ b/server-tools/instance-manager/instance_options.h
@@ -0,0 +1,106 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include <my_sys.h>
+#include "parse.h"
+#include "portability.h"
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+
+/*
+ This class contains options of an instance and methods to operate them.
+
+ We do not provide this class with the means of synchronization as it is
+ supposed that options for instances are all loaded at once during the
+ instance_map initilization and we do not change them later. This way we
+ don't have to synchronize between threads.
+*/
+
+#define USUAL_INSTANCE 0
+#define DEFAULT_SINGLE_INSTANCE 1
+
+class Instance_options
+{
+public:
+ Instance_options() :
+ mysqld_version(0), mysqld_socket(0), mysqld_datadir(0),
+ mysqld_bind_address(0), mysqld_pid_file(0), mysqld_port(0),
+ mysqld_port_val(0), mysqld_path(0), nonguarded(0), shutdown_delay(0),
+ shutdown_delay_val(0), filled_default_options(0)
+ {}
+ ~Instance_options();
+ /* fills in argv */
+ int complete_initialization(const char *default_path, uint instance_type);
+
+ int add_option(const char* option);
+ int init(const char *instance_name_arg);
+ pid_t get_pid();
+ int get_pid_filename(char *result);
+ int unlink_pidfile();
+ void print_argv();
+
+public:
+ /*
+ We need this value to be greater or equal then FN_REFLEN found in
+ my_global.h to use my_load_path()
+ */
+ enum { MAX_PATH_LEN= 512 };
+ enum { MAX_NUMBER_OF_DEFAULT_OPTIONS= 2 };
+ enum { MEM_ROOT_BLOCK_SIZE= 512 };
+ char pid_file_with_path[MAX_PATH_LEN];
+ char **argv;
+ /*
+ Here we cache the version string, obtained from mysqld --version.
+ In the case when mysqld binary is not found we get NULL here.
+ */
+ const char *mysqld_version;
+ /* We need the some options, so we store them as a separate pointers */
+ const char *mysqld_socket;
+ const char *mysqld_datadir;
+ const char *mysqld_bind_address;
+ const char *mysqld_pid_file;
+ const char *mysqld_port;
+ uint mysqld_port_val;
+ const char *instance_name;
+ uint instance_name_len;
+ const char *mysqld_path;
+ uint mysqld_path_len;
+ const char *nonguarded;
+ const char *shutdown_delay;
+ uint shutdown_delay_val;
+ /* log enums are defined in parse.h */
+ char *logs[3];
+
+ /* this value is computed and cashed here */
+ DYNAMIC_ARRAY options_array;
+private:
+ int fill_log_options();
+ int fill_instance_version();
+ int add_to_argv(const char *option);
+ int get_default_option(char *result, size_t result_len,
+ const char *option_name);
+private:
+ uint filled_default_options;
+ MEM_ROOT alloc;
+};
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H */
diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc
new file mode 100644
index 00000000000..374946d3b73
--- /dev/null
+++ b/server-tools/instance-manager/listener.cc
@@ -0,0 +1,392 @@
+/* Copyright (C) 2003 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 */
+
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+#include "listener.h"
+#include "priv.h"
+#include <m_string.h>
+#include <mysql.h>
+#include <violite.h>
+#ifndef __WIN__
+#include <sys/un.h>
+#endif
+#include <sys/stat.h>
+
+#include "thread_registry.h"
+#include "options.h"
+#include "instance_map.h"
+#include "log.h"
+#include "mysql_connection.h"
+#include "portability.h"
+
+
+/*
+ Listener_thread - incapsulates listening functionality
+*/
+
+class Listener_thread: public Listener_thread_args
+{
+public:
+ Listener_thread(const Listener_thread_args &args);
+ ~Listener_thread();
+ void run();
+private:
+ static const int LISTEN_BACK_LOG_SIZE= 5; /* standard backlog size */
+ ulong total_connection_count;
+ Thread_info thread_info;
+
+ int sockets[2];
+ int num_sockets;
+ fd_set read_fds;
+private:
+ void handle_new_mysql_connection(Vio *vio);
+ int create_tcp_socket();
+ int create_unix_socket(struct sockaddr_un &unix_socket_address);
+};
+
+
+Listener_thread::Listener_thread(const Listener_thread_args &args) :
+ Listener_thread_args(args.thread_registry, args.options, args.user_map,
+ args.instance_map)
+ ,total_connection_count(0)
+ ,thread_info(pthread_self())
+ ,num_sockets(0)
+{
+}
+
+
+Listener_thread::~Listener_thread()
+{
+}
+
+
+/*
+ Listener_thread::run() - listen all supported sockets and spawn a thread
+ to handle incoming connection.
+ Using 'die' in case of syscall failure is OK now - we don't hold any
+ resources and 'die' kills the signal thread automatically. To be rewritten
+ one day.
+ See also comments in mysqlmanager.cc to picture general Instance Manager
+ architecture.
+*/
+
+void Listener_thread::run()
+{
+ int n= 0;
+
+#ifndef __WIN__
+ /* we use this var to check whether we are running on LinuxThreads */
+ pid_t thread_pid;
+
+ thread_pid= getpid();
+
+ struct sockaddr_un unix_socket_address;
+ /* set global variable */
+ linuxthreads= (thread_pid != manager_pid);
+#endif
+
+ thread_registry.register_thread(&thread_info);
+
+ my_thread_init();
+
+ FD_ZERO(&read_fds);
+
+ /* I. prepare 'listen' sockets */
+ if (create_tcp_socket())
+ goto err;
+
+#ifndef __WIN__
+ if (create_unix_socket(unix_socket_address))
+ goto err;
+#endif
+
+ /* II. Listen sockets and spawn childs */
+ for (int i= 0; i < num_sockets; i++)
+ n= max(n, sockets[i]);
+ n++;
+
+ timeval tv;
+ tv.tv_sec= 0;
+ tv.tv_usec= 100000;
+ while (!thread_registry.is_shutdown())
+ {
+ fd_set read_fds_arg= read_fds;
+
+ /*
+ When using valgrind 2.0 this syscall doesn't get kicked off by a
+ signal during shutdown. This results in failing assert
+ (Thread_registry::~Thread_registry). Valgrind 2.2 works fine.
+ */
+ int rc= select(n, &read_fds_arg, 0, 0, &tv);
+
+ if (rc == 0 || rc == -1)
+ {
+ if (rc == -1 && errno != EINTR)
+ log_error("Listener_thread::run(): select() failed, %s",
+ strerror(errno));
+ continue;
+ }
+
+
+ for (int socket_index= 0; socket_index < num_sockets; socket_index++)
+ {
+ /* Assuming that rc > 0 as we asked to wait forever */
+ if (FD_ISSET(sockets[socket_index], &read_fds_arg))
+ {
+ int client_fd= accept(sockets[socket_index], 0, 0);
+ /* accept may return -1 (failure or spurious wakeup) */
+ if (client_fd >= 0) // connection established
+ {
+ Vio *vio= vio_new(client_fd, socket_index == 0 ?
+ VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
+ socket_index == 0 ? 1 : 0);
+ if (vio != 0)
+ handle_new_mysql_connection(vio);
+ else
+ {
+ shutdown(client_fd, SHUT_RDWR);
+ close(client_fd);
+ }
+ }
+ }
+ }
+ }
+
+ /* III. Release all resources and exit */
+
+ log_info("Listener_thread::run(): shutdown requested, exiting...");
+
+ for (int i= 0; i < num_sockets; i++)
+ close(sockets[i]);
+
+#ifndef __WIN__
+ unlink(unix_socket_address.sun_path);
+#endif
+
+ thread_registry.unregister_thread(&thread_info);
+ my_thread_end();
+ return;
+
+err:
+ // we have to close the ip sockets in case of error
+ for (int i= 0; i < num_sockets; i++)
+ close(sockets[i]);
+
+ thread_registry.unregister_thread(&thread_info);
+ thread_registry.request_shutdown();
+ my_thread_end();
+ return;
+}
+
+void set_non_blocking(int socket)
+{
+#ifndef __WIN__
+ int flags= fcntl(socket, F_GETFL, 0);
+ fcntl(socket, F_SETFL, flags | O_NONBLOCK);
+#else
+ u_long arg= 1;
+ ioctlsocket(socket, FIONBIO, &arg);
+#endif
+}
+
+void set_no_inherit(int socket)
+{
+#ifndef __WIN__
+ int flags= fcntl(socket, F_GETFD, 0);
+ fcntl(socket, F_SETFD, flags | FD_CLOEXEC);
+#endif
+}
+
+int Listener_thread::create_tcp_socket()
+{
+ /* value to be set by setsockopt */
+ int arg= 1;
+
+ int ip_socket= socket(AF_INET, SOCK_STREAM, 0);
+ if (ip_socket == INVALID_SOCKET)
+ {
+ log_error("Listener_thead::run(): socket(AF_INET) failed, %s",
+ strerror(errno));
+ return -1;
+ }
+
+ struct sockaddr_in ip_socket_address;
+ bzero(&ip_socket_address, sizeof(ip_socket_address));
+
+ ulong im_bind_addr;
+ if (options.bind_address != 0)
+ {
+ if ((im_bind_addr= (ulong) inet_addr(options.bind_address)) == INADDR_NONE)
+ im_bind_addr= htonl(INADDR_ANY);
+ }
+ else
+ im_bind_addr= htonl(INADDR_ANY);
+ uint im_port= options.port_number;
+
+ ip_socket_address.sin_family= AF_INET;
+ ip_socket_address.sin_addr.s_addr= im_bind_addr;
+
+
+ ip_socket_address.sin_port= (unsigned short)
+ htons((unsigned short) im_port);
+
+ setsockopt(ip_socket, SOL_SOCKET, SO_REUSEADDR, (char*) &arg, sizeof(arg));
+ if (bind(ip_socket, (struct sockaddr *) &ip_socket_address,
+ sizeof(ip_socket_address)))
+ {
+ log_error("Listener_thread::run(): bind(ip socket) failed, '%s'",
+ strerror(errno));
+ close(ip_socket);
+ return -1;
+ }
+
+ if (listen(ip_socket, LISTEN_BACK_LOG_SIZE))
+ {
+ log_error("Listener_thread::run(): listen(ip socket) failed, %s",
+ strerror(errno));
+ close(ip_socket);
+ return -1;
+ }
+
+ /* set the socket nonblocking */
+ set_non_blocking(ip_socket);
+
+ /* make sure that instances won't be listening our sockets */
+ set_no_inherit(ip_socket);
+
+ FD_SET(ip_socket, &read_fds);
+ sockets[num_sockets++]= ip_socket;
+ log_info("accepting connections on ip socket");
+ return 0;
+}
+
+#ifndef __WIN__
+int Listener_thread::
+create_unix_socket(struct sockaddr_un &unix_socket_address)
+{
+ int unix_socket= socket(AF_UNIX, SOCK_STREAM, 0);
+ if (unix_socket == INVALID_SOCKET)
+ {
+ log_error("Listener_thead::run(): socket(AF_UNIX) failed, %s",
+ strerror(errno));
+ return -1;
+ }
+
+ bzero(&unix_socket_address, sizeof(unix_socket_address));
+
+ unix_socket_address.sun_family= AF_UNIX;
+ strmake(unix_socket_address.sun_path, options.socket_file_name,
+ sizeof(unix_socket_address.sun_path));
+ unlink(unix_socket_address.sun_path); // in case we have stale socket file
+
+ /*
+ POSIX specifies default permissions for a pathname created by bind
+ to be 0777. We need everybody to have access to the socket.
+ */
+ mode_t old_mask= umask(0);
+ if (bind(unix_socket, (struct sockaddr *) &unix_socket_address,
+ sizeof(unix_socket_address)))
+ {
+ log_error("Listener_thread::run(): bind(unix socket) failed, "
+ "socket file name is '%s', error '%s'",
+ unix_socket_address.sun_path, strerror(errno));
+ close(unix_socket);
+ return -1;
+ }
+
+ umask(old_mask);
+
+ if (listen(unix_socket, LISTEN_BACK_LOG_SIZE))
+ {
+ log_error("Listener_thread::run(): listen(unix socket) failed, %s",
+ strerror(errno));
+ close(unix_socket);
+ return -1;
+ }
+
+ /* set the socket nonblocking */
+ set_non_blocking(unix_socket);
+
+ /* make sure that instances won't be listening our sockets */
+ set_no_inherit(unix_socket);
+
+ log_info("accepting connections on unix socket %s",
+ unix_socket_address.sun_path);
+ sockets[num_sockets++]= unix_socket;
+ FD_SET(unix_socket, &read_fds);
+ return 0;
+}
+#endif
+
+
+/*
+ Create new mysql connection. Created thread is responsible for deletion of
+ the Mysql_connection_thread_args and Vio instances passed to it.
+ SYNOPSYS
+ handle_new_mysql_connection()
+*/
+
+void Listener_thread::handle_new_mysql_connection(Vio *vio)
+{
+ if (Mysql_connection_thread_args *mysql_thread_args=
+ new Mysql_connection_thread_args(vio, thread_registry, user_map,
+ ++total_connection_count,
+ instance_map)
+ )
+ {
+ /*
+ Initialize thread attributes to create detached thread; it seems
+ easier to do it ad-hoc than have a global variable for attributes.
+ */
+ pthread_t mysql_thd_id;
+ pthread_attr_t mysql_thd_attr;
+ pthread_attr_init(&mysql_thd_attr);
+ pthread_attr_setdetachstate(&mysql_thd_attr, PTHREAD_CREATE_DETACHED);
+ if (pthread_create(&mysql_thd_id, &mysql_thd_attr, mysql_connection,
+ mysql_thread_args))
+ {
+ delete mysql_thread_args;
+ vio_delete(vio);
+ log_error("handle_one_mysql_connection(): pthread_create(mysql) failed");
+ }
+ pthread_attr_destroy(&mysql_thd_attr);
+ }
+ else
+ vio_delete(vio);
+}
+
+
+C_MODE_START
+
+
+pthread_handler_decl(listener, arg)
+{
+ Listener_thread_args *args= (Listener_thread_args *) arg;
+ Listener_thread listener(*args);
+ listener.run();
+ /*
+ args is a stack variable because listener thread lives as long as the
+ manager process itself
+ */
+ return 0;
+}
+
+
+C_MODE_END
+
diff --git a/server-tools/instance-manager/listener.h b/server-tools/instance-manager/listener.h
new file mode 100644
index 00000000000..67a090c3aa2
--- /dev/null
+++ b/server-tools/instance-manager/listener.h
@@ -0,0 +1,56 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_LISTENER_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_LISTENER_H
+/* Copyright (C) 2003 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 */
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include <my_global.h>
+#include <my_pthread.h>
+
+
+C_MODE_START
+
+pthread_handler_decl(listener, arg);
+
+C_MODE_END
+
+class Thread_registry;
+struct Options;
+class User_map;
+class Instance_map;
+
+struct Listener_thread_args
+{
+ Thread_registry &thread_registry;
+ const Options &options;
+ const User_map &user_map;
+ Instance_map &instance_map;
+
+ Listener_thread_args(Thread_registry &thread_registry_arg,
+ const Options &options_arg,
+ const User_map &user_map_arg,
+ Instance_map &instance_map_arg) :
+ thread_registry(thread_registry_arg)
+ ,options(options_arg)
+ ,user_map(user_map_arg)
+ ,instance_map(instance_map_arg)
+ {}
+};
+
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_LISTENER_H
diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc
new file mode 100644
index 00000000000..3f54bc0649a
--- /dev/null
+++ b/server-tools/instance-manager/log.cc
@@ -0,0 +1,169 @@
+/* Copyright (C) 2003 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_global.h>
+
+#include "log.h"
+#include "portability.h"
+#include <stdarg.h>
+#include <m_string.h>
+#include <my_sys.h>
+
+/*
+ TODO:
+ - add flexible header support
+ - rewrite all fprintf with fwrite
+ - think about using 'write' instead of fwrite/fprintf on POSIX systems
+*/
+
+/*
+ Format log entry and write it to the given stream.
+ SYNOPSYS
+ log()
+*/
+
+static inline void log(FILE *file, const char *format, va_list args)
+{
+ /*
+ log() should be thread-safe; it implies that we either call fprintf()
+ once per log(), or use flockfile()/funlockfile(). But flockfile() is
+ POSIX, not ANSI C, so we try to vsnprintf the whole message to the
+ stack, and if stack buffer is not enough, to malloced string. When
+ message is formatted, it is fprintf()'ed to the file.
+ */
+
+ /* Format time like MYSQL_LOG does. */
+ time_t now= time(0);
+ struct tm bd_time; // broken-down time
+ localtime_r(&now, &bd_time);
+
+ char buff_date[32];
+ sprintf(buff_date, "%02d%02d%02d %2d:%02d:%02d\t",
+ bd_time.tm_year % 100,
+ bd_time.tm_mon + 1,
+ bd_time.tm_mday,
+ bd_time.tm_hour,
+ bd_time.tm_min,
+ bd_time.tm_sec);
+ /* Format the message */
+ char buff_stack[256];
+
+ int n= vsnprintf(buff_stack, sizeof(buff_stack), format, args);
+ /*
+ return value of vsnprintf can vary, according to various standards;
+ try to check all cases.
+ */
+ char *buff_msg= buff_stack;
+ if (n < 0 || n == sizeof(buff_stack))
+ {
+ int size= sizeof(buff_stack) * 2;
+ buff_msg= (char*) my_malloc(size, MYF(0));
+ while (true)
+ {
+ if (buff_msg == 0)
+ {
+ strmake(buff_stack, "log(): message is too big, my_malloc() failed",
+ sizeof(buff_stack) - 1);
+ buff_msg= buff_stack;
+ break;
+ }
+ n = vsnprintf(buff_msg, size, format, args);
+ if (n >= 0 && n < size)
+ break;
+ size*= 2;
+ /* realloc() does unnecessary memcpy */
+ my_free(buff_msg, 0);
+ buff_msg= (char*) my_malloc(size, MYF(0));
+ }
+ }
+ else if ((size_t) n > sizeof(buff_stack))
+ {
+ buff_msg= (char*) my_malloc(n + 1, MYF(0));
+#ifdef DBUG
+ DBUG_ASSERT(n == vsnprintf(buff_msg, n + 1, format, args));
+#else
+ vsnprintf(buff_msg, n + 1, format, args);
+#endif
+ }
+ fprintf(file, "%s%s\n", buff_date, buff_msg);
+ if (buff_msg != buff_stack)
+ my_free(buff_msg, 0);
+
+ /* don't fflush() the file: buffering strategy is set in log_init() */
+}
+
+
+void log_error(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ log(stderr, format, args);
+ va_end(args);
+}
+
+
+void log_info(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ log(stdout, format, args);
+ va_end(args);
+}
+
+/* TODO: rewrite with buffering print */
+void print_info(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfprintf(stdout, format, args);
+ va_end(args);
+}
+
+void print_error(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+}
+
+/*
+ log_init()
+ RETURN VALUE
+ 0 ok
+ !0 error
+*/
+
+void log_init()
+{
+ /*
+ stderr is unbuffered by default; there is no good of line buffering,
+ as all logging is performed linewise - so remove buffering from stdout
+ also
+ */
+ setbuf(stdout, 0);
+}
+
+void die(const char *format, ...)
+{
+ va_list args;
+ fprintf(stderr,"%s: ", my_progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
diff --git a/server-tools/instance-manager/log.h b/server-tools/instance-manager/log.h
new file mode 100644
index 00000000000..825d7515513
--- /dev/null
+++ b/server-tools/instance-manager/log.h
@@ -0,0 +1,81 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
+/* Copyright (C) 2003 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 */
+
+/*
+ Logging facilities.
+
+ Two logging streams are supported: error log and info log. Additionally
+ libdbug may be used for debug information output.
+ ANSI C buffered I/O is used to perform logging.
+ Logging is performed via stdout/stder, so one can reopen them to point to
+ ordinary files. To initialize loggin environment log_init() must be called.
+
+ Rationale:
+ - no MYSQL_LOG as it has BIN mode, and not easy to fetch from sql_class.h
+ - no constructors/desctructors to make logging available all the time
+ Function names are subject to change.
+*/
+
+
+/* Precede error message with date and time and print it to the stdout */
+void log_info(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format(printf, 1, 2)))
+#endif
+ ;
+
+
+/* Precede error message with date and time and print it to the stderr */
+void log_error(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+
+
+/*
+ Now this is simple catchouts for printf (no date/time is logged), to be
+ able to replace underlying streams in future.
+*/
+
+void print_info(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+
+
+void print_error(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+
+/* initialize logs */
+void log_init();
+
+
+/* print information to the error log and eixt(1) */
+
+void die(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc
new file mode 100644
index 00000000000..a42a25eadf3
--- /dev/null
+++ b/server-tools/instance-manager/manager.cc
@@ -0,0 +1,263 @@
+/* Copyright (C) 2003 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_global.h>
+#include "manager.h"
+
+#include "priv.h"
+#include "thread_registry.h"
+#include "listener.h"
+#include "instance_map.h"
+#include "options.h"
+#include "user_map.h"
+#include "log.h"
+#include "guardian.h"
+
+#include <my_sys.h>
+#include <m_string.h>
+#include <signal.h>
+#include <thr_alarm.h>
+#ifndef __WIN__
+#include <sys/wait.h>
+#endif
+
+
+static int create_pid_file(const char *pid_file_name)
+{
+ if (FILE *pid_file= my_fopen(pid_file_name,
+ O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
+ {
+ fprintf(pid_file, "%d\n", (int) getpid());
+ my_fclose(pid_file, MYF(0));
+ return 0;
+ }
+ log_error("can't create pid file %s: errno=%d, %s",
+ pid_file_name, errno, strerror(errno));
+ return 1;
+}
+
+#ifndef __WIN__
+void set_signals(sigset_t *mask)
+{
+ /* block signals */
+ sigemptyset(mask);
+ sigaddset(mask, SIGINT);
+ sigaddset(mask, SIGTERM);
+ sigaddset(mask, SIGPIPE);
+ sigaddset(mask, SIGHUP);
+ signal(SIGPIPE, SIG_IGN);
+
+ /*
+ We want this signal to be blocked in all theads but the signal
+ one. It is needed for the thr_alarm subsystem to work.
+ */
+ sigaddset(mask,THR_SERVER_ALARM);
+
+ /* all new threads will inherite this signal mask */
+ pthread_sigmask(SIG_BLOCK, mask, NULL);
+
+ /*
+ In our case the signal thread also implements functions of alarm thread.
+ Here we init alarm thread functionality. We suppose that we won't have
+ more then 10 alarms at the same time.
+ */
+ init_thr_alarm(10);
+}
+#else
+
+bool have_signal;
+
+void onsignal(int signo)
+{
+ have_signal= true;
+}
+
+void set_signals(sigset_t *set)
+{
+ signal(SIGINT, onsignal);
+ signal(SIGTERM, onsignal);
+ have_signal= false;
+}
+
+int my_sigwait(const sigset_t *set, int *sig)
+{
+ while (!have_signal)
+ {
+ Sleep(100);
+ }
+ return 0;
+}
+
+#endif
+
+
+/*
+ manager - entry point to the main instance manager process: start
+ listener thread, write pid file and enter into signal handling.
+ See also comments in mysqlmanager.cc to picture general Instance Manager
+ architecture.
+*/
+
+void manager(const Options &options)
+{
+ Thread_registry thread_registry;
+ /*
+ All objects created in the manager() function live as long as
+ thread_registry lives, and thread_registry is alive until there are
+ working threads.
+ */
+
+ User_map user_map;
+ Instance_map instance_map(options.default_mysqld_path);
+ Guardian_thread guardian_thread(thread_registry,
+ &instance_map,
+ options.monitoring_interval);
+
+ Listener_thread_args listener_args(thread_registry, options, user_map,
+ instance_map);
+
+ manager_pid= getpid();
+ instance_map.guardian= &guardian_thread;
+
+ if (instance_map.init() || user_map.init())
+ return;
+
+
+ if (instance_map.load())
+ {
+ log_error("Cannot init instances repository. This might be caused by "
+ "the wrong config file options. For instance, missing mysqld "
+ "binary. Aborting.");
+ return;
+ }
+
+ if (user_map.load(options.password_file_name))
+ return;
+
+ /* write pid file */
+ if (create_pid_file(options.pid_file_name))
+ return;
+
+ sigset_t mask;
+ set_signals(&mask);
+
+ /* create the listener */
+ {
+ pthread_t listener_thd_id;
+ pthread_attr_t listener_thd_attr;
+ int rc;
+
+ pthread_attr_init(&listener_thd_attr);
+ pthread_attr_setdetachstate(&listener_thd_attr, PTHREAD_CREATE_DETACHED);
+ rc= pthread_create(&listener_thd_id, &listener_thd_attr, listener,
+ &listener_args);
+ pthread_attr_destroy(&listener_thd_attr);
+ if (rc)
+ {
+ log_error("manager(): pthread_create(listener) failed");
+ goto err;
+ }
+
+ }
+
+ /* create guardian thread */
+ {
+ pthread_t guardian_thd_id;
+ pthread_attr_t guardian_thd_attr;
+ int rc;
+
+ /*
+ NOTE: Guardian should be shutdown first. Only then all other threads
+ need to be stopped. This should be done, as guardian is responsible for
+ shutting down the instances, and this is a long operation.
+ */
+
+ pthread_attr_init(&guardian_thd_attr);
+ pthread_attr_setdetachstate(&guardian_thd_attr, PTHREAD_CREATE_DETACHED);
+ rc= pthread_create(&guardian_thd_id, &guardian_thd_attr, guardian,
+ &guardian_thread);
+ pthread_attr_destroy(&guardian_thd_attr);
+ if (rc)
+ {
+ log_error("manager(): pthread_create(guardian) failed");
+ goto err;
+ }
+
+ }
+
+ /*
+ To work nicely with LinuxThreads, the signal thread is the first thread
+ in the process.
+ */
+ int signo;
+ bool shutdown_complete;
+
+ shutdown_complete= FALSE;
+
+ /* init list of guarded instances */
+ guardian_thread.lock();
+
+ guardian_thread.init();
+
+ guardian_thread.unlock();
+
+ /*
+ After the list of guarded instances have been initialized,
+ Guardian should start them.
+ */
+ pthread_cond_signal(&guardian_thread.COND_guardian);
+
+ while (!shutdown_complete)
+ {
+ int status= 0;
+
+ if ((status= my_sigwait(&mask, &signo)) != 0)
+ {
+ log_error("sigwait() failed");
+ goto err;
+ }
+
+#ifndef __WIN__
+ if (THR_SERVER_ALARM == signo)
+ process_alarm(signo);
+ else
+#endif
+ {
+ if (!guardian_thread.is_stopped())
+ {
+ bool stop_instances= true;
+ guardian_thread.request_shutdown(stop_instances);
+ pthread_cond_signal(&guardian_thread.COND_guardian);
+ }
+ else
+ {
+ thread_registry.deliver_shutdown();
+ shutdown_complete= TRUE;
+ }
+ }
+ }
+
+err:
+ /* delete the pid file */
+ my_delete(options.pid_file_name, MYF(0));
+
+#ifndef __WIN__
+ /* free alarm structures */
+ end_thr_alarm(1);
+ /* don't pthread_exit to kill all threads who did not shut down in time */
+#endif
+}
+
diff --git a/merge/mrg_static.c b/server-tools/instance-manager/manager.h
index 1b7327c870f..12ed6b3b1ff 100644
--- a/merge/mrg_static.c
+++ b/server-tools/instance-manager/manager.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
+/* Copyright (C) 2003 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
@@ -14,13 +16,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*
- Static variables for pisam library. All definied here for easy making of
- a shared library
-*/
+struct Options;
-#ifndef stdin
-#include "mrg_def.h"
-#endif
+void manager(const Options &options);
-LIST *mrg_open_list=0;
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
diff --git a/server-tools/instance-manager/messages.cc b/server-tools/instance-manager/messages.cc
new file mode 100644
index 00000000000..a9b00b9e01f
--- /dev/null
+++ b/server-tools/instance-manager/messages.cc
@@ -0,0 +1,89 @@
+/* Copyright (C) 2003 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_global.h>
+#include "messages.h"
+
+#include "mysqld_error.h"
+#include "mysql_manager_error.h"
+
+#include <mysql_com.h>
+#include <assert.h>
+
+
+static const char *mysqld_error_message(unsigned sql_errno)
+{
+ switch (sql_errno) {
+ case ER_HANDSHAKE_ERROR:
+ return "Bad handshake";
+ case ER_OUT_OF_RESOURCES:
+ return "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";
+ case ER_ACCESS_DENIED_ERROR:
+ return "Access denied. Bad username/password pair";
+ case ER_NOT_SUPPORTED_AUTH_MODE:
+ return "Client does not support authentication protocol requested by"
+ " server; consider upgrading MySQL client";
+ case ER_UNKNOWN_COM_ERROR:
+ return "Unknown command";
+ case ER_SYNTAX_ERROR:
+ return "You have an error in your command syntax. Check the manual that"
+ " corresponds to your MySQL Instance Manager version for the right"
+ " syntax to use";
+ case ER_BAD_INSTANCE_NAME:
+ return "Bad instance name. Check that the instance with such a name exists";
+ case ER_INSTANCE_IS_NOT_STARTED:
+ return "Cannot stop instance. Perhaps the instance is not started, or was started"
+ "manually, so IM cannot find the pidfile.";
+ case ER_INSTANCE_ALREADY_STARTED:
+ return "The instance is already started";
+ case ER_CANNOT_START_INSTANCE:
+ return "Cannot start instance. Possible reasons are wrong instance options"
+ " or resources shortage";
+ case ER_OFFSET_ERROR:
+ return "Cannot read negative number of bytes";
+ case ER_STOP_INSTANCE:
+ return "Cannot stop instance";
+ case ER_READ_FILE:
+ return "Cannot read requested part of the logfile";
+ case ER_NO_SUCH_LOG:
+ return "The instance has no such log enabled";
+ case ER_OPEN_LOGFILE:
+ return "Cannot open log file";
+ case ER_GUESS_LOGFILE:
+ return "Cannot guess the log filename. Try specifying full log name"
+ "in the instance options";
+ case ER_ACCESS_OPTION_FILE:
+ return "Cannot open the option file to edit. Check permissions";
+ default:
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
+
+const char *message(unsigned sql_errno)
+{
+ return mysqld_error_message(sql_errno);
+}
+
+
+const char *errno_to_sqlstate(unsigned sql_errno)
+{
+ return mysql_errno_to_sqlstate(sql_errno);
+}
diff --git a/merge/mrg_def.h b/server-tools/instance-manager/messages.h
index 8b6be08c32d..b771efe5e13 100644
--- a/merge/mrg_def.h
+++ b/server-tools/instance-manager/messages.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_MESSAGES_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_MESSAGES_H
+/* Copyright (C) 2003 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
@@ -14,16 +16,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Denna fil includeras i alla merge-filer */
+const char *message(unsigned sql_errno);
-#ifndef N_MAXKEY
-#include "../isam/isamdef.h"
-#endif
+const char *errno_to_sqlstate(unsigned sql_errno);
-#include "merge.h"
-
-extern LIST *mrg_open_list;
-
-#ifdef THREAD
-extern pthread_mutex_t THR_LOCK_open;
-#endif
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MESSAGES_H
diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc
new file mode 100644
index 00000000000..dfa12f6f6e2
--- /dev/null
+++ b/server-tools/instance-manager/mysql_connection.cc
@@ -0,0 +1,389 @@
+/* Copyright (C) 2003 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 */
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include "mysql_connection.h"
+
+#include "priv.h"
+#include "mysql_manager_error.h"
+#include "mysqld_error.h"
+#include "thread_registry.h"
+#include "log.h"
+#include "user_map.h"
+#include "protocol.h"
+#include "messages.h"
+#include "command.h"
+#include "parse.h"
+
+#include <mysql.h>
+#include <violite.h>
+#include <mysql_com.h>
+#include <m_string.h>
+#include <my_sys.h>
+
+
+Mysql_connection_thread_args::Mysql_connection_thread_args(
+ struct st_vio *vio_arg,
+ Thread_registry &thread_registry_arg,
+ const User_map &user_map_arg,
+ ulong connection_id_arg,
+ Instance_map &instance_map_arg) :
+ vio(vio_arg)
+ ,thread_registry(thread_registry_arg)
+ ,user_map(user_map_arg)
+ ,connection_id(connection_id_arg)
+ ,instance_map(instance_map_arg)
+ {}
+
+/*
+ MySQL connection - handle one connection with mysql command line client
+ See also comments in mysqlmanager.cc to picture general Instance Manager
+ architecture.
+ We use conventional technique to work with classes without exceptions:
+ class acquires all vital resource in init(); Thus if init() succeed,
+ a user must call cleanup(). All other methods are valid only between
+ init() and cleanup().
+*/
+
+class Mysql_connection_thread: public Mysql_connection_thread_args
+{
+public:
+ Mysql_connection_thread(const Mysql_connection_thread_args &args);
+
+ int init();
+ void cleanup();
+
+ void run();
+
+ ~Mysql_connection_thread();
+private:
+ Thread_info thread_info;
+ NET net;
+ struct rand_struct rand_st;
+ char scramble[SCRAMBLE_LENGTH + 1];
+ uint status;
+ ulong client_capabilities;
+private:
+ /* Names are conventionally the same as in mysqld */
+ int check_connection();
+ int do_command();
+ int dispatch_command(enum enum_server_command command,
+ const char *text, uint len);
+};
+
+
+Mysql_connection_thread::Mysql_connection_thread(
+ const Mysql_connection_thread_args &args) :
+ Mysql_connection_thread_args(args.vio,
+ args.thread_registry,
+ args.user_map,
+ args.connection_id,
+ args.instance_map)
+ ,thread_info(pthread_self())
+{
+ thread_registry.register_thread(&thread_info);
+}
+
+
+/*
+ NET subsystem requieres its user to provide my_net_local_init extern
+ C function (exactly as declared below). my_net_local_init is called by
+ my_net_init and is supposed to set NET controlling variables.
+ See also priv.h for variables description.
+*/
+
+C_MODE_START
+
+void my_net_local_init(NET *net)
+{
+ net->max_packet= net_buffer_length;
+ net->read_timeout= net_read_timeout;
+ net->write_timeout= net_write_timeout;
+ net->retry_count= net_retry_count;
+ net->max_packet_size= max_allowed_packet;
+}
+
+C_MODE_END
+
+
+/*
+ Every resource, which we can fail to acquire, is allocated in init().
+ This function is complementary to cleanup().
+*/
+
+int Mysql_connection_thread::init()
+{
+ /* Allocate buffers for network I/O */
+ if (my_net_init(&net, vio))
+ return 1;
+ net.return_status= &status;
+ /* Initialize random number generator */
+ {
+ ulong seed1= (ulong) &rand_st + rand();
+ ulong seed2= rand() + time(0);
+ randominit(&rand_st, seed1, seed2);
+ }
+ /* Fill scramble - server's random message used for handshake */
+ create_random_string(scramble, SCRAMBLE_LENGTH, &rand_st);
+ /* We don't support transactions, every query is atomic */
+ status= SERVER_STATUS_AUTOCOMMIT;
+ return 0;
+}
+
+
+void Mysql_connection_thread::cleanup()
+{
+ net_end(&net);
+}
+
+
+Mysql_connection_thread::~Mysql_connection_thread()
+{
+ /* vio_delete closes the socket if necessary */
+ vio_delete(vio);
+ thread_registry.unregister_thread(&thread_info);
+}
+
+
+void Mysql_connection_thread::run()
+{
+ log_info("accepted mysql connection %d", connection_id);
+
+ my_thread_init();
+
+ if (check_connection())
+ {
+ my_thread_end();
+ return;
+ }
+
+ log_info("connection %d is checked successfully", connection_id);
+
+ vio_keepalive(vio, TRUE);
+
+ while (!net.error && net.vio && !thread_registry.is_shutdown())
+ {
+ if (do_command())
+ break;
+ }
+
+ my_thread_end();
+}
+
+
+int Mysql_connection_thread::check_connection()
+{
+ ulong pkt_len=0; // to hold client reply length
+ /* maximum size of the version string */
+ enum { MAX_VERSION_LENGTH= 80 };
+
+ /* buffer for the first packet */ /* packet contains: */
+ char buff[MAX_VERSION_LENGTH + 1 + // server version, 0-ended
+ 4 + // connection id
+ SCRAMBLE_LENGTH + 2 + // scramble (in 2 pieces)
+ 18]; // server variables: flags,
+ // charset number, status,
+ char *pos= buff;
+ ulong server_flags;
+
+ memcpy(pos, mysqlmanager_version, mysqlmanager_version_length + 1);
+ pos+= mysqlmanager_version_length + 1;
+
+ int4store((uchar*) pos, connection_id);
+ pos+= 4;
+
+ /*
+ Old clients does not understand long scrambles, but can ignore packet
+ tail: that's why first part of the scramble is placed here, and second
+ part at the end of packet (even though we don't support old clients,
+ we must follow standard packet format.)
+ */
+ memcpy(pos, scramble, SCRAMBLE_LENGTH_323);
+ pos+= SCRAMBLE_LENGTH_323;
+ *pos++= '\0';
+
+ server_flags= CLIENT_LONG_FLAG | CLIENT_PROTOCOL_41 |
+ CLIENT_SECURE_CONNECTION;
+
+ /*
+ 18-bytes long section for various flags/variables
+
+ Every flag occupies a bit in first half of ulong; int2store will
+ gracefully pick up all flags.
+ */
+ int2store(pos, server_flags);
+ pos+= 2;
+ *pos++= (char) default_charset_info->number; // global mysys variable
+ int2store(pos, status); // connection status
+ pos+= 2;
+ bzero(pos, 13); // not used now
+ pos+= 13;
+
+ /* second part of the scramble, null-terminated */
+ memcpy(pos, scramble + SCRAMBLE_LENGTH_323,
+ SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1);
+ pos+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1;
+
+ /* write connection message and read reply */
+ enum { MIN_HANDSHAKE_SIZE= 2 };
+ if (net_write_command(&net, protocol_version, "", 0, buff, pos - buff) ||
+ (pkt_len= my_net_read(&net)) == packet_error ||
+ pkt_len < MIN_HANDSHAKE_SIZE)
+ {
+ net_send_error(&net, ER_HANDSHAKE_ERROR);
+ return 1;
+ }
+
+ client_capabilities= uint2korr(net.read_pos);
+ if (!(client_capabilities & CLIENT_PROTOCOL_41))
+ {
+ net_send_error_323(&net, ER_NOT_SUPPORTED_AUTH_MODE);
+ return 1;
+ }
+ client_capabilities|= ((ulong) uint2korr(net.read_pos + 2)) << 16;
+
+ pos= (char*) net.read_pos + 32;
+
+ /* At least one byte for username and one byte for password */
+ if (pos >= (char*) net.read_pos + pkt_len + 2)
+ {
+ /*TODO add user and password handling in error messages*/
+ net_send_error(&net, ER_HANDSHAKE_ERROR);
+ return 1;
+ }
+
+ const char *user= pos;
+ const char *password= strend(user)+1;
+ ulong password_len= *password++;
+ if (password_len != SCRAMBLE_LENGTH)
+ {
+ net_send_error(&net, ER_ACCESS_DENIED_ERROR);
+ return 1;
+ }
+ if (user_map.authenticate(user, password-user-2, password, scramble))
+ {
+ net_send_error(&net, ER_ACCESS_DENIED_ERROR);
+ return 1;
+ }
+ net_send_ok(&net, connection_id, NULL);
+ return 0;
+}
+
+
+int Mysql_connection_thread::do_command()
+{
+ char *packet;
+ ulong packet_length;
+
+ /* We start to count packets from 0 for each new command */
+ net.pkt_nr= 0;
+
+ if ((packet_length=my_net_read(&net)) == packet_error)
+ {
+ /* Check if we can continue without closing the connection */
+ if (net.error != 3) // what is 3 - find out
+ return 1;
+ if (thread_registry.is_shutdown())
+ return 1;
+ net_send_error(&net, net.last_errno);
+ net.error= 0;
+ return 0;
+ }
+ else
+ {
+ if (thread_registry.is_shutdown())
+ return 1;
+ packet= (char*) net.read_pos;
+ enum enum_server_command command= (enum enum_server_command)
+ (uchar) *packet;
+ log_info("connection %d: packet_length=%d, command=%d",
+ connection_id, packet_length, command);
+ return dispatch_command(command, packet + 1, packet_length - 1);
+ }
+}
+
+int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
+ const char *packet, uint len)
+{
+ switch (command) {
+ case COM_QUIT: // client exit
+ log_info("query for connection %d received quit command", connection_id);
+ return 1;
+ case COM_PING:
+ log_info("query for connection %d received ping command", connection_id);
+ net_send_ok(&net, connection_id, NULL);
+ break;
+ case COM_QUERY:
+ {
+ log_info("query for connection %d : ----\n%s\n-------------------------",
+ connection_id,packet);
+ if (Command *command= parse_command(&instance_map, packet))
+ {
+ int res= 0;
+ log_info("query for connection %d successefully parsed",connection_id);
+ res= command->execute(&net, connection_id);
+ delete command;
+ if (!res)
+ log_info("query for connection %d executed ok",connection_id);
+ else
+ {
+ log_info("query for connection %d executed err=%d",connection_id,res);
+ net_send_error(&net, res);
+ return 0;
+ }
+ }
+ else
+ {
+ net_send_error(&net,ER_OUT_OF_RESOURCES);
+ return 0;
+ }
+ break;
+ }
+ default:
+ log_info("query for connection %d received unknown command",connection_id);
+ net_send_error(&net, ER_UNKNOWN_COM_ERROR);
+ break;
+ }
+ return 0;
+}
+
+
+C_MODE_START
+
+pthread_handler_decl(mysql_connection, arg)
+{
+ Mysql_connection_thread_args *args= (Mysql_connection_thread_args *) arg;
+ Mysql_connection_thread mysql_connection_thread(*args);
+ delete args;
+ if (mysql_connection_thread.init())
+ log_info("mysql_connection(): error initializing thread");
+ else
+ {
+ mysql_connection_thread.run();
+ mysql_connection_thread.cleanup();
+ }
+ return 0;
+}
+
+C_MODE_END
+
+
+/*
+ vim: fdm=marker
+*/
diff --git a/server-tools/instance-manager/mysql_connection.h b/server-tools/instance-manager/mysql_connection.h
new file mode 100644
index 00000000000..e0109ce234f
--- /dev/null
+++ b/server-tools/instance-manager/mysql_connection.h
@@ -0,0 +1,54 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H
+/* Copyright (C) 2003 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 */
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include <my_global.h>
+#include <my_pthread.h>
+
+
+C_MODE_START
+
+pthread_handler_decl(mysql_connection, arg);
+
+C_MODE_END
+
+
+class Thread_registry;
+class User_map;
+class Instance_map;
+struct st_vio;
+
+struct Mysql_connection_thread_args
+{
+ struct st_vio *vio;
+ Thread_registry &thread_registry;
+ const User_map &user_map;
+ ulong connection_id;
+ Instance_map &instance_map;
+
+ Mysql_connection_thread_args(struct st_vio *vio_arg,
+ Thread_registry &thread_registry_arg,
+ const User_map &user_map_arg,
+ ulong connection_id_arg,
+ Instance_map &instance_map_arg);
+};
+
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H
diff --git a/server-tools/instance-manager/mysql_manager_error.h b/server-tools/instance-manager/mysql_manager_error.h
new file mode 100644
index 00000000000..ff782923a8e
--- /dev/null
+++ b/server-tools/instance-manager/mysql_manager_error.h
@@ -0,0 +1,33 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Definefile for instance manager error messagenumbers */
+
+#define ER_BAD_INSTANCE_NAME 3000
+#define ER_INSTANCE_IS_NOT_STARTED 3001
+#define ER_INSTANCE_ALREADY_STARTED 3002
+#define ER_CANNOT_START_INSTANCE 3003
+#define ER_STOP_INSTANCE 3004
+#define ER_NO_SUCH_LOG 3005
+#define ER_OPEN_LOGFILE 3006
+#define ER_GUESS_LOGFILE 3007
+#define ER_ACCESS_OPTION_FILE 3008
+#define ER_OFFSET_ERROR 3009
+#define ER_READ_FILE 3010
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */
diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc
new file mode 100644
index 00000000000..3d2907f4776
--- /dev/null
+++ b/server-tools/instance-manager/mysqlmanager.cc
@@ -0,0 +1,361 @@
+/* Copyright (C) 2003 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_global.h>
+#include "manager.h"
+
+#include "options.h"
+#include "log.h"
+
+#include <my_sys.h>
+#include <string.h>
+#include <signal.h>
+#ifndef __WIN__
+#include <pwd.h>
+#include <grp.h>
+#include <sys/wait.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef __WIN__
+#include "windowsservice.h"
+#endif
+
+/*
+ Few notes about Instance Manager architecture:
+ Instance Manager consisits of two processes: the angel process, and the
+ instance manager process. Responsibilities of the angel process is to
+ monitor the instance manager process, and restart it in case of
+ failure/shutdown. The angel process is started only if startup option
+ '--run-as-service' is provided.
+ The Instance Manager process consists of several
+ subsystems (thread sets):
+ - the signal handling thread: it's responsibilities are to handle
+ user signals and propogate them to the other threads. All other threads
+ are accounted in the signal handler thread Thread Registry.
+ - the listener: listens all sockets. There is a listening
+ socket for each (mysql, http, snmp, rendezvous (?)) subsystem.
+ - mysql subsystem: Instance Manager acts like an ordinary MySQL Server,
+ but with very restricted command set. Each MySQL client connection is
+ handled in a separate thread. All MySQL client connections threads
+ constitute mysql subsystem.
+ - http subsystem: it is also possible to talk with Instance Manager via
+ http. One thread per http connection is used. Threads are pooled.
+ - 'snmp' connections (FIXME: I know nothing about it yet)
+ - rendezvous threads
+*/
+
+static void init_environment(char *progname);
+#ifndef __WIN__
+static void daemonize(const char *log_file_name);
+static void angel(const Options &options);
+static struct passwd *check_user(const char *user);
+static int set_user(const char *user, struct passwd *user_info);
+#else
+int HandleServiceOptions(Options options);
+#endif
+
+
+/*
+ main, entry point
+ - init environment
+ - handle options
+ - daemonize and run angel process (if necessary)
+ - run manager process
+*/
+
+int main(int argc, char *argv[])
+{
+ int return_value= 1;
+ init_environment(argv[0]);
+ Options options;
+ struct passwd *user_info;
+
+ if (options.load(argc, argv))
+ goto err;
+
+#ifndef __WIN__
+ if ((user_info= check_user(options.user)))
+ {
+ if (set_user(options.user, user_info))
+ goto err;
+ }
+
+ if (options.run_as_service)
+ {
+ /* forks, and returns only in child */
+ daemonize(options.log_file_name);
+ /* forks again, and returns only in child: parent becomes angel */
+ angel(options);
+ }
+#else
+ if (!options.stand_alone)
+ {
+ if (HandleServiceOptions(options))
+ goto err;
+ }
+ else
+#endif
+
+ manager(options);
+ return_value= 0;
+
+err:
+ options.cleanup();
+ my_end(0);
+ return return_value;
+}
+
+/******************* Auxilary functions implementation **********************/
+
+#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
+/* Change to run as another user if started with --user */
+
+static struct passwd *check_user(const char *user)
+{
+ struct passwd *user_info;
+ uid_t user_id= geteuid();
+
+ /* Don't bother if we aren't superuser */
+ if (user_id)
+ {
+ if (user)
+ {
+ /* Don't give a warning, if real user is same as given with --user */
+ user_info= getpwnam(user);
+ if ((!user_info || user_id != user_info->pw_uid))
+ log_info("One can only use the --user switch if running as root\n");
+ }
+ return NULL;
+ }
+ if (!user)
+ {
+ log_info("You are running mysqlmanager as root! This might introduce security problems. It is safer to use --user option istead.\n");
+ return NULL;
+ }
+ if (!strcmp(user, "root"))
+ return NULL; /* Avoid problem with dynamic libraries */
+ if (!(user_info= getpwnam(user)))
+ {
+ /* Allow a numeric uid to be used */
+ const char *pos;
+ for (pos= user; my_isdigit(default_charset_info, *pos); pos++)
+ {}
+ if (*pos) /* Not numeric id */
+ goto err;
+ if (!(user_info= getpwuid(atoi(user))))
+ goto err;
+ else
+ return user_info;
+ }
+ else
+ return user_info;
+
+err:
+ log_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n", user);
+ return NULL;
+}
+
+static int set_user(const char *user, struct passwd *user_info)
+{
+ DBUG_ASSERT(user_info);
+#ifdef HAVE_INITGROUPS
+ initgroups((char*) user,user_info->pw_gid);
+#endif
+ if (setgid(user_info->pw_gid) == -1)
+ {
+ log_error("setgid() failed");
+ return 1;
+ }
+ if (setuid(user_info->pw_uid) == -1)
+ {
+ log_error("setuid() failed");
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+
+/*
+ Init environment, common for daemon and non-daemon
+*/
+
+static void init_environment(char *progname)
+{
+ MY_INIT(progname);
+ log_init();
+ umask(0117);
+ srand(time(0));
+}
+
+
+#ifndef __WIN__
+/*
+ Become a UNIX service
+ SYNOPSYS
+ daemonize()
+*/
+
+static void daemonize(const char *log_file_name)
+{
+ pid_t pid= fork();
+ switch (pid) {
+ case -1: // parent, fork error
+ die("daemonize(): fork failed, %s", strerror(errno));
+ case 0: // child, fork ok
+ int fd;
+ /*
+ Become a session leader: setsid must succeed because child is
+ guaranteed not to be a process group leader (it belongs to the
+ process group of the parent.)
+ The goal is not to have a controlling terminal.
+ */
+ setsid();
+ /*
+ As we now don't have a controlling terminal we will not receive
+ tty-related signals - no need to ignore them.
+ */
+
+ close(STDIN_FILENO);
+
+ fd= open(log_file_name, O_WRONLY | O_CREAT | O_APPEND | O_NOCTTY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (fd < 0)
+ die("daemonize(): failed to open log file %s, %s", log_file_name,
+ strerror(errno));
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd != STDOUT_FILENO && fd != STDERR_FILENO)
+ close(fd);
+
+ /* TODO: chroot() and/or chdir() here */
+ break;
+ default:
+ /* successfully exit from parent */
+ exit(0);
+ }
+}
+
+
+enum { CHILD_OK= 0, CHILD_NEED_RESPAWN, CHILD_EXIT_ANGEL };
+
+static volatile sig_atomic_t child_status= CHILD_OK;
+
+/*
+ Signal handler for SIGCHLD: reap child, analyze child exit status, and set
+ child_status appropriately.
+*/
+
+void reap_child(int __attribute__((unused)) signo)
+{
+ int child_exit_status;
+ /* As we have only one child, no need to cycle waitpid */
+ if (waitpid(0, &child_exit_status, WNOHANG) > 0)
+ {
+ if (WIFSIGNALED(child_exit_status))
+ child_status= CHILD_NEED_RESPAWN;
+ else
+ /*
+ As reap_child is not called for SIGSTOP, we should be here only
+ if the child exited normally.
+ */
+ child_status= CHILD_EXIT_ANGEL;
+ }
+}
+
+static volatile sig_atomic_t is_terminated= 0;
+
+/*
+ Signal handler for terminate signals - SIGTERM, SIGHUP, SIGINT.
+ Set termination status and return.
+ (q) do we need to handle SIGQUIT?
+*/
+
+void terminate(int signo)
+{
+ is_terminated= signo;
+}
+
+
+/*
+ Fork a child and monitor it.
+ User can explicitly kill the angel process with SIGTERM/SIGHUP/SIGINT.
+ Angel process will exit silently if mysqlmanager exits normally.
+*/
+
+static void angel(const Options &options)
+{
+ /* install signal handlers */
+ sigset_t zeromask; // to sigsuspend in parent
+ struct sigaction sa_chld, sa_term;
+ struct sigaction sa_chld_out, sa_term_out, sa_int_out, sa_hup_out;
+
+ sigemptyset(&zeromask);
+ sigemptyset(&sa_chld.sa_mask);
+ sigemptyset(&sa_term.sa_mask);
+
+ sa_chld.sa_handler= reap_child;
+ sa_chld.sa_flags= SA_NOCLDSTOP;
+ sa_term.sa_handler= terminate;
+ sa_term.sa_flags= 0;
+
+ /* sigaction can fail only on wrong arguments */
+ sigaction(SIGCHLD, &sa_chld, &sa_chld_out);
+ sigaction(SIGTERM, &sa_term, &sa_term_out);
+ sigaction(SIGINT, &sa_term, &sa_int_out);
+ sigaction(SIGHUP, &sa_term, &sa_hup_out);
+
+ /* spawn a child */
+spawn:
+ pid_t pid= fork();
+ switch (pid) {
+ case -1:
+ die("angel(): fork failed, %s", strerror(errno));
+ case 0: // child, success
+ /*
+ restore default actions for signals to let the manager work with
+ signals as he wishes
+ */
+ sigaction(SIGCHLD, &sa_chld_out, 0);
+ sigaction(SIGTERM, &sa_term_out, 0);
+ sigaction(SIGINT, &sa_int_out, 0);
+ sigaction(SIGHUP, &sa_hup_out, 0);
+ /* Here we return to main, and fall into manager */
+ break;
+ default: // parent, success
+ while (child_status == CHILD_OK && is_terminated == 0)
+ sigsuspend(&zeromask);
+
+ if (is_terminated)
+ log_info("angel got signal %d, exiting", is_terminated);
+ else if (child_status == CHILD_NEED_RESPAWN)
+ {
+ child_status= CHILD_OK;
+ log_error("angel(): mysqlmanager exited abnormally: respawning...");
+ sleep(1); /* don't respawn too fast */
+ goto spawn;
+ }
+ /*
+ mysqlmanager successfully exited, let's silently evaporate
+ If we return to main we fall into the manager() function, so let's
+ simply exit().
+ */
+ exit(0);
+ }
+}
+
+#endif
diff --git a/server-tools/instance-manager/mysqlmanager.vcproj b/server-tools/instance-manager/mysqlmanager.vcproj
new file mode 100644
index 00000000000..a5ef7cb21e3
--- /dev/null
+++ b/server-tools/instance-manager/mysqlmanager.vcproj
@@ -0,0 +1,373 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="mysqlmanager"
+ ProjectGUID="{6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include,../../extra/yassl/include"
+ PreprocessorDefinitions="MYSQL_INSTANCE_MANAGER;MYSQL_SERVER;_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;CONSOLE"
+ MinimalRebuild="TRUE"
+ ExceptionHandling="FALSE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib"
+ OutputFile="$(OutDir)/mysqlmanager.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/mysqlmanager.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\include,../../extra/yassl/include"
+ PreprocessorDefinitions="MYSQL_INSTANCE_MANAGER;MYSQL_SERVER;_WINDOWS;CONSOLE"
+ ExceptionHandling="FALSE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wsock32.lib"
+ OutputFile="$(OutDir)/mysqlmanager.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath=".\buffer.cpp">
+ </File>
+ <File
+ RelativePath="..\..\sql\client.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\command.cpp">
+ </File>
+ <File
+ RelativePath=".\commands.cpp">
+ </File>
+ <File
+ RelativePath="..\..\libmysql\get_password.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\guardian.cpp">
+ </File>
+ <File
+ RelativePath=".\IMService.cpp">
+ </File>
+ <File
+ RelativePath=".\instance.cpp">
+ </File>
+ <File
+ RelativePath=".\instance_map.cpp">
+ </File>
+ <File
+ RelativePath=".\instance_options.cpp">
+ </File>
+ <File
+ RelativePath=".\listener.cpp">
+ </File>
+ <File
+ RelativePath=".\log.cpp">
+ </File>
+ <File
+ RelativePath=".\manager.cpp">
+ </File>
+ <File
+ RelativePath=".\messages.cpp">
+ </File>
+ <File
+ RelativePath="..\..\sql\mini_client_errors.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\mysql_connection.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\mysqlmanager.cpp">
+ </File>
+ <File
+ RelativePath="..\..\sql\net_serv.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\options.cpp">
+ </File>
+ <File
+ RelativePath="..\..\sql\pack.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\parse.cpp">
+ </File>
+ <File
+ RelativePath=".\parse_output.cpp">
+ </File>
+ <File
+ RelativePath="..\..\sql\password.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\priv.cpp">
+ </File>
+ <File
+ RelativePath=".\protocol.cpp">
+ </File>
+ <File
+ RelativePath="..\..\sql\sql_state.c">
+ </File>
+ <File
+ RelativePath=".\thread_registry.cpp">
+ </File>
+ <File
+ RelativePath=".\user_map.cpp">
+ </File>
+ <File
+ RelativePath=".\WindowsService.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath=".\buffer.h">
+ </File>
+ <File
+ RelativePath=".\command.h">
+ </File>
+ <File
+ RelativePath=".\commands.h">
+ </File>
+ <File
+ RelativePath=".\factory.h">
+ </File>
+ <File
+ RelativePath=".\guardian.h">
+ </File>
+ <File
+ RelativePath=".\IMService.h">
+ </File>
+ <File
+ RelativePath=".\instance.h">
+ </File>
+ <File
+ RelativePath=".\instance_map.h">
+ </File>
+ <File
+ RelativePath=".\instance_options.h">
+ </File>
+ <File
+ RelativePath=".\listener.h">
+ </File>
+ <File
+ RelativePath=".\log.h">
+ </File>
+ <File
+ RelativePath=".\manager.h">
+ </File>
+ <File
+ RelativePath=".\messages.h">
+ </File>
+ <File
+ RelativePath=".\mysql_connection.h">
+ </File>
+ <File
+ RelativePath=".\mysql_manager_error.h">
+ </File>
+ <File
+ RelativePath=".\options.h">
+ </File>
+ <File
+ RelativePath=".\parse.h">
+ </File>
+ <File
+ RelativePath=".\parse_output.h">
+ </File>
+ <File
+ RelativePath=".\portability.h">
+ </File>
+ <File
+ RelativePath=".\priv.h">
+ </File>
+ <File
+ RelativePath=".\protocol.h">
+ </File>
+ <File
+ RelativePath=".\thread_registry.h">
+ </File>
+ <File
+ RelativePath=".\user_map.h">
+ </File>
+ <File
+ RelativePath=".\WindowsService.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc
new file mode 100644
index 00000000000..74ccade3a2c
--- /dev/null
+++ b/server-tools/instance-manager/options.cc
@@ -0,0 +1,321 @@
+/* Copyright (C) 2003 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 */
+
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+#include "options.h"
+
+#include "priv.h"
+#include "portability.h"
+#include <my_sys.h>
+#include <my_getopt.h>
+#include <m_string.h>
+#include <mysql_com.h>
+
+#define QUOTE2(x) #x
+#define QUOTE(x) QUOTE2(x)
+
+#ifdef __WIN__
+char Options::install_as_service;
+char Options::remove_service;
+char Options::stand_alone;
+char windows_config_file[FN_REFLEN];
+char default_password_file_name[FN_REFLEN];
+char default_log_file_name[FN_REFLEN];
+const char *Options::config_file= windows_config_file;
+#else
+char Options::run_as_service;
+const char *Options::user= 0; /* No default value */
+const char *default_password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME);
+const char *default_log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
+const char *Options::config_file= QUOTE(DEFAULT_CONFIG_FILE);
+#endif
+const char *Options::log_file_name= default_log_file_name;
+const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
+const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
+const char *Options::password_file_name= default_password_file_name;
+const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
+const char *Options::bind_address= 0; /* No default value */
+uint Options::monitoring_interval= DEFAULT_MONITORING_INTERVAL;
+uint Options::port_number= DEFAULT_PORT;
+/* just to declare */
+char **Options::saved_argv= NULL;
+
+/*
+ List of options, accepted by the instance manager.
+ List must be closed with empty option.
+*/
+
+enum options {
+ OPT_LOG= 256,
+ OPT_PID_FILE,
+ OPT_SOCKET,
+ OPT_PASSWORD_FILE,
+ OPT_MYSQLD_PATH,
+#ifndef __WIN__
+ OPT_RUN_AS_SERVICE,
+ OPT_USER,
+#else
+ OPT_INSTALL_SERVICE,
+ OPT_REMOVE_SERVICE,
+ OPT_STAND_ALONE,
+#endif
+ OPT_MONITORING_INTERVAL,
+ OPT_PORT,
+ OPT_BIND_ADDRESS
+};
+
+static struct my_option my_long_options[] =
+{
+ { "help", '?', "Display this help and exit.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "log", OPT_LOG, "Path to log file. Used only with --run-as-service.",
+ (gptr *) &Options::log_file_name, (gptr *) &Options::log_file_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "pid-file", OPT_PID_FILE, "Pid file to use.",
+ (gptr *) &Options::pid_file_name, (gptr *) &Options::pid_file_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "socket", OPT_SOCKET, "Socket file to use for connection.",
+ (gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "passwd", 'P', "Prepare entry for passwd file and exit.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.",
+ (gptr *) &Options::bind_address, (gptr *) &Options::bind_address,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "port", OPT_PORT, "Port number to use for connections",
+ (gptr *) &Options::port_number, (gptr *) &Options::port_number,
+ 0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 },
+
+ { "password-file", OPT_PASSWORD_FILE, "Look for Instance Manager users"
+ " and passwords here.",
+ (gptr *) &Options::password_file_name,
+ (gptr *) &Options::password_file_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "default-mysqld-path", OPT_MYSQLD_PATH, "Where to look for MySQL"
+ " Server binary.",
+ (gptr *) &Options::default_mysqld_path,
+ (gptr *) &Options::default_mysqld_path,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "monitoring-interval", OPT_MONITORING_INTERVAL, "Interval to monitor"
+ " instances in seconds.",
+ (gptr *) &Options::monitoring_interval,
+ (gptr *) &Options::monitoring_interval,
+ 0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL,
+ 0, 0, 0, 0, 0 },
+#ifdef __WIN__
+ { "install", OPT_INSTALL_SERVICE, "Install as system service.",
+ (gptr *) &Options::install_as_service, (gptr*) &Options::install_as_service,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
+ { "remove", OPT_REMOVE_SERVICE, "Remove system service.",
+ (gptr *)&Options::remove_service, (gptr*) &Options::remove_service,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
+ { "standalone", OPT_STAND_ALONE, "Run the application in stand alone mode.",
+ (gptr *)&Options::stand_alone, (gptr*) &Options::stand_alone,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
+#else
+ { "run-as-service", OPT_RUN_AS_SERVICE,
+ "Daemonize and start angel process.", (gptr *) &Options::run_as_service,
+ 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
+
+ { "user", OPT_USER, "Username to start mysqlmanager",
+ (gptr *) &Options::user,
+ (gptr *) &Options::user,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+#endif
+ { "version", 'V', "Output version information and exit.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
+};
+
+static void version()
+{
+ printf("%s Ver %s for %s on %s\n", my_progname, mysqlmanager_version,
+ SYSTEM_TYPE, MACHINE_TYPE);
+}
+
+
+static const char *default_groups[]= { "manager", 0 };
+
+
+static void usage()
+{
+ version();
+
+ printf("Copyright (C) 2003, 2004 MySQL AB\n"
+ "This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
+ "and you are welcome to modify and redistribute it under the GPL license\n");
+ printf("Usage: %s [OPTIONS] \n", my_progname);
+
+ my_print_help(my_long_options);
+ printf("\nThe following options may be given as the first argument:\n"
+ "--print-defaults Print the program argument list and exit\n"
+ "--defaults-file=# Only read manager configuration and instance\n"
+ " setings from the given file #. The same file\n"
+ " will be used to modify configuration of instances\n"
+ " with SET commands.\n");
+ my_print_variables(my_long_options);
+}
+
+
+static void passwd()
+{
+ char user[1024], *p;
+ const char *pw1, *pw2;
+ char pw1msg[]= "Enter password: ";
+ char pw2msg[]= "Re-type password: ";
+ char crypted_pw[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
+
+ fprintf(stderr, "Creating record for new user.\n");
+ fprintf(stderr, "Enter user name: ");
+ if (!fgets(user, sizeof(user), stdin))
+ {
+ fprintf(stderr, "Unable to read user.\n");
+ return;
+ }
+ if ((p= strchr(user, '\n'))) *p= 0;
+
+ pw1= get_tty_password(pw1msg);
+ pw2= get_tty_password(pw2msg);
+
+ if (strcmp(pw1, pw2))
+ {
+ fprintf(stderr, "Sorry, passwords do not match.\n");
+ return;
+ }
+
+ make_scrambled_password(crypted_pw, pw1);
+ printf("%s:%s\n", user, crypted_pw);
+}
+
+
+C_MODE_START
+
+static my_bool
+get_one_option(int optid,
+ const struct my_option *opt __attribute__((unused)),
+ char *argument __attribute__((unused)))
+{
+ switch(optid) {
+ case 'V':
+ version();
+ exit(0);
+ case 'P':
+ passwd();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ }
+ return 0;
+}
+
+C_MODE_END
+
+
+/*
+ - Process argv of original program: get tid of --defaults-extra-file
+ and print a message if met there.
+ - call load_defaults to load configuration file section and save the pointer
+ for free_defaults.
+ - call handle_options to assign defaults and command-line arguments
+ to the class members.
+ if either of these function fail, return the error code.
+*/
+
+int Options::load(int argc, char **argv)
+{
+ if (argc >= 2)
+ {
+ if (is_prefix(argv[1], "--defaults-file="))
+ {
+ Options::config_file= strchr(argv[1], '=') + 1;
+ }
+ if (is_prefix(argv[1], "--defaults-extra-file=") ||
+ is_prefix(argv[1], "--no-defaults"))
+ {
+ /* the log is not enabled yet */
+ fprintf(stderr, "The --defaults-extra-file and --no-defaults options"
+ " are not supported by\n"
+ "Instance Manager. Program aborted.\n");
+ goto err;
+ }
+ }
+
+#ifdef __WIN__
+ if (setup_windows_defaults())
+ goto err;
+#endif
+ /* load_defaults will reset saved_argv with a new allocated list */
+ saved_argv= argv;
+
+ /* config-file options are prepended to command-line ones */
+ load_defaults(config_file, default_groups, &argc,
+ &saved_argv);
+
+ if ((handle_options(&argc, &saved_argv, my_long_options,
+ get_one_option)) != 0)
+ goto err;
+
+ return 0;
+
+err:
+ return 1;
+}
+
+void Options::cleanup()
+{
+ /* free_defaults returns nothing */
+ if (Options::saved_argv != NULL)
+ free_defaults(Options::saved_argv);
+}
+
+#ifdef __WIN__
+
+int Options::setup_windows_defaults()
+{
+ if (!GetModuleFileName(NULL, default_password_file_name,
+ sizeof(default_password_file_name)))
+ return 1;
+ char *filename= strstr(default_password_file_name, ".exe");
+ strcpy(filename, ".passwd");
+
+ if (!GetModuleFileName(NULL, default_log_file_name,
+ sizeof(default_log_file_name)))
+ return 1;
+ filename= strstr(default_log_file_name, ".exe");
+ strcpy(filename, ".log");
+
+ if (!GetModuleFileName(NULL, windows_config_file,
+ sizeof(windows_config_file)))
+ return 1;
+ char *slash= strrchr(windows_config_file, '\\');
+ strcpy(slash, "\\my.ini");
+ return 0;
+}
+
+#endif
diff --git a/server-tools/instance-manager/options.h b/server-tools/instance-manager/options.h
new file mode 100644
index 00000000000..a5cd049decf
--- /dev/null
+++ b/server-tools/instance-manager/options.h
@@ -0,0 +1,60 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
+/* Copyright (C) 2003 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 */
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+/*
+ Options - all possible options for the instance manager grouped in one
+ struct.
+*/
+#include <my_global.h>
+
+struct Options
+{
+#ifdef __WIN__
+ static char install_as_service;
+ static char remove_service;
+ static char stand_alone;
+#else
+ static char run_as_service; /* handle_options doesn't support bool */
+ static const char *user;
+#endif
+ static const char *log_file_name;
+ static const char *pid_file_name;
+ static const char *socket_file_name;
+ static const char *password_file_name;
+ static const char *default_mysqld_path;
+ /* the option which should be passed to process_default_option_files */
+ static uint monitoring_interval;
+ static uint port_number;
+ static const char *bind_address;
+ static const char *config_file;
+
+ /* argv pointer returned by load_defaults() to be used by free_defaults() */
+ static char **saved_argv;
+
+ int load(int argc, char **argv);
+ void cleanup();
+#ifdef __WIN__
+ int setup_windows_defaults();
+#endif
+};
+
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc
new file mode 100644
index 00000000000..d83af2b9cf0
--- /dev/null
+++ b/server-tools/instance-manager/parse.cc
@@ -0,0 +1,323 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "parse.h"
+#include "commands.h"
+
+#include <string.h>
+
+
+enum Token
+{
+ TOK_ERROR= 0, /* Encodes the "ERROR" word, it doesn't indicate error. */
+ TOK_FILES,
+ TOK_FLUSH,
+ TOK_GENERAL,
+ TOK_INSTANCE,
+ TOK_INSTANCES,
+ TOK_LOG,
+ TOK_OPTIONS,
+ TOK_SET,
+ TOK_SLOW,
+ TOK_START,
+ TOK_STATUS,
+ TOK_STOP,
+ TOK_SHOW,
+ TOK_UNSET,
+ TOK_NOT_FOUND, // must be after all tokens
+ TOK_END
+};
+
+
+struct tokens_st
+{
+ uint length;
+ const char *tok_name;
+};
+
+
+static struct tokens_st tokens[]= {
+ {5, "ERROR"},
+ {5, "FILES"},
+ {5, "FLUSH"},
+ {7, "GENERAL"},
+ {8, "INSTANCE"},
+ {9, "INSTANCES"},
+ {3, "LOG"},
+ {7, "OPTIONS"},
+ {3, "SET"},
+ {4, "SLOW"},
+ {5, "START"},
+ {6, "STATUS"},
+ {4, "STOP"},
+ {4, "SHOW"},
+ {5, "UNSET"}
+};
+
+
+/*
+ Returns token no if word corresponds to some token, otherwise returns
+ TOK_NOT_FOUND
+*/
+
+inline Token find_token(const char *word, uint word_len)
+{
+ int i= 0;
+ do
+ {
+ if (my_strnncoll(default_charset_info, (const uchar *) tokens[i].tok_name,
+ tokens[i].length, (const uchar *) word, word_len) == 0)
+ break;
+ }
+ while (++i < TOK_NOT_FOUND);
+ return (Token) i;
+}
+
+
+Token get_token(const char **text, uint *word_len)
+{
+ get_word(text, word_len);
+ if (*word_len)
+ return find_token(*text, *word_len);
+ return TOK_END;
+}
+
+
+Token shift_token(const char **text, uint *word_len)
+{
+ Token save= get_token(text, word_len);
+ (*text)+= *word_len;
+ return save;
+}
+
+
+int get_text_id(const char **text, uint *word_len, const char **id)
+{
+ get_word(text, word_len);
+ if (word_len == 0)
+ return 1;
+ *id= *text;
+ return 0;
+}
+
+
+Command *parse_command(Instance_map *map, const char *text)
+{
+ uint word_len;
+ const char *instance_name;
+ uint instance_name_len;
+ const char *option;
+ uint option_len;
+ const char *option_value;
+ uint option_value_len;
+ const char *log_size;
+ Command *command;
+ const char *saved_text= text;
+ bool skip= false;
+ const char *tmp;
+
+ Token tok1= shift_token(&text, &word_len);
+
+ switch (tok1) {
+ case TOK_START: // fallthrough
+ case TOK_STOP:
+ if (shift_token(&text, &word_len) != TOK_INSTANCE)
+ goto syntax_error;
+ get_word(&text, &word_len);
+ if (word_len == 0)
+ goto syntax_error;
+ instance_name= text;
+ instance_name_len= word_len;
+ text+= word_len;
+ /* it should be the end of command */
+ get_word(&text, &word_len);
+ if (word_len)
+ goto syntax_error;
+
+ if (tok1 == TOK_START)
+ command= new Start_instance(map, instance_name, instance_name_len);
+ else
+ command= new Stop_instance(map, instance_name, instance_name_len);
+ break;
+ case TOK_FLUSH:
+ if (shift_token(&text, &word_len) != TOK_INSTANCES)
+ goto syntax_error;
+
+ get_word(&text, &word_len);
+ if (word_len)
+ goto syntax_error;
+
+ command= new Flush_instances(map);
+ break;
+ case TOK_UNSET:
+ skip= true;
+ case TOK_SET:
+
+ get_text_id(&text, &instance_name_len, &instance_name);
+ text+= instance_name_len;
+
+ /* the next token should be a dot */
+ get_word(&text, &word_len);
+ if (*text != '.')
+ goto syntax_error;
+ text++;
+
+ get_word(&text, &option_len, NONSPACE);
+ option= text;
+ if ((tmp= strchr(text, '=')) != NULL)
+ option_len= tmp - text;
+ text+= option_len;
+
+ get_word(&text, &word_len);
+ if (*text == '=')
+ {
+ text++; /* skip '=' */
+ get_word(&text, &option_value_len, NONSPACE);
+ option_value= text;
+ text+= option_value_len;
+ }
+ else
+ {
+ option_value= "";
+ option_value_len= 0;
+ }
+
+ /* should be empty */
+ get_word(&text, &word_len);
+ if (word_len)
+ goto syntax_error;
+
+ if (skip)
+ command= new Unset_option(map, instance_name, instance_name_len,
+ option, option_len, option_value,
+ option_value_len);
+ else
+ command= new Set_option(map, instance_name, instance_name_len,
+ option, option_len, option_value,
+ option_value_len);
+ break;
+ case TOK_SHOW:
+ switch (shift_token(&text, &word_len)) {
+ case TOK_INSTANCES:
+ get_word(&text, &word_len);
+ if (word_len)
+ goto syntax_error;
+ command= new Show_instances(map);
+ break;
+ case TOK_INSTANCE:
+ switch (Token tok2= shift_token(&text, &word_len)) {
+ case TOK_OPTIONS:
+ case TOK_STATUS:
+ get_text_id(&text, &instance_name_len, &instance_name);
+ text+= instance_name_len;
+ /* check that this is the end of the command */
+ get_word(&text, &word_len);
+ if (word_len)
+ goto syntax_error;
+ if (tok2 == TOK_STATUS)
+ command= new Show_instance_status(map, instance_name,
+ instance_name_len);
+ else
+ command= new Show_instance_options(map, instance_name,
+ instance_name_len);
+ break;
+ default:
+ goto syntax_error;
+ }
+ break;
+ default:
+ instance_name= text - word_len;
+ instance_name_len= word_len;
+ if (instance_name_len)
+ {
+ Log_type log_type;
+ switch (shift_token(&text, &word_len)) {
+ case TOK_LOG:
+ switch (Token tok3= shift_token(&text, &word_len)) {
+ case TOK_FILES:
+ get_word(&text, &word_len);
+ /* check that this is the end of the command */
+ if (word_len)
+ goto syntax_error;
+ command= new Show_instance_log_files(map, instance_name,
+ instance_name_len);
+ break;
+ case TOK_ERROR:
+ case TOK_GENERAL:
+ case TOK_SLOW:
+ /* define a log type */
+ switch (tok3) {
+ case TOK_ERROR:
+ log_type= IM_LOG_ERROR;
+ break;
+ case TOK_GENERAL:
+ log_type= IM_LOG_GENERAL;
+ break;
+ case TOK_SLOW:
+ log_type= IM_LOG_SLOW;
+ break;
+ default:
+ goto syntax_error;
+ }
+ /* get the size of the log we want to retrieve */
+ get_text_id(&text, &word_len, &log_size);
+ text+= word_len;
+ /* this parameter is required */
+ if (!word_len)
+ goto syntax_error;
+ /* the next token should be comma, or nothing */
+ get_word(&text, &word_len);
+ switch (*text) {
+ case ',':
+ text++; /* swallow the comma */
+ /* read the next word */
+ get_word(&text, &word_len);
+ if (!word_len)
+ goto syntax_error;
+ command= new Show_instance_log(map, instance_name,
+ instance_name_len, log_type,
+ log_size, text);
+
+ //get_text_id(&text, &log_size_len, &log_size);
+ break;
+ case '\0':
+ command= new Show_instance_log(map, instance_name,
+ instance_name_len, log_type,
+ log_size, NULL);
+ break; /* this is ok */
+ default:
+ goto syntax_error;
+ }
+ break;
+ default:
+ goto syntax_error;
+ }
+ break;
+ default:
+ goto syntax_error;
+ }
+ }
+ else
+ goto syntax_error;
+ break;
+ }
+ break;
+ default:
+syntax_error:
+ command= new Syntax_error();
+ }
+ return command;
+}
diff --git a/server-tools/instance-manager/parse.h b/server-tools/instance-manager/parse.h
new file mode 100644
index 00000000000..3da53e3a61e
--- /dev/null
+++ b/server-tools/instance-manager/parse.h
@@ -0,0 +1,65 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include <my_sys.h>
+
+class Command;
+class Instance_map;
+
+enum Log_type
+{
+ IM_LOG_ERROR= 0,
+ IM_LOG_GENERAL,
+ IM_LOG_SLOW
+};
+
+Command *parse_command(Instance_map *instance_map, const char *text);
+
+/* define kinds of the word seek method */
+enum { ALPHANUM= 1, NONSPACE };
+
+/*
+ tries to find next word in the text
+ if found, returns the beginning and puts word length to word_len argument.
+ if not found returns pointer to first non-space or to '\0', word_len == 0
+*/
+
+inline void get_word(const char **text, uint *word_len,
+ int seek_method= ALPHANUM)
+{
+ const char *word_end;
+
+ /* skip space */
+ while (my_isspace(default_charset_info, **text))
+ ++(*text);
+
+ word_end= *text;
+
+ if (seek_method == ALPHANUM)
+ while (my_isalnum(default_charset_info, *word_end))
+ ++word_end;
+ else
+ while (!my_isspace(default_charset_info, *word_end) &&
+ (*word_end != '\0'))
+ ++word_end;
+
+ *word_len= word_end - *text;
+}
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H */
diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc
new file mode 100644
index 00000000000..4ec9a71bfd2
--- /dev/null
+++ b/server-tools/instance-manager/parse_output.cc
@@ -0,0 +1,117 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include "parse.h"
+#include "parse_output.h"
+
+#include <stdio.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include "portability.h"
+
+
+/*
+ Parse output of the given command
+
+ SYNOPSYS
+ parse_output_and_get_value()
+
+ command the command to execue with popen.
+ word the word to look for (usually an option name)
+ result the buffer to store the next word (option value)
+ input_buffer_len self-explanatory
+ flag this equals to GET_LINE if we want to get all the line after
+ the matched word and GET_VALUE otherwise.
+
+ DESCRIPTION
+
+ Parse output of the "command". Find the "word" and return the next one
+ if flag is GET_VALUE. Return the rest of the parsed string otherwise.
+
+ RETURN
+ 0 - ok, the word has been found
+ 1 - error occured or the word is not found
+*/
+
+int parse_output_and_get_value(const char *command, const char *word,
+ char *result, size_t input_buffer_len,
+ uint flag)
+{
+ FILE *output;
+ uint wordlen;
+ /* should be enough to store the string from the output */
+ enum { MAX_LINE_LEN= 512 };
+ char linebuf[MAX_LINE_LEN];
+ int rc= 1;
+
+ wordlen= strlen(word);
+
+ /*
+ Successful return of popen does not tell us whether the command has been
+ executed successfully: if the command was not found, we'll get EOF
+ when reading the output buffer below.
+ */
+ if (!(output= popen(command, "r")))
+ goto err;
+
+ /*
+ We want fully buffered stream. We also want system to
+ allocate appropriate buffer.
+ */
+ setvbuf(output, NULL, _IOFBF, 0);
+
+ while (fgets(linebuf, sizeof(linebuf) - 1, output))
+ {
+ uint found_word_len= 0;
+ char *linep= linebuf;
+
+ linebuf[sizeof(linebuf) - 1]= '\0'; /* safety */
+
+ /*
+ Get the word, which might contain non-alphanumeric characters. (Usually
+ these are '/', '-' and '.' in the path expressions and filenames)
+ */
+ get_word((const char **) &linep, &found_word_len, NONSPACE);
+ if (!strncmp(word, linep, wordlen))
+ {
+ /*
+ If we have found the word, return the next one (this is usually
+ an option value) or the whole line (if flag)
+ */
+ linep+= found_word_len; /* swallow the previous one */
+ if (flag & GET_VALUE)
+ {
+ get_word((const char **) &linep, &found_word_len, NONSPACE);
+ if (input_buffer_len <= found_word_len)
+ goto err;
+ strmake(result, linep, found_word_len);
+ }
+ else /* currently there are only two options */
+ strmake(result, linep, input_buffer_len - 1);
+ rc= 0;
+ break;
+ }
+ }
+
+pclose:
+ /* we are not interested in the termination status */
+ pclose(output);
+
+err:
+ return rc;
+}
+
diff --git a/merge/mrg_delete.c b/server-tools/instance-manager/parse_output.h
index 920156be01e..6a84fabbf17 100644
--- a/merge/mrg_delete.c
+++ b/server-tools/instance-manager/parse_output.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H
+/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,16 +16,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Delete last read record */
+#define GET_VALUE 1
+#define GET_LINE 2
-#include "mrg_def.h"
+int parse_output_and_get_value(const char *command, const char *word,
+ char *result, size_t input_buffer_len,
+ uint flag);
-int mrg_delete(MRG_INFO *info,const byte *record)
-{
- if (!info->current_table)
- {
- my_errno=HA_ERR_NO_ACTIVE_RECORD;
- return(-1);
- }
- return nisam_delete(info->current_table->table,record);
-}
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H */
diff --git a/server-tools/instance-manager/portability.h b/server-tools/instance-manager/portability.h
new file mode 100644
index 00000000000..c2b4e8b7467
--- /dev/null
+++ b/server-tools/instance-manager/portability.h
@@ -0,0 +1,25 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H
+
+#ifdef __WIN__
+
+#define vsnprintf _vsnprintf
+
+#define SIGKILL 9
+#define SHUT_RDWR 0x2
+
+/*TODO: fix this */
+#define DEFAULT_MONITORING_INTERVAL 20
+#define DEFAULT_PORT 2273
+#define PROTOCOL_VERSION 10
+
+typedef int pid_t;
+
+#undef popen
+#define popen(A,B) _popen(A,B)
+
+#endif /* __WIN__ */
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H */
+
+
diff --git a/server-tools/instance-manager/priv.cc b/server-tools/instance-manager/priv.cc
new file mode 100644
index 00000000000..02a788ec469
--- /dev/null
+++ b/server-tools/instance-manager/priv.cc
@@ -0,0 +1,54 @@
+/* Copyright (C) 2003 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_global.h>
+#include "priv.h"
+#include "portability.h"
+
+/* the pid of the manager process (of the signal thread on the LinuxThreads) */
+pid_t manager_pid;
+
+/*
+ This flag is set if mysqlmanager has detected that it is running on the
+ system using LinuxThreads
+*/
+bool linuxthreads;
+
+/*
+ The following string must be less then 80 characters, as
+ mysql_connection.cc relies on it
+*/
+const char mysqlmanager_version[] = "0.2-alpha";
+
+const int mysqlmanager_version_length= sizeof(mysqlmanager_version) - 1;
+
+const unsigned char protocol_version= PROTOCOL_VERSION;
+
+unsigned long net_buffer_length= 16384;
+
+unsigned long max_allowed_packet= 16384;
+
+unsigned long net_read_timeout= 30; // same as in mysqld
+
+unsigned long net_write_timeout= 60; // same as in mysqld
+
+unsigned long net_retry_count= 10; // same as in mysqld
+
+/* needed by net_serv.cc */
+unsigned int test_flags= 0;
+unsigned long bytes_sent = 0L, bytes_received = 0L;
+unsigned long mysqld_net_retry_count = 10L;
+unsigned long open_files_limit;
diff --git a/server-tools/instance-manager/priv.h b/server-tools/instance-manager/priv.h
new file mode 100644
index 00000000000..ce9d54293c7
--- /dev/null
+++ b/server-tools/instance-manager/priv.h
@@ -0,0 +1,83 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H
+/* Copyright (C) 2003 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 <sys/types.h>
+#ifdef __WIN__
+#include "portability.h"
+#else
+#include <unistd.h>
+#endif
+
+
+/* the pid of the manager process (of the signal thread on the LinuxThreads) */
+extern pid_t manager_pid;
+
+#ifndef __WIN__
+/*
+ This flag is set if mysqlmanager has detected that it is running on the
+ system using LinuxThreads
+*/
+extern bool linuxthreads;
+#endif
+
+extern const char mysqlmanager_version[];
+extern const int mysqlmanager_version_length;
+
+/* MySQL client-server protocol version: substituted from configure */
+extern const unsigned char protocol_version;
+
+/*
+ These variables are used in MySQL subsystem to work with mysql clients
+ To be moved to a config file/options one day.
+*/
+
+
+/* Buffer length for TCP/IP and socket communication */
+extern unsigned long net_buffer_length;
+
+
+/* Maximum allowed incoming/ougoung packet length */
+extern unsigned long max_allowed_packet;
+
+
+/*
+ Number of seconds to wait for more data from a connection before aborting
+ the read
+*/
+extern unsigned long net_read_timeout;
+
+
+/*
+ Number of seconds to wait for a block to be written to a connection
+ before aborting the write.
+*/
+extern unsigned long net_write_timeout;
+
+
+/*
+ If a read on a communication port is interrupted, retry this many times
+ before giving up.
+*/
+extern unsigned long net_retry_count;
+
+extern unsigned int test_flags;
+extern unsigned long bytes_sent, bytes_received;
+extern unsigned long mysqld_net_retry_count;
+extern unsigned long open_files_limit;
+
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H
diff --git a/server-tools/instance-manager/protocol.cc b/server-tools/instance-manager/protocol.cc
new file mode 100644
index 00000000000..cd1be805b6b
--- /dev/null
+++ b/server-tools/instance-manager/protocol.cc
@@ -0,0 +1,215 @@
+/* Copyright (C) 2003 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 "protocol.h"
+
+#include "messages.h"
+
+#include <mysql_com.h>
+#include <m_string.h>
+
+
+static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
+
+
+int net_send_ok(struct st_net *net, unsigned long connection_id,
+ const char *message)
+{
+ /*
+ The format of a packet
+ 1 packet type code
+ 1-9 affected rows count
+ 1-9 connection id
+ 2 thread return status
+ 2 warning count
+ 1-9 + message length message to send (isn't stored if no message)
+ */
+ Buffer buff;
+ char *pos= buff.buffer;
+
+ /* check that we have space to hold mandatory fields */
+ buff.reserve(0, 23);
+
+ enum { OK_PACKET_CODE= 0 };
+ *pos++= OK_PACKET_CODE;
+ pos= net_store_length(pos, (ulonglong) 0);
+ pos= net_store_length(pos, (ulonglong) connection_id);
+ int2store(pos, *net->return_status);
+ pos+= 2;
+ /* We don't support warnings, so store 0 for total warning count */
+ int2store(pos, 0);
+ pos+= 2;
+
+ uint position= pos - buff.buffer; /* we might need it for message */
+
+ if (message != NULL)
+ {
+ buff.reserve(position, 9 + strlen(message));
+ store_to_protocol_packet(&buff, message, &position);
+ }
+
+ return my_net_write(net, buff.buffer, position) || net_flush(net);
+}
+
+
+int net_send_error(struct st_net *net, uint sql_errno)
+{
+ const char *err= message(sql_errno);
+ char buff[1 + // packet type code
+ 2 + // sql error number
+ 1 + SQLSTATE_LENGTH + // sql state
+ MYSQL_ERRMSG_SIZE]; // message
+ char *pos= buff;
+
+ enum { ERROR_PACKET_CODE= 255 };
+ *pos++= ERROR_PACKET_CODE;
+ int2store(pos, sql_errno);
+ pos+= 2;
+ /* The first # is to make the protocol backward compatible */
+ *pos++= '#';
+ memcpy(pos, errno_to_sqlstate(sql_errno), SQLSTATE_LENGTH);
+ pos+= SQLSTATE_LENGTH;
+ pos= strmake(pos, err, MYSQL_ERRMSG_SIZE - 1) + 1;
+ return my_net_write(net, buff, pos - buff) || net_flush(net);
+}
+
+
+int net_send_error_323(struct st_net *net, uint sql_errno)
+{
+ const char *err= message(sql_errno);
+ char buff[1 + // packet type code
+ 2 + // sql error number
+ MYSQL_ERRMSG_SIZE]; // message
+ char *pos= buff;
+
+ enum { ERROR_PACKET_CODE= 255 };
+ *pos++= ERROR_PACKET_CODE;
+ int2store(pos, sql_errno);
+ pos+= 2;
+ pos= strmake(pos, err, MYSQL_ERRMSG_SIZE - 1) + 1;
+ return my_net_write(net, buff, pos - buff) || net_flush(net);
+}
+
+char *net_store_length(char *pkg, uint length)
+{
+ uchar *packet=(uchar*) pkg;
+ if (length < 251)
+ {
+ *packet=(uchar) length;
+ return (char*) packet+1;
+ }
+ *packet++=252;
+ int2store(packet,(uint) length);
+ return (char*) packet+2;
+}
+
+
+int store_to_protocol_packet(Buffer *buf, const char *string, uint *position,
+ uint string_len)
+{
+ uint currpos;
+
+ /* reserve max amount of bytes needed to store length */
+ if (buf->reserve(*position, 9))
+ goto err;
+ currpos= (net_store_length(buf->buffer + *position,
+ (ulonglong) string_len) - buf->buffer);
+ if (buf->append(currpos, string, string_len))
+ goto err;
+ *position= *position + string_len + (currpos - *position);
+
+ return 0;
+err:
+ return 1;
+}
+
+
+int store_to_protocol_packet(Buffer *buf, const char *string, uint *position)
+{
+ uint string_len;
+
+ string_len= strlen(string);
+ return store_to_protocol_packet(buf, string, position, string_len);
+}
+
+
+int send_eof(struct st_net *net)
+{
+ char buff[1 + /* eof packet code */
+ 2 + /* warning count */
+ 2]; /* server status */
+
+ buff[0]=254;
+ int2store(buff+1, 0);
+ int2store(buff+3, 0);
+ return my_net_write(net, buff, sizeof buff);
+}
+
+int send_fields(struct st_net *net, LIST *fields)
+{
+ LIST *tmp= fields;
+ Buffer send_buff;
+ char small_buff[4];
+ uint position= 0;
+ NAME_WITH_LENGTH *field;
+
+ /* send the number of fileds */
+ net_store_length(small_buff, (uint) list_length(fields));
+ if (my_net_write(net, small_buff, (uint) 1))
+ goto err;
+
+ while (tmp)
+ {
+ position= 0;
+ field= (NAME_WITH_LENGTH *) tmp->data;
+
+ store_to_protocol_packet(&send_buff,
+ (char*) "", &position); /* catalog name */
+ store_to_protocol_packet(&send_buff,
+ (char*) "", &position); /* db name */
+ store_to_protocol_packet(&send_buff,
+ (char*) "", &position); /* table name */
+ store_to_protocol_packet(&send_buff,
+ (char*) "", &position); /* table name alias */
+ store_to_protocol_packet(&send_buff,
+ field->name, &position); /* column name */
+ store_to_protocol_packet(&send_buff,
+ field->name, &position); /* column name alias */
+ send_buff.reserve(position, 12);
+ if (send_buff.is_error())
+ goto err;
+ send_buff.buffer[position++]= 12;
+ int2store(send_buff.buffer + position, 1); /* charsetnr */
+ int4store(send_buff.buffer + position + 2,
+ field->length); /* field length */
+ send_buff.buffer[position+6]= FIELD_TYPE_STRING; /* type */
+ int2store(send_buff.buffer + position + 7, 0); /* flags */
+ send_buff.buffer[position + 9]= (char) 0; /* decimals */
+ send_buff.buffer[position + 10]= 0;
+ send_buff.buffer[position + 11]= 0;
+ position+= 12;
+ if (my_net_write(net, send_buff.buffer, (uint) position+1))
+ goto err;
+ tmp= list_rest(tmp);
+ }
+
+ if (my_net_write(net, eof_buff, 1))
+ goto err;
+ return 0;
+
+err:
+ return 1;
+}
diff --git a/server-tools/instance-manager/protocol.h b/server-tools/instance-manager/protocol.h
new file mode 100644
index 00000000000..f38eac6b079
--- /dev/null
+++ b/server-tools/instance-manager/protocol.h
@@ -0,0 +1,51 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H
+/* Copyright (C) 2003 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 "buffer.h"
+
+#include <my_list.h>
+
+typedef struct field {
+ char *name;
+ uint length;
+} NAME_WITH_LENGTH;
+
+/* default field length to be used in various field-realted functions */
+enum { DEFAULT_FIELD_LENGTH= 20 };
+
+struct st_net;
+
+int net_send_ok(struct st_net *net, unsigned long connection_id,
+ const char *message);
+
+int net_send_error(struct st_net *net, unsigned sql_errno);
+
+int net_send_error_323(struct st_net *net, unsigned sql_errno);
+
+int send_fields(struct st_net *net, LIST *fields);
+
+char *net_store_length(char *pkg, uint length);
+
+int store_to_protocol_packet(Buffer *buf, const char *string, uint *position);
+
+int store_to_protocol_packet(Buffer *buf, const char *string, uint *position,
+ uint string_len);
+
+int send_eof(struct st_net *net);
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H */
diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc
new file mode 100644
index 00000000000..a7384c0fa13
--- /dev/null
+++ b/server-tools/instance-manager/thread_registry.cc
@@ -0,0 +1,233 @@
+/* cOPYRIght (C) 2003 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 */
+
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+#include "thread_registry.h"
+
+#include "log.h"
+
+#include <assert.h>
+#include <signal.h>
+#include <thr_alarm.h>
+
+
+#ifndef __WIN__
+/* Kick-off signal handler */
+
+enum { THREAD_KICK_OFF_SIGNAL= SIGUSR2 };
+
+static void handle_signal(int __attribute__((unused)) sig_no)
+{
+}
+#endif
+
+/*
+ TODO: think about moving signal information (now it's shutdown_in_progress)
+ to Thread_info. It will reduce contention and allow signal deliverence to
+ a particular thread, not to the whole worker crew
+*/
+
+Thread_registry::Thread_registry() :
+ shutdown_in_progress(false)
+ ,sigwait_thread_pid(pthread_self())
+{
+ pthread_mutex_init(&LOCK_thread_registry, 0);
+ pthread_cond_init(&COND_thread_registry_is_empty, 0);
+
+ /* head is used by-value to simplify nodes inserting */
+ head.next= head.prev= &head;
+}
+
+
+Thread_registry::~Thread_registry()
+{
+ /* Check that no one uses the repository. */
+ pthread_mutex_lock(&LOCK_thread_registry);
+
+ /* All threads must unregister */
+ DBUG_ASSERT(head.next == &head);
+
+ pthread_mutex_unlock(&LOCK_thread_registry);
+ pthread_cond_destroy(&COND_thread_registry_is_empty);
+ pthread_mutex_destroy(&LOCK_thread_registry);
+}
+
+
+/*
+ Set signal handler for kick-off thread, and insert a thread info to the
+ repository. New node is appended to the end of the list; head.prev always
+ points to the last node.
+*/
+
+void Thread_registry::register_thread(Thread_info *info)
+{
+#ifndef __WIN__
+ struct sigaction sa;
+ sa.sa_handler= handle_signal;
+ sa.sa_flags= 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(THREAD_KICK_OFF_SIGNAL, &sa, 0);
+#endif
+ info->current_cond= 0;
+
+ pthread_mutex_lock(&LOCK_thread_registry);
+ info->next= &head;
+ info->prev= head.prev;
+ head.prev->next= info;
+ head.prev= info;
+ pthread_mutex_unlock(&LOCK_thread_registry);
+}
+
+
+/*
+ Unregister a thread from the repository and free Thread_info structure.
+ Every registered thread must unregister. Unregistering should be the last
+ thing a thread is doing, otherwise it could have no time to finalize.
+*/
+
+void Thread_registry::unregister_thread(Thread_info *info)
+{
+ pthread_mutex_lock(&LOCK_thread_registry);
+ info->prev->next= info->next;
+ info->next->prev= info->prev;
+ if (head.next == &head)
+ pthread_cond_signal(&COND_thread_registry_is_empty);
+ pthread_mutex_unlock(&LOCK_thread_registry);
+}
+
+
+/*
+ Check whether shutdown is in progress, and if yes, return immediately.
+ Else set info->current_cond and call pthread_cond_wait. When
+ pthread_cond_wait returns, unregister current cond and check the shutdown
+ status again.
+ RETURN VALUE
+ return value from pthread_cond_wait
+*/
+
+int Thread_registry::cond_wait(Thread_info *info, pthread_cond_t *cond,
+ pthread_mutex_t *mutex)
+{
+ pthread_mutex_lock(&LOCK_thread_registry);
+ if (shutdown_in_progress)
+ {
+ pthread_mutex_unlock(&LOCK_thread_registry);
+ return 0;
+ }
+ info->current_cond= cond;
+ pthread_mutex_unlock(&LOCK_thread_registry);
+ /* sic: race condition here, cond can be signaled in deliver_shutdown */
+ int rc= pthread_cond_wait(cond, mutex);
+ pthread_mutex_lock(&LOCK_thread_registry);
+ info->current_cond= 0;
+ pthread_mutex_unlock(&LOCK_thread_registry);
+ return rc;
+}
+
+
+int Thread_registry::cond_timedwait(Thread_info *info, pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ struct timespec *wait_time)
+{
+ pthread_mutex_lock(&LOCK_thread_registry);
+ if (shutdown_in_progress)
+ {
+ pthread_mutex_unlock(&LOCK_thread_registry);
+ return 0;
+ }
+ info->current_cond= cond;
+ pthread_mutex_unlock(&LOCK_thread_registry);
+ /* sic: race condition here, cond can be signaled in deliver_shutdown */
+ int rc= pthread_cond_timedwait(cond, mutex, wait_time);
+ pthread_mutex_lock(&LOCK_thread_registry);
+ info->current_cond= 0;
+ pthread_mutex_unlock(&LOCK_thread_registry);
+ return rc;
+}
+
+
+/*
+ Deliver shutdown message to the workers crew.
+ As it's impossible to avoid all race conditions, signal latecomers
+ again.
+*/
+
+void Thread_registry::deliver_shutdown()
+{
+ Thread_info *info;
+ struct timespec shutdown_time;
+ set_timespec(shutdown_time, 1);
+
+ pthread_mutex_lock(&LOCK_thread_registry);
+ shutdown_in_progress= true;
+
+#ifndef __WIN__
+ /* to stop reading from the network we need to flush alarm queue */
+ end_thr_alarm(0);
+ /*
+ We have to deliver final alarms this way, as the main thread has already
+ stopped alarm processing.
+ */
+ process_alarm(THR_SERVER_ALARM);
+#endif
+
+ for (info= head.next; info != &head; info= info->next)
+ {
+ pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL);
+ /*
+ sic: race condition here, the thread may not yet fall into
+ pthread_cond_wait.
+ */
+ if (info->current_cond)
+ pthread_cond_signal(info->current_cond);
+ }
+ /*
+ The common practice is to test predicate before pthread_cond_wait.
+ I don't do that here because the predicate is practically always false
+ before wait - is_shutdown's been just set, and the lock's still not
+ released - the only case when the predicate is false is when no other
+ threads exist.
+ */
+ while (pthread_cond_timedwait(&COND_thread_registry_is_empty,
+ &LOCK_thread_registry,
+ &shutdown_time) != ETIMEDOUT &&
+ head.next != &head)
+ ;
+ /*
+ If previous signals did not reach some threads, they must be sleeping
+ in pthread_cond_wait or in a blocking syscall. Wake them up:
+ every thread shall check signal variables after each syscall/cond_wait,
+ so this time everybody should be informed (presumably each worker can
+ get CPU during shutdown_time.)
+ */
+ for (info= head.next; info != &head; info= info->next)
+ {
+ pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL);
+ if (info->current_cond)
+ pthread_cond_signal(info->current_cond);
+ }
+
+ pthread_mutex_unlock(&LOCK_thread_registry);
+}
+
+
+void Thread_registry::request_shutdown()
+{
+ pthread_kill(sigwait_thread_pid, SIGTERM);
+}
diff --git a/server-tools/instance-manager/thread_registry.h b/server-tools/instance-manager/thread_registry.h
new file mode 100644
index 00000000000..28899810f23
--- /dev/null
+++ b/server-tools/instance-manager/thread_registry.h
@@ -0,0 +1,118 @@
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_THREAD_REGISTRY_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_THREAD_REGISTRY_H
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ A multi-threaded application shall nicely work with signals.
+
+ This means it shall, first of all, shut down nicely on ``quit'' signals:
+ stop all running threads, cleanup and exit.
+
+ Note, that a thread can't be shut down nicely if it doesn't want to be.
+ That's why to perform clean shutdown, all threads constituting a process
+ must observe certain rules. Here we use the rules, described in Butenhof
+ book 'Programming with POSIX threads', namely:
+ - all user signals are handled in 'signal thread' in synchronous manner
+ (by means of sigwait). To guarantee that the signal thread is the only who
+ can receive user signals, all threads block them, and signal thread is
+ the only who calls sigwait() with an apporpriate sigmask.
+ To propogate a signal to the workers the signal thread sets
+ a variable, corresponding to the signal. Additionally the signal thread
+ sends each worker an internal signal (by means of pthread_kill) to kick it
+ out from possible blocking syscall, and possibly pthread_cond_signal if
+ some thread is blocked in pthread_cond_[timed]wait.
+ - a worker handles only internal 'kick' signal (the handler does nothing).
+ In case when a syscall returns 'EINTR' the worker checks all
+ signal-related variables and behaves accordingly.
+ Also these variables shall be checked from time to time in long
+ CPU-bounded operations, and before/after pthread_cond_wait. (It's supposed
+ that a worker thread either waits in a syscall/conditional variable, or
+ computes something.)
+ - to guarantee signal deliverence, there should be some kind of feedback,
+ e. g. all workers shall account in the signal thread Thread Repository and
+ unregister from it on exit.
+
+ Configuration reload (on SIGHUP) and thread timeouts/alarms can be handled
+ in manner, similar to ``quit'' signals.
+*/
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include <my_global.h>
+#include <my_pthread.h>
+
+
+/*
+ Thread_info - repository entry for each worker thread
+ All entries comprise double-linked list like:
+ 0 -- entry -- entry -- entry - 0
+ Double-linked list is used to unregister threads easy.
+*/
+
+class Thread_info
+{
+ pthread_cond_t *current_cond;
+ Thread_info *prev, *next;
+ pthread_t thread_id;
+ Thread_info() {}
+ friend class Thread_registry;
+public:
+ Thread_info(pthread_t thread_id_arg) : thread_id(thread_id_arg) {}
+};
+
+
+/*
+ Thread_registry - contains handles for each worker thread to deliver
+ signal information to workers.
+*/
+
+class Thread_registry
+{
+public:
+ Thread_registry();
+ ~Thread_registry();
+
+ void register_thread(Thread_info *info);
+ void unregister_thread(Thread_info *info);
+ void deliver_shutdown();
+ void request_shutdown();
+ inline bool is_shutdown();
+ int cond_wait(Thread_info *info, pthread_cond_t *cond,
+ pthread_mutex_t *mutex);
+ int cond_timedwait(Thread_info *info, pthread_cond_t *cond,
+ pthread_mutex_t *mutex, struct timespec *wait_time);
+private:
+ Thread_info head;
+ bool shutdown_in_progress;
+ pthread_mutex_t LOCK_thread_registry;
+ pthread_cond_t COND_thread_registry_is_empty;
+ pthread_t sigwait_thread_pid;
+};
+
+
+inline bool Thread_registry::is_shutdown()
+{
+ pthread_mutex_lock(&LOCK_thread_registry);
+ bool res= shutdown_in_progress;
+ pthread_mutex_unlock(&LOCK_thread_registry);
+ return res;
+}
+
+
+#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_THREAD_REGISTRY_H */
diff --git a/server-tools/instance-manager/user_map.cc b/server-tools/instance-manager/user_map.cc
new file mode 100644
index 00000000000..d13eb681d05
--- /dev/null
+++ b/server-tools/instance-manager/user_map.cc
@@ -0,0 +1,183 @@
+/* Copyright (C) 2003 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 */
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include "user_map.h"
+
+#include <mysql_com.h>
+#include <m_string.h>
+
+#include "log.h"
+
+struct User
+{
+ char user[USERNAME_LENGTH + 1];
+ uint8 user_length;
+ uint8 salt[SCRAMBLE_LENGTH];
+ int init(const char *line);
+};
+
+
+int User::init(const char *line)
+{
+ const char *name_begin, *name_end, *password;
+ int line_ending_len= 1;
+
+ if (line[0] == '\'' || line[0] == '"')
+ {
+ name_begin= line + 1;
+ name_end= strchr(name_begin, line[0]);
+ if (name_end == 0 || name_end[1] != ':')
+ goto err;
+ password= name_end + 2;
+ }
+ else
+ {
+ name_begin= line;
+ name_end= strchr(name_begin, ':');
+ if (name_end == 0)
+ goto err;
+ password= name_end + 1;
+ }
+ user_length= name_end - name_begin;
+ if (user_length > USERNAME_LENGTH)
+ goto err;
+
+ /*
+ assume that newline characater is present
+ we support reading password files that end in \n or \r\n on
+ either platform.
+ */
+ if (password[strlen(password)-2] == '\r')
+ line_ending_len= 2;
+ if (strlen(password) != SCRAMBLED_PASSWORD_CHAR_LENGTH + line_ending_len)
+ goto err;
+
+ memcpy(user, name_begin, user_length);
+ user[user_length]= 0;
+ get_salt_from_password(salt, password);
+ log_info("loaded user %s", user);
+
+ return 0;
+err:
+ log_error("error parsing user and password at line %s", line);
+ return 1;
+}
+
+
+C_MODE_START
+
+static byte* get_user_key(const byte* u, uint* len,
+ my_bool __attribute__((unused)) t)
+{
+ const User *user= (const User *) u;
+ *len= user->user_length;
+ return (byte *) user->user;
+}
+
+static void delete_user(void *u)
+{
+ User *user= (User *) u;
+ delete user;
+}
+
+C_MODE_END
+
+
+int User_map::init()
+{
+ enum { START_HASH_SIZE= 16 };
+ if (hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
+ get_user_key, delete_user, 0))
+ return 1;
+ return 0;
+}
+
+
+User_map::~User_map()
+{
+ hash_free(&hash);
+}
+
+
+/*
+ Load all users from the password file. Must be called once right after
+ construction.
+ In case of failure, puts error message to the log file and returns 1
+*/
+
+int User_map::load(const char *password_file_name)
+{
+ FILE *file;
+ char line[USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH +
+ 2 + /* for possible quotes */
+ 1 + /* for ':' */
+ 2 + /* for newline */
+ 1]; /* for trailing zero */
+ User *user;
+ int rc= 1;
+
+ if ((file= my_fopen(password_file_name, O_RDONLY | O_BINARY, MYF(0))) == 0)
+ {
+ /* Probably the password file wasn't specified. Try to leave without it */
+ log_info("[WARNING] can't open password file %s: errno=%d, %s", password_file_name,
+ errno, strerror(errno));
+ return 0;
+ }
+
+ while (fgets(line, sizeof(line), file))
+ {
+ /* skip comments and empty lines */
+ if (line[0] == '#' || line[0] == '\n' &&
+ (line[1] == '\0' || line[1] == '\r'))
+ continue;
+ if ((user= new User) == 0)
+ goto done;
+ if (user->init(line) || my_hash_insert(&hash, (byte *) user))
+ goto err_init_user;
+ }
+ if (feof(file))
+ rc= 0;
+ goto done;
+err_init_user:
+ delete user;
+done:
+ my_fclose(file, MYF(0));
+ return rc;
+}
+
+
+/*
+ Check if user exists and password is correct
+ RETURN VALUE
+ 0 - user found and password OK
+ 1 - password mismatch
+ 2 - user not found
+*/
+
+int User_map::authenticate(const char *user_name, uint length,
+ const char *scrambled_password,
+ const char *scramble) const
+{
+ const User *user= (const User *) hash_search((HASH *) &hash,
+ (byte *) user_name, length);
+ if (user)
+ return check_scramble(scrambled_password, scramble, user->salt);
+ return 2;
+}
diff --git a/merge/mrg_locking.c b/server-tools/instance-manager/user_map.h
index bd33e047091..4c86edd93d9 100644
--- a/merge/mrg_locking.c
+++ b/server-tools/instance-manager/user_map.h
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MAP_H
+#define INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MAP_H
+/* Copyright (C) 2003 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
@@ -14,20 +16,31 @@
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
+#endif
+
+#include <my_global.h>
+
+#include <my_sys.h>
+#include <hash.h>
+
/*
- Lock databases against read or write.
+ User_map -- all users and passwords
*/
-#include "mrg_def.h"
-
-int mrg_lock_database(MRG_INFO *info,int lock_type)
+class User_map
{
- int error,new_error;
- MRG_TABLE *file;
-
- error=0;
- for (file=info->open_tables ; file != info->end_table ; file++)
- if ((new_error=nisam_lock_database(file->table,lock_type)))
- error=new_error;
- return(error);
-}
+public:
+ ~User_map();
+
+ int init();
+ int load(const char *password_file_name);
+ int authenticate(const char *user_name, uint length,
+ const char *scrambled_password,
+ const char *scramble) const;
+private:
+ HASH hash;
+};
+
+#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MAP_H
diff --git a/sql-bench/limits/mysql-4.0.cfg b/sql-bench/limits/mysql-4.0.cfg
index 35bdc9fa842..6a23be36fce 100644
--- a/sql-bench/limits/mysql-4.0.cfg
+++ b/sql-bench/limits/mysql-4.0.cfg
@@ -84,7 +84,7 @@ alter_drop_unique=with drop key # Alter table drop unique
###< alter table crash_q drop constraint u1 restrict
###> execute error: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 'constraint u1 restrict' at line 1
###
- ###< alter table crash_q drop key c1
+ ###< alter table crash_q drop key u1
###> OK
alter_modify_col=yes # Alter table modify column
###< alter table crash_q modify c1 CHAR(20)
@@ -395,7 +395,7 @@ date_format_inresult=iso # Date format in result
###> OK
###
###< select a from crash_me_d
- ###> 2003-08-27
+ ###> 2003-12-24
###< delete from crash_me_d
###> OK
###< insert into crash_me_d values( sysdate() )
@@ -664,14 +664,14 @@ func_extra_add_months=no # Function ADD_MONTHS
###
###<select add_months('1997-01-01',1) from crash_me_d
###> execute failed: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 '('1997-01-01',1) from crash_me_d' at line 1
-func_extra_adddate=no # Function ADDDATE
+func_extra_adddate=yes # Function ADDDATE
###
###<select ADDDATE('2002-12-01',3) from crash_me_d
- ###> execute failed: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 '3) from crash_me_d' at line 1
-func_extra_addtime=no # Function ADDTIME
+ ###>2002-12-04
+func_extra_addtime=yes # Function ADDTIME
###
###<select ADDTIME('20:02:12','00:00:03')
- ###> execute failed: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 '('20:02:12','00:00:03')' at line 1
+ ###>20:02:15
func_extra_alpha=no # Function ALPHA
###
###<select alpha('Aâ',2)
@@ -754,10 +754,10 @@ func_extra_cosh=no # Function COSH
###
###<select cosh(0)
###> execute failed: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 '(0)' at line 1
-func_extra_date=no # Function DATE
+func_extra_date=yes # Function DATE
###
###<select date('1963-08-16') from crash_me_d
- ###> execute failed: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 '('1963-08-16') from crash_me_d' at line 1
+ ###>1963-08-16
func_extra_date_format=yes # Function DATE_FORMAT
###
###<select date_format('1997-01-02 03:04:05','M W D Y y m d h i s w') from crash_me_d
@@ -769,11 +769,11 @@ func_extra_dateadd=no # Function DATEADD
func_extra_datediff=no # Function DATEDIFF
###
###<select datediff(month,'Oct 21 1997','Nov 30 1997') from crash_me_d
- ###> execute failed: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 '(month,'Oct 21 1997','Nov 30 1997') from crash_me_d' at line 1
-func_extra_datediff2arg=no # Function DATEDIFF (2 arg)
+ ###> execute failed: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 ''Nov 30 1997') from crash_me_d' at line 1
+func_extra_datediff2arg=yes # Function DATEDIFF (2 arg)
###
###<select DATEDIFF('2002-12-04','2002-12-01') from crash_me_d
- ###> execute failed: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 '('2002-12-04','2002-12-01') from crash_me_d' at line 1
+ ###>3
func_extra_datename=no # Function DATENAME
###
###<select datename(month,'Nov 30 1997') from crash_me_d
@@ -782,10 +782,10 @@ func_extra_datepart=no # Function DATEPART
###
###<select datepart(month,'July 20 1997') from crash_me_d
###> execute failed: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 '(month,'July 20 1997') from crash_me_d' at line 1
-func_extra_day=no # Function DAY
+func_extra_day=yes # Function DAY
###
###<select DAY('2002-12-01') from crash_me_d
- ###> execute failed: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 '('2002-12-01') from crash_me_d' at line 1
+ ###>1
func_extra_decode=no # Function DECODE
###
###<select DECODE('S-103','T72',1,'S-103',2,'Leopard',3)
@@ -801,7 +801,7 @@ func_extra_elt=yes # Function ELT
func_extra_encrypt=yes # Function ENCRYPT
###
###<select encrypt('hello')
- ###>tHrzZO8Aq1FG6
+ ###>1Wi1s0yzcGqMY
func_extra_expand2arg=no # Function EXPAND
###
###<select expand('abcd',6)
@@ -878,10 +878,10 @@ func_extra_interval=yes # Function INTERVAL
###
###<select interval(55,10,20,30,40,50,60,70,80,90,100)
###>5
-func_extra_last_day=no # Function LAST_DAY
+func_extra_last_day=yes # Function LAST_DAY
###
###<select last_day('1997-04-01') from crash_me_d
- ###> execute failed: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 '('1997-04-01') from crash_me_d' at line 1
+ ###>1997-04-30
func_extra_last_insert_id=yes # Function LAST_INSERT_ID
###
###<select last_insert_id()
@@ -931,14 +931,14 @@ func_extra_ltrim2arg=no # Function LTRIM (2 arg)
###
###<select ltrim('..abcd..','.')
###> execute failed: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
-func_extra_makedate=no # Function MAKEDATE
+func_extra_makedate=yes # Function MAKEDATE
###
###<select MAKEDATE(1963,228) from crash_me_d
- ###> execute failed: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 '(1963,228) from crash_me_d' at line 1
-func_extra_maketime=no # Function MAKETIME
+ ###>1963-08-16
+func_extra_maketime=yes # Function MAKETIME
###
###<select MAKETIME(20,02,12)
- ###> execute failed: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 '(20,02,12)' at line 1
+ ###>20:02:12
func_extra_mapchar=no # Function MAPCHAR
###
###<select mapchar('Aâ')
@@ -947,10 +947,11 @@ func_extra_mdy=no # Function MDY
###
###<select mdy(7,1,1998) from crash_me_d
###> execute failed: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 '(7,1,1998) from crash_me_d' at line 1
-func_extra_microsecond=no # Function MICROSECOND
+func_extra_microsecond=error # Function MICROSECOND
###
###<select MICROSECOND('19630816200212111111')
- ###> execute failed: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 '('19630816200212111111')' at line 1
+ ###>11
+ ###We expected '111111' but got '11'
func_extra_mid=yes # Function SUBSTRING as MID
###
###<select mid('hello',3,2)
@@ -968,7 +969,7 @@ func_extra_noround=no # Function NOROUND
###> execute error: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 '(22.6)' at line 1
func_extra_not=yes # Function NOT in SELECT
###
- ###<select not 0
+ ###<select not false
###>1
func_extra_not_between=yes # Function NOT BETWEEN in SELECT
###
@@ -985,11 +986,11 @@ func_extra_num=no # Function NUM
func_extra_odbc_convert=no # Function ODBC CONVERT
###
###<select convert(5,SQL_CHAR)
- ###> execute failed: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 'SQL_CHAR)' at line 1
+ ###> execute failed: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
func_extra_password=yes # Function PASSWORD
###
###<select password('hello')
- ###>70de51425df9d787
+ ###>*6B4F89A54E2D27ECD7E8DA05B4AB8FD9D1D8B119
func_extra_paste=no # Function PASTE
###
###<select paste('ABCDEFG',3,2,'1234')
@@ -1074,18 +1075,18 @@ func_extra_stuff=no # Function STUFF
###
###<select stuff('abc',2,3,'xyz')
###> execute failed: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 '('abc',2,3,'xyz')' at line 1
-func_extra_subdate=no # Function SUBDATE
+func_extra_subdate=yes # Function SUBDATE
###
###<select SUBDATE('2002-12-04',3) from crash_me_d
- ###> execute failed: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 '3) from crash_me_d' at line 1
-func_extra_substr2arg=no # Function SUBSTR (2 arg)
+ ###>2002-12-01
+func_extra_substr2arg=yes # Function SUBSTR (2 arg)
###
###<select substr('abcd',2)
- ###> execute failed: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 '('abcd',2)' at line 1
-func_extra_substr3arg=no # Function SUBSTR (3 arg)
+ ###>bcd
+func_extra_substr3arg=yes # Function SUBSTR (3 arg)
###
###<select substr('abcd',2,2)
- ###> execute failed: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 '('abcd',2,2)' at line 1
+ ###>bc
func_extra_substrb=no # Function SUBSTRB
###
###<select SUBSTRB('ABCDEFG',5,4.2)
@@ -1094,14 +1095,14 @@ func_extra_substring_index=yes # Function SUBSTRING_INDEX
###
###<select substring_index('www.tcx.se','.',-2)
###>tcx.se
-func_extra_subtime=no # Function SUBTIME
+func_extra_subtime=yes # Function SUBTIME
###
###<select SUBTIME('20:02:15','00:00:03')
- ###> execute failed: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 '('20:02:15','00:00:03')' at line 1
+ ###>20:02:12
func_extra_sysdate=yes # Function SYSDATE
###
###<select sysdate()
- ###>2003-08-27 19:55:21
+ ###>2003-12-24 09:46:11
func_extra_tail=no # Function TAIL
###
###<select tail('ABCDEFG',3)
@@ -1110,22 +1111,23 @@ func_extra_tanh=no # Function TANH
###
###<select tanh(1)
###> execute failed: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
-func_extra_time=no # Function TIME
+func_extra_time=yes # Function TIME
###
###<select time('20:02:12')
- ###> execute failed: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 '('20:02:12')' at line 1
+ ###>20:02:12
func_extra_time_to_sec=yes # Function TIME_TO_SEC
###
###<select time_to_sec('01:23:21')
###>5001
-func_extra_timediff=no # Function TIMEDIFF
+func_extra_timediff=yes # Function TIMEDIFF
###
###<select TIMEDIFF('20:02:15','20:02:12')
- ###> execute failed: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 '('20:02:15','20:02:12')' at line 1
-func_extra_timestamp=no # Function TIMESTAMP
+ ###>00:00:03
+func_extra_timestamp=error # Function TIMESTAMP
###
###<select timestamp('19630816','00200212')
- ###> execute failed: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 '('19630816','00200212')' at line 1
+ ###>1963-08-16 20:02:12
+ ###We expected '19630816200212000000' but got '1963-08-16 20:02:12'
func_extra_to_days=yes # Function TO_DAYS
###
###<select to_days('1996-01-01') from crash_me_d
@@ -1166,7 +1168,7 @@ func_extra_uid=no # Function UID
func_extra_unix_timestamp=yes # Function UNIX_TIMESTAMP
###
###<select unix_timestamp()
- ###>1062003321
+ ###>1072251971
func_extra_userenv=no # Function USERENV
###
###<select userenv
@@ -1178,15 +1180,15 @@ func_extra_value=no # Function VALUE
func_extra_version=yes # Function VERSION
###
###<select version()
- ###>4.0.15-debug-log
+ ###>5.0.0-alpha-debug-log
func_extra_weekday=yes # Function WEEKDAY
###
###<select weekday('1997-11-29') from crash_me_d
###>5
-func_extra_weekofyear=no # Function WEEKOFYEAR
+func_extra_weekofyear=yes # Function WEEKOFYEAR
###
###<select WEEKOFYEAR('1963-08-16') from crash_me_d
- ###> execute failed: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 '('1963-08-16') from crash_me_d' at line 1
+ ###>33
func_extra_|=yes # Function | (bitwise or)
###
###<select 1 | 2
@@ -1246,11 +1248,11 @@ func_odbc_cot=yes # Function COT
func_odbc_curdate=yes # Function CURDATE
###
###<select curdate()
- ###>2003-08-27
+ ###>2003-12-24
func_odbc_curtime=yes # Function CURTIME
###
###<select curtime()
- ###>19:55:21
+ ###>09:46:11
func_odbc_database=yes # Function DATABASE
###
###<select database()
@@ -1397,7 +1399,7 @@ func_odbc_monthname=yes # Function MONTHNAME
func_odbc_now=yes # Function NOW
###
###<select now()
- ###>2003-08-27 19:55:21
+ ###>2003-12-24 09:46:11
func_odbc_pi=yes # Function PI
###
###<select pi()
@@ -1476,20 +1478,19 @@ func_odbc_tan=yes # Function TAN
###
###<select tan(1)
###>1.557408
-func_odbc_timestampadd=no # Function TIMESTAMPADD
+func_odbc_timestampadd=yes # Function TIMESTAMPADD
###
###<select timestampadd(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')
- ###> execute failed: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 '(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')' at line 1
- ###
- ###<select {fn timestampadd(SQL_TSI_SECOND,1,{ts '1997-01-01 00:00:00'}) }
- ###> execute failed: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 '(SQL_TSI_SECOND,1,{ts '1997-01-01 00:00:00'}) }' at line 1
-func_odbc_timestampdiff=no # Function TIMESTAMPDIFF
+ ###>1997-01-01 00:00:01
+func_odbc_timestampdiff=error # Function TIMESTAMPDIFF
###
###<select timestampdiff(SQL_TSI_SECOND,'1997-01-01 00:00:02', '1997-01-01 00:00:01')
- ###> execute failed: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 '(SQL_TSI_SECOND,'1997-01-01 00:00:02', '1997-01-01 00:00:01')'
+ ###>-1
+ ###We expected '1' but got '-1'
###
###<select {fn timestampdiff(SQL_TSI_SECOND,{ts '1997-01-01 00:00:02'}, {ts '1997-01-01 00:00:01'}) }
- ###> execute failed: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 '(SQL_TSI_SECOND,{ts '1997-01-01 00:00:02'}, {ts '1997-01-01 00:
+ ###>-1
+ ###We expected '1' but got '-1'
func_odbc_truncate=yes # Function TRUNCATE
###
###<select truncate(18.18,-1)
@@ -1556,15 +1557,15 @@ func_sql_concat_as_||=error # Function concatenation with ||
func_sql_current_date=yes # Function CURRENT_DATE
###
###<select current_date
- ###>2003-08-27
+ ###>2003-12-24
func_sql_current_time=yes # Function CURRENT_TIME
###
###<select current_time
- ###>19:55:21
+ ###>09:46:11
func_sql_current_timestamp=yes # Function CURRENT_TIMESTAMP
###
###<select current_timestamp
- ###>2003-08-27 19:55:21
+ ###>2003-12-24 09:46:11
func_sql_current_user=with_parenthesis # CURRENT_USER
###< select CURRENT_USER
###> execute error:Unknown column 'CURRENT_USER' in 'field list'
@@ -1585,11 +1586,11 @@ func_sql_extract_sql=yes # Function EXTRACT
func_sql_localtime=yes # Function LOCALTIME
###
###<select localtime
- ###>2003-08-27 19:55:21
+ ###>2003-12-24 09:46:11
func_sql_localtimestamp=yes # Function LOCALTIMESTAMP
###
###<select localtimestamp
- ###>2003-08-27 19:55:21
+ ###>2003-12-24 09:46:11
func_sql_lower=yes # Function LOWER
###
###<select LOWER('ABC')
@@ -1682,22 +1683,22 @@ func_where_between=yes # Function BETWEEN
###
###<select a from crash_me where 5 between 4 and 6
###>1
-func_where_eq_all=no # Function = ALL
+func_where_eq_all=yes # Function = ALL
###
###<select a from crash_me where b =all (select b from crash_me)
- ###> execute failed: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 'all (select b from crash_me)' at line 1
-func_where_eq_any=no # Function = ANY
+ ###>1
+func_where_eq_any=yes # Function = ANY
###
###<select a from crash_me where b =any (select b from crash_me)
- ###> execute failed: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 b from crash_me)' at line 1
-func_where_eq_some=no # Function = SOME
+ ###>1
+func_where_eq_some=yes # Function = SOME
###
###<select a from crash_me where b =some (select b from crash_me)
- ###> execute failed: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 b from crash_me)' at line 1
-func_where_exists=no # Function EXISTS
+ ###>1
+func_where_exists=yes # Function EXISTS
###
###<select a from crash_me where exists (select * from crash_me)
- ###> execute failed: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 'exists (select * from crash_me)' at line 1
+ ###>1
func_where_in_num=yes # Function IN on numbers
###
###<select a from crash_me where 2 in (3,2,5,9,5,1)
@@ -1726,10 +1727,10 @@ func_where_not_between=yes # Function NOT BETWEEN
###
###<select a from crash_me where 7 not between 4 and 6
###>1
-func_where_not_exists=no # Function NOT EXISTS
+func_where_not_exists=yes # Function NOT EXISTS
###
###<select a from crash_me where not exists (select * from crash_me where a = 2)
- ###> execute failed: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 'exists (select * from crash_me where a = 2)' at line 1
+ ###>1
func_where_not_like=yes # Function NOT LIKE
###
###<select a from crash_me where b not like 'b%'
@@ -1800,10 +1801,10 @@ group_func_extra_stddev=yes # Group function STDDEV
###
###<select stddev(a),a from crash_me group by a
###>0.0000
-group_func_extra_variance=no # Group function VARIANCE
+group_func_extra_variance=yes # Group function VARIANCE
###
###<select variance(a),a from crash_me group by a
- ###> execute failed: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),a from crash_me group by a' at line 1
+ ###>0.0000
group_func_sql_any=no # Group function ANY
###
###<select any(a),a from crash_me group by a
@@ -1867,13 +1868,9 @@ group_on_unused=yes # Group on unused column
###> OK
###
###As far as all queries returned OK, result is YES
-has_true_false=no # TRUE and FALSE
- ###< select (1=1)=true
- ###> execute error:Unknown column 'true' in 'field list'
+has_true_false=yes # TRUE and FALSE
###< select (1=1)=true
###> OK
- ###< select (1=1)=true
- ###> execute error:Unknown column 'true' in 'field list'
having=yes # Having
###<select a from crash_me group by a having a > 0
###>1
@@ -2013,10 +2010,10 @@ intersect_incompat=no # intersect (incompatible lists)
###> execute error: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 crash_me2' at line 1
###
###As far as some queries didnt return OK, result is NO
-join_tables=31 # tables in join
+join_tables=61 # tables in join
###We are trying (example with N=5):
###select crash_me.a,t0.a,t1.a,t2.a,t3.a,t4.a from crash_me,crash_me t0,crash_me t1,crash_me t2,crash_me t3,crash_me t4
- ### 32:FAIL 7:OK 19:OK 25:OK 28:OK 30:OK 31:FAIL
+ ### 32:OK 48:OK 56:OK 60:OK 62:FAIL 61:FAIL
left_outer_join=yes # left outer join
###< select crash_me.a from crash_me left join crash_me2 ON crash_me.a=crash_me2.a
###> OK
@@ -2071,32 +2068,32 @@ logical_value=1 # Value of logical operation (1=1)
###>1
max_big_expressions=10 # big expressions
###We are trying (example with N=5):
- ###select 0+(1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+...(14308)
+ ###select 0+(1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+...(14328)
### 50:FAIL 10:OK 30:FAIL 14:FAIL 11:FAIL
-max_char_size=255 # max char() size
+max_char_size=1048543 # max char() size
###We are trying (example with N=5):
###create table crash_q (q char(5))
###insert into crash_q values ('aaaaa')
###select * from crash_q
- ### 524287:FAIL 104858:FAIL 20972:FAIL 4195:FAIL 839:FAIL 168:OK 503:FAIL 235:OK 369:FAIL 262:FAIL 241:OK 251:OK 256:FAIL 252:OK 254:OK 255:OK
+ ### 524287:OK 786431:OK 917503:OK 983039:OK 1015807:OK 1032191:OK 1040383:OK 1044479:OK 1046527:OK 1047551:OK 1048063:OK 1048319:OK 1048447:OK 1048511:OK 1048543:OK 1048559:FAIL 1048546:FAIL 1048544:FAIL
max_column_name=64 # column name length
###We are trying (example with N=5):
###create table crash_q (qaaaaa integer)
###insert into crash_q (qaaaaa) values(1)
###select qaaaaa from crash_q
### 256:FAIL 51:OK 153:FAIL 72:FAIL 55:OK 63:OK 67:FAIL 64:FAIL
-max_columns=3398 # Columns in table
+max_columns=2599 # Columns in table
###We are trying (example with N=5):
###create table crash_q (a integer ,a0 integer,a1 integer,a2 integer,a3 integer,a4 integer)
- ### 4096:FAIL 819:OK 2457:OK 3276:OK 3686:FAIL 3358:OK 3522:FAIL 3391:OK 3456:FAIL 3404:FAIL 3394:OK 3399:FAIL 3395:OK 3397:OK 3398:FAIL
+ ### 4096:FAIL 819:OK 2457:OK 3276:FAIL 2621:FAIL 2490:OK 2555:OK 2588:OK 2604:FAIL 2591:OK 2597:OK 2600:FAIL 2598:OK 2599:FAIL
max_conditions=85660 # OR and AND in WHERE
###We are trying (example with N=5):
###select a from crash_me where a=1 and b='a' or a=0 and b='0' or a=1 and b='1' or a=2 and b='2' or a=3 and b='3' or a=4 and b='4'
### 27592:OK 41389:OK 48287:FAIL 42769:OK 45528:FAIL 43321:FAIL 42880:FAIL 42791:OK 42835:FAIL 42800:OK 42817:OK 42826:OK 42830:OK 42832:FAIL 42831:FAIL
-max_expressions=1450 # simple expressions
+max_expressions=1452 # simple expressions
###We are trying (example with N=5):
###select 1+1+1+1+1+1
- ### 5000:FAIL 1000:OK 3000:FAIL 1400:OK 2200:FAIL 1560:FAIL 1432:OK 1496:FAIL 1445:OK 1470:FAIL 1450:OK 1460:FAIL 1452:FAIL 1451:FAIL
+ ### 5000:FAIL 1000:OK 3000:FAIL 1400:OK 2200:FAIL 1560:FAIL 1432:OK 1496:FAIL 1445:OK 1470:FAIL 1450:OK 1460:FAIL 1452:OK 1456:FAIL 1453:FAIL
max_index=32 # max index
### max_unique_index=32 ,so max_index must be same
### max_unique_index=32 ,so max_index must be same
@@ -2115,6 +2112,7 @@ max_index_part_length=255 # max index part length
###create table crash_q (q char(5) not null,unique(q))
###insert into crash_q (q) values ('aaaaa')
###select q from crash_q
+ ### 524271:FAIL 104854:FAIL 20971:FAIL 4194:FAIL 839:FAIL 168:OK 503:FAIL 235:OK 369:FAIL 262:FAIL 241:OK 251:OK 256:FAIL 252:OK 254:OK 255:OK
max_index_parts=16 # index parts
###We are trying (example with N=5):
###create table crash_q (q0 integer not null,q1 integer not null,q2 integer not null,q3 integer not null,q4 integer not nul...(1263)
@@ -2126,11 +2124,12 @@ max_index_varchar_part_length=255 # index varchar part length
###create table crash_q (q varchar(5) not null,unique(q))
###insert into crash_q (q) values ('aaaaa')
###select q from crash_q
+ ### 524271:FAIL 104854:FAIL 20971:FAIL 4194:FAIL 839:FAIL 168:OK 503:FAIL 235:OK 369:FAIL 262:FAIL 241:OK 251:OK 256:FAIL 252:OK 254:OK 255:OK
max_row_length=65534 # max table row length (without blobs)
###We are trying (example with N=5):
###create table crash_q (q0 char(5) not null)
###insert into crash_q values ('aaaaa')
- ### 433245:FAIL 86649:FAIL 17330:OK 51989:OK 69319:FAIL 55455:OK 62387:OK 65853:FAIL 63080:OK 64466:OK 65159:OK 65506:OK 65679:FAIL 65541:FAIL 65513:OK 65527:OK 65534:OK 65537:FAIL 65535:FAIL
+ ### 331372:FAIL 66275:FAIL 13255:OK 39765:OK 53020:OK 59647:OK 62961:OK 64618:OK 65446:OK 65860:FAIL 65529:OK 65694:FAIL 65562:FAIL 65536:FAIL 65531:OK 65533:OK 65534:OK 65535:FAIL
max_row_length_with_null=65502 # table row length with nulls (without blobs)
###We are trying (example with N=5):
###create table crash_q (q0 char(5) )
@@ -2139,10 +2138,10 @@ max_row_length_with_null=65502 # table row length with nulls (without blobs)
max_select_alias_name=+512 # select alias name length
###We are trying (example with N=5):
###select b as aaaaa from crash_me
-max_stack_expression=1450 # stacked expressions
+max_stack_expression=1452 # stacked expressions
###We are trying (example with N=5):
###select 1+(1+(1+(1+(1+(1)))))
- ### 1000:OK 1500:FAIL 1100:OK 1300:OK 1400:OK 1450:OK 1475:FAIL 1455:FAIL 1451:FAIL
+ ### 1000:OK 1500:FAIL 1100:OK 1300:OK 1400:OK 1450:OK 1475:FAIL 1455:FAIL 1451:OK 1453:FAIL 1452:OK
max_table_alias_name=+512 # table alias name length
###We are trying (example with N=5):
###select aaaaa.b from crash_me aaaaa
@@ -2164,12 +2163,12 @@ max_unique_index=32 # unique indexes
###insert into crash_q (q,q1,q2,q3,q4,q5) values (1,1,1,1,1,1)
###select q from crash_q
### 32:OK 48:FAIL 35:FAIL 33:FAIL
-max_varchar_size=255 # max varchar() size
+max_varchar_size=1048543 # max varchar() size
###We are trying (example with N=5):
###create table crash_q (q varchar(5))
###insert into crash_q values ('aaaaa')
###select * from crash_q
- ### 524287:FAIL 104858:FAIL 20972:FAIL 4195:FAIL 839:FAIL 168:OK 503:FAIL 235:OK 369:FAIL 262:FAIL 241:OK 251:OK 256:FAIL 252:OK 254:OK 255:OK
+ ### 524287:OK 786431:OK 917503:OK 983039:OK 1015807:OK 1032191:OK 1040383:OK 1044479:OK 1046527:OK 1047551:OK 1048063:OK 1048319:OK 1048447:OK 1048511:OK 1048543:OK 1048559:FAIL 1048546:FAIL 1048544:FAIL
minus=no # minus
###< select * from crash_me minus select * from crash_me3
###> execute error: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 crash_me3' at line 1
@@ -2426,13 +2425,13 @@ psm_functions=no # PSM functions (ANSI SQL)
###< create table crash_q (a int)
###> OK
###< create function crash_func(in a1 int, in b1 int) returns int language sql deterministic contains sql begin return a1 * b1; end
- ###> execute error: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 '(in a1 int, in b1 int) returns int language sql deterministic c
+ ###> execute error: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 'in a1 int, in b1 int) returns int language sql deterministic co
###< insert into crash_q values(crash_func(2,4))
###> execute error: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,4))' at line 1
###< select a,crash_func(a,2) from crash_q
###> execute error: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,2) from crash_q' at line 1
###< drop function crash_func cascade
- ###> execute error: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 'cascade' at line 1
+ ###> execute error:Failed to DROP FUNCTION crash_func
###< drop table crash_q
###> OK
###
@@ -2443,7 +2442,7 @@ psm_modules=no # PSM modules (ANSI SQL)
###< create module crash_m declare procedure crash_proc(in a1 int, in b1 int) language sql modifies sql data begin declare c1 int; set c1 = a1 + b1; insert into crash_q(a,b) values (a1,c1); end; declare procedure crash_proc2(INOUT a int, in b int) contains sql set a = b + 10; end module
###> execute error: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 'module crash_m declare procedure crash_proc(in a1 int, in b1 in
###< call crash_proc(1,10)
- ###> execute error: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 'call crash_proc(1,10)' at line 1
+ ###> execute error:PROCEDURE crash_proc does not exist
###< drop module crash_m cascade
###> execute error: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 'module crash_m cascade' at line 1
###< drop table crash_q cascade
@@ -2454,11 +2453,11 @@ psm_procedures=no # PSM procedures (ANSI SQL)
###< create table crash_q (a int,b int)
###> OK
###< create procedure crash_proc(in a1 int, in b1 int) language sql modifies sql data begin declare c1 int; set c1 = a1 + b1; insert into crash_q(a,b) values (a1,c1); end
- ###> execute error: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 'procedure crash_proc(in a1 int, in b1 int) language sql modifie
+ ###> execute error: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 'sql data begin declare c1 int; set c1 = a1 + b1; insert into cr
###< call crash_proc(1,10)
- ###> execute error: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 'call crash_proc(1,10)' at line 1
+ ###> execute error:PROCEDURE crash_proc does not exist
###< drop procedure crash_proc
- ###> execute error: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 'procedure crash_proc' at line 1
+ ###> execute error:Failed to DROP PROCEDURE crash_proc
###< drop table crash_q
###> OK
###
@@ -2502,6 +2501,9 @@ quote_with_"=yes # Allows ' and " as string markers
###> OK
###
###As far as all queries returned OK, result is YES
+recursive_subqueries=+64 # recursive subqueries
+ ###We are trying (example with N=5):
+ ###select a from crash_me where a in (select a from crash_me where a in (select a from crash_me where a in (select a from c...(82)
remember_end_space=no # Remembers end space in char()
###< create table crash_q (a char(10))
###> OK
@@ -2651,13 +2653,13 @@ reserved_word_ansi-92/99_authorization=no # Keyword AUTHORIZATION
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_before=no # Keyword BEFORE
+reserved_word_ansi-92/99_before=yes # Keyword BEFORE
###< create table crash_me10 (BEFORE int not null)
- ###> OK
+ ###> execute error: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 'BEFORE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_begin=no # Keyword BEGIN
###< create table crash_me10 (BEGIN int not null)
###> OK
@@ -2700,13 +2702,13 @@ reserved_word_ansi-92/99_by=yes # Keyword BY
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_call=no # Keyword CALL
+reserved_word_ansi-92/99_call=yes # Keyword CALL
###< create table crash_me10 (CALL int not null)
- ###> OK
+ ###> execute error: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 'CALL int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_cascade=yes # Keyword CASCADE
###< create table crash_me10 (CASCADE int not null)
###> execute error: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 'CASCADE int not null)' at line 1
@@ -2770,13 +2772,13 @@ reserved_word_ansi-92/99_close=no # Keyword CLOSE
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_collate=no # Keyword COLLATE
+reserved_word_ansi-92/99_collate=yes # Keyword COLLATE
###< create table crash_me10 (COLLATE int not null)
- ###> OK
+ ###> execute error: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 'COLLATE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_collation=no # Keyword COLLATION
###< create table crash_me10 (COLLATION int not null)
###> OK
@@ -2812,13 +2814,13 @@ reserved_word_ansi-92/99_connect=no # Keyword CONNECT
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_connection=no # Keyword CONNECTION
+reserved_word_ansi-92/99_connection=yes # Keyword CONNECTION
###< create table crash_me10 (CONNECTION int not null)
- ###> OK
+ ###> execute error: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 'CONNECTION int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_constraint=yes # Keyword CONSTRAINT
###< create table crash_me10 (CONSTRAINT int not null)
###> execute error: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 'int not null)' at line 1
@@ -2833,13 +2835,13 @@ reserved_word_ansi-92/99_constraints=no # Keyword CONSTRAINTS
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_continue=no # Keyword CONTINUE
+reserved_word_ansi-92/99_continue=yes # Keyword CONTINUE
###< create table crash_me10 (CONTINUE int not null)
- ###> OK
+ ###> execute error: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 'CONTINUE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_corresponding=no # Keyword CORRESPONDING
###< create table crash_me10 (CORRESPONDING int not null)
###> OK
@@ -2896,13 +2898,13 @@ reserved_word_ansi-92/99_current_user=no # Keyword CURRENT_USER
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_cursor=no # Keyword CURSOR
+reserved_word_ansi-92/99_cursor=yes # Keyword CURSOR
###< create table crash_me10 (CURSOR int not null)
- ###> OK
+ ###> execute error: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 'CURSOR int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_cycle=no # Keyword CYCLE
###< create table crash_me10 (CYCLE int not null)
###> OK
@@ -2952,13 +2954,13 @@ reserved_word_ansi-92/99_decimal=yes # Keyword DECIMAL
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_declare=no # Keyword DECLARE
+reserved_word_ansi-92/99_declare=yes # Keyword DECLARE
###< create table crash_me10 (DECLARE int not null)
- ###> OK
+ ###> execute error: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 'DECLARE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_default=yes # Keyword DEFAULT
###< create table crash_me10 (DEFAULT int not null)
###> execute error: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 int not null)' at line 1
@@ -3078,13 +3080,13 @@ reserved_word_ansi-92/99_else=yes # Keyword ELSE
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_elseif=no # Keyword ELSEIF
+reserved_word_ansi-92/99_elseif=yes # Keyword ELSEIF
###< create table crash_me10 (ELSEIF int not null)
- ###> OK
+ ###> execute error: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 'ELSEIF int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_end=no # Keyword END
###< create table crash_me10 (END int not null)
###> OK
@@ -3148,20 +3150,20 @@ reserved_word_ansi-92/99_external=no # Keyword EXTERNAL
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_false=no # Keyword FALSE
+reserved_word_ansi-92/99_false=yes # Keyword FALSE
###< create table crash_me10 (FALSE int not null)
- ###> OK
+ ###> execute error: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 'FALSE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_fetch=no # Keyword FETCH
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_fetch=yes # Keyword FETCH
###< create table crash_me10 (FETCH int not null)
- ###> OK
+ ###> execute error: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 'FETCH int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_first=no # Keyword FIRST
###< create table crash_me10 (FIRST int not null)
###> OK
@@ -3190,13 +3192,13 @@ reserved_word_ansi-92/99_foreign=yes # Keyword FOREIGN
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_found=no # Keyword FOUND
+reserved_word_ansi-92/99_found=yes # Keyword FOUND
###< create table crash_me10 (FOUND int not null)
- ###> OK
+ ###> execute error: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 'FOUND int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_from=yes # Keyword FROM
###< create table crash_me10 (FROM int not null)
###> execute error: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 int not null)' at line 1
@@ -3428,13 +3430,13 @@ reserved_word_ansi-92/99_leading=yes # Keyword LEADING
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_leave=no # Keyword LEAVE
+reserved_word_ansi-92/99_leave=yes # Keyword LEAVE
###< create table crash_me10 (LEAVE int not null)
- ###> OK
+ ###> execute error: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 'LEAVE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_left=yes # Keyword LEFT
###< create table crash_me10 (LEFT int not null)
###> execute error: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 'LEFT int not null)' at line 1
@@ -3458,7 +3460,7 @@ reserved_word_ansi-92/99_level=no # Keyword LEVEL
###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_like=yes # Keyword LIKE
###< create table crash_me10 (LIKE int not null)
- ###> execute error: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 'LIKE int not null)' at line 1
+ ###> execute error: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 'int not null)' at line 1
###< drop table crash_me10
###> execute error:Unknown table 'crash_me10'
###
@@ -3477,13 +3479,13 @@ reserved_word_ansi-92/99_local=no # Keyword LOCAL
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_loop=no # Keyword LOOP
+reserved_word_ansi-92/99_loop=yes # Keyword LOOP
###< create table crash_me10 (LOOP int not null)
- ###> OK
+ ###> execute error: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 'LOOP int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_match=yes # Keyword MATCH
###< create table crash_me10 (MATCH int not null)
###> execute error: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 'MATCH int not null)' at line 1
@@ -3701,13 +3703,13 @@ reserved_word_ansi-92/99_parameters=no # Keyword PARAMETERS
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_partial=yes # Keyword PARTIAL
+reserved_word_ansi-92/99_partial=no # Keyword PARTIAL
###< create table crash_me10 (PARTIAL int not null)
- ###> execute error: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 'PARTIAL int not null)' at line 1
+ ###> OK
###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
+ ###> OK
###
- ###As far as some queries didnt return OK, result is YES
+ ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_precision=yes # Keyword PRECISION
###< create table crash_me10 (PRECISION int not null)
###> execute error: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 'PRECISION int not null)' at line 1
@@ -3834,20 +3836,20 @@ reserved_word_ansi-92/99_restrict=yes # Keyword RESTRICT
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_return=no # Keyword RETURN
+reserved_word_ansi-92/99_return=yes # Keyword RETURN
###< create table crash_me10 (RETURN int not null)
- ###> OK
+ ###> execute error: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 'RETURN int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_returns=yes # Keyword RETURNS
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_returns=no # Keyword RETURNS
###< create table crash_me10 (RETURNS int not null)
- ###> execute error: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 'RETURNS int not null)' at line 1
+ ###> OK
###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
+ ###> OK
###
- ###As far as some queries didnt return OK, result is YES
+ ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_revoke=yes # Keyword REVOKE
###< create table crash_me10 (REVOKE int not null)
###> execute error: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 'REVOKE int not null)' at line 1
@@ -4009,34 +4011,34 @@ reserved_word_ansi-92/99_space=no # Keyword SPACE
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_sql=no # Keyword SQL
+reserved_word_ansi-92/99_sql=yes # Keyword SQL
###< create table crash_me10 (SQL int not null)
- ###> OK
+ ###> execute error: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 'SQL int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_sqlexception=no # Keyword SQLEXCEPTION
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_sqlexception=yes # Keyword SQLEXCEPTION
###< create table crash_me10 (SQLEXCEPTION int not null)
- ###> OK
+ ###> execute error: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 'SQLEXCEPTION int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_sqlstate=no # Keyword SQLSTATE
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_sqlstate=yes # Keyword SQLSTATE
###< create table crash_me10 (SQLSTATE int not null)
- ###> OK
+ ###> execute error: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 'SQLSTATE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_sqlwarning=no # Keyword SQLWARNING
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_sqlwarning=yes # Keyword SQLWARNING
###< create table crash_me10 (SQLWARNING int not null)
- ###> OK
+ ###> execute error: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 'SQLWARNING int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_structure=no # Keyword STRUCTURE
###< create table crash_me10 (STRUCTURE int not null)
###> OK
@@ -4135,13 +4137,13 @@ reserved_word_ansi-92/99_trigger=no # Keyword TRIGGER
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_true=no # Keyword TRUE
+reserved_word_ansi-92/99_true=yes # Keyword TRUE
###< create table crash_me10 (TRUE int not null)
- ###> OK
+ ###> execute error: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 'TRUE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_under=no # Keyword UNDER
###< create table crash_me10 (UNDER int not null)
###> OK
@@ -4261,13 +4263,13 @@ reserved_word_ansi-92/99_where=yes # Keyword WHERE
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_while=no # Keyword WHILE
+reserved_word_ansi-92/99_while=yes # Keyword WHILE
###< create table crash_me10 (WHILE int not null)
- ###> OK
+ ###> execute error: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 'WHILE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_with=yes # Keyword WITH
###< create table crash_me10 (WITH int not null)
###> execute error: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 'WITH int not null)' at line 1
@@ -4387,13 +4389,13 @@ reserved_word_ansi92_extract=no # Keyword EXTRACT
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi92_insensitive=no # Keyword INSENSITIVE
+reserved_word_ansi92_insensitive=yes # Keyword INSENSITIVE
###< create table crash_me10 (INSENSITIVE int not null)
- ###> OK
+ ###> execute error: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 'INSENSITIVE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi92_lower=no # Keyword LOWER
###< create table crash_me10 (LOWER int not null)
###> OK
@@ -4492,13 +4494,13 @@ reserved_word_ansi92_replace=yes # Keyword REPLACE
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_ansi92_sensitive=no # Keyword SENSITIVE
+reserved_word_ansi92_sensitive=yes # Keyword SENSITIVE
###< create table crash_me10 (SENSITIVE int not null)
- ###> OK
+ ###> execute error: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 'SENSITIVE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi92_similar=no # Keyword SIMILAR
###< create table crash_me10 (SIMILAR int not null)
###> OK
@@ -4646,13 +4648,13 @@ reserved_word_ansi99_clob=no # Keyword CLOB
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi99_condition=no # Keyword CONDITION
+reserved_word_ansi99_condition=yes # Keyword CONDITION
###< create table crash_me10 (CONDITION int not null)
- ###> OK
+ ###> execute error: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 'CONDITION int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_constructor=no # Keyword CONSTRUCTOR
###< create table crash_me10 (CONSTRUCTOR int not null)
###> OK
@@ -4716,13 +4718,13 @@ reserved_word_ansi99_destructor=no # Keyword DESTRUCTOR
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi99_deterministic=no # Keyword DETERMINISTIC
+reserved_word_ansi99_deterministic=yes # Keyword DETERMINISTIC
###< create table crash_me10 (DETERMINISTIC int not null)
- ###> OK
+ ###> execute error: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 'DETERMINISTIC int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_do=no # Keyword DO
###< create table crash_me10 (DO int not null)
###> OK
@@ -4744,13 +4746,13 @@ reserved_word_ansi99_every=no # Keyword EVERY
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi99_exit=no # Keyword EXIT
+reserved_word_ansi99_exit=yes # Keyword EXIT
###< create table crash_me10 (EXIT int not null)
- ###> OK
+ ###> execute error: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 'EXIT int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_expand=no # Keyword EXPAND
###< create table crash_me10 (EXPAND int not null)
###> OK
@@ -4814,20 +4816,20 @@ reserved_word_ansi99_initialize=no # Keyword INITIALIZE
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi99_inout=no # Keyword INOUT
+reserved_word_ansi99_inout=yes # Keyword INOUT
###< create table crash_me10 (INOUT int not null)
- ###> OK
+ ###> execute error: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 'INOUT int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_iterate=no # Keyword ITERATE
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi99_iterate=yes # Keyword ITERATE
###< create table crash_me10 (ITERATE int not null)
- ###> OK
+ ###> execute error: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 'ITERATE int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_large=no # Keyword LARGE
###< create table crash_me10 (LARGE int not null)
###> OK
@@ -4898,13 +4900,13 @@ reserved_word_ansi99_ordinality=no # Keyword ORDINALITY
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi99_out=no # Keyword OUT
+reserved_word_ansi99_out=yes # Keyword OUT
###< create table crash_me10 (OUT int not null)
- ###> OK
+ ###> execute error: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 'OUT int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_parameter=no # Keyword PARAMETER
###< create table crash_me10 (PARAMETER int not null)
###> OK
@@ -4961,13 +4963,13 @@ reserved_word_ansi99_redo=no # Keyword REDO
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi99_repeat=no # Keyword REPEAT
+reserved_word_ansi99_repeat=yes # Keyword REPEAT
###< create table crash_me10 (REPEAT int not null)
- ###> OK
+ ###> execute error: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 'REPEAT int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_result=no # Keyword RESULT
###< create table crash_me10 (RESULT int not null)
###> OK
@@ -4989,13 +4991,13 @@ reserved_word_ansi99_sets=no # Keyword SETS
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi99_specific=no # Keyword SPECIFIC
+reserved_word_ansi99_specific=yes # Keyword SPECIFIC
###< create table crash_me10 (SPECIFIC int not null)
- ###> OK
+ ###> execute error: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 'SPECIFIC int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_specifictype=no # Keyword SPECIFICTYPE
###< create table crash_me10 (SPECIFICTYPE int not null)
###> OK
@@ -5052,13 +5054,13 @@ reserved_word_ansi99_treat=no # Keyword TREAT
###> OK
###
###As far as all queries returned OK, result is NO
-reserved_word_ansi99_undo=no # Keyword UNDO
+reserved_word_ansi99_undo=yes # Keyword UNDO
###< create table crash_me10 (UNDO int not null)
- ###> OK
+ ###> execute error: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 'UNDO int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_until=no # Keyword UNTIL
###< create table crash_me10 (UNTIL int not null)
###> OK
@@ -5955,13 +5957,13 @@ reserved_word_extra_soname=yes # Keyword SONAME
###> execute error:Unknown table 'crash_me10'
###
###As far as some queries didnt return OK, result is YES
-reserved_word_extra_spatial=no # Keyword SPATIAL
+reserved_word_extra_spatial=yes # Keyword SPATIAL
###< create table crash_me10 (SPATIAL int not null)
- ###> OK
+ ###> execute error: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 'int not null)' at line 1
###< drop table crash_me10
- ###> OK
+ ###> execute error:Unknown table 'crash_me10'
###
- ###As far as all queries returned OK, result is NO
+ ###As far as some queries didnt return OK, result is YES
reserved_word_extra_sql_big_result=yes # Keyword SQL_BIG_RESULT
###< create table crash_me10 (SQL_BIG_RESULT int not null)
###> execute error: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 'SQL_BIG_RESULT int not null)' at line 1
@@ -6273,13 +6275,16 @@ select_limit3=yes # SELECT with LIMIT # OFFSET #
select_string_size=1048565 # constant string size in SELECT
###We are trying (example with N=5):
###select 'aaaaa'
-select_table_update=no # Update with sub select
+select_table_update=yes # Update with sub select
###< create table crash_q (a integer,b char(10))
###> OK
###< insert into crash_q values(1,'c')
###> OK
###< update crash_q set b= (select b from crash_me where crash_q.a = crash_me.a)
- ###> execute error: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 b from crash_me where crash_q.a = crash_me.a)' at line 1
+ ###> OK
+ ###
+ ###<select b from crash_q
+ ###>a
###
###< drop table crash_q
###> OK
@@ -6288,7 +6293,7 @@ select_without_from=yes # SELECT without FROM
###> OK
###
###As far as all queries returned OK, result is YES
-server_version=MySQL 4.0.20 debug/ # server version
+server_version=MySQL 5.0.0 alpha debug log/ # server version
simple_joins=yes # ANSI SQL simple joins
###< select crash_me.a from crash_me, crash_me t0
###> OK
@@ -6383,11 +6388,11 @@ storage_of_float=round # Storage of float values
###
###< drop table crash_q
###> OK
-subqueries=no # subqueries
+subqueries=yes # subqueries
###< select a from crash_me where crash_me.a in (select max(a) from crash_me)
- ###> execute error: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 max(a) from crash_me)' at line 1
+ ###> OK
###
- ###As far as some queries didnt return OK, result is NO
+ ###As far as all queries returned OK, result is YES
table_alias=yes # Table alias
###< select b.a from crash_me as b
###> OK
@@ -6455,21 +6460,7 @@ time_format_inresult=iso # Time format in result
###> OK
###
###< select a from crash_me_t
- ###> 19:55:21
- ###< delete from crash_me_t
- ###> OK
- ###< insert into crash_me_t values(CURRENT_TIME)
- ###> OK
- ###
- ###< select a from crash_me_t
- ###> 13:45:04
- ###< delete from crash_me_t
- ###> OK
- ###< insert into crash_me_t values(CURRENT_TIME)
- ###> OK
- ###
- ###< select a from crash_me_t
- ###> 13:47:18
+ ###> 09:46:11
###< delete from crash_me_t
###> OK
transactions=yes # transactions
@@ -6688,13 +6679,13 @@ type_extra_line=no # Type line
###> execute error:Unknown table 'crash_q'
###
###As far as some queries didnt return OK, result is NO
-type_extra_long=no # Type long
+type_extra_long=yes # Type long
###< create table crash_q (q long)
- ###> execute error: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
+ ###> OK
###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
+ ###> OK
###
- ###As far as some queries didnt return OK, result is NO
+ ###As far as all queries returned OK, result is YES
type_extra_long_raw=no # Type long raw
###< create table crash_q (q long raw)
###> execute error: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 'raw)' at line 1
@@ -6807,20 +6798,20 @@ type_extra_path=no # Type path
###> execute error:Unknown table 'crash_q'
###
###As far as some queries didnt return OK, result is NO
-type_extra_point=no # Type point
+type_extra_point=yes # Type point
###< create table crash_q (q point)
- ###> execute error: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 'point)' at line 1
+ ###> OK
###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
+ ###> OK
###
- ###As far as some queries didnt return OK, result is NO
-type_extra_polygon=no # Type polygon
+ ###As far as all queries returned OK, result is YES
+type_extra_polygon=yes # Type polygon
###< create table crash_q (q polygon)
- ###> execute error: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 'polygon)' at line 1
+ ###> OK
###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
+ ###> OK
###
- ###As far as some queries didnt return OK, result is NO
+ ###As far as all queries returned OK, result is YES
type_extra_raw(1_arg)=no # Type raw(1 arg)
###< create table crash_q (q raw(16))
###> execute error: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 'raw(16))' at line 1
@@ -6842,13 +6833,13 @@ type_extra_rowid=no # Type rowid
###> execute error:Unknown table 'crash_q'
###
###As far as some queries didnt return OK, result is NO
-type_extra_serial=no # Type serial
+type_extra_serial=yes # Type serial
###< create table crash_q (q serial)
- ###> execute error: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 'serial)' at line 1
+ ###> OK
###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
+ ###> OK
###
- ###As far as some queries didnt return OK, result is NO
+ ###As far as all queries returned OK, result is YES
type_extra_set(1_arg)=yes # Type set(1 arg)
###< create table crash_q (q set('red'))
###> OK
@@ -6884,13 +6875,13 @@ type_extra_text=yes # Type text
###> OK
###
###As far as all queries returned OK, result is YES
-type_extra_text(1_arg)=no # Type text(1 arg)
+type_extra_text(1_arg)=yes # Type text(1 arg)
###< create table crash_q (q text(10))
- ###> execute error: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 '(10))' at line 1
+ ###> OK
###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
+ ###> OK
###
- ###As far as some queries didnt return OK, result is NO
+ ###As far as all queries returned OK, result is YES
type_extra_timespan=no # Type timespan
###< create table crash_q (q timespan)
###> execute error: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 'timespan)' at line 1
@@ -6975,13 +6966,13 @@ type_sql_bit_varying(1_arg)=no # Type bit varying(1 arg)
###> execute error:Unknown table 'crash_q'
###
###As far as some queries didnt return OK, result is NO
-type_sql_boolean=no # Type boolean
+type_sql_boolean=yes # Type boolean
###< create table crash_q (q boolean)
- ###> execute error: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 'boolean)' at line 1
+ ###> OK
###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
+ ###> OK
###
- ###As far as some queries didnt return OK, result is NO
+ ###As far as all queries returned OK, result is YES
type_sql_char(1_arg)=yes # Type char(1 arg)
###< create table crash_q (q char(1))
###> OK
@@ -7281,12 +7272,12 @@ unique_null_in_create=yes # unique null in create
###> OK
###
###As far as all queries returned OK, result is YES
-value_of_false=not supported # Value of FALSE
+value_of_false=0 # Value of FALSE
###<select FALSE
- ###> execute failed:Unknown column 'FALSE' in 'field list'
-value_of_true=not supported # Value of TRUE
+ ###>0
+value_of_true=1 # Value of TRUE
###<select TRUE
- ###> execute failed:Unknown column 'TRUE' in 'field list'
+ ###>1
views=no # views
###< create view crash_q as select a from crash_me
###> execute error: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 'view crash_q as select a from crash_me' at line 1
diff --git a/sql-bench/limits/mysql-4.1.cfg b/sql-bench/limits/mysql-4.1.cfg
new file mode 100644
index 00000000000..64f91f07363
--- /dev/null
+++ b/sql-bench/limits/mysql-4.1.cfg
@@ -0,0 +1,7056 @@
+#This file is automaticly generated by crash-me 1.61
+
+NEG=yes # update of column= -column
+ ###< create table crash_q (a integer)
+ ###> OK
+ ###< insert into crash_q values(10)
+ ###> OK
+ ###< update crash_q set a=-a
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+Need_cast_for_null=no # Need to cast NULL for arithmetic
+ ### Check if numeric_null (NULL) is 'NULL'
+alter_add_col=yes # Alter table add column
+ ###< alter table crash_q add d integer
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+alter_add_constraint=yes # Alter table add constraint
+ ###< alter table crash_q add constraint c2 check(a > b)
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+alter_add_foreign_key=no # Alter table add foreign key
+ ###< alter table crash_q add constraint f1 foreign key(c1)
+ ###> execute error: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
+ ###< references crash_q1(c1)
+ ###> execute error: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 'references crash_q1(c1)' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+alter_add_multi_col=yes # Alter table add many columns
+ ###< alter table crash_q add (f integer,g integer)
+ ###> OK
+alter_add_primary_key=with constraint # Alter table add primary key
+ ###< alter table crash_q1 add constraint p1 primary key(c1)
+ ###> OK
+alter_add_unique=yes # Alter table add unique
+ ###< alter table crash_q add constraint u1 unique(c1)
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+alter_alter_col=yes # Alter table alter column default
+ ###< alter table crash_q alter b set default 10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+alter_change_col=yes # Alter table change column
+ ###< alter table crash_q change a e char(50)
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+alter_drop_col=yes # Alter table drop column
+ ###< alter table crash_q drop column b
+ ###> OK
+alter_drop_constraint=no # Alter table drop constraint
+ ###< alter table crash_q drop constraint c2
+ ###> execute error: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 'constraint c2' at line 1
+ ###
+ ###< alter table crash_q drop constraint c2 restrict
+ ###> execute error: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 'constraint c2 restrict' at line 1
+alter_drop_foreign_key=with drop foreign key # Alter table drop foreign key
+ ###< alter table crash_q drop constraint f1
+ ###> execute error: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 'constraint f1' at line 1
+ ###
+ ###< alter table crash_q drop constraint f1 restrict
+ ###> execute error: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 'constraint f1 restrict' at line 1
+ ###
+ ###< alter table crash_q drop foreign key f1
+ ###> OK
+alter_drop_primary_key=drop primary key # Alter table drop primary key
+ ###< alter table crash_q1 drop constraint p1 restrict
+ ###> execute error: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 'constraint p1 restrict' at line 1
+ ###
+ ###< alter table crash_q1 drop primary key
+ ###> OK
+alter_drop_unique=with drop key # Alter table drop unique
+ ###< alter table crash_q drop constraint u1
+ ###> execute error: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 'constraint u1' at line 1
+ ###
+ ###< alter table crash_q drop constraint u1 restrict
+ ###> execute error: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 'constraint u1 restrict' at line 1
+ ###
+ ###< alter table crash_q drop key u1
+ ###> OK
+alter_modify_col=yes # Alter table modify column
+ ###< alter table crash_q modify c1 CHAR(20)
+ ###> OK
+alter_rename_table=yes # Alter table rename table
+ ###< alter table crash_q rename to crash_q1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+atomic_updates=no # atomic updates
+ ###< create table crash_q (a integer not null,primary key (a))
+ ###> OK
+ ###< insert into crash_q values (2)
+ ###> OK
+ ###< insert into crash_q values (3)
+ ###> OK
+ ###< insert into crash_q values (1)
+ ###> OK
+ ###< update crash_q set a=a+1
+ ###> execute error:Duplicate entry '3' for key 1
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as some queries didnt return OK, result is NO
+automatic_rowid=_rowid # Automatic row id
+ ###< create table crash_q (a int not null, primary key(a))
+ ###> OK
+ ###< insert into crash_q values (1)
+ ###> OK
+ ###< select _rowid from crash_q
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+binary_numbers=no # binary numbers (0b1001)
+ ###< select 0b1001
+ ###> execute error:Unknown column '0b1001' in 'field list'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+binary_strings=no # binary strings (b'0110')
+ ###< select b'0110'
+ ###> execute error:Unknown column 'b' in 'field list'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+case_insensitive_strings=yes # Case insensitive compare
+ ###
+ ###<select b from crash_me where b = 'A'
+ ###>a
+char_is_space_filled=no # char are space filled
+ ###
+ ###<select concat(b,b) from crash_me where b = 'a '
+ ###>aa
+ ###We expected 'a a ' but got 'aa'
+column_alias=yes # Column alias
+ ###< select a as ab from crash_me
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+columns_in_group_by=+64 # number of columns in group by
+ ###We are trying (example with N=5):
+ ###create table crash_q (q1 integer,q2 integer,q3 integer,q4 integer,q5 integer)
+ ###insert into crash_q values(1,1,1,1,1)
+ ###insert into crash_q values(1,1,1,1,1)
+ ###select q1,q2,q3,q4,q5 from crash_q group by q1,q2,q3,q4,q5
+columns_in_order_by=+64 # number of columns in order by
+ ###We are trying (example with N=5):
+ ###create table crash_q (q1 integer,q2 integer,q3 integer,q4 integer,q5 integer)
+ ###insert into crash_q values(1,1,1,1,1)
+ ###insert into crash_q values(1,1,1,1,1)
+ ###select * from crash_q order by q1,q2,q3,q4,q5
+comment_#=yes # # as comment
+ ###< select * from crash_me # Testing of comments
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+comment_--=yes # -- as comment (ANSI)
+ ###< select * from crash_me -- Testing of comments
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+comment_/**/=yes # /* */ as comment
+ ###< select * from crash_me /* Testing of comments */
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+comment_//=no # // as comment
+ ###< select * from crash_me // Testing of comments
+ ###> execute error: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 '// Testing of comments' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+compute=no # Compute
+ ###< select a from crash_me order by a compute sum(a) by a
+ ###> execute error: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 'compute sum(a) by a' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+connections=101 # Simultaneous connections (installation default)
+constraint_check=syntax only # Column constraints
+ ###< create table crash_q (a int check (a>0))
+ ###> OK
+ ###
+ ###< insert into crash_q values(0)
+ ###> OK
+ ###
+ ###< drop table crash_q
+ ###> OK
+constraint_check_named=syntax only # Named constraints
+ ###< create table crash_q (a int ,b int, constraint abc check (a>b))
+ ###> OK
+ ###
+ ###< insert into crash_q values(0,0)
+ ###> OK
+ ###
+ ###< drop table crash_q
+ ###> OK
+constraint_check_table=syntax only # Table constraints
+ ###< create table crash_q (a int ,b int, check (a>b))
+ ###> OK
+ ###
+ ###< insert into crash_q values(0,0)
+ ###> OK
+ ###
+ ###< drop table crash_q
+ ###> OK
+constraint_null=yes # NULL constraint (SyBase style)
+ ###< create table crash_q (a int null)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+crash_me_safe=yes # crash me safe
+crash_me_version=1.61 # crash me version
+create_default=yes # default value for column
+ ###< create table crash_q (q integer default 10 not null)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+create_default_func=no # default value function for column
+ ###< create table crash_q (q integer not null,q1 integer default (1+1))
+ ###> execute error: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
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+create_if_not_exists=yes # create table if not exists
+ ###< create table crash_q (q integer)
+ ###> OK
+ ###< create table if not exists crash_q (q integer)
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+create_index=yes # create index
+ ###< create index crash_q on crash_me (a)
+ ###> OK
+create_schema=no # Create SCHEMA
+ ###< create schema crash_schema create table crash_q (a int) create table crash_q2(b int)
+ ###> execute error: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 'schema crash_schema create table crash_q (a int) create table c
+ ###< drop schema crash_schema cascade
+ ###> execute error: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 'schema crash_schema cascade' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+create_table_select=yes # create table from select
+ ###< create table crash_q SELECT * from crash_me
+ ###> OK
+cross_join=yes # cross join (same as from a,b)
+ ###< select crash_me.a from crash_me cross join crash_me3
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+date_as_string=yes # String functions on date columns
+ ###< create table crash_me2 (a date not null)
+ ###> OK
+ ###< insert into crash_me2 values ('1998-03-03')
+ ###> OK
+ ###
+ ###<select left(a,4) from crash_me2
+ ###>1998
+ ###
+ ###< drop table crash_me2
+ ###> OK
+date_format_EUR=error # Supports DD.MM.YYYY (EUR) format
+ ###< insert into crash_me_d(a) values ('16.08.1963')
+ ###> OK
+ ###
+ ###<select a from crash_me_d
+ ###>0000-00-00
+ ###We expected '1963-08-16' but got '0000-00-00'
+ ###
+ ###< delete from crash_me_d
+ ###> OK
+date_format_EUR_with_date=error # Supports DATE 'DD.MM.YYYY' (EUR) format
+ ###< insert into crash_me_d(a) values (DATE '16.08.1963')
+ ###> OK
+ ###
+ ###<select a from crash_me_d
+ ###>0000-00-00
+ ###We expected '1963-08-16' but got '0000-00-00'
+ ###
+ ###< delete from crash_me_d
+ ###> OK
+date_format_ISO=yes # Supports YYYY-MM-DD (ISO) format
+ ###< insert into crash_me_d(a) values ('1963-08-16')
+ ###> OK
+ ###
+ ###<select a from crash_me_d
+ ###>1963-08-16
+ ###
+ ###< delete from crash_me_d
+ ###> OK
+date_format_ISO_with_date=yes # Supports DATE 'YYYY-MM-DD' (ISO) format
+ ###< insert into crash_me_d(a) values (DATE '1963-08-16')
+ ###> OK
+ ###
+ ###<select a from crash_me_d
+ ###>1963-08-16
+ ###
+ ###< delete from crash_me_d
+ ###> OK
+date_format_USA=error # Supports MM/DD/YYYY format
+ ###< insert into crash_me_d(a) values ('08/16/1963')
+ ###> OK
+ ###
+ ###<select a from crash_me_d
+ ###>0000-00-00
+ ###We expected '1963-08-16' but got '0000-00-00'
+ ###
+ ###< delete from crash_me_d
+ ###> OK
+date_format_USA_with_date=error # Supports DATE 'MM/DD/YYYY' format
+ ###< insert into crash_me_d(a) values (DATE '08/16/1963')
+ ###> OK
+ ###
+ ###<select a from crash_me_d
+ ###>0000-00-00
+ ###We expected '1963-08-16' but got '0000-00-00'
+ ###
+ ###< delete from crash_me_d
+ ###> OK
+date_format_YYYYMMDD=yes # Supports YYYYMMDD format
+ ###< insert into crash_me_d(a) values ('19630816')
+ ###> OK
+ ###
+ ###<select a from crash_me_d
+ ###>1963-08-16
+ ###
+ ###< delete from crash_me_d
+ ###> OK
+date_format_YYYYMMDD_with_date=yes # Supports DATE 'YYYYMMDD' format
+ ###< insert into crash_me_d(a) values (DATE '19630816')
+ ###> OK
+ ###
+ ###<select a from crash_me_d
+ ###>1963-08-16
+ ###
+ ###< delete from crash_me_d
+ ###> OK
+date_format_inresult=iso # Date format in result
+ ###< insert into crash_me_d values( sysdate() )
+ ###> OK
+ ###
+ ###< select a from crash_me_d
+ ###> 2004-04-06
+ ###< delete from crash_me_d
+ ###> OK
+date_infinity=error # Supports 'infinity dates
+ ###< create table crash_me2 (a date not null)
+ ###> OK
+ ###< insert into crash_me2 values ('infinity')
+ ###> OK
+ ###
+ ###<select a from crash_me2
+ ###>0000-00-00
+ ###We expected 'infinity' but got '0000-00-00'
+ ###
+ ###< drop table crash_me2
+ ###> OK
+date_last=yes # Supports 9999-12-31 dates
+ ###< create table crash_me2 (a date not null)
+ ###> OK
+ ###< insert into crash_me2 values ('9999-12-31')
+ ###> OK
+ ###
+ ###<select a from crash_me2
+ ###>9999-12-31
+ ###
+ ###< drop table crash_me2
+ ###> OK
+date_one=yes # Supports 0001-01-01 dates
+ ###< create table crash_me2 (a date not null)
+ ###> OK
+ ###< insert into crash_me2 values ('0001-01-01')
+ ###> OK
+ ###
+ ###<select a from crash_me2
+ ###>0001-01-01
+ ###
+ ###< drop table crash_me2
+ ###> OK
+date_with_YY=yes # Supports YY-MM-DD 2000 compilant dates
+ ###< create table crash_me2 (a date not null)
+ ###> OK
+ ###< insert into crash_me2 values ('98-03-03')
+ ###> OK
+ ###
+ ###<select a from crash_me2
+ ###>1998-03-03
+ ###
+ ###< drop table crash_me2
+ ###> OK
+ ###
+ ###< create table crash_me2 (a date not null)
+ ###> OK
+ ###< insert into crash_me2 values ('10-03-03')
+ ###> OK
+ ###
+ ###<select a from crash_me2
+ ###>2010-03-03
+ ###
+ ###< drop table crash_me2
+ ###> OK
+date_zero=yes # Supports 0000-00-00 dates
+ ###< create table crash_me2 (a date not null)
+ ###> OK
+ ###< insert into crash_me2 values ('0000-00-00')
+ ###> OK
+ ###
+ ###<select a from crash_me2
+ ###>0000-00-00
+ ###
+ ###< drop table crash_me2
+ ###> OK
+domains=no # Domains (ANSI SQL)
+ ###< create domain crash_d as varchar(10) default 'Empty' check (value <> 'abcd')
+ ###> execute error: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 'domain crash_d as varchar(10) default 'Empty' check (value <> '
+ ###< create table crash_q(a crash_d, b int)
+ ###> execute error: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 'crash_d, b int)' at line 1
+ ###< insert into crash_q(a,b) values('xyz',10)
+ ###> execute error:Table 'test.crash_q' doesn't exist
+ ###< insert into crash_q(b) values(10)
+ ###> execute error:Table 'test.crash_q' doesn't exist
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###< drop domain crash_d
+ ###> execute error: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 'domain crash_d' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+dont_require_cast_to_float=yes # No need to cast from integer to float
+ ###< select exp(1)
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+double_quotes=yes # Double '' as ' in strings
+ ###
+ ###<select 'Walker''s'
+ ###>Walker's
+drop_if_exists=yes # drop table if exists
+ ###< create table crash_q (q integer)
+ ###> OK
+ ###< drop table if exists crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+drop_index=with 'ON' # drop index
+ ###< drop index crash_q
+ ###> execute error: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
+ ###
+ ###< drop index crash_q from crash_me
+ ###> execute error: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 crash_me' at line 1
+ ###
+ ###< drop index crash_q on crash_me
+ ###> OK
+drop_requires_cascade=no # drop table require cascade/restrict
+ ###< create table crash_me (a integer not null)
+ ###> OK
+ ###< drop table crash_me
+ ###> OK
+drop_restrict=yes # drop table with cascade/restrict
+ ###< create table crash_q (a int)
+ ###> OK
+ ###< drop table crash_q restrict
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+end_colon=yes # allows end ';'
+ ###< select * from crash_me;
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+except=no # except
+ ###< select * from crash_me except select * from crash_me3
+ ###> execute error: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 crash_me3' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+except_all=no # except all
+ ###< select * from crash_me except all select * from crash_me3
+ ###> execute error: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 'all select * from crash_me3' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+except_all_incompat=no # except all (incompatible lists)
+ ###< select * from crash_me except all select * from crash_me2
+ ###> execute error: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 'all select * from crash_me2' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+except_incompat=no # except (incompatible lists)
+ ###< select * from crash_me except select * from crash_me2
+ ###> execute error: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 crash_me2' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+field_name_case=yes # case independent field names
+ ###< create table crash_q (q integer)
+ ###> OK
+ ###< insert into crash_q(Q) values (1)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+float_int_expr=yes # mixing of integer and float in expression
+ ###< select 1+1.0
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+foreign_key=syntax only # foreign keys
+ ###< create table crash_me_qf (a integer not null,primary key (a))
+ ###> OK
+ ###
+ ###< create table crash_me_qf2 (a integer not null,foreign key (a) references crash_me_qf (a))
+ ###> OK
+ ###
+ ###< insert into crash_me_qf values (1)
+ ###> OK
+ ###
+ ###< insert into crash_me_qf2 values (2)
+ ###> OK
+ ###
+ ###< drop table crash_me_qf2
+ ###> OK
+ ###
+ ###< drop table crash_me_qf
+ ###> OK
+full_outer_join=no # full outer join
+ ###< select crash_me.a from crash_me full join crash_me2 ON
+ ### crash_me.a=crash_me2.a
+ ###> execute error:Unknown table 'crash_me' in field list
+ ###
+ ###As far as some queries didnt return OK, result is NO
+func_extra_!=yes # Function NOT as '!' in SELECT
+ ###
+ ###<select ! 1
+ ###>0
+func_extra_%=yes # Function MOD as %
+ ###
+ ###<select 10%7
+ ###>3
+func_extra_&=yes # Function & (bitwise and)
+ ###
+ ###<select 5 & 3
+ ###>1
+func_extra_&&=yes # Function AND as '&&'
+ ###
+ ###<select 1=1 && 2=2
+ ###>1
+func_extra_<>=yes # Function <> in SELECT
+ ###
+ ###<select 1<>1
+ ###>0
+func_extra_==yes # Function =
+ ###
+ ###<select (1=1)
+ ###>1
+func_extra_add_months=no # Function ADD_MONTHS
+ ###
+ ###<select add_months('1997-01-01',1) from crash_me_d
+ ###> execute failed: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 '('1997-01-01',1) from crash_me_d' at line 1
+func_extra_adddate=yes # Function ADDDATE
+ ###
+ ###<select ADDDATE('2002-12-01',3) from crash_me_d
+ ###>2002-12-04
+func_extra_addtime=yes # Function ADDTIME
+ ###
+ ###<select ADDTIME('20:02:12','00:00:03')
+ ###>20:02:15
+func_extra_alpha=no # Function ALPHA
+ ###
+ ###<select alpha('Aâ',2)
+ ###> execute failed: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â',2)' at line 1
+func_extra_and_or=yes # Function AND and OR in SELECT
+ ###
+ ###<select 1=1 AND 2=2
+ ###>1
+func_extra_ascii_char=no # Function ASCII_CHAR
+ ###
+ ###<select ASCII_CHAR(65)
+ ###> execute failed: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 '(65)' at line 1
+func_extra_ascii_code=no # Function ASCII_CODE
+ ###
+ ###<select ASCII_CODE('A')
+ ###> execute failed: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')' at line 1
+func_extra_ascii_string=error # Function ASCII in string cast
+ ###
+ ###<select ascii('a')
+ ###>97
+ ###We expected 'a' but got '97'
+func_extra_atn2=no # Function ATN2
+ ###
+ ###<select atn2(1,0)
+ ###> execute failed: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
+func_extra_auto_num2string=yes # Function automatic num->string convert
+ ###
+ ###<select concat('a',2)
+ ###>a2
+func_extra_auto_string2num=yes # Function automatic string->num convert
+ ###
+ ###<select '1'+2
+ ###>3
+func_extra_between=yes # Function BETWEEN in SELECT
+ ###
+ ###<select 5 between 4 and 6
+ ###>1
+func_extra_binary_shifts=yes # Function << and >> (bitwise shifts)
+ ###
+ ###<select (1 << 4) >> 2
+ ###>4
+func_extra_bit_count=yes # Function BIT_COUNT
+ ###
+ ###<select bit_count(5)
+ ###>2
+func_extra_ceil=yes # Function CEIL
+ ###
+ ###<select ceil(-4.5)
+ ###>-4
+func_extra_char_date=no # Function CHAR (conversation date)
+ ###
+ ###<select CHAR(a,EUR) from crash_me_d
+ ###> execute failed:Unknown column 'EUR' in 'field list'
+func_extra_charindex=no # Function CHARINDEX
+ ###
+ ###<select charindex('a','crash')
+ ###> execute failed: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','crash')' at line 1
+func_extra_chr=no # Function CHR
+ ###
+ ###<select CHR(65)
+ ###> execute failed: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 '(65)' at line 1
+func_extra_chr_str=no # Function CHR (any type to string)
+ ###
+ ###<select CHR(67)
+ ###> execute failed: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 '(67)' at line 1
+func_extra_concat_as_+=error # Function concatenation with +
+ ###
+ ###<select 'abc' + 'def'
+ ###>0
+ ###We expected 'abcdef' but got '0'
+func_extra_concat_list=yes # Function CONCAT(list)
+ ###
+ ###<select concat('a','b','c','d')
+ ###>abcd
+func_extra_convert=no # Function CONVERT
+ ###
+ ###<select convert(CHAR,5)
+ ###> execute failed: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 '5)' at line 1
+func_extra_cosh=no # Function COSH
+ ###
+ ###<select cosh(0)
+ ###> execute failed: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 '(0)' at line 1
+func_extra_date=yes # Function DATE
+ ###
+ ###<select date('1963-08-16') from crash_me_d
+ ###>1963-08-16
+func_extra_date_format=yes # Function DATE_FORMAT
+ ###
+ ###<select date_format('1997-01-02 03:04:05','M W D Y y m d h i s w') from crash_me_d
+ ###>M W D Y y m d h i s w
+func_extra_dateadd=no # Function DATEADD
+ ###
+ ###<select dateadd(day,3,'1997-11-30') from crash_me_d
+ ###> execute failed: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 '(day,3,'1997-11-30') from crash_me_d' at line 1
+func_extra_datediff=no # Function DATEDIFF
+ ###
+ ###<select datediff(month,'Oct 21 1997','Nov 30 1997') from crash_me_d
+ ###> execute failed: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 ''Nov 30 1997') from crash_me_d' at line 1
+func_extra_datediff2arg=yes # Function DATEDIFF (2 arg)
+ ###
+ ###<select DATEDIFF('2002-12-04','2002-12-01') from crash_me_d
+ ###>3
+func_extra_datename=no # Function DATENAME
+ ###
+ ###<select datename(month,'Nov 30 1997') from crash_me_d
+ ###> execute failed: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 '(month,'Nov 30 1997') from crash_me_d' at line 1
+func_extra_datepart=no # Function DATEPART
+ ###
+ ###<select datepart(month,'July 20 1997') from crash_me_d
+ ###> execute failed: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 '(month,'July 20 1997') from crash_me_d' at line 1
+func_extra_day=yes # Function DAY
+ ###
+ ###<select DAY('2002-12-01') from crash_me_d
+ ###>1
+func_extra_decode=no # Function DECODE
+ ###
+ ###<select DECODE('S-103','T72',1,'S-103',2,'Leopard',3)
+ ###> execute failed: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,'S-103',2,'Leopard',3)' at line 1
+func_extra_ebcdic_string=no # Function EBCDIC in string cast
+ ###
+ ###<select ebcdic('a')
+ ###> execute failed: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')' at line 1
+func_extra_elt=yes # Function ELT
+ ###
+ ###<select elt(2,'ONE','TWO','THREE')
+ ###>TWO
+func_extra_encrypt=yes # Function ENCRYPT
+ ###
+ ###<select encrypt('hello')
+ ###>VNeu3dE4DbVJY
+func_extra_expand2arg=no # Function EXPAND
+ ###
+ ###<select expand('abcd',6)
+ ###> execute failed: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 '('abcd',6)' at line 1
+func_extra_field=yes # Function FIELD
+ ###
+ ###<select field('IBM','NCA','ICL','SUN','IBM','DIGITAL')
+ ###>4
+func_extra_fixed=no # Function FIXED
+ ###
+ ###<select fixed(222.6666,10,2)
+ ###> execute failed: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 '(222.6666,10,2)' at line 1
+func_extra_float=no # Function FLOAT
+ ###
+ ###<select float(6666.66,4)
+ ###> execute failed: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 'float(6666.66,4)' at line 1
+func_extra_format=yes # Function FORMAT
+ ###
+ ###<select format(1234.5555,2)
+ ###>1,234.56
+func_extra_from_days=yes # Function FROM_DAYS
+ ###
+ ###<select from_days(729024) from crash_me_d
+ ###>1996-01-01
+func_extra_from_unixtime=yes # Function FROM_UNIXTIME
+ ###
+ ###<select from_unixtime(0) from crash_me_d
+ ###>1970-01-01 02:00:00
+func_extra_getdate=no # Function GETDATE
+ ###
+ ###<select getdate()
+ ###> execute failed: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
+func_extra_greatest=yes # Function GREATEST
+ ###
+ ###<select greatest('HARRY','HARRIOT','HAROLD')
+ ###>HARRY
+func_extra_hex=yes # Function HEX
+ ###
+ ###<select HEX('A')
+ ###>41
+func_extra_if=yes # Function IF
+ ###
+ ###<select if(5,6,7)
+ ###>6
+func_extra_in_num=yes # Function IN on numbers in SELECT
+ ###
+ ###<select 2 in (3,2,5,9,5,1)
+ ###>1
+func_extra_in_str=yes # Function IN on strings in SELECT
+ ###
+ ###<select 'monty' in ('david','monty','allan')
+ ###>1
+func_extra_index=no # Function INDEX
+ ###
+ ###<select index('abcdefg','cd',1,1)
+ ###> execute failed: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 'index('abcdefg','cd',1,1)' at line 1
+func_extra_initcap=no # Function INITCAP
+ ###
+ ###<select initcap('the soap')
+ ###> execute failed: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 '('the soap')' at line 1
+func_extra_instr=yes # Function LOCATE as INSTR
+ ###
+ ###<select instr('hello','ll')
+ ###>3
+func_extra_instr_oracle=no # Function INSTR (Oracle syntax)
+ ###
+ ###<select INSTR('CORPORATE FLOOR','OR',3,2)
+ ###> execute failed: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 '3,2)' at line 1
+func_extra_instrb=no # Function INSTRB
+ ###
+ ###<select INSTRB('CORPORATE FLOOR','OR',5,2)
+ ###> execute failed: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 '('CORPORATE FLOOR','OR',5,2)' at line 1
+func_extra_interval=yes # Function INTERVAL
+ ###
+ ###<select interval(55,10,20,30,40,50,60,70,80,90,100)
+ ###>5
+func_extra_last_day=yes # Function LAST_DAY
+ ###
+ ###<select last_day('1997-04-01') from crash_me_d
+ ###>1997-04-30
+func_extra_last_insert_id=yes # Function LAST_INSERT_ID
+ ###
+ ###<select last_insert_id()
+ ###>0
+func_extra_least=yes # Function LEAST
+ ###
+ ###<select least('HARRY','HARRIOT','HAROLD')
+ ###>HAROLD
+func_extra_length=error # Function LENGTH
+ ###
+ ###<select length(1)
+ ###>1
+ ###We expected '2' but got '1'
+func_extra_lengthb=no # Function LENGTHB
+ ###
+ ###<select lengthb('CANDIDE')
+ ###> execute failed: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 '('CANDIDE')' at line 1
+func_extra_lfill3arg=no # Function LFILL (3 arg)
+ ###
+ ###<select lfill('abcd','.',6)
+ ###> execute failed: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 '('abcd','.',6)' at line 1
+func_extra_like=yes # Function LIKE in SELECT
+ ###
+ ###<select 'a' like 'a%'
+ ###>1
+func_extra_like_escape=yes # Function LIKE ESCAPE in SELECT
+ ###
+ ###<select '%' like 'a%' escape 'a'
+ ###>1
+func_extra_ln=yes # Function LN
+ ###
+ ###<select ln(95)
+ ###>4.553877
+func_extra_log(m_n)=yes # Function LOG(m,n)
+ ###
+ ###<select log(10,100)
+ ###>2.000000
+func_extra_logn=no # Function LOGN
+ ###
+ ###<select logn(2)
+ ###> execute failed: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)' at line 1
+func_extra_lpad=yes # Function LPAD
+ ###
+ ###<select lpad('hi',4,'??')
+ ###>??hi
+func_extra_ltrim2arg=no # Function LTRIM (2 arg)
+ ###
+ ###<select ltrim('..abcd..','.')
+ ###> execute failed: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
+func_extra_makedate=yes # Function MAKEDATE
+ ###
+ ###<select MAKEDATE(1963,228) from crash_me_d
+ ###>1963-08-16
+func_extra_maketime=yes # Function MAKETIME
+ ###
+ ###<select MAKETIME(20,02,12)
+ ###>20:02:12
+func_extra_mapchar=no # Function MAPCHAR
+ ###
+ ###<select mapchar('Aâ')
+ ###> execute failed: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â')' at line 1
+func_extra_mdy=no # Function MDY
+ ###
+ ###<select mdy(7,1,1998) from crash_me_d
+ ###> execute failed: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 '(7,1,1998) from crash_me_d' at line 1
+func_extra_microsecond=yes # Function MICROSECOND
+ ###
+ ###<select MICROSECOND('19630816200212111111')
+ ###>110000
+func_extra_mid=yes # Function SUBSTRING as MID
+ ###
+ ###<select mid('hello',3,2)
+ ###>ll
+func_extra_months_between=no # Function MONTHS_BETWEEN
+ ###
+ ###<select months_between('1997-02-02','1997-01-01') from crash_me_d
+ ###> execute failed: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 '('1997-02-02','1997-01-01') from crash_me_d' at line 1
+func_extra_noround=no # Function NOROUND
+ ###< select noround(22.6)
+ ###> execute error: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 '(22.6)' at line 1
+func_extra_not=yes # Function NOT in SELECT
+ ###
+ ###<select not false
+ ###>1
+func_extra_not_between=yes # Function NOT BETWEEN in SELECT
+ ###
+ ###<select 5 not between 4 and 6
+ ###>0
+func_extra_not_like=yes # Function NOT LIKE in SELECT
+ ###
+ ###<select 'a' not like 'a%'
+ ###>0
+func_extra_num=no # Function NUM
+ ###
+ ###<select NUM('2123')
+ ###> execute failed: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 '('2123')' at line 1
+func_extra_odbc_convert=no # Function ODBC CONVERT
+ ###
+ ###<select convert(5,SQL_CHAR)
+ ###> execute failed: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 'SQL_CHAR)' at line 1
+func_extra_password=yes # Function PASSWORD
+ ###
+ ###<select password('hello')
+ ###>*6B4F89A54E2D27ECD7E8DA05B4AB8FD9D1D8B119
+func_extra_paste=no # Function PASTE
+ ###
+ ###<select paste('ABCDEFG',3,2,'1234')
+ ###> execute failed: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 '('ABCDEFG',3,2,'1234')' at line 1
+func_extra_patindex=no # Function PATINDEX
+ ###
+ ###<select patindex('%a%','crash')
+ ###> execute failed: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%','crash')' at line 1
+func_extra_period_add=yes # Function PERIOD_ADD
+ ###
+ ###<select period_add(9602,-12) from crash_me_d
+ ###>199502
+func_extra_period_diff=yes # Function PERIOD_DIFF
+ ###
+ ###<select period_diff(199505,199404) from crash_me_d
+ ###>13
+func_extra_pow=yes # Function POW
+ ###
+ ###<select pow(3,2)
+ ###>9.000000
+func_extra_range=no # Function RANGE
+ ###
+ ###<select range(a)
+ ###> execute failed: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)' at line 1
+func_extra_regexp=yes # Function REGEXP in SELECT
+ ###
+ ###<select 'a' regexp '^(a|b)*$'
+ ###>1
+func_extra_replace2arg=no # Function REPLACE (2 arg)
+ ###
+ ###<select replace('AbCd','bC')
+ ###> execute failed: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
+func_extra_replicate=no # Function REPLICATE
+ ###
+ ###<select replicate('a',5)
+ ###> execute failed: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',5)' at line 1
+func_extra_reverse=yes # Function REVERSE
+ ###
+ ###<select reverse('abcd')
+ ###>dcba
+func_extra_rfill3arg=no # Function RFILL (3 arg)
+ ###
+ ###<select rfill('abcd','.',6)
+ ###> execute failed: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 '('abcd','.',6)' at line 1
+func_extra_root=no # Function ROOT
+ ###
+ ###<select root(4)
+ ###> execute failed: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 '(4)' at line 1
+func_extra_round1=yes # Function ROUND(1 arg)
+ ###
+ ###<select round(5.63)
+ ###>6
+func_extra_rpad=yes # Function RPAD
+ ###
+ ###<select rpad('hi',4,'??')
+ ###>hi??
+func_extra_rpad4arg=no # Function RPAD (4 arg)
+ ###
+ ###<select rpad('abcd',2,'+-',8)
+ ###> execute failed: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 '8)' at line 1
+func_extra_rtrim2arg=no # Function RTRIM (2 arg)
+ ###
+ ###<select rtrim('..abcd..','.')
+ ###> execute failed: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
+func_extra_sec_to_time=yes # Function SEC_TO_TIME
+ ###
+ ###<select sec_to_time(5001)
+ ###>01:23:21
+func_extra_sinh=no # Function SINH
+ ###
+ ###<select sinh(1)
+ ###> execute failed: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
+func_extra_str=no # Function STR
+ ###
+ ###<select str(123.45,5,1)
+ ###> execute failed: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.45,5,1)' at line 1
+func_extra_strcmp=yes # Function STRCMP
+ ###
+ ###<select strcmp('abc','adc')
+ ###>-1
+func_extra_stuff=no # Function STUFF
+ ###
+ ###<select stuff('abc',2,3,'xyz')
+ ###> execute failed: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 '('abc',2,3,'xyz')' at line 1
+func_extra_subdate=yes # Function SUBDATE
+ ###
+ ###<select SUBDATE('2002-12-04',3) from crash_me_d
+ ###>2002-12-01
+func_extra_substr2arg=yes # Function SUBSTR (2 arg)
+ ###
+ ###<select substr('abcd',2)
+ ###>bcd
+func_extra_substr3arg=yes # Function SUBSTR (3 arg)
+ ###
+ ###<select substr('abcd',2,2)
+ ###>bc
+func_extra_substrb=no # Function SUBSTRB
+ ###
+ ###<select SUBSTRB('ABCDEFG',5,4.2)
+ ###> execute failed: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 '('ABCDEFG',5,4.2)' at line 1
+func_extra_substring_index=yes # Function SUBSTRING_INDEX
+ ###
+ ###<select substring_index('www.tcx.se','.',-2)
+ ###>tcx.se
+func_extra_subtime=yes # Function SUBTIME
+ ###
+ ###<select SUBTIME('20:02:15','00:00:03')
+ ###>20:02:12
+func_extra_sysdate=yes # Function SYSDATE
+ ###
+ ###<select sysdate()
+ ###>2004-04-06 13:49:05
+func_extra_tail=no # Function TAIL
+ ###
+ ###<select tail('ABCDEFG',3)
+ ###> execute failed: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 '('ABCDEFG',3)' at line 1
+func_extra_tanh=no # Function TANH
+ ###
+ ###<select tanh(1)
+ ###> execute failed: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
+func_extra_time=yes # Function TIME
+ ###
+ ###<select time('20:02:12')
+ ###>20:02:12
+func_extra_time_to_sec=yes # Function TIME_TO_SEC
+ ###
+ ###<select time_to_sec('01:23:21')
+ ###>5001
+func_extra_timediff=yes # Function TIMEDIFF
+ ###
+ ###<select TIMEDIFF('20:02:15','20:02:12')
+ ###>00:00:03
+func_extra_timestamp=error # Function TIMESTAMP
+ ###
+ ###<select timestamp('19630816','00200212')
+ ###>1963-08-16 20:02:12
+ ###We expected '19630816200212000000' but got '1963-08-16 20:02:12'
+func_extra_to_days=yes # Function TO_DAYS
+ ###
+ ###<select to_days('1996-01-01') from crash_me_d
+ ###>729024
+func_extra_translate=no # Function TRANSLATE
+ ###
+ ###<select translate('abc','bc','de')
+ ###> execute failed: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 '('abc','bc','de')' at line 1
+func_extra_trim1arg=yes # Function TRIM (1 arg)
+ ###
+ ###<select trim(' abcd ')
+ ###>abcd
+func_extra_trim2arg=no # Function TRIM (2 arg)
+ ###
+ ###<select trim('..abcd..','.')
+ ###> execute failed: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
+func_extra_trim_many_char=error # Function TRIM; Many char extension
+ ###
+ ###<select trim(':!' FROM ':abc!')
+ ###>:abc!
+ ###We expected 'abc' but got ':abc!'
+func_extra_trim_substring=yes # Function TRIM; Substring extension
+ ###
+ ###<select trim('cb' FROM 'abccb')
+ ###>abc
+func_extra_trunc=no # Function TRUNC
+ ###
+ ###<select trunc(18.18,-1)
+ ###> execute failed: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 '(18.18,-1)' at line 1
+func_extra_trunc1arg=no # Function TRUNC (1 arg)
+ ###
+ ###<select trunc(222.6)
+ ###> execute failed: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 '(222.6)' at line 1
+func_extra_uid=no # Function UID
+ ###
+ ###<select uid
+ ###> execute failed:Unknown column 'uid' in 'field list'
+func_extra_unix_timestamp=yes # Function UNIX_TIMESTAMP
+ ###
+ ###<select unix_timestamp()
+ ###>1081248545
+func_extra_userenv=no # Function USERENV
+ ###
+ ###<select userenv
+ ###> execute failed:Unknown column 'userenv' in 'field list'
+func_extra_value=no # Function VALUE
+ ###
+ ###<select value(NULL,'WALRUS')
+ ###> execute failed: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,'WALRUS')' at line 1
+func_extra_version=yes # Function VERSION
+ ###
+ ###<select version()
+ ###>4.1.2-alpha
+func_extra_weekday=yes # Function WEEKDAY
+ ###
+ ###<select weekday('1997-11-29') from crash_me_d
+ ###>5
+func_extra_weekofyear=yes # Function WEEKOFYEAR
+ ###
+ ###<select WEEKOFYEAR('1963-08-16') from crash_me_d
+ ###>33
+func_extra_|=yes # Function | (bitwise or)
+ ###
+ ###<select 1 | 2
+ ###>3
+func_extra_||=yes # Function OR as '||'
+ ###
+ ###<select 1=0 || 1=1
+ ###>1
+func_extra_~*=no # Function ~* (case insensitive compare)
+ ###
+ ###<select 'hi' ~* 'HI'
+ ###> execute failed: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 '~* 'HI'' at line 1
+func_odbc_abs=yes # Function ABS
+ ###
+ ###<select abs(-5)
+ ###>5
+func_odbc_acos=yes # Function ACOS
+ ###
+ ###<select acos(0)
+ ###>1.570796
+func_odbc_ascii=yes # Function ASCII
+ ###
+ ###<select ASCII('A')
+ ###>65
+func_odbc_asin=yes # Function ASIN
+ ###
+ ###<select asin(1)
+ ###>1.570796
+func_odbc_atan=yes # Function ATAN
+ ###
+ ###<select atan(1)
+ ###>0.785398
+func_odbc_atan2=yes # Function ATAN2
+ ###
+ ###<select atan2(1,0)
+ ###>1.570796
+func_odbc_ceiling=yes # Function CEILING
+ ###
+ ###<select ceiling(-4.5)
+ ###>-4
+func_odbc_char=yes # Function CHAR
+ ###
+ ###<select CHAR(65)
+ ###>A
+func_odbc_concat=yes # Function CONCAT(2 arg)
+ ###
+ ###<select concat('a','b')
+ ###>ab
+func_odbc_cos=yes # Function COS
+ ###
+ ###<select cos(0)
+ ###>1.000000
+func_odbc_cot=yes # Function COT
+ ###
+ ###<select cot(1)
+ ###>0.64209262
+func_odbc_curdate=yes # Function CURDATE
+ ###
+ ###<select curdate()
+ ###>2004-04-06
+func_odbc_curtime=yes # Function CURTIME
+ ###
+ ###<select curtime()
+ ###>13:49:04
+func_odbc_database=yes # Function DATABASE
+ ###
+ ###<select database()
+ ###>test
+func_odbc_dayname=yes # Function DAYNAME
+ ###< insert into crash_me_d values('1997-02-01')
+ ###
+ ###<select dayname(a) from crash_me_d
+ ###>Saturday
+func_odbc_dayofmonth=yes # Function DAYOFMONTH
+ ###< insert into crash_me_d values('1997-02-01')
+ ###
+ ###<select dayofmonth(a) from crash_me_d
+ ###>1
+func_odbc_dayofweek=yes # Function DAYOFWEEK
+ ###< insert into crash_me_d values('1997-02-01')
+ ###
+ ###<select dayofweek(a) from crash_me_d
+ ###>7
+func_odbc_dayofyear=yes # Function DAYOFYEAR
+ ###< insert into crash_me_d values('1997-02-01')
+ ###
+ ###<select dayofyear(a) from crash_me_d
+ ###>32
+func_odbc_degrees=yes # Function DEGREES
+ ###
+ ###<select degrees(6.283185)
+ ###>359.99998239991
+func_odbc_difference=no # Function DIFFERENCE()
+ ###
+ ###<select difference('abc','abe')
+ ###> execute failed: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 '('abc','abe')' at line 1
+ ###
+ ###<select {fn difference('abc','abe') }
+ ###> execute failed: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 '('abc','abe') }' at line 1
+func_odbc_exp=yes # Function EXP
+ ###
+ ###<select exp(1.0)
+ ###>2.718282
+func_odbc_floor=yes # Function FLOOR
+ ###
+ ###<select floor(2.5)
+ ###>2
+func_odbc_fn_left=yes # Function ODBC syntax LEFT & RIGHT
+ ###
+ ###<select { fn LEFT( { fn RIGHT('abcd',2) },1) }
+ ###>c
+func_odbc_hour=yes # Function HOUR
+ ###< insert into crash_me_t values(20:08:16)
+ ###
+ ###<select hour('12:13:14')
+ ###>12
+func_odbc_hour_time=yes # Function ANSI HOUR
+ ###< insert into crash_me_t values(20:08:16)
+ ###
+ ###<select hour(TIME '12:13:14')
+ ###>12
+func_odbc_ifnull=yes # Function IFNULL
+ ###
+ ###<select ifnull(2,3)
+ ###>2
+func_odbc_insert=yes # Function INSERT
+ ###
+ ###<select insert('abcd',2,2,'ef')
+ ###>aefd
+func_odbc_lcase=yes # Function LCASE
+ ###
+ ###<select lcase('ABC')
+ ###>abc
+func_odbc_left=yes # Function LEFT
+ ###
+ ###<select left('abcd',2)
+ ###>ab
+func_odbc_length=yes # Function REAL LENGTH
+ ###
+ ###<select length('abcd ')
+ ###>5
+func_odbc_length_without_space=error # Function ODBC LENGTH
+ ###
+ ###<select length('abcd ')
+ ###>5
+ ###We expected '4' but got '5'
+ ###
+ ###<select {fn length('abcd ') }
+ ###>5
+ ###We expected '4' but got '5'
+func_odbc_locate_2=yes # Function LOCATE(2 arg)
+ ###
+ ###<select locate('bcd','abcd')
+ ###>2
+func_odbc_locate_3=yes # Function LOCATE(3 arg)
+ ###
+ ###<select locate('bcd','abcd',3)
+ ###>0
+func_odbc_log=yes # Function LOG
+ ###
+ ###<select log(2)
+ ###>0.693147
+func_odbc_log10=yes # Function LOG10
+ ###
+ ###<select log10(10)
+ ###>1.000000
+func_odbc_ltrim=yes # Function LTRIM
+ ###
+ ###<select ltrim(' abcd')
+ ###>abcd
+func_odbc_minute=yes # Function MINUTE
+ ###< insert into crash_me_t values(20:08:16)
+ ###
+ ###<select minute('12:13:14')
+ ###>13
+func_odbc_mod=yes # Function MOD
+ ###
+ ###<select mod(11,7)
+ ###>4
+func_odbc_month=yes # Function MONTH
+ ###< insert into crash_me_d values('1997-02-01')
+ ###
+ ###<select month(a) from crash_me_d
+ ###>2
+func_odbc_monthname=yes # Function MONTHNAME
+ ###< insert into crash_me_d values('1997-02-01')
+ ###
+ ###<select monthname(a) from crash_me_d
+ ###>February
+func_odbc_now=yes # Function NOW
+ ###
+ ###<select now()
+ ###>2004-04-06 13:49:04
+func_odbc_pi=yes # Function PI
+ ###
+ ###<select pi()
+ ###>3.141593
+func_odbc_power=yes # Function POWER
+ ###
+ ###<select power(2,4)
+ ###>16.000000
+func_odbc_quarter=yes # Function QUARTER
+ ###< insert into crash_me_d values('1997-02-01')
+ ###
+ ###<select quarter(a) from crash_me_d
+ ###>1
+func_odbc_radians=yes # Function RADIANS
+ ###
+ ###<select radians(360)
+ ###>6.2831853071796
+func_odbc_rand=yes # Function RAND
+ ###
+ ###<select rand(1)
+ ###>0.40540353712198
+func_odbc_repeat=yes # Function REPEAT
+ ###
+ ###<select repeat('ab',3)
+ ###>ababab
+func_odbc_replace=yes # Function REPLACE
+ ###
+ ###<select replace('abbaab','ab','ba')
+ ###>bababa
+func_odbc_right=yes # Function RIGHT
+ ###
+ ###<select right('abcd',2)
+ ###>cd
+func_odbc_round=yes # Function ROUND(2 arg)
+ ###
+ ###<select round(5.63,2)
+ ###>5.63
+func_odbc_rtrim=yes # Function RTRIM
+ ###
+ ###<select rtrim(' abcd ')
+ ###> abcd
+func_odbc_second=yes # Function SECOND
+ ###< insert into crash_me_t values(20:08:16)
+ ###
+ ###<select second('12:13:14')
+ ###>14
+func_odbc_sign=yes # Function SIGN
+ ###
+ ###<select sign(-5)
+ ###>-1
+func_odbc_sin=yes # Function SIN
+ ###
+ ###<select sin(1)
+ ###>0.841471
+func_odbc_soundex=yes # Function SOUNDEX
+ ###
+ ###<select soundex('hello')
+ ###>H400
+func_odbc_space=yes # Function SPACE
+ ###
+ ###<select space(5)
+ ###>
+func_odbc_sqrt=yes # Function SQRT
+ ###
+ ###<select sqrt(4)
+ ###>2.000000
+func_odbc_substring=yes # Function ODBC SUBSTRING
+ ###
+ ###<select substring('abcd',3,2)
+ ###>cd
+func_odbc_tan=yes # Function TAN
+ ###
+ ###<select tan(1)
+ ###>1.557408
+func_odbc_timestampadd=no # Function TIMESTAMPADD
+ ###
+ ###<select timestampadd(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')
+ ###> execute failed: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 '(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')' at line 1
+ ###
+ ###<select {fn timestampadd(SQL_TSI_SECOND,1,{ts '1997-01-01 00:00:00'}) }
+ ###> execute failed: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 '(SQL_TSI_SECOND,1,{ts '1997-01-01 00:00:00'}) }' at line 1
+func_odbc_timestampdiff=no # Function TIMESTAMPDIFF
+ ###
+ ###<select timestampdiff(SQL_TSI_SECOND,'1997-01-01 00:00:02', '1997-01-01 00:00:01')
+ ###> execute failed: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 '(SQL_TSI_SECOND,'1997-01-01 00:00:02', '1997-01-01 00:00:01')'
+ ###
+ ###<select {fn timestampdiff(SQL_TSI_SECOND,{ts '1997-01-01 00:00:02'}, {ts '1997-01-01 00:00:01'}) }
+ ###> execute failed: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 '(SQL_TSI_SECOND,{ts '1997-01-01 00:00:02'}, {ts '1997-01-01 00:
+func_odbc_truncate=yes # Function TRUNCATE
+ ###
+ ###<select truncate(18.18,-1)
+ ###>10
+func_odbc_ucase=yes # Function UCASE
+ ###
+ ###<select ucase('abc')
+ ###>ABC
+func_odbc_user()=yes # Function USER()
+ ###
+ ###<select user()
+ ###>monty@localhost
+func_odbc_week=USA # WEEK
+ ###<select week('1997-02-01')
+ ###>4
+ ###We expected '5' but got '4'
+func_odbc_year=yes # Function YEAR
+ ###< insert into crash_me_d values('1997-02-01')
+ ###
+ ###<select year(a) from crash_me_d
+ ###>1997
+func_sql_+=yes # Function +, -, * and /
+ ###
+ ###<select 5*3-4/2+1
+ ###>14.00
+func_sql_bit_length=yes # Function BIT_LENGTH
+ ###
+ ###<select bit_length('abc')
+ ###>24
+func_sql_cast=yes # Function CAST
+ ###
+ ###<select CAST(1 as CHAR)
+ ###>1
+func_sql_char_length=error # Function CHAR_LENGTH
+ ###
+ ###<select char_length(b) from crash_me
+ ###>1
+ ###We expected '10' but got '1'
+func_sql_char_length(constant)=yes # Function CHAR_LENGTH(constant)
+ ###
+ ###<select char_length('abcd')
+ ###>4
+func_sql_character_length=yes # Function CHARACTER_LENGTH
+ ###
+ ###<select character_length('abcd')
+ ###>4
+func_sql_coalesce=yes # Function COALESCE
+ ###
+ ###<select coalesce(NULL,'bcd','qwe')
+ ###>bcd
+func_sql_concat_as_||=error # Function concatenation with ||
+ ###
+ ###<select 'abc' || 'def'
+ ###>0
+ ###We expected 'abcdef' but got '0'
+func_sql_current_date=yes # Function CURRENT_DATE
+ ###
+ ###<select current_date
+ ###>2004-04-06
+func_sql_current_time=yes # Function CURRENT_TIME
+ ###
+ ###<select current_time
+ ###>13:49:04
+func_sql_current_timestamp=yes # Function CURRENT_TIMESTAMP
+ ###
+ ###<select current_timestamp
+ ###>2004-04-06 13:49:04
+func_sql_current_user=yes # CURRENT_USER
+ ###< select CURRENT_USER
+ ###> OK
+func_sql_extract_sql=yes # Function EXTRACT
+ ###
+ ###<select extract(minute from timestamp '2000-02-23 18:43:12.987')
+ ###>43
+func_sql_localtime=yes # Function LOCALTIME
+ ###
+ ###<select localtime
+ ###>2004-04-06 13:49:04
+func_sql_localtimestamp=yes # Function LOCALTIMESTAMP
+ ###
+ ###<select localtimestamp
+ ###>2004-04-06 13:49:04
+func_sql_lower=yes # Function LOWER
+ ###
+ ###<select LOWER('ABC')
+ ###>abc
+func_sql_nullif_num=yes # Function NULLIF with numbers
+ ###
+ ###<select NULLIF(NULLIF(1,2),1)
+ ###>
+func_sql_nullif_string=yes # Function NULLIF with strings
+ ###
+ ###<select NULLIF(NULLIF('first','second'),'first')
+ ###>
+func_sql_octet_length=yes # Function OCTET_LENGTH
+ ###
+ ###<select octet_length('abc')
+ ###>3
+func_sql_position=yes # Function POSITION
+ ###
+ ###<select position('ll' in 'hello')
+ ###>3
+func_sql_searched_case=yes # Function searched CASE
+ ###
+ ###<select case when 1 > 2 then 'false' when 2 > 1 then 'true' end
+ ###>true
+func_sql_session_user=with_parenthesis # SESSION_USER
+ ###< select SESSION_USER
+ ###> execute error:Unknown column 'SESSION_USER' in 'field list'
+ ###
+ ###< select SESSION_USER()
+ ###> OK
+func_sql_simple_case=yes # Function simple CASE
+ ###
+ ###<select case 2 when 1 then 'false' when 2 then 'true' end
+ ###>true
+func_sql_substring=yes # Function ANSI SQL SUBSTRING
+ ###
+ ###<select substring('abcd' from 2 for 2)
+ ###>bc
+func_sql_system_user=with_parenthesis # SYSTEM_USER
+ ###< select SYSTEM_USER
+ ###> execute error:Unknown column 'SYSTEM_USER' in 'field list'
+ ###
+ ###< select SYSTEM_USER()
+ ###> OK
+func_sql_trim=yes # Function TRIM
+ ###
+ ###<select trim(trailing from trim(LEADING FROM ' abc '))
+ ###>abc
+func_sql_upper=yes # Function UPPER
+ ###
+ ###<select UPPER('abc')
+ ###>ABC
+func_sql_user=with_parenthesis # USER
+ ###< select USER
+ ###> execute error:Unknown column 'USER' in 'field list'
+ ###
+ ###< select USER()
+ ###> OK
+func_where_between=yes # Function BETWEEN
+ ###
+ ###<select a from crash_me where 5 between 4 and 6
+ ###>1
+func_where_eq_all=yes # Function = ALL
+ ###
+ ###<select a from crash_me where b =all (select b from crash_me)
+ ###>1
+func_where_eq_any=yes # Function = ANY
+ ###
+ ###<select a from crash_me where b =any (select b from crash_me)
+ ###>1
+func_where_eq_some=yes # Function = SOME
+ ###
+ ###<select a from crash_me where b =some (select b from crash_me)
+ ###>1
+func_where_exists=yes # Function EXISTS
+ ###
+ ###<select a from crash_me where exists (select * from crash_me)
+ ###>1
+func_where_in_num=yes # Function IN on numbers
+ ###
+ ###<select a from crash_me where 2 in (3,2,5,9,5,1)
+ ###>1
+func_where_like=yes # Function LIKE
+ ###
+ ###<select a from crash_me where b like 'a%'
+ ###>1
+func_where_like_escape=yes # Function LIKE ESCAPE
+ ###
+ ###<select a from crash_me where b like '%' escape 'a'
+ ###>1
+func_where_match=no # Function MATCH
+ ###
+ ###<select a from crash_me where 1 match (select a from crash_me)
+ ###> execute failed: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 'match (select a from crash_me)' at line 1
+func_where_match_unique=no # Function MATCH UNIQUE
+ ###
+ ###<select a from crash_me where 1 match unique (select a from crash_me)
+ ###> execute failed: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 'match unique (select a from crash_me)' at line 1
+func_where_matches=no # Function MATCHES
+ ###
+ ###<select a from crash_me where b matcjhes 'a*'
+ ###> execute failed: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 'matcjhes 'a*'' at line 1
+func_where_not_between=yes # Function NOT BETWEEN
+ ###
+ ###<select a from crash_me where 7 not between 4 and 6
+ ###>1
+func_where_not_exists=yes # Function NOT EXISTS
+ ###
+ ###<select a from crash_me where not exists (select * from crash_me where a = 2)
+ ###>1
+func_where_not_like=yes # Function NOT LIKE
+ ###
+ ###<select a from crash_me where b not like 'b%'
+ ###>1
+func_where_not_unique=no # Function NOT UNIQUE
+ ###
+ ###<select a from crash_me where not unique (select * from crash_me where a = 2)
+ ###> execute failed: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 'unique (select * from crash_me where a = 2)' at line 1
+func_where_unique=no # Function UNIQUE
+ ###
+ ###<select a from crash_me where unique (select * from crash_me)
+ ###> execute failed: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 'unique (select * from crash_me)' at line 1
+functions=yes # Functions
+ ###< select 1+1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+group_by=yes # Group by
+ ###< select a from crash_me group by a
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+group_by_alias=yes # Group by alias
+ ###< select a as ab from crash_me group by ab
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+group_by_null=yes # Group on column with null values
+ ###< create table crash_q (s char(10))
+ ###> OK
+ ###< insert into crash_q values(null)
+ ###> OK
+ ###< insert into crash_q values(null)
+ ###> OK
+ ###
+ ###<select count(*),s from crash_q group by s
+ ###>2
+ ###
+ ###< drop table crash_q
+ ###> OK
+group_by_position=yes # Group by position
+ ###< select a from crash_me group by 1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+group_distinct_functions=yes # Group functions with distinct
+ ###< select count(distinct a) from crash_me
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+group_func_extra_bit_and=yes # Group function BIT_AND
+ ###
+ ###<select bit_and(a),a from crash_me group by a
+ ###>1
+group_func_extra_bit_or=yes # Group function BIT_OR
+ ###
+ ###<select bit_or(a),a from crash_me group by a
+ ###>1
+group_func_extra_count_distinct_list=yes # Group function COUNT(DISTINCT expr,expr,...)
+ ###
+ ###<select count(distinct a,b),a from crash_me group by a
+ ###>1
+group_func_extra_std=yes # Group function STD
+ ###
+ ###<select std(a),a from crash_me group by a
+ ###>0.0000
+group_func_extra_stddev=yes # Group function STDDEV
+ ###
+ ###<select stddev(a),a from crash_me group by a
+ ###>0.0000
+group_func_extra_variance=yes # Group function VARIANCE
+ ###
+ ###<select variance(a),a from crash_me group by a
+ ###>0.0000
+group_func_sql_any=no # Group function ANY
+ ###
+ ###<select any(a),a from crash_me group by a
+ ###> execute failed: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),a from crash_me group by a' at line 1
+group_func_sql_avg=yes # Group function AVG
+ ###
+ ###<select avg(a),a from crash_me group by a
+ ###>1.0000
+group_func_sql_count_*=yes # Group function COUNT (*)
+ ###
+ ###<select count(*),a from crash_me group by a
+ ###>1
+group_func_sql_count_column=yes # Group function COUNT column name
+ ###
+ ###<select count(a),a from crash_me group by a
+ ###>1
+group_func_sql_count_distinct=yes # Group function COUNT(DISTINCT expr)
+ ###
+ ###<select count(distinct a),a from crash_me group by a
+ ###>1
+group_func_sql_every=no # Group function EVERY
+ ###
+ ###<select every(a),a from crash_me group by a
+ ###> execute failed: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),a from crash_me group by a' at line 1
+group_func_sql_max=yes # Group function MAX on numbers
+ ###
+ ###<select max(a),a from crash_me group by a
+ ###>1
+group_func_sql_max_str=yes # Group function MAX on strings
+ ###
+ ###<select max(b),a from crash_me group by a
+ ###>a
+group_func_sql_min=yes # Group function MIN on numbers
+ ###
+ ###<select min(a),a from crash_me group by a
+ ###>1
+group_func_sql_min_str=yes # Group function MIN on strings
+ ###
+ ###<select min(b),a from crash_me group by a
+ ###>a
+group_func_sql_some=no # Group function SOME
+ ###
+ ###<select some(a),a from crash_me group by a
+ ###> execute failed: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),a from crash_me group by a' at line 1
+group_func_sql_sum=yes # Group function SUM
+ ###
+ ###<select sum(a),a from crash_me group by a
+ ###>1
+group_functions=yes # Group functions
+ ###< select count(*) from crash_me
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+group_many_distinct_functions=yes # Group functions with several distinct
+ ###< select count(distinct a), count(distinct b) from crash_me
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+group_on_unused=yes # Group on unused column
+ ###< select count(*) from crash_me group by a
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+has_true_false=yes # TRUE and FALSE
+ ###< select (1=1)=true
+ ###> OK
+having=yes # Having
+ ###<select a from crash_me group by a having a > 0
+ ###>1
+ ###
+ ###<select a from crash_me group by a having a < 0
+ ###> didn't return any result:
+having_with_alias=yes # Having on alias
+ ###< select a as ab from crash_me group by a having ab > 0
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+having_with_group=yes # Having with group function
+ ###< select a from crash_me group by a having count(*) = 1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+hex_numbers=yes # hex numbers (0x41)
+ ###< select 0x41
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+hex_strings=yes # hex strings (x'1ace')
+ ###< select x'1ace'
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+ignore_end_space=yes # Ignore end space in compare
+ ###
+ ###<select b from crash_me where b = 'a '
+ ###>a
+index_in_create=yes # index in create table
+ ###< create table crash_q (q integer not null,index (q))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+index_namespace=yes # different namespace for index
+ ###< create index crash_me on crash_me (b)
+ ###> OK
+ ###< drop index crash_me on crash_me
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+index_parts=yes # index on column part (extension)
+ ###< create index crash_q on crash_me (b(5))
+ ###> OK
+ ###< drop index crash_q on crash_me
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+inner_join=yes # inner join
+ ###< select crash_me.a from crash_me inner join crash_me2 ON crash_me.a=crash_me2.a
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+insert_default_values=no # INSERT DEFAULT VALUES
+ ###< create table crash_me_q (a int)
+ ###> OK
+ ###< insert into crash_me_q DEFAULT VALUES
+ ###> execute error: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 VALUES' at line 1
+ ###< drop table crash_me_q
+ ###> OK
+ ###
+ ###As far as some queries didnt return OK, result is NO
+insert_empty_string=yes # insert empty string
+ ###< create table crash_q (a char(10) not null,b char(10))
+ ###> OK
+ ###< insert into crash_q values ('','')
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+insert_multi_value=yes # INSERT with Value lists
+ ###< create table crash_q (s char(10))
+ ###> OK
+ ###< insert into crash_q values ('a'),('b')
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+insert_select=yes # insert INTO ... SELECT ...
+ ###< create table crash_q (a int)
+ ###> OK
+ ###< insert into crash_q (a) SELECT crash_me.a from crash_me
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+insert_with_default=yes # INSERT with DEFAULT
+ ###< create table crash_me_q (a int)
+ ###> OK
+ ###< insert into crash_me_q (a) values (DEFAULT)
+ ###> OK
+ ###< drop table crash_me_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+insert_with_empty_value_list=no # INSERT with empty value list
+ ###< create table crash_me_q (a int)
+ ###> OK
+ ###< insert into crash_me_q (a) values ()
+ ###> execute error:Column count doesn't match value count at row 1
+ ###< drop table crash_me_q
+ ###> OK
+ ###
+ ###As far as some queries didnt return OK, result is NO
+insert_with_set=yes # INSERT with set syntax
+ ###< create table crash_q (a integer)
+ ###> OK
+ ###< insert into crash_q SET a=1
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+intersect=no # intersect
+ ###< select * from crash_me intersect select * from crash_me3
+ ###> execute error: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 crash_me3' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+intersect_all=no # intersect all
+ ###< select * from crash_me intersect all select * from crash_me3
+ ###> execute error: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 'all select * from crash_me3' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+intersect_all_incompat=no # intersect all (incompatible lists)
+ ###< select * from crash_me intersect all select * from crash_me2
+ ###> execute error: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 'all select * from crash_me2' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+intersect_incompat=no # intersect (incompatible lists)
+ ###< select * from crash_me intersect select * from crash_me2
+ ###> execute error: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 crash_me2' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+join_tables=61 # tables in join
+ ###We are trying (example with N=5):
+ ###select crash_me.a,t0.a,t1.a,t2.a,t3.a,t4.a from crash_me,crash_me t0,crash_me t1,crash_me t2,crash_me t3,crash_me t4
+ ### 32:OK 48:OK 56:OK 60:OK 62:FAIL 61:FAIL
+left_outer_join=yes # left outer join
+ ###< select crash_me.a from crash_me left join crash_me2 ON crash_me.a=crash_me2.a
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+left_outer_join_using=yes # left outer join using
+ ###< select c1 from crash_me left join crash_me2 using (a)
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+length_of_varchar_field=actual length # CHARACTER_LENGTH(varchar_field)
+ ###< CREATE TABLE crash_me1 (S1 VARCHAR(100))
+ ###> OK
+ ###< INSERT INTO crash_me1 VALUES ('X')
+ ###> OK
+ ###
+ ###< SELECT CHARACTER_LENGTH(S1) FROM crash_me1
+ ### > 1
+ ###< drop table crash_me1
+ ###> OK
+like_with_column=yes # column LIKE column
+ ###< create table crash_q (a char(10),b char(10))
+ ###> OK
+ ###< insert into crash_q values('abc','abc')
+ ###> OK
+ ###< select * from crash_q where a like b
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+like_with_number=yes # LIKE on numbers
+ ###< create table crash_q (a int,b int)
+ ###> OK
+ ###< insert into crash_q values(10,10)
+ ###> OK
+ ###< select * from crash_q where a like '10'
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+lock_tables=yes # lock table
+ ###< lock table crash_me READ
+ ###> OK
+ ###< unlock tables
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+logical_value=1 # Value of logical operation (1=1)
+ ###<select (1=1)
+ ###>1
+max_big_expressions=10 # big expressions
+ ###We are trying (example with N=5):
+ ###select 0+(1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+...(8168)
+ ### 50:FAIL 10:OK 30:FAIL 14:FAIL 11:FAIL
+max_char_size=1048543 # max char() size
+ ###We are trying (example with N=5):
+ ###create table crash_q (q char(5))
+ ###insert into crash_q values ('aaaaa')
+ ###select * from crash_q
+ ### 524287:OK 786431:OK 917503:OK 983039:OK 1015807:OK 1032191:OK 1040383:OK 1044479:OK 1046527:OK 1047551:OK 1048063:OK 1048319:OK 1048447:OK 1048511:OK 1048543:OK 1048559:FAIL 1048546:FAIL 1048544:FAIL
+max_column_name=64 # column name length
+ ###We are trying (example with N=5):
+ ###create table crash_q (qaaaaa integer)
+ ###insert into crash_q (qaaaaa) values(1)
+ ###select qaaaaa from crash_q
+ ### 256:FAIL 51:OK 153:FAIL 72:FAIL 55:OK 63:OK 67:FAIL 64:FAIL
+max_columns=2599 # Columns in table
+ ###We are trying (example with N=5):
+ ###create table crash_q (a integer ,a0 integer,a1 integer,a2 integer,a3 integer,a4 integer)
+ ### 4096:FAIL 819:OK 2457:OK 3276:FAIL 2621:FAIL 2490:OK 2555:OK 2588:OK 2604:FAIL 2591:OK 2597:OK 2600:FAIL 2598:OK 2599:FAIL
+max_conditions=85660 # OR and AND in WHERE
+ ###We are trying (example with N=5):
+ ###select a from crash_me where a=1 and b='a' or a=0 and b='0' or a=1 and b='1' or a=2 and b='2' or a=3 and b='3' or a=4 and b='4'
+ ### 27592:OK 41389:OK 48287:FAIL 42769:OK 45528:FAIL 43321:FAIL 42880:FAIL 42791:OK 42835:FAIL 42800:OK 42817:OK 42826:OK 42830:OK 42832:FAIL 42831:FAIL
+max_expressions=836 # simple expressions
+ ###We are trying (example with N=5):
+ ###select 1+1+1+1+1+1
+ ### 5000:FAIL 1000:FAIL 200:OK 600:OK 800:OK 900:FAIL 820:OK 860:FAIL 828:OK 844:FAIL 831:OK 837:FAIL 832:OK 834:OK 835:OK 836:OK
+max_index=32 # max index
+ ### max_unique_index=32 ,so max_index must be same
+max_index_length=1000 # index length
+ ###We are trying (example with N=5):
+ ###create table crash_q (q0 char(5) not null,unique (q0))
+ ###insert into crash_q values('aaaaa')
+ ### 4096:FAIL 819:OK 2457:FAIL 1147:FAIL 885:OK 1016:FAIL 911:OK 963:OK 989:OK 1002:FAIL 992:OK 997:OK 999:OK 1000:OK 1001:FAIL
+max_index_name=64 # index name length
+ ###We are trying (example with N=5):
+ ###create index crash_qaaaaa on crash_me (a)
+ ### 256:FAIL 51:OK 153:FAIL 72:FAIL 55:OK 63:FAIL 57:OK 60:FAIL 58:FAIL
+max_index_part_length=255 # max index part length
+ ###We are trying (example with N=5):
+ ###create table crash_q (q char(5) not null,unique(q))
+ ###insert into crash_q (q) values ('aaaaa')
+ ###select q from crash_q
+ ### 524271:FAIL 104854:FAIL 20971:FAIL 4194:FAIL 839:FAIL 168:OK 503:FAIL 235:OK 369:FAIL 262:FAIL 241:OK 251:OK 256:FAIL 252:OK 254:OK 255:OK
+max_index_parts=16 # index parts
+ ###We are trying (example with N=5):
+ ###create table crash_q (q0 integer not null,q1 integer not null,q2 integer not null,q3 integer not null,q4 integer not nul...(1263)
+ ###insert into crash_q (q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q...(284)
+ ###select q0 from crash_q
+ ### 32:FAIL 7:OK 19:FAIL 10:OK 14:OK 16:FAIL 15:OK
+max_index_varchar_part_length=255 # index varchar part length
+ ###We are trying (example with N=5):
+ ###create table crash_q (q varchar(5) not null,unique(q))
+ ###insert into crash_q (q) values ('aaaaa')
+ ###select q from crash_q
+ ### 524271:FAIL 104854:FAIL 20971:FAIL 4194:FAIL 839:FAIL 168:OK 503:FAIL 235:OK 369:FAIL 262:FAIL 241:OK 251:OK 256:FAIL 252:OK 254:OK 255:OK
+max_row_length=65534 # max table row length (without blobs)
+ ###We are trying (example with N=5):
+ ###create table crash_q (q0 char(5) not null)
+ ###insert into crash_q values ('aaaaa')
+ ### 331372:FAIL 66275:FAIL 13255:OK 39765:OK 53020:OK 59647:OK 62961:OK 64618:OK 65446:OK 65860:FAIL 65529:OK 65694:FAIL 65562:FAIL 65536:FAIL 65531:OK 65533:OK 65534:OK 65535:FAIL
+max_row_length_with_null=65502 # table row length with nulls (without blobs)
+ ###We are trying (example with N=5):
+ ###create table crash_q (q0 char(5) )
+ ###insert into crash_q values ('aaaaa')
+ ### 65534:FAIL 13107:OK 39320:OK 52427:OK 58980:OK 62257:OK 63895:OK 64714:OK 65124:OK 65329:OK 65431:OK 65482:OK 65508:FAIL 65487:OK 65497:OK 65502:OK 65505:FAIL 65503:FAIL
+max_select_alias_name=+512 # select alias name length
+ ###We are trying (example with N=5):
+ ###select b as aaaaa from crash_me
+max_stack_expression=836 # stacked expressions
+ ###We are trying (example with N=5):
+ ###select 1+(1+(1+(1+(1+(1)))))
+ ### 1000:FAIL 200:OK 600:OK 800:OK 900:FAIL 820:OK 860:FAIL 828:OK 844:FAIL 831:OK 837:FAIL 832:OK 834:OK 835:OK 836:OK
+max_table_alias_name=+512 # table alias name length
+ ###We are trying (example with N=5):
+ ###select aaaaa.b from crash_me aaaaa
+max_table_name=64 # table name length
+ ###We are trying (example with N=5):
+ ###create table crash_qaaaaa (q integer)
+ ###insert into crash_qaaaaa values(1)
+ ###select * from crash_qaaaaa
+ ### 256:FAIL 51:OK 153:FAIL 72:FAIL 55:OK 63:FAIL 57:OK 60:FAIL 58:FAIL
+max_text_size=1048543 # max text or blob size
+ ###We are trying (example with N=5):
+ ###create table crash_q (q mediumtext)
+ ###insert into crash_q values ('aaaaa')
+ ###select * from crash_q
+ ### 524272:OK 786408:OK 917476:OK 983010:OK 1015777:OK 1032161:OK 1040353:OK 1044449:OK 1046497:OK 1047521:OK 1048033:OK 1048289:OK 1048417:OK 1048481:OK 1048513:OK 1048529:OK 1048537:OK 1048541:OK 1048543:OK 1048544:FAIL
+max_unique_index=32 # unique indexes
+ ###We are trying (example with N=5):
+ ###create table crash_q (q integer,q1 integer not null,unique (q1),q2 integer not null,unique (q2),q3 integer not null,uniq...(72)
+ ###insert into crash_q (q,q1,q2,q3,q4,q5) values (1,1,1,1,1,1)
+ ###select q from crash_q
+ ### 32:OK 48:FAIL 35:FAIL 33:FAIL
+max_varchar_size=1048543 # max varchar() size
+ ###We are trying (example with N=5):
+ ###create table crash_q (q varchar(5))
+ ###insert into crash_q values ('aaaaa')
+ ###select * from crash_q
+ ### 524287:OK 786431:OK 917503:OK 983039:OK 1015807:OK 1032191:OK 1040383:OK 1044479:OK 1046527:OK 1047551:OK 1048063:OK 1048319:OK 1048447:OK 1048511:OK 1048543:OK 1048559:FAIL 1048546:FAIL 1048544:FAIL
+minus=no # minus
+ ###< select * from crash_me minus select * from crash_me3
+ ###> execute error: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 crash_me3' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+minus_incompat=no # minus (incompatible lists)
+ ###< select * from crash_me minus select * from crash_me2
+ ###> execute error: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 crash_me2' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+minus_neg=yes # Calculate 1--1
+ ###
+ ###<select a--1 from crash_me
+ ###>2
+multi_drop=yes # many tables to drop table
+ ###< create table crash_q (a int)
+ ###> OK
+ ###< create table crash_q2 (a int)
+ ###> OK
+ ###< drop table crash_q,crash_q2
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+multi_null_in_unique=yes # null in unique index
+ ###< create table crash_q (q integer, x integer,unique (q))
+ ###> OK
+ ###< insert into crash_q(x) values(1)
+ ###> OK
+ ###< insert into crash_q(x) values(2)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+multi_strings=yes # Multiple line strings
+ ###
+ ###<select a from crash_me where b < 'a'
+ ###'b'
+ ###>1
+multi_table_delete=yes # DELETE FROM table1,table2...
+ ###< create table crash_q (a integer,b char(10))
+ ###> OK
+ ###< insert into crash_q values(1,'c')
+ ###> OK
+ ###< delete crash_q.* from crash_q,crash_me where crash_q.a=crash_me.a
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+multi_table_update=yes # Update with many tables
+ ###< create table crash_q (a integer,b char(10))
+ ###> OK
+ ###< insert into crash_q values(1,'c')
+ ###> OK
+ ###< update crash_q left join crash_me on crash_q.a=crash_me.a set crash_q.b=crash_me.b
+ ###> OK
+ ###
+ ###<select b from crash_q
+ ###>a
+ ###
+ ###< drop table crash_q
+ ###> OK
+natural_join=yes # natural join
+ ###< select * from crash_me natural join crash_me3
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+natural_join_incompat=yes # natural join (incompatible lists)
+ ###< select c1 from crash_me natural join crash_me2
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+natural_left_outer_join=yes # natural left outer join
+ ###< select c1 from crash_me natural left join crash_me2
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+no_primary_key=yes # Tables without primary key
+ ###< create table crash_me (a integer not null,b char(10) not null)
+ ###> OK
+ ###< insert into crash_me (a,b) values (1,'a')
+ ###> OK
+not_id_between=no # NOT ID BETWEEN interprets as ID NOT BETWEEN
+ ###< create table crash_me_b (i int)
+ ###> OK
+ ###< insert into crash_me_b values(2)
+ ###> OK
+ ###< insert into crash_me_b values(5)
+ ###> OK
+ ###
+ ###<select i from crash_me_b where not i between 1 and 3
+ ###> didn't return any result:
+ ###
+ ###< drop table crash_me_b
+ ###> OK
+null_concat_expr=yes # Is concat('a',NULL) = NULL
+ ###
+ ###<select concat('a',NULL)
+ ###>
+null_in_index=yes # null in index
+ ###< create table crash_q (a char(10),index (a))
+ ###> OK
+ ###< insert into crash_q values (NULL)
+ ###> OK
+ ###
+ ###<select * from crash_q
+ ###>
+ ###
+ ###< drop table crash_q
+ ###> OK
+null_in_unique=yes # null in unique index
+ ###< create table crash_q (q integer,unique (q))
+ ###> OK
+ ###< insert into crash_q (q) values(NULL)
+ ###> OK
+ ###< insert into crash_q (q) values(NULL)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+null_num_expr=yes # Is 1+NULL = NULL
+ ###
+ ###<select 1+NULL
+ ###>
+nulls_in_unique=yes # null combination in unique index
+ ###< create table crash_q (q integer,q1 integer,unique (q,q1))
+ ###> OK
+ ###< insert into crash_q (q,q1) values(1,NULL)
+ ###> OK
+ ###< insert into crash_q (q,q1) values(1,NULL)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+odbc_left_outer_join=yes # left outer join odbc style
+ ###< select crash_me.a from { oj crash_me left outer join crash_me2 ON crash_me.a=crash_me2.a }
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+operating_system=Linux 2.4.21-199-smp4G i686 # crash-me tested on
+order_by=yes # Order by
+ ###< select a from crash_me order by a
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+order_by_alias=yes # Order by alias
+ ###< select a as ab from crash_me order by ab
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+order_by_function=yes # Order by function
+ ###< select a from crash_me order by a+1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+order_by_position=yes # Order by position
+ ###< select a from crash_me order by 1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+order_on_unused=yes # Order by on unused column
+ ###< select b from crash_me order by a
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+position_of_null=first # Where is null values in sorted recordset
+ ###< insert into crash_me_n (i) values(1)
+ ###> OK
+ ###< insert into crash_me_n values(2,2)
+ ###> OK
+ ###< insert into crash_me_n values(3,3)
+ ###> OK
+ ###< insert into crash_me_n values(4,4)
+ ###> OK
+ ###< insert into crash_me_n (i) values(5)
+ ###> OK
+ ###
+ ###< select r from crash_me_n order by r
+ ###>
+ ###>
+ ###> 2
+ ###> 3
+ ###> 4
+position_of_null_desc=last # Where is null values in sorted recordset (DESC)
+ ###< select r from crash_me_n order by r desc
+ ###> 4
+ ###> 3
+ ###> 2
+ ###>
+ ###>
+primary_key_in_create=yes # primary key in create table
+ ###< create table crash_q (q integer not null,primary key (q))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+psm_functions=no # PSM functions (ANSI SQL)
+ ###< create table crash_q (a int)
+ ###> OK
+ ###< create function crash_func(in a1 int, in b1 int) returns int language sql deterministic contains sql begin return a1 * b1; end
+ ###> execute error: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 '(in a1 int, in b1 int) returns int language sql deterministic c
+ ###< insert into crash_q values(crash_func(2,4))
+ ###> execute error: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,4))' at line 1
+ ###< select a,crash_func(a,2) from crash_q
+ ###> execute error: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,2) from crash_q' at line 1
+ ###< drop function crash_func cascade
+ ###> execute error: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 'cascade' at line 1
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as some queries didnt return OK, result is NO
+psm_modules=no # PSM modules (ANSI SQL)
+ ###< create table crash_q (a int,b int)
+ ###> OK
+ ###< create module crash_m declare procedure crash_proc(in a1 int, in b1 int) language sql modifies sql data begin declare c1 int; set c1 = a1 + b1; insert into crash_q(a,b) values (a1,c1); end; declare procedure crash_proc2(INOUT a int, in b int) contains sql set a = b + 10; end module
+ ###> execute error: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 'module crash_m declare procedure crash_proc(in a1 int, in b1 in
+ ###< call crash_proc(1,10)
+ ###> execute error: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 'call crash_proc(1,10)' at line 1
+ ###< drop module crash_m cascade
+ ###> execute error: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 'module crash_m cascade' at line 1
+ ###< drop table crash_q cascade
+ ###> OK
+ ###
+ ###As far as some queries didnt return OK, result is NO
+psm_procedures=no # PSM procedures (ANSI SQL)
+ ###< create table crash_q (a int,b int)
+ ###> OK
+ ###< create procedure crash_proc(in a1 int, in b1 int) language sql modifies sql data begin declare c1 int; set c1 = a1 + b1; insert into crash_q(a,b) values (a1,c1); end
+ ###> execute error: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 'procedure crash_proc(in a1 int, in b1 int) language sql modifie
+ ###< call crash_proc(1,10)
+ ###> execute error: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 'call crash_proc(1,10)' at line 1
+ ###< drop procedure crash_proc
+ ###> execute error: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 'procedure crash_proc' at line 1
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as some queries didnt return OK, result is NO
+psm_trigger=no # Triggers (ANSI SQL)
+ ###< create table crash_q (a int ,b int)
+ ###> OK
+ ###< create trigger crash_trigger after insert on crash_q referencing new table as new_a when (localtime > time '18:00:00') begin atomic end
+ ###> execute error: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 'trigger crash_trigger after insert on crash_q referencing new t
+ ###< insert into crash_q values(1,2)
+ ###> OK
+ ###< drop trigger crash_trigger
+ ###> execute error: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 'trigger crash_trigger' at line 1
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as some queries didnt return OK, result is NO
+query_size=1048574 # query size
+quote_ident_with_"=error # " as identifier quote (ANSI SQL)
+ ###
+ ###<select "A" from crash_me
+ ###>A
+ ###We expected '1' but got 'A'
+quote_ident_with_[=no # [] as identifier quote
+ ###
+ ###<select [A] from crash_me
+ ###> execute failed: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 crash_me' at line 1
+quote_ident_with_`=yes # ` as identifier quote
+ ###
+ ###<select `A` from crash_me
+ ###>1
+quote_ident_with_dbl_"=no # Double "" in identifiers as "
+ ###< create table crash_me1 ("abc""d" integer)
+ ###> execute error: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 '"abc""d" integer)' at line 1
+ ###< drop table crash_me1
+ ###> execute error:Unknown table 'crash_me1'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+quote_with_"=yes # Allows ' and " as string markers
+ ###< select a from crash_me where b<"c"
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+recursive_subqueries=+64 # recursive subqueries
+ ###We are trying (example with N=5):
+ ###select a from crash_me where a in (select a from crash_me where a in (select a from crash_me where a in (select a from c...(82)
+remember_end_space=no # Remembers end space in char()
+ ###< create table crash_q (a char(10))
+ ###> OK
+ ###< insert into crash_q values('hello ')
+ ###> OK
+ ###
+ ###<select a from crash_q where a = 'hello '
+ ###>hello
+ ###We expected 'hello ' but got 'hello'
+ ###
+ ###< drop table crash_q
+ ###> OK
+remember_end_space_varchar=no # Remembers end space in varchar()
+ ###< create table crash_q (a varchar(10))
+ ###> OK
+ ###< insert into crash_q values('hello ')
+ ###> OK
+ ###
+ ###<select a from crash_q where a = 'hello '
+ ###>hello
+ ###We expected 'hello ' but got 'hello'
+ ###
+ ###< drop table crash_q
+ ###> OK
+rename_table=yes # rename table
+ ###< create table crash_q (a integer, b integer,c1 CHAR(10))
+ ###> OK
+ ###< rename table crash_q to crash_q1
+ ###> OK
+ ###< drop table crash_q1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+repeat_string_size=1048576 # return string size from function
+ ###We are trying (example with N=5):
+ ###select repeat('a',5)
+ ### 4000000:FAIL 800000:OK 2400000:FAIL 1120000:FAIL 864000:OK 992000:OK 1056000:FAIL 1004800:OK 1030400:OK 1043200:OK 1049600:FAIL 1044480:OK 1047040:OK 1048320:OK 1048960:FAIL 1048448:OK 1048704:FAIL 1048499:OK 1048601:FAIL 1048520:OK 1048560:OK 1048580:FAIL 1048564:OK 1048572:OK 1048576:OK 1048578:FAIL 1048577:FAIL
+reserved_word_ansi-92/99_absolute=no # Keyword ABSOLUTE
+ ###< create table crash_me10 (ABSOLUTE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_action=no # Keyword ACTION
+ ###< create table crash_me10 (ACTION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_add=yes # Keyword ADD
+ ###< create table crash_me10 (ADD int not null)
+ ###> execute error: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 'ADD int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_after=no # Keyword AFTER
+ ###< create table crash_me10 (AFTER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_alias=no # Keyword ALIAS
+ ###< create table crash_me10 (ALIAS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_all=yes # Keyword ALL
+ ###< create table crash_me10 (ALL int not null)
+ ###> execute error: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 'ALL int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_allocate=no # Keyword ALLOCATE
+ ###< create table crash_me10 (ALLOCATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_alter=yes # Keyword ALTER
+ ###< create table crash_me10 (ALTER int not null)
+ ###> execute error: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 'ALTER int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_and=yes # Keyword AND
+ ###< create table crash_me10 (AND int not null)
+ ###> execute error: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 'AND int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_any=no # Keyword ANY
+ ###< create table crash_me10 (ANY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_are=no # Keyword ARE
+ ###< create table crash_me10 (ARE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_as=yes # Keyword AS
+ ###< create table crash_me10 (AS int not null)
+ ###> execute error: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 'AS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_asc=yes # Keyword ASC
+ ###< create table crash_me10 (ASC int not null)
+ ###> execute error: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 'ASC int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_assertion=no # Keyword ASSERTION
+ ###< create table crash_me10 (ASSERTION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_at=no # Keyword AT
+ ###< create table crash_me10 (AT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_authorization=no # Keyword AUTHORIZATION
+ ###< create table crash_me10 (AUTHORIZATION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_before=yes # Keyword BEFORE
+ ###< create table crash_me10 (BEFORE int not null)
+ ###> execute error: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 'BEFORE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_begin=no # Keyword BEGIN
+ ###< create table crash_me10 (BEGIN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_bit=no # Keyword BIT
+ ###< create table crash_me10 (BIT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_boolean=no # Keyword BOOLEAN
+ ###< create table crash_me10 (BOOLEAN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_both=yes # Keyword BOTH
+ ###< create table crash_me10 (BOTH int not null)
+ ###> execute error: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 'BOTH int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_breadth=no # Keyword BREADTH
+ ###< create table crash_me10 (BREADTH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_by=yes # Keyword BY
+ ###< create table crash_me10 (BY int not null)
+ ###> execute error: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 'BY int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_call=no # Keyword CALL
+ ###< create table crash_me10 (CALL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_cascade=yes # Keyword CASCADE
+ ###< create table crash_me10 (CASCADE int not null)
+ ###> execute error: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 'CASCADE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_cascaded=no # Keyword CASCADED
+ ###< create table crash_me10 (CASCADED int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_case=yes # Keyword CASE
+ ###< create table crash_me10 (CASE int not null)
+ ###> execute error: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 'CASE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_cast=no # Keyword CAST
+ ###< create table crash_me10 (CAST int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_catalog=no # Keyword CATALOG
+ ###< create table crash_me10 (CATALOG int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_char=yes # Keyword CHAR
+ ###< create table crash_me10 (CHAR int not null)
+ ###> execute error: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 'CHAR int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_character=yes # Keyword CHARACTER
+ ###< create table crash_me10 (CHARACTER int not null)
+ ###> execute error: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 'CHARACTER int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_check=yes # Keyword CHECK
+ ###< create table crash_me10 (CHECK int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_close=no # Keyword CLOSE
+ ###< create table crash_me10 (CLOSE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_collate=yes # Keyword COLLATE
+ ###< create table crash_me10 (COLLATE int not null)
+ ###> execute error: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 'COLLATE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_collation=no # Keyword COLLATION
+ ###< create table crash_me10 (COLLATION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_column=yes # Keyword COLUMN
+ ###< create table crash_me10 (COLUMN int not null)
+ ###> execute error: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 'COLUMN int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_commit=no # Keyword COMMIT
+ ###< create table crash_me10 (COMMIT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_completion=no # Keyword COMPLETION
+ ###< create table crash_me10 (COMPLETION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_connect=no # Keyword CONNECT
+ ###< create table crash_me10 (CONNECT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_connection=no # Keyword CONNECTION
+ ###< create table crash_me10 (CONNECTION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_constraint=yes # Keyword CONSTRAINT
+ ###< create table crash_me10 (CONSTRAINT int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_constraints=no # Keyword CONSTRAINTS
+ ###< create table crash_me10 (CONSTRAINTS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_continue=no # Keyword CONTINUE
+ ###< create table crash_me10 (CONTINUE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_corresponding=no # Keyword CORRESPONDING
+ ###< create table crash_me10 (CORRESPONDING int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_create=yes # Keyword CREATE
+ ###< create table crash_me10 (CREATE int not null)
+ ###> execute error: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 'CREATE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_cross=yes # Keyword CROSS
+ ###< create table crash_me10 (CROSS int not null)
+ ###> execute error: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 'CROSS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_current=no # Keyword CURRENT
+ ###< create table crash_me10 (CURRENT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_current_date=yes # Keyword CURRENT_DATE
+ ###< create table crash_me10 (CURRENT_DATE int not null)
+ ###> execute error: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 'CURRENT_DATE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_current_time=yes # Keyword CURRENT_TIME
+ ###< create table crash_me10 (CURRENT_TIME int not null)
+ ###> execute error: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 'CURRENT_TIME int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_current_timestamp=yes # Keyword CURRENT_TIMESTAMP
+ ###< create table crash_me10 (CURRENT_TIMESTAMP int not null)
+ ###> execute error: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 'CURRENT_TIMESTAMP int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_current_user=no # Keyword CURRENT_USER
+ ###< create table crash_me10 (CURRENT_USER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_cursor=no # Keyword CURSOR
+ ###< create table crash_me10 (CURSOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_cycle=no # Keyword CYCLE
+ ###< create table crash_me10 (CYCLE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_data=no # Keyword DATA
+ ###< create table crash_me10 (DATA int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_date=no # Keyword DATE
+ ###< create table crash_me10 (DATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_day=no # Keyword DAY
+ ###< create table crash_me10 (DAY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_deallocate=no # Keyword DEALLOCATE
+ ###< create table crash_me10 (DEALLOCATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_dec=yes # Keyword DEC
+ ###< create table crash_me10 (DEC int not null)
+ ###> execute error: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 'DEC int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_decimal=yes # Keyword DECIMAL
+ ###< create table crash_me10 (DECIMAL int not null)
+ ###> execute error: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 'DECIMAL int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_declare=no # Keyword DECLARE
+ ###< create table crash_me10 (DECLARE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_default=yes # Keyword DEFAULT
+ ###< create table crash_me10 (DEFAULT int not null)
+ ###> execute error: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 int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_deferrable=no # Keyword DEFERRABLE
+ ###< create table crash_me10 (DEFERRABLE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_deferred=no # Keyword DEFERRED
+ ###< create table crash_me10 (DEFERRED int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_delete=yes # Keyword DELETE
+ ###< create table crash_me10 (DELETE int not null)
+ ###> execute error: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 'DELETE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_depth=no # Keyword DEPTH
+ ###< create table crash_me10 (DEPTH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_desc=yes # Keyword DESC
+ ###< create table crash_me10 (DESC int not null)
+ ###> execute error: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 'DESC int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_describe=yes # Keyword DESCRIBE
+ ###< create table crash_me10 (DESCRIBE int not null)
+ ###> execute error: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 'DESCRIBE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_descriptor=no # Keyword DESCRIPTOR
+ ###< create table crash_me10 (DESCRIPTOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_diagnostics=no # Keyword DIAGNOSTICS
+ ###< create table crash_me10 (DIAGNOSTICS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_dictionary=no # Keyword DICTIONARY
+ ###< create table crash_me10 (DICTIONARY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_disconnect=no # Keyword DISCONNECT
+ ###< create table crash_me10 (DISCONNECT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_distinct=yes # Keyword DISTINCT
+ ###< create table crash_me10 (DISTINCT int not null)
+ ###> execute error: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 'DISTINCT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_domain=no # Keyword DOMAIN
+ ###< create table crash_me10 (DOMAIN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_double=yes # Keyword DOUBLE
+ ###< create table crash_me10 (DOUBLE int not null)
+ ###> execute error: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 'DOUBLE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_drop=yes # Keyword DROP
+ ###< create table crash_me10 (DROP int not null)
+ ###> execute error: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 'DROP int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_each=no # Keyword EACH
+ ###< create table crash_me10 (EACH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_else=yes # Keyword ELSE
+ ###< create table crash_me10 (ELSE int not null)
+ ###> execute error: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 'ELSE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_elseif=no # Keyword ELSEIF
+ ###< create table crash_me10 (ELSEIF int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_end=no # Keyword END
+ ###< create table crash_me10 (END int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_end-exec=yes # Keyword END-EXEC
+ ###< create table crash_me10 (END-EXEC int not null)
+ ###> execute error: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 '-EXEC int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_equals=no # Keyword EQUALS
+ ###< create table crash_me10 (EQUALS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_escape=no # Keyword ESCAPE
+ ###< create table crash_me10 (ESCAPE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_except=no # Keyword EXCEPT
+ ###< create table crash_me10 (EXCEPT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_exception=no # Keyword EXCEPTION
+ ###< create table crash_me10 (EXCEPTION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_exec=no # Keyword EXEC
+ ###< create table crash_me10 (EXEC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_execute=no # Keyword EXECUTE
+ ###< create table crash_me10 (EXECUTE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_external=no # Keyword EXTERNAL
+ ###< create table crash_me10 (EXTERNAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_false=yes # Keyword FALSE
+ ###< create table crash_me10 (FALSE int not null)
+ ###> execute error: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 'FALSE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_fetch=no # Keyword FETCH
+ ###< create table crash_me10 (FETCH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_first=no # Keyword FIRST
+ ###< create table crash_me10 (FIRST int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_float=yes # Keyword FLOAT
+ ###< create table crash_me10 (FLOAT int not null)
+ ###> execute error: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 'FLOAT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_for=yes # Keyword FOR
+ ###< create table crash_me10 (FOR int not null)
+ ###> execute error: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 'FOR int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_foreign=yes # Keyword FOREIGN
+ ###< create table crash_me10 (FOREIGN int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_found=no # Keyword FOUND
+ ###< create table crash_me10 (FOUND int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_from=yes # Keyword FROM
+ ###< create table crash_me10 (FROM int not null)
+ ###> execute error: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 int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_full=no # Keyword FULL
+ ###< create table crash_me10 (FULL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_general=no # Keyword GENERAL
+ ###< create table crash_me10 (GENERAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_get=no # Keyword GET
+ ###< create table crash_me10 (GET int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_global=no # Keyword GLOBAL
+ ###< create table crash_me10 (GLOBAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_go=no # Keyword GO
+ ###< create table crash_me10 (GO int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_goto=no # Keyword GOTO
+ ###< create table crash_me10 (GOTO int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_grant=yes # Keyword GRANT
+ ###< create table crash_me10 (GRANT int not null)
+ ###> execute error: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 'GRANT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_group=yes # Keyword GROUP
+ ###< create table crash_me10 (GROUP int not null)
+ ###> execute error: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 'GROUP int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_having=yes # Keyword HAVING
+ ###< create table crash_me10 (HAVING int not null)
+ ###> execute error: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 'HAVING int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_hour=no # Keyword HOUR
+ ###< create table crash_me10 (HOUR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_identity=no # Keyword IDENTITY
+ ###< create table crash_me10 (IDENTITY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_if=yes # Keyword IF
+ ###< create table crash_me10 (IF int not null)
+ ###> execute error: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 'IF int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_ignore=yes # Keyword IGNORE
+ ###< create table crash_me10 (IGNORE int not null)
+ ###> execute error: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 'IGNORE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_immediate=no # Keyword IMMEDIATE
+ ###< create table crash_me10 (IMMEDIATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_in=yes # Keyword IN
+ ###< create table crash_me10 (IN int not null)
+ ###> execute error: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 'IN int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_indicator=no # Keyword INDICATOR
+ ###< create table crash_me10 (INDICATOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_initially=no # Keyword INITIALLY
+ ###< create table crash_me10 (INITIALLY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_inner=yes # Keyword INNER
+ ###< create table crash_me10 (INNER int not null)
+ ###> execute error: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 'INNER int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_input=no # Keyword INPUT
+ ###< create table crash_me10 (INPUT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_insert=yes # Keyword INSERT
+ ###< create table crash_me10 (INSERT int not null)
+ ###> execute error: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 'INSERT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_int=yes # Keyword INT
+ ###< create table crash_me10 (INT int not null)
+ ###> execute error: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 'INT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_integer=yes # Keyword INTEGER
+ ###< create table crash_me10 (INTEGER int not null)
+ ###> execute error: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 'INTEGER int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_intersect=no # Keyword INTERSECT
+ ###< create table crash_me10 (INTERSECT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_interval=yes # Keyword INTERVAL
+ ###< create table crash_me10 (INTERVAL int not null)
+ ###> execute error: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 'INTERVAL int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_into=yes # Keyword INTO
+ ###< create table crash_me10 (INTO int not null)
+ ###> execute error: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 'INTO int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_is=yes # Keyword IS
+ ###< create table crash_me10 (IS int not null)
+ ###> execute error: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 'IS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_isolation=no # Keyword ISOLATION
+ ###< create table crash_me10 (ISOLATION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_join=yes # Keyword JOIN
+ ###< create table crash_me10 (JOIN int not null)
+ ###> execute error: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 'JOIN int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_key=yes # Keyword KEY
+ ###< create table crash_me10 (KEY int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_language=no # Keyword LANGUAGE
+ ###< create table crash_me10 (LANGUAGE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_last=no # Keyword LAST
+ ###< create table crash_me10 (LAST int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_leading=yes # Keyword LEADING
+ ###< create table crash_me10 (LEADING int not null)
+ ###> execute error: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 'LEADING int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_leave=no # Keyword LEAVE
+ ###< create table crash_me10 (LEAVE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_left=yes # Keyword LEFT
+ ###< create table crash_me10 (LEFT int not null)
+ ###> execute error: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 'LEFT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_less=no # Keyword LESS
+ ###< create table crash_me10 (LESS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_level=no # Keyword LEVEL
+ ###< create table crash_me10 (LEVEL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_like=yes # Keyword LIKE
+ ###< create table crash_me10 (LIKE int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_limit=yes # Keyword LIMIT
+ ###< create table crash_me10 (LIMIT int not null)
+ ###> execute error: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 'LIMIT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_local=no # Keyword LOCAL
+ ###< create table crash_me10 (LOCAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_loop=no # Keyword LOOP
+ ###< create table crash_me10 (LOOP int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_match=yes # Keyword MATCH
+ ###< create table crash_me10 (MATCH int not null)
+ ###> execute error: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 'MATCH int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_minute=no # Keyword MINUTE
+ ###< create table crash_me10 (MINUTE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_modify=no # Keyword MODIFY
+ ###< create table crash_me10 (MODIFY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_module=no # Keyword MODULE
+ ###< create table crash_me10 (MODULE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_month=no # Keyword MONTH
+ ###< create table crash_me10 (MONTH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_names=no # Keyword NAMES
+ ###< create table crash_me10 (NAMES int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_national=no # Keyword NATIONAL
+ ###< create table crash_me10 (NATIONAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_natural=yes # Keyword NATURAL
+ ###< create table crash_me10 (NATURAL int not null)
+ ###> execute error: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 'NATURAL int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_nchar=no # Keyword NCHAR
+ ###< create table crash_me10 (NCHAR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_new=no # Keyword NEW
+ ###< create table crash_me10 (NEW int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_next=no # Keyword NEXT
+ ###< create table crash_me10 (NEXT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_no=no # Keyword NO
+ ###< create table crash_me10 (NO int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_none=no # Keyword NONE
+ ###< create table crash_me10 (NONE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_not=yes # Keyword NOT
+ ###< create table crash_me10 (NOT int not null)
+ ###> execute error: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 'NOT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_null=yes # Keyword NULL
+ ###< create table crash_me10 (NULL int not null)
+ ###> execute error: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 int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_numeric=yes # Keyword NUMERIC
+ ###< create table crash_me10 (NUMERIC int not null)
+ ###> execute error: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 'NUMERIC int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_object=no # Keyword OBJECT
+ ###< create table crash_me10 (OBJECT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_of=no # Keyword OF
+ ###< create table crash_me10 (OF int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_off=no # Keyword OFF
+ ###< create table crash_me10 (OFF int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_old=no # Keyword OLD
+ ###< create table crash_me10 (OLD int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_on=yes # Keyword ON
+ ###< create table crash_me10 (ON int not null)
+ ###> execute error: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 'ON int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_only=no # Keyword ONLY
+ ###< create table crash_me10 (ONLY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_open=no # Keyword OPEN
+ ###< create table crash_me10 (OPEN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_operation=no # Keyword OPERATION
+ ###< create table crash_me10 (OPERATION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_option=yes # Keyword OPTION
+ ###< create table crash_me10 (OPTION int not null)
+ ###> execute error: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 'OPTION int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_or=yes # Keyword OR
+ ###< create table crash_me10 (OR int not null)
+ ###> execute error: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 'OR int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_order=yes # Keyword ORDER
+ ###< create table crash_me10 (ORDER int not null)
+ ###> execute error: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 'ORDER int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_outer=yes # Keyword OUTER
+ ###< create table crash_me10 (OUTER int not null)
+ ###> execute error: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 'OUTER int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_output=no # Keyword OUTPUT
+ ###< create table crash_me10 (OUTPUT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_pad=no # Keyword PAD
+ ###< create table crash_me10 (PAD int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_parameters=no # Keyword PARAMETERS
+ ###< create table crash_me10 (PARAMETERS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_partial=no # Keyword PARTIAL
+ ###< create table crash_me10 (PARTIAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_precision=yes # Keyword PRECISION
+ ###< create table crash_me10 (PRECISION int not null)
+ ###> execute error: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 'PRECISION int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_preorder=no # Keyword PREORDER
+ ###< create table crash_me10 (PREORDER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_prepare=no # Keyword PREPARE
+ ###< create table crash_me10 (PREPARE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_preserve=no # Keyword PRESERVE
+ ###< create table crash_me10 (PRESERVE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_primary=yes # Keyword PRIMARY
+ ###< create table crash_me10 (PRIMARY int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_prior=no # Keyword PRIOR
+ ###< create table crash_me10 (PRIOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_privileges=yes # Keyword PRIVILEGES
+ ###< create table crash_me10 (PRIVILEGES int not null)
+ ###> execute error: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 'PRIVILEGES int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_procedure=yes # Keyword PROCEDURE
+ ###< create table crash_me10 (PROCEDURE int not null)
+ ###> execute error: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 'PROCEDURE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_public=no # Keyword PUBLIC
+ ###< create table crash_me10 (PUBLIC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_read=yes # Keyword READ
+ ###< create table crash_me10 (READ int not null)
+ ###> execute error: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 'READ int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_real=yes # Keyword REAL
+ ###< create table crash_me10 (REAL int not null)
+ ###> execute error: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 'REAL int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_recursive=no # Keyword RECURSIVE
+ ###< create table crash_me10 (RECURSIVE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_ref=no # Keyword REF
+ ###< create table crash_me10 (REF int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_references=yes # Keyword REFERENCES
+ ###< create table crash_me10 (REFERENCES int not null)
+ ###> execute error: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 'REFERENCES int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_referencing=no # Keyword REFERENCING
+ ###< create table crash_me10 (REFERENCING int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_relative=no # Keyword RELATIVE
+ ###< create table crash_me10 (RELATIVE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_resignal=no # Keyword RESIGNAL
+ ###< create table crash_me10 (RESIGNAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_restrict=yes # Keyword RESTRICT
+ ###< create table crash_me10 (RESTRICT int not null)
+ ###> execute error: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 'RESTRICT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_return=no # Keyword RETURN
+ ###< create table crash_me10 (RETURN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_returns=yes # Keyword RETURNS
+ ###< create table crash_me10 (RETURNS int not null)
+ ###> execute error: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 'RETURNS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_revoke=yes # Keyword REVOKE
+ ###< create table crash_me10 (REVOKE int not null)
+ ###> execute error: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 'REVOKE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_right=yes # Keyword RIGHT
+ ###< create table crash_me10 (RIGHT int not null)
+ ###> execute error: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 'RIGHT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_role=no # Keyword ROLE
+ ###< create table crash_me10 (ROLE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_rollback=no # Keyword ROLLBACK
+ ###< create table crash_me10 (ROLLBACK int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_routine=no # Keyword ROUTINE
+ ###< create table crash_me10 (ROUTINE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_row=no # Keyword ROW
+ ###< create table crash_me10 (ROW int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_rows=no # Keyword ROWS
+ ###< create table crash_me10 (ROWS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_savepoint=no # Keyword SAVEPOINT
+ ###< create table crash_me10 (SAVEPOINT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_schema=no # Keyword SCHEMA
+ ###< create table crash_me10 (SCHEMA int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_scroll=no # Keyword SCROLL
+ ###< create table crash_me10 (SCROLL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_search=no # Keyword SEARCH
+ ###< create table crash_me10 (SEARCH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_second=no # Keyword SECOND
+ ###< create table crash_me10 (SECOND int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_section=no # Keyword SECTION
+ ###< create table crash_me10 (SECTION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_select=yes # Keyword SELECT
+ ###< create table crash_me10 (SELECT int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_sequence=no # Keyword SEQUENCE
+ ###< create table crash_me10 (SEQUENCE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_session=no # Keyword SESSION
+ ###< create table crash_me10 (SESSION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_session_user=no # Keyword SESSION_USER
+ ###< create table crash_me10 (SESSION_USER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_set=yes # Keyword SET
+ ###< create table crash_me10 (SET int not null)
+ ###> execute error: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 'SET int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_signal=no # Keyword SIGNAL
+ ###< create table crash_me10 (SIGNAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_size=no # Keyword SIZE
+ ###< create table crash_me10 (SIZE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_smallint=yes # Keyword SMALLINT
+ ###< create table crash_me10 (SMALLINT int not null)
+ ###> execute error: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 'SMALLINT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_some=no # Keyword SOME
+ ###< create table crash_me10 (SOME int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_space=no # Keyword SPACE
+ ###< create table crash_me10 (SPACE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_sql=no # Keyword SQL
+ ###< create table crash_me10 (SQL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_sqlexception=no # Keyword SQLEXCEPTION
+ ###< create table crash_me10 (SQLEXCEPTION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_sqlstate=no # Keyword SQLSTATE
+ ###< create table crash_me10 (SQLSTATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_sqlwarning=no # Keyword SQLWARNING
+ ###< create table crash_me10 (SQLWARNING int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_structure=no # Keyword STRUCTURE
+ ###< create table crash_me10 (STRUCTURE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_system_user=no # Keyword SYSTEM_USER
+ ###< create table crash_me10 (SYSTEM_USER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_table=yes # Keyword TABLE
+ ###< create table crash_me10 (TABLE int not null)
+ ###> execute error: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 'TABLE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_temporary=no # Keyword TEMPORARY
+ ###< create table crash_me10 (TEMPORARY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_then=yes # Keyword THEN
+ ###< create table crash_me10 (THEN int not null)
+ ###> execute error: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 'THEN int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_time=no # Keyword TIME
+ ###< create table crash_me10 (TIME int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_timestamp=no # Keyword TIMESTAMP
+ ###< create table crash_me10 (TIMESTAMP int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_timezone_hour=no # Keyword TIMEZONE_HOUR
+ ###< create table crash_me10 (TIMEZONE_HOUR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_timezone_minute=no # Keyword TIMEZONE_MINUTE
+ ###< create table crash_me10 (TIMEZONE_MINUTE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_to=yes # Keyword TO
+ ###< create table crash_me10 (TO int not null)
+ ###> execute error: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 'TO int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_trailing=yes # Keyword TRAILING
+ ###< create table crash_me10 (TRAILING int not null)
+ ###> execute error: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 'TRAILING int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_transaction=no # Keyword TRANSACTION
+ ###< create table crash_me10 (TRANSACTION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_translation=no # Keyword TRANSLATION
+ ###< create table crash_me10 (TRANSLATION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_trigger=no # Keyword TRIGGER
+ ###< create table crash_me10 (TRIGGER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_true=yes # Keyword TRUE
+ ###< create table crash_me10 (TRUE int not null)
+ ###> execute error: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 'TRUE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_under=no # Keyword UNDER
+ ###< create table crash_me10 (UNDER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_union=yes # Keyword UNION
+ ###< create table crash_me10 (UNION int not null)
+ ###> execute error: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 'UNION int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_unique=yes # Keyword UNIQUE
+ ###< create table crash_me10 (UNIQUE int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_unknown=no # Keyword UNKNOWN
+ ###< create table crash_me10 (UNKNOWN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_update=yes # Keyword UPDATE
+ ###< create table crash_me10 (UPDATE int not null)
+ ###> execute error: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 'UPDATE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_usage=yes # Keyword USAGE
+ ###< create table crash_me10 (USAGE int not null)
+ ###> execute error: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 'USAGE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_user=no # Keyword USER
+ ###< create table crash_me10 (USER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_using=yes # Keyword USING
+ ###< create table crash_me10 (USING int not null)
+ ###> execute error: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 'USING int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_value=no # Keyword VALUE
+ ###< create table crash_me10 (VALUE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_values=yes # Keyword VALUES
+ ###< create table crash_me10 (VALUES int not null)
+ ###> execute error: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 'VALUES int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_varchar=yes # Keyword VARCHAR
+ ###< create table crash_me10 (VARCHAR int not null)
+ ###> execute error: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 'VARCHAR int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_variable=no # Keyword VARIABLE
+ ###< create table crash_me10 (VARIABLE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_varying=yes # Keyword VARYING
+ ###< create table crash_me10 (VARYING int not null)
+ ###> execute error: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 'VARYING int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_view=no # Keyword VIEW
+ ###< create table crash_me10 (VIEW int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_when=yes # Keyword WHEN
+ ###< create table crash_me10 (WHEN int not null)
+ ###> execute error: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 'WHEN int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_whenever=no # Keyword WHENEVER
+ ###< create table crash_me10 (WHENEVER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_where=yes # Keyword WHERE
+ ###< create table crash_me10 (WHERE int not null)
+ ###> execute error: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 int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_while=no # Keyword WHILE
+ ###< create table crash_me10 (WHILE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_with=yes # Keyword WITH
+ ###< create table crash_me10 (WITH int not null)
+ ###> execute error: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 'WITH int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_without=no # Keyword WITHOUT
+ ###< create table crash_me10 (WITHOUT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_work=no # Keyword WORK
+ ###< create table crash_me10 (WORK int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_write=yes # Keyword WRITE
+ ###< create table crash_me10 (WRITE int not null)
+ ###> execute error: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 'WRITE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_year=no # Keyword YEAR
+ ###< create table crash_me10 (YEAR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_zone=no # Keyword ZONE
+ ###< create table crash_me10 (ZONE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_async=no # Keyword ASYNC
+ ###< create table crash_me10 (ASYNC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_avg=no # Keyword AVG
+ ###< create table crash_me10 (AVG int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_between=yes # Keyword BETWEEN
+ ###< create table crash_me10 (BETWEEN int not null)
+ ###> execute error: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 'BETWEEN int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi92_bit_length=no # Keyword BIT_LENGTH
+ ###< create table crash_me10 (BIT_LENGTH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_char_length=no # Keyword CHAR_LENGTH
+ ###< create table crash_me10 (CHAR_LENGTH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_character_length=no # Keyword CHARACTER_LENGTH
+ ###< create table crash_me10 (CHARACTER_LENGTH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_coalesce=no # Keyword COALESCE
+ ###< create table crash_me10 (COALESCE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_convert=yes # Keyword CONVERT
+ ###< create table crash_me10 (CONVERT int not null)
+ ###> execute error: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 'CONVERT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi92_count=no # Keyword COUNT
+ ###< create table crash_me10 (COUNT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_exists=yes # Keyword EXISTS
+ ###< create table crash_me10 (EXISTS int not null)
+ ###> execute error: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 'EXISTS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi92_extract=no # Keyword EXTRACT
+ ###< create table crash_me10 (EXTRACT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_insensitive=no # Keyword INSENSITIVE
+ ###< create table crash_me10 (INSENSITIVE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_lower=no # Keyword LOWER
+ ###< create table crash_me10 (LOWER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_max=no # Keyword MAX
+ ###< create table crash_me10 (MAX int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_min=no # Keyword MIN
+ ###< create table crash_me10 (MIN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_nullif=no # Keyword NULLIF
+ ###< create table crash_me10 (NULLIF int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_octet_length=no # Keyword OCTET_LENGTH
+ ###< create table crash_me10 (OCTET_LENGTH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_oid=no # Keyword OID
+ ###< create table crash_me10 (OID int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_operators=no # Keyword OPERATORS
+ ###< create table crash_me10 (OPERATORS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_others=no # Keyword OTHERS
+ ###< create table crash_me10 (OTHERS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_overlaps=no # Keyword OVERLAPS
+ ###< create table crash_me10 (OVERLAPS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_pendant=no # Keyword PENDANT
+ ###< create table crash_me10 (PENDANT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_position=no # Keyword POSITION
+ ###< create table crash_me10 (POSITION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_private=no # Keyword PRIVATE
+ ###< create table crash_me10 (PRIVATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_protected=no # Keyword PROTECTED
+ ###< create table crash_me10 (PROTECTED int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_replace=yes # Keyword REPLACE
+ ###< create table crash_me10 (REPLACE int not null)
+ ###> execute error: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 'REPLACE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi92_sensitive=no # Keyword SENSITIVE
+ ###< create table crash_me10 (SENSITIVE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_similar=no # Keyword SIMILAR
+ ###< create table crash_me10 (SIMILAR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_sqlcode=no # Keyword SQLCODE
+ ###< create table crash_me10 (SQLCODE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_sqlerror=no # Keyword SQLERROR
+ ###< create table crash_me10 (SQLERROR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_substring=no # Keyword SUBSTRING
+ ###< create table crash_me10 (SUBSTRING int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_sum=no # Keyword SUM
+ ###< create table crash_me10 (SUM int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_test=no # Keyword TEST
+ ###< create table crash_me10 (TEST int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_there=no # Keyword THERE
+ ###< create table crash_me10 (THERE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_translate=no # Keyword TRANSLATE
+ ###< create table crash_me10 (TRANSLATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_trim=no # Keyword TRIM
+ ###< create table crash_me10 (TRIM int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_type=no # Keyword TYPE
+ ###< create table crash_me10 (TYPE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_upper=no # Keyword UPPER
+ ###< create table crash_me10 (UPPER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_virtual=no # Keyword VIRTUAL
+ ###< create table crash_me10 (VIRTUAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_visible=no # Keyword VISIBLE
+ ###< create table crash_me10 (VISIBLE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_wait=no # Keyword WAIT
+ ###< create table crash_me10 (WAIT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_admin=no # Keyword ADMIN
+ ###< create table crash_me10 (ADMIN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_aggregate=no # Keyword AGGREGATE
+ ###< create table crash_me10 (AGGREGATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_array=no # Keyword ARRAY
+ ###< create table crash_me10 (ARRAY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_binary=yes # Keyword BINARY
+ ###< create table crash_me10 (BINARY int not null)
+ ###> execute error: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 'BINARY int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi99_blob=yes # Keyword BLOB
+ ###< create table crash_me10 (BLOB int not null)
+ ###> execute error: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 'BLOB int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi99_class=no # Keyword CLASS
+ ###< create table crash_me10 (CLASS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_clob=no # Keyword CLOB
+ ###< create table crash_me10 (CLOB int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_condition=no # Keyword CONDITION
+ ###< create table crash_me10 (CONDITION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_constructor=no # Keyword CONSTRUCTOR
+ ###< create table crash_me10 (CONSTRUCTOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_contains=no # Keyword CONTAINS
+ ###< create table crash_me10 (CONTAINS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_cube=no # Keyword CUBE
+ ###< create table crash_me10 (CUBE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_current_path=no # Keyword CURRENT_PATH
+ ###< create table crash_me10 (CURRENT_PATH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_current_role=no # Keyword CURRENT_ROLE
+ ###< create table crash_me10 (CURRENT_ROLE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_datalink=no # Keyword DATALINK
+ ###< create table crash_me10 (DATALINK int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_deref=no # Keyword DEREF
+ ###< create table crash_me10 (DEREF int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_destroy=no # Keyword DESTROY
+ ###< create table crash_me10 (DESTROY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_destructor=no # Keyword DESTRUCTOR
+ ###< create table crash_me10 (DESTRUCTOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_deterministic=no # Keyword DETERMINISTIC
+ ###< create table crash_me10 (DETERMINISTIC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_do=no # Keyword DO
+ ###< create table crash_me10 (DO int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_dynamic=no # Keyword DYNAMIC
+ ###< create table crash_me10 (DYNAMIC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_every=no # Keyword EVERY
+ ###< create table crash_me10 (EVERY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_exit=no # Keyword EXIT
+ ###< create table crash_me10 (EXIT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_expand=no # Keyword EXPAND
+ ###< create table crash_me10 (EXPAND int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_expanding=no # Keyword EXPANDING
+ ###< create table crash_me10 (EXPANDING int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_free=no # Keyword FREE
+ ###< create table crash_me10 (FREE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_function=no # Keyword FUNCTION
+ ###< create table crash_me10 (FUNCTION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_grouping=no # Keyword GROUPING
+ ###< create table crash_me10 (GROUPING int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_handler=no # Keyword HANDLER
+ ###< create table crash_me10 (HANDLER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_hast=no # Keyword HAST
+ ###< create table crash_me10 (HAST int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_host=no # Keyword HOST
+ ###< create table crash_me10 (HOST int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_initialize=no # Keyword INITIALIZE
+ ###< create table crash_me10 (INITIALIZE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_inout=no # Keyword INOUT
+ ###< create table crash_me10 (INOUT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_iterate=no # Keyword ITERATE
+ ###< create table crash_me10 (ITERATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_large=no # Keyword LARGE
+ ###< create table crash_me10 (LARGE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_lateral=no # Keyword LATERAL
+ ###< create table crash_me10 (LATERAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_localtime=yes # Keyword LOCALTIME
+ ###< create table crash_me10 (LOCALTIME int not null)
+ ###> execute error: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 'LOCALTIME int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi99_localtimestamp=yes # Keyword LOCALTIMESTAMP
+ ###< create table crash_me10 (LOCALTIMESTAMP int not null)
+ ###> execute error: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 'LOCALTIMESTAMP int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi99_locator=no # Keyword LOCATOR
+ ###< create table crash_me10 (LOCATOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_meets=no # Keyword MEETS
+ ###< create table crash_me10 (MEETS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_modifies=no # Keyword MODIFIES
+ ###< create table crash_me10 (MODIFIES int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_nclob=no # Keyword NCLOB
+ ###< create table crash_me10 (NCLOB int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_normalize=no # Keyword NORMALIZE
+ ###< create table crash_me10 (NORMALIZE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_ordinality=no # Keyword ORDINALITY
+ ###< create table crash_me10 (ORDINALITY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_out=no # Keyword OUT
+ ###< create table crash_me10 (OUT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_parameter=no # Keyword PARAMETER
+ ###< create table crash_me10 (PARAMETER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_path=no # Keyword PATH
+ ###< create table crash_me10 (PATH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_period=no # Keyword PERIOD
+ ###< create table crash_me10 (PERIOD int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_postfix=no # Keyword POSTFIX
+ ###< create table crash_me10 (POSTFIX int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_precedes=no # Keyword PRECEDES
+ ###< create table crash_me10 (PRECEDES int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_prefix=no # Keyword PREFIX
+ ###< create table crash_me10 (PREFIX int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_reads=no # Keyword READS
+ ###< create table crash_me10 (READS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_redo=no # Keyword REDO
+ ###< create table crash_me10 (REDO int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_repeat=no # Keyword REPEAT
+ ###< create table crash_me10 (REPEAT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_result=no # Keyword RESULT
+ ###< create table crash_me10 (RESULT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_rollup=no # Keyword ROLLUP
+ ###< create table crash_me10 (ROLLUP int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_sets=no # Keyword SETS
+ ###< create table crash_me10 (SETS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_specific=no # Keyword SPECIFIC
+ ###< create table crash_me10 (SPECIFIC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_specifictype=no # Keyword SPECIFICTYPE
+ ###< create table crash_me10 (SPECIFICTYPE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_start=no # Keyword START
+ ###< create table crash_me10 (START int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_state=no # Keyword STATE
+ ###< create table crash_me10 (STATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_static=no # Keyword STATIC
+ ###< create table crash_me10 (STATIC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_succeeds=no # Keyword SUCCEEDS
+ ###< create table crash_me10 (SUCCEEDS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_terminate=no # Keyword TERMINATE
+ ###< create table crash_me10 (TERMINATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_than=no # Keyword THAN
+ ###< create table crash_me10 (THAN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_treat=no # Keyword TREAT
+ ###< create table crash_me10 (TREAT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_undo=no # Keyword UNDO
+ ###< create table crash_me10 (UNDO int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_until=no # Keyword UNTIL
+ ###< create table crash_me10 (UNTIL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_access=no # Keyword ACCESS
+ ###< create table crash_me10 (ACCESS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_analyze=yes # Keyword ANALYZE
+ ###< create table crash_me10 (ANALYZE int not null)
+ ###> execute error: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 'ANALYZE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_audit=no # Keyword AUDIT
+ ###< create table crash_me10 (AUDIT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_auto_increment=no # Keyword AUTO_INCREMENT
+ ###< create table crash_me10 (AUTO_INCREMENT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_backup=no # Keyword BACKUP
+ ###< create table crash_me10 (BACKUP int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_bdb=no # Keyword BDB
+ ###< create table crash_me10 (BDB int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_berkeleydb=no # Keyword BERKELEYDB
+ ###< create table crash_me10 (BERKELEYDB int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_bigint=yes # Keyword BIGINT
+ ###< create table crash_me10 (BIGINT int not null)
+ ###> execute error: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 'BIGINT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_break=no # Keyword BREAK
+ ###< create table crash_me10 (BREAK int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_browse=no # Keyword BROWSE
+ ###< create table crash_me10 (BROWSE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_btree=no # Keyword BTREE
+ ###< create table crash_me10 (BTREE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_bulk=no # Keyword BULK
+ ###< create table crash_me10 (BULK int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_change=yes # Keyword CHANGE
+ ###< create table crash_me10 (CHANGE int not null)
+ ###> execute error: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 'CHANGE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_checkpoint=no # Keyword CHECKPOINT
+ ###< create table crash_me10 (CHECKPOINT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_cluster=no # Keyword CLUSTER
+ ###< create table crash_me10 (CLUSTER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_clustered=no # Keyword CLUSTERED
+ ###< create table crash_me10 (CLUSTERED int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_columns=yes # Keyword COLUMNS
+ ###< create table crash_me10 (COLUMNS int not null)
+ ###> execute error: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 'COLUMNS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_comment=no # Keyword COMMENT
+ ###< create table crash_me10 (COMMENT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_compress=no # Keyword COMPRESS
+ ###< create table crash_me10 (COMPRESS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_compute=no # Keyword COMPUTE
+ ###< create table crash_me10 (COMPUTE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_containstable=no # Keyword CONTAINSTABLE
+ ###< create table crash_me10 (CONTAINSTABLE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_database=yes # Keyword DATABASE
+ ###< create table crash_me10 (DATABASE int not null)
+ ###> execute error: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 'DATABASE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_databases=yes # Keyword DATABASES
+ ###< create table crash_me10 (DATABASES int not null)
+ ###> execute error: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 'DATABASES int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_day_hour=yes # Keyword DAY_HOUR
+ ###< create table crash_me10 (DAY_HOUR int not null)
+ ###> execute error: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 'DAY_HOUR int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_day_minute=yes # Keyword DAY_MINUTE
+ ###< create table crash_me10 (DAY_MINUTE int not null)
+ ###> execute error: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 'DAY_MINUTE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_day_second=yes # Keyword DAY_SECOND
+ ###< create table crash_me10 (DAY_SECOND int not null)
+ ###> execute error: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 'DAY_SECOND int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_dbcc=no # Keyword DBCC
+ ###< create table crash_me10 (DBCC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_delayed=yes # Keyword DELAYED
+ ###< create table crash_me10 (DELAYED int not null)
+ ###> execute error: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 'DELAYED int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_deny=no # Keyword DENY
+ ###< create table crash_me10 (DENY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_disk=no # Keyword DISK
+ ###< create table crash_me10 (DISK int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_distinctrow=yes # Keyword DISTINCTROW
+ ###< create table crash_me10 (DISTINCTROW int not null)
+ ###> execute error: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 'DISTINCTROW int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_distributed=no # Keyword DISTRIBUTED
+ ###< create table crash_me10 (DISTRIBUTED int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_dummy=no # Keyword DUMMY
+ ###< create table crash_me10 (DUMMY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_dump=no # Keyword DUMP
+ ###< create table crash_me10 (DUMP int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_enclosed=yes # Keyword ENCLOSED
+ ###< create table crash_me10 (ENCLOSED int not null)
+ ###> execute error: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 'ENCLOSED int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_errlvl=no # Keyword ERRLVL
+ ###< create table crash_me10 (ERRLVL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_errors=no # Keyword ERRORS
+ ###< create table crash_me10 (ERRORS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_escaped=yes # Keyword ESCAPED
+ ###< create table crash_me10 (ESCAPED int not null)
+ ###> execute error: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 'ESCAPED int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_exclusive=no # Keyword EXCLUSIVE
+ ###< create table crash_me10 (EXCLUSIVE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_explain=yes # Keyword EXPLAIN
+ ###< create table crash_me10 (EXPLAIN int not null)
+ ###> execute error: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 'EXPLAIN int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_fields=yes # Keyword FIELDS
+ ###< create table crash_me10 (FIELDS int not null)
+ ###> execute error: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 'FIELDS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_file=no # Keyword FILE
+ ###< create table crash_me10 (FILE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_fillfactor=no # Keyword FILLFACTOR
+ ###< create table crash_me10 (FILLFACTOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_freetext=no # Keyword FREETEXT
+ ###< create table crash_me10 (FREETEXT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_freetexttable=no # Keyword FREETEXTTABLE
+ ###< create table crash_me10 (FREETEXTTABLE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_fulltext=yes # Keyword FULLTEXT
+ ###< create table crash_me10 (FULLTEXT int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_geometry=no # Keyword GEOMETRY
+ ###< create table crash_me10 (GEOMETRY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_hash=no # Keyword HASH
+ ###< create table crash_me10 (HASH int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_high_priority=yes # Keyword HIGH_PRIORITY
+ ###< create table crash_me10 (HIGH_PRIORITY int not null)
+ ###> execute error: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 'HIGH_PRIORITY int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_holdlock=no # Keyword HOLDLOCK
+ ###< create table crash_me10 (HOLDLOCK int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_hour_minute=yes # Keyword HOUR_MINUTE
+ ###< create table crash_me10 (HOUR_MINUTE int not null)
+ ###> execute error: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 'HOUR_MINUTE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_hour_second=yes # Keyword HOUR_SECOND
+ ###< create table crash_me10 (HOUR_SECOND int not null)
+ ###> execute error: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 'HOUR_SECOND int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_identified=no # Keyword IDENTIFIED
+ ###< create table crash_me10 (IDENTIFIED int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_identity_insert=no # Keyword IDENTITY_INSERT
+ ###< create table crash_me10 (IDENTITY_INSERT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_identitycol=no # Keyword IDENTITYCOL
+ ###< create table crash_me10 (IDENTITYCOL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_increment=no # Keyword INCREMENT
+ ###< create table crash_me10 (INCREMENT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_index=yes # Keyword INDEX
+ ###< create table crash_me10 (INDEX int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_infile=yes # Keyword INFILE
+ ###< create table crash_me10 (INFILE int not null)
+ ###> execute error: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 'INFILE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_initial=no # Keyword INITIAL
+ ###< create table crash_me10 (INITIAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_innodb=no # Keyword INNODB
+ ###< create table crash_me10 (INNODB int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_keys=yes # Keyword KEYS
+ ###< create table crash_me10 (KEYS int not null)
+ ###> execute error: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 'KEYS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_kill=yes # Keyword KILL
+ ###< create table crash_me10 (KILL int not null)
+ ###> execute error: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 'KILL int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_lineno=no # Keyword LINENO
+ ###< create table crash_me10 (LINENO int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_lines=yes # Keyword LINES
+ ###< create table crash_me10 (LINES int not null)
+ ###> execute error: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 'LINES int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_load=yes # Keyword LOAD
+ ###< create table crash_me10 (LOAD int not null)
+ ###> execute error: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 'LOAD int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_lock=yes # Keyword LOCK
+ ###< create table crash_me10 (LOCK int not null)
+ ###> execute error: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 'LOCK int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_long=yes # Keyword LONG
+ ###< create table crash_me10 (LONG int not null)
+ ###> execute error: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 'LONG int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_longblob=yes # Keyword LONGBLOB
+ ###< create table crash_me10 (LONGBLOB int not null)
+ ###> execute error: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 'LONGBLOB int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_longtext=yes # Keyword LONGTEXT
+ ###< create table crash_me10 (LONGTEXT int not null)
+ ###> execute error: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 'LONGTEXT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_low_priority=yes # Keyword LOW_PRIORITY
+ ###< create table crash_me10 (LOW_PRIORITY int not null)
+ ###> execute error: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 'LOW_PRIORITY int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_master_server_id=no # Keyword MASTER_SERVER_ID
+ ###< create table crash_me10 (MASTER_SERVER_ID int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_maxextents=no # Keyword MAXEXTENTS
+ ###< create table crash_me10 (MAXEXTENTS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_mediumblob=yes # Keyword MEDIUMBLOB
+ ###< create table crash_me10 (MEDIUMBLOB int not null)
+ ###> execute error: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 'MEDIUMBLOB int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_mediumint=yes # Keyword MEDIUMINT
+ ###< create table crash_me10 (MEDIUMINT int not null)
+ ###> execute error: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 'MEDIUMINT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_mediumtext=yes # Keyword MEDIUMTEXT
+ ###< create table crash_me10 (MEDIUMTEXT int not null)
+ ###> execute error: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 'MEDIUMTEXT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_middleint=yes # Keyword MIDDLEINT
+ ###< create table crash_me10 (MIDDLEINT int not null)
+ ###> execute error: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 'MIDDLEINT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_minus=no # Keyword MINUS
+ ###< create table crash_me10 (MINUS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_minute_second=yes # Keyword MINUTE_SECOND
+ ###< create table crash_me10 (MINUTE_SECOND int not null)
+ ###> execute error: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 'MINUTE_SECOND int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_mlslabel=no # Keyword MLSLABEL
+ ###< create table crash_me10 (MLSLABEL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_mode=no # Keyword MODE
+ ###< create table crash_me10 (MODE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_mrg_myisam=no # Keyword MRG_MYISAM
+ ###< create table crash_me10 (MRG_MYISAM int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_noaudit=no # Keyword NOAUDIT
+ ###< create table crash_me10 (NOAUDIT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_nocheck=no # Keyword NOCHECK
+ ###< create table crash_me10 (NOCHECK int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_nocompress=no # Keyword NOCOMPRESS
+ ###< create table crash_me10 (NOCOMPRESS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_nonclustered=no # Keyword NONCLUSTERED
+ ###< create table crash_me10 (NONCLUSTERED int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_nowait=no # Keyword NOWAIT
+ ###< create table crash_me10 (NOWAIT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_number=no # Keyword NUMBER
+ ###< create table crash_me10 (NUMBER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_offline=no # Keyword OFFLINE
+ ###< create table crash_me10 (OFFLINE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_offsets=no # Keyword OFFSETS
+ ###< create table crash_me10 (OFFSETS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_online=no # Keyword ONLINE
+ ###< create table crash_me10 (ONLINE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_opendatasource=no # Keyword OPENDATASOURCE
+ ###< create table crash_me10 (OPENDATASOURCE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_openquery=no # Keyword OPENQUERY
+ ###< create table crash_me10 (OPENQUERY int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_openrowset=no # Keyword OPENROWSET
+ ###< create table crash_me10 (OPENROWSET int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_openxml=no # Keyword OPENXML
+ ###< create table crash_me10 (OPENXML int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_optimize=yes # Keyword OPTIMIZE
+ ###< create table crash_me10 (OPTIMIZE int not null)
+ ###> execute error: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 'OPTIMIZE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_optionally=yes # Keyword OPTIONALLY
+ ###< create table crash_me10 (OPTIONALLY int not null)
+ ###> execute error: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 'OPTIONALLY int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_outfile=yes # Keyword OUTFILE
+ ###< create table crash_me10 (OUTFILE int not null)
+ ###> execute error: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 'OUTFILE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_over=no # Keyword OVER
+ ###< create table crash_me10 (OVER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_pctfree=no # Keyword PCTFREE
+ ###< create table crash_me10 (PCTFREE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_percent=no # Keyword PERCENT
+ ###< create table crash_me10 (PERCENT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_plan=no # Keyword PLAN
+ ###< create table crash_me10 (PLAN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_print=no # Keyword PRINT
+ ###< create table crash_me10 (PRINT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_proc=no # Keyword PROC
+ ###< create table crash_me10 (PROC int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_purge=yes # Keyword PURGE
+ ###< create table crash_me10 (PURGE int not null)
+ ###> execute error: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 'PURGE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_raiserror=no # Keyword RAISERROR
+ ###< create table crash_me10 (RAISERROR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_raw=no # Keyword RAW
+ ###< create table crash_me10 (RAW int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_readtext=no # Keyword READTEXT
+ ###< create table crash_me10 (READTEXT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_reconfigure=no # Keyword RECONFIGURE
+ ###< create table crash_me10 (RECONFIGURE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_regexp=yes # Keyword REGEXP
+ ###< create table crash_me10 (REGEXP int not null)
+ ###> execute error: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 'REGEXP int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_rename=yes # Keyword RENAME
+ ###< create table crash_me10 (RENAME int not null)
+ ###> execute error: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 'RENAME int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_replication=no # Keyword REPLICATION
+ ###< create table crash_me10 (REPLICATION int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_require=yes # Keyword REQUIRE
+ ###< create table crash_me10 (REQUIRE int not null)
+ ###> execute error: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 'REQUIRE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_resource=no # Keyword RESOURCE
+ ###< create table crash_me10 (RESOURCE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_restore=no # Keyword RESTORE
+ ###< create table crash_me10 (RESTORE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_rlike=yes # Keyword RLIKE
+ ###< create table crash_me10 (RLIKE int not null)
+ ###> execute error: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 'RLIKE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_rowcount=no # Keyword ROWCOUNT
+ ###< create table crash_me10 (ROWCOUNT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_rowguidcol=no # Keyword ROWGUIDCOL
+ ###< create table crash_me10 (ROWGUIDCOL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_rowid=no # Keyword ROWID
+ ###< create table crash_me10 (ROWID int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_rownum=no # Keyword ROWNUM
+ ###< create table crash_me10 (ROWNUM int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_rtree=no # Keyword RTREE
+ ###< create table crash_me10 (RTREE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_rule=no # Keyword RULE
+ ###< create table crash_me10 (RULE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_save=no # Keyword SAVE
+ ###< create table crash_me10 (SAVE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_setuser=no # Keyword SETUSER
+ ###< create table crash_me10 (SETUSER int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_share=no # Keyword SHARE
+ ###< create table crash_me10 (SHARE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_show=yes # Keyword SHOW
+ ###< create table crash_me10 (SHOW int not null)
+ ###> execute error: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 'SHOW int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_shutdown=no # Keyword SHUTDOWN
+ ###< create table crash_me10 (SHUTDOWN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_soname=yes # Keyword SONAME
+ ###< create table crash_me10 (SONAME int not null)
+ ###> execute error: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 'SONAME int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_spatial=yes # Keyword SPATIAL
+ ###< create table crash_me10 (SPATIAL int not null)
+ ###> execute error: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 'int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_sql_big_result=yes # Keyword SQL_BIG_RESULT
+ ###< create table crash_me10 (SQL_BIG_RESULT int not null)
+ ###> execute error: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 'SQL_BIG_RESULT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_sql_calc_found_rows=yes # Keyword SQL_CALC_FOUND_ROWS
+ ###< create table crash_me10 (SQL_CALC_FOUND_ROWS int not null)
+ ###> execute error: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 'SQL_CALC_FOUND_ROWS int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_sql_small_result=yes # Keyword SQL_SMALL_RESULT
+ ###< create table crash_me10 (SQL_SMALL_RESULT int not null)
+ ###> execute error: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 'SQL_SMALL_RESULT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_ssl=yes # Keyword SSL
+ ###< create table crash_me10 (SSL int not null)
+ ###> execute error: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 'SSL int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_starting=yes # Keyword STARTING
+ ###< create table crash_me10 (STARTING int not null)
+ ###> execute error: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 'STARTING int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_statistics=no # Keyword STATISTICS
+ ###< create table crash_me10 (STATISTICS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_straight_join=yes # Keyword STRAIGHT_JOIN
+ ###< create table crash_me10 (STRAIGHT_JOIN int not null)
+ ###> execute error: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 'STRAIGHT_JOIN int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_striped=no # Keyword STRIPED
+ ###< create table crash_me10 (STRIPED int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_successful=no # Keyword SUCCESSFUL
+ ###< create table crash_me10 (SUCCESSFUL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_synonym=no # Keyword SYNONYM
+ ###< create table crash_me10 (SYNONYM int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_sysdate=no # Keyword SYSDATE
+ ###< create table crash_me10 (SYSDATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_tables=yes # Keyword TABLES
+ ###< create table crash_me10 (TABLES int not null)
+ ###> execute error: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 'TABLES int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_terminated=yes # Keyword TERMINATED
+ ###< create table crash_me10 (TERMINATED int not null)
+ ###> execute error: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 'TERMINATED int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_textsize=no # Keyword TEXTSIZE
+ ###< create table crash_me10 (TEXTSIZE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_tinyblob=yes # Keyword TINYBLOB
+ ###< create table crash_me10 (TINYBLOB int not null)
+ ###> execute error: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 'TINYBLOB int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_tinyint=yes # Keyword TINYINT
+ ###< create table crash_me10 (TINYINT int not null)
+ ###> execute error: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 'TINYINT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_tinytext=yes # Keyword TINYTEXT
+ ###< create table crash_me10 (TINYTEXT int not null)
+ ###> execute error: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 'TINYTEXT int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_top=no # Keyword TOP
+ ###< create table crash_me10 (TOP int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_tran=no # Keyword TRAN
+ ###< create table crash_me10 (TRAN int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_truncate=no # Keyword TRUNCATE
+ ###< create table crash_me10 (TRUNCATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_tsequal=no # Keyword TSEQUAL
+ ###< create table crash_me10 (TSEQUAL int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_types=no # Keyword TYPES
+ ###< create table crash_me10 (TYPES int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_uid=no # Keyword UID
+ ###< create table crash_me10 (UID int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_unlock=yes # Keyword UNLOCK
+ ###< create table crash_me10 (UNLOCK int not null)
+ ###> execute error: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 'UNLOCK int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_unsigned=yes # Keyword UNSIGNED
+ ###< create table crash_me10 (UNSIGNED int not null)
+ ###> execute error: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 'UNSIGNED int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_updatetext=no # Keyword UPDATETEXT
+ ###< create table crash_me10 (UPDATETEXT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_use=yes # Keyword USE
+ ###< create table crash_me10 (USE int not null)
+ ###> execute error: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 'USE int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_user_resources=no # Keyword USER_RESOURCES
+ ###< create table crash_me10 (USER_RESOURCES int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_validate=no # Keyword VALIDATE
+ ###< create table crash_me10 (VALIDATE int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_varbinary=yes # Keyword VARBINARY
+ ###< create table crash_me10 (VARBINARY int not null)
+ ###> execute error: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 'VARBINARY int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_varchar2=no # Keyword VARCHAR2
+ ###< create table crash_me10 (VARCHAR2 int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_waitfor=no # Keyword WAITFOR
+ ###< create table crash_me10 (WAITFOR int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_warnings=no # Keyword WARNINGS
+ ###< create table crash_me10 (WARNINGS int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_writetext=no # Keyword WRITETEXT
+ ###< create table crash_me10 (WRITETEXT int not null)
+ ###> OK
+ ###< drop table crash_me10
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is NO
+reserved_word_extra_xor=yes # Keyword XOR
+ ###< create table crash_me10 (XOR int not null)
+ ###> execute error: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 'XOR int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_year_month=yes # Keyword YEAR_MONTH
+ ###< create table crash_me10 (YEAR_MONTH int not null)
+ ###> execute error: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 'YEAR_MONTH int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_zerofill=yes # Keyword ZEROFILL
+ ###< create table crash_me10 (ZEROFILL int not null)
+ ###> execute error: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 'ZEROFILL int not null)' at line 1
+ ###< drop table crash_me10
+ ###> execute error:Unknown table 'crash_me10'
+ ###
+ ###As far as some queries didnt return OK, result is YES
+right_outer_join=yes # right outer join
+ ###< select crash_me.a from crash_me right join crash_me2 ON crash_me.a=crash_me2.a
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+rollback_metadata=no # rollback_metadata
+ ###< create table crash_q (a integer not null)
+ ###> OK
+ ###
+ ###< insert into crash_q values (1)
+ ###> OK
+rowid=auto_increment # Type for row id
+ ###< create table crash_q (a rowid)
+ ###> execute error: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 'rowid)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###< create table crash_q (a int not null auto_increment, primary key(a))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+safe_decimal_arithmetic=no # safe decimal arithmetic
+ ###< create table crash_me_a (a decimal(10,2),b decimal(10,2))
+ ###> OK
+ ###
+ ###< insert into crash_me_a (a,b) values (11.4,18.9)
+ ###> OK
+ ###
+ ###<select count(*) from crash_me_a where a+b=30.3
+ ###>0
+ ###We expected '1' but got '0'
+select_constants=yes # Select constants
+ ###< select 1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+select_limit=with LIMIT # LIMIT number of rows
+ ###< select * from crash_me limit 1
+ ###> OK
+select_limit2=yes # SELECT with LIMIT #,#
+ ###< select * from crash_me limit 1,1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+select_limit3=yes # SELECT with LIMIT # OFFSET #
+ ###< select * from crash_me limit 1 offset 1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+select_string_size=1048565 # constant string size in SELECT
+ ###We are trying (example with N=5):
+ ###select 'aaaaa'
+select_table_update=yes # Update with sub select
+ ###< create table crash_q (a integer,b char(10))
+ ###> OK
+ ###< insert into crash_q values(1,'c')
+ ###> OK
+ ###< update crash_q set b= (select b from crash_me where crash_q.a = crash_me.a)
+ ###> OK
+ ###
+ ###<select b from crash_q
+ ###>a
+ ###
+ ###< drop table crash_q
+ ###> OK
+select_without_from=yes # SELECT without FROM
+ ###< select 1
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+server_version=MySQL 4.1.2 alpha # server version
+simple_joins=yes # ANSI SQL simple joins
+ ###< select crash_me.a from crash_me, crash_me t0
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+sorted_group_by=yes # Group by always sorted
+ ###< create table crash_me_t1 (a int not null, b int not null)
+ ###> OK
+ ###< insert into crash_me_t1 values (1,1)
+ ###> OK
+ ###< insert into crash_me_t1 values (1,2)
+ ###> OK
+ ###< insert into crash_me_t1 values (3,1)
+ ###> OK
+ ###< insert into crash_me_t1 values (3,2)
+ ###> OK
+ ###< insert into crash_me_t1 values (2,2)
+ ###> OK
+ ###< insert into crash_me_t1 values (2,1)
+ ###> OK
+ ###< create table crash_me_t2 (a int not null, b int not null)
+ ###> OK
+ ###< create index crash_me_t2_ind on crash_me_t2 (a)
+ ###> OK
+ ###< insert into crash_me_t2 values (1,3)
+ ###> OK
+ ###< insert into crash_me_t2 values (3,1)
+ ###> OK
+ ###< insert into crash_me_t2 values (2,2)
+ ###> OK
+ ###< insert into crash_me_t2 values (1,1)
+ ###> OK
+ ###
+ ###< select crash_me_t1.a,crash_me_t2.b from crash_me_t1,crash_me_t2 where crash_me_t1.a=crash_me_t2.a group by crash_me_t1.a,crash_me_t2.b
+ ### > 1,1
+ ### > 1,3
+ ### > 2,2
+ ### > 3,1
+ ###
+ ### Check recordset:
+ ### 1,1 expected: 1,1
+ ### 1,3 expected: 1,3
+ ### 2,2 expected: 2,2
+ ### 3,1 expected: 3,1
+ ### Recordset corresponds with template
+ ###< drop table crash_me_t1
+ ###> OK
+ ###< drop table crash_me_t2
+ ###> OK
+storage_of_float=round # Storage of float values
+ ###< create table crash_q (q1 float(4,1))
+ ###> OK
+ ###< insert into crash_q values(1.14)
+ ###> OK
+ ###
+ ###<select q1 from crash_q
+ ###>1.1
+ ###
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###< create table crash_q (q1 float(4,1))
+ ###> OK
+ ###< insert into crash_q values(1.16)
+ ###> OK
+ ###
+ ###<select q1 from crash_q
+ ###>1.2
+ ###We expected '1.1' but got '1.2'
+ ###
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###< create table crash_q (q1 float(4,1))
+ ###> OK
+ ###< insert into crash_q values(1.14)
+ ###> OK
+ ###
+ ###<select q1 from crash_q
+ ###>1.1
+ ###
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###< create table crash_q (q1 float(4,1))
+ ###> OK
+ ###< insert into crash_q values(1.16)
+ ###> OK
+ ###
+ ###<select q1 from crash_q
+ ###>1.2
+ ###
+ ###< drop table crash_q
+ ###> OK
+subqueries=yes # subqueries
+ ###< select a from crash_me where crash_me.a in (select max(a) from crash_me)
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+table_alias=yes # Table alias
+ ###< select b.a from crash_me as b
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+table_name_case=no # case independent table names
+ ###< create table crash_q (q integer)
+ ###> OK
+ ###< drop table CRASH_Q
+ ###> execute error:Unknown table 'CRASH_Q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+table_wildcard=yes # Select table_name.*
+ ###< select crash_me.* from crash_me
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+temporary_table=yes # temporary tables
+ ###< create temporary table crash_q (q integer not null)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+time_format_EUR=error # Supports HH.MM.SS (EUR) time format
+ ###< insert into crash_me_t(a) values ('20.08.16')
+ ###> OK
+ ###
+ ###<select a from crash_me_t
+ ###>00:00:20
+ ###We expected '20:08:16' but got '00:00:20'
+ ###
+ ###< delete from crash_me_t
+ ###> OK
+time_format_HHHHMMSS=yes # Supports HHHHmmSS time format
+ ###< insert into crash_me_t(a) values ('00200816')
+ ###> OK
+ ###
+ ###<select a from crash_me_t
+ ###>20:08:16
+ ###
+ ###< delete from crash_me_t
+ ###> OK
+time_format_ISO=yes # Supports HH:MM:SS (ISO) time format
+ ###< insert into crash_me_t(a) values ('20:08:16')
+ ###> OK
+ ###
+ ###<select a from crash_me_t
+ ###>20:08:16
+ ###
+ ###< delete from crash_me_t
+ ###> OK
+time_format_USA=error # Supports HH:MM:SS (AM|PM) time format
+ ###< insert into crash_me_t(a) values ('08:08:16 PM')
+ ###> OK
+ ###
+ ###<select a from crash_me_t
+ ###>08:08:16
+ ###We expected '20:08:16' but got '08:08:16'
+ ###
+ ###< delete from crash_me_t
+ ###> OK
+time_format_inresult=iso # Time format in result
+ ###< insert into crash_me_t values(CURRENT_TIME)
+ ###> OK
+ ###
+ ###< select a from crash_me_t
+ ###> 13:49:05
+ ###< delete from crash_me_t
+ ###> OK
+transactions=yes # transactions
+ ###<select * from crash_q
+ ###>1
+ ###We expected '' but got '1'
+truncate_table=yes # truncate
+ ###< create table crash_q (a integer, b integer,c1 CHAR(10))
+ ###> OK
+ ###< truncate table crash_q
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_abstime=no # Type abstime
+ ###< create table crash_q (q abstime)
+ ###> execute error: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 'abstime)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_bfile=no # Type bfile
+ ###< create table crash_q (q bfile)
+ ###> execute error: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 'bfile)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_blob=yes # Type blob
+ ###< create table crash_q (q blob)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_bool=yes # Type bool
+ ###< create table crash_q (q bool)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_box=no # Type box
+ ###< create table crash_q (q box)
+ ###> execute error: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 'box)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_byte=no # Type byte
+ ###< create table crash_q (q byte)
+ ###> execute error: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 'byte)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_char(1_arg)_binary=yes # Type char(1 arg) binary
+ ###< create table crash_q (q char(10) binary)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_cidr=no # Type cidr
+ ###< create table crash_q (q cidr)
+ ###> execute error: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 'cidr)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_circle=no # Type circle
+ ###< create table crash_q (q circle)
+ ###> execute error: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 'circle)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_clob=no # Type clob
+ ###< create table crash_q (q clob)
+ ###> execute error: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 'clob)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_datetime=yes # Type datetime
+ ###< create table crash_q (q datetime)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_double=yes # Type double
+ ###< create table crash_q (q double)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_enum(1_arg)=yes # Type enum(1 arg)
+ ###< create table crash_q (q enum('red'))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_float(2_arg)=yes # Type float(2 arg)
+ ###< create table crash_q (q float(6,2))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_float4=yes # Type float4
+ ###< create table crash_q (q float4)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_float8=yes # Type float8
+ ###< create table crash_q (q float8)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_image=no # Type image
+ ###< create table crash_q (q image)
+ ###> execute error: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 'image)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_inet=no # Type inet
+ ###< create table crash_q (q inet)
+ ###> execute error: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 'inet)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_int(1_arg)_zerofill=yes # Type int(1 arg) zerofill
+ ###< create table crash_q (q int(5) zerofill)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_int1=yes # Type int1
+ ###< create table crash_q (q int1)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_int2=yes # Type int2
+ ###< create table crash_q (q int2)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_int3=yes # Type int3
+ ###< create table crash_q (q int3)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_int4=yes # Type int4
+ ###< create table crash_q (q int4)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_int8=yes # Type int8
+ ###< create table crash_q (q int8)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_int_auto_increment=yes # Type int not null auto_increment
+ ###< create table crash_q (q int not null auto_increment,unique(q))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_int_identity=no # Type int not null identity
+ ###< create table crash_q (q int not null identity,unique(q))
+ ###> execute error: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 'identity,unique(q))' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_int_unsigned=yes # Type int unsigned
+ ###< create table crash_q (q int unsigned)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_interval=no # Type interval
+ ###< create table crash_q (q interval)
+ ###> execute error: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 'interval)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_line=no # Type line
+ ###< create table crash_q (q line)
+ ###> execute error: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 'line)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_long=yes # Type long
+ ###< create table crash_q (q long)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_long_raw=no # Type long raw
+ ###< create table crash_q (q long raw)
+ ###> execute error: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 'raw)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_long_varbinary=yes # Type long varbinary
+ ###< create table crash_q (q long varbinary)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_long_varchar(1_arg)=no # Type long varchar(1 arg)
+ ###< create table crash_q (q long varchar(1))
+ ###> execute error: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
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_lseg=no # Type lseg
+ ###< create table crash_q (q lseg)
+ ###> execute error: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 'lseg)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_macaddr=no # Type macaddr
+ ###< create table crash_q (q macaddr)
+ ###> execute error: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 'macaddr)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_mediumint=yes # Type mediumint
+ ###< create table crash_q (q mediumint)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_mediumtext=yes # Type mediumtext
+ ###< create table crash_q (q mediumtext)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_middleint=yes # Type middleint
+ ###< create table crash_q (q middleint)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_mlslabel=no # Type mlslabel
+ ###< create table crash_q (q mlslabel)
+ ###> execute error: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 'mlslabel)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_money=no # Type money
+ ###< create table crash_q (q money)
+ ###> execute error: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 'money)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_nclob=no # Type nclob
+ ###< create table crash_q (q nclob)
+ ###> execute error: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 'nclob)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_number=no # Type number
+ ###< create table crash_q (q number)
+ ###> execute error: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 'number)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_number(1_arg)=no # Type number(1 arg)
+ ###< create table crash_q (q number(9))
+ ###> execute error: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 'number(9))' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_number(2_arg)=no # Type number(2 arg)
+ ###< create table crash_q (q number(9,2))
+ ###> execute error: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 'number(9,2))' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_nvarchar2(1_arg)=no # Type nvarchar2(1 arg)
+ ###< create table crash_q (q nvarchar2(16))
+ ###> execute error: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 'nvarchar2(16))' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_path=no # Type path
+ ###< create table crash_q (q path)
+ ###> execute error: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 'path)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_point=yes # Type point
+ ###< create table crash_q (q point)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_polygon=yes # Type polygon
+ ###< create table crash_q (q polygon)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_raw(1_arg)=no # Type raw(1 arg)
+ ###< create table crash_q (q raw(16))
+ ###> execute error: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 'raw(16))' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_reltime=no # Type reltime
+ ###< create table crash_q (q reltime)
+ ###> execute error: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 'reltime)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_rowid=no # Type rowid
+ ###< create table crash_q (q rowid)
+ ###> execute error: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 'rowid)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_serial=yes # Type serial
+ ###< create table crash_q (q serial)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_set(1_arg)=yes # Type set(1 arg)
+ ###< create table crash_q (q set('red'))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_smalldatetime=no # Type smalldatetime
+ ###< create table crash_q (q smalldatetime)
+ ###> execute error: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 'smalldatetime)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_smallfloat=no # Type smallfloat
+ ###< create table crash_q (q smallfloat)
+ ###> execute error: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 'smallfloat)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_smallmoney=no # Type smallmoney
+ ###< create table crash_q (q smallmoney)
+ ###> execute error: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 'smallmoney)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_text=yes # Type text
+ ###< create table crash_q (q text)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_text(1_arg)=yes # Type text(1 arg)
+ ###< create table crash_q (q text(10))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_extra_timespan=no # Type timespan
+ ###< create table crash_q (q timespan)
+ ###> execute error: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 'timespan)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_uint=no # Type uint
+ ###< create table crash_q (q uint)
+ ###> execute error: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 'uint)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_varchar2(1_arg)=no # Type varchar2(1 arg)
+ ###< create table crash_q (q varchar2(257))
+ ###> execute error: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 'varchar2(257))' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_extra_year=yes # Type year
+ ###< create table crash_q (q year)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_odbc_bigint=yes # Type bigint
+ ###< create table crash_q (q bigint)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_odbc_binary(1_arg)=yes # Type binary(1 arg)
+ ###< create table crash_q (q binary(1))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_odbc_datetime=yes # Type datetime
+ ###< create table crash_q (q datetime)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_odbc_tinyint=yes # Type tinyint
+ ###< create table crash_q (q tinyint)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_odbc_varbinary(1_arg)=yes # Type varbinary(1 arg)
+ ###< create table crash_q (q varbinary(1))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_bit=yes # Type bit
+ ###< create table crash_q (q bit)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_bit(1_arg)=yes # Type bit(1 arg)
+ ###< create table crash_q (q bit(2))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_bit_varying(1_arg)=no # Type bit varying(1 arg)
+ ###< create table crash_q (q bit varying(2))
+ ###> execute error: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 'varying(2))' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_boolean=yes # Type boolean
+ ###< create table crash_q (q boolean)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_char(1_arg)=yes # Type char(1 arg)
+ ###< create table crash_q (q char(1))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_char_varying(1_arg)=yes # Type char varying(1 arg)
+ ###< create table crash_q (q char varying(1))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_character(1_arg)=yes # Type character(1 arg)
+ ###< create table crash_q (q character(1))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_character_varying(1_arg)=yes # Type character varying(1 arg)
+ ###< create table crash_q (q character varying(1))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_date=yes # Type date
+ ###< create table crash_q (q date)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_dec(2_arg)=yes # Type dec(2 arg)
+ ###< create table crash_q (q dec(6,2))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_decimal(2_arg)=yes # Type decimal(2 arg)
+ ###< create table crash_q (q decimal(6,2))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_double_precision=yes # Type double precision
+ ###< create table crash_q (q double precision)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_float=yes # Type float
+ ###< create table crash_q (q float)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_float(1_arg)=yes # Type float(1 arg)
+ ###< create table crash_q (q float(8))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_int=yes # Type int
+ ###< create table crash_q (q int)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_integer=yes # Type integer
+ ###< create table crash_q (q integer)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_interval_day=no # Type interval day
+ ###< create table crash_q (q interval day)
+ ###> execute error: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 'interval day)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_day_to_hour=no # Type interval day to hour
+ ###< create table crash_q (q interval day to hour)
+ ###> execute error: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 'interval day to hour)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_day_to_minute=no # Type interval day to minute
+ ###< create table crash_q (q interval day to minute)
+ ###> execute error: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 'interval day to minute)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_day_to_second=no # Type interval day to second
+ ###< create table crash_q (q interval day to second)
+ ###> execute error: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 'interval day to second)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_hour=no # Type interval hour
+ ###< create table crash_q (q interval hour)
+ ###> execute error: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 'interval hour)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_hour_to_minute=no # Type interval hour to minute
+ ###< create table crash_q (q interval hour to minute)
+ ###> execute error: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 'interval hour to minute)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_hour_to_second=no # Type interval hour to second
+ ###< create table crash_q (q interval hour to second)
+ ###> execute error: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 'interval hour to second)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_minute=no # Type interval minute
+ ###< create table crash_q (q interval minute)
+ ###> execute error: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 'interval minute)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_minute_to_second=no # Type interval minute to second
+ ###< create table crash_q (q interval minute to second)
+ ###> execute error: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 'interval minute to second)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_month=no # Type interval month
+ ###< create table crash_q (q interval month)
+ ###> execute error: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 'interval month)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_second=no # Type interval second
+ ###< create table crash_q (q interval second)
+ ###> execute error: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 'interval second)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_year=no # Type interval year
+ ###< create table crash_q (q interval year)
+ ###> execute error: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 'interval year)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_interval_year_to_month=no # Type interval year to month
+ ###< create table crash_q (q interval year to month)
+ ###> execute error: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 'interval year to month)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_national_char_varying(1_arg)=yes # Type national char varying(1 arg)
+ ###< create table crash_q (q national char varying(20))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_national_character(1_arg)=yes # Type national character(1 arg)
+ ###< create table crash_q (q national character(20))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_national_character_varying(1_arg)=yes # Type national character varying(1 arg)
+ ###< create table crash_q (q national character varying(20))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_nchar(1_arg)=yes # Type nchar(1 arg)
+ ###< create table crash_q (q nchar(1))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_nchar_varying(1_arg)=yes # Type nchar varying(1 arg)
+ ###< create table crash_q (q nchar varying(20))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_numeric(2_arg)=yes # Type numeric(2 arg)
+ ###< create table crash_q (q numeric(9,2))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_real=yes # Type real
+ ###< create table crash_q (q real)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_smallint=yes # Type smallint
+ ###< create table crash_q (q smallint)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_time=yes # Type time
+ ###< create table crash_q (q time)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_timestamp=yes # Type timestamp
+ ###< create table crash_q (q timestamp)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+type_sql_timestamp_with_time_zone=no # Type timestamp with time zone
+ ###< create table crash_q (q timestamp with time zone)
+ ###> execute error: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 'with time zone)' at line 1
+ ###< drop table crash_q
+ ###> execute error:Unknown table 'crash_q'
+ ###
+ ###As far as some queries didnt return OK, result is NO
+type_sql_varchar(1_arg)=yes # Type varchar(1 arg)
+ ###< create table crash_q (q varchar(1))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+union=yes # union
+ ###< select * from crash_me union select a,b from crash_me3
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+union_all=yes # union all
+ ###< select * from crash_me union all select a,b from crash_me3
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+union_all_incompat=yes # union all (incompatible lists)
+ ###< select * from crash_me union all select a,b from crash_me2
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+union_incompat=yes # union (incompatible lists)
+ ###< select * from crash_me union select a,b from crash_me2
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+unique_in_create=yes # unique in create table
+ ###< create table crash_q (q integer not null,unique (q))
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+unique_null_in_create=yes # unique null in create
+ ###< create table crash_q (q integer,unique (q))
+ ###> OK
+ ###< insert into crash_q (q) values (NULL)
+ ###> OK
+ ###< insert into crash_q (q) values (NULL)
+ ###> OK
+ ###< insert into crash_q (q) values (1)
+ ###> OK
+ ###< drop table crash_q
+ ###> OK
+ ###
+ ###As far as all queries returned OK, result is YES
+value_of_false=0 # Value of FALSE
+ ###<select FALSE
+ ###>0
+value_of_true=1 # Value of TRUE
+ ###<select TRUE
+ ###>1
+views=no # views
+ ###< create view crash_q as select a from crash_me
+ ###> execute error: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 'view crash_q as select a from crash_me' at line 1
+ ###< drop view crash_q
+ ###> execute error: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 'view crash_q' at line 1
+ ###
+ ###As far as some queries didnt return OK, result is NO
+where_string_size=1048539 # constant string size in where
+ ###We are trying (example with N=5):
+ ###select a from crash_me where b >='11111'
diff --git a/sql-bench/limits/mysql.cfg b/sql-bench/limits/mysql.cfg
index 64f91f07363..76565cb16ff 100644
--- a/sql-bench/limits/mysql.cfg
+++ b/sql-bench/limits/mysql.cfg
@@ -1,7056 +1,1119 @@
#This file is automaticly generated by crash-me 1.61
NEG=yes # update of column= -column
- ###< create table crash_q (a integer)
- ###> OK
- ###< insert into crash_q values(10)
- ###> OK
- ###< update crash_q set a=-a
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
Need_cast_for_null=no # Need to cast NULL for arithmetic
- ### Check if numeric_null (NULL) is 'NULL'
alter_add_col=yes # Alter table add column
- ###< alter table crash_q add d integer
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
alter_add_constraint=yes # Alter table add constraint
- ###< alter table crash_q add constraint c2 check(a > b)
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
-alter_add_foreign_key=no # Alter table add foreign key
- ###< alter table crash_q add constraint f1 foreign key(c1)
- ###> execute error: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
- ###< references crash_q1(c1)
- ###> execute error: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 'references crash_q1(c1)' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
+alter_add_foreign_key=yes # Alter table add foreign key
alter_add_multi_col=yes # Alter table add many columns
- ###< alter table crash_q add (f integer,g integer)
- ###> OK
alter_add_primary_key=with constraint # Alter table add primary key
- ###< alter table crash_q1 add constraint p1 primary key(c1)
- ###> OK
alter_add_unique=yes # Alter table add unique
- ###< alter table crash_q add constraint u1 unique(c1)
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
alter_alter_col=yes # Alter table alter column default
- ###< alter table crash_q alter b set default 10
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
alter_change_col=yes # Alter table change column
- ###< alter table crash_q change a e char(50)
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
alter_drop_col=yes # Alter table drop column
- ###< alter table crash_q drop column b
- ###> OK
alter_drop_constraint=no # Alter table drop constraint
- ###< alter table crash_q drop constraint c2
- ###> execute error: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 'constraint c2' at line 1
- ###
- ###< alter table crash_q drop constraint c2 restrict
- ###> execute error: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 'constraint c2 restrict' at line 1
alter_drop_foreign_key=with drop foreign key # Alter table drop foreign key
- ###< alter table crash_q drop constraint f1
- ###> execute error: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 'constraint f1' at line 1
- ###
- ###< alter table crash_q drop constraint f1 restrict
- ###> execute error: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 'constraint f1 restrict' at line 1
- ###
- ###< alter table crash_q drop foreign key f1
- ###> OK
alter_drop_primary_key=drop primary key # Alter table drop primary key
- ###< alter table crash_q1 drop constraint p1 restrict
- ###> execute error: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 'constraint p1 restrict' at line 1
- ###
- ###< alter table crash_q1 drop primary key
- ###> OK
alter_drop_unique=with drop key # Alter table drop unique
- ###< alter table crash_q drop constraint u1
- ###> execute error: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 'constraint u1' at line 1
- ###
- ###< alter table crash_q drop constraint u1 restrict
- ###> execute error: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 'constraint u1 restrict' at line 1
- ###
- ###< alter table crash_q drop key u1
- ###> OK
alter_modify_col=yes # Alter table modify column
- ###< alter table crash_q modify c1 CHAR(20)
- ###> OK
alter_rename_table=yes # Alter table rename table
- ###< alter table crash_q rename to crash_q1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
atomic_updates=no # atomic updates
- ###< create table crash_q (a integer not null,primary key (a))
- ###> OK
- ###< insert into crash_q values (2)
- ###> OK
- ###< insert into crash_q values (3)
- ###> OK
- ###< insert into crash_q values (1)
- ###> OK
- ###< update crash_q set a=a+1
- ###> execute error:Duplicate entry '3' for key 1
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as some queries didnt return OK, result is NO
automatic_rowid=_rowid # Automatic row id
- ###< create table crash_q (a int not null, primary key(a))
- ###> OK
- ###< insert into crash_q values (1)
- ###> OK
- ###< select _rowid from crash_q
- ###> OK
- ###< drop table crash_q
- ###> OK
-binary_numbers=no # binary numbers (0b1001)
- ###< select 0b1001
- ###> execute error:Unknown column '0b1001' in 'field list'
- ###
- ###As far as some queries didnt return OK, result is NO
-binary_strings=no # binary strings (b'0110')
- ###< select b'0110'
- ###> execute error:Unknown column 'b' in 'field list'
- ###
- ###As far as some queries didnt return OK, result is NO
+binary_numbers=yes # binary numbers (0b1001)
+binary_strings=yes # binary strings (b'0110')
case_insensitive_strings=yes # Case insensitive compare
- ###
- ###<select b from crash_me where b = 'A'
- ###>a
char_is_space_filled=no # char are space filled
- ###
- ###<select concat(b,b) from crash_me where b = 'a '
- ###>aa
- ###We expected 'a a ' but got 'aa'
column_alias=yes # Column alias
- ###< select a as ab from crash_me
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
columns_in_group_by=+64 # number of columns in group by
- ###We are trying (example with N=5):
- ###create table crash_q (q1 integer,q2 integer,q3 integer,q4 integer,q5 integer)
- ###insert into crash_q values(1,1,1,1,1)
- ###insert into crash_q values(1,1,1,1,1)
- ###select q1,q2,q3,q4,q5 from crash_q group by q1,q2,q3,q4,q5
columns_in_order_by=+64 # number of columns in order by
- ###We are trying (example with N=5):
- ###create table crash_q (q1 integer,q2 integer,q3 integer,q4 integer,q5 integer)
- ###insert into crash_q values(1,1,1,1,1)
- ###insert into crash_q values(1,1,1,1,1)
- ###select * from crash_q order by q1,q2,q3,q4,q5
comment_#=yes # # as comment
- ###< select * from crash_me # Testing of comments
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
comment_--=yes # -- as comment (ANSI)
- ###< select * from crash_me -- Testing of comments
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
comment_/**/=yes # /* */ as comment
- ###< select * from crash_me /* Testing of comments */
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
comment_//=no # // as comment
- ###< select * from crash_me // Testing of comments
- ###> execute error: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 '// Testing of comments' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
compute=no # Compute
- ###< select a from crash_me order by a compute sum(a) by a
- ###> execute error: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 'compute sum(a) by a' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
connections=101 # Simultaneous connections (installation default)
constraint_check=syntax only # Column constraints
- ###< create table crash_q (a int check (a>0))
- ###> OK
- ###
- ###< insert into crash_q values(0)
- ###> OK
- ###
- ###< drop table crash_q
- ###> OK
constraint_check_named=syntax only # Named constraints
- ###< create table crash_q (a int ,b int, constraint abc check (a>b))
- ###> OK
- ###
- ###< insert into crash_q values(0,0)
- ###> OK
- ###
- ###< drop table crash_q
- ###> OK
constraint_check_table=syntax only # Table constraints
- ###< create table crash_q (a int ,b int, check (a>b))
- ###> OK
- ###
- ###< insert into crash_q values(0,0)
- ###> OK
- ###
- ###< drop table crash_q
- ###> OK
constraint_null=yes # NULL constraint (SyBase style)
- ###< create table crash_q (a int null)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
crash_me_safe=yes # crash me safe
crash_me_version=1.61 # crash me version
create_default=yes # default value for column
- ###< create table crash_q (q integer default 10 not null)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
create_default_func=no # default value function for column
- ###< create table crash_q (q integer not null,q1 integer default (1+1))
- ###> execute error: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
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
create_if_not_exists=yes # create table if not exists
- ###< create table crash_q (q integer)
- ###> OK
- ###< create table if not exists crash_q (q integer)
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
create_index=yes # create index
- ###< create index crash_q on crash_me (a)
- ###> OK
create_schema=no # Create SCHEMA
- ###< create schema crash_schema create table crash_q (a int) create table crash_q2(b int)
- ###> execute error: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 'schema crash_schema create table crash_q (a int) create table c
- ###< drop schema crash_schema cascade
- ###> execute error: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 'schema crash_schema cascade' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
create_table_select=yes # create table from select
- ###< create table crash_q SELECT * from crash_me
- ###> OK
cross_join=yes # cross join (same as from a,b)
- ###< select crash_me.a from crash_me cross join crash_me3
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
date_as_string=yes # String functions on date columns
- ###< create table crash_me2 (a date not null)
- ###> OK
- ###< insert into crash_me2 values ('1998-03-03')
- ###> OK
- ###
- ###<select left(a,4) from crash_me2
- ###>1998
- ###
- ###< drop table crash_me2
- ###> OK
date_format_EUR=error # Supports DD.MM.YYYY (EUR) format
- ###< insert into crash_me_d(a) values ('16.08.1963')
- ###> OK
- ###
- ###<select a from crash_me_d
- ###>0000-00-00
- ###We expected '1963-08-16' but got '0000-00-00'
- ###
- ###< delete from crash_me_d
- ###> OK
date_format_EUR_with_date=error # Supports DATE 'DD.MM.YYYY' (EUR) format
- ###< insert into crash_me_d(a) values (DATE '16.08.1963')
- ###> OK
- ###
- ###<select a from crash_me_d
- ###>0000-00-00
- ###We expected '1963-08-16' but got '0000-00-00'
- ###
- ###< delete from crash_me_d
- ###> OK
date_format_ISO=yes # Supports YYYY-MM-DD (ISO) format
- ###< insert into crash_me_d(a) values ('1963-08-16')
- ###> OK
- ###
- ###<select a from crash_me_d
- ###>1963-08-16
- ###
- ###< delete from crash_me_d
- ###> OK
date_format_ISO_with_date=yes # Supports DATE 'YYYY-MM-DD' (ISO) format
- ###< insert into crash_me_d(a) values (DATE '1963-08-16')
- ###> OK
- ###
- ###<select a from crash_me_d
- ###>1963-08-16
- ###
- ###< delete from crash_me_d
- ###> OK
date_format_USA=error # Supports MM/DD/YYYY format
- ###< insert into crash_me_d(a) values ('08/16/1963')
- ###> OK
- ###
- ###<select a from crash_me_d
- ###>0000-00-00
- ###We expected '1963-08-16' but got '0000-00-00'
- ###
- ###< delete from crash_me_d
- ###> OK
date_format_USA_with_date=error # Supports DATE 'MM/DD/YYYY' format
- ###< insert into crash_me_d(a) values (DATE '08/16/1963')
- ###> OK
- ###
- ###<select a from crash_me_d
- ###>0000-00-00
- ###We expected '1963-08-16' but got '0000-00-00'
- ###
- ###< delete from crash_me_d
- ###> OK
date_format_YYYYMMDD=yes # Supports YYYYMMDD format
- ###< insert into crash_me_d(a) values ('19630816')
- ###> OK
- ###
- ###<select a from crash_me_d
- ###>1963-08-16
- ###
- ###< delete from crash_me_d
- ###> OK
date_format_YYYYMMDD_with_date=yes # Supports DATE 'YYYYMMDD' format
- ###< insert into crash_me_d(a) values (DATE '19630816')
- ###> OK
- ###
- ###<select a from crash_me_d
- ###>1963-08-16
- ###
- ###< delete from crash_me_d
- ###> OK
date_format_inresult=iso # Date format in result
- ###< insert into crash_me_d values( sysdate() )
- ###> OK
- ###
- ###< select a from crash_me_d
- ###> 2004-04-06
- ###< delete from crash_me_d
- ###> OK
date_infinity=error # Supports 'infinity dates
- ###< create table crash_me2 (a date not null)
- ###> OK
- ###< insert into crash_me2 values ('infinity')
- ###> OK
- ###
- ###<select a from crash_me2
- ###>0000-00-00
- ###We expected 'infinity' but got '0000-00-00'
- ###
- ###< drop table crash_me2
- ###> OK
date_last=yes # Supports 9999-12-31 dates
- ###< create table crash_me2 (a date not null)
- ###> OK
- ###< insert into crash_me2 values ('9999-12-31')
- ###> OK
- ###
- ###<select a from crash_me2
- ###>9999-12-31
- ###
- ###< drop table crash_me2
- ###> OK
date_one=yes # Supports 0001-01-01 dates
- ###< create table crash_me2 (a date not null)
- ###> OK
- ###< insert into crash_me2 values ('0001-01-01')
- ###> OK
- ###
- ###<select a from crash_me2
- ###>0001-01-01
- ###
- ###< drop table crash_me2
- ###> OK
date_with_YY=yes # Supports YY-MM-DD 2000 compilant dates
- ###< create table crash_me2 (a date not null)
- ###> OK
- ###< insert into crash_me2 values ('98-03-03')
- ###> OK
- ###
- ###<select a from crash_me2
- ###>1998-03-03
- ###
- ###< drop table crash_me2
- ###> OK
- ###
- ###< create table crash_me2 (a date not null)
- ###> OK
- ###< insert into crash_me2 values ('10-03-03')
- ###> OK
- ###
- ###<select a from crash_me2
- ###>2010-03-03
- ###
- ###< drop table crash_me2
- ###> OK
date_zero=yes # Supports 0000-00-00 dates
- ###< create table crash_me2 (a date not null)
- ###> OK
- ###< insert into crash_me2 values ('0000-00-00')
- ###> OK
- ###
- ###<select a from crash_me2
- ###>0000-00-00
- ###
- ###< drop table crash_me2
- ###> OK
domains=no # Domains (ANSI SQL)
- ###< create domain crash_d as varchar(10) default 'Empty' check (value <> 'abcd')
- ###> execute error: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 'domain crash_d as varchar(10) default 'Empty' check (value <> '
- ###< create table crash_q(a crash_d, b int)
- ###> execute error: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 'crash_d, b int)' at line 1
- ###< insert into crash_q(a,b) values('xyz',10)
- ###> execute error:Table 'test.crash_q' doesn't exist
- ###< insert into crash_q(b) values(10)
- ###> execute error:Table 'test.crash_q' doesn't exist
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###< drop domain crash_d
- ###> execute error: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 'domain crash_d' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
dont_require_cast_to_float=yes # No need to cast from integer to float
- ###< select exp(1)
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
double_quotes=yes # Double '' as ' in strings
- ###
- ###<select 'Walker''s'
- ###>Walker's
drop_if_exists=yes # drop table if exists
- ###< create table crash_q (q integer)
- ###> OK
- ###< drop table if exists crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
drop_index=with 'ON' # drop index
- ###< drop index crash_q
- ###> execute error: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
- ###
- ###< drop index crash_q from crash_me
- ###> execute error: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 crash_me' at line 1
- ###
- ###< drop index crash_q on crash_me
- ###> OK
drop_requires_cascade=no # drop table require cascade/restrict
- ###< create table crash_me (a integer not null)
- ###> OK
- ###< drop table crash_me
- ###> OK
drop_restrict=yes # drop table with cascade/restrict
- ###< create table crash_q (a int)
- ###> OK
- ###< drop table crash_q restrict
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
end_colon=yes # allows end ';'
- ###< select * from crash_me;
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
except=no # except
- ###< select * from crash_me except select * from crash_me3
- ###> execute error: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 crash_me3' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
except_all=no # except all
- ###< select * from crash_me except all select * from crash_me3
- ###> execute error: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 'all select * from crash_me3' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
except_all_incompat=no # except all (incompatible lists)
- ###< select * from crash_me except all select * from crash_me2
- ###> execute error: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 'all select * from crash_me2' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
except_incompat=no # except (incompatible lists)
- ###< select * from crash_me except select * from crash_me2
- ###> execute error: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 crash_me2' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
field_name_case=yes # case independent field names
- ###< create table crash_q (q integer)
- ###> OK
- ###< insert into crash_q(Q) values (1)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
float_int_expr=yes # mixing of integer and float in expression
- ###< select 1+1.0
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
foreign_key=syntax only # foreign keys
- ###< create table crash_me_qf (a integer not null,primary key (a))
- ###> OK
- ###
- ###< create table crash_me_qf2 (a integer not null,foreign key (a) references crash_me_qf (a))
- ###> OK
- ###
- ###< insert into crash_me_qf values (1)
- ###> OK
- ###
- ###< insert into crash_me_qf2 values (2)
- ###> OK
- ###
- ###< drop table crash_me_qf2
- ###> OK
- ###
- ###< drop table crash_me_qf
- ###> OK
full_outer_join=no # full outer join
- ###< select crash_me.a from crash_me full join crash_me2 ON
- ### crash_me.a=crash_me2.a
- ###> execute error:Unknown table 'crash_me' in field list
- ###
- ###As far as some queries didnt return OK, result is NO
func_extra_!=yes # Function NOT as '!' in SELECT
- ###
- ###<select ! 1
- ###>0
func_extra_%=yes # Function MOD as %
- ###
- ###<select 10%7
- ###>3
func_extra_&=yes # Function & (bitwise and)
- ###
- ###<select 5 & 3
- ###>1
func_extra_&&=yes # Function AND as '&&'
- ###
- ###<select 1=1 && 2=2
- ###>1
func_extra_<>=yes # Function <> in SELECT
- ###
- ###<select 1<>1
- ###>0
func_extra_==yes # Function =
- ###
- ###<select (1=1)
- ###>1
func_extra_add_months=no # Function ADD_MONTHS
- ###
- ###<select add_months('1997-01-01',1) from crash_me_d
- ###> execute failed: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 '('1997-01-01',1) from crash_me_d' at line 1
func_extra_adddate=yes # Function ADDDATE
- ###
- ###<select ADDDATE('2002-12-01',3) from crash_me_d
- ###>2002-12-04
func_extra_addtime=yes # Function ADDTIME
- ###
- ###<select ADDTIME('20:02:12','00:00:03')
- ###>20:02:15
func_extra_alpha=no # Function ALPHA
- ###
- ###<select alpha('Aâ',2)
- ###> execute failed: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â',2)' at line 1
func_extra_and_or=yes # Function AND and OR in SELECT
- ###
- ###<select 1=1 AND 2=2
- ###>1
func_extra_ascii_char=no # Function ASCII_CHAR
- ###
- ###<select ASCII_CHAR(65)
- ###> execute failed: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 '(65)' at line 1
func_extra_ascii_code=no # Function ASCII_CODE
- ###
- ###<select ASCII_CODE('A')
- ###> execute failed: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')' at line 1
func_extra_ascii_string=error # Function ASCII in string cast
- ###
- ###<select ascii('a')
- ###>97
- ###We expected 'a' but got '97'
func_extra_atn2=no # Function ATN2
- ###
- ###<select atn2(1,0)
- ###> execute failed: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
func_extra_auto_num2string=yes # Function automatic num->string convert
- ###
- ###<select concat('a',2)
- ###>a2
func_extra_auto_string2num=yes # Function automatic string->num convert
- ###
- ###<select '1'+2
- ###>3
func_extra_between=yes # Function BETWEEN in SELECT
- ###
- ###<select 5 between 4 and 6
- ###>1
func_extra_binary_shifts=yes # Function << and >> (bitwise shifts)
- ###
- ###<select (1 << 4) >> 2
- ###>4
func_extra_bit_count=yes # Function BIT_COUNT
- ###
- ###<select bit_count(5)
- ###>2
func_extra_ceil=yes # Function CEIL
- ###
- ###<select ceil(-4.5)
- ###>-4
func_extra_char_date=no # Function CHAR (conversation date)
- ###
- ###<select CHAR(a,EUR) from crash_me_d
- ###> execute failed:Unknown column 'EUR' in 'field list'
func_extra_charindex=no # Function CHARINDEX
- ###
- ###<select charindex('a','crash')
- ###> execute failed: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','crash')' at line 1
func_extra_chr=no # Function CHR
- ###
- ###<select CHR(65)
- ###> execute failed: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 '(65)' at line 1
func_extra_chr_str=no # Function CHR (any type to string)
- ###
- ###<select CHR(67)
- ###> execute failed: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 '(67)' at line 1
func_extra_concat_as_+=error # Function concatenation with +
- ###
- ###<select 'abc' + 'def'
- ###>0
- ###We expected 'abcdef' but got '0'
func_extra_concat_list=yes # Function CONCAT(list)
- ###
- ###<select concat('a','b','c','d')
- ###>abcd
func_extra_convert=no # Function CONVERT
- ###
- ###<select convert(CHAR,5)
- ###> execute failed: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 '5)' at line 1
func_extra_cosh=no # Function COSH
- ###
- ###<select cosh(0)
- ###> execute failed: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 '(0)' at line 1
func_extra_date=yes # Function DATE
- ###
- ###<select date('1963-08-16') from crash_me_d
- ###>1963-08-16
func_extra_date_format=yes # Function DATE_FORMAT
- ###
- ###<select date_format('1997-01-02 03:04:05','M W D Y y m d h i s w') from crash_me_d
- ###>M W D Y y m d h i s w
func_extra_dateadd=no # Function DATEADD
- ###
- ###<select dateadd(day,3,'1997-11-30') from crash_me_d
- ###> execute failed: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 '(day,3,'1997-11-30') from crash_me_d' at line 1
func_extra_datediff=no # Function DATEDIFF
- ###
- ###<select datediff(month,'Oct 21 1997','Nov 30 1997') from crash_me_d
- ###> execute failed: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 ''Nov 30 1997') from crash_me_d' at line 1
func_extra_datediff2arg=yes # Function DATEDIFF (2 arg)
- ###
- ###<select DATEDIFF('2002-12-04','2002-12-01') from crash_me_d
- ###>3
func_extra_datename=no # Function DATENAME
- ###
- ###<select datename(month,'Nov 30 1997') from crash_me_d
- ###> execute failed: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 '(month,'Nov 30 1997') from crash_me_d' at line 1
func_extra_datepart=no # Function DATEPART
- ###
- ###<select datepart(month,'July 20 1997') from crash_me_d
- ###> execute failed: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 '(month,'July 20 1997') from crash_me_d' at line 1
func_extra_day=yes # Function DAY
- ###
- ###<select DAY('2002-12-01') from crash_me_d
- ###>1
func_extra_decode=no # Function DECODE
- ###
- ###<select DECODE('S-103','T72',1,'S-103',2,'Leopard',3)
- ###> execute failed: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,'S-103',2,'Leopard',3)' at line 1
func_extra_ebcdic_string=no # Function EBCDIC in string cast
- ###
- ###<select ebcdic('a')
- ###> execute failed: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')' at line 1
func_extra_elt=yes # Function ELT
- ###
- ###<select elt(2,'ONE','TWO','THREE')
- ###>TWO
func_extra_encrypt=yes # Function ENCRYPT
- ###
- ###<select encrypt('hello')
- ###>VNeu3dE4DbVJY
func_extra_expand2arg=no # Function EXPAND
- ###
- ###<select expand('abcd',6)
- ###> execute failed: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 '('abcd',6)' at line 1
func_extra_field=yes # Function FIELD
- ###
- ###<select field('IBM','NCA','ICL','SUN','IBM','DIGITAL')
- ###>4
func_extra_fixed=no # Function FIXED
- ###
- ###<select fixed(222.6666,10,2)
- ###> execute failed: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 '(222.6666,10,2)' at line 1
func_extra_float=no # Function FLOAT
- ###
- ###<select float(6666.66,4)
- ###> execute failed: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 'float(6666.66,4)' at line 1
func_extra_format=yes # Function FORMAT
- ###
- ###<select format(1234.5555,2)
- ###>1,234.56
func_extra_from_days=yes # Function FROM_DAYS
- ###
- ###<select from_days(729024) from crash_me_d
- ###>1996-01-01
func_extra_from_unixtime=yes # Function FROM_UNIXTIME
- ###
- ###<select from_unixtime(0) from crash_me_d
- ###>1970-01-01 02:00:00
func_extra_getdate=no # Function GETDATE
- ###
- ###<select getdate()
- ###> execute failed: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
func_extra_greatest=yes # Function GREATEST
- ###
- ###<select greatest('HARRY','HARRIOT','HAROLD')
- ###>HARRY
func_extra_hex=yes # Function HEX
- ###
- ###<select HEX('A')
- ###>41
func_extra_if=yes # Function IF
- ###
- ###<select if(5,6,7)
- ###>6
func_extra_in_num=yes # Function IN on numbers in SELECT
- ###
- ###<select 2 in (3,2,5,9,5,1)
- ###>1
func_extra_in_str=yes # Function IN on strings in SELECT
- ###
- ###<select 'monty' in ('david','monty','allan')
- ###>1
func_extra_index=no # Function INDEX
- ###
- ###<select index('abcdefg','cd',1,1)
- ###> execute failed: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 'index('abcdefg','cd',1,1)' at line 1
func_extra_initcap=no # Function INITCAP
- ###
- ###<select initcap('the soap')
- ###> execute failed: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 '('the soap')' at line 1
func_extra_instr=yes # Function LOCATE as INSTR
- ###
- ###<select instr('hello','ll')
- ###>3
func_extra_instr_oracle=no # Function INSTR (Oracle syntax)
- ###
- ###<select INSTR('CORPORATE FLOOR','OR',3,2)
- ###> execute failed: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 '3,2)' at line 1
func_extra_instrb=no # Function INSTRB
- ###
- ###<select INSTRB('CORPORATE FLOOR','OR',5,2)
- ###> execute failed: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 '('CORPORATE FLOOR','OR',5,2)' at line 1
func_extra_interval=yes # Function INTERVAL
- ###
- ###<select interval(55,10,20,30,40,50,60,70,80,90,100)
- ###>5
func_extra_last_day=yes # Function LAST_DAY
- ###
- ###<select last_day('1997-04-01') from crash_me_d
- ###>1997-04-30
func_extra_last_insert_id=yes # Function LAST_INSERT_ID
- ###
- ###<select last_insert_id()
- ###>0
func_extra_least=yes # Function LEAST
- ###
- ###<select least('HARRY','HARRIOT','HAROLD')
- ###>HAROLD
func_extra_length=error # Function LENGTH
- ###
- ###<select length(1)
- ###>1
- ###We expected '2' but got '1'
func_extra_lengthb=no # Function LENGTHB
- ###
- ###<select lengthb('CANDIDE')
- ###> execute failed: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 '('CANDIDE')' at line 1
func_extra_lfill3arg=no # Function LFILL (3 arg)
- ###
- ###<select lfill('abcd','.',6)
- ###> execute failed: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 '('abcd','.',6)' at line 1
func_extra_like=yes # Function LIKE in SELECT
- ###
- ###<select 'a' like 'a%'
- ###>1
func_extra_like_escape=yes # Function LIKE ESCAPE in SELECT
- ###
- ###<select '%' like 'a%' escape 'a'
- ###>1
func_extra_ln=yes # Function LN
- ###
- ###<select ln(95)
- ###>4.553877
func_extra_log(m_n)=yes # Function LOG(m,n)
- ###
- ###<select log(10,100)
- ###>2.000000
func_extra_logn=no # Function LOGN
- ###
- ###<select logn(2)
- ###> execute failed: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)' at line 1
func_extra_lpad=yes # Function LPAD
- ###
- ###<select lpad('hi',4,'??')
- ###>??hi
func_extra_ltrim2arg=no # Function LTRIM (2 arg)
- ###
- ###<select ltrim('..abcd..','.')
- ###> execute failed: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
func_extra_makedate=yes # Function MAKEDATE
- ###
- ###<select MAKEDATE(1963,228) from crash_me_d
- ###>1963-08-16
func_extra_maketime=yes # Function MAKETIME
- ###
- ###<select MAKETIME(20,02,12)
- ###>20:02:12
func_extra_mapchar=no # Function MAPCHAR
- ###
- ###<select mapchar('Aâ')
- ###> execute failed: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â')' at line 1
func_extra_mdy=no # Function MDY
- ###
- ###<select mdy(7,1,1998) from crash_me_d
- ###> execute failed: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 '(7,1,1998) from crash_me_d' at line 1
func_extra_microsecond=yes # Function MICROSECOND
- ###
- ###<select MICROSECOND('19630816200212111111')
- ###>110000
func_extra_mid=yes # Function SUBSTRING as MID
- ###
- ###<select mid('hello',3,2)
- ###>ll
func_extra_months_between=no # Function MONTHS_BETWEEN
- ###
- ###<select months_between('1997-02-02','1997-01-01') from crash_me_d
- ###> execute failed: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 '('1997-02-02','1997-01-01') from crash_me_d' at line 1
func_extra_noround=no # Function NOROUND
- ###< select noround(22.6)
- ###> execute error: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 '(22.6)' at line 1
func_extra_not=yes # Function NOT in SELECT
- ###
- ###<select not false
- ###>1
func_extra_not_between=yes # Function NOT BETWEEN in SELECT
- ###
- ###<select 5 not between 4 and 6
- ###>0
func_extra_not_like=yes # Function NOT LIKE in SELECT
- ###
- ###<select 'a' not like 'a%'
- ###>0
func_extra_num=no # Function NUM
- ###
- ###<select NUM('2123')
- ###> execute failed: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 '('2123')' at line 1
func_extra_odbc_convert=no # Function ODBC CONVERT
- ###
- ###<select convert(5,SQL_CHAR)
- ###> execute failed: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 'SQL_CHAR)' at line 1
func_extra_password=yes # Function PASSWORD
- ###
- ###<select password('hello')
- ###>*6B4F89A54E2D27ECD7E8DA05B4AB8FD9D1D8B119
func_extra_paste=no # Function PASTE
- ###
- ###<select paste('ABCDEFG',3,2,'1234')
- ###> execute failed: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 '('ABCDEFG',3,2,'1234')' at line 1
func_extra_patindex=no # Function PATINDEX
- ###
- ###<select patindex('%a%','crash')
- ###> execute failed: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%','crash')' at line 1
func_extra_period_add=yes # Function PERIOD_ADD
- ###
- ###<select period_add(9602,-12) from crash_me_d
- ###>199502
func_extra_period_diff=yes # Function PERIOD_DIFF
- ###
- ###<select period_diff(199505,199404) from crash_me_d
- ###>13
func_extra_pow=yes # Function POW
- ###
- ###<select pow(3,2)
- ###>9.000000
func_extra_range=no # Function RANGE
- ###
- ###<select range(a)
- ###> execute failed: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)' at line 1
func_extra_regexp=yes # Function REGEXP in SELECT
- ###
- ###<select 'a' regexp '^(a|b)*$'
- ###>1
func_extra_replace2arg=no # Function REPLACE (2 arg)
- ###
- ###<select replace('AbCd','bC')
- ###> execute failed: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
func_extra_replicate=no # Function REPLICATE
- ###
- ###<select replicate('a',5)
- ###> execute failed: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',5)' at line 1
func_extra_reverse=yes # Function REVERSE
- ###
- ###<select reverse('abcd')
- ###>dcba
func_extra_rfill3arg=no # Function RFILL (3 arg)
- ###
- ###<select rfill('abcd','.',6)
- ###> execute failed: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 '('abcd','.',6)' at line 1
func_extra_root=no # Function ROOT
- ###
- ###<select root(4)
- ###> execute failed: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 '(4)' at line 1
func_extra_round1=yes # Function ROUND(1 arg)
- ###
- ###<select round(5.63)
- ###>6
func_extra_rpad=yes # Function RPAD
- ###
- ###<select rpad('hi',4,'??')
- ###>hi??
func_extra_rpad4arg=no # Function RPAD (4 arg)
- ###
- ###<select rpad('abcd',2,'+-',8)
- ###> execute failed: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 '8)' at line 1
func_extra_rtrim2arg=no # Function RTRIM (2 arg)
- ###
- ###<select rtrim('..abcd..','.')
- ###> execute failed: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
func_extra_sec_to_time=yes # Function SEC_TO_TIME
- ###
- ###<select sec_to_time(5001)
- ###>01:23:21
func_extra_sinh=no # Function SINH
- ###
- ###<select sinh(1)
- ###> execute failed: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
func_extra_str=no # Function STR
- ###
- ###<select str(123.45,5,1)
- ###> execute failed: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.45,5,1)' at line 1
func_extra_strcmp=yes # Function STRCMP
- ###
- ###<select strcmp('abc','adc')
- ###>-1
func_extra_stuff=no # Function STUFF
- ###
- ###<select stuff('abc',2,3,'xyz')
- ###> execute failed: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 '('abc',2,3,'xyz')' at line 1
func_extra_subdate=yes # Function SUBDATE
- ###
- ###<select SUBDATE('2002-12-04',3) from crash_me_d
- ###>2002-12-01
func_extra_substr2arg=yes # Function SUBSTR (2 arg)
- ###
- ###<select substr('abcd',2)
- ###>bcd
func_extra_substr3arg=yes # Function SUBSTR (3 arg)
- ###
- ###<select substr('abcd',2,2)
- ###>bc
func_extra_substrb=no # Function SUBSTRB
- ###
- ###<select SUBSTRB('ABCDEFG',5,4.2)
- ###> execute failed: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 '('ABCDEFG',5,4.2)' at line 1
func_extra_substring_index=yes # Function SUBSTRING_INDEX
- ###
- ###<select substring_index('www.tcx.se','.',-2)
- ###>tcx.se
func_extra_subtime=yes # Function SUBTIME
- ###
- ###<select SUBTIME('20:02:15','00:00:03')
- ###>20:02:12
func_extra_sysdate=yes # Function SYSDATE
- ###
- ###<select sysdate()
- ###>2004-04-06 13:49:05
func_extra_tail=no # Function TAIL
- ###
- ###<select tail('ABCDEFG',3)
- ###> execute failed: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 '('ABCDEFG',3)' at line 1
func_extra_tanh=no # Function TANH
- ###
- ###<select tanh(1)
- ###> execute failed: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
func_extra_time=yes # Function TIME
- ###
- ###<select time('20:02:12')
- ###>20:02:12
func_extra_time_to_sec=yes # Function TIME_TO_SEC
- ###
- ###<select time_to_sec('01:23:21')
- ###>5001
func_extra_timediff=yes # Function TIMEDIFF
- ###
- ###<select TIMEDIFF('20:02:15','20:02:12')
- ###>00:00:03
func_extra_timestamp=error # Function TIMESTAMP
- ###
- ###<select timestamp('19630816','00200212')
- ###>1963-08-16 20:02:12
- ###We expected '19630816200212000000' but got '1963-08-16 20:02:12'
func_extra_to_days=yes # Function TO_DAYS
- ###
- ###<select to_days('1996-01-01') from crash_me_d
- ###>729024
func_extra_translate=no # Function TRANSLATE
- ###
- ###<select translate('abc','bc','de')
- ###> execute failed: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 '('abc','bc','de')' at line 1
func_extra_trim1arg=yes # Function TRIM (1 arg)
- ###
- ###<select trim(' abcd ')
- ###>abcd
func_extra_trim2arg=no # Function TRIM (2 arg)
- ###
- ###<select trim('..abcd..','.')
- ###> execute failed: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
func_extra_trim_many_char=error # Function TRIM; Many char extension
- ###
- ###<select trim(':!' FROM ':abc!')
- ###>:abc!
- ###We expected 'abc' but got ':abc!'
func_extra_trim_substring=yes # Function TRIM; Substring extension
- ###
- ###<select trim('cb' FROM 'abccb')
- ###>abc
func_extra_trunc=no # Function TRUNC
- ###
- ###<select trunc(18.18,-1)
- ###> execute failed: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 '(18.18,-1)' at line 1
func_extra_trunc1arg=no # Function TRUNC (1 arg)
- ###
- ###<select trunc(222.6)
- ###> execute failed: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 '(222.6)' at line 1
func_extra_uid=no # Function UID
- ###
- ###<select uid
- ###> execute failed:Unknown column 'uid' in 'field list'
func_extra_unix_timestamp=yes # Function UNIX_TIMESTAMP
- ###
- ###<select unix_timestamp()
- ###>1081248545
func_extra_userenv=no # Function USERENV
- ###
- ###<select userenv
- ###> execute failed:Unknown column 'userenv' in 'field list'
func_extra_value=no # Function VALUE
- ###
- ###<select value(NULL,'WALRUS')
- ###> execute failed: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,'WALRUS')' at line 1
func_extra_version=yes # Function VERSION
- ###
- ###<select version()
- ###>4.1.2-alpha
func_extra_weekday=yes # Function WEEKDAY
- ###
- ###<select weekday('1997-11-29') from crash_me_d
- ###>5
func_extra_weekofyear=yes # Function WEEKOFYEAR
- ###
- ###<select WEEKOFYEAR('1963-08-16') from crash_me_d
- ###>33
func_extra_|=yes # Function | (bitwise or)
- ###
- ###<select 1 | 2
- ###>3
func_extra_||=yes # Function OR as '||'
- ###
- ###<select 1=0 || 1=1
- ###>1
func_extra_~*=no # Function ~* (case insensitive compare)
- ###
- ###<select 'hi' ~* 'HI'
- ###> execute failed: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 '~* 'HI'' at line 1
func_odbc_abs=yes # Function ABS
- ###
- ###<select abs(-5)
- ###>5
func_odbc_acos=yes # Function ACOS
- ###
- ###<select acos(0)
- ###>1.570796
func_odbc_ascii=yes # Function ASCII
- ###
- ###<select ASCII('A')
- ###>65
func_odbc_asin=yes # Function ASIN
- ###
- ###<select asin(1)
- ###>1.570796
func_odbc_atan=yes # Function ATAN
- ###
- ###<select atan(1)
- ###>0.785398
func_odbc_atan2=yes # Function ATAN2
- ###
- ###<select atan2(1,0)
- ###>1.570796
func_odbc_ceiling=yes # Function CEILING
- ###
- ###<select ceiling(-4.5)
- ###>-4
func_odbc_char=yes # Function CHAR
- ###
- ###<select CHAR(65)
- ###>A
func_odbc_concat=yes # Function CONCAT(2 arg)
- ###
- ###<select concat('a','b')
- ###>ab
func_odbc_cos=yes # Function COS
- ###
- ###<select cos(0)
- ###>1.000000
func_odbc_cot=yes # Function COT
- ###
- ###<select cot(1)
- ###>0.64209262
func_odbc_curdate=yes # Function CURDATE
- ###
- ###<select curdate()
- ###>2004-04-06
func_odbc_curtime=yes # Function CURTIME
- ###
- ###<select curtime()
- ###>13:49:04
func_odbc_database=yes # Function DATABASE
- ###
- ###<select database()
- ###>test
func_odbc_dayname=yes # Function DAYNAME
- ###< insert into crash_me_d values('1997-02-01')
- ###
- ###<select dayname(a) from crash_me_d
- ###>Saturday
func_odbc_dayofmonth=yes # Function DAYOFMONTH
- ###< insert into crash_me_d values('1997-02-01')
- ###
- ###<select dayofmonth(a) from crash_me_d
- ###>1
func_odbc_dayofweek=yes # Function DAYOFWEEK
- ###< insert into crash_me_d values('1997-02-01')
- ###
- ###<select dayofweek(a) from crash_me_d
- ###>7
func_odbc_dayofyear=yes # Function DAYOFYEAR
- ###< insert into crash_me_d values('1997-02-01')
- ###
- ###<select dayofyear(a) from crash_me_d
- ###>32
func_odbc_degrees=yes # Function DEGREES
- ###
- ###<select degrees(6.283185)
- ###>359.99998239991
func_odbc_difference=no # Function DIFFERENCE()
- ###
- ###<select difference('abc','abe')
- ###> execute failed: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 '('abc','abe')' at line 1
- ###
- ###<select {fn difference('abc','abe') }
- ###> execute failed: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 '('abc','abe') }' at line 1
func_odbc_exp=yes # Function EXP
- ###
- ###<select exp(1.0)
- ###>2.718282
func_odbc_floor=yes # Function FLOOR
- ###
- ###<select floor(2.5)
- ###>2
func_odbc_fn_left=yes # Function ODBC syntax LEFT & RIGHT
- ###
- ###<select { fn LEFT( { fn RIGHT('abcd',2) },1) }
- ###>c
func_odbc_hour=yes # Function HOUR
- ###< insert into crash_me_t values(20:08:16)
- ###
- ###<select hour('12:13:14')
- ###>12
func_odbc_hour_time=yes # Function ANSI HOUR
- ###< insert into crash_me_t values(20:08:16)
- ###
- ###<select hour(TIME '12:13:14')
- ###>12
func_odbc_ifnull=yes # Function IFNULL
- ###
- ###<select ifnull(2,3)
- ###>2
func_odbc_insert=yes # Function INSERT
- ###
- ###<select insert('abcd',2,2,'ef')
- ###>aefd
func_odbc_lcase=yes # Function LCASE
- ###
- ###<select lcase('ABC')
- ###>abc
func_odbc_left=yes # Function LEFT
- ###
- ###<select left('abcd',2)
- ###>ab
func_odbc_length=yes # Function REAL LENGTH
- ###
- ###<select length('abcd ')
- ###>5
func_odbc_length_without_space=error # Function ODBC LENGTH
- ###
- ###<select length('abcd ')
- ###>5
- ###We expected '4' but got '5'
- ###
- ###<select {fn length('abcd ') }
- ###>5
- ###We expected '4' but got '5'
func_odbc_locate_2=yes # Function LOCATE(2 arg)
- ###
- ###<select locate('bcd','abcd')
- ###>2
func_odbc_locate_3=yes # Function LOCATE(3 arg)
- ###
- ###<select locate('bcd','abcd',3)
- ###>0
func_odbc_log=yes # Function LOG
- ###
- ###<select log(2)
- ###>0.693147
func_odbc_log10=yes # Function LOG10
- ###
- ###<select log10(10)
- ###>1.000000
func_odbc_ltrim=yes # Function LTRIM
- ###
- ###<select ltrim(' abcd')
- ###>abcd
func_odbc_minute=yes # Function MINUTE
- ###< insert into crash_me_t values(20:08:16)
- ###
- ###<select minute('12:13:14')
- ###>13
func_odbc_mod=yes # Function MOD
- ###
- ###<select mod(11,7)
- ###>4
func_odbc_month=yes # Function MONTH
- ###< insert into crash_me_d values('1997-02-01')
- ###
- ###<select month(a) from crash_me_d
- ###>2
func_odbc_monthname=yes # Function MONTHNAME
- ###< insert into crash_me_d values('1997-02-01')
- ###
- ###<select monthname(a) from crash_me_d
- ###>February
func_odbc_now=yes # Function NOW
- ###
- ###<select now()
- ###>2004-04-06 13:49:04
func_odbc_pi=yes # Function PI
- ###
- ###<select pi()
- ###>3.141593
func_odbc_power=yes # Function POWER
- ###
- ###<select power(2,4)
- ###>16.000000
func_odbc_quarter=yes # Function QUARTER
- ###< insert into crash_me_d values('1997-02-01')
- ###
- ###<select quarter(a) from crash_me_d
- ###>1
func_odbc_radians=yes # Function RADIANS
- ###
- ###<select radians(360)
- ###>6.2831853071796
func_odbc_rand=yes # Function RAND
- ###
- ###<select rand(1)
- ###>0.40540353712198
func_odbc_repeat=yes # Function REPEAT
- ###
- ###<select repeat('ab',3)
- ###>ababab
func_odbc_replace=yes # Function REPLACE
- ###
- ###<select replace('abbaab','ab','ba')
- ###>bababa
func_odbc_right=yes # Function RIGHT
- ###
- ###<select right('abcd',2)
- ###>cd
func_odbc_round=yes # Function ROUND(2 arg)
- ###
- ###<select round(5.63,2)
- ###>5.63
func_odbc_rtrim=yes # Function RTRIM
- ###
- ###<select rtrim(' abcd ')
- ###> abcd
func_odbc_second=yes # Function SECOND
- ###< insert into crash_me_t values(20:08:16)
- ###
- ###<select second('12:13:14')
- ###>14
func_odbc_sign=yes # Function SIGN
- ###
- ###<select sign(-5)
- ###>-1
func_odbc_sin=yes # Function SIN
- ###
- ###<select sin(1)
- ###>0.841471
func_odbc_soundex=yes # Function SOUNDEX
- ###
- ###<select soundex('hello')
- ###>H400
func_odbc_space=yes # Function SPACE
- ###
- ###<select space(5)
- ###>
func_odbc_sqrt=yes # Function SQRT
- ###
- ###<select sqrt(4)
- ###>2.000000
func_odbc_substring=yes # Function ODBC SUBSTRING
- ###
- ###<select substring('abcd',3,2)
- ###>cd
func_odbc_tan=yes # Function TAN
- ###
- ###<select tan(1)
- ###>1.557408
-func_odbc_timestampadd=no # Function TIMESTAMPADD
- ###
- ###<select timestampadd(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')
- ###> execute failed: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 '(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')' at line 1
- ###
- ###<select {fn timestampadd(SQL_TSI_SECOND,1,{ts '1997-01-01 00:00:00'}) }
- ###> execute failed: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 '(SQL_TSI_SECOND,1,{ts '1997-01-01 00:00:00'}) }' at line 1
-func_odbc_timestampdiff=no # Function TIMESTAMPDIFF
- ###
- ###<select timestampdiff(SQL_TSI_SECOND,'1997-01-01 00:00:02', '1997-01-01 00:00:01')
- ###> execute failed: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 '(SQL_TSI_SECOND,'1997-01-01 00:00:02', '1997-01-01 00:00:01')'
- ###
- ###<select {fn timestampdiff(SQL_TSI_SECOND,{ts '1997-01-01 00:00:02'}, {ts '1997-01-01 00:00:01'}) }
- ###> execute failed: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 '(SQL_TSI_SECOND,{ts '1997-01-01 00:00:02'}, {ts '1997-01-01 00:
+func_odbc_timestampadd=yes # Function TIMESTAMPADD
+func_odbc_timestampdiff=error # Function TIMESTAMPDIFF
func_odbc_truncate=yes # Function TRUNCATE
- ###
- ###<select truncate(18.18,-1)
- ###>10
func_odbc_ucase=yes # Function UCASE
- ###
- ###<select ucase('abc')
- ###>ABC
func_odbc_user()=yes # Function USER()
- ###
- ###<select user()
- ###>monty@localhost
func_odbc_week=USA # WEEK
- ###<select week('1997-02-01')
- ###>4
- ###We expected '5' but got '4'
func_odbc_year=yes # Function YEAR
- ###< insert into crash_me_d values('1997-02-01')
- ###
- ###<select year(a) from crash_me_d
- ###>1997
func_sql_+=yes # Function +, -, * and /
- ###
- ###<select 5*3-4/2+1
- ###>14.00
func_sql_bit_length=yes # Function BIT_LENGTH
- ###
- ###<select bit_length('abc')
- ###>24
func_sql_cast=yes # Function CAST
- ###
- ###<select CAST(1 as CHAR)
- ###>1
func_sql_char_length=error # Function CHAR_LENGTH
- ###
- ###<select char_length(b) from crash_me
- ###>1
- ###We expected '10' but got '1'
func_sql_char_length(constant)=yes # Function CHAR_LENGTH(constant)
- ###
- ###<select char_length('abcd')
- ###>4
func_sql_character_length=yes # Function CHARACTER_LENGTH
- ###
- ###<select character_length('abcd')
- ###>4
func_sql_coalesce=yes # Function COALESCE
- ###
- ###<select coalesce(NULL,'bcd','qwe')
- ###>bcd
func_sql_concat_as_||=error # Function concatenation with ||
- ###
- ###<select 'abc' || 'def'
- ###>0
- ###We expected 'abcdef' but got '0'
func_sql_current_date=yes # Function CURRENT_DATE
- ###
- ###<select current_date
- ###>2004-04-06
func_sql_current_time=yes # Function CURRENT_TIME
- ###
- ###<select current_time
- ###>13:49:04
func_sql_current_timestamp=yes # Function CURRENT_TIMESTAMP
- ###
- ###<select current_timestamp
- ###>2004-04-06 13:49:04
func_sql_current_user=yes # CURRENT_USER
- ###< select CURRENT_USER
- ###> OK
func_sql_extract_sql=yes # Function EXTRACT
- ###
- ###<select extract(minute from timestamp '2000-02-23 18:43:12.987')
- ###>43
func_sql_localtime=yes # Function LOCALTIME
- ###
- ###<select localtime
- ###>2004-04-06 13:49:04
func_sql_localtimestamp=yes # Function LOCALTIMESTAMP
- ###
- ###<select localtimestamp
- ###>2004-04-06 13:49:04
func_sql_lower=yes # Function LOWER
- ###
- ###<select LOWER('ABC')
- ###>abc
func_sql_nullif_num=yes # Function NULLIF with numbers
- ###
- ###<select NULLIF(NULLIF(1,2),1)
- ###>
func_sql_nullif_string=yes # Function NULLIF with strings
- ###
- ###<select NULLIF(NULLIF('first','second'),'first')
- ###>
func_sql_octet_length=yes # Function OCTET_LENGTH
- ###
- ###<select octet_length('abc')
- ###>3
func_sql_position=yes # Function POSITION
- ###
- ###<select position('ll' in 'hello')
- ###>3
func_sql_searched_case=yes # Function searched CASE
- ###
- ###<select case when 1 > 2 then 'false' when 2 > 1 then 'true' end
- ###>true
func_sql_session_user=with_parenthesis # SESSION_USER
- ###< select SESSION_USER
- ###> execute error:Unknown column 'SESSION_USER' in 'field list'
- ###
- ###< select SESSION_USER()
- ###> OK
func_sql_simple_case=yes # Function simple CASE
- ###
- ###<select case 2 when 1 then 'false' when 2 then 'true' end
- ###>true
func_sql_substring=yes # Function ANSI SQL SUBSTRING
- ###
- ###<select substring('abcd' from 2 for 2)
- ###>bc
func_sql_system_user=with_parenthesis # SYSTEM_USER
- ###< select SYSTEM_USER
- ###> execute error:Unknown column 'SYSTEM_USER' in 'field list'
- ###
- ###< select SYSTEM_USER()
- ###> OK
func_sql_trim=yes # Function TRIM
- ###
- ###<select trim(trailing from trim(LEADING FROM ' abc '))
- ###>abc
func_sql_upper=yes # Function UPPER
- ###
- ###<select UPPER('abc')
- ###>ABC
func_sql_user=with_parenthesis # USER
- ###< select USER
- ###> execute error:Unknown column 'USER' in 'field list'
- ###
- ###< select USER()
- ###> OK
func_where_between=yes # Function BETWEEN
- ###
- ###<select a from crash_me where 5 between 4 and 6
- ###>1
func_where_eq_all=yes # Function = ALL
- ###
- ###<select a from crash_me where b =all (select b from crash_me)
- ###>1
func_where_eq_any=yes # Function = ANY
- ###
- ###<select a from crash_me where b =any (select b from crash_me)
- ###>1
func_where_eq_some=yes # Function = SOME
- ###
- ###<select a from crash_me where b =some (select b from crash_me)
- ###>1
func_where_exists=yes # Function EXISTS
- ###
- ###<select a from crash_me where exists (select * from crash_me)
- ###>1
func_where_in_num=yes # Function IN on numbers
- ###
- ###<select a from crash_me where 2 in (3,2,5,9,5,1)
- ###>1
func_where_like=yes # Function LIKE
- ###
- ###<select a from crash_me where b like 'a%'
- ###>1
func_where_like_escape=yes # Function LIKE ESCAPE
- ###
- ###<select a from crash_me where b like '%' escape 'a'
- ###>1
func_where_match=no # Function MATCH
- ###
- ###<select a from crash_me where 1 match (select a from crash_me)
- ###> execute failed: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 'match (select a from crash_me)' at line 1
func_where_match_unique=no # Function MATCH UNIQUE
- ###
- ###<select a from crash_me where 1 match unique (select a from crash_me)
- ###> execute failed: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 'match unique (select a from crash_me)' at line 1
func_where_matches=no # Function MATCHES
- ###
- ###<select a from crash_me where b matcjhes 'a*'
- ###> execute failed: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 'matcjhes 'a*'' at line 1
func_where_not_between=yes # Function NOT BETWEEN
- ###
- ###<select a from crash_me where 7 not between 4 and 6
- ###>1
func_where_not_exists=yes # Function NOT EXISTS
- ###
- ###<select a from crash_me where not exists (select * from crash_me where a = 2)
- ###>1
func_where_not_like=yes # Function NOT LIKE
- ###
- ###<select a from crash_me where b not like 'b%'
- ###>1
func_where_not_unique=no # Function NOT UNIQUE
- ###
- ###<select a from crash_me where not unique (select * from crash_me where a = 2)
- ###> execute failed: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 'unique (select * from crash_me where a = 2)' at line 1
func_where_unique=no # Function UNIQUE
- ###
- ###<select a from crash_me where unique (select * from crash_me)
- ###> execute failed: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 'unique (select * from crash_me)' at line 1
functions=yes # Functions
- ###< select 1+1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
group_by=yes # Group by
- ###< select a from crash_me group by a
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
group_by_alias=yes # Group by alias
- ###< select a as ab from crash_me group by ab
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
group_by_null=yes # Group on column with null values
- ###< create table crash_q (s char(10))
- ###> OK
- ###< insert into crash_q values(null)
- ###> OK
- ###< insert into crash_q values(null)
- ###> OK
- ###
- ###<select count(*),s from crash_q group by s
- ###>2
- ###
- ###< drop table crash_q
- ###> OK
group_by_position=yes # Group by position
- ###< select a from crash_me group by 1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
group_distinct_functions=yes # Group functions with distinct
- ###< select count(distinct a) from crash_me
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
group_func_extra_bit_and=yes # Group function BIT_AND
- ###
- ###<select bit_and(a),a from crash_me group by a
- ###>1
group_func_extra_bit_or=yes # Group function BIT_OR
- ###
- ###<select bit_or(a),a from crash_me group by a
- ###>1
group_func_extra_count_distinct_list=yes # Group function COUNT(DISTINCT expr,expr,...)
- ###
- ###<select count(distinct a,b),a from crash_me group by a
- ###>1
group_func_extra_std=yes # Group function STD
- ###
- ###<select std(a),a from crash_me group by a
- ###>0.0000
group_func_extra_stddev=yes # Group function STDDEV
- ###
- ###<select stddev(a),a from crash_me group by a
- ###>0.0000
group_func_extra_variance=yes # Group function VARIANCE
- ###
- ###<select variance(a),a from crash_me group by a
- ###>0.0000
group_func_sql_any=no # Group function ANY
- ###
- ###<select any(a),a from crash_me group by a
- ###> execute failed: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),a from crash_me group by a' at line 1
group_func_sql_avg=yes # Group function AVG
- ###
- ###<select avg(a),a from crash_me group by a
- ###>1.0000
group_func_sql_count_*=yes # Group function COUNT (*)
- ###
- ###<select count(*),a from crash_me group by a
- ###>1
group_func_sql_count_column=yes # Group function COUNT column name
- ###
- ###<select count(a),a from crash_me group by a
- ###>1
group_func_sql_count_distinct=yes # Group function COUNT(DISTINCT expr)
- ###
- ###<select count(distinct a),a from crash_me group by a
- ###>1
group_func_sql_every=no # Group function EVERY
- ###
- ###<select every(a),a from crash_me group by a
- ###> execute failed: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),a from crash_me group by a' at line 1
group_func_sql_max=yes # Group function MAX on numbers
- ###
- ###<select max(a),a from crash_me group by a
- ###>1
group_func_sql_max_str=yes # Group function MAX on strings
- ###
- ###<select max(b),a from crash_me group by a
- ###>a
group_func_sql_min=yes # Group function MIN on numbers
- ###
- ###<select min(a),a from crash_me group by a
- ###>1
group_func_sql_min_str=yes # Group function MIN on strings
- ###
- ###<select min(b),a from crash_me group by a
- ###>a
group_func_sql_some=no # Group function SOME
- ###
- ###<select some(a),a from crash_me group by a
- ###> execute failed: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),a from crash_me group by a' at line 1
group_func_sql_sum=yes # Group function SUM
- ###
- ###<select sum(a),a from crash_me group by a
- ###>1
group_functions=yes # Group functions
- ###< select count(*) from crash_me
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
group_many_distinct_functions=yes # Group functions with several distinct
- ###< select count(distinct a), count(distinct b) from crash_me
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
group_on_unused=yes # Group on unused column
- ###< select count(*) from crash_me group by a
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
has_true_false=yes # TRUE and FALSE
- ###< select (1=1)=true
- ###> OK
having=yes # Having
- ###<select a from crash_me group by a having a > 0
- ###>1
- ###
- ###<select a from crash_me group by a having a < 0
- ###> didn't return any result:
having_with_alias=yes # Having on alias
- ###< select a as ab from crash_me group by a having ab > 0
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
having_with_group=yes # Having with group function
- ###< select a from crash_me group by a having count(*) = 1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
hex_numbers=yes # hex numbers (0x41)
- ###< select 0x41
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
hex_strings=yes # hex strings (x'1ace')
- ###< select x'1ace'
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
ignore_end_space=yes # Ignore end space in compare
- ###
- ###<select b from crash_me where b = 'a '
- ###>a
index_in_create=yes # index in create table
- ###< create table crash_q (q integer not null,index (q))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
index_namespace=yes # different namespace for index
- ###< create index crash_me on crash_me (b)
- ###> OK
- ###< drop index crash_me on crash_me
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
index_parts=yes # index on column part (extension)
- ###< create index crash_q on crash_me (b(5))
- ###> OK
- ###< drop index crash_q on crash_me
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
inner_join=yes # inner join
- ###< select crash_me.a from crash_me inner join crash_me2 ON crash_me.a=crash_me2.a
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
insert_default_values=no # INSERT DEFAULT VALUES
- ###< create table crash_me_q (a int)
- ###> OK
- ###< insert into crash_me_q DEFAULT VALUES
- ###> execute error: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 VALUES' at line 1
- ###< drop table crash_me_q
- ###> OK
- ###
- ###As far as some queries didnt return OK, result is NO
insert_empty_string=yes # insert empty string
- ###< create table crash_q (a char(10) not null,b char(10))
- ###> OK
- ###< insert into crash_q values ('','')
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
insert_multi_value=yes # INSERT with Value lists
- ###< create table crash_q (s char(10))
- ###> OK
- ###< insert into crash_q values ('a'),('b')
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
insert_select=yes # insert INTO ... SELECT ...
- ###< create table crash_q (a int)
- ###> OK
- ###< insert into crash_q (a) SELECT crash_me.a from crash_me
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
insert_with_default=yes # INSERT with DEFAULT
- ###< create table crash_me_q (a int)
- ###> OK
- ###< insert into crash_me_q (a) values (DEFAULT)
- ###> OK
- ###< drop table crash_me_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
insert_with_empty_value_list=no # INSERT with empty value list
- ###< create table crash_me_q (a int)
- ###> OK
- ###< insert into crash_me_q (a) values ()
- ###> execute error:Column count doesn't match value count at row 1
- ###< drop table crash_me_q
- ###> OK
- ###
- ###As far as some queries didnt return OK, result is NO
insert_with_set=yes # INSERT with set syntax
- ###< create table crash_q (a integer)
- ###> OK
- ###< insert into crash_q SET a=1
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
intersect=no # intersect
- ###< select * from crash_me intersect select * from crash_me3
- ###> execute error: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 crash_me3' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
intersect_all=no # intersect all
- ###< select * from crash_me intersect all select * from crash_me3
- ###> execute error: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 'all select * from crash_me3' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
intersect_all_incompat=no # intersect all (incompatible lists)
- ###< select * from crash_me intersect all select * from crash_me2
- ###> execute error: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 'all select * from crash_me2' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
intersect_incompat=no # intersect (incompatible lists)
- ###< select * from crash_me intersect select * from crash_me2
- ###> execute error: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 crash_me2' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
join_tables=61 # tables in join
- ###We are trying (example with N=5):
- ###select crash_me.a,t0.a,t1.a,t2.a,t3.a,t4.a from crash_me,crash_me t0,crash_me t1,crash_me t2,crash_me t3,crash_me t4
- ### 32:OK 48:OK 56:OK 60:OK 62:FAIL 61:FAIL
left_outer_join=yes # left outer join
- ###< select crash_me.a from crash_me left join crash_me2 ON crash_me.a=crash_me2.a
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
left_outer_join_using=yes # left outer join using
- ###< select c1 from crash_me left join crash_me2 using (a)
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
length_of_varchar_field=actual length # CHARACTER_LENGTH(varchar_field)
- ###< CREATE TABLE crash_me1 (S1 VARCHAR(100))
- ###> OK
- ###< INSERT INTO crash_me1 VALUES ('X')
- ###> OK
- ###
- ###< SELECT CHARACTER_LENGTH(S1) FROM crash_me1
- ### > 1
- ###< drop table crash_me1
- ###> OK
like_with_column=yes # column LIKE column
- ###< create table crash_q (a char(10),b char(10))
- ###> OK
- ###< insert into crash_q values('abc','abc')
- ###> OK
- ###< select * from crash_q where a like b
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
like_with_number=yes # LIKE on numbers
- ###< create table crash_q (a int,b int)
- ###> OK
- ###< insert into crash_q values(10,10)
- ###> OK
- ###< select * from crash_q where a like '10'
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
lock_tables=yes # lock table
- ###< lock table crash_me READ
- ###> OK
- ###< unlock tables
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
logical_value=1 # Value of logical operation (1=1)
- ###<select (1=1)
- ###>1
max_big_expressions=10 # big expressions
- ###We are trying (example with N=5):
- ###select 0+(1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+...(8168)
- ### 50:FAIL 10:OK 30:FAIL 14:FAIL 11:FAIL
-max_char_size=1048543 # max char() size
- ###We are trying (example with N=5):
- ###create table crash_q (q char(5))
- ###insert into crash_q values ('aaaaa')
- ###select * from crash_q
- ### 524287:OK 786431:OK 917503:OK 983039:OK 1015807:OK 1032191:OK 1040383:OK 1044479:OK 1046527:OK 1047551:OK 1048063:OK 1048319:OK 1048447:OK 1048511:OK 1048543:OK 1048559:FAIL 1048546:FAIL 1048544:FAIL
+max_char_size=255 # max char() size
max_column_name=64 # column name length
- ###We are trying (example with N=5):
- ###create table crash_q (qaaaaa integer)
- ###insert into crash_q (qaaaaa) values(1)
- ###select qaaaaa from crash_q
- ### 256:FAIL 51:OK 153:FAIL 72:FAIL 55:OK 63:OK 67:FAIL 64:FAIL
max_columns=2599 # Columns in table
- ###We are trying (example with N=5):
- ###create table crash_q (a integer ,a0 integer,a1 integer,a2 integer,a3 integer,a4 integer)
- ### 4096:FAIL 819:OK 2457:OK 3276:FAIL 2621:FAIL 2490:OK 2555:OK 2588:OK 2604:FAIL 2591:OK 2597:OK 2600:FAIL 2598:OK 2599:FAIL
max_conditions=85660 # OR and AND in WHERE
- ###We are trying (example with N=5):
- ###select a from crash_me where a=1 and b='a' or a=0 and b='0' or a=1 and b='1' or a=2 and b='2' or a=3 and b='3' or a=4 and b='4'
- ### 27592:OK 41389:OK 48287:FAIL 42769:OK 45528:FAIL 43321:FAIL 42880:FAIL 42791:OK 42835:FAIL 42800:OK 42817:OK 42826:OK 42830:OK 42832:FAIL 42831:FAIL
-max_expressions=836 # simple expressions
- ###We are trying (example with N=5):
- ###select 1+1+1+1+1+1
- ### 5000:FAIL 1000:FAIL 200:OK 600:OK 800:OK 900:FAIL 820:OK 860:FAIL 828:OK 844:FAIL 831:OK 837:FAIL 832:OK 834:OK 835:OK 836:OK
-max_index=32 # max index
- ### max_unique_index=32 ,so max_index must be same
+max_expressions=580 # simple expressions
+max_index=+64 # max index
max_index_length=1000 # index length
- ###We are trying (example with N=5):
- ###create table crash_q (q0 char(5) not null,unique (q0))
- ###insert into crash_q values('aaaaa')
- ### 4096:FAIL 819:OK 2457:FAIL 1147:FAIL 885:OK 1016:FAIL 911:OK 963:OK 989:OK 1002:FAIL 992:OK 997:OK 999:OK 1000:OK 1001:FAIL
max_index_name=64 # index name length
- ###We are trying (example with N=5):
- ###create index crash_qaaaaa on crash_me (a)
- ### 256:FAIL 51:OK 153:FAIL 72:FAIL 55:OK 63:FAIL 57:OK 60:FAIL 58:FAIL
max_index_part_length=255 # max index part length
- ###We are trying (example with N=5):
- ###create table crash_q (q char(5) not null,unique(q))
- ###insert into crash_q (q) values ('aaaaa')
- ###select q from crash_q
- ### 524271:FAIL 104854:FAIL 20971:FAIL 4194:FAIL 839:FAIL 168:OK 503:FAIL 235:OK 369:FAIL 262:FAIL 241:OK 251:OK 256:FAIL 252:OK 254:OK 255:OK
max_index_parts=16 # index parts
- ###We are trying (example with N=5):
- ###create table crash_q (q0 integer not null,q1 integer not null,q2 integer not null,q3 integer not null,q4 integer not nul...(1263)
- ###insert into crash_q (q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q...(284)
- ###select q0 from crash_q
- ### 32:FAIL 7:OK 19:FAIL 10:OK 14:OK 16:FAIL 15:OK
-max_index_varchar_part_length=255 # index varchar part length
- ###We are trying (example with N=5):
- ###create table crash_q (q varchar(5) not null,unique(q))
- ###insert into crash_q (q) values ('aaaaa')
- ###select q from crash_q
- ### 524271:FAIL 104854:FAIL 20971:FAIL 4194:FAIL 839:FAIL 168:OK 503:FAIL 235:OK 369:FAIL 262:FAIL 241:OK 251:OK 256:FAIL 252:OK 254:OK 255:OK
+max_index_varchar_part_length=1000 # index varchar part length
max_row_length=65534 # max table row length (without blobs)
- ###We are trying (example with N=5):
- ###create table crash_q (q0 char(5) not null)
- ###insert into crash_q values ('aaaaa')
- ### 331372:FAIL 66275:FAIL 13255:OK 39765:OK 53020:OK 59647:OK 62961:OK 64618:OK 65446:OK 65860:FAIL 65529:OK 65694:FAIL 65562:FAIL 65536:FAIL 65531:OK 65533:OK 65534:OK 65535:FAIL
max_row_length_with_null=65502 # table row length with nulls (without blobs)
- ###We are trying (example with N=5):
- ###create table crash_q (q0 char(5) )
- ###insert into crash_q values ('aaaaa')
- ### 65534:FAIL 13107:OK 39320:OK 52427:OK 58980:OK 62257:OK 63895:OK 64714:OK 65124:OK 65329:OK 65431:OK 65482:OK 65508:FAIL 65487:OK 65497:OK 65502:OK 65505:FAIL 65503:FAIL
max_select_alias_name=+512 # select alias name length
- ###We are trying (example with N=5):
- ###select b as aaaaa from crash_me
-max_stack_expression=836 # stacked expressions
- ###We are trying (example with N=5):
- ###select 1+(1+(1+(1+(1+(1)))))
- ### 1000:FAIL 200:OK 600:OK 800:OK 900:FAIL 820:OK 860:FAIL 828:OK 844:FAIL 831:OK 837:FAIL 832:OK 834:OK 835:OK 836:OK
+max_stack_expression=580 # stacked expressions
max_table_alias_name=+512 # table alias name length
- ###We are trying (example with N=5):
- ###select aaaaa.b from crash_me aaaaa
max_table_name=64 # table name length
- ###We are trying (example with N=5):
- ###create table crash_qaaaaa (q integer)
- ###insert into crash_qaaaaa values(1)
- ###select * from crash_qaaaaa
- ### 256:FAIL 51:OK 153:FAIL 72:FAIL 55:OK 63:FAIL 57:OK 60:FAIL 58:FAIL
max_text_size=1048543 # max text or blob size
- ###We are trying (example with N=5):
- ###create table crash_q (q mediumtext)
- ###insert into crash_q values ('aaaaa')
- ###select * from crash_q
- ### 524272:OK 786408:OK 917476:OK 983010:OK 1015777:OK 1032161:OK 1040353:OK 1044449:OK 1046497:OK 1047521:OK 1048033:OK 1048289:OK 1048417:OK 1048481:OK 1048513:OK 1048529:OK 1048537:OK 1048541:OK 1048543:OK 1048544:FAIL
-max_unique_index=32 # unique indexes
- ###We are trying (example with N=5):
- ###create table crash_q (q integer,q1 integer not null,unique (q1),q2 integer not null,unique (q2),q3 integer not null,uniq...(72)
- ###insert into crash_q (q,q1,q2,q3,q4,q5) values (1,1,1,1,1,1)
- ###select q from crash_q
- ### 32:OK 48:FAIL 35:FAIL 33:FAIL
+max_unique_index=+64 # unique indexes
max_varchar_size=1048543 # max varchar() size
- ###We are trying (example with N=5):
- ###create table crash_q (q varchar(5))
- ###insert into crash_q values ('aaaaa')
- ###select * from crash_q
- ### 524287:OK 786431:OK 917503:OK 983039:OK 1015807:OK 1032191:OK 1040383:OK 1044479:OK 1046527:OK 1047551:OK 1048063:OK 1048319:OK 1048447:OK 1048511:OK 1048543:OK 1048559:FAIL 1048546:FAIL 1048544:FAIL
minus=no # minus
- ###< select * from crash_me minus select * from crash_me3
- ###> execute error: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 crash_me3' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
minus_incompat=no # minus (incompatible lists)
- ###< select * from crash_me minus select * from crash_me2
- ###> execute error: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 crash_me2' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
minus_neg=yes # Calculate 1--1
- ###
- ###<select a--1 from crash_me
- ###>2
multi_drop=yes # many tables to drop table
- ###< create table crash_q (a int)
- ###> OK
- ###< create table crash_q2 (a int)
- ###> OK
- ###< drop table crash_q,crash_q2
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
multi_null_in_unique=yes # null in unique index
- ###< create table crash_q (q integer, x integer,unique (q))
- ###> OK
- ###< insert into crash_q(x) values(1)
- ###> OK
- ###< insert into crash_q(x) values(2)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
multi_strings=yes # Multiple line strings
- ###
- ###<select a from crash_me where b < 'a'
- ###'b'
- ###>1
multi_table_delete=yes # DELETE FROM table1,table2...
- ###< create table crash_q (a integer,b char(10))
- ###> OK
- ###< insert into crash_q values(1,'c')
- ###> OK
- ###< delete crash_q.* from crash_q,crash_me where crash_q.a=crash_me.a
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
multi_table_update=yes # Update with many tables
- ###< create table crash_q (a integer,b char(10))
- ###> OK
- ###< insert into crash_q values(1,'c')
- ###> OK
- ###< update crash_q left join crash_me on crash_q.a=crash_me.a set crash_q.b=crash_me.b
- ###> OK
- ###
- ###<select b from crash_q
- ###>a
- ###
- ###< drop table crash_q
- ###> OK
natural_join=yes # natural join
- ###< select * from crash_me natural join crash_me3
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
natural_join_incompat=yes # natural join (incompatible lists)
- ###< select c1 from crash_me natural join crash_me2
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
natural_left_outer_join=yes # natural left outer join
- ###< select c1 from crash_me natural left join crash_me2
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
no_primary_key=yes # Tables without primary key
- ###< create table crash_me (a integer not null,b char(10) not null)
- ###> OK
- ###< insert into crash_me (a,b) values (1,'a')
- ###> OK
-not_id_between=no # NOT ID BETWEEN interprets as ID NOT BETWEEN
- ###< create table crash_me_b (i int)
- ###> OK
- ###< insert into crash_me_b values(2)
- ###> OK
- ###< insert into crash_me_b values(5)
- ###> OK
- ###
- ###<select i from crash_me_b where not i between 1 and 3
- ###> didn't return any result:
- ###
- ###< drop table crash_me_b
- ###> OK
+not_id_between=yes # NOT ID BETWEEN interprets as ID NOT BETWEEN
null_concat_expr=yes # Is concat('a',NULL) = NULL
- ###
- ###<select concat('a',NULL)
- ###>
null_in_index=yes # null in index
- ###< create table crash_q (a char(10),index (a))
- ###> OK
- ###< insert into crash_q values (NULL)
- ###> OK
- ###
- ###<select * from crash_q
- ###>
- ###
- ###< drop table crash_q
- ###> OK
null_in_unique=yes # null in unique index
- ###< create table crash_q (q integer,unique (q))
- ###> OK
- ###< insert into crash_q (q) values(NULL)
- ###> OK
- ###< insert into crash_q (q) values(NULL)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
null_num_expr=yes # Is 1+NULL = NULL
- ###
- ###<select 1+NULL
- ###>
nulls_in_unique=yes # null combination in unique index
- ###< create table crash_q (q integer,q1 integer,unique (q,q1))
- ###> OK
- ###< insert into crash_q (q,q1) values(1,NULL)
- ###> OK
- ###< insert into crash_q (q,q1) values(1,NULL)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
odbc_left_outer_join=yes # left outer join odbc style
- ###< select crash_me.a from { oj crash_me left outer join crash_me2 ON crash_me.a=crash_me2.a }
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
-operating_system=Linux 2.4.21-199-smp4G i686 # crash-me tested on
+operating_system=Linux 2.6.8-my i686 # crash-me tested on
order_by=yes # Order by
- ###< select a from crash_me order by a
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
order_by_alias=yes # Order by alias
- ###< select a as ab from crash_me order by ab
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
order_by_function=yes # Order by function
- ###< select a from crash_me order by a+1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
order_by_position=yes # Order by position
- ###< select a from crash_me order by 1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
order_on_unused=yes # Order by on unused column
- ###< select b from crash_me order by a
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
position_of_null=first # Where is null values in sorted recordset
- ###< insert into crash_me_n (i) values(1)
- ###> OK
- ###< insert into crash_me_n values(2,2)
- ###> OK
- ###< insert into crash_me_n values(3,3)
- ###> OK
- ###< insert into crash_me_n values(4,4)
- ###> OK
- ###< insert into crash_me_n (i) values(5)
- ###> OK
- ###
- ###< select r from crash_me_n order by r
- ###>
- ###>
- ###> 2
- ###> 3
- ###> 4
position_of_null_desc=last # Where is null values in sorted recordset (DESC)
- ###< select r from crash_me_n order by r desc
- ###> 4
- ###> 3
- ###> 2
- ###>
- ###>
primary_key_in_create=yes # primary key in create table
- ###< create table crash_q (q integer not null,primary key (q))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
psm_functions=no # PSM functions (ANSI SQL)
- ###< create table crash_q (a int)
- ###> OK
- ###< create function crash_func(in a1 int, in b1 int) returns int language sql deterministic contains sql begin return a1 * b1; end
- ###> execute error: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 '(in a1 int, in b1 int) returns int language sql deterministic c
- ###< insert into crash_q values(crash_func(2,4))
- ###> execute error: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,4))' at line 1
- ###< select a,crash_func(a,2) from crash_q
- ###> execute error: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,2) from crash_q' at line 1
- ###< drop function crash_func cascade
- ###> execute error: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 'cascade' at line 1
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as some queries didnt return OK, result is NO
psm_modules=no # PSM modules (ANSI SQL)
- ###< create table crash_q (a int,b int)
- ###> OK
- ###< create module crash_m declare procedure crash_proc(in a1 int, in b1 int) language sql modifies sql data begin declare c1 int; set c1 = a1 + b1; insert into crash_q(a,b) values (a1,c1); end; declare procedure crash_proc2(INOUT a int, in b int) contains sql set a = b + 10; end module
- ###> execute error: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 'module crash_m declare procedure crash_proc(in a1 int, in b1 in
- ###< call crash_proc(1,10)
- ###> execute error: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 'call crash_proc(1,10)' at line 1
- ###< drop module crash_m cascade
- ###> execute error: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 'module crash_m cascade' at line 1
- ###< drop table crash_q cascade
- ###> OK
- ###
- ###As far as some queries didnt return OK, result is NO
psm_procedures=no # PSM procedures (ANSI SQL)
- ###< create table crash_q (a int,b int)
- ###> OK
- ###< create procedure crash_proc(in a1 int, in b1 int) language sql modifies sql data begin declare c1 int; set c1 = a1 + b1; insert into crash_q(a,b) values (a1,c1); end
- ###> execute error: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 'procedure crash_proc(in a1 int, in b1 int) language sql modifie
- ###< call crash_proc(1,10)
- ###> execute error: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 'call crash_proc(1,10)' at line 1
- ###< drop procedure crash_proc
- ###> execute error: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 'procedure crash_proc' at line 1
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as some queries didnt return OK, result is NO
psm_trigger=no # Triggers (ANSI SQL)
- ###< create table crash_q (a int ,b int)
- ###> OK
- ###< create trigger crash_trigger after insert on crash_q referencing new table as new_a when (localtime > time '18:00:00') begin atomic end
- ###> execute error: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 'trigger crash_trigger after insert on crash_q referencing new t
- ###< insert into crash_q values(1,2)
- ###> OK
- ###< drop trigger crash_trigger
- ###> execute error: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 'trigger crash_trigger' at line 1
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as some queries didnt return OK, result is NO
query_size=1048574 # query size
quote_ident_with_"=error # " as identifier quote (ANSI SQL)
- ###
- ###<select "A" from crash_me
- ###>A
- ###We expected '1' but got 'A'
quote_ident_with_[=no # [] as identifier quote
- ###
- ###<select [A] from crash_me
- ###> execute failed: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 crash_me' at line 1
quote_ident_with_`=yes # ` as identifier quote
- ###
- ###<select `A` from crash_me
- ###>1
quote_ident_with_dbl_"=no # Double "" in identifiers as "
- ###< create table crash_me1 ("abc""d" integer)
- ###> execute error: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 '"abc""d" integer)' at line 1
- ###< drop table crash_me1
- ###> execute error:Unknown table 'crash_me1'
- ###
- ###As far as some queries didnt return OK, result is NO
quote_with_"=yes # Allows ' and " as string markers
- ###< select a from crash_me where b<"c"
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
recursive_subqueries=+64 # recursive subqueries
- ###We are trying (example with N=5):
- ###select a from crash_me where a in (select a from crash_me where a in (select a from crash_me where a in (select a from c...(82)
remember_end_space=no # Remembers end space in char()
- ###< create table crash_q (a char(10))
- ###> OK
- ###< insert into crash_q values('hello ')
- ###> OK
- ###
- ###<select a from crash_q where a = 'hello '
- ###>hello
- ###We expected 'hello ' but got 'hello'
- ###
- ###< drop table crash_q
- ###> OK
-remember_end_space_varchar=no # Remembers end space in varchar()
- ###< create table crash_q (a varchar(10))
- ###> OK
- ###< insert into crash_q values('hello ')
- ###> OK
- ###
- ###<select a from crash_q where a = 'hello '
- ###>hello
- ###We expected 'hello ' but got 'hello'
- ###
- ###< drop table crash_q
- ###> OK
+remember_end_space_varchar=yes # Remembers end space in varchar()
rename_table=yes # rename table
- ###< create table crash_q (a integer, b integer,c1 CHAR(10))
- ###> OK
- ###< rename table crash_q to crash_q1
- ###> OK
- ###< drop table crash_q1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
repeat_string_size=1048576 # return string size from function
- ###We are trying (example with N=5):
- ###select repeat('a',5)
- ### 4000000:FAIL 800000:OK 2400000:FAIL 1120000:FAIL 864000:OK 992000:OK 1056000:FAIL 1004800:OK 1030400:OK 1043200:OK 1049600:FAIL 1044480:OK 1047040:OK 1048320:OK 1048960:FAIL 1048448:OK 1048704:FAIL 1048499:OK 1048601:FAIL 1048520:OK 1048560:OK 1048580:FAIL 1048564:OK 1048572:OK 1048576:OK 1048578:FAIL 1048577:FAIL
reserved_word_ansi-92/99_absolute=no # Keyword ABSOLUTE
- ###< create table crash_me10 (ABSOLUTE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_action=no # Keyword ACTION
- ###< create table crash_me10 (ACTION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_add=yes # Keyword ADD
- ###< create table crash_me10 (ADD int not null)
- ###> execute error: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 'ADD int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_after=no # Keyword AFTER
- ###< create table crash_me10 (AFTER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_alias=no # Keyword ALIAS
- ###< create table crash_me10 (ALIAS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_all=yes # Keyword ALL
- ###< create table crash_me10 (ALL int not null)
- ###> execute error: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 'ALL int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_allocate=no # Keyword ALLOCATE
- ###< create table crash_me10 (ALLOCATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_alter=yes # Keyword ALTER
- ###< create table crash_me10 (ALTER int not null)
- ###> execute error: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 'ALTER int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_and=yes # Keyword AND
- ###< create table crash_me10 (AND int not null)
- ###> execute error: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 'AND int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_any=no # Keyword ANY
- ###< create table crash_me10 (ANY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_are=no # Keyword ARE
- ###< create table crash_me10 (ARE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_as=yes # Keyword AS
- ###< create table crash_me10 (AS int not null)
- ###> execute error: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 'AS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_asc=yes # Keyword ASC
- ###< create table crash_me10 (ASC int not null)
- ###> execute error: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 'ASC int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_assertion=no # Keyword ASSERTION
- ###< create table crash_me10 (ASSERTION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_at=no # Keyword AT
- ###< create table crash_me10 (AT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_authorization=no # Keyword AUTHORIZATION
- ###< create table crash_me10 (AUTHORIZATION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_before=yes # Keyword BEFORE
- ###< create table crash_me10 (BEFORE int not null)
- ###> execute error: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 'BEFORE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_begin=no # Keyword BEGIN
- ###< create table crash_me10 (BEGIN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_bit=no # Keyword BIT
- ###< create table crash_me10 (BIT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_boolean=no # Keyword BOOLEAN
- ###< create table crash_me10 (BOOLEAN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_both=yes # Keyword BOTH
- ###< create table crash_me10 (BOTH int not null)
- ###> execute error: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 'BOTH int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_breadth=no # Keyword BREADTH
- ###< create table crash_me10 (BREADTH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_by=yes # Keyword BY
- ###< create table crash_me10 (BY int not null)
- ###> execute error: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 'BY int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_call=no # Keyword CALL
- ###< create table crash_me10 (CALL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_call=yes # Keyword CALL
reserved_word_ansi-92/99_cascade=yes # Keyword CASCADE
- ###< create table crash_me10 (CASCADE int not null)
- ###> execute error: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 'CASCADE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_cascaded=no # Keyword CASCADED
- ###< create table crash_me10 (CASCADED int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_case=yes # Keyword CASE
- ###< create table crash_me10 (CASE int not null)
- ###> execute error: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 'CASE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_cast=no # Keyword CAST
- ###< create table crash_me10 (CAST int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_catalog=no # Keyword CATALOG
- ###< create table crash_me10 (CATALOG int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_char=yes # Keyword CHAR
- ###< create table crash_me10 (CHAR int not null)
- ###> execute error: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 'CHAR int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_character=yes # Keyword CHARACTER
- ###< create table crash_me10 (CHARACTER int not null)
- ###> execute error: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 'CHARACTER int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_check=yes # Keyword CHECK
- ###< create table crash_me10 (CHECK int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_close=no # Keyword CLOSE
- ###< create table crash_me10 (CLOSE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_collate=yes # Keyword COLLATE
- ###< create table crash_me10 (COLLATE int not null)
- ###> execute error: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 'COLLATE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_collation=no # Keyword COLLATION
- ###< create table crash_me10 (COLLATION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_column=yes # Keyword COLUMN
- ###< create table crash_me10 (COLUMN int not null)
- ###> execute error: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 'COLUMN int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_commit=no # Keyword COMMIT
- ###< create table crash_me10 (COMMIT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_completion=no # Keyword COMPLETION
- ###< create table crash_me10 (COMPLETION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_connect=no # Keyword CONNECT
- ###< create table crash_me10 (CONNECT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_connection=no # Keyword CONNECTION
- ###< create table crash_me10 (CONNECTION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_connection=yes # Keyword CONNECTION
reserved_word_ansi-92/99_constraint=yes # Keyword CONSTRAINT
- ###< create table crash_me10 (CONSTRAINT int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_constraints=no # Keyword CONSTRAINTS
- ###< create table crash_me10 (CONSTRAINTS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_continue=no # Keyword CONTINUE
- ###< create table crash_me10 (CONTINUE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_continue=yes # Keyword CONTINUE
reserved_word_ansi-92/99_corresponding=no # Keyword CORRESPONDING
- ###< create table crash_me10 (CORRESPONDING int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_create=yes # Keyword CREATE
- ###< create table crash_me10 (CREATE int not null)
- ###> execute error: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 'CREATE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_cross=yes # Keyword CROSS
- ###< create table crash_me10 (CROSS int not null)
- ###> execute error: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 'CROSS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_current=no # Keyword CURRENT
- ###< create table crash_me10 (CURRENT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_current_date=yes # Keyword CURRENT_DATE
- ###< create table crash_me10 (CURRENT_DATE int not null)
- ###> execute error: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 'CURRENT_DATE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_current_time=yes # Keyword CURRENT_TIME
- ###< create table crash_me10 (CURRENT_TIME int not null)
- ###> execute error: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 'CURRENT_TIME int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_current_timestamp=yes # Keyword CURRENT_TIMESTAMP
- ###< create table crash_me10 (CURRENT_TIMESTAMP int not null)
- ###> execute error: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 'CURRENT_TIMESTAMP int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_current_user=no # Keyword CURRENT_USER
- ###< create table crash_me10 (CURRENT_USER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_cursor=no # Keyword CURSOR
- ###< create table crash_me10 (CURSOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_current_user=yes # Keyword CURRENT_USER
+reserved_word_ansi-92/99_cursor=yes # Keyword CURSOR
reserved_word_ansi-92/99_cycle=no # Keyword CYCLE
- ###< create table crash_me10 (CYCLE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_data=no # Keyword DATA
- ###< create table crash_me10 (DATA int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_date=no # Keyword DATE
- ###< create table crash_me10 (DATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_day=no # Keyword DAY
- ###< create table crash_me10 (DAY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_deallocate=no # Keyword DEALLOCATE
- ###< create table crash_me10 (DEALLOCATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_dec=yes # Keyword DEC
- ###< create table crash_me10 (DEC int not null)
- ###> execute error: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 'DEC int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_decimal=yes # Keyword DECIMAL
- ###< create table crash_me10 (DECIMAL int not null)
- ###> execute error: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 'DECIMAL int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_declare=no # Keyword DECLARE
- ###< create table crash_me10 (DECLARE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_declare=yes # Keyword DECLARE
reserved_word_ansi-92/99_default=yes # Keyword DEFAULT
- ###< create table crash_me10 (DEFAULT int not null)
- ###> execute error: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 int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_deferrable=no # Keyword DEFERRABLE
- ###< create table crash_me10 (DEFERRABLE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_deferred=no # Keyword DEFERRED
- ###< create table crash_me10 (DEFERRED int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_delete=yes # Keyword DELETE
- ###< create table crash_me10 (DELETE int not null)
- ###> execute error: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 'DELETE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_depth=no # Keyword DEPTH
- ###< create table crash_me10 (DEPTH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_desc=yes # Keyword DESC
- ###< create table crash_me10 (DESC int not null)
- ###> execute error: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 'DESC int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_describe=yes # Keyword DESCRIBE
- ###< create table crash_me10 (DESCRIBE int not null)
- ###> execute error: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 'DESCRIBE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_descriptor=no # Keyword DESCRIPTOR
- ###< create table crash_me10 (DESCRIPTOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_diagnostics=no # Keyword DIAGNOSTICS
- ###< create table crash_me10 (DIAGNOSTICS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_dictionary=no # Keyword DICTIONARY
- ###< create table crash_me10 (DICTIONARY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_disconnect=no # Keyword DISCONNECT
- ###< create table crash_me10 (DISCONNECT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_distinct=yes # Keyword DISTINCT
- ###< create table crash_me10 (DISTINCT int not null)
- ###> execute error: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 'DISTINCT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_domain=no # Keyword DOMAIN
- ###< create table crash_me10 (DOMAIN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_double=yes # Keyword DOUBLE
- ###< create table crash_me10 (DOUBLE int not null)
- ###> execute error: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 'DOUBLE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_drop=yes # Keyword DROP
- ###< create table crash_me10 (DROP int not null)
- ###> execute error: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 'DROP int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_each=no # Keyword EACH
- ###< create table crash_me10 (EACH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_each=yes # Keyword EACH
reserved_word_ansi-92/99_else=yes # Keyword ELSE
- ###< create table crash_me10 (ELSE int not null)
- ###> execute error: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 'ELSE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_elseif=no # Keyword ELSEIF
- ###< create table crash_me10 (ELSEIF int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_elseif=yes # Keyword ELSEIF
reserved_word_ansi-92/99_end=no # Keyword END
- ###< create table crash_me10 (END int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_end-exec=yes # Keyword END-EXEC
- ###< create table crash_me10 (END-EXEC int not null)
- ###> execute error: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 '-EXEC int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_equals=no # Keyword EQUALS
- ###< create table crash_me10 (EQUALS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_escape=no # Keyword ESCAPE
- ###< create table crash_me10 (ESCAPE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_except=no # Keyword EXCEPT
- ###< create table crash_me10 (EXCEPT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_exception=no # Keyword EXCEPTION
- ###< create table crash_me10 (EXCEPTION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_exec=no # Keyword EXEC
- ###< create table crash_me10 (EXEC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_execute=no # Keyword EXECUTE
- ###< create table crash_me10 (EXECUTE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_external=no # Keyword EXTERNAL
- ###< create table crash_me10 (EXTERNAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_false=yes # Keyword FALSE
- ###< create table crash_me10 (FALSE int not null)
- ###> execute error: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 'FALSE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_fetch=no # Keyword FETCH
- ###< create table crash_me10 (FETCH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_fetch=yes # Keyword FETCH
reserved_word_ansi-92/99_first=no # Keyword FIRST
- ###< create table crash_me10 (FIRST int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_float=yes # Keyword FLOAT
- ###< create table crash_me10 (FLOAT int not null)
- ###> execute error: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 'FLOAT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_for=yes # Keyword FOR
- ###< create table crash_me10 (FOR int not null)
- ###> execute error: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 'FOR int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_foreign=yes # Keyword FOREIGN
- ###< create table crash_me10 (FOREIGN int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_found=no # Keyword FOUND
- ###< create table crash_me10 (FOUND int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_from=yes # Keyword FROM
- ###< create table crash_me10 (FROM int not null)
- ###> execute error: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 int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_full=no # Keyword FULL
- ###< create table crash_me10 (FULL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_general=no # Keyword GENERAL
- ###< create table crash_me10 (GENERAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_get=no # Keyword GET
- ###< create table crash_me10 (GET int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_global=no # Keyword GLOBAL
- ###< create table crash_me10 (GLOBAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_go=no # Keyword GO
- ###< create table crash_me10 (GO int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_goto=no # Keyword GOTO
- ###< create table crash_me10 (GOTO int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_goto=yes # Keyword GOTO
reserved_word_ansi-92/99_grant=yes # Keyword GRANT
- ###< create table crash_me10 (GRANT int not null)
- ###> execute error: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 'GRANT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_group=yes # Keyword GROUP
- ###< create table crash_me10 (GROUP int not null)
- ###> execute error: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 'GROUP int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_having=yes # Keyword HAVING
- ###< create table crash_me10 (HAVING int not null)
- ###> execute error: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 'HAVING int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_hour=no # Keyword HOUR
- ###< create table crash_me10 (HOUR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_identity=no # Keyword IDENTITY
- ###< create table crash_me10 (IDENTITY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_if=yes # Keyword IF
- ###< create table crash_me10 (IF int not null)
- ###> execute error: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 'IF int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_ignore=yes # Keyword IGNORE
- ###< create table crash_me10 (IGNORE int not null)
- ###> execute error: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 'IGNORE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_immediate=no # Keyword IMMEDIATE
- ###< create table crash_me10 (IMMEDIATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_in=yes # Keyword IN
- ###< create table crash_me10 (IN int not null)
- ###> execute error: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 'IN int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_indicator=no # Keyword INDICATOR
- ###< create table crash_me10 (INDICATOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_initially=no # Keyword INITIALLY
- ###< create table crash_me10 (INITIALLY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_inner=yes # Keyword INNER
- ###< create table crash_me10 (INNER int not null)
- ###> execute error: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 'INNER int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_input=no # Keyword INPUT
- ###< create table crash_me10 (INPUT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_insert=yes # Keyword INSERT
- ###< create table crash_me10 (INSERT int not null)
- ###> execute error: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 'INSERT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_int=yes # Keyword INT
- ###< create table crash_me10 (INT int not null)
- ###> execute error: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 'INT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_integer=yes # Keyword INTEGER
- ###< create table crash_me10 (INTEGER int not null)
- ###> execute error: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 'INTEGER int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_intersect=no # Keyword INTERSECT
- ###< create table crash_me10 (INTERSECT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_interval=yes # Keyword INTERVAL
- ###< create table crash_me10 (INTERVAL int not null)
- ###> execute error: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 'INTERVAL int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_into=yes # Keyword INTO
- ###< create table crash_me10 (INTO int not null)
- ###> execute error: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 'INTO int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_is=yes # Keyword IS
- ###< create table crash_me10 (IS int not null)
- ###> execute error: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 'IS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_isolation=no # Keyword ISOLATION
- ###< create table crash_me10 (ISOLATION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_join=yes # Keyword JOIN
- ###< create table crash_me10 (JOIN int not null)
- ###> execute error: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 'JOIN int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_key=yes # Keyword KEY
- ###< create table crash_me10 (KEY int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_language=no # Keyword LANGUAGE
- ###< create table crash_me10 (LANGUAGE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_last=no # Keyword LAST
- ###< create table crash_me10 (LAST int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_leading=yes # Keyword LEADING
- ###< create table crash_me10 (LEADING int not null)
- ###> execute error: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 'LEADING int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_leave=no # Keyword LEAVE
- ###< create table crash_me10 (LEAVE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_leave=yes # Keyword LEAVE
reserved_word_ansi-92/99_left=yes # Keyword LEFT
- ###< create table crash_me10 (LEFT int not null)
- ###> execute error: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 'LEFT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_less=no # Keyword LESS
- ###< create table crash_me10 (LESS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_level=no # Keyword LEVEL
- ###< create table crash_me10 (LEVEL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_like=yes # Keyword LIKE
- ###< create table crash_me10 (LIKE int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_limit=yes # Keyword LIMIT
- ###< create table crash_me10 (LIMIT int not null)
- ###> execute error: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 'LIMIT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_local=no # Keyword LOCAL
- ###< create table crash_me10 (LOCAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_loop=no # Keyword LOOP
- ###< create table crash_me10 (LOOP int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_loop=yes # Keyword LOOP
reserved_word_ansi-92/99_match=yes # Keyword MATCH
- ###< create table crash_me10 (MATCH int not null)
- ###> execute error: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 'MATCH int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_minute=no # Keyword MINUTE
- ###< create table crash_me10 (MINUTE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_modify=no # Keyword MODIFY
- ###< create table crash_me10 (MODIFY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_module=no # Keyword MODULE
- ###< create table crash_me10 (MODULE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_month=no # Keyword MONTH
- ###< create table crash_me10 (MONTH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_names=no # Keyword NAMES
- ###< create table crash_me10 (NAMES int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_national=no # Keyword NATIONAL
- ###< create table crash_me10 (NATIONAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_natural=yes # Keyword NATURAL
- ###< create table crash_me10 (NATURAL int not null)
- ###> execute error: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 'NATURAL int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_nchar=no # Keyword NCHAR
- ###< create table crash_me10 (NCHAR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_new=no # Keyword NEW
- ###< create table crash_me10 (NEW int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_next=no # Keyword NEXT
- ###< create table crash_me10 (NEXT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_no=no # Keyword NO
- ###< create table crash_me10 (NO int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_none=no # Keyword NONE
- ###< create table crash_me10 (NONE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_not=yes # Keyword NOT
- ###< create table crash_me10 (NOT int not null)
- ###> execute error: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 'NOT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_null=yes # Keyword NULL
- ###< create table crash_me10 (NULL int not null)
- ###> execute error: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 int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_numeric=yes # Keyword NUMERIC
- ###< create table crash_me10 (NUMERIC int not null)
- ###> execute error: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 'NUMERIC int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_object=no # Keyword OBJECT
- ###< create table crash_me10 (OBJECT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_of=no # Keyword OF
- ###< create table crash_me10 (OF int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_off=no # Keyword OFF
- ###< create table crash_me10 (OFF int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_old=no # Keyword OLD
- ###< create table crash_me10 (OLD int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_on=yes # Keyword ON
- ###< create table crash_me10 (ON int not null)
- ###> execute error: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 'ON int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_only=no # Keyword ONLY
- ###< create table crash_me10 (ONLY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_open=no # Keyword OPEN
- ###< create table crash_me10 (OPEN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_operation=no # Keyword OPERATION
- ###< create table crash_me10 (OPERATION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_option=yes # Keyword OPTION
- ###< create table crash_me10 (OPTION int not null)
- ###> execute error: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 'OPTION int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_or=yes # Keyword OR
- ###< create table crash_me10 (OR int not null)
- ###> execute error: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 'OR int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_order=yes # Keyword ORDER
- ###< create table crash_me10 (ORDER int not null)
- ###> execute error: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 'ORDER int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_outer=yes # Keyword OUTER
- ###< create table crash_me10 (OUTER int not null)
- ###> execute error: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 'OUTER int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_output=no # Keyword OUTPUT
- ###< create table crash_me10 (OUTPUT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_pad=no # Keyword PAD
- ###< create table crash_me10 (PAD int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_parameters=no # Keyword PARAMETERS
- ###< create table crash_me10 (PARAMETERS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_partial=no # Keyword PARTIAL
- ###< create table crash_me10 (PARTIAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_precision=yes # Keyword PRECISION
- ###< create table crash_me10 (PRECISION int not null)
- ###> execute error: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 'PRECISION int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_preorder=no # Keyword PREORDER
- ###< create table crash_me10 (PREORDER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_prepare=no # Keyword PREPARE
- ###< create table crash_me10 (PREPARE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_preserve=no # Keyword PRESERVE
- ###< create table crash_me10 (PRESERVE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_primary=yes # Keyword PRIMARY
- ###< create table crash_me10 (PRIMARY int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_prior=no # Keyword PRIOR
- ###< create table crash_me10 (PRIOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_privileges=yes # Keyword PRIVILEGES
- ###< create table crash_me10 (PRIVILEGES int not null)
- ###> execute error: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 'PRIVILEGES int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_privileges=no # Keyword PRIVILEGES
reserved_word_ansi-92/99_procedure=yes # Keyword PROCEDURE
- ###< create table crash_me10 (PROCEDURE int not null)
- ###> execute error: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 'PROCEDURE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_public=no # Keyword PUBLIC
- ###< create table crash_me10 (PUBLIC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_read=yes # Keyword READ
- ###< create table crash_me10 (READ int not null)
- ###> execute error: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 'READ int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_real=yes # Keyword REAL
- ###< create table crash_me10 (REAL int not null)
- ###> execute error: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 'REAL int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_recursive=no # Keyword RECURSIVE
- ###< create table crash_me10 (RECURSIVE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_ref=no # Keyword REF
- ###< create table crash_me10 (REF int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_references=yes # Keyword REFERENCES
- ###< create table crash_me10 (REFERENCES int not null)
- ###> execute error: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 'REFERENCES int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_referencing=no # Keyword REFERENCING
- ###< create table crash_me10 (REFERENCING int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_relative=no # Keyword RELATIVE
- ###< create table crash_me10 (RELATIVE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_resignal=no # Keyword RESIGNAL
- ###< create table crash_me10 (RESIGNAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_restrict=yes # Keyword RESTRICT
- ###< create table crash_me10 (RESTRICT int not null)
- ###> execute error: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 'RESTRICT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_return=no # Keyword RETURN
- ###< create table crash_me10 (RETURN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_returns=yes # Keyword RETURNS
- ###< create table crash_me10 (RETURNS int not null)
- ###> execute error: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 'RETURNS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
+reserved_word_ansi-92/99_return=yes # Keyword RETURN
+reserved_word_ansi-92/99_returns=no # Keyword RETURNS
reserved_word_ansi-92/99_revoke=yes # Keyword REVOKE
- ###< create table crash_me10 (REVOKE int not null)
- ###> execute error: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 'REVOKE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_right=yes # Keyword RIGHT
- ###< create table crash_me10 (RIGHT int not null)
- ###> execute error: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 'RIGHT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_role=no # Keyword ROLE
- ###< create table crash_me10 (ROLE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_rollback=no # Keyword ROLLBACK
- ###< create table crash_me10 (ROLLBACK int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_routine=no # Keyword ROUTINE
- ###< create table crash_me10 (ROUTINE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_row=no # Keyword ROW
- ###< create table crash_me10 (ROW int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_rows=no # Keyword ROWS
- ###< create table crash_me10 (ROWS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_savepoint=no # Keyword SAVEPOINT
- ###< create table crash_me10 (SAVEPOINT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_schema=no # Keyword SCHEMA
- ###< create table crash_me10 (SCHEMA int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_schema=yes # Keyword SCHEMA
reserved_word_ansi-92/99_scroll=no # Keyword SCROLL
- ###< create table crash_me10 (SCROLL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_search=no # Keyword SEARCH
- ###< create table crash_me10 (SEARCH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_second=no # Keyword SECOND
- ###< create table crash_me10 (SECOND int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_section=no # Keyword SECTION
- ###< create table crash_me10 (SECTION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_select=yes # Keyword SELECT
- ###< create table crash_me10 (SELECT int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_sequence=no # Keyword SEQUENCE
- ###< create table crash_me10 (SEQUENCE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_session=no # Keyword SESSION
- ###< create table crash_me10 (SESSION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_session_user=no # Keyword SESSION_USER
- ###< create table crash_me10 (SESSION_USER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_set=yes # Keyword SET
- ###< create table crash_me10 (SET int not null)
- ###> execute error: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 'SET int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_signal=no # Keyword SIGNAL
- ###< create table crash_me10 (SIGNAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_size=no # Keyword SIZE
- ###< create table crash_me10 (SIZE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_smallint=yes # Keyword SMALLINT
- ###< create table crash_me10 (SMALLINT int not null)
- ###> execute error: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 'SMALLINT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_some=no # Keyword SOME
- ###< create table crash_me10 (SOME int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_space=no # Keyword SPACE
- ###< create table crash_me10 (SPACE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_sql=no # Keyword SQL
- ###< create table crash_me10 (SQL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_sqlexception=no # Keyword SQLEXCEPTION
- ###< create table crash_me10 (SQLEXCEPTION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_sqlstate=no # Keyword SQLSTATE
- ###< create table crash_me10 (SQLSTATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_sqlwarning=no # Keyword SQLWARNING
- ###< create table crash_me10 (SQLWARNING int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_sql=yes # Keyword SQL
+reserved_word_ansi-92/99_sqlexception=yes # Keyword SQLEXCEPTION
+reserved_word_ansi-92/99_sqlstate=yes # Keyword SQLSTATE
+reserved_word_ansi-92/99_sqlwarning=yes # Keyword SQLWARNING
reserved_word_ansi-92/99_structure=no # Keyword STRUCTURE
- ###< create table crash_me10 (STRUCTURE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_system_user=no # Keyword SYSTEM_USER
- ###< create table crash_me10 (SYSTEM_USER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_table=yes # Keyword TABLE
- ###< create table crash_me10 (TABLE int not null)
- ###> execute error: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 'TABLE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_temporary=no # Keyword TEMPORARY
- ###< create table crash_me10 (TEMPORARY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_then=yes # Keyword THEN
- ###< create table crash_me10 (THEN int not null)
- ###> execute error: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 'THEN int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_time=no # Keyword TIME
- ###< create table crash_me10 (TIME int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_timestamp=no # Keyword TIMESTAMP
- ###< create table crash_me10 (TIMESTAMP int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_timezone_hour=no # Keyword TIMEZONE_HOUR
- ###< create table crash_me10 (TIMEZONE_HOUR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_timezone_minute=no # Keyword TIMEZONE_MINUTE
- ###< create table crash_me10 (TIMEZONE_MINUTE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_to=yes # Keyword TO
- ###< create table crash_me10 (TO int not null)
- ###> execute error: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 'TO int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_trailing=yes # Keyword TRAILING
- ###< create table crash_me10 (TRAILING int not null)
- ###> execute error: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 'TRAILING int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_transaction=no # Keyword TRANSACTION
- ###< create table crash_me10 (TRANSACTION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_translation=no # Keyword TRANSLATION
- ###< create table crash_me10 (TRANSLATION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi-92/99_trigger=no # Keyword TRIGGER
- ###< create table crash_me10 (TRIGGER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_trigger=yes # Keyword TRIGGER
reserved_word_ansi-92/99_true=yes # Keyword TRUE
- ###< create table crash_me10 (TRUE int not null)
- ###> execute error: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 'TRUE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_under=no # Keyword UNDER
- ###< create table crash_me10 (UNDER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_union=yes # Keyword UNION
- ###< create table crash_me10 (UNION int not null)
- ###> execute error: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 'UNION int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_unique=yes # Keyword UNIQUE
- ###< create table crash_me10 (UNIQUE int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_unknown=no # Keyword UNKNOWN
- ###< create table crash_me10 (UNKNOWN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_update=yes # Keyword UPDATE
- ###< create table crash_me10 (UPDATE int not null)
- ###> execute error: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 'UPDATE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_usage=yes # Keyword USAGE
- ###< create table crash_me10 (USAGE int not null)
- ###> execute error: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 'USAGE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_user=no # Keyword USER
- ###< create table crash_me10 (USER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_using=yes # Keyword USING
- ###< create table crash_me10 (USING int not null)
- ###> execute error: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 'USING int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_value=no # Keyword VALUE
- ###< create table crash_me10 (VALUE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_values=yes # Keyword VALUES
- ###< create table crash_me10 (VALUES int not null)
- ###> execute error: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 'VALUES int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_varchar=yes # Keyword VARCHAR
- ###< create table crash_me10 (VARCHAR int not null)
- ###> execute error: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 'VARCHAR int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_variable=no # Keyword VARIABLE
- ###< create table crash_me10 (VARIABLE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_varying=yes # Keyword VARYING
- ###< create table crash_me10 (VARYING int not null)
- ###> execute error: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 'VARYING int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_view=no # Keyword VIEW
- ###< create table crash_me10 (VIEW int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_when=yes # Keyword WHEN
- ###< create table crash_me10 (WHEN int not null)
- ###> execute error: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 'WHEN int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_whenever=no # Keyword WHENEVER
- ###< create table crash_me10 (WHENEVER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_where=yes # Keyword WHERE
- ###< create table crash_me10 (WHERE int not null)
- ###> execute error: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 int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi-92/99_while=no # Keyword WHILE
- ###< create table crash_me10 (WHILE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi-92/99_while=yes # Keyword WHILE
reserved_word_ansi-92/99_with=yes # Keyword WITH
- ###< create table crash_me10 (WITH int not null)
- ###> execute error: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 'WITH int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_without=no # Keyword WITHOUT
- ###< create table crash_me10 (WITHOUT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_work=no # Keyword WORK
- ###< create table crash_me10 (WORK int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_write=yes # Keyword WRITE
- ###< create table crash_me10 (WRITE int not null)
- ###> execute error: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 'WRITE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi-92/99_year=no # Keyword YEAR
- ###< create table crash_me10 (YEAR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi-92/99_zone=no # Keyword ZONE
- ###< create table crash_me10 (ZONE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_async=no # Keyword ASYNC
- ###< create table crash_me10 (ASYNC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_avg=no # Keyword AVG
- ###< create table crash_me10 (AVG int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_between=yes # Keyword BETWEEN
- ###< create table crash_me10 (BETWEEN int not null)
- ###> execute error: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 'BETWEEN int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi92_bit_length=no # Keyword BIT_LENGTH
- ###< create table crash_me10 (BIT_LENGTH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_char_length=no # Keyword CHAR_LENGTH
- ###< create table crash_me10 (CHAR_LENGTH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_character_length=no # Keyword CHARACTER_LENGTH
- ###< create table crash_me10 (CHARACTER_LENGTH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_coalesce=no # Keyword COALESCE
- ###< create table crash_me10 (COALESCE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_convert=yes # Keyword CONVERT
- ###< create table crash_me10 (CONVERT int not null)
- ###> execute error: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 'CONVERT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi92_count=no # Keyword COUNT
- ###< create table crash_me10 (COUNT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_exists=yes # Keyword EXISTS
- ###< create table crash_me10 (EXISTS int not null)
- ###> execute error: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 'EXISTS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi92_extract=no # Keyword EXTRACT
- ###< create table crash_me10 (EXTRACT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi92_insensitive=no # Keyword INSENSITIVE
- ###< create table crash_me10 (INSENSITIVE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_insensitive=yes # Keyword INSENSITIVE
reserved_word_ansi92_lower=no # Keyword LOWER
- ###< create table crash_me10 (LOWER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_max=no # Keyword MAX
- ###< create table crash_me10 (MAX int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_min=no # Keyword MIN
- ###< create table crash_me10 (MIN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_nullif=no # Keyword NULLIF
- ###< create table crash_me10 (NULLIF int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_octet_length=no # Keyword OCTET_LENGTH
- ###< create table crash_me10 (OCTET_LENGTH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_oid=no # Keyword OID
- ###< create table crash_me10 (OID int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_operators=no # Keyword OPERATORS
- ###< create table crash_me10 (OPERATORS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_others=no # Keyword OTHERS
- ###< create table crash_me10 (OTHERS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_overlaps=no # Keyword OVERLAPS
- ###< create table crash_me10 (OVERLAPS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_pendant=no # Keyword PENDANT
- ###< create table crash_me10 (PENDANT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_position=no # Keyword POSITION
- ###< create table crash_me10 (POSITION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_private=no # Keyword PRIVATE
- ###< create table crash_me10 (PRIVATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_protected=no # Keyword PROTECTED
- ###< create table crash_me10 (PROTECTED int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_replace=yes # Keyword REPLACE
- ###< create table crash_me10 (REPLACE int not null)
- ###> execute error: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 'REPLACE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_ansi92_sensitive=no # Keyword SENSITIVE
- ###< create table crash_me10 (SENSITIVE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi92_sensitive=yes # Keyword SENSITIVE
reserved_word_ansi92_similar=no # Keyword SIMILAR
- ###< create table crash_me10 (SIMILAR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_sqlcode=no # Keyword SQLCODE
- ###< create table crash_me10 (SQLCODE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_sqlerror=no # Keyword SQLERROR
- ###< create table crash_me10 (SQLERROR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_substring=no # Keyword SUBSTRING
- ###< create table crash_me10 (SUBSTRING int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_sum=no # Keyword SUM
- ###< create table crash_me10 (SUM int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_test=no # Keyword TEST
- ###< create table crash_me10 (TEST int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_there=no # Keyword THERE
- ###< create table crash_me10 (THERE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_translate=no # Keyword TRANSLATE
- ###< create table crash_me10 (TRANSLATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_trim=no # Keyword TRIM
- ###< create table crash_me10 (TRIM int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_type=no # Keyword TYPE
- ###< create table crash_me10 (TYPE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_upper=no # Keyword UPPER
- ###< create table crash_me10 (UPPER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_virtual=no # Keyword VIRTUAL
- ###< create table crash_me10 (VIRTUAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_visible=no # Keyword VISIBLE
- ###< create table crash_me10 (VISIBLE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi92_wait=no # Keyword WAIT
- ###< create table crash_me10 (WAIT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_admin=no # Keyword ADMIN
- ###< create table crash_me10 (ADMIN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_aggregate=no # Keyword AGGREGATE
- ###< create table crash_me10 (AGGREGATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_array=no # Keyword ARRAY
- ###< create table crash_me10 (ARRAY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_binary=yes # Keyword BINARY
- ###< create table crash_me10 (BINARY int not null)
- ###> execute error: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 'BINARY int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_blob=yes # Keyword BLOB
- ###< create table crash_me10 (BLOB int not null)
- ###> execute error: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 'BLOB int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_class=no # Keyword CLASS
- ###< create table crash_me10 (CLASS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_clob=no # Keyword CLOB
- ###< create table crash_me10 (CLOB int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_condition=no # Keyword CONDITION
- ###< create table crash_me10 (CONDITION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_condition=yes # Keyword CONDITION
reserved_word_ansi99_constructor=no # Keyword CONSTRUCTOR
- ###< create table crash_me10 (CONSTRUCTOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_contains=no # Keyword CONTAINS
- ###< create table crash_me10 (CONTAINS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_cube=no # Keyword CUBE
- ###< create table crash_me10 (CUBE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_current_path=no # Keyword CURRENT_PATH
- ###< create table crash_me10 (CURRENT_PATH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_current_role=no # Keyword CURRENT_ROLE
- ###< create table crash_me10 (CURRENT_ROLE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_datalink=no # Keyword DATALINK
- ###< create table crash_me10 (DATALINK int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_deref=no # Keyword DEREF
- ###< create table crash_me10 (DEREF int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_destroy=no # Keyword DESTROY
- ###< create table crash_me10 (DESTROY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_destructor=no # Keyword DESTRUCTOR
- ###< create table crash_me10 (DESTRUCTOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_deterministic=no # Keyword DETERMINISTIC
- ###< create table crash_me10 (DETERMINISTIC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_deterministic=yes # Keyword DETERMINISTIC
reserved_word_ansi99_do=no # Keyword DO
- ###< create table crash_me10 (DO int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_dynamic=no # Keyword DYNAMIC
- ###< create table crash_me10 (DYNAMIC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_every=no # Keyword EVERY
- ###< create table crash_me10 (EVERY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_exit=no # Keyword EXIT
- ###< create table crash_me10 (EXIT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_exit=yes # Keyword EXIT
reserved_word_ansi99_expand=no # Keyword EXPAND
- ###< create table crash_me10 (EXPAND int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_expanding=no # Keyword EXPANDING
- ###< create table crash_me10 (EXPANDING int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_free=no # Keyword FREE
- ###< create table crash_me10 (FREE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_function=no # Keyword FUNCTION
- ###< create table crash_me10 (FUNCTION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_grouping=no # Keyword GROUPING
- ###< create table crash_me10 (GROUPING int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_handler=no # Keyword HANDLER
- ###< create table crash_me10 (HANDLER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_hast=no # Keyword HAST
- ###< create table crash_me10 (HAST int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_host=no # Keyword HOST
- ###< create table crash_me10 (HOST int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_initialize=no # Keyword INITIALIZE
- ###< create table crash_me10 (INITIALIZE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_inout=no # Keyword INOUT
- ###< create table crash_me10 (INOUT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_iterate=no # Keyword ITERATE
- ###< create table crash_me10 (ITERATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_inout=yes # Keyword INOUT
+reserved_word_ansi99_iterate=yes # Keyword ITERATE
reserved_word_ansi99_large=no # Keyword LARGE
- ###< create table crash_me10 (LARGE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_lateral=no # Keyword LATERAL
- ###< create table crash_me10 (LATERAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_localtime=yes # Keyword LOCALTIME
- ###< create table crash_me10 (LOCALTIME int not null)
- ###> execute error: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 'LOCALTIME int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_localtimestamp=yes # Keyword LOCALTIMESTAMP
- ###< create table crash_me10 (LOCALTIMESTAMP int not null)
- ###> execute error: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 'LOCALTIMESTAMP int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_ansi99_locator=no # Keyword LOCATOR
- ###< create table crash_me10 (LOCATOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_meets=no # Keyword MEETS
- ###< create table crash_me10 (MEETS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_modifies=no # Keyword MODIFIES
- ###< create table crash_me10 (MODIFIES int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_modifies=yes # Keyword MODIFIES
reserved_word_ansi99_nclob=no # Keyword NCLOB
- ###< create table crash_me10 (NCLOB int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_normalize=no # Keyword NORMALIZE
- ###< create table crash_me10 (NORMALIZE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_ordinality=no # Keyword ORDINALITY
- ###< create table crash_me10 (ORDINALITY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_out=no # Keyword OUT
- ###< create table crash_me10 (OUT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_out=yes # Keyword OUT
reserved_word_ansi99_parameter=no # Keyword PARAMETER
- ###< create table crash_me10 (PARAMETER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_path=no # Keyword PATH
- ###< create table crash_me10 (PATH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_period=no # Keyword PERIOD
- ###< create table crash_me10 (PERIOD int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_postfix=no # Keyword POSTFIX
- ###< create table crash_me10 (POSTFIX int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_precedes=no # Keyword PRECEDES
- ###< create table crash_me10 (PRECEDES int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_prefix=no # Keyword PREFIX
- ###< create table crash_me10 (PREFIX int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_reads=no # Keyword READS
- ###< create table crash_me10 (READS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_reads=yes # Keyword READS
reserved_word_ansi99_redo=no # Keyword REDO
- ###< create table crash_me10 (REDO int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_repeat=no # Keyword REPEAT
- ###< create table crash_me10 (REPEAT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_repeat=yes # Keyword REPEAT
reserved_word_ansi99_result=no # Keyword RESULT
- ###< create table crash_me10 (RESULT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_rollup=no # Keyword ROLLUP
- ###< create table crash_me10 (ROLLUP int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_sets=no # Keyword SETS
- ###< create table crash_me10 (SETS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_specific=no # Keyword SPECIFIC
- ###< create table crash_me10 (SPECIFIC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_specific=yes # Keyword SPECIFIC
reserved_word_ansi99_specifictype=no # Keyword SPECIFICTYPE
- ###< create table crash_me10 (SPECIFICTYPE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_start=no # Keyword START
- ###< create table crash_me10 (START int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_state=no # Keyword STATE
- ###< create table crash_me10 (STATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_static=no # Keyword STATIC
- ###< create table crash_me10 (STATIC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_succeeds=no # Keyword SUCCEEDS
- ###< create table crash_me10 (SUCCEEDS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_terminate=no # Keyword TERMINATE
- ###< create table crash_me10 (TERMINATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_than=no # Keyword THAN
- ###< create table crash_me10 (THAN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_ansi99_treat=no # Keyword TREAT
- ###< create table crash_me10 (TREAT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_ansi99_undo=no # Keyword UNDO
- ###< create table crash_me10 (UNDO int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
+reserved_word_ansi99_undo=yes # Keyword UNDO
reserved_word_ansi99_until=no # Keyword UNTIL
- ###< create table crash_me10 (UNTIL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_access=no # Keyword ACCESS
- ###< create table crash_me10 (ACCESS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_analyze=yes # Keyword ANALYZE
- ###< create table crash_me10 (ANALYZE int not null)
- ###> execute error: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 'ANALYZE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_audit=no # Keyword AUDIT
- ###< create table crash_me10 (AUDIT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_auto_increment=no # Keyword AUTO_INCREMENT
- ###< create table crash_me10 (AUTO_INCREMENT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_backup=no # Keyword BACKUP
- ###< create table crash_me10 (BACKUP int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_bdb=no # Keyword BDB
- ###< create table crash_me10 (BDB int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_berkeleydb=no # Keyword BERKELEYDB
- ###< create table crash_me10 (BERKELEYDB int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_bigint=yes # Keyword BIGINT
- ###< create table crash_me10 (BIGINT int not null)
- ###> execute error: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 'BIGINT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_break=no # Keyword BREAK
- ###< create table crash_me10 (BREAK int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_browse=no # Keyword BROWSE
- ###< create table crash_me10 (BROWSE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_btree=no # Keyword BTREE
- ###< create table crash_me10 (BTREE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_bulk=no # Keyword BULK
- ###< create table crash_me10 (BULK int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_change=yes # Keyword CHANGE
- ###< create table crash_me10 (CHANGE int not null)
- ###> execute error: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 'CHANGE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_checkpoint=no # Keyword CHECKPOINT
- ###< create table crash_me10 (CHECKPOINT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_cluster=no # Keyword CLUSTER
- ###< create table crash_me10 (CLUSTER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_clustered=no # Keyword CLUSTERED
- ###< create table crash_me10 (CLUSTERED int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_extra_columns=yes # Keyword COLUMNS
- ###< create table crash_me10 (COLUMNS int not null)
- ###> execute error: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 'COLUMNS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_columns=no # Keyword COLUMNS
reserved_word_extra_comment=no # Keyword COMMENT
- ###< create table crash_me10 (COMMENT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_compress=no # Keyword COMPRESS
- ###< create table crash_me10 (COMPRESS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_compute=no # Keyword COMPUTE
- ###< create table crash_me10 (COMPUTE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_containstable=no # Keyword CONTAINSTABLE
- ###< create table crash_me10 (CONTAINSTABLE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_database=yes # Keyword DATABASE
- ###< create table crash_me10 (DATABASE int not null)
- ###> execute error: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 'DATABASE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_databases=yes # Keyword DATABASES
- ###< create table crash_me10 (DATABASES int not null)
- ###> execute error: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 'DATABASES int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_day_hour=yes # Keyword DAY_HOUR
- ###< create table crash_me10 (DAY_HOUR int not null)
- ###> execute error: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 'DAY_HOUR int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_day_minute=yes # Keyword DAY_MINUTE
- ###< create table crash_me10 (DAY_MINUTE int not null)
- ###> execute error: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 'DAY_MINUTE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_day_second=yes # Keyword DAY_SECOND
- ###< create table crash_me10 (DAY_SECOND int not null)
- ###> execute error: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 'DAY_SECOND int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_dbcc=no # Keyword DBCC
- ###< create table crash_me10 (DBCC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_delayed=yes # Keyword DELAYED
- ###< create table crash_me10 (DELAYED int not null)
- ###> execute error: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 'DELAYED int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_deny=no # Keyword DENY
- ###< create table crash_me10 (DENY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_disk=no # Keyword DISK
- ###< create table crash_me10 (DISK int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_distinctrow=yes # Keyword DISTINCTROW
- ###< create table crash_me10 (DISTINCTROW int not null)
- ###> execute error: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 'DISTINCTROW int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_distributed=no # Keyword DISTRIBUTED
- ###< create table crash_me10 (DISTRIBUTED int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_dummy=no # Keyword DUMMY
- ###< create table crash_me10 (DUMMY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_dump=no # Keyword DUMP
- ###< create table crash_me10 (DUMP int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_enclosed=yes # Keyword ENCLOSED
- ###< create table crash_me10 (ENCLOSED int not null)
- ###> execute error: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 'ENCLOSED int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_errlvl=no # Keyword ERRLVL
- ###< create table crash_me10 (ERRLVL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_errors=no # Keyword ERRORS
- ###< create table crash_me10 (ERRORS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_escaped=yes # Keyword ESCAPED
- ###< create table crash_me10 (ESCAPED int not null)
- ###> execute error: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 'ESCAPED int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_exclusive=no # Keyword EXCLUSIVE
- ###< create table crash_me10 (EXCLUSIVE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_explain=yes # Keyword EXPLAIN
- ###< create table crash_me10 (EXPLAIN int not null)
- ###> execute error: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 'EXPLAIN int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
-reserved_word_extra_fields=yes # Keyword FIELDS
- ###< create table crash_me10 (FIELDS int not null)
- ###> execute error: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 'FIELDS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_fields=no # Keyword FIELDS
reserved_word_extra_file=no # Keyword FILE
- ###< create table crash_me10 (FILE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_fillfactor=no # Keyword FILLFACTOR
- ###< create table crash_me10 (FILLFACTOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_freetext=no # Keyword FREETEXT
- ###< create table crash_me10 (FREETEXT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_freetexttable=no # Keyword FREETEXTTABLE
- ###< create table crash_me10 (FREETEXTTABLE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_fulltext=yes # Keyword FULLTEXT
- ###< create table crash_me10 (FULLTEXT int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_geometry=no # Keyword GEOMETRY
- ###< create table crash_me10 (GEOMETRY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_hash=no # Keyword HASH
- ###< create table crash_me10 (HASH int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_high_priority=yes # Keyword HIGH_PRIORITY
- ###< create table crash_me10 (HIGH_PRIORITY int not null)
- ###> execute error: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 'HIGH_PRIORITY int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_holdlock=no # Keyword HOLDLOCK
- ###< create table crash_me10 (HOLDLOCK int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_hour_minute=yes # Keyword HOUR_MINUTE
- ###< create table crash_me10 (HOUR_MINUTE int not null)
- ###> execute error: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 'HOUR_MINUTE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_hour_second=yes # Keyword HOUR_SECOND
- ###< create table crash_me10 (HOUR_SECOND int not null)
- ###> execute error: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 'HOUR_SECOND int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_identified=no # Keyword IDENTIFIED
- ###< create table crash_me10 (IDENTIFIED int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_identity_insert=no # Keyword IDENTITY_INSERT
- ###< create table crash_me10 (IDENTITY_INSERT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_identitycol=no # Keyword IDENTITYCOL
- ###< create table crash_me10 (IDENTITYCOL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_increment=no # Keyword INCREMENT
- ###< create table crash_me10 (INCREMENT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_index=yes # Keyword INDEX
- ###< create table crash_me10 (INDEX int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_infile=yes # Keyword INFILE
- ###< create table crash_me10 (INFILE int not null)
- ###> execute error: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 'INFILE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_initial=no # Keyword INITIAL
- ###< create table crash_me10 (INITIAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_innodb=no # Keyword INNODB
- ###< create table crash_me10 (INNODB int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_keys=yes # Keyword KEYS
- ###< create table crash_me10 (KEYS int not null)
- ###> execute error: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 'KEYS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_kill=yes # Keyword KILL
- ###< create table crash_me10 (KILL int not null)
- ###> execute error: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 'KILL int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_lineno=no # Keyword LINENO
- ###< create table crash_me10 (LINENO int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_lines=yes # Keyword LINES
- ###< create table crash_me10 (LINES int not null)
- ###> execute error: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 'LINES int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_load=yes # Keyword LOAD
- ###< create table crash_me10 (LOAD int not null)
- ###> execute error: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 'LOAD int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_lock=yes # Keyword LOCK
- ###< create table crash_me10 (LOCK int not null)
- ###> execute error: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 'LOCK int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_long=yes # Keyword LONG
- ###< create table crash_me10 (LONG int not null)
- ###> execute error: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 'LONG int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_longblob=yes # Keyword LONGBLOB
- ###< create table crash_me10 (LONGBLOB int not null)
- ###> execute error: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 'LONGBLOB int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_longtext=yes # Keyword LONGTEXT
- ###< create table crash_me10 (LONGTEXT int not null)
- ###> execute error: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 'LONGTEXT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_low_priority=yes # Keyword LOW_PRIORITY
- ###< create table crash_me10 (LOW_PRIORITY int not null)
- ###> execute error: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 'LOW_PRIORITY int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_master_server_id=no # Keyword MASTER_SERVER_ID
- ###< create table crash_me10 (MASTER_SERVER_ID int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_maxextents=no # Keyword MAXEXTENTS
- ###< create table crash_me10 (MAXEXTENTS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_mediumblob=yes # Keyword MEDIUMBLOB
- ###< create table crash_me10 (MEDIUMBLOB int not null)
- ###> execute error: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 'MEDIUMBLOB int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_mediumint=yes # Keyword MEDIUMINT
- ###< create table crash_me10 (MEDIUMINT int not null)
- ###> execute error: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 'MEDIUMINT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_mediumtext=yes # Keyword MEDIUMTEXT
- ###< create table crash_me10 (MEDIUMTEXT int not null)
- ###> execute error: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 'MEDIUMTEXT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_middleint=yes # Keyword MIDDLEINT
- ###< create table crash_me10 (MIDDLEINT int not null)
- ###> execute error: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 'MIDDLEINT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_minus=no # Keyword MINUS
- ###< create table crash_me10 (MINUS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_minute_second=yes # Keyword MINUTE_SECOND
- ###< create table crash_me10 (MINUTE_SECOND int not null)
- ###> execute error: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 'MINUTE_SECOND int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_mlslabel=no # Keyword MLSLABEL
- ###< create table crash_me10 (MLSLABEL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_mode=no # Keyword MODE
- ###< create table crash_me10 (MODE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_mrg_myisam=no # Keyword MRG_MYISAM
- ###< create table crash_me10 (MRG_MYISAM int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_noaudit=no # Keyword NOAUDIT
- ###< create table crash_me10 (NOAUDIT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_nocheck=no # Keyword NOCHECK
- ###< create table crash_me10 (NOCHECK int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_nocompress=no # Keyword NOCOMPRESS
- ###< create table crash_me10 (NOCOMPRESS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_nonclustered=no # Keyword NONCLUSTERED
- ###< create table crash_me10 (NONCLUSTERED int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_nowait=no # Keyword NOWAIT
- ###< create table crash_me10 (NOWAIT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_number=no # Keyword NUMBER
- ###< create table crash_me10 (NUMBER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_offline=no # Keyword OFFLINE
- ###< create table crash_me10 (OFFLINE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_offsets=no # Keyword OFFSETS
- ###< create table crash_me10 (OFFSETS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_online=no # Keyword ONLINE
- ###< create table crash_me10 (ONLINE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_opendatasource=no # Keyword OPENDATASOURCE
- ###< create table crash_me10 (OPENDATASOURCE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_openquery=no # Keyword OPENQUERY
- ###< create table crash_me10 (OPENQUERY int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_openrowset=no # Keyword OPENROWSET
- ###< create table crash_me10 (OPENROWSET int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_openxml=no # Keyword OPENXML
- ###< create table crash_me10 (OPENXML int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_optimize=yes # Keyword OPTIMIZE
- ###< create table crash_me10 (OPTIMIZE int not null)
- ###> execute error: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 'OPTIMIZE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_optionally=yes # Keyword OPTIONALLY
- ###< create table crash_me10 (OPTIONALLY int not null)
- ###> execute error: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 'OPTIONALLY int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_outfile=yes # Keyword OUTFILE
- ###< create table crash_me10 (OUTFILE int not null)
- ###> execute error: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 'OUTFILE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_over=no # Keyword OVER
- ###< create table crash_me10 (OVER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_pctfree=no # Keyword PCTFREE
- ###< create table crash_me10 (PCTFREE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_percent=no # Keyword PERCENT
- ###< create table crash_me10 (PERCENT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_plan=no # Keyword PLAN
- ###< create table crash_me10 (PLAN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_print=no # Keyword PRINT
- ###< create table crash_me10 (PRINT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_proc=no # Keyword PROC
- ###< create table crash_me10 (PROC int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_purge=yes # Keyword PURGE
- ###< create table crash_me10 (PURGE int not null)
- ###> execute error: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 'PURGE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_raiserror=no # Keyword RAISERROR
- ###< create table crash_me10 (RAISERROR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_raw=no # Keyword RAW
- ###< create table crash_me10 (RAW int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_readtext=no # Keyword READTEXT
- ###< create table crash_me10 (READTEXT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_reconfigure=no # Keyword RECONFIGURE
- ###< create table crash_me10 (RECONFIGURE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_regexp=yes # Keyword REGEXP
- ###< create table crash_me10 (REGEXP int not null)
- ###> execute error: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 'REGEXP int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_rename=yes # Keyword RENAME
- ###< create table crash_me10 (RENAME int not null)
- ###> execute error: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 'RENAME int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_replication=no # Keyword REPLICATION
- ###< create table crash_me10 (REPLICATION int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_require=yes # Keyword REQUIRE
- ###< create table crash_me10 (REQUIRE int not null)
- ###> execute error: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 'REQUIRE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_resource=no # Keyword RESOURCE
- ###< create table crash_me10 (RESOURCE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_restore=no # Keyword RESTORE
- ###< create table crash_me10 (RESTORE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_rlike=yes # Keyword RLIKE
- ###< create table crash_me10 (RLIKE int not null)
- ###> execute error: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 'RLIKE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_rowcount=no # Keyword ROWCOUNT
- ###< create table crash_me10 (ROWCOUNT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_rowguidcol=no # Keyword ROWGUIDCOL
- ###< create table crash_me10 (ROWGUIDCOL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_rowid=no # Keyword ROWID
- ###< create table crash_me10 (ROWID int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_rownum=no # Keyword ROWNUM
- ###< create table crash_me10 (ROWNUM int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_rtree=no # Keyword RTREE
- ###< create table crash_me10 (RTREE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_rule=no # Keyword RULE
- ###< create table crash_me10 (RULE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_save=no # Keyword SAVE
- ###< create table crash_me10 (SAVE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_setuser=no # Keyword SETUSER
- ###< create table crash_me10 (SETUSER int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_share=no # Keyword SHARE
- ###< create table crash_me10 (SHARE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_show=yes # Keyword SHOW
- ###< create table crash_me10 (SHOW int not null)
- ###> execute error: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 'SHOW int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_shutdown=no # Keyword SHUTDOWN
- ###< create table crash_me10 (SHUTDOWN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_soname=yes # Keyword SONAME
- ###< create table crash_me10 (SONAME int not null)
- ###> execute error: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 'SONAME int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_spatial=yes # Keyword SPATIAL
- ###< create table crash_me10 (SPATIAL int not null)
- ###> execute error: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 'int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_sql_big_result=yes # Keyword SQL_BIG_RESULT
- ###< create table crash_me10 (SQL_BIG_RESULT int not null)
- ###> execute error: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 'SQL_BIG_RESULT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_sql_calc_found_rows=yes # Keyword SQL_CALC_FOUND_ROWS
- ###< create table crash_me10 (SQL_CALC_FOUND_ROWS int not null)
- ###> execute error: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 'SQL_CALC_FOUND_ROWS int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_sql_small_result=yes # Keyword SQL_SMALL_RESULT
- ###< create table crash_me10 (SQL_SMALL_RESULT int not null)
- ###> execute error: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 'SQL_SMALL_RESULT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_ssl=yes # Keyword SSL
- ###< create table crash_me10 (SSL int not null)
- ###> execute error: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 'SSL int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_starting=yes # Keyword STARTING
- ###< create table crash_me10 (STARTING int not null)
- ###> execute error: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 'STARTING int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_statistics=no # Keyword STATISTICS
- ###< create table crash_me10 (STATISTICS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_straight_join=yes # Keyword STRAIGHT_JOIN
- ###< create table crash_me10 (STRAIGHT_JOIN int not null)
- ###> execute error: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 'STRAIGHT_JOIN int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_striped=no # Keyword STRIPED
- ###< create table crash_me10 (STRIPED int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_successful=no # Keyword SUCCESSFUL
- ###< create table crash_me10 (SUCCESSFUL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_synonym=no # Keyword SYNONYM
- ###< create table crash_me10 (SYNONYM int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_sysdate=no # Keyword SYSDATE
- ###< create table crash_me10 (SYSDATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
-reserved_word_extra_tables=yes # Keyword TABLES
- ###< create table crash_me10 (TABLES int not null)
- ###> execute error: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 'TABLES int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
+reserved_word_extra_tables=no # Keyword TABLES
reserved_word_extra_terminated=yes # Keyword TERMINATED
- ###< create table crash_me10 (TERMINATED int not null)
- ###> execute error: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 'TERMINATED int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_textsize=no # Keyword TEXTSIZE
- ###< create table crash_me10 (TEXTSIZE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_tinyblob=yes # Keyword TINYBLOB
- ###< create table crash_me10 (TINYBLOB int not null)
- ###> execute error: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 'TINYBLOB int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_tinyint=yes # Keyword TINYINT
- ###< create table crash_me10 (TINYINT int not null)
- ###> execute error: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 'TINYINT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_tinytext=yes # Keyword TINYTEXT
- ###< create table crash_me10 (TINYTEXT int not null)
- ###> execute error: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 'TINYTEXT int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_top=no # Keyword TOP
- ###< create table crash_me10 (TOP int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_tran=no # Keyword TRAN
- ###< create table crash_me10 (TRAN int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_truncate=no # Keyword TRUNCATE
- ###< create table crash_me10 (TRUNCATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_tsequal=no # Keyword TSEQUAL
- ###< create table crash_me10 (TSEQUAL int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_types=no # Keyword TYPES
- ###< create table crash_me10 (TYPES int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_uid=no # Keyword UID
- ###< create table crash_me10 (UID int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_unlock=yes # Keyword UNLOCK
- ###< create table crash_me10 (UNLOCK int not null)
- ###> execute error: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 'UNLOCK int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_unsigned=yes # Keyword UNSIGNED
- ###< create table crash_me10 (UNSIGNED int not null)
- ###> execute error: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 'UNSIGNED int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_updatetext=no # Keyword UPDATETEXT
- ###< create table crash_me10 (UPDATETEXT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_use=yes # Keyword USE
- ###< create table crash_me10 (USE int not null)
- ###> execute error: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 'USE int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_user_resources=no # Keyword USER_RESOURCES
- ###< create table crash_me10 (USER_RESOURCES int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_validate=no # Keyword VALIDATE
- ###< create table crash_me10 (VALIDATE int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_varbinary=yes # Keyword VARBINARY
- ###< create table crash_me10 (VARBINARY int not null)
- ###> execute error: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 'VARBINARY int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_varchar2=no # Keyword VARCHAR2
- ###< create table crash_me10 (VARCHAR2 int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_waitfor=no # Keyword WAITFOR
- ###< create table crash_me10 (WAITFOR int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_warnings=no # Keyword WARNINGS
- ###< create table crash_me10 (WARNINGS int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_writetext=no # Keyword WRITETEXT
- ###< create table crash_me10 (WRITETEXT int not null)
- ###> OK
- ###< drop table crash_me10
- ###> OK
- ###
- ###As far as all queries returned OK, result is NO
reserved_word_extra_xor=yes # Keyword XOR
- ###< create table crash_me10 (XOR int not null)
- ###> execute error: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 'XOR int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_year_month=yes # Keyword YEAR_MONTH
- ###< create table crash_me10 (YEAR_MONTH int not null)
- ###> execute error: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 'YEAR_MONTH int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
reserved_word_extra_zerofill=yes # Keyword ZEROFILL
- ###< create table crash_me10 (ZEROFILL int not null)
- ###> execute error: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 'ZEROFILL int not null)' at line 1
- ###< drop table crash_me10
- ###> execute error:Unknown table 'crash_me10'
- ###
- ###As far as some queries didnt return OK, result is YES
right_outer_join=yes # right outer join
- ###< select crash_me.a from crash_me right join crash_me2 ON crash_me.a=crash_me2.a
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
rollback_metadata=no # rollback_metadata
- ###< create table crash_q (a integer not null)
- ###> OK
- ###
- ###< insert into crash_q values (1)
- ###> OK
rowid=auto_increment # Type for row id
- ###< create table crash_q (a rowid)
- ###> execute error: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 'rowid)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###< create table crash_q (a int not null auto_increment, primary key(a))
- ###> OK
- ###< drop table crash_q
- ###> OK
-safe_decimal_arithmetic=no # safe decimal arithmetic
- ###< create table crash_me_a (a decimal(10,2),b decimal(10,2))
- ###> OK
- ###
- ###< insert into crash_me_a (a,b) values (11.4,18.9)
- ###> OK
- ###
- ###<select count(*) from crash_me_a where a+b=30.3
- ###>0
- ###We expected '1' but got '0'
+safe_decimal_arithmetic=yes # safe decimal arithmetic
select_constants=yes # Select constants
- ###< select 1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
select_limit=with LIMIT # LIMIT number of rows
- ###< select * from crash_me limit 1
- ###> OK
select_limit2=yes # SELECT with LIMIT #,#
- ###< select * from crash_me limit 1,1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
select_limit3=yes # SELECT with LIMIT # OFFSET #
- ###< select * from crash_me limit 1 offset 1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
select_string_size=1048565 # constant string size in SELECT
- ###We are trying (example with N=5):
- ###select 'aaaaa'
select_table_update=yes # Update with sub select
- ###< create table crash_q (a integer,b char(10))
- ###> OK
- ###< insert into crash_q values(1,'c')
- ###> OK
- ###< update crash_q set b= (select b from crash_me where crash_q.a = crash_me.a)
- ###> OK
- ###
- ###<select b from crash_q
- ###>a
- ###
- ###< drop table crash_q
- ###> OK
select_without_from=yes # SELECT without FROM
- ###< select 1
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
-server_version=MySQL 4.1.2 alpha # server version
+server_version=MySQL 5.0.7 beta valgrind max debug/ # server version
simple_joins=yes # ANSI SQL simple joins
- ###< select crash_me.a from crash_me, crash_me t0
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
sorted_group_by=yes # Group by always sorted
- ###< create table crash_me_t1 (a int not null, b int not null)
- ###> OK
- ###< insert into crash_me_t1 values (1,1)
- ###> OK
- ###< insert into crash_me_t1 values (1,2)
- ###> OK
- ###< insert into crash_me_t1 values (3,1)
- ###> OK
- ###< insert into crash_me_t1 values (3,2)
- ###> OK
- ###< insert into crash_me_t1 values (2,2)
- ###> OK
- ###< insert into crash_me_t1 values (2,1)
- ###> OK
- ###< create table crash_me_t2 (a int not null, b int not null)
- ###> OK
- ###< create index crash_me_t2_ind on crash_me_t2 (a)
- ###> OK
- ###< insert into crash_me_t2 values (1,3)
- ###> OK
- ###< insert into crash_me_t2 values (3,1)
- ###> OK
- ###< insert into crash_me_t2 values (2,2)
- ###> OK
- ###< insert into crash_me_t2 values (1,1)
- ###> OK
- ###
- ###< select crash_me_t1.a,crash_me_t2.b from crash_me_t1,crash_me_t2 where crash_me_t1.a=crash_me_t2.a group by crash_me_t1.a,crash_me_t2.b
- ### > 1,1
- ### > 1,3
- ### > 2,2
- ### > 3,1
- ###
- ### Check recordset:
- ### 1,1 expected: 1,1
- ### 1,3 expected: 1,3
- ### 2,2 expected: 2,2
- ### 3,1 expected: 3,1
- ### Recordset corresponds with template
- ###< drop table crash_me_t1
- ###> OK
- ###< drop table crash_me_t2
- ###> OK
storage_of_float=round # Storage of float values
- ###< create table crash_q (q1 float(4,1))
- ###> OK
- ###< insert into crash_q values(1.14)
- ###> OK
- ###
- ###<select q1 from crash_q
- ###>1.1
- ###
- ###< drop table crash_q
- ###> OK
- ###
- ###< create table crash_q (q1 float(4,1))
- ###> OK
- ###< insert into crash_q values(1.16)
- ###> OK
- ###
- ###<select q1 from crash_q
- ###>1.2
- ###We expected '1.1' but got '1.2'
- ###
- ###< drop table crash_q
- ###> OK
- ###
- ###< create table crash_q (q1 float(4,1))
- ###> OK
- ###< insert into crash_q values(1.14)
- ###> OK
- ###
- ###<select q1 from crash_q
- ###>1.1
- ###
- ###< drop table crash_q
- ###> OK
- ###
- ###< create table crash_q (q1 float(4,1))
- ###> OK
- ###< insert into crash_q values(1.16)
- ###> OK
- ###
- ###<select q1 from crash_q
- ###>1.2
- ###
- ###< drop table crash_q
- ###> OK
subqueries=yes # subqueries
- ###< select a from crash_me where crash_me.a in (select max(a) from crash_me)
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
table_alias=yes # Table alias
- ###< select b.a from crash_me as b
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
table_name_case=no # case independent table names
- ###< create table crash_q (q integer)
- ###> OK
- ###< drop table CRASH_Q
- ###> execute error:Unknown table 'CRASH_Q'
- ###
- ###As far as some queries didnt return OK, result is NO
table_wildcard=yes # Select table_name.*
- ###< select crash_me.* from crash_me
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
temporary_table=yes # temporary tables
- ###< create temporary table crash_q (q integer not null)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
time_format_EUR=error # Supports HH.MM.SS (EUR) time format
- ###< insert into crash_me_t(a) values ('20.08.16')
- ###> OK
- ###
- ###<select a from crash_me_t
- ###>00:00:20
- ###We expected '20:08:16' but got '00:00:20'
- ###
- ###< delete from crash_me_t
- ###> OK
time_format_HHHHMMSS=yes # Supports HHHHmmSS time format
- ###< insert into crash_me_t(a) values ('00200816')
- ###> OK
- ###
- ###<select a from crash_me_t
- ###>20:08:16
- ###
- ###< delete from crash_me_t
- ###> OK
time_format_ISO=yes # Supports HH:MM:SS (ISO) time format
- ###< insert into crash_me_t(a) values ('20:08:16')
- ###> OK
- ###
- ###<select a from crash_me_t
- ###>20:08:16
- ###
- ###< delete from crash_me_t
- ###> OK
time_format_USA=error # Supports HH:MM:SS (AM|PM) time format
- ###< insert into crash_me_t(a) values ('08:08:16 PM')
- ###> OK
- ###
- ###<select a from crash_me_t
- ###>08:08:16
- ###We expected '20:08:16' but got '08:08:16'
- ###
- ###< delete from crash_me_t
- ###> OK
time_format_inresult=iso # Time format in result
- ###< insert into crash_me_t values(CURRENT_TIME)
- ###> OK
- ###
- ###< select a from crash_me_t
- ###> 13:49:05
- ###< delete from crash_me_t
- ###> OK
transactions=yes # transactions
- ###<select * from crash_q
- ###>1
- ###We expected '' but got '1'
truncate_table=yes # truncate
- ###< create table crash_q (a integer, b integer,c1 CHAR(10))
- ###> OK
- ###< truncate table crash_q
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_abstime=no # Type abstime
- ###< create table crash_q (q abstime)
- ###> execute error: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 'abstime)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_bfile=no # Type bfile
- ###< create table crash_q (q bfile)
- ###> execute error: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 'bfile)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_blob=yes # Type blob
- ###< create table crash_q (q blob)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_bool=yes # Type bool
- ###< create table crash_q (q bool)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_box=no # Type box
- ###< create table crash_q (q box)
- ###> execute error: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 'box)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_byte=no # Type byte
- ###< create table crash_q (q byte)
- ###> execute error: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 'byte)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_char(1_arg)_binary=yes # Type char(1 arg) binary
- ###< create table crash_q (q char(10) binary)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_cidr=no # Type cidr
- ###< create table crash_q (q cidr)
- ###> execute error: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 'cidr)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_circle=no # Type circle
- ###< create table crash_q (q circle)
- ###> execute error: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 'circle)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_clob=no # Type clob
- ###< create table crash_q (q clob)
- ###> execute error: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 'clob)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_datetime=yes # Type datetime
- ###< create table crash_q (q datetime)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_double=yes # Type double
- ###< create table crash_q (q double)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_enum(1_arg)=yes # Type enum(1 arg)
- ###< create table crash_q (q enum('red'))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_float(2_arg)=yes # Type float(2 arg)
- ###< create table crash_q (q float(6,2))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_float4=yes # Type float4
- ###< create table crash_q (q float4)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_float8=yes # Type float8
- ###< create table crash_q (q float8)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_image=no # Type image
- ###< create table crash_q (q image)
- ###> execute error: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 'image)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_inet=no # Type inet
- ###< create table crash_q (q inet)
- ###> execute error: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 'inet)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_int(1_arg)_zerofill=yes # Type int(1 arg) zerofill
- ###< create table crash_q (q int(5) zerofill)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_int1=yes # Type int1
- ###< create table crash_q (q int1)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_int2=yes # Type int2
- ###< create table crash_q (q int2)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_int3=yes # Type int3
- ###< create table crash_q (q int3)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_int4=yes # Type int4
- ###< create table crash_q (q int4)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_int8=yes # Type int8
- ###< create table crash_q (q int8)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_int_auto_increment=yes # Type int not null auto_increment
- ###< create table crash_q (q int not null auto_increment,unique(q))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_int_identity=no # Type int not null identity
- ###< create table crash_q (q int not null identity,unique(q))
- ###> execute error: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 'identity,unique(q))' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_int_unsigned=yes # Type int unsigned
- ###< create table crash_q (q int unsigned)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_interval=no # Type interval
- ###< create table crash_q (q interval)
- ###> execute error: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 'interval)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_line=no # Type line
- ###< create table crash_q (q line)
- ###> execute error: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 'line)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_long=yes # Type long
- ###< create table crash_q (q long)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_long_raw=no # Type long raw
- ###< create table crash_q (q long raw)
- ###> execute error: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 'raw)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_long_varbinary=yes # Type long varbinary
- ###< create table crash_q (q long varbinary)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_long_varchar(1_arg)=no # Type long varchar(1 arg)
- ###< create table crash_q (q long varchar(1))
- ###> execute error: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
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_lseg=no # Type lseg
- ###< create table crash_q (q lseg)
- ###> execute error: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 'lseg)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_macaddr=no # Type macaddr
- ###< create table crash_q (q macaddr)
- ###> execute error: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 'macaddr)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_mediumint=yes # Type mediumint
- ###< create table crash_q (q mediumint)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_mediumtext=yes # Type mediumtext
- ###< create table crash_q (q mediumtext)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_middleint=yes # Type middleint
- ###< create table crash_q (q middleint)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_mlslabel=no # Type mlslabel
- ###< create table crash_q (q mlslabel)
- ###> execute error: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 'mlslabel)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_money=no # Type money
- ###< create table crash_q (q money)
- ###> execute error: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 'money)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_nclob=no # Type nclob
- ###< create table crash_q (q nclob)
- ###> execute error: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 'nclob)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_number=no # Type number
- ###< create table crash_q (q number)
- ###> execute error: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 'number)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_number(1_arg)=no # Type number(1 arg)
- ###< create table crash_q (q number(9))
- ###> execute error: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 'number(9))' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_number(2_arg)=no # Type number(2 arg)
- ###< create table crash_q (q number(9,2))
- ###> execute error: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 'number(9,2))' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_nvarchar2(1_arg)=no # Type nvarchar2(1 arg)
- ###< create table crash_q (q nvarchar2(16))
- ###> execute error: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 'nvarchar2(16))' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_path=no # Type path
- ###< create table crash_q (q path)
- ###> execute error: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 'path)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_point=yes # Type point
- ###< create table crash_q (q point)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_polygon=yes # Type polygon
- ###< create table crash_q (q polygon)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_raw(1_arg)=no # Type raw(1 arg)
- ###< create table crash_q (q raw(16))
- ###> execute error: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 'raw(16))' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_reltime=no # Type reltime
- ###< create table crash_q (q reltime)
- ###> execute error: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 'reltime)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_rowid=no # Type rowid
- ###< create table crash_q (q rowid)
- ###> execute error: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 'rowid)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_serial=yes # Type serial
- ###< create table crash_q (q serial)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_set(1_arg)=yes # Type set(1 arg)
- ###< create table crash_q (q set('red'))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_smalldatetime=no # Type smalldatetime
- ###< create table crash_q (q smalldatetime)
- ###> execute error: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 'smalldatetime)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_smallfloat=no # Type smallfloat
- ###< create table crash_q (q smallfloat)
- ###> execute error: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 'smallfloat)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_smallmoney=no # Type smallmoney
- ###< create table crash_q (q smallmoney)
- ###> execute error: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 'smallmoney)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_text=yes # Type text
- ###< create table crash_q (q text)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_text(1_arg)=yes # Type text(1 arg)
- ###< create table crash_q (q text(10))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_extra_timespan=no # Type timespan
- ###< create table crash_q (q timespan)
- ###> execute error: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 'timespan)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_uint=no # Type uint
- ###< create table crash_q (q uint)
- ###> execute error: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 'uint)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_varchar2(1_arg)=no # Type varchar2(1 arg)
- ###< create table crash_q (q varchar2(257))
- ###> execute error: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 'varchar2(257))' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_extra_year=yes # Type year
- ###< create table crash_q (q year)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_odbc_bigint=yes # Type bigint
- ###< create table crash_q (q bigint)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_odbc_binary(1_arg)=yes # Type binary(1 arg)
- ###< create table crash_q (q binary(1))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_odbc_datetime=yes # Type datetime
- ###< create table crash_q (q datetime)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_odbc_tinyint=yes # Type tinyint
- ###< create table crash_q (q tinyint)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_odbc_varbinary(1_arg)=yes # Type varbinary(1 arg)
- ###< create table crash_q (q varbinary(1))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_bit=yes # Type bit
- ###< create table crash_q (q bit)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_bit(1_arg)=yes # Type bit(1 arg)
- ###< create table crash_q (q bit(2))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_bit_varying(1_arg)=no # Type bit varying(1 arg)
- ###< create table crash_q (q bit varying(2))
- ###> execute error: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 'varying(2))' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_boolean=yes # Type boolean
- ###< create table crash_q (q boolean)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_char(1_arg)=yes # Type char(1 arg)
- ###< create table crash_q (q char(1))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_char_varying(1_arg)=yes # Type char varying(1 arg)
- ###< create table crash_q (q char varying(1))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_character(1_arg)=yes # Type character(1 arg)
- ###< create table crash_q (q character(1))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_character_varying(1_arg)=yes # Type character varying(1 arg)
- ###< create table crash_q (q character varying(1))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_date=yes # Type date
- ###< create table crash_q (q date)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_dec(2_arg)=yes # Type dec(2 arg)
- ###< create table crash_q (q dec(6,2))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_decimal(2_arg)=yes # Type decimal(2 arg)
- ###< create table crash_q (q decimal(6,2))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_double_precision=yes # Type double precision
- ###< create table crash_q (q double precision)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_float=yes # Type float
- ###< create table crash_q (q float)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_float(1_arg)=yes # Type float(1 arg)
- ###< create table crash_q (q float(8))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_int=yes # Type int
- ###< create table crash_q (q int)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_integer=yes # Type integer
- ###< create table crash_q (q integer)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_interval_day=no # Type interval day
- ###< create table crash_q (q interval day)
- ###> execute error: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 'interval day)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_day_to_hour=no # Type interval day to hour
- ###< create table crash_q (q interval day to hour)
- ###> execute error: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 'interval day to hour)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_day_to_minute=no # Type interval day to minute
- ###< create table crash_q (q interval day to minute)
- ###> execute error: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 'interval day to minute)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_day_to_second=no # Type interval day to second
- ###< create table crash_q (q interval day to second)
- ###> execute error: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 'interval day to second)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_hour=no # Type interval hour
- ###< create table crash_q (q interval hour)
- ###> execute error: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 'interval hour)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_hour_to_minute=no # Type interval hour to minute
- ###< create table crash_q (q interval hour to minute)
- ###> execute error: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 'interval hour to minute)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_hour_to_second=no # Type interval hour to second
- ###< create table crash_q (q interval hour to second)
- ###> execute error: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 'interval hour to second)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_minute=no # Type interval minute
- ###< create table crash_q (q interval minute)
- ###> execute error: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 'interval minute)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_minute_to_second=no # Type interval minute to second
- ###< create table crash_q (q interval minute to second)
- ###> execute error: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 'interval minute to second)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_month=no # Type interval month
- ###< create table crash_q (q interval month)
- ###> execute error: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 'interval month)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_second=no # Type interval second
- ###< create table crash_q (q interval second)
- ###> execute error: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 'interval second)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_year=no # Type interval year
- ###< create table crash_q (q interval year)
- ###> execute error: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 'interval year)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_interval_year_to_month=no # Type interval year to month
- ###< create table crash_q (q interval year to month)
- ###> execute error: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 'interval year to month)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_national_char_varying(1_arg)=yes # Type national char varying(1 arg)
- ###< create table crash_q (q national char varying(20))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_national_character(1_arg)=yes # Type national character(1 arg)
- ###< create table crash_q (q national character(20))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_national_character_varying(1_arg)=yes # Type national character varying(1 arg)
- ###< create table crash_q (q national character varying(20))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_nchar(1_arg)=yes # Type nchar(1 arg)
- ###< create table crash_q (q nchar(1))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_nchar_varying(1_arg)=yes # Type nchar varying(1 arg)
- ###< create table crash_q (q nchar varying(20))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_numeric(2_arg)=yes # Type numeric(2 arg)
- ###< create table crash_q (q numeric(9,2))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_real=yes # Type real
- ###< create table crash_q (q real)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_smallint=yes # Type smallint
- ###< create table crash_q (q smallint)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_time=yes # Type time
- ###< create table crash_q (q time)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_timestamp=yes # Type timestamp
- ###< create table crash_q (q timestamp)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
type_sql_timestamp_with_time_zone=no # Type timestamp with time zone
- ###< create table crash_q (q timestamp with time zone)
- ###> execute error: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 'with time zone)' at line 1
- ###< drop table crash_q
- ###> execute error:Unknown table 'crash_q'
- ###
- ###As far as some queries didnt return OK, result is NO
type_sql_varchar(1_arg)=yes # Type varchar(1 arg)
- ###< create table crash_q (q varchar(1))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
union=yes # union
- ###< select * from crash_me union select a,b from crash_me3
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
union_all=yes # union all
- ###< select * from crash_me union all select a,b from crash_me3
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
union_all_incompat=yes # union all (incompatible lists)
- ###< select * from crash_me union all select a,b from crash_me2
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
union_incompat=yes # union (incompatible lists)
- ###< select * from crash_me union select a,b from crash_me2
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
unique_in_create=yes # unique in create table
- ###< create table crash_q (q integer not null,unique (q))
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
unique_null_in_create=yes # unique null in create
- ###< create table crash_q (q integer,unique (q))
- ###> OK
- ###< insert into crash_q (q) values (NULL)
- ###> OK
- ###< insert into crash_q (q) values (NULL)
- ###> OK
- ###< insert into crash_q (q) values (1)
- ###> OK
- ###< drop table crash_q
- ###> OK
- ###
- ###As far as all queries returned OK, result is YES
value_of_false=0 # Value of FALSE
- ###<select FALSE
- ###>0
value_of_true=1 # Value of TRUE
- ###<select TRUE
- ###>1
-views=no # views
- ###< create view crash_q as select a from crash_me
- ###> execute error: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 'view crash_q as select a from crash_me' at line 1
- ###< drop view crash_q
- ###> execute error: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 'view crash_q' at line 1
- ###
- ###As far as some queries didnt return OK, result is NO
+views=yes # views
where_string_size=1048539 # constant string size in where
- ###We are trying (example with N=5):
- ###select a from crash_me where b >='11111'
diff --git a/sql-common/client.c b/sql-common/client.c
index 3979b9304f7..08ad906e2b6 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -57,7 +57,7 @@
my_bool net_flush(NET *net);
#else /*EMBEDDED_LIBRARY*/
-#define CLI_MYSQL_REAL_CONNECT mysql_real_connect
+#define CLI_MYSQL_REAL_CONNECT STDCALL mysql_real_connect
#endif /*EMBEDDED_LIBRARY*/
#include <my_sys.h>
#include <mysys_err.h>
@@ -98,9 +98,6 @@ my_bool net_flush(NET *net);
# include <sys/un.h>
#endif
-#ifndef INADDR_NONE
-#define INADDR_NONE -1
-#endif
#if defined(MSDOS) || defined(__WIN__)
#define perror(A)
#else
@@ -653,6 +650,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
NET *net= &mysql->net;
my_bool result= 1;
init_sigpipe_variables
+ DBUG_ENTER("cli_advanced_command");
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
@@ -660,12 +658,13 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
if (mysql->net.vio == 0)
{ /* Do reconnect if possible */
if (mysql_reconnect(mysql))
- return 1;
+ DBUG_RETURN(1);
}
if (mysql->status != MYSQL_STATUS_READY)
{
+ DBUG_PRINT("error",("state: %d", mysql->status));
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
- return 1;
+ DBUG_RETURN(1);
}
net->last_error[0]=0;
@@ -704,7 +703,8 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
1 : 0);
end:
reset_sigpipe(mysql);
- return result;
+ DBUG_PRINT("exit",("result: %d", result));
+ DBUG_RETURN(result);
}
void free_old_query(MYSQL *mysql)
@@ -867,6 +867,8 @@ mysql_free_result(MYSQL_RES *result)
{
(*mysql->methods->flush_use_result)(mysql);
mysql->status=MYSQL_STATUS_READY;
+ if (mysql->unbuffered_fetch_owner)
+ *mysql->unbuffered_fetch_owner= TRUE;
}
}
free_rows(result->data);
@@ -893,6 +895,7 @@ static const char *default_options[]=
"replication-probe", "enable-reads-from-master", "repl-parse-query",
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
"multi-results", "multi-statements", "multi-queries", "secure-auth",
+ "report-data-truncation",
NullS
};
@@ -1104,6 +1107,9 @@ void mysql_read_default_options(struct st_mysql_options *options,
case 33: /* secure-auth */
options->secure_auth= TRUE;
break;
+ case 34: /* report-data-truncation */
+ options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
+ break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
}
@@ -1448,6 +1454,7 @@ mysql_init(MYSQL *mysql)
#endif
mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;
+ mysql->options.report_data_truncation= TRUE; /* default */
return mysql;
}
@@ -1533,7 +1540,8 @@ static MYSQL_METHODS client_methods=
#endif
};
-MYSQL * STDCALL
+
+MYSQL *
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,ulong client_flag)
@@ -1555,7 +1563,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
#ifdef HAVE_SYS_UN_H
struct sockaddr_un UNIXaddr;
#endif
-
init_sigpipe_variables
DBUG_ENTER("mysql_real_connect");
LINT_INIT(host_info);
@@ -1608,8 +1615,24 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
port=mysql->options.port;
if (!unix_socket)
unix_socket=mysql->options.unix_socket;
+
+ /*
+ By default we don't reconnect because it could silently corrupt data (after
+ reconnection you potentially lose table locks, user variables, session
+ variables (transactions but they are specifically dealt with in
+ mysql_reconnect()).
+ This is a change: < 5.0.3 mysql->reconnect was set to 1 by default.
+ How this change impacts existing apps:
+ - existing apps which relyed on the default will see a behaviour change;
+ they will have to set reconnect=1 after mysql_real_connect().
+ - existing apps which explicitely asked for reconnection (the only way they
+ could do it was by setting mysql.reconnect to 1 after mysql_real_connect())
+ will not see a behaviour change.
+ - existing apps which explicitely asked for no reconnection
+ (mysql.reconnect=0) will not see a behaviour change.
+ */
+ mysql->reconnect= 0;
- mysql->reconnect=1; /* Reconnect as default */
mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
/*
@@ -1664,7 +1687,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
ER(net->last_errno),socket_errno);
goto error;
}
- net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE);
+ net->vio= vio_new(sock, VIO_TYPE_SOCKET,
+ VIO_LOCALHOST | VIO_BUFFERED_READ);
bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
UNIXaddr.sun_family = AF_UNIX;
strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
@@ -1739,7 +1763,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
ER(net->last_errno),socket_errno);
goto error;
}
- net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE);
+ net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
bzero((char*) &sock_addr,sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
@@ -2107,7 +2131,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
for (; ptr<end; ptr++)
{
MYSQL_RES *res;
- if (mysql_real_query(mysql,*ptr, strlen(*ptr)))
+ if (mysql_real_query(mysql,*ptr, (ulong) strlen(*ptr)))
goto error;
if (mysql->fields)
{
@@ -2179,8 +2203,9 @@ my_bool mysql_reconnect(MYSQL *mysql)
DBUG_RETURN(1);
}
mysql_init(&tmp_mysql);
- tmp_mysql.options=mysql->options;
- tmp_mysql.rpl_pivot = mysql->rpl_pivot;
+ tmp_mysql.options= mysql->options;
+ tmp_mysql.rpl_pivot= mysql->rpl_pivot;
+
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
mysql->db, mysql->port, mysql->unix_socket,
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
@@ -2190,6 +2215,19 @@ my_bool mysql_reconnect(MYSQL *mysql)
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
DBUG_RETURN(1);
}
+ if (mysql_set_character_set(&tmp_mysql, mysql->charset->csname))
+ {
+ DBUG_PRINT("error", ("mysql_set_character_set() failed"));
+ bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options));
+ mysql_close(&tmp_mysql);
+ mysql->net.last_errno= tmp_mysql.net.last_errno;
+ strmov(mysql->net.last_error, tmp_mysql.net.last_error);
+ strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
+ DBUG_RETURN(1);
+ }
+
+ DBUG_PRINT("info", ("reconnect succeded"));
+ tmp_mysql.reconnect= 1;
tmp_mysql.free_me= mysql->free_me;
/*
@@ -2252,6 +2290,8 @@ mysql_select_db(MYSQL *mysql, const char *db)
static void mysql_close_free_options(MYSQL *mysql)
{
+ DBUG_ENTER("mysql_close_free_options");
+
my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
@@ -2280,6 +2320,7 @@ static void mysql_close_free_options(MYSQL *mysql)
my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif /* HAVE_SMEM */
bzero((char*) &mysql->options,sizeof(mysql->options));
+ DBUG_VOID_RETURN;
}
@@ -2426,8 +2467,6 @@ get_info:
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
mysql->server_status|= SERVER_STATUS_IN_TRANS;
- mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
-
if (!(fields=(*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,
protocol_41(mysql) ? 7 : 5)))
DBUG_RETURN(1);
@@ -2438,6 +2477,7 @@ get_info:
mysql->status= MYSQL_STATUS_GET_RESULT;
mysql->field_count= (uint) field_count;
mysql->warning_count= 0;
+ DBUG_PRINT("exit",("ok"));
DBUG_RETURN(0);
}
@@ -2637,6 +2677,25 @@ mysql_fetch_row(MYSQL_RES *res)
}
+/**************************************************************************
+ Get column lengths of the current row
+ If one uses mysql_use_result, res->lengths contains the length information,
+ else the lengths are calculated from the offset between pointers.
+**************************************************************************/
+
+ulong * STDCALL
+mysql_fetch_lengths(MYSQL_RES *res)
+{
+ MYSQL_ROW column;
+
+ if (!(column=res->current_row))
+ return 0; /* Something is wrong */
+ if (res->data)
+ (*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
+ return res->lengths;
+}
+
+
int STDCALL
mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
{
@@ -2705,6 +2764,12 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
case MYSQL_SECURE_AUTH:
mysql->options.secure_auth= *(my_bool *) arg;
break;
+ case MYSQL_REPORT_DATA_TRUNCATION:
+ mysql->options.report_data_truncation= test(*(my_bool *) arg);
+ break;
+ case MYSQL_OPT_RECONNECT:
+ mysql->reconnect= *(my_bool *) arg;
+ break;
default:
DBUG_RETURN(1);
}
@@ -2733,8 +2798,49 @@ uint STDCALL mysql_errno(MYSQL *mysql)
return mysql->net.last_errno;
}
+
const char * STDCALL mysql_error(MYSQL *mysql)
{
return mysql->net.last_error;
}
+/*
+ mysql_set_character_set function sends SET NAMES cs_name to
+ the server (which changes character_set_client, character_set_result
+ and character_set_connection) and updates mysql->charset so other
+ functions like mysql_real_escape will work correctly.
+*/
+int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
+{
+ struct charset_info_st *cs;
+ const char *save_csdir= charsets_dir;
+
+ if (mysql->options.charset_dir)
+ charsets_dir= mysql->options.charset_dir;
+
+ if (strlen(cs_name) < MY_CS_NAME_SIZE &&
+ (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
+ {
+ char buff[MY_CS_NAME_SIZE + 10];
+ charsets_dir= save_csdir;
+ sprintf(buff, "SET NAMES %s", cs_name);
+ if (!mysql_real_query(mysql, buff, strlen(buff)))
+ {
+ mysql->charset= cs;
+ }
+ }
+ else
+ {
+ char cs_dir_name[FN_REFLEN];
+ get_charsets_dir(cs_dir_name);
+ mysql->net.last_errno= CR_CANT_READ_CHARSET;
+ strmov(mysql->net.sqlstate, unknown_sqlstate);
+ my_snprintf(mysql->net.last_error, sizeof(mysql->net.last_error) - 1,
+ ER(mysql->net.last_errno), cs_name, cs_dir_name);
+
+ }
+ charsets_dir= save_csdir;
+ return mysql->net.last_errno;
+}
+
+
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 40d7799e274..72809ee9b4b 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -47,6 +47,62 @@ uchar days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
static long my_time_zone=0;
+/* Calc days in one year. works with 0 <= year <= 99 */
+
+uint calc_days_in_year(uint year)
+{
+ return ((year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ?
+ 366 : 365);
+}
+
+/*
+ Check datetime value for validity according to flags.
+
+ SYNOPSIS
+ check_date()
+ ltime Date to check.
+ not_zero_date ltime is not the zero date
+ flags flags to check
+ was_cut set to 2 if value was truncated.
+ NOTE: This is not touched if value was not truncated
+ NOTES
+ Here we assume that year and month is ok !
+ If month is 0 we allow any date. (This only happens if we allow zero
+ date parts in str_to_datetime())
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+static my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
+ ulong flags, int *was_cut)
+{
+ if (not_zero_date)
+ {
+ if ((((flags & TIME_NO_ZERO_IN_DATE) || !(flags & TIME_FUZZY_DATE)) &&
+ (ltime->month == 0 || ltime->day == 0)) ||
+ (!(flags & TIME_INVALID_DATES) &&
+ ltime->month && ltime->day > days_in_month[ltime->month-1] &&
+ (ltime->month != 2 || calc_days_in_year(ltime->year) != 366 ||
+ ltime->day != 29)))
+ {
+ *was_cut= 2;
+ return TRUE;
+ }
+ }
+ else if (flags & TIME_NO_ZERO_DATE)
+ {
+ /*
+ We don't set *was_cut here to signal that the problem was a zero date
+ and not an invalid date
+ */
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
/*
Convert a timestamp string to a MYSQL_TIME value.
@@ -58,8 +114,12 @@ static long my_time_zone=0;
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.
+ TIME_NO_ZERO_IN_DATE Don't allow partial dates
+ TIME_NO_ZERO_DATE Don't allow 0000-00-00 date
+ TIME_INVALID_DATES Allow 2000-02-31
+ was_cut 0 Value ok
+ 1 If value was cut during conversion
+ 2 Date part was within ranges but date was wrong
DESCRIPTION
At least the following formats are recogniced (based on number of digits)
@@ -104,11 +164,11 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
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;
+ my_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;
+ my_bool found_delimitier= 0, found_space= 0;
uint frac_pos, frac_len;
DBUG_ENTER("str_to_datetime");
DBUG_PRINT("ENTER",("str: %.*s",length,str));
@@ -349,8 +409,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
if (number_of_fields < 3 ||
l_time->year > 9999 || 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)))
+ l_time->minute > 59 || l_time->second > 59)
{
/* Only give warning for a zero date if there is some garbage after */
if (!not_zero_date) /* If zero date */
@@ -364,11 +423,13 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
}
}
}
- if (not_zero_date)
- *was_cut= 1;
+ *was_cut= test(not_zero_date);
goto err;
}
+ if (check_date(l_time, not_zero_date, flags, was_cut))
+ goto err;
+
l_time->time_type= (number_of_fields <= 3 ?
MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);
@@ -414,12 +475,12 @@ err:
1 error
*/
-bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
- int *was_cut)
+my_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;
+ my_bool found_days,found_hours;
uint state;
l_time->neg=0;
@@ -586,7 +647,7 @@ void init_time(void)
time_t seconds;
struct tm *l_time,tm_tmp;
MYSQL_TIME my_time;
- bool not_used;
+ my_bool not_used;
seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp);
@@ -652,7 +713,8 @@ long calc_daynr(uint year,uint month,uint day)
Time in UTC seconds since Unix Epoch representation.
*/
my_time_t
-my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
+my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone,
+ my_bool *in_dst_time_gap)
{
uint loop;
time_t tmp;
@@ -816,3 +878,172 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to)
return 0;
}
}
+
+
+/*
+ Convert datetime value specified as number to broken-down TIME
+ representation and form value of DATETIME type as side-effect.
+
+ SYNOPSIS
+ number_to_datetime()
+ nr - datetime value as number
+ time_res - pointer for structure for broken-down representation
+ flags - flags to use in validating date, as in str_to_datetime()
+ was_cut 0 Value ok
+ 1 If value was cut during conversion
+ 2 Date part was within ranges but date was wrong
+
+ 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
+ -1 Timestamp with wrong values
+ anything else DATETIME as integer in YYYYMMDDHHMMSS format
+ Datetime value in YYYYMMDDHHMMSS format.
+*/
+
+longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
+ uint flags, int *was_cut)
+{
+ long part1,part2;
+
+ *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)
+ {
+ 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 &&
+ !check_date(time_res, (nr != 0), flags, was_cut))
+ return nr;
+
+ /* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */
+ if (!nr && (flags & TIME_NO_ZERO_DATE))
+ return LL(-1);
+
+ err:
+ *was_cut= 1;
+ return LL(-1);
+}
+
+
+/* Convert time value to integer in YYYYMMDDHHMMSS format */
+
+ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *time)
+{
+ return ((ulonglong) (time->year * 10000UL +
+ time->month * 100UL +
+ time->day) * ULL(1000000) +
+ (ulonglong) (time->hour * 10000UL +
+ time->minute * 100UL +
+ time->second));
+}
+
+
+/* Convert TIME value to integer in YYYYMMDD format */
+
+ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *time)
+{
+ return (ulonglong) (time->year * 10000UL + time->month * 100UL + time->day);
+}
+
+
+/*
+ Convert TIME value to integer in HHMMSS format.
+ This function doesn't take into account time->day member:
+ it's assumed that days have been converted to hours already.
+*/
+
+ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *time)
+{
+ return (ulonglong) (time->hour * 10000UL +
+ time->minute * 100UL +
+ time->second);
+}
+
+
+/*
+ Convert struct TIME (date and time split into year/month/day/hour/...
+ to a number in format YYYYMMDDHHMMSS (DATETIME),
+ YYYYMMDD (DATE) or HHMMSS (TIME).
+
+ SYNOPSIS
+ TIME_to_ulonglong()
+
+ DESCRIPTION
+ The function is used when we need to convert value of time item
+ to a number if it's used in numeric context, i. e.:
+ SELECT NOW()+1, CURDATE()+0, CURTIMIE()+0;
+ SELECT ?+1;
+
+ NOTE
+ This function doesn't check that given TIME structure members are
+ in valid range. If they are not, return value won't reflect any
+ valid date either.
+*/
+
+ulonglong TIME_to_ulonglong(const MYSQL_TIME *time)
+{
+ switch (time->time_type) {
+ case MYSQL_TIMESTAMP_DATETIME:
+ return TIME_to_ulonglong_datetime(time);
+ case MYSQL_TIMESTAMP_DATE:
+ return TIME_to_ulonglong_date(time);
+ case MYSQL_TIMESTAMP_TIME:
+ return TIME_to_ulonglong_time(time);
+ case MYSQL_TIMESTAMP_NONE:
+ case MYSQL_TIMESTAMP_ERROR:
+ return ULL(0);
+ default:
+ DBUG_ASSERT(0);
+ }
+ return 0;
+}
+
diff --git a/sql/Makefile.am b/sql/Makefile.am
index ea7cea9c7b9..4824a75d6fa 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -19,7 +19,7 @@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
-INCLUDES = @MT_INCLUDES@ @ZLIB_INCLUDES@ \
+INCLUDES = @ZLIB_INCLUDES@ \
@bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \
-I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_srcdir)/regex -I$(srcdir) $(openssl_includes)
@@ -29,8 +29,7 @@ libexec_PROGRAMS = mysqld
noinst_PROGRAMS = gen_lex_hash
bin_PROGRAMS = mysql_tzinfo_to_sql
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
-LDADD = @isam_libs@ \
- $(top_builddir)/myisam/libmyisam.a \
+LDADD = $(top_builddir)/myisam/libmyisam.a \
$(top_builddir)/myisammrg/libmyisammrg.a \
$(top_builddir)/heap/libheap.a \
$(top_builddir)/vio/libvio.a \
@@ -50,8 +49,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
mysql_priv.h item_geofunc.h sql_bitmap.h \
procedure.h sql_class.h sql_lex.h sql_list.h \
sql_manager.h sql_map.h sql_string.h unireg.h \
- field.h handler.h mysqld_suffix.h \
- ha_isammrg.h ha_isam.h ha_myisammrg.h\
+ sql_error.h field.h handler.h mysqld_suffix.h \
+ ha_myisammrg.h\
ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
ha_ndbcluster.h opt_range.h protocol.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
@@ -59,8 +58,13 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.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 tzfile.h \
- tztime.h examples/ha_example.h examples/ha_archive.h \
- examples/ha_tina.h ha_blackhole.h
+ tztime.h my_decimal.h\
+ sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
+ parse_file.h sql_view.h sql_trigger.h \
+ sql_array.h \
+ examples/ha_example.h examples/ha_archive.h \
+ examples/ha_tina.h ha_blackhole.h \
+ ha_federated.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
@@ -82,17 +86,21 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
records.cc filesort.cc handler.cc \
ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
ha_berkeley.cc ha_innodb.cc \
- ha_isam.cc ha_isammrg.cc ha_ndbcluster.cc \
+ ha_ndbcluster.cc \
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
slave.cc sql_repl.cc sql_union.cc sql_derived.cc \
client.c sql_client.cc mini_client_errors.c pack.c\
stacktrace.c repl_failsafe.h repl_failsafe.cc \
+ sql_olap.cc sql_view.cc \
gstream.cc spatial.cc sql_help.cc protocol_cursor.cc \
- tztime.cc my_time.c \
+ tztime.cc my_time.c my_decimal.cc\
+ sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
+ sp_cache.cc parse_file.cc sql_trigger.cc \
examples/ha_example.cc examples/ha_archive.cc \
- examples/ha_tina.cc ha_blackhole.cc
+ examples/ha_tina.cc ha_blackhole.cc \
+ ha_federated.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
@@ -107,6 +115,7 @@ DEFS = -DMYSQL_SERVER \
BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h
EXTRA_DIST = udf_example.cc $(BUILT_SOURCES)
+DISTCLEANFILES = lex_hash.h
AM_YFLAGS = -d
mysql_tzinfo_to_sql.cc:
@@ -145,8 +154,5 @@ lex_hash.h: gen_lex_hash$(EXEEXT)
udf_example.so: udf_example.cc
$(CXXCOMPILE) -shared -o $@ $<
-distclean:
- rm -f lex_hash.h
-
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/sql/derror.cc b/sql/derror.cc
index 09f43d20044..bee818a14c1 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -24,15 +24,43 @@ static bool read_texts(const char *file_name,const char ***point,
uint error_messages);
static void init_myfunc_errs(void);
- /* Read messages from errorfile */
+/*
+ Read messages from errorfile.
+
+ SYNOPSIS
+ init_errmessage()
+
+ DESCRIPTION
+ This function can be called multiple times to reload the messages.
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
bool init_errmessage(void)
{
+ const char **errmsgs;
DBUG_ENTER("init_errmessage");
- if (read_texts(ERRMSG_FILE,&my_errmsg[ERRMAPP],ER_ERROR_MESSAGES))
+ /*
+ Get a pointer to the old error messages pointer array.
+ read_texts() tries to free it.
+ */
+ errmsgs= my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST);
+
+ /* Read messages from file. */
+ if (read_texts(ERRMSG_FILE, &errmsgs, ER_ERROR_LAST - ER_ERROR_FIRST + 1))
DBUG_RETURN(TRUE);
- errmesg=my_errmsg[ERRMAPP]; /* Init global variabel */
+
+ /* Register messages for use with my_error(). */
+ if (my_error_register(errmsgs, ER_ERROR_FIRST, ER_ERROR_LAST))
+ {
+ x_free((gptr) errmsgs);
+ DBUG_RETURN(TRUE);
+ }
+
+ errmesg= errmsgs; /* Init global variabel */
init_myfunc_errs(); /* Init myfunc messages */
DBUG_RETURN(FALSE);
}
@@ -50,7 +78,6 @@ static bool read_texts(const char *file_name,const char ***point,
char name[FN_REFLEN];
const char *buff;
uchar head[32],*pos;
- CHARSET_INFO *cset; // For future
DBUG_ENTER("read_texts");
*point=0; // If something goes wrong
@@ -76,7 +103,7 @@ Please install the latest version of this file.",name);
}
/* TODO: Convert the character set to server system character set */
- if (!(cset= get_charset(head[30],MYF(MY_WME))))
+ if (!get_charset(head[30],MYF(MY_WME)))
{
sql_print_error("Character set #%d is not supported for messagefile '%s'",
(int)head[30],name);
@@ -148,20 +175,20 @@ static void init_myfunc_errs()
init_glob_errs(); /* Initiate english errors */
if (!(specialflag & SPECIAL_ENGLISH))
{
- globerrs[EE_FILENOTFOUND % ERRMOD] = ER(ER_FILE_NOT_FOUND);
- globerrs[EE_CANTCREATEFILE % ERRMOD]= ER(ER_CANT_CREATE_FILE);
- globerrs[EE_READ % ERRMOD] = ER(ER_ERROR_ON_READ);
- globerrs[EE_WRITE % ERRMOD] = ER(ER_ERROR_ON_WRITE);
- globerrs[EE_BADCLOSE % ERRMOD] = ER(ER_ERROR_ON_CLOSE);
- globerrs[EE_OUTOFMEMORY % ERRMOD] = ER(ER_OUTOFMEMORY);
- globerrs[EE_DELETE % ERRMOD] = ER(ER_CANT_DELETE_FILE);
- globerrs[EE_LINK % ERRMOD] = ER(ER_ERROR_ON_RENAME);
- globerrs[EE_EOFERR % ERRMOD] = ER(ER_UNEXPECTED_EOF);
- globerrs[EE_CANTLOCK % ERRMOD] = ER(ER_CANT_LOCK);
- globerrs[EE_DIR % ERRMOD] = ER(ER_CANT_READ_DIR);
- globerrs[EE_STAT % ERRMOD] = ER(ER_CANT_GET_STAT);
- globerrs[EE_GETWD % ERRMOD] = ER(ER_CANT_GET_WD);
- globerrs[EE_SETWD % ERRMOD] = ER(ER_CANT_SET_WD);
- globerrs[EE_DISK_FULL % ERRMOD] = ER(ER_DISK_FULL);
+ EE(EE_FILENOTFOUND) = ER(ER_FILE_NOT_FOUND);
+ EE(EE_CANTCREATEFILE) = ER(ER_CANT_CREATE_FILE);
+ EE(EE_READ) = ER(ER_ERROR_ON_READ);
+ EE(EE_WRITE) = ER(ER_ERROR_ON_WRITE);
+ EE(EE_BADCLOSE) = ER(ER_ERROR_ON_CLOSE);
+ EE(EE_OUTOFMEMORY) = ER(ER_OUTOFMEMORY);
+ EE(EE_DELETE) = ER(ER_CANT_DELETE_FILE);
+ EE(EE_LINK) = ER(ER_ERROR_ON_RENAME);
+ EE(EE_EOFERR) = ER(ER_UNEXPECTED_EOF);
+ EE(EE_CANTLOCK) = ER(ER_CANT_LOCK);
+ EE(EE_DIR) = ER(ER_CANT_READ_DIR);
+ EE(EE_STAT) = ER(ER_CANT_GET_STAT);
+ EE(EE_GETWD) = ER(ER_CANT_GET_WD);
+ EE(EE_SETWD) = ER(ER_CANT_SET_WD);
+ EE(EE_DISK_FULL) = ER(ER_DISK_FULL);
}
}
diff --git a/sql/des_key_file.cc b/sql/des_key_file.cc
index 342939ad8ba..77cb0c8de0f 100644
--- a/sql/des_key_file.cc
+++ b/sql/des_key_file.cc
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <mysql_priv.h>
+#include "mysql_priv.h"
#include <m_ctype.h>
#ifdef HAVE_OPENSSL
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
index ee4cad25460..85104405024 100644
--- a/sql/examples/ha_archive.cc
+++ b/sql/examples/ha_archive.cc
@@ -22,6 +22,7 @@
#ifdef HAVE_ARCHIVE_DB
#include "ha_archive.h"
+#include <my_dir.h>
/*
First, if you want to understand storage engines you should look at
@@ -134,6 +135,28 @@ static HASH archive_open_tables;
#define DATA_BUFFER_SIZE 2 // Size of the data used in the data file
#define ARCHIVE_CHECK_HEADER 254 // The number we use to determine corruption
+/* dummy handlerton - only to have something to return from archive_db_init */
+static handlerton archive_hton = {
+ "archive",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* releas savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
+
/*
Used for hash table that tracks open tables.
*/
@@ -153,19 +176,20 @@ static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length,
void
RETURN
- FALSE OK
- TRUE Error
+ &archive_hton OK
+ 0 Error
*/
-bool archive_db_init()
+handlerton *archive_db_init()
{
archive_inited= 1;
VOID(pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST));
- return (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
- (hash_get_key) archive_get_key, 0, 0));
+ if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
+ (hash_get_key) archive_get_key, 0, 0))
+ return 0;
+ return &archive_hton;
}
-
/*
Release the archive handler.
@@ -188,6 +212,15 @@ bool archive_db_end()
return FALSE;
}
+ha_archive::ha_archive(TABLE *table_arg)
+ :handler(&archive_hton, table_arg), delayed_insert(0), bulk_insert(0)
+{
+ /* Set our original buffer from pre-allocated memory */
+ buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
+
+ /* The size of the offset value we will use for position() */
+ ref_length = sizeof(z_off_t);
+}
/*
This method reads the header of a datafile and returns whether or not it was successful.
@@ -239,7 +272,7 @@ error:
This method reads the header of a meta file and returns whether or not it was successful.
*rows will contain the current number of rows in the data file upon success.
*/
-int ha_archive::read_meta_file(File meta_file, ulonglong *rows)
+int ha_archive::read_meta_file(File meta_file, ha_rows *rows)
{
uchar meta_buffer[META_BUFFER_SIZE];
ulonglong check_point;
@@ -253,7 +286,7 @@ int ha_archive::read_meta_file(File meta_file, ulonglong *rows)
/*
Parse out the meta data, we ignore version at the moment
*/
- *rows= uint8korr(meta_buffer + 2);
+ *rows= (ha_rows)uint8korr(meta_buffer + 2);
check_point= uint8korr(meta_buffer + 10);
DBUG_PRINT("ha_archive::read_meta_file", ("Check %d", (uint)meta_buffer[0]));
@@ -274,10 +307,9 @@ int ha_archive::read_meta_file(File meta_file, ulonglong *rows)
/*
This method writes out the header of a meta file and returns whether or not it was successful.
By setting dirty you say whether or not the file represents the actual state of the data file.
- Upon ::open() we set to dirty, and upon ::close() we set to clean. If we determine during
- a read that the file was dirty we will force a rebuild of this file.
+ Upon ::open() we set to dirty, and upon ::close() we set to clean.
*/
-int ha_archive::write_meta_file(File meta_file, ulonglong rows, bool dirty)
+int ha_archive::write_meta_file(File meta_file, ha_rows rows, bool dirty)
{
uchar meta_buffer[META_BUFFER_SIZE];
ulonglong check_point= 0; //Reserved for the future
@@ -286,12 +318,12 @@ int ha_archive::write_meta_file(File meta_file, ulonglong rows, bool dirty)
meta_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER;
meta_buffer[1]= (uchar)ARCHIVE_VERSION;
- int8store(meta_buffer + 2, rows);
+ int8store(meta_buffer + 2, (ulonglong)rows);
int8store(meta_buffer + 10, check_point);
*(meta_buffer + 18)= (uchar)dirty;
DBUG_PRINT("ha_archive::write_meta_file", ("Check %d", (uint)ARCHIVE_CHECK_HEADER));
DBUG_PRINT("ha_archive::write_meta_file", ("Version %d", (uint)ARCHIVE_VERSION));
- DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", rows));
+ DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", (ulonglong)rows));
DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %llu", check_point));
DBUG_PRINT("ha_archive::write_meta_file", ("Dirty %d", (uint)dirty));
@@ -307,6 +339,9 @@ int ha_archive::write_meta_file(File meta_file, ulonglong rows, bool dirty)
/*
We create the shared memory space that we will use for the open table.
+ No matter what we try to get or create a share. This is so that a repair
+ table operation can occur.
+
See ha_example.cc for a longer description.
*/
ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
@@ -335,6 +370,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
share->use_count= 0;
share->table_name_length= length;
share->table_name= tmp_name;
+ share->crashed= FALSE;
fn_format(share->data_file_name,table_name,"",ARZ,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
fn_format(meta_file_name,table_name,"",ARM,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
strmov(share->table_name,table_name);
@@ -343,26 +379,17 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
*/
VOID(pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST));
if ((share->meta_file= my_open(meta_file_name, O_RDWR, MYF(0))) == -1)
- goto error;
+ share->crashed= TRUE;
- if (read_meta_file(share->meta_file, &share->rows_recorded))
- {
- /*
- The problem here is that for some reason, probably a crash, the meta
- file has been corrupted. So what do we do? Well we try to rebuild it
- ourself. Once that happens, we reread it, but if that fails we just
- call it quits and return an error.
- */
- if (rebuild_meta_file(share->table_name, share->meta_file))
- goto error;
- if (read_meta_file(share->meta_file, &share->rows_recorded))
- goto error;
- }
/*
After we read, we set the file to dirty. When we close, we will do the
- opposite.
+ opposite. If the meta file will not open we assume it is crashed and
+ leave it up to the user to fix.
*/
- (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
+ if (read_meta_file(share->meta_file, &share->rows_recorded))
+ share->crashed= TRUE;
+ else
+ (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
/*
It is expensive to open and close the data files and since you can't have
@@ -370,27 +397,14 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
that is shared amoung all open tables.
*/
if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
- goto error2;
- if (my_hash_insert(&archive_open_tables, (byte*) share))
- goto error3;
+ share->crashed= TRUE;
+ VOID(my_hash_insert(&archive_open_tables, (byte*) share));
thr_lock_init(&share->lock);
}
share->use_count++;
pthread_mutex_unlock(&archive_mutex);
return share;
-
-error3:
- /* We close, but ignore errors since we already have errors */
- (void)gzclose(share->archive_write);
-error2:
- my_close(share->meta_file,MYF(0));
-error:
- pthread_mutex_unlock(&archive_mutex);
- VOID(pthread_mutex_destroy(&share->mutex));
- my_free((gptr) share, MYF(0));
-
- return NULL;
}
@@ -420,11 +434,20 @@ int ha_archive::free_share(ARCHIVE_SHARE *share)
}
-/*
+/*
We just implement one additional file extension.
*/
+static const char *ha_archive_exts[] = {
+ ARZ,
+ ARN,
+ ARM,
+ NullS
+};
+
const char **ha_archive::bas_ext() const
-{ static const char *ext[]= { ARZ, ARN, ARM, NullS }; return ext; }
+{
+ return ha_archive_exts;
+}
/*
@@ -438,13 +461,14 @@ 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);
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM); // Not handled well by calling code!
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(errno ? errno : -1);
+ if (errno == EROFS || errno == EACCES)
+ DBUG_RETURN(my_errno= errno);
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
}
DBUG_RETURN(0);
@@ -552,6 +576,44 @@ error:
DBUG_RETURN(error ? error : -1);
}
+/*
+ This is where the actual row is written out.
+*/
+int ha_archive::real_write_row(byte *buf, gzFile writer)
+{
+ z_off_t written;
+ uint *ptr, *end;
+ DBUG_ENTER("ha_archive::real_write_row");
+
+ written= gzwrite(writer, buf, table->s->reclength);
+ DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength));
+ if (!delayed_insert || !bulk_insert)
+ share->dirty= TRUE;
+
+ if (written != (z_off_t)table->s->reclength)
+ DBUG_RETURN(errno ? errno : -1);
+ /*
+ We should probably mark the table as damagaged if the record is written
+ but the blob fails.
+ */
+ for (ptr= table->s->blob_field, end= ptr + table->s->blob_fields ;
+ ptr != end ;
+ ptr++)
+ {
+ char *data_ptr;
+ uint32 size= ((Field_blob*) table->field[*ptr])->get_length();
+
+ if (size)
+ {
+ ((Field_blob*) table->field[*ptr])->get_ptr(&data_ptr);
+ written= gzwrite(writer, data_ptr, (unsigned)size);
+ if (written != (z_off_t)size)
+ DBUG_RETURN(errno ? errno : -1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
/*
Look at ha_archive::open() for an explanation of the row format.
@@ -562,48 +624,25 @@ error:
for implementing start_bulk_insert() is that we could skip
setting dirty to true each time.
*/
-int ha_archive::write_row(byte * buf)
+int ha_archive::write_row(byte *buf)
{
- z_off_t written;
- Field_blob **field;
+ int rc;
DBUG_ENTER("ha_archive::write_row");
- statistic_increment(ha_write_count,&LOCK_status);
+ if (share->crashed)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
+ statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
pthread_mutex_lock(&share->mutex);
- written= gzwrite(share->archive_write, buf, table->reclength);
- DBUG_PRINT("ha_archive::get_row", ("Wrote %d bytes expected %d", written, table->reclength));
- share->dirty= TRUE;
- if (written != (z_off_t)table->reclength)
- goto error;
- /*
- We should probably mark the table as damagaged if the record is written
- but the blob fails.
- */
- for (field= table->blob_field ; *field ; field++)
- {
- char *ptr;
- uint32 size= (*field)->get_length();
-
- if (size)
- {
- (*field)->get_ptr(&ptr);
- written= gzwrite(share->archive_write, ptr, (unsigned)size);
- if (written != (z_off_t)size)
- goto error;
- }
- }
share->rows_recorded++;
+ rc= real_write_row(buf, share->archive_write);
pthread_mutex_unlock(&share->mutex);
- DBUG_RETURN(0);
-error:
- pthread_mutex_unlock(&share->mutex);
- DBUG_RETURN(errno ? errno : -1);
+ DBUG_RETURN(rc);
}
-
/*
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
@@ -613,6 +652,9 @@ error:
int ha_archive::rnd_init(bool scan)
{
DBUG_ENTER("ha_archive::rnd_init");
+
+ if (share->crashed)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
/* We rewind the file so that we can read from the beginning if scan */
if (scan)
@@ -650,13 +692,13 @@ int ha_archive::rnd_init(bool scan)
int ha_archive::get_row(gzFile file_to_read, byte *buf)
{
int read; // Bytes read, gzread() returns int
+ uint *ptr, *end;
char *last;
size_t total_blob_length= 0;
- Field_blob **field;
DBUG_ENTER("ha_archive::get_row");
- read= gzread(file_to_read, buf, table->reclength);
- DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->reclength));
+ read= gzread(file_to_read, buf, table->s->reclength);
+ DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->s->reclength));
if (read == Z_STREAM_ERROR)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
@@ -665,28 +707,35 @@ int ha_archive::get_row(gzFile file_to_read, byte *buf)
if (read == 0)
DBUG_RETURN(HA_ERR_END_OF_FILE);
- /* If the record is the wrong size, the file is probably damaged */
- if ((ulong) read != table->reclength)
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ /*
+ If the record is the wrong size, the file is probably damaged, unless
+ we are dealing with a delayed insert or a bulk insert.
+ */
+ if ((ulong) read != table->s->reclength)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
/* Calculate blob length, we use this for our buffer */
- for (field=table->blob_field; *field ; field++)
- total_blob_length += (*field)->get_length();
+ for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
+ ptr != end ;
+ ptr++)
+ total_blob_length += ((Field_blob*) table->field[*ptr])->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=table->blob_field; *field ; field++)
+ for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
+ ptr != end ;
+ ptr++)
{
- size_t size= (*field)->get_length();
+ size_t size= ((Field_blob*) table->field[*ptr])->get_length();
if (size)
{
read= gzread(file_to_read, last, size);
if ((size_t) read != size)
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- (*field)->set_ptr(size, last);
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ ((Field_blob*) table->field[*ptr])->set_ptr(size, last);
last += size;
}
}
@@ -704,11 +753,15 @@ int ha_archive::rnd_next(byte *buf)
int rc;
DBUG_ENTER("ha_archive::rnd_next");
+ if (share->crashed)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
if (!scan_rows)
DBUG_RETURN(HA_ERR_END_OF_FILE);
scan_rows--;
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
current_position= gztell(archive);
rc= get_row(archive, buf);
@@ -720,7 +773,7 @@ int ha_archive::rnd_next(byte *buf)
}
-/*
+/*
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.
@@ -729,7 +782,7 @@ int ha_archive::rnd_next(byte *buf)
void ha_archive::position(const byte *record)
{
DBUG_ENTER("ha_archive::position");
- ha_store_ptr(ref, ref_length, current_position);
+ my_store_ptr(ref, ref_length, current_position);
DBUG_VOID_RETURN;
}
@@ -744,68 +797,30 @@ void ha_archive::position(const byte *record)
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);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
+ current_position= (z_off_t)my_get_ptr(pos, ref_length);
(void)gzseek(archive, current_position, SEEK_SET);
DBUG_RETURN(get_row(archive, buf));
}
/*
- This method rebuilds the meta file. It does this by walking the datafile and
- rewriting the meta file.
+ This method repairs the meta file. It does this by walking the datafile and
+ rewriting the meta file. Currently it does this by calling optimize with
+ the extended flag.
*/
-int ha_archive::rebuild_meta_file(char *table_name, File meta_file)
+int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
{
- int rc;
- byte *buf;
- ulonglong rows_recorded= 0;
- gzFile rebuild_file; /* Archive file we are working with */
- char data_file_name[FN_REFLEN];
- DBUG_ENTER("ha_archive::rebuild_meta_file");
+ DBUG_ENTER("ha_archive::repair");
+ check_opt->flags= T_EXTEND;
+ int rc= optimize(thd, check_opt);
- /*
- Open up the meta file to recreate it.
- */
- fn_format(data_file_name, table_name, "", ARZ,
- MY_REPLACE_EXT|MY_UNPACK_FILENAME);
- if ((rebuild_file= gzopen(data_file_name, "rb")) == NULL)
- DBUG_RETURN(errno ? errno : -1);
+ if (rc)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
- if ((rc= read_data_header(rebuild_file)))
- goto error;
-
- /*
- We malloc up the buffer we will use for counting the rows.
- I know, this malloc'ing memory but this should be a very
- rare event.
- */
- if (!(buf= (byte*) my_malloc(table->rec_buff_length > sizeof(ulonglong) +1 ?
- table->rec_buff_length : sizeof(ulonglong) +1 ,
- MYF(MY_WME))))
- {
- rc= HA_ERR_CRASHED_ON_USAGE;
- goto error;
- }
-
- while (!(rc= get_row(rebuild_file, buf)))
- rows_recorded++;
-
- /*
- Only if we reach the end of the file do we assume we can rewrite.
- At this point we reset rc to a non-message state.
- */
- if (rc == HA_ERR_END_OF_FILE)
- {
- (void)write_meta_file(meta_file, rows_recorded, FALSE);
- rc= 0;
- }
-
- my_free((gptr) buf, MYF(0));
-error:
- gzclose(rebuild_file);
-
- DBUG_RETURN(rc);
+ share->crashed= FALSE;
+ DBUG_RETURN(0);
}
/*
@@ -815,56 +830,99 @@ error:
int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("ha_archive::optimize");
- int read; // Bytes read, gzread() returns int
- gzFile reader, writer;
- char block[IO_SIZE];
+ int rc;
+ gzFile writer;
char writer_filename[FN_REFLEN];
+ /* Flush any waiting data */
+ gzflush(share->archive_write, Z_SYNC_FLUSH);
+
/* Lets create a file to contain the new data */
fn_format(writer_filename, share->table_name, "", ARN,
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
- /* Closing will cause all data waiting to be flushed, to be flushed */
- gzclose(share->archive_write);
+ if ((writer= gzopen(writer_filename, "wb")) == NULL)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- if ((reader= gzopen(share->data_file_name, "rb")) == NULL)
- DBUG_RETURN(-1);
+ /*
+ An extended rebuild is a lot more effort. We open up each row and re-record it.
+ Any dead rows are removed (aka rows that may have been partially recorded).
+ */
- if ((writer= gzopen(writer_filename, "wb")) == NULL)
+ if (check_opt->flags == T_EXTEND)
{
- gzclose(reader);
- DBUG_RETURN(-1);
- }
+ byte *buf;
- while ((read= gzread(reader, block, IO_SIZE)))
- gzwrite(writer, block, read);
+ /*
+ First we create a buffer that we can use for reading rows, and can pass
+ to get_row().
+ */
+ if (!(buf= (byte*) my_malloc(table->s->reclength, MYF(MY_WME))))
+ {
+ rc= HA_ERR_OUT_OF_MEM;
+ goto error;
+ }
- gzclose(reader);
- gzclose(writer);
+ /*
+ Now we will rewind the archive file so that we are positioned at the
+ start of the file.
+ */
+ rc= read_data_header(archive);
+
+ /*
+ Assuming now error from rewinding the archive file, we now write out the
+ new header for out data file.
+ */
+ if (!rc)
+ rc= write_data_header(writer);
- my_rename(writer_filename,share->data_file_name,MYF(0));
+ /*
+ On success of writing out the new header, we now fetch each row and
+ insert it into the new archive file.
+ */
+ if (!rc)
+ {
+ share->rows_recorded= 0;
+ while (!(rc= get_row(archive, buf)))
+ {
+ real_write_row(buf, writer);
+ share->rows_recorded++;
+ }
+ }
- /*
- We reopen the file in case some IO is waiting to go through.
- In theory the table is closed right after this operation,
- but it is possible for IO to still happen.
- I may be being a bit too paranoid right here.
- */
- if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
- DBUG_RETURN(errno ? errno : -1);
- share->dirty= FALSE;
+ my_free((char*)buf, MYF(0));
+ if (rc && rc != HA_ERR_END_OF_FILE)
+ goto error;
+ }
+ else
+ {
+ /*
+ The quick method is to just read the data raw, and then compress it directly.
+ */
+ int read; // Bytes read, gzread() returns int
+ char block[IO_SIZE];
+ if (gzrewind(archive) == -1)
+ {
+ rc= HA_ERR_CRASHED_ON_USAGE;
+ goto error;
+ }
+
+ while ((read= gzread(archive, block, IO_SIZE)))
+ gzwrite(writer, block, read);
+ }
+
+ gzflush(writer, Z_SYNC_FLUSH);
+ gzclose(share->archive_write);
+ share->archive_write= writer;
+
+ my_rename(writer_filename,share->data_file_name,MYF(0));
DBUG_RETURN(0);
-}
+error:
+ gzclose(writer);
-/*
- No transactions yet, so this is pretty dull.
-*/
-int ha_archive::external_lock(THD *thd, int lock_type)
-{
- DBUG_ENTER("ha_archive::external_lock");
- DBUG_RETURN(0);
+ DBUG_RETURN(rc);
}
/*
@@ -874,6 +932,11 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
+ if (lock_type == TL_WRITE_DELAYED)
+ delayed_insert= TRUE;
+ else
+ delayed_insert= FALSE;
+
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
{
/*
@@ -908,98 +971,62 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
}
-/******************************************************************************
-
- 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);
-}
-
-
+/*
+ Hints for optimizer, see ha_tina for more information
+*/
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 */
+ /*
+ This should be an accurate number now, though bulk and delayed inserts can
+ cause the number to be inaccurate.
+ */
records= share->rows_recorded;
deleted= 0;
+ /* Costs quite a bit more to get all information */
+ if (flag & HA_STATUS_TIME)
+ {
+ MY_STAT file_stat; // Stat information for the data file
+
+ VOID(my_stat(share->data_file_name, &file_stat, MYF(MY_WME)));
+
+ mean_rec_length= table->s->reclength + buffer.alloced_length();
+ data_file_length= file_stat.st_size;
+ create_time= file_stat.st_ctime;
+ update_time= file_stat.st_mtime;
+ max_data_file_length= share->rows_recorded * mean_rec_length;
+ }
+ delete_length= 0;
+ index_file_length=0;
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)
+/*
+ This method tells us that a bulk insert operation is about to occur. We set
+ a flag which will keep write_row from saying that its data is dirty. This in
+ turn will keep selects from causing a sync to occur.
+ Basically, yet another optimizations to keep compression working well.
+*/
+void ha_archive::start_bulk_insert(ha_rows rows)
{
- DBUG_ENTER("ha_archive::reset");
- DBUG_RETURN(0);
+ DBUG_ENTER("ha_archive::start_bulk_insert");
+ bulk_insert= TRUE;
+ DBUG_VOID_RETURN;
}
-ha_rows ha_archive::records_in_range(uint inx, key_range *min_key,
- key_range *max_key)
+
+/*
+ Other side of start_bulk_insert, is end_bulk_insert. Here we turn off the bulk insert
+ flag, and set the share dirty so that the next select will call sync for us.
+*/
+int ha_archive::end_bulk_insert()
{
- DBUG_ENTER("ha_archive::records_in_range ");
- DBUG_RETURN(records); // HA_ERR_WRONG_COMMAND
+ DBUG_ENTER("ha_archive::end_bulk_insert");
+ bulk_insert= FALSE;
+ share->dirty= TRUE;
+ DBUG_RETURN(0);
}
/*
diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h
index 6ceb660e951..e2d8aa49add 100644
--- a/sql/examples/ha_archive.h
+++ b/sql/examples/ha_archive.h
@@ -32,10 +32,11 @@ typedef struct st_archive_share {
uint table_name_length,use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
- File meta_file; /* Meta file we use */
- gzFile archive_write; /* Archive file we are working with */
- bool dirty; /* Flag for if a flush should occur */
- ulonglong rows_recorded; /* Number of rows in tables */
+ File meta_file; /* Meta file we use */
+ gzFile archive_write; /* Archive file we are working with */
+ bool dirty; /* Flag for if a flush should occur */
+ bool crashed; /* Meta file is crashed */
+ ha_rows rows_recorded; /* Number of rows in tables */
} ARCHIVE_SHARE;
/*
@@ -52,17 +53,12 @@ class ha_archive: public handler
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 */
- ulonglong scan_rows; /* Number of rows left in scan */
+ ha_rows scan_rows; /* Number of rows left in scan */
+ bool delayed_insert; /* If the insert is delayed */
+ bool bulk_insert; /* If we are performing a bulk insert */
public:
- ha_archive(TABLE *table): handler(table)
- {
- /* Set our original buffer from pre-allocated memory */
- buffer.set((char*)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(TABLE *table_arg);
~ha_archive()
{
}
@@ -72,61 +68,43 @@ public:
ulong table_flags() const
{
return (HA_REC_NOT_IN_SEQ | HA_NOT_EXACT_COUNT | HA_NO_AUTO_INCREMENT |
- HA_FILE_BASED);
+ HA_FILE_BASED | HA_CAN_INSERT_DELAYED);
}
ulong index_flags(uint idx, uint part, bool all_parts) 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(uint index, uint ranges, 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 real_write_row(byte *buf, gzFile writer);
int delete_all_rows();
- 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(gzFile file_to_read, byte *buf);
- int read_meta_file(File meta_file, ulonglong *rows);
- int write_meta_file(File meta_file, ulonglong rows, bool dirty);
+ int read_meta_file(File meta_file, ha_rows *rows);
+ int write_meta_file(File meta_file, ha_rows rows, bool dirty);
ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table);
int free_share(ARCHIVE_SHARE *share);
- int rebuild_meta_file(char *table_name, File meta_file);
+ bool auto_repair() const { return 1; } // For the moment we just do this
int read_data_header(gzFile file_to_read);
int write_data_header(gzFile file_to_write);
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(uint inx, key_range *min_key, key_range *max_key);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
+ int repair(THD* thd, HA_CHECK_OPT* check_opt);
+ void start_bulk_insert(ha_rows rows);
+ int end_bulk_insert();
+ enum row_type get_row_type() const
+ {
+ return ROW_TYPE_COMPRESSED;
+ }
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
};
-bool archive_db_init(void);
+handlerton *archive_db_init(void);
bool archive_db_end(void);
diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc
index b3edce5ba4a..dfc2fa7a260 100644
--- a/sql/examples/ha_example.cc
+++ b/sql/examples/ha_example.cc
@@ -72,6 +72,27 @@
#ifdef HAVE_EXAMPLE_DB
#include "ha_example.h"
+
+static handlerton example_hton= {
+ "CSV",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
/* Variables for example share methods */
static HASH example_open_tables; // Hash used to track open tables
pthread_mutex_t example_mutex; // This is the mutex we use to init the hash
@@ -179,13 +200,23 @@ static int free_share(EXAMPLE_SHARE *share)
}
+ha_example::ha_example(TABLE *table_arg)
+ :handler(&example_hton, table_arg)
+{}
+
/*
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.
*/
+static const char *ha_example_exts[] = {
+ NullS
+};
+
const char **ha_example::bas_ext() const
-{ static const char *ext[]= { NullS }; return ext; }
+{
+ return ha_example_exts;
+}
/*
@@ -412,7 +443,7 @@ int ha_example::rnd_next(byte *buf)
position() is called after each call to rnd_next() if the data needs
to be ordered. You can do something like the following to store
the position:
- ha_store_ptr(ref, ref_length, current_position);
+ my_store_ptr(ref, ref_length, current_position);
The server uses ref to store data. ref_length in the above case is
the size needed to store current_position. ref is just a byte array
diff --git a/sql/examples/ha_example.h b/sql/examples/ha_example.h
index ae72e5bb275..37f38fe5210 100644
--- a/sql/examples/ha_example.h
+++ b/sql/examples/ha_example.h
@@ -45,9 +45,7 @@ class ha_example: public handler
EXAMPLE_SHARE *share; /* Shared lock info */
public:
- ha_example(TABLE *table): handler(table)
- {
- }
+ ha_example(TABLE *table_arg);
~ha_example()
{
}
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index 8a9aa91c680..5c3cbdcf2ca 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -54,6 +54,26 @@ pthread_mutex_t tina_mutex;
static HASH tina_open_tables;
static int tina_init= 0;
+static handlerton tina_hton= {
+ "CSV",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
/*****************************************************************************
** TINA tables
*****************************************************************************/
@@ -228,6 +248,20 @@ byte * find_eoln(byte *data, off_t begin, off_t end)
return 0;
}
+
+ha_tina::ha_tina(TABLE *table_arg)
+ :handler(&tina_hton, table_arg),
+ /*
+ These definitions are found in hanler.h
+ These are not probably completely right.
+ */
+ current_position(0), next_position(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH)
+{
+ /* Set our original buffers from pre-allocated memory */
+ buffer.set(byte_buffer, IO_SIZE, system_charset_info);
+ chain= chain_buffer;
+}
+
/*
Encode a buffer into the quoted format.
*/
@@ -374,7 +408,7 @@ int ha_tina::find_current_row(byte *buf)
}
next_position= (end_ptr - share->mapped_file)+1;
/* Maybe use \N for null? */
- memset(buf, 0, table->null_bytes); /* We do not implement nulls! */
+ memset(buf, 0, table->s->null_bytes); /* We do not implement nulls! */
DBUG_RETURN(0);
}
@@ -383,8 +417,15 @@ int ha_tina::find_current_row(byte *buf)
If frm_error() is called in table.cc this is called to find out what file
extensions exist for this handler.
*/
+static const char *ha_tina_exts[] = {
+ ".CSV",
+ NullS
+};
+
const char **ha_tina::bas_ext() const
-{ static const char *ext[]= { ".CSV", NullS }; return ext; }
+{
+ return ha_tina_exts;
+}
/*
@@ -425,7 +466,7 @@ int ha_tina::write_row(byte * buf)
int size;
DBUG_ENTER("ha_tina::write_row");
- statistic_increment(ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
@@ -461,7 +502,8 @@ int ha_tina::update_row(const byte * old_data, byte * new_data)
int size;
DBUG_ENTER("ha_tina::update_row");
- statistic_increment(ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
@@ -488,7 +530,7 @@ int ha_tina::update_row(const byte * old_data, byte * new_data)
int ha_tina::delete_row(const byte * buf)
{
DBUG_ENTER("ha_tina::delete_row");
- statistic_increment(ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
if (chain_append())
DBUG_RETURN(-1);
@@ -631,7 +673,8 @@ int ha_tina::rnd_next(byte *buf)
{
DBUG_ENTER("ha_tina::rnd_next");
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
current_position= next_position;
if (!share->mapped_file)
@@ -647,7 +690,7 @@ int ha_tina::rnd_next(byte *buf)
In the case of an order by rows will need to be sorted.
::position() is called after each call to ::rnd_next(),
the data it stores is to a byte array. You can store this
- data via ha_store_ptr(). ref_length is a variable defined to the
+ data via my_store_ptr(). ref_length is a variable defined to the
class that is the sizeof() of position being stored. In our case
its just a position. Look at the bdb code if you want to see a case
where something other then a number is stored.
@@ -655,21 +698,22 @@ int ha_tina::rnd_next(byte *buf)
void ha_tina::position(const byte *record)
{
DBUG_ENTER("ha_tina::position");
- ha_store_ptr(ref, ref_length, current_position);
+ my_store_ptr(ref, ref_length, current_position);
DBUG_VOID_RETURN;
}
/*
Used to fetch a row from a posiion stored with ::position().
- ha_get_ptr() retrieves the data for you.
+ my_get_ptr() retrieves the data for you.
*/
int ha_tina::rnd_pos(byte * buf, byte *pos)
{
DBUG_ENTER("ha_tina::rnd_pos");
- statistic_increment(ha_read_rnd_count,&LOCK_status);
- current_position= ha_get_ptr(pos,ref_length);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
+ current_position= my_get_ptr(pos,ref_length);
DBUG_RETURN(find_current_row(buf));
}
diff --git a/sql/examples/ha_tina.h b/sql/examples/ha_tina.h
index 22193c01013..5679d77a4dc 100644
--- a/sql/examples/ha_tina.h
+++ b/sql/examples/ha_tina.h
@@ -49,18 +49,8 @@ class ha_tina: public handler
byte chain_alloced;
uint32 chain_size;
- public:
- ha_tina(TABLE *table): handler(table),
- /*
- These definitions are found in hanler.h
- Theses are not probably completely right.
- */
- current_position(0), next_position(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH)
- {
- /* Set our original buffers from pre-allocated memory */
- buffer.set(byte_buffer, IO_SIZE, system_charset_info);
- chain = chain_buffer;
- }
+public:
+ ha_tina(TABLE *table_arg);
~ha_tina()
{
if (chain_alloced)
diff --git a/sql/field.cc b/sql/field.cc
index 6d2f92e27ea..e8731cb0ea5 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -38,7 +38,7 @@
Instansiate templates and static variables
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<create_field>;
template class List_iterator<create_field>;
#endif
@@ -57,9 +57,9 @@ const char field_separator=',';
following #defines describe that gap and how to canculate number of fields
and index of field in thia array.
*/
-#define FIELDTYPE_TEAR_FROM (MYSQL_TYPE_NEWDATE+1)
-#define FIELDTYPE_TEAR_TO (MYSQL_TYPE_ENUM-1)
-#define FIELDTYPE_NUM (FIELDTYPE_TEAR_FROM + (255-FIELDTYPE_TEAR_TO))
+#define FIELDTYPE_TEAR_FROM (MYSQL_TYPE_BIT + 1)
+#define FIELDTYPE_TEAR_TO (MYSQL_TYPE_NEWDECIMAL - 1)
+#define FIELDTYPE_NUM (FIELDTYPE_TEAR_FROM + (255 - FIELDTYPE_TEAR_TO))
inline int field_type2index (enum_field_types field_type)
{
return (field_type < FIELDTYPE_TEAR_FROM ?
@@ -72,118 +72,126 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
/* MYSQL_TYPE_DECIMAL -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_TINY -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_TINY,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_TINY, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_TINY, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_SHORT -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_SHORT,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_SHORT,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_SHORT, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_SHORT, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_SHORT,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_SHORT,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_LONG -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_LONG,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_LONG,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_LONG, MYSQL_TYPE_LONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_LONG, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_LONG, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONG,
+ MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_LONG,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_FLOAT -> */
{
@@ -194,25 +202,27 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_FLOAT, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_FLOAT,
+ MYSQL_TYPE_FLOAT, MYSQL_TYPE_INT24,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_FLOAT,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_FLOAT,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_DOUBLE, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_DOUBLE -> */
{
@@ -223,30 +233,32 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_DOUBLE, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
+ MYSQL_TYPE_DOUBLE, MYSQL_TYPE_INT24,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_DOUBLE,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_DOUBLE, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_NULL -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_TINY,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
@@ -259,192 +271,206 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_TIME,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_NEWDATE,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_ENUM,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_BIT,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_ENUM,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY
},
/* MYSQL_TYPE_TIMESTAMP -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_TIMESTAMP,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_DATETIME,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_LONGLONG -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_LONGLONG,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_LONGLONG,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONGLONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_LONGLONG, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONG,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_LONGLONG,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_LONGLONG,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_INT24 -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_INT24,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_INT24,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_INT24, MYSQL_TYPE_LONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_INT24, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_INT24, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_INT24,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INT24,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_DATE -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_NEWDATE,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_TIME -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIME,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_DATETIME,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_DATETIME -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_DATETIME,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_YEAR -> */
{
@@ -455,112 +481,213 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_YEAR, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_YEAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_YEAR,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_YEAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_NEWDATE -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_NEWDATE,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ },
+ /* MYSQL_TYPE_VARCHAR -> */
+ {
+ //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
+ //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
+ MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
+ //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR
+ },
+ /* MYSQL_TYPE_BIT -> */
+ {
+ //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
+ MYSQL_TYPE_BIT, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_BIT,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
+ //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
+ MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
+ //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ },
+ /* MYSQL_TYPE_NEWDECIMAL -> */
+ {
+ //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
+ //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
+ //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
+ MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
+ //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
+ //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_NEWDECIMAL,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
+ //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
+ MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
+ //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_ENUM -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_ENUM, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_ENUM, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_SET -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_SET, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_SET, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_TINY_BLOB -> */
{
@@ -578,10 +705,12 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_NEWDATE <14>
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
+ //MYSQL_TYPE_BIT <16>-<245>
MYSQL_TYPE_TINY_BLOB,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_TINY_BLOB,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
@@ -607,10 +736,12 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_NEWDATE <14>
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
+ //MYSQL_TYPE_BIT <16>-<245>
MYSQL_TYPE_MEDIUM_BLOB,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_MEDIUM_BLOB,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
@@ -636,10 +767,12 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_NEWDATE <14>
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
+ //MYSQL_TYPE_BIT <16>-<245>
MYSQL_TYPE_LONG_BLOB,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_LONG_BLOB,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
@@ -665,10 +798,12 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_NEWDATE <14>
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
+ //MYSQL_TYPE_BIT <16>-<245>
MYSQL_TYPE_BLOB,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_BLOB,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
@@ -681,31 +816,33 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
/* MYSQL_TYPE_VAR_STRING -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_STRING -> */
{
@@ -723,45 +860,49 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
- //MYSQL_TYPE_NEWDATE <14>
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
MYSQL_TYPE_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_STRING,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
MYSQL_TYPE_STRING, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
MYSQL_TYPE_STRING, MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_GEOMETRY -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_GEOMETRY, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_GEOMETRY, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_BIT <16>-<245>
+ MYSQL_TYPE_VARCHAR,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
+ MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
+ MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY
}
@@ -791,7 +932,7 @@ enum_field_types Field::field_type_merge(enum_field_types a,
static Item_result field_types_result_type [FIELDTYPE_NUM]=
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- REAL_RESULT, INT_RESULT,
+ DECIMAL_RESULT, INT_RESULT,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
INT_RESULT, INT_RESULT,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
@@ -804,10 +945,12 @@ static Item_result field_types_result_type [FIELDTYPE_NUM]=
STRING_RESULT, STRING_RESULT,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
STRING_RESULT, INT_RESULT,
- //MYSQL_TYPE_NEWDATE <14>
+ //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
+ STRING_RESULT, STRING_RESULT,
+ //MYSQL_TYPE_BIT <16>-<245>
STRING_RESULT,
- //<246> MYSQL_TYPE_ENUM
- STRING_RESULT,
+ //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
+ DECIMAL_RESULT, STRING_RESULT,
//MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
STRING_RESULT, STRING_RESULT,
//MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
@@ -841,6 +984,58 @@ Item_result Field::result_merge_type(enum_field_types field_type)
Static help functions
*****************************************************************************/
+
+/*
+ Check whether a field type can be partially indexed by a key
+
+ This is a static method, rather than a virtual function, because we need
+ to check the type of a non-Field in mysql_alter_table().
+
+ SYNOPSIS
+ type_can_have_key_part()
+ type field type
+
+ RETURN
+ TRUE Type can have a prefixed key
+ FALSE Type can not have a prefixed key
+*/
+
+bool Field::type_can_have_key_part(enum enum_field_types type)
+{
+ switch (type) {
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+
+/*
+ Numeric fields base class constructor
+*/
+Field_num::Field_num(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg,
+ uint8 dec_arg, bool zero_arg, bool unsigned_arg)
+ :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg),
+ dec(dec_arg),zerofill(zero_arg),unsigned_flag(unsigned_arg)
+{
+ if (zerofill)
+ flags|=ZEROFILL_FLAG;
+ if (unsigned_flag)
+ flags|=UNSIGNED_FLAG;
+}
+
+
void Field_num::prepend_zeros(String *value)
{
int diff;
@@ -871,33 +1066,78 @@ void Field_num::prepend_zeros(String *value)
Make this multi-byte-character safe
RETURN
- 0 ok
- 1 error
+ 0 OK
+ 1 error. A warning is pushed if field_name != 0
*/
-bool test_if_int(const char *str, int length, const char *int_end,
- CHARSET_INFO *cs)
+bool Field::check_int(const char *str, int length, const char *int_end,
+ CHARSET_INFO *cs)
{
+ const char *end;
if (str == int_end)
- return 0; // Empty string
- const char *end=str+length;
+ {
+ char buff[128];
+ String tmp(buff,(uint32) sizeof(buff), system_charset_info);
+ tmp.copy(str, length, system_charset_info);
+ push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+ ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
+ "integer", tmp.c_ptr(), field_name,
+ (ulong) table->in_use->row_count);
+ return 1; // Empty string
+ }
+ end= str+length;
if ((str= int_end) == end)
- return 1; // All digits was used
+ return 0; // OK; All digits was used
/* Allow end .0000 */
if (*str == '.')
{
- for (str++ ; str != end && *str == '0'; str++) ;
+ for (str++ ; str != end && *str == '0'; str++)
+ ;
}
/* Allow end space */
- for (str++ ; str != end ; str++)
+ for ( ; str != end ; str++)
{
if (!my_isspace(cs,*str))
- return 0;
+ {
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+ return 1;
+ }
}
- return 1;
+ return 0;
+}
+
+
+/*
+ Process decimal library return codes and issue warnings for overflow and
+ truncation.
+
+ SYNOPSIS
+ Field::warn_if_overflow()
+ op_result decimal library return code (E_DEC_* see include/decimal.h)
+
+ RETURN
+ 1 there was overflow
+ 0 no error or some other errors except overflow
+*/
+
+int Field::warn_if_overflow(int op_result)
+{
+ if (op_result == E_DEC_OVERFLOW)
+ {
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ return 1;
+ }
+ if (op_result == E_DEC_TRUNCATED)
+ {
+ set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
+ /* We return 0 here as this is not a critical issue */
+ }
+ return 0;
}
+
#ifdef NOT_USED
static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
{
@@ -953,10 +1193,30 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
#endif
-/****************************************************************************
-** Functions for the base classes
-** This is an unpacked number.
-****************************************************************************/
+/*
+ Interpret field value as an integer but return the result as a string.
+
+ This is used for printing bit_fields as numbers while debugging
+*/
+
+String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_val)
+{
+ CHARSET_INFO *cs= &my_charset_bin;
+ uint length= 21;
+ longlong value= val_int();
+ if (val_buffer->alloc(length))
+ return 0;
+ length= (uint) (*cs->cset->longlong10_to_str)(cs, (char*) val_buffer->ptr(),
+ length,
+ unsigned_val ? 10 : -10,
+ value);
+ val_buffer->length(length);
+ return val_buffer;
+}
+
+
+/* This is used as a table name when the table structure is not set up */
+const char *unknown_table_name= 0;
Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -964,7 +1224,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
struct st_table *table_arg)
:ptr(ptr_arg),null_ptr(null_ptr_arg),
table(table_arg),orig_table(table_arg),
- table_name(table_arg ? table_arg->table_name : 0),
+ table_name(table_arg ? &table_arg->alias : &unknown_table_name),
field_name(field_name_arg),
query_id(0), key_start(0), part_of_key(0), part_of_sortkey(0),
unireg_check(unireg_check_arg),
@@ -1001,6 +1261,14 @@ bool Field::send_binary(Protocol *protocol)
}
+my_decimal *Field::val_decimal(my_decimal *decimal)
+{
+ /* This never have to be called */
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
void Field_num::add_zerofill_and_unsigned(String &res) const
{
if (unsigned_flag)
@@ -1009,47 +1277,170 @@ void Field_num::add_zerofill_and_unsigned(String &res) const
res.append(" zerofill");
}
-void Field_num::make_field(Send_field *field)
+
+void Field::make_field(Send_field *field)
{
- /* table_cache_key is not set for temp tables */
- if (orig_table->table_cache_key)
+ if (orig_table->s->table_cache_key && *(orig_table->s->table_cache_key))
{
- field->db_name= orig_table->table_cache_key;
- field->org_table_name= orig_table->real_name;
+ field->org_table_name= orig_table->s->table_name;
+ field->db_name= orig_table->s->table_cache_key;
}
else
- {
- field->db_name= field->org_table_name= "";
- }
- field->table_name= orig_table->table_name;
- field->col_name=field->org_col_name=field_name;
+ field->org_table_name= field->db_name= "";
+ field->table_name= orig_table->alias;
+ field->col_name= field->org_col_name= field_name;
field->charsetnr= charset()->number;
field->length=field_length;
field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
- field->decimals=dec;
+ field->decimals= 0;
}
-void Field_str::make_field(Send_field *field)
+/*
+ Conversion from decimal to longlong with checking overflow and
+ setting correct value (min/max) in case of overflow
+
+ SYNOPSIS
+ Field::convert_decimal2longlong()
+ val value which have to be converted
+ unsigned_flag type of integer in which we convert val
+ err variable to pass error code
+
+ RETURN
+ value converted from val
+*/
+longlong Field::convert_decimal2longlong(const my_decimal *val,
+ bool unsigned_flag, int *err)
{
- /* table_cache_key is not set for temp tables */
- if (orig_table->table_cache_key)
+ longlong i;
+ if (unsigned_flag)
{
- field->db_name= orig_table->table_cache_key;
- field->org_table_name= orig_table->real_name;
+ if (val->sign())
+ {
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ i= 0;
+ *err= 1;
+ }
+ else if (warn_if_overflow(my_decimal2int(E_DEC_ERROR &
+ ~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED,
+ val, TRUE, &i)))
+ {
+ i= ~(longlong) 0;
+ *err= 1;
+ }
}
- else
+ else if (warn_if_overflow(my_decimal2int(E_DEC_ERROR &
+ ~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED,
+ val, FALSE, &i)))
{
- field->db_name= field->org_table_name= "";
+ i= (val->sign() ? LONGLONG_MIN : LONGLONG_MAX);
+ *err= 1;
}
- field->table_name= orig_table->table_name;
- field->col_name=field->org_col_name=field_name;
- field->charsetnr= charset()->number;
- field->length=field_length;
- field->type=type();
- field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
- field->decimals=0;
+ return i;
+}
+
+
+/*
+ Storing decimal in integer fields.
+
+ SYNOPSIS
+ Field_num::store_decimal()
+ val value for storing
+
+ NOTE
+ This method is used by all integer fields, real/decimal redefine it
+
+ RETURN
+ 0 OK
+ != 0 error
+*/
+
+int Field_num::store_decimal(const my_decimal *val)
+{
+ int err= 0;
+ longlong i= convert_decimal2longlong(val, unsigned_flag, &err);
+ return test(err | store(i, unsigned_flag));
+}
+
+
+/*
+ Return decimal value of integer field
+
+ SYNOPSIS
+ Field_num::val_decimal()
+ decimal_value buffer for storing decimal value
+
+ NOTE
+ This method is used by all integer fields, real/decimal redefine it
+ All longlong values fit in our decimal buffer which cal store 8*9=72
+ digits of integer number
+
+ RETURN
+ pointer to decimal buffer with value of field
+*/
+
+my_decimal* Field_num::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(result_type() == INT_RESULT);
+ longlong nr= val_int();
+ int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
+ return decimal_value;
+}
+
+
+Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg,CHARSET_INFO *charset)
+ :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg)
+{
+ field_charset=charset;
+ if (charset->state & MY_CS_BINSORT)
+ flags|=BINARY_FLAG;
+}
+
+
+void Field_num::make_field(Send_field *field)
+{
+ Field::make_field(field);
+ field->decimals= dec;
+}
+
+/*
+ Decimal representation of Field_str
+
+ SYNOPSIS
+ Field_str::store_decimal()
+ d value for storing
+
+ NOTE
+ Field_str is the base class for fields like Field_enum, Field_date and some
+ similar. Some dates use fraction and also string value should be
+ converted to floating point value according our rules, so we use double
+ to store value of decimal in string
+
+ RETURN
+ 0 OK
+ != 0 error
+*/
+
+int Field_str::store_decimal(const my_decimal *d)
+{
+ double val;
+ /* TODO: use decimal2string? */
+ int err= warn_if_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
+ ~E_DEC_OVERFLOW, d, &val));
+ return err | store(val);
+}
+
+
+my_decimal *Field_str::val_decimal(my_decimal *decimal_value)
+{
+ longlong nr= val_int();
+ int2my_decimal(E_DEC_FATAL_ERROR, nr, 0, decimal_value);
+ return decimal_value;
}
@@ -1063,11 +1454,12 @@ uint Field::fill_cache_field(CACHE_FIELD *copy)
{
copy->blob_field=(Field_blob*) this;
copy->strip=0;
- copy->length-=table->blob_ptr_size;
+ copy->length-= table->s->blob_ptr_size;
return copy->length;
}
- else if (!zero_pack() && (type() == FIELD_TYPE_STRING && copy->length > 4 ||
- type() == FIELD_TYPE_VAR_STRING))
+ else if (!zero_pack() &&
+ (type() == MYSQL_TYPE_STRING && copy->length >= 4 &&
+ copy->length < 256))
{
copy->strip=1; /* Remove end space */
store_length= 2;
@@ -1109,11 +1501,11 @@ bool Field::get_time(TIME *ltime)
Needs to be changed if/when we want to support different time formats
*/
-void Field::store_time(TIME *ltime,timestamp_type type)
+int Field::store_time(TIME *ltime, timestamp_type type)
{
char buff[MAX_DATE_STRING_REP_LENGTH];
uint length= (uint) my_TIME_to_str(ltime, buff);
- store(buff, length, &my_charset_bin);
+ return store(buff, length, &my_charset_bin);
}
@@ -1122,6 +1514,140 @@ bool Field::optimize_range(uint idx, uint part)
return test(table->file->index_flags(idx, part, 1) & HA_READ_RANGE);
}
+
+Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table)
+{
+ Field *tmp;
+ if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of())))
+ return 0;
+
+ if (tmp->table->maybe_null)
+ tmp->flags&= ~NOT_NULL_FLAG;
+ tmp->table= new_table;
+ tmp->key_start.init(0);
+ tmp->part_of_key.init(0);
+ tmp->part_of_sortkey.init(0);
+ tmp->unireg_check=Field::NONE;
+ tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
+ ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+ tmp->reset_fields();
+ return tmp;
+}
+
+
+Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ char *new_ptr, uchar *new_null_ptr,
+ uint new_null_bit)
+{
+ Field *tmp;
+ if ((tmp= new_field(root, new_table)))
+ {
+ tmp->ptr= new_ptr;
+ tmp->null_ptr= new_null_ptr;
+ tmp->null_bit= new_null_bit;
+ }
+ return tmp;
+}
+
+
+/*
+ SYNOPSIS
+ Field::quote_data()
+ unquoted_string Pointer pointing to the value of a field
+
+ DESCRIPTION
+ Simple method that passes the field type to the method "type_quote"
+ To get a true/false value as to whether the value in string1 needs
+ to be enclosed with quotes. This ensures that values in the final
+ sql statement to be passed to the remote server will be quoted properly
+
+ RETURN_VALUE
+ void Immediately - if string doesn't need quote
+ void Upon prepending/appending quotes on each side of variable
+
+*/
+
+bool Field::quote_data(String *unquoted_string)
+{
+ char escaped_string[IO_SIZE];
+ char *unquoted_string_buffer= (char *)(unquoted_string->ptr());
+ DBUG_ENTER("Field::quote_data");
+
+ if (!needs_quotes())
+ DBUG_RETURN(0);
+
+ // this is the same call that mysql_real_escape_string() calls
+ if (escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
+ sizeof(escaped_string), unquoted_string->ptr(),
+ unquoted_string->length()) == (ulong)~0)
+ DBUG_RETURN(1);
+
+ // reset string, then re-append with quotes and escaped values
+ unquoted_string->length(0);
+ if (unquoted_string->append('\'') ||
+ unquoted_string->append((char *)escaped_string) ||
+ unquoted_string->append('\''))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Quote a field type if needed
+
+ SYNOPSIS
+ Field::type_quote
+
+ DESCRIPTION
+ Simple method to give true/false whether a field should be quoted.
+ Used when constructing INSERT and UPDATE queries to the remote server
+ see write_row and update_row
+
+ RETURN VALUE
+ 0 if value is of type NOT needing quotes
+ 1 if value is of type needing quotes
+*/
+
+bool Field::needs_quotes(void)
+{
+ DBUG_ENTER("Field::type_quote");
+
+ switch (type()) {
+ //FIX this when kernel is fixed
+ case MYSQL_TYPE_VARCHAR :
+ case FIELD_TYPE_STRING :
+ case FIELD_TYPE_VAR_STRING :
+ case FIELD_TYPE_YEAR :
+ case FIELD_TYPE_NEWDATE :
+ case FIELD_TYPE_TIME :
+ case FIELD_TYPE_TIMESTAMP :
+ case FIELD_TYPE_DATE :
+ case FIELD_TYPE_DATETIME :
+ case FIELD_TYPE_TINY_BLOB :
+ case FIELD_TYPE_BLOB :
+ case FIELD_TYPE_MEDIUM_BLOB :
+ case FIELD_TYPE_LONG_BLOB :
+ case FIELD_TYPE_GEOMETRY :
+ DBUG_RETURN(1);
+
+ case FIELD_TYPE_DECIMAL :
+ case FIELD_TYPE_TINY :
+ case FIELD_TYPE_SHORT :
+ case FIELD_TYPE_INT24 :
+ case FIELD_TYPE_LONG :
+ case FIELD_TYPE_FLOAT :
+ case FIELD_TYPE_DOUBLE :
+ case FIELD_TYPE_LONGLONG :
+ case FIELD_TYPE_NULL :
+ case FIELD_TYPE_SET :
+ case FIELD_TYPE_ENUM :
+ DBUG_RETURN(0);
+ default:
+ DBUG_RETURN(0);
+ }
+}
+
+
/****************************************************************************
Field_null, a field that always return NULL
****************************************************************************/
@@ -1184,7 +1710,7 @@ void Field_decimal::overflow(bool negative)
int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmp(buff,sizeof(buff), &my_charset_bin);
/* Convert character set if the old one is multi byte */
@@ -1259,7 +1785,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, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
is_cuted_fields_incr=1;
}
else if (*from == '+' || *from == '-') // Found some sign ?
@@ -1325,7 +1851,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
/*
We only have to generate warnings if count_cuted_fields is set.
This is to avoid extra checks of the number when they are not needed.
- Even if this flag is not set, it's ok to increment warnings, if
+ Even if this flag is not set, it's OK to increment warnings, if
it makes the code easer to read.
*/
@@ -1335,7 +1861,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
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, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
is_cuted_fields_incr=1;
}
}
@@ -1403,7 +1929,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
int_digits_added_zeros=0;
}
}
- tmp_uint= (tmp_dec+(int_digits_end-int_digits_from)+
+ tmp_uint= (uint) (tmp_dec+(int_digits_end-int_digits_from)+
(uint)(frac_digits_from-int_digits_tail_from)+
int_digits_added_zeros);
}
@@ -1514,7 +2040,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
{
if (!is_cuted_fields_incr)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, 1);
+ WARN_DATA_TRUNCATED, 1);
return 0;
}
continue;
@@ -1531,7 +2057,13 @@ 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, 1);
+ {
+ /*
+ This is a note, not a warning, as we don't want to abort
+ when we cut decimals in strict mode
+ */
+ set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
+ }
return 0;
}
continue;
@@ -1590,36 +2122,37 @@ int Field_decimal::store(double nr)
}
-int Field_decimal::store(longlong nr)
+int Field_decimal::store(longlong nr, bool unsigned_val)
{
- if (unsigned_flag && nr < 0)
+ char buff[22];
+ uint length, int_part;
+ char fyllchar, *to;
+
+ if (nr < 0 && unsigned_flag && !unsigned_val)
{
overflow(1);
return 1;
}
- char buff[22];
- uint length=(uint) (longlong10_to_str(nr,buff,-10)-buff);
- uint int_part=field_length- (dec ? dec+1 : 0);
+ length= (uint) (longlong10_to_str(nr,buff,unsigned_val ? 10 : -10) - buff);
+ int_part= field_length- (dec ? dec+1 : 0);
if (length > int_part)
{
- overflow(test(nr < 0L)); /* purecov: inspected */
+ overflow(!unsigned_val && nr < 0L); /* purecov: inspected */
return 1;
}
- else
+
+ fyllchar = zerofill ? (char) '0' : (char) ' ';
+ to= ptr;
+ for (uint i=int_part-length ; i-- > 0 ;)
+ *to++ = fyllchar;
+ memcpy(to,buff,length);
+ if (dec)
{
- char fyllchar = zerofill ? (char) '0' : (char) ' ';
- char *to=ptr;
- for (uint i=int_part-length ; i-- > 0 ;)
- *to++ = fyllchar;
- memcpy(to,buff,length);
- if (dec)
- {
- to[length]='.';
- bfill(to+length+1,dec,'0');
- }
- return 0;
+ to[length]='.';
+ bfill(to+length+1,dec,'0');
}
+ return 0;
}
@@ -1736,6 +2269,311 @@ void Field_decimal::sql_type(String &res) const
/****************************************************************************
+** Field_new_decimal
+****************************************************************************/
+
+Field_new_decimal::Field_new_decimal(char *ptr_arg,
+ uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg,
+ enum utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg,
+ uint8 dec_arg,bool zero_arg,
+ bool unsigned_arg)
+ :Field_num(ptr_arg, len_arg,
+ null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg,
+ dec_arg, zero_arg, unsigned_arg)
+{
+ precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
+ DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
+ (dec <= DECIMAL_MAX_SCALE));
+ bin_size= my_decimal_get_binary_size(precision, dec);
+}
+
+
+Field_new_decimal::Field_new_decimal(uint32 len_arg,
+ bool maybe_null,
+ const char *name,
+ struct st_table *t_arg,
+ uint8 dec_arg,
+ bool unsigned_arg)
+ :Field_num((char*) 0, len_arg,
+ maybe_null ? (uchar*) "": 0, 0,
+ NONE, name, t_arg,
+ dec_arg,
+ 0, unsigned_arg)
+{
+ precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
+ DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
+ (dec <= DECIMAL_MAX_SCALE));
+ bin_size= my_decimal_get_binary_size(precision, dec);
+}
+
+
+void Field_new_decimal::reset(void)
+{
+ store_value(&decimal_zero);
+}
+
+
+/*
+ Generate max/min decimal value in case of overflow.
+
+ SYNOPSIS
+ Field_new_decimal::set_value_on_overflow();
+ decimal_value buffer for value
+ sign sign of value which caused overflow
+*/
+
+void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
+ bool sign)
+{
+ DBUG_ENTER("Field_new_decimal::set_value_on_overflow");
+ max_my_decimal(decimal_value, precision, decimals());
+ if (sign)
+ {
+ if (unsigned_flag)
+ my_decimal_set_zero(decimal_value);
+ else
+ decimal_value->sign(TRUE);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Store decimal value in the binary buffer
+
+ SYNOPSIS
+ store_value(const my_decimal *decimal_value)
+ decimal_value my_decimal
+
+ DESCRIPTION
+ checks if decimal_value fits into field size.
+ if it does, stores the decimal in the buffer using binary format.
+ Otherwise sets maximal number that can be stored in the field.
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool Field_new_decimal::store_value(const my_decimal *decimal_value)
+{
+ int error= 0;
+ DBUG_ENTER("Field_new_decimal::store_value");
+#ifndef DBUG_OFF
+ {
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, decimal_value)));
+ }
+#endif
+
+ /* check that we do not try to write negative value in unsigned field */
+ if (unsigned_flag && decimal_value->sign())
+ {
+ DBUG_PRINT("info", ("unsigned overflow"));
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ error= 1;
+ decimal_value= &decimal_zero;
+ }
+#ifndef DBUG_OFF
+ {
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ DBUG_PRINT("info", ("saving with precision %d, scale: %d, value %s",
+ (int)precision, (int)dec,
+ dbug_decimal_as_string(dbug_buff, decimal_value)));
+ }
+#endif
+
+ if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
+ decimal_value, ptr, precision, dec)))
+ {
+ my_decimal buff;
+ DBUG_PRINT("info", ("overflow"));
+ set_value_on_overflow(&buff, decimal_value->sign());
+ my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec);
+ error= 1;
+ }
+ DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr, bin_size););
+ DBUG_RETURN(error);
+}
+
+
+int Field_new_decimal::store(const char *from, uint length,
+ CHARSET_INFO *charset)
+{
+ int err;
+ my_decimal decimal_value;
+ DBUG_ENTER("Field_new_decimal::store(char*)");
+
+ if ((err= str2my_decimal(E_DEC_FATAL_ERROR &
+ ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
+ from, length, charset, &decimal_value)) &&
+ table->in_use->abort_on_warning)
+ {
+ push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+ ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
+ "decimal", from, field_name,
+ (ulong) table->in_use->row_count);
+ DBUG_RETURN(err);
+ }
+
+ switch (err) {
+ case E_DEC_TRUNCATED:
+ set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
+ break;
+ case E_DEC_OVERFLOW:
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ set_value_on_overflow(&decimal_value, decimal_value.sign());
+ break;
+ case E_DEC_BAD_NUM:
+ push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+ ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
+ "decimal", from, field_name,
+ (ulong) table->in_use->row_count);
+ my_decimal_set_zero(&decimal_value);
+ break;
+ }
+
+#ifndef DBUG_OFF
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ DBUG_PRINT("enter", ("value: %s",
+ dbug_decimal_as_string(dbug_buff, &decimal_value)));
+#endif
+ store_value(&decimal_value);
+ DBUG_RETURN(err);
+}
+
+
+int Field_new_decimal::store(double nr)
+{
+ my_decimal decimal_value;
+ int err;
+ DBUG_ENTER("Field_new_decimal::store(double)");
+
+ err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
+ &decimal_value);
+ /*
+ TODO: fix following when double2my_decimal when double2decimal
+ will return E_DEC_TRUNCATED always correctly
+ */
+ if (!err)
+ {
+ double nr2;
+ my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &nr2);
+ if (nr2 != nr)
+ err= E_DEC_TRUNCATED;
+ }
+ if (err)
+ {
+ if (check_overflow(err))
+ set_value_on_overflow(&decimal_value, decimal_value.sign());
+ /* Only issue a warning if store_value doesn't issue an warning */
+ table->in_use->got_warning= 0;
+ }
+ if (store_value(&decimal_value))
+ err= 1;
+ else if (err && !table->in_use->got_warning)
+ err= warn_if_overflow(err);
+ DBUG_RETURN(err);
+}
+
+
+int Field_new_decimal::store(longlong nr, bool unsigned_val)
+{
+ my_decimal decimal_value;
+ int err;
+
+ if ((err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
+ nr, unsigned_val, &decimal_value)))
+ {
+ if (check_overflow(err))
+ set_value_on_overflow(&decimal_value, decimal_value.sign());
+ /* Only issue a warning if store_value doesn't issue an warning */
+ table->in_use->got_warning= 0;
+ }
+ if (store_value(&decimal_value))
+ err= 1;
+ else if (err && !table->in_use->got_warning)
+ err= warn_if_overflow(err);
+ return err;
+}
+
+
+int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
+{
+ return store_value(decimal_value);
+}
+
+
+double Field_new_decimal::val_real(void)
+{
+ double dbl;
+ my_decimal decimal_value;
+ my_decimal2double(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), &dbl);
+ return dbl;
+}
+
+
+longlong Field_new_decimal::val_int(void)
+{
+ longlong i;
+ my_decimal decimal_value;
+ my_decimal2int(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
+ unsigned_flag, &i);
+ return i;
+}
+
+
+my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ENTER("Field_new_decimal::val_decimal");
+ binary2my_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value,
+ precision, dec);
+ DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr,
+ bin_size););
+ DBUG_RETURN(decimal_value);
+}
+
+
+String *Field_new_decimal::val_str(String *val_buffer,
+ String *val_ptr __attribute__((unused)))
+{
+ my_decimal decimal_value;
+ uint fixed_precision= zerofill ? precision : 0;
+ my_decimal2string(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
+ fixed_precision, dec, '0', val_buffer);
+ return val_buffer;
+}
+
+
+int Field_new_decimal::cmp(const char *a,const char*b)
+{
+ return memcmp(a, b, bin_size);
+}
+
+
+void Field_new_decimal::sort_string(char *buff,
+ uint length __attribute__((unused)))
+{
+ memcpy(buff, ptr, bin_size);
+}
+
+
+void Field_new_decimal::sql_type(String &str) const
+{
+ CHARSET_INFO *cs= str.charset();
+ str.length(cs->cset->snprintf(cs, (char*) str.ptr(), str.alloced_length(),
+ "decimal(%d,%d)", precision, (int)dec));
+ add_zerofill_and_unsigned(str);
+}
+
+
+/****************************************************************************
** tiny int
****************************************************************************/
@@ -1760,11 +2598,8 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- 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, 1);
+ else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs))
error= 1;
- }
}
else
{
@@ -1780,11 +2615,8 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- 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, 1);
+ else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs))
error= 1;
- }
}
ptr[0]= (char) tmp;
return error;
@@ -1827,23 +2659,25 @@ int Field_tiny::store(double nr)
error= 1;
}
else
- *ptr=(char) nr;
+ *ptr=(char) (int) nr;
}
return error;
}
-int Field_tiny::store(longlong nr)
+
+int Field_tiny::store(longlong nr, bool unsigned_val)
{
int error= 0;
+
if (unsigned_flag)
{
- if (nr < 0L)
+ if (nr < 0 && !unsigned_val)
{
- *ptr=0;
+ *ptr= 0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr > 255L)
+ else if ((ulonglong) nr > (ulonglong) 255)
{
*ptr= (char) 255;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
@@ -1854,13 +2688,15 @@ int Field_tiny::store(longlong nr)
}
else
{
- if (nr < -128L)
+ if (nr < 0 && unsigned_val)
+ nr= 256; // Generate overflow
+ if (nr < -128)
{
*ptr= (char) -128;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr > 127L)
+ else if (nr > 127)
{
*ptr=127;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
@@ -1880,6 +2716,7 @@ double Field_tiny::val_real(void)
return (double) tmp;
}
+
longlong Field_tiny::val_int(void)
{
int tmp= unsigned_flag ? (int) ((uchar*) ptr)[0] :
@@ -1887,6 +2724,7 @@ longlong Field_tiny::val_int(void)
return (longlong) tmp;
}
+
String *Field_tiny::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
@@ -1958,17 +2796,14 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (tmp > (uint16) ~0)
+ else if (tmp > UINT_MAX16)
{
- tmp=(uint16) ~0;
+ tmp=UINT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- 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, 1);
+ else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs))
error= 1;
- }
}
else
{
@@ -1984,14 +2819,11 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- 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, 1);
+ else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs))
error= 1;
- }
}
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int2store(ptr,tmp);
}
@@ -2015,9 +2847,9 @@ int Field_short::store(double nr)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr > (double) (uint16) ~0)
+ else if (nr > (double) UINT_MAX16)
{
- res=(int16) (uint16) ~0;
+ res=(int16) UINT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
@@ -2039,10 +2871,10 @@ int Field_short::store(double nr)
error= 1;
}
else
- res=(int16) nr;
+ res=(int16) (int) nr;
}
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int2store(ptr,res);
}
@@ -2052,21 +2884,23 @@ int Field_short::store(double nr)
return error;
}
-int Field_short::store(longlong nr)
+
+int Field_short::store(longlong nr, bool unsigned_val)
{
int error= 0;
int16 res;
+
if (unsigned_flag)
{
- if (nr < 0L)
+ if (nr < 0L && !unsigned_val)
{
res=0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr > (longlong) (uint16) ~0)
+ else if ((ulonglong) nr > (ulonglong) UINT_MAX16)
{
- res=(int16) (uint16) ~0;
+ res=(int16) UINT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
@@ -2075,13 +2909,16 @@ int Field_short::store(longlong nr)
}
else
{
+ if (nr < 0 && unsigned_val)
+ nr= UINT_MAX16+1; // Generate overflow
+
if (nr < INT_MIN16)
{
res=INT_MIN16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr > INT_MAX16)
+ else if (nr > (longlong) INT_MAX16)
{
res=INT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
@@ -2091,7 +2928,7 @@ int Field_short::store(longlong nr)
res=(int16) nr;
}
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int2store(ptr,res);
}
@@ -2106,7 +2943,7 @@ double Field_short::val_real(void)
{
short j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint2korr(ptr);
else
#endif
@@ -2118,7 +2955,7 @@ longlong Field_short::val_int(void)
{
short j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint2korr(ptr);
else
#endif
@@ -2137,7 +2974,7 @@ String *Field_short::val_str(String *val_buffer,
char *to=(char*) val_buffer->ptr();
short j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint2korr(ptr);
else
#endif
@@ -2165,7 +3002,7 @@ int Field_short::cmp(const char *a_ptr, const char *b_ptr)
{
short a,b;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
a=sint2korr(a_ptr);
b=sint2korr(b_ptr);
@@ -2186,7 +3023,7 @@ int Field_short::cmp(const char *a_ptr, const char *b_ptr)
void Field_short::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
+ if (!table->s->db_low_byte_first)
{
if (unsigned_flag)
to[0] = ptr[0];
@@ -2239,11 +3076,8 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- 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, 1);
+ else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs))
error= 1;
- }
}
else
{
@@ -2259,11 +3093,8 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- 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, 1);
+ else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs))
error= 1;
- }
}
int3store(ptr,tmp);
@@ -2315,20 +3146,22 @@ int Field_medium::store(double nr)
return error;
}
-int Field_medium::store(longlong nr)
+
+int Field_medium::store(longlong nr, bool unsigned_val)
{
int error= 0;
+
if (unsigned_flag)
{
- if (nr < 0L)
+ if (nr < 0 && !unsigned_val)
{
int3store(ptr,0);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr >= (longlong) (long) (1L << 24))
+ else if ((ulonglong) nr >= (ulonglong) (long) (1L << 24))
{
- long tmp=(long) (1L << 24)-1L;;
+ long tmp= (long) (1L << 24)-1L;
int3store(ptr,tmp);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
@@ -2338,9 +3171,12 @@ int Field_medium::store(longlong nr)
}
else
{
+ if (nr < 0 && unsigned_val)
+ nr= (ulonglong) (long) (1L << 24); // Generate overflow
+
if (nr < (longlong) INT_MIN24)
{
- long tmp=(long) INT_MIN24;
+ long tmp= (long) INT_MIN24;
int3store(ptr,tmp);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
@@ -2457,71 +3293,72 @@ static bool test_if_minus(CHARSET_INFO *cs,
int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
{
- long tmp;
- int error= 0;
+ ulong tmp_scan;
+ longlong tmp;
+ long store_tmp;
+ int error;
char *end;
-
- tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES);
- len-= tmp;
- from+= tmp;
- my_errno=0;
- if (unsigned_flag)
+ tmp_scan= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES);
+ len-= tmp_scan;
+ from+= tmp_scan;
+
+ end= (char*) from+len;
+ tmp= cs->cset->strtoll10(cs, from, &end, &error);
+
+ if (error != MY_ERRNO_EDOM)
{
- if (!len || test_if_minus(cs, from, from + len))
+ if (unsigned_flag)
{
- tmp=0; // Set negative to 0
- my_errno=ERANGE;
- error= 1;
+ if (error < 0)
+ {
+ error= 1;
+ tmp= 0;
+ }
+ else if ((ulonglong) tmp > (ulonglong) UINT_MAX32)
+ {
+ tmp= UINT_MAX32;
+ error= 1;
+ }
+ else
+ error= 0;
}
else
- tmp=(long) my_strntoul(cs,from,len,10,&end,&error);
- }
- else
- tmp=my_strntol(cs,from,len,10,&end,&error);
- if (error ||
- (from+len != end && table->in_use->count_cuted_fields &&
- !test_if_int(from,len,end,cs)))
- {
- if (error != 1)
- error= 2;
- }
-#if SIZEOF_LONG > 4
- if (unsigned_flag)
- {
- if ((ulong) tmp > UINT_MAX32)
{
- tmp= UINT_MAX32;
- error= 1;
- my_errno=ERANGE;
+ if (error < 0)
+ {
+ error= 0;
+ if (tmp < INT_MIN32)
+ {
+ tmp= INT_MIN32;
+ error= 1;
+ }
+ }
+ else if (tmp > INT_MAX32)
+ {
+ tmp= INT_MAX32;
+ error= 1;
+ }
}
}
- else
+ if (error)
{
- if (tmp > INT_MAX32)
- {
- tmp= INT_MAX32;
- error= 1;
- my_errno=ERANGE;
- }
- else if (tmp < INT_MIN32)
- {
- tmp= INT_MIN32;
- error= 1;
- my_errno=ERANGE;
- }
+ error= error != MY_ERRNO_EDOM ? 1 : 2;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
}
-#endif
- if (error)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ else if (from+len != end && table->in_use->count_cuted_fields &&
+ check_int(from,len,end,cs))
+ error= 2;
+
+ store_tmp= (long) tmp;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
- int4store(ptr,tmp);
+ int4store(ptr, store_tmp);
}
else
#endif
- longstore(ptr,tmp);
+ longstore(ptr, store_tmp);
return error;
}
@@ -2536,7 +3373,6 @@ int Field_long::store(double nr)
if (nr < 0)
{
res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) UINT_MAX32)
@@ -2553,20 +3389,21 @@ 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, 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, 1);
error= 1;
}
else
- res=(int32) nr;
+ res=(int32) (longlong) nr;
}
+ if (error)
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int4store(ptr,res);
}
@@ -2577,30 +3414,22 @@ int Field_long::store(double nr)
}
-int Field_long::store(longlong nr)
+int Field_long::store(longlong nr, bool unsigned_val)
{
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);
+ DBUG_ASSERT(table->in_use == current_thd); // General safety
if (unsigned_flag)
{
- if (nr < 0)
+ if (nr < 0 && !unsigned_val)
{
res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr >= (LL(1) << 32))
+ else if ((ulonglong) nr >= (LL(1) << 32))
{
res=(int32) (uint32) ~0L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -2608,23 +3437,26 @@ int Field_long::store(longlong nr)
}
else
{
- if (nr < (longlong) INT_MIN32)
+ if (nr < 0 && unsigned_val)
+ nr= INT_MAX32+1; // Generate overflow
+ if (nr < (longlong) INT_MIN32)
{
res=(int32) INT_MIN32;
- 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, 1);
error= 1;
}
else
res=(int32) nr;
}
+ if (error)
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int4store(ptr,res);
}
@@ -2639,7 +3471,7 @@ double Field_long::val_real(void)
{
int32 j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint4korr(ptr);
else
#endif
@@ -2653,7 +3485,7 @@ longlong Field_long::val_int(void)
/* 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)
+ if (table->s->db_low_byte_first)
j=sint4korr(ptr);
else
#endif
@@ -2671,7 +3503,7 @@ String *Field_long::val_str(String *val_buffer,
char *to=(char*) val_buffer->ptr();
int32 j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint4korr(ptr);
else
#endif
@@ -2697,7 +3529,7 @@ int Field_long::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
a=sint4korr(a_ptr);
b=sint4korr(b_ptr);
@@ -2716,7 +3548,7 @@ int Field_long::cmp(const char *a_ptr, const char *b_ptr)
void Field_long::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
+ if (!table->s->db_low_byte_first)
{
if (unsigned_flag)
to[0] = ptr[0];
@@ -2757,17 +3589,15 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
longlong tmp;
int error= 0;
char *end;
-
+
tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES);
len-= (uint)tmp;
from+= tmp;
- my_errno=0;
if (unsigned_flag)
{
if (!len || test_if_minus(cs, from, from + len))
{
tmp=0; // Set negative to 0
- my_errno= ERANGE;
error= 1;
}
else
@@ -2775,18 +3605,16 @@ 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 && table->in_use->count_cuted_fields &&
- !test_if_int(from,len,end,cs)))
+ if (error)
{
- if (error != 1)
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- error= 2;
- }
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ error= 1;
}
+ else if (from+len != end && table->in_use->count_cuted_fields &&
+ check_int(from,len,end,cs))
+ error= 2;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int8store(ptr,tmp);
}
@@ -2801,19 +3629,18 @@ int Field_longlong::store(double nr)
{
int error= 0;
longlong res;
- nr=rint(nr);
+
+ nr= rint(nr);
if (unsigned_flag)
{
if (nr < 0)
{
res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr >= (double) ~ (ulonglong) 0)
+ else if (nr >= (double) ULONGLONG_MAX)
{
res= ~(longlong) 0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -2823,21 +3650,22 @@ 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, 1);
- error= 1;
+ res= LONGLONG_MIN;
+ error= (nr < (double) LONGLONG_MIN);
}
else if (nr >= (double) (ulonglong) LONGLONG_MAX)
{
- res=(longlong) LONGLONG_MAX;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
+ res= LONGLONG_MAX;
+ error= (nr > (double) LONGLONG_MAX);
}
else
res=(longlong) nr;
}
+ if (error)
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int8store(ptr,res);
}
@@ -2848,17 +3676,33 @@ int Field_longlong::store(double nr)
}
-int Field_longlong::store(longlong nr)
+int Field_longlong::store(longlong nr, bool unsigned_val)
{
+ int error= 0;
+
+ if (nr < 0) // Only possible error
+ {
+ /*
+ if field is unsigned and value is signed (< 0) or
+ if field is signed and value is unsigned we have an overflow
+ */
+ if (unsigned_flag != unsigned_val)
+ {
+ nr= unsigned_flag ? (ulonglong) 0 : (ulonglong) LONGLONG_MAX;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ error= 1;
+ }
+ }
+
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int8store(ptr,nr);
}
else
#endif
longlongstore(ptr,nr);
- return 0;
+ return error;
}
@@ -2866,7 +3710,7 @@ double Field_longlong::val_real(void)
{
longlong j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
j=sint8korr(ptr);
}
@@ -2887,7 +3731,7 @@ longlong Field_longlong::val_int(void)
{
longlong j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint8korr(ptr);
else
#endif
@@ -2906,7 +3750,7 @@ String *Field_longlong::val_str(String *val_buffer,
char *to=(char*) val_buffer->ptr();
longlong j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint8korr(ptr);
else
#endif
@@ -2931,7 +3775,7 @@ int Field_longlong::cmp(const char *a_ptr, const char *b_ptr)
{
longlong a,b;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
a=sint8korr(a_ptr);
b=sint8korr(b_ptr);
@@ -2951,7 +3795,7 @@ int Field_longlong::cmp(const char *a_ptr, const char *b_ptr)
void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
+ if (!table->s->db_low_byte_first)
{
if (unsigned_flag)
to[0] = ptr[0];
@@ -3001,10 +3845,12 @@ 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 && table->in_use->count_cuted_fields))
+ if (error || (!len || (uint) (end-from) != len &&
+ table->in_use->count_cuted_fields))
{
- error= 2;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ (error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
+ error= error ? 1 : 2;
}
Field_float::store(nr);
return error;
@@ -3064,7 +3910,7 @@ int Field_float::store(double nr)
}
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float4store(ptr,j);
}
@@ -3075,9 +3921,9 @@ int Field_float::store(double nr)
}
-int Field_float::store(longlong nr)
+int Field_float::store(longlong nr, bool unsigned_val)
{
- return store((double)nr);
+ return store(unsigned_val ? ulonglong2double((ulonglong) nr) : (double) nr);
}
@@ -3085,7 +3931,7 @@ double Field_float::val_real(void)
{
float j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float4get(j,ptr);
}
@@ -3099,7 +3945,7 @@ longlong Field_float::val_int(void)
{
float j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float4get(j,ptr);
}
@@ -3115,7 +3961,7 @@ String *Field_float::val_str(String *val_buffer,
{
float nr;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float4get(nr,ptr);
}
@@ -3197,7 +4043,7 @@ int Field_float::cmp(const char *a_ptr, const char *b_ptr)
{
float a,b;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float4get(a,a_ptr);
float4get(b,b_ptr);
@@ -3217,7 +4063,7 @@ void Field_float::sort_string(char *to,uint length __attribute__((unused)))
{
float nr;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float4get(nr,ptr);
}
@@ -3287,10 +4133,12 @@ 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 && table->in_use->count_cuted_fields))
+ if (error || (!len || (uint) (end-from) != len &&
+ table->in_use->count_cuted_fields))
{
- error= 2;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ (error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
+ error= error ? 1 : 2;
}
Field_double::store(nr);
return error;
@@ -3343,7 +4191,7 @@ int Field_double::store(double nr)
}
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float8store(ptr,nr);
}
@@ -3354,17 +4202,24 @@ int Field_double::store(double nr)
}
-int Field_double::store(longlong nr)
+int Field_double::store(longlong nr, bool unsigned_val)
{
- return store((double)nr);
+ return store(unsigned_val ? ulonglong2double((ulonglong) nr) : (double) nr);
}
+int Field_real::store_decimal(const my_decimal *dm)
+{
+ double dbl;
+ my_decimal2double(E_DEC_FATAL_ERROR, dm, &dbl);
+ return store(dbl);
+}
+
double Field_double::val_real(void)
{
double j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float8get(j,ptr);
}
@@ -3378,7 +4233,7 @@ longlong Field_double::val_int(void)
{
double j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float8get(j,ptr);
}
@@ -3389,12 +4244,19 @@ longlong Field_double::val_int(void)
}
+my_decimal *Field_real::val_decimal(my_decimal *decimal_value)
+{
+ double2my_decimal(E_DEC_FATAL_ERROR, val_real(), decimal_value);
+ return decimal_value;
+}
+
+
String *Field_double::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
double nr;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float8get(nr,ptr);
}
@@ -3482,7 +4344,7 @@ int Field_double::cmp(const char *a_ptr, const char *b_ptr)
{
double a,b;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float8get(a,a_ptr);
float8get(b,b_ptr);
@@ -3505,7 +4367,7 @@ void Field_double::sort_string(char *to,uint length __attribute__((unused)))
{
double nr;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
float8get(nr,ptr);
}
@@ -3556,7 +4418,7 @@ void Field_double::sql_type(String &res) const
TIMESTAMP_OLD_FIELD - old timestamp, if there was not any fields with
auto-set-on-update (or now() as default) in this table before, then this
field has NOW() as default and is updated when row changes, else it is
- field which has 0 as default value and is not automaitcally updated.
+ field which has 0 as default value and is not automatically updated.
TIMESTAMP_DN_FIELD - field with NOW() as default but not set on update
automatically (TIMESTAMP DEFAULT NOW())
TIMESTAMP_UN_FIELD - field which is set on update automatically but has not
@@ -3618,7 +4480,7 @@ timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
return TIMESTAMP_AUTO_SET_ON_UPDATE;
case TIMESTAMP_OLD_FIELD:
/*
- Altough we can have several such columns in legacy tables this
+ Although we can have several such columns in legacy tables this
function should be called only for first of them (i.e. the one
having auto-set property).
*/
@@ -3643,30 +4505,37 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
my_time_t tmp= 0;
int error;
bool have_smth_to_conv;
- bool in_dst_time_gap;
+ my_bool in_dst_time_gap;
THD *thd= table->in_use;
- have_smth_to_conv= (str_to_datetime(from, len, &l_time, 0, &error) >
+ /* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
+ have_smth_to_conv= (str_to_datetime(from, len, &l_time,
+ (table->in_use->variables.sql_mode &
+ MODE_NO_ZERO_DATE) |
+ MODE_NO_ZERO_IN_DATE, &error) >
MYSQL_TIMESTAMP_ERROR);
-
- if (error)
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
+
+ if (error || !have_smth_to_conv)
+ {
+ error= 1;
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_DATETIME, 1);
+ }
- if (have_smth_to_conv)
+ /* Only convert a correct date (not a zero date) */
+ if (have_smth_to_conv && l_time.month)
{
if (!(tmp= TIME_to_timestamp(thd, &l_time, &in_dst_time_gap)))
{
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ 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,
+ ER_WARN_INVALID_TIMESTAMP,
from, len, MYSQL_TIMESTAMP_DATETIME, !error);
error= 1;
}
@@ -3675,7 +4544,7 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
error= 2;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int4store(ptr,tmp);
}
@@ -3685,62 +4554,70 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
return error;
}
+
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,
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
nr, MYSQL_TIMESTAMP_DATETIME);
nr= 0; // Avoid overflow on buff
error= 1;
}
- error|= Field_timestamp::store((longlong) rint(nr));
+ error|= Field_timestamp::store((longlong) rint(nr), FALSE);
return error;
}
-int Field_timestamp::store(longlong nr)
+int Field_timestamp::store(longlong nr, bool unsigned_val)
{
TIME l_time;
my_time_t timestamp= 0;
int error;
- bool in_dst_time_gap;
+ my_bool in_dst_time_gap;
THD *thd= table->in_use;
- if (number_to_TIME(nr, &l_time, 0, &error))
+ /* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
+ longlong tmp= number_to_datetime(nr, &l_time, (thd->variables.sql_mode &
+ MODE_NO_ZERO_DATE) |
+ MODE_NO_ZERO_IN_DATE, &error);
+ if (tmp == LL(-1))
+ {
+ error= 2;
+ }
+
+ if (!error && tmp)
{
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);
+ 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);
+ ER_WARN_INVALID_TIMESTAMP,
+ nr, MYSQL_TIMESTAMP_DATETIME, 1);
error= 1;
}
- }
- else if (error)
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED,
+ } else if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_DATA_TRUNCATED,
nr, MYSQL_TIMESTAMP_DATETIME, 1);
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int4store(ptr,timestamp);
}
else
#endif
longstore(ptr,(uint32) timestamp);
-
+
return error;
}
@@ -3757,7 +4634,7 @@ longlong Field_timestamp::val_int(void)
THD *thd= table->in_use;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
temp=uint4korr(ptr);
else
#endif
@@ -3787,7 +4664,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
val_buffer->length(field_length);
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
temp=uint4korr(ptr);
else
#endif
@@ -3852,14 +4729,14 @@ 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)
+ if (table->s->db_low_byte_first)
temp=uint4korr(ptr);
else
#endif
longget(temp,ptr);
if (temp == 0L)
{ /* Zero time is "000000" */
- if (!fuzzydate)
+ if (fuzzydate & TIME_NO_ZERO_DATE)
return 1;
bzero((char*) ltime,sizeof(*ltime));
}
@@ -3880,7 +4757,7 @@ bool Field_timestamp::get_time(TIME *ltime)
bool Field_timestamp::send_binary(Protocol *protocol)
{
TIME tm;
- Field_timestamp::get_date(&tm, TIME_FUZZY_DATE);
+ Field_timestamp::get_date(&tm, 0);
return protocol->store(&tm);
}
@@ -3889,7 +4766,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
a=sint4korr(a_ptr);
b=sint4korr(b_ptr);
@@ -3907,7 +4784,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
+ if (!table->s->db_low_byte_first)
{
to[0] = ptr[0];
to[1] = ptr[1];
@@ -3936,7 +4813,7 @@ void Field_timestamp::set_time()
long tmp= (long) table->in_use->query_start();
set_notnull();
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int4store(ptr,tmp);
}
@@ -3962,14 +4839,14 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp=0L;
error= 2;
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_TIME, 1);
}
else
{
if (error)
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED,
+ WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_TIME, 1);
if (ltime.month)
@@ -3989,11 +4866,21 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
if (ltime.neg)
tmp= -tmp;
- error |= Field_time::store((longlong) tmp);
+ error |= Field_time::store((longlong) tmp, FALSE);
return error;
}
+int Field_time::store_time(TIME *ltime, timestamp_type type)
+{
+ long tmp= ((ltime->month ? 0 : ltime->day * 24L) + ltime->hour) * 10000L +
+ (ltime->minute * 100 + ltime->second);
+ if (ltime->neg)
+ tmp= -tmp;
+ return Field_time::store((longlong) tmp);
+}
+
+
int Field_time::store(double nr)
{
long tmp;
@@ -4031,21 +4918,21 @@ int Field_time::store(double nr)
}
-int Field_time::store(longlong nr)
+int Field_time::store(longlong nr, bool unsigned_val)
{
long tmp;
int error= 0;
- if (nr > (longlong) 8385959L)
+ if (nr < (longlong) -8385959L && !unsigned_val)
{
- tmp=8385959L;
+ tmp= -8385959L;
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)
+ else if (nr > (longlong) 8385959 || nr < 0 && unsigned_val)
{
- tmp= -8385959L;
+ tmp=8385959L;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr,
MYSQL_TIMESTAMP_TIME, 1);
@@ -4107,7 +4994,7 @@ String *Field_time::val_str(String *val_buffer,
/*
- Normally we would not consider 'time' as a vaild date, but we allow
+ Normally we would not consider 'time' as a valid date, but we allow
get_date() here to be able to do things like
DATE_FORMAT(time, "%l.%i %p")
*/
@@ -4115,7 +5002,7 @@ String *Field_time::val_str(String *val_buffer,
bool Field_time::get_date(TIME *ltime, uint fuzzydate)
{
long tmp;
- if (!fuzzydate)
+ if (!(fuzzydate & TIME_FUZZY_DATE))
{
push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
@@ -4197,26 +5084,19 @@ void Field_time::sql_type(String &res) const
int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
{
- int err;
char *end;
- long nr= my_strntol(cs, from, len, 10, &end, &err);
-
- if (err)
- {
- if (table->in_use->count_cuted_fields)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- *ptr= 0;
- return 0;
- }
+ int error;
+ long nr= my_strntol(cs, from, len, 10, &end, &error);
- if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155)
+ if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155 || error)
{
*ptr=0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
- 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 (table->in_use->count_cuted_fields && check_int(from,len,end,cs))
+ error= 1;
+
if (nr != 0 || len != 4)
{
if (nr < YY_PART_YEAR)
@@ -4225,7 +5105,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
nr-= 1900;
}
*ptr= (char) (unsigned char) nr;
- return 0;
+ return error;
}
@@ -4233,18 +5113,18 @@ int Field_year::store(double nr)
{
if (nr < 0.0 || nr >= 2155.0)
{
- (void) Field_year::store((longlong) -1);
+ (void) Field_year::store((longlong) -1, FALSE);
return 1;
}
- else
- return Field_year::store((longlong) nr);
+ return Field_year::store((longlong) nr, FALSE);
}
-int Field_year::store(longlong nr)
+
+int Field_year::store(longlong nr, bool unsigned_val)
{
if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155)
{
- *ptr=0;
+ *ptr= 0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
@@ -4259,17 +5139,20 @@ int Field_year::store(longlong nr)
return 0;
}
+
bool Field_year::send_binary(Protocol *protocol)
{
ulonglong tmp= Field_year::val_int();
return protocol->store_short(tmp);
}
+
double Field_year::val_real(void)
{
return (double) Field_year::val_int();
}
+
longlong Field_year::val_int(void)
{
int tmp= (int) ((uchar*) ptr)[0];
@@ -4280,6 +5163,7 @@ longlong Field_year::val_int(void)
return (longlong) tmp;
}
+
String *Field_year::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
@@ -4290,6 +5174,7 @@ String *Field_year::val_str(String *val_buffer,
return val_buffer;
}
+
void Field_year::sql_type(String &res) const
{
CHARSET_INFO *cs=res.charset();
@@ -4310,21 +5195,25 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
TIME l_time;
uint32 tmp;
int error;
-
- if (str_to_datetime(from, len, &l_time, 1, &error) <= MYSQL_TIMESTAMP_ERROR)
+
+ if (str_to_datetime(from, len, &l_time, TIME_FUZZY_DATE |
+ (table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES)),
+ &error) <= MYSQL_TIMESTAMP_ERROR)
{
- tmp=0;
+ tmp= 0;
error= 2;
}
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,
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_DATE, 1);
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int4store(ptr,tmp);
}
@@ -4337,56 +5226,57 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
int Field_date::store(double nr)
{
- long tmp;
+ longlong tmp;
int error= 0;
if (nr >= 19000000000000.0 && nr <= 99991231235959.0)
nr=floor(nr/1000000.0); // Timestamp to date
if (nr < 0.0 || nr > 99991231.0)
{
- tmp=0L;
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_OUT_OF_RANGE,
+ tmp= LL(0);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
nr, MYSQL_TIMESTAMP_DATE);
error= 1;
}
else
- tmp=(long) rint(nr);
-#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int4store(ptr,tmp);
- }
- else
-#endif
- longstore(ptr,tmp);
- return error;
+ tmp= (longlong) rint(nr);
+
+ return Field_date::store(tmp);
}
-int Field_date::store(longlong nr)
+int Field_date::store(longlong nr, bool unsigned_val)
{
- long tmp;
- int error= 0;
- if (nr >= LL(19000000000000) && nr < LL(99991231235959))
- nr=nr/LL(1000000); // Timestamp to date
- if (nr < 0 || nr > LL(99991231))
+ TIME not_used;
+ int error;
+ longlong initial_nr= nr;
+
+ nr= number_to_datetime(nr, &not_used, (TIME_FUZZY_DATE |
+ (table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE |
+ MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES))), &error);
+
+ if (nr == LL(-1))
{
- tmp=0L;
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_OUT_OF_RANGE,
- nr, MYSQL_TIMESTAMP_DATE, 0);
- error= 1;
+ nr= 0;
+ error= 2;
}
- else
- tmp=(long) nr;
+
+ if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ error == 2 ? ER_WARN_DATA_OUT_OF_RANGE :
+ WARN_DATA_TRUNCATED, initial_nr,
+ MYSQL_TIMESTAMP_DATETIME, 1);
+
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
- int4store(ptr,tmp);
+ int4store(ptr, nr);
}
else
#endif
- longstore(ptr,tmp);
+ longstore(ptr, nr);
return error;
}
@@ -4406,7 +5296,7 @@ double Field_date::val_real(void)
{
int32 j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint4korr(ptr);
else
#endif
@@ -4414,11 +5304,12 @@ double Field_date::val_real(void)
return (double) (uint32) j;
}
+
longlong Field_date::val_int(void)
{
int32 j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint4korr(ptr);
else
#endif
@@ -4426,6 +5317,7 @@ longlong Field_date::val_int(void)
return (longlong) (uint32) j;
}
+
String *Field_date::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
@@ -4433,7 +5325,7 @@ String *Field_date::val_str(String *val_buffer,
val_buffer->alloc(field_length);
int32 tmp;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
tmp=sint4korr(ptr);
else
#endif
@@ -4451,7 +5343,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr)
{
int32 a,b;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
a=sint4korr(a_ptr);
b=sint4korr(b_ptr);
@@ -4469,7 +5361,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr)
void Field_date::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
+ if (!table->s->db_low_byte_first)
{
to[0] = ptr[0];
to[1] = ptr[1];
@@ -4491,6 +5383,7 @@ void Field_date::sql_type(String &res) const
res.set_ascii("date", 4);
}
+
/****************************************************************************
** The new date type
** This is identical to the old date type, but stored on 3 bytes instead of 4
@@ -4502,90 +5395,86 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
TIME l_time;
long tmp;
int error;
- if (str_to_datetime(from, len, &l_time, 1, &error) <= MYSQL_TIMESTAMP_ERROR)
- {
- tmp=0L;
+ if (str_to_datetime(from, len, &l_time,
+ (TIME_FUZZY_DATE |
+ (table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES))),
+ &error) <= MYSQL_TIMESTAMP_ERROR)
+ {
+ tmp= 0L;
error= 2;
}
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,
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_DATE, 1);
-
+
int3store(ptr,tmp);
return error;
}
+
int Field_newdate::store(double nr)
{
if (nr < 0.0 || nr > 99991231235959.0)
{
- (void) Field_newdate::store((longlong) -1);
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, nr, MYSQL_TIMESTAMP_DATE);
+ int3store(ptr,(int32) 0);
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_DATA_TRUNCATED, nr, MYSQL_TIMESTAMP_DATE);
return 1;
}
- else
- return Field_newdate::store((longlong) rint(nr));
+ return Field_newdate::store((longlong) rint(nr), FALSE);
}
-int Field_newdate::store(longlong nr)
+int Field_newdate::store(longlong nr, bool unsigned_val)
{
- int32 tmp;
- int error= 0;
- if (nr >= LL(100000000) && nr <= LL(99991231235959))
- nr=nr/LL(1000000); // Timestamp to date
- if (nr < 0L || nr > 99991231L)
- {
- tmp=0;
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_OUT_OF_RANGE, nr,
- MYSQL_TIMESTAMP_DATE, 1);
- error= 1;
+ TIME l_time;
+ longlong tmp;
+ int error;
+ if (number_to_datetime(nr, &l_time,
+ (TIME_FUZZY_DATE |
+ (table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES))),
+ &error) == LL(-1))
+ {
+ tmp= 0L;
+ error= 2;
}
else
- {
- tmp=(int32) nr;
- if (tmp)
- {
- if (tmp < YY_PART_YEAR*10000L) // Fix short dates
- tmp+= (uint32) 20000000L;
- else if (tmp < 999999L)
- tmp+= (uint32) 19000000L;
- }
- uint month= (uint) ((tmp/100) % 100);
- uint day= (uint) (tmp%100);
- if (month > 12 || day > 31)
- {
- tmp=0L; // Don't allow date to change
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_OUT_OF_RANGE, nr,
- MYSQL_TIMESTAMP_DATE, 1);
- error= 1;
- }
- else
- tmp= day + month*32 + (tmp/10000)*16*32;
- }
- int3store(ptr,(int32) tmp);
+ tmp= l_time.day + l_time.month*32 + l_time.year*16*32;
+
+ if (error)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ error == 2 ? ER_WARN_DATA_OUT_OF_RANGE :
+ WARN_DATA_TRUNCATED,nr,MYSQL_TIMESTAMP_DATE, 1);
+
+ int3store(ptr,tmp);
return error;
}
-void Field_newdate::store_time(TIME *ltime,timestamp_type type)
+
+int Field_newdate::store_time(TIME *ltime,timestamp_type type)
{
long tmp;
+ int error= 0;
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, 1);
+ error= 1;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
int3store(ptr,tmp);
+ return error;
}
+
bool Field_newdate::send_binary(Protocol *protocol)
{
TIME tm;
@@ -4593,11 +5482,13 @@ bool Field_newdate::send_binary(Protocol *protocol)
return protocol->store_date(&tm);
}
+
double Field_newdate::val_real(void)
{
return (double) Field_newdate::val_int();
}
+
longlong Field_newdate::val_int(void)
{
ulong j= uint3korr(ptr);
@@ -4605,6 +5496,7 @@ longlong Field_newdate::val_int(void)
return (longlong) j;
}
+
String *Field_newdate::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
@@ -4632,24 +5524,26 @@ String *Field_newdate::val_str(String *val_buffer,
return val_buffer;
}
+
bool Field_newdate::get_date(TIME *ltime,uint fuzzydate)
{
- if (is_null())
- return 1;
uint32 tmp=(uint32) uint3korr(ptr);
ltime->day= tmp & 31;
ltime->month= (tmp >> 5) & 15;
ltime->year= (tmp >> 9);
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;
+ return ((!(fuzzydate & TIME_FUZZY_DATE) && (!ltime->month || !ltime->day)) ?
+ 1 : 0);
}
+
bool Field_newdate::get_time(TIME *ltime)
{
return Field_newdate::get_date(ltime,0);
}
+
int Field_newdate::cmp(const char *a_ptr, const char *b_ptr)
{
uint32 a,b;
@@ -4658,6 +5552,7 @@ int Field_newdate::cmp(const char *a_ptr, const char *b_ptr)
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
+
void Field_newdate::sort_string(char *to,uint length __attribute__((unused)))
{
to[0] = ptr[2];
@@ -4665,6 +5560,7 @@ void Field_newdate::sort_string(char *to,uint length __attribute__((unused)))
to[2] = ptr[0];
}
+
void Field_newdate::sql_type(String &res) const
{
res.set_ascii("date", 4);
@@ -4683,17 +5579,26 @@ int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
TIME time_tmp;
int error;
ulonglong tmp= 0;
-
- if (str_to_datetime(from, len, &time_tmp, 1, &error) > MYSQL_TIMESTAMP_ERROR)
+ enum enum_mysql_timestamp_type func_res;
+
+ func_res= str_to_datetime(from, len, &time_tmp,
+ (TIME_FUZZY_DATE |
+ (table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES))),
+ &error);
+ if ((int) func_res > (int) MYSQL_TIMESTAMP_ERROR)
tmp= TIME_to_ulonglong_datetime(&time_tmp);
-
+ else
+ error= 1; // Fix if invalid zero date
+
if (error)
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ 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)
+ if (table->s->db_low_byte_first)
{
int8store(ptr,tmp);
}
@@ -4712,29 +5617,40 @@ int Field_datetime::store(double nr)
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
nr, MYSQL_TIMESTAMP_DATETIME);
- nr=0.0;
+ nr= 0.0;
error= 1;
}
- error |= Field_datetime::store((longlong) rint(nr));
+ error|= Field_datetime::store((longlong) rint(nr), FALSE);
return error;
}
-int Field_datetime::store(longlong nr)
+int Field_datetime::store(longlong nr, bool unsigned_val)
{
TIME not_used;
int error;
longlong initial_nr= nr;
-
- nr= number_to_TIME(nr, &not_used, 1, &error);
+
+ nr= number_to_datetime(nr, &not_used, (TIME_FUZZY_DATE |
+ (table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE |
+ MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES))), &error);
+
+ if (nr == LL(-1))
+ {
+ nr= 0;
+ error= 2;
+ }
if (error)
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, initial_nr,
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ error == 2 ? ER_WARN_DATA_OUT_OF_RANGE :
+ WARN_DATA_TRUNCATED, initial_nr,
MYSQL_TIMESTAMP_DATETIME, 1);
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int8store(ptr,nr);
}
@@ -4745,9 +5661,10 @@ int Field_datetime::store(longlong nr)
}
-void Field_datetime::store_time(TIME *ltime,timestamp_type type)
+int Field_datetime::store_time(TIME *ltime,timestamp_type type)
{
longlong tmp;
+ int error= 0;
/*
We don't perform range checking here since values stored in TIME
structure always fit into DATETIME range.
@@ -4758,16 +5675,18 @@ void Field_datetime::store_time(TIME *ltime,timestamp_type type)
else
{
tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ error= 1;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int8store(ptr,tmp);
}
else
#endif
longlongstore(ptr,tmp);
+ return error;
}
bool Field_datetime::send_binary(Protocol *protocol)
@@ -4787,7 +5706,7 @@ longlong Field_datetime::val_int(void)
{
longlong j;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
j=sint8korr(ptr);
else
#endif
@@ -4807,14 +5726,14 @@ String *Field_datetime::val_str(String *val_buffer,
int part3;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
tmp=sint8korr(ptr);
else
#endif
longlongget(tmp,ptr);
/*
- Avoid problem with slow longlong aritmetic and sprintf
+ Avoid problem with slow longlong arithmetic and sprintf
*/
part1=(long) (tmp/LL(1000000));
@@ -4860,7 +5779,7 @@ bool Field_datetime::get_date(TIME *ltime, uint fuzzydate)
ltime->day= (int) (part1%100);
ltime->month= (int) (part1/100%100);
ltime->year= (int) (part1/10000);
- return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0;
+ return (!(fuzzydate & TIME_FUZZY_DATE) && (!ltime->month || !ltime->day)) ? 1 : 0;
}
bool Field_datetime::get_time(TIME *ltime)
@@ -4872,7 +5791,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr)
{
longlong a,b;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
a=sint8korr(a_ptr);
b=sint8korr(b_ptr);
@@ -4890,7 +5809,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr)
void Field_datetime::sort_string(char *to,uint length __attribute__((unused)))
{
#ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
+ if (!table->s->db_low_byte_first)
{
to[0] = ptr[0];
to[1] = ptr[1];
@@ -4932,14 +5851,14 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
int error= 0, well_formed_error;
uint32 not_used;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
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 */
+ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used))
{
uint conv_errors;
@@ -4974,7 +5893,12 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
error= 2;
}
if (error)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ {
+ if (table->in_use->abort_on_warning)
+ set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ else
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+ }
return error;
}
@@ -5025,30 +5949,41 @@ int Field_str::store(double nr)
}
-int Field_string::store(longlong nr)
+int Field_string::store(longlong nr, bool unsigned_val)
{
char buff[64];
int l;
CHARSET_INFO *cs=charset();
- l= (cs->cset->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr);
+ l= (cs->cset->longlong10_to_str)(cs,buff,sizeof(buff),
+ unsigned_val ? 10 : -10, nr);
return Field_string::store(buff,(uint)l,cs);
}
+int Field_longstr::store_decimal(const my_decimal *d)
+{
+ char buff[DECIMAL_MAX_STR_LENGTH+1];
+ String str(buff, sizeof(buff), &my_charset_bin);
+ my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
+ return store(str.ptr(), str.length(), str.charset());
+}
+
+
double Field_string::val_real(void)
{
int not_used;
char *end_not_used;
- CHARSET_INFO *cs=charset();
- return my_strntod(cs, ptr, field_length, &end_not_used, &not_used);
+ CHARSET_INFO *cs= charset();
+ return my_strntod(cs,ptr,field_length,&end_not_used,&not_used);
}
longlong Field_string::val_int(void)
{
int not_used;
+ char *end_not_used;
CHARSET_INFO *cs=charset();
- return my_strntoll(cs,ptr,field_length,10,NULL,&not_used);
+ return my_strntoll(cs,ptr,field_length,10,&end_not_used,&not_used);
}
@@ -5063,6 +5998,14 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
}
+my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
+{
+ str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(),
+ decimal_value);
+ return decimal_value;
+}
+
+
int Field_string::cmp(const char *a_ptr, const char *b_ptr)
{
uint a_len, b_len;
@@ -5076,7 +6019,7 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr)
return field_charset->coll->strnncollsp(field_charset,
(const uchar*) a_ptr, field_length,
(const uchar*) b_ptr,
- field_length);
+ field_length, 0);
}
if (field_charset->mbmaxlen != 1)
{
@@ -5104,20 +6047,22 @@ void Field_string::sql_type(String &res) const
{
THD *thd= table->in_use;
CHARSET_INFO *cs=res.charset();
- ulong length= cs->cset->snprintf(cs,(char*) res.ptr(),
- res.alloced_length(), "%s(%d)",
- (field_length > 3 &&
- (table->db_options_in_use &
- HA_OPTION_PACK_RECORD) ?
- (has_charset() ? "varchar" : "varbinary") :
+ ulong length;
+
+ length= cs->cset->snprintf(cs,(char*) res.ptr(),
+ res.alloced_length(), "%s(%d)",
+ ((type() == MYSQL_TYPE_VAR_STRING &&
+ !thd->variables.new_mode) ?
+ (has_charset() ? "varchar" : "varbinary") :
(has_charset() ? "char" : "binary")),
- (int) field_length / charset()->mbmaxlen);
+ (int) field_length / charset()->mbmaxlen);
res.length(length);
if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
has_charset() && (charset()->state & MY_CS_BINSORT))
res.append(" binary");
}
+
char *Field_string::pack(char *to, const char *from, uint max_length)
{
uint length= min(field_length,max_length);
@@ -5151,10 +6096,27 @@ const char *Field_string::unpack(char *to, const char *from)
}
-int Field_string::pack_cmp(const char *a, const char *b, uint length)
+/*
+ Compare two packed keys
+
+ SYNOPSIS
+ pack_cmp()
+ a New key
+ b Original key
+ length Key length
+ insert_or_update 1 if this is an insert or update
+
+ RETURN
+ < 0 a < b
+ 0 a = b
+ > 0 a > b
+*/
+
+int Field_string::pack_cmp(const char *a, const char *b, uint length,
+ my_bool insert_or_update)
{
uint a_length, b_length;
- if (field_length > 255)
+ if (length > 255)
{
a_length= uint2korr(a);
b_length= uint2korr(b);
@@ -5166,29 +6128,51 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*)a,a_length,
- (const uchar*)b,b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_string::pack_cmp(const char *b, uint length)
+/*
+ Compare a packed key against row
+
+ SYNOPSIS
+ pack_cmp()
+ key Original key
+ length Key length. (May be less than field length)
+ insert_or_update 1 if this is an insert or update
+
+ RETURN
+ < 0 row < key
+ 0 row = key
+ > 0 row > key
+*/
+
+int Field_string::pack_cmp(const char *key, uint length,
+ my_bool insert_or_update)
{
- uint b_length;
- if (field_length > 255)
+ uint row_length, key_length;
+ char *end;
+ if (length > 255)
{
- b_length= uint2korr(b);
- b+= 2;
+ key_length= uint2korr(key);
+ key+= 2;
}
else
- b_length= (uint) (uchar) *b++;
- char *end= ptr + field_length;
+ key_length= (uint) (uchar) *key++;
+
+ /* Only use 'length' of key, not field_length */
+ end= ptr + length;
while (end > ptr && end[-1] == ' ')
end--;
- uint a_length = (uint) (end - ptr);
- return my_strnncoll(field_charset,
- (const uchar*)ptr,a_length,
- (const uchar*)b, b_length);
+ row_length= (uint) (end - ptr);
+
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) ptr, row_length,
+ (const uchar*) key, key_length,
+ insert_or_update);
}
@@ -5196,29 +6180,57 @@ uint Field_string::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+2;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_string::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
}
+Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
+{
+ if (type() != MYSQL_TYPE_VAR_STRING || table == new_table)
+ return Field::new_field(root, new_table);
+
+ /*
+ Old VARCHAR field which should be modified to a VARCHAR on copy
+ This is done to ensure that ALTER TABLE will convert old VARCHAR fields
+ to now VARCHAR fields.
+ */
+ return new Field_varstring(field_length, maybe_null(),
+ field_name, new_table,
+ charset());
+}
+
/****************************************************************************
-** VARCHAR type (Not available for the end user yet)
+ VARCHAR type
+ Data in field->ptr is stored as:
+ 1 or 2 bytes length-prefix-header (from Field_varstring::length_bytes)
+ data
+
+ NOTE:
+ When VARCHAR is stored in a key (for handler::index_read() etc) it's always
+ stored with a 2 byte prefix. (Just like blob keys).
+
+ Normally length_bytes is calculated as (field_length < 256 : 1 ? 2)
+ The exception is if there is a prefix key field that is part of a long
+ VARCHAR, in which case field_length for this may be 1 but the length_bytes
+ is 2.
****************************************************************************/
int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
- int error= 0;
- uint32 not_used;
- char buff[80];
+ uint32 not_used, copy_length;
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
+ int error_code= 0, well_formed_error;
+ enum MYSQL_ERROR::enum_warning_level level= MYSQL_ERROR::WARN_LEVEL_WARN;
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used))
{
uint conv_errors;
@@ -5226,38 +6238,67 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
from= tmpstr.ptr();
length= tmpstr.length();
if (conv_errors)
- error= 2;
+ error_code= WARN_DATA_TRUNCATED;
}
- if (length > field_length)
+ /*
+ Make sure we don't break a multibyte sequence
+ as well as don't copy a malformed data.
+ */
+ copy_length= field_charset->cset->well_formed_len(field_charset,
+ from,from+length,
+ field_length/
+ field_charset->mbmaxlen,
+ &well_formed_error);
+ memcpy(ptr + length_bytes, from, copy_length);
+ if (length_bytes == 1)
+ *ptr= (uchar) copy_length;
+ else
+ int2store(ptr, copy_length);
+
+ // Check if we lost something other than just trailing spaces
+ if ((copy_length < length) && table->in_use->count_cuted_fields &&
+ !error_code)
{
- length=field_length;
- error= 2;
+ const char *end= from + length;
+ from+= copy_length;
+ from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES);
+ /* If we lost only spaces then produce a NOTE, not a WARNING */
+ if (from == end)
+ level= MYSQL_ERROR::WARN_LEVEL_NOTE;
+ error_code= WARN_DATA_TRUNCATED;
}
- if (error)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length);
- int2store(ptr, length);
- return error;
+ if (error_code)
+ {
+ if (level == MYSQL_ERROR::WARN_LEVEL_WARN &&
+ table->in_use->abort_on_warning)
+ error_code= ER_DATA_TOO_LONG;
+ set_warning(level, error_code, 1);
+ return 2;
+ }
+ return 0;
}
-int Field_varstring::store(longlong nr)
+int Field_varstring::store(longlong nr, bool unsigned_val)
{
char buff[64];
- int l;
- CHARSET_INFO *cs=charset();
- l= (cs->cset->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr);
- return Field_varstring::store(buff,(uint)l,cs);
+ uint length;
+ length= (uint) (field_charset->cset->longlong10_to_str)(field_charset,
+ buff,
+ sizeof(buff),
+ (unsigned_val ? 10:
+ -10),
+ nr);
+ return Field_varstring::store(buff, length, field_charset);
}
double Field_varstring::val_real(void)
{
int not_used;
- uint length=uint2korr(ptr)+HA_KEY_BLOB_LENGTH;
- CHARSET_INFO *cs=charset();
char *end_not_used;
- return my_strntod(cs, ptr+HA_KEY_BLOB_LENGTH, length, &end_not_used,
+ uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
+ return my_strntod(field_charset, ptr+length_bytes, length, &end_not_used,
&not_used);
}
@@ -5265,110 +6306,267 @@ double Field_varstring::val_real(void)
longlong Field_varstring::val_int(void)
{
int not_used;
- uint length=uint2korr(ptr)+HA_KEY_BLOB_LENGTH;
- CHARSET_INFO *cs=charset();
- return my_strntoll(cs,ptr+HA_KEY_BLOB_LENGTH,length,10,NULL, &not_used);
+ char *end_not_used;
+ uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
+ return my_strntoll(field_charset, ptr+length_bytes, length, 10,
+ &end_not_used, &not_used);
}
-
String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
- uint length=uint2korr(ptr);
- val_ptr->set((const char*) ptr+HA_KEY_BLOB_LENGTH,length,field_charset);
+ uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
+ val_ptr->set((const char*) ptr+length_bytes, length, field_charset);
return val_ptr;
}
+my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value)
+{
+ uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
+ str2my_decimal(E_DEC_FATAL_ERROR, ptr+length_bytes, length, charset(),
+ decimal_value);
+ return decimal_value;
+}
+
+
int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
{
- uint a_length=uint2korr(a_ptr);
- uint b_length=uint2korr(b_ptr);
+ uint a_length, b_length;
int diff;
- diff= my_strnncoll(field_charset,
- (const uchar*) a_ptr+HA_KEY_BLOB_LENGTH,
- min(a_length,b_length),
- (const uchar*) b_ptr+HA_KEY_BLOB_LENGTH,
- min(a_length,b_length));
- return diff ? diff : (int) (a_length - b_length);
+
+ if (length_bytes == 1)
+ {
+ a_length= (uint) (uchar) *a_ptr;
+ b_length= (uint) (uchar) *b_ptr;
+ }
+ else
+ {
+ a_length= uint2korr(a_ptr);
+ b_length= uint2korr(b_ptr);
+ }
+ diff= field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a_ptr+
+ length_bytes,
+ a_length,
+ (const uchar*) b_ptr+
+ length_bytes,
+ b_length,0);
+ return diff;
+}
+
+
+/*
+ NOTE: varstring and blob keys are ALWAYS stored with a 2 byte length prefix
+*/
+
+int Field_varstring::key_cmp(const byte *key_ptr, uint max_key_length)
+{
+ uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
+ uint char_length= max_key_length / field_charset->mbmaxlen;
+
+ char_length= my_charpos(field_charset, ptr + length_bytes,
+ ptr + length_bytes + length, char_length);
+ set_if_smaller(length, char_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) ptr + length_bytes,
+ length,
+ (const uchar*) key_ptr+
+ HA_KEY_BLOB_LENGTH,
+ uint2korr(key_ptr), 0);
}
+
+/*
+ Compare to key segments (always 2 byte length prefix)
+
+ NOTE
+ This is used only to compare key segments created for index_read().
+ (keys are created and compared in key.cc)
+*/
+
+int Field_varstring::key_cmp(const byte *a,const byte *b)
+{
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a +
+ HA_KEY_BLOB_LENGTH,
+ uint2korr(a),
+ (const uchar*) b +
+ HA_KEY_BLOB_LENGTH,
+ uint2korr(b),
+ 0);
+}
+
+
void Field_varstring::sort_string(char *to,uint length)
{
- uint tot_length=uint2korr(ptr);
+ uint tot_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
tot_length= my_strnxfrm(field_charset,
(uchar*) to, length,
- (uchar*) ptr+HA_KEY_BLOB_LENGTH,
+ (uchar*) ptr + length_bytes,
tot_length);
DBUG_ASSERT(tot_length == length);
}
+enum ha_base_keytype Field_varstring::key_type() const
+{
+ enum ha_base_keytype res;
+
+ if (binary())
+ res= length_bytes == 1 ? HA_KEYTYPE_VARBINARY1 : HA_KEYTYPE_VARBINARY2;
+ else
+ res= length_bytes == 1 ? HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2;
+ return res;
+}
+
+
void Field_varstring::sql_type(String &res) const
{
+ THD *thd= table->in_use;
CHARSET_INFO *cs=res.charset();
- ulong length= cs->cset->snprintf(cs,(char*) res.ptr(),
- res.alloced_length(),"varchar(%u)",
- field_length / charset()->mbmaxlen);
+ ulong length;
+
+ length= cs->cset->snprintf(cs,(char*) res.ptr(),
+ res.alloced_length(), "%s(%d)",
+ (has_charset() ? "varchar" : "varbinary"),
+ (int) field_length / charset()->mbmaxlen);
res.length(length);
+ if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
+ has_charset() && (charset()->state & MY_CS_BINSORT))
+ res.append(" binary");
}
+
+/*
+ Functions to create a packed row.
+ Here the number of length bytes are depending on the given max_length
+*/
+
char *Field_varstring::pack(char *to, const char *from, uint max_length)
{
- uint length=uint2korr(from);
+ uint length= length_bytes == 1 ? (uint) (uchar) *from : uint2korr(from);
+ set_if_smaller(max_length, field_length);
if (length > max_length)
length=max_length;
*to++= (char) (length & 255);
if (max_length > 255)
*to++= (char) (length >> 8);
if (length)
- memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
+ memcpy(to, from+length_bytes, length);
return to+length;
}
-char *Field_varstring::pack_key(char *to, const char *from, uint max_length)
+char *Field_varstring::pack_key(char *to, const char *key, uint max_length)
{
- uint length=uint2korr(from);
- uint char_length= (field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length;
- from+=HA_KEY_BLOB_LENGTH;
+ uint length= length_bytes == 1 ? (uint) (uchar) *key : uint2korr(key);
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ max_length/field_charset->mbmaxlen : max_length);
+ key+= length_bytes;
if (length > char_length)
- char_length= my_charpos(field_charset, from, from+length, char_length);
- set_if_smaller(length, char_length);
+ {
+ char_length= my_charpos(field_charset, key, key+length, char_length);
+ set_if_smaller(length, char_length);
+ }
+ *to++= (char) (length & 255);
+ if (max_length > 255)
+ *to++= (char) (length >> 8);
+ if (length)
+ memcpy(to, key, length);
+ return to+length;
+}
+
+
+/*
+ Unpack a key into a record buffer.
+
+ SYNOPSIS
+ unpack_key()
+ to Pointer into the record buffer.
+ key Pointer to the packed key.
+ max_length Key length limit from key description.
+
+ DESCRIPTION
+ A VARCHAR 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'.
+
+ RETURN
+ Pointer to end of 'key' (To the next key part if multi-segment key)
+*/
+
+const char *Field_varstring::unpack_key(char *to, const char *key,
+ uint max_length)
+{
+ /* get length of the blob key */
+ uint32 length= *((uchar*) key++);
+ if (max_length > 255)
+ length+= (*((uchar*) key++)) << 8;
+
+ /* put the length into the record buffer */
+ if (length_bytes == 1)
+ *ptr= (uchar) length;
+ else
+ int2store(ptr, length);
+ memcpy(ptr + length_bytes, key, length);
+ return key + length;
+}
+
+/*
+ Create a packed key that will be used for storage in the index tree
+
+ SYNOPSIS
+ pack_key_from_key_image()
+ to Store packed key segment here
+ from Key segment (as given to index_read())
+ max_length Max length of key
+
+ RETURN
+ end of key storage
+*/
+
+char *Field_varstring::pack_key_from_key_image(char *to, const char *from,
+ uint max_length)
+{
+ /* Key length is always stored as 2 bytes */
+ uint length= uint2korr(from);
+ if (length > max_length)
+ length= max_length;
*to++= (char) (length & 255);
if (max_length > 255)
*to++= (char) (length >> 8);
if (length)
- memcpy(to, from, length);
+ memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
return to+length;
}
+/*
+ unpack field packed with Field_varstring::pack()
+*/
+
const char *Field_varstring::unpack(char *to, const char *from)
{
uint length;
- if (field_length > 255)
- {
+ if (length_bytes == 1)
length= (uint) (uchar) (*to= *from++);
- to[1]=0;
- }
else
{
- length=uint2korr(from);
- to[0] = *from++;
- to[1] = *from++;
+ length= uint2korr(from);
+ to[0]= *from++;
+ to[1]= *from++;
}
if (length)
- memcpy(to+HA_KEY_BLOB_LENGTH, from, length);
+ memcpy(to+ length_bytes, from, length);
return from+length;
}
-int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
+int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update)
{
- uint a_length;
- uint b_length;
+ uint a_length, b_length;
if (key_length > 255)
{
a_length=uint2korr(a); a+= 2;
@@ -5379,63 +6577,136 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_varstring::pack_cmp(const char *b, uint key_length)
+
+int Field_varstring::pack_cmp(const char *b, uint key_length,
+ my_bool insert_or_update)
{
- char *a= ptr+HA_KEY_BLOB_LENGTH;
- uint a_length= uint2korr(ptr);
+ char *a= ptr+ length_bytes;
+ uint a_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
uint b_length;
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ key_length / field_charset->mbmaxlen : key_length);
+
if (key_length > 255)
{
- b_length=uint2korr(b); b+= 2;
+ b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
}
else
- {
b_length= (uint) (uchar) *b++;
+
+ if (a_length > char_length)
+ {
+ char_length= my_charpos(field_charset, a, a+a_length, char_length);
+ set_if_smaller(a_length, char_length);
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a,
+ a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
+
uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(data_ptr)+HA_KEY_BLOB_LENGTH;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return uint2korr(data_ptr)+2;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_varstring::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
}
-void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
- imagetype type)
+
+void Field_varstring::get_key_image(char *buff, uint length, imagetype type)
{
- uint f_length=uint2korr(ptr);
- if (f_length > length)
- f_length= length;
- int2store(buff,length);
- memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, length);
-#ifdef HAVE_purify
+ uint f_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
+ uint char_length= length / field_charset->mbmaxlen;
+ char *pos= ptr+length_bytes;
+ char_length= my_charpos(field_charset, pos, pos + f_length, char_length);
+ set_if_smaller(f_length, char_length);
+ /* Key is always stored with 2 bytes */
+ int2store(buff,f_length);
+ memcpy(buff+HA_KEY_BLOB_LENGTH, pos, f_length);
if (f_length < length)
+ {
+ /*
+ Must clear this as we do a memcmp in opt_range.cc to detect
+ identical keys
+ */
bzero(buff+HA_KEY_BLOB_LENGTH+f_length, (length-f_length));
-#endif
+ }
+}
+
+
+void Field_varstring::set_key_image(char *buff,uint length)
+{
+ length= uint2korr(buff); // Real length is here
+ (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length,
+ field_charset);
+}
+
+
+int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr,
+ uint32 max_length)
+{
+ uint32 a_length,b_length;
+
+ if (length_bytes == 1)
+ {
+ a_length= (uint) (uchar) *a_ptr;
+ b_length= (uint) (uchar) *b_ptr;
+ }
+ else
+ {
+ a_length= uint2korr(a_ptr);
+ b_length= uint2korr(b_ptr);
+ }
+ set_if_smaller(a_length, max_length);
+ set_if_smaller(b_length, max_length);
+ if (a_length != b_length)
+ return 1;
+ return memcmp(a_ptr+length_bytes, b_ptr+length_bytes, a_length);
}
-void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+
+Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table)
{
- length=uint2korr(buff); // Real length is here
- (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
+ Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table);
+ if (res)
+ res->length_bytes= length_bytes;
+ return res;
}
+Field *Field_varstring::new_key_field(MEM_ROOT *root,
+ struct st_table *new_table,
+ char *new_ptr, uchar *new_null_ptr,
+ uint new_null_bit)
+{
+ Field_varstring *res;
+ if ((res= (Field_varstring*) Field::new_key_field(root,
+ new_table,
+ new_ptr,
+ new_null_ptr,
+ new_null_bit)))
+ {
+ /* Keys length prefixes are always packed with 2 bytes */
+ res->length_bytes= 2;
+ }
+ return res;
+}
+
/****************************************************************************
** blob type
@@ -5447,14 +6718,14 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
CHARSET_INFO *cs)
- :Field_str(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length),
+ :Field_longstr(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length),
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
table_arg, cs),
packlength(blob_pack_length)
{
flags|= BLOB_FLAG;
if (table)
- table->blob_fields++;
+ table->s->blob_fields++;
}
@@ -5466,7 +6737,7 @@ void Field_blob::store_length(uint32 number)
break;
case 2:
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int2store(ptr,(unsigned short) number);
}
@@ -5479,7 +6750,7 @@ void Field_blob::store_length(uint32 number)
break;
case 4:
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int4store(ptr,number);
}
@@ -5499,7 +6770,7 @@ uint32 Field_blob::get_length(const char *pos)
{
uint16 tmp;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
tmp=sint2korr(pos);
else
#endif
@@ -5512,7 +6783,7 @@ uint32 Field_blob::get_length(const char *pos)
{
uint32 tmp;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
tmp=uint4korr(pos);
else
#endif
@@ -5570,17 +6841,22 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
else
{
bool was_conversion;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
uint copy_length;
uint32 not_used;
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if ((was_conversion= String::needs_conversion(length, cs, field_charset,
&not_used)))
{
uint conv_errors;
- tmpstr.copy(from, length, cs, field_charset, &conv_errors);
+ if (tmpstr.copy(from, length, cs, field_charset, &conv_errors))
+ {
+ /* Fatal OOM error */
+ bzero(ptr,Field_blob::pack_length());
+ return -1;
+ }
from= tmpstr.ptr();
length= tmpstr.length();
if (conv_errors)
@@ -5589,7 +6865,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
copy_length= max_data_length();
/*
- copy_length is ok as last argument to well_formed_len as this is never
+ copy_length is OK as last argument to well_formed_len as this is never
used to limit the length of the data. The cut of long data is done with
the 'min()' call below.
*/
@@ -5612,7 +6888,12 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
bmove(ptr+packlength,(char*) &from,sizeof(char*));
}
if (error)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ {
+ if (table->in_use->abort_on_warning)
+ set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ else
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+ }
return 0;
}
@@ -5625,10 +6906,13 @@ int Field_blob::store(double nr)
}
-int Field_blob::store(longlong nr)
+int Field_blob::store(longlong nr, bool unsigned_val)
{
CHARSET_INFO *cs=charset();
- value.set(nr, cs);
+ if (unsigned_val)
+ value.set((ulonglong) nr, cs);
+ else
+ value.set(nr, cs);
return Field_blob::store(value.ptr(), (uint) value.length(), cs);
}
@@ -5636,14 +6920,16 @@ int Field_blob::store(longlong nr)
double Field_blob::val_real(void)
{
int not_used;
- char *blob;
- char *end_not_used;
+ char *end_not_used, *blob;
+ uint32 length;
+ CHARSET_INFO *cs;
+
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0.0;
- uint32 length=get_length(ptr);
- CHARSET_INFO *cs=charset();
- return my_strntod(cs,blob,length, &end_not_used, &not_used);
+ length= get_length(ptr);
+ cs= charset();
+ return my_strntod(cs, blob, length, &end_not_used, &not_used);
}
@@ -5658,7 +6944,6 @@ longlong Field_blob::val_int(void)
return my_strntoll(charset(),blob,length,10,NULL,&not_used);
}
-
String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
@@ -5672,13 +6957,25 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
}
+my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
+{
+ const char *blob;
+ memcpy_fixed(&blob, ptr+packlength, sizeof(const char*));
+ if (!blob)
+ blob= "";
+ str2my_decimal(E_DEC_FATAL_ERROR, blob, get_length(ptr), charset(),
+ decimal_value);
+ return decimal_value;
+}
+
+
int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
uint32 b_length)
{
- return field_charset->coll->strnncoll(field_charset,
- (const uchar*)a, a_length,
- (const uchar*)b, b_length,
- 0);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*)a, a_length,
+ (const uchar*)b, b_length,
+ 0);
}
@@ -5692,18 +6989,6 @@ int Field_blob::cmp(const char *a_ptr, const char *b_ptr)
}
-int Field_blob::cmp_offset(uint row_offset)
-{
- return Field_blob::cmp(ptr,ptr+row_offset);
-}
-
-
-int Field_blob::cmp_binary_offset(uint row_offset)
-{
- return cmp_binary(ptr, ptr+row_offset);
-}
-
-
int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
uint32 max_length)
{
@@ -5725,8 +7010,7 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
/* The following is used only when comparing a key */
-void Field_blob::get_key_image(char *buff,uint length,
- CHARSET_INFO *cs, imagetype type)
+void Field_blob::get_key_image(char *buff, uint length, imagetype type)
{
uint32 blob_length= get_length(ptr);
char *blob;
@@ -5761,8 +7045,9 @@ void Field_blob::get_key_image(char *buff,uint length,
#endif /*HAVE_SPATIAL*/
get_ptr(&blob);
- uint char_length= length / cs->mbmaxlen;
- char_length= my_charpos(cs, blob, blob + blob_length, char_length);
+ uint char_length= length / field_charset->mbmaxlen;
+ char_length= my_charpos(field_charset, blob, blob + blob_length,
+ char_length);
set_if_smaller(blob_length, char_length);
if ((uint32) length > blob_length)
@@ -5778,10 +7063,11 @@ void Field_blob::get_key_image(char *buff,uint length,
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
}
-void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+
+void Field_blob::set_key_image(char *buff,uint length)
{
length= uint2korr(buff);
- (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
+ (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, field_charset);
}
@@ -5794,7 +7080,7 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
uint char_length= max_key_length / cs->mbmaxlen;
char_length= my_charpos(cs, blob1, blob1+blob_length, char_length);
set_if_smaller(blob_length, char_length);
- return Field_blob::cmp(blob1,min(blob_length, max_key_length),
+ return Field_blob::cmp(blob1, blob_length,
(char*) key_ptr+HA_KEY_BLOB_LENGTH,
uint2korr(key_ptr));
}
@@ -5883,10 +7169,10 @@ const char *Field_blob::unpack(char *to, const char *from)
/* Keys for blobs are like keys on varchars */
-int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
+int Field_blob::pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update)
{
- uint a_length;
- uint b_length;
+ uint a_length, b_length;
if (key_length > 255)
{
a_length=uint2korr(a); a+=2;
@@ -5897,13 +7183,15 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_blob::pack_cmp(const char *b, uint key_length)
+int Field_blob::pack_cmp(const char *b, uint key_length,
+ my_bool insert_or_update)
{
char *a;
memcpy_fixed(&a,ptr+packlength,sizeof(char*));
@@ -5917,12 +7205,11 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
b_length=uint2korr(b); b+=2;
}
else
- {
b_length= (uint) (uchar) *b++;
- }
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
/* Create a packed key that will be used for storage from a MySQL row */
@@ -5932,8 +7219,8 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
char *save=ptr;
ptr=(char*) from;
uint32 length=get_length(); // Length of from string
- uint char_length= (field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length;
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ max_length/field_charset->mbmaxlen : max_length);
if (length)
get_ptr((char**) &from);
if (length > char_length)
@@ -5991,6 +7278,7 @@ const char *Field_blob::unpack_key(char *to, const char *from, uint max_length)
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,
@@ -6007,14 +7295,15 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
return to+length;
}
+
uint Field_blob::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+2;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_blob::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
@@ -6023,8 +7312,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
#ifdef HAVE_SPATIAL
-void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
- imagetype type)
+void Field_geom::get_key_image(char *buff, uint length, imagetype type)
{
char *blob;
const char *dummy;
@@ -6053,11 +7341,6 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
}
-void Field_geom::set_key_image(char *buff, uint length, CHARSET_INFO *cs)
-{
- Field_blob::set_key_image(buff, length, cs);
-}
-
void Field_geom::sql_type(String &res) const
{
CHARSET_INFO *cs= &my_charset_latin1;
@@ -6090,12 +7373,38 @@ void Field_geom::sql_type(String &res) const
}
+int Field_geom::store(double nr)
+{
+ my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
+ ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
+ return -1;
+}
+
+
+int Field_geom::store(longlong nr, bool unsigned_val)
+{
+ my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
+ ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
+ return -1;
+}
+
+
+int Field_geom::store_decimal(const my_decimal *)
+{
+ my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
+ ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
+ return -1;
+}
+
+
int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
{
if (!length)
bzero(ptr, Field_blob::pack_length());
else
{
+ if (from == Geometry::bad_geometry_data.ptr())
+ goto err;
// Check given WKB
uint32 wkb_type;
if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2)
@@ -6103,7 +7412,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
wkb_type= uint4korr(from + WKB_HEADER_SIZE);
if (wkb_type < (uint32) Geometry::wkb_point ||
wkb_type > (uint32) Geometry::wkb_end)
- return -1;
+ goto err;
Field_blob::store_length(length);
if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
{ // Must make a copy
@@ -6116,6 +7425,8 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
err:
bzero(ptr, Field_blob::pack_length());
+ my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
+ ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
return -1;
}
@@ -6144,7 +7455,7 @@ void Field_enum::store_type(ulonglong value)
case 1: ptr[0]= (uchar) value; break;
case 2:
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int2store(ptr,(unsigned short) value);
}
@@ -6155,7 +7466,7 @@ void Field_enum::store_type(ulonglong value)
case 3: int3store(ptr,(long) value); break;
case 4:
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int4store(ptr,value);
}
@@ -6165,7 +7476,7 @@ void Field_enum::store_type(ulonglong value)
break;
case 8:
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
{
int8store(ptr,value);
}
@@ -6185,10 +7496,10 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{
int err= 0;
uint32 not_used;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used))
{
uint dummy_errors;
@@ -6210,11 +7521,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, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
}
else
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
store_type((ulonglong) tmp);
return err;
@@ -6223,16 +7534,16 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
int Field_enum::store(double nr)
{
- return Field_enum::store((longlong) nr);
+ return Field_enum::store((longlong) nr, FALSE);
}
-int Field_enum::store(longlong nr)
+int Field_enum::store(longlong nr, bool unsigned_val)
{
int error= 0;
- if ((uint) nr > typelib->count || nr == 0)
+ if ((ulonglong) nr > typelib->count || nr == 0)
{
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
nr=0;
error=1;
}
@@ -6256,7 +7567,7 @@ longlong Field_enum::val_int(void)
{
uint16 tmp;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
tmp=sint2korr(ptr);
else
#endif
@@ -6269,7 +7580,7 @@ longlong Field_enum::val_int(void)
{
uint32 tmp;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
tmp=uint4korr(ptr);
else
#endif
@@ -6280,7 +7591,7 @@ longlong Field_enum::val_int(void)
{
longlong tmp;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
tmp=sint8korr(ptr);
else
#endif
@@ -6369,10 +7680,10 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
char *not_used;
uint not_used2;
uint32 not_used_offset;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used_offset))
{
uint dummy_errors;
@@ -6391,24 +7702,24 @@ 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, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
}
else if (got_warning)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
store_type(tmp);
return err;
}
-int Field_set::store(longlong nr)
+int Field_set::store(longlong nr, bool unsigned_val)
{
int error= 0;
if ((ulonglong) nr > (ulonglong) (((longlong) 1 << typelib->count) -
(longlong) 1))
{
nr&= (longlong) (((longlong) 1 << typelib->count) - (longlong) 1);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
error=1;
}
store_type((ulonglong) nr);
@@ -6486,9 +7797,9 @@ bool Field_enum::eq_def(Field *field)
for (uint i=0 ; i < from_lib->count ; i++)
if (my_strnncoll(field_charset,
(const uchar*)typelib->type_names[i],
- strlen(typelib->type_names[i]),
+ (uint) strlen(typelib->type_names[i]),
(const uchar*)from_lib->type_names[i],
- strlen(from_lib->type_names[i])))
+ (uint) strlen(from_lib->type_names[i])))
return 0;
return 1;
}
@@ -6507,8 +7818,328 @@ bool Field_num::eq_def(Field *field)
}
+/*
+ Bit field.
+
+ We store the first 0 - 6 uneven bits among the null bits
+ at the start of the record. The rest bytes are stored in
+ the record itself.
+
+ For example:
+
+ CREATE TABLE t1 (a int, b bit(17), c bit(21) not null, d bit(8));
+ We would store data as follows in the record:
+
+ Byte Bit
+ 1 7 - reserve for delete
+ 6 - null bit for 'a'
+ 5 - null bit for 'b'
+ 4 - first (high) bit of 'b'
+ 3 - first (high) bit of 'c'
+ 2 - second bit of 'c'
+ 1 - third bit of 'c'
+ 0 - forth bit of 'c'
+ 2 7 - firth bit of 'c'
+ 6 - null bit for 'd'
+ 3 - 6 four bytes for 'a'
+ 7 - 8 two bytes for 'b'
+ 9 - 10 two bytes for 'c'
+ 11 one byte for 'd'
+*/
+
+Field_bit::Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ struct st_table *table_arg)
+ : Field(ptr_arg, len_arg >> 3, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg),
+ bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7)
+{
+ /*
+ Ensure that Field::eq() can distinguish between two different bit fields.
+ (two bit fields that are not null, may have same ptr and null_ptr)
+ */
+ if (!null_ptr_arg)
+ null_bit= bit_ofs_arg;
+}
+
+
+Field *Field_bit::new_key_field(MEM_ROOT *root,
+ struct st_table *new_table,
+ char *new_ptr, uchar *new_null_ptr,
+ uint new_null_bit)
+{
+ Field_bit *res;
+ if ((res= (Field_bit*) Field::new_key_field(root, new_table,
+ new_ptr, new_null_ptr,
+ new_null_bit)))
+ {
+ /* Move bits normally stored in null_pointer to new_ptr */
+ res->bit_ptr= (uchar*) new_ptr;
+ res->bit_ofs= 0;
+ if (bit_len)
+ res->ptr++; // Store rest of data here
+ }
+ return res;
+}
+
+
+int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs)
+{
+ int delta;
+
+ for (; !*from && length; from++, length--); // skip left 0's
+ delta= field_length - length;
+
+ if (delta < -1 ||
+ (delta == -1 && (uchar) *from > ((1 << bit_len) - 1)) ||
+ (!bit_len && delta < 0))
+ {
+ set_rec_bits(0xff, bit_ptr, bit_ofs, bit_len);
+ memset(ptr, 0xff, field_length);
+ if (table->in_use->really_abort_on_warning())
+ set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ else
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ return 1;
+ }
+ /* delta is >= -1 here */
+ if (delta > 0)
+ {
+ if (bit_len)
+ clr_rec_bits(bit_ptr, bit_ofs, bit_len);
+ bzero(ptr, delta);
+ memcpy(ptr + delta, from, length);
+ }
+ else if (delta == 0)
+ {
+ if (bit_len)
+ clr_rec_bits(bit_ptr, bit_ofs, bit_len);
+ memcpy(ptr, from, length);
+ }
+ else
+ {
+ if (bit_len)
+ {
+ set_rec_bits((uchar) *from, bit_ptr, bit_ofs, bit_len);
+ from++;
+ }
+ memcpy(ptr, from, field_length);
+ }
+ return 0;
+}
+
+
+int Field_bit::store(double nr)
+{
+ return store((longlong) nr, FALSE);
+}
+
+
+int Field_bit::store(longlong nr, bool unsigned_val)
+{
+ char buf[8];
+
+ mi_int8store(buf, nr);
+ return store(buf, 8, NULL);
+}
+
+
+int Field_bit::store_decimal(const my_decimal *val)
+{
+ int err= 0;
+ longlong i= convert_decimal2longlong(val, 1, &err);
+ return test(err | store(i));
+}
+
+
+double Field_bit::val_real(void)
+{
+ return (double) Field_bit::val_int();
+}
+
+
+longlong Field_bit::val_int(void)
+{
+ ulonglong bits= 0;
+ if (bit_len)
+ {
+ bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
+ bits<<= (field_length * 8);
+ }
+
+ switch (field_length) {
+ case 0: return bits;
+ case 1: return bits | (ulonglong) (uchar) ptr[0];
+ case 2: return bits | mi_uint2korr(ptr);
+ case 3: return bits | mi_uint3korr(ptr);
+ case 4: return bits | mi_uint4korr(ptr);
+ case 5: return bits | mi_uint5korr(ptr);
+ case 6: return bits | mi_uint6korr(ptr);
+ case 7: return bits | mi_uint7korr(ptr);
+ default: return mi_uint8korr(ptr + field_length - sizeof(longlong));
+ }
+}
+
+
+String *Field_bit::val_str(String *val_buffer,
+ String *val_ptr __attribute__((unused)))
+{
+ char buff[sizeof(longlong)];
+ uint length= min(pack_length(), sizeof(longlong));
+ ulonglong bits= val_int();
+ mi_int8store(buff,bits);
+
+ val_buffer->alloc(length);
+ memcpy_fixed((char*) val_buffer->ptr(), buff+8-length, length);
+ val_buffer->length(length);
+ val_buffer->set_charset(&my_charset_bin);
+ return val_buffer;
+}
+
+
+my_decimal *Field_bit::val_decimal(my_decimal *deciaml_value)
+{
+ int2my_decimal(E_DEC_FATAL_ERROR, val_int(), 1, deciaml_value);
+ return deciaml_value;
+}
+
+
+int Field_bit::key_cmp(const byte *str, uint length)
+{
+ if (bit_len)
+ {
+ int flag;
+ uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
+ if ((flag= (int) (bits - *(uchar*) str)))
+ return flag;
+ str++;
+ length--;
+ }
+ return memcmp(ptr, str, length);
+}
+
+
+int Field_bit::cmp_offset(uint row_offset)
+{
+ if (bit_len)
+ {
+ int flag;
+ uchar bits_a= get_rec_bits(bit_ptr, bit_ofs, bit_len);
+ uchar bits_b= get_rec_bits(bit_ptr + row_offset, bit_ofs, bit_len);
+ if ((flag= (int) (bits_a - bits_b)))
+ return flag;
+ }
+ return memcmp(ptr, ptr + row_offset, field_length);
+}
+
+
+void Field_bit::get_key_image(char *buff, uint length, imagetype type)
+{
+ if (bit_len)
+ {
+ uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
+ *buff++= bits;
+ length--;
+ }
+ memcpy(buff, ptr, min(length, field_length));
+}
+
+
+void Field_bit::sql_type(String &res) const
+{
+ CHARSET_INFO *cs= res.charset();
+ ulong length= cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
+ "bit(%d)",
+ (int) field_length * 8 + bit_len);
+ res.length((uint) length);
+}
+
+
+char *Field_bit::pack(char *to, const char *from, uint max_length)
+{
+ uint length= min(field_length + (bit_len > 0), max_length);
+ if (bit_len)
+ {
+ uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
+ *to++= bits;
+ length--;
+ }
+ memcpy(to, from, length);
+ return to + length;
+}
+
+
+const char *Field_bit::unpack(char *to, const char *from)
+{
+ if (bit_len)
+ {
+ set_rec_bits(*from, bit_ptr, bit_ofs, bit_len);
+ from++;
+ }
+ memcpy(to, from, field_length);
+ return from + field_length;
+}
+
+
+/*
+ Bit field support for non-MyISAM tables.
+*/
+
+Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg,
+ uchar *null_ptr_arg, uchar null_bit_arg,
+ uchar *bit_ptr_arg, uchar bit_ofs_arg,
+ enum utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg)
+ : Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, bit_ptr_arg,
+ bit_ofs_arg, unireg_check_arg, field_name_arg, table_arg),
+ create_length(len_arg)
+{
+ bit_ptr= 0;
+ bit_ofs= 0;
+ bit_len= 0;
+ field_length= ((len_arg + 7) & ~7) / 8;
+}
+
+
+int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs)
+{
+ int delta;
+ uchar bits= create_length & 7;
+
+ for (; !*from && length; from++, length--); // skip left 0's
+ delta= field_length - length;
+
+ if (delta < 0 ||
+ (delta == 0 && bits && (uint) (uchar) *from >= (uint) (1 << bits)))
+ {
+ memset(ptr, 0xff, field_length);
+ if (bits)
+ *ptr&= ((1 << bits) - 1); /* set first byte */
+ if (table->in_use->really_abort_on_warning())
+ set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ else
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ return 1;
+ }
+ bzero(ptr, delta);
+ memcpy(ptr + delta, from, length);
+ return 0;
+}
+
+
+void Field_bit_as_char::sql_type(String &res) const
+{
+ CHARSET_INFO *cs= res.charset();
+ ulong length= cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
+ "bit(%d)", (int) create_length);
+ res.length((uint) length);
+}
+
+
/*****************************************************************************
-** Handling of field and create_field
+ Handling of field and create_field
*****************************************************************************/
void create_field::create_length_to_internal_length(void)
@@ -6520,20 +8151,77 @@ void create_field::create_length_to_internal_length(void)
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VARCHAR:
length*= charset->mbmaxlen;
- pack_length= calc_pack_length(sql_type == FIELD_TYPE_VAR_STRING ?
- FIELD_TYPE_STRING : sql_type, length);
+ key_length= length;
+ pack_length= calc_pack_length(sql_type, length);
break;
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
+ /* Pack_length already calculated in sql_parse.cc */
length*= charset->mbmaxlen;
+ key_length= pack_length;
+ break;
+ case MYSQL_TYPE_BIT:
+ if (f_bit_as_char(pack_flag))
+ {
+ key_length= pack_length= ((length + 7) & ~7) / 8;
+ }
+ else
+ {
+ pack_length= length / 8;
+ /* We need one extra byte to store the bits we save among the null bits */
+ key_length= pack_length + test(length & 7);
+ }
+ break;
+ case MYSQL_TYPE_NEWDECIMAL:
+ key_length= pack_length=
+ my_decimal_get_binary_size(my_decimal_length_to_precision(length,
+ decimals,
+ flags &
+ UNSIGNED_FLAG),
+ decimals);
break;
default:
- /* do nothing */
+ key_length= pack_length= calc_pack_length(sql_type, length);
break;
}
}
+
+void create_field::init_for_tmp_table(enum_field_types sql_type_arg,
+ uint32 length_arg, uint32 decimals,
+ bool maybe_null, bool is_unsigned)
+{
+ field_name= "";
+ sql_type= sql_type_arg;
+ length= length_arg;;
+ unireg_check= Field::NONE;
+ interval= 0;
+ charset= &my_charset_bin;
+ geom_type= Field::GEOM_GEOMETRY;
+ pack_flag= (FIELDFLAG_NUMBER |
+ ((decimals & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT) |
+ (maybe_null ? FIELDFLAG_MAYBE_NULL : 0) |
+ (is_unsigned ? 0 : FIELDFLAG_DECIMAL));
+}
+
+
+enum_field_types get_blob_type_from_length(ulong length)
+{
+ enum_field_types type;
+ if (length < 256)
+ type= FIELD_TYPE_TINY_BLOB;
+ else if (length < 65536)
+ type= FIELD_TYPE_BLOB;
+ else if (length < 256L*256L*256L)
+ type= FIELD_TYPE_MEDIUM_BLOB;
+ else
+ type= FIELD_TYPE_LONG_BLOB;
+ return type;
+}
+
+
/*
Make a field from the .frm file info
*/
@@ -6541,9 +8229,10 @@ void create_field::create_length_to_internal_length(void)
uint32 calc_pack_length(enum_field_types type,uint32 length)
{
switch (type) {
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_DECIMAL: return (length);
- case FIELD_TYPE_VAR_STRING: return (length+HA_KEY_BLOB_LENGTH);
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case FIELD_TYPE_DECIMAL: return (length);
+ case MYSQL_TYPE_VARCHAR: return (length + (length < 256 ? 1: 2));
case FIELD_TYPE_YEAR:
case FIELD_TYPE_TINY : return 1;
case FIELD_TYPE_SHORT : return 2;
@@ -6564,10 +8253,13 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
case FIELD_TYPE_LONG_BLOB: return 4+portable_sizeof_char_ptr;
case FIELD_TYPE_GEOMETRY: return 4+portable_sizeof_char_ptr;
case FIELD_TYPE_SET:
- case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen
- default: return 0;
+ case FIELD_TYPE_ENUM:
+ case FIELD_TYPE_NEWDECIMAL:
+ abort(); return 0; // This shouldn't happen
+ case FIELD_TYPE_BIT: return length / 8;
+ default:
+ return 0;
}
- return 0; // Keep compiler happy
}
@@ -6595,11 +8287,30 @@ Field *make_field(char *ptr, uint32 field_length,
const char *field_name,
struct st_table *table)
{
+ uchar *bit_ptr;
+ uchar bit_offset;
+ LINT_INIT(bit_ptr);
+ LINT_INIT(bit_offset);
+ if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag))
+ {
+ bit_ptr= null_pos;
+ bit_offset= null_bit;
+ if (f_maybe_null(pack_flag)) // if null field
+ {
+ bit_ptr+= (null_bit == 7); // shift bit_ptr and bit_offset
+ bit_offset= (bit_offset + 1) & 7;
+ }
+ }
+
if (!f_maybe_null(pack_flag))
{
null_pos=0;
null_bit=0;
}
+ else
+ {
+ null_bit= ((uchar) 1) << null_bit;
+ }
switch (field_type)
{
@@ -6616,12 +8327,18 @@ Field *make_field(char *ptr, uint32 field_length,
{
if (!f_is_packed(pack_flag))
{
- if (field_type == FIELD_TYPE_STRING ||
+ if (field_type == MYSQL_TYPE_STRING ||
field_type == FIELD_TYPE_DECIMAL || // 3.23 or 4.0 string
- field_type == FIELD_TYPE_VAR_STRING)
+ field_type == MYSQL_TYPE_VAR_STRING)
return new Field_string(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table,
field_charset);
+ if (field_type == MYSQL_TYPE_VARCHAR)
+ return new Field_varstring(ptr,field_length,
+ HA_VARCHAR_PACKLENGTH(field_length),
+ null_pos,null_bit,
+ unireg_check, field_name, table,
+ field_charset);
return 0; // Error
}
@@ -6659,6 +8376,12 @@ Field *make_field(char *ptr, uint32 field_length,
f_decimals(pack_flag),
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
+ case FIELD_TYPE_NEWDECIMAL:
+ return new Field_new_decimal(ptr,field_length,null_pos,null_bit,
+ unireg_check, field_name, table,
+ f_decimals(pack_flag),
+ f_is_zerofill(pack_flag) != 0,
+ f_is_dec(pack_flag) == 0);
case FIELD_TYPE_FLOAT:
return new Field_float(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table,
@@ -6717,6 +8440,12 @@ Field *make_field(char *ptr, uint32 field_length,
unireg_check, field_name, table, field_charset);
case FIELD_TYPE_NULL:
return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset);
+ case FIELD_TYPE_BIT:
+ return f_bit_as_char(pack_flag) ?
+ new Field_bit_as_char(ptr, field_length, null_pos, null_bit, bit_ptr,
+ bit_offset, unireg_check, field_name, table) :
+ new Field_bit(ptr, field_length, null_pos, null_bit, bit_ptr,
+ bit_offset, unireg_check, field_name, table);
default: // Impossible (Wrong version)
break;
}
@@ -6734,83 +8463,123 @@ create_field::create_field(Field *old_field,Field *orig_field)
flags= old_field->flags;
unireg_check=old_field->unireg_check;
pack_length=old_field->pack_length();
+ key_length= old_field->key_length();
sql_type= old_field->real_type();
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
+ decimals= old_field->decimals();
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
- pack_length= (pack_length- old_field->table->blob_ptr_size +
+ pack_length= (pack_length- old_field->table->s->blob_ptr_size +
portable_sizeof_char_ptr);
- switch (sql_type)
- {
- case FIELD_TYPE_BLOB:
- switch (pack_length - portable_sizeof_char_ptr)
- {
- case 1: sql_type= FIELD_TYPE_TINY_BLOB; break;
- case 2: sql_type= FIELD_TYPE_BLOB; break;
- case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
- default: sql_type= FIELD_TYPE_LONG_BLOB; break;
- }
- length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; // QQ: Probably not needed
- break;
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
- length=(length+charset->mbmaxlen-1)/charset->mbmaxlen;
- break;
- default:
- break;
- }
-
- decimals= old_field->decimals();
- if (sql_type == FIELD_TYPE_STRING)
- {
+ switch (sql_type) {
+ case FIELD_TYPE_BLOB:
+ switch (pack_length - portable_sizeof_char_ptr) {
+ case 1: sql_type= FIELD_TYPE_TINY_BLOB; break;
+ case 2: sql_type= FIELD_TYPE_BLOB; break;
+ case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
+ default: sql_type= FIELD_TYPE_LONG_BLOB; break;
+ }
+ length=(length+charset->mbmaxlen-1) / charset->mbmaxlen;
+ key_length/= charset->mbmaxlen;
+ break;
+ case MYSQL_TYPE_STRING:
/* Change CHAR -> VARCHAR if dynamic record length */
- sql_type=old_field->type();
- decimals=0;
+ if (old_field->type() == MYSQL_TYPE_VAR_STRING)
+ sql_type= MYSQL_TYPE_VARCHAR;
+ /* fall through */
+
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ /* This is corrected in create_length_to_internal_length */
+ length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
+ break;
+#ifdef HAVE_SPATIAL
+ case FIELD_TYPE_GEOMETRY:
+ geom_type= ((Field_geom*)old_field)->geom_type;
+ break;
+#endif
+ case FIELD_TYPE_BIT:
+ length= (old_field->key_type() == HA_KEYTYPE_BIT) ?
+ ((Field_bit *) old_field)->bit_len + length * 8 :
+ ((Field_bit_as_char *) old_field)->create_length;
+ break;
+ default:
+ break;
}
+
if (flags & (ENUM_FLAG | SET_FLAG))
interval= ((Field_enum*) old_field)->typelib;
else
interval=0;
def=0;
- if (!old_field->is_real_null() && ! (flags & BLOB_FLAG) &&
- old_field->ptr && orig_field)
+
+ if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) &&
+ old_field->ptr && orig_field &&
+ (sql_type != FIELD_TYPE_TIMESTAMP || /* set def only if */
+ old_field->table->timestamp_field != old_field || /* timestamp field */
+ unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */
{
char buff[MAX_FIELD_WIDTH],*pos;
- String tmp(buff,sizeof(buff), charset);
+ String tmp(buff,sizeof(buff), charset), *res;
+ my_ptrdiff_t diff;
/* Get the value from default_values */
- my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2);
+ diff= (my_ptrdiff_t) (orig_field->table->s->default_values-
+ orig_field->table->record[0]);
orig_field->move_field(diff); // Points now at default_values
bool is_null=orig_field->is_real_null();
- orig_field->val_str(&tmp);
+ res= orig_field->val_str(&tmp);
orig_field->move_field(-diff); // Back to record[0]
if (!is_null)
{
- pos= (char*) sql_memdup(tmp.ptr(),tmp.length()+1);
- pos[tmp.length()]=0;
- def= new Item_string(pos, tmp.length(), charset);
+ pos= (char*) sql_strmake(res->ptr(), res->length());
+ def= new Item_string(pos, res->length(), charset);
}
}
-#ifdef HAVE_SPATIAL
- if (sql_type == FIELD_TYPE_GEOMETRY)
+}
+
+
+/*
+ maximum possible display length for blob
+
+ SYNOPSIS
+ Field_blob::max_length()
+
+ RETURN
+ length
+*/
+uint32 Field_blob::max_length()
+{
+ switch (packlength)
{
- geom_type= ((Field_geom*)old_field)->geom_type;
+ 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;
}
-#endif
}
-/* Warning handling */
+/*****************************************************************************
+ Warning handling
+*****************************************************************************/
/*
Produce warning or note about data saved into field
- SYNOPSYS
+ SYNOPSIS
set_warning()
level - level of message (Note/Warning/Error)
code - error code of message to be produced
@@ -6821,18 +8590,20 @@ create_field::create_field(Field *old_field,Field *orig_field)
if count_cuted_fields == FIELD_CHECK_IGNORE for current thread.
RETURN VALUE
- true - if count_cuted_fields == FIELD_CHECK_IGNORE
- false - otherwise
+ 1 if count_cuted_fields == FIELD_CHECK_IGNORE
+ 0 otherwise
*/
+
bool
-Field::set_warning(const uint level, const uint code, int cuted_increment)
+Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code,
+ int cuted_increment)
{
THD *thd= table->in_use;
if (thd->count_cuted_fields)
{
thd->cuted_fields+= cuted_increment;
- push_warning_printf(thd, (MYSQL_ERROR::enum_warning_level) level,
- code, ER(code), field_name, thd->row_count);
+ push_warning_printf(thd, level, code, ER(code), field_name,
+ thd->row_count);
return 0;
}
return 1;
@@ -6842,8 +8613,8 @@ Field::set_warning(const uint level, const uint code, int cuted_increment)
/*
Produce warning or note about datetime string data saved into field
- SYNOPSYS
- set_warning()
+ SYNOPSIS
+ set_datime_warning()
level - level of message (Note/Warning/Error)
code - error code of message to be produced
str - string value which we tried to save
@@ -6856,20 +8627,23 @@ Field::set_warning(const uint level, const uint code, int cuted_increment)
fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current
thread.
*/
+
void
-Field::set_datetime_warning(const uint level, const uint code,
+Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, 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);
+ if (table->in_use->really_abort_on_warning() ||
+ set_warning(level, code, cuted_increment))
+ make_truncated_value_warning(table->in_use, str, str_length, ts_type,
+ field_name);
}
/*
Produce warning or note about integer datetime value saved into field
- SYNOPSYS
+ SYNOPSIS
set_warning()
level - level of message (Note/Warning/Error)
code - error code of message to be produced
@@ -6882,17 +8656,20 @@ Field::set_datetime_warning(const uint level, const uint code,
fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current
thread.
*/
+
void
-Field::set_datetime_warning(const uint level, const uint code,
+Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code,
longlong nr, timestamp_type ts_type,
int cuted_increment)
{
- if (set_warning(level, code, cuted_increment))
+ if (table->in_use->really_abort_on_warning() ||
+ 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);
+ make_truncated_value_warning(table->in_use, str_nr,
+ (uint) (str_end - str_nr),
+ ts_type, field_name);
}
}
@@ -6900,7 +8677,7 @@ Field::set_datetime_warning(const uint level, const uint code,
/*
Produce warning or note about double datetime data saved into field
- SYNOPSYS
+ SYNOPSIS
set_warning()
level - level of message (Note/Warning/Error)
code - error code of message to be produced
@@ -6912,42 +8689,18 @@ Field::set_datetime_warning(const uint level, const uint code,
fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current
thread.
*/
+
void
-Field::set_datetime_warning(const uint level, const uint code,
+Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code,
double nr, timestamp_type ts_type)
{
- if (set_warning(level, code, 1))
+ if (table->in_use->really_abort_on_warning() ||
+ 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;
+ make_truncated_value_warning(table->in_use, str_nr, str_len, ts_type,
+ field_name);
}
}
diff --git a/sql/field.h b/sql/field.h
index ba963418c7a..632169868bc 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -49,11 +49,7 @@ class Field
void operator=(Field &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
- static void operator delete(void *ptr_arg, size_t size) {
-#ifdef SAFEMALLOC
- bfill(ptr_arg, size, 0x8F);
-#endif
- }
+ static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); }
char *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
@@ -63,9 +59,9 @@ public:
*/
struct st_table *table; // Pointer for table
struct st_table *orig_table; // Pointer to original table
- const char *table_name,*field_name;
+ const char **table_name, *field_name;
LEX_STRING comment;
- ulong query_id; // For quick test of used fields
+ query_id_t query_id; // For quick test of used fields
/* Field is part of the following keys */
key_map key_start,part_of_key,part_of_sortkey;
/*
@@ -90,6 +86,7 @@ public:
utype unireg_check;
uint32 field_length; // Length of field
+ uint field_index; // field number in fields array
uint16 flags;
uchar null_bit; // Bit used to test null bit
@@ -100,10 +97,12 @@ public:
/* Store functions returns 1 on overflow and -1 on fatal error */
virtual int store(const char *to,uint length,CHARSET_INFO *cs)=0;
virtual int store(double nr)=0;
- virtual int store(longlong nr)=0;
- virtual void store_time(TIME *ltime,timestamp_type t_type);
+ virtual int store(longlong nr, bool unsigned_val)=0;
+ virtual int store_decimal(const my_decimal *d)=0;
+ virtual int store_time(TIME *ltime, timestamp_type t_type);
virtual double val_real(void)=0;
virtual longlong val_int(void)=0;
+ virtual my_decimal *val_decimal(my_decimal *);
inline String *val_str(String *str) { return val_str(str, str); }
/*
val_str(buf1, buf2) gets two buffers and should use them as follows:
@@ -118,19 +117,26 @@ public:
This trickery is used to decrease a number of malloc calls.
*/
virtual String *val_str(String*,String *)=0;
+ String *val_int_as_str(String *val_buffer, my_bool unsigned_flag);
virtual Item_result result_type () const=0;
virtual Item_result cmp_type () const { return result_type(); }
virtual Item_result cast_to_int_type () const { return result_type(); }
+ static bool type_can_have_key_part(enum_field_types);
static enum_field_types field_type_merge(enum_field_types, enum_field_types);
static Item_result result_merge_type(enum_field_types);
- bool eq(Field *field) { return ptr == field->ptr && null_ptr == field->null_ptr; }
+ bool eq(Field *field)
+ {
+ return (ptr == field->ptr && null_ptr == field->null_ptr &&
+ null_bit == field->null_bit);
+ }
virtual bool eq_def(Field *field);
virtual uint32 pack_length() const { return (uint32) field_length; }
+ virtual uint32 pack_length_in_rec() const { return pack_length(); }
virtual void reset(void) { bzero(ptr,pack_length()); }
virtual void reset_fields() {}
virtual void set_default()
{
- my_ptrdiff_t offset = (my_ptrdiff_t) (table->default_values -
+ my_ptrdiff_t offset = (my_ptrdiff_t) (table->s->default_values -
table->record[0]);
memcpy(ptr, ptr + offset, pack_length());
if (null_ptr)
@@ -147,10 +153,9 @@ public:
virtual int cmp(const char *,const char *)=0;
virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L)
{ return memcmp(a,b,pack_length()); }
- virtual int cmp_offset(uint row_offset)
- { return memcmp(ptr,ptr+row_offset,pack_length()); }
- virtual int cmp_binary_offset(uint row_offset)
- { return memcmp(ptr,ptr+row_offset,pack_length()); }
+ int cmp_offset(uint row_offset) { return cmp(ptr,ptr+row_offset); }
+ int cmp_binary_offset(uint row_offset)
+ { return cmp_binary(ptr, ptr+row_offset); };
virtual int key_cmp(const byte *a,const byte *b)
{ return cmp((char*) a,(char*) b); }
virtual int key_cmp(const byte *str, uint length)
@@ -180,7 +185,7 @@ public:
{ if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; }
inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; }
inline bool real_maybe_null(void) { return null_ptr != 0; }
- virtual void make_field(Send_field *)=0;
+ virtual void make_field(Send_field *);
virtual void sort_string(char *buff,uint length)=0;
virtual bool optimize_range(uint idx, uint part);
/*
@@ -192,27 +197,10 @@ public:
*/
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
- Field *new_field(MEM_ROOT *root, struct st_table *new_table)
- {
- Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
- if (tmp)
- {
- if (tmp->table->maybe_null)
- tmp->flags&= ~NOT_NULL_FLAG;
- tmp->table= new_table;
- tmp->key_start.init(0);
- tmp->part_of_key.init(0);
- tmp->part_of_sortkey.init(0);
- tmp->unireg_check=Field::NONE;
- tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
- ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
-#ifdef PROBABLY_WRONG
- tmp->table_name= new_table->table_name;
-#endif
- tmp->reset_fields();
- }
- return tmp;
- }
+ virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table);
+ virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ char *new_ptr, uchar *new_null_ptr,
+ uint new_null_bit);
inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
@@ -228,11 +216,10 @@ public:
{ memcpy(buff,ptr,length); }
inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
{ memcpy(ptr,buff,length); }
- virtual void get_key_image(char *buff,uint length, CHARSET_INFO *cs,
- imagetype type)
- { get_image(buff,length,cs); }
- virtual void set_key_image(char *buff,uint length, CHARSET_INFO *cs)
- { set_image(buff,length,cs); }
+ virtual void get_key_image(char *buff, uint length, imagetype type)
+ { get_image(buff,length, &my_charset_bin); }
+ virtual void set_key_image(char *buff,uint length)
+ { set_image(buff,length, &my_charset_bin); }
inline longlong val_int_offset(uint row_offset)
{
ptr+=row_offset;
@@ -240,6 +227,17 @@ public:
ptr-=row_offset;
return tmp;
}
+
+ inline String *val_str(String *str, char *new_ptr)
+ {
+ char *old_ptr= ptr;
+ ptr= new_ptr;
+ val_str(str);
+ ptr= old_ptr;
+ return str;
+ }
+ bool quote_data(String *unquoted_string);
+ bool needs_quotes(void);
virtual bool send_binary(Protocol *protocol);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{
@@ -271,9 +269,11 @@ public:
virtual uint max_packed_col_length(uint max_length)
{ return max_length;}
- virtual int pack_cmp(const char *a,const char *b, uint key_length_arg)
+ virtual int pack_cmp(const char *a,const char *b, uint key_length_arg,
+ my_bool insert_or_update)
{ return cmp(a,b); }
- virtual int pack_cmp(const char *b, uint key_length_arg)
+ virtual int pack_cmp(const char *b, uint key_length_arg,
+ my_bool insert_or_update)
{ return cmp(ptr,b); }
uint offset(); // Should be inline ...
void copy_from_tmp(int offset);
@@ -284,18 +284,28 @@ public:
virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
virtual bool has_charset(void) const { return FALSE; }
virtual void set_charset(CHARSET_INFO *charset) { }
- bool set_warning(const unsigned int level, const unsigned int code,
+ bool set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code,
int cuted_increment);
- void set_datetime_warning(const uint level, const uint code,
+ bool check_int(const char *str, int length, const char *int_end,
+ CHARSET_INFO *cs);
+ void set_datetime_warning(MYSQL_ERROR::enum_warning_level, 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,
+ void set_datetime_warning(MYSQL_ERROR::enum_warning_level, uint code,
longlong nr, timestamp_type ts_type,
int cuted_increment);
- void set_datetime_warning(const uint level, const uint code,
+ void set_datetime_warning(MYSQL_ERROR::enum_warning_level, const uint code,
double nr, timestamp_type ts_type);
+ inline bool check_overflow(int op_result)
+ {
+ return (op_result == E_DEC_OVERFLOW);
+ }
+ int warn_if_overflow(int op_result);
/* maximum possible display length */
virtual uint32 max_length()= 0;
+ /* convert decimal to longlong with overflow check */
+ longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
+ int *err);
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);
@@ -322,16 +332,7 @@ public:
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg,
- uint8 dec_arg,bool zero_arg,bool unsigned_arg)
- :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg),
- dec(dec_arg),zerofill(zero_arg),unsigned_flag(unsigned_arg)
- {
- if (zerofill)
- flags|=ZEROFILL_FLAG;
- if (unsigned_flag)
- flags|=UNSIGNED_FLAG;
- }
+ uint8 dec_arg, bool zero_arg, bool unsigned_arg);
Item_result result_type () const { return REAL_RESULT; }
void prepend_zeros(String *value);
void add_zerofill_and_unsigned(String &res) const;
@@ -340,6 +341,8 @@ public:
uint decimals() const { return (uint) dec; }
uint size_of() const { return sizeof(*this); }
bool eq_def(Field *field);
+ int store_decimal(const my_decimal *);
+ my_decimal *val_decimal(my_decimal *);
};
@@ -350,39 +353,68 @@ public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
- struct st_table *table_arg,CHARSET_INFO *charset)
- :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg)
- {
- field_charset=charset;
- if (charset->state & MY_CS_BINSORT)
- flags|=BINARY_FLAG;
- }
+ struct st_table *table_arg, CHARSET_INFO *charset);
Item_result result_type () const { return STRING_RESULT; }
uint decimals() const { return NOT_FIXED_DEC; }
int store(double nr);
- int store(longlong nr)=0;
+ int store(longlong nr, bool unsigned_val)=0;
+ int store_decimal(const my_decimal *);
int store(const char *to,uint length,CHARSET_INFO *cs)=0;
- void make_field(Send_field *);
uint size_of() const { return sizeof(*this); }
CHARSET_INFO *charset(void) const { return field_charset; }
void set_charset(CHARSET_INFO *charset) { field_charset=charset; }
bool binary() const { return field_charset == &my_charset_bin; }
uint32 max_length() { return field_length; }
friend class create_field;
+ my_decimal *val_decimal(my_decimal *);
};
-class Field_decimal :public Field_num {
+/* base class for Field_string, Field_varstring and Field_blob */
+
+class Field_longstr :public Field_str
+{
+public:
+ Field_longstr(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg,CHARSET_INFO *charset)
+ :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
+ field_name_arg, table_arg, charset)
+ {}
+
+ int store_decimal(const my_decimal *d);
+};
+
+/* base class for float and double and decimal (old one) */
+class Field_real :public Field_num {
+public:
+
+ Field_real(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg,
+ uint8 dec_arg, bool zero_arg, bool unsigned_arg)
+ :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
+ field_name_arg, table_arg, dec_arg, zero_arg, unsigned_arg)
+ {}
+
+
+ int store_decimal(const my_decimal *);
+ my_decimal *val_decimal(my_decimal *);
+};
+
+
+class Field_decimal :public Field_real {
public:
Field_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
uint8 dec_arg,bool zero_arg,bool unsigned_arg)
- :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg,
- dec_arg, zero_arg,unsigned_arg)
+ :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg,
+ dec_arg, zero_arg, unsigned_arg)
{}
enum_field_types type() const { return FIELD_TYPE_DECIMAL;}
enum ha_base_keytype key_type() const
@@ -390,7 +422,7 @@ public:
void reset(void);
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -403,6 +435,51 @@ public:
};
+/* New decimal/numeric field which use fixed point arithmetic */
+class Field_new_decimal :public Field_num {
+public:
+ /* The maximum number of decimal digits can be stored */
+ uint precision;
+ uint bin_size;
+ /*
+ Constructors take max_length of the field as a parameter - not the
+ precision as the number of decimal digits allowed.
+ So for example we need to count length from precision handling
+ CREATE TABLE ( DECIMAL(x,y))
+ */
+ Field_new_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ struct st_table *table_arg,
+ uint8 dec_arg, bool zero_arg, bool unsigned_arg);
+ Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg, uint8 dec_arg,
+ bool unsigned_arg);
+ enum_field_types type() const { return FIELD_TYPE_NEWDECIMAL;}
+ enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
+ Item_result result_type () const { return DECIMAL_RESULT; }
+ void reset(void);
+ bool store_value(const my_decimal *decimal_value);
+ void set_value_on_overflow(my_decimal *decimal_value, bool sign);
+ int store(const char *to, uint length, CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int store_decimal(const my_decimal *);
+ double val_real(void);
+ longlong val_int(void);
+ my_decimal *val_decimal(my_decimal *);
+ String *val_str(String*, String *);
+ int cmp(const char *, const char*);
+ void sort_string(char *buff, uint length);
+ bool zero_pack() const { return 0; }
+ void sql_type(String &str) const;
+ uint32 max_length() { return field_length; }
+ uint size_of() const { return sizeof(*this); }
+ uint32 pack_length() const { return (uint32) bin_size; }
+};
+
+
class Field_tiny :public Field_num {
public:
Field_tiny(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
@@ -420,7 +497,7 @@ public:
{ return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { ptr[0]=0; }
double val_real(void);
longlong val_int(void);
@@ -456,7 +533,7 @@ public:
{ return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { ptr[0]=ptr[1]=0; }
double val_real(void);
longlong val_int(void);
@@ -487,7 +564,7 @@ public:
{ return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
double val_real(void);
longlong val_int(void);
@@ -523,7 +600,7 @@ public:
{ return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void);
longlong val_int(void);
@@ -561,7 +638,7 @@ public:
{ return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; }
double val_real(void);
longlong val_int(void);
@@ -576,27 +653,28 @@ public:
};
#endif
-class Field_float :public Field_num {
+
+class Field_float :public Field_real {
public:
Field_float(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint8 dec_arg,bool zero_arg,bool unsigned_arg)
- :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg,
- dec_arg, zero_arg,unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
+ :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg,
+ dec_arg, zero_arg, unsigned_arg)
{}
Field_float(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, uint8 dec_arg)
- :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
- NONE, field_name_arg, table_arg,dec_arg,0,0)
+ :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
+ NONE, field_name_arg, table_arg, dec_arg, 0, 0)
{}
enum_field_types type() const { return FIELD_TYPE_FLOAT;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { bzero(ptr,sizeof(float)); }
double val_real(void);
longlong val_int(void);
@@ -610,27 +688,27 @@ public:
};
-class Field_double :public Field_num {
+class Field_double :public Field_real {
public:
Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
uint8 dec_arg,bool zero_arg,bool unsigned_arg)
- :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg,
- dec_arg, zero_arg,unsigned_arg)
+ :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg,
+ dec_arg, zero_arg, unsigned_arg)
{}
Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, uint8 dec_arg)
- :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
- NONE, field_name_arg, table_arg,dec_arg,0,0)
+ :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
+ NONE, field_name_arg, table_arg, dec_arg, 0, 0)
{}
enum_field_types type() const { return FIELD_TYPE_DOUBLE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { bzero(ptr,sizeof(double)); }
double val_real(void);
longlong val_int(void);
@@ -644,7 +722,7 @@ public:
};
-/* Everything saved in this will disapper. It will always return NULL */
+/* Everything saved in this will disappear. It will always return NULL */
class Field_null :public Field_str {
static uchar null[1];
@@ -659,10 +737,12 @@ public:
int store(const char *to, uint length, CHARSET_INFO *cs)
{ null[0]=1; return 0; }
int store(double nr) { null[0]=1; return 0; }
- int store(longlong nr) { null[0]=1; return 0; }
+ int store(longlong nr, bool unsigned_val) { null[0]=1; return 0; }
+ int store_decimal(const my_decimal *d) { null[0]=1; return 0; }
void reset(void) {}
double val_real(void) { return 0.0;}
longlong val_int(void) { return 0;}
+ my_decimal *val_decimal(my_decimal *) { return 0; }
String *val_str(String *value,String *value2)
{ value2->length(0); return value2;}
int cmp(const char *a, const char *b) { return 0;}
@@ -686,7 +766,7 @@ public:
enum Item_result cmp_type () const { return INT_RESULT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void);
longlong val_int(void);
@@ -713,7 +793,7 @@ public:
if ((*null_value= is_null()))
return 0;
#ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
+ if (table->s->db_low_byte_first)
return sint4korr(ptr);
#endif
long tmp;
@@ -738,7 +818,7 @@ public:
enum_field_types type() const { return FIELD_TYPE_YEAR;}
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -765,7 +845,7 @@ public:
enum Item_result cmp_type () const { return INT_RESULT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void);
longlong val_int(void);
@@ -793,8 +873,8 @@ public:
enum Item_result cmp_type () const { return INT_RESULT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
- void store_time(TIME *ltime,timestamp_type type);
+ int store(longlong nr, bool unsigned_val);
+ int store_time(TIME *ltime, timestamp_type type);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
double val_real(void);
longlong val_int(void);
@@ -826,9 +906,10 @@ public:
enum_field_types type() const { return FIELD_TYPE_TIME;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
enum Item_result cmp_type () const { return INT_RESULT; }
+ int store_time(TIME *ltime, timestamp_type type);
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
double val_real(void);
longlong val_int(void);
@@ -865,8 +946,8 @@ public:
uint decimals() const { return DATETIME_DEC; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
- void store_time(TIME *ltime,timestamp_type type);
+ int store(longlong nr, bool unsigned_val);
+ int store_time(TIME *ltime, timestamp_type type);
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; }
double val_real(void);
longlong val_int(void);
@@ -883,100 +964,127 @@ public:
};
-class Field_string :public Field_str {
+class Field_string :public Field_longstr {
public:
Field_string(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs)
- :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg,cs) {};
+ :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg, cs) {};
Field_string(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg, CHARSET_INFO *cs)
- :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg, cs) {};
+ struct st_table *table_arg, CHARSET_INFO *cs)
+ :Field_longstr((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
+ NONE, field_name_arg, table_arg, cs) {};
enum_field_types type() const
{
- return ((table && table->db_create_options & HA_OPTION_PACK_RECORD &&
- field_length >= 4) ?
- FIELD_TYPE_VAR_STRING : FIELD_TYPE_STRING);
+ return ((orig_table &&
+ orig_table->s->db_create_options & HA_OPTION_PACK_RECORD &&
+ field_length >= 4) &&
+ orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR ?
+ MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING);
}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
bool zero_pack() const { return 0; }
void reset(void) { charset()->cset->fill(charset(),ptr,field_length,' '); }
int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ my_decimal *val_decimal(my_decimal *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from);
- int pack_cmp(const char *a,const char *b,uint key_length);
- int pack_cmp(const char *b,uint key_length);
+ int pack_cmp(const char *a,const char *b,uint key_length,
+ my_bool insert_or_update);
+ int pack_cmp(const char *b,uint key_length,my_bool insert_or_update);
uint packed_col_length(const char *to, uint length);
uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return FIELD_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table);
};
-class Field_varstring :public Field_str {
+class Field_varstring :public Field_longstr {
public:
- Field_varstring(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
+ /* Store number of bytes used to store length (1 or 2) */
+ uint32 length_bytes;
+ Field_varstring(char *ptr_arg,
+ uint32 len_arg, uint length_bytes_arg,
+ uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs)
- :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg, cs)
- {}
+ :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg, cs),
+ length_bytes(length_bytes_arg)
+ {
+ if (table)
+ table->s->varchar_fields++;
+ }
Field_varstring(uint32 len_arg,bool maybe_null_arg,
- const char *field_name_arg,
- struct st_table *table_arg, CHARSET_INFO *cs)
- :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg, cs)
- {}
+ const char *field_name_arg,
+ struct st_table *table_arg, CHARSET_INFO *cs)
+ :Field_longstr((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
+ NONE, field_name_arg, table_arg, cs),
+ length_bytes(len_arg < 256 ? 1 :2)
+ {
+ if (table)
+ table->s->varchar_fields++;
+ }
- enum_field_types type() const { return FIELD_TYPE_VAR_STRING; }
- enum ha_base_keytype key_type() const
- { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
+ enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
+ enum ha_base_keytype key_type() const;
bool zero_pack() const { return 0; }
- void reset(void) { bzero(ptr,field_length+2); }
- uint32 pack_length() const { return (uint32) field_length+2; }
+ void reset(void) { bzero(ptr,field_length+length_bytes); }
+ uint32 pack_length() const { return (uint32) field_length+length_bytes; }
uint32 key_length() const { return (uint32) field_length; }
int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ my_decimal *val_decimal(my_decimal *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
- void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
- void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+ void get_key_image(char *buff,uint length, imagetype type);
+ void set_key_image(char *buff,uint length);
void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
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(char* to, const char *from);
- int pack_cmp(const char *a, const char *b, uint key_length);
- int pack_cmp(const char *b, uint key_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,
+ my_bool insert_or_update);
+ int pack_cmp(const char *b, uint key_length,my_bool insert_or_update);
+ int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
+ int key_cmp(const byte *,const byte*);
+ int key_cmp(const byte *str, uint length);
uint packed_col_length(const char *to, uint length);
uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); }
- enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; }
+ enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table);
+ Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ char *new_ptr, uchar *new_null_ptr,
+ uint new_null_bit);
};
-class Field_blob :public Field_str {
+class Field_blob :public Field_longstr {
protected:
uint packlength;
String value; // For temporaries
@@ -987,32 +1095,31 @@ public:
CHARSET_INFO *cs);
Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs)
- :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg, cs),
+ :Field_longstr((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
+ NONE, field_name_arg, table_arg, cs),
packlength(4)
{
flags|= BLOB_FLAG;
}
enum_field_types type() const { return FIELD_TYPE_BLOB;}
enum ha_base_keytype key_type() const
- { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
+ { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
+ my_decimal *val_decimal(my_decimal *);
int cmp(const char *,const char*);
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
- int cmp_offset(uint offset);
int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
- int cmp_binary_offset(uint row_offset);
int key_cmp(const byte *,const byte*);
int key_cmp(const byte *str, uint length);
uint32 key_length() const { return 0; }
void sort_string(char *buff,uint length);
uint32 pack_length() const
- { return (uint32) (packlength+table->blob_ptr_size); }
+ { return (uint32) (packlength+table->s->blob_ptr_size); }
inline uint32 max_data_length() const
{
return (uint32) (((ulonglong) 1 << (packlength*8)) -1);
@@ -1038,8 +1145,8 @@ public:
store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
}
- void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
- void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+ void get_key_image(char *buff,uint length, imagetype type);
+ void set_key_image(char *buff,uint length);
void sql_type(String &str) const;
inline bool copy()
{ char *tmp;
@@ -1053,12 +1160,13 @@ public:
return 0;
}
char *pack(char *to, const char *from, uint max_length= ~(uint) 0);
- 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(char *to, const char *from);
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);
+ int pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update);
+ int pack_cmp(const char *b, uint key_length,my_bool insert_or_update);
uint packed_col_length(const char *col_ptr, uint length);
uint max_packed_col_length(uint max_length);
void free() { value.free(); }
@@ -1070,6 +1178,7 @@ public:
uint32 max_length();
};
+
#ifdef HAVE_SPATIAL
class Field_geom :public Field_blob {
public:
@@ -1087,18 +1196,19 @@ public:
:Field_blob(len_arg, maybe_null_arg, field_name_arg,
table_arg, &my_charset_bin)
{ geom_type= geom_type_arg; }
- enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; }
+ enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
enum_field_types type() const { return FIELD_TYPE_GEOMETRY; }
void sql_type(String &str) const;
int store(const char *to, uint length, CHARSET_INFO *charset);
- int store(double nr) { return 1; }
- int store(longlong nr) { return 1; }
-
- void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
- void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int store_decimal(const my_decimal *);
+ void get_key_image(char *buff,uint length,imagetype type);
+ uint size_of() const { return sizeof(*this); }
};
#endif /*HAVE_SPATIAL*/
+
class Field_enum :public Field_str {
protected:
uint packlength;
@@ -1122,7 +1232,7 @@ public:
enum ha_base_keytype key_type() const;
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
- int store(longlong nr);
+ int store(longlong nr, bool unsigned_val);
void reset() { bzero(ptr,packlength); }
double val_real(void);
longlong val_int(void);
@@ -1158,8 +1268,8 @@ public:
flags=(flags & ~ENUM_FLAG) | SET_FLAG;
}
int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr) { return Field_set::store((longlong) nr); }
- int store(longlong nr);
+ int store(double nr) { return Field_set::store((longlong) nr, FALSE); }
+ int store(longlong nr, bool unsigned_val);
virtual bool zero_pack() const { return 1; }
String *val_str(String*,String *);
void sql_type(String &str) const;
@@ -1168,11 +1278,82 @@ public:
};
+class Field_bit :public Field {
+public:
+ uchar *bit_ptr; // position in record where 'uneven' bits store
+ uchar bit_ofs; // offset to 'uneven' high bits
+ uint bit_len; // number of 'uneven' high bits
+ Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ struct st_table *table_arg);
+ enum_field_types type() const { return FIELD_TYPE_BIT; }
+ enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
+ uint32 key_length() const { return (uint32) field_length + (bit_len > 0); }
+ uint32 max_length() { return (uint32) field_length * 8 + bit_len; }
+ uint size_of() const { return sizeof(*this); }
+ Item_result result_type () const { return INT_RESULT; }
+ void reset(void) { bzero(ptr, field_length); }
+ int store(const char *to, uint length, CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int store_decimal(const my_decimal *);
+ double val_real(void);
+ longlong val_int(void);
+ String *val_str(String*, String *);
+ my_decimal *val_decimal(my_decimal *);
+ int cmp(const char *a, const char *b)
+ { return cmp_binary(a, b); }
+ int key_cmp(const byte *a, const byte *b)
+ { return cmp_binary((char *) a, (char *) b); }
+ int key_cmp(const byte *str, uint length);
+ int cmp_offset(uint row_offset);
+ void get_key_image(char *buff, uint length, imagetype type);
+ void set_key_image(char *buff, uint length)
+ { Field_bit::store(buff, length, &my_charset_bin); }
+ void sort_string(char *buff, uint length)
+ { get_key_image(buff, length, itRAW); }
+ uint32 pack_length() const
+ { return (uint32) field_length + (bit_len > 0); }
+ uint32 pack_length_in_rec() const { return field_length; }
+ void sql_type(String &str) const;
+ char *pack(char *to, const char *from, uint max_length=~(uint) 0);
+ const char *unpack(char* to, const char *from);
+ Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ char *new_ptr, uchar *new_null_ptr,
+ uint new_null_bit);
+ void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg)
+ {
+ bit_ptr= bit_ptr_arg;
+ bit_ofs= bit_ofs_arg;
+ }
+};
+
+
+class Field_bit_as_char: public Field_bit {
+public:
+ uchar create_length;
+ Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ struct st_table *table_arg);
+ enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
+ uint32 max_length() { return (uint32) create_length; }
+ uint size_of() const { return sizeof(*this); }
+ int store(const char *to, uint length, CHARSET_INFO *charset);
+ int store(double nr) { return Field_bit::store(nr); }
+ int store(longlong nr, bool unsigned_val)
+ { return Field_bit::store(nr, unsigned_val); }
+ void sql_type(String &str) const;
+};
+
+
/*
Create field class for CREATE TABLE
*/
-class create_field :public Sql_alloc {
+class create_field :public Sql_alloc
+{
public:
const char *field_name;
const char *change; // If done with alter table
@@ -1180,8 +1361,8 @@ public:
LEX_STRING comment; // Comment for field
Item *def; // Default value
enum enum_field_types sql_type;
- uint32 length;
- uint decimals,flags,pack_length;
+ ulong length;
+ uint decimals, flags, pack_length, key_length;
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
List<String> interval_list;
@@ -1194,6 +1375,11 @@ public:
create_field() :after(0) {}
create_field(Field *field, Field *orig_field);
void create_length_to_internal_length(void);
+
+ /* Init for a tmp table field. To be extended if need be. */
+ void init_for_tmp_table(enum_field_types sql_type_arg,
+ uint32 max_length, uint32 decimals,
+ bool maybe_null, bool is_unsigned);
};
@@ -1246,11 +1432,10 @@ Field *make_field(char *ptr, uint32 field_length,
TYPELIB *interval, const char *field_name,
struct st_table *table);
uint pack_length_to_packflag(uint type);
+enum_field_types get_blob_type_from_length(ulong length);
uint32 calc_pack_length(enum_field_types type,uint32 length);
int set_field_to_null(Field *field);
int set_field_to_null_with_conversions(Field *field, bool no_conversions);
-bool test_if_int(const char *str, int length, const char *int_end,
- CHARSET_INFO *cs);
/*
The following are for the interface with the .frm file
@@ -1266,9 +1451,12 @@ bool test_if_int(const char *str, int length, const char *int_end,
#define FIELDFLAG_BLOB 1024 // mangled with decimals!
#define FIELDFLAG_GEOM 2048 // mangled with decimals!
+#define FIELDFLAG_TREAT_BIT_AS_CHAR 4096 /* use Field_bit_as_char */
+
#define FIELDFLAG_LEFT_FULLSCREEN 8192
#define FIELDFLAG_RIGHT_FULLSCREEN 16384
#define FIELDFLAG_FORMAT_NUMBER 16384 // predit: ###,,## in output
+#define FIELDFLAG_NO_DEFAULT 16384 /* sql */
#define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag
#define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql
#define FIELDFLAG_PACK_SHIFT 3
@@ -1277,8 +1465,6 @@ bool test_if_int(const char *str, int length, const char *int_end,
#define FIELDFLAG_NUM_SCREEN_TYPE 0x7F01
#define FIELDFLAG_ALFA_SCREEN_TYPE 0x7800
-#define FIELD_SORT_REVERSE 16384
-
#define MTYP_TYPENR(type) (type & 127) /* Remove bits from type */
#define f_is_dec(x) ((x) & FIELDFLAG_DECIMAL)
@@ -1296,3 +1482,5 @@ bool test_if_int(const char *str, int length, const char *int_end,
#define f_is_equ(x) ((x) & (1+2+FIELDFLAG_PACK+31*256))
#define f_settype(x) (((int) x) << FIELDFLAG_PACK_SHIFT)
#define f_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL)
+#define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT)
+#define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 7998dd6d5f8..bbe2dbe5e9f 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -121,13 +121,11 @@ 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, 1);
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
return 0;
}
if (!current_thd->no_errors)
- my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
- field->field_name);
+ my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
return -1;
}
@@ -185,8 +183,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
return 0;
}
if (!current_thd->no_errors)
- my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
- field->field_name);
+ my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
return -1;
}
@@ -232,7 +229,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, 1);
+ WARN_DATA_TRUNCATED, 1);
copy->to_field->reset();
}
else
@@ -307,14 +304,16 @@ static void do_field_string(Copy_field *copy)
char buff[MAX_FIELD_WIDTH];
copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
copy->from_field->val_str(&copy->tmp);
- copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),copy->tmp.charset());
+ copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),
+ copy->tmp.charset());
}
static void do_field_int(Copy_field *copy)
{
- longlong value=copy->from_field->val_int();
- copy->to_field->store(value);
+ longlong value= copy->from_field->val_int();
+ copy->to_field->store(value,
+ test(copy->from_field->flags & UNSIGNED_FLAG));
}
static void do_field_real(Copy_field *copy)
@@ -341,7 +340,7 @@ static void do_cut_string(Copy_field *copy)
MY_SEQ_SPACES) < copy->from_length - copy->to_length)
{
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, 1);
+ WARN_DATA_TRUNCATED, 1);
}
}
@@ -369,7 +368,7 @@ static void do_cut_string_complex(Copy_field *copy)
MY_SEQ_SPACES) < (copy->from_length - copy_length))
{
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, 1);
+ WARN_DATA_TRUNCATED, 1);
}
if (copy_length < copy->to_length)
@@ -388,18 +387,35 @@ static void do_expand_string(Copy_field *copy)
copy->to_length-copy->from_length, ' ');
}
-static void do_varstring(Copy_field *copy)
+
+static void do_varstring1(Copy_field *copy)
+{
+ uint length= (uint) *(uchar*) copy->from_ptr;
+ if (length > copy->to_length- 1)
+ {
+ length=copy->to_length - 1;
+ if (current_thd->count_cuted_fields)
+ copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_DATA_TRUNCATED, 1);
+ }
+ *(uchar*) copy->to_ptr= (uchar) length;
+ memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
+}
+
+
+static void do_varstring2(Copy_field *copy)
{
uint length=uint2korr(copy->from_ptr);
- if (length > copy->to_length-2)
+ if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
{
- length=copy->to_length-2;
+ length=copy->to_length-HA_KEY_BLOB_LENGTH;
if (current_thd->count_cuted_fields)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, 1);
+ WARN_DATA_TRUNCATED, 1);
}
int2store(copy->to_ptr,length);
- memcpy(copy->to_ptr+2, copy->from_ptr,length);
+ memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
+ length);
}
/***************************************************************************
@@ -507,26 +523,38 @@ void Copy_field::set(Field *to,Field *from,bool save)
void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
{
+ bool compatible_db_low_byte_first= (to->table->s->db_low_byte_first ==
+ from->table->s->db_low_byte_first);
if (to->flags & BLOB_FLAG)
{
if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
return do_conv_blob;
- if (from_length != to_length ||
- to->table->db_low_byte_first != from->table->db_low_byte_first)
+ if (from_length != to_length || !compatible_db_low_byte_first)
{
// Correct pointer to point at char pointer
- to_ptr+=to_length - to->table->blob_ptr_size;
- from_ptr+=from_length- from->table->blob_ptr_size;
+ to_ptr+= to_length - to->table->s->blob_ptr_size;
+ from_ptr+= from_length- from->table->s->blob_ptr_size;
return do_copy_blob;
}
}
else
{
+ if (to->real_type() == FIELD_TYPE_BIT ||
+ from->real_type() == FIELD_TYPE_BIT)
+ return do_field_int;
// Check if identical fields
if (from->result_type() == STRING_RESULT)
{
+ /*
+ If we are copying date or datetime's we have to check the dates
+ if we don't allow 'all' dates.
+ */
if (to->real_type() != from->real_type() ||
- to->table->db_low_byte_first != from->table->db_low_byte_first)
+ !compatible_db_low_byte_first ||
+ ((to->table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) &&
+ to->type() == FIELD_TYPE_DATE ||
+ to->type() == FIELD_TYPE_DATETIME))
{
if (from->real_type() == FIELD_TYPE_ENUM ||
from->real_type() == FIELD_TYPE_SET)
@@ -542,9 +570,15 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
}
else if (to->charset() != from->charset())
return do_field_string;
- else if (to->real_type() == FIELD_TYPE_VAR_STRING && to_length !=
- from_length)
- return do_varstring;
+ else if (to->real_type() == MYSQL_TYPE_VARCHAR)
+ {
+ if (((Field_varstring*) to)->length_bytes !=
+ ((Field_varstring*) from)->length_bytes)
+ return do_field_string;
+ if (to_length != from_length)
+ return (((Field_varstring*) to)->length_bytes == 1 ?
+ do_varstring1 : do_varstring2);
+ }
else if (to_length < from_length)
return (from->charset()->mbmaxlen == 1 ?
do_cut_string : do_cut_string_complex);
@@ -553,7 +587,7 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
}
else if (to->real_type() != from->real_type() ||
to_length != from_length ||
- to->table->db_low_byte_first != from->table->db_low_byte_first)
+ !compatible_db_low_byte_first)
{
if (to->real_type() == FIELD_TYPE_DECIMAL ||
to->result_type() == STRING_RESULT)
@@ -564,8 +598,7 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
}
else
{
- if (!to->eq_def(from) ||
- to->table->db_low_byte_first != from->table->db_low_byte_first)
+ if (!to->eq_def(from) || !compatible_db_low_byte_first)
{
if (to->real_type() == FIELD_TYPE_DECIMAL)
return do_field_string;
@@ -599,10 +632,25 @@ void field_conv(Field *to,Field *from)
!(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) &&
to->real_type() != FIELD_TYPE_ENUM &&
to->real_type() != FIELD_TYPE_SET &&
+ to->real_type() != FIELD_TYPE_BIT &&
+ (to->real_type() != FIELD_TYPE_NEWDECIMAL ||
+ (to->field_length == from->field_length &&
+ (((Field_num*)to)->dec == ((Field_num*)from)->dec))) &&
from->charset() == to->charset() &&
- to->table->db_low_byte_first == from->table->db_low_byte_first)
+ to->table->s->db_low_byte_first == from->table->s->db_low_byte_first &&
+ (!(to->table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) ||
+ to->type() != FIELD_TYPE_DATE &&
+ to->type() != FIELD_TYPE_DATETIME) &&
+ (from->real_type() != MYSQL_TYPE_VARCHAR ||
+ ((Field_varstring*)from)->length_bytes ==
+ ((Field_varstring*)to)->length_bytes))
{ // Identical fields
- memcpy(to->ptr,from->ptr,to->pack_length());
+#ifdef HAVE_purify
+ /* This may happen if one does 'UPDATE ... SET x=x' */
+ if (to->ptr != from->ptr)
+#endif
+ memcpy(to->ptr,from->ptr,to->pack_length());
return;
}
}
@@ -611,7 +659,8 @@ void field_conv(Field *to,Field *from)
Field_blob *blob=(Field_blob*) to;
from->val_str(&blob->value);
if (!blob->value.is_alloced() &&
- from->real_type() != FIELD_TYPE_STRING)
+ from->real_type() != MYSQL_TYPE_STRING &&
+ from->real_type() != MYSQL_TYPE_VARCHAR)
blob->value.copy();
blob->store(blob->value.ptr(),blob->value.length(),from->charset());
return;
@@ -625,10 +674,21 @@ void field_conv(Field *to,Field *from)
char buff[MAX_FIELD_WIDTH];
String result(buff,sizeof(buff),from->charset());
from->val_str(&result);
+ /*
+ We use c_ptr_quick() here to make it easier if to is a float/double
+ as the conversion routines will do a copy of the result doesn't
+ end with \0. Can be replaced with .ptr() when we have our own
+ string->double conversion.
+ */
to->store(result.c_ptr_quick(),result.length(),from->charset());
}
else if (from->result_type() == REAL_RESULT)
to->store(from->val_real());
+ else if (from->result_type() == DECIMAL_RESULT)
+ {
+ my_decimal buff;
+ to->store_decimal(from->val_decimal(&buff));
+ }
else
- to->store(from->val_int());
+ to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG));
}
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 63a8515020b..ad784c729fa 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -48,7 +48,8 @@ static int merge_index(SORTPARAM *param,uchar *sort_buffer,
BUFFPEK *buffpek,
uint maxbuffer,IO_CACHE *tempfile,
IO_CACHE *outfile);
-static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
+static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count,
+ FILESORT_INFO *table_sort);
static uint sortlength(SORT_FIELD *sortorder, uint s_length,
bool *multi_byte_charset);
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
@@ -106,8 +107,16 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_PUSH(""); /* No DBUG here */
#endif
-
- outfile= table->sort.io_cache;
+ FILESORT_INFO table_sort;
+ /*
+ Don't use table->sort in filesort as it is also used by
+ QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
+ when index_merge select has finished with it.
+ */
+ memcpy(&table_sort, &table->sort, sizeof(FILESORT_INFO));
+ table->sort.io_cache= NULL;
+
+ outfile= table_sort.io_cache;
my_b_clear(&tempfile);
my_b_clear(&buffpek_pointers);
buffpek=0;
@@ -118,7 +127,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
param.ref_length= table->file->ref_length;
param.addon_field= 0;
param.addon_length= 0;
- if (!(table->tmp_table || table->fulltext_searched))
+ if (!(table->file->table_flags() & HA_FAST_KEY_READ) &&
+ !table->fulltext_searched)
{
/*
Get the descriptors of all fields whose values are appended
@@ -128,14 +138,15 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
param.sort_length,
&param.addon_length);
}
- table->sort.addon_buf= 0;
- table->sort.addon_length= param.addon_length;
- table->sort.addon_field= param.addon_field;
- table->sort.unpack= unpack_addon_fields;
+
+ table_sort.addon_buf= 0;
+ table_sort.addon_length= param.addon_length;
+ table_sort.addon_field= param.addon_field;
+ table_sort.unpack= unpack_addon_fields;
if (param.addon_field)
{
param.res_length= param.addon_length;
- if (!(table->sort.addon_buf= (byte *) my_malloc(param.addon_length,
+ if (!(table_sort.addon_buf= (byte *) my_malloc(param.addon_length,
MYF(MY_WME))))
goto err;
}
@@ -153,11 +164,11 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
if (select && select->quick)
{
- statistic_increment(filesort_range_count, &LOCK_status);
+ statistic_increment(thd->status_var.filesort_range_count, &LOCK_status);
}
else
{
- statistic_increment(filesort_scan_count, &LOCK_status);
+ statistic_increment(thd->status_var.filesort_scan_count, &LOCK_status);
}
#ifdef CAN_TRUST_RANGE
if (select && select->quick && select->quick->records > 0L)
@@ -218,7 +229,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
if (maxbuffer == 0) // The whole set is in memory
{
- if (save_index(&param,sort_keys,(uint) records))
+ if (save_index(&param,sort_keys,(uint) records, &table_sort))
goto err;
}
else
@@ -274,13 +285,16 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
}
}
if (error)
- my_error(ER_FILSORT_ABORT,MYF(ME_ERROR+ME_WAITTANG));
+ my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
+ MYF(ME_ERROR+ME_WAITTANG));
else
- statistic_add(filesort_rows, (ulong) records, &LOCK_status);
+ statistic_add(thd->status_var.filesort_rows,
+ (ulong) records, &LOCK_status);
*examined_rows= param.examined_rows;
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_POP(); /* Ok to DBUG */
#endif
+ memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
DBUG_PRINT("exit",("records: %ld",records));
DBUG_RETURN(error ? HA_POS_ERROR : records);
} /* filesort */
@@ -387,7 +401,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
byte *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
my_off_t record;
TABLE *sort_form;
- volatile my_bool *killed= &current_thd->killed;
+ volatile THD::killed_state *killed= &current_thd->killed;
handler *file;
DBUG_ENTER("find_all_keys");
DBUG_PRINT("info",("using: %s",(select?select->quick?"ranges":"where":"every row")));
@@ -407,21 +421,30 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
next_pos=ref_pos;
if (! indexfile && ! quick_select)
{
- file->reset(); // QQ; Shouldn't be needed
- 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->ha_rnd_init(1);
file->extra_opt(HA_EXTRA_CACHE,
current_thd->variables.read_buff_size);
}
+ READ_RECORD read_record_info;
+ if (quick_select)
+ {
+ if (select->quick->reset())
+ DBUG_RETURN(HA_POS_ERROR);
+ init_read_record(&read_record_info, current_thd, select->quick->head,
+ select, 1, 1);
+ }
+
for (;;)
{
if (quick_select)
{
- if ((error=select->quick->get_next()))
- break;
+ if ((error= read_record_info.read_record(&read_record_info)))
+ {
+ error= HA_ERR_END_OF_FILE;
+ break;
+ }
file->position(sort_form->record[0]);
}
else /* Not quick-select */
@@ -440,8 +463,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
error=file->rnd_next(sort_form->record[0]);
if (!flag)
{
- ha_store_ptr(ref_pos,ref_length,record); // Position to row
- record+=sort_form->db_record_offset;
+ my_store_ptr(ref_pos,ref_length,record); // Position to row
+ record+= sort_form->s->db_record_offset;
}
else if (!error)
file->position(sort_form->record[0]);
@@ -449,6 +472,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
if (error && error != HA_ERR_RECORD_DELETED)
break;
}
+
if (*killed)
{
DBUG_PRINT("info",("Sort killed by user"));
@@ -475,9 +499,21 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
else
file->unlock_row();
}
- (void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
- if (!next_pos)
- file->ha_rnd_end();
+ if (quick_select)
+ {
+ /*
+ index_merge quick select uses table->sort when retrieving rows, so free
+ resoures it has allocated.
+ */
+ end_read_record(&read_record_info);
+ }
+ else
+ {
+ (void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
+ if (!next_pos)
+ file->ha_rnd_end();
+ }
+
DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos));
if (error != HA_ERR_END_OF_FILE)
{
@@ -532,10 +568,10 @@ write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
if (!my_b_inited(tempfile) &&
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
MYF(MY_WME)))
- goto err; /* purecov: inspected */
+ goto err; /* purecov: inspected */
buffpek.file_pos= my_b_tell(tempfile);
if ((ha_rows) count > param->max_rows)
- count=(uint) param->max_rows; /* purecov: inspected */
+ count=(uint) param->max_rows; /* purecov: inspected */
buffpek.count=(ha_rows) count;
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
if (my_b_write(tempfile, (byte*) *sort_keys, (uint) rec_length))
@@ -584,20 +620,21 @@ static void make_sortkey(register SORTPARAM *param,
else
{ // Item
Item *item=sort_field->item;
+ maybe_null= item->maybe_null;
switch (sort_field->result_type) {
case STRING_RESULT:
{
CHARSET_INFO *cs=item->collation.collation;
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
- if ((maybe_null=item->maybe_null))
+ if (maybe_null)
*to++=1;
/* All item->str() to use some extra byte for end null.. */
String tmp((char*) to,sort_field->length+4,cs);
- String *res=item->val_str(&tmp);
+ String *res= item->str_result(&tmp);
if (!res)
{
- if (item->maybe_null)
+ if (maybe_null)
bzero((char*) to-1,sort_field->length+1);
else
{
@@ -636,21 +673,23 @@ static void make_sortkey(register SORTPARAM *param,
}
case INT_RESULT:
{
- longlong value=item->val_int();
- if ((maybe_null=item->maybe_null))
+ longlong value= item->val_int_result();
+ if (maybe_null)
+ {
*to++=1; /* purecov: inspected */
- if (item->null_value)
- {
- if (item->maybe_null)
- bzero((char*) to-1,sort_field->length+1);
- else
- {
- DBUG_PRINT("warning",
- ("Got null on something that shouldn't be null"));
- bzero((char*) to,sort_field->length);
- }
- break;
- }
+ if (item->null_value)
+ {
+ if (maybe_null)
+ bzero((char*) to-1,sort_field->length+1);
+ else
+ {
+ DBUG_PRINT("warning",
+ ("Got null on something that shouldn't be null"));
+ bzero((char*) to,sort_field->length);
+ }
+ break;
+ }
+ }
#if SIZEOF_LONG_LONG > 4
to[7]= (uchar) value;
to[6]= (uchar) (value >> 8);
@@ -674,17 +713,37 @@ static void make_sortkey(register SORTPARAM *param,
#endif
break;
}
+ case DECIMAL_RESULT:
+ {
+ my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
+ if (maybe_null)
+ {
+ if (item->null_value)
+ {
+ bzero((char*)to, sort_field->length+1);
+ to++;
+ break;
+ }
+ *to++=1;
+ }
+ my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, (char*)to,
+ item->max_length - (item->decimals ? 1:0),
+ item->decimals);
+ break;
+ }
case REAL_RESULT:
{
- double value=item->val();
- if ((maybe_null=item->null_value))
- {
- bzero((char*) to,sort_field->length+1);
- to++;
- break;
- }
- if ((maybe_null=item->maybe_null))
+ double value= item->val_result();
+ if (maybe_null)
+ {
+ if (item->null_value)
+ {
+ bzero((char*) to,sort_field->length+1);
+ to++;
+ break;
+ }
*to++=1;
+ }
change_double_for_sort(value,(byte*) to);
break;
}
@@ -720,7 +779,7 @@ static void make_sortkey(register SORTPARAM *param,
*/
SORT_ADDON_FIELD *addonf= param->addon_field;
uchar *nulls= to;
- DBUG_ASSERT(addonf);
+ DBUG_ASSERT(addonf != 0);
bzero((char *) nulls, addonf->offset);
to+= addonf->offset;
for ( ; (field= addonf->field) ; addonf++)
@@ -753,8 +812,8 @@ static void make_sortkey(register SORTPARAM *param,
return;
}
-
-static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count)
+static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count,
+ FILESORT_INFO *table_sort)
{
uint offset,res_length;
byte *to;
@@ -765,7 +824,7 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count)
offset= param->rec_length-res_length;
if ((ha_rows) count > param->max_rows)
count=(uint) param->max_rows;
- if (!(to= param->sort_form->sort.record_pointers=
+ if (!(to= table_sort->record_pointers=
(byte*) my_malloc(res_length*count, MYF(MY_WME))))
DBUG_RETURN(1); /* purecov: inspected */
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
@@ -850,6 +909,39 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
} /* read_to_buffer */
+/*
+ Put all room used by freed buffer to use in adjacent buffer. Note, that
+ we can't simply distribute memory evenly between all buffers, because
+ new areas must not overlap with old ones.
+ SYNOPSYS
+ reuse_freed_buff()
+ queue IN list of non-empty buffers, without freed buffer
+ reuse IN empty buffer
+ key_length IN key length
+*/
+
+void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
+{
+ uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
+ for (uint i= 0; i < queue->elements; ++i)
+ {
+ BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
+ if (bp->base + bp->max_keys * key_length == reuse->base)
+ {
+ bp->max_keys+= reuse->max_keys;
+ return;
+ }
+ else if (bp->base == reuse_end)
+ {
+ bp->base= reuse->base;
+ bp->max_keys+= reuse->max_keys;
+ return;
+ }
+ }
+ DBUG_ASSERT(0);
+}
+
+
/*
Merge buffers to one buffer
SYNOPSIS
@@ -879,18 +971,19 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
ha_rows max_rows,org_max_rows;
my_off_t to_start_filepos;
uchar *strpos;
- BUFFPEK *buffpek,**refpek;
+ BUFFPEK *buffpek;
QUEUE queue;
qsort2_cmp cmp;
- volatile my_bool *killed= &current_thd->killed;
- my_bool not_killable;
+ volatile THD::killed_state *killed= &current_thd->killed;
+ THD::killed_state not_killable;
DBUG_ENTER("merge_buffers");
- statistic_increment(filesort_merge_passes, &LOCK_status);
+ statistic_increment(current_thd->status_var.filesort_merge_passes,
+ &LOCK_status);
if (param->not_killable)
{
killed= &not_killable;
- not_killable= 0;
+ not_killable= THD::NOT_KILLED;
}
error=0;
@@ -993,29 +1086,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
if (!(error= (int) read_to_buffer(from_file,buffpek,
rec_length)))
{
- uchar *base= buffpek->base;
- ulong max_keys= buffpek->max_keys;
-
VOID(queue_remove(&queue,0));
-
- /* Put room used by buffer to use in other buffer */
- for (refpek= (BUFFPEK**) &queue_top(&queue);
- refpek <= (BUFFPEK**) &queue_end(&queue);
- refpek++)
- {
- buffpek= *refpek;
- if (buffpek->base+buffpek->max_keys*rec_length == base)
- {
- buffpek->max_keys+= max_keys;
- break;
- }
- else if (base+max_keys*rec_length == buffpek->base)
- {
- buffpek->base= base;
- buffpek->max_keys+= max_keys;
- break;
- }
- }
+ reuse_freed_buff(&queue, buffpek, rec_length);
break; /* One buffer have been removed */
}
else if (error == -1)
@@ -1140,7 +1212,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
{
sortorder->need_strxnfrm= 1;
*multi_byte_charset= 1;
- sortorder->length= sortorder->length*cs->strxfrm_multiply;
+ sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
}
}
if (sortorder->field->maybe_null())
@@ -1153,7 +1225,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
sortorder->length=sortorder->item->max_length;
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
{
- sortorder->length= sortorder->length*cs->strxfrm_multiply;
+ sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
sortorder->need_strxnfrm= 1;
*multi_byte_charset= 1;
}
@@ -1165,6 +1237,12 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
sortorder->length=4;
#endif
break;
+ case DECIMAL_RESULT:
+ sortorder->length=
+ my_decimal_get_binary_size(sortorder->item->max_length -
+ (sortorder->item->decimals ? 1 : 0),
+ sortorder->item->decimals);
+ break;
case REAL_RESULT:
sortorder->length=sizeof(double);
break;
@@ -1224,27 +1302,29 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength)
uint length= 0;
uint fields= 0;
uint null_fields= 0;
-
- /*
- If there is a reference to a field in the query add it
- to the the set of appended fields.
- Note for future refinement:
- This this a too strong condition.
- Actually we need only the fields referred in the
- result set. And for some of them it makes sense to use
- the values directly from sorted fields.
+ query_id_t query_id= thd->query_id;
+ /*
+ If there is a reference to a field in the query add it
+ to the the set of appended fields.
+ Note for future refinement:
+ This this a too strong condition.
+ Actually we need only the fields referred in the
+ result set. And for some of them it makes sense to use
+ the values directly from sorted fields.
*/
*plength= 0;
+
/*
- The following statement is added to avoid sorting in alter_table.
- The fact is the filter 'field->query_id != thd->query_id'
- doesn't work for alter table
+ The following statement is added to avoid sorting in alter_table.
+ The fact is the filter 'field->query_id != thd->query_id'
+ doesn't work for alter table
*/
- if (thd->lex->sql_command != SQLCOM_SELECT)
+ if (thd->lex->sql_command != SQLCOM_SELECT &&
+ thd->lex->sql_command != SQLCOM_INSERT_SELECT)
return 0;
for (pfield= ptabfield; (field= *pfield) ; pfield++)
{
- if (field->query_id != thd->query_id)
+ if (field->query_id != query_id)
continue;
if (field->flags & BLOB_FLAG)
return 0;
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 0bbdf84c8d6..7e0b178f7af 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -83,8 +83,17 @@ TODO:
#include "mysql_version.h"
#include "lex.h"
+const char *default_dbug_option="d:t:o,/tmp/gen_lex_hash.trace";
+
struct my_option my_long_options[] =
{
+#ifdef DBUG_OFF
+ {"debug", '#', "This is a non-debug version. Catch this and exit",
+ 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#else
+ {"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
+ (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"help", '?', "Display help and exit",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit",
@@ -108,7 +117,7 @@ hash_lex_struct *get_hash_struct_by_len(hash_lex_struct **root_by_len,
{
if (*max_len<len){
*root_by_len= (hash_lex_struct *)realloc((char*)*root_by_len,
- sizeof(hash_lex_struct)*len);
+ sizeof(hash_lex_struct)*len);
hash_lex_struct *cur, *end= *root_by_len + len;
for (cur= *root_by_len + *max_len; cur<end; cur++)
cur->first_char= 0;
@@ -291,7 +300,7 @@ void print_hash_map(const char *name)
char *cur;
int i;
- printf("uchar %s[%d]= {\n",name,size_hash_map);
+ printf("static uchar %s[%d]= {\n",name,size_hash_map);
for (i=0, cur= hash_map; i<size_hash_map; i++, cur++)
{
switch(i%4){
@@ -353,6 +362,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case '?':
usage(0);
exit(0);
+ case '#':
+ DBUG_PUSH(argument ? argument : default_dbug_option);
+ break;
}
return 0;
}
@@ -425,11 +437,12 @@ int check_duplicates()
int main(int argc,char **argv)
{
MY_INIT(argv[0]);
+ DBUG_PROCESS(argv[0]);
if (get_options(argc,(char **) argv))
exit(1);
- printf("/* Copyright (C) 2001 MySQL AB\n\
+ printf("/* Copyright (C) 2001-2004 MySQL AB\n\
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
and you are welcome to modify and redistribute it under the GPL license\n\
\n*/\n\n");
@@ -446,12 +459,11 @@ int main(int argc,char **argv)
generate_find_structs();
print_find_structs();
- printf("\nunsigned int sql_functions_max_len=%d;\n",max_len);
- printf("\nunsigned int symbols_max_len=%d;\n\n",max_len2);
+ printf("\nstatic unsigned int sql_functions_max_len=%d;\n", max_len);
+ printf("\nstatic unsigned int symbols_max_len=%d;\n\n", max_len2);
- printf
-(
-"inline SYMBOL *get_hash_symbol(const char *s,\n\
+ printf("\
+static inline SYMBOL *get_hash_symbol(const char *s,\n\
unsigned int len,bool function)\n\
{\n\
register uchar *hash_map;\n\
@@ -516,5 +528,7 @@ int main(int argc,char **argv)
}\n\
}\n"
);
+ my_end(0);
+ exit(0);
}
diff --git a/sql/gstream.cc b/sql/gstream.cc
index f7d11d76b0c..4083cb2fe71 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -83,7 +83,7 @@ bool Gis_read_stream::get_next_number(double *d)
}
*d = my_strntod(m_charset, (char *)m_cur,
- m_limit-m_cur, &endptr, &err);
+ (uint) (m_limit-m_cur), &endptr, &err);
if (err)
return 1;
if (endptr)
@@ -115,6 +115,6 @@ bool Gis_read_stream::check_next_symbol(char symbol)
void Gis_read_stream::set_error_msg(const char *msg)
{
size_t len= strlen(msg); // ok in this context
- m_err_msg= (char *) my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
+ m_err_msg= (char *) my_realloc(m_err_msg, (uint) len + 1, MYF(MY_ALLOW_ZERO_PTR));
memcpy(m_err_msg, msg, len + 1);
}
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 33f7b6238b0..b8a779c08cf 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -103,11 +103,39 @@ static int write_status(DB *status_block, char *buff, uint length);
static void update_status(BDB_SHARE *share, TABLE *table);
static void berkeley_noticecall(DB_ENV *db_env, db_notices notice);
-
+static int berkeley_close_connection(THD *thd);
+static int berkeley_commit(THD *thd, bool all);
+static int berkeley_rollback(THD *thd, bool all);
+
+static handlerton berkeley_hton = {
+ "BerkeleyDB",
+ 0, /* slot */
+ 0, /* savepoint size */
+ berkeley_close_connection,
+ NULL, /* savepoint_set */
+ NULL, /* savepoint_rollback */
+ NULL, /* savepoint_release */
+ berkeley_commit,
+ berkeley_rollback,
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_CLOSE_CURSORS_AT_COMMIT
+};
+
+typedef struct st_berkeley_trx_data {
+ DB_TXN *all;
+ DB_TXN *stmt;
+ uint bdb_lock_count;
+} berkeley_trx_data;
/* General functions */
-bool berkeley_init(void)
+handlerton *berkeley_init(void)
{
DBUG_ENTER("berkeley_init");
@@ -136,7 +164,7 @@ bool berkeley_init(void)
berkeley_log_file_size= max(berkeley_log_file_size, 10*1024*1024L);
if (db_env_create(&db_env,0))
- DBUG_RETURN(1); /* purecov: inspected */
+ DBUG_RETURN(0);
db_env->set_errcall(db_env,berkeley_print_error);
db_env->set_errpfx(db_env,"bdb");
db_env->set_noticecall(db_env, berkeley_noticecall);
@@ -164,16 +192,15 @@ bool berkeley_init(void)
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN |
DB_CREATE | DB_THREAD, 0666))
{
- db_env->close(db_env,0); /* purecov: inspected */
- db_env=0; /* purecov: inspected */
- goto err;
+ db_env->close(db_env,0);
+ db_env=0;
+ DBUG_RETURN(0);
}
(void) hash_init(&bdb_open_tables,system_charset_info,32,0,0,
(hash_get_key) bdb_get_key,0,0);
pthread_mutex_init(&bdb_mutex,MY_MUTEX_INIT_FAST);
-err:
- DBUG_RETURN(db_env == 0);
+ DBUG_RETURN(&berkeley_hton);
}
@@ -191,6 +218,12 @@ bool berkeley_end(void)
DBUG_RETURN(error != 0);
}
+static int berkeley_close_connection(THD *thd)
+{
+ my_free((gptr)thd->ha_data[berkeley_hton.slot], MYF(0));
+ return 0;
+}
+
bool berkeley_flush_logs()
{
int error;
@@ -209,26 +242,29 @@ bool berkeley_flush_logs()
DBUG_RETURN(result);
}
-
-int berkeley_commit(THD *thd, void *trans)
+static int berkeley_commit(THD *thd, bool all)
{
DBUG_ENTER("berkeley_commit");
- DBUG_PRINT("trans",("ending transaction %s",
- trans == thd->transaction.stmt.bdb_tid ? "stmt" : "all"));
- int error=txn_commit((DB_TXN*) trans,0);
+ DBUG_PRINT("trans",("ending transaction %s", all ? "all" : "stmt"));
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ DB_TXN **txn= all ? &trx->all : &trx->stmt;
+ int error=txn_commit(*txn,0);
+ *txn=0;
#ifndef DBUG_OFF
if (error)
- DBUG_PRINT("error",("error: %d",error)); /* purecov: inspected */
+ DBUG_PRINT("error",("error: %d",error));
#endif
DBUG_RETURN(error);
}
-int berkeley_rollback(THD *thd, void *trans)
+static int berkeley_rollback(THD *thd, bool all)
{
DBUG_ENTER("berkeley_rollback");
- DBUG_PRINT("trans",("aborting transaction %s",
- trans == thd->transaction.stmt.bdb_tid ? "stmt" : "all"));
- int error=txn_abort((DB_TXN*) trans);
+ DBUG_PRINT("trans",("aborting transaction %s", all ? "all" : "stmt"));
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ DB_TXN **txn= all ? &trx->all : &trx->stmt;
+ int error=txn_abort(*txn);
+ *txn=0;
DBUG_RETURN(error);
}
@@ -341,11 +377,26 @@ void berkeley_cleanup_log_files(void)
** Berkeley DB tables
*****************************************************************************/
-static const char *ha_bdb_bas_exts[]= { ha_berkeley_ext, NullS };
-const char **ha_berkeley::bas_ext() const
-{ return ha_bdb_bas_exts; }
+ha_berkeley::ha_berkeley(TABLE *table_arg)
+ :handler(&berkeley_hton, table_arg), alloc_ptr(0), rec_buff(0), file(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)
+{}
+static const char *ha_berkeley_exts[] = {
+ ha_berkeley_ext,
+ NullS
+};
+
+const char **ha_berkeley::bas_ext() const
+{
+ return ha_berkeley_exts;
+}
+
ulong ha_berkeley::index_flags(uint idx, uint part, bool all_parts) const
{
ulong flags= (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_KEYREAD_ONLY
@@ -360,7 +411,8 @@ ulong ha_berkeley::index_flags(uint idx, uint part, bool all_parts) const
}
switch (table->key_info[idx].key_part[i].field->key_type()) {
case HA_KEYTYPE_TEXT:
- case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
/*
As BDB stores only one copy of equal strings, we can't use key read
on these. Binary collations do support key read though.
@@ -395,9 +447,11 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key)
KEY_PART_INFO *key_part= key->key_part, *end=key_part+key->key_parts;
uint key_length=new_key->size;
+ DBUG_DUMP("key_in_index", saved_key_ptr, saved_key->size);
for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
+ uint length;
if (key_part->null_bit)
{
if (*new_key_ptr != *saved_key_ptr++)
@@ -406,11 +460,12 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key)
if (!*new_key_ptr++)
continue;
}
- if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,
- key_part->length)))
+ if ((cmp= key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,
+ key_part->length,
+ key->table->insert_or_update)))
return cmp;
- uint length=key_part->field->packed_col_length(new_key_ptr,
- key_part->length);
+ length= key_part->field->packed_col_length(new_key_ptr,
+ key_part->length);
new_key_ptr+=length;
key_length-=length;
saved_key_ptr+=key_part->field->packed_col_length(saved_key_ptr,
@@ -436,7 +491,7 @@ berkeley_cmp_fix_length_key(DB *file, const DBT *new_key, const DBT *saved_key)
for (; key_part != end && (int) key_length > 0 ; key_part++)
{
int cmp;
- if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,0)))
+ if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,0,0)))
return cmp;
new_key_ptr+=key_part->length;
key_length-= key_part->length;
@@ -446,6 +501,7 @@ berkeley_cmp_fix_length_key(DB *file, const DBT *new_key, const DBT *saved_key)
}
#endif
+
/* Compare key against row */
static bool
@@ -457,6 +513,7 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
+ uint length;
if (key_part->null_bit)
{
key_length--;
@@ -470,27 +527,34 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
if (!*key++) // Null value
continue;
}
- if ((cmp=key_part->field->pack_cmp(key,key_part->length)))
+ /*
+ Last argument has to be 0 as we are also using this to function to see
+ if a key like 'a ' matched a row with 'a'
+ */
+ if ((cmp= key_part->field->pack_cmp(key, key_part->length, 0)))
return cmp;
- uint length=key_part->field->packed_col_length(key,key_part->length);
- key+=length;
- key_length-=length;
+ length= key_part->field->packed_col_length(key,key_part->length);
+ key+= length;
+ key_length-= length;
}
return 0; // Identical keys
}
+
int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
{
char name_buff[FN_REFLEN];
uint open_mode=(mode == O_RDONLY ? DB_RDONLY : 0) | DB_THREAD;
+ uint max_key_length;
int error;
+ TABLE_SHARE *table_share= table->s;
DBUG_ENTER("ha_berkeley::open");
/* Open primary key */
hidden_primary_key=0;
- if ((primary_key=table->primary_key) >= MAX_KEY)
+ if ((primary_key= table_share->primary_key) >= MAX_KEY)
{ // No primary key
- primary_key=table->keys;
+ primary_key= table_share->keys;
key_used_on_scan=MAX_KEY;
ref_length=hidden_primary_key=BDB_HIDDEN_PRIMARY_KEY_LENGTH;
}
@@ -498,18 +562,18 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
key_used_on_scan=primary_key;
/* Need some extra memory in case of packed keys */
- uint max_key_length= table->max_key_length + MAX_REF_PARTS*3;
+ max_key_length= table_share->max_key_length + MAX_REF_PARTS*3;
if (!(alloc_ptr=
my_multi_malloc(MYF(MY_WME),
&key_buff, max_key_length,
&key_buff2, max_key_length,
&primary_key_buff,
(hidden_primary_key ? 0 :
- table->key_info[table->primary_key].key_length),
+ table->key_info[table_share->primary_key].key_length),
NullS)))
DBUG_RETURN(1); /* purecov: inspected */
if (!(rec_buff= (byte*) my_malloc((alloced_rec_buff_length=
- table->rec_buff_length),
+ table_share->rec_buff_length),
MYF(MY_WME))))
{
my_free(alloc_ptr,MYF(0)); /* purecov: inspected */
@@ -517,7 +581,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
}
/* Init shared structure */
- if (!(share=get_share(name,table)))
+ if (!(share= get_share(name,table)))
{
my_free((char*) rec_buff,MYF(0)); /* purecov: inspected */
my_free(alloc_ptr,MYF(0)); /* purecov: inspected */
@@ -530,7 +594,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
/* Fill in shared structure, if needed */
pthread_mutex_lock(&share->mutex);
- file = share->file;
+ file= share->file;
if (!share->use_count++)
{
if ((error=db_create(&file, db_env, 0)))
@@ -541,13 +605,13 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
my_errno=error; /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
- share->file = file;
+ share->file= file;
file->set_bt_compare(file,
(hidden_primary_key ? berkeley_cmp_hidden_key :
berkeley_cmp_packed_key));
if (!hidden_primary_key)
- file->app_private= (void*) (table->key_info+table->primary_key);
+ file->app_private= (void*) (table->key_info + table_share->primary_key);
if ((error= txn_begin(db_env, 0, (DB_TXN**) &transaction, 0)) ||
(error= (file->open(file, transaction,
fn_format(name_buff, name, "", ha_berkeley_ext,
@@ -555,7 +619,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
"main", DB_BTREE, open_mode, 0))) ||
(error= transaction->commit(transaction, 0)))
{
- free_share(share,table, hidden_primary_key,1); /* purecov: inspected */
+ free_share(share, table, hidden_primary_key,1); /* purecov: inspected */
my_free((char*) rec_buff,MYF(0)); /* purecov: inspected */
my_free(alloc_ptr,MYF(0)); /* purecov: inspected */
my_errno=error; /* purecov: inspected */
@@ -567,7 +631,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
key_type[primary_key]=DB_NOOVERWRITE;
DB **ptr=key_file;
- for (uint i=0, used_keys=0; i < table->keys ; i++, ptr++)
+ for (uint i=0, used_keys=0; i < table_share->keys ; i++, ptr++)
{
char part[7];
if (i != primary_key)
@@ -599,7 +663,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
}
}
/* Calculate pack_length of primary key */
- share->fixed_length_primary_key=1;
+ share->fixed_length_primary_key= 1;
if (!hidden_primary_key)
{
ref_length=0;
@@ -609,18 +673,19 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
ref_length+= key_part->field->max_packed_col_length(key_part->length);
share->fixed_length_primary_key=
(ref_length == table->key_info[primary_key].key_length);
- share->status|=STATUS_PRIMARY_KEY_INIT;
+ share->status|= STATUS_PRIMARY_KEY_INIT;
}
- share->ref_length=ref_length;
+ share->ref_length= ref_length;
}
- ref_length=share->ref_length; // If second open
+ ref_length= share->ref_length; // If second open
pthread_mutex_unlock(&share->mutex);
transaction=0;
cursor=0;
key_read=0;
block_size=8192; // Berkeley DB block size
- share->fixed_length_row=!(table->db_create_options & HA_OPTION_PACK_RECORD);
+ share->fixed_length_row= !(table_share->db_create_options &
+ HA_OPTION_PACK_RECORD);
get_status();
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
@@ -660,9 +725,15 @@ bool ha_berkeley::fix_rec_buff_for_blob(ulong length)
ulong ha_berkeley::max_row_length(const byte *buf)
{
- ulong length=table->reclength + table->fields*2;
- for (Field_blob **ptr=table->blob_field ; *ptr ; ptr++)
- length+= (*ptr)->get_length((char*) buf+(*ptr)->offset())+2;
+ ulong length= table->s->reclength + table->s->fields*2;
+ uint *ptr, *end;
+ for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
+ ptr != end ;
+ ptr++)
+ {
+ Field_blob *blob= ((Field_blob*) table->field[*ptr]);
+ length+= blob->get_length((char*) buf + blob->offset())+2;
+ }
return length;
}
@@ -678,29 +749,30 @@ ulong ha_berkeley::max_row_length(const byte *buf)
int ha_berkeley::pack_row(DBT *row, const byte *record, bool new_row)
{
+ byte *ptr;
bzero((char*) row,sizeof(*row));
if (share->fixed_length_row)
{
row->data=(void*) record;
- row->size=table->reclength+hidden_primary_key;
+ row->size= table->s->reclength+hidden_primary_key;
if (hidden_primary_key)
{
if (new_row)
get_auto_primary_key(current_ident);
- memcpy_fixed((char*) record+table->reclength, (char*) current_ident,
+ memcpy_fixed((char*) record+table->s->reclength, (char*) current_ident,
BDB_HIDDEN_PRIMARY_KEY_LENGTH);
}
return 0;
}
- if (table->blob_fields)
+ if (table->s->blob_fields)
{
if (fix_rec_buff_for_blob(max_row_length(record)))
return HA_ERR_OUT_OF_MEM; /* purecov: inspected */
}
/* Copy null bits */
- memcpy(rec_buff, record, table->null_bytes);
- byte *ptr=rec_buff + table->null_bytes;
+ memcpy(rec_buff, record, table->s->null_bytes);
+ ptr= rec_buff + table->s->null_bytes;
for (Field **field=table->field ; *field ; field++)
ptr=(byte*) (*field)->pack((char*) ptr,
@@ -723,13 +795,13 @@ int ha_berkeley::pack_row(DBT *row, const byte *record, bool new_row)
void ha_berkeley::unpack_row(char *record, DBT *row)
{
if (share->fixed_length_row)
- memcpy(record,(char*) row->data,table->reclength+hidden_primary_key);
+ memcpy(record,(char*) row->data,table->s->reclength+hidden_primary_key);
else
{
/* Copy null bits */
const char *ptr= (const char*) row->data;
- memcpy(record, ptr, table->null_bytes);
- ptr+=table->null_bytes;
+ memcpy(record, ptr, table->s->null_bytes);
+ ptr+= table->s->null_bytes;
for (Field **field=table->field ; *field ; field++)
ptr= (*field)->unpack(record + (*field)->offset(), ptr);
}
@@ -740,11 +812,11 @@ void ha_berkeley::unpack_row(char *record, DBT *row)
void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
{
- KEY *key_info=table->key_info+index;
+ KEY *key_info= table->key_info+index;
KEY_PART_INFO *key_part= key_info->key_part,
- *end=key_part+key_info->key_parts;
+ *end= key_part+key_info->key_parts;
+ char *pos= (char*) key->data;
- char *pos=(char*) key->data;
for (; key_part != end; key_part++)
{
if (key_part->null_bit)
@@ -768,8 +840,10 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
/*
- Create a packed key from from a row
- This will never fail as the key buffer is pre allocated.
+ Create a packed key from a row. This key will be written as such
+ to the index tree.
+
+ This will never fail as the key buffer is pre-allocated.
*/
DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
@@ -815,7 +889,10 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
/*
- Create a packed key from from a MySQL unpacked key
+ Create a packed key from from a MySQL unpacked key (like the one that is
+ sent from the index_read()
+
+ This key is to be used to read a row
*/
DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff,
@@ -861,7 +938,7 @@ int ha_berkeley::write_row(byte * record)
int error;
DBUG_ENTER("write_row");
- statistic_increment(ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && record == table->record[0])
@@ -869,7 +946,8 @@ int ha_berkeley::write_row(byte * record)
if ((error=pack_row(&row, record,1)))
DBUG_RETURN(error); /* purecov: inspected */
- if (table->keys + test(hidden_primary_key) == 1)
+ table->insert_or_update= 1; // For handling of VARCHAR
+ if (table->s->keys + test(hidden_primary_key) == 1)
{
error=file->put(file, transaction, create_key(&prim_key, primary_key,
key_buff, record),
@@ -880,22 +958,15 @@ int ha_berkeley::write_row(byte * record)
{
DB_TXN *sub_trans = transaction;
/* 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);
- if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) /* purecov: deadcode */
- break; /* purecov: deadcode */
- DBUG_PRINT("trans",("starting subtransaction")); /* purecov: deadcode */
- }
if (!(error=file->put(file, sub_trans, create_key(&prim_key, primary_key,
key_buff, record),
&row, key_type[primary_key])))
{
changed_keys.set_bit(primary_key);
- for (uint keynr=0 ; keynr < table->keys ; keynr++)
+ for (uint keynr=0 ; keynr < table->s->keys ; keynr++)
{
if (keynr == primary_key)
continue;
@@ -919,15 +990,11 @@ int ha_berkeley::write_row(byte * record)
if (using_ignore)
{
int new_error = 0;
- if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
- {
- DBUG_PRINT("trans",("aborting subtransaction")); /* purecov: deadcode */
- new_error=txn_abort(sub_trans); /* purecov: deadcode */
- }
- else if (!changed_keys.is_clear_all())
+ if (!changed_keys.is_clear_all())
{
new_error = 0;
- for (uint keynr=0 ; keynr < table->keys+test(hidden_primary_key) ;
+ for (uint keynr=0;
+ keynr < table->s->keys+test(hidden_primary_key);
keynr++)
{
if (changed_keys.is_set(keynr))
@@ -945,15 +1012,11 @@ int ha_berkeley::write_row(byte * record)
}
}
}
- else if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- DBUG_PRINT("trans",("committing subtransaction")); /* purecov: deadcode */
- error=txn_commit(sub_trans, 0); /* purecov: deadcode */
- }
if (error != DB_LOCK_DEADLOCK)
break;
}
}
+ table->insert_or_update= 0;
if (error == DB_KEYEXIST)
error=HA_ERR_FOUND_DUPP_KEY;
else if (!error)
@@ -978,7 +1041,7 @@ int ha_berkeley::key_cmp(uint keynr, const byte * old_row,
(new_row[key_part->null_offset] & key_part->null_bit))
return 1;
}
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
if (key_part->field->cmp_binary((char*) (old_row + key_part->offset),
@@ -1005,7 +1068,7 @@ int ha_berkeley::key_cmp(uint keynr, const byte * old_row,
int ha_berkeley::update_primary_key(DB_TXN *trans, bool primary_key_changed,
const byte * old_row, DBT *old_key,
const byte * new_row, DBT *new_key,
- ulong thd_options, bool local_using_ignore)
+ bool local_using_ignore)
{
DBT row;
int error;
@@ -1024,8 +1087,7 @@ int ha_berkeley::update_primary_key(DB_TXN *trans, bool primary_key_changed,
{
// Probably a duplicated key; restore old key and row if needed
last_dup_key=primary_key;
- if (local_using_ignore &&
- !(thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
+ if (local_using_ignore)
{
int new_error;
if ((new_error=pack_row(&row, old_row, 0)) ||
@@ -1055,8 +1117,7 @@ int ha_berkeley::update_primary_key(DB_TXN *trans, bool primary_key_changed,
int ha_berkeley::restore_keys(DB_TXN *trans, key_map *changed_keys,
uint primary_key,
const byte *old_row, DBT *old_key,
- const byte *new_row, DBT *new_key,
- ulong thd_options)
+ const byte *new_row, DBT *new_key)
{
int error;
DBT tmp_key;
@@ -1066,7 +1127,7 @@ int ha_berkeley::restore_keys(DB_TXN *trans, key_map *changed_keys,
/* Restore the old primary key, and the old row, but don't ignore
duplicate key failure */
if ((error=update_primary_key(trans, TRUE, new_row, new_key,
- old_row, old_key, thd_options, FALSE)))
+ old_row, old_key, FALSE)))
goto err; /* purecov: inspected */
/* Remove the new key, and put back the old key
@@ -1076,7 +1137,7 @@ int ha_berkeley::restore_keys(DB_TXN *trans, key_map *changed_keys,
that one just put back the old value. */
if (!changed_keys->is_clear_all())
{
- for (keynr=0 ; keynr < table->keys+test(hidden_primary_key) ; keynr++)
+ for (keynr=0 ; keynr < table->s->keys+test(hidden_primary_key) ; keynr++)
{
if (changed_keys->is_set(keynr))
{
@@ -1103,15 +1164,15 @@ 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->tmp_table == NO_TMP_TABLE ? table->in_use->options : 0;
bool primary_key_changed;
DBUG_ENTER("update_row");
LINT_INIT(error);
- statistic_increment(ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
+ table->insert_or_update= 1; // For handling of VARCHAR
if (hidden_primary_key)
{
primary_key_changed=0;
@@ -1134,20 +1195,14 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
for (uint retry=0 ; retry < berkeley_trans_retry ; retry++)
{
key_map changed_keys(0);
- if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) /* purecov: deadcode */
- break; /* purecov: deadcode */
- DBUG_PRINT("trans",("starting subtransaction")); /* purecov: deadcode */
- }
/* Start by updating the primary key */
if (!(error=update_primary_key(sub_trans, primary_key_changed,
old_row, &old_prim_key,
new_row, &prim_key,
- thd_options, using_ignore)))
+ using_ignore)))
{
// Update all other keys
- for (uint keynr=0 ; keynr < table->keys ; keynr++)
+ for (uint keynr=0 ; keynr < table->s->keys ; keynr++)
{
if (keynr == primary_key)
continue;
@@ -1155,15 +1210,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
{
if ((error=remove_key(sub_trans, keynr, old_row, &old_prim_key)))
{
- if (using_ignore && /* purecov: inspected */
- (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- int new_error;
- DBUG_PRINT("trans",("aborting subtransaction"));
- new_error=txn_abort(sub_trans);
- if (new_error)
- error = new_error;
- }
+ table->insert_or_update= 0;
DBUG_RETURN(error); // Fatal error /* purecov: inspected */
}
changed_keys.set_bit(keynr);
@@ -1185,30 +1232,21 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
if (using_ignore)
{
int new_error = 0;
- if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
- {
- DBUG_PRINT("trans",("aborting subtransaction")); /* purecov: deadcode */
- new_error=txn_abort(sub_trans); /* purecov: deadcode */
- }
- else if (!changed_keys.is_clear_all())
+ if (!changed_keys.is_clear_all())
new_error=restore_keys(transaction, &changed_keys, primary_key,
- old_row, &old_prim_key, new_row, &prim_key,
- thd_options);
+ old_row, &old_prim_key, new_row, &prim_key);
if (new_error)
{
- error=new_error; // This shouldn't happen /* purecov: inspected */
- break; /* purecov: inspected */
+ /* This shouldn't happen */
+ error=new_error; /* purecov: inspected */
+ break; /* purecov: inspected */
}
}
}
- else if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- DBUG_PRINT("trans",("committing subtransaction")); /* purecov: deadcode */
- error=txn_commit(sub_trans, 0); /* purecov: deadcode */
- }
if (error != DB_LOCK_DEADLOCK)
break;
}
+ table->insert_or_update= 0;
if (error == DB_KEYEXIST)
error=HA_ERR_FOUND_DUPP_KEY;
DBUG_RETURN(error);
@@ -1275,7 +1313,9 @@ int ha_berkeley::remove_keys(DB_TXN *trans, const byte *record,
DBT *new_record, DBT *prim_key, key_map *keys)
{
int result = 0;
- for (uint keynr=0 ; keynr < table->keys+test(hidden_primary_key) ; keynr++)
+ for (uint keynr=0;
+ keynr < table->s->keys+test(hidden_primary_key);
+ keynr++)
{
if (keys->is_set(keynr))
{
@@ -1295,10 +1335,9 @@ 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->tmp_table == NO_TMP_TABLE ? table->in_use->options : 0;
+ key_map keys= table->s->keys_in_use;
DBUG_ENTER("delete_row");
- statistic_increment(ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
if ((error=pack_row(&row, record, 0)))
DBUG_RETURN((error)); /* purecov: inspected */
@@ -1311,34 +1350,11 @@ int ha_berkeley::delete_row(const byte * record)
DB_TXN *sub_trans = transaction;
for (uint retry=0 ; retry < berkeley_trans_retry ; retry++)
{
- if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
- {
- if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) /* purecov: deadcode */
- break; /* purecov: deadcode */
- DBUG_PRINT("trans",("starting sub transaction")); /* purecov: deadcode */
- }
error=remove_keys(sub_trans, record, &row, &prim_key, &keys);
- if (!error && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- DBUG_PRINT("trans",("ending sub transaction")); /* purecov: deadcode */
- error=txn_commit(sub_trans, 0); /* purecov: deadcode */
- }
if (error)
{ /* purecov: inspected */
DBUG_PRINT("error",("Got error %d",error));
- if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
- {
- /* retry */
- int new_error;
- DBUG_PRINT("trans",("aborting subtransaction"));
- if ((new_error=txn_abort(sub_trans)))
- {
- error=new_error; // This shouldn't happen
- break;
- }
- }
- else
- break; // No retry - return error
+ break; // No retry - return error
}
if (error != DB_LOCK_DEADLOCK)
break;
@@ -1355,7 +1371,7 @@ int ha_berkeley::index_init(uint keynr)
{
int error;
DBUG_ENTER("ha_berkeley::index_init");
- DBUG_PRINT("enter",("table: '%s' key: %d", table->real_name, keynr));
+ DBUG_PRINT("enter",("table: '%s' key: %d", table->s->table_name, keynr));
/*
Under some very rare conditions (like full joins) we may already have
@@ -1382,7 +1398,7 @@ int ha_berkeley::index_end()
DBUG_ENTER("ha_berkely::index_end");
if (cursor)
{
- DBUG_PRINT("enter",("table: '%s'", table->real_name));
+ DBUG_PRINT("enter",("table: '%s'", table->s->table_name));
error=cursor->c_close(cursor);
cursor=0;
}
@@ -1445,7 +1461,7 @@ int ha_berkeley::read_row(int error, char *buf, uint keynr, DBT *row,
int ha_berkeley::index_read_idx(byte * buf, uint keynr, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
+ table->in_use->status_var.ha_read_key_count++;
DBUG_ENTER("index_read_idx");
current_row.flags=DB_DBT_REALLOC;
active_index=MAX_KEY;
@@ -1466,7 +1482,7 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
int do_prev= 0;
DBUG_ENTER("ha_berkeley::index_read");
- statistic_increment(ha_read_key_count,&LOCK_status);
+ table->in_use->status_var.ha_read_key_count++;
bzero((char*) &row,sizeof(row));
if (find_flag == HA_READ_BEFORE_KEY)
{
@@ -1478,7 +1494,8 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
find_flag= HA_READ_AFTER_KEY;
do_prev= 1;
}
- if (key_len == key_info->key_length)
+ if (key_len == key_info->key_length &&
+ !(table->key_info[active_index].flags & HA_END_SPACE_KEY))
{
if (find_flag == HA_READ_AFTER_KEY)
key_info->handler.bdb_return_if_eq= 1;
@@ -1535,7 +1552,8 @@ int ha_berkeley::index_read_last(byte * buf, const byte * key, uint key_len)
KEY *key_info= &table->key_info[active_index];
DBUG_ENTER("ha_berkeley::index_read");
- statistic_increment(ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
/* read of partial key */
@@ -1559,7 +1577,8 @@ int ha_berkeley::index_next(byte * buf)
{
DBT row;
DBUG_ENTER("index_next");
- statistic_increment(ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_NEXT),
(char*) buf, active_index, &row, &last_key, 1));
@@ -1570,9 +1589,11 @@ int ha_berkeley::index_next_same(byte * buf, const byte *key, uint keylen)
DBT row;
int error;
DBUG_ENTER("index_next_same");
- statistic_increment(ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
- if (keylen == table->key_info[active_index].key_length)
+ if (keylen == table->key_info[active_index].key_length &&
+ !(table->key_info[active_index].flags & HA_END_SPACE_KEY))
error=read_row(cursor->c_get(cursor, &last_key, &row, DB_NEXT_DUP),
(char*) buf, active_index, &row, &last_key, 1);
else
@@ -1590,7 +1611,8 @@ int ha_berkeley::index_prev(byte * buf)
{
DBT row;
DBUG_ENTER("index_prev");
- statistic_increment(ha_read_prev_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_prev_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV),
(char*) buf, active_index, &row, &last_key, 1));
@@ -1601,7 +1623,8 @@ int ha_berkeley::index_first(byte * buf)
{
DBT row;
DBUG_ENTER("index_first");
- statistic_increment(ha_read_first_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_first_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_FIRST),
(char*) buf, active_index, &row, &last_key, 1));
@@ -1611,7 +1634,8 @@ int ha_berkeley::index_last(byte * buf)
{
DBT row;
DBUG_ENTER("index_last");
- statistic_increment(ha_read_last_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_last_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_LAST),
(char*) buf, active_index, &row, &last_key, 0));
@@ -1633,7 +1657,8 @@ int ha_berkeley::rnd_next(byte *buf)
{
DBT row;
DBUG_ENTER("rnd_next");
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_NEXT),
(char*) buf, primary_key, &row, &last_key, 1));
@@ -1657,6 +1682,7 @@ DBT *ha_berkeley::get_pos(DBT *to, byte *pos)
pos+=key_part->field->packed_col_length((char*) pos,key_part->length);
to->size= (uint) (pos- (byte*) to->data);
}
+ DBUG_DUMP("key", (char*) to->data, to->size);
return to;
}
@@ -1664,9 +1690,10 @@ DBT *ha_berkeley::get_pos(DBT *to, byte *pos)
int ha_berkeley::rnd_pos(byte * buf, byte *pos)
{
DBT db_pos;
- statistic_increment(ha_read_rnd_count,&LOCK_status);
+
DBUG_ENTER("ha_berkeley::rnd_pos");
-
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
active_index= MAX_KEY;
DBUG_RETURN(read_row(file->get(file, transaction,
get_pos(&db_pos, pos),
@@ -1726,14 +1753,14 @@ void ha_berkeley::info(uint flag)
if ((flag & HA_STATUS_CONST) || version != share->version)
{
version=share->version;
- for (uint i=0 ; i < table->keys ; i++)
+ for (uint i=0 ; i < table->s->keys ; i++)
{
table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]=
share->rec_per_key[i];
}
}
/* Don't return key if we got an error for the internal primary key */
- if (flag & HA_STATUS_ERRKEY && last_dup_key < table->keys)
+ if (flag & HA_STATUS_ERRKEY && last_dup_key < table->s->keys)
errkey= last_dup_key;
DBUG_VOID_RETURN;
}
@@ -1795,61 +1822,65 @@ int ha_berkeley::reset(void)
int ha_berkeley::external_lock(THD *thd, int lock_type)
{
int error=0;
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
DBUG_ENTER("ha_berkeley::external_lock");
+ if (!trx)
+ {
+ thd->ha_data[berkeley_hton.slot]= trx= (berkeley_trx_data *)
+ my_malloc(sizeof(*trx), MYF(MY_ZEROFILL));
+ if (!trx)
+ DBUG_RETURN(1);
+ }
if (lock_type != F_UNLCK)
{
- if (!thd->transaction.bdb_lock_count++)
+ if (!trx->bdb_lock_count++)
{
- DBUG_ASSERT(thd->transaction.stmt.bdb_tid == 0);
+ DBUG_ASSERT(trx->stmt == 0);
transaction=0; // Safety
/* First table lock, start transaction */
if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
- OPTION_TABLE_LOCK)) &&
- !thd->transaction.all.bdb_tid)
+ OPTION_TABLE_LOCK)) && !trx->all)
{
/* We have to start a master transaction */
- DBUG_PRINT("trans",("starting transaction all"));
- if ((error=txn_begin(db_env, 0,
- (DB_TXN**) &thd->transaction.all.bdb_tid,
- 0)))
+ DBUG_PRINT("trans",("starting transaction all: options: 0x%lx",
+ (ulong) thd->options));
+ if ((error=txn_begin(db_env, 0, &trx->all, 0)))
{
- thd->transaction.bdb_lock_count--; // We didn't get the lock /* purecov: inspected */
- DBUG_RETURN(error); /* purecov: inspected */
+ trx->bdb_lock_count--; // We didn't get the lock
+ DBUG_RETURN(error);
}
+ trans_register_ha(thd, TRUE, &berkeley_hton);
if (thd->in_lock_tables)
DBUG_RETURN(0); // Don't create stmt trans
}
DBUG_PRINT("trans",("starting transaction stmt"));
- if ((error=txn_begin(db_env,
- (DB_TXN*) thd->transaction.all.bdb_tid,
- (DB_TXN**) &thd->transaction.stmt.bdb_tid,
- 0)))
+ if ((error=txn_begin(db_env, trx->all, &trx->stmt, 0)))
{
/* We leave the possible master transaction open */
- thd->transaction.bdb_lock_count--; // We didn't get the lock /* purecov: inspected */
- DBUG_RETURN(error); /* purecov: inspected */
+ trx->bdb_lock_count--; // We didn't get the lock
+ DBUG_RETURN(error);
}
+ trans_register_ha(thd, FALSE, &berkeley_hton);
}
- transaction= (DB_TXN*) thd->transaction.stmt.bdb_tid;
+ transaction= trx->stmt;
}
else
{
lock.type=TL_UNLOCK; // Unlocked
thread_safe_add(share->rows, changed_rows, &share->mutex);
changed_rows=0;
- if (!--thd->transaction.bdb_lock_count)
+ if (!--trx->bdb_lock_count)
{
- if (thd->transaction.stmt.bdb_tid)
+ if (trx->stmt)
{
/*
- F_UNLOCK is done without a transaction commit / rollback.
+ F_UNLCK is done without a transaction commit / rollback.
This happens if the thread didn't update any rows
We must in this case commit the work to keep the row locks
*/
DBUG_PRINT("trans",("commiting non-updating transaction"));
- error=txn_commit((DB_TXN*) thd->transaction.stmt.bdb_tid,0);
- thd->transaction.stmt.bdb_tid=0;
- transaction=0;
+ error= txn_commit(trx->stmt,0);
+ trx->stmt= transaction= 0;
}
}
}
@@ -1867,14 +1898,20 @@ int ha_berkeley::start_stmt(THD *thd)
{
int error=0;
DBUG_ENTER("ha_berkeley::start_stmt");
- if (!thd->transaction.stmt.bdb_tid)
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ DBUG_ASSERT(trx);
+ /*
+ note that trx->stmt may have been already initialized as start_stmt()
+ is called for *each table* not for each storage engine,
+ and there could be many bdb tables referenced in the query
+ */
+ if (!trx->stmt)
{
DBUG_PRINT("trans",("starting transaction stmt"));
- error=txn_begin(db_env, (DB_TXN*) thd->transaction.all.bdb_tid,
- (DB_TXN**) &thd->transaction.stmt.bdb_tid,
- 0);
+ error=txn_begin(db_env, trx->all, &trx->stmt, 0);
+ trans_register_ha(thd, FALSE, &berkeley_hton);
}
- transaction= (DB_TXN*) thd->transaction.stmt.bdb_tid;
+ transaction= trx->stmt;
DBUG_RETURN(error);
}
@@ -1918,9 +1955,7 @@ THR_LOCK_DATA **ha_berkeley::store_lock(THD *thd, THR_LOCK_DATA **to,
lock_type <= TL_WRITE) &&
!thd->in_lock_tables)
lock_type = TL_WRITE_ALLOW_WRITE;
- lock.type=lock_type;
- lock_on_read= ((table->reginfo.lock_type > TL_WRITE_ALLOW_READ) ? DB_RMW :
- 0);
+ lock.type= lock_type;
}
*to++= &lock;
return to;
@@ -1974,9 +2009,9 @@ int ha_berkeley::create(const char *name, register TABLE *form,
if ((error= create_sub_table(name_buff,"main",DB_BTREE,0)))
DBUG_RETURN(error); /* purecov: inspected */
- primary_key=table->primary_key;
+ primary_key= table->s->primary_key;
/* Create the keys */
- for (uint i=0; i < form->keys; i++)
+ for (uint i=0; i < form->s->keys; i++)
{
if (i != primary_key)
{
@@ -1998,7 +2033,7 @@ int ha_berkeley::create(const char *name, register TABLE *form,
"status", DB_BTREE, DB_CREATE, 0))))
{
char rec_buff[4+MAX_KEY*4];
- uint length= 4+ table->keys*4;
+ uint length= 4+ table->s->keys*4;
bzero(rec_buff, length);
error= write_status(status_block, rec_buff, length);
status_block->close(status_block,0);
@@ -2062,19 +2097,35 @@ ha_rows ha_berkeley::records_in_range(uint keynr, key_range *start_key,
DB_KEY_RANGE start_range, end_range;
DB *kfile=key_file[keynr];
double start_pos,end_pos,rows;
- DBUG_ENTER("records_in_range");
-
- if ((start_key && kfile->key_range(kfile,transaction,
- pack_key(&key, keynr, key_buff,
- start_key->key,
- start_key->length),
- &start_range,0)) ||
- (end_key && kfile->key_range(kfile,transaction,
- pack_key(&key, keynr, key_buff,
- end_key->key,
- end_key->length),
- &end_range,0)))
- DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); // Better than returning an error /* purecov: inspected */
+ bool error;
+ KEY *key_info= &table->key_info[keynr];
+ DBUG_ENTER("ha_berkeley::records_in_range");
+
+ /* Ensure we get maximum range, even for varchar keys with different space */
+ key_info->handler.bdb_return_if_eq= -1;
+ error= ((start_key && kfile->key_range(kfile,transaction,
+ pack_key(&key, keynr, key_buff,
+ start_key->key,
+ start_key->length),
+ &start_range,0)));
+ if (error)
+ {
+ key_info->handler.bdb_return_if_eq= 0;
+ // Better than returning an error
+ DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); /* purecov: inspected */
+ }
+ key_info->handler.bdb_return_if_eq= 1;
+ error= (end_key && kfile->key_range(kfile,transaction,
+ pack_key(&key, keynr, key_buff,
+ end_key->key,
+ end_key->length),
+ &end_range,0));
+ key_info->handler.bdb_return_if_eq= 0;
+ if (error)
+ {
+ // Better than returning an error
+ DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); /* purecov: inspected */
+ }
if (!start_key)
start_pos= 0.0;
@@ -2091,20 +2142,20 @@ ha_rows ha_berkeley::records_in_range(uint keynr, key_range *start_key,
end_pos=end_range.less+end_range.equal;
rows=(end_pos-start_pos)*records;
DBUG_PRINT("exit",("rows: %g",rows));
- DBUG_RETURN(rows <= 1.0 ? (ha_rows) 1 : (ha_rows) rows);
+ DBUG_RETURN((ha_rows)(rows <= 1.0 ? 1 : rows));
}
-longlong ha_berkeley::get_auto_increment()
+ulonglong ha_berkeley::get_auto_increment()
{
- longlong nr=1; // Default if error or new key
+ ulonglong nr=1; // Default if error or new key
int error;
(void) ha_berkeley::extra(HA_EXTRA_KEYREAD);
/* Set 'active_index' */
- ha_berkeley::index_init(table->next_number_index);
+ ha_berkeley::index_init(table->s->next_number_index);
- if (!table->next_number_key_offset)
+ if (!table->s->next_number_key_offset)
{ // Autoincrement at key-start
error=ha_berkeley::index_last(table->record[1]);
}
@@ -2117,7 +2168,7 @@ longlong ha_berkeley::get_auto_increment()
/* Reading next available number for a sub key */
ha_berkeley::create_key(&last_key, active_index,
key_buff, table->record[0],
- table->next_number_key_offset);
+ table->s->next_number_key_offset);
/* Store for compare */
memcpy(old_key.data=key_buff2, key_buff, (old_key.size=last_key.size));
old_key.app_private=(void*) key_info;
@@ -2146,8 +2197,8 @@ longlong ha_berkeley::get_auto_increment()
}
}
if (!error)
- nr=(longlong)
- table->next_number_field->val_int_offset(table->rec_buff_length)+1;
+ nr= (ulonglong)
+ table->next_number_field->val_int_offset(table->s->rec_buff_length)+1;
ha_berkeley::index_end();
(void) ha_berkeley::extra(HA_EXTRA_NO_KEYREAD);
return nr;
@@ -2185,7 +2236,7 @@ static void print_msg(THD *thd, const char *table_name, const char *op_name,
protocol->store(msg_type);
protocol->store(msgbuf);
if (protocol->write())
- thd->killed=1;
+ thd->killed=THD::KILL_CONNECTION;
}
#endif
@@ -2194,6 +2245,8 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
uint i;
DB_BTREE_STAT *stat=0;
DB_TXN_STAT *txn_stat_ptr= 0;
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ DBUG_ASSERT(trx);
/*
Original bdb documentation says:
@@ -2208,13 +2261,10 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
txn_stat_ptr && txn_stat_ptr->st_nactive>=2)
{
DB_TXN_ACTIVE *atxn_stmt= 0, *atxn_all= 0;
-
- DB_TXN *txn_all= (DB_TXN*) thd->transaction.all.bdb_tid;
- u_int32_t all_id= txn_all->id(txn_all);
-
- DB_TXN *txn_stmt= (DB_TXN*) thd->transaction.stmt.bdb_tid;
- u_int32_t stmt_id= txn_stmt->id(txn_stmt);
-
+
+ u_int32_t all_id= trx->all->id(trx->all);
+ u_int32_t stmt_id= trx->stmt->id(trx->stmt);
+
DB_TXN_ACTIVE *cur= txn_stat_ptr->st_txnarray;
DB_TXN_ACTIVE *end= cur + txn_stat_ptr->st_nactive;
for (; cur!=end && (!atxn_stmt || !atxn_all); cur++)
@@ -2222,7 +2272,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
if (cur->txnid==all_id) atxn_all= cur;
if (cur->txnid==stmt_id) atxn_stmt= cur;
}
-
+
if (atxn_stmt && atxn_all &&
log_compare(&atxn_stmt->lsn,&atxn_all->lsn))
{
@@ -2232,7 +2282,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
free(txn_stat_ptr);
}
- for (i=0 ; i < table->keys ; i++)
+ for (i=0 ; i < table->s->keys ; i++)
{
if (stat)
{
@@ -2367,14 +2417,15 @@ static BDB_SHARE *get_share(const char *table_name, TABLE *table)
char *tmp_name;
DB **key_file;
u_int32_t *key_type;
+ uint keys= table->s->keys;
if ((share=(BDB_SHARE *)
my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
&share, sizeof(*share),
- &rec_per_key, table->keys * sizeof(ha_rows),
+ &rec_per_key, keys * sizeof(ha_rows),
&tmp_name, length+1,
- &key_file, (table->keys+1) * sizeof(*key_file),
- &key_type, (table->keys+1) * sizeof(u_int32_t),
+ &key_file, (keys+1) * sizeof(*key_file),
+ &key_type, (keys+1) * sizeof(u_int32_t),
NullS)))
{
share->rec_per_key = rec_per_key;
@@ -2401,7 +2452,7 @@ static int free_share(BDB_SHARE *share, TABLE *table, uint hidden_primary_key,
bool mutex_is_locked)
{
int error, result = 0;
- uint keys=table->keys + test(hidden_primary_key);
+ uint keys= table->s->keys + test(hidden_primary_key);
pthread_mutex_lock(&bdb_mutex);
if (mutex_is_locked)
pthread_mutex_unlock(&share->mutex); /* purecov: inspected */
@@ -2465,8 +2516,8 @@ void ha_berkeley::get_status()
}
if (!(share->status & STATUS_ROW_COUNT_INIT) && share->status_block)
{
- share->org_rows=share->rows=
- table->max_rows ? table->max_rows : HA_BERKELEY_MAX_ROWS;
+ share->org_rows= share->rows=
+ table->s->max_rows ? table->s->max_rows : HA_BERKELEY_MAX_ROWS;
if (!share->status_block->cursor(share->status_block, 0, &cursor, 0))
{
DBT row;
@@ -2481,9 +2532,10 @@ void ha_berkeley::get_status()
uint i;
uchar *pos=(uchar*) row.data;
share->org_rows=share->rows=uint4korr(pos); pos+=4;
- for (i=0 ; i < table->keys ; i++)
+ for (i=0 ; i < table->s->keys ; i++)
{
- share->rec_per_key[i]=uint4korr(pos); pos+=4;
+ share->rec_per_key[i]=uint4korr(pos);
+ pos+=4;
}
}
cursor->c_close(cursor);
@@ -2541,7 +2593,7 @@ static void update_status(BDB_SHARE *share, TABLE *table)
{
char rec_buff[4+MAX_KEY*4], *pos=rec_buff;
int4store(pos,share->rows); pos+=4;
- for (uint i=0 ; i < table->keys ; i++)
+ for (uint i=0 ; i < table->s->keys ; i++)
{
int4store(pos,share->rec_per_key[i]); pos+=4;
}
@@ -2557,6 +2609,7 @@ end:
DBUG_VOID_RETURN;
}
+
/*
Return an estimated of the number of rows in the table.
Used when sorting to allocate buffers and by the optimizer.
@@ -2567,4 +2620,29 @@ ha_rows ha_berkeley::estimate_rows_upper_bound()
return share->rows + HA_BERKELEY_EXTRA_ROWS;
}
+int ha_berkeley::cmp_ref(const byte *ref1, const byte *ref2)
+{
+ if (hidden_primary_key)
+ return memcmp(ref1, ref2, BDB_HIDDEN_PRIMARY_KEY_LENGTH);
+
+ int result;
+ Field *field;
+ KEY *key_info=table->key_info+table->s->primary_key;
+ KEY_PART_INFO *key_part=key_info->key_part;
+ KEY_PART_INFO *end=key_part+key_info->key_parts;
+
+ for (; key_part != end; key_part++)
+ {
+ field= key_part->field;
+ result= field->pack_cmp((const char*)ref1, (const char*)ref2,
+ key_part->length, 0);
+ if (result)
+ return result;
+ ref1+= field->packed_col_length((const char*)ref1, key_part->length);
+ ref2+= field->packed_col_length((const char*)ref2, key_part->length);
+ }
+
+ return 0;
+}
+
#endif /* HAVE_BERKELEY_DB */
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 1d4823bbdc0..282641e3f25 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -57,7 +57,6 @@ class ha_berkeley: public handler
ulong alloced_rec_buff_length;
ulong changed_rows;
uint primary_key,last_dup_key, hidden_primary_key, version;
- u_int32_t lock_on_read;
bool key_read, using_ignore;
bool fix_rec_buff_for_blob(ulong length);
byte current_ident[BDB_HIDDEN_PRIMARY_KEY_LENGTH];
@@ -75,23 +74,17 @@ class ha_berkeley: public handler
DBT *prim_key, key_map *keys);
int restore_keys(DB_TXN *trans, key_map *changed_keys, uint primary_key,
const byte *old_row, DBT *old_key,
- const byte *new_row, DBT *new_key,
- ulong thd_options);
+ const byte *new_row, DBT *new_key);
int key_cmp(uint keynr, const byte * old_row, const byte * new_row);
int update_primary_key(DB_TXN *trans, bool primary_key_changed,
const byte * old_row, DBT *old_key,
const byte * new_row, DBT *prim_key,
- ulong thd_options, bool local_using_ignore);
+ bool local_using_ignore);
int read_row(int error, char *buf, uint keynr, DBT *row, DBT *key, bool);
DBT *get_pos(DBT *to, byte *pos);
public:
- ha_berkeley(TABLE *table): handler(table), alloc_ptr(0),rec_buff(0), file(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(TABLE *table_arg);
~ha_berkeley() {}
const char *table_type() const { return "BerkeleyDB"; }
ulong index_flags(uint idx, uint part, bool all_parts) const;
@@ -153,9 +146,11 @@ class ha_berkeley: public handler
int5store(to,share->auto_ident);
pthread_mutex_unlock(&share->mutex);
}
- longlong get_auto_increment();
+ ulonglong get_auto_increment();
void print_error(int error, myf errflag);
uint8 table_cache_type() { return HA_CACHE_TBL_TRANSACT; }
+ bool primary_key_is_clustered() { return true; }
+ int cmp_ref(const byte *ref1, const byte *ref2);
};
extern bool berkeley_shared_data;
@@ -166,9 +161,7 @@ extern char *berkeley_home, *berkeley_tmpdir, *berkeley_logdir;
extern long berkeley_lock_scan_time;
extern TYPELIB berkeley_lock_typelib;
-bool berkeley_init(void);
+handlerton *berkeley_init(void);
bool berkeley_end(void);
bool berkeley_flush_logs(void);
-int berkeley_commit(THD *thd, void *trans);
-int berkeley_rollback(THD *thd, void *trans);
int berkeley_show_logs(Protocol *protocol);
diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc
index 9ac4ba2da15..a287d6e446b 100644
--- a/sql/ha_blackhole.cc
+++ b/sql/ha_blackhole.cc
@@ -24,10 +24,44 @@
#include "ha_blackhole.h"
+/* Blackhole storage engine handlerton */
+
+static handlerton blackhole_hton= {
+ "BLACKHOLE",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
+/*****************************************************************************
+** BLACKHOLE tables
+*****************************************************************************/
+
+ha_blackhole::ha_blackhole(TABLE *table_arg)
+ :handler(&blackhole_hton, table_arg)
+{}
+
+
+static const char *ha_blackhole_exts[] = {
+ NullS
+};
+
const char **ha_blackhole::bas_ext() const
-{
- static const char *ext[]= { NullS };
- return ext;
+{
+ return ha_blackhole_exts;
}
int ha_blackhole::open(const char *name, int mode, uint test_if_locked)
diff --git a/sql/ha_blackhole.h b/sql/ha_blackhole.h
index 88715c62408..7238147a06a 100644
--- a/sql/ha_blackhole.h
+++ b/sql/ha_blackhole.h
@@ -28,9 +28,7 @@ class ha_blackhole: public handler
THR_LOCK thr_lock;
public:
- ha_blackhole(TABLE *table): handler(table)
- {
- }
+ ha_blackhole(TABLE *table_arg);
~ha_blackhole()
{
}
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
new file mode 100644
index 00000000000..2590e7881a4
--- /dev/null
+++ b/sql/ha_federated.cc
@@ -0,0 +1,2652 @@
+/* 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 */
+
+/*
+
+ MySQL Federated Storage Engine
+
+ ha_federated.cc - MySQL Federated Storage Engine
+ Patrick Galbraith and Brian Aker, 2004
+
+ This is a handler which uses a foreign database as the data file, as
+ opposed to a handler like MyISAM, which uses .MYD files locally.
+
+ How this handler works
+ ----------------------------------
+ Normal database files are local and as such: You create a table called
+ 'users', a file such as 'users.MYD' is created. A handler reads, inserts,
+ deletes, updates data in this file. The data is stored in particular format,
+ so to read, that data has to be parsed into fields, to write, fields have to
+ be stored in this format to write to this data file.
+
+ With MySQL Federated storage engine, there will be no local files for each
+ table's data (such as .MYD). A foreign database will store the data that would
+ normally be in this file. This will necessitate the use of MySQL client API
+ to read, delete, update, insert this data. The data will have to be retrieve
+ via an SQL call "SELECT * FROM users". Then, to read this data, it will have
+ to be retrieved via mysql_fetch_row one row at a time, then converted from
+ the column in this select into the format that the handler expects.
+
+ The create table will simply create the .frm file, and within the
+ "CREATE TABLE" SQL, there SHALL be any of the following :
+
+ comment=scheme://username:password@hostname:port/database/tablename
+ comment=scheme://username@hostname/database/tablename
+ comment=scheme://username:password@hostname/database/tablename
+ comment=scheme://username:password@hostname/database/tablename
+
+ An example would be:
+
+ comment=mysql://username:password@hostname:port/database/tablename
+
+ ***IMPORTANT***
+
+ This is a first release, conceptual release
+ Only 'mysql://' is supported at this release.
+
+
+ This comment connection string is necessary for the handler to be
+ able to connect to the foreign server.
+
+
+ The basic flow is this:
+
+ SQL calls issues locally ->
+ mysql handler API (data in handler format) ->
+ mysql client API (data converted to SQL calls) ->
+ foreign database -> mysql client API ->
+ convert result sets (if any) to handler format ->
+ handler API -> results or rows affected to local
+
+ What this handler does and doesn't support
+ ------------------------------------------
+ * Tables MUST be created on the foreign server prior to any action on those
+ tables via the handler, first version. IMPORTANT: IF you MUST use the
+ federated storage engine type on the REMOTE end, MAKE SURE [ :) ] That
+ the table you connect to IS NOT a table pointing BACK to your ORIGNAL
+ table! You know and have heard the screaching of audio feedback? You
+ know putting two mirror in front of each other how the reflection
+ continues for eternity? Well, need I say more?!
+ * There will not be support for transactions.
+ * There is no way for the handler to know if the foreign database or table
+ has changed. The reason for this is that this database has to work like a
+ data file that would never be written to by anything other than the
+ database. The integrity of the data in the local table could be breached
+ if there was any change to the foreign database.
+ * Support for SELECT, INSERT, UPDATE , DELETE, indexes.
+ * No ALTER TABLE, DROP TABLE or any other Data Definition Language calls.
+ * Prepared statements will not be used in the first implementation, it
+ remains to to be seen whether the limited subset of the client API for the
+ server supports this.
+ * This uses SELECT, INSERT, UPDATE, DELETE and not HANDLER for its
+ implementation.
+ * This will not work with the query cache.
+
+ Method calls
+
+ A two column table, with one record:
+
+ (SELECT)
+
+ "SELECT * FROM foo"
+ ha_federated::info
+ ha_federated::scan_time:
+ ha_federated::rnd_init: share->select_query SELECT * FROM foo
+ ha_federated::extra
+
+ <for every row of data retrieved>
+ ha_federated::rnd_next
+ ha_federated::convert_row_to_internal_format
+ ha_federated::rnd_next
+ </for every row of data retrieved>
+
+ ha_federated::rnd_end
+ ha_federated::extra
+ ha_federated::reset
+
+ (INSERT)
+
+ "INSERT INTO foo (id, ts) VALUES (2, now());"
+
+ ha_federated::write_row
+
+ <for every field/column>
+ Field::quote_data
+ Field::quote_data
+ </for every field/column>
+
+ ha_federated::reset
+
+ (UPDATE)
+
+ "UPDATE foo SET ts = now() WHERE id = 1;"
+
+ ha_federated::index_init
+ ha_federated::index_read
+ ha_federated::index_read_idx
+ Field::quote_data
+ ha_federated::rnd_next
+ ha_federated::convert_row_to_internal_format
+ ha_federated::update_row
+
+ <quote 3 cols, new and old data>
+ Field::quote_data
+ Field::quote_data
+ Field::quote_data
+ Field::quote_data
+ Field::quote_data
+ Field::quote_data
+ </quote 3 cols, new and old data>
+
+ ha_federated::extra
+ ha_federated::extra
+ ha_federated::extra
+ ha_federated::external_lock
+ ha_federated::reset
+
+
+ How do I use this handler?
+ --------------------------
+ First of all, you need to build this storage engine:
+
+ ./configure --with-federated-storage-engine
+ make
+
+ Next, to use this handler, it's very simple. You must
+ have two databases running, either both on the same host, or
+ on different hosts.
+
+ One the server that will be connecting to the foreign
+ host (client), you create your table as such:
+
+ CREATE TABLE test_table (
+ id int(20) NOT NULL auto_increment,
+ name varchar(32) NOT NULL default '',
+ other int(20) NOT NULL default '0',
+ PRIMARY KEY (id),
+ KEY name (name),
+ KEY other_key (other))
+ ENGINE="FEDERATED"
+ DEFAULT CHARSET=latin1
+ COMMENT='root@127.0.0.1:9306/federated/test_federated';
+
+ Notice the "COMMENT" and "ENGINE" field? This is where you
+ respectively set the engine type, "FEDERATED" and foreign
+ host information, this being the database your 'client' database
+ will connect to and use as the "data file". Obviously, the foreign
+ database is running on port 9306, so you want to start up your other
+ database so that it is indeed on port 9306, and your federated
+ database on a port other than that. In my setup, I use port 5554
+ for federated, and port 5555 for the foreign database.
+
+ Then, on the foreign database:
+
+ CREATE TABLE test_table (
+ id int(20) NOT NULL auto_increment,
+ name varchar(32) NOT NULL default '',
+ other int(20) NOT NULL default '0',
+ PRIMARY KEY (id),
+ KEY name (name),
+ KEY other_key (other))
+ ENGINE="<NAME>" <-- whatever you want, or not specify
+ DEFAULT CHARSET=latin1 ;
+
+ This table is exactly the same (and must be exactly the same),
+ except that it is not using the federated handler and does
+ not need the URL.
+
+
+ How to see the handler in action
+ --------------------------------
+
+ When developing this handler, I compiled the federated database with
+ debugging:
+
+ ./configure --with-federated-storage-engine
+ --prefix=/home/mysql/mysql-build/federated/ --with-debug
+
+ Once compiled, I did a 'make install' (not for the purpose of installing
+ the binary, but to install all the files the binary expects to see in the
+ diretory I specified in the build with --prefix,
+ "/home/mysql/mysql-build/federated".
+
+ Then, I started the foreign server:
+
+ /usr/local/mysql/bin/mysqld_safe
+ --user=mysql --log=/tmp/mysqld.5555.log -P 5555
+
+ Then, I went back to the directory containing the newly compiled mysqld,
+ <builddir>/sql/, started up gdb:
+
+ gdb ./mysqld
+
+ Then, withn the (gdb) prompt:
+ (gdb) run --gdb --port=5554 --socket=/tmp/mysqld.5554 --skip-innodb --debug
+
+ Next, I open several windows for each:
+
+ 1. Tail the debug trace: tail -f /tmp/mysqld.trace|grep ha_fed
+ 2. Tail the SQL calls to the foreign database: tail -f /tmp/mysqld.5555.log
+ 3. A window with a client open to the federated server on port 5554
+ 4. A window with a client open to the federated server on port 5555
+
+ I would create a table on the client to the foreign server on port
+ 5555, and then to the federated server on port 5554. At this point,
+ I would run whatever queries I wanted to on the federated server,
+ just always remembering that whatever changes I wanted to make on
+ the table, or if I created new tables, that I would have to do that
+ on the foreign server.
+
+ Another thing to look for is 'show variables' to show you that you have
+ support for federated handler support:
+
+ show variables like '%federat%'
+
+ and:
+
+ show storage engines;
+
+ Both should display the federated storage handler.
+
+
+ Testing
+ -------
+
+ There is a test for MySQL Federated Storage Handler in ./mysql-test/t,
+ federatedd.test It starts both a slave and master database using
+ the same setup that the replication tests use, with the exception that
+ it turns off replication, and sets replication to ignore the test tables.
+ After ensuring that you actually do have support for the federated storage
+ handler, numerous queries/inserts/updates/deletes are run, many derived
+ from the MyISAM tests, plus som other tests which were meant to reveal
+ any issues that would be most likely to affect this handler. All tests
+ should work! ;)
+
+ To run these tests, go into ./mysql-test (based in the directory you
+ built the server in)
+
+ ./mysql-test-run federatedd
+
+ To run the test, or if you want to run the test and have debug info:
+
+ ./mysql-test-run --debug federated
+
+ This will run the test in debug mode, and you can view the trace and
+ log files in the ./mysql-test/var/log directory
+
+ ls -l mysql-test/var/log/
+ -rw-r--r-- 1 patg patg 17 4 Dec 12:27 current_test
+ -rw-r--r-- 1 patg patg 692 4 Dec 12:52 manager.log
+ -rw-rw---- 1 patg patg 21246 4 Dec 12:51 master-bin.000001
+ -rw-rw---- 1 patg patg 68 4 Dec 12:28 master-bin.index
+ -rw-r--r-- 1 patg patg 1620 4 Dec 12:51 master.err
+ -rw-rw---- 1 patg patg 23179 4 Dec 12:51 master.log
+ -rw-rw---- 1 patg patg 16696550 4 Dec 12:51 master.trace
+ -rw-r--r-- 1 patg patg 0 4 Dec 12:28 mysqltest-time
+ -rw-r--r-- 1 patg patg 2024051 4 Dec 12:51 mysqltest.trace
+ -rw-rw---- 1 patg patg 94992 4 Dec 12:51 slave-bin.000001
+ -rw-rw---- 1 patg patg 67 4 Dec 12:28 slave-bin.index
+ -rw-rw---- 1 patg patg 249 4 Dec 12:52 slave-relay-bin.000003
+ -rw-rw---- 1 patg patg 73 4 Dec 12:28 slave-relay-bin.index
+ -rw-r--r-- 1 patg patg 1349 4 Dec 12:51 slave.err
+ -rw-rw---- 1 patg patg 96206 4 Dec 12:52 slave.log
+ -rw-rw---- 1 patg patg 15706355 4 Dec 12:51 slave.trace
+ -rw-r--r-- 1 patg patg 0 4 Dec 12:51 warnings
+
+ Of course, again, you can tail the trace log:
+
+ tail -f mysql-test/var/log/master.trace |grep ha_fed
+
+ As well as the slave query log:
+
+ tail -f mysql-test/var/log/slave.log
+
+ Files that comprise the test suit
+ ---------------------------------
+ mysql-test/t/federated.test
+ mysql-test/r/federated.result
+ mysql-test/r/have_federated_db.require
+ mysql-test/include/have_federated_db.inc
+
+
+ Other tidbits
+ -------------
+
+ These were the files that were modified or created for this
+ Federated handler to work:
+
+ ./configure.in
+ ./sql/Makefile.am
+ ./config/ac_macros/ha_federated.m4
+ ./sql/handler.cc
+ ./sql/mysqld.cc
+ ./sql/set_var.cc
+ ./sql/field.h
+ ./sql/sql_string.h
+ ./mysql-test/mysql-test-run(.sh)
+ ./mysql-test/t/federated.test
+ ./mysql-test/r/federated.result
+ ./mysql-test/r/have_federated_db.require
+ ./mysql-test/include/have_federated_db.inc
+ ./sql/ha_federated.cc
+ ./sql/ha_federated.h
+
+*/
+
+#include "mysql_priv.h"
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+#ifdef HAVE_FEDERATED_DB
+#include "ha_federated.h"
+
+#include "m_string.h"
+/* Variables for federated share methods */
+static HASH federated_open_tables; // Hash used to track open
+ // tables
+pthread_mutex_t federated_mutex; // This is the mutex we use to
+ // init the hash
+static int federated_init= FALSE; // Variable for checking the
+ // init state of hash
+
+/* Function we use in the creation of our hash to get key. */
+
+static byte *federated_get_key(FEDERATED_SHARE *share, uint *length,
+ my_bool not_used __attribute__ ((unused)))
+{
+ *length= share->table_name_length;
+ return (byte*) share->table_name;
+}
+
+/*
+ Initialize the federated handler.
+
+ SYNOPSIS
+ federated_db_init()
+ void
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+bool federated_db_init()
+{
+ federated_init= 1;
+ VOID(pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST));
+ return (hash_init(&federated_open_tables, system_charset_info, 32, 0, 0,
+ (hash_get_key) federated_get_key, 0, 0));
+}
+
+
+/*
+ Release the federated handler.
+
+ SYNOPSIS
+ federated_db_end()
+ void
+
+ RETURN
+ FALSE OK
+*/
+
+bool federated_db_end()
+{
+ if (federated_init)
+ {
+ hash_free(&federated_open_tables);
+ VOID(pthread_mutex_destroy(&federated_mutex));
+ }
+ federated_init= 0;
+ return FALSE;
+}
+
+/*
+ Check (in create) whether the tables exists, and that it can be connected to
+
+ SYNOPSIS
+ check_foreign_data_source()
+ share pointer to FEDERATED share
+ table_create_flag tells us that ::create is the caller,
+ therefore, return CANT_CREATE_FEDERATED_TABLE
+
+ DESCRIPTION
+ This method first checks that the connection information that parse url
+ has populated into the share will be sufficient to connect to the foreign
+ table, and if so, does the foreign table exist.
+*/
+
+static int check_foreign_data_source(
+ FEDERATED_SHARE *share,
+ bool table_create_flag)
+{
+ char escaped_table_name[NAME_LEN*2];
+ char query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ uint error_code;
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ MYSQL *mysql;
+ DBUG_ENTER("ha_federated::check_foreign_data_source");
+ /* Zero the length, otherwise the string will have misc chars */
+ query.length(0);
+
+ /* error out if we can't alloc memory for mysql_init(NULL) (per Georg) */
+ if (!(mysql= mysql_init(NULL)))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ /* check if we can connect */
+ if (!mysql_real_connect(mysql,
+ share->hostname,
+ share->username,
+ share->password,
+ share->database,
+ share->port,
+ share->socket, 0))
+ {
+ /*
+ we want the correct error message, but it to return
+ ER_CANT_CREATE_FEDERATED_TABLE if called by ::create
+ */
+ error_code= table_create_flag?
+ ER_CANT_CREATE_FEDERATED_TABLE : ER_CONNECT_TO_FOREIGN_DATA_SOURCE;
+
+ my_sprintf(error_buffer,
+ (error_buffer, " database %s username %s hostname %s",
+ share->database, share->username, share->hostname));
+
+ my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), error_buffer);
+ goto error;
+ }
+ else
+ {
+ /*
+ Since we do not support transactions at this version, we can let the
+ client API silently reconnect. For future versions, we will need more
+ logic to deal with transactions
+ */
+ mysql->reconnect= 1;
+ /*
+ Note: I am not using INORMATION_SCHEMA because this needs to work with
+ versions prior to 5.0
+
+ if we can connect, then make sure the table exists
+
+ the query will be: SELECT * FROM `tablename` WHERE 1=0
+ */
+ query.append(FEDERATED_SELECT);
+ query.append(FEDERATED_STAR);
+ query.append(FEDERATED_FROM);
+ query.append(FEDERATED_BTICK);
+ escape_string_for_mysql(&my_charset_bin, (char *)escaped_table_name,
+ sizeof(escaped_table_name),
+ share->table_name,
+ share->table_name_length);
+ query.append(escaped_table_name);
+ query.append(FEDERATED_BTICK);
+ query.append(FEDERATED_WHERE);
+ query.append(FEDERATED_FALSE);
+
+ DBUG_PRINT("info", ("check_foreign_data_source query %s",
+ query.c_ptr_quick()));
+ if (mysql_real_query(mysql, query.ptr(), query.length()))
+ {
+ error_code= table_create_flag ?
+ ER_CANT_CREATE_FEDERATED_TABLE : ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST;
+ my_sprintf(error_buffer, (error_buffer, ": %d : %s",
+ mysql_errno(mysql), mysql_error(mysql)));
+
+ my_error(error_code, MYF(0), error_buffer);
+ goto error;
+ }
+ }
+ error_code=0;
+
+error:
+ mysql_close(mysql);
+ DBUG_RETURN(error_code);
+}
+
+
+static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num)
+{
+ char buf[FEDERATED_QUERY_BUFFER_SIZE];
+ int buf_len;
+ DBUG_ENTER("ha_federated parse_url_error");
+ if (share->scheme)
+ {
+ DBUG_PRINT("info",
+ ("error: parse_url. Returning error code %d \
+ freeing share->scheme %lx", error_num, share->scheme));
+ my_free((gptr) share->scheme, MYF(0));
+ share->scheme= 0;
+ }
+ buf_len= (table->s->connect_string.length > (FEDERATED_QUERY_BUFFER_SIZE - 1))
+ ? FEDERATED_QUERY_BUFFER_SIZE - 1 : table->s->connect_string.length;
+
+ strnmov(buf, table->s->connect_string.str, buf_len);
+ buf[buf_len]= '\0';
+ my_error(error_num, MYF(0), buf);
+ DBUG_RETURN(error_num);
+}
+
+/*
+ Parse connection info from table->s->connect_string
+
+ SYNOPSIS
+ parse_url()
+ share pointer to FEDERATED share
+ table pointer to current TABLE class
+ table_create_flag determines what error to throw
+
+ DESCRIPTION
+ populates the share with information about the connection
+ to the foreign database that will serve as the data source.
+ This string must be specified (currently) in the "comment" field,
+ listed in the CREATE TABLE statement.
+
+ This string MUST be in the format of any of these:
+
+ scheme://username:password@hostname:port/database/table
+ scheme://username@hostname/database/table
+ scheme://username@hostname:port/database/table
+ scheme://username:password@hostname/database/table
+
+ An Example:
+
+ mysql://joe:joespass@192.168.1.111:9308/federated/testtable
+
+ ***IMPORTANT***
+ Currently, only "mysql://" is supported.
+
+ 'password' and 'port' are both optional.
+
+ RETURN VALUE
+ 0 success
+ error_num particular error code
+
+*/
+
+static int parse_url(FEDERATED_SHARE *share, TABLE *table,
+ uint table_create_flag)
+{
+ uint error_num= (table_create_flag ?
+ ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE :
+ ER_FOREIGN_DATA_STRING_INVALID);
+ DBUG_ENTER("ha_federated::parse_url");
+
+ share->port= 0;
+ DBUG_PRINT("info", ("Length %d \n", table->s->connect_string.length));
+ DBUG_PRINT("info", ("String %.*s \n", table->s->connect_string.length,
+ table->s->connect_string.str));
+ share->scheme= my_strdup_with_length(table->s->connect_string.str,
+ table->s->connect_string.length+1,
+ MYF(0));
+ // Add a null for later termination of table name
+ share->scheme[table->s->connect_string.length]= 0;
+ DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme));
+
+ /*
+ remove addition of null terminator and store length
+ for each string in share
+ */
+ if (!(share->username= strstr(share->scheme, "://")))
+ goto error;
+ share->scheme[share->username - share->scheme]= '\0';
+
+ if (strcmp(share->scheme, "mysql") != 0)
+ goto error;
+
+ share->username+= 3;
+
+ if (!(share->hostname= strchr(share->username, '@')))
+ goto error;
+
+ share->username[share->hostname - share->username]= '\0';
+ share->hostname++;
+
+ if ((share->password= strchr(share->username, ':')))
+ {
+ share->username[share->password - share->username]= '\0';
+ share->password++;
+ share->username= share->username;
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->password, '/') || strchr(share->hostname, '@')))
+ goto error;
+ /*
+ Found that if the string is:
+ user:@hostname:port/database/table
+ Then password is a null string, so set to NULL
+ */
+ if ((share->password[0] == '\0'))
+ share->password= NULL;
+ }
+ else
+ share->username= share->username;
+
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
+ goto error;
+
+ if (!(share->database= strchr(share->hostname, '/')))
+ goto error;
+ share->hostname[share->database - share->hostname]= '\0';
+ share->database++;
+
+ if ((share->sport= strchr(share->hostname, ':')))
+ {
+ share->hostname[share->sport - share->hostname]= '\0';
+ share->sport++;
+ if (share->sport[0] == '\0')
+ share->sport= NULL;
+ else
+ share->port= atoi(share->sport);
+ }
+
+ if (!(share->table_name= strchr(share->database, '/')))
+ goto error;
+ share->database[share->table_name - share->database]= '\0';
+ share->table_name++;
+
+ share->table_name_length= strlen(share->table_name);
+
+ /* make sure there's not an extra / */
+ if ((strchr(share->table_name, '/')))
+ goto error;
+
+ if (share->hostname[0] == '\0')
+ share->hostname= NULL;
+
+ if (!share->port)
+ {
+ if (strcmp(share->hostname, my_localhost) == 0)
+ share->socket= my_strdup(MYSQL_UNIX_ADDR, MYF(0));
+ else
+ share->port= MYSQL_PORT;
+ }
+
+ DBUG_PRINT("info",
+ ("scheme %s username %s password %s \
+ hostname %s port %d database %s tablename %s\n",
+ share->scheme, share->username, share->password,
+ share->hostname, share->port, share->database,
+ share->table_name));
+
+ DBUG_RETURN(0);
+
+error:
+ DBUG_RETURN(parse_url_error(share, table, error_num));
+}
+
+
+/* Federated storage engine handlerton */
+
+static handlerton federated_hton= {
+ "FEDERATED",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
+
+/*****************************************************************************
+** FEDERATED tables
+*****************************************************************************/
+
+ha_federated::ha_federated(TABLE *table_arg)
+ :handler(&federated_hton, table_arg),
+ mysql(0), stored_result(0), scan_flag(0),
+ ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
+{}
+
+
+/*
+ Convert MySQL result set row to handler internal format
+
+ SYNOPSIS
+ convert_row_to_internal_format()
+ record Byte pointer to record
+ row MySQL result set row from fetchrow()
+
+ DESCRIPTION
+ This method simply iterates through a row returned via fetchrow with
+ values from a successful SELECT , and then stores each column's value
+ in the field object via the field object pointer (pointing to the table's
+ array of field object pointers). This is how the handler needs the data
+ to be stored to then return results back to the user
+
+ RETURN VALUE
+ 0 After fields have had field values stored from record
+ */
+
+uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row)
+{
+ ulong *lengths;
+ Field **field;
+
+ DBUG_ENTER("ha_federated::convert_row_to_internal_format");
+
+ // num_fields= mysql_num_fields(stored_result);
+ lengths= mysql_fetch_lengths(stored_result);
+
+ memset(record, 0, table->s->null_bytes);
+
+ for (field= table->field; *field; field++)
+ {
+ /*
+ index variable to move us through the row at the
+ same iterative step as the field
+ */
+ int x= field - table->field;
+ my_ptrdiff_t old_ptr;
+ old_ptr= (my_ptrdiff_t) (record - table->record[0]);
+ (*field)->move_field(old_ptr);
+ if (!row[x])
+ (*field)->set_null();
+ else
+ {
+ (*field)->set_notnull();
+ (*field)->store(row[x], lengths[x], &my_charset_bin);
+ }
+ (*field)->move_field(-old_ptr);
+ }
+
+ DBUG_RETURN(0);
+}
+
+static bool emit_key_part_name(String *to, KEY_PART_INFO *part)
+{
+ DBUG_ENTER("emit_key_part_name");
+ if (to->append(FEDERATED_BTICK) ||
+ to->append(part->field->field_name) ||
+ to->append(FEDERATED_BTICK))
+ DBUG_RETURN(1); // Out of memory
+ DBUG_RETURN(0);
+}
+
+static bool emit_key_part_element(String *to, KEY_PART_INFO *part,
+ bool needs_quotes, bool is_like,
+ const byte *ptr, uint len)
+{
+ Field *field= part->field;
+ DBUG_ENTER("emit_key_part_element");
+
+ if (needs_quotes && to->append(FEDERATED_SQUOTE))
+ DBUG_RETURN(1);
+
+ if (part->type == HA_KEYTYPE_BIT)
+ {
+ char buff[STRING_BUFFER_USUAL_SIZE], *buf= buff;
+
+ *buf++= '0';
+ *buf++= 'x';
+ for (; len; ptr++,len--)
+ {
+ uint tmp= (uint)(uchar) *ptr;
+ *buf++= _dig_vec_upper[tmp >> 4];
+ *buf++= _dig_vec_upper[tmp & 15];
+ }
+ if (to->append(buff, (uint)(buf - buff)))
+ DBUG_RETURN(1);
+ }
+ else if (part->key_part_flag & HA_BLOB_PART)
+ {
+ String blob;
+ uint blob_length= uint2korr(ptr);
+ blob.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
+ blob_length, &my_charset_bin);
+ if (append_escaped(to, &blob))
+ DBUG_RETURN(1);
+ }
+ else if (part->key_part_flag & HA_VAR_LENGTH_PART)
+ {
+ String varchar;
+ uint var_length= uint2korr(ptr);
+ varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH,
+ var_length, &my_charset_bin);
+ if (append_escaped(to, &varchar))
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ char strbuff[MAX_FIELD_WIDTH];
+ String str(strbuff, sizeof(strbuff), part->field->charset()), *res;
+
+ res= field->val_str(&str, (char *)ptr);
+
+ if (field->result_type() == STRING_RESULT)
+ {
+ if (append_escaped(to, res))
+ DBUG_RETURN(1);
+ }
+ else if (to->append(res->ptr(), res->length()))
+ DBUG_RETURN(1);
+ }
+
+ if (is_like && to->append(FEDERATED_PERCENT))
+ DBUG_RETURN(1);
+
+ if (needs_quotes && to->append(FEDERATED_SQUOTE))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Create a WHERE clause based off of values in keys
+ Note: This code was inspired by key_copy from key.cc
+
+ SYNOPSIS
+ create_where_from_key ()
+ to String object to store WHERE clause
+ key_info KEY struct pointer
+ key byte pointer containing key
+ key_length length of key
+ range_type 0 - no range, 1 - min range, 2 - max range
+ (see enum range_operation)
+
+ DESCRIPTION
+ Using iteration through all the keys via a KEY_PART_INFO pointer,
+ This method 'extracts' the value of each key in the byte pointer
+ *key, and for each key found, constructs an appropriate WHERE clause
+
+ RETURN VALUE
+ 0 After all keys have been accounted for to create the WHERE clause
+ 1 No keys found
+
+ Range flags Table per Timour:
+
+ -----------------
+ - start_key:
+ * ">" -> HA_READ_AFTER_KEY
+ * ">=" -> HA_READ_KEY_OR_NEXT
+ * "=" -> HA_READ_KEY_EXACT
+
+ - end_key:
+ * "<" -> HA_READ_BEFORE_KEY
+ * "<=" -> HA_READ_AFTER_KEY
+
+ records_in_range:
+ -----------------
+ - start_key:
+ * ">" -> HA_READ_AFTER_KEY
+ * ">=" -> HA_READ_KEY_EXACT
+ * "=" -> HA_READ_KEY_EXACT
+
+ - end_key:
+ * "<" -> HA_READ_BEFORE_KEY
+ * "<=" -> HA_READ_AFTER_KEY
+ * "=" -> HA_READ_AFTER_KEY
+
+0 HA_READ_KEY_EXACT, Find first record else error
+1 HA_READ_KEY_OR_NEXT, Record or next record
+2 HA_READ_KEY_OR_PREV, Record or previous
+3 HA_READ_AFTER_KEY, Find next rec. after key-record
+4 HA_READ_BEFORE_KEY, Find next rec. before key-record
+5 HA_READ_PREFIX, Key which as same prefix
+6 HA_READ_PREFIX_LAST, Last key with the same prefix
+7 HA_READ_PREFIX_LAST_OR_PREV, Last or prev key with the same prefix
+
+Flags that I've found:
+
+id, primary key, varchar
+
+id = 'ccccc'
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 0 end_key NULL
+
+id > 'ccccc'
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id < 'ccccc'
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 'ccccc'
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id >= 'ccccc'
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id like 'cc%cc'
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 'aaaaa' and id < 'ccccc'
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 'aaaaa' and id < 'ccccc';
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 'aaaaa' and id <= 'ccccc';
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 'aaaaa' and id <= 'ccccc';
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+numeric keys:
+
+id = 4
+index_read_idx: start_key 0 end_key NULL
+
+id > 4
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id >= 4
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id < 4
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 4
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id like 4
+full table scan, select * from
+
+id > 2 and id < 8
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 2 and id < 8
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 2 and id <= 8
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 2 and id <= 8
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+multi keys (id int, name varchar, other varchar)
+
+id = 1;
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 0 end_key NULL
+
+id > 4;
+id > 2 and name = '333'; remote: id > 2
+id > 2 and name > '333'; remote: id > 2
+id > 2 and name > '333' and other < 'ddd'; remote: id > 2 no results
+id > 2 and name >= '333' and other < 'ddd'; remote: id > 2 1 result
+id >= 4 and name = 'eric was here' and other > 'eeee';
+records_in_range: start_key 3 end_key NULL
+read_range_first: start_key 3 end_key NULL
+
+id >= 4;
+id >= 2 and name = '333' and other < 'ddd';
+remote: `id` >= 2 AND `name` >= '333';
+records_in_range: start_key 0 end_key NULL
+read_range_first: start_key 1 end_key NULL
+
+id < 4;
+id < 3 and name = '222' and other <= 'ccc'; remote: id < 3
+records_in_range: start_key NULL end_key 4
+read_range_first: start_key NULL end_key 4
+
+id <= 4;
+records_in_range: start_key NULL end_key 3
+read_range_first: start_key NULL end_key 3
+
+id like 4;
+full table scan
+
+id > 2 and id < 4;
+records_in_range: start_key 3 end_key 4
+read_range_first: start_key 3 end_key 4
+
+id >= 2 and id < 4;
+records_in_range: start_key 0 end_key 4
+read_range_first: start_key 1 end_key 4
+
+id >= 2 and id <= 4;
+records_in_range: start_key 0 end_key 3
+read_range_first: start_key 1 end_key 3
+
+id > 2 and id <= 4;
+id = 6 and name = 'eric was here' and other > 'eeee';
+remote: (`id` > 6 AND `name` > 'eric was here' AND `other` > 'eeee')
+AND (`id` <= 6) AND ( AND `name` <= 'eric was here')
+no results
+records_in_range: start_key 3 end_key 3
+read_range_first: start_key 3 end_key 3
+
+Summary:
+
+* If the start key flag is 0 the max key flag shouldn't even be set,
+ and if it is, the query produced would be invalid.
+* Multipart keys, even if containing some or all numeric columns,
+ are treated the same as non-numeric keys
+
+ If the query is " = " (quotes or not):
+ - records in range start key flag HA_READ_KEY_EXACT,
+ end key flag HA_READ_AFTER_KEY (incorrect)
+ - any other: start key flag HA_READ_KEY_OR_NEXT,
+ end key flag HA_READ_AFTER_KEY (correct)
+
+* 'like' queries (of key)
+ - Numeric, full table scan
+ - Non-numeric
+ records_in_range: start_key 0 end_key 3
+ other : start_key 1 end_key 3
+
+* If the key flag is HA_READ_AFTER_KEY:
+ if start_key, append >
+ if end_key, append <=
+
+* If create_where_key was called by records_in_range:
+
+ - if the key is numeric:
+ start key flag is 0 when end key is NULL, end key flag is 3 or 4
+ - if create_where_key was called by any other function:
+ start key flag is 1 when end key is NULL, end key flag is 3 or 4
+ - if the key is non-numeric, or multipart
+ When the query is an exact match, the start key flag is 0,
+ end key flag is 3 for what should be a no-range condition where
+ you should have 0 and max key NULL, which it is if called by
+ read_range_first
+
+Conclusion:
+
+1. Need logic to determin if a key is min or max when the flag is
+HA_READ_AFTER_KEY, and handle appending correct operator accordingly
+
+2. Need a boolean flag to pass to create_where_from_key, used in the
+switch statement. Add 1 to the flag if:
+ - start key flag is HA_READ_KEY_EXACT and the end key is NULL
+
+*/
+
+bool ha_federated::create_where_from_key(String *to,
+ KEY *key_info,
+ const key_range *start_key,
+ const key_range *end_key,
+ bool records_in_range)
+{
+ bool both_not_null=
+ (start_key != NULL && end_key != NULL) ? TRUE : FALSE;
+ const byte *ptr;
+ uint remainder, length;
+ char tmpbuff[FEDERATED_QUERY_BUFFER_SIZE];
+ String tmp(tmpbuff, sizeof(tmpbuff), system_charset_info);
+ const key_range *ranges[2]= { start_key, end_key };
+
+ DBUG_ENTER("ha_federated::create_where_from_key");
+ tmp.length(0);
+ if (start_key == NULL && end_key == NULL)
+ DBUG_RETURN(1);
+
+ for (int i= 0; i <= 1; i++)
+ {
+ bool needs_quotes;
+ KEY_PART_INFO *key_part;
+ if (ranges[i] == NULL)
+ continue;
+
+ if (both_not_null)
+ {
+ if (i > 0)
+ tmp.append(FEDERATED_CONJUNCTION);
+ else
+ tmp.append(FEDERATED_OPENPAREN);
+ }
+
+ for (key_part= key_info->key_part,
+ remainder= key_info->key_parts,
+ length= ranges[i]->length,
+ ptr= ranges[i]->key; ;
+ remainder--,
+ key_part++)
+ {
+ Field *field= key_part->field;
+ uint store_length= key_part->store_length;
+ uint part_length= min(store_length, length);
+ needs_quotes= field->needs_quotes();
+ DBUG_DUMP("key, start of loop", (char *) ptr, length);
+
+ if (key_part->null_bit)
+ {
+ if (*ptr++)
+ {
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(FEDERATED_ISNULL))
+ DBUG_RETURN(1);
+ continue;
+ }
+ }
+
+ if (tmp.append(FEDERATED_OPENPAREN))
+ DBUG_RETURN(1);
+
+ switch(ranges[i]->flag) {
+ case(HA_READ_KEY_EXACT):
+ if (store_length >= length ||
+ !needs_quotes ||
+ key_part->type == HA_KEYTYPE_BIT ||
+ field->result_type() != STRING_RESULT)
+ {
+ if (emit_key_part_name(&tmp, key_part))
+ DBUG_RETURN(1);
+
+ if (records_in_range)
+ {
+ if (tmp.append(FEDERATED_GE))
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ if (tmp.append(FEDERATED_EQ))
+ DBUG_RETURN(1);
+ }
+
+ if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ DBUG_RETURN(1);
+ }
+ else
+ /* LIKE */
+ {
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(FEDERATED_LIKE) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 1, ptr,
+ part_length))
+ DBUG_RETURN(1);
+ }
+ break;
+ case(HA_READ_AFTER_KEY):
+ if (store_length >= length) /* end key */
+ {
+ if (emit_key_part_name(&tmp, key_part))
+ DBUG_RETURN(1);
+
+ if (i > 0) /* end key */
+ {
+ if (tmp.append(FEDERATED_LE))
+ DBUG_RETURN(1);
+ }
+ else /* start key */
+ {
+ if (tmp.append(FEDERATED_GT))
+ DBUG_RETURN(1);
+ }
+
+ if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ {
+ DBUG_RETURN(1);
+ }
+ break;
+ }
+ case(HA_READ_KEY_OR_NEXT):
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(FEDERATED_GE) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ DBUG_RETURN(1);
+ break;
+ case(HA_READ_BEFORE_KEY):
+ if (store_length >= length)
+ {
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(FEDERATED_LT) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ DBUG_RETURN(1);
+ break;
+ }
+ case(HA_READ_KEY_OR_PREV):
+ if (emit_key_part_name(&tmp, key_part) ||
+ tmp.append(FEDERATED_LE) ||
+ emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr,
+ part_length))
+ DBUG_RETURN(1);
+ break;
+ default:
+ DBUG_PRINT("info",("cannot handle flag %d", ranges[i]->flag));
+ DBUG_RETURN(1);
+ }
+ if (tmp.append(FEDERATED_CLOSEPAREN))
+ DBUG_RETURN(1);
+
+next_loop:
+ if (store_length >= length)
+ break;
+ DBUG_PRINT("info", ("remainder %d", remainder));
+ DBUG_ASSERT(remainder > 1);
+ length-= store_length;
+ ptr+= store_length;
+ if (tmp.append(FEDERATED_AND))
+ DBUG_RETURN(1);
+
+ DBUG_PRINT("info",
+ ("create_where_from_key WHERE clause: %s",
+ tmp.c_ptr_quick()));
+ }
+ }
+ if (both_not_null)
+ if (tmp.append(FEDERATED_CLOSEPAREN))
+ DBUG_RETURN(1);
+
+ if (to->append(FEDERATED_WHERE))
+ DBUG_RETURN(1);
+
+ if (to->append(tmp))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Example of simple lock controls. The "share" it creates is structure we will
+ pass to each federated handler. Do you have to have one of these? Well, you
+ have pieces that are used for locking, and they are needed to function.
+*/
+
+static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
+{
+ char *select_query, *tmp_table_name;
+ char query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ uint tmp_table_name_length;
+ Field **field;
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ FEDERATED_SHARE *share;
+ /*
+ In order to use this string, we must first zero it's length,
+ or it will contain garbage
+ */
+ query.length(0);
+
+ pthread_mutex_lock(&federated_mutex);
+ tmp_table_name= (char *)table->s->table_name;
+ tmp_table_name_length= (uint) strlen(tmp_table_name);
+
+ if (!(share= (FEDERATED_SHARE *) hash_search(&federated_open_tables,
+ (byte*) table_name,
+ strlen(table_name))))
+ {
+ query.set_charset(system_charset_info);
+ query.append(FEDERATED_SELECT);
+ for (field= table->field; *field; field++)
+ {
+ query.append(FEDERATED_BTICK);
+ query.append((*field)->field_name);
+ query.append(FEDERATED_BTICK);
+ query.append(FEDERATED_COMMA);
+ }
+ query.length(query.length()- strlen(FEDERATED_COMMA));
+ query.append(FEDERATED_FROM);
+ query.append(FEDERATED_BTICK);
+
+
+ if (!(share= (FEDERATED_SHARE *)
+ my_multi_malloc(MYF(MY_WME),
+ &share, sizeof(*share),
+ &tmp_table_name, tmp_table_name_length+ 1,
+ &select_query,
+ query.length()+table->s->connect_string.length+1,
+ NullS)))
+ {
+ pthread_mutex_unlock(&federated_mutex);
+ return NULL;
+ }
+
+ if (parse_url(share, table, 0))
+ goto error;
+
+ query.append(share->table_name, share->table_name_length);
+ query.append(FEDERATED_BTICK);
+ share->select_query= select_query;
+ strmov(share->select_query, query.ptr());
+ share->use_count= 0;
+ share->table_name_length= strlen(share->table_name);
+ DBUG_PRINT("info",
+ ("share->select_query %s", share->select_query));
+
+ if (my_hash_insert(&federated_open_tables, (byte*) share))
+ goto error;
+ thr_lock_init(&share->lock);
+ pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
+ }
+ share->use_count++;
+ pthread_mutex_unlock(&federated_mutex);
+
+ return share;
+
+error:
+ pthread_mutex_unlock(&federated_mutex);
+ if (share->scheme)
+ {
+ my_free((gptr) share->scheme, MYF(0));
+ share->scheme= 0;
+ }
+ return NULL;
+}
+
+
+/*
+ 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.
+*/
+
+static int free_share(FEDERATED_SHARE *share)
+{
+ DBUG_ENTER("free_share");
+ pthread_mutex_lock(&federated_mutex);
+
+ if (!--share->use_count)
+ {
+ if (share->scheme)
+ {
+ my_free((gptr) share->scheme, MYF(0));
+ share->scheme= 0;
+ }
+
+ hash_delete(&federated_open_tables, (byte*) share);
+ thr_lock_delete(&share->lock);
+ VOID(pthread_mutex_destroy(&share->mutex));
+ my_free((gptr) share, MYF(0));
+ }
+ pthread_mutex_unlock(&federated_mutex);
+
+ DBUG_RETURN(0);
+}
+
+
+ha_rows ha_federated::records_in_range(uint inx, key_range *start_key,
+ key_range *end_key)
+{
+ /*
+
+ We really want indexes to be used as often as possible, therefore
+ we just need to hard-code the return value to a very low number to
+ force the issue
+
+*/
+ DBUG_ENTER("ha_federated::records_in_range");
+ DBUG_RETURN(FEDERATED_RECORDS_IN_RANGE);
+}
+/*
+ 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.
+*/
+
+const char **ha_federated::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
+ open and closed for each request, they are cached).
+
+ Called from handler.cc by handler::ha_open(). The server opens
+ all tables by calling ha_open() which then calls the handler
+ specific open().
+*/
+
+int ha_federated::open(const char *name, int mode, uint test_if_locked)
+{
+ DBUG_ENTER("ha_federated::open");
+
+ if (!(share= get_share(name, table)))
+ DBUG_RETURN(1);
+ thr_lock_data_init(&share->lock, &lock, NULL);
+
+ /* Connect to foreign database mysql_real_connect() */
+ mysql= mysql_init(0);
+ if (!mysql_real_connect(mysql,
+ share->hostname,
+ share->username,
+ share->password,
+ share->database,
+ share->port,
+ share->socket, 0))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ /*
+ Since we do not support transactions at this version, we can let the client
+ API silently reconnect. For future versions, we will need more logic to deal
+ with transactions
+ */
+ mysql->reconnect= 1;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ 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
+ myisam table.
+ For sql_base.cc look at close_data_tables().
+*/
+
+int ha_federated::close(void)
+{
+ int retval;
+ DBUG_ENTER("ha_federated::close");
+
+ /* free the result set */
+ if (stored_result)
+ {
+ DBUG_PRINT("info",
+ ("mysql_free_result result at address %lx", stored_result));
+ mysql_free_result(stored_result);
+ stored_result= 0;
+ }
+ /* Disconnect from mysql */
+ mysql_close(mysql);
+ retval= free_share(share);
+ DBUG_RETURN(retval);
+
+}
+
+/*
+
+ Checks if a field in a record is SQL NULL.
+
+ SYNOPSIS
+ field_in_record_is_null()
+ table TABLE pointer, MySQL table object
+ field Field pointer, MySQL field object
+ record char pointer, contains record
+
+ DESCRIPTION
+ This method uses the record format information in table to track
+ the null bit in record.
+
+ RETURN VALUE
+ 1 if NULL
+ 0 otherwise
+*/
+
+inline uint field_in_record_is_null(TABLE *table,
+ Field *field,
+ char *record)
+{
+ int null_offset;
+ DBUG_ENTER("ha_federated::field_in_record_is_null");
+
+ if (!field->null_ptr)
+ DBUG_RETURN(0);
+
+ null_offset= (uint) ((char*)field->null_ptr - (char*)table->record[0]);
+
+ if (record[null_offset] & field->null_bit)
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+/*
+ 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
+ information to extract the data from the native byte array type.
+ Example of this would be:
+ for (Field **field=table->field ; *field ; field++)
+ {
+ ...
+ }
+
+ 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_federated::write_row(byte *buf)
+{
+ bool has_fields= FALSE;
+ uint all_fields_have_same_query_id= 1;
+ ulong current_query_id= 1;
+ ulong tmp_query_id= 1;
+ char insert_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ char values_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ Field **field;
+
+ /* The main insert query string */
+ String insert_string(insert_buffer, sizeof(insert_buffer), &my_charset_bin);
+ /* The string containing the values to be added to the insert */
+ String values_string(values_buffer, sizeof(values_buffer), &my_charset_bin);
+ /* The actual value of the field, to be added to the values_string */
+ String insert_field_value_string(insert_field_value_buffer,
+ sizeof(insert_field_value_buffer),
+ &my_charset_bin);
+ values_string.length(0);
+ insert_string.length(0);
+ insert_field_value_string.length(0);
+
+ DBUG_ENTER("ha_federated::write_row");
+ DBUG_PRINT("info",
+ ("table charset name %s csname %s",
+ table->s->table_charset->name,
+ table->s->table_charset->csname));
+
+ statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
+ table->timestamp_field->set_time();
+
+ /*
+ get the current query id - the fields that we add to the insert
+ statement to send to the foreign will not be appended unless they match
+ this query id
+ */
+ current_query_id= table->in_use->query_id;
+ DBUG_PRINT("info", ("current query id %d", current_query_id));
+
+ /*
+ start both our field and field values strings
+ */
+ insert_string.append(FEDERATED_INSERT);
+ insert_string.append(FEDERATED_BTICK);
+ insert_string.append(share->table_name, share->table_name_length);
+ insert_string.append(FEDERATED_BTICK);
+ insert_string.append(FEDERATED_OPENPAREN);
+
+ values_string.append(FEDERATED_VALUES);
+ values_string.append(FEDERATED_OPENPAREN);
+
+ /*
+ Even if one field is different, all_fields_same_query_id can't remain
+ 0 if it remains 0, then that means no fields were specified in the query
+ such as in the case of INSERT INTO table VALUES (val1, val2, valN)
+
+ */
+ for (field= table->field; *field; field++)
+ {
+ if (field > table->field && tmp_query_id != (*field)->query_id)
+ all_fields_have_same_query_id= 0;
+
+ tmp_query_id= (*field)->query_id;
+ }
+ /*
+ loop through the field pointer array, add any fields to both the values
+ list and the fields list that match the current query id
+
+ You might ask "Why an index variable (has_fields) ?" My answer is that
+ we need to count how many fields we actually need
+ */
+ for (field= table->field; *field; field++)
+ {
+ /* if there is a query id and if it's equal to the current query id */
+ if (((*field)->query_id && (*field)->query_id == current_query_id)
+ || all_fields_have_same_query_id)
+ {
+ /*
+ There are some fields. This will be used later to determine
+ whether to chop off commas and parens.
+ */
+ has_fields= TRUE;
+
+ if ((*field)->is_null())
+ insert_field_value_string.append(FEDERATED_NULL);
+ else
+ {
+ (*field)->val_str(&insert_field_value_string);
+ /* quote these fields if they require it */
+ (*field)->quote_data(&insert_field_value_string);
+ }
+ /* append the field name */
+ insert_string.append((*field)->field_name);
+
+ /* append the value */
+ values_string.append(insert_field_value_string);
+ insert_field_value_string.length(0);
+
+ /* append commas between both fields and fieldnames */
+ /*
+ unfortunately, we can't use the logic
+ if *(fields + 1) to make the following
+ appends conditional because we may not append
+ if the next field doesn't match the condition:
+ (((*field)->query_id && (*field)->query_id == current_query_id)
+ */
+ insert_string.append(FEDERATED_COMMA);
+ values_string.append(FEDERATED_COMMA);
+ }
+ }
+
+ /*
+ remove trailing comma
+ */
+ insert_string.length(insert_string.length() - strlen(FEDERATED_COMMA));
+ /*
+ if there were no fields, we don't want to add a closing paren
+ AND, we don't want to chop off the last char '('
+ insert will be "INSERT INTO t1 VALUES ();"
+ */
+ if (has_fields)
+ {
+ /* chops off leading commas */
+ values_string.length(values_string.length() - strlen(FEDERATED_COMMA));
+ insert_string.append(FEDERATED_CLOSEPAREN);
+ }
+ /* we always want to append this, even if there aren't any fields */
+ values_string.append(FEDERATED_CLOSEPAREN);
+
+ /* add the values */
+ insert_string.append(values_string);
+
+ DBUG_PRINT("info", ("insert query %s", insert_string.c_ptr_quick()));
+
+ if (mysql_real_query(mysql, insert_string.ptr(), insert_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+int ha_federated::optimize(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ char query_buffer[STRING_BUFFER_USUAL_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+
+ DBUG_ENTER("ha_federated::optimize");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(FEDERATED_OPTIMIZE);
+ query.append(FEDERATED_BTICK);
+ query.append(share->table_name, share->table_name_length);
+ query.append(FEDERATED_BTICK);
+
+ if (mysql_real_query(mysql, query.ptr(), query.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+int ha_federated::repair(THD* thd, HA_CHECK_OPT* check_opt)
+{
+ char query_buffer[STRING_BUFFER_USUAL_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+
+ DBUG_ENTER("ha_federated::repair");
+
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(FEDERATED_REPAIR);
+ query.append(FEDERATED_BTICK);
+ query.append(share->table_name, share->table_name_length);
+ query.append(FEDERATED_BTICK);
+ if (check_opt->flags & T_QUICK)
+ query.append(FEDERATED_QUICK);
+ if (check_opt->flags & T_EXTEND)
+ query.append(FEDERATED_EXTENDED);
+ if (check_opt->sql_flags & TT_USEFRM)
+ query.append(FEDERATED_USE_FRM);
+
+ if (mysql_real_query(mysql, query.ptr(), query.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Yes, update_row() does what you expect, it updates a row. old_data will have
+ the previous row record in it, while new_data will have the newest data in
+ it.
+
+ Keep in mind that the server can do updates based on ordering if an ORDER BY
+ clause was used. Consecutive ordering is not guarenteed.
+ Currently new_data will not have an updated auto_increament record, or
+ and updated timestamp field. You can do these for federated by doing these:
+ if (table->timestamp_on_update_now)
+ update_timestamp(new_row+table->timestamp_on_update_now-1);
+ if (table->next_number_field && record == table->record[0])
+ update_auto_increment();
+
+ Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
+*/
+
+int ha_federated::update_row(const byte *old_data, byte *new_data)
+{
+ /*
+ This used to control how the query was built. If there was a primary key,
+ the query would be built such that there was a where clause with only
+ that column as the condition. This is flawed, because if we have a multi-part
+ primary key, it would only use the first part! We don't need to do this anyway,
+ because read_range_first will retrieve the correct record, which is what is used
+ to build the WHERE clause. We can however use this to append a LIMIT to the end
+ if there is NOT a primary key. Why do this? Because we only are updating one
+ record, and LIMIT enforces this.
+ */
+ bool has_a_primary_key= (table->s->primary_key == 0 ? TRUE : FALSE);
+ /*
+ buffers for following strings
+ */
+ char old_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ char new_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ char update_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ char where_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+
+ /* stores the value to be replaced of the field were are updating */
+ String old_field_value(old_field_value_buffer,
+ sizeof(old_field_value_buffer),
+ &my_charset_bin);
+ /* stores the new value of the field */
+ String new_field_value(new_field_value_buffer,
+ sizeof(new_field_value_buffer),
+ &my_charset_bin);
+ /* stores the update query */
+ String update_string(update_buffer,
+ sizeof(update_buffer),
+ &my_charset_bin);
+ /* stores the WHERE clause */
+ String where_string(where_buffer,
+ sizeof(where_buffer),
+ &my_charset_bin);
+
+ DBUG_ENTER("ha_federated::update_row");
+ /*
+ set string lengths to 0 to avoid misc chars in string
+ */
+ old_field_value.length(0);
+ new_field_value.length(0);
+ update_string.length(0);
+ where_string.length(0);
+
+ update_string.append(FEDERATED_UPDATE);
+ update_string.append(FEDERATED_BTICK);
+ update_string.append(share->table_name);
+ update_string.append(FEDERATED_BTICK);
+ update_string.append(FEDERATED_SET);
+
+/*
+ In this loop, we want to match column names to values being inserted
+ (while building INSERT statement).
+
+ Iterate through table->field (new data) and share->old_filed (old_data)
+ using the same index to created an SQL UPDATE statement, new data is
+ used to create SET field=value and old data is used to create WHERE
+ field=oldvalue
+ */
+
+ for (Field **field= table->field; *field; field++)
+ {
+ where_string.append((*field)->field_name);
+ update_string.append((*field)->field_name);
+ update_string.append(FEDERATED_EQ);
+
+ if ((*field)->is_null())
+ new_field_value.append(FEDERATED_NULL);
+ else
+ {
+ /* otherwise = */
+ (*field)->val_str(&new_field_value);
+ (*field)->quote_data(&new_field_value);
+
+ if (!field_in_record_is_null(table, *field, (char*) old_data))
+ where_string.append(FEDERATED_EQ);
+ }
+
+ if (field_in_record_is_null(table, *field, (char*) old_data))
+ where_string.append(FEDERATED_ISNULL);
+ else
+ {
+ (*field)->val_str(&old_field_value,
+ (char*) (old_data + (*field)->offset()));
+ (*field)->quote_data(&old_field_value);
+ where_string.append(old_field_value);
+ }
+
+ update_string.append(new_field_value);
+ new_field_value.length(0);
+
+ /*
+ Only append conjunctions if we have another field in which
+ to iterate
+ */
+ if (*(field + 1))
+ {
+ update_string.append(FEDERATED_COMMA);
+ where_string.append(FEDERATED_AND);
+ }
+ old_field_value.length(0);
+ }
+ update_string.append(FEDERATED_WHERE);
+ update_string.append(where_string);
+ /*
+ If this table has not a primary key, then we could possibly
+ update multiple rows. We want to make sure to only update one!
+ */
+ if (!has_a_primary_key)
+ update_string.append(FEDERATED_LIMIT1);
+
+ if (mysql_real_query(mysql, update_string.ptr(), update_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ 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.
+ Keep in mind that the server does no guarentee consecutive deletions.
+ ORDER BY clauses can be used.
+
+ Called in sql_acl.cc and sql_udf.cc to manage internal table information.
+ Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select
+ it is used for removing duplicates while in insert it is used for REPLACE
+ calls.
+*/
+
+int ha_federated::delete_row(const byte *buf)
+{
+ char delete_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ char data_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+
+ String delete_string(delete_buffer, sizeof(delete_buffer), &my_charset_bin);
+ String data_string(data_buffer, sizeof(data_buffer), &my_charset_bin);
+ DBUG_ENTER("ha_federated::delete_row");
+
+ delete_string.length(0);
+ delete_string.append(FEDERATED_DELETE);
+ delete_string.append(FEDERATED_FROM);
+ delete_string.append(FEDERATED_BTICK);
+ delete_string.append(share->table_name);
+ delete_string.append(FEDERATED_BTICK);
+ delete_string.append(FEDERATED_WHERE);
+
+ for (Field **field= table->field; *field; field++)
+ {
+ Field *cur_field= *field;
+ data_string.length(0);
+ delete_string.append(cur_field->field_name);
+
+ if (cur_field->is_null())
+ {
+ delete_string.append(FEDERATED_IS);
+ data_string.append(FEDERATED_NULL);
+ }
+ else
+ {
+ delete_string.append(FEDERATED_EQ);
+ cur_field->val_str(&data_string);
+ cur_field->quote_data(&data_string);
+ }
+
+ delete_string.append(data_string);
+ delete_string.append(FEDERATED_AND);
+ }
+ delete_string.length(delete_string.length()-5); // Remove trailing AND
+
+ delete_string.append(FEDERATED_LIMIT1);
+ DBUG_PRINT("info",
+ ("Delete sql: %s", delete_string.c_ptr_quick()));
+ if (mysql_real_query(mysql, delete_string.ptr(), delete_string.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ deleted+= mysql->affected_rows;
+ DBUG_PRINT("info",
+ ("rows deleted %d rows deleted for all time %d",
+ int(mysql->affected_rows), deleted));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Positions an index cursor to the index specified in the handle. Fetches the
+ row if available. If the key value is null, begin at the first key of the
+ index. This method, which is called in the case of an SQL statement having
+ a WHERE clause on a non-primary key index, simply calls index_read_idx.
+*/
+
+int ha_federated::index_read(byte *buf, const byte *key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ int retval;
+ DBUG_ENTER("ha_federated::index_read");
+ retval= index_read_idx(buf, active_index, key, key_len, find_flag);
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ Positions an index cursor to the index specified in key. Fetches the
+ row if any. This is only used to read whole keys.
+
+ This method is called via index_read in the case of a WHERE clause using
+ a regular non-primary key index, OR is called DIRECTLY when the WHERE clause
+ uses a PRIMARY KEY index.
+*/
+
+int ha_federated::index_read_idx(byte *buf, uint index, const byte *key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ int retval;
+ char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ char index_value[STRING_BUFFER_USUAL_SIZE];
+ char sql_query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ String index_string(index_value,
+ sizeof(index_value),
+ &my_charset_bin);
+ String sql_query(sql_query_buffer,
+ sizeof(sql_query_buffer),
+ &my_charset_bin);
+ key_range range;
+
+ index_string.length(0);
+ sql_query.length(0);
+
+ DBUG_ENTER("ha_federated::index_read_idx");
+
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
+
+ sql_query.append(share->select_query);
+
+ range.key= key;
+ range.length= key_len;
+ range.flag= find_flag;
+ create_where_from_key(&index_string,
+ &table->key_info[index],
+ &range,
+ NULL, 0);
+ sql_query.append(index_string);
+
+ DBUG_PRINT("info",
+ ("current key %d key value %s index_string value %s length %d",
+ index, (char*) key, index_string.c_ptr_quick(),
+ index_string.length()));
+
+ DBUG_PRINT("info",
+ ("current position %d sql_query %s", current_position,
+ sql_query.c_ptr_quick()));
+
+ if (stored_result)
+ {
+ mysql_free_result(stored_result);
+ stored_result= 0;
+ }
+ if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
+ {
+ my_sprintf(error_buffer, (error_buffer, ": %d : %s",
+ mysql_errno(mysql), mysql_error(mysql)));
+ retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ goto error;
+ }
+ stored_result= mysql_store_result(mysql);
+
+ if (!stored_result)
+ {
+ retval= HA_ERR_END_OF_FILE;
+ goto error;
+ }
+ /*
+ This basically says that the record in table->record[0] is legal,
+ and that it is ok to use this record, for whatever reason, such
+ as with a join (without it, joins will not work)
+ */
+ table->status= 0;
+
+ retval= rnd_next(buf);
+ DBUG_RETURN(retval);
+
+error:
+ if (stored_result)
+ {
+ mysql_free_result(stored_result);
+ stored_result= 0;
+ }
+ table->status= STATUS_NOT_FOUND;
+ my_error(retval, MYF(0), error_buffer);
+ DBUG_RETURN(retval);
+}
+
+/* Initialized at each key walk (called multiple times unlike rnd_init()) */
+int ha_federated::index_init(uint keynr)
+{
+ DBUG_ENTER("ha_federated::index_init");
+ DBUG_PRINT("info",
+ ("table: '%s' key: %d", table->s->table_name, keynr));
+ active_index= keynr;
+ DBUG_RETURN(0);
+}
+
+/*
+
+ int read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted);
+*/
+int ha_federated::read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted)
+{
+ char sql_query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ int retval;
+ String sql_query(sql_query_buffer,
+ sizeof(sql_query_buffer),
+ &my_charset_bin);
+
+ DBUG_ENTER("ha_federated::read_range_first");
+ if (start_key == NULL && end_key == NULL)
+ DBUG_RETURN(0);
+
+ sql_query.length(0);
+ sql_query.append(share->select_query);
+ create_where_from_key(&sql_query,
+ &table->key_info[active_index],
+ start_key, end_key, 0);
+
+ if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
+ {
+ retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ goto error;
+ }
+ sql_query.length(0);
+
+ if (stored_result)
+ {
+ DBUG_PRINT("info",
+ ("mysql_free_result address %lx", stored_result));
+ mysql_free_result(stored_result);
+ stored_result= 0;
+ }
+ stored_result= mysql_store_result(mysql);
+
+ if (!stored_result)
+ {
+ retval= HA_ERR_END_OF_FILE;
+ goto error;
+ }
+
+ /* This was successful, please let it be known! */
+ table->status= 0;
+
+ retval= rnd_next(table->record[0]);
+ DBUG_RETURN(retval);
+
+error:
+ table->status= STATUS_NOT_FOUND;
+ if (stored_result)
+ {
+ DBUG_PRINT("info", ("mysql_free_result address %lx", stored_result));
+ mysql_free_result(stored_result);
+ stored_result= 0;
+ }
+ DBUG_RETURN(retval);
+}
+
+int ha_federated::read_range_next()
+{
+ int retval;
+ DBUG_ENTER("ha_federated::read_range_next");
+ retval= rnd_next(table->record[0]);
+ DBUG_RETURN(retval);
+}
+
+
+/* Used to read forward through the index. */
+int ha_federated::index_next(byte *buf)
+{
+ int retval;
+ DBUG_ENTER("ha_federated::index_next");
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
+ retval= rnd_next(buf);
+ DBUG_RETURN(retval);
+}
+/*
+ rnd_init() is called when the system wants the storage engine to do a table
+ scan.
+
+ This is the method that gets data for the SELECT calls.
+
+ See the federated 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, and sql_update.cc.
+*/
+
+int ha_federated::rnd_init(bool scan)
+{
+ DBUG_ENTER("ha_federated::rnd_init");
+ /*
+ The use of the 'scan' flag is incredibly important for this handler
+ to work properly, especially with updates containing WHERE clauses
+ using indexed columns.
+
+ When the initial query contains a WHERE clause of the query using an
+ indexed column, it's index_read_idx that selects the exact record from
+ the foreign database.
+
+ When there is NO index in the query, either due to not having a WHERE
+ clause, or the WHERE clause is using columns that are not indexed, a
+ 'full table scan' done by rnd_init, which in this situation simply means
+ a 'select * from ...' on the foreign table.
+
+ In other words, this 'scan' flag gives us the means to ensure that if
+ there is an index involved in the query, we want index_read_idx to
+ retrieve the exact record (scan flag is 0), and do not want rnd_init
+ to do a 'full table scan' and wipe out that result set.
+
+ Prior to using this flag, the problem was most apparent with updates.
+
+ An initial query like 'UPDATE tablename SET anything = whatever WHERE
+ indexedcol = someval', index_read_idx would get called, using a query
+ constructed with a WHERE clause built from the values of index ('indexcol'
+ in this case, having a value of 'someval'). mysql_store_result would
+ then get called (this would be the result set we want to use).
+
+ After this rnd_init (from sql_update.cc) would be called, it would then
+ unecessarily call "select * from table" on the foreign table, then call
+ mysql_store_result, which would wipe out the correct previous result set
+ from the previous call of index_read_idx's that had the result set
+ containing the correct record, hence update the wrong row!
+
+ */
+ scan_flag= scan;
+ if (scan)
+ {
+ DBUG_PRINT("info", ("share->select_query %s", share->select_query));
+ if (stored_result)
+ {
+ DBUG_PRINT("info",
+ ("mysql_free_result address %lx", stored_result));
+ mysql_free_result(stored_result);
+ stored_result= 0;
+ }
+
+ if (mysql_real_query(mysql,
+ share->select_query,
+ strlen(share->select_query)))
+ goto error;
+
+ stored_result= mysql_store_result(mysql);
+ if (!stored_result)
+ goto error;
+ }
+ DBUG_RETURN(0);
+
+error:
+ DBUG_RETURN(stash_remote_error());
+}
+
+int ha_federated::rnd_end()
+{
+ int retval;
+ DBUG_ENTER("ha_federated::rnd_end");
+
+ if (stored_result)
+ {
+ DBUG_PRINT("info", ("mysql_free_result address %lx", stored_result));
+ mysql_free_result(stored_result);
+ stored_result= 0;
+ }
+ retval= index_end();
+ DBUG_RETURN(retval);
+}
+
+int ha_federated::index_end(void)
+{
+ DBUG_ENTER("ha_federated::index_end");
+ active_index= MAX_KEY;
+ 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
+ in a manner that will allow the server to understand it.
+
+ Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc,
+ sql_table.cc, and sql_update.cc.
+*/
+
+int ha_federated::rnd_next(byte *buf)
+{
+ int retval;
+ MYSQL_ROW row;
+ DBUG_ENTER("ha_federated::rnd_next");
+
+ if (stored_result == 0)
+ {
+ /*
+ Return value of rnd_init is not always checked (see records.cc),
+ so we can get here _even_ if there is _no_ pre-fetched result-set!
+ TODO: fix it.
+ */
+ DBUG_RETURN(1);
+ }
+
+ /* Fetch a row, insert it back in a row format. */
+ current_position= stored_result->data_cursor;
+ DBUG_PRINT("info", ("current position %d", current_position));
+ if (!(row= mysql_fetch_row(stored_result)))
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ retval= convert_row_to_internal_format(buf, row);
+ DBUG_RETURN(retval);
+}
+
+
+/*
+ 'position()' is called after each call to rnd_next() if the data needs to be
+ ordered. You can do something like the following to store the position:
+ my_store_ptr(ref, ref_length, current_position);
+
+ The server uses ref to store data. ref_length in the above case is 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.
+
+ Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc.
+*/
+
+void ha_federated::position(const byte *record)
+{
+ DBUG_ENTER("ha_federated::position");
+ /* my_store_ptr Add seek storage */
+ *(MYSQL_ROW_OFFSET *) ref= current_position; // ref is always aligned
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ This is like rnd_next, but you are given a position to use to determine the
+ row. The position will be of the type that you stored in ref. You can use
+ ha_get_ptr(pos,ref_length) to retrieve whatever key or position you saved
+ when position() was called.
+
+ This method is required for an ORDER BY.
+
+ Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc.
+*/
+int ha_federated::rnd_pos(byte *buf, byte *pos)
+{
+ DBUG_ENTER("ha_federated::rnd_pos");
+ /*
+ we do not need to do any of this if there has been a scan performed
+ already, or if this is an update and index_read_idx already has a result
+ set in which to build it's update query from
+ */
+ if (scan_flag)
+ {
+ int retval;
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
+ memcpy_fixed(&current_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos
+ /* is not aligned */
+ stored_result->current_row= 0;
+ stored_result->data_cursor= current_position;
+ retval= rnd_next(buf);
+ DBUG_RETURN(retval);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ ::info() is used to return information to the optimizer.
+ Currently this table handler doesn't implement most of the fields
+ really needed. SHOW also makes use of this data
+ Another note, you will probably want to have the following in your
+ code:
+ 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
+ it will probably be better to set records to two so you can return
+ as many records as you need.
+ Along with records a few more variables you may wish to set are:
+ records
+ deleted
+ data_file_length
+ index_file_length
+ delete_length
+ check_time
+ Take a look at the public variables in handler.h for more information.
+
+ Called in:
+ filesort.cc
+ ha_heap.cc
+ item_sum.cc
+ opt_sum.cc
+ sql_delete.cc
+ sql_delete.cc
+ sql_derived.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_select.cc
+ sql_show.cc
+ sql_show.cc
+ sql_show.cc
+ sql_show.cc
+ sql_table.cc
+ sql_union.cc
+ sql_update.cc
+
+*/
+
+void ha_federated::info(uint flag)
+{
+ char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ char status_buf[FEDERATED_QUERY_BUFFER_SIZE];
+ char escaped_table_name[FEDERATED_QUERY_BUFFER_SIZE];
+ int error;
+ uint error_code;
+ MYSQL_RES *result= 0;
+ MYSQL_ROW row;
+ String status_query_string(status_buf, sizeof(status_buf), &my_charset_bin);
+
+ DBUG_ENTER("ha_federated::info");
+
+ error_code= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
+ /* we want not to show table status if not needed to do so */
+ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST))
+ {
+ status_query_string.length(0);
+ status_query_string.append(FEDERATED_INFO);
+ status_query_string.append(FEDERATED_SQUOTE);
+
+ escape_string_for_mysql(&my_charset_bin, (char *)escaped_table_name,
+ sizeof(escaped_table_name),
+ share->table_name,
+ share->table_name_length);
+ status_query_string.append(escaped_table_name);
+ status_query_string.append(FEDERATED_SQUOTE);
+
+ if (mysql_real_query(mysql, status_query_string.ptr(),
+ status_query_string.length()))
+ goto error;
+
+ status_query_string.length(0);
+
+ result= mysql_store_result(mysql);
+ if (!result)
+ goto error;
+
+ if (!mysql_num_rows(result))
+ goto error;
+
+ if (!(row= mysql_fetch_row(result)))
+ goto error;
+
+ if (flag & HA_STATUS_VARIABLE | HA_STATUS_CONST)
+ {
+ /*
+ deleted is set in ha_federated::info
+ */
+ /*
+ need to figure out what this means as far as federated is concerned,
+ since we don't have a "file"
+
+ data_file_length = ?
+ index_file_length = ?
+ delete_length = ?
+ */
+ if (row[4] != NULL)
+ records= (ha_rows) my_strtoll10(row[4], (char**) 0, &error);
+ if (row[5] != NULL)
+ mean_rec_length= (ha_rows) my_strtoll10(row[5], (char**) 0, &error);
+ if (row[12] != NULL)
+ update_time= (ha_rows) my_strtoll10(row[12], (char**) 0, &error);
+ if (row[13] != NULL)
+ check_time= (ha_rows) my_strtoll10(row[13], (char**) 0, &error);
+ }
+ if (flag & HA_STATUS_CONST)
+ {
+ block_size= 4096;
+ }
+ }
+
+ if (result)
+ mysql_free_result(result);
+
+ DBUG_VOID_RETURN;
+
+error:
+ if (result)
+ mysql_free_result(result);
+ my_sprintf(error_buffer, (error_buffer, ": %d : %s",
+ mysql_errno(mysql), mysql_error(mysql)));
+ my_error(error_code, MYF(0), error_buffer);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ 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.
+
+ 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().
+ Called from sql_union.cc by st_select_lex_unit::exec().
+*/
+
+int ha_federated::delete_all_rows()
+{
+ DBUG_ENTER("ha_federated::delete_all_rows");
+
+ char query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
+ String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
+ query.length(0);
+
+ query.set_charset(system_charset_info);
+ query.append(FEDERATED_TRUNCATE);
+ query.append(FEDERATED_BTICK);
+ query.append(share->table_name);
+ query.append(FEDERATED_BTICK);
+
+ /*
+ TRUNCATE won't return anything in mysql_affected_rows
+ */
+ deleted+= records;
+ if (mysql_real_query(mysql, query.ptr(), query.length()))
+ {
+ DBUG_RETURN(stash_remote_error());
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ The idea with handler::store_lock() is the following:
+
+ The statement decided which locks we should need for the table
+ for updates/deletes/inserts we get WRITE locks, for SELECT... we get
+ read locks.
+
+ Before adding the lock into the table lock handler (see thr_lock.c)
+ mysqld calls store lock with the requested locks. Store lock can now
+ modify a write lock to a read lock (or some other lock), ignore the
+ 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 federated 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.
+
+ When releasing locks, store_lock() are also called. In this case one
+ usually doesn't have to do anything.
+
+ In some exceptional cases MySQL may send a request for a TL_IGNORE;
+ This means that we are requesting the same lock as last time and this
+ should also be ignored. (This may happen when someone does a flush
+ table when we have opened a part of the tables, in which case mysqld
+ closes and reopens the tables and tries to get the same locks at last
+ time). In the future we will probably try to remove this.
+
+ Called from lock.cc by get_lock_data().
+*/
+
+THR_LOCK_DATA **ha_federated::store_lock(THD *thd,
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+{
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
+ {
+ /*
+ Here is where we get into the guts of a row level lock.
+ If TL_UNLOCK is set
+ If we are not doing a LOCK TABLE or DISCARD/IMPORT
+ TABLESPACE, then allow multiple writers
+ */
+
+ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
+ lock_type <= TL_WRITE) && !thd->in_lock_tables)
+ lock_type= TL_WRITE_ALLOW_WRITE;
+
+ /*
+ In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
+ MySQL would use the lock TL_READ_NO_INSERT on t2, and that
+ would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
+ to t2. Convert the lock to a normal read lock to allow
+ concurrent inserts to t2.
+ */
+
+ if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables)
+ lock_type= TL_READ;
+
+ lock.type= lock_type;
+ }
+
+ *to++= &lock;
+
+ return to;
+}
+
+/*
+ create() does nothing, since we have no local setup of our own.
+ FUTURE: We should potentially connect to the foreign database and
+*/
+
+int ha_federated::create(const char *name, TABLE *table_arg,
+ HA_CREATE_INFO *create_info)
+{
+ int retval= 0;
+ /*
+ only a temporary share, to test the url
+ */
+ FEDERATED_SHARE tmp_share;
+ DBUG_ENTER("ha_federated::create");
+
+ if ((retval= parse_url(&tmp_share, table_arg, 1)))
+ goto error;
+
+ if ((retval= check_foreign_data_source(&tmp_share, 1)))
+ goto error;
+
+ if (tmp_share.scheme)
+ {
+ my_free((gptr) tmp_share.scheme, MYF(0));
+ tmp_share.scheme= 0;
+ }
+ DBUG_RETURN(retval);
+
+error:
+ if (tmp_share.scheme)
+ {
+ my_free((gptr) tmp_share.scheme, MYF(0));
+ tmp_share.scheme= 0;
+ }
+ DBUG_RETURN(retval);
+
+}
+
+
+int ha_federated::stash_remote_error()
+{
+ DBUG_ENTER("ha_federated::stash_remote_error()");
+ remote_error_number= mysql_errno(mysql);
+ snprintf(remote_error_buf, FEDERATED_QUERY_BUFFER_SIZE, mysql_error(mysql));
+ DBUG_RETURN(HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM);
+}
+
+
+bool ha_federated::get_error_message(int error, String* buf)
+{
+ DBUG_ENTER("ha_federated::get_error_message");
+ DBUG_PRINT("enter", ("error: %d", error));
+ if (error == HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM)
+ {
+ buf->append("Error on remote system: ");
+ buf->qs_append(remote_error_number);
+ buf->append(": ");
+ buf->append(remote_error_buf, FEDERATED_QUERY_BUFFER_SIZE);
+
+ remote_error_number= 0;
+ remote_error_buf[0]= '\0';
+ }
+ DBUG_PRINT("exit", ("message: %s", buf->ptr()));
+ DBUG_RETURN(FALSE);
+}
+
+#endif /* HAVE_FEDERATED_DB */
diff --git a/sql/ha_federated.h b/sql/ha_federated.h
new file mode 100644
index 00000000000..b25071dda16
--- /dev/null
+++ b/sql/ha_federated.h
@@ -0,0 +1,304 @@
+/* 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 */
+
+/*
+ Please read ha_exmple.cc before reading this file.
+ Please keep in mind that the federated storage engine implements all methods
+ that are required to be implemented. handler.h has a full list of methods
+ that you can implement.
+*/
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+#include <mysql.h>
+
+/*
+ handler::print_error has a case statement for error numbers.
+ This value is (10000) is far out of range and will envoke the
+ default: case.
+ (Current error range is 120-159 from include/my_base.h)
+*/
+#define HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM 10000
+
+#define FEDERATED_QUERY_BUFFER_SIZE STRING_BUFFER_USUAL_SIZE * 5
+#define FEDERATED_RECORDS_IN_RANGE 2
+
+#define FEDERATED_INFO " SHOW TABLE STATUS LIKE "
+#define FEDERATED_INFO_LEN sizeof(FEDERATED_INFO)
+#define FEDERATED_SELECT "SELECT "
+#define FEDERATED_SELECT_LEN sizeof(FEDERATED_SELECT)
+#define FEDERATED_WHERE " WHERE "
+#define FEDERATED_WHERE_LEN sizeof(FEDERATED_WHERE)
+#define FEDERATED_FROM " FROM "
+#define FEDERATED_FROM_LEN sizeof(FEDERATED_FROM)
+#define FEDERATED_PERCENT "%"
+#define FEDERATED_PERCENT_LEN sizeof(FEDERATED_PERCENT)
+#define FEDERATED_IS " IS "
+#define FEDERATED_IS_LEN sizeof(FEDERATED_IS)
+#define FEDERATED_NULL " NULL "
+#define FEDERATED_NULL_LEN sizeof(FEDERATED_NULL)
+#define FEDERATED_ISNULL " IS NULL "
+#define FEDERATED_ISNULL_LEN sizeof(FEDERATED_ISNULL)
+#define FEDERATED_LIKE " LIKE "
+#define FEDERATED_LIKE_LEN sizeof(FEDERATED_LIKE)
+#define FEDERATED_TRUNCATE "TRUNCATE "
+#define FEDERATED_TRUNCATE_LEN sizeof(FEDERATED_TRUNCATE)
+#define FEDERATED_DELETE "DELETE "
+#define FEDERATED_DELETE_LEN sizeof(FEDERATED_DELETE)
+#define FEDERATED_INSERT "INSERT INTO "
+#define FEDERATED_INSERT_LEN sizeof(FEDERATED_INSERT)
+#define FEDERATED_OPTIMIZE "OPTIMIZE TABLE "
+#define FEDERATED_OPTIMIZE_LEN sizeof(FEDERATED_OPTIMIZE)
+#define FEDERATED_REPAIR "REPAIR TABLE "
+#define FEDERATED_REPAIR_LEN sizeof(FEDERATED_REPAIR)
+#define FEDERATED_QUICK " QUICK"
+#define FEDERATED_QUICK_LEN sizeof(FEDERATED_QUICK)
+#define FEDERATED_EXTENDED " EXTENDED"
+#define FEDERATED_EXTENDED_LEN sizeof(FEDERATED_EXTENDED)
+#define FEDERATED_USE_FRM " USE_FRM"
+#define FEDERATED_USE_FRM_LEN sizeof(FEDERATED_USE_FRM)
+#define FEDERATED_LIMIT1 " LIMIT 1"
+#define FEDERATED_LIMIT1_LEN sizeof(FEDERATED_LIMIT1)
+#define FEDERATED_VALUES "VALUES "
+#define FEDERATED_VALUES_LEN sizeof(FEDERATED_VALUES)
+#define FEDERATED_UPDATE "UPDATE "
+#define FEDERATED_UPDATE_LEN sizeof(FEDERATED_UPDATE)
+#define FEDERATED_SET "SET "
+#define FEDERATED_SET_LEN sizeof(FEDERATED_SET)
+#define FEDERATED_AND " AND "
+#define FEDERATED_AND_LEN sizeof(FEDERATED_AND)
+#define FEDERATED_CONJUNCTION ") AND ("
+#define FEDERATED_CONJUNCTION_LEN sizeof(FEDERATED_CONJUNCTION)
+#define FEDERATED_OR " OR "
+#define FEDERATED_OR_LEN sizeof(FEDERATED_OR)
+#define FEDERATED_NOT " NOT "
+#define FEDERATED_NOT_LEN sizeof(FEDERATED_NOT)
+#define FEDERATED_STAR "* "
+#define FEDERATED_STAR_LEN sizeof(FEDERATED_STAR)
+#define FEDERATED_SPACE " "
+#define FEDERATED_SPACE_LEN sizeof(FEDERATED_SPACE)
+#define FEDERATED_SQUOTE "'"
+#define FEDERATED_SQUOTE_LEN sizeof(FEDERATED_SQUOTE)
+#define FEDERATED_COMMA ", "
+#define FEDERATED_COMMA_LEN sizeof(FEDERATED_COMMA)
+#define FEDERATED_BTICK "`"
+#define FEDERATED_BTICK_LEN sizeof(FEDERATED_BTICK)
+#define FEDERATED_OPENPAREN " ("
+#define FEDERATED_OPENPAREN_LEN sizeof(FEDERATED_OPENPAREN)
+#define FEDERATED_CLOSEPAREN ") "
+#define FEDERATED_CLOSEPAREN_LEN sizeof(FEDERATED_CLOSEPAREN)
+#define FEDERATED_NE " != "
+#define FEDERATED_NE_LEN sizeof(FEDERATED_NE)
+#define FEDERATED_GT " > "
+#define FEDERATED_GT_LEN sizeof(FEDERATED_GT)
+#define FEDERATED_LT " < "
+#define FEDERATED_LT_LEN sizeof(FEDERATED_LT)
+#define FEDERATED_LE " <= "
+#define FEDERATED_LE_LEN sizeof(FEDERATED_LE)
+#define FEDERATED_GE " >= "
+#define FEDERATED_GE_LEN sizeof(FEDERATED_GE)
+#define FEDERATED_EQ " = "
+#define FEDERATED_EQ_LEN sizeof(FEDERATED_EQ)
+#define FEDERATED_FALSE " 1=0"
+#define FEDERATED_FALSE_LEN sizeof(FEDERATED_FALSE)
+
+/*
+ FEDERATED_SHARE is a structure that will be shared amoung all open handlers
+ The example implements the minimum of what you will probably need.
+*/
+typedef struct st_federated_share {
+ /*
+ the primary select query to be used in rnd_init
+ */
+ char *select_query;
+ /*
+ remote host info, parse_url supplies
+ */
+ char *scheme;
+ char *hostname;
+ char *username;
+ char *password;
+ char *database;
+ char *table_name;
+ char *table;
+ char *socket;
+ char *sport;
+ ushort port;
+ uint table_name_length, use_count;
+ pthread_mutex_t mutex;
+ THR_LOCK lock;
+} FEDERATED_SHARE;
+
+/*
+ Class definition for the storage engine
+*/
+class ha_federated: public handler
+{
+ THR_LOCK_DATA lock; /* MySQL lock */
+ FEDERATED_SHARE *share; /* Shared lock info */
+ MYSQL *mysql; /* MySQL connection */
+ MYSQL_RES *stored_result;
+ bool scan_flag;
+ uint ref_length;
+ uint fetch_num; // stores the fetch num
+ MYSQL_ROW_OFFSET current_position; // Current position used by ::position()
+ int remote_error_number;
+ char remote_error_buf[FEDERATED_QUERY_BUFFER_SIZE];
+
+private:
+ /*
+ return 0 on success
+ return errorcode otherwise
+ */
+ uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row);
+ bool create_where_from_key(String *to, KEY *key_info,
+ const key_range *start_key,
+ const key_range *end_key,
+ bool records_in_range);
+ int stash_remote_error();
+
+public:
+ ha_federated(TABLE *table_arg);
+ ~ha_federated()
+ {
+ }
+ /* The name that will be used for display purposes */
+ const char *table_type() const { return "FEDERATED"; }
+ /*
+ The name of the index type that will be used for display
+ don't implement this method unless you really have indexes
+ */
+ // perhaps get index type
+ const char *index_type(uint inx) { return "REMOTE"; }
+ const char **bas_ext() const;
+ /*
+ This is a list of flags that says what the storage engine
+ implements. The current table flags are documented in
+ handler.h
+ */
+ ulong table_flags() const
+ {
+ /* fix server to be able to get remote server table flags */
+ return (HA_NOT_EXACT_COUNT |
+ HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED | HA_REC_NOT_IN_SEQ |
+ HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS| HA_NO_PREFIX_CHAR_KEYS);
+ }
+ /*
+ This is a bitmap 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
+ here.
+
+ part is the key part to check. First key part is 0
+ If all_parts it's set, MySQL want to know the flags for the combined
+ index up to and including 'part'.
+ */
+ /* fix server to be able to get remote server index flags */
+ ulong index_flags(uint inx, uint part, bool all_parts) const
+ {
+ return (HA_READ_NEXT | HA_READ_RANGE | HA_READ_AFTER_KEY);
+ }
+ uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
+ uint max_supported_keys() const { return MAX_KEY; }
+ uint max_supported_key_parts() const { return MAX_REF_PARTS; }
+ uint max_supported_key_length() const { return MAX_KEY_LENGTH; }
+ /*
+ Called in test_quick_select to determine if indexes should be used.
+ Normally, we need to know number of blocks . For federated we need to
+ know number of blocks on remote side, and number of packets and blocks
+ on the network side (?)
+ Talk to Kostja about this - how to get the
+ number of rows * ...
+ disk scan time on other side (block size, size of the row) + network time ...
+ The reason for "records * 1000" is that such a large number forces
+ this to use indexes "
+ */
+ double scan_time()
+ {
+ DBUG_PRINT("info",
+ ("records %d", records));
+ return (double)(records*1000);
+ }
+ /*
+ The next method will never be called if you do not implement indexes.
+ */
+ double read_time(uint index, uint ranges, ha_rows rows)
+ {
+ /*
+ Per Brian, this number is bugus, but this method must be implemented,
+ and at a later date, he intends to document this issue for handler code
+ */
+ return (double) rows / 20.0+1;
+ }
+
+ const key_map *keys_to_use_for_scanning() { return &key_map_full; }
+ /*
+ Everything below are methods that we implment in ha_federated.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); // 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);
+ int index_init(uint keynr);
+ 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_end();
+ int read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted);
+ int read_range_next();
+ /*
+ 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 repair(THD* thd, HA_CHECK_OPT* check_opt);
+ int optimize(THD* thd, HA_CHECK_OPT* check_opt);
+
+ int delete_all_rows(void);
+ int create(const char *name, TABLE *form,
+ HA_CREATE_INFO *create_info); //required
+ ha_rows records_in_range(uint inx, key_range *start_key,
+ key_range *end_key);
+ uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
+
+ THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type); //required
+ virtual bool get_error_message(int error, String *buf);
+};
+
+bool federated_db_init(void);
+bool federated_db_end(void);
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index f8c2e6cc338..94ee3f8e656 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -23,12 +23,44 @@
#include <myisampack.h>
#include "ha_heap.h"
+static handlerton heap_hton= {
+ "MEMORY",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
/*****************************************************************************
** HEAP tables
*****************************************************************************/
+ha_heap::ha_heap(TABLE *table_arg)
+ :handler(&heap_hton, table_arg), file(0), records_changed(0),
+ key_stats_ok(0)
+{}
+
+
+static const char *ha_heap_exts[] = {
+ NullS
+};
+
const char **ha_heap::bas_ext() const
-{ static const char *ext[1]= { NullS }; return ext; }
+{
+ return ha_heap_exts;
+}
/*
Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
@@ -98,16 +130,17 @@ int ha_heap::close(void)
void ha_heap::set_keys_for_scanning(void)
{
btree_keys.clear_all();
- for (uint i= 0 ; i < table->keys ; i++)
+ for (uint i= 0 ; i < table->s->keys ; i++)
{
if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
btree_keys.set_bit(i);
}
}
+
void ha_heap::update_key_stats()
{
- for (uint i= 0; i < table->keys; i++)
+ for (uint i= 0; i < table->s->keys; i++)
{
KEY *key=table->key_info+i;
if (!key->rec_per_key)
@@ -124,17 +157,18 @@ void ha_heap::update_key_stats()
key_stats_ok= TRUE;
}
+
int ha_heap::write_row(byte * buf)
{
int res;
- statistic_increment(ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
update_auto_increment();
res= heap_write(file,buf);
- if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
- file->s->records)
+ if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
+ file->s->records))
key_stats_ok= FALSE;
return res;
}
@@ -142,7 +176,7 @@ int ha_heap::write_row(byte * buf)
int ha_heap::update_row(const byte * old_data, byte * new_data)
{
int res;
- statistic_increment(ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
res= heap_update(file,old_data,new_data);
@@ -155,9 +189,9 @@ int ha_heap::update_row(const byte * old_data, byte * new_data)
int ha_heap::delete_row(const byte * buf)
{
int res;
- statistic_increment(ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
res= heap_delete(file,buf);
- if (!res && table->tmp_table == NO_TMP_TABLE &&
+ if (!res && table->s->tmp_table == NO_TMP_TABLE &&
++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
key_stats_ok= FALSE;
return res;
@@ -167,7 +201,8 @@ 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);
+ statistic_increment(table->in_use->status_var.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;
return error;
@@ -176,7 +211,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error= heap_rkey(file, buf, active_index, key, key_len,
HA_READ_PREFIX_LAST);
table->status= error ? STATUS_NOT_FOUND : 0;
@@ -186,7 +222,8 @@ int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len)
int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(ha_read_key_count, &LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error = heap_rkey(file, buf, index, key, key_len, find_flag);
table->status = error ? STATUS_NOT_FOUND : 0;
return error;
@@ -195,7 +232,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=heap_rnext(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -204,7 +242,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_prev_count,
+ &LOCK_status);
int error=heap_rprev(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -213,7 +252,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_first_count,
+ &LOCK_status);
int error=heap_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -222,7 +262,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_last_count,
+ &LOCK_status);
int error=heap_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -235,7 +276,8 @@ int ha_heap::rnd_init(bool scan)
int ha_heap::rnd_next(byte *buf)
{
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
int error=heap_scan(file, buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -245,7 +287,8 @@ int ha_heap::rnd_pos(byte * buf, byte *pos)
{
int error;
HEAP_PTR position;
- statistic_increment(ha_read_rnd_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
memcpy_fixed((char*) &position,pos,sizeof(HEAP_PTR));
error=heap_rrnd(file, buf, position);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -289,7 +332,7 @@ int ha_heap::extra(enum ha_extra_function operation)
int ha_heap::delete_all_rows()
{
heap_clear(file);
- if (table->tmp_table == NO_TMP_TABLE)
+ if (table->s->tmp_table == NO_TMP_TABLE)
key_stats_ok= FALSE;
return 0;
}
@@ -449,35 +492,35 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
min_key->flag != HA_READ_KEY_EXACT ||
max_key->flag != HA_READ_AFTER_KEY)
return HA_POS_ERROR; // Can only use exact keys
- else
- {
- /* Assert that info() did run. We need current statistics here. */
- DBUG_ASSERT(key_stats_ok);
- return key->rec_per_key[key->key_parts-1];
- }
+
+ /* Assert that info() did run. We need current statistics here. */
+ DBUG_ASSERT(key_stats_ok);
+ return key->rec_per_key[key->key_parts-1];
}
int ha_heap::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
- uint key, parts, mem_per_row= 0;
+ uint key, parts, mem_per_row= 0, keys= table_arg->s->keys;
uint auto_key= 0, auto_key_type= 0;
ha_rows max_rows;
HP_KEYDEF *keydef;
HA_KEYSEG *seg;
char buff[FN_REFLEN];
int error;
+ TABLE_SHARE *share= table_arg->s;
+ bool found_real_auto_increment= 0;
- for (key= parts= 0; key < table_arg->keys; key++)
+ for (key= parts= 0; key < keys; key++)
parts+= table_arg->key_info[key].key_parts;
- if (!(keydef= (HP_KEYDEF*) my_malloc(table_arg->keys * sizeof(HP_KEYDEF) +
+ if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) +
parts * sizeof(HA_KEYSEG),
MYF(MY_WME))))
return my_errno;
- seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + table_arg->keys);
- for (key= 0; key < table_arg->keys; key++)
+ seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + keys);
+ for (key= 0; key < keys; key++)
{
KEY *pos= table_arg->key_info+key;
KEY_PART_INFO *key_part= pos->key_part;
@@ -500,22 +543,26 @@ int ha_heap::create(const char *name, TABLE *table_arg,
default:
DBUG_ASSERT(0); // cannot happen
}
- keydef[key].algorithm= ((pos->algorithm == HA_KEY_ALG_UNDEF) ?
- HA_KEY_ALG_HASH : pos->algorithm);
for (; key_part != key_part_end; key_part++, seg++)
{
Field *field= key_part->field;
+
if (pos->algorithm == HA_KEY_ALG_BTREE)
seg->type= field->key_type();
else
{
- if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT)
+ if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
+ seg->type != HA_KEYTYPE_VARTEXT1 &&
+ seg->type != HA_KEYTYPE_VARTEXT2 &&
+ seg->type != HA_KEYTYPE_VARBINARY1 &&
+ seg->type != HA_KEYTYPE_VARBINARY2)
seg->type= HA_KEYTYPE_BINARY;
}
seg->start= (uint) key_part->offset;
seg->length= (uint) key_part->length;
- seg->flag = 0;
+ seg->flag= key_part->key_part_flag;
+
seg->charset= field->charset();
if (field->null_ptr)
{
@@ -529,7 +576,7 @@ int ha_heap::create(const char *name, TABLE *table_arg,
}
if (field->flags & AUTO_INCREMENT_FLAG &&
table_arg->found_next_number_field &&
- key == table_arg->next_number_index)
+ key == share->next_number_index)
{
/*
Store key number and type for found auto_increment key
@@ -540,21 +587,29 @@ int ha_heap::create(const char *name, TABLE *table_arg,
}
}
}
- mem_per_row+= MY_ALIGN(table_arg->reclength + 1, sizeof(char*));
+ mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*));
+ max_rows = (ha_rows) (table->in_use->variables.max_heap_table_size /
+ mem_per_row);
+ if (table_arg->found_next_number_field)
+ {
+ keydef[share->next_number_index].flag|= HA_AUTO_KEY;
+ found_real_auto_increment= share->next_number_key_offset == 0;
+ }
HP_CREATE_INFO hp_create_info;
hp_create_info.auto_key= auto_key;
hp_create_info.auto_key_type= auto_key_type;
hp_create_info.auto_increment= (create_info->auto_increment_value ?
create_info->auto_increment_value - 1 : 0);
hp_create_info.max_table_size=current_thd->variables.max_heap_table_size;
+ hp_create_info.with_auto_increment= found_real_auto_increment;
max_rows = (ha_rows) (hp_create_info.max_table_size / mem_per_row);
error= heap_create(fn_format(buff,name,"","",
MY_REPLACE_EXT|MY_UNPACK_FILENAME),
- table_arg->keys,keydef, table_arg->reclength,
- (ulong) ((table_arg->max_rows < max_rows &&
- table_arg->max_rows) ?
- table_arg->max_rows : max_rows),
- (ulong) table_arg->min_rows, &hp_create_info);
+ keys, keydef, share->reclength,
+ (ulong) ((share->max_rows < max_rows &&
+ share->max_rows) ?
+ share->max_rows : max_rows),
+ (ulong) share->min_rows, &hp_create_info);
my_free((gptr) keydef, MYF(0));
if (file)
info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
@@ -569,7 +624,7 @@ void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
create_info->auto_increment_value= auto_increment_value;
}
-longlong ha_heap::get_auto_increment()
+ulonglong ha_heap::get_auto_increment()
{
ha_heap::info(HA_STATUS_AUTO);
return auto_increment_value;
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index cbe2474492d..7c4227e952c 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -31,15 +31,20 @@ class ha_heap: public handler
uint records_changed;
bool key_stats_ok;
public:
- ha_heap(TABLE *table): handler(table), file(0), records_changed(0),
- key_stats_ok(0) {}
+ ha_heap(TABLE *table);
~ha_heap() {}
- const char *table_type() const { return "HEAP"; }
+ const char *table_type() const
+ {
+ return (table->in_use->variables.sql_mode & MODE_MYSQL323) ?
+ "HEAP" : "MEMORY";
+ }
const char *index_type(uint inx)
{
return ((table->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ? "BTREE" :
"HASH");
}
+ /* Rows also use a fixed-size format */
+ enum row_type get_row_type() const { return ROW_TYPE_FIXED; }
const char **bas_ext() const;
ulong table_flags() const
{
@@ -66,7 +71,7 @@ public:
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
- longlong get_auto_increment();
+ ulonglong get_auto_increment();
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,
@@ -95,6 +100,12 @@ public:
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
+ int cmp_ref(const byte *ref1, const byte *ref2)
+ {
+ HEAP_PTR ptr1=*(HEAP_PTR*)ref1;
+ HEAP_PTR ptr2=*(HEAP_PTR*)ref2;
+ return ptr1 < ptr2? -1 : (ptr1 > ptr2? 1 : 0);
+ }
private:
void update_key_stats();
};
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index b30ddfe8227..4ed5fadb603 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & Innobase Oy
+/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,15 +14,14 @@
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 defines the InnoDB handler: the interface between MySQL and
-InnoDB
+/* This file defines the InnoDB handler: the interface between MySQL and InnoDB
NOTE: You can only use noninlined InnoDB functions in this file, because we
have disables the InnoDB inlining in this file. */
-/* TODO list for the InnoDB handler in 4.1:
- - Remove the flag innodb_active_trans from thd and replace it with a
- function call innodb_active_trans(thd), which looks at the InnoDB
+/* TODO list for the InnoDB handler in 5.0:
+ - Remove the flag trx->active_trans and look at the InnoDB
trx struct state field
+ - fix savepoint functions to use savepoint storage area
- Find out what kind of problems the OS X case-insensitivity causes to
table and database names; should we 'normalize' the names like we do
in Windows?
@@ -46,9 +45,62 @@ have disables the InnoDB inlining in this file. */
#include "ha_innodb.h"
-pthread_mutex_t innobase_mutex;
+pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */
+ prepare_commit_mutex; /* to force correct commit order in
+ binlog */
+ulong commit_threads= 0;
+pthread_mutex_t commit_threads_m;
+pthread_cond_t commit_cond;
+pthread_mutex_t commit_cond_m;
bool innodb_inited= 0;
+/*-----------------------------------------------------------------*/
+/* These variables are used to implement (semi-)synchronous MySQL binlog
+replication for InnoDB tables. */
+
+pthread_cond_t innobase_repl_cond; /* Posix cond variable;
+ this variable is signaled
+ when enough binlog has been
+ sent to slave, so that a
+ waiting trx can return the
+ 'ok' message to the client
+ for a commit */
+pthread_mutex_t innobase_repl_cond_mutex; /* Posix cond variable mutex
+ that also protects the next
+ innobase_repl_... variables */
+uint innobase_repl_state; /* 1 if synchronous replication
+ is switched on and is working
+ ok; else 0 */
+uint innobase_repl_file_name_inited = 0; /* This is set to 1 when
+ innobase_repl_file_name
+ contains meaningful data */
+char* innobase_repl_file_name; /* The binlog name up to which
+ we have sent some binlog to
+ the slave */
+my_off_t innobase_repl_pos; /* The position in that file
+ up to which we have sent the
+ binlog to the slave */
+uint innobase_repl_n_wait_threads = 0; /* This tells how many
+ transactions currently are
+ waiting for the binlog to be
+ sent to the client */
+uint innobase_repl_wait_file_name_inited = 0; /* This is set to 1
+ when we know the 'smallest'
+ wait position */
+char* innobase_repl_wait_file_name; /* NULL, or the 'smallest'
+ innobase_repl_file_name that
+ a transaction is waiting for */
+my_off_t innobase_repl_wait_pos; /* The smallest position in
+ that file that a trx is
+ waiting for: the trx can
+ proceed and send an 'ok' to
+ the client when MySQL has sent
+ the binlog up to this position
+ to the slave */
+/*-----------------------------------------------------------------*/
+
+
+
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB
uses unsigned char; the header univ.i which we include next defines
'byte' as a macro which expands to 'unsigned char' */
@@ -80,6 +132,7 @@ extern "C" {
#include "../innobase/include/fsp0fsp.h"
#include "../innobase/include/sync0sync.h"
#include "../innobase/include/fil0fil.h"
+#include "../innobase/include/trx0xa.h"
}
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
@@ -87,6 +140,7 @@ extern "C" {
uint innobase_init_flags = 0;
ulong innobase_cache_size = 0;
+ulong innobase_large_page_size = 0;
/* The default values for the following, type long, start-up parameters
are declared in mysqld.cc: */
@@ -95,9 +149,8 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_log_file_size, innobase_log_buffer_size,
innobase_buffer_pool_awe_mem_mb,
innobase_buffer_pool_size, innobase_additional_mem_pool_size,
- innobase_file_io_threads, innobase_lock_wait_timeout,
- innobase_thread_concurrency, innobase_force_recovery,
- innobase_open_files;
+ innobase_file_io_threads, innobase_lock_wait_timeout,
+ innobase_force_recovery, innobase_open_files;
/* The default values for the following char* start-up parameters
are determined in innobase_init below: */
@@ -114,12 +167,12 @@ char* innobase_unix_file_flush_method = NULL;
values */
uint innobase_flush_log_at_trx_commit = 1;
+ulong innobase_fast_shutdown = 1;
my_bool innobase_log_archive = FALSE;/* unused */
+my_bool innobase_use_doublewrite = TRUE;
+my_bool innobase_use_checksums = TRUE;
+my_bool innobase_use_large_pages = FALSE;
my_bool innobase_use_native_aio = FALSE;
-my_bool innobase_fast_shutdown = TRUE;
-my_bool innobase_very_fast_shutdown = FALSE; /* this can be set to
- 1 just prior calling
- innobase_end() */
my_bool innobase_file_per_table = FALSE;
my_bool innobase_locks_unsafe_for_binlog = FALSE;
my_bool innobase_create_status_file = FALSE;
@@ -136,8 +189,6 @@ ulong innobase_active_counter = 0;
char* innobase_home = NULL;
-char innodb_dummy_stmt_trx_handle = 'D';
-
static HASH innobase_open_tables;
#ifdef __NETWARE__ /* some special cleanup for NetWare */
@@ -148,6 +199,129 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
my_bool not_used __attribute__((unused)));
static INNOBASE_SHARE *get_share(const char *table_name);
static void free_share(INNOBASE_SHARE *share);
+static int innobase_close_connection(THD* thd);
+static int innobase_commit(THD* thd, bool all);
+static int innobase_rollback(THD* thd, bool all);
+static int innobase_rollback_to_savepoint(THD* thd, void *savepoint);
+static int innobase_savepoint(THD* thd, void *savepoint);
+static int innobase_release_savepoint(THD* thd, void *savepoint);
+
+static handlerton innobase_hton = {
+ "InnoDB",
+ 0, /* slot */
+ sizeof(trx_named_savept_t), /* savepoint size. TODO: use it */
+ innobase_close_connection,
+ innobase_savepoint,
+ innobase_rollback_to_savepoint,
+ innobase_release_savepoint,
+ innobase_commit, /* commit */
+ innobase_rollback, /* rollback */
+ innobase_xa_prepare, /* prepare */
+ innobase_xa_recover, /* recover */
+ innobase_commit_by_xid, /* commit_by_xid */
+ innobase_rollback_by_xid, /* rollback_by_xid */
+ innobase_create_cursor_view,
+ innobase_set_cursor_view,
+ innobase_close_cursor_view,
+ HTON_NO_FLAGS
+};
+
+/*********************************************************************
+Commits a transaction in an InnoDB database. */
+
+void
+innobase_commit_low(
+/*================*/
+ trx_t* trx); /* in: transaction handle */
+
+struct show_var_st innodb_status_variables[]= {
+ {"buffer_pool_pages_data",
+ (char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
+ {"buffer_pool_pages_dirty",
+ (char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG},
+ {"buffer_pool_pages_flushed",
+ (char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
+ {"buffer_pool_pages_free",
+ (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
+ {"buffer_pool_pages_latched",
+ (char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
+ {"buffer_pool_pages_misc",
+ (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
+ {"buffer_pool_pages_total",
+ (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
+ {"buffer_pool_read_ahead_rnd",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
+ {"buffer_pool_read_ahead_seq",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
+ {"buffer_pool_read_requests",
+ (char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
+ {"buffer_pool_reads",
+ (char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
+ {"buffer_pool_wait_free",
+ (char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
+ {"buffer_pool_write_requests",
+ (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
+ {"data_fsyncs",
+ (char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
+ {"data_pending_fsyncs",
+ (char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
+ {"data_pending_reads",
+ (char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
+ {"data_pending_writes",
+ (char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
+ {"data_read",
+ (char*) &export_vars.innodb_data_read, SHOW_LONG},
+ {"data_reads",
+ (char*) &export_vars.innodb_data_reads, SHOW_LONG},
+ {"data_writes",
+ (char*) &export_vars.innodb_data_writes, SHOW_LONG},
+ {"data_written",
+ (char*) &export_vars.innodb_data_written, SHOW_LONG},
+ {"dblwr_pages_written",
+ (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
+ {"dblwr_writes",
+ (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
+ {"log_waits",
+ (char*) &export_vars.innodb_log_waits, SHOW_LONG},
+ {"log_write_requests",
+ (char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
+ {"log_writes",
+ (char*) &export_vars.innodb_log_writes, SHOW_LONG},
+ {"os_log_fsyncs",
+ (char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
+ {"os_log_pending_fsyncs",
+ (char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
+ {"os_log_pending_writes",
+ (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
+ {"os_log_written",
+ (char*) &export_vars.innodb_os_log_written, SHOW_LONG},
+ {"page_size",
+ (char*) &export_vars.innodb_page_size, SHOW_LONG},
+ {"pages_created",
+ (char*) &export_vars.innodb_pages_created, SHOW_LONG},
+ {"pages_read",
+ (char*) &export_vars.innodb_pages_read, SHOW_LONG},
+ {"pages_written",
+ (char*) &export_vars.innodb_pages_written, SHOW_LONG},
+ {"row_lock_current_waits",
+ (char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
+ {"row_lock_time",
+ (char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
+ {"row_lock_time_avg",
+ (char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
+ {"row_lock_time_max",
+ (char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
+ {"row_lock_waits",
+ (char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
+ {"rows_deleted",
+ (char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
+ {"rows_inserted",
+ (char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
+ {"rows_read",
+ (char*) &export_vars.innodb_rows_read, SHOW_LONG},
+ {"rows_updated",
+ (char*) &export_vars.innodb_rows_updated, SHOW_LONG},
+ {NullS, NullS, SHOW_LONG}};
/* General functions */
@@ -160,7 +334,7 @@ innodb_srv_conc_enter_innodb(
/*=========================*/
trx_t* trx) /* in: transaction handle */
{
- if (srv_thread_concurrency >= 500) {
+ if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) {
return;
}
@@ -177,7 +351,7 @@ innodb_srv_conc_exit_innodb(
/*========================*/
trx_t* trx) /* in: transaction handle */
{
- if (srv_thread_concurrency >= 500) {
+ if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) {
return;
}
@@ -215,9 +389,20 @@ documentation, see handler.cc. */
void
innobase_release_temporary_latches(
/*===============================*/
- void* innobase_tid)
+ THD *thd)
{
- innobase_release_stat_resources((trx_t*)innobase_tid);
+ trx_t* trx;
+
+ if (!innodb_inited) {
+
+ return;
+ }
+
+ trx = (trx_t*) thd->ha_data[innobase_hton.slot];
+
+ if (trx) {
+ innobase_release_stat_resources(trx);
+ }
}
/************************************************************************
@@ -278,13 +463,9 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
- /* Since we rolled back the whole transaction, we must
- tell it also to MySQL so that MySQL knows to empty the
- cached binlog for this transaction */
-
- if (thd) {
- ha_rollback(thd);
- }
+ /* Starting from 5.0.13, we let MySQL just roll back the
+ latest SQL statement in a lock wait timeout. Previously, we
+ rolled back the whole transaction. */
return(HA_ERR_LOCK_WAIT_TIMEOUT);
@@ -357,7 +538,7 @@ innobase_mysql_prepare_print_arbitrary_thd(void)
}
/*****************************************************************
-Relases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
+Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
function! */
extern "C"
@@ -369,24 +550,25 @@ innobase_mysql_end_print_arbitrary_thd(void)
}
/*****************************************************************
-Prints info of a THD object (== user session thread) to the
-standard output. NOTE that /mysql/innobase/trx/trx0trx.c must contain
-the prototype for this function! */
+Prints info of a THD object (== user session thread) to the given file.
+NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for
+this function! */
extern "C"
void
innobase_mysql_print_thd(
/*=====================*/
- FILE* f, /* in: output stream */
- void* input_thd)/* in: pointer to a MySQL THD object */
+ FILE* f, /* in: output stream */
+ void* input_thd, /* in: pointer to a MySQL THD object */
+ uint max_query_len) /* in: max query length to print, or 0 to
+ use the default max length */
{
const THD* thd;
const char* s;
- char buf[301];
thd = (const THD*) input_thd;
fprintf(f, "MySQL thread id %lu, query id %lu",
- thd->thread_id, thd->query_id);
+ thd->thread_id, (ulong) thd->query_id);
if (thd->host) {
putc(' ', f);
fputs(thd->host, f);
@@ -408,31 +590,81 @@ innobase_mysql_print_thd(
}
if ((s = thd->query)) {
- /* determine the length of the query string */
- uint32 i, len;
+ /* 3100 is chosen because currently 3000 is the maximum
+ max_query_len we ever give this. */
+ char buf[3100];
+ uint len;
+
+ /* If buf is too small, we dynamically allocate storage
+ in this. */
+ char* dyn_str = NULL;
+
+ /* Points to buf or dyn_str. */
+ char* str = buf;
+
+ if (max_query_len == 0)
+ {
+ /* ADDITIONAL SAFETY: the default is to print at
+ most 300 chars to reduce the probability of a
+ seg fault if there is a race in
+ thd->query_length in MySQL; after May 14, 2004
+ probably no race any more, but better be
+ safe */
+ max_query_len = 300;
+ }
- len = thd->query_length;
-
- if (len > 300) {
- len = 300; /* ADDITIONAL SAFETY: print at most
- 300 chars to reduce the probability of
- a seg fault if there is a race in
- thd->query_length in MySQL; after
- May 14, 2004 probably no race any more,
- but better be safe */
+ len = min(thd->query_length, max_query_len);
+
+ if (len > (sizeof(buf) - 1))
+ {
+ dyn_str = my_malloc(len + 1, MYF(0));
+ str = dyn_str;
}
- /* Use strmake to reduce the timeframe
- for a race, compared to fwrite() */
- i= (uint) (strmake(buf, s, len) - buf);
+ /* Use strmake to reduce the timeframe for a race,
+ compared to fwrite() */
+ len = (uint) (strmake(str, s, len) - str);
putc('\n', f);
- fwrite(buf, 1, i, f);
+ fwrite(str, 1, len, f);
+
+ if (dyn_str)
+ {
+ my_free(dyn_str, MYF(0));
+ }
}
putc('\n', f);
}
/**********************************************************************
+Get the variable length bounds of the given character set.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/data/data0type.ic! */
+extern "C"
+void
+innobase_get_cset_width(
+/*====================*/
+ ulint cset, /* in: MySQL charset-collation code */
+ ulint* mbminlen, /* out: minimum length of a char (in bytes) */
+ ulint* mbmaxlen) /* out: maximum length of a char (in bytes) */
+{
+ CHARSET_INFO* cs;
+ ut_ad(cset < 256);
+ ut_ad(mbminlen);
+ ut_ad(mbmaxlen);
+
+ cs = all_charsets[cset];
+ if (cs) {
+ *mbminlen = cs->mbminlen;
+ *mbmaxlen = cs->mbmaxlen;
+ } else {
+ ut_a(cset == 0);
+ *mbminlen = *mbmaxlen = 0;
+ }
+}
+
+/**********************************************************************
Compares NUL-terminated UTF-8 strings case insensitively.
NOTE that the exact prototype of this function has to be in
@@ -498,9 +730,10 @@ innobase_mysql_tmpfile(void)
if (fd2 < 0) {
DBUG_PRINT("error",("Got error %d on dup",fd2));
my_errno=errno;
- my_error(EE_OUT_OF_FILERESOURCES,
- MYF(ME_BELL+ME_WAITTANG), filename, my_errno);
- }
+ my_error(EE_OUT_OF_FILERESOURCES,
+ MYF(ME_BELL+ME_WAITTANG),
+ filename, my_errno);
+ }
my_close(fd, MYF(MY_WME));
}
return(fd2);
@@ -521,25 +754,21 @@ check_trx_exists(
ut_ad(thd == current_thd);
- trx = (trx_t*) thd->transaction.all.innobase_tid;
+ trx = (trx_t*) thd->ha_data[innobase_hton.slot];
if (trx == NULL) {
DBUG_ASSERT(thd != NULL);
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
- trx->mysql_query_str = &((*thd).query);
-
- thd->transaction.all.innobase_tid = trx;
+ trx->mysql_query_str = &(thd->query);
+ trx->active_trans = 0;
- /* The execution of a single SQL statement is denoted by
- a 'transaction' handle which is a dummy pointer: InnoDB
- remembers internally where the latest SQL statement
- started, and if error handling requires rolling back the
- latest statement, InnoDB does a rollback to a savepoint. */
+ /* Update the info whether we should skip XA steps that eat
+ CPU time */
+ trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
- thd->transaction.stmt.innobase_tid =
- (void*)&innodb_dummy_stmt_trx_handle;
+ thd->ha_data[innobase_hton.slot] = trx;
} else {
if (trx->magic_n != TRX_MAGIC_N) {
mem_analyze_corruption((byte*)trx);
@@ -563,6 +792,24 @@ check_trx_exists(
return(trx);
}
+
+/*************************************************************************
+Construct ha_innobase handler. */
+
+ha_innobase::ha_innobase(TABLE *table_arg)
+ :handler(&innobase_hton, table_arg),
+ int_table_flags(HA_REC_NOT_IN_SEQ |
+ HA_NULL_IN_KEY |
+ HA_CAN_INDEX_BLOBS |
+ HA_CAN_SQL_HANDLER |
+ HA_NOT_EXACT_COUNT |
+ HA_PRIMARY_KEY_IN_READ_INDEX |
+ HA_TABLE_SCAN_ON_INDEX),
+ last_dup_key((uint) -1),
+ start_of_scan(0),
+ num_write_row(0)
+{}
+
/*************************************************************************
Updates the user_thd field in a handle and also allocates a new InnoDB
transaction handle if needed, and updates the transaction fields in the
@@ -576,7 +823,7 @@ ha_innobase::update_thd(
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
trx_t* trx;
-
+
trx = check_trx_exists(thd);
if (prebuilt->trx != trx) {
@@ -589,6 +836,45 @@ ha_innobase::update_thd(
return(0);
}
+/*************************************************************************
+Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
+roll back the statement if the statement results in an error. This MUST be
+called for every SQL statement that may be rolled back by MySQL. Calling this
+several times to register the same statement is allowed, too. */
+inline
+void
+innobase_register_stmt(
+/*===================*/
+ THD* thd) /* in: MySQL thd (connection) object */
+{
+ /* Register the statement */
+ trans_register_ha(thd, FALSE, &innobase_hton);
+}
+
+/*************************************************************************
+Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
+to call the InnoDB prepare and commit, or rollback for the transaction. This
+MUST be called for every transaction for which the user may call commit or
+rollback. Calling this several times to register the same transaction is
+allowed, too.
+This function also registers the current SQL statement. */
+inline
+void
+innobase_register_trx_and_stmt(
+/*===========================*/
+ THD* thd) /* in: MySQL thd (connection) object */
+{
+ /* NOTE that actually innobase_register_stmt() registers also
+ the transaction in the AUTOCOMMIT=1 mode. */
+
+ innobase_register_stmt(thd);
+
+ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
+
+ /* No autocommit mode, register for a transaction */
+ trans_register_ha(thd, TRUE, &innobase_hton);
+ }
+}
/* BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
------------------------------------------------------------
@@ -643,7 +929,14 @@ returns TRUE for all tables in the query.
If thd is not in the autocommit state, this function also starts a new
transaction for thd if there is no active trx yet, and assigns a consistent
-read view to it if there is no read view yet. */
+read view to it if there is no read view yet.
+
+Why a deadlock of threads is not possible: the query cache calls this function
+at the start of a SELECT processing. Then the calling thread cannot be
+holding any InnoDB semaphores. The calling thread is holding the
+query cache mutex, and this function will reserver the InnoDB kernel mutex.
+Thus, the 'rank' in sync0sync.h of the MySQL query cache mutex is above
+the InnoDB kernel mutex. */
my_bool
innobase_query_caching_of_table_permitted(
@@ -658,8 +951,9 @@ innobase_query_caching_of_table_permitted(
char* full_name, /* in: concatenation of database name,
the null character '\0', and the table
name */
- uint full_name_len) /* in: length of the full name, i.e.
+ uint full_name_len, /* in: length of the full name, i.e.
len(dbname) + len(tablename) + 1 */
+ ulonglong *unused) /* unused for this engine */
{
ibool is_autocommit;
trx_t* trx;
@@ -674,10 +968,12 @@ innobase_query_caching_of_table_permitted(
return((my_bool)FALSE);
}
- trx = (trx_t*) thd->transaction.all.innobase_tid;
-
- if (trx == NULL) {
- trx = check_trx_exists(thd);
+ trx = check_trx_exists(thd);
+ if (trx->has_search_latch) {
+ ut_print_timestamp(stderr);
+ sql_print_error("The calling thread is holding the adaptive "
+ "search, latch though calling "
+ "innobase_query_caching_of_table_permitted.");
}
innobase_release_stat_resources(trx);
@@ -725,7 +1021,11 @@ innobase_query_caching_of_table_permitted(
/* The call of row_search_.. will start a new transaction if it is
not yet started */
- thd->transaction.all.innodb_active_trans = 1;
+ if (trx->active_trans == 0) {
+
+ innobase_register_trx_and_stmt(thd);
+ trx->active_trans = 1;
+ }
if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
@@ -755,6 +1055,10 @@ innobase_invalidate_query_cache(
ulint full_name_len) /* in: full name length where also the null
chars count */
{
+ /* Note that the sync0sync.h rank of the query cache mutex is just
+ above the InnoDB kernel mutex. The caller of this function must not
+ have latches of a lower rank. */
+
/* Argument TRUE below means we are using transactions */
#ifdef HAVE_QUERY_CACHE
query_cache.invalidate((THD*)(trx->mysql_thd),
@@ -781,7 +1085,19 @@ mysql_get_identifier_quote_char(
return(EOF);
}
return(get_quote_char_for_identifier((THD*) trx->mysql_thd,
- name, namelen));
+ name, (int) namelen));
+}
+
+/**************************************************************************
+Determines if the currently running transaction has been interrupted. */
+extern "C"
+ibool
+trx_is_interrupted(
+/*===============*/
+ /* out: TRUE if interrupted */
+ trx_t* trx) /* in: transaction */
+{
+ return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed);
}
/**************************************************************************
@@ -833,7 +1149,12 @@ ha_innobase::init_table_handle_for_HANDLER(void)
/* Set the MySQL flag to mark that there is an active transaction */
- current_thd->transaction.all.innodb_active_trans = 1;
+ if (prebuilt->trx->active_trans == 0) {
+
+ innobase_register_trx_and_stmt(current_thd);
+
+ prebuilt->trx->active_trans = 1;
+ }
/* We did the necessary inits in this function, no need to repeat them
in row_search_for_mysql */
@@ -856,12 +1177,14 @@ ha_innobase::init_table_handle_for_HANDLER(void)
prebuilt->read_just_key = FALSE;
prebuilt->used_in_HANDLER = TRUE;
+
+ prebuilt->keep_other_fields_on_keyread = FALSE;
}
/*************************************************************************
Opens an InnoDB database. */
-bool
+handlerton*
innobase_init(void)
/*===============*/
/* out: TRUE if error */
@@ -873,6 +1196,8 @@ innobase_init(void)
DBUG_ENTER("innobase_init");
+ ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
+
os_innodb_umask = (ulint)my_umask;
/* First calculate the default path for innodb_data_home_dir etc.,
@@ -936,7 +1261,9 @@ innobase_init(void)
if (ret == FALSE) {
sql_print_error(
"InnoDB: syntax error in innodb_data_file_path");
- DBUG_RETURN(TRUE);
+ my_free(internal_innobase_data_file_path,
+ MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(0);
}
/* -------------- Log files ---------------------------*/
@@ -962,11 +1289,12 @@ innobase_init(void)
&srv_log_group_home_dirs);
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
- fprintf(stderr,
- "InnoDB: syntax error in innodb_log_group_home_dir\n"
- "InnoDB: or a wrong number of mirrored log groups\n");
+ sql_print_error("syntax error in innodb_log_group_home_dir, or a "
+ "wrong number of mirrored log groups");
- DBUG_RETURN(TRUE);
+ my_free(internal_innobase_data_file_path,
+ MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(0);
}
/* --------------------------------------------------*/
@@ -1008,11 +1336,14 @@ innobase_init(void)
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
- srv_thread_concurrency = (ulint) innobase_thread_concurrency;
srv_force_recovery = (ulint) innobase_force_recovery;
- srv_fast_shutdown = (ibool) innobase_fast_shutdown;
+ srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
+ srv_use_checksums = (ibool) innobase_use_checksums;
+ os_use_large_pages = (ibool) innobase_use_large_pages;
+ os_large_page_size = (ulint) innobase_large_page_size;
+
srv_file_per_table = (ibool) innobase_file_per_table;
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
@@ -1021,13 +1352,13 @@ innobase_init(void)
srv_print_verbose_log = mysqld_embedded ? 0 : 1;
- /* Store the default charset-collation number of this MySQL
+ /* Store the default charset-collation number of this MySQL
installation */
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
- data_mysql_latin1_swedish_charset_coll =
- (ulint)my_charset_latin1.number;
+ ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
+ my_charset_latin1.number);
/* Store the latin1_swedish_ci character ordering table to InnoDB. For
non-latin1_swedish_ci charsets we use the MySQL comparison functions,
@@ -1049,13 +1380,18 @@ innobase_init(void)
err = innobase_start_or_create_for_mysql();
if (err != DB_SUCCESS) {
-
- DBUG_RETURN(1);
+ my_free(internal_innobase_data_file_path,
+ MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(0);
}
(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
(hash_get_key) innobase_get_key, 0, 0);
- pthread_mutex_init(&innobase_mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&commit_cond, NULL);
innodb_inited= 1;
/* If this is a replication slave and we needed to do a crash recovery,
@@ -1073,7 +1409,7 @@ innobase_init(void)
glob_mi.pos = trx_sys_mysql_master_log_pos;
}
*/
- DBUG_RETURN(0);
+ DBUG_RETURN(&innobase_hton);
}
/***********************************************************************
@@ -1093,23 +1429,21 @@ innobase_end(void)
set_panic_flag_for_netware();
}
#endif
- if (innodb_inited)
- {
- if (innobase_very_fast_shutdown) {
- srv_very_fast_shutdown = TRUE;
- fprintf(stderr,
-"InnoDB: MySQL has requested a very fast shutdown without flushing\n"
-"InnoDB: the InnoDB buffer pool to data files. At the next mysqld startup\n"
-"InnoDB: InnoDB will do a crash recovery!\n");
+ if (innodb_inited) {
- }
-
- innodb_inited= 0;
- if (innobase_shutdown_for_mysql() != DB_SUCCESS)
- err= 1;
- hash_free(&innobase_open_tables);
- my_free(internal_innobase_data_file_path,MYF(MY_ALLOW_ZERO_PTR));
- pthread_mutex_destroy(&innobase_mutex);
+ srv_fast_shutdown = (ulint) innobase_fast_shutdown;
+ innodb_inited = 0;
+ if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
+ err = 1;
+ }
+ hash_free(&innobase_open_tables);
+ my_free(internal_innobase_data_file_path,
+ MYF(MY_ALLOW_ZERO_PTR));
+ pthread_mutex_destroy(&innobase_share_mutex);
+ pthread_mutex_destroy(&prepare_commit_mutex);
+ pthread_mutex_destroy(&commit_threads_m);
+ pthread_mutex_destroy(&commit_cond_m);
+ pthread_cond_destroy(&commit_cond);
}
DBUG_RETURN(err);
@@ -1147,13 +1481,15 @@ innobase_commit_low(
}
#ifdef HAVE_REPLICATION
- if (current_thd->slave_thread) {
+ THD *thd=current_thd;
+
+ if (thd && thd->slave_thread) {
/* Update the replication position info inside InnoDB */
trx->mysql_master_log_file_name
= active_mi->rli.group_master_log_name;
- trx->mysql_master_log_pos= ((ib_longlong)
- active_mi->rli.future_group_master_log_pos);
+ trx->mysql_master_log_pos = ((ib_longlong)
+ active_mi->rli.future_group_master_log_pos);
}
#endif /* HAVE_REPLICATION */
@@ -1197,7 +1533,12 @@ innobase_start_trx_and_assign_read_view(
/* Set the MySQL flag to mark that there is an active transaction */
- current_thd->transaction.all.innodb_active_trans = 1;
+ if (trx->active_trans == 0) {
+
+ innobase_register_trx_and_stmt(current_thd);
+
+ trx->active_trans = 1;
+ }
DBUG_RETURN(0);
}
@@ -1205,16 +1546,15 @@ innobase_start_trx_and_assign_read_view(
/*********************************************************************
Commits a transaction in an InnoDB database or marks an SQL statement
ended. */
-
+static
int
innobase_commit(
/*============*/
/* out: 0 */
THD* thd, /* in: MySQL thread handle of the user for whom
the transaction should be committed */
- void* trx_handle)/* in: InnoDB trx handle or
- &innodb_dummy_stmt_trx_handle: the latter means
- that the current SQL statement ended */
+ bool all) /* in: TRUE - commit transaction
+ FALSE - the current SQL statement ended */
{
trx_t* trx;
@@ -1223,43 +1563,83 @@ innobase_commit(
trx = check_trx_exists(thd);
+ /* Update the info whether we should skip XA steps that eat CPU time */
+ trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
+
/* Release a possible FIFO ticket and search latch. Since we will
reserve the kernel mutex, we have to release the search system latch
first to obey the latching order. */
- innobase_release_stat_resources(trx);
-
- /* The flag thd->transaction.all.innodb_active_trans is set to 1 in
+ if (trx->has_search_latch) {
+ trx_search_latch_release_if_reserved(trx);
+ }
+
+ /* The flag trx->active_trans is set to 1 in
1. ::external_lock(),
2. ::start_stmt(),
3. innobase_query_caching_of_table_permitted(),
4. innobase_savepoint(),
5. ::init_table_handle_for_HANDLER(),
- 6. innobase_start_trx_and_assign_read_view()
+ 6. innobase_start_trx_and_assign_read_view(),
+ 7. ::transactional_table_lock()
and it is only set to 0 in a commit or a rollback. If it is 0 we know
there cannot be resources to be freed and we could return immediately.
For the time being, we play safe and do the cleanup though there should
be nothing to clean up. */
- if (thd->transaction.all.innodb_active_trans == 0
+ if (trx->active_trans == 0
&& trx->conc_state != TRX_NOT_STARTED) {
- fprintf(stderr,
-"InnoDB: Error: thd->transaction.all.innodb_active_trans == 0\n"
-"InnoDB: but trx->conc_state != TRX_NOT_STARTED\n");
+ sql_print_error("trx->active_trans == 0, but trx->conc_state != "
+ "TRX_NOT_STARTED");
}
-
- if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle
+ if (all
|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
- /* We were instructed to commit the whole transaction, or
+ /* We were instructed to commit the whole transaction, or
this is an SQL statement end and autocommit is on */
+ /* We need current binlog position for ibbackup to work.
+ Note, the position is current because of prepare_commit_mutex */
+retry:
+ if (srv_commit_concurrency > 0)
+ {
+ pthread_mutex_lock(&commit_cond_m);
+ commit_threads++;
+ if (commit_threads > srv_commit_concurrency)
+ {
+ commit_threads--;
+ pthread_cond_wait(&commit_cond, &commit_cond_m);
+ pthread_mutex_unlock(&commit_cond_m);
+ goto retry;
+ }
+ else
+ pthread_mutex_unlock(&commit_cond_m);
+ }
+
+ trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
+ trx->mysql_log_offset =
+ (ib_longlong)mysql_bin_log.get_log_file()->pos_in_file;
+
innobase_commit_low(trx);
- thd->transaction.all.innodb_active_trans = 0;
+ if (srv_commit_concurrency > 0)
+ {
+ pthread_mutex_lock(&commit_cond_m);
+ commit_threads--;
+ pthread_cond_signal(&commit_cond);
+ pthread_mutex_unlock(&commit_cond_m);
+ }
+
+ if (trx->active_trans == 2) {
+
+ pthread_mutex_unlock(&prepare_commit_mutex);
+ }
+
+ trx->active_trans = 0;
+
} else {
/* We just mark the SQL statement ended and do not do a
transaction commit */
@@ -1279,12 +1659,20 @@ innobase_commit(
/* Tell the InnoDB server that there might be work for utility
threads: */
+ if (trx->declared_to_be_inside_innodb) {
+ /* Release our possible ticket in the FIFO */
+ srv_conc_force_exit_innodb(trx);
+ }
srv_active_wake_master_thread();
DBUG_RETURN(0);
}
+/* TODO: put the
+MySQL-4.1 functionality back to 5.0. This is needed to get InnoDB Hot Backup
+to work. */
+
/*********************************************************************
This is called when MySQL writes the binlog entry for the current
transaction. Writes to the InnoDB tablespace info which tells where the
@@ -1310,18 +1698,70 @@ innobase_report_binlog_offset_and_commit(
ut_a(trx != NULL);
- trx->mysql_log_file_name = log_file_name;
+ trx->mysql_log_file_name = log_file_name;
trx->mysql_log_offset = (ib_longlong)end_offset;
-
+
+#ifdef HAVE_REPLICATION
+ if (thd->variables.sync_replication) {
+ /* Let us store the binlog file name and the position, so that
+ we know how long to wait for the binlog to the replicated to
+ the slave in synchronous replication. */
+
+ if (trx->repl_wait_binlog_name == NULL) {
+
+ trx->repl_wait_binlog_name =
+ (char*)mem_alloc_noninline(FN_REFLEN + 100);
+ }
+
+ ut_a(strlen(log_file_name) < FN_REFLEN + 100);
+
+ strcpy(trx->repl_wait_binlog_name, log_file_name);
+
+ trx->repl_wait_binlog_pos = (ib_longlong)end_offset;
+ }
+#endif /* HAVE_REPLICATION */
trx->flush_log_later = TRUE;
- innobase_commit(thd, trx_handle);
+ innobase_commit(thd, TRUE);
trx->flush_log_later = FALSE;
return(0);
}
+#if 0
+/***********************************************************************
+This function stores the 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);
+
+ /* Synchronous flush of the log buffer to disk */
+ log_buffer_flush_to_disk();
+}
+#endif
+
/*********************************************************************
This is called after MySQL has written the binlog entry for the current
transaction. Flushes the InnoDB log files to disk if required. */
@@ -1330,36 +1770,248 @@ int
innobase_commit_complete(
/*=====================*/
/* out: 0 */
- void* trx_handle) /* in: InnoDB trx handle */
+ THD* thd) /* in: user thread */
{
trx_t* trx;
- if (srv_flush_log_at_trx_commit == 0) {
+ trx = (trx_t*) thd->ha_data[innobase_hton.slot];
- return(0);
- }
+ if (trx && trx->active_trans) {
- trx = (trx_t*)trx_handle;
+ trx->active_trans = 0;
- ut_a(trx != NULL);
+ if (srv_flush_log_at_trx_commit == 0) {
+
+ return(0);
+ }
+
+ trx_commit_complete_for_mysql(trx);
+ }
+
+#ifdef HAVE_REPLICATION
+ if (thd->variables.sync_replication
+ && trx->repl_wait_binlog_name
+ && innobase_repl_state != 0) {
+
+ struct timespec abstime;
+ int cmp;
+ int ret;
+
+ /* In synchronous replication, let us wait until the MySQL
+ replication has sent the relevant binlog segment to the
+ replication slave. */
+
+ pthread_mutex_lock(&innobase_repl_cond_mutex);
+try_again:
+ if (innobase_repl_state == 0) {
+
+ pthread_mutex_unlock(&innobase_repl_cond_mutex);
+
+ return(0);
+ }
+
+ cmp = strcmp(innobase_repl_file_name,
+ trx->repl_wait_binlog_name);
+ if (cmp > 0
+ || (cmp == 0 && innobase_repl_pos
+ >= (my_off_t)trx->repl_wait_binlog_pos)) {
+ /* We have already sent the relevant binlog to the
+ slave: no need to wait here */
+
+ pthread_mutex_unlock(&innobase_repl_cond_mutex);
+
+/* printf("Binlog now sent\n"); */
+
+ return(0);
+ }
- trx_commit_complete_for_mysql(trx);
+ /* Let us update the info about the minimum binlog position
+ of waiting threads in the innobase_repl_... variables */
+ if (innobase_repl_wait_file_name_inited != 0) {
+ cmp = strcmp(trx->repl_wait_binlog_name,
+ innobase_repl_wait_file_name);
+ if (cmp < 0
+ || (cmp == 0 && (my_off_t)trx->repl_wait_binlog_pos
+ <= innobase_repl_wait_pos)) {
+ /* This thd has an even lower position, let
+ us update the minimum info */
+
+ strcpy(innobase_repl_wait_file_name,
+ trx->repl_wait_binlog_name);
+
+ innobase_repl_wait_pos =
+ trx->repl_wait_binlog_pos;
+ }
+ } else {
+ strcpy(innobase_repl_wait_file_name,
+ trx->repl_wait_binlog_name);
+
+ innobase_repl_wait_pos = trx->repl_wait_binlog_pos;
+
+ innobase_repl_wait_file_name_inited = 1;
+ }
+ set_timespec(abstime, thd->variables.sync_replication_timeout);
+
+ /* Let us suspend this thread to wait on the condition;
+ when replication has progressed far enough, we will release
+ these waiting threads. The following call
+ pthread_cond_timedwait also atomically unlocks
+ innobase_repl_cond_mutex. */
+
+ innobase_repl_n_wait_threads++;
+
+/* printf("Waiting for binlog to be sent\n"); */
+
+ ret = pthread_cond_timedwait(&innobase_repl_cond,
+ &innobase_repl_cond_mutex, &abstime);
+ innobase_repl_n_wait_threads--;
+
+ if (ret != 0) {
+ ut_print_timestamp(stderr);
+
+ sql_print_error("MySQL synchronous replication was "
+ "not able to send the binlog to the "
+ "slave within the timeout %lu. We "
+ "assume that the slave has become "
+ "inaccessible, and switch off "
+ "synchronous replication until the "
+ "communication to the slave works "
+ "again. MySQL synchronous replication "
+ "has sent binlog to the slave up to "
+ "file %s, position %lu. This "
+ "transaction needs it to be sent up "
+ "to file %s, position %lu.",
+ thd->variables.sync_replication_timeout,
+ innobase_repl_file_name,
+ (ulong) innobase_repl_pos,
+ trx->repl_wait_binlog_name,
+ (ulong) trx->repl_wait_binlog_pos);
+
+ innobase_repl_state = 0;
+
+ pthread_mutex_unlock(&innobase_repl_cond_mutex);
+
+ return(0);
+ }
+
+ goto try_again;
+ }
+#endif // HAVE_REPLICATION
return(0);
}
+#ifdef HAVE_REPLICATION
/*********************************************************************
-Rolls back a transaction or the latest SQL statement. */
+In synchronous replication, reports to InnoDB up to which binlog position
+we have sent the binlog to the slave. Note that replication is synchronous
+for one slave only. For other slaves, we do nothing in this function. This
+function is used in a replication master. */
int
+innobase_repl_report_sent_binlog(
+/*=============================*/
+ /* out: 0 */
+ THD* thd, /* in: thread doing the binlog communication to
+ the slave */
+ char* log_file_name, /* in: binlog file name */
+ my_off_t end_offset) /* in: the offset in the binlog file up to
+ which we sent the contents to the slave */
+{
+ int cmp;
+ ibool can_release_threads = 0;
+
+ /* If synchronous replication is not switched on, or this thd is
+ sending binlog to a slave where we do not need synchronous replication,
+ then return immediately */
+
+ if (thd->server_id != thd->variables.sync_replication_slave_id) {
+
+ /* Do nothing */
+
+ return(0);
+ }
+
+ pthread_mutex_lock(&innobase_repl_cond_mutex);
+
+ if (innobase_repl_state == 0) {
+
+ ut_print_timestamp(stderr);
+ sql_print_warning("Switching MySQL synchronous replication on "
+ "again at binlog file %s, position %lu",
+ log_file_name, (ulong) end_offset);
+
+ innobase_repl_state = 1;
+ }
+
+ /* The position should increase monotonically, since just one thread
+ is sending the binlog to the slave for which we want synchronous
+ replication. Let us check this, and print an error to the .err log
+ if that is not the case. */
+
+ if (innobase_repl_file_name_inited) {
+ cmp = strcmp(log_file_name, innobase_repl_file_name);
+
+ if (cmp < 0
+ || (cmp == 0 && end_offset < innobase_repl_pos)) {
+
+ ut_print_timestamp(stderr);
+ sql_print_error("MySQL synchronous replication has "
+ "sent binlog to the slave up to file "
+ "%s, position %lu, but now MySQL "
+ "reports that it sent the binlog only "
+ "up to file %s, position %lu",
+ innobase_repl_file_name,
+ (ulong) innobase_repl_pos,
+ log_file_name, (ulong) end_offset);
+ }
+ }
+
+ strcpy(innobase_repl_file_name, log_file_name);
+ innobase_repl_pos = end_offset;
+ innobase_repl_file_name_inited = 1;
+
+ if (innobase_repl_n_wait_threads > 0) {
+ /* Let us check if some of the waiting threads doing a trx
+ commit can now proceed */
+
+ cmp = strcmp(innobase_repl_file_name,
+ innobase_repl_wait_file_name);
+ if (cmp > 0
+ || (cmp == 0 && innobase_repl_pos
+ >= innobase_repl_wait_pos)) {
+
+ /* Yes, at least one waiting thread can now proceed:
+ let us release all waiting threads with a broadcast */
+
+ can_release_threads = 1;
+
+ innobase_repl_wait_file_name_inited = 0;
+ }
+ }
+
+ pthread_mutex_unlock(&innobase_repl_cond_mutex);
+
+ if (can_release_threads) {
+
+ pthread_cond_broadcast(&innobase_repl_cond);
+ }
+
+ return(0);
+}
+#endif /* HAVE_REPLICATION */
+
+/*********************************************************************
+Rolls back a transaction or the latest SQL statement. */
+
+static int
innobase_rollback(
/*==============*/
/* out: 0 or error number */
THD* thd, /* in: handle to the MySQL thread of the user
whose transaction should be rolled back */
- void* trx_handle)/* in: InnoDB trx handle or a dummy stmt handle;
- the latter means we roll back the latest SQL
- statement */
+ bool all) /* in: TRUE - commit transaction
+ FALSE - the current SQL statement ended */
{
int error = 0;
trx_t* trx;
@@ -1369,6 +2021,9 @@ innobase_rollback(
trx = check_trx_exists(thd);
+ /* Update the info whether we should skip XA steps that eat CPU time */
+ trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
+
/* Release a possible FIFO ticket and search latch. Since we will
reserve the kernel mutex, we have to release the search system latch
first to obey the latching order. */
@@ -1383,11 +2038,11 @@ innobase_rollback(
row_unlock_table_autoinc_for_mysql(trx);
}
- if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle
+ if (all
|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
error = trx_rollback_for_mysql(trx);
- thd->transaction.all.innodb_active_trans = 0;
+ trx->active_trans = 0;
} else {
error = trx_rollback_last_sql_stat_for_mysql(trx);
}
@@ -1396,23 +2051,54 @@ innobase_rollback(
}
/*********************************************************************
-Rolls back a transaction to a savepoint. */
+Rolls back a transaction */
int
+innobase_rollback_trx(
+/*==================*/
+ /* out: 0 or error number */
+ trx_t* trx) /* in: transaction */
+{
+ int error = 0;
+
+ DBUG_ENTER("innobase_rollback_trx");
+ DBUG_PRINT("trans", ("aborting transaction"));
+
+ /* Release a possible FIFO ticket and search latch. Since we will
+ reserve the kernel mutex, we have to release the search system latch
+ first to obey the latching order. */
+
+ innobase_release_stat_resources(trx);
+
+ if (trx->auto_inc_lock) {
+ /* If we had reserved the auto-inc lock for some table (if
+ we come here to roll back the latest SQL statement) we
+ release it now before a possibly lengthy rollback */
+
+ row_unlock_table_autoinc_for_mysql(trx);
+ }
+
+ error = trx_rollback_for_mysql(trx);
+
+ DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
+}
+
+/*********************************************************************
+Rolls back a transaction to a savepoint. */
+
+static int
innobase_rollback_to_savepoint(
/*===========================*/
/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
no savepoint with the given name */
THD* thd, /* in: handle to the MySQL thread of the user
whose transaction should be rolled back */
- char* savepoint_name, /* in: savepoint name */
- my_off_t* binlog_cache_pos)/* out: position which corresponds to the
- savepoint in the binlog cache of this
- transaction, not defined if error */
+ void *savepoint) /* in: savepoint data */
{
ib_longlong mysql_binlog_cache_pos;
int error = 0;
trx_t* trx;
+ char name[64];
DBUG_ENTER("innobase_rollback_to_savepoint");
@@ -1424,27 +2110,53 @@ innobase_rollback_to_savepoint(
innobase_release_stat_resources(trx);
- error = trx_rollback_to_savepoint_for_mysql(trx, savepoint_name,
+ /* TODO: use provided savepoint data area to store savepoint data */
+
+ longlong2str((ulonglong)savepoint, name, 36);
+
+ error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
&mysql_binlog_cache_pos);
- *binlog_cache_pos = (my_off_t)mysql_binlog_cache_pos;
+ DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
+}
+
+/*********************************************************************
+Release transaction savepoint name. */
+static
+int
+innobase_release_savepoint(
+/*=======================*/
+ /* out: 0 if success, HA_ERR_NO_SAVEPOINT if
+ no savepoint with the given name */
+ THD* thd, /* in: handle to the MySQL thread of the user
+ whose transaction should be rolled back */
+ void* savepoint) /* in: savepoint data */
+{
+ int error = 0;
+ trx_t* trx;
+ char name[64];
+
+ DBUG_ENTER("innobase_release_savepoint");
+
+ trx = check_trx_exists(thd);
+
+ /* TODO: use provided savepoint data area to store savepoint data */
+
+ longlong2str((ulonglong)savepoint, name, 36);
+
+ error = (int) trx_release_savepoint_for_mysql(trx, name);
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
/*********************************************************************
Sets a transaction savepoint. */
-
+static
int
innobase_savepoint(
/*===============*/
/* out: always 0, that is, always succeeds */
THD* thd, /* in: handle to the MySQL thread */
- char* savepoint_name, /* in: savepoint name */
- my_off_t binlog_cache_pos)/* in: offset up to which the current
- transaction has cached log entries to its
- binlog cache, not defined if no transaction
- active, or we are in the autocommit state, or
- binlogging is not switched on */
+ void* savepoint) /* in: savepoint data */
{
int error = 0;
trx_t* trx;
@@ -1465,40 +2177,53 @@ innobase_savepoint(
innobase_release_stat_resources(trx);
- /* Setting a savepoint starts a transaction inside InnoDB since
- it allocates resources for it (memory to store the savepoint name,
- for example) */
+ /* cannot happen outside of transaction */
+ DBUG_ASSERT(trx->active_trans);
- thd->transaction.all.innodb_active_trans = 1;
+ /* TODO: use provided savepoint data area to store savepoint data */
+ char name[64];
+ longlong2str((ulonglong)savepoint,name,36);
- error = trx_savepoint_for_mysql(trx, savepoint_name,
- (ib_longlong)binlog_cache_pos);
+ error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
/*********************************************************************
Frees a possible InnoDB trx object associated with the current THD. */
-
+static
int
innobase_close_connection(
/*======================*/
/* out: 0 or error number */
THD* thd) /* in: handle to the MySQL thread of the user
- whose transaction should be rolled back */
+ whose resources should be free'd */
{
trx_t* trx;
- trx = (trx_t*)thd->transaction.all.innobase_tid;
+ trx = (trx_t*)thd->ha_data[innobase_hton.slot];
- if (NULL != trx) {
- innobase_rollback(thd, (void*)trx);
+ ut_a(trx);
- trx_free_for_mysql(trx);
-
- thd->transaction.all.innobase_tid = NULL;
+ if (trx->active_trans == 0
+ && trx->conc_state != TRX_NOT_STARTED) {
+
+ sql_print_error("trx->active_trans == 0, but trx->conc_state != "
+ "TRX_NOT_STARTED");
}
+
+ if (trx->conc_state != TRX_NOT_STARTED &&
+ global_system_variables.log_warnings)
+ sql_print_warning("MySQL is closing a connection that has an active "
+ "InnoDB transaction. %lu row modifications will "
+ "roll back.",
+ (ulong)trx->undo_no.low);
+
+ innobase_rollback_trx(trx);
+
+ trx_free_for_mysql(trx);
+
return(0);
}
@@ -1508,18 +2233,41 @@ innobase_close_connection(
*****************************************************************************/
/********************************************************************
+Get the record format from the data dictionary. */
+enum row_type
+ha_innobase::get_row_type() const
+/*=============================*/
+ /* out: ROW_TYPE_REDUNDANT or ROW_TYPE_COMPACT */
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+
+ if (prebuilt && prebuilt->table) {
+ if (prebuilt->table->comp) {
+ return(ROW_TYPE_COMPACT);
+ } else {
+ return(ROW_TYPE_REDUNDANT);
+ }
+ }
+ ut_ad(0);
+ return(ROW_TYPE_NOT_USED);
+}
+
+/********************************************************************
Gives the file extension of an InnoDB single-table tablespace. */
+static const char* ha_innobase_exts[] = {
+ ".ibd",
+ NullS
+};
const char**
ha_innobase::bas_ext() const
/*========================*/
/* out: file extension string */
{
- static const char* ext[] = {".ibd", NullS};
-
- return(ext);
+ return ha_innobase_exts;
}
+
/*********************************************************************
Normalizes a table name string. A normalized name consists of the
database name catenated to '/' and table name. An example:
@@ -1604,7 +2352,8 @@ ha_innobase::open(
fields when packed actually became 1 byte longer, when we also
stored the string length as the first byte. */
- upd_and_key_val_buff_len = table->reclength + table->max_key_length
+ upd_and_key_val_buff_len =
+ table->s->reclength + table->s->max_key_length
+ MAX_REF_PARTS * 3;
if (!(mysql_byte*) my_multi_malloc(MYF(MY_WME),
&upd_buff, upd_and_key_val_buff_len,
@@ -1621,48 +2370,51 @@ ha_innobase::open(
norm_name, NULL);
if (NULL == ib_table) {
ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB error:\n"
-"Cannot find table %s from the internal data dictionary\n"
-"of InnoDB though the .frm file for the table exists. Maybe you\n"
-"have deleted and recreated InnoDB data files but have forgotten\n"
-"to delete the corresponding .frm files of InnoDB tables, or you\n"
-"have moved .frm files to another database?\n"
-"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
-"how you can resolve the problem.\n",
- norm_name);
+ sql_print_error("Cannot find table %s from the internal data "
+ "dictionary\nof InnoDB though the .frm file "
+ "for the table exists. Maybe you\nhave "
+ "deleted and recreated InnoDB data files but "
+ "have forgotten\nto delete the corresponding "
+ ".frm files of InnoDB tables, or you\n"
+ "have moved .frm files to another database?\n"
+ "Look from section 15.1 of "
+ "http://www.innodb.com/ibman.html\n"
+ "how you can resolve the problem.\n",
+ norm_name);
free_share(share);
my_free((char*) upd_buff, MYF(0));
my_errno = ENOENT;
- DBUG_RETURN(1);
+ DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
if (ib_table->ibd_file_missing && !thd->tablespace_op) {
ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB error:\n"
-"MySQL is trying to open a table handle but the .ibd file for\n"
-"table %s does not exist.\n"
-"Have you deleted the .ibd file from the database directory under\n"
-"the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
-"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
-"how you can resolve the problem.\n",
- norm_name);
+ sql_print_error("MySQL is trying to open a table handle but "
+ "the .ibd file for\ntable %s does not exist.\n"
+ "Have you deleted the .ibd file from the "
+ "database directory under\nthe MySQL datadir, "
+ "or have you used DISCARD TABLESPACE?\n"
+ "Look from section 15.1 of "
+ "http://www.innodb.com/ibman.html\n"
+ "how you can resolve the problem.\n",
+ norm_name);
free_share(share);
my_free((char*) upd_buff, MYF(0));
my_errno = ENOENT;
dict_table_decrement_handle_count(ib_table);
-
- DBUG_RETURN(1);
+ DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
innobase_prebuilt = row_create_prebuilt(ib_table);
- ((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = table->reclength;
+ ((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len =
+ table->s->reclength;
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
- primary_key = table->primary_key;
+ primary_key = table->s->primary_key;
key_used_on_scan = primary_key;
/* Allocate a buffer for a 'row reference'. A row reference is
@@ -1673,34 +2425,30 @@ ha_innobase::open(
if (!row_table_got_default_clust_index(ib_table)) {
if (primary_key >= MAX_KEY) {
- fprintf(stderr,
- "InnoDB: Error: table %s has a primary key in InnoDB\n"
- "InnoDB: data dictionary, but not in MySQL!\n", name);
+ sql_print_error("Table %s has a primary key in InnoDB data "
+ "dictionary, but not in MySQL!", name);
}
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = FALSE;
- /*
- MySQL allocates the buffer for ref. key_info->key_length
- includes space for all key columns + one byte for each column
- that may be NULL. ref_length must be as exact as possible to
- save space, because all row reference buffers are allocated
- based on ref_length.
- */
+ /* MySQL allocates the buffer for ref. key_info->key_length
+ includes space for all key columns + one byte for each column
+ that may be NULL. ref_length must be as exact as possible to
+ save space, because all row reference buffers are allocated
+ based on ref_length. */
ref_length = table->key_info[primary_key].key_length;
} else {
if (primary_key != MAX_KEY) {
- fprintf(stderr,
- "InnoDB: Error: table %s has no primary key in InnoDB\n"
- "InnoDB: data dictionary, but has one in MySQL!\n"
- "InnoDB: If you created the table with a MySQL\n"
- "InnoDB: version < 3.23.54 and did not define a primary\n"
- "InnoDB: key, but defined a unique key with all non-NULL\n"
- "InnoDB: columns, then MySQL internally treats that key\n"
- "InnoDB: as the primary key. You can fix this error by\n"
- "InnoDB: dump + DROP + CREATE + reimport of the table.\n",
- name);
+ sql_print_error("Table %s has no primary key in InnoDB data "
+ "dictionary, but has one in MySQL! If you "
+ "created the table with a MySQL version < "
+ "3.23.54 and did not define a primary key, "
+ "but defined a unique key with all non-NULL "
+ "columns, then MySQL internally treats that "
+ "key as the primary key. You can fix this "
+ "error by dump + DROP + CREATE + reimport "
+ "of the table.", name);
}
((row_prebuilt_t*)innobase_prebuilt)
@@ -1708,26 +2456,21 @@ ha_innobase::open(
ref_length = DATA_ROW_ID_LEN;
- /*
- If we automatically created the clustered index, then
- MySQL does not know about it, and MySQL must NOT be aware
- of the index used on scan, to make it avoid checking if we
- update the column of the index. That is why we assert below
- that key_used_on_scan is the undefined value MAX_KEY.
- The column is the row id in the automatical generation case,
- and it will never be updated anyway.
- */
+ /* If we automatically created the clustered index, then
+ MySQL does not know about it, and MySQL must NOT be aware
+ of the index used on scan, to make it avoid checking if we
+ update the column of the index. That is why we assert below
+ that key_used_on_scan is the undefined value MAX_KEY.
+ The column is the row id in the automatical generation case,
+ and it will never be updated anyway. */
if (key_used_on_scan != MAX_KEY) {
- fprintf(stderr,
-"InnoDB: Warning: table %s key_used_on_scan is %lu even though there is no\n"
-"InnoDB: primary key inside InnoDB.\n",
- name, (ulong)key_used_on_scan);
+ sql_print_warning("Table %s key_used_on_scan is %lu even "
+ "though there is no primary key inside "
+ "InnoDB.", name, (ulong) key_used_on_scan);
}
}
- auto_inc_counter_for_this_stat = 0;
-
block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
in query optimization */
@@ -1826,18 +2569,6 @@ set_field_in_record_to_null(
record[null_offset] = record[null_offset] | field->null_bit;
}
-/******************************************************************
-Resets SQL NULL bits in a record to zero. */
-inline
-void
-reset_null_bits(
-/*============*/
- TABLE* table, /* in: MySQL table object */
- char* record) /* in: a row in MySQL format */
-{
- bzero(record, table->null_bytes);
-}
-
extern "C" {
/*****************************************************************
InnoDB uses this function to compare two data fields for which the data type
@@ -1870,12 +2601,14 @@ innobase_mysql_cmp(
switch (mysql_tp) {
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_BLOB:
case FIELD_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_VARCHAR:
/* Use the charset number to pick the right charset struct for
the comparison. Since the MySQL function get_charset may be
slow before Bar removes the mutex operation there, we first
@@ -1889,9 +2622,10 @@ innobase_mysql_cmp(
charset = get_charset(charset_number, MYF(MY_WME));
if (charset == NULL) {
- fprintf(stderr,
-"InnoDB: fatal error: InnoDB needs charset %lu for doing a comparison,\n"
-"InnoDB: but MySQL cannot find that charset.\n", (ulong)charset_number);
+ sql_print_error("InnoDB needs charset %lu for doing "
+ "a comparison, but MySQL cannot "
+ "find that charset.",
+ (ulong) charset_number);
ut_a(0);
}
}
@@ -1903,7 +2637,7 @@ innobase_mysql_cmp(
ret = charset->coll->strnncollsp(charset,
a, a_length,
- b, b_length);
+ b, b_length, 0);
if (ret < 0) {
return(-1);
} else if (ret > 0) {
@@ -1920,7 +2654,9 @@ innobase_mysql_cmp(
}
/******************************************************************
-Converts a MySQL type to an InnoDB type. */
+Converts a MySQL type to an InnoDB type. Note that this function returns
+the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
+VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'. */
inline
ulint
get_innobase_type_from_mysql_type(
@@ -1965,8 +2701,9 @@ get_innobase_type_from_mysql_type(
switch (field->type()) {
/* NOTE that we only allow string types in DATA_MYSQL
and DATA_VARMYSQL */
- case FIELD_TYPE_VAR_STRING: if (field->binary()) {
-
+ case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
+ case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
+ if (field->binary()) {
return(DATA_BINARY);
} else if (strcmp(
field->charset()->name,
@@ -1975,7 +2712,8 @@ get_innobase_type_from_mysql_type(
} else {
return(DATA_VARMYSQL);
}
- case FIELD_TYPE_STRING: if (field->binary()) {
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_STRING: if (field->binary()) {
return(DATA_FIXBINARY);
} else if (strcmp(
@@ -1985,6 +2723,8 @@ get_innobase_type_from_mysql_type(
} else {
return(DATA_MYSQL);
}
+ case FIELD_TYPE_NEWDECIMAL:
+ return(DATA_FIXBINARY);
case FIELD_TYPE_LONG:
case FIELD_TYPE_LONGLONG:
case FIELD_TYPE_TINY:
@@ -2016,6 +2756,35 @@ get_innobase_type_from_mysql_type(
}
/***********************************************************************
+Writes an unsigned integer value < 64k to 2 bytes, in the little-endian
+storage format. */
+inline
+void
+innobase_write_to_2_little_endian(
+/*==============================*/
+ byte* buf, /* in: where to store */
+ ulint val) /* in: value to write, must be < 64k */
+{
+ ut_a(val < 256 * 256);
+
+ buf[0] = (byte)(val & 0xFF);
+ buf[1] = (byte)(val / 256);
+}
+
+/***********************************************************************
+Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
+storage format. */
+inline
+uint
+innobase_read_from_2_little_endian(
+/*===============================*/
+ /* out: value */
+ const mysql_byte* buf) /* in: from where to read */
+{
+ return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
+}
+
+/***********************************************************************
Stores a key value for a row to a buffer. */
uint
@@ -2054,9 +2823,14 @@ ha_innobase::store_key_val_for_row(
3. In a column prefix field, prefix_len next bytes are reserved for
data. In a normal field the max field length next bytes are reserved
for data. For a VARCHAR(n) the max field length is n. If the stored
- value is the SQL NULL then these data bytes are set to 0. */
+ value is the SQL NULL then these data bytes are set to 0.
- /* We have to zero-fill the buffer so that MySQL is able to use a
+ 4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
+ in the MySQL row format, the length is stored in 1 or 2 bytes,
+ depending on the maximum allowed length. But in the MySQL key value
+ format, the length always takes 2 bytes.
+
+ We have to zero-fill the buffer so that MySQL is able to use a
simple memcmp to compare two key values to determine if they are
equal. MySQL does this to compare contents of two 'ref' values. */
@@ -2079,7 +2853,50 @@ ha_innobase::store_key_val_for_row(
field = key_part->field;
mysql_type = field->type();
- if (mysql_type == FIELD_TYPE_TINY_BLOB
+ if (mysql_type == MYSQL_TYPE_VARCHAR) {
+ /* >= 5.0.3 true VARCHAR */
+ ulint lenlen;
+ ulint len;
+ byte* data;
+
+ if (is_null) {
+ buff += key_part->length + 2;
+
+ continue;
+ }
+
+ lenlen = (ulint)
+ (((Field_varstring*)field)->length_bytes);
+
+ data = row_mysql_read_true_varchar(&len,
+ (byte*) (record
+ + (ulint)get_field_offset(table, field)),
+ lenlen);
+
+ /* In a column prefix index, we may need to truncate
+ the stored value: */
+
+ if (len > key_part->length) {
+ len = key_part->length;
+ }
+
+ /* The length in a key value is always stored in 2
+ bytes */
+
+ row_mysql_store_true_var_len((byte*)buff, len, 2);
+ buff += 2;
+
+ memcpy(buff, data, len);
+
+ /* Note that we always reserve the maximum possible
+ length of the true VARCHAR in the key value, though
+ only len first bytes after the 2 length bytes contain
+ actual data. The rest of the space was reset to zero
+ in the bzero() call above. */
+
+ buff += key_part->length;
+
+ } else if (mysql_type == FIELD_TYPE_TINY_BLOB
|| mysql_type == FIELD_TYPE_MEDIUM_BLOB
|| mysql_type == FIELD_TYPE_BLOB
|| mysql_type == FIELD_TYPE_LONG_BLOB) {
@@ -2087,9 +2904,9 @@ ha_innobase::store_key_val_for_row(
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
if (is_null) {
- buff += key_part->length + 2;
+ buff += key_part->length + 2;
- continue;
+ continue;
}
blob_data = row_mysql_read_blob_ref(&blob_len,
@@ -2099,6 +2916,11 @@ ha_innobase::store_key_val_for_row(
ut_a(get_field_offset(table, field)
== key_part->offset);
+
+ /* All indexes on BLOB and TEXT are column prefix
+ indexes, and we may need to truncate the data to be
+ stored in the key value: */
+
if (blob_len > key_part->length) {
blob_len = key_part->length;
}
@@ -2106,19 +2928,28 @@ ha_innobase::store_key_val_for_row(
/* MySQL reserves 2 bytes for the length and the
storage of the number is little-endian */
- ut_a(blob_len < 256);
- *((byte*)buff) = (byte)blob_len;
+ innobase_write_to_2_little_endian(
+ (byte*)buff, (ulint)blob_len);
buff += 2;
memcpy(buff, blob_data, blob_len);
+ /* Note that we always reserve the maximum possible
+ length of the BLOB prefix in the key value. */
+
buff += key_part->length;
} else {
+ /* Here we handle all other data types except the
+ true VARCHAR, BLOB and TEXT. Note that the column
+ value we store may be also in a column prefix
+ index. */
+
if (is_null) {
buff += key_part->length;
continue;
}
+
memcpy(buff, record + key_part->offset,
key_part->length);
buff += key_part->length;
@@ -2154,6 +2985,8 @@ build_template(
ibool fetch_all_in_key = FALSE;
ibool fetch_primary_key_cols = FALSE;
ulint i;
+ /* byte offset of the end of last requested column */
+ ulint mysql_prefix_len = 0;
if (prebuilt->select_lock_type == LOCK_X) {
/* We always retrieve the whole clustered index record if we
@@ -2210,7 +3043,7 @@ build_template(
the clustered index */
}
- n_fields = (ulint)table->fields; /* number of columns */
+ n_fields = (ulint)table->s->fields; /* number of columns */
if (!prebuilt->mysql_template) {
prebuilt->mysql_template = (mysql_row_templ_t*)
@@ -2219,7 +3052,7 @@ build_template(
}
prebuilt->template_type = templ_type;
- prebuilt->null_bitmap_len = table->null_bytes;
+ prebuilt->null_bitmap_len = table->s->null_bytes;
prebuilt->templ_contains_blob = FALSE;
@@ -2229,18 +3062,44 @@ build_template(
templ = prebuilt->mysql_template + n_requested_fields;
field = table->field[i];
- if (templ_type == ROW_MYSQL_REC_FIELDS
- && !(fetch_all_in_key
- && dict_index_contains_col_or_prefix(index, i))
- && !(fetch_primary_key_cols
- && dict_table_col_in_clustered_key(index->table, i))
- && thd->query_id != field->query_id) {
+ if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
+ /* Decide which columns we should fetch
+ and which we can skip. */
+ register const ibool index_contains_field =
+ dict_index_contains_col_or_prefix(index, i);
+
+ if (!index_contains_field && prebuilt->read_just_key) {
+ /* If this is a 'key read', we do not need
+ columns that are not in the key */
+
+ goto skip_field;
+ }
+
+ if (index_contains_field && fetch_all_in_key) {
+ /* This field is needed in the query */
+
+ goto include_field;
+ }
+
+ if (thd->query_id == field->query_id) {
+ /* This field is needed in the query */
+
+ goto include_field;
+ }
+
+ if (fetch_primary_key_cols
+ && dict_table_col_in_clustered_key(index->table,
+ i)) {
+ /* This field is needed in the query */
+
+ goto include_field;
+ }
/* This field is not needed in the query, skip it */
goto skip_field;
}
-
+include_field:
n_requested_fields++;
templ->col_no = i;
@@ -2271,12 +3130,25 @@ build_template(
get_field_offset(table, field);
templ->mysql_col_len = (ulint) field->pack_length();
+ if (mysql_prefix_len < templ->mysql_col_offset
+ + templ->mysql_col_len) {
+ mysql_prefix_len = templ->mysql_col_offset
+ + templ->mysql_col_len;
+ }
templ->type = index->table->cols[i].type.mtype;
- templ->is_unsigned = index->table->cols[i].type.prtype
- & DATA_UNSIGNED;
+ templ->mysql_type = (ulint)field->type();
+
+ if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
+ templ->mysql_length_bytes = (ulint)
+ (((Field_varstring*)field)->length_bytes);
+ }
+
templ->charset = dtype_get_charset_coll_noninline(
index->table->cols[i].type.prtype);
-
+ templ->mbminlen = index->table->cols[i].type.mbminlen;
+ templ->mbmaxlen = index->table->cols[i].type.mbmaxlen;
+ templ->is_unsigned = index->table->cols[i].type.prtype
+ & DATA_UNSIGNED;
if (templ->type == DATA_BLOB) {
prebuilt->templ_contains_blob = TRUE;
}
@@ -2285,6 +3157,7 @@ skip_field:
}
prebuilt->n_template = n_requested_fields;
+ prebuilt->mysql_prefix_len = mysql_prefix_len;
if (index != clust_index && prebuilt->need_to_access_clustered) {
/* Change rec_field_no's to correspond to the clustered index
@@ -2312,31 +3185,31 @@ ha_innobase::write_row(
int error;
longlong auto_inc;
longlong dummy;
- ibool incremented_auto_inc_for_stat = FALSE;
- ibool incremented_auto_inc_counter = FALSE;
- ibool skip_auto_inc_decr;
+ ibool auto_inc_used= FALSE;
DBUG_ENTER("ha_innobase::write_row");
if (prebuilt->trx !=
- (trx_t*) current_thd->transaction.all.innobase_tid) {
- fprintf(stderr,
-"InnoDB: Error: the transaction object for the table handle is at\n"
-"InnoDB: %p, but for the current thread it is at %p\n",
- prebuilt->trx,
- current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]) {
+ sql_print_error("The transaction object for the table handle is at "
+ "%p, but for the current thread it is at %p",
+ prebuilt->trx,
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
fputs("\n"
"InnoDB: Dump of 200 bytes around transaction.all: ",
stderr);
ut_print_buf(stderr,
- ((byte*)(&(current_thd->transaction.all))) - 100, 200);
+ ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100,
+ 200);
putc('\n', stderr);
ut_error;
}
- statistic_increment(ha_write_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_write_count,
+ &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
@@ -2356,7 +3229,7 @@ ha_innobase::write_row(
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
dict_table_t* src_table;
- ibool mode;
+ ulint mode;
num_write_row = 0;
@@ -2368,7 +3241,7 @@ ha_innobase::write_row(
src_table = lock_get_src_table(
prebuilt->trx, prebuilt->table, &mode);
if (!src_table) {
- no_commit:
+no_commit:
/* Unknown situation: do not commit */
/*
ut_print_timestamp(stderr);
@@ -2383,14 +3256,15 @@ ha_innobase::write_row(
no need to re-acquire locks on it. */
/* Altering to InnoDB format */
- innobase_commit(user_thd, prebuilt->trx);
+ innobase_commit(user_thd, 1);
/* Note that this transaction is still active. */
- user_thd->transaction.all.innodb_active_trans = 1;
+ prebuilt->trx->active_trans = 1;
/* We will need an IX lock on the destination table. */
prebuilt->sql_stat_start = TRUE;
} else {
/* Ensure that there are no other table locks than
LOCK_IX and LOCK_AUTO_INC on the destination table. */
+
if (!lock_is_table_exclusive(prebuilt->table,
prebuilt->trx)) {
goto no_commit;
@@ -2398,9 +3272,9 @@ ha_innobase::write_row(
/* Commit the transaction. This will release the table
locks, so they have to be acquired again. */
- innobase_commit(user_thd, prebuilt->trx);
+ innobase_commit(user_thd, 1);
/* Note that this transaction is still active. */
- user_thd->transaction.all.innodb_active_trans = 1;
+ prebuilt->trx->active_trans = 1;
/* Re-acquire the table lock on the source table. */
row_lock_table_for_mysql(prebuilt, src_table, mode);
/* We will need an IX lock on the destination table. */
@@ -2445,99 +3319,29 @@ ha_innobase::write_row(
prebuilt->sql_stat_start = TRUE;
}
- /* Fetch the value the user possibly has set in the
- autoincrement field */
+ /* We have to use the transactional lock mechanism on the
+ auto-inc counter of the table to ensure that replication and
+ roll-forward of the binlog exactly imitates also the given
+ auto-inc values. The lock is released at each SQL statement's
+ end. This lock also prevents a race where two threads would
+ call ::get_auto_increment() simultaneously. */
- auto_inc = table->next_number_field->val_int();
+ error = row_lock_table_autoinc_for_mysql(prebuilt);
- /* In replication and also otherwise the auto-inc column
- can be set with SET INSERT_ID. Then we must look at
- user_thd->next_insert_id. If it is nonzero and the user
- has not supplied a value, we must use it, and use values
- incremented by 1 in all subsequent inserts within the
- same SQL statement! */
+ if (error != DB_SUCCESS) {
+ /* Deadlock or lock wait timeout */
- if (auto_inc == 0 && user_thd->next_insert_id != 0) {
+ error = convert_error_code_to_mysql(error, user_thd);
- auto_inc_counter_for_this_stat
- = user_thd->next_insert_id;
+ goto func_exit;
}
- if (auto_inc == 0 && auto_inc_counter_for_this_stat) {
- /* The user set the auto-inc counter for
- this SQL statement with SET INSERT_ID. We must
- assign sequential values from the counter. */
-
- auto_inc = auto_inc_counter_for_this_stat;
-
- /* We give MySQL a new value to place in the
- auto-inc column */
- user_thd->next_insert_id = auto_inc;
-
- auto_inc_counter_for_this_stat++;
- incremented_auto_inc_for_stat = TRUE;
- }
-
- if (auto_inc != 0) {
- /* This call will calculate the max of the current
- value and the value supplied by the user and
- update the counter accordingly */
-
- /* We have to use the transactional lock mechanism
- on the auto-inc counter of the table to ensure
- that replication and roll-forward of the binlog
- exactly imitates also the given auto-inc values.
- The lock is released at each SQL statement's
- end. */
-
- innodb_srv_conc_enter_innodb(prebuilt->trx);
- error = row_lock_table_autoinc_for_mysql(prebuilt);
- innodb_srv_conc_exit_innodb(prebuilt->trx);
-
- if (error != DB_SUCCESS) {
-
- error = convert_error_code_to_mysql(error,
- user_thd);
- goto func_exit;
- }
-
- dict_table_autoinc_update(prebuilt->table, auto_inc);
- } else {
- innodb_srv_conc_enter_innodb(prebuilt->trx);
-
- if (!prebuilt->trx->auto_inc_lock) {
-
- error = row_lock_table_autoinc_for_mysql(
- prebuilt);
- if (error != DB_SUCCESS) {
- innodb_srv_conc_exit_innodb(
- prebuilt->trx);
-
- error = convert_error_code_to_mysql(
- error, user_thd);
- goto func_exit;
- }
- }
-
- /* The following call gets the value of the auto-inc
- counter of the table and increments it by 1 */
-
- auto_inc = dict_table_autoinc_get(prebuilt->table);
- incremented_auto_inc_counter = TRUE;
-
- innodb_srv_conc_exit_innodb(prebuilt->trx);
-
- /* We can give the new value for MySQL to place in
- the field */
-
- user_thd->next_insert_id = auto_inc;
- }
-
- /* This call of a handler.cc function places
- user_thd->next_insert_id to the column value, if the column
- value was not set by the user */
+ /* We must use the handler code to update the auto-increment
+ value to be sure that we increment it correctly. */
update_auto_increment();
+ auto_inc_used = 1;
+
}
if (prebuilt->mysql_template == NULL
@@ -2552,101 +3356,47 @@ ha_innobase::write_row(
error = row_insert_for_mysql((byte*) record, prebuilt);
- innodb_srv_conc_exit_innodb(prebuilt->trx);
+ if (error == DB_SUCCESS && auto_inc_used) {
- if (error != DB_SUCCESS) {
- /* If the insert did not succeed we restore the value of
- the auto-inc counter we used; note that this behavior was
- introduced only in version 4.0.4.
- NOTE that a REPLACE command and LOAD DATA INFILE REPLACE
- handles a duplicate key error
- itself, and we must not decrement the autoinc counter
- if we are performing those statements.
- NOTE 2: if there was an error, for example a deadlock,
- which caused InnoDB to roll back the whole transaction
- already in the call of row_insert_for_mysql(), we may no
- longer have the AUTO-INC lock, and cannot decrement
- the counter here. */
-
- skip_auto_inc_decr = FALSE;
-
- if (error == DB_DUPLICATE_KEY
- && (user_thd->lex->sql_command == SQLCOM_REPLACE
- || user_thd->lex->sql_command
- == SQLCOM_REPLACE_SELECT
- || (user_thd->lex->sql_command == SQLCOM_LOAD
- && user_thd->lex->duplicates == DUP_REPLACE))) {
-
- skip_auto_inc_decr= TRUE;
- }
+ /* Fetch the value that was set in the autoincrement field */
- if (!skip_auto_inc_decr && incremented_auto_inc_counter
- && prebuilt->trx->auto_inc_lock) {
- dict_table_autoinc_decrement(prebuilt->table);
- }
+ auto_inc = table->next_number_field->val_int();
- if (!skip_auto_inc_decr && incremented_auto_inc_for_stat
- && prebuilt->trx->auto_inc_lock) {
- auto_inc_counter_for_this_stat--;
- }
- }
+ if (auto_inc != 0) {
+ /* This call will update the counter according to the
+ value that was inserted in the table */
- error = convert_error_code_to_mysql(error, user_thd);
+ dict_table_autoinc_update(prebuilt->table, auto_inc);
+ }
+ }
- /* Tell InnoDB server that there might be work for
- utility threads: */
-func_exit:
- innobase_active_small();
+ /* A REPLACE command and LOAD DATA INFILE REPLACE handle a duplicate
+ key error themselves, and we must update the autoinc counter if we are
+ performing those statements. */
- DBUG_RETURN(error);
-}
+ if (error == DB_DUPLICATE_KEY && auto_inc_used
+ && (user_thd->lex->sql_command == SQLCOM_REPLACE
+ || user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT
+ || (user_thd->lex->sql_command == SQLCOM_LOAD
+ && user_thd->lex->duplicates == DUP_REPLACE))) {
-/******************************************************************
-Converts field data for storage in an InnoDB update vector. */
-inline
-mysql_byte*
-innobase_convert_and_store_changed_col(
-/*===================================*/
- /* out: pointer to the end of the converted
- data in the buffer */
- upd_field_t* ufield, /* in/out: field in the update vector */
- mysql_byte* buf, /* in: buffer we can use in conversion */
- mysql_byte* data, /* in: column data to store */
- ulint len, /* in: data len */
- ulint col_type,/* in: data type in InnoDB type numbers */
- ulint is_unsigned)/* in: != 0 if an unsigned integer type */
-{
- uint i;
-
- if (len == UNIV_SQL_NULL) {
- data = NULL;
- } else if (col_type == DATA_VARCHAR || col_type == DATA_BINARY
- || col_type == DATA_VARMYSQL) {
- /* Remove trailing spaces */
- while (len > 0 && data[len - 1] == ' ') {
- len--;
- }
- } else if (col_type == DATA_INT) {
- /* Store integer data in InnoDB in a big-endian
- format, sign bit negated, if signed */
+ auto_inc = table->next_number_field->val_int();
- for (i = 0; i < len; i++) {
- buf[len - 1 - i] = data[i];
- }
-
- if (!is_unsigned) {
- buf[0] = buf[0] ^ 128;
- }
+ if (auto_inc != 0) {
+ dict_table_autoinc_update(prebuilt->table, auto_inc);
+ }
+ }
- data = buf;
+ innodb_srv_conc_exit_innodb(prebuilt->trx);
- buf += len;
- }
+ error = convert_error_code_to_mysql(error, user_thd);
- ufield->new_val.data = data;
- ufield->new_val.len = len;
+ /* Tell InnoDB server that there might be work for
+ utility threads: */
+func_exit:
+ innobase_active_small();
- return(buf);
+ DBUG_RETURN(error);
}
/**************************************************************************
@@ -2669,19 +3419,22 @@ calc_row_difference(
{
mysql_byte* original_upd_buff = upd_buff;
Field* field;
+ enum_field_types field_mysql_type;
uint n_fields;
ulint o_len;
ulint n_len;
+ ulint col_pack_len;
+ byte* new_mysql_row_col;
byte* o_ptr;
byte* n_ptr;
byte* buf;
upd_field_t* ufield;
ulint col_type;
- ulint is_unsigned;
ulint n_changed = 0;
+ dfield_t dfield;
uint i;
- n_fields = table->fields;
+ n_fields = table->s->fields;
/* We use upd_buff to convert changed fields */
buf = (byte*) upd_buff;
@@ -2698,25 +3451,50 @@ calc_row_difference(
o_ptr = (byte*) old_row + get_field_offset(table, field);
n_ptr = (byte*) new_row + get_field_offset(table, field);
- o_len = field->pack_length();
- n_len = field->pack_length();
+
+ /* Use new_mysql_row_col and col_pack_len save the values */
+
+ new_mysql_row_col = n_ptr;
+ col_pack_len = field->pack_length();
+
+ o_len = col_pack_len;
+ n_len = col_pack_len;
+ /* We use o_ptr and n_ptr to dig up the actual data for
+ comparison. */
+
+ field_mysql_type = field->type();
+
col_type = prebuilt->table->cols[i].type.mtype;
- is_unsigned = prebuilt->table->cols[i].type.prtype &
- DATA_UNSIGNED;
+
switch (col_type) {
case DATA_BLOB:
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
+
break;
+
case DATA_VARCHAR:
case DATA_BINARY:
case DATA_VARMYSQL:
- o_ptr = row_mysql_read_var_ref_noninline(&o_len,
- o_ptr);
- n_ptr = row_mysql_read_var_ref_noninline(&n_len,
- n_ptr);
+ if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
+ /* This is a >= 5.0.3 type true VARCHAR where
+ the real payload data length is stored in
+ 1 or 2 bytes */
+
+ o_ptr = row_mysql_read_true_varchar(
+ &o_len, o_ptr,
+ (ulint)
+ (((Field_varstring*)field)->length_bytes));
+
+ n_ptr = row_mysql_read_true_varchar(
+ &n_len, n_ptr,
+ (ulint)
+ (((Field_varstring*)field)->length_bytes));
+ }
+
+ break;
default:
;
}
@@ -2738,12 +3516,27 @@ calc_row_difference(
/* The field has changed */
ufield = uvect->fields + n_changed;
+
+ /* Let us use a dummy dfield to make the conversion
+ from the MySQL column format to the InnoDB format */
+
+ dfield.type = (prebuilt->table->cols + i)->type;
+
+ if (n_len != UNIV_SQL_NULL) {
+ buf = row_mysql_store_col_in_innobase_format(
+ &dfield,
+ (byte*)buf,
+ TRUE,
+ new_mysql_row_col,
+ col_pack_len,
+ prebuilt->table->comp);
+ ufield->new_val.data = dfield.data;
+ ufield->new_val.len = dfield.len;
+ } else {
+ ufield->new_val.data = NULL;
+ ufield->new_val.len = UNIV_SQL_NULL;
+ }
- buf = (byte*)
- innobase_convert_and_store_changed_col(ufield,
- (mysql_byte*)buf,
- (mysql_byte*)n_ptr, n_len, col_type,
- is_unsigned);
ufield->exp = NULL;
ufield->field_no = prebuilt->table->cols[i].clust_pos;
n_changed++;
@@ -2780,7 +3573,7 @@ ha_innobase::update_row(
DBUG_ENTER("ha_innobase::update_row");
ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
@@ -2841,7 +3634,7 @@ ha_innobase::delete_row(
DBUG_ENTER("ha_innobase::delete_row");
ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
if (last_query_id != user_thd->query_id) {
prebuilt->sql_stat_start = TRUE;
@@ -2874,6 +3667,33 @@ ha_innobase::delete_row(
DBUG_RETURN(error);
}
+/**************************************************************************
+Removes a new lock set on a row. This can be called after a row has been read
+in the processing of an UPDATE or a DELETE query, if the option
+innodb_locks_unsafe_for_binlog is set. */
+
+void
+ha_innobase::unlock_row(void)
+/*=========================*/
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+
+ DBUG_ENTER("ha_innobase::unlock_row");
+
+ if (last_query_id != user_thd->query_id) {
+ ut_print_timestamp(stderr);
+ sql_print_error("last_query_id is %lu != user_thd_query_id is "
+ "%lu", (ulong) last_query_id,
+ (ulong) user_thd->query_id);
+ mem_analyze_corruption((byte *) prebuilt->trx);
+ ut_error;
+ }
+
+ if (srv_locks_unsafe_for_binlog) {
+ row_unlock_for_mysql(prebuilt, FALSE);
+ }
+}
+
/**********************************************************************
Initializes a handle to use an index. */
@@ -3025,9 +3845,10 @@ ha_innobase::index_read(
DBUG_ENTER("index_read");
ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
- statistic_increment(ha_read_key_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_key_count,
+ &LOCK_status);
if (last_query_id != user_thd->query_id) {
prebuilt->sql_stat_start = TRUE;
@@ -3075,7 +3896,7 @@ ha_innobase::index_read(
match_mode = ROW_SEL_EXACT_PREFIX;
}
- last_match_mode = match_mode;
+ last_match_mode = (uint) match_mode;
innodb_srv_conc_enter_innodb(prebuilt->trx);
@@ -3095,7 +3916,7 @@ ha_innobase::index_read(
error = HA_ERR_KEY_NOT_FOUND;
table->status = STATUS_NOT_FOUND;
} else {
- error = convert_error_code_to_mysql(ret, user_thd);
+ error = convert_error_code_to_mysql((int) ret, user_thd);
table->status = STATUS_NOT_FOUND;
}
@@ -3133,16 +3954,17 @@ ha_innobase::change_active_index(
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
KEY* key=0;
- statistic_increment(ha_read_key_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_key_count,
+ &LOCK_status);
DBUG_ENTER("change_active_index");
ut_ad(user_thd == current_thd);
ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
active_index = keynr;
- if (keynr != MAX_KEY && table->keys > 0) {
+ if (keynr != MAX_KEY && table->s->keys > 0) {
key = table->key_info + active_index;
prebuilt->index = dict_table_get_index_noninline(
@@ -3154,9 +3976,10 @@ ha_innobase::change_active_index(
}
if (!prebuilt->index) {
- sql_print_error(
-"Innodb could not find key n:o %u with name %s from dict cache for table %s",
- keynr, key ? key->name : "NULL", prebuilt->table->name);
+ sql_print_error("Innodb could not find key n:o %u with name %s "
+ "from dict cache for table %s",
+ keynr, key ? key->name : "NULL",
+ prebuilt->table->name);
DBUG_RETURN(1);
}
@@ -3226,7 +4049,7 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
innodb_srv_conc_enter_innodb(prebuilt->trx);
@@ -3246,7 +4069,7 @@ ha_innobase::general_fetch(
error = HA_ERR_END_OF_FILE;
table->status = STATUS_NOT_FOUND;
} else {
- error = convert_error_code_to_mysql(ret, user_thd);
+ error = convert_error_code_to_mysql((int) ret, user_thd);
table->status = STATUS_NOT_FOUND;
}
@@ -3265,7 +4088,8 @@ ha_innobase::index_next(
mysql_byte* buf) /* in/out: buffer for next row in MySQL
format */
{
- statistic_increment(ha_read_next_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_next_count,
+ &LOCK_status);
return(general_fetch(buf, ROW_SEL_NEXT, 0));
}
@@ -3282,7 +4106,8 @@ ha_innobase::index_next_same(
const mysql_byte* key, /* in: key value */
uint keylen) /* in: key value length */
{
- statistic_increment(ha_read_next_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_next_count,
+ &LOCK_status);
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
}
@@ -3316,7 +4141,8 @@ ha_innobase::index_first(
int error;
DBUG_ENTER("index_first");
- statistic_increment(ha_read_first_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_first_count,
+ &LOCK_status);
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
@@ -3342,7 +4168,8 @@ ha_innobase::index_last(
int error;
DBUG_ENTER("index_last");
- statistic_increment(ha_read_last_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_last_count,
+ &LOCK_status);
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
@@ -3407,7 +4234,8 @@ ha_innobase::rnd_next(
int error;
DBUG_ENTER("rnd_next");
- statistic_increment(ha_read_rnd_next_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
if (start_of_scan) {
error = index_first(buf);
@@ -3443,10 +4271,11 @@ ha_innobase::rnd_pos(
DBUG_ENTER("rnd_pos");
DBUG_DUMP("key", (char*) pos, ref_length);
- statistic_increment(ha_read_rnd_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_rnd_count,
+ &LOCK_status);
ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
@@ -3460,7 +4289,7 @@ ha_innobase::rnd_pos(
}
if (error) {
- DBUG_PRINT("error",("Got error: %ld",error));
+ DBUG_PRINT("error", ("Got error: %ld", error));
DBUG_RETURN(error);
}
@@ -3468,10 +4297,11 @@ ha_innobase::rnd_pos(
for the table, and it is == ref_length */
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
- if (error)
- {
- DBUG_PRINT("error",("Got error: %ld",error));
+
+ if (error) {
+ DBUG_PRINT("error", ("Got error: %ld", error));
}
+
change_active_index(keynr);
DBUG_RETURN(error);
@@ -3495,7 +4325,7 @@ ha_innobase::position(
uint len;
ut_ad(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
@@ -3511,14 +4341,12 @@ ha_innobase::position(
ref_length, record);
}
- /* Since we do not store len to the buffer 'ref', we must assume
- that len is always fixed for this table. The following assertion
- checks this. */
+ /* We assume that the 'ref' value len is always fixed for the same
+ table. */
if (len != ref_length) {
- fprintf(stderr,
- "InnoDB: Error: stored ref len is %lu, but table ref len is %lu\n",
- (ulong)len, (ulong)ref_length);
+ sql_print_error("Stored ref len is %lu, but table ref len is %lu",
+ (ulong) len, (ulong) ref_length);
}
}
@@ -3532,7 +4360,7 @@ create_table_def(
TABLE* form, /* in: information on table
columns and indexes */
const char* table_name, /* in: table name */
- const char* path_of_temp_table)/* in: if this is a table explicitly
+ const char* path_of_temp_table,/* in: if this is a table explicitly
created by the user with the
TEMPORARY keyword, then this
parameter is the dir path where the
@@ -3540,27 +4368,30 @@ create_table_def(
an .ibd file for it (no .ibd extension
in the path, though); otherwise this
is NULL */
+ ibool comp) /* in: TRUE=compact record format */
{
Field* field;
dict_table_t* table;
ulint n_cols;
int error;
ulint col_type;
+ ulint col_len;
ulint nulls_allowed;
ulint unsigned_type;
ulint binary_type;
+ ulint long_true_varchar;
ulint charset_no;
ulint i;
DBUG_ENTER("create_table_def");
DBUG_PRINT("enter", ("table_name: %s", table_name));
- n_cols = form->fields;
+ n_cols = form->s->fields;
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
- table = dict_mem_table_create((char*) table_name, 0, n_cols);
+ table = dict_mem_table_create(table_name, 0, n_cols, comp);
if (path_of_temp_table) {
table->dir_path_of_temp_table =
@@ -3571,7 +4402,7 @@ create_table_def(
field = form->field[i];
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
- field);
+ field);
if (field->null_ptr) {
nulls_allowed = 0;
} else {
@@ -3590,17 +4421,40 @@ create_table_def(
charset_no = (ulint)field->charset()->number;
- ut_a(charset_no < 256); /* in ut0type.h we assume that
- the number fits in one byte */
+ ut_a(charset_no < 256); /* in data0type.h we assume
+ that the number fits in one
+ byte */
+ }
+
+ ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
+ that this fits in one byte */
+ col_len = field->pack_length();
+
+ /* The MySQL pack length contains 1 or 2 bytes length field
+ for a true VARCHAR. Let us subtract that, so that the InnoDB
+ column length in the InnoDB data dictionary is the real
+ maximum byte length of the actual data. */
+
+ long_true_varchar = 0;
+
+ if (field->type() == MYSQL_TYPE_VARCHAR) {
+ col_len -= ((Field_varstring*)field)->length_bytes;
+
+ if (((Field_varstring*)field)->length_bytes == 2) {
+ long_true_varchar = DATA_LONG_TRUE_VARCHAR;
+ }
}
- dict_mem_table_add_col(table, (char*) field->field_name,
- col_type, dtype_form_prtype(
- (ulint)field->type()
- | nulls_allowed | unsigned_type
- | binary_type,
- + charset_no),
- field->pack_length(), 0);
+ dict_mem_table_add_col(table,
+ (char*) field->field_name,
+ col_type,
+ dtype_form_prtype(
+ (ulint)field->type()
+ | nulls_allowed | unsigned_type
+ | binary_type | long_true_varchar,
+ charset_no),
+ col_len,
+ 0);
}
error = row_create_table_for_mysql(table, trx);
@@ -3643,7 +4497,7 @@ create_index(
ind_type = 0;
- if (key_num == form->primary_key) {
+ if (key_num == form->s->primary_key) {
ind_type = ind_type | DICT_CLUSTERED;
}
@@ -3666,7 +4520,7 @@ create_index(
the length of the key part versus the column. */
field = NULL;
- for (j = 0; j < form->fields; j++) {
+ for (j = 0; j < form->s->fields; j++) {
field = form->field[j];
@@ -3679,13 +4533,17 @@ create_index(
}
}
- ut_a(j < form->fields);
+ ut_a(j < form->s->fields);
col_type = get_innobase_type_from_mysql_type(
&is_unsigned, key_part->field);
if (DATA_BLOB == col_type
- || key_part->length < field->pack_length()) {
+ || (key_part->length < field->pack_length()
+ && field->type() != MYSQL_TYPE_VARCHAR)
+ || (field->type() == MYSQL_TYPE_VARCHAR
+ && key_part->length < field->pack_length()
+ - ((Field_varstring*)field)->length_bytes)) {
prefix_len = key_part->length;
@@ -3693,11 +4551,13 @@ create_index(
|| col_type == DATA_FLOAT
|| col_type == DATA_DOUBLE
|| col_type == DATA_DECIMAL) {
- fprintf(stderr,
-"InnoDB: error: MySQL is trying to create a column prefix index field\n"
-"InnoDB: on an inappropriate data type. Table name %s, column name %s.\n",
- table_name, key_part->field->field_name);
-
+ sql_print_error("MySQL is trying to create a column "
+ "prefix index field, on an "
+ "inappropriate data type. Table "
+ "name %s, column name %s.",
+ table_name,
+ key_part->field->field_name);
+
prefix_len = 0;
}
} else {
@@ -3774,7 +4634,7 @@ ha_innobase::create(
DBUG_ASSERT(thd != NULL);
- if (form->fields > 1000) {
+ if (form->s->fields > 1000) {
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
but we play safe here */
@@ -3822,27 +4682,18 @@ ha_innobase::create(
/* Create the table definition in InnoDB */
- if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
-
- error = create_table_def(trx, form, norm_name, name2);
- } else {
- error = create_table_def(trx, form, norm_name, NULL);
- }
+ error = create_table_def(trx, form, norm_name,
+ create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
+ form->s->row_type != ROW_TYPE_REDUNDANT);
if (error) {
- innobase_commit_low(trx);
-
- row_mysql_unlock_data_dictionary(trx);
-
- trx_free_for_mysql(trx);
-
- DBUG_RETURN(error);
+ goto cleanup;
}
/* Look for a primary key */
- primary_key_no= (table->primary_key != MAX_KEY ?
- (int) table->primary_key :
+ primary_key_no= (table->s->primary_key != MAX_KEY ?
+ (int) table->s->primary_key :
-1);
/* Our function row_get_mysql_key_number_for_index assumes
@@ -3852,7 +4703,7 @@ ha_innobase::create(
/* Create the keys */
- if (form->keys == 0 || primary_key_no == -1) {
+ if (form->s->keys == 0 || primary_key_no == -1) {
/* Create an index which is used as the clustered index;
order the rows by their row id which is internally generated
by InnoDB */
@@ -3860,13 +4711,7 @@ ha_innobase::create(
error = create_clustered_index_when_no_primary(trx,
norm_name);
if (error) {
- innobase_commit_low(trx);
-
- row_mysql_unlock_data_dictionary(trx);
-
- trx_free_for_mysql(trx);
-
- DBUG_RETURN(error);
+ goto cleanup;
}
}
@@ -3875,29 +4720,16 @@ ha_innobase::create(
first */
if ((error = create_index(trx, form, norm_name,
(uint) primary_key_no))) {
- innobase_commit_low(trx);
-
- row_mysql_unlock_data_dictionary(trx);
-
- trx_free_for_mysql(trx);
-
- DBUG_RETURN(error);
+ goto cleanup;
}
}
- for (i = 0; i < form->keys; i++) {
+ for (i = 0; i < form->s->keys; i++) {
if (i != (uint) primary_key_no) {
if ((error = create_index(trx, form, norm_name, i))) {
-
- innobase_commit_low(trx);
-
- row_mysql_unlock_data_dictionary(trx);
-
- trx_free_for_mysql(trx);
-
- DBUG_RETURN(error);
+ goto cleanup;
}
}
}
@@ -3910,21 +4742,18 @@ ha_innobase::create(
current_thd->query_length,
current_thd->charset())) {
error = HA_ERR_OUT_OF_MEM;
- } else {
- error = row_table_add_foreign_constraints(trx,
- q.str, norm_name);
-
- error = convert_error_code_to_mysql(error, NULL);
+
+ goto cleanup;
}
- if (error) {
- innobase_commit_low(trx);
-
- row_mysql_unlock_data_dictionary(trx);
+ error = row_table_add_foreign_constraints(trx,
+ q.str, norm_name,
+ create_info->options & HA_LEX_CREATE_TMP_TABLE);
- trx_free_for_mysql(trx);
+ error = convert_error_code_to_mysql(error, NULL);
- DBUG_RETURN(error);
+ if (error) {
+ goto cleanup;
}
}
@@ -3964,6 +4793,15 @@ ha_innobase::create(
trx_free_for_mysql(trx);
DBUG_RETURN(0);
+
+cleanup:
+ innobase_commit_low(trx);
+
+ row_mysql_unlock_data_dictionary(trx);
+
+ trx_free_for_mysql(trx);
+
+ DBUG_RETURN(error);
}
/*********************************************************************
@@ -3984,7 +4822,7 @@ ha_innobase::discard_or_import_tablespace(
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
dict_table = prebuilt->table;
trx = prebuilt->trx;
@@ -4001,6 +4839,46 @@ ha_innobase::discard_or_import_tablespace(
}
/*********************************************************************
+Deletes all rows of an InnoDB table. */
+
+int
+ha_innobase::delete_all_rows(void)
+/*==============================*/
+ /* out: error number */
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
+ int error;
+ trx_t* trx;
+ THD* thd = current_thd;
+
+ DBUG_ENTER("ha_innobase::delete_all_rows");
+
+ if (thd->lex->sql_command != SQLCOM_TRUNCATE) {
+ fallback:
+ /* We only handle TRUNCATE TABLE t as a special case.
+ DELETE FROM t will have to use ha_innobase::delete_row(). */
+ DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
+ }
+
+ /* Get the transaction associated with the current thd, or create one
+ if not yet created */
+
+ trx = check_trx_exists(thd);
+
+ /* Truncate the table in InnoDB */
+
+ error = row_truncate_table_for_mysql(prebuilt->table, trx);
+ if (error == DB_ERROR) {
+ /* Cannot truncate; resort to ha_innobase::delete_row() */
+ goto fallback;
+ }
+
+ error = convert_error_code_to_mysql(error, NULL);
+
+ DBUG_RETURN(error);
+}
+
+/*********************************************************************
Drops a table from an InnoDB database. Before calling this function,
MySQL calls innobase_commit to commit the transaction of the current user.
Then the current user cannot have locks set on the table. Drop table
@@ -4122,7 +5000,7 @@ innobase_drop_database(
}
ptr++;
- namebuf = my_malloc(len + 2, MYF(0));
+ namebuf = my_malloc((uint) len + 2, MYF(0));
memcpy(namebuf, ptr, len);
namebuf[len] = '/';
@@ -4254,11 +5132,11 @@ ha_innobase::records_in_range(
KEY* key;
dict_index_t* index;
mysql_byte* key_val_buff2 = (mysql_byte*) my_malloc(
- table->reclength
- + table->max_key_length + 100,
+ table->s->reclength
+ + table->s->max_key_length + 100,
MYF(MY_WME));
- ulint buff2_len = table->reclength
- + table->max_key_length + 100;
+ ulint buff2_len = table->s->reclength
+ + table->s->max_key_length + 100;
dtuple_t* range_start;
dtuple_t* range_end;
ib_longlong n_rows;
@@ -4415,21 +5293,27 @@ ha_innobase::read_time(
ha_rows total_rows;
double time_for_scan;
- if (index != table->primary_key)
- return handler::read_time(index, ranges, rows); // Not clustered
+ if (index != table->s->primary_key) {
+ /* Not clustered */
+ return(handler::read_time(index, ranges, rows));
+ }
+
+ if (rows <= 2) {
- if (rows <= 2)
- return (double) rows;
+ return((double) rows);
+ }
/* Assume that the read time is proportional to the scan time for all
rows + at most one seek per range. */
time_for_scan = scan_time();
- if ((total_rows = estimate_rows_upper_bound()) < rows)
- return time_for_scan;
+ if ((total_rows = estimate_rows_upper_bound()) < rows) {
+
+ return(time_for_scan);
+ }
- return (ranges + (double) rows / (double) total_rows * time_for_scan);
+ return(ranges + (double) rows / (double) total_rows * time_for_scan);
}
/*************************************************************************
@@ -4520,7 +5404,7 @@ ha_innobase::info(
is an accurate estimate if it is zero. Of course, it is not,
since we do not have any locks on the rows yet at this phase.
Since SHOW TABLE STATUS seems to call this function with the
- HA_STATUS_TIME flag set, while the left join optizer does not
+ HA_STATUS_TIME flag set, while the left join optimizer does not
set that flag, we add one to a zero value if the flag is not
set. That way SHOW TABLE STATUS will show the best estimate,
while the optimizer never sees the table empty. */
@@ -4558,15 +5442,17 @@ ha_innobase::info(
index = dict_table_get_next_index_noninline(index);
}
- for (i = 0; i < table->keys; i++) {
+ for (i = 0; i < table->s->keys; i++) {
if (index == NULL) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: table %s contains less indexes inside InnoDB\n"
-"InnoDB: than are defined in the MySQL .frm file. Have you mixed up\n"
-"InnoDB: .frm files from different installations? See section\n"
-"InnoDB: 15.1 at http://www.innodb.com/ibman.html\n",
- ib_table->name);
+ sql_print_error("Table %s contains less "
+ "indexes inside InnoDB than "
+ "are defined in the MySQL "
+ ".frm file. Have you mixed up "
+ ".frm files from different "
+ "installations? See section "
+ "15.1 at http://www.innodb.com/ibman.html",
+ ib_table->name);
break;
}
@@ -4574,15 +5460,21 @@ ha_innobase::info(
if (j + 1 > index->n_uniq) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: index %s of %s has %lu columns unique inside InnoDB\n"
-"InnoDB: but MySQL is asking statistics for %lu columns. Have you mixed up\n"
-"InnoDB: .frm files from different installations? See section\n"
-"InnoDB: 15.1 at http://www.innodb.com/ibman.html\n",
- index->name,
- ib_table->name,
- (unsigned long) index->n_uniq,
- j + 1);
+ sql_print_error("Index %s of %s has "
+ "%lu columns unique "
+ "inside InnoDB, but "
+ "MySQL is asking "
+ "statistics for %lu "
+ "columns. Have you "
+ "mixed up .frm files "
+ "from different "
+ "installations? See "
+ "section 15.1 at "
+ "http://www.innodb.com/ibman.html",
+ index->name,
+ ib_table->name,
+ (unsigned long)
+ index->n_uniq, j + 1);
break;
}
@@ -4622,6 +5514,33 @@ ha_innobase::info(
trx_get_error_info(prebuilt->trx));
}
+ if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
+ longlong auto_inc;
+ int ret;
+
+ /* The following function call can the first time fail in
+ a lock wait timeout error because it reserves the auto-inc
+ lock on the table. If it fails, then someone is already initing
+ the auto-inc counter, and the second call is guaranteed to
+ succeed. */
+
+ ret = innobase_read_and_init_auto_inc(&auto_inc);
+
+ if (ret != 0) {
+ ret = innobase_read_and_init_auto_inc(&auto_inc);
+
+ if (ret != 0) {
+ ut_print_timestamp(stderr);
+ sql_print_error("Cannot get table %s auto-inc"
+ "counter value in ::info\n",
+ ib_table->name);
+ auto_inc = 0;
+ }
+ }
+
+ auto_increment_value = auto_inc;
+ }
+
prebuilt->trx->op_info = (char*)"";
DBUG_VOID_RETURN;
@@ -4676,7 +5595,7 @@ ha_innobase::check(
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
if (prebuilt->mysql_template == NULL) {
/* Build the template; we will use a dummy template
@@ -4706,7 +5625,7 @@ ha_innobase::update_table_comment(
info on foreign keys */
const char* comment)/* in: table comment defined by user */
{
- uint length = strlen(comment);
+ uint length = (uint) strlen(comment);
char* str;
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
@@ -4714,7 +5633,7 @@ ha_innobase::update_table_comment(
external_lock(). To be safe, update the thd of the current table
handle. */
- if(length > 64000 - 3) {
+ if (length > 64000 - 3) {
return((char*)comment); /* string too long */
}
@@ -4752,13 +5671,13 @@ ha_innobase::update_table_comment(
if (str) {
char* pos = str + length;
- if(length) {
+ if (length) {
memcpy(str, comment, length);
*pos++ = ';';
*pos++ = ' ';
}
rewind(file);
- flen = fread(pos, 1, flen, file);
+ flen = (uint) fread(pos, 1, flen, file);
pos[flen] = 0;
}
@@ -4810,7 +5729,7 @@ ha_innobase::get_foreign_key_create_info(void)
flen = ftell(file);
if (flen < 0) {
flen = 0;
- } else if(flen > 64000 - 1) {
+ } else if (flen > 64000 - 1) {
flen = 64000 - 1;
}
@@ -4821,7 +5740,7 @@ ha_innobase::get_foreign_key_create_info(void)
if (str) {
rewind(file);
- flen = fread(str, 1, flen, file);
+ flen = (uint) fread(str, 1, flen, file);
str[flen] = 0;
}
@@ -4834,6 +5753,103 @@ ha_innobase::get_foreign_key_create_info(void)
return(str);
}
+
+int
+ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
+{
+ dict_foreign_t* foreign;
+
+ DBUG_ENTER("get_foreign_key_list");
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
+ ut_a(prebuilt != NULL);
+ update_thd(current_thd);
+ prebuilt->trx->op_info = (char*)"getting list of foreign keys";
+ trx_search_latch_release_if_reserved(prebuilt->trx);
+ mutex_enter_noninline(&(dict_sys->mutex));
+ foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
+
+ while (foreign != NULL)
+ {
+ uint i;
+ FOREIGN_KEY_INFO f_key_info;
+ LEX_STRING *name= 0;
+ const char *tmp_buff;
+
+ tmp_buff= foreign->id;
+ i= 0;
+ while (tmp_buff[i] != '/')
+ i++;
+ tmp_buff+= i + 1;
+ f_key_info.forein_id= make_lex_string(thd, 0, tmp_buff,
+ (uint) strlen(tmp_buff), 1);
+ tmp_buff= foreign->referenced_table_name;
+ i= 0;
+ while (tmp_buff[i] != '/')
+ i++;
+ f_key_info.referenced_db= make_lex_string(thd, 0,
+ tmp_buff, i, 1);
+ tmp_buff+= i + 1;
+ f_key_info.referenced_table= make_lex_string(thd, 0, tmp_buff,
+ (uint) strlen(tmp_buff), 1);
+
+ for (i= 0;;)
+ {
+ tmp_buff= foreign->foreign_col_names[i];
+ name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1);
+ f_key_info.foreign_fields.push_back(name);
+ tmp_buff= foreign->referenced_col_names[i];
+ name= make_lex_string(thd, name, tmp_buff, (uint) strlen(tmp_buff), 1);
+ f_key_info.referenced_fields.push_back(name);
+ if (++i >= foreign->n_fields)
+ break;
+ }
+
+ ulong length= 0;
+ if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE)
+ {
+ length=17;
+ tmp_buff= "ON DELETE CASCADE";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL)
+ {
+ length=18;
+ tmp_buff= "ON DELETE SET NULL";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_DELETE_NO_ACTION)
+ {
+ length=19;
+ tmp_buff= "ON DELETE NO ACTION";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_UPDATE_CASCADE)
+ {
+ length=17;
+ tmp_buff= "ON UPDATE CASCADE";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_UPDATE_SET_NULL)
+ {
+ length=18;
+ tmp_buff= "ON UPDATE SET NULL";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_UPDATE_NO_ACTION)
+ {
+ length=19;
+ tmp_buff= "ON UPDATE NO ACTION";
+ }
+ f_key_info.constraint_method= make_lex_string(thd,
+ f_key_info.constraint_method,
+ tmp_buff, length, 1);
+
+ FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *)
+ thd->memdup((gptr) &f_key_info,
+ sizeof(FOREIGN_KEY_INFO)));
+ f_key_list->push_back(pf_key_info);
+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ }
+ mutex_exit_noninline(&(dict_sys->mutex));
+ prebuilt->trx->op_info = (char*)"";
+ DBUG_RETURN(0);
+}
+
/*********************************************************************
Checks if ALTER TABLE may change the storage engine of the table.
Changing storage engines is not allowed for tables for which there
@@ -4922,9 +5938,11 @@ ha_innobase::extra(
if (prebuilt->blob_heap) {
row_mysql_prebuilt_free_blob_heap(prebuilt);
}
+ prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_RESET_STATE:
+ prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_NO_KEYREAD:
@@ -4943,6 +5961,9 @@ ha_innobase::extra(
case HA_EXTRA_KEYREAD:
prebuilt->read_just_key = 1;
break;
+ case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
+ prebuilt->keep_other_fields_on_keyread = 1;
+ break;
default:/* Do nothing */
;
}
@@ -4955,7 +5976,12 @@ MySQL calls this function at the start of each SQL statement inside LOCK
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
mark SQL statement borders. Note also a special case: if a temporary table
is created inside LOCK TABLES, MySQL has not called external_lock() at all
-on that table. */
+on that table.
+MySQL-5.0 also calls this before each statement in an execution of a stored
+procedure. To make the execution more deterministic for binlogging, MySQL-5.0
+locks all tables involved in a stored procedure with full explicit table
+locks (thd->in_lock_tables is true in ::store_lock()) before executing the
+procedure. */
int
ha_innobase::start_stmt(
@@ -4980,17 +6006,17 @@ ha_innobase::start_stmt(
innobase_release_stat_resources(trx);
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
- && trx->read_view) {
+ && trx->global_read_view) {
/* At low transaction isolation levels we let
each consistent read set its own snapshot */
read_view_close_for_mysql(trx);
}
- auto_inc_counter_for_this_stat = 0;
prebuilt->sql_stat_start = TRUE;
prebuilt->hint_need_to_fetch_extra_cols = 0;
prebuilt->read_just_key = 0;
+ prebuilt->keep_other_fields_on_keyread = FALSE;
if (!prebuilt->mysql_has_locked) {
/* This handle is for a temporary table created inside
@@ -5013,8 +6039,9 @@ ha_innobase::start_stmt(
select_lock_type value. The value of
stored_select_lock_type was decided in:
1) ::store_lock(),
- 2) ::external_lock(), and
- 3) ::init_table_handle_for_HANDLER(). */
+ 2) ::external_lock(),
+ 3) ::init_table_handle_for_HANDLER(), and
+ 4) :.transactional_table_lock(). */
prebuilt->select_lock_type =
prebuilt->stored_select_lock_type;
@@ -5022,9 +6049,9 @@ ha_innobase::start_stmt(
if (prebuilt->stored_select_lock_type != LOCK_S
&& prebuilt->stored_select_lock_type != LOCK_X) {
- fprintf(stderr,
-"InnoDB: Error: stored_select_lock_type is %lu inside ::start_stmt()!\n",
- prebuilt->stored_select_lock_type);
+ sql_print_error("stored_select_lock_type is %lu inside "
+ "::start_stmt()!",
+ prebuilt->stored_select_lock_type);
/* Set the value to LOCK_X: this is just fault
tolerance, we do not know what the correct value
@@ -5035,7 +6062,13 @@ ha_innobase::start_stmt(
}
/* Set the MySQL flag to mark that there is an active transaction */
- thd->transaction.all.innodb_active_trans = 1;
+ if (trx->active_trans == 0) {
+
+ innobase_register_trx_and_stmt(thd);
+ trx->active_trans = 1;
+ } else {
+ innobase_register_stmt(thd);
+ }
return(0);
}
@@ -5088,6 +6121,7 @@ ha_innobase::external_lock(
prebuilt->hint_need_to_fetch_extra_cols = 0;
prebuilt->read_just_key = 0;
+ prebuilt->keep_other_fields_on_keyread = FALSE;
if (lock_type == F_WRLCK) {
@@ -5102,7 +6136,13 @@ ha_innobase::external_lock(
/* Set the MySQL flag to mark that there is an active
transaction */
- thd->transaction.all.innodb_active_trans = 1;
+ if (trx->active_trans == 0) {
+
+ innobase_register_trx_and_stmt(thd);
+ trx->active_trans = 1;
+ } else if (trx->n_mysql_tables_in_use == 0) {
+ innobase_register_stmt(thd);
+ }
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
@@ -5127,28 +6167,32 @@ ha_innobase::external_lock(
reads. */
prebuilt->select_lock_type = LOCK_S;
+ prebuilt->stored_select_lock_type = LOCK_S;
}
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
an InnoDB table lock if it is released immediately at the end
of LOCK TABLES, and InnoDB's table locks in that case cause
- VERY easily deadlocks. */
+ VERY easily deadlocks. We do not set InnoDB table locks when
+ MySQL sets them at the start of a stored procedure call
+ (MySQL does have thd->in_lock_tables TRUE there). */
if (prebuilt->select_lock_type != LOCK_NONE) {
if (thd->in_lock_tables &&
+ thd->lex->sql_command != SQLCOM_CALL &&
thd->variables.innodb_table_locks &&
(thd->options & OPTION_NOT_AUTOCOMMIT)) {
ulint error;
error = row_lock_table_for_mysql(prebuilt,
- NULL, LOCK_TABLE_EXP);
+ NULL, 0);
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(
- error, user_thd);
- DBUG_RETURN(error);
+ (int) error, user_thd);
+ DBUG_RETURN((int) error);
}
}
@@ -5162,10 +6206,6 @@ ha_innobase::external_lock(
trx->n_mysql_tables_in_use--;
prebuilt->mysql_has_locked = FALSE;
- auto_inc_counter_for_this_stat = 0;
- if (trx->n_lock_table_exp) {
- row_unlock_tables_for_mysql(trx);
- }
/* If the MySQL lock count drops to zero we know that the current SQL
statement has ended */
@@ -5182,12 +6222,12 @@ ha_innobase::external_lock(
innobase_release_stat_resources(trx);
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
- if (thd->transaction.all.innodb_active_trans != 0) {
- innobase_commit(thd, trx);
+ if (trx->active_trans != 0) {
+ innobase_commit(thd, TRUE);
}
} else {
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
- && trx->read_view) {
+ && trx->global_read_view) {
/* At low transaction isolation levels we let
each consistent read set its own snapshot */
@@ -5200,11 +6240,112 @@ ha_innobase::external_lock(
DBUG_RETURN(0);
}
+/**********************************************************************
+With this function MySQL request a transactional lock to a table when
+user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
+
+int
+ha_innobase::transactional_table_lock(
+/*==================================*/
+ /* out: error code */
+ THD* thd, /* in: handle to the user thread */
+ int lock_type) /* in: lock type */
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ trx_t* trx;
+
+ DBUG_ENTER("ha_innobase::transactional_table_lock");
+ DBUG_PRINT("enter",("lock_type: %d", lock_type));
+
+ /* We do not know if MySQL can call this function before calling
+ external_lock(). To be safe, update the thd of the current table
+ handle. */
+
+ update_thd(thd);
+
+ if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB error:\n"
+"MySQL is trying to use a table handle but the .ibd file for\n"
+"table %s does not exist.\n"
+"Have you deleted the .ibd file from the database directory under\n"
+"the MySQL datadir?"
+"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
+"how you can resolve the problem.\n",
+ prebuilt->table->name);
+ DBUG_RETURN(HA_ERR_CRASHED);
+ }
+
+ trx = prebuilt->trx;
+
+ prebuilt->sql_stat_start = TRUE;
+ prebuilt->hint_need_to_fetch_extra_cols = 0;
+
+ prebuilt->read_just_key = 0;
+ prebuilt->keep_other_fields_on_keyread = FALSE;
+
+ if (lock_type == F_WRLCK) {
+ prebuilt->select_lock_type = LOCK_X;
+ prebuilt->stored_select_lock_type = LOCK_X;
+ } else if (lock_type == F_RDLCK) {
+ prebuilt->select_lock_type = LOCK_S;
+ prebuilt->stored_select_lock_type = LOCK_S;
+ } else {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB error:\n"
+"MySQL is trying to set transactional table lock with corrupted lock type\n"
+"to table %s, lock type %d does not exist.\n",
+ prebuilt->table->name, lock_type);
+ DBUG_RETURN(HA_ERR_CRASHED);
+ }
+
+ /* MySQL is setting a new transactional table lock */
+
+ /* Set the MySQL flag to mark that there is an active transaction */
+ if (trx->active_trans == 0) {
+
+ innobase_register_trx_and_stmt(thd);
+ trx->active_trans = 1;
+ }
+
+ if (thd->in_lock_tables && thd->variables.innodb_table_locks) {
+ ulint error = DB_SUCCESS;
+
+ error = row_lock_table_for_mysql(prebuilt, NULL, 0);
+
+ if (error != DB_SUCCESS) {
+ error = convert_error_code_to_mysql((int) error, user_thd);
+ DBUG_RETURN((int) error);
+ }
+
+ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
+
+ /* Store the current undo_no of the transaction
+ so that we know where to roll back if we have
+ to roll back the next SQL statement */
+
+ trx_mark_sql_stat_end(trx);
+ }
+ }
+
+ DBUG_RETURN(0);
+}
+
+/****************************************************************************
+Here we export InnoDB status variables to MySQL. */
+
+void
+innodb_export_status(void)
+/*======================*/
+{
+ srv_export_innodb_status();
+}
+
/****************************************************************************
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
Monitor to the client. */
-int
+bool
innodb_show_status(
/*===============*/
THD* thd) /* in: the MySQL query thread of the caller */
@@ -5222,7 +6363,7 @@ innodb_show_status(
my_message(ER_NOT_SUPPORTED_YET,
"Cannot call SHOW INNODB STATUS because skip-innodb is defined",
MYF(0));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
trx = check_trx_exists(thd);
@@ -5241,6 +6382,7 @@ innodb_show_status(
&trx_list_start, &trx_list_end);
flen = ftell(srv_monitor_file);
os_file_set_eof(srv_monitor_file);
+
if (flen < 0) {
flen = 0;
}
@@ -5257,28 +6399,28 @@ innodb_show_status(
if (!(str = my_malloc(usable_len + 1, MYF(0))))
{
mutex_exit_noninline(&srv_monitor_file_mutex);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
rewind(srv_monitor_file);
if (flen < MAX_STATUS_SIZE) {
/* Display the entire output. */
- flen = fread(str, 1, flen, srv_monitor_file);
+ flen = (long) fread(str, 1, flen, srv_monitor_file);
} else if (trx_list_end < (ulint) flen
&& trx_list_start < trx_list_end
&& trx_list_start + (flen - trx_list_end)
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
/* Omit the beginning of the list of active transactions. */
- long len = fread(str, 1, trx_list_start, srv_monitor_file);
+ long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
len += sizeof truncated_msg - 1;
usable_len = (MAX_STATUS_SIZE - 1) - len;
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
- len += fread(str + len, 1, usable_len, srv_monitor_file);
+ len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
flen = len;
} else {
/* Omit the end of the output. */
- flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
+ flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
}
mutex_exit_noninline(&srv_monitor_file_mutex);
@@ -5287,22 +6429,122 @@ innodb_show_status(
field_list.push_back(new Item_empty_string("Status", flen));
- if (protocol->send_fields(&field_list, 1)) {
-
+ if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF)) {
my_free(str, MYF(0));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
protocol->prepare_for_resend();
protocol->store(str, flen, system_charset_info);
my_free(str, MYF(0));
- if (protocol->write())
- DBUG_RETURN(-1);
+ if (protocol->write()) {
+ DBUG_RETURN(TRUE);
+ }
send_eof(thd);
- DBUG_RETURN(0);
+
+ DBUG_RETURN(FALSE);
+}
+
+/****************************************************************************
+Implements the SHOW MUTEX STATUS command. . */
+
+bool
+innodb_mutex_show_status(
+/*===============*/
+ THD* thd) /* in: the MySQL query thread of the caller */
+{
+ Protocol *protocol= thd->protocol;
+ List<Item> field_list;
+ mutex_t* mutex;
+ ulint rw_lock_count= 0;
+ ulint rw_lock_count_spin_loop= 0;
+ ulint rw_lock_count_spin_rounds= 0;
+ ulint rw_lock_count_os_wait= 0;
+ ulint rw_lock_count_os_yield= 0;
+ ulonglong rw_lock_wait_time= 0;
+ DBUG_ENTER("innodb_mutex_show_status");
+
+ field_list.push_back(new Item_empty_string("Mutex", FN_REFLEN));
+ field_list.push_back(new Item_empty_string("Module", FN_REFLEN));
+ field_list.push_back(new Item_uint("Count", 21));
+ field_list.push_back(new Item_uint("Spin_waits", 21));
+ field_list.push_back(new Item_uint("Spin_rounds", 21));
+ field_list.push_back(new Item_uint("OS_waits", 21));
+ field_list.push_back(new Item_uint("OS_yields", 21));
+ field_list.push_back(new Item_uint("OS_waits_time", 21));
+
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
+
+#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
+ mutex_enter(&mutex_list_mutex);
+#endif
+
+ mutex = UT_LIST_GET_FIRST(mutex_list);
+
+ while ( mutex != NULL )
+ {
+ if (mutex->mutex_type != 1)
+ {
+ if (mutex->count_using > 0)
+ {
+ protocol->prepare_for_resend();
+ protocol->store(mutex->cmutex_name, system_charset_info);
+ protocol->store(mutex->cfile_name, system_charset_info);
+ protocol->store((ulonglong)mutex->count_using);
+ protocol->store((ulonglong)mutex->count_spin_loop);
+ protocol->store((ulonglong)mutex->count_spin_rounds);
+ protocol->store((ulonglong)mutex->count_os_wait);
+ protocol->store((ulonglong)mutex->count_os_yield);
+ protocol->store((ulonglong)mutex->lspent_time/1000);
+
+ if (protocol->write())
+ {
+#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
+ mutex_exit(&mutex_list_mutex);
+#endif
+ DBUG_RETURN(1);
+ }
+ }
+ }
+ else
+ {
+ rw_lock_count += mutex->count_using;
+ rw_lock_count_spin_loop += mutex->count_spin_loop;
+ rw_lock_count_spin_rounds += mutex->count_spin_rounds;
+ rw_lock_count_os_wait += mutex->count_os_wait;
+ rw_lock_count_os_yield += mutex->count_os_yield;
+ rw_lock_wait_time += mutex->lspent_time;
+ }
+
+ mutex = UT_LIST_GET_NEXT(list, mutex);
+ }
+
+ protocol->prepare_for_resend();
+ protocol->store("rw_lock_mutexes", system_charset_info);
+ protocol->store("", system_charset_info);
+ protocol->store((ulonglong)rw_lock_count);
+ protocol->store((ulonglong)rw_lock_count_spin_loop);
+ protocol->store((ulonglong)rw_lock_count_spin_rounds);
+ protocol->store((ulonglong)rw_lock_count_os_wait);
+ protocol->store((ulonglong)rw_lock_count_os_yield);
+ protocol->store((ulonglong)rw_lock_wait_time/1000);
+
+ if (protocol->write())
+ {
+ DBUG_RETURN(1);
+ }
+
+#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
+ mutex_exit(&mutex_list_mutex);
+#endif
+ send_eof(thd);
+ DBUG_RETURN(FALSE);
}
/****************************************************************************
@@ -5320,7 +6562,7 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
static INNOBASE_SHARE *get_share(const char *table_name)
{
INNOBASE_SHARE *share;
- pthread_mutex_lock(&innobase_mutex);
+ pthread_mutex_lock(&innobase_share_mutex);
uint length=(uint) strlen(table_name);
if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
(mysql_byte*) table_name,
@@ -5334,7 +6576,7 @@ static INNOBASE_SHARE *get_share(const char *table_name)
strmov(share->table_name,table_name);
if (my_hash_insert(&innobase_open_tables, (mysql_byte*) share))
{
- pthread_mutex_unlock(&innobase_mutex);
+ pthread_mutex_unlock(&innobase_share_mutex);
my_free((gptr) share,0);
return 0;
}
@@ -5343,13 +6585,13 @@ static INNOBASE_SHARE *get_share(const char *table_name)
}
}
share->use_count++;
- pthread_mutex_unlock(&innobase_mutex);
+ pthread_mutex_unlock(&innobase_share_mutex);
return share;
}
static void free_share(INNOBASE_SHARE *share)
{
- pthread_mutex_lock(&innobase_mutex);
+ pthread_mutex_lock(&innobase_share_mutex);
if (!--share->use_count)
{
hash_delete(&innobase_open_tables, (mysql_byte*) share);
@@ -5357,7 +6599,7 @@ static void free_share(INNOBASE_SHARE *share)
pthread_mutex_destroy(&share->mutex);
my_free((gptr) share, MYF(0));
}
- pthread_mutex_unlock(&innobase_mutex);
+ pthread_mutex_unlock(&innobase_share_mutex);
}
/*********************************************************************
@@ -5381,11 +6623,16 @@ ha_innobase::store_lock(
of current handle is stored
next to this array */
enum thr_lock_type lock_type) /* in: lock type to store in
- 'lock' */
+ 'lock'; this may also be
+ TL_IGNORE */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
- if ((lock_type == TL_READ && thd->in_lock_tables) ||
+ /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
+ Be careful to ignore TL_IGNORE if we are going to do something with
+ only 'real' locks! */
+
+ if ((lock_type == TL_READ && thd->in_lock_tables) ||
(lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) ||
lock_type == TL_READ_WITH_SHARED_LOCKS ||
lock_type == TL_READ_NO_INSERT ||
@@ -5402,15 +6649,18 @@ ha_innobase::store_lock(
MySQL is doing LOCK TABLES ... READ.
5) we let InnoDB do locking reads for all SQL statements that
are not simple SELECTs; note that select_lock_type in this
- case may get strengthened in ::external_lock() to LOCK_X. */
+ case may get strengthened in ::external_lock() to LOCK_X.
+ Note that we MUST use a locking read in all data modifying
+ SQL statements, because otherwise the execution would not be
+ serializable, and also the results from the update could be
+ unexpected if an obsolete consistent read view would be
+ used. */
if (srv_locks_unsafe_for_binlog &&
prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE &&
(lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
- thd->lex->sql_command != SQLCOM_SELECT &&
- thd->lex->sql_command != SQLCOM_UPDATE_MULTI &&
- thd->lex->sql_command != SQLCOM_DELETE_MULTI &&
- thd->lex->sql_command != SQLCOM_LOCK_TABLES) {
+ (thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
+ thd->lex->sql_command == SQLCOM_UPDATE)) {
/* In case we have innobase_locks_unsafe_for_binlog
option set and isolation level of the transaction
@@ -5428,10 +6678,6 @@ ha_innobase::store_lock(
} else if (lock_type != TL_IGNORE) {
- /* In ha_berkeley.cc there is a comment that MySQL
- may in exceptional cases call this with TL_IGNORE also
- when it is NOT going to release the lock. */
-
/* We set possible LOCK_X value in external_lock, not yet
here even if this would be SELECT ... FOR UPDATE */
@@ -5441,6 +6687,14 @@ ha_innobase::store_lock(
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
+ /* Starting from 5.0.7, we weaken also the table locks
+ set at the start of a MySQL stored procedure call, just like
+ we weaken the locks set at the start of an SQL statement.
+ MySQL does set thd->in_lock_tables TRUE there, but in reality
+ we do not need table locks to make the execution of a
+ single transaction stored procedure call deterministic
+ (if it does not use a consistent read). */
+
if (lock_type == TL_READ && thd->in_lock_tables) {
/* We come here if MySQL is processing LOCK TABLES
... READ LOCAL. MyISAM under that table lock type
@@ -5457,11 +6711,14 @@ ha_innobase::store_lock(
}
/* If we are not doing a LOCK TABLE or DISCARD/IMPORT
- TABLESPACE, then allow multiple writers */
+ TABLESPACE or TRUNCATE TABLE, then allow multiple writers */
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
- lock_type <= TL_WRITE) && !thd->in_lock_tables
+ lock_type <= TL_WRITE)
+ && (!thd->in_lock_tables
+ || thd->lex->sql_command == SQLCOM_CALL)
&& !thd->tablespace_op
+ && thd->lex->sql_command != SQLCOM_TRUNCATE
&& thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
lock_type = TL_WRITE_ALLOW_WRITE;
@@ -5473,11 +6730,14 @@ ha_innobase::store_lock(
to t2. Convert the lock to a normal read lock to allow
concurrent inserts to t2. */
- if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) {
+ if (lock_type == TL_READ_NO_INSERT
+ && (!thd->in_lock_tables
+ || thd->lex->sql_command == SQLCOM_CALL)) {
+
lock_type = TL_READ;
}
- lock.type=lock_type;
+ lock.type = lock_type;
}
*to++= &lock;
@@ -5488,25 +6748,31 @@ 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 paramete ret returns
+counter if it already has been initialized. In parameter ret returns
the value of the auto-inc counter. */
int
ha_innobase::innobase_read_and_init_auto_inc(
/*=========================================*/
- /* out: 0 or error code: deadlock or
- lock wait timeout */
+ /* out: 0 or error code: deadlock or lock wait
+ timeout */
longlong* ret) /* out: auto-inc value */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
longlong auto_inc;
+ ulint old_select_lock_type;
+ ibool trx_was_not_started = FALSE;
int error;
ut_a(prebuilt);
ut_a(prebuilt->trx ==
- (trx_t*) current_thd->transaction.all.innobase_tid);
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
ut_a(prebuilt->table);
+ if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
+ trx_was_not_started = TRUE;
+ }
+
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
@@ -5518,7 +6784,9 @@ ha_innobase::innobase_read_and_init_auto_inc(
/* Already initialized */
*ret = auto_inc;
- return(0);
+ error = 0;
+
+ goto func_exit_early;
}
error = row_lock_table_autoinc_for_mysql(prebuilt);
@@ -5526,7 +6794,7 @@ ha_innobase::innobase_read_and_init_auto_inc(
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(error, user_thd);
- goto func_exit;
+ goto func_exit_early;
}
/* Check again if someone has initialized the counter meanwhile */
@@ -5535,30 +6803,37 @@ ha_innobase::innobase_read_and_init_auto_inc(
if (auto_inc != 0) {
*ret = auto_inc;
- return(0);
+ error = 0;
+
+ goto func_exit_early;
}
(void) extra(HA_EXTRA_KEYREAD);
- index_init(table->next_number_index);
-
- /* We use an exclusive lock when we read the max key value from the
- auto-increment column index. This is because then build_template will
- advise InnoDB to fetch all columns. In SHOW TABLE STATUS the query
- id of the auto-increment column is not changed, and previously InnoDB
- did not fetch it, causing SHOW TABLE STATUS to show wrong values
- for the autoinc column. */
+ index_init(table->s->next_number_index);
- prebuilt->select_lock_type = LOCK_X;
+ /* Starting from 5.0.9, we use a consistent read to read the auto-inc
+ column maximum value. This eliminates the spurious deadlocks caused
+ by the row X-lock that we previously used. Note the following flaw
+ in our algorithm: if some other user meanwhile UPDATEs the auto-inc
+ column, our consistent read will not return the largest value. We
+ accept this flaw, since the deadlocks were a bigger trouble. */
- /* Play safe and also give in another way the hint to fetch
- all columns in the key: */
+ /* Fetch all the columns in the key */
prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
- prebuilt->trx->mysql_n_tables_locked += 1;
-
+ old_select_lock_type = prebuilt->select_lock_type;
+ prebuilt->select_lock_type = LOCK_NONE;
+
+ /* Eliminate an InnoDB error print that happens when we try to SELECT
+ from a table when no table has been locked in ::external_lock(). */
+ prebuilt->trx->n_mysql_tables_in_use++;
+
error = index_last(table->record[1]);
+ prebuilt->trx->n_mysql_tables_in_use--;
+ prebuilt->select_lock_type = old_select_lock_type;
+
if (error) {
if (error == HA_ERR_END_OF_FILE) {
/* The table was empty, initialize to 1 */
@@ -5566,15 +6841,22 @@ ha_innobase::innobase_read_and_init_auto_inc(
error = 0;
} else {
- /* Deadlock or a lock wait timeout */
+ /* This should not happen in a consistent read */
+ sql_print_error("Consistent read of auto-inc column "
+ "returned %lu", (ulong) error);
auto_inc = -1;
goto func_exit;
}
} else {
- /* Initialize to max(col) + 1 */
- auto_inc = (longlong) table->next_number_field->
- val_int_offset(table->rec_buff_length) + 1;
+ /* Initialize to max(col) + 1; we use
+ 'found_next_number_field' below because MySQL in SHOW TABLE
+ STATUS does not seem to set 'next_number_field'. The comment
+ in table.h says that 'next_number_field' is set when it is
+ 'active'. */
+
+ auto_inc = (longlong) table->found_next_number_field->
+ val_int_offset(table->s->rec_buff_length) + 1;
}
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
@@ -5586,7 +6868,20 @@ func_exit:
*ret = auto_inc;
- return(error);
+func_exit_early:
+ /* Since MySQL does not seem to call autocommit after SHOW TABLE
+ STATUS (even if we would register the trx here), we commit our
+ transaction here if it was started here. This is to eliminate a
+ dangling transaction. If the user had AUTOCOMMIT=0, then SHOW
+ TABLE STATUS does leave a dangling transaction if the user does not
+ himself call COMMIT. */
+
+ if (trx_was_not_started) {
+
+ innobase_commit_low(prebuilt->trx);
+ }
+
+ return(error);
}
/***********************************************************************
@@ -5595,7 +6890,7 @@ initialized yet. This function does not change the value of the auto-inc
counter if it already has been initialized. Returns the value of the
auto-inc counter. */
-longlong
+ulonglong
ha_innobase::get_auto_increment()
/*=============================*/
/* out: auto-increment column value, -1 if error
@@ -5607,42 +6902,114 @@ ha_innobase::get_auto_increment()
error = innobase_read_and_init_auto_inc(&nr);
if (error) {
-
- return(-1);
+ /* This should never happen in the current (5.0.6) code, since
+ we call this function only after the counter has been
+ initialized. */
+
+ ut_print_timestamp(stderr);
+ sql_print_error("Error %lu in ::get_auto_increment()",
+ (ulong) error);
+ return(~(ulonglong) 0);
}
- return(nr);
+ return((ulonglong) nr);
+}
+
+/* See comment in handler.h */
+int
+ha_innobase::reset_auto_increment(ulonglong value)
+{
+ DBUG_ENTER("ha_innobase::reset_auto_increment");
+
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ int error;
+
+ error = row_lock_table_autoinc_for_mysql(prebuilt);
+
+ if (error != DB_SUCCESS) {
+ error = convert_error_code_to_mysql(error, user_thd);
+
+ DBUG_RETURN(error);
+ }
+
+ dict_table_autoinc_initialize(prebuilt->table, value);
+
+ DBUG_RETURN(0);
}
/***********************************************************************
-This function stores the binlog offset and flushes logs. */
+Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
+If there is no explicitly declared non-null unique key or a primary key, then
+InnoDB internally uses the row id as the primary key. */
-void
-innobase_store_binlog_offset_and_flush_log(
-/*=======================================*/
- char *binlog_name, /* in: binlog name */
- longlong offset) /* in: binlog offset */
+int
+ha_innobase::cmp_ref(
+/*=================*/
+ /* out: < 0 if ref1 < ref2, 0 if equal, else
+ > 0 */
+ const mysql_byte* ref1, /* in: an (internal) primary key value in the
+ MySQL key value format */
+ const mysql_byte* ref2) /* in: an (internal) primary key value in the
+ MySQL key value format */
{
- mtr_t mtr;
-
- assert(binlog_name != NULL);
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ enum_field_types mysql_type;
+ Field* field;
+ KEY_PART_INFO* key_part;
+ KEY_PART_INFO* key_part_end;
+ uint len1;
+ uint len2;
+ int result;
- /* Start a mini-transaction */
- mtr_start_noninline(&mtr);
+ if (prebuilt->clust_index_was_generated) {
+ /* The 'ref' is an InnoDB row id */
- /* Update the latest MySQL binlog name and offset info
- in trx sys header */
+ return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
+ }
- trx_sys_update_mysql_binlog_offset(
- binlog_name,
- offset,
- TRX_SYS_MYSQL_LOG_INFO, &mtr);
+ /* Do a type-aware comparison of primary key fields. PK fields
+ are always NOT NULL, so no checks for NULL are performed. */
- /* Commits the mini-transaction */
- mtr_commit(&mtr);
-
- /* Syncronous flush of the log buffer to disk */
- log_buffer_flush_to_disk();
+ key_part = table->key_info[table->s->primary_key].key_part;
+
+ key_part_end = key_part
+ + table->key_info[table->s->primary_key].key_parts;
+
+ for (; key_part != key_part_end; ++key_part) {
+ field = key_part->field;
+ mysql_type = field->type();
+
+ if (mysql_type == FIELD_TYPE_TINY_BLOB
+ || mysql_type == FIELD_TYPE_MEDIUM_BLOB
+ || mysql_type == FIELD_TYPE_BLOB
+ || mysql_type == FIELD_TYPE_LONG_BLOB) {
+
+ /* In the MySQL key value format, a column prefix of
+ a BLOB is preceded by a 2-byte length field */
+
+ len1 = innobase_read_from_2_little_endian(ref1);
+ len2 = innobase_read_from_2_little_endian(ref2);
+
+ ref1 += 2;
+ ref2 += 2;
+ result = ((Field_blob*)field)->cmp(
+ (const char*)ref1, len1,
+ (const char*)ref2, len2);
+ } else {
+ result = field->cmp((const char*)ref1,
+ (const char*)ref2);
+ }
+
+ if (result) {
+
+ return(result);
+ }
+
+ ref1 += key_part->store_length;
+ ref2 += key_part->store_length;
+ }
+
+ return(0);
}
char*
@@ -5686,7 +7053,7 @@ innobase_get_at_most_n_mbchars(
ulint n_chars; /* number of characters in prefix */
CHARSET_INFO* charset; /* charset used in the field */
- charset = get_charset(charset_id, MYF(MY_WME));
+ charset = get_charset((uint) charset_id, MYF(MY_WME));
ut_ad(charset);
ut_ad(charset->mbmaxlen);
@@ -5720,7 +7087,7 @@ innobase_get_at_most_n_mbchars(
whole string. */
char_length = my_charpos(charset, str,
- str + data_len, n_chars);
+ str + data_len, (int) n_chars);
if (char_length > data_len) {
char_length = data_len;
}
@@ -5757,15 +7124,17 @@ innobase_query_is_update(void)
thd = (THD *)innobase_current_thd();
- if ( thd->lex->sql_command == SQLCOM_REPLACE ||
- thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
- ( thd->lex->sql_command == SQLCOM_LOAD &&
- thd->lex->duplicates == DUP_REPLACE )) {
+ if (thd->lex->sql_command == SQLCOM_REPLACE ||
+ thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
+ (thd->lex->sql_command == SQLCOM_LOAD &&
+ thd->lex->duplicates == DUP_REPLACE)) {
+
return(1);
}
- if ( thd->lex->sql_command == SQLCOM_INSERT &&
- thd->lex->duplicates == DUP_UPDATE ) {
+ if (thd->lex->sql_command == SQLCOM_INSERT &&
+ thd->lex->duplicates == DUP_UPDATE) {
+
return(1);
}
@@ -5773,4 +7142,204 @@ innobase_query_is_update(void)
}
}
+/***********************************************************************
+This function is used to prepare X/Open XA distributed transaction */
+
+int
+innobase_xa_prepare(
+/*================*/
+ /* out: 0 or error number */
+ THD* thd, /* in: handle to the MySQL thread of the user
+ whose XA transaction should be prepared */
+ bool all) /* in: TRUE - commit transaction
+ FALSE - the current SQL statement ended */
+{
+ int error = 0;
+ trx_t* trx = check_trx_exists(thd);
+
+ if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
+
+ /* For ibbackup to work the order of transactions in binlog
+ and InnoDB must be the same. Consider the situation
+
+ thread1> prepare; write to binlog; ...
+ <context switch>
+ thread2> prepare; write to binlog; commit
+ thread1> ... commit
+
+ To ensure this will not happen we're taking the mutex on
+ prepare, and releasing it on commit.
+
+ Note: only do it for normal commits, done via ha_commit_trans.
+ If 2pc protocol is executed by external transaction
+ coordinator, it will be just a regular MySQL client
+ executing XA PREPARE and XA COMMIT commands.
+ In this case we cannot know how many minutes or hours
+ will be between XA PREPARE and XA COMMIT, and we don't want
+ to block for undefined period of time.
+ */
+ pthread_mutex_lock(&prepare_commit_mutex);
+ trx->active_trans = 2;
+ }
+
+ if (!thd->variables.innodb_support_xa) {
+
+ return(0);
+ }
+
+ trx->xid=thd->transaction.xid_state.xid;
+
+ /* Release a possible FIFO ticket and search latch. Since we will
+ reserve the kernel mutex, we have to release the search system latch
+ first to obey the latching order. */
+
+ innobase_release_stat_resources(trx);
+
+ if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
+
+ sql_print_error("trx->active_trans == 0, but trx->conc_state != "
+ "TRX_NOT_STARTED");
+ }
+
+ if (all
+ || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
+
+ /* We were instructed to prepare the whole transaction, or
+ this is an SQL statement end and autocommit is on */
+
+ ut_ad(trx->active_trans);
+
+ error = (int) trx_prepare_for_mysql(trx);
+ } else {
+ /* We just mark the SQL statement ended and do not do a
+ transaction prepare */
+
+ if (trx->auto_inc_lock) {
+ /* If we had reserved the auto-inc lock for some
+ table in this SQL statement we release it now */
+
+ row_unlock_table_autoinc_for_mysql(trx);
+ }
+ /* Store the current undo_no of the transaction so that we
+ know where to roll back if we have to roll back the next
+ SQL statement */
+
+ trx_mark_sql_stat_end(trx);
+ }
+
+ /* Tell the InnoDB server that there might be work for utility
+ threads: */
+
+ srv_active_wake_master_thread();
+
+ return error;
+}
+
+/***********************************************************************
+This function is used to recover X/Open XA distributed transactions */
+
+int
+innobase_xa_recover(
+/*================*/
+ /* out: number of prepared transactions
+ stored in xid_list */
+ XID* xid_list, /* in/out: prepared transactions */
+ uint len) /* in: number of slots in xid_list */
+{
+ if (len == 0 || xid_list == NULL) {
+
+ return(0);
+ }
+
+ return(trx_recover_for_mysql(xid_list, len));
+}
+
+/***********************************************************************
+This function is used to commit one X/Open XA distributed transaction
+which is in the prepared state */
+
+int
+innobase_commit_by_xid(
+/*===================*/
+ /* out: 0 or error number */
+ XID* xid) /* in: X/Open XA transaction identification */
+{
+ trx_t* trx;
+
+ trx = trx_get_trx_by_xid(xid);
+
+ if (trx) {
+ innobase_commit_low(trx);
+
+ return(XA_OK);
+ } else {
+ return(XAER_NOTA);
+ }
+}
+
+/***********************************************************************
+This function is used to rollback one X/Open XA distributed transaction
+which is in the prepared state */
+
+int
+innobase_rollback_by_xid(
+/*=====================*/
+ /* out: 0 or error number */
+ XID *xid) /* in: X/Open XA transaction identification */
+{
+ trx_t* trx;
+
+ trx = trx_get_trx_by_xid(xid);
+
+ if (trx) {
+ return(innobase_rollback_trx(trx));
+ } else {
+ return(XAER_NOTA);
+ }
+}
+
+/***********************************************************************
+Create a consistent view for a cursor based on current transaction
+which is created if the corresponding MySQL thread still lacks one.
+This consistent view is then used inside of MySQL when accessing records
+using a cursor. */
+
+void*
+innobase_create_cursor_view(void)
+/*=============================*/
+ /* out: Pointer to cursor view or NULL */
+{
+ return(read_cursor_view_create_for_mysql(
+ check_trx_exists(current_thd)));
+}
+
+/***********************************************************************
+Close the given consistent cursor view of a transaction and restore
+global read view to a transaction read view. Transaction is created if the
+corresponding MySQL thread still lacks one. */
+
+void
+innobase_close_cursor_view(
+/*=======================*/
+ void* curview)/* in: Consistent read view to be closed */
+{
+ read_cursor_view_close_for_mysql(check_trx_exists(current_thd),
+ (cursor_view_t*) curview);
+}
+
+/***********************************************************************
+Set the given consistent cursor view to a transaction which is created
+if the corresponding MySQL thread still lacks one. If the given
+consistent cursor view is NULL global read view of a transaction is
+restored to a transaction read view. */
+
+void
+innobase_set_cursor_view(
+/*=====================*/
+ void* curview)/* in: Consistent cursor view to be set */
+{
+ read_cursor_set_for_mysql(check_trx_exists(current_thd),
+ (cursor_view_t*) curview);
+}
+
#endif /* HAVE_INNOBASE_DB */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index d336811a1eb..672e48d9817 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB && Innobase Oy
+/* Copyright (C) 2000-2005 MySQL AB && Innobase Oy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,16 +33,21 @@ typedef struct st_innobase_share {
} INNOBASE_SHARE;
+my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
+ uint full_name_len,
+ ulonglong *unused);
+
/* The class defining a handle to an Innodb table */
class ha_innobase: public handler
{
- void* innobase_prebuilt; /* (row_prebuilt_t*) prebuilt
- struct in Innodb, used to save
- CPU */
+ void* innobase_prebuilt;/* (row_prebuilt_t*) prebuilt
+ struct in InnoDB, used to save
+ CPU time with prebuilt data
+ structures*/
THD* user_thd; /* the thread handle of the user
currently using the handle; this is
set in external_lock function */
- ulong last_query_id; /* the latest query id where the
+ query_id_t last_query_id; /* the latest query id where the
handle was used */
THR_LOCK_DATA lock;
INNOBASE_SHARE *share;
@@ -65,7 +70,6 @@ class ha_innobase: public handler
ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
or undefined */
uint num_write_row; /* number of write_row() calls */
- longlong auto_inc_counter_for_this_stat;
ulong max_supported_row_length(const byte *buf);
uint store_key_val_for_row(uint keynr, char* buff, uint buff_len,
@@ -77,20 +81,13 @@ class ha_innobase: public handler
/* Init values for the class: */
public:
- ha_innobase(TABLE *table): handler(table),
- int_table_flags(HA_REC_NOT_IN_SEQ |
- HA_NULL_IN_KEY | HA_FAST_KEY_READ |
- HA_CAN_INDEX_BLOBS |
- HA_CAN_SQL_HANDLER |
- HA_NOT_EXACT_COUNT |
- HA_PRIMARY_KEY_IN_READ_INDEX |
- HA_TABLE_SCAN_ON_INDEX),
- last_dup_key((uint) -1),
- start_of_scan(0),
- num_write_row(0)
- {
- }
+ ha_innobase(TABLE *table_arg);
~ha_innobase() {}
+ /*
+ Get the row type from the storage engine. If this method returns
+ ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used.
+ */
+ enum row_type get_row_type() const;
const char* table_type() const { return("InnoDB");}
const char *index_type(uint key_number) { return "BTREE"; }
@@ -98,7 +95,10 @@ class ha_innobase: public handler
ulong table_flags() const { return int_table_flags; }
ulong index_flags(uint idx, uint part, bool all_parts) const
{
- return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE |
+ return (HA_READ_NEXT |
+ HA_READ_PREV |
+ HA_READ_ORDER |
+ HA_READ_RANGE |
HA_KEYREAD_ONLY);
}
uint max_supported_keys() const { return MAX_KEY; }
@@ -122,6 +122,7 @@ class ha_innobase: public handler
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
+ void unlock_row();
int index_init(uint index);
int index_end();
@@ -148,35 +149,58 @@ class ha_innobase: public handler
int discard_or_import_tablespace(my_bool discard);
int extra(enum ha_extra_function operation);
int external_lock(THD *thd, int lock_type);
+ int transactional_table_lock(THD *thd, int lock_type);
int start_stmt(THD *thd);
void position(byte *record);
- ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
+ ha_rows records_in_range(uint inx, key_range *min_key, key_range
+ *max_key);
ha_rows estimate_rows_upper_bound();
int create(const char *name, register TABLE *form,
HA_CREATE_INFO *create_info);
+ int delete_all_rows();
int delete_table(const char *name);
int rename_table(const char* from, const char* to);
int check(THD* thd, HA_CHECK_OPT* check_opt);
char* update_table_comment(const char* comment);
char* get_foreign_key_create_info();
+ int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
bool can_switch_engines();
uint referenced_by_foreign_key();
void free_foreign_key_create_info(char* str);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
void init_table_handle_for_HANDLER();
- longlong get_auto_increment();
+ ulonglong get_auto_increment();
+ int reset_auto_increment(ulonglong value);
+
uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; }
-
- static char *get_mysql_bin_log_name();
+ /*
+ ask handler about permission to cache table during query registration
+ */
+ my_bool register_query_cache_table(THD *thd, char *table_key,
+ uint key_length,
+ qc_engine_callback *call_back,
+ ulonglong *engine_data)
+ {
+ *call_back= innobase_query_caching_of_table_permitted;
+ *engine_data= 0;
+ return innobase_query_caching_of_table_permitted(thd, table_key,
+ key_length,
+ engine_data);
+ }
+ 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);
};
+extern struct show_var_st innodb_status_variables[];
extern uint innobase_init_flags, innobase_lock_type;
extern uint innobase_flush_log_at_trx_commit;
-extern ulong innobase_cache_size;
+extern ulong innobase_cache_size, innobase_fast_shutdown;
+extern ulong innobase_large_page_size;
extern char *innobase_home, *innobase_tmpdir, *innobase_logdir;
extern long innobase_lock_scan_time;
extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
@@ -184,14 +208,17 @@ extern long innobase_log_file_size, innobase_log_buffer_size;
extern long innobase_buffer_pool_size, innobase_additional_mem_pool_size;
extern long innobase_buffer_pool_awe_mem_mb;
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
-extern long innobase_force_recovery, innobase_thread_concurrency;
+extern long innobase_force_recovery;
extern long innobase_open_files;
extern char *innobase_data_home_dir, *innobase_data_file_path;
extern char *innobase_log_group_home_dir, *innobase_log_arch_dir;
extern char *innobase_unix_file_flush_method;
/* The following variables have to be my_bool for SHOW VARIABLES to work */
extern my_bool innobase_log_archive,
- innobase_use_native_aio, innobase_fast_shutdown,
+ innobase_use_doublewrite,
+ innobase_use_checksums,
+ innobase_use_large_pages,
+ innobase_use_native_aio,
innobase_file_per_table, innobase_locks_unsafe_for_binlog,
innobase_create_status_file;
extern my_bool innobase_very_fast_shutdown; /* set this to 1 just before
@@ -203,40 +230,118 @@ extern "C" {
extern ulong srv_max_buf_pool_modified_pct;
extern ulong srv_max_purge_lag;
extern ulong srv_auto_extend_increment;
+extern ulong srv_n_spin_wait_rounds;
+extern ulong srv_n_free_tickets_to_enter;
+extern ulong srv_thread_sleep_delay;
+extern ulong srv_thread_concurrency;
+extern ulong srv_commit_concurrency;
}
extern TYPELIB innobase_lock_typelib;
-bool innobase_init(void);
+handlerton *innobase_init(void);
bool innobase_end(void);
bool innobase_flush_logs(void);
uint innobase_get_free_space(void);
-int innobase_commit(THD *thd, void* trx_handle);
+/*
+ don't delete it - it may be re-enabled later
+ as an optimization for the most common case InnoDB+binlog
+*/
+#if 0
int innobase_report_binlog_offset_and_commit(
THD* thd,
void* trx_handle,
char* log_file_name,
my_off_t end_offset);
-int innobase_commit_complete(
- void* trx_handle);
-int innobase_rollback(THD *thd, void* trx_handle);
-int innobase_rollback_to_savepoint(
- THD* thd,
- char* savepoint_name,
- my_off_t* binlog_cache_pos);
-int innobase_savepoint(
- THD* thd,
- char* savepoint_name,
- my_off_t binlog_cache_pos);
-int innobase_close_connection(THD *thd);
+int innobase_commit_complete(void* trx_handle);
+void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
+#endif
+
int innobase_drop_database(char *path);
-int innodb_show_status(THD* thd);
+bool innodb_show_status(THD* thd);
+bool innodb_mutex_show_status(THD* thd);
+void innodb_export_status(void);
-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_release_temporary_latches(THD *thd);
void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
int innobase_start_trx_and_assign_read_view(THD* thd);
+
+/***********************************************************************
+This function is used to prepare X/Open XA distributed transaction */
+
+int innobase_xa_prepare(
+/*====================*/
+ /* out: 0 or error number */
+ THD* thd, /* in: handle to the MySQL thread of the user
+ whose XA transaction should be prepared */
+ bool all); /* in: TRUE - commit transaction
+ FALSE - the current SQL statement ended */
+
+/***********************************************************************
+This function is used to recover X/Open XA distributed transactions */
+
+int innobase_xa_recover(
+/*====================*/
+ /* out: number of prepared transactions
+ stored in xid_list */
+ XID* xid_list, /* in/out: prepared transactions */
+ uint len); /* in: number of slots in xid_list */
+
+/***********************************************************************
+This function is used to commit one X/Open XA distributed transaction
+which is in the prepared state */
+
+int innobase_commit_by_xid(
+/*=======================*/
+ /* out: 0 or error number */
+ XID* xid); /* in : X/Open XA Transaction Identification */
+
+/***********************************************************************
+This function is used to rollback one X/Open XA distributed transaction
+which is in the prepared state */
+
+int innobase_rollback_by_xid(
+ /* out: 0 or error number */
+ XID *xid); /* in : X/Open XA Transaction Identification */
+
+
+int innobase_xa_end(THD *thd);
+
+
+int innobase_repl_report_sent_binlog(THD *thd, char *log_file_name,
+ my_off_t end_offset);
+
+/***********************************************************************
+Create a consistent view for a cursor based on current transaction
+which is created if the corresponding MySQL thread still lacks one.
+This consistent view is then used inside of MySQL when accessing records
+using a cursor. */
+
+void*
+innobase_create_cursor_view(void);
+/*=============================*/
+ /* out: Pointer to cursor view or NULL */
+
+/***********************************************************************
+Close the given consistent cursor view of a transaction and restore
+global read view to a transaction read view. Transaction is created if the
+corresponding MySQL thread still lacks one. */
+
+void
+innobase_close_cursor_view(
+/*=======================*/
+ void* curview); /* in: Consistent read view to be closed */
+
+/***********************************************************************
+Set the given consistent cursor view to a transaction which is created
+if the corresponding MySQL thread still lacks one. If the given
+consistent cursor view is NULL global read view of a transaction is
+restored to a transaction read view. */
+
+void
+innobase_set_cursor_view(
+/*=====================*/
+ void* curview); /* in: Consistent read view to be closed */
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc
deleted file mode 100644
index afa7dffa5f4..00000000000
--- a/sql/ha_isam.cc
+++ /dev/null
@@ -1,401 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifdef USE_PRAGMA_IMPLEMENTATION
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include "mysql_priv.h"
-#ifdef HAVE_ISAM
-#include <m_ctype.h>
-#include <myisampack.h>
-#include "ha_isam.h"
-#ifndef MASTER
-#include "../srclib/isam/isamdef.h"
-#else
-#include "../isam/isamdef.h"
-#endif
-
-/*****************************************************************************
-** isam tables
-*****************************************************************************/
-
-
-const char **ha_isam::bas_ext() const
-{ static const char *ext[]= { ".ISM",".ISD", NullS }; return ext; }
-
-int ha_isam::open(const char *name, int mode, uint test_if_locked)
-{
- char name_buff[FN_REFLEN];
- if (!(file=nisam_open(fn_format(name_buff,name,"","",2 | 4), mode,
- test_if_locked)))
- return (my_errno ? my_errno : -1);
-
- if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
- test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
- (void) nisam_extra(file,HA_EXTRA_NO_WAIT_LOCK);
- info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
- if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
- (void) nisam_extra(file,HA_EXTRA_WAIT_LOCK);
- if (!table->db_record_offset)
- int_table_flags|=HA_REC_NOT_IN_SEQ;
- return (0);
-}
-
-int ha_isam::close(void)
-{
- return !nisam_close(file) ? 0 : my_errno ? my_errno : -1;
-}
-
-uint ha_isam::min_record_length(uint options) const
-{
- return (options & HA_OPTION_PACK_RECORD) ? 1 : 5;
-}
-
-
-int ha_isam::write_row(byte * buf)
-{
- statistic_increment(ha_write_count,&LOCK_status);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
- if (table->next_number_field && buf == table->record[0])
- update_auto_increment();
- return !nisam_write(file,buf) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::update_row(const byte * old_data, byte * new_data)
-{
- statistic_increment(ha_update_count,&LOCK_status);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
- return !nisam_update(file,old_data,new_data) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::delete_row(const byte * buf)
-{
- statistic_increment(ha_delete_count,&LOCK_status);
- return !nisam_delete(file,buf) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- statistic_increment(ha_read_key_count,&LOCK_status);
- int error=nisam_rkey(file, buf, active_index, key, key_len, find_flag);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- statistic_increment(ha_read_key_count,&LOCK_status);
- int error=nisam_rkey(file, buf, index, key, key_len, find_flag);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::index_read_last(byte * buf, const byte * key, uint key_len)
-{
- statistic_increment(ha_read_key_count,&LOCK_status);
- int error=nisam_rkey(file, buf, active_index, key, key_len,
- HA_READ_PREFIX_LAST);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::index_next(byte * buf)
-{
- statistic_increment(ha_read_next_count,&LOCK_status);
- int error=nisam_rnext(file,buf,active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
-}
-
-int ha_isam::index_prev(byte * buf)
-{
- statistic_increment(ha_read_prev_count,&LOCK_status);
- int error=nisam_rprev(file,buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
-}
-
-int ha_isam::index_first(byte * buf)
-{
- statistic_increment(ha_read_first_count,&LOCK_status);
- int error=nisam_rfirst(file, buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
-}
-
-int ha_isam::index_last(byte * buf)
-{
- statistic_increment(ha_read_last_count,&LOCK_status);
- int error=nisam_rlast(file, buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
-}
-
-int ha_isam::rnd_init(bool scan)
-{
- return nisam_extra(file,HA_EXTRA_RESET) ? 0 : my_errno ? my_errno : -1;;
-}
-
-int ha_isam::rnd_next(byte *buf)
-{
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
- int error=nisam_rrnd(file, buf, NI_POS_ERROR);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::rnd_pos(byte * buf, byte *pos)
-{
- statistic_increment(ha_read_rnd_count,&LOCK_status);
- int error=nisam_rrnd(file, buf, (ulong) ha_get_ptr(pos,ref_length));
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-void ha_isam::position(const byte *record)
-{
- my_off_t position=nisam_position(file);
- if (position == (my_off_t) ~ (ulong) 0)
- position=HA_OFFSET_ERROR;
- ha_store_ptr(ref, ref_length, position);
-}
-
-void ha_isam::info(uint flag)
-{
- N_ISAMINFO info;
- (void) nisam_info(file,&info,flag);
- if (flag & HA_STATUS_VARIABLE)
- {
- records = info.records;
- deleted = info.deleted;
- data_file_length=info.data_file_length;
- index_file_length=info.index_file_length;
- delete_length = info.delete_length;
- check_time = info.isamchk_time;
- mean_rec_length=info.mean_reclength;
- }
- if (flag & HA_STATUS_CONST)
- {
- max_data_file_length=info.max_data_file_length;
- max_index_file_length=info.max_index_file_length;
- create_time = info.create_time;
- sortkey = info.sortkey;
- block_size=nisam_block_size;
- table->keys = min(table->keys,info.keys);
- table->keys_in_use.set_prefix(table->keys);
- table->db_options_in_use= info.options;
- table->db_record_offset=
- (table->db_options_in_use &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? 0 :
- table->reclength;
- if (!table->tmp_table)
- {
- ulong *rec_per_key=info.rec_per_key;
- for (uint i=0 ; i < table->keys ; i++)
- {
- table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]=
- *(rec_per_key++);
- }
- }
- ref_length=4;
- }
- if (flag & HA_STATUS_ERRKEY)
- {
- errkey = info.errkey;
- ha_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
- }
- if (flag & HA_STATUS_TIME)
- update_time = info.update_time;
-}
-
-
-int ha_isam::extra(enum ha_extra_function operation)
-{
- if ((specialflag & SPECIAL_SAFE_MODE || test_flags & TEST_NO_EXTRA) &&
- (operation == HA_EXTRA_WRITE_CACHE ||
- operation == HA_EXTRA_KEYREAD))
- return 0;
- return nisam_extra(file,operation);
-}
-
-int ha_isam::external_lock(THD *thd, int lock_type)
-{
- if (!table->tmp_table)
- return nisam_lock_database(file,lock_type);
- return 0;
-}
-
-
-THR_LOCK_DATA **ha_isam::store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
- file->lock.type=lock_type;
- *to++= &file->lock;
- return to;
-}
-
-
-int ha_isam::create(const char *name, register TABLE *form,
- HA_CREATE_INFO *create_info)
-
-{
- uint options=form->db_options_in_use;
- int error;
- uint i,j,recpos,minpos,fieldpos,temp_length,length;
- enum ha_base_keytype type;
- char buff[FN_REFLEN];
- KEY *pos;
- N_KEYDEF keydef[MAX_KEY];
- N_RECINFO *recinfo,*recinfo_pos;
- DBUG_ENTER("ha_isam::create");
-
- type=HA_KEYTYPE_BINARY; // Keep compiler happy
- if (!(recinfo= (N_RECINFO*) my_malloc((form->fields*2+2)*sizeof(N_RECINFO),
- MYF(MY_WME))))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
-
- pos=form->key_info;
- for (i=0; i < form->keys ; i++, pos++)
- {
- keydef[i].base.flag= (pos->flags & HA_NOSAME);
- for (j=0 ; (int7) j < pos->key_parts ; j++)
- {
- keydef[i].seg[j].base.flag=pos->key_part[j].key_part_flag;
- Field *field=pos->key_part[j].field;
- type=field->key_type();
-
- if ((options & HA_OPTION_PACK_KEYS ||
- (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
- HA_SPACE_PACK_USED))) &&
- pos->key_part[j].length > 8 &&
- (type == HA_KEYTYPE_TEXT ||
- type == HA_KEYTYPE_NUM ||
- (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
- {
- if (j == 0)
- keydef[i].base.flag|=HA_PACK_KEY;
- if (!(field->flags & ZEROFILL_FLAG) &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING ||
- ((int) (pos->key_part[j].length - field->decimals()))
- >= 4))
- keydef[i].seg[j].base.flag|=HA_SPACE_PACK;
- }
- keydef[i].seg[j].base.type=(int) type;
- keydef[i].seg[j].base.start= pos->key_part[j].offset;
- keydef[i].seg[j].base.length= pos->key_part[j].length;
- }
- keydef[i].seg[j].base.type=(int) HA_KEYTYPE_END; /* End of key-parts */
- }
-
- recpos=0; recinfo_pos=recinfo;
- while (recpos < (uint) form->reclength)
- {
- Field **field,*found=0;
- minpos=form->reclength; length=0;
-
- for (field=form->field ; *field ; field++)
- {
- if ((fieldpos=(*field)->offset()) >= recpos &&
- fieldpos <= minpos)
- {
- /* skip null fields */
- if (!(temp_length= (*field)->pack_length()))
- continue; /* Skip null-fields */
- if (! found || fieldpos < minpos ||
- (fieldpos == minpos && temp_length < length))
- {
- minpos=fieldpos; found= *field; length=temp_length;
- }
- }
- }
- DBUG_PRINT("loop",("found: %lx recpos: %d minpos: %d length: %d",
- found,recpos,minpos,length));
- if (recpos != minpos)
- { // Reserved space (Null bits?)
- recinfo_pos->base.type=(int) FIELD_NORMAL;
- recinfo_pos++->base.length= (uint16) (minpos-recpos);
- }
- if (! found)
- break;
-
- if (found->flags & BLOB_FLAG)
- {
- /* ISAM can only handle blob pointers of sizeof(char(*)) */
- recinfo_pos->base.type= (int) FIELD_BLOB;
- if (options & HA_OPTION_LONG_BLOB_PTR)
- length= length-portable_sizeof_char_ptr+sizeof(char*);
- }
- else if (!(options & HA_OPTION_PACK_RECORD))
- recinfo_pos->base.type= (int) FIELD_NORMAL;
- else if (found->zero_pack())
- recinfo_pos->base.type= (int) FIELD_SKIP_ZERO;
- else
- recinfo_pos->base.type= (int) ((length <= 3 ||
- (found->flags & ZEROFILL_FLAG)) ?
- FIELD_NORMAL :
- found->type() == FIELD_TYPE_STRING ||
- found->type() == FIELD_TYPE_VAR_STRING ?
- FIELD_SKIP_ENDSPACE :
- FIELD_SKIP_PRESPACE);
- recinfo_pos++ ->base.length=(uint16) length;
- recpos=minpos+length;
- DBUG_PRINT("loop",("length: %d type: %d",
- recinfo_pos[-1].base.length,recinfo_pos[-1].base.type));
-
- if ((found->flags & BLOB_FLAG) && (options & HA_OPTION_LONG_BLOB_PTR) &&
- sizeof(char*) != portable_sizeof_char_ptr)
- { // Not used space
- recinfo_pos->base.type=(int) FIELD_ZERO;
- recinfo_pos++->base.length=
- (uint16) (portable_sizeof_char_ptr-sizeof(char*));
- recpos+= (portable_sizeof_char_ptr-sizeof(char*));
- }
- }
- recinfo_pos->base.type= (int) FIELD_LAST; /* End of fieldinfo */
- error=nisam_create(fn_format(buff,name,"","",2+4+16),form->keys,keydef,
- recinfo,(ulong) form->max_rows, (ulong) form->min_rows,
- 0, 0, 0L);
- my_free((gptr) recinfo,MYF(0));
- DBUG_RETURN(error);
-
-}
-
-static key_range no_range= { (byte*) 0, 0, HA_READ_KEY_EXACT };
-
-ha_rows ha_isam::records_in_range(uint inx, key_range *min_key,
- key_range *max_key)
-{
- /* ISAM checks if 'key' pointer <> 0 to know if there is no range */
- if (!min_key)
- min_key= &no_range;
- if (!max_key)
- max_key= &no_range;
- return (ha_rows) nisam_records_in_range(file,
- (int) inx,
- min_key->key, min_key->length,
- min_key->flag,
- max_key->key, max_key->length,
- max_key->flag);
-}
-#endif /* HAVE_ISAM */
diff --git a/sql/ha_isam.h b/sql/ha_isam.h
deleted file mode 100644
index 1f9b8eb28fe..00000000000
--- a/sql/ha_isam.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#ifdef USE_PRAGMA_INTERFACE
-#pragma interface /* gcc class implementation */
-#endif
-
-/* class for the the myisam handler */
-
-#include <nisam.h>
-
-class ha_isam: public handler
-{
- N_INFO *file;
- /* We need this as table_flags() may change after open() */
- ulong int_table_flags;
-
- public:
- ha_isam(TABLE *table)
- :handler(table), file(0),
- 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, bool all_parts) 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_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; }
-
- 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_read_last(byte * buf, const byte * key, uint key_len);
- 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);
- int rnd_next(byte *buf);
- int rnd_pos(byte * buf, byte *pos);
- void position(const byte *record);
- void info(uint);
- int extra(enum ha_extra_function operation);
- int external_lock(THD *thd, int lock_type);
- ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
-
- 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/ha_isammrg.cc b/sql/ha_isammrg.cc
deleted file mode 100644
index c0e6f665f08..00000000000
--- a/sql/ha_isammrg.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#ifdef USE_PRAGMA_IMPLEMENTATION
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include "mysql_priv.h"
-#ifdef HAVE_ISAM
-#include <m_ctype.h>
-#ifndef MASTER
-#include "../srclib/merge/mrg_def.h"
-#else
-#include "../merge/mrg_def.h"
-#endif
-#include "ha_isammrg.h"
-
-/*****************************************************************************
-** ISAM MERGE tables
-*****************************************************************************/
-
-const char **ha_isammrg::bas_ext() const
-{ static const char *ext[]= { ".MRG", NullS }; return ext; }
-
-int ha_isammrg::open(const char *name, int mode, uint test_if_locked)
-{
- char name_buff[FN_REFLEN];
- if (!(file=mrg_open(fn_format(name_buff,name,"","",2 | 4), mode,
- test_if_locked)))
- return (my_errno ? my_errno : -1);
-
- if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
- test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
- mrg_extra(file,HA_EXTRA_NO_WAIT_LOCK);
- info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
- if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
- mrg_extra(file,HA_EXTRA_WAIT_LOCK);
- if (table->reclength != mean_rec_length)
- {
- DBUG_PRINT("error",("reclength: %d mean_rec_length: %d",
- table->reclength, mean_rec_length));
- mrg_close(file);
- file=0;
- return ER_WRONG_MRG_TABLE;
- }
- return (0);
-}
-
-int ha_isammrg::close(void)
-{
- return !mrg_close(file) ? 0 : my_errno ? my_errno : -1;
-}
-
-uint ha_isammrg::min_record_length(uint options) const
-{
- return (options & HA_OPTION_PACK_RECORD) ? 1 : 5;
-}
-
-int ha_isammrg::write_row(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::update_row(const byte * old_data, byte * new_data)
-{
- statistic_increment(ha_update_count,&LOCK_status);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
- return !mrg_update(file,old_data,new_data) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::delete_row(const byte * buf)
-{
- statistic_increment(ha_delete_count,&LOCK_status);
- return !mrg_delete(file,buf) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_next(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_prev(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_first(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_last(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::rnd_init(bool scan)
-{
- return !mrg_extra(file,HA_EXTRA_RESET) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::rnd_next(byte *buf)
-{
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
- int error=mrg_rrnd(file, buf, ~(mrg_off_t) 0);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::rnd_pos(byte * buf, byte *pos)
-{
- statistic_increment(ha_read_rnd_count,&LOCK_status);
- int error=mrg_rrnd(file, buf, (ulong) ha_get_ptr(pos,ref_length));
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-void ha_isammrg::position(const byte *record)
-{
- ulong position= mrg_position(file);
- ha_store_ptr(ref, ref_length, (my_off_t) position);
-}
-
-
-void ha_isammrg::info(uint flag)
-{
- MERGE_INFO info;
- (void) mrg_info(file,&info,flag);
- records = (ha_rows) info.records;
- deleted = (ha_rows) info.deleted;
- data_file_length=info.data_file_length;
- errkey = info.errkey;
- table->keys_in_use.clear_all(); // No keys yet
- table->db_options_in_use = info.options;
- mean_rec_length=info.reclength;
- block_size=0;
- update_time=0;
- ref_length=4; // Should be big enough
-}
-
-
-int ha_isammrg::extra(enum ha_extra_function operation)
-{
- return !mrg_extra(file,operation) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::external_lock(THD *thd, int lock_type)
-{
- return !mrg_lock_database(file,lock_type) ? 0 : my_errno ? my_errno : -1;
-}
-
-uint ha_isammrg::lock_count(void) const
-{
- return file->tables;
-}
-
-THR_LOCK_DATA **ha_isammrg::store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- MRG_TABLE *open_table;
-
- for (open_table=file->open_tables ;
- open_table != file->end_table ;
- open_table++)
- {
- *(to++)= &open_table->table->lock;
- if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
- open_table->table->lock.type=lock_type;
- }
- return to;
-}
-
-
-int ha_isammrg::create(const char *name, register TABLE *form,
- HA_CREATE_INFO *create_info)
-
-{
- char buff[FN_REFLEN];
- return mrg_create(fn_format(buff,name,"","",2+4+16),0);
-}
-#endif /* HAVE_ISAM */
diff --git a/sql/ha_isammrg.h b/sql/ha_isammrg.h
deleted file mode 100644
index 82a2e312ca3..00000000000
--- a/sql/ha_isammrg.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#ifdef USE_PRAGMA_INTERFACE
-#pragma interface /* gcc class implementation */
-#endif
-
-/* class for the the myisam merge handler */
-
-#include <merge.h>
-
-class ha_isammrg: public handler
-{
- MRG_INFO *file;
-
- public:
- ha_isammrg(TABLE *table): handler(table), file(0) {}
- ~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_REC_NOT_IN_SEQ | HA_FILE_BASED); }
- ulong index_flags(uint idx, uint part, bool all_parts) const
- { DBUG_ASSERT(0); return 0; }
-
- uint max_supported_keys() const { return 0; }
- bool low_byte_first() const { return 0; }
- uint min_record_length(uint options) const;
-
- 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 indx, 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);
- int rnd_next(byte *buf);
- int rnd_pos(byte * buf, byte *pos);
- void position(const byte *record);
- void info(uint);
- int extra(enum ha_extra_function operation);
- int external_lock(THD *thd, int lock_type);
- uint lock_count(void) const;
- 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);
- uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
-};
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 615cecb7a19..b680c739958 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -50,6 +50,32 @@ TYPELIB myisam_stats_method_typelib= {
** MyISAM tables
*****************************************************************************/
+/* MyISAM handlerton */
+
+static handlerton myisam_hton= {
+ "MyISAM",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ /*
+ MyISAM doesn't support transactions and doesn't have
+ transaction-dependent context: cursors can survive a commit.
+ */
+ HTON_NO_FLAGS
+};
+
// collect errors printed by mi_check routines
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
@@ -93,9 +119,10 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
extern "C" {
-volatile my_bool *killed_ptr(MI_CHECK *param)
+volatile int *killed_ptr(MI_CHECK *param)
{
- return &(((THD *)(param->thd))->killed);
+ /* In theory Unsafe conversion, but should be ok for now */
+ return (int*) &(((THD *)(param->thd))->killed);
}
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
@@ -128,8 +155,27 @@ void mi_check_print_warning(MI_CHECK *param, const char *fmt,...)
}
+
+ha_myisam::ha_myisam(TABLE *table_arg)
+ :handler(&myisam_hton, table_arg), file(0),
+ 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 | HA_CAN_BIT_FIELD),
+ can_enable_indexes(1)
+{}
+
+
+static const char *ha_myisam_exts[] = {
+ ".MYI",
+ ".MYD",
+ NullS
+};
+
const char **ha_myisam::bas_ext() const
-{ static const char *ext[]= { ".MYI",".MYD", NullS }; return ext; }
+{
+ return ha_myisam_exts;
+}
const char *ha_myisam::index_type(uint key_number)
@@ -238,7 +284,7 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
- if (!table->db_record_offset)
+ if (!table->s->db_record_offset)
int_table_flags|=HA_REC_NOT_IN_SEQ;
if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
int_table_flags|=HA_HAS_CHECKSUM;
@@ -254,7 +300,7 @@ int ha_myisam::close(void)
int ha_myisam::write_row(byte * buf)
{
- statistic_increment(ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
/* If we have a timestamp column, update it to the current time */
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
@@ -280,9 +326,9 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
thd->proc_info="Checking table";
myisamchk_init(&param);
param.thd = thd;
- param.op_name = (char*)"check";
- param.db_name = table->table_cache_key;
- param.table_name = table->table_name;
+ param.op_name = "check";
+ param.db_name= table->s->db;
+ param.table_name= table->alias;
param.testflag = check_opt->flags | T_CHECK | T_SILENT;
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
@@ -368,11 +414,11 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
myisamchk_init(&param);
param.thd = thd;
- param.op_name = (char*) "analyze";
- param.db_name = table->table_cache_key;
- param.table_name = table->table_name;
- param.testflag=(T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
- T_DONT_CHECK_CHECKSUM);
+ param.op_name= "analyze";
+ param.db_name= table->s->db;
+ param.table_name= table->alias;
+ param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
+ T_DONT_CHECK_CHECKSUM);
param.using_global_keycache = 1;
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
@@ -395,9 +441,9 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
{
HA_CHECK_OPT tmp_check_opt;
- char* backup_dir= thd->lex->backup_dir;
+ char *backup_dir= thd->lex->backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
- char* table_name = table->real_name;
+ const char *table_name= table->s->table_name;
int error;
const char* errmsg;
DBUG_ENTER("restore");
@@ -406,11 +452,11 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
MI_NAME_DEXT))
DBUG_RETURN(HA_ADMIN_INVALID);
- if (my_copy(src_path, fn_format(dst_path, table->path, "",
+ if (my_copy(src_path, fn_format(dst_path, table->s->path, "",
MI_NAME_DEXT, 4), MYF(MY_WME)))
{
- error = HA_ADMIN_FAILED;
- errmsg = "Failed in my_copy (Error %d)";
+ error= HA_ADMIN_FAILED;
+ errmsg= "Failed in my_copy (Error %d)";
goto err;
}
@@ -422,11 +468,11 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
{
MI_CHECK param;
myisamchk_init(&param);
- param.thd = thd;
- param.op_name = (char*)"restore";
- param.db_name = table->table_cache_key;
- param.table_name = table->table_name;
- param.testflag = 0;
+ param.thd= thd;
+ param.op_name= "restore";
+ param.db_name= table->s->db;
+ param.table_name= table->s->table_name;
+ param.testflag= 0;
mi_check_print_error(&param, errmsg, my_errno);
DBUG_RETURN(error);
}
@@ -435,9 +481,9 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
{
- char* backup_dir= thd->lex->backup_dir;
+ char *backup_dir= thd->lex->backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
- char* table_name = table->real_name;
+ const char *table_name= table->s->table_name;
int error;
const char *errmsg;
DBUG_ENTER("ha_myisam::backup");
@@ -445,12 +491,13 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir,
reg_ext))
{
- errmsg = "Failed in fn_format() for .frm file (errno: %d)";
- error = HA_ADMIN_INVALID;
+ errmsg= "Failed in fn_format() for .frm file (errno: %d)";
+ error= HA_ADMIN_INVALID;
goto err;
}
- if (my_copy(fn_format(src_path, table->path,"", reg_ext, MY_UNPACK_FILENAME),
+ if (my_copy(fn_format(src_path, table->s->path, "", reg_ext,
+ MY_UNPACK_FILENAME),
dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE)))
{
@@ -468,7 +515,7 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
goto err;
}
- if (my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT,
+ if (my_copy(fn_format(src_path, table->s->path, "", MI_NAME_DEXT,
MY_UNPACK_FILENAME),
dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE)))
@@ -483,11 +530,11 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
{
MI_CHECK param;
myisamchk_init(&param);
- param.thd = thd;
- param.op_name = (char*)"backup";
- param.db_name = table->table_cache_key;
- param.table_name = table->table_name;
- param.testflag = 0;
+ param.thd= thd;
+ param.op_name= "backup";
+ param.db_name= table->s->db;
+ param.table_name= table->s->table_name;
+ param.testflag = 0;
mi_check_print_error(&param,errmsg, my_errno);
DBUG_RETURN(error);
}
@@ -504,10 +551,10 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
myisamchk_init(&param);
param.thd = thd;
- param.op_name = (char*) "repair";
- param.testflag = ((check_opt->flags & ~(T_EXTEND)) |
- T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
- (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
+ param.op_name= "repair";
+ param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
+ T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
+ (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
param.sort_buffer_length= check_opt->sort_buffer_size;
start_records=file->state->records;
while ((error=repair(thd,param,0)) && param.retry_repair)
@@ -518,7 +565,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
{
param.testflag&= ~T_RETRY_WITHOUT_QUICK;
sql_print_information("Retrying repair of: '%s' without quick",
- table->path);
+ table->s->path);
continue;
}
param.testflag&= ~T_QUICK;
@@ -526,7 +573,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
{
param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
sql_print_information("Retrying repair of: '%s' with keycache",
- table->path);
+ table->s->path);
continue;
}
break;
@@ -538,7 +585,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
sql_print_information("Found %s of %s rows when repairing '%s'",
llstr(file->state->records, llbuff),
llstr(start_records, llbuff2),
- table->path);
+ table->s->path);
}
return error;
}
@@ -551,9 +598,9 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
myisamchk_init(&param);
param.thd = thd;
- param.op_name = (char*) "optimize";
- param.testflag = (check_opt->flags | T_SILENT | T_FORCE_CREATE |
- T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
+ param.op_name= "optimize";
+ param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
+ T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
param.sort_buffer_length= check_opt->sort_buffer_size;
if ((error= repair(thd,param,1)) && param.retry_repair)
{
@@ -577,18 +624,18 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
ha_rows rows= file->state->records;
DBUG_ENTER("ha_myisam::repair");
- param.db_name = table->table_cache_key;
- param.table_name = table->table_name;
+ param.db_name= table->s->db;
+ param.table_name= table->alias;
param.tmpfile_createflag = O_RDWR | O_TRUNC;
param.using_global_keycache = 1;
- param.thd=thd;
- param.tmpdir=&mysql_tmpdir_list;
- param.out_flag=0;
+ param.thd= thd;
+ param.tmpdir= &mysql_tmpdir_list;
+ param.out_flag= 0;
strmov(fixed_name,file->filename);
// Don't lock tables if we have used LOCK TABLE
if (!thd->locked_tables &&
- mi_lock_database(file, table->tmp_table ? F_EXTRA_LCK : F_WRLCK))
+ mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
{
mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
DBUG_RETURN(HA_ADMIN_FAILED);
@@ -600,7 +647,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))))
{
ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
- ((ulonglong) 1L << share->base.keys)-1 :
+ mi_get_mask_all_keys_active(share->base.keys) :
share->state.key_map);
uint testflag=param.testflag;
if (mi_test_if_sort_rep(file,file->state->records,key_map,0) &&
@@ -609,7 +656,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
local_testflag|= T_STATISTICS;
param.testflag|= T_STATISTICS; // We get this for free
statistics_done=1;
- if (current_thd->variables.myisam_repair_threads>1)
+ if (thd->variables.myisam_repair_threads>1)
{
char buf[40];
/* TODO: respect myisam_repair_threads variable */
@@ -733,7 +780,7 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
{
- char buf[80];
+ char buf[STRING_BUFFER_USUAL_SIZE];
my_snprintf(buf, sizeof(buf),
"Failed to flush to index file (errno: %d)", error);
errmsg= buf;
@@ -747,9 +794,9 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
MI_CHECK param;
myisamchk_init(&param);
param.thd= thd;
- param.op_name= (char*)"assign_to_keycache";
- param.db_name= table->table_cache_key;
- param.table_name= table->table_name;
+ param.op_name= "assign_to_keycache";
+ param.db_name= table->s->db;
+ param.table_name= table->s->table_name;
param.testflag= 0;
mi_check_print_error(&param, errmsg);
}
@@ -815,10 +862,10 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
MI_CHECK param;
myisamchk_init(&param);
param.thd= thd;
- param.op_name= (char*)"preload_keys";
- param.db_name= table->table_cache_key;
- param.table_name= table->table_name;
- param.testflag= 0;
+ param.op_name= "preload_keys";
+ param.db_name= table->s->db;
+ param.table_name= table->s->table_name;
+ param.testflag= 0;
mi_check_print_error(&param, errmsg);
DBUG_RETURN(error);
}
@@ -901,7 +948,7 @@ int ha_myisam::enable_indexes(uint mode)
{
int error;
- if (file->s->state.key_map == set_bits(ulonglong, file->s->base.keys))
+ if (mi_is_all_keys_active(file->s->state.key_map, file->s->base.keys))
{
/* All indexes are enabled already. */
return 0;
@@ -923,9 +970,9 @@ int ha_myisam::enable_indexes(uint mode)
const char *save_proc_info=thd->proc_info;
thd->proc_info="Creating index";
myisamchk_init(&param);
- param.op_name = (char*) "recreating_index";
- param.testflag = (T_SILENT | T_REP_BY_SORT | T_QUICK |
- T_CREATE_MISSING_KEYS);
+ param.op_name= "recreating_index";
+ param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
+ T_CREATE_MISSING_KEYS);
param.myf_rw&= ~MY_WAIT_IF_FULL;
param.sort_buffer_length= thd->variables.myisam_sort_buff_size;
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
@@ -934,8 +981,11 @@ int ha_myisam::enable_indexes(uint mode)
{
sql_print_warning("Warning: Enabling keys got errno %d, retrying",
my_errno);
+ thd->clear_error();
param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
error= (repair(thd,param,0) != HA_ADMIN_OK);
+ if (!error && thd->net.report_error)
+ error= HA_ERR_CRASHED;
}
info(HA_STATUS_CONST);
thd->proc_info=save_proc_info;
@@ -988,8 +1038,9 @@ int ha_myisam::indexes_are_disabled(void)
void ha_myisam::start_bulk_insert(ha_rows rows)
{
DBUG_ENTER("ha_myisam::start_bulk_insert");
- THD *thd=current_thd;
- ulong size= min(thd->variables.read_buff_size, table->avg_row_length*rows);
+ THD *thd= current_thd;
+ ulong size= min(thd->variables.read_buff_size,
+ table->s->avg_row_length*rows);
DBUG_PRINT("info",("start_bulk_insert: rows %lu size %lu",
(ulong) rows, size));
@@ -997,8 +1048,8 @@ void ha_myisam::start_bulk_insert(ha_rows rows)
if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
mi_extra(file, HA_EXTRA_WRITE_CACHE, (void*) &size);
- can_enable_indexes= (file->s->state.key_map ==
- set_bits(ulonglong, file->s->base.keys));
+ can_enable_indexes= mi_is_all_keys_active(file->s->state.key_map,
+ file->s->base.keys);
if (!(specialflag & SPECIAL_SAFE_MODE))
{
@@ -1057,18 +1108,18 @@ bool ha_myisam::check_and_repair(THD *thd)
// Don't use quick if deleted rows
if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
check_opt.flags|=T_QUICK;
- sql_print_warning("Checking table: '%s'",table->path);
+ sql_print_warning("Checking table: '%s'",table->s->path);
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);
+ thd->query= (char*) table->s->table_name;
+ thd->query_length= (uint32) strlen(table->s->table_name);
pthread_mutex_unlock(&LOCK_thread_count);
if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
{
- sql_print_warning("Recovering table: '%s'",table->path);
+ sql_print_warning("Recovering table: '%s'",table->s->path);
check_opt.flags=
((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
(marked_crashed ? 0 : T_QUICK) |
@@ -1092,7 +1143,7 @@ bool ha_myisam::is_crashed() const
int ha_myisam::update_row(const byte * old_data, byte * new_data)
{
- statistic_increment(ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return mi_update(file,old_data,new_data);
@@ -1100,7 +1151,7 @@ int ha_myisam::update_row(const byte * old_data, byte * new_data)
int ha_myisam::delete_row(const byte * buf)
{
- statistic_increment(ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
return mi_delete(file,buf);
}
@@ -1108,7 +1159,8 @@ 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);
+ statistic_increment(table->in_use->status_var.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;
return error;
@@ -1117,7 +1169,8 @@ int ha_myisam::index_read(byte * buf, const byte * key,
int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=mi_rkey(file,buf,index, key, key_len, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1126,7 +1179,8 @@ 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);
+ statistic_increment(table->in_use->status_var.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;
return error;
@@ -1135,7 +1189,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=mi_rnext(file,buf,active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1144,7 +1199,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_prev_count,
+ &LOCK_status);
int error=mi_rprev(file,buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1153,7 +1209,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_first_count,
+ &LOCK_status);
int error=mi_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1162,7 +1219,8 @@ 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);
+ statistic_increment(table->in_use->status_var.ha_read_last_count,
+ &LOCK_status);
int error=mi_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1173,7 +1231,8 @@ int ha_myisam::index_next_same(byte * buf,
uint length __attribute__((unused)))
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=mi_rnext_same(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1189,7 +1248,8 @@ int ha_myisam::rnd_init(bool scan)
int ha_myisam::rnd_next(byte *buf)
{
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
int error=mi_scan(file, buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1202,8 +1262,9 @@ int ha_myisam::restart_rnd_next(byte *buf, byte *pos)
int ha_myisam::rnd_pos(byte * buf, byte *pos)
{
- statistic_increment(ha_read_rnd_count,&LOCK_status);
- int error=mi_rrnd(file, buf, ha_get_ptr(pos,ref_length));
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
+ int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -1211,7 +1272,7 @@ int ha_myisam::rnd_pos(byte * buf, byte *pos)
void ha_myisam::position(const byte* record)
{
my_off_t position=mi_position(file);
- ha_store_ptr(ref, ref_length, position);
+ my_store_ptr(ref, ref_length, position);
}
void ha_myisam::info(uint flag)
@@ -1232,25 +1293,25 @@ void ha_myisam::info(uint flag)
}
if (flag & HA_STATUS_CONST)
{
- max_data_file_length=info.max_data_file_length;
- max_index_file_length=info.max_index_file_length;
- create_time = info.create_time;
- sortkey = info.sortkey;
- ref_length=info.reflength;
- table->db_options_in_use = info.options;
- block_size=myisam_block_size;
- table->keys_in_use.set_prefix(table->keys);
- table->keys_in_use.intersect(info.key_map);
- table->keys_for_keyread= table->keys_in_use;
- table->keys_for_keyread.subtract(table->read_only_keys);
- table->db_record_offset=info.record_offset;
- if (table->key_parts)
+ TABLE_SHARE *share= table->s;
+ max_data_file_length= info.max_data_file_length;
+ max_index_file_length= info.max_index_file_length;
+ create_time= info.create_time;
+ sortkey= info.sortkey;
+ ref_length= info.reflength;
+ share->db_options_in_use= info.options;
+ block_size= myisam_block_size;
+ share->keys_in_use.set_prefix(share->keys);
+ share->keys_in_use.intersect_extended(info.key_map);
+ share->keys_for_keyread.intersect(share->keys_in_use);
+ share->db_record_offset= info.record_offset;
+ if (share->key_parts)
memcpy((char*) table->key_info[0].rec_per_key,
(char*) info.rec_per_key,
- sizeof(table->key_info[0].rec_per_key)*table->key_parts);
- raid_type=info.raid_type;
- raid_chunks=info.raid_chunks;
- raid_chunksize=info.raid_chunksize;
+ sizeof(table->key_info[0].rec_per_key)*share->key_parts);
+ raid_type= info.raid_type;
+ raid_chunks= info.raid_chunks;
+ raid_chunksize= info.raid_chunksize;
/*
Set data_file_name and index_file_name to point at the symlink value
@@ -1267,7 +1328,7 @@ void ha_myisam::info(uint flag)
if (flag & HA_STATUS_ERRKEY)
{
errkey = info.errkey;
- ha_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
+ my_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
}
if (flag & HA_STATUS_TIME)
update_time = info.update_time;
@@ -1306,7 +1367,7 @@ int ha_myisam::delete_table(const char *name)
int ha_myisam::external_lock(THD *thd, int lock_type)
{
- return mi_lock_database(file, !table->tmp_table ?
+ return mi_lock_database(file, !table->s->tmp_table ?
lock_type : ((lock_type == F_UNLCK) ?
F_UNLCK : F_EXTRA_LCK));
}
@@ -1351,21 +1412,23 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
MI_KEYDEF *keydef;
MI_COLUMNDEF *recinfo,*recinfo_pos;
HA_KEYSEG *keyseg;
- uint options=table_arg->db_options_in_use;
+ TABLE_SHARE *share= table->s;
+ uint options= share->db_options_in_use;
DBUG_ENTER("ha_myisam::create");
type=HA_KEYTYPE_BINARY; // Keep compiler happy
if (!(my_multi_malloc(MYF(MY_WME),
- &recinfo,(table_arg->fields*2+2)*sizeof(MI_COLUMNDEF),
- &keydef, table_arg->keys*sizeof(MI_KEYDEF),
+ &recinfo,(share->fields*2+2)*
+ sizeof(MI_COLUMNDEF),
+ &keydef, share->keys*sizeof(MI_KEYDEF),
&keyseg,
- ((table_arg->key_parts + table_arg->keys) *
+ ((share->key_parts + share->keys) *
sizeof(HA_KEYSEG)),
NullS)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
pos=table_arg->key_info;
- for (i=0; i < table_arg->keys ; i++, pos++)
+ for (i=0; i < share->keys ; i++, pos++)
{
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
@@ -1375,9 +1438,9 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].keysegs=pos->key_parts;
for (j=0 ; j < pos->key_parts ; j++)
{
- keydef[i].seg[j].flag=pos->key_part[j].key_part_flag;
Field *field=pos->key_part[j].field;
type=field->key_type();
+ keydef[i].seg[j].flag=pos->key_part[j].key_part_flag;
if (options & HA_OPTION_PACK_KEYS ||
(pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
@@ -1392,8 +1455,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
if (j == 0)
keydef[i].flag|=HA_PACK_KEY;
if (!(field->flags & ZEROFILL_FLAG) &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING ||
+ (field->type() == MYSQL_TYPE_STRING ||
+ field->type() == MYSQL_TYPE_VAR_STRING ||
((int) (pos->key_part[j].length - field->decimals()))
>= 4))
keydef[i].seg[j].flag|=HA_SPACE_PACK;
@@ -1404,8 +1467,10 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].seg[j].type= (int) type;
keydef[i].seg[j].start= pos->key_part[j].offset;
keydef[i].seg[j].length= pos->key_part[j].length;
- keydef[i].seg[j].bit_start=keydef[i].seg[j].bit_end=0;
- keydef[i].seg[j].language = field->charset()->number;
+ keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end=
+ keydef[i].seg[j].bit_length= 0;
+ keydef[i].seg[j].bit_pos= 0;
+ keydef[i].seg[j].language= field->charset()->number;
if (field->null_ptr)
{
@@ -1424,7 +1489,14 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].seg[j].flag|=HA_BLOB_PART;
/* save number of bytes used to pack length */
keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
- table_arg->blob_ptr_size);
+ share->blob_ptr_size);
+ }
+ else if (field->type() == FIELD_TYPE_BIT)
+ {
+ keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
+ keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
+ keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
+ (uchar*) table_arg->record[0]);
}
}
keyseg+=pos->key_parts;
@@ -1432,15 +1504,16 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
if (table_arg->found_next_number_field)
{
- keydef[table_arg->next_number_index].flag|= HA_AUTO_KEY;
- found_real_auto_increment= table_arg->next_number_key_offset == 0;
+ keydef[share->next_number_index].flag|= HA_AUTO_KEY;
+ found_real_auto_increment= share->next_number_key_offset == 0;
}
recpos=0; recinfo_pos=recinfo;
- while (recpos < (uint) table_arg->reclength)
+ while (recpos < (uint) share->reclength)
{
Field **field,*found=0;
- minpos=table_arg->reclength; length=0;
+ minpos= share->reclength;
+ length=0;
for (field=table_arg->field ; *field ; field++)
{
@@ -1448,7 +1521,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
fieldpos <= minpos)
{
/* skip null fields */
- if (!(temp_length= (*field)->pack_length()))
+ if (!(temp_length= (*field)->pack_length_in_rec()))
continue; /* Skip null-fields */
if (! found || fieldpos < minpos ||
(fieldpos == minpos && temp_length < length))
@@ -1457,7 +1530,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
}
}
}
- DBUG_PRINT("loop",("found: %lx recpos: %d minpos: %d length: %d",
+ DBUG_PRINT("loop",("found: 0x%lx recpos: %d minpos: %d length: %d",
found,recpos,minpos,length));
if (recpos != minpos)
{ // Reserved space (Null bits?)
@@ -1469,33 +1542,33 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
break;
if (found->flags & BLOB_FLAG)
- {
recinfo_pos->type= (int) FIELD_BLOB;
- }
+ else if (found->type() == MYSQL_TYPE_VARCHAR)
+ recinfo_pos->type= FIELD_VARCHAR;
else if (!(options & HA_OPTION_PACK_RECORD))
recinfo_pos->type= (int) FIELD_NORMAL;
else if (found->zero_pack())
recinfo_pos->type= (int) FIELD_SKIP_ZERO;
else
recinfo_pos->type= (int) ((length <= 3 ||
- (found->flags & ZEROFILL_FLAG)) ?
- FIELD_NORMAL :
- found->type() == FIELD_TYPE_STRING ||
- found->type() == FIELD_TYPE_VAR_STRING ?
- FIELD_SKIP_ENDSPACE :
- FIELD_SKIP_PRESPACE);
+ (found->flags & ZEROFILL_FLAG)) ?
+ FIELD_NORMAL :
+ found->type() == MYSQL_TYPE_STRING ||
+ found->type() == MYSQL_TYPE_VAR_STRING ?
+ FIELD_SKIP_ENDSPACE :
+ FIELD_SKIP_PRESPACE);
if (found->null_ptr)
{
recinfo_pos->null_bit=found->null_bit;
recinfo_pos->null_pos= (uint) (found->null_ptr-
- (uchar*) table_arg->record[0]);
+ (uchar*) table_arg->record[0]);
}
else
{
recinfo_pos->null_bit=0;
recinfo_pos->null_pos=0;
}
- (recinfo_pos++) ->length=(uint16) length;
+ (recinfo_pos++)->length= (uint16) length;
recpos=minpos+length;
DBUG_PRINT("loop",("length: %d type: %d",
recinfo_pos[-1].length,recinfo_pos[-1].type));
@@ -1503,21 +1576,21 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
}
MI_CREATE_INFO create_info;
bzero((char*) &create_info,sizeof(create_info));
- create_info.max_rows=table_arg->max_rows;
- create_info.reloc_rows=table_arg->min_rows;
+ create_info.max_rows= share->max_rows;
+ create_info.reloc_rows= share->min_rows;
create_info.with_auto_increment=found_real_auto_increment;
create_info.auto_increment=(info->auto_increment_value ?
info->auto_increment_value -1 :
(ulonglong) 0);
- create_info.data_file_length= ((ulonglong) table_arg->max_rows *
- table_arg->avg_row_length);
+ create_info.data_file_length= ((ulonglong) share->max_rows *
+ share->avg_row_length);
create_info.raid_type=info->raid_type;
create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks :
RAID_DEFAULT_CHUNKS);
- create_info.raid_chunksize=(info->raid_chunksize ? info->raid_chunksize :
- RAID_DEFAULT_CHUNKSIZE);
- create_info.data_file_name= info->data_file_name;
- create_info.index_file_name=info->index_file_name;
+ create_info.raid_chunksize= (info->raid_chunksize ? info->raid_chunksize :
+ RAID_DEFAULT_CHUNKSIZE);
+ create_info.data_file_name= info->data_file_name;
+ create_info.index_file_name= info->index_file_name;
if (info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= HA_CREATE_TMP_TABLE;
@@ -1530,7 +1603,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
/* TODO: Check that the following fn_format is really needed */
error=mi_create(fn_format(buff,name,"","",2+4),
- table_arg->keys,keydef,
+ share->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo,
0, (MI_UNIQUEDEF*) 0,
&create_info, create_flags);
@@ -1546,30 +1619,35 @@ int ha_myisam::rename_table(const char * from, const char * to)
}
-longlong ha_myisam::get_auto_increment()
+ulonglong ha_myisam::get_auto_increment()
{
- if (!table->next_number_key_offset)
+ ulonglong nr;
+ int error;
+ byte key[MI_MAX_KEY_LENGTH];
+
+ if (!table->s->next_number_key_offset)
{ // Autoincrement at key-start
ha_myisam::info(HA_STATUS_AUTO);
return auto_increment_value;
}
/* it's safe to call the following if bulk_insert isn't on */
- mi_flush_bulk_insert(file, table->next_number_index);
+ mi_flush_bulk_insert(file, table->s->next_number_index);
- longlong nr;
- int error;
- byte key[MI_MAX_KEY_LENGTH];
(void) extra(HA_EXTRA_KEYREAD);
- key_copy(key,table,table->next_number_index,
- table->next_number_key_offset);
- error=mi_rkey(file,table->record[1],(int) table->next_number_index,
- key,table->next_number_key_offset,HA_READ_PREFIX_LAST);
+ key_copy(key, table->record[0],
+ table->key_info + table->s->next_number_index,
+ table->s->next_number_key_offset);
+ error= mi_rkey(file,table->record[1],(int) table->s->next_number_index,
+ key,table->s->next_number_key_offset,HA_READ_PREFIX_LAST);
if (error)
- nr=1;
+ nr= 1;
else
- nr=(longlong)
- table->next_number_field->val_int_offset(table->rec_buff_length)+1;
+ {
+ /* Get data from record[1] */
+ nr= ((ulonglong) table->next_number_field->
+ val_int_offset(table->s->rec_buff_length)+1);
+ }
extra(HA_EXTRA_NO_KEYREAD);
return nr;
}
@@ -1614,7 +1692,8 @@ int ha_myisam::ft_read(byte * buf)
if (!ft_handler)
return -1;
- thread_safe_increment(ha_read_next_count,&LOCK_status); // why ?
+ thread_safe_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status); // why ?
error=ft_handler->please->read_next(ft_handler,(char*) buf);
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index b256d4777f9..ca684463311 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -43,13 +43,7 @@ class ha_myisam: public handler
int repair(THD *thd, MI_CHECK &param, bool optimize);
public:
- ha_myisam(TABLE *table): handler(table), file(0),
- 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(TABLE *table_arg);
~ha_myisam() {}
const char *table_type() const { return "MyISAM"; }
const char *index_type(uint key_number);
@@ -115,7 +109,7 @@ class ha_myisam: public handler
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);
- longlong get_auto_increment();
+ ulonglong get_auto_increment();
int rename_table(const char * from, const char * to);
int delete_table(const char *name);
int check(THD* thd, HA_CHECK_OPT* check_opt);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index edb3521470f..f92717e11eb 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -32,8 +32,43 @@
** MyISAM MERGE tables
*****************************************************************************/
+/* MyISAM MERGE handlerton */
+
+static handlerton myisammrg_hton= {
+ "MRG_MyISAM",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
+
+ha_myisammrg::ha_myisammrg(TABLE *table_arg)
+ :handler(&myisammrg_hton, table_arg), file(0)
+{}
+
+static const char *ha_myisammrg_exts[] = {
+ ".MRG",
+ NullS
+};
+
const char **ha_myisammrg::bas_ext() const
-{ static const char *ext[]= { ".MRG", NullS }; return ext; }
+{
+ return ha_myisammrg_exts;
+}
+
const char *ha_myisammrg::index_type(uint key_number)
{
@@ -67,15 +102,15 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
myrg_extra(file,HA_EXTRA_WAIT_LOCK,0);
- if (table->reclength != mean_rec_length && mean_rec_length)
+ if (table->s->reclength != mean_rec_length && mean_rec_length)
{
DBUG_PRINT("error",("reclength: %d mean_rec_length: %d",
- table->reclength, mean_rec_length));
+ table->s->reclength, mean_rec_length));
goto err;
}
#if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4
/* Merge table has more than 2G rows */
- if (table->crashed)
+ if (table->s->crashed)
goto err;
#endif
return (0);
@@ -92,7 +127,7 @@ int ha_myisammrg::close(void)
int ha_myisammrg::write_row(byte * buf)
{
- statistic_increment(ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
@@ -102,7 +137,7 @@ int ha_myisammrg::write_row(byte * buf)
int ha_myisammrg::update_row(const byte * old_data, byte * new_data)
{
- statistic_increment(ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return myrg_update(file,old_data,new_data);
@@ -110,14 +145,15 @@ int ha_myisammrg::update_row(const byte * old_data, byte * new_data)
int ha_myisammrg::delete_row(const byte * buf)
{
- statistic_increment(ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
return myrg_delete(file,buf);
}
int ha_myisammrg::index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -126,7 +162,8 @@ int ha_myisammrg::index_read(byte * buf, const byte * key,
int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=myrg_rkey(file,buf,index, key, key_len, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -134,7 +171,8 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=myrg_rkey(file,buf,active_index, key, key_len,
HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -143,7 +181,8 @@ int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
int ha_myisammrg::index_next(byte * buf)
{
- statistic_increment(ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=myrg_rnext(file,buf,active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -151,7 +190,8 @@ int ha_myisammrg::index_next(byte * buf)
int ha_myisammrg::index_prev(byte * buf)
{
- statistic_increment(ha_read_prev_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_prev_count,
+ &LOCK_status);
int error=myrg_rprev(file,buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -159,7 +199,8 @@ int ha_myisammrg::index_prev(byte * buf)
int ha_myisammrg::index_first(byte * buf)
{
- statistic_increment(ha_read_first_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_first_count,
+ &LOCK_status);
int error=myrg_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -167,7 +208,8 @@ int ha_myisammrg::index_first(byte * buf)
int ha_myisammrg::index_last(byte * buf)
{
- statistic_increment(ha_read_last_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_last_count,
+ &LOCK_status);
int error=myrg_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -177,7 +219,8 @@ int ha_myisammrg::index_next_same(byte * buf,
const byte *key __attribute__((unused)),
uint length __attribute__((unused)))
{
- statistic_increment(ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=myrg_rnext_same(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -190,7 +233,8 @@ int ha_myisammrg::rnd_init(bool scan)
int ha_myisammrg::rnd_next(byte *buf)
{
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
int error=myrg_rrnd(file, buf, HA_OFFSET_ERROR);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -198,8 +242,9 @@ int ha_myisammrg::rnd_next(byte *buf)
int ha_myisammrg::rnd_pos(byte * buf, byte *pos)
{
- statistic_increment(ha_read_rnd_count,&LOCK_status);
- int error=myrg_rrnd(file, buf, ha_get_ptr(pos,ref_length));
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
+ int error=myrg_rrnd(file, buf, my_get_ptr(pos,ref_length));
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -207,7 +252,7 @@ int ha_myisammrg::rnd_pos(byte * buf, byte *pos)
void ha_myisammrg::position(const byte *record)
{
ulonglong position= myrg_position(file);
- ha_store_ptr(ref, ref_length, (my_off_t) position);
+ my_store_ptr(ref, ref_length, (my_off_t) position);
}
@@ -231,14 +276,14 @@ void ha_myisammrg::info(uint flag)
#if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4
if ((info.records >= (ulonglong) 1 << 32) ||
(info.deleted >= (ulonglong) 1 << 32))
- table->crashed=1;
+ table->s->crashed= 1;
#endif
data_file_length=info.data_file_length;
errkey = info.errkey;
- table->keys_in_use.set_prefix(table->keys);
- table->db_options_in_use = info.options;
- table->is_view=1;
- mean_rec_length=info.reclength;
+ table->s->keys_in_use.set_prefix(table->s->keys);
+ table->s->db_options_in_use= info.options;
+ table->s->is_view= 1;
+ mean_rec_length= info.reclength;
block_size=0;
update_time=0;
#if SIZEOF_OFF_T > 4
@@ -248,10 +293,10 @@ void ha_myisammrg::info(uint flag)
#endif
if (flag & HA_STATUS_CONST)
{
- if (table->key_parts && info.rec_per_key)
+ if (table->s->key_parts && info.rec_per_key)
memcpy((char*) table->key_info[0].rec_per_key,
(char*) info.rec_per_key,
- sizeof(table->key_info[0].rec_per_key)*table->key_parts);
+ sizeof(table->key_info[0].rec_per_key)*table->s->key_parts);
}
}
@@ -351,14 +396,14 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
goto err;
split_file_name(open_table->table->filename, &db, &name);
- if (!(ptr->real_name= thd->strmake(name.str, name.length)))
+ if (!(ptr->table_name= thd->strmake(name.str, name.length)))
goto err;
if (db.length && !(ptr->db= thd->strmake(db.str, db.length)))
goto err;
create_info->merge_list.elements++;
(*create_info->merge_list.next) = (byte*) ptr;
- create_info->merge_list.next= (byte**) &ptr->next;
+ create_info->merge_list.next= (byte**) &ptr->next_local;
}
*create_info->merge_list.next=0;
}
@@ -378,21 +423,22 @@ err:
int ha_myisammrg::create(const char *name, register TABLE *form,
HA_CREATE_INFO *create_info)
{
- char buff[FN_REFLEN],**table_names,**pos;
+ char buff[FN_REFLEN];
+ const char **table_names, **pos;
TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
THD *thd= current_thd;
uint dirlgt= dirname_length(name);
DBUG_ENTER("ha_myisammrg::create");
- if (!(table_names= (char**) thd->alloc((create_info->merge_list.elements+1)*
- sizeof(char*))))
+ if (!(table_names= (const char**)
+ thd->alloc((create_info->merge_list.elements+1) * sizeof(char*))))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- for (pos=table_names ; tables ; tables=tables->next)
+ for (pos= table_names; tables; tables= tables->next_local)
{
- char *table_name;
+ const char *table_name;
TABLE **tbl= 0;
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
- tbl= find_temporary_table(thd, tables->db, tables->real_name);
+ tbl= find_temporary_table(thd, tables->db, tables->table_name);
if (!tbl)
{
/*
@@ -407,7 +453,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
an embedded server without changing the paths in the .MRG file.
*/
uint length= my_snprintf(buff, FN_REFLEN, "%s/%s/%s", mysql_data_home,
- tables->db, tables->real_name);
+ tables->db, tables->table_name);
/*
If a MyISAM table is in the same directory as the MERGE table,
we use the table name without a path. This means that the
@@ -415,19 +461,18 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
as the MyISAM tables are from the same database as the MERGE table.
*/
if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt))
- table_name= tables->real_name;
+ table_name= tables->table_name;
else
if (! (table_name= thd->strmake(buff, length)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
else
- table_name=(*tbl)->path;
- DBUG_PRINT("info",("MyISAM table_name: '%s'", table_name));
+ table_name= (*tbl)->s->path;
*pos++= table_name;
}
*pos=0;
DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16),
- (const char **) table_names,
+ table_names,
create_info->merge_insert_method,
(my_bool) 0));
}
@@ -447,8 +492,8 @@ void ha_myisammrg::append_create_info(String *packet)
packet->append(" UNION=(",8);
MYRG_TABLE *open_table,*first;
- current_db= table->table_cache_key;
- db_length= strlen(current_db);
+ current_db= table->s->db;
+ db_length= (uint) strlen(current_db);
for (first=open_table=file->open_tables ;
open_table != file->end_table ;
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index 7348096b695..c762b7c286e 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -28,7 +28,7 @@ class ha_myisammrg: public handler
MYRG_INFO *file;
public:
- ha_myisammrg(TABLE *table): handler(table), file(0) {}
+ ha_myisammrg(TABLE *table_arg);
~ha_myisammrg() {}
const char *table_type() const { return "MRG_MyISAM"; }
const char **bas_ext() const;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index d1de0bd100e..ff631ac9db8 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -1,4 +1,4 @@
- /* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -12,7 +12,7 @@
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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
@@ -37,14 +37,38 @@ extern my_bool opt_ndb_optimized_node_selection;
extern const char *opt_ndbcluster_connectstring;
// Default value for parallelism
-static const int parallelism= 240;
+static const int parallelism= 0;
// Default value for max number of transactions
// createable against NDB from this handler
-static const int max_transactions= 256;
+static const int max_transactions= 2;
static const char *ha_ndb_ext=".ndb";
+static int ndbcluster_close_connection(THD *thd);
+static int ndbcluster_commit(THD *thd, bool all);
+static int ndbcluster_rollback(THD *thd, bool all);
+
+static handlerton ndbcluster_hton = {
+ "ndbcluster",
+ 0, /* slot */
+ 0, /* savepoint size */
+ ndbcluster_close_connection,
+ NULL, /* savepoint_set */
+ NULL, /* savepoint_rollback */
+ NULL, /* savepoint_release */
+ ndbcluster_commit,
+ ndbcluster_rollback,
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
#define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8
#define NDB_FAILED_AUTO_INCREMENT ~(Uint64)0
@@ -53,10 +77,11 @@ static const char *ha_ndb_ext=".ndb";
#define ERR_PRINT(err) \
DBUG_PRINT("error", ("%d message: %s", err.code, err.message))
-#define ERR_RETURN(err) \
-{ \
- ERR_PRINT(err); \
- DBUG_RETURN(ndb_to_mysql_error(&err)); \
+#define ERR_RETURN(err) \
+{ \
+ const NdbError& tmp= err; \
+ ERR_PRINT(tmp); \
+ DBUG_RETURN(ndb_to_mysql_error(&tmp)); \
}
// Typedefs for long names
@@ -83,17 +108,61 @@ static void free_share(NDB_SHARE *share);
static int packfrm(const void *data, uint len, const void **pack_data, uint *pack_len);
static int unpackfrm(const void **data, uint *len,
- const void* pack_data);
+ const void* pack_data);
static int ndb_get_table_statistics(Ndb*, const char *,
- Uint64* rows, Uint64* commits);
+ struct Ndb_statistics *);
+// Util thread variables
+static pthread_t ndb_util_thread;
+pthread_mutex_t LOCK_ndb_util_thread;
+pthread_cond_t COND_ndb_util_thread;
+extern "C" pthread_handler_decl(ndb_util_thread_func, arg);
+ulong ndb_cache_check_time;
/*
Dummy buffer to read zero pack_length fields
which are mapped to 1 char
*/
-static byte dummy_buf[1];
+static uint32 dummy_buf;
+
+/*
+ Stats that can be retrieved from ndb
+*/
+
+struct Ndb_statistics {
+ Uint64 row_count;
+ Uint64 commit_count;
+ Uint64 row_size;
+ Uint64 fragment_memory;
+};
+
+/* Status variables shown with 'show status like 'Ndb%' */
+
+static long ndb_cluster_node_id= 0;
+static const char * ndb_connected_host= 0;
+static long ndb_connected_port= 0;
+static long ndb_number_of_replicas= 0;
+static long ndb_number_of_storage_nodes= 0;
+
+static int update_status_variables(Ndb_cluster_connection *c)
+{
+ ndb_cluster_node_id= c->node_id();
+ ndb_connected_port= c->get_connected_port();
+ ndb_connected_host= c->get_connected_host();
+ ndb_number_of_replicas= 0;
+ ndb_number_of_storage_nodes= c->no_db_nodes();
+ return 0;
+}
+
+struct show_var_st ndb_status_variables[]= {
+ {"cluster_node_id", (char*) &ndb_cluster_node_id, SHOW_LONG},
+ {"connected_host", (char*) &ndb_connected_host, SHOW_CHAR_PTR},
+ {"connected_port", (char*) &ndb_connected_port, SHOW_LONG},
+// {"number_of_replicas", (char*) &ndb_number_of_replicas, SHOW_LONG},
+ {"number_of_storage_nodes",(char*) &ndb_number_of_storage_nodes, SHOW_LONG},
+ {NullS, NullS, SHOW_LONG}
+};
/*
Error handling functions
@@ -114,7 +183,7 @@ static const err_code_mapping err_map[]=
{ 721, HA_ERR_TABLE_EXIST, 1 },
{ 4244, HA_ERR_TABLE_EXIST, 1 },
- { 709, HA_ERR_NO_SUCH_TABLE, 1 },
+ { 709, HA_ERR_NO_SUCH_TABLE, 0 },
{ 266, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
{ 274, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
@@ -129,6 +198,8 @@ static const err_code_mapping err_map[]=
{ 827, HA_ERR_RECORD_FILE_FULL, 1 },
{ 832, HA_ERR_RECORD_FILE_FULL, 1 },
+ { 284, HA_ERR_TABLE_DEF_CHANGED, 0 },
+
{ 0, 1, 0 },
{ -1, -1, 1 }
@@ -143,8 +214,8 @@ static int ndb_to_mysql_error(const NdbError *err)
{
// Push the NDB error message as warning
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
- err->code, err->message, "NDB");
+ ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
+ err->code, err->message, "NDB");
}
if (err_map[i].my_err == -1)
return err->code;
@@ -154,58 +225,67 @@ static int ndb_to_mysql_error(const NdbError *err)
inline
-int execute_no_commit(ha_ndbcluster *h, NdbConnection *trans)
+int execute_no_commit(ha_ndbcluster *h, NdbTransaction *trans)
{
- int m_batch_execute= 0;
#ifdef NOT_USED
+ int m_batch_execute= 0;
if (m_batch_execute)
return 0;
#endif
- return trans->execute(NoCommit,AbortOnError,h->m_force_send);
+ return trans->execute(NdbTransaction::NoCommit,
+ NdbTransaction::AbortOnError,
+ h->m_force_send);
}
inline
-int execute_commit(ha_ndbcluster *h, NdbConnection *trans)
+int execute_commit(ha_ndbcluster *h, NdbTransaction *trans)
{
- int m_batch_execute= 0;
#ifdef NOT_USED
+ int m_batch_execute= 0;
if (m_batch_execute)
return 0;
#endif
- return trans->execute(Commit,AbortOnError,h->m_force_send);
+ return trans->execute(NdbTransaction::Commit,
+ NdbTransaction::AbortOnError,
+ h->m_force_send);
}
inline
-int execute_commit(THD *thd, NdbConnection *trans)
+int execute_commit(THD *thd, NdbTransaction *trans)
{
- int m_batch_execute= 0;
#ifdef NOT_USED
+ int m_batch_execute= 0;
if (m_batch_execute)
return 0;
#endif
- return trans->execute(Commit,AbortOnError,thd->variables.ndb_force_send);
+ return trans->execute(NdbTransaction::Commit,
+ NdbTransaction::AbortOnError,
+ thd->variables.ndb_force_send);
}
inline
-int execute_no_commit_ie(ha_ndbcluster *h, NdbConnection *trans)
+int execute_no_commit_ie(ha_ndbcluster *h, NdbTransaction *trans)
{
- int m_batch_execute= 0;
#ifdef NOT_USED
+ int m_batch_execute= 0;
if (m_batch_execute)
return 0;
#endif
- return trans->execute(NoCommit, AO_IgnoreError,h->m_force_send);
+ return trans->execute(NdbTransaction::NoCommit,
+ NdbTransaction::AO_IgnoreError,
+ h->m_force_send);
}
/*
Place holder for ha_ndbcluster thread specific data
*/
-
Thd_ndb::Thd_ndb()
{
ndb= new Ndb(g_ndb_cluster_connection, "");
lock_count= 0;
count= 0;
+ all= NULL;
+ stmt= NULL;
error= 0;
}
@@ -213,13 +293,22 @@ Thd_ndb::~Thd_ndb()
{
if (ndb)
delete ndb;
- ndb= 0;
+ ndb= NULL;
+ changed_tables.empty();
}
inline
+Thd_ndb *
+get_thd_ndb(THD *thd) { return (Thd_ndb *) thd->ha_data[ndbcluster_hton.slot]; }
+
+inline
+void
+set_thd_ndb(THD *thd, Thd_ndb *thd_ndb) { thd->ha_data[ndbcluster_hton.slot]= thd_ndb; }
+
+inline
Ndb *ha_ndbcluster::get_ndb()
{
- return ((Thd_ndb*)current_thd->transaction.thd_ndb)->ndb;
+ return get_thd_ndb(current_thd)->ndb;
}
/*
@@ -235,7 +324,7 @@ struct Ndb_local_table_statistics {
void ha_ndbcluster::set_rec_per_key()
{
DBUG_ENTER("ha_ndbcluster::get_status_const");
- for (uint i=0 ; i < table->keys ; i++)
+ for (uint i=0 ; i < table->s->keys ; i++)
{
table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]= 1;
}
@@ -250,19 +339,21 @@ void ha_ndbcluster::records_update()
struct Ndb_local_table_statistics *info=
(struct Ndb_local_table_statistics *)m_table_info;
DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
- ((const NDBTAB *)m_table)->getTableId(),
- info->no_uncommitted_rows_count));
+ ((const NDBTAB *)m_table)->getTableId(),
+ info->no_uncommitted_rows_count));
// if (info->records == ~(ha_rows)0)
{
Ndb *ndb= get_ndb();
- Uint64 rows;
- if(ndb_get_table_statistics(ndb, m_tabname, &rows, 0) == 0){
- info->records= rows;
+ struct Ndb_statistics stat;
+ if (ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){
+ mean_rec_length= stat.row_size;
+ data_file_length= stat.fragment_memory;
+ info->records= stat.row_count;
}
}
{
THD *thd= current_thd;
- if (((Thd_ndb*)(thd->transaction.thd_ndb))->error)
+ if (get_thd_ndb(thd)->error)
info->no_uncommitted_rows_count= 0;
}
records= info->records+ info->no_uncommitted_rows_count;
@@ -274,8 +365,7 @@ void ha_ndbcluster::no_uncommitted_rows_execute_failure()
if (m_ha_not_exact_count)
return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_execute_failure");
- THD *thd= current_thd;
- ((Thd_ndb*)(thd->transaction.thd_ndb))->error= 1;
+ get_thd_ndb(current_thd)->error= 1;
DBUG_VOID_RETURN;
}
@@ -286,15 +376,15 @@ void ha_ndbcluster::no_uncommitted_rows_init(THD *thd)
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_init");
struct Ndb_local_table_statistics *info=
(struct Ndb_local_table_statistics *)m_table_info;
- Thd_ndb *thd_ndb= (Thd_ndb *)thd->transaction.thd_ndb;
+ Thd_ndb *thd_ndb= get_thd_ndb(thd);
if (info->last_count != thd_ndb->count)
{
- info->last_count = thd_ndb->count;
+ info->last_count= thd_ndb->count;
info->no_uncommitted_rows_count= 0;
info->records= ~(ha_rows)0;
DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
- ((const NDBTAB *)m_table)->getTableId(),
- info->no_uncommitted_rows_count));
+ ((const NDBTAB *)m_table)->getTableId(),
+ info->no_uncommitted_rows_count));
}
DBUG_VOID_RETURN;
}
@@ -308,8 +398,8 @@ void ha_ndbcluster::no_uncommitted_rows_update(int c)
(struct Ndb_local_table_statistics *)m_table_info;
info->no_uncommitted_rows_count+= c;
DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
- ((const NDBTAB *)m_table)->getTableId(),
- info->no_uncommitted_rows_count));
+ ((const NDBTAB *)m_table)->getTableId(),
+ info->no_uncommitted_rows_count));
DBUG_VOID_RETURN;
}
@@ -318,16 +408,17 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd)
if (m_ha_not_exact_count)
return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_reset");
- ((Thd_ndb*)(thd->transaction.thd_ndb))->count++;
- ((Thd_ndb*)(thd->transaction.thd_ndb))->error= 0;
+ Thd_ndb *thd_ndb= get_thd_ndb(thd);
+ thd_ndb->count++;
+ thd_ndb->error= 0;
DBUG_VOID_RETURN;
}
/*
Take care of the error that occured in NDB
-
+
RETURN
- 0 No error
+ 0 No error
# The mapped error code
*/
@@ -353,42 +444,42 @@ void ha_ndbcluster::invalidate_dictionary_cache(bool global)
}
else
dict->removeCachedTable(m_tabname);
- table->version=0L; /* Free when thread is ready */
+ table->s->version=0L; /* Free when thread is ready */
/* Invalidate indexes */
- for (uint i= 0; i < table->keys; i++)
+ for (uint i= 0; i < table->s->keys; i++)
{
NDBINDEX *index = (NDBINDEX *) m_index[i].index;
NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index;
NDB_INDEX_TYPE idx_type= m_index[i].type;
- switch(idx_type) {
- case(PRIMARY_KEY_ORDERED_INDEX):
- case(ORDERED_INDEX):
+ switch (idx_type) {
+ case PRIMARY_KEY_ORDERED_INDEX:
+ case ORDERED_INDEX:
if (global)
dict->invalidateIndex(index->getName(), m_tabname);
else
dict->removeCachedIndex(index->getName(), m_tabname);
- break;
- case(UNIQUE_ORDERED_INDEX):
+ break;
+ case UNIQUE_ORDERED_INDEX:
if (global)
dict->invalidateIndex(index->getName(), m_tabname);
else
dict->removeCachedIndex(index->getName(), m_tabname);
- case(UNIQUE_INDEX):
+ case UNIQUE_INDEX:
if (global)
dict->invalidateIndex(unique_index->getName(), m_tabname);
else
dict->removeCachedIndex(unique_index->getName(), m_tabname);
break;
- case(PRIMARY_KEY_INDEX):
- case(UNDEFINED_INDEX):
+ case PRIMARY_KEY_INDEX:
+ case UNDEFINED_INDEX:
break;
}
}
DBUG_VOID_RETURN;
}
-int ha_ndbcluster::ndb_err(NdbConnection *trans)
+int ha_ndbcluster::ndb_err(NdbTransaction *trans)
{
int res;
NdbError err= trans->getNdbError();
@@ -397,7 +488,6 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans)
ERR_PRINT(err);
switch (err.classification) {
case NdbError::SchemaError:
- {
invalidate_dictionary_cache(TRUE);
if (err.code==284)
@@ -415,29 +505,19 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans)
if (err.code != 709)
DBUG_RETURN(1);
}
- else
- {
- DBUG_PRINT("info", ("Table exist but must have changed"));
- /* In 5.0, this should be replaced with a mapping to a mysql error */
- my_printf_error(ER_UNKNOWN_ERROR,
- "Table definition has changed, "\
- "please retry transaction",
- MYF(0));
- DBUG_RETURN(1);
- }
+ DBUG_PRINT("info", ("Table exists but must have changed"));
}
break;
- }
default:
break;
}
res= ndb_to_mysql_error(&err);
DBUG_PRINT("info", ("transformed ndbcluster error %d to mysql error %d",
- err.code, res));
+ err.code, res));
if (res == HA_ERR_FOUND_DUPP_KEY)
{
if (m_rows_to_insert == 1)
- m_dupkey= table->primary_key;
+ m_dupkey= table->s->primary_key;
else
{
/* We are batching inserts, offending key is not available */
@@ -454,7 +534,7 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans)
*/
bool ha_ndbcluster::get_error_message(int error,
- String *buf)
+ String *buf)
{
DBUG_ENTER("ha_ndbcluster::get_error_message");
DBUG_PRINT("enter", ("error: %d", error));
@@ -479,7 +559,6 @@ bool ha_ndbcluster::get_error_message(int error,
static bool ndb_supported_type(enum_field_types type)
{
switch (type) {
- case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG:
@@ -487,6 +566,8 @@ static bool ndb_supported_type(enum_field_types type)
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_DATE:
@@ -495,12 +576,14 @@ static bool ndb_supported_type(enum_field_types type)
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_BIT:
return TRUE;
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_GEOMETRY:
@@ -516,11 +599,11 @@ static bool ndb_supported_type(enum_field_types type)
*/
bool ha_ndbcluster::set_hidden_key(NdbOperation *ndb_op,
- uint fieldnr, const byte *field_ptr)
+ uint fieldnr, const byte *field_ptr)
{
DBUG_ENTER("set_hidden_key");
DBUG_RETURN(ndb_op->equal(fieldnr, (char*)field_ptr,
- NDB_HIDDEN_PRIMARY_KEY_LENGTH) != 0);
+ NDB_HIDDEN_PRIMARY_KEY_LENGTH) != 0);
}
@@ -563,21 +646,50 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field,
DBUG_ASSERT(ndb_supported_type(field->type()));
{
// ndb currently does not support size 0
- const byte *empty_field= "";
+ uint32 empty_field;
if (pack_len == 0)
{
- pack_len= 1;
- field_ptr= empty_field;
+ pack_len= sizeof(empty_field);
+ field_ptr= (byte *)&empty_field;
+ if (field->is_null())
+ empty_field= 0;
+ else
+ empty_field= 1;
}
if (! (field->flags & BLOB_FLAG))
{
- if (field->is_null())
- // Set value to NULL
- DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL, pack_len) != 0));
- // Common implementation for most field types
- DBUG_RETURN(ndb_op->setValue(fieldnr, (char*)field_ptr, pack_len) != 0);
+ if (field->type() != MYSQL_TYPE_BIT)
+ {
+ if (field->is_null())
+ // Set value to NULL
+ DBUG_RETURN((ndb_op->setValue(fieldnr,
+ (char*)NULL, pack_len) != 0));
+ // Common implementation for most field types
+ DBUG_RETURN(ndb_op->setValue(fieldnr,
+ (char*)field_ptr, pack_len) != 0);
+ }
+ else // if (field->type() == MYSQL_TYPE_BIT)
+ {
+ longlong bits= field->val_int();
+
+ // Round up bit field length to nearest word boundry
+ pack_len= ((pack_len + 3) >> 2) << 2;
+ DBUG_ASSERT(pack_len <= 8);
+ if (field->is_null())
+ // Set value to NULL
+ DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL, pack_len) != 0));
+ DBUG_PRINT("info", ("bit field"));
+ DBUG_DUMP("value", (char*)&bits, pack_len);
+#ifdef WORDS_BIGENDIAN
+ if (pack_len < 5)
+ {
+ DBUG_RETURN(ndb_op->setValue(fieldnr,
+ ((char*)&bits)+4, pack_len) != 0);
+ }
+#endif
+ DBUG_RETURN(ndb_op->setValue(fieldnr, (char*)&bits, pack_len) != 0);
+ }
}
-
// Blob type
NdbBlob *ndb_blob= ndb_op->getBlobHandle(fieldnr);
if (ndb_blob != NULL)
@@ -598,12 +710,12 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field,
blob_ptr= (char*)"";
}
- DBUG_PRINT("value", ("set blob ptr=%x len=%u",
- (unsigned)blob_ptr, blob_len));
+ DBUG_PRINT("value", ("set blob ptr=%p len=%u",
+ blob_ptr, blob_len));
DBUG_DUMP("value", (char*)blob_ptr, min(blob_len, 26));
if (set_blob_value)
- *set_blob_value= TRUE;
+ *set_blob_value= TRUE;
// No callback needed to write value
DBUG_RETURN(ndb_blob->setValue(blob_ptr, blob_len) != 0);
}
@@ -644,7 +756,7 @@ int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob)
for (int loop= 0; loop <= 1; loop++)
{
uint32 offset= 0;
- for (uint i= 0; i < table->fields; i++)
+ for (uint i= 0; i < table->s->fields; i++)
{
Field *field= table->field[i];
NdbValue value= m_value[i];
@@ -707,14 +819,21 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field,
DBUG_ASSERT(ndb_supported_type(field->type()));
DBUG_ASSERT(field->ptr != NULL);
if (! (field->flags & BLOB_FLAG))
- {
- byte *field_buf;
- if (field->pack_length() != 0)
- field_buf= buf + (field->ptr - table->record[0]);
- else
- field_buf= dummy_buf;
- m_value[fieldnr].rec= ndb_op->getValue(fieldnr,
- field_buf);
+ {
+ if (field->type() != MYSQL_TYPE_BIT)
+ {
+ byte *field_buf;
+ if (field->pack_length() != 0)
+ field_buf= buf + (field->ptr - table->record[0]);
+ else
+ field_buf= (byte *)&dummy_buf;
+ m_value[fieldnr].rec= ndb_op->getValue(fieldnr,
+ field_buf);
+ }
+ else // if (field->type() == MYSQL_TYPE_BIT)
+ {
+ m_value[fieldnr].rec= ndb_op->getValue(fieldnr);
+ }
DBUG_RETURN(m_value[fieldnr].rec == NULL);
}
@@ -741,14 +860,14 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field,
*/
bool ha_ndbcluster::uses_blob_value(bool all_fields)
{
- if (table->blob_fields == 0)
+ if (table->s->blob_fields == 0)
return FALSE;
if (all_fields)
return TRUE;
{
- uint no_fields= table->fields;
+ uint no_fields= table->s->fields;
int i;
- THD *thd= table->in_use;
+ THD *thd= current_thd;
// They always put blobs at the end..
for (i= no_fields - 1; i >= 0; i--)
{
@@ -801,7 +920,7 @@ int ha_ndbcluster::get_metadata(const char *path)
*/
error= 0;
if (readfrm(path, &data, &length) ||
- packfrm(data, length, &pack_data, &pack_length))
+ packfrm(data, length, &pack_data, &pack_length))
{
my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
@@ -809,24 +928,24 @@ int ha_ndbcluster::get_metadata(const char *path)
}
if ((pack_length != tab->getFrmLength()) ||
- (memcmp(pack_data, tab->getFrmData(), pack_length)))
+ (memcmp(pack_data, tab->getFrmData(), pack_length)))
{
if (!invalidating_ndb_table)
{
- DBUG_PRINT("info", ("Invalidating table"));
+ DBUG_PRINT("info", ("Invalidating table"));
invalidate_dictionary_cache(TRUE);
- invalidating_ndb_table= TRUE;
+ invalidating_ndb_table= TRUE;
}
else
{
- DBUG_PRINT("error",
- ("metadata, pack_length: %d getFrmLength: %d memcmp: %d",
- pack_length, tab->getFrmLength(),
- memcmp(pack_data, tab->getFrmData(), pack_length)));
- DBUG_DUMP("pack_data", (char*)pack_data, pack_length);
- DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength());
- error= 3;
- invalidating_ndb_table= FALSE;
+ DBUG_PRINT("error",
+ ("metadata, pack_length: %d getFrmLength: %d memcmp: %d",
+ pack_length, tab->getFrmLength(),
+ memcmp(pack_data, tab->getFrmData(), pack_length)));
+ DBUG_DUMP("pack_data", (char*)pack_data, pack_length);
+ DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength());
+ error= 3;
+ invalidating_ndb_table= FALSE;
}
}
else
@@ -848,8 +967,8 @@ int ha_ndbcluster::get_metadata(const char *path)
}
static int fix_unique_index_attr_order(NDB_INDEX_DATA &data,
- const NDBINDEX *index,
- KEY *key_info)
+ const NDBINDEX *index,
+ KEY *key_info)
{
DBUG_ENTER("fix_unique_index_attr_order");
unsigned sz= index->getNoOfIndexColumns();
@@ -864,19 +983,16 @@ static int fix_unique_index_attr_order(NDB_INDEX_DATA &data,
for (unsigned i= 0; key_part != end; key_part++, i++)
{
const char *field_name= key_part->field->field_name;
- unsigned name_sz= strlen(field_name);
- if (name_sz >= NDB_MAX_ATTR_NAME_SIZE)
- name_sz= NDB_MAX_ATTR_NAME_SIZE-1;
#ifndef DBUG_OFF
data.unique_index_attrid_map[i]= 255;
#endif
for (unsigned j= 0; j < sz; j++)
{
const NDBCOL *c= index->getColumn(j);
- if (strncmp(field_name, c->getName(), name_sz) == 0)
+ if (strcmp(field_name, c->getName()) == 0)
{
- data.unique_index_attrid_map[i]= j;
- break;
+ data.unique_index_attrid_map[i]= j;
+ break;
}
}
DBUG_ASSERT(data.unique_index_attrid_map[i] != 255);
@@ -888,16 +1004,16 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase)
{
uint i;
int error= 0;
- const char *name, *index_name;
+ const char *index_name;
char unique_index_name[FN_LEN];
static const char* unique_suffix= "$unique";
KEY* key_info= tab->key_info;
- const char **key_name= tab->keynames.type_names;
+ const char **key_name= tab->s->keynames.type_names;
NDBDICT *dict= ndb->getDictionary();
- DBUG_ENTER("build_index_list");
+ DBUG_ENTER("ha_ndbcluster::build_index_list");
// Save information about all known indexes
- for (i= 0; i < tab->keys; i++, key_info++, key_name++)
+ for (i= 0; i < tab->s->keys; i++, key_info++, key_name++)
{
index_name= *key_name;
NDB_INDEX_TYPE idx_type= get_index_type_from_table(i);
@@ -906,40 +1022,40 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase)
{
strxnmov(unique_index_name, FN_LEN, index_name, unique_suffix, NullS);
DBUG_PRINT("info", ("Created unique index name \'%s\' for index %d",
- unique_index_name, i));
+ unique_index_name, i));
}
// Create secondary indexes if in create phase
if (phase == ILBP_CREATE)
{
DBUG_PRINT("info", ("Creating index %u: %s", i, index_name));
switch (idx_type){
-
+
case PRIMARY_KEY_INDEX:
- // Do nothing, already created
- break;
+ // Do nothing, already created
+ break;
case PRIMARY_KEY_ORDERED_INDEX:
- error= create_ordered_index(index_name, key_info);
- break;
+ error= create_ordered_index(index_name, key_info);
+ break;
case UNIQUE_ORDERED_INDEX:
- if (!(error= create_ordered_index(index_name, key_info)))
- error= create_unique_index(unique_index_name, key_info);
- break;
+ if (!(error= create_ordered_index(index_name, key_info)))
+ error= create_unique_index(unique_index_name, key_info);
+ break;
case UNIQUE_INDEX:
- if (!(error= check_index_fields_not_null(i)))
- error= create_unique_index(unique_index_name, key_info);
- break;
+ if (!(error= check_index_fields_not_null(i)))
+ error= create_unique_index(unique_index_name, key_info);
+ break;
case ORDERED_INDEX:
- error= create_ordered_index(index_name, key_info);
- break;
+ error= create_ordered_index(index_name, key_info);
+ break;
default:
- DBUG_ASSERT(FALSE);
- break;
+ DBUG_ASSERT(FALSE);
+ break;
}
if (error)
{
- DBUG_PRINT("error", ("Failed to create index %u", i));
- drop_table();
- break;
+ DBUG_PRINT("error", ("Failed to create index %u", i));
+ drop_table();
+ break;
}
}
// Add handles to index objects
@@ -971,12 +1087,12 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase)
NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const
{
bool is_hash_index= (table->key_info[inx].algorithm == HA_KEY_ALG_HASH);
- if (inx == table->primary_key)
+ if (inx == table->s->primary_key)
return is_hash_index ? PRIMARY_KEY_INDEX : PRIMARY_KEY_ORDERED_INDEX;
- else
- return ((table->key_info[inx].flags & HA_NOSAME) ?
- (is_hash_index ? UNIQUE_INDEX : UNIQUE_ORDERED_INDEX) :
- ORDERED_INDEX);
+
+ return ((table->key_info[inx].flags & HA_NOSAME) ?
+ (is_hash_index ? UNIQUE_INDEX : UNIQUE_ORDERED_INDEX) :
+ ORDERED_INDEX);
}
int ha_ndbcluster::check_index_fields_not_null(uint inx)
@@ -984,16 +1100,16 @@ int ha_ndbcluster::check_index_fields_not_null(uint inx)
KEY* key_info= table->key_info + inx;
KEY_PART_INFO* key_part= key_info->key_part;
KEY_PART_INFO* end= key_part+key_info->key_parts;
- DBUG_ENTER("check_index_fields_not_null");
+ DBUG_ENTER("ha_ndbcluster::check_index_fields_not_null");
for (; key_part != end; key_part++)
{
Field* field= key_part->field;
if (field->maybe_null())
{
- my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX),
- MYF(0),field->field_name);
- DBUG_RETURN(ER_NULL_COLUMN_IN_INDEX);
+ my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX),
+ MYF(0),field->field_name);
+ DBUG_RETURN(ER_NULL_COLUMN_IN_INDEX);
}
}
@@ -1051,6 +1167,7 @@ static const ulong index_type_flags[]=
*/
// HA_KEYREAD_ONLY |
HA_READ_NEXT |
+ HA_READ_PREV |
HA_READ_RANGE |
HA_READ_ORDER,
@@ -1059,11 +1176,13 @@ static const ulong index_type_flags[]=
/* UNIQUE_ORDERED_INDEX */
HA_READ_NEXT |
+ HA_READ_PREV |
HA_READ_RANGE |
HA_READ_ORDER,
/* ORDERED_INDEX */
HA_READ_NEXT |
+ HA_READ_PREV |
HA_READ_RANGE |
HA_READ_ORDER
};
@@ -1087,16 +1206,34 @@ inline NDB_INDEX_TYPE ha_ndbcluster::get_index_type(uint idx_no) const
inline ulong ha_ndbcluster::index_flags(uint idx_no, uint part,
bool all_parts) const
{
- DBUG_ENTER("index_flags");
+ DBUG_ENTER("ha_ndbcluster::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)]);
}
+static void shrink_varchar(Field* field, const byte* & ptr, char* buf)
+{
+ if (field->type() == MYSQL_TYPE_VARCHAR && ptr != NULL) {
+ Field_varstring* f= (Field_varstring*)field;
+ if (f->length_bytes == 1) {
+ uint pack_len= field->pack_length();
+ DBUG_ASSERT(1 <= pack_len && pack_len <= 256);
+ if (ptr[1] == 0) {
+ buf[0]= ptr[0];
+ } else {
+ DBUG_ASSERT(FALSE);
+ buf[0]= 255;
+ }
+ memmove(buf + 1, ptr + 2, pack_len - 1);
+ ptr= buf;
+ }
+ }
+}
int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key)
{
- KEY* key_info= table->key_info + table->primary_key;
+ KEY* key_info= table->key_info + table->s->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");
@@ -1104,10 +1241,13 @@ int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key)
for (; key_part != end; key_part++)
{
Field* field= key_part->field;
+ const byte* ptr= key;
+ char buf[256];
+ shrink_varchar(field, ptr, buf);
if (set_ndb_key(op, field,
- key_part->fieldnr-1, key))
+ key_part->fieldnr-1, ptr))
ERR_RETURN(op->getNdbError());
- key += key_part->length;
+ key += key_part->store_length;
}
DBUG_RETURN(0);
}
@@ -1115,7 +1255,7 @@ int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key)
int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *record)
{
- KEY* key_info= table->key_info + table->primary_key;
+ KEY* key_info= table->key_info + table->s->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_record");
@@ -1130,16 +1270,81 @@ int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *rec
DBUG_RETURN(0);
}
+int
+ha_ndbcluster::set_index_key(NdbOperation *op,
+ const KEY *key_info,
+ const byte * key_ptr)
+{
+ DBUG_ENTER("ha_ndbcluster::set_index_key");
+ uint i;
+ KEY_PART_INFO* key_part= key_info->key_part;
+ KEY_PART_INFO* end= key_part+key_info->key_parts;
+
+ for (i= 0; key_part != end; key_part++, i++)
+ {
+ Field* field= key_part->field;
+ const byte* ptr= key_part->null_bit ? key_ptr + 1 : key_ptr;
+ char buf[256];
+ shrink_varchar(field, ptr, buf);
+ if (set_ndb_key(op, field, m_index[active_index].unique_index_attrid_map[i], ptr))
+ ERR_RETURN(m_active_trans->getNdbError());
+ key_ptr+= key_part->store_length;
+ }
+ DBUG_RETURN(0);
+}
+
+inline
+int ha_ndbcluster::define_read_attrs(byte* buf, NdbOperation* op)
+{
+ uint i;
+ THD *thd= current_thd;
+
+ DBUG_ENTER("define_read_attrs");
+
+ // Define attributes to read
+ for (i= 0; i < table->s->fields; i++)
+ {
+ Field *field= table->field[i];
+ if ((thd->query_id == field->query_id) ||
+ ((field->flags & PRI_KEY_FLAG)) ||
+ m_retrieve_all_fields)
+ {
+ if (get_ndb_value(op, field, i, buf))
+ ERR_RETURN(op->getNdbError());
+ }
+ else
+ {
+ m_value[i].ptr= NULL;
+ }
+ }
+
+ if (table->s->primary_key == MAX_KEY)
+ {
+ DBUG_PRINT("info", ("Getting hidden key"));
+ // Scanning table with no primary key
+ int hidden_no= table->s->fields;
+#ifndef DBUG_OFF
+ const NDBTAB *tab= (const NDBTAB *) m_table;
+ if (!tab->getColumn(hidden_no))
+ DBUG_RETURN(1);
+#endif
+ if (get_ndb_value(op, NULL, hidden_no, NULL))
+ ERR_RETURN(op->getNdbError());
+ }
+ DBUG_RETURN(0);
+}
+
/*
Read one record from NDB using primary key
*/
int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf)
{
- uint no_fields= table->fields, i;
+ uint no_fields= table->s->fields;
NdbConnection *trans= m_active_trans;
NdbOperation *op;
- THD *thd= current_thd;
+
+ int res;
DBUG_ENTER("pk_read");
DBUG_PRINT("enter", ("key_len: %u", key_len));
DBUG_DUMP("key", (char*)key, key_len);
@@ -1149,43 +1354,27 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf)
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
op->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
-
- if (table->primary_key == MAX_KEY)
+
+ if (table->s->primary_key == MAX_KEY)
{
// This table has no primary key, use "hidden" primary key
DBUG_PRINT("info", ("Using hidden key"));
DBUG_DUMP("key", (char*)key, 8);
if (set_hidden_key(op, no_fields, key))
ERR_RETURN(trans->getNdbError());
-
+
// Read key at the same time, for future reference
if (get_ndb_value(op, NULL, no_fields, NULL))
ERR_RETURN(trans->getNdbError());
}
else
{
- int res;
if ((res= set_primary_key(op, key)))
return res;
}
- // Read all wanted non-key field(s) unless HA_EXTRA_RETRIEVE_ALL_COLS
- for (i= 0; i < no_fields; i++)
- {
- Field *field= table->field[i];
- if ((thd->query_id == field->query_id) ||
- m_retrieve_all_fields ||
- (field->flags & PRI_KEY_FLAG) && m_retrieve_primary_key)
- {
- if (get_ndb_value(op, field, i, buf))
- ERR_RETURN(trans->getNdbError());
- }
- else
- {
- // Attribute was not to be read
- m_value[i].ptr= NULL;
- }
- }
+ if ((res= define_read_attrs(buf, op)))
+ DBUG_RETURN(res);
if (execute_no_commit_ie(this,trans) != 0)
{
@@ -1199,15 +1388,14 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf)
DBUG_RETURN(0);
}
-
/*
Read one complementing record from NDB using primary key from old_data
*/
int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data)
{
- uint no_fields= table->fields, i;
- NdbConnection *trans= m_active_trans;
+ uint no_fields= table->s->fields, i;
+ NdbTransaction *trans= m_active_trans;
NdbOperation *op;
THD *thd= current_thd;
DBUG_ENTER("complemented_pk_read");
@@ -1221,20 +1409,18 @@ int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data)
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
op->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
-
int res;
if ((res= set_primary_key_from_record(op, old_data)))
ERR_RETURN(trans->getNdbError());
-
// Read all unreferenced non-key field(s)
for (i= 0; i < no_fields; i++)
{
Field *field= table->field[i];
- if (!(field->flags & PRI_KEY_FLAG) &&
- (thd->query_id != field->query_id))
+ if (!((field->flags & PRI_KEY_FLAG) ||
+ (thd->query_id == field->query_id)))
{
if (get_ndb_value(op, field, i, new_data))
- ERR_RETURN(trans->getNdbError());
+ ERR_RETURN(trans->getNdbError());
}
}
@@ -1247,6 +1433,20 @@ int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data)
// The value have now been fetched from NDB
unpack_record(new_data);
table->status= 0;
+
+ /**
+ * restore m_value
+ */
+ for (i= 0; i < no_fields; i++)
+ {
+ Field *field= table->field[i];
+ if (!((field->flags & PRI_KEY_FLAG) ||
+ (thd->query_id == field->query_id)))
+ {
+ m_value[i].ptr= NULL;
+ }
+ }
+
DBUG_RETURN(0);
}
@@ -1256,26 +1456,25 @@ int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data)
int ha_ndbcluster::peek_row(const byte *record)
{
- NdbConnection *trans= m_active_trans;
+ NdbTransaction *trans= m_active_trans;
NdbOperation *op;
- THD *thd= current_thd;
DBUG_ENTER("peek_row");
-
+
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
op->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
-
+
int res;
if ((res= set_primary_key_from_record(op, record)))
ERR_RETURN(trans->getNdbError());
-
+
if (execute_no_commit_ie(this,trans) != 0)
- {
- table->status= STATUS_NOT_FOUND;
- DBUG_RETURN(ndb_err(trans));
- }
+ {
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(ndb_err(trans));
+ }
DBUG_RETURN(0);
}
@@ -1284,58 +1483,29 @@ int ha_ndbcluster::peek_row(const byte *record)
*/
int ha_ndbcluster::unique_index_read(const byte *key,
- uint key_len, byte *buf)
+ uint key_len, byte *buf)
{
- NdbConnection *trans= m_active_trans;
+ int res;
+ NdbTransaction *trans= m_active_trans;
NdbIndexOperation *op;
- THD *thd= current_thd;
- byte *key_ptr;
- KEY* key_info;
- KEY_PART_INFO *key_part, *end;
- uint i;
- DBUG_ENTER("unique_index_read");
+ DBUG_ENTER("ha_ndbcluster::unique_index_read");
DBUG_PRINT("enter", ("key_len: %u, index: %u", key_len, active_index));
DBUG_DUMP("key", (char*)key, key_len);
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
if (!(op= trans->getNdbIndexOperation((NDBINDEX *)
- m_index[active_index].unique_index,
+ m_index[active_index].unique_index,
(const NDBTAB *) m_table)) ||
op->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
// Set secondary index key(s)
- key_ptr= (byte *) key;
- key_info= table->key_info + active_index;
- DBUG_ASSERT(key_info->key_length == key_len);
- end= (key_part= key_info->key_part) + key_info->key_parts;
-
- for (i= 0; key_part != end; key_part++, i++)
- {
- if (set_ndb_key(op, key_part->field,
- m_index[active_index].unique_index_attrid_map[i],
- key_part->null_bit ? key_ptr + 1 : key_ptr))
- ERR_RETURN(trans->getNdbError());
- key_ptr+= key_part->store_length;
- }
-
- // Get non-index 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)) // && m_retrieve_primary_key ??
- {
- if (get_ndb_value(op, field, i, buf))
- ERR_RETURN(op->getNdbError());
- }
- else
- {
- // Attribute was not to be read
- m_value[i].ptr= NULL;
- }
- }
+ if ((res= set_index_key(op, table->key_info + active_index, key)))
+ DBUG_RETURN(res);
+
+ if ((res= define_read_attrs(buf, op)))
+ DBUG_RETURN(res);
if (execute_no_commit_ie(this,trans) != 0)
{
@@ -1348,31 +1518,12 @@ int ha_ndbcluster::unique_index_read(const byte *key,
DBUG_RETURN(0);
}
-/*
- 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)
-{
+inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
+{
+ DBUG_ENTER("fetch_next");
int check;
- NdbConnection *trans= m_active_trans;
- NdbResultSet *cursor= m_active_cursor;
- DBUG_ENTER("next_result");
-
- 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
- */
+ NdbTransaction *trans= m_active_trans;
+
bool contact_ndb= m_lock.type < TL_WRITE_ALLOW_WRITE;
do {
DBUG_PRINT("info", ("Call nextResult, contact_ndb: %d", contact_ndb));
@@ -1382,60 +1533,95 @@ inline int ha_ndbcluster::next_result(byte *buf)
if (m_ops_pending && m_blobs_pending)
{
if (execute_no_commit(this,trans) != 0)
- DBUG_RETURN(ndb_err(trans));
+ DBUG_RETURN(ndb_err(trans));
m_ops_pending= 0;
m_blobs_pending= FALSE;
}
- check= cursor->nextResult(contact_ndb, m_force_send);
- if (check == 0)
+
+ if ((check= cursor->nextResult(contact_ndb, m_force_send)) == 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
+ 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", m_ops_pending));
if (m_ops_pending)
{
- // if (current_thd->transaction.on)
- if (m_transaction_on)
- {
- if (execute_no_commit(this,trans) != 0)
- DBUG_RETURN(ndb_err(trans));
- }
- else
- {
- if (execute_commit(this,trans) != 0)
- DBUG_RETURN(ndb_err(trans));
- int res= trans->restart();
- DBUG_ASSERT(res == 0);
- }
- m_ops_pending= 0;
+ if (m_transaction_on)
+ {
+ if (execute_no_commit(this,trans) != 0)
+ DBUG_RETURN(-1);
+ }
+ else
+ {
+ if (execute_commit(this,trans) != 0)
+ DBUG_RETURN(-1);
+ if (trans->restart() != 0)
+ {
+ DBUG_ASSERT(0);
+ DBUG_RETURN(-1);
+ }
+ }
+ m_ops_pending= 0;
}
-
contact_ndb= (check == 2);
}
+ else
+ {
+ DBUG_RETURN(-1);
+ }
} while (check == 2);
-
- table->status= STATUS_NOT_FOUND;
- if (check == -1)
- DBUG_RETURN(ndb_err(trans));
- // No more records
- DBUG_PRINT("info", ("No more records"));
- DBUG_RETURN(HA_ERR_END_OF_FILE);
+ DBUG_RETURN(1);
+}
+
+/*
+ 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 res;
+ DBUG_ENTER("next_result");
+
+ if (!m_active_cursor)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ if ((res= fetch_next(m_active_cursor)) == 0)
+ {
+ DBUG_PRINT("info", ("One more record found"));
+
+ unpack_record(buf);
+ table->status= 0;
+ DBUG_RETURN(0);
+ }
+ else if (res == 1)
+ {
+ // No more records
+ table->status= STATUS_NOT_FOUND;
+
+ DBUG_PRINT("info", ("No more records"));
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
+ else
+ {
+ DBUG_RETURN(ndb_err(m_active_trans));
+ }
}
/*
@@ -1443,7 +1629,8 @@ inline int ha_ndbcluster::next_result(byte *buf)
*/
int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
- const key_range *keys[2])
+ const key_range *keys[2],
+ uint range_no)
{
const KEY *const key_info= table->key_info + active_index;
const uint key_parts= key_info->key_parts;
@@ -1476,7 +1663,9 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
{
KEY_PART_INFO *key_part= &key_info->key_part[i];
Field *field= key_part->field;
+#ifndef DBUG_OFF
uint part_len= key_part->length;
+#endif
uint part_store_len= key_part->store_length;
// Info about each key part
struct part_st {
@@ -1491,7 +1680,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
for (j= 0; j <= 1; j++)
{
- struct part_st &p = part[j];
+ struct part_st &p= part[j];
p.key= NULL;
p.bound_type= -1;
if (tot_len < key_tot_len[j])
@@ -1510,6 +1699,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
case HA_READ_KEY_EXACT:
p.bound_type= NdbIndexScanOperation::BoundEQ;
break;
+ // ascending
case HA_READ_KEY_OR_NEXT:
p.bound_type= NdbIndexScanOperation::BoundLE;
break;
@@ -1519,6 +1709,19 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
else
p.bound_type= NdbIndexScanOperation::BoundLT;
break;
+ // descending
+ case HA_READ_PREFIX_LAST: // weird
+ p.bound_type= NdbIndexScanOperation::BoundEQ;
+ break;
+ case HA_READ_PREFIX_LAST_OR_PREV: // weird
+ p.bound_type= NdbIndexScanOperation::BoundGE;
+ break;
+ case HA_READ_BEFORE_KEY:
+ if (! p.part_last)
+ p.bound_type= NdbIndexScanOperation::BoundGE;
+ else
+ p.bound_type= NdbIndexScanOperation::BoundGT;
+ break;
default:
break;
}
@@ -1526,6 +1729,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
if (j == 1) {
switch (p.key->flag)
{
+ // ascending
case HA_READ_BEFORE_KEY:
if (! p.part_last)
p.bound_type= NdbIndexScanOperation::BoundGE;
@@ -1537,14 +1741,16 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
break;
default:
break;
+ // descending strangely sets no end key
}
}
if (p.bound_type == -1)
{
DBUG_PRINT("error", ("key %d unknown flag %d", j, p.key->flag));
- DBUG_ASSERT(false);
+ DBUG_ASSERT(FALSE);
// Stop setting bounds but continue with what we have
+ op->end_of_bound(range_no);
DBUG_RETURN(0);
}
}
@@ -1570,7 +1776,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
for (j= 0; j <= 1; j++)
{
- struct part_st &p = part[j];
+ struct part_st &p= part[j];
// Set bound if not done with this key
if (p.key != NULL)
{
@@ -1580,79 +1786,38 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
// Set bound if not cancelled via type -1
if (p.bound_type != -1)
- {
- if (op->setBound(i, p.bound_type, p.bound_ptr))
+ {
+ const char* ptr= p.bound_ptr;
+ char buf[256];
+ shrink_varchar(field, ptr, buf);
+ if (op->setBound(i, p.bound_type, ptr))
ERR_RETURN(op->getNdbError());
- }
+ }
}
}
tot_len+= part_store_len;
}
+ op->end_of_bound(range_no);
DBUG_RETURN(0);
}
-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) ||
- m_retrieve_all_fields)
- {
- if (get_ndb_value(op, field, i, buf))
- ERR_RETURN(op->getNdbError());
- }
- else
- {
- m_value[i].ptr= NULL;
- }
- }
-
- if (table->primary_key == MAX_KEY)
- {
- DBUG_PRINT("info", ("Getting hidden key"));
- // Scanning table with no primary key
- int hidden_no= table->fields;
-#ifndef DBUG_OFF
- const NDBTAB *tab= (const NDBTAB *) m_table;
- if (!tab->getColumn(hidden_no))
- DBUG_RETURN(1);
-#endif
- if (get_ndb_value(op, NULL, hidden_no, NULL))
- ERR_RETURN(op->getNdbError());
- }
-
- if (execute_no_commit(this,trans) != 0)
- DBUG_RETURN(ndb_err(trans));
- DBUG_PRINT("exit", ("Scan started successfully"));
- DBUG_RETURN(next_result(buf));
-}
-
/*
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)
+ const key_range *end_key,
+ bool sorted, bool descending, byte* buf)
{
+ int res;
bool restart;
- NdbConnection *trans= m_active_trans;
- NdbResultSet *cursor;
+ NdbTransaction *trans= m_active_trans;
NdbIndexScanOperation *op;
- DBUG_ENTER("ordered_index_scan");
- DBUG_PRINT("enter", ("index: %u, sorted: %d", active_index, sorted));
+ DBUG_ENTER("ha_ndbcluster::ordered_index_scan");
+ DBUG_PRINT("enter", ("index: %u, sorted: %d, descending: %d",
+ active_index, sorted, descending));
DBUG_PRINT("enter", ("Starting new ordered scan on %s", m_tabname));
// Check that sorted seems to be initialised
@@ -1660,130 +1825,46 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
if (m_active_cursor == 0)
{
- restart= false;
+ restart= FALSE;
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
if (!(op= trans->getNdbIndexScanOperation((NDBINDEX *)
- m_index[active_index].index,
- (const NDBTAB *) m_table)) ||
- !(cursor= op->readTuples(lm, 0, parallelism, sorted)))
+ m_index[active_index].index,
+ (const NDBTAB *) m_table)) ||
+ op->readTuples(lm, 0, parallelism, sorted, descending))
ERR_RETURN(trans->getNdbError());
- m_active_cursor= cursor;
+ m_active_cursor= op;
} else {
- restart= true;
- op= (NdbIndexScanOperation*)m_active_cursor->getOperation();
+ restart= TRUE;
+ op= (NdbIndexScanOperation*)m_active_cursor;
DBUG_ASSERT(op->getSorted() == sorted);
DBUG_ASSERT(op->getLockMode() ==
- (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type));
- if(op->reset_bounds(m_force_send))
+ (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type));
+ if (op->reset_bounds(m_force_send))
DBUG_RETURN(ndb_err(m_active_trans));
}
-
+
{
const key_range *keys[2]= { start_key, end_key };
- int ret= set_bounds(op, keys);
- if (ret)
- DBUG_RETURN(ret);
- }
-
- if (!restart)
- {
- DBUG_RETURN(define_read_attrs(buf, op));
- }
- else
- {
- if (execute_no_commit(this,trans) != 0)
- DBUG_RETURN(ndb_err(trans));
-
- DBUG_RETURN(next_result(buf));
+ res= set_bounds(op, keys);
+ if (res)
+ DBUG_RETURN(res);
}
-}
-
-/*
- 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)
-{
- NdbConnection *trans= m_active_trans;
- NdbResultSet *cursor;
- NdbScanOperation *op;
- DBUG_ENTER("filtered_scan");
- DBUG_PRINT("enter", ("key_len: %u, index: %u",
- key_len, active_index));
- DBUG_DUMP("key", (char*)key, key_len);
- DBUG_PRINT("info", ("Starting a new filtered scan on %s",
- m_tabname));
-
- NdbOperation::LockMode lm=
- (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
- if (!(op= trans->getNdbScanOperation((const NDBTAB *) m_table)) ||
- !(cursor= op->readTuples(lm, 0, parallelism)))
- ERR_RETURN(trans->getNdbError());
- m_active_cursor= cursor;
+ if (!restart && generate_scan_filter(m_cond_stack, op))
+ DBUG_RETURN(ndb_err(trans));
+ if (!restart && (res= define_read_attrs(buf, op)))
{
- // Start scan filter
- NdbScanFilter sf(op);
- sf.begin();
-
- // Set filter using the supplied key data
- byte *key_ptr= (byte *) key;
- uint tot_len= 0;
- KEY* key_info= table->key_info + active_index;
- for (uint k= 0; k < key_info->key_parts; k++)
- {
- KEY_PART_INFO* key_part= key_info->key_part+k;
- Field* field= key_part->field;
- uint ndb_fieldnr= key_part->fieldnr-1;
- DBUG_PRINT("key_part", ("fieldnr: %d", ndb_fieldnr));
- //const NDBCOL *col= ((const NDBTAB *) m_table)->getColumn(ndb_fieldnr);
- uint32 field_len= field->pack_length();
- DBUG_DUMP("key", (char*)key, field_len);
-
- DBUG_PRINT("info", ("Column %s, type: %d, len: %d",
- field->field_name, field->real_type(), field_len));
-
- // Define scan filter
- if (field->real_type() == MYSQL_TYPE_STRING)
- sf.eq(ndb_fieldnr, key_ptr, field_len);
- else
- {
- if (field_len == 8)
- sf.eq(ndb_fieldnr, (Uint64)*key_ptr);
- else if (field_len <= 4)
- sf.eq(ndb_fieldnr, (Uint32)*key_ptr);
- else
- DBUG_RETURN(1);
- }
-
- key_ptr += field_len;
- tot_len += field_len;
-
- if (tot_len >= key_len)
- break;
- }
- // End scan filter
- sf.end();
+ DBUG_RETURN(res);
}
- DBUG_RETURN(define_read_attrs(buf, op));
-}
-
+ if (execute_no_commit(this,trans) != 0)
+ DBUG_RETURN(ndb_err(trans));
+
+ DBUG_RETURN(next_result(buf));
+}
/*
Start full table scan in NDB
@@ -1791,10 +1872,9 @@ int ha_ndbcluster::filtered_scan(const byte *key, uint key_len,
int ha_ndbcluster::full_table_scan(byte *buf)
{
- uint i;
- NdbResultSet *cursor;
+ int res;
NdbScanOperation *op;
- NdbConnection *trans= m_active_trans;
+ NdbTransaction *trans= m_active_trans;
DBUG_ENTER("full_table_scan");
DBUG_PRINT("enter", ("Starting new scan on %s", m_tabname));
@@ -1802,10 +1882,18 @@ int ha_ndbcluster::full_table_scan(byte *buf)
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
if (!(op=trans->getNdbScanOperation((const NDBTAB *) m_table)) ||
- !(cursor= op->readTuples(lm, 0, parallelism)))
+ op->readTuples(lm, 0, parallelism))
ERR_RETURN(trans->getNdbError());
- m_active_cursor= cursor;
- DBUG_RETURN(define_read_attrs(buf, op));
+ m_active_cursor= op;
+ if (generate_scan_filter(m_cond_stack, op))
+ DBUG_RETURN(ndb_err(trans));
+ if ((res= define_read_attrs(buf, op)))
+ DBUG_RETURN(res);
+
+ if (execute_no_commit(this,trans) != 0)
+ DBUG_RETURN(ndb_err(trans));
+ DBUG_PRINT("exit", ("Scan started successfully"));
+ DBUG_RETURN(next_result(buf));
}
/*
@@ -1815,25 +1903,27 @@ int ha_ndbcluster::write_row(byte *record)
{
bool has_auto_increment;
uint i;
- NdbConnection *trans= m_active_trans;
+ NdbTransaction *trans= m_active_trans;
NdbOperation *op;
int res;
+ THD *thd= current_thd;
+
DBUG_ENTER("write_row");
- if(m_ignore_dup_key && table->primary_key != MAX_KEY)
+ if (m_ignore_dup_key && table->s->primary_key != MAX_KEY)
{
int peek_res= peek_row(record);
if (!peek_res)
{
- m_dupkey= table->primary_key;
+ m_dupkey= table->s->primary_key;
DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
}
if (peek_res != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(peek_res);
}
-
- statistic_increment(ha_write_count,&LOCK_status);
+
+ statistic_increment(thd->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
has_auto_increment= (table->next_number_field && record == table->record[0]);
@@ -1845,7 +1935,7 @@ int ha_ndbcluster::write_row(byte *record)
if (res != 0)
ERR_RETURN(trans->getNdbError());
- if (table->primary_key == MAX_KEY)
+ if (table->s->primary_key == MAX_KEY)
{
// Table has hidden primary key
Ndb *ndb= get_ndb();
@@ -1858,7 +1948,7 @@ int ha_ndbcluster::write_row(byte *record)
ndb->getNdbError().status == NdbError::TemporaryError);
if (auto_value == NDB_FAILED_AUTO_INCREMENT)
ERR_RETURN(ndb->getNdbError());
- if (set_hidden_key(op, table->fields, (const byte*)&auto_value))
+ if (set_hidden_key(op, table->s->fields, (const byte*)&auto_value))
ERR_RETURN(op->getNdbError());
}
else
@@ -1867,8 +1957,12 @@ int ha_ndbcluster::write_row(byte *record)
if (has_auto_increment)
{
+ THD *thd= table->in_use;
+
m_skip_auto_increment= FALSE;
update_auto_increment();
+ /* Ensure that handler is always called for auto_increment values */
+ thd->next_insert_id= 0;
m_skip_auto_increment= !auto_increment_column_changed;
}
@@ -1878,17 +1972,19 @@ int ha_ndbcluster::write_row(byte *record)
// Set non-key attribute(s)
bool set_blob_value= FALSE;
- for (i= 0; i < table->fields; i++)
+ for (i= 0; i < table->s->fields; i++)
{
Field *field= table->field[i];
if (!(field->flags & PRI_KEY_FLAG) &&
- set_ndb_value(op, field, i, &set_blob_value))
+ set_ndb_value(op, field, i, &set_blob_value))
{
m_skip_auto_increment= TRUE;
ERR_RETURN(op->getNdbError());
}
}
+ m_rows_changed++;
+
/*
Execute write operation
NOTE When doing inserts with many values in
@@ -1904,33 +2000,34 @@ int ha_ndbcluster::write_row(byte *record)
m_primary_key_update ||
set_blob_value)
{
- THD *thd= current_thd;
// Send rows to NDB
DBUG_PRINT("info", ("Sending inserts to NDB, "\
- "rows_inserted:%d, bulk_insert_rows: %d",
- (int)m_rows_inserted, (int)m_bulk_insert_rows));
+ "rows_inserted:%d, bulk_insert_rows: %d",
+ (int)m_rows_inserted, (int)m_bulk_insert_rows));
m_bulk_insert_not_flushed= FALSE;
- // if (thd->transaction.on)
if (m_transaction_on)
{
if (execute_no_commit(this,trans) != 0)
{
- m_skip_auto_increment= TRUE;
- no_uncommitted_rows_execute_failure();
- DBUG_RETURN(ndb_err(trans));
+ m_skip_auto_increment= TRUE;
+ no_uncommitted_rows_execute_failure();
+ DBUG_RETURN(ndb_err(trans));
}
}
else
{
if (execute_commit(this,trans) != 0)
{
- m_skip_auto_increment= TRUE;
- no_uncommitted_rows_execute_failure();
- DBUG_RETURN(ndb_err(trans));
+ m_skip_auto_increment= TRUE;
+ no_uncommitted_rows_execute_failure();
+ DBUG_RETURN(ndb_err(trans));
+ }
+ if (trans->restart() != 0)
+ {
+ DBUG_ASSERT(0);
+ DBUG_RETURN(-1);
}
- int res= trans->restart();
- DBUG_ASSERT(res == 0);
}
}
if ((has_auto_increment) && (m_skip_auto_increment))
@@ -1938,11 +2035,11 @@ int ha_ndbcluster::write_row(byte *record)
Ndb *ndb= get_ndb();
Uint64 next_val= (Uint64) table->next_number_field->val_int() + 1;
DBUG_PRINT("info",
- ("Trying to set next auto increment value to %lu",
+ ("Trying to set next auto increment value to %lu",
(ulong) next_val));
if (ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, TRUE))
DBUG_PRINT("info",
- ("Setting next auto increment value to %u", next_val));
+ ("Setting next auto increment value to %u", next_val));
}
m_skip_auto_increment= TRUE;
@@ -1953,7 +2050,7 @@ int ha_ndbcluster::write_row(byte *record)
/* Compare if a key in a row has changed */
int ha_ndbcluster::key_cmp(uint keynr, const byte * old_row,
- const byte * new_row)
+ const byte * new_row)
{
KEY_PART_INFO *key_part=table->key_info[keynr].key_part;
KEY_PART_INFO *end=key_part+table->key_info[keynr].key_parts;
@@ -1963,22 +2060,22 @@ int ha_ndbcluster::key_cmp(uint keynr, const byte * old_row,
if (key_part->null_bit)
{
if ((old_row[key_part->null_offset] & key_part->null_bit) !=
- (new_row[key_part->null_offset] & key_part->null_bit))
- return 1;
+ (new_row[key_part->null_offset] & key_part->null_bit))
+ return 1;
}
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
if (key_part->field->cmp_binary((char*) (old_row + key_part->offset),
- (char*) (new_row + key_part->offset),
- (ulong) key_part->length))
- return 1;
+ (char*) (new_row + key_part->offset),
+ (ulong) key_part->length))
+ return 1;
}
else
{
if (memcmp(old_row+key_part->offset, new_row+key_part->offset,
- key_part->length))
- return 1;
+ key_part->length))
+ return 1;
}
}
return 0;
@@ -1991,13 +2088,13 @@ int ha_ndbcluster::key_cmp(uint keynr, const byte * old_row,
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;
+ NdbTransaction *trans= m_active_trans;
+ NdbScanOperation* cursor= m_active_cursor;
NdbOperation *op;
uint i;
DBUG_ENTER("update_row");
- statistic_increment(ha_update_count,&LOCK_status);
+ statistic_increment(thd->status_var.ha_update_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
{
table->timestamp_field->set_time();
@@ -2006,8 +2103,8 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
}
/* Check for update of primary key for special handling */
- if ((table->primary_key != MAX_KEY) &&
- (key_cmp(table->primary_key, old_data, new_data)))
+ if ((table->s->primary_key != MAX_KEY) &&
+ (key_cmp(table->s->primary_key, old_data, new_data)))
{
int read_res, insert_res, delete_res, undo_res;
@@ -2064,7 +2161,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
the active record in cursor
*/
DBUG_PRINT("info", ("Calling updateTuple on cursor"));
- if (!(op= cursor->updateTuple()))
+ if (!(op= cursor->updateCurrentTuple()))
ERR_RETURN(trans->getNdbError());
m_ops_pending++;
if (uses_blob_value(FALSE))
@@ -2073,39 +2170,41 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
else
{
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
- op->updateTuple() != 0)
+ op->updateTuple() != 0)
ERR_RETURN(trans->getNdbError());
- if (table->primary_key == MAX_KEY)
+ if (table->s->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].rec;
+ uint no_fields= table->s->fields;
+ const NdbRecAttr* rec= m_value[no_fields].rec;
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());
+ ERR_RETURN(op->getNdbError());
}
else
{
int res;
if ((res= set_primary_key_from_record(op, old_data)))
- DBUG_RETURN(res);
+ DBUG_RETURN(res);
}
}
+ m_rows_changed++;
+
// Set non-key attribute(s)
- for (i= 0; i < table->fields; i++)
+ for (i= 0; i < table->s->fields; i++)
{
Field *field= table->field[i];
if (((thd->query_id == field->query_id) || m_retrieve_all_fields) &&
(!(field->flags & PRI_KEY_FLAG)) &&
- set_ndb_value(op, field, i))
+ set_ndb_value(op, field, i))
ERR_RETURN(op->getNdbError());
}
@@ -2125,12 +2224,14 @@ 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;
+ THD *thd= current_thd;
+ NdbTransaction *trans= m_active_trans;
+ NdbScanOperation* cursor= m_active_cursor;
NdbOperation *op;
DBUG_ENTER("delete_row");
- statistic_increment(ha_delete_count,&LOCK_status);
+ statistic_increment(thd->status_var.ha_delete_count,&LOCK_status);
+ m_rows_changed++;
if (cursor)
{
@@ -2142,7 +2243,7 @@ int ha_ndbcluster::delete_row(const byte *record)
the active record in cursor
*/
DBUG_PRINT("info", ("Calling deleteTuple on cursor"));
- if (cursor->deleteTuple() != 0)
+ if (cursor->deleteCurrentTuple() != 0)
ERR_RETURN(trans->getNdbError());
m_ops_pending++;
@@ -2156,21 +2257,21 @@ int ha_ndbcluster::delete_row(const byte *record)
{
if (!(op=trans->getNdbOperation((const NDBTAB *) m_table)) ||
- op->deleteTuple() != 0)
+ op->deleteTuple() != 0)
ERR_RETURN(trans->getNdbError());
no_uncommitted_rows_update(-1);
- if (table->primary_key == MAX_KEY)
+ if (table->s->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].rec;
+ uint no_fields= table->s->fields;
+ const NdbRecAttr* rec= m_value[no_fields].rec;
DBUG_ASSERT(rec != NULL);
if (set_hidden_key(op, no_fields, rec->aRef()))
- ERR_RETURN(op->getNdbError());
+ ERR_RETURN(op->getNdbError());
}
else
{
@@ -2179,7 +2280,7 @@ int ha_ndbcluster::delete_row(const byte *record)
return res;
}
}
-
+
// Execute delete operation
if (execute_no_commit(this,trans) != 0) {
no_uncommitted_rows_execute_failure();
@@ -2193,7 +2294,7 @@ int ha_ndbcluster::delete_row(const byte *record)
SYNOPSIS
unpack_record()
- buf Buffer to store read row
+ buf Buffer to store read row
NOTE
The data for each row is read directly into the
@@ -2208,10 +2309,12 @@ void ha_ndbcluster::unpack_record(byte* buf)
Field **field, **end;
NdbValue *value= m_value;
DBUG_ENTER("unpack_record");
+
+ end= table->field + table->s->fields;
// Set null flag(s)
- bzero(buf, table->null_bytes);
- for (field= table->field, end= field+table->fields;
+ bzero(buf, table->s->null_bytes);
+ for (field= table->field;
field < end;
field++, value++)
{
@@ -2221,33 +2324,56 @@ void ha_ndbcluster::unpack_record(byte* buf)
{
if ((*value).rec->isNULL())
(*field)->set_null(row_offset);
+ else if ((*field)->type() == MYSQL_TYPE_BIT)
+ {
+ uint pack_len= (*field)->pack_length();
+ if (pack_len < 5)
+ {
+ DBUG_PRINT("info", ("bit field H'%.8X",
+ (*value).rec->u_32_value()));
+ ((Field_bit *) *field)->store((longlong)
+ (*value).rec->u_32_value(),
+ FALSE);
+ }
+ else
+ {
+ DBUG_PRINT("info", ("bit field H'%.8X%.8X",
+ *(Uint32 *)(*value).rec->aRef(),
+ *((Uint32 *)(*value).rec->aRef()+1)));
+ ((Field_bit *) *field)->store((longlong)
+ (*value).rec->u_64_value(), TRUE);
+ }
+ }
}
else
{
NdbBlob* ndb_blob= (*value).blob;
bool isNull= TRUE;
- int ret= ndb_blob->getNull(isNull);
+#ifndef DBUG_OFF
+ int ret=
+#endif
+ ndb_blob->getNull(isNull);
DBUG_ASSERT(ret == 0);
if (isNull)
- (*field)->set_null(row_offset);
+ (*field)->set_null(row_offset);
}
}
}
-
+
#ifndef DBUG_OFF
// Read and print all values that was fetched
- if (table->primary_key == MAX_KEY)
+ if (table->s->primary_key == MAX_KEY)
{
// Table with hidden primary key
- int hidden_no= table->fields;
+ int hidden_no= table->s->fields;
const NDBTAB *tab= (const NDBTAB *) m_table;
const NDBCOL *hidden_col= tab->getColumn(hidden_no);
- NdbRecAttr* rec= m_value[hidden_no].rec;
+ const NdbRecAttr* rec= m_value[hidden_no].rec;
DBUG_ASSERT(rec);
DBUG_PRINT("hidden", ("%d: %s \"%llu\"", hidden_no,
hidden_col->getName(), rec->u_64_value()));
}
- print_results();
+ //print_results();
#endif
DBUG_VOID_RETURN;
}
@@ -2258,167 +2384,59 @@ void ha_ndbcluster::unpack_record(byte* buf)
void ha_ndbcluster::print_results()
{
- const NDBTAB *tab= (const NDBTAB*) m_table;
DBUG_ENTER("print_results");
#ifndef DBUG_OFF
+ const NDBTAB *tab= (const NDBTAB*) m_table;
+
if (!_db_on_)
DBUG_VOID_RETURN;
-
- for (uint f=0; f<table->fields;f++)
+
+ char buf_type[MAX_FIELD_WIDTH], buf_val[MAX_FIELD_WIDTH];
+ String type(buf_type, sizeof(buf_type), &my_charset_bin);
+ String val(buf_val, sizeof(buf_val), &my_charset_bin);
+ for (uint f= 0; f < table->s->fields; f++)
{
+ /* Use DBUG_PRINT since DBUG_FILE cannot be filtered out */
+ char buf[2000];
Field *field;
- const NDBCOL *col;
+ void* ptr;
NdbValue value;
+ buf[0]= 0;
+ field= table->field[f];
if (!(value= m_value[f]).ptr)
{
- fprintf(DBUG_FILE, "Field %d was not read\n", f);
- continue;
+ strmov(buf, "not read");
+ goto print_value;
}
- field= table->field[f];
- DBUG_DUMP("field->ptr", (char*)field->ptr, field->pack_length());
- col= tab->getColumn(f);
- fprintf(DBUG_FILE, "%d: %s\t", f, col->getName());
- NdbBlob *ndb_blob= NULL;
+ ptr= field->ptr;
+
if (! (field->flags & BLOB_FLAG))
{
if (value.rec->isNULL())
{
- fprintf(DBUG_FILE, "NULL\n");
- continue;
+ strmov(buf, "NULL");
+ goto print_value;
}
+ type.length(0);
+ val.length(0);
+ field->sql_type(type);
+ field->val_str(&val);
+ my_snprintf(buf, sizeof(buf), "%s %s", type.c_ptr(), val.c_ptr());
}
else
{
- ndb_blob= value.blob;
+ NdbBlob *ndb_blob= value.blob;
bool isNull= TRUE;
ndb_blob->getNull(isNull);
- if (isNull) {
- fprintf(DBUG_FILE, "NULL\n");
- continue;
- }
+ if (isNull)
+ strmov(buf, "NULL");
}
- switch (col->getType()) {
- case NdbDictionary::Column::Tinyint: {
- char value= *field->ptr;
- fprintf(DBUG_FILE, "Tinyint\t%d", value);
- break;
- }
- case NdbDictionary::Column::Tinyunsigned: {
- unsigned char value= *field->ptr;
- fprintf(DBUG_FILE, "Tinyunsigned\t%u", value);
- break;
- }
- case NdbDictionary::Column::Smallint: {
- short value= *field->ptr;
- fprintf(DBUG_FILE, "Smallint\t%d", value);
- break;
- }
- case NdbDictionary::Column::Smallunsigned: {
- unsigned short value= *field->ptr;
- fprintf(DBUG_FILE, "Smallunsigned\t%u", value);
- break;
- }
- case NdbDictionary::Column::Mediumint: {
- byte value[3];
- memcpy(value, field->ptr, 3);
- fprintf(DBUG_FILE, "Mediumint\t%d,%d,%d", value[0], value[1], value[2]);
- break;
- }
- case NdbDictionary::Column::Mediumunsigned: {
- byte value[3];
- memcpy(value, field->ptr, 3);
- fprintf(DBUG_FILE, "Mediumunsigned\t%u,%u,%u", value[0], value[1], value[2]);
- break;
- }
- case NdbDictionary::Column::Int: {
- fprintf(DBUG_FILE, "Int\t%lld", field->val_int());
- break;
- }
- case NdbDictionary::Column::Unsigned: {
- Uint32 value= (Uint32) *field->ptr;
- fprintf(DBUG_FILE, "Unsigned\t%u", value);
- break;
- }
- case NdbDictionary::Column::Bigint: {
- Int64 value= (Int64) *field->ptr;
- fprintf(DBUG_FILE, "Bigint\t%lld", value);
- break;
- }
- case NdbDictionary::Column::Bigunsigned: {
- Uint64 value= (Uint64) *field->ptr;
- fprintf(DBUG_FILE, "Bigunsigned\t%llu", value);
- break;
- }
- case NdbDictionary::Column::Float: {
- float value= (float) *field->ptr;
- fprintf(DBUG_FILE, "Float\t%f", value);
- break;
- }
- case NdbDictionary::Column::Double: {
- double value= (double) *field->ptr;
- fprintf(DBUG_FILE, "Double\t%f", value);
- break;
- }
- case NdbDictionary::Column::Olddecimal: {
- char *value= field->ptr;
- fprintf(DBUG_FILE, "Olddecimal\t'%-*s'", field->pack_length(), value);
- break;
- }
- case NdbDictionary::Column::Olddecimalunsigned: {
- char *value= field->ptr;
- fprintf(DBUG_FILE, "Olddecimalunsigned\t'%-*s'", field->pack_length(), value);
- break;
- }
- case NdbDictionary::Column::Char:{
- const char *value= (char *) field->ptr;
- fprintf(DBUG_FILE, "Char\t'%.*s'", field->pack_length(), value);
- break;
- }
- case NdbDictionary::Column::Varchar:
- case NdbDictionary::Column::Binary:
- case NdbDictionary::Column::Varbinary: {
- const char *value= (char *) field->ptr;
- fprintf(DBUG_FILE, "Var\t'%.*s'", field->pack_length(), value);
- break;
- }
- case NdbDictionary::Column::Datetime: {
- Uint64 value= (Uint64) *field->ptr;
- fprintf(DBUG_FILE, "Datetime\t%llu", value);
- break;
- }
- case NdbDictionary::Column::Date: {
- Uint64 value= (Uint64) *field->ptr;
- fprintf(DBUG_FILE, "Date\t%llu", value);
- break;
- }
- case NdbDictionary::Column::Time: {
- Uint64 value= (Uint64) *field->ptr;
- fprintf(DBUG_FILE, "Time\t%llu", value);
- break;
- }
- case NdbDictionary::Column::Blob: {
- Uint64 len= 0;
- ndb_blob->getLength(len);
- fprintf(DBUG_FILE, "Blob\t[len=%u]", (unsigned)len);
- break;
- }
- case NdbDictionary::Column::Text: {
- Uint64 len= 0;
- ndb_blob->getLength(len);
- fprintf(DBUG_FILE, "Text\t[len=%u]", (unsigned)len);
- break;
- }
- case NdbDictionary::Column::Undefined:
- default:
- fprintf(DBUG_FILE, "Unknown type: %d", col->getType());
- break;
- }
- fprintf(DBUG_FILE, "\n");
-
+print_value:
+ DBUG_PRINT("value", ("%u,%s: %s", f, field->field_name, buf));
}
#endif
DBUG_VOID_RETURN;
@@ -2427,7 +2445,7 @@ void ha_ndbcluster::print_results()
int ha_ndbcluster::index_init(uint index)
{
- DBUG_ENTER("index_init");
+ DBUG_ENTER("ha_ndbcluster::index_init");
DBUG_PRINT("enter", ("index: %u", index));
DBUG_RETURN(handler::index_init(index));
}
@@ -2435,7 +2453,7 @@ int ha_ndbcluster::index_init(uint index)
int ha_ndbcluster::index_end()
{
- DBUG_ENTER("index_end");
+ DBUG_ENTER("ha_ndbcluster::index_end");
DBUG_RETURN(close_scan());
}
@@ -2447,14 +2465,14 @@ int
check_null_in_key(const KEY* key_info, const byte *key, uint key_len)
{
KEY_PART_INFO *curr_part, *end_part;
- const byte* end_ptr = key + key_len;
+ const byte* end_ptr= key + key_len;
curr_part= key_info->key_part;
end_part= curr_part + key_info->key_parts;
for (; curr_part != end_part && key < end_ptr; curr_part++)
{
- if(curr_part->null_bit && *key)
+ if (curr_part->null_bit && *key)
return 1;
key += curr_part->store_length;
@@ -2463,23 +2481,23 @@ check_null_in_key(const KEY* key_info, const byte *key, uint key_len)
}
int ha_ndbcluster::index_read(byte *buf,
- const byte *key, uint key_len,
- enum ha_rkey_function find_flag)
+ const byte *key, uint key_len,
+ enum ha_rkey_function find_flag)
{
- DBUG_ENTER("index_read");
+ DBUG_ENTER("ha_ndbcluster::index_read");
DBUG_PRINT("enter", ("active_index: %u, key_len: %u, find_flag: %d",
active_index, key_len, find_flag));
int error;
- ndb_index_type type = get_index_type(active_index);
- const KEY* key_info = table->key_info+active_index;
+ ndb_index_type type= get_index_type(active_index);
+ const KEY* key_info= table->key_info+active_index;
switch (type){
case PRIMARY_KEY_ORDERED_INDEX:
case PRIMARY_KEY_INDEX:
if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len)
{
- if(m_active_cursor && (error= close_scan()))
- DBUG_RETURN(error);
+ if (m_active_cursor && (error= close_scan()))
+ DBUG_RETURN(error);
DBUG_RETURN(pk_read(key, key_len, buf));
}
else if (type == PRIMARY_KEY_INDEX)
@@ -2490,10 +2508,10 @@ int ha_ndbcluster::index_read(byte *buf,
case UNIQUE_ORDERED_INDEX:
case UNIQUE_INDEX:
if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len &&
- !check_null_in_key(key_info, key, key_len))
+ !check_null_in_key(key_info, key, key_len))
{
- if(m_active_cursor && (error= close_scan()))
- DBUG_RETURN(error);
+ if (m_active_cursor && (error= close_scan()))
+ DBUG_RETURN(error);
DBUG_RETURN(unique_index_read(key, key_len, buf));
}
else if (type == UNIQUE_INDEX)
@@ -2511,20 +2529,31 @@ int ha_ndbcluster::index_read(byte *buf,
}
key_range start_key;
- start_key.key = key;
- start_key.length = key_len;
- start_key.flag = find_flag;
- error= ordered_index_scan(&start_key, 0, TRUE, buf);
+ start_key.key= key;
+ start_key.length= key_len;
+ start_key.flag= find_flag;
+ bool descending= FALSE;
+ switch (find_flag) {
+ case HA_READ_KEY_OR_PREV:
+ case HA_READ_BEFORE_KEY:
+ case HA_READ_PREFIX_LAST:
+ case HA_READ_PREFIX_LAST_OR_PREV:
+ descending= TRUE;
+ break;
+ default:
+ break;
+ }
+ error= ordered_index_scan(&start_key, 0, TRUE, descending, buf);
DBUG_RETURN(error == HA_ERR_END_OF_FILE ? HA_ERR_KEY_NOT_FOUND : error);
}
int ha_ndbcluster::index_read_idx(byte *buf, uint index_no,
- const byte *key, uint key_len,
- enum ha_rkey_function find_flag)
+ const byte *key, uint key_len,
+ enum ha_rkey_function find_flag)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
- DBUG_ENTER("index_read_idx");
+ statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
+ DBUG_ENTER("ha_ndbcluster::index_read_idx");
DBUG_PRINT("enter", ("index_no: %u, key_len: %u", index_no, key_len));
index_init(index_no);
DBUG_RETURN(index_read(buf, key, key_len, find_flag));
@@ -2533,72 +2562,68 @@ int ha_ndbcluster::index_read_idx(byte *buf, uint index_no,
int ha_ndbcluster::index_next(byte *buf)
{
- DBUG_ENTER("index_next");
-
- int error= 1;
- statistic_increment(ha_read_next_count,&LOCK_status);
+ DBUG_ENTER("ha_ndbcluster::index_next");
+ statistic_increment(current_thd->status_var.ha_read_next_count,
+ &LOCK_status);
DBUG_RETURN(next_result(buf));
}
int ha_ndbcluster::index_prev(byte *buf)
{
- DBUG_ENTER("index_prev");
- statistic_increment(ha_read_prev_count,&LOCK_status);
- DBUG_RETURN(1);
+ DBUG_ENTER("ha_ndbcluster::index_prev");
+ statistic_increment(current_thd->status_var.ha_read_prev_count,
+ &LOCK_status);
+ DBUG_RETURN(next_result(buf));
}
int ha_ndbcluster::index_first(byte *buf)
{
- DBUG_ENTER("index_first");
- statistic_increment(ha_read_first_count,&LOCK_status);
+ DBUG_ENTER("ha_ndbcluster::index_first");
+ statistic_increment(current_thd->status_var.ha_read_first_count,
+ &LOCK_status);
// Start the ordered index scan and fetch the first row
// Only HA_READ_ORDER indexes get called by index_first
- DBUG_RETURN(ordered_index_scan(0, 0, TRUE, buf));
+ DBUG_RETURN(ordered_index_scan(0, 0, TRUE, FALSE, buf));
}
int ha_ndbcluster::index_last(byte *buf)
{
- DBUG_ENTER("index_last");
- statistic_increment(ha_read_last_count,&LOCK_status);
- int res;
- if((res= ordered_index_scan(0, 0, TRUE, buf)) == 0){
- NdbResultSet *cursor= m_active_cursor;
- while((res= cursor->nextResult(TRUE, m_force_send)) == 0);
- if(res == 1){
- unpack_record(buf);
- table->status= 0;
- DBUG_RETURN(0);
- }
- }
- DBUG_RETURN(res);
+ DBUG_ENTER("ha_ndbcluster::index_last");
+ statistic_increment(current_thd->status_var.ha_read_last_count,&LOCK_status);
+ DBUG_RETURN(ordered_index_scan(0, 0, TRUE, TRUE, buf));
}
+int ha_ndbcluster::index_read_last(byte * buf, const byte * key, uint key_len)
+{
+ DBUG_ENTER("ha_ndbcluster::index_read_last");
+ DBUG_RETURN(index_read(buf, key, key_len, HA_READ_PREFIX_LAST));
+}
inline
int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
- const key_range *end_key,
- bool eq_range, bool sorted,
- byte* buf)
+ const key_range *end_key,
+ bool eq_r, bool sorted,
+ byte* buf)
{
KEY* key_info;
int error= 1;
DBUG_ENTER("ha_ndbcluster::read_range_first_to_buf");
- DBUG_PRINT("info", ("eq_range: %d, sorted: %d", eq_range, sorted));
+ DBUG_PRINT("info", ("eq_r: %d, sorted: %d", eq_r, sorted));
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)
+ start_key->length == key_info->key_length &&
+ start_key->flag == HA_READ_KEY_EXACT)
{
- if(m_active_cursor && (error= close_scan()))
- DBUG_RETURN(error);
+ if (m_active_cursor && (error= close_scan()))
+ DBUG_RETURN(error);
error= pk_read(start_key->key, start_key->length, buf);
DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
}
@@ -2607,11 +2632,11 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
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 &&
- !check_null_in_key(key_info, start_key->key, start_key->length))
+ start_key->flag == HA_READ_KEY_EXACT &&
+ !check_null_in_key(key_info, start_key->key, start_key->length))
{
- if(m_active_cursor && (error= close_scan()))
- DBUG_RETURN(error);
+ if (m_active_cursor && (error= close_scan()))
+ DBUG_RETURN(error);
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);
}
@@ -2621,23 +2646,23 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
}
// Start the ordered index scan and fetch the first row
- error= ordered_index_scan(start_key, end_key, sorted, buf);
+ error= ordered_index_scan(start_key, end_key, sorted, FALSE, buf);
DBUG_RETURN(error);
}
int ha_ndbcluster::read_range_first(const key_range *start_key,
- const key_range *end_key,
- bool eq_range, bool sorted)
+ const key_range *end_key,
+ bool eq_r, bool sorted)
{
byte* buf= table->record[0];
DBUG_ENTER("ha_ndbcluster::read_range_first");
DBUG_RETURN(read_range_first_to_buf(start_key,
- end_key,
- eq_range,
- sorted,
- buf));
+ end_key,
+ eq_r,
+ sorted,
+ buf));
}
int ha_ndbcluster::read_range_next()
@@ -2649,7 +2674,7 @@ int ha_ndbcluster::read_range_next()
int ha_ndbcluster::rnd_init(bool scan)
{
- NdbResultSet *cursor= m_active_cursor;
+ NdbScanOperation *cursor= m_active_cursor;
DBUG_ENTER("rnd_init");
DBUG_PRINT("enter", ("scan: %d", scan));
// Check if scan is to be restarted
@@ -2657,22 +2682,26 @@ int ha_ndbcluster::rnd_init(bool scan)
{
if (!scan)
DBUG_RETURN(1);
- int res= cursor->restart(m_force_send);
- DBUG_ASSERT(res == 0);
+ if (cursor->restart(m_force_send) != 0)
+ {
+ DBUG_ASSERT(0);
+ DBUG_RETURN(-1);
+ }
}
- index_init(table->primary_key);
+ index_init(table->s->primary_key);
DBUG_RETURN(0);
}
int ha_ndbcluster::close_scan()
{
- NdbResultSet *cursor= m_active_cursor;
- NdbConnection *trans= m_active_trans;
+ NdbTransaction *trans= m_active_trans;
DBUG_ENTER("close_scan");
- if (!cursor)
+ m_multi_cursor= 0;
+ if (!m_active_cursor && !m_multi_cursor)
DBUG_RETURN(1);
+ NdbScanOperation *cursor= m_active_cursor ? m_active_cursor : m_multi_cursor;
if (m_ops_pending)
{
@@ -2688,8 +2717,8 @@ int ha_ndbcluster::close_scan()
m_ops_pending= 0;
}
- cursor->close(m_force_send);
- m_active_cursor= NULL;
+ cursor->close(m_force_send, TRUE);
+ m_active_cursor= m_multi_cursor= NULL;
DBUG_RETURN(0);
}
@@ -2703,7 +2732,8 @@ int ha_ndbcluster::rnd_end()
int ha_ndbcluster::rnd_next(byte *buf)
{
DBUG_ENTER("rnd_next");
- statistic_increment(ha_read_rnd_next_count, &LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
if (!m_active_cursor)
DBUG_RETURN(full_table_scan(buf));
@@ -2721,7 +2751,8 @@ int ha_ndbcluster::rnd_next(byte *buf)
int ha_ndbcluster::rnd_pos(byte *buf, byte *pos)
{
DBUG_ENTER("rnd_pos");
- statistic_increment(ha_read_rnd_count,&LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_rnd_count,
+ &LOCK_status);
// The primary key for the record is stored in pos
// Perform a pk_read using primary key "index"
DBUG_RETURN(pk_read(pos, ref_length, buf));
@@ -2742,9 +2773,9 @@ void ha_ndbcluster::position(const byte *record)
byte *buff;
DBUG_ENTER("position");
- if (table->primary_key != MAX_KEY)
+ if (table->s->primary_key != MAX_KEY)
{
- key_info= table->key_info + table->primary_key;
+ key_info= table->key_info + table->s->primary_key;
key_part= key_info->key_part;
end= key_part + key_info->key_parts;
buff= ref;
@@ -2768,15 +2799,17 @@ void ha_ndbcluster::position(const byte *record)
{
// No primary key, get hidden key
DBUG_PRINT("info", ("Getting hidden key"));
- int hidden_no= table->fields;
- NdbRecAttr* rec= m_value[hidden_no].rec;
+ int hidden_no= table->s->fields;
+ const NdbRecAttr* rec= m_value[hidden_no].rec;
+ memcpy(ref, (const void*)rec->aRef(), ref_length);
+#ifndef DBUG_OFF
const NDBTAB *tab= (const NDBTAB *) m_table;
const NDBCOL *hidden_col= tab->getColumn(hidden_no);
DBUG_ASSERT(hidden_col->getPrimaryKey() &&
hidden_col->getAutoIncrement() &&
rec != NULL &&
ref_length == NDB_HIDDEN_PRIMARY_KEY_LENGTH);
- memcpy(ref, (const void*)rec->aRef(), ref_length);
+#endif
}
DBUG_DUMP("ref", (char*)ref, ref_length);
@@ -2801,19 +2834,28 @@ void ha_ndbcluster::info(uint flag)
if (m_table_info)
{
if (m_ha_not_exact_count)
- records= 100;
+ records= 100;
else
- records_update();
+ records_update();
}
else
{
if ((my_errno= check_ndb_connection()))
DBUG_VOID_RETURN;
Ndb *ndb= get_ndb();
- Uint64 rows= 100;
- if (current_thd->variables.ndb_use_exact_count)
- ndb_get_table_statistics(ndb, m_tabname, &rows, 0);
- records= rows;
+ struct Ndb_statistics stat;
+ if (current_thd->variables.ndb_use_exact_count &&
+ ndb_get_table_statistics(ndb, m_tabname, &stat) == 0)
+ {
+ mean_rec_length= stat.row_size;
+ data_file_length= stat.fragment_memory;
+ records= stat.row_count;
+ }
+ else
+ {
+ mean_rec_length= 0;
+ records= 100;
+ }
}
}
if (flag & HA_STATUS_CONST)
@@ -2853,6 +2895,8 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
break;
case HA_EXTRA_RESET: /* Reset database to after open */
DBUG_PRINT("info", ("HA_EXTRA_RESET"));
+ DBUG_PRINT("info", ("Clearing condition stack"));
+ cond_clear();
break;
case HA_EXTRA_CACHE: /* Cash record in HA_rrnd() */
DBUG_PRINT("info", ("HA_EXTRA_CACHE"));
@@ -2939,8 +2983,8 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
m_ignore_dup_key= FALSE;
break;
case HA_EXTRA_RETRIEVE_ALL_COLS: /* Retrieve all columns, not just those
- where field->query_id is the same as
- the current query id */
+ where field->query_id is the same as
+ the current query id */
DBUG_PRINT("info", ("HA_EXTRA_RETRIEVE_ALL_COLS"));
m_retrieve_all_fields= TRUE;
break;
@@ -2962,6 +3006,8 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
break;
case HA_EXTRA_CHANGE_KEY_TO_DUP:
DBUG_PRINT("info", ("HA_EXTRA_CHANGE_KEY_TO_DUP"));
+ case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
+ DBUG_PRINT("info", ("HA_EXTRA_KEYREAD_PRESERVE_FIELDS"));
break;
}
@@ -3024,7 +3070,7 @@ int ha_ndbcluster::end_bulk_insert()
// Check if last inserts need to be flushed
if (m_bulk_insert_not_flushed)
{
- NdbConnection *trans= m_active_trans;
+ NdbTransaction *trans= m_active_trans;
// Send rows to NDB
DBUG_PRINT("info", ("Sending inserts to NDB, "\
"rows_inserted:%d, bulk_insert_rows: %d",
@@ -3049,19 +3095,16 @@ int ha_ndbcluster::extra_opt(enum ha_extra_function operation, ulong cache_size)
DBUG_RETURN(extra(operation));
}
+static const char *ha_ndbcluster_exts[] = {
+ ha_ndb_ext,
+ NullS
+};
-int ha_ndbcluster::reset()
+const char** ha_ndbcluster::bas_ext() const
{
- DBUG_ENTER("reset");
- // Reset what?
- DBUG_RETURN(1);
+ return ha_ndbcluster_exts;
}
-static const char *ha_ndb_bas_exts[]= { ha_ndb_ext, NullS };
-const char **ha_ndbcluster::bas_ext() const
-{ return ha_ndb_bas_exts; }
-
-
/*
How many seeks it will take to read through the table
This is to be comparable to the number returned by records_in_range so
@@ -3073,7 +3116,7 @@ double ha_ndbcluster::scan_time()
DBUG_ENTER("ha_ndbcluster::scan_time()");
double res= rows2double(records*1000);
DBUG_PRINT("exit", ("table: %s value: %f",
- m_tabname, res));
+ m_tabname, res));
DBUG_RETURN(res);
}
@@ -3139,9 +3182,9 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd,
As MySQL will execute an external lock for every new table it uses
we can use this to start the transactions.
If we are in auto_commit mode we just need to start a transaction
- for the statement, this will be stored in transaction.stmt.
+ for the statement, this will be stored in thd_ndb.stmt.
If not, we have to start a master transaction if there doesn't exist
- one from before, this will be stored in transaction.all
+ one from before, this will be stored in thd_ndb.all
When a table lock is held one transaction will be started which holds
the table lock and for each statement a hupp transaction will be started
@@ -3154,21 +3197,21 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd,
int ha_ndbcluster::external_lock(THD *thd, int lock_type)
{
int error=0;
- NdbConnection* trans= NULL;
+ NdbTransaction* trans= NULL;
DBUG_ENTER("external_lock");
/*
Check that this handler instance has a connection
set up to the Ndb object of thd
*/
- if (check_ndb_connection())
+ if (check_ndb_connection(thd))
DBUG_RETURN(1);
-
- Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb;
+
+ Thd_ndb *thd_ndb= get_thd_ndb(thd);
Ndb *ndb= thd_ndb->ndb;
- DBUG_PRINT("enter", ("transaction.thd_ndb->lock_count: %d",
- thd_ndb->lock_count));
+ DBUG_PRINT("enter", ("thd: %x, thd_ndb: %x, thd_ndb->lock_count: %d",
+ thd, thd_ndb, thd_ndb->lock_count));
if (lock_type != F_UNLCK)
{
@@ -3176,23 +3219,23 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
if (!thd_ndb->lock_count++)
{
PRINT_OPTION_FLAGS(thd);
-
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK)))
{
// Autocommit transaction
- DBUG_ASSERT(!thd->transaction.stmt.ndb_tid);
+ DBUG_ASSERT(!thd_ndb->stmt);
DBUG_PRINT("trans",("Starting transaction stmt"));
trans= ndb->startTransaction();
if (trans == NULL)
ERR_RETURN(ndb->getNdbError());
- no_uncommitted_rows_reset(thd);
- thd->transaction.stmt.ndb_tid= trans;
+ no_uncommitted_rows_reset(thd);
+ thd_ndb->stmt= trans;
+ trans_register_ha(thd, FALSE, &ndbcluster_hton);
}
else
{
- if (!thd->transaction.all.ndb_tid)
- {
+ if (!thd_ndb->all)
+ {
// Not autocommit transaction
// A "master" transaction ha not been started yet
DBUG_PRINT("trans",("starting transaction, all"));
@@ -3200,7 +3243,9 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
trans= ndb->startTransaction();
if (trans == NULL)
ERR_RETURN(ndb->getNdbError());
- no_uncommitted_rows_reset(thd);
+ no_uncommitted_rows_reset(thd);
+ thd_ndb->all= trans;
+ trans_register_ha(thd, TRUE, &ndbcluster_hton);
/*
If this is the start of a LOCK TABLE, a table look
@@ -3209,12 +3254,11 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
Check if it should be read or write lock
*/
if (thd->options & (OPTION_TABLE_LOCK))
- {
+ {
//lockThisTable();
DBUG_PRINT("info", ("Locking the table..." ));
}
- thd->transaction.all.ndb_tid= trans;
}
}
}
@@ -3239,22 +3283,20 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
m_transaction_on= FALSE;
else
m_transaction_on= thd->variables.ndb_use_transactions;
- // m_use_local_query_cache= thd->variables.ndb_use_local_query_cache;
- m_active_trans= thd->transaction.all.ndb_tid ?
- (NdbConnection*)thd->transaction.all.ndb_tid:
- (NdbConnection*)thd->transaction.stmt.ndb_tid;
+ m_active_trans= thd_ndb->all ? thd_ndb->all : thd_ndb->stmt;
DBUG_ASSERT(m_active_trans);
// Start of transaction
+ m_rows_changed= 0;
m_retrieve_all_fields= FALSE;
m_retrieve_primary_key= FALSE;
- m_ops_pending= 0;
+ m_ops_pending= 0;
{
NDBDICT *dict= ndb->getDictionary();
const NDBTAB *tab;
void *tab_info;
if (!(tab= dict->getTable(m_tabname, &tab_info)))
- ERR_RETURN(dict->getNdbError());
+ ERR_RETURN(dict->getNdbError());
DBUG_PRINT("info", ("Table schema version: %d",
tab->getObjectVersion()));
// Check if thread has stale local cache
@@ -3281,16 +3323,34 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
m_table_info= tab_info;
}
no_uncommitted_rows_init(thd);
- }
- else
+ }
+ else
{
DBUG_PRINT("info", ("lock_type == F_UNLCK"));
+
+ if (ndb_cache_check_time && m_rows_changed)
+ {
+ DBUG_PRINT("info", ("Rows has changed and util thread is running"));
+ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
+ {
+ DBUG_PRINT("info", ("Add share to list of tables to be invalidated"));
+ /* NOTE push_back allocates memory using transactions mem_root! */
+ thd_ndb->changed_tables.push_back(m_share, &thd->transaction.mem_root);
+ }
+
+ pthread_mutex_lock(&m_share->mutex);
+ DBUG_PRINT("info", ("Invalidating commit_count"));
+ m_share->commit_count= 0;
+ m_share->commit_count_lock++;
+ pthread_mutex_unlock(&m_share->mutex);
+ }
+
if (!--thd_ndb->lock_count)
{
DBUG_PRINT("trans", ("Last external_lock"));
PRINT_OPTION_FLAGS(thd);
- if (thd->transaction.stmt.ndb_tid)
+ if (thd_ndb->stmt)
{
/*
Unlock is done without a transaction commit / rollback.
@@ -3299,10 +3359,11 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
*/
DBUG_PRINT("trans",("ending non-updating transaction"));
ndb->closeTransaction(m_active_trans);
- thd->transaction.stmt.ndb_tid= 0;
+ thd_ndb->stmt= NULL;
}
}
m_table_info= NULL;
+
/*
This is the place to make sure this handler instance
no longer are connected to the active transaction.
@@ -3316,6 +3377,10 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
DBUG_PRINT("warning", ("m_active_cursor != NULL"));
m_active_cursor= NULL;
+ if (m_multi_cursor)
+ DBUG_PRINT("warning", ("m_multi_cursor != NULL"));
+ m_multi_cursor= NULL;
+
if (m_blobs_pending)
DBUG_PRINT("warning", ("blobs_pending != 0"));
m_blobs_pending= 0;
@@ -3341,21 +3406,24 @@ int ha_ndbcluster::start_stmt(THD *thd)
DBUG_ENTER("start_stmt");
PRINT_OPTION_FLAGS(thd);
- NdbConnection *trans= (NdbConnection*)thd->transaction.stmt.ndb_tid;
+ Thd_ndb *thd_ndb= get_thd_ndb(thd);
+ NdbTransaction *trans= thd_ndb->stmt;
if (!trans){
- Ndb *ndb= ((Thd_ndb*)thd->transaction.thd_ndb)->ndb;
+ Ndb *ndb= thd_ndb->ndb;
DBUG_PRINT("trans",("Starting transaction stmt"));
-
- NdbConnection *tablock_trans=
- (NdbConnection*)thd->transaction.all.ndb_tid;
+
+#if 0
+ NdbTransaction *tablock_trans= thd_ndb->all;
DBUG_PRINT("info", ("tablock_trans: %x", (UintPtr)tablock_trans));
DBUG_ASSERT(tablock_trans);
// trans= ndb->hupp(tablock_trans);
+#endif
trans= ndb->startTransaction();
if (trans == NULL)
ERR_RETURN(ndb->getNdbError());
no_uncommitted_rows_reset(thd);
- thd->transaction.stmt.ndb_tid= trans;
+ thd_ndb->stmt= trans;
+ trans_register_ha(thd, FALSE, &ndbcluster_hton);
}
m_active_trans= trans;
@@ -3369,18 +3437,19 @@ int ha_ndbcluster::start_stmt(THD *thd)
/*
- Commit a transaction started in NDB
+ Commit a transaction started in NDB
*/
-int ndbcluster_commit(THD *thd, void *ndb_transaction)
+int ndbcluster_commit(THD *thd, bool all)
{
int res= 0;
- Ndb *ndb= ((Thd_ndb*)thd->transaction.thd_ndb)->ndb;
- NdbConnection *trans= (NdbConnection*)ndb_transaction;
+ Thd_ndb *thd_ndb= get_thd_ndb(thd);
+ Ndb *ndb= thd_ndb->ndb;
+ NdbTransaction *trans= all ? thd_ndb->all : thd_ndb->stmt;
DBUG_ENTER("ndbcluster_commit");
DBUG_PRINT("transaction",("%s",
- trans == thd->transaction.stmt.ndb_tid ?
+ trans == thd_ndb->stmt ?
"stmt" : "all"));
DBUG_ASSERT(ndb && trans);
@@ -3388,12 +3457,31 @@ int ndbcluster_commit(THD *thd, void *ndb_transaction)
{
const NdbError err= trans->getNdbError();
const NdbOperation *error_op= trans->getNdbErrorOperation();
- ERR_PRINT(err);
+ ERR_PRINT(err);
res= ndb_to_mysql_error(&err);
- if (res != -1)
+ if (res != -1)
ndbcluster_print_error(res, error_op);
}
ndb->closeTransaction(trans);
+
+ if (all)
+ thd_ndb->all= NULL;
+ else
+ thd_ndb->stmt= NULL;
+
+ /* Clear commit_count for tables changed by transaction */
+ NDB_SHARE* share;
+ List_iterator_fast<NDB_SHARE> it(thd_ndb->changed_tables);
+ while ((share= it++))
+ {
+ pthread_mutex_lock(&share->mutex);
+ DBUG_PRINT("info", ("Invalidate commit_count for %s, share->commit_count: %d ", share->table_name, share->commit_count));
+ share->commit_count= 0;
+ share->commit_count_lock++;
+ pthread_mutex_unlock(&share->mutex);
+ }
+ thd_ndb->changed_tables.empty();
+
DBUG_RETURN(res);
}
@@ -3402,19 +3490,20 @@ int ndbcluster_commit(THD *thd, void *ndb_transaction)
Rollback a transaction started in NDB
*/
-int ndbcluster_rollback(THD *thd, void *ndb_transaction)
+int ndbcluster_rollback(THD *thd, bool all)
{
int res= 0;
- Ndb *ndb= ((Thd_ndb*)thd->transaction.thd_ndb)->ndb;
- NdbConnection *trans= (NdbConnection*)ndb_transaction;
+ Thd_ndb *thd_ndb= get_thd_ndb(thd);
+ Ndb *ndb= thd_ndb->ndb;
+ NdbTransaction *trans= all ? thd_ndb->all : thd_ndb->stmt;
DBUG_ENTER("ndbcluster_rollback");
DBUG_PRINT("transaction",("%s",
- trans == thd->transaction.stmt.ndb_tid ?
+ trans == thd_ndb->stmt ?
"stmt" : "all"));
DBUG_ASSERT(ndb && trans);
- if (trans->execute(Rollback) != 0)
+ if (trans->execute(NdbTransaction::Rollback) != 0)
{
const NdbError err= trans->getNdbError();
const NdbOperation *error_op= trans->getNdbErrorOperation();
@@ -3424,7 +3513,16 @@ int ndbcluster_rollback(THD *thd, void *ndb_transaction)
ndbcluster_print_error(res, error_op);
}
ndb->closeTransaction(trans);
- DBUG_RETURN(0);
+
+ if (all)
+ thd_ndb->all= NULL;
+ else
+ thd_ndb->stmt= NULL;
+
+ /* Clear list of tables changed by transaction */
+ thd_ndb->changed_tables.empty();
+
+ DBUG_RETURN(res);
}
@@ -3432,6 +3530,9 @@ int ndbcluster_rollback(THD *thd, void *ndb_transaction)
Define NDB column based on Field.
Returns 0 or mysql error code.
Not member of ha_ndbcluster because NDBCOL cannot be declared.
+
+ MySQL text types with character set "binary" are mapped to true
+ NDB binary types without a character set. This may change.
*/
static int create_ndb_column(NDBCOL &col,
@@ -3439,12 +3540,7 @@ static int create_ndb_column(NDBCOL &col,
HA_CREATE_INFO *info)
{
// Set name
- {
- char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE];
- strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name));
- truncated_field_name[sizeof(truncated_field_name)-1]= '\0';
- col.setName(truncated_field_name);
- }
+ col.setName(field->field_name);
// Get char set
CHARSET_INFO *cs= field->charset();
// Set type and sizes
@@ -3514,6 +3610,24 @@ static int create_ndb_column(NDBCOL &col,
col.setLength(1);
}
break;
+ case MYSQL_TYPE_NEWDECIMAL:
+ {
+ Field_new_decimal *f= (Field_new_decimal*)field;
+ uint precision= f->precision;
+ uint scale= f->decimals();
+ if (field->flags & UNSIGNED_FLAG)
+ {
+ col.setType(NDBCOL::Decimalunsigned);
+ }
+ else
+ {
+ col.setType(NDBCOL::Decimal);
+ }
+ col.setPrecision(precision);
+ col.setScale(scale);
+ col.setLength(1);
+ }
+ break;
// Date types
case MYSQL_TYPE_DATETIME:
col.setType(NDBCOL::Datetime);
@@ -3541,30 +3655,56 @@ static int create_ndb_column(NDBCOL &col,
break;
// Char types
case MYSQL_TYPE_STRING:
- if (field->flags & BINARY_FLAG)
+ if (field->pack_length() == 0)
+ {
+ col.setType(NDBCOL::Bit);
+ col.setLength(1);
+ }
+ else if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
+ {
col.setType(NDBCOL::Binary);
- else {
- col.setType(NDBCOL::Char);
- col.setCharset(cs);
+ col.setLength(field->pack_length());
}
- if (field->pack_length() == 0)
- col.setLength(1); // currently ndb does not support size 0
else
+ {
+ col.setType(NDBCOL::Char);
+ col.setCharset(cs);
col.setLength(field->pack_length());
+ }
break;
- case MYSQL_TYPE_VAR_STRING:
- if (field->flags & BINARY_FLAG)
- col.setType(NDBCOL::Varbinary);
- else {
- col.setType(NDBCOL::Varchar);
- col.setCharset(cs);
+ case MYSQL_TYPE_VAR_STRING: // ?
+ case MYSQL_TYPE_VARCHAR:
+ {
+ Field_varstring* f= (Field_varstring*)field;
+ if (f->length_bytes == 1)
+ {
+ if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
+ col.setType(NDBCOL::Varbinary);
+ else {
+ col.setType(NDBCOL::Varchar);
+ col.setCharset(cs);
+ }
+ }
+ else if (f->length_bytes == 2)
+ {
+ if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
+ col.setType(NDBCOL::Longvarbinary);
+ else {
+ col.setType(NDBCOL::Longvarchar);
+ col.setCharset(cs);
+ }
+ }
+ else
+ {
+ return HA_ERR_UNSUPPORTED;
+ }
+ col.setLength(field->field_length);
}
- col.setLength(field->pack_length());
break;
// Blob types (all come in as MYSQL_TYPE_BLOB)
mysql_type_tiny_blob:
case MYSQL_TYPE_TINY_BLOB:
- if (field->flags & BINARY_FLAG)
+ if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Blob);
else {
col.setType(NDBCOL::Text);
@@ -3575,9 +3715,9 @@ static int create_ndb_column(NDBCOL &col,
col.setPartSize(0);
col.setStripeSize(0);
break;
- mysql_type_blob:
+ //mysql_type_blob:
case MYSQL_TYPE_BLOB:
- if (field->flags & BINARY_FLAG)
+ if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Blob);
else {
col.setType(NDBCOL::Text);
@@ -3599,7 +3739,7 @@ static int create_ndb_column(NDBCOL &col,
break;
mysql_type_medium_blob:
case MYSQL_TYPE_MEDIUM_BLOB:
- if (field->flags & BINARY_FLAG)
+ if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Blob);
else {
col.setType(NDBCOL::Text);
@@ -3611,7 +3751,7 @@ static int create_ndb_column(NDBCOL &col,
break;
mysql_type_long_blob:
case MYSQL_TYPE_LONG_BLOB:
- if (field->flags & BINARY_FLAG)
+ if ((field->flags & BINARY_FLAG) && cs == &my_charset_bin)
col.setType(NDBCOL::Blob);
else {
col.setType(NDBCOL::Text);
@@ -3630,6 +3770,16 @@ static int create_ndb_column(NDBCOL &col,
col.setType(NDBCOL::Char);
col.setLength(field->pack_length());
break;
+ case MYSQL_TYPE_BIT:
+ {
+ int no_of_bits= field->field_length*8 + ((Field_bit *) field)->bit_len;
+ col.setType(NDBCOL::Bit);
+ if (!no_of_bits)
+ col.setLength(1);
+ else
+ col.setLength(no_of_bits);
+ break;
+ }
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_GEOMETRY:
goto mysql_type_unsupported;
@@ -3660,7 +3810,7 @@ static int create_ndb_column(NDBCOL &col,
static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
{
- if (form->max_rows == (ha_rows) 0) /* default setting, don't set fragmentation */
+ if (form->s->max_rows == (ha_rows) 0) /* default setting, don't set fragmentation */
return;
/**
* get the number of fragments right
@@ -3678,12 +3828,12 @@ static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
acc_row_size+= 4 + /*safety margin*/ 4;
#endif
ulonglong acc_fragment_size= 512*1024*1024;
- ulonglong max_rows= form->max_rows;
+ ulonglong max_rows= form->s->max_rows;
#if MYSQL_VERSION_ID >= 50100
no_fragments= (max_rows*acc_row_size)/acc_fragment_size+1;
#else
no_fragments= ((max_rows*acc_row_size)/acc_fragment_size+1
- +1/*correct rounding*/)/2;
+ +1/*correct rounding*/)/2;
#endif
}
{
@@ -3693,8 +3843,8 @@ static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
{
ftype= NDBTAB::FragAllLarge;
if (no_fragments > 4*no_nodes)
- push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
- "Ndb might have problems storing the max amount of rows specified");
+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Ndb might have problems storing the max amount of rows specified");
}
else if (no_fragments > no_nodes)
ftype= NDBTAB::FragAllMedium;
@@ -3705,18 +3855,17 @@ static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
}
int ha_ndbcluster::create(const char *name,
- TABLE *form,
- HA_CREATE_INFO *info)
+ TABLE *form,
+ HA_CREATE_INFO *info)
{
NDBTAB tab;
NDBCOL col;
uint pack_length, length, i, pk_length= 0;
const void *data, *pack_data;
- const char **key_names= form->keynames.type_names;
char name2[FN_HEADLEN];
bool create_from_engine= (info->table_options & HA_CREATE_FROM_ENGINE);
- DBUG_ENTER("create");
+ DBUG_ENTER("ha_ndbcluster::create");
DBUG_PRINT("enter", ("name: %s", name));
fn_format(name2, name, "", "",2); // Remove the .frm extension
set_dbname(name2);
@@ -3748,21 +3897,21 @@ int ha_ndbcluster::create(const char *name,
my_free((char*)data, MYF(0));
my_free((char*)pack_data, MYF(0));
- for (i= 0; i < form->fields; i++)
+ for (i= 0; i < form->s->fields; i++)
{
Field *field= form->field[i];
DBUG_PRINT("info", ("name: %s, type: %u, pack_length: %d",
field->field_name, field->real_type(),
- field->pack_length()));
+ field->pack_length()));
if ((my_errno= create_ndb_column(col, field, info)))
DBUG_RETURN(my_errno);
tab.addColumn(col);
- if(col.getPrimaryKey())
+ if (col.getPrimaryKey())
pk_length += (field->pack_length() + 3) / 4;
}
// No primary key, create shadow key as 64 bit, auto increment
- if (form->primary_key == MAX_KEY)
+ if (form->s->primary_key == MAX_KEY)
{
DBUG_PRINT("info", ("Generating shadow key"));
col.setName("$PK");
@@ -3776,7 +3925,7 @@ int ha_ndbcluster::create(const char *name,
}
// Make sure that blob tables don't have to big part size
- for (i= 0; i < form->fields; i++)
+ for (i= 0; i < form->s->fields; i++)
{
/**
* The extra +7 concists
@@ -3788,13 +3937,13 @@ int ha_ndbcluster::create(const char *name,
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
{
- NdbDictionary::Column * col = tab.getColumn(i);
- int size = pk_length + (col->getPartSize()+3)/4 + 7;
- if(size > NDB_MAX_TUPLE_SIZE_IN_WORDS &&
- (pk_length+7) < NDB_MAX_TUPLE_SIZE_IN_WORDS)
+ NdbDictionary::Column * col= tab.getColumn(i);
+ int size= pk_length + (col->getPartSize()+3)/4 + 7;
+ if (size > NDB_MAX_TUPLE_SIZE_IN_WORDS &&
+ (pk_length+7) < NDB_MAX_TUPLE_SIZE_IN_WORDS)
{
- size = NDB_MAX_TUPLE_SIZE_IN_WORDS - pk_length - 7;
- col->setPartSize(4*size);
+ size= NDB_MAX_TUPLE_SIZE_IN_WORDS - pk_length - 7;
+ col->setPartSize(4*size);
}
/**
* If size > NDB_MAX and pk_length+7 >= NDB_MAX
@@ -3836,17 +3985,17 @@ int ha_ndbcluster::create(const char *name,
int ha_ndbcluster::create_ordered_index(const char *name,
- KEY *key_info)
+ KEY *key_info)
{
- DBUG_ENTER("create_ordered_index");
+ DBUG_ENTER("ha_ndbcluster::create_ordered_index");
DBUG_RETURN(create_index(name, key_info, FALSE));
}
int ha_ndbcluster::create_unique_index(const char *name,
- KEY *key_info)
+ KEY *key_info)
{
- DBUG_ENTER("create_unique_index");
+ DBUG_ENTER("ha_ndbcluster::create_unique_index");
DBUG_RETURN(create_index(name, key_info, TRUE));
}
@@ -3856,15 +4005,15 @@ int ha_ndbcluster::create_unique_index(const char *name,
*/
int ha_ndbcluster::create_index(const char *name,
- KEY *key_info,
- bool unique)
+ KEY *key_info,
+ bool unique)
{
Ndb *ndb= get_ndb();
NdbDictionary::Dictionary *dict= 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_ENTER("ha_ndbcluster::create_index");
DBUG_PRINT("enter", ("name: %s ", name));
NdbDictionary::Index ndb_index(name);
@@ -3882,12 +4031,7 @@ int ha_ndbcluster::create_index(const char *name,
{
Field *field= key_part->field;
DBUG_PRINT("info", ("attr: %s", field->field_name));
- {
- char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE];
- strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name));
- truncated_field_name[sizeof(truncated_field_name)-1]= '\0';
- ndb_index.addColumnName(truncated_field_name);
- }
+ ndb_index.addColumnName(field->field_name);
}
if (dict->createIndex(ndb_index))
@@ -3918,7 +4062,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
if (check_ndb_connection())
DBUG_RETURN(my_errno= HA_ERR_NO_CONNECTION);
-
+
Ndb *ndb= get_ndb();
dict= ndb->getDictionary();
if (!(orig_tab= dict->getTable(m_tabname)))
@@ -3953,7 +4097,6 @@ int ha_ndbcluster::alter_table_name(const char *to)
Ndb *ndb= get_ndb();
NDBDICT *dict= ndb->getDictionary();
const NDBTAB *orig_tab= (const NDBTAB *) m_table;
- int ret;
DBUG_ENTER("alter_table_name_table");
NdbDictionary::Table new_tab= *orig_tab;
@@ -3969,68 +4112,66 @@ int ha_ndbcluster::alter_table_name(const char *to)
/*
- Delete a table from NDB Cluster
+ Delete table from NDB Cluster
+
*/
int ha_ndbcluster::delete_table(const char *name)
{
- DBUG_ENTER("delete_table");
+ DBUG_ENTER("ha_ndbcluster::delete_table");
DBUG_PRINT("enter", ("name: %s", name));
set_dbname(name);
set_tabname(name);
-
+
if (check_ndb_connection())
DBUG_RETURN(HA_ERR_NO_CONNECTION);
- // Remove .ndb file
+
+ /* Call ancestor function to delete .ndb file */
handler::delete_table(name);
+
+ /* Drop the table from NDB */
DBUG_RETURN(drop_table());
}
/*
- Drop a table in NDB Cluster
+ Drop table in NDB Cluster
*/
int ha_ndbcluster::drop_table()
{
Ndb *ndb= get_ndb();
NdbDictionary::Dictionary *dict= ndb->getDictionary();
-
+
DBUG_ENTER("drop_table");
DBUG_PRINT("enter", ("Deleting %s", m_tabname));
-
- if (dict->dropTable(m_tabname))
- {
- const NdbError err= dict->getNdbError();
- if (err.code == 709)
- ; // 709: No such table existed
- else
- ERR_RETURN(dict->getNdbError());
- }
+
release_metadata();
+ if (dict->dropTable(m_tabname))
+ ERR_RETURN(dict->getNdbError());
DBUG_RETURN(0);
}
-longlong ha_ndbcluster::get_auto_increment()
+ulonglong ha_ndbcluster::get_auto_increment()
{
+ int cache_size;
+ Uint64 auto_value;
DBUG_ENTER("get_auto_increment");
DBUG_PRINT("enter", ("m_tabname: %s", m_tabname));
Ndb *ndb= get_ndb();
-
+
if (m_rows_inserted > m_rows_to_insert)
{
/* We guessed too low */
m_rows_to_insert+= m_autoincrement_prefetch;
}
- int cache_size=
- (int)
- (m_rows_to_insert - m_rows_inserted < m_autoincrement_prefetch) ?
- m_rows_to_insert - m_rows_inserted
- : (m_rows_to_insert > m_autoincrement_prefetch) ?
- m_rows_to_insert
- : m_autoincrement_prefetch;
- Uint64 auto_value= NDB_FAILED_AUTO_INCREMENT;
+ cache_size=
+ (int) ((m_rows_to_insert - m_rows_inserted < m_autoincrement_prefetch) ?
+ m_rows_to_insert - m_rows_inserted :
+ ((m_rows_to_insert > m_autoincrement_prefetch) ?
+ m_rows_to_insert : m_autoincrement_prefetch));
+ auto_value= NDB_FAILED_AUTO_INCREMENT;
uint retries= NDB_AUTO_INCREMENT_RETRIES;
do {
auto_value=
@@ -4051,16 +4192,18 @@ longlong ha_ndbcluster::get_auto_increment()
*/
ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
- handler(table_arg),
+ handler(&ndbcluster_hton, table_arg),
m_active_trans(NULL),
m_active_cursor(NULL),
m_table(NULL),
m_table_version(-1),
m_table_info(NULL),
m_table_flags(HA_REC_NOT_IN_SEQ |
- HA_NULL_IN_KEY |
- HA_AUTO_PART_KEY |
- HA_NO_PREFIX_CHAR_KEYS),
+ HA_NULL_IN_KEY |
+ HA_AUTO_PART_KEY |
+ HA_NO_PREFIX_CHAR_KEYS |
+ HA_NEED_READ_RANGE_BUFFER |
+ HA_CAN_BIT_FIELD),
m_share(0),
m_use_write(FALSE),
m_ignore_dup_key(FALSE),
@@ -4070,6 +4213,7 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_rows_to_insert((ha_rows) 1),
m_rows_inserted((ha_rows) 0),
m_bulk_insert_rows((ha_rows) 1024),
+ m_rows_changed((ha_rows) 0),
m_bulk_insert_not_flushed(FALSE),
m_ops_pending(0),
m_skip_auto_increment(TRUE),
@@ -4081,10 +4225,11 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_force_send(TRUE),
m_autoincrement_prefetch((ha_rows) 32),
m_transaction_on(TRUE),
- m_use_local_query_cache(FALSE)
-{
+ m_cond_stack(NULL),
+ m_multi_cursor(NULL)
+{
int i;
-
+
DBUG_ENTER("ha_ndbcluster");
m_tabname[0]= '\0';
@@ -4127,10 +4272,15 @@ ha_ndbcluster::~ha_ndbcluster()
}
DBUG_ASSERT(m_active_trans == NULL);
+ // Discard the condition stack
+ DBUG_PRINT("info", ("Clearing condition stack"));
+ cond_clear();
+
DBUG_VOID_RETURN;
}
+
/*
Open a table for further use
- fetch metadata for this table from NDB
@@ -4148,9 +4298,9 @@ int ha_ndbcluster::open(const char *name, int mode, uint test_if_locked)
// Setup ref_length to make room for the whole
// primary key to be written in the ref variable
- if (table->primary_key != MAX_KEY)
+ if (table->s->primary_key != MAX_KEY)
{
- key= table->key_info+table->primary_key;
+ key= table->key_info+table->s->primary_key;
ref_length= key->key_length;
DBUG_PRINT("info", (" ref_length: %d", ref_length));
}
@@ -4231,23 +4381,20 @@ void ha_ndbcluster::release_thd_ndb(Thd_ndb* thd_ndb)
Ndb* check_ndb_in_thd(THD* thd)
{
- DBUG_ENTER("check_ndb_in_thd");
- Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb;
-
+ Thd_ndb *thd_ndb= get_thd_ndb(thd);
if (!thd_ndb)
{
if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb()))
- DBUG_RETURN(NULL);
- thd->transaction.thd_ndb= thd_ndb;
+ return NULL;
+ set_thd_ndb(thd, thd_ndb);
}
- DBUG_RETURN(thd_ndb->ndb);
+ return thd_ndb->ndb;
}
-int ha_ndbcluster::check_ndb_connection()
+int ha_ndbcluster::check_ndb_connection(THD* thd)
{
- THD* thd= current_thd;
Ndb *ndb;
DBUG_ENTER("check_ndb_connection");
@@ -4258,16 +4405,16 @@ int ha_ndbcluster::check_ndb_connection()
}
-void ndbcluster_close_connection(THD *thd)
+int ndbcluster_close_connection(THD *thd)
{
- Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb;
+ Thd_ndb *thd_ndb= get_thd_ndb(thd);
DBUG_ENTER("ndbcluster_close_connection");
if (thd_ndb)
{
ha_ndbcluster::release_thd_ndb(thd_ndb);
- thd->transaction.thd_ndb= NULL;
+ set_thd_ndb(thd, NULL); // not strictly required but does not hurt either
}
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
@@ -4276,7 +4423,7 @@ void ndbcluster_close_connection(THD *thd)
*/
int ndbcluster_discover(THD* thd, const char *db, const char *name,
- const void** frmblob, uint* frmlen)
+ const void** frmblob, uint* frmlen)
{
uint len;
const void* data;
@@ -4322,33 +4469,31 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
/*
Check if a table exists in NDB
-
+
*/
int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name)
{
- uint len;
- const void* data;
const NDBTAB* tab;
Ndb* ndb;
DBUG_ENTER("ndbcluster_table_exists_in_engine");
- DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
+ DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
if (!(ndb= check_ndb_in_thd(thd)))
- DBUG_RETURN(HA_ERR_NO_CONNECTION);
+ DBUG_RETURN(HA_ERR_NO_CONNECTION);
ndb->setDatabaseName(db);
NDBDICT* dict= ndb->getDictionary();
dict->set_local_table_data_size(sizeof(Ndb_local_table_statistics));
dict->invalidateTable(name);
if (!(tab= dict->getTable(name)))
- {
+ {
const NdbError err= dict->getNdbError();
if (err.code == 709)
DBUG_RETURN(0);
ERR_RETURN(err);
}
-
+
DBUG_PRINT("info", ("Found table %s", tab->getName()));
DBUG_RETURN(1);
}
@@ -4356,7 +4501,7 @@ int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name
extern "C" byte* tables_get_key(const char *entry, uint *length,
- my_bool not_used __attribute__((unused)))
+ my_bool not_used __attribute__((unused)))
{
*length= strlen(entry);
return (byte*) entry;
@@ -4420,7 +4565,7 @@ int ndbcluster_drop_database(const char *path)
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
- const char *wild, bool dir, List<char> *files)
+ const char *wild, bool dir, List<char> *files)
{
DBUG_ENTER("ndbcluster_find_files");
DBUG_PRINT("enter", ("db: %s", db));
@@ -4440,18 +4585,18 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
// List tables in NDB
NDBDICT *dict= ndb->getDictionary();
if (dict->listObjects(list,
- NdbDictionary::Object::UserTable) != 0)
+ NdbDictionary::Object::UserTable) != 0)
ERR_RETURN(dict->getNdbError());
if (hash_init(&ndb_tables, system_charset_info,list.count,0,0,
- (hash_get_key)tables_get_key,0,0))
+ (hash_get_key)tables_get_key,0,0))
{
DBUG_PRINT("error", ("Failed to init HASH ndb_tables"));
DBUG_RETURN(-1);
}
if (hash_init(&ok_tables, system_charset_info,32,0,0,
- (hash_get_key)tables_get_key,0,0))
+ (hash_get_key)tables_get_key,0,0))
{
DBUG_PRINT("error", ("Failed to init HASH ok_tables"));
hash_free(&ndb_tables);
@@ -4472,11 +4617,11 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
{
if (lower_case_table_names)
{
- if (wild_case_compare(files_charset_info, t.name, wild))
- continue;
+ if (wild_case_compare(files_charset_info, t.name, wild))
+ continue;
}
else if (wild_compare(t.name,wild,0))
- continue;
+ continue;
}
DBUG_PRINT("info", ("Inserting %s into ndb_tables hash", t.name));
my_hash_insert(&ndb_tables, (byte*)thd->strdup(t.name));
@@ -4498,7 +4643,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
// File is not in NDB, check for .ndb file with this name
(void)strxnmov(name, FN_REFLEN,
- mysql_data_home,"/",db,"/",file_name,ha_ndb_ext,NullS);
+ mysql_data_home,"/",db,"/",file_name,ha_ndb_ext,NullS);
DBUG_PRINT("info", ("Check access for %s", name));
if (access(name, F_OK))
{
@@ -4542,17 +4687,20 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
// Delete old files
List_iterator_fast<char> it3(delete_list);
while ((file_name=it3++))
- {
- DBUG_PRINT("info", ("Remove table %s/%s",db, file_name ));
+ {
+ DBUG_PRINT("info", ("Remove table %s/%s", db, file_name));
// Delete the table and all related files
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
table_list.db= (char*) db;
- table_list.alias=table_list.real_name=(char*)file_name;
- (void)mysql_rm_table_part2(thd, &table_list,
- /* if_exists */ TRUE,
- /* drop_temporary */ FALSE,
- /* dont_log_query*/ TRUE);
+ table_list.alias= table_list.table_name= (char*)file_name;
+ (void)mysql_rm_table_part2(thd, &table_list,
+ /* if_exists */ FALSE,
+ /* drop_temporary */ FALSE,
+ /* drop_view */ FALSE,
+ /* dont_log_query*/ TRUE);
+ /* Clear error message that is returned when table is deleted */
+ thd->clear_error();
}
}
@@ -4560,7 +4708,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
List_iterator_fast<char> it2(create_list);
while ((file_name=it2++))
{
- DBUG_PRINT("info", ("Table %s need discovery", name));
+ DBUG_PRINT("info", ("Table %s need discovery", file_name));
if (ha_create_table_from_engine(thd, db, file_name) == 0)
files->push_back(thd->strdup(file_name));
}
@@ -4579,7 +4727,15 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
a NDB Cluster table handler
*/
-bool ndbcluster_init()
+/* Call back after cluster connect */
+static int connect_callback()
+{
+ update_status_variables(g_ndb_cluster_connection);
+ return 0;
+}
+
+handlerton *
+ndbcluster_init()
{
int res;
DBUG_ENTER("ndbcluster_init");
@@ -4590,7 +4746,7 @@ bool ndbcluster_init()
new Ndb_cluster_connection(opt_ndbcluster_connectstring)) == 0)
{
DBUG_PRINT("error",("Ndb_cluster_connection(%s)",
- opt_ndbcluster_connectstring));
+ opt_ndbcluster_connectstring));
goto ndbcluster_init_error;
}
@@ -4598,7 +4754,11 @@ bool ndbcluster_init()
(opt_ndb_optimized_node_selection);
// Create a Ndb object to open the connection to NDB
- g_ndb= new Ndb(g_ndb_cluster_connection, "sys");
+ if ( (g_ndb= new Ndb(g_ndb_cluster_connection, "sys")) == 0 )
+ {
+ DBUG_PRINT("error", ("failed to create global ndb object"));
+ goto ndbcluster_init_error;
+ }
g_ndb->getDictionary()->set_local_table_data_size(sizeof(Ndb_local_table_statistics));
if (g_ndb->init() != 0)
{
@@ -4608,22 +4768,29 @@ bool ndbcluster_init()
if ((res= g_ndb_cluster_connection->connect(0,0,0)) == 0)
{
+ connect_callback();
DBUG_PRINT("info",("NDBCLUSTER storage engine at %s on port %d",
- g_ndb_cluster_connection->get_connected_host(),
- g_ndb_cluster_connection->get_connected_port()));
+ g_ndb_cluster_connection->get_connected_host(),
+ g_ndb_cluster_connection->get_connected_port()));
g_ndb_cluster_connection->wait_until_ready(10,3);
}
- else if(res == 1)
+ else if (res == 1)
{
- if (g_ndb_cluster_connection->start_connect_thread()) {
+ if (g_ndb_cluster_connection->start_connect_thread(connect_callback))
+ {
DBUG_PRINT("error", ("g_ndb_cluster_connection->start_connect_thread()"));
goto ndbcluster_init_error;
}
+#ifndef DBUG_OFF
{
char buf[1024];
- DBUG_PRINT("info",("NDBCLUSTER storage engine not started, will connect using %s",
- g_ndb_cluster_connection->get_connectstring(buf,sizeof(buf))));
+ DBUG_PRINT("info",
+ ("NDBCLUSTER storage engine not started, "
+ "will connect using %s",
+ g_ndb_cluster_connection->
+ get_connectstring(buf,sizeof(buf))));
}
+#endif
}
else
{
@@ -4635,35 +4802,66 @@ bool ndbcluster_init()
(void) hash_init(&ndbcluster_open_tables,system_charset_info,32,0,0,
(hash_get_key) ndbcluster_get_key,0,0);
pthread_mutex_init(&ndbcluster_mutex,MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_ndb_util_thread, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&COND_ndb_util_thread, NULL);
+
+ // Create utility thread
+ pthread_t tmp;
+ if (pthread_create(&tmp, &connection_attrib, ndb_util_thread_func, 0))
+ {
+ DBUG_PRINT("error", ("Could not create ndb utility thread"));
+ hash_free(&ndbcluster_open_tables);
+ pthread_mutex_destroy(&ndbcluster_mutex);
+ pthread_mutex_destroy(&LOCK_ndb_util_thread);
+ pthread_cond_destroy(&COND_ndb_util_thread);
+ goto ndbcluster_init_error;
+ }
+
ndbcluster_inited= 1;
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(&ndbcluster_hton);
ndbcluster_init_error:
- ndbcluster_end();
- DBUG_RETURN(TRUE);
+ if (g_ndb)
+ delete g_ndb;
+ g_ndb= NULL;
+ if (g_ndb_cluster_connection)
+ delete g_ndb_cluster_connection;
+ g_ndb_cluster_connection= NULL;
+ DBUG_RETURN(NULL);
}
/*
End use of the NDB Cluster table handler
- free all global variables allocated by
- ndcluster_init()
+ ndbcluster_init()
*/
bool ndbcluster_end()
{
DBUG_ENTER("ndbcluster_end");
- if(g_ndb)
+
+ if (!ndbcluster_inited)
+ DBUG_RETURN(0);
+
+ // Kill ndb utility thread
+ (void) pthread_mutex_lock(&LOCK_ndb_util_thread);
+ DBUG_PRINT("exit",("killing ndb util thread: %lx", ndb_util_thread));
+ (void) pthread_cond_signal(&COND_ndb_util_thread);
+ (void) pthread_mutex_unlock(&LOCK_ndb_util_thread);
+
+ if (g_ndb)
delete g_ndb;
g_ndb= NULL;
if (g_ndb_cluster_connection)
delete g_ndb_cluster_connection;
g_ndb_cluster_connection= NULL;
- if (!ndbcluster_inited)
- DBUG_RETURN(0);
+
hash_free(&ndbcluster_open_tables);
pthread_mutex_destroy(&ndbcluster_mutex);
+ pthread_mutex_destroy(&LOCK_ndb_util_thread);
+ pthread_cond_destroy(&COND_ndb_util_thread);
ndbcluster_inited= 0;
DBUG_RETURN(0);
}
@@ -4679,7 +4877,7 @@ void ndbcluster_print_error(int error, const NdbOperation *error_op)
DBUG_ENTER("ndbcluster_print_error");
TABLE tab;
const char *tab_name= (error_op) ? error_op->getTableName() : "";
- tab.table_name= (char *) tab_name;
+ tab.alias= (char *) tab_name;
ha_ndbcluster error_handler(&tab);
tab.file= &error_handler;
error_handler.print_error(error, MYF(0));
@@ -4844,16 +5042,216 @@ const char* ha_ndbcluster::index_type(uint key_number)
return "HASH";
}
}
+
uint8 ha_ndbcluster::table_cache_type()
{
- if (m_use_local_query_cache)
- return HA_CACHE_TBL_TRANSACT;
+ DBUG_ENTER("ha_ndbcluster::table_cache_type=HA_CACHE_TBL_ASKTRANSACT");
+ DBUG_RETURN(HA_CACHE_TBL_ASKTRANSACT);
+}
+
+
+uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname,
+ Uint64 *commit_count)
+{
+ DBUG_ENTER("ndb_get_commitcount");
+
+ char name[FN_REFLEN];
+ NDB_SHARE *share;
+ (void)strxnmov(name, FN_REFLEN, "./",dbname,"/",tabname,NullS);
+ DBUG_PRINT("enter", ("name: %s", name));
+ pthread_mutex_lock(&ndbcluster_mutex);
+ if (!(share=(NDB_SHARE*) hash_search(&ndbcluster_open_tables,
+ (byte*) name,
+ strlen(name))))
+ {
+ pthread_mutex_unlock(&ndbcluster_mutex);
+ DBUG_PRINT("info", ("Table %s not found in ndbcluster_open_tables",
+ name));
+ DBUG_RETURN(1);
+ }
+ share->use_count++;
+ pthread_mutex_unlock(&ndbcluster_mutex);
+
+ pthread_mutex_lock(&share->mutex);
+ if (ndb_cache_check_time > 0)
+ {
+ if (share->commit_count != 0)
+ {
+ *commit_count= share->commit_count;
+ DBUG_PRINT("info", ("Getting commit_count: %llu from share",
+ share->commit_count));
+ pthread_mutex_unlock(&share->mutex);
+ free_share(share);
+ DBUG_RETURN(0);
+ }
+ }
+ DBUG_PRINT("info", ("Get commit_count from NDB"));
+ Ndb *ndb;
+ if (!(ndb= check_ndb_in_thd(thd)))
+ DBUG_RETURN(1);
+ ndb->setDatabaseName(dbname);
+ uint lock= share->commit_count_lock;
+ pthread_mutex_unlock(&share->mutex);
+
+ struct Ndb_statistics stat;
+ if (ndb_get_table_statistics(ndb, tabname, &stat))
+ {
+ free_share(share);
+ DBUG_RETURN(1);
+ }
+
+ pthread_mutex_lock(&share->mutex);
+ if (share->commit_count_lock == lock)
+ {
+ DBUG_PRINT("info", ("Setting commit_count to %llu", stat.commit_count));
+ share->commit_count= stat.commit_count;
+ *commit_count= stat.commit_count;
+ }
else
- return HA_CACHE_TBL_NOCACHE;
+ {
+ DBUG_PRINT("info", ("Discarding commit_count, comit_count_lock changed"));
+ *commit_count= 0;
+ }
+ pthread_mutex_unlock(&share->mutex);
+ free_share(share);
+ DBUG_RETURN(0);
}
+
/*
- Handling the shared NDB_SHARE structure that is needed to
+ Check if a cached query can be used.
+ This is done by comparing the supplied engine_data to commit_count of
+ the table.
+ The commit_count is either retrieved from the share for the table, where
+ it has been cached by the util thread. If the util thread is not started,
+ NDB has to be contacetd to retrieve the commit_count, this will introduce
+ a small delay while waiting for NDB to answer.
+
+
+ SYNOPSIS
+ ndbcluster_cache_retrieval_allowed
+ thd thread handle
+ full_name concatenation of database name,
+ the null character '\0', and the table
+ name
+ full_name_len length of the full name,
+ i.e. len(dbname) + len(tablename) + 1
+
+ engine_data parameter retrieved when query was first inserted into
+ the cache. If the value of engine_data is changed,
+ all queries for this table should be invalidated.
+
+ RETURN VALUE
+ TRUE Yes, use the query from cache
+ FALSE No, don't use the cached query, and if engine_data
+ has changed, all queries for this table should be invalidated
+
+*/
+
+static my_bool
+ndbcluster_cache_retrieval_allowed(THD *thd,
+ char *full_name, uint full_name_len,
+ ulonglong *engine_data)
+{
+ DBUG_ENTER("ndbcluster_cache_retrieval_allowed");
+
+ Uint64 commit_count;
+ bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
+ char *dbname= full_name;
+ char *tabname= dbname+strlen(dbname)+1;
+
+ DBUG_PRINT("enter", ("dbname: %s, tabname: %s, is_autocommit: %d",
+ dbname, tabname, is_autocommit));
+
+ if (!is_autocommit)
+ {
+ DBUG_PRINT("exit", ("No, don't use cache in transaction"));
+ DBUG_RETURN(FALSE);
+ }
+
+ if (ndb_get_commitcount(thd, dbname, tabname, &commit_count))
+ {
+ *engine_data= 0; /* invalidate */
+ DBUG_PRINT("exit", ("No, could not retrieve commit_count"));
+ DBUG_RETURN(FALSE);
+ }
+ DBUG_PRINT("info", ("*engine_data: %llu, commit_count: %llu",
+ *engine_data, commit_count));
+ if (commit_count == 0)
+ {
+ *engine_data= 0; /* invalidate */
+ DBUG_PRINT("exit", ("No, local commit has been performed"));
+ DBUG_RETURN(FALSE);
+ }
+ else if (*engine_data != commit_count)
+ {
+ *engine_data= commit_count; /* invalidate */
+ DBUG_PRINT("exit", ("No, commit_count has changed"));
+ DBUG_RETURN(FALSE);
+ }
+
+ DBUG_PRINT("exit", ("OK to use cache, engine_data: %llu", *engine_data));
+ DBUG_RETURN(TRUE);
+}
+
+
+/**
+ Register a table for use in the query cache. Fetch the commit_count
+ for the table and return it in engine_data, this will later be used
+ to check if the table has changed, before the cached query is reused.
+
+ SYNOPSIS
+ ha_ndbcluster::can_query_cache_table
+ thd thread handle
+ full_name concatenation of database name,
+ the null character '\0', and the table
+ name
+ full_name_len length of the full name,
+ i.e. len(dbname) + len(tablename) + 1
+ qc_engine_callback function to be called before using cache on this table
+ engine_data out, commit_count for this table
+
+ RETURN VALUE
+ TRUE Yes, it's ok to cahce this query
+ FALSE No, don't cach the query
+
+*/
+
+my_bool
+ha_ndbcluster::register_query_cache_table(THD *thd,
+ char *full_name, uint full_name_len,
+ qc_engine_callback *engine_callback,
+ ulonglong *engine_data)
+{
+ DBUG_ENTER("ha_ndbcluster::register_query_cache_table");
+
+ bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
+
+ DBUG_PRINT("enter",("dbname: %s, tabname: %s, is_autocommit: %d",
+ m_dbname, m_tabname, is_autocommit));
+
+ if (!is_autocommit)
+ {
+ DBUG_PRINT("exit", ("Can't register table during transaction"))
+ DBUG_RETURN(FALSE);
+ }
+
+ Uint64 commit_count;
+ if (ndb_get_commitcount(thd, m_dbname, m_tabname, &commit_count))
+ {
+ *engine_data= 0;
+ DBUG_PRINT("exit", ("Error, could not get commitcount"))
+ DBUG_RETURN(FALSE);
+ }
+ *engine_data= commit_count;
+ *engine_callback= ndbcluster_cache_retrieval_allowed;
+ DBUG_PRINT("exit", ("commit_count: %llu", commit_count));
+ DBUG_RETURN(commit_count > 0);
+}
+
+
+/*
+ Handling the shared NDB_SHARE structure that is needed to
provide table locking.
It's also used for sharing data with other NDB handlers
in the same MySQL Server. There is currently not much
@@ -4861,7 +5259,7 @@ uint8 ha_ndbcluster::table_cache_type()
*/
static byte* ndbcluster_get_key(NDB_SHARE *share,uint *length,
- my_bool not_used __attribute__((unused)))
+ my_bool not_used __attribute__((unused)))
{
*length=share->table_name_length;
return (byte*) share->table_name;
@@ -4890,9 +5288,22 @@ static NDB_SHARE* get_share(const char *table_name)
}
thr_lock_init(&share->lock);
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
+ share->commit_count= 0;
+ share->commit_count_lock= 0;
+ }
+ else
+ {
+ DBUG_PRINT("error", ("Failed to alloc share"));
+ pthread_mutex_unlock(&ndbcluster_mutex);
+ return 0;
}
}
share->use_count++;
+
+ DBUG_PRINT("share",
+ ("table_name: %s, length: %d, use_count: %d, commit_count: %d",
+ share->table_name, share->table_name_length, share->use_count,
+ share->commit_count));
pthread_mutex_unlock(&ndbcluster_mutex);
return share;
}
@@ -4903,7 +5314,7 @@ static void free_share(NDB_SHARE *share)
pthread_mutex_lock(&ndbcluster_mutex);
if (!--share->use_count)
{
- hash_delete(&ndbcluster_open_tables, (byte*) share);
+ hash_delete(&ndbcluster_open_tables, (byte*) share);
thr_lock_delete(&share->lock);
pthread_mutex_destroy(&share->mutex);
my_free((gptr) share, MYF(0));
@@ -4932,7 +5343,7 @@ struct frm_blob_struct
static int packfrm(const void *data, uint len,
- const void **pack_data, uint *pack_len)
+ const void **pack_data, uint *pack_len)
{
int error;
ulong org_len, comp_len;
@@ -4974,7 +5385,7 @@ err:
static int unpackfrm(const void **unpack_data, uint *unpack_len,
- const void *pack_data)
+ const void *pack_data)
{
const frm_blob_struct *blob= (frm_blob_struct*)pack_data;
byte *data;
@@ -4982,12 +5393,12 @@ static int unpackfrm(const void **unpack_data, uint *unpack_len,
DBUG_ENTER("unpackfrm");
DBUG_PRINT("enter", ("pack_data: %x", pack_data));
- complen= uint4korr((char*)&blob->head.complen);
- orglen= uint4korr((char*)&blob->head.orglen);
- ver= uint4korr((char*)&blob->head.ver);
+ complen= uint4korr((char*)&blob->head.complen);
+ orglen= uint4korr((char*)&blob->head.orglen);
+ ver= uint4korr((char*)&blob->head.ver);
DBUG_PRINT("blob",("ver: %d complen: %d orglen: %d",
- ver,complen,orglen));
+ ver,complen,orglen));
DBUG_DUMP("blob->data", (char*) blob->data, complen);
if (ver != 1)
@@ -5012,12 +5423,12 @@ static int unpackfrm(const void **unpack_data, uint *unpack_len,
static
int
-ndb_get_table_statistics(Ndb* ndb, const char * table,
- Uint64* row_count, Uint64* commit_count)
+ndb_get_table_statistics(Ndb* ndb, const char * table,
+ struct Ndb_statistics * ndbstat)
{
DBUG_ENTER("ndb_get_table_statistics");
DBUG_PRINT("enter", ("table: %s", table));
- NdbConnection* pTrans= ndb->startTransaction();
+ NdbTransaction* pTrans= ndb->startTransaction();
do
{
if (pTrans == NULL)
@@ -5027,45 +5438,63 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
if (pOp == NULL)
break;
- NdbResultSet* rs= pOp->readTuples(NdbOperation::LM_CommittedRead);
- if (rs == 0)
+ if (pOp->readTuples(NdbOperation::LM_CommittedRead))
break;
int check= pOp->interpret_exit_last_row();
if (check == -1)
break;
- Uint64 rows, commits;
+ Uint64 rows, commits, mem;
+ Uint32 size;
pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows);
pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits);
+ pOp->getValue(NdbDictionary::Column::ROW_SIZE, (char*)&size);
+ pOp->getValue(NdbDictionary::Column::FRAGMENT_MEMORY, (char*)&mem);
- check= pTrans->execute(NoCommit, AbortOnError, TRUE);
+ check= pTrans->execute(NdbTransaction::NoCommit,
+ NdbTransaction::AbortOnError,
+ TRUE);
if (check == -1)
break;
+ Uint32 count= 0;
Uint64 sum_rows= 0;
Uint64 sum_commits= 0;
- while((check= rs->nextResult(TRUE, TRUE)) == 0)
+ Uint64 sum_row_size= 0;
+ Uint64 sum_mem= 0;
+ while ((check= pOp->nextResult(TRUE, TRUE)) == 0)
{
sum_rows+= rows;
sum_commits+= commits;
+ if (sum_row_size < size)
+ sum_row_size= size;
+ sum_mem+= mem;
+ count++;
}
if (check == -1)
break;
- rs->close(TRUE);
+ pOp->close(TRUE);
ndb->closeTransaction(pTrans);
- if(row_count)
- * row_count= sum_rows;
- if(commit_count)
- * commit_count= sum_commits;
- DBUG_PRINT("exit", ("records: %u commits: %u", sum_rows, sum_commits));
+
+ ndbstat->row_count= sum_rows;
+ ndbstat->commit_count= sum_commits;
+ ndbstat->row_size= sum_row_size;
+ ndbstat->fragment_memory= sum_mem;
+
+ DBUG_PRINT("exit", ("records: %llu commits: %llu "
+ "row_size: %llu mem: %llu count: %u",
+ sum_rows, sum_commits, sum_row_size,
+ sum_mem, count));
+
DBUG_RETURN(0);
- } while(0);
+ } while (0);
- ndb->closeTransaction(pTrans);
+ if (pTrans)
+ ndb->closeTransaction(pTrans);
DBUG_PRINT("exit", ("failed"));
DBUG_RETURN(-1);
}
@@ -5085,7 +5514,7 @@ int ha_ndbcluster::write_ndb_file()
DBUG_PRINT("enter", ("db: %s, name: %s", m_dbname, m_tabname));
(void)strxnmov(path, FN_REFLEN,
- mysql_data_home,"/",m_dbname,"/",m_tabname,ha_ndb_ext,NullS);
+ mysql_data_home,"/",m_dbname,"/",m_tabname,ha_ndb_ext,NullS);
if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{
@@ -5096,4 +5525,1871 @@ int ha_ndbcluster::write_ndb_file()
DBUG_RETURN(error);
}
+int
+ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
+ KEY_MULTI_RANGE *ranges,
+ uint range_count,
+ bool sorted,
+ HANDLER_BUFFER *buffer)
+{
+ DBUG_ENTER("ha_ndbcluster::read_multi_range_first");
+
+ int res;
+ KEY* key_info= table->key_info + active_index;
+ NDB_INDEX_TYPE index_type= get_index_type(active_index);
+ ulong reclength= table->s->reclength;
+ NdbOperation* op;
+
+ if (uses_blob_value(m_retrieve_all_fields))
+ {
+ /**
+ * blobs can't be batched currently
+ */
+ m_disable_multi_read= TRUE;
+ DBUG_RETURN(handler::read_multi_range_first(found_range_p,
+ ranges,
+ range_count,
+ sorted,
+ buffer));
+ }
+
+ m_disable_multi_read= FALSE;
+
+ /**
+ * Copy arguments into member variables
+ */
+ m_multi_ranges= ranges;
+ multi_range_curr= ranges;
+ multi_range_end= ranges+range_count;
+ multi_range_sorted= sorted;
+ multi_range_buffer= buffer;
+
+ /**
+ * read multi range will read ranges as follows (if not ordered)
+ *
+ * input read order
+ * ====== ==========
+ * pk-op 1 pk-op 1
+ * pk-op 2 pk-op 2
+ * range 3 range (3,5) NOTE result rows will be intermixed
+ * pk-op 4 pk-op 4
+ * range 5
+ * pk-op 6 pk-ok 6
+ */
+
+ /**
+ * Variables for loop
+ */
+ byte *curr= (byte*)buffer->buffer;
+ byte *end_of_buffer= (byte*)buffer->buffer_end;
+ NdbOperation::LockMode lm=
+ (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
+ const NDBTAB *tab= (const NDBTAB *) m_table;
+ const NDBINDEX *unique_idx= (NDBINDEX *) m_index[active_index].unique_index;
+ const NDBINDEX *idx= (NDBINDEX *) m_index[active_index].index;
+ const NdbOperation* lastOp= m_active_trans->getLastDefinedOperation();
+ NdbIndexScanOperation* scanOp= 0;
+ for (; multi_range_curr<multi_range_end && curr+reclength <= end_of_buffer;
+ multi_range_curr++)
+ {
+ switch (index_type){
+ case PRIMARY_KEY_ORDERED_INDEX:
+ if (!(multi_range_curr->start_key.length == key_info->key_length &&
+ multi_range_curr->start_key.flag == HA_READ_KEY_EXACT))
+ goto range;
+ /* fall through */
+ case PRIMARY_KEY_INDEX:
+ {
+ multi_range_curr->range_flag |= UNIQUE_RANGE;
+ if ((op= m_active_trans->getNdbOperation(tab)) &&
+ !op->readTuple(lm) &&
+ !set_primary_key(op, multi_range_curr->start_key.key) &&
+ !define_read_attrs(curr, op) &&
+ (op->setAbortOption(AO_IgnoreError), TRUE))
+ curr += reclength;
+ else
+ ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
+ break;
+ }
+ break;
+ case UNIQUE_ORDERED_INDEX:
+ if (!(multi_range_curr->start_key.length == key_info->key_length &&
+ multi_range_curr->start_key.flag == HA_READ_KEY_EXACT &&
+ !check_null_in_key(key_info, multi_range_curr->start_key.key,
+ multi_range_curr->start_key.length)))
+ goto range;
+ /* fall through */
+ case UNIQUE_INDEX:
+ {
+ multi_range_curr->range_flag |= UNIQUE_RANGE;
+ if ((op= m_active_trans->getNdbIndexOperation(unique_idx, tab)) &&
+ !op->readTuple(lm) &&
+ !set_index_key(op, key_info, multi_range_curr->start_key.key) &&
+ !define_read_attrs(curr, op) &&
+ (op->setAbortOption(AO_IgnoreError), TRUE))
+ curr += reclength;
+ else
+ ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
+ break;
+ }
+ case ORDERED_INDEX:
+ {
+ range:
+ multi_range_curr->range_flag &= ~(uint)UNIQUE_RANGE;
+ if (scanOp == 0)
+ {
+ if (m_multi_cursor)
+ {
+ scanOp= m_multi_cursor;
+ DBUG_ASSERT(scanOp->getSorted() == sorted);
+ DBUG_ASSERT(scanOp->getLockMode() ==
+ (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type));
+ if (scanOp->reset_bounds(m_force_send))
+ DBUG_RETURN(ndb_err(m_active_trans));
+
+ end_of_buffer -= reclength;
+ }
+ else if ((scanOp= m_active_trans->getNdbIndexScanOperation(idx, tab))
+ &&!scanOp->readTuples(lm, 0, parallelism, sorted, FALSE, TRUE)
+ &&!generate_scan_filter(m_cond_stack, scanOp)
+ &&!define_read_attrs(end_of_buffer-reclength, scanOp))
+ {
+ m_multi_cursor= scanOp;
+ m_multi_range_cursor_result_ptr= end_of_buffer-reclength;
+ }
+ else
+ {
+ ERR_RETURN(scanOp ? scanOp->getNdbError() :
+ m_active_trans->getNdbError());
+ }
+ }
+
+ const key_range *keys[2]= { &multi_range_curr->start_key,
+ &multi_range_curr->end_key };
+ if ((res= set_bounds(scanOp, keys, multi_range_curr-ranges)))
+ DBUG_RETURN(res);
+ break;
+ }
+ case UNDEFINED_INDEX:
+ DBUG_ASSERT(FALSE);
+ DBUG_RETURN(1);
+ break;
+ }
+ }
+
+ if (multi_range_curr != multi_range_end)
+ {
+ /**
+ * Mark that we're using entire buffer (even if might not) as
+ * we haven't read all ranges for some reason
+ * This as we don't want mysqld to reuse the buffer when we read
+ * the remaining ranges
+ */
+ buffer->end_of_used_area= (byte*)buffer->buffer_end;
+ }
+ else
+ {
+ buffer->end_of_used_area= curr;
+ }
+
+ /**
+ * Set first operation in multi range
+ */
+ m_current_multi_operation=
+ lastOp ? lastOp->next() : m_active_trans->getFirstDefinedOperation();
+ if (!(res= execute_no_commit_ie(this, m_active_trans)))
+ {
+ m_multi_range_defined= multi_range_curr;
+ multi_range_curr= ranges;
+ m_multi_range_result_ptr= (byte*)buffer->buffer;
+ DBUG_RETURN(read_multi_range_next(found_range_p));
+ }
+ ERR_RETURN(m_active_trans->getNdbError());
+}
+
+#if 0
+#define DBUG_MULTI_RANGE(x) printf("read_multi_range_next: case %d\n", x);
+#else
+#define DBUG_MULTI_RANGE(x)
+#endif
+
+int
+ha_ndbcluster::read_multi_range_next(KEY_MULTI_RANGE ** multi_range_found_p)
+{
+ DBUG_ENTER("ha_ndbcluster::read_multi_range_next");
+ if (m_disable_multi_read)
+ {
+ DBUG_RETURN(handler::read_multi_range_next(multi_range_found_p));
+ }
+
+ int res;
+ int range_no;
+ ulong reclength= table->s->reclength;
+ const NdbOperation* op= m_current_multi_operation;
+ for (;multi_range_curr < m_multi_range_defined; multi_range_curr++)
+ {
+ if (multi_range_curr->range_flag & UNIQUE_RANGE)
+ {
+ if (op->getNdbError().code == 0)
+ goto found_next;
+
+ op= m_active_trans->getNextCompletedOperation(op);
+ m_multi_range_result_ptr += reclength;
+ continue;
+ }
+ else if (m_multi_cursor && !multi_range_sorted)
+ {
+ DBUG_MULTI_RANGE(1);
+ if ((res= fetch_next(m_multi_cursor)) == 0)
+ {
+ DBUG_MULTI_RANGE(2);
+ range_no= m_multi_cursor->get_range_no();
+ goto found;
+ }
+ else
+ {
+ goto close_scan;
+ }
+ }
+ else if (m_multi_cursor && multi_range_sorted)
+ {
+ if (m_active_cursor && (res= fetch_next(m_multi_cursor)))
+ {
+ DBUG_MULTI_RANGE(3);
+ goto close_scan;
+ }
+
+ range_no= m_multi_cursor->get_range_no();
+ uint current_range_no= multi_range_curr - m_multi_ranges;
+ if ((uint) range_no == current_range_no)
+ {
+ DBUG_MULTI_RANGE(4);
+ // return current row
+ goto found;
+ }
+ else if (range_no > (int)current_range_no)
+ {
+ DBUG_MULTI_RANGE(5);
+ // wait with current row
+ m_active_cursor= 0;
+ continue;
+ }
+ else
+ {
+ DBUG_MULTI_RANGE(6);
+ // First fetch from cursor
+ DBUG_ASSERT(range_no == -1);
+ if ((res= m_multi_cursor->nextResult(true)))
+ {
+ goto close_scan;
+ }
+ multi_range_curr--; // Will be increased in for-loop
+ continue;
+ }
+ }
+ else /** m_multi_cursor == 0 */
+ {
+ DBUG_MULTI_RANGE(7);
+ /**
+ * Corresponds to range 5 in example in read_multi_range_first
+ */
+ (void)1;
+ continue;
+ }
+
+ DBUG_ASSERT(FALSE); // Should only get here via goto's
+close_scan:
+ if (res == 1)
+ {
+ m_multi_cursor->close(FALSE, TRUE);
+ m_active_cursor= m_multi_cursor= 0;
+ DBUG_MULTI_RANGE(8);
+ continue;
+ }
+ else
+ {
+ DBUG_RETURN(ndb_err(m_active_trans));
+ }
+ }
+
+ if (multi_range_curr == multi_range_end)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ /**
+ * Read remaining ranges
+ */
+ DBUG_RETURN(read_multi_range_first(multi_range_found_p,
+ multi_range_curr,
+ multi_range_end - multi_range_curr,
+ multi_range_sorted,
+ multi_range_buffer));
+
+found:
+ /**
+ * Found a record belonging to a scan
+ */
+ m_active_cursor= m_multi_cursor;
+ * multi_range_found_p= m_multi_ranges + range_no;
+ memcpy(table->record[0], m_multi_range_cursor_result_ptr, reclength);
+ setup_recattr(m_active_cursor->getFirstRecAttr());
+ unpack_record(table->record[0]);
+ table->status= 0;
+ DBUG_RETURN(0);
+
+found_next:
+ /**
+ * Found a record belonging to a pk/index op,
+ * copy result and move to next to prepare for next call
+ */
+ * multi_range_found_p= multi_range_curr;
+ memcpy(table->record[0], m_multi_range_result_ptr, reclength);
+ setup_recattr(op->getFirstRecAttr());
+ unpack_record(table->record[0]);
+ table->status= 0;
+
+ multi_range_curr++;
+ m_current_multi_operation= m_active_trans->getNextCompletedOperation(op);
+ m_multi_range_result_ptr += reclength;
+ DBUG_RETURN(0);
+}
+
+int
+ha_ndbcluster::setup_recattr(const NdbRecAttr* curr)
+{
+ DBUG_ENTER("setup_recattr");
+
+ Field **field, **end;
+ NdbValue *value= m_value;
+
+ end= table->field + table->s->fields;
+
+ for (field= table->field; field < end; field++, value++)
+ {
+ if ((* value).ptr)
+ {
+ DBUG_ASSERT(curr != 0);
+ (* value).rec= curr;
+ curr= curr->next();
+ }
+ }
+
+ DBUG_RETURN(0);
+}
+
+char*
+ha_ndbcluster::update_table_comment(
+ /* out: table comment + additional */
+ const char* comment)/* in: table comment defined by user */
+{
+ uint length= strlen(comment);
+ if (length > 64000 - 3)
+ {
+ return((char*)comment); /* string too long */
+ }
+
+ Ndb* ndb;
+ if (!(ndb= get_ndb()))
+ {
+ return((char*)comment);
+ }
+
+ ndb->setDatabaseName(m_dbname);
+ NDBDICT* dict= ndb->getDictionary();
+ const NDBTAB* tab;
+ if (!(tab= dict->getTable(m_tabname)))
+ {
+ return((char*)comment);
+ }
+
+ char *str;
+ const char *fmt="%s%snumber_of_replicas: %d";
+ const unsigned fmt_len_plus_extra= length + strlen(fmt);
+ if ((str= my_malloc(fmt_len_plus_extra, MYF(0))) == NULL)
+ {
+ return (char*)comment;
+ }
+
+ my_snprintf(str,fmt_len_plus_extra,fmt,comment,
+ length > 0 ? " ":"",
+ tab->getReplicaCount());
+ return str;
+}
+
+
+// Utility thread main loop
+extern "C" pthread_handler_decl(ndb_util_thread_func,
+ arg __attribute__((unused)))
+{
+ THD *thd; /* needs to be first for thread_stack */
+ Ndb* ndb;
+ int error= 0;
+ struct timespec abstime;
+
+ my_thread_init();
+ DBUG_ENTER("ndb_util_thread");
+ DBUG_PRINT("enter", ("ndb_cache_check_time: %d", ndb_cache_check_time));
+
+ thd= new THD; /* note that contructor of THD uses DBUG_ */
+ THD_CHECK_SENTRY(thd);
+ ndb= new Ndb(g_ndb_cluster_connection, "");
+
+ pthread_detach_this_thread();
+ ndb_util_thread= pthread_self();
+
+ thd->thread_stack= (char*)&thd; /* remember where our stack is */
+ if (thd->store_globals() && (ndb->init() != -1))
+ {
+ thd->cleanup();
+ delete thd;
+ delete ndb;
+ DBUG_RETURN(NULL);
+ }
+
+ List<NDB_SHARE> util_open_tables;
+ set_timespec(abstime, 0);
+ for (;;)
+ {
+
+ pthread_mutex_lock(&LOCK_ndb_util_thread);
+ error= pthread_cond_timedwait(&COND_ndb_util_thread,
+ &LOCK_ndb_util_thread,
+ &abstime);
+ pthread_mutex_unlock(&LOCK_ndb_util_thread);
+
+ DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %d",
+ ndb_cache_check_time));
+
+ if (abort_loop)
+ break; /* Shutting down server */
+
+ if (ndb_cache_check_time == 0)
+ {
+ /* Wake up in 1 second to check if value has changed */
+ set_timespec(abstime, 1);
+ continue;
+ }
+
+ /* Lock mutex and fill list with pointers to all open tables */
+ NDB_SHARE *share;
+ pthread_mutex_lock(&ndbcluster_mutex);
+ for (uint i= 0; i < ndbcluster_open_tables.records; i++)
+ {
+ share= (NDB_SHARE *)hash_element(&ndbcluster_open_tables, i);
+ share->use_count++; /* Make sure the table can't be closed */
+ DBUG_PRINT("ndb_util_thread",
+ ("Found open table[%d]: %s, use_count: %d",
+ i, share->table_name, share->use_count));
+
+ /* Store pointer to table */
+ util_open_tables.push_back(share);
+ }
+ pthread_mutex_unlock(&ndbcluster_mutex);
+
+ /* Iterate through the open files list */
+ List_iterator_fast<NDB_SHARE> it(util_open_tables);
+ while ((share= it++))
+ {
+ /* Split tab- and dbname */
+ char buf[FN_REFLEN];
+ char *tabname, *db;
+ uint length= dirname_length(share->table_name);
+ tabname= share->table_name+length;
+ memcpy(buf, share->table_name, length-1);
+ buf[length-1]= 0;
+ db= buf+dirname_length(buf);
+ DBUG_PRINT("ndb_util_thread",
+ ("Fetching commit count for: %s",
+ share->table_name));
+
+ /* Contact NDB to get commit count for table */
+ ndb->setDatabaseName(db);
+ struct Ndb_statistics stat;
+
+ uint lock;
+ pthread_mutex_lock(&share->mutex);
+ lock= share->commit_count_lock;
+ pthread_mutex_unlock(&share->mutex);
+
+ if (ndb_get_table_statistics(ndb, tabname, &stat) == 0)
+ {
+ DBUG_PRINT("ndb_util_thread",
+ ("Table: %s, commit_count: %llu, rows: %llu",
+ share->table_name, stat.commit_count, stat.row_count));
+ }
+ else
+ {
+ DBUG_PRINT("ndb_util_thread",
+ ("Error: Could not get commit count for table %s",
+ share->table_name));
+ stat.commit_count= 0;
+ }
+
+ pthread_mutex_lock(&share->mutex);
+ if (share->commit_count_lock == lock)
+ share->commit_count= stat.commit_count;
+ pthread_mutex_unlock(&share->mutex);
+
+ /* Decrease the use count and possibly free share */
+ free_share(share);
+ }
+
+ /* Clear the list of open tables */
+ util_open_tables.empty();
+
+ /* Calculate new time to wake up */
+ int secs= 0;
+ int msecs= ndb_cache_check_time;
+
+ struct timeval tick_time;
+ gettimeofday(&tick_time, 0);
+ abstime.tv_sec= tick_time.tv_sec;
+ abstime.tv_nsec= tick_time.tv_usec * 1000;
+
+ if (msecs >= 1000){
+ secs= msecs / 1000;
+ msecs= msecs % 1000;
+ }
+
+ abstime.tv_sec+= secs;
+ abstime.tv_nsec+= msecs * 1000000;
+ if (abstime.tv_nsec >= 1000000000) {
+ abstime.tv_sec+= 1;
+ abstime.tv_nsec-= 1000000000;
+ }
+ }
+
+ thd->cleanup();
+ delete thd;
+ delete ndb;
+ DBUG_PRINT("exit", ("ndb_util_thread"));
+ my_thread_end();
+ pthread_exit(0);
+ DBUG_RETURN(NULL);
+}
+
+/*
+ Condition pushdown
+*/
+/*
+ Push a condition to ndbcluster storage engine for evaluation
+ during table and index scans. The conditions will be stored on a stack
+ for possibly storing several conditions. The stack can be popped
+ by calling cond_pop, handler::extra(HA_EXTRA_RESET) (handler::reset())
+ will clear the stack.
+ The current implementation supports arbitrary AND/OR nested conditions
+ with comparisons between columns and constants (including constant
+ expressions and function calls) and the following comparison operators:
+ =, !=, >, >=, <, <=, "is null", and "is not null".
+
+ RETURN
+ NULL The condition was supported and will be evaluated for each
+ row found during the scan
+ cond The condition was not supported and all rows will be returned from
+ the scan for evaluation (and thus not saved on stack)
+*/
+const
+COND*
+ha_ndbcluster::cond_push(const COND *cond)
+{
+ DBUG_ENTER("cond_push");
+ Ndb_cond_stack *ndb_cond = new Ndb_cond_stack();
+ DBUG_EXECUTE("where",print_where((COND *)cond, m_tabname););
+ if (m_cond_stack)
+ ndb_cond->next= m_cond_stack;
+ else
+ ndb_cond->next= NULL;
+ m_cond_stack= ndb_cond;
+
+ if (serialize_cond(cond, ndb_cond))
+ {
+ DBUG_RETURN(NULL);
+ }
+ else
+ {
+ cond_pop();
+ }
+ DBUG_RETURN(cond);
+}
+
+/*
+ Pop the top condition from the condition stack of the handler instance.
+*/
+void
+ha_ndbcluster::cond_pop()
+{
+ Ndb_cond_stack *ndb_cond_stack= m_cond_stack;
+ if (ndb_cond_stack)
+ {
+ m_cond_stack= ndb_cond_stack->next;
+ delete ndb_cond_stack;
+ }
+}
+
+/*
+ Clear the condition stack
+*/
+void
+ha_ndbcluster::cond_clear()
+{
+ DBUG_ENTER("cond_clear");
+ while (m_cond_stack)
+ cond_pop();
+
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Serialize the item tree into a linked list represented by Ndb_cond
+ for fast generation of NbdScanFilter. Adds information such as
+ position of fields that is not directly available in the Item tree.
+ Also checks if condition is supported.
+*/
+void ndb_serialize_cond(const Item *item, void *arg)
+{
+ Ndb_cond_traverse_context *context= (Ndb_cond_traverse_context *) arg;
+ DBUG_ENTER("ndb_serialize_cond");
+
+ // Check if we are skipping arguments to a function to be evaluated
+ if (context->skip)
+ {
+ DBUG_PRINT("info", ("Skiping argument %d", context->skip));
+ context->skip--;
+ switch (item->type()) {
+ case Item::FUNC_ITEM:
+ {
+ Item_func *func_item= (Item_func *) item;
+ context->skip+= func_item->argument_count();
+ break;
+ }
+ case Item::INT_ITEM:
+ case Item::REAL_ITEM:
+ case Item::STRING_ITEM:
+ case Item::VARBIN_ITEM:
+ case Item::DECIMAL_ITEM:
+ break;
+ default:
+ context->supported= FALSE;
+ break;
+ }
+
+ DBUG_VOID_RETURN;
+ }
+
+ if (context->supported)
+ {
+ Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
+ const Item_func *func_item;
+ // Check if we are rewriting some unsupported function call
+ if (rewrite_context &&
+ (func_item= rewrite_context->func_item) &&
+ rewrite_context->count++ == 0)
+ {
+ switch (func_item->functype()) {
+ case Item_func::BETWEEN:
+ /*
+ Rewrite
+ <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2>
+ to <field>|<const> > <const1>|<field1> AND
+ <field>|<const> < <const2>|<field2>
+ or actually in prefix format
+ BEGIN(AND) GT(<field>|<const>, <const1>|<field1>),
+ LT(<field>|<const>, <const2>|<field2>), END()
+ */
+ case Item_func::IN_FUNC:
+ {
+ /*
+ Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..)
+ to <field>|<const> = <const1>|<field1> OR
+ <field> = <const2>|<field2> ...
+ or actually in prefix format
+ BEGIN(OR) EQ(<field>|<const>, <const1><field1>),
+ EQ(<field>|<const>, <const2>|<field2>), ... END()
+ Each part of the disjunction is added for each call
+ to ndb_serialize_cond and end of rewrite statement
+ is wrapped in end of ndb_serialize_cond
+ */
+ if (context->expecting(item->type()))
+ {
+ // This is the <field>|<const> item, save it in the rewrite context
+ rewrite_context->left_hand_item= item;
+ if (item->type() == Item::FUNC_ITEM)
+ {
+ Item_func *func_item= (Item_func *) item;
+ if (func_item->functype() == Item_func::UNKNOWN_FUNC &&
+ func_item->const_item())
+ {
+ // Skip any arguments since we will evaluate function instead
+ DBUG_PRINT("info", ("Skip until end of arguments marker"));
+ context->skip= func_item->argument_count();
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Found unsupported functional expression in BETWEEN|IN"));
+ context->supported= FALSE;
+ DBUG_VOID_RETURN;
+
+ }
+ }
+ }
+ else
+ {
+ // Non-supported BETWEEN|IN expression
+ DBUG_PRINT("info", ("Found unexpected item of type %u in BETWEEN|IN",
+ item->type()));
+ context->supported= FALSE;
+ DBUG_VOID_RETURN;
+ }
+ break;
+ }
+ default:
+ context->supported= FALSE;
+ break;
+ }
+ DBUG_VOID_RETURN;
+ }
+ else
+ {
+ Ndb_cond_stack *ndb_stack= context->stack_ptr;
+ Ndb_cond *prev_cond= context->cond_ptr;
+ Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond();
+ if (!ndb_stack->ndb_cond)
+ ndb_stack->ndb_cond= curr_cond;
+ curr_cond->prev= prev_cond;
+ if (prev_cond) prev_cond->next= curr_cond;
+ // Check if we are rewriting some unsupported function call
+ if (context->rewrite_stack)
+ {
+ Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
+ const Item_func *func_item= rewrite_context->func_item;
+ switch (func_item->functype()) {
+ case Item_func::BETWEEN:
+ {
+ /*
+ Rewrite
+ <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2>
+ to <field>|<const> > <const1>|<field1> AND
+ <field>|<const> < <const2>|<field2>
+ or actually in prefix format
+ BEGIN(AND) GT(<field>|<const>, <const1>|<field1>),
+ LT(<field>|<const>, <const2>|<field2>), END()
+ */
+ if (rewrite_context->count == 2)
+ {
+ // Lower limit of BETWEEN
+ DBUG_PRINT("info", ("GE_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(Item_func::GE_FUNC, 2);
+ }
+ else if (rewrite_context->count == 3)
+ {
+ // Upper limit of BETWEEN
+ DBUG_PRINT("info", ("LE_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(Item_func::LE_FUNC, 2);
+ }
+ else
+ {
+ // Illegal BETWEEN expression
+ DBUG_PRINT("info", ("Illegal BETWEEN expression"));
+ context->supported= FALSE;
+ DBUG_VOID_RETURN;
+ }
+ break;
+ }
+ case Item_func::IN_FUNC:
+ {
+ /*
+ Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..)
+ to <field>|<const> = <const1>|<field1> OR
+ <field> = <const2>|<field2> ...
+ or actually in prefix format
+ BEGIN(OR) EQ(<field>|<const>, <const1><field1>),
+ EQ(<field>|<const>, <const2>|<field2>), ... END()
+ Each part of the disjunction is added for each call
+ to ndb_serialize_cond and end of rewrite statement
+ is wrapped in end of ndb_serialize_cond
+ */
+ DBUG_PRINT("info", ("EQ_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(Item_func::EQ_FUNC, 2);
+ break;
+ }
+ default:
+ context->supported= FALSE;
+ }
+ // Handle left hand <field>|<const>
+ context->rewrite_stack= NULL; // Disable rewrite mode
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FUNC_ITEM);
+ ndb_serialize_cond(rewrite_context->left_hand_item, arg);
+ context->skip= 0; // Any FUNC_ITEM expression has already been parsed
+ context->rewrite_stack= rewrite_context; // Enable rewrite mode
+ if (!context->supported)
+ DBUG_VOID_RETURN;
+
+ prev_cond= context->cond_ptr;
+ curr_cond= context->cond_ptr= new Ndb_cond();
+ prev_cond->next= curr_cond;
+ }
+
+ // Check for end of AND/OR expression
+ if (!item)
+ {
+ // End marker for condition group
+ DBUG_PRINT("info", ("End of condition group"));
+ curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
+ }
+ else
+ {
+ switch (item->type()) {
+ case Item::FIELD_ITEM:
+ {
+ Item_field *field_item= (Item_field *) item;
+ Field *field= field_item->field;
+ enum_field_types type= field->type();
+ /*
+ Check that the field is part of the table of the handler
+ instance and that we expect a field with of this result type.
+ */
+ if (context->table == field->table)
+ {
+ const NDBTAB *tab= (const NDBTAB *) context->ndb_table;
+ DBUG_PRINT("info", ("FIELD_ITEM"));
+ DBUG_PRINT("info", ("table %s", tab->getName()));
+ DBUG_PRINT("info", ("column %s", field->field_name));
+ DBUG_PRINT("info", ("result type %d", field->result_type()));
+
+ // Check that we are expecting a field and with the correct
+ // result type
+ if (context->expecting(Item::FIELD_ITEM) &&
+ (context->expecting_field_result(field->result_type()) ||
+ // Date and year can be written as string or int
+ ((type == MYSQL_TYPE_TIME ||
+ type == MYSQL_TYPE_DATE ||
+ type == MYSQL_TYPE_YEAR ||
+ type == MYSQL_TYPE_DATETIME)
+ ? (context->expecting_field_result(STRING_RESULT) ||
+ context->expecting_field_result(INT_RESULT))
+ : true)) &&
+ // Bit fields no yet supported in scan filter
+ type != MYSQL_TYPE_BIT)
+ {
+ const NDBCOL *col= tab->getColumn(field->field_name);
+ DBUG_ASSERT(col);
+ curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo());
+ context->dont_expect(Item::FIELD_ITEM);
+ context->expect_no_field_result();
+ if (context->expect_mask)
+ {
+ // We have not seen second argument yet
+ if (type == MYSQL_TYPE_TIME ||
+ type == MYSQL_TYPE_DATE ||
+ type == MYSQL_TYPE_YEAR ||
+ type == MYSQL_TYPE_DATETIME)
+ {
+ context->expect_only(Item::STRING_ITEM);
+ context->expect(Item::INT_ITEM);
+ }
+ else
+ switch (field->result_type()) {
+ case STRING_RESULT:
+ // Expect char string or binary string
+ context->expect_only(Item::STRING_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect_collation(field_item->collation.collation);
+ break;
+ case REAL_RESULT:
+ context->expect_only(Item::REAL_ITEM);
+ context->expect(Item::DECIMAL_ITEM);
+ context->expect(Item::INT_ITEM);
+ break;
+ case INT_RESULT:
+ context->expect_only(Item::INT_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ break;
+ case DECIMAL_RESULT:
+ context->expect_only(Item::DECIMAL_ITEM);
+ context->expect(Item::REAL_ITEM);
+ context->expect(Item::INT_ITEM);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ // Check that field and string constant collations are the same
+ if ((field->result_type() == STRING_RESULT) &&
+ !context->expecting_collation(item->collation.collation)
+ && type != MYSQL_TYPE_TIME
+ && type != MYSQL_TYPE_DATE
+ && type != MYSQL_TYPE_YEAR
+ && type != MYSQL_TYPE_DATETIME)
+ {
+ DBUG_PRINT("info", ("Found non-matching collation %s",
+ item->collation.collation->name));
+ context->supported= FALSE;
+ }
+ }
+ break;
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Was not expecting field of type %u(%u)",
+ field->result_type(), type));
+ context->supported= FALSE;
+ }
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Was not expecting field from table %s(%s)",
+ context->table->s->table_name,
+ field->table->s->table_name));
+ context->supported= FALSE;
+ }
+ break;
+ }
+ case Item::FUNC_ITEM:
+ {
+ Item_func *func_item= (Item_func *) item;
+ // Check that we expect a function or functional expression here
+ if (context->expecting(Item::FUNC_ITEM) ||
+ func_item->functype() == Item_func::UNKNOWN_FUNC)
+ context->expect_nothing();
+ else
+ {
+ // Did not expect function here
+ context->supported= FALSE;
+ break;
+ }
+
+ switch (func_item->functype()) {
+ case Item_func::EQ_FUNC:
+ {
+ DBUG_PRINT("info", ("EQ_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::REAL_ITEM);
+ context->expect(Item::DECIMAL_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ break;
+ }
+ case Item_func::NE_FUNC:
+ {
+ DBUG_PRINT("info", ("NE_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::REAL_ITEM);
+ context->expect(Item::DECIMAL_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ break;
+ }
+ case Item_func::LT_FUNC:
+ {
+ DBUG_PRINT("info", ("LT_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::REAL_ITEM);
+ context->expect(Item::DECIMAL_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ break;
+ }
+ case Item_func::LE_FUNC:
+ {
+ DBUG_PRINT("info", ("LE_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::REAL_ITEM);
+ context->expect(Item::DECIMAL_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ break;
+ }
+ case Item_func::GE_FUNC:
+ {
+ DBUG_PRINT("info", ("GE_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::REAL_ITEM);
+ context->expect(Item::DECIMAL_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ break;
+ }
+ case Item_func::GT_FUNC:
+ {
+ DBUG_PRINT("info", ("GT_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::REAL_ITEM);
+ context->expect(Item::DECIMAL_ITEM);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ break;
+ }
+ case Item_func::LIKE_FUNC:
+ {
+ DBUG_PRINT("info", ("LIKE_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect(Item::FUNC_ITEM);
+ break;
+ }
+ case Item_func::ISNULL_FUNC:
+ {
+ DBUG_PRINT("info", ("ISNULL_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ break;
+ }
+ case Item_func::ISNOTNULL_FUNC:
+ {
+ DBUG_PRINT("info", ("ISNOTNULL_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::FIELD_ITEM);
+ context->expect_field_result(STRING_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(INT_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ break;
+ }
+ case Item_func::NOT_FUNC:
+ {
+ DBUG_PRINT("info", ("NOT_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+ func_item);
+ context->expect(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ break;
+ }
+ case Item_func::BETWEEN:
+ {
+ DBUG_PRINT("info", ("BETWEEN, rewriting using AND"));
+ Item_func_between *between_func= (Item_func_between *) func_item;
+ Ndb_rewrite_context *rewrite_context=
+ new Ndb_rewrite_context(func_item);
+ rewrite_context->next= context->rewrite_stack;
+ context->rewrite_stack= rewrite_context;
+ if (between_func->negated)
+ {
+ DBUG_PRINT("info", ("NOT_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(Item_func::NOT_FUNC, 1);
+ prev_cond= curr_cond;
+ curr_cond= context->cond_ptr= new Ndb_cond();
+ curr_cond->prev= prev_cond;
+ prev_cond->next= curr_cond;
+ }
+ DBUG_PRINT("info", ("COND_AND_FUNC"));
+ curr_cond->ndb_item=
+ new Ndb_item(Item_func::COND_AND_FUNC,
+ func_item->argument_count() - 1);
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FUNC_ITEM);
+ break;
+ }
+ case Item_func::IN_FUNC:
+ {
+ DBUG_PRINT("info", ("IN_FUNC, rewriting using OR"));
+ Item_func_in *in_func= (Item_func_in *) func_item;
+ Ndb_rewrite_context *rewrite_context=
+ new Ndb_rewrite_context(func_item);
+ rewrite_context->next= context->rewrite_stack;
+ context->rewrite_stack= rewrite_context;
+ if (in_func->negated)
+ {
+ DBUG_PRINT("info", ("NOT_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(Item_func::NOT_FUNC, 1);
+ prev_cond= curr_cond;
+ curr_cond= context->cond_ptr= new Ndb_cond();
+ curr_cond->prev= prev_cond;
+ prev_cond->next= curr_cond;
+ }
+ DBUG_PRINT("info", ("COND_OR_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(Item_func::COND_OR_FUNC,
+ func_item->argument_count() - 1);
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect(Item::INT_ITEM);
+ context->expect(Item::STRING_ITEM);
+ context->expect(Item::VARBIN_ITEM);
+ context->expect(Item::FUNC_ITEM);
+ break;
+ }
+ case Item_func::UNKNOWN_FUNC:
+ {
+ DBUG_PRINT("info", ("UNKNOWN_FUNC %s",
+ func_item->const_item()?"const":""));
+ DBUG_PRINT("info", ("result type %d", func_item->result_type()));
+ if (func_item->const_item())
+ {
+ switch (func_item->result_type()) {
+ case STRING_RESULT:
+ {
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::STRING_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(STRING_RESULT);
+ context->expect_collation(func_item->collation.collation);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ // Check that string result have correct collation
+ if (!context->expecting_collation(item->collation.collation))
+ {
+ DBUG_PRINT("info", ("Found non-matching collation %s",
+ item->collation.collation->name));
+ context->supported= FALSE;
+ }
+ }
+ // Skip any arguments since we will evaluate function instead
+ DBUG_PRINT("info", ("Skip until end of arguments marker"));
+ context->skip= func_item->argument_count();
+ break;
+ }
+ case REAL_RESULT:
+ {
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::REAL_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(REAL_RESULT);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ }
+
+ // Skip any arguments since we will evaluate function instead
+ DBUG_PRINT("info", ("Skip until end of arguments marker"));
+ context->skip= func_item->argument_count();
+ break;
+ }
+ case INT_RESULT:
+ {
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::INT_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(INT_RESULT);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ }
+
+ // Skip any arguments since we will evaluate function instead
+ DBUG_PRINT("info", ("Skip until end of arguments marker"));
+ context->skip= func_item->argument_count();
+ break;
+ }
+ case DECIMAL_RESULT:
+ {
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::DECIMAL_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(DECIMAL_RESULT);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ }
+ // Skip any arguments since we will evaluate function instead
+ DBUG_PRINT("info", ("Skip until end of arguments marker"));
+ context->skip= func_item->argument_count();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else
+ // Function does not return constant expression
+ context->supported= FALSE;
+ break;
+ }
+ default:
+ {
+ DBUG_PRINT("info", ("Found func_item of type %d",
+ func_item->functype()));
+ context->supported= FALSE;
+ }
+ }
+ break;
+ }
+ case Item::STRING_ITEM:
+ DBUG_PRINT("info", ("STRING_ITEM"));
+ if (context->expecting(Item::STRING_ITEM))
+ {
+#ifndef DBUG_OFF
+ char buff[256];
+ String str(buff,(uint32) sizeof(buff), system_charset_info);
+ str.length(0);
+ Item_string *string_item= (Item_string *) item;
+ DBUG_PRINT("info", ("value \"%s\"",
+ string_item->val_str(&str)->ptr()));
+#endif
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::STRING_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(STRING_RESULT);
+ context->expect_collation(item->collation.collation);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ // Check that we are comparing with a field with same collation
+ if (!context->expecting_collation(item->collation.collation))
+ {
+ DBUG_PRINT("info", ("Found non-matching collation %s",
+ item->collation.collation->name));
+ context->supported= FALSE;
+ }
+ }
+ }
+ else
+ context->supported= FALSE;
+ break;
+ case Item::INT_ITEM:
+ DBUG_PRINT("info", ("INT_ITEM"));
+ if (context->expecting(Item::INT_ITEM))
+ {
+ Item_int *int_item= (Item_int *) item;
+ DBUG_PRINT("info", ("value %d", int_item->value));
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::INT_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(INT_RESULT);
+ context->expect_field_result(REAL_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ }
+ }
+ else
+ context->supported= FALSE;
+ break;
+ case Item::REAL_ITEM:
+ DBUG_PRINT("info", ("REAL_ITEM %s"));
+ if (context->expecting(Item::REAL_ITEM))
+ {
+ Item_float *float_item= (Item_float *) item;
+ DBUG_PRINT("info", ("value %f", float_item->value));
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::REAL_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(REAL_RESULT);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ }
+ }
+ else
+ context->supported= FALSE;
+ break;
+ case Item::VARBIN_ITEM:
+ DBUG_PRINT("info", ("VARBIN_ITEM"));
+ if (context->expecting(Item::VARBIN_ITEM))
+ {
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::VARBIN_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(STRING_RESULT);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ }
+ }
+ else
+ context->supported= FALSE;
+ break;
+ case Item::DECIMAL_ITEM:
+ DBUG_PRINT("info", ("DECIMAL_ITEM %s"));
+ if (context->expecting(Item::DECIMAL_ITEM))
+ {
+ Item_decimal *decimal_item= (Item_decimal *) item;
+ DBUG_PRINT("info", ("value %f", decimal_item->val_real()));
+ NDB_ITEM_QUALIFICATION q;
+ q.value_type= Item::DECIMAL_ITEM;
+ curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+ if (context->expect_field_result_mask)
+ {
+ // We have not seen the field argument yet
+ context->expect_only(Item::FIELD_ITEM);
+ context->expect_only_field_result(REAL_RESULT);
+ context->expect_field_result(DECIMAL_RESULT);
+ }
+ else
+ {
+ // Expect another logical expression
+ context->expect_only(Item::FUNC_ITEM);
+ context->expect(Item::COND_ITEM);
+ }
+ }
+ else
+ context->supported= FALSE;
+ break;
+ case Item::COND_ITEM:
+ {
+ Item_cond *cond_item= (Item_cond *) item;
+
+ if (context->expecting(Item::COND_ITEM))
+ {
+ switch (cond_item->functype()) {
+ case Item_func::COND_AND_FUNC:
+ DBUG_PRINT("info", ("COND_AND_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
+ cond_item);
+ break;
+ case Item_func::COND_OR_FUNC:
+ DBUG_PRINT("info", ("COND_OR_FUNC"));
+ curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
+ cond_item);
+ break;
+ default:
+ DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype()));
+ context->supported= FALSE;
+ break;
+ }
+ }
+ else
+ {
+ /* Did not expect condition */
+ context->supported= FALSE;
+ }
+ break;
+ }
+ default:
+ {
+ DBUG_PRINT("info", ("Found item of type %d", item->type()));
+ context->supported= FALSE;
+ }
+ }
+ }
+ if (context->supported && context->rewrite_stack)
+ {
+ Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
+ if (rewrite_context->count ==
+ rewrite_context->func_item->argument_count())
+ {
+ // Rewrite is done, wrap an END() at the en
+ DBUG_PRINT("info", ("End of condition group"));
+ prev_cond= curr_cond;
+ curr_cond= context->cond_ptr= new Ndb_cond();
+ curr_cond->prev= prev_cond;
+ prev_cond->next= curr_cond;
+ curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
+ // Pop rewrite stack
+ context->rewrite_stack= context->rewrite_stack->next;
+ }
+ }
+ }
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+bool
+ha_ndbcluster::serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond)
+{
+ DBUG_ENTER("serialize_cond");
+ Item *item= (Item *) cond;
+ Ndb_cond_traverse_context context(table, (void *)m_table, ndb_cond);
+ // Expect a logical expression
+ context.expect(Item::FUNC_ITEM);
+ context.expect(Item::COND_ITEM);
+ item->traverse_cond(&ndb_serialize_cond, (void *) &context, Item::PREFIX);
+ DBUG_PRINT("info", ("The pushed condition is %ssupported", (context.supported)?"":"not "));
+
+ DBUG_RETURN(context.supported);
+}
+
+int
+ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
+ NdbScanFilter *filter,
+ bool negated)
+{
+ DBUG_ENTER("build_scan_filter_predicate");
+ switch (cond->ndb_item->type) {
+ case NDB_FUNCTION:
+ {
+ if (!cond->next)
+ break;
+ Ndb_item *a= cond->next->ndb_item;
+ Ndb_item *b, *field, *value= NULL;
+ LINT_INIT(field);
+
+ switch (cond->ndb_item->argument_count()) {
+ case 1:
+ field=
+ (a->type == NDB_FIELD)? a : NULL;
+ break;
+ case 2:
+ if (!cond->next->next)
+ break;
+ b= cond->next->next->ndb_item;
+ value=
+ (a->type == NDB_VALUE)? a
+ : (b->type == NDB_VALUE)? b
+ : NULL;
+ field=
+ (a->type == NDB_FIELD)? a
+ : (b->type == NDB_FIELD)? b
+ : NULL;
+ break;
+ default:
+ break;
+ }
+ switch ((negated) ?
+ Ndb_item::negate(cond->ndb_item->qualification.function_type)
+ : cond->ndb_item->qualification.function_type) {
+ case NDB_EQ_FUNC:
+ {
+ if (!value || !field) break;
+ // Save value in right format for the field type
+ value->save_in_field(field);
+ DBUG_PRINT("info", ("Generating EQ filter"));
+ if (filter->cmp(NdbScanFilter::COND_EQ,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ cond= cond->next->next->next;
+ DBUG_RETURN(0);
+ }
+ case NDB_NE_FUNC:
+ {
+ if (!value || !field) break;
+ // Save value in right format for the field type
+ value->save_in_field(field);
+ DBUG_PRINT("info", ("Generating NE filter"));
+ if (filter->cmp(NdbScanFilter::COND_NE,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ cond= cond->next->next->next;
+ DBUG_RETURN(0);
+ }
+ case NDB_LT_FUNC:
+ {
+ if (!value || !field) break;
+ // Save value in right format for the field type
+ value->save_in_field(field);
+ if (a == field)
+ {
+ DBUG_PRINT("info", ("Generating LT filter"));
+ if (filter->cmp(NdbScanFilter::COND_LT,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Generating GT filter"));
+ if (filter->cmp(NdbScanFilter::COND_GT,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ }
+ cond= cond->next->next->next;
+ DBUG_RETURN(0);
+ }
+ case NDB_LE_FUNC:
+ {
+ if (!value || !field) break;
+ // Save value in right format for the field type
+ value->save_in_field(field);
+ if (a == field)
+ {
+ DBUG_PRINT("info", ("Generating LE filter"));
+ if (filter->cmp(NdbScanFilter::COND_LE,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Generating GE filter"));
+ if (filter->cmp(NdbScanFilter::COND_GE,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ }
+ cond= cond->next->next->next;
+ DBUG_RETURN(0);
+ }
+ case NDB_GE_FUNC:
+ {
+ if (!value || !field) break;
+ // Save value in right format for the field type
+ value->save_in_field(field);
+ if (a == field)
+ {
+ DBUG_PRINT("info", ("Generating GE filter"));
+ if (filter->cmp(NdbScanFilter::COND_GE,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Generating LE filter"));
+ if (filter->cmp(NdbScanFilter::COND_LE,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ }
+ cond= cond->next->next->next;
+ DBUG_RETURN(0);
+ }
+ case NDB_GT_FUNC:
+ {
+ if (!value || !field) break;
+ // Save value in right format for the field type
+ value->save_in_field(field);
+ if (a == field)
+ {
+ DBUG_PRINT("info", ("Generating GT filter"));
+ if (filter->cmp(NdbScanFilter::COND_GT,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Generating LT filter"));
+ if (filter->cmp(NdbScanFilter::COND_LT,
+ field->get_field_no(),
+ field->get_val(),
+ field->pack_length()) == -1)
+ DBUG_RETURN(1);
+ }
+ cond= cond->next->next->next;
+ DBUG_RETURN(0);
+ }
+ case NDB_LIKE_FUNC:
+ {
+ if (!value || !field) break;
+ if ((value->qualification.value_type != Item::STRING_ITEM) &&
+ (value->qualification.value_type != Item::VARBIN_ITEM))
+ break;
+ // Save value in right format for the field type
+ value->save_in_field(field);
+ DBUG_PRINT("info", ("Generating LIKE filter: like(%d,%s,%d)",
+ field->get_field_no(), value->get_val(),
+ value->pack_length()));
+ if (filter->cmp(NdbScanFilter::COND_LIKE,
+ field->get_field_no(),
+ value->get_val(),
+ value->pack_length()) == -1)
+ DBUG_RETURN(1);
+ cond= cond->next->next->next;
+ DBUG_RETURN(0);
+ }
+ case NDB_NOTLIKE_FUNC:
+ {
+ if (!value || !field) break;
+ if ((value->qualification.value_type != Item::STRING_ITEM) &&
+ (value->qualification.value_type != Item::VARBIN_ITEM))
+ break;
+ // Save value in right format for the field type
+ value->save_in_field(field);
+ DBUG_PRINT("info", ("Generating NOTLIKE filter: notlike(%d,%s,%d)",
+ field->get_field_no(), value->get_val(),
+ value->pack_length()));
+ if (filter->cmp(NdbScanFilter::COND_NOT_LIKE,
+ field->get_field_no(),
+ value->get_val(),
+ value->pack_length()) == -1)
+ DBUG_RETURN(1);
+ cond= cond->next->next->next;
+ DBUG_RETURN(0);
+ }
+ case NDB_ISNULL_FUNC:
+ if (!field)
+ break;
+ DBUG_PRINT("info", ("Generating ISNULL filter"));
+ if (filter->isnull(field->get_field_no()) == -1)
+ DBUG_RETURN(1);
+ cond= cond->next->next;
+ DBUG_RETURN(0);
+ case NDB_ISNOTNULL_FUNC:
+ {
+ if (!field)
+ break;
+ DBUG_PRINT("info", ("Generating ISNOTNULL filter"));
+ if (filter->isnotnull(field->get_field_no()) == -1)
+ DBUG_RETURN(1);
+ cond= cond->next->next;
+ DBUG_RETURN(0);
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ DBUG_PRINT("info", ("Found illegal condition"));
+ DBUG_RETURN(1);
+}
+
+int
+ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter)
+{
+ uint level=0;
+ bool negated= FALSE;
+ DBUG_ENTER("build_scan_filter_group");
+
+ do
+ {
+ if (!cond)
+ DBUG_RETURN(1);
+ switch (cond->ndb_item->type) {
+ case NDB_FUNCTION:
+ {
+ switch (cond->ndb_item->qualification.function_type) {
+ case NDB_COND_AND_FUNC:
+ {
+ level++;
+ DBUG_PRINT("info", ("Generating %s group %u", (negated)?"NAND":"AND",
+ level));
+ if ((negated) ? filter->begin(NdbScanFilter::NAND)
+ : filter->begin(NdbScanFilter::AND) == -1)
+ DBUG_RETURN(1);
+ negated= FALSE;
+ cond= cond->next;
+ break;
+ }
+ case NDB_COND_OR_FUNC:
+ {
+ level++;
+ DBUG_PRINT("info", ("Generating %s group %u", (negated)?"NOR":"OR",
+ level));
+ if ((negated) ? filter->begin(NdbScanFilter::NOR)
+ : filter->begin(NdbScanFilter::OR) == -1)
+ DBUG_RETURN(1);
+ negated= FALSE;
+ cond= cond->next;
+ break;
+ }
+ case NDB_NOT_FUNC:
+ {
+ DBUG_PRINT("info", ("Generating negated query"));
+ cond= cond->next;
+ negated= TRUE;
+ break;
+ }
+ default:
+ if (build_scan_filter_predicate(cond, filter, negated))
+ DBUG_RETURN(1);
+ negated= FALSE;
+ break;
+ }
+ break;
+ }
+ case NDB_END_COND:
+ DBUG_PRINT("info", ("End of group %u", level));
+ level--;
+ if (cond) cond= cond->next;
+ if (filter->end() == -1)
+ DBUG_RETURN(1);
+ if (!negated)
+ break;
+ // else fall through (NOT END is an illegal condition)
+ default:
+ {
+ DBUG_PRINT("info", ("Illegal scan filter"));
+ }
+ }
+ } while (level > 0 || negated);
+
+ DBUG_RETURN(0);
+}
+
+int
+ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter)
+{
+ bool simple_cond= TRUE;
+ DBUG_ENTER("build_scan_filter");
+
+ switch (cond->ndb_item->type) {
+ case NDB_FUNCTION:
+ switch (cond->ndb_item->qualification.function_type) {
+ case NDB_COND_AND_FUNC:
+ case NDB_COND_OR_FUNC:
+ simple_cond= FALSE;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (simple_cond && filter->begin() == -1)
+ DBUG_RETURN(1);
+ if (build_scan_filter_group(cond, filter))
+ DBUG_RETURN(1);
+ if (simple_cond && filter->end() == -1)
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+int
+ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack,
+ NdbScanOperation *op)
+{
+ DBUG_ENTER("generate_scan_filter");
+ if (ndb_cond_stack)
+ {
+ DBUG_PRINT("info", ("Generating scan filter"));
+ NdbScanFilter filter(op);
+ bool multiple_cond= FALSE;
+ // Wrap an AND group around multiple conditions
+ if (ndb_cond_stack->next) {
+ multiple_cond= TRUE;
+ if (filter.begin() == -1)
+ DBUG_RETURN(1);
+ }
+ for (Ndb_cond_stack *stack= ndb_cond_stack;
+ (stack);
+ stack= stack->next)
+ {
+ Ndb_cond *cond= stack->ndb_cond;
+
+ if (build_scan_filter(cond, &filter))
+ {
+ DBUG_PRINT("info", ("build_scan_filter failed"));
+ DBUG_RETURN(1);
+ }
+ }
+ if (multiple_cond && filter.end() == -1)
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Empty stack"));
+ }
+
+ DBUG_RETURN(0);
+}
+
#endif /* HAVE_NDBCLUSTER_DB */
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 4b3a30fb9b9..034bb9292e8 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -29,15 +29,16 @@
class Ndb; // Forward declaration
class NdbOperation; // Forward declaration
-class NdbConnection; // Forward declaration
+class NdbTransaction; // Forward declaration
class NdbRecAttr; // Forward declaration
-class NdbResultSet; // Forward declaration
class NdbScanOperation;
+class NdbScanFilter;
class NdbIndexScanOperation;
class NdbBlob;
// connectstring to cluster if given by mysqld
extern const char *ndbcluster_connectstring;
+extern ulong ndb_cache_check_time;
typedef enum ndb_index_type {
UNDEFINED_INDEX = 0,
@@ -60,20 +61,394 @@ typedef struct st_ndbcluster_share {
pthread_mutex_t mutex;
char *table_name;
uint table_name_length,use_count;
+ uint commit_count_lock;
+ ulonglong commit_count;
} NDB_SHARE;
+typedef enum ndb_item_type {
+ NDB_VALUE = 0, // Qualified more with Item::Type
+ NDB_FIELD = 1, // Qualified from table definition
+ NDB_FUNCTION = 2,// Qualified from Item_func::Functype
+ NDB_END_COND = 3 // End marker for condition group
+} NDB_ITEM_TYPE;
+
+typedef enum ndb_func_type {
+ NDB_EQ_FUNC = 0,
+ NDB_NE_FUNC = 1,
+ NDB_LT_FUNC = 2,
+ NDB_LE_FUNC = 3,
+ NDB_GT_FUNC = 4,
+ NDB_GE_FUNC = 5,
+ NDB_ISNULL_FUNC = 6,
+ NDB_ISNOTNULL_FUNC = 7,
+ NDB_LIKE_FUNC = 8,
+ NDB_NOTLIKE_FUNC = 9,
+ NDB_NOT_FUNC = 10,
+ NDB_UNKNOWN_FUNC = 11,
+ NDB_COND_AND_FUNC = 12,
+ NDB_COND_OR_FUNC = 13,
+ NDB_UNSUPPORTED_FUNC = 14
+} NDB_FUNC_TYPE;
+
+typedef union ndb_item_qualification {
+ Item::Type value_type;
+ enum_field_types field_type; // Instead of Item::FIELD_ITEM
+ NDB_FUNC_TYPE function_type; // Instead of Item::FUNC_ITEM
+} NDB_ITEM_QUALIFICATION;
+
+typedef struct ndb_item_field_value {
+ Field* field;
+ int column_no;
+} NDB_ITEM_FIELD_VALUE;
+
+typedef union ndb_item_value {
+ const Item *item;
+ NDB_ITEM_FIELD_VALUE *field_value;
+ uint arg_count;
+} NDB_ITEM_VALUE;
+
+struct negated_function_mapping
+{
+ NDB_FUNC_TYPE pos_fun;
+ NDB_FUNC_TYPE neg_fun;
+};
+
+/*
+ Define what functions can be negated in condition pushdown.
+ Note, these HAVE to be in the same order as in definition enum
+*/
+static const negated_function_mapping neg_map[]=
+{
+ {NDB_EQ_FUNC, NDB_NE_FUNC},
+ {NDB_NE_FUNC, NDB_EQ_FUNC},
+ {NDB_LT_FUNC, NDB_GE_FUNC},
+ {NDB_LE_FUNC, NDB_GT_FUNC},
+ {NDB_GT_FUNC, NDB_LE_FUNC},
+ {NDB_GE_FUNC, NDB_LT_FUNC},
+ {NDB_ISNULL_FUNC, NDB_ISNOTNULL_FUNC},
+ {NDB_ISNOTNULL_FUNC, NDB_ISNULL_FUNC},
+ {NDB_LIKE_FUNC, NDB_NOTLIKE_FUNC},
+ {NDB_NOTLIKE_FUNC, NDB_LIKE_FUNC},
+ {NDB_NOT_FUNC, NDB_UNSUPPORTED_FUNC},
+ {NDB_UNKNOWN_FUNC, NDB_UNSUPPORTED_FUNC},
+ {NDB_COND_AND_FUNC, NDB_UNSUPPORTED_FUNC},
+ {NDB_COND_OR_FUNC, NDB_UNSUPPORTED_FUNC},
+ {NDB_UNSUPPORTED_FUNC, NDB_UNSUPPORTED_FUNC}
+};
+
+/*
+ This class is the construction element for serialization of Item tree
+ in condition pushdown.
+ An instance of Ndb_Item represents a constant, table field reference,
+ unary or binary comparison predicate, and start/end of AND/OR.
+ Instances of Ndb_Item are stored in a linked list implemented by Ndb_cond
+ class.
+ The order of elements produced by Ndb_cond::next corresponds to
+ breadth-first traversal of the Item (i.e. expression) tree in prefix order.
+ AND and OR have arbitrary arity, so the end of AND/OR group is marked with
+ Ndb_item with type == NDB_END_COND.
+ NOT items represent negated conditions and generate NAND/NOR groups.
+*/
+class Ndb_item {
+ public:
+ Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {};
+ Ndb_item(NDB_ITEM_TYPE item_type,
+ NDB_ITEM_QUALIFICATION item_qualification,
+ const Item *item_value)
+ : type(item_type), qualification(item_qualification)
+ {
+ switch(item_type) {
+ case(NDB_VALUE):
+ value.item= item_value;
+ break;
+ case(NDB_FIELD): {
+ NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
+ Item_field *field_item= (Item_field *) item_value;
+ field_value->field= field_item->field;
+ field_value->column_no= -1; // Will be fetched at scan filter generation
+ value.field_value= field_value;
+ break;
+ }
+ case(NDB_FUNCTION):
+ value.item= item_value;
+ value.arg_count= ((Item_func *) item_value)->argument_count();
+ break;
+ case(NDB_END_COND):
+ break;
+ }
+ };
+ Ndb_item(Field *field, int column_no) : type(NDB_FIELD)
+ {
+ NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
+ qualification.field_type= field->type();
+ field_value->field= field;
+ field_value->column_no= column_no;
+ value.field_value= field_value;
+ };
+ Ndb_item(Item_func::Functype func_type, const Item *item_value)
+ : type(NDB_FUNCTION)
+ {
+ qualification.function_type= item_func_to_ndb_func(func_type);
+ value.item= item_value;
+ value.arg_count= ((Item_func *) item_value)->argument_count();
+ };
+ Ndb_item(Item_func::Functype func_type, uint no_args)
+ : type(NDB_FUNCTION)
+ {
+ qualification.function_type= item_func_to_ndb_func(func_type);
+ value.arg_count= no_args;
+ };
+ ~Ndb_item()
+ {
+ if (type == NDB_FIELD)
+ {
+ delete value.field_value;
+ value.field_value= NULL;
+ }
+ };
+
+ uint32 pack_length()
+ {
+ switch(type) {
+ case(NDB_VALUE):
+ if(qualification.value_type == Item::STRING_ITEM)
+ return value.item->str_value.length();
+ break;
+ case(NDB_FIELD):
+ return value.field_value->field->pack_length();
+ default:
+ break;
+ }
+
+ return 0;
+ };
+
+ Field * get_field() { return value.field_value->field; };
+
+ int get_field_no() { return value.field_value->column_no; };
+
+ int argument_count()
+ {
+ return value.arg_count;
+ };
+
+ const char* get_val()
+ {
+ switch(type) {
+ case(NDB_VALUE):
+ if(qualification.value_type == Item::STRING_ITEM)
+ return value.item->str_value.ptr();
+ break;
+ case(NDB_FIELD):
+ return value.field_value->field->ptr;
+ default:
+ break;
+ }
+
+ return NULL;
+ };
+
+ void save_in_field(Ndb_item *field_item)
+ {
+ Field *field = field_item->value.field_value->field;
+ const Item *item= value.item;
+
+ if (item && field)
+ ((Item *)item)->save_in_field(field, false);
+ };
+
+ static NDB_FUNC_TYPE item_func_to_ndb_func(Item_func::Functype fun)
+ {
+ switch (fun) {
+ case (Item_func::EQ_FUNC): { return NDB_EQ_FUNC; }
+ case (Item_func::NE_FUNC): { return NDB_NE_FUNC; }
+ case (Item_func::LT_FUNC): { return NDB_LT_FUNC; }
+ case (Item_func::LE_FUNC): { return NDB_LE_FUNC; }
+ case (Item_func::GT_FUNC): { return NDB_GT_FUNC; }
+ case (Item_func::GE_FUNC): { return NDB_GE_FUNC; }
+ case (Item_func::ISNULL_FUNC): { return NDB_ISNULL_FUNC; }
+ case (Item_func::ISNOTNULL_FUNC): { return NDB_ISNOTNULL_FUNC; }
+ case (Item_func::LIKE_FUNC): { return NDB_LIKE_FUNC; }
+ case (Item_func::NOT_FUNC): { return NDB_NOT_FUNC; }
+ case (Item_func::UNKNOWN_FUNC): { return NDB_UNKNOWN_FUNC; }
+ case (Item_func::COND_AND_FUNC): { return NDB_COND_AND_FUNC; }
+ case (Item_func::COND_OR_FUNC): { return NDB_COND_OR_FUNC; }
+ default: { return NDB_UNSUPPORTED_FUNC; }
+ }
+ };
+
+ static NDB_FUNC_TYPE negate(NDB_FUNC_TYPE fun)
+ {
+ uint i= (uint) fun;
+ DBUG_ASSERT(fun == neg_map[i].pos_fun);
+ return neg_map[i].neg_fun;
+ };
+
+ NDB_ITEM_TYPE type;
+ NDB_ITEM_QUALIFICATION qualification;
+ private:
+ NDB_ITEM_VALUE value;
+};
+
+/*
+ This class implements a linked list used for storing a
+ serialization of the Item tree for condition pushdown.
+ */
+class Ndb_cond
+{
+ public:
+ Ndb_cond() : ndb_item(NULL), next(NULL), prev(NULL) {};
+ ~Ndb_cond()
+ {
+ if (ndb_item) delete ndb_item;
+ ndb_item= NULL;
+ if (next) delete next;
+ next= prev= NULL;
+ };
+ Ndb_item *ndb_item;
+ Ndb_cond *next;
+ Ndb_cond *prev;
+};
+
+/*
+ This class implements a stack for storing several conditions
+ for pushdown (represented as serialized Item trees using Ndb_cond).
+ The current implementation only pushes one condition, but is
+ prepared for handling several (C1 AND C2 ...) if the logic for
+ pushing conditions is extended in sql_select.
+*/
+class Ndb_cond_stack
+{
+ public:
+ Ndb_cond_stack() : ndb_cond(NULL), next(NULL) {};
+ ~Ndb_cond_stack()
+ {
+ if (ndb_cond) delete ndb_cond;
+ ndb_cond= NULL;
+ if (next) delete next;
+ next= NULL;
+ };
+ Ndb_cond *ndb_cond;
+ Ndb_cond_stack *next;
+};
+
+class Ndb_rewrite_context
+{
+public:
+ Ndb_rewrite_context(Item_func *func)
+ : func_item(func), left_hand_item(NULL), count(0) {};
+ ~Ndb_rewrite_context()
+ {
+ if (next) delete next;
+ }
+ const Item_func *func_item;
+ const Item *left_hand_item;
+ uint count;
+ Ndb_rewrite_context *next;
+};
+
+/*
+ This class is used for storing the context when traversing
+ the Item tree. It stores a reference to the table the condition
+ is defined on, the serialized representation being generated,
+ if the condition found is supported, and information what is
+ expected next in the tree inorder for the condition to be supported.
+*/
+class Ndb_cond_traverse_context
+{
+ public:
+ Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack)
+ : table(tab), ndb_table(ndb_tab),
+ supported(TRUE), stack_ptr(stack), cond_ptr(NULL),
+ expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL),
+ rewrite_stack(NULL)
+ {
+ if (stack)
+ cond_ptr= stack->ndb_cond;
+ };
+ ~Ndb_cond_traverse_context()
+ {
+ if (rewrite_stack) delete rewrite_stack;
+ }
+ void expect(Item::Type type)
+ {
+ expect_mask|= (1 << type);
+ };
+ void dont_expect(Item::Type type)
+ {
+ expect_mask&= ~(1 << type);
+ };
+ bool expecting(Item::Type type)
+ {
+ return (expect_mask & (1 << type));
+ };
+ void expect_nothing()
+ {
+ expect_mask= 0;
+ };
+ void expect_only(Item::Type type)
+ {
+ expect_mask= 0;
+ expect(type);
+ };
+
+ void expect_field_result(Item_result result)
+ {
+ expect_field_result_mask|= (1 << result);
+ };
+ bool expecting_field_result(Item_result result)
+ {
+ return (expect_field_result_mask & (1 << result));
+ };
+ void expect_no_field_result()
+ {
+ expect_field_result_mask= 0;
+ };
+ void expect_only_field_result(Item_result result)
+ {
+ expect_field_result_mask= 0;
+ expect_field_result(result);
+ };
+ void expect_collation(CHARSET_INFO* col)
+ {
+ collation= col;
+ };
+ bool expecting_collation(CHARSET_INFO* col)
+ {
+ bool matching= (!collation) ? true : (collation == col);
+ collation= NULL;
+
+ return matching;
+ };
+
+ TABLE* table;
+ void* ndb_table;
+ bool supported;
+ Ndb_cond_stack* stack_ptr;
+ Ndb_cond* cond_ptr;
+ uint expect_mask;
+ uint expect_field_result_mask;
+ uint skip;
+ CHARSET_INFO* collation;
+ Ndb_rewrite_context *rewrite_stack;
+};
+
/*
Place holder for ha_ndbcluster thread specific data
*/
-class Thd_ndb {
+class Thd_ndb
+{
public:
Thd_ndb();
~Thd_ndb();
Ndb *ndb;
ulong count;
uint lock_count;
+ NdbTransaction *all;
+ NdbTransaction *stmt;
int error;
+ List<NDB_SHARE> changed_tables;
};
class ha_ndbcluster: public handler
@@ -91,32 +466,40 @@ class ha_ndbcluster: public handler
int index_init(uint index);
int index_end();
int index_read(byte *buf, const byte *key, uint key_len,
- enum ha_rkey_function find_flag);
+ enum ha_rkey_function find_flag);
int index_read_idx(byte *buf, uint index, const byte *key, uint key_len,
- enum ha_rkey_function find_flag);
+ 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 index_read_last(byte * buf, const byte * key, uint key_len);
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);
+ const key_range *end_key,
+ bool eq_range, bool sorted);
int read_range_first_to_buf(const key_range *start_key,
- const key_range *end_key,
- bool eq_range, bool sorted,
- byte* buf);
+ const key_range *end_key,
+ bool eq_range, bool sorted,
+ byte* buf);
int read_range_next();
+ /**
+ * Multi range stuff
+ */
+ int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
+ KEY_MULTI_RANGE*ranges, uint range_count,
+ bool sorted, HANDLER_BUFFER *buffer);
+ int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
+
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);
- int reset();
int external_lock(THD *thd, int lock_type);
int start_stmt(THD *thd);
const char * table_type() const;
@@ -132,8 +515,8 @@ class ha_ndbcluster: public handler
int delete_table(const char *name);
int create(const char *name, TABLE *form, HA_CREATE_INFO *info);
THR_LOCK_DATA **store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type);
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type);
bool low_byte_first() const;
bool has_transactions();
@@ -146,12 +529,55 @@ class ha_ndbcluster: public handler
static Thd_ndb* seize_thd_ndb();
static void release_thd_ndb(Thd_ndb* thd_ndb);
- uint8 table_cache_type();
- static void set_dbname(const char *pathname, char *dbname);
- static void set_tabname(const char *pathname, char *tabname);
+static void set_dbname(const char *pathname, char *dbname);
+static void set_tabname(const char *pathname, char *tabname);
+
+ /*
+ Condition pushdown
+ */
+
+ /*
+ Push condition down to the table handler.
+ SYNOPSIS
+ cond_push()
+ cond Condition to be pushed. The condition tree must not be
+ modified by the by the caller.
+ RETURN
+ The 'remainder' condition that caller must use to filter out records.
+ NULL means the handler will not return rows that do not match the
+ passed condition.
+ NOTES
+ The pushed conditions form a stack (from which one can remove the
+ last pushed condition using cond_pop).
+ The table handler filters out rows using (pushed_cond1 AND pushed_cond2
+ AND ... AND pushed_condN)
+ or less restrictive condition, depending on handler's capabilities.
- private:
+ handler->extra(HA_EXTRA_RESET) call empties the condition stack.
+ Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the
+ condition stack.
+ The current implementation supports arbitrary AND/OR nested conditions
+ with comparisons between columns and constants (including constant
+ expressions and function calls) and the following comparison operators:
+ =, !=, >, >=, <, <=, like, "not like", "is null", and "is not null".
+ Negated conditions are supported by NOT which generate NAND/NOR groups.
+ */
+ const COND *cond_push(const COND *cond);
+ /*
+ Pop the top condition from the condition stack of the handler instance.
+ SYNOPSIS
+ cond_pop()
+ Pops the top if condition stack, if stack is not empty
+ */
+ void cond_pop();
+
+ uint8 table_cache_type();
+ my_bool register_query_cache_table(THD *thd, char *table_key,
+ uint key_length,
+ qc_engine_callback *engine_callback,
+ ulonglong *engine_data);
+private:
int alter_table_name(const char *to);
int drop_table();
int create_index(const char *name, KEY *key_info, bool unique);
@@ -170,16 +596,17 @@ class ha_ndbcluster: public handler
int complemented_pk_read(const byte *old_data, byte *new_data);
int peek_row(const byte *record);
int unique_index_read(const byte *key, uint key_len,
- byte *buf);
+ byte *buf);
int ordered_index_scan(const key_range *start_key,
- const key_range *end_key,
- bool sorted, byte* buf);
+ const key_range *end_key,
+ bool sorted, bool descending, byte* buf);
int full_table_scan(byte * buf);
+ int fetch_next(NdbScanOperation* op);
int next_result(byte *buf);
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);
+ byte *buf,
+ enum ha_rkey_function find_flag);
int close_scan();
void unpack_record(byte *buf);
int get_ndb_lock_type(enum thr_lock_type type);
@@ -188,31 +615,58 @@ class ha_ndbcluster: public handler
void set_tabname(const char *pathname);
bool set_hidden_key(NdbOperation*,
- uint fieldnr, const byte* field_ptr);
+ uint fieldnr, const byte* field_ptr);
int set_ndb_key(NdbOperation*, Field *field,
- uint fieldnr, const byte* field_ptr);
+ uint fieldnr, const byte* field_ptr);
int set_ndb_value(NdbOperation*, Field *field, uint fieldnr, bool *set_blob_value= 0);
int get_ndb_value(NdbOperation*, Field *field, uint fieldnr, byte*);
friend int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg);
int get_ndb_blobs_value(NdbBlob *last_ndb_blob);
int set_primary_key(NdbOperation *op, const byte *key);
int set_primary_key_from_record(NdbOperation *op, const byte *record);
- int set_bounds(NdbIndexScanOperation *ndb_op, const key_range *keys[2]);
+ int set_bounds(NdbIndexScanOperation*, const key_range *keys[2], uint= 0);
int key_cmp(uint keynr, const byte * old_row, const byte * new_row);
+ int set_index_key(NdbOperation *, const KEY *key_info, const byte *key_ptr);
void print_results();
- longlong get_auto_increment();
+ ulonglong get_auto_increment();
void invalidate_dictionary_cache(bool global);
- int ndb_err(NdbConnection*);
+ int ndb_err(NdbTransaction*);
bool uses_blob_value(bool all_fields);
+ char *update_table_comment(const char * comment);
+
int write_ndb_file();
- private:
- int check_ndb_connection();
+ int check_ndb_connection(THD* thd= current_thd);
- NdbConnection *m_active_trans;
- NdbResultSet *m_active_cursor;
+ void set_rec_per_key();
+ void records_update();
+ void no_uncommitted_rows_execute_failure();
+ void no_uncommitted_rows_update(int);
+ void no_uncommitted_rows_init(THD *);
+ void no_uncommitted_rows_reset(THD *);
+
+ /*
+ Condition pushdown
+ */
+ void cond_clear();
+ bool serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond);
+ int build_scan_filter_predicate(Ndb_cond* &cond,
+ NdbScanFilter* filter,
+ bool negated= false);
+ int build_scan_filter_group(Ndb_cond* &cond,
+ NdbScanFilter* filter);
+ int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
+ int generate_scan_filter(Ndb_cond_stack* cond_stack,
+ NdbScanOperation* op);
+
+ friend int execute_commit(ha_ndbcluster*, NdbTransaction*);
+ friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*);
+ friend int execute_no_commit_ie(ha_ndbcluster*, NdbTransaction*);
+
+ NdbTransaction *m_active_trans;
+ NdbScanOperation *m_active_cursor;
void *m_table;
int m_table_version;
void *m_table_info;
@@ -224,7 +678,7 @@ class ha_ndbcluster: public handler
NDB_SHARE *m_share;
NDB_INDEX_DATA m_index[MAX_KEY];
// NdbRecAttr has no reference to blob
- typedef union { NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue;
+ typedef union { const NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue;
NdbValue m_value[NDB_MAX_ATTRIBUTES_IN_TABLE];
bool m_use_write;
bool m_ignore_dup_key;
@@ -234,6 +688,7 @@ class ha_ndbcluster: public handler
ha_rows m_rows_to_insert;
ha_rows m_rows_inserted;
ha_rows m_bulk_insert_rows;
+ ha_rows m_rows_changed;
bool m_bulk_insert_not_flushed;
ha_rows m_ops_pending;
bool m_skip_auto_increment;
@@ -247,33 +702,27 @@ class ha_ndbcluster: public handler
bool m_force_send;
ha_rows m_autoincrement_prefetch;
bool m_transaction_on;
- bool m_use_local_query_cache;
-
+ Ndb_cond_stack *m_cond_stack;
+ bool m_disable_multi_read;
+ byte *m_multi_range_result_ptr;
+ KEY_MULTI_RANGE *m_multi_ranges;
+ KEY_MULTI_RANGE *m_multi_range_defined;
+ const NdbOperation *m_current_multi_operation;
+ NdbIndexScanOperation *m_multi_cursor;
+ byte *m_multi_range_cursor_result_ptr;
+ int setup_recattr(const NdbRecAttr*);
Ndb *get_ndb();
- void set_rec_per_key();
- void records_update();
- void no_uncommitted_rows_execute_failure();
- void no_uncommitted_rows_update(int);
- void no_uncommitted_rows_init(THD *);
- void no_uncommitted_rows_reset(THD *);
-
- friend int execute_no_commit(ha_ndbcluster*, NdbConnection*);
- friend int execute_commit(ha_ndbcluster*, NdbConnection*);
- friend int execute_no_commit_ie(ha_ndbcluster*, NdbConnection*);
};
-bool ndbcluster_init(void);
-bool ndbcluster_end(void);
-
-int ndbcluster_commit(THD *thd, void* ndb_transaction);
-int ndbcluster_rollback(THD *thd, void* ndb_transaction);
+extern struct show_var_st ndb_status_variables[];
-void ndbcluster_close_connection(THD *thd);
+handlerton *ndbcluster_init(void);
+bool ndbcluster_end(void);
int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
- const void** frmblob, uint* frmlen);
+ const void** frmblob, uint* frmlen);
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
- const char *wild, bool dir, List<char> *files);
+ const char *wild, bool dir, List<char> *files);
int ndbcluster_table_exists_in_engine(THD* thd,
const char *db, const char *name);
int ndbcluster_drop_database(const char* path);
diff --git a/sql/handler.cc b/sql/handler.cc
index e6bc1496a00..b3754891d05 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -25,10 +25,6 @@
#include "ha_heap.h"
#include "ha_myisam.h"
#include "ha_myisammrg.h"
-#ifdef HAVE_ISAM
-#include "ha_isam.h"
-#include "ha_isammrg.h"
-#endif
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"
#endif
@@ -50,29 +46,34 @@
#ifdef HAVE_NDBCLUSTER_DB
#include "ha_ndbcluster.h"
#endif
+#ifdef HAVE_FEDERATED_DB
+#include "ha_federated.h"
+#endif
#include <myisampack.h>
#include <errno.h>
/* static functions defined in this file */
-static int NEAR_F delete_file(const char *name,const char *ext,int extflag);
+static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
-ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
- ha_read_key_count, ha_read_next_count, ha_read_prev_count,
- ha_read_first_count, ha_read_last_count,
- ha_commit_count, ha_rollback_count,
- ha_read_rnd_count, ha_read_rnd_next_count, ha_discover_count;
+/* list of all available storage engines (of their handlertons) */
+handlerton *handlertons[MAX_HA]={0};
-static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
+/* number of entries in handlertons[] */
+ulong total_ha;
+/* number of storage engines (from handlertons[]) that support 2pc */
+ulong total_ha_2pc;
+/* size of savepoint storage area (see ha_init) */
+ulong savepoint_alloc_size;
struct show_table_type_st sys_table_types[]=
{
{"MyISAM", &have_yes,
"Default engine as of MySQL 3.23 with great performance", DB_TYPE_MYISAM},
- {"HEAP", &have_yes,
- "Alias for MEMORY", DB_TYPE_HEAP},
{"MEMORY", &have_yes,
"Hash based, stored in memory, useful for temporary tables", DB_TYPE_HEAP},
+ {"HEAP", &have_yes,
+ "Alias for MEMORY", DB_TYPE_HEAP},
{"MERGE", &have_yes,
"Collection of identical MyISAM tables", DB_TYPE_MRG_MYISAM},
{"MRG_MYISAM",&have_yes,
@@ -99,13 +100,16 @@ struct show_table_type_st sys_table_types[]=
"Archive storage engine", DB_TYPE_ARCHIVE_DB},
{"CSV",&have_csv_db,
"CSV storage engine", DB_TYPE_CSV_DB},
+ {"FEDERATED",&have_federated_db,
+ "Federated MySQL storage engine", DB_TYPE_FEDERATED_DB},
{"BLACKHOLE",&have_blackhole_db,
- "Storage engine designed to act as null storage", DB_TYPE_BLACKHOLE_DB},
+ "/dev/null storage engine (anything you write to it disappears)",
+ DB_TYPE_BLACKHOLE_DB},
{NullS, NULL, NullS, DB_TYPE_UNKNOWN}
};
const char *ha_row_type[] = {
- "", "FIXED", "DYNAMIC", "COMPRESSED","?","?","?"
+ "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "?","?","?"
};
const char *tx_isolation_names[] =
@@ -119,11 +123,11 @@ uint known_extensions_id= 0;
enum db_type ha_resolve_by_name(const char *name, uint namelen)
{
- THD *thd=current_thd;
+ THD *thd= current_thd;
if (thd && !my_strcasecmp(&my_charset_latin1, name, "DEFAULT")) {
return (enum db_type) thd->variables.table_type;
}
-
+
show_table_type_st *types;
for (types= sys_table_types; types->type; types++)
{
@@ -141,7 +145,7 @@ const char *ha_get_storage_engine(enum db_type db_type)
if (db_type == types->db_type)
return types->type;
}
-
+
return "none";
}
@@ -161,11 +165,22 @@ my_bool ha_storage_engine_is_enabled(enum db_type database_type)
/* Use other database handler if databasehandler is not incompiled */
-enum db_type ha_checktype(enum db_type database_type)
+enum db_type ha_checktype(THD *thd, enum db_type database_type,
+ bool no_substitute, bool report_error)
{
if (ha_storage_engine_is_enabled(database_type))
return database_type;
+ if (no_substitute)
+ {
+ if (report_error)
+ {
+ const char *engine_name= ha_get_storage_engine(database_type);
+ my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
+ }
+ return DB_TYPE_UNKNOWN;
+ }
+
switch (database_type) {
#ifndef NO_HASH
case DB_TYPE_HASH:
@@ -177,12 +192,12 @@ enum db_type ha_checktype(enum db_type database_type)
break;
}
- return
- DB_TYPE_UNKNOWN != (enum db_type) current_thd->variables.table_type ?
- (enum db_type) current_thd->variables.table_type :
- DB_TYPE_UNKNOWN != (enum db_type) global_system_variables.table_type ?
- (enum db_type) global_system_variables.table_type :
- DB_TYPE_MYISAM;
+ return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ?
+ (enum db_type) thd->variables.table_type :
+ ((enum db_type) global_system_variables.table_type !=
+ DB_TYPE_UNKNOWN ?
+ (enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM)
+ );
} /* ha_checktype */
@@ -193,15 +208,8 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
case DB_TYPE_HASH:
return new ha_hash(table);
#endif
-#ifdef HAVE_ISAM
- case DB_TYPE_MRG_ISAM:
- return new ha_isammrg(table);
- case DB_TYPE_ISAM:
- return new ha_isam(table);
-#else
case DB_TYPE_MRG_ISAM:
return new ha_myisammrg(table);
-#endif
#ifdef HAVE_BERKELEY_DB
case DB_TYPE_BERKELEY_DB:
return new ha_berkeley(table);
@@ -222,6 +230,10 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
case DB_TYPE_BLACKHOLE_DB:
return new ha_blackhole(table);
#endif
+#ifdef HAVE_FEDERATED_DB
+ case DB_TYPE_FEDERATED_DB:
+ return new ha_federated(table);
+#endif
#ifdef HAVE_CSV_DB
case DB_TYPE_CSV_DB:
return new ha_tina(table);
@@ -247,65 +259,190 @@ 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)
+/*
+ Register handler error messages for use with my_error().
+
+ SYNOPSIS
+ ha_init_errors()
+
+ RETURN
+ 0 OK
+ != 0 Error
+*/
+
+static int ha_init_errors(void)
{
-#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;
+#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
+ const char **errmsgs;
+
+ /* Allocate a pointer array for the error message strings. */
+ /* Zerofill it to avoid uninitialized gaps. */
+ if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
+ MYF(MY_WME | MY_ZEROFILL))))
+ return 1;
+
+ /* Set the dedicated error messages. */
+ SETMSG(HA_ERR_KEY_NOT_FOUND, ER(ER_KEY_NOT_FOUND));
+ SETMSG(HA_ERR_FOUND_DUPP_KEY, ER(ER_DUP_KEY));
+ SETMSG(HA_ERR_RECORD_CHANGED, "Update wich is recoverable");
+ SETMSG(HA_ERR_WRONG_INDEX, "Wrong index given to function");
+ SETMSG(HA_ERR_CRASHED, ER(ER_NOT_KEYFILE));
+ SETMSG(HA_ERR_WRONG_IN_RECORD, ER(ER_CRASHED_ON_USAGE));
+ SETMSG(HA_ERR_OUT_OF_MEM, "Table handler out of memory");
+ SETMSG(HA_ERR_NOT_A_TABLE, "Incorrect file format '%.64s'");
+ SETMSG(HA_ERR_WRONG_COMMAND, "Command not supported");
+ SETMSG(HA_ERR_OLD_FILE, ER(ER_OLD_KEYFILE));
+ SETMSG(HA_ERR_NO_ACTIVE_RECORD, "No record read in update");
+ SETMSG(HA_ERR_RECORD_DELETED, "Intern record deleted");
+ SETMSG(HA_ERR_RECORD_FILE_FULL, ER(ER_RECORD_FILE_FULL));
+ SETMSG(HA_ERR_INDEX_FILE_FULL, "No more room in index file '%.64s'");
+ SETMSG(HA_ERR_END_OF_FILE, "End in next/prev/first/last");
+ SETMSG(HA_ERR_UNSUPPORTED, ER(ER_ILLEGAL_HA));
+ SETMSG(HA_ERR_TO_BIG_ROW, "Too big row");
+ SETMSG(HA_WRONG_CREATE_OPTION, "Wrong create option");
+ SETMSG(HA_ERR_FOUND_DUPP_UNIQUE, ER(ER_DUP_UNIQUE));
+ SETMSG(HA_ERR_UNKNOWN_CHARSET, "Can't open charset");
+ SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF, ER(ER_WRONG_MRG_TABLE));
+ SETMSG(HA_ERR_CRASHED_ON_REPAIR, ER(ER_CRASHED_ON_REPAIR));
+ SETMSG(HA_ERR_CRASHED_ON_USAGE, ER(ER_CRASHED_ON_USAGE));
+ SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT, ER(ER_LOCK_WAIT_TIMEOUT));
+ SETMSG(HA_ERR_LOCK_TABLE_FULL, ER(ER_LOCK_TABLE_FULL));
+ SETMSG(HA_ERR_READ_ONLY_TRANSACTION, ER(ER_READ_ONLY_TRANSACTION));
+ SETMSG(HA_ERR_LOCK_DEADLOCK, ER(ER_LOCK_DEADLOCK));
+ SETMSG(HA_ERR_CANNOT_ADD_FOREIGN, ER(ER_CANNOT_ADD_FOREIGN));
+ SETMSG(HA_ERR_NO_REFERENCED_ROW, ER(ER_NO_REFERENCED_ROW));
+ SETMSG(HA_ERR_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED));
+ SETMSG(HA_ERR_NO_SAVEPOINT, "No savepoint with that name");
+ SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE, "Non unique key block size");
+ SETMSG(HA_ERR_NO_SUCH_TABLE, "No such table: '%.64s'");
+ SETMSG(HA_ERR_TABLE_EXIST, ER(ER_TABLE_EXISTS_ERROR));
+ SETMSG(HA_ERR_NO_CONNECTION, "Could not connect to storage engine");
+ SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED));
+
+ /* Register the error messages for use with my_error(). */
+ return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
+}
+
+
+/*
+ Unregister handler error messages.
+
+ SYNOPSIS
+ ha_finish_errors()
+
+ RETURN
+ 0 OK
+ != 0 Error
+*/
+
+static int ha_finish_errors(void)
+{
+ const char **errmsgs;
+
+ /* Allocate a pointer array for the error message strings. */
+ if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
+ return 1;
+ my_free((gptr) errmsgs, MYF(0));
+ return 0;
+}
+
+
+static inline void ha_was_inited_ok(handlerton **ht)
+{
+ uint tmp= (*ht)->savepoint_offset;
+ (*ht)->savepoint_offset= savepoint_alloc_size;
+ savepoint_alloc_size+= tmp;
+ (*ht)->slot= total_ha++;
+ if ((*ht)->prepare)
+ total_ha_2pc++;
}
int ha_init()
{
int error= 0;
+ handlerton **ht= handlertons;
+ total_ha= savepoint_alloc_size= 0;
+
+ if (ha_init_errors())
+ return 1;
+
+ if (opt_bin_log)
+ {
+ if (!(*ht= binlog_init())) // Always succeed
+ {
+ mysql_bin_log.close(LOG_CLOSE_INDEX); // Never used
+ opt_bin_log= 0; // Never used
+ error= 1; // Never used
+ }
+ else
+ ha_was_inited_ok(ht++);
+ }
#ifdef HAVE_BERKELEY_DB
if (have_berkeley_db == SHOW_OPTION_YES)
{
- if (berkeley_init())
+ if (!(*ht= berkeley_init()))
{
have_berkeley_db= SHOW_OPTION_DISABLED; // If we couldn't use handler
error= 1;
}
else
- opt_using_transactions=1;
+ ha_was_inited_ok(ht++);
}
#endif
#ifdef HAVE_INNOBASE_DB
if (have_innodb == SHOW_OPTION_YES)
{
- if (innobase_init())
+ if (!(*ht= innobase_init()))
{
have_innodb= SHOW_OPTION_DISABLED; // If we couldn't use handler
error= 1;
}
else
- opt_using_transactions=1;
+ ha_was_inited_ok(ht++);
}
#endif
#ifdef HAVE_NDBCLUSTER_DB
if (have_ndbcluster == SHOW_OPTION_YES)
{
- if (ndbcluster_init())
+ if (!(*ht= ndbcluster_init()))
{
have_ndbcluster= SHOW_OPTION_DISABLED;
error= 1;
}
else
- opt_using_transactions=1;
+ ha_was_inited_ok(ht++);
+ }
+#endif
+#ifdef HAVE_FEDERATED_DB
+ if (have_federated_db == SHOW_OPTION_YES)
+ {
+ if (federated_db_init())
+ {
+ have_federated_db= SHOW_OPTION_DISABLED;
+ error= 1;
+ }
}
#endif
#ifdef HAVE_ARCHIVE_DB
if (have_archive_db == SHOW_OPTION_YES)
{
- if (archive_db_init())
+ if (!(*ht= archive_db_init()))
{
have_archive_db= SHOW_OPTION_DISABLED;
error= 1;
}
+ else
+ ha_was_inited_ok(ht++);
}
#endif
+ DBUG_ASSERT(total_ha < MAX_HA);
+ /*
+ Check if there is a transaction-capable storage engine besides the
+ binary log (which is considered a transaction-capable storage engine in
+ counting total_ha)
+ */
+ opt_using_transactions= total_ha>(ulong)opt_bin_log;
+ savepoint_alloc_size+= sizeof(SAVEPOINT);
return error;
}
@@ -337,10 +474,16 @@ int ha_panic(enum ha_panic_function flag)
if (have_ndbcluster == SHOW_OPTION_YES)
error|=ndbcluster_end();
#endif
+#ifdef HAVE_FEDERATED_DB
+ if (have_federated_db == SHOW_OPTION_YES)
+ error|= federated_db_end();
+#endif
#ifdef HAVE_ARCHIVE_DB
if (have_archive_db == SHOW_OPTION_YES)
error|= archive_db_end();
#endif
+ if (ha_finish_errors())
+ error= 1;
return error;
} /* ha_panic */
@@ -356,16 +499,289 @@ void ha_drop_database(char* path)
#endif
}
+/* don't bother to rollback here, it's done already */
void ha_close_connection(THD* thd)
{
-#ifdef HAVE_INNOBASE_DB
- if (have_innodb == SHOW_OPTION_YES)
- innobase_close_connection(thd);
-#endif
-#ifdef HAVE_NDBCLUSTER_DB
- if (have_ndbcluster == SHOW_OPTION_YES)
- ndbcluster_close_connection(thd);
+ for (uint i=0; i < total_ha; i++)
+ if (thd->ha_data[i])
+ (*handlertons[i]->close_connection)(thd);
+}
+
+/* ========================================================================
+ ======================= TRANSACTIONS ===================================*/
+
+/*
+ Register a storage engine for a transaction
+
+ DESCRIPTION
+ Every storage engine MUST call this function when it starts
+ a transaction or a statement (that is it must be called both for the
+ "beginning of transaction" and "beginning of statement").
+ Only storage engines registered for the transaction/statement
+ will know when to commit/rollback it.
+
+ NOTE
+ trans_register_ha is idempotent - storage engine may register many
+ times per transaction.
+
+*/
+void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
+{
+ THD_TRANS *trans;
+ handlerton **ht;
+ DBUG_ENTER("trans_register_ha");
+ DBUG_PRINT("enter",("%s", all ? "all" : "stmt"));
+
+ if (all)
+ {
+ trans= &thd->transaction.all;
+ thd->server_status|= SERVER_STATUS_IN_TRANS;
+ }
+ else
+ trans= &thd->transaction.stmt;
+
+ for (ht=trans->ht; *ht; ht++)
+ if (*ht == ht_arg)
+ DBUG_VOID_RETURN; /* already registered, return */
+
+ trans->ht[trans->nht++]=ht_arg;
+ DBUG_ASSERT(*ht == ht_arg);
+ trans->no_2pc|=(ht_arg->prepare==0);
+ if (thd->transaction.xid_state.xid.is_null())
+ thd->transaction.xid_state.xid.set(thd->query_id);
+ DBUG_VOID_RETURN;
+}
+
+/*
+ RETURN
+ 0 - ok
+ 1 - error, transaction was rolled back
+*/
+int ha_prepare(THD *thd)
+{
+ int error=0, all=1;
+ THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
+ handlerton **ht=trans->ht;
+ DBUG_ENTER("ha_prepare");
+#ifdef USING_TRANSACTIONS
+ if (trans->nht)
+ {
+ for (; *ht; ht++)
+ {
+ int err;
+ statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
+ if ((*ht)->prepare)
+ {
+ if ((err= (*(*ht)->prepare)(thd, all)))
+ {
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
+ ha_rollback_trans(thd, all);
+ error=1;
+ break;
+ }
+ }
+ else
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), (*ht)->name);
+ }
+ }
+ }
+#endif /* USING_TRANSACTIONS */
+ DBUG_RETURN(error);
+}
+
+/*
+ RETURN
+ 0 - ok
+ 1 - transaction was rolled back
+ 2 - error during commit, data may be inconsistent
+*/
+int ha_commit_trans(THD *thd, bool all)
+{
+ int error= 0, cookie= 0;
+ THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
+ bool is_real_trans= all || thd->transaction.all.nht == 0;
+ handlerton **ht= trans->ht;
+ my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
+ DBUG_ENTER("ha_commit_trans");
+
+ if (thd->in_sub_stmt)
+ {
+ /*
+ Since we don't support nested statement transactions in 5.0,
+ we can't commit or rollback stmt transactions while we are inside
+ stored functions or triggers. So we simply do nothing now.
+ TODO: This should be fixed in later ( >= 5.1) releases.
+ */
+ if (!all)
+ DBUG_RETURN(0);
+ /*
+ We assume that all statements which commit or rollback main transaction
+ are prohibited inside of stored functions or triggers. So they should
+ bail out with error even before ha_commit_trans() call. To be 100% safe
+ let us throw error in non-debug builds.
+ */
+ DBUG_ASSERT(0);
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ DBUG_RETURN(2);
+ }
+#ifdef USING_TRANSACTIONS
+ if (trans->nht)
+ {
+ if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
+ {
+ ha_rollback_trans(thd, all);
+ DBUG_RETURN(1);
+ }
+ DBUG_EXECUTE_IF("crash_commit_before", abort(););
+
+ /* Close all cursors that can not survive COMMIT */
+ if (is_real_trans) /* not a statement commit */
+ thd->stmt_map.close_transient_cursors();
+
+ if (!trans->no_2pc && trans->nht > 1)
+ {
+ for (; *ht && !error; ht++)
+ {
+ int err;
+ if ((err= (*(*ht)->prepare)(thd, all)))
+ {
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
+ error= 1;
+ }
+ statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
+ }
+ DBUG_EXECUTE_IF("crash_commit_after_prepare", abort(););
+ if (error || (is_real_trans && xid &&
+ (error= !(cookie= tc_log->log(thd, xid)))))
+ {
+ ha_rollback_trans(thd, all);
+ error= 1;
+ goto end;
+ }
+ DBUG_EXECUTE_IF("crash_commit_after_log", abort(););
+ }
+ error=ha_commit_one_phase(thd, all) ? cookie ? 2 : 1 : 0;
+ DBUG_EXECUTE_IF("crash_commit_before_unlog", abort(););
+ if (cookie)
+ tc_log->unlog(cookie, xid);
+ DBUG_EXECUTE_IF("crash_commit_after", abort(););
+end:
+ if (is_real_trans)
+ start_waiting_global_read_lock(thd);
+ }
+#endif /* USING_TRANSACTIONS */
+ DBUG_RETURN(error);
+}
+
+/*
+ NOTE - this function does not care about global read lock.
+ A caller should.
+*/
+int ha_commit_one_phase(THD *thd, bool all)
+{
+ int error=0;
+ THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
+ bool is_real_trans=all || thd->transaction.all.nht == 0;
+ handlerton **ht=trans->ht;
+ DBUG_ENTER("ha_commit_one_phase");
+#ifdef USING_TRANSACTIONS
+ if (trans->nht)
+ {
+ for (ht=trans->ht; *ht; ht++)
+ {
+ int err;
+ if ((err= (*(*ht)->commit)(thd, all)))
+ {
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
+ error=1;
+ }
+ statistic_increment(thd->status_var.ha_commit_count,&LOCK_status);
+ *ht= 0;
+ }
+ trans->nht=0;
+ trans->no_2pc=0;
+ if (is_real_trans)
+ thd->transaction.xid_state.xid.null();
+ if (all)
+ {
+#ifdef HAVE_QUERY_CACHE
+ if (thd->transaction.changed_tables)
+ query_cache.invalidate(thd->transaction.changed_tables);
#endif
+ thd->variables.tx_isolation=thd->session_tx_isolation;
+ thd->transaction.cleanup();
+ }
+ }
+#endif /* USING_TRANSACTIONS */
+ DBUG_RETURN(error);
+}
+
+
+int ha_rollback_trans(THD *thd, bool all)
+{
+ int error=0;
+ THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
+ bool is_real_trans=all || thd->transaction.all.nht == 0;
+ DBUG_ENTER("ha_rollback_trans");
+ if (thd->in_sub_stmt)
+ {
+ /*
+ If we are inside stored function or trigger we should not commit or
+ rollback current statement transaction. See comment in ha_commit_trans()
+ call for more information.
+ */
+ if (!all)
+ DBUG_RETURN(0);
+ DBUG_ASSERT(0);
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ DBUG_RETURN(1);
+ }
+#ifdef USING_TRANSACTIONS
+ if (trans->nht)
+ {
+ /* Close all cursors that can not survive ROLLBACK */
+ if (is_real_trans) /* not a statement commit */
+ thd->stmt_map.close_transient_cursors();
+
+ for (handlerton **ht=trans->ht; *ht; ht++)
+ {
+ int err;
+ if ((err= (*(*ht)->rollback)(thd, all)))
+ { // cannot happen
+ my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
+ error=1;
+ }
+ statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status);
+ *ht= 0;
+ }
+ trans->nht=0;
+ trans->no_2pc=0;
+ if (is_real_trans)
+ thd->transaction.xid_state.xid.null();
+ if (all)
+ {
+ thd->variables.tx_isolation=thd->session_tx_isolation;
+ thd->transaction.cleanup();
+ }
+ }
+#endif /* USING_TRANSACTIONS */
+ /*
+ If a non-transactional table was updated, warn; don't warn if this is a
+ slave thread (because when a slave thread executes a ROLLBACK, it has
+ been read from the binary log, so it's 100% sure and normal to produce
+ error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
+ slave SQL thread, it would not stop the thread but just be printed in
+ the error log; but we don't want users to wonder why they have this
+ message in the error log, so we don't send it.
+ */
+ if (is_real_trans && (thd->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
+ !thd->slave_thread)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NOT_COMPLETE_ROLLBACK,
+ ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
+ DBUG_RETURN(error);
}
/*
@@ -381,7 +797,7 @@ int ha_autocommit_or_rollback(THD *thd, int error)
{
DBUG_ENTER("ha_autocommit_or_rollback");
#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
+ if (thd->transaction.stmt.nht)
{
if (!error)
{
@@ -397,83 +813,245 @@ int ha_autocommit_or_rollback(THD *thd, int error)
DBUG_RETURN(error);
}
+int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
+{
+ handlerton **ht= handlertons, **end_ht=ht+total_ha;
+ int res= 1;
+
+ for ( ; ht < end_ht ; ht++)
+ if ((*ht)->recover)
+ res= res &&
+ (*(commit ? (*ht)->commit_by_xid : (*ht)->rollback_by_xid))(xid);
+ return res;
+}
+
+#ifndef DBUG_OFF
+/* this does not need to be multi-byte safe or anything */
+static char* xid_to_str(char *buf, XID *xid)
+{
+ int i;
+ char *s=buf;
+ *s++='\'';
+ for (i=0; i < xid->gtrid_length+xid->bqual_length; i++)
+ {
+ uchar c=(uchar)xid->data[i];
+ /* is_next_dig is set if next character is a number */
+ bool is_next_dig= FALSE;
+ if (i < XIDDATASIZE)
+ {
+ char ch= xid->data[i+1];
+ is_next_dig= (ch >= '0' && ch <='9');
+ }
+ if (i == xid->gtrid_length)
+ {
+ *s++='\'';
+ if (xid->bqual_length)
+ {
+ *s++='.';
+ *s++='\'';
+ }
+ }
+ if (c < 32 || c > 126)
+ {
+ *s++='\\';
+ /*
+ If next character is a number, write current character with
+ 3 octal numbers to ensure that the next number is not seen
+ as part of the octal number
+ */
+ if (c > 077 || is_next_dig)
+ *s++=_dig_vec_lower[c >> 6];
+ if (c > 007 || is_next_dig)
+ *s++=_dig_vec_lower[(c >> 3) & 7];
+ *s++=_dig_vec_lower[c & 7];
+ }
+ else
+ {
+ if (c == '\'' || c == '\\')
+ *s++='\\';
+ *s++=c;
+ }
+ }
+ *s++='\'';
+ *s=0;
+ return buf;
+}
+#endif
+
/*
- This function is called when MySQL writes the log segment of a
- transaction to the binlog. It is called when the LOCK_log mutex is
- reserved. Here we communicate to transactional table handlers what
- binlog position corresponds to the current transaction. The handler
- can store it and in recovery print to the user, so that the user
- knows from what position in the binlog to start possible
- roll-forward, for example, if the crashed server was a slave in
- replication. This function also calls the commit of the table
- handler, because the order of transactions in the log of the table
- handler must be the same as in the binlog.
- NOTE that to eliminate the bottleneck of the group commit, we do not
- flush the handler log files here, but only later in a call of
- ha_commit_complete().
+ recover() step of xa
- arguments:
- thd: the thread handle of the current connection
- log_file_name: latest binlog file name
- end_offset: the offset in the binlog file up to which we wrote
- return value: 0 if success, 1 if error
-*/
+ NOTE
+ there are three modes of operation:
-int ha_report_binlog_offset_and_commit(THD *thd,
- char *log_file_name,
- my_off_t end_offset)
+ - automatic recover after a crash
+ in this case commit_list != 0, tc_heuristic_recover==0
+ all xids from commit_list are committed, others are rolled back
+
+ - manual (heuristic) recover
+ in this case commit_list==0, tc_heuristic_recover != 0
+ DBA has explicitly specified that all prepared transactions should
+ be committed (or rolled back).
+
+ - no recovery (MySQL did not detect a crash)
+ in this case commit_list==0, tc_heuristic_recover == 0
+ there should be no prepared transactions in this case.
+*/
+int ha_recover(HASH *commit_list)
{
- int error= 0;
-#ifdef HAVE_INNOBASE_DB
- THD_TRANS *trans;
- trans = &thd->transaction.all;
- if (trans->innodb_active_trans)
+ int len, got, found_foreign_xids=0, found_my_xids=0;
+ handlerton **ht= handlertons, **end_ht=ht+total_ha;
+ XID *list=0;
+ bool dry_run=(commit_list==0 && tc_heuristic_recover==0);
+ DBUG_ENTER("ha_recover");
+
+ /* commit_list and tc_heuristic_recover cannot be set both */
+ DBUG_ASSERT(commit_list==0 || tc_heuristic_recover==0);
+ /* if either is set, total_ha_2pc must be set too */
+ DBUG_ASSERT(dry_run || total_ha_2pc>(ulong)opt_bin_log);
+
+ if (total_ha_2pc <= (ulong)opt_bin_log)
+ DBUG_RETURN(0);
+
+ if (commit_list)
+ sql_print_information("Starting crash recovery...");
+
+#ifndef WILL_BE_DELETED_LATER
+ /*
+ for now, only InnoDB supports 2pc. It means we can always safely
+ rollback all pending transactions, without risking inconsistent data
+ */
+ DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
+ tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
+ dry_run=FALSE;
+#endif
+
+ for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2)
{
- /*
- 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)))
+ list=(XID *)my_malloc(len*sizeof(XID), MYF(0));
+ }
+ if (!list)
+ {
+ sql_print_error(ER(ER_OUTOFMEMORY), len*sizeof(XID));
+ DBUG_RETURN(1);
+ }
+
+ for ( ; ht < end_ht ; ht++)
+ {
+ if (!(*ht)->recover)
+ continue;
+ while ((got=(*(*ht)->recover)(list, len)) > 0 )
{
- my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
- error=1;
+ sql_print_information("Found %d prepared transaction(s) in %s",
+ got, (*ht)->name);
+ for (int i=0; i < got; i ++)
+ {
+ my_xid x=list[i].get_my_xid();
+ if (!x) // not "mine" - that is generated by external TM
+ {
+#ifndef DBUG_OFF
+ char buf[XIDDATASIZE*4+6]; // see xid_to_str
+ sql_print_information("ignore xid %s", xid_to_str(buf, list+i));
+#endif
+ xid_cache_insert(list+i, XA_PREPARED);
+ found_foreign_xids++;
+ continue;
+ }
+ if (dry_run)
+ {
+ found_my_xids++;
+ continue;
+ }
+ // recovery mode
+ if (commit_list ?
+ hash_search(commit_list, (byte *)&x, sizeof(x)) != 0 :
+ tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
+ {
+#ifndef DBUG_OFF
+ char buf[XIDDATASIZE*4+6]; // see xid_to_str
+ sql_print_information("commit xid %s", xid_to_str(buf, list+i));
+#endif
+ (*(*ht)->commit_by_xid)(list+i);
+ }
+ else
+ {
+#ifndef DBUG_OFF
+ char buf[XIDDATASIZE*4+6]; // see xid_to_str
+ sql_print_information("rollback xid %s", xid_to_str(buf, list+i));
+#endif
+ (*(*ht)->rollback_by_xid)(list+i);
+ }
+ }
+ if (got < len)
+ break;
}
}
- 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;
+ my_free((gptr)list, MYF(0));
+ if (found_foreign_xids)
+ sql_print_warning("Found %d prepared XA transactions", found_foreign_xids);
+ if (dry_run && found_my_xids)
+ {
+ sql_print_error("Found %d prepared transactions! It means that mysqld was "
+ "not shut down properly last time and critical recovery "
+ "information (last binlog or %s file) was manually deleted "
+ "after a crash. You have to start mysqld with "
+ "--tc-heuristic-recover switch to commit or rollback "
+ "pending transactions.",
+ found_my_xids, opt_tc_log_file);
+ DBUG_RETURN(1);
+ }
+ if (commit_list)
+ sql_print_information("Crash recovery finished.");
+ DBUG_RETURN(0);
}
/*
- Flushes the handler log files (if my.cnf settings do not free us from it)
- after we have called ha_report_binlog_offset_and_commit(). To eliminate
- the bottleneck from the group commit, this should be called when
- LOCK_log has been released in log.cc.
+ return the list of XID's to a client, the same way SHOW commands do
- arguments:
- thd: the thread handle of the current connection
- return value: always 0
+ NOTE
+ I didn't find in XA specs that an RM cannot return the same XID twice,
+ so mysql_xa_recover does not filter XID's to ensure uniqueness.
+ It can be easily fixed later, if necessary.
*/
-
-int ha_commit_complete(THD *thd)
+bool mysql_xa_recover(THD *thd)
{
-#ifdef HAVE_INNOBASE_DB
- THD_TRANS *trans;
- trans = &thd->transaction.all;
- if (trans->innobase_tid)
- {
- innobase_commit_complete(trans->innobase_tid);
+ List<Item> field_list;
+ Protocol *protocol= thd->protocol;
+ int i=0;
+ XID_STATE *xs;
+ DBUG_ENTER("mysql_xa_recover");
+
+ field_list.push_back(new Item_int("formatID",0,11));
+ field_list.push_back(new Item_int("gtrid_length",0,11));
+ field_list.push_back(new Item_int("bqual_length",0,11));
+ field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
+
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(1);
- trans->innodb_active_trans=0;
+ pthread_mutex_lock(&LOCK_xid_cache);
+ while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
+ {
+ if (xs->xa_state==XA_PREPARED)
+ {
+ protocol->prepare_for_resend();
+ protocol->store_longlong((longlong)xs->xid.formatID, FALSE);
+ protocol->store_longlong((longlong)xs->xid.gtrid_length, FALSE);
+ protocol->store_longlong((longlong)xs->xid.bqual_length, FALSE);
+ protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
+ &my_charset_bin);
+ if (protocol->write())
+ {
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ DBUG_RETURN(1);
+ }
+ }
}
-#endif
- return 0;
+
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ send_eof(thd);
+ DBUG_RETURN(0);
}
/*
@@ -496,313 +1074,126 @@ int ha_commit_complete(THD *thd)
int ha_release_temporary_latches(THD *thd)
{
#ifdef HAVE_INNOBASE_DB
- THD_TRANS *trans;
- trans = &thd->transaction.all;
- if (trans->innobase_tid)
- innobase_release_temporary_latches(trans->innobase_tid);
+ if (opt_innodb)
+ innobase_release_temporary_latches(thd);
#endif
return 0;
}
-int ha_commit_trans(THD *thd, THD_TRANS* trans)
-{
- int error=0;
- DBUG_ENTER("ha_commit_trans");
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
- {
- bool transaction_commited= 0;
- bool operation_done= 0, need_start_waiters= 0;
- /* If transaction has done some updates to tables */
- if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
- my_b_tell(&thd->transaction.trans_log))
- {
- if ((error= wait_if_global_read_lock(thd, 0, 0)))
- {
- /*
- Note that ROLLBACK [TO SAVEPOINT] does not have this test; it's
- because ROLLBACK never updates data, so needn't wait on the lock.
- */
- my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
- error= 1;
- }
- else
- need_start_waiters= 1;
- if (mysql_bin_log.is_open())
- {
- mysql_bin_log.write(thd, &thd->transaction.trans_log, 1);
- statistic_increment(binlog_cache_use, &LOCK_status);
- if (thd->transaction.trans_log.disk_writes != 0)
- {
- /*
- We have to do this after addition of trans_log to main binlog since
- this operation can cause flushing of end of trans_log to disk.
- */
- statistic_increment(binlog_cache_disk_use, &LOCK_status);
- thd->transaction.trans_log.disk_writes= 0;
- }
- 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;
- }
- }
-#ifdef HAVE_NDBCLUSTER_DB
- if (trans->ndb_tid)
- {
- if ((error=ndbcluster_commit(thd,trans->ndb_tid)))
- {
- if (error == -1)
- my_error(ER_ERROR_DURING_COMMIT, MYF(0));
- error=1;
- }
- if (trans == &thd->transaction.all)
- operation_done= transaction_commited= 1;
- trans->ndb_tid=0;
- }
-#endif
-#ifdef HAVE_BERKELEY_DB
- if (trans->bdb_tid)
- {
- if ((error=berkeley_commit(thd,trans->bdb_tid)))
- {
- my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
- error=1;
- }
- else
- if (!(thd->options & OPTION_BEGIN))
- transaction_commited= 1;
- trans->bdb_tid=0;
- }
-#endif
+/*
+ Export statistics for different engines. Currently we use it only for
+ InnoDB.
+*/
+
+int ha_update_statistics()
+{
#ifdef HAVE_INNOBASE_DB
- if (trans->innobase_tid)
- {
- if ((error=innobase_commit(thd,trans->innobase_tid)))
- {
- my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
- error=1;
- }
- trans->innodb_active_trans=0;
- if (trans == &thd->transaction.all)
- operation_done= transaction_commited= 1;
- }
+ if (opt_innodb)
+ innodb_export_status();
#endif
-#ifdef HAVE_QUERY_CACHE
- if (transaction_commited && thd->transaction.changed_tables)
- query_cache.invalidate(thd->transaction.changed_tables);
-#endif /*HAVE_QUERY_CACHE*/
- if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
- sql_print_error("Got error during commit; Binlog is not up to date!");
- thd->variables.tx_isolation=thd->session_tx_isolation;
- if (operation_done)
- {
- statistic_increment(ha_commit_count,&LOCK_status);
- thd->transaction.cleanup();
- }
- if (need_start_waiters)
- start_waiting_global_read_lock(thd);
- }
-#endif // using transactions
- DBUG_RETURN(error);
+ return 0;
}
-
-int ha_rollback_trans(THD *thd, THD_TRANS *trans)
+int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
{
int error=0;
- DBUG_ENTER("ha_rollback_trans");
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
+ THD_TRANS *trans=&thd->transaction.all;
+ handlerton **ht=trans->ht, **end_ht;
+ DBUG_ENTER("ha_rollback_to_savepoint");
+ DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0);
+
+ trans->nht=sv->nht;
+ trans->no_2pc=0;
+ end_ht=ht+sv->nht;
+ /*
+ rolling back to savepoint in all storage engines that were part of the
+ transaction when the savepoint was set
+ */
+ for (; ht < end_ht; ht++)
{
- bool operation_done=0;
- /*
- As rollback can be 30 times slower than insert in InnoDB, and user may
- not know there's rollback (if it's because of a dupl row), better warn.
- */
- const char *save_proc_info= thd->proc_info;
- thd->proc_info= "Rolling back";
-#ifdef HAVE_NDBCLUSTER_DB
- if (trans->ndb_tid)
- {
- if ((error=ndbcluster_rollback(thd, trans->ndb_tid)))
- {
- if (error == -1)
- my_error(ER_ERROR_DURING_ROLLBACK, MYF(0));
- error=1;
- }
- trans->ndb_tid = 0;
- operation_done=1;
- }
-#endif
-#ifdef HAVE_BERKELEY_DB
- if (trans->bdb_tid)
- {
- if ((error=berkeley_rollback(thd, trans->bdb_tid)))
- {
- my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
- error=1;
- }
- trans->bdb_tid=0;
- operation_done=1;
- }
-#endif
-#ifdef HAVE_INNOBASE_DB
- if (trans->innobase_tid)
- {
- if ((error=innobase_rollback(thd, trans->innobase_tid)))
- {
- my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
- error=1;
- }
- trans->innodb_active_trans=0;
- operation_done=1;
+ int err;
+ DBUG_ASSERT((*ht)->savepoint_set != 0);
+ if ((err= (*(*ht)->savepoint_rollback)(thd, (byte *)(sv+1)+(*ht)->savepoint_offset)))
+ { // cannot happen
+ my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
+ error=1;
}
-#endif
- 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.
- */
- if (my_b_tell(&thd->transaction.trans_log))
- {
- if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
- mysql_bin_log.write(thd, &thd->transaction.trans_log, 0);
- statistic_increment(binlog_cache_use, &LOCK_status);
- if (thd->transaction.trans_log.disk_writes != 0)
- {
- /*
- We have to do this after addition of trans_log to main binlog since
- this operation can cause flushing of end of trans_log to disk.
- */
- statistic_increment(binlog_cache_disk_use, &LOCK_status);
- thd->transaction.trans_log.disk_writes= 0;
- }
- }
- /* Flushed or not, empty the binlog cache */
- 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();
+ statistic_increment(thd->status_var.ha_savepoint_rollback_count,&LOCK_status);
+ trans->no_2pc|=(*ht)->prepare == 0;
+ }
+ /*
+ rolling back the transaction in all storage engines that were not part of
+ the transaction when the savepoint was set
+ */
+ for (; *ht ; ht++)
+ {
+ int err;
+ if ((err= (*(*ht)->rollback)(thd, 1)))
+ { // cannot happen
+ my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
+ error=1;
}
- thd->variables.tx_isolation=thd->session_tx_isolation;
- if (operation_done)
- statistic_increment(ha_rollback_count,&LOCK_status);
- thd->proc_info= save_proc_info;
+ statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status);
+ *ht=0; // keep it conveniently zero-filled
}
-#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
}
-
/*
- Rolls the current transaction back to a savepoint.
- Return value: 0 if success, 1 if there was not a savepoint of the given
- name.
- NOTE: how do we handle this (unlikely but legal) case:
- [transaction] + [update to non-trans table] + [rollback to savepoint] ?
- The problem occurs when a savepoint is before the update to the
- non-transactional table. Then when there's a rollback to the savepoint, if we
- 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.
- 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
- will chop the SAVEPOINT command from the binlog cache, which is good as in
- that case there is no need to have it in the binlog).
+ note, that according to the sql standard (ISO/IEC 9075-2:2003)
+ section "4.33.4 SQL-statements and transaction states",
+ SAVEPOINT is *not* transaction-initiating SQL-statement
*/
-int ha_rollback_to_savepoint(THD *thd, char *savepoint_name)
+int ha_savepoint(THD *thd, SAVEPOINT *sv)
{
- my_off_t binlog_cache_pos=0;
- bool operation_done=0;
int error=0;
- DBUG_ENTER("ha_rollback_to_savepoint");
+ THD_TRANS *trans=&thd->transaction.all;
+ handlerton **ht=trans->ht;
+ DBUG_ENTER("ha_savepoint");
+ DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0);
#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
+ for (; *ht; ht++)
{
-#ifdef HAVE_INNOBASE_DB
- /*
- Retrieve the trans_log binlog cache position corresponding to the
- savepoint, and if the rollback is successful inside InnoDB reset the write
- position in the binlog cache to what it was at the savepoint.
- */
- if ((error=innobase_rollback_to_savepoint(thd, savepoint_name,
- &binlog_cache_pos)))
+ int err;
+ if (! (*ht)->savepoint_set)
{
- my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
+ my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
error=1;
+ break;
}
- else if (mysql_bin_log.is_open())
- {
- /*
- Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some
- non-transactional table. Otherwise, truncate the binlog cache starting
- from the SAVEPOINT command.
- */
- if (unlikely((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
- my_b_tell(&thd->transaction.trans_log)))
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
- if (mysql_bin_log.write(&qinfo))
- error= 1;
- }
- else
- reinit_io_cache(&thd->transaction.trans_log, WRITE_CACHE,
- binlog_cache_pos, 0, 0);
+ if ((err= (*(*ht)->savepoint_set)(thd, (byte *)(sv+1)+(*ht)->savepoint_offset)))
+ { // cannot happen
+ my_error(ER_GET_ERRNO, MYF(0), err);
+ error=1;
}
- operation_done=1;
-#endif
- if (operation_done)
- statistic_increment(ha_rollback_count,&LOCK_status);
+ statistic_increment(thd->status_var.ha_savepoint_count,&LOCK_status);
}
+ sv->nht=trans->nht;
#endif /* USING_TRANSACTIONS */
-
DBUG_RETURN(error);
}
-
-/*
-Sets a transaction savepoint.
-Return value: always 0, that is, succeeds always
-*/
-
-int ha_savepoint(THD *thd, char *savepoint_name)
+int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
{
int error=0;
- DBUG_ENTER("ha_savepoint");
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
+ handlerton **ht=thd->transaction.all.ht, **end_ht;
+ DBUG_ENTER("ha_release_savepoint");
+ DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0);
+
+ end_ht=ht+sv->nht;
+ for (; ht < end_ht; ht++)
{
- /* Write it to the binary log (see comments of ha_rollback_to_savepoint) */
- if (mysql_bin_log.is_open())
- {
-#ifdef HAVE_INNOBASE_DB
- innobase_savepoint(thd,savepoint_name,
- my_b_tell(&thd->transaction.trans_log));
-#endif
- Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
- if (mysql_bin_log.write(&qinfo))
- error= 1;
+ int err;
+ if (!(*ht)->savepoint_release)
+ continue;
+ if ((err= (*(*ht)->savepoint_release)(thd, (byte *)(sv+1)+(*ht)->savepoint_offset)))
+ { // cannot happen
+ my_error(ER_GET_ERRNO, MYF(0), err);
+ error=1;
}
-#ifdef HAVE_INNOBASE_DB
- else
- innobase_savepoint(thd,savepoint_name,0);
-#endif
}
-#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
}
@@ -846,12 +1237,25 @@ bool ha_flush_logs()
The .frm file will be deleted only if we return 0 or ENOENT
*/
-int ha_delete_table(enum db_type table_type, const char *path)
+int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
+ const char *alias, bool generate_warning)
{
+ handler *file;
char tmp_path[FN_REFLEN];
- handler *file=get_new_handler((TABLE*) 0, table_type);
- if (!file)
- return ENOENT;
+ int error;
+ TABLE dummy_table;
+ TABLE_SHARE dummy_share;
+ DBUG_ENTER("ha_delete_table");
+
+ bzero((char*) &dummy_table, sizeof(dummy_table));
+ bzero((char*) &dummy_share, sizeof(dummy_share));
+ dummy_table.s= &dummy_share;
+
+ /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
+ if (table_type == DB_TYPE_UNKNOWN ||
+ ! (file=get_new_handler(&dummy_table, table_type)))
+ DBUG_RETURN(ENOENT);
+
if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
{
/* Ensure that table handler get path in lower case */
@@ -859,64 +1263,45 @@ int ha_delete_table(enum db_type table_type, const char *path)
my_casedn_str(files_charset_info, tmp_path);
path= tmp_path;
}
- int error=file->delete_table(path);
- delete file;
- return error;
-}
-
-
-void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos)
-{
- switch (pack_length) {
-#if SIZEOF_OFF_T > 4
- case 8: mi_int8store(buff,pos); break;
- case 7: mi_int7store(buff,pos); break;
- case 6: mi_int6store(buff,pos); break;
- case 5: mi_int5store(buff,pos); break;
-#endif
- case 4: mi_int4store(buff,pos); break;
- case 3: mi_int3store(buff,pos); break;
- case 2: mi_int2store(buff,(uint) pos); break;
- case 1: buff[0]= (uchar) pos; break;
- }
- return;
-}
-
-my_off_t ha_get_ptr(byte *ptr, uint pack_length)
-{
- my_off_t pos;
- switch (pack_length) {
-#if SIZEOF_OFF_T > 4
- case 8:
- pos= (my_off_t) mi_uint8korr(ptr);
- break;
- case 7:
- pos= (my_off_t) mi_uint7korr(ptr);
- break;
- case 6:
- pos= (my_off_t) mi_uint6korr(ptr);
- break;
- case 5:
- pos= (my_off_t) mi_uint5korr(ptr);
- break;
-#endif
- case 4:
- pos= (my_off_t) mi_uint4korr(ptr);
- break;
- case 3:
- pos= (my_off_t) mi_uint3korr(ptr);
- break;
- case 2:
- pos= (my_off_t) mi_uint2korr(ptr);
- break;
- case 1:
- pos= (my_off_t) mi_uint2korr(ptr);
- break;
- default:
- pos=0; // Impossible
- break;
+ if ((error= file->delete_table(path)) && generate_warning)
+ {
+ /*
+ Because file->print_error() use my_error() to generate the error message
+ we must store the error state in thd, reset it and restore it to
+ be able to get hold of the error message.
+ (We should in the future either rewrite handler::print_error() or make
+ a nice method of this.
+ */
+ bool query_error= thd->query_error;
+ sp_rcontext *spcont= thd->spcont;
+ SELECT_LEX *current_select= thd->lex->current_select;
+ char buff[sizeof(thd->net.last_error)];
+ char new_error[sizeof(thd->net.last_error)];
+ int last_errno= thd->net.last_errno;
+
+ strmake(buff, thd->net.last_error, sizeof(buff)-1);
+ thd->query_error= 0;
+ thd->spcont= 0;
+ thd->lex->current_select= 0;
+ thd->net.last_error[0]= 0;
+
+ /* Fill up strucutures that print_error may need */
+ dummy_table.s->path= path;
+ dummy_table.alias= alias;
+
+ file->print_error(error, 0);
+ strmake(new_error, thd->net.last_error, sizeof(buff)-1);
+
+ /* restore thd */
+ thd->query_error= query_error;
+ thd->spcont= spcont;
+ thd->lex->current_select= current_select;
+ thd->net.last_errno= last_errno;
+ strmake(thd->net.last_error, buff, sizeof(buff)-1);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, new_error);
}
- return pos;
+ delete file;
+ DBUG_RETURN(error);
}
/****************************************************************************
@@ -931,8 +1316,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
int error;
DBUG_ENTER("handler::ha_open");
DBUG_PRINT("enter",("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d",
- name, table->db_type, table->db_stat, mode,
- test_if_locked));
+ name, table->s->db_type, table->db_stat, mode,
+ test_if_locked));
if ((error=open(name,mode,test_if_locked)))
{
@@ -950,7 +1335,7 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
}
else
{
- if (table->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
+ if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
table->db_stat|=HA_READ_ONLY;
(void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
@@ -980,7 +1365,7 @@ int handler::read_first_row(byte * buf, uint primary_key)
register int error;
DBUG_ENTER("handler::read_first_row");
- statistic_increment(ha_read_first_count,&LOCK_status);
+ statistic_increment(current_thd->status_var.ha_read_first_count,&LOCK_status);
/*
If there is very few deleted rows in the table, find the first row by
@@ -1004,71 +1389,218 @@ int handler::read_first_row(byte * buf, uint primary_key)
DBUG_RETURN(error);
}
+/*
+ Generate the next auto-increment number based on increment and offset
+
+ In most cases increment= offset= 1, in which case we get:
+ 1,2,3,4,5,...
+ If increment=10 and offset=5 and previous number is 1, we get:
+ 1,5,15,25,35,...
+*/
+
+inline ulonglong
+next_insert_id(ulonglong nr,struct system_variables *variables)
+{
+ nr= (((nr+ variables->auto_increment_increment -
+ variables->auto_increment_offset)) /
+ (ulonglong) variables->auto_increment_increment);
+ return (nr* (ulonglong) variables->auto_increment_increment +
+ variables->auto_increment_offset);
+}
+
/*
- Updates field with field_type NEXT_NUMBER according to following:
- if field = 0 change field to the next free key in database.
+ Update the auto_increment field if necessary
+
+ SYNOPSIS
+ update_auto_increment()
+
+ RETURN
+ 0 ok
+ 1 get_auto_increment() was called and returned ~(ulonglong) 0
+
+
+ IMPLEMENTATION
+
+ Updates columns with type NEXT_NUMBER if:
+
+ - If column value is set to NULL (in which case
+ auto_increment_field_not_null is 0)
+ - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
+ set. In the future we will only set NEXT_NUMBER fields if one sets them
+ to NULL (or they are not included in the insert list).
+
+
+ There are two different cases when the above is true:
+
+ - thd->next_insert_id == 0 (This is the normal case)
+ In this case we set the set the column for the first row to the value
+ next_insert_id(get_auto_increment(column))) which is normally
+ max-used-column-value +1.
+
+ We call get_auto_increment() only for the first row in a multi-row
+ statement. For the following rows we generate new numbers based on the
+ last used number.
+
+ - thd->next_insert_id != 0. This happens when we have read a statement
+ from the binary log or when one has used SET LAST_INSERT_ID=#.
+
+ In this case we will set the column to the value of next_insert_id.
+ The next row will be given the id
+ next_insert_id(next_insert_id)
+
+ The idea is that generated auto_increment values are predictable and
+ independent of the column values in the table. This is needed to be
+ able to replicate into a table that already has rows with a higher
+ auto-increment value than the one that is inserted.
+
+ After we have already generated an auto-increment number and the user
+ inserts a column with a higher value than the last used one, we will
+ start counting from the inserted value.
+
+ thd->next_insert_id is cleared after it's been used for a statement.
*/
-void handler::update_auto_increment()
+bool handler::update_auto_increment()
{
- longlong nr;
- THD *thd;
+ ulonglong nr;
+ THD *thd= table->in_use;
+ struct system_variables *variables= &thd->variables;
+ bool auto_increment_field_not_null;
+ bool result= 0;
DBUG_ENTER("handler::update_auto_increment");
- if (table->next_number_field->val_int() != 0 ||
- table->auto_increment_field_not_null &&
- current_thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)
+
+ /*
+ We must save the previous value to be able to restore it if the
+ row was not inserted
+ */
+ thd->prev_insert_id= thd->next_insert_id;
+ auto_increment_field_not_null= table->auto_increment_field_not_null;
+ table->auto_increment_field_not_null= FALSE;
+
+ if ((nr= table->next_number_field->val_int()) != 0 ||
+ auto_increment_field_not_null &&
+ thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)
{
- table->auto_increment_field_not_null= FALSE;
+ /* Clear flag for next row */
+ /* Mark that we didn't generate a new value **/
auto_increment_column_changed=0;
- DBUG_VOID_RETURN;
+
+ /* Update next_insert_id if we have already generated a value */
+ if (thd->clear_next_insert_id && nr >= thd->next_insert_id)
+ {
+ if (variables->auto_increment_increment != 1)
+ nr= next_insert_id(nr, variables);
+ else
+ nr++;
+ thd->next_insert_id= nr;
+ DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr));
+ }
+ DBUG_RETURN(0);
}
- table->auto_increment_field_not_null= FALSE;
- thd=current_thd;
- if ((nr=thd->next_insert_id))
- thd->next_insert_id=0; // Clear after use
- else
- nr=get_auto_increment();
- if (!table->next_number_field->store(nr))
+ if (!(nr= thd->next_insert_id))
+ {
+ if ((nr= get_auto_increment()) == ~(ulonglong) 0)
+ result= 1; // Mark failure
+
+ if (variables->auto_increment_increment != 1)
+ nr= next_insert_id(nr-1, variables);
+ /*
+ Update next row based on the found value. This way we don't have to
+ call the handler for every generated auto-increment value on a
+ multi-row statement
+ */
+ thd->next_insert_id= nr;
+ }
+
+ DBUG_PRINT("info",("auto_increment: %lu", (ulong) nr));
+
+ /* Mark that we should clear next_insert_id before next stmt */
+ thd->clear_next_insert_id= 1;
+
+ if (!table->next_number_field->store((longlong) nr, TRUE))
thd->insert_id((ulonglong) nr);
else
thd->insert_id(table->next_number_field->val_int());
+
+ /*
+ We can't set next_insert_id if the auto-increment key is not the
+ first key part, as there is no guarantee that the first parts will be in
+ sequence
+ */
+ if (!table->s->next_number_key_offset)
+ {
+ /*
+ Set next insert id to point to next auto-increment value to be able to
+ handle multi-row statements
+ This works even if auto_increment_increment > 1
+ */
+ thd->next_insert_id= next_insert_id(nr, variables);
+ }
+ else
+ thd->next_insert_id= 0;
+
+ /* Mark that we generated a new value */
auto_increment_column_changed=1;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(result);
}
+/*
+ restore_auto_increment
+
+ In case of error on write, we restore the last used next_insert_id value
+ because the previous value was not used.
+*/
-longlong handler::get_auto_increment()
+void handler::restore_auto_increment()
{
- longlong nr;
+ THD *thd= table->in_use;
+ if (thd->next_insert_id)
+ thd->next_insert_id= thd->prev_insert_id;
+}
+
+
+ulonglong handler::get_auto_increment()
+{
+ ulonglong nr;
int error;
(void) extra(HA_EXTRA_KEYREAD);
- index_init(table->next_number_index);
- if (!table->next_number_key_offset)
+ index_init(table->s->next_number_index);
+ if (!table->s->next_number_key_offset)
{ // Autoincrement at key-start
error=index_last(table->record[1]);
}
else
{
byte key[MAX_KEY_LENGTH];
- key_copy(key,table,table->next_number_index,
- table->next_number_key_offset);
- error=index_read(table->record[1], key, table->next_number_key_offset,
- HA_READ_PREFIX_LAST);
+ key_copy(key, table->record[0],
+ table->key_info + table->s->next_number_index,
+ table->s->next_number_key_offset);
+ error= index_read(table->record[1], key, table->s->next_number_key_offset,
+ HA_READ_PREFIX_LAST);
}
if (error)
nr=1;
else
- nr=(longlong) table->next_number_field->
- val_int_offset(table->rec_buff_length)+1;
+ nr= ((ulonglong) table->next_number_field->
+ val_int_offset(table->s->rec_buff_length)+1);
index_end();
(void) extra(HA_EXTRA_NO_KEYREAD);
return nr;
}
- /* Print error that we got from handler function */
+
+/*
+ Print error that we got from handler function
+
+ NOTE
+ In case of delete table it's only safe to use the following parts of
+ the 'table' structure:
+ table->s->path
+ table->alias
+*/
void handler::print_error(int error, myf errflag)
{
@@ -1109,7 +1641,7 @@ void handler::print_error(int error, myf errflag)
str.length(max_length-4);
str.append("...");
}
- my_error(ER_DUP_ENTRY,MYF(0),str.c_ptr(),key_nr+1);
+ my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), key_nr+1);
DBUG_VOID_RETURN;
}
textno=ER_DUP_KEY;
@@ -1117,7 +1649,7 @@ void handler::print_error(int error, myf errflag)
}
case HA_ERR_NULL_IN_SPATIAL:
textno= ER_UNKNOWN_ERROR;
- DBUG_VOID_RETURN;
+ break;
case HA_ERR_FOUND_DUPP_UNIQUE:
textno=ER_DUP_UNIQUE;
break;
@@ -1127,15 +1659,21 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_CRASHED:
textno=ER_NOT_KEYFILE;
break;
+ case HA_ERR_WRONG_IN_RECORD:
+ textno= ER_CRASHED_ON_USAGE;
+ break;
case HA_ERR_CRASHED_ON_USAGE:
textno=ER_CRASHED_ON_USAGE;
break;
+ case HA_ERR_NOT_A_TABLE:
+ textno= error;
+ break;
case HA_ERR_CRASHED_ON_REPAIR:
textno=ER_CRASHED_ON_REPAIR;
break;
case HA_ERR_OUT_OF_MEM:
- my_error(ER_OUT_OF_RESOURCES,errflag);
- DBUG_VOID_RETURN;
+ textno=ER_OUT_OF_RESOURCES;
+ break;
case HA_ERR_WRONG_COMMAND:
textno=ER_ILLEGAL_HA;
break;
@@ -1146,6 +1684,7 @@ void handler::print_error(int error, myf errflag)
textno=ER_UNSUPPORTED_EXTENSION;
break;
case HA_ERR_RECORD_FILE_FULL:
+ case HA_ERR_INDEX_FILE_FULL:
textno=ER_RECORD_FILE_FULL;
break;
case HA_ERR_LOCK_WAIT_TIMEOUT:
@@ -1169,6 +1708,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_NO_REFERENCED_ROW:
textno=ER_NO_REFERENCED_ROW;
break;
+ case HA_ERR_TABLE_DEF_CHANGED:
+ textno=ER_TABLE_DEF_CHANGED;
+ break;
case HA_ERR_NO_SUCH_TABLE:
{
/*
@@ -1178,10 +1720,10 @@ void handler::print_error(int error, myf errflag)
*/
char *db;
char buff[FN_REFLEN];
- uint length=dirname_part(buff,table->path);
+ uint length= dirname_part(buff,table->s->path);
buff[length-1]=0;
db=buff+dirname_length(buff);
- my_error(ER_NO_SUCH_TABLE,MYF(0),db,table->table_name);
+ my_error(ER_NO_SUCH_TABLE, MYF(0), db, table->alias);
break;
}
default:
@@ -1195,27 +1737,27 @@ void handler::print_error(int error, myf errflag)
{
const char* engine= table_type();
if (temporary)
- my_error(ER_GET_TEMPORARY_ERRMSG,MYF(0),error,str.ptr(),engine);
+ my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
else
- my_error(ER_GET_ERRMSG,MYF(0),error,str.ptr(),engine);
+ my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
}
- else
+ else
my_error(ER_GET_ERRNO,errflag,error);
DBUG_VOID_RETURN;
}
}
- my_error(textno,errflag,table->table_name,error);
+ my_error(textno, errflag, table->alias, error);
DBUG_VOID_RETURN;
}
-/*
+/*
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
*/
@@ -1238,16 +1780,40 @@ uint handler::get_dup_key(int error)
}
+/*
+ Delete all files with extension from bas_ext()
+
+ SYNOPSIS
+ delete_table()
+ name Base name of table
+
+ NOTES
+ We assume that the handler may return more extensions than
+ was actually used for the file.
+
+ RETURN
+ 0 If we successfully deleted at least one file from base_ext and
+ didn't get any other errors than ENOENT
+ # Error
+*/
+
int handler::delete_table(const char *name)
{
- int error=0;
+ int error= 0;
+ int enoent_or_zero= ENOENT; // Error if no file was deleted
+ char buff[FN_REFLEN];
+
for (const char **ext=bas_ext(); *ext ; ext++)
{
- if (delete_file(name,*ext,2))
+ fn_format(buff, name, "", *ext, 2 | 4);
+ if (my_delete_with_symlink(buff, MYF(0)))
{
- if ((error=errno) != ENOENT)
+ if ((error= my_errno) != ENOENT)
break;
}
+ else
+ enoent_or_zero= 0; // No error for ENOENT
+ error= enoent_or_zero;
}
return error;
}
@@ -1269,7 +1835,12 @@ int handler::rename_table(const char * from, const char * to)
}
/*
- Tell the handler to turn on or off transaction in the handler
+ Tell the storage engine that it is allowed to "disable transaction" in the
+ handler. It is a hint that ACID is not required - it is used in NDB for
+ ALTER TABLE, for example, when data are copied to temporary table.
+ A storage engine may treat this hint any way it likes. NDB for example
+ starts to commit every now and then automatically.
+ This hint can be safely ignored.
*/
int ha_enable_transaction(THD *thd, bool on)
@@ -1278,6 +1849,16 @@ int ha_enable_transaction(THD *thd, bool on)
DBUG_ENTER("ha_enable_transaction");
thd->transaction.on= on;
+ if (on)
+ {
+ /*
+ Now all storage engines should have transaction handling enabled.
+ But some may have it enabled all the time - "disabling" transactions
+ is an optimization hint that storage engine is free to ignore.
+ So, let's commit an open transaction (if any) now.
+ */
+ error= end_trans(thd, COMMIT);
+ }
DBUG_RETURN(error);
}
@@ -1313,7 +1894,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
char name_buff[FN_REFLEN];
DBUG_ENTER("ha_create_table");
- if (openfrm(name,"",0,(uint) READ_ALL, 0, &table))
+ if (openfrm(current_thd, name,"",0,(uint) READ_ALL, 0, &table))
DBUG_RETURN(1);
if (update_create_info)
{
@@ -1331,7 +1912,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
error=table.file->create(name,&table,create_info);
VOID(closefrm(&table));
if (error)
- my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,error);
+ my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name,error);
DBUG_RETURN(error != 0);
}
@@ -1378,7 +1959,7 @@ int ha_create_table_from_engine(THD* thd,
if (error)
DBUG_RETURN(2);
- if (openfrm(path,"",0,(uint) READ_ALL, 0, &table))
+ if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table))
DBUG_RETURN(3);
update_create_info_from_table(&create_info, &table);
@@ -1396,13 +1977,6 @@ int ha_create_table_from_engine(THD* thd,
DBUG_RETURN(error != 0);
}
-static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
-{
- char buff[FN_REFLEN];
- VOID(fn_format(buff,name,"",ext,extflag | 4));
- return(my_delete_with_symlink(buff,MYF(MY_WME)));
-}
-
void st_ha_check_opt::init()
{
flags= sql_flags= 0;
@@ -1521,7 +2095,7 @@ int ha_discover(THD *thd, const char *db, const char *name,
error= ndbcluster_discover(thd, db, name, frmblob, frmlen);
#endif
if (!error)
- statistic_increment(ha_discover_count,&LOCK_status);
+ statistic_increment(thd->status_var.ha_discover_count,&LOCK_status);
DBUG_RETURN(error);
}
@@ -1572,6 +2146,131 @@ int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
/*
+ Read the first row of a multi-range set.
+
+ SYNOPSIS
+ read_multi_range_first()
+ found_range_p Returns a pointer to the element in 'ranges' that
+ corresponds to the returned row.
+ ranges An array of KEY_MULTI_RANGE range descriptions.
+ range_count Number of ranges in 'ranges'.
+ sorted If result should be sorted per key.
+ buffer A HANDLER_BUFFER for internal handler usage.
+
+ NOTES
+ Record is read into table->record[0].
+ *found_range_p returns a valid value only if read_multi_range_first()
+ returns 0.
+ Sorting is done within each range. If you want an overall sort, enter
+ 'ranges' with sorted ranges.
+
+ RETURN
+ 0 OK, found a row
+ HA_ERR_END_OF_FILE No rows in range
+ # Error code
+*/
+
+int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
+ KEY_MULTI_RANGE *ranges, uint range_count,
+ bool sorted, HANDLER_BUFFER *buffer)
+{
+ int result= HA_ERR_END_OF_FILE;
+ DBUG_ENTER("handler::read_multi_range_first");
+ multi_range_sorted= sorted;
+ multi_range_buffer= buffer;
+
+ for (multi_range_curr= ranges, multi_range_end= ranges + range_count;
+ multi_range_curr < multi_range_end;
+ multi_range_curr++)
+ {
+ result= read_range_first(multi_range_curr->start_key.length ?
+ &multi_range_curr->start_key : 0,
+ multi_range_curr->end_key.length ?
+ &multi_range_curr->end_key : 0,
+ test(multi_range_curr->range_flag & EQ_RANGE),
+ multi_range_sorted);
+ if (result != HA_ERR_END_OF_FILE)
+ break;
+ }
+
+ *found_range_p= multi_range_curr;
+ DBUG_PRINT("exit",("result %d", result));
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Read the next row of a multi-range set.
+
+ SYNOPSIS
+ read_multi_range_next()
+ found_range_p Returns a pointer to the element in 'ranges' that
+ corresponds to the returned row.
+
+ NOTES
+ Record is read into table->record[0].
+ *found_range_p returns a valid value only if read_multi_range_next()
+ returns 0.
+
+ RETURN
+ 0 OK, found a row
+ HA_ERR_END_OF_FILE No (more) rows in range
+ # Error code
+*/
+
+int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
+{
+ int result;
+ DBUG_ENTER("handler::read_multi_range_next");
+
+ /* We should not be called after the last call returned EOF. */
+ DBUG_ASSERT(multi_range_curr < multi_range_end);
+
+ do
+ {
+ /* Save a call if there can be only one row in range. */
+ if (multi_range_curr->range_flag != (UNIQUE_RANGE | EQ_RANGE))
+ {
+ result= read_range_next();
+
+ /* On success or non-EOF errors jump to the end. */
+ if (result != HA_ERR_END_OF_FILE)
+ break;
+ }
+ else
+ {
+ /*
+ We need to set this for the last range only, but checking this
+ condition is more expensive than just setting the result code.
+ */
+ result= HA_ERR_END_OF_FILE;
+ }
+
+ /* Try the next range(s) until one matches a record. */
+ for (multi_range_curr++;
+ multi_range_curr < multi_range_end;
+ multi_range_curr++)
+ {
+ result= read_range_first(multi_range_curr->start_key.length ?
+ &multi_range_curr->start_key : 0,
+ multi_range_curr->end_key.length ?
+ &multi_range_curr->end_key : 0,
+ test(multi_range_curr->range_flag & EQ_RANGE),
+ multi_range_sorted);
+ if (result != HA_ERR_END_OF_FILE)
+ break;
+ }
+ }
+ while ((result == HA_ERR_END_OF_FILE) &&
+ (multi_range_curr < multi_range_end));
+
+ *found_range_p= multi_range_curr;
+ DBUG_PRINT("exit",("handler::read_multi_range_next: result %d", result));
+ DBUG_RETURN(result);
+}
+
+
+/*
Read first row between two ranges.
Store ranges for future calls to read_range_next
@@ -1725,9 +2424,10 @@ TYPELIB *ha_known_exts(void)
const char **ext, *old_ext;
known_extensions_id= mysys_usage_id;
- found_exts.push_back((char*) ".db");
+ found_exts.push_back((char*) triggers_file_ext);
+ found_exts.push_back((char*) trigname_file_ext);
for (types= sys_table_types; types->type; types++)
- {
+ {
if (*types->value == SHOW_OPTION_YES)
{
handler *file= get_new_handler(0,(enum db_type) types->db_type);
@@ -1750,7 +2450,7 @@ TYPELIB *ha_known_exts(void)
(found_exts.elements+1),
MYF(MY_WME | MY_FAE));
- DBUG_ASSERT(ext);
+ DBUG_ASSERT(ext != 0);
known_extensions.count= found_exts.elements;
known_extensions.type_names= ext;
@@ -1760,3 +2460,56 @@ TYPELIB *ha_known_exts(void)
}
return &known_extensions;
}
+
+
+#ifdef HAVE_REPLICATION
+/*
+ Reports to table handlers up to which position we have sent the binlog
+ to a slave in replication
+
+ SYNOPSIS
+ ha_repl_report_sent_binlog()
+ thd thread doing the binlog communication to the slave
+ log_file_name binlog file name
+ end_offse t the offset in the binlog file up to which we sent the
+ contents to the slave
+
+ NOTES
+ Only works for InnoDB at the moment
+
+ RETURN VALUE
+ Always 0 (= success)
+*/
+
+int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
+ my_off_t end_offset)
+{
+#ifdef HAVE_INNOBASE_DB
+ return innobase_repl_report_sent_binlog(thd,log_file_name,end_offset);
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ Reports to table handlers that we stop replication to a specific slave
+
+ SYNOPSIS
+ ha_repl_report_replication_stop()
+ thd thread doing the binlog communication to the slave
+
+ NOTES
+ Does nothing at the moment
+
+ RETURN VALUE
+ Always 0 (= success)
+
+ PARAMETERS
+*/
+
+int ha_repl_report_replication_stop(THD *thd)
+{
+ return 0;
+}
+#endif /* HAVE_REPLICATION */
diff --git a/sql/handler.h b/sql/handler.h
index d4bb19dd7b2..b61683c59b9 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -44,16 +44,25 @@
#define HA_ADMIN_INVALID -5
#define HA_ADMIN_REJECT -6
#define HA_ADMIN_TRY_ALTER -7
+#define HA_ADMIN_WRONG_CHECKSUM -8
/* Bits in table_flags() to show what database can do */
-#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 */
+
+/*
+ Can switch index during the scan with ::rnd_same() - not used yet.
+ see mi_rsame/heap_rsame/myrg_rsame
+*/
+#define HA_READ_RND_SAME (1 << 0)
#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_CAN_GEOMETRY (1 << 4)
-#define HA_FAST_KEY_READ (1 << 5) /* no need for a record cache in filesort */
+/*
+ Reading keys in random order is as fast as reading keys in sort order
+ (Used in records.cc to decide if we should use a record cache and by
+ filesort to decide if we should sort key + data or key + pointer-to-row
+*/
+#define HA_FAST_KEY_READ (1 << 5)
#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 */
@@ -61,9 +70,11 @@
#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_CAN_INSERT_DELAYED (1 << 14) /* only handlers with table-level locks
- need no special code to support
- INSERT DELAYED */
+/*
+ INSERT_DELAYED only works with handlers that uses MySQL internal table
+ level locks
+*/
+#define HA_CAN_INSERT_DELAYED (1 << 14)
#define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15)
#define HA_NOT_DELETE_WITH_CACHE (1 << 18)
#define HA_NO_PREFIX_CHAR_KEYS (1 << 20)
@@ -73,6 +84,9 @@
#define HA_HAS_CHECKSUM (1 << 24)
/* Table data are stored in separate files (for lower_case_table_names) */
#define HA_FILE_BASED (1 << 26)
+#define HA_NO_VARCHAR (1 << 27)
+#define HA_CAN_BIT_FIELD (1 << 28) /* supports bit fields */
+#define HA_NEED_READ_RANGE_BUFFER (1 << 29) /* for read_multi_range */
#define HA_ANY_INDEX_MAY_BE_UNIQUE (1 << 30)
@@ -90,6 +104,13 @@
#define HA_KEY_SWITCH_NONUNIQ_SAVE 2
#define HA_KEY_SWITCH_ALL_SAVE 3
+/*
+ Note: the following includes binlog and closing 0.
+ so: innodb + bdb + ndb + binlog + myisam + myisammrg + archive +
+ example + csv + heap + blackhole + federated + 0
+ (yes, the sum is deliberately inaccurate)
+*/
+#define MAX_HA 14
/*
Bits in index_ddl_flags(KEY *wanted_index)
@@ -142,13 +163,13 @@
/* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
#define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1
-enum db_type
-{
+enum db_type
+{
DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM,
DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
- DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
+ DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
DB_TYPE_FEDERATED_DB,
@@ -164,27 +185,196 @@ struct show_table_type_st {
};
enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
- ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED};
+ ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
+ ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT };
/* struct to hold information about the table that should be created */
/* Bits in used_fields */
-#define HA_CREATE_USED_AUTO 1
-#define HA_CREATE_USED_RAID 2
-#define HA_CREATE_USED_UNION 4
-#define HA_CREATE_USED_INSERT_METHOD 8
-#define HA_CREATE_USED_MIN_ROWS 16
-#define HA_CREATE_USED_MAX_ROWS 32
-#define HA_CREATE_USED_AVG_ROW_LENGTH 64
-#define HA_CREATE_USED_PACK_KEYS 128
-#define HA_CREATE_USED_CHARSET 256
-#define HA_CREATE_USED_DEFAULT_CHARSET 512
-
-typedef struct st_thd_trans {
- void *bdb_tid;
- void *innobase_tid;
- bool innodb_active_trans;
- void *ndb_tid;
+#define HA_CREATE_USED_AUTO (1L << 0)
+#define HA_CREATE_USED_RAID (1L << 1)
+#define HA_CREATE_USED_UNION (1L << 2)
+#define HA_CREATE_USED_INSERT_METHOD (1L << 3)
+#define HA_CREATE_USED_MIN_ROWS (1L << 4)
+#define HA_CREATE_USED_MAX_ROWS (1L << 5)
+#define HA_CREATE_USED_AVG_ROW_LENGTH (1L << 6)
+#define HA_CREATE_USED_PACK_KEYS (1L << 7)
+#define HA_CREATE_USED_CHARSET (1L << 8)
+#define HA_CREATE_USED_DEFAULT_CHARSET (1L << 9)
+#define HA_CREATE_USED_DATADIR (1L << 10)
+#define HA_CREATE_USED_INDEXDIR (1L << 11)
+#define HA_CREATE_USED_ENGINE (1L << 12)
+#define HA_CREATE_USED_CHECKSUM (1L << 13)
+#define HA_CREATE_USED_DELAY_KEY_WRITE (1L << 14)
+#define HA_CREATE_USED_ROW_FORMAT (1L << 15)
+#define HA_CREATE_USED_COMMENT (1L << 16)
+#define HA_CREATE_USED_PASSWORD (1L << 17)
+#define HA_CREATE_USED_CONNECTION (1L << 18)
+
+typedef ulonglong my_xid; // this line is the same as in log_event.h
+#define MYSQL_XID_PREFIX "MySQLXid"
+#define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8
+#define MYSQL_XID_OFFSET (MYSQL_XID_PREFIX_LEN+sizeof(server_id))
+#define MYSQL_XID_GTRID_LEN (MYSQL_XID_OFFSET+sizeof(my_xid))
+
+#define XIDDATASIZE 128
+#define MAXGTRIDSIZE 64
+#define MAXBQUALSIZE 64
+
+struct xid_t {
+ long formatID;
+ long gtrid_length;
+ long bqual_length;
+ char data[XIDDATASIZE]; // not \0-terminated !
+
+ bool eq(struct xid_t *xid)
+ { return !memcmp(this, xid, length()); }
+ bool eq(long g, long b, const char *d)
+ { return g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); }
+ void set(struct xid_t *xid)
+ { memcpy(this, xid, xid->length()); }
+ void set(long f, const char *g, long gl, const char *b, long bl)
+ {
+ formatID= f;
+ memcpy(data, g, gtrid_length= gl);
+ memcpy(data+gl, b, bqual_length= bl);
+ }
+ void set(ulonglong xid)
+ {
+ my_xid tmp;
+ formatID= 1;
+ set(MYSQL_XID_PREFIX_LEN, 0, MYSQL_XID_PREFIX);
+ memcpy(data+MYSQL_XID_PREFIX_LEN, &server_id, sizeof(server_id));
+ tmp= xid;
+ memcpy(data+MYSQL_XID_OFFSET, &tmp, sizeof(tmp));
+ gtrid_length=MYSQL_XID_GTRID_LEN;
+ }
+ void set(long g, long b, const char *d)
+ {
+ formatID= 1;
+ gtrid_length= g;
+ bqual_length= b;
+ memcpy(data, d, g+b);
+ }
+ bool is_null() { return formatID == -1; }
+ void null() { formatID= -1; }
+ my_xid quick_get_my_xid()
+ {
+ my_xid tmp;
+ memcpy(&tmp, data+MYSQL_XID_OFFSET, sizeof(tmp));
+ return tmp;
+ }
+ my_xid get_my_xid()
+ {
+ return gtrid_length == MYSQL_XID_GTRID_LEN && bqual_length == 0 &&
+ !memcmp(data+MYSQL_XID_PREFIX_LEN, &server_id, sizeof(server_id)) &&
+ !memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ?
+ quick_get_my_xid() : 0;
+ }
+ uint length()
+ {
+ return sizeof(formatID)+sizeof(gtrid_length)+sizeof(bqual_length)+
+ gtrid_length+bqual_length;
+ }
+};
+typedef struct xid_t XID;
+
+/* for recover() handlerton call */
+#define MIN_XID_LIST_SIZE 128
+#ifdef SAFEMALLOC
+#define MAX_XID_LIST_SIZE 256
+#else
+#define MAX_XID_LIST_SIZE (1024*128)
+#endif
+
+/*
+ handlerton is a singleton structure - one instance per storage engine -
+ to provide access to storage engine functionality that works on the
+ "global" level (unlike handler class that works on a per-table basis)
+
+ usually handlerton instance is defined statically in ha_xxx.cc as
+
+ static handlerton { ... } xxx_hton;
+
+ savepoint_*, prepare, recover, and *_by_xid pointers can be 0.
+*/
+typedef struct
+{
+ /*
+ storage engine name as it should be printed to a user
+ */
+ const char *name;
+ /*
+ each storage engine has it's own memory area (actually a pointer)
+ in the thd, for storing per-connection information.
+ It is accessed as
+
+ thd->ha_data[xxx_hton.slot]
+
+ slot number is initialized by MySQL after xxx_init() is called.
+ */
+ uint slot;
+ /*
+ to store per-savepoint data storage engine is provided with an area
+ of a requested size (0 is ok here).
+ savepoint_offset must be initialized statically to the size of
+ the needed memory to store per-savepoint information.
+ After xxx_init it is changed to be an offset to savepoint storage
+ area and need not be used by storage engine.
+ see binlog_hton and binlog_savepoint_set/rollback for an example.
+ */
+ uint savepoint_offset;
+ /*
+ handlerton methods:
+
+ close_connection is only called if
+ thd->ha_data[xxx_hton.slot] is non-zero, so even if you don't need
+ this storage area - set it to something, so that MySQL would know
+ this storage engine was accessed in this connection
+ */
+ int (*close_connection)(THD *thd);
+ /*
+ sv points to an uninitialized storage area of requested size
+ (see savepoint_offset description)
+ */
+ int (*savepoint_set)(THD *thd, void *sv);
+ /*
+ sv points to a storage area, that was earlier passed
+ to the savepoint_set call
+ */
+ int (*savepoint_rollback)(THD *thd, void *sv);
+ int (*savepoint_release)(THD *thd, void *sv);
+ /*
+ 'all' is true if it's a real commit, that makes persistent changes
+ 'all' is false if it's not in fact a commit but an end of the
+ statement that is part of the transaction.
+ NOTE 'all' is also false in auto-commit mode where 'end of statement'
+ and 'real commit' mean the same event.
+ */
+ int (*commit)(THD *thd, bool all);
+ int (*rollback)(THD *thd, bool all);
+ int (*prepare)(THD *thd, bool all);
+ int (*recover)(XID *xid_list, uint len);
+ int (*commit_by_xid)(XID *xid);
+ int (*rollback_by_xid)(XID *xid);
+ void *(*create_cursor_read_view)();
+ void (*set_cursor_read_view)(void *);
+ void (*close_cursor_read_view)(void *);
+ uint32 flags; /* global handler flags */
+} handlerton;
+
+/* Possible flags of a handlerton */
+#define HTON_NO_FLAGS 0
+#define HTON_CLOSE_CURSORS_AT_COMMIT 1
+
+typedef struct st_thd_trans
+{
+ /* number of entries in the ht[] */
+ uint nht;
+ /* true is not all entries in the ht[] support 2pc */
+ bool no_2pc;
+ /* storage engines that registered themselves for this transaction */
+ handlerton *ht[MAX_HA];
} THD_TRANS;
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
@@ -193,6 +383,7 @@ enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
typedef struct st_ha_create_information
{
CHARSET_INFO *table_charset, *default_table_charset;
+ LEX_STRING connect_string;
const char *comment,*password;
const char *data_file_name, *index_file_name;
const char *alias;
@@ -210,6 +401,8 @@ typedef struct st_ha_create_information
uint raid_type,raid_chunks;
uint merge_insert_method;
bool table_existed; /* 1 in create if table existed */
+ bool frm_only; /* 1 if no ha_create_table() */
+ bool varchar; /* 1 if table has a VARCHAR */
} HA_CREATE_INFO;
@@ -217,6 +410,14 @@ typedef struct st_ha_create_information
struct st_table;
typedef struct st_table TABLE;
+struct st_foreign_key_info;
+typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
+
+typedef struct st_savepoint SAVEPOINT;
+extern ulong savepoint_alloc_size;
+
+/* Forward declaration for condition pushdown to storage engine */
+typedef class Item COND;
typedef struct st_ha_check_opt
{
@@ -228,6 +429,21 @@ typedef struct st_ha_check_opt
} HA_CHECK_OPT;
+/*
+ This is a buffer area that the handler can use to store rows.
+ 'end_of_used_area' should be kept updated after calls to
+ read-functions so that other parts of the code can use the
+ remaining area (until next read calls is issued).
+*/
+
+typedef struct st_handler_buffer
+{
+ const byte *buffer; /* Buffer one can start using */
+ const byte *buffer_end; /* End of buffer */
+ byte *end_of_used_area; /* End of area that was used by handler */
+} HANDLER_BUFFER;
+
+
class handler :public Sql_alloc
{
protected:
@@ -246,6 +462,7 @@ class handler :public Sql_alloc
virtual int rnd_end() { return 0; }
public:
+ const handlerton *ht; /* storage engine of this handler */
byte *ref; /* Pointer to current row */
byte *dupp_ref; /* Pointer to dupp row */
ulonglong data_file_length; /* Length off data file */
@@ -262,6 +479,12 @@ public:
time_t check_time;
time_t update_time;
+ /* The following are for read_multi_range */
+ bool multi_range_sorted;
+ KEY_MULTI_RANGE *multi_range_curr;
+ KEY_MULTI_RANGE *multi_range_end;
+ HANDLER_BUFFER *multi_range_buffer;
+
/* The following are for read_range() */
key_range save_end_range, *end_range;
KEY_PART_INFO *range_key_part;
@@ -279,20 +502,22 @@ public:
enum {NONE=0, INDEX, RND} inited;
bool auto_increment_column_changed;
bool implicit_emptied; /* Can be !=0 only if HEAP */
+ const COND *pushed_cond;
-
- handler(TABLE *table_arg) :table(table_arg),
+ handler(const handlerton *ht_arg, TABLE *table_arg) :table(table_arg),
+ ht(ht_arg),
ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0),
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_KEY),
ref_length(sizeof(my_off_t)), block_size(0),
- raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0)
+ raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0),
+ pushed_cond(NULL)
{}
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
int ha_open(const char *name, int mode, int test_if_locked);
- void update_auto_increment();
+ bool 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);
@@ -314,33 +539,43 @@ public:
virtual ha_rows estimate_rows_upper_bound()
{ return records+EXTRA_RECORDS; }
+ /*
+ Get the row type from the storage engine. If this method returns
+ ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used.
+ */
+ virtual enum row_type get_row_type() const { return ROW_TYPE_NOT_USED; }
+
virtual const char *index_type(uint key_number) { DBUG_ASSERT(0); return "";}
int ha_index_init(uint idx)
{
+ DBUG_ENTER("ha_index_init");
DBUG_ASSERT(inited==NONE);
inited=INDEX;
- return index_init(idx);
+ DBUG_RETURN(index_init(idx));
}
int ha_index_end()
{
+ DBUG_ENTER("ha_index_end");
DBUG_ASSERT(inited==INDEX);
inited=NONE;
- return index_end();
+ DBUG_RETURN(index_end());
}
int ha_rnd_init(bool scan)
{
+ DBUG_ENTER("ha_rnd_init");
DBUG_ASSERT(inited==NONE || (inited==RND && scan));
inited=RND;
- return rnd_init(scan);
+ DBUG_RETURN(rnd_init(scan));
}
int ha_rnd_end()
{
+ DBUG_ENTER("ha_rnd_end");
DBUG_ASSERT(inited==RND);
inited=NONE;
- return rnd_end();
+ DBUG_RETURN(rnd_end());
}
- /* this is neseccary in many places, e.g. in HANDLER command */
+ /* this is necessary 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;
@@ -369,6 +604,10 @@ public:
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); }
+ virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
+ KEY_MULTI_RANGE *ranges, uint range_count,
+ bool sorted, HANDLER_BUFFER *buffer);
+ virtual int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
virtual int read_range_first(const key_range *start_key,
const key_range *end_key,
bool eq_range, bool sorted);
@@ -400,7 +639,7 @@ public:
virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
{ return extra(operation); }
virtual int reset() { return extra(HA_EXTRA_RESET); }
- virtual int external_lock(THD *thd, int lock_type)=0;
+ virtual int external_lock(THD *thd, int lock_type) { return 0; }
virtual void unlock_row() {}
virtual int start_stmt(THD *thd) {return 0;}
/*
@@ -411,7 +650,18 @@ public:
*/
virtual int delete_all_rows()
{ return (my_errno=HA_ERR_WRONG_COMMAND); }
- virtual longlong get_auto_increment();
+ virtual ulonglong get_auto_increment();
+ virtual void restore_auto_increment();
+
+ /*
+ Reset the auto-increment counter to the given value, i.e. the next row
+ inserted will get the given value. This is called e.g. after TRUNCATE
+ is emulated by doing a 'DELETE FROM t'. HA_ERR_WRONG_COMMAND is
+ returned by storage engines that don't support this operation.
+ */
+ virtual int reset_auto_increment(ulonglong value)
+ { return HA_ERR_WRONG_COMMAND; }
+
virtual void update_create_info(HA_CREATE_INFO *create_info) {}
/* admin commands - called from mysql_admin_table */
@@ -455,6 +705,8 @@ public:
/* used in ALTER TABLE; 1 if changing storage engine is allowed */
virtual bool can_switch_engines() { return 1; }
/* used in REPLACE; is > 0 if table is referred by a FOREIGN KEY */
+ virtual int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
+ { return 0; }
virtual uint referenced_by_foreign_key() { return 0;}
virtual void init_table_handle_for_HANDLER()
{ return; } /* prepare InnoDB for HANDLER */
@@ -511,10 +763,61 @@ 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)
- */
+ /* ask handler about permission to cache table when query is to be cached */
+ virtual my_bool register_query_cache_table(THD *thd, char *table_key,
+ uint key_length,
+ qc_engine_callback
+ *engine_callback,
+ ulonglong *engine_data)
+ {
+ *engine_callback= 0;
+ return 1;
+ }
+ /*
+ 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);
+ }
+
+ /*
+ Condition pushdown to storage engines
+ */
+
+ /*
+ Push condition down to the table handler.
+ SYNOPSIS
+ cond_push()
+ cond Condition to be pushed. The condition tree must not be
+ modified by the by the caller.
+ RETURN
+ The 'remainder' condition that caller must use to filter out records.
+ NULL means the handler will not return rows that do not match the
+ passed condition.
+ NOTES
+ The pushed conditions form a stack (from which one can remove the
+ last pushed condition using cond_pop).
+ The table handler filters out rows using (pushed_cond1 AND pushed_cond2
+ AND ... AND pushed_condN)
+ or less restrictive condition, depending on handler's capabilities.
+
+ handler->extra(HA_EXTRA_RESET) call empties the condition stack.
+ Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the
+ condition stack.
+ */
+ virtual const COND *cond_push(const COND *cond) { return cond; };
+ /*
+ Pop the top condition from the condition stack of the handler instance.
+ SYNOPSIS
+ cond_pop()
+ Pops the top if condition stack, if stack is not empty
+ */
+ virtual void cond_pop() { return; };
};
/* Some extern variables used with handlers */
@@ -523,12 +826,14 @@ extern struct show_table_type_st sys_table_types[];
extern const char *ha_row_type[];
extern TYPELIB tx_isolation_typelib;
extern TYPELIB myisam_stats_method_typelib;
+extern handlerton *handlertons[MAX_HA];
+extern ulong total_ha, total_ha_2pc;
/* Wrapper functions */
-#define ha_commit_stmt(thd) (ha_commit_trans((thd), &((thd)->transaction.stmt)))
-#define ha_rollback_stmt(thd) (ha_rollback_trans((thd), &((thd)->transaction.stmt)))
-#define ha_commit(thd) (ha_commit_trans((thd), &((thd)->transaction.all)))
-#define ha_rollback(thd) (ha_rollback_trans((thd), &((thd)->transaction.all)))
+#define ha_commit_stmt(thd) (ha_commit_trans((thd), FALSE))
+#define ha_rollback_stmt(thd) (ha_rollback_trans((thd), FALSE))
+#define ha_commit(thd) (ha_commit_trans((thd), TRUE))
+#define ha_rollback(thd) (ha_rollback_trans((thd), TRUE))
#define ha_supports_generate(T) (T != DB_TYPE_INNODB && \
T != DB_TYPE_BERKELEY_DB && \
@@ -536,46 +841,75 @@ extern TYPELIB myisam_stats_method_typelib;
T != DB_TYPE_FEDERATED_DB && \
T != DB_TYPE_NDBCLUSTER)
-bool ha_caching_allowed(THD* thd, char* table_key,
- uint key_length, uint8 cache_type);
+/* lookups */
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);
-my_off_t ha_get_ptr(byte *ptr, uint pack_length);
-void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos);
+enum db_type ha_checktype(THD *thd, enum db_type database_type,
+ bool no_substitute, bool report_error);
+
+/* basic stuff */
int ha_init(void);
+TYPELIB *ha_known_exts(void);
int ha_panic(enum ha_panic_function flag);
+int ha_update_statistics();
void ha_close_connection(THD* thd);
-enum db_type ha_checktype(enum db_type database_type);
my_bool ha_storage_engine_is_enabled(enum db_type database_type);
+bool ha_flush_logs(void);
+void ha_drop_database(char* path);
int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info);
+int ha_delete_table(THD *thd, enum db_type db_type, const char *path,
+ const char *alias, bool generate_warning);
+
+/* discovery */
int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
-int ha_delete_table(enum db_type db_type, const char *path);
-void ha_drop_database(char* path);
+int ha_discover(THD* thd, const char* dbname, const char* name,
+ const void** frmblob, uint* frmlen);
+int ha_find_files(THD *thd,const char *db,const char *path,
+ const char *wild, bool dir,List<char>* files);
+int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
+
+/* key cache */
int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
int ha_resize_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache_param(KEY_CACHE *key_cache);
+int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
int ha_end_key_cache(KEY_CACHE *key_cache);
-int ha_start_stmt(THD *thd);
-int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name,
- my_off_t end_offset);
-int ha_commit_complete(THD *thd);
+
+/* report to InnoDB that control passes to the client */
int ha_release_temporary_latches(THD *thd);
-int ha_commit_trans(THD *thd, THD_TRANS *trans);
-int ha_rollback_trans(THD *thd, THD_TRANS *trans);
-int ha_rollback_to_savepoint(THD *thd, char *savepoint_name);
-int ha_savepoint(THD *thd, char *savepoint_name);
+
+/* transactions: interface to handlerton functions */
+int ha_start_consistent_snapshot(THD *thd);
+int ha_commit_or_rollback_by_xid(XID *xid, bool commit);
+int ha_commit_one_phase(THD *thd, bool all);
+int ha_rollback_trans(THD *thd, bool all);
+int ha_prepare(THD *thd);
+int ha_recover(HASH *commit_list);
+
+/* transactions: these functions never call handlerton functions directly */
+int ha_commit_trans(THD *thd, bool all);
int ha_autocommit_or_rollback(THD *thd, int error);
-void ha_set_spin_retries(uint retries);
-bool ha_flush_logs(void);
int ha_enable_transaction(THD *thd, bool on);
-int ha_change_key_cache(KEY_CACHE *old_key_cache,
- KEY_CACHE *new_key_cache);
-int ha_discover(THD* thd, const char* dbname, const char* name,
- const void** frmblob, uint* frmlen);
-int ha_find_files(THD *thd,const char *db,const char *path,
- const char *wild, bool dir,List<char>* files);
-int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
-TYPELIB *ha_known_exts(void);
-int ha_start_consistent_snapshot(THD *thd);
+
+/* savepoints */
+int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv);
+int ha_savepoint(THD *thd, SAVEPOINT *sv);
+int ha_release_savepoint(THD *thd, SAVEPOINT *sv);
+
+/* these are called by storage engines */
+void trans_register_ha(THD *thd, bool all, handlerton *ht);
+
+/*
+ Storage engine has to assume the transaction will end up with 2pc if
+ - there is more than one 2pc-capable storage engine available
+ - in the current transaction 2pc was not disabled yet
+*/
+#define trans_need_2pc(thd, all) ((total_ha_2pc > 1) && \
+ !((all ? &thd->transaction.all : &thd->transaction.stmt)->no_2pc))
+
+/* semi-synchronous replication */
+int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
+ my_off_t end_offset);
+int ha_repl_report_replication_stop(THD *thd);
diff --git a/sql/hostname.cc b/sql/hostname.cc
index 32e1d84fac3..3b1eeb63d37 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -140,10 +140,10 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors)
uint i;
host_entry *entry;
DBUG_ENTER("ip_to_hostname");
- *errors= 0;
+ *errors=0;
/* We always treat the loopback address as "localhost". */
- if (in->s_addr == htonl(INADDR_LOOPBACK))
+ if (in->s_addr == htonl(INADDR_LOOPBACK)) // is expanded inline by gcc
DBUG_RETURN((char *)my_localhost);
/* Check first if we have name in cache */
diff --git a/sql/init.cc b/sql/init.cc
index 4beb8db0c6f..e53eeab8902 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -39,12 +39,11 @@ void unireg_init(ulong options)
#endif
VOID(strmov(reg_ext,".frm"));
- specialflag=SPECIAL_SAME_DB_NAME;
+ specialflag=SPECIAL_SAME_DB_NAME | options; /* Set options from argv */
/* Make a tab of powers of 10 */
for (i=0,nr=1.0; i < array_elements(log_10) ; i++)
{ /* It's used by filesort... */
log_10[i]= nr ; nr*= 10.0;
}
- specialflag|=options; /* Set options from argv */
DBUG_VOID_RETURN;
}
diff --git a/sql/item.cc b/sql/item.cc
index 010189c321c..df57c301327 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -21,6 +21,10 @@
#include "mysql_priv.h"
#include <m_ctype.h>
#include "my_dir.h"
+#include "sp_rcontext.h"
+#include "sp_head.h"
+#include "sql_trigger.h"
+#include "sql_select.h"
static void mark_as_dependent(THD *thd,
SELECT_LEX *last, SELECT_LEX *current,
@@ -28,6 +32,131 @@ static void mark_as_dependent(THD *thd,
const String my_null_string("NULL", 4, default_charset_info);
+/****************************************************************************/
+
+/* Hybrid_type_traits {_real} */
+
+void Hybrid_type_traits::fix_length_and_dec(Item *item, Item *arg) const
+{
+ item->decimals= NOT_FIXED_DEC;
+ item->max_length= item->float_length(arg->decimals);
+}
+
+static const Hybrid_type_traits real_traits_instance;
+
+const Hybrid_type_traits *Hybrid_type_traits::instance()
+{
+ return &real_traits_instance;
+}
+
+
+my_decimal *
+Hybrid_type_traits::val_decimal(Hybrid_type *val, my_decimal *to) const
+{
+ double2my_decimal(E_DEC_FATAL_ERROR, val->real, val->dec_buf);
+ return val->dec_buf;
+}
+
+
+String *
+Hybrid_type_traits::val_str(Hybrid_type *val, String *to, uint8 decimals) const
+{
+ to->set(val->real, decimals, &my_charset_bin);
+ return to;
+}
+
+/* Hybrid_type_traits_decimal */
+static const Hybrid_type_traits_decimal decimal_traits_instance;
+
+const Hybrid_type_traits_decimal *Hybrid_type_traits_decimal::instance()
+{
+ return &decimal_traits_instance;
+}
+
+
+void
+Hybrid_type_traits_decimal::fix_length_and_dec(Item *item, Item *arg) const
+{
+ item->decimals= arg->decimals;
+ item->max_length= min(arg->max_length + DECIMAL_LONGLONG_DIGITS,
+ DECIMAL_MAX_STR_LENGTH);
+}
+
+
+void Hybrid_type_traits_decimal::set_zero(Hybrid_type *val) const
+{
+ my_decimal_set_zero(&val->dec_buf[0]);
+ val->used_dec_buf_no= 0;
+}
+
+
+void Hybrid_type_traits_decimal::add(Hybrid_type *val, Field *f) const
+{
+ my_decimal_add(E_DEC_FATAL_ERROR,
+ &val->dec_buf[val->used_dec_buf_no ^ 1],
+ &val->dec_buf[val->used_dec_buf_no],
+ f->val_decimal(&val->dec_buf[2]));
+ val->used_dec_buf_no^= 1;
+}
+
+
+void Hybrid_type_traits_decimal::div(Hybrid_type *val, ulonglong u) const
+{
+ int2my_decimal(E_DEC_FATAL_ERROR, u, TRUE, &val->dec_buf[2]);
+ /* XXX: what is '4' for scale? */
+ my_decimal_div(E_DEC_FATAL_ERROR,
+ &val->dec_buf[val->used_dec_buf_no ^ 1],
+ &val->dec_buf[val->used_dec_buf_no],
+ &val->dec_buf[2], 4);
+ val->used_dec_buf_no^= 1;
+}
+
+
+longlong
+Hybrid_type_traits_decimal::val_int(Hybrid_type *val, bool unsigned_flag) const
+{
+ longlong result;
+ my_decimal2int(E_DEC_FATAL_ERROR, &val->dec_buf[val->used_dec_buf_no],
+ unsigned_flag, &result);
+ return result;
+}
+
+
+double
+Hybrid_type_traits_decimal::val_real(Hybrid_type *val) const
+{
+ my_decimal2double(E_DEC_FATAL_ERROR, &val->dec_buf[val->used_dec_buf_no],
+ &val->real);
+ return val->real;
+}
+
+
+String *
+Hybrid_type_traits_decimal::val_str(Hybrid_type *val, String *to,
+ uint8 decimals) const
+{
+ my_decimal_round(E_DEC_FATAL_ERROR, &val->dec_buf[val->used_dec_buf_no],
+ decimals, FALSE, &val->dec_buf[2]);
+ my_decimal2string(E_DEC_FATAL_ERROR, &val->dec_buf[2], 0, 0, 0, to);
+ return to;
+}
+
+/* Hybrid_type_traits_integer */
+static const Hybrid_type_traits_integer integer_traits_instance;
+
+const Hybrid_type_traits_integer *Hybrid_type_traits_integer::instance()
+{
+ return &integer_traits_instance;
+}
+
+void
+Hybrid_type_traits_integer::fix_length_and_dec(Item *item, Item *arg) const
+{
+ item->decimals= 0;
+ item->max_length= 21;
+ item->unsigned_flag= 0;
+}
+
/*****************************************************************************
** Item functions
*****************************************************************************/
@@ -39,13 +168,158 @@ void item_init(void)
item_user_lock_init();
}
+
+/*
+TODO: make this functions class dependent
+*/
+
+bool Item::val_bool()
+{
+ switch(result_type()) {
+ case INT_RESULT:
+ return val_int() != 0;
+ case DECIMAL_RESULT:
+ {
+ my_decimal decimal_value;
+ my_decimal *val= val_decimal(&decimal_value);
+ if (val)
+ return !my_decimal_is_zero(val);
+ return 0;
+ }
+ case REAL_RESULT:
+ case STRING_RESULT:
+ return val_real() != 0.0;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ return 0; // Wrong (but safe)
+ }
+}
+
+
+String *Item::val_string_from_real(String *str)
+{
+ double nr= val_real();
+ if (null_value)
+ return 0; /* purecov: inspected */
+ str->set(nr,decimals, &my_charset_bin);
+ return str;
+}
+
+
+String *Item::val_string_from_int(String *str)
+{
+ longlong nr= val_int();
+ if (null_value)
+ return 0;
+ if (unsigned_flag)
+ str->set((ulonglong) nr, &my_charset_bin);
+ else
+ str->set(nr, &my_charset_bin);
+ return str;
+}
+
+
+String *Item::val_string_from_decimal(String *str)
+{
+ my_decimal dec_buf, *dec= val_decimal(&dec_buf);
+ if (null_value)
+ return 0;
+ my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf);
+ my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, 0, str);
+ return str;
+}
+
+
+my_decimal *Item::val_decimal_from_real(my_decimal *decimal_value)
+{
+ double nr= val_real();
+ if (null_value)
+ return 0;
+ double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
+ return (decimal_value);
+}
+
+
+my_decimal *Item::val_decimal_from_int(my_decimal *decimal_value)
+{
+ longlong nr= val_int();
+ if (null_value)
+ return 0;
+ int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
+ return decimal_value;
+}
+
+
+my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value)
+{
+ String *res;
+ char *end_ptr;
+ if (!(res= val_str(&str_value)))
+ return 0; // NULL or EOM
+
+ end_ptr= (char*) res->ptr()+ res->length();
+ if (str2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_BAD_NUM,
+ res->ptr(), res->length(), res->charset(),
+ decimal_value) & E_DEC_BAD_NUM)
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), "DECIMAL",
+ str_value.c_ptr());
+ }
+ return decimal_value;
+}
+
+
+double Item::val_real_from_decimal()
+{
+ /* Note that fix_fields may not be called for Item_avg_field items */
+ double result;
+ my_decimal value_buff, *dec_val= val_decimal(&value_buff);
+ if (null_value)
+ return 0.0;
+ my_decimal2double(E_DEC_FATAL_ERROR, dec_val, &result);
+ return result;
+}
+
+
+longlong Item::val_int_from_decimal()
+{
+ /* Note that fix_fields may not be called for Item_avg_field items */
+ longlong result;
+ my_decimal value, *dec_val= val_decimal(&value);
+ if (null_value)
+ return 0;
+ my_decimal2int(E_DEC_FATAL_ERROR, dec_val, unsigned_flag, &result);
+ return result;
+}
+
+
+void *Item::operator new(size_t size, Item *reuse, uint *rsize)
+{
+ if (reuse && size <= reuse->rsize)
+ {
+ if (rsize)
+ (*rsize)= reuse->rsize;
+ reuse->cleanup();
+ delete reuse;
+ TRASH((void *)reuse, size);
+ return (void *)reuse;
+ }
+ if (rsize)
+ (*rsize)= (uint) size;
+ return (void *)sql_alloc((uint)size);
+}
+
+
Item::Item():
- fixed(0)
+ rsize(0), name(0), orig_name(0), name_length(0), fixed(0),
+ is_autogenerated_name(TRUE),
+ collation(&my_charset_bin, DERIVATION_COERCIBLE)
{
marker= 0;
maybe_null=null_value=with_sum_func=unsigned_flag=0;
- collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
- name= 0;
decimals= 0; max_length= 0;
/* Put item in free list so that we can free all items at end */
@@ -68,13 +342,15 @@ Item::Item():
}
/*
- Constructor used by Item_field, Item_*_ref & agregate (sum) functions.
+ Constructor used by Item_field, Item_*_ref & aggregate (sum) functions.
Used for duplicating lists in processing queries with temporary
tables
*/
Item::Item(THD *thd, Item *item):
+ rsize(0),
str_value(item->str_value),
name(item->name),
+ orig_name(item->orig_name),
max_length(item->max_length),
marker(item->marker),
decimals(item->decimals),
@@ -90,38 +366,105 @@ Item::Item(THD *thd, Item *item):
}
+uint Item::decimal_precision() const
+{
+ Item_result restype= result_type();
+
+ if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
+ return min(my_decimal_length_to_precision(max_length, decimals, unsigned_flag),
+ DECIMAL_MAX_PRECISION);
+ return min(max_length, DECIMAL_MAX_PRECISION);
+}
+
+
void Item::print_item_w_name(String *str)
{
print(str);
if (name)
{
- str->append(" AS `", 5);
- str->append(name);
- str->append('`');
+ THD *thd= current_thd;
+ str->append(" AS ", 4);
+ append_identifier(thd, str, name, (uint) strlen(name));
}
}
-Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
- const char *field_name_par)
- :orig_db_name(db_name_par), orig_table_name(table_name_par),
- orig_field_name(field_name_par),
- db_name(db_name_par), table_name(table_name_par),
- field_name(field_name_par), cached_field_index(NO_CACHED_FIELD_INDEX),
+void Item::cleanup()
+{
+ DBUG_ENTER("Item::cleanup");
+ DBUG_PRINT("info", ("Item: 0x%lx, Type: %d, name %s, original name %s",
+ this, (int)type(), name ? name : "(null)",
+ orig_name ? orig_name : "null"));
+ fixed=0;
+ marker= 0;
+ if (orig_name)
+ name= orig_name;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ cleanup() item if it is 'fixed'
+
+ SYNOPSIS
+ cleanup_processor()
+ arg - a dummy parameter, is not used here
+*/
+
+bool Item::cleanup_processor(byte *arg)
+{
+ if (fixed)
+ cleanup();
+ return FALSE;
+}
+
+
+/*
+ rename item (used for views, cleanup() return original name)
+
+ SYNOPSIS
+ Item::rename()
+ new_name new name of item;
+*/
+
+void Item::rename(char *new_name)
+{
+ /*
+ we can compare pointers to names here, because if name was not changed,
+ pointer will be same
+ */
+ if (!orig_name && new_name != name)
+ orig_name= name;
+ name= new_name;
+}
+
+
+Item_ident::Item_ident(Name_resolution_context *context_arg,
+ const char *db_name_arg,const char *table_name_arg,
+ const char *field_name_arg)
+ :orig_db_name(db_name_arg), orig_table_name(table_name_arg),
+ orig_field_name(field_name_arg), context(context_arg),
+ db_name(db_name_arg), table_name(table_name_arg),
+ field_name(field_name_arg),
+ alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
cached_table(0), depended_from(0)
{
- name = (char*) field_name_par;
+ name = (char*) field_name_arg;
}
-// Constructor used by Item_field & Item_*_ref (see Item comment)
+
+/* Constructor used by Item_field & Item_*_ref (see Item comment) */
+
Item_ident::Item_ident(THD *thd, Item_ident *item)
:Item(thd, item),
orig_db_name(item->orig_db_name),
orig_table_name(item->orig_table_name),
orig_field_name(item->orig_field_name),
+ context(item->context),
db_name(item->db_name),
table_name(item->table_name),
field_name(item->field_name),
+ alias_name_used(item->alias_name_used),
cached_field_index(item->cached_field_index),
cached_table(item->cached_table),
depended_from(item->depended_from)
@@ -130,14 +473,19 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
void Item_ident::cleanup()
{
DBUG_ENTER("Item_ident::cleanup");
- DBUG_PRINT("enter", ("b:%s(%s), t:%s(%s), f:%s(%s)",
- db_name, orig_db_name,
- table_name, orig_table_name,
- field_name, orig_field_name));
+#ifdef CANT_BE_USED_AS_MEMORY_IS_FREED
+ db_name ? db_name : "(null)",
+ orig_db_name ? orig_db_name : "(null)",
+ table_name ? table_name : "(null)",
+ orig_table_name ? orig_table_name : "(null)",
+ field_name ? field_name : "(null)",
+ orig_field_name ? orig_field_name : "(null)"));
+#endif
Item::cleanup();
db_name= orig_db_name;
table_name= orig_table_name;
field_name= orig_field_name;
+ depended_from= 0;
DBUG_VOID_RETURN;
}
@@ -150,6 +498,45 @@ bool Item_ident::remove_dependence_processor(byte * arg)
}
+/*
+ Store the pointer to this item field into a list if not already there.
+
+ SYNOPSIS
+ Item_field::collect_item_field_processor()
+ arg pointer to a List<Item_field>
+
+ DESCRIPTION
+ The method is used by Item::walk to collect all unique Item_field objects
+ from a tree of Items into a set of items represented as a list.
+
+ IMPLEMENTATION
+ Item_cond::walk() and Item_func::walk() stop the evaluation of the
+ processor function for its arguments once the processor returns
+ true.Therefore in order to force this method being called for all item
+ arguments in a condition the method must return false.
+
+ RETURN
+ false to force the evaluation of collect_item_field_processor
+ for the subsequent items.
+*/
+
+bool Item_field::collect_item_field_processor(byte *arg)
+{
+ DBUG_ENTER("Item_field::collect_item_field_processor");
+ DBUG_PRINT("info", ("%s", field->field_name ? field->field_name : "noname"));
+ List<Item_field> *item_list= (List<Item_field>*) arg;
+ List_iterator<Item_field> item_list_it(*item_list);
+ Item_field *curr_item;
+ while ((curr_item= item_list_it++))
+ {
+ if (curr_item->eq(this, 1))
+ DBUG_RETURN(FALSE); /* Already in the set. */
+ }
+ item_list->push_back(this);
+ DBUG_RETURN(FALSE);
+}
+
+
bool Item::check_cols(uint c)
{
if (c != 1)
@@ -167,12 +554,15 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
{
/* Empty string, used by AS or internal function like last_insert_id() */
name= (char*) str;
+ name_length= 0;
return;
}
if (cs->ctype)
{
- // This will probably need a better implementation in the future:
- // a function in CHARSET_INFO structure.
+ /*
+ This will probably need a better implementation in the future:
+ a function in CHARSET_INFO structure.
+ */
while (length && !my_isgraph(cs,*str))
{ // Fix problem with yacc
length--;
@@ -182,12 +572,12 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
if (!my_charset_same(cs, system_charset_info))
{
uint32 res_length;
- name= sql_strmake_with_convert(str, length, cs,
+ name= sql_strmake_with_convert(str, name_length= length, cs,
MAX_ALIAS_NAME, system_charset_info,
&res_length);
}
else
- name=sql_strmake(str, min(length,MAX_ALIAS_NAME));
+ name= sql_strmake(str, (name_length= min(length,MAX_ALIAS_NAME)));
}
@@ -243,7 +633,39 @@ Item *Item_num::safe_charset_converter(CHARSET_INFO *tocs)
if ((conv= new Item_string(s->ptr(), s->length(), s->charset())))
{
conv->str_value.copy();
- conv->str_value.shrink_to_length();
+ conv->str_value.mark_as_const();
+ }
+ return conv;
+}
+
+
+Item *Item_static_int_func::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ Item_string *conv;
+ char buf[64];
+ String *s, tmp(buf, sizeof(buf), &my_charset_bin);
+ s= val_str(&tmp);
+ if ((conv= new Item_static_string_func(func_name, s->ptr(), s->length(),
+ s->charset())))
+ {
+ conv->str_value.copy();
+ conv->str_value.mark_as_const();
+ }
+ return conv;
+}
+
+
+Item *Item_static_float_func::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ Item_string *conv;
+ char buf[64];
+ String *s, tmp(buf, sizeof(buf), &my_charset_bin);
+ s= val_str(&tmp);
+ if ((conv= new Item_static_string_func(func_name, s->ptr(), s->length(),
+ s->charset())))
+ {
+ conv->str_value.copy();
+ conv->str_value.mark_as_const();
}
return conv;
}
@@ -268,45 +690,36 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
return NULL;
}
conv->str_value.copy();
- /*
- The above line executes str_value.realloc() internally,
- which alligns Alloced_length using ALLIGN_SIZE.
- In the case of Item_string::str_value we don't want
- Alloced_length to be longer than str_length.
- Otherwise, some functions like Item_func_concat::val_str()
- try to reuse str_value as a buffer for concatenation result
- for optimization purposes, so our string constant become
- corrupted. See bug#8785 for more details.
- Let's shrink Alloced_length to str_length to avoid this problem.
- */
- conv->str_value.shrink_to_length();
+ /* Ensure that no one is going to change the result string */
+ conv->str_value.mark_as_const();
return conv;
}
-Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs)
+Item *Item_static_string_func::safe_charset_converter(CHARSET_INFO *tocs)
{
- if (const_item())
+ Item_string *conv;
+ uint conv_errors;
+ String tmp, cstr, *ostr= val_str(&tmp);
+ cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
+ if (conv_errors ||
+ !(conv= new Item_static_string_func(func_name,
+ cstr.ptr(), cstr.length(),
+ cstr.charset(),
+ collation.derivation)))
{
- Item_string *conv;
- uint conv_errors;
- char buf[MAX_FIELD_WIDTH];
- String tmp(buf, sizeof(buf), &my_charset_bin);
- String cstr, *ostr= val_str(&tmp);
/*
- As safe_charset_converter is not executed for
- a parameter bound to NULL, ostr should never be 0.
+ Safe conversion is not possible (or EOM).
+ We could not convert a string into the requested character set
+ without data loss. The target charset does not cover all the
+ characters from the string. Operation cannot be done correctly.
*/
- cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
- if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
- cstr.charset(),
- collation.derivation)))
- return NULL;
- conv->str_value.copy();
- conv->str_value.shrink_to_length();
- return conv;
+ return NULL;
}
- return NULL;
+ conv->str_value.copy();
+ /* Ensure that no one is going to change the result string */
+ conv->str_value.mark_as_const();
+ return conv;
}
@@ -365,6 +778,244 @@ CHARSET_INFO *Item::default_charset()
}
+int Item::save_in_field_no_warnings(Field *field, bool no_conversions)
+{
+ int res;
+ THD *thd= field->table->in_use;
+ enum_check_fields tmp= thd->count_cuted_fields;
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+ res= save_in_field(field, no_conversions);
+ thd->count_cuted_fields= tmp;
+ return res;
+}
+
+
+/*****************************************************************************
+ Item_splocal methods
+*****************************************************************************/
+double Item_splocal::val_real()
+{
+ DBUG_ASSERT(fixed);
+ Item *it= this_item();
+ double ret= it->val_real();
+ null_value= it->null_value;
+ return ret;
+}
+
+
+longlong Item_splocal::val_int()
+{
+ DBUG_ASSERT(fixed);
+ Item *it= this_item();
+ longlong ret= it->val_int();
+ null_value= it->null_value;
+ return ret;
+}
+
+
+String *Item_splocal::val_str(String *sp)
+{
+ DBUG_ASSERT(fixed);
+ Item *it= this_item();
+ String *ret= it->val_str(sp);
+
+ null_value= it->null_value;
+ /*
+ This way we mark returned value of val_str as const,
+ so that various functions (e.g. CONCAT) won't try to
+ modify the value of the Item. Analogous mechanism is
+ implemented for Item_param.
+ Without this trick Item_splocal could be changed as a
+ side-effect of expression computation. Here is an example
+ of what happens without it: suppose x is varchar local
+ variable in a SP with initial value 'ab' Then
+ select concat(x,'c');
+ would change x's value to 'abc', as Item_func_concat::val_str()
+ would use x's internal buffer to compute the result.
+ This is intended behaviour of Item_func_concat. Comments to
+ Item_param class contain some more details on the topic.
+ */
+
+ if (!ret)
+ return NULL;
+
+ str_value_ptr.set(ret->ptr(), ret->length(),
+ ret->charset());
+ return &str_value_ptr;
+}
+
+
+my_decimal *Item_splocal::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed);
+ Item *it= this_item();
+ my_decimal *val= it->val_decimal(decimal_value);
+ null_value= it->null_value;
+ return val;
+}
+
+
+bool Item_splocal::is_null()
+{
+ Item *it= this_item();
+ bool ret= it->is_null();
+ null_value= it->null_value;
+ return ret;
+}
+
+
+Item *
+Item_splocal::this_item()
+{
+ THD *thd= current_thd;
+
+ return thd->spcont->get_item(m_offset);
+}
+
+
+Item **
+Item_splocal::this_item_addr(THD *thd, Item **addr)
+{
+ return thd->spcont->get_item_addr(m_offset);
+}
+
+Item *
+Item_splocal::this_const_item() const
+{
+ THD *thd= current_thd;
+
+ return thd->spcont->get_item(m_offset);
+}
+
+Item::Type
+Item_splocal::type() const
+{
+ THD *thd= current_thd;
+
+ if (thd->spcont)
+ return thd->spcont->get_item(m_offset)->type();
+ return NULL_ITEM; // Anything but SUBSELECT_ITEM
+}
+
+
+bool Item_splocal::fix_fields(THD *, Item **)
+{
+ Item *it= this_item();
+ DBUG_ASSERT(it->fixed);
+ max_length= it->max_length;
+ decimals= it->decimals;
+ fixed= 1;
+ return FALSE;
+}
+
+
+void Item_splocal::cleanup()
+{
+ fixed= 0;
+}
+
+
+void Item_splocal::print(String *str)
+{
+ str->reserve(m_name.length+8);
+ str->append(m_name.str, m_name.length);
+ str->append('@');
+ str->qs_append(m_offset);
+}
+
+
+/*****************************************************************************
+ Item_name_const methods
+*****************************************************************************/
+double Item_name_const::val_real()
+{
+ DBUG_ASSERT(fixed);
+ double ret= value_item->val_real();
+ null_value= value_item->null_value;
+ return ret;
+}
+
+
+longlong Item_name_const::val_int()
+{
+ DBUG_ASSERT(fixed);
+ longlong ret= value_item->val_int();
+ null_value= value_item->null_value;
+ return ret;
+}
+
+
+String *Item_name_const::val_str(String *sp)
+{
+ DBUG_ASSERT(fixed);
+ String *ret= value_item->val_str(sp);
+ null_value= value_item->null_value;
+ return ret;
+}
+
+
+my_decimal *Item_name_const::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed);
+ my_decimal *val= value_item->val_decimal(decimal_value);
+ null_value= value_item->null_value;
+ return val;
+}
+
+
+bool Item_name_const::is_null()
+{
+ bool ret= value_item->is_null();
+ null_value= value_item->null_value;
+ return ret;
+}
+
+Item::Type Item_name_const::type() const
+{
+ return value_item->type();
+}
+
+
+bool Item_name_const::fix_fields(THD *thd, Item **)
+{
+ char buf[128];
+ String *item_name;
+ String s(buf, sizeof(buf), &my_charset_bin);
+ s.length(0);
+
+ if (value_item->fix_fields(thd, &value_item) ||
+ name_item->fix_fields(thd, &name_item))
+ return TRUE;
+ if (!(value_item->const_item() && name_item->const_item()))
+ return TRUE;
+
+ if (!(item_name= name_item->val_str(&s)))
+ return TRUE; /* Can't have a NULL name */
+
+ set_name(item_name->ptr(), (uint) item_name->length(), system_charset_info);
+ max_length= value_item->max_length;
+ decimals= value_item->decimals;
+ fixed= 1;
+ return FALSE;
+}
+
+
+void Item_name_const::cleanup()
+{
+ fixed= 0;
+}
+
+
+void Item_name_const::print(String *str)
+{
+ str->append("NAME_CONST(");
+ name_item->print(str);
+ str->append(',');
+ value_item->print(str);
+ str->append(')');
+}
+
+
/*
Move SUM items out from item tree and replace with reference
@@ -393,9 +1044,9 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
/* Will split complicated items and ignore simple ones */
split_sum_func(thd, ref_pointer_array, fields);
}
- else if ((type() == SUM_FUNC_ITEM ||
- (used_tables() & ~PARAM_TABLE_BIT)) &&
- type() != REF_ITEM)
+ else if ((type() == SUM_FUNC_ITEM || (used_tables() & ~PARAM_TABLE_BIT)) &&
+ (type() != REF_ITEM ||
+ ((Item_ref*)this)->ref_type() == Item_ref::VIEW_REF))
{
/*
Replace item with a reference so that we can easily calculate
@@ -404,14 +1055,17 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
The test above is to ensure we don't do a reference for things
that are constants (PARAM_TABLE_BIT is in effect a constant)
or already referenced (for example an item in HAVING)
+ Exception is Item_direct_view_ref which we need to convert to
+ Item_ref to allow fields from view being stored in tmp table.
*/
uint el= fields.elements;
- Item *new_item;
- ref_pointer_array[el]= this;
- if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name)))
+ Item *new_item, *real_itm= real_item();
+
+ ref_pointer_array[el]= real_itm;
+ if (!(new_item= new Item_ref(&thd->lex->current_select->context,
+ ref_pointer_array + el, 0, name)))
return; // fatal_error is set
- fields.push_front(this);
- ref_pointer_array[el]= this;
+ fields.push_front(real_itm);
thd->change_item_tree(ref, new_item);
}
}
@@ -421,7 +1075,7 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
Aggregate two collations together taking
into account their coercibility (aka derivation):
- 0 == DERIVATION_EXPLICIT - an explicitely written COLLATE clause
+ 0 == DERIVATION_EXPLICIT - an explicitly written COLLATE clause
1 == DERIVATION_NONE - a mix of two different collations
2 == DERIVATION_IMPLICIT - a column
3 == DERIVATION_COERCIBLE - a string constant
@@ -459,7 +1113,7 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
/*
We do allow to use binary strings (like BLOBS)
together with character strings.
- Binaries have more precedance than a character
+ Binaries have more precedence than a character
string of the same derivation.
*/
if (collation == &my_charset_bin)
@@ -537,10 +1191,8 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
return 1;
}
if (collation->state & MY_CS_BINSORT)
- {
return 0;
- }
- else if (dt.collation->state & MY_CS_BINSORT)
+ if (dt.collation->state & MY_CS_BINSORT)
{
set(dt);
return 0;
@@ -662,13 +1314,13 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
}
THD *thd= current_thd;
- Item_arena *arena, backup;
+ Query_arena *arena, backup;
bool res= FALSE;
/*
In case we're in statement prepare, create conversion item
in its memory: it will be reused on each execute.
*/
- arena= thd->change_arena_if_needed(&backup);
+ arena= thd->activate_stmt_arena_if_needed(&backup);
for (arg= args, last= args + nargs; arg < last; arg++)
{
@@ -691,7 +1343,8 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
res= TRUE;
break; // we cannot return here, we need to restore "arena".
}
- conv->fix_fields(thd, 0, &conv);
+ if ((*arg)->type() == Item::FIELD_ITEM)
+ ((Item_field *)(*arg))->no_const_subst= 1;
/*
If in statement prepare, then we create a converter for two
constant items, do it once and then reuse it.
@@ -706,9 +1359,14 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
*arg= conv;
else
thd->change_item_tree(arg, conv);
+ /*
+ We do not check conv->fixed, because Item_func_conv_charset which can
+ be return by safe_charset_converter can't be fixed at creation
+ */
+ conv->fix_fields(thd, arg);
}
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ thd->restore_active_arena(arena, &backup);
return res;
}
@@ -718,7 +1376,9 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
/**********************************************/
Item_field::Item_field(Field *f)
- :Item_ident(NullS, f->table_name, f->field_name)
+ :Item_ident(0, NullS, *f->table_name, f->field_name),
+ item_equal(0), no_const_subst(0),
+ have_privileges(0), any_privileges(0)
{
set_field(f);
/*
@@ -728,8 +1388,11 @@ Item_field::Item_field(Field *f)
orig_table_name= orig_field_name= "";
}
-Item_field::Item_field(THD *thd, Field *f)
- :Item_ident(f->table->table_cache_key, f->table_name, f->field_name)
+Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
+ Field *f)
+ :Item_ident(context_arg, f->table->s->db, *f->table_name, f->field_name),
+ item_equal(0), no_const_subst(0),
+ have_privileges(0), any_privileges(0)
{
/*
We always need to provide Item_field with a fully qualified field
@@ -746,7 +1409,7 @@ Item_field::Item_field(THD *thd, Field *f)
structure can go away and pop up again between subsequent executions
of a prepared statement).
*/
- if (thd->current_arena->is_stmt_prepare())
+ if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
{
if (db_name)
orig_db_name= thd->strdup(db_name);
@@ -762,11 +1425,26 @@ Item_field::Item_field(THD *thd, Field *f)
set_field(f);
}
+
+Item_field::Item_field(Name_resolution_context *context_arg,
+ const char *db_arg,const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_ident(context_arg, db_arg,table_name_arg,field_name_arg),
+ field(0), result_field(0), item_equal(0), no_const_subst(0),
+ have_privileges(0), any_privileges(0)
+{
+ collation.set(DERIVATION_IMPLICIT);
+}
+
// Constructor need to process subselect with temporary tables (see Item)
Item_field::Item_field(THD *thd, Item_field *item)
:Item_ident(thd, item),
field(item->field),
- result_field(item->result_field)
+ result_field(item->result_field),
+ item_equal(item->item_equal),
+ no_const_subst(item->no_const_subst),
+ have_privileges(item->have_privileges),
+ any_privileges(item->any_privileges)
{
collation.set(DERIVATION_IMPLICIT);
}
@@ -775,11 +1453,12 @@ void Item_field::set_field(Field *field_par)
{
field=result_field=field_par; // for easy coding with fields
maybe_null=field->maybe_null();
- max_length=field_par->max_length();
decimals= field->decimals();
- table_name=field_par->table_name;
- field_name=field_par->field_name;
- db_name=field_par->table->table_cache_key;
+ max_length= field_par->max_length();
+ table_name= *field_par->table_name;
+ field_name= field_par->field_name;
+ db_name= field_par->table->s->db;
+ alias_name_used= field_par->table->alias_name_used;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
collation.set(field_par->charset(), DERIVATION_IMPLICIT);
fixed= 1;
@@ -824,6 +1503,59 @@ const char *Item_ident::full_name() const
return tmp;
}
+void Item_ident::print(String *str)
+{
+ THD *thd= current_thd;
+ char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
+ const char *d_name= db_name, *t_name= table_name;
+ if (lower_case_table_names== 1 ||
+ (lower_case_table_names == 2 && !alias_name_used))
+ {
+ if (table_name && table_name[0])
+ {
+ strmov(t_name_buff, table_name);
+ my_casedn_str(files_charset_info, t_name_buff);
+ t_name= t_name_buff;
+ }
+ if (db_name && db_name[0])
+ {
+ strmov(d_name_buff, db_name);
+ my_casedn_str(files_charset_info, d_name_buff);
+ d_name= d_name_buff;
+ }
+ }
+
+ if (!table_name || !field_name)
+ {
+ const char *nm= field_name ? field_name : name ? name : "tmp_field";
+ append_identifier(thd, str, nm, (uint) strlen(nm));
+ return;
+ }
+ if (db_name && db_name[0] && !alias_name_used)
+ {
+ if (!(cached_table && cached_table->belong_to_view &&
+ cached_table->belong_to_view->compact_view_format))
+ {
+ append_identifier(thd, str, d_name, (uint)strlen(d_name));
+ str->append('.');
+ }
+ append_identifier(thd, str, t_name, (uint)strlen(t_name));
+ str->append('.');
+ append_identifier(thd, str, field_name, (uint)strlen(field_name));
+ }
+ else
+ {
+ if (table_name[0])
+ {
+ append_identifier(thd, str, t_name, (uint) strlen(t_name));
+ str->append('.');
+ append_identifier(thd, str, field_name, (uint) strlen(field_name));
+ }
+ else
+ append_identifier(thd, str, field_name, (uint) strlen(field_name));
+ }
+}
+
/* ARGSUSED */
String *Item_field::val_str(String *str)
{
@@ -834,7 +1566,8 @@ String *Item_field::val_str(String *str)
return field->val_str(str,&str_value);
}
-double Item_field::val()
+
+double Item_field::val_real()
{
DBUG_ASSERT(fixed == 1);
if ((null_value=field->is_null()))
@@ -842,6 +1575,7 @@ double Item_field::val()
return field->val_real();
}
+
longlong Item_field::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -851,6 +1585,14 @@ longlong Item_field::val_int()
}
+my_decimal *Item_field::val_decimal(my_decimal *decimal_value)
+{
+ if ((null_value= field->is_null()))
+ return 0;
+ return field->val_decimal(decimal_value);
+}
+
+
String *Item_field::str_result(String *str)
{
if ((null_value=result_field->is_null()))
@@ -905,6 +1647,40 @@ longlong Item_field::val_int_result()
}
+my_decimal *Item_field::val_decimal_result(my_decimal *decimal_value)
+{
+ if ((null_value= result_field->is_null()))
+ return 0;
+ return result_field->val_decimal(decimal_value);
+}
+
+
+bool Item_field::val_bool_result()
+{
+ if ((null_value= result_field->is_null()))
+ return FALSE;
+ switch (result_field->result_type()) {
+ case INT_RESULT:
+ return result_field->val_int() != 0;
+ case DECIMAL_RESULT:
+ {
+ my_decimal decimal_value;
+ my_decimal *val= result_field->val_decimal(&decimal_value);
+ if (val)
+ return !my_decimal_is_zero(val);
+ return 0;
+ }
+ case REAL_RESULT:
+ case STRING_RESULT:
+ return result_field->val_real() != 0.0;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ return 0; // Shut up compiler
+ }
+}
+
+
bool Item_field::eq(const Item *item, bool binary_cmp) const
{
if (item->type() != FIELD_ITEM)
@@ -952,8 +1728,9 @@ Item *Item_field::get_tmp_table_item(THD *thd)
/*
- Create an item from a string we KNOW points to a valid longlong/ulonglong
- end \0 terminated number string
+ Create an item from a string we KNOW points to a valid longlong
+ end \0 terminated number string.
+ This is always 'signed'. Unsigned values are created with Item_uint()
*/
Item_int::Item_int(const char *str_arg, uint length)
@@ -967,6 +1744,12 @@ Item_int::Item_int(const char *str_arg, uint length)
}
+my_decimal *Item_int::val_decimal(my_decimal *decimal_value)
+{
+ int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_value);
+ return decimal_value;
+}
+
String *Item_int::val_str(String *str)
{
// following assert is redundant, because fixed=1 assigned in constructor
@@ -1014,7 +1797,116 @@ void Item_uint::print(String *str)
}
-String *Item_real::val_str(String *str)
+Item_decimal::Item_decimal(const char *str_arg, uint length,
+ CHARSET_INFO *charset)
+{
+ str2my_decimal(E_DEC_FATAL_ERROR, str_arg, length, charset, &decimal_value);
+ name= (char*) str_arg;
+ decimals= (uint8) decimal_value.frac;
+ fixed= 1;
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
+}
+
+Item_decimal::Item_decimal(longlong val, bool unsig)
+{
+ int2my_decimal(E_DEC_FATAL_ERROR, val, unsig, &decimal_value);
+ decimals= (uint8) decimal_value.frac;
+ fixed= 1;
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
+}
+
+
+Item_decimal::Item_decimal(double val, int precision, int scale)
+{
+ double2my_decimal(E_DEC_FATAL_ERROR, val, &decimal_value);
+ decimals= (uint8) decimal_value.frac;
+ fixed= 1;
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
+}
+
+
+Item_decimal::Item_decimal(const char *str, const my_decimal *val_arg,
+ uint decimal_par, uint length)
+{
+ my_decimal2decimal(val_arg, &decimal_value);
+ name= (char*) str;
+ decimals= (uint8) decimal_par;
+ max_length= length;
+ fixed= 1;
+}
+
+
+Item_decimal::Item_decimal(my_decimal *value_par)
+{
+ my_decimal2decimal(value_par, &decimal_value);
+ decimals= (uint8) decimal_value.frac;
+ fixed= 1;
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, !decimal_value.sign());
+}
+
+
+Item_decimal::Item_decimal(const char *bin, int precision, int scale)
+{
+ binary2my_decimal(E_DEC_FATAL_ERROR, bin,
+ &decimal_value, precision, scale);
+ decimals= (uint8) decimal_value.frac;
+ fixed= 1;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ !decimal_value.sign());
+}
+
+
+longlong Item_decimal::val_int()
+{
+ longlong result;
+ my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &result);
+ return result;
+}
+
+double Item_decimal::val_real()
+{
+ double result;
+ my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result);
+ return result;
+}
+
+String *Item_decimal::val_str(String *result)
+{
+ result->set_charset(&my_charset_bin);
+ my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, result);
+ return result;
+}
+
+void Item_decimal::print(String *str)
+{
+ my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, &str_value);
+ str->append(str_value);
+}
+
+
+bool Item_decimal::eq(const Item *item, bool binary_cmp) const
+{
+ if (type() == item->type() && item->basic_const_item())
+ {
+ /*
+ We need to cast off const to call val_decimal(). This should
+ be OK for a basic constant. Additionally, we can pass 0 as
+ a true decimal constant will return its internal decimal
+ storage and ignore the argument.
+ */
+ Item *arg= (Item*) item;
+ my_decimal *value= arg->val_decimal(0);
+ return !my_decimal_cmp(&decimal_value, value);
+ }
+ return 0;
+}
+
+
+String *Item_float::val_str(String *str)
{
// following assert is redundant, because fixed=1 assigned in constructor
DBUG_ASSERT(fixed == 1);
@@ -1023,6 +1915,15 @@ String *Item_real::val_str(String *str)
}
+my_decimal *Item_float::val_decimal(my_decimal *decimal_value)
+{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
+ double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_value);
+ return (decimal_value);
+}
+
+
void Item_string::print(String *str)
{
str->append('_');
@@ -1032,9 +1933,76 @@ void Item_string::print(String *str)
str->append('\'');
}
+
+inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str, char *end)
+{
+ return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end;
+}
+
+
+double Item_string::val_real()
+{
+ DBUG_ASSERT(fixed == 1);
+ int error;
+ char *end, *org_end;
+ double tmp;
+ CHARSET_INFO *cs= str_value.charset();
+
+ org_end= (char*) str_value.ptr() + str_value.length();
+ tmp= my_strntod(cs, (char*) str_value.ptr(), str_value.length(), &end,
+ &error);
+ if (error || (end != org_end && !check_if_only_end_space(cs, end, org_end)))
+ {
+ /*
+ We can use str_value.ptr() here as Item_string is gurantee to put an
+ end \0 here.
+ */
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), "DOUBLE",
+ str_value.ptr());
+ }
+ return tmp;
+}
+
+
+longlong Item_string::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ int err;
+ longlong tmp;
+ char *end= (char*) str_value.ptr()+ str_value.length();
+ char *org_end= end;
+ CHARSET_INFO *cs= str_value.charset();
+
+ tmp= (*(cs->cset->strtoll10))(cs, str_value.ptr(), &end, &err);
+ /*
+ TODO: Give error if we wanted a signed integer and we got an unsigned
+ one
+ */
+ if (err > 0 ||
+ (end != org_end && !check_if_only_end_space(cs, end, org_end)))
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
+ str_value.ptr());
+ }
+ return tmp;
+}
+
+
+my_decimal *Item_string::val_decimal(my_decimal *decimal_value)
+{
+ return val_decimal_from_string(decimal_value);
+}
+
+
bool Item_null::eq(const Item *item, bool binary_cmp) const
{ return item->type() == type(); }
-double Item_null::val()
+
+
+double Item_null::val_real()
{
// following assert is redundant, because fixed=1 assigned in constructor
DBUG_ASSERT(fixed == 1);
@@ -1057,6 +2025,11 @@ String *Item_null::val_str(String *str)
return 0;
}
+my_decimal *Item_null::val_decimal(my_decimal *decimal_value)
+{
+ return 0;
+}
+
Item *Item_null::safe_charset_converter(CHARSET_INFO *tocs)
{
@@ -1079,12 +2052,13 @@ default_set_param_func(Item_param *param,
param->set_null();
}
+
Item_param::Item_param(unsigned pos_in_query_arg) :
state(NO_VALUE),
item_result_type(STRING_RESULT),
/* Don't pretend to be a literal unless value for this item is set. */
item_type(PARAM_ITEM),
- param_type(MYSQL_TYPE_STRING),
+ param_type(MYSQL_TYPE_VARCHAR),
pos_in_query(pos_in_query_arg),
set_param_func(default_set_param_func)
{
@@ -1097,11 +2071,11 @@ Item_param::Item_param(unsigned pos_in_query_arg) :
maybe_null= 1;
}
+
void Item_param::set_null()
{
DBUG_ENTER("Item_param::set_null");
/* These are cleared after each execution by reset() method */
- max_length= 0;
null_value= 1;
/*
Because of NULL and string values we need to set max_length for each new
@@ -1139,6 +2113,36 @@ void Item_param::set_double(double d)
/*
+ Set decimal parameter value from string.
+
+ SYNOPSIS
+ set_decimal()
+ str - character string
+ length - string length
+
+ NOTE
+ as we use character strings to send decimal values in
+ binary protocol, we use str2my_decimal to convert it to
+ internal decimal value.
+*/
+
+void Item_param::set_decimal(const char *str, ulong length)
+{
+ char *end;
+ DBUG_ENTER("Item_param::set_decimal");
+
+ end= (char*) str+length;
+ str2my_decimal(E_DEC_FATAL_ERROR, str, &decimal_value, &end);
+ state= DECIMAL_VALUE;
+ decimals= decimal_value.frac;
+ max_length= my_decimal_precision_to_length(decimal_value.precision(),
+ decimals, unsigned_flag);
+ maybe_null= 0;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
Set parameter value from TIME value.
SYNOPSIS
@@ -1167,7 +2171,7 @@ void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg)
{
char buff[MAX_DATE_STRING_REP_LENGTH];
uint length= my_TIME_to_str(&value.time, buff);
- make_truncated_value_warning(current_thd, buff, length, type);
+ make_truncated_value_warning(current_thd, buff, length, type, 0);
set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR);
}
@@ -1191,6 +2195,7 @@ bool Item_param::set_str(const char *str, ulong length)
&dummy_errors))
DBUG_RETURN(TRUE);
state= STRING_VALUE;
+ max_length= length;
maybe_null= 0;
/* max_length and decimals are set after charset conversion */
/* sic: str may be not null-terminated, don't add DBUG_PRINT here */
@@ -1230,7 +2235,7 @@ bool Item_param::set_longdata(const char *str, ulong length)
RETURN
0 OK
- 1 Out of memort
+ 1 Out of memory
*/
bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
@@ -1276,6 +2281,16 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
DBUG_RETURN(1);
break;
}
+ case DECIMAL_RESULT:
+ {
+ const my_decimal *ent_value= (const my_decimal *)entry->value;
+ my_decimal2decimal(ent_value, &decimal_value);
+ state= DECIMAL_VALUE;
+ decimals= ent_value->frac;
+ max_length= my_decimal_precision_to_length(ent_value->precision(),
+ decimals, unsigned_flag);
+ break;
+ }
default:
DBUG_ASSERT(0);
set_null();
@@ -1300,6 +2315,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
void Item_param::reset()
{
+ DBUG_ENTER("Item_param::reset");
/* Shrink string buffer if it's bigger than max possible CHAR column */
if (str_value.alloced_length() > MAX_CHAR_WIDTH)
str_value.free();
@@ -1307,7 +2323,7 @@ void Item_param::reset()
str_value.length(0);
str_value_ptr.length(0);
/*
- We must prevent all charset conversions untill data has been written
+ We must prevent all charset conversions until data has been written
to the binary log.
*/
str_value.set_charset(&my_charset_bin);
@@ -1324,6 +2340,7 @@ void Item_param::reset()
DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_*
methods).
*/
+ DBUG_VOID_RETURN;
}
@@ -1333,9 +2350,11 @@ int Item_param::save_in_field(Field *field, bool no_conversions)
switch (state) {
case INT_VALUE:
- return field->store(value.integer);
+ return field->store(value.integer, unsigned_flag);
case REAL_VALUE:
return field->store(value.real);
+ case DECIMAL_VALUE:
+ return field->store_decimal(&decimal_value);
case TIME_VALUE:
field->store_time(&value.time, value.time.time_type);
return 0;
@@ -1379,21 +2398,27 @@ bool Item_param::get_date(TIME *res, uint fuzzydate)
}
-double Item_param::val()
+double Item_param::val_real()
{
switch (state) {
case REAL_VALUE:
return value.real;
case INT_VALUE:
return (double) value.integer;
+ case DECIMAL_VALUE:
+ {
+ double result;
+ my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result);
+ return result;
+ }
case STRING_VALUE:
case LONG_DATA_VALUE:
- {
- int dummy_err;
- char *end_not_used;
- return my_strntod(str_value.charset(), (char*) str_value.ptr(),
- str_value.length(), &end_not_used, &dummy_err);
- }
+ {
+ int dummy_err;
+ char *end_not_used;
+ return my_strntod(str_value.charset(), (char*) str_value.ptr(),
+ str_value.length(), &end_not_used, &dummy_err);
+ }
case TIME_VALUE:
/*
This works for example when user says SELECT ?+0.0 and supplies
@@ -1416,6 +2441,12 @@ longlong Item_param::val_int()
return (longlong) (value.real + (value.real > 0 ? 0.5 : -0.5));
case INT_VALUE:
return value.integer;
+ case DECIMAL_VALUE:
+ {
+ longlong i;
+ my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &i);
+ return i;
+ }
case STRING_VALUE:
case LONG_DATA_VALUE:
{
@@ -1434,6 +2465,36 @@ longlong Item_param::val_int()
}
+my_decimal *Item_param::val_decimal(my_decimal *dec)
+{
+ switch (state) {
+ case DECIMAL_VALUE:
+ return &decimal_value;
+ case REAL_VALUE:
+ double2my_decimal(E_DEC_FATAL_ERROR, value.real, dec);
+ return dec;
+ case INT_VALUE:
+ int2my_decimal(E_DEC_FATAL_ERROR, value.integer, unsigned_flag, dec);
+ return dec;
+ case STRING_VALUE:
+ case LONG_DATA_VALUE:
+ string2my_decimal(E_DEC_FATAL_ERROR, &str_value, dec);
+ return dec;
+ case TIME_VALUE:
+ {
+ longlong i= (longlong) TIME_to_ulonglong(&value.time);
+ int2my_decimal(E_DEC_FATAL_ERROR, i, 0, dec);
+ return dec;
+ }
+ case NULL_VALUE:
+ return 0;
+ default:
+ DBUG_ASSERT(0);
+ }
+ return 0;
+}
+
+
String *Item_param::val_str(String* str)
{
switch (state) {
@@ -1446,6 +2507,11 @@ String *Item_param::val_str(String* str)
case INT_VALUE:
str->set(value.integer, &my_charset_bin);
return str;
+ case DECIMAL_VALUE:
+ if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
+ 0, 0, 0, str) <= 1)
+ return str;
+ return NULL;
case TIME_VALUE:
{
if (str->reserve(MAX_DATE_STRING_REP_LENGTH))
@@ -1478,6 +2544,11 @@ const String *Item_param::query_val_str(String* str) const
case REAL_VALUE:
str->set(value.real, NOT_FIXED_DEC, &my_charset_bin);
break;
+ case DECIMAL_VALUE:
+ if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
+ 0, 0, 0, str) > 1)
+ return &my_null_string;
+ break;
case TIME_VALUE:
{
char *buf, *ptr;
@@ -1515,11 +2586,11 @@ const String *Item_param::query_val_str(String* str) const
else
{
*ptr++= '\'';
- ptr+= escape_string_for_mysql(str_value.charset(), ptr,
+ ptr+= escape_string_for_mysql(str_value.charset(), ptr, 0,
str_value.ptr(), str_value.length());
*ptr++='\'';
}
- str->length(ptr - buf);
+ str->length((uint32) (ptr - buf));
break;
}
case NULL_VALUE:
@@ -1580,6 +2651,7 @@ bool Item_param::basic_const_item() const
return TRUE;
}
+
Item *
Item_param::new_item()
{
@@ -1592,7 +2664,7 @@ Item_param::new_item()
new Item_uint(name, value.integer, max_length) :
new Item_int(name, value.integer, max_length));
case REAL_VALUE:
- return new Item_real(name, value.real, decimals, max_length);
+ return new Item_float(name, value.real, decimals, max_length);
case STRING_VALUE:
case LONG_DATA_VALUE:
return new Item_string(name, str_value.c_ptr_quick(), str_value.length(),
@@ -1626,7 +2698,7 @@ Item_param::eq(const Item *arg, bool binary_cmp) const
return value.integer == item->val_int() &&
unsigned_flag == item->unsigned_flag;
case REAL_VALUE:
- return value.real == item->val();
+ return value.real == item->val_real();
case STRING_VALUE:
case LONG_DATA_VALUE:
if (binary_cmp)
@@ -1640,6 +2712,26 @@ Item_param::eq(const Item *arg, bool binary_cmp) const
/* End of Item_param related */
+void Item_param::print(String *str)
+{
+ if (state == NO_VALUE)
+ {
+ str->append('?');
+ }
+ else
+ {
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buffer, sizeof(buffer), &my_charset_bin);
+ const String *res;
+ res= query_val_str(&tmp);
+ str->append(*res);
+ }
+}
+
+
+/****************************************************************************
+ Item_copy_string
+****************************************************************************/
void Item_copy_string::copy()
{
@@ -1659,6 +2751,17 @@ String *Item_copy_string::val_str(String *str)
}
+my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value)
+{
+ // Item_copy_string is used without fix_fields call
+ if (null_value)
+ return 0;
+ string2my_decimal(E_DEC_FATAL_ERROR, &str_value, decimal_value);
+ return (decimal_value);
+}
+
+
+
int Item_copy_string::save_in_field(Field *field, bool no_conversions)
{
if (null_value)
@@ -1673,18 +2776,16 @@ int Item_copy_string::save_in_field(Field *field, bool no_conversions)
*/
/* ARGSUSED */
-bool Item::fix_fields(THD *thd,
- struct st_table_list *list,
- Item ** ref)
+bool Item::fix_fields(THD *thd, Item ** ref)
{
// We do not check fields which are fixed during construction
DBUG_ASSERT(fixed == 0 || basic_const_item());
fixed= 1;
- return 0;
+ return FALSE;
}
-double Item_ref_null_helper::val()
+double Item_ref_null_helper::val_real()
{
DBUG_ASSERT(fixed == 1);
double tmp= (*ref)->val_result();
@@ -1702,6 +2803,24 @@ longlong Item_ref_null_helper::val_int()
}
+my_decimal *Item_ref_null_helper::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed == 1);
+ my_decimal *val= (*ref)->val_decimal_result(decimal_value);
+ owner->was_null|= null_value= (*ref)->null_value;
+ return val;
+}
+
+
+bool Item_ref_null_helper::val_bool()
+{
+ DBUG_ASSERT(fixed == 1);
+ bool val= (*ref)->val_bool_result();
+ owner->was_null|= null_value= (*ref)->null_value;
+ return val;
+}
+
+
String* Item_ref_null_helper::val_str(String* s)
{
DBUG_ASSERT(fixed == 1);
@@ -1718,29 +2837,37 @@ bool Item_ref_null_helper::get_date(TIME *ltime, uint fuzzydate)
/*
- Mark item and SELECT_LEXs as dependent if it is not outer resolving
+ Mark item and SELECT_LEXs as dependent if item was resolved in outer SELECT
SYNOPSIS
mark_as_dependent()
thd - thread handler
last - select from which current item depend
current - current select
- item - item which should be marked
+ resolved_item - item which was resolved in outer SELECT(for warning)
+ mark_item - item which should be marked (can be differ in case of
+ substitution)
*/
static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
- Item_ident *item)
-{
- // store pointer on SELECT_LEX from which item is dependent
- item->depended_from= last;
+ Item_ident *resolved_item,
+ Item_ident *mark_item)
+{
+ const char *db_name= (resolved_item->db_name ?
+ resolved_item->db_name : "");
+ const char *table_name= (resolved_item->table_name ?
+ resolved_item->table_name : "");
+ /* store pointer on SELECT_LEX from which item is dependent */
+ if (mark_item)
+ mark_item->depended_from= last;
current->mark_as_dependent(last);
if (thd->lex->describe & DESCRIBE_EXTENDED)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_WARN_FIELD_RESOLVED),
- (item->db_name?item->db_name:""), (item->db_name?".":""),
- (item->table_name?item->table_name:""), (item->table_name?".":""),
- item->field_name,
+ db_name, (db_name[0] ? "." : ""),
+ table_name, (table_name [0] ? "." : ""),
+ resolved_item->field_name,
current->select_number, last->select_number);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_WARN_FIELD_RESOLVED, warn_buff);
@@ -1748,177 +2875,546 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
}
-bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+/*
+ Mark range of selects and resolved identifier (field/reference) item as
+ dependent
+
+ SYNOPSIS
+ mark_select_range_as_dependent()
+ thd - thread handler
+ last_select - select where resolved_item was resolved
+ current_sel - current select (select where resolved_item was placed)
+ found_field - field which was found during resolving
+ found_item - Item which was found during resolving (if resolved
+ identifier belongs to VIEW)
+ resolved_item - Identifier which was resolved
+
+ NOTE:
+ We have to mark all items between current_sel (including) and
+ last_select (excluding) as dependend (select before last_select should
+ be marked with actual table mask used by resolved item, all other with
+ OUTER_REF_TABLE_BIT) and also write dependence information to Item of
+ resolved identifier.
+*/
+
+void mark_select_range_as_dependent(THD *thd,
+ SELECT_LEX *last_select,
+ SELECT_LEX *current_sel,
+ Field *found_field, Item *found_item,
+ Item_ident *resolved_item)
+{
+ /*
+ Go from current SELECT to SELECT where field was resolved (it
+ have to be reachable from current SELECT, because it was already
+ done once when we resolved this field and cached result of
+ resolving)
+ */
+ SELECT_LEX *previous_select= current_sel;
+ for (; previous_select->outer_select() != last_select;
+ previous_select= previous_select->outer_select())
+ {
+ Item_subselect *prev_subselect_item=
+ previous_select->master_unit()->item;
+ prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
+ prev_subselect_item->const_item_cache= 0;
+ }
+ {
+ Item_subselect *prev_subselect_item=
+ previous_select->master_unit()->item;
+ Item_ident *dependent= resolved_item;
+ if (found_field == view_ref_found)
+ {
+ Item::Type type= found_item->type();
+ prev_subselect_item->used_tables_cache|=
+ found_item->used_tables();
+ dependent= ((type == Item::REF_ITEM || type == Item::FIELD_ITEM) ?
+ (Item_ident*) found_item :
+ 0);
+ }
+ else
+ prev_subselect_item->used_tables_cache|=
+ found_field->table->map;
+ prev_subselect_item->const_item_cache= 0;
+ mark_as_dependent(thd, last_select, current_sel, resolved_item,
+ dependent);
+ }
+}
+
+
+/*
+ Search a GROUP BY clause for a field with a certain name.
+
+ SYNOPSIS
+ find_field_in_group_list()
+ find_item the item being searched for
+ group_list GROUP BY clause
+
+ DESCRIPTION
+ Search the GROUP BY list for a column named as find_item. When searching
+ preference is given to columns that are qualified with the same table (and
+ database) name as the one being searched for.
+
+ RETURN
+ - the found item on success
+ - NULL if find_item is not in group_list
+*/
+
+static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
+{
+ const char *db_name;
+ const char *table_name;
+ const char *field_name;
+ ORDER *found_group= NULL;
+ int found_match_degree= 0;
+ Item_field *cur_field;
+ int cur_match_degree= 0;
+
+ if (find_item->type() == Item::FIELD_ITEM ||
+ find_item->type() == Item::REF_ITEM)
+ {
+ db_name= ((Item_ident*) find_item)->db_name;
+ table_name= ((Item_ident*) find_item)->table_name;
+ field_name= ((Item_ident*) find_item)->field_name;
+ }
+ else
+ return NULL;
+
+ DBUG_ASSERT(field_name != 0);
+
+ for (ORDER *cur_group= group_list ; cur_group ; cur_group= cur_group->next)
+ {
+ if ((*(cur_group->item))->type() == Item::FIELD_ITEM)
+ {
+ cur_field= (Item_field*) *cur_group->item;
+ cur_match_degree= 0;
+
+ DBUG_ASSERT(cur_field->field_name != 0);
+
+ if (!my_strcasecmp(system_charset_info,
+ cur_field->field_name, field_name))
+ ++cur_match_degree;
+ else
+ continue;
+
+ if (cur_field->table_name && table_name)
+ {
+ /* If field_name is qualified by a table name. */
+ if (strcmp(cur_field->table_name, table_name))
+ /* Same field names, different tables. */
+ return NULL;
+
+ ++cur_match_degree;
+ if (cur_field->db_name && db_name)
+ {
+ /* If field_name is also qualified by a database name. */
+ if (strcmp(cur_field->db_name, db_name))
+ /* Same field names, different databases. */
+ return NULL;
+ ++cur_match_degree;
+ }
+ }
+
+ if (cur_match_degree > found_match_degree)
+ {
+ found_match_degree= cur_match_degree;
+ found_group= cur_group;
+ }
+ else if (found_group && (cur_match_degree == found_match_degree) &&
+ ! (*(found_group->item))->eq(cur_field, 0))
+ {
+ /*
+ If the current resolve candidate matches equally well as the current
+ best match, they must reference the same column, otherwise the field
+ is ambiguous.
+ */
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find_item->full_name(), current_thd->where);
+ return NULL;
+ }
+ }
+ }
+
+ if (found_group)
+ return found_group->item;
+ else
+ return NULL;
+}
+
+
+/*
+ Resolve a column reference in a sub-select.
+
+ SYNOPSIS
+ resolve_ref_in_select_and_group()
+ thd current thread
+ ref column reference being resolved
+ select the sub-select that ref is resolved against
+
+ DESCRIPTION
+ Resolve a column reference (usually inside a HAVING clause) against the
+ SELECT and GROUP BY clauses of the query described by 'select'. The name
+ resolution algorithm searches both the SELECT and GROUP BY clauses, and in
+ case of a name conflict prefers GROUP BY column names over SELECT names. If
+ both clauses contain different fields with the same names, a warning is
+ issued that name of 'ref' is ambiguous. We extend ANSI SQL in that when no
+ GROUP BY column is found, then a HAVING name is resolved as a possibly
+ derived SELECT column.
+
+ NOTES
+ The resolution procedure is:
+ - Search for a column or derived column named col_ref_i [in table T_j]
+ in the SELECT clause of Q.
+ - Search for a column named col_ref_i [in table T_j]
+ in the GROUP BY clause of Q.
+ - If found different columns with the same name in GROUP BY and SELECT
+ - issue a warning and return the GROUP BY column,
+ - otherwise return the found SELECT column.
+
+
+ RETURN
+ NULL - there was an error, and the error was already reported
+ not_found_item - the item was not resolved, no error was reported
+ resolved item - if the item was resolved
+*/
+
+static Item**
+resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
+{
+ Item **group_by_ref= NULL;
+ Item **select_ref= NULL;
+ ORDER *group_list= (ORDER*) select->group_list.first;
+ bool ambiguous_fields= FALSE;
+ uint counter;
+ bool not_used;
+
+ /*
+ Search for a column or derived column named as 'ref' in the SELECT
+ clause of the current select.
+ */
+ if (!(select_ref= find_item_in_list(ref, *(select->get_item_list()),
+ &counter, REPORT_EXCEPT_NOT_FOUND,
+ &not_used)))
+ return NULL; /* Some error occurred. */
+
+ /* If this is a non-aggregated field inside HAVING, search in GROUP BY. */
+ if (select->having_fix_field && !ref->with_sum_func && group_list)
+ {
+ group_by_ref= find_field_in_group_list(ref, group_list);
+
+ /* Check if the fields found in SELECT and GROUP BY are the same field. */
+ if (group_by_ref && (select_ref != not_found_item) &&
+ !((*group_by_ref)->eq(*select_ref, 0)))
+ {
+ ambiguous_fields= TRUE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
+ ER(ER_NON_UNIQ_ERROR), ref->full_name(),
+ current_thd->where);
+
+ }
+ }
+
+ if (select_ref != not_found_item || group_by_ref)
+ {
+ if (select_ref != not_found_item && !ambiguous_fields)
+ {
+ DBUG_ASSERT(*select_ref != 0);
+ if (!select->ref_pointer_array[counter])
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0),
+ ref->name, "forward reference in item list");
+ return NULL;
+ }
+ DBUG_ASSERT((*select_ref)->fixed);
+ return (select->ref_pointer_array + counter);
+ }
+ if (group_by_ref)
+ return group_by_ref;
+ DBUG_ASSERT(FALSE);
+ return NULL; /* So there is no compiler warning. */
+ }
+
+ return (Item**) not_found_item;
+}
+
+
+/*
+ Resolve the name of a column reference.
+
+ SYNOPSIS
+ Item_field::fix_fields()
+ thd [in] current thread
+ reference [in/out] view column if this item was resolved to a view column
+
+ DESCRIPTION
+ The method resolves the column reference represented by 'this' as a column
+ present in one of: FROM clause, SELECT clause, GROUP BY clause of a query
+ Q, or in outer queries that contain Q.
+
+ NOTES
+ The name resolution algorithm used is (where [T_j] is an optional table
+ name that qualifies the column name):
+
+ resolve_column_reference([T_j].col_ref_i)
+ {
+ search for a column or derived column named col_ref_i
+ [in table T_j] in the FROM clause of Q;
+
+ if such a column is NOT found AND // Lookup in outer queries.
+ there are outer queries
+ {
+ for each outer query Q_k beginning from the inner-most one
+ {
+ if - Q_k is not a group query AND
+ - Q_k is not inside an aggregate function
+ OR
+ - Q_(k-1) is not in a HAVING or SELECT clause of Q_k
+ {
+ search for a column or derived column named col_ref_i
+ [in table T_j] in the FROM clause of Q_k;
+ }
+
+ if such a column is not found
+ Search for a column or derived column named col_ref_i
+ [in table T_j] in the SELECT and GROUP clauses of Q_k.
+ }
+ }
+ }
+
+ Notice that compared to Item_ref::fix_fields, here we first search the FROM
+ clause, and then we search the SELECT and GROUP BY clauses.
+
+ RETURN
+ TRUE if error
+ FALSE on success
+*/
+
+bool Item_field::fix_fields(THD *thd, Item **reference)
{
enum_parsing_place place= NO_MATTER;
DBUG_ASSERT(fixed == 0);
if (!field) // If field is not checked
{
- TABLE_LIST *where= 0;
- bool upward_lookup= 0;
- Field *tmp= (Field *)not_found_field;
- if ((tmp= find_field_in_tables(thd, this, tables, &where, 0)) ==
+ bool upward_lookup= FALSE;
+ Field *from_field= (Field *)not_found_field;
+ /*
+ In case of view, find_field_in_tables() write pointer to view field
+ expression to 'reference', i.e. it substitute that expression instead
+ of this Item_field
+ */
+ if ((from_field= find_field_in_tables(thd, this,
+ context->first_name_resolution_table,
+ context->last_name_resolution_table,
+ reference,
+ IGNORE_EXCEPT_NON_UNIQUE,
+ !any_privileges &&
+ context->check_privileges,
+ TRUE)) ==
not_found_field)
{
/*
- We can't find table field in table list of current select,
- consequently we have to find it in outer subselect(s).
- We can't join lists of outer & current select, because of scope
- of view rules. For example if both tables (outer & current) have
- field 'field' it is not mistake to refer to this field without
- mention of table name, but if we join tables in one list it will
- cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
+ If there are outer contexts (outer selects, but current select is
+ not derived table or view) try to resolve this reference in the
+ outer contexts.
+
+ We treat each subselect as a separate namespace, so that different
+ subselects may contain columns with the same names. The subselects
+ are searched starting from the innermost.
*/
- SELECT_LEX *last= 0;
-#ifdef EMBEDDED_LIBRARY
- thd->net.last_errno= 0;
-#endif
- TABLE_LIST *table_list;
- Item **refer= (Item **)not_found_item;
- uint counter;
- bool not_used;
- // Prevent using outer fields in subselects, that is not supported now
- SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select;
- if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE)
+ Name_resolution_context *last_checked_context= context;
+ Item **ref= (Item **) not_found_item;
+ Name_resolution_context *outer_context= context->outer_context;
+ for (;
+ outer_context;
+ outer_context= outer_context->outer_context)
{
- SELECT_LEX_UNIT *prev_unit= cursel->master_unit();
- for (SELECT_LEX *sl= prev_unit->outer_select();
- sl;
- sl= (prev_unit= sl->master_unit())->outer_select())
- {
- upward_lookup= 1;
- table_list= (last= sl)->get_table_list();
- if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
- {
- /*
- it is primary INSERT st_select_lex => skip first table
- resolving
- */
- table_list= table_list->next;
- }
+ SELECT_LEX *select= outer_context->select_lex;
+ Item_subselect *prev_subselect_item=
+ last_checked_context->select_lex->master_unit()->item;
+ last_checked_context= outer_context;
+ upward_lookup= TRUE;
- Item_subselect *prev_subselect_item= prev_unit->item;
- place= prev_subselect_item->parsing_place;
- /*
- check table fields only if subquery used somewhere out of HAVING
- or outer SELECT do not use groupping (i.e. tables are
- accessable)
- */
- if ((place != IN_HAVING ||
- (sl->with_sum_func == 0 && sl->group_list.elements == 0)) &&
- (tmp= find_field_in_tables(thd, this,
- table_list, &where,
- 0)) != not_found_field)
+ place= prev_subselect_item->parsing_place;
+ /*
+ Check table fields only if the subquery is used somewhere out of
+ HAVING, or the outer SELECT does not use grouping (i.e. tables are
+ accessible).
+
+ In case of a view, find_field_in_tables() writes the pointer to
+ the found view field into '*reference', in other words, it
+ substitutes this Item_field with the found expression.
+ */
+ if ((place != IN_HAVING ||
+ (!select->with_sum_func &&
+ select->group_list.elements == 0)) &&
+ (from_field= find_field_in_tables(thd, this,
+ outer_context->
+ first_name_resolution_table,
+ outer_context->
+ last_name_resolution_table,
+ reference,
+ IGNORE_EXCEPT_NON_UNIQUE,
+ outer_context->
+ check_privileges,
+ TRUE)) !=
+ not_found_field)
+ {
+ if (from_field)
{
- if (!tmp)
- return -1;
- prev_subselect_item->used_tables_cache|= tmp->table->map;
- prev_subselect_item->const_item_cache= 0;
+ if (from_field != view_ref_found)
+ {
+ prev_subselect_item->used_tables_cache|= from_field->table->map;
+ prev_subselect_item->const_item_cache= 0;
+ }
+ else
+ {
+ Item::Type type= (*reference)->type();
+ prev_subselect_item->used_tables_cache|=
+ (*reference)->used_tables();
+ prev_subselect_item->const_item_cache&=
+ (*reference)->const_item();
+ mark_as_dependent(thd, last_checked_context->select_lex,
+ context->select_lex, this,
+ ((type == REF_ITEM || type == FIELD_ITEM) ?
+ (Item_ident*) (*reference) :
+ 0));
+ /*
+ A reference to a view field had been found and we
+ substituted it instead of this Item (find_field_in_tables
+ does it by assigning the new value to *reference), so now
+ we can return from this function.
+ */
+ return FALSE;
+ }
+ }
+ break;
+ }
+
+ /* Search in SELECT and GROUP lists of the outer select. */
+ if (outer_context->resolve_in_select_list)
+ {
+ if (!(ref= resolve_ref_in_select_and_group(thd, this, select)))
+ goto error; /* Some error occurred (e.g. ambiguous names). */
+ if (ref != not_found_item)
+ {
+ DBUG_ASSERT(*ref && (*ref)->fixed);
+ prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
+ prev_subselect_item->const_item_cache&= (*ref)->const_item();
break;
}
- if (sl->resolve_mode == SELECT_LEX::SELECT_MODE &&
- (refer= find_item_in_list(this, sl->item_list, &counter,
- REPORT_EXCEPT_NOT_FOUND,
- &not_used)) !=
- (Item **) not_found_item)
- {
- if (refer && (*refer)->fixed) // Avoid crash in case of error
- {
- prev_subselect_item->used_tables_cache|= (*refer)->used_tables();
- prev_subselect_item->const_item_cache&= (*refer)->const_item();
- }
- break;
- }
-
- // Reference is not found => depend from outer (or just error)
- prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
- prev_subselect_item->const_item_cache= 0;
-
- if (sl->master_unit()->first_select()->linkage ==
- DERIVED_TABLE_TYPE)
- break; // do not look over derived table
- }
+ }
+
+ /*
+ Reference is not found in this select => this subquery depend on
+ outer select (or we just trying to find wrong identifier, in this
+ case it does not matter which used tables bits we set)
+ */
+ prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
+ prev_subselect_item->const_item_cache= 0;
}
- if (!tmp)
- return -1;
- else if (!refer)
- return 1;
- else if (tmp == not_found_field && refer == (Item **)not_found_item)
+
+ DBUG_ASSERT(ref != 0);
+ if (!from_field)
+ goto error;
+ if (ref == not_found_item && from_field == not_found_field)
{
if (upward_lookup)
{
- // We can't say exactly what absend table or field
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
- full_name(), thd->where);
+ // We can't say exactly what absent table or field
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), thd->where);
}
else
{
- // Call to report error
- find_field_in_tables(thd, this, tables, &where, 1);
+ /* Call find_field_in_tables only to report the error */
+ find_field_in_tables(thd, this,
+ context->first_name_resolution_table,
+ context->last_name_resolution_table,
+ reference, REPORT_ALL_ERRORS,
+ !any_privileges &&
+ context->check_privileges, TRUE);
}
- return -1;
+ goto error;
}
- else if (refer != (Item **)not_found_item)
+ else if (ref != not_found_item)
{
- if (!last->ref_pointer_array[counter])
- {
- my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
- "forward reference in item list");
- return -1;
- }
- DBUG_ASSERT((*refer)->fixed);
+ Item *save;
+ Item_ref *rf;
+
+ /* Should have been checked in resolve_ref_in_select_and_group(). */
+ DBUG_ASSERT(*ref && (*ref)->fixed);
/*
Here, a subset of actions performed by Item_ref::set_properties
is not enough. So we pass ptr to NULL into Item_[direct]_ref
constructor, so no initialization is performed, and call
fix_fields() below.
*/
- Item *save= last->ref_pointer_array[counter];
- last->ref_pointer_array[counter]= NULL;
- Item_ref *rf= (place == IN_HAVING ?
- new Item_ref(last->ref_pointer_array + counter,
- (char *)table_name,
- (char *)field_name) :
- new Item_direct_ref(last->ref_pointer_array + counter,
- (char *)table_name,
- (char *)field_name));
+ save= *ref;
+ *ref= NULL; // Don't call set_properties()
+ rf= (place == IN_HAVING ?
+ new Item_ref(context, ref, (char*) table_name,
+ (char*) field_name) :
+ new Item_direct_ref(context, ref, (char*) table_name,
+ (char*) field_name));
+ *ref= save;
if (!rf)
- return 1;
- thd->change_item_tree(ref, rf);
- last->ref_pointer_array[counter]= save;
+ goto error;
+ thd->change_item_tree(reference, rf);
/*
rf is Item_ref => never substitute other items (in this case)
during fix_fields() => we can use rf after fix_fields()
*/
- if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1))
- return 1;
-
- mark_as_dependent(thd, last, cursel, rf);
- return 0;
+ DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
+ if (rf->fix_fields(thd, reference) || rf->check_cols(1))
+ goto error;
+
+ mark_as_dependent(thd, last_checked_context->select_lex,
+ context->select_lex, this,
+ rf);
+ return FALSE;
}
else
{
- mark_as_dependent(thd, last, cursel, this);
- if (last->having_fix_field)
+ mark_as_dependent(thd, last_checked_context->select_lex,
+ context->select_lex,
+ this, this);
+ if (last_checked_context->select_lex->having_fix_field)
{
Item_ref *rf;
- rf= new Item_ref((where->db[0] ? where->db : 0),
- (char*) where->alias, (char*) field_name);
+ rf= new Item_ref(context,
+ (cached_table->db[0] ? cached_table->db : 0),
+ (char*) cached_table->alias, (char*) field_name);
if (!rf)
- return 1;
- thd->change_item_tree(ref, rf);
+ goto error;
+ thd->change_item_tree(reference, rf);
/*
rf is Item_ref => never substitute other items (in this case)
during fix_fields() => we can use rf after fix_fields()
*/
- return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
+ DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
+ if (rf->fix_fields(thd, reference) || rf->check_cols(1))
+ goto error;
+ return FALSE;
}
}
}
- else if (!tmp)
- return -1;
+ else if (!from_field)
+ goto error;
+
+ /*
+ if it is not expression from merged VIEW we will set this field.
+
+ We can leave expression substituted from view for next PS/SP rexecution
+ (i.e. do not register this substitution for reverting on cleupup()
+ (register_item_tree_changing())), because this subtree will be
+ fix_field'ed during setup_tables()->setup_ancestor() (i.e. before
+ all other expressions of query, and references on tables which do
+ not present in query will not make problems.
+
+ Also we suppose that view can't be changed during PS/SP life.
+ */
+ if (from_field == view_ref_found)
+ return FALSE;
- set_field(tmp);
+ set_field(from_field);
}
else if (thd->set_query_id && field->query_id != thd->query_id)
{
@@ -1927,24 +3423,191 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
field->query_id=thd->query_id;
table->used_fields++;
table->used_keys.intersect(field->part_of_key);
- fixed= 1;
}
- return 0;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (any_privileges)
+ {
+ char *db, *tab;
+ if (cached_table->view)
+ {
+ db= cached_table->view_db.str;
+ tab= cached_table->view_name.str;
+ }
+ else
+ {
+ db= cached_table->db;
+ tab= cached_table->table_name;
+ }
+ if (!(have_privileges= (get_column_grant(thd, &field->table->grant,
+ db, tab, field_name) &
+ VIEW_ANY_ACL)))
+ {
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ "ANY", thd->priv_user, thd->host_or_ip,
+ field_name, tab);
+ goto error;
+ }
+ }
+#endif
+ fixed= 1;
+ return FALSE;
+
+error:
+ context->process_error(thd);
+ return TRUE;
}
+
+Item *Item_field::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ no_const_subst= 1;
+ return Item::safe_charset_converter(tocs);
+}
+
+
void Item_field::cleanup()
{
DBUG_ENTER("Item_field::cleanup");
Item_ident::cleanup();
/*
Even if this object was created by direct link to field in setup_wild()
- it will be linked correctly next tyme by name of field and table alias.
+ it will be linked correctly next time by name of field and table alias.
I.e. we can drop 'field'.
*/
field= result_field= 0;
DBUG_VOID_RETURN;
}
+/*
+ Find a field among specified multiple equalities
+
+ SYNOPSIS
+ find_item_equal()
+ cond_equal reference to list of multiple equalities where
+ the field (this object) is to be looked for
+
+ DESCRIPTION
+ The function first searches the field among multiple equalities
+ of the current level (in the cond_equal->current_level list).
+ If it fails, it continues searching in upper levels accessed
+ through a pointer cond_equal->upper_levels.
+ The search terminates as soon as a multiple equality containing
+ the field is found.
+
+ RETURN VALUES
+ First Item_equal containing the field, if success
+ 0, otherwise
+*/
+Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
+{
+ Item_equal *item= 0;
+ while (cond_equal)
+ {
+ List_iterator_fast<Item_equal> li(cond_equal->current_level);
+ while ((item= li++))
+ {
+ if (item->contains(field))
+ return item;
+ }
+ /*
+ The field is not found in any of the multiple equalities
+ of the current level. Look for it in upper levels
+ */
+ cond_equal= cond_equal->upper_levels;
+ }
+ return 0;
+}
+
+
+/*
+ Set a pointer to the multiple equality the field reference belongs to
+ (if any)
+
+ SYNOPSIS
+ equal_fields_propagator()
+ arg - reference to list of multiple equalities where
+ the field (this object) is to be looked for
+
+ DESCRIPTION
+ The function looks for a multiple equality containing the field item
+ among those referenced by arg.
+ In the case such equality exists the function does the following.
+ If the found multiple equality contains a constant, then the field
+ reference is substituted for this constant, otherwise it sets a pointer
+ to the multiple equality in the field item.
+
+ NOTES
+ This function is supposed to be called as a callback parameter in calls
+ of the transform method.
+
+ RETURN VALUES
+ pointer to the replacing constant item, if the field item was substituted
+ pointer to the field item, otherwise.
+*/
+
+Item *Item_field::equal_fields_propagator(byte *arg)
+{
+ if (no_const_subst)
+ return this;
+ item_equal= find_item_equal((COND_EQUAL *) arg);
+ Item *item= 0;
+ if (item_equal)
+ item= item_equal->get_const();
+ if (!item)
+ item= this;
+ return item;
+}
+
+
+/*
+ Mark the item to not be part of substitution if it's not a binary item
+ See comments in Arg_comparator::set_compare_func() for details
+*/
+
+Item *Item_field::set_no_const_sub(byte *arg)
+{
+ if (field->charset() != &my_charset_bin)
+ no_const_subst=1;
+ return this;
+}
+
+
+/*
+ Replace an Item_field for an equal Item_field that evaluated earlier
+ (if any)
+
+ SYNOPSIS
+ replace_equal_field_()
+ arg - a dummy parameter, is not used here
+
+ DESCRIPTION
+ The function returns a pointer to an item that is taken from
+ the very beginning of the item_equal list which the Item_field
+ object refers to (belongs to).
+ If the Item_field object does not refer any Item_equal object
+ 'this' is returned
+
+ NOTES
+ This function is supposed to be called as a callback parameter in calls
+ of the thransformer method.
+
+ RETURN VALUES
+ pointer to a replacement Item_field if there is a better equal item;
+ this - otherwise.
+*/
+
+Item *Item_field::replace_equal_field(byte *arg)
+{
+ if (item_equal)
+ {
+ Item_field *subst= item_equal->get_first();
+ if (!field->eq(subst->field))
+ return subst;
+ }
+ return this;
+}
+
+
void Item::init_make_field(Send_field *tmp_field,
enum enum_field_types field_type)
{
@@ -1973,18 +3636,69 @@ void Item::make_field(Send_field *tmp_field)
void Item_empty_string::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_VAR_STRING);
+ enum_field_types type= FIELD_TYPE_VAR_STRING;
+ if (max_length >= 16777216)
+ type= FIELD_TYPE_LONG_BLOB;
+ else if (max_length >= 65536)
+ type= FIELD_TYPE_MEDIUM_BLOB;
+ init_make_field(tmp_field, type);
}
enum_field_types Item::field_type() const
{
- return ((result_type() == STRING_RESULT) ? FIELD_TYPE_VAR_STRING :
- (result_type() == INT_RESULT) ? FIELD_TYPE_LONGLONG :
- FIELD_TYPE_DOUBLE);
+ switch (result_type()) {
+ case STRING_RESULT: return MYSQL_TYPE_VARCHAR;
+ case INT_RESULT: return FIELD_TYPE_LONGLONG;
+ case DECIMAL_RESULT: return FIELD_TYPE_NEWDECIMAL;
+ case REAL_RESULT: return FIELD_TYPE_DOUBLE;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ return MYSQL_TYPE_VARCHAR;
+ }
}
+/*
+ Create a field to hold a string value from an item
+
+ SYNOPSIS
+ make_string_field()
+ table Table for which the field is created
+
+ IMPLEMENTATION
+ If max_length > CONVERT_IF_BIGGER_TO_BLOB create a blob
+ If max_length > 0 create a varchar
+ If max_length == 0 create a CHAR(0)
+*/
+
+
+Field *Item::make_string_field(TABLE *table)
+{
+ DBUG_ASSERT(collation.collation);
+ if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB)
+ return new Field_blob(max_length, maybe_null, name, table,
+ collation.collation);
+ if (max_length > 0)
+ return new Field_varstring(max_length, maybe_null, name, table,
+ collation.collation);
+ return new Field_string(max_length, maybe_null, name, table,
+ collation.collation);
+}
+
+
+/*
+ Create a field based on field_type of argument
+
+ For now, this is only used to create a field for
+ IFNULL(x,something)
+
+ RETURN
+ 0 error
+ # Created field
+*/
+
Field *Item::tmp_table_field_from_field_type(TABLE *table)
{
/*
@@ -1994,8 +3708,10 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
switch (field_type()) {
case MYSQL_TYPE_DECIMAL:
- return new Field_decimal((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, decimals, 0, unsigned_flag);
+ case MYSQL_TYPE_NEWDECIMAL:
+ return new Field_new_decimal((char*) 0, max_length, null_ptr, 0,
+ Field::NONE, name, table, decimals, 0,
+ unsigned_flag);
case MYSQL_TYPE_TINY:
return new Field_tiny((char*) 0, max_length, null_ptr, 0, Field::NONE,
name, table, 0, unsigned_flag);
@@ -2033,35 +3749,28 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
case MYSQL_TYPE_YEAR:
return new Field_year((char*) 0, max_length, null_ptr, 0, Field::NONE,
name, table);
+ case MYSQL_TYPE_BIT:
+ return new Field_bit_as_char(NULL, max_length, null_ptr, 0, NULL, 0,
+ Field::NONE, name, table);
default:
- /* This case should never be choosen */
+ /* This case should never be chosen */
DBUG_ASSERT(0);
/* If something goes awfully wrong, it's better to get a string than die */
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
- case MYSQL_TYPE_VAR_STRING:
- DBUG_ASSERT(collation.collation);
- if (max_length/collation.collation->mbmaxlen > 255)
- break; // If blob
- return new Field_varstring(max_length, maybe_null, name, table,
- collation.collation);
case MYSQL_TYPE_STRING:
- DBUG_ASSERT(collation.collation);
- if (max_length/collation.collation->mbmaxlen > 255) // If blob
- break;
- return new Field_string(max_length, maybe_null, name, table,
- collation.collation);
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_VARCHAR:
+ return make_string_field(table);
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
+ return new Field_blob(max_length, maybe_null, name, table,
+ collation.collation);
break; // Blob handled outside of case
}
-
- /* blob is special as it's generated for both blobs and long strings */
- return new Field_blob(max_length, maybe_null, name, table,
- collation.collation);
}
@@ -2069,7 +3778,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
void Item_field::make_field(Send_field *tmp_field)
{
field->make_field(tmp_field);
- DBUG_ASSERT(tmp_field->table_name);
+ DBUG_ASSERT(tmp_field->table_name != 0);
if (name)
tmp_field->col_name=name; // Use user supplied name
}
@@ -2141,7 +3850,7 @@ int Item_null::save_in_field(Field *field, bool no_conversions)
field Field where we want to store NULL
RETURN VALUES
- 0 ok
+ 0 OK
1 Field doesn't support NULL values
*/
@@ -2174,19 +3883,28 @@ int Item::save_in_field(Field *field, bool no_conversions)
}
else if (result_type() == REAL_RESULT)
{
- double nr=val();
+ double nr= val_real();
if (null_value)
return set_field_to_null(field);
field->set_notnull();
error=field->store(nr);
}
+ else if (result_type() == DECIMAL_RESULT)
+ {
+ my_decimal decimal_value;
+ my_decimal *value= val_decimal(&decimal_value);
+ if (null_value)
+ return set_field_to_null(field);
+ field->set_notnull();
+ error=field->store_decimal(value);
+ }
else
{
longlong nr=val_int();
if (null_value)
return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull();
- error=field->store(nr);
+ error=field->store(nr, unsigned_flag);
}
return error;
}
@@ -2202,12 +3920,10 @@ int Item_string::save_in_field(Field *field, bool no_conversions)
return field->store(result->ptr(),result->length(),collation.collation);
}
+
int Item_uint::save_in_field(Field *field, bool no_conversions)
{
- /*
- TODO: To be fixed when wen have a
- field->store(longlong, unsigned_flag) method
- */
+ /* Item_int::save_in_field handles both signed and unsigned. */
return Item_int::save_in_field(field, no_conversions);
}
@@ -2218,7 +3934,14 @@ int Item_int::save_in_field(Field *field, bool no_conversions)
if (null_value)
return set_field_to_null(field);
field->set_notnull();
- return field->store(nr);
+ return field->store(nr, unsigned_flag);
+}
+
+
+int Item_decimal::save_in_field(Field *field, bool no_conversions)
+{
+ field->set_notnull();
+ return field->store_decimal(&decimal_value);
}
@@ -2253,12 +3976,64 @@ Item *Item_int_with_ref::new_item()
Item_num *Item_uint::neg()
{
- return new Item_real(name, - ((double) value), 0, max_length);
+ Item_decimal *item= new Item_decimal(value, 1);
+ return item->neg();
+}
+
+
+static uint nr_of_decimals(const char *str, const char *end)
+{
+ const char *decimal_point;
+
+ /* Find position for '.' */
+ for (;;)
+ {
+ if (str == end)
+ return 0;
+ if (*str == 'e' || *str == 'E')
+ return NOT_FIXED_DEC;
+ if (*str++ == '.')
+ break;
+ }
+ decimal_point= str;
+ for (; my_isdigit(system_charset_info, *str) ; str++)
+ ;
+ if (*str == 'e' || *str == 'E')
+ return NOT_FIXED_DEC;
+ return (uint) (str - decimal_point);
+}
+
+
+/*
+ This function is only called during parsing. We will signal an error if
+ value is not a true double value (overflow)
+*/
+
+Item_float::Item_float(const char *str_arg, uint length)
+{
+ int error;
+ char *end_not_used;
+ value= my_strntod(&my_charset_bin, (char*) str_arg, length, &end_not_used,
+ &error);
+ if (error)
+ {
+ /*
+ Note that we depend on that str_arg is null terminated, which is true
+ when we are in the parser
+ */
+ DBUG_ASSERT(str_arg[length] == 0);
+ my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", (char*) str_arg);
+ }
+ presentation= name=(char*) str_arg;
+ decimals=(uint8) nr_of_decimals(str_arg, str_arg+length);
+ max_length=length;
+ fixed= 1;
}
-int Item_real::save_in_field(Field *field, bool no_conversions)
+
+int Item_float::save_in_field(Field *field, bool no_conversions)
{
- double nr=val();
+ double nr= val_real();
if (null_value)
return set_field_to_null(field);
field->set_notnull();
@@ -2266,7 +4041,27 @@ int Item_real::save_in_field(Field *field, bool no_conversions)
}
-bool Item_real::eq(const Item *arg, bool binary_cmp) const
+void Item_float::print(String *str)
+{
+ if (presentation)
+ {
+ str->append(presentation);
+ return;
+ }
+ char buffer[20];
+ String num(buffer, sizeof(buffer), &my_charset_bin);
+ num.set(value, decimals, &my_charset_bin);
+ str->append(num);
+}
+
+
+/*
+ hex item
+ In string context this is a binary string.
+ In number context this is a longlong value.
+*/
+
+bool Item_float::eq(const Item *arg, bool binary_cmp) const
{
if (arg->basic_const_item() && arg->type() == type())
{
@@ -2275,16 +4070,11 @@ bool Item_real::eq(const Item *arg, bool binary_cmp) const
a basic constant.
*/
Item *item= (Item*) arg;
- return item->val() == value;
+ return item->val_real() == value;
}
return FALSE;
}
-/****************************************************************************
-** varbinary item
-** In string context this is a binary string
-** In number context this is a longlong value.
-****************************************************************************/
inline uint char_val(char X)
{
@@ -2294,7 +4084,7 @@ inline uint char_val(char X)
}
-Item_varbinary::Item_varbinary(const char *str, uint str_length)
+Item_hex_string::Item_hex_string(const char *str, uint str_length)
{
name=(char*) str-2; // Lex makes this start with 0x
max_length=(str_length+1)/2;
@@ -2316,7 +4106,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length)
unsigned_flag= 1;
}
-longlong Item_varbinary::val_int()
+longlong Item_hex_string::val_int()
{
// following assert is redundant, because fixed=1 assigned in constructor
DBUG_ASSERT(fixed == 1);
@@ -2330,7 +4120,17 @@ longlong Item_varbinary::val_int()
}
-int Item_varbinary::save_in_field(Field *field, bool no_conversions)
+my_decimal *Item_hex_string::val_decimal(my_decimal *decimal_value)
+{
+ // following assert is redundant, because fixed=1 assigned in constructor
+ DBUG_ASSERT(fixed == 1);
+ ulonglong value= (ulonglong)val_int();
+ int2my_decimal(E_DEC_FATAL_ERROR, value, TRUE, decimal_value);
+ return (decimal_value);
+}
+
+
+int Item_hex_string::save_in_field(Field *field, bool no_conversions)
{
int error;
field->set_notnull();
@@ -2341,13 +4141,13 @@ int Item_varbinary::save_in_field(Field *field, bool no_conversions)
else
{
longlong nr=val_int();
- error=field->store(nr);
+ error=field->store(nr, TRUE); // Assume hex numbers are unsigned
}
return error;
}
-bool Item_varbinary::eq(const Item *arg, bool binary_cmp) const
+bool Item_hex_string::eq(const Item *arg, bool binary_cmp) const
{
if (arg->basic_const_item() && arg->type() == type())
{
@@ -2359,7 +4159,7 @@ bool Item_varbinary::eq(const Item *arg, bool binary_cmp) const
}
-Item *Item_varbinary::safe_charset_converter(CHARSET_INFO *tocs)
+Item *Item_hex_string::safe_charset_converter(CHARSET_INFO *tocs)
{
Item_string *conv;
String tmp, *str= val_str(&tmp);
@@ -2367,12 +4167,50 @@ Item *Item_varbinary::safe_charset_converter(CHARSET_INFO *tocs)
if (!(conv= new Item_string(str->ptr(), str->length(), tocs)))
return NULL;
conv->str_value.copy();
- conv->str_value.shrink_to_length();
+ conv->str_value.mark_as_const();
return conv;
}
/*
+ bin item.
+ In string context this is a binary string.
+ In number context this is a longlong value.
+*/
+
+Item_bin_string::Item_bin_string(const char *str, uint str_length)
+{
+ const char *end= str + str_length - 1;
+ uchar bits= 0;
+ uint power= 1;
+
+ name= (char*) str - 2;
+ max_length= (str_length + 7) >> 3;
+ char *ptr= (char*) sql_alloc(max_length + 1);
+ if (!ptr)
+ return;
+ str_value.set(ptr, max_length, &my_charset_bin);
+ ptr+= max_length - 1;
+ ptr[1]= 0; // Set end null for string
+ for (; end >= str; end--)
+ {
+ if (power == 256)
+ {
+ power= 1;
+ *ptr--= bits;
+ bits= 0;
+ }
+ if (*end == '1')
+ bits|= power;
+ power<<= 1;
+ }
+ *ptr= (char) bits;
+ collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
+ fixed= 1;
+}
+
+
+/*
Pack data in buffer for sending
*/
@@ -2389,7 +4227,7 @@ bool Item::send(Protocol *protocol, String *buffer)
{
bool result;
enum_field_types type;
- LINT_INIT(result);
+ LINT_INIT(result); // Will be set if null_value == 0
switch ((type=field_type())) {
default:
@@ -2404,6 +4242,9 @@ bool Item::send(Protocol *protocol, String *buffer)
case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_NEWDECIMAL:
{
String *res;
if ((res=val_str(buffer)))
@@ -2419,6 +4260,7 @@ bool Item::send(Protocol *protocol, String *buffer)
break;
}
case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
{
longlong nr;
nr= val_int();
@@ -2446,15 +4288,14 @@ bool Item::send(Protocol *protocol, String *buffer)
case MYSQL_TYPE_FLOAT:
{
float nr;
- nr= (float) val();
+ nr= (float) val_real();
if (!null_value)
result= protocol->store(nr, decimals, buffer);
break;
}
case MYSQL_TYPE_DOUBLE:
{
- double nr;
- nr= val();
+ double nr= val_real();
if (!null_value)
result= protocol->store(nr, decimals, buffer);
break;
@@ -2495,200 +4336,294 @@ bool Item_field::send(Protocol *protocol, String *buffer)
}
+Item_ref::Item_ref(Name_resolution_context *context_arg,
+ Item **item, const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_ident(context_arg, NullS, table_name_arg, field_name_arg),
+ result_field(0), ref(item)
+{
+ /*
+ This constructor used to create some internals references over fixed items
+ */
+ DBUG_ASSERT(ref != 0);
+ if (*ref && (*ref)->fixed)
+ set_properties();
+}
+
+
/*
- This is used for HAVING clause
- Find field in select list having the same name
+ Resolve the name of a reference to a column reference.
+
+ SYNOPSIS
+ Item_ref::fix_fields()
+ thd [in] current thread
+ reference [in/out] view column if this item was resolved to a view column
+
+ DESCRIPTION
+ The method resolves the column reference represented by 'this' as a column
+ present in one of: GROUP BY clause, SELECT clause, outer queries. It is
+ used typically for columns in the HAVING clause which are not under
+ aggregate functions.
+
+ NOTES
+ The name resolution algorithm used is (where [T_j] is an optional table
+ name that qualifies the column name):
+
+ resolve_extended([T_j].col_ref_i)
+ {
+ Search for a column or derived column named col_ref_i [in table T_j]
+ in the SELECT and GROUP clauses of Q.
+
+ if such a column is NOT found AND // Lookup in outer queries.
+ there are outer queries
+ {
+ for each outer query Q_k beginning from the inner-most one
+ {
+ Search for a column or derived column named col_ref_i
+ [in table T_j] in the SELECT and GROUP clauses of Q_k.
+
+ if such a column is not found AND
+ - Q_k is not a group query AND
+ - Q_k is not inside an aggregate function
+ OR
+ - Q_(k-1) is not in a HAVING or SELECT clause of Q_k
+ {
+ search for a column or derived column named col_ref_i
+ [in table T_j] in the FROM clause of Q_k;
+ }
+ }
+ }
+ }
+
+ This procedure treats GROUP BY and SELECT clauses as one namespace for
+ column references in HAVING. Notice that compared to
+ Item_field::fix_fields, here we first search the SELECT and GROUP BY
+ clauses, and then we search the FROM clause.
+
+ POSTCONDITION
+ Item_ref::ref is 0 or points to a valid item
+
+ RETURN
+ TRUE if error
+ FALSE on success
*/
-bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
+bool Item_ref::fix_fields(THD *thd, Item **reference)
{
- DBUG_ASSERT(fixed == 0);
- uint counter;
enum_parsing_place place= NO_MATTER;
- bool not_used;
- if (!ref)
+ DBUG_ASSERT(fixed == 0);
+ SELECT_LEX *current_sel= thd->lex->current_select;
+
+ if (!ref || ref == not_found_item)
{
- TABLE_LIST *where= 0, *table_list;
- SELECT_LEX_UNIT *prev_unit= thd->lex->current_select->master_unit();
- SELECT_LEX *sl= prev_unit->outer_select();
- /*
- Finding only in current select will be performed for selects that have
- not outer one and for derived tables (which not support using outer
- fields for now)
- */
- if ((ref= find_item_in_list(this,
- *(thd->lex->current_select->get_item_list()),
- &counter,
- ((sl &&
- thd->lex->current_select->master_unit()->
- first_select()->linkage !=
- DERIVED_TABLE_TYPE) ?
- REPORT_EXCEPT_NOT_FOUND :
- REPORT_ALL_ERRORS ), &not_used)) ==
- (Item **)not_found_item)
+ if (!(ref= resolve_ref_in_select_and_group(thd, this,
+ context->select_lex)))
+ goto error; /* Some error occurred (e.g. ambiguous names). */
+
+ if (ref == not_found_item) /* This reference was not resolved. */
{
- Field *tmp= (Field*) not_found_field;
- SELECT_LEX *last= 0;
+ Name_resolution_context *last_checked_context= context;
+ Name_resolution_context *outer_context= context->outer_context;
+ Field *from_field;
+ ref= 0;
+
+ if (!outer_context)
+ {
+ /* The current reference cannot be resolved in this query. */
+ my_error(ER_BAD_FIELD_ERROR,MYF(0),
+ this->full_name(), current_thd->where);
+ goto error;
+ }
+
/*
- We can't find table field in select list of current select,
- consequently we have to find it in outer subselect(s).
- We can't join lists of outer & current select, because of scope
- of view rules. For example if both tables (outer & current) have
- field 'field' it is not mistake to refer to this field without
- mention of table name, but if we join tables in one list it will
- cause error ER_NON_UNIQ_ERROR in find_item_in_list.
+ If there is an outer context (select), and it is not a derived table
+ (which do not support the use of outer fields for now), try to
+ resolve this reference in the outer select(s).
+
+ We treat each subselect as a separate namespace, so that different
+ subselects may contain columns with the same names. The subselects are
+ searched starting from the innermost.
*/
- for ( ; sl ; sl= (prev_unit= sl->master_unit())->outer_select())
+ from_field= (Field*) not_found_field;
+
+ do
{
- last= sl;
- Item_subselect *prev_subselect_item= prev_unit->item;
- if (sl->resolve_mode == SELECT_LEX::SELECT_MODE &&
- (ref= find_item_in_list(this, sl->item_list,
- &counter, REPORT_EXCEPT_NOT_FOUND,
- &not_used)) !=
- (Item **)not_found_item)
- {
- if (ref && (*ref)->fixed) // Avoid crash in case of error
- {
- prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
- prev_subselect_item->const_item_cache&= (*ref)->const_item();
- }
- break;
- }
- table_list= sl->get_table_list();
- if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
- {
- // it is primary INSERT st_select_lex => skip first table resolving
- table_list= table_list->next;
- }
+ SELECT_LEX *select= outer_context->select_lex;
+ Item_subselect *prev_subselect_item=
+ last_checked_context->select_lex->master_unit()->item;
+ last_checked_context= outer_context;
+
+ /* Search in the SELECT and GROUP lists of the outer select. */
+ if (outer_context->resolve_in_select_list)
+ {
+ if (!(ref= resolve_ref_in_select_and_group(thd, this, select)))
+ goto error; /* Some error occurred (e.g. ambiguous names). */
+ if (ref != not_found_item)
+ {
+ DBUG_ASSERT(*ref && (*ref)->fixed);
+ prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
+ prev_subselect_item->const_item_cache&= (*ref)->const_item();
+ break;
+ }
+ /*
+ Set ref to 0 to ensure that we get an error in case we replaced
+ this item with another item and still use this item in some
+ other place of the parse tree.
+ */
+ ref= 0;
+ }
+
place= prev_subselect_item->parsing_place;
/*
- check table fields only if subquery used somewhere out of HAVING
- or SELECT list or outer SELECT do not use groupping (i.e. tables
- are accessable)
+ Check table fields only if the subquery is used somewhere out of
+ HAVING or the outer SELECT does not use grouping (i.e. tables are
+ accessible).
+ TODO:
+ Here we could first find the field anyway, and then test this
+ condition, so that we can give a better error message -
+ ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
+ ER_BAD_FIELD_ERROR which we produce now.
*/
if ((place != IN_HAVING ||
- (sl->with_sum_func == 0 && sl->group_list.elements == 0)) &&
- (tmp= find_field_in_tables(thd, this,
- table_list, &where,
- 0)) != not_found_field)
+ (!select->with_sum_func &&
+ select->group_list.elements == 0)))
{
- prev_subselect_item->used_tables_cache|= tmp->table->map;
- prev_subselect_item->const_item_cache= 0;
- break;
+ /*
+ In case of view, find_field_in_tables() write pointer to view
+ field expression to 'reference', i.e. it substitute that
+ expression instead of this Item_ref
+ */
+ from_field= find_field_in_tables(thd, this,
+ outer_context->
+ first_name_resolution_table,
+ outer_context->
+ last_name_resolution_table,
+ reference,
+ IGNORE_EXCEPT_NON_UNIQUE,
+ outer_context->check_privileges,
+ TRUE);
+ if (! from_field)
+ goto error;
+ if (from_field == view_ref_found)
+ {
+ Item::Type type= (*reference)->type();
+ prev_subselect_item->used_tables_cache|=
+ (*reference)->used_tables();
+ prev_subselect_item->const_item_cache&=
+ (*reference)->const_item();
+ DBUG_ASSERT((*reference)->type() == REF_ITEM);
+ mark_as_dependent(thd, last_checked_context->select_lex,
+ context->select_lex, this,
+ ((type == REF_ITEM || type == FIELD_ITEM) ?
+ (Item_ident*) (*reference) :
+ 0));
+ /*
+ view reference found, we substituted it instead of this
+ Item, so can quit
+ */
+ return FALSE;
+ }
+ if (from_field != not_found_field)
+ {
+ prev_subselect_item->used_tables_cache|= from_field->table->map;
+ prev_subselect_item->const_item_cache= 0;
+ break;
+ }
}
- // Reference is not found => depend from outer (or just error)
- prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
- prev_subselect_item->const_item_cache= 0;
+ DBUG_ASSERT(from_field == not_found_field);
- if (sl->master_unit()->first_select()->linkage ==
- DERIVED_TABLE_TYPE)
- break; // do not look over derived table
- }
+ /* Reference is not found => depend on outer (or just error). */
+ prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
+ prev_subselect_item->const_item_cache= 0;
- if (!ref)
- return 1;
- if (!tmp)
- return -1;
- if (ref == (Item **)not_found_item && tmp == not_found_field)
- {
- // We can't say exactly what absend (table or field)
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
- full_name(), thd->where);
- ref= 0; // Safety
- return 1;
- }
- if (tmp != not_found_field)
+ outer_context= outer_context->outer_context;
+ } while (outer_context);
+
+ DBUG_ASSERT(from_field != 0 && from_field != view_ref_found);
+ if (from_field != not_found_field)
{
Item_field* fld;
- /*
- Set ref to 0 as we are replacing this item with the found item
- and this will ensure we get an error if this item would be
- used elsewhere
- */
- ref= 0; // Safety
- if (!(fld= new Item_field(tmp)))
- return 1;
- thd->change_item_tree(reference, fld);
- mark_as_dependent(thd, last, thd->lex->current_select, fld);
- return 0;
- }
- if (!last->ref_pointer_array[counter])
- {
- my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
- "forward reference in item list");
- return -1;
- }
- DBUG_ASSERT((*ref)->fixed);
- mark_as_dependent(thd, last, thd->lex->current_select,
- this);
- if (place == IN_HAVING)
- {
- Item_ref *rf;
- if (!(rf= new Item_direct_ref(last->ref_pointer_array + counter,
- (char *)table_name,
- (char *)field_name)))
- return 1;
- ref= 0; // Safety
- if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1))
- return 1;
- thd->change_item_tree(reference, rf);
- return 0;
+ if (!(fld= new Item_field(from_field)))
+ goto error;
+ thd->change_item_tree(reference, fld);
+ mark_as_dependent(thd, last_checked_context->select_lex,
+ thd->lex->current_select, this, fld);
+ return FALSE;
}
- ref= last->ref_pointer_array + counter;
- }
- else if (!ref)
- return 1;
- else
- {
- if (!(*ref)->fixed)
+ if (ref == 0)
{
- my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
- "forward reference in item list");
- return -1;
+ /* The item was not a table field and not a reference */
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ this->full_name(), current_thd->where);
+ goto error;
}
- ref= thd->lex->current_select->ref_pointer_array + counter;
+ /* Should be checked in resolve_ref_in_select_and_group(). */
+ DBUG_ASSERT(*ref && (*ref)->fixed);
+ mark_as_dependent(thd, last_checked_context->select_lex,
+ context->select_lex, this, this);
}
}
+ DBUG_ASSERT(*ref);
/*
- The following conditional is changed as to correctly identify
- incorrect references in group functions or forward references
- with sub-select's / derived tables, while it prevents this
- check when Item_ref is created in an expression involving
- summing function, which is to be placed in the user variable.
+ Check if this is an incorrect reference in a group function or forward
+ reference. Do not issue an error if this is an unnamed reference inside an
+ aggregate function.
*/
if (((*ref)->with_sum_func && name &&
(depended_from ||
- !(thd->lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- thd->lex->current_select->having_fix_field))) ||
+ !(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
+ current_sel->having_fix_field))) ||
!(*ref)->fixed)
{
- my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
- ((*ref)->with_sum_func?
- "reference on group function":
- "forward reference in item list"));
- return 1;
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0),
+ name, ((*ref)->with_sum_func?
+ "reference to group function":
+ "forward reference in item list"));
+ goto error;
}
set_properties();
- if (ref && (*ref)->check_cols(1))
- return 1;
- return 0;
+ if ((*ref)->check_cols(1))
+ goto error;
+ return FALSE;
+
+error:
+ context->process_error(thd);
+ return TRUE;
}
+
void Item_ref::set_properties()
{
max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;
collation.set((*ref)->collation);
+ /*
+ We have to remember if we refer to a sum function, to ensure that
+ split_sum_func() doesn't try to change the reference.
+ */
with_sum_func= (*ref)->with_sum_func;
unsigned_flag= (*ref)->unsigned_flag;
+ if ((*ref)->type() == FIELD_ITEM)
+ alias_name_used= ((Item_ident *) (*ref))->alias_name_used;
+ else
+ alias_name_used= TRUE; // it is not field, so it is was resolved by alias
fixed= 1;
}
+
+void Item_ref::cleanup()
+{
+ DBUG_ENTER("Item_ref::cleanup");
+ Item_ident::cleanup();
+ result_field= 0;
+ DBUG_VOID_RETURN;
+}
+
+
void Item_ref::print(String *str)
{
if (ref && *ref)
@@ -2698,6 +4633,183 @@ void Item_ref::print(String *str)
}
+bool Item_ref::send(Protocol *prot, String *tmp)
+{
+ if (result_field)
+ return prot->store(result_field);
+ return (*ref)->send(prot, tmp);
+}
+
+
+double Item_ref::val_result()
+{
+ if (result_field)
+ {
+ if ((null_value= result_field->is_null()))
+ return 0.0;
+ return result_field->val_real();
+ }
+ return val_real();
+}
+
+
+longlong Item_ref::val_int_result()
+{
+ if (result_field)
+ {
+ if ((null_value= result_field->is_null()))
+ return 0;
+ return result_field->val_int();
+ }
+ return val_int();
+}
+
+
+String *Item_ref::str_result(String* str)
+{
+ if (result_field)
+ {
+ if ((null_value= result_field->is_null()))
+ return 0;
+ str->set_charset(str_value.charset());
+ return result_field->val_str(str, &str_value);
+ }
+ return val_str(str);
+}
+
+
+my_decimal *Item_ref::val_decimal_result(my_decimal *decimal_value)
+{
+ if (result_field)
+ {
+ if ((null_value= result_field->is_null()))
+ return 0;
+ return result_field->val_decimal(decimal_value);
+ }
+ return val_decimal(decimal_value);
+}
+
+
+bool Item_ref::val_bool_result()
+{
+ if (result_field)
+ {
+ if ((null_value= result_field->is_null()))
+ return 0;
+ switch (result_field->result_type()) {
+ case INT_RESULT:
+ return result_field->val_int() != 0;
+ case DECIMAL_RESULT:
+ {
+ my_decimal decimal_value;
+ my_decimal *val= result_field->val_decimal(&decimal_value);
+ if (val)
+ return !my_decimal_is_zero(val);
+ return 0;
+ }
+ case REAL_RESULT:
+ case STRING_RESULT:
+ return result_field->val_real() != 0.0;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+ return val_bool();
+}
+
+
+double Item_ref::val_real()
+{
+ DBUG_ASSERT(fixed);
+ double tmp=(*ref)->val_result();
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+longlong Item_ref::val_int()
+{
+ DBUG_ASSERT(fixed);
+ longlong tmp=(*ref)->val_int_result();
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+bool Item_ref::val_bool()
+{
+ DBUG_ASSERT(fixed);
+ bool tmp= (*ref)->val_bool_result();
+ null_value= (*ref)->null_value;
+ return tmp;
+}
+
+
+String *Item_ref::val_str(String* tmp)
+{
+ DBUG_ASSERT(fixed);
+ tmp=(*ref)->str_result(tmp);
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+bool Item_ref::is_null()
+{
+ DBUG_ASSERT(fixed);
+ (void) (*ref)->val_int_result();
+ return (*ref)->null_value;
+}
+
+
+bool Item_ref::get_date(TIME *ltime,uint fuzzydate)
+{
+ return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
+}
+
+
+my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
+{
+ my_decimal *val= (*ref)->val_decimal_result(decimal_value);
+ null_value= (*ref)->null_value;
+ return val;
+}
+
+int Item_ref::save_in_field(Field *to, bool no_conversions)
+{
+ int res;
+ if (result_field)
+ {
+ if (result_field->is_null())
+ {
+ null_value= 1;
+ return set_field_to_null_with_conversions(to, no_conversions);
+ }
+ to->set_notnull();
+ field_conv(to, result_field);
+ null_value= 0;
+ return 0;
+ }
+ res= (*ref)->save_in_field(to, no_conversions);
+ null_value= (*ref)->null_value;
+ return res;
+}
+
+
+void Item_ref::make_field(Send_field *field)
+{
+ (*ref)->make_field(field);
+ /* Non-zero in case of a view */
+ if (name)
+ field->col_name= name;
+ if (table_name)
+ field->table_name= table_name;
+ if (db_name)
+ field->db_name= db_name;
+}
+
+
void Item_ref_null_helper::print(String *str)
{
str->append("<ref_null_helper>(", 18);
@@ -2709,6 +4821,112 @@ void Item_ref_null_helper::print(String *str)
}
+double Item_direct_ref::val_real()
+{
+ double tmp=(*ref)->val_real();
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+longlong Item_direct_ref::val_int()
+{
+ longlong tmp=(*ref)->val_int();
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+String *Item_direct_ref::val_str(String* tmp)
+{
+ tmp=(*ref)->val_str(tmp);
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+my_decimal *Item_direct_ref::val_decimal(my_decimal *decimal_value)
+{
+ my_decimal *tmp= (*ref)->val_decimal(decimal_value);
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+bool Item_direct_ref::val_bool()
+{
+ bool tmp= (*ref)->val_bool();
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+bool Item_direct_ref::is_null()
+{
+ return (*ref)->is_null();
+}
+
+
+bool Item_direct_ref::get_date(TIME *ltime,uint fuzzydate)
+{
+ return (null_value=(*ref)->get_date(ltime,fuzzydate));
+}
+
+
+/*
+ Prepare referenced view viewld then call usual Item_direct_ref::fix_fields
+
+ SYNOPSIS
+ Item_direct_view_ref::fix_fields()
+ thd thread handler
+ reference reference on reference where this item stored
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
+{
+ /* view fild reference must be defined */
+ DBUG_ASSERT(*ref);
+ /* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */
+ if (!(*ref)->fixed &&
+ ((*ref)->fix_fields(thd, ref)))
+ return TRUE;
+ return Item_direct_ref::fix_fields(thd, reference);
+}
+
+/*
+ Compare view field's name with item's name before call to referenced
+ item's eq()
+
+ SYNOPSIS
+ Item_direct_view_ref::eq()
+ item item to compare with
+ binary_cmp make binary comparison
+
+ DESCRIPTION
+ Consider queries:
+ create view v1 as select t1.f1 as f2, t1.f2 as f1 from t1;
+ select * from v1 order by f1;
+ In order to choose right field for sorting we need to compare
+ given item's name (f1) to view field's name prior to calling
+ referenced item's eq().
+
+ RETURN
+ TRUE Referenced item is equal to given item
+ FALSE otherwise
+*/
+
+
+bool Item_direct_view_ref::eq(const Item *item, bool binary_cmp) const
+{
+ Item *it= ((Item *) item)->real_item();
+ return (!it->name || !my_strcasecmp(system_charset_info, it->name,
+ field_name)) && ref && (*ref)->real_item()->eq(it, binary_cmp);
+}
+
void Item_null_helper::print(String *str)
{
str->append("<null_helper>(", 14);
@@ -2724,39 +4942,49 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const
}
-bool Item_default_value::fix_fields(THD *thd,
- struct st_table_list *table_list,
- Item **items)
+bool Item_default_value::fix_fields(THD *thd, Item **items)
{
+ Item *real_arg;
+ Item_field *field_arg;
+ Field *def_field;
DBUG_ASSERT(fixed == 0);
+
if (!arg)
{
fixed= 1;
- return 0;
+ return FALSE;
}
- if (!arg->fixed && arg->fix_fields(thd, table_list, &arg))
- return 1;
-
- if (arg->type() == REF_ITEM)
+ if (!arg->fixed && arg->fix_fields(thd, &arg))
+ goto error;
+
+
+ real_arg= arg->real_item();
+ if (real_arg->type() != FIELD_ITEM)
{
- Item_ref *ref= (Item_ref *)arg;
- if (ref->ref[0]->type() != FIELD_ITEM)
- {
- return 1;
- }
- arg= ref->ref[0];
+ my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
+ goto error;
}
- Item_field *field_arg= (Item_field *)arg;
- Field *def_field= (Field*) sql_alloc(field_arg->field->size_of());
- if (!def_field)
- return 1;
+
+ field_arg= (Item_field *)real_arg;
+ if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)
+ {
+ my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
+ goto error;
+ }
+ if (!(def_field= (Field*) sql_alloc(field_arg->field->size_of())))
+ goto error;
memcpy(def_field, field_arg->field, field_arg->field->size_of());
- def_field->move_field(def_field->table->default_values -
+ def_field->move_field(def_field->table->s->default_values -
def_field->table->record[0]);
set_field(def_field);
- return 0;
+ return FALSE;
+
+error:
+ context->process_error(thd);
+ return TRUE;
}
+
void Item_default_value::print(String *str)
{
if (!arg)
@@ -2769,6 +4997,40 @@ void Item_default_value::print(String *str)
str->append(')');
}
+
+int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
+{
+ if (!arg)
+ {
+ if (field_arg->flags & NO_DEFAULT_VALUE_FLAG)
+ {
+ if (context->error_processor == &view_error_processor)
+ {
+ TABLE_LIST *view= cached_table->top_table();
+ push_warning_printf(field_arg->table->in_use,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_NO_DEFAULT_FOR_VIEW_FIELD,
+ ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
+ view->view_db.str,
+ view->view_name.str);
+ }
+ else
+ {
+ push_warning_printf(field_arg->table->in_use,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_NO_DEFAULT_FOR_FIELD,
+ ER(ER_NO_DEFAULT_FOR_FIELD),
+ field_arg->field_name);
+ }
+ return 1;
+ }
+ field_arg->set_default();
+ return 0;
+ }
+ return Item_field::save_in_field(field_arg, no_conversions);
+}
+
+
bool Item_insert_value::eq(const Item *item, bool binary_cmp) const
{
return item->type() == INSERT_VALUE_ITEM &&
@@ -2776,20 +5038,18 @@ bool Item_insert_value::eq(const Item *item, bool binary_cmp) const
}
-bool Item_insert_value::fix_fields(THD *thd,
- struct st_table_list *table_list,
- Item **items)
+bool Item_insert_value::fix_fields(THD *thd, Item **items)
{
DBUG_ASSERT(fixed == 0);
- if (!arg->fixed && arg->fix_fields(thd, table_list, &arg))
- return 1;
+ if (!arg->fixed && arg->fix_fields(thd, &arg))
+ return TRUE;
if (arg->type() == REF_ITEM)
{
Item_ref *ref= (Item_ref *)arg;
if (ref->ref[0]->type() != FIELD_ITEM)
{
- return 1;
+ return TRUE;
}
arg= ref->ref[0];
}
@@ -2798,7 +5058,7 @@ bool Item_insert_value::fix_fields(THD *thd,
{
Field *def_field= (Field*) sql_alloc(field_arg->field->size_of());
if (!def_field)
- return 1;
+ return TRUE;
memcpy(def_field, field_arg->field, field_arg->field->size_of());
def_field->move_field(def_field->table->insert_values -
def_field->table->record[0]);
@@ -2811,7 +5071,7 @@ bool Item_insert_value::fix_fields(THD *thd,
set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name,
tmp_field->table, &my_charset_bin));
}
- return 0;
+ return FALSE;
}
void Item_insert_value::print(String *str)
@@ -2821,6 +5081,97 @@ void Item_insert_value::print(String *str)
str->append(')');
}
+
+/*
+ Find index of Field object which will be appropriate for item
+ representing field of row being changed in trigger.
+
+ SYNOPSIS
+ setup_field()
+ thd - current thread context
+ table - table of trigger (and where we looking for fields)
+
+ NOTE
+ This function does almost the same as fix_fields() for Item_field
+ but is invoked right after trigger definition parsing. Since at
+ this stage we can't say exactly what Field object (corresponding
+ to TABLE::record[0] or TABLE::record[1]) should be bound to this
+ Item, we only find out index of the Field and then select concrete
+ Field object in fix_fields() (by that time Table_trigger_list::old_field/
+ new_field should point to proper array of Fields).
+ It also binds Item_trigger_field to Table_triggers_list object for
+ table of trigger which uses this item.
+*/
+
+void Item_trigger_field::setup_field(THD *thd, TABLE *table)
+{
+ bool save_set_query_id= thd->set_query_id;
+
+ /* TODO: Think more about consequences of this step. */
+ thd->set_query_id= 0;
+ /*
+ Try to find field by its name and if it will be found
+ set field_idx properly.
+ */
+ (void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name),
+ 0, 0, &field_idx);
+ thd->set_query_id= save_set_query_id;
+ triggers= table->triggers;
+}
+
+
+bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const
+{
+ return item->type() == TRIGGER_FIELD_ITEM &&
+ row_version == ((Item_trigger_field *)item)->row_version &&
+ !my_strcasecmp(system_charset_info, field_name,
+ ((Item_trigger_field *)item)->field_name);
+}
+
+
+bool Item_trigger_field::fix_fields(THD *thd, Item **items)
+{
+ /*
+ Since trigger is object tightly associated with TABLE object most
+ of its set up can be performed during trigger loading i.e. trigger
+ parsing! So we have little to do in fix_fields. :)
+ FIXME may be we still should bother about permissions here.
+ */
+ DBUG_ASSERT(fixed == 0);
+
+ if (field_idx != (uint)-1)
+ {
+ field= (row_version == OLD_ROW) ? triggers->old_field[field_idx] :
+ triggers->new_field[field_idx];
+ set_field(field);
+ fixed= 1;
+ return 0;
+ }
+
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), field_name,
+ (row_version == NEW_ROW) ? "NEW" : "OLD");
+ return 1;
+}
+
+
+void Item_trigger_field::print(String *str)
+{
+ str->append((row_version == NEW_ROW) ? "NEW" : "OLD", 3);
+ str->append('.');
+ str->append(field_name);
+}
+
+
+void Item_trigger_field::cleanup()
+{
+ /*
+ Since special nature of Item_trigger_field we should not do most of
+ things from Item_field::cleanup() or Item_ident::cleanup() here.
+ */
+ Item::cleanup();
+}
+
+
/*
If item is a const function, calculate it and return a const item
The original item is freed if not returned
@@ -2834,6 +5185,9 @@ Item_result item_cmp_type(Item_result a,Item_result b)
return INT_RESULT;
else if (a == ROW_RESULT || b == ROW_RESULT)
return ROW_RESULT;
+ if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
+ (b == INT_RESULT || b == DECIMAL_RESULT))
+ return DECIMAL_RESULT;
return REAL_RESULT;
}
@@ -2848,7 +5202,8 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
item->result_type());
char *name=item->name; // Alloced by sql_alloc
- if (res_type == STRING_RESULT)
+ switch (res_type) {
+ case STRING_RESULT:
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),&my_charset_bin),*result;
@@ -2861,22 +5216,40 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
char *tmp_str= sql_strmake(result->ptr(), length);
new_item= new Item_string(name, tmp_str, length, result->charset());
}
+ break;
}
- else if (res_type == INT_RESULT)
+ case INT_RESULT:
{
longlong result=item->val_int();
uint length=item->max_length;
bool null_value=item->null_value;
new_item= (null_value ? (Item*) new Item_null(name) :
(Item*) new Item_int(name, result, length));
+ break;
}
- else
+ case REAL_RESULT:
{ // It must REAL_RESULT
- double result=item->val();
+ double result= item->val_real();
uint length=item->max_length,decimals=item->decimals;
bool null_value=item->null_value;
new_item= (null_value ? (Item*) new Item_null(name) : (Item*)
- new Item_real(name, result, decimals, length));
+ new Item_float(name, result, decimals, length));
+ break;
+ }
+ case DECIMAL_RESULT:
+ {
+ my_decimal decimal_value;
+ my_decimal *result= item->val_decimal(&decimal_value);
+ uint length= item->max_length, decimals= item->decimals;
+ bool null_value= item->null_value;
+ new_item= (null_value ?
+ (Item*) new Item_null(name) :
+ (Item*) new Item_decimal(name, result, length, decimals));
+ break;
+ }
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
}
if (new_item)
thd->change_item_tree(ref, new_item);
@@ -2907,7 +5280,17 @@ bool field_is_equal_to_item(Field *field,Item *item)
}
if (res_type == INT_RESULT)
return 1; // Both where of type int
- double result=item->val();
+ if (res_type == DECIMAL_RESULT)
+ {
+ my_decimal item_buf, *item_val,
+ field_buf, *field_val;
+ item_val= item->val_decimal(&item_buf);
+ if (item->null_value)
+ return 1; // This must be true
+ field_val= field->val_decimal(&field_buf);
+ return !my_decimal_cmp(item_val, field_val);
+ }
+ double result= item->val_real();
if (item->null_value)
return 1;
return result == field->val_real();
@@ -2915,12 +5298,13 @@ bool field_is_equal_to_item(Field *field,Item *item)
Item_cache* Item_cache::get_cache(Item_result type)
{
- switch (type)
- {
+ switch (type) {
case INT_RESULT:
return new Item_cache_int();
case REAL_RESULT:
return new Item_cache_real();
+ case DECIMAL_RESULT:
+ return new Item_cache_decimal();
case STRING_RESULT:
return new Item_cache_str();
case ROW_RESULT:
@@ -2948,6 +5332,23 @@ void Item_cache_int::store(Item *item)
{
value= item->val_int_result();
null_value= item->null_value;
+ unsigned_flag= item->unsigned_flag;
+}
+
+
+String *Item_cache_int::val_str(String *str)
+{
+ DBUG_ASSERT(fixed == 1);
+ str->set(value, default_charset());
+ return str;
+}
+
+
+my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val)
+{
+ DBUG_ASSERT(fixed == 1);
+ int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val);
+ return decimal_val;
}
@@ -2958,6 +5359,68 @@ void Item_cache_real::store(Item *item)
}
+longlong Item_cache_real::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) (value+(value > 0 ? 0.5 : -0.5));
+}
+
+
+String* Item_cache_real::val_str(String *str)
+{
+ DBUG_ASSERT(fixed == 1);
+ str->set(value, decimals, default_charset());
+ return str;
+}
+
+
+my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val)
+{
+ DBUG_ASSERT(fixed == 1);
+ double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val);
+ return decimal_val;
+}
+
+
+void Item_cache_decimal::store(Item *item)
+{
+ my_decimal *val= item->val_decimal_result(&decimal_value);
+ if (!(null_value= item->null_value) && val != &decimal_value)
+ my_decimal2decimal(val, &decimal_value);
+}
+
+double Item_cache_decimal::val_real()
+{
+ DBUG_ASSERT(fixed);
+ double res;
+ my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res);
+ return res;
+}
+
+longlong Item_cache_decimal::val_int()
+{
+ DBUG_ASSERT(fixed);
+ longlong res;
+ my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res);
+ return res;
+}
+
+String* Item_cache_decimal::val_str(String *str)
+{
+ DBUG_ASSERT(fixed);
+ my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, FALSE,
+ &decimal_value);
+ my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, str);
+ return str;
+}
+
+my_decimal *Item_cache_decimal::val_decimal(my_decimal *val)
+{
+ DBUG_ASSERT(fixed);
+ return &decimal_value;
+}
+
+
void Item_cache_str::store(Item *item)
{
value_buff.set(buffer, sizeof(buffer), item->collation.collation);
@@ -2979,18 +5442,15 @@ void Item_cache_str::store(Item *item)
}
}
-
-double Item_cache_str::val()
+double Item_cache_str::val_real()
{
DBUG_ASSERT(fixed == 1);
- int err;
+ int err_not_used;
+ char *end_not_used;
if (value)
- {
- char *end_not_used;
return my_strntod(value->charset(), (char*) value->ptr(),
- value->length(), &end_not_used, &err);
- }
- return (double)0;
+ value->length(), &end_not_used, &err_not_used);
+ return (double) 0;
}
@@ -3005,6 +5465,16 @@ longlong Item_cache_str::val_int()
return (longlong)0;
}
+my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val)
+{
+ DBUG_ASSERT(fixed == 1);
+ if (value)
+ string2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val);
+ else
+ decimal_val= 0;
+ return decimal_val;
+}
+
bool Item_cache_row::allocate(uint num)
{
@@ -3102,6 +5572,10 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
maybe_null= item->maybe_null;
collation.set(item->collation);
get_full_info(item);
+ /* fix variable decimals which always is NOT_FIXED_DEC */
+ if (Field::result_merge_type(fld_type) == INT_RESULT)
+ decimals= 0;
+ prev_decimal_int_part= item->decimal_int_part();
}
@@ -3160,7 +5634,7 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
break;
}
case FUNC_ITEM:
- if (((Item_func *) item)->functype() == Item_func::VAR_VALUE_FUNC)
+ if (((Item_func *) item)->functype() == Item_func::GUSERVAR_FUNC)
{
/*
There are work around of problem with changing variable type on the
@@ -3168,14 +5642,15 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
acceptable information for client in send_field, so we make field
type from expression type.
*/
- switch (item->result_type())
- {
+ switch (item->result_type()) {
case STRING_RESULT:
return MYSQL_TYPE_VAR_STRING;
case INT_RESULT:
return MYSQL_TYPE_LONGLONG;
case REAL_RESULT:
return MYSQL_TYPE_DOUBLE;
+ case DECIMAL_RESULT:
+ return MYSQL_TYPE_NEWDECIMAL;
case ROW_RESULT:
default:
DBUG_ASSERT(0);
@@ -3205,8 +5680,32 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
bool Item_type_holder::join_types(THD *thd, Item *item)
{
- max_length= max(max_length, display_length(item));
+ DBUG_ENTER("Item_type_holder::join_types");
+ DBUG_PRINT("info:", ("was type %d len %d, dec %d name %s",
+ fld_type, max_length, decimals,
+ (name ? name : "<NULL>")));
+ DBUG_PRINT("info:", ("in type %d len %d, dec %d",
+ get_real_type(item),
+ item->max_length, item->decimals));
fld_type= Field::field_type_merge(fld_type, get_real_type(item));
+ {
+ int item_decimals= item->decimals;
+ /* fix variable decimals which always is NOT_FIXED_DEC */
+ if (Field::result_merge_type(fld_type) == INT_RESULT)
+ item_decimals= 0;
+ decimals= max(decimals, item_decimals);
+ }
+ if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
+ {
+ decimals= min(max(decimals, item->decimals), DECIMAL_MAX_SCALE);
+ int precision= min(max(prev_decimal_int_part, item->decimal_int_part())
+ + decimals, DECIMAL_MAX_PRECISION);
+ unsigned_flag&= item->unsigned_flag;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
+ }
+ else
+ max_length= max(max_length, display_length(item));
if (Field::result_merge_type(fld_type) == STRING_RESULT)
{
const char *old_cs, *old_derivation;
@@ -3219,13 +5718,17 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
item->collation.collation->name,
item->collation.derivation_name(),
"UNION");
- return TRUE;
+ DBUG_RETURN(TRUE);
}
}
- decimals= max(decimals, item->decimals);
maybe_null|= item->maybe_null;
get_full_info(item);
- return FALSE;
+
+ /* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
+ prev_decimal_int_part= decimal_int_part();
+ DBUG_PRINT("info", ("become type: %d len: %u dec: %u",
+ (int) fld_type, max_length, (uint) decimals));
+ DBUG_RETURN(FALSE);
}
/*
@@ -3253,6 +5756,9 @@ uint32 Item_type_holder::display_length(Item *item)
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_TINY_BLOB:
@@ -3318,10 +5824,6 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
Field::NONE, name,
table, get_set_pack_length(enum_set_typelib->count),
enum_set_typelib, collation.collation);
- case MYSQL_TYPE_VAR_STRING:
- table->db_create_options|= HA_OPTION_PACK_RECORD;
- fld_type= MYSQL_TYPE_STRING;
- break;
default:
break;
}
@@ -3365,7 +5867,7 @@ void Item_type_holder::get_full_info(Item *item)
}
-double Item_type_holder::val()
+double Item_type_holder::val_real()
{
DBUG_ASSERT(0); // should never be called
return 0.0;
@@ -3378,6 +5880,11 @@ longlong Item_type_holder::val_int()
return 0;
}
+my_decimal *Item_type_holder::val_decimal(my_decimal *)
+{
+ DBUG_ASSERT(0); // should never be called
+ return 0;
+}
String *Item_type_holder::val_str(String*)
{
@@ -3393,13 +5900,42 @@ void Item_result_field::cleanup()
DBUG_VOID_RETURN;
}
+/*
+ Dummy error processor used by default by Name_resolution_context
+
+ SYNOPSIS
+ dummy_error_processor()
+
+ NOTE
+ do nothing
+*/
+
+void dummy_error_processor(THD *thd, void *data)
+{}
+
+/*
+ Wrapper of hide_view_error call for Name_resolution_context error processor
+
+ SYNOPSIS
+ view_error_processor()
+
+ NOTE
+ hide view underlying tables details in error messages
+*/
+
+void view_error_processor(THD *thd, void *data)
+{
+ ((TABLE_LIST *)data)->hide_view_error(thd);
+}
+
/*****************************************************************************
** Instantiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<Item>;
template class List_iterator<Item>;
template class List_iterator_fast<Item>;
+template class List_iterator_fast<Item_field>;
template class List<List_item>;
#endif
diff --git a/sql/item.h b/sql/item.h
index e683cda5786..381ba98e193 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -22,11 +22,11 @@
class Protocol;
struct st_table_list;
void item_init(void); /* Init item functions */
-
+class Item_field;
/*
"Declared Type Collation"
- A combination of collation and its deriviation.
+ A combination of collation and its derivation.
*/
enum Derivation
@@ -45,7 +45,7 @@ enum Derivation
MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
(i.e. constant).
MY_COLL_ALLOW_CONV - allow any kind of conversion
- (combintion of the above two)
+ (combination of the above two)
MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE
(e.g. when aggregating for comparison)
MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV
@@ -105,74 +105,312 @@ public:
}
};
+
+/*************************************************************************/
+/*
+ A framework to easily handle different return types for hybrid items
+ (hybrid item is an item whose operand can be of any type, e.g. integer,
+ real, decimal).
+*/
+
+struct Hybrid_type_traits;
+
+struct Hybrid_type
+{
+ longlong integer;
+
+ double real;
+ /*
+ Use two decimal buffers interchangeably to speed up += operation
+ which has no native support in decimal library.
+ Hybrid_type+= arg is implemented as dec_buf[1]= dec_buf[0] + arg.
+ The third decimal is used as a handy temporary storage.
+ */
+ my_decimal dec_buf[3];
+ int used_dec_buf_no;
+
+ /*
+ Traits moved to a separate class to
+ a) be able to easily change object traits in runtime
+ b) they work as a differentiator for the union above
+ */
+ const Hybrid_type_traits *traits;
+
+ Hybrid_type() {}
+ /* XXX: add traits->copy() when needed */
+ Hybrid_type(const Hybrid_type &rhs) :traits(rhs.traits) {}
+};
+
+
+/* Hybryd_type_traits interface + default implementation for REAL_RESULT */
+
+struct Hybrid_type_traits
+{
+ virtual Item_result type() const { return REAL_RESULT; }
+
+ virtual void
+ fix_length_and_dec(Item *item, Item *arg) const;
+
+ /* Hybrid_type operations. */
+ virtual void set_zero(Hybrid_type *val) const { val->real= 0.0; }
+ virtual void add(Hybrid_type *val, Field *f) const
+ { val->real+= f->val_real(); }
+ virtual void div(Hybrid_type *val, ulonglong u) const
+ { val->real/= ulonglong2double(u); }
+
+ virtual longlong val_int(Hybrid_type *val, bool unsigned_flag) const
+ { return (longlong) val->real; }
+ virtual double val_real(Hybrid_type *val) const { return val->real; }
+ virtual my_decimal *val_decimal(Hybrid_type *val, my_decimal *buf) const;
+ virtual String *val_str(Hybrid_type *val, String *buf, uint8 decimals) const;
+ static const Hybrid_type_traits *instance();
+};
+
+
+struct Hybrid_type_traits_decimal: public Hybrid_type_traits
+{
+ virtual Item_result type() const { return DECIMAL_RESULT; }
+
+ virtual void
+ fix_length_and_dec(Item *arg, Item *item) const;
+
+ /* Hybrid_type operations. */
+ virtual void set_zero(Hybrid_type *val) const;
+ virtual void add(Hybrid_type *val, Field *f) const;
+ virtual void div(Hybrid_type *val, ulonglong u) const;
+
+ virtual longlong val_int(Hybrid_type *val, bool unsigned_flag) const;
+ virtual double val_real(Hybrid_type *val) const;
+ virtual my_decimal *val_decimal(Hybrid_type *val, my_decimal *buf) const
+ { return &val->dec_buf[val->used_dec_buf_no]; }
+ virtual String *val_str(Hybrid_type *val, String *buf, uint8 decimals) const;
+ static const Hybrid_type_traits_decimal *instance();
+};
+
+
+struct Hybrid_type_traits_integer: public Hybrid_type_traits
+{
+ virtual Item_result type() const { return INT_RESULT; }
+
+ virtual void
+ fix_length_and_dec(Item *arg, Item *item) const;
+
+ /* Hybrid_type operations. */
+ virtual void set_zero(Hybrid_type *val) const
+ { val->integer= 0; }
+ virtual void add(Hybrid_type *val, Field *f) const
+ { val->integer+= f->val_int(); }
+ virtual void div(Hybrid_type *val, ulonglong u) const
+ { val->integer/= (longlong) u; }
+
+ virtual longlong val_int(Hybrid_type *val, bool unsigned_flag) const
+ { return val->integer; }
+ virtual double val_real(Hybrid_type *val) const
+ { return (double) val->integer; }
+ virtual my_decimal *val_decimal(Hybrid_type *val, my_decimal *buf) const
+ {
+ int2my_decimal(E_DEC_FATAL_ERROR, val->integer, 0, &val->dec_buf[2]);
+ return &val->dec_buf[2];
+ }
+ virtual String *val_str(Hybrid_type *val, String *buf, uint8 decimals) const
+ { buf->set(val->integer, &my_charset_bin); return buf;}
+ static const Hybrid_type_traits_integer *instance();
+};
+
+
+void dummy_error_processor(THD *thd, void *data);
+
+void view_error_processor(THD *thd, void *data);
+
+/*
+ Instances of Name_resolution_context store the information necesary for
+ name resolution of Items and other context analysis of a query made in
+ fix_fields().
+
+ This structure is a part of SELECT_LEX, a pointer to this structure is
+ assigned when an item is created (which happens mostly during parsing
+ (sql_yacc.yy)), but the structure itself will be initialized after parsing
+ is complete
+
+ TODO: move subquery of INSERT ... SELECT and CREATE ... SELECT to
+ separate SELECT_LEX which allow to remove tricks of changing this
+ structure before and after INSERT/CREATE and its SELECT to make correct
+ field name resolution.
+*/
+struct Name_resolution_context: Sql_alloc
+{
+ /*
+ The name resolution context to search in when an Item cannot be
+ resolved in this context (the context of an outer select)
+ */
+ Name_resolution_context *outer_context;
+
+ /*
+ List of tables used to resolve the items of this context. Usually these
+ are tables from the FROM clause of SELECT statement. The exceptions are
+ INSERT ... SELECT and CREATE ... SELECT statements, where SELECT
+ subquery is not moved to a separate SELECT_LEX. For these types of
+ statements we have to change this member dynamically to ensure correct
+ name resolution of different parts of the statement.
+ */
+ TABLE_LIST *table_list;
+ /*
+ In most cases the two table references below replace 'table_list' above
+ for the purpose of name resolution. The first and last name resolution
+ table references allow us to search only in a sub-tree of the nested
+ join tree in a FROM clause. This is needed for NATURAL JOIN, JOIN ... USING
+ and JOIN ... ON.
+ */
+ TABLE_LIST *first_name_resolution_table;
+ /*
+ Last table to search in the list of leaf table references that begins
+ with first_name_resolution_table.
+ */
+ TABLE_LIST *last_name_resolution_table;
+
+ /*
+ SELECT_LEX item belong to, in case of merged VIEW it can differ from
+ SELECT_LEX where item was created, so we can't use table_list/field_list
+ from there
+ */
+ st_select_lex *select_lex;
+
+ /*
+ Processor of errors caused during Item name resolving, now used only to
+ hide underlying tables in errors about views (i.e. it substitute some
+ errors for views)
+ */
+ void (*error_processor)(THD *, void *);
+ void *error_processor_data;
+
+ /*
+ When TRUE items are resolved in this context both against the
+ SELECT list and this->table_list. If FALSE, items are resolved
+ only against this->table_list.
+ */
+ bool resolve_in_select_list;
+
+ /*
+ When FALSE we do not check columns right of resolving items, used to
+ prevent rights check on underlying tables of view
+ */
+ bool check_privileges;
+
+ Name_resolution_context()
+ :outer_context(0), table_list(0), select_lex(0),
+ error_processor_data(0),
+ check_privileges(TRUE)
+ {}
+
+ void init()
+ {
+ resolve_in_select_list= FALSE;
+ error_processor= &dummy_error_processor;
+ first_name_resolution_table= NULL;
+ last_name_resolution_table= NULL;
+ }
+
+ void resolve_in_table_list_only(TABLE_LIST *tables)
+ {
+ table_list= first_name_resolution_table= tables;
+ resolve_in_select_list= FALSE;
+ }
+
+ void process_error(THD *thd)
+ {
+ (*error_processor)(thd, error_processor_data);
+ }
+};
+
+
+/*************************************************************************/
+
typedef bool (Item::*Item_processor)(byte *arg);
+typedef Item* (Item::*Item_transformer) (byte *arg);
+typedef void (*Cond_traverser) (const Item *item, void *arg);
+
class Item {
Item(const Item &); /* Prevent use of these */
void operator=(Item &);
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ { return (void*) sql_alloc((uint) size); }
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
- static void operator delete(void *ptr,size_t size) {}
+ /* Special for SP local variable assignment - reusing slots */
+ static void *operator new(size_t size, Item *reuse, uint *rsize);
+ static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
- enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
+ enum Type {FIELD_ITEM= 0, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM,
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,
- PARAM_ITEM};
+ PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM,
+ VIEW_FIXER_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
+
+ enum traverse_order { POSTFIX, PREFIX };
+ /* Reuse size, only used by SP local variable assignment, otherwize 0 */
+ uint rsize;
+
/*
str_values's main purpose is to be used to cache the value in
save_in_field
*/
String str_value;
my_string name; /* Name from select */
+ /* Original item name (if it was renamed)*/
+ my_string orig_name;
Item *next;
uint32 max_length;
- uint8 marker,decimals;
+ uint name_length; /* Length of name */
+ uint8 marker, decimals;
my_bool maybe_null; /* If item may be null */
my_bool null_value; /* if item is null */
my_bool unsigned_flag;
my_bool with_sum_func;
my_bool fixed; /* If item fixed with fix_fields */
+ my_bool is_autogenerated_name; /* indicate was name of this Item
+ autogenerated or set by user */
DTCollation collation;
// alloc & destruct is done as start of select using sql_alloc
Item();
/*
- Constructor used by Item_field, Item_ref & agregate (sum) functions.
+ Constructor used by Item_field, Item_ref & aggregate (sum) functions.
Used for duplicating lists in processing queries with temporary
tables
Also it used for Item_cond_and/Item_cond_or for creating
- top AND/OR ctructure of WHERE clause to protect it of
+ top AND/OR structure of WHERE clause to protect it of
optimisation changes in prepared statements
*/
Item(THD *thd, Item *item);
- virtual ~Item() { name=0; } /*lint -e1509 */
- void set_name(const char *str,uint length, CHARSET_INFO *cs);
- void init_make_field(Send_field *tmp_field,enum enum_field_types type);
- virtual void cleanup()
+ virtual ~Item()
{
- DBUG_ENTER("Item::cleanup");
- DBUG_PRINT("info", ("Type: %d", (int)type()));
- fixed=0;
- marker= 0;
- DBUG_VOID_RETURN;
- }
+#ifdef EXTRA_DEBUG
+ name=0;
+#endif
+ } /*lint -e1509 */
+ void set_name(const char *str, uint length, CHARSET_INFO *cs);
+ void rename(char *new_name);
+ void init_make_field(Send_field *tmp_field,enum enum_field_types type);
+ virtual void cleanup();
virtual void make_field(Send_field *field);
- virtual bool fix_fields(THD *, struct st_table_list *, Item **);
+ Field *make_string_field(TABLE *table);
+ virtual bool fix_fields(THD *, Item **);
/*
should be used in case where we are sure that we do not need
complete fix_fields() procedure.
*/
inline void quick_fix_field() { fixed= 1; }
/* Function returns 1 on overflow and -1 on fatal errors */
+ int save_in_field_no_warnings(Field *field, bool no_conversions);
virtual int save_in_field(Field *field, bool no_conversions);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field, 1); }
@@ -185,40 +423,122 @@ public:
virtual enum_field_types field_type() const;
virtual enum Type type() const =0;
/* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
- virtual double val()=0;
+ /*
+ Return double precision floating point representation of item.
+
+ SYNOPSIS
+ val_real()
+
+ RETURN
+ In case of NULL value return 0.0 and set null_value flag to TRUE.
+ If value is not null null_value flag will be reset to FALSE.
+ */
+ virtual double val_real()=0;
+ /*
+ Return integer representation of item.
+
+ SYNOPSIS
+ val_int()
+
+ RETURN
+ In case of NULL value return 0 and set null_value flag to TRUE.
+ If value is not null null_value flag will be reset to FALSE.
+ */
virtual longlong val_int()=0;
/*
+ This is just a shortcut to avoid the cast. You should still use
+ unsigned_flag to check the sign of the item.
+ */
+ inline ulonglong val_uint() { return (ulonglong) val_int(); }
+ /*
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.
+ SYNOPSIS
+ val_str()
+ str an allocated buffer this or any nested Item object can use to
+ store return value of this method.
+
+ NOTE
+ Buffer passed via argument 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 preferable 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 argument, 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.
+
+ RETURN
+ In case of NULL value return 0 (NULL pointer) and set null_value flag
+ to TRUE.
+ If value is not null null_value flag will be reset to FALSE.
*/
- virtual String *val_str(String*)=0;
+ virtual String *val_str(String *str)=0;
+ /*
+ Return decimal representation of item with fixed point.
+
+ SYNOPSIS
+ val_decimal()
+ decimal_buffer buffer which can be used by Item for returning value
+ (but can be not)
+
+ NOTE
+ Returned value should not be changed if it is not the same which was
+ passed via argument.
+
+ RETURN
+ Return pointer on my_decimal (it can be other then passed via argument)
+ if value is not NULL (null_value flag will be reset to FALSE).
+ In case of NULL value it return 0 pointer and set null_value flag
+ to TRUE.
+ */
+ virtual my_decimal *val_decimal(my_decimal *decimal_buffer)= 0;
+ /*
+ Return boolean value of item.
+
+ RETURN
+ FALSE value is false or NULL
+ TRUE value is true (not equal to 0)
+ */
+ virtual bool val_bool();
+ /* Helper functions, see item_sum.cc */
+ String *val_string_from_real(String *str);
+ String *val_string_from_int(String *str);
+ String *val_string_from_decimal(String *str);
+ my_decimal *val_decimal_from_real(my_decimal *decimal_value);
+ my_decimal *val_decimal_from_int(my_decimal *decimal_value);
+ my_decimal *val_decimal_from_string(my_decimal *decimal_value);
+ longlong val_int_from_decimal();
+ double val_real_from_decimal();
+
virtual Field *get_tmp_table_field() { return 0; }
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
- virtual double val_result() { return val(); }
+
+ /*
+ *result* family of methods is analog of *val* family (see above) but
+ return value of result_field of item if it is present. If Item have not
+ result field, it return val(). This methods set null_value flag in same
+ way as *val* methods do it.
+ */
+ virtual double val_result() { return val_real(); }
virtual longlong val_int_result() { return val_int(); }
virtual String *str_result(String* tmp) { return val_str(tmp); }
+ virtual my_decimal *val_decimal_result(my_decimal *val)
+ { return val_decimal(val); }
+ virtual bool val_bool_result() { return val_bool(); }
+
/* bit map of tables used by item */
virtual table_map used_tables() const { return (table_map) 0L; }
/*
@@ -243,6 +563,9 @@ public:
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
+ virtual uint decimal_precision() const;
+ inline int decimal_int_part() const
+ { return my_decimal_int_part(decimal_precision(), decimals); }
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
@@ -254,6 +577,18 @@ public:
*/
virtual bool const_during_execution() const
{ return (used_tables() & ~PARAM_TABLE_BIT) == 0; }
+ /*
+ This is an essential method for correct functioning of VIEWS.
+ To save a view in an .frm file we need its unequivocal
+ definition in SQL that takes into account sql_mode and
+ environmental settings. Currently such definition is restored
+ by traversing through the parsed tree of a view and
+ print()'ing SQL syntax of every node to a String buffer. This
+ method is used to print the SQL definition of an item. The
+ second use of this method is for EXPLAIN EXTENDED, to print
+ the SQL of a query after all optimizations of the parsed tree
+ have been done.
+ */
virtual void print(String *str_arg) { str_arg->append(full_name()); }
void print_item_w_name(String *);
virtual void update_used_tables() {}
@@ -282,14 +617,14 @@ public:
virtual void top_level_item() {}
/*
set field of temporary table for Item which can be switched on temporary
- table during query processing (groupping and so on)
+ table during query processing (grouping and so on)
*/
virtual void set_result_field(Field *field) {}
virtual bool is_result_field() { return 0; }
virtual bool is_bool_func() { return 0; }
virtual void save_in_result_field(bool no_conversions) {}
/*
- set value of aggegate function in case of no rows for groupping were found
+ set value of aggregate function in case of no rows for grouping were found
*/
virtual void no_rows_in_result() {}
virtual Item *copy_or_same(THD *thd) { return this; }
@@ -305,9 +640,41 @@ public:
return (this->*processor)(arg);
}
+ virtual Item* transform(Item_transformer transformer, byte *arg)
+ {
+ return (this->*transformer)(arg);
+ }
+
+ virtual void traverse_cond(Cond_traverser traverser,
+ void *arg, traverse_order order)
+ {
+ (*traverser)(this, arg);
+ }
+
virtual bool remove_dependence_processor(byte * arg) { return 0; }
virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
-
+ virtual bool cleanup_processor(byte *arg);
+ virtual bool collect_item_field_processor(byte * arg) { return 0; }
+ virtual bool change_context_processor(byte *context) { return 0; }
+ virtual bool reset_query_id_processor(byte *query_id) { return 0; }
+
+ virtual Item *equal_fields_propagator(byte * arg) { return this; }
+ virtual Item *set_no_const_sub(byte *arg) { return this; }
+ virtual Item *replace_equal_field(byte * arg) { return this; }
+
+ /*
+ For SP local variable returns pointer to Item representing its
+ current value and pointer to current Item otherwise.
+ */
+ virtual Item *this_item() { return this; }
+ /*
+ For SP local variable returns address of pointer to Item representing its
+ current value and pointer passed via parameter otherwise.
+ */
+ virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; }
+ /* For SPs mostly. */
+ virtual Item *this_const_item() const { return const_cast<Item*>(this); }
+
// Row emulation
virtual uint cols() { return 1; }
virtual Item* el(uint i) { return this; }
@@ -319,6 +686,7 @@ public:
virtual void bring_value() {}
Field *tmp_table_field_from_field_type(TABLE *table);
+ virtual Item_field *filed_for_view_update() { return 0; }
virtual Item *neg_transformer(THD *thd) { return NULL; }
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
@@ -327,9 +695,178 @@ public:
cleanup();
delete this;
}
+
+ virtual bool is_splocal() { return 0; } /* Needed for error checking */
};
+/*
+ A reference to local SP variable (incl. reference to SP parameter), used in
+ runtime.
+
+ NOTE
+ This item has a "value" item, defined as
+ this_item() = thd->spcont->get_item(m_offset)
+ and it delegates everything to that item (if !this_item() then this item
+ poses as Item_null) except for name, which is the name of SP local
+ variable.
+*/
+
+class Item_splocal : public Item
+{
+ uint m_offset;
+
+public:
+ LEX_STRING m_name;
+
+ /*
+ Buffer, pointing to the string value of the item. We need it to
+ protect internal buffer from changes. See comment to analogous
+ member in Item_param for more details.
+ */
+ String str_value_ptr;
+
+ /*
+ Position of this reference to SP variable in the statement (the
+ statement itself is in sp_instr_stmt::m_query).
+ This is valid only for references to SP variables in statements,
+ excluding DECLARE CURSOR statement. It is used to replace references to SP
+ variables with NAME_CONST calls when putting statements into the binary
+ log.
+ Value of 0 means that this object doesn't corresponding to reference to
+ SP variable in query text.
+ */
+ int pos_in_query;
+
+ Item_splocal(LEX_STRING name, uint offset, int pos_in_q=0)
+ : m_offset(offset), m_name(name), pos_in_query(pos_in_q)
+ {
+ maybe_null= TRUE;
+ }
+
+ /* For error printing */
+ inline LEX_STRING *my_name(LEX_STRING *get_name)
+ {
+ if (!get_name)
+ return &m_name;
+ (*get_name)= m_name;
+ return get_name;
+ }
+
+ bool is_splocal() { return 1; } /* Needed for error checking */
+
+ Item *this_item();
+ Item **this_item_addr(THD *thd, Item **);
+ Item *this_const_item() const;
+
+ bool fix_fields(THD *, Item **);
+ void cleanup();
+
+ inline uint get_offset()
+ {
+ return m_offset;
+ }
+
+ // Abstract methods inherited from Item. Just defer the call to
+ // the item in the frame
+ enum Type type() const;
+
+ double val_real();
+ longlong val_int();
+ String *val_str(String *sp);
+ my_decimal *val_decimal(my_decimal *);
+ bool is_null();
+ void print(String *str);
+
+ void make_field(Send_field *field)
+ {
+ Item *it= this_item();
+
+ if (name)
+ it->set_name(name, (uint) strlen(name), system_charset_info);
+ else
+ it->set_name(m_name.str, m_name.length, system_charset_info);
+ it->make_field(field);
+ }
+
+ Item_result result_type() const
+ {
+ return this_const_item()->result_type();
+ }
+
+ bool const_item() const
+ {
+ return TRUE;
+ }
+
+ int save_in_field(Field *field, bool no_conversions)
+ {
+ return this_item()->save_in_field(field, no_conversions);
+ }
+
+ bool send(Protocol *protocol, String *str)
+ {
+ return this_item()->send(protocol, str);
+ }
+};
+
+
+/*
+ NAME_CONST(given_name, const_value).
+ This 'function' has all properties of the supplied const_value (which is
+ assumed to be a literal constant), and the name given_name.
+
+ This is used to replace references to SP variables when we write PROCEDURE
+ statements into the binary log.
+
+ TODO
+ Together with Item_splocal and Item::this_item() we can actually extract
+ common a base of this class and Item_splocal. Maybe it is possible to
+ extract a common base with class Item_ref, too.
+*/
+
+class Item_name_const : public Item
+{
+ Item *value_item;
+ Item *name_item;
+public:
+ Item_name_const(Item *name, Item *val): value_item(val), name_item(name)
+ {
+ Item::maybe_null= TRUE;
+ }
+
+ bool fix_fields(THD *, Item **);
+ void cleanup();
+
+ enum Type type() const;
+ double val_real();
+ longlong val_int();
+ String *val_str(String *sp);
+ my_decimal *val_decimal(my_decimal *);
+ bool is_null();
+ void print(String *str);
+
+ Item_result result_type() const
+ {
+ return value_item->result_type();
+ }
+
+ bool const_item() const
+ {
+ return TRUE;
+ }
+
+ int save_in_field(Field *field, bool no_conversions)
+ {
+ return value_item->save_in_field(field, no_conversions);
+ }
+
+ bool send(Protocol *protocol, String *str)
+ {
+ return value_item->send(protocol, str);
+ }
+};
+
bool agg_item_collations(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags= 0);
bool agg_item_collations_for_comparison(DTCollation &c, const char *name,
@@ -361,10 +898,13 @@ protected:
const char *orig_db_name;
const char *orig_table_name;
const char *orig_field_name;
+
public:
+ Name_resolution_context *context;
const char *db_name;
const char *table_name;
const char *field_name;
+ bool alias_name_used; /* true if item was resolved against alias */
/*
Cached value of index for this field in table->field array, used by prep.
stmts for speeding up their re-execution. Holds NO_CACHED_FIELD_INDEX
@@ -378,26 +918,44 @@ public:
*/
TABLE_LIST *cached_table;
st_select_lex *depended_from;
- Item_ident(const char *db_name_par,const char *table_name_par,
- const char *field_name_par);
+ Item_ident(Name_resolution_context *context_arg,
+ const char *db_name_arg, const char *table_name_arg,
+ const char *field_name_arg);
Item_ident(THD *thd, Item_ident *item);
const char *full_name() const;
void cleanup();
bool remove_dependence_processor(byte * arg);
+ void print(String *str);
+ virtual bool change_context_processor(byte *cntx)
+ { context= (Name_resolution_context *)cntx; return FALSE; }
+ friend bool insert_fields(THD *thd, Name_resolution_context *context,
+ const char *db_name,
+ const char *table_name, List_iterator<Item> *it,
+ bool any_privileges);
};
+class Item_equal;
+class COND_EQUAL;
class Item_field :public Item_ident
{
+protected:
void set_field(Field *field);
public:
Field *field,*result_field;
+ Item_equal *item_equal;
+ bool no_const_subst;
+ /*
+ if any_privileges set to TRUE then here real effective privileges will
+ be stored
+ */
+ uint have_privileges;
+ /* field need any privileges (for VIEW creation) */
+ bool any_privileges;
- 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)
- { collation.set(DERIVATION_IMPLICIT); }
+ Item_field(Name_resolution_context *context_arg,
+ const char *db_arg,const char *table_name_arg,
+ const char *field_name_arg);
/*
Constructor needed to process subselect with temporary tables (see Item)
*/
@@ -407,7 +965,7 @@ public:
and database names will live as long as Item_field (this is important
in prepared statements).
*/
- Item_field(THD *thd, Field *field);
+ Item_field(THD *thd, Name_resolution_context *context_arg, Field *field);
/*
If this constructor is used, fix_fields() won't work, because
db_name, table_name and column_name are unknown. It's necessary to call
@@ -416,15 +974,18 @@ public:
Item_field(Field *field);
enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- double val();
+ double val_real();
longlong val_int();
+ my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
+ my_decimal *val_decimal_result(my_decimal *);
+ bool val_bool_result();
bool send(Protocol *protocol, String *str_arg);
void reset_field(Field *f);
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void make_field(Send_field *tmp_field);
int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field);
@@ -448,8 +1009,22 @@ public:
bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); }
Item *get_tmp_table_item(THD *thd);
+ bool collect_item_field_processor(byte * arg);
+ bool reset_query_id_processor(byte *arg)
+ {
+ field->query_id= *((query_id_t *) arg);
+ if (result_field)
+ result_field->query_id= field->query_id;
+ return 0;
+ }
void cleanup();
+ Item_equal *find_item_equal(COND_EQUAL *cond_equal);
+ Item *equal_fields_propagator(byte *arg);
+ Item *set_no_const_sub(byte *arg);
+ Item *replace_equal_field(byte *arg);
inline uint32 max_disp_length() { return field->max_length(); }
+ Item_field *filed_for_view_update() { return this; }
+ Item *safe_charset_converter(CHARSET_INFO *tocs);
friend class Item_default_value;
friend class Item_insert_value;
friend class st_select_lex_unit;
@@ -468,15 +1043,16 @@ public:
}
enum Type type() const { return NULL_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
+ my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field);
bool send(Protocol *protocol, String *str);
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
- // to prevent drop fixed flag (no need parent cleanup call)
+ /* to prevent drop fixed flag (no need parent cleanup call) */
void cleanup() {}
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
@@ -505,7 +1081,8 @@ public:
enum enum_item_param_state
{
NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE,
- STRING_VALUE, TIME_VALUE, LONG_DATA_VALUE
+ STRING_VALUE, TIME_VALUE, LONG_DATA_VALUE,
+ DECIMAL_VALUE
} state;
/*
@@ -519,6 +1096,7 @@ public:
Can not be declared inside the union as it's not a POD type.
*/
String str_value_ptr;
+ my_decimal decimal_value;
union
{
longlong integer;
@@ -569,8 +1147,9 @@ public:
enum Type type() const { return item_type; }
enum_field_types field_type() const { return param_type; }
- double val();
+ double val_real();
longlong val_int();
+ my_decimal *val_decimal(my_decimal*);
String *val_str(String*);
bool get_time(TIME *tm);
bool get_date(TIME *tm, uint fuzzydate);
@@ -579,6 +1158,7 @@ public:
void set_null();
void set_int(longlong i, uint32 max_length_arg);
void set_double(double i);
+ void set_decimal(const char *str, ulong length);
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);
@@ -603,7 +1183,7 @@ public:
*/
virtual table_map used_tables() const
{ return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; }
- void print(String *str) { str->append('?'); }
+ void print(String *str);
bool is_null()
{ DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; }
bool basic_const_item() const;
@@ -618,7 +1198,6 @@ public:
basic_const_item returned TRUE.
*/
Item *new_item();
- Item *safe_charset_converter(CHARSET_INFO *tocs);
/*
Implement by-value equality evaluation if parameter value
is set and is a basic constant (integer, real or string).
@@ -634,10 +1213,10 @@ public:
longlong value;
Item_int(int32 i,uint length=11) :value((longlong) i)
{ max_length=length; fixed= 1; }
-#ifdef HAVE_LONG_LONG
Item_int(longlong i,uint length=21) :value(i)
- { max_length=length; fixed= 1;}
-#endif
+ { max_length=length; fixed= 1; }
+ Item_int(ulonglong i, uint length= 21) :value((longlong)i)
+ { max_length=length; fixed= 1; unsigned_flag= 1; }
Item_int(const char *str_arg,longlong i,uint length) :value(i)
{ max_length=length; name=(char*) str_arg; fixed= 1; }
Item_int(const char *str_arg, uint length=64);
@@ -645,7 +1224,8 @@ public:
enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
int save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; }
@@ -654,77 +1234,134 @@ public:
void cleanup() {}
void print(String *str);
Item_num *neg() { value= -value; return this; }
+ uint decimal_precision() const
+ { return (uint)(max_length - test(value < 0)); }
bool eq(const Item *, bool binary_cmp) const;
};
+class Item_static_int_func :public Item_int
+{
+ const char *func_name;
+public:
+ Item_static_int_func(const char *str_arg, longlong i, uint length)
+ :Item_int(NullS, i, length), func_name(str_arg)
+ {}
+ Item *safe_charset_converter(CHARSET_INFO *tocs);
+ void print(String *str) { str->append(func_name); }
+};
+
+
class Item_uint :public Item_int
{
public:
Item_uint(const char *str_arg, uint length);
+ Item_uint(ulonglong i) :Item_int((ulonglong) i, 10) {}
Item_uint(const char *str_arg, longlong i, uint length);
- Item_uint(uint32 i) :Item_int((longlong) i, 10)
- { unsigned_flag= 1; }
- double val()
+ double val_real()
{ DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); }
String *val_str(String*);
Item *new_item() { return new Item_uint(name,max_length); }
int save_in_field(Field *field, bool no_conversions);
void print(String *str);
Item_num *neg ();
+ uint decimal_precision() const { return max_length; }
};
-class Item_real :public Item_num
+/* decimal (fixed point) constant */
+class Item_decimal :public Item_num
{
+protected:
+ my_decimal decimal_value;
public:
- double value;
- // Item_real() :value(0) {}
- Item_real(const char *str_arg, uint length) :value(my_atof(str_arg))
+ Item_decimal(const char *str_arg, uint length, CHARSET_INFO *charset);
+ Item_decimal(const char *str, const my_decimal *val_arg,
+ uint decimal_par, uint length);
+ Item_decimal(my_decimal *value_par);
+ Item_decimal(longlong val, bool unsig);
+ Item_decimal(double val, int precision, int scale);
+ Item_decimal(const char *bin, int precision, int scale);
+
+ enum Type type() const { return DECIMAL_ITEM; }
+ enum Item_result result_type () const { return DECIMAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ longlong val_int();
+ double val_real();
+ String *val_str(String*);
+ my_decimal *val_decimal(my_decimal *val) { return &decimal_value; }
+ int save_in_field(Field *field, bool no_conversions);
+ bool basic_const_item() const { return 1; }
+ Item *new_item()
{
- name=(char*) str_arg;
- decimals=(uint8) nr_of_decimals(str_arg);
- max_length=length;
- fixed= 1;
+ return new Item_decimal(name, &decimal_value, decimals, max_length);
}
- Item_real(const char *str,double val_arg,uint decimal_par,uint length)
+ // to prevent drop fixed flag (no need parent cleanup call)
+ void cleanup() {}
+ void print(String *str);
+ Item_num *neg()
+ {
+ my_decimal_neg(&decimal_value);
+ unsigned_flag= !decimal_value.sign();
+ return this;
+ }
+ uint decimal_precision() const { return decimal_value.precision(); }
+ bool eq(const Item *, bool binary_cmp) const;
+};
+
+
+class Item_float :public Item_num
+{
+ char *presentation;
+public:
+ double value;
+ // Item_real() :value(0) {}
+ Item_float(const char *str_arg, uint length);
+ Item_float(const char *str,double val_arg,uint decimal_par,uint length)
:value(val_arg)
{
- name=(char*) str;
+ presentation= name=(char*) str;
decimals=(uint8) decimal_par;
max_length=length;
fixed= 1;
}
- Item_real(double value_par) :value(value_par) { fixed= 1; }
+ Item_float(double value_par) :presentation(0), value(value_par) { fixed= 1; }
+
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
- double val() { DBUG_ASSERT(fixed == 1); return value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return value; }
longlong val_int()
{
DBUG_ASSERT(fixed == 1);
return (longlong) (value+(value > 0 ? 0.5 : -0.5));
}
String *val_str(String*);
+ my_decimal *val_decimal(my_decimal *);
bool basic_const_item() const { return 1; }
// to prevent drop fixed flag (no need parent cleanup call)
void cleanup() {}
- Item *new_item() { return new Item_real(name,value,decimals,max_length); }
+ Item *new_item()
+ { return new Item_float(name, value, decimals, max_length); }
Item_num *neg() { value= -value; return this; }
+ void print(String *str);
bool eq(const Item *, bool binary_cmp) const;
};
-class Item_float :public Item_real
+class Item_static_float_func :public Item_float
{
+ const char *func_name;
public:
- Item_float(const char *str,uint length) :Item_real(str,length)
- {
- decimals=NOT_FIXED_DEC;
- max_length=DBL_DIG+8;
- }
+ Item_static_float_func(const char *str, double val_arg, uint decimal_par,
+ uint length)
+ :Item_float(NullS, val_arg, decimal_par, length), func_name(str)
+ {}
+ void print(String *str) { str->append(func_name); }
+ Item *safe_charset_converter(CHARSET_INFO *tocs);
};
+
class Item_string :public Item
{
public:
@@ -746,41 +1383,47 @@ public:
// it is constant => can be used without fix_fields (and frequently used)
fixed= 1;
}
+ /* Just create an item and do not fill string representation */
+ Item_string(CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
+ {
+ collation.set(cs, dv);
+ max_length= 0;
+ set_name(NULL, 0, cs);
+ decimals= NOT_FIXED_DEC;
+ fixed= 1;
+ }
Item_string(const char *name_par, const char *str, uint length,
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
{
collation.set(cs, dv);
str_value.set_or_copy_aligned(str,length,cs);
max_length= str_value.numchars()*cs->mbmaxlen;
- set_name(name_par,0,cs);
+ set_name(name_par, 0, cs);
decimals=NOT_FIXED_DEC;
// it is constant => can be used without fix_fields (and frequently used)
fixed= 1;
}
- enum Type type() const { return STRING_ITEM; }
- double val()
- {
- DBUG_ASSERT(fixed == 1);
- int err;
- char *end_not_used;
- return my_strntod(str_value.charset(), (char*) str_value.ptr(),
- str_value.length(), &end_not_used, &err);
- }
- longlong val_int()
+ /*
+ This is used in stored procedures to avoid memory leaks and
+ does a deep copy of its argument.
+ */
+ void set_str_with_copy(const char *str_arg, uint length_arg)
{
- DBUG_ASSERT(fixed == 1);
- int err;
- return my_strntoll(str_value.charset(), str_value.ptr(),
- str_value.length(), 10, (char**) 0, &err);
+ str_value.copy(str_arg, length_arg, collation.collation);
+ max_length= str_value.numchars() * collation.collation->mbmaxlen;
}
+ enum Type type() const { return STRING_ITEM; }
+ double val_real();
+ longlong val_int();
String *val_str(String*)
{
DBUG_ASSERT(fixed == 1);
return (String*) &str_value;
}
+ my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const;
Item *new_item()
@@ -796,13 +1439,28 @@ public:
void cleanup() {}
};
+
+class Item_static_string_func :public Item_string
+{
+ const char *func_name;
+public:
+ Item_static_string_func(const char *name_par, const char *str, uint length,
+ CHARSET_INFO *cs,
+ Derivation dv= DERIVATION_COERCIBLE)
+ :Item_string(NullS, str, length, cs, dv), func_name(name_par)
+ {}
+ Item *safe_charset_converter(CHARSET_INFO *tocs);
+ void print(String *str) { str->append(func_name); }
+};
+
+
/* for show tables */
class Item_datetime :public Item_string
{
public:
Item_datetime(const char *item_name): Item_string(item_name,"",0,
- &my_charset_bin)
+ &my_charset_bin)
{ max_length=19;}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
};
@@ -830,19 +1488,21 @@ public:
};
-class Item_varbinary :public Item
+class Item_hex_string: public Item
{
public:
- Item_varbinary(const char *str,uint str_length);
+ Item_hex_string(): Item() {}
+ Item_hex_string(const char *str,uint str_length);
enum Type type() const { return VARBIN_ITEM; }
- double val()
- { DBUG_ASSERT(fixed == 1); return (double) Item_varbinary::val_int(); }
+ double val_real()
+ { DBUG_ASSERT(fixed == 1); return (double) Item_hex_string::val_int(); }
longlong val_int();
bool basic_const_item() const { return 1; }
String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
+ my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
// to prevent drop fixed flag (no need parent cleanup call)
void cleanup() {}
bool eq(const Item *item, bool binary_cmp) const;
@@ -850,6 +1510,12 @@ public:
};
+class Item_bin_string: public Item_hex_string
+{
+public:
+ Item_bin_string(const char *str,uint str_length);
+};
+
class Item_result_field :public Item /* Item with result field */
{
public:
@@ -879,11 +1545,14 @@ class Item_ref :public Item_ident
protected:
void set_properties();
public:
+ enum Ref_Type { REF, DIRECT_REF, VIEW_REF };
Field *result_field; /* Save result here */
Item **ref;
- Item_ref(const char *db_par, const char *table_name_par,
- const char *field_name_par)
- :Item_ident(db_par, table_name_par, field_name_par), ref(0) {}
+ Item_ref(Name_resolution_context *context_arg,
+ const char *db_arg, const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_ident(context_arg, db_arg, table_name_arg, field_name_arg),
+ result_field(0), ref(0) {}
/*
This constructor is used in two scenarios:
A) *item = NULL
@@ -898,72 +1567,66 @@ public:
TODO we probably fix a superset of problems like in BUG#6658. Check this
with Bar, and if we have a more broader set of problems like this.
*/
- Item_ref(Item **item, const char *table_name_par, const char *field_name_par)
- :Item_ident(NullS, table_name_par, field_name_par), ref(item)
- {
- DBUG_ASSERT(item);
- if (*item)
- set_properties();
- }
+ Item_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg, const char *field_name_arg);
/* Constructor need to process subselect with temporary tables (see Item) */
- Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), ref(item->ref) {}
+ Item_ref(THD *thd, Item_ref *item)
+ :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {}
enum Type type() const { return REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const
- { return ref && (*ref)->eq(item, binary_cmp); }
- double val()
- {
- DBUG_ASSERT(fixed);
- double tmp=(*ref)->val_result();
- null_value=(*ref)->null_value;
- return tmp;
- }
- longlong val_int()
- {
- DBUG_ASSERT(fixed);
- longlong tmp=(*ref)->val_int_result();
- null_value=(*ref)->null_value;
- return tmp;
- }
- String *val_str(String* tmp)
- {
- DBUG_ASSERT(fixed);
- tmp=(*ref)->str_result(tmp);
- null_value=(*ref)->null_value;
- return tmp;
- }
- bool is_null()
- {
- DBUG_ASSERT(fixed);
- (void) (*ref)->val_int_result();
- return (*ref)->null_value;
- }
- bool get_date(TIME *ltime,uint fuzzydate)
- {
- DBUG_ASSERT(fixed);
- return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
+ {
+ Item *it= ((Item *) item)->real_item();
+ return ref && (*ref)->eq(it, binary_cmp);
}
- bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); }
- void make_field(Send_field *field) { (*ref)->make_field(field); }
- bool fix_fields(THD *, struct st_table_list *, Item **);
- int save_in_field(Field *field, bool no_conversions)
- { return (*ref)->save_in_field(field, no_conversions); }
+ double val_real();
+ longlong val_int();
+ my_decimal *val_decimal(my_decimal *);
+ bool val_bool();
+ String *val_str(String* tmp);
+ bool is_null();
+ bool get_date(TIME *ltime,uint fuzzydate);
+ double val_result();
+ longlong val_int_result();
+ String *str_result(String* tmp);
+ my_decimal *val_decimal_result(my_decimal *);
+ bool val_bool_result();
+ bool send(Protocol *prot, String *tmp);
+ void make_field(Send_field *field);
+ bool fix_fields(THD *, Item **);
+ int save_in_field(Field *field, bool no_conversions);
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
enum_field_types field_type() const { return (*ref)->field_type(); }
- Field *get_tmp_table_field() { return result_field; }
+ Field *get_tmp_table_field()
+ { return result_field ? result_field : (*ref)->get_tmp_table_field(); }
+ Item *get_tmp_table_item(THD *thd)
+ {
+ return (result_field ? new Item_field(result_field) :
+ (*ref)->get_tmp_table_item(thd));
+ }
table_map used_tables() const
{
return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables();
}
+ table_map not_null_tables() const { return (*ref)->not_null_tables(); }
void set_result_field(Field *field) { result_field= field; }
bool is_result_field() { return 1; }
void save_in_result_field(bool no_conversions)
{
(*ref)->save_in_field(result_field, no_conversions);
}
- Item *real_item() { return *ref; }
+ Item *real_item()
+ {
+ return (*ref)->real_item();
+ }
+ bool walk(Item_processor processor, byte *arg)
+ { return (*ref)->walk(processor, arg); }
void print(String *str);
+ void cleanup();
+ Item_field *filed_for_view_update()
+ { return (*ref)->filed_for_view_update(); }
+ virtual Ref_Type ref_type() { return REF; }
};
@@ -974,39 +1637,41 @@ public:
class Item_direct_ref :public Item_ref
{
public:
- Item_direct_ref(Item **item, const char *table_name_par,
- const char *field_name_par)
- :Item_ref(item, table_name_par, field_name_par) {}
+ Item_direct_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_ref(context_arg, item, table_name_arg, field_name_arg) {}
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
- double val()
- {
- double tmp=(*ref)->val();
- null_value=(*ref)->null_value;
- return tmp;
- }
- longlong val_int()
- {
- longlong tmp=(*ref)->val_int();
- null_value=(*ref)->null_value;
- return tmp;
- }
- String *val_str(String* tmp)
- {
- tmp=(*ref)->val_str(tmp);
- null_value=(*ref)->null_value;
- return tmp;
- }
- bool is_null()
- {
- (void) (*ref)->val_int();
- return (*ref)->null_value;
- }
- bool get_date(TIME *ltime,uint fuzzydate)
- {
- return (null_value=(*ref)->get_date(ltime,fuzzydate));
- }
+ double val_real();
+ longlong val_int();
+ String *val_str(String* tmp);
+ my_decimal *val_decimal(my_decimal *);
+ bool val_bool();
+ bool is_null();
+ bool get_date(TIME *ltime,uint fuzzydate);
+ virtual Ref_Type ref_type() { return DIRECT_REF; }
+};
+
+/*
+ Class for view fields, the same as Item_direct_ref, but call fix_fields
+ of reference if it is not called yet
+*/
+class Item_direct_view_ref :public Item_direct_ref
+{
+public:
+ Item_direct_view_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg) {}
+ /* Constructor need to process subselect with temporary tables (see Item) */
+ Item_direct_view_ref(THD *thd, Item_direct_ref *item)
+ :Item_direct_ref(thd, item) {}
+
+ bool fix_fields(THD *, Item **);
+ bool eq(const Item *item, bool binary_cmp) const;
+ virtual Ref_Type ref_type() { return VIEW_REF; }
};
@@ -1017,12 +1682,16 @@ class Item_ref_null_helper: public Item_ref
protected:
Item_in_subselect* owner;
public:
- Item_ref_null_helper(Item_in_subselect* master, Item **item,
- const char *table_name_par, const char *field_name_par):
- Item_ref(item, table_name_par, field_name_par), owner(master) {}
- double val();
+ Item_ref_null_helper(Name_resolution_context *context_arg,
+ Item_in_subselect* master, Item **item,
+ const char *table_name_arg, const char *field_name_arg)
+ :Item_ref(context_arg, item, table_name_arg, field_name_arg),
+ owner(master) {}
+ double val_real();
longlong val_int();
String* val_str(String* s);
+ my_decimal *val_decimal(my_decimal *);
+ bool val_bool();
bool get_date(TIME *ltime, uint fuzzydate);
void print(String *str);
/*
@@ -1040,9 +1709,11 @@ class Item_null_helper :public Item_ref_null_helper
{
Item *store;
public:
- Item_null_helper(Item_in_subselect* master, Item *item,
- const char *table_name_par, const char *field_name_par)
- :Item_ref_null_helper(master, &item, table_name_par, field_name_par),
+ Item_null_helper(Name_resolution_context *context_arg,
+ Item_in_subselect* master, Item *item,
+ const char *table_name_arg, const char *field_name_arg)
+ :Item_ref_null_helper(context_arg, master, (store= 0, &store),
+ table_name_arg, field_name_arg),
store(item)
{ ref= &store; }
void print(String *str);
@@ -1102,20 +1773,23 @@ public:
enum Type type() const { return COPY_STR_ITEM; }
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return cached_field_type; }
- double val()
+ double val_real()
{
- int err;
+ int err_not_used;
char *end_not_used;
return (null_value ? 0.0 :
my_strntod(str_value.charset(), (char*) str_value.ptr(),
- str_value.length(), &end_not_used, &err));
+ str_value.length(), &end_not_used, &err_not_used));
}
longlong val_int()
- {
+ {
int err;
- return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),10, (char**) 0,&err);
+ return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),
+ str_value.length(),10, (char**) 0,
+ &err);
}
String *val_str(String*);
+ my_decimal *val_decimal(my_decimal *);
void make_field(Send_field *field) { item->make_field(field); }
void copy();
int save_in_field(Field *field, bool no_conversions);
@@ -1125,55 +1799,64 @@ public:
};
-class Item_buff :public Sql_alloc
+class Cached_item :public Sql_alloc
{
public:
my_bool null_value;
- Item_buff() :null_value(0) {}
+ Cached_item() :null_value(0) {}
virtual bool cmp(void)=0;
- virtual ~Item_buff(); /*line -e1509 */
+ virtual ~Cached_item(); /*line -e1509 */
};
-class Item_str_buff :public Item_buff
+class Cached_item_str :public Cached_item
{
Item *item;
String value,tmp_value;
public:
- Item_str_buff(THD *thd, Item *arg);
+ Cached_item_str(THD *thd, Item *arg);
bool cmp(void);
- ~Item_str_buff(); // Deallocate String:s
+ ~Cached_item_str(); // Deallocate String:s
};
-class Item_real_buff :public Item_buff
+class Cached_item_real :public Cached_item
{
Item *item;
double value;
public:
- Item_real_buff(Item *item_par) :item(item_par),value(0.0) {}
+ Cached_item_real(Item *item_par) :item(item_par),value(0.0) {}
bool cmp(void);
};
-class Item_int_buff :public Item_buff
+class Cached_item_int :public Cached_item
{
Item *item;
longlong value;
public:
- Item_int_buff(Item *item_par) :item(item_par),value(0) {}
+ Cached_item_int(Item *item_par) :item(item_par),value(0) {}
bool cmp(void);
};
-class Item_field_buff :public Item_buff
+class Cached_item_decimal :public Cached_item
+{
+ Item *item;
+ my_decimal value;
+public:
+ Cached_item_decimal(Item *item_par);
+ bool cmp(void);
+};
+
+class Cached_item_field :public Cached_item
{
char *buff;
Field *field;
uint length;
public:
- Item_field_buff(Item_field *item)
+ Cached_item_field(Item_field *item)
{
- field=item->field;
+ field= item->field;
buff= (char*) sql_calloc(length=field->pack_length());
}
bool cmp(void);
@@ -1183,40 +1866,51 @@ class Item_default_value : public Item_field
{
public:
Item *arg;
- Item_default_value() :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {}
- Item_default_value(Item *a) :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
+ Item_default_value(Name_resolution_context *context_arg)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(NULL) {}
+ Item_default_value(Name_resolution_context *context_arg, Item *a)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(a) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void print(String *str);
- int save_in_field(Field *field_arg, bool no_conversions)
- {
- if (!arg)
- {
- field_arg->set_default();
- return 0;
- }
- return Item_field::save_in_field(field_arg, no_conversions);
- }
+ int save_in_field(Field *field_arg, bool no_conversions);
table_map used_tables() const { return (table_map)0L; }
-
+
bool walk(Item_processor processor, byte *args)
{
return arg->walk(processor, args) ||
(this->*processor)(args);
}
+
+ /*
+ This method like the walk method traverses the item tree, but
+ at the same time it can replace some nodes in the tree
+ */
+ Item *transform(Item_transformer transformer, byte *args)
+ {
+ Item *new_item= arg->transform(transformer, args);
+ if (!new_item)
+ return 0;
+ arg= new_item;
+ return (this->*transformer)(args);
+ }
};
class Item_insert_value : public Item_field
{
public:
Item *arg;
- Item_insert_value(Item *a) :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
+ Item_insert_value(Name_resolution_context *context_arg, Item *a)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(a) {}
bool eq(const Item *item, bool binary_cmp) const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void print(String *str);
int save_in_field(Field *field_arg, bool no_conversions)
{
@@ -1231,6 +1925,70 @@ public:
}
};
+
+/*
+ We need this two enums here instead of sql_lex.h because
+ at least one of them is used by Item_trigger_field interface.
+
+ Time when trigger is invoked (i.e. before or after row actually
+ inserted/updated/deleted).
+*/
+enum trg_action_time_type
+{
+ TRG_ACTION_BEFORE= 0, TRG_ACTION_AFTER= 1, TRG_ACTION_MAX
+};
+
+/*
+ Event on which trigger is invoked.
+*/
+enum trg_event_type
+{
+ TRG_EVENT_INSERT= 0 , TRG_EVENT_UPDATE= 1, TRG_EVENT_DELETE= 2, TRG_EVENT_MAX
+};
+
+class Table_triggers_list;
+
+/*
+ Represents NEW/OLD version of field of row which is
+ changed/read in trigger.
+
+ Note: For this item main part of actual binding to Field object happens
+ not during fix_fields() call (like for Item_field) but right after
+ parsing of trigger definition, when table is opened, with special
+ setup_field() call. On fix_fields() stage we simply choose one of
+ two Field instances representing either OLD or NEW version of this
+ field.
+*/
+class Item_trigger_field : public Item_field
+{
+public:
+ /* Is this item represents row from NEW or OLD row ? */
+ enum row_version_type {OLD_ROW, NEW_ROW};
+ row_version_type row_version;
+ /* Next in list of all Item_trigger_field's in trigger */
+ Item_trigger_field *next_trg_field;
+ /* Index of the field in the TABLE::field array */
+ uint field_idx;
+ /* Pointer to Table_trigger_list object for table of this trigger */
+ Table_triggers_list *triggers;
+
+ Item_trigger_field(Name_resolution_context *context_arg,
+ row_version_type row_ver_arg,
+ const char *field_name_arg)
+ :Item_field(context_arg,
+ (const char *)NULL, (const char *)NULL, field_name_arg),
+ row_version(row_ver_arg), field_idx((uint)-1)
+ {}
+ void setup_field(THD *thd, TABLE *table);
+ enum Type type() const { return TRIGGER_FIELD_ITEM; }
+ bool eq(const Item *item, bool binary_cmp) const;
+ bool fix_fields(THD *, Item **);
+ void print(String *str);
+ table_map used_tables() const { return (table_map)0L; }
+ void cleanup();
+};
+
+
class Item_cache: public Item
{
protected:
@@ -1260,24 +2018,23 @@ public:
void print(String *str);
};
+
class Item_cache_int: public Item_cache
{
+protected:
longlong value;
public:
Item_cache_int(): Item_cache(), value(0) {}
-
+
void store(Item *item);
- double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
- String* val_str(String *str)
- {
- DBUG_ASSERT(fixed == 1);
- str->set(value, default_charset());
- return str;
- }
+ String* val_str(String *str);
+ my_decimal *val_decimal(my_decimal *);
enum Item_result result_type() const { return INT_RESULT; }
};
+
class Item_cache_real: public Item_cache
{
double value;
@@ -1285,31 +2042,42 @@ public:
Item_cache_real(): Item_cache(), value(0) {}
void store(Item *item);
- double val() { DBUG_ASSERT(fixed == 1); return value; }
- longlong val_int()
- {
- DBUG_ASSERT(fixed == 1);
- return (longlong) (value+(value > 0 ? 0.5 : -0.5));
- }
- String* val_str(String *str)
- {
- str->set(value, decimals, default_charset());
- return str;
- }
+ double val_real() { DBUG_ASSERT(fixed == 1); return value; }
+ longlong val_int();
+ String* val_str(String *str);
+ my_decimal *val_decimal(my_decimal *);
enum Item_result result_type() const { return REAL_RESULT; }
};
+
+class Item_cache_decimal: public Item_cache
+{
+protected:
+ my_decimal decimal_value;
+public:
+ Item_cache_decimal(): Item_cache() {}
+
+ void store(Item *item);
+ double val_real();
+ longlong val_int();
+ String* val_str(String *str);
+ my_decimal *val_decimal(my_decimal *);
+ enum Item_result result_type() const { return DECIMAL_RESULT; }
+};
+
+
class Item_cache_str: public Item_cache
{
- char buffer[80];
+ char buffer[STRING_BUFFER_USUAL_SIZE];
String *value, value_buff;
public:
Item_cache_str(): Item_cache(), value(0) { }
-
+
void store(Item *item);
- double val();
+ double val_real();
longlong val_int();
String* val_str(String *) { DBUG_ASSERT(fixed == 1); return value; }
+ my_decimal *val_decimal(my_decimal *);
enum Item_result result_type() const { return STRING_RESULT; }
CHARSET_INFO *charset() const { return value->charset(); };
};
@@ -1339,7 +2107,7 @@ public:
{
illegal_method_call((const char*)"make_field");
};
- double val()
+ double val_real()
{
illegal_method_call((const char*)"val");
return 0;
@@ -1354,6 +2122,12 @@ public:
illegal_method_call((const char*)"val_str");
return 0;
};
+ my_decimal *val_decimal(my_decimal *val)
+ {
+ illegal_method_call((const char*)"val_decimal");
+ return 0;
+ };
+
enum Item_result result_type() const { return ROW_RESULT; }
uint cols() { return item_count; }
@@ -1390,14 +2164,18 @@ protected:
enum_field_types fld_type;
void get_full_info(Item *item);
+
+ /* It is used to count decimal precision in join_types */
+ int prev_decimal_int_part;
public:
Item_type_holder(THD*, Item*);
Item_result result_type() const;
- virtual enum_field_types field_type() const { return fld_type; };
+ enum_field_types field_type() const { return fld_type; };
enum Type type() const { return TYPE_HOLDER; }
- double val();
+ double val_real();
longlong val_int();
+ my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
bool join_types(THD *thd, Item *);
Field *make_field_by_type(TABLE *table);
@@ -1406,7 +2184,14 @@ public:
};
-extern Item_buff *new_Item_buff(THD *thd, Item *item);
+class st_select_lex;
+void mark_select_range_as_dependent(THD *thd,
+ st_select_lex *last_select,
+ st_select_lex *current_sel,
+ Field *found_field, Item *found_item,
+ Item_ident *resolved_item);
+
+extern Cached_item *new_Cached_item(THD *thd, Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item);
extern bool field_is_equal_to_item(Field *field,Item *item);
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 8298ce2cfb7..9db2f465080 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -20,33 +20,42 @@
#include "mysql_priv.h"
/*
-** Create right type of item_buffer for an item
+** Create right type of Cached_item for an item
*/
-Item_buff *new_Item_buff(THD *thd, Item *item)
+Cached_item *new_Cached_item(THD *thd, Item *item)
{
- if (item->type() == Item::FIELD_ITEM &&
- !(((Item_field *) item)->field->flags & BLOB_FLAG))
- return new Item_field_buff((Item_field *) item);
- if (item->result_type() == STRING_RESULT)
- return new Item_str_buff(thd, (Item_field *) item);
- if (item->result_type() == INT_RESULT)
- return new Item_int_buff((Item_field *) item);
- return new Item_real_buff(item);
+ if (item->real_item()->type() == Item::FIELD_ITEM &&
+ !(((Item_field *) (item->real_item()))->field->flags & BLOB_FLAG))
+ return new Cached_item_field((Item_field *) (item->real_item()));
+ switch (item->result_type()) {
+ case STRING_RESULT:
+ return new Cached_item_str(thd, (Item_field *) item);
+ case INT_RESULT:
+ return new Cached_item_int((Item_field *) item);
+ case REAL_RESULT:
+ return new Cached_item_real(item);
+ case DECIMAL_RESULT:
+ return new Cached_item_decimal(item);
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ return 0;
+ }
}
-Item_buff::~Item_buff() {}
+Cached_item::~Cached_item() {}
/*
** Compare with old value and replace value with new value
** Return true if values have changed
*/
-Item_str_buff::Item_str_buff(THD *thd, Item *arg)
+Cached_item_str::Cached_item_str(THD *thd, Item *arg)
:item(arg), value(min(arg->max_length, thd->variables.max_sort_length))
{}
-bool Item_str_buff::cmp(void)
+bool Cached_item_str::cmp(void)
{
String *res;
bool tmp;
@@ -68,14 +77,14 @@ bool Item_str_buff::cmp(void)
return tmp;
}
-Item_str_buff::~Item_str_buff()
+Cached_item_str::~Cached_item_str()
{
item=0; // Safety
}
-bool Item_real_buff::cmp(void)
+bool Cached_item_real::cmp(void)
{
- double nr=item->val();
+ double nr= item->val_real();
if (null_value != item->null_value || nr != value)
{
null_value= item->null_value;
@@ -85,7 +94,7 @@ bool Item_real_buff::cmp(void)
return FALSE;
}
-bool Item_int_buff::cmp(void)
+bool Cached_item_int::cmp(void)
{
longlong nr=item->val_int();
if (null_value != item->null_value || nr != value)
@@ -98,7 +107,7 @@ bool Item_int_buff::cmp(void)
}
-bool Item_field_buff::cmp(void)
+bool Cached_item_field::cmp(void)
{
bool tmp= field->cmp(buff) != 0; // This is not a blob!
if (tmp)
@@ -112,11 +121,32 @@ bool Item_field_buff::cmp(void)
}
+Cached_item_decimal::Cached_item_decimal(Item *it)
+ :item(it)
+{
+ my_decimal_set_zero(&value);
+}
+
+
+bool Cached_item_decimal::cmp()
+{
+ my_decimal tmp;
+ my_decimal *ptmp= item->val_decimal(&tmp);
+ if (null_value != item->null_value || my_decimal_cmp(&value, ptmp) == 0)
+ {
+ null_value= item->null_value;
+ my_decimal2decimal(ptmp, &value);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
/*****************************************************************************
** Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
-template class List<Item_buff>;
-template class List_iterator<Item_buff>;
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
+template class List<Cached_item>;
+template class List_iterator<Cached_item>;
#endif
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 74eed7fa41a..48839abcb10 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -31,6 +31,8 @@ static Item_result item_store_type(Item_result a,Item_result b)
return STRING_RESULT;
else if (a == REAL_RESULT || b == REAL_RESULT)
return REAL_RESULT;
+ else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT)
+ return DECIMAL_RESULT;
else
return INT_RESULT;
}
@@ -54,10 +56,10 @@ static void agg_cmp_type(Item_result *type, Item **items, uint nitems)
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
const char *fname)
{
- my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
- c1.collation->name,c1.derivation_name(),
- c2.collation->name,c2.derivation_name(),
- fname);
+ my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
+ c1.collation->name,c1.derivation_name(),
+ c2.collation->name,c2.derivation_name(),
+ fname);
}
@@ -105,7 +107,7 @@ Item_bool_func2* Le_creator::create(Item *a, Item *b) const
longlong Item_func_not::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ bool value= args[0]->val_bool();
null_value=args[0]->null_value;
return ((!null_value && value == 0) ? 1 : 0);
}
@@ -117,11 +119,11 @@ longlong Item_func_not::val_int()
longlong Item_func_not_all::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value= args[0]->val();
+ bool value= args[0]->val_bool();
/*
- return TRUE if there was records in underlaying select in max/min
- optimisation (ALL subquery)
+ return TRUE if there was records in underlying select in max/min
+ optimization (ALL subquery)
*/
if (empty_underlying_subquery())
return 1;
@@ -148,18 +150,18 @@ void Item_func_not_all::print(String *str)
/*
Special NOP (No OPeration) for ALL subquery it is like Item_func_not_all
- (return TRUE if underlaying sudquery do not return rows) but if subquery
+ (return TRUE if underlying subquery do not return rows) but if subquery
returns some rows it return same value as argument (TRUE/FALSE).
*/
longlong Item_func_nop_all::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value= args[0]->val();
+ longlong value= args[0]->val_int();
/*
- return FALSE if there was records in underlaying select in max/min
- optimisation (SAME/ANY subquery)
+ return FALSE if there was records in underlying select in max/min
+ optimization (SAME/ANY subquery)
*/
if (empty_underlying_subquery())
return 0;
@@ -208,12 +210,26 @@ void Item_bool_func2::fix_length_and_dec()
if (!args[0] || !args[1])
return;
+ /*
+ We allow to convert to Unicode character sets in some cases.
+ The conditions when conversion is possible are:
+ - arguments A and B have different charsets
+ - A wins according to coercibility rules
+ - character set of A is superset for character set of B
+
+ If all of the above is true, then it's possible to convert
+ B into the character set of A, and then compare according
+ to the collation of A.
+ */
+
+
DTCollation coll;
if (args[0]->result_type() == STRING_RESULT &&
args[1]->result_type() == STRING_RESULT &&
agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV))
return;
-
+
+
// Make a special case of compare with fields to get nicer DATE comparisons
if (functype() == LIKE_FUNC) // Disable conversion in case of LIKE function.
@@ -221,30 +237,35 @@ void Item_bool_func2::fix_length_and_dec()
set_cmp_func();
return;
}
-
- if (args[0]->type() == FIELD_ITEM)
+
+ if (!thd->is_context_analysis_only())
{
- Field *field=((Item_field*) args[0])->field;
- if (field->can_be_compared_as_longlong())
+ Item *real_item= args[0]->real_item();
+ if (real_item->type() == FIELD_ITEM)
{
- if (convert_constant_item(thd, field,&args[1]))
+ Field *field=((Item_field*) real_item)->field;
+ if (field->can_be_compared_as_longlong())
{
- cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
- INT_RESULT); // Works for all types.
- return;
+ if (convert_constant_item(thd, field,&args[1]))
+ {
+ cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
+ INT_RESULT); // Works for all types.
+ return;
+ }
}
}
- }
- if (args[1]->type() == FIELD_ITEM)
- {
- Field *field=((Item_field*) args[1])->field;
- if (field->can_be_compared_as_longlong())
+ real_item= args[1]->real_item();
+ if (real_item->type() == FIELD_ITEM /* && !real_item->const_item() */)
{
- if (convert_constant_item(thd, field,&args[0]))
+ Field *field=((Item_field*) real_item)->field;
+ if (field->can_be_compared_as_longlong())
{
- cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
- INT_RESULT); // Works for all types.
- return;
+ if (convert_constant_item(thd, field,&args[0]))
+ {
+ cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
+ INT_RESULT); // Works for all types.
+ return;
+ }
}
}
}
@@ -257,7 +278,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
owner= item;
func= comparator_matrix[type]
[test(owner->functype() == Item_func::EQUAL_FUNC)];
- if (type == ROW_RESULT)
+ switch (type) {
+ case ROW_RESULT:
{
uint n= (*a)->cols();
if (n != (*b)->cols())
@@ -277,8 +299,9 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
}
comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
}
+ break;
}
- else if (type == STRING_RESULT)
+ case STRING_RESULT:
{
/*
We must set cmp_charset here as we may be called from for an automatic
@@ -300,15 +323,28 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
func= &Arg_comparator::compare_binary_string;
else if (func == &Arg_comparator::compare_e_string)
func= &Arg_comparator::compare_e_binary_string;
+
+ /*
+ As this is binary compassion, mark all fields that they can't be
+ transformed. Otherwise we would get into trouble with comparisons
+ like:
+ WHERE col= 'j' AND col LIKE BINARY 'j'
+ which would be transformed to:
+ WHERE col= 'j'
+ */
+ (*a)->transform(&Item::set_no_const_sub, (byte*) 0);
+ (*b)->transform(&Item::set_no_const_sub, (byte*) 0);
}
+ break;
}
- else if (type == INT_RESULT)
+ case INT_RESULT:
{
if (func == &Arg_comparator::compare_int_signed)
{
if ((*a)->unsigned_flag)
- func= ((*b)->unsigned_flag)? &Arg_comparator::compare_int_unsigned :
- &Arg_comparator::compare_int_unsigned_signed;
+ func= (((*b)->unsigned_flag)?
+ &Arg_comparator::compare_int_unsigned :
+ &Arg_comparator::compare_int_unsigned_signed);
else if ((*b)->unsigned_flag)
func= &Arg_comparator::compare_int_signed_unsigned;
}
@@ -317,6 +353,13 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
if ((*a)->unsigned_flag ^ (*b)->unsigned_flag)
func= &Arg_comparator::compare_e_int_diff_signedness;
}
+ break;
+ }
+ case DECIMAL_RESULT:
+ case REAL_RESULT:
+ break;
+ default:
+ DBUG_ASSERT(0);
}
return 0;
}
@@ -400,10 +443,10 @@ int Arg_comparator::compare_real()
performing the comparison.
*/
volatile double val1, val2;
- val1= (*a)->val();
+ val1= (*a)->val_real();
if (!(*a)->null_value)
{
- val2= (*b)->val();
+ val2= (*b)->val_real();
if (!(*b)->null_value)
{
owner->null_value= 0;
@@ -416,15 +459,43 @@ int Arg_comparator::compare_real()
return -1;
}
+int Arg_comparator::compare_decimal()
+{
+ my_decimal value1;
+ my_decimal *val1= (*a)->val_decimal(&value1);
+ if (!(*a)->null_value)
+ {
+ my_decimal value2;
+ my_decimal *val2= (*b)->val_decimal(&value2);
+ if (!(*b)->null_value)
+ {
+ owner->null_value= 0;
+ return my_decimal_cmp(val1, val2);
+ }
+ }
+ owner->null_value= 1;
+ return -1;
+}
+
int Arg_comparator::compare_e_real()
{
- double val1= (*a)->val();
- double val2= (*b)->val();
+ double val1= (*a)->val_real();
+ double val2= (*b)->val_real();
if ((*a)->null_value || (*b)->null_value)
return test((*a)->null_value && (*b)->null_value);
return test(val1 == val2);
}
+int Arg_comparator::compare_e_decimal()
+{
+ my_decimal value1, value2;
+ my_decimal *val1= (*a)->val_decimal(&value1);
+ my_decimal *val2= (*b)->val_decimal(&value2);
+ if ((*a)->null_value || (*b)->null_value)
+ return test((*a)->null_value && (*b)->null_value);
+ return test(my_decimal_cmp(val1, val2) == 0);
+}
+
int Arg_comparator::compare_int_signed()
{
longlong val1= (*a)->val_int();
@@ -543,19 +614,38 @@ int Arg_comparator::compare_e_int_diff_signedness()
int Arg_comparator::compare_row()
{
int res= 0;
+ bool was_null= 0;
(*a)->bring_value();
(*b)->bring_value();
uint n= (*a)->cols();
for (uint i= 0; i<n; i++)
{
- if ((res= comparators[i].compare()))
- return res;
+ res= comparators[i].compare();
if (owner->null_value)
- return -1;
+ {
+ // NULL was compared
+ if (owner->abort_on_null)
+ return -1; // We do not need correct NULL returning
+ was_null= 1;
+ owner->null_value= 0;
+ res= 0; // continue comparison (maybe we will meet explicit difference)
+ }
+ else if (res)
+ return res;
}
- return res;
+ if (was_null)
+ {
+ /*
+ There was NULL(s) in comparison in some parts, but there was not
+ explicit difference in other parts, so we have to return NULL
+ */
+ owner->null_value= 1;
+ return -1;
+ }
+ return 0;
}
+
int Arg_comparator::compare_e_row()
{
(*a)->bring_value();
@@ -570,11 +660,9 @@ int Arg_comparator::compare_e_row()
}
-bool Item_in_optimizer::fix_left(THD *thd,
- struct st_table_list *tables,
- Item **ref)
+bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
{
- if (!args[0]->fixed && args[0]->fix_fields(thd, tables, args) ||
+ if (!args[0]->fixed && args[0]->fix_fields(thd, args) ||
!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
return 1;
@@ -583,7 +671,7 @@ bool Item_in_optimizer::fix_left(THD *thd,
If it is preparation PS only then we do not know values of parameters =>
cant't get there values and do not need that values.
*/
- if (! thd->current_arena->is_stmt_prepare())
+ if (!thd->stmt_arena->is_stmt_prepare())
cache->store(args[0]);
if (cache->cols() == 1)
{
@@ -611,22 +699,21 @@ bool Item_in_optimizer::fix_left(THD *thd,
}
-bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
- Item ** ref)
+bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
- if (fix_left(thd, tables, ref))
- return 1;
+ if (fix_left(thd, ref))
+ return TRUE;
if (args[0]->maybe_null)
maybe_null=1;
- if (!args[1]->fixed && args[1]->fix_fields(thd, tables, args+1))
- return 1;
+ if (!args[1]->fixed && args[1]->fix_fields(thd, args+1))
+ return TRUE;
Item_in_subselect * sub= (Item_in_subselect *)args[1];
if (args[0]->cols() != sub->engine->cols())
{
my_error(ER_OPERAND_COLUMNS, MYF(0), args[0]->cols());
- return 1;
+ return TRUE;
}
if (args[1]->maybe_null)
maybe_null=1;
@@ -635,7 +722,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
not_null_tables_cache|= args[1]->not_null_tables();
const_item_cache&= args[1]->const_item();
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -648,7 +735,7 @@ longlong Item_in_optimizer::val_int()
null_value= 1;
return 0;
}
- longlong tmp= args[1]->val_int_result();
+ bool tmp= args[1]->val_bool_result();
null_value= args[1]->null_value;
return tmp;
}
@@ -757,6 +844,8 @@ longlong Item_func_strcmp::val_int()
void Item_func_interval::fix_length_and_dec()
{
+ use_decimal_comparison= (row->el(0)->result_type() == DECIMAL_RESULT) ||
+ (row->el(0)->result_type() == INT_RESULT);
if (row->cols() > 8)
{
bool consts=1;
@@ -767,10 +856,41 @@ void Item_func_interval::fix_length_and_dec()
}
if (consts &&
- (intervals=(double*) sql_alloc(sizeof(double)*(row->cols()-1))))
+ (intervals=
+ (interval_range*) sql_alloc(sizeof(interval_range)*(row->cols()-1))))
{
- for (uint i=1 ; i < row->cols(); i++)
- intervals[i-1]=row->el(i)->val();
+ if (use_decimal_comparison)
+ {
+ for (uint i=1 ; i < row->cols(); i++)
+ {
+ Item *el= row->el(i);
+ interval_range *range= intervals + (i-1);
+ if ((el->result_type() == DECIMAL_RESULT) ||
+ (el->result_type() == INT_RESULT))
+ {
+ range->type= DECIMAL_RESULT;
+ range->dec.init();
+ my_decimal *dec= el->val_decimal(&range->dec);
+ if (dec != &range->dec)
+ {
+ range->dec= *dec;
+ range->dec.fix_buffer_pointer();
+ }
+ }
+ else
+ {
+ range->type= REAL_RESULT;
+ range->dbl= el->val_real();
+ }
+ }
+ }
+ else
+ {
+ for (uint i=1 ; i < row->cols(); i++)
+ {
+ intervals[i-1].dbl= row->el(i)->val_real();
+ }
+ }
}
}
maybe_null= 0;
@@ -783,20 +903,43 @@ void Item_func_interval::fix_length_and_dec()
/*
- return -1 if null value,
- 0 if lower than lowest
- 1 - arg_count-1 if between args[n] and args[n+1]
- arg_count if higher than biggest argument
+ Execute Item_func_interval()
+
+ SYNOPSIS
+ Item_func_interval::val_int()
+
+ NOTES
+ If we are doing a decimal comparison, we are
+ evaluating the first item twice.
+
+ RETURN
+ -1 if null value,
+ 0 if lower than lowest
+ 1 - arg_count-1 if between args[n] and args[n+1]
+ arg_count if higher than biggest argument
*/
longlong Item_func_interval::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value= row->el(0)->val();
+ double value;
+ my_decimal dec_buf, *dec= NULL;
uint i;
- if (row->el(0)->null_value)
- return -1; // -1 if null
+ if (use_decimal_comparison)
+ {
+ dec= row->el(0)->val_decimal(&dec_buf);
+ if (row->el(0)->null_value)
+ return -1;
+ my_decimal2double(E_DEC_FATAL_ERROR, dec, &value);
+ }
+ else
+ {
+ value= row->el(0)->val_real();
+ if (row->el(0)->null_value)
+ return -1;
+ }
+
if (intervals)
{ // Use binary search to find interval
uint start,end;
@@ -805,17 +948,40 @@ longlong Item_func_interval::val_int()
while (start != end)
{
uint mid= (start + end + 1) / 2;
- if (intervals[mid] <= value)
+ interval_range *range= intervals + mid;
+ my_bool cmp_result;
+ /*
+ The values in the range intervall may have different types,
+ Only do a decimal comparision of the first argument is a decimal
+ and we are comparing against a decimal
+ */
+ if (dec && range->type == DECIMAL_RESULT)
+ cmp_result= my_decimal_cmp(&range->dec, dec) <= 0;
+ else
+ cmp_result= (range->dbl <= value);
+ if (cmp_result)
start= mid;
else
end= mid - 1;
}
- return (value < intervals[start]) ? 0 : start + 1;
+ interval_range *range= intervals+start;
+ return ((dec && range->type == DECIMAL_RESULT) ?
+ my_decimal_cmp(dec, &range->dec) < 0 :
+ value < range->dbl) ? 0 : start + 1;
}
for (i=1 ; i < row->cols() ; i++)
{
- if (row->el(i)->val() > value)
+ Item *el= row->el(i);
+ if (use_decimal_comparison &&
+ ((el->result_type() == DECIMAL_RESULT) ||
+ (el->result_type() == INT_RESULT)))
+ {
+ my_decimal e_dec_buf, *e_dec= row->el(i)->val_decimal(&e_dec_buf);
+ if (my_decimal_cmp(e_dec, dec) > 0)
+ return i-1;
+ }
+ else if (row->el(i)->val_real() > value)
return i-1;
}
return i-1;
@@ -851,10 +1017,9 @@ longlong Item_func_interval::val_int()
1 got error
*/
-bool Item_func_between::fix_fields(THD *thd, struct st_table_list *tables,
- Item **ref)
+bool Item_func_between::fix_fields(THD *thd, Item **ref)
{
- if (Item_func_opt_neg::fix_fields(thd, tables, ref))
+ if (Item_func_opt_neg::fix_fields(thd, ref))
return 1;
/* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
@@ -877,7 +1042,7 @@ void Item_func_between::fix_length_and_dec()
/*
As some compare functions are generated after sql_yacc,
- we have to check for out of memory conditons here
+ we have to check for out of memory conditions here
*/
if (!args[0] || !args[1] || !args[2])
return;
@@ -887,14 +1052,15 @@ void Item_func_between::fix_length_and_dec()
return;
/*
- Make a special case of compare with date/time and longlong fields.
+ Make a special ease of compare with date/time and longlong fields.
They are compared as integers, so for const item this time-consuming
conversion can be done only once, not for every single comparison
*/
if (args[0]->type() == FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
- if (field->can_be_compared_as_longlong())
+ if (!thd->is_context_analysis_only() &&
+ field->can_be_compared_as_longlong())
{
/*
The following can't be recoded with || as convert_constant_item
@@ -939,7 +1105,7 @@ longlong Item_func_between::val_int()
}
else if (cmp_type == INT_RESULT)
{
- longlong value=args[0]->val_int(),a,b;
+ longlong value=args[0]->val_int(), a, b;
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
a=args[1]->val_int();
@@ -957,13 +1123,31 @@ longlong Item_func_between::val_int()
null_value= value >= a;
}
}
+ else if (cmp_type == DECIMAL_RESULT)
+ {
+ my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf),
+ a_buf, *a_dec, b_buf, *b_dec;
+ if ((null_value=args[0]->null_value))
+ return 0; /* purecov: inspected */
+ a_dec= args[1]->val_decimal(&a_buf);
+ b_dec= args[2]->val_decimal(&b_buf);
+ if (!args[1]->null_value && !args[2]->null_value)
+ return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 &&
+ my_decimal_cmp(dec, b_dec) <= 0) != negated);
+ if (args[1]->null_value && args[2]->null_value)
+ null_value=1;
+ else if (args[1]->null_value)
+ null_value= (my_decimal_cmp(dec, b_dec) <= 0);
+ else
+ null_value= (my_decimal_cmp(dec, a_dec) >= 0);
+ }
else
{
- double value=args[0]->val(),a,b;
+ double value= args[0]->val_real(),a,b;
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
- a=args[1]->val();
- b=args[2]->val();
+ a= args[1]->val_real();
+ b= args[2]->val_real();
if (!args[1]->null_value && !args[2]->null_value)
return (longlong) ((value >= a && value <= b) != negated);
if (args[1]->null_value && args[2]->null_value)
@@ -997,20 +1181,41 @@ void Item_func_between::print(String *str)
void
Item_func_ifnull::fix_length_and_dec()
{
+ agg_result_type(&hybrid_type, args, 2);
maybe_null=args[1]->maybe_null;
- max_length=max(args[0]->max_length,args[1]->max_length);
- decimals=max(args[0]->decimals,args[1]->decimals);
- agg_result_type(&cached_result_type, args, 2);
- if (cached_result_type == STRING_RESULT)
+ decimals= max(args[0]->decimals, args[1]->decimals);
+ max_length= (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT) ?
+ (max(args[0]->max_length - args[0]->decimals,
+ args[1]->max_length - args[1]->decimals) + decimals) :
+ max(args[0]->max_length, args[1]->max_length);
+
+ switch (hybrid_type) {
+ case STRING_RESULT:
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
- else if (cached_result_type != REAL_RESULT)
+ break;
+ case DECIMAL_RESULT:
+ case REAL_RESULT:
+ break;
+ case INT_RESULT:
decimals= 0;
-
+ break;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
cached_field_type= args[0]->field_type();
if (cached_field_type != args[1]->field_type())
cached_field_type= Item_func::field_type();
}
+
+uint Item_func_ifnull::decimal_precision() const
+{
+ int max_int_part=max(args[0]->decimal_int_part(),args[1]->decimal_int_part());
+ return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+}
+
+
enum_field_types Item_func_ifnull::field_type() const
{
return cached_field_type;
@@ -1022,23 +1227,23 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table)
}
double
-Item_func_ifnull::val()
+Item_func_ifnull::real_op()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if (!args[0]->null_value)
{
null_value=0;
return value;
}
- value=args[1]->val();
+ value= args[1]->val_real();
if ((null_value=args[1]->null_value))
return 0.0;
return value;
}
longlong
-Item_func_ifnull::val_int()
+Item_func_ifnull::int_op()
{
DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int();
@@ -1053,8 +1258,25 @@ Item_func_ifnull::val_int()
return value;
}
+
+my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed == 1);
+ my_decimal *value= args[0]->val_decimal(decimal_value);
+ if (!args[0]->null_value)
+ {
+ null_value= 0;
+ return value;
+ }
+ value= args[1]->val_decimal(decimal_value);
+ if ((null_value= args[1]->null_value))
+ return 0;
+ return value;
+}
+
+
String *
-Item_func_ifnull::val_str(String *str)
+Item_func_ifnull::str_op(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str);
@@ -1100,12 +1322,12 @@ Item_func_ifnull::val_str(String *str)
*/
bool
-Item_func_if::fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
+Item_func_if::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
args[0]->top_level_item();
- if (Item_func::fix_fields(thd, tlist, ref))
+ if (Item_func::fix_fields(thd, ref))
return 1;
not_null_tables_cache= (args[1]->not_null_tables() &
@@ -1119,8 +1341,8 @@ void
Item_func_if::fix_length_and_dec()
{
maybe_null=args[1]->maybe_null || args[2]->maybe_null;
- max_length=max(args[1]->max_length,args[2]->max_length);
- decimals=max(args[1]->decimals,args[2]->decimals);
+ 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]->const_item() && args[1]->null_value;
@@ -1142,22 +1364,35 @@ Item_func_if::fix_length_and_dec()
if (cached_result_type == STRING_RESULT)
{
if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV))
- return;
+ return;
}
else
{
collation.set(&my_charset_bin); // Number
}
}
+ max_length=
+ (cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT) ?
+ (max(args[1]->max_length - args[1]->decimals,
+ args[2]->max_length - args[2]->decimals) + decimals) :
+ max(args[1]->max_length, args[2]->max_length);
+}
+
+
+uint Item_func_if::decimal_precision() const
+{
+ int precision=(max(args[1]->decimal_int_part(),args[2]->decimal_int_part())+
+ decimals);
+ return min(precision, DECIMAL_MAX_PRECISION);
}
double
-Item_func_if::val()
+Item_func_if::val_real()
{
DBUG_ASSERT(fixed == 1);
- Item *arg= args[0]->val_int() ? args[1] : args[2];
- double value=arg->val();
+ Item *arg= args[0]->val_bool() ? args[1] : args[2];
+ double value= arg->val_real();
null_value=arg->null_value;
return value;
}
@@ -1166,7 +1401,7 @@ longlong
Item_func_if::val_int()
{
DBUG_ASSERT(fixed == 1);
- Item *arg= args[0]->val_int() ? args[1] : args[2];
+ Item *arg= args[0]->val_bool() ? args[1] : args[2];
longlong value=arg->val_int();
null_value=arg->null_value;
return value;
@@ -1176,7 +1411,7 @@ String *
Item_func_if::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- Item *arg= args[0]->val_int() ? args[1] : args[2];
+ Item *arg= args[0]->val_bool() ? args[1] : args[2];
String *res=arg->val_str(str);
if (res)
res->set_charset(collation.collation);
@@ -1185,6 +1420,17 @@ Item_func_if::val_str(String *str)
}
+my_decimal *
+Item_func_if::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed == 1);
+ Item *arg= args[0]->val_bool() ? args[1] : args[2];
+ my_decimal *value= arg->val_decimal(decimal_value);
+ null_value= arg->null_value;
+ return value;
+}
+
+
void
Item_func_nullif::fix_length_and_dec()
{
@@ -1194,13 +1440,15 @@ Item_func_nullif::fix_length_and_dec()
{
max_length=args[0]->max_length;
decimals=args[0]->decimals;
- agg_result_type(&cached_result_type, args, 2);
+ unsigned_flag= args[0]->unsigned_flag;
+ cached_result_type= args[0]->result_type();
if (cached_result_type == STRING_RESULT &&
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV))
return;
}
}
+
/*
nullif () returns NULL if arguments are equal, else it returns the
first argument.
@@ -1209,7 +1457,7 @@ Item_func_nullif::fix_length_and_dec()
*/
double
-Item_func_nullif::val()
+Item_func_nullif::val_real()
{
DBUG_ASSERT(fixed == 1);
double value;
@@ -1218,7 +1466,7 @@ Item_func_nullif::val()
null_value=1;
return 0.0;
}
- value=args[0]->val();
+ value= args[0]->val_real();
null_value=args[0]->null_value;
return value;
}
@@ -1254,6 +1502,22 @@ Item_func_nullif::val_str(String *str)
}
+my_decimal *
+Item_func_nullif::val_decimal(my_decimal * decimal_value)
+{
+ DBUG_ASSERT(fixed == 1);
+ my_decimal *res;
+ if (!cmp.compare())
+ {
+ null_value=1;
+ return 0;
+ }
+ res= args[0]->val_decimal(decimal_value);
+ null_value= args[0]->null_value;
+ return res;
+}
+
+
bool
Item_func_nullif::is_null()
{
@@ -1267,16 +1531,18 @@ Item_func_nullif::is_null()
Item *Item_func_case::find_item(String *str)
{
- String *first_expr_str,*tmp;
+ String *first_expr_str, *tmp;
+ my_decimal *first_expr_dec, first_expr_dec_val;
longlong first_expr_int;
double first_expr_real;
char buff[MAX_FIELD_WIDTH];
String buff_str(buff,sizeof(buff),default_charset());
-
+
/* These will be initialized later */
LINT_INIT(first_expr_str);
LINT_INIT(first_expr_int);
LINT_INIT(first_expr_real);
+ LINT_INIT(first_expr_dec);
if (first_expr_num != -1)
{
@@ -1293,13 +1559,18 @@ Item *Item_func_case::find_item(String *str)
return else_expr_num != -1 ? args[else_expr_num] : 0;
break;
case REAL_RESULT:
- first_expr_real= args[first_expr_num]->val();
+ first_expr_real= args[first_expr_num]->val_real();
if (args[first_expr_num]->null_value)
return else_expr_num != -1 ? args[else_expr_num] : 0;
break;
+ case DECIMAL_RESULT:
+ first_expr_dec= args[first_expr_num]->val_decimal(&first_expr_dec_val);
+ if (args[first_expr_num]->null_value)
+ return else_expr_num != -1 ? args[else_expr_num] : 0;
+ break;
case ROW_RESULT:
default:
- // This case should never be choosen
+ // This case should never be chosen
DBUG_ASSERT(0);
break;
}
@@ -1311,7 +1582,7 @@ Item *Item_func_case::find_item(String *str)
if (first_expr_num == -1)
{
// No expression between CASE and the first WHEN
- if (args[i]->val_int())
+ if (args[i]->val_bool())
return args[i+1];
continue;
}
@@ -1326,12 +1597,19 @@ Item *Item_func_case::find_item(String *str)
return args[i+1];
break;
case REAL_RESULT:
- if (args[i]->val()==first_expr_real && !args[i]->null_value)
+ if (args[i]->val_real() == first_expr_real && !args[i]->null_value)
+ return args[i+1];
+ break;
+ case DECIMAL_RESULT:
+ {
+ my_decimal value;
+ if (my_decimal_cmp(args[i]->val_decimal(&value), first_expr_dec) == 0)
return args[i+1];
break;
+ }
case ROW_RESULT:
default:
- // This case should never be choosen
+ // This case should never be chosen
DBUG_ASSERT(0);
break;
}
@@ -1341,7 +1619,6 @@ Item *Item_func_case::find_item(String *str)
}
-
String *Item_func_case::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -1378,7 +1655,7 @@ longlong Item_func_case::val_int()
return res;
}
-double Item_func_case::val()
+double Item_func_case::val_real()
{
DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
@@ -1391,11 +1668,51 @@ double Item_func_case::val()
null_value=1;
return 0;
}
- res=item->val();
+ res= item->val_real();
null_value=item->null_value;
return res;
}
+
+my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed == 1);
+ char buff[MAX_FIELD_WIDTH];
+ String dummy_str(buff, sizeof(buff), default_charset());
+ Item *item= find_item(&dummy_str);
+ my_decimal *res;
+
+ if (!item)
+ {
+ null_value=1;
+ return 0;
+ }
+
+ res= item->val_decimal(decimal_value);
+ null_value= item->null_value;
+ return res;
+}
+
+
+bool Item_func_case::fix_fields(THD *thd, Item **ref)
+{
+ /*
+ buff should match stack usage from
+ Item_func_case::val_int() -> Item_func_case::find_item()
+ */
+ char buff[MAX_FIELD_WIDTH*2+sizeof(String)*2+sizeof(String*)*2+sizeof(double)*2+sizeof(longlong)*2];
+ bool res= Item_func::fix_fields(thd, ref);
+ /*
+ Call check_stack_overrun after fix_fields to be sure that stack variable
+ is not optimized away
+ */
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
+ return TRUE; // Fatal error flag is set!
+ return res;
+}
+
+
+
void Item_func_case::fix_length_and_dec()
{
Item **agg;
@@ -1404,8 +1721,10 @@ void Item_func_case::fix_length_and_dec()
if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
return;
- // Aggregate all THEN and ELSE expression types
- // and collations when string result
+ /*
+ Aggregate all THEN and ELSE expression types
+ and collations when string result
+ */
for (nagg= 0 ; nagg < ncases/2 ; nagg++)
agg[nagg]= args[nagg*2+1];
@@ -1432,7 +1751,7 @@ void Item_func_case::fix_length_and_dec()
agg_cmp_type(&cmp_type, agg, nagg);
if ((cmp_type == STRING_RESULT) &&
agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV))
- return;
+ return;
}
if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
@@ -1453,6 +1772,18 @@ void Item_func_case::fix_length_and_dec()
}
+uint Item_func_case::decimal_precision() const
+{
+ int max_int_part=0;
+ for (uint i=0 ; i < ncases ; i+=2)
+ set_if_bigger(max_int_part, args[i+1]->decimal_int_part());
+
+ if (else_expr_num != -1)
+ set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part());
+ return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+}
+
+
/* TODO: Fix this so that it prints the whole CASE expression */
void Item_func_case::print(String *str)
@@ -1484,7 +1815,7 @@ void Item_func_case::print(String *str)
Coalesce - return first not NULL argument.
*/
-String *Item_func_coalesce::val_str(String *str)
+String *Item_func_coalesce::str_op(String *str)
{
DBUG_ASSERT(fixed == 1);
null_value=0;
@@ -1498,7 +1829,7 @@ String *Item_func_coalesce::val_str(String *str)
return 0;
}
-longlong Item_func_coalesce::val_int()
+longlong Item_func_coalesce::int_op()
{
DBUG_ASSERT(fixed == 1);
null_value=0;
@@ -1512,13 +1843,13 @@ longlong Item_func_coalesce::val_int()
return 0;
}
-double Item_func_coalesce::val()
+double Item_func_coalesce::real_op()
{
DBUG_ASSERT(fixed == 1);
null_value=0;
for (uint i=0 ; i < arg_count ; i++)
{
- double res=args[i]->val();
+ double res= args[i]->val_real();
if (!args[i]->null_value)
return res;
}
@@ -1527,20 +1858,44 @@ double Item_func_coalesce::val()
}
-void Item_func_coalesce::fix_length_and_dec()
+my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
{
- max_length= 0;
- decimals= 0;
- agg_result_type(&cached_result_type, args, arg_count);
- for (uint i=0 ; i < arg_count ; i++)
+ DBUG_ASSERT(fixed == 1);
+ null_value= 0;
+ for (uint i= 0; i < arg_count; i++)
{
- set_if_bigger(max_length,args[i]->max_length);
- set_if_bigger(decimals,args[i]->decimals);
+ my_decimal *res= args[i]->val_decimal(decimal_value);
+ if (!args[i]->null_value)
+ return res;
}
- if (cached_result_type == STRING_RESULT)
+ null_value=1;
+ return 0;
+}
+
+
+void Item_func_coalesce::fix_length_and_dec()
+{
+ agg_result_type(&hybrid_type, args, arg_count);
+ switch (hybrid_type) {
+ case STRING_RESULT:
+ count_only_length();
+ decimals= NOT_FIXED_DEC;
agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV);
- else if (cached_result_type != REAL_RESULT)
+ break;
+ case DECIMAL_RESULT:
+ count_decimal_length();
+ break;
+ case REAL_RESULT:
+ count_real_length();
+ break;
+ case INT_RESULT:
+ count_only_length();
decimals= 0;
+ break;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
}
/****************************************************************************
@@ -1557,11 +1912,24 @@ static int cmp_double(void *cmp_arg, double *a,double *b)
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
-static int cmp_row(void *cmp_arg, cmp_item_row* a, cmp_item_row* b)
+static int cmp_row(void *cmp_arg, cmp_item_row *a, cmp_item_row *b)
{
return a->compare(b);
}
+
+static int cmp_decimal(void *cmp_arg, my_decimal *a, my_decimal *b)
+{
+ /*
+ We need call of fixing buffer pointer, because fast sort just copy
+ decimal buffers in memory and pointers left pointing on old buffer place
+ */
+ a->fix_buffer_pointer();
+ b->fix_buffer_pointer();
+ return my_decimal_cmp(a, b);
+}
+
+
int in_vector::find(Item *item)
{
byte *result=get_value(item);
@@ -1683,28 +2051,58 @@ in_double::in_double(uint elements)
void in_double::set(uint pos,Item *item)
{
- ((double*) base)[pos]=item->val();
+ ((double*) base)[pos]= item->val_real();
}
byte *in_double::get_value(Item *item)
{
- tmp= item->val();
+ tmp= item->val_real();
if (item->null_value)
return 0; /* purecov: inspected */
return (byte*) &tmp;
}
-cmp_item* cmp_item::get_comparator(Item *item)
+
+in_decimal::in_decimal(uint elements)
+ :in_vector(elements, sizeof(my_decimal),(qsort2_cmp) cmp_decimal, 0)
+{}
+
+
+void in_decimal::set(uint pos, Item *item)
+{
+ /* as far as 'item' is constant, we can store reference on my_decimal */
+ my_decimal *dec= ((my_decimal *)base) + pos;
+ dec->len= DECIMAL_BUFF_LENGTH;
+ dec->fix_buffer_pointer();
+ my_decimal *res= item->val_decimal(dec);
+ if (res != dec)
+ my_decimal2decimal(res, dec);
+}
+
+
+byte *in_decimal::get_value(Item *item)
+{
+ my_decimal *result= item->val_decimal(&val);
+ if (item->null_value)
+ return 0;
+ return (byte *)result;
+}
+
+
+cmp_item* cmp_item::get_comparator(Item_result type,
+ CHARSET_INFO *cs)
{
- switch (item->result_type()) {
+ switch (type) {
case STRING_RESULT:
- return new cmp_item_sort_string(item->collation.collation);
+ return new cmp_item_sort_string(cs);
case INT_RESULT:
return new cmp_item_int;
case REAL_RESULT:
return new cmp_item_real;
case ROW_RESULT:
return new cmp_item_row;
+ case DECIMAL_RESULT:
+ return new cmp_item_decimal;
default:
DBUG_ASSERT(0);
break;
@@ -1737,7 +2135,7 @@ cmp_item* cmp_item_row::make_same()
cmp_item_row::~cmp_item_row()
{
DBUG_ENTER("~cmp_item_row");
- DBUG_PRINT("enter",("this: %lx", this));
+ DBUG_PRINT("enter",("this: 0x%lx", this));
if (comparators)
{
for (uint i= 0; i < n; i++)
@@ -1763,7 +2161,9 @@ void cmp_item_row::store_value(Item *item)
for (uint i=0; i < n; i++)
{
if (!comparators[i])
- if (!(comparators[i]= cmp_item::get_comparator(item->el(i))))
+ if (!(comparators[i]=
+ cmp_item::get_comparator(item->el(i)->result_type(),
+ item->el(i)->collation.collation)))
break; // new failed
comparators[i]->store_value(item->el(i));
item->null_value|= item->el(i)->null_value;
@@ -1834,6 +2234,37 @@ int cmp_item_row::compare(cmp_item *c)
}
+void cmp_item_decimal::store_value(Item *item)
+{
+ my_decimal *val= item->val_decimal(&value);
+ /* val may be zero if item is nnull */
+ if (val && val != &value)
+ my_decimal2decimal(val, &value);
+}
+
+
+int cmp_item_decimal::cmp(Item *arg)
+{
+ my_decimal tmp_buf, *tmp= arg->val_decimal(&tmp_buf);
+ if (arg->null_value)
+ return 1;
+ return my_decimal_cmp(&value, tmp);
+}
+
+
+int cmp_item_decimal::compare(cmp_item *arg)
+{
+ cmp_item_decimal *cmp= (cmp_item_decimal*) arg;
+ return my_decimal_cmp(&value, &cmp->value);
+}
+
+
+cmp_item* cmp_item_decimal::make_same()
+{
+ return new cmp_item_decimal();
+}
+
+
bool Item_func_in::nulls_in_row()
{
Item **arg,**arg_end;
@@ -1876,11 +2307,11 @@ bool Item_func_in::nulls_in_row()
*/
bool
-Item_func_in::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_func_in::fix_fields(THD *thd, Item **ref)
{
Item **arg, **arg_end;
- if (Item_func_opt_neg::fix_fields(thd, tables, ref))
+ if (Item_func_opt_neg::fix_fields(thd, ref))
return 1;
/* not_null_tables_cache == union(T1(e),union(T1(ei))) */
@@ -1900,7 +2331,7 @@ static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{
return cs->coll->strnncollsp(cs,
(uchar *) x->ptr(),x->length(),
- (uchar *) y->ptr(),y->length());
+ (uchar *) y->ptr(),y->length(), 0);
}
@@ -1917,7 +2348,13 @@ void Item_func_in::fix_length_and_dec()
return;
for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
- const_itm&= arg[0]->const_item();
+ {
+ if (!arg[0]->const_item())
+ {
+ const_itm= 0;
+ break;
+ }
+ }
/*
Row item with NULLs inside can return NULL or FALSE =>
@@ -1939,6 +2376,9 @@ void Item_func_in::fix_length_and_dec()
case ROW_RESULT:
array= new in_row(arg_count-1, args[0]);
break;
+ case DECIMAL_RESULT:
+ array= new in_decimal(arg_count - 1);
+ break;
default:
DBUG_ASSERT(0);
return;
@@ -1960,7 +2400,7 @@ void Item_func_in::fix_length_and_dec()
}
else
{
- in_item= cmp_item::get_comparator(args[0]);
+ in_item= cmp_item::get_comparator(cmp_type, cmp_collation.collation);
if (cmp_type == STRING_RESULT)
in_item->cmp_charset= cmp_collation.collation;
}
@@ -2064,7 +2504,7 @@ void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
bool
-Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_cond::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
List_iterator<Item> li(list);
@@ -2073,15 +2513,30 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
char buff[sizeof(char*)]; // Max local vars in function
#endif
not_null_tables_cache= used_tables_cache= 0;
- const_item_cache= 0;
+ const_item_cache= 1;
/*
and_table_cache is the value that Item_cond_or() returns for
not_null_tables()
*/
and_tables_cache= ~(table_map) 0;
- if (check_stack_overrun(thd, buff))
- return 1; // Fatal error flag is set!
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
+ return TRUE; // Fatal error flag is set!
+ /*
+ The following optimization reduces the depth of an AND-OR tree.
+ E.g. a WHERE clause like
+ F1 AND (F2 AND (F2 AND F4))
+ is parsed into a tree with the same nested structure as defined
+ by braces. This optimization will transform such tree into
+ AND (F1, F2, F3, F4).
+ Trees of OR items are flattened as well:
+ ((F1 OR F2) OR (F3 OR F4)) => OR (F1, F2, F3, F4)
+ Items for removed AND/OR levels will dangle until the death of the
+ entire statement.
+ The optimization is currently prepared statements and stored procedures
+ friendly as it doesn't allocate any memory and its effects are durable
+ (i.e. do not depend on PS/SP arguments).
+ */
while ((item=li++))
{
table_map tmp_table_map;
@@ -2097,14 +2552,14 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
// item can be substituted in fix_fields
if ((!item->fixed &&
- item->fix_fields(thd, tables, li.ref())) ||
+ item->fix_fields(thd, li.ref())) ||
(item= *li.ref())->check_cols(1))
- return 1; /* purecov: inspected */
+ return TRUE; /* purecov: inspected */
used_tables_cache|= item->used_tables();
tmp_table_map= item->not_null_tables();
not_null_tables_cache|= tmp_table_map;
and_tables_cache&= tmp_table_map;
- const_item_cache&= item->const_item();
+ const_item_cache&= item->const_item();
with_sum_func= with_sum_func || item->with_sum_func;
if (item->maybe_null)
maybe_null=1;
@@ -2112,7 +2567,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->lex->current_select->cond_count+= list.elements;
fix_length_and_dec();
fixed= 1;
- return 0;
+ return FALSE;
}
bool Item_cond::walk(Item_processor processor, byte *arg)
@@ -2127,6 +2582,66 @@ bool Item_cond::walk(Item_processor processor, byte *arg)
/*
+ Transform an Item_cond object with a transformer callback function
+
+ SYNOPSIS
+ transform()
+ transformer the transformer callback function to be applied to the nodes
+ of the tree of the object
+ arg parameter to be passed to the transformer
+
+ DESCRIPTION
+ The function recursively applies the transform method with the
+ same transformer to each member item of the condition list.
+ If the call of the method for a member item returns a new item
+ the old item is substituted for a new one.
+ After this the transform method is applied to the root node
+ of the Item_cond object.
+
+ RETURN VALUES
+ Item returned as the result of transformation of the root node
+*/
+
+Item *Item_cond::transform(Item_transformer transformer, byte *arg)
+{
+ List_iterator<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ {
+ Item *new_item= item->transform(transformer, arg);
+ if (!new_item)
+ return 0;
+ if (new_item != item)
+ li.replace(new_item);
+ }
+ return Item_func::transform(transformer, arg);
+}
+
+void Item_cond::traverse_cond(Cond_traverser traverser,
+ void *arg, traverse_order order)
+{
+ List_iterator<Item> li(list);
+ Item *item;
+
+ switch(order) {
+ case(PREFIX):
+ (*traverser)(this, arg);
+ while ((item= li++))
+ {
+ item->traverse_cond(traverser, arg, order);
+ }
+ (*traverser)(NULL, arg);
+ break;
+ case(POSTFIX):
+ while ((item= li++))
+ {
+ item->traverse_cond(traverser, arg, order);
+ }
+ (*traverser)(this, arg);
+ }
+}
+
+/*
Move SUM items out from item tree and replace with reference
SYNOPSIS
@@ -2173,7 +2688,7 @@ void Item_cond::update_used_tables()
{
item->update_used_tables();
used_tables_cache|= item->used_tables();
- const_item_cache&= item->const_item();
+ const_item_cache&= item->const_item();
}
}
@@ -2214,7 +2729,7 @@ void Item_cond::neg_arguments(THD *thd)
/*
- Evalution of AND(expr, expr, expr ...)
+ Evaluation of AND(expr, expr, expr ...)
NOTES:
abort_if_null is set for AND expressions for which we don't care if the
@@ -2239,7 +2754,7 @@ longlong Item_cond_and::val_int()
null_value= 0;
while ((item=li++))
{
- if (item->val_int() == 0)
+ if (!item->val_bool())
{
if (abort_on_null || !(null_value= item->null_value))
return 0; // return FALSE
@@ -2257,7 +2772,7 @@ longlong Item_cond_or::val_int()
null_value=0;
while ((item=li++))
{
- if (item->val_int() != 0)
+ if (item->val_bool())
{
null_value=0;
return 1;
@@ -2424,17 +2939,17 @@ Item_func::optimize_type Item_func_like::select_optimize() const
}
-bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
+bool Item_func_like::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
- if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
- escape_item->fix_fields(thd, tlist, &escape_item))
- return 1;
+ if (Item_bool_func2::fix_fields(thd, ref) ||
+ escape_item->fix_fields(thd, &escape_item))
+ return TRUE;
if (!escape_item->const_during_execution())
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
- return 1;
+ return TRUE;
}
if (escape_item->const_item())
@@ -2477,7 +2992,7 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
}
else
escape= '\\';
-
+
/*
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.
@@ -2487,7 +3002,7 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
String* res2 = args[1]->val_str(&tmp_value2);
if (!res2)
- return 0; // Null argument
+ return FALSE; // Null argument
const size_t len = res2->length();
const char* first = res2->ptr();
@@ -2508,10 +3023,11 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
if (canDoTurboBM)
{
pattern = first + 1;
- pattern_len = len - 2;
+ pattern_len = (int) len - 2;
DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
- int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
- alphabet_size));
+ int *suff = (int*) thd->alloc((int) (sizeof(int)*
+ ((pattern_len + 1)*2+
+ alphabet_size)));
bmGs = suff + pattern_len + 1;
bmBc = bmGs + pattern_len + 1;
turboBM_compute_good_suffix_shifts(suff);
@@ -2520,26 +3036,26 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
}
}
}
- return 0;
+ return FALSE;
}
#ifdef USE_REGEX
bool
-Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_func_regex::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
if ((!args[0]->fixed &&
- args[0]->fix_fields(thd, tables, args)) || args[0]->check_cols(1) ||
- (!args[1]->fixed &&
- args[1]->fix_fields(thd,tables, args + 1)) || args[1]->check_cols(1))
- return 1; /* purecov: inspected */
+ args[0]->fix_fields(thd, args)) || args[0]->check_cols(1) ||
+ (!args[1]->fixed &&
+ args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1))
+ return TRUE; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length= 1;
decimals= 0;
if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV))
- return 1;
+ return TRUE;
used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
not_null_tables_cache= (args[0]->not_null_tables() |
@@ -2553,7 +3069,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (args[1]->null_value)
{ // Will always return NULL
maybe_null=1;
- return 0;
+ return FALSE;
}
int error;
if ((error= regcomp(&preg,res->c_ptr(),
@@ -2564,8 +3080,8 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
cmp_collation.collation)))
{
(void) regerror(error,&preg,buff,sizeof(buff));
- my_printf_error(ER_REGEXP_ERROR,ER(ER_REGEXP_ERROR),MYF(0),buff);
- return 1;
+ my_error(ER_REGEXP_ERROR, MYF(0), buff);
+ return TRUE;
}
regex_compiled=regex_is_const=1;
maybe_null=args[0]->maybe_null;
@@ -2573,7 +3089,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
else
maybe_null=1;
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -2608,7 +3124,7 @@ longlong Item_func_regex::val_int()
regfree(&preg);
regex_compiled=0;
}
- if (regcomp(&preg,res2->c_ptr(),
+ if (regcomp(&preg,res2->c_ptr_safe(),
((cmp_collation.collation->state &
(MY_CS_BINSORT | MY_CS_CSSORT)) ?
REG_EXTENDED | REG_NOSUB :
@@ -2905,7 +3421,7 @@ longlong Item_cond_xor::val_int()
/*
Apply NOT transformation to the item and return a new one.
- SYNPOSIS
+ SYNOPSIS
neg_transformer()
thd thread handler
@@ -3016,3 +3532,287 @@ Item *Item_bool_rowready_func2::negated_item()
DBUG_ASSERT(0);
return 0;
}
+
+Item_equal::Item_equal(Item_field *f1, Item_field *f2)
+ : Item_bool_func(), const_item(0), eval_item(0), cond_false(0)
+{
+ const_item_cache= 0;
+ fields.push_back(f1);
+ fields.push_back(f2);
+}
+
+Item_equal::Item_equal(Item *c, Item_field *f)
+ : Item_bool_func(), eval_item(0), cond_false(0)
+{
+ const_item_cache= 0;
+ fields.push_back(f);
+ const_item= c;
+}
+
+
+Item_equal::Item_equal(Item_equal *item_equal)
+ : Item_bool_func(), eval_item(0), cond_false(0)
+{
+ const_item_cache= 0;
+ List_iterator_fast<Item_field> li(item_equal->fields);
+ Item_field *item;
+ while ((item= li++))
+ {
+ fields.push_back(item);
+ }
+ const_item= item_equal->const_item;
+ cond_false= item_equal->cond_false;
+}
+
+void Item_equal::add(Item *c)
+{
+ if (cond_false)
+ return;
+ if (!const_item)
+ {
+ const_item= c;
+ return;
+ }
+ Item_func_eq *func= new Item_func_eq(c, const_item);
+ func->set_cmp_func();
+ func->quick_fix_field();
+ cond_false = !(func->val_int());
+}
+
+void Item_equal::add(Item_field *f)
+{
+ fields.push_back(f);
+}
+
+uint Item_equal::members()
+{
+ return fields.elements;
+}
+
+
+/*
+ Check whether a field is referred in the multiple equality
+
+ SYNOPSIS
+ contains()
+ field field whose occurrence is to be checked
+
+ DESCRIPTION
+ The function checks whether field is occurred in the Item_equal object
+
+ RETURN VALUES
+ 1 if nultiple equality contains a reference to field
+ 0 otherwise
+*/
+
+bool Item_equal::contains(Field *field)
+{
+ List_iterator_fast<Item_field> it(fields);
+ Item_field *item;
+ while ((item= it++))
+ {
+ if (field->eq(item->field))
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ Join members of another Item_equal object
+
+ SYNOPSIS
+ merge()
+ item multiple equality whose members are to be joined
+
+ DESCRIPTION
+ The function actually merges two multiple equalities.
+ After this operation the Item_equal object additionally contains
+ the field items of another item of the type Item_equal.
+ If the optional constant items are not equal the cond_false flag is
+ set to 1.
+
+ RETURN VALUES
+ none
+*/
+
+void Item_equal::merge(Item_equal *item)
+{
+ fields.concat(&item->fields);
+ Item *c= item->const_item;
+ if (c)
+ {
+ /*
+ The flag cond_false will be set to 1 after this, if
+ the multiple equality already contains a constant and its
+ value is not equal to the value of c.
+ */
+ add(const_item);
+ }
+ cond_false|= item->cond_false;
+}
+
+
+/*
+ Order field items in multiple equality according to a sorting criteria
+
+ SYNOPSIS
+ sort()
+ cmp function to compare field item
+ arg context extra parameter for the cmp function
+
+ DESCRIPTION
+ The function perform ordering of the field items in the Item_equal
+ object according to the criteria determined by the cmp callback parameter.
+ If cmp(item_field1,item_field2,arg)<0 than item_field1 must be
+ placed after item_fiel2.
+
+ IMPLEMENTATION
+ The function sorts field items by the exchange sort algorithm.
+ The list of field items is looked through and whenever two neighboring
+ members follow in a wrong order they are swapped. This is performed
+ again and again until we get all members in a right order.
+
+ RETURN VALUES
+ None
+*/
+
+void Item_equal::sort(Item_field_cmpfunc cmp, void *arg)
+{
+ bool swap;
+ List_iterator<Item_field> it(fields);
+ do
+ {
+ Item_field *item1= it++;
+ Item_field **ref1= it.ref();
+ Item_field *item2;
+
+ swap= FALSE;
+ while ((item2= it++))
+ {
+ Item_field **ref2= it.ref();
+ if (cmp(item1, item2, arg) < 0)
+ {
+ Item_field *item= *ref1;
+ *ref1= *ref2;
+ *ref2= item;
+ swap= TRUE;
+ }
+ else
+ {
+ item1= item2;
+ ref1= ref2;
+ }
+ }
+ it.rewind();
+ } while (swap);
+}
+
+bool Item_equal::fix_fields(THD *thd, Item **ref)
+{
+ List_iterator_fast<Item_field> li(fields);
+ Item *item;
+ not_null_tables_cache= used_tables_cache= 0;
+ const_item_cache= 0;
+ while ((item=li++))
+ {
+ table_map tmp_table_map;
+ used_tables_cache|= item->used_tables();
+ tmp_table_map= item->not_null_tables();
+ not_null_tables_cache|= tmp_table_map;
+ if (item->maybe_null)
+ maybe_null=1;
+ }
+ fix_length_and_dec();
+ fixed= 1;
+ return 0;
+}
+
+void Item_equal::update_used_tables()
+{
+ List_iterator_fast<Item_field> li(fields);
+ Item *item;
+ not_null_tables_cache= used_tables_cache= 0;
+ if ((const_item_cache= cond_false))
+ return;
+ while ((item=li++))
+ {
+ item->update_used_tables();
+ used_tables_cache|= item->used_tables();
+ const_item_cache&= item->const_item();
+ }
+}
+
+longlong Item_equal::val_int()
+{
+ if (cond_false)
+ return 0;
+ List_iterator_fast<Item_field> it(fields);
+ Item *item= const_item ? const_item : it++;
+ if ((null_value= item->null_value))
+ return 0;
+ eval_item->store_value(item);
+ while ((item= it++))
+ {
+ if ((null_value= item->null_value) || eval_item->cmp(item))
+ return 0;
+ }
+ return 1;
+}
+
+void Item_equal::fix_length_and_dec()
+{
+ Item *item= const_item ? const_item : get_first();
+ eval_item= cmp_item::get_comparator(item->result_type(),
+ item->collation.collation);
+ if (item->result_type() == STRING_RESULT)
+ eval_item->cmp_charset= cmp_collation.collation;
+}
+
+bool Item_equal::walk(Item_processor processor, byte *arg)
+{
+ List_iterator_fast<Item_field> it(fields);
+ Item *item;
+ while ((item= it++))
+ if (item->walk(processor, arg))
+ return 1;
+ return Item_func::walk(processor, arg);
+}
+
+Item *Item_equal::transform(Item_transformer transformer, byte *arg)
+{
+ List_iterator<Item_field> it(fields);
+ Item *item;
+ while ((item= it++))
+ {
+ Item *new_item= item->transform(transformer, arg);
+ if (!new_item)
+ return 0;
+ if (new_item != item)
+ it.replace((Item_field *) new_item);
+ }
+ return Item_func::transform(transformer, arg);
+}
+
+void Item_equal::print(String *str)
+{
+ str->append(func_name());
+ str->append('(');
+ List_iterator_fast<Item_field> it(fields);
+ Item *item;
+ if (const_item)
+ const_item->print(str);
+ else
+ {
+ item= it++;
+ item->print(str);
+ }
+ while ((item= it++))
+ {
+ str->append(',');
+ str->append(' ');
+ item->print(str);
+ }
+ str->append(')');
+}
+
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 741ae90108a..09a0fa8c357 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -27,6 +27,8 @@ class Arg_comparator;
typedef int (Arg_comparator::*arg_cmp_func)();
+typedef int (*Item_field_cmpfunc)(Item_field *f1, Item_field *f2, void *arg);
+
class Arg_comparator: public Sql_alloc
{
Item **a, **b;
@@ -65,6 +67,7 @@ public:
int compare_string(); // compare args[0] & args[1]
int compare_binary_string(); // compare args[0] & args[1]
int compare_real(); // compare args[0] & args[1]
+ int compare_decimal(); // compare args[0] & args[1]
int compare_int_signed(); // compare args[0] & args[1]
int compare_int_signed_unsigned();
int compare_int_unsigned_signed();
@@ -73,11 +76,12 @@ public:
int compare_e_string(); // compare args[0] & args[1]
int compare_e_binary_string(); // compare args[0] & args[1]
int compare_e_real(); // compare args[0] & args[1]
+ int compare_e_decimal(); // compare args[0] & args[1]
int compare_e_int(); // compare args[0] & args[1]
int compare_e_int_diff_signedness();
int compare_e_row(); // compare args[0] & args[1]
- static arg_cmp_func comparator_matrix [4][2];
+ static arg_cmp_func comparator_matrix [5][2];
friend class Item_func;
};
@@ -91,6 +95,7 @@ public:
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
bool is_bool_func() { return 1; }
void fix_length_and_dec() { decimals=0; max_length=1; }
+ uint decimal_precision() const { return 1; }
};
class Item_cache;
@@ -103,8 +108,8 @@ public:
Item_in_optimizer(Item *a, Item_in_subselect *b):
Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), save_cache(0)
{}
- bool fix_fields(THD *, struct st_table_list *, Item **);
- bool fix_left(THD *thd, struct st_table_list *tables, Item **ref);
+ bool fix_fields(THD *, Item **);
+ bool fix_left(THD *thd, Item **ref);
bool is_null();
/*
Item_in_optimizer item is special boolean function. On value request
@@ -188,10 +193,11 @@ class Item_bool_func2 :public Item_int_func
protected:
Arg_comparator cmp;
String tmp_value1,tmp_value2;
+ bool abort_on_null;
public:
Item_bool_func2(Item *a,Item *b)
- :Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
+ :Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), abort_on_null(FALSE) {}
void fix_length_and_dec();
void set_cmp_func()
{
@@ -204,6 +210,8 @@ public:
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
+ uint decimal_precision() const { return 1; }
+ void top_level_item() { abort_on_null=1; }
friend class Arg_comparator;
};
@@ -230,9 +238,44 @@ public:
};
class Item_maxmin_subselect;
+
+/*
+ The class Item_func_trig_cond is used for guarded predicates
+ which are employed only for internal purposes.
+ A guarded predicates is an object consisting of an a regular or
+ a guarded predicate P and a pointer to a boolean guard variable g.
+ A guarded predicate P/g is evaluated to true if the value of the
+ guard g is false, otherwise it is evaluated to the same value that
+ the predicate P: val(P/g)= g ? val(P):true.
+ Guarded predicates allow us to include predicates into a conjunction
+ conditionally. Currently they are utilized for pushed down predicates
+ in queries with outer join operations.
+
+ In the future, probably, it makes sense to extend this class to
+ the objects consisting of three elements: a predicate P, a pointer
+ to a variable g and a firing value s with following evaluation
+ rule: val(P/g,s)= g==s? val(P) : true. It will allow us to build only
+ one item for the objects of the form P/g1/g2...
+
+ Objects of this class are built only for query execution after
+ the execution plan has been already selected. That's why this
+ class needs only val_int out of generic methods.
+*/
+
+class Item_func_trig_cond: public Item_bool_func
+{
+ bool *trig_var;
+public:
+ Item_func_trig_cond(Item *a, bool *f) : Item_bool_func(a) { trig_var= f; }
+ longlong val_int() { return *trig_var ? args[0]->val_int() : 1; }
+ enum Functype functype() const { return TRIG_COND_FUNC; };
+ const char *func_name() const { return "trigcond"; };
+ bool const_item() const { return FALSE; }
+};
+
class Item_func_not_all :public Item_func_not
{
- /* allow to check presence od values in max/min optimisation */
+ /* allow to check presence of values in max/min optimization */
Item_sum_hybrid *test_sum_item;
Item_maxmin_subselect *test_sub_item;
@@ -400,10 +443,12 @@ public:
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
enum Functype functype() const { return BETWEEN; }
const char *func_name() const { return "between"; }
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void fix_length_and_dec();
void print(String *str);
+ bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
+ uint decimal_precision() const { return 1; }
};
@@ -414,13 +459,22 @@ public:
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
const char *func_name() const { return "strcmp"; }
+ void print(String *str) { Item_func::print(str); }
};
+struct interval_range
+{
+ Item_result type;
+ double dbl;
+ my_decimal dec;
+};
+
class Item_func_interval :public Item_int_func
{
Item_row *row;
- double *intervals;
+ my_bool use_decimal_comparison;
+ interval_range *intervals;
public:
Item_func_interval(Item_row *a)
:Item_int_func(a),row(a),intervals(0)
@@ -430,27 +484,44 @@ public:
longlong val_int();
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
+ uint decimal_precision() const { return 2; }
};
-class Item_func_ifnull :public Item_func
+class Item_func_coalesce :public Item_func_numhybrid
{
- enum Item_result cached_result_type;
+protected:
+ Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
+public:
+ Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {}
+ double real_op();
+ longlong int_op();
+ String *str_op(String *);
+ my_decimal *decimal_op(my_decimal *);
+ void fix_length_and_dec();
+ void find_num_type() {}
+ enum Item_result result_type () const { return hybrid_type; }
+ const char *func_name() const { return "coalesce"; }
+ table_map not_null_tables() const { return 0; }
+};
+
+
+class Item_func_ifnull :public Item_func_coalesce
+{
+protected:
enum_field_types cached_field_type;
bool field_type_defined;
public:
- Item_func_ifnull(Item *a,Item *b)
- :Item_func(a,b), cached_result_type(INT_RESULT)
- {}
- double val();
- longlong val_int();
- String *val_str(String *str);
- enum Item_result result_type () const { return cached_result_type; }
+ Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {}
+ double real_op();
+ longlong int_op();
+ String *str_op(String *str);
+ my_decimal *decimal_op(my_decimal *);
enum_field_types field_type() const;
void fix_length_and_dec();
const char *func_name() const { return "ifnull"; }
Field *tmp_table_field(TABLE *table);
- table_map not_null_tables() const { return 0; }
+ uint decimal_precision() const;
};
@@ -461,12 +532,14 @@ public:
Item_func_if(Item *a,Item *b,Item *c)
:Item_func(a,b,c), cached_result_type(INT_RESULT)
{}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
+ my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return cached_result_type; }
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void fix_length_and_dec();
+ uint decimal_precision() const;
const char *func_name() const { return "if"; }
};
@@ -478,11 +551,13 @@ public:
Item_func_nullif(Item *a,Item *b)
:Item_bool_func2(a,b), cached_result_type(INT_RESULT)
{}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
+ my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return cached_result_type; }
void fix_length_and_dec();
+ uint decimal_precision() const { return args[0]->decimal_precision(); }
const char *func_name() const { return "nullif"; }
void print(String *str) { Item_func::print(str); }
table_map not_null_tables() const { return 0; }
@@ -490,23 +565,6 @@ public:
};
-class Item_func_coalesce :public Item_func
-{
- enum Item_result cached_result_type;
-public:
- Item_func_coalesce(List<Item> &list)
- :Item_func(list),cached_result_type(INT_RESULT)
- {}
- double val();
- longlong val_int();
- String *val_str(String *);
- void fix_length_and_dec();
- enum Item_result result_type () const { return cached_result_type; }
- const char *func_name() const { return "coalesce"; }
- table_map not_null_tables() const { return 0; }
-};
-
-
class Item_func_case :public Item_func
{
int first_expr_num, else_expr_num;
@@ -519,7 +577,7 @@ public:
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
:Item_func(), first_expr_num(-1), else_expr_num(-1),
cached_result_type(INT_RESULT)
- {
+ {
ncases= list.elements;
if (first_expr_arg)
{
@@ -533,10 +591,13 @@ public:
}
set_arguments(list);
}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *);
+ my_decimal *val_decimal(my_decimal *);
+ bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
+ uint decimal_precision() const;
table_map not_null_tables() const { return 0; }
enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; }
@@ -576,7 +637,7 @@ public:
class in_string :public in_vector
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmp;
public:
in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
@@ -603,6 +664,16 @@ public:
byte *get_value(Item *item);
};
+class in_decimal :public in_vector
+{
+ my_decimal val;
+public:
+ in_decimal(uint elements);
+ void set(uint pos, Item *item);
+ byte *get_value(Item *item);
+};
+
+
/*
** Classes for easy comparing of non const items
*/
@@ -617,7 +688,7 @@ public:
virtual int cmp(Item *item)= 0;
// for optimized IN with row
virtual int compare(cmp_item *item)= 0;
- static cmp_item* get_comparator(Item *);
+ static cmp_item* get_comparator(Item_result type, CHARSET_INFO *cs);
virtual cmp_item *make_same()= 0;
virtual void store_value_by_template(cmp_item *tmpl, Item *item)
{
@@ -638,7 +709,7 @@ public:
class cmp_item_sort_string :public cmp_item_string
{
protected:
- char value_buff[80];
+ char value_buff[STRING_BUFFER_USUAL_SIZE];
String value;
public:
cmp_item_sort_string(CHARSET_INFO *cs):
@@ -650,7 +721,7 @@ public:
}
int cmp(Item *arg)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmp(buff, sizeof(buff), cmp_charset), *res;
if (!(res= arg->val_str(&tmp)))
return 1; /* Can't be right */
@@ -690,11 +761,11 @@ class cmp_item_real :public cmp_item
public:
void store_value(Item *item)
{
- value= item->val();
+ value= item->val_real();
}
int cmp(Item *arg)
{
- return value != arg->val();
+ return value != arg->val_real();
}
int compare(cmp_item *c)
{
@@ -704,6 +775,18 @@ public:
cmp_item *make_same();
};
+
+class cmp_item_decimal :public cmp_item
+{
+ my_decimal value;
+public:
+ void store_value(Item *item);
+ int cmp(Item *arg);
+ int compare(cmp_item *c);
+ cmp_item *make_same();
+};
+
+
class cmp_item_row :public cmp_item
{
cmp_item **comparators;
@@ -776,8 +859,9 @@ class Item_func_in :public Item_func_opt_neg
allowed_arg_cols= 0; // Fetch this value from first argument
}
longlong val_int();
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void fix_length_and_dec();
+ uint decimal_precision() const { return 1; }
void cleanup()
{
DBUG_ENTER("Item_func_in::cleanup");
@@ -863,8 +947,9 @@ public:
class Item_func_isnotnull :public Item_bool_func
{
+ bool abort_on_null;
public:
- Item_func_isnotnull(Item *a) :Item_bool_func(a) {}
+ Item_func_isnotnull(Item *a) :Item_bool_func(a), abort_on_null(0) {}
longlong val_int();
enum Functype functype() const { return ISNOTNULL_FUNC; }
void fix_length_and_dec()
@@ -873,10 +958,12 @@ public:
}
const char *func_name() const { return "isnotnull"; }
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
- table_map not_null_tables() const { return 0; }
+ table_map not_null_tables() const
+ { return abort_on_null ? not_null_tables_cache : 0; }
Item *neg_transformer(THD *thd);
void print(String *str);
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
+ void top_level_item() { abort_on_null=1; }
};
@@ -910,7 +997,7 @@ public:
optimize_type select_optimize() const;
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; }
- bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
+ bool fix_fields(THD *thd, Item **ref);
};
#ifdef USE_REGEX
@@ -929,7 +1016,7 @@ public:
regex_compiled(0),regex_is_const(0) {}
void cleanup();
longlong val_int();
- bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
+ bool fix_fields(THD *thd, Item **ref);
const char *func_name() const { return "regexp"; }
void print(String *str) { print_op(str); }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
@@ -962,7 +1049,7 @@ public:
/* Item_cond() is only used to create top level items */
Item_cond(): Item_bool_func(), abort_on_null(1)
{ const_item_cache=0; }
- Item_cond(Item *i1,Item *i2)
+ Item_cond(Item *i1,Item *i2)
:Item_bool_func(), abort_on_null(0)
{
list.push_back(i1);
@@ -972,7 +1059,8 @@ public:
Item_cond(List<Item> &nlist)
:Item_bool_func(), list(nlist), abort_on_null(0) {}
bool add(Item *item) { return list.push_back(item); }
- bool fix_fields(THD *, struct st_table_list *, Item **ref);
+ void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
+ bool fix_fields(THD *, Item **ref);
enum Type type() const { return COND_ITEM; }
List<Item>* argument_list() { return &list; }
@@ -980,17 +1068,163 @@ public:
void update_used_tables();
void print(String *str);
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
- friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
+ friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
+ COND **conds);
void top_level_item() { abort_on_null=1; }
void copy_andor_arguments(THD *thd, Item_cond *item);
bool walk(Item_processor processor, byte *arg);
+ Item *transform(Item_transformer transformer, byte *arg);
+ void traverse_cond(Cond_traverser, void *arg, traverse_order order);
void neg_arguments(THD *thd);
};
+/*
+ The class Item_equal is used to represent conjunctions of equality
+ predicates of the form field1 = field2, and field=const in where
+ conditions and on expressions.
+
+ All equality predicates of the form field1=field2 contained in a
+ conjunction are substituted for a sequence of items of this class.
+ An item of this class Item_equal(f1,f2,...fk) represents a
+ multiple equality f1=f2=...=fk.
+
+ If a conjunction contains predicates f1=f2 and f2=f3, a new item of
+ this class is created Item_equal(f1,f2,f3) representing the multiple
+ equality f1=f2=f3 that substitutes the above equality predicates in
+ the conjunction.
+ A conjunction of the predicates f2=f1 and f3=f1 and f3=f2 will be
+ substituted for the item representing the same multiple equality
+ f1=f2=f3.
+ An item Item_equal(f1,f2) can appear instead of a conjunction of
+ f2=f1 and f1=f2, or instead of just the predicate f1=f2.
+
+ An item of the class Item_equal inherits equalities from outer
+ conjunctive levels.
+
+ Suppose we have a where condition of the following form:
+ WHERE f1=f2 AND f3=f4 AND f3=f5 AND ... AND (...OR (f1=f3 AND ...)).
+ In this case:
+ f1=f2 will be substituted for Item_equal(f1,f2);
+ f3=f4 and f3=f5 will be substituted for Item_equal(f3,f4,f5);
+ f1=f3 will be substituted for Item_equal(f1,f2,f3,f4,f5);
+
+ An object of the class Item_equal can contain an optional constant
+ item c. Then it represents a multiple equality of the form
+ c=f1=...=fk.
+
+ Objects of the class Item_equal are used for the following:
+
+ 1. An object Item_equal(t1.f1,...,tk.fk) allows us to consider any
+ pair of tables ti and tj as joined by an equi-condition.
+ Thus it provide us with additional access paths from table to table.
+
+ 2. An object Item_equal(t1.f1,...,tk.fk) is applied to deduce new
+ SARGable predicates:
+ f1=...=fk AND P(fi) => f1=...=fk AND P(fi) AND P(fj).
+ It also can give us additional index scans and can allow us to
+ improve selectivity estimates.
+
+ 3. An object Item_equal(t1.f1,...,tk.fk) is used to optimize the
+ selected execution plan for the query: if table ti is accessed
+ before the table tj then in any predicate P in the where condition
+ the occurrence of tj.fj is substituted for ti.fi. This can allow
+ an evaluation of the predicate at an earlier step.
+
+ When feature 1 is supported they say that join transitive closure
+ is employed.
+ When feature 2 is supported they say that search argument transitive
+ closure is employed.
+ Both features are usually supported by preprocessing original query and
+ adding additional predicates.
+ We do not just add predicates, we rather dynamically replace some
+ predicates that can not be used to access tables in the investigated
+ plan for those, obtained by substitution of some fields for equal fields,
+ that can be used.
+
+ Prepared Statements/Stored Procedures note: instances of class
+ Item_equal are created only at the time a PS/SP is executed and
+ are deleted in the end of execution. All changes made to these
+ objects need not be registered in the list of changes of the parse
+ tree and do not harm PS/SP re-execution.
+*/
+
+class Item_equal: public Item_bool_func
+{
+ List<Item_field> fields; /* list of equal field items */
+ Item *const_item; /* optional constant item equal to fields items */
+ cmp_item *eval_item;
+ bool cond_false;
+ DTCollation cmp_collation;
+public:
+ inline Item_equal()
+ : Item_bool_func(), const_item(0), eval_item(0), cond_false(0)
+ { const_item_cache=0 ;}
+ Item_equal(Item_field *f1, Item_field *f2);
+ Item_equal(Item *c, Item_field *f);
+ Item_equal(Item_equal *item_equal);
+ inline Item* get_const() { return const_item; }
+ void add(Item *c);
+ void add(Item_field *f);
+ uint members();
+ bool contains(Field *field);
+ Item_field* get_first() { return fields.head(); }
+ void merge(Item_equal *item);
+ enum Functype functype() const { return MULT_EQUAL_FUNC; }
+ longlong val_int();
+ const char *func_name() const { return "multiple equal"; }
+ optimize_type select_optimize() const { return OPTIMIZE_EQUAL; }
+ void sort(Item_field_cmpfunc cmp, void *arg);
+ friend class Item_equal_iterator;
+ void fix_length_and_dec();
+ bool fix_fields(THD *thd, Item **ref);
+ void update_used_tables();
+ bool walk(Item_processor processor, byte *arg);
+ Item *transform(Item_transformer transformer, byte *arg);
+ void print(String *str);
+ CHARSET_INFO *compare_collation()
+ { return fields.head()->collation.collation; }
+};
+
+class COND_EQUAL: public Sql_alloc
+{
+public:
+ uint max_members; /* max number of members the current level
+ list and all lower level lists */
+ COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
+ List<Item_equal> current_level; /* list of multiple equalities of
+ the current and level */
+ COND_EQUAL()
+ {
+ max_members= 0;
+ upper_levels= 0;
+ }
+};
+
+
+class Item_equal_iterator : public List_iterator_fast<Item_field>
+{
+public:
+ inline Item_equal_iterator(Item_equal &item_equal)
+ :List_iterator_fast<Item_field> (item_equal.fields)
+ {}
+ inline Item_field* operator++(int)
+ {
+ Item_field *item= (*(List_iterator_fast<Item_field> *) this)++;
+ return item;
+ }
+ inline void rewind(void)
+ {
+ List_iterator_fast<Item_field>::rewind();
+ }
+};
+
class Item_cond_and :public Item_cond
{
public:
+ COND_EQUAL cond_equal; /* contains list of Item_equal objects for
+ the current and level and reference
+ to multiple equalities of upper and levels */
Item_cond_and() :Item_cond() {}
Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
@@ -1033,7 +1267,7 @@ public:
/*
- XOR is Item_cond, not an Item_int_func bevause we could like to
+ XOR is Item_cond, not an Item_int_func because we could like to
optimize (a XOR b) later on. It's low prio, though
*/
@@ -1051,7 +1285,7 @@ public:
};
-/* Some usefull inline functions */
+/* Some useful inline functions */
inline Item *and_conds(Item *a, Item *b)
{
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 2b12a1310b9..342ef245a76 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -18,10 +18,6 @@
#include "mysql_priv.h"
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
Item *create_func_abs(Item* a)
{
return new Item_func_abs(a);
@@ -77,12 +73,13 @@ Item *create_func_connection_id(void)
{
THD *thd=current_thd;
thd->lex->safe_to_cache_query= 0;
- return new Item_int(NullS,(longlong)
- ((thd->slave_thread) ?
- thd->variables.pseudo_thread_id :
- thd->thread_id),
- 10);
-}
+ return new Item_static_int_func("connection_id()",
+ (longlong)
+ ((thd->slave_thread) ?
+ thd->variables.pseudo_thread_id :
+ thd->thread_id),
+ 10);
+}
Item *create_func_conv(Item* a, Item *b, Item *c)
{
@@ -112,7 +109,7 @@ Item *create_func_dayofmonth(Item* a)
Item *create_func_dayofweek(Item* a)
{
- return new Item_func_weekday(new Item_func_to_days(a),1);
+ return new Item_func_weekday(a, 1);
}
Item *create_func_dayofyear(Item* a)
@@ -122,7 +119,7 @@ Item *create_func_dayofyear(Item* a)
Item *create_func_dayname(Item* a)
{
- return new Item_func_dayname(new Item_func_to_days(a));
+ return new Item_func_dayname(a);
}
Item *create_func_degrees(Item *a)
@@ -264,6 +261,11 @@ Item *create_func_mod(Item* a, Item *b)
return new Item_func_mod(a,b);
}
+Item *create_func_name_const(Item *a, Item *b)
+{
+ return new Item_name_const(a,b);
+}
+
Item *create_func_monthname(Item* a)
{
return new Item_func_monthname(a);
@@ -292,7 +294,7 @@ Item *create_func_period_diff(Item* a, Item *b)
Item *create_func_pi(void)
{
- return new Item_real("pi()",M_PI,6,8);
+ return new Item_static_float_func("pi()", M_PI, 6, 8);
}
Item *create_func_pow(Item* a, Item *b)
@@ -302,20 +304,8 @@ Item *create_func_pow(Item* a, Item *b)
Item *create_func_current_user()
{
- THD *thd=current_thd;
- char buff[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
- uint length;
-
- thd->lex->safe_to_cache_query= 0;
- length= (uint) (strxmov(buff, thd->priv_user, "@", thd->priv_host, NullS) -
- buff);
- return new Item_string(NullS, thd->memdup(buff, length), length,
- system_charset_info);
-}
-
-Item *create_func_quarter(Item* a)
-{
- return new Item_func_quarter(a);
+ current_thd->lex->safe_to_cache_query= 0;
+ return new Item_func_user(TRUE);
}
Item *create_func_radians(Item *a)
@@ -369,6 +359,12 @@ Item *create_func_sha(Item* a)
return new Item_func_sha(a);
}
+Item *create_func_sleep(Item* a)
+{
+ current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ return new Item_func_sleep(a);
+}
+
Item *create_func_space(Item *a)
{
CHARSET_INFO *cs= current_thd->variables.collation_connection;
@@ -440,14 +436,14 @@ Item *create_func_uuid(void)
Item *create_func_version(void)
{
- return new Item_string(NullS,server_version,
+ return new Item_static_string_func("version()", server_version,
(uint) strlen(server_version),
system_charset_info, DERIVATION_SYSCONST);
}
Item *create_func_weekday(Item* a)
{
- return new Item_func_weekday(new Item_func_to_days(a),0);
+ return new Item_func_weekday(a, 0);
}
Item *create_func_year(Item* a)
@@ -462,7 +458,7 @@ Item *create_load_file(Item* a)
}
-Item *create_func_cast(Item *a, Cast_target cast_type, int len,
+Item *create_func_cast(Item *a, Cast_target cast_type, int len, int dec,
CHARSET_INFO *cs)
{
Item *res;
@@ -475,6 +471,9 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len,
case ITEM_CAST_DATE: res= new Item_date_typecast(a); break;
case ITEM_CAST_TIME: res= new Item_time_typecast(a); break;
case ITEM_CAST_DATETIME: res= new Item_datetime_typecast(a); break;
+ case ITEM_CAST_DECIMAL:
+ res= new Item_decimal_typecast(a, (len>0) ? len : 10, dec ? dec : 2);
+ break;
case ITEM_CAST_CHAR:
res= new Item_char_typecast(a, len, cs ? cs :
current_thd->variables.collation_connection);
diff --git a/sql/item_create.h b/sql/item_create.h
index faff6f45220..35db9be3c89 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -28,7 +28,8 @@ Item *create_func_bit_length(Item* a);
Item *create_func_coercibility(Item* a);
Item *create_func_ceiling(Item* a);
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_cast(Item *a, Cast_target cast_type, int len, int dec,
+ CHARSET_INFO *cs);
Item *create_func_connection_id(void);
Item *create_func_conv(Item* a, Item *b, Item *c);
Item *create_func_cos(Item* a);
@@ -64,6 +65,7 @@ Item *create_func_ltrim(Item* a);
Item *create_func_md5(Item* a);
Item *create_func_mod(Item* a, Item *b);
Item *create_func_monthname(Item* a);
+Item *create_func_name_const(Item *a, Item *b);
Item *create_func_nullif(Item* a, Item *b);
Item *create_func_oct(Item *);
Item *create_func_ord(Item* a);
@@ -72,7 +74,6 @@ Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b);
Item *create_func_current_user(void);
-Item *create_func_quarter(Item* a);
Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a);
Item *create_func_repeat(Item* a, Item *b);
@@ -83,6 +84,7 @@ Item *create_func_sec_to_time(Item* a);
Item *create_func_sign(Item* a);
Item *create_func_sin(Item* a);
Item *create_func_sha(Item* a);
+Item *create_func_sleep(Item* a);
Item *create_func_soundex(Item* a);
Item *create_func_space(Item *);
Item *create_func_sqrt(Item* a);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ebb200ec4da..518fb011e0f 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -28,6 +28,9 @@
#include <time.h>
#include <ft_global.h>
+#include "sp_head.h"
+#include "sp_rcontext.h"
+#include "sp.h"
bool check_reserved_words(LEX_STRING *name)
{
@@ -52,15 +55,16 @@ void Item_func::set_arguments(List<Item> &list)
{
allowed_arg_cols= 1;
arg_count=list.elements;
- if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
+ args= tmp_arg; // If 2 arguments
+ if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
{
- uint i=0;
List_iterator_fast<Item> li(list);
Item *item;
+ Item **save_args= args;
while ((item=li++))
{
- args[i++]= item;
+ *(save_args++)= item;
with_sum_func|=item->with_sum_func;
}
}
@@ -101,7 +105,6 @@ Item_func::Item_func(THD *thd, Item_func *item)
SYNOPSIS:
fix_fields()
thd Thread object
- tables List of all open tables involved in the query
ref Pointer to where this object is used. This reference
is used if we want to replace this object with another
one (for example in the summary functions).
@@ -125,12 +128,12 @@ Item_func::Item_func(THD *thd, Item_func *item)
item.
RETURN VALUES
- 0 ok
- 1 Got error. Stored with my_error().
+ FALSE ok
+ TRUE Got error. Stored with my_error().
*/
bool
-Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_func::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
Item **arg,**arg_end;
@@ -141,8 +144,8 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
used_tables_cache= not_null_tables_cache= 0;
const_item_cache=1;
- if (check_stack_overrun(thd, buff))
- return 1; // Fatal error if flag is set!
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
+ return TRUE; // Fatal error if flag is set!
if (arg_count)
{ // Print purify happy
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
@@ -152,9 +155,8 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
We can't yet set item to *arg as fix_fields may change *arg
We shouldn't call fix_fields() twice, so check 'fixed' field first
*/
- if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
- return 1; /* purecov: inspected */
-
+ if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
+ return TRUE; /* purecov: inspected */
item= *arg;
if (allowed_arg_cols)
@@ -180,10 +182,10 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
}
fix_length_and_dec();
- if (thd->net.last_errno) // An error inside fix_length_and_dec occured
- return 1;
+ if (thd->net.report_error) // An error inside fix_length_and_dec occured
+ return TRUE;
fixed= 1;
- return 0;
+ return FALSE;
}
bool Item_func::walk (Item_processor processor, byte *argument)
@@ -200,6 +202,71 @@ bool Item_func::walk (Item_processor processor, byte *argument)
return (this->*processor)(argument);
}
+void Item_func::traverse_cond(Cond_traverser traverser,
+ void *argument, traverse_order order)
+{
+ if (arg_count)
+ {
+ Item **arg,**arg_end;
+
+ switch (order) {
+ case(PREFIX):
+ (*traverser)(this, argument);
+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
+ {
+ (*arg)->traverse_cond(traverser, argument, order);
+ }
+ break;
+ case (POSTFIX):
+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
+ {
+ (*arg)->traverse_cond(traverser, argument, order);
+ }
+ (*traverser)(this, argument);
+ }
+ }
+}
+
+
+
+/*
+ Transform an Item_func object with a transformer callback function
+
+ SYNOPSIS
+ transform()
+ transformer the transformer callback function to be applied to the nodes
+ of the tree of the object
+ argument parameter to be passed to the transformer
+
+ DESCRIPTION
+ The function recursively applies the transform method with the
+ same transformer to each argument the function.
+ If the call of the method for a member item returns a new item
+ the old item is substituted for a new one.
+ After this the transform method is applied to the root node
+ of the Item_func object.
+
+ RETURN VALUES
+ Item returned as the result of transformation of the root node
+*/
+
+Item *Item_func::transform(Item_transformer transformer, byte *argument)
+{
+ if (arg_count)
+ {
+ Item **arg,**arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
+ {
+ Item *new_item= (*arg)->transform(transformer, argument);
+ if (!new_item)
+ return 0;
+ if (*arg != new_item)
+ current_thd->change_item_tree(arg, new_item);
+ }
+ }
+ return (this->*transformer)(argument);
+}
+
/* See comments in Item_cmp_func::split_sum_func() */
@@ -289,6 +356,7 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const
return 1;
}
+
Field *Item_func::tmp_table_field(TABLE *t_arg)
{
Field *res;
@@ -307,25 +375,35 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
res= new Field_double(max_length, maybe_null, name, t_arg, decimals);
break;
case STRING_RESULT:
- if (max_length > 255)
- res= new Field_blob(max_length, maybe_null, name, t_arg, collation.collation);
- else
- res= new Field_string(max_length, maybe_null, name, t_arg, collation.collation);
+ res= make_string_field(t_arg);
+ break;
+ case DECIMAL_RESULT:
+ res= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(),
+ decimals,
+ unsigned_flag),
+ maybe_null, name, t_arg, decimals, unsigned_flag);
break;
case ROW_RESULT:
default:
- // This case should never be choosen
+ // This case should never be chosen
DBUG_ASSERT(0);
break;
}
return res;
}
+my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed);
+ int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
+ return decimal_value;
+}
+
String *Item_real_func::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals, &my_charset_bin);
@@ -333,38 +411,121 @@ String *Item_real_func::val_str(String *str)
}
-String *Item_num_func::val_str(String *str)
+my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value)
{
- DBUG_ASSERT(fixed == 1);
- if (hybrid_type == INT_RESULT)
+ DBUG_ASSERT(fixed);
+ double nr= val_real();
+ if (null_value)
+ return 0; /* purecov: inspected */
+ double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
+ return decimal_value;
+}
+
+
+void Item_func::fix_num_length_and_dec()
+{
+ decimals= 0;
+ for (uint i=0 ; i < arg_count ; i++)
{
- longlong nr=val_int();
- if (null_value)
- return 0; /* purecov: inspected */
- if (!unsigned_flag)
- str->set(nr,&my_charset_bin);
- else
- str->set((ulonglong) nr,&my_charset_bin);
+ set_if_bigger(decimals, args[i]->decimals);
}
- else
+ max_length= float_length(decimals);
+}
+
+
+void Item_func_numhybrid::fix_num_length_and_dec()
+{}
+
+
+/*
+ Set max_length/decimals of function if function is fixed point and
+ result length/precision depends on argument ones
+
+ SYNOPSIS
+ Item_func::count_decimal_length()
+*/
+
+void Item_func::count_decimal_length()
+{
+ int max_int_part= 0;
+ decimals= 0;
+ unsigned_flag= 1;
+ for (uint i=0 ; i < arg_count ; i++)
{
- double nr=val();
- if (null_value)
- return 0; /* purecov: inspected */
- str->set(nr,decimals,&my_charset_bin);
+ set_if_bigger(decimals, args[i]->decimals);
+ set_if_bigger(max_int_part, args[i]->decimal_int_part());
+ set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
}
- return str;
+ int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
}
-void Item_func::fix_num_length_and_dec()
+/*
+ Set max_length of if it is maximum length of its arguments
+
+ SYNOPSIS
+ Item_func::count_only_length()
+*/
+
+void Item_func::count_only_length()
{
- decimals=0;
+ max_length= 0;
+ unsigned_flag= 0;
for (uint i=0 ; i < arg_count ; i++)
- set_if_bigger(decimals,args[i]->decimals);
- max_length=float_length(decimals);
+ {
+ set_if_bigger(max_length, args[i]->max_length);
+ set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
+ }
}
+
+/*
+ Set max_length/decimals of function if function is floating point and
+ result length/precision depends on argument ones
+
+ SYNOPSIS
+ Item_func::count_real_length()
+*/
+
+void Item_func::count_real_length()
+{
+ uint32 length= 0;
+ decimals= 0;
+ max_length= 0;
+ for (uint i=0 ; i < arg_count ; i++)
+ {
+ if (decimals != NOT_FIXED_DEC)
+ {
+ set_if_bigger(decimals, args[i]->decimals);
+ set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
+ }
+ set_if_bigger(max_length, args[i]->max_length);
+ }
+ if (decimals != NOT_FIXED_DEC)
+ {
+ max_length= length;
+ length+= decimals;
+ if (length < max_length) // If previous operation gave overflow
+ max_length= UINT_MAX32;
+ else
+ max_length= length;
+ }
+}
+
+
+
+void Item_func::signal_divide_by_null()
+{
+ THD *thd= current_thd;
+ if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO,
+ ER(ER_DIVISION_BY_ZERO));
+ null_value= 1;
+}
+
+
Item *Item_func::get_tmp_table_item(THD *thd)
{
if (!with_sum_func && !const_item())
@@ -385,45 +546,247 @@ String *Item_int_func::val_str(String *str)
return str;
}
+
/*
- Change from REAL_RESULT (default) to INT_RESULT if both arguments are
- integers
+ Check arguments here to determine result's type for a numeric
+ function of two arguments.
+
+ SYNOPSIS
+ Item_num_op::find_num_type()
*/
void Item_num_op::find_num_type(void)
{
- if (args[0]->result_type() == INT_RESULT &&
- args[1]->result_type() == INT_RESULT)
+ DBUG_ENTER("Item_num_op::find_num_type");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ DBUG_ASSERT(arg_count == 2);
+ Item_result r0= args[0]->result_type();
+ Item_result r1= args[1]->result_type();
+
+ if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
+ r0 == STRING_RESULT || r1 ==STRING_RESULT)
{
+ count_real_length();
+ max_length= float_length(decimals);
+ hybrid_type= REAL_RESULT;
+ }
+ else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT)
+ {
+ hybrid_type= DECIMAL_RESULT;
+ result_precision();
+ }
+ else
+ {
+ DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
+ decimals= 0;
hybrid_type=INT_RESULT;
- unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
+ result_precision();
}
+ DBUG_PRINT("info", ("Type: %s",
+ (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
+ hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ hybrid_type == INT_RESULT ? "INT_RESULT" :
+ "--ILLEGAL!!!--")));
+ DBUG_VOID_RETURN;
}
-String *Item_num_op::val_str(String *str)
+
+/*
+ Set result type for a numeric function of one argument
+ (can be also used by a numeric function of many arguments, if the result
+ type depends only on the first argument)
+
+ SYNOPSIS
+ Item_func_num1::find_num_type()
+*/
+
+void Item_func_num1::find_num_type()
+{
+ DBUG_ENTER("Item_func_num1::find_num_type");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ switch (hybrid_type= args[0]->result_type()) {
+ case INT_RESULT:
+ unsigned_flag= args[0]->unsigned_flag;
+ break;
+ case STRING_RESULT:
+ case REAL_RESULT:
+ hybrid_type= REAL_RESULT;
+ max_length= float_length(decimals);
+ break;
+ case DECIMAL_RESULT:
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ DBUG_PRINT("info", ("Type: %s",
+ (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
+ hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ hybrid_type == INT_RESULT ? "INT_RESULT" :
+ "--ILLEGAL!!!--")));
+ DBUG_VOID_RETURN;
+}
+
+
+void Item_func_num1::fix_num_length_and_dec()
+{
+ decimals= args[0]->decimals;
+ max_length= args[0]->max_length;
+}
+
+
+void Item_func_numhybrid::fix_length_and_dec()
+{
+ fix_num_length_and_dec();
+ find_num_type();
+}
+
+
+String *Item_func_numhybrid::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- if (hybrid_type == INT_RESULT)
+ switch (hybrid_type) {
+ case DECIMAL_RESULT:
{
- longlong nr=val_int();
+ my_decimal decimal_value, *val;
+ if (!(val= decimal_op(&decimal_value)))
+ return 0; // null is set
+ my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
+ my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
+ break;
+ }
+ case INT_RESULT:
+ {
+ longlong nr= int_op();
if (null_value)
return 0; /* purecov: inspected */
if (!unsigned_flag)
str->set(nr,&my_charset_bin);
else
str->set((ulonglong) nr,&my_charset_bin);
+ break;
}
- else
+ case REAL_RESULT:
{
- double nr=val();
+ double nr= real_op();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals,&my_charset_bin);
+ break;
+ }
+ case STRING_RESULT:
+ return str_op(&str_value);
+ default:
+ DBUG_ASSERT(0);
}
return str;
}
+double Item_func_numhybrid::val_real()
+{
+ DBUG_ASSERT(fixed == 1);
+ switch (hybrid_type) {
+ case DECIMAL_RESULT:
+ {
+ my_decimal decimal_value, *val;
+ double result;
+ if (!(val= decimal_op(&decimal_value)))
+ return 0.0; // null is set
+ my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
+ return result;
+ }
+ case INT_RESULT:
+ return (double)int_op();
+ case REAL_RESULT:
+ return real_op();
+ case STRING_RESULT:
+ {
+ char *end_not_used;
+ int err_not_used;
+ String *res= str_op(&str_value);
+ return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
+ &end_not_used, &err_not_used) : 0.0);
+ }
+ default:
+ DBUG_ASSERT(0);
+ }
+ return 0.0;
+}
+
+
+longlong Item_func_numhybrid::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ switch (hybrid_type) {
+ case DECIMAL_RESULT:
+ {
+ my_decimal decimal_value, *val;
+ if (!(val= decimal_op(&decimal_value)))
+ return 0; // null is set
+ longlong result;
+ my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
+ return result;
+ }
+ case INT_RESULT:
+ return int_op();
+ case REAL_RESULT:
+ return (longlong)real_op();
+ case STRING_RESULT:
+ {
+ int err_not_used;
+ String *res;
+ if (!(res= str_op(&str_value)))
+ return 0;
+
+ char *end= (char*) res->ptr() + res->length();
+ CHARSET_INFO *cs= str_value.charset();
+ return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
+ }
+ default:
+ DBUG_ASSERT(0);
+ }
+ return 0;
+}
+
+
+my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
+{
+ my_decimal *val= decimal_value;
+ DBUG_ASSERT(fixed == 1);
+ switch (hybrid_type) {
+ case DECIMAL_RESULT:
+ val= decimal_op(decimal_value);
+ break;
+ case INT_RESULT:
+ {
+ longlong result= int_op();
+ int2my_decimal(E_DEC_FATAL_ERROR, result, unsigned_flag, decimal_value);
+ break;
+ }
+ case REAL_RESULT:
+ {
+ double result= (double)real_op();
+ double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
+ break;
+ }
+ case STRING_RESULT:
+ {
+ String *res;
+ if (!(res= str_op(&str_value)))
+ return NULL;
+
+ str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
+ res->length(), res->charset(), decimal_value);
+ break;
+ }
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ return val;
+}
+
+
void Item_func_signed::print(String *str)
{
str->append("cast(", 5);
@@ -515,26 +878,121 @@ longlong Item_func_unsigned::val_int()
}
-double Item_func_plus::val()
+String *Item_decimal_typecast::val_str(String *str)
{
- DBUG_ASSERT(fixed == 1);
- double value=args[0]->val()+args[1]->val();
+ my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
+ if (null_value)
+ return NULL;
+ my_decimal2string(E_DEC_FATAL_ERROR, &tmp_buf, 0, 0, 0, str);
+ return str;
+}
+
+
+double Item_decimal_typecast::val_real()
+{
+ my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
+ double res;
+ if (null_value)
+ return 0.0;
+ my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res);
+ return res;
+}
+
+
+longlong Item_decimal_typecast::val_int()
+{
+ my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
+ longlong res;
+ if (null_value)
+ return 0;
+ my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res);
+ return res;
+}
+
+
+my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
+{
+ my_decimal tmp_buf, *tmp= args[0]->val_decimal(&tmp_buf);
+ if ((null_value= args[0]->null_value))
+ return NULL;
+ my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
+ return dec;
+}
+
+
+void Item_decimal_typecast::print(String *str)
+{
+ str->append("cast(", 5);
+ args[0]->print(str);
+ str->append(" as decimal)", 12);
+}
+
+
+double Item_func_plus::real_op()
+{
+ double value= args[0]->val_real() + args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
return value;
}
-longlong Item_func_plus::val_int()
+
+longlong Item_func_plus::int_op()
{
- DBUG_ASSERT(fixed == 1);
- if (hybrid_type == INT_RESULT)
- {
- longlong value=args[0]->val_int()+args[1]->val_int();
- if ((null_value=args[0]->null_value || args[1]->null_value))
- return 0;
- return value;
- }
- return (longlong) Item_func_plus::val();
+ longlong value=args[0]->val_int()+args[1]->val_int();
+ if ((null_value=args[0]->null_value || args[1]->null_value))
+ return 0;
+ return value;
+}
+
+
+/*
+ Calculate plus of two decimail's
+
+ SYNOPSIS
+ decimal_op()
+ decimal_value Buffer that can be used to store result
+
+ RETURN
+ 0 Value was NULL; In this case null_value is set
+ # Value of operation as a decimal
+*/
+
+my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
+{
+ my_decimal value1, *val1;
+ my_decimal value2, *val2;
+ val1= args[0]->val_decimal(&value1);
+ if ((null_value= args[0]->null_value))
+ return 0;
+ val2= args[1]->val_decimal(&value2);
+ if (!(null_value= (args[1]->null_value ||
+ my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1,
+ val2) > 1)))
+ return decimal_value;
+ return 0;
+}
+
+/*
+ Set precision of results for additive operations (+ and -)
+
+ SYNOPSIS
+ Item_func_additive_op::result_precision()
+*/
+void Item_func_additive_op::result_precision()
+{
+ decimals= max(args[0]->decimals, args[1]->decimals);
+ int max_int_part= max(args[0]->decimal_precision() - args[0]->decimals,
+ args[1]->decimal_precision() - args[1]->decimals);
+ int precision= min(max_int_part + 1 + decimals, DECIMAL_MAX_PRECISION);
+
+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
+ if (result_type() == INT_RESULT)
+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
+ else
+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
}
@@ -552,84 +1010,179 @@ void Item_func_minus::fix_length_and_dec()
}
-double Item_func_minus::val()
+double Item_func_minus::real_op()
{
- DBUG_ASSERT(fixed == 1);
- double value=args[0]->val() - args[1]->val();
+ double value= args[0]->val_real() - args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
return value;
}
-longlong Item_func_minus::val_int()
+
+longlong Item_func_minus::int_op()
{
- DBUG_ASSERT(fixed == 1);
- if (hybrid_type == INT_RESULT)
- {
- longlong value=args[0]->val_int() - args[1]->val_int();
- if ((null_value=args[0]->null_value || args[1]->null_value))
- return 0;
- return value;
- }
- return (longlong) Item_func_minus::val();
+ longlong value=args[0]->val_int() - args[1]->val_int();
+ if ((null_value=args[0]->null_value || args[1]->null_value))
+ return 0;
+ return value;
}
-double Item_func_mul::val()
+/* See Item_func_plus::decimal_op for comments */
+
+my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
+{
+ my_decimal value1, *val1;
+ my_decimal value2, *val2=
+
+ val1= args[0]->val_decimal(&value1);
+ if ((null_value= args[0]->null_value))
+ return 0;
+ val2= args[1]->val_decimal(&value2);
+ if (!(null_value= (args[1]->null_value ||
+ my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1,
+ val2) > 1)))
+ return decimal_value;
+ return 0;
+}
+
+
+double Item_func_mul::real_op()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val()*args[1]->val();
+ double value= args[0]->val_real() * args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
- return 0.0; /* purecov: inspected */
+ return 0.0;
return value;
}
-longlong Item_func_mul::val_int()
+
+longlong Item_func_mul::int_op()
{
DBUG_ASSERT(fixed == 1);
- if (hybrid_type == INT_RESULT)
- {
- longlong value=args[0]->val_int()*args[1]->val_int();
- if ((null_value=args[0]->null_value || args[1]->null_value))
- return 0; /* purecov: inspected */
- return value;
- }
- return (longlong) Item_func_mul::val();
+ longlong value=args[0]->val_int()*args[1]->val_int();
+ if ((null_value=args[0]->null_value || args[1]->null_value))
+ return 0;
+ return value;
+}
+
+
+/* See Item_func_plus::decimal_op for comments */
+
+my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
+{
+ my_decimal value1, *val1;
+ my_decimal value2, *val2;
+ val1= args[0]->val_decimal(&value1);
+ if ((null_value= args[0]->null_value))
+ return 0;
+ val2= args[1]->val_decimal(&value2);
+ if (!(null_value= (args[1]->null_value ||
+ my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1,
+ val2) > 1)))
+ return decimal_value;
+ return 0;
+}
+
+
+void Item_func_mul::result_precision()
+{
+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
+ if (result_type() == INT_RESULT)
+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
+ else
+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
+ decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
+ int precision= min(args[0]->decimal_precision() + args[1]->decimal_precision(),
+ DECIMAL_MAX_PRECISION);
+ max_length= my_decimal_precision_to_length(precision, decimals,unsigned_flag);
}
-double Item_func_div::val()
+double Item_func_div::real_op()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- double val2=args[1]->val();
- if ((null_value= val2 == 0.0 || args[0]->null_value || args[1]->null_value))
+ double value= args[0]->val_real();
+ double val2= args[1]->val_real();
+ if ((null_value= args[0]->null_value || args[1]->null_value))
return 0.0;
+ if (val2 == 0.0)
+ {
+ signal_divide_by_null();
+ return 0.0;
+ }
return value/val2;
}
-longlong Item_func_div::val_int()
+
+my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
{
- DBUG_ASSERT(fixed == 1);
- if (hybrid_type == INT_RESULT)
- {
- longlong value=args[0]->val_int();
- longlong val2=args[1]->val_int();
- if ((null_value= val2 == 0 || args[0]->null_value || args[1]->null_value))
- return 0;
- return value/val2;
+ my_decimal value1, *val1;
+ my_decimal value2, *val2;
+
+ val1= args[0]->val_decimal(&value1);
+ if ((null_value= args[0]->null_value))
+ return 0;
+ val2= args[1]->val_decimal(&value2);
+ if ((null_value= args[1]->null_value))
+ return 0;
+ switch (my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
+ val1, val2, prec_increment)) {
+ case E_DEC_TRUNCATED:
+ case E_DEC_OK:
+ return decimal_value;
+ case E_DEC_DIV_ZERO:
+ signal_divide_by_null();
+ default:
+ null_value= 1; // Safety
+ return 0;
}
- return (longlong) Item_func_div::val();
}
+
+void Item_func_div::result_precision()
+{
+ uint precision=min(args[0]->decimal_precision() + prec_increment,
+ DECIMAL_MAX_PRECISION);
+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
+ if (result_type() == INT_RESULT)
+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
+ else
+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
+ decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
+}
+
+
void Item_func_div::fix_length_and_dec()
{
- decimals=max(args[0]->decimals,args[1]->decimals)+2;
- set_if_smaller(decimals, NOT_FIXED_DEC);
- max_length=args[0]->max_length - args[0]->decimals + decimals;
- uint tmp=float_length(decimals);
- set_if_smaller(max_length,tmp);
- maybe_null=1;
+ DBUG_ENTER("Item_func_div::fix_length_and_dec");
+ prec_increment= current_thd->variables.div_precincrement;
+ Item_num_op::fix_length_and_dec();
+ switch(hybrid_type) {
+ case REAL_RESULT:
+ {
+ decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
+ set_if_smaller(decimals, NOT_FIXED_DEC);
+ max_length=args[0]->max_length - args[0]->decimals + decimals;
+ uint tmp=float_length(decimals);
+ set_if_smaller(max_length,tmp);
+ break;
+ }
+ case INT_RESULT:
+ hybrid_type= DECIMAL_RESULT;
+ DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
+ result_precision();
+ break;
+ case DECIMAL_RESULT:
+ result_precision();
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ maybe_null= 1; // devision by zero
+ DBUG_VOID_RETURN;
}
@@ -639,8 +1192,13 @@ longlong Item_func_int_div::val_int()
DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int();
longlong val2=args[1]->val_int();
- if ((null_value= val2 == 0 || args[0]->null_value || args[1]->null_value))
+ if ((null_value= (args[0]->null_value || args[1]->null_value)))
return 0;
+ if (val2 == 0)
+ {
+ signal_divide_by_null();
+ return 0;
+ }
return (unsigned_flag ?
(ulonglong) value / (ulonglong) val2 :
value / val2);
@@ -649,131 +1207,180 @@ longlong Item_func_int_div::val_int()
void Item_func_int_div::fix_length_and_dec()
{
- find_num_type();
max_length=args[0]->max_length - args[0]->decimals;
maybe_null=1;
+ unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
}
-double Item_func_mod::val()
-{
- DBUG_ASSERT(fixed == 1);
- double x= args[0]->val();
- double y= args[1]->val();
- if ((null_value= (y == 0.0) || args[0]->null_value || args[1]->null_value))
- return 0.0; /* purecov: inspected */
- return fmod(x, y);
-}
-
-longlong Item_func_mod::val_int()
+longlong Item_func_mod::int_op()
{
DBUG_ASSERT(fixed == 1);
longlong value= args[0]->val_int();
longlong val2= args[1]->val_int();
- if ((null_value=val2 == 0 || args[0]->null_value || args[1]->null_value))
+ if ((null_value= args[0]->null_value || args[1]->null_value))
return 0; /* purecov: inspected */
+ if (val2 == 0)
+ {
+ signal_divide_by_null();
+ return 0;
+ }
return value % val2;
}
-void Item_func_mod::fix_length_and_dec()
+double Item_func_mod::real_op()
{
- Item_num_op::fix_length_and_dec();
+ DBUG_ASSERT(fixed == 1);
+ double value= args[0]->val_real();
+ double val2= args[1]->val_real();
+ if ((null_value= args[0]->null_value || args[1]->null_value))
+ return 0.0; /* purecov: inspected */
+ if (val2 == 0.0)
+ {
+ signal_divide_by_null();
+ return 0.0;
+ }
+ return fmod(value,val2);
}
-double Item_func_neg::val()
+my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
{
- DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- null_value=args[0]->null_value;
+ my_decimal value1, *val1;
+ my_decimal value2, *val2;
+
+ val1= args[0]->val_decimal(&value1);
+ if ((null_value= args[0]->null_value))
+ return 0;
+ val2= args[1]->val_decimal(&value2);
+ if ((null_value= args[1]->null_value))
+ return 0;
+ switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
+ val1, val2)) {
+ case E_DEC_TRUNCATED:
+ case E_DEC_OK:
+ return decimal_value;
+ case E_DEC_DIV_ZERO:
+ signal_divide_by_null();
+ default:
+ null_value= 1;
+ return 0;
+ }
+}
+
+
+void Item_func_mod::result_precision()
+{
+ decimals= max(args[0]->decimals, args[1]->decimals);
+ max_length= max(args[0]->max_length, args[1]->max_length);
+}
+
+
+double Item_func_neg::real_op()
+{
+ double value= args[0]->val_real();
+ null_value= args[0]->null_value;
return -value;
}
-longlong Item_func_neg::val_int()
+longlong Item_func_neg::int_op()
{
- DBUG_ASSERT(fixed == 1);
- longlong value=args[0]->val_int();
- null_value=args[0]->null_value;
+ longlong value= args[0]->val_int();
+ null_value= args[0]->null_value;
return -value;
}
+my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
+{
+ my_decimal val, *value= args[0]->val_decimal(&val);
+ if (!(null_value= args[0]->null_value))
+ {
+ my_decimal2decimal(value, decimal_value);
+ my_decimal_neg(decimal_value);
+ return decimal_value;
+ }
+ return 0;
+}
+
+
+void Item_func_neg::fix_num_length_and_dec()
+{
+ decimals= args[0]->decimals;
+ /* 1 add because sign can appear */
+ max_length= args[0]->max_length + 1;
+}
+
+
void Item_func_neg::fix_length_and_dec()
{
- enum Item_result arg_result= args[0]->result_type();
- enum Item::Type arg_type= args[0]->type();
- decimals=args[0]->decimals;
- max_length=args[0]->max_length;
- hybrid_type= REAL_RESULT;
-
+ DBUG_ENTER("Item_func_neg::fix_length_and_dec");
+ Item_func_num1::fix_length_and_dec();
+
/*
- We need to account for added '-' in the following cases:
- A) argument is a real or integer positive constant - in this case
- argument's max_length is set to actual number of bytes occupied, and not
- maximum number of bytes real or integer may require. Note that all
- constants are non negative so we don't need to account for removed '-'.
- B) argument returns a string.
+ If this is in integer context keep the context as integer if possible
+ (This is how multiplication and other integer functions works)
Use val() to get value as arg_type doesn't mean that item is
Item_int or Item_real due to existence of Item_param.
*/
- if (arg_result == STRING_RESULT ||
- (arg_type == REAL_ITEM && args[0]->val() >= 0) ||
- (arg_type == INT_ITEM && args[0]->val_int() > 0))
- max_length++;
-
- if (args[0]->result_type() == INT_RESULT)
+ if (hybrid_type == INT_RESULT &&
+ args[0]->type() == INT_ITEM &&
+ ((ulonglong) args[0]->val_int() >= (ulonglong) LONGLONG_MIN))
{
/*
- If this is in integer context keep the context as integer
- (This is how multiplication and other integer functions works)
-
- We must however do a special case in the case where the argument
- is a unsigned bigint constant as in this case the only safe
- number to convert in integer context is 9223372036854775808.
- (This is needed because the lex parser doesn't anymore handle
- signed integers)
+ Ensure that result is converted to DECIMAL, as longlong can't hold
+ the negated number
*/
- if (args[0]->type() != INT_ITEM ||
- (((ulonglong) args[0]->val_int()) <= (ulonglong) LONGLONG_MIN))
- hybrid_type= INT_RESULT;
+ hybrid_type= DECIMAL_RESULT;
+ DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
}
+ unsigned_flag= 0;
+ DBUG_VOID_RETURN;
}
-double Item_func_abs::val()
+double Item_func_abs::real_op()
{
- DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- null_value=args[0]->null_value;
+ double value= args[0]->val_real();
+ null_value= args[0]->null_value;
return fabs(value);
}
-longlong Item_func_abs::val_int()
+longlong Item_func_abs::int_op()
{
- DBUG_ASSERT(fixed == 1);
- longlong value=args[0]->val_int();
- null_value=args[0]->null_value;
+ longlong value= args[0]->val_int();
+ null_value= args[0]->null_value;
return value >= 0 ? value : -value;
}
+my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
+{
+ my_decimal val, *value= args[0]->val_decimal(&val);
+ if (!(null_value= args[0]->null_value))
+ {
+ my_decimal2decimal(value, decimal_value);
+ if (decimal_value->sign())
+ my_decimal_neg(decimal_value);
+ return decimal_value;
+ }
+ return 0;
+}
+
+
void Item_func_abs::fix_length_and_dec()
{
- decimals=args[0]->decimals;
- max_length=args[0]->max_length;
- hybrid_type= REAL_RESULT;
- if (args[0]->result_type() == INT_RESULT)
- hybrid_type= INT_RESULT;
+ Item_func_num1::fix_length_and_dec();
}
/* Gateway to natural LOG function */
-double Item_func_ln::val()
+double Item_func_ln::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
return log(value);
@@ -784,15 +1391,15 @@ double Item_func_ln::val()
We have to check if all values are > zero and first one is not one
as these are the cases then result is not a number.
*/
-double Item_func_log::val()
+double Item_func_log::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
if (arg_count == 2)
{
- double value2= args[1]->val();
+ double value2= args[1]->val_real();
if ((null_value=(args[1]->null_value || value2 <= 0.0 || value == 1.0)))
return 0.0;
return log(value2) / log(value);
@@ -800,47 +1407,47 @@ double Item_func_log::val()
return log(value);
}
-double Item_func_log2::val()
+double Item_func_log2::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
- return log(value) / log(2.0);
+ return log(value) / M_LN2;
}
-double Item_func_log10::val()
+double Item_func_log10::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0; /* purecov: inspected */
return log10(value);
}
-double Item_func_exp::val()
+double Item_func_exp::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0; /* purecov: inspected */
return exp(value);
}
-double Item_func_sqrt::val()
+double Item_func_sqrt::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value < 0)))
return 0.0; /* purecov: inspected */
return sqrt(value);
}
-double Item_func_pow::val()
+double Item_func_pow::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- double val2=args[1]->val();
+ double value= args[0]->val_real();
+ double val2= args[1]->val_real();
if ((null_value=(args[0]->null_value || args[1]->null_value)))
return 0.0; /* purecov: inspected */
return pow(value,val2);
@@ -848,35 +1455,35 @@ double Item_func_pow::val()
// Trigonometric functions
-double Item_func_acos::val()
+double Item_func_acos::val_real()
{
DBUG_ASSERT(fixed == 1);
// the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
- volatile double value=args[0]->val();
+ volatile double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
return 0.0;
return fix_result(acos(value));
}
-double Item_func_asin::val()
+double Item_func_asin::val_real()
{
DBUG_ASSERT(fixed == 1);
// the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
- volatile double value=args[0]->val();
+ volatile double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
return 0.0;
return fix_result(asin(value));
}
-double Item_func_atan::val()
+double Item_func_atan::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
if (arg_count == 2)
{
- double val2= args[1]->val();
+ double val2= args[1]->val_real();
if ((null_value=args[1]->null_value))
return 0.0;
return fix_result(atan2(value,val2));
@@ -884,28 +1491,28 @@ double Item_func_atan::val()
return fix_result(atan(value));
}
-double Item_func_cos::val()
+double Item_func_cos::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
return fix_result(cos(value));
}
-double Item_func_sin::val()
+double Item_func_sin::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
return fix_result(sin(value));
}
-double Item_func_tan::val()
+double Item_func_tan::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
return fix_result(tan(value));
@@ -966,54 +1573,219 @@ void Item_func_integer::fix_length_and_dec()
decimals=0;
}
-longlong Item_func_ceiling::val_int()
+void Item_func_int_val::fix_num_length_and_dec()
{
- DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- null_value=args[0]->null_value;
- return (longlong) ceil(value);
+ max_length= args[0]->max_length - (args[0]->decimals ?
+ args[0]->decimals + 1 :
+ 0) + 2;
+ uint tmp= float_length(decimals);
+ set_if_smaller(max_length,tmp);
+ decimals= 0;
}
-longlong Item_func_floor::val_int()
+
+void Item_func_int_val::find_num_type()
{
- DBUG_ASSERT(fixed == 1);
- // the volatile's for BUG #3051 to calm optimizer down (because of gcc's bug)
- volatile double value=args[0]->val();
- null_value=args[0]->null_value;
- return (longlong) floor(value);
+ DBUG_ENTER("Item_func_int_val::find_num_type");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ switch(hybrid_type= args[0]->result_type())
+ {
+ case STRING_RESULT:
+ case REAL_RESULT:
+ hybrid_type= REAL_RESULT;
+ max_length= float_length(decimals);
+ break;
+ case INT_RESULT:
+ case DECIMAL_RESULT:
+ /*
+ -2 because in most high position can't be used any digit for longlong
+ and one position for increasing value during operation
+ */
+ if ((args[0]->max_length - args[0]->decimals) >=
+ (DECIMAL_LONGLONG_DIGITS - 2))
+ {
+ hybrid_type= DECIMAL_RESULT;
+ }
+ else
+ {
+ unsigned_flag= args[0]->unsigned_flag;
+ hybrid_type= INT_RESULT;
+ }
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ DBUG_PRINT("info", ("Type: %s",
+ (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
+ hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ hybrid_type == INT_RESULT ? "INT_RESULT" :
+ "--ILLEGAL!!!--")));
+
+ DBUG_VOID_RETURN;
}
-void Item_func_round::fix_length_and_dec()
+
+longlong Item_func_ceiling::int_op()
{
- max_length=args[0]->max_length;
- decimals=args[0]->decimals;
- if (args[1]->const_item())
+ longlong result;
+ switch (args[0]->result_type()) {
+ case INT_RESULT:
+ result= args[0]->val_int();
+ null_value= args[0]->null_value;
+ break;
+ case DECIMAL_RESULT:
{
- int tmp=(int) args[1]->val_int();
- if (tmp < 0)
- decimals=0;
+ my_decimal dec_buf, *dec;
+ if ((dec= Item_func_ceiling::decimal_op(&dec_buf)))
+ my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
else
- decimals=min(tmp,NOT_FIXED_DEC);
- if ((tmp= decimals - args[0]->decimals) > 0)
- max_length+= tmp;
+ result= 0;
+ break;
}
+ default:
+ result= (longlong)Item_func_ceiling::real_op();
+ };
+ return result;
}
-double Item_func_round::val()
+
+double Item_func_ceiling::real_op()
+{
+ /*
+ the volatile's for BUG #3051 to calm optimizer down (because of gcc's
+ bug)
+ */
+ volatile double value= args[0]->val_real();
+ null_value= args[0]->null_value;
+ return ceil(value);
+}
+
+
+my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value)
+{
+ my_decimal val, *value= args[0]->val_decimal(&val);
+ if (!(null_value= (args[0]->null_value ||
+ my_decimal_ceiling(E_DEC_FATAL_ERROR, value,
+ decimal_value) > 1)))
+ return decimal_value;
+ return 0;
+}
+
+
+longlong Item_func_floor::int_op()
+{
+ longlong result;
+ switch (args[0]->result_type()) {
+ case INT_RESULT:
+ result= args[0]->val_int();
+ null_value= args[0]->null_value;
+ break;
+ case DECIMAL_RESULT:
+ {
+ my_decimal dec_buf, *dec;
+ if ((dec= Item_func_floor::decimal_op(&dec_buf)))
+ my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
+ else
+ result= 0;
+ break;
+ }
+ default:
+ result= (longlong)Item_func_floor::real_op();
+ };
+ return result;
+}
+
+
+double Item_func_floor::real_op()
+{
+ /*
+ the volatile's for BUG #3051 to calm optimizer down (because of gcc's
+ bug)
+ */
+ volatile double value= args[0]->val_real();
+ null_value= args[0]->null_value;
+ return floor(value);
+}
+
+
+my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
+{
+ my_decimal val, *value= args[0]->val_decimal(&val);
+ if (!(null_value= (args[0]->null_value ||
+ my_decimal_floor(E_DEC_FATAL_ERROR, value,
+ decimal_value) > 1)))
+ return decimal_value;
+ return 0;
+}
+
+
+void Item_func_round::fix_length_and_dec()
+{
+ unsigned_flag= args[0]->unsigned_flag;
+ if (!args[1]->const_item())
+ {
+ max_length= args[0]->max_length;
+ decimals= args[0]->decimals;
+ hybrid_type= REAL_RESULT;
+ return;
+ }
+
+ int decimals_to_set= max((int)args[1]->val_int(), 0);
+ if (args[0]->decimals == NOT_FIXED_DEC)
+ {
+ max_length= args[0]->max_length;
+ decimals= min(decimals_to_set, NOT_FIXED_DEC);
+ hybrid_type= REAL_RESULT;
+ return;
+ }
+
+ switch (args[0]->result_type()) {
+ case REAL_RESULT:
+ case STRING_RESULT:
+ hybrid_type= REAL_RESULT;
+ decimals= min(decimals_to_set, NOT_FIXED_DEC);
+ max_length= float_length(decimals);
+ break;
+ case INT_RESULT:
+ if (!decimals_to_set &&
+ (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)))
+ {
+ int length_can_increase= test(!truncate && (args[1]->val_int() < 0));
+ max_length= args[0]->max_length + length_can_increase;
+ /* Here we can keep INT_RESULT */
+ hybrid_type= INT_RESULT;
+ decimals= 0;
+ break;
+ }
+ /* fall through */
+ case DECIMAL_RESULT:
+ {
+ hybrid_type= DECIMAL_RESULT;
+ int decimals_delta= args[0]->decimals - decimals_to_set;
+ int precision= args[0]->decimal_precision();
+ int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;
+
+ precision-= decimals_delta - length_increase;
+ decimals= decimals_to_set;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
+ break;
+ }
+ default:
+ DBUG_ASSERT(0); /* This result type isn't handled */
+ }
+}
+
+double my_double_round(double value, int dec, bool truncate)
{
- DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- int dec=(int) args[1]->val_int();
- uint abs_dec=abs(dec);
double tmp;
+ uint abs_dec= abs(dec);
/*
tmp2 is here to avoid return the value with 80 bit precision
This will fix that the test round(0.1,1) = round(0.1,1) is true
*/
volatile double tmp2;
- if ((null_value=args[0]->null_value || args[1]->null_value))
- return 0.0;
tmp=(abs_dec < array_elements(log_10) ?
log_10[abs_dec] : pow(10.0,(double) abs_dec));
@@ -1030,10 +1802,74 @@ double Item_func_round::val()
}
-bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
- Item **ref)
+double Item_func_round::real_op()
+{
+ double value= args[0]->val_real();
+ int dec= (int) args[1]->val_int();
+
+ if (!(null_value= args[0]->null_value || args[1]->null_value))
+ return my_double_round(value, dec, truncate);
+
+ return 0.0;
+}
+
+
+longlong Item_func_round::int_op()
{
- if (Item_real_func::fix_fields(thd, tables, ref))
+ longlong value= args[0]->val_int();
+ int dec=(int) args[1]->val_int();
+ decimals= 0;
+ uint abs_dec;
+ if ((null_value= args[0]->null_value || args[1]->null_value))
+ return 0;
+ if (dec >= 0)
+ return value; // integer have not digits after point
+
+ abs_dec= -dec;
+ double tmp;
+ /*
+ tmp2 is here to avoid return the value with 80 bit precision
+ This will fix that the test round(0.1,1) = round(0.1,1) is true
+ */
+ volatile double tmp2;
+
+ tmp= (abs_dec < array_elements(log_10) ?
+ log_10[abs_dec] : pow(10.0, (double) abs_dec));
+
+ if (truncate)
+ {
+ if (unsigned_flag)
+ tmp2= floor(ulonglong2double(value)/tmp)*tmp;
+ else if (value >= 0)
+ tmp2= floor(((double)value)/tmp)*tmp;
+ else
+ tmp2= ceil(((double)value)/tmp)*tmp;
+ }
+ else
+ tmp2= rint(((double)value)/tmp)*tmp;
+ return (longlong)tmp2;
+}
+
+
+my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
+{
+ my_decimal val, *value= args[0]->val_decimal(&val);
+ int dec=(int) args[1]->val_int();
+ if (dec > 0)
+ {
+ decimals= min(dec, DECIMAL_MAX_SCALE); // to get correct output
+ }
+ if (!(null_value= (args[0]->null_value || args[1]->null_value ||
+ my_decimal_round(E_DEC_FATAL_ERROR, value, dec, truncate,
+ decimal_value) > 1)))
+ return decimal_value;
+ return 0;
+}
+
+
+bool Item_func_rand::fix_fields(THD *thd,Item **ref)
+{
+ if (Item_real_func::fix_fields(thd, ref))
return TRUE;
used_tables_cache|= RAND_TABLE_BIT;
if (arg_count)
@@ -1044,12 +1880,15 @@ bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
return TRUE;
}
/*
- Allocate rand structure once: we must use thd->current_arena
+ Allocate rand structure once: we must use thd->stmt_arena
to create rand in proper mem_root if it's a prepared statement or
stored procedure.
+
+ No need to send a Rand log event if seed was given eg: RAND(seed),
+ as it will be replicated in the query as such.
*/
if (!rand && !(rand= (struct rand_struct*)
- thd->current_arena->alloc(sizeof(*rand))))
+ thd->stmt_arena->alloc(sizeof(*rand))))
return TRUE;
/*
PARAM_ITEM is returned if we're in statement prepare and consequently
@@ -1069,16 +1908,16 @@ bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
else
{
/*
- No need to send a Rand log event if seed was given eg: RAND(seed),
- as it will be replicated in the query as such.
-
Save the seed only the first time RAND() is used in the query
Once events are forwarded rather than recreated,
the following can be skipped if inside the slave thread
*/
- thd->rand_used=1;
- thd->rand_saved_seed1=thd->rand.seed1;
- thd->rand_saved_seed2=thd->rand.seed2;
+ if (!thd->rand_used)
+ {
+ thd->rand_used= 1;
+ thd->rand_saved_seed1= thd->rand.seed1;
+ thd->rand_saved_seed2= thd->rand.seed2;
+ }
rand= &thd->rand;
}
return FALSE;
@@ -1091,7 +1930,7 @@ void Item_func_rand::update_used_tables()
}
-double Item_func_rand::val()
+double Item_func_rand::val_real()
{
DBUG_ASSERT(fixed == 1);
return my_rnd(rand);
@@ -1100,16 +1939,16 @@ double Item_func_rand::val()
longlong Item_func_sign::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
null_value=args[0]->null_value;
return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
}
-double Item_func_units::val()
+double Item_func_units::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0;
return value*mul+add;
@@ -1118,23 +1957,26 @@ double Item_func_units::val()
void Item_func_min_max::fix_length_and_dec()
{
+ int max_int_part=0;
decimals=0;
max_length=0;
- maybe_null=1;
+ maybe_null=0;
cmp_type=args[0]->result_type();
for (uint i=0 ; i < arg_count ; i++)
{
- if (max_length < args[i]->max_length)
- max_length=args[i]->max_length;
- if (decimals < args[i]->decimals)
- decimals=args[i]->decimals;
- if (!args[i]->maybe_null)
- maybe_null=0;
+ set_if_bigger(max_length, args[i]->max_length);
+ set_if_bigger(decimals, args[i]->decimals);
+ set_if_bigger(max_int_part, args[i]->decimal_int_part());
+ if (args[i]->maybe_null)
+ maybe_null=1;
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
}
if (cmp_type == STRING_RESULT)
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
+ else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
+ max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals,
+ unsigned_flag);
}
@@ -1153,9 +1995,17 @@ String *Item_func_min_max::val_str(String *str)
str->set((ulonglong) nr,&my_charset_bin);
return str;
}
+ case DECIMAL_RESULT:
+ {
+ my_decimal dec_buf, *dec_val= val_decimal(&dec_buf);
+ if (null_value)
+ return 0;
+ my_decimal2string(E_DEC_FATAL_ERROR, dec_val, 0, 0, 0, str);
+ return str;
+ }
case REAL_RESULT:
{
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals,&my_charset_bin);
@@ -1165,14 +2015,11 @@ String *Item_func_min_max::val_str(String *str)
{
String *res;
LINT_INIT(res);
- null_value=1;
+ null_value= 0;
for (uint i=0; i < arg_count ; i++)
{
- if (null_value)
- {
+ if (i == 0)
res=args[i]->val_str(str);
- null_value=args[i]->null_value;
- }
else
{
String *res2;
@@ -1183,7 +2030,11 @@ String *Item_func_min_max::val_str(String *str)
if ((cmp_sign < 0 ? cmp : -cmp) < 0)
res=res2;
}
+ else
+ res= 0;
}
+ if ((null_value= args[i]->null_value))
+ break;
}
if (res) // If !NULL
res->set_charset(collation.collation);
@@ -1191,7 +2042,7 @@ String *Item_func_min_max::val_str(String *str)
}
case ROW_RESULT:
default:
- // This case should never be choosen
+ // This case should never be chosen
DBUG_ASSERT(0);
return 0;
}
@@ -1199,24 +2050,23 @@ String *Item_func_min_max::val_str(String *str)
}
-double Item_func_min_max::val()
+double Item_func_min_max::val_real()
{
DBUG_ASSERT(fixed == 1);
double value=0.0;
- null_value=1;
+ null_value= 0;
for (uint i=0; i < arg_count ; i++)
{
- if (null_value)
- {
- value=args[i]->val();
- null_value=args[i]->null_value;
- }
+ if (i == 0)
+ value= args[i]->val_real();
else
{
- double tmp=args[i]->val();
+ double tmp= args[i]->val_real();
if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
value=tmp;
}
+ if ((null_value= args[i]->null_value))
+ break;
}
return value;
}
@@ -1226,24 +2076,56 @@ longlong Item_func_min_max::val_int()
{
DBUG_ASSERT(fixed == 1);
longlong value=0;
- null_value=1;
+ null_value= 0;
for (uint i=0; i < arg_count ; i++)
{
- if (null_value)
- {
+ if (i == 0)
value=args[i]->val_int();
- null_value=args[i]->null_value;
- }
else
{
longlong tmp=args[i]->val_int();
if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
value=tmp;
}
+ if ((null_value= args[i]->null_value))
+ break;
}
return value;
}
+
+my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
+{
+ DBUG_ASSERT(fixed == 1);
+ my_decimal tmp_buf, *tmp, *res= NULL;
+ null_value= 0;
+ for (uint i=0; i < arg_count ; i++)
+ {
+ if (i == 0)
+ res= args[i]->val_decimal(dec);
+ else
+ {
+ tmp= args[i]->val_decimal(&tmp_buf);
+ if (args[i]->null_value)
+ res= 0;
+ else if ((my_decimal_cmp(tmp, res) * cmp_sign) < 0)
+ {
+ if (tmp == &tmp_buf)
+ {
+ my_decimal2decimal(tmp, dec);
+ res= dec;
+ }
+ else
+ res= tmp;
+ }
+ }
+ if ((null_value= args[i]->null_value))
+ break;
+ }
+ return res;
+}
+
+
longlong Item_func_length::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -1345,8 +2227,8 @@ longlong Item_func_field::val_int()
if (cmp_type == STRING_RESULT)
{
String *field;
- if (!(field=args[0]->val_str(&value)))
- return 0; // -1 if null ?
+ if (!(field= args[0]->val_str(&value)))
+ return 0;
for (uint i=1 ; i < arg_count ; i++)
{
String *tmp_value=args[i]->val_str(&tmp);
@@ -1365,14 +2247,27 @@ longlong Item_func_field::val_int()
return (longlong) (i);
}
}
+ else if (cmp_type == DECIMAL_RESULT)
+ {
+ my_decimal dec_arg_buf, *dec_arg,
+ dec_buf, *dec= args[0]->val_decimal(&dec_buf);
+ if (args[0]->null_value)
+ return 0;
+ for (uint i=1; i < arg_count; i++)
+ {
+ dec_arg= args[i]->val_decimal(&dec_arg_buf);
+ if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec))
+ return (longlong) (i);
+ }
+ }
else
{
- double val= args[0]->val();
+ double val= args[0]->val_real();
if (args[0]->null_value)
return 0;
for (uint i=1; i < arg_count ; i++)
{
- if (val == args[i]->val() && !args[i]->null_value)
+ if (val == args[i]->val_real() && !args[i]->null_value)
return (longlong) (i);
}
}
@@ -1516,12 +2411,12 @@ longlong Item_func_find_in_set::val_int()
}
str_end= substr_end;
}
- else if (str_end - str_begin == 0 &&
- find_str_len == 0 &&
+ else if (str_end - str_begin == 0 &&
+ find_str_len == 0 &&
wc == (my_wc_t) separator)
return (longlong) ++position;
else
- return (longlong) 0;
+ return LL(0);
}
}
return 0;
@@ -1548,13 +2443,6 @@ longlong Item_func_bit_count::val_int()
#ifdef HAVE_DLOPEN
-udf_handler::~udf_handler()
-{
- /* Everything should be properly cleaned up by this moment. */
- DBUG_ASSERT(not_original || !(initialized || buffers));
-}
-
-
void udf_handler::cleanup()
{
if (!not_original)
@@ -1578,7 +2466,7 @@ void udf_handler::cleanup()
bool
-udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
+udf_handler::fix_fields(THD *thd, Item_result_field *func,
uint arg_count, Item **arguments)
{
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
@@ -1586,16 +2474,15 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
#endif
DBUG_ENTER("Item_udf_func::fix_fields");
- if (check_stack_overrun(thd, buff))
- DBUG_RETURN(1); // Fatal error flag is set!
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
+ DBUG_RETURN(TRUE); // Fatal error flag is set!
udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
if (!tmp_udf)
{
- my_printf_error(ER_CANT_FIND_UDF,ER(ER_CANT_FIND_UDF),MYF(0),u_d->name.str,
- errno);
- DBUG_RETURN(1);
+ my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str, errno);
+ DBUG_RETURN(TRUE);
}
u_d=tmp_udf;
args=arguments;
@@ -1612,7 +2499,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
{
free_udf(u_d);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
uint i;
Item **arg,**arg_end;
@@ -1620,13 +2507,13 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
arg != arg_end ;
arg++,i++)
{
- if (!(*arg)->fixed &&
- (*arg)->fix_fields(thd, tables, arg))
+ if (!(*arg)->fixed &&
+ (*arg)->fix_fields(thd, arg))
DBUG_RETURN(1);
// we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg;
if (item->check_cols(1))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
/*
TODO: We should think about this. It is not always
right way just to set an UDF result to return my_charset_bin
@@ -1636,7 +2523,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
Moreover, some arguments can represent a numeric input
which doesn't effect the result character set and collation.
There is no a general rule for UDF. Everything depends on
- the particular user definted function.
+ the particular user defined function.
*/
if (item->collation.collation->state & MY_CS_BINSORT)
func->collation.set(&my_charset_bin);
@@ -1647,14 +2534,19 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
const_item_cache&=item->const_item();
f_args.arg_type[i]=item->result_type();
}
+ //TODO: why all following memory is not allocated with 1 call of sql_alloc?
if (!(buffers=new String[arg_count]) ||
!(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
- !(f_args.lengths=(ulong*) sql_alloc(arg_count * sizeof(long))) ||
- !(f_args.maybe_null=(char*) sql_alloc(arg_count * sizeof(char))) ||
- !(num_buffer= (char*) sql_alloc(ALIGN_SIZE(sizeof(double))*arg_count)))
+ !(f_args.lengths= (ulong*) sql_alloc(arg_count * sizeof(long))) ||
+ !(f_args.maybe_null= (char*) sql_alloc(arg_count * sizeof(char))) ||
+ !(num_buffer= (char*) sql_alloc(arg_count *
+ ALIGN_SIZE(sizeof(double)))) ||
+ !(f_args.attributes= (char**) sql_alloc(arg_count * sizeof(char *))) ||
+ !(f_args.attribute_lengths= (ulong*) sql_alloc(arg_count *
+ sizeof(long))))
{
free_udf(u_d);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
func->fix_length_and_dec();
@@ -1670,8 +2562,10 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
for (uint i=0; i < arg_count; i++)
{
f_args.args[i]=0;
- f_args.lengths[i]=arguments[i]->max_length;
- f_args.maybe_null[i]=(char) arguments[i]->maybe_null;
+ f_args.lengths[i]= arguments[i]->max_length;
+ f_args.maybe_null[i]= (char) arguments[i]->maybe_null;
+ f_args.attributes[i]= arguments[i]->name;
+ f_args.attribute_lengths[i]= arguments[i]->name_length;
switch(arguments[i]->type()) {
case Item::STRING_ITEM: // Constant string !
@@ -1691,7 +2585,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
}
break;
case Item::REAL_ITEM:
- *((double*) to) = arguments[i]->val();
+ *((double*) to)= arguments[i]->val_real();
if (!arguments[i]->null_value)
{
f_args.args[i]=to;
@@ -1708,10 +2602,10 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
u_d->func_init;
if ((error=(uchar) init(&initid, &f_args, thd->net.last_error)))
{
- my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0),
- u_d->name.str, thd->net.last_error);
+ my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
+ u_d->name.str, thd->net.last_error);
free_udf(u_d);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
func->max_length=min(initid.max_length,MAX_BLOB_WIDTH);
func->maybe_null=initid.maybe_null;
@@ -1721,11 +2615,11 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
initialized=1;
if (error)
{
- my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0),
- u_d->name.str, ER(ER_UNKNOWN_ERROR));
- DBUG_RETURN(1);
+ my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
+ u_d->name.str, ER(ER_UNKNOWN_ERROR));
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -1740,6 +2634,7 @@ bool udf_handler::get_arguments()
f_args.args[i]=0;
switch (f_args.arg_type[i]) {
case STRING_RESULT:
+ case DECIMAL_RESULT:
{
String *res=args[i]->val_str(&buffers[str_count++]);
if (!(args[i]->null_value))
@@ -1758,7 +2653,7 @@ bool udf_handler::get_arguments()
}
break;
case REAL_RESULT:
- *((double*) to) = args[i]->val();
+ *((double*) to)= args[i]->val_real();
if (!args[i]->null_value)
{
f_args.args[i]=to;
@@ -1767,7 +2662,7 @@ bool udf_handler::get_arguments()
break;
case ROW_RESULT:
default:
- // This case should never be choosen
+ // This case should never be chosen
DBUG_ASSERT(0);
break;
}
@@ -1812,6 +2707,36 @@ String *udf_handler::val_str(String *str,String *save_str)
}
+/*
+ For the moment, UDF functions are returning DECIMAL values as strings
+*/
+
+my_decimal *udf_handler::val_decimal(my_bool *null_value, my_decimal *dec_buf)
+{
+ char buf[DECIMAL_MAX_STR_LENGTH+1], *end;
+ ulong res_length= DECIMAL_MAX_STR_LENGTH;
+
+ if (get_arguments())
+ {
+ *null_value=1;
+ return 0;
+ }
+ char *(*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)=
+ (char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *))
+ u_d->func;
+
+ char *res= func(&initid, &f_args, buf, &res_length, &is_null, &error);
+ if (is_null || error)
+ {
+ *null_value= 1;
+ return 0;
+ }
+ end= res+ res_length;
+ str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
+ return dec_buf;
+}
+
+
void Item_udf_func::cleanup()
{
udf.cleanup();
@@ -1819,7 +2744,7 @@ void Item_udf_func::cleanup()
}
-double Item_func_udf_float::val()
+double Item_func_udf_float::val_real()
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_udf_float::val");
@@ -1832,7 +2757,7 @@ double Item_func_udf_float::val()
String *Item_func_udf_float::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals,&my_charset_bin);
@@ -1864,6 +2789,59 @@ String *Item_func_udf_int::val_str(String *str)
return str;
}
+
+longlong Item_func_udf_decimal::val_int()
+{
+ my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
+ longlong result;
+ if (null_value)
+ return 0;
+ my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
+ return result;
+}
+
+
+double Item_func_udf_decimal::val_real()
+{
+ my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
+ double result;
+ if (null_value)
+ return 0.0;
+ my_decimal2double(E_DEC_FATAL_ERROR, dec, &result);
+ return result;
+}
+
+
+my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf)
+{
+ DBUG_ASSERT(fixed == 1);
+ DBUG_ENTER("Item_func_udf_decimal::val_decimal");
+ DBUG_PRINT("info",("result_type: %d arg_count: %d",
+ args[0]->result_type(), arg_count));
+
+ DBUG_RETURN(udf.val_decimal(&null_value, dec_buf));
+}
+
+
+String *Item_func_udf_decimal::val_str(String *str)
+{
+ my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
+ if (null_value)
+ return 0;
+ if (str->length() < DECIMAL_MAX_STR_LENGTH)
+ str->length(DECIMAL_MAX_STR_LENGTH);
+ my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf);
+ my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, '0', str);
+ return str;
+}
+
+
+void Item_func_udf_decimal::fix_length_and_dec()
+{
+ fix_num_length_and_dec();
+}
+
+
/* Default max_length is max argument length */
void Item_func_udf_str::fix_length_and_dec()
@@ -1883,6 +2861,18 @@ String *Item_func_udf_str::val_str(String *str)
return res;
}
+
+/*
+ This has to come last in the udf_handler methods, or C for AIX
+ version 6.0.0.0 fails to compile with debugging enabled. (Yes, really.)
+ */
+
+udf_handler::~udf_handler()
+{
+ /* Everything should be properly cleaned up by this moment. */
+ DBUG_ASSERT(not_original || !(initialized || buffers));
+}
+
#else
bool udf_handler::get_arguments() { return 0; }
#endif /* HAVE_DLOPEN */
@@ -1966,18 +2956,6 @@ void item_user_lock_free(void)
void item_user_lock_release(User_level_lock *ull)
{
ull->locked=0;
- if (mysql_bin_log.is_open())
- {
- char buf[256];
- const char *command="DO RELEASE_LOCK(\"";
- String tmp(buf,sizeof(buf), system_charset_info);
- tmp.copy(command, strlen(command), tmp.charset());
- tmp.append(ull->key,ull->key_length);
- tmp.append("\")", 2);
- Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1, FALSE);
- qev.error_code=0; // this query is always safe to run on slave
- mysql_bin_log.write(&qev);
- }
if (--ull->count)
pthread_cond_signal(&ull->cond);
else
@@ -2020,7 +2998,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
THD* thd=current_thd;
User_level_lock* ull;
struct timespec abstime;
- int lock_name_len,error=0;
+ int lock_name_len;
lock_name_len=strlen(lock_name);
pthread_mutex_lock(&LOCK_user_locks);
@@ -2054,8 +3032,8 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
set_timespec(abstime,lock_timeout);
while (!thd->killed &&
- (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
- != ETIME && error != ETIMEDOUT && ull->locked) ;
+ pthread_cond_timedwait(&ull->cond, &LOCK_user_locks,
+ &abstime) != ETIMEDOUT && ull->locked) ;
if (ull->locked)
{
if (!--ull->count)
@@ -2101,6 +3079,16 @@ longlong Item_func_get_lock::val_int()
User_level_lock *ull;
int error=0;
+ /*
+ In slave thread no need to get locks, everything is serialized. Anyway
+ there is no way to make GET_LOCK() work on slave like it did on master
+ (i.e. make it return exactly the same value) because we don't have the
+ same other concurrent threads environment. No matter what we return here,
+ it's not guaranteed to be same as on master.
+ */
+ if (thd->slave_thread)
+ return 1;
+
pthread_mutex_lock(&LOCK_user_locks);
if (!res || !res->length())
@@ -2147,14 +3135,14 @@ longlong Item_func_get_lock::val_int()
set_timespec(abstime,timeout);
while (!thd->killed &&
(error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
- != ETIME && error != ETIMEDOUT && error != EINVAL && ull->locked) ;
+ != ETIMEDOUT && error != EINVAL && ull->locked) ;
if (thd->killed)
error=EINTR; // Return NULL
if (ull->locked)
{
if (!--ull->count)
delete ull; // Should never happen
- if (error != ETIME && error != ETIMEDOUT)
+ if (error != ETIMEDOUT)
{
error=1;
null_value=1; // Return NULL
@@ -2224,16 +3212,17 @@ longlong Item_func_release_lock::val_int()
longlong Item_func_last_insert_id::val_int()
{
+ THD *thd= current_thd;
DBUG_ASSERT(fixed == 1);
if (arg_count)
{
- longlong value=args[0]->val_int();
- current_thd->insert_id(value);
- null_value=args[0]->null_value;
+ longlong value= args[0]->val_int();
+ thd->insert_id(value);
+ null_value= args[0]->null_value;
+ return value; // Avoid side effect of insert_id()
}
- else
- current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- return current_thd->insert_id();
+ thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ return thd->insert_id();
}
/* This function is just used to test speed of different functions */
@@ -2249,7 +3238,7 @@ longlong Item_func_benchmark::val_int()
{
switch (args[0]->result_type()) {
case REAL_RESULT:
- (void) args[0]->val();
+ (void) args[0]->val_real();
break;
case INT_RESULT:
(void) args[0]->val_int();
@@ -2259,7 +3248,7 @@ longlong Item_func_benchmark::val_int()
break;
case ROW_RESULT:
default:
- // This case should never be choosen
+ // This case should never be chosen
DBUG_ASSERT(0);
return 0;
}
@@ -2281,6 +3270,43 @@ void Item_func_benchmark::print(String *str)
str->append(')');
}
+/* This function is just used to create tests with time gaps */
+
+longlong Item_func_sleep::val_int()
+{
+ THD *thd= current_thd;
+ struct timespec abstime;
+ pthread_cond_t cond;
+ int error;
+
+ DBUG_ASSERT(fixed == 1);
+
+ double time= args[0]->val_real();
+ set_timespec_nsec(abstime, (ulonglong)(time * ULL(1000000000)));
+
+ pthread_cond_init(&cond, NULL);
+ pthread_mutex_lock(&LOCK_user_locks);
+
+ thd->mysys_var->current_mutex= &LOCK_user_locks;
+ thd->mysys_var->current_cond= &cond;
+
+ while (!thd->killed &&
+ (error= pthread_cond_timedwait(&cond, &LOCK_user_locks,
+ &abstime)) != ETIMEDOUT &&
+ error != EINVAL) ;
+
+ pthread_mutex_lock(&thd->mysys_var->mutex);
+ thd->mysys_var->current_mutex= 0;
+ thd->mysys_var->current_cond= 0;
+ pthread_mutex_unlock(&thd->mysys_var->mutex);
+
+ pthread_mutex_unlock(&LOCK_user_locks);
+ pthread_cond_destroy(&cond);
+
+ return (error == ETIMEDOUT) ? 0 : 1;
+}
+
+
#define extra_size sizeof(double)
static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
@@ -2331,14 +3357,13 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
SELECT @a:= ).
*/
-bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
- Item **ref)
+bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
- if (Item_func::fix_fields(thd, tables, ref) ||
+ if (Item_func::fix_fields(thd, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
- return 1;
+ return TRUE;
/*
Remember the last query which updated it, this way a query can later know
if this variable is a constant item in the query (it is if update_query_id
@@ -2360,11 +3385,12 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
from the argument if the argument is NULL
and the variable has previously been initialized.
*/
- if (!entry->collation.collation || !args[0]->null_value)
+ null_item= (args[0]->type() == NULL_ITEM);
+ if (!entry->collation.collation || !null_item)
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
cached_result_type= args[0]->result_type();
- return 0;
+ return FALSE;
}
@@ -2378,18 +3404,34 @@ Item_func_set_user_var::fix_length_and_dec()
}
-bool Item_func_set_user_var::update_hash(void *ptr, uint length,
- Item_result type,
- CHARSET_INFO *cs,
- Derivation dv)
+/*
+ Set value to user variable.
+
+ SYNOPSYS
+ update_hash()
+ entry - pointer to structure representing variable
+ set_null - should we set NULL value ?
+ ptr - pointer to buffer with new value
+ length - length of new value
+ type - type of new value
+ cs - charset info for new value
+ dv - derivation for new value
+
+ RETURN VALUE
+ False - success, True - failure
+*/
+
+static bool
+update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
+ Item_result type, CHARSET_INFO *cs, Derivation dv)
{
- if ((null_value=args[0]->null_value))
+ if (set_null)
{
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
if (entry->value && entry->value != pos)
my_free(entry->value,MYF(0));
- entry->value=0;
- entry->length=0;
+ entry->value= 0;
+ entry->length= 0;
}
else
{
@@ -2416,7 +3458,7 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length,
entry->value=0;
if (!(entry->value=(char*) my_realloc(entry->value, length,
MYF(MY_ALLOW_ZERO_PTR))))
- goto err;
+ return 1;
}
}
if (type == STRING_RESULT)
@@ -2425,22 +3467,40 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length,
entry->value[length]= 0; // Store end \0
}
memcpy(entry->value,ptr,length);
+ if (type == DECIMAL_RESULT)
+ ((my_decimal*)entry->value)->fix_buffer_pointer();
entry->length= length;
- entry->type=type;
entry->collation.set(cs, dv);
}
+ entry->type=type;
return 0;
+}
- err:
- current_thd->fatal_error(); // Probably end of memory
- null_value= 1;
- return 1;
+
+bool
+Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type,
+ CHARSET_INFO *cs, Derivation dv)
+{
+ /*
+ If we set a variable explicitely to NULL then keep the old
+ result type of the variable
+ */
+ if ((null_value= args[0]->null_value) && null_item)
+ type= entry->type; // Don't change type of item
+ if (::update_hash(entry, (null_value= args[0]->null_value),
+ ptr, length, type, cs, dv))
+ {
+ current_thd->fatal_error(); // Probably end of memory
+ null_value= 1;
+ return 1;
+ }
+ return 0;
}
/* Get the value of a variable as a double */
-double user_var_entry::val(my_bool *null_value)
+double user_var_entry::val_real(my_bool *null_value)
{
if ((*null_value= (value == 0)))
return 0.0;
@@ -2450,6 +3510,12 @@ double user_var_entry::val(my_bool *null_value)
return *(double*) value;
case INT_RESULT:
return (double) *(longlong*) value;
+ case DECIMAL_RESULT:
+ {
+ double result;
+ my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
+ return result;
+ }
case STRING_RESULT:
return my_atof(value); // This is null terminated
case ROW_RESULT:
@@ -2472,6 +3538,12 @@ longlong user_var_entry::val_int(my_bool *null_value)
return (longlong) *(double*) value;
case INT_RESULT:
return *(longlong*) value;
+ case DECIMAL_RESULT:
+ {
+ longlong result;
+ my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
+ return result;
+ }
case STRING_RESULT:
{
int error;
@@ -2500,6 +3572,9 @@ String *user_var_entry::val_str(my_bool *null_value, String *str,
case INT_RESULT:
str->set(*(longlong*) value, &my_charset_bin);
break;
+ case DECIMAL_RESULT:
+ my_decimal2string(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, 0, 0, str);
+ break;
case STRING_RESULT:
if (str->copy(value, length, collation.collation))
str= 0; // EOM error
@@ -2510,19 +3585,46 @@ String *user_var_entry::val_str(my_bool *null_value, String *str,
return(str);
}
+/* Get the value of a variable as a decimal */
+
+my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
+{
+ if ((*null_value= (value == 0)))
+ return 0;
+
+ switch (type) {
+ case REAL_RESULT:
+ double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
+ break;
+ case INT_RESULT:
+ int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) value, 0, val);
+ break;
+ case DECIMAL_RESULT:
+ val= (my_decimal *)value;
+ break;
+ case STRING_RESULT:
+ str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
+ break;
+ case ROW_RESULT:
+ DBUG_ASSERT(1); // Impossible
+ break;
+ }
+ return(val);
+}
+
/*
This functions is invoked on SET @variable or @variable:= expression.
- Evaluete (and check expression), store results.
+ Evaluate (and check expression), store results.
SYNOPSYS
Item_func_set_user_var::check()
NOTES
- For now it always return OK. All problem with value evalueting
- will be catched by thd->net.report_error check in sql_set_variables().
+ For now it always return OK. All problem with value evaluating
+ will be caught by thd->net.report_error check in sql_set_variables().
RETURN
- 0 - OK.
+ FALSE OK.
*/
bool
@@ -2533,7 +3635,7 @@ Item_func_set_user_var::check()
switch (cached_result_type) {
case REAL_RESULT:
{
- save_result.vreal= args[0]->val();
+ save_result.vreal= args[0]->val_real();
break;
}
case INT_RESULT:
@@ -2546,13 +3648,18 @@ Item_func_set_user_var::check()
save_result.vstr= args[0]->val_str(&value);
break;
}
+ case DECIMAL_RESULT:
+ {
+ save_result.vdec= args[0]->val_decimal(&decimal_buff);
+ break;
+ }
case ROW_RESULT:
default:
- // This case should never be choosen
+ // This case should never be chosen
DBUG_ASSERT(0);
break;
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -2567,7 +3674,7 @@ Item_func_set_user_var::check()
the value method used by the user
RETURN
- 0 Ok
+ 0 OK
1 EOM Error
*/
@@ -2604,9 +3711,20 @@ Item_func_set_user_var::update()
DERIVATION_IMPLICIT);
break;
}
+ case DECIMAL_RESULT:
+ {
+ if (!save_result.vdec) // Null value
+ res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
+ DERIVATION_IMPLICIT);
+ else
+ res= update_hash((void*) save_result.vdec,
+ sizeof(my_decimal), DECIMAL_RESULT,
+ &my_charset_bin, DERIVATION_IMPLICIT);
+ break;
+ }
case ROW_RESULT:
default:
- // This case should never be choosen
+ // This case should never be chosen
DBUG_ASSERT(0);
break;
}
@@ -2614,12 +3732,12 @@ Item_func_set_user_var::update()
}
-double Item_func_set_user_var::val()
+double Item_func_set_user_var::val_real()
{
DBUG_ASSERT(fixed == 1);
check();
update(); // Store expression
- return entry->val(&null_value);
+ return entry->val_real(&null_value);
}
longlong Item_func_set_user_var::val_int()
@@ -2639,6 +3757,15 @@ String *Item_func_set_user_var::val_str(String *str)
}
+my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
+{
+ DBUG_ASSERT(fixed == 1);
+ check();
+ update(); // Store expression
+ return entry->val_decimal(&null_value, val);
+}
+
+
void Item_func_set_user_var::print(String *str)
{
str->append("(@", 2);
@@ -2649,6 +3776,16 @@ void Item_func_set_user_var::print(String *str)
}
+void Item_func_set_user_var::print_as_stmt(String *str)
+{
+ str->append("set @", 5);
+ str->append(name.str, name.length);
+ str->append(":=", 2);
+ args[0]->print(str);
+ str->append(')');
+}
+
+
String *
Item_func_get_user_var::val_str(String *str)
{
@@ -2660,12 +3797,21 @@ Item_func_get_user_var::val_str(String *str)
}
-double Item_func_get_user_var::val()
+double Item_func_get_user_var::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!var_entry)
return 0.0; // No such variable
- return (var_entry->val(&null_value));
+ return (var_entry->val_real(&null_value));
+}
+
+
+my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec)
+{
+ DBUG_ASSERT(fixed == 1);
+ if (!var_entry)
+ return 0;
+ return var_entry->val_decimal(&null_value, dec);
}
@@ -2693,21 +3839,21 @@ longlong Item_func_get_user_var::val_int()
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
-
+ 0 OK
+ 1 Failed to put appropriate record into binary log
+
*/
-int get_var_with_binlog(THD *thd, LEX_STRING &name,
- user_var_entry **out_entry)
+int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
+ LEX_STRING &name, user_var_entry **out_entry)
{
BINLOG_USER_VAR_EVENT *user_var_event;
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)))
+
+ if (!(opt_bin_log && is_update_query(sql_command)))
{
*out_entry= var_entry;
return 0;
@@ -2720,8 +3866,8 @@ int get_var_with_binlog(THD *thd, LEX_STRING &name,
that it gets into the binlog (if it didn't, the slave could be
influenced by a variable of the same name previously set by another
thread).
- We create it like if it had been explicitely set with SET before.
- The 'new' mimicks what sql_yacc.yy does when 'SET @a=10;'.
+ We create it like if it had been explicitly set with SET before.
+ The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
in dispatch_command()). Instead of building a one-element list to pass to
sql_set_variables(), we could instead manually call check() and update();
@@ -2738,7 +3884,8 @@ int get_var_with_binlog(THD *thd, LEX_STRING &name,
if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
goto err;
}
- else if (var_entry->used_query_id == thd->query_id)
+ else if (var_entry->used_query_id == thd->query_id ||
+ mysql_bin_log.is_query_in_union(thd, var_entry->used_query_id))
{
/*
If this variable was already stored in user_var_events by this query
@@ -2752,13 +3899,19 @@ int get_var_with_binlog(THD *thd, LEX_STRING &name,
uint size;
/*
First we need to store value of var_entry, when the next situation
- appers:
+ appears:
> set @a:=1;
> insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
- We have to write to binlog value @a= 1;
+ We have to write to binlog value @a= 1.
+
+ We allocate the user_var_event on user_var_events_alloc pool, not on
+ the this-statement-execution pool because in SPs user_var_event objects
+ may need to be valid after current [SP] statement execution pool is
+ destroyed.
*/
- size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
- if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size)))
+ size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
+ if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
+ alloc_root(thd->user_var_events_alloc, size)))
goto err;
user_var_event->value= (char*) user_var_event +
@@ -2800,7 +3953,7 @@ void Item_func_get_user_var::fix_length_and_dec()
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- error= get_var_with_binlog(thd, name, &var_entry);
+ error= get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry);
if (var_entry)
{
@@ -2808,13 +3961,21 @@ void Item_func_get_user_var::fix_length_and_dec()
switch (var_entry->type) {
case REAL_RESULT:
max_length= DBL_DIG + 8;
+ break;
case INT_RESULT:
max_length= MAX_BIGINT_WIDTH;
+ decimals=0;
break;
case STRING_RESULT:
max_length= MAX_BLOB_WIDTH;
break;
+ case DECIMAL_RESULT:
+ max_length= DECIMAL_MAX_STR_LENGTH;
+ decimals= DECIMAL_MAX_SCALE;
+ break;
case ROW_RESULT: // Keep compiler happy
+ default:
+ DBUG_ASSERT(0);
break;
}
}
@@ -2863,7 +4024,7 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
return 1; // Same item is same.
/* Check if other type is also a get_user_var() object */
if (item->type() != FUNC_ITEM ||
- ((Item_func*) item)->func_name() != func_name())
+ ((Item_func*) item)->functype() != functype())
return 0;
Item_func_get_user_var *other=(Item_func_get_user_var*) item;
return (name.length == other->name.length &&
@@ -2871,6 +4032,76 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
}
+bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
+{
+ DBUG_ASSERT(fixed == 0);
+ if (Item::fix_fields(thd, ref) ||
+ !(entry= get_variable(&thd->user_vars, name, 1)))
+ return TRUE;
+ entry->type= STRING_RESULT;
+ /*
+ Let us set the same collation which is used for loading
+ of fields in LOAD DATA INFILE.
+ (Since Item_user_var_as_out_param is used only there).
+ */
+ entry->collation.set(thd->variables.collation_database);
+ entry->update_query_id= thd->query_id;
+ return FALSE;
+}
+
+
+void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
+{
+ if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
+ DERIVATION_IMPLICIT))
+ current_thd->fatal_error(); // Probably end of memory
+}
+
+
+void Item_user_var_as_out_param::set_value(const char *str, uint length,
+ CHARSET_INFO* cs)
+{
+ if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
+ DERIVATION_IMPLICIT))
+ current_thd->fatal_error(); // Probably end of memory
+}
+
+
+double Item_user_var_as_out_param::val_real()
+{
+ DBUG_ASSERT(0);
+ return 0.0;
+}
+
+
+longlong Item_user_var_as_out_param::val_int()
+{
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
+String* Item_user_var_as_out_param::val_str(String *str)
+{
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
+my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
+{
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
+void Item_user_var_as_out_param::print(String *str)
+{
+ str->append('@');
+ str->append(name.str,name.length);
+}
+
+
Item_func_get_system_var::
Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
LEX_STRING *component_arg, const char *name_arg,
@@ -2883,7 +4114,7 @@ Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
bool
-Item_func_get_system_var::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_func_get_system_var::fix_fields(THD *thd, Item **ref)
{
Item *item;
DBUG_ENTER("Item_func_get_system_var::fix_fields");
@@ -3018,7 +4249,7 @@ void Item_func_match::init_search(bool no_order)
}
-bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
+bool Item_func_match::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
Item *item;
@@ -3033,11 +4264,11 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
modifications to find_best and auto_close as complement to auto_init code
above.
*/
- if (Item_func::fix_fields(thd, tlist, ref) ||
+ if (Item_func::fix_fields(thd, ref) ||
!args[0]->const_during_execution())
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
- return 1;
+ return TRUE;
}
const_item_cache=0;
@@ -3060,7 +4291,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
- return 1;
+ return TRUE;
}
table=((Item_field *)item)->field->table;
if (!(table->file->table_flags() & HA_CAN_FULLTEXT))
@@ -3084,7 +4315,7 @@ bool Item_func_match::fix_index()
if (!table)
goto err;
- for (keynr=0 ; keynr < table->keys ; keynr++)
+ for (keynr=0 ; keynr < table->s->keys ; keynr++)
{
if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
(table->keys_in_use_for_query.is_set(keynr)))
@@ -3150,14 +4381,16 @@ err:
key=NO_SUCH_KEY;
return 0;
}
- my_error(ER_FT_MATCHING_KEY_NOT_FOUND,MYF(0));
+ my_message(ER_FT_MATCHING_KEY_NOT_FOUND,
+ ER(ER_FT_MATCHING_KEY_NOT_FOUND), MYF(0));
return 1;
}
bool Item_func_match::eq(const Item *item, bool binary_cmp) const
{
- if (item->type() != FUNC_ITEM || ((Item_func*)item)->functype() != FT_FUNC ||
+ if (item->type() != FUNC_ITEM ||
+ ((Item_func*)item)->functype() != FT_FUNC ||
flags != ((Item_func_match*)item)->flags)
return 0;
@@ -3171,7 +4404,7 @@ bool Item_func_match::eq(const Item *item, bool binary_cmp) const
}
-double Item_func_match::val()
+double Item_func_match::val_real()
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_match::val");
@@ -3278,7 +4511,7 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
{
if (!var->is_struct())
{
- net_printf(thd, ER_VARIABLE_IS_NOT_STRUCT, base_name->str);
+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);
return 0;
}
}
@@ -3347,10 +4580,280 @@ longlong Item_func_is_used_lock::val_int()
}
-longlong Item_func_found_rows::val_int()
+longlong Item_func_row_count::val_int()
{
DBUG_ASSERT(fixed == 1);
THD *thd= current_thd;
- return thd->found_rows();
+ return thd->row_count_func;
+}
+
+
+Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
+ :Item_func(), context(context_arg), m_name(name), m_sp(NULL),
+ result_field(NULL)
+{
+ maybe_null= 1;
+ m_name->init_qname(current_thd);
+ dummy_table= (TABLE*) sql_calloc(sizeof(TABLE));
+}
+
+
+Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
+ sp_name *name, List<Item> &list)
+ :Item_func(list), context(context_arg), m_name(name), m_sp(NULL),
+ result_field(NULL)
+{
+ maybe_null= 1;
+ m_name->init_qname(current_thd);
+ dummy_table= (TABLE*) sql_calloc(sizeof(TABLE));
+}
+
+void
+Item_func_sp::cleanup()
+{
+ if (result_field)
+ {
+ delete result_field;
+ result_field= NULL;
+ }
+ m_sp= NULL;
+ Item_func::cleanup();
+}
+
+const char *
+Item_func_sp::func_name() const
+{
+ THD *thd= current_thd;
+ /* Calculate length to avoid reallocation of string for sure */
+ uint len= ((m_name->m_db.length +
+ m_name->m_name.length)*2 + //characters*quoting
+ 2 + // ` and `
+ 1 + // .
+ 1 + // end of string
+ ALIGN_SIZE(1)); // to avoid String reallocation
+ String qname((char *)alloc_root(thd->mem_root, len), len,
+ system_charset_info);
+
+ qname.length(0);
+ append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
+ qname.append('.');
+ append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
+ return qname.ptr();
+}
+
+
+Field *
+Item_func_sp::sp_result_field(void) const
+{
+ Field *field;
+ DBUG_ENTER("Item_func_sp::sp_result_field");
+
+ if (!m_sp)
+ {
+ if (!(m_sp= sp_find_function(current_thd, m_name, TRUE)))
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
+ DBUG_RETURN(0);
+ }
+ }
+ if (!dummy_table->s)
+ {
+ char *empty_name= (char *) "";
+ TABLE_SHARE *share;
+ dummy_table->s= share= &dummy_table->share_not_to_be_used;
+ dummy_table->alias = empty_name;
+ dummy_table->maybe_null = maybe_null;
+ dummy_table->in_use= current_thd;
+ share->table_cache_key = empty_name;
+ share->table_name = empty_name;
+ }
+ field= m_sp->make_field(max_length, name, dummy_table);
+ DBUG_RETURN(field);
+}
+
+
+/*
+ Execute function & store value in field
+
+ RETURN
+ 0 value <> NULL
+ 1 value = NULL or error
+*/
+
+int
+Item_func_sp::execute(Field **flp)
+{
+ Item *it;
+ Field *f;
+ if (execute(&it))
+ {
+ null_value= 1;
+ return 1;
+ }
+ if (!(f= *flp))
+ {
+ *flp= f= sp_result_field();
+ f->move_field((f->pack_length() > sizeof(result_buf)) ?
+ sql_alloc(f->pack_length()) : result_buf);
+ f->null_ptr= (uchar *)&null_value;
+ f->null_bit= 1;
+ }
+ it->save_in_field(f, 1);
+ return null_value= f->is_null();
+}
+
+
+int
+Item_func_sp::execute(Item **itp)
+{
+ DBUG_ENTER("Item_func_sp::execute");
+ THD *thd= current_thd;
+ int res= -1;
+ Sub_statement_state statement_state;
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ st_sp_security_context save_ctx;
+#endif
+
+ if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE)))
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
+ goto error;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (check_routine_access(thd, EXECUTE_ACL,
+ m_sp->m_db.str, m_sp->m_name.str, 0, 0))
+ goto error;
+ sp_change_security_context(thd, m_sp, &save_ctx);
+ if (save_ctx.changed &&
+ check_routine_access(thd, EXECUTE_ACL,
+ m_sp->m_db.str, m_sp->m_name.str, 0, 0))
+ goto error_check_ctx;
+#endif
+ /*
+ Disable the binlogging if this is not a SELECT statement. If this is a
+ SELECT, leave binlogging on, so execute_function() code writes the
+ function call into binlog.
+ */
+ thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
+ res= m_sp->execute_function(thd, args, arg_count, itp);
+ thd->restore_sub_statement_state(&statement_state);
+
+ if (res && mysql_bin_log.is_open() &&
+ (m_sp->m_chistics->daccess == SP_CONTAINS_SQL ||
+ m_sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA))
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_FAILED_ROUTINE_BREAK_BINLOG,
+ ER(ER_FAILED_ROUTINE_BREAK_BINLOG));
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+error_check_ctx:
+ sp_restore_security_context(thd, m_sp, &save_ctx);
+#endif
+
+error:
+ DBUG_RETURN(res);
+}
+
+
+void
+Item_func_sp::make_field(Send_field *tmp_field)
+{
+ Field *field;
+ DBUG_ENTER("Item_func_sp::make_field");
+ if ((field= sp_result_field()))
+ {
+ field->make_field(tmp_field);
+ delete field;
+ DBUG_VOID_RETURN;
+ }
+ init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);
+ DBUG_VOID_RETURN;
+}
+
+
+enum enum_field_types
+Item_func_sp::field_type() const
+{
+ Field *field;
+ DBUG_ENTER("Item_func_sp::field_type");
+
+ if (result_field)
+ DBUG_RETURN(result_field->type());
+ if ((field= sp_result_field()))
+ {
+ enum_field_types result= field->type();
+ delete field;
+ DBUG_RETURN(result);
+ }
+ DBUG_RETURN(MYSQL_TYPE_VARCHAR);
+}
+
+
+Item_result
+Item_func_sp::result_type() const
+{
+ Field *field;
+ DBUG_ENTER("Item_func_sp::result_type");
+ DBUG_PRINT("info", ("m_sp = %p", m_sp));
+
+ if (result_field)
+ DBUG_RETURN(result_field->result_type());
+ if ((field= sp_result_field()))
+ {
+ Item_result result= field->result_type();
+ delete field;
+ DBUG_RETURN(result);
+ }
+ DBUG_RETURN(STRING_RESULT);
+}
+
+void
+Item_func_sp::fix_length_and_dec()
+{
+ Field *field;
+ DBUG_ENTER("Item_func_sp::fix_length_and_dec");
+
+ if (result_field)
+ {
+ decimals= result_field->decimals();
+ max_length= result_field->field_length;
+ DBUG_VOID_RETURN;
+ }
+
+ if (!(field= sp_result_field()))
+ {
+ context->process_error(current_thd);
+ DBUG_VOID_RETURN;
+ }
+ decimals= field->decimals();
+ max_length= field->field_length;
+ maybe_null= 1;
+ delete field;
+ DBUG_VOID_RETURN;
+}
+
+
+longlong Item_func_found_rows::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ return current_thd->found_rows();
+}
+
+
+Field *
+Item_func_sp::tmp_table_field(TABLE *t_arg)
+{
+ Field *res= 0;
+ DBUG_ENTER("Item_func_sp::tmp_table_field");
+
+ if (m_sp)
+ res= m_sp->make_field(max_length, (const char *)name, t_arg);
+
+ if (!res)
+ res= Item_func::tmp_table_field(t_arg);
+
+ DBUG_RETURN(res);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 5d6cc445317..019abb0c072 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -43,16 +43,21 @@ public:
bool const_item_cache;
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
GE_FUNC,GT_FUNC,FT_FUNC,
- LIKE_FUNC,NOTLIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC,
- COND_AND_FUNC, COND_OR_FUNC, COND_XOR_FUNC, BETWEEN, IN_FUNC,
+ LIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC,
+ COND_AND_FUNC, COND_OR_FUNC, COND_XOR_FUNC,
+ BETWEEN, IN_FUNC, MULT_EQUAL_FUNC,
INTERVAL_FUNC, ISNOTNULLTEST_FUNC,
SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC,
SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC,
SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC,
SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING,
SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN,
- NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC, VAR_VALUE_FUNC};
- enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL };
+ NOT_FUNC, NOT_ALL_FUNC,
+ NOW_FUNC, TRIG_COND_FUNC,
+ GUSERVAR_FUNC, COLLATE_FUNC,
+ EXTRACT_FUNC, CHAR_TYPECAST_FUNC };
+ enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
+ OPTIMIZE_EQUAL };
enum Type type() const { return FUNC_ITEM; }
virtual enum Functype functype() const { return UNKNOWN_FUNC; }
Item_func(void):
@@ -111,7 +116,7 @@ public:
Item_func(List<Item> &list);
// Constructor used for Item_cond_and/or (see Item comment)
Item_func(THD *thd, Item_func *item);
- bool fix_fields(THD *,struct st_table_list *, Item **ref);
+ bool fix_fields(THD *, Item **ref);
table_map used_tables() const;
table_map not_null_tables() const;
void update_used_tables();
@@ -119,7 +124,17 @@ public:
virtual optimize_type select_optimize() const { return OPTIMIZE_NONE; }
virtual bool have_rev_func() const { return 0; }
virtual Item *key_item() const { return args[0]; }
- virtual const char *func_name() const { return "?"; }
+ /*
+ This method is used for debug purposes to print the name of an
+ item to the debug log. The second use of this method is as
+ a helper function of print(), where it is applicable.
+ To suit both goals it should return a meaningful,
+ distinguishable and sintactically correct string. This method
+ should not be used for runtime type identification, use enum
+ {Sum}Functype and Item_func::functype()/Item_sum::sum_func()
+ instead.
+ */
+ virtual const char *func_name() const= 0;
virtual bool const_item() const { return const_item_cache; }
inline Item **arguments() const { return args; }
void set_arguments(List<Item> &list);
@@ -129,7 +144,10 @@ public:
void print(String *str);
void print_op(String *str);
void print_args(String *str, uint from);
- void fix_num_length_and_dec();
+ virtual void fix_num_length_and_dec();
+ void count_only_length();
+ void count_real_length();
+ void count_decimal_length();
inline bool get_arg0_date(TIME *ltime, uint fuzzy_date)
{
return (null_value=args[0]->get_date(ltime, fuzzy_date));
@@ -139,11 +157,14 @@ public:
return (null_value=args[0]->get_time(ltime));
}
bool is_null() { (void) val_int(); return null_value; }
+ void signal_divide_by_null();
friend class udf_handler;
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg);
Item *get_tmp_table_item(THD *thd);
-
+
+ my_decimal *val_decimal(my_decimal *);
+
bool agg_arg_collations(DTCollation &c, Item **items, uint nitems,
uint flags= 0)
{
@@ -162,6 +183,9 @@ public:
return agg_item_charsets(c, func_name(), items, nitems, flags);
}
bool walk(Item_processor processor, byte *arg);
+ Item *transform(Item_transformer transformer, byte *arg);
+ void traverse_cond(Cond_traverser traverser,
+ void * arg, traverse_order order);
};
@@ -173,52 +197,82 @@ public:
Item_real_func(Item *a,Item *b) :Item_func(a,b) {}
Item_real_func(List<Item> &list) :Item_func(list) {}
String *val_str(String*str);
- longlong val_int() { DBUG_ASSERT(fixed == 1); return (longlong) val(); }
+ my_decimal *val_decimal(my_decimal *decimal_value);
+ longlong val_int()
+ { DBUG_ASSERT(fixed == 1); return (longlong) val_real(); }
enum Item_result result_type () const { return REAL_RESULT; }
- void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
+ void fix_length_and_dec()
+ { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
};
-class Item_num_func :public Item_func
+class Item_func_numhybrid: public Item_func
{
- protected:
+protected:
Item_result hybrid_type;
public:
- Item_num_func(Item *a) :Item_func(a),hybrid_type(REAL_RESULT) {}
- Item_num_func(Item *a,Item *b) :Item_func(a,b),hybrid_type(REAL_RESULT) {}
- String *val_str(String*str);
- longlong val_int() { DBUG_ASSERT(fixed == 1); return (longlong) val(); }
+ Item_func_numhybrid(Item *a) :Item_func(a), hybrid_type(REAL_RESULT)
+ {}
+ Item_func_numhybrid(Item *a,Item *b)
+ :Item_func(a,b), hybrid_type(REAL_RESULT)
+ {}
+ Item_func_numhybrid(List<Item> &list)
+ :Item_func(list), hybrid_type(REAL_RESULT)
+ {}
+
enum Item_result result_type () const { return hybrid_type; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
- bool is_null() { (void) val(); return null_value; }
+ void fix_length_and_dec();
+ void fix_num_length_and_dec();
+ virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */
+
+ double val_real();
+ longlong val_int();
+ my_decimal *val_decimal(my_decimal *);
+ String *val_str(String*str);
+
+ virtual longlong int_op()= 0;
+ virtual double real_op()= 0;
+ virtual my_decimal *decimal_op(my_decimal *)= 0;
+ virtual String *str_op(String *)= 0;
+ bool is_null() { (void) val_real(); return null_value; }
+};
+
+/* function where type of result detected by first argument */
+class Item_func_num1: public Item_func_numhybrid
+{
+public:
+ Item_func_num1(Item *a) :Item_func_numhybrid(a) {}
+ Item_func_num1(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
+
+ void fix_num_length_and_dec();
+ void find_num_type();
+ String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
};
-class Item_num_op :public Item_func
+/* Base class for operations like '+', '-', '*' */
+class Item_num_op :public Item_func_numhybrid
{
- protected:
- Item_result hybrid_type;
public:
- Item_num_op(Item *a,Item *b) :Item_func(a,b),hybrid_type(REAL_RESULT) {}
- String *val_str(String*str);
+ Item_num_op(Item *a,Item *b) :Item_func_numhybrid(a, b) {}
+ virtual void result_precision()= 0;
void print(String *str) { print_op(str); }
- enum Item_result result_type () const { return hybrid_type; }
- void fix_length_and_dec() { fix_num_length_and_dec(); find_num_type(); }
- void find_num_type(void);
- bool is_null() { (void) val(); return null_value; }
+ void find_num_type();
+ String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
};
class Item_int_func :public Item_func
{
public:
- Item_int_func() :Item_func() { max_length=21; }
- Item_int_func(Item *a) :Item_func(a) { max_length=21; }
- Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length=21; }
- Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; }
- Item_int_func(List<Item> &list) :Item_func(list) { max_length=21; }
+ Item_int_func() :Item_func() { max_length= 21; }
+ Item_int_func(Item *a) :Item_func(a) { max_length= 21; }
+ Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length= 21; }
+ Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c)
+ { max_length= 21; }
+ Item_int_func(List<Item> &list) :Item_func(list) { max_length= 21; }
Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {}
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() {}
@@ -230,9 +284,9 @@ class Item_func_signed :public Item_int_func
public:
Item_func_signed(Item *a) :Item_int_func(a) {}
const char *func_name() const { return "cast_as_signed"; }
- double val()
+ double val_real()
{
- double tmp= args[0]->val();
+ double tmp= args[0]->val_real();
null_value= args[0]->null_value;
return tmp;
}
@@ -241,6 +295,8 @@ public:
void fix_length_and_dec()
{ max_length=args[0]->max_length; unsigned_flag=0; }
void print(String *str);
+ uint decimal_precision() const { return args[0]->decimal_precision(); }
+
};
@@ -256,22 +312,53 @@ public:
};
-class Item_func_plus :public Item_num_op
+class Item_decimal_typecast :public Item_func
{
+ my_decimal decimal_value;
public:
- Item_func_plus(Item *a,Item *b) :Item_num_op(a,b) {}
- const char *func_name() const { return "+"; }
- double val();
+ Item_decimal_typecast(Item *a, int len, int dec) :Item_func(a)
+ {
+ max_length= len + 2;
+ decimals= dec;
+ }
+ String *val_str(String *str);
+ double val_real();
longlong val_int();
+ my_decimal *val_decimal(my_decimal*);
+ enum Item_result result_type () const { return DECIMAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ void fix_length_and_dec() {};
+ const char *func_name() const { return "decimal_typecast"; }
+ void print(String *);
+};
+
+
+class Item_func_additive_op :public Item_num_op
+{
+public:
+ Item_func_additive_op(Item *a,Item *b) :Item_num_op(a,b) {}
+ void result_precision();
+};
+
+
+class Item_func_plus :public Item_func_additive_op
+{
+public:
+ Item_func_plus(Item *a,Item *b) :Item_func_additive_op(a,b) {}
+ const char *func_name() const { return "+"; }
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
};
-class Item_func_minus :public Item_num_op
+class Item_func_minus :public Item_func_additive_op
{
public:
- Item_func_minus(Item *a,Item *b) :Item_num_op(a,b) {}
+ Item_func_minus(Item *a,Item *b) :Item_func_additive_op(a,b) {}
const char *func_name() const { return "-"; }
- double val();
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
void fix_length_and_dec();
};
@@ -281,31 +368,36 @@ class Item_func_mul :public Item_num_op
public:
Item_func_mul(Item *a,Item *b) :Item_num_op(a,b) {}
const char *func_name() const { return "*"; }
- double val();
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
+ void result_precision();
};
class Item_func_div :public Item_num_op
{
public:
+ uint prec_increment;
Item_func_div(Item *a,Item *b) :Item_num_op(a,b) {}
- double val();
- longlong val_int();
+ longlong int_op() { DBUG_ASSERT(0); return 0; }
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "/"; }
void fix_length_and_dec();
+ void result_precision();
};
-class Item_func_int_div :public Item_num_op
+class Item_func_int_div :public Item_int_func
{
public:
- Item_func_int_div(Item *a,Item *b) :Item_num_op(a,b)
- { hybrid_type=INT_RESULT; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ Item_func_int_div(Item *a,Item *b) :Item_int_func(a,b)
+ {}
longlong val_int();
const char *func_name() const { return "DIV"; }
void fix_length_and_dec();
+ void print(String *str) { print_op(str); }
};
@@ -313,37 +405,40 @@ class Item_func_mod :public Item_num_op
{
public:
Item_func_mod(Item *a,Item *b) :Item_num_op(a,b) {}
- double val();
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "%"; }
- void fix_length_and_dec();
+ void result_precision();
};
-class Item_func_neg :public Item_num_func
+class Item_func_neg :public Item_func_num1
{
public:
- Item_func_neg(Item *a) :Item_num_func(a) {}
- double val();
- longlong val_int();
+ Item_func_neg(Item *a) :Item_func_num1(a) {}
+ double real_op();
+ longlong int_op();
+ my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "-"; }
void fix_length_and_dec();
+ void fix_num_length_and_dec();
+ uint decimal_precision() const { return args[0]->decimal_precision(); }
};
-class Item_func_abs :public Item_num_func
+class Item_func_abs :public Item_func_num1
{
public:
- Item_func_abs(Item *a) :Item_num_func(a) {}
+ Item_func_abs(Item *a) :Item_func_num1(a) {}
+ double real_op();
+ longlong int_op();
+ my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "abs"; }
- double val();
- longlong val_int();
- enum Item_result result_type () const
- { return args[0]->result_type() == INT_RESULT ? INT_RESULT : REAL_RESULT; }
void fix_length_and_dec();
};
-// A class to handle logaritmic and trigometric functions
+// A class to handle logarithmic and trigonometric functions
class Item_dec_func :public Item_real_func
{
@@ -373,7 +468,7 @@ class Item_func_exp :public Item_dec_func
{
public:
Item_func_exp(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "exp"; }
};
@@ -382,7 +477,7 @@ class Item_func_ln :public Item_dec_func
{
public:
Item_func_ln(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "ln"; }
};
@@ -392,7 +487,7 @@ class Item_func_log :public Item_dec_func
public:
Item_func_log(Item *a) :Item_dec_func(a) {}
Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {}
- double val();
+ double val_real();
const char *func_name() const { return "log"; }
};
@@ -401,7 +496,7 @@ class Item_func_log2 :public Item_dec_func
{
public:
Item_func_log2(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "log2"; }
};
@@ -410,7 +505,7 @@ class Item_func_log10 :public Item_dec_func
{
public:
Item_func_log10(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "log10"; }
};
@@ -419,7 +514,7 @@ class Item_func_sqrt :public Item_dec_func
{
public:
Item_func_sqrt(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "sqrt"; }
};
@@ -428,57 +523,57 @@ class Item_func_pow :public Item_dec_func
{
public:
Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {}
- double val();
+ double val_real();
const char *func_name() const { return "pow"; }
};
class Item_func_acos :public Item_dec_func
{
- public:
+public:
Item_func_acos(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "acos"; }
};
class Item_func_asin :public Item_dec_func
{
- public:
+public:
Item_func_asin(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "asin"; }
};
class Item_func_atan :public Item_dec_func
{
- public:
+public:
Item_func_atan(Item *a) :Item_dec_func(a) {}
Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {}
- double val();
+ double val_real();
const char *func_name() const { return "atan"; }
};
class Item_func_cos :public Item_dec_func
{
- public:
+public:
Item_func_cos(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "cos"; }
};
class Item_func_sin :public Item_dec_func
{
- public:
+public:
Item_func_sin(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "sin"; }
};
class Item_func_tan :public Item_dec_func
{
- public:
+public:
Item_func_tan(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "tan"; }
};
@@ -490,33 +585,48 @@ public:
};
-class Item_func_ceiling :public Item_func_integer
+class Item_func_int_val :public Item_func_num1
{
- Item_func_ceiling(); /* Never called */
public:
- Item_func_ceiling(Item *a) :Item_func_integer(a) {}
+ Item_func_int_val(Item *a) :Item_func_num1(a) {}
+ void fix_num_length_and_dec();
+ void find_num_type();
+};
+
+
+class Item_func_ceiling :public Item_func_int_val
+{
+public:
+ Item_func_ceiling(Item *a) :Item_func_int_val(a) {}
const char *func_name() const { return "ceiling"; }
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
};
-class Item_func_floor :public Item_func_integer
+
+class Item_func_floor :public Item_func_int_val
{
public:
- Item_func_floor(Item *a) :Item_func_integer(a) {}
+ Item_func_floor(Item *a) :Item_func_int_val(a) {}
const char *func_name() const { return "floor"; }
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
};
/* This handles round and truncate */
-class Item_func_round :public Item_real_func
+class Item_func_round :public Item_func_num1
{
bool truncate;
public:
- Item_func_round(Item *a,Item *b,bool trunc_arg)
- :Item_real_func(a,b),truncate(trunc_arg) {}
+ Item_func_round(Item *a, Item *b, bool trunc_arg)
+ :Item_func_num1(a,b), truncate(trunc_arg) {}
const char *func_name() const { return truncate ? "truncate" : "round"; }
- double val();
+ double real_op();
+ longlong int_op();
+ my_decimal *decimal_op(my_decimal *);
void fix_length_and_dec();
};
@@ -527,11 +637,11 @@ class Item_func_rand :public Item_real_func
public:
Item_func_rand(Item *a) :Item_real_func(a), rand(0) {}
Item_func_rand() :Item_real_func() {}
- double val();
+ double val_real();
const char *func_name() const { return "rand"; }
bool const_item() const { return 0; }
void update_used_tables();
- bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
+ bool fix_fields(THD *thd, Item **ref);
};
@@ -548,12 +658,13 @@ class Item_func_units :public Item_real_func
{
char *name;
double mul,add;
- public:
+public:
Item_func_units(char *name_arg,Item *a,double mul_arg,double add_arg)
:Item_real_func(a),name(name_arg),mul(mul_arg),add(add_arg) {}
- double val();
+ double val_real();
const char *func_name() const { return name; }
- void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
+ void fix_length_and_dec()
+ { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
};
@@ -565,12 +676,12 @@ class Item_func_min_max :public Item_func
public:
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list),
cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg) {}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *);
+ my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec();
enum Item_result result_type () const { return cmp_type; }
- table_map not_null_tables() const { return 0; }
};
class Item_func_min :public Item_func_min_max
@@ -755,13 +866,18 @@ public:
Item_func_last_insert_id(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "last_insert_id"; }
- void fix_length_and_dec() { if (arg_count) max_length= args[0]->max_length; }
+ void fix_length_and_dec()
+ {
+ if (arg_count)
+ max_length= args[0]->max_length;
+ }
};
+
class Item_func_benchmark :public Item_int_func
{
ulong loop_count;
- public:
+public:
Item_func_benchmark(ulong loop_count_arg,Item *expr)
:Item_int_func(expr), loop_count(loop_count_arg)
{}
@@ -772,22 +888,39 @@ class Item_func_benchmark :public Item_int_func
};
+class Item_func_sleep :public Item_int_func
+{
+public:
+ Item_func_sleep(Item *a) :Item_int_func(a) {}
+ bool const_item() const { return 0; }
+ const char *func_name() const { return "sleep"; }
+ void update_used_tables()
+ {
+ Item_int_func::update_used_tables();
+ used_tables_cache|= RAND_TABLE_BIT;
+ }
+ longlong val_int();
+};
+
+
+
#ifdef HAVE_DLOPEN
class Item_udf_func :public Item_func
{
- protected:
+protected:
udf_handler udf;
public:
- Item_udf_func(udf_func *udf_arg) :Item_func(), udf(udf_arg) {}
+ Item_udf_func(udf_func *udf_arg)
+ :Item_func(), udf(udf_arg) {}
Item_udf_func(udf_func *udf_arg, List<Item> &list)
:Item_func(list), udf(udf_arg) {}
const char *func_name() const { return udf.name(); }
- bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
+ bool fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
- bool res= udf.fix_fields(thd, tables, this, arg_count, args);
+ bool res= udf.fix_fields(thd, this, arg_count, args);
used_tables_cache= udf.used_tables_cache;
const_item_cache= udf.const_item_cache;
fixed= 1;
@@ -802,12 +935,25 @@ public:
class Item_func_udf_float :public Item_udf_func
{
public:
- Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
- Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
- :Item_udf_func(udf_arg,list) {}
+ Item_func_udf_float(udf_func *udf_arg)
+ :Item_udf_func(udf_arg) {}
+ Item_func_udf_float(udf_func *udf_arg,
+ List<Item> &list)
+ :Item_udf_func(udf_arg, list) {}
longlong val_int()
- { DBUG_ASSERT(fixed == 1); return (longlong) Item_func_udf_float::val(); }
- double val();
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) Item_func_udf_float::val_real();
+ }
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ {
+ double res=val_real();
+ if (null_value)
+ return NULL;
+ double2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf);
+ return dec_buf;
+ }
+ double val_real();
String *val_str(String *str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
};
@@ -816,38 +962,66 @@ class Item_func_udf_float :public Item_udf_func
class Item_func_udf_int :public Item_udf_func
{
public:
- Item_func_udf_int(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
- Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
- :Item_udf_func(udf_arg,list) {}
+ Item_func_udf_int(udf_func *udf_arg)
+ :Item_udf_func(udf_arg) {}
+ Item_func_udf_int(udf_func *udf_arg,
+ List<Item> &list)
+ :Item_udf_func(udf_arg, list) {}
longlong val_int();
- double val() { return (double) Item_func_udf_int::val_int(); }
+ double val_real() { return (double) Item_func_udf_int::val_int(); }
String *val_str(String *str);
enum Item_result result_type () const { return INT_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ void fix_length_and_dec() { decimals= 0; max_length= 21; }
+};
+
+
+class Item_func_udf_decimal :public Item_udf_func
+{
+public:
+ Item_func_udf_decimal(udf_func *udf_arg)
+ :Item_udf_func(udf_arg) {}
+ Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
+ :Item_udf_func(udf_arg, list) {}
+ longlong val_int();
+ double val_real();
+ my_decimal *val_decimal(my_decimal *);
+ String *val_str(String *str);
+ enum Item_result result_type () const { return DECIMAL_RESULT; }
+ void fix_length_and_dec();
};
class Item_func_udf_str :public Item_udf_func
{
public:
- Item_func_udf_str(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
+ Item_func_udf_str(udf_func *udf_arg)
+ :Item_udf_func(udf_arg) {}
Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
- :Item_udf_func(udf_arg,list) {}
+ :Item_udf_func(udf_arg, list) {}
String *val_str(String *);
- double val()
+ double val_real()
{
- int err;
- String *res;
+ int err_not_used;
char *end_not_used;
- res=val_str(&str_value);
- return res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
- &end_not_used, &err) : 0.0;
+ String *res;
+ res= val_str(&str_value);
+ return res ? my_strntod(res->charset(),(char*) res->ptr(),
+ res->length(), &end_not_used, &err_not_used) : 0.0;
}
longlong val_int()
{
- int err;
+ int err_not_used;
String *res; res=val_str(&str_value);
- return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10,(char**) 0,&err) : (longlong) 0;
+ return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10,
+ (char**) 0, &err_not_used) : (longlong) 0;
+ }
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ {
+ String *res=val_str(&str_value);
+ if (!res)
+ return NULL;
+ string2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf);
+ return dec_buf;
}
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
@@ -858,29 +1032,46 @@ public:
class Item_func_udf_float :public Item_real_func
{
public:
- Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {}
- Item_func_udf_float(udf_func *udf_arg, List<Item> &list) :Item_real_func(list) {}
- double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ Item_func_udf_float(udf_func *udf_arg)
+ :Item_real_func() {}
+ Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
+ :Item_real_func(list) {}
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
};
class Item_func_udf_int :public Item_int_func
{
public:
- Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {}
- Item_func_udf_int(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
+ Item_func_udf_int(udf_func *udf_arg)
+ :Item_int_func() {}
+ Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
+ :Item_int_func(list) {}
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
};
+class Item_func_udf_decimal :public Item_int_func
+{
+public:
+ Item_func_udf_decimal(udf_func *udf_arg)
+ :Item_int_func() {}
+ Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
+ :Item_int_func(list) {}
+ my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
+};
+
+
class Item_func_udf_str :public Item_func
{
public:
- Item_func_udf_str(udf_func *udf_arg) :Item_func() {}
- Item_func_udf_str(udf_func *udf_arg, List<Item> &list) :Item_func(list) {}
+ Item_func_udf_str(udf_func *udf_arg)
+ :Item_func() {}
+ Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
+ :Item_func(list) {}
String *val_str(String *)
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
- double val() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; }
longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec() { maybe_null=1; max_length=0; }
@@ -910,7 +1101,7 @@ class Item_func_get_lock :public Item_int_func
class Item_func_release_lock :public Item_int_func
{
String value;
- public:
+public:
Item_func_release_lock(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "release_lock"; }
@@ -922,7 +1113,7 @@ class Item_func_release_lock :public Item_int_func
class Item_master_pos_wait :public Item_int_func
{
String value;
- public:
+public:
Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {}
Item_master_pos_wait(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
longlong val_int();
@@ -931,7 +1122,7 @@ class Item_master_pos_wait :public Item_int_func
};
-/* Handling of user definiable variables */
+/* Handling of user definable variables */
class user_var_entry;
@@ -942,11 +1133,14 @@ class Item_func_set_user_var :public Item_func
user_var_entry *entry;
char buffer[MAX_FIELD_WIDTH];
String value;
+ my_decimal decimal_buff;
+ bool null_item;
union
{
longlong vint;
double vreal;
String *vstr;
+ my_decimal *vdec;
} save_result;
String save_buff;
@@ -955,17 +1149,19 @@ public:
Item_func_set_user_var(LEX_STRING a,Item *b)
:Item_func(b), cached_result_type(INT_RESULT), name(a)
{}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
+ my_decimal *val_decimal(my_decimal *);
bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, Derivation dv);
bool check();
bool update();
enum Item_result result_type () const { return cached_result_type; }
- bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
+ bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
void print(String *str);
+ void print_as_stmt(String *str);
const char *func_name() const { return "set_user_var"; }
};
@@ -978,8 +1174,11 @@ class Item_func_get_user_var :public Item_func
public:
Item_func_get_user_var(LEX_STRING a):
Item_func(), name(a) {}
- double val();
+ enum Functype functype() const { return GUSERVAR_FUNC; }
+ LEX_STRING get_name() { return name; }
+ double val_real();
longlong val_int();
+ my_decimal *val_decimal(my_decimal*);
String *val_str(String* str);
void fix_length_and_dec();
void print(String *str);
@@ -988,8 +1187,7 @@ public:
We must always return variables as strings to guard against selects of type
select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b)
*/
- enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
- enum Functype functype() const { return VAR_VALUE_FUNC; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
const char *func_name() const { return "get_user_var"; }
bool const_item() const;
table_map used_tables() const
@@ -998,6 +1196,35 @@ public:
};
+/*
+ This item represents user variable used as out parameter (e.g in LOAD DATA),
+ and it is supposed to be used only for this purprose. So it is simplified
+ a lot. Actually you should never obtain its value.
+
+ The only two reasons for this thing being an Item is possibility to store it
+ in List<Item> and desire to place this code somewhere near other functions
+ working with user variables.
+*/
+class Item_user_var_as_out_param :public Item
+{
+ LEX_STRING name;
+ user_var_entry *entry;
+public:
+ Item_user_var_as_out_param(LEX_STRING a) : name(a) {}
+ /* We should return something different from FIELD_ITEM here */
+ enum Type type() const { return STRING_ITEM;}
+ double val_real();
+ longlong val_int();
+ String *val_str(String *str);
+ my_decimal *val_decimal(my_decimal *decimal_buffer);
+ /* fix_fields() binds variable name with its entry structure */
+ bool fix_fields(THD *thd, Item **ref);
+ void print(String *str);
+ void set_null_value(CHARSET_INFO* cs);
+ void set_value(const char *str, uint length, CHARSET_INFO* cs);
+};
+
+
/* A system variable */
class Item_func_get_system_var :public Item_func
@@ -1009,15 +1236,17 @@ public:
Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
LEX_STRING *component_arg, const char *name_arg,
size_t name_len_arg);
- bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
+ bool fix_fields(THD *thd, Item **ref);
/*
Stubs for pure virtual methods. Should never be called: this
item is always substituted with a constant in fix_fields().
*/
- double val() { DBUG_ASSERT(0); return 0.0; }
+ double val_real() { DBUG_ASSERT(0); return 0.0; }
longlong val_int() { DBUG_ASSERT(0); return 0; }
String* val_str(String*) { DBUG_ASSERT(0); return 0; }
void fix_length_and_dec() { DBUG_ASSERT(0); }
+ /* TODO: fix to support views */
+ const char *func_name() const { return "get_system_var"; }
};
@@ -1061,22 +1290,18 @@ public:
table->file->ft_handler=0;
table->fulltext_searched=0;
}
- if (concat)
- {
- delete concat;
- concat= 0;
- }
+ concat= 0;
DBUG_VOID_RETURN;
}
enum Functype functype() const { return FT_FUNC; }
const char *func_name() const { return "match"; }
void update_used_tables() {}
table_map not_null_tables() const { return 0; }
- bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
+ bool fix_fields(THD *thd, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
/* The following should be safe, even if we compare doubles */
- longlong val_int() { DBUG_ASSERT(fixed == 1); return val()!=0.0; }
- double val();
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return val_real() != 0.0; }
+ double val_real();
void print(String *str);
bool fix_index();
@@ -1117,7 +1342,99 @@ public:
enum Cast_target
{
ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
- ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR
+ ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR,
+ ITEM_CAST_DECIMAL
+};
+
+
+class Item_func_row_count :public Item_int_func
+{
+public:
+ Item_func_row_count() :Item_int_func() {}
+ longlong val_int();
+ const char *func_name() const { return "row_count"; }
+ void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+};
+
+
+/*
+ *
+ * Stored FUNCTIONs
+ *
+ */
+
+class sp_head;
+class sp_name;
+
+class Item_func_sp :public Item_func
+{
+private:
+ Name_resolution_context *context;
+ sp_name *m_name;
+ mutable sp_head *m_sp;
+ TABLE *dummy_table;
+ Field *result_field;
+ char result_buf[64];
+
+ int execute(Item **itp);
+ int execute(Field **flp);
+ Field *sp_result_field(void) const;
+
+public:
+
+ Item_func_sp(Name_resolution_context *context_arg, sp_name *name);
+
+ Item_func_sp(Name_resolution_context *context_arg,
+ sp_name *name, List<Item> &list);
+
+ virtual ~Item_func_sp()
+ {}
+
+ void cleanup();
+
+ const char *func_name() const;
+
+ enum enum_field_types field_type() const;
+
+ Field *tmp_table_field(TABLE *t_arg);
+
+ void make_field(Send_field *tmp_field);
+
+ Item_result result_type() const;
+
+ longlong val_int()
+ {
+ if (execute(&result_field))
+ return (longlong) 0;
+ return result_field->val_int();
+ }
+
+ double val_real()
+ {
+ if (execute(&result_field))
+ return 0.0;
+ return result_field->val_real();
+ }
+
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ {
+ if (execute(&result_field))
+ return NULL;
+ return result_field->val_decimal(dec_buf);
+ }
+
+ String *val_str(String *str)
+ {
+ if (execute(&result_field))
+ return NULL;
+ return result_field->val_str(str);
+ }
+
+ virtual bool change_context_processor(byte *cntx)
+ { context= (Name_resolution_context *)cntx; return FALSE; }
+
+ void fix_length_and_dec();
+
};
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 8b856d809d6..4a6ceb4bf7d 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -54,8 +54,11 @@ String *Item_func_geometry_from_text::val_str(String *str)
return 0;
str->length(0);
str->q_append(srid);
- if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
- return 0;
+ if (!Geometry::create_from_wkt(&buffer, &trs, str, 0))
+ /* We shouldn't return NULL here as NULL is a legal spatial object */
+ /* Geometry::bad_spatial_data will produce error message beeing stored*/
+ /* in GEOMETRY field */
+ return &Geometry::bad_geometry_data;
return str;
}
@@ -318,8 +321,8 @@ err:
String *Item_func_point::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double x= args[0]->val();
- double y= args[1]->val();
+ double x= args[0]->val_real();
+ double y= args[1]->val_real();
if ((null_value= (args[0]->null_value ||
args[1]->null_value ||
@@ -626,7 +629,7 @@ longlong Item_func_numpoints::val_int()
}
-double Item_func_x::val()
+double Item_func_x::val_real()
{
DBUG_ASSERT(fixed == 1);
double res= 0.0; // In case of errors
@@ -643,7 +646,7 @@ double Item_func_x::val()
}
-double Item_func_y::val()
+double Item_func_y::val_real()
{
DBUG_ASSERT(fixed == 1);
double res= 0; // In case of errors
@@ -660,7 +663,7 @@ double Item_func_y::val()
}
-double Item_func_area::val()
+double Item_func_area::val_real()
{
DBUG_ASSERT(fixed == 1);
double res= 0; // In case of errors
@@ -677,7 +680,7 @@ double Item_func_area::val()
return res;
}
-double Item_func_glength::val()
+double Item_func_glength::val_real()
{
DBUG_ASSERT(fixed == 1);
double res= 0; // In case of errors
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 5f060416ff3..c45fb88a48a 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -263,7 +263,7 @@ class Item_func_x: public Item_real_func
String value;
public:
Item_func_x(Item *a): Item_real_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "x"; }
};
@@ -273,7 +273,7 @@ class Item_func_y: public Item_real_func
String value;
public:
Item_func_y(Item *a): Item_real_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "y"; }
};
@@ -316,7 +316,7 @@ class Item_func_area: public Item_real_func
String value;
public:
Item_func_area(Item *a): Item_real_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "area"; }
};
@@ -326,7 +326,7 @@ class Item_func_glength: public Item_real_func
String value;
public:
Item_func_glength(Item *a): Item_real_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "glength"; }
};
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 12d202a1699..9362518e6ef 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -53,7 +53,7 @@ void Item_row::illegal_method_call(const char *method)
DBUG_VOID_RETURN;
}
-bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
+bool Item_row::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
null_value= 0;
@@ -61,8 +61,8 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
Item **arg, **arg_end;
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
{
- if ((*arg)->fix_fields(thd, tabl, arg))
- return 1;
+ if ((*arg)->fix_fields(thd, arg))
+ return TRUE;
// we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg;
used_tables_cache |= item->used_tables();
@@ -73,15 +73,15 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
with_null|= item->null_inside();
else
{
- item->val_int();
- with_null|= item->null_value;
+ if (item->is_null())
+ with_null|= 1;
}
}
maybe_null|= item->maybe_null;
with_sum_func= with_sum_func || item->with_sum_func;
}
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -138,6 +138,18 @@ bool Item_row::walk(Item_processor processor, byte *arg)
return (this->*processor)(arg);
}
+Item *Item_row::transform(Item_transformer transformer, byte *arg)
+{
+ for (uint i= 0; i < arg_count; i++)
+ {
+ Item *new_item= items[i]->transform(transformer, arg);
+ if (!new_item)
+ return 0;
+ items[i]= new_item;
+ }
+ return (this->*transformer)(arg);
+}
+
void Item_row::bring_value()
{
for (uint i= 0; i < arg_count; i++)
diff --git a/sql/item_row.h b/sql/item_row.h
index 39bc4513e1e..6fbe7436b72 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -41,7 +41,7 @@ public:
{
illegal_method_call((const char*)"make_field");
};
- double val()
+ double val_real()
{
illegal_method_call((const char*)"val");
return 0;
@@ -56,7 +56,12 @@ public:
illegal_method_call((const char*)"val_str");
return 0;
};
- bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
+ my_decimal *val_decimal(my_decimal *)
+ {
+ illegal_method_call((const char*)"val_decimal");
+ return 0;
+ };
+ bool fix_fields(THD *thd, Item **ref);
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
table_map used_tables() const { return used_tables_cache; };
bool const_item() const { return const_item_cache; };
@@ -65,6 +70,7 @@ public:
void print(String *str);
bool walk(Item_processor processor, byte *arg);
+ Item *transform(Item_transformer transformer, byte *arg);
uint cols() { return arg_count; }
Item* el(uint i) { return items[i]; }
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 6962ba7c4ac..309e6dcdcd2 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -41,35 +41,25 @@ String my_empty_string("",default_charset_info);
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
const char *fname)
{
- my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
- c1.collation->name,c1.derivation_name(),
- c2.collation->name,c2.derivation_name(),
- fname);
+ my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
+ c1.collation->name, c1.derivation_name(),
+ c2.collation->name, c2.derivation_name(),
+ fname);
}
-uint nr_of_decimals(const char *str)
-{
- if ((str=strchr(str,'.')))
- {
- const char *start= ++str;
- for (; my_isdigit(system_charset_info,*str) ; str++) ;
- return (uint) (str-start);
- }
- return 0;
-}
-double Item_str_func::val()
+double Item_str_func::val_real()
{
DBUG_ASSERT(fixed == 1);
- int err;
- char buff[64];
- char *end_not_used;
+ int err_not_used;
+ char *end_not_used, buff[64];
String *res, tmp(buff,sizeof(buff), &my_charset_bin);
res= val_str(&tmp);
- return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
- &end_not_used, &err) : 0.0;
+ return res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
+ &end_not_used, &err_not_used) : 0.0;
}
+
longlong Item_str_func::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -467,7 +457,6 @@ String *Item_func_des_decrypt::val_str(String *str)
DBUG_ASSERT(fixed == 1);
#ifdef HAVE_OPENSSL
uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE;
- DES_key_schedule ks1, ks2, ks3;
DES_cblock ivec;
struct st_des_keyblock keyblock;
struct st_des_keyschedule keyschedule;
@@ -937,7 +926,7 @@ void Item_func_insert::fix_length_and_dec()
}
-String *Item_func_lcase::val_str(String *str)
+String *Item_str_conv::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res;
@@ -947,24 +936,25 @@ String *Item_func_lcase::val_str(String *str)
return 0; /* purecov: inspected */
}
null_value=0;
- res=copy_if_not_alloced(str,res,res->length());
- res->casedn();
- return res;
-}
-
-
-String *Item_func_ucase::val_str(String *str)
-{
- DBUG_ASSERT(fixed == 1);
- String *res;
- if (!(res=args[0]->val_str(str)))
+ if (multiply == 1)
{
- null_value=1; /* purecov: inspected */
- return 0; /* purecov: inspected */
+ uint len;
+ res= copy_if_not_alloced(str,res,res->length());
+ len= converter(collation.collation, (char*) res->ptr(), res->length(),
+ (char*) res->ptr(), res->length());
+ DBUG_ASSERT(len <= res->length());
+ res->length(len);
+ }
+ else
+ {
+ uint len= res->length() * multiply;
+ tmp_value.alloc(len);
+ tmp_value.set_charset(collation.collation);
+ len= converter(collation.collation, (char*) res->ptr(), res->length(),
+ (char*) tmp_value.ptr(), len);
+ tmp_value.length(len);
+ res= &tmp_value;
}
- null_value=0;
- res=copy_if_not_alloced(str,res,res->length());
- res->caseup();
return res;
}
@@ -1227,21 +1217,29 @@ String *Item_func_substr_index::val_str(String *str)
String *Item_func_ltrim::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- String *res =args[0]->val_str(str);
- if ((null_value=args[0]->null_value))
- return 0; /* purecov: inspected */
- char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff),res->charset());
- String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove;
+ char buff[MAX_FIELD_WIDTH], *ptr, *end;
+ String tmp(buff,sizeof(buff),system_charset_info);
+ String *res, *remove_str;
uint remove_length;
LINT_INIT(remove_length);
- if (!remove_str || (remove_length=remove_str->length()) == 0 ||
+ res= args[0]->val_str(str);
+ if ((null_value=args[0]->null_value))
+ return 0;
+ remove_str= &remove; /* Default value. */
+ if (arg_count == 2)
+ {
+ remove_str= args[1]->val_str(&tmp);
+ if ((null_value= args[1]->null_value))
+ return 0;
+ }
+
+ if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length())
return res;
- char *ptr=(char*) res->ptr();
- char *end=ptr+res->length();
+ ptr= (char*) res->ptr();
+ end= ptr+res->length();
if (remove_length == 1)
{
char chr=(*remove_str)[0];
@@ -1266,21 +1264,29 @@ String *Item_func_ltrim::val_str(String *str)
String *Item_func_rtrim::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- String *res =args[0]->val_str(str);
- if ((null_value=args[0]->null_value))
- return 0; /* purecov: inspected */
- char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff),res->charset());
- String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove;
+ char buff[MAX_FIELD_WIDTH], *ptr, *end;
+ String tmp(buff, sizeof(buff), system_charset_info);
+ String *res, *remove_str;
uint remove_length;
LINT_INIT(remove_length);
- if (!remove_str || (remove_length=remove_str->length()) == 0 ||
+ res= args[0]->val_str(str);
+ if ((null_value=args[0]->null_value))
+ return 0;
+ remove_str= &remove; /* Default value. */
+ if (arg_count == 2)
+ {
+ remove_str= args[1]->val_str(&tmp);
+ if ((null_value= args[1]->null_value))
+ return 0;
+ }
+
+ if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length())
return res;
- char *ptr=(char*) res->ptr();
- char *end=ptr+res->length();
+ ptr= (char*) res->ptr();
+ end= ptr+res->length();
#ifdef USE_MB
char *p=ptr;
register uint32 l;
@@ -1339,31 +1345,31 @@ String *Item_func_rtrim::val_str(String *str)
String *Item_func_trim::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- String *res =args[0]->val_str(str);
- if ((null_value=args[0]->null_value))
- return 0; /* purecov: inspected */
- char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff),res->charset());
+ char buff[MAX_FIELD_WIDTH], *ptr, *end;
+ const char *r_ptr;
+ String tmp(buff, sizeof(buff), system_charset_info);
+ String *res, *remove_str;
uint remove_length;
LINT_INIT(remove_length);
- String *remove_str; /* The string to remove from res. */
+ res= args[0]->val_str(str);
+ if ((null_value=args[0]->null_value))
+ return 0;
+ remove_str= &remove; /* Default value. */
if (arg_count == 2)
{
remove_str= args[1]->val_str(&tmp);
if ((null_value= args[1]->null_value))
return 0;
}
- else
- remove_str= &remove; /* Default value. */
- if (!remove_str || (remove_length=remove_str->length()) == 0 ||
+ if ((remove_length= remove_str->length()) == 0 ||
remove_length > res->length())
return res;
- char *ptr=(char*) res->ptr();
- char *end=ptr+res->length();
- const char *r_ptr=remove_str->ptr();
+ ptr= (char*) res->ptr();
+ end= ptr+res->length();
+ r_ptr= remove_str->ptr();
while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
ptr+=remove_length;
#ifdef USE_MB
@@ -1555,14 +1561,16 @@ Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs)
uint conv_errors;
String tmp, cstr, *ostr= val_str(&tmp);
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
- if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
- cstr.charset(),
- collation.derivation)))
+ if (conv_errors ||
+ !(conv= new Item_static_string_func(fully_qualified_func_name(),
+ cstr.ptr(), cstr.length(),
+ cstr.charset(),
+ collation.derivation)))
{
return NULL;
}
conv->str_value.copy();
- conv->str_value.shrink_to_length();
+ conv->str_value.mark_as_const();
return conv;
}
@@ -1588,13 +1596,24 @@ String *Item_func_user::val_str(String *str)
DBUG_ASSERT(fixed == 1);
THD *thd=current_thd;
CHARSET_INFO *cs= system_charset_info;
- const char *host= thd->host_or_ip;
+ const char *host, *user;
uint res_length;
+ if (is_current)
+ {
+ user= thd->priv_user;
+ host= thd->priv_host;
+ }
+ else
+ {
+ user= thd->user;
+ host= thd->host_or_ip;
+ }
+
// For system threads (e.g. replication SQL thread) user may be empty
- if (!thd->user)
+ if (!user)
return &my_empty_string;
- res_length= (strlen(thd->user)+strlen(host)+2) * cs->mbmaxlen;
+ res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
if (str->alloc(res_length))
{
@@ -1602,12 +1621,13 @@ String *Item_func_user::val_str(String *str)
return 0;
}
res_length=cs->cset->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s",
- thd->user, host);
+ user, host);
str->length(res_length);
str->set_charset(cs);
return str;
}
+
void Item_func_soundex::fix_length_and_dec()
{
collation.set(args[0]->collation);
@@ -1702,27 +1722,41 @@ Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org)
String *Item_func_format::val_str(String *str)
{
- DBUG_ASSERT(fixed == 1);
- double nr =args[0]->val();
+ uint32 length, str_length ,dec;
int diff;
- uint32 length, str_length;
- uint dec;
- if ((null_value=args[0]->null_value))
- return 0; /* purecov: inspected */
+ DBUG_ASSERT(fixed == 1);
dec= decimals ? decimals+1 : 0;
- /* Here default_charset() is right as this is not an automatic conversion */
- str->set(nr,decimals, default_charset());
- if (isnan(nr))
- return str;
- str_length=str->length();
- if (nr < 0)
- str_length--; // Don't count sign
+ if (args[0]->result_type() == DECIMAL_RESULT ||
+ args[0]->result_type() == INT_RESULT)
+ {
+ my_decimal dec_val, rnd_dec, *res;
+ res= args[0]->val_decimal(&dec_val);
+ my_decimal_round(E_DEC_FATAL_ERROR, res, decimals, false, &rnd_dec);
+ my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str);
+ str_length= str->length();
+ if (rnd_dec.sign())
+ str_length--;
+ }
+ else
+ {
+ double nr= args[0]->val_real();
+ if ((null_value=args[0]->null_value))
+ return 0; /* purecov: inspected */
+ nr= my_double_round(nr, decimals, FALSE);
+ /* Here default_charset() is right as this is not an automatic conversion */
+ str->set(nr,decimals, default_charset());
+ if (isnan(nr))
+ return str;
+ str_length=str->length();
+ if (nr < 0)
+ str_length--; // Don't count sign
+ }
/* We need this test to handle 'nan' values */
if (str_length >= dec+4)
{
char *tmp,*pos;
- length= str->length()+(diff= (int)(str_length- dec-1)/3);
+ length= str->length()+(diff=((int)(str_length- dec-1))/3);
str= copy_if_not_alloced(&tmp_str,str,length);
str->length(length);
tmp= (char*) str->ptr()+length - dec-1;
@@ -1775,14 +1809,14 @@ void Item_func_elt::fix_length_and_dec()
}
-double Item_func_elt::val()
+double Item_func_elt::val_real()
{
DBUG_ASSERT(fixed == 1);
uint tmp;
null_value=1;
if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
return 0.0;
- double result= args[tmp]->val();
+ double result= args[tmp]->val_real();
null_value= args[tmp]->null_value;
return result;
}
@@ -1835,7 +1869,7 @@ void Item_func_make_set::fix_length_and_dec()
for (uint i=0 ; i < arg_count ; i++)
max_length+=args[i]->max_length;
-
+
used_tables_cache|= item->used_tables();
not_null_tables_cache&= item->not_null_tables();
const_item_cache&= item->const_item();
@@ -1946,6 +1980,33 @@ b1: str->append((char)(num>>8));
}
str->set_charset(collation.collation);
str->realloc(str->length()); // Add end 0 (for Purify)
+
+ /* Check whether we got a well-formed string */
+ CHARSET_INFO *cs= collation.collation;
+ int well_formed_error;
+ uint wlen= cs->cset->well_formed_len(cs,
+ str->ptr(), str->ptr() + str->length(),
+ str->length(), &well_formed_error);
+ if (wlen < str->length())
+ {
+ THD *thd= current_thd;
+ char hexbuf[7];
+ enum MYSQL_ERROR::enum_warning_level level;
+ uint diff= str->length() - wlen;
+ set_if_smaller(diff, 3);
+ octet2hex(hexbuf, (const uchar*) str->ptr() + wlen, diff);
+ if (thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))
+ {
+ level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+ null_value= 1;
+ str= 0;
+ }
+ else
+ level= MYSQL_ERROR::WARN_LEVEL_WARN;
+ push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING,
+ ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
+ }
return str;
}
@@ -2098,7 +2159,7 @@ String *Item_func_rpad::val_str(String *str)
func_name(), current_thd->variables.max_allowed_packet);
goto err;
}
- if(args[2]->null_value || !pad_char_length)
+ if (args[2]->null_value || !pad_char_length)
goto err;
res_byte_length= res->length(); /* Must be done before alloc_buffer */
if (!(res= alloc_buffer(res,str,&tmp_value,byte_count)))
@@ -2304,8 +2365,8 @@ void Item_func_set_collation::fix_length_and_dec()
if (!set_collation ||
!my_charset_same(args[0]->collation.collation,set_collation))
{
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- colname,args[0]->collation.collation->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ colname, args[0]->collation.collation->csname);
return;
}
collation.set(set_collation, DERIVATION_EXPLICIT);
@@ -2322,7 +2383,7 @@ bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const
return 0;
Item_func *item_func=(Item_func*) item;
if (arg_count != item_func->arg_count ||
- func_name() != item_func->func_name())
+ functype() != item_func->functype())
return 0;
Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item;
if (collation.collation != item_func_sc->collation.collation)
@@ -2333,6 +2394,18 @@ bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const
return 1;
}
+
+void Item_func_set_collation::print(String *str)
+{
+ str->append('(');
+ args[0]->print(str);
+ str->append(" collate ", 9);
+ DBUG_ASSERT(args[1]->basic_const_item() &&
+ args[1]->type() == Item::STRING_ITEM);
+ args[1]->str_value.print(str);
+ str->append(')');
+}
+
String *Item_func_charset::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -2366,9 +2439,10 @@ String *Item_func_hex::val_str(String *str)
ulonglong dec;
char ans[65],*ptr;
/* Return hex of unsigned longlong value */
- if (args[0]->result_type() == REAL_RESULT)
+ if (args[0]->result_type() == REAL_RESULT ||
+ args[0]->result_type() == DECIMAL_RESULT)
{
- double val= args[0]->val();
+ double val= args[0]->val_real();
if ((val <= (double) LONGLONG_MIN) ||
(val >= (double) (ulonglong) ULONGLONG_MAX))
dec= ~(longlong) 0;
@@ -2913,6 +2987,8 @@ String *Item_func_uuid::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
char *s;
+ THD *thd= current_thd;
+
pthread_mutex_lock(&LOCK_uuid_generator);
if (! uuid_time) /* first UUID() call. initializing data */
{
@@ -2927,7 +3003,7 @@ String *Item_func_uuid::val_str(String *str)
with a clock_seq value (initialized random below), we use a separate
randominit() here
*/
- randominit(&uuid_rand, tmp + (ulong)current_thd, tmp + query_id);
+ randominit(&uuid_rand, tmp + (ulong) thd, tmp + (ulong)query_id);
for (i=0; i < (int)sizeof(mac); i++)
mac[i]=(uchar)(my_rnd(&uuid_rand)*255);
}
@@ -2937,16 +3013,17 @@ String *Item_func_uuid::val_str(String *str)
*--s=_dig_vec_lower[mac[i] & 15];
*--s=_dig_vec_lower[mac[i] >> 4];
}
- randominit(&uuid_rand, tmp + (ulong)start_time, tmp + bytes_sent);
+ randominit(&uuid_rand, tmp + (ulong)start_time,
+ tmp + thd->status_var.bytes_sent);
set_clock_seq_str();
}
ulonglong tv=my_getsystime() + UUID_TIME_OFFSET + nanoseq;
if (unlikely(tv < uuid_time))
set_clock_seq_str();
- else
- if (unlikely(tv == uuid_time))
- { /* special protection from low-res system clocks */
+ else if (unlikely(tv == uuid_time))
+ {
+ /* special protection from low-res system clocks */
nanoseq++;
tv++;
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index b01d75b8e02..fa098849a43 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -32,7 +32,7 @@ public:
Item_str_func(Item *a,Item *b,Item *c,Item *d, Item* e) :Item_func(a,b,c,d,e) {decimals=NOT_FIXED_DEC; }
Item_str_func(List<Item> &list) :Item_func(list) {decimals=NOT_FIXED_DEC; }
longlong val_int();
- double val();
+ double val_real();
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
};
@@ -134,13 +134,14 @@ public:
class Item_str_conv :public Item_str_func
{
+protected:
+ uint multiply;
+ uint (*converter)(CHARSET_INFO *cs, char *src, uint srclen,
+ char *dst, uint dstlen);
+ String tmp_value;
public:
Item_str_conv(Item *item) :Item_str_func(item) {}
- void fix_length_and_dec()
- {
- collation.set(args[0]->collation);
- max_length = args[0]->max_length;
- }
+ String *val_str(String *);
};
@@ -148,16 +149,28 @@ class Item_func_lcase :public Item_str_conv
{
public:
Item_func_lcase(Item *item) :Item_str_conv(item) {}
- String *val_str(String *);
const char *func_name() const { return "lcase"; }
+ void fix_length_and_dec()
+ {
+ collation.set(args[0]->collation);
+ multiply= collation.collation->casedn_multiply;
+ converter= collation.collation->cset->casedn;
+ max_length= args[0]->max_length * multiply;
+ }
};
class Item_func_ucase :public Item_str_conv
{
public:
Item_func_ucase(Item *item) :Item_str_conv(item) {}
- String *val_str(String *);
const char *func_name() const { return "ucase"; }
+ void fix_length_and_dec()
+ {
+ collation.set(args[0]->collation);
+ multiply= collation.collation->caseup_multiply;
+ converter= collation.collation->cset->caseup;
+ max_length= args[0]->max_length * multiply;
+ }
};
@@ -202,7 +215,7 @@ public:
Item_func_substr_index(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
String *val_str(String *);
void fix_length_and_dec();
- const char *func_name() const { return "substr_index"; }
+ const char *func_name() const { return "substring_index"; }
};
@@ -245,7 +258,7 @@ public:
Returns strcat('*', octet2hex(sha1(sha1(password)))). '*' stands for new
password format, sha1(sha1(password) is so-called hash_stage2 value.
Length of returned string is always 41 byte. To find out how entire
- authentification procedure works, see comments in password.c.
+ authentication procedure works, see comments in password.c.
*/
class Item_func_password :public Item_str_func
@@ -310,7 +323,7 @@ public:
Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {}
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; }
- const char *func_name() const { return "ecrypt"; }
+ const char *func_name() const { return "encrypt"; }
};
#include "sql_crypt.h"
@@ -344,8 +357,15 @@ public:
Item_func_sysconst()
{ collation.set(system_charset_info,DERIVATION_SYSCONST); }
Item *safe_charset_converter(CHARSET_INFO *tocs);
+ /*
+ Used to create correct Item name in new converted item in
+ safe_charset_converter, return string representation of this function
+ call
+ */
+ virtual const char *fully_qualified_func_name() const = 0;
};
+
class Item_func_database :public Item_func_sysconst
{
public:
@@ -357,18 +377,27 @@ public:
maybe_null=1;
}
const char *func_name() const { return "database"; }
+ const char *fully_qualified_func_name() const { return "database()"; }
};
+
class Item_func_user :public Item_func_sysconst
{
+ bool is_current;
+
public:
- Item_func_user() :Item_func_sysconst() {}
+ Item_func_user(bool is_current_arg)
+ :Item_func_sysconst(), is_current(is_current_arg) {}
String *val_str(String *);
- void fix_length_and_dec()
- {
- max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*system_charset_info->mbmaxlen;
+ void fix_length_and_dec()
+ {
+ max_length= ((USERNAME_LENGTH + HOSTNAME_LENGTH + 1) *
+ system_charset_info->mbmaxlen);
}
- const char *func_name() const { return "user"; }
+ const char *func_name() const
+ { return is_current ? "current_user" : "user"; }
+ const char *fully_qualified_func_name() const
+ { return is_current ? "current_user()" : "user()"; }
};
@@ -387,7 +416,7 @@ class Item_func_elt :public Item_str_func
{
public:
Item_func_elt(List<Item> &list) :Item_str_func(list) {}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
void fix_length_and_dec();
@@ -403,13 +432,12 @@ class Item_func_make_set :public Item_str_func
public:
Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
String *val_str(String *str);
- bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
+ bool fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
- return (!item->fixed &&
- item->fix_fields(thd, tlist, &item) ||
+ return ((!item->fixed && item->fix_fields(thd, &item)) ||
item->check_cols(1) ||
- Item_func::fix_fields(thd, tlist, ref));
+ Item_func::fix_fields(thd, ref));
}
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
void fix_length_and_dec();
@@ -421,6 +449,14 @@ public:
return item->walk(processor, arg) ||
Item_str_func::walk(processor, arg);
}
+ Item *transform(Item_transformer transformer, byte *arg)
+ {
+ Item *new_item= item->transform(transformer, arg);
+ if (!new_item)
+ return 0;
+ item= new_item;
+ return Item_str_func::transform(transformer, arg);
+ }
void print(String *str);
};
@@ -554,6 +590,7 @@ public:
max_length=args[0]->max_length;
}
void print(String *str);
+ const char *func_name() const { return "cast_as_binary"; }
};
@@ -629,7 +666,13 @@ public:
void fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "collate"; }
- void print(String *str) { print_op(str); }
+ enum Functype func_type() const { return COLLATE_FUNC; }
+ void print(String *str);
+ Item_field *filed_for_view_update()
+ {
+ /* this function is transparent for view updating */
+ return args[0]->filed_for_view_update();
+ }
};
class Item_func_charset :public Item_str_func
@@ -715,7 +758,12 @@ public:
Item_func_uuid(): Item_str_func() {}
void fix_length_and_dec() {
collation.set(system_charset_info);
- max_length= UUID_LENGTH;
+ /*
+ NOTE! uuid() should be changed to use 'ascii'
+ charset when hex(), format(), md5(), etc, and implicit
+ number-to-string conversion will use 'ascii'
+ */
+ max_length= UUID_LENGTH * system_charset_info->mbmaxlen;
}
const char *func_name() const{ return "uuid"; }
String *val_str(String *);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index c8405a9f8f4..52a74b6f4c6 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -53,7 +53,7 @@ void Item_subselect::init(st_select_lex *select_lex,
{
DBUG_ENTER("Item_subselect::init");
- DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
+ DBUG_PRINT("enter", ("select_lex: 0x%x", (ulong) select_lex));
unit= select_lex->master_unit();
if (unit->item)
@@ -66,7 +66,7 @@ void Item_subselect::init(st_select_lex *select_lex,
parsing_place= unit->item->parsing_place;
unit->item->engine= 0;
unit->item= this;
- engine->change_item(this, result);
+ engine->change_result(this, result);
}
else
{
@@ -130,20 +130,20 @@ Item_subselect::select_transformer(JOIN *join)
}
-bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
+bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
{
+ char const *save_where= thd_param->where;
+ bool res;
+
DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
- char const *save_where= thd->where;
- int res;
-
- if (check_stack_overrun(thd, (gptr)&res))
- return 1;
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, (gptr)&res))
+ return TRUE;
res= engine->prepare();
- // all transformetion is done (used by prepared statements)
+ // all transformation is done (used by prepared statements)
changed= 1;
if (!res)
@@ -165,7 +165,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
substitution= 0;
thd->where= "checking transformed subquery";
if (!(*ref)->fixed)
- ret= (*ref)->fix_fields(thd, tables, ref);
+ ret= (*ref)->fix_fields(thd, ref);
thd->where= save_where;
return ret;
}
@@ -173,7 +173,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
if (engine->cols() > max_columns)
{
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
- return 1;
+ return TRUE;
}
fix_length_and_dec();
}
@@ -194,15 +194,8 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
bool Item_subselect::exec()
{
int res;
- MEM_ROOT *old_root= thd->mem_root;
- /*
- As this is execution, all objects should be allocated through the main
- mem root
- */
- thd->mem_root= &thd->main_mem_root;
res= engine->exec();
- thd->mem_root= old_root;
if (engine_changed)
{
@@ -246,7 +239,7 @@ void Item_subselect::update_used_tables()
{
if (!engine->uncacheable())
{
- // did all used tables become ststic?
+ // did all used tables become static?
if (!(used_tables_cache & ~engine->upper_select_const_tables()))
const_item_cache= 1;
}
@@ -271,7 +264,8 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
DBUG_VOID_RETURN;
}
-Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent,
+Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param,
+ Item_subselect *parent,
st_select_lex *select_lex,
bool max_arg)
:Item_singlerow_subselect(), was_values(TRUE)
@@ -290,6 +284,12 @@ Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent,
used_tables_cache= parent->get_used_tables_cache();
const_item_cache= parent->get_const_item_cache();
+ /*
+ this subquery always creates during preparation, so we can assign
+ thd here
+ */
+ thd= thd_param;
+
DBUG_VOID_RETURN;
}
@@ -333,10 +333,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK;
SELECT_LEX *select_lex= join->select_lex;
-
- /* Juggle with current arena only if we're in prepared statement prepare */
- Item_arena *arena= join->thd->current_arena;
-
+ Query_arena *arena= thd->stmt_arena;
+
if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements &&
select_lex->item_list.elements == 1 &&
@@ -351,20 +349,20 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
!(select_lex->item_list.head()->type() == FIELD_ITEM ||
select_lex->item_list.head()->type() == REF_ITEM) &&
/*
- switch off this optimisation for prepare statement,
+ switch off this optimization for prepare statement,
because we do not rollback this changes
TODO: make rollback for it, or special name resolving mode in 5.0.
*/
- !arena->is_stmt_prepare()
+ !arena->is_stmt_prepare_or_first_sp_execute()
)
{
have_to_be_excluded= 1;
- if (join->thd->lex->describe)
+ if (thd->lex->describe)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
- push_warning(join->thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
substitution= select_lex->item_list.head();
@@ -381,6 +379,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK;
}
+
void Item_singlerow_subselect::store(uint i, Item *item)
{
row[i]->store(item);
@@ -443,13 +442,13 @@ void Item_singlerow_subselect::bring_value()
exec();
}
-double Item_singlerow_subselect::val()
+double Item_singlerow_subselect::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value)
{
null_value= 0;
- return value->val();
+ return value->val_real();
}
else
{
@@ -473,7 +472,7 @@ longlong Item_singlerow_subselect::val_int()
}
}
-String *Item_singlerow_subselect::val_str (String *str)
+String *Item_singlerow_subselect::val_str(String *str)
{
if (!exec() && !value->null_value)
{
@@ -488,17 +487,46 @@ String *Item_singlerow_subselect::val_str (String *str)
}
+my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
+{
+ if (!exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val_decimal(decimal_value);
+ }
+ else
+ {
+ reset();
+ return 0;
+ }
+}
+
+
+bool Item_singlerow_subselect::val_bool()
+{
+ if (!exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val_bool();
+ }
+ else
+ {
+ reset();
+ return 0;
+ }
+}
+
+
Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
Item_subselect()
{
DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
+ bool val_bool();
init(select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
value= 0;
- // We need only 1 row to determinate existence
- select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN;
}
@@ -565,9 +593,11 @@ void Item_exists_subselect::fix_length_and_dec()
decimals= 0;
max_length= 1;
max_columns= engine->cols();
+ /* We need only 1 row to determine existence */
+ unit->global_parameters->select_limit= new Item_int((int32) 1);
}
-double Item_exists_subselect::val()
+double Item_exists_subselect::val_real()
{
DBUG_ASSERT(fixed == 1);
if (exec())
@@ -597,12 +627,37 @@ String *Item_exists_subselect::val_str(String *str)
reset();
return 0;
}
- str->set(value,&my_charset_bin);
+ str->set((ulonglong)value,&my_charset_bin);
return str;
}
-double Item_in_subselect::val()
+my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed == 1);
+ if (exec())
+ {
+ reset();
+ return 0;
+ }
+ int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
+ return decimal_value;
+}
+
+
+bool Item_exists_subselect::val_bool()
+{
+ DBUG_ASSERT(fixed == 1);
+ if (exec())
+ {
+ reset();
+ return 0;
+ }
+ return value != 0;
+}
+
+
+double Item_in_subselect::val_real()
{
/*
As far as Item_in_subselect called only from Item_in_optimizer this
@@ -624,6 +679,11 @@ double Item_in_subselect::val()
longlong Item_in_subselect::val_int()
{
+ /*
+ As far as Item_in_subselect called only from Item_in_optimizer this
+ method should not be used
+ */
+ DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
if (exec())
{
@@ -656,20 +716,55 @@ String *Item_in_subselect::val_str(String *str)
null_value= 1;
return 0;
}
- str->set(value, &my_charset_bin);
+ str->set((ulonglong)value, &my_charset_bin);
return str;
}
+bool Item_in_subselect::val_bool()
+{
+ DBUG_ASSERT(fixed == 1);
+ if (exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ return value;
+}
+
+my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
+{
+ /*
+ As far as Item_in_subselect called only from Item_in_optimizer this
+ method should not be used
+ */
+ DBUG_ASSERT(0);
+ DBUG_ASSERT(fixed == 1);
+ if (exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
+ return decimal_value;
+}
+
+
/* Rewrite a single-column IN/ALL/ANY subselect. */
Item_subselect::trans_res
Item_in_subselect::single_value_transformer(JOIN *join,
Comp_creator *func)
{
- DBUG_ENTER("Item_in_subselect::single_value_transformer");
-
+ Item_subselect::trans_res result= RES_ERROR;
SELECT_LEX *select_lex= join->select_lex;
+ DBUG_ENTER("Item_in_subselect::single_value_transformer");
/*
Check that the right part of the subselect contains no more than one
@@ -735,9 +830,10 @@ Item_in_subselect::single_value_transformer(JOIN *join,
/*
Item_sum_(max|min) can't substitute other item => we can use 0 as
- reference
+ reference, also Item_sum_(max|min) can't be fixed after creation, so
+ we do not check item->fixed
*/
- if (item->fix_fields(thd, join->tables_list, 0))
+ if (item->fix_fields(thd, 0))
DBUG_RETURN(RES_ERROR);
/* we added aggregate function => we have to change statistic */
count_field_types(&join->tmp_table_param, join->all_fields, 0);
@@ -747,10 +843,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
else
{
Item_maxmin_subselect *item;
- // remove LIMIT placed by ALL/ANY subquery
- select_lex->master_unit()->global_parameters->select_limit=
- HA_POS_ERROR;
- subs= item= new Item_maxmin_subselect(this, select_lex, func->l_op());
+ subs= item= new Item_maxmin_subselect(thd, this, select_lex, func->l_op());
if (upper_item)
upper_item->set_sub_test(item);
}
@@ -769,7 +862,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
thd->lex->current_select= up= current->return_after_parsing();
//optimizer never use Item **ref => we can pass 0 as parameter
- if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
+ if (!optimizer || optimizer->fix_left(thd, 0))
{
thd->lex->current_select= current;
DBUG_RETURN(RES_ERROR);
@@ -777,10 +870,11 @@ Item_in_subselect::single_value_transformer(JOIN *join,
thd->lex->current_select= current;
/*
- As far as Item_ref_in_optimizer do not substitude itself on fix_fields
+ As far as Item_ref_in_optimizer do not substitute itself on fix_fields
we can use same item for all selects.
*/
- expr= new Item_direct_ref((Item**)optimizer->get_cache(),
+ expr= new Item_direct_ref(&select_lex->context,
+ (Item**)optimizer->get_cache(),
(char *)"<no matter>",
(char *)in_left_expr_name);
@@ -788,9 +882,6 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
- Item *item;
-
- item= (Item*) select_lex->item_list.head();
/*
Add the left part of a subselect to a WHERE or HAVING clause of
the right part, e.g. SELECT 1 IN (SELECT a FROM t1) =>
@@ -801,11 +892,18 @@ Item_in_subselect::single_value_transformer(JOIN *join,
if (join->having || select_lex->with_sum_func ||
select_lex->group_list.elements)
{
- item= func->create(expr,
- new Item_ref_null_helper(this,
- select_lex->ref_pointer_array,
- (char *)"<ref>",
- this->full_name()));
+ bool tmp;
+ Item *item= func->create(expr,
+ new Item_ref_null_helper(&select_lex->context,
+ this,
+ select_lex->
+ ref_pointer_array,
+ (char *)"<ref>",
+ this->full_name()));
+#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
+ if (!abort_on_null && left_expr->maybe_null)
+ item= new Item_cond_or(new Item_func_isnull(left_expr), item);
+#endif
/*
AND and comparison functions can't be changed during fix_fields()
we can assign select_lex->having here, and pass 0 as last
@@ -813,21 +911,26 @@ Item_in_subselect::single_value_transformer(JOIN *join,
*/
select_lex->having= join->having= and_items(join->having, item);
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd, join->tables_list, 0))
- {
- select_lex->having_fix_field= 0;
- DBUG_RETURN(RES_ERROR);
- }
+ /*
+ we do not check join->having->fixed, because Item_and (from and_items)
+ or comparison function (from func->create) can't be fixed after creation
+ */
+ tmp= join->having->fix_fields(thd, 0);
select_lex->having_fix_field= 0;
+ if (tmp)
+ DBUG_RETURN(RES_ERROR);
}
else
{
+ Item *item= (Item*) select_lex->item_list.head();
+
select_lex->item_list.empty();
select_lex->item_list.push_back(new Item_int("Not_used",
(longlong) 1, 21));
select_lex->ref_pointer_array[0]= select_lex->item_list.head();
if (select_lex->table_list.elements)
{
+ bool tmp;
Item *having= item, *orig_item= item;
item= func->create(expr, item);
if (!abort_on_null && orig_item->maybe_null)
@@ -843,14 +946,21 @@ Item_in_subselect::single_value_transformer(JOIN *join,
new Item_cond_and(having, join->having) :
having);
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd, join->tables_list, 0))
- {
- select_lex->having_fix_field= 0;
+ /*
+ we do not check join->having->fixed, because Item_and (from
+ and_items) or comparison function (from func->create) can't be
+ fixed after creation
+ */
+ tmp= join->having->fix_fields(thd, 0);
+ select_lex->having_fix_field= 0;
+ if (tmp)
DBUG_RETURN(RES_ERROR);
- }
- select_lex->having_fix_field= 0;
item= new Item_cond_or(item,
new Item_func_isnull(orig_item));
+#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
+ if (left_expr->maybe_null)
+ item= new Item_cond_or(new Item_func_isnull(left_expr), item);
+#endif
}
item->name= (char *)in_additional_cond;
/*
@@ -860,38 +970,48 @@ Item_in_subselect::single_value_transformer(JOIN *join,
*/
select_lex->where= join->conds= and_items(join->conds, item);
select_lex->where->top_level_item();
- if (join->conds->fix_fields(thd, join->tables_list, 0))
+ /*
+ we do not check join->conds->fixed, because Item_and can't be fixed
+ after creation
+ */
+ if (join->conds->fix_fields(thd, 0))
DBUG_RETURN(RES_ERROR);
}
else
{
+ bool tmp;
if (select_lex->master_unit()->first_select()->next_select())
{
/*
comparison functions can't be changed during fix_fields()
we can assign select_lex->having here, and pass 0 as last
argument (reference) to fix_fields()
- */
- select_lex->having=
- join->having=
- func->create(expr,
- new Item_null_helper(this, item,
- (char *)"<no matter>",
- (char *)"<result>"));
+ */
+ item= func->create(expr,
+ new Item_null_helper(&select_lex->context,
+ this, item,
+ (char *)"<no matter>",
+ (char *)"<result>"));
+#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
+ if (!abort_on_null && left_expr->maybe_null)
+ item= new Item_cond_or(new Item_func_isnull(left_expr), item);
+#endif
+ select_lex->having= join->having= item;
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd, join->tables_list,
- 0))
- {
- select_lex->having_fix_field= 0;
+ /*
+ we do not check join->having->fixed, because comparison function
+ (from func->create) can't be fixed after creation
+ */
+ tmp= join->having->fix_fields(thd, 0);
+ select_lex->having_fix_field= 0;
+ if (tmp)
DBUG_RETURN(RES_ERROR);
- }
- select_lex->having_fix_field= 0;
}
else
{
// it is single select without tables => possible optimization
item= func->create(left_expr, item);
- // fix_field of item will be done in time of substituting
+ // fix_field of item will be done in time of substituting
substitution= item;
have_to_be_excluded= 1;
if (thd->lex->describe)
@@ -936,13 +1056,13 @@ Item_in_subselect::row_value_transformer(JOIN *join)
SELECT_LEX *current= thd->lex->current_select, *up;
thd->lex->current_select= up= current->return_after_parsing();
//optimizer never use Item **ref => we can pass 0 as parameter
- if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
+ if (!optimizer || optimizer->fix_left(thd, 0))
{
thd->lex->current_select= current;
DBUG_RETURN(RES_ERROR);
}
- // we will refer to apper level cache array => we have to save it in PS
+ // we will refer to upper level cache array => we have to save it in PS
optimizer->keep_top_level_cache();
thd->lex->current_select= current;
@@ -973,21 +1093,24 @@ Item_in_subselect::row_value_transformer(JOIN *join)
DBUG_RETURN(RES_ERROR);
Item *item_eq=
new Item_func_eq(new
- Item_direct_ref((*optimizer->get_cache())->
+ Item_direct_ref(&select_lex->context,
+ (*optimizer->get_cache())->
addr(i),
(char *)"<no matter>",
(char *)in_left_expr_name),
new
- Item_direct_ref(select_lex->ref_pointer_array + i,
+ Item_direct_ref(&select_lex->context,
+ select_lex->ref_pointer_array + i,
(char *)"<no matter>",
(char *)"<list ref>")
);
Item *item_isnull=
new Item_func_isnull(new
- Item_direct_ref( select_lex->
- ref_pointer_array+i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_direct_ref(&select_lex->context,
+ select_lex->
+ ref_pointer_array+i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
having_item=
and_items(having_item,
@@ -997,7 +1120,8 @@ Item_in_subselect::row_value_transformer(JOIN *join)
new
Item_is_not_null_test(this,
new
- Item_direct_ref(select_lex->
+ Item_direct_ref(&select_lex->context,
+ select_lex->
ref_pointer_array + i,
(char *)"<no matter>",
(char *)"<list ref>")
@@ -1037,15 +1161,17 @@ Item_in_subselect::row_value_transformer(JOIN *join)
DBUG_RETURN(RES_ERROR);
item=
new Item_func_eq(new
- Item_direct_ref((*optimizer->get_cache())->
+ Item_direct_ref(&select_lex->context,
+ (*optimizer->get_cache())->
addr(i),
(char *)"<no matter>",
(char *)in_left_expr_name),
new
- Item_direct_ref( select_lex->
- ref_pointer_array+i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_direct_ref(&select_lex->context,
+ select_lex->
+ ref_pointer_array+i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
if (!abort_on_null)
{
@@ -1054,7 +1180,8 @@ Item_in_subselect::row_value_transformer(JOIN *join)
new
Item_is_not_null_test(this,
new
- Item_direct_ref(select_lex->
+ Item_direct_ref(&select_lex->context,
+ select_lex->
ref_pointer_array + i,
(char *)"<no matter>",
(char *)"<list ref>")
@@ -1062,10 +1189,11 @@ Item_in_subselect::row_value_transformer(JOIN *join)
);
item_isnull= new
Item_func_isnull(new
- Item_direct_ref( select_lex->
- ref_pointer_array+i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_direct_ref(&select_lex->context,
+ select_lex->
+ ref_pointer_array+i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
item= new Item_cond_or(item, item_isnull);
@@ -1080,7 +1208,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
*/
select_lex->where= join->conds= and_items(join->conds, where_item);
select_lex->where->top_level_item();
- if (join->conds->fix_fields(thd, join->tables_list, 0))
+ if (join->conds->fix_fields(thd, 0))
DBUG_RETURN(RES_ERROR);
}
if (having_item)
@@ -1094,13 +1222,14 @@ Item_in_subselect::row_value_transformer(JOIN *join)
argument (reference) to fix_fields()
*/
select_lex->having_fix_field= 1;
- res= join->having->fix_fields(thd, join->tables_list, 0);
+ res= join->having->fix_fields(thd, 0);
select_lex->having_fix_field= 0;
if (res)
{
DBUG_RETURN(RES_ERROR);
}
}
+
DBUG_RETURN(RES_OK);
}
@@ -1136,7 +1265,7 @@ Item_in_subselect::select_transformer(JOIN *join)
Item_subselect::trans_res
Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
{
- Item_arena *arena, backup;
+ Query_arena *arena, backup;
SELECT_LEX *current= thd->lex->current_select, *up;
const char *save_where= thd->where;
Item_subselect::trans_res res= RES_ERROR;
@@ -1158,18 +1287,17 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
*/
if (!optimizer)
{
- arena= thd->change_arena_if_needed(&backup);
+ arena= thd->activate_stmt_arena_if_needed(&backup);
result= (!(optimizer= new Item_in_optimizer(left_expr, this)));
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ thd->restore_active_arena(arena, &backup);
if (result)
goto err;
}
thd->lex->current_select= up= current->return_after_parsing();
result= (!left_expr->fixed &&
- left_expr->fix_fields(thd, up->get_table_list(),
- optimizer->arguments()));
+ left_expr->fix_fields(thd, optimizer->arguments()));
/* fix_fields can change reference to left_expr, we need reassign it */
left_expr= optimizer->arguments()[0];
@@ -1178,7 +1306,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
goto err;
transformed= 1;
- arena= thd->change_arena_if_needed(&backup);
+ arena= thd->activate_stmt_arena_if_needed(&backup);
/*
Both transformers call fix_fields() only for Items created inside them,
and all that items do not make permanent changes in current item arena
@@ -1194,14 +1322,14 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
if (func != &eq_creator)
{
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ thd->restore_active_arena(arena, &backup);
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
DBUG_RETURN(RES_ERROR);
}
res= row_value_transformer(join);
}
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ thd->restore_active_arena(arena, &backup);
err:
thd->where= save_where;
DBUG_RETURN(res);
@@ -1246,24 +1374,23 @@ void Item_allany_subselect::print(String *str)
}
+void subselect_engine::set_thd(THD *thd_arg)
+{
+ thd= thd_arg;
+ if (result)
+ result->set_thd(thd_arg);
+}
+
+
subselect_single_select_engine::
subselect_single_select_engine(st_select_lex *select,
select_subselect *result,
Item_subselect *item)
:subselect_engine(item, result),
- prepared(0), optimized(0), executed(0), join(0)
+ prepared(0), optimized(0), executed(0),
+ select_lex(select), join(0)
{
- select_lex= select;
- SELECT_LEX_UNIT *unit= select_lex->master_unit();
- unit->offset_limit_cnt= unit->global_parameters->offset_limit;
- unit->select_limit_cnt= unit->global_parameters->select_limit+
- unit->global_parameters ->offset_limit;
- if (unit->select_limit_cnt < unit->global_parameters->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // no limit
- if (unit->select_limit_cnt == HA_POS_ERROR)
- select_lex->options&= ~OPTION_FOUND_ROWS;
- unit->item= item;
- this->select_lex= select_lex;
+ select_lex->master_unit()->item= item;
}
@@ -1406,17 +1533,20 @@ void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row)
int subselect_single_select_engine::exec()
{
DBUG_ENTER("subselect_single_select_engine::exec");
- char const *save_where= join->thd->where;
- SELECT_LEX *save_select= join->thd->lex->current_select;
- join->thd->lex->current_select= select_lex;
+ char const *save_where= thd->where;
+ SELECT_LEX *save_select= thd->lex->current_select;
+ thd->lex->current_select= select_lex;
if (!optimized)
{
- optimized=1;
+ SELECT_LEX_UNIT *unit= select_lex->master_unit();
+
+ optimized= 1;
+ unit->set_limit(unit->global_parameters);
if (join->optimize())
{
- join->thd->where= save_where;
+ thd->where= save_where;
executed= 1;
- join->thd->lex->current_select= save_select;
+ thd->lex->current_select= save_select;
DBUG_RETURN(join->error ? join->error : 1);
}
if (item->engine_changed)
@@ -1428,8 +1558,8 @@ int subselect_single_select_engine::exec()
{
if (join->reinit())
{
- join->thd->where= save_where;
- join->thd->lex->current_select= save_select;
+ thd->where= save_where;
+ thd->lex->current_select= save_select;
DBUG_RETURN(1);
}
item->reset();
@@ -1440,20 +1570,20 @@ int subselect_single_select_engine::exec()
item->reset_value_registration();
join->exec();
executed= 1;
- join->thd->where= save_where;
- join->thd->lex->current_select= save_select;
+ thd->where= save_where;
+ thd->lex->current_select= save_select;
DBUG_RETURN(join->error||thd->is_fatal_error);
}
- join->thd->where= save_where;
- join->thd->lex->current_select= save_select;
+ thd->where= save_where;
+ thd->lex->current_select= save_select;
DBUG_RETURN(0);
}
int subselect_union_engine::exec()
{
- char const *save_where= unit->thd->where;
+ char const *save_where= thd->where;
int res= unit->exec();
- unit->thd->where= save_where;
+ thd->where= save_where;
return res;
}
@@ -1576,7 +1706,7 @@ int subselect_indexsubquery_engine::exec()
uint subselect_single_select_engine::cols()
{
- DBUG_ASSERT(select_lex->join); // should be called after fix_fields()
+ DBUG_ASSERT(select_lex->join != 0); // should be called after fix_fields()
return select_lex->join->fields_list.elements;
}
@@ -1621,7 +1751,7 @@ void subselect_uniquesubquery_engine::exclude()
table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
{
table_map map= 0;
- for (; table; table= table->next)
+ for (; table; table= table->next_leaf)
{
TABLE *tbl= table->table;
if (tbl && tbl->const_table)
@@ -1634,14 +1764,13 @@ table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
table_map subselect_single_select_engine::upper_select_const_tables()
{
return calc_const_tables((TABLE_LIST *) select_lex->outer_select()->
- table_list.first);
+ leaf_tables);
}
table_map subselect_union_engine::upper_select_const_tables()
{
- return calc_const_tables((TABLE_LIST *) unit->outer_select()->
- table_list.first);
+ return calc_const_tables((TABLE_LIST *) unit->outer_select()->leaf_tables);
}
@@ -1662,7 +1791,7 @@ void subselect_uniquesubquery_engine::print(String *str)
str->append("<primary_index_lookup>(", 23);
tab->ref.items[0]->print(str);
str->append(" in ", 4);
- str->append(tab->table->real_name);
+ str->append(tab->table->s->table_name);
KEY *key_info= tab->table->key_info+ tab->ref.key;
str->append(" on ", 4);
str->append(key_info->name);
@@ -1680,12 +1809,12 @@ void subselect_indexsubquery_engine::print(String *str)
str->append("<index_lookup>(", 15);
tab->ref.items[0]->print(str);
str->append(" in ", 4);
- str->append(tab->table->real_name);
+ str->append(tab->table->s->table_name);
KEY *key_info= tab->table->key_info+ tab->ref.key;
str->append(" on ", 4);
str->append(key_info->name);
if (check_null)
- str->append(" chicking NULL", 14);
+ str->append(" checking NULL", 14);
if (cond)
{
str->append(" where ", 7);
@@ -1697,18 +1826,18 @@ void subselect_indexsubquery_engine::print(String *str)
/*
change select_result object of engine
- SINOPSYS
+ SYNOPSIS
subselect_single_select_engine::change_result()
si new subselect Item
res new select_result object
RETURN
- 0 OK
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_single_select_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_single_select_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
item= si;
result= res;
@@ -1719,18 +1848,18 @@ int subselect_single_select_engine::change_item(Item_subselect *si,
/*
change select_result object of engine
- SINOPSYS
+ SYNOPSIS
subselect_single_select_engine::change_result()
si new subselect Item
res new select_result object
RETURN
- 0 OK
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_union_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_union_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
item= si;
int rc= unit->change_result(res, result);
@@ -1742,27 +1871,28 @@ int subselect_union_engine::change_item(Item_subselect *si,
/*
change select_result emulation, never should be called
- SINOPSYS
+ SYNOPSIS
subselect_single_select_engine::change_result()
si new subselect Item
res new select_result object
RETURN
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_uniquesubquery_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_uniquesubquery_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
DBUG_ASSERT(0);
- return -1;
+ return TRUE;
}
/*
Report about presence of tables in subquery
- SINOPSYS
+ SYNOPSIS
subselect_single_select_engine::no_tables()
RETURN
@@ -1778,7 +1908,7 @@ bool subselect_single_select_engine::no_tables()
/*
Report about presence of tables in subquery
- SINOPSYS
+ SYNOPSIS
subselect_union_engine::no_tables()
RETURN
@@ -1799,7 +1929,7 @@ bool subselect_union_engine::no_tables()
/*
Report about presence of tables in subquery
- SINOPSYS
+ SYNOPSIS
subselect_uniquesubquery_engine::no_tables()
RETURN
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index dec32398a80..5b22930ae1f 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -26,7 +26,6 @@ class JOIN;
class select_subselect;
class subselect_engine;
class Item_bool_func2;
-class Statement;
/* base class for subselects */
@@ -92,10 +91,11 @@ public:
val_int();
return null_value;
}
- bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
+ bool fix_fields(THD *thd, Item **ref);
virtual bool exec();
virtual void fix_length_and_dec();
table_map used_tables() const;
+ table_map not_null_tables() const { return 0; }
bool const_item() const;
inline table_map get_used_tables_cache() { return used_tables_cache; }
inline bool get_const_item_cache() { return const_item_cache; }
@@ -114,11 +114,15 @@ public:
mechanism. Engine call this method before rexecution query.
*/
virtual void reset_value_registration() {}
+ enum_parsing_place place() { return parsing_place; }
friend class select_subselect;
friend class Item_in_optimizer;
- friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
- friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **);
+ friend bool Item_field::fix_fields(THD *, Item **);
+ friend bool Item_ref::fix_fields(THD *, Item **);
+ friend void mark_select_range_as_dependent(THD*,
+ st_select_lex*, st_select_lex*,
+ Field*, Item*, Item_ident*);
};
/* single value subselect */
@@ -138,9 +142,11 @@ public:
void reset();
trans_res select_transformer(JOIN *join);
void store(uint i, Item* item);
- double val();
+ double val_real();
longlong val_int ();
String *val_str (String *);
+ my_decimal *val_decimal(my_decimal *);
+ bool val_bool();
enum Item_result result_type() const;
void fix_length_and_dec();
@@ -154,7 +160,7 @@ public:
friend class select_singlerow_subselect;
};
-/* used in static ALL/ANY optimisation */
+/* used in static ALL/ANY optimization */
class select_max_min_finder_subselect;
class Item_maxmin_subselect :public Item_singlerow_subselect
{
@@ -162,7 +168,7 @@ protected:
bool max;
bool was_values; // Set if we have found at least one row
public:
- Item_maxmin_subselect(Item_subselect *parent,
+ Item_maxmin_subselect(THD *thd, Item_subselect *parent,
st_select_lex *select_lex, bool max);
void print(String *str);
void cleanup();
@@ -176,7 +182,7 @@ public:
class Item_exists_subselect :public Item_subselect
{
protected:
- longlong value; /* value of this item (boolean: exists/not-exists) */
+ bool value; /* value of this item (boolean: exists/not-exists) */
public:
Item_exists_subselect(st_select_lex *select_lex);
@@ -190,8 +196,10 @@ public:
enum Item_result result_type() const { return INT_RESULT;}
longlong val_int();
- double val();
+ double val_real();
String *val_str(String*);
+ my_decimal *val_decimal(my_decimal *);
+ bool val_bool();
void fix_length_and_dec();
void print(String *str);
@@ -236,8 +244,10 @@ public:
trans_res single_value_transformer(JOIN *join, Comp_creator *func);
trans_res row_value_transformer(JOIN * join);
longlong val_int();
- double val();
+ double val_real();
String *val_str(String*);
+ my_decimal *val_decimal(my_decimal *);
+ bool val_bool();
void top_level_item() { abort_on_null=1; }
bool test_limit(st_select_lex_unit *unit);
void print(String *str);
@@ -288,13 +298,16 @@ public:
virtual ~subselect_engine() {}; // to satisfy compiler
virtual void cleanup()= 0;
- // set_thd should be called before prepare()
- void set_thd(THD *thd_arg) { thd= thd_arg; }
+ /*
+ Also sets "thd" for subselect_engine::result.
+ Should be called before prepare().
+ */
+ void set_thd(THD *thd_arg);
THD * get_thd() { return thd; }
virtual int prepare()= 0;
virtual void fix_length_and_dec(Item_cache** row)= 0;
virtual int exec()= 0;
- virtual uint cols()= 0; /* return number of columnss in select */
+ virtual uint cols()= 0; /* return number of columns in select */
virtual uint8 uncacheable()= 0; /* query is uncacheable */
enum Item_result type() { return res_type; }
virtual void exclude()= 0;
@@ -302,7 +315,7 @@ public:
virtual table_map upper_select_const_tables()= 0;
static table_map calc_const_tables(TABLE_LIST *);
virtual void print(String *str)= 0;
- virtual int change_item(Item_subselect *si, select_subselect *result)= 0;
+ virtual bool change_result(Item_subselect *si, select_subselect *result)= 0;
virtual bool no_tables()= 0;
};
@@ -327,7 +340,7 @@ public:
void exclude();
table_map upper_select_const_tables();
void print (String *str);
- int change_item(Item_subselect *si, select_subselect *result);
+ bool change_result(Item_subselect *si, select_subselect *result);
bool no_tables();
};
@@ -348,7 +361,7 @@ public:
void exclude();
table_map upper_select_const_tables();
void print (String *str);
- int change_item(Item_subselect *si, select_subselect *result);
+ bool change_result(Item_subselect *si, select_subselect *result);
bool no_tables();
};
@@ -378,7 +391,7 @@ public:
void exclude();
table_map upper_select_const_tables() { return 0; }
void print (String *str);
- int change_item(Item_subselect *si, select_subselect *result);
+ bool change_result(Item_subselect *si, select_subselect *result);
bool no_tables();
};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 6ae782db557..880ab4c8cb1 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -22,6 +22,7 @@
#endif
#include "mysql_priv.h"
+#include "sql_select.h"
Item_sum::Item_sum(List<Item> &list)
:arg_count(list.elements)
@@ -85,7 +86,6 @@ void Item_sum::make_field(Send_field *tmp_field)
void Item_sum::print(String *str)
{
str->append(func_name());
- str->append('(');
for (uint i=0 ; i < arg_count ; i++)
{
if (i)
@@ -124,6 +124,7 @@ Item *Item_sum::get_tmp_table_item(THD *thd)
return sum_item;
}
+
bool Item_sum::walk (Item_processor processor, byte *argument)
{
if (arg_count)
@@ -138,52 +139,78 @@ bool Item_sum::walk (Item_processor processor, byte *argument)
return (this->*processor)(argument);
}
+
+Field *Item_sum::create_tmp_field(bool group, TABLE *table,
+ uint convert_blob_length)
+{
+ switch (result_type()) {
+ case REAL_RESULT:
+ return new Field_double(max_length,maybe_null,name,table,decimals);
+ case INT_RESULT:
+ return new Field_longlong(max_length,maybe_null,name,table,unsigned_flag);
+ case STRING_RESULT:
+ if (max_length > 255 && convert_blob_length)
+ return new Field_varstring(convert_blob_length, maybe_null,
+ name, table,
+ collation.collation);
+ return make_string_field(table);
+ case DECIMAL_RESULT:
+ return new Field_new_decimal(max_length, maybe_null, name, table,
+ decimals, unsigned_flag);
+ case ROW_RESULT:
+ default:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
+
String *
Item_sum_num::val_str(String *str)
{
- DBUG_ASSERT(fixed == 1);
- double nr=val();
- if (null_value)
- return 0;
- str->set(nr,decimals, &my_charset_bin);
- return str;
+ return val_string_from_real(str);
+}
+
+
+my_decimal *Item_sum_num::val_decimal(my_decimal *decimal_value)
+{
+ return val_decimal_from_real(decimal_value);
}
String *
Item_sum_int::val_str(String *str)
{
- DBUG_ASSERT(fixed == 1);
- longlong nr= val_int();
- if (null_value)
- return 0;
- if (unsigned_flag)
- str->set((ulonglong) nr, &my_charset_bin);
- else
- str->set(nr, &my_charset_bin);
- return str;
+ return val_string_from_int(str);
+}
+
+
+my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value)
+{
+ return val_decimal_from_int(decimal_value);
}
bool
-Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_sum_num::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
thd->allow_sum_func=0; // No included group funcs
decimals=0;
maybe_null=0;
for (uint i=0 ; i < arg_count ; i++)
{
- if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
- return 1;
- if (decimals < args[i]->decimals)
- decimals=args[i]->decimals;
+ if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1))
+ return TRUE;
+ set_if_bigger(decimals, args[i]->decimals);
maybe_null |= args[i]->maybe_null;
}
result_field=0;
@@ -192,42 +219,80 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
fix_length_and_dec();
thd->allow_sum_func=1; // Allow group functions
fixed= 1;
- return 0;
+ return FALSE;
}
+Item_sum_hybrid::Item_sum_hybrid(THD *thd, Item_sum_hybrid *item)
+ :Item_sum(thd, item), value(item->value), hybrid_type(item->hybrid_type),
+ hybrid_field_type(item->hybrid_field_type), cmp_sign(item->cmp_sign),
+ used_table_cache(item->used_table_cache), was_values(item->was_values)
+{
+ /* copy results from old value */
+ switch (hybrid_type) {
+ case INT_RESULT:
+ sum_int= item->sum_int;
+ break;
+ case DECIMAL_RESULT:
+ my_decimal2decimal(&item->sum_dec, &sum_dec);
+ break;
+ case REAL_RESULT:
+ sum= item->sum;
+ break;
+ case STRING_RESULT:
+ /*
+ This can happen with ROLLUP. Note that the value is already
+ copied at function call.
+ */
+ break;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ collation.set(item->collation);
+}
+
bool
-Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
Item *item= args[0];
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
thd->allow_sum_func=0; // No included group funcs
// 'item' can be changed during fix_fields
if (!item->fixed &&
- item->fix_fields(thd, tables, args) ||
+ item->fix_fields(thd, args) ||
(item= args[0])->check_cols(1))
- return 1;
-
- hybrid_type= item->result_type();
- if (hybrid_type == INT_RESULT)
- {
- max_length=20;
- }
- else if (hybrid_type == REAL_RESULT)
- {
- max_length=float_length(decimals);
- }else
- {
- max_length=item->max_length;
- }
+ return TRUE;
decimals=item->decimals;
+
+ switch (hybrid_type= item->result_type()) {
+ case INT_RESULT:
+ max_length= 20;
+ sum_int= 0;
+ break;
+ case DECIMAL_RESULT:
+ max_length= item->max_length;
+ my_decimal_set_zero(&sum_dec);
+ break;
+ case REAL_RESULT:
+ max_length= float_length(decimals);
+ sum= 0.0;
+ break;
+ case STRING_RESULT:
+ max_length= item->max_length;
+ break;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ };
/* MIN/MAX can return NULL for empty set indepedent of the used column */
maybe_null= 1;
unsigned_flag=item->unsigned_flag;
@@ -241,7 +306,38 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
else
hybrid_field_type= Item::field_type();
fixed= 1;
- return 0;
+ return FALSE;
+}
+
+Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table,
+ uint convert_blob_length)
+{
+ if (args[0]->type() == Item::FIELD_ITEM)
+ {
+ Field *field= ((Item_field*) args[0])->field;
+
+ if ((field= create_tmp_field_from_field(current_thd, field, name, table,
+ NULL, convert_blob_length)))
+ field->flags&= ~NOT_NULL_FLAG;
+ return field;
+ }
+ /*
+ DATE/TIME fields have STRING_RESULT result types.
+ In order to preserve field type, it's needed to handle DATE/TIME
+ fields creations separately.
+ */
+ switch (args[0]->field_type()) {
+ case MYSQL_TYPE_DATE:
+ return new Field_date(maybe_null, name, table, collation.collation);
+ case MYSQL_TYPE_TIME:
+ return new Field_time(maybe_null, name, table, collation.collation);
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ return new Field_datetime(maybe_null, name, table, collation.collation);
+ default:
+ break;
+ }
+ return Item_sum::create_tmp_field(group, table, convert_blob_length);
}
@@ -249,6 +345,20 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
** reset and add of sum_func
***********************************************************************/
+Item_sum_sum::Item_sum_sum(THD *thd, Item_sum_sum *item)
+ :Item_sum_num(thd, item), hybrid_type(item->hybrid_type),
+ curr_dec_buff(item->curr_dec_buff)
+{
+ /* TODO: check if the following assignments are really needed */
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ my_decimal2decimal(item->dec_buffs, dec_buffs);
+ my_decimal2decimal(item->dec_buffs + 1, dec_buffs + 1);
+ }
+ else
+ sum= item->sum;
+}
+
Item *Item_sum_sum::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_sum_sum(thd, this);
@@ -257,26 +367,404 @@ Item *Item_sum_sum::copy_or_same(THD* thd)
void Item_sum_sum::clear()
{
- null_value=1; sum=0.0;
+ DBUG_ENTER("Item_sum_sum::clear");
+ null_value=1;
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ curr_dec_buff= 0;
+ my_decimal_set_zero(dec_buffs);
+ }
+ else
+ sum= 0.0;
+ DBUG_VOID_RETURN;
+}
+
+
+void Item_sum_sum::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_sum_sum::fix_length_and_dec");
+ maybe_null=null_value=1;
+ decimals= args[0]->decimals;
+ switch (args[0]->result_type()) {
+ case REAL_RESULT:
+ case STRING_RESULT:
+ hybrid_type= REAL_RESULT;
+ sum= 0.0;
+ break;
+ case INT_RESULT:
+ case DECIMAL_RESULT:
+ {
+ /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
+ int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
+ curr_dec_buff= 0;
+ hybrid_type= DECIMAL_RESULT;
+ my_decimal_set_zero(dec_buffs);
+ break;
+ }
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ DBUG_PRINT("info", ("Type: %s (%d, %d)",
+ (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
+ hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ hybrid_type == INT_RESULT ? "INT_RESULT" :
+ "--ILLEGAL!!!--"),
+ max_length,
+ (int)decimals));
+ DBUG_VOID_RETURN;
}
bool Item_sum_sum::add()
{
- sum+=args[0]->val();
- if (!args[0]->null_value)
- null_value= 0;
- return 0;
+ DBUG_ENTER("Item_sum_sum::add");
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ my_decimal value, *val= args[0]->val_decimal(&value);
+ if (!args[0]->null_value)
+ {
+ my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff^1),
+ val, dec_buffs + curr_dec_buff);
+ curr_dec_buff^= 1;
+ null_value= 0;
+ }
+ }
+ else
+ {
+ sum+= args[0]->val_real();
+ if (!args[0]->null_value)
+ null_value= 0;
+ }
+ DBUG_RETURN(0);
}
-double Item_sum_sum::val()
+longlong Item_sum_sum::val_int()
{
DBUG_ASSERT(fixed == 1);
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ longlong result;
+ my_decimal2int(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, unsigned_flag,
+ &result);
+ return result;
+ }
+ return (longlong) val_real();
+}
+
+
+double Item_sum_sum::val_real()
+{
+ DBUG_ASSERT(fixed == 1);
+ if (hybrid_type == DECIMAL_RESULT)
+ my_decimal2double(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, &sum);
return sum;
}
+String *Item_sum_sum::val_str(String *str)
+{
+ if (hybrid_type == DECIMAL_RESULT)
+ return val_string_from_decimal(str);
+ return val_string_from_real(str);
+}
+
+
+my_decimal *Item_sum_sum::val_decimal(my_decimal *val)
+{
+ if (hybrid_type == DECIMAL_RESULT)
+ return (dec_buffs + curr_dec_buff);
+ return val_decimal_from_real(val);
+}
+
+/***************************************************************************/
+
+C_MODE_START
+
+/* Declarations for auxilary C-callbacks */
+
+static int simple_raw_key_cmp(void* arg, const void* key1, const void* key2)
+{
+ return memcmp(key1, key2, *(uint *) arg);
+}
+
+
+static int item_sum_distinct_walk(void *element, element_count num_of_dups,
+ void *item)
+{
+ return ((Item_sum_distinct*) (item))->unique_walk_function(element);
+}
+
+C_MODE_END
+
+/* Item_sum_distinct */
+
+Item_sum_distinct::Item_sum_distinct(Item *item_arg)
+ :Item_sum_num(item_arg), tree(0)
+{
+ /*
+ quick_group is an optimizer hint, which means that GROUP BY can be
+ handled with help of index on grouped columns.
+ By setting quick_group to zero we force creation of temporary table
+ to perform GROUP BY.
+ */
+ quick_group= 0;
+}
+
+
+Item_sum_distinct::Item_sum_distinct(THD *thd, Item_sum_distinct *original)
+ :Item_sum_num(thd, original), val(original->val), tree(0),
+ table_field_type(original->table_field_type)
+{
+ quick_group= 0;
+}
+
+
+/*
+ Behaves like an Integer except to fix_length_and_dec().
+ Additionally div() converts val with this traits to a val with true
+ decimal traits along with conversion of integer value to decimal value.
+ This is to speedup SUM/AVG(DISTINCT) evaluation for 8-32 bit integer
+ values.
+*/
+struct Hybrid_type_traits_fast_decimal: public
+ Hybrid_type_traits_integer
+{
+ virtual Item_result type() const { return DECIMAL_RESULT; }
+ virtual void fix_length_and_dec(Item *item, Item *arg) const
+ { Hybrid_type_traits_decimal::instance()->fix_length_and_dec(item, arg); }
+
+ virtual void div(Hybrid_type *val, ulonglong u) const
+ {
+ int2my_decimal(E_DEC_FATAL_ERROR, val->integer, 0, val->dec_buf);
+ val->used_dec_buf_no= 0;
+ val->traits= Hybrid_type_traits_decimal::instance();
+ val->traits->div(val, u);
+ }
+ static const Hybrid_type_traits_fast_decimal *instance();
+};
+
+static const Hybrid_type_traits_fast_decimal fast_decimal_traits_instance;
+
+const Hybrid_type_traits_fast_decimal
+ *Hybrid_type_traits_fast_decimal::instance()
+{
+ return &fast_decimal_traits_instance;
+}
+
+void Item_sum_distinct::fix_length_and_dec()
+{
+ DBUG_ASSERT(args[0]->fixed);
+
+ table_field_type= args[0]->field_type();
+
+ /* Adjust tmp table type according to the chosen aggregation type */
+ switch (args[0]->result_type()) {
+ case STRING_RESULT:
+ case REAL_RESULT:
+ val.traits= Hybrid_type_traits::instance();
+ if (table_field_type != MYSQL_TYPE_FLOAT)
+ table_field_type= MYSQL_TYPE_DOUBLE;
+ break;
+ case INT_RESULT:
+ /*
+ Preserving int8, int16, int32 field types gives ~10% performance boost
+ as the size of result tree becomes significantly smaller.
+ Another speed up we gain by using longlong for intermediate
+ calculations. The range of int64 is enough to hold sum 2^32 distinct
+ integers each <= 2^32.
+ */
+ if (table_field_type == MYSQL_TYPE_INT24 ||
+ table_field_type >= MYSQL_TYPE_TINY &&
+ table_field_type <= MYSQL_TYPE_LONG)
+ {
+ val.traits= Hybrid_type_traits_fast_decimal::instance();
+ break;
+ }
+ table_field_type= MYSQL_TYPE_LONGLONG;
+ /* fallthrough */
+ case DECIMAL_RESULT:
+ val.traits= Hybrid_type_traits_decimal::instance();
+ if (table_field_type != MYSQL_TYPE_LONGLONG)
+ table_field_type= MYSQL_TYPE_NEWDECIMAL;
+ break;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ val.traits->fix_length_and_dec(this, args[0]);
+}
+
+
+bool Item_sum_distinct::setup(THD *thd)
+{
+ List<create_field> field_list;
+ create_field field_def; /* field definition */
+ DBUG_ENTER("Item_sum_distinct::setup");
+ DBUG_ASSERT(tree == 0);
+
+ /*
+ Virtual table and the tree are created anew on each re-execution of
+ PS/SP. Hence all further allocations are performed in the runtime
+ mem_root.
+ */
+ if (field_list.push_back(&field_def))
+ return TRUE;
+
+ null_value= maybe_null= 1;
+ quick_group= 0;
+
+ DBUG_ASSERT(args[0]->fixed);
+
+ field_def.init_for_tmp_table(table_field_type, args[0]->max_length,
+ args[0]->decimals, args[0]->maybe_null,
+ args[0]->unsigned_flag);
+
+ if (! (table= create_virtual_tmp_table(thd, field_list)))
+ return TRUE;
+
+ /* XXX: check that the case of CHAR(0) works OK */
+ tree_key_length= table->s->reclength - table->s->null_bytes;
+
+ /*
+ Unique handles all unique elements in a tree until they can't fit
+ in. Then the tree is dumped to the temporary file. We can use
+ simple_raw_key_cmp because the table contains numbers only; decimals
+ are converted to binary representation as well.
+ */
+ tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
+ thd->variables.max_heap_table_size);
+
+ DBUG_RETURN(tree == 0);
+}
+
+
+bool Item_sum_distinct::add()
+{
+ args[0]->save_in_field(table->field[0], FALSE);
+ if (!table->field[0]->is_null())
+ {
+ DBUG_ASSERT(tree);
+ null_value= 0;
+ /*
+ '0' values are also stored in the tree. This doesn't matter
+ for SUM(DISTINCT), but is important for AVG(DISTINCT)
+ */
+ return tree->unique_add(table->field[0]->ptr);
+ }
+ return 0;
+}
+
+
+bool Item_sum_distinct::unique_walk_function(void *element)
+{
+ memcpy(table->field[0]->ptr, element, tree_key_length);
+ ++count;
+ val.traits->add(&val, table->field[0]);
+ return 0;
+}
+
+
+void Item_sum_distinct::clear()
+{
+ DBUG_ENTER("Item_sum_distinct::clear");
+ DBUG_ASSERT(tree != 0); /* we always have a tree */
+ null_value= 1;
+ tree->reset();
+ DBUG_VOID_RETURN;
+}
+
+void Item_sum_distinct::cleanup()
+{
+ Item_sum_num::cleanup();
+ delete tree;
+ tree= 0;
+ table= 0;
+}
+
+Item_sum_distinct::~Item_sum_distinct()
+{
+ delete tree;
+ /* no need to free the table */
+}
+
+
+void Item_sum_distinct::calculate_val_and_count()
+{
+ count= 0;
+ val.traits->set_zero(&val);
+ /*
+ We don't have a tree only if 'setup()' hasn't been called;
+ this is the case of sql_select.cc:return_zero_rows.
+ */
+ if (tree)
+ {
+ table->field[0]->set_notnull();
+ tree->walk(item_sum_distinct_walk, (void*) this);
+ }
+}
+
+
+double Item_sum_distinct::val_real()
+{
+ calculate_val_and_count();
+ return val.traits->val_real(&val);
+}
+
+
+my_decimal *Item_sum_distinct::val_decimal(my_decimal *to)
+{
+ calculate_val_and_count();
+ if (null_value)
+ return 0;
+ return val.traits->val_decimal(&val, to);
+}
+
+
+longlong Item_sum_distinct::val_int()
+{
+ calculate_val_and_count();
+ return val.traits->val_int(&val, unsigned_flag);
+}
+
+
+String *Item_sum_distinct::val_str(String *str)
+{
+ calculate_val_and_count();
+ if (null_value)
+ return 0;
+ return val.traits->val_str(&val, str, decimals);
+}
+
+/* end of Item_sum_distinct */
+
+/* Item_sum_avg_distinct */
+
+void
+Item_sum_avg_distinct::fix_length_and_dec()
+{
+ Item_sum_distinct::fix_length_and_dec();
+ prec_increment= current_thd->variables.div_precincrement;
+ /*
+ AVG() will divide val by count. We need to reserve digits
+ after decimal point as the result can be fractional.
+ */
+ decimals= min(decimals + prec_increment, NOT_FIXED_DEC);
+}
+
+
+void
+Item_sum_avg_distinct::calculate_val_and_count()
+{
+ Item_sum_distinct::calculate_val_and_count();
+ if (count)
+ val.traits->div(&val, count);
+}
+
+
Item *Item_sum_count::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_sum_count(thd, this);
@@ -321,6 +809,25 @@ void Item_sum_count::cleanup()
/*
Avgerage
*/
+void Item_sum_avg::fix_length_and_dec()
+{
+ Item_sum_sum::fix_length_and_dec();
+ maybe_null=null_value=1;
+ prec_increment= current_thd->variables.div_precincrement;
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ int precision= args[0]->decimal_precision() + prec_increment;
+ decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
+ f_precision= min(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
+ f_scale= args[0]->decimals;
+ dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
+ }
+ else
+ decimals= min(args[0]->decimals + prec_increment, NOT_FIXED_DEC);
+}
+
Item *Item_sum_avg::copy_or_same(THD* thd)
{
@@ -328,24 +835,44 @@ Item *Item_sum_avg::copy_or_same(THD* thd)
}
+Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table,
+ uint convert_blob_len)
+{
+ if (group)
+ {
+ /*
+ We must store both value and counter in the temporary table in one field.
+ The easyest way is to do this is to store both value in a string
+ and unpack on access.
+ */
+ return new Field_string(((hybrid_type == DECIMAL_RESULT) ?
+ dec_bin_size : sizeof(double)) + sizeof(longlong),
+ 0, name, table, &my_charset_bin);
+ }
+ if (hybrid_type == DECIMAL_RESULT)
+ return new Field_new_decimal(max_length, maybe_null, name, table,
+ decimals, unsigned_flag);
+ return new Field_double(max_length, maybe_null, name, table, decimals);
+}
+
+
void Item_sum_avg::clear()
{
- sum=0.0; count=0;
+ Item_sum_sum::clear();
+ count=0;
}
bool Item_sum_avg::add()
{
- double nr=args[0]->val();
+ if (Item_sum_sum::add())
+ return TRUE;
if (!args[0]->null_value)
- {
- sum+=nr;
count++;
- }
- return 0;
+ return FALSE;
}
-double Item_sum_avg::val()
+double Item_sum_avg::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!count)
@@ -353,8 +880,32 @@ double Item_sum_avg::val()
null_value=1;
return 0.0;
}
- null_value=0;
- return sum/ulonglong2double(count);
+ return Item_sum_sum::val_real() / ulonglong2double(count);
+}
+
+
+my_decimal *Item_sum_avg::val_decimal(my_decimal *val)
+{
+ my_decimal sum, cnt;
+ const my_decimal *sum_dec;
+ DBUG_ASSERT(fixed == 1);
+ if (!count)
+ {
+ null_value=1;
+ return NULL;
+ }
+ sum_dec= Item_sum_sum::val_decimal(&sum);
+ int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &cnt);
+ my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, prec_increment);
+ return val;
+}
+
+
+String *Item_sum_avg::val_str(String *str)
+{
+ if (hybrid_type == DECIMAL_RESULT)
+ return val_string_from_decimal(str);
+ return val_string_from_real(str);
}
@@ -362,10 +913,10 @@ double Item_sum_avg::val()
Standard deviation
*/
-double Item_sum_std::val()
+double Item_sum_std::val_real()
{
DBUG_ASSERT(fixed == 1);
- double tmp= Item_sum_variance::val();
+ double tmp= Item_sum_variance::val_real();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
@@ -379,34 +930,163 @@ Item *Item_sum_std::copy_or_same(THD* thd)
Variance
*/
+
+Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item):
+ Item_sum_num(thd, item), hybrid_type(item->hybrid_type),
+ cur_dec(item->cur_dec), count(item->count), sample(item->sample),
+ prec_increment(item->prec_increment)
+{
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ memcpy(dec_sum, item->dec_sum, sizeof(item->dec_sum));
+ memcpy(dec_sqr, item->dec_sqr, sizeof(item->dec_sqr));
+ for (int i=0; i<2; i++)
+ {
+ dec_sum[i].fix_buffer_pointer();
+ dec_sqr[i].fix_buffer_pointer();
+ }
+ }
+ else
+ {
+ sum= item->sum;
+ sum_sqr= item->sum_sqr;
+ }
+}
+
+
+void Item_sum_variance::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_sum_variance::fix_length_and_dec");
+ maybe_null= null_value= 1;
+ prec_increment= current_thd->variables.div_precincrement;
+ switch (args[0]->result_type()) {
+ case REAL_RESULT:
+ case STRING_RESULT:
+ decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC);
+ hybrid_type= REAL_RESULT;
+ sum= 0.0;
+ break;
+ case INT_RESULT:
+ case DECIMAL_RESULT:
+ {
+ int precision= args[0]->decimal_precision()*2 + prec_increment;
+ decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
+ cur_dec= 0;
+ hybrid_type= DECIMAL_RESULT;
+ my_decimal_set_zero(dec_sum);
+ my_decimal_set_zero(dec_sqr);
+
+ /*
+ The maxium value to usable for variance is DECIMAL_MAX_LENGTH/2
+ becasue we need to be able to calculate in dec_bin_size1
+ column_value * column_value
+ */
+ f_scale0= args[0]->decimals;
+ f_precision0= min(args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS,
+ DECIMAL_MAX_PRECISION);
+ f_scale1= min(args[0]->decimals * 2, DECIMAL_MAX_SCALE);
+ f_precision1= min(args[0]->decimal_precision()*2 + DECIMAL_LONGLONG_DIGITS,
+ DECIMAL_MAX_PRECISION);
+ dec_bin_size0= my_decimal_get_binary_size(f_precision0, f_scale0);
+ dec_bin_size1= my_decimal_get_binary_size(f_precision1, f_scale1);
+ break;
+ }
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ DBUG_PRINT("info", ("Type: %s (%d, %d)",
+ (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
+ hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ hybrid_type == INT_RESULT ? "INT_RESULT" :
+ "--ILLEGAL!!!--"),
+ max_length,
+ (int)decimals));
+ DBUG_VOID_RETURN;
+}
+
+
Item *Item_sum_variance::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_sum_variance(thd, this);
}
+Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table,
+ uint convert_blob_len)
+{
+ if (group)
+ {
+ /*
+ We must store both value and counter in the temporary table in one field.
+ The easyest way is to do this is to store both value in a string
+ and unpack on access.
+ */
+ return new Field_string(((hybrid_type == DECIMAL_RESULT) ?
+ dec_bin_size0 + dec_bin_size1 :
+ sizeof(double)*2) + sizeof(longlong),
+ 0, name, table, &my_charset_bin);
+ }
+ if (hybrid_type == DECIMAL_RESULT)
+ return new Field_new_decimal(max_length, maybe_null, name, table,
+ decimals, unsigned_flag);
+ return new Field_double(max_length, maybe_null,name,table,decimals);
+}
+
+
void Item_sum_variance::clear()
{
- sum=sum_sqr=0.0;
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ my_decimal_set_zero(dec_sum);
+ my_decimal_set_zero(dec_sqr);
+ cur_dec= 0;
+ }
+ else
+ sum=sum_sqr=0.0;
count=0;
}
bool Item_sum_variance::add()
{
- double nr=args[0]->val();
- if (!args[0]->null_value)
+ if (hybrid_type == DECIMAL_RESULT)
{
- sum+=nr;
- sum_sqr+=nr*nr;
- count++;
+ my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf);
+ my_decimal sqr_buf;
+ if (!args[0]->null_value)
+ {
+ count++;
+ int next_dec= cur_dec ^ 1;
+ my_decimal_mul(E_DEC_FATAL_ERROR, &sqr_buf, dec, dec);
+ my_decimal_add(E_DEC_FATAL_ERROR, dec_sqr+next_dec,
+ dec_sqr+cur_dec, &sqr_buf);
+ my_decimal_add(E_DEC_FATAL_ERROR, dec_sum+next_dec,
+ dec_sum+cur_dec, dec);
+ cur_dec= next_dec;
+ }
+ }
+ else
+ {
+ double nr= args[0]->val_real();
+ if (!args[0]->null_value)
+ {
+ sum+=nr;
+ sum_sqr+=nr*nr;
+ count++;
+ }
}
return 0;
}
-double Item_sum_variance::val()
+double Item_sum_variance::val_real()
{
DBUG_ASSERT(fixed == 1);
- if (!count)
+ if (hybrid_type == DECIMAL_RESULT)
+ return val_real_from_decimal();
+
+ if (count <= sample)
{
null_value=1;
return 0.0;
@@ -414,38 +1094,117 @@ double Item_sum_variance::val()
null_value=0;
/* Avoid problems when the precision isn't good enough */
double tmp=ulonglong2double(count);
- double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
+ double tmp2= (sum_sqr - sum*sum/tmp)/(tmp - (double)sample);
return tmp2 <= 0.0 ? 0.0 : tmp2;
}
+
+my_decimal *Item_sum_variance::val_decimal(my_decimal *dec_buf)
+{
+ my_decimal count_buf, count1_buf, sum_sqr_buf;
+ DBUG_ASSERT(fixed ==1 );
+ if (hybrid_type == REAL_RESULT)
+ return val_decimal_from_real(dec_buf);
+
+ if (count <= sample)
+ {
+ null_value= 1;
+ return 0;
+ }
+ null_value= 0;
+ int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &count_buf);
+ int2my_decimal(E_DEC_FATAL_ERROR, count-sample, 0, &count1_buf);
+ my_decimal_mul(E_DEC_FATAL_ERROR, &sum_sqr_buf,
+ dec_sum+cur_dec, dec_sum+cur_dec);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
+ &sum_sqr_buf, &count_buf, prec_increment);
+ my_decimal_sub(E_DEC_FATAL_ERROR, &sum_sqr_buf, dec_sqr+cur_dec, dec_buf);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
+ &sum_sqr_buf, &count1_buf, prec_increment);
+ return dec_buf;
+}
+
+
void Item_sum_variance::reset_field()
{
- double nr=args[0]->val();
- char *res=result_field->ptr;
+ double nr;
+ char *res= result_field->ptr;
+
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ my_decimal value, *arg_dec, *arg2_dec;
+ longlong tmp;
+
+ arg_dec= args[0]->val_decimal(&value);
+ if (args[0]->null_value)
+ {
+ arg_dec= arg2_dec= &decimal_zero;
+ tmp= 0;
+ }
+ else
+ {
+ my_decimal_mul(E_DEC_FATAL_ERROR, dec_sum, arg_dec, arg_dec);
+ arg2_dec= dec_sum;
+ tmp= 1;
+ }
+ my_decimal2binary(E_DEC_FATAL_ERROR, arg_dec,
+ res, f_precision0, f_scale0);
+ my_decimal2binary(E_DEC_FATAL_ERROR, arg2_dec,
+ res+dec_bin_size0, f_precision1, f_scale1);
+ res+= dec_bin_size0 + dec_bin_size1;
+ int8store(res,tmp);
+ return;
+ }
+ nr= args[0]->val_real();
if (args[0]->null_value)
bzero(res,sizeof(double)*2+sizeof(longlong));
else
{
+ longlong tmp;
float8store(res,nr);
nr*=nr;
float8store(res+sizeof(double),nr);
- longlong tmp=1;
+ tmp= 1;
int8store(res+sizeof(double)*2,tmp);
}
}
+
void Item_sum_variance::update_field()
{
- double nr,old_nr,old_sqr;
longlong field_count;
char *res=result_field->ptr;
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ my_decimal value, *arg_val= args[0]->val_decimal(&value);
+ if (!args[0]->null_value)
+ {
+ binary2my_decimal(E_DEC_FATAL_ERROR, res,
+ dec_sum+1, f_precision0, f_scale0);
+ binary2my_decimal(E_DEC_FATAL_ERROR, res+dec_bin_size0,
+ dec_sqr+1, f_precision1, f_scale1);
+ field_count= sint8korr(res + (dec_bin_size0 + dec_bin_size1));
+ my_decimal_add(E_DEC_FATAL_ERROR, dec_sum, arg_val, dec_sum+1);
+ my_decimal_mul(E_DEC_FATAL_ERROR, dec_sum+1, arg_val, arg_val);
+ my_decimal_add(E_DEC_FATAL_ERROR, dec_sqr, dec_sqr+1, dec_sum+1);
+ field_count++;
+ my_decimal2binary(E_DEC_FATAL_ERROR, dec_sum,
+ res, f_precision0, f_scale0);
+ my_decimal2binary(E_DEC_FATAL_ERROR, dec_sqr,
+ res+dec_bin_size0, f_precision1, f_scale1);
+ res+= dec_bin_size0 + dec_bin_size1;
+ int8store(res, field_count);
+ }
+ return;
+ }
+ double nr,old_nr,old_sqr;
float8get(old_nr, res);
float8get(old_sqr, res+sizeof(double));
field_count=sint8korr(res+sizeof(double)*2);
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
old_nr+=nr;
@@ -454,35 +1213,52 @@ void Item_sum_variance::update_field()
}
float8store(res,old_nr);
float8store(res+sizeof(double),old_sqr);
- int8store(res+sizeof(double)*2,field_count);
+ res+= sizeof(double)*2;
+ int8store(res,field_count);
}
+
/* min & max */
void Item_sum_hybrid::clear()
{
- sum= 0.0;
- sum_int= 0;
- value.length(0);
+ switch (hybrid_type) {
+ case INT_RESULT:
+ sum_int= 0;
+ break;
+ case DECIMAL_RESULT:
+ my_decimal_set_zero(&sum_dec);
+ break;
+ case REAL_RESULT:
+ sum= 0.0;
+ break;
+ default:
+ value.length(0);
+ }
null_value= 1;
}
-double Item_sum_hybrid::val()
+double Item_sum_hybrid::val_real()
{
DBUG_ASSERT(fixed == 1);
- int err;
- char *end_not_used;
if (null_value)
return 0.0;
switch (hybrid_type) {
case STRING_RESULT:
+ {
+ char *end_not_used;
+ int err_not_used;
String *res; res=val_str(&str_value);
- return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
- &end_not_used, &err) : 0.0);
+ return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
+ &end_not_used, &err_not_used) : 0.0);
+ }
case INT_RESULT:
if (unsigned_flag)
return ulonglong2double(sum_int);
return (double) sum_int;
+ case DECIMAL_RESULT:
+ my_decimal2double(E_DEC_FATAL_ERROR, &sum_dec, &sum);
+ return sum;
case REAL_RESULT:
return sum;
case ROW_RESULT:
@@ -491,7 +1267,6 @@ double Item_sum_hybrid::val()
DBUG_ASSERT(0);
return 0;
}
- return 0; // Keep compiler happy
}
longlong Item_sum_hybrid::val_int()
@@ -499,9 +1274,46 @@ longlong Item_sum_hybrid::val_int()
DBUG_ASSERT(fixed == 1);
if (null_value)
return 0;
- if (hybrid_type == INT_RESULT)
+ switch (hybrid_type) {
+ case INT_RESULT:
return sum_int;
- return (longlong) Item_sum_hybrid::val();
+ case DECIMAL_RESULT:
+ {
+ longlong result;
+ my_decimal2int(E_DEC_FATAL_ERROR, &sum_dec, unsigned_flag, &result);
+ return sum_int;
+ }
+ default:
+ return (longlong) Item_sum_hybrid::val_real();
+ }
+}
+
+
+my_decimal *Item_sum_hybrid::val_decimal(my_decimal *val)
+{
+ DBUG_ASSERT(fixed == 1);
+ if (null_value)
+ return 0;
+ switch (hybrid_type) {
+ case STRING_RESULT:
+ string2my_decimal(E_DEC_FATAL_ERROR, &value, val);
+ break;
+ case REAL_RESULT:
+ double2my_decimal(E_DEC_FATAL_ERROR, sum, val);
+ break;
+ case DECIMAL_RESULT:
+ val= &sum_dec;
+ break;
+ case INT_RESULT:
+ int2my_decimal(E_DEC_FATAL_ERROR, sum_int, unsigned_flag, val);
+ break;
+ case ROW_RESULT:
+ default:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ break;
+ }
+ return val; // Keep compiler happy
}
@@ -517,6 +1329,9 @@ Item_sum_hybrid::val_str(String *str)
case REAL_RESULT:
str->set(sum,decimals, &my_charset_bin);
break;
+ case DECIMAL_RESULT:
+ my_decimal2string(E_DEC_FATAL_ERROR, &sum_dec, 0, 0, 0, str);
+ return str;
case INT_RESULT:
if (unsigned_flag)
str->set((ulonglong) sum_int, &my_charset_bin);
@@ -590,9 +1405,20 @@ bool Item_sum_min::add()
}
}
break;
+ case DECIMAL_RESULT:
+ {
+ my_decimal value, *val= args[0]->val_decimal(&value);
+ if (!args[0]->null_value &&
+ (null_value || (my_decimal_cmp(&sum_dec, val) > 0)))
+ {
+ my_decimal2decimal(val, &sum_dec);
+ null_value= 0;
+ }
+ }
+ break;
case REAL_RESULT:
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value && (null_value || nr < sum))
{
sum=nr;
@@ -643,9 +1469,20 @@ bool Item_sum_max::add()
}
}
break;
+ case DECIMAL_RESULT:
+ {
+ my_decimal value, *val= args[0]->val_decimal(&value);
+ if (!args[0]->null_value &&
+ (null_value || (my_decimal_cmp(val, &sum_dec) > 0)))
+ {
+ my_decimal2decimal(val, &sum_dec);
+ null_value= 0;
+ }
+ }
+ break;
case REAL_RESULT:
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value && (null_value || nr > sum))
{
sum=nr;
@@ -725,7 +1562,7 @@ bool Item_sum_and::add()
void Item_sum_num::reset_field()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
char *res=result_field->ptr;
if (maybe_null)
@@ -744,7 +1581,8 @@ void Item_sum_num::reset_field()
void Item_sum_hybrid::reset_field()
{
- if (hybrid_type == STRING_RESULT)
+ switch(hybrid_type) {
+ case STRING_RESULT:
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),result_field->charset()),*res;
@@ -760,8 +1598,9 @@ void Item_sum_hybrid::reset_field()
result_field->set_notnull();
result_field->store(res->ptr(),res->length(),tmp.charset());
}
+ break;
}
- else if (hybrid_type == INT_RESULT)
+ case INT_RESULT:
{
longlong nr=args[0]->val_int();
@@ -775,11 +1614,12 @@ void Item_sum_hybrid::reset_field()
else
result_field->set_notnull();
}
- result_field->store(nr);
+ result_field->store(nr, unsigned_flag);
+ break;
}
- else // REAL_RESULT
+ case REAL_RESULT:
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (maybe_null)
{
@@ -792,14 +1632,50 @@ void Item_sum_hybrid::reset_field()
result_field->set_notnull();
}
result_field->store(nr);
+ break;
+ }
+ case DECIMAL_RESULT:
+ {
+ my_decimal value, *arg_dec= args[0]->val_decimal(&value);
+
+ if (maybe_null)
+ {
+ if (args[0]->null_value)
+ result_field->set_null();
+ else
+ result_field->set_notnull();
+ }
+ /*
+ We must store zero in the field as we will use the field value in
+ add()
+ */
+ if (!arg_dec) // Null
+ arg_dec= &decimal_zero;
+ result_field->store_decimal(arg_dec);
+ break;
+ }
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
}
}
void Item_sum_sum::reset_field()
{
- double nr=args[0]->val(); // Nulls also return 0
- float8store(result_field->ptr,nr);
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ my_decimal value, *arg_val= args[0]->val_decimal(&value);
+ if (!arg_val) // Null
+ arg_val= &decimal_zero;
+ result_field->store_decimal(arg_val);
+ }
+ else
+ {
+ DBUG_ASSERT(hybrid_type == REAL_RESULT);
+ double nr= args[0]->val_real(); // Nulls also return 0
+ float8store(result_field->ptr, nr);
+ }
if (args[0]->null_value)
result_field->set_null();
else
@@ -826,20 +1702,39 @@ void Item_sum_count::reset_field()
void Item_sum_avg::reset_field()
{
- double nr=args[0]->val();
char *res=result_field->ptr;
-
- if (args[0]->null_value)
- bzero(res,sizeof(double)+sizeof(longlong));
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ longlong tmp;
+ my_decimal value, *arg_dec= args[0]->val_decimal(&value);
+ if (args[0]->null_value)
+ {
+ arg_dec= &decimal_zero;
+ tmp= 0;
+ }
+ else
+ tmp= 1;
+ my_decimal2binary(E_DEC_FATAL_ERROR, arg_dec, res, f_precision, f_scale);
+ res+= dec_bin_size;
+ int8store(res, tmp);
+ }
else
{
- float8store(res,nr);
- res+=sizeof(double);
- longlong tmp=1;
- int8store(res,tmp);
+ double nr= args[0]->val_real();
+
+ if (args[0]->null_value)
+ bzero(res,sizeof(double)+sizeof(longlong));
+ else
+ {
+ longlong tmp= 1;
+ float8store(res,nr);
+ res+=sizeof(double);
+ int8store(res,tmp);
+ }
}
}
+
void Item_sum_bit::reset_field()
{
reset();
@@ -854,23 +1749,46 @@ void Item_sum_bit::update_field()
int8store(res, bits);
}
+
/*
** calc next value and merge it with field_value
*/
void Item_sum_sum::update_field()
{
- double old_nr,nr;
- char *res=result_field->ptr;
-
- float8get(old_nr,res);
- nr=args[0]->val();
- if (!args[0]->null_value)
+ if (hybrid_type == DECIMAL_RESULT)
{
- old_nr+=nr;
- result_field->set_notnull();
+ my_decimal value, *arg_val= args[0]->val_decimal(&value);
+ if (!args[0]->null_value)
+ {
+ if (!result_field->is_null())
+ {
+ my_decimal field_value,
+ *field_val= result_field->val_decimal(&field_value);
+ my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, field_val);
+ result_field->store_decimal(dec_buffs);
+ }
+ else
+ {
+ result_field->store_decimal(arg_val);
+ result_field->set_notnull();
+ }
+ }
+ }
+ else
+ {
+ double old_nr,nr;
+ char *res=result_field->ptr;
+
+ float8get(old_nr,res);
+ nr= args[0]->val_real();
+ if (!args[0]->null_value)
+ {
+ old_nr+=nr;
+ result_field->set_notnull();
+ }
+ float8store(res,old_nr);
}
- float8store(res,old_nr);
}
@@ -894,32 +1812,59 @@ void Item_sum_count::update_field()
void Item_sum_avg::update_field()
{
- double nr,old_nr;
longlong field_count;
char *res=result_field->ptr;
-
- float8get(old_nr,res);
- field_count=sint8korr(res+sizeof(double));
-
- nr=args[0]->val();
- if (!args[0]->null_value)
+ if (hybrid_type == DECIMAL_RESULT)
{
- old_nr+=nr;
- field_count++;
+ my_decimal value, *arg_val= args[0]->val_decimal(&value);
+ if (!args[0]->null_value)
+ {
+ binary2my_decimal(E_DEC_FATAL_ERROR, res,
+ dec_buffs + 1, f_precision, f_scale);
+ field_count= sint8korr(res + dec_bin_size);
+ my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, dec_buffs + 1);
+ my_decimal2binary(E_DEC_FATAL_ERROR, dec_buffs,
+ res, f_precision, f_scale);
+ res+= dec_bin_size;
+ field_count++;
+ int8store(res, field_count);
+ }
+ }
+ else
+ {
+ double nr;
+
+ nr= args[0]->val_real();
+ if (!args[0]->null_value)
+ {
+ double old_nr;
+ float8get(old_nr, res);
+ field_count= sint8korr(res + sizeof(double));
+ old_nr+= nr;
+ float8store(res,old_nr);
+ res+= sizeof(double);
+ field_count++;
+ int8store(res, field_count);
+ }
}
- float8store(res,old_nr);
- res+=sizeof(double);
- int8store(res,field_count);
}
+
void Item_sum_hybrid::update_field()
{
- if (hybrid_type == STRING_RESULT)
+ switch (hybrid_type) {
+ case STRING_RESULT:
min_max_update_str_field();
- else if (hybrid_type == INT_RESULT)
+ break;
+ case INT_RESULT:
min_max_update_int_field();
- else
+ break;
+ case DECIMAL_RESULT:
+ min_max_update_decimal_field();
+ break;
+ default:
min_max_update_real_field();
+ }
}
@@ -947,7 +1892,7 @@ Item_sum_hybrid::min_max_update_real_field()
double nr,old_nr;
old_nr=result_field->val_real();
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
if (result_field->is_null(0) ||
@@ -985,118 +1930,247 @@ Item_sum_hybrid::min_max_update_int_field()
}
else if (result_field->is_null(0))
result_field->set_null();
- result_field->store(old_nr);
+ result_field->store(old_nr, unsigned_flag);
}
-Item_avg_field::Item_avg_field(Item_sum_avg *item)
+void
+Item_sum_hybrid::min_max_update_decimal_field()
+{
+ /* TODO: optimize: do not get result_field in case of args[0] is NULL */
+ my_decimal old_val, nr_val;
+ const my_decimal *old_nr= result_field->val_decimal(&old_val);
+ const my_decimal *nr= args[0]->val_decimal(&nr_val);
+ if (!args[0]->null_value)
+ {
+ if (result_field->is_null(0))
+ old_nr=nr;
+ else
+ {
+ bool res= my_decimal_cmp(old_nr, nr) > 0;
+ /* (cmp_sign > 0 && res) || (!(cmp_sign > 0) && !res) */
+ if ((cmp_sign > 0) ^ (!res))
+ old_nr=nr;
+ }
+ result_field->set_notnull();
+ }
+ else if (result_field->is_null(0))
+ result_field->set_null();
+ result_field->store_decimal(old_nr);
+}
+
+
+Item_avg_field::Item_avg_field(Item_result res_type, Item_sum_avg *item)
{
name=item->name;
decimals=item->decimals;
- max_length=item->max_length;
+ max_length= item->max_length;
+ unsigned_flag= item->unsigned_flag;
field=item->result_field;
maybe_null=1;
+ hybrid_type= res_type;
+ prec_increment= item->prec_increment;
+ if (hybrid_type == DECIMAL_RESULT)
+ {
+ f_scale= item->f_scale;
+ f_precision= item->f_precision;
+ dec_bin_size= item->dec_bin_size;
+ }
}
-
-double Item_avg_field::val()
+double Item_avg_field::val_real()
{
// fix_fields() never calls for this Item
double nr;
longlong count;
+ char *res;
+
+ if (hybrid_type == DECIMAL_RESULT)
+ return val_real_from_decimal();
+
float8get(nr,field->ptr);
- char *res=(field->ptr+sizeof(double));
- count=sint8korr(res);
+ res= (field->ptr+sizeof(double));
+ count= sint8korr(res);
- if (!count)
- {
- null_value=1;
+ if ((null_value= !count))
return 0.0;
- }
- null_value=0;
return nr/(double) count;
}
-String *Item_avg_field::val_str(String *str)
+
+longlong Item_avg_field::val_int()
+{
+ return (longlong) val_real();
+}
+
+
+my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf)
{
// fix_fields() never calls for this Item
- double nr=Item_avg_field::val();
- if (null_value)
+ if (hybrid_type == REAL_RESULT)
+ return val_decimal_from_real(dec_buf);
+
+ longlong count= sint8korr(field->ptr + dec_bin_size);
+ if ((null_value= !count))
return 0;
- str->set(nr,decimals, &my_charset_bin);
- return str;
+
+ my_decimal dec_count, dec_field;
+ binary2my_decimal(E_DEC_FATAL_ERROR,
+ field->ptr, &dec_field, f_precision, f_scale);
+ int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &dec_count);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
+ &dec_field, &dec_count, prec_increment);
+ return dec_buf;
}
+
+String *Item_avg_field::val_str(String *str)
+{
+ // fix_fields() never calls for this Item
+ if (hybrid_type == DECIMAL_RESULT)
+ return val_string_from_decimal(str);
+ return val_string_from_real(str);
+}
+
+
Item_std_field::Item_std_field(Item_sum_std *item)
: Item_variance_field(item)
{
}
-double Item_std_field::val()
+
+double Item_std_field::val_real()
{
+ double nr;
// fix_fields() never calls for this Item
- double tmp= Item_variance_field::val();
- return tmp <= 0.0 ? 0.0 : sqrt(tmp);
+ if (hybrid_type == REAL_RESULT)
+ {
+ /*
+ We can't call Item_variance_field::val_real() on a DECIMAL_RESULT
+ as this would call Item_std_field::val_decimal() and we would
+ calculate sqrt() twice
+ */
+ nr= Item_variance_field::val_real();
+ }
+ else
+ {
+ my_decimal dec_buf,*dec;
+ dec= Item_variance_field::val_decimal(&dec_buf);
+ if (!dec)
+ nr= 0.0; // NULL; Return 0.0
+ else
+ my_decimal2double(E_DEC_FATAL_ERROR, dec, &nr);
+ }
+ return nr <= 0.0 ? 0.0 : sqrt(nr);
+}
+
+
+my_decimal *Item_std_field::val_decimal(my_decimal *dec_buf)
+{
+ /*
+ We can't call val_decimal_from_real() for DECIMAL_RESULT as
+ Item_variance_field::val_real() would cause an infinite loop
+ */
+ my_decimal tmp_dec, *dec;
+ double nr;
+ if (hybrid_type == REAL_RESULT)
+ return val_decimal_from_real(dec_buf);
+ dec= Item_variance_field::val_decimal(dec_buf);
+ if (!dec)
+ return 0;
+ my_decimal2double(E_DEC_FATAL_ERROR, dec, &nr);
+ nr= nr <= 0.0 ? 0.0 : sqrt(nr);
+ double2my_decimal(E_DEC_FATAL_ERROR, nr, &tmp_dec);
+ my_decimal_round(E_DEC_FATAL_ERROR, &tmp_dec, decimals, FALSE, dec_buf);
+ return dec_buf;
}
+
Item_variance_field::Item_variance_field(Item_sum_variance *item)
{
name=item->name;
decimals=item->decimals;
max_length=item->max_length;
+ unsigned_flag= item->unsigned_flag;
field=item->result_field;
maybe_null=1;
+ sample= item->sample;
+ prec_increment= item->prec_increment;
+ if ((hybrid_type= item->hybrid_type) == DECIMAL_RESULT)
+ {
+ f_scale0= item->f_scale0;
+ f_precision0= item->f_precision0;
+ dec_bin_size0= item->dec_bin_size0;
+ f_scale1= item->f_scale1;
+ f_precision1= item->f_precision1;
+ dec_bin_size1= item->dec_bin_size1;
+ }
}
-double Item_variance_field::val()
+
+double Item_variance_field::val_real()
{
// fix_fields() never calls for this Item
+ if (hybrid_type == DECIMAL_RESULT)
+ return val_real_from_decimal();
+
double sum,sum_sqr;
longlong count;
float8get(sum,field->ptr);
float8get(sum_sqr,(field->ptr+sizeof(double)));
count=sint8korr(field->ptr+sizeof(double)*2);
- if (!count)
- {
- null_value=1;
+ if ((null_value= (count <= sample)))
return 0.0;
- }
- null_value=0;
+
double tmp= (double) count;
- double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
+ double tmp2= (sum_sqr - sum*sum/tmp)/(tmp - (double)sample);
return tmp2 <= 0.0 ? 0.0 : tmp2;
}
+
String *Item_variance_field::val_str(String *str)
{
+ if (hybrid_type == DECIMAL_RESULT)
+ return val_string_from_decimal(str);
+ return val_string_from_real(str);
+}
+
+
+my_decimal *Item_variance_field::val_decimal(my_decimal *dec_buf)
+{
// fix_fields() never calls for this Item
- double nr=val();
- if (null_value)
+ if (hybrid_type == REAL_RESULT)
+ return val_decimal_from_real(dec_buf);
+
+ longlong count= sint8korr(field->ptr+dec_bin_size0+dec_bin_size1);
+ if ((null_value= (count <= sample)))
return 0;
- str->set(nr,decimals, &my_charset_bin);
- return str;
+
+ my_decimal dec_count, dec1_count, dec_sum, dec_sqr, tmp;
+ int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &dec_count);
+ int2my_decimal(E_DEC_FATAL_ERROR, count-sample, 0, &dec1_count);
+ binary2my_decimal(E_DEC_FATAL_ERROR, field->ptr,
+ &dec_sum, f_precision0, f_scale0);
+ binary2my_decimal(E_DEC_FATAL_ERROR, field->ptr+dec_bin_size0,
+ &dec_sqr, f_precision1, f_scale1);
+ my_decimal_mul(E_DEC_FATAL_ERROR, &tmp, &dec_sum, &dec_sum);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &tmp, &dec_count, prec_increment);
+ my_decimal_sub(E_DEC_FATAL_ERROR, &dec_sum, &dec_sqr, dec_buf);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
+ &dec_sum, &dec1_count, prec_increment);
+ return dec_buf;
}
+
/****************************************************************************
** COUNT(DISTINCT ...)
****************************************************************************/
-#include "sql_select.h"
-
-int simple_raw_key_cmp(void* arg, byte* key1, byte* key2)
-{
- return memcmp(key1, key2, *(uint*) arg);
-}
-
int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
{
- Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
- CHARSET_INFO *cs=item->key_charset;
- uint len=item->key_length;
- return cs->coll->strnncollsp(cs,
- (const uchar*) key1, len,
- (const uchar*) key2, len);
+ Field *f= (Field*) arg;
+ return f->cmp((const char*)key1, (const char*)key2);
}
/*
@@ -1110,13 +2184,13 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2)
{
Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
Field **field = item->table->field;
- Field **field_end= field + item->table->fields;
+ Field **field_end= field + item->table->s->fields;
uint32 *lengths=item->field_lengths;
for (; field < field_end; ++field)
{
Field* f = *field;
int len = *lengths++;
- int res = f->key_cmp(key1, key2);
+ int res = f->cmp((char *) key1, (char *) key2);
if (res)
return res;
key1 += len;
@@ -1125,54 +2199,42 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2)
return 0;
}
-/*
- helper function for walking the tree when we dump it to MyISAM -
- tree_walk will call it for each leaf
-*/
-int dump_leaf(byte* key, uint32 count __attribute__((unused)),
- Item_sum_count_distinct* item)
+C_MODE_START
+
+static int count_distinct_walk(void *elem, element_count count, void *arg)
{
- byte* buf = item->table->record[0];
- int error;
- /*
- The first item->rec_offset bytes are taken care of with
- restore_record(table,default_values) in setup()
- */
- memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
- if ((error = item->table->file->write_row(buf)))
- {
- if (error != HA_ERR_FOUND_DUPP_KEY &&
- error != HA_ERR_FOUND_DUPP_UNIQUE)
- return 1;
- }
+ (*((ulonglong*)arg))++;
return 0;
}
+C_MODE_END
+
void Item_sum_count_distinct::cleanup()
{
DBUG_ENTER("Item_sum_count_distinct::cleanup");
Item_sum_int::cleanup();
- /*
- Free table and tree if they belong to this item (if item have not pointer
- to original item from which was made copy => it own its objects )
- */
+
+ /* Free objects only if we own them. */
if (!original)
{
+ /*
+ We need to delete the table and the tree in cleanup() as
+ they were allocated in the runtime memroot. Using the runtime
+ memroot reduces memory footprint for PS/SP and simplifies setup().
+ */
+ delete tree;
+ tree= 0;
if (table)
{
- free_tmp_table(current_thd, table);
+ free_tmp_table(table->in_use, table);
table= 0;
}
delete tmp_table_param;
tmp_table_param= 0;
- if (use_tree)
- {
- delete_tree(tree);
- use_tree= 0;
- }
}
+ always_null= FALSE;
DBUG_VOID_RETURN;
}
@@ -1183,8 +2245,15 @@ void Item_sum_count_distinct::make_unique()
{
table=0;
original= 0;
- use_tree= 0; // to prevent delete_tree call on uninitialized tree
- tree= &tree_base;
+ tree= 0;
+ tmp_table_param= 0;
+ always_null= FALSE;
+}
+
+
+Item_sum_count_distinct::~Item_sum_count_distinct()
+{
+ cleanup();
}
@@ -1192,18 +2261,23 @@ bool Item_sum_count_distinct::setup(THD *thd)
{
List<Item> list;
SELECT_LEX *select_lex= thd->lex->current_select;
- if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
- return 1;
-
+
+ /*
+ Setup can be called twice for ROLLUP items. This is a bug.
+ Please add DBUG_ASSERT(tree == 0) here when it's fixed.
+ */
+ if (tree || table || tmp_table_param)
+ return FALSE;
+
if (!(tmp_table_param= new TMP_TABLE_PARAM))
- return 1;
+ return TRUE;
/* Create a table with an unique key over all parameters */
for (uint i=0; i < arg_count ; i++)
{
Item *item=args[i];
if (list.push_back(item))
- return 1; // End of memory
+ return TRUE; // End of memory
if (item->const_item())
{
(void) item->val_int();
@@ -1212,139 +2286,88 @@ bool Item_sum_count_distinct::setup(THD *thd)
}
}
if (always_null)
- return 0;
+ return FALSE;
count_field_types(tmp_table_param,list,0);
- if (table)
- {
- free_tmp_table(thd, table);
- tmp_table_param->cleanup();
- }
+ DBUG_ASSERT(table == 0);
if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
0,
- select_lex->options | thd->options,
+ (select_lex->options | thd->options),
HA_POS_ERROR, (char*)"")))
- return 1;
+ return TRUE;
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
table->no_rows=1;
-
- // no blobs, otherwise it would be MyISAM
- if (table->db_type == DB_TYPE_HEAP)
+ if (table->s->db_type == DB_TYPE_HEAP)
{
+ /*
+ No blobs, otherwise it would have been MyISAM: set up a compare
+ function and its arguments to use with Unique.
+ */
qsort_cmp2 compare_key;
void* cmp_arg;
+ Field **field= table->field;
+ Field **field_end= field + table->s->fields;
+ bool all_binary= TRUE;
- // to make things easier for dump_leaf if we ever have to dump to MyISAM
- restore_record(table,default_values);
-
- if (table->fields == 1)
+ for (tree_key_length= 0; field < field_end; ++field)
{
- /*
- If we have only one field, which is the most common use of
- count(distinct), it is much faster to use a simpler key
- compare method that can take advantage of not having to worry
- about other fields
- */
- Field* field = table->field[0];
- switch(field->type())
+ Field *f= *field;
+ enum enum_field_types type= f->type();
+ tree_key_length+= f->pack_length();
+ if (!f->binary() && (type == MYSQL_TYPE_STRING ||
+ type == MYSQL_TYPE_VAR_STRING ||
+ type == MYSQL_TYPE_VARCHAR))
{
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
- if (field->binary())
- {
- compare_key = (qsort_cmp2)simple_raw_key_cmp;
- cmp_arg = (void*) &key_length;
- }
- else
- {
- /*
- If we have a string, we must take care of charsets and case
- sensitivity
- */
- compare_key = (qsort_cmp2)simple_str_key_cmp;
- cmp_arg = (void*) this;
- }
- break;
- default:
- /*
- Since at this point we cannot have blobs anything else can
- be compared with memcmp
- */
- compare_key = (qsort_cmp2)simple_raw_key_cmp;
- cmp_arg = (void*) &key_length;
- break;
+ all_binary= FALSE;
+ break;
}
- key_charset = field->charset();
- key_length = field->pack_length();
- rec_offset = 1;
}
- else // too bad, cannot cheat - there is more than one field
+ if (all_binary)
{
- bool all_binary = 1;
- Field** field, **field_end;
- field_end = (field = table->field) + table->fields;
- uint32 *lengths;
- if (!(field_lengths=
- (uint32*) thd->alloc(sizeof(uint32) * table->fields)))
- return 1;
-
- for (key_length = 0, lengths=field_lengths; field < field_end; ++field)
- {
- uint32 length= (*field)->pack_length();
- key_length += length;
- *lengths++ = length;
- if (!(*field)->binary())
- all_binary = 0; // Can't break loop here
- }
- rec_offset = table->reclength - key_length;
- if (all_binary)
+ cmp_arg= (void*) &tree_key_length;
+ compare_key= (qsort_cmp2) simple_raw_key_cmp;
+ }
+ else
+ {
+ if (table->s->fields == 1)
{
- compare_key = (qsort_cmp2)simple_raw_key_cmp;
- cmp_arg = (void*) &key_length;
+ /*
+ If we have only one field, which is the most common use of
+ count(distinct), it is much faster to use a simpler key
+ compare method that can take advantage of not having to worry
+ about other fields.
+ */
+ compare_key= (qsort_cmp2) simple_str_key_cmp;
+ cmp_arg= (void*) table->field[0];
+ /* tree_key_length has been set already */
}
else
{
- compare_key = (qsort_cmp2) composite_key_cmp ;
- cmp_arg = (void*) this;
+ uint32 *length;
+ compare_key= (qsort_cmp2) composite_key_cmp;
+ cmp_arg= (void*) this;
+ field_lengths= (uint32*) thd->alloc(table->s->fields * sizeof(uint32));
+ for (tree_key_length= 0, length= field_lengths, field= table->field;
+ field < field_end; ++field, ++length)
+ {
+ *length= (*field)->pack_length();
+ tree_key_length+= *length;
+ }
}
}
-
- if (use_tree)
- delete_tree(tree);
- init_tree(tree, min(thd->variables.max_heap_table_size,
- thd->variables.sortbuff_size/16), 0,
- key_length, compare_key, 0, NULL, cmp_arg);
- use_tree = 1;
-
+ DBUG_ASSERT(tree == 0);
+ tree= new Unique(compare_key, cmp_arg, tree_key_length,
+ thd->variables.max_heap_table_size);
/*
- The only time key_length could be 0 is if someone does
+ The only time tree_key_length could be 0 is if someone does
count(distinct) on a char(0) field - stupid thing to do,
but this has to be handled - otherwise someone can crash
the server with a DoS attack
*/
- max_elements_in_tree = ((key_length) ?
- thd->variables.max_heap_table_size/key_length : 1);
-
- }
- if (original)
- {
- original->table= table;
- original->use_tree= use_tree;
+ if (! tree)
+ return TRUE;
}
- return 0;
-}
-
-
-int Item_sum_count_distinct::tree_to_myisam()
-{
- if (create_myisam_from_heap(current_thd, table, tmp_table_param,
- HA_ERR_RECORD_FILE_FULL, 1) ||
- tree_walk(tree, (tree_walk_action)&dump_leaf, (void*)this,
- left_root_right))
- return 1;
- delete_tree(tree);
- use_tree = 0;
- return 0;
+ return FALSE;
}
@@ -1356,8 +2379,9 @@ Item *Item_sum_count_distinct::copy_or_same(THD* thd)
void Item_sum_count_distinct::clear()
{
- if (use_tree)
- reset_tree(tree);
+ /* tree and table can be both null only if always_null */
+ if (tree)
+ tree->reset();
else if (table)
{
table->file->extra(HA_EXTRA_NO_CACHE);
@@ -1378,32 +2402,21 @@ bool Item_sum_count_distinct::add()
if ((*field)->is_real_null(0))
return 0; // Don't count NULL
- if (use_tree)
+ if (tree)
{
/*
- If the tree got too big, convert to MyISAM, otherwise insert into the
- tree.
+ The first few bytes of record (at least one) are just markers
+ for deleted and NULLs. We want to skip them since they will
+ bloat the tree without providing any valuable info. Besides,
+ key_length used to initialize the tree didn't include space for them.
*/
- if (tree->elements_in_tree > max_elements_in_tree)
- {
- if (tree_to_myisam())
- return 1;
- }
- else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
- tree->custom_arg))
- return 1;
+ return tree->unique_add(table->record[0] + table->s->null_bytes);
}
- else if ((error=table->file->write_row(table->record[0])))
- {
- if (error != HA_ERR_FOUND_DUPP_KEY &&
- error != HA_ERR_FOUND_DUPP_UNIQUE)
- {
- if (create_myisam_from_heap(current_thd, table, tmp_table_param, error,
- 1))
- return 1; // Not a table_is_full error
- }
- }
- return 0;
+ if ((error= table->file->write_row(table->record[0])) &&
+ error != HA_ERR_FOUND_DUPP_KEY &&
+ error != HA_ERR_FOUND_DUPP_UNIQUE)
+ return TRUE;
+ return FALSE;
}
@@ -1412,20 +2425,21 @@ longlong Item_sum_count_distinct::val_int()
DBUG_ASSERT(fixed == 1);
if (!table) // Empty query
return LL(0);
- if (use_tree)
- return tree->elements_in_tree;
+ if (tree)
+ {
+ ulonglong count;
+
+ if (tree->elements == 0)
+ return (longlong) tree->elements_in_tree(); // everything fits in memory
+ count= 0;
+ tree->walk(count_distinct_walk, (void*) &count);
+ return (longlong) count;
+ }
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records;
}
-void Item_sum_count_distinct::print(String *str)
-{
- str->append("count(distinct ", 15);
- args[0]->print(str);
- str->append(')');
-}
-
/****************************************************************************
** Functions to handle dynamic loadable aggregates
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
@@ -1460,12 +2474,26 @@ void Item_udf_sum::cleanup()
}
+void Item_udf_sum::print(String *str)
+{
+ str->append(func_name());
+ str->append('(');
+ for (uint i=0 ; i < arg_count ; i++)
+ {
+ if (i)
+ str->append(',');
+ args[i]->print(str);
+ }
+ str->append(')');
+}
+
+
Item *Item_sum_udf_float::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_sum_udf_float(thd, this);
}
-double Item_sum_udf_float::val()
+double Item_sum_udf_float::val_real()
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_sum_udf_float::val");
@@ -1474,14 +2502,51 @@ double Item_sum_udf_float::val()
DBUG_RETURN(udf.val(&null_value));
}
+
String *Item_sum_udf_float::val_str(String *str)
{
+ return val_string_from_real(str);
+}
+
+
+my_decimal *Item_sum_udf_float::val_decimal(my_decimal *dec)
+{
+ return val_decimal_from_real(dec);
+}
+
+
+String *Item_sum_udf_decimal::val_str(String *str)
+{
+ return val_string_from_decimal(str);
+}
+
+
+double Item_sum_udf_decimal::val_real()
+{
+ return val_real_from_decimal();
+}
+
+
+longlong Item_sum_udf_decimal::val_int()
+{
+ return val_int_from_decimal();
+}
+
+
+my_decimal *Item_sum_udf_decimal::val_decimal(my_decimal *dec_buf)
+{
DBUG_ASSERT(fixed == 1);
- double nr=val();
- if (null_value)
- return 0; /* purecov: inspected */
- str->set(nr,decimals, &my_charset_bin);
- return str;
+ DBUG_ENTER("Item_func_udf_decimal::val_decimal");
+ DBUG_PRINT("info",("result_type: %d arg_count: %d",
+ args[0]->result_type(), arg_count));
+
+ DBUG_RETURN(udf.val_decimal(&null_value, dec_buf));
+}
+
+
+Item *Item_sum_udf_decimal::copy_or_same(THD* thd)
+{
+ return new (thd->mem_root) Item_sum_udf_decimal(thd, this);
}
@@ -1490,7 +2555,6 @@ Item *Item_sum_udf_int::copy_or_same(THD* thd)
return new (thd->mem_root) Item_sum_udf_int(thd, this);
}
-
longlong Item_sum_udf_int::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -1503,14 +2567,15 @@ longlong Item_sum_udf_int::val_int()
String *Item_sum_udf_int::val_str(String *str)
{
- DBUG_ASSERT(fixed == 1);
- longlong nr=val_int();
- if (null_value)
- return 0;
- str->set(nr, &my_charset_bin);
- return str;
+ return val_string_from_int(str);
}
+my_decimal *Item_sum_udf_int::val_decimal(my_decimal *dec)
+{
+ return val_decimal_from_int(dec);
+}
+
+
/* Default max_length is max argument length */
void Item_sum_udf_str::fix_length_and_dec()
@@ -1529,6 +2594,11 @@ Item *Item_sum_udf_str::copy_or_same(THD* thd)
}
+my_decimal *Item_sum_udf_str::val_decimal(my_decimal *dec)
+{
+ return val_decimal_from_string(dec);
+}
+
String *Item_sum_udf_str::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -1545,7 +2615,7 @@ String *Item_sum_udf_str::val_str(String *str)
GROUP_CONCAT function
SQL SYNTAX:
- GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
+ GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
[SEPARATOR str_const])
concat of values from "group by" operation
@@ -1565,6 +2635,7 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
byte* key2)
{
Item_func_group_concat* grp_item= (Item_func_group_concat*)arg;
+ TABLE *table= grp_item->table;
Item **field_item, **end;
for (field_item= grp_item->args, end= field_item + grp_item->arg_count_field;
@@ -1584,8 +2655,8 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
if (field && !(*field_item)->const_item())
{
int res;
- uint offset= field->offset();
- if ((res= field->key_cmp(key1 + offset, key2 + offset)))
+ uint offset= field->offset() - table->s->null_bytes;
+ if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset)))
return res;
}
}
@@ -1602,6 +2673,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
{
Item_func_group_concat* grp_item= (Item_func_group_concat*) arg;
ORDER **order_item, **end;
+ TABLE *table= grp_item->table;
for (order_item= grp_item->order, end=order_item+ grp_item->arg_count_order;
order_item < end;
@@ -1621,15 +2693,15 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
if (field && !item->const_item())
{
int res;
- uint offset= field->offset();
- if ((res= field->key_cmp(key1 + offset, key2 + offset)))
+ uint offset= field->offset() - table->s->null_bytes;
+ if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset)))
return (*order_item)->asc ? res : -res;
}
}
/*
We can't return 0 because in that case the tree class would remove this
item as double value. This would cause problems for case-changes and
- if the the returned values are not the same we do the sort on.
+ if the returned values are not the same we do the sort on.
*/
return 1;
}
@@ -1658,51 +2730,51 @@ int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
Append data from current leaf to item->result
*/
-int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
+int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
Item_func_group_concat *item)
{
- char buff[MAX_FIELD_WIDTH];
- String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2;
+ TABLE *table= item->table;
+ String tmp((char *)table->record[1], table->s->reclength,
+ default_charset_info);
+ String tmp2;
+ String *result= &item->result;
+ Item **arg= item->args, **arg_end= item->args + item->arg_count_field;
if (item->no_appended)
item->no_appended= FALSE;
else
- item->result.append(*item->separator);
+ result->append(*item->separator);
tmp.length(0);
-
- for (uint i= 0; i < item->arg_count_field; i++)
+
+ for (; arg < arg_end; arg++)
{
- Item *show_item= item->args[i];
- if (!show_item->const_item())
+ String *res;
+ if (! (*arg)->const_item())
{
/*
We have to use get_tmp_table_field() instead of
real_item()->get_tmp_table_field() because we want the field in
the temporary table, not the original field
+ We also can't use table->field array to access the fields
+ because it contains both order and arg list fields.
*/
- Field *field= show_item->get_tmp_table_field();
- String *res;
- char *save_ptr= field->ptr;
- DBUG_ASSERT(field->offset() < item->table->reclength);
- field->ptr= (char *) key + field->offset();
- res= field->val_str(&tmp,&tmp2);
- item->result.append(*res);
- field->ptr= save_ptr;
- }
- else
- {
- String *res= show_item->val_str(&tmp);
- if (res)
- item->result.append(*res);
+ Field *field= (*arg)->get_tmp_table_field();
+ uint offset= field->offset() - table->s->null_bytes;
+ DBUG_ASSERT(offset < table->s->reclength);
+ res= field->val_str(&tmp, (char *) key + offset);
}
+ else
+ res= (*arg)->val_str(&tmp);
+ if (res)
+ result->append(*res);
}
- /* stop if length of result more than group_concat_max_len */
- if (item->result.length() > item->group_concat_max_len)
+ /* stop if length of result more than max_length */
+ if (result->length() > item->max_length)
{
item->count_cut_values++;
- item->result.length(item->group_concat_max_len);
+ result->length(item->max_length);
item->warning_for_row= TRUE;
return 1;
}
@@ -1712,36 +2784,32 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
/*
Constructor of Item_func_group_concat
- is_distinct - distinct
- is_select - list of expression for show values
- is_order - list of sort columns
- is_separator - string value of separator
+ distinct_arg - distinct
+ select_list - list of expression for show values
+ order_list - list of sort columns
+ separator_arg - string value of separator
*/
-Item_func_group_concat::Item_func_group_concat(bool is_distinct,
- List<Item> *is_select,
- SQL_LIST *is_order,
- String *is_separator)
- :Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0),
- key_length(0), tree_mode(0), distinct(is_distinct), warning_for_row(0),
- separator(is_separator), tree(&tree_base), table(0),
- order(0), tables_list(0),
- arg_count_order(0), arg_count_field(0),
- count_cut_values(0)
+Item_func_group_concat::
+Item_func_group_concat(Name_resolution_context *context_arg,
+ bool distinct_arg, List<Item> *select_list,
+ SQL_LIST *order_list, String *separator_arg)
+ :tmp_table_param(0), warning(0),
+ separator(separator_arg), tree(0), table(0),
+ order(0), context(context_arg),
+ arg_count_order(order_list ? order_list->elements : 0),
+ arg_count_field(select_list->elements),
+ count_cut_values(0),
+ distinct(distinct_arg),
+ warning_for_row(FALSE),
+ original(0)
{
Item *item_select;
Item **arg_ptr;
- original= 0;
- quick_group= 0;
- mark_as_sum_func();
- order= 0;
- group_concat_max_len= current_thd->variables.group_concat_max_len;
-
- arg_count_field= is_select->elements;
- arg_count_order= is_order ? is_order->elements : 0;
+ quick_group= FALSE;
arg_count= arg_count_field + arg_count_order;
-
+
/*
We need to allocate:
args - arg_count_field+arg_count_order
@@ -1749,23 +2817,23 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
order - arg_count_order
*/
if (!(args= (Item**) sql_alloc(sizeof(Item*) * arg_count +
- sizeof(ORDER*)*arg_count_order)))
+ sizeof(ORDER*)*arg_count_order)))
return;
order= (ORDER**)(args + arg_count);
/* fill args items of show and sort */
- List_iterator_fast<Item> li(*is_select);
+ List_iterator_fast<Item> li(*select_list);
for (arg_ptr=args ; (item_select= li++) ; arg_ptr++)
*arg_ptr= item_select;
- if (arg_count_order)
+ if (arg_count_order)
{
ORDER **order_ptr= order;
- for (ORDER *order_item= (ORDER*) is_order->first;
- order_item != NULL;
- order_item= order_item->next)
+ for (ORDER *order_item= (ORDER*) order_list->first;
+ order_item != NULL;
+ order_item= order_item->next)
{
(*order_ptr++)= order_item;
*arg_ptr= *order_item->item;
@@ -1773,28 +2841,24 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
}
}
}
-
+
Item_func_group_concat::Item_func_group_concat(THD *thd,
- Item_func_group_concat *item)
- :Item_sum(thd, item),item_thd(thd),
+ Item_func_group_concat *item)
+ :Item_sum(thd, item),
tmp_table_param(item->tmp_table_param),
- max_elements_in_tree(item->max_elements_in_tree),
warning(item->warning),
- key_length(item->key_length),
- tree_mode(item->tree_mode),
- distinct(item->distinct),
- warning_for_row(item->warning_for_row),
separator(item->separator),
tree(item->tree),
table(item->table),
order(item->order),
- tables_list(item->tables_list),
- group_concat_max_len(item->group_concat_max_len),
+ context(item->context),
arg_count_order(item->arg_count_order),
arg_count_field(item->arg_count_field),
- field_list_offset(item->field_list_offset),
count_cut_values(item->count_cut_values),
+ distinct(item->distinct),
+ warning_for_row(item->warning_for_row),
+ always_null(item->always_null),
original(item)
{
quick_group= item->quick_group;
@@ -1824,28 +2888,33 @@ void Item_func_group_concat::cleanup()
*/
if (!original)
{
+ delete tmp_table_param;
+ tmp_table_param= 0;
if (table)
{
+ THD *thd= table->in_use;
free_tmp_table(thd, table);
table= 0;
+ if (tree)
+ {
+ delete_tree(tree);
+ tree= 0;
+ }
+ if (warning)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
+ warning->set_msg(thd, warn_buff);
+ warning= 0;
+ }
}
- delete tmp_table_param;
- tmp_table_param= 0;
- if (tree_mode)
- {
- tree_mode= 0;
- delete_tree(tree);
- }
+ DBUG_ASSERT(tree == 0);
+ DBUG_ASSERT(warning == 0);
}
DBUG_VOID_RETURN;
}
-Item_func_group_concat::~Item_func_group_concat()
-{
-}
-
-
Item *Item_func_group_concat::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_func_group_concat(thd, this);
@@ -1859,8 +2928,9 @@ void Item_func_group_concat::clear()
null_value= TRUE;
warning_for_row= FALSE;
no_appended= TRUE;
- if (tree_mode)
+ if (tree)
reset_tree(tree);
+ /* No need to reset the table as we never call write_row */
}
@@ -1871,66 +2941,63 @@ bool Item_func_group_concat::add()
copy_fields(tmp_table_param);
copy_funcs(tmp_table_param->items_to_copy);
- for (Item **arg= args, **arg_end= args + arg_count_field;
- arg < arg_end; arg++)
+ for (uint i= 0; i < arg_count_field; i++)
{
- if (!(*arg)->const_item() &&
- (*arg)->get_tmp_table_field()->is_null_in_record(
- (const uchar*) table->record[0]))
- return 0; // Skip row if it contains null
+ Item *show_item= args[i];
+ if (!show_item->const_item())
+ {
+ Field *f= show_item->get_tmp_table_field();
+ if (f->is_null_in_record((const uchar*) table->record[0]))
+ return 0; // Skip row if it contains null
+ }
}
null_value= FALSE;
TREE_ELEMENT *el= 0; // Only for safety
- if (tree_mode)
- el= tree_insert(tree, table->record[0], 0, tree->custom_arg);
+ if (tree)
+ el= tree_insert(tree, table->record[0] + table->s->null_bytes, 0,
+ tree->custom_arg);
/*
If the row is not a duplicate (el->count == 1)
we can dump the row here in case of GROUP_CONCAT(DISTINCT...)
instead of doing tree traverse later.
*/
- if (result.length() <= group_concat_max_len &&
+ if (result.length() <= max_length &&
!warning_for_row &&
- (!tree_mode || (el->count == 1 && distinct && !arg_count_order)))
- dump_leaf_key(table->record[0], 1, this);
+ (!tree || (el->count == 1 && distinct && !arg_count_order)))
+ dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this);
return 0;
}
-void Item_func_group_concat::reset_field()
-{
- DBUG_ASSERT(0);
-}
-
-
bool
-Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+Item_func_group_concat::fix_fields(THD *thd, Item **ref)
{
- uint i; /* for loop variable */
+ uint i; /* for loop variable */
DBUG_ASSERT(fixed == 0);
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
-
+
thd->allow_sum_func= 0;
maybe_null= 1;
- item_thd= thd;
/*
Fix fields for select list and ORDER clause
*/
- for (i=0 ; i < arg_count ; i++)
+ for (i=0 ; i < arg_count ; i++)
{
- if ((!args[i]->fixed &&
- args[i]->fix_fields(thd, tables, args + i)) ||
+ if ((!args[i]->fixed &&
+ args[i]->fix_fields(thd, args + i)) ||
args[i]->check_cols(1))
- return 1;
+ return TRUE;
}
if (agg_item_charsets(collation, func_name(),
@@ -1940,11 +3007,10 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
result.set_charset(collation.collation);
result_field= 0;
null_value= 1;
- max_length= group_concat_max_len;
- thd->allow_sum_func= 1;
- tables_list= tables;
+ thd->allow_sum_func= 1;
+ max_length= thd->variables.group_concat_max_len;
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -1952,89 +3018,80 @@ bool Item_func_group_concat::setup(THD *thd)
{
List<Item> list;
SELECT_LEX *select_lex= thd->lex->current_select;
- uint const_fields;
- byte *record;
qsort_cmp2 compare_key;
DBUG_ENTER("Item_func_group_concat::setup");
- if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
- DBUG_RETURN(1);
+ /*
+ Currently setup() can be called twice. Please add
+ assertion here when this is fixed.
+ */
+ if (table || tree)
+ DBUG_RETURN(FALSE);
if (!(tmp_table_param= new TMP_TABLE_PARAM))
- return 1;
- /* We'll convert all blobs to varchar fields in the temporary table */
- tmp_table_param->convert_blob_length= group_concat_max_len;
+ DBUG_RETURN(TRUE);
- /*
- push all not constant fields to list and create temp table
- */
- const_fields= 0;
+ /* We'll convert all blobs to varchar fields in the temporary table */
+ tmp_table_param->convert_blob_length= max_length;
+ /* Push all not constant fields to the list and create a temp table */
always_null= 0;
for (uint i= 0; i < arg_count_field; i++)
{
Item *item= args[i];
if (list.push_back(item))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
if (item->const_item())
{
- const_fields++;
- (void) item->val_int();
- if (item->null_value)
- always_null= 1;
+ if (item->is_null())
+ {
+ always_null= 1;
+ DBUG_RETURN(FALSE);
+ }
}
}
- if (always_null)
- DBUG_RETURN(0);
-
+
List<Item> all_fields(list);
- if (arg_count_order)
- {
- bool hidden_group_fields;
- setup_group(thd, args, tables_list, list, all_fields, *order,
- &hidden_group_fields);
- }
-
+ /*
+ Try to find every ORDER expression in the list of GROUP_CONCAT
+ arguments. If an expression is not found, prepend it to
+ "all_fields". The resulting field list is used as input to create
+ tmp table columns.
+ */
+ if (arg_count_order &&
+ setup_order(thd, args, context->table_list, list, all_fields, *order))
+ DBUG_RETURN(TRUE);
+
count_field_types(tmp_table_param,all_fields,0);
- if (table)
- {
- /*
- We come here when we are getting the result from a temporary table,
- not the original tables used in the query
- */
- free_tmp_table(thd, table);
- tmp_table_param->cleanup();
- }
+ DBUG_ASSERT(table == 0);
/*
- We have to create a temporary table to get descriptions of fields
+ We have to create a temporary table to get descriptions of fields
(types, sizes and so on).
Note that in the table, we first have the ORDER BY fields, then the
field list.
- We need to set set_sum_field in true for storing value of blob in buffer
- of a record instead of a pointer of one.
+ We need to set set_sum_field in true for storing value of blob in buffer
+ of a record instead of a pointer of one.
*/
- if (!(table=create_tmp_table(thd, tmp_table_param, all_fields,
- (ORDER*) 0, 0, TRUE,
- select_lex->options | thd->options,
- HA_POS_ERROR,(char *) "")))
- DBUG_RETURN(1);
+ if (!(table= create_tmp_table(thd, tmp_table_param, all_fields,
+ (ORDER*) 0, 0, TRUE,
+ (select_lex->options | thd->options),
+ HA_POS_ERROR, (char*) "")))
+ DBUG_RETURN(TRUE);
table->file->extra(HA_EXTRA_NO_ROWS);
table->no_rows= 1;
- key_length= table->reclength;
- record= table->record[0];
- /* Offset to first result field in table */
- field_list_offset= table->fields - (list.elements - const_fields);
-
- if (tree_mode)
- delete_tree(tree);
-
- /* choose function of sort */
- tree_mode= distinct || arg_count_order;
- if (tree_mode)
+ if (distinct || arg_count_order)
{
+ /*
+ Need sorting: init tree and choose a function to sort.
+ Don't reserve space for NULLs: if any of gconcat arguments is NULL,
+ the row is not added to the result.
+ */
+ uint tree_key_length= table->s->reclength - table->s->null_bytes;
+
+ tree= &tree_base;
if (arg_count_order)
{
if (distinct)
@@ -2047,27 +3104,16 @@ bool Item_func_group_concat::setup(THD *thd)
compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct;
}
/*
- Create a tree of sort. Tree is used for a sort and a remove double
- values (according with syntax of the function). If function doesn't
- contain DISTINCT and ORDER BY clauses, we don't create this tree.
+ Create a tree for sorting. The tree is used to sort and to remove
+ duplicate values (according to the syntax of this function). If there
+ is no DISTINCT or ORDER BY clauses, we don't create this tree.
*/
init_tree(tree, min(thd->variables.max_heap_table_size,
- thd->variables.sortbuff_size/16), 0,
- key_length, compare_key, 0, NULL, (void*) this);
- max_elements_in_tree= (key_length ?
- thd->variables.max_heap_table_size/key_length : 1);
- };
-
- /*
- Copy table and tree_mode if they belong to this item (if item have not
- pointer to original item from which was made copy => it own its objects)
- */
- if (original)
- {
- original->table= table;
- original->tree_mode= tree_mode;
+ thd->variables.sortbuff_size/16), 0,
+ tree_key_length, compare_key, 0, NULL, (void*) this);
}
- DBUG_RETURN(0);
+
+ DBUG_RETURN(FALSE);
}
@@ -2075,10 +3121,10 @@ bool Item_func_group_concat::setup(THD *thd)
void Item_func_group_concat::make_unique()
{
+ tmp_table_param= 0;
table=0;
original= 0;
- tree_mode= 0; // to prevent delete_tree call on uninitialized tree
- tree= &tree_base;
+ tree= 0;
}
@@ -2088,20 +3134,21 @@ String* Item_func_group_concat::val_str(String* str)
if (null_value)
return 0;
if (count_cut_values && !warning)
+ {
/*
ER_CUT_VALUE_GROUP_CONCAT needs an argument, but this gets set in
Item_func_group_concat::cleanup().
*/
- warning= push_warning(item_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ DBUG_ASSERT(table);
+ warning= push_warning(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CUT_VALUE_GROUP_CONCAT,
ER(ER_CUT_VALUE_GROUP_CONCAT));
+ }
if (result.length())
return &result;
- if (tree_mode)
- {
+ if (tree)
tree_walk(tree, (tree_walk_action)&dump_leaf_key, (void*)this,
left_root_right);
- }
return &result;
}
@@ -2123,7 +3170,7 @@ void Item_func_group_concat::print(String *str)
for (uint i= 0 ; i < arg_count_order ; i++)
{
if (i)
- str->append(',');
+ str->append(',');
(*order[i]->item)->print(str);
}
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index d53d8d861ae..87cc248e5e4 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -27,9 +27,9 @@ class Item_sum :public Item_result_field
{
public:
enum Sumfunctype
- { COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
- MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
- UDF_SUM_FUNC, GROUP_CONCAT_FUNC
+ { COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC,
+ AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, UNIQUE_USERS_FUNC, STD_FUNC,
+ VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC
};
Item **args, *tmp_args[2];
@@ -66,6 +66,9 @@ public:
a temporary table. Similar to reset(), but must also store value in
result_field. Like reset() it is supposed to reset start value to
default.
+ This set of methods (reult_field(), reset_field, update_field()) of
+ Item_sum is used only if quick_group is not null. Otherwise
+ copy_or_same() is used to obtain a copy of this item.
*/
virtual void reset_field()=0;
/*
@@ -76,9 +79,24 @@ public:
virtual void update_field()=0;
virtual bool keep_field_type(void) const { return 0; }
virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
- virtual const char *func_name() const { return "?"; }
+ /*
+ This method is used for debug purposes to print the name of an
+ item to the debug log. The second use of this method is as
+ a helper function of print(), where it is applicable.
+ To suit both goals it should return a meaningful,
+ distinguishable and sintactically correct string. This method
+ should not be used for runtime type identification, use enum
+ {Sum}Functype and Item_func::functype()/Item_sum::sum_func()
+ instead.
+
+ NOTE: for Items inherited from Item_sum, func_name() return part of
+ function name till first argument (including '(') to make difference in
+ names for functions with 'distinct' clause and without 'distinct' and
+ also to make printing of items inherited from Item_sum uniform.
+ */
+ virtual const char *func_name() const= 0;
virtual Item *result_item(Field *field)
- { return new Item_field(field);}
+ { return new Item_field(field); }
table_map used_tables() const { return ~(table_map) 0; } /* Not used */
bool const_item() const { return 0; }
bool is_null() { return null_value; }
@@ -90,7 +108,8 @@ public:
virtual bool setup(THD *thd) {return 0;}
virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd);
-
+ virtual Field *create_tmp_field(bool group, TABLE *table,
+ uint convert_blob_length);
bool walk (Item_processor processor, byte *argument);
};
@@ -103,10 +122,14 @@ public:
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
Item_sum_num(List<Item> &list) :Item_sum(list) {}
Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {}
- bool fix_fields(THD *, TABLE_LIST *, Item **);
+ bool fix_fields(THD *, Item **);
longlong val_int()
- { DBUG_ASSERT(fixed == 1); return (longlong) val(); } /* Real as default */
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) val_real(); /* Real as default */
+ }
String *val_str(String*str);
+ my_decimal *val_decimal(my_decimal *);
void reset_field();
};
@@ -117,8 +140,9 @@ public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {}
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
+ my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
{ decimals=0; max_length=21; maybe_null=null_value=0; }
@@ -127,25 +151,115 @@ public:
class Item_sum_sum :public Item_sum_num
{
+protected:
+ Item_result hybrid_type;
double sum;
- void fix_length_and_dec() { maybe_null=null_value=1; }
+ my_decimal dec_buffs[2];
+ uint curr_dec_buff;
+ void fix_length_and_dec();
- public:
- Item_sum_sum(Item *item_par) :Item_sum_num(item_par),sum(0.0) {}
- Item_sum_sum(THD *thd, Item_sum_sum *item)
- :Item_sum_num(thd, item), sum(item->sum) {}
+public:
+ Item_sum_sum(Item *item_par) :Item_sum_num(item_par) {}
+ Item_sum_sum(THD *thd, Item_sum_sum *item);
enum Sumfunctype sum_func () const {return SUM_FUNC;}
void clear();
bool add();
- double val();
+ double val_real();
+ longlong val_int();
+ String *val_str(String*str);
+ my_decimal *val_decimal(my_decimal *);
+ enum Item_result result_type () const { return hybrid_type; }
void reset_field();
void update_field();
void no_rows_in_result() {}
- const char *func_name() const { return "sum"; }
+ const char *func_name() const { return "sum("; }
Item *copy_or_same(THD* thd);
};
+
+/* Common class for SUM(DISTINCT), AVG(DISTINCT) */
+
+class Unique;
+
+class Item_sum_distinct :public Item_sum_num
+{
+protected:
+ /* storage for the summation result */
+ ulonglong count;
+ Hybrid_type val;
+ /* storage for unique elements */
+ Unique *tree;
+ TABLE *table;
+ enum enum_field_types table_field_type;
+ uint tree_key_length;
+protected:
+ Item_sum_distinct(THD *thd, Item_sum_distinct *item);
+public:
+ Item_sum_distinct(Item *item_par);
+ ~Item_sum_distinct();
+
+ bool setup(THD *thd);
+ void clear();
+ void cleanup();
+ bool add();
+ double val_real();
+ my_decimal *val_decimal(my_decimal *);
+ longlong val_int();
+ String *val_str(String *str);
+
+ /* XXX: does it need make_unique? */
+
+ enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
+ void reset_field() {} // not used
+ void update_field() {} // not used
+ virtual void no_rows_in_result() {}
+ void fix_length_and_dec();
+ enum Item_result result_type () const { return val.traits->type(); }
+ virtual void calculate_val_and_count();
+ virtual bool unique_walk_function(void *elem);
+};
+
+
+/*
+ Item_sum_sum_distinct - implementation of SUM(DISTINCT expr).
+ See also: MySQL manual, chapter 'Adding New Functions To MySQL'
+ and comments in item_sum.cc.
+*/
+
+class Item_sum_sum_distinct :public Item_sum_distinct
+{
+private:
+ Item_sum_sum_distinct(THD *thd, Item_sum_sum_distinct *item)
+ :Item_sum_distinct(thd, item) {}
+public:
+ Item_sum_sum_distinct(Item *item_arg) :Item_sum_distinct(item_arg) {}
+
+ enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
+ const char *func_name() const { return "sum(distinct "; }
+ Item *copy_or_same(THD* thd) { return new Item_sum_sum_distinct(thd, this); }
+};
+
+
+/* Item_sum_avg_distinct - SELECT AVG(DISTINCT expr) FROM ... */
+
+class Item_sum_avg_distinct: public Item_sum_distinct
+{
+private:
+ Item_sum_avg_distinct(THD *thd, Item_sum_avg_distinct *original)
+ :Item_sum_distinct(thd, original) {}
+public:
+ uint prec_increment;
+ Item_sum_avg_distinct(Item *item_arg) : Item_sum_distinct(item_arg) {}
+
+ void fix_length_and_dec();
+ virtual void calculate_val_and_count();
+ enum Sumfunctype sum_func () const { return AVG_DISTINCT_FUNC; }
+ const char *func_name() const { return "avg(distinct "; }
+ Item *copy_or_same(THD* thd) { return new Item_sum_avg_distinct(thd, this); }
+};
+
+
class Item_sum_count :public Item_sum_int
{
longlong count;
@@ -170,7 +284,7 @@ class Item_sum_count :public Item_sum_int
void reset_field();
void cleanup();
void update_field();
- const char *func_name() const { return "count"; }
+ const char *func_name() const { return "count("; }
Item *copy_or_same(THD* thd);
};
@@ -180,80 +294,55 @@ class TMP_TABLE_PARAM;
class Item_sum_count_distinct :public Item_sum_int
{
TABLE *table;
- table_map used_table_cache;
uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param;
- TREE tree_base;
- TREE *tree;
+ /*
+ If there are no blobs, we can use a tree, which
+ is faster than heap table. In that case, we still use the table
+ to help get things set up, but we insert nothing in it
+ */
+ Unique *tree;
/*
Following is 0 normal object and pointer to original one for copy
(to correctly free resources)
*/
Item_sum_count_distinct *original;
+ uint tree_key_length;
- uint key_length;
- CHARSET_INFO *key_charset;
-
- /*
- Calculated based on max_heap_table_size. If reached,
- walk the tree and dump it into MyISAM table
- */
- uint max_elements_in_tree;
-
- /*
- The first few bytes of record ( at least one)
- are just markers for deleted and NULLs. We want to skip them since
- they will just bloat the tree without providing any valuable info
- */
- int rec_offset;
- /*
- If there are no blobs, we can use a tree, which
- is faster than heap table. In that case, we still use the table
- to help get things set up, but we insert nothing in it
- */
- bool use_tree;
bool always_null; // Set to 1 if the result is always NULL
- int tree_to_myisam();
friend int composite_key_cmp(void* arg, byte* key1, byte* key2);
friend int simple_str_key_cmp(void* arg, byte* key1, byte* key2);
- friend int simple_raw_key_cmp(void* arg, byte* key1, byte* key2);
- friend int dump_leaf(byte* key, uint32 count __attribute__((unused)),
- Item_sum_count_distinct* item);
- public:
+public:
Item_sum_count_distinct(List<Item> &list)
- :Item_sum_int(list), table(0), used_table_cache(~(table_map) 0),
- tmp_table_param(0), tree(&tree_base), original(0), use_tree(0),
- always_null(0)
+ :Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0),
+ tree(0), original(0), always_null(FALSE)
{ quick_group= 0; }
Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item)
:Item_sum_int(thd, item), table(item->table),
- used_table_cache(item->used_table_cache),
field_lengths(item->field_lengths),
tmp_table_param(item->tmp_table_param),
- tree(item->tree), original(item), key_length(item->key_length),
- max_elements_in_tree(item->max_elements_in_tree),
- rec_offset(item->rec_offset), use_tree(item->use_tree),
+ tree(item->tree), original(item), tree_key_length(item->tree_key_length),
always_null(item->always_null)
{}
+ ~Item_sum_count_distinct();
+
void cleanup();
- table_map used_tables() const { return used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; }
void clear();
bool add();
longlong val_int();
void reset_field() { return ;} // Never called
void update_field() { return ; } // Never called
- const char *func_name() const { return "count_distinct"; }
+ const char *func_name() const { return "count(distinct "; }
bool setup(THD *thd);
void make_unique();
Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
- void print(String *str);
};
@@ -265,43 +354,55 @@ class Item_avg_field :public Item_result_field
{
public:
Field *field;
- Item_avg_field(Item_sum_avg *item);
+ Item_result hybrid_type;
+ uint f_precision, f_scale, dec_bin_size;
+ uint prec_increment;
+ Item_avg_field(Item_result res_type, Item_sum_avg *item);
enum Type type() const { return FIELD_AVG_ITEM; }
- double val();
- longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); }
+ double val_real();
+ longlong val_int();
+ my_decimal *val_decimal(my_decimal *);
bool is_null() { (void) val_int(); return null_value; }
String *val_str(String*);
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ enum_field_types field_type() const
+ {
+ return hybrid_type == DECIMAL_RESULT ?
+ MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE;
+ }
void fix_length_and_dec() {}
+ enum Item_result result_type () const { return hybrid_type; }
};
-class Item_sum_avg :public Item_sum_num
+class Item_sum_avg :public Item_sum_sum
{
- void fix_length_and_dec()
- {
- decimals=min(decimals+4, NOT_FIXED_DEC);
- maybe_null=1;
- }
-
- double sum;
+public:
ulonglong count;
+ uint prec_increment;
+ uint f_precision, f_scale, dec_bin_size;
- public:
- Item_sum_avg(Item *item_par) :Item_sum_num(item_par), sum(0.0), count(0) {}
+ Item_sum_avg(Item *item_par) :Item_sum_sum(item_par), count(0) {}
Item_sum_avg(THD *thd, Item_sum_avg *item)
- :Item_sum_num(thd, item), sum(item->sum), count(item->count) {}
+ :Item_sum_sum(thd, item), count(item->count),
+ prec_increment(item->prec_increment) {}
+
+ void fix_length_and_dec();
enum Sumfunctype sum_func () const {return AVG_FUNC;}
void clear();
bool add();
- double val();
+ double val_real();
+ // In SPs we might force the "wrong" type with select into a declare variable
+ longlong val_int() { return (longlong)val_real(); }
+ my_decimal *val_decimal(my_decimal *);
+ String *val_str(String *str);
void reset_field();
void update_field();
Item *result_item(Field *field)
- { return new Item_avg_field(this); }
+ { return new Item_avg_field(hybrid_type, this); }
void no_rows_in_result() {}
- const char *func_name() const { return "avg"; }
+ const char *func_name() const { return "avg("; }
Item *copy_or_same(THD* thd);
+ Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
};
class Item_sum_variance;
@@ -310,14 +411,27 @@ class Item_variance_field :public Item_result_field
{
public:
Field *field;
+ Item_result hybrid_type;
+ uint f_precision0, f_scale0;
+ uint f_precision1, f_scale1;
+ uint dec_bin_size0, dec_bin_size1;
+ uint sample;
+ uint prec_increment;
Item_variance_field(Item_sum_variance *item);
enum Type type() const {return FIELD_VARIANCE_ITEM; }
- double val();
- longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); }
+ double val_real();
+ longlong val_int()
+ { /* can't be fix_fields()ed */ return (longlong) val_real(); }
String *val_str(String*);
+ my_decimal *val_decimal(my_decimal *);
bool is_null() { (void) val_int(); return null_value; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ enum_field_types field_type() const
+ {
+ return hybrid_type == DECIMAL_RESULT ?
+ MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE;
+ }
void fix_length_and_dec() {}
+ enum Item_result result_type () const { return hybrid_type; }
};
@@ -335,30 +449,39 @@ public:
class Item_sum_variance : public Item_sum_num
{
+ void fix_length_and_dec();
+
+public:
+ Item_result hybrid_type;
double sum, sum_sqr;
+ my_decimal dec_sum[2], dec_sqr[2];
+ int cur_dec;
ulonglong count;
- void fix_length_and_dec()
- {
- decimals=min(decimals+4, NOT_FIXED_DEC);
- maybe_null=1;
- }
-
- public:
- Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {}
- Item_sum_variance(THD *thd, Item_sum_variance *item):
- Item_sum_num(thd, item), sum(item->sum), sum_sqr(item->sum_sqr),
- count(item->count) {}
+ uint f_precision0, f_scale0;
+ uint f_precision1, f_scale1;
+ uint dec_bin_size0, dec_bin_size1;
+ uint sample;
+ uint prec_increment;
+
+ Item_sum_variance(Item *item_par, uint sample_arg) :Item_sum_num(item_par),
+ hybrid_type(REAL_RESULT), cur_dec(0), count(0), sample(sample_arg)
+ {}
+ Item_sum_variance(THD *thd, Item_sum_variance *item);
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void clear();
bool add();
- double val();
+ double val_real();
+ my_decimal *val_decimal(my_decimal *);
void reset_field();
void update_field();
Item *result_item(Field *field)
{ return new Item_variance_field(this); }
void no_rows_in_result() {}
- const char *func_name() const { return "variance"; }
+ const char *func_name() const
+ { return sample ? "var_samp(" : "variance("; }
Item *copy_or_same(THD* thd);
+ Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
+ enum Item_result result_type () const { return hybrid_type; }
};
class Item_sum_std;
@@ -368,7 +491,10 @@ class Item_std_field :public Item_variance_field
public:
Item_std_field(Item_sum_std *item);
enum Type type() const { return FIELD_STD_ITEM; }
- double val();
+ double val_real();
+ my_decimal *val_decimal(my_decimal *);
+ enum Item_result result_type () const { return REAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;}
};
/*
@@ -378,26 +504,30 @@ public:
class Item_sum_std :public Item_sum_variance
{
public:
- Item_sum_std(Item *item_par) :Item_sum_variance(item_par) {}
+ Item_sum_std(Item *item_par, uint sample_arg)
+ :Item_sum_variance(item_par, sample_arg) {}
Item_sum_std(THD *thd, Item_sum_std *item)
:Item_sum_variance(thd, item)
{}
enum Sumfunctype sum_func () const { return STD_FUNC; }
- double val();
+ double val_real();
Item *result_item(Field *field)
{ return new Item_std_field(this); }
- const char *func_name() const { return "std"; }
+ const char *func_name() const { return "std("; }
Item *copy_or_same(THD* thd);
+ enum Item_result result_type () const { return REAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;}
};
// This class is a string or number function depending on num_func
class Item_sum_hybrid :public Item_sum
{
- protected:
+protected:
String value,tmp_value;
double sum;
longlong sum_int;
+ my_decimal sum_dec;
Item_result hybrid_type;
enum_field_types hybrid_field_type;
int cmp_sign;
@@ -408,22 +538,18 @@ class Item_sum_hybrid :public Item_sum
Item_sum_hybrid(Item *item_par,int sign)
:Item_sum(item_par), sum(0.0), sum_int(0),
hybrid_type(INT_RESULT), hybrid_field_type(FIELD_TYPE_LONGLONG),
- cmp_sign(sign), used_table_cache(~(table_map) 0), was_values(TRUE)
- { collation.set(&my_charset_bin); }
- Item_sum_hybrid(THD *thd, Item_sum_hybrid *item):
- Item_sum(thd, item), value(item->value),
- sum(item->sum), sum_int(item->sum_int), hybrid_type(item->hybrid_type),
- hybrid_field_type(item->hybrid_field_type),cmp_sign(item->cmp_sign),
- used_table_cache(item->used_table_cache),
+ cmp_sign(sign), used_table_cache(~(table_map) 0),
was_values(TRUE)
- { collation.set(item->collation); }
- bool fix_fields(THD *, TABLE_LIST *, Item **);
+ { collation.set(&my_charset_bin); }
+ Item_sum_hybrid(THD *thd, Item_sum_hybrid *item);
+ bool fix_fields(THD *, Item **);
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
void clear();
- double val();
+ double val_real();
longlong val_int();
+ my_decimal *val_decimal(my_decimal *);
void reset_field();
String *val_str(String *);
void make_const() { used_table_cache=0; }
@@ -434,9 +560,12 @@ 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 min_max_update_decimal_field();
void cleanup();
bool any_value() { return was_values; }
void no_rows_in_result();
+ Field *create_tmp_field(bool group, TABLE *table,
+ uint convert_blob_length);
};
@@ -448,7 +577,7 @@ public:
enum Sumfunctype sum_func () const {return MIN_FUNC;}
bool add();
- const char *func_name() const { return "min"; }
+ const char *func_name() const { return "min("; }
Item *copy_or_same(THD* thd);
};
@@ -461,7 +590,7 @@ public:
enum Sumfunctype sum_func () const {return MAX_FUNC;}
bool add();
- const char *func_name() const { return "max"; }
+ const char *func_name() const { return "max("; }
Item *copy_or_same(THD* thd);
};
@@ -482,7 +611,7 @@ public:
void reset_field();
void update_field();
void fix_length_and_dec()
- { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; }
+ { decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; }
};
@@ -492,7 +621,7 @@ public:
Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {}
bool add();
- const char *func_name() const { return "bit_or"; }
+ const char *func_name() const { return "bit_or("; }
Item *copy_or_same(THD* thd);
};
@@ -503,7 +632,7 @@ class Item_sum_and :public Item_sum_bit
Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {}
Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {}
bool add();
- const char *func_name() const { return "bit_and"; }
+ const char *func_name() const { return "bit_and("; }
Item *copy_or_same(THD* thd);
};
@@ -513,7 +642,7 @@ class Item_sum_xor :public Item_sum_bit
Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {}
bool add();
- const char *func_name() const { return "bit_xor"; }
+ const char *func_name() const { return "bit_xor("; }
Item *copy_or_same(THD* thd);
};
@@ -530,18 +659,21 @@ protected:
udf_handler udf;
public:
- Item_udf_sum(udf_func *udf_arg) :Item_sum(), udf(udf_arg) { quick_group=0;}
- Item_udf_sum( udf_func *udf_arg, List<Item> &list )
- :Item_sum( list ), udf(udf_arg)
+ Item_udf_sum(udf_func *udf_arg)
+ :Item_sum(), udf(udf_arg)
+ { quick_group=0; }
+ Item_udf_sum(udf_func *udf_arg, List<Item> &list)
+ :Item_sum(list), udf(udf_arg)
{ quick_group=0;}
Item_udf_sum(THD *thd, Item_udf_sum *item)
- :Item_sum(thd, item), udf(item->udf) { udf.not_original= TRUE; }
+ :Item_sum(thd, item), udf(item->udf)
+ { udf.not_original= TRUE; }
const char *func_name() const { return udf.name(); }
- bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+ bool fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
fixed= 1;
- return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
+ return udf.fix_fields(thd, this, this->arg_count, this->args);
}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
virtual bool have_field_update(void) const { return 0; }
@@ -551,21 +683,27 @@ public:
void reset_field() {};
void update_field() {};
void cleanup();
+ void print(String *str);
};
class Item_sum_udf_float :public Item_udf_sum
{
public:
- Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
+ Item_sum_udf_float(udf_func *udf_arg)
+ :Item_udf_sum(udf_arg) {}
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list)
- :Item_udf_sum(udf_arg,list) {}
+ :Item_udf_sum(udf_arg, list) {}
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
:Item_udf_sum(thd, item) {}
longlong val_int()
- { DBUG_ASSERT(fixed == 1); return (longlong) Item_sum_udf_float::val(); }
- double val();
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) Item_sum_udf_float::val_real();
+ }
+ double val_real();
String *val_str(String*str);
+ my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec() { fix_num_length_and_dec(); }
Item *copy_or_same(THD* thd);
};
@@ -574,15 +712,17 @@ class Item_sum_udf_float :public Item_udf_sum
class Item_sum_udf_int :public Item_udf_sum
{
public:
- Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
+ Item_sum_udf_int(udf_func *udf_arg)
+ :Item_udf_sum(udf_arg) {}
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list)
- :Item_udf_sum(udf_arg,list) {}
+ :Item_udf_sum(udf_arg, list) {}
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
:Item_udf_sum(thd, item) {}
longlong val_int();
- double val()
+ double val_real()
{ DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str);
+ my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=21; }
Item *copy_or_same(THD* thd);
@@ -592,43 +732,72 @@ public:
class Item_sum_udf_str :public Item_udf_sum
{
public:
- Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
+ Item_sum_udf_str(udf_func *udf_arg)
+ :Item_udf_sum(udf_arg) {}
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {}
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
:Item_udf_sum(thd, item) {}
String *val_str(String *);
- double val()
+ double val_real()
{
- int err;
+ int err_not_used;
char *end_not_used;
String *res;
res=val_str(&str_value);
return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(),
- &end_not_used, &err) : 0.0;
+ &end_not_used, &err_not_used) : 0.0;
}
longlong val_int()
{
- int err;
- String *res; res=val_str(&str_value);
- return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10, (char**) 0, &err) : (longlong) 0;
+ int err_not_used;
+ char *end;
+ String *res;
+ CHARSET_INFO *cs;
+
+ if (!(res= val_str(&str_value)))
+ return 0; /* Null value */
+ cs= res->charset();
+ end= (char*) res->ptr()+res->length();
+ return cs->cset->strtoll10(cs, res->ptr(), &end, &err_not_used);
}
+ my_decimal *val_decimal(my_decimal *dec);
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
Item *copy_or_same(THD* thd);
};
+
+class Item_sum_udf_decimal :public Item_udf_sum
+{
+public:
+ Item_sum_udf_decimal(udf_func *udf_arg)
+ :Item_udf_sum(udf_arg) {}
+ Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list)
+ :Item_udf_sum(udf_arg, list) {}
+ Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item)
+ :Item_udf_sum(thd, item) {}
+ String *val_str(String *);
+ double val_real();
+ longlong val_int();
+ my_decimal *val_decimal(my_decimal *);
+ enum Item_result result_type () const { return DECIMAL_RESULT; }
+ void fix_length_and_dec() { fix_num_length_and_dec(); }
+ Item *copy_or_same(THD* thd);
+};
+
#else /* Dummy functions to get sql_yacc.cc compiled */
class Item_sum_udf_float :public Item_sum_num
{
public:
- Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {}
+ Item_sum_udf_float(udf_func *udf_arg)
+ :Item_sum_num() {}
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
:Item_sum_num(thd, item) {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
- double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
void clear() {}
bool add() { return 0; }
void update_field() {}
@@ -638,29 +807,50 @@ class Item_sum_udf_float :public Item_sum_num
class Item_sum_udf_int :public Item_sum_num
{
public:
- Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {}
+ Item_sum_udf_int(udf_func *udf_arg)
+ :Item_sum_num() {}
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
:Item_sum_num(thd, item) {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
- double val() { DBUG_ASSERT(fixed == 1); return 0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0; }
void clear() {}
bool add() { return 0; }
void update_field() {}
};
+class Item_sum_udf_decimal :public Item_sum_num
+{
+ public:
+ Item_sum_udf_decimal(udf_func *udf_arg)
+ :Item_sum_num() {}
+ Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list)
+ :Item_sum_num() {}
+ Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item)
+ :Item_sum_num(thd, item) {}
+ enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
+ void clear() {}
+ bool add() { return 0; }
+ void update_field() {}
+};
+
+
class Item_sum_udf_str :public Item_sum_num
{
public:
- Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {}
- Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
+ Item_sum_udf_str(udf_func *udf_arg)
+ :Item_sum_num() {}
+ Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
+ :Item_sum_num() {}
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
:Item_sum_num(thd, item) {}
String *val_str(String *)
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
- double val() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; }
longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec() { maybe_null=1; max_length=0; }
@@ -676,15 +866,27 @@ class MYSQL_ERROR;
class Item_func_group_concat : public Item_sum
{
- THD *item_thd;
TMP_TABLE_PARAM *tmp_table_param;
- uint max_elements_in_tree;
MYSQL_ERROR *warning;
- uint key_length;
- bool tree_mode;
+ String result;
+ String *separator;
+ TREE tree_base;
+ TREE *tree;
+ TABLE *table;
+ ORDER **order;
+ Name_resolution_context *context;
+ uint arg_count_order; // total count of ORDER BY items
+ uint arg_count_field; // count of arguments
+ uint count_cut_values;
bool distinct;
bool warning_for_row;
bool always_null;
+ bool no_appended;
+ /*
+ Following is 0 normal object and pointer to original one for copy
+ (to correctly free resources)
+ */
+ Item_func_group_concat *original;
friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
byte* key2);
@@ -693,34 +895,17 @@ class Item_func_group_concat : public Item_sum
friend int group_concat_key_cmp_with_distinct_and_order(void* arg,
byte* key1,
byte* key2);
- friend int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
+ friend int dump_leaf_key(byte* key,
+ element_count count __attribute__((unused)),
Item_func_group_concat *group_concat_item);
- public:
- String result;
- String *separator;
- TREE tree_base;
- TREE *tree;
- TABLE *table;
- ORDER **order;
- TABLE_LIST *tables_list;
- ulong group_concat_max_len;
- uint arg_count_order;
- uint arg_count_field;
- uint field_list_offset;
- uint count_cut_values;
- bool no_appended;
- /*
- Following is 0 normal object and pointer to original one for copy
- (to correctly free resources)
- */
- Item_func_group_concat *original;
-
- Item_func_group_concat(bool is_distinct,List<Item> *is_select,
- SQL_LIST *is_order,String *is_separator);
-
+public:
+ Item_func_group_concat(Name_resolution_context *context_arg,
+ bool is_distinct, List<Item> *is_select,
+ SQL_LIST *is_order, String *is_separator);
+
Item_func_group_concat(THD *thd, Item_func_group_concat *item);
- ~Item_func_group_concat();
+ ~Item_func_group_concat() {}
void cleanup();
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
@@ -728,12 +913,12 @@ class Item_func_group_concat : public Item_sum
virtual Item_result result_type () const { return STRING_RESULT; }
void clear();
bool add();
- void reset_field();
- bool fix_fields(THD *, TABLE_LIST *, Item **);
+ void reset_field() { DBUG_ASSERT(0); } // not used
+ void update_field() { DBUG_ASSERT(0); } // not used
+ bool fix_fields(THD *,Item **);
bool setup(THD *thd);
void make_unique();
- virtual void update_field() {}
- double val()
+ double val_real()
{
String *res; res=val_str(&str_value);
return res ? my_atof(res->c_ptr()) : 0.0;
@@ -748,8 +933,14 @@ class Item_func_group_concat : public Item_sum
end_ptr= (char*) res->ptr()+ res->length();
return my_strtoll10(res->ptr(), &end_ptr, &error);
}
+ my_decimal *val_decimal(my_decimal *decimal_value)
+ {
+ return val_decimal_from_string(decimal_value);
+ }
String* val_str(String* str);
Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
void print(String *str);
+ virtual bool change_context_processor(byte *cntx)
+ { context= (Name_resolution_context *)cntx; return FALSE; }
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 2c53ba82007..7f94c19647e 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -160,7 +160,8 @@ static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0,
static bool extract_date_time(DATE_TIME_FORMAT *format,
const char *val, uint length, TIME *l_time,
timestamp_type cached_timestamp_type,
- const char **sub_pattern_end)
+ const char **sub_pattern_end,
+ const char *date_time_type)
{
int weekday= 0, yearday= 0, daypart= 0;
int week_number= -1;
@@ -188,12 +189,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
for (; ptr != end && val != val_end; ptr++)
{
-
if (*ptr == '%' && ptr+1 != end)
{
int val_len;
char *tmp;
+ error= 0;
/* Skip pre-space between each argument */
while (val != val_end && my_isspace(cs, *val))
val++;
@@ -343,16 +344,22 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
/* Time in AM/PM notation */
case 'r':
- error= extract_date_time(&time_ampm_format, val,
- (uint)(val_end - val), l_time,
- cached_timestamp_type, &val);
+ /*
+ We can't just set error here, as we don't want to generate two
+ warnings in case of errors
+ */
+ if (extract_date_time(&time_ampm_format, val,
+ (uint)(val_end - val), l_time,
+ cached_timestamp_type, &val, "time"))
+ DBUG_RETURN(1);
break;
/* Time in 24-hour notation */
case 'T':
- error= extract_date_time(&time_24hrs_format, val,
- (uint)(val_end - val), l_time,
- cached_timestamp_type, &val);
+ if (extract_date_time(&time_24hrs_format, val,
+ (uint)(val_end - val), l_time,
+ cached_timestamp_type, &val, "time"))
+ DBUG_RETURN(1);
break;
/* Conversion specifiers that match classes of characters */
@@ -463,7 +470,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
if (!my_isspace(&my_charset_latin1,*val))
{
make_truncated_value_warning(current_thd, val_begin, length,
- cached_timestamp_type);
+ cached_timestamp_type, NullS);
break;
}
} while (++val != val_end);
@@ -471,6 +478,13 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
DBUG_RETURN(0);
err:
+ {
+ char buff[128];
+ strmake(buff, val_begin, min(length, sizeof(buff)-1));
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
+ date_time_type, buff, "str_to_time");
+ }
DBUG_RETURN(1);
}
@@ -483,7 +497,6 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
timestamp_type type, String *str)
{
char intbuff[15];
- uint days_i;
uint hours_i;
uint weekday;
ulong length;
@@ -586,8 +599,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
break;
case 'h':
case 'I':
- days_i= l_time->hour/24;
- hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i;
+ hours_i= (l_time->hour%24 + 11)%12+1;
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 2, '0');
break;
@@ -608,8 +620,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'l':
- days_i= l_time->hour/24;
- hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i;
+ hours_i= (l_time->hour%24 + 11)%12+1;
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 1, '0');
break;
@@ -869,7 +880,7 @@ longlong Item_func_to_days::val_int()
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- if (get_arg0_date(&ltime,0))
+ if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
return 0;
return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
}
@@ -878,7 +889,7 @@ longlong Item_func_dayofyear::val_int()
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- if (get_arg0_date(&ltime,0))
+ if (get_arg0_date(&ltime,TIME_NO_ZERO_DATE))
return 0;
return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day) -
calc_daynr(ltime.year,1,1) + 1;
@@ -888,7 +899,7 @@ longlong Item_func_dayofmonth::val_int()
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- (void) get_arg0_date(&ltime,1);
+ (void) get_arg0_date(&ltime, TIME_FUZZY_DATE);
return (longlong) ltime.day;
}
@@ -896,7 +907,7 @@ longlong Item_func_month::val_int()
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- (void) get_arg0_date(&ltime,1);
+ (void) get_arg0_date(&ltime, TIME_FUZZY_DATE);
return (longlong) ltime.month;
}
@@ -925,7 +936,7 @@ longlong Item_func_quarter::val_int()
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- (void) get_arg0_date(&ltime,1);
+ (void) get_arg0_date(&ltime, TIME_FUZZY_DATE);
return (longlong) ((ltime.month+2)/3);
}
@@ -997,7 +1008,7 @@ longlong Item_func_week::val_int()
DBUG_ASSERT(fixed == 1);
uint year;
TIME ltime;
- if (get_arg0_date(&ltime,0))
+ if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
return 0;
return (longlong) calc_week(&ltime,
week_mode((uint) args[1]->val_int()),
@@ -1010,7 +1021,7 @@ longlong Item_func_yearweek::val_int()
DBUG_ASSERT(fixed == 1);
uint year,week;
TIME ltime;
- if (get_arg0_date(&ltime,0))
+ if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
return 0;
week= calc_week(&ltime,
(week_mode((uint) args[1]->val_int()) | WEEK_YEAR),
@@ -1019,16 +1030,17 @@ longlong Item_func_yearweek::val_int()
}
-/* weekday() has a automatic to_days() on item */
-
longlong Item_func_weekday::val_int()
{
DBUG_ASSERT(fixed == 1);
- ulong tmp_value=(ulong) args[0]->val_int();
- if ((null_value=(args[0]->null_value || !tmp_value)))
- return 0; /* purecov: inspected */
+ TIME ltime;
+
+ if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
+ return 0;
- return (longlong) calc_weekday(tmp_value,odbc_type)+test(odbc_type);
+ return (longlong) calc_weekday(calc_daynr(ltime.year, ltime.month,
+ ltime.day),
+ odbc_type) + test(odbc_type);
}
@@ -1051,7 +1063,7 @@ longlong Item_func_year::val_int()
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- (void) get_arg0_date(&ltime,1);
+ (void) get_arg0_date(&ltime, TIME_FUZZY_DATE);
return (longlong) ltime.year;
}
@@ -1059,7 +1071,7 @@ longlong Item_func_year::val_int()
longlong Item_func_unix_timestamp::val_int()
{
TIME ltime;
- bool not_used;
+ my_bool not_used;
DBUG_ASSERT(fixed == 1);
if (arg_count == 0)
@@ -1150,9 +1162,15 @@ static bool get_interval_value(Item *args,interval_type int_type,
case INTERVAL_YEAR:
interval->year= (ulong) value;
break;
+ case INTERVAL_QUARTER:
+ interval->month= (ulong)(value*3);
+ break;
case INTERVAL_MONTH:
interval->month= (ulong) value;
break;
+ case INTERVAL_WEEK:
+ interval->day= (ulong)(value*7);
+ break;
case INTERVAL_DAY:
interval->day= (ulong) value;
break;
@@ -1459,9 +1477,9 @@ void Item_func_now_utc::store_now_in_TIME(TIME *now_time)
bool Item_func_now::get_date(TIME *res,
- uint fuzzy_date __attribute__((unused)))
+ uint fuzzy_date __attribute__((unused)))
{
- *res=ltime;
+ *res= ltime;
return 0;
}
@@ -1474,6 +1492,70 @@ int Item_func_now::save_in_field(Field *to, bool no_conversions)
}
+/*
+ Converts current time in my_time_t to TIME represenatation for local
+ time zone. Defines time zone (local) used for whole SYSDATE function.
+*/
+void Item_func_sysdate_local::store_now_in_TIME(TIME *now_time)
+{
+ THD *thd= current_thd;
+ thd->variables.time_zone->gmt_sec_to_TIME(now_time, time(NULL));
+ thd->time_zone_used= 1;
+}
+
+
+String *Item_func_sysdate_local::val_str(String *str)
+{
+ DBUG_ASSERT(fixed == 1);
+ store_now_in_TIME(&ltime);
+ buff_length= (uint) my_datetime_to_str(&ltime, buff);
+ str_value.set(buff, buff_length, &my_charset_bin);
+ return &str_value;
+}
+
+
+longlong Item_func_sysdate_local::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ store_now_in_TIME(&ltime);
+ return (longlong) TIME_to_ulonglong_datetime(&ltime);
+}
+
+
+double Item_func_sysdate_local::val_real()
+{
+ DBUG_ASSERT(fixed == 1);
+ store_now_in_TIME(&ltime);
+ return (longlong) TIME_to_ulonglong_datetime(&ltime);
+}
+
+
+void Item_func_sysdate_local::fix_length_and_dec()
+{
+ decimals= 0;
+ collation.set(&my_charset_bin);
+ max_length= MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
+}
+
+
+bool Item_func_sysdate_local::get_date(TIME *res,
+ uint fuzzy_date __attribute__((unused)))
+{
+ store_now_in_TIME(&ltime);
+ *res= ltime;
+ return 0;
+}
+
+
+int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions)
+{
+ store_now_in_TIME(&ltime);
+ to->set_notnull();
+ to->store_time(&ltime, MYSQL_TIMESTAMP_DATETIME);
+ return 0;
+}
+
+
String *Item_func_sec_to_time::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -1623,7 +1705,7 @@ String *Item_func_date_format::val_str(String *str)
if (!is_time_format)
{
- if (get_arg0_date(&l_time,1))
+ if (get_arg0_date(&l_time, TIME_FUZZY_DATE))
return 0;
}
else
@@ -1736,15 +1818,15 @@ void Item_func_convert_tz::fix_length_and_dec()
bool
-Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **ref)
+Item_func_convert_tz::fix_fields(THD *thd_arg, Item **ref)
{
String str;
- if (Item_date_func::fix_fields(thd_arg, tables_arg, ref))
- return 1;
+ if (Item_date_func::fix_fields(thd_arg, ref))
+ return TRUE;
tz_tables= thd_arg->lex->time_zone_tables_used;
- return 0;
+ return FALSE;
}
@@ -1778,10 +1860,9 @@ longlong Item_func_convert_tz::val_int()
bool Item_func_convert_tz::get_date(TIME *ltime,
- uint fuzzy_date __attribute__((unused)))
+ uint fuzzy_date __attribute__((unused)))
{
my_time_t my_time_tmp;
- bool not_used;
String str;
if (!from_tz_cached)
@@ -1796,7 +1877,7 @@ bool Item_func_convert_tz::get_date(TIME *ltime,
to_tz_cached= args[2]->const_item();
}
- if (from_tz==0 || to_tz==0 || get_arg0_date(ltime, 0))
+ if (from_tz==0 || to_tz==0 || get_arg0_date(ltime, TIME_NO_ZERO_DATE))
{
null_value= 1;
return 1;
@@ -1807,6 +1888,7 @@ bool Item_func_convert_tz::get_date(TIME *ltime,
ltime->year==TIMESTAMP_MAX_YEAR && ltime->month==1 && ltime->day==1 ||
ltime->year==TIMESTAMP_MIN_YEAR && ltime->month==12 && ltime->day==31)
{
+ my_bool not_used;
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);
@@ -1867,7 +1949,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
INTERVAL interval;
ltime->neg= 0;
- if (args[0]->get_date(ltime,0) ||
+ if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE) ||
get_interval_value(args[1],int_type,&value,&interval))
goto null_date;
sign= (interval.neg ? -1 : 1);
@@ -1921,33 +2003,35 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
/* Day number from year 0 to 9999-12-31 */
if ((ulonglong) daynr >= MAX_DAY_NUMBER)
- goto null_date;
+ goto invalid_date;
get_date_from_daynr((long) daynr, &ltime->year, &ltime->month,
&ltime->day);
break;
}
case INTERVAL_DAY:
+ case INTERVAL_WEEK:
period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
sign * (long) interval.day);
/* Daynumber from year 0 to 9999-12-31 */
if ((ulong) period >= MAX_DAY_NUMBER)
- goto null_date;
+ goto invalid_date;
get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
break;
case INTERVAL_YEAR:
ltime->year+= sign * (long) interval.year;
if ((ulong) ltime->year >= 10000L)
- goto null_date;
+ goto invalid_date;
if (ltime->month == 2 && ltime->day == 29 &&
calc_days_in_year(ltime->year) != 366)
ltime->day=28; // Was leap-year
break;
case INTERVAL_YEAR_MONTH:
+ case INTERVAL_QUARTER:
case INTERVAL_MONTH:
period= (ltime->year*12 + sign * (long) interval.year*12 +
ltime->month-1 + sign * (long) interval.month);
if ((ulong) period >= 120000L)
- goto null_date;
+ goto invalid_date;
ltime->year= (uint) (period / 12);
ltime->month= (uint) (period % 12L)+1;
/* Adjust day if the new month doesn't have enough days */
@@ -1963,6 +2047,11 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
}
return 0; // Ok
+invalid_date:
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_DATETIME_FUNCTION_OVERFLOW,
+ ER(ER_DATETIME_FUNCTION_OVERFLOW),
+ "datetime");
null_date:
return (null_value=1);
}
@@ -1974,7 +2063,7 @@ String *Item_date_add_interval::val_str(String *str)
TIME ltime;
enum date_time_format_types format;
- if (Item_date_add_interval::get_date(&ltime,0))
+ if (Item_date_add_interval::get_date(&ltime, TIME_NO_ZERO_DATE))
return 0;
if (ltime.time_type == MYSQL_TIMESTAMP_DATE)
@@ -1997,7 +2086,7 @@ longlong Item_date_add_interval::val_int()
DBUG_ASSERT(fixed == 1);
TIME ltime;
longlong date;
- if (Item_date_add_interval::get_date(&ltime,0))
+ if (Item_date_add_interval::get_date(&ltime, TIME_NO_ZERO_DATE))
return (longlong) 0;
date = (ltime.year*100L + ltime.month)*100L + ltime.day;
return ltime.time_type == MYSQL_TIMESTAMP_DATE ? date :
@@ -2006,12 +2095,13 @@ longlong Item_date_add_interval::val_int()
static const char *interval_names[]=
{
- "year", "month", "day", "hour", "minute",
- "second", "microsecond", "year_month",
- "day_hour", "day_minute", "day_second",
- "hour_minute", "hour_second", "minute_second",
- "day_microsecond", "hour_microsecond",
- "minute_microsecond", "second_microsecond"
+ "year", "quarter", "month", "day", "hour",
+ "minute", "week", "second", "microsecond",
+ "year_month", "day_hour", "day_minute",
+ "day_second", "hour_minute", "hour_second",
+ "minute_second", "day_microsecond",
+ "hour_microsecond", "minute_microsecond",
+ "second_microsecond"
};
void Item_date_add_interval::print(String *str)
@@ -2042,7 +2132,9 @@ void Item_extract::fix_length_and_dec()
switch (int_type) {
case INTERVAL_YEAR: max_length=4; date_value=1; break;
case INTERVAL_YEAR_MONTH: max_length=6; date_value=1; break;
+ case INTERVAL_QUARTER: max_length=2; date_value=1; break;
case INTERVAL_MONTH: max_length=2; date_value=1; break;
+ case INTERVAL_WEEK: max_length=2; date_value=1; break;
case INTERVAL_DAY: max_length=2; date_value=1; break;
case INTERVAL_DAY_HOUR: max_length=9; date_value=0; break;
case INTERVAL_DAY_MINUTE: max_length=11; date_value=0; break;
@@ -2066,10 +2158,12 @@ longlong Item_extract::val_int()
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
+ uint year;
+ ulong week_format;
long neg;
if (date_value)
{
- if (get_arg0_date(&ltime,1))
+ if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
return 0;
neg=1;
}
@@ -2087,7 +2181,13 @@ longlong Item_extract::val_int()
switch (int_type) {
case INTERVAL_YEAR: return ltime.year;
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
+ case INTERVAL_QUARTER: return ltime.month/3 + 1;
case INTERVAL_MONTH: return ltime.month;
+ case INTERVAL_WEEK:
+ {
+ week_format= current_thd->variables.default_week_format;
+ return calc_week(&ltime, week_mode(week_format), &year);
+ }
case INTERVAL_DAY: return ltime.day;
case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg;
case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+
@@ -2128,7 +2228,7 @@ bool Item_extract::eq(const Item *item, bool binary_cmp) const
if (this == item)
return 1;
if (item->type() != FUNC_ITEM ||
- func_name() != ((Item_func*)item)->func_name())
+ functype() != ((Item_func*)item)->functype())
return 0;
Item_extract* ie= (Item_extract*)item;
@@ -2146,7 +2246,7 @@ bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const
if (this == item)
return 1;
if (item->type() != FUNC_ITEM ||
- func_name() != ((Item_func*)item)->func_name())
+ functype() != ((Item_func*)item)->functype())
return 0;
Item_char_typecast *cast= (Item_char_typecast*)item;
@@ -2187,7 +2287,7 @@ void Item_char_typecast::print(String *str)
if (cast_cs)
{
str->append(" charset ", 9);
- str->append(cast_cs->name);
+ str->append(cast_cs->csname);
}
str->append(')');
}
@@ -2223,39 +2323,47 @@ String *Item_char_typecast::val_str(String *str)
res->set_charset(cast_cs);
/*
- Cut the tail if cast with length
- and the result is longer than cast length, e.g.
- CAST('string' AS CHAR(1))
+ Cut the tail if cast with length
+ and the result is longer than cast length, e.g.
+ CAST('string' AS CHAR(1))
*/
if (cast_length >= 0 &&
(res->length() > (length= (uint32) res->charpos(cast_length))))
{ // Safe even if const arg
+ char char_type[40];
+ my_snprintf(char_type, sizeof(char_type), "CHAR(%lu)", length);
+
if (!res->alloced_length())
{ // Don't change const str
str_value= *res; // Not malloced string
res= &str_value;
}
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), char_type,
+ res->c_ptr_safe());
res->length((uint) length);
}
null_value= 0;
return res;
}
+
void Item_char_typecast::fix_length_and_dec()
{
uint32 char_length;
- /*
- We always force character set conversion if cast_cs
- is a multi-byte character set. It garantees that the
- result of CAST is a well-formed string.
- For single-byte character sets we allow just to copy
- from the argument. A single-byte character sets string
- is always well-formed.
+ /*
+ We always force character set conversion if cast_cs is a
+ multi-byte character set. It garantees that the result of CAST is
+ a well-formed string. For single-byte character sets we allow
+ just to copy from the argument. A single-byte character sets
+ string is always well-formed.
*/
- charset_conversion= (cast_cs->mbmaxlen > 1) ||
- !my_charset_same(args[0]->collation.collation, cast_cs) &&
- args[0]->collation.collation != &my_charset_bin &&
- cast_cs != &my_charset_bin;
+ charset_conversion= ((cast_cs->mbmaxlen > 1) ||
+ !my_charset_same(args[0]->collation.collation,
+ cast_cs) &&
+ args[0]->collation.collation != &my_charset_bin &&
+ cast_cs != &my_charset_bin);
collation.set(cast_cs, DERIVATION_IMPLICIT);
char_length= (cast_length >= 0) ? cast_length :
args[0]->max_length/args[0]->collation.collation->mbmaxlen;
@@ -2267,7 +2375,7 @@ String *Item_datetime_typecast::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- if (!get_arg0_date(&ltime,1) &&
+ if (!get_arg0_date(&ltime, TIME_FUZZY_DATE) &&
!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
&ltime, str))
return str;
@@ -2308,7 +2416,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);
+ bool res= get_arg0_date(ltime, TIME_FUZZY_DATE);
ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
ltime->time_type= MYSQL_TIMESTAMP_DATE;
return res;
@@ -2320,7 +2428,7 @@ String *Item_date_typecast::val_str(String *str)
DBUG_ASSERT(fixed == 1);
TIME ltime;
- if (!get_arg0_date(&ltime,1) && !str->alloc(11))
+ if (!get_arg0_date(&ltime, TIME_FUZZY_DATE) && !str->alloc(11))
{
make_date((DATE_TIME_FORMAT *) 0, &ltime, str);
return str;
@@ -2414,7 +2522,7 @@ String *Item_func_add_time::val_str(String *str)
null_value=0;
if (is_date) // TIMESTAMP function
{
- if (get_arg0_date(&l_time1,1) ||
+ if (get_arg0_date(&l_time1, TIME_FUZZY_DATE) ||
args[1]->get_time(&l_time2) ||
l_time1.time_type == MYSQL_TIMESTAMP_TIME ||
l_time2.time_type != MYSQL_TIMESTAMP_TIME)
@@ -2486,7 +2594,7 @@ void Item_func_add_time::print(String *str)
}
args[0]->print(str);
str->append(',');
- args[0]->print(str);
+ args[1]->print(str);
str->append(')');
}
@@ -2594,6 +2702,163 @@ longlong Item_func_microsecond::val_int()
}
+longlong Item_func_timestamp_diff::val_int()
+{
+ TIME ltime1, ltime2;
+ longlong seconds;
+ long microseconds;
+ long months= 0;
+ int neg= 1;
+
+ null_value= 0;
+ if (args[0]->get_date(&ltime1, TIME_NO_ZERO_DATE) ||
+ args[1]->get_date(&ltime2, TIME_NO_ZERO_DATE))
+ goto null_date;
+
+ if (calc_time_diff(&ltime2,&ltime1, 1,
+ &seconds, &microseconds))
+ neg= -1;
+
+ if (int_type == INTERVAL_YEAR ||
+ int_type == INTERVAL_QUARTER ||
+ int_type == INTERVAL_MONTH)
+ {
+ uint year;
+ uint year_beg, year_end, month_beg, month_end;
+ uint diff_days= (uint) (seconds/86400L);
+ uint diff_years= 0;
+ if (neg == -1)
+ {
+ year_beg= ltime2.year;
+ year_end= ltime1.year;
+ month_beg= ltime2.month;
+ month_end= ltime1.month;
+ }
+ else
+ {
+ year_beg= ltime1.year;
+ year_end= ltime2.year;
+ month_beg= ltime1.month;
+ month_end= ltime2.month;
+ }
+ /* calc years*/
+ for (year= year_beg;year < year_end; year++)
+ {
+ uint days=calc_days_in_year(year);
+ if (days > diff_days)
+ break;
+ diff_days-= days;
+ diff_years++;
+ }
+
+ /* calc months; Current year is in the 'year' variable */
+ month_beg--; /* Change months to be 0-11 for easier calculation */
+ month_end--;
+
+ months= 12*diff_years;
+ while (month_beg != month_end)
+ {
+ uint m_days= (uint) days_in_month[month_beg];
+ if (month_beg == 1)
+ {
+ /* This is only calculated once so there is no reason to cache it*/
+ uint leap= (uint) ((year & 3) == 0 && (year%100 ||
+ (year%400 == 0 && year)));
+ m_days+= leap;
+ }
+ if (m_days > diff_days)
+ break;
+ diff_days-= m_days;
+ months++;
+ if (month_beg++ == 11) /* if we wrap to next year */
+ {
+ month_beg= 0;
+ year++;
+ }
+ }
+ if (neg == -1)
+ months= -months;
+ }
+
+ switch (int_type) {
+ case INTERVAL_YEAR:
+ return months/12;
+ case INTERVAL_QUARTER:
+ return months/3;
+ case INTERVAL_MONTH:
+ return months;
+ case INTERVAL_WEEK:
+ return seconds/86400L/7L*neg;
+ case INTERVAL_DAY:
+ return seconds/86400L*neg;
+ case INTERVAL_HOUR:
+ return seconds/3600L*neg;
+ case INTERVAL_MINUTE:
+ return seconds/60L*neg;
+ case INTERVAL_SECOND:
+ return seconds*neg;
+ case INTERVAL_MICROSECOND:
+ /*
+ In MySQL difference between any two valid datetime values
+ in microseconds fits into longlong.
+ */
+ return (seconds*1000000L+microseconds)*neg;
+ default:
+ break;
+ }
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+void Item_func_timestamp_diff::print(String *str)
+{
+ str->append(func_name());
+ str->append('(');
+
+ switch (int_type) {
+ case INTERVAL_YEAR:
+ str->append("YEAR");
+ break;
+ case INTERVAL_QUARTER:
+ str->append("QUARTER");
+ break;
+ case INTERVAL_MONTH:
+ str->append("MONTH");
+ break;
+ case INTERVAL_WEEK:
+ str->append("WEEK");
+ break;
+ case INTERVAL_DAY:
+ str->append("DAY");
+ break;
+ case INTERVAL_HOUR:
+ str->append("HOUR");
+ break;
+ case INTERVAL_MINUTE:
+ str->append("MINUTE");
+ break;
+ case INTERVAL_SECOND:
+ str->append("SECOND");
+ break;
+ case INTERVAL_MICROSECOND:
+ str->append("SECOND_FRAC");
+ break;
+ default:
+ break;
+ }
+
+ for (uint i=0 ; i < 2 ; i++)
+ {
+ str->append(',');
+ args[i]->print(str);
+ }
+ str->append(')');
+}
+
+
String *Item_func_get_format::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -2700,9 +2965,9 @@ get_date_time_result_type(const char *format, uint length)
have all types of date-time components and can end our search.
*/
return DATE_TIME_MICROSECOND;
- }
}
}
+ }
/* We don't have all three types of date-time components */
if (frac_second_used)
@@ -2780,7 +3045,7 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
date_time_format.format.str= (char*) format->ptr();
date_time_format.format.length= format->length();
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
- ltime, cached_timestamp_type, 0))
+ ltime, cached_timestamp_type, 0, "datetime"))
goto null_date;
if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day)
{
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 0df84d14bea..8e15acbc1fc 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -88,7 +88,7 @@ class Item_func_month :public Item_func
public:
Item_func_month(Item *a) :Item_func(a) {}
longlong val_int();
- double val()
+ double val_real()
{ DBUG_ASSERT(fixed == 1); return (double) Item_func_month::val_int(); }
String *val_str(String *str)
{
@@ -250,14 +250,17 @@ public:
Item_func_weekday(Item *a,bool type_arg)
:Item_func(a), odbc_type(type_arg) {}
longlong val_int();
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
str->set(val_int(), &my_charset_bin);
return null_value ? 0 : str;
}
- const char *func_name() const { return "weekday"; }
+ const char *func_name() const
+ {
+ return (odbc_type ? "dayofweek" : "weekday");
+ }
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
{
@@ -315,7 +318,9 @@ public:
};
-/* This can't be a Item_str_func, because the val() functions are special */
+/*
+ This can't be a Item_str_func, because the val_real() functions are special
+*/
class Item_date :public Item_func
{
@@ -326,7 +331,7 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
String *val_str(String *str);
longlong val_int();
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
const char *func_name() const { return "date"; }
void fix_length_and_dec()
{
@@ -369,7 +374,7 @@ public:
Item_func_curtime(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
String *val_str(String *str);
void fix_length_and_dec();
@@ -444,6 +449,7 @@ public:
class Item_func_now :public Item_date_func
{
+protected:
longlong value;
char buff[20*2+32]; // +32 to make my_snprintf_{8bit|ucs2} happy
uint buff_length;
@@ -452,7 +458,7 @@ public:
Item_func_now() :Item_date_func() {}
Item_func_now(Item *a) :Item_date_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
int save_in_field(Field *to, bool no_conversions);
String *val_str(String *str);
@@ -483,6 +489,32 @@ public:
};
+/*
+ This is like NOW(), but always uses the real current time, not the
+ query_start(). This matches the Oracle behavior.
+*/
+class Item_func_sysdate_local :public Item_func_now
+{
+public:
+ Item_func_sysdate_local() :Item_func_now() {}
+ Item_func_sysdate_local(Item *a) :Item_func_now(a) {}
+ bool const_item() const { return 0; }
+ const char *func_name() const { return "sysdate"; }
+ void store_now_in_TIME(TIME *now_time);
+ double val_real();
+ longlong val_int();
+ int save_in_field(Field *to, bool no_conversions);
+ String *val_str(String *str);
+ void fix_length_and_dec();
+ bool get_date(TIME *res, uint fuzzy_date);
+ void update_used_tables()
+ {
+ Item_func_now::update_used_tables();
+ used_tables_cache|= RAND_TABLE_BIT;
+ }
+};
+
+
class Item_func_from_days :public Item_date
{
public:
@@ -501,7 +533,8 @@ public:
Item_func_date_format(Item *a,Item *b,bool is_time_format_arg)
:Item_str_func(a,b),is_time_format(is_time_format_arg) {}
String *val_str(String *str);
- const char *func_name() const { return "date_format"; }
+ const char *func_name() const
+ { return is_time_format ? "time_format" : "date_format"; }
void fix_length_and_dec();
uint format_length(const String *format);
};
@@ -512,7 +545,7 @@ class Item_func_from_unixtime :public Item_date_func
THD *thd;
public:
Item_func_from_unixtime(Item *a) :Item_date_func(a) {}
- double val()
+ double val_real()
{
DBUG_ASSERT(fixed == 1);
return (double) Item_func_from_unixtime::val_int();
@@ -555,10 +588,10 @@ class Item_func_convert_tz :public Item_date_func
Item_func_convert_tz(Item *a, Item *b, Item *c):
Item_date_func(a, b, c), from_tz_cached(0), to_tz_cached(0) {}
longlong val_int();
- double val() { return (double) val_int(); }
+ double val_real() { return (double) val_int(); }
String *val_str(String *str);
const char *func_name() const { return "convert_tz"; }
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void fix_length_and_dec();
bool get_date(TIME *res, uint fuzzy_date);
void cleanup();
@@ -569,7 +602,7 @@ class Item_func_sec_to_time :public Item_str_func
{
public:
Item_func_sec_to_time(Item *item) :Item_str_func(item) {}
- double val()
+ double val_real()
{
DBUG_ASSERT(fixed == 1);
return (double) Item_func_sec_to_time::val_int();
@@ -597,11 +630,11 @@ public:
enum interval_type
{
- INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
- INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH,
- INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND,
- INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND,
- INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND,
+ INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR,
+ INTERVAL_MINUTE, INTERVAL_WEEK, INTERVAL_SECOND, INTERVAL_MICROSECOND ,
+ INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
+ INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
+ INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND,
INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND
};
@@ -619,7 +652,7 @@ public:
const char *func_name() const { return "date_add_interval"; }
void fix_length_and_dec();
enum_field_types field_type() const { return cached_field_type; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
longlong val_int();
bool get_date(TIME *res, uint fuzzy_date);
void print(String *str);
@@ -635,6 +668,7 @@ class Item_extract :public Item_int_func
Item_extract(interval_type type_arg, Item *a)
:Item_int_func(a), int_type(type_arg) {}
longlong val_int();
+ enum Functype functype() const { return EXTRACT_FUNC; }
const char *func_name() const { return "extract"; }
void fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
@@ -687,6 +721,7 @@ class Item_char_typecast :public Item_typecast
public:
Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg)
:Item_typecast(a), cast_length(length_arg), cast_cs(cs_arg) {}
+ enum Functype functype() const { return CHAR_TYPECAST_FUNC; }
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "cast_as_char"; }
const char* cast_type() const { return "char"; };
@@ -794,6 +829,7 @@ public:
return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin));
}
void print(String *str);
+ const char *func_name() const { return "add_time"; }
};
class Item_func_timediff :public Item_str_func
@@ -848,6 +884,23 @@ public:
};
+class Item_func_timestamp_diff :public Item_int_func
+{
+ const interval_type int_type;
+public:
+ Item_func_timestamp_diff(Item *a,Item *b,interval_type type_arg)
+ :Item_int_func(a,b), int_type(type_arg) {}
+ const char *func_name() const { return "timestampdiff"; }
+ longlong val_int();
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ maybe_null=1;
+ }
+ void print(String *str);
+};
+
+
enum date_time_format
{
USA_FORMAT, JIS_FORMAT, ISO_FORMAT, EUR_FORMAT, INTERNAL_FORMAT
diff --git a/sql/item_uniq.cc b/sql/item_uniq.cc
index 7701bbbb63e..79b2ca68f4f 100644
--- a/sql/item_uniq.cc
+++ b/sql/item_uniq.cc
@@ -21,3 +21,9 @@
#endif
#include "mysql_priv.h"
+
+Field *Item_sum_unique_users::create_tmp_field(bool group, TABLE *table,
+ uint convert_blob_length)
+{
+ return new Field_long(9,maybe_null,name,table,1);
+}
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index b7e00f9f080..c884c454dac 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -27,9 +27,10 @@ class Item_func_unique_users :public Item_real_func
public:
Item_func_unique_users(Item *name_arg,int start,int end,List<Item> &list)
:Item_real_func(list) {}
- double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
void fix_length_and_dec() { decimals=0; max_length=6; }
void print(String *str) { str->append("0.0", 3); }
+ const char *func_name() const { return "unique_users"; }
};
@@ -40,21 +41,23 @@ public:
:Item_sum_num(item_arg) {}
Item_sum_unique_users(THD *thd, Item_sum_unique_users *item)
:Item_sum_num(thd, item) {}
- double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void clear() {}
bool add() { return 0; }
void reset_field() {}
void update_field() {}
- bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
+ bool fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
fixed= 1;
- return 0;
+ return FALSE;
}
Item *copy_or_same(THD* thd)
{
return new Item_sum_unique_users(thd, this);
}
void print(String *str) { str->append("0.0", 3); }
+ Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
+ const char *func_name() const { return "sum_unique_users"; }
};
diff --git a/sql/key.cc b/sql/key.cc
index 7ddd40de2c9..4bd71d2fa47 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -38,7 +38,9 @@ int find_ref_key(TABLE *table,Field *field, uint *key_length)
/* Test if some key starts as fieldpos */
- for (i=0, key_info=table->key_info ; i < (int) table->keys ; i++, key_info++)
+ for (i= 0, key_info= table->key_info ;
+ i < (int) table->s->keys ;
+ i++, key_info++)
{
if (key_info->key_part[0].offset == fieldpos)
{ /* Found key. Calc keylength */
@@ -48,7 +50,9 @@ int find_ref_key(TABLE *table,Field *field, uint *key_length)
}
/* Test if some key contains fieldpos */
- for (i=0, key_info=table->key_info ; i < (int) table->keys ; i++, key_info++)
+ for (i= 0, key_info= table->key_info ;
+ i < (int) table->s->keys ;
+ i++, key_info++)
{
uint j;
KEY_PART_INFO *key_part;
@@ -66,94 +70,159 @@ int find_ref_key(TABLE *table,Field *field, uint *key_length)
}
- /* Copy a key from record to some buffer */
- /* if length == 0 then copy whole key */
+/*
+ Copy part of a record that forms a key or key prefix to a buffer.
+
+ SYNOPSIS
+ key_copy()
+ to_key buffer that will be used as a key
+ from_record full record to be copied from
+ key_info descriptor of the index
+ key_length specifies length of all keyparts that will be copied
+
+ DESCRIPTION
+ The function takes a complete table record (as e.g. retrieved by
+ handler::index_read()), and a description of an index on the same table,
+ and extracts the first key_length bytes of the record which are part of a
+ key into to_key. If length == 0 then copy all bytes from the record that
+ form a key.
+
+ RETURN
+ None
+*/
-void key_copy(byte *key,TABLE *table,uint idx,uint key_length)
+void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length)
{
uint length;
- KEY *key_info=table->key_info+idx;
KEY_PART_INFO *key_part;
if (key_length == 0)
- key_length=key_info->key_length;
- for (key_part=key_info->key_part;
- (int) key_length > 0 ;
- key_part++)
+ key_length= key_info->key_length;
+ for (key_part= key_info->key_part; (int) key_length > 0; key_part++)
{
if (key_part->null_bit)
{
- *key++= test(table->record[0][key_part->null_offset] &
+ *to_key++= test(from_record[key_part->null_offset] &
key_part->null_bit);
key_length--;
}
+ if (key_part->type == HA_KEYTYPE_BIT)
+ {
+ Field_bit *field= (Field_bit *) (key_part->field);
+ if (field->bit_len)
+ {
+ uchar bits= get_rec_bits((uchar*) from_record +
+ key_part->null_offset +
+ (key_part->null_bit == 128),
+ field->bit_ofs, field->bit_len);
+ *to_key++= bits;
+ key_length--;
+ }
+ }
if (key_part->key_part_flag & HA_BLOB_PART)
{
char *pos;
- ulong blob_length=((Field_blob*) key_part->field)->get_length();
- key_length-=2;
+ ulong blob_length= ((Field_blob*) key_part->field)->get_length();
+ key_length-= HA_KEY_BLOB_LENGTH;
((Field_blob*) key_part->field)->get_ptr(&pos);
- length=min(key_length,key_part->length);
- set_if_smaller(blob_length,length);
- int2store(key,(uint) blob_length);
- key+=2; // Skip length info
- memcpy(key,pos,blob_length);
+ length=min(key_length, key_part->length);
+ set_if_smaller(blob_length, length);
+ int2store(to_key, (uint) blob_length);
+ to_key+= HA_KEY_BLOB_LENGTH; // Skip length info
+ memcpy(to_key, pos, blob_length);
+ }
+ else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
+ {
+ key_length-= HA_KEY_BLOB_LENGTH;
+ length= min(key_length, key_part->length);
+ key_part->field->get_key_image((char *) to_key, length, Field::itRAW);
+ to_key+= HA_KEY_BLOB_LENGTH;
}
else
{
- length=min(key_length,key_part->length);
- memcpy(key,table->record[0]+key_part->offset,(size_t) length);
+ length= min(key_length, key_part->length);
+ memcpy(to_key, from_record + key_part->offset, (size_t) length);
}
- key+=length;
- key_length-=length;
+ to_key+= length;
+ key_length-= length;
}
-} /* key_copy */
+}
+
+/*
+ Restore a key from some buffer to record.
+
+ SYNOPSIS
+ key_restore()
+ to_record record buffer where the key will be restored to
+ from_key buffer that contains a key
+ key_info descriptor of the index
+ key_length specifies length of all keyparts that will be restored
- /* restore a key from some buffer to record */
+ DESCRIPTION
+ This function converts a key into record format. It can be used in cases
+ when we want to return a key as a result row.
+
+ RETURN
+ None
+*/
-void key_restore(TABLE *table,byte *key,uint idx,uint key_length)
+void key_restore(byte *to_record, byte *from_key, KEY *key_info,
+ uint key_length)
{
uint length;
- KEY *key_info=table->key_info+idx;
KEY_PART_INFO *key_part;
if (key_length == 0)
{
- if (idx == (uint) -1)
- return;
- key_length=key_info->key_length;
+ key_length= key_info->key_length;
}
- for (key_part=key_info->key_part;
- (int) key_length > 0 ;
- key_part++)
+ for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++)
{
if (key_part->null_bit)
{
- if (*key++)
- table->record[0][key_part->null_offset]|= key_part->null_bit;
+ if (*from_key++)
+ to_record[key_part->null_offset]|= key_part->null_bit;
else
- table->record[0][key_part->null_offset]&= ~key_part->null_bit;
+ to_record[key_part->null_offset]&= ~key_part->null_bit;
key_length--;
}
+ if (key_part->type == HA_KEYTYPE_BIT)
+ {
+ Field_bit *field= (Field_bit *) (key_part->field);
+ if (field->bit_len)
+ {
+ uchar bits= *(from_key + key_part->length - field->field_length -1);
+ set_rec_bits(bits, to_record + key_part->null_offset +
+ (key_part->null_bit == 128),
+ field->bit_ofs, field->bit_len);
+ }
+ }
if (key_part->key_part_flag & HA_BLOB_PART)
{
- uint blob_length=uint2korr(key);
- key+=2;
- key_length-=2;
+ uint blob_length= uint2korr(from_key);
+ from_key+= HA_KEY_BLOB_LENGTH;
+ key_length-= HA_KEY_BLOB_LENGTH;
((Field_blob*) key_part->field)->set_ptr((ulong) blob_length,
- (char*) key);
- length=key_part->length;
+ (char*) from_key);
+ length= key_part->length;
+ }
+ else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
+ {
+ key_length-= HA_KEY_BLOB_LENGTH;
+ length= min(key_length, key_part->length);
+ key_part->field->set_key_image((char *) from_key, length);
+ from_key+= HA_KEY_BLOB_LENGTH;
}
else
{
- length=min(key_length,key_part->length);
- memcpy(table->record[0]+key_part->offset,key,(size_t) length);
+ length= min(key_length, key_part->length);
+ memcpy(to_record + key_part->offset, from_key, (size_t) length);
}
- key+=length;
- key_length-=length;
+ from_key+= length;
+ key_length-= length;
}
-} /* key_restore */
+}
/*
@@ -179,54 +248,54 @@ void key_restore(TABLE *table,byte *key,uint idx,uint key_length)
bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length)
{
- uint length;
+ uint store_length;
KEY_PART_INFO *key_part;
+ const byte *key_end= key + key_length;;
for (key_part=table->key_info[idx].key_part;
- (int) key_length > 0;
- key_part++, key+=length, key_length-=length)
+ key < key_end ;
+ key_part++, key+= store_length)
{
+ uint length;
+ store_length= key_part->store_length;
+
if (key_part->null_bit)
{
- key_length--;
if (*key != test(table->record[0][key_part->null_offset] &
key_part->null_bit))
return 1;
if (*key)
- {
- length=key_part->store_length;
continue;
- }
key++;
+ store_length--;
}
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART |
+ HA_BIT_PART))
{
- if (key_part->field->key_cmp(key, key_part->length+ HA_KEY_BLOB_LENGTH))
+ if (key_part->field->key_cmp(key, key_part->length))
return 1;
- length=key_part->length+HA_KEY_BLOB_LENGTH;
+ continue;
}
- else
+ length= min((uint) (key_end-key), store_length);
+ if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
+ FIELDFLAG_PACK)))
{
- length=min(key_length,key_part->length);
- if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
- FIELDFLAG_PACK)))
+ CHARSET_INFO *cs= key_part->field->charset();
+ uint char_length= key_part->length / cs->mbmaxlen;
+ const byte *pos= table->record[0] + key_part->offset;
+ if (length > char_length)
{
- CHARSET_INFO *cs= key_part->field->charset();
- uint char_length= key_part->length / cs->mbmaxlen;
- const byte *pos= table->record[0] + key_part->offset;
- if (length > char_length)
- {
- char_length= my_charpos(cs, pos, pos + length, char_length);
- set_if_smaller(char_length, length);
- }
- if (cs->coll->strnncollsp(cs,
- (const uchar*) key, length,
- (const uchar*) pos, char_length))
- return 1;
+ char_length= my_charpos(cs, pos, pos + length, char_length);
+ set_if_smaller(char_length, length);
}
- else if (memcmp(key,table->record[0]+key_part->offset,length))
- return 1;
+ if (cs->coll->strnncollsp(cs,
+ (const uchar*) key, length,
+ (const uchar*) pos, char_length, 0))
+ return 1;
+ continue;
}
+ if (memcmp(key,table->record[0]+key_part->offset,length))
+ return 1;
}
return 0;
}
@@ -302,9 +371,9 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
If table handler has primary key as part of the index, check that primary
key is not updated
*/
- if (idx != table->primary_key && table->primary_key < MAX_KEY &&
+ if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
(table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
- return check_if_key_used(table, table->primary_key, fields);
+ return check_if_key_used(table, table->s->primary_key, fields);
return 0;
}
diff --git a/sql/lex.h b/sql/lex.h
index 325d052de90..a5366742fd9 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -19,11 +19,11 @@
#include "lex_symbol.h"
-/* We don't want to include sql_yacc.h into gen_lex_hash */
SYM_GROUP sym_group_common= {"", ""};
SYM_GROUP sym_group_geom= {"Spatial extentions", "HAVE_SPATIAL"};
SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
+/* We don't want to include sql_yacc.h into gen_lex_hash */
#ifdef NO_YACC_SYMBOLS
#define SYM_OR_NULL(A) 0
#else
@@ -48,7 +48,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
*/
static SYMBOL symbols[] = {
- { "&&", SYM(AND_SYM)},
+ { "&&", SYM(AND_AND_SYM)},
{ "<", SYM(LT)},
{ "<=", SYM(LE)},
{ "<>", SYM(NE)},
@@ -65,6 +65,7 @@ static SYMBOL symbols[] = {
{ "AGAINST", SYM(AGAINST)},
{ "AGGREGATE", SYM(AGGREGATE_SYM)},
{ "ALL", SYM(ALL)},
+ { "ALGORITHM", SYM(ALGORITHM_SYM)},
{ "ALTER", SYM(ALTER)},
{ "ANALYZE", SYM(ANALYZE_SYM)},
{ "AND", SYM(AND_SYM)},
@@ -72,6 +73,7 @@ static SYMBOL symbols[] = {
{ "AS", SYM(AS)},
{ "ASC", SYM(ASC)},
{ "ASCII", SYM(ASCII_SYM)},
+ { "ASENSITIVE", SYM(ASENSITIVE_SYM)},
{ "AUTO_INCREMENT", SYM(AUTO_INC)},
{ "AVG", SYM(AVG_SYM)},
{ "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)},
@@ -93,8 +95,11 @@ static SYMBOL symbols[] = {
{ "BY", SYM(BY)},
{ "BYTE", SYM(BYTE_SYM)},
{ "CACHE", SYM(CACHE_SYM)},
+ { "CALL", SYM(CALL_SYM)},
{ "CASCADE", SYM(CASCADE)},
+ { "CASCADED", SYM(CASCADED)},
{ "CASE", SYM(CASE_SYM)},
+ { "CHAIN", SYM(CHAIN_SYM)},
{ "CHANGE", SYM(CHANGE)},
{ "CHANGED", SYM(CHANGED)},
{ "CHAR", SYM(CHAR_SYM)},
@@ -112,10 +117,15 @@ static SYMBOL symbols[] = {
{ "COMMENT", SYM(COMMENT_SYM)},
{ "COMMIT", SYM(COMMIT_SYM)},
{ "COMMITTED", SYM(COMMITTED_SYM)},
+ { "COMPACT", SYM(COMPACT_SYM)},
{ "COMPRESSED", SYM(COMPRESSED_SYM)},
{ "CONCURRENT", SYM(CONCURRENT)},
+ { "CONDITION", SYM(CONDITION_SYM)},
+ { "CONNECTION", SYM(CONNECTION_SYM)},
{ "CONSISTENT", SYM(CONSISTENT_SYM)},
{ "CONSTRAINT", SYM(CONSTRAINT)},
+ { "CONTAINS", SYM(CONTAINS_SYM)},
+ { "CONTINUE", SYM(CONTINUE_SYM)},
{ "CONVERT", SYM(CONVERT_SYM)},
{ "CREATE", SYM(CREATE)},
{ "CROSS", SYM(CROSS)},
@@ -124,6 +134,7 @@ static SYMBOL symbols[] = {
{ "CURRENT_TIME", SYM(CURTIME)},
{ "CURRENT_TIMESTAMP", SYM(NOW_SYM)},
{ "CURRENT_USER", SYM(CURRENT_USER)},
+ { "CURSOR", SYM(CURSOR_SYM)},
{ "DATA", SYM(DATA_SYM)},
{ "DATABASE", SYM(DATABASE)},
{ "DATABASES", SYM(DATABASES)},
@@ -137,13 +148,16 @@ static SYMBOL symbols[] = {
{ "DEALLOCATE", SYM(DEALLOCATE_SYM)},
{ "DEC", SYM(DECIMAL_SYM)},
{ "DECIMAL", SYM(DECIMAL_SYM)},
+ { "DECLARE", SYM(DECLARE_SYM)},
{ "DEFAULT", SYM(DEFAULT)},
+ { "DEFINER", SYM(DEFINER_SYM)},
{ "DELAYED", SYM(DELAYED_SYM)},
{ "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM)},
{ "DELETE", SYM(DELETE_SYM)},
{ "DESC", SYM(DESC)},
{ "DESCRIBE", SYM(DESCRIBE)},
{ "DES_KEY_FILE", SYM(DES_KEY_FILE)},
+ { "DETERMINISTIC", SYM(DETERMINISTIC_SYM)},
{ "DIRECTORY", SYM(DIRECTORY_SYM)},
{ "DISABLE", SYM(DISABLE_SYM)},
{ "DISCARD", SYM(DISCARD)},
@@ -157,7 +171,9 @@ static SYMBOL symbols[] = {
{ "DUMPFILE", SYM(DUMPFILE)},
{ "DUPLICATE", SYM(DUPLICATE_SYM)},
{ "DYNAMIC", SYM(DYNAMIC_SYM)},
+ { "EACH", SYM(EACH_SYM)},
{ "ELSE", SYM(ELSE)},
+ { "ELSEIF", SYM(ELSEIF_SYM)},
{ "ENABLE", SYM(ENABLE_SYM)},
{ "ENCLOSED", SYM(ENCLOSED)},
{ "END", SYM(END)},
@@ -170,11 +186,13 @@ static SYMBOL symbols[] = {
{ "EVENTS", SYM(EVENTS_SYM)},
{ "EXECUTE", SYM(EXECUTE_SYM)},
{ "EXISTS", SYM(EXISTS)},
+ { "EXIT", SYM(EXIT_SYM)},
{ "EXPANSION", SYM(EXPANSION_SYM)},
{ "EXPLAIN", SYM(DESCRIBE)},
{ "EXTENDED", SYM(EXTENDED_SYM)},
{ "FALSE", SYM(FALSE_SYM)},
{ "FAST", SYM(FAST_SYM)},
+ { "FETCH", SYM(FETCH_SYM)},
{ "FIELDS", SYM(COLUMNS)},
{ "FILE", SYM(FILE_SYM)},
{ "FIRST", SYM(FIRST_SYM)},
@@ -186,14 +204,19 @@ static SYMBOL symbols[] = {
{ "FOR", SYM(FOR_SYM)},
{ "FORCE", SYM(FORCE_SYM)},
{ "FOREIGN", SYM(FOREIGN)},
+ { "FOUND", SYM(FOUND_SYM)},
+ { "FRAC_SECOND", SYM(FRAC_SECOND_SYM)},
{ "FROM", SYM(FROM)},
{ "FULL", SYM(FULL)},
{ "FULLTEXT", SYM(FULLTEXT_SYM)},
- { "FUNCTION", SYM(UDF_SYM)},
+ { "FUNCTION", SYM(FUNCTION_SYM)},
{ "GEOMETRY", SYM(GEOMETRY_SYM)},
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
{ "GET_FORMAT", SYM(GET_FORMAT)},
{ "GLOBAL", SYM(GLOBAL_SYM)},
+#ifdef SP_GOTO
+ { "GOTO", SYM(GOTO_SYM)},
+#endif
{ "GRANT", SYM(GRANT)},
{ "GRANTS", SYM(GRANTS)},
{ "GROUP", SYM(GROUP)},
@@ -218,6 +241,8 @@ static SYMBOL symbols[] = {
{ "INNER", SYM(INNER_SYM)},
{ "INNOBASE", SYM(INNOBASE_SYM)},
{ "INNODB", SYM(INNOBASE_SYM)},
+ { "INOUT", SYM(INOUT_SYM)},
+ { "INSENSITIVE", SYM(INSENSITIVE_SYM)},
{ "INSERT", SYM(INSERT)},
{ "INSERT_METHOD", SYM(INSERT_METHOD)},
{ "INT", SYM(INT_SYM)},
@@ -233,12 +258,20 @@ static SYMBOL symbols[] = {
{ "IS", SYM(IS)},
{ "ISOLATION", SYM(ISOLATION)},
{ "ISSUER", SYM(ISSUER_SYM)},
+ { "ITERATE", SYM(ITERATE_SYM)},
+ { "INVOKER", SYM(INVOKER_SYM)},
{ "JOIN", SYM(JOIN_SYM)},
{ "KEY", SYM(KEY_SYM)},
{ "KEYS", SYM(KEYS)},
{ "KILL", SYM(KILL_SYM)},
+#ifdef SP_GOTO
+ /* QQ This will go away when the GOTO label syntax is fixed */
+ { "LABEL", SYM(LABEL_SYM)},
+#endif
+ { "LANGUAGE", SYM(LANGUAGE_SYM)},
{ "LAST", SYM(LAST_SYM)},
{ "LEADING", SYM(LEADING)},
+ { "LEAVE", SYM(LEAVE_SYM)},
{ "LEAVES", SYM(LEAVES)},
{ "LEFT", SYM(LEFT)},
{ "LEVEL", SYM(LEVEL_SYM)},
@@ -256,6 +289,7 @@ static SYMBOL symbols[] = {
{ "LONG", SYM(LONG_SYM)},
{ "LONGBLOB", SYM(LONGBLOB)},
{ "LONGTEXT", SYM(LONGTEXT)},
+ { "LOOP", SYM(LOOP_SYM)},
{ "LOW_PRIORITY", SYM(LOW_PRIORITY)},
{ "MASTER", SYM(MASTER_SYM)},
{ "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)},
@@ -277,23 +311,29 @@ static SYMBOL symbols[] = {
{ "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)},
{ "MAX_ROWS", SYM(MAX_ROWS)},
{ "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)},
+ { "MAX_USER_CONNECTIONS", SYM(MAX_USER_CONNECTIONS_SYM)},
{ "MEDIUM", SYM(MEDIUM_SYM)},
{ "MEDIUMBLOB", SYM(MEDIUMBLOB)},
{ "MEDIUMINT", SYM(MEDIUMINT)},
{ "MEDIUMTEXT", SYM(MEDIUMTEXT)},
+ { "MERGE", SYM(MERGE_SYM)},
{ "MICROSECOND", SYM(MICROSECOND_SYM)},
{ "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */
+ { "MIGRATE", SYM(MIGRATE_SYM)},
{ "MINUTE", SYM(MINUTE_SYM)},
{ "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM)},
{ "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM)},
{ "MIN_ROWS", SYM(MIN_ROWS)},
{ "MOD", SYM(MOD_SYM)},
{ "MODE", SYM(MODE_SYM)},
+ { "MODIFIES", SYM(MODIFIES_SYM)},
{ "MODIFY", SYM(MODIFY_SYM)},
{ "MONTH", SYM(MONTH_SYM)},
{ "MULTILINESTRING", SYM(MULTILINESTRING)},
{ "MULTIPOINT", SYM(MULTIPOINT)},
{ "MULTIPOLYGON", SYM(MULTIPOLYGON)},
+ { "MUTEX", SYM(MUTEX_SYM)},
+ { "NAME", SYM(NAME_SYM)},
{ "NAMES", SYM(NAMES_SYM)},
{ "NATIONAL", SYM(NATIONAL_SYM)},
{ "NATURAL", SYM(NATURAL)},
@@ -304,7 +344,7 @@ static SYMBOL symbols[] = {
{ "NEXT", SYM(NEXT_SYM)},
{ "NO", SYM(NO_SYM)},
{ "NONE", SYM(NONE_SYM)},
- { "NOT", SYM(NOT)},
+ { "NOT", SYM(NOT_SYM)},
{ "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)},
{ "NULL", SYM(NULL_SYM)},
{ "NUMERIC", SYM(NUMERIC_SYM)},
@@ -312,6 +352,7 @@ static SYMBOL symbols[] = {
{ "OFFSET", SYM(OFFSET_SYM)},
{ "OLD_PASSWORD", SYM(OLD_PASSWORD)},
{ "ON", SYM(ON)},
+ { "ONE", SYM(ONE_SYM)},
{ "ONE_SHOT", SYM(ONE_SHOT_SYM)},
{ "OPEN", SYM(OPEN_SYM)},
{ "OPTIMIZE", SYM(OPTIMIZE)},
@@ -319,11 +360,13 @@ static SYMBOL symbols[] = {
{ "OPTIONALLY", SYM(OPTIONALLY)},
{ "OR", SYM(OR_SYM)},
{ "ORDER", SYM(ORDER_SYM)},
+ { "OUT", SYM(OUT_SYM)},
{ "OUTER", SYM(OUTER)},
{ "OUTFILE", SYM(OUTFILE)},
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)},
{ "PARTIAL", SYM(PARTIAL)},
{ "PASSWORD", SYM(PASSWORD)},
+ { "PHASE", SYM(PHASE_SYM)},
{ "POINT", SYM(POINT_SYM)},
{ "POLYGON", SYM(POLYGON)},
{ "PRECISION", SYM(PRECISION)},
@@ -335,6 +378,7 @@ static SYMBOL symbols[] = {
{ "PROCESS" , SYM(PROCESS)},
{ "PROCESSLIST", SYM(PROCESSLIST_SYM)},
{ "PURGE", SYM(PURGE)},
+ { "QUARTER", SYM(QUARTER_SYM)},
{ "QUERY", SYM(QUERY_SYM)},
{ "QUICK", SYM(QUICK)},
{ "RAID0", SYM(RAID_0_SYM)},
@@ -342,36 +386,48 @@ static SYMBOL symbols[] = {
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE)},
{ "RAID_TYPE", SYM(RAID_TYPE)},
{ "READ", SYM(READ_SYM)},
+ { "READS", SYM(READS_SYM)},
{ "REAL", SYM(REAL)},
+ { "RECOVER", SYM(RECOVER_SYM)},
+ { "REDUNDANT", SYM(REDUNDANT_SYM)},
{ "REFERENCES", SYM(REFERENCES)},
{ "REGEXP", SYM(REGEXP)},
{ "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM)},
{ "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM)},
{ "RELAY_THREAD", SYM(RELAY_THREAD)},
+ { "RELEASE", SYM(RELEASE_SYM)},
{ "RELOAD", SYM(RELOAD)},
{ "RENAME", SYM(RENAME)},
{ "REPAIR", SYM(REPAIR)},
{ "REPEATABLE", SYM(REPEATABLE_SYM)},
{ "REPLACE", SYM(REPLACE)},
{ "REPLICATION", SYM(REPLICATION)},
+ { "REPEAT", SYM(REPEAT_SYM)},
{ "REQUIRE", SYM(REQUIRE_SYM)},
{ "RESET", SYM(RESET_SYM)},
{ "RESTORE", SYM(RESTORE_SYM)},
{ "RESTRICT", SYM(RESTRICT)},
- { "RETURNS", SYM(UDF_RETURNS_SYM)},
+ { "RESUME", SYM(RESUME_SYM)},
+ { "RETURN", SYM(RETURN_SYM)},
+ { "RETURNS", SYM(RETURNS_SYM)},
{ "REVOKE", SYM(REVOKE)},
{ "RIGHT", SYM(RIGHT)},
{ "RLIKE", SYM(REGEXP)}, /* Like in mSQL2 */
{ "ROLLBACK", SYM(ROLLBACK_SYM)},
{ "ROLLUP", SYM(ROLLUP_SYM)},
+ { "ROUTINE", SYM(ROUTINE_SYM)},
{ "ROW", SYM(ROW_SYM)},
{ "ROWS", SYM(ROWS_SYM)},
{ "ROW_FORMAT", SYM(ROW_FORMAT_SYM)},
{ "RTREE", SYM(RTREE_SYM)},
{ "SAVEPOINT", SYM(SAVEPOINT_SYM)},
+ { "SCHEMA", SYM(DATABASE)},
+ { "SCHEMAS", SYM(DATABASES)},
{ "SECOND", SYM(SECOND_SYM)},
{ "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM)},
+ { "SECURITY", SYM(SECURITY_SYM)},
{ "SELECT", SYM(SELECT_SYM)},
+ { "SENSITIVE", SYM(SENSITIVE_SYM)},
{ "SEPARATOR", SYM(SEPARATOR_SYM)},
{ "SERIAL", SYM(SERIAL_SYM)},
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM)},
@@ -389,6 +445,11 @@ static SYMBOL symbols[] = {
{ "SONAME", SYM(UDF_SONAME_SYM)},
{ "SOUNDS", SYM(SOUNDS_SYM)},
{ "SPATIAL", SYM(SPATIAL_SYM)},
+ { "SPECIFIC", SYM(SPECIFIC_SYM)},
+ { "SQL", SYM(SQL_SYM)},
+ { "SQLEXCEPTION", SYM(SQLEXCEPTION_SYM)},
+ { "SQLSTATE", SYM(SQLSTATE_SYM)},
+ { "SQLWARNING", SYM(SQLWARNING_SYM)},
{ "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT)},
{ "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT)},
{ "SQL_CACHE", SYM(SQL_CACHE_SYM)},
@@ -396,6 +457,15 @@ static SYMBOL symbols[] = {
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM)},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)},
{ "SQL_THREAD", SYM(SQL_THREAD)},
+ { "SQL_TSI_FRAC_SECOND", SYM(FRAC_SECOND_SYM)},
+ { "SQL_TSI_SECOND", SYM(SECOND_SYM)},
+ { "SQL_TSI_MINUTE", SYM(MINUTE_SYM)},
+ { "SQL_TSI_HOUR", SYM(HOUR_SYM)},
+ { "SQL_TSI_DAY", SYM(DAY_SYM)},
+ { "SQL_TSI_WEEK", SYM(WEEK_SYM)},
+ { "SQL_TSI_MONTH", SYM(MONTH_SYM)},
+ { "SQL_TSI_QUARTER", SYM(QUARTER_SYM)},
+ { "SQL_TSI_YEAR", SYM(YEAR_SYM)},
{ "SSL", SYM(SSL_SYM)},
{ "START", SYM(START_SYM)},
{ "STARTING", SYM(STARTING)},
@@ -407,29 +477,38 @@ static SYMBOL symbols[] = {
{ "STRIPED", SYM(RAID_STRIPED_SYM)},
{ "SUBJECT", SYM(SUBJECT_SYM)},
{ "SUPER", SYM(SUPER_SYM)},
+ { "SUSPEND", SYM(SUSPEND_SYM)},
{ "TABLE", SYM(TABLE_SYM)},
{ "TABLES", SYM(TABLES)},
{ "TABLESPACE", SYM(TABLESPACE)},
{ "TEMPORARY", SYM(TEMPORARY)},
+ { "TEMPTABLE", SYM(TEMPTABLE_SYM)},
{ "TERMINATED", SYM(TERMINATED)},
{ "TEXT", SYM(TEXT_SYM)},
{ "THEN", SYM(THEN_SYM)},
{ "TIME", SYM(TIME_SYM)},
{ "TIMESTAMP", SYM(TIMESTAMP)},
+ { "TIMESTAMPADD", SYM(TIMESTAMP_ADD)},
+ { "TIMESTAMPDIFF", SYM(TIMESTAMP_DIFF)},
{ "TINYBLOB", SYM(TINYBLOB)},
{ "TINYINT", SYM(TINYINT)},
{ "TINYTEXT", SYM(TINYTEXT)},
{ "TO", SYM(TO_SYM)},
{ "TRAILING", SYM(TRAILING)},
{ "TRANSACTION", SYM(TRANSACTION_SYM)},
+ { "TRIGGER", SYM(TRIGGER_SYM)},
+ { "TRIGGERS", SYM(TRIGGERS_SYM)},
{ "TRUE", SYM(TRUE_SYM)},
{ "TRUNCATE", SYM(TRUNCATE_SYM)},
{ "TYPE", SYM(TYPE_SYM)},
{ "TYPES", SYM(TYPES_SYM)},
{ "UNCOMMITTED", SYM(UNCOMMITTED_SYM)},
+ { "UNDEFINED", SYM(UNDEFINED_SYM)},
+ { "UNDO", SYM(UNDO_SYM)},
{ "UNICODE", SYM(UNICODE_SYM)},
{ "UNION", SYM(UNION_SYM)},
{ "UNIQUE", SYM(UNIQUE_SYM)},
+ { "UNKNOWN", SYM(UNKNOWN_SYM)},
{ "UNLOCK", SYM(UNLOCK_SYM)},
{ "UNSIGNED", SYM(UNSIGNED)},
{ "UNTIL", SYM(UNTIL_SYM)},
@@ -451,17 +530,21 @@ static SYMBOL symbols[] = {
{ "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)},
{ "WARNINGS", SYM(WARNINGS)},
+ { "WEEK", SYM(WEEK_SYM)},
{ "WHEN", SYM(WHEN_SYM)},
{ "WHERE", SYM(WHERE)},
+ { "WHILE", SYM(WHILE_SYM)},
+ { "VIEW", SYM(VIEW_SYM)},
{ "WITH", SYM(WITH)},
{ "WORK", SYM(WORK_SYM)},
{ "WRITE", SYM(WRITE_SYM)},
{ "X509", SYM(X509_SYM)},
{ "XOR", SYM(XOR)},
+ { "XA", SYM(XA_SYM)},
{ "YEAR", SYM(YEAR_SYM)},
{ "YEAR_MONTH", SYM(YEAR_MONTH_SYM)},
{ "ZEROFILL", SYM(ZEROFILL)},
- { "||", SYM(OR_OR_CONCAT)}
+ { "||", SYM(OR_OR_SYM)}
};
@@ -499,7 +582,6 @@ static SYMBOL sql_functions[] = {
{ "CONCAT", SYM(CONCAT)},
{ "CONCAT_WS", SYM(CONCAT_WS)},
{ "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", SYM(CONVERT_TZ_SYM)},
{ "COUNT", SYM(COUNT_SYM)},
@@ -614,6 +696,7 @@ static SYMBOL sql_functions[] = {
{ "MULTIPOINTFROMWKB",SYM(GEOMFROMWKB)},
{ "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT)},
{ "MULTIPOLYGONFROMWKB",SYM(GEOMFROMWKB)},
+ { "NAME_CONST", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_name_const)},
{ "NOW", SYM(NOW_SYM)},
{ "NULLIF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)},
{ "NUMGEOMETRIES", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numgeometries)},
@@ -636,14 +719,13 @@ static SYMBOL sql_functions[] = {
{ "POSITION", SYM(POSITION_SYM)},
{ "POW", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
{ "POWER", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
- { "QUARTER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quarter)},
{ "QUOTE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)},
{ "RADIANS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)},
{ "RAND", SYM(RAND)},
{ "RELEASE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)},
- { "REPEAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_repeat)},
{ "REVERSE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)},
{ "ROUND", SYM(ROUND)},
+ { "ROW_COUNT", SYM(ROW_COUNT_SYM)},
{ "RPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)},
{ "RTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)},
{ "SEC_TO_TIME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)},
@@ -653,6 +735,7 @@ static SYMBOL sql_functions[] = {
{ "SIN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)},
{ "SHA", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
{ "SHA1", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
+ { "SLEEP", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sleep)},
{ "SOUNDEX", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)},
{ "SPACE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)},
{ "SQRT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)},
@@ -660,6 +743,8 @@ static SYMBOL sql_functions[] = {
{ "STARTPOINT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_startpoint)},
{ "STD", SYM(STD_SYM)},
{ "STDDEV", SYM(STD_SYM)},
+ { "STDDEV_POP", SYM(STD_SYM)},
+ { "STDDEV_SAMP", SYM(STDDEV_SAMP_SYM)},
{ "STR_TO_DATE", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)},
{ "STRCMP", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
{ "SUBSTR", SYM(SUBSTRING)},
@@ -667,7 +752,7 @@ static SYMBOL sql_functions[] = {
{ "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX)},
{ "SUBTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
{ "SUM", SYM(SUM_SYM)},
- { "SYSDATE", SYM(NOW_SYM)},
+ { "SYSDATE", SYM(SYSDATE)},
{ "SYSTEM_USER", SYM(USER)},
{ "TAN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)},
{ "TIME_FORMAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
@@ -685,8 +770,9 @@ static SYMBOL sql_functions[] = {
{ "UPPER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "UUID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_uuid)},
{ "VARIANCE", SYM(VARIANCE_SYM)},
+ { "VAR_POP", SYM(VARIANCE_SYM)},
+ { "VAR_SAMP", SYM(VAR_SAMP_SYM)},
{ "VERSION", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
- { "WEEK", SYM(WEEK_SYM)},
{ "WEEKDAY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
{ "WEEKOFYEAR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)},
{ "WITHIN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)},
diff --git a/sql/lock.cc b/sql/lock.cc
index 944c36d4d1e..f4c4a781e45 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -79,7 +79,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
bool unlock, TABLE **write_locked);
static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
-static void print_lock_error(int error);
+static void print_lock_error(int error, const char *);
/*
@@ -93,18 +93,33 @@ static void print_lock_error(int error);
flags Options:
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK Ignore a global read lock
MYSQL_LOCK_IGNORE_FLUSH Ignore a flush tables.
+ MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN Instead of reopening altered
+ or dropped tables by itself,
+ mysql_lock_tables() should
+ notify upper level and rely
+ on caller doing this.
+ need_reopen Out parameter, TRUE if some tables were altered
+ or deleted and should be reopened by caller.
RETURN
A lock structure pointer on success.
- NULL on error.
+ NULL on error or if some tables should be reopen.
*/
-MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
+/* Map the return value of thr_lock to an error from errmsg.txt */
+static int thr_lock_errno_to_mysql[]=
+{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
+
+MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
+ uint flags, bool *need_reopen)
{
MYSQL_LOCK *sql_lock;
TABLE *write_lock_used;
+ int rc;
DBUG_ENTER("mysql_lock_tables");
+ *need_reopen= FALSE;
+
for (;;)
{
if (!(sql_lock = get_lock_data(thd,tables,count, 0,&write_lock_used)))
@@ -135,15 +150,24 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
{
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
- thd->proc_info=0;
break;
}
thd->proc_info="Table lock";
thd->locked=1;
- if (thr_multi_lock(sql_lock->locks,sql_lock->lock_count))
+ rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks,
+ sql_lock->lock_count,
+ thd->lock_id)];
+ if (rc > 1) /* a timeout or a deadlock */
+ {
+ my_error(rc, MYF(0));
+ my_free((gptr) sql_lock,MYF(0));
+ sql_lock= 0;
+ break;
+ }
+ else if (rc == 1) /* aborted */
{
thd->some_tables_deleted=1; // Try again
- sql_lock->lock_count=0; // Locks are alread freed
+ sql_lock->lock_count= 0; // Locks are already freed
}
else if (!thd->some_tables_deleted || (flags & MYSQL_LOCK_IGNORE_FLUSH))
{
@@ -164,13 +188,18 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
thd->locked=0;
retry:
sql_lock=0;
+ if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN)
+ {
+ *need_reopen= TRUE;
+ break;
+ }
if (wait_for_tables(thd))
break; // Couldn't open tables
}
thd->proc_info=0;
if (thd->killed)
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0));
+ thd->send_kill_message();
if (sql_lock)
{
mysql_unlock_tables(thd,sql_lock);
@@ -200,12 +229,12 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
if ((error=(*tables)->file->external_lock(thd,lock_type)))
{
+ print_lock_error(error, (*tables)->file->table_type());
for (; i-- ; tables--)
{
(*tables)->file->external_lock(thd, F_UNLCK);
(*tables)->current_lock=F_UNLCK;
}
- print_lock_error(error);
DBUG_RETURN(error);
}
else
@@ -408,12 +437,13 @@ static int unlock_external(THD *thd, TABLE **table,uint count)
{
(*table)->current_lock = F_UNLCK;
if ((error=(*table)->file->external_lock(thd, F_UNLCK)))
+ {
error_code=error;
+ print_lock_error(error_code, (*table)->file->table_type());
+ }
}
table++;
} while (--count);
- if (error_code)
- print_lock_error(error_code);
DBUG_RETURN(error_code);
}
@@ -434,11 +464,24 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
*write_lock_used=0;
for (i=tables=lock_count=0 ; i < count ; i++)
{
- if (table_ptr[i]->tmp_table != TMP_TABLE)
+ if (table_ptr[i]->s->tmp_table != TMP_TABLE)
{
tables+=table_ptr[i]->file->lock_count();
lock_count++;
}
+ /*
+ To be able to open and lock for reading system tables like 'mysql.proc',
+ when we already have some tables opened and locked, and avoid deadlocks
+ we have to disallow write-locking of these tables with any other tables.
+ */
+ if (table_ptr[i]->s->system_table &&
+ table_ptr[i]->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE &&
+ count != 1)
+ {
+ my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0), table_ptr[i]->s->db,
+ table_ptr[i]->s->table_name);
+ return 0;
+ }
}
if (!(sql_lock= (MYSQL_LOCK*)
@@ -454,7 +497,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
for (i=0 ; i < count ; i++)
{
TABLE *table;
- if ((table=table_ptr[i])->tmp_table == TMP_TABLE)
+ if ((table=table_ptr[i])->s->tmp_table == TMP_TABLE)
continue;
*to++=table;
enum thr_lock_type lock_type= table->reginfo.lock_type;
@@ -463,7 +506,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
*write_lock_used=table;
if (table->db_stat & HA_READ_ONLY)
{
- my_error(ER_OPEN_AS_READONLY,MYF(0),table->table_name);
+ my_error(ER_OPEN_AS_READONLY, MYF(0), table->alias);
my_free((gptr) sql_lock,MYF(0));
return 0;
}
@@ -559,11 +602,11 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
char *db= table_list->db;
uint key_length;
DBUG_ENTER("lock_table_name");
- DBUG_PRINT("enter",("db: %s name: %s", db, table_list->real_name));
+ DBUG_PRINT("enter",("db: %s name: %s", db, table_list->table_name));
safe_mutex_assert_owner(&LOCK_open);
- key_length=(uint) (strmov(strmov(key,db)+1,table_list->real_name)
+ key_length=(uint) (strmov(strmov(key,db)+1,table_list->table_name)
-key)+ 1;
@@ -582,8 +625,10 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length,
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(-1);
- memcpy((table->table_cache_key= (char*) (table+1)), key, key_length);
- table->key_length=key_length;
+ table->s= &table->share_not_to_be_used;
+ memcpy((table->s->table_cache_key= (char*) (table+1)), key, key_length);
+ table->s->db= table->s->table_cache_key;
+ table->s->key_length=key_length;
table->in_use=thd;
table->locked_by_name=1;
table_list->table=table;
@@ -594,11 +639,9 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
DBUG_RETURN(-1);
}
- if (remove_table_from_cache(thd, db, table_list->real_name, RTFC_NO_FLAG))
- {
- DBUG_RETURN(1); // Table is in use
- }
- DBUG_RETURN(0);
+ /* Return 1 if table is in use */
+ DBUG_RETURN(test(remove_table_from_cache(thd, db, table_list->table_name,
+ RTFC_NO_FLAG)));
}
@@ -614,7 +657,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list)
static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
{
- for (; table_list ; table_list=table_list->next)
+ for (; table_list ; table_list=table_list->next_local)
{
if (table_list->table && table_is_used(table_list->table,0))
return 1;
@@ -668,7 +711,7 @@ bool lock_table_names(THD *thd, TABLE_LIST *table_list)
bool got_all_locks=1;
TABLE_LIST *lock_table;
- for (lock_table=table_list ; lock_table ; lock_table=lock_table->next)
+ for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
{
int got_lock;
if ((got_lock=lock_table_name(thd,lock_table)) < 0)
@@ -711,13 +754,15 @@ end:
void unlock_table_names(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *last_table)
{
- for (TABLE_LIST *table=table_list ; table != last_table ; table=table->next)
+ for (TABLE_LIST *table= table_list;
+ table != last_table;
+ table= table->next_local)
unlock_table_name(thd,table);
pthread_cond_broadcast(&COND_refresh);
}
-static void print_lock_error(int error)
+static void print_lock_error(int error, const char *table)
{
int textno;
DBUG_ENTER("print_lock_error");
@@ -729,11 +774,22 @@ static void print_lock_error(int error)
case HA_ERR_READ_ONLY_TRANSACTION:
textno=ER_READ_ONLY_TRANSACTION;
break;
+ case HA_ERR_LOCK_DEADLOCK:
+ textno=ER_LOCK_DEADLOCK;
+ break;
+ case HA_ERR_WRONG_COMMAND:
+ textno=ER_ILLEGAL_HA;
+ break;
default:
textno=ER_CANT_LOCK;
break;
}
- my_error(textno,MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG),error);
+
+ if ( textno == ER_ILLEGAL_HA )
+ my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), table);
+ else
+ my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), error);
+
DBUG_VOID_RETURN;
}
@@ -757,6 +813,13 @@ static void print_lock_error(int error)
protect_against_global_read_lock
count of threads which have set protection against global read lock.
+ access to them is protected with a mutex LOCK_global_read_lock
+
+ (XXX: one should never take LOCK_open if LOCK_global_read_lock is taken,
+ otherwise a deadlock may occur - see mysql_rm_table. Other mutexes could
+ be a problem too - grep the code for global_read_lock if you want to use
+ any other mutex here)
+
How blocking of threads by global read lock is achieved: that's
advisory. Any piece of code which should be blocked by global read lock must
be designed like this:
@@ -794,17 +857,13 @@ static void print_lock_error(int error)
table instance of thd2
thd1: COMMIT; # blocked by thd3.
thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
-
+
Note that we need to support that one thread does
FLUSH TABLES WITH READ LOCK; and then COMMIT;
(that's what innobackup does, for some good reason).
So in this exceptional case the COMMIT should not be blocked by the FLUSH
TABLES WITH READ LOCK.
- TODO in MySQL 5.x: make_global_read_lock_block_commit() should be
- killable. Normally CPU does not spend a long time in this function (COMMITs
- are quite fast), but it would still be nice.
-
****************************************************************************/
volatile uint global_read_lock=0;
@@ -821,8 +880,8 @@ bool lock_global_read_lock(THD *thd)
if (!thd->global_read_lock)
{
- (void) pthread_mutex_lock(&LOCK_open);
- const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
+ (void) pthread_mutex_lock(&LOCK_global_read_lock);
+ const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_global_read_lock,
"Waiting to get readlock");
DBUG_PRINT("info",
("waiting_for: %d protect_against: %d",
@@ -830,7 +889,7 @@ bool lock_global_read_lock(THD *thd)
waiting_for_read_lock++;
while (protect_against_global_read_lock && !thd->killed)
- pthread_cond_wait(&COND_refresh, &LOCK_open);
+ pthread_cond_wait(&COND_refresh, &LOCK_global_read_lock);
waiting_for_read_lock--;
if (thd->killed)
{
@@ -839,7 +898,7 @@ bool lock_global_read_lock(THD *thd)
}
thd->global_read_lock= GOT_GLOBAL_READ_LOCK;
global_read_lock++;
- thd->exit_cond(old_message);
+ thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
}
/*
We DON'T set global_read_lock_blocks_commit now, it will be set after
@@ -855,11 +914,11 @@ bool lock_global_read_lock(THD *thd)
void unlock_global_read_lock(THD *thd)
{
uint tmp;
- pthread_mutex_lock(&LOCK_open);
+ pthread_mutex_lock(&LOCK_global_read_lock);
tmp= --global_read_lock;
if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
--global_read_lock_blocks_commit;
- pthread_mutex_unlock(&LOCK_open);
+ pthread_mutex_unlock(&LOCK_global_read_lock);
/* Send the signal outside the mutex to avoid a context switch */
if (!tmp)
pthread_cond_broadcast(&COND_refresh);
@@ -878,14 +937,15 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
DBUG_ENTER("wait_if_global_read_lock");
LINT_INIT(old_message);
- (void) pthread_mutex_lock(&LOCK_open);
+ (void) pthread_mutex_lock(&LOCK_global_read_lock);
if ((need_exit_cond= must_wait))
{
if (thd->global_read_lock) // This thread had the read locks
{
if (is_not_commit)
- my_error(ER_CANT_UPDATE_WITH_READLOCK,MYF(0));
- (void) pthread_mutex_unlock(&LOCK_open);
+ my_message(ER_CANT_UPDATE_WITH_READLOCK,
+ ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0));
+ (void) pthread_mutex_unlock(&LOCK_global_read_lock);
/*
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
This allowance is needed to not break existing versions of innobackup
@@ -893,11 +953,11 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
*/
DBUG_RETURN(is_not_commit);
}
- old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
+ old_message=thd->enter_cond(&COND_refresh, &LOCK_global_read_lock,
"Waiting for release of readlock");
while (must_wait && ! thd->killed &&
(!abort_on_refresh || thd->version == refresh_version))
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_global_read_lock);
if (thd->killed)
result=1;
}
@@ -907,10 +967,10 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
The following is only true in case of a global read locks (which is rare)
and if old_message is set
*/
- if (unlikely(need_exit_cond))
- thd->exit_cond(old_message);
+ if (unlikely(need_exit_cond))
+ thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
else
- pthread_mutex_unlock(&LOCK_open);
+ pthread_mutex_unlock(&LOCK_global_read_lock);
DBUG_RETURN(result);
}
@@ -921,31 +981,45 @@ void start_waiting_global_read_lock(THD *thd)
DBUG_ENTER("start_waiting_global_read_lock");
if (unlikely(thd->global_read_lock))
DBUG_VOID_RETURN;
- (void) pthread_mutex_lock(&LOCK_open);
+ (void) pthread_mutex_lock(&LOCK_global_read_lock);
tmp= (!--protect_against_global_read_lock &&
(waiting_for_read_lock || global_read_lock_blocks_commit));
- (void) pthread_mutex_unlock(&LOCK_open);
+ (void) pthread_mutex_unlock(&LOCK_global_read_lock);
if (tmp)
pthread_cond_broadcast(&COND_refresh);
DBUG_VOID_RETURN;
}
-void make_global_read_lock_block_commit(THD *thd)
+bool make_global_read_lock_block_commit(THD *thd)
{
+ bool error;
+ const char *old_message;
+ DBUG_ENTER("make_global_read_lock_block_commit");
/*
If we didn't succeed lock_global_read_lock(), or if we already suceeded
make_global_read_lock_block_commit(), do nothing.
*/
if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
- return;
- pthread_mutex_lock(&LOCK_open);
+ DBUG_RETURN(0);
+ pthread_mutex_lock(&LOCK_global_read_lock);
/* increment this BEFORE waiting on cond (otherwise race cond) */
global_read_lock_blocks_commit++;
- while (protect_against_global_read_lock)
- pthread_cond_wait(&COND_refresh, &LOCK_open);
- pthread_mutex_unlock(&LOCK_open);
- thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
+ /* For testing we set up some blocking, to see if we can be killed */
+ DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
+ protect_against_global_read_lock++;);
+ old_message= thd->enter_cond(&COND_refresh, &LOCK_global_read_lock,
+ "Waiting for all running commits to finish");
+ while (protect_against_global_read_lock && !thd->killed)
+ pthread_cond_wait(&COND_refresh, &LOCK_global_read_lock);
+ DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
+ protect_against_global_read_lock--;);
+ if ((error= test(thd->killed)))
+ global_read_lock_blocks_commit--; // undo what we did
+ else
+ thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
+ thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
+ DBUG_RETURN(error);
}
diff --git a/sql/log.cc b/sql/log.cc
index a67f35e30bf..920a3fcff42 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -24,7 +24,6 @@
#include "mysql_priv.h"
#include "sql_repl.h"
-#include "ha_innodb.h" // necessary to cut the binlog when crash recovery
#include <my_dir.h>
#include <stdarg.h>
@@ -34,28 +33,254 @@
#include "message.h"
#endif
-MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
+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);
+static int binlog_close_connection(THD *thd);
+static int binlog_savepoint_set(THD *thd, void *sv);
+static int binlog_savepoint_rollback(THD *thd, void *sv);
+static int binlog_commit(THD *thd, bool all);
+static int binlog_rollback(THD *thd, bool all);
+static int binlog_prepare(THD *thd, bool all);
+
+static handlerton binlog_hton = {
+ "binlog",
+ 0,
+ sizeof(my_off_t), /* savepoint size = binlog offset */
+ binlog_close_connection,
+ binlog_savepoint_set,
+ binlog_savepoint_rollback,
+ NULL, /* savepoint_release */
+ binlog_commit,
+ binlog_rollback,
+ binlog_prepare,
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
+/*
+ this function is mostly a placeholder.
+ conceptually, binlog initialization (now mostly done in MYSQL_LOG::open)
+ should be moved here.
+*/
+
+handlerton *binlog_init()
+{
+ return &binlog_hton;
+}
+
+static int binlog_close_connection(THD *thd)
+{
+ IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
+ DBUG_ASSERT(mysql_bin_log.is_open() && !my_b_tell(trans_log));
+ close_cached_file(trans_log);
+ my_free((gptr)trans_log, MYF(0));
+ return 0;
+}
+
+static int binlog_end_trans(THD *thd, IO_CACHE *trans_log, Log_event *end_ev)
+{
+ int error=0;
+ DBUG_ENTER("binlog_end_trans");
+ if (end_ev)
+ error= mysql_bin_log.write(thd, trans_log, end_ev);
+
+ statistic_increment(binlog_cache_use, &LOCK_status);
+ if (trans_log->disk_writes != 0)
+ {
+ statistic_increment(binlog_cache_disk_use, &LOCK_status);
+ trans_log->disk_writes= 0;
+ }
+ reinit_io_cache(trans_log, WRITE_CACHE, (my_off_t) 0, 0, 1); // cannot fail
+ trans_log->end_of_file= max_binlog_cache_size;
+ DBUG_RETURN(error);
+}
+
+static int binlog_prepare(THD *thd, bool all)
+{
+ /*
+ do nothing.
+ just pretend we can do 2pc, so that MySQL won't
+ switch to 1pc.
+ real work will be done in MYSQL_LOG::log()
+ */
+ return 0;
+}
+
+static int binlog_commit(THD *thd, bool all)
+{
+ IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
+ DBUG_ENTER("binlog_commit");
+ DBUG_ASSERT(mysql_bin_log.is_open() &&
+ (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))));
+
+ if (!my_b_tell(trans_log))
+ {
+ // we're here because trans_log was flushed in MYSQL_LOG::log()
+ DBUG_RETURN(0);
+ }
+ Query_log_event qev(thd, "COMMIT", 6, TRUE, FALSE);
+ DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev));
+}
+
+static int binlog_rollback(THD *thd, bool all)
+{
+ int error=0;
+ IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
+ DBUG_ENTER("binlog_rollback");
+ /*
+ First assert is guaranteed - see trans_register_ha() call below.
+ The second must be true. If it is not, we're registering
+ unnecessary, doing extra work. The cause should be found and eliminated
+ */
+ DBUG_ASSERT(all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
+ DBUG_ASSERT(mysql_bin_log.is_open() && my_b_tell(trans_log));
+ /*
+ 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...)
+ */
+ if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
+ {
+ Query_log_event qev(thd, "ROLLBACK", 8, TRUE, FALSE);
+ error= binlog_end_trans(thd, trans_log, &qev);
+ }
+ else
+ error= binlog_end_trans(thd, trans_log, 0);
+ DBUG_RETURN(error);
+}
+
+/*
+ NOTE: how do we handle this (unlikely but legal) case:
+ [transaction] + [update to non-trans table] + [rollback to savepoint] ?
+ The problem occurs when a savepoint is before the update to the
+ non-transactional table. Then when there's a rollback to the savepoint, if we
+ 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.
+ 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
+ will chop the SAVEPOINT command from the binlog cache, which is good as in
+ that case there is no need to have it in the binlog).
+*/
+
+static int binlog_savepoint_set(THD *thd, void *sv)
+{
+ IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
+ DBUG_ENTER("binlog_savepoint_set");
+ DBUG_ASSERT(mysql_bin_log.is_open() && my_b_tell(trans_log));
+
+ *(my_off_t *)sv= my_b_tell(trans_log);
+ /* Write it to the binary log */
+ Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
+ DBUG_RETURN(mysql_bin_log.write(&qinfo));
+}
+
+static int binlog_savepoint_rollback(THD *thd, void *sv)
+{
+ IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
+ DBUG_ENTER("binlog_savepoint_rollback");
+ DBUG_ASSERT(mysql_bin_log.is_open() && my_b_tell(trans_log));
+
+ /*
+ Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some
+ non-transactional table. Otherwise, truncate the binlog cache starting
+ from the SAVEPOINT command.
+ */
+ if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
+ DBUG_RETURN(mysql_bin_log.write(&qinfo));
+ }
+ reinit_io_cache(trans_log, WRITE_CACHE, *(my_off_t *)sv, 0, 0);
+ DBUG_RETURN(0);
+}
+
+int check_binlog_magic(IO_CACHE* log, const char** errmsg)
+{
+ char magic[4];
+ DBUG_ASSERT(my_b_tell(log) == 0);
+
+ if (my_b_read(log, (byte*) magic, sizeof(magic)))
+ {
+ *errmsg = "I/O error reading the header from the binary log";
+ sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
+ log->error);
+ return 1;
+ }
+ if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
+ {
+ *errmsg = "Binlog has bad magic number; It's not a binary log file that can be used by this version of MySQL";
+ return 1;
+ }
+ return 0;
+}
+
+File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg)
+{
+ File file;
+ DBUG_ENTER("open_binlog");
+
+ if ((file = my_open(log_file_name, O_RDONLY | O_BINARY | O_SHARE,
+ MYF(MY_WME))) < 0)
+ {
+ sql_print_error("Failed to open log (file '%s', errno %d)",
+ log_file_name, my_errno);
+ *errmsg = "Could not open log file";
+ goto err;
+ }
+ if (init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
+ MYF(MY_WME|MY_DONT_CHECK_FILESIZE)))
+ {
+ sql_print_error("Failed to create a cache on log (file '%s')",
+ log_file_name);
+ *errmsg = "Could not open log file";
+ goto err;
+ }
+ if (check_binlog_magic(log,errmsg))
+ goto err;
+ DBUG_RETURN(file);
+
+err:
+ if (file >= 0)
+ {
+ my_close(file,MYF(0));
+ end_io_cache(log);
+ }
+ DBUG_RETURN(-1);
+}
#ifdef __NT__
static int eventSource = 0;
-void setup_windows_event_source()
+void setup_windows_event_source()
{
- HKEY hRegKey= NULL;
+ HKEY hRegKey= NULL;
DWORD dwError= 0;
TCHAR szPath[MAX_PATH];
DWORD dwTypes;
-
+
if (eventSource) // Ensure that we are only called once
return;
eventSource= 1;
// Create the event source registry key
- dwError= RegCreateKey(HKEY_LOCAL_MACHINE,
+ dwError= RegCreateKey(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\MySQL",
&hRegKey);
@@ -63,9 +288,8 @@ void setup_windows_event_source()
GetModuleFileName(NULL, szPath, MAX_PATH);
/* Register EventMessageFile */
- dwError = RegSetValueEx(hRegKey, "EventMessageFile", 0, REG_EXPAND_SZ,
+ dwError = RegSetValueEx(hRegKey, "EventMessageFile", 0, REG_EXPAND_SZ,
(PBYTE) szPath, strlen(szPath)+1);
-
/* Register supported event types */
dwTypes= (EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
@@ -128,25 +352,20 @@ static int find_uniq_filename(char *name)
MYSQL_LOG::MYSQL_LOG()
:bytes_written(0), last_time(0), query_start(0), name(0),
file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0),
- need_start_event(1)
+ need_start_event(1), prepared_xids(0), description_event_for_exec(0),
+ description_event_for_queue(0)
{
/*
We don't want to initialize LOCK_Log here as such initialization depends on
safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is
called only in main(). Doing initialization here would make it happen
- before main().
+ before main().
*/
index_file_name[0] = 0;
bzero((char*) &log_file,sizeof(log_file));
bzero((char*) &index_file, sizeof(index_file));
}
-
-MYSQL_LOG::~MYSQL_LOG()
-{
- cleanup();
-}
-
/* this is called only once */
void MYSQL_LOG::cleanup()
@@ -155,7 +374,9 @@ void MYSQL_LOG::cleanup()
if (inited)
{
inited= 0;
- close(LOG_CLOSE_INDEX);
+ close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT);
+ delete description_event_for_queue;
+ delete description_event_for_exec;
(void) pthread_mutex_destroy(&LOCK_log);
(void) pthread_mutex_destroy(&LOCK_index);
(void) pthread_cond_destroy(&update_cond);
@@ -165,7 +386,7 @@ void MYSQL_LOG::cleanup()
int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
-{
+{
fn_format(new_name,log_name,mysql_data_home,"",4);
if (log_type != LOG_NORMAL)
{
@@ -206,6 +427,66 @@ void MYSQL_LOG::init_pthread_objects()
(void) pthread_cond_init(&update_cond, 0);
}
+const char *MYSQL_LOG::generate_name(const char *log_name,
+ const char *suffix,
+ bool strip_ext, char *buff)
+{
+ if (!log_name || !log_name[0])
+ {
+ /*
+ TODO: The following should be using fn_format(); We just need to
+ first change fn_format() to cut the file name if it's too long.
+ */
+ strmake(buff,glob_hostname,FN_REFLEN-5);
+ strmov(fn_ext(buff),suffix);
+ return (const char *)buff;
+ }
+ // get rid of extension if the log is binary to avoid problems
+ if (strip_ext)
+ {
+ char *p = fn_ext(log_name);
+ uint length=(uint) (p-log_name);
+ strmake(buff,log_name,min(length,FN_REFLEN));
+ return (const char*)buff;
+ }
+ return log_name;
+}
+
+bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
+ const char *log_name)
+{
+ File index_file_nr= -1;
+ DBUG_ASSERT(!my_b_inited(&index_file));
+
+ /*
+ First open of this class instance
+ Create an index file that will hold all file names uses for logging.
+ Add new entries to the end of it.
+ */
+ myf opt= MY_UNPACK_FILENAME;
+ if (!index_file_name_arg)
+ {
+ index_file_name_arg= log_name; // Use same basename for index file
+ opt= MY_UNPACK_FILENAME | MY_REPLACE_EXT;
+ }
+ fn_format(index_file_name, index_file_name_arg, mysql_data_home,
+ ".index", opt);
+ 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)),
+ 0, MYF(MY_WME | MY_WAIT_IF_FULL)))
+ {
+ if (index_file_nr >= 0)
+ my_close(index_file_nr,MYF(0));
+ return TRUE;
+ }
+ return FALSE;
+}
+
/*
Open a (new) log file.
@@ -221,34 +502,39 @@ void MYSQL_LOG::init_pthread_objects()
1 error
*/
-bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
- const char *new_name, const char *index_file_name_arg,
- enum cache_type io_cache_type_arg,
- bool no_auto_events_arg,
- ulong max_size_arg)
+bool MYSQL_LOG::open(const char *log_name,
+ enum_log_type log_type_arg,
+ const char *new_name,
+ enum cache_type io_cache_type_arg,
+ bool no_auto_events_arg,
+ ulong max_size_arg,
+ bool null_created_arg)
{
- char buff[512];
- File file= -1, index_file_nr= -1;
- int open_flags = O_CREAT | O_APPEND | O_BINARY;
+ char buff[FN_REFLEN];
+ File file= -1;
+ int open_flags = O_CREAT | O_BINARY;
DBUG_ENTER("MYSQL_LOG::open");
- DBUG_PRINT("enter",("log_type: %d",(int) log_type));
+ DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg));
last_time=query_start=0;
write_error=0;
init(log_type_arg,io_cache_type_arg,no_auto_events_arg,max_size_arg);
-
+
if (!(name=my_strdup(log_name,MYF(MY_WME))))
+ {
+ name= (char *)log_name; // for the error message
goto err;
+ }
if (new_name)
strmov(log_file_name,new_name);
else if (generate_new_name(log_file_name, name))
goto err;
-
+
if (io_cache_type == SEQ_READ_APPEND)
- open_flags |= O_RDWR;
+ open_flags |= O_RDWR | O_APPEND;
else
- open_flags |= O_WRONLY;
+ open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
db[0]=0;
open_count++;
@@ -307,13 +593,6 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
{
bool write_file_name_to_index_file=0;
- myf opt= MY_UNPACK_FILENAME;
- if (!index_file_name_arg)
- {
- index_file_name_arg= name; // Use same basename for index file
- opt= MY_UNPACK_FILENAME | MY_REPLACE_EXT;
- }
-
if (!my_b_filelength(&log_file))
{
/*
@@ -325,43 +604,64 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
if (my_b_safe_write(&log_file, (byte*) BINLOG_MAGIC,
BIN_LOG_HEADER_SIZE))
goto err;
- bytes_written += BIN_LOG_HEADER_SIZE;
- write_file_name_to_index_file=1;
+ bytes_written+= BIN_LOG_HEADER_SIZE;
+ write_file_name_to_index_file= 1;
}
- if (!my_b_inited(&index_file))
+ DBUG_ASSERT(my_b_inited(&index_file) != 0);
+ reinit_io_cache(&index_file, WRITE_CACHE,
+ my_b_filelength(&index_file), 0, 0);
+ if (need_start_event && !no_auto_events)
{
/*
- First open of this class instance
- Create an index file that will hold all file names uses for logging.
- Add new entries to the end of it.
- Index file (and binlog) are so critical for recovery/replication
- that we create them with MY_WAIT_IF_FULL.
+ In 4.x we set need_start_event=0 here, but in 5.0 we want a Start event
+ even if this is not the very first binlog.
*/
- fn_format(index_file_name, index_file_name_arg, mysql_data_home,
- ".index", opt);
- 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)),
- 0, MYF(MY_WME | MY_WAIT_IF_FULL)))
- goto err;
- }
- else
- {
- safe_mutex_assert_owner(&LOCK_index);
- reinit_io_cache(&index_file, WRITE_CACHE, my_b_filelength(&index_file),
- 0, 0);
+ Format_description_log_event s(BINLOG_VERSION);
+ /*
+ don't set LOG_EVENT_BINLOG_IN_USE_F for SEQ_READ_APPEND io_cache
+ as we won't be able to reset it later
+ */
+ if (io_cache_type == WRITE_CACHE)
+ s.flags|= LOG_EVENT_BINLOG_IN_USE_F;
+ if (!s.is_valid())
+ goto err;
+ if (null_created_arg)
+ s.created= 0;
+ if (s.write(&log_file))
+ goto err;
+ bytes_written+= s.data_written;
}
- if (need_start_event && !no_auto_events)
+ if (description_event_for_queue &&
+ description_event_for_queue->binlog_version>=4)
{
- need_start_event=0;
- Start_log_event s;
- s.set_log_pos(this);
- s.write(&log_file);
+ /*
+ This is a relay log written to by the I/O slave thread.
+ Write the event so that others can later know the format of this relay
+ log.
+ Note that this event is very close to the original event from the
+ master (it has binlog version of the master, event types of the
+ master), so this is suitable to parse the next relay log's event. It
+ has been produced by
+ Format_description_log_event::Format_description_log_event(char* buf,).
+ Why don't we want to write the description_event_for_queue if this
+ event is for format<4 (3.23 or 4.x): this is because in that case, the
+ description_event_for_queue describes the data received from the
+ master, but not the data written to the relay log (*conversion*),
+ which is in format 4 (slave's).
+ */
+ /*
+ Set 'created' to 0, so that in next relay logs this event does not
+ trigger cleaning actions on the slave in
+ Format_description_log_event::exec_event().
+ */
+ description_event_for_queue->created= 0;
+ /* Don't set log_pos in event header */
+ description_event_for_queue->artificial_event=1;
+
+ if (description_event_for_queue->write(&log_file))
+ goto err;
+ bytes_written+= description_event_for_queue->data_written;
}
if (flush_io_cache(&log_file) ||
my_sync(log_file.file, MYF(MY_WME)))
@@ -393,11 +693,9 @@ err:
sql_print_error("Could not use %s for logging (error %d). \
Turning logging off for the whole duration of the MySQL server process. \
To turn it on again: fix the cause, \
-shutdown the MySQL server and restart it.", log_name, errno);
+shutdown the MySQL server and restart it.", name, errno);
if (file >= 0)
my_close(file,MYF(0));
- if (index_file_nr >= 0)
- my_close(index_file_nr,MYF(0));
end_io_cache(&log_file);
end_io_cache(&index_file);
safeFree(name);
@@ -503,8 +801,8 @@ int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
DBUG_PRINT("enter",("log_name: %s", log_name ? log_name : "NULL"));
/*
- Mutex needed because we need to make sure the file pointer does not move
- from under our feet
+ Mutex needed because we need to make sure the file pointer does not
+ move from under our feet
*/
if (need_lock)
pthread_mutex_lock(&LOCK_index);
@@ -587,7 +885,7 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
error = !index_file.error ? LOG_INFO_EOF : LOG_INFO_IO;
goto err;
}
- fname[length-1]=0; // kill /n
+ fname[length-1]=0; // kill \n
linfo->index_file_offset = my_b_tell(&index_file);
err:
@@ -629,6 +927,13 @@ bool MYSQL_LOG::reset_logs(THD* thd)
*/
pthread_mutex_lock(&LOCK_log);
pthread_mutex_lock(&LOCK_index);
+ /*
+ The following mutex is needed to ensure that no threads call
+ 'delete thd' as we would then risk missing a 'rollback' from this
+ thread. If the transaction involved MyISAM tables, it should go
+ into binlog even on rollback.
+ */
+ (void) pthread_mutex_lock(&LOCK_thread_count);
/* Save variables so that we can reopen the log */
save_name=name;
@@ -643,7 +948,7 @@ bool MYSQL_LOG::reset_logs(THD* thd)
error=1;
goto err;
}
-
+
for (;;)
{
my_delete(linfo.log_file_name, MYF(MY_WME));
@@ -656,11 +961,13 @@ bool MYSQL_LOG::reset_logs(THD* thd)
my_delete(index_file_name, MYF(MY_WME)); // Reset (open will update)
if (!thd->slave_thread)
need_start_event=1;
- open(save_name, save_log_type, 0, index_file_name,
- io_cache_type, no_auto_events, max_size);
+ if (!open_index_file(index_file_name, 0))
+ open(save_name, save_log_type, 0,
+ io_cache_type, no_auto_events, max_size, 0);
my_free((gptr) save_name, MYF(0));
-err:
+err:
+ (void) pthread_mutex_unlock(&LOCK_thread_count);
pthread_mutex_unlock(&LOCK_index);
pthread_mutex_unlock(&LOCK_log);
DBUG_RETURN(error);
@@ -679,7 +986,7 @@ err:
rli->group_relay_log_name are deleted ; if true, the latter is
deleted too (i.e. all relay logs
read by the SQL slave thread are deleted).
-
+
NOTE
- This is only called from the slave-execute thread when it has read
all commands from a relay log and want to switch to a new relay log.
@@ -839,24 +1146,21 @@ int MYSQL_LOG::purge_logs(const char *to_log,
while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&
!log_in_use(log_info.log_file_name))
{
- ulong tmp;
- LINT_INIT(tmp);
+ ulong file_size= 0;
if (decrease_log_space) //stat the file we want to delete
{
MY_STAT s;
+
+ /*
+ If we could not stat, we can't know the amount
+ of space that deletion will free. In most cases,
+ deletion won't work either, so it's not a problem.
+ */
if (my_stat(log_info.log_file_name,&s,MYF(0)))
- tmp= s.st_size;
+ file_size= s.st_size;
else
- {
- /*
- If we could not stat, we can't know the amount
- of space that deletion will free. In most cases,
- deletion won't work either, so it's not a problem.
- */
sql_print_information("Failed to execute my_stat on file '%s'",
log_info.log_file_name);
- tmp= 0;
- }
}
/*
It's not fatal if we can't delete a log file ;
@@ -864,7 +1168,7 @@ int MYSQL_LOG::purge_logs(const char *to_log,
*/
DBUG_PRINT("info",("purging %s",log_info.log_file_name));
if (!my_delete(log_info.log_file_name, MYF(0)) && decrease_log_space)
- *decrease_log_space-= tmp;
+ *decrease_log_space-= file_size;
if (find_next_log(&log_info, 0) || exit_loop)
break;
}
@@ -980,8 +1284,7 @@ bool MYSQL_LOG::is_active(const char *log_file_name_arg)
SYNOPSIS
new_file()
- need_lock Set to 1 (default) if caller has not locked
- LOCK_log and LOCK_index
+ need_lock Set to 1 if caller has not locked LOCK_log
NOTE
The new file name is stored last in the index file
@@ -1000,13 +1303,30 @@ void MYSQL_LOG::new_file(bool need_lock)
}
if (need_lock)
- {
pthread_mutex_lock(&LOCK_log);
- pthread_mutex_lock(&LOCK_index);
- }
+ pthread_mutex_lock(&LOCK_index);
+
safe_mutex_assert_owner(&LOCK_log);
safe_mutex_assert_owner(&LOCK_index);
+ /*
+ if binlog is used as tc log, be sure all xids are "unlogged",
+ so that on recover we only need to scan one - latest - binlog file
+ for prepared xids. As this is expected to be a rare event,
+ simple wait strategy is enough. We're locking LOCK_log to be sure no
+ new Xid_log_event's are added to the log (and prepared_xids is not
+ increased), and waiting on COND_prep_xids for late threads to
+ catch up.
+ */
+ if (prepared_xids)
+ {
+ tc_log_page_waits++;
+ pthread_mutex_lock(&LOCK_prep_xids);
+ while (prepared_xids)
+ pthread_cond_wait(&COND_prep_xids, &LOCK_prep_xids);
+ pthread_mutex_unlock(&LOCK_prep_xids);
+ }
+
/* Reuse old name if not binlog and not update log */
new_name_ptr= name;
@@ -1018,7 +1338,7 @@ void MYSQL_LOG::new_file(bool need_lock)
if (generate_new_name(new_name, name))
goto end;
new_name_ptr=new_name;
-
+
if (log_type == LOG_BIN)
{
if (!no_auto_events)
@@ -1029,38 +1349,43 @@ void MYSQL_LOG::new_file(bool need_lock)
*/
THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */
Rotate_log_event r(thd,new_name+dirname_length(new_name));
- r.set_log_pos(this);
r.write(&log_file);
- bytes_written += r.get_event_len();
+ bytes_written += r.data_written;
}
/*
Update needs to be signalled even if there is no rotate event
log rotation should give the waiting thread a signal to
discover EOF and move on to the next log.
*/
- signal_update();
+ signal_update();
}
old_name=name;
save_log_type=log_type;
name=0; // Don't free name
close(LOG_CLOSE_TO_BE_OPENED);
- /*
+ /*
Note that at this point, log_type != LOG_CLOSED (important for is_open()).
*/
- open(old_name, save_log_type, new_name_ptr, index_file_name, io_cache_type,
- no_auto_events, max_size);
- if (this == &mysql_bin_log)
- report_pos_in_innodb();
+ /*
+ new_file() is only used for rotation (in FLUSH LOGS or because size >
+ max_binlog_size or max_relay_log_size).
+ If this is a binary log, the Format_description_log_event at the beginning of
+ the new file should have created=0 (to distinguish with the
+ Format_description_log_event written at server startup, which should
+ trigger temp tables deletion on slaves.
+ */
+
+ open(old_name, save_log_type, new_name_ptr,
+ io_cache_type, no_auto_events, max_size, 1);
my_free(old_name,MYF(0));
end:
if (need_lock)
- {
- pthread_mutex_unlock(&LOCK_index);
pthread_mutex_unlock(&LOCK_log);
- }
+ pthread_mutex_unlock(&LOCK_index);
+
DBUG_VOID_RETURN;
}
@@ -1081,16 +1406,12 @@ bool MYSQL_LOG::append(Log_event* ev)
error=1;
goto err;
}
- bytes_written += ev->get_event_len();
+ bytes_written+= ev->data_written;
DBUG_PRINT("info",("max_size: %lu",max_size));
if ((uint) my_b_append_tell(&log_file) > max_size)
- {
- pthread_mutex_lock(&LOCK_index);
new_file(0);
- pthread_mutex_unlock(&LOCK_index);
- }
-err:
+err:
pthread_mutex_unlock(&LOCK_log);
signal_update(); // Safe as we don't call close
DBUG_RETURN(error);
@@ -1103,9 +1424,9 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
DBUG_ENTER("MYSQL_LOG::appendv");
va_list(args);
va_start(args,len);
-
+
DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
-
+
pthread_mutex_lock(&LOCK_log);
do
{
@@ -1118,11 +1439,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
} while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
DBUG_PRINT("info",("max_size: %lu",max_size));
if ((uint) my_b_append_tell(&log_file) > max_size)
- {
- pthread_mutex_lock(&LOCK_index);
new_file(0);
- pthread_mutex_unlock(&LOCK_index);
- }
err:
pthread_mutex_unlock(&LOCK_log);
@@ -1134,7 +1451,7 @@ err:
/*
Write to normal (not rotable) log
- This is the format for the 'normal', 'slow' and 'update' logs.
+ This is the format for the 'normal' log.
*/
bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
@@ -1222,55 +1539,75 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
return 0;
}
+bool MYSQL_LOG::flush_and_sync()
+{
+ int err=0, fd=log_file.file;
+ safe_mutex_assert_owner(&LOCK_log);
+ if (flush_io_cache(&log_file))
+ return 1;
+ if (++sync_binlog_counter >= sync_binlog_period && sync_binlog_period)
+ {
+ sync_binlog_counter= 0;
+ err=my_sync(fd, MYF(MY_WME));
+ }
+ return err;
+}
+
+void MYSQL_LOG::start_union_events(THD *thd)
+{
+ DBUG_ASSERT(!thd->binlog_evt_union.do_union);
+ thd->binlog_evt_union.do_union= TRUE;
+ thd->binlog_evt_union.unioned_events= FALSE;
+ thd->binlog_evt_union.unioned_events_trans= FALSE;
+ thd->binlog_evt_union.first_query_id= thd->query_id;
+}
-inline bool sync_binlog(IO_CACHE *cache)
+void MYSQL_LOG::stop_union_events(THD *thd)
{
- return (sync_binlog_period &&
- (sync_binlog_period == ++sync_binlog_counter) &&
- (sync_binlog_counter= 0, my_sync(cache->file, MYF(MY_WME))));
+ DBUG_ASSERT(thd->binlog_evt_union.do_union);
+ thd->binlog_evt_union.do_union= FALSE;
+}
+
+bool MYSQL_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
+{
+ return (thd->binlog_evt_union.do_union &&
+ query_id_param >= thd->binlog_evt_union.first_query_id);
}
/*
Write an event to the binary log
*/
-bool MYSQL_LOG::write(Log_event* event_info)
+bool MYSQL_LOG::write(Log_event *event_info)
{
- THD *thd=event_info->thd;
- bool called_handler_commit=0;
- bool error=0;
- bool should_rotate = 0;
- DBUG_ENTER("MYSQL_LOG::write(event)");
+ THD *thd= event_info->thd;
+ bool error= 1;
+ DBUG_ENTER("MYSQL_LOG::write(Log_event *)");
+
+ if (thd->binlog_evt_union.do_union)
+ {
+ /*
+ In Stored function; Remember that function call caused an update.
+ We will log the function call to the binary log on function exit
+ */
+ thd->binlog_evt_union.unioned_events= TRUE;
+ thd->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt;
+ DBUG_RETURN(0);
+ }
pthread_mutex_lock(&LOCK_log);
- /*
+ /*
In most cases this is only called if 'is_open()' is true; in fact this is
mostly called if is_open() *was* true a few instructions before, but it
could have changed since.
*/
- if (is_open())
+ if (likely(is_open()))
{
const char *local_db= event_info->get_db();
IO_CACHE *file= &log_file;
-#ifdef USING_TRANSACTIONS
- /*
- Should we write to the binlog cache or to the binlog on disk?
- Write to the binlog cache if:
- - it is already not empty (meaning we're in a transaction; note that the
- present event could be about a non-transactional table, but still we need
- to write to the binlog cache in that case to handle updates to mixed
- trans/non-trans table types the best possible in binlogging)
- - or if the event asks for it (cache_stmt == true).
- */
- if (opt_using_transactions &&
- (event_info->get_cache_stmt() ||
- (thd && my_b_tell(&thd->transaction.trans_log))))
- file= &thd->transaction.trans_log;
-#endif
- DBUG_PRINT("info",("event type=%d",event_info->get_type_code()));
#ifdef HAVE_REPLICATION
- /*
+ /*
In the future we need to add to the following if tests like
"do the involved tables match (to be implemented)
binlog_[wild_]{do|ignore}_table?" (WL#1049)"
@@ -1284,88 +1621,81 @@ bool MYSQL_LOG::write(Log_event* event_info)
}
#endif /* HAVE_REPLICATION */
- error=1;
+#ifdef USING_TRANSACTIONS
+ /*
+ Should we write to the binlog cache or to the binlog on disk?
+ Write to the binlog cache if:
+ - it is already not empty (meaning we're in a transaction; note that the
+ present event could be about a non-transactional table, but still we need
+ to write to the binlog cache in that case to handle updates to mixed
+ trans/non-trans table types the best possible in binlogging)
+ - or if the event asks for it (cache_stmt == TRUE).
+ */
+ if (opt_using_transactions && thd)
+ {
+ IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
+
+ if (event_info->get_cache_stmt())
+ {
+ if (!trans_log)
+ {
+ thd->ha_data[binlog_hton.slot]= trans_log= (IO_CACHE *)
+ my_malloc(sizeof(IO_CACHE), MYF(MY_ZEROFILL));
+ if (!trans_log || open_cached_file(trans_log, mysql_tmpdir,
+ LOG_PREFIX,
+ binlog_cache_size, MYF(MY_WME)))
+ {
+ my_free((gptr)trans_log, MYF(MY_ALLOW_ZERO_PTR));
+ thd->ha_data[binlog_hton.slot]= trans_log= 0;
+ goto err;
+ }
+ trans_log->end_of_file= max_binlog_cache_size;
+ trans_register_ha(thd,
+ thd->options & (OPTION_NOT_AUTOCOMMIT |
+ OPTION_BEGIN),
+ &binlog_hton);
+ }
+ else if (!my_b_tell(trans_log))
+ trans_register_ha(thd,
+ thd->options & (OPTION_NOT_AUTOCOMMIT |
+ OPTION_BEGIN),
+ &binlog_hton);
+ file= trans_log;
+ }
+ else if (trans_log && my_b_tell(trans_log))
+ file= trans_log;
+ }
+#endif
+ DBUG_PRINT("info",("event type=%d",event_info->get_type_code()));
+
/*
No check for auto events flag here - this write method should
never be called if auto-events are enabled
*/
/*
- 1. Write first log events which describe the 'run environment'
- of the SQL command
+ 1. Write first log events which describe the 'run environment'
+ of the SQL command
*/
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, FALSE);
- e.set_log_pos(this);
- e.error_code = 0; // This statement cannot fail (see [1]).
- 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, FALSE);
- e.set_log_pos(this);
- e.error_code = 0; // This statement cannot fail (see [1]).
- if (e.write(file))
- goto err;
- }
-#endif
-
if (thd->last_insert_id_used)
{
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
thd->current_insert_id);
- e.set_log_pos(this);
if (e.write(file))
goto err;
}
if (thd->insert_id_used)
{
Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id);
- e.set_log_pos(this);
if (e.write(file))
goto err;
}
if (thd->rand_used)
{
Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2);
- e.set_log_pos(this);
if (e.write(file))
goto err;
}
@@ -1381,139 +1711,25 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
user_var_event->length,
user_var_event->type,
user_var_event->charset_number);
- e.set_log_pos(this);
if (e.write(file))
goto err;
}
}
-#ifdef TO_BE_REMOVED
- if (thd->variables.convert_set)
- {
- char buf[256], *p;
- p= strmov(strmov(buf, "SET CHARACTER SET "),
- thd->variables.convert_set->name);
- Query_log_event e(thd, buf, (ulong) (p - buf), 0);
- e.set_log_pos(this);
- e.error_code = 0; // This statement cannot fail (see [1]).
- if (e.write(file))
- goto err;
- }
-#endif
-
- /*
- If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL
- command in the binlog inside:
- SET FOREIGN_KEY_CHECKS=0;
- <command>;
- SET FOREIGN_KEY_CHECKS=1;
- */
-
- if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
- {
- Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0, FALSE);
- e.set_log_pos(this);
- e.error_code = 0; // This statement cannot fail (see [1]).
- if (e.write(file))
- goto err;
- }
}
- /*
- Write the SQL command
-
- [1] If this statement has an error code, the slave is required to fail
- with the same error code or stop. The preamble and epilogue should
- *not* have this error code since the execution of those is
- guaranteed *not* to produce any error code. This would therefore
- stop the slave even if the execution of the real statement can be
- handled gracefully by the slave.
+ /*
+ Write the SQL command
*/
- event_info->set_log_pos(this);
if (event_info->write(file))
goto err;
- /* Write log events to reset the 'run environment' of the SQL command */
-
- if (thd)
- {
- if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
- {
- Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0, FALSE);
- e.set_log_pos(this);
- e.error_code = 0; // This statement cannot fail (see [1]).
- if (e.write(file))
- goto err;
- }
- }
-
- /*
- Tell for transactional table handlers up to which position in the
- binlog file we wrote. The table handler can store this info, and
- after crash recovery print for the user the offset of the last
- transactions which were recovered. Actually, we must also call
- the table handler commit here, protected by the LOCK_log mutex,
- because otherwise the transactions may end up in a different order
- in the table handler log!
-
- Note that we will NOT call ha_report_binlog_offset_and_commit() if
- there are binlog events cached in the transaction cache. That is
- because then the log event which we write to the binlog here is
- not a transactional event. In versions < 4.0.13 before this fix this
- caused an InnoDB transaction to be committed if in the middle there
- was a MyISAM event!
- */
-
if (file == &log_file) // we are writing to the real log (disk)
{
- if (flush_io_cache(file) || sync_binlog(file))
+ if (flush_and_sync())
goto err;
-
- if (opt_using_transactions &&
- !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
- {
- /*
- LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog
- chunks also before it is successfully completed. We only report
- the binlog write and do the commit inside the transactional table
- handler if the log event type is appropriate.
- */
-
- if (event_info->get_type_code() == QUERY_EVENT ||
- event_info->get_type_code() == EXEC_LOAD_EVENT)
- {
-#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;
- }
- }
- /* We wrote to the real log, check automatic rotation; */
- DBUG_PRINT("info",("max_size: %lu",max_size));
- should_rotate= (my_b_tell(file) >= (my_off_t) max_size);
+ signal_update();
+ rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
}
error=0;
@@ -1521,44 +1737,38 @@ err:
if (error)
{
if (my_errno == EFBIG)
- my_error(ER_TRANS_CACHE_FULL, MYF(0));
+ my_message(ER_TRANS_CACHE_FULL, ER(ER_TRANS_CACHE_FULL), MYF(0));
else
my_error(ER_ERROR_ON_WRITE, MYF(0), name, errno);
write_error=1;
}
- if (file == &log_file)
- signal_update();
- if (should_rotate)
- {
- pthread_mutex_lock(&LOCK_index);
- new_file(0); // inside mutex
- pthread_mutex_unlock(&LOCK_index);
- }
}
pthread_mutex_unlock(&LOCK_log);
+ DBUG_RETURN(error);
+}
- /*
- Flush the transactional handler log file now that we have released
- LOCK_log; the flush is placed here to eliminate the bottleneck on the
- group commit
- */
-
- if (called_handler_commit)
- ha_commit_complete(thd);
-
-#ifdef HAVE_REPLICATION
- if (should_rotate && expire_logs_days)
+void MYSQL_LOG::rotate_and_purge(uint flags)
+{
+ if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
+ pthread_mutex_lock(&LOCK_log);
+ if ((flags & RP_FORCE_ROTATE) ||
+ (my_b_tell(&log_file) >= (my_off_t) max_size))
{
- long purge_time= time(0) - expire_logs_days*24*60*60;
- if (purge_time >= 0)
- error= purge_logs_before_date(purge_time);
- }
+ new_file(0);
+#ifdef HAVE_REPLICATION
+ if (expire_logs_days)
+ {
+ long purge_time= time(0) - expire_logs_days*24*60*60;
+ if (purge_time >= 0)
+ purge_logs_before_date(purge_time);
+ }
#endif
- DBUG_RETURN(error);
+ }
+ if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
+ pthread_mutex_unlock(&LOCK_log);
}
-
uint MYSQL_LOG::next_file_id()
{
uint res;
@@ -1574,10 +1784,8 @@ uint MYSQL_LOG::next_file_id()
SYNOPSIS
write()
- thd
+ thd
cache The cache to copy to the binlog
- commit_or_rollback If true, will write "COMMIT" in the end, if false will
- write "ROLLBACK".
NOTE
- We only come here if there is something in the cache.
@@ -1587,35 +1795,25 @@ uint MYSQL_LOG::next_file_id()
IMPLEMENTATION
- To support transaction over replication, we wrap the transaction
with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log.
- We want to write a BEGIN/ROLLBACK block when a non-transactional table was
- updated in a transaction which was rolled back. This is to ensure that the
- same updates are run on the slave.
+ We want to write a BEGIN/ROLLBACK block when a non-transactional table
+ was updated in a transaction which was rolled back. This is to ensure
+ that the same updates are run on the slave.
*/
-bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
+bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
{
- bool should_rotate= 0, error= 0;
+ DBUG_ENTER("MYSQL_LOG::write(THD *, IO_CACHE *, Log_event *)");
VOID(pthread_mutex_lock(&LOCK_log));
- DBUG_ENTER("MYSQL_LOG::write(cache");
-
- if (is_open()) // Should always be true
+
+ if (likely(is_open())) // Should always be true
{
uint length;
/*
- Add the "BEGIN" and "COMMIT" in the binlog around transactions
- which may contain more than 1 SQL statement. If we run with
- AUTOCOMMIT=1, then MySQL immediately writes each SQL statement to
- the binlog when the statement has been completed. No need to add
- "BEGIN" ... "COMMIT" around such statements. Otherwise, MySQL uses
- thd->transaction.trans_log to cache the SQL statements until the
- explicit commit, and at the commit writes the contents in .trans_log
- to the binlog.
-
- We write the "BEGIN" mark first in the buffer (.trans_log) where we
- store the SQL statements for a transaction. At the transaction commit
- we will add the "COMMIT mark and write the buffer to the binlog.
+ Log "BEGIN" at the beginning of the transaction.
+ which may contain more than 1 SQL statement.
*/
+ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
{
Query_log_event qinfo(thd, "BEGIN", 5, TRUE, FALSE);
/*
@@ -1633,7 +1831,6 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
master's binlog, which would result in wrong positions being shown to
the user, MASTER_POS_WAIT undue waiting etc.
*/
- qinfo.set_log_pos(this);
if (qinfo.write(&log_file))
goto err;
}
@@ -1641,83 +1838,45 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
goto err;
length=my_b_bytes_in_cache(cache);
+ DBUG_EXECUTE_IF("half_binlogged_transaction", length-=100;);
do
{
/* Write data to the binary log file */
if (my_b_write(&log_file, cache->read_pos, length))
goto err;
cache->read_pos=cache->read_end; // Mark buffer used up
+ DBUG_EXECUTE_IF("half_binlogged_transaction", goto DBUG_skip_commit;);
} while ((length=my_b_fill(cache)));
- /*
- We write the command "COMMIT" as the last SQL command in the
- binlog segment cached for this transaction
- */
-
- {
- Query_log_event qinfo(thd,
- commit_or_rollback ? "COMMIT" : "ROLLBACK",
- commit_or_rollback ? 6 : 8,
- TRUE, FALSE);
- qinfo.error_code= 0;
- qinfo.set_log_pos(this);
- if (qinfo.write(&log_file) || flush_io_cache(&log_file) ||
- sync_binlog(&log_file))
- goto err;
- }
+ if (commit_event->write(&log_file))
+ goto err;
+DBUG_skip_commit:
+ if (flush_and_sync())
+ goto err;
+ DBUG_EXECUTE_IF("half_binlogged_transaction", abort(););
if (cache->error) // Error on read
{
sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
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;
signal_update();
- DBUG_PRINT("info",("max_size: %lu",max_size));
- if (should_rotate= (my_b_tell(&log_file) >= (my_off_t) max_size))
- {
- pthread_mutex_lock(&LOCK_index);
- new_file(0); // inside mutex
- pthread_mutex_unlock(&LOCK_index);
- }
-
+ /*
+ if commit_event is Xid_log_event, increase the number of
+ prepared_xids (it's decreasd in ::unlog()). Binlog cannot be rotated
+ if there're prepared xids in it - see the comment in new_file() for
+ an explanation.
+ If the commit_event is not Xid_log_event (then it's a Query_log_event)
+ rotate binlog, if necessary.
+ */
+ if (commit_event->get_type_code() == XID_EVENT)
+ thread_safe_increment(prepared_xids, &LOCK_prep_xids);
+ else
+ rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
}
VOID(pthread_mutex_unlock(&LOCK_log));
- /* Flush the transactional handler log file now that we have released
- LOCK_log; the flush is placed here to eliminate the bottleneck on the
- group commit */
-
- ha_commit_complete(thd);
-
-#ifdef HAVE_REPLICATION
- if (should_rotate && expire_logs_days)
- {
- long purge_time= time(0) - expire_logs_days*24*60*60;
- if (purge_time >= 0)
- error= purge_logs_before_date(purge_time);
- }
-#endif
-
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
err:
if (!write_error)
@@ -1731,8 +1890,7 @@ err:
/*
- Write update log in a format suitable for incremental backup
- This is also used by the slow query log.
+ Write to the slow query log.
*/
bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
@@ -1863,26 +2021,26 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
SYNOPSIS
wait_for_update()
thd Thread variable
- master_or_slave If 0, the caller is the Binlog_dump thread from master;
+ is_slave If 0, the caller is the Binlog_dump thread from master;
if 1, the caller is the SQL thread from the slave. This
influences only thd->proc_info.
NOTES
One must have a lock on LOCK_log before calling this function.
- This lock will be freed before return! That's required by
+ This lock will be released before return! That's required by
THD::enter_cond() (see NOTES in sql_class.h).
*/
-void MYSQL_LOG::wait_for_update(THD* thd, bool master_or_slave)
+void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave)
{
const char *old_msg;
DBUG_ENTER("wait_for_update");
old_msg= thd->enter_cond(&update_cond, &LOCK_log,
- master_or_slave ?
+ is_slave ?
"Has read all relay log; waiting for the slave I/O "
- "thread to update it" :
+ "thread to update it" :
"Has sent all binlog to slave; waiting for binlog "
- "to be updated");
+ "to be updated");
pthread_cond_wait(&update_cond, &LOCK_log);
thd->exit_cond(old_msg);
DBUG_VOID_RETURN;
@@ -1894,11 +2052,11 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool master_or_slave)
SYNOPSIS
close()
- exiting Bitmask for one or more of the following bits:
- LOG_CLOSE_INDEX if we should close the index file
- LOG_CLOSE_TO_BE_OPENED if we intend to call open
- at once after close.
- LOG_CLOSE_STOP_EVENT write a 'stop' event to the log
+ exiting Bitmask for one or more of the following bits:
+ LOG_CLOSE_INDEX if we should close the index file
+ LOG_CLOSE_TO_BE_OPENED if we intend to call open
+ at once after close.
+ LOG_CLOSE_STOP_EVENT write a 'stop' event to the log
NOTES
One can do an open on the object at once after doing a close.
@@ -1916,13 +2074,27 @@ void MYSQL_LOG::close(uint exiting)
(exiting & LOG_CLOSE_STOP_EVENT))
{
Stop_log_event s;
- s.set_log_pos(this);
s.write(&log_file);
+ bytes_written+= s.data_written;
signal_update();
}
#endif /* HAVE_REPLICATION */
end_io_cache(&log_file);
- if (my_close(log_file.file,MYF(0)) < 0 && ! write_error)
+
+ /* don't pwrite in a file opened with O_APPEND - it doesn't work */
+ if (log_file.type == WRITE_CACHE && log_type == LOG_BIN)
+ {
+ my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET;
+ byte flags=0; // clearing LOG_EVENT_BINLOG_IN_USE_F
+ my_pwrite(log_file.file, &flags, 1, offset, MYF(0));
+ }
+
+ if (my_sync(log_file.file,MYF(MY_WME)) && ! write_error)
+ {
+ write_error=1;
+ sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
+ }
+ if (my_close(log_file.file,MYF(MY_WME)) && ! write_error)
{
write_error=1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
@@ -2073,7 +2245,7 @@ bool flush_error_log()
On Windows is necessary a temporary file for to rename
the current error file.
*/
- strmov(strmov(err_temp, err_renamed),"-tmp");
+ strxmov(err_temp, err_renamed,"-tmp",NullS);
(void) my_delete(err_temp, MYF(0));
if (freopen(err_temp,"a+",stdout))
{
@@ -2106,145 +2278,6 @@ bool flush_error_log()
return result;
}
-
-/*
- 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;
- 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();
- ulonglong actual_size;
- char llbuf1[22], llbuf2[22];
-
- 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;
-}
-
-
void MYSQL_LOG::signal_update()
{
DBUG_ENTER("MYSQL_LOG::signal_update");
@@ -2309,7 +2342,7 @@ void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
vprint_msg_to_log()
event_type Type of event to write (Error, Warning, or Info)
format Printf style format of message
- args va_list list of arguments for the message
+ args va_list list of arguments for the message
NOTE
@@ -2375,3 +2408,648 @@ void sql_print_information(const char *format, ...)
DBUG_VOID_RETURN;
}
+
+
+/********* transaction coordinator log for 2pc - mmap() based solution *******/
+
+/*
+ the log consists of a file, mmapped to a memory.
+ file is divided on pages of tc_log_page_size size.
+ (usable size of the first page is smaller because of log header)
+ there's PAGE control structure for each page
+ each page (or rather PAGE control structure) can be in one of three
+ states - active, syncing, pool.
+ there could be only one page in active or syncing states,
+ but many in pool - pool is fifo queue.
+ usual lifecycle of a page is pool->active->syncing->pool
+ "active" page - is a page where new xid's are logged.
+ the page stays active as long as syncing slot is taken.
+ "syncing" page is being synced to disk. no new xid can be added to it.
+ when the sync is done the page is moved to a pool and an active page
+ becomes "syncing".
+
+ the result of such an architecture is a natural "commit grouping" -
+ If commits are coming faster than the system can sync, they do not
+ stall. Instead, all commit that came since the last sync are
+ logged to the same page, and they all are synced with the next -
+ one - sync. Thus, thought individual commits are delayed, throughput
+ is not decreasing.
+
+ when a xid is added to an active page, the thread of this xid waits
+ for a page's condition until the page is synced. when syncing slot
+ becomes vacant one of these waiters is awaken to take care of syncing.
+ it syncs the page and signals all waiters that the page is synced.
+ PAGE::waiters is used to count these waiters, and a page may never
+ become active again until waiters==0 (that is all waiters from the
+ previous sync have noticed the sync was completed)
+
+ note, that the page becomes "dirty" and has to be synced only when a
+ new xid is added into it. Removing a xid from a page does not make it
+ dirty - we don't sync removals to disk.
+*/
+
+ulong tc_log_page_waits= 0;
+
+#ifdef HAVE_MMAP
+
+#define TC_LOG_HEADER_SIZE (sizeof(tc_log_magic)+1)
+
+static const char tc_log_magic[]={(char) 254, 0x23, 0x05, 0x74};
+
+ulong opt_tc_log_size= TC_LOG_MIN_SIZE;
+ulong tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_cur_pages_used=0;
+
+int TC_LOG_MMAP::open(const char *opt_name)
+{
+ uint i;
+ bool crashed=FALSE;
+ PAGE *pg;
+
+ DBUG_ASSERT(total_ha_2pc > 1);
+ DBUG_ASSERT(opt_name && opt_name[0]);
+
+ tc_log_page_size= my_getpagesize();
+ DBUG_ASSERT(TC_LOG_PAGE_SIZE % tc_log_page_size == 0);
+
+ fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
+ if ((fd= my_open(logname, O_RDWR, MYF(0))) < 0)
+ {
+ if (my_errno != ENOENT)
+ goto err;
+ if (using_heuristic_recover())
+ return 1;
+ if ((fd= my_create(logname, O_RDWR, 0, MYF(MY_WME))) < 0)
+ goto err;
+ inited=1;
+ file_length= opt_tc_log_size;
+ if (my_chsize(fd, file_length, 0, MYF(MY_WME)))
+ goto err;
+ }
+ else
+ {
+ inited= 1;
+ crashed= TRUE;
+ sql_print_information("Recovering after a crash using %s", opt_name);
+ if (tc_heuristic_recover)
+ {
+ sql_print_error("Cannot perform automatic crash recovery when "
+ "--tc-heuristic-recover is used");
+ goto err;
+ }
+ file_length= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
+ if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size)
+ goto err;
+ }
+
+ data= (uchar *)my_mmap(0, (size_t)file_length, PROT_READ|PROT_WRITE,
+ MAP_NOSYNC|MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED)
+ {
+ my_errno=errno;
+ goto err;
+ }
+ inited=2;
+
+ npages=(uint)file_length/tc_log_page_size;
+ DBUG_ASSERT(npages >= 3); // to guarantee non-empty pool
+ if (!(pages=(PAGE *)my_malloc(npages*sizeof(PAGE), MYF(MY_WME|MY_ZEROFILL))))
+ goto err;
+ inited=3;
+ for (pg=pages, i=0; i < npages; i++, pg++)
+ {
+ pg->next=pg+1;
+ pg->waiters=0;
+ pg->state=POOL;
+ pthread_mutex_init(&pg->lock, MY_MUTEX_INIT_FAST);
+ pthread_cond_init (&pg->cond, 0);
+ pg->start=(my_xid *)(data + i*tc_log_page_size);
+ pg->end=(my_xid *)(pg->start + tc_log_page_size);
+ pg->size=pg->free=tc_log_page_size/sizeof(my_xid);
+ }
+ pages[0].size=pages[0].free=
+ (tc_log_page_size-TC_LOG_HEADER_SIZE)/sizeof(my_xid);
+ pages[0].start=pages[0].end-pages[0].size;
+ pages[npages-1].next=0;
+ inited=4;
+
+ if (crashed && recover())
+ goto err;
+
+ memcpy(data, tc_log_magic, sizeof(tc_log_magic));
+ data[sizeof(tc_log_magic)]= (uchar)total_ha_2pc;
+ my_msync(fd, data, tc_log_page_size, MS_SYNC);
+ inited=5;
+
+ pthread_mutex_init(&LOCK_sync, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_active, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_pool, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&COND_active, 0);
+ pthread_cond_init(&COND_pool, 0);
+
+ inited=6;
+
+ syncing= 0;
+ active=pages;
+ pool=pages+1;
+ pool_last=pages+npages-1;
+
+ return 0;
+
+err:
+ close();
+ return 1;
+}
+
+/*
+ there is no active page, let's got one from the pool
+
+ two strategies here:
+ 1. take the first from the pool
+ 2. if there're waiters - take the one with the most free space
+
+ TODO page merging. try to allocate adjacent page first,
+ so that they can be flushed both in one sync
+*/
+void TC_LOG_MMAP::get_active_from_pool()
+{
+ PAGE **p, **best_p=0;
+ int best_free;
+
+ if (syncing)
+ pthread_mutex_lock(&LOCK_pool);
+
+ do
+ {
+ best_p= p= &pool;
+ if ((*p)->waiters == 0) // can the first page be used ?
+ break; // yes - take it.
+
+ best_free=0; // no - trying second strategy
+ for (p=&(*p)->next; *p; p=&(*p)->next)
+ {
+ if ((*p)->waiters == 0 && (*p)->free > best_free)
+ {
+ best_free=(*p)->free;
+ best_p=p;
+ }
+ }
+ }
+ while ((*best_p == 0 || best_free == 0) && overflow());
+
+ active=*best_p;
+ if (active->free == active->size) // we've chosen an empty page
+ {
+ tc_log_cur_pages_used++;
+ set_if_bigger(tc_log_max_pages_used, tc_log_cur_pages_used);
+ }
+
+ if ((*best_p)->next) // unlink the page from the pool
+ *best_p=(*best_p)->next;
+ else
+ pool_last=*best_p;
+
+ if (syncing)
+ pthread_mutex_unlock(&LOCK_pool);
+}
+
+int TC_LOG_MMAP::overflow()
+{
+ /*
+ simple overflow handling - just wait
+ TODO perhaps, increase log size ?
+ let's check the behaviour of tc_log_page_waits first
+ */
+ tc_log_page_waits++;
+ pthread_cond_wait(&COND_pool, &LOCK_pool);
+ return 1; // always return 1
+}
+
+/*
+ all access to active page is serialized but it's not a problem, as
+ we're assuming that fsync() will be a main bottleneck.
+ That is, parallelizing writes to log pages we'll decrease number of
+ threads waiting for a page, but then all these threads will be waiting
+ for a fsync() anyway
+
+ RETURN
+ 0 - error
+ otherwise - "cookie", a number that will be passed as an argument
+ to unlog() call. tc_log can define it any way it wants,
+ and use for whatever purposes. TC_LOG_MMAP sets it
+ to the position in memory where xid was logged to.
+*/
+
+int TC_LOG_MMAP::log(THD *thd, my_xid xid)
+{
+ int err;
+ PAGE *p;
+ ulong cookie;
+
+ pthread_mutex_lock(&LOCK_active);
+
+ /*
+ if active page is full - just wait...
+ frankly speaking, active->free here accessed outside of mutex
+ protection, but it's safe, because it only means we may miss an
+ unlog() for the active page, and we're not waiting for it here -
+ unlog() does not signal COND_active.
+ */
+ while (unlikely(active && active->free == 0))
+ pthread_cond_wait(&COND_active, &LOCK_active);
+
+ /* no active page ? take one from the pool */
+ if (active == 0)
+ get_active_from_pool();
+
+ p=active;
+ pthread_mutex_lock(&p->lock);
+
+ /* searching for an empty slot */
+ while (*p->ptr)
+ {
+ p->ptr++;
+ DBUG_ASSERT(p->ptr < p->end); // because p->free > 0
+ }
+
+ /* found! store xid there and mark the page dirty */
+ cookie= (ulong)((uchar *)p->ptr - data); // can never be zero
+ *p->ptr++= xid;
+ p->free--;
+ p->state= DIRTY;
+
+ /* to sync or not to sync - this is the question */
+ pthread_mutex_unlock(&LOCK_active);
+ pthread_mutex_lock(&LOCK_sync);
+ pthread_mutex_unlock(&p->lock);
+
+ if (syncing)
+ { // somebody's syncing. let's wait
+ p->waiters++;
+ /*
+ note - it must be while (), not do ... while () here
+ as p->state may be not DIRTY when we come here
+ */
+ while (p->state == DIRTY && syncing)
+ pthread_cond_wait(&p->cond, &LOCK_sync);
+ p->waiters--;
+ err= p->state == ERROR;
+ if (p->state != DIRTY) // page was synced
+ {
+ if (p->waiters == 0)
+ pthread_cond_signal(&COND_pool); // in case somebody's waiting
+ pthread_mutex_unlock(&LOCK_sync);
+ goto done; // we're done
+ }
+ } // page was not synced! do it now
+ DBUG_ASSERT(active == p && syncing == 0);
+ pthread_mutex_lock(&LOCK_active);
+ syncing=p; // place is vacant - take it
+ active=0; // page is not active anymore
+ pthread_cond_broadcast(&COND_active); // in case somebody's waiting
+ pthread_mutex_unlock(&LOCK_active);
+ pthread_mutex_unlock(&LOCK_sync);
+ err= sync();
+
+done:
+ return err ? 0 : cookie;
+}
+
+int TC_LOG_MMAP::sync()
+{
+ int err;
+
+ DBUG_ASSERT(syncing != active);
+
+ /*
+ sit down and relax - this can take a while...
+ note - no locks are held at this point
+ */
+ err= my_msync(fd, syncing->start, 1, MS_SYNC);
+
+ /* page is synced. let's move it to the pool */
+ pthread_mutex_lock(&LOCK_pool);
+ pool_last->next=syncing;
+ pool_last=syncing;
+ syncing->next=0;
+ syncing->state= err ? ERROR : POOL;
+ pthread_cond_broadcast(&syncing->cond); // signal "sync done"
+ pthread_cond_signal(&COND_pool); // in case somebody's waiting
+ pthread_mutex_unlock(&LOCK_pool);
+
+ /* marking 'syncing' slot free */
+ pthread_mutex_lock(&LOCK_sync);
+ syncing=0;
+ pthread_cond_signal(&active->cond); // wake up a new syncer
+ pthread_mutex_unlock(&LOCK_sync);
+ return err;
+}
+
+/*
+ erase xid from the page, update page free space counters/pointers.
+ cookie points directly to the memory where xid was logged
+*/
+void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
+{
+ PAGE *p=pages+(cookie/tc_log_page_size);
+ my_xid *x=(my_xid *)(data+cookie);
+
+ DBUG_ASSERT(*x == xid);
+ DBUG_ASSERT(x >= p->start && x < p->end);
+ *x=0;
+
+ pthread_mutex_lock(&p->lock);
+ p->free++;
+ DBUG_ASSERT(p->free <= p->size);
+ set_if_smaller(p->ptr, x);
+ if (p->free == p->size) // the page is completely empty
+ statistic_decrement(tc_log_cur_pages_used, &LOCK_status);
+ if (p->waiters == 0) // the page is in pool and ready to rock
+ pthread_cond_signal(&COND_pool); // ping ... for overflow()
+ pthread_mutex_unlock(&p->lock);
+}
+
+void TC_LOG_MMAP::close()
+{
+ uint i;
+ switch (inited) {
+ case 6:
+ pthread_mutex_destroy(&LOCK_sync);
+ pthread_mutex_destroy(&LOCK_active);
+ pthread_mutex_destroy(&LOCK_pool);
+ pthread_cond_destroy(&COND_pool);
+ case 5:
+ data[0]='A'; // garble the first (signature) byte, in case my_delete fails
+ case 4:
+ for (i=0; i < npages; i++)
+ {
+ if (pages[i].ptr == 0)
+ break;
+ pthread_mutex_destroy(&pages[i].lock);
+ pthread_cond_destroy(&pages[i].cond);
+ }
+ case 3:
+ my_free((gptr)pages, MYF(0));
+ case 2:
+ my_munmap(data, (size_t)file_length);
+ case 1:
+ my_close(fd, MYF(0));
+ }
+ if (inited>=5) // cannot do in the switch because of Windows
+ my_delete(logname, MYF(MY_WME));
+ inited=0;
+}
+
+int TC_LOG_MMAP::recover()
+{
+ HASH xids;
+ PAGE *p=pages, *end_p=pages+npages;
+
+ if (memcmp(data, tc_log_magic, sizeof(tc_log_magic)))
+ {
+ sql_print_error("Bad magic header in tc log");
+ goto err1;
+ }
+
+ /*
+ the first byte after magic signature is set to current
+ number of storage engines on startup
+ */
+ if (data[sizeof(tc_log_magic)] != total_ha_2pc)
+ {
+ sql_print_error("Recovery failed! You must enable "
+ "exactly %d storage engines that support "
+ "two-phase commit protocol",
+ data[sizeof(tc_log_magic)]);
+ goto err1;
+ }
+
+ if (hash_init(&xids, &my_charset_bin, tc_log_page_size/3, 0,
+ sizeof(my_xid), 0, 0, MYF(0)))
+ goto err1;
+
+ for ( ; p < end_p ; p++)
+ {
+ for (my_xid *x=p->start; x < p->end; x++)
+ if (*x && my_hash_insert(&xids, (byte *)x))
+ goto err2; // OOM
+ }
+
+ if (ha_recover(&xids))
+ goto err2;
+
+ hash_free(&xids);
+ bzero(data, (size_t)file_length);
+ return 0;
+
+err2:
+ hash_free(&xids);
+err1:
+ sql_print_error("Crash recovery failed. Either correct the problem "
+ "(if it's, for example, out of memory error) and restart, "
+ "or delete tc log and start mysqld with "
+ "--tc-heuristic-recover={commit|rollback}");
+ return 1;
+}
+#endif
+
+TC_LOG *tc_log;
+TC_LOG_DUMMY tc_log_dummy;
+TC_LOG_MMAP tc_log_mmap;
+
+/*
+ Perform heuristic recovery, if --tc-heuristic-recover was used
+
+ RETURN VALUE
+ 0 no heuristic recovery was requested
+ 1 heuristic recovery was performed
+
+ NOTE
+ no matter whether heuristic recovery was successful or not
+ mysqld must exit. So, return value is the same in both cases.
+*/
+
+int TC_LOG::using_heuristic_recover()
+{
+ if (!tc_heuristic_recover)
+ return 0;
+
+ sql_print_information("Heuristic crash recovery mode");
+ if (ha_recover(0))
+ sql_print_error("Heuristic crash recovery failed");
+ sql_print_information("Please restart mysqld without --tc-heuristic-recover");
+ return 1;
+}
+
+/****** transaction coordinator log for 2pc - binlog() based solution ******/
+#define TC_LOG_BINLOG MYSQL_LOG
+
+/*
+ TODO keep in-memory list of prepared transactions
+ (add to list in log(), remove on unlog())
+ and copy it to the new binlog if rotated
+ but let's check the behaviour of tc_log_page_waits first!
+*/
+
+int TC_LOG_BINLOG::open(const char *opt_name)
+{
+ LOG_INFO log_info;
+ int error= 1;
+
+ DBUG_ASSERT(total_ha_2pc > 1);
+ DBUG_ASSERT(opt_name && opt_name[0]);
+
+ pthread_mutex_init(&LOCK_prep_xids, MY_MUTEX_INIT_FAST);
+ pthread_cond_init (&COND_prep_xids, 0);
+
+ if (!my_b_inited(&index_file))
+ {
+ /* There was a failure to open the index file, can't open the binlog */
+ cleanup();
+ return 1;
+ }
+
+ if (using_heuristic_recover())
+ {
+ /* generate a new binlog to mask a corrupted one */
+ open(opt_name, LOG_BIN, 0, WRITE_CACHE, 0, max_binlog_size, 0);
+ cleanup();
+ return 1;
+ }
+
+ if ((error= find_log_pos(&log_info, NullS, 1)))
+ {
+ if (error != LOG_INFO_EOF)
+ sql_print_error("find_log_pos() failed (error: %d)", error);
+ else
+ error= 0;
+ goto err;
+ }
+
+ {
+ const char *errmsg;
+ IO_CACHE log;
+ File file;
+ Log_event *ev=0;
+ Format_description_log_event fdle(BINLOG_VERSION);
+ char log_name[FN_REFLEN];
+
+ if (! fdle.is_valid())
+ goto err;
+
+ do
+ {
+ strmake(log_name, log_info.log_file_name, sizeof(log_name)-1);
+ } while (!(error= find_next_log(&log_info, 1)));
+
+ if (error != LOG_INFO_EOF)
+ {
+ sql_print_error("find_log_pos() failed (error: %d)", error);
+ goto err;
+ }
+
+ if ((file= open_binlog(&log, log_name, &errmsg)) < 0)
+ {
+ sql_print_error("%s", errmsg);
+ goto err;
+ }
+
+ if ((ev= Log_event::read_log_event(&log, 0, &fdle)) &&
+ ev->get_type_code() == FORMAT_DESCRIPTION_EVENT &&
+ ev->flags & LOG_EVENT_BINLOG_IN_USE_F)
+ {
+ sql_print_information("Recovering after a crash using %s", opt_name);
+ error= recover(&log, (Format_description_log_event *)ev);
+ }
+ else
+ error=0;
+
+ delete ev;
+ end_io_cache(&log);
+ my_close(file, MYF(MY_WME));
+
+ if (error)
+ goto err;
+ }
+
+err:
+ return error;
+}
+
+/* this is called on shutdown, after ha_panic */
+void TC_LOG_BINLOG::close()
+{
+ DBUG_ASSERT(prepared_xids==0);
+ pthread_mutex_destroy(&LOCK_prep_xids);
+ pthread_cond_destroy (&COND_prep_xids);
+}
+
+/*
+ TODO group commit
+
+ RETURN
+ 0 - error
+ 1 - success
+*/
+int TC_LOG_BINLOG::log(THD *thd, my_xid xid)
+{
+ Xid_log_event xle(thd, xid);
+ IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
+ return !binlog_end_trans(thd, trans_log, &xle); // invert return value
+}
+
+void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
+{
+ pthread_mutex_lock(&LOCK_prep_xids);
+ if (--prepared_xids == 0)
+ pthread_cond_signal(&COND_prep_xids);
+ pthread_mutex_unlock(&LOCK_prep_xids);
+ rotate_and_purge(0); // as ::write() did not rotate
+}
+
+int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)
+{
+ Log_event *ev;
+ HASH xids;
+ MEM_ROOT mem_root;
+
+ if (! fdle->is_valid() ||
+ hash_init(&xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0,
+ sizeof(my_xid), 0, 0, MYF(0)))
+ goto err1;
+
+ init_alloc_root(&mem_root, TC_LOG_PAGE_SIZE, TC_LOG_PAGE_SIZE);
+
+ fdle->flags&= ~LOG_EVENT_BINLOG_IN_USE_F; // abort on the first error
+
+ while ((ev= Log_event::read_log_event(log,0,fdle)) && ev->is_valid())
+ {
+ if (ev->get_type_code() == XID_EVENT)
+ {
+ Xid_log_event *xev=(Xid_log_event *)ev;
+ byte *x=(byte *)memdup_root(&mem_root, (char *)& xev->xid,
+ sizeof(xev->xid));
+ if (! x)
+ goto err2;
+ my_hash_insert(&xids, x);
+ }
+ delete ev;
+ }
+
+ if (ha_recover(&xids))
+ goto err2;
+
+ free_root(&mem_root, MYF(0));
+ hash_free(&xids);
+ return 0;
+
+err2:
+ free_root(&mem_root, MYF(0));
+ hash_free(&xids);
+err1:
+ sql_print_error("Crash recovery failed. Either correct the problem "
+ "(if it's, for example, out of memory error) and restart, "
+ "or delete (or rename) binary log and start mysqld with "
+ "--tc-heuristic-recover={commit|rollback}");
+ return 1;
+}
+
diff --git a/sql/log_event.cc b/sql/log_event.cc
index b08439a20b8..5cb4c289a10 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000-2004 MySQL AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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 */
@@ -121,7 +121,8 @@ static char *pretty_print_str(char *packet, char *str, int len)
static inline char* slave_load_file_stem(char*buf, uint file_id,
int event_server_id)
{
- fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "", MY_UNPACK_FILENAME);
+ fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "",
+ MY_UNPACK_FILENAME | MY_UNIX_PATH);
buf = strend(buf);
buf = int10_to_str(::server_id, buf, 10);
*buf++ = '-';
@@ -182,10 +183,12 @@ static void cleanup_load_tmpdir()
write_str()
*/
-static bool write_str(IO_CACHE *file, char *str, byte length)
+static bool write_str(IO_CACHE *file, char *str, uint length)
{
- return (my_b_safe_write(file, &length, 1) ||
- my_b_safe_write(file, (byte*) str, (int) length));
+ byte tmp[1];
+ tmp[0]= (byte) length;
+ return (my_b_safe_write(file, tmp, sizeof(tmp)) ||
+ my_b_safe_write(file, (byte*) str, length));
}
@@ -193,17 +196,18 @@ static bool write_str(IO_CACHE *file, char *str, byte length)
read_str()
*/
-static inline int read_str(char * &buf, char *buf_end, char * &str,
- uint8 &len)
+static inline int read_str(char **buf, char *buf_end, char **str,
+ uint8 *len)
{
- if (buf + (uint) (uchar) *buf >= buf_end)
+ if (*buf + ((uint) (uchar) **buf) >= buf_end)
return 1;
- len = (uint8) *buf;
- str= buf+1;
- buf+= (uint) len+1;
+ *len= (uint8) **buf;
+ *str= (*buf)+1;
+ (*buf)+= (uint) *len+1;
return 0;
}
+
/*
Transforms a string into "" or its expression in 0x... form.
*/
@@ -227,9 +231,25 @@ char *str_to_hex(char *to, const char *from, uint len)
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.
+*/
+
+static void print_set_option(FILE* file, uint32 bits_changed, uint32 option,
+ uint32 flags, const char* name, bool* need_comma)
+{
+ if (bits_changed & option)
+ {
+ if (*need_comma)
+ fprintf(file,", ");
+ fprintf(file,"%s=%d", name, test(flags & option));
+ *need_comma= 1;
+ }
+}
/**************************************************************************
- Log_event methods
+ Log_event methods (= the parent class of all events)
**************************************************************************/
/*
@@ -239,7 +259,7 @@ char *str_to_hex(char *to, const char *from, uint len)
const char* Log_event::get_type_str()
{
switch(get_type_code()) {
- case START_EVENT: return "Start";
+ case START_EVENT_V3: return "Start_v3";
case STOP_EVENT: return "Stop";
case QUERY_EVENT: return "Query";
case ROTATE_EVENT: return "Rotate";
@@ -252,8 +272,12 @@ const char* Log_event::get_type_str()
case DELETE_FILE_EVENT: return "Delete_file";
case EXEC_LOAD_EVENT: return "Exec_load";
case RAND_EVENT: return "RAND";
+ case XID_EVENT: return "Xid";
case USER_VAR_EVENT: return "User var";
- default: return "Unknown"; /* impossible */
+ case FORMAT_DESCRIPTION_EVENT: return "Format_desc";
+ case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query";
+ case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query";
+ default: return "Unknown"; /* impossible */
}
}
@@ -264,25 +288,23 @@ const char* Log_event::get_type_str()
#ifndef MYSQL_CLIENT
Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
- :log_pos(0), temp_buf(0), exec_time(0), cached_event_len(0),
- flags(flags_arg), thd(thd_arg)
+ :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg), thd(thd_arg)
{
server_id= thd->server_id;
when= thd->start_time;
- cache_stmt= (using_trans &&
- (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
+ cache_stmt= using_trans;
}
/*
- This minimal constructor is for when you are not even sure that there is a
- valid THD. For example in the server when we are shutting down or flushing
- logs after receiving a SIGHUP (then we must write a Rotate to the binlog but
- we have no THD, so we need this minimal constructor).
+ This minimal constructor is for when you are not even sure that there
+ is a valid THD. For example in the server when we are shutting down or
+ flushing logs after receiving a SIGHUP (then we must write a Rotate to
+ the binlog but we have no THD, so we need this minimal constructor).
*/
Log_event::Log_event()
- :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0),
+ :temp_buf(0), exec_time(0), flags(0), cache_stmt(0),
thd(0)
{
server_id= ::server_id;
@@ -296,24 +318,71 @@ Log_event::Log_event()
Log_event::Log_event()
*/
-Log_event::Log_event(const char* buf, bool old_format)
- :temp_buf(0), cached_event_len(0), cache_stmt(0)
+Log_event::Log_event(const char* buf,
+ const Format_description_log_event* description_event)
+ :temp_buf(0), cache_stmt(0)
{
+#ifndef MYSQL_CLIENT
+ thd = 0;
+#endif
when = uint4korr(buf);
server_id = uint4korr(buf + SERVER_ID_OFFSET);
- if (old_format)
+ if (description_event->binlog_version==1)
{
- log_pos=0;
- flags=0;
+ log_pos= 0;
+ flags= 0;
+ return;
}
- else
+ /* 4.0 or newer */
+ log_pos= uint4korr(buf + LOG_POS_OFFSET);
+ /*
+ If the log is 4.0 (so here it can only be a 4.0 relay log read by
+ the SQL thread or a 4.0 master binlog read by the I/O thread),
+ log_pos is the beginning of the event: we transform it into the end
+ of the event, which is more useful.
+ But how do you know that the log is 4.0: you know it if
+ description_event is version 3 *and* you are not reading a
+ Format_desc (remember that mysqlbinlog starts by assuming that 5.0
+ logs are in 4.0 format, until it finds a Format_desc).
+ */
+ if (description_event->binlog_version==3 &&
+ buf[EVENT_TYPE_OFFSET]<FORMAT_DESCRIPTION_EVENT && log_pos)
{
- log_pos = uint4korr(buf + LOG_POS_OFFSET);
- flags = uint2korr(buf + FLAGS_OFFSET);
+ /*
+ If log_pos=0, don't change it. log_pos==0 is a marker to mean
+ "don't change rli->group_master_log_pos" (see
+ inc_group_relay_log_pos()). As it is unreal log_pos, adding the
+ event len's is nonsense. For example, a fake Rotate event should
+ not have its log_pos (which is 0) changed or it will modify
+ Exec_master_log_pos in SHOW SLAVE STATUS, displaying a nonsense
+ value of (a non-zero offset which does not exist in the master's
+ binlog, so which will cause problems if the user uses this value
+ in CHANGE MASTER).
+ */
+ log_pos+= uint4korr(buf + EVENT_LEN_OFFSET);
}
-#ifndef MYSQL_CLIENT
- thd = 0;
-#endif
+ DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
+
+ flags= uint2korr(buf + FLAGS_OFFSET);
+ if ((buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) ||
+ (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT))
+ {
+ /*
+ These events always have a header which stops here (i.e. their
+ header is FROZEN).
+ */
+ /*
+ Initialization to zero of all other Log_event members as they're
+ not specified. Currently there are no such members; in the future
+ there will be an event UID (but Format_description and Rotate
+ don't need this UID, as they are not propagated through
+ --log-slave-updates (remember the UID is used to not play a query
+ twice when you have two masters which are slaves of a 3rd master).
+ Then we are done.
+ */
+ return;
+ }
+ /* otherwise, go on with reading the header from buf (nothing now) */
}
#ifndef MYSQL_CLIENT
@@ -339,41 +408,42 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
only in the case discussed above, 'if (rli)' is useless here.
But as we are not 100% sure, keep it for now.
*/
- if (rli)
+ if (rli)
{
/*
- If in a transaction, and if the slave supports transactions,
- just inc_event_relay_log_pos(). We only have to check for OPTION_BEGIN
- (not OPTION_NOT_AUTOCOMMIT) as transactions are logged
- with BEGIN/COMMIT, not with SET AUTOCOMMIT= .
-
+ If in a transaction, and if the slave supports transactions, just
+ inc_event_relay_log_pos(). We only have to check for OPTION_BEGIN
+ (not OPTION_NOT_AUTOCOMMIT) as transactions are logged with
+ BEGIN/COMMIT, not with SET AUTOCOMMIT= .
+
CAUTION: opt_using_transactions means
- innodb || bdb ; suppose the master supports InnoDB and BDB,
+ innodb || bdb ; suppose the master supports InnoDB and BDB,
but the slave supports only BDB, problems
- will arise:
+ will arise:
- suppose an InnoDB table is created on the master,
- then it will be MyISAM on the slave
- - but as opt_using_transactions is true, the slave will believe he is
- transactional with the MyISAM table. And problems will come when one
- does START SLAVE; STOP SLAVE; START SLAVE; (the slave will resume at
- BEGIN whereas there has not been any rollback). This is the problem of
- using opt_using_transactions instead of a finer
- "does the slave support _the_transactional_handler_used_on_the_master_".
-
- More generally, we'll have problems when a query mixes a transactional
- handler and MyISAM and STOP SLAVE is issued in the middle of the
- "transaction". START SLAVE will resume at BEGIN while the MyISAM table
- has already been updated.
+ - but as opt_using_transactions is true, the slave will believe he
+ is transactional with the MyISAM table. And problems will come
+ when one does START SLAVE; STOP SLAVE; START SLAVE; (the slave
+ will resume at BEGIN whereas there has not been any rollback).
+ This is the problem of using opt_using_transactions instead of a
+ finer "does the slave support
+ _the_transactional_handler_used_on_the_master_".
+
+ More generally, we'll have problems when a query mixes a
+ transactional handler and MyISAM and STOP SLAVE is issued in the
+ middle of the "transaction". START SLAVE will resume at BEGIN
+ while the MyISAM table has already been updated.
*/
if ((thd->options & OPTION_BEGIN) && opt_using_transactions)
- rli->inc_event_relay_log_pos(get_event_len());
+ rli->inc_event_relay_log_pos();
else
{
- rli->inc_group_relay_log_pos(get_event_len(),log_pos);
+ rli->inc_group_relay_log_pos(log_pos);
flush_relay_log_info(rli);
/*
- Note that Rotate_log_event::exec_event() does not call this function,
- so there is no chance that a fake rotate event resets
+ Note that Rotate_log_event::exec_event() does not call this
+ function, so there is no chance that a fake rotate event resets
last_master_timestamp.
Note that we update without mutex (probably ok - except in some very
rare cases, only consequence is that value may take some time to
@@ -434,58 +504,101 @@ void Log_event::init_show_field_list(List<Item>* field_list)
field_list->push_back(new Item_empty_string("Event_type", 20));
field_list->push_back(new Item_return_int("Server_id", 10,
MYSQL_TYPE_LONG));
- field_list->push_back(new Item_return_int("Orig_log_pos", 11,
+ field_list->push_back(new Item_return_int("End_log_pos", 11,
MYSQL_TYPE_LONGLONG));
field_list->push_back(new Item_empty_string("Info", 20));
}
-#endif /* !MYSQL_CLIENT */
/*
Log_event::write()
*/
-int Log_event::write(IO_CACHE* file)
+bool Log_event::write_header(IO_CACHE* file, ulong event_data_length)
{
- return (write_header(file) || write_data(file)) ? -1 : 0;
-}
+ byte header[LOG_EVENT_HEADER_LEN];
+ DBUG_ENTER("Log_event::write_header");
+ /* Store number of bytes that will be written by this event */
+ data_written= event_data_length + sizeof(header);
-/*
- Log_event::write_header()
-*/
+ /*
+ log_pos != 0 if this is relay-log event. In this case we should not
+ change the position
+ */
-int Log_event::write_header(IO_CACHE* file)
-{
- char buf[LOG_EVENT_HEADER_LEN];
- char* pos = buf;
- int4store(pos, (ulong) when); // timestamp
- pos += 4;
- *pos++ = get_type_code(); // event type code
- int4store(pos, server_id);
- pos += 4;
- long tmp=get_data_size() + LOG_EVENT_HEADER_LEN;
- int4store(pos, tmp);
- pos += 4;
- int4store(pos, log_pos);
- pos += 4;
- int2store(pos, flags);
- pos += 2;
- return (my_b_safe_write(file, (byte*) buf, (uint) (pos - buf)));
+ if (is_artificial_event())
+ {
+ /*
+ We should not do any cleanup on slave when reading this. We
+ mark this by setting log_pos to 0. Start_log_event_v3() will
+ detect this on reading and set artificial_event=1 for the event.
+ */
+ log_pos= 0;
+ }
+ else if (!log_pos)
+ {
+ /*
+ Calculate position of end of event
+
+ Note that with a SEQ_READ_APPEND cache, my_b_tell() does not
+ work well. So this will give slightly wrong positions for the
+ Format_desc/Rotate/Stop events which the slave writes to its
+ relay log. For example, the initial Format_desc will have
+ end_log_pos=91 instead of 95. Because after writing the first 4
+ bytes of the relay log, my_b_tell() still reports 0. Because
+ my_b_append() does not update the counter which my_b_tell()
+ later uses (one should probably use my_b_append_tell() to work
+ around this). To get right positions even when writing to the
+ relay log, we use the (new) my_b_safe_tell().
+
+ Note that this raises a question on the correctness of all these
+ DBUG_ASSERT(my_b_tell()=rli->event_relay_log_pos).
+
+ If in a transaction, the log_pos which we calculate below is not
+ very good (because then my_b_safe_tell() returns start position
+ of the BEGIN, so it's like the statement was at the BEGIN's
+ place), but it's not a very serious problem (as the slave, when
+ it is in a transaction, does not take those end_log_pos into
+ account (as it calls inc_event_relay_log_pos()). To be fixed
+ later, so that it looks less strange. But not bug.
+ */
+
+ log_pos= my_b_safe_tell(file)+data_written;
+ }
+
+ /*
+ Header will be of size LOG_EVENT_HEADER_LEN for all events, except for
+ FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT, where it will be
+ LOG_EVENT_MINIMAL_HEADER_LEN (remember these 2 have a frozen header,
+ because we read them before knowing the format).
+ */
+
+ int4store(header, (ulong) when); // timestamp
+ header[EVENT_TYPE_OFFSET]= get_type_code();
+ int4store(header+ SERVER_ID_OFFSET, server_id);
+ int4store(header+ EVENT_LEN_OFFSET, data_written);
+ int4store(header+ LOG_POS_OFFSET, log_pos);
+ int2store(header+ FLAGS_OFFSET, flags);
+
+ DBUG_RETURN(my_b_safe_write(file, header, sizeof(header)) != 0);
}
/*
Log_event::read_log_event()
+
+ This needn't be format-tolerant, because we only read
+ LOG_EVENT_MINIMAL_HEADER_LEN (we just want to read the event's length).
+
*/
-#ifndef MYSQL_CLIENT
int Log_event::read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock)
{
ulong data_len;
int result=0;
- char buf[LOG_EVENT_HEADER_LEN];
+ char buf[LOG_EVENT_MINIMAL_HEADER_LEN];
DBUG_ENTER("read_log_event");
if (log_lock)
@@ -505,24 +618,25 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
goto end;
}
data_len= uint4korr(buf + EVENT_LEN_OFFSET);
- if (data_len < LOG_EVENT_HEADER_LEN ||
+ if (data_len < LOG_EVENT_MINIMAL_HEADER_LEN ||
data_len > current_thd->variables.max_allowed_packet)
{
DBUG_PRINT("error",("data_len: %ld", data_len));
- result= ((data_len < LOG_EVENT_HEADER_LEN) ? LOG_READ_BOGUS :
+ result= ((data_len < LOG_EVENT_MINIMAL_HEADER_LEN) ? LOG_READ_BOGUS :
LOG_READ_TOO_LARGE);
goto end;
}
packet->append(buf, sizeof(buf));
- data_len-= LOG_EVENT_HEADER_LEN;
+ data_len-= LOG_EVENT_MINIMAL_HEADER_LEN;
if (data_len)
{
if (packet->append(file, data_len))
{
/*
- Here we should never hit EOF in a non-error condition.
+ Here if we hit EOF it's really an error: as data_len is >=0
+ there's supposed to be more bytes available.
EOF means we are reading the event partially, which should
- never happen.
+ never happen: either we read badly or the binlog is truncated.
*/
result= file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO;
/* Implicit goto end; */
@@ -539,42 +653,63 @@ end:
#ifndef MYSQL_CLIENT
#define UNLOCK_MUTEX if (log_lock) pthread_mutex_unlock(log_lock);
#define LOCK_MUTEX if (log_lock) pthread_mutex_lock(log_lock);
-#define max_allowed_packet current_thd->variables.max_allowed_packet
#else
#define UNLOCK_MUTEX
#define LOCK_MUTEX
-#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet)
#endif
/*
Log_event::read_log_event()
NOTE:
- Allocates memory; The caller is responsible for clean-up
+ Allocates memory; The caller is responsible for clean-up.
*/
#ifndef MYSQL_CLIENT
Log_event* Log_event::read_log_event(IO_CACHE* file,
pthread_mutex_t* log_lock,
- bool old_format)
+ const Format_description_log_event *description_event)
#else
-Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
-#endif
+Log_event* Log_event::read_log_event(IO_CACHE* file,
+ const Format_description_log_event *description_event)
+#endif
{
- char head[LOG_EVENT_HEADER_LEN];
- uint header_size= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ DBUG_ENTER("Log_event::read_log_event(IO_CACHE *, Format_description_log_event *");
+ DBUG_ASSERT(description_event != 0);
+ char head[LOG_EVENT_MINIMAL_HEADER_LEN];
+ /*
+ First we only want to read at most LOG_EVENT_MINIMAL_HEADER_LEN, just to
+ check the event for sanity and to know its length; no need to really parse
+ it. We say "at most" because this could be a 3.23 master, which has header
+ of 13 bytes, whereas LOG_EVENT_MINIMAL_HEADER_LEN is 19 bytes (it's
+ "minimal" over the set {MySQL >=4.0}).
+ */
+ uint header_size= min(description_event->common_header_len,
+ LOG_EVENT_MINIMAL_HEADER_LEN);
LOCK_MUTEX;
+ DBUG_PRINT("info", ("my_b_tell=%lu", my_b_tell(file)));
if (my_b_read(file, (byte *) head, header_size))
{
+ DBUG_PRINT("info", ("Log_event::read_log_event(IO_CACHE*,Format_desc*) \
+failed my_b_read"));
UNLOCK_MUTEX;
- return 0;
+ /*
+ No error here; it could be that we are at the file's end. However
+ if the next my_b_read() fails (below), it will be an error as we
+ were able to read the first bytes.
+ */
+ DBUG_RETURN(0);
}
uint data_len = uint4korr(head + EVENT_LEN_OFFSET);
char *buf= 0;
const char *error= 0;
Log_event *res= 0;
+#ifndef max_allowed_packet
+ THD *thd=current_thd;
+ uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~(ulong)0;
+#endif
if (data_len > max_allowed_packet)
{
@@ -601,15 +736,16 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
error = "read error";
goto err;
}
- if ((res = read_log_event(buf, data_len, &error, old_format)))
+ if ((res= read_log_event(buf, data_len, &error, description_event)))
res->register_temp_buf(buf);
err:
UNLOCK_MUTEX;
- if (error)
+ if (!res)
{
- sql_print_error("\
-Error in Log_event::read_log_event(): '%s', data_len: %d, event_type: %d",
+ DBUG_ASSERT(error != 0);
+ sql_print_error("Error in Log_event::read_log_event(): "
+ "'%s', data_len: %d, event_type: %d",
error,data_len,head[EVENT_TYPE_OFFSET]);
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
/*
@@ -622,94 +758,120 @@ Error in Log_event::read_log_event(): '%s', data_len: %d, event_type: %d",
*/
file->error= -1;
}
- return res;
+ DBUG_RETURN(res);
}
/*
Log_event::read_log_event()
+ Binlog format tolerance is in (buf, event_len, description_event)
+ constructors.
*/
-Log_event* Log_event::read_log_event(const char* buf, int event_len,
- const char **error, bool old_format)
+Log_event* Log_event::read_log_event(const char* buf, uint event_len,
+ const char **error,
+ const Format_description_log_event *description_event)
{
- DBUG_ENTER("Log_event::read_log_event");
-
+ Log_event* ev;
+ DBUG_ENTER("Log_event::read_log_event(char*,...)");
+ DBUG_ASSERT(description_event != 0);
+ DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version));
if (event_len < EVENT_LEN_OFFSET ||
(uint) event_len != uint4korr(buf+EVENT_LEN_OFFSET))
{
*error="Sanity check failed"; // Needed to free buffer
DBUG_RETURN(NULL); // general sanity check - will fail on a partial read
}
-
- Log_event* ev = NULL;
-
+
switch(buf[EVENT_TYPE_OFFSET]) {
case QUERY_EVENT:
- ev = new Query_log_event(buf, event_len, old_format);
+ ev = new Query_log_event(buf, event_len, description_event, QUERY_EVENT);
break;
case LOAD_EVENT:
- ev = new Create_file_log_event(buf, event_len, old_format);
+ ev = new Load_log_event(buf, event_len, description_event);
break;
case NEW_LOAD_EVENT:
- ev = new Load_log_event(buf, event_len, old_format);
+ ev = new Load_log_event(buf, event_len, description_event);
break;
case ROTATE_EVENT:
- ev = new Rotate_log_event(buf, event_len, old_format);
+ ev = new Rotate_log_event(buf, event_len, description_event);
break;
#ifdef HAVE_REPLICATION
- case SLAVE_EVENT:
+ case SLAVE_EVENT: /* can never happen (unused event) */
ev = new Slave_log_event(buf, event_len);
break;
#endif /* HAVE_REPLICATION */
case CREATE_FILE_EVENT:
- ev = new Create_file_log_event(buf, event_len, old_format);
+ ev = new Create_file_log_event(buf, event_len, description_event);
break;
case APPEND_BLOCK_EVENT:
- ev = new Append_block_log_event(buf, event_len);
+ ev = new Append_block_log_event(buf, event_len, description_event);
break;
case DELETE_FILE_EVENT:
- ev = new Delete_file_log_event(buf, event_len);
+ ev = new Delete_file_log_event(buf, event_len, description_event);
break;
case EXEC_LOAD_EVENT:
- ev = new Execute_load_log_event(buf, event_len);
+ ev = new Execute_load_log_event(buf, event_len, description_event);
break;
- case START_EVENT:
- ev = new Start_log_event(buf, old_format);
+ case START_EVENT_V3: /* this is sent only by MySQL <=4.x */
+ ev = new Start_log_event_v3(buf, description_event);
break;
-#ifdef HAVE_REPLICATION
case STOP_EVENT:
- ev = new Stop_log_event(buf, old_format);
+ ev = new Stop_log_event(buf, description_event);
break;
-#endif /* HAVE_REPLICATION */
case INTVAR_EVENT:
- ev = new Intvar_log_event(buf, old_format);
+ ev = new Intvar_log_event(buf, description_event);
+ break;
+ case XID_EVENT:
+ ev = new Xid_log_event(buf, description_event);
break;
case RAND_EVENT:
- ev = new Rand_log_event(buf, old_format);
+ ev = new Rand_log_event(buf, description_event);
break;
case USER_VAR_EVENT:
- ev = new User_var_log_event(buf, old_format);
+ ev = new User_var_log_event(buf, description_event);
+ break;
+ case FORMAT_DESCRIPTION_EVENT:
+ ev = new Format_description_log_event(buf, event_len, description_event);
+ break;
+ case BEGIN_LOAD_QUERY_EVENT:
+ ev = new Begin_load_query_log_event(buf, event_len, description_event);
+ break;
+ case EXECUTE_LOAD_QUERY_EVENT:
+ ev = new Execute_load_query_log_event(buf, event_len, description_event);
break;
default:
+ DBUG_PRINT("error",("Unknown evernt code: %d",(int) buf[EVENT_TYPE_OFFSET]));
+ ev= NULL;
break;
}
+
+ /*
+ is_valid() are small event-specific sanity tests which are
+ important; for example there are some my_malloc() in constructors
+ (e.g. Query_log_event::Query_log_event(char*...)); when these
+ my_malloc() fail we can't return an error out of the constructor
+ (because constructor is "void") ; so instead we leave the pointer we
+ wanted to allocate (e.g. 'query') to 0 and we test it in is_valid().
+ Same for Format_description_log_event, member 'post_header_len'.
+ */
if (!ev || !ev->is_valid())
{
+ DBUG_PRINT("error",("Found invalid event in binary log"));
+
delete ev;
#ifdef MYSQL_CLIENT
- if (!force_opt)
+ if (!force_opt) /* then mysqlbinlog dies */
{
*error= "Found invalid event in binary log";
DBUG_RETURN(0);
}
- ev= new Unknown_log_event(buf, old_format);
+ ev= new Unknown_log_event(buf, description_event);
#else
*error= "Found invalid event in binary log";
DBUG_RETURN(0);
#endif
}
- ev->cached_event_len = event_len;
DBUG_RETURN(ev);
}
@@ -724,7 +886,7 @@ void Log_event::print_header(FILE* file)
char llbuff[22];
fputc('#', file);
print_timestamp(file);
- fprintf(file, " server id %d log_pos %s ", server_id,
+ fprintf(file, " server id %d end_log_pos %s ", server_id,
llstr(log_pos,llbuff));
}
@@ -756,19 +918,6 @@ void Log_event::print_timestamp(FILE* file, time_t* ts)
#endif /* MYSQL_CLIENT */
-/*
- Log_event::set_log_pos()
-*/
-
-#ifndef MYSQL_CLIENT
-void Log_event::set_log_pos(MYSQL_LOG* log)
-{
- if (!log_pos)
- log_pos = my_b_tell(&log->log_file);
-}
-#endif /* !MYSQL_CLIENT */
-
-
/**************************************************************************
Query_log_event methods
**************************************************************************/
@@ -777,15 +926,20 @@ void Log_event::set_log_pos(MYSQL_LOG* log)
/*
Query_log_event::pack_info()
+ This (which is used only for SHOW BINLOG EVENTS) could be updated to
+ print SET @@session_var=. But this is not urgent, as SHOW BINLOG EVENTS is
+ only an information, it does not produce suitable queries to replay (for
+ example it does not print LOAD DATA INFILE).
*/
void Query_log_event::pack_info(Protocol *protocol)
{
+ // TODO: show the catalog ??
char *buf, *pos;
if (!(buf= my_malloc(9 + db_len + q_len, MYF(MY_WME))))
return;
- pos= buf;
- if (!(flags & LOG_EVENT_SUPPRESS_USE_F)
+ pos= buf;
+ if (!(flags & LOG_EVENT_SUPPRESS_USE_F)
&& db && db_len)
{
pos= strmov(buf, "use `");
@@ -802,34 +956,50 @@ void Query_log_event::pack_info(Protocol *protocol)
}
#endif
+#ifndef MYSQL_CLIENT
-/*
- Query_log_event::write()
-*/
-
-int Query_log_event::write(IO_CACHE* file)
+/* Utility function for the next method */
+static void write_str_with_code_and_len(char **dst, const char *src,
+ int len, uint code)
{
- return query ? Log_event::write(file) : -1;
+ DBUG_ASSERT(src);
+ *((*dst)++)= code;
+ *((*dst)++)= (uchar) len;
+ bmove(*dst, src, len);
+ (*dst)+= len;
}
/*
- Query_log_event::write_data()
+ Query_log_event::write()
+
+ NOTES:
+ In this event we have to modify the header to have the correct
+ EVENT_LEN_OFFSET as we don't yet know how many status variables we
+ will print!
*/
-int Query_log_event::write_data(IO_CACHE* file)
+bool Query_log_event::write(IO_CACHE* file)
{
- char buf[QUERY_HEADER_LEN];
+ uchar buf[QUERY_HEADER_LEN+
+ 1+4+ // code of flags2 and flags2
+ 1+8+ // code of sql_mode and sql_mode
+ 1+1+FN_REFLEN+ // code of catalog and catalog length and catalog
+ 1+4+ // code of autoinc and the 2 autoinc variables
+ 1+6+ // code of charset and charset
+ 1+1+MAX_TIME_ZONE_NAME_LENGTH // code of tz and tz length and tz name
+ ], *start, *start_of_status;
+ ulong event_length;
if (!query)
- return -1;
-
+ return 1; // Something wrong with event
+
/*
We want to store the thread id:
(- as an information for the user when he reads the binlog)
- if the query uses temporary table: for the slave SQL thread to know to
which master connection the temp table belongs.
- Now imagine we (write_data()) are called by the slave SQL thread (we are
+ Now imagine we (write()) are called by the slave SQL thread (we are
logging a query executed by this thread; the slave runs with
--log-slave-updates). Then this query will be logged with
thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of
@@ -866,78 +1036,334 @@ int Query_log_event::write_data(IO_CACHE* file)
buf[Q_DB_LEN_OFFSET] = (char) db_len;
int2store(buf + Q_ERR_CODE_OFFSET, error_code);
- return (my_b_safe_write(file, (byte*) buf, QUERY_HEADER_LEN) ||
- my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
- my_b_safe_write(file, (byte*) query, q_len)) ? -1 : 0;
+ /*
+ You MUST always write status vars in increasing order of code. This
+ guarantees that a slightly older slave will be able to parse those he
+ knows.
+ */
+ start_of_status= start= buf+QUERY_HEADER_LEN;
+ if (flags2_inited)
+ {
+ *start++= Q_FLAGS2_CODE;
+ int4store(start, flags2);
+ start+= 4;
+ }
+ if (sql_mode_inited)
+ {
+ *start++= Q_SQL_MODE_CODE;
+ int8store(start, (ulonglong)sql_mode);
+ start+= 8;
+ }
+ if (catalog_len) // i.e. this var is inited (false for 4.0 events)
+ {
+ write_str_with_code_and_len((char **)(&start),
+ catalog, catalog_len, Q_CATALOG_NZ_CODE);
+ /*
+ In 5.0.x where x<4 masters we used to store the end zero here. This was
+ a waste of one byte so we don't do it in x>=4 masters. We change code to
+ Q_CATALOG_NZ_CODE, because re-using the old code would make x<4 slaves
+ of this x>=4 master segfault (expecting a zero when there is
+ none). Remaining compatibility problems are: the older slave will not
+ find the catalog; but it is will not crash, and it's not an issue
+ that it does not find the catalog as catalogs were not used in these
+ older MySQL versions (we store it in binlog and read it from relay log
+ but do nothing useful with it). What is an issue is that the older slave
+ will stop processing the Q_* blocks (and jumps to the db/query) as soon
+ as it sees unknown Q_CATALOG_NZ_CODE; so it will not be able to read
+ Q_AUTO_INCREMENT*, Q_CHARSET and so replication will fail silently in
+ various ways. Documented that you should not mix alpha/beta versions if
+ they are not exactly the same version, with example of 5.0.3->5.0.2 and
+ 5.0.4->5.0.3. If replication is from older to new, the new will
+ recognize Q_CATALOG_CODE and have no problem.
+ */
+ }
+ if (auto_increment_increment != 1)
+ {
+ *start++= Q_AUTO_INCREMENT;
+ int2store(start, auto_increment_increment);
+ int2store(start+2, auto_increment_offset);
+ start+= 4;
+ }
+ if (charset_inited)
+ {
+ *start++= Q_CHARSET_CODE;
+ memcpy(start, charset, 6);
+ start+= 6;
+ }
+ if (time_zone_len)
+ {
+ /* In the TZ sys table, column Name is of length 64 so this should be ok */
+ DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
+ *start++= Q_TIME_ZONE_CODE;
+ *start++= time_zone_len;
+ memcpy(start, time_zone_str, time_zone_len);
+ start+= time_zone_len;
+ }
+ /*
+ Here there could be code like
+ if (command-line-option-which-says-"log_this_variable" && inited)
+ {
+ *start++= Q_THIS_VARIABLE_CODE;
+ int4store(start, this_variable);
+ start+= 4;
+ }
+ */
+
+ /* Store length of status variables */
+ status_vars_len= (uint) (start-start_of_status);
+ int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len);
+
+ /*
+ Calculate length of whole event
+ The "1" below is the \0 in the db's length
+ */
+ event_length= (uint) (start-buf) + get_post_header_size_for_derived() + db_len + 1 + q_len;
+
+ return (write_header(file, event_length) ||
+ my_b_safe_write(file, (byte*) buf, QUERY_HEADER_LEN) ||
+ write_post_header_for_derived(file) ||
+ my_b_safe_write(file, (byte*) start_of_status,
+ (uint) (start-start_of_status)) ||
+ my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
+ my_b_safe_write(file, (byte*) query, q_len)) ? 1 : 0;
}
/*
Query_log_event::Query_log_event()
*/
-
-#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans,
bool suppress_use)
- :Log_event(thd_arg,
+ :Log_event(thd_arg,
((thd_arg->tmp_table_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0)
| (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0)),
using_trans),
- data_buf(0), query(query_arg),
+ data_buf(0), query(query_arg), catalog(thd_arg->catalog),
db(thd_arg->db), q_len((uint32) query_length),
- error_code(thd_arg->killed ?
+ error_code((thd_arg->killed != THD::NOT_KILLED) ?
((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ?
- 0 : ER_SERVER_SHUTDOWN) : thd_arg->net.last_errno),
+ 0 : thd->killed_errno()) : thd_arg->net.last_errno),
thread_id(thd_arg->thread_id),
/* save the original thread id; we already know the server id */
- slave_proxy_id(thd_arg->variables.pseudo_thread_id)
+ slave_proxy_id(thd_arg->variables.pseudo_thread_id),
+ flags2_inited(1), sql_mode_inited(1), charset_inited(1),
+ sql_mode(thd_arg->variables.sql_mode),
+ auto_increment_increment(thd_arg->variables.auto_increment_increment),
+ auto_increment_offset(thd_arg->variables.auto_increment_offset)
{
time_t end_time;
time(&end_time);
exec_time = (ulong) (end_time - thd->start_time);
+ catalog_len = (catalog) ? (uint32) strlen(catalog) : 0;
+ /* status_vars_len is set just before writing the event */
db_len = (db) ? (uint32) strlen(db) : 0;
+ /*
+ If we don't use flags2 for anything else than options contained in
+ thd->options, it would be more efficient to flags2=thd_arg->options
+ (OPTIONS_WRITTEN_TO_BINLOG would be used only at reading time).
+ But it's likely that we don't want to use 32 bits for 3 bits; in the future
+ we will probably want to reclaim the 29 bits. So we need the &.
+ */
+ flags2= thd_arg->options & OPTIONS_WRITTEN_TO_BIN_LOG;
+ DBUG_ASSERT(thd->variables.character_set_client->number < 256*256);
+ DBUG_ASSERT(thd->variables.collation_connection->number < 256*256);
+ DBUG_ASSERT(thd->variables.collation_server->number < 256*256);
+ int2store(charset, thd_arg->variables.character_set_client->number);
+ int2store(charset+2, thd_arg->variables.collation_connection->number);
+ int2store(charset+4, thd_arg->variables.collation_server->number);
+ if (thd_arg->time_zone_used)
+ {
+ /*
+ Note that our event becomes dependent on the Time_zone object
+ representing the time zone. Fortunately such objects are never deleted
+ or changed during mysqld's lifetime.
+ */
+ time_zone_len= thd_arg->variables.time_zone->get_name()->length();
+ time_zone_str= thd_arg->variables.time_zone->get_name()->ptr();
+ }
+ else
+ time_zone_len= 0;
+ DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode));
}
#endif /* MYSQL_CLIENT */
+/* 2 utility functions for the next method */
+
+static void get_str_len_and_pointer(const char **dst, const char **src, uint *len)
+{
+ if ((*len= **src))
+ *dst= *src + 1; // Will be copied later
+ (*src)+= *len+1;
+}
+
+
+static void copy_str_and_move(char **dst, const char **src, uint len)
+{
+ memcpy(*dst, *src, len);
+ *src= *dst;
+ (*dst)+= len;
+ *(*dst)++= 0;
+}
+
+
/*
Query_log_event::Query_log_event()
+ This is used by the SQL slave thread to prepare the event before execution.
*/
-Query_log_event::Query_log_event(const char* buf, int event_len,
- bool old_format)
- :Log_event(buf, old_format),data_buf(0), query(NULL), db(NULL)
+Query_log_event::Query_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event,
+ Log_event_type event_type)
+ :Log_event(buf, description_event), data_buf(0), query(NullS),
+ db(NullS), catalog_len(0), status_vars_len(0),
+ flags2_inited(0), sql_mode_inited(0), charset_inited(0),
+ auto_increment_increment(1), auto_increment_offset(1),
+ time_zone_len(0)
{
ulong data_len;
- if (old_format)
- {
- if ((uint)event_len < OLD_HEADER_LEN + QUERY_HEADER_LEN)
- return;
- data_len = event_len - (QUERY_HEADER_LEN + OLD_HEADER_LEN);
- buf += OLD_HEADER_LEN;
- }
- else
- {
- if ((uint)event_len < QUERY_EVENT_OVERHEAD)
- return;
- data_len = event_len - QUERY_EVENT_OVERHEAD;
- buf += LOG_EVENT_HEADER_LEN;
- }
-
+ uint32 tmp;
+ uint8 common_header_len, post_header_len;
+ char *start;
+ const char *end;
+ bool catalog_nz= 1;
+ DBUG_ENTER("Query_log_event::Query_log_event(char*,...)");
+
+ common_header_len= description_event->common_header_len;
+ post_header_len= description_event->post_header_len[event_type-1];
+ DBUG_PRINT("info",("event_len=%ld, common_header_len=%d, post_header_len=%d",
+ event_len, common_header_len, post_header_len));
+
+ /*
+ We test if the event's length is sensible, and if so we compute data_len.
+ We cannot rely on QUERY_HEADER_LEN here as it would not be format-tolerant.
+ We use QUERY_HEADER_MINIMAL_LEN which is the same for 3.23, 4.0 & 5.0.
+ */
+ if (event_len < (uint)(common_header_len + post_header_len))
+ DBUG_VOID_RETURN;
+ data_len = event_len - (common_header_len + post_header_len);
+ buf+= common_header_len;
+
+ slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET);
exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET);
+ db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars
error_code = uint2korr(buf + Q_ERR_CODE_OFFSET);
- if (!(data_buf = (char*) my_malloc(data_len + 1, MYF(MY_WME))))
- return;
+ /*
+ 5.0 format starts here.
+ Depending on the format, we may or not have affected/warnings etc
+ The remnent post-header to be parsed has length:
+ */
+ tmp= post_header_len - QUERY_HEADER_MINIMAL_LEN;
+ if (tmp)
+ {
+ status_vars_len= uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
+ data_len-= status_vars_len;
+ DBUG_PRINT("info", ("Query_log_event has status_vars_len: %u",
+ (uint) status_vars_len));
+ tmp-= 2;
+ }
+ /*
+ We have parsed everything we know in the post header for QUERY_EVENT,
+ the rest of post header is either comes from older version MySQL or
+ dedicated to derived events (e.g. Execute_load_query...)
+ */
- memcpy(data_buf, buf + Q_DATA_OFFSET, data_len);
- slave_proxy_id= thread_id= uint4korr(buf + Q_THREAD_ID_OFFSET);
- db = data_buf;
- db_len = (uint)buf[Q_DB_LEN_OFFSET];
- query=data_buf + db_len + 1;
- q_len = data_len - 1 - db_len;
- *((char*)query+q_len) = 0;
+ /* variable-part: the status vars; only in MySQL 5.0 */
+
+ start= (char*) (buf+post_header_len);
+ end= (const char*) (start+status_vars_len);
+ for (const uchar* pos= (const uchar*) start; pos < (const uchar*) end;)
+ {
+ switch (*pos++) {
+ case Q_FLAGS2_CODE:
+ flags2_inited= 1;
+ flags2= uint4korr(pos);
+ DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", flags2));
+ pos+= 4;
+ break;
+ case Q_SQL_MODE_CODE:
+ {
+#ifndef DBUG_OFF
+ char buff[22];
+#endif
+ sql_mode_inited= 1;
+ sql_mode= (ulong) uint8korr(pos); // QQ: Fix when sql_mode is ulonglong
+ DBUG_PRINT("info",("In Query_log_event, read sql_mode: %s",
+ llstr(sql_mode, buff)));
+ pos+= 8;
+ break;
+ }
+ case Q_CATALOG_NZ_CODE:
+ get_str_len_and_pointer(&catalog, (const char **)(&pos), &catalog_len);
+ break;
+ case Q_AUTO_INCREMENT:
+ auto_increment_increment= uint2korr(pos);
+ auto_increment_offset= uint2korr(pos+2);
+ pos+= 4;
+ break;
+ case Q_CHARSET_CODE:
+ {
+ charset_inited= 1;
+ memcpy(charset, pos, 6);
+ pos+= 6;
+ break;
+ }
+ case Q_TIME_ZONE_CODE:
+ {
+ get_str_len_and_pointer(&time_zone_str, (const char **)(&pos), &time_zone_len);
+ break;
+ }
+ case Q_CATALOG_CODE: /* for 5.0.x where 0<=x<=3 masters */
+ if ((catalog_len= *pos))
+ catalog= (char*) pos+1; // Will be copied later
+ pos+= catalog_len+2; // leap over end 0
+ catalog_nz= 0; // catalog has end 0 in event
+ break;
+ default:
+ /* That's why you must write status vars in growing order of code */
+ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\
+ code: %u), skipping the rest of them", (uint) *(pos-1)));
+ pos= (const uchar*) end; // Break loop
+ }
+ }
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE)
+ if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 +
+ time_zone_len + 1 +
+ data_len + 1 +
+ QUERY_CACHE_FLAGS_SIZE +
+ db_len + 1,
+ MYF(MY_WME))))
+#else
+ if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 +
+ time_zone_len + 1 +
+ data_len + 1,
+ MYF(MY_WME))))
+#endif
+ DBUG_VOID_RETURN;
+ if (catalog_len) // If catalog is given
+ {
+ if (likely(catalog_nz)) // true except if event comes from 5.0.0|1|2|3.
+ copy_str_and_move(&start, &catalog, catalog_len);
+ else
+ {
+ memcpy(start, catalog, catalog_len+1); // copy end 0
+ catalog= start;
+ start+= catalog_len+1;
+ }
+ }
+ if (time_zone_len)
+ copy_str_and_move(&start, &time_zone_str, time_zone_len);
+
+ /* A 2nd variable part; this is common to all versions */
+ memcpy((char*) start, end, data_len); // Copy db and query
+ start[data_len]= '\0'; // End query with \0 (For safetly)
+ db= start;
+ query= start + db_len + 1;
+ q_len= data_len - db_len -1;
+ DBUG_VOID_RETURN;
}
@@ -946,30 +1372,27 @@ Query_log_event::Query_log_event(const char* buf, int event_len,
*/
#ifdef MYSQL_CLIENT
-void Query_log_event::print(FILE* file, bool short_form, char* last_db)
+void Query_log_event::print_query_header(FILE* file, bool short_form,
+ LAST_EVENT_INFO* last_event_info)
{
+ // TODO: print the catalog ??
char buff[40],*end; // Enough for SET TIMESTAMP
+ bool different_db= 1;
+ uint32 tmp;
+
if (!short_form)
{
print_header(file);
- fprintf(file, "\tQuery\tthread_id=%lu\texec_time=%lu\terror_code=%d\n",
- (ulong) thread_id, (ulong) exec_time, error_code);
+ fprintf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n",
+ get_type_str(), (ulong) thread_id, (ulong) exec_time, error_code);
}
- bool different_db= 1;
-
- if (!(flags & LOG_EVENT_SUPPRESS_USE_F))
+ if (!(flags & LOG_EVENT_SUPPRESS_USE_F) && db)
{
- if (db && last_db)
- {
- if (different_db= memcmp(last_db, db, db_len + 1))
- memcpy(last_db, db, db_len + 1);
- }
-
- if (db && db[0] && different_db)
- {
+ if (different_db= memcmp(last_event_info->db, db, db_len + 1))
+ memcpy(last_event_info->db, db, db_len + 1);
+ if (db[0] && different_db)
fprintf(file, "use %s;\n", db);
- }
}
end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10);
@@ -978,8 +1401,114 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
my_fwrite(file, (byte*) buff, (uint) (end-buff),MYF(MY_NABP | MY_WME));
if (flags & LOG_EVENT_THREAD_SPECIFIC_F)
fprintf(file,"SET @@session.pseudo_thread_id=%lu;\n",(ulong)thread_id);
+
+ /*
+ If flags2_inited==0, this is an event from 3.23 or 4.0; nothing to
+ print (remember we don't produce mixed relay logs so there cannot be
+ 5.0 events before that one so there is nothing to reset).
+ */
+ if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */
+ {
+ /* tmp is a bitmask of bits which have changed. */
+ if (likely(last_event_info->flags2_inited))
+ /* All bits which have changed */
+ tmp= (last_event_info->flags2) ^ flags2;
+ else /* that's the first Query event we read */
+ {
+ last_event_info->flags2_inited= 1;
+ tmp= ~((uint32)0); /* all bits have changed */
+ }
+
+ if (unlikely(tmp)) /* some bits have changed */
+ {
+ bool need_comma= 0;
+ fprintf(file, "SET ");
+ print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2,
+ "@@session.foreign_key_checks", &need_comma);
+ print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2,
+ "@@session.sql_auto_is_null", &need_comma);
+ print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2,
+ "@@session.unique_checks", &need_comma);
+ fprintf(file,";\n");
+ last_event_info->flags2= flags2;
+ }
+ }
+
+ /*
+ Now the session variables;
+ it's more efficient to pass SQL_MODE as a number instead of a
+ comma-separated list.
+ FOREIGN_KEY_CHECKS, SQL_AUTO_IS_NULL, UNIQUE_CHECKS are session-only
+ variables (they have no global version; they're not listed in
+ sql_class.h), The tests below work for pure binlogs or pure relay
+ logs. Won't work for mixed relay logs but we don't create mixed
+ relay logs (that is, there is no relay log with a format change
+ except within the 3 first events, which mysqlbinlog handles
+ gracefully). So this code should always be good.
+ */
+
+ if (likely(sql_mode_inited))
+ {
+ if (unlikely(!last_event_info->sql_mode_inited)) /* first Query event */
+ {
+ last_event_info->sql_mode_inited= 1;
+ /* force a difference to force write */
+ last_event_info->sql_mode= ~sql_mode;
+ }
+ if (unlikely(last_event_info->sql_mode != sql_mode))
+ {
+ fprintf(file,"SET @@session.sql_mode=%lu;\n",(ulong)sql_mode);
+ last_event_info->sql_mode= sql_mode;
+ }
+ }
+ if (last_event_info->auto_increment_increment != auto_increment_increment ||
+ last_event_info->auto_increment_offset != auto_increment_offset)
+ {
+ fprintf(file,"SET @@session.auto_increment_increment=%lu, @@session.auto_increment_offset=%lu;\n",
+ auto_increment_increment,auto_increment_offset);
+ last_event_info->auto_increment_increment= auto_increment_increment;
+ last_event_info->auto_increment_offset= auto_increment_offset;
+ }
+
+ /* TODO: print the catalog when we feature SET CATALOG */
+
+ if (likely(charset_inited))
+ {
+ if (unlikely(!last_event_info->charset_inited)) /* first Query event */
+ {
+ last_event_info->charset_inited= 1;
+ last_event_info->charset[0]= ~charset[0]; // force a difference to force write
+ }
+ if (unlikely(bcmp(last_event_info->charset, charset, 6)))
+ {
+ fprintf(file,"SET "
+ "@@session.character_set_client=%d,"
+ "@@session.collation_connection=%d,"
+ "@@session.collation_server=%d"
+ ";\n",
+ uint2korr(charset),
+ uint2korr(charset+2),
+ uint2korr(charset+4));
+ memcpy(last_event_info->charset, charset, 6);
+ }
+ }
+ if (time_zone_len)
+ {
+ if (bcmp(last_event_info->time_zone_str, time_zone_str, time_zone_len+1))
+ {
+ fprintf(file,"SET @@session.time_zone='%s';\n", time_zone_str);
+ memcpy(last_event_info->time_zone_str, time_zone_str, time_zone_len+1);
+ }
+ }
+}
+
+
+void Query_log_event::print(FILE* file, bool short_form,
+ LAST_EVENT_INFO* last_event_info)
+{
+ print_query_header(file, short_form, last_event_info);
my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
- fprintf(file, ";\n");
+ fputs(";\n", file);
}
#endif /* MYSQL_CLIENT */
@@ -991,21 +1520,38 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Query_log_event::exec_event(struct st_relay_log_info* rli)
{
+ return exec_event(rli, query, q_len);
+}
+
+
+int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query_arg, uint32 q_len_arg)
+{
int expected_error,actual_error= 0;
+ /*
+ Colleagues: please never free(thd->catalog) in MySQL. This would lead to
+ bugs as here thd->catalog is a part of an alloced block, not an entire
+ alloced block (see Query_log_event::exec_event()). Same for thd->db.
+ Thank you.
+ */
+ thd->catalog= catalog_len ? (char *) catalog : (char *)"";
thd->db_length= db_len;
thd->db= (char*) rewrite_db(db, &thd->db_length);
+ thd->variables.auto_increment_increment= auto_increment_increment;
+ thd->variables.auto_increment_offset= auto_increment_offset;
/*
- InnoDB internally stores the master log position it has processed so far;
- position to store is of the END of the current log event.
+ InnoDB internally stores the master log position it has executed so far,
+ i.e. the position just after the COMMIT event.
+ When InnoDB will want to store, the positions in rli won't have
+ been updated yet, so group_master_log_* will point to old BEGIN
+ and event_master_log* will point to the beginning of current COMMIT.
+ But log_pos of the COMMIT Query event is what we want, i.e. the pos of the
+ END of the current log event (COMMIT). We save it in rli so that InnoDB can
+ access it.
*/
-#if MYSQL_VERSION_ID < 50000
- rli->future_group_master_log_pos= log_pos + get_event_len() -
- (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0);
-#else
- /* In 5.0 we store the end_log_pos in the relay log so no problem */
rli->future_group_master_log_pos= log_pos;
-#endif
+ DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
+
clear_all_errors(thd, rli);
/*
@@ -1021,17 +1567,79 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
thd->set_time((time_t)when);
- thd->query_length= q_len;
- thd->query = (char*)query;
+ thd->query_length= q_len_arg;
+ thd->query= (char*)query_arg;
VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query_id = query_id++;
+ thd->query_id = next_query_id();
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->variables.pseudo_thread_id= thread_id; // for temp tables
-
DBUG_PRINT("query",("%s",thd->query));
+
if (ignored_error_code((expected_error= error_code)) ||
!check_expected_error(thd,rli,expected_error))
- mysql_parse(thd, thd->query, q_len);
+ {
+ if (flags2_inited)
+ /*
+ all bits of thd->options which are 1 in OPTIONS_WRITTEN_TO_BIN_LOG must
+ take their value from flags2.
+ */
+ thd->options= flags2|(thd->options & ~(ulong)OPTIONS_WRITTEN_TO_BIN_LOG);
+ /*
+ else, we are in a 3.23/4.0 binlog; we previously received a
+ Rotate_log_event which reset thd->options and sql_mode etc, so nothing to do.
+ */
+ /*
+ We do not replicate IGNORE_DIR_IN_CREATE. That is, if the master is a
+ slave which runs with SQL_MODE=IGNORE_DIR_IN_CREATE, this should not
+ force us to ignore the dir too. Imagine you are a ring of machines, and
+ one has a disk problem so that you temporarily need IGNORE_DIR_IN_CREATE
+ on this machine; you don't want it to propagate elsewhere (you don't want
+ all slaves to start ignoring the dirs).
+ */
+ if (sql_mode_inited)
+ thd->variables.sql_mode=
+ (ulong) ((thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) |
+ (sql_mode & ~(ulong) MODE_NO_DIR_IN_CREATE));
+ if (charset_inited)
+ {
+ if (rli->cached_charset_compare(charset))
+ {
+ /* Verify that we support the charsets found in the event. */
+ if (!(thd->variables.character_set_client=
+ get_charset(uint2korr(charset), MYF(MY_WME))) ||
+ !(thd->variables.collation_connection=
+ get_charset(uint2korr(charset+2), MYF(MY_WME))) ||
+ !(thd->variables.collation_server=
+ get_charset(uint2korr(charset+4), MYF(MY_WME))))
+ {
+ /*
+ We updated the thd->variables with nonsensical values (0). Let's
+ set them to something safe (i.e. which avoids crash), and we'll
+ stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
+ ignore this error).
+ */
+ set_slave_thread_default_charset(thd, rli);
+ goto compare_errors;
+ }
+ thd->update_charset(); // for the charset change to take effect
+ }
+ }
+ if (time_zone_len)
+ {
+ String tmp(time_zone_str, time_zone_len, &my_charset_bin);
+ if (!(thd->variables.time_zone=
+ my_tz_find_with_opening_tz_tables(thd, &tmp)))
+ {
+ my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
+ thd->variables.time_zone= global_system_variables.time_zone;
+ goto compare_errors;
+ }
+ }
+
+ /* Execute the query (note that we bypass dispatch_command()) */
+ mysql_parse(thd, thd->query, thd->query_length);
+
+ }
else
{
/*
@@ -1041,7 +1649,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
we exit gracefully; otherwise we warn about the bad error and tell DBA
to check/fix it.
*/
- if (mysql_test_parse_for_slave(thd, thd->query, q_len))
+ if (mysql_test_parse_for_slave(thd, thd->query, thd->query_length))
clear_all_errors(thd, rli); /* Can ignore query */
else
{
@@ -1061,19 +1669,21 @@ START SLAVE; . Query: '%s'", expected_error, thd->query);
if (thd->net.last_errno != ER_SLAVE_IGNORED_TABLE)
mysql_log.write(thd,COM_QUERY,"%s",thd->query);
- /*
+compare_errors:
+
+ /*
If we expected a non-zero error code, and we don't get the same error
code, and none of them should be ignored.
*/
DBUG_PRINT("info",("expected_error: %d last_errno: %d",
- expected_error, thd->net.last_errno));
+ expected_error, thd->net.last_errno));
if ((expected_error != (actual_error= thd->net.last_errno)) &&
- expected_error &&
- !ignored_error_code(actual_error) &&
- !ignored_error_code(expected_error))
+ expected_error &&
+ !ignored_error_code(actual_error) &&
+ !ignored_error_code(expected_error))
{
slave_print_error(rli, 0,
- "\
+ "\
Query caused different errors on master and slave. \
Error on master: '%s' (%d), Error on slave: '%s' (%d). \
Default database: '%s'. Query: '%s'",
@@ -1081,14 +1691,14 @@ Default database: '%s'. Query: '%s'",
expected_error,
actual_error ? thd->net.last_error: "no error",
actual_error,
- print_slave_db_safe(thd->db), query);
+ print_slave_db_safe(db), query_arg);
thd->query_error= 1;
}
/*
If we get the same error code as expected, or they should be ignored.
*/
else if (expected_error == actual_error ||
- ignored_error_code(actual_error))
+ ignored_error_code(actual_error))
{
DBUG_PRINT("info",("error ignored"));
clear_all_errors(thd, rli);
@@ -1102,14 +1712,46 @@ Default database: '%s'. Query: '%s'",
"Error '%s' on query. Default database: '%s'. Query: '%s'",
(actual_error ? thd->net.last_error :
"unexpected success or fatal error"),
- print_slave_db_safe(thd->db), query);
+ print_slave_db_safe(thd->db), query_arg);
thd->query_error= 1;
}
+
+ /*
+ TODO: compare the values of "affected rows" around here. Something
+ like:
+ if ((uint32) affected_in_event != (uint32) affected_on_slave)
+ {
+ sql_print_error("Slave: did not get the expected number of affected \
+ rows running query from master - expected %d, got %d (this numbers \
+ should have matched modulo 4294967296).", 0, ...);
+ thd->query_error = 1;
+ }
+ We may also want an option to tell the slave to ignore "affected"
+ mismatch. This mismatch could be implemented with a new ER_ code, and
+ to ignore it you would use --slave-skip-errors...
+
+ To do the comparison we need to know the value of "affected" which the
+ above mysql_parse() computed. And we need to know the value of
+ "affected" in the master's binlog. Both will be implemented later. The
+ important thing is that we now have the format ready to log the values
+ of "affected" in the binlog. So we can release 5.0.0 before effectively
+ logging "affected" and effectively comparing it.
+ */
} /* End of if (db_ok(... */
end:
VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->db= 0; // prevent db from being freed
+ /*
+ Probably we have set thd->query, thd->db, thd->catalog to point to places
+ in the data_buf of this event. Now the event is going to be deleted
+ probably, so data_buf will be freed, so the thd->... listed above will be
+ pointers to freed memory.
+ So we must set them to 0, so that those bad pointers values are not later
+ used. Note that "cleanup" queries like automatic DROP TEMPORARY TABLE
+ don't suffer from these assignments to 0 as DROP TEMPORARY
+ TABLE uses the db.table syntax.
+ */
+ thd->db= thd->catalog= 0; // prevent db from being freed
thd->query= 0; // just to be sure
thd->query_length= thd->db_length =0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
@@ -1122,22 +1764,30 @@ end:
updating query.
*/
return (thd->query_error ? thd->query_error :
- (thd->one_shot_set ? (rli->inc_event_relay_log_pos(get_event_len()),0) :
+ (thd->one_shot_set ? (rli->inc_event_relay_log_pos(),0) :
Log_event::exec_event(rli)));
}
#endif
/**************************************************************************
- Start_log_event methods
+ Start_log_event_v3 methods
**************************************************************************/
+#ifndef MYSQL_CLIENT
+Start_log_event_v3::Start_log_event_v3() :Log_event(), binlog_version(BINLOG_VERSION), artificial_event(0)
+{
+ created= when;
+ memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
+}
+#endif
+
/*
- Start_log_event::pack_info()
+ Start_log_event_v3::pack_info()
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Start_log_event::pack_info(Protocol *protocol)
+void Start_log_event_v3::pack_info(Protocol *protocol)
{
char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
pos= strmov(buf, "Server ver: ");
@@ -1150,57 +1800,80 @@ void Start_log_event::pack_info(Protocol *protocol)
/*
- Start_log_event::print()
+ Start_log_event_v3::print()
*/
#ifdef MYSQL_CLIENT
-void Start_log_event::print(FILE* file, bool short_form, char* last_db)
+void Start_log_event_v3::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
{
- if (short_form)
- return;
-
- print_header(file);
- fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version,
- server_version);
- print_timestamp(file);
- if (created)
- fprintf(file," at startup");
- fputc('\n', file);
+ if (!short_form)
+ {
+ print_header(file);
+ fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version,
+ server_version);
+ print_timestamp(file);
+ if (created)
+ fprintf(file," at startup");
+ fputc('\n', file);
+ if (flags & LOG_EVENT_BINLOG_IN_USE_F)
+ fprintf(file, "# Warning: this binlog was not closed properly. "
+ "Most probably mysqld crashed writing it.\n");
+ }
+ if (!artificial_event && created)
+ {
+#ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND
+ /*
+ This is for mysqlbinlog: like in replication, we want to delete the stale
+ tmp files left by an unclean shutdown of mysqld (temporary tables)
+ and rollback unfinished transaction.
+ Probably this can be done with RESET CONNECTION (syntax to be defined).
+ */
+ fprintf(file,"RESET CONNECTION;\n");
+#else
+ fprintf(file,"ROLLBACK;\n");
+#endif
+ }
fflush(file);
}
#endif /* MYSQL_CLIENT */
/*
- Start_log_event::Start_log_event()
+ Start_log_event_v3::Start_log_event_v3()
*/
-Start_log_event::Start_log_event(const char* buf,
- bool old_format)
- :Log_event(buf, old_format)
+Start_log_event_v3::Start_log_event_v3(const char* buf,
+ const Format_description_log_event* description_event)
+ :Log_event(buf, description_event)
{
- buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
- binlog_version = uint2korr(buf+ST_BINLOG_VER_OFFSET);
+ buf+= description_event->common_header_len;
+ binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
ST_SERVER_VER_LEN);
- created = uint4korr(buf+ST_CREATED_OFFSET);
+ created= uint4korr(buf+ST_CREATED_OFFSET);
+ /* We use log_pos to mark if this was an artificial event or not */
+ artificial_event= (log_pos == 0);
}
/*
- Start_log_event::write_data()
+ Start_log_event_v3::write()
*/
-int Start_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool Start_log_event_v3::write(IO_CACHE* file)
{
- char buff[START_HEADER_LEN];
+ char buff[START_V3_HEADER_LEN];
int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
int4store(buff + ST_CREATED_OFFSET,created);
- return (my_b_safe_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
+ return (write_header(file, sizeof(buff)) ||
+ my_b_safe_write(file, (byte*) buff, sizeof(buff)));
}
+#endif
+
/*
- Start_log_event::exec_event()
+ Start_log_event_v3::exec_event()
The master started
@@ -1219,84 +1892,321 @@ int Start_log_event::write_data(IO_CACHE* file)
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Start_log_event::exec_event(struct st_relay_log_info* rli)
+int Start_log_event_v3::exec_event(struct st_relay_log_info* rli)
{
- DBUG_ENTER("Start_log_event::exec_event");
-
- /*
- If the I/O thread has not started, mi->old_format is BINLOG_FORMAT_CURRENT
- (that's what the MASTER_INFO constructor does), so the test below is not
- perfect at all.
- */
- switch (rli->mi->old_format) {
- case BINLOG_FORMAT_CURRENT:
- /*
- This is 4.x, so a Start_log_event is only at master startup,
- so we are sure the master has restarted and cleared his temp tables.
- */
- close_temporary_tables(thd);
- cleanup_load_tmpdir();
+ DBUG_ENTER("Start_log_event_v3::exec_event");
+ switch (binlog_version)
+ {
+ case 3:
+ case 4:
/*
- As a transaction NEVER spans on 2 or more binlogs:
- if we have an active transaction at this point, the master died while
- writing the transaction to the binary log, i.e. while flushing the binlog
- cache to the binlog. As the write was started, the transaction had been
- committed on the master, so we lack of information to replay this
- transaction on the slave; all we can do is stop with error.
+ This can either be 4.x (then a Start_log_event_v3 is only at master
+ startup so we are sure the master has restarted and cleared his temp
+ tables; the event always has 'created'>0) or 5.0 (then we have to test
+ 'created').
*/
- if (thd->options & OPTION_BEGIN)
+ if (created)
{
- slave_print_error(rli, 0, "\
-Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. \
-A probable cause is that the master died while writing the transaction to its \
-binary log.");
- return(1);
+ close_temporary_tables(thd);
+ cleanup_load_tmpdir();
}
break;
- /*
+ /*
Now the older formats; in that case load_tmpdir is cleaned up by the I/O
thread.
*/
- case BINLOG_FORMAT_323_LESS_57:
- /*
- Cannot distinguish a Start_log_event generated at master startup and
- one generated by master FLUSH LOGS, so cannot be sure temp tables
- have to be dropped. So do nothing.
- */
- break;
- case BINLOG_FORMAT_323_GEQ_57:
+ case 1:
+ if (strncmp(rli->relay_log.description_event_for_exec->server_version,
+ "3.23.57",7) >= 0 && created)
+ {
+ /*
+ Can distinguish, based on the value of 'created': this event was
+ generated at master startup.
+ */
+ close_temporary_tables(thd);
+ }
/*
- Can distinguish, based on the value of 'created',
- which was generated at master startup.
+ Otherwise, can't distinguish a Start_log_event generated at
+ master startup and one generated by master FLUSH LOGS, so cannot
+ be sure temp tables have to be dropped. So do nothing.
*/
- if (created)
- close_temporary_tables(thd);
break;
default:
/* this case is impossible */
- return 1;
+ DBUG_RETURN(1);
}
-
DBUG_RETURN(Log_event::exec_event(rli));
}
#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
-/**************************************************************************
- Load_log_event methods
-**************************************************************************/
+/***************************************************************************
+ Format_description_log_event methods
+****************************************************************************/
/*
- Load_log_event::pack_info()
+ Format_description_log_event 1st ctor.
+
+ SYNOPSIS
+ Format_description_log_event::Format_description_log_event
+ binlog_version the binlog version for which we want to build
+ an event. Can be 1 (=MySQL 3.23), 3 (=4.0.x
+ x>=2 and 4.1) or 4 (MySQL 5.0). Note that the
+ old 4.0 (binlog version 2) is not supported;
+ it should not be used for replication with
+ 5.0.
+
+ DESCRIPTION
+ Ctor. Can be used to create the event to write to the binary log (when the
+ server starts or when FLUSH LOGS), or to create artificial events to parse
+ binlogs from MySQL 3.23 or 4.x.
+ When in a client, only the 2nd use is possible.
+*/
+
+Format_description_log_event::
+Format_description_log_event(uint8 binlog_ver, const char* server_ver)
+ :Start_log_event_v3()
+{
+ created= when;
+ binlog_version= binlog_ver;
+ switch (binlog_ver) {
+ case 4: /* MySQL 5.0 */
+ memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
+ common_header_len= LOG_EVENT_HEADER_LEN;
+ number_of_event_types= LOG_EVENT_TYPES;
+ /* we'll catch my_malloc() error in is_valid() */
+ post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8),
+ MYF(MY_ZEROFILL));
+ /*
+ This long list of assignments is not beautiful, but I see no way to
+ make it nicer, as the right members are #defines, not array members, so
+ it's impossible to write a loop.
+ */
+ if (post_header_len)
+ {
+ post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN;
+ post_header_len[QUERY_EVENT-1]= QUERY_HEADER_LEN;
+ post_header_len[ROTATE_EVENT-1]= ROTATE_HEADER_LEN;
+ post_header_len[LOAD_EVENT-1]= LOAD_HEADER_LEN;
+ post_header_len[CREATE_FILE_EVENT-1]= CREATE_FILE_HEADER_LEN;
+ post_header_len[APPEND_BLOCK_EVENT-1]= APPEND_BLOCK_HEADER_LEN;
+ post_header_len[EXEC_LOAD_EVENT-1]= EXEC_LOAD_HEADER_LEN;
+ post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN;
+ post_header_len[NEW_LOAD_EVENT-1]= post_header_len[LOAD_EVENT-1];
+ post_header_len[FORMAT_DESCRIPTION_EVENT-1]= FORMAT_DESCRIPTION_HEADER_LEN;
+ post_header_len[BEGIN_LOAD_QUERY_EVENT-1]= post_header_len[APPEND_BLOCK_EVENT-1];
+ post_header_len[EXECUTE_LOAD_QUERY_EVENT-1]= EXECUTE_LOAD_QUERY_HEADER_LEN;
+ }
+ break;
+
+ case 1: /* 3.23 */
+ case 3: /* 4.0.x x>=2 */
+ /*
+ We build an artificial (i.e. not sent by the master) event, which
+ describes what those old master versions send.
+ */
+ if (binlog_ver==1)
+ strmov(server_version, server_ver ? server_ver : "3.23");
+ else
+ strmov(server_version, server_ver ? server_ver : "4.0");
+ common_header_len= binlog_ver==1 ? OLD_HEADER_LEN :
+ LOG_EVENT_MINIMAL_HEADER_LEN;
+ /*
+ The first new event in binlog version 4 is Format_desc. So any event type
+ after that does not exist in older versions. We use the events known by
+ version 3, even if version 1 had only a subset of them (this is not a
+ problem: it uses a few bytes for nothing but unifies code; it does not
+ make the slave detect less corruptions).
+ */
+ number_of_event_types= FORMAT_DESCRIPTION_EVENT - 1;
+ post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8),
+ MYF(0));
+ if (post_header_len)
+ {
+ post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN;
+ post_header_len[QUERY_EVENT-1]= QUERY_HEADER_MINIMAL_LEN;
+ post_header_len[STOP_EVENT-1]= 0;
+ post_header_len[ROTATE_EVENT-1]= (binlog_ver==1) ? 0 : ROTATE_HEADER_LEN;
+ post_header_len[INTVAR_EVENT-1]= 0;
+ post_header_len[LOAD_EVENT-1]= LOAD_HEADER_LEN;
+ post_header_len[SLAVE_EVENT-1]= 0;
+ post_header_len[CREATE_FILE_EVENT-1]= CREATE_FILE_HEADER_LEN;
+ post_header_len[APPEND_BLOCK_EVENT-1]= APPEND_BLOCK_HEADER_LEN;
+ post_header_len[EXEC_LOAD_EVENT-1]= EXEC_LOAD_HEADER_LEN;
+ post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN;
+ post_header_len[NEW_LOAD_EVENT-1]= post_header_len[LOAD_EVENT-1];
+ post_header_len[RAND_EVENT-1]= 0;
+ post_header_len[USER_VAR_EVENT-1]= 0;
+ }
+ break;
+ default: /* Includes binlog version 2 i.e. 4.0.x x<=1 */
+ post_header_len= 0; /* will make is_valid() fail */
+ break;
+ }
+}
+
+
+/*
+ The problem with this constructor is that the fixed header may have a
+ length different from this version, but we don't know this length as we
+ have not read the Format_description_log_event which says it, yet. This
+ length is in the post-header of the event, but we don't know where the
+ post-header starts.
+ So this type of event HAS to:
+ - either have the header's length at the beginning (in the header, at a
+ fixed position which will never be changed), not in the post-header. That
+ would make the header be "shifted" compared to other events.
+ - or have a header of size LOG_EVENT_MINIMAL_HEADER_LEN (19), in all future
+ versions, so that we know for sure.
+ I (Guilhem) chose the 2nd solution. Rotate has the same constraint (because
+ it is sent before Format_description_log_event).
+*/
+
+Format_description_log_event::
+Format_description_log_event(const char* buf,
+ uint event_len,
+ const
+ Format_description_log_event*
+ description_event)
+ :Start_log_event_v3(buf, description_event)
+{
+ DBUG_ENTER("Format_description_log_event::Format_description_log_event(char*,...)");
+ buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
+ if ((common_header_len=buf[ST_COMMON_HEADER_LEN_OFFSET]) < OLD_HEADER_LEN)
+ DBUG_VOID_RETURN; /* sanity check */
+ number_of_event_types=
+ event_len-(LOG_EVENT_MINIMAL_HEADER_LEN+ST_COMMON_HEADER_LEN_OFFSET+1);
+ DBUG_PRINT("info", ("common_header_len=%d number_of_event_types=%d",
+ common_header_len, number_of_event_types));
+ /* If alloc fails, we'll detect it in is_valid() */
+ post_header_len= (uint8*) my_memdup((byte*)buf+ST_COMMON_HEADER_LEN_OFFSET+1,
+ number_of_event_types*
+ sizeof(*post_header_len), MYF(0));
+ DBUG_VOID_RETURN;
+}
+
+#ifndef MYSQL_CLIENT
+bool Format_description_log_event::write(IO_CACHE* file)
+{
+ /*
+ We don't call Start_log_event_v3::write() because this would make 2
+ my_b_safe_write().
+ */
+ byte buff[FORMAT_DESCRIPTION_HEADER_LEN];
+ int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
+ memcpy((char*) buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
+ int4store(buff + ST_CREATED_OFFSET,created);
+ buff[ST_COMMON_HEADER_LEN_OFFSET]= LOG_EVENT_HEADER_LEN;
+ memcpy((char*) buff+ST_COMMON_HEADER_LEN_OFFSET+1, (byte*) post_header_len,
+ LOG_EVENT_TYPES);
+ return (write_header(file, sizeof(buff)) ||
+ my_b_safe_write(file, buff, sizeof(buff)));
+}
+#endif
+
+/*
+ SYNOPSIS
+ Format_description_log_event::exec_event()
+
+ IMPLEMENTATION
+ Save the information which describes the binlog's format, to be able to
+ read all coming events.
+ Call Start_log_event_v3::exec_event().
*/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-void Load_log_event::pack_info(Protocol *protocol)
+int Format_description_log_event::exec_event(struct st_relay_log_info* rli)
{
- char *buf, *pos;
- uint buf_len;
+ DBUG_ENTER("Format_description_log_event::exec_event");
+
+ /* save the information describing this binlog */
+ delete rli->relay_log.description_event_for_exec;
+ rli->relay_log.description_event_for_exec= this;
- buf_len=
+#ifdef USING_TRANSACTIONS
+ /*
+ As a transaction NEVER spans on 2 or more binlogs:
+ if we have an active transaction at this point, the master died
+ while writing the transaction to the binary log, i.e. while
+ flushing the binlog cache to the binlog. As the write was started,
+ the transaction had been committed on the master, so we lack of
+ information to replay this transaction on the slave; all we can do
+ is stop with error.
+ Note: this event could be sent by the master to inform us of the
+ format of its binlog; in other words maybe it is not at its
+ original place when it comes to us; we'll know this by checking
+ log_pos ("artificial" events have log_pos == 0).
+ */
+ if (!artificial_event && created && thd->transaction.all.nht)
+ {
+ slave_print_error(rli, 0, "Rolling back unfinished transaction (no "
+ "COMMIT or ROLLBACK) from relay log. A probable cause "
+ "is that the master died while writing the transaction "
+ "to its binary log.");
+ end_trans(thd, ROLLBACK);
+ }
+#endif
+ /*
+ If this event comes from ourselves, there is no cleaning task to perform,
+ we don't call Start_log_event_v3::exec_event() (this was just to update the
+ log's description event).
+ */
+ if (server_id == (uint32) ::server_id)
+ {
+ /*
+ Do not modify rli->group_master_log_pos, as this event did not exist on
+ the master. That is, just update the *relay log* coordinates; this is
+ done by passing log_pos=0 to inc_group_relay_log_pos, like we do in
+ Stop_log_event::exec_event().
+ If in a transaction, don't touch group_* coordinates.
+ */
+ if (thd->options & OPTION_BEGIN)
+ rli->inc_event_relay_log_pos();
+ else
+ {
+ rli->inc_group_relay_log_pos(0);
+ flush_relay_log_info(rli);
+ }
+ DBUG_RETURN(0);
+ }
+
+ /*
+ If the event was not requested by the slave i.e. the master sent it while
+ the slave asked for a position >4, the event will make
+ rli->group_master_log_pos advance. Say that the slave asked for position
+ 1000, and the Format_desc event's end is 96. Then in the beginning of
+ replication rli->group_master_log_pos will be 0, then 96, then jump to
+ first really asked event (which is >96). So this is ok.
+ */
+ DBUG_RETURN(Start_log_event_v3::exec_event(rli));
+}
+#endif
+
+ /**************************************************************************
+ Load_log_event methods
+ General note about Load_log_event: the binlogging of LOAD DATA INFILE is
+ going to be changed in 5.0 (or maybe in 5.1; not decided yet).
+ However, the 5.0 slave could still have to read such events (from a 4.x
+ master), convert them (which just means maybe expand the header, when 5.0
+ servers have a UID in events) (remember that whatever is after the header
+ will be like in 4.x, as this event's format is not modified in 5.0 as we
+ will use new types of events to log the new LOAD DATA INFILE features).
+ To be able to read/convert, we just need to not assume that the common
+ header is of length LOG_EVENT_HEADER_LEN (we must use the description
+ event).
+ Note that I (Guilhem) manually tested replication of a big LOAD DATA INFILE
+ between 3.23 and 5.0, and between 4.0 and 5.0, and it works fine (and the
+ positions displayed in SHOW SLAVE STATUS then are fine too).
+ **************************************************************************/
+
+/*
+ Load_log_event::pack_info()
+*/
+
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+uint Load_log_event::get_query_buffer_length()
+{
+ return
5 + db_len + 3 + // "use DB; "
18 + fname_len + 2 + // "LOAD DATA INFILE 'file''"
7 + // LOCAL
@@ -1306,14 +2216,18 @@ void Load_log_event::pack_info(Protocol *protocol)
23 + sql_ex.enclosed_len*4 + 2 + // " OPTIONALLY ENCLOSED BY 'str'"
12 + sql_ex.escaped_len*4 + 2 + // " ESCAPED BY 'str'"
21 + sql_ex.line_term_len*4 + 2 + // " FIELDS TERMINATED BY 'str'"
- 19 + sql_ex.line_start_len*4 + 2 + // " LINES STARTING BY 'str'"
- 15 + 22 + // " IGNORE xxx LINES"
+ 19 + sql_ex.line_start_len*4 + 2 + // " LINES STARTING BY 'str'"
+ 15 + 22 + // " IGNORE xxx LINES"
3 + (num_fields-1)*2 + field_block_len; // " (field1, field2, ...)"
+}
- if (!(buf= my_malloc(buf_len, MYF(MY_WME))))
- return;
- pos= buf;
- if (db && db_len)
+
+void Load_log_event::print_query(bool need_db, char *buf,
+ char **end, char **fn_start, char **fn_end)
+{
+ char *pos= buf;
+
+ if (need_db && db && db_len)
{
pos= strmov(pos, "use `");
memcpy(pos, db, db_len);
@@ -1321,6 +2235,10 @@ void Load_log_event::pack_info(Protocol *protocol)
}
pos= strmov(pos, "LOAD DATA ");
+
+ if (fn_start)
+ *fn_start= pos;
+
if (check_fname_outside_temp_buf())
pos= strmov(pos, "LOCAL ");
pos= strmov(pos, "INFILE '");
@@ -1332,7 +2250,12 @@ void Load_log_event::pack_info(Protocol *protocol)
else if (sql_ex.opt_flags & IGNORE_FLAG)
pos= strmov(pos, " IGNORE ");
- pos= strmov(pos ,"INTO TABLE `");
+ pos= strmov(pos ,"INTO");
+
+ if (fn_end)
+ *fn_end= pos;
+
+ pos= strmov(pos ," TABLE `");
memcpy(pos, table_name, table_name_len);
pos+= table_name_len;
@@ -1381,17 +2304,30 @@ void Load_log_event::pack_info(Protocol *protocol)
*pos++= ')';
}
- protocol->store(buf, pos-buf, &my_charset_bin);
+ *end= pos;
+}
+
+
+void Load_log_event::pack_info(Protocol *protocol)
+{
+ char *buf, *end;
+
+ if (!(buf= my_malloc(get_query_buffer_length(), MYF(MY_WME))))
+ return;
+ print_query(TRUE, buf, &end, 0, 0);
+ protocol->store(buf, end-buf, &my_charset_bin);
my_free(buf, MYF(0));
}
#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
+#ifndef MYSQL_CLIENT
+
/*
Load_log_event::write_data_header()
*/
-int Load_log_event::write_data_header(IO_CACHE* file)
+bool Load_log_event::write_data_header(IO_CACHE* file)
{
char buf[LOAD_HEADER_LEN];
int4store(buf + L_THREAD_ID_OFFSET, slave_proxy_id);
@@ -1400,7 +2336,7 @@ int Load_log_event::write_data_header(IO_CACHE* file)
buf[L_TBL_LEN_OFFSET] = (char)table_name_len;
buf[L_DB_LEN_OFFSET] = (char)db_len;
int4store(buf + L_NUM_FIELDS_OFFSET, num_fields);
- return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN);
+ return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN) != 0;
}
@@ -1408,7 +2344,7 @@ int Load_log_event::write_data_header(IO_CACHE* file)
Load_log_event::write_data_body()
*/
-int Load_log_event::write_data_body(IO_CACHE* file)
+bool Load_log_event::write_data_body(IO_CACHE* file)
{
if (sql_ex.write_data(file))
return 1;
@@ -1428,7 +2364,6 @@ int Load_log_event::write_data_body(IO_CACHE* file)
Load_log_event::Load_log_event()
*/
-#ifndef MYSQL_CLIENT
Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
const char *db_arg, const char *table_name_arg,
List<Item> &fields_arg,
@@ -1512,6 +2447,7 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
}
#endif /* !MYSQL_CLIENT */
+
/*
Load_log_event::Load_log_event()
@@ -1520,15 +2456,25 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
constructed event.
*/
-Load_log_event::Load_log_event(const char *buf, int event_len,
- bool old_format)
- :Log_event(buf, old_format), num_fields(0), fields(0),
- field_lens(0), field_block_len(0),
+Load_log_event::Load_log_event(const char *buf, uint event_len,
+ const Format_description_log_event *description_event)
+ :Log_event(buf, description_event), num_fields(0), fields(0),
+ field_lens(0),field_block_len(0),
table_name(0), db(0), fname(0), local_fname(FALSE)
{
DBUG_ENTER("Load_log_event");
- if (event_len) // derived class, will call copy_log_event() itself
- copy_log_event(buf, event_len, old_format);
+ /*
+ I (Guilhem) manually tested replication of LOAD DATA INFILE for 3.23->5.0,
+ 4.0->5.0 and 5.0->5.0 and it works.
+ */
+ if (event_len)
+ copy_log_event(buf, event_len,
+ ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
+ LOAD_HEADER_LEN +
+ description_event->common_header_len :
+ LOAD_HEADER_LEN + LOG_EVENT_HEADER_LEN),
+ description_event);
+ /* otherwise it's a derived class, will call copy_log_event() itself */
DBUG_VOID_RETURN;
}
@@ -1538,14 +2484,14 @@ Load_log_event::Load_log_event(const char *buf, int event_len,
*/
int Load_log_event::copy_log_event(const char *buf, ulong event_len,
- bool old_format)
+ int body_offset,
+ const Format_description_log_event *description_event)
{
+ DBUG_ENTER("Load_log_event::copy_log_event");
uint data_len;
char* buf_end = (char*)buf + event_len;
- uint header_len= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
- const char* data_head = buf + header_len;
- DBUG_ENTER("Load_log_event::copy_log_event");
-
+ /* this is the beginning of the post-header */
+ const char* data_head = buf + description_event->common_header_len;
slave_proxy_id= thread_id= uint4korr(data_head + L_THREAD_ID_OFFSET);
exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET);
skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET);
@@ -1553,21 +2499,17 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
db_len = (uint)data_head[L_DB_LEN_OFFSET];
num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET);
- int body_offset = ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
- LOAD_HEADER_LEN + header_len :
- get_data_body_offset());
-
if ((int) event_len < body_offset)
DBUG_RETURN(1);
/*
Sql_ex.init() on success returns the pointer to the first byte after
the sql_ex structure, which is the start of field lengths array.
*/
- if (!(field_lens=(uchar*)sql_ex.init((char*)buf + body_offset,
- buf_end,
- buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
+ if (!(field_lens= (uchar*)sql_ex.init((char*)buf + body_offset,
+ buf_end,
+ buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
DBUG_RETURN(1);
-
+
data_len = event_len - body_offset;
if (num_fields > data_len) // simple sanity check against corruption
DBUG_RETURN(1);
@@ -1580,6 +2522,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
fname = db + db_len + 1;
fname_len = strlen(fname);
// null termination is accomplished by the caller doing buf[event_len]=0
+
DBUG_RETURN(0);
}
@@ -1589,13 +2532,13 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
*/
#ifdef MYSQL_CLIENT
-void Load_log_event::print(FILE* file, bool short_form, char* last_db)
+void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
{
- print(file, short_form, last_db, 0);
+ print(file, short_form, last_event_info, 0);
}
-void Load_log_event::print(FILE* file, bool short_form, char* last_db,
+void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info,
bool commented)
{
DBUG_ENTER("Load_log_event::print");
@@ -1607,7 +2550,7 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db,
}
bool different_db= 1;
- if (db && last_db)
+ if (db)
{
/*
If the database is different from the one of the previous statement, we
@@ -1615,9 +2558,9 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db,
But if commented, the "use" is going to be commented so we should not
update the last_db.
*/
- if ((different_db= memcmp(last_db, db, db_len + 1)) &&
+ if ((different_db= memcmp(last_event_info->db, db, db_len + 1)) &&
!commented)
- memcpy(last_db, db, db_len + 1);
+ memcpy(last_event_info->db, db, db_len + 1);
}
if (db && db[0] && different_db)
@@ -1696,13 +2639,15 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db,
#ifndef MYSQL_CLIENT
void Load_log_event::set_fields(const char* affected_db,
- List<Item> &field_list)
+ List<Item> &field_list,
+ Name_resolution_context *context)
{
uint i;
const char* field = fields;
for (i= 0; i < num_fields; i++)
{
- field_list.push_back(new Item_field(affected_db, table_name, field));
+ field_list.push_back(new Item_field(context,
+ affected_db, table_name, field));
field+= field_lens[i] + 1;
}
}
@@ -1739,7 +2684,6 @@ void Load_log_event::set_fields(const char* affected_db,
int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors)
{
- char *load_data_query= 0;
thd->db_length= db_len;
thd->db= (char*) rewrite_db(db, &thd->db_length);
DBUG_ASSERT(thd->query == 0);
@@ -1753,15 +2697,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
mysql_init_query(thd, 0, 0);
if (!use_rli_only_for_errors)
{
-#if MYSQL_VERSION_ID < 50000
- rli->future_group_master_log_pos= log_pos + get_event_len() -
- (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0);
-#else
+ /* Saved for InnoDB, see comment in Query_log_event::exec_event() */
rli->future_group_master_log_pos= log_pos;
-#endif
+ DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
}
-
- /*
+
+ /*
We test replicate_*_db rules. Note that we have already prepared the file
to load, even if we are going to ignore and delete it now. So it is
possible that we did a lot of disk writes for nothing. In other words, a
@@ -1787,7 +2728,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
{
thd->set_time((time_t)when);
VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query_id = query_id++;
+ thd->query_id = next_query_id();
VOID(pthread_mutex_unlock(&LOCK_thread_count));
/*
Initing thd->row_count is not necessary in theory as this variable has no
@@ -1795,12 +2736,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
"data truncated" warning but which is absorbed and never gets to the
error log); still we init it to avoid a Valgrind message.
*/
- mysql_reset_errors(thd);
+ mysql_reset_errors(thd, 0);
TABLE_LIST tables;
bzero((char*) &tables,sizeof(tables));
tables.db = thd->db;
- tables.alias = tables.real_name = (char*)table_name;
+ tables.alias = tables.table_name = (char*) table_name;
tables.lock_type = TL_WRITE;
tables.updating= 1;
@@ -1814,22 +2755,30 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
else
{
char llbuff[22];
+ char *end;
enum enum_duplicates handle_dup;
bool ignore= 0;
+ char *load_data_query;
+
/*
- Make a simplified LOAD DATA INFILE query, for the information of the
- user in SHOW PROCESSLIST. Note that db is known in the 'db' column.
+ Forge LOAD DATA INFILE query which will be used in SHOW PROCESS LIST
+ and written to slave's binlog if binlogging is on.
*/
- if ((load_data_query= (char *) my_alloca(18 + strlen(fname) + 14 +
- strlen(tables.real_name) + 8)))
+ if (!(load_data_query= (char *)thd->alloc(get_query_buffer_length() + 1)))
{
- thd->query_length= (uint)(strxmov(load_data_query,
- "LOAD DATA INFILE '", fname,
- "' INTO TABLE `", tables.real_name,
- "` <...>", NullS) - load_data_query);
- thd->query= load_data_query;
+ /*
+ This will set thd->fatal_error in case of OOM. So we surely will notice
+ that something is wrong.
+ */
+ goto error;
}
+ print_query(FALSE, load_data_query, &end, (char **)&thd->lex->fname_start,
+ (char **)&thd->lex->fname_end);
+ *end= 0;
+ thd->query_length= end - load_data_query;
+ thd->query= load_data_query;
+
if (sql_ex.opt_flags & REPLACE_FLAG)
{
handle_dup= DUP_REPLACE;
@@ -1885,8 +2834,10 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
ex.skip_lines = skip_lines;
List<Item> field_list;
- set_fields(thd->db,field_list);
+ thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables);
+ set_fields(thd->db, field_list, &thd->main_lex.select_lex.context);
thd->variables.pseudo_thread_id= thread_id;
+ List<Item> set_fields;
if (net)
{
// mysql_load will use thd->net to read the file
@@ -1896,9 +2847,13 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
*/
thd->net.pkt_nr = net->pkt_nr;
}
- if (mysql_load(thd, &ex, &tables, field_list, handle_dup, ignore, net != 0,
- TL_WRITE))
- thd->query_error = 1;
+ /*
+ It is safe to use set_fields twice because we are not going to
+ update it inside mysql_load().
+ */
+ if (mysql_load(thd, &ex, &tables, field_list, set_fields, set_fields,
+ handle_dup, ignore, net != 0))
+ thd->query_error= 1;
if (thd->cuted_fields)
{
/* log_pos is the position of the LOAD event in the master log */
@@ -1924,20 +2879,19 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
if (net)
skip_load_data_infile(net);
}
-
+
+error:
thd->net.vio = 0;
char *save_db= thd->db;
VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->db= 0;
+ thd->db= thd->catalog= 0;
thd->query= 0;
thd->query_length= thd->db_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd);
- if (load_data_query)
- my_afree(load_data_query);
if (thd->query_error)
{
- /* this err/sql_errno code is copy-paste from send_error() */
+ /* this err/sql_errno code is copy-paste from net_send_error() */
const char *err;
int sql_errno;
if ((err=thd->net.last_error)[0])
@@ -1995,17 +2949,17 @@ void Rotate_log_event::pack_info(Protocol *protocol)
*/
#ifdef MYSQL_CLIENT
-void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
+void Rotate_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
{
char buf[22];
+
if (short_form)
return;
-
print_header(file);
fprintf(file, "\tRotate to ");
if (new_log_ident)
my_fwrite(file, (byte*) new_log_ident, (uint)ident_len,
- MYF(MY_NABP | MY_WME));
+ MYF(MY_NABP | MY_WME));
fprintf(file, " pos: %s", llstr(pos, buf));
fputc('\n', file);
fflush(file);
@@ -2017,31 +2971,22 @@ void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
Rotate_log_event::Rotate_log_event()
*/
-Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
- bool old_format)
- :Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
+Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event)
+ :Log_event(buf, description_event) ,new_log_ident(NULL),alloced(0)
{
+ DBUG_ENTER("Rotate_log_event::Rotate_log_event(char*,...)");
// The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
- int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ uint8 header_size= description_event->common_header_len;
+ uint8 post_header_len= description_event->post_header_len[ROTATE_EVENT-1];
uint ident_offset;
- DBUG_ENTER("Rotate_log_event");
-
if (event_len < header_size)
DBUG_VOID_RETURN;
-
buf += header_size;
- if (old_format)
- {
- ident_len = (uint)(event_len - OLD_HEADER_LEN);
- pos = 4;
- ident_offset = 0;
- }
- else
- {
- ident_len = (uint)(event_len - ROTATE_EVENT_OVERHEAD);
- pos = uint8korr(buf + R_POS_OFFSET);
- ident_offset = ROTATE_HEADER_LEN;
- }
+ pos = post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4;
+ ident_len = (uint)(event_len -
+ (header_size+post_header_len));
+ ident_offset = post_header_len;
set_if_smaller(ident_len,FN_REFLEN-1);
if (!(new_log_ident= my_strdup_with_length((byte*) buf +
ident_offset,
@@ -2054,29 +2999,32 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
/*
- Rotate_log_event::write_data()
+ Rotate_log_event::write()
*/
-int Rotate_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool Rotate_log_event::write(IO_CACHE* file)
{
char buf[ROTATE_HEADER_LEN];
int8store(buf + R_POS_OFFSET, pos);
- return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
- my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
+ return (write_header(file, ROTATE_HEADER_LEN + ident_len) ||
+ my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
+ my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
}
-
+#endif
/*
Rotate_log_event::exec_event()
- Got a rotate log even from the master
+ Got a rotate log event from the master
IMPLEMENTATION
This is mainly used so that we can later figure out the logname and
position for the master.
- We can't rotate the slave as this will cause infinitive rotations
+ We can't rotate the slave's BINlog as this will cause infinitive rotations
in a A -> B -> A setup.
+ The NOTES below is a wrong comment which will disappear when 4.1 is merged.
RETURN VALUES
0 ok
@@ -2088,7 +3036,7 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
DBUG_ENTER("Rotate_log_event::exec_event");
pthread_mutex_lock(&rli->data_lock);
- rli->event_relay_log_pos += get_event_len();
+ rli->event_relay_log_pos= my_b_tell(rli->cur_log);
/*
If we are in a transaction: the only normal case is when the I/O thread was
copying a big transaction, then it was stopped and restarted: we have this
@@ -2100,15 +3048,31 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
COMMIT or ROLLBACK
In that case, we don't want to touch the coordinates which correspond to
the beginning of the transaction.
+ Starting from 5.0.0, there also are some rotates from the slave itself, in
+ the relay log.
*/
if (!(thd->options & OPTION_BEGIN))
{
memcpy(rli->group_master_log_name, new_log_ident, ident_len+1);
rli->notify_group_master_log_name_update();
- rli->group_master_log_pos = pos;
- rli->group_relay_log_pos = rli->event_relay_log_pos;
- DBUG_PRINT("info", ("group_master_log_pos: %lu",
+ rli->group_master_log_pos= pos;
+ rli->group_relay_log_pos= rli->event_relay_log_pos;
+ DBUG_PRINT("info", ("group_master_log_name: '%s' group_master_log_pos:\
+%lu",
+ rli->group_master_log_name,
(ulong) rli->group_master_log_pos));
+ /*
+ Reset thd->options and sql_mode etc, because this could be the signal of
+ a master's downgrade from 5.0 to 4.0.
+ However, no need to reset description_event_for_exec: indeed, if the next
+ master is 5.0 (even 5.0.1) we will soon get a Format_desc; if the next
+ master is 4.0 then the events are in the slave's format (conversion).
+ */
+ set_slave_thread_options(thd);
+ set_slave_thread_default_charset(thd, rli);
+ thd->variables.sql_mode= global_system_variables.sql_mode;
+ thd->variables.auto_increment_increment=
+ thd->variables.auto_increment_offset= 1;
}
pthread_mutex_unlock(&rli->data_lock);
pthread_cond_broadcast(&rli->data_cond);
@@ -2142,12 +3106,13 @@ void Intvar_log_event::pack_info(Protocol *protocol)
Intvar_log_event::Intvar_log_event()
*/
-Intvar_log_event::Intvar_log_event(const char* buf, bool old_format)
- :Log_event(buf, old_format)
+Intvar_log_event::Intvar_log_event(const char* buf,
+ const Format_description_log_event* description_event)
+ :Log_event(buf, description_event)
{
- buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
- type = buf[I_TYPE_OFFSET];
- val = uint8korr(buf+I_VAL_OFFSET);
+ buf+= description_event->common_header_len;
+ type= buf[I_TYPE_OFFSET];
+ val= uint8korr(buf+I_VAL_OFFSET);
}
@@ -2166,16 +3131,19 @@ const char* Intvar_log_event::get_var_type_name()
/*
- Intvar_log_event::write_data()
+ Intvar_log_event::write()
*/
-int Intvar_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool Intvar_log_event::write(IO_CACHE* file)
{
- char buf[9];
- buf[I_TYPE_OFFSET] = type;
+ byte buf[9];
+ buf[I_TYPE_OFFSET]= (byte) type;
int8store(buf + I_VAL_OFFSET, val);
- return my_b_safe_write(file, (byte*) buf, sizeof(buf));
+ return (write_header(file, sizeof(buf)) ||
+ my_b_safe_write(file, buf, sizeof(buf)));
}
+#endif
/*
@@ -2183,7 +3151,8 @@ int Intvar_log_event::write_data(IO_CACHE* file)
*/
#ifdef MYSQL_CLIENT
-void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
+void Intvar_log_event::print(FILE* file, bool short_form,
+ LAST_EVENT_INFO* last_event_info)
{
char llbuff[22];
const char *msg;
@@ -2226,7 +3195,7 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
thd->next_insert_id = val;
break;
}
- rli->inc_event_relay_log_pos(get_event_len());
+ rli->inc_event_relay_log_pos();
return 0;
}
#endif
@@ -2249,26 +3218,30 @@ void Rand_log_event::pack_info(Protocol *protocol)
#endif
-Rand_log_event::Rand_log_event(const char* buf, bool old_format)
- :Log_event(buf, old_format)
+Rand_log_event::Rand_log_event(const char* buf,
+ const Format_description_log_event* description_event)
+ :Log_event(buf, description_event)
{
- buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
- seed1 = uint8korr(buf+RAND_SEED1_OFFSET);
- seed2 = uint8korr(buf+RAND_SEED2_OFFSET);
+ buf+= description_event->common_header_len;
+ seed1= uint8korr(buf+RAND_SEED1_OFFSET);
+ seed2= uint8korr(buf+RAND_SEED2_OFFSET);
}
-int Rand_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool Rand_log_event::write(IO_CACHE* file)
{
- char buf[16];
+ byte buf[16];
int8store(buf + RAND_SEED1_OFFSET, seed1);
int8store(buf + RAND_SEED2_OFFSET, seed2);
- return my_b_safe_write(file, (byte*) buf, sizeof(buf));
+ return (write_header(file, sizeof(buf)) ||
+ my_b_safe_write(file, buf, sizeof(buf)));
}
+#endif
#ifdef MYSQL_CLIENT
-void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
+void Rand_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
{
char llbuff[22],llbuff2[22];
if (!short_form)
@@ -2288,13 +3261,83 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
{
thd->rand.seed1= (ulong) seed1;
thd->rand.seed2= (ulong) seed2;
- rli->inc_event_relay_log_pos(get_event_len());
+ rli->inc_event_relay_log_pos();
return 0;
}
#endif /* !MYSQL_CLIENT */
/**************************************************************************
+ Xid_log_event methods
+**************************************************************************/
+
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Xid_log_event::pack_info(Protocol *protocol)
+{
+ char buf[128], *pos;
+ pos= strmov(buf, "COMMIT /* xid=");
+ pos= longlong10_to_str(xid, pos, 10);
+ pos= strmov(pos, " */");
+ protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
+}
+#endif
+
+/*
+ NOTE it's ok not to use int8store here,
+ as long as xid_t::set(ulonglong) and
+ xid_t::get_my_xid doesn't do it either
+
+ we don't care about actual values of xids as long as
+ identical numbers compare identically
+*/
+
+Xid_log_event::
+Xid_log_event(const char* buf,
+ const Format_description_log_event *description_event)
+ :Log_event(buf, description_event)
+{
+ buf+= description_event->common_header_len;
+ memcpy((char*) &xid, buf, sizeof(xid));
+}
+
+
+#ifndef MYSQL_CLIENT
+bool Xid_log_event::write(IO_CACHE* file)
+{
+ return write_header(file, sizeof(xid)) ||
+ my_b_safe_write(file, (byte*) &xid, sizeof(xid));
+}
+#endif
+
+
+#ifdef MYSQL_CLIENT
+void Xid_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
+{
+ if (!short_form)
+ {
+ char buf[64];
+ longlong10_to_str(xid, buf, 10);
+
+ print_header(file);
+ fprintf(file, "\tXid = %s\n", buf);
+ fflush(file);
+ }
+ fprintf(file, "COMMIT;\n");
+}
+#endif /* MYSQL_CLIENT */
+
+
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Xid_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ /* For a slave Xid_log_event is COMMIT */
+ mysql_log.write(thd,COM_QUERY,"COMMIT /* implicit, from Xid_log_event */");
+ return end_trans(thd, COMMIT) || Log_event::exec_event(rli);
+}
+#endif /* !MYSQL_CLIENT */
+
+
+/**************************************************************************
User_var_log_event methods
**************************************************************************/
@@ -2325,6 +3368,16 @@ void User_var_log_event::pack_info(Protocol* protocol)
buf= my_malloc(val_offset + 22, MYF(MY_WME));
event_len= longlong10_to_str(uint8korr(val), buf + val_offset,-10)-buf;
break;
+ case DECIMAL_RESULT:
+ {
+ buf= my_malloc(val_offset + DECIMAL_MAX_STR_LENGTH, MYF(MY_WME));
+ String str(buf+val_offset, DECIMAL_MAX_STR_LENGTH, &my_charset_bin);
+ my_decimal dec;
+ binary2my_decimal(E_DEC_FATAL_ERROR, val+2, &dec, val[0], val[1]);
+ my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, 0, &str);
+ event_len= str.length() + val_offset;
+ break;
+ }
case STRING_RESULT:
/* 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));
@@ -2359,10 +3412,12 @@ void User_var_log_event::pack_info(Protocol* protocol)
#endif /* !MYSQL_CLIENT */
-User_var_log_event::User_var_log_event(const char* buf, bool old_format)
- :Log_event(buf, old_format)
+User_var_log_event::
+User_var_log_event(const char* buf,
+ const Format_description_log_event* description_event)
+ :Log_event(buf, description_event)
{
- buf+= (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+ buf+= description_event->common_header_len;
name_len= uint4korr(buf);
name= (char *) buf + UV_NAME_LEN_SIZE;
buf+= UV_NAME_LEN_SIZE + name_len;
@@ -2386,13 +3441,15 @@ User_var_log_event::User_var_log_event(const char* buf, bool old_format)
}
-int User_var_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool User_var_log_event::write(IO_CACHE* file)
{
char buf[UV_NAME_LEN_SIZE];
char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE];
- char buf2[8], *pos= buf2;
+ char buf2[max(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos= buf2;
uint buf1_length;
+ ulong event_length;
int4store(buf, name_len);
@@ -2405,8 +3462,6 @@ int User_var_log_event::write_data(IO_CACHE* file)
{
buf1[1]= type;
int4store(buf1 + 2, charset_number);
- int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
- buf1_length= 10;
switch (type) {
case REAL_RESULT:
@@ -2415,6 +3470,16 @@ int User_var_log_event::write_data(IO_CACHE* file)
case INT_RESULT:
int8store(buf2, *(longlong*) val);
break;
+ case DECIMAL_RESULT:
+ {
+ my_decimal *dec= (my_decimal *)val;
+ dec->fix_buffer_pointer();
+ buf2[0]= (char)(dec->intg + dec->frac);
+ buf2[1]= (char)dec->frac;
+ decimal2bin((decimal_t*)val, buf2+2, buf2[0], buf2[1]);
+ val_len= decimal_bin_size(buf2[0], buf2[1]) + 2;
+ break;
+ }
case STRING_RESULT:
pos= val;
break;
@@ -2423,12 +3488,20 @@ int User_var_log_event::write_data(IO_CACHE* file)
DBUG_ASSERT(1);
return 0;
}
+ int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
+ buf1_length= 10;
}
- return (my_b_safe_write(file, (byte*) buf, sizeof(buf)) ||
+
+ /* Length of the whole event */
+ event_length= sizeof(buf)+ name_len + buf1_length + val_len;
+
+ return (write_header(file, event_length) ||
+ my_b_safe_write(file, (byte*) buf, sizeof(buf)) ||
my_b_safe_write(file, (byte*) name, name_len) ||
my_b_safe_write(file, (byte*) buf1, buf1_length) ||
my_b_safe_write(file, (byte*) pos, val_len));
}
+#endif
/*
@@ -2436,7 +3509,7 @@ int User_var_log_event::write_data(IO_CACHE* file)
*/
#ifdef MYSQL_CLIENT
-void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
+void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
{
if (!short_form)
{
@@ -2465,6 +3538,23 @@ void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
longlong10_to_str(uint8korr(val), int_buf, -10);
fprintf(file, ":=%s;\n", int_buf);
break;
+ case DECIMAL_RESULT:
+ {
+ char str_buf[200];
+ int str_len= sizeof(str_buf) - 1;
+ int precision= (int)val[0];
+ int scale= (int)val[1];
+ decimal_digit_t dec_buf[10];
+ decimal_t dec;
+ dec.len= 10;
+ dec.buf= dec_buf;
+
+ bin2decimal(val+2, &dec, precision, scale);
+ decimal2string(&dec, str_buf, &str_len, 0, 0, 0);
+ str_buf[str_len]= 0;
+ fprintf(file, ":=%s;\n",str_buf);
+ break;
+ }
case STRING_RESULT:
{
/*
@@ -2541,7 +3631,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
switch (type) {
case REAL_RESULT:
float8get(real_val, val);
- it= new Item_real(real_val);
+ it= new Item_float(real_val);
val= (char*) &real_val; // Pointer to value in native format
val_len= 8;
break;
@@ -2551,6 +3641,14 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
val= (char*) &int_val; // Pointer to value in native format
val_len= 8;
break;
+ case DECIMAL_RESULT:
+ {
+ Item_decimal *dec= new Item_decimal(val+2, val[0], val[1]);
+ it= dec;
+ val= (char *)dec->val_decimal(NULL);
+ val_len= sizeof(my_decimal);
+ break;
+ }
case STRING_RESULT:
it= new Item_string(val, val_len, charset);
break;
@@ -2565,7 +3663,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
Item_func_set_user_var can't substitute something else on its place =>
0 can be passed as last argument (reference on item)
*/
- e.fix_fields(thd, 0, 0);
+ e.fix_fields(thd, 0);
/*
A variable can just be considered as a table with
a single record and with a single column. Thus, like
@@ -2574,7 +3672,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT);
free_root(thd->mem_root,0);
- rli->inc_event_relay_log_pos(get_event_len());
+ rli->inc_event_relay_log_pos();
return 0;
}
#endif /* !MYSQL_CLIENT */
@@ -2586,7 +3684,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
#ifdef HAVE_REPLICATION
#ifdef MYSQL_CLIENT
-void Unknown_log_event::print(FILE* file, bool short_form, char* last_db)
+void Unknown_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
{
if (short_form)
return;
@@ -2616,12 +3714,12 @@ void Slave_log_event::pack_info(Protocol *protocol)
#ifndef MYSQL_CLIENT
Slave_log_event::Slave_log_event(THD* thd_arg,
struct st_relay_log_info* rli)
- :Log_event(thd_arg, 0, 0), mem_pool(0), master_host(0)
+ :Log_event(thd_arg, 0, 0) , mem_pool(0), master_host(0)
{
DBUG_ENTER("Slave_log_event");
if (!rli->inited) // QQ When can this happen ?
DBUG_VOID_RETURN;
-
+
MASTER_INFO* mi = rli->mi;
// TODO: re-write this better without holding both locks at the same time
pthread_mutex_lock(&mi->data_lock);
@@ -2657,7 +3755,7 @@ Slave_log_event::~Slave_log_event()
#ifdef MYSQL_CLIENT
-void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
+void Slave_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
{
char llbuff[22];
if (short_form)
@@ -2677,13 +3775,18 @@ int Slave_log_event::get_data_size()
}
-int Slave_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool Slave_log_event::write(IO_CACHE* file)
{
+ ulong event_length= get_data_size();
int8store(mem_pool + SL_MASTER_POS_OFFSET, master_pos);
int2store(mem_pool + SL_MASTER_PORT_OFFSET, master_port);
// log and host are already there
- return my_b_safe_write(file, (byte*)mem_pool, get_data_size());
+
+ return (write_header(file, event_length) ||
+ my_b_safe_write(file, (byte*) mem_pool, event_length));
}
+#endif
void Slave_log_event::init_from_mem_pool(int data_size)
@@ -2703,12 +3806,13 @@ void Slave_log_event::init_from_mem_pool(int data_size)
}
-Slave_log_event::Slave_log_event(const char* buf, int event_len)
- :Log_event(buf,0),mem_pool(0),master_host(0)
+/* This code is not used, so has not been updated to be format-tolerant */
+Slave_log_event::Slave_log_event(const char* buf, uint event_len)
+ :Log_event(buf,0) /*unused event*/ ,mem_pool(0),master_host(0)
{
- event_len -= LOG_EVENT_HEADER_LEN;
- if (event_len < 0)
+ if (event_len < LOG_EVENT_HEADER_LEN)
return;
+ event_len -= LOG_EVENT_HEADER_LEN;
if (!(mem_pool = (char*) my_malloc(event_len + 1, MYF(MY_WME))))
return;
memcpy(mem_pool, buf + LOG_EVENT_HEADER_LEN, event_len);
@@ -2736,7 +3840,7 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli)
*/
#ifdef MYSQL_CLIENT
-void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
+void Stop_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info)
{
if (short_form)
return;
@@ -2751,14 +3855,14 @@ void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
/*
Stop_log_event::exec_event()
- The master stopped.
+ The master stopped.
We used to clean up all temporary tables but this is useless as, as the
- master has shut down properly, it has written all DROP TEMPORARY TABLE and DO
- RELEASE_LOCK (prepared statements' deletion is TODO).
+ master has shut down properly, it has written all DROP TEMPORARY TABLE
+ (prepared statements' deletion is TODO only when we binlog prep stmts).
We used to clean up slave_load_tmpdir, but this is useless as it has been
cleared at the end of LOAD DATA INFILE.
So we have nothing to do here.
- The place were we must do this cleaning is in Start_log_event::exec_event(),
+ The place were we must do this cleaning is in Start_log_event_v3::exec_event(),
not here. Because if we come here, the master was sane.
*/
@@ -2772,8 +3876,13 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli)
could give false triggers in MASTER_POS_WAIT() that we have reached
the target position when in fact we have not.
*/
- rli->inc_group_relay_log_pos(get_event_len(), 0);
- flush_relay_log_info(rli);
+ if (thd->options & OPTION_BEGIN)
+ rli->inc_event_relay_log_pos();
+ else
+ {
+ rli->inc_group_relay_log_pos(0);
+ flush_relay_log_info(rli);
+ }
return 0;
}
#endif /* !MYSQL_CLIENT */
@@ -2804,20 +3913,19 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex,
sql_ex.force_new_format();
DBUG_VOID_RETURN;
}
-#endif /* !MYSQL_CLIENT */
/*
Create_file_log_event::write_data_body()
*/
-int Create_file_log_event::write_data_body(IO_CACHE* file)
+bool Create_file_log_event::write_data_body(IO_CACHE* file)
{
- int res;
- if ((res = Load_log_event::write_data_body(file)) || fake_base)
+ bool res;
+ if ((res= Load_log_event::write_data_body(file)) || fake_base)
return res;
return (my_b_safe_write(file, (byte*) "", 1) ||
- my_b_safe_write(file, (byte*) block, block_len));
+ my_b_safe_write(file, (byte*) block, block_len));
}
@@ -2825,14 +3933,14 @@ int Create_file_log_event::write_data_body(IO_CACHE* file)
Create_file_log_event::write_data_header()
*/
-int Create_file_log_event::write_data_header(IO_CACHE* file)
+bool Create_file_log_event::write_data_header(IO_CACHE* file)
{
- int res;
- if ((res = Load_log_event::write_data_header(file)) || fake_base)
- return res;
+ bool res;
byte buf[CREATE_FILE_HEADER_LEN];
+ if ((res= Load_log_event::write_data_header(file)) || fake_base)
+ return res;
int4store(buf + CF_FILE_ID_OFFSET, file_id);
- return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN);
+ return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN) != 0;
}
@@ -2840,42 +3948,58 @@ int Create_file_log_event::write_data_header(IO_CACHE* file)
Create_file_log_event::write_base()
*/
-int Create_file_log_event::write_base(IO_CACHE* file)
+bool Create_file_log_event::write_base(IO_CACHE* file)
{
- int res;
- fake_base = 1; // pretend we are Load event
- res = write(file);
- fake_base = 0;
+ bool res;
+ fake_base= 1; // pretend we are Load event
+ res= write(file);
+ fake_base= 0;
return res;
}
+#endif /* !MYSQL_CLIENT */
/*
Create_file_log_event ctor
*/
-Create_file_log_event::Create_file_log_event(const char* buf, int len,
- bool old_format)
- :Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0)
+Create_file_log_event::Create_file_log_event(const char* buf, uint len,
+ const Format_description_log_event* description_event)
+ :Load_log_event(buf,0,description_event),fake_base(0),block(0),inited_from_old(0)
{
- int block_offset;
- DBUG_ENTER("Create_file_log_event");
-
- /*
- We must make copy of 'buf' as this event may have to live over a
- rotate log entry when used in mysqlbinlog
- */
+ DBUG_ENTER("Create_file_log_event::Create_file_log_event(char*,...)");
+ uint block_offset;
+ uint header_len= description_event->common_header_len;
+ uint8 load_header_len= description_event->post_header_len[LOAD_EVENT-1];
+ uint8 create_file_header_len= description_event->post_header_len[CREATE_FILE_EVENT-1];
if (!(event_buf= my_memdup((byte*) buf, len, MYF(MY_WME))) ||
- (copy_log_event(event_buf, len, old_format)))
+ copy_log_event(event_buf,len,
+ ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
+ load_header_len + header_len :
+ (fake_base ? (header_len+load_header_len) :
+ (header_len+load_header_len) +
+ create_file_header_len)),
+ description_event))
DBUG_VOID_RETURN;
-
- if (!old_format)
+ if (description_event->binlog_version!=1)
{
- file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN +
- + LOAD_HEADER_LEN + CF_FILE_ID_OFFSET);
- // + 1 for \0 terminating fname
- block_offset = (LOG_EVENT_HEADER_LEN + Load_log_event::get_data_size() +
- CREATE_FILE_HEADER_LEN + 1);
+ file_id= uint4korr(buf +
+ header_len +
+ load_header_len + CF_FILE_ID_OFFSET);
+ /*
+ Note that it's ok to use get_data_size() below, because it is computed
+ with values we have already read from this event (because we called
+ copy_log_event()); we are not using slave's format info to decode
+ master's format, we are really using master's format info.
+ Anyway, both formats should be identical (except the common_header_len)
+ as these Load events are not changed between 4.0 and 5.0 (as logging of
+ LOAD DATA INFILE does not use Load_log_event in 5.0).
+
+ The + 1 is for \0 terminating fname
+ */
+ block_offset= (description_event->common_header_len +
+ Load_log_event::get_data_size() +
+ create_file_header_len + 1);
if (len < block_offset)
return;
block = (char*)buf + block_offset;
@@ -2896,18 +4020,18 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len,
#ifdef MYSQL_CLIENT
void Create_file_log_event::print(FILE* file, bool short_form,
- char* last_db, bool enable_local)
+ LAST_EVENT_INFO* last_event_info, bool enable_local)
{
if (short_form)
{
if (enable_local && check_fname_outside_temp_buf())
- Load_log_event::print(file, 1, last_db);
+ Load_log_event::print(file, 1, last_event_info);
return;
}
if (enable_local)
{
- Load_log_event::print(file, short_form, last_db, !check_fname_outside_temp_buf());
+ Load_log_event::print(file, short_form, last_event_info, !check_fname_outside_temp_buf());
/*
That one is for "file_id: etc" below: in mysqlbinlog we want the #, in
SHOW BINLOG EVENTS we don't.
@@ -2920,9 +4044,9 @@ void Create_file_log_event::print(FILE* file, bool short_form,
void Create_file_log_event::print(FILE* file, bool short_form,
- char* last_db)
+ LAST_EVENT_INFO* last_event_info)
{
- print(file,short_form,last_db,0);
+ print(file,short_form,last_event_info,0);
}
#endif /* MYSQL_CLIENT */
@@ -3043,30 +4167,38 @@ Append_block_log_event::Append_block_log_event(THD* thd_arg, const char* db_arg,
Append_block_log_event ctor
*/
-Append_block_log_event::Append_block_log_event(const char* buf, int len)
- :Log_event(buf, 0),block(0)
+Append_block_log_event::Append_block_log_event(const char* buf, uint len,
+ const Format_description_log_event* description_event)
+ :Log_event(buf, description_event),block(0)
{
- DBUG_ENTER("Append_block_log_event");
- if ((uint)len < APPEND_BLOCK_EVENT_OVERHEAD)
+ DBUG_ENTER("Append_block_log_event::Append_block_log_event(char*,...)");
+ uint8 common_header_len= description_event->common_header_len;
+ uint8 append_block_header_len=
+ description_event->post_header_len[APPEND_BLOCK_EVENT-1];
+ uint total_header_len= common_header_len+append_block_header_len;
+ if (len < total_header_len)
DBUG_VOID_RETURN;
- file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
- block = (char*)buf + APPEND_BLOCK_EVENT_OVERHEAD;
- block_len = len - APPEND_BLOCK_EVENT_OVERHEAD;
+ file_id= uint4korr(buf + common_header_len + AB_FILE_ID_OFFSET);
+ block= (char*)buf + total_header_len;
+ block_len= len - total_header_len;
DBUG_VOID_RETURN;
}
/*
- Append_block_log_event::write_data()
+ Append_block_log_event::write()
*/
-int Append_block_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool Append_block_log_event::write(IO_CACHE* file)
{
byte buf[APPEND_BLOCK_HEADER_LEN];
int4store(buf + AB_FILE_ID_OFFSET, file_id);
- return (my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) ||
+ return (write_header(file, APPEND_BLOCK_HEADER_LEN + block_len) ||
+ my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) ||
my_b_safe_write(file, (byte*) block, block_len));
}
+#endif
/*
@@ -3075,14 +4207,14 @@ int Append_block_log_event::write_data(IO_CACHE* file)
#ifdef MYSQL_CLIENT
void Append_block_log_event::print(FILE* file, bool short_form,
- char* last_db)
+ LAST_EVENT_INFO* last_event_info)
{
if (short_form)
return;
print_header(file);
fputc('\n', file);
- fprintf(file, "#Append_block: file_id: %d block_len: %d\n",
- file_id, block_len);
+ fprintf(file, "#%s: file_id: %d block_len: %d\n",
+ get_type_str(), file_id, block_len);
}
#endif /* MYSQL_CLIENT */
@@ -3101,14 +4233,21 @@ void Append_block_log_event::pack_info(Protocol *protocol)
block_len));
protocol->store(buf, length, &my_charset_bin);
}
-#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
/*
+ Append_block_log_event::get_create_or_append()
+*/
+
+int Append_block_log_event::get_create_or_append() const
+{
+ return 0; /* append to the file, fail if not exists */
+}
+
+/*
Append_block_log_event::exec_event()
*/
-#if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
{
char proc_info[17+FN_REFLEN+10], *fname= proc_info+17;
@@ -3120,14 +4259,32 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
memcpy(p, ".data", 6);
strnmov(proc_info, "Making temp file ", 17); // no end 0
thd->proc_info= proc_info;
- if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY|O_NOFOLLOW, MYF(MY_WME))) < 0)
+ if (get_create_or_append())
{
- slave_print_error(rli,my_errno, "Error in Append_block event: could not open file '%s'", fname);
+ my_delete(fname, MYF(0)); // old copy may exist already
+ if ((fd= my_create(fname, CREATE_MODE,
+ O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
+ MYF(MY_WME))) < 0)
+ {
+ slave_print_error(rli, my_errno,
+ "Error in %s event: could not create file '%s'",
+ get_type_str(), fname);
+ goto err;
+ }
+ }
+ else if ((fd = my_open(fname, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW,
+ MYF(MY_WME))) < 0)
+ {
+ slave_print_error(rli, my_errno,
+ "Error in %s event: could not open file '%s'",
+ get_type_str(), fname);
goto err;
}
if (my_write(fd, (byte*) block, block_len, MYF(MY_WME+MY_NABP)))
{
- slave_print_error(rli,my_errno, "Error in Append_block event: write to '%s' failed", fname);
+ slave_print_error(rli, my_errno,
+ "Error in %s event: write to '%s' failed",
+ get_type_str(), fname);
goto err;
}
error=0;
@@ -3161,25 +4318,31 @@ Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char* db_arg,
Delete_file_log_event ctor
*/
-Delete_file_log_event::Delete_file_log_event(const char* buf, int len)
- :Log_event(buf, 0),file_id(0)
+Delete_file_log_event::Delete_file_log_event(const char* buf, uint len,
+ const Format_description_log_event* description_event)
+ :Log_event(buf, description_event),file_id(0)
{
- if ((uint)len < DELETE_FILE_EVENT_OVERHEAD)
+ uint8 common_header_len= description_event->common_header_len;
+ uint8 delete_file_header_len= description_event->post_header_len[DELETE_FILE_EVENT-1];
+ if (len < (uint)(common_header_len + delete_file_header_len))
return;
- file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
+ file_id= uint4korr(buf + common_header_len + DF_FILE_ID_OFFSET);
}
/*
- Delete_file_log_event::write_data()
+ Delete_file_log_event::write()
*/
-int Delete_file_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool Delete_file_log_event::write(IO_CACHE* file)
{
byte buf[DELETE_FILE_HEADER_LEN];
int4store(buf + DF_FILE_ID_OFFSET, file_id);
- return my_b_safe_write(file, buf, DELETE_FILE_HEADER_LEN);
+ return (write_header(file, sizeof(buf)) ||
+ my_b_safe_write(file, buf, sizeof(buf)));
}
+#endif
/*
@@ -3188,7 +4351,7 @@ int Delete_file_log_event::write_data(IO_CACHE* file)
#ifdef MYSQL_CLIENT
void Delete_file_log_event::print(FILE* file, bool short_form,
- char* last_db)
+ LAST_EVENT_INFO* last_event_info)
{
if (short_form)
return;
@@ -3251,25 +4414,31 @@ Execute_load_log_event::Execute_load_log_event(THD *thd_arg, const char* db_arg,
Execute_load_log_event ctor
*/
-Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
- :Log_event(buf, 0), file_id(0)
+Execute_load_log_event::Execute_load_log_event(const char* buf, uint len,
+ const Format_description_log_event* description_event)
+ :Log_event(buf, description_event), file_id(0)
{
- if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
+ uint8 common_header_len= description_event->common_header_len;
+ uint8 exec_load_header_len= description_event->post_header_len[EXEC_LOAD_EVENT-1];
+ if (len < (uint)(common_header_len+exec_load_header_len))
return;
- file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET);
+ file_id= uint4korr(buf + common_header_len + EL_FILE_ID_OFFSET);
}
/*
- Execute_load_log_event::write_data()
+ Execute_load_log_event::write()
*/
-int Execute_load_log_event::write_data(IO_CACHE* file)
+#ifndef MYSQL_CLIENT
+bool Execute_load_log_event::write(IO_CACHE* file)
{
byte buf[EXEC_LOAD_HEADER_LEN];
int4store(buf + EL_FILE_ID_OFFSET, file_id);
- return my_b_safe_write(file, buf, EXEC_LOAD_HEADER_LEN);
+ return (write_header(file, sizeof(buf)) ||
+ my_b_safe_write(file, buf, sizeof(buf)));
}
+#endif
/*
@@ -3278,7 +4447,7 @@ int Execute_load_log_event::write_data(IO_CACHE* file)
#ifdef MYSQL_CLIENT
void Execute_load_log_event::print(FILE* file, bool short_form,
- char* last_db)
+ LAST_EVENT_INFO* last_event_info)
{
if (short_form)
return;
@@ -3317,7 +4486,8 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
Load_log_event* lev = 0;
memcpy(p, ".info", 6);
- if ((fd = my_open(fname, O_RDONLY|O_BINARY|O_NOFOLLOW, MYF(MY_WME))) < 0 ||
+ if ((fd = my_open(fname, O_RDONLY | O_BINARY | O_NOFOLLOW,
+ MYF(MY_WME))) < 0 ||
init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0,
MYF(MY_WME|MY_NABP)))
{
@@ -3325,8 +4495,8 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
goto err;
}
if (!(lev = (Load_log_event*)Log_event::read_log_event(&file,
- (pthread_mutex_t*)0,
- (bool)0)) ||
+ (pthread_mutex_t*)0,
+ rli->relay_log.description_event_for_exec)) ||
lev->get_type_code() != NEW_LOAD_EVENT)
{
slave_print_error(rli,0, "Error in Exec_load event: file '%s' appears corrupted", fname);
@@ -3341,15 +4511,7 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
mysql_load()).
*/
-#if MYSQL_VERSION_ID < 40100
- rli->future_master_log_pos= log_pos + get_event_len() -
- (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0);
-#elif MYSQL_VERSION_ID < 50000
- rli->future_group_master_log_pos= log_pos + get_event_len() -
- (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0);
-#else
- rli->future_group_master_log_pos= log_pos;
-#endif
+ rli->future_group_master_log_pos= log_pos;
if (lev->exec_event(0,rli,1))
{
/*
@@ -3400,6 +4562,223 @@ err:
/**************************************************************************
+ Begin_load_query_log_event methods
+**************************************************************************/
+
+#ifndef MYSQL_CLIENT
+Begin_load_query_log_event::
+Begin_load_query_log_event(THD* thd_arg, const char* db_arg, char* block_arg,
+ uint block_len_arg, bool using_trans)
+ :Append_block_log_event(thd_arg, db_arg, block_arg, block_len_arg,
+ using_trans)
+{
+ file_id= thd_arg->file_id= mysql_bin_log.next_file_id();
+}
+#endif
+
+
+Begin_load_query_log_event::
+Begin_load_query_log_event(const char* buf, uint len,
+ const Format_description_log_event* desc_event)
+ :Append_block_log_event(buf, len, desc_event)
+{
+}
+
+
+#if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+int Begin_load_query_log_event::get_create_or_append() const
+{
+ return 1; /* create the file */
+}
+#endif /* defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
+
+
+/**************************************************************************
+ Execute_load_query_log_event methods
+**************************************************************************/
+
+
+#ifndef MYSQL_CLIENT
+Execute_load_query_log_event::
+Execute_load_query_log_event(THD* thd_arg, const char* query_arg,
+ ulong query_length_arg, uint fn_pos_start_arg,
+ uint fn_pos_end_arg,
+ enum_load_dup_handling dup_handling_arg,
+ bool using_trans, bool suppress_use):
+ Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
+ suppress_use),
+ file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
+ fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
+{
+}
+#endif /* !MYSQL_CLIENT */
+
+
+Execute_load_query_log_event::
+Execute_load_query_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* desc_event):
+ Query_log_event(buf, event_len, desc_event, EXECUTE_LOAD_QUERY_EVENT),
+ file_id(0), fn_pos_start(0), fn_pos_end(0)
+{
+ if (!Query_log_event::is_valid())
+ return;
+
+ buf+= desc_event->common_header_len;
+
+ fn_pos_start= uint4korr(buf + ELQ_FN_POS_START_OFFSET);
+ fn_pos_end= uint4korr(buf + ELQ_FN_POS_END_OFFSET);
+ dup_handling= (enum_load_dup_handling)(*(buf + ELQ_DUP_HANDLING_OFFSET));
+
+ if (fn_pos_start > q_len || fn_pos_end > q_len ||
+ dup_handling > LOAD_DUP_REPLACE)
+ return;
+
+ file_id= uint4korr(buf + ELQ_FILE_ID_OFFSET);
+}
+
+
+ulong Execute_load_query_log_event::get_post_header_size_for_derived()
+{
+ return EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN;
+}
+
+
+#ifndef MYSQL_CLIENT
+bool
+Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file)
+{
+ char buf[EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN];
+ int4store(buf, file_id);
+ int4store(buf + 4, fn_pos_start);
+ int4store(buf + 4 + 4, fn_pos_end);
+ *(buf + 4 + 4 + 4)= (char)dup_handling;
+ return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
+}
+#endif
+
+
+#ifdef MYSQL_CLIENT
+void Execute_load_query_log_event::print(FILE* file, bool short_form,
+ LAST_EVENT_INFO* last_event_info)
+{
+ print(file, short_form, last_event_info, 0);
+}
+
+
+void Execute_load_query_log_event::print(FILE* file, bool short_form,
+ LAST_EVENT_INFO* last_event_info,
+ const char *local_fname)
+{
+ print_query_header(file, short_form, last_event_info);
+
+ if (local_fname)
+ {
+ my_fwrite(file, (byte*) query, fn_pos_start, MYF(MY_NABP | MY_WME));
+ fprintf(file, " LOCAL INFILE \'");
+ fprintf(file, local_fname);
+ fprintf(file, "\'");
+ if (dup_handling == LOAD_DUP_REPLACE)
+ fprintf(file, " REPLACE");
+ fprintf(file, " INTO");
+ my_fwrite(file, (byte*) query + fn_pos_end, q_len-fn_pos_end,
+ MYF(MY_NABP | MY_WME));
+ fprintf(file, ";\n");
+ }
+ else
+ {
+ my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
+ fprintf(file, ";\n");
+ }
+
+ if (!short_form)
+ fprintf(file, "# file_id: %d \n", file_id);
+}
+#endif
+
+
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+void Execute_load_query_log_event::pack_info(Protocol *protocol)
+{
+ char *buf, *pos;
+ if (!(buf= my_malloc(9 + db_len + q_len + 10 + 21, MYF(MY_WME))))
+ return;
+ pos= buf;
+ if (db && db_len)
+ {
+ pos= strmov(buf, "use `");
+ memcpy(pos, db, db_len);
+ pos= strmov(pos+db_len, "`; ");
+ }
+ if (query && q_len)
+ {
+ memcpy(pos, query, q_len);
+ pos+= q_len;
+ }
+ pos= strmov(pos, " ;file_id=");
+ pos= int10_to_str((long) file_id, pos, 10);
+ protocol->store(buf, pos-buf, &my_charset_bin);
+ my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
+}
+
+
+int
+Execute_load_query_log_event::exec_event(struct st_relay_log_info* rli)
+{
+ char *p;
+ char *buf;
+ char *fname;
+ char *fname_end;
+ int error;
+
+ /* Replace filename and LOCAL keyword in query before executing it */
+ if (!(buf = my_malloc(q_len + 1 - (fn_pos_end - fn_pos_start) +
+ (FN_REFLEN + 10) + 10 + 8 + 5, MYF(MY_WME))))
+ {
+ slave_print_error(rli, my_errno, "Not enough memory");
+ return 1;
+ }
+
+ p= buf;
+ memcpy(p, query, fn_pos_start);
+ p+= fn_pos_start;
+ fname= (p= strmake(p, " INFILE \'", 9));
+ p= slave_load_file_stem(p, file_id, server_id);
+ fname_end= (p= strmake(p, ".data", 5));
+ *(p++)='\'';
+ switch (dup_handling)
+ {
+ case LOAD_DUP_IGNORE:
+ p= strmake(p, " IGNORE", 7);
+ break;
+ case LOAD_DUP_REPLACE:
+ p= strmake(p, " REPLACE", 8);
+ break;
+ default:
+ /* Ordinary load data */
+ break;
+ }
+ p= strmake(p, " INTO", 5);
+ p= strmake(p, query+fn_pos_end, q_len-fn_pos_end);
+
+ error= Query_log_event::exec_event(rli, buf, p-buf);
+
+ /* Forging file name for deletion in same buffer */
+ *fname_end= 0;
+
+ /*
+ If there was an error the slave is going to stop, leave the
+ file so that we can re-execute this event at START SLAVE.
+ */
+ if (!error)
+ (void) my_delete(fname, MYF(MY_WME));
+
+ my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
+ return error;
+}
+#endif
+
+
+/**************************************************************************
sql_ex_info methods
**************************************************************************/
@@ -3407,15 +4786,15 @@ err:
sql_ex_info::write_data()
*/
-int sql_ex_info::write_data(IO_CACHE* file)
+bool sql_ex_info::write_data(IO_CACHE* file)
{
if (new_format())
{
- return (write_str(file, field_term, field_term_len) ||
- write_str(file, enclosed, enclosed_len) ||
- write_str(file, line_term, line_term_len) ||
- write_str(file, line_start, line_start_len) ||
- write_str(file, escaped, escaped_len) ||
+ return (write_str(file, field_term, (uint) field_term_len) ||
+ write_str(file, enclosed, (uint) enclosed_len) ||
+ write_str(file, line_term, (uint) line_term_len) ||
+ write_str(file, line_start, (uint) line_start_len) ||
+ write_str(file, escaped, (uint) escaped_len) ||
my_b_safe_write(file,(byte*) &opt_flags,1));
}
else
@@ -3428,7 +4807,7 @@ int sql_ex_info::write_data(IO_CACHE* file)
old_ex.escaped= *escaped;
old_ex.opt_flags= opt_flags;
old_ex.empty_flags=empty_flags;
- return my_b_safe_write(file, (byte*) &old_ex, sizeof(old_ex));
+ return my_b_safe_write(file, (byte*) &old_ex, sizeof(old_ex)) != 0;
}
}
@@ -3450,11 +4829,11 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
the case when we have old format because we will be reusing net buffer
to read the actual file before we write out the Create_file event.
*/
- if (read_str(buf, buf_end, field_term, field_term_len) ||
- read_str(buf, buf_end, enclosed, enclosed_len) ||
- read_str(buf, buf_end, line_term, line_term_len) ||
- read_str(buf, buf_end, line_start, line_start_len) ||
- read_str(buf, buf_end, escaped, escaped_len))
+ if (read_str(&buf, buf_end, &field_term, &field_term_len) ||
+ read_str(&buf, buf_end, &enclosed, &enclosed_len) ||
+ read_str(&buf, buf_end, &line_term, &line_term_len) ||
+ read_str(&buf, buf_end, &line_start, &line_start_len) ||
+ read_str(&buf, buf_end, &escaped, &escaped_len))
return 0;
opt_flags = *buf++;
}
diff --git a/sql/log_event.h b/sql/log_event.h
index 5c81d0c92f0..29580589a34 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -35,12 +35,42 @@
#define LOG_EVENT_OFFSET 4
-#define BINLOG_VERSION 3
+/*
+ 3 is MySQL 4.x; 4 is MySQL 5.0.0.
+ Compared to version 3, version 4 has:
+ - a different Start_log_event, which includes info about the binary log
+ (sizes of headers); this info is included for better compatibility if the
+ master's MySQL version is different from the slave's.
+ - all events have a unique ID (the triplet (server_id, timestamp at server
+ start, other) to be sure an event is not executed more than once in a
+ multimaster setup, example:
+ M1
+ / \
+ v v
+ M2 M3
+ \ /
+ v v
+ S
+ if a query is run on M1, it will arrive twice on S, so we need that S
+ remembers the last unique ID it has processed, to compare and know if the
+ event should be skipped or not. Example of ID: we already have the server id
+ (4 bytes), plus:
+ timestamp_when_the_master_started (4 bytes), a counter (a sequence number
+ which increments every time we write an event to the binlog) (3 bytes).
+ Q: how do we handle when the counter is overflowed and restarts from 0 ?
+
+ - Query and Load (Create or Execute) events may have a more precise timestamp
+ (with microseconds), number of matched/affected/warnings rows
+ and fields of session variables: SQL_MODE,
+ FOREIGN_KEY_CHECKS, UNIQUE_CHECKS, SQL_AUTO_IS_NULL, the collations and
+ charsets, the PASSWORD() version (old/new/...).
+*/
+#define BINLOG_VERSION 4
/*
We could have used SERVER_VERSION_LENGTH, but this introduces an
obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH
- this would have broken the replication protocol
+ this would break the replication protocol
*/
#define ST_SERVER_VER_LEN 50
@@ -49,6 +79,12 @@
TERMINATED etc).
*/
+/*
+ These are flags and structs to handle all the LOAD DATA INFILE options (LINES
+ TERMINATED etc).
+ DUMPFILE_FLAG is probably useless (DUMPFILE is a clause of SELECT, not of LOAD
+ DATA).
+*/
#define DUMPFILE_FLAG 0x1
#define OPT_ENCLOSED_FLAG 0x2
#define REPLACE_FLAG 0x4
@@ -92,18 +128,18 @@ struct sql_ex_info
char* escaped;
int cached_new_format;
uint8 field_term_len,enclosed_len,line_term_len,line_start_len, escaped_len;
- char opt_flags;
+ char opt_flags;
char empty_flags;
-
+
// store in new format even if old is possible
- void force_new_format() { cached_new_format = 1;}
+ void force_new_format() { cached_new_format = 1;}
int data_size()
{
return (new_format() ?
field_term_len + enclosed_len + line_term_len +
line_start_len + escaped_len + 6 : 7);
}
- int write_data(IO_CACHE* file);
+ bool write_data(IO_CACHE* file);
char* init(char* buf,char* buf_end,bool use_new_format);
bool new_format()
{
@@ -127,28 +163,44 @@ struct sql_ex_info
See the #defines below for the format specifics.
- The events which really update data are Query_log_event and
- Load_log_event/Create_file_log_event/Execute_load_log_event (these 3 act
- together to replicate LOAD DATA INFILE, with the help of
- Append_block_log_event which prepares temporary files to load into the table).
+ The events which really update data are Query_log_event,
+ Execute_load_query_log_event and old Load_log_event and
+ Execute_load_log_event events (Execute_load_query is used together with
+ Begin_load_query and Append_block events to replicate LOAD DATA INFILE.
+ Create_file/Append_block/Execute_load (which includes Load_log_event)
+ were used to replicate LOAD DATA before the 5.0.3).
****************************************************************************/
#define LOG_EVENT_HEADER_LEN 19 /* the fixed header length */
#define OLD_HEADER_LEN 13 /* the fixed header length in 3.23 */
+/*
+ Fixed header length, where 4.x and 5.0 agree. That is, 5.0 may have a longer
+ header (it will for sure when we have the unique event's ID), but at least
+ the first 19 bytes are the same in 4.x and 5.0. So when we have the unique
+ event's ID, LOG_EVENT_HEADER_LEN will be something like 26, but
+ LOG_EVENT_MINIMAL_HEADER_LEN will remain 19.
+*/
+#define LOG_EVENT_MINIMAL_HEADER_LEN 19
/* event-specific post-header sizes */
-#define QUERY_HEADER_LEN (4 + 4 + 1 + 2)
+// where 3.23, 4.x and 5.0 agree
+#define QUERY_HEADER_MINIMAL_LEN (4 + 4 + 1 + 2)
+// where 5.0 differs: 2 for len of N-bytes vars.
+#define QUERY_HEADER_LEN (QUERY_HEADER_MINIMAL_LEN + 2)
#define LOAD_HEADER_LEN (4 + 4 + 4 + 1 +1 + 4)
-#define START_HEADER_LEN (2 + ST_SERVER_VER_LEN + 4)
-#define ROTATE_HEADER_LEN 8
+#define START_V3_HEADER_LEN (2 + ST_SERVER_VER_LEN + 4)
+#define ROTATE_HEADER_LEN 8 // this is FROZEN (the Rotate post-header is frozen)
#define CREATE_FILE_HEADER_LEN 4
#define APPEND_BLOCK_HEADER_LEN 4
#define EXEC_LOAD_HEADER_LEN 4
#define DELETE_FILE_HEADER_LEN 4
+#define FORMAT_DESCRIPTION_HEADER_LEN (START_V3_HEADER_LEN+1+LOG_EVENT_TYPES)
+#define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1)
+#define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)
-/*
- Event header offsets;
+/*
+ Event header offsets;
these point to places inside the fixed header.
*/
@@ -158,11 +210,12 @@ struct sql_ex_info
#define LOG_POS_OFFSET 13
#define FLAGS_OFFSET 17
-/* start event post-header */
+/* start event post-header (for v3 and v4) */
#define ST_BINLOG_VER_OFFSET 0
#define ST_SERVER_VER_OFFSET 2
#define ST_CREATED_OFFSET (ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN)
+#define ST_COMMON_HEADER_LEN_OFFSET (ST_CREATED_OFFSET + 4)
/* slave event post-header (this event is never written) */
@@ -176,7 +229,28 @@ struct sql_ex_info
#define Q_EXEC_TIME_OFFSET 4
#define Q_DB_LEN_OFFSET 8
#define Q_ERR_CODE_OFFSET 9
+#define Q_STATUS_VARS_LEN_OFFSET 11
#define Q_DATA_OFFSET QUERY_HEADER_LEN
+/* these are codes, not offsets; not more than 256 values (1 byte). */
+#define Q_FLAGS2_CODE 0
+#define Q_SQL_MODE_CODE 1
+/*
+ Q_CATALOG_CODE is catalog with end zero stored; it is used only by MySQL
+ 5.0.x where 0<=x<=3. We have to keep it to be able to replicate these
+ old masters.
+*/
+#define Q_CATALOG_CODE 2
+#define Q_AUTO_INCREMENT 3
+#define Q_CHARSET_CODE 4
+#define Q_TIME_ZONE_CODE 5
+/*
+ Q_CATALOG_NZ_CODE is catalog withOUT end zero stored; it is used by MySQL
+ 5.0.x where x>=4. Saves one byte in every Query_log_event in binlog,
+ compared to Q_CATALOG_CODE. The reason we didn't simply re-use
+ Q_CATALOG_CODE is that then a 5.0.3 slave of this 5.0.x (x>=4) master would
+ crash (segfault etc) because it would expect a 0 when there is none.
+*/
+#define Q_CATALOG_NZ_CODE 6
/* Intvar event post-header */
@@ -228,15 +302,11 @@ struct sql_ex_info
/* DF = "Delete File" */
#define DF_FILE_ID_OFFSET 0
-#define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
-#define QUERY_DATA_OFFSET (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
-#define ROTATE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+ROTATE_HEADER_LEN)
-#define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN)
-#define CREATE_FILE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+\
- +LOAD_HEADER_LEN+CREATE_FILE_HEADER_LEN)
-#define DELETE_FILE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+DELETE_FILE_HEADER_LEN)
-#define EXEC_LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+EXEC_LOAD_HEADER_LEN)
-#define APPEND_BLOCK_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+APPEND_BLOCK_HEADER_LEN)
+/* ELQ = "Execute Load Query" */
+#define ELQ_FILE_ID_OFFSET QUERY_HEADER_LEN
+#define ELQ_FN_POS_START_OFFSET ELQ_FILE_ID_OFFSET + 4
+#define ELQ_FN_POS_END_OFFSET ELQ_FILE_ID_OFFSET + 8
+#define ELQ_DUP_HANDLING_OFFSET ELQ_FILE_ID_OFFSET + 12
/* 4 bytes which all binlogs should begin with */
#define BINLOG_MAGIC "\xfe\x62\x69\x6e"
@@ -249,20 +319,45 @@ struct sql_ex_info
So they are now removed and their place may later be reused for other
flags. Then one must remember that Rotate events in 4.x have
LOG_EVENT_FORCED_ROTATE_F set, so one should not rely on the value of the
- replacing flag when reading a Rotate event.
+ replacing flag when reading a Rotate event.
I keep the defines here just to remember what they were.
*/
#ifdef TO_BE_REMOVED
#define LOG_EVENT_TIME_F 0x1
-#define LOG_EVENT_FORCED_ROTATE_F 0x2
+#define LOG_EVENT_FORCED_ROTATE_F 0x2
#endif
-/*
+
+/*
+ This flag only makes sense for Format_description_log_event. It is set
+ when the event is written, and *reset* when a binlog file is
+ closed (yes, it's the only case when MySQL modifies already written
+ part of binlog). Thus it is a reliable indicator that binlog was
+ closed correctly. (Stop_log_event is not enough, there's always a
+ small chance that mysqld crashes in the middle of insert and end of
+ the binlog would look like a Stop_log_event).
+
+ This flag is used to detect a restart after a crash, and to provide
+ "unbreakable" binlog. The problem is that on a crash storage engines
+ rollback automatically, while binlog does not. To solve this we use this
+ flag and automatically append ROLLBACK to every non-closed binlog (append
+ virtually, on reading, file itself is not changed). If this flag is found,
+ mysqlbinlog simply prints "ROLLBACK" Replication master does not abort on
+ binlog corruption, but takes it as EOF, and replication slave forces a
+ rollback in this case.
+
+ Note, that old binlogs does not have this flag set, so we get a
+ a backward-compatible behaviour.
+*/
+
+#define LOG_EVENT_BINLOG_IN_USE_F 0x1
+
+/*
If the query depends on the thread (for example: TEMPORARY TABLE).
Currently this is used by mysqlbinlog to know it must print
SET @@PSEUDO_THREAD_ID=xx; before the query (it would not hurt to print it
for every query but this would be slow).
*/
-#define LOG_EVENT_THREAD_SPECIFIC_F 0x4
+#define LOG_EVENT_THREAD_SPECIFIC_F 0x4
/*
Suppress the generation of 'USE' statements before the actual
@@ -277,15 +372,67 @@ struct sql_ex_info
*/
#define LOG_EVENT_SUPPRESS_USE_F 0x8
+/*
+ OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must be
+ written to the binlog. OPTIONS_WRITTEN_TO_BINLOG could be written
+ into the Format_description_log_event, so that if later we don't want
+ to replicate a variable we did replicate, or the contrary, it's
+ doable. But it should not be too hard to decide once for all of what
+ we replicate and what we don't, among the fixed 32 bits of
+ thd->options.
+ I (Guilhem) have read through every option's usage, and it looks like
+ OPTION_AUTO_IS_NULL and OPTION_NO_FOREIGN_KEYS are the only ones
+ which alter how the query modifies the table. It's good to replicate
+ OPTION_RELAXED_UNIQUE_CHECKS too because otherwise, the slave may
+ insert data slower than the master, in InnoDB.
+ OPTION_BIG_SELECTS is not needed (the slave thread runs with
+ max_join_size=HA_POS_ERROR) and OPTION_BIG_TABLES is not needed
+ either, as the manual says (because a too big in-memory temp table is
+ automatically written to disk).
+*/
+#define OPTIONS_WRITTEN_TO_BIN_LOG (OPTION_AUTO_IS_NULL | \
+OPTION_NO_FOREIGN_KEY_CHECKS | OPTION_RELAXED_UNIQUE_CHECKS)
+
+#if OPTIONS_WRITTEN_TO_BIN_LOG != ((1L << 14) | (1L << 26) | (1L << 27))
+#error OPTIONS_WRITTEN_TO_BIN_LOG must NOT change their values!
+#endif
+
enum Log_event_type
{
- UNKNOWN_EVENT= 0, START_EVENT= 1, QUERY_EVENT= 2, STOP_EVENT= 3,
- ROTATE_EVENT= 4, INTVAR_EVENT= 5, LOAD_EVENT=6, SLAVE_EVENT= 7,
- CREATE_FILE_EVENT= 8, APPEND_BLOCK_EVENT= 9, EXEC_LOAD_EVENT= 10,
- DELETE_FILE_EVENT= 11, NEW_LOAD_EVENT= 12, RAND_EVENT= 13,
- USER_VAR_EVENT= 14
+ /*
+ Every time you update this enum (when you add a type), you have to
+ fix Format_description_log_event::Format_description_log_event().
+ */
+ UNKNOWN_EVENT= 0, START_EVENT_V3, QUERY_EVENT, STOP_EVENT, ROTATE_EVENT,
+ INTVAR_EVENT, LOAD_EVENT, SLAVE_EVENT, CREATE_FILE_EVENT,
+ APPEND_BLOCK_EVENT, EXEC_LOAD_EVENT, DELETE_FILE_EVENT,
+ /*
+ NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer
+ sql_ex, allowing multibyte TERMINATED BY etc; both types share the
+ same class (Load_log_event)
+ */
+ NEW_LOAD_EVENT,
+ RAND_EVENT, USER_VAR_EVENT,
+ FORMAT_DESCRIPTION_EVENT,
+ XID_EVENT,
+ BEGIN_LOAD_QUERY_EVENT,
+ EXECUTE_LOAD_QUERY_EVENT,
+
+ /*
+ add new events here - right above this comment!
+ existing events should never change their numbers
+ */
+
+ ENUM_END_EVENT /* end marker */
};
+/*
+ The number of types we handle in Format_description_log_event (UNKNOWN_EVENT
+ is not to be handled, it does not exist in binlogs, it does not have a
+ format).
+*/
+#define LOG_EVENT_TYPES (ENUM_END_EVENT-1)
+
enum Int_event_type
{
INVALID_INT_EVENT = 0, LAST_INSERT_ID_EVENT = 1, INSERT_ID_EVENT = 2
@@ -298,8 +445,45 @@ class MYSQL_LOG;
class THD;
#endif
+class Format_description_log_event;
+
struct st_relay_log_info;
+#ifdef MYSQL_CLIENT
+/*
+ A structure for mysqlbinlog to remember the last db, flags2, sql_mode etc; it
+ is passed to events' print() methods, so that they print only the necessary
+ USE and SET commands.
+*/
+typedef struct st_last_event_info
+{
+ // TODO: have the last catalog here ??
+ char db[FN_REFLEN+1]; // TODO: make this a LEX_STRING when thd->db is
+ bool flags2_inited;
+ uint32 flags2;
+ bool sql_mode_inited;
+ ulong sql_mode; /* must be same as THD.variables.sql_mode */
+ ulong auto_increment_increment, auto_increment_offset;
+ bool charset_inited;
+ char charset[6]; // 3 variables, each of them storable in 2 bytes
+ char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
+ st_last_event_info()
+ :flags2_inited(0), sql_mode_inited(0),
+ auto_increment_increment(1),auto_increment_offset(1), charset_inited(0)
+ {
+ /*
+ Currently we only use static LAST_EVENT_INFO objects, so zeroed at
+ program's startup, but these explicit bzero() is for the day someone
+ creates dynamic instances.
+ */
+ bzero(db, sizeof(db));
+ bzero(charset, sizeof(charset));
+ bzero(time_zone_str, sizeof(time_zone_str));
+ }
+} LAST_EVENT_INFO;
+#endif
+
+
/*****************************************************************************
Log_event class
@@ -310,69 +494,76 @@ struct st_relay_log_info;
class Log_event
{
public:
- /*
- The offset in the log where this event originally appeared (it is preserved
- in relay logs, making SHOW SLAVE STATUS able to print coordinates of the
- event in the master's binlog). Note: when a transaction is written by the
- master to its binlog (wrapped in BEGIN/COMMIT) the log_pos of all the
- queries it contains is the one of the BEGIN (this way, when one does SHOW
- SLAVE STATUS it sees the offset of the BEGIN, which is logical as rollback
- may occur), except the COMMIT query which has its real offset.
+ /*
+ The offset in the log where this event originally appeared (it is
+ preserved in relay logs, making SHOW SLAVE STATUS able to print
+ coordinates of the event in the master's binlog). Note: when a
+ transaction is written by the master to its binlog (wrapped in
+ BEGIN/COMMIT) the log_pos of all the queries it contains is the
+ one of the BEGIN (this way, when one does SHOW SLAVE STATUS it
+ sees the offset of the BEGIN, which is logical as rollback may
+ occur), except the COMMIT query which has its real offset.
*/
my_off_t log_pos;
- /*
+ /*
A temp buffer for read_log_event; it is later analysed according to the
event's type, and its content is distributed in the event-specific fields.
*/
- char *temp_buf;
+ char *temp_buf;
/*
- Timestamp on the master(for debugging and replication of NOW()/TIMESTAMP).
- It is important for queries and LOAD DATA INFILE. This is set at the event's
- creation time, except for Query and Load (et al.) events where this is set
- at the query's execution time, which guarantees good replication (otherwise,
- we could have a query and its event with different timestamps).
+ Timestamp on the master(for debugging and replication of
+ NOW()/TIMESTAMP). It is important for queries and LOAD DATA
+ INFILE. This is set at the event's creation time, except for Query
+ and Load (et al.) events where this is set at the query's
+ execution time, which guarantees good replication (otherwise, we
+ could have a query and its event with different timestamps).
*/
time_t when;
/* The number of seconds the query took to run on the master. */
ulong exec_time;
- /*
- The master's server id (is preserved in the relay log; used to prevent from
- infinite loops in circular replication).
+ /* Number of bytes written by write() function */
+ ulong data_written;
+
+ /*
+ The master's server id (is preserved in the relay log; used to
+ prevent from infinite loops in circular replication).
*/
uint32 server_id;
- uint cached_event_len;
/*
- Some 16 flags. Only one is really used now; look above for
- LOG_EVENT_TIME_F, LOG_EVENT_FORCED_ROTATE_F,
- LOG_EVENT_THREAD_SPECIFIC_F, and LOG_EVENT_SUPPRESS_USE_F for
- notes.
+ Some 16 flags. Look above for LOG_EVENT_TIME_F,
+ LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F, and
+ LOG_EVENT_SUPPRESS_USE_F for notes.
*/
uint16 flags;
bool cache_stmt;
+
#ifndef MYSQL_CLIENT
THD* thd;
- Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt);
Log_event();
+ Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt);
/*
- read_log_event() functions read an event from a binlog or relay log; used by
- SHOW BINLOG EVENTS, the binlog_dump thread on the master (reads master's
- binlog), the slave IO thread (reads the event sent by binlog_dump), the
- slave SQL thread (reads the event from the relay log).
+ read_log_event() functions read an event from a binlog or relay
+ log; used by SHOW BINLOG EVENTS, the binlog_dump thread on the
+ master (reads master's binlog), the slave IO thread (reads the
+ event sent by binlog_dump), the slave SQL thread (reads the event
+ from the relay log). If mutex is 0, the read will proceed without
+ mutex. We need the description_event to be able to parse the
+ event (to know the post-header's size); in fact in read_log_event
+ we detect the event's type, then call the specific event's
+ constructor and pass description_event as an argument.
*/
- // if mutex is 0, the read will proceed without mutex
static Log_event* read_log_event(IO_CACHE* file,
pthread_mutex_t* log_lock,
- bool old_format);
+ const Format_description_log_event *description_event);
static int read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock);
- /* set_log_pos() is used to fill log_pos with tell(log). */
- void set_log_pos(MYSQL_LOG* log);
/*
- init_show_field_list() prepares the column names and types for the output of
- SHOW BINLOG EVENTS; it is used only by SHOW BINLOG EVENTS.
+ init_show_field_list() prepares the column names and types for the
+ output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG
+ EVENTS.
*/
static void init_show_field_list(List<Item>* field_list);
#ifdef HAVE_REPLICATION
@@ -393,13 +584,15 @@ public:
return thd ? thd->db : 0;
}
#else
- // avoid having to link mysqlbinlog against libpthread
- static Log_event* read_log_event(IO_CACHE* file, bool old_format);
+ Log_event() : temp_buf(0) {}
+ /* avoid having to link mysqlbinlog against libpthread */
+ static Log_event* read_log_event(IO_CACHE* file,
+ const Format_description_log_event *description_event);
/* print*() functions are used by mysqlbinlog */
- virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
+ virtual void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0) = 0;
void print_timestamp(FILE* file, time_t *ts = 0);
void print_header(FILE* file);
-#endif
+#endif
static void *operator new(size_t size)
{
@@ -409,19 +602,25 @@ public:
{
my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
}
-
- int write(IO_CACHE* file);
- int write_header(IO_CACHE* file);
- virtual int write_data(IO_CACHE* file)
- { return write_data_header(file) || write_data_body(file); }
- virtual int write_data_header(IO_CACHE* file __attribute__((unused)))
+
+#ifndef MYSQL_CLIENT
+ bool write_header(IO_CACHE* file, ulong data_length);
+ virtual bool write(IO_CACHE* file)
+ {
+ return (write_header(file, get_data_size()) ||
+ write_data_header(file) ||
+ write_data_body(file));
+ }
+ virtual bool write_data_header(IO_CACHE* file)
{ return 0; }
- virtual int write_data_body(IO_CACHE* file __attribute__((unused)))
+ virtual bool write_data_body(IO_CACHE* file __attribute__((unused)))
{ return 0; }
+#endif
virtual Log_event_type get_type_code() = 0;
- virtual bool is_valid() = 0;
+ virtual bool is_valid() const = 0;
+ virtual bool is_artificial_event() { return 0; }
inline bool get_cache_stmt() { return cache_stmt; }
- Log_event(const char* buf, bool old_format);
+ Log_event(const char* buf, const Format_description_log_event* description_event);
virtual ~Log_event() { free_temp_buf();}
void register_temp_buf(char* buf) { temp_buf = buf; }
void free_temp_buf()
@@ -432,19 +631,31 @@ public:
temp_buf = 0;
}
}
+ /*
+ Get event length for simple events. For complicated events the length
+ is calculated during write()
+ */
virtual int get_data_size() { return 0;}
- virtual int get_data_body_offset() { return 0; }
- int get_event_len()
- {
- return (cached_event_len ? cached_event_len :
- (cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()));
- }
- static Log_event* read_log_event(const char* buf, int event_len,
- const char **error, bool old_format);
+ static Log_event* read_log_event(const char* buf, uint event_len,
+ const char **error,
+ const Format_description_log_event
+ *description_event);
/* returns the human readable name of the event's type */
const char* get_type_str();
};
+/*
+ One class for each type of event.
+ Two constructors for each class:
+ - one to create the event for logging (when the server acts as a master),
+ called after an update to the database is done,
+ which accepts parameters like the query, the database, the options for LOAD
+ DATA INFILE...
+ - one to create the event from a packet (when the server acts as a slave),
+ called before reproducing the update, which accepts parameters (like a
+ buffer). Used to read from the master, from the relay log, and in
+ mysqlbinlog. This constructor must be format-tolerant.
+*/
/*****************************************************************************
@@ -459,6 +670,7 @@ protected:
char* data_buf;
public:
const char* query;
+ const char* catalog;
const char* db;
/*
If we already know the length of the query string
@@ -469,13 +681,64 @@ public:
uint32 db_len;
uint16 error_code;
ulong thread_id;
- /*
- For events created by Query_log_event::exec_event (and
- Load_log_event::exec_event()) we need the *original* thread id, to be able
- to log the event with the original (=master's) thread id (fix for
- BUG#1686).
+ /*
+ For events created by Query_log_event::exec_event (and
+ Load_log_event::exec_event()) we need the *original* thread id, to be able
+ to log the event with the original (=master's) thread id (fix for
+ BUG#1686).
*/
ulong slave_proxy_id;
+
+ /*
+ Binlog format 3 and 4 start to differ (as far as class members are
+ concerned) from here.
+ */
+
+ uint catalog_len; // <= 255 char; 0 means uninited
+
+ /*
+ We want to be able to store a variable number of N-bit status vars:
+ (generally N=32; but N=64 for SQL_MODE) a user may want to log the number
+ of affected rows (for debugging) while another does not want to lose 4
+ bytes in this.
+ The storage on disk is the following:
+ status_vars_len is part of the post-header,
+ status_vars are in the variable-length part, after the post-header, before
+ the db & query.
+ status_vars on disk is a sequence of pairs (code, value) where 'code' means
+ 'sql_mode', 'affected' etc. Sometimes 'value' must be a short string, so
+ its first byte is its length. For now the order of status vars is:
+ flags2 - sql_mode - catalog - autoinc - charset
+ We should add the same thing to Load_log_event, but in fact
+ LOAD DATA INFILE is going to be logged with a new type of event (logging of
+ the plain text query), so Load_log_event would be frozen, so no need. The
+ new way of logging LOAD DATA INFILE would use a derived class of
+ Query_log_event, so automatically benefit from the work already done for
+ status variables in Query_log_event.
+ */
+ uint16 status_vars_len;
+
+ /*
+ 'flags2' is a second set of flags (on top of those in Log_event), for
+ session variables. These are thd->options which is & against a mask
+ (OPTIONS_WRITTEN_TO_BINLOG).
+ flags2_inited helps make a difference between flags2==0 (3.23 or 4.x
+ master, we don't know flags2, so use the slave server's global options) and
+ flags2==0 (5.0 master, we know this has a meaning of flags all down which
+ must influence the query).
+ */
+ bool flags2_inited;
+ bool sql_mode_inited;
+ bool charset_inited;
+
+ uint32 flags2;
+ /* In connections sql_mode is 32 bits now but will be 64 bits soon */
+ ulong sql_mode;
+ ulong auto_increment_increment, auto_increment_offset;
+ char charset[6];
+ uint time_zone_len; /* 0 means uninited */
+ const char *time_zone_str;
+
#ifndef MYSQL_CLIENT
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
@@ -484,31 +747,35 @@ public:
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
+ int exec_event(struct st_relay_log_info* rli, const char *query_arg,
+ uint32 q_len_arg);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
+ void print_query_header(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
#endif
- Query_log_event(const char* buf, int event_len, bool old_format);
+ Query_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event,
+ Log_event_type event_type);
~Query_log_event()
{
if (data_buf)
- {
my_free((gptr) data_buf, MYF(0));
- }
}
Log_event_type get_type_code() { return QUERY_EVENT; }
- int write(IO_CACHE* file);
- int write_data(IO_CACHE* file); // returns 0 on success, -1 on error
- bool is_valid() { return query != 0; }
- int get_data_size()
- {
- return (q_len + db_len + 2
- + 4 // thread_id
- + 4 // exec_time
- + 2 // error_code
- );
- }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+ virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
+#endif
+ bool is_valid() const { return query != 0; }
+
+ /*
+ Returns number of bytes additionaly written to post header by derived
+ events (so far it is only Execute_load_query event).
+ */
+ virtual ulong get_post_header_size_for_derived() { return 0; }
+ /* Writes derived event-specific part of post header. */
};
#ifdef HAVE_REPLICATION
@@ -518,6 +785,7 @@ public:
Slave Log Event class
Note that this class is currently not used at all; no code writes a
Slave_log_event (though some code in repl_failsafe.cc reads Slave_log_event).
+ So it's not a problem if this code is not maintained.
****************************************************************************/
class Slave_log_event: public Log_event
@@ -533,20 +801,22 @@ public:
int master_log_len;
uint16 master_port;
-#ifndef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+#endif
- Slave_log_event(const char* buf, int event_len);
+ Slave_log_event(const char* buf, uint event_len);
~Slave_log_event();
int get_data_size();
- bool is_valid() { return master_host != 0; }
+ bool is_valid() const { return master_host != 0; }
Log_event_type get_type_code() { return SLAVE_EVENT; }
- int write_data(IO_CACHE* file );
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
};
#endif /* HAVE_REPLICATION */
@@ -559,13 +829,23 @@ public:
****************************************************************************/
class Load_log_event: public Log_event
{
+private:
+ uint get_query_buffer_length();
+ void print_query(bool need_db, char *buf, char **end,
+ char **fn_start, char **fn_end);
protected:
- int copy_log_event(const char *buf, ulong event_len, bool old_format);
+ int copy_log_event(const char *buf, ulong event_len,
+ int body_offset, const Format_description_log_event* description_event);
public:
ulong thread_id;
ulong slave_proxy_id;
uint32 table_name_len;
+ /*
+ No need to have a catalog, as these events can only come from 4.x.
+ TODO: this may become false if Dmitri pushes his new LOAD DATA INFILE in
+ 5.0 only (not in 4.x).
+ */
uint32 db_len;
uint32 fname_len;
uint32 num_fields;
@@ -596,12 +876,13 @@ public:
#ifndef MYSQL_CLIENT
String field_lens_buf;
String fields_buf;
-
+
Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
const char* table_name_arg,
List<Item>& fields_arg, enum enum_duplicates handle_dup, bool ignore,
bool using_trans);
- void set_fields(const char* db, List<Item> &fields_arg);
+ void set_fields(const char* db, List<Item> &fields_arg,
+ Name_resolution_context *context);
const char* get_db() { return db; }
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
@@ -609,60 +890,76 @@ public:
{
return exec_event(thd->slave_net,rli,0);
}
- int exec_event(NET* net, struct st_relay_log_info* rli,
+ int exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
- void print(FILE* file, bool short_form, char* last_db, bool commented);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info = 0);
+ void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, bool commented);
#endif
- Load_log_event(const char* buf, int event_len, bool old_format);
+ /*
+ Note that for all the events related to LOAD DATA (Load_log_event,
+ Create_file/Append/Exec/Delete, we pass description_event; however as
+ logging of LOAD DATA is going to be changed in 4.1 or 5.0, this is only used
+ for the common_header_len (post_header_len will not be changed).
+ */
+ Load_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event);
~Load_log_event()
{}
Log_event_type get_type_code()
{
return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
}
- int write_data_header(IO_CACHE* file);
- int write_data_body(IO_CACHE* file);
- bool is_valid() { return table_name != 0; }
+#ifndef MYSQL_CLIENT
+ bool write_data_header(IO_CACHE* file);
+ bool write_data_body(IO_CACHE* file);
+#endif
+ bool is_valid() const { return table_name != 0; }
int get_data_size()
{
- return (table_name_len + 2 + db_len + 2 + fname_len
- + 4 // thread_id
- + 4 // exec_time
- + 4 // skip_lines
- + 4 // field block len
+ return (table_name_len + db_len + 2 + fname_len
+ + LOAD_HEADER_LEN
+ sql_ex.data_size() + field_block_len + num_fields);
}
- int get_data_body_offset() { return LOAD_EVENT_OVERHEAD; }
};
extern char server_version[SERVER_VERSION_LENGTH];
/*****************************************************************************
- Start Log Event class
+ Start Log Event_v3 class
+
+ Start_log_event_v3 is the Start_log_event of binlog format 3 (MySQL 3.23 and
+ 4.x).
+ Format_description_log_event derives from Start_log_event_v3; it is the
+ Start_log_event of binlog format 4 (MySQL 5.0), that is, the event that
+ describes the other events' header/postheader lengths. This event is sent by
+ MySQL 5.0 whenever it starts sending a new binlog if the requested position
+ is >4 (otherwise if ==4 the event will be sent naturally).
****************************************************************************/
-class Start_log_event: public Log_event
+
+class Start_log_event_v3: public Log_event
{
public:
- /*
- If this event is at the start of the first binary log since server startup
- 'created' should be the timestamp when the event (and the binary log) was
- created.
- In the other case (i.e. this event is at the start of a binary log created
- by FLUSH LOGS or automatic rotation), 'created' should be 0.
- This "trick" is used by MySQL >=4.0.14 slaves to know if they must drop the
- stale temporary tables or not.
- Note that when 'created'!=0, it is always equal to the event's timestamp;
- indeed Start_log_event is written only in log.cc where the first
- constructor below is called, in which 'created' is set to 'when'.
- So in fact 'created' is a useless variable. When it is 0
- we can read the actual value from timestamp ('when') and when it is
- non-zero we can read the same value from timestamp ('when'). Conclusion:
+ /*
+ If this event is at the start of the first binary log since server
+ startup 'created' should be the timestamp when the event (and the
+ binary log) was created. In the other case (i.e. this event is at
+ the start of a binary log created by FLUSH LOGS or automatic
+ rotation), 'created' should be 0. This "trick" is used by MySQL
+ >=4.0.14 slaves to know whether they must drop stale temporary
+ tables and whether they should abort unfinished transaction.
+
+ Note that when 'created'!=0, it is always equal to the event's
+ timestamp; indeed Start_log_event is written only in log.cc where
+ the first constructor below is called, in which 'created' is set
+ to 'when'. So in fact 'created' is a useless variable. When it is
+ 0 we can read the actual value from timestamp ('when') and when it
+ is non-zero we can read the same value from timestamp
+ ('when'). Conclusion:
- we use timestamp to print when the binlog was created.
- we use 'created' only to know if this is a first binlog or not.
In 3.23.57 we did not pay attention to this identity, so mysqlbinlog in
@@ -672,29 +969,89 @@ public:
time_t created;
uint16 binlog_version;
char server_version[ST_SERVER_VER_LEN];
+ /*
+ artifical_event is 1 in the case where this is a generated event that
+ should not case any cleanup actions. We handle this in the log by
+ setting log_event == 0 (for now).
+ */
+ bool artificial_event;
#ifndef MYSQL_CLIENT
- Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION)
- {
- created = (time_t) when;
- memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
- }
+ Start_log_event_v3();
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-
- Start_log_event(const char* buf, bool old_format);
- ~Start_log_event() {}
- Log_event_type get_type_code() { return START_EVENT;}
- int write_data(IO_CACHE* file);
- bool is_valid() { return 1; }
+ Start_log_event_v3() {}
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+#endif
+
+ Start_log_event_v3(const char* buf,
+ const Format_description_log_event* description_event);
+ ~Start_log_event_v3() {}
+ Log_event_type get_type_code() { return START_EVENT_V3;}
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
+ bool is_valid() const { return 1; }
+ int get_data_size()
+ {
+ return START_V3_HEADER_LEN; //no variable-sized part
+ }
+ virtual bool is_artificial_event() { return artificial_event; }
+};
+
+
+/*
+ For binlog version 4.
+ This event is saved by threads which read it, as they need it for future
+ use (to decode the ordinary events).
+*/
+
+class Format_description_log_event: public Start_log_event_v3
+{
+public:
+ /*
+ The size of the fixed header which _all_ events have
+ (for binlogs written by this version, this is equal to
+ LOG_EVENT_HEADER_LEN), except FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT
+ (those have a header of size LOG_EVENT_MINIMAL_HEADER_LEN).
+ */
+ uint8 common_header_len;
+ uint8 number_of_event_types;
+ /* The list of post-headers' lengthes */
+ uint8 *post_header_len;
+
+ Format_description_log_event(uint8 binlog_ver, const char* server_ver=0);
+
+#ifndef MYSQL_CLIENT
+#ifdef HAVE_REPLICATION
+ int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
+#endif
+
+ Format_description_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event);
+ ~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); }
+ Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;}
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
+ bool is_valid() const
+ {
+ return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN :
+ LOG_EVENT_MINIMAL_HEADER_LEN)) &&
+ (post_header_len != NULL));
+ }
int get_data_size()
{
- return START_HEADER_LEN;
+ /*
+ The vector of post-header lengths is considered as part of the
+ post-header, because in a given version it never changes (contrary to the
+ query in a Query_log_event).
+ */
+ return FORMAT_DESCRIPTION_HEADER_LEN;
}
};
@@ -706,13 +1063,14 @@ public:
Logs special variables such as auto_increment values
****************************************************************************/
+
class Intvar_log_event: public Log_event
{
public:
ulonglong val;
uchar type;
-#ifndef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
:Log_event(thd_arg,0,0),val(val_arg),type(type_arg)
{}
@@ -721,25 +1079,32 @@ public:
int exec_event(struct st_relay_log_info* rli);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+#endif
- Intvar_log_event(const char* buf, bool old_format);
+ Intvar_log_event(const char* buf, const Format_description_log_event* description_event);
~Intvar_log_event() {}
Log_event_type get_type_code() { return INTVAR_EVENT;}
const char* get_var_type_name();
int get_data_size() { return 9; /* sizeof(type) + sizeof(val) */;}
- int write_data(IO_CACHE* file);
- bool is_valid() { return 1; }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
+ bool is_valid() const { return 1; }
};
+
/*****************************************************************************
Rand Log Event class
- Logs random seed used by the next RAND(), and by PASSWORD() in 4.1.
+ Logs random seed used by the next RAND(), and by PASSWORD() in 4.1.0.
+ 4.1.1 does not need it (it's repeatable again) so this event needn't be
+ written in 4.1.1 for PASSWORD() (but the fact that it is written is just a
+ waste, it does not cause bugs).
****************************************************************************/
+
class Rand_log_event: public Log_event
{
public:
@@ -755,15 +1120,54 @@ class Rand_log_event: public Log_event
int exec_event(struct st_relay_log_info* rli);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
#endif
- Rand_log_event(const char* buf, bool old_format);
+ Rand_log_event(const char* buf, const Format_description_log_event* description_event);
~Rand_log_event() {}
Log_event_type get_type_code() { return RAND_EVENT;}
int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ }
- int write_data(IO_CACHE* file);
- bool is_valid() { return 1; }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
+ bool is_valid() const { return 1; }
+};
+
+/*****************************************************************************
+
+ Xid Log Event class
+
+ Logs xid of the transaction-to-be-committed in the 2pc protocol.
+ Has no meaning in replication, slaves ignore it.
+
+ ****************************************************************************/
+#ifdef MYSQL_CLIENT
+typedef ulonglong my_xid; // this line is the same as in handler.h
+#endif
+
+class Xid_log_event: public Log_event
+{
+ public:
+ my_xid xid;
+
+#ifndef MYSQL_CLIENT
+ Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg,0,0), xid(x) {}
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
+ int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
+#else
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+#endif
+
+ Xid_log_event(const char* buf, const Format_description_log_event* description_event);
+ ~Xid_log_event() {}
+ Log_event_type get_type_code() { return XID_EVENT;}
+ int get_data_size() { return sizeof(xid); }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
+ bool is_valid() const { return 1; }
};
/*****************************************************************************
@@ -774,6 +1178,7 @@ class Rand_log_event: public Log_event
written before the Query_log_event, to set the user variable.
****************************************************************************/
+
class User_var_log_event: public Log_event
{
public:
@@ -794,29 +1199,24 @@ public:
void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
#endif
- User_var_log_event(const char* buf, bool old_format);
+ User_var_log_event(const char* buf, const Format_description_log_event* description_event);
~User_var_log_event() {}
Log_event_type get_type_code() { return USER_VAR_EVENT;}
- int get_data_size()
- {
- return (is_null ? UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL :
- UV_NAME_LEN_SIZE + name_len + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
- UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE + val_len);
- }
- int write_data(IO_CACHE* file);
- bool is_valid() { return 1; }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
+ bool is_valid() const { return 1; }
};
+
/*****************************************************************************
Stop Log Event class
****************************************************************************/
-#ifdef HAVE_REPLICATION
-
class Stop_log_event: public Log_event
{
public:
@@ -825,27 +1225,25 @@ public:
{}
int exec_event(struct st_relay_log_info* rli);
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+#endif
- Stop_log_event(const char* buf, bool old_format):
- Log_event(buf, old_format)
+ Stop_log_event(const char* buf, const Format_description_log_event* description_event):
+ Log_event(buf, description_event)
{}
~Stop_log_event() {}
Log_event_type get_type_code() { return STOP_EVENT;}
- bool is_valid() { return 1; }
+ bool is_valid() const { return 1; }
};
-#endif /* HAVE_REPLICATION */
-
-
/*****************************************************************************
Rotate Log Event class
- This will be depricated when we move to using sequence ids.
+ This will be deprecated when we move to using sequence ids.
****************************************************************************/
+
class Rotate_log_event: public Log_event
{
public:
@@ -853,7 +1251,7 @@ public:
ulonglong pos;
uint ident_len;
bool alloced;
-#ifndef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
uint ident_len_arg = 0,
ulonglong pos_arg = LOG_EVENT_OFFSET)
@@ -866,10 +1264,11 @@ public:
int exec_event(struct st_relay_log_info* rli);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
#endif
- Rotate_log_event(const char* buf, int event_len, bool old_format);
+ Rotate_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event);
~Rotate_log_event()
{
if (alloced)
@@ -877,17 +1276,19 @@ public:
}
Log_event_type get_type_code() { return ROTATE_EVENT;}
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
- bool is_valid() { return new_log_ident != 0; }
- int write_data(IO_CACHE* file);
+ bool is_valid() const { return new_log_ident != 0; }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
};
+
/* the classes below are for the new LOAD DATA INFILE logging */
/*****************************************************************************
-
Create File Log Event class
-
****************************************************************************/
+
class Create_file_log_event: public Load_log_event
{
protected:
@@ -896,7 +1297,7 @@ protected:
our Load part - used on the slave when writing event out to
SQL_LOAD-*.info file
*/
- bool fake_base;
+ bool fake_base;
public:
char* block;
const char *event_buf;
@@ -916,11 +1317,12 @@ public:
int exec_event(struct st_relay_log_info* rli);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
- void print(FILE* file, bool short_form, char* last_db, bool enable_local);
-#endif
-
- Create_file_log_event(const char* buf, int event_len, bool old_format);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+ void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, bool enable_local);
+#endif
+
+ Create_file_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event);
~Create_file_log_event()
{
my_free((char*) event_buf, MYF(MY_ALLOW_ZERO_PTR));
@@ -936,19 +1338,16 @@ public:
Load_log_event::get_data_size() +
4 + 1 + block_len);
}
- int get_data_body_offset()
- {
- return (fake_base ? LOAD_EVENT_OVERHEAD:
- LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN);
- }
- bool is_valid() { return inited_from_old || block != 0; }
- int write_data_header(IO_CACHE* file);
- int write_data_body(IO_CACHE* file);
+ bool is_valid() const { return inited_from_old || block != 0; }
+#ifndef MYSQL_CLIENT
+ bool write_data_header(IO_CACHE* file);
+ bool write_data_body(IO_CACHE* file);
/*
Cut out Create_file extentions and
write it as Load event - used on the slave
*/
- int write_base(IO_CACHE* file);
+ bool write_base(IO_CACHE* file);
+#endif
};
@@ -957,6 +1356,7 @@ public:
Append Block Log Event class
****************************************************************************/
+
class Append_block_log_event: public Log_event
{
public:
@@ -964,14 +1364,15 @@ public:
uint block_len;
uint file_id;
/*
- 'db' is filled when the event is created in mysql_load() (the event needs to
- have a 'db' member to be well filtered by binlog-*-db rules). 'db' is not
- written to the binlog (it's not used by Append_block_log_event::write()), so
- it can't be read in the Append_block_log_event(const char* buf, int
- event_len) constructor.
- In other words, 'db' is used only for filtering by binlog-*-db rules.
- Create_file_log_event is different: its 'db' (which is inherited from
- Load_log_event) is written to the binlog and can be re-read.
+ 'db' is filled when the event is created in mysql_load() (the
+ event needs to have a 'db' member to be well filtered by
+ binlog-*-db rules). 'db' is not written to the binlog (it's not
+ used by Append_block_log_event::write()), so it can't be read in
+ the Append_block_log_event(const char* buf, int event_len)
+ constructor. In other words, 'db' is used only for filtering by
+ binlog-*-db rules. Create_file_log_event is different: it's 'db'
+ (which is inherited from Load_log_event) is written to the binlog
+ and can be re-read.
*/
const char* db;
@@ -981,31 +1382,37 @@ public:
#ifdef HAVE_REPLICATION
int exec_event(struct st_relay_log_info* rli);
void pack_info(Protocol* protocol);
+ virtual int get_create_or_append() const;
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
#endif
-
- Append_block_log_event(const char* buf, int event_len);
+
+ Append_block_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event);
~Append_block_log_event() {}
Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;}
int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;}
- bool is_valid() { return block != 0; }
- int write_data(IO_CACHE* file);
+ bool is_valid() const { return block != 0; }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
const char* get_db() { return db; }
};
+
/*****************************************************************************
Delete File Log Event class
****************************************************************************/
+
class Delete_file_log_event: public Log_event
{
public:
uint file_id;
const char* db; /* see comment in Append_block_log_event */
-
+
#ifndef MYSQL_CLIENT
Delete_file_log_event(THD* thd, const char* db_arg, bool using_trans);
#ifdef HAVE_REPLICATION
@@ -1013,29 +1420,34 @@ public:
int exec_event(struct st_relay_log_info* rli);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
- void print(FILE* file, bool short_form, char* last_db, bool enable_local);
-#endif
-
- Delete_file_log_event(const char* buf, int event_len);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+ void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, bool enable_local);
+#endif
+
+ Delete_file_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event);
~Delete_file_log_event() {}
Log_event_type get_type_code() { return DELETE_FILE_EVENT;}
int get_data_size() { return DELETE_FILE_HEADER_LEN ;}
- bool is_valid() { return file_id != 0; }
- int write_data(IO_CACHE* file);
+ bool is_valid() const { return file_id != 0; }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
const char* get_db() { return db; }
};
+
/*****************************************************************************
Execute Load Log Event class
****************************************************************************/
+
class Execute_load_log_event: public Log_event
{
public:
uint file_id;
- const char* db; /* see comment in Append_block_log_event */
+ const char* db; /* see comment in Append_block_log_event */
#ifndef MYSQL_CLIENT
Execute_load_log_event(THD* thd, const char* db_arg, bool using_trans);
@@ -1044,30 +1456,128 @@ public:
int exec_event(struct st_relay_log_info* rli);
#endif /* HAVE_REPLICATION */
#else
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-
- Execute_load_log_event(const char* buf, int event_len);
+ void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
+#endif
+
+ Execute_load_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event);
~Execute_load_log_event() {}
Log_event_type get_type_code() { return EXEC_LOAD_EVENT;}
int get_data_size() { return EXEC_LOAD_HEADER_LEN ;}
- bool is_valid() { return file_id != 0; }
- int write_data(IO_CACHE* file);
+ bool is_valid() const { return file_id != 0; }
+#ifndef MYSQL_CLIENT
+ bool write(IO_CACHE* file);
+#endif
const char* get_db() { return db; }
};
+
+/***************************************************************************
+
+ Begin load query Log Event class
+
+ Event for the first block of file to be loaded, its only difference from
+ Append_block event is that this event creates or truncates existing file
+ before writing data.
+
+****************************************************************************/
+class Begin_load_query_log_event: public Append_block_log_event
+{
+public:
+#ifndef MYSQL_CLIENT
+ Begin_load_query_log_event(THD* thd_arg, const char *db_arg,
+ char* block_arg, uint block_len_arg,
+ bool using_trans);
+#ifdef HAVE_REPLICATION
+ Begin_load_query_log_event(THD* thd);
+ int get_create_or_append() const;
+#endif /* HAVE_REPLICATION */
+#endif
+ Begin_load_query_log_event(const char* buf, uint event_len,
+ const Format_description_log_event* description_event);
+ ~Begin_load_query_log_event() {}
+ Log_event_type get_type_code() { return BEGIN_LOAD_QUERY_EVENT; }
+};
+
+
+/*
+ Elements of this enum describe how LOAD DATA handles duplicates.
+*/
+enum enum_load_dup_handling { LOAD_DUP_ERROR= 0, LOAD_DUP_IGNORE,
+ LOAD_DUP_REPLACE };
+
+/****************************************************************************
+
+ Execute load query Log Event class
+
+ Event responsible for LOAD DATA execution, it similar to Query_log_event
+ but before executing the query it substitutes original filename in LOAD DATA
+ query with name of temporary file.
+
+****************************************************************************/
+class Execute_load_query_log_event: public Query_log_event
+{
+public:
+ uint file_id; // file_id of temporary file
+ uint fn_pos_start; // pointer to the part of the query that should
+ // be substituted
+ uint fn_pos_end; // pointer to the end of this part of query
+ /*
+ We have to store type of duplicate handling explicitly, because
+ for LOAD DATA it also depends on LOCAL option. And this part
+ of query will be rewritten during replication so this information
+ may be lost...
+ */
+ enum_load_dup_handling dup_handling;
+
+#ifndef MYSQL_CLIENT
+ Execute_load_query_log_event(THD* thd, const char* query_arg,
+ ulong query_length, uint fn_pos_start_arg,
+ uint fn_pos_end_arg,
+ enum_load_dup_handling dup_handling_arg,
+ bool using_trans, bool suppress_use);
+#ifdef HAVE_REPLICATION
+ void pack_info(Protocol* protocol);
+ int exec_event(struct st_relay_log_info* rli);
+#endif /* HAVE_REPLICATION */
+#else
+ void print(FILE* file, bool short_form = 0,
+ LAST_EVENT_INFO* last_event_info= 0);
+ /* Prints the query as LOAD DATA LOCAL and with rewritten filename */
+ void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info,
+ const char *local_fname);
+#endif
+ Execute_load_query_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event);
+ ~Execute_load_query_log_event() {}
+
+ Log_event_type get_type_code() { return EXECUTE_LOAD_QUERY_EVENT; }
+ bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; }
+
+ ulong get_post_header_size_for_derived();
+#ifndef MYSQL_CLIENT
+ bool write_post_header_for_derived(IO_CACHE* file);
+#endif
+ };
+
+
#ifdef MYSQL_CLIENT
class Unknown_log_event: public Log_event
{
public:
- Unknown_log_event(const char* buf, bool old_format):
- Log_event(buf, old_format)
+ /*
+ Even if this is an unknown event, we still pass description_event to
+ Log_event's ctor, this way we can extract maximum information from the
+ event's header (the unique ID for example).
+ */
+ Unknown_log_event(const char* buf, const Format_description_log_event* description_event):
+ Log_event(buf, description_event)
{}
~Unknown_log_event() {}
- void print(FILE* file, bool short_form= 0, char* last_db= 0);
+ void print(FILE* file, bool short_form= 0, LAST_EVENT_INFO* last_event_info= 0);
Log_event_type get_type_code() { return UNKNOWN_EVENT;}
- bool is_valid() { return 1; }
+ bool is_valid() const { return 1; }
};
-#endif
+#endif
char *str_to_hex(char *to, const char *from, uint len);
#endif /* _log_event_h */
diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc
new file mode 100644
index 00000000000..f188d27ff78
--- /dev/null
+++ b/sql/my_decimal.cc
@@ -0,0 +1,235 @@
+/* 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 "mysql_priv.h"
+
+#ifndef MYSQL_CLIENT
+/*
+ report result of decimal operation
+
+ SYNOPSIS
+ decimal_operation_results()
+ result decimal library return code (E_DEC_* see include/decimal.h)
+
+ TODO
+ Fix error messages
+
+ RETURN
+ result
+*/
+
+int decimal_operation_results(int result)
+{
+ switch (result) {
+ case E_DEC_OK:
+ break;
+ case E_DEC_TRUNCATED:
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
+ "", (long)-1);
+ break;
+ case E_DEC_OVERFLOW:
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE),
+ "DECIMAL", "");
+ break;
+ case E_DEC_DIV_ZERO:
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
+ break;
+ case E_DEC_BAD_NUM:
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+ ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
+ "decimal", "", "", (long)-1);
+ break;
+ case E_DEC_OOM:
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ return result;
+}
+
+
+/*
+ Converting decimal to string
+
+ SYNOPSIS
+ my_decimal2string()
+
+ return
+ E_DEC_OK
+ E_DEC_TRUNCATED
+ E_DEC_OVERFLOW
+ E_DEC_OOM
+*/
+
+int my_decimal2string(uint mask, const my_decimal *d,
+ uint fixed_prec, uint fixed_dec,
+ char filler, String *str)
+{
+ int length= (fixed_prec ? (fixed_prec + 1) : my_decimal_string_length(d));
+ int result;
+ if (str->alloc(length))
+ return check_result(mask, E_DEC_OOM);
+ result= decimal2string((decimal_t*) d, (char*) str->ptr(),
+ &length, (int)fixed_prec, fixed_dec,
+ filler);
+ str->length(length);
+ return check_result(mask, result);
+}
+
+
+/*
+ Convert from decimal to binary representation
+
+ SYNOPSIS
+ my_decimal2binary()
+ mask error processing mask
+ d number for conversion
+ bin pointer to buffer where to write result
+ prec overall number of decimal digits
+ scale number of decimal digits after decimal point
+
+ NOTE
+ Before conversion we round number if it need but produce truncation
+ error in this case
+
+ RETURN
+ E_DEC_OK
+ E_DEC_TRUNCATED
+ E_DEC_OVERFLOW
+*/
+
+int my_decimal2binary(uint mask, const my_decimal *d, char *bin, int prec,
+ int scale)
+{
+ int err1= E_DEC_OK, err2;
+ my_decimal rounded;
+ my_decimal2decimal(d, &rounded);
+ rounded.frac= decimal_actual_fraction(&rounded);
+ if (scale < rounded.frac)
+ {
+ err1= E_DEC_TRUNCATED;
+ /* decimal_round can return only E_DEC_TRUNCATED */
+ decimal_round(&rounded, &rounded, scale, HALF_UP);
+ }
+ err2= decimal2bin(&rounded, bin, prec, scale);
+ if (!err2)
+ err2= err1;
+ return check_result(mask, err2);
+}
+
+
+/*
+ Convert string for decimal when string can be in some multibyte charset
+
+ SYNOPSIS
+ str2my_decimal()
+ mask error processing mask
+ from string to process
+ length length of given string
+ charset charset of given string
+ decimal_value buffer for result storing
+
+ RESULT
+ E_DEC_OK
+ E_DEC_TRUNCATED
+ E_DEC_OVERFLOW
+ E_DEC_BAD_NUM
+ E_DEC_OOM
+*/
+
+int str2my_decimal(uint mask, const char *from, uint length,
+ CHARSET_INFO *charset, my_decimal *decimal_value)
+{
+ char *end, *from_end;
+ int err;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+ if (charset->mbminlen > 1)
+ {
+ uint dummy_errors;
+ tmp.copy(from, length, charset, &my_charset_latin1, &dummy_errors);
+ from= tmp.ptr();
+ length= tmp.length();
+ charset= &my_charset_bin;
+ }
+ from_end= end= (char*) from+length;
+ err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
+ if (end != from_end && !err)
+ {
+ /* Give warning if there is something other than end space */
+ for ( ; end < from_end; end++)
+ {
+ if (!my_isspace(&my_charset_latin1, *end))
+ {
+ err= E_DEC_TRUNCATED;
+ break;
+ }
+ }
+ }
+ check_result(mask, err);
+ return err;
+}
+
+
+#ifndef DBUG_OFF
+/* routines for debugging print */
+
+/* print decimal */
+void
+print_decimal(const my_decimal *dec)
+{
+ fprintf(DBUG_FILE,
+ "\nDecimal: sign: %d intg: %d frac: %d \n\
+%09d,%09d,%09d,%09d,%09d,%09d,%09d,%09d\n",
+ dec->sign(), dec->intg, dec->frac,
+ dec->buf[0], dec->buf[1], dec->buf[2], dec->buf[3],
+ dec->buf[4], dec->buf[5], dec->buf[6], dec->buf[7]);
+}
+
+
+/* print decimal with its binary representation */
+void
+print_decimal_buff(const my_decimal *dec, const byte* ptr, int length)
+{
+ print_decimal(dec);
+ fprintf(DBUG_FILE, "Record: ");
+ for (int i= 0; i < length; i++)
+ {
+ fprintf(DBUG_FILE, "%02X ", (uint)((uchar *)ptr)[i]);
+ }
+ fprintf(DBUG_FILE, "\n");
+}
+
+
+const char *dbug_decimal_as_string(char *buff, const my_decimal *val)
+{
+ int length= DECIMAL_MAX_STR_LENGTH;
+ if (!val)
+ return "NULL";
+ (void)decimal2string((decimal_t*) val, buff, &length, 0,0,0);
+ return buff;
+}
+
+#endif /*DBUG_OFF*/
+
+
+#endif /*MYSQL_CLIENT*/
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
new file mode 100644
index 00000000000..b65e6aedaa2
--- /dev/null
+++ b/sql/my_decimal.h
@@ -0,0 +1,359 @@
+/* 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 */
+
+/*
+ It is interface module to fixed precision decimals library.
+
+ Most functions use 'uint mask' as parameter, if during operation error
+ which fit in this mask is detected then it will be processed automatically
+ here. (errors are E_DEC_* constants, see include/decimal.h)
+
+ Most function are just inline wrappers around library calls
+*/
+
+#ifndef my_decimal_h
+#define my_decimal_h
+
+C_MODE_START
+#include <decimal.h>
+C_MODE_END
+
+#define DECIMAL_LONGLONG_DIGITS 22
+#define DECIMAL_LONG_DIGITS 10
+#define DECIMAL_LONG3_DIGITS 8
+
+/* maximum length of buffer in our big digits (uint32) */
+#define DECIMAL_BUFF_LENGTH 9
+/*
+ maximum guaranteed precision of number in decimal digits (number of our
+ digits * number of decimal digits in one our big digit - number of decimal
+ digits in one our big digit decreased on 1 (because we always put decimal
+ point on the border of our big digits))
+*/
+#define DECIMAL_MAX_PRECISION ((DECIMAL_BUFF_LENGTH * 9) - 8*2)
+#define DECIMAL_MAX_SCALE 30
+#define DECIMAL_NOT_SPECIFIED 31
+
+/*
+ maximum length of string representation (number of maximum decimal
+ digits + 1 position for sign + 1 position for decimal point)
+*/
+#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_PRECISION + 2)
+/*
+ maximum size of packet length
+*/
+#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
+
+
+inline uint my_decimal_size(uint precision, uint scale)
+{
+ /*
+ Always allocate more space to allow library to put decimal point
+ where it want
+ */
+ return decimal_size(precision, scale) + 1;
+}
+
+
+inline int my_decimal_int_part(uint precision, uint decimals)
+{
+ return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
+}
+
+
+/*
+ my_decimal class limits 'decimal_t' type to what we need in MySQL
+ It contains internally all necessary space needed by the instance so
+ no extra memory is needed. One should call fix_buffer_pointer() function
+ when he moves my_decimal objects in memory
+*/
+
+class my_decimal :public decimal_t
+{
+ decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
+
+public:
+
+ void init()
+ {
+ len= DECIMAL_BUFF_LENGTH;
+ buf= buffer;
+#if !defined (HAVE_purify) && !defined(DBUG_OFF)
+ /* Set buffer to 'random' value to find wrong buffer usage */
+ for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
+ buffer[i]= i;
+#endif
+ }
+ my_decimal()
+ {
+ init();
+ }
+ void fix_buffer_pointer() { buf= buffer; }
+
+ bool sign() const { return decimal_t::sign; }
+ void sign(bool s) { decimal_t::sign= s; }
+ uint precision() const { return intg + frac; }
+};
+
+
+#ifndef DBUG_OFF
+void print_decimal(const my_decimal *dec);
+void print_decimal_buff(const my_decimal *dec, const byte* ptr, int length);
+const char *dbug_decimal_as_string(char *buff, const my_decimal *val);
+#else
+#define dbug_decimal_as_string(A) NULL
+#endif
+
+#ifndef MYSQL_CLIENT
+int decimal_operation_results(int result);
+#else
+inline int decimal_operation_results(int result)
+{
+ return result;
+}
+#endif /*MYSQL_CLIENT*/
+
+inline int check_result(uint mask, int result)
+{
+ if (result & mask)
+ decimal_operation_results(result);
+ return result;
+}
+
+inline uint my_decimal_length_to_precision(uint length, uint scale,
+ bool unsigned_flag)
+{
+ return (uint) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
+}
+
+inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
+ bool unsigned_flag)
+{
+ set_if_smaller(precision, DECIMAL_MAX_PRECISION);
+ return (uint32)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
+}
+
+inline
+int my_decimal_string_length(const my_decimal *d)
+{
+ return decimal_string_size(d);
+}
+
+
+inline
+int my_decimal_max_length(const my_decimal *d)
+{
+ /* -1 because we do not count \0 */
+ return decimal_string_size(d) - 1;
+}
+
+
+inline
+int my_decimal_get_binary_size(uint precision, uint scale)
+{
+ return decimal_bin_size((int)precision, (int)scale);
+}
+
+
+inline
+void my_decimal2decimal(const my_decimal *from, my_decimal *to)
+{
+ *to= *from;
+ to->fix_buffer_pointer();
+}
+
+
+int my_decimal2binary(uint mask, const my_decimal *d, char *bin, int prec,
+ int scale);
+
+
+inline
+int binary2my_decimal(uint mask, const char *bin, my_decimal *d, int prec,
+ int scale)
+{
+ return check_result(mask, bin2decimal((char *)bin, (decimal_t*) d, prec,
+ scale));
+}
+
+
+inline
+int my_decimal_set_zero(my_decimal *d)
+{
+ decimal_make_zero(((decimal_t*) d));
+ return 0;
+}
+
+
+inline
+bool my_decimal_is_zero(const my_decimal *decimal_value)
+{
+ return decimal_is_zero((decimal_t*) decimal_value);
+}
+
+
+inline
+int my_decimal_round(uint mask, const my_decimal *from, int scale,
+ bool truncate, my_decimal *to)
+{
+ return check_result(mask, decimal_round((decimal_t*) from, to, scale,
+ (truncate ? TRUNCATE : HALF_UP)));
+}
+
+
+inline
+int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
+{
+ return check_result(mask, decimal_round((decimal_t*) from, to, 0, FLOOR));
+}
+
+
+inline
+int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
+{
+ return check_result(mask, decimal_round((decimal_t*) from, to, 0, CEILING));
+}
+
+
+#ifndef MYSQL_CLIENT
+int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
+ uint fixed_dec, char filler, String *str);
+#endif
+
+inline
+int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag,
+ longlong *l)
+{
+ my_decimal rounded;
+ /* decimal_round can return only E_DEC_TRUNCATED */
+ decimal_round((decimal_t*)d, &rounded, 0, HALF_UP);
+ return check_result(mask, (unsigned_flag ?
+ decimal2ulonglong(&rounded, (ulonglong *)l) :
+ decimal2longlong(&rounded, l)));
+}
+
+
+inline
+int my_decimal2double(uint mask, const my_decimal *d, double *result)
+{
+ /* No need to call check_result as this will always succeed */
+ return decimal2double((decimal_t*) d, result);
+}
+
+
+inline
+int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end)
+{
+ return check_result(mask, string2decimal(str, (decimal_t*) d, end));
+}
+
+
+int str2my_decimal(uint mask, const char *from, uint length,
+ CHARSET_INFO *charset, my_decimal *decimal_value);
+
+#if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
+inline
+int string2my_decimal(uint mask, const String *str, my_decimal *d)
+{
+ return str2my_decimal(mask, str->ptr(), str->length(), str->charset(), d);
+}
+#endif
+
+inline
+int double2my_decimal(uint mask, double val, my_decimal *d)
+{
+ return check_result(mask, double2decimal(val, (decimal_t*) d));
+}
+
+
+inline
+int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d)
+{
+ return check_result(mask, (unsigned_flag ?
+ ulonglong2decimal((ulonglong)i, d) :
+ longlong2decimal(i, d)));
+}
+
+
+inline
+void my_decimal_neg(decimal_t *arg)
+{
+ if (decimal_is_zero(arg))
+ {
+ arg->sign= 0;
+ return;
+ }
+ decimal_neg(arg);
+}
+
+
+inline
+int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b)
+{
+ return check_result(mask, decimal_add((decimal_t*) a, (decimal_t*) b, res));
+}
+
+
+inline
+int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b)
+{
+ return check_result(mask, decimal_sub((decimal_t*) a, (decimal_t*) b, res));
+}
+
+
+inline
+int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b)
+{
+ return check_result(mask, decimal_mul((decimal_t*) a, (decimal_t*) b, res));
+}
+
+
+inline
+int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b, int div_scale_inc)
+{
+ return check_result(mask, decimal_div((decimal_t*) a, (decimal_t*) b, res,
+ div_scale_inc));
+}
+
+
+inline
+int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b)
+{
+ return check_result(mask, decimal_mod((decimal_t*) a, (decimal_t*) b, res));
+}
+
+
+/* Returns -1 if a<b, 1 if a>b and 0 if a==b */
+inline
+int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
+{
+ return decimal_cmp((decimal_t*) a, (decimal_t*) b);
+}
+
+inline
+void max_my_decimal(my_decimal *to, int precision, int frac)
+{
+ DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
+ (frac <= DECIMAL_MAX_SCALE));
+ max_decimal(precision, frac, (decimal_t*) to);
+}
+
+#endif /*my_decimal_h*/
+
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 32c5861028e..2d45360ab64 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -14,6 +14,15 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/*
+ Mostly this file is used in the server. But a little part of it is used in
+ mysqlbinlog too (definition of SELECT_DISTINCT and others).
+ The consequence is that 90% of the file is wrapped in #ifndef MYSQL_CLIENT,
+ except the part which must be in the server and in the client.
+*/
+
+#ifndef MYSQL_CLIENT
+
#include <my_global.h>
#include <mysql_version.h>
#include <mysql_embed.h>
@@ -25,6 +34,7 @@
#include <thr_lock.h>
#include <my_base.h> /* Needed by field.h */
#include "sql_bitmap.h"
+#include "sql_array.h"
#ifdef __EMX__
#undef write /* remove pthread.h macro definition for EMX */
@@ -35,6 +45,13 @@ typedef ulonglong table_map; /* Used for table bits in join */
typedef Bitmap<64> key_map; /* Used for finding keys */
typedef ulong key_part_map; /* Used for finding key parts */
+/* query_id */
+typedef ulonglong query_id_t;
+extern query_id_t query_id;
+
+/* increment query_id and return it. */
+inline query_id_t next_query_id() { return query_id++; }
+
/* useful constants */
extern const key_map key_map_empty;
extern key_map key_map_full; /* Should be threaded as const */
@@ -55,11 +72,10 @@ char *sql_strmake_with_convert(const char *str, uint32 arg_length,
CHARSET_INFO *from_cs,
uint32 max_res_length,
CHARSET_INFO *to_cs, uint32 *result_length);
-void kill_one_thread(THD *thd, ulong id);
+void kill_one_thread(THD *thd, ulong id, bool only_kill_query);
bool net_request_file(NET* net, const char* fname);
char* query_table_status(THD *thd,const char *db,const char *table_name);
-
#define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); }
#define safeFree(x) { if(x) { my_free((gptr) x,MYF(0)); x = NULL; } }
#define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
@@ -79,7 +95,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MAX_FIELDS_BEFORE_HASH 32
#define USER_VARS_HASH_SIZE 16
#define STACK_MIN_SIZE 8192 // Abort if less stack during eval.
-#define STACK_BUFF_ALLOC 64 // For stack overrun checks
+#define STACK_BUFF_ALLOC 256 // For stack overrun checks
#ifndef MYSQLD_NET_RETRY_COUNT
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
#endif
@@ -101,7 +117,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
The following parameters is to decide when to use an extra cache to
optimise seeks when reading a big table in sorted order
*/
-#define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (16L*1024*1024)
+#define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (10L*1024*1024)
#define MIN_ROWS_TO_USE_TABLE_CACHE 100
#define MIN_ROWS_TO_USE_BULK_INSERT 100
@@ -113,6 +129,26 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define TIME_FOR_COMPARE 5 // 5 compares == one read
/*
+ Number of comparisons of table rowids equivalent to reading one row from a
+ table.
+*/
+#define TIME_FOR_COMPARE_ROWID (TIME_FOR_COMPARE*2)
+
+/*
+ For sequential disk seeks the cost formula is:
+ DISK_SEEK_BASE_COST + DISK_SEEK_PROP_COST * #blocks_to_skip
+
+ The cost of average seek
+ DISK_SEEK_BASE_COST + DISK_SEEK_PROP_COST*BLOCKS_IN_AVG_SEEK =1.0.
+*/
+#define DISK_SEEK_BASE_COST ((double)0.5)
+
+#define BLOCKS_IN_AVG_SEEK 128
+
+#define DISK_SEEK_PROP_COST ((double)0.5/BLOCKS_IN_AVG_SEEK)
+
+
+/*
Number of rows in a reference table when refereed through a not unique key.
This value is only used when we don't know anything about the key
distribution.
@@ -143,6 +179,17 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define FLUSH_TIME 0 /* Don't flush tables */
#define MAX_CONNECT_ERRORS 10 // errors before disabling host
+#ifdef HAVE_INNOBASE_DB
+#define IF_INNOBASE_DB(A, B) (A)
+#else
+#define IF_INNOBASE_DB(A, B) (B)
+#endif
+#ifdef __NETWARE__
+#define IF_NETWARE(A,B) (A)
+#else
+#define IF_NETWARE(A,B) (B)
+#endif
+
#if defined(__WIN__) || defined(OS2)
#define IF_WIN(A,B) (A)
#undef FLUSH_TIME
@@ -172,64 +219,91 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define TEST_CORE_ON_SIGNAL 256 /* Give core if signal */
#define TEST_NO_STACKTRACE 512
#define TEST_SIGINT 1024 /* Allow sigint on threads */
-#define TEST_SYNCHRONIZATION 2048 /* get server to do sleep in some
- places */
-
-/* options for select set by the yacc parser (stored in lex->options) */
-#define SELECT_DISTINCT (1L << 0)
-#define SELECT_STRAIGHT_JOIN (1L << 1)
-#define SELECT_DESCRIBE (1L << 2)
-#define SELECT_SMALL_RESULT (1L << 3)
-#define SELECT_BIG_RESULT (1L << 4)
-#define OPTION_FOUND_ROWS (1L << 5)
-#define OPTION_TO_QUERY_CACHE (1L << 6)
-#define SELECT_NO_JOIN_CACHE (1L << 7) /* Intern */
-#define OPTION_BIG_TABLES (1L << 8) /* for SQL OPTION */
-#define OPTION_BIG_SELECTS (1L << 9) /* for SQL OPTION */
-#define OPTION_LOG_OFF (1L << 10)
-#define OPTION_UPDATE_LOG (1L << 11) /* update log flag */
-#define TMP_TABLE_ALL_COLUMNS (1L << 12)
-#define OPTION_WARNINGS (1L << 13)
-#define OPTION_AUTO_IS_NULL (1L << 14)
-#define OPTION_FOUND_COMMENT (1L << 15)
-#define OPTION_SAFE_UPDATES (1L << 16)
-#define OPTION_BUFFER_RESULT (1L << 17)
-#define OPTION_BIN_LOG (1L << 18)
-#define OPTION_NOT_AUTOCOMMIT (1L << 19)
-#define OPTION_BEGIN (1L << 20)
-#define OPTION_TABLE_LOCK (1L << 21)
-#define OPTION_QUICK (1L << 22)
-#define OPTION_QUOTE_SHOW_CREATE (1L << 23)
-#define OPTION_INTERNAL_SUBTRANSACTIONS (1L << 24)
+#define TEST_SYNCHRONIZATION 2048 /* get server to do sleep in
+ some places */
+#endif
+
+/*
+ This is included in the server and in the client.
+ Options for select set by the yacc parser (stored in lex->options).
+
+ XXX:
+ log_event.h defines OPTIONS_WRITTEN_TO_BIN_LOG to specify what THD
+ options list are written into binlog. These options can NOT change their
+ values, or it will break replication between version.
+
+ context is encoded as following:
+ SELECT - SELECT_LEX_NODE::options
+ THD - THD::options
+ intern - neither. used only as
+ func(..., select_node->options | thd->options | OPTION_XXX, ...)
+
+ TODO: separate three contexts above, move them to separate bitfields.
+*/
+
+#define SELECT_DISTINCT (1L << 0) // SELECT, user
+#define SELECT_STRAIGHT_JOIN (1L << 1) // SELECT, user
+#define SELECT_DESCRIBE (1L << 2) // SELECT, user
+#define SELECT_SMALL_RESULT (1L << 3) // SELECT, user
+#define SELECT_BIG_RESULT (1L << 4) // SELECT, user
+#define OPTION_FOUND_ROWS (1L << 5) // SELECT, user
+#define OPTION_TO_QUERY_CACHE (1L << 6) // SELECT, user
+#define SELECT_NO_JOIN_CACHE (1L << 7) // intern
+#define OPTION_BIG_TABLES (1L << 8) // THD, user
+#define OPTION_BIG_SELECTS (1L << 9) // THD, user
+#define OPTION_LOG_OFF (1L << 10) // THD, user
+#define OPTION_UPDATE_LOG (1L << 11) // THD, user, unused
+#define TMP_TABLE_ALL_COLUMNS (1L << 12) // SELECT, intern
+#define OPTION_WARNINGS (1L << 13) // THD, user
+#define OPTION_AUTO_IS_NULL (1L << 14) // THD, user, binlog
+#define OPTION_FOUND_COMMENT (1L << 15) // SELECT, intern, parser
+#define OPTION_SAFE_UPDATES (1L << 16) // THD, user
+#define OPTION_BUFFER_RESULT (1L << 17) // SELECT, user
+#define OPTION_BIN_LOG (1L << 18) // THD, user
+#define OPTION_NOT_AUTOCOMMIT (1L << 19) // THD, user
+#define OPTION_BEGIN (1L << 20) // THD, intern
+#define OPTION_TABLE_LOCK (1L << 21) // THD, intern
+#define OPTION_QUICK (1L << 22) // SELECT (for DELETE)
+#define OPTION_QUOTE_SHOW_CREATE (1L << 23) // THD, user
+
+/* Thr following is used to detect a conflict with DISTINCT
+ in the user query has requested */
+#define SELECT_ALL (1L << 24) // SELECT, user, parser
/* Set if we are updating a non-transaction safe table */
-#define OPTION_STATUS_NO_TRANS_UPDATE (1L << 25)
+#define OPTION_STATUS_NO_TRANS_UPDATE (1L << 25) // THD, intern
/* The following can be set when importing tables in a 'wrong order'
to suppress foreign key checks */
-#define OPTION_NO_FOREIGN_KEY_CHECKS (1L << 26)
+#define OPTION_NO_FOREIGN_KEY_CHECKS (1L << 26) // THD, user, binlog
/* The following speeds up inserts to InnoDB tables by suppressing unique
key checks in some cases */
-#define OPTION_RELAXED_UNIQUE_CHECKS (1L << 27)
-#define SELECT_NO_UNLOCK (1L << 28)
-/* Thr following is used to detect a conflict with DISTINCT
- in the user query has requested */
-#define SELECT_ALL (1L << 29)
-
+#define OPTION_RELAXED_UNIQUE_CHECKS (1L << 27) // THD, user, binlog
+#define SELECT_NO_UNLOCK (1L << 28) // SELECT, intern
+#define OPTION_SCHEMA_TABLE (1L << 29) // SELECT, intern
+/* Flag set if setup_tables already done */
+#define OPTION_SETUP_TABLES_DONE (1L << 30) // intern
+/* If not set then the thread will ignore all warnings with level notes. */
+#define OPTION_SQL_NOTES (1L << 31) // THD, user
/*
Force the used temporary table to be a MyISAM table (because we will use
fulltext functions when reading from it.
*/
-#define TMP_TABLE_FORCE_MYISAM (1L << 30)
+#define TMP_TABLE_FORCE_MYISAM (LL(1) << 32)
+
+/*
+ Maximum length of time zone name that we support
+ (Time zone name is char(64) in db). mysqlbinlog needs it.
+*/
+#define MAX_TIME_ZONE_NAME_LENGTH 72
-/* If set to 0, then the thread will ignore all warnings with level notes.
- Set by executing SET SQL_NOTES=1 */
-#define OPTION_SQL_NOTES (1L << 31)
+/* The rest of the file is included in the server only */
+#ifndef MYSQL_CLIENT
/* Bits for different SQL modes modes (including ANSI mode) */
-#define MODE_REAL_AS_FLOAT 1
-#define MODE_PIPES_AS_CONCAT 2
-#define MODE_ANSI_QUOTES 4
+#define MODE_REAL_AS_FLOAT 1
+#define MODE_PIPES_AS_CONCAT 2
+#define MODE_ANSI_QUOTES 4
#define MODE_IGNORE_SPACE 8
#define MODE_NOT_USED 16
#define MODE_ONLY_FULL_GROUP_BY 32
@@ -241,12 +315,33 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MODE_DB2 2048
#define MODE_MAXDB 4096
#define MODE_NO_KEY_OPTIONS 8192
-#define MODE_NO_TABLE_OPTIONS 16384
-#define MODE_NO_FIELD_OPTIONS 32768
-#define MODE_MYSQL323 65536
-#define MODE_MYSQL40 (MODE_MYSQL323*2)
-#define MODE_ANSI (MODE_MYSQL40*2)
-#define MODE_NO_AUTO_VALUE_ON_ZERO (MODE_ANSI*2)
+#define MODE_NO_TABLE_OPTIONS 16384
+#define MODE_NO_FIELD_OPTIONS 32768
+#define MODE_MYSQL323 65536
+#define MODE_MYSQL40 (MODE_MYSQL323*2)
+#define MODE_ANSI (MODE_MYSQL40*2)
+#define MODE_NO_AUTO_VALUE_ON_ZERO (MODE_ANSI*2)
+#define MODE_NO_BACKSLASH_ESCAPES (MODE_NO_AUTO_VALUE_ON_ZERO*2)
+#define MODE_STRICT_TRANS_TABLES (MODE_NO_BACKSLASH_ESCAPES*2)
+#define MODE_STRICT_ALL_TABLES (MODE_STRICT_TRANS_TABLES*2)
+#define MODE_NO_ZERO_IN_DATE (MODE_STRICT_ALL_TABLES*2)
+#define MODE_NO_ZERO_DATE (MODE_NO_ZERO_IN_DATE*2)
+#define MODE_INVALID_DATES (MODE_NO_ZERO_DATE*2)
+#define MODE_ERROR_FOR_DIVISION_BY_ZERO (MODE_INVALID_DATES*2)
+#define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2)
+#define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2)
+#define MODE_HIGH_NOT_PRECEDENCE (MODE_NO_AUTO_CREATE_USER*2)
+#define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2)
+/*
+ Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
+ use strictly more than 64 bits by adding one more define above, you should
+ contact the replication team because the replication code should then be
+ updated (to store more bytes on disk).
+
+ NOTE: When adding new SQL_MODE types, make sure to also add them to
+ ../scripts/mysql_create_system_tables.sh and
+ ../scripts/mysql_fix_privilege_tables.sql
+*/
#define RAID_BLOCK_SIZE 1024
@@ -284,6 +379,10 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
#define SHOW_LOG_STATUS_FREE "FREE"
#define SHOW_LOG_STATUS_INUSE "IN USE"
+struct st_table_list;
+class String;
+void view_store_options(THD *thd, st_table_list *table, String *buff);
+
/* Options to add_table_to_list() */
#define TL_OPTION_UPDATING 1
#define TL_OPTION_FORCE_INDEX 2
@@ -301,6 +400,8 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
#define WEEK_YEAR 2
#define WEEK_FIRST_WEEKDAY 4
+#define STRING_BUFFER_USUAL_SIZE 80
+
enum enum_parsing_place
{
NO_MATTER,
@@ -311,7 +412,6 @@ enum enum_parsing_place
struct st_table;
class THD;
-class Item_arena;
/* Struct to handle simple linked lists */
@@ -344,11 +444,18 @@ typedef struct st_sql_list {
first= save->first;
elements+= save->elements;
}
+ inline void push_back(struct st_sql_list *save)
+ {
+ if (save->first)
+ {
+ *next= save->first;
+ next= save->next;
+ elements+= save->elements;
+ }
+ }
} SQL_LIST;
-uint nr_of_decimals(const char *str); /* Neaded by sql_string.h */
-
extern pthread_key(THD*, THR_THD);
inline THD *_current_thd(void)
{
@@ -356,38 +463,68 @@ inline THD *_current_thd(void)
}
#define current_thd _current_thd()
+/*
+ External variables
+*/
+extern ulong server_id, concurrency;
+
+
+typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key,
+ uint key_length,
+ ulonglong *engine_data);
#include "sql_string.h"
#include "sql_list.h"
#include "sql_map.h"
+#include "my_decimal.h"
#include "handler.h"
+#include "parse_file.h"
#include "table.h"
+#include "sql_error.h"
#include "field.h" /* Field definitions */
#include "protocol.h"
#include "sql_udf.h"
class user_var_entry;
enum enum_var_type
{
- OPT_DEFAULT, OPT_SESSION, OPT_GLOBAL
+ OPT_DEFAULT= 0, OPT_SESSION, OPT_GLOBAL
};
class sys_var;
#include "item.h"
+extern my_decimal decimal_zero;
typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
/* sql_parse.cc */
void free_items(Item *item);
void cleanup_items(Item *item);
class THD;
void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
-int check_one_table_access(THD *thd, ulong privilege,
+bool check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables);
+bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
+ bool is_proc, bool no_errors);
+bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list);
-int multi_update_precheck(THD *thd, TABLE_LIST *tables);
-int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count);
-int update_precheck(THD *thd, TABLE_LIST *tables);
-int delete_precheck(THD *thd, TABLE_LIST *tables);
-int insert_precheck(THD *thd, TABLE_LIST *tables);
-int create_table_precheck(THD *thd, TABLE_LIST *tables,
- TABLE_LIST *create_table);
+bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
+bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
+bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
+bool mysql_multi_update_prepare(THD *thd);
+bool mysql_multi_delete_prepare(THD *thd);
+bool mysql_insert_select_prepare(THD *thd);
+bool update_precheck(THD *thd, TABLE_LIST *tables);
+bool delete_precheck(THD *thd, TABLE_LIST *tables);
+bool insert_precheck(THD *thd, TABLE_LIST *tables);
+bool create_table_precheck(THD *thd, TABLE_LIST *tables,
+ TABLE_LIST *create_table);
+bool default_view_definer(THD *thd, st_lex_user *definer);
+
+
+enum enum_mysql_completiontype {
+ ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7,
+ COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6
+};
+
+int end_trans(THD *thd, enum enum_mysql_completiontype completion);
+
Item *negate_expression(THD *thd, Item *expr);
#include "sql_class.h"
#include "sql_acl.h"
@@ -399,6 +536,7 @@ struct Query_cache_query_flags
{
unsigned int client_long_flag:1;
unsigned int client_protocol_41:1;
+ unsigned int more_results_exists:1;
uint character_set_client_num;
uint character_set_results_num;
uint collation_connection_num;
@@ -440,32 +578,33 @@ struct Query_cache_query_flags
#define query_cache_invalidate_by_MyISAM_filename_ref NULL
#endif /*HAVE_QUERY_CACHE*/
-int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
-int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
-int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
+bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
+bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
+bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
-int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
- my_bool drop_temporary);
+bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
+ my_bool drop_temporary);
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
- bool drop_temporary, bool log_query);
+ bool drop_temporary, bool drop_view, bool log_query);
int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
bool if_exists, bool drop_temporary,
bool log_query);
int quick_rm_table(enum db_type base,const char *db,
const char *table_name);
+void close_cached_table(THD *thd, TABLE *table);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
-bool mysql_change_db(THD *thd,const char *name);
+bool mysql_change_db(THD *thd,const char *name,bool no_access_check);
void mysql_parse(THD *thd,char *inBuf,uint length);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
bool is_update_query(enum enum_sql_command command);
-bool alloc_query(THD *thd, char *packet, ulong packet_length);
+bool alloc_query(THD *thd, const char *packet, uint packet_length);
void mysql_init_select(LEX *lex);
-void mysql_init_query(THD *thd, uchar *buf, uint length);
void mysql_reset_thd_for_next_command(THD *thd);
+void mysql_init_query(THD *thd, uchar *buf, uint length);
bool mysql_new_select(LEX *lex, bool move_down);
void create_select_for_variable(const char *var_name);
void mysql_init_multi_delete(LEX *lex);
-void fix_multi_delete_lex(LEX* lex);
+bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
void init_max_user_conn(void);
void init_update_queries(void);
void free_max_user_conn(void);
@@ -473,7 +612,7 @@ extern "C" pthread_handler_decl(handle_one_connection,arg);
extern "C" pthread_handler_decl(handle_bootstrap,arg);
void end_thread(THD *thd,bool put_in_cache);
void flush_thread_cache();
-void mysql_execute_command(THD *thd);
+bool mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length);
@@ -488,30 +627,32 @@ void close_connection(THD *thd, uint errcode, bool lock);
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog);
bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
- bool no_grant, bool no_errors);
+ bool no_grant, bool no_errors, bool schema_db);
bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
bool no_errors);
bool check_global_access(THD *thd, ulong want_access);
-int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
-int mysql_restore_table(THD* thd, TABLE_LIST* table_list);
-
-int mysql_checksum_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_check_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_repair_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
- LEX_STRING *key_cache_name);
-int mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
+bool mysql_backup_table(THD* thd, TABLE_LIST* table_list);
+bool mysql_restore_table(THD* thd, TABLE_LIST* table_list);
+
+bool mysql_checksum_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_check_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_repair_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
+ LEX_STRING *key_cache_name);
+bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache,
KEY_CACHE *dst_cache);
+bool mysql_xa_recover(THD *thd);
+
bool check_simple_select();
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
@@ -521,96 +662,102 @@ int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields);
-int handle_select(THD *thd, LEX *lex, select_result *result);
-int mysql_select(THD *thd, Item ***rref_pointer_array,
- TABLE_LIST *tables, uint wild_num, List<Item> &list,
- COND *conds, uint og_num, ORDER *order, ORDER *group,
- Item *having, ORDER *proc_param, ulong select_type,
- select_result *result, SELECT_LEX_UNIT *unit,
- SELECT_LEX *select_lex);
+bool handle_select(THD *thd, LEX *lex, select_result *result,
+ ulong setup_tables_done_option);
+bool mysql_select(THD *thd, Item ***rref_pointer_array,
+ TABLE_LIST *tables, uint wild_num, List<Item> &list,
+ COND *conds, uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc_param, ulong select_type,
+ select_result *result, SELECT_LEX_UNIT *unit,
+ SELECT_LEX *select_lex);
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
-int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
- select_result *result);
+bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
+ select_result *result);
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result);
-int mysql_union(THD *thd, LEX *lex, select_result *result,
- SELECT_LEX_UNIT *unit);
-int mysql_handle_derived(LEX *lex);
+bool mysql_union(THD *thd, LEX *lex, select_result *result,
+ SELECT_LEX_UNIT *unit, ulong setup_tables_done_option);
+int mysql_handle_derived(LEX *lex, int (*processor)(THD *thd,
+ LEX *lex,
+ TABLE_LIST *table));
+int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t);
+int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field,
- bool group, bool modify_item, uint convert_blob_length);
-int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
- List<create_field> &fields,
- List<Key> &keys, uint &db_options,
- handler *file, KEY *&key_info_buffer,
- uint &key_count, int select_field_count);
-int mysql_create_table(THD *thd,const char *db, const char *table_name,
- HA_CREATE_INFO *create_info,
- List<create_field> &fields, List<Key> &keys,
- bool tmp_table, uint select_field_count);
+ bool group, bool modify_item,
+ bool table_cant_handle_bit_fields,
+ uint convert_blob_length);
+void sp_prepare_create_field(THD *thd, create_field *sql_field);
+int prepare_create_field(create_field *sql_field,
+ uint *blob_columns,
+ int *timestamps, int *timestamps_with_niladic,
+ uint table_flags);
+bool mysql_create_table(THD *thd,const char *db, const char *table_name,
+ HA_CREATE_INFO *create_info,
+ List<create_field> &fields, List<Key> &keys,
+ bool tmp_table, uint select_field_count);
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
- const char *db, const char *name,
+ TABLE_LIST *create_table,
List<create_field> *extra_fields,
List<Key> *keys,
List<Item> *items,
- MYSQL_LOCK **lock);
-int mysql_alter_table(THD *thd, char *new_db, char *new_name,
- HA_CREATE_INFO *create_info,
- TABLE_LIST *table_list,
- List<create_field> &fields,
- List<Key> &keys,
- uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates,
- bool ignore,
- 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);
+ MYSQL_LOCK **lock);
+bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ List<create_field> &fields,
+ List<Key> &keys,
+ uint order_num, ORDER *order,
+ enum enum_duplicates handle_duplicates,
+ bool ignore,
+ ALTER_INFO *alter_info, bool do_send_ok);
+bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
+bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *src_table);
bool mysql_rename_table(enum db_type base,
const char *old_db,
const char * old_name,
const char *new_db,
const char * new_name);
-int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
-int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
- ALTER_INFO *alter_info);
-int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- TABLE_LIST *update_table_list,
- Item **conds, uint order_num, ORDER *order);
+bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
+bool mysql_drop_index(THD *thd, TABLE_LIST *table_list,
+ ALTER_INFO *alter_info);
+bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
+ Item **conds, uint order_num, ORDER *order);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
- uint order_num, ORDER *order, ha_rows limit,
+ uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates, bool ignore);
-int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
- List<Item> *fields, List<Item> *values,
- COND *conds, ulong options,
- enum enum_duplicates handle_duplicates, bool ignore,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
-int mysql_multi_update_lock(THD *thd,
- TABLE_LIST *table_list,
- List<Item> *fields,
- SELECT_LEX *select_lex);
-int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
- TABLE_LIST *insert_table_list,
- TABLE_LIST *dup_table_list, TABLE *table,
- List<Item> &fields, List_item *values,
- List<Item> &update_fields,
- List<Item> &update_values, enum_duplicates duplic);
-int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
- List<List_item> &values, List<Item> &update_fields,
- List<Item> &update_values, enum_duplicates flag, bool ignore);
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
-int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order,
- ha_rows rows, ulong options);
-int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok);
+bool mysql_multi_update(THD *thd, TABLE_LIST *table_list,
+ List<Item> *fields, List<Item> *values,
+ COND *conds, ulonglong options,
+ enum enum_duplicates handle_duplicates, bool ignore,
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
+bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
+ List<Item> &fields, List_item *values,
+ List<Item> &update_fields,
+ List<Item> &update_values, enum_duplicates duplic,
+ COND **where, bool select_insert);
+bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
+ List<List_item> &values, List<Item> &update_fields,
+ List<Item> &update_values, enum_duplicates flag,
+ bool ignore);
+int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
+ TABLE_LIST *table_list);
+bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
+bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
+ SQL_LIST *order, ha_rows rows, ulonglong options,
+ bool reset_auto_increment);
+bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok);
+bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
-TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
- bool *refresh);
+TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem,
+ bool *refresh, uint flags);
TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table);
TABLE *find_locked_table(THD *thd, const char *db,const char *table_name);
-bool reopen_table(TABLE *table,bool locked=0);
+bool reopen_table(TABLE *table,bool locked);
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh);
void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
bool send_refresh);
@@ -621,12 +768,30 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
void execute_init_command(THD *thd, sys_var_str *init_command_var,
rw_lock_t *var_mutex);
-extern const Field *not_found_field;
-Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
- TABLE_LIST **where, bool report_error);
-Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
- bool check_grant,bool allow_rowid,
- uint *cached_field_index_ptr);
+extern Field *not_found_field;
+extern Field *view_ref_found;
+
+enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
+ IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
+ IGNORE_EXCEPT_NON_UNIQUE};
+Field *
+find_field_in_tables(THD *thd, Item_ident *item,
+ TABLE_LIST *first_table, TABLE_LIST *last_table,
+ Item **ref, find_item_error_report_type report_error,
+ bool check_privileges, bool register_tree_change);
+Field *
+find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
+ const char *name, const char *item_name,
+ const char *table_name, const char *db_name,
+ uint length, Item **ref,
+ bool check_grants_table, bool check_grants_view,
+ bool allow_rowid,
+ uint *cached_field_index_ptr,
+ bool register_tree_change, TABLE_LIST **actual_table);
+Field *
+find_field_in_table(THD *thd, TABLE *table, const char *name,
+ uint length, bool check_grants, bool allow_rowid,
+ uint *cached_field_index_ptr);
#ifdef HAVE_OPENSSL
#include <openssl/des.h>
struct st_des_keyblock
@@ -645,62 +810,71 @@ bool load_des_key_file(const char *file_name);
#endif /* HAVE_OPENSSL */
/* sql_do.cc */
-int mysql_do(THD *thd, List<Item> &values);
+bool mysql_do(THD *thd, List<Item> &values);
+
+/* sql_analyse.h */
+bool append_escaped(String *to_str, String *from_str);
/* sql_show.cc */
-int mysqld_show_dbs(THD *thd,const char *wild);
-int mysqld_show_open_tables(THD *thd,const char *wild);
-int mysqld_show_tables(THD *thd,const char *db,const char *wild);
-int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild);
-int mysqld_show_fields(THD *thd,TABLE_LIST *table, const char *wild,
- bool verbose);
-int mysqld_show_keys(THD *thd, TABLE_LIST *table);
-int mysqld_show_logs(THD *thd);
+bool mysqld_show_open_tables(THD *thd,const char *wild);
+bool mysqld_show_logs(THD *thd);
void append_identifier(THD *thd, String *packet, const char *name,
uint length);
int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
-int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
-int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
-int mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
+int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd);
+bool mysqld_show_create(THD *thd, TABLE_LIST *table_list);
+bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
int mysqld_show_status(THD *thd);
int mysqld_show_variables(THD *thd,const char *wild);
-int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
- enum enum_var_type value_type,
- pthread_mutex_t *mutex);
int mysql_find_files(THD *thd,List<char> *files, const char *db,
const char *path, const char *wild, bool dir);
-int mysqld_show_charsets(THD *thd,const char *wild);
-int mysqld_show_collations(THD *thd,const char *wild);
-int mysqld_show_storage_engines(THD *thd);
-int mysqld_show_privileges(THD *thd);
-int mysqld_show_column_types(THD *thd);
-int mysqld_help (THD *thd, const char *text);
+bool mysqld_show_storage_engines(THD *thd);
+bool mysqld_show_privileges(THD *thd);
+bool mysqld_show_column_types(THD *thd);
+bool mysqld_help (THD *thd, const char *text);
+void calc_sum_of_all_status(STATUS_VAR *to);
+
+/* information schema */
+extern LEX_STRING information_schema_name;
+LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
+ const char* str, uint length,
+ bool allocate_lex_string);
+ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name);
+ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx);
+int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
+ enum enum_schema_tables schema_table_idx);
+int make_schema_select(THD *thd, SELECT_LEX *sel,
+ enum enum_schema_tables schema_table_idx);
+int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list);
+int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
+int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
+int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
+int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
+bool get_schema_tables_result(JOIN *join);
+#define is_schema_db(X) \
+ !my_strcasecmp(system_charset_info, information_schema_name.str, (X))
/* sql_prepare.cc */
-int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
- LEX_STRING *name=NULL);
+
+void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length);
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length);
-void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name);
-void mysql_stmt_free(THD *thd, char *packet);
+void mysql_stmt_close(THD *thd, char *packet);
+void mysql_sql_stmt_prepare(THD *thd);
+void mysql_sql_stmt_execute(THD *thd);
+void mysql_sql_stmt_close(THD *thd);
+void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length);
void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
-
-/* sql_error.cc */
-MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
- const char *msg);
-void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
- uint code, const char *format, ...);
-void mysql_reset_errors(THD *thd);
-my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
+void reinit_stmt_before_use(THD *thd, LEX *lex);
/* sql_handler.cc */
-int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0);
-int mysql_ha_close(THD *thd, TABLE_LIST *tables);
-int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
- List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
+bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen);
+bool mysql_ha_close(THD *thd, TABLE_LIST *tables);
+bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
+ List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags);
/* mysql_ha_flush mode_flags bits */
#define MYSQL_HA_CLOSE_FINAL 0x00
@@ -718,42 +892,67 @@ bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type,
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
uint uint_geom_type);
+create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
+ char *length, char *decimals,
+ uint type_modifier,
+ Item *default_value, Item *on_update_value,
+ LEX_STRING *comment, char *change,
+ List<String> *interval_list, CHARSET_INFO *cs,
+ uint uint_geom_type);
void store_position_for_column(const char *name);
-bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0);
+bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
+Name_resolution_context *make_join_on_context(THD *thd, TABLE_LIST *left_op,
+ TABLE_LIST *right_op);
void add_join_on(TABLE_LIST *b,Item *expr);
-void add_join_natural(TABLE_LIST *a,TABLE_LIST *b);
+void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
bool add_proc_to_list(THD *thd, Item *item);
TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
+void update_non_unique_table_error(TABLE_LIST *update,
+ const char *operation,
+ TABLE_LIST *duplicate);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
- table_map read_tables, COND *conds, int *error);
-enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
- IGNORE_ERRORS};
-extern const Item **not_found_item;
+ table_map read_tables, COND *conds,
+ bool allow_null_cond, int *error);
+extern Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error,
bool *unaliased);
bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list);
-bool insert_fields(THD *thd,TABLE_LIST *tables,
+bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name, const char *table_name,
- List_iterator<Item> *it);
-bool setup_tables(TABLE_LIST *tables);
+ List_iterator<Item> *it, bool any_privileges);
+bool setup_tables(THD *thd, Name_resolution_context *context,
+ List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
+ Item **conds, TABLE_LIST **leaves, bool select_insert);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num);
-int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
- List<Item> &item, bool set_query_id,
- List<Item> *sum_func_list, bool allow_sum_func);
-int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
+bool setup_fields(THD *thd, Item** ref_pointer_array,
+ List<Item> &item, bool set_query_id,
+ List<Item> *sum_func_list, bool allow_sum_func);
+inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
+ List<Item> &item, bool set_query_id,
+ List<Item> *sum_func_list,
+ bool allow_sum_func)
+{
+ bool res;
+ thd->lex->select_lex.no_wrap_view_item= TRUE;
+ res= setup_fields(thd, ref_pointer_array, item, set_query_id, sum_func_list,
+ allow_sum_func);
+ thd->lex->select_lex.no_wrap_view_item= FALSE;
+ return res;
+}
+int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
+ COND **conds);
int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
void wait_for_refresh(THD *thd);
-int open_tables(THD *thd, TABLE_LIST *tables, uint *counter);
+int open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags);
int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
-int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
-int open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables);
-void relink_tables_for_derived(THD *thd);
-int lock_tables(THD *thd, TABLE_LIST *tables, uint counter);
+bool open_and_lock_tables(THD *thd,TABLE_LIST *tables);
+bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
+int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
bool rm_temporary_table(enum db_type base, char *path);
@@ -761,18 +960,20 @@ void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
bool close_thread_table(THD *thd, TABLE **table_ptr);
void close_temporary_tables(THD *thd);
-TABLE_LIST * find_table_in_list(TABLE_LIST *table,
- const char *db_name, const char *table_name);
-TABLE_LIST * find_real_table_in_list(TABLE_LIST *table,
- const char *db_name,
- const char *table_name);
+void close_tables_for_reopen(THD *thd, TABLE_LIST *tables);
+TABLE_LIST *find_table_in_list(TABLE_LIST *table,
+ uint offset_to_list,
+ const char *db_name,
+ const char *table_name);
+TABLE_LIST *unique_table(TABLE_LIST *table, TABLE_LIST *table_list);
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name);
bool close_temporary_table(THD *thd, const char *db, const char *table_name);
-void close_temporary(TABLE *table, bool delete_table=1);
+void close_temporary(TABLE *table, bool delete_table);
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
const char *table_name);
void remove_db_from_cache(const char *db);
void flush_tables();
+bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
/* bits for last argument to remove_table_from_cache() */
#define RTFC_NO_FLAG 0x0000
@@ -784,19 +985,47 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table,
bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables);
void copy_field_from_tmp_record(Field *field,int offset);
-int fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors);
-int fill_record(Field **field,List<Item> &values, bool ignore_errors);
-OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild);
+bool fill_record(THD *thd, Field **field, List<Item> &values,
+ bool ignore_errors);
+bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
+ List<Item> &values,
+ bool ignore_errors,
+ Table_triggers_list *triggers,
+ enum trg_event_type event);
+bool fill_record_n_invoke_before_triggers(THD *thd, Field **field,
+ List<Item> &values,
+ bool ignore_errors,
+ Table_triggers_list *triggers,
+ enum trg_event_type event);
+OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
+
+inline TABLE_LIST *find_table_in_global_list(TABLE_LIST *table,
+ const char *db_name,
+ const char *table_name)
+{
+ return find_table_in_list(table, offsetof(TABLE_LIST, next_global),
+ db_name, table_name);
+}
+
+inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table,
+ const char *db_name,
+ const char *table_name)
+{
+ return find_table_in_list(table, offsetof(TABLE_LIST, next_local),
+ db_name, table_name);
+}
+
/* sql_calc.cc */
bool eval_const_cond(COND *cond);
/* sql_load.cc */
-int mysql_load(THD *thd,sql_exchange *ex, TABLE_LIST *table_list,
- List<Item> &fields, enum enum_duplicates handle_duplicates,
- bool ignore,
- bool local_file,thr_lock_type lock_type);
-int write_record(TABLE *table,COPY_INFO *info);
+bool mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list,
+ List<Item> &fields_vars, List<Item> &set_fields,
+ List<Item> &set_values_list,
+ enum enum_duplicates handle_duplicates, bool ignore,
+ bool local_file);
+int write_record(THD *thd, TABLE *table, COPY_INFO *info);
/* sql_manager.cc */
/* bits set in manager_status */
@@ -811,12 +1040,15 @@ extern "C" pthread_handler_decl(handle_manager, arg);
void print_where(COND *cond,const char *info);
void print_cached_tables(void);
void TEST_filesort(SORT_FIELD *sortorder,uint s_length);
+void print_plan(JOIN* join, double read_time, double record_count,
+ uint idx, const char *info);
#endif
-void mysql_print_status(THD *thd);
+void mysql_print_status();
/* key.cc */
int find_ref_key(TABLE *form,Field *field, uint *offset);
-void key_copy(byte *key,TABLE *form,uint index,uint key_length);
-void key_restore(TABLE *form,byte *key,uint index,uint key_length);
+void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length);
+void key_restore(byte *to_record, byte *from_key, KEY *key_info,
+ uint key_length);
bool key_cmp_if_same(TABLE *form,const byte *key,uint index,uint key_length);
void key_unpack(String *to,TABLE *form,uint index);
bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields);
@@ -834,11 +1066,9 @@ void sql_print_information(const char *format, ...);
bool fn_format_relative_to_data_home(my_string to, const char *name,
const char *dir, const char *extension);
-bool open_log(MYSQL_LOG *log, const char *hostname,
- const char *opt_name, const char *extension,
- const char *index_file_name,
- enum_log_type type, bool read_append,
- bool no_auto_events, ulong max_size);
+File open_binlog(IO_CACHE *log, const char *log_file_name,
+ const char **errmsg);
+handlerton *binlog_init();
/* mysqld.cc */
extern void yyerror(const char*);
@@ -879,6 +1109,8 @@ extern const char *first_keyword, *my_localhost, *delayed_user, *binary_keyword;
extern const char **errmesg; /* Error messages */
extern const char *myisam_recover_options_str;
extern const char *in_left_expr_name, *in_additional_cond;
+extern const char * const triggers_file_ext;
+extern const char * const trigname_file_ext;
extern Eq_creator eq_creator;
extern Ne_creator ne_creator;
extern Gt_creator gt_creator;
@@ -888,45 +1120,36 @@ extern Le_creator le_creator;
extern char language[FN_REFLEN], reg_ext[FN_EXTLEN];
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
-extern char log_error_file[FN_REFLEN];
+extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
extern double log_10[32];
extern ulonglong log_10_int[20];
extern ulonglong keybuff_size;
-extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
-extern ulong created_tmp_tables, created_tmp_disk_tables, bytes_sent;
+extern ulonglong thd_startup_options;
+extern ulong refresh_version,flush_version, thread_id;
extern ulong binlog_cache_use, binlog_cache_disk_use;
extern ulong aborted_threads,aborted_connects;
extern ulong delayed_insert_timeout;
extern ulong delayed_insert_limit, delayed_queue_size;
extern ulong delayed_insert_threads, delayed_insert_writes;
extern ulong delayed_rows_in_use,delayed_insert_errors;
-extern ulong filesort_rows, filesort_range_count, filesort_scan_count;
-extern ulong filesort_merge_passes;
-extern ulong select_range_check_count, select_range_count, select_scan_count;
-extern ulong select_full_range_join_count,select_full_join_count;
extern ulong slave_open_temp_tables;
extern ulong query_cache_size, query_cache_min_res_unit;
-extern ulong thd_startup_options, slow_launch_threads, slow_launch_time;
-extern ulong server_id, concurrency;
-extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count;
-extern ulong ha_read_key_count, ha_read_next_count, ha_read_prev_count;
-extern ulong ha_read_first_count, ha_read_last_count;
-extern ulong ha_read_rnd_count, ha_read_rnd_next_count, ha_discover_count;
-extern ulong ha_commit_count, ha_rollback_count,table_cache_size;
+extern ulong slow_launch_threads, slow_launch_time;
+extern ulong table_cache_size;
extern ulong max_connections,max_connect_errors, connect_timeout;
extern ulong slave_net_timeout, slave_trans_retries;
-extern ulong max_user_connections;
-extern ulong long_query_count, what_to_log,flush_time;
-extern ulong query_buff_size, thread_stack,thread_stack_min;
+extern uint max_user_connections;
+extern ulong what_to_log,flush_time;
+extern ulong query_buff_size, thread_stack;
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
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 com_stmt_prepare, com_stmt_execute, com_stmt_send_long_data;
-extern ulong com_stmt_reset, com_stmt_close;
+extern ulong back_log;
extern ulong specialflag, current_pid;
extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter;
-extern my_bool relay_log_purge, opt_innodb_safe_binlog;
+extern ulong opt_tc_log_size, tc_log_max_pages_used, tc_log_page_size;
+extern ulong tc_log_page_waits;
+extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb;
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;
@@ -937,6 +1160,7 @@ extern bool opt_log, opt_update_log, opt_bin_log, opt_slow_log, opt_error_log;
extern bool opt_disable_networking, opt_skip_show_db;
extern bool opt_character_set_client_handshake;
extern bool volatile abort_loop, shutdown_in_progress, grant_option;
+extern bool mysql_proc_table_exists;
extern uint volatile thread_count, thread_running, global_read_lock;
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile;
@@ -945,21 +1169,27 @@ extern my_bool opt_readonly, lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
extern my_bool opt_log_slow_admin_statements;
+extern my_bool sp_automatic_privileges, opt_noacl;
+extern my_bool opt_old_style_user_limits, trust_routine_creators;
extern uint opt_crash_binlog_innodb;
extern char *shared_memory_base_name, *mysqld_unix_port;
extern bool opt_enable_shared_memory;
extern char *default_tz_name;
+extern my_bool opt_large_pages;
+extern uint opt_large_page_size;
-extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
+extern MYSQL_LOG mysql_log,mysql_slow_log,mysql_bin_log;
extern FILE *bootstrap_file;
+extern int bootstrap_error;
extern FILE *stderror_file;
extern pthread_key(MEM_ROOT**,THR_MALLOC);
extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
- LOCK_slave_list, LOCK_active_mi, LOCK_manager,
- LOCK_global_system_variables, LOCK_user_conn;
+ LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_read_lock,
+ LOCK_global_system_variables, LOCK_user_conn,
+ LOCK_bytes_sent, LOCK_bytes_received;
#ifdef HAVE_OPENSSL
extern pthread_mutex_t LOCK_des_key_file;
#endif
@@ -972,12 +1202,9 @@ extern MY_BITMAP temp_pool;
extern String my_empty_string;
extern const String my_null_string;
extern SHOW_VAR init_vars[],status_vars[], internal_vars[];
-extern SHOW_COMP_OPTION have_isam;
-extern SHOW_COMP_OPTION have_innodb;
-extern SHOW_COMP_OPTION have_berkeley_db;
-extern SHOW_COMP_OPTION have_ndbcluster;
extern struct system_variables global_system_variables;
extern struct system_variables max_system_variables;
+extern struct system_status_var global_status_var;
extern struct rand_struct sql_rand;
extern const char *opt_date_time_formats[];
@@ -989,17 +1216,20 @@ extern TABLE *unused_tables;
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
extern const char* any_db;
extern struct my_option my_long_options[];
+extern const LEX_STRING view_type;
/* optional things, have_* variables */
extern SHOW_COMP_OPTION have_isam, have_innodb, have_berkeley_db;
extern SHOW_COMP_OPTION have_example_db, have_archive_db, have_csv_db;
+extern SHOW_COMP_OPTION have_federated_db;
+extern SHOW_COMP_OPTION have_blackhole_db;
+extern SHOW_COMP_OPTION have_ndbcluster;
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_query_cache;
extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
extern SHOW_COMP_OPTION have_crypt;
extern SHOW_COMP_OPTION have_compress;
-extern SHOW_COMP_OPTION have_blackhole_db;
#ifndef __WIN__
extern pthread_t signal_thread;
@@ -1009,10 +1239,12 @@ extern pthread_t signal_thread;
extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */
-MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, uint flags);
+MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
+ uint flags, bool *need_reopen);
/* mysql_lock_tables() flags bits */
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK 0x0001
#define MYSQL_LOCK_IGNORE_FLUSH 0x0002
+#define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
@@ -1023,10 +1255,11 @@ bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
bool lock_global_read_lock(THD *thd);
void unlock_global_read_lock(THD *thd);
-bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commit);
+bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
+ bool is_not_commit);
void start_waiting_global_read_lock(THD *thd);
-void make_global_read_lock_block_commit(THD *thd);
-my_bool set_protect_against_global_read_lock(void);
+bool make_global_read_lock_block_commit(THD *thd);
+bool set_protect_against_global_read_lock(void);
void unset_protect_against_global_read_lock(void);
/* Lock based on name */
@@ -1036,7 +1269,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list);
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
bool lock_table_names(THD *thd, TABLE_LIST *table_list);
void unlock_table_names(THD *thd, TABLE_LIST *table_list,
- TABLE_LIST *last_table= 0);
+ TABLE_LIST *last_table);
/* old unireg functions */
@@ -1055,31 +1288,29 @@ int rea_create_table(THD *thd, my_string file_name,
uint key_count,KEY *key_info);
int format_number(uint inputflag,uint max_length,my_string pos,uint length,
my_string *errpos);
-int openfrm(const char *name,const char *alias,uint filestat,uint prgflag,
- uint ha_open_flags, TABLE *outparam);
+int openfrm(THD *thd, const char *name,const char *alias,uint filestat,
+ uint prgflag, uint ha_open_flags, TABLE *outparam);
int readfrm(const char *name, const void** data, uint* length);
int writefrm(const char* name, const void* data, uint len);
int closefrm(TABLE *table);
-db_type get_table_type(const char *name);
+db_type get_table_type(THD *thd, const char *name);
int read_string(File file, gptr *to, uint length);
void free_blobs(TABLE *table);
int set_zone(int nr,int min_zone,int max_zone);
ulong convert_period_to_month(ulong period);
ulong convert_month_to_period(ulong month);
-uint calc_days_in_year(uint year);
void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
-my_time_t TIME_to_timestamp(THD *thd, const TIME *t, bool *not_exist);
+my_time_t TIME_to_timestamp(THD *thd, const TIME *t, my_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);
void make_truncated_value_warning(THD *thd, const char *str_val,
- uint str_length, timestamp_type time_type);
+ uint str_length, timestamp_type time_type,
+ const char *field_name);
extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type,
const char *format_str,
uint format_length);
@@ -1095,10 +1326,6 @@ void make_date(const DATE_TIME_FORMAT *format, const TIME *l_time,
String *str);
void make_time(const DATE_TIME_FORMAT *format, const TIME *l_time,
String *str);
-ulonglong TIME_to_ulonglong_datetime(const TIME *time);
-ulonglong TIME_to_ulonglong_date(const TIME *time);
-ulonglong TIME_to_ulonglong_time(const TIME *time);
-ulonglong TIME_to_ulonglong(const TIME *time);
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
@@ -1111,6 +1338,7 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
ha_rows max_rows, ha_rows *examined_rows);
void filesort_free_buffers(TABLE *table);
void change_double_for_sort(double nr,byte *to);
+double my_double_round(double value, int dec, bool truncate);
int get_quick_record(SQL_SELECT *select);
int calc_weekday(long daynr,bool sunday_first_day_of_week);
uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
@@ -1122,7 +1350,7 @@ ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname);
ulong next_io_size(ulong pos);
void append_unescaped(String *res, const char *pos, uint length);
-int create_frm(char *name, const char *db, const char *table,
+int create_frm(THD *thd, char *name, const char *db, const char *table,
uint reclength,uchar *fileinfo,
HA_CREATE_INFO *create_info, uint keys);
void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
@@ -1151,8 +1379,8 @@ extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
/* item_func.cc */
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
LEX_STRING component);
-int get_var_with_binlog(THD *thd, LEX_STRING &name,
- user_var_entry **out_entry);
+int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
+ LEX_STRING &name, user_var_entry **out_entry);
/* log.cc */
bool flush_error_log(void);
@@ -1168,6 +1396,8 @@ extern int yyparse(void *thd);
SQL_CRYPT *get_crypt_for_frm(void);
#endif
+#include "sql_view.h"
+
/* Some inline functions for more speed */
inline bool add_item_to_list(THD *thd, Item *item)
@@ -1194,13 +1424,14 @@ inline void mark_as_null_row(TABLE *table)
{
table->null_row=1;
table->status|=STATUS_NULL_ROW;
- bfill(table->null_flags,table->null_bytes,255);
+ bfill(table->null_flags,table->s->null_bytes,255);
}
inline void table_case_convert(char * name, uint length)
{
if (lower_case_table_names)
- my_casedn(files_charset_info, name, length);
+ files_charset_info->cset->casedn(files_charset_info,
+ name, length, name, length);
}
inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
@@ -1244,8 +1475,14 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
table->const_table= 0;
table->null_row= 0;
table->status= STATUS_NO_RECORD;
- table->keys_in_use_for_query= table->keys_in_use;
- table->maybe_null= test(table->outer_join= table_list->outer_join);
+ table->keys_in_use_for_query= table->s->keys_in_use;
+ table->maybe_null= table_list->outer_join;
+ TABLE_LIST *embedding= table_list->embedding;
+ while (!table->maybe_null && embedding)
+ {
+ table->maybe_null= embedding->outer_join;
+ embedding= embedding->embedding;
+ }
table->tablenr= tablenr;
table->map= (table_map) 1 << tablenr;
table->force_index= table_list->force_index;
@@ -1277,9 +1514,11 @@ inline int hexchar_to_int(char c)
#ifndef EMBEDDED_LIBRARY
extern "C" void unireg_abort(int exit_code);
void kill_delayed_threads(void);
-bool check_stack_overrun(THD *thd,char *dummy);
+bool check_stack_overrun(THD *thd, long margin, char *dummy);
#else
#define unireg_abort(exit_code) DBUG_RETURN(exit_code)
inline void kill_delayed_threads(void) {}
-#define check_stack_overrun(A, B) 0
+#define check_stack_overrun(A, B, C) 0
#endif
+
+#endif /* MYSQL_CLIENT */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 7d9743fad5d..ad2b6c5fd68 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -22,6 +22,7 @@
#include "repl_failsafe.h"
#include "stacktrace.h"
#include "mysqld_suffix.h"
+#include "mysys_err.h"
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"
#endif
@@ -29,9 +30,6 @@
#include "ha_innodb.h"
#endif
#include "ha_myisam.h"
-#ifdef HAVE_ISAM
-#include "ha_isam.h"
-#endif
#ifdef HAVE_NDBCLUSTER_DB
#include "ha_ndbcluster.h"
#endif
@@ -41,19 +39,11 @@
#else
#define OPT_INNODB_DEFAULT 0
#endif
-#ifdef HAVE_BERKLEY_DB
-#define OPT_BDB_DEFAULT 1
-#else
#define OPT_BDB_DEFAULT 0
-#endif
-#ifdef HAVE_ISAM_DB
-#define OPT_ISAM_DEFAULT 1
-#else
-#define OPT_ISAM_DEFAULT 0
-#endif
#ifdef HAVE_NDBCLUSTER_DB
#define OPT_NDBCLUSTER_DEFAULT 0
-#if defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000
+#if defined(NOT_ENOUGH_TESTED) \
+ && defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000
#define OPT_NDB_SHM_DEFAULT 1
#else
#define OPT_NDB_SHM_DEFAULT 0
@@ -62,10 +52,11 @@
#define OPT_NDBCLUSTER_DEFAULT 0
#endif
-#include <nisam.h>
#include <thr_alarm.h>
#include <ft_global.h>
#include <errmsg.h>
+#include "sp_rcontext.h"
+#include "sp_cache.h"
#define mysqld_charset &my_charset_latin1
@@ -79,10 +70,6 @@
#define IF_PURIFY(A,B) (B)
#endif
-#ifndef INADDR_NONE
-#define INADDR_NONE -1 // Error value from inet_addr
-#endif
-
/* stack traces are only supported on linux intel */
#if defined(__linux__) && defined(__i386__) && defined(USE_PSTACK)
#define HAVE_STACK_TRACE_ON_SEGV
@@ -112,10 +99,11 @@ extern "C" { // Because of SCO 3.2V4.2
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
+#include <my_net.h>
#if defined(OS2)
# include <sys/un.h>
-#elif !defined( __WIN__)
+#elif !defined(__WIN__)
# ifndef __NETWARE__
#include <sys/resource.h>
# endif /* __NETWARE__ */
@@ -147,11 +135,11 @@ int deny_severity = LOG_WARNING;
#include <sys/mman.h>
#endif
+#ifdef __NETWARE__
#define zVOLSTATE_ACTIVE 6
#define zVOLSTATE_DEACTIVE 2
#define zVOLSTATE_MAINTENANCE 3
-#ifdef __NETWARE__
#include <nks/netware.h>
#include <nks/vm.h>
#include <library.h>
@@ -232,17 +220,67 @@ extern "C" int gethostname(char *name, int namelen);
/* Constants */
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
-const char *sql_mode_names[] =
+static const char *sql_mode_names[]=
{
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
"?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
"NO_DIR_IN_CREATE",
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
- "NO_AUTO_VALUE_ON_ZERO", NullS
+ "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES",
+ "STRICT_ALL_TABLES",
+ "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES",
+ "ERROR_FOR_DIVISION_BY_ZERO",
+ "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
+ "NO_ENGINE_SUBSTITUTION",
+ NullS
+};
+static const unsigned int sql_mode_names_len[]=
+{
+ /*REAL_AS_FLOAT*/ 13,
+ /*PIPES_AS_CONCAT*/ 15,
+ /*ANSI_QUOTES*/ 11,
+ /*IGNORE_SPACE*/ 12,
+ /*?*/ 1,
+ /*ONLY_FULL_GROUP_BY*/ 18,
+ /*NO_UNSIGNED_SUBTRACTION*/ 23,
+ /*NO_DIR_IN_CREATE*/ 16,
+ /*POSTGRESQL*/ 10,
+ /*ORACLE*/ 6,
+ /*MSSQL*/ 5,
+ /*DB2*/ 3,
+ /*MAXDB*/ 5,
+ /*NO_KEY_OPTIONS*/ 14,
+ /*NO_TABLE_OPTIONS*/ 16,
+ /*NO_FIELD_OPTIONS*/ 16,
+ /*MYSQL323*/ 8,
+ /*MYSQL40*/ 7,
+ /*ANSI*/ 4,
+ /*NO_AUTO_VALUE_ON_ZERO*/ 21,
+ /*NO_BACKSLASH_ESCAPES*/ 20,
+ /*STRICT_TRANS_TABLES*/ 19,
+ /*STRICT_ALL_TABLES*/ 17,
+ /*NO_ZERO_IN_DATE*/ 15,
+ /*NO_ZERO_DATE*/ 12,
+ /*ALLOW_INVALID_DATES*/ 19,
+ /*ERROR_FOR_DIVISION_BY_ZERO*/ 26,
+ /*TRADITIONAL*/ 11,
+ /*NO_AUTO_CREATE_USER*/ 19,
+ /*HIGH_NOT_PRECEDENCE*/ 19,
+ /*NO_ENGINE_SUBSTITUTION*/ 22
};
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
- sql_mode_names, NULL };
+ sql_mode_names,
+ (unsigned int *)sql_mode_names_len };
+static const char *tc_heuristic_recover_names[]=
+{
+ "COMMIT", "ROLLBACK", NullS
+};
+static TYPELIB tc_heuristic_recover_typelib=
+{
+ array_elements(tc_heuristic_recover_names)-1,"",
+ tc_heuristic_recover_names, NULL
+};
const char *first_keyword= "first", *binary_keyword= "BINARY";
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
@@ -256,15 +294,44 @@ bool opt_large_files= sizeof(my_off_t) > 4;
/*
Used with --help for detailed option
*/
-bool opt_help= 0;
-bool opt_verbose= 0;
+static bool opt_help= 0, opt_verbose= 0;
-arg_cmp_func Arg_comparator::comparator_matrix[4][2] =
+arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
{{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string},
{&Arg_comparator::compare_real, &Arg_comparator::compare_e_real},
{&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
- {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row}};
+ {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row},
+ {&Arg_comparator::compare_decimal, &Arg_comparator::compare_e_decimal}};
+
+/* static variables */
+
+static bool lower_case_table_names_used= 0;
+static bool volatile select_thread_in_use, signal_thread_in_use;
+static bool volatile ready_to_exit;
+static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
+static my_bool opt_bdb, opt_isam, opt_ndbcluster;
+static my_bool opt_short_log_format= 0;
+static my_bool opt_log_queries_not_using_indexes= 0;
+static uint kill_cached_threads, wake_thread;
+static ulong killed_threads, thread_created;
+static ulong max_used_connections;
+static ulong my_bind_addr; /* the address we bind to */
+static volatile ulong cached_thread_count= 0;
+static const char *sql_mode_str= "OFF";
+static char *mysqld_user, *mysqld_chroot, *log_error_file_ptr;
+static char *opt_init_slave, *language_ptr, *opt_init_connect;
+static char *default_character_set_name;
+static char *my_bind_addr_str;
+static char *default_collation_name;
+static char mysql_data_home_buff[2];
+static struct passwd *user_info;
+static I_List<THD> thread_cache;
+
+static pthread_cond_t COND_thread_cache, COND_flush_thread_cache;
+#ifdef HAVE_BERKELEY_DB
+static my_bool opt_sync_bdb_logs;
+#endif
/* Global variables */
@@ -272,34 +339,46 @@ bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
bool opt_error_log= IF_WIN(1,0);
bool opt_disable_networking=0, opt_skip_show_db=0;
bool opt_character_set_client_handshake= 1;
-bool lower_case_table_names_used= 0;
bool server_id_supplied = 0;
bool opt_endinfo,using_udf_functions, locked_in_memory;
bool opt_using_transactions, using_update_log;
-bool volatile abort_loop, select_thread_in_use, signal_thread_in_use;
-bool volatile ready_to_exit, shutdown_in_progress, grant_option;
+bool volatile abort_loop;
+bool volatile shutdown_in_progress, grant_option;
my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted
my_bool opt_reckless_slave = 0;
-my_bool opt_enable_named_pipe= 0, opt_debugging= 0;
-my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol;
+my_bool opt_enable_named_pipe= 0;
+my_bool opt_local_infile, opt_slave_compressed_protocol;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
my_bool opt_log_slave_updates= 0;
-my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam, opt_ndbcluster;
+my_bool opt_innodb;
#ifdef HAVE_NDBCLUSTER_DB
const char *opt_ndbcluster_connectstring= 0;
+const char *opt_ndb_connectstring= 0;
+char opt_ndb_constrbuf[1024];
+unsigned opt_ndb_constrbuf_len= 0;
my_bool opt_ndb_shm, opt_ndb_optimized_node_selection;
+ulong opt_ndb_cache_check_time;
+const char *opt_ndb_mgmd;
+ulong opt_ndb_nodeid;
#endif
my_bool opt_readonly, use_temp_pool, relay_log_purge;
-my_bool opt_sync_bdb_logs, opt_sync_frm, opt_allow_suspicious_udfs;
+my_bool opt_sync_frm, opt_allow_suspicious_udfs;
my_bool opt_secure_auth= 0;
-my_bool opt_short_log_format= 0;
-my_bool opt_log_queries_not_using_indexes= 0;
my_bool opt_log_slow_admin_statements= 0;
my_bool lower_case_file_system= 0;
-my_bool opt_innodb_safe_binlog= 0;
+my_bool opt_large_pages= 0;
+uint opt_large_page_size= 0;
+my_bool opt_old_style_user_limits= 0, trust_routine_creators= 0;
+/*
+ True if there is at least one per-hour limit for some user, so we should
+ check them before each query (and possibly reset counters when hour is
+ changed). False otherwise.
+*/
volatile bool mqh_used = 0;
+my_bool opt_noacl;
+my_bool sp_automatic_privileges= 1;
#ifdef HAVE_INITGROUPS
static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
@@ -307,41 +386,30 @@ static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
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;
-ulong server_id, thd_startup_options;
-ulong table_cache_size, thread_stack, thread_stack_min, what_to_log;
+uint tc_heuristic_recover= 0;
+uint volatile thread_count, thread_running;
+ulonglong thd_startup_options;
+ulong back_log, connect_timeout, concurrency, server_id;
+ulong table_cache_size, thread_stack, what_to_log;
ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
ulong open_files_limit, max_binlog_size, max_relay_log_size;
ulong slave_net_timeout, slave_trans_retries;
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
ulong query_cache_size=0;
-ulong com_stat[(uint) SQLCOM_END], com_other;
-ulong com_stmt_prepare, com_stmt_execute, com_stmt_send_long_data;
-ulong com_stmt_close, com_stmt_reset;
-ulong bytes_sent, bytes_received, net_big_packet_count;
ulong refresh_version, flush_version; /* Increments on each reload */
-ulong query_id, long_query_count;
-ulong aborted_threads, killed_threads, aborted_connects;
+query_id_t query_id;
+ulong aborted_threads, aborted_connects;
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
-ulong delayed_insert_errors,flush_time, thread_created;
-ulong filesort_rows, filesort_range_count, filesort_scan_count;
-ulong filesort_merge_passes;
-ulong select_range_check_count, select_range_count, select_scan_count;
-ulong select_full_range_join_count,select_full_join_count;
-ulong specialflag=0,opened_tables=0,created_tmp_tables=0,
- created_tmp_disk_tables=0;
+ulong delayed_insert_errors,flush_time;
+ulong specialflag=0;
ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
-ulong max_connections,max_used_connections,
- max_connect_errors, max_user_connections = 0;
+ulong max_connections, max_connect_errors;
+uint max_user_connections= 0;
ulong thread_id=1L,current_pid;
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 */
-volatile ulong cached_thread_count= 0;
double log_10[32]; /* 10 potences */
time_t start_time;
@@ -349,11 +417,9 @@ time_t start_time;
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[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
- *mysqld_user,*mysqld_chroot, *opt_init_file,
- *opt_init_connect, *opt_init_slave,
+ *opt_init_file, *opt_tc_log_file,
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
const key_map key_map_empty(0);
@@ -361,20 +427,17 @@ key_map key_map_full(0); // Will be initialized later
const char *opt_date_time_formats[3];
-char *language_ptr, *default_collation_name, *default_character_set_name;
-char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
-struct passwd *user_info;
+char *mysql_data_home= mysql_real_data_home;
char server_version[SERVER_VERSION_LENGTH];
char *mysqld_unix_port, *opt_mysql_tmpdir;
-char *my_bind_addr_str;
const char **errmesg; /* Error messages */
const char *myisam_recover_options_str="OFF";
const char *myisam_stats_method_str="nulls_inequal";
-const char *sql_mode_str="OFF";
/* name of reference on left espression in rewritten IN subquery */
const char *in_left_expr_name= "<left expr>";
/* name of additional condition */
const char *in_additional_cond= "<IN COND>";
+my_decimal decimal_zero;
/* classes for comparation parsing/processing */
Eq_creator eq_creator;
Ne_creator ne_creator;
@@ -385,17 +448,19 @@ Le_creator le_creator;
FILE *bootstrap_file;
+int bootstrap_error;
FILE *stderror_file=0;
I_List<i_string_pair> replicate_rewrite_db;
I_List<i_string> replicate_do_db, replicate_ignore_db;
// allow the user to tell us which db to replicate and which to ignore
I_List<i_string> binlog_do_db, binlog_ignore_db;
-I_List<THD> threads,thread_cache;
+I_List<THD> threads;
I_List<NAMED_LIST> key_caches;
struct system_variables global_system_variables;
struct system_variables max_system_variables;
+struct system_status_var global_status_var;
MY_TMPDIR mysql_tmpdir_list;
MY_BITMAP temp_pool;
@@ -405,6 +470,7 @@ CHARSET_INFO *national_charset_info, *table_alias_charset;
SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam, have_ndbcluster,
have_example_db, have_archive_db, have_csv_db;
+SHOW_COMP_OPTION have_federated_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;
@@ -415,7 +481,7 @@ SHOW_COMP_OPTION have_blackhole_db;
pthread_key(MEM_ROOT**,THR_MALLOC);
pthread_key(THD*, THR_THD);
pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
- LOCK_mapped_file, LOCK_status,
+ LOCK_mapped_file, LOCK_status, LOCK_global_read_lock,
LOCK_error_log, LOCK_uuid_generator,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
@@ -425,9 +491,7 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
pthread_mutex_t LOCK_des_key_file;
#endif
rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
-pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
- COND_slave_start;
-pthread_cond_t COND_thread_cache,COND_flush_thread_cache;
+pthread_cond_t COND_refresh,COND_thread_count;
pthread_t signal_thread;
pthread_attr_t connection_attrib;
@@ -445,11 +509,11 @@ char *master_ssl_ca, *master_ssl_capath, *master_ssl_cipher;
/* Static variables */
static bool kill_in_progress, segfaulted;
-static my_bool opt_do_pstack, opt_noacl, opt_bootstrap, opt_myisam_log;
+static my_bool opt_do_pstack, opt_bootstrap, opt_myisam_log;
static int cleanup_done;
static ulong opt_specialflag, opt_myisam_block_size;
static char *opt_logname, *opt_update_logname, *opt_binlog_index_name;
-static char *opt_slow_logname;
+static char *opt_slow_logname, *opt_tc_heuristic_recover;
static char *mysql_home_ptr, *pidfile_name_ptr;
static char **defaults_argv;
static char *opt_bin_logname;
@@ -502,7 +566,7 @@ static const char* default_dbug_option;
char *libwrapName= NULL;
#endif
#ifdef HAVE_QUERY_CACHE
-ulong query_cache_limit= 0;
+static ulong query_cache_limit= 0;
ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
Query_cache query_cache;
#endif
@@ -522,7 +586,7 @@ struct st_VioSSLAcceptorFd *ssl_acceptor_fd;
/* Function declarations */
static void start_signal_handler(void);
-extern "C" pthread_handler_decl(signal_hand, arg);
+static pthread_handler_decl(signal_hand, arg);
static void mysql_init_variables(void);
static void get_options(int argc,char **argv);
static void set_server_version(void);
@@ -531,7 +595,7 @@ static char *get_relative_path(const char *path);
static void fix_paths(void);
extern "C" pthread_handler_decl(handle_connections_sockets,arg);
extern "C" pthread_handler_decl(kill_server_thread,arg);
-static int bootstrap(FILE *file);
+static void bootstrap(FILE *file);
static void close_server_sock();
static bool read_init_file(char *file_name);
#ifdef __NT__
@@ -568,14 +632,14 @@ static void close_connections(void)
(void) pthread_mutex_lock(&LOCK_manager);
if (manager_thread_in_use)
{
- DBUG_PRINT("quit",("killing manager thread: %lx",manager_thread));
+ DBUG_PRINT("quit",("killing manager thread: 0x%lx",manager_thread));
(void) pthread_cond_signal(&COND_manager);
}
(void) pthread_mutex_unlock(&LOCK_manager);
/* kill connection thread */
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
- DBUG_PRINT("quit",("waiting for select thread: %lx",select_thread));
+ DBUG_PRINT("quit",("waiting for select thread: 0x%lx",select_thread));
(void) pthread_mutex_lock(&LOCK_thread_count);
while (select_thread_in_use)
@@ -609,7 +673,7 @@ static void close_connections(void)
/* Abort listening to new connections */
DBUG_PRINT("quit",("Closing sockets"));
- if ( !opt_disable_networking )
+ if (!opt_disable_networking )
{
if (ip_sock != INVALID_SOCKET)
{
@@ -622,7 +686,7 @@ static void close_connections(void)
if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
{
HANDLE temp;
- DBUG_PRINT( "quit", ("Closing named pipes") );
+ DBUG_PRINT("quit", ("Closing named pipes") );
/* Create connection to the handle named pipe handler to break the loop */
if ((temp = CreateFile(pipe_name,
@@ -668,9 +732,10 @@ static void close_connections(void)
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
/* We skip slave threads on this first loop through. */
- if (tmp->slave_thread) continue;
+ if (tmp->slave_thread)
+ continue;
- tmp->killed= 1;
+ tmp->killed= THD::KILL_CONNECTION;
if (tmp->mysys_var)
{
tmp->mysys_var->abort=1;
@@ -801,7 +866,7 @@ void kill_mysql(void)
}
#endif
#elif defined(OS2)
- pthread_cond_signal( &eventShutdown); // post semaphore
+ pthread_cond_signal(&eventShutdown); // post semaphore
#elif defined(HAVE_PTHREAD_KILL)
if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
{
@@ -838,9 +903,9 @@ static void __cdecl kill_server(int sig_ptr)
#define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN
#endif
{
- int sig=(int) (long) sig_ptr; // This is passed a int
DBUG_ENTER("kill_server");
#ifndef EMBEDDED_LIBRARY
+ int sig=(int) (long) sig_ptr; // This is passed a int
// if there is a signal during the kill in progress, ignore the other
if (kill_in_progress) // Safety
RETURN_FROM_KILL_SERVER;
@@ -872,9 +937,10 @@ static void __cdecl kill_server(int sig_ptr)
unireg_abort(1); /* purecov: inspected */
else
unireg_end();
+
#ifdef __NETWARE__
if (!event_flag)
- pthread_join(select_thread, NULL); // wait for main thread
+ pthread_join(select_thread, NULL); // wait for main thread
#endif /* __NETWARE__ */
pthread_exit(0); /* purecov: deadcode */
@@ -965,7 +1031,6 @@ void clean_up(bool print_message)
mysql_log.cleanup();
mysql_slow_log.cleanup();
- mysql_update_log.cleanup();
mysql_bin_log.cleanup();
#ifdef HAVE_REPLICATION
@@ -990,6 +1055,9 @@ void clean_up(bool print_message)
udf_free();
#endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
+ if (tc_log)
+ tc_log->close();
+ xid_cache_free();
delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
multi_keycache_free();
end_thr_alarm(1); /* Free allocated memory */
@@ -1037,7 +1105,9 @@ void clean_up(bool print_message)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
#endif
- x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
+ finish_client_errs();
+ my_free((gptr) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
+ MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
DBUG_PRINT("quit", ("Error messages freed"));
/* Tell main we are ready */
(void) pthread_mutex_lock(&LOCK_thread_count);
@@ -1106,6 +1176,7 @@ static void clean_up_mutexes()
(void) rwlock_destroy(&LOCK_sys_init_connect);
(void) rwlock_destroy(&LOCK_sys_init_slave);
(void) pthread_mutex_destroy(&LOCK_global_system_variables);
+ (void) pthread_mutex_destroy(&LOCK_global_read_lock);
(void) pthread_cond_destroy(&COND_thread_count);
(void) pthread_cond_destroy(&COND_refresh);
(void) pthread_cond_destroy(&COND_thread_cache);
@@ -1201,7 +1272,7 @@ err:
static void set_user(const char *user, struct passwd *user_info)
{
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
- DBUG_ASSERT(user_info);
+ DBUG_ASSERT(user_info != 0);
#ifdef HAVE_INITGROUPS
/*
We can get a SIGSEGV when calling initgroups() on some systems when NSS
@@ -1230,7 +1301,7 @@ static void set_user(const char *user, struct passwd *user_info)
static void set_effective_user(struct passwd *user_info)
{
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
- DBUG_ASSERT(user_info);
+ DBUG_ASSERT(user_info != 0);
if (setregid((gid_t)-1, user_info->pw_gid) == -1)
{
sql_perror("setregid");
@@ -1259,7 +1330,7 @@ static void set_root(const char *path)
#endif
}
-static void server_init(void)
+static void network_init(void)
{
struct sockaddr_in IPaddr;
#ifdef HAVE_SYS_UN_H
@@ -1268,18 +1339,6 @@ static void server_init(void)
int arg=1;
DBUG_ENTER("server_init");
-#ifdef __WIN__
- if ( !opt_disable_networking )
- {
- WSADATA WsaData;
- if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
- {
- my_message(0,"WSAStartup Failed\n",MYF(0));
- unireg_abort(1);
- }
- }
-#endif /* __WIN__ */
-
set_ports();
if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
@@ -1321,16 +1380,6 @@ static void server_init(void)
}
}
- if ((user_info= check_user(mysqld_user)))
- {
-#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
- if (locked_in_memory) // getuid() == 0 here
- set_effective_user(user_info);
- else
-#endif
- set_user(mysqld_user, user_info);
- }
-
#ifdef __NT__
/* create named pipe */
if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
@@ -1353,7 +1402,7 @@ static void server_init(void)
sql_perror("Can't start server : Set security descriptor");
unireg_abort(1);
}
- saPipeSecurity.nLength = sizeof( SECURITY_ATTRIBUTES );
+ saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
saPipeSecurity.bInheritHandle = FALSE;
if ((hPipe= CreateNamedPipe(pipe_name,
@@ -1373,9 +1422,9 @@ static void server_init(void)
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, 0, NULL );
- MessageBox( NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",
- MB_OK|MB_ICONINFORMATION );
- LocalFree( lpMsgBuf );
+ MessageBox(NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",
+ MB_OK|MB_ICONINFORMATION);
+ LocalFree(lpMsgBuf);
unireg_abort(1);
}
}
@@ -1436,8 +1485,9 @@ void yyerror(const char *s)
/* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
s=ER(ER_SYNTAX_ERROR);
- net_printf(thd,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
- thd->lex->yylineno);
+ my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
+ (yytext ? (char*) yytext : ""),
+ thd->lex->yylineno);
}
@@ -1465,11 +1515,11 @@ void close_connection(THD *thd, uint errcode, bool lock)
errcode ? ER(errcode) : ""));
if (lock)
(void) pthread_mutex_lock(&LOCK_thread_count);
- thd->killed=1;
- if ((vio=thd->net.vio) != 0)
+ thd->killed= THD::KILL_CONNECTION;
+ if ((vio= thd->net.vio) != 0)
{
if (errcode)
- send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
+ net_send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
vio_close(vio); /* vio is freed in delete thd */
}
if (lock)
@@ -1582,7 +1632,7 @@ extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
THD *thd=current_thd;
DBUG_ENTER("abort_thread");
if (thd)
- thd->killed=1;
+ thd->killed= THD::KILL_CONNECTION;
DBUG_VOID_RETURN;
}
#endif
@@ -1598,7 +1648,7 @@ static void init_signals(void)
{
int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
- signal( signals[i], kill_server) ;
+ signal(signals[i], kill_server) ;
#if defined(__WIN__)
signal(SIGBREAK,SIG_IGN); //ignore SIGBREAK for NT
#else
@@ -1622,18 +1672,18 @@ static void check_data_home(const char *path)
// down server event callback
void mysql_down_server_cb(void *, void *)
{
- event_flag = TRUE;
+ event_flag= TRUE;
kill_server(0);
}
// destroy callback resources
void mysql_cb_destroy(void *)
-{
- UnRegisterEventNotification(eh); // cleanup down event notification
+{
+ UnRegisterEventNotification(eh); // cleanup down event notification
NX_UNWRAP_INTERFACE(ref);
- /* Deregister NSS volume deactivation event */
- NX_UNWRAP_INTERFACE(refneb);
+ /* Deregister NSS volume deactivation event */
+ NX_UNWRAP_INTERFACE(refneb);
if (neb_consumer_id)
UnRegisterConsumer(neb_consumer_id, NULL);
}
@@ -1757,7 +1807,6 @@ ulong neb_event_callback(struct EventBlock *eblock)
nw_panic = TRUE;
event_flag= TRUE;
kill_server(0);
-
}
}
return 0;
@@ -1815,7 +1864,7 @@ static void getvolumeID(BYTE *volumeName)
datavolid.clockSeqLow= info.vol.volumeID.clockSeqLow;
/* This is guranteed to be 6-byte length (but sizeof() would be better) */
memcpy(datavolid.node, info.vol.volumeID.node, (unsigned int) 6);
-
+
exit:
if (rootKey)
zClose(rootKey);
@@ -1858,7 +1907,8 @@ static void check_data_home(const char *path)
static void sig_reload(int signo)
{
// Flush everything
- reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0, NULL);
+ bool not_used;
+ reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0, &not_used);
signal(signo, SIG_ACK);
}
@@ -1924,12 +1974,12 @@ the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n",
(ulong) dflt_key_cache->key_cache_mem_size);
- fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
- fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
- fprintf(stderr, "max_connections=%ld\n", max_connections);
- fprintf(stderr, "threads_connected=%d\n", thread_count);
+ fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
+ fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
+ fprintf(stderr, "max_connections=%lu\n", max_connections);
+ fprintf(stderr, "threads_connected=%u\n", thread_count);
fprintf(stderr, "It is possible that mysqld could use up to \n\
-key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
+key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %lu K\n\
bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
(global_system_variables.read_buff_size +
global_system_variables.sortbuff_size) *
@@ -1960,7 +2010,7 @@ the thread stack. Please read http://www.mysql.com/doc/en/Linux.html\n\n",
fprintf(stderr, "Trying to get some variables.\n\
Some pointers may be invalid and cause the dump to abort...\n");
safe_print_str("thd->query", thd->query, 1024);
- fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id);
+ fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id);
}
fprintf(stderr, "\
The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\
@@ -2085,8 +2135,16 @@ static void start_signal_handler(void)
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
+#if defined(__ia64__) || defined(__ia64)
+ /*
+ Peculiar things with ia64 platforms - it seems we only have half the
+ stack size in reality, so we have to double it here
+ */
+ pthread_attr_setstacksize(&thr_attr,thread_stack*2);
+#else
pthread_attr_setstacksize(&thr_attr,thread_stack);
#endif
+#endif
(void) pthread_mutex_lock(&LOCK_thread_count);
if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
@@ -2106,7 +2164,7 @@ static void start_signal_handler(void)
/* This threads handles all signals and alarms */
/* ARGSUSED */
-extern "C" void *signal_hand(void *arg __attribute__((unused)))
+static void *signal_hand(void *arg __attribute__((unused)))
{
sigset_t set;
int sig;
@@ -2199,7 +2257,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
- (void*) sig))
+ (void*) &sig))
sql_print_error("Can't create thread to kill server");
#else
kill_server((void*) sig); // MIT THREAD has a alarm thread
@@ -2209,12 +2267,13 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
case SIGHUP:
if (!abort_loop)
{
- mysql_print_status((THD*) 0); // Print some debug info
+ bool not_used;
+ mysql_print_status(); // Print some debug info
reload_acl_and_cache((THD*) 0,
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
- REFRESH_STATUS | REFRESH_GRANT |
+ REFRESH_GRANT |
REFRESH_THREADS | REFRESH_HOSTS),
- (TABLE_LIST*) 0, NULL); // Flush logs
+ (TABLE_LIST*) 0, &not_used); // Flush logs
}
break;
#ifdef USE_ONE_SIGNAL_HAND
@@ -2240,19 +2299,34 @@ static void check_data_home(const char *path)
/*
- All global error messages are sent here where the first one is stored for
- the client
+ All global error messages are sent here where the first one is stored
+ for the client
*/
/* ARGSUSED */
-extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
+static int my_message_sql(uint error, const char *str, myf MyFlags)
{
THD *thd;
DBUG_ENTER("my_message_sql");
- DBUG_PRINT("error", ("Message: '%s'", str));
+ DBUG_PRINT("error", ("error: %u message: '%s'", error, str));
+ /*
+ Put here following assertion when situation with EE_* error codes
+ will be fixed
+ DBUG_ASSERT(error != 0);
+ */
if ((thd= current_thd))
{
+ if (thd->spcont &&
+ thd->spcont->find_handler(error, MYSQL_ERROR::WARN_LEVEL_ERROR))
+ {
+ DBUG_RETURN(0);
+ }
+
+ thd->query_error= 1; // needed to catch query errors during replication
+
+ if (!thd->no_warnings_for_error)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
/*
thd->lex->current_select == 0 if lex structure is not inited
(not query command (COM_QUERY))
@@ -2264,13 +2338,14 @@ extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
(thd->lex->current_select ?
thd->lex->current_select->no_error : 0),
(int) thd->is_fatal_error));
-
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
}
else
{
NET *net= &thd->net;
net->report_error= 1;
+#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
+ query_cache_abort(net);
+#endif
if (!net->last_error[0]) // Return only first message
{
strmake(net->last_error, str, sizeof(net->last_error)-1);
@@ -2283,6 +2358,19 @@ extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
DBUG_RETURN(0);
}
+
+static void *my_str_malloc_mysqld(size_t size)
+{
+ return my_malloc(size, MYF(MY_FAE));
+}
+
+
+static void my_str_free_mysqld(void *ptr)
+{
+ my_free((gptr)ptr, MYF(MY_FAE));
+}
+
+
#ifdef __WIN__
struct utsname
@@ -2331,10 +2419,10 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
my_thread_init();
// wait semaphore
- pthread_cond_wait( &eventShutdown, NULL);
+ pthread_cond_wait(&eventShutdown, NULL);
// close semaphore and kill server
- pthread_cond_destroy( &eventShutdown);
+ pthread_cond_destroy(&eventShutdown);
/*
Exit main loop on main thread, so kill will be done from
@@ -2351,43 +2439,16 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
#endif
-const char *load_default_groups[]= {
+static const char *load_default_groups[]= {
#ifdef HAVE_NDBCLUSTER_DB
"mysql_cluster",
#endif
-"mysqld","server",MYSQL_BASE_VERSION,0,0};
+"mysqld","server", MYSQL_BASE_VERSION, 0, 0};
+
+#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
static const int load_default_groups_sz=
sizeof(load_default_groups)/sizeof(load_default_groups[0]);
-
-bool open_log(MYSQL_LOG *log, const char *hostname,
- const char *opt_name, const char *extension,
- const char *index_file_name,
- enum_log_type type, bool read_append,
- bool no_auto_events, ulong max_size)
-{
- char tmp[FN_REFLEN];
- if (!opt_name || !opt_name[0])
- {
- /*
- TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
- */
- strmake(tmp,hostname,FN_REFLEN-5);
- strmov(fn_ext(tmp),extension);
- opt_name=tmp;
- }
- // get rid of extension if the log is binary to avoid problems
- if (type == LOG_BIN)
- {
- char *p = fn_ext(opt_name);
- uint length=(uint) (p-opt_name);
- strmake(tmp,opt_name,min(length,FN_REFLEN));
- opt_name=tmp;
- }
- return log->open(opt_name, type, 0, index_file_name,
- (read_append) ? SEQ_READ_APPEND : WRITE_CACHE,
- no_auto_events, max_size);
-}
+#endif
/*
@@ -2397,7 +2458,7 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
init_global_datetime_format()
format_type What kind of format should be supported
var_ptr Pointer to variable that should be updated
-
+
NOTES
The default value is taken from either opt_date_time_formats[] or
the ISO format (ANSI SQL)
@@ -2407,8 +2468,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
1 error
*/
-bool init_global_datetime_format(timestamp_type format_type,
- DATE_TIME_FORMAT **var_ptr)
+static bool init_global_datetime_format(timestamp_type format_type,
+ DATE_TIME_FORMAT **var_ptr)
{
/* Get command line option */
const char *str= opt_date_time_formats[format_type];
@@ -2436,6 +2497,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
char **argv, const char **groups)
{
umask(((~my_umask) & 0666));
+ my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
tzset(); // Set tzname
max_system_variables.pseudo_thread_id= (ulong)~0;
@@ -2476,7 +2538,6 @@ static int init_common_variables(const char *conf_file_name, int argc,
before MY_INIT(). So we do it here.
*/
mysql_log.init_pthread_objects();
- mysql_update_log.init_pthread_objects();
mysql_slow_log.init_pthread_objects();
mysql_bin_log.init_pthread_objects();
@@ -2493,6 +2554,19 @@ static int init_common_variables(const char *conf_file_name, int argc,
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
server_version, SYSTEM_TYPE,MACHINE_TYPE));
+#ifdef HAVE_LARGE_PAGES
+ /* Initialize large page size */
+ if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
+ {
+ my_use_large_pages= 1;
+ my_large_page_size= opt_large_page_size;
+#ifdef HAVE_INNOBASE_DB
+ innobase_use_large_pages= 1;
+ innobase_large_page_size= opt_large_page_size;
+#endif
+ }
+#endif /* HAVE_LARGE_PAGES */
+
/* connections and databases needs lots of files */
{
uint files, wanted_files;
@@ -2645,6 +2719,7 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_global_read_lock, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
#ifdef HAVE_OPENSSL
(void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
@@ -2661,6 +2736,7 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_rpl_status, NULL);
#endif
+ sp_cache_init();
/* Parameter for threads created for connections */
(void) pthread_attr_init(&connection_attrib);
(void) pthread_attr_setdetachstate(&connection_attrib,
@@ -2688,7 +2764,7 @@ static void init_ssl()
ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
opt_ssl_ca, opt_ssl_capath,
opt_ssl_cipher);
- DBUG_PRINT("info",("ssl_acceptor_fd: %lx", (long) ssl_acceptor_fd));
+ DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
if (!ssl_acceptor_fd)
opt_use_ssl = 0;
}
@@ -2716,41 +2792,69 @@ static int init_server_components()
#endif
/* Setup log files */
if (opt_log)
- open_log(&mysql_log, glob_hostname, opt_logname, ".log", NullS,
- LOG_NORMAL, 0, 0, 0);
+ mysql_log.open_query_log(opt_logname);
if (opt_update_log)
{
- open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
- NullS, LOG_NEW, 0, 0, 0);
- using_update_log=1;
- }
- if (opt_slow_log)
- open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
- NullS, LOG_NORMAL, 0, 0, 0);
-
- if (opt_bin_log)
- {
- /* If we fail to open binlog, it's going to hinder our recovery, so die */
- if (open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
- opt_binlog_index_name, LOG_BIN, 0, 0, max_binlog_size))
- unireg_abort(1);
- using_update_log=1;
-#ifdef HAVE_REPLICATION
- if (expire_logs_days)
+ /*
+ Update log is removed since 5.0. But we still accept the option.
+ The idea is if the user already uses the binlog and the update log,
+ we completely ignore any option/variable related to the update log, like
+ if the update log did not exist. But if the user uses only the update
+ log, then we translate everything into binlog for him (with warnings).
+ Implementation of the above :
+ - If mysqld is started with --log-update and --log-bin,
+ ignore --log-update (print a warning), push a warning when SQL_LOG_UPDATE
+ is used, and turn off --sql-bin-update-same.
+ This will completely ignore SQL_LOG_UPDATE
+ - If mysqld is started with --log-update only,
+ change it to --log-bin (with the filename passed to log-update,
+ plus '-bin') (print a warning), push a warning when SQL_LOG_UPDATE is
+ used, and turn on --sql-bin-update-same.
+ This will translate SQL_LOG_UPDATE to SQL_LOG_BIN.
+
+ Note that we tell the user that --sql-bin-update-same is deprecated and
+ does nothing, and we don't take into account if he used this option or
+ not; but internally we give this variable a value to have the behaviour
+ we want (i.e. have SQL_LOG_UPDATE influence SQL_LOG_BIN or not).
+ As sql-bin-update-same, log-update and log-bin cannot be changed by the
+ user after starting the server (they are not variables), the user will
+ not later interfere with the settings we do here.
+ */
+ if (opt_bin_log)
{
- long purge_time= time(0) - expire_logs_days*24*60*60;
- if (purge_time >= 0)
- mysql_bin_log.purge_logs_before_date(purge_time);
+ opt_sql_bin_update= 0;
+ sql_print_error("The update log is no longer supported by MySQL in \
+version 5.0 and above. It is replaced by the binary log.");
+ }
+ else
+ {
+ opt_sql_bin_update= 1;
+ opt_bin_log= 1;
+ if (opt_update_logname)
+ {
+ /* as opt_bin_log==0, no need to free opt_bin_logname */
+ if (!(opt_bin_logname= my_strdup(opt_update_logname, MYF(MY_WME))))
+ exit(EXIT_OUT_OF_MEMORY);
+ sql_print_error("The update log is no longer supported by MySQL in \
+version 5.0 and above. It is replaced by the binary log. Now starting MySQL \
+with --log-bin='%s' instead.",opt_bin_logname);
+ }
+ else
+ sql_print_error("The update log is no longer supported by MySQL in \
+version 5.0 and above. It is replaced by the binary log. Now starting MySQL \
+with --log-bin instead.");
}
-#endif
}
- else if (opt_log_slave_updates)
+ if (opt_log_slave_updates && !opt_bin_log)
{
- sql_print_warning("\
-you need to use --log-bin to make --log-slave-updates work. \
-Now disabling --log-slave-updates.");
+ sql_print_warning("You need to use --log-bin to make "
+ "--log-slave-updates work.");
+ unireg_abort(1);
}
+ if (opt_slow_log)
+ mysql_slow_log.open_slow_log(opt_slow_logname);
+
#ifdef HAVE_REPLICATION
if (opt_log_slave_updates && replicate_same_server_id)
{
@@ -2781,60 +2885,84 @@ server.");
}
}
- if (opt_innodb_safe_binlog)
+ if (opt_bin_log)
{
- if (have_innodb != SHOW_OPTION_YES)
- sql_print_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_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)
+ char buf[FN_REFLEN];
+ const char *ln;
+ ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
+ if (!opt_bin_logname && !opt_binlog_index_name)
{
/*
- 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).
+ User didn't give us info to name the binlog index file.
+ Picking `hostname`-bin.index like did in 4.x, causes replication to
+ fail if the hostname is changed later. So, we would like to instead
+ require a name. But as we don't want to break many existing setups, we
+ only give warning, not error.
*/
- sql_print_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.");
+ sql_print_warning("No argument was provided to --log-bin, and "
+ "--log-bin-index was not used; so replication "
+ "may break when this MySQL server acts as a "
+ "master and has his hostname changed!! Please "
+ "use '--log-bin=%s' to avoid this problem.", ln);
}
- if (sync_binlog_period != 1)
+ if (ln == buf)
{
- sql_print_warning("--innodb-safe-binlog is meaningful only if "
- "the global sync_binlog variable is 1; now setting it "
- "to 1.");
- sync_binlog_period= 1;
+ my_free(opt_bin_logname, MYF(MY_ALLOW_ZERO_PTR));
+ opt_bin_logname=my_strdup(buf, MYF(0));
}
-#endif
+ if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln))
+ {
+ unireg_abort(1);
+ }
+
+ /*
+ Used to specify which type of lock we need to use for queries of type
+ INSERT ... SELECT. This will change when we have row level logging.
+ */
+ using_update_log=1;
}
+ if (xid_cache_init())
+ {
+ sql_print_error("Out of memory");
+ unireg_abort(1);
+ }
if (ha_init())
{
sql_print_error("Can't init databases");
unireg_abort(1);
}
- if (opt_myisam_log)
- (void) mi_log(1);
+ tc_log= (total_ha_2pc > 1 ? (opt_bin_log ?
+ (TC_LOG *) &mysql_bin_log :
+ (TC_LOG *) &tc_log_mmap) :
+ (TC_LOG *) &tc_log_dummy);
- /*
- 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)
+ if (tc_log->open(opt_bin_logname))
{
- /* not fatal if fails (but print errors) */
- mysql_bin_log.cut_spurious_tail();
+ sql_print_error("Can't init tc log");
+ unireg_abort(1);
}
- mysql_bin_log.report_pos_in_innodb();
+
+ if (ha_recover(0))
+ {
+ unireg_abort(1);
+ }
+
+ if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
+ WRITE_CACHE, 0, max_binlog_size, 0))
+ unireg_abort(1);
+
+#ifdef HAVE_REPLICATION
+ if (opt_bin_log && expire_logs_days)
+ {
+ long purge_time= time(0) - expire_logs_days*24*60*60;
+ if (purge_time >= 0)
+ mysql_bin_log.purge_logs_before_date(purge_time);
+ }
+#endif
+
+ if (opt_myisam_log)
+ (void) mi_log(1);
/* call ha_init_key_cache() on all key caches to init them */
process_key_caches(&ha_init_key_cache);
@@ -2983,19 +3111,33 @@ int win_main(int argc, char **argv)
int main(int argc, char **argv)
#endif
{
-
DEBUGGER_OFF;
-
MY_INIT(argv[0]); // init my_sys library & pthreads
#ifdef _CUSTOMSTARTUPCONFIG_
if (_cust_check_startup())
{
/ * _cust_check_startup will report startup failure error * /
- exit( 1 );
+ exit(1);
}
#endif
+#ifdef __WIN__
+ /*
+ Before performing any socket operation (like retrieving hostname
+ in init_common_variables we have to call WSAStartup
+ */
+ {
+ WSADATA WsaData;
+ if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
+ {
+ /* errors are not read yet, so we use english text here */
+ my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
+ unireg_abort(1);
+ }
+ }
+#endif /* __WIN__ */
+
if (init_common_variables(MYSQL_CONFIG_NAME,
argc, argv, load_default_groups))
unireg_abort(1); // Will do exit
@@ -3003,23 +3145,37 @@ int main(int argc, char **argv)
init_signals();
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
+#if defined(__ia64__) || defined(__ia64)
+ /*
+ Peculiar things with ia64 platforms - it seems we only have half the
+ stack size in reality, so we have to double it here
+ */
+ pthread_attr_setstacksize(&connection_attrib,thread_stack*2);
+#else
pthread_attr_setstacksize(&connection_attrib,thread_stack);
+#endif
#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
{
/* Retrieve used stack size; Needed for checking stack overflows */
size_t stack_size= 0;
pthread_attr_getstacksize(&connection_attrib, &stack_size);
+#if defined(__ia64__) || defined(__ia64)
+ stack_size/= 2;
+#endif
/* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
if (stack_size && stack_size < thread_stack)
{
if (global_system_variables.log_warnings)
sql_print_warning("Asked for %ld thread stack, but got %ld",
- thread_stack, stack_size);
+ thread_stack, stack_size);
+#if defined(__ia64__) || defined(__ia64)
+ thread_stack= stack_size*2;
+#else
thread_stack= stack_size;
+#endif
}
}
#endif
- thread_stack_min=thread_stack - STACK_MIN_SIZE;
(void) thr_setconcurrency(concurrency); // 10 by default
@@ -3043,7 +3199,17 @@ int main(int argc, char **argv)
mysql_data_home= mysql_data_home_buff;
mysql_data_home[0]=FN_CURLIB; // all paths are relative from here
mysql_data_home[1]=0;
- server_init();
+
+ if ((user_info= check_user(mysqld_user)))
+ {
+#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
+ if (locked_in_memory) // getuid() == 0 here
+ set_effective_user(user_info);
+ else
+#endif
+ set_user(mysqld_user, user_info);
+ }
+
if (opt_bin_log && !server_id)
{
@@ -3068,6 +3234,8 @@ we force server id to 2, but this MySQL server will not act as a slave.");
if (init_server_components())
exit(1);
+ network_init();
+
#ifdef __WIN__
if (!opt_console)
{
@@ -3078,10 +3246,16 @@ we force server id to 2, but this MySQL server will not act as a slave.");
#endif
/*
+ Initialize my_str_malloc() and my_str_free()
+ */
+ my_str_malloc= &my_str_malloc_mysqld;
+ my_str_free= &my_str_free_mysqld;
+
+ /*
init signals & alarm
After this we can't quit by a simple unireg_abort
*/
- error_handler_hook = my_message_sql;
+ error_handler_hook= my_message_sql;
start_signal_handler(); // Creates pidfile
if (acl_init(opt_noacl) ||
my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
@@ -3123,9 +3297,9 @@ we force server id to 2, but this MySQL server will not act as a slave.");
if (opt_bootstrap)
{
select_thread_in_use= 0; // Allow 'kill' to work
- int error= bootstrap(stdin);
+ bootstrap(stdin);
end_thr_alarm(1); // Don't allow alarms
- unireg_abort(error ? 1 : 0);
+ unireg_abort(bootstrap_error ? 1 : 0);
}
if (opt_init_file)
{
@@ -3139,20 +3313,17 @@ we force server id to 2, but this MySQL server will not act as a slave.");
create_shutdown_thread();
create_maintenance_thread();
- printf(ER(ER_READY),my_progname,server_version,
- ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysqld_unix_port),
- mysqld_port, "");
- if (MYSQL_COMPILATION_COMMENT[0] != '\0')
- fputs(" " MYSQL_COMPILATION_COMMENT, stdout);
-
- putchar('\n');
- fflush(stdout);
+ sql_print_information(ER(ER_STARTUP),my_progname,server_version,
+ ((unix_sock == INVALID_SOCKET) ? (char*) ""
+ : mysqld_unix_port),
+ mysqld_port,
+ MYSQL_COMPILATION_COMMENT);
#if defined(__NT__) || defined(HAVE_SMEM)
handle_connections_methods();
#else
#ifdef __WIN__
- if ( !have_tcpip || opt_disable_networking)
+ if (!have_tcpip || opt_disable_networking)
{
sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces");
unireg_abort(1);
@@ -3255,7 +3426,8 @@ default_service_handling(char **argv,
const char *servicename,
const char *displayname,
const char *file_path,
- const char *extra_opt)
+ const char *extra_opt,
+ const char *account_name)
{
char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
end= path_and_service + sizeof(path_and_service)-3;
@@ -3274,12 +3446,14 @@ default_service_handling(char **argv,
if (Service.got_service_option(argv, "install"))
{
- Service.Install(1, servicename, displayname, path_and_service);
+ Service.Install(1, servicename, displayname, path_and_service,
+ account_name);
return 0;
}
if (Service.got_service_option(argv, "install-manual"))
{
- Service.Install(0, servicename, displayname, path_and_service);
+ Service.Install(0, servicename, displayname, path_and_service,
+ account_name);
return 0;
}
if (Service.got_service_option(argv, "remove"))
@@ -3294,13 +3468,14 @@ default_service_handling(char **argv,
int main(int argc, char **argv)
{
- /* When several instances are running on the same machine, we
- need to have an unique named hEventShudown through the
- application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
- */
+ /*
+ When several instances are running on the same machine, we
+ need to have an unique named hEventShudown through the
+ application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
+ */
int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
- "MySQLShutdown"), 10);
-
+ "MySQLShutdown"), 10);
+
/* Must be initialized early for comparison of service name */
system_charset_info= &my_charset_utf8_general_ci;
@@ -3314,7 +3489,7 @@ int main(int argc, char **argv)
if (argc == 2)
{
if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
- file_path, ""))
+ file_path, "", NULL))
return 0;
if (Service.IsService(argv[1])) /* Start an optional service */
{
@@ -3333,7 +3508,8 @@ int main(int argc, char **argv)
}
else if (argc == 3) /* install or remove any optional service */
{
- if (!default_service_handling(argv, argv[2], argv[2], file_path, ""))
+ if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
+ NULL))
return 0;
if (Service.IsService(argv[2]))
{
@@ -3351,15 +3527,30 @@ int main(int argc, char **argv)
return 0;
}
}
- else if (argc == 4)
+ else if (argc == 4 || argc == 5)
{
/*
- Install an optional service with optional config file
- mysqld --install-manual mysqldopt --defaults-file=c:\miguel\my.ini
+ This may seem strange, because we handle --local-service while
+ preserving 4.1's behavior of allowing any one other argument that is
+ passed to the service on startup. (The assumption is that this is
+ --defaults-file=file, but that was not enforced in 4.1, so we don't
+ enforce it here.)
*/
- if (!default_service_handling(argv, argv[2], argv[2], file_path,
- argv[3]))
- return 0;
+ const char *extra_opt= NullS;
+ const char *account_name = NullS;
+ int index;
+ for (index = 3; index < argc; index++)
+ {
+ if (!strcmp(argv[index], "--local-service"))
+ account_name= "NT AUTHORITY\\LocalService";
+ else
+ extra_opt= argv[index];
+ }
+
+ if (argc == 4 || account_name)
+ if (!default_service_handling(argv, argv[2], argv[2], file_path,
+ extra_opt, account_name))
+ return 0;
}
else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
{
@@ -3383,9 +3574,8 @@ int main(int argc, char **argv)
create MySQL privilege tables without having to start a full MySQL server.
*/
-static int bootstrap(FILE *file)
+static void bootstrap(FILE *file)
{
- int error= 0;
DBUG_ENTER("bootstrap");
THD *thd= new THD;
@@ -3403,7 +3593,8 @@ static int bootstrap(FILE *file)
(void*) thd))
{
sql_print_warning("Can't create thread to handle bootstrap");
- DBUG_RETURN(-1);
+ bootstrap_error=-1;
+ DBUG_VOID_RETURN;
}
/* Wait for thread to die */
(void) pthread_mutex_lock(&LOCK_thread_count);
@@ -3418,13 +3609,7 @@ static int bootstrap(FILE *file)
handle_bootstrap((void *)thd);
#endif
- error= thd->is_fatal_error;
-#ifndef EMBEDDED_LIBRARY
- net_end(&thd->net);
-#endif
- thd->cleanup();
- delete thd;
- DBUG_RETURN(error);
+ DBUG_VOID_RETURN;
}
@@ -3435,7 +3620,7 @@ static bool read_init_file(char *file_name)
DBUG_PRINT("enter",("name: %s",file_name));
if (!(file=my_fopen(file_name,O_RDONLY,MYF(MY_WME))))
return(1);
- bootstrap(file); /* Ignore errors from this */
+ bootstrap(file);
(void) my_fclose(file,MYF(MY_WME));
return 0;
}
@@ -3500,10 +3685,10 @@ static void create_new_thread(THD *thd)
("Can't create thread to handle request (error %d)",
error));
thread_count--;
- thd->killed=1; // Safety
+ thd->killed= THD::KILL_CONNECTION; // Safety
(void) pthread_mutex_unlock(&LOCK_thread_count);
statistic_increment(aborted_connects,&LOCK_status);
- net_printf(thd,ER_CANT_CREATE_THREAD,error);
+ net_printf_error(thd, ER_CANT_CREATE_THREAD, error);
(void) pthread_mutex_lock(&LOCK_thread_count);
close_connection(thd,0,0);
delete thd;
@@ -3531,11 +3716,8 @@ inline void kill_broken_server()
(!opt_disable_networking && ip_sock == INVALID_SOCKET))
{
select_thread_in_use = 0;
-#ifdef __NETWARE__
- kill_server(MYSQL_KILL_SIGNAL); /* never returns */
-#else
- kill_server((void*)MYSQL_KILL_SIGNAL); /* never returns */
-#endif /* __NETWARE__ */
+ /* The following call will never return */
+ kill_server(IF_NETWARE(MYSQL_KILL_SIGNAL, (void*) MYSQL_KILL_SIGNAL));
}
}
#define MAYBE_BROKEN_SYSCALL kill_broken_server();
@@ -3727,7 +3909,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets,
if (!(vio_tmp=vio_new(new_sock,
sock == unix_sock ? VIO_TYPE_SOCKET :
VIO_TYPE_TCPIP,
- sock == unix_sock)) ||
+ sock == unix_sock ? VIO_LOCALHOST: 0)) ||
my_net_init(&thd->net,vio_tmp))
{
if (vio_tmp)
@@ -3774,25 +3956,27 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
while (!abort_loop)
{
/* wait for named pipe connection */
- fConnected = ConnectNamedPipe( hPipe, NULL );
+ fConnected = ConnectNamedPipe(hPipe, NULL);
if (abort_loop)
break;
if (!fConnected)
fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
if (!fConnected)
{
- CloseHandle( hPipe );
- if ((hPipe = CreateNamedPipe(pipe_name,
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_BYTE |
- PIPE_READMODE_BYTE |
- PIPE_WAIT,
- PIPE_UNLIMITED_INSTANCES,
- (int) global_system_variables.net_buffer_length,
- (int) global_system_variables.net_buffer_length,
- NMPWAIT_USE_DEFAULT_WAIT,
- &saPipeSecurity )) ==
- INVALID_HANDLE_VALUE )
+ CloseHandle(hPipe);
+ if ((hPipe= CreateNamedPipe(pipe_name,
+ PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_BYTE |
+ PIPE_READMODE_BYTE |
+ PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES,
+ (int) global_system_variables.
+ net_buffer_length,
+ (int) global_system_variables.
+ net_buffer_length,
+ NMPWAIT_USE_DEFAULT_WAIT,
+ &saPipeSecurity)) ==
+ INVALID_HANDLE_VALUE)
{
sql_perror("Can't create new named pipe!");
break; // Abort
@@ -3819,8 +4003,8 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
if (!(thd = new THD))
{
- DisconnectNamedPipe( hConnectedPipe );
- CloseHandle( hConnectedPipe );
+ DisconnectNamedPipe(hConnectedPipe);
+ CloseHandle(hConnectedPipe);
continue;
}
if (!(thd->net.vio = vio_new_win32pipe(hConnectedPipe)) ||
@@ -3921,7 +4105,7 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
/*
it can be after shutdown command
*/
- if (abort_loop)
+ if (abort_loop)
goto error;
HANDLE handle_client_file_map= 0;
@@ -4104,7 +4288,7 @@ enum options_mysqld
OPT_MASTER_HOST, OPT_MASTER_USER,
OPT_MASTER_PASSWORD, OPT_MASTER_PORT,
OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
- OPT_MASTER_RETRY_COUNT,
+ OPT_MASTER_RETRY_COUNT, OPT_LOG_TC, OPT_LOG_TC_SIZE,
OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH,
OPT_MASTER_SSL_CIPHER, OPT_MASTER_SSL_CA,
@@ -4118,7 +4302,7 @@ enum options_mysqld
OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE,
OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE,
OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_REPLICATE_SAME_SERVER_ID,
- OPT_DISCONNECT_SLAVE_EVENT_COUNT,
+ OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_TC_HEURISTIC_RECOVER,
OPT_ABORT_SLAVE_EVENT_COUNT,
OPT_INNODB_DATA_HOME_DIR,
OPT_INNODB_DATA_FILE_PATH,
@@ -4127,16 +4311,21 @@ enum options_mysqld
OPT_INNODB_LOG_ARCHIVE,
OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
OPT_INNODB_FLUSH_METHOD,
+ OPT_INNODB_DOUBLEWRITE,
+ OPT_INNODB_CHECKSUMS,
OPT_INNODB_FAST_SHUTDOWN,
OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB,
OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
+ OPT_LOG_BIN_TRUST_ROUTINE_CREATORS,
OPT_SAFE_SHOW_DB, OPT_INNODB_SAFE_BINLOG,
OPT_INNODB, OPT_ISAM,
+ OPT_ENGINE_CONDITION_PUSHDOWN,
OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, OPT_NDB_USE_EXACT_COUNT,
OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
- OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION,
+ OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_NDB_CACHE_CHECK_TIME,
+ OPT_NDB_MGMD, OPT_NDB_NODEID,
OPT_SKIP_SAFEMALLOC,
- OPT_TEMP_POOL, OPT_TX_ISOLATION,
+ OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
@@ -4167,7 +4356,7 @@ enum options_mysqld
OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
OPT_MAX_LENGTH_FOR_SORT_DATA,
OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
- OPT_MAX_ERROR_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
+ OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
OPT_MYISAM_STATS_METHOD,
@@ -4177,7 +4366,8 @@ enum options_mysqld
OPT_PRELOAD_BUFFER_SIZE,
OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE,
OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER,
- OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
+ OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT, OPT_RELAY_LOG_SPACE_LIMIT,
+ OPT_RELAY_LOG_PURGE,
OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING,
OPT_SORT_BUFFER, OPT_TABLE_CACHE,
@@ -4199,8 +4389,12 @@ enum options_mysqld
OPT_INNODB_STATUS_FILE,
OPT_INNODB_MAX_DIRTY_PAGES_PCT,
OPT_INNODB_TABLE_LOCKS,
+ OPT_INNODB_SUPPORT_XA,
OPT_INNODB_OPEN_FILES,
OPT_INNODB_AUTOEXTEND_INCREMENT,
+ OPT_INNODB_SYNC_SPIN_LOOPS,
+ OPT_INNODB_CONCURRENCY_TICKETS,
+ OPT_INNODB_THREAD_SLEEP_DELAY,
OPT_BDB_CACHE_SIZE,
OPT_BDB_LOG_BUFFER_SIZE,
OPT_BDB_MAX_LOCK,
@@ -4229,7 +4423,16 @@ enum options_mysqld
OPT_DATETIME_FORMAT,
OPT_LOG_QUERIES_NOT_USING_INDEXES,
OPT_DEFAULT_TIME_ZONE,
- OPT_LOG_SLOW_ADMIN_STATEMENTS
+ OPT_OPTIMIZER_SEARCH_DEPTH,
+ OPT_OPTIMIZER_PRUNE_LEVEL,
+ OPT_UPDATABLE_VIEWS_WITH_LIMIT,
+ OPT_SP_AUTOMATIC_PRIVILEGES,
+ OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
+ OPT_ENABLE_LARGE_PAGES,
+ OPT_TIMED_MUTEXES,
+ OPT_OLD_STYLE_USER_LIMITS,
+ OPT_LOG_SLOW_ADMIN_STATEMENTS,
+ OPT_TABLE_LOCK_WAIT_TIMEOUT
};
@@ -4255,6 +4458,20 @@ struct my_option my_long_options[] =
"from libc.so",
(gptr*) &opt_allow_suspicious_udfs, (gptr*) &opt_allow_suspicious_udfs,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"auto-increment-increment", OPT_AUTO_INCREMENT,
+ "Auto-increment columns are incremented by this",
+ (gptr*) &global_system_variables.auto_increment_increment,
+ (gptr*) &max_system_variables.auto_increment_increment, 0, GET_ULONG,
+ OPT_ARG, 1, 1, 65535, 0, 1, 0 },
+ {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET,
+ "Offset added to Auto-increment columns. Used when auto-increment-increment != 1",
+ (gptr*) &global_system_variables.auto_increment_offset,
+ (gptr*) &max_system_variables.auto_increment_offset, 0, GET_ULONG, OPT_ARG,
+ 1, 1, 65535, 0, 1, 0 },
+ {"automatic-sp-privileges", OPT_SP_AUTOMATIC_PRIVILEGES,
+ "Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.",
+ (gptr*) &sp_automatic_privileges, (gptr*) &sp_automatic_privileges,
+ 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"basedir", 'b',
"Path to installation directory. All paths are usually resolved relative to this.",
(gptr*) &mysql_home_ptr, (gptr*) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG,
@@ -4276,8 +4493,7 @@ Disable with --skip-bdb (will save memory).",
"Don't try to recover Berkeley DB tables on start.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"bdb-no-sync", OPT_BDB_NOSYNC,
- "Disable synchronously flushing logs. This option is deprecated, use --skip-sync-bdb-logs or sync-bdb-logs=0 instead",
- // (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
+ "This option is deprecated, use --skip-sync-bdb-logs instead",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"bdb-shared-data", OPT_BDB_SHARED,
"Start Berkeley DB in multi-process mode.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
@@ -4317,10 +4533,14 @@ Disable with --skip-bdb (will save memory).",
{"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 },
+ {"completion-type", OPT_COMPLETION_TYPE, "Default completion type.",
+ (gptr*) &global_system_variables.completion_type,
+ (gptr*) &max_system_variables.completion_type, 0, GET_ULONG,
+ REQUIRED_ARG, 0, 0, 2, 0, 1, 0},
{"concurrent-insert", OPT_CONCURRENT_INSERT,
- "Use concurrent insert with MyISAM. Disable with --skip-concurrent-insert.",
+ "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0",
(gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert,
- 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ 0, GET_LONG, OPT_ARG, 1, 0, 2, 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},
@@ -4377,6 +4597,12 @@ Disable with --skip-bdb (will save memory).",
{"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure.",
(gptr*) &opt_do_pstack, (gptr*) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
+ {"engine-condition-pushdown",
+ OPT_ENGINE_CONDITION_PUSHDOWN,
+ "Push supported query conditions to the storage engine.",
+ (gptr*) &global_system_variables.engine_condition_pushdown,
+ (gptr*) &global_system_variables.engine_condition_pushdown,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0,
GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running.",
@@ -4390,6 +4616,12 @@ Disable with --skip-bdb (will save memory).",
"Set up signals usable for debugging",
(gptr*) &opt_debugging, (gptr*) &opt_debugging,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_LARGE_PAGES
+ {"large-pages", OPT_ENABLE_LARGE_PAGES, "Enable support for large pages. \
+Disable with --skip-large-pages.",
+ (gptr*) &opt_large_pages, (gptr*) &opt_large_pages, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ 0, 0, 0},
+#endif
{"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection",
(gptr*) &opt_init_connect, (gptr*) &opt_init_connect, 0, GET_STR_ALLOC,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -4405,6 +4637,11 @@ Disable with --skip-bdb (will save memory).",
Disable with --skip-innodb (will save memory).",
(gptr*) &opt_innodb, (gptr*) &opt_innodb, 0, GET_BOOL, NO_ARG, OPT_INNODB_DEFAULT, 0, 0,
0, 0, 0},
+#ifdef HAVE_INNOBASE_DB
+ {"innodb_checksums", OPT_INNODB_CHECKSUMS, "Enable InnoDB checksums validation (enabled by default). \
+Disable with --skip-innodb-checksums.", (gptr*) &innobase_use_checksums,
+ (gptr*) &innobase_use_checksums, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+#endif
{"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH,
"Path to individual files and their sizes.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -4413,9 +4650,23 @@ Disable with --skip-innodb (will save memory).",
"The common part for InnoDB table spaces.", (gptr*) &innobase_data_home_dir,
(gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
0},
+ {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, "Enable InnoDB doublewrite buffer (enabled by default). \
+Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
+ (gptr*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN,
- "Speeds up server shutdown process.", (gptr*) &innobase_fast_shutdown,
- (gptr*) &innobase_fast_shutdown, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+ "Speeds up the shutdown process of the InnoDB storage engine. Possible "
+ "values are 0, 1 (faster)"
+ /*
+ NetWare can't close unclosed files, can't automatically kill remaining
+ threads, etc, so on this OS we disable the crash-like InnoDB shutdown.
+ */
+#ifndef __NETWARE__
+ " or 2 (fastest - crash-like)"
+#endif
+ ".",
+ (gptr*) &innobase_fast_shutdown,
+ (gptr*) &innobase_fast_shutdown, 0, GET_ULONG, OPT_ARG, 1, 0,
+ IF_NETWARE(1,2), 0, 0, 0},
{"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE,
"Stores each InnoDB table to an .ibd file in the database dir.",
(gptr*) &innobase_file_per_table,
@@ -4460,12 +4711,16 @@ Disable with --skip-innodb (will save memory).",
(gptr*) &global_system_variables.innodb_table_locks,
(gptr*) &global_system_variables.innodb_table_locks,
0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+ {"innodb_support_xa", OPT_INNODB_SUPPORT_XA,
+ "Enable InnoDB support for the XA two-phase commit",
+ (gptr*) &global_system_variables.innodb_support_xa,
+ (gptr*) &global_system_variables.innodb_support_xa,
+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
#endif /* End HAVE_INNOBASE_DB */
- {"isam", OPT_ISAM, "Enable ISAM (if this version of MySQL supports it). \
-Disable with --skip-isam.",
- (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, OPT_ISAM_DEFAULT, 0, 0,
+ {"isam", OPT_ISAM, "Obsolete. ISAM storage engine is no longer supported.",
+ (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
- {"language", 'L',
+ {"language", 'L',
"Client error messages in given language. May be given as a full path.",
(gptr*) &language_ptr, (gptr*) &language_ptr, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
@@ -4477,14 +4732,27 @@ Disable with --skip-isam.",
{"log", 'l', "Log connections and queries to file.", (gptr*) &opt_logname,
(gptr*) &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"log-bin", OPT_BIN_LOG,
- "Log update queries in binary format.",
+ "Log update queries in binary format. Optional (but strongly recommended "
+ "to avoid replication problems if server's hostname changes) argument "
+ "should be the chosen location for the binary log files.",
(gptr*) &opt_bin_logname, (gptr*) &opt_bin_logname, 0, GET_STR_ALLOC,
OPT_ARG, 0, 0, 0, 0, 0, 0},
{"log-bin-index", OPT_BIN_LOG_INDEX,
"File that holds the names for last binary log files.",
(gptr*) &opt_binlog_index_name, (gptr*) &opt_binlog_index_name, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"log-error", OPT_ERROR_LOG_FILE, "Log error file.",
+ /*
+ This option starts with "log-bin" to emphasize that it is specific of
+ binary logging. Hopefully in 5.1 nobody will need it anymore, when we have
+ row-level binlog.
+ */
+ {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_ROUTINE_CREATORS,
+ "If equal to 0 (the default), then when --log-bin is used, creation of "
+ "a routine is allowed only to users having the SUPER privilege and only"
+ "if this routine may not break binary logging",
+ (gptr*) &trust_routine_creators, (gptr*) &trust_routine_creators, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"log-error", OPT_ERROR_LOG_FILE, "Error log file.",
(gptr*) &log_error_file_ptr, (gptr*) &log_error_file_ptr, 0, GET_STR,
OPT_ARG, 0, 0, 0, 0, 0, 0},
{"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
@@ -4514,13 +4782,24 @@ Disable with --skip-isam.",
"Log slow queries to this log file. Defaults logging to hostname-slow.log file. Must be enabled to activate other slow log options.",
(gptr*) &opt_slow_logname, (gptr*) &opt_slow_logname, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
+ {"log-tc", OPT_LOG_TC,
+ "Path to transaction coordinator log (used for transactions that affect "
+ "more than one storage engine, when binary log is disabled)",
+ (gptr*) &opt_tc_log_file, (gptr*) &opt_tc_log_file, 0, GET_STR,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_MMAP
+ {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.",
+ (gptr*) &opt_tc_log_size, (gptr*) &opt_tc_log_size, 0, GET_ULONG,
+ REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0L, 0, TC_LOG_PAGE_SIZE, 0},
+#endif
{"log-update", OPT_UPDATE_LOG,
- "Log updates to file.# where # is a unique number if not given.",
+ "The update log is deprecated since version 5.0, is replaced by the binary \
+log and this option justs turns on --log-bin instead.",
(gptr*) &opt_update_logname, (gptr*) &opt_update_logname, 0, GET_STR,
OPT_ARG, 0, 0, 0, 0, 0, 0},
- {"log-warnings", 'W', "Log some non-critical warnings to the error log file. Use this option twice or --log-warnings=2 if you also want 'Aborted connections' warnings.",
+ {"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_ULONG, OPT_ARG, 1, 0, ~0L,
+ (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0,
0, 0, 0},
{"low-priority-updates", OPT_LOW_PRIORITY_UPDATES,
"INSERT/DELETE/UPDATE has lower priority than selects.",
@@ -4600,9 +4879,19 @@ Disable with --skip-ndbcluster (will save memory).",
#ifdef HAVE_NDBCLUSTER_DB
{"ndb-connectstring", OPT_NDB_CONNECTSTRING,
"Connect string for ndbcluster.",
- (gptr*) &opt_ndbcluster_connectstring,
- (gptr*) &opt_ndbcluster_connectstring,
+ (gptr*) &opt_ndb_connectstring,
+ (gptr*) &opt_ndb_connectstring,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"ndb-mgmd-host", OPT_NDB_MGMD,
+ "Set host and port for ndb_mgmd. Syntax: hostname[:port]",
+ (gptr*) &opt_ndb_mgmd,
+ (gptr*) &opt_ndb_mgmd,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"ndb-nodeid", OPT_NDB_NODEID,
+ "Nodeid for this mysqlserver in the cluster.",
+ (gptr*) &opt_ndb_nodeid,
+ (gptr*) &opt_ndb_nodeid,
+ 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"ndb-autoincrement-prefetch-sz", OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
"Specify number of autoincrement values that are prefetched.",
(gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
@@ -4640,6 +4929,10 @@ Disable with --skip-ndbcluster (will save memory).",
(gptr*) &opt_ndb_optimized_node_selection,
(gptr*) &opt_ndb_optimized_node_selection,
0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+ { "ndb-cache-check-time", OPT_NDB_CACHE_CHECK_TIME,
+ "A dedicated thread is created to, at the given millisecons interval, invalidate the query cache if another MySQL server in the cluster has changed the data in the database.",
+ (gptr*) &opt_ndb_cache_check_time, (gptr*) &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG,
+ 0, 0, LONG_TIMEOUT, 0, 1, 0},
#endif
{"new", 'n', "Use very new possible 'unsafe' functions.",
(gptr*) &global_system_variables.new_mode,
@@ -4659,6 +4952,10 @@ Disable with --skip-ndbcluster (will save memory).",
"Only use one thread (for debugging under Linux).", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"old-style-user-limits", OPT_OLD_STYLE_USER_LIMITS,
+ "Enable old-style user limits (before 5.0.3 user resources were counted per each user+host vs. per account)",
+ (gptr*) &opt_old_style_user_limits, (gptr*) &opt_old_style_user_limits,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"pid-file", OPT_PID_FILE, "Pid file used by safe_mysqld.",
(gptr*) &pidfile_name_ptr, (gptr*) &pidfile_name_ptr, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -4822,9 +5119,9 @@ replicating a LOAD DATA INFILE command.",
0},
#endif /* HAVE_REPLICATION */
{"sql-bin-update-same", OPT_SQL_BIN_UPDATE_SAME,
- "If set, setting SQL_LOG_BIN to a value will automatically set SQL_LOG_UPDATE to the same value and vice versa.",
- (gptr*) &opt_sql_bin_update, (gptr*) &opt_sql_bin_update, 0, GET_BOOL,
- NO_ARG, 0, 0, 0, 0, 0, 0},
+ "The update log is deprecated since version 5.0, is replaced by the binary \
+log and this option does nothing anymore.",
+ 0, 0, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"sql-mode", OPT_SQL_MODE,
"Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.",
(gptr*) &sql_mode_str, (gptr*) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0,
@@ -4840,13 +5137,21 @@ replicating a LOAD DATA INFILE command.",
{"symbolic-links", 's', "Enable symbolic link support.",
(gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
IF_PURIFY(0,1), 0, 0, 0, 0, 0},
+ {"tc-heuristic-recover", OPT_TC_HEURISTIC_RECOVER,
+ "Decision to use in heuristic recover process. Possible values are COMMIT or ROLLBACK",
+ (gptr*) &opt_tc_heuristic_recover, (gptr*) &opt_tc_heuristic_recover,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"temp-pool", OPT_TEMP_POOL,
"Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
(gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
+ {"timed_mutexes", OPT_TIMED_MUTEXES,
+ "Specify whether to time mutexes (only InnoDB mutexes are currently supported)",
+ (gptr*) &timed_mutexes, (gptr*) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
+ 0, 0, 0, 0, 0},
{"tmpdir", 't',
"Path for temporary files. Several paths may be specified, separated by a "
-#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
+#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
"semicolon (;)"
#else
"colon (:)"
@@ -4906,12 +5211,6 @@ replicating a LOAD DATA INFILE command.",
"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
{ "date_format", OPT_DATE_FORMAT,
"The DATE format (For future).",
(gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE],
@@ -4993,6 +5292,12 @@ replicating a LOAD DATA INFILE command.",
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
(gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0,
GET_LONG, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, ~0L, 0, 1024*1024L, 0},
+ {"innodb_concurrency_tickets", OPT_INNODB_CONCURRENCY_TICKETS,
+ "Number of times a thread is allowed to enter InnoDB within the same \
+ SQL query after it has once got the ticket",
+ (gptr*) &srv_n_free_tickets_to_enter,
+ (gptr*) &srv_n_free_tickets_to_enter,
+ 0, GET_LONG, REQUIRED_ARG, 500L, 1L, ~0L, 0, 1L, 0},
{"innodb_file_io_threads", OPT_INNODB_FILE_IO_THREADS,
"Number of file I/O threads in InnoDB.", (gptr*) &innobase_file_io_threads,
(gptr*) &innobase_file_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 4, 64, 0,
@@ -5026,30 +5331,25 @@ replicating a LOAD DATA INFILE command.",
"How many files at the maximum InnoDB keeps open at the same time.",
(gptr*) &innobase_open_files, (gptr*) &innobase_open_files, 0,
GET_LONG, REQUIRED_ARG, 300L, 10L, ~0L, 0, 1L, 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_sync_spin_loops", OPT_INNODB_SYNC_SPIN_LOOPS,
+ "Count of spin-loop rounds in InnoDB mutexes",
+ (gptr*) &srv_n_spin_wait_rounds,
+ (gptr*) &srv_n_spin_wait_rounds,
+ 0, GET_LONG, REQUIRED_ARG, 20L, 0L, ~0L, 0, 1L, 0},
{"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
"Helps in performance tuning in heavily concurrent environments.",
- (gptr*) &innobase_thread_concurrency, (gptr*) &innobase_thread_concurrency,
- 0, GET_LONG, REQUIRED_ARG, 8, 1, 1000, 0, 1, 0},
+ (gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency,
+ 0, GET_LONG, REQUIRED_ARG, 20, 1, 1000, 0, 1, 0},
+ {"innodb_commit_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
+ "Helps in performance tuning in heavily concurrent environments.",
+ (gptr*) &srv_commit_concurrency, (gptr*) &srv_commit_concurrency,
+ 0, GET_LONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0},
+ {"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY,
+ "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0"
+ " disable a sleep",
+ (gptr*) &srv_thread_sleep_delay,
+ (gptr*) &srv_thread_sleep_delay,
+ 0, GET_LONG, REQUIRED_ARG, 10000L, 0L, ~0L, 0, 1L, 0},
#endif /* HAVE_INNOBASE_DB */
{"interactive_timeout", OPT_INTERACTIVE_TIMEOUT,
"The number of seconds the server waits for activity on an interactive connection before closing it.",
@@ -5067,7 +5367,7 @@ replicating a LOAD DATA INFILE command.",
(gptr*) &dflt_key_cache_var.param_buff_size,
(gptr*) 0,
0, (GET_ULL | GET_ASK_ADDR),
- REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, UINT_MAX32, MALLOC_OVERHEAD,
+ REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~(ulong) 0, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
"This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache",
@@ -5171,12 +5471,17 @@ The minimum value for this variable is 4096.",
REQUIRED_ARG, 32, 1, ~0L, 0, 1, 0},
{"max_user_connections", OPT_MAX_USER_CONNECTIONS,
"The maximum number of active connections for a single user (0 = no limit).",
- (gptr*) &max_user_connections, (gptr*) &max_user_connections, 0, GET_ULONG,
- REQUIRED_ARG, 0, 1, ~0L, 0, 1, 0},
+ (gptr*) &max_user_connections, (gptr*) &max_user_connections, 0, GET_UINT,
+ REQUIRED_ARG, 0, 1, ~0, 0, 1, 0},
{"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
"After this many write locks, allow some read locks to run in between.",
(gptr*) &max_write_lock_count, (gptr*) &max_write_lock_count, 0, GET_ULONG,
REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0},
+ {"multi_range_count", OPT_MULTI_RANGE_COUNT,
+ "Number of key ranges to request at once.",
+ (gptr*) &global_system_variables.multi_range_count,
+ (gptr*) &max_system_variables.multi_range_count, 0,
+ GET_ULONG, REQUIRED_ARG, 256, 1, ~0L, 0, 1, 0},
{"myisam_block_size", OPT_MYISAM_BLOCK_SIZE,
"Block size to be used for MyISAM index pages.",
(gptr*) &opt_myisam_block_size,
@@ -5187,9 +5492,9 @@ The minimum value for this variable is 4096.",
"Default pointer size to be used for MyISAM tables.",
(gptr*) &myisam_data_pointer_size,
(gptr*) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG,
- 4, 2, 7, 0, 1, 0},
+ 6, 2, 7, 0, 1, 0},
{"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
- "Used to help MySQL to decide when to use the slow but safe key cache index create method.",
+ "Deprecated option",
(gptr*) &global_system_variables.myisam_max_extra_sort_file_size,
(gptr*) &max_system_variables.myisam_max_extra_sort_file_size,
0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH,
@@ -5239,6 +5544,16 @@ The minimum value for this variable is 4096.",
"If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.",
(gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, OS_FILE_LIMIT, 0, 1, 0},
+ {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL,
+ "Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows.",
+ (gptr*) &global_system_variables.optimizer_prune_level,
+ (gptr*) &max_system_variables.optimizer_prune_level,
+ 0, GET_ULONG, OPT_ARG, 1, 0, 1, 0, 1, 0},
+ {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH,
+ "Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Smaller values than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value; if set to MAX_TABLES+2, the optimizer will switch to the original find_best (used for testing/comparison).",
+ (gptr*) &global_system_variables.optimizer_search_depth,
+ (gptr*) &max_system_variables.optimizer_search_depth,
+ 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0},
{"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
"The size of the buffer that is allocated when preloading indexes",
(gptr*) &global_system_variables.preload_buff_size,
@@ -5302,6 +5617,11 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.read_rnd_buff_size, 0,
GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD,
~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+ {"div_precision_increment", OPT_DIV_PRECINCREMENT,
+ "Precision of the result of '/' operator will be increased on that value.",
+ (gptr*) &global_system_variables.div_precincrement,
+ (gptr*) &max_system_variables.div_precincrement, 0, GET_ULONG,
+ REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
{"record_buffer", OPT_RECORD_BUFFER,
"Alias for read_buffer_size",
(gptr*) &global_system_variables.read_buff_size,
@@ -5332,7 +5652,7 @@ The minimum value for this variable is 4096.",
"it failed with a deadlock or elapsed lock wait timeout, "
"before giving up and stopping.",
(gptr*) &slave_trans_retries, (gptr*) &slave_trans_retries, 0,
- GET_ULONG, REQUIRED_ARG, 0L, 0L, (longlong) ULONG_MAX, 0, 1, 0},
+ GET_ULONG, REQUIRED_ARG, 10L, 0L, (longlong) ULONG_MAX, 0, 1, 0},
#endif /* HAVE_REPLICATION */
{"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
"If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.",
@@ -5346,40 +5666,44 @@ The minimum value for this variable is 4096.",
1, 0},
#ifdef HAVE_BERKELEY_DB
{"sync-bdb-logs", OPT_BDB_SYNC,
- "Synchronously flush logs. Enabled by default",
+ "Synchronously flush Berkeley DB logs. Enabled by default",
(gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
NO_ARG, 1, 0, 0, 0, 0, 0},
#endif /* HAVE_BERKELEY_DB */
{"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},
-#ifdef DOES_NOTHING_YET
+ "Synchronously flush binary log to disk after every #th event. "
+ "Use 0 (default) to disable synchronous flushing.",
+ (gptr*) &sync_binlog_period, (gptr*) &sync_binlog_period, 0, GET_ULONG,
+ REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0},
+ {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.",
+ (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
+ 0, 0, 0, 0},
+#ifdef HAVE_REPLICATION
{"sync-replication", OPT_SYNC_REPLICATION,
- "Enable synchronous replication",
+ "Enable synchronous replication.",
(gptr*) &global_system_variables.sync_replication,
(gptr*) &global_system_variables.sync_replication,
0, GET_ULONG, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
{"sync-replication-slave-id", OPT_SYNC_REPLICATION_SLAVE_ID,
- "Synchronous replication is wished for this slave",
+ "Synchronous replication is wished for this slave.",
(gptr*) &global_system_variables.sync_replication_slave_id,
(gptr*) &global_system_variables.sync_replication_slave_id,
0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0},
{"sync-replication-timeout", OPT_SYNC_REPLICATION_TIMEOUT,
- "Synchronous replication timeout",
+ "Synchronous replication timeout.",
(gptr*) &global_system_variables.sync_replication_timeout,
(gptr*) &global_system_variables.sync_replication_timeout,
0, GET_ULONG, REQUIRED_ARG, 10, 0, ~0L, 0, 1, 0},
-#endif
- {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default",
- (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
- 0, 0, 0, 0},
+#endif /* HAVE_REPLICATION */
{"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,
0, 1, 0},
+ {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT, "Timeout in "
+ "seconds to wait for a table level lock before returning an error. Used"
+ " only if the connection has active cursors.",
+ (gptr*) &table_lock_wait_timeout, (gptr*) &table_lock_wait_timeout,
+ 0, GET_ULONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
{"thread_cache_size", OPT_THREAD_CACHE_SIZE,
"How many threads we should keep in a cache for reuse.",
(gptr*) &thread_cache_size, (gptr*) &thread_cache_size, 0, GET_ULONG,
@@ -5412,6 +5736,11 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.trans_prealloc_size,
(gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
+ {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT,
+ "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).",
+ (gptr*) &global_system_variables.updatable_views_with_limit,
+ (gptr*) &max_system_variables.updatable_views_with_limit,
+ 0, GET_ULONG, REQUIRED_ARG, 1, 0, 1, 0, 1, 0},
{"wait_timeout", OPT_WAIT_TIMEOUT,
"The number of seconds the server waits for activity on a connection before closing it.",
(gptr*) &global_system_variables.net_wait_timeout,
@@ -5427,172 +5756,177 @@ struct show_var_st status_vars[]= {
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
{"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG},
{"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG},
- {"Bytes_received", (char*) &bytes_received, SHOW_LONG},
- {"Bytes_sent", (char*) &bytes_sent, SHOW_LONG},
- {"Com_admin_commands", (char*) &com_other, SHOW_LONG},
- {"Com_alter_db", (char*) (com_stat+(uint) SQLCOM_ALTER_DB),SHOW_LONG},
- {"Com_alter_table", (char*) (com_stat+(uint) SQLCOM_ALTER_TABLE),SHOW_LONG},
- {"Com_analyze", (char*) (com_stat+(uint) SQLCOM_ANALYZE),SHOW_LONG},
- {"Com_backup_table", (char*) (com_stat+(uint) SQLCOM_BACKUP_TABLE),SHOW_LONG},
- {"Com_begin", (char*) (com_stat+(uint) SQLCOM_BEGIN),SHOW_LONG},
- {"Com_change_db", (char*) (com_stat+(uint) SQLCOM_CHANGE_DB),SHOW_LONG},
- {"Com_change_master", (char*) (com_stat+(uint) SQLCOM_CHANGE_MASTER),SHOW_LONG},
- {"Com_check", (char*) (com_stat+(uint) SQLCOM_CHECK),SHOW_LONG},
- {"Com_checksum", (char*) (com_stat+(uint) SQLCOM_CHECKSUM),SHOW_LONG},
- {"Com_commit", (char*) (com_stat+(uint) SQLCOM_COMMIT),SHOW_LONG},
- {"Com_create_db", (char*) (com_stat+(uint) SQLCOM_CREATE_DB),SHOW_LONG},
- {"Com_create_function", (char*) (com_stat+(uint) SQLCOM_CREATE_FUNCTION),SHOW_LONG},
- {"Com_create_index", (char*) (com_stat+(uint) SQLCOM_CREATE_INDEX),SHOW_LONG},
- {"Com_create_table", (char*) (com_stat+(uint) SQLCOM_CREATE_TABLE),SHOW_LONG},
- {"Com_dealloc_sql", (char*) (com_stat+(uint)
- SQLCOM_DEALLOCATE_PREPARE), SHOW_LONG},
- {"Com_delete", (char*) (com_stat+(uint) SQLCOM_DELETE),SHOW_LONG},
- {"Com_delete_multi", (char*) (com_stat+(uint) SQLCOM_DELETE_MULTI),SHOW_LONG},
- {"Com_do", (char*) (com_stat+(uint) SQLCOM_DO),SHOW_LONG},
- {"Com_drop_db", (char*) (com_stat+(uint) SQLCOM_DROP_DB),SHOW_LONG},
- {"Com_drop_function", (char*) (com_stat+(uint) SQLCOM_DROP_FUNCTION),SHOW_LONG},
- {"Com_drop_index", (char*) (com_stat+(uint) SQLCOM_DROP_INDEX),SHOW_LONG},
- {"Com_drop_table", (char*) (com_stat+(uint) SQLCOM_DROP_TABLE),SHOW_LONG},
- {"Com_drop_user", (char*) (com_stat+(uint) SQLCOM_DROP_USER),SHOW_LONG},
- {"Com_execute_sql", (char*) (com_stat+(uint) SQLCOM_EXECUTE),
- SHOW_LONG},
- {"Com_flush", (char*) (com_stat+(uint) SQLCOM_FLUSH),SHOW_LONG},
- {"Com_grant", (char*) (com_stat+(uint) SQLCOM_GRANT),SHOW_LONG},
- {"Com_ha_close", (char*) (com_stat+(uint) SQLCOM_HA_CLOSE),SHOW_LONG},
- {"Com_ha_open", (char*) (com_stat+(uint) SQLCOM_HA_OPEN),SHOW_LONG},
- {"Com_ha_read", (char*) (com_stat+(uint) SQLCOM_HA_READ),SHOW_LONG},
- {"Com_help", (char*) (com_stat+(uint) SQLCOM_HELP),SHOW_LONG},
- {"Com_insert", (char*) (com_stat+(uint) SQLCOM_INSERT),SHOW_LONG},
- {"Com_insert_select", (char*) (com_stat+(uint) SQLCOM_INSERT_SELECT),SHOW_LONG},
- {"Com_kill", (char*) (com_stat+(uint) SQLCOM_KILL),SHOW_LONG},
- {"Com_load", (char*) (com_stat+(uint) SQLCOM_LOAD),SHOW_LONG},
- {"Com_load_master_data", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_DATA),SHOW_LONG},
- {"Com_load_master_table", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_TABLE),SHOW_LONG},
- {"Com_lock_tables", (char*) (com_stat+(uint) SQLCOM_LOCK_TABLES),SHOW_LONG},
- {"Com_optimize", (char*) (com_stat+(uint) SQLCOM_OPTIMIZE),SHOW_LONG},
- {"Com_preload_keys", (char*) (com_stat+(uint) SQLCOM_PRELOAD_KEYS),SHOW_LONG},
- {"Com_prepare_sql", (char*) (com_stat+(uint) SQLCOM_PREPARE),
- SHOW_LONG},
- {"Com_purge", (char*) (com_stat+(uint) SQLCOM_PURGE),SHOW_LONG},
- {"Com_purge_before_date", (char*) (com_stat+(uint) SQLCOM_PURGE_BEFORE),SHOW_LONG},
- {"Com_rename_table", (char*) (com_stat+(uint) SQLCOM_RENAME_TABLE),SHOW_LONG},
- {"Com_repair", (char*) (com_stat+(uint) SQLCOM_REPAIR),SHOW_LONG},
- {"Com_replace", (char*) (com_stat+(uint) SQLCOM_REPLACE),SHOW_LONG},
- {"Com_replace_select", (char*) (com_stat+(uint) SQLCOM_REPLACE_SELECT),SHOW_LONG},
- {"Com_reset", (char*) (com_stat+(uint) SQLCOM_RESET),SHOW_LONG},
- {"Com_restore_table", (char*) (com_stat+(uint) SQLCOM_RESTORE_TABLE),SHOW_LONG},
- {"Com_revoke", (char*) (com_stat+(uint) SQLCOM_REVOKE),SHOW_LONG},
- {"Com_revoke_all", (char*) (com_stat+(uint) SQLCOM_REVOKE_ALL),SHOW_LONG},
- {"Com_rollback", (char*) (com_stat+(uint) SQLCOM_ROLLBACK),SHOW_LONG},
- {"Com_savepoint", (char*) (com_stat+(uint) SQLCOM_SAVEPOINT),SHOW_LONG},
- {"Com_select", (char*) (com_stat+(uint) SQLCOM_SELECT),SHOW_LONG},
- {"Com_set_option", (char*) (com_stat+(uint) SQLCOM_SET_OPTION),SHOW_LONG},
- {"Com_show_binlog_events", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOG_EVENTS),SHOW_LONG},
- {"Com_show_binlogs", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOGS),SHOW_LONG},
- {"Com_show_charsets", (char*) (com_stat+(uint) SQLCOM_SHOW_CHARSETS),SHOW_LONG},
- {"Com_show_collations", (char*) (com_stat+(uint) SQLCOM_SHOW_COLLATIONS),SHOW_LONG},
- {"Com_show_column_types", (char*) (com_stat+(uint) SQLCOM_SHOW_COLUMN_TYPES),SHOW_LONG},
- {"Com_show_create_db", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE_DB),SHOW_LONG},
- {"Com_show_create_table", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG},
- {"Com_show_databases", (char*) (com_stat+(uint) SQLCOM_SHOW_DATABASES),SHOW_LONG},
- {"Com_show_errors", (char*) (com_stat+(uint) SQLCOM_SHOW_ERRORS),SHOW_LONG},
- {"Com_show_fields", (char*) (com_stat+(uint) SQLCOM_SHOW_FIELDS),SHOW_LONG},
- {"Com_show_grants", (char*) (com_stat+(uint) SQLCOM_SHOW_GRANTS),SHOW_LONG},
- {"Com_show_innodb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_INNODB_STATUS),SHOW_LONG},
- {"Com_show_keys", (char*) (com_stat+(uint) SQLCOM_SHOW_KEYS),SHOW_LONG},
- {"Com_show_logs", (char*) (com_stat+(uint) SQLCOM_SHOW_LOGS),SHOW_LONG},
- {"Com_show_master_status", (char*) (com_stat+(uint) SQLCOM_SHOW_MASTER_STAT),SHOW_LONG},
- {"Com_show_new_master", (char*) (com_stat+(uint) SQLCOM_SHOW_NEW_MASTER),SHOW_LONG},
- {"Com_show_open_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_OPEN_TABLES),SHOW_LONG},
- {"Com_show_privileges", (char*) (com_stat+(uint) SQLCOM_SHOW_PRIVILEGES),SHOW_LONG},
- {"Com_show_processlist", (char*) (com_stat+(uint) SQLCOM_SHOW_PROCESSLIST),SHOW_LONG},
- {"Com_show_slave_hosts", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_HOSTS),SHOW_LONG},
- {"Com_show_slave_status", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG},
- {"Com_show_status", (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG},
- {"Com_show_storage_engines", (char*) (com_stat+(uint) SQLCOM_SHOW_STORAGE_ENGINES),SHOW_LONG},
- {"Com_show_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG},
- {"Com_show_variables", (char*) (com_stat+(uint) SQLCOM_SHOW_VARIABLES),SHOW_LONG},
- {"Com_show_warnings", (char*) (com_stat+(uint) SQLCOM_SHOW_WARNS),SHOW_LONG},
- {"Com_slave_start", (char*) (com_stat+(uint) SQLCOM_SLAVE_START),SHOW_LONG},
- {"Com_slave_stop", (char*) (com_stat+(uint) SQLCOM_SLAVE_STOP),SHOW_LONG},
- {"Com_stmt_close", (char*) &com_stmt_close, SHOW_LONG},
- {"Com_stmt_execute", (char*) &com_stmt_execute, SHOW_LONG},
- {"Com_stmt_prepare", (char*) &com_stmt_prepare, SHOW_LONG},
- {"Com_stmt_reset", (char*) &com_stmt_reset, SHOW_LONG},
- {"Com_stmt_send_long_data", (char*) &com_stmt_send_long_data, SHOW_LONG},
- {"Com_truncate", (char*) (com_stat+(uint) SQLCOM_TRUNCATE),SHOW_LONG},
- {"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},
+ {"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONG_STATUS},
+ {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONG_STATUS},
+ {"Com_admin_commands", (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS},
+ {"Com_alter_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS},
+ {"Com_alter_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS},
+ {"Com_analyze", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS},
+ {"Com_backup_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BACKUP_TABLE]), SHOW_LONG_STATUS},
+ {"Com_begin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS},
+ {"Com_change_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS},
+ {"Com_change_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS},
+ {"Com_check", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS},
+ {"Com_checksum", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS},
+ {"Com_commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS},
+ {"Com_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS},
+ {"Com_create_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS},
+ {"Com_create_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
+ {"Com_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
+ {"Com_dealloc_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS},
+ {"Com_delete", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS},
+ {"Com_delete_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS},
+ {"Com_do", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS},
+ {"Com_drop_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS},
+ {"Com_drop_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS},
+ {"Com_drop_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
+ {"Com_drop_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
+ {"Com_drop_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS},
+ {"Com_execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
+ {"Com_flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
+ {"Com_grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
+ {"Com_ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS},
+ {"Com_ha_open", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS},
+ {"Com_ha_read", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS},
+ {"Com_help", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS},
+ {"Com_insert", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS},
+ {"Com_insert_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS},
+ {"Com_kill", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS},
+ {"Com_load", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS},
+ {"Com_load_master_data", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_DATA]), SHOW_LONG_STATUS},
+ {"Com_load_master_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_TABLE]), SHOW_LONG_STATUS},
+ {"Com_lock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS},
+ {"Com_optimize", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS},
+ {"Com_preload_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS},
+ {"Com_prepare_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS},
+ {"Com_purge", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS},
+ {"Com_purge_before_date", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS},
+ {"Com_rename_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS},
+ {"Com_repair", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS},
+ {"Com_replace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
+ {"Com_replace_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
+ {"Com_reset", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS},
+ {"Com_restore_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESTORE_TABLE]), SHOW_LONG_STATUS},
+ {"Com_revoke", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS},
+ {"Com_revoke_all", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS},
+ {"Com_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS},
+ {"Com_savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
+ {"Com_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS},
+ {"Com_set_option", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
+ {"Com_show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
+ {"Com_show_binlogs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS},
+ {"Com_show_charsets", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS},
+ {"Com_show_collations", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS},
+ {"Com_show_column_types", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLUMN_TYPES]), SHOW_LONG_STATUS},
+ {"Com_show_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
+ {"Com_show_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
+ {"Com_show_databases", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS},
+ {"Com_show_errors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
+ {"Com_show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
+ {"Com_show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
+ {"Com_show_innodb_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INNODB_STATUS]), SHOW_LONG_STATUS},
+ {"Com_show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
+ {"Com_show_logs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_LOGS]), SHOW_LONG_STATUS},
+ {"Com_show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
+ {"Com_show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
+ {"Com_show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
+ {"Com_show_privileges", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},
+ {"Com_show_processlist", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
+ {"Com_show_slave_hosts", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
+ {"Com_show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
+ {"Com_show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
+ {"Com_show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
+ {"Com_show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
+ {"Com_show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
+ {"Com_show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
+ {"Com_show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
+ {"Com_slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
+ {"Com_slave_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS},
+ {"Com_stmt_close", (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS},
+ {"Com_stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS},
+ {"Com_stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS},
+ {"Com_stmt_prepare", (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
+ {"Com_stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
+ {"Com_stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
+ {"Com_truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
+ {"Com_unlock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
+ {"Com_update", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
+ {"Com_update_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS},
+ {"Com_xa_commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),SHOW_LONG_STATUS},
+ {"Com_xa_end", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),SHOW_LONG_STATUS},
+ {"Com_xa_prepare", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),SHOW_LONG_STATUS},
+ {"Com_xa_recover", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS},
+ {"Com_xa_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS},
+ {"Com_xa_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS},
{"Connections", (char*) &thread_id, SHOW_LONG_CONST},
- {"Created_tmp_disk_tables", (char*) &created_tmp_disk_tables,SHOW_LONG},
+ {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
{"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG},
- {"Created_tmp_tables", (char*) &created_tmp_tables, SHOW_LONG},
+ {"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
{"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG},
{"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_CONST},
{"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG},
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_CONST},
- {"Handler_commit", (char*) &ha_commit_count, SHOW_LONG},
- {"Handler_delete", (char*) &ha_delete_count, SHOW_LONG},
- {"Handler_discover", (char*) &ha_discover_count, SHOW_LONG},
- {"Handler_read_first", (char*) &ha_read_first_count, SHOW_LONG},
- {"Handler_read_key", (char*) &ha_read_key_count, SHOW_LONG},
- {"Handler_read_next", (char*) &ha_read_next_count, SHOW_LONG},
- {"Handler_read_prev", (char*) &ha_read_prev_count, SHOW_LONG},
- {"Handler_read_rnd", (char*) &ha_read_rnd_count, SHOW_LONG},
- {"Handler_read_rnd_next", (char*) &ha_read_rnd_next_count, SHOW_LONG},
- {"Handler_rollback", (char*) &ha_rollback_count, SHOW_LONG},
- {"Handler_update", (char*) &ha_update_count, SHOW_LONG},
- {"Handler_write", (char*) &ha_write_count, SHOW_LONG},
- {"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.global_blocks_changed,
- SHOW_KEY_CACHE_LONG},
- {"Key_blocks_unused", (char*) &dflt_key_cache_var.blocks_unused,
- SHOW_KEY_CACHE_CONST_LONG},
- {"Key_blocks_used", (char*) &dflt_key_cache_var.blocks_used,
- SHOW_KEY_CACHE_CONST_LONG},
- {"Key_read_requests", (char*) &dflt_key_cache_var.global_cache_r_requests,
- SHOW_KEY_CACHE_LONGLONG},
- {"Key_reads", (char*) &dflt_key_cache_var.global_cache_read,
- SHOW_KEY_CACHE_LONGLONG},
- {"Key_write_requests", (char*) &dflt_key_cache_var.global_cache_w_requests,
- SHOW_KEY_CACHE_LONGLONG},
- {"Key_writes", (char*) &dflt_key_cache_var.global_cache_write,
- SHOW_KEY_CACHE_LONGLONG},
+ {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
+ {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
+ {"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS},
+ {"Handler_prepare", (char*) offsetof(STATUS_VAR, ha_prepare_count), SHOW_LONG_STATUS},
+ {"Handler_read_first", (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS},
+ {"Handler_read_key", (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS},
+ {"Handler_read_next", (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONG_STATUS},
+ {"Handler_read_prev", (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONG_STATUS},
+ {"Handler_read_rnd", (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS},
+ {"Handler_read_rnd_next", (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONG_STATUS},
+ {"Handler_rollback", (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONG_STATUS},
+ {"Handler_savepoint", (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONG_STATUS},
+ {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONG_STATUS},
+ {"Handler_update", (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
+ {"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
+#ifdef HAVE_INNOBASE_DB
+ {"Innodb_", (char*) &innodb_status_variables, SHOW_VARS},
+#endif /*HAVE_INNOBASE_DB*/
+ {"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.global_blocks_changed, SHOW_KEY_CACHE_LONG},
+ {"Key_blocks_unused", (char*) &dflt_key_cache_var.blocks_unused, SHOW_KEY_CACHE_CONST_LONG},
+ {"Key_blocks_used", (char*) &dflt_key_cache_var.blocks_used, SHOW_KEY_CACHE_CONST_LONG},
+ {"Key_read_requests", (char*) &dflt_key_cache_var.global_cache_r_requests, SHOW_KEY_CACHE_LONGLONG},
+ {"Key_reads", (char*) &dflt_key_cache_var.global_cache_read, SHOW_KEY_CACHE_LONGLONG},
+ {"Key_write_requests", (char*) &dflt_key_cache_var.global_cache_w_requests, SHOW_KEY_CACHE_LONGLONG},
+ {"Key_writes", (char*) &dflt_key_cache_var.global_cache_write, SHOW_KEY_CACHE_LONGLONG},
+ {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
+#ifdef HAVE_NDBCLUSTER_DB
+ {"Ndb_", (char*) &ndb_status_variables, SHOW_VARS},
+#endif /*HAVE_NDBCLUSTER_DB*/
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
{"Open_streams", (char*) &my_stream_opened, SHOW_LONG_CONST},
{"Open_tables", (char*) 0, SHOW_OPENTABLES},
- {"Opened_tables", (char*) &opened_tables, SHOW_LONG},
+ {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
#ifdef HAVE_QUERY_CACHE
- {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks,
- SHOW_LONG_CONST},
- {"Qcache_free_memory", (char*) &query_cache.free_memory,
- SHOW_LONG_CONST},
+ {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_CONST},
+ {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_CONST},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG},
{"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
- {"Qcache_total_blocks", (char*) &query_cache.total_blocks,
- SHOW_LONG_CONST},
+ {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_CONST},
#endif /*HAVE_QUERY_CACHE*/
{"Questions", (char*) 0, SHOW_QUESTION},
{"Rpl_status", (char*) 0, SHOW_RPL_STATUS},
- {"Select_full_join", (char*) &select_full_join_count, SHOW_LONG},
- {"Select_full_range_join", (char*) &select_full_range_join_count, SHOW_LONG},
- {"Select_range", (char*) &select_range_count, SHOW_LONG},
- {"Select_range_check", (char*) &select_range_check_count, SHOW_LONG},
- {"Select_scan", (char*) &select_scan_count, SHOW_LONG},
+ {"Select_full_join", (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS},
+ {"Select_full_range_join", (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS},
+ {"Select_range", (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONG_STATUS},
+ {"Select_range_check", (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONG_STATUS},
+ {"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS},
{"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_LONG},
{"Slave_retried_transactions",(char*) 0, SHOW_SLAVE_RETRIED_TRANS},
{"Slave_running", (char*) 0, SHOW_SLAVE_RUNNING},
{"Slow_launch_threads", (char*) &slow_launch_threads, SHOW_LONG},
- {"Slow_queries", (char*) &long_query_count, SHOW_LONG},
- {"Sort_merge_passes", (char*) &filesort_merge_passes, SHOW_LONG},
- {"Sort_range", (char*) &filesort_range_count, SHOW_LONG},
- {"Sort_rows", (char*) &filesort_rows, SHOW_LONG},
- {"Sort_scan", (char*) &filesort_scan_count, SHOW_LONG},
+ {"Slow_queries", (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
+ {"Sort_merge_passes", (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONG_STATUS},
+ {"Sort_range", (char*) offsetof(STATUS_VAR, filesort_range_count), SHOW_LONG_STATUS},
+ {"Sort_rows", (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONG_STATUS},
+ {"Sort_scan", (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS},
#ifdef HAVE_OPENSSL
{"Ssl_accept_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE},
{"Ssl_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT},
@@ -5620,6 +5954,11 @@ struct show_var_st status_vars[]= {
#endif /* HAVE_OPENSSL */
{"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG},
{"Table_locks_waited", (char*) &locks_waited, SHOW_LONG},
+#ifdef HAVE_MMAP
+ {"Tc_log_max_pages_used", (char*) &tc_log_max_pages_used, SHOW_LONG},
+ {"Tc_log_page_size", (char*) &tc_log_page_size, SHOW_LONG},
+ {"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG},
+#endif
{"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_CONST},
{"Threads_connected", (char*) &thread_count, SHOW_INT_CONST},
{"Threads_created", (char*) &thread_created, SHOW_LONG_CONST},
@@ -5704,9 +6043,11 @@ static void mysql_init_variables(void)
/* Things reset to zero */
opt_skip_slave_start= opt_reckless_slave = 0;
mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
- opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0;
+ opt_log= opt_update_log= opt_slow_log= 0;
+ opt_bin_log= 0;
opt_disable_networking= opt_skip_show_db=0;
- opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname=0;
+ opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
+ opt_tc_log_file= (char *)"tc.log"; // no hostname in tc_log file name !
opt_secure_auth= 0;
opt_bootstrap= opt_myisam_log= 0;
mqh_used= 0;
@@ -5717,27 +6058,23 @@ static void mysql_init_variables(void)
test_flags= select_errors= dropping_tables= ha_open_options=0;
thread_count= thread_running= kill_cached_threads= wake_thread=0;
slave_open_temp_tables= 0;
- com_other= 0;
cached_thread_count= 0;
- bytes_sent= bytes_received= 0;
opt_endinfo= using_udf_functions= 0;
opt_using_transactions= using_update_log= 0;
abort_loop= select_thread_in_use= signal_thread_in_use= 0;
ready_to_exit= shutdown_in_progress= grant_option= 0;
- long_query_count= aborted_threads= aborted_connects= 0;
+ aborted_threads= aborted_connects= 0;
delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
delayed_insert_errors= thread_created= 0;
- filesort_rows= filesort_range_count= filesort_scan_count= 0;
- filesort_merge_passes= select_range_check_count= select_range_count= 0;
- select_scan_count= select_full_range_join_count= select_full_join_count= 0;
- specialflag= opened_tables= created_tmp_tables= created_tmp_disk_tables= 0;
+ specialflag= 0;
binlog_cache_use= binlog_cache_disk_use= 0;
max_used_connections= slow_launch_threads = 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;
bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
- bzero((gptr) &com_stat, sizeof(com_stat));
+ bzero((char *) &global_status_var, sizeof(global_status_var));
+ opt_large_pages= 0;
key_map_full.set_all();
/* Character sets */
@@ -5838,11 +6175,7 @@ static void mysql_init_variables(void)
#else
have_innodb=SHOW_OPTION_NO;
#endif
-#ifdef HAVE_ISAM
- have_isam=SHOW_OPTION_YES;
-#else
have_isam=SHOW_OPTION_NO;
-#endif
#ifdef HAVE_EXAMPLE_DB
have_example_db= SHOW_OPTION_YES;
#else
@@ -5858,6 +6191,11 @@ static void mysql_init_variables(void)
#else
have_blackhole_db= SHOW_OPTION_NO;
#endif
+#ifdef HAVE_FEDERATED_DB
+ have_federated_db= SHOW_OPTION_YES;
+#else
+ have_federated_db= SHOW_OPTION_NO;
+#endif
#ifdef HAVE_CSV_DB
have_csv_db= SHOW_OPTION_YES;
#else
@@ -5939,7 +6277,7 @@ static void mysql_init_variables(void)
}
-extern "C" my_bool
+static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
@@ -6014,7 +6352,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_update_log=1;
break;
case (int) OPT_BIN_LOG:
- opt_bin_log=1;
+ opt_bin_log= test(argument != disabled_my_option);
break;
case (int) OPT_ERROR_LOG_FILE:
opt_error_log= 1;
@@ -6149,6 +6487,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
myisam_concurrent_insert=0;
myisam_recover_options= HA_RECOVER_NONE;
+ sp_automatic_privileges=0;
my_use_symdir=0;
ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
#ifdef HAVE_QUERY_CACHE
@@ -6235,9 +6574,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_error_log= 0; // Force logs to stdout
break;
case (int) OPT_FLUSH:
-#ifdef HAVE_ISAM
- nisam_flush=1;
-#endif
myisam_flush=1;
flush_time=0; // No auto flush
break;
@@ -6322,7 +6658,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *end;
uint length= strlen(argument);
long value= my_strntol(&my_charset_latin1, argument, length, 10, &end, &err);
- if (test_if_int(argument,(uint) length, end, &my_charset_latin1))
+ if (end == argument+length)
berkeley_lock_scan_time= value;
else
{
@@ -6345,14 +6681,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
have_berkeley_db= SHOW_OPTION_DISABLED;
#endif
break;
- case OPT_ISAM:
-#ifdef HAVE_ISAM
- if (opt_isam)
- have_isam= SHOW_OPTION_YES;
- else
- have_isam= SHOW_OPTION_DISABLED;
-#endif
- break;
case OPT_NDBCLUSTER:
#ifdef HAVE_NDBCLUSTER_DB
if (opt_ndbcluster)
@@ -6361,6 +6689,31 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
have_ndbcluster= SHOW_OPTION_DISABLED;
#endif
break;
+#ifdef HAVE_NDBCLUSTER_DB
+ case OPT_NDB_MGMD:
+ case OPT_NDB_NODEID:
+ {
+ int len= my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len,
+ sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len,
+ "%s%s%s",opt_ndb_constrbuf_len > 0 ? ",":"",
+ optid == OPT_NDB_NODEID ? "nodeid=" : "",
+ argument);
+ opt_ndb_constrbuf_len+= len;
+ }
+ /* fall through to add the connectstring to the end
+ * and set opt_ndbcluster_connectstring
+ */
+ case OPT_NDB_CONNECTSTRING:
+ if (opt_ndb_connectstring && opt_ndb_connectstring[0])
+ my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len,
+ sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len,
+ "%s%s", opt_ndb_constrbuf_len > 0 ? ",":"",
+ opt_ndb_connectstring);
+ else
+ opt_ndb_constrbuf[opt_ndb_constrbuf_len]= 0;
+ opt_ndbcluster_connectstring= opt_ndb_constrbuf;
+ break;
+#endif
case OPT_INNODB:
#ifdef HAVE_INNOBASE_DB
if (opt_innodb)
@@ -6378,9 +6731,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case OPT_INNODB_LOG_ARCHIVE:
innobase_log_archive= argument ? test(atoi(argument)) : 1;
break;
- case OPT_INNODB_FAST_SHUTDOWN:
- innobase_fast_shutdown= argument ? test(atoi(argument)) : 1;
- break;
#endif /* HAVE_INNOBASE_DB */
case OPT_MYISAM_RECOVER:
{
@@ -6402,6 +6752,21 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
break;
}
+ case OPT_CONCURRENT_INSERT:
+ /* The following code is mainly here to emulate old behavior */
+ if (!argument) /* --concurrent-insert */
+ myisam_concurrent_insert= 1;
+ else if (argument == disabled_my_option)
+ myisam_concurrent_insert= 0; /* --skip-concurrent-insert */
+ break;
+ case OPT_TC_HEURISTIC_RECOVER:
+ {
+ if ((tc_heuristic_recover=find_type(argument,
+ &tc_heuristic_recover_typelib, 2)) <=0)
+ {
+ fprintf(stderr, "Unknown option to tc-heuristic-recover: %s\n",argument);
+ exit(1);
+ }
case OPT_MYISAM_STATS_METHOD:
{
myisam_stats_method_str= argument;
@@ -6411,9 +6776,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
fprintf(stderr, "Invalid value of myisam_stats_method: %s.\n", argument);
exit(1);
}
- global_system_variables.myisam_stats_method=
- test(method-1)? MI_STATS_METHOD_NULLS_EQUAL :
- MI_STATS_METHOD_NULLS_NOT_EQUAL;
+ global_system_variables.myisam_stats_method= method;
break;
}
case OPT_SQL_MODE:
@@ -6451,7 +6814,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
/* Initiates DEBUG - but no debugging here ! */
-extern "C" gptr *
+static gptr *
mysql_getopt_value(const char *keyname, uint key_length,
const struct my_option *option)
{
@@ -6480,7 +6843,7 @@ mysql_getopt_value(const char *keyname, uint key_length,
}
-void option_error_reporter(enum loglevel level, const char *format, ...)
+static void option_error_reporter(enum loglevel level, const char *format, ...)
{
va_list args;
va_start(args, format);
@@ -6586,8 +6949,6 @@ static void get_options(int argc,char **argv)
my_default_record_cache_size=global_system_variables.read_buff_size;
myisam_max_temp_length=
(my_off_t) global_system_variables.myisam_max_sort_file_size;
- myisam_max_extra_temp_length=
- (my_off_t) global_system_variables.myisam_max_extra_sort_file_size;
/* Set global variables based on startup options */
myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
@@ -6842,12 +7203,13 @@ static void create_pid_file()
Instantiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
/* Used templates */
template class I_List<THD>;
template class I_List_iterator<THD>;
template class I_List<i_string>;
template class I_List<i_string_pair>;
template class I_List<NAMED_LIST>;
-FIX_GCC_LINKING_PROBLEM
+template class I_List<Statement>;
+template class I_List_iterator<Statement>;
#endif
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 93fa7ac938c..7326c0395e3 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -72,7 +72,7 @@
/* The following is because alarms doesn't work on windows. */
#define NO_ALARM
#endif
-
+
#ifndef NO_ALARM
#include "my_pthread.h"
void sql_print_error(const char *format,...);
@@ -83,7 +83,6 @@ void sql_print_error(const char *format,...);
#include "thr_alarm.h"
#ifdef MYSQL_SERVER
-#define USE_QUERY_CACHE
/*
The following variables/functions should really not be declared
extern, but as it's hard to include mysql_priv.h here, we have to
@@ -92,12 +91,16 @@ void sql_print_error(const char *format,...);
extern uint test_flags;
extern ulong bytes_sent, bytes_received, net_big_packet_count;
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
+#ifndef MYSQL_INSTANCE_MANAGER
extern void query_cache_insert(NET *net, const char *packet, ulong length);
-#else
-#undef statistic_add
-#undef statistic_increment
-#define statistic_add(A,B,C)
-#define statistic_increment(A,B)
+#define USE_QUERY_CACHE
+#define update_statistics(A) A
+#endif /* MYSQL_INSTANCE_MANGER */
+#endif /* defined(MYSQL_SERVER) && !defined(MYSQL_INSTANCE_MANAGER) */
+
+#if !defined(MYSQL_SERVER) || defined(MYSQL_INSTANCE_MANAGER)
+#define update_statistics(A)
+#define thd_increment_bytes_sent(N)
#endif
#define TEST_BLOCKING 8
@@ -118,7 +121,7 @@ my_bool my_net_init(NET *net, Vio* vio)
DBUG_RETURN(1);
net->buff_end=net->buff+net->max_packet;
net->vio = vio;
- net->no_send_ok = 0;
+ net->no_send_ok= net->no_send_eof= net->no_send_error= 0;
net->error=0; net->return_errno=0; net->return_status=0;
net->pkt_nr=net->compress_pkt_nr=0;
net->write_pos=net->read_pos = net->buff;
@@ -445,7 +448,8 @@ net_real_write(NET *net,const char *packet,ulong len)
my_bool net_blocking = vio_is_blocking(net->vio);
DBUG_ENTER("net_real_write");
-#if defined(MYSQL_SERVER) && defined(HAVE_QUERY_CACHE)
+#if defined(MYSQL_SERVER) && defined(HAVE_QUERY_CACHE) \
+ && !defined(MYSQL_INSTANCE_MANAGER)
if (net->query_cache_query != 0)
query_cache_insert(net, packet, len);
#endif
@@ -554,7 +558,7 @@ net_real_write(NET *net,const char *packet,ulong len)
break;
}
pos+=length;
- statistic_add(bytes_sent,length,&LOCK_bytes_sent);
+ update_statistics(thd_increment_bytes_sent(length));
}
#ifndef __WIN__
end:
@@ -625,7 +629,7 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain));
/* The following is good for debugging */
- statistic_increment(net_big_packet_count,&LOCK_bytes_received);
+ update_statistics(thd_increment_net_big_packet_count(1));
if (!thr_alarm_in_use(alarmed))
{
@@ -641,7 +645,7 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
uint length= min(remain, net->max_packet);
if (net_safe_read(net, (char*) net->buff, length, alarmed))
DBUG_RETURN(1);
- statistic_add(bytes_received, length, &LOCK_bytes_received);
+ update_statistics(thd_increment_bytes_received(length));
remain -= (uint32) length;
}
if (old != MAX_PACKET_LENGTH)
@@ -766,7 +770,7 @@ my_real_read(NET *net, ulong *complen)
}
remain -= (uint32) length;
pos+= (ulong) length;
- statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
+ update_statistics(thd_increment_bytes_received(length));
}
if (i == 0)
{ /* First parts is packet length */
diff --git a/sql/nt_servc.h b/sql/nt_servc.h
index 6d74eaccea2..a3c12569114 100644
--- a/sql/nt_servc.h
+++ b/sql/nt_servc.h
@@ -48,8 +48,9 @@ class NTService
//service install / un-install
- BOOL Install(int startType,LPCSTR szInternName,LPCSTR szDisplayName,LPCSTR szFullPath,
- LPCSTR szAccountName=NULL,LPCSTR szPassword=NULL);
+ BOOL Install(int startType,LPCSTR szInternName,LPCSTR szDisplayName,
+ LPCSTR szFullPath, LPCSTR szAccountName=NULL,
+ LPCSTR szPassword=NULL);
BOOL SeekStatus(LPCSTR szInternName, int OperationType);
BOOL Remove(LPCSTR szInternName);
BOOL IsService(LPCSTR ServiceName);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 5cb330100f8..edb4289e76f 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -23,13 +23,25 @@
*/
+/*
+ Classes in this file are used in the following way:
+ 1. For a selection condition a tree of SEL_IMERGE/SEL_TREE/SEL_ARG objects
+ is created. #of rows in table and index statistics are ignored at this
+ step.
+ 2. Created SEL_TREE and index stats data are used to construct a
+ TABLE_READ_PLAN-derived object (TRP_*). Several 'candidate' table read
+ plans may be created.
+ 3. The least expensive table read plan is used to create a tree of
+ QUICK_SELECT_I-derived objects which are later used for row retrieval.
+ QUICK_RANGEs are also created in this step.
+*/
+
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation // gcc: Class implementation
#endif
#include "mysql_priv.h"
#include <m_ctype.h>
-#include <nisam.h>
#include "sql_select.h"
#ifndef EXTRA_DEBUG
@@ -37,6 +49,11 @@
#define test_use_count(A) {}
#endif
+/*
+ Convert double value to #rows. Currently this does floor(), and we
+ might consider using round() instead.
+*/
+#define double2rows(x) ((ha_rows)(x))
static int sel_cmp(Field *f,char *a,char *b,uint8 a_flag,uint8 b_flag);
@@ -167,8 +184,7 @@ public:
min_value=arg->max_value;
min_flag=arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN;
}
- void store(uint length,char **min_key,uint min_key_flag,
- char **max_key, uint max_key_flag)
+ void store_min(uint length,char **min_key,uint min_key_flag)
{
if ((min_flag & GEOM_FLAG) ||
(!(min_flag & NO_MIN_RANGE) &&
@@ -183,6 +199,11 @@ public:
memcpy(*min_key,min_value,length);
(*min_key)+= length;
}
+ }
+ void store(uint length,char **min_key,uint min_key_flag,
+ char **max_key, uint max_key_flag)
+ {
+ store_min(length, min_key, min_key_flag);
if (!(max_flag & NO_MAX_RANGE) &&
!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
{
@@ -267,31 +288,78 @@ public:
SEL_ARG *clone_tree();
};
+class SEL_IMERGE;
+
class SEL_TREE :public Sql_alloc
{
public:
enum Type { IMPOSSIBLE, ALWAYS, MAYBE, KEY, KEY_SMALLER } type;
SEL_TREE(enum Type type_arg) :type(type_arg) {}
- SEL_TREE() :type(KEY) { bzero((char*) keys,sizeof(keys));}
+ SEL_TREE() :type(KEY)
+ {
+ keys_map.clear_all();
+ bzero((char*) keys,sizeof(keys));
+ }
SEL_ARG *keys[MAX_KEY];
+ key_map keys_map; /* bitmask of non-NULL elements in keys */
+
+ /*
+ Possible ways to read rows using index_merge. The list is non-empty only
+ if type==KEY. Currently can be non empty only if keys_map.is_clear_all().
+ */
+ List<SEL_IMERGE> merges;
+
+ /* The members below are filled/used only after get_mm_tree is done */
+ key_map ror_scans_map; /* bitmask of ROR scan-able elements in keys */
+ uint n_ror_scans; /* number of set bits in ror_scans_map */
+
+ struct st_ror_scan_info **ror_scans; /* list of ROR key scans */
+ struct st_ror_scan_info **ror_scans_end; /* last ROR scan */
+ /* Note that #records for each key scan is stored in table->quick_rows */
};
typedef struct st_qsel_param {
THD *thd;
TABLE *table;
- KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY];
- MEM_ROOT *mem_root;
+ KEY_PART *key_parts,*key_parts_end;
+ KEY_PART *key[MAX_KEY]; /* First key parts of keys used in the query */
+ MEM_ROOT *mem_root, *old_root;
table_map prev_tables,read_tables,current_table;
- uint baseflag, keys, max_key_part, range_count;
+ uint baseflag, max_key_part, range_count;
+
+ uint keys; /* number of keys used in the query */
+
+ /* used_key_no -> table_key_no translation table */
uint real_keynr[MAX_KEY];
+
char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
bool quick; // Don't calulate possible keys
COND *cond;
+
+ uint fields_bitmap_size;
+ MY_BITMAP needed_fields; /* bitmask of fields needed by the query */
+
+ key_map *needed_reg; /* ptr to SQL_SELECT::needed_reg */
+
+ uint *imerge_cost_buff; /* buffer for index_merge cost estimates */
+ uint imerge_cost_buff_size; /* size of the buffer */
+
+ /* TRUE if last checked tree->key can be used for ROR-scan */
+ bool is_ror_scan;
} PARAM;
+class TABLE_READ_PLAN;
+ class TRP_RANGE;
+ class TRP_ROR_INTERSECT;
+ class TRP_ROR_UNION;
+ class TRP_ROR_INDEX_MERGE;
+ class TRP_GROUP_MIN_MAX;
+
+struct st_ror_scan_info;
+
static SEL_TREE * get_mm_parts(PARAM *param,COND *cond_func,Field *field,
Item_func::Functype type,Item *value,
Item_result cmp_type);
@@ -299,32 +367,279 @@ static SEL_ARG *get_mm_leaf(PARAM *param,COND *cond_func,Field *field,
KEY_PART *key_part,
Item_func::Functype type,Item *value);
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond);
+
+static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree);
static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
char *min_key,uint min_key_flag,
char *max_key, uint max_key_flag);
-static QUICK_SELECT *get_quick_select(PARAM *param,uint index,
- SEL_ARG *key_tree);
+QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
+ SEL_ARG *key_tree,
+ MEM_ROOT *alloc = NULL);
+static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
+ bool index_read_must_be_used,
+ double read_time);
+static
+TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
+ double read_time,
+ bool *are_all_covering);
+static
+TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
+ SEL_TREE *tree,
+ double read_time);
+static
+TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
+ double read_time);
+static
+TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree);
+static int get_index_merge_params(PARAM *param, key_map& needed_reg,
+ SEL_IMERGE *imerge, double *read_time,
+ ha_rows* imerge_rows);
+static double get_index_only_read_time(const PARAM* param, ha_rows records,
+ int keynr);
+
#ifndef DBUG_OFF
-static void print_quick(QUICK_SELECT *quick,const key_map* needed_reg);
+static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
+ const char *msg);
+static void print_ror_scans_arr(TABLE *table, const char *msg,
+ struct st_ror_scan_info **start,
+ struct st_ror_scan_info **end);
+static void print_rowid(byte* val, int len);
+static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg);
#endif
+
static SEL_TREE *tree_and(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2);
static SEL_TREE *tree_or(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2);
static SEL_ARG *sel_add(SEL_ARG *key1,SEL_ARG *key2);
static SEL_ARG *key_or(SEL_ARG *key1,SEL_ARG *key2);
static SEL_ARG *key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag);
static bool get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1);
-static bool get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
+bool get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
SEL_ARG *key_tree,char *min_key,uint min_key_flag,
char *max_key,uint max_key_flag);
static bool eq_tree(SEL_ARG* a,SEL_ARG *b);
static SEL_ARG null_element(SEL_ARG::IMPOSSIBLE);
-static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length);
+static bool null_part_in_key(KEY_PART *key_part, const char *key,
+ uint length);
+bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2, PARAM* param);
+
+
+/*
+ SEL_IMERGE is a list of possible ways to do index merge, i.e. it is
+ a condition in the following form:
+ (t_1||t_2||...||t_N) && (next)
+
+ where all t_i are SEL_TREEs, next is another SEL_IMERGE and no pair
+ (t_i,t_j) contains SEL_ARGS for the same index.
+
+ SEL_TREE contained in SEL_IMERGE always has merges=NULL.
+
+ This class relies on memory manager to do the cleanup.
+*/
+
+class SEL_IMERGE : public Sql_alloc
+{
+ enum { PREALLOCED_TREES= 10};
+public:
+ SEL_TREE *trees_prealloced[PREALLOCED_TREES];
+ SEL_TREE **trees; /* trees used to do index_merge */
+ SEL_TREE **trees_next; /* last of these trees */
+ SEL_TREE **trees_end; /* end of allocated space */
+
+ SEL_ARG ***best_keys; /* best keys to read in SEL_TREEs */
+
+ SEL_IMERGE() :
+ trees(&trees_prealloced[0]),
+ trees_next(trees),
+ trees_end(trees + PREALLOCED_TREES)
+ {}
+ int or_sel_tree(PARAM *param, SEL_TREE *tree);
+ int or_sel_tree_with_checks(PARAM *param, SEL_TREE *new_tree);
+ int or_sel_imerge_with_checks(PARAM *param, SEL_IMERGE* imerge);
+};
+
+
+/*
+ Add SEL_TREE to this index_merge without any checks,
+
+ NOTES
+ This function implements the following:
+ (x_1||...||x_N) || t = (x_1||...||x_N||t), where x_i, t are SEL_TREEs
+
+ RETURN
+ 0 - OK
+ -1 - Out of memory.
+*/
+
+int SEL_IMERGE::or_sel_tree(PARAM *param, SEL_TREE *tree)
+{
+ if (trees_next == trees_end)
+ {
+ const int realloc_ratio= 2; /* Double size for next round */
+ uint old_elements= (trees_end - trees);
+ uint old_size= sizeof(SEL_TREE**) * old_elements;
+ uint new_size= old_size * realloc_ratio;
+ SEL_TREE **new_trees;
+ if (!(new_trees= (SEL_TREE**)alloc_root(param->mem_root, new_size)))
+ return -1;
+ memcpy(new_trees, trees, old_size);
+ trees= new_trees;
+ trees_next= trees + old_elements;
+ trees_end= trees + old_elements * realloc_ratio;
+ }
+ *(trees_next++)= tree;
+ return 0;
+}
+
+
+/*
+ Perform OR operation on this SEL_IMERGE and supplied SEL_TREE new_tree,
+ combining new_tree with one of the trees in this SEL_IMERGE if they both
+ have SEL_ARGs for the same key.
+
+ SYNOPSIS
+ or_sel_tree_with_checks()
+ param PARAM from SQL_SELECT::test_quick_select
+ new_tree SEL_TREE with type KEY or KEY_SMALLER.
+
+ NOTES
+ This does the following:
+ (t_1||...||t_k)||new_tree =
+ either
+ = (t_1||...||t_k||new_tree)
+ or
+ = (t_1||....||(t_j|| new_tree)||...||t_k),
+
+ where t_i, y are SEL_TREEs.
+ new_tree is combined with the first t_j it has a SEL_ARG on common
+ key with. As a consequence of this, choice of keys to do index_merge
+ read may depend on the order of conditions in WHERE part of the query.
+
+ RETURN
+ 0 OK
+ 1 One of the trees was combined with new_tree to SEL_TREE::ALWAYS,
+ and (*this) should be discarded.
+ -1 An error occurred.
+*/
+
+int SEL_IMERGE::or_sel_tree_with_checks(PARAM *param, SEL_TREE *new_tree)
+{
+ for (SEL_TREE** tree = trees;
+ tree != trees_next;
+ tree++)
+ {
+ if (sel_trees_can_be_ored(*tree, new_tree, param))
+ {
+ *tree = tree_or(param, *tree, new_tree);
+ if (!*tree)
+ return 1;
+ if (((*tree)->type == SEL_TREE::MAYBE) ||
+ ((*tree)->type == SEL_TREE::ALWAYS))
+ return 1;
+ /* SEL_TREE::IMPOSSIBLE is impossible here */
+ return 0;
+ }
+ }
+
+ /* New tree cannot be combined with any of existing trees. */
+ return or_sel_tree(param, new_tree);
+}
+
+
+/*
+ Perform OR operation on this index_merge and supplied index_merge list.
+
+ RETURN
+ 0 - OK
+ 1 - One of conditions in result is always TRUE and this SEL_IMERGE
+ should be discarded.
+ -1 - An error occurred
+*/
+
+int SEL_IMERGE::or_sel_imerge_with_checks(PARAM *param, SEL_IMERGE* imerge)
+{
+ for (SEL_TREE** tree= imerge->trees;
+ tree != imerge->trees_next;
+ tree++)
+ {
+ if (or_sel_tree_with_checks(param, *tree))
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ Perform AND operation on two index_merge lists and store result in *im1.
+*/
+
+inline void imerge_list_and_list(List<SEL_IMERGE> *im1, List<SEL_IMERGE> *im2)
+{
+ im1->concat(im2);
+}
+
+
+/*
+ Perform OR operation on 2 index_merge lists, storing result in first list.
+
+ NOTES
+ The following conversion is implemented:
+ (a_1 &&...&& a_N)||(b_1 &&...&& b_K) = AND_i,j(a_i || b_j) =>
+ => (a_1||b_1).
+
+ i.e. all conjuncts except the first one are currently dropped.
+ This is done to avoid producing N*K ways to do index_merge.
+
+ If (a_1||b_1) produce a condition that is always TRUE, NULL is returned
+ and index_merge is discarded (while it is actually possible to try
+ harder).
+
+ As a consequence of this, choice of keys to do index_merge read may depend
+ on the order of conditions in WHERE part of the query.
+
+ RETURN
+ 0 OK, result is stored in *im1
+ other Error, both passed lists are unusable
+*/
+
+int imerge_list_or_list(PARAM *param,
+ List<SEL_IMERGE> *im1,
+ List<SEL_IMERGE> *im2)
+{
+ SEL_IMERGE *imerge= im1->head();
+ im1->empty();
+ im1->push_back(imerge);
+
+ return imerge->or_sel_imerge_with_checks(param, im2->head());
+}
+
+
+/*
+ Perform OR operation on index_merge list and key tree.
+
+ RETURN
+ 0 OK, result is stored in *im1.
+ other Error
+*/
+
+int imerge_list_or_tree(PARAM *param,
+ List<SEL_IMERGE> *im1,
+ SEL_TREE *tree)
+{
+ SEL_IMERGE *imerge;
+ List_iterator<SEL_IMERGE> it(*im1);
+ while ((imerge= it++))
+ {
+ if (imerge->or_sel_tree_with_checks(param, tree))
+ it.remove();
+ }
+ return im1->is_empty();
+}
/***************************************************************************
-** Basic functions for SQL_SELECT and QUICK_SELECT
+** Basic functions for SQL_SELECT and QUICK_RANGE_SELECT
***************************************************************************/
/* make a select from mysql info
@@ -334,13 +649,17 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length);
*/
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
- table_map read_tables, COND *conds, int *error)
+ table_map read_tables, COND *conds,
+ bool allow_null_cond,
+ int *error)
+
{
SQL_SELECT *select;
DBUG_ENTER("make_select");
*error=0;
- if (!conds)
+
+ if (!conds && !allow_null_cond)
DBUG_RETURN(0);
if (!(select= new SQL_SELECT))
{
@@ -380,7 +699,7 @@ void SQL_SELECT::cleanup()
free_cond=0;
delete cond;
cond= 0;
- }
+ }
close_cached_file(&file);
}
@@ -392,11 +711,29 @@ SQL_SELECT::~SQL_SELECT()
#undef index // Fix for Unixware 7
-QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc)
- :dont_free(0),sorted(0),error(0),index(key_nr),max_used_key_length(0),
- used_key_parts(0), head(table), it(ranges),range(0)
+QUICK_SELECT_I::QUICK_SELECT_I()
+ :max_used_key_length(0),
+ used_key_parts(0)
+{}
+
+QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
+ bool no_alloc, MEM_ROOT *parent_alloc)
+ :dont_free(0),error(0),free_file(0),in_range(0),cur_range(NULL),range(0)
{
- if (!no_alloc)
+ sorted= 0;
+ index= key_nr;
+ head= table;
+ key_part_info= head->key_info[index].key_part;
+ my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16);
+
+ /* 'thd' is not accessible in QUICK_RANGE_SELECT::reset(). */
+ multi_range_bufsiz= thd->variables.read_rnd_buff_size;
+ multi_range_count= thd->variables.multi_range_count;
+ multi_range_length= 0;
+ multi_range= NULL;
+ multi_range_buff= NULL;
+
+ if (!no_alloc && !parent_alloc)
{
// Allocates everything through the internal memroot
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
@@ -404,21 +741,463 @@ QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc)
}
else
bzero((char*) &alloc,sizeof(alloc));
- file=head->file;
- record=head->record[0];
- init();
+ file= head->file;
+ record= head->record[0];
+}
+
+
+int QUICK_RANGE_SELECT::init()
+{
+ DBUG_ENTER("QUICK_RANGE_SELECT::init");
+
+ if (file->inited != handler::NONE)
+ file->ha_index_or_rnd_end();
+ DBUG_RETURN(error= file->ha_index_init(index));
+}
+
+
+void QUICK_RANGE_SELECT::range_end()
+{
+ if (file->inited != handler::NONE)
+ file->ha_index_or_rnd_end();
}
-QUICK_SELECT::~QUICK_SELECT()
+
+QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
{
+ DBUG_ENTER("QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT");
if (!dont_free)
{
- if (file->inited)
- file->ha_index_end();
+ /* file is NULL for CPK scan on covering ROR-intersection */
+ if (file)
+ {
+ range_end();
+ file->extra(HA_EXTRA_NO_KEYREAD);
+ if (free_file)
+ {
+ DBUG_PRINT("info", ("Freeing separate handler %p (free=%d)", file,
+ free_file));
+ file->reset();
+ file->external_lock(current_thd, F_UNLCK);
+ file->close();
+ }
+ }
+ delete_dynamic(&ranges); /* ranges are allocated in alloc */
free_root(&alloc,MYF(0));
}
+ if (multi_range)
+ my_free((char*) multi_range, MYF(0));
+ if (multi_range_buff)
+ my_free((char*) multi_range_buff, MYF(0));
+ DBUG_VOID_RETURN;
+}
+
+
+QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
+ TABLE *table)
+ :pk_quick_select(NULL), thd(thd_param)
+{
+ DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT");
+ index= MAX_KEY;
+ head= table;
+ bzero(&read_record, sizeof(read_record));
+ init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
+ DBUG_VOID_RETURN;
+}
+
+int QUICK_INDEX_MERGE_SELECT::init()
+{
+ DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::init");
+ DBUG_RETURN(0);
+}
+
+int QUICK_INDEX_MERGE_SELECT::reset()
+{
+ DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::reset");
+ DBUG_RETURN(read_keys_and_merge());
+}
+
+bool
+QUICK_INDEX_MERGE_SELECT::push_quick_back(QUICK_RANGE_SELECT *quick_sel_range)
+{
+ /*
+ Save quick_select that does scan on clustered primary key as it will be
+ processed separately.
+ */
+ if (head->file->primary_key_is_clustered() &&
+ quick_sel_range->index == head->s->primary_key)
+ pk_quick_select= quick_sel_range;
+ else
+ return quick_selects.push_back(quick_sel_range);
+ return 0;
+}
+
+QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT()
+{
+ List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
+ QUICK_RANGE_SELECT* quick;
+ DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT");
+ quick_it.rewind();
+ while ((quick= quick_it++))
+ quick->file= NULL;
+ quick_selects.delete_elements();
+ delete pk_quick_select;
+ free_root(&alloc,MYF(0));
+ DBUG_VOID_RETURN;
+}
+
+
+QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
+ TABLE *table,
+ bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc)
+ : cpk_quick(NULL), thd(thd_param), need_to_fetch_row(retrieve_full_rows),
+ scans_inited(FALSE)
+{
+ index= MAX_KEY;
+ head= table;
+ record= head->record[0];
+ if (!parent_alloc)
+ init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
+ else
+ bzero(&alloc, sizeof(MEM_ROOT));
+ last_rowid= (byte*)alloc_root(parent_alloc? parent_alloc : &alloc,
+ head->file->ref_length);
+}
+
+
+/*
+ Do post-constructor initialization.
+ SYNOPSIS
+ QUICK_ROR_INTERSECT_SELECT::init()
+
+ RETURN
+ 0 OK
+ other Error code
+*/
+
+int QUICK_ROR_INTERSECT_SELECT::init()
+{
+ DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init");
+ /* Check if last_rowid was successfully allocated in ctor */
+ DBUG_RETURN(!last_rowid);
+}
+
+
+/*
+ Initialize this quick select to be a ROR-merged scan.
+
+ SYNOPSIS
+ QUICK_RANGE_SELECT::init_ror_merged_scan()
+ reuse_handler If TRUE, use head->file, otherwise create a separate
+ handler object
+
+ NOTES
+ This function creates and prepares for subsequent use a separate handler
+ object if it can't reuse head->file. The reason for this is that during
+ ROR-merge several key scans are performed simultaneously, and a single
+ handler is only capable of preserving context of a single key scan.
+
+ In ROR-merge the quick select doing merge does full records retrieval,
+ merged quick selects read only keys.
+
+ RETURN
+ 0 ROR child scan initialized, ok to use.
+ 1 error
+*/
+
+int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
+{
+ handler *save_file= file;
+ DBUG_ENTER("QUICK_RANGE_SELECT::init_ror_merged_scan");
+
+ if (reuse_handler)
+ {
+ DBUG_PRINT("info", ("Reusing handler %p", file));
+ if (file->extra(HA_EXTRA_KEYREAD) ||
+ file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) ||
+ init() || reset())
+ {
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+ }
+
+ /* Create a separate handler object for this quick select */
+ if (free_file)
+ {
+ /* already have own 'handler' object. */
+ DBUG_RETURN(0);
+ }
+
+ THD *thd= current_thd;
+ if (!(file= get_new_handler(head, head->s->db_type)))
+ goto failure;
+ DBUG_PRINT("info", ("Allocated new handler %p", file));
+ if (file->ha_open(head->s->path, head->db_stat, HA_OPEN_IGNORE_IF_LOCKED))
+ {
+ /* Caller will free the memory */
+ goto failure;
+ }
+ if (file->external_lock(thd, F_RDLCK))
+ goto failure;
+
+ if (file->extra(HA_EXTRA_KEYREAD) ||
+ file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) ||
+ init() || reset())
+ {
+ file->external_lock(thd, F_UNLCK);
+ file->close();
+ goto failure;
+ }
+ free_file= TRUE;
+ last_rowid= file->ref;
+ DBUG_RETURN(0);
+
+failure:
+ file= save_file;
+ DBUG_RETURN(1);
+}
+
+
+/*
+ Initialize this quick select to be a part of a ROR-merged scan.
+ SYNOPSIS
+ QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan()
+ reuse_handler If TRUE, use head->file, otherwise create separate
+ handler object.
+ RETURN
+ 0 OK
+ other error code
+*/
+int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
+{
+ List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
+ QUICK_RANGE_SELECT* quick;
+ DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan");
+
+ /* Initialize all merged "children" quick selects */
+ DBUG_ASSERT(!need_to_fetch_row || reuse_handler);
+ if (!need_to_fetch_row && reuse_handler)
+ {
+ quick= quick_it++;
+ /*
+ There is no use of this->file. Use it for the first of merged range
+ selects.
+ */
+ if (quick->init_ror_merged_scan(TRUE))
+ DBUG_RETURN(1);
+ quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
+ }
+ while ((quick= quick_it++))
+ {
+ if (quick->init_ror_merged_scan(FALSE))
+ DBUG_RETURN(1);
+ quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
+ /* All merged scans share the same record buffer in intersection. */
+ quick->record= head->record[0];
+ }
+
+ if (need_to_fetch_row && head->file->ha_rnd_init(1))
+ {
+ DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Initialize quick select for row retrieval.
+ SYNOPSIS
+ reset()
+ RETURN
+ 0 OK
+ other Error code
+*/
+
+int QUICK_ROR_INTERSECT_SELECT::reset()
+{
+ DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::reset");
+ if (!scans_inited && init_ror_merged_scan(TRUE))
+ DBUG_RETURN(1);
+ scans_inited= TRUE;
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ QUICK_RANGE_SELECT *quick;
+ while ((quick= it++))
+ quick->reset();
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Add a merged quick select to this ROR-intersection quick select.
+
+ SYNOPSIS
+ QUICK_ROR_INTERSECT_SELECT::push_quick_back()
+ quick Quick select to be added. The quick select must return
+ rows in rowid order.
+ NOTES
+ This call can only be made before init() is called.
+
+ RETURN
+ FALSE OK
+ TRUE Out of memory.
+*/
+
+bool
+QUICK_ROR_INTERSECT_SELECT::push_quick_back(QUICK_RANGE_SELECT *quick)
+{
+ return quick_selects.push_back(quick);
+}
+
+QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT()
+{
+ DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT");
+ quick_selects.delete_elements();
+ delete cpk_quick;
+ free_root(&alloc,MYF(0));
+ if (need_to_fetch_row && head->file->inited != handler::NONE)
+ head->file->ha_rnd_end();
+ DBUG_VOID_RETURN;
+}
+
+
+QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
+ TABLE *table)
+ : thd(thd_param), scans_inited(FALSE)
+{
+ index= MAX_KEY;
+ head= table;
+ rowid_length= table->file->ref_length;
+ record= head->record[0];
+ init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
+ thd_param->mem_root= &alloc;
+}
+
+
+/*
+ Do post-constructor initialization.
+ SYNOPSIS
+ QUICK_ROR_UNION_SELECT::init()
+
+ RETURN
+ 0 OK
+ other Error code
+*/
+
+int QUICK_ROR_UNION_SELECT::init()
+{
+ DBUG_ENTER("QUICK_ROR_UNION_SELECT::init");
+ if (init_queue(&queue, quick_selects.elements, 0,
+ FALSE , QUICK_ROR_UNION_SELECT::queue_cmp,
+ (void*) this))
+ {
+ bzero(&queue, sizeof(QUEUE));
+ DBUG_RETURN(1);
+ }
+
+ if (!(cur_rowid= (byte*)alloc_root(&alloc, 2*head->file->ref_length)))
+ DBUG_RETURN(1);
+ prev_rowid= cur_rowid + head->file->ref_length;
+ DBUG_RETURN(0);
}
+
+/*
+ Comparison function to be used QUICK_ROR_UNION_SELECT::queue priority
+ queue.
+
+ SYNPOSIS
+ QUICK_ROR_UNION_SELECT::queue_cmp()
+ arg Pointer to QUICK_ROR_UNION_SELECT
+ val1 First merged select
+ val2 Second merged select
+*/
+
+int QUICK_ROR_UNION_SELECT::queue_cmp(void *arg, byte *val1, byte *val2)
+{
+ QUICK_ROR_UNION_SELECT *self= (QUICK_ROR_UNION_SELECT*)arg;
+ return self->head->file->cmp_ref(((QUICK_SELECT_I*)val1)->last_rowid,
+ ((QUICK_SELECT_I*)val2)->last_rowid);
+}
+
+
+/*
+ Initialize quick select for row retrieval.
+ SYNOPSIS
+ reset()
+
+ RETURN
+ 0 OK
+ other Error code
+*/
+
+int QUICK_ROR_UNION_SELECT::reset()
+{
+ QUICK_SELECT_I* quick;
+ int error;
+ DBUG_ENTER("QUICK_ROR_UNION_SELECT::reset");
+ have_prev_rowid= FALSE;
+ if (!scans_inited)
+ {
+ QUICK_SELECT_I *quick;
+ List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
+ while ((quick= it++))
+ {
+ if (quick->init_ror_merged_scan(FALSE))
+ DBUG_RETURN(1);
+ }
+ scans_inited= TRUE;
+ }
+ queue_remove_all(&queue);
+ /*
+ Initialize scans for merged quick selects and put all merged quick
+ selects into the queue.
+ */
+ List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
+ while ((quick= it++))
+ {
+ if (quick->reset())
+ DBUG_RETURN(1);
+ if ((error= quick->get_next()))
+ {
+ if (error == HA_ERR_END_OF_FILE)
+ continue;
+ DBUG_RETURN(error);
+ }
+ quick->save_last_pos();
+ queue_insert(&queue, (byte*)quick);
+ }
+
+ if (head->file->ha_rnd_init(1))
+ {
+ DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
+ DBUG_RETURN(1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+bool
+QUICK_ROR_UNION_SELECT::push_quick_back(QUICK_SELECT_I *quick_sel_range)
+{
+ return quick_selects.push_back(quick_sel_range);
+}
+
+QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT()
+{
+ DBUG_ENTER("QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT");
+ delete_queue(&queue);
+ quick_selects.delete_elements();
+ if (head->file->inited != handler::NONE)
+ head->file->ha_rnd_end();
+ free_root(&alloc,MYF(0));
+ DBUG_VOID_RETURN;
+}
+
+
QUICK_RANGE::QUICK_RANGE()
:min_key(0),max_key(0),min_length(0),max_length(0),
flag(NO_MIN_RANGE | NO_MAX_RANGE)
@@ -582,28 +1361,270 @@ SEL_ARG *SEL_ARG::clone_tree()
return root;
}
+
/*
- Test if a key can be used in different ranges
+ Table rows retrieval plan. Range optimizer creates QUICK_SELECT_I-derived
+ objects from table read plans.
+*/
+class TABLE_READ_PLAN
+{
+public:
+ /*
+ Plan read cost, with or without cost of full row retrieval, depending
+ on plan creation parameters.
+ */
+ double read_cost;
+ ha_rows records; /* estimate of #rows to be examined */
+
+ /*
+ If TRUE, the scan returns rows in rowid order. This is used only for
+ scans that can be both ROR and non-ROR.
+ */
+ bool is_ror;
+
+ /*
+ Create quick select for this plan.
+ SYNOPSIS
+ make_quick()
+ param Parameter from test_quick_select
+ retrieve_full_rows If TRUE, created quick select will do full record
+ retrieval.
+ parent_alloc Memory pool to use, if any.
+
+ NOTES
+ retrieve_full_rows is ignored by some implementations.
+
+ RETURN
+ created quick select
+ NULL on any error.
+ */
+ virtual QUICK_SELECT_I *make_quick(PARAM *param,
+ bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc=NULL) = 0;
+
+ /* Table read plans are allocated on MEM_ROOT and are never deleted */
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
+ static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
+ static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ }
+};
+
+class TRP_ROR_INTERSECT;
+class TRP_ROR_UNION;
+class TRP_INDEX_MERGE;
+
+
+/*
+ Plan for a QUICK_RANGE_SELECT scan.
+ TRP_RANGE::make_quick ignores retrieve_full_rows parameter because
+ QUICK_RANGE_SELECT doesn't distinguish between 'index only' scans and full
+ record retrieval scans.
+*/
+class TRP_RANGE : public TABLE_READ_PLAN
+{
+public:
+ SEL_ARG *key; /* set of intervals to be used in "range" method retrieval */
+ uint key_idx; /* key number in PARAM::key */
+
+ TRP_RANGE(SEL_ARG *key_arg, uint idx_arg)
+ : key(key_arg), key_idx(idx_arg)
+ {}
+
+ QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc)
+ {
+ DBUG_ENTER("TRP_RANGE::make_quick");
+ QUICK_RANGE_SELECT *quick;
+ if ((quick= get_quick_select(param, key_idx, key, parent_alloc)))
+ {
+ quick->records= records;
+ quick->read_time= read_cost;
+ }
+ DBUG_RETURN(quick);
+ }
+};
+
+
+/* Plan for QUICK_ROR_INTERSECT_SELECT scan. */
+
+class TRP_ROR_INTERSECT : public TABLE_READ_PLAN
+{
+public:
+ QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc);
+
+ /* Array of pointers to ROR range scans used in this intersection */
+ struct st_ror_scan_info **first_scan;
+ struct st_ror_scan_info **last_scan; /* End of the above array */
+ struct st_ror_scan_info *cpk_scan; /* Clustered PK scan, if there is one */
+ bool is_covering; /* TRUE if no row retrieval phase is necessary */
+ double index_scan_costs; /* SUM(cost(index_scan)) */
+};
+
+
+/*
+ Plan for QUICK_ROR_UNION_SELECT scan.
+ QUICK_ROR_UNION_SELECT always retrieves full rows, so retrieve_full_rows
+ is ignored by make_quick.
+*/
+
+class TRP_ROR_UNION : public TABLE_READ_PLAN
+{
+public:
+ QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc);
+ TABLE_READ_PLAN **first_ror; /* array of ptrs to plans for merged scans */
+ TABLE_READ_PLAN **last_ror; /* end of the above array */
+};
+
+
+/*
+ Plan for QUICK_INDEX_MERGE_SELECT scan.
+ QUICK_ROR_INTERSECT_SELECT always retrieves full rows, so retrieve_full_rows
+ is ignored by make_quick.
+*/
+
+class TRP_INDEX_MERGE : public TABLE_READ_PLAN
+{
+public:
+ QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc);
+ TRP_RANGE **range_scans; /* array of ptrs to plans of merged scans */
+ TRP_RANGE **range_scans_end; /* end of the array */
+};
+
+
+/*
+ Plan for a QUICK_GROUP_MIN_MAX_SELECT scan.
+*/
+
+class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
+{
+private:
+ bool have_min, have_max;
+ KEY_PART_INFO *min_max_arg_part;
+ uint group_prefix_len;
+ uint used_key_parts;
+ uint group_key_parts;
+ KEY *index_info;
+ uint index;
+ uint key_infix_len;
+ byte key_infix[MAX_KEY_LENGTH];
+ SEL_TREE *range_tree; /* Represents all range predicates in the query. */
+ SEL_ARG *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */
+ uint param_idx; /* Index of used key in param->key. */
+ /* Number of records selected by the ranges in index_tree. */
+public:
+ ha_rows quick_prefix_records;
+public:
+ TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
+ KEY_PART_INFO *min_max_arg_part_arg,
+ uint group_prefix_len_arg, uint used_key_parts_arg,
+ uint group_key_parts_arg, KEY *index_info_arg,
+ uint index_arg, uint key_infix_len_arg,
+ byte *key_infix_arg,
+ SEL_TREE *tree_arg, SEL_ARG *index_tree_arg,
+ uint param_idx_arg, ha_rows quick_prefix_records_arg)
+ : have_min(have_min_arg), have_max(have_max_arg),
+ min_max_arg_part(min_max_arg_part_arg),
+ group_prefix_len(group_prefix_len_arg), used_key_parts(used_key_parts_arg),
+ group_key_parts(group_key_parts_arg), index_info(index_info_arg),
+ index(index_arg), key_infix_len(key_infix_len_arg), range_tree(tree_arg),
+ index_tree(index_tree_arg), param_idx(param_idx_arg),
+ quick_prefix_records(quick_prefix_records_arg)
+ {
+ if (key_infix_len)
+ memcpy(this->key_infix, key_infix_arg, key_infix_len);
+ }
+
+ QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc);
+};
+
+
+/*
+ Fill param->needed_fields with bitmap of fields used in the query.
SYNOPSIS
- SQL_SELECT::test_quick_select(thd,keys_to_use, prev_tables,
- limit, force_quick_range)
+ fill_used_fields_bitmap()
+ param Parameter from test_quick_select function.
+
+ NOTES
+ Clustered PK members are not put into the bitmap as they are implicitly
+ present in all keys (and it is impossible to avoid reading them).
+ RETURN
+ 0 Ok
+ 1 Out of memory.
+*/
+
+static int fill_used_fields_bitmap(PARAM *param)
+{
+ TABLE *table= param->table;
+ param->fields_bitmap_size= (table->s->fields/8 + 1);
+ uchar *tmp;
+ uint pk;
+ if (!(tmp= (uchar*)alloc_root(param->mem_root,param->fields_bitmap_size)) ||
+ bitmap_init(&param->needed_fields, tmp, param->fields_bitmap_size*8,
+ FALSE))
+ return 1;
+
+ bitmap_clear_all(&param->needed_fields);
+ for (uint i= 0; i < table->s->fields; i++)
+ {
+ if (param->thd->query_id == table->field[i]->query_id)
+ bitmap_set_bit(&param->needed_fields, i+1);
+ }
+
+ pk= param->table->s->primary_key;
+ if (param->table->file->primary_key_is_clustered() && pk != MAX_KEY)
+ {
+ /* The table uses clustered PK and it is not internally generated */
+ KEY_PART_INFO *key_part= param->table->key_info[pk].key_part;
+ KEY_PART_INFO *key_part_end= key_part +
+ param->table->key_info[pk].key_parts;
+ for (;key_part != key_part_end; ++key_part)
+ {
+ bitmap_clear_bit(&param->needed_fields, key_part->fieldnr);
+ }
+ }
+ return 0;
+}
- Updates the following in the select parameter:
- needed_reg - Bits for keys with may be used if all prev regs are read
- quick - Parameter to use when reading records.
- In the table struct the following information is updated:
- quick_keys - Which keys can be used
- quick_rows - How many rows the key matches
- RETURN VALUES
- -1 if impossible select
- 0 if can't use quick_select
- 1 if found usable range
+/*
+ Test if a key can be used in different ranges
+
+ SYNOPSIS
+ SQL_SELECT::test_quick_select()
+ thd Current thread
+ keys_to_use Keys to use for range retrieval
+ prev_tables Tables assumed to be already read when the scan is
+ performed (but not read at the moment of this call)
+ limit Query limit
+ force_quick_range Prefer to use range (instead of full table scan) even
+ if it is more expensive.
+
+ NOTES
+ Updates the following in the select parameter:
+ needed_reg - Bits for keys with may be used if all prev regs are read
+ quick - Parameter to use when reading records.
+
+ In the table struct the following information is updated:
+ quick_keys - Which keys can be used
+ quick_rows - How many rows the key matches
+
+ TODO
+ Check if this function really needs to modify keys_to_use, and change the
+ code to pass it by reference if it doesn't.
+
+ In addition to force_quick_range other means can be (an usually are) used
+ to make this function prefer range over full table scan. Figure out if
+ force_quick_range is really needed.
- TODO
- check if the function really needs to modify keys_to_use, and change the
- code to pass it by reference if not
+ RETURN
+ -1 if impossible select (i.e. certainly no rows will be selected)
+ 0 if can't use quick_select
+ 1 if found usable ranges and quick select has been successfully created.
*/
int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
@@ -612,28 +1633,29 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
uint idx;
double scan_time;
- DBUG_ENTER("test_quick_select");
+ DBUG_ENTER("SQL_SELECT::test_quick_select");
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
keys_to_use.to_ulonglong(), (ulong) prev_tables,
(ulong) const_tables));
-
+ DBUG_PRINT("info", ("records=%lu", (ulong)head->file->records));
delete quick;
quick=0;
- needed_reg.clear_all(); quick_keys.clear_all();
- if (!cond || (specialflag & SPECIAL_SAFE_MODE) && ! force_quick_range ||
+ needed_reg.clear_all();
+ quick_keys.clear_all();
+ if ((specialflag & SPECIAL_SAFE_MODE) && ! force_quick_range ||
!limit)
DBUG_RETURN(0); /* purecov: inspected */
if (keys_to_use.is_clear_all())
DBUG_RETURN(0);
- records=head->file->records;
+ 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.1;
+ scan_time= (double) records / TIME_FOR_COMPARE + 1;
+ read_time= (double) head->file->scan_time() + scan_time + 1.1;
if (head->force_index)
scan_time= read_time= DBL_MAX;
if (limit < records)
- read_time=(double) records+scan_time+1; // Force to use index
+ read_time= (double) records + scan_time + 1; // Force to use index
else if (read_time <= 2.0 && !force_quick_range)
DBUG_RETURN(0); /* No need for quick select */
@@ -642,8 +1664,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
keys_to_use.intersect(head->keys_in_use_for_query);
if (!keys_to_use.is_clear_all())
{
- MEM_ROOT *old_root,alloc;
- SEL_TREE *tree;
+ MEM_ROOT alloc;
+ SEL_TREE *tree= NULL;
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
@@ -657,22 +1679,30 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
param.table=head;
param.keys=0;
param.mem_root= &alloc;
+ param.old_root= thd->mem_root;
+ param.needed_reg= &needed_reg;
+ param.imerge_cost_buff_size= 0;
+
thd->no_errors=1; // Don't warn about NULL
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
- if (!(param.key_parts = (KEY_PART*) alloc_root(&alloc,
- sizeof(KEY_PART)*
- head->key_parts)))
+ if (!(param.key_parts= (KEY_PART*) alloc_root(&alloc,
+ sizeof(KEY_PART)*
+ head->s->key_parts)) ||
+ fill_used_fields_bitmap(&param))
{
thd->no_errors=0;
free_root(&alloc,MYF(0)); // Return memory & allocator
DBUG_RETURN(0); // Can't use range
}
key_parts= param.key_parts;
- old_root= thd->mem_root;
thd->mem_root= &alloc;
+ /*
+ Make an array with description of all key parts of all table keys.
+ This is used in get_mm_parts function.
+ */
key_info= head->key_info;
- for (idx=0 ; idx < head->keys ; idx++, key_info++)
+ for (idx=0 ; idx < head->s->keys ; idx++, key_info++)
{
KEY_PART_INFO *key_part_info;
if (!keys_to_use.is_set(idx))
@@ -698,81 +1728,143 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
}
param.key_parts_end=key_parts;
- if ((tree=get_mm_tree(&param,cond)))
+ /* Calculate cost of full index read for the shortest covering index */
+ if (!head->used_keys.is_clear_all())
{
- if (tree->type == SEL_TREE::IMPOSSIBLE)
+ int key_for_use= find_shortest_key(head, &head->used_keys);
+ double key_read_time= (get_index_only_read_time(&param, records,
+ key_for_use) +
+ (double) records / TIME_FOR_COMPARE);
+ DBUG_PRINT("info", ("'all'+'using index' scan will be using key %d, "
+ "read time %g", key_for_use, key_read_time));
+ if (key_read_time < read_time)
+ read_time= key_read_time;
+ }
+
+ TABLE_READ_PLAN *best_trp= NULL;
+ TRP_GROUP_MIN_MAX *group_trp;
+ double best_read_time= read_time;
+
+ if (cond)
+ {
+ if ((tree= get_mm_tree(&param,cond)))
{
- records=0L; // Return -1 from this function
- read_time= (double) HA_POS_ERROR;
+ if (tree->type == SEL_TREE::IMPOSSIBLE)
+ {
+ records=0L; /* Return -1 from this function. */
+ read_time= (double) HA_POS_ERROR;
+ goto free_mem;
+ }
+ if (tree->type != SEL_TREE::KEY &&
+ tree->type != SEL_TREE::KEY_SMALLER)
+ goto free_mem;
}
- else if (tree->type == SEL_TREE::KEY ||
- tree->type == SEL_TREE::KEY_SMALLER)
+ }
+
+ /*
+ Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
+ Notice that it can be constructed no matter if there is a range tree.
+ */
+ group_trp= get_best_group_min_max(&param, tree);
+ if (group_trp && group_trp->read_cost < best_read_time)
+ {
+ best_trp= group_trp;
+ best_read_time= best_trp->read_cost;
+ }
+
+ if (tree)
+ {
+ /*
+ It is possible to use a range-based quick select (but it might be
+ slower than 'all' table scan).
+ */
+ if (tree->merges.is_empty())
+ {
+ TRP_RANGE *range_trp;
+ TRP_ROR_INTERSECT *rori_trp;
+ bool can_build_covering= FALSE;
+
+ /* Get best 'range' plan and prepare data for making other plans */
+ if ((range_trp= get_key_scans_params(&param, tree, FALSE,
+ best_read_time)))
+ {
+ best_trp= range_trp;
+ best_read_time= best_trp->read_cost;
+ }
+
+ /*
+ Simultaneous key scans and row deletes on several handler
+ objects are not allowed so don't use ROR-intersection for
+ table deletes.
+ */
+ if ((thd->lex->sql_command != SQLCOM_DELETE))
+#ifdef NOT_USED
+ if ((thd->lex->sql_command != SQLCOM_UPDATE))
+#endif
+ {
+ /*
+ Get best non-covering ROR-intersection plan and prepare data for
+ building covering ROR-intersection.
+ */
+ if ((rori_trp= get_best_ror_intersect(&param, tree, best_read_time,
+ &can_build_covering)))
+ {
+ best_trp= rori_trp;
+ best_read_time= best_trp->read_cost;
+ /*
+ Try constructing covering ROR-intersect only if it looks possible
+ and worth doing.
+ */
+ if (!rori_trp->is_covering && can_build_covering &&
+ (rori_trp= get_best_covering_ror_intersect(&param, tree,
+ best_read_time)))
+ best_trp= rori_trp;
+ }
+ }
+ }
+ else
{
- SEL_ARG **key,**end,**best_key=0;
+ /* Try creating index_merge/ROR-union scan. */
+ SEL_IMERGE *imerge;
+ TABLE_READ_PLAN *best_conj_trp= NULL, *new_conj_trp;
+ LINT_INIT(new_conj_trp); /* no empty index_merge lists possible */
+
+ DBUG_PRINT("info",("No range reads possible,"
+ " trying to construct index_merge"));
+ List_iterator_fast<SEL_IMERGE> it(tree->merges);
+ while ((imerge= it++))
+ {
+ new_conj_trp= get_best_disjunct_quick(&param, imerge, best_read_time);
+ if (!best_conj_trp || (new_conj_trp && new_conj_trp->read_cost <
+ best_conj_trp->read_cost))
+ best_conj_trp= new_conj_trp;
+ }
+ if (best_conj_trp)
+ best_trp= best_conj_trp;
+ }
+ }
+ thd->mem_root= param.old_root;
- for (idx=0,key=tree->keys, end=key+param.keys ;
- key != end ;
- key++,idx++)
- {
- ha_rows found_records;
- double found_read_time;
- if (*key)
- {
- uint keynr= param.real_keynr[idx];
- if ((*key)->type == SEL_ARG::MAYBE_KEY ||
- (*key)->maybe_flag)
- needed_reg.set_bit(keynr);
-
- found_records=check_quick_select(&param, idx, *key);
- if (found_records != HA_POS_ERROR && found_records > 2 &&
- head->used_keys.is_set(keynr) &&
- (head->file->index_flags(keynr, param.max_key_part, 1) &
- HA_KEYREAD_ONLY))
- {
- /*
- We can resolve this by only reading through this key.
- Assume that we will read trough the whole key range
- and that all key blocks are half full (normally things are
- much better).
- */
- uint keys_per_block= (head->file->block_size/2/
- (head->key_info[keynr].key_length+
- head->file->ref_length) + 1);
- found_read_time=((double) (found_records+keys_per_block-1)/
- (double) keys_per_block);
- }
- else
- found_read_time= (head->file->read_time(keynr,
- param.range_count,
- 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=found_read_time;
- records=found_records;
- best_key=key;
- }
- }
- }
- if (best_key && records)
- {
- if ((quick=get_quick_select(&param,(uint) (best_key-tree->keys),
- *best_key)))
- {
- quick->records=records;
- quick->read_time=read_time;
- }
- }
+ /* If we got a read plan, create a quick select from it. */
+ if (best_trp)
+ {
+ records= best_trp->records;
+ if (!(quick= best_trp->make_quick(&param, TRUE)) || quick->init())
+ {
+ delete quick;
+ quick= NULL;
}
}
+
+ free_mem:
free_root(&alloc,MYF(0)); // Return memory & allocator
- thd->mem_root= old_root;
+ thd->mem_root= param.old_root;
thd->no_errors=0;
}
- DBUG_EXECUTE("info",print_quick(quick,&needed_reg););
+
+ DBUG_EXECUTE("info", print_quick(quick, &needed_reg););
+
/*
Assume that if the user is using 'limit' we will only need to scan
limit rows if we are using a key
@@ -780,11 +1872,1597 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_RETURN(records ? test(quick) : -1);
}
+
+/*
+ Get cost of 'sweep' full records retrieval.
+ SYNOPSIS
+ get_sweep_read_cost()
+ param Parameter from test_quick_select
+ records # of records to be retrieved
+ RETURN
+ cost of sweep
+*/
+
+double get_sweep_read_cost(const PARAM *param, ha_rows records)
+{
+ double result;
+ DBUG_ENTER("get_sweep_read_cost");
+ if (param->table->file->primary_key_is_clustered())
+ {
+ result= param->table->file->read_time(param->table->s->primary_key,
+ records, records);
+ }
+ else
+ {
+ double n_blocks=
+ ceil(ulonglong2double(param->table->file->data_file_length) / IO_SIZE);
+ double busy_blocks=
+ n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(records)));
+ if (busy_blocks < 1.0)
+ busy_blocks= 1.0;
+ DBUG_PRINT("info",("sweep: nblocks=%g, busy_blocks=%g", n_blocks,
+ busy_blocks));
+ /*
+ Disabled: Bail out if # of blocks to read is bigger than # of blocks in
+ table data file.
+ if (max_cost != DBL_MAX && (busy_blocks+index_reads_cost) >= n_blocks)
+ return 1;
+ */
+ JOIN *join= param->thd->lex->select_lex.join;
+ if (!join || join->tables == 1)
+ {
+ /* No join, assume reading is done in one 'sweep' */
+ result= busy_blocks*(DISK_SEEK_BASE_COST +
+ DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
+ }
+ else
+ {
+ /*
+ Possibly this is a join with source table being non-last table, so
+ assume that disk seeks are random here.
+ */
+ result= busy_blocks;
+ }
+ }
+ DBUG_PRINT("info",("returning cost=%g", result));
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Get best plan for a SEL_IMERGE disjunctive expression.
+ SYNOPSIS
+ get_best_disjunct_quick()
+ param Parameter from check_quick_select function
+ imerge Expression to use
+ read_time Don't create scans with cost > read_time
+
+ NOTES
+ index_merge cost is calculated as follows:
+ index_merge_cost =
+ cost(index_reads) + (see #1)
+ cost(rowid_to_row_scan) + (see #2)
+ cost(unique_use) (see #3)
+
+ 1. cost(index_reads) =SUM_i(cost(index_read_i))
+ For non-CPK scans,
+ cost(index_read_i) = {cost of ordinary 'index only' scan}
+ For CPK scan,
+ cost(index_read_i) = {cost of non-'index only' scan}
+
+ 2. cost(rowid_to_row_scan)
+ If table PK is clustered then
+ cost(rowid_to_row_scan) =
+ {cost of ordinary clustered PK scan with n_ranges=n_rows}
+
+ Otherwise, we use the following model to calculate costs:
+ We need to retrieve n_rows rows from file that occupies n_blocks blocks.
+ We assume that offsets of rows we need are independent variates with
+ uniform distribution in [0..max_file_offset] range.
+
+ We'll denote block as "busy" if it contains row(s) we need to retrieve
+ and "empty" if doesn't contain rows we need.
+
+ Probability that a block is empty is (1 - 1/n_blocks)^n_rows (this
+ applies to any block in file). Let x_i be a variate taking value 1 if
+ block #i is empty and 0 otherwise.
+
+ Then E(x_i) = (1 - 1/n_blocks)^n_rows;
+
+ E(n_empty_blocks) = E(sum(x_i)) = sum(E(x_i)) =
+ = n_blocks * ((1 - 1/n_blocks)^n_rows) =
+ ~= n_blocks * exp(-n_rows/n_blocks).
+
+ E(n_busy_blocks) = n_blocks*(1 - (1 - 1/n_blocks)^n_rows) =
+ ~= n_blocks * (1 - exp(-n_rows/n_blocks)).
+
+ Average size of "hole" between neighbor non-empty blocks is
+ E(hole_size) = n_blocks/E(n_busy_blocks).
+
+ The total cost of reading all needed blocks in one "sweep" is:
+
+ E(n_busy_blocks)*
+ (DISK_SEEK_BASE_COST + DISK_SEEK_PROP_COST*n_blocks/E(n_busy_blocks)).
+
+ 3. Cost of Unique use is calculated in Unique::get_use_cost function.
+
+ ROR-union cost is calculated in the same way index_merge, but instead of
+ Unique a priority queue is used.
+
+ RETURN
+ Created read plan
+ NULL - Out of memory or no read scan could be built.
+*/
+
+static
+TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
+ double read_time)
+{
+ SEL_TREE **ptree;
+ TRP_INDEX_MERGE *imerge_trp= NULL;
+ uint n_child_scans= imerge->trees_next - imerge->trees;
+ TRP_RANGE **range_scans;
+ TRP_RANGE **cur_child;
+ TRP_RANGE **cpk_scan= NULL;
+ bool imerge_too_expensive= FALSE;
+ double imerge_cost= 0.0;
+ ha_rows cpk_scan_records= 0;
+ ha_rows non_cpk_scan_records= 0;
+ bool pk_is_clustered= param->table->file->primary_key_is_clustered();
+ bool all_scans_ror_able= TRUE;
+ bool all_scans_rors= TRUE;
+ uint unique_calc_buff_size;
+ TABLE_READ_PLAN **roru_read_plans;
+ TABLE_READ_PLAN **cur_roru_plan;
+ double roru_index_costs;
+ ha_rows roru_total_records;
+ double roru_intersect_part= 1.0;
+ DBUG_ENTER("get_best_disjunct_quick");
+ DBUG_PRINT("info", ("Full table scan cost =%g", read_time));
+
+ if (!(range_scans= (TRP_RANGE**)alloc_root(param->mem_root,
+ sizeof(TRP_RANGE*)*
+ n_child_scans)))
+ DBUG_RETURN(NULL);
+ /*
+ Collect best 'range' scan for each of disjuncts, and, while doing so,
+ analyze possibility of ROR scans. Also calculate some values needed by
+ other parts of the code.
+ */
+ for (ptree= imerge->trees, cur_child= range_scans;
+ ptree != imerge->trees_next;
+ ptree++, cur_child++)
+ {
+ DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
+ "tree in SEL_IMERGE"););
+ if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, read_time)))
+ {
+ /*
+ One of index scans in this index_merge is more expensive than entire
+ table read for another available option. The entire index_merge (and
+ any possible ROR-union) will be more expensive then, too. We continue
+ here only to update SQL_SELECT members.
+ */
+ imerge_too_expensive= TRUE;
+ }
+ if (imerge_too_expensive)
+ continue;
+
+ imerge_cost += (*cur_child)->read_cost;
+ all_scans_ror_able &= ((*ptree)->n_ror_scans > 0);
+ all_scans_rors &= (*cur_child)->is_ror;
+ if (pk_is_clustered &&
+ param->real_keynr[(*cur_child)->key_idx] ==
+ param->table->s->primary_key)
+ {
+ cpk_scan= cur_child;
+ cpk_scan_records= (*cur_child)->records;
+ }
+ else
+ non_cpk_scan_records += (*cur_child)->records;
+ }
+
+ DBUG_PRINT("info", ("index_merge scans cost=%g", imerge_cost));
+ if (imerge_too_expensive || (imerge_cost > read_time) ||
+ (non_cpk_scan_records+cpk_scan_records >= param->table->file->records) &&
+ read_time != DBL_MAX)
+ {
+ /*
+ Bail out if it is obvious that both index_merge and ROR-union will be
+ more expensive
+ */
+ DBUG_PRINT("info", ("Sum of index_merge scans is more expensive than "
+ "full table scan, bailing out"));
+ DBUG_RETURN(NULL);
+ }
+ if (all_scans_rors)
+ {
+ roru_read_plans= (TABLE_READ_PLAN**)range_scans;
+ goto skip_to_ror_scan;
+ }
+ if (cpk_scan)
+ {
+ /*
+ Add one ROWID comparison for each row retrieved on non-CPK scan. (it
+ is done in QUICK_RANGE_SELECT::row_in_ranges)
+ */
+ imerge_cost += non_cpk_scan_records / TIME_FOR_COMPARE_ROWID;
+ }
+
+ /* Calculate cost(rowid_to_row_scan) */
+ imerge_cost += get_sweep_read_cost(param, non_cpk_scan_records);
+ DBUG_PRINT("info",("index_merge cost with rowid-to-row scan: %g",
+ imerge_cost));
+ if (imerge_cost > read_time)
+ goto build_ror_index_merge;
+
+ /* Add Unique operations cost */
+ unique_calc_buff_size=
+ Unique::get_cost_calc_buff_size(non_cpk_scan_records,
+ param->table->file->ref_length,
+ param->thd->variables.sortbuff_size);
+ if (param->imerge_cost_buff_size < unique_calc_buff_size)
+ {
+ if (!(param->imerge_cost_buff= (uint*)alloc_root(param->mem_root,
+ unique_calc_buff_size)))
+ DBUG_RETURN(NULL);
+ param->imerge_cost_buff_size= unique_calc_buff_size;
+ }
+
+ imerge_cost +=
+ Unique::get_use_cost(param->imerge_cost_buff, non_cpk_scan_records,
+ param->table->file->ref_length,
+ param->thd->variables.sortbuff_size);
+ DBUG_PRINT("info",("index_merge total cost: %g (wanted: less then %g)",
+ imerge_cost, read_time));
+ if (imerge_cost < read_time)
+ {
+ if ((imerge_trp= new (param->mem_root)TRP_INDEX_MERGE))
+ {
+ imerge_trp->read_cost= imerge_cost;
+ imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
+ imerge_trp->records= min(imerge_trp->records,
+ param->table->file->records);
+ imerge_trp->range_scans= range_scans;
+ imerge_trp->range_scans_end= range_scans + n_child_scans;
+ read_time= imerge_cost;
+ }
+ }
+
+build_ror_index_merge:
+ if (!all_scans_ror_able || param->thd->lex->sql_command == SQLCOM_DELETE)
+ DBUG_RETURN(imerge_trp);
+
+ /* Ok, it is possible to build a ROR-union, try it. */
+ bool dummy;
+ if (!(roru_read_plans=
+ (TABLE_READ_PLAN**)alloc_root(param->mem_root,
+ sizeof(TABLE_READ_PLAN*)*
+ n_child_scans)))
+ DBUG_RETURN(imerge_trp);
+skip_to_ror_scan:
+ roru_index_costs= 0.0;
+ roru_total_records= 0;
+ cur_roru_plan= roru_read_plans;
+
+ /* Find 'best' ROR scan for each of trees in disjunction */
+ for (ptree= imerge->trees, cur_child= range_scans;
+ ptree != imerge->trees_next;
+ ptree++, cur_child++, cur_roru_plan++)
+ {
+ /*
+ Assume the best ROR scan is the one that has cheapest full-row-retrieval
+ scan cost.
+ Also accumulate index_only scan costs as we'll need them to calculate
+ overall index_intersection cost.
+ */
+ double cost;
+ if ((*cur_child)->is_ror)
+ {
+ /* Ok, we have index_only cost, now get full rows scan cost */
+ cost= param->table->file->
+ read_time(param->real_keynr[(*cur_child)->key_idx], 1,
+ (*cur_child)->records) +
+ rows2double((*cur_child)->records) / TIME_FOR_COMPARE;
+ }
+ else
+ cost= read_time;
+
+ TABLE_READ_PLAN *prev_plan= *cur_child;
+ if (!(*cur_roru_plan= get_best_ror_intersect(param, *ptree, cost,
+ &dummy)))
+ {
+ if (prev_plan->is_ror)
+ *cur_roru_plan= prev_plan;
+ else
+ DBUG_RETURN(imerge_trp);
+ roru_index_costs += (*cur_roru_plan)->read_cost;
+ }
+ else
+ roru_index_costs +=
+ ((TRP_ROR_INTERSECT*)(*cur_roru_plan))->index_scan_costs;
+ roru_total_records += (*cur_roru_plan)->records;
+ roru_intersect_part *= (*cur_roru_plan)->records /
+ param->table->file->records;
+ }
+
+ /*
+ rows to retrieve=
+ SUM(rows_in_scan_i) - table_rows * PROD(rows_in_scan_i / table_rows).
+ This is valid because index_merge construction guarantees that conditions
+ in disjunction do not share key parts.
+ */
+ roru_total_records -= (ha_rows)(roru_intersect_part*
+ param->table->file->records);
+ /* ok, got a ROR read plan for each of the disjuncts
+ Calculate cost:
+ cost(index_union_scan(scan_1, ... scan_n)) =
+ SUM_i(cost_of_index_only_scan(scan_i)) +
+ queue_use_cost(rowid_len, n) +
+ cost_of_row_retrieval
+ See get_merge_buffers_cost function for queue_use_cost formula derivation.
+ */
+
+ double roru_total_cost;
+ roru_total_cost= roru_index_costs +
+ rows2double(roru_total_records)*log((double)n_child_scans) /
+ (TIME_FOR_COMPARE_ROWID * M_LN2) +
+ get_sweep_read_cost(param, roru_total_records);
+
+ DBUG_PRINT("info", ("ROR-union: cost %g, %d members", roru_total_cost,
+ n_child_scans));
+ TRP_ROR_UNION* roru;
+ if (roru_total_cost < read_time)
+ {
+ if ((roru= new (param->mem_root) TRP_ROR_UNION))
+ {
+ roru->first_ror= roru_read_plans;
+ roru->last_ror= roru_read_plans + n_child_scans;
+ roru->read_cost= roru_total_cost;
+ roru->records= roru_total_records;
+ DBUG_RETURN(roru);
+ }
+ }
+ DBUG_RETURN(imerge_trp);
+}
+
+
+/*
+ Calculate cost of 'index only' scan for given index and number of records.
+
+ SYNOPSIS
+ get_index_only_read_time()
+ param parameters structure
+ records #of records to read
+ keynr key to read
+
+ NOTES
+ It is assumed that we will read trough the whole key range and that all
+ key blocks are half full (normally things are much better). It is also
+ assumed that each time we read the next key from the index, the handler
+ performs a random seek, thus the cost is proportional to the number of
+ blocks read.
+
+ TODO:
+ Move this to handler->read_time() by adding a flag 'index-only-read' to
+ this call. The reason for doing this is that the current function doesn't
+ handle the case when the row is stored in the b-tree (like in innodb
+ clustered index)
+*/
+
+static double get_index_only_read_time(const PARAM* param, ha_rows records,
+ int keynr)
+{
+ double read_time;
+ uint keys_per_block= (param->table->file->block_size/2/
+ (param->table->key_info[keynr].key_length+
+ param->table->file->ref_length) + 1);
+ read_time=((double) (records+keys_per_block-1)/
+ (double) keys_per_block);
+ return read_time;
+}
+
+
+typedef struct st_ror_scan_info
+{
+ uint idx; /* # of used key in param->keys */
+ uint keynr; /* # of used key in table */
+ ha_rows records; /* estimate of # records this scan will return */
+
+ /* Set of intervals over key fields that will be used for row retrieval. */
+ SEL_ARG *sel_arg;
+
+ /* Fields used in the query and covered by this ROR scan. */
+ MY_BITMAP covered_fields;
+ uint used_fields_covered; /* # of set bits in covered_fields */
+ int key_rec_length; /* length of key record (including rowid) */
+
+ /*
+ Cost of reading all index records with values in sel_arg intervals set
+ (assuming there is no need to access full table records)
+ */
+ double index_read_cost;
+ uint first_uncovered_field; /* first unused bit in covered_fields */
+ uint key_components; /* # of parts in the key */
+} ROR_SCAN_INFO;
+
+
+/*
+ Create ROR_SCAN_INFO* structure with a single ROR scan on index idx using
+ sel_arg set of intervals.
+
+ SYNOPSIS
+ make_ror_scan()
+ param Parameter from test_quick_select function
+ idx Index of key in param->keys
+ sel_arg Set of intervals for a given key
+
+ RETURN
+ NULL - out of memory
+ ROR scan structure containing a scan for {idx, sel_arg}
+*/
+
+static
+ROR_SCAN_INFO *make_ror_scan(const PARAM *param, int idx, SEL_ARG *sel_arg)
+{
+ ROR_SCAN_INFO *ror_scan;
+ uchar *bitmap_buf;
+ uint keynr;
+ DBUG_ENTER("make_ror_scan");
+
+ if (!(ror_scan= (ROR_SCAN_INFO*)alloc_root(param->mem_root,
+ sizeof(ROR_SCAN_INFO))))
+ DBUG_RETURN(NULL);
+
+ ror_scan->idx= idx;
+ ror_scan->keynr= keynr= param->real_keynr[idx];
+ ror_scan->key_rec_length= (param->table->key_info[keynr].key_length +
+ param->table->file->ref_length);
+ ror_scan->sel_arg= sel_arg;
+ ror_scan->records= param->table->quick_rows[keynr];
+
+ if (!(bitmap_buf= (uchar*)alloc_root(param->mem_root,
+ param->fields_bitmap_size)))
+ DBUG_RETURN(NULL);
+
+ if (bitmap_init(&ror_scan->covered_fields, bitmap_buf,
+ param->fields_bitmap_size*8, FALSE))
+ DBUG_RETURN(NULL);
+ bitmap_clear_all(&ror_scan->covered_fields);
+
+ KEY_PART_INFO *key_part= param->table->key_info[keynr].key_part;
+ KEY_PART_INFO *key_part_end= key_part +
+ param->table->key_info[keynr].key_parts;
+ for (;key_part != key_part_end; ++key_part)
+ {
+ if (bitmap_is_set(&param->needed_fields, key_part->fieldnr))
+ bitmap_set_bit(&ror_scan->covered_fields, key_part->fieldnr);
+ }
+ ror_scan->index_read_cost=
+ get_index_only_read_time(param, param->table->quick_rows[ror_scan->keynr],
+ ror_scan->keynr);
+ DBUG_RETURN(ror_scan);
+}
+
+
+/*
+ Compare two ROR_SCAN_INFO** by E(#records_matched) * key_record_length.
+ SYNOPSIS
+ cmp_ror_scan_info()
+ a ptr to first compared value
+ b ptr to second compared value
+
+ RETURN
+ -1 a < b
+ 0 a = b
+ 1 a > b
+*/
+
+static int cmp_ror_scan_info(ROR_SCAN_INFO** a, ROR_SCAN_INFO** b)
+{
+ double val1= rows2double((*a)->records) * (*a)->key_rec_length;
+ double val2= rows2double((*b)->records) * (*b)->key_rec_length;
+ return (val1 < val2)? -1: (val1 == val2)? 0 : 1;
+}
+
+/*
+ Compare two ROR_SCAN_INFO** by
+ (#covered fields in F desc,
+ #components asc,
+ number of first not covered component asc)
+
+ SYNOPSIS
+ cmp_ror_scan_info_covering()
+ a ptr to first compared value
+ b ptr to second compared value
+
+ RETURN
+ -1 a < b
+ 0 a = b
+ 1 a > b
+*/
+
+static int cmp_ror_scan_info_covering(ROR_SCAN_INFO** a, ROR_SCAN_INFO** b)
+{
+ if ((*a)->used_fields_covered > (*b)->used_fields_covered)
+ return -1;
+ if ((*a)->used_fields_covered < (*b)->used_fields_covered)
+ return 1;
+ if ((*a)->key_components < (*b)->key_components)
+ return -1;
+ if ((*a)->key_components > (*b)->key_components)
+ return 1;
+ if ((*a)->first_uncovered_field < (*b)->first_uncovered_field)
+ return -1;
+ if ((*a)->first_uncovered_field > (*b)->first_uncovered_field)
+ return 1;
+ return 0;
+}
+
+
+/* Auxiliary structure for incremental ROR-intersection creation */
+typedef struct
+{
+ const PARAM *param;
+ MY_BITMAP covered_fields; /* union of fields covered by all scans */
+ /*
+ Fraction of table records that satisfies conditions of all scans.
+ This is the number of full records that will be retrieved if a
+ non-index_only index intersection will be employed.
+ */
+ double out_rows;
+ /* TRUE if covered_fields is a superset of needed_fields */
+ bool is_covering;
+
+ ha_rows index_records; /* sum(#records to look in indexes) */
+ double index_scan_costs; /* SUM(cost of 'index-only' scans) */
+ double total_cost;
+} ROR_INTERSECT_INFO;
+
+
+/*
+ Allocate a ROR_INTERSECT_INFO and initialize it to contain zero scans.
+
+ SYNOPSIS
+ ror_intersect_init()
+ param Parameter from test_quick_select
+
+ RETURN
+ allocated structure
+ NULL on error
+*/
+
+static
+ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param)
+{
+ ROR_INTERSECT_INFO *info;
+ uchar* buf;
+ if (!(info= (ROR_INTERSECT_INFO*)alloc_root(param->mem_root,
+ sizeof(ROR_INTERSECT_INFO))))
+ return NULL;
+ info->param= param;
+ if (!(buf= (uchar*)alloc_root(param->mem_root, param->fields_bitmap_size)))
+ return NULL;
+ if (bitmap_init(&info->covered_fields, buf, param->fields_bitmap_size*8,
+ FALSE))
+ return NULL;
+ info->is_covering= FALSE;
+ info->index_scan_costs= 0.0;
+ info->index_records= 0;
+ info->out_rows= param->table->file->records;
+ bitmap_clear_all(&info->covered_fields);
+ return info;
+}
+
+void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
+{
+ dst->param= src->param;
+ memcpy(dst->covered_fields.bitmap, src->covered_fields.bitmap,
+ src->covered_fields.bitmap_size);
+ dst->out_rows= src->out_rows;
+ dst->is_covering= src->is_covering;
+ dst->index_records= src->index_records;
+ dst->index_scan_costs= src->index_scan_costs;
+ dst->total_cost= src->total_cost;
+}
+
+
+/*
+ Get selectivity of a ROR scan wrt ROR-intersection.
+
+ SYNOPSIS
+ ror_scan_selectivity()
+ info ROR-interection
+ scan ROR scan
+
+ NOTES
+ Suppose we have a condition on several keys
+ cond=k_11=c_11 AND k_12=c_12 AND ... // parts of first key
+ k_21=c_21 AND k_22=c_22 AND ... // parts of second key
+ ...
+ k_n1=c_n1 AND k_n3=c_n3 AND ... (1) //parts of the key used by *scan
+
+ where k_ij may be the same as any k_pq (i.e. keys may have common parts).
+
+ A full row is retrieved if entire condition holds.
+
+ The recursive procedure for finding P(cond) is as follows:
+
+ First step:
+ Pick 1st part of 1st key and break conjunction (1) into two parts:
+ cond= (k_11=c_11 AND R)
+
+ Here R may still contain condition(s) equivalent to k_11=c_11.
+ Nevertheless, the following holds:
+
+ P(k_11=c_11 AND R) = P(k_11=c_11) * P(R | k_11=c_11).
+
+ Mark k_11 as fixed field (and satisfied condition) F, save P(F),
+ save R to be cond and proceed to recursion step.
+
+ Recursion step:
+ We have a set of fixed fields/satisfied conditions) F, probability P(F),
+ and remaining conjunction R
+ Pick next key part on current key and its condition "k_ij=c_ij".
+ We will add "k_ij=c_ij" into F and update P(F).
+ Lets denote k_ij as t, R = t AND R1, where R1 may still contain t. Then
+
+ P((t AND R1)|F) = P(t|F) * P(R1|t|F) = P(t|F) * P(R1|(t AND F)) (2)
+
+ (where '|' mean conditional probability, not "or")
+
+ Consider the first multiplier in (2). One of the following holds:
+ a) F contains condition on field used in t (i.e. t AND F = F).
+ Then P(t|F) = 1
+
+ b) F doesn't contain condition on field used in t. Then F and t are
+ considered independent.
+
+ P(t|F) = P(t|(fields_before_t_in_key AND other_fields)) =
+ = P(t|fields_before_t_in_key).
+
+ P(t|fields_before_t_in_key) = #records(fields_before_t_in_key) /
+ #records(fields_before_t_in_key, t)
+
+ The second multiplier is calculated by applying this step recursively.
+
+ IMPLEMENTATION
+ This function calculates the result of application of the "recursion step"
+ described above for all fixed key members of a single key, accumulating set
+ of covered fields, selectivity, etc.
+
+ The calculation is conducted as follows:
+ Lets denote #records(keypart1, ... keypartK) as n_k. We need to calculate
+
+ n_{k1} n_{k_2}
+ --------- * --------- * .... (3)
+ n_{k1-1} n_{k2_1}
+
+ where k1,k2,... are key parts which fields were not yet marked as fixed
+ ( this is result of application of option b) of the recursion step for
+ parts of a single key).
+ Since it is reasonable to expect that most of the fields are not marked
+ as fixed, we calculate (3) as
+
+ n_{i1} n_{i_2}
+ (3) = n_{max_key_part} / ( --------- * --------- * .... )
+ n_{i1-1} n_{i2_1}
+
+ where i1,i2, .. are key parts that were already marked as fixed.
+
+ In order to minimize number of expensive records_in_range calls we group
+ and reduce adjacent fractions.
+
+ RETURN
+ Selectivity of given ROR scan.
+
+*/
+
+static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
+ const ROR_SCAN_INFO *scan)
+{
+ double selectivity_mult= 1.0;
+ KEY_PART_INFO *key_part= info->param->table->key_info[scan->keynr].key_part;
+ byte key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */
+ char *key_ptr= (char*) key_val;
+ SEL_ARG *sel_arg, *tuple_arg= NULL;
+ bool cur_covered;
+ bool prev_covered= test(bitmap_is_set(&info->covered_fields,
+ key_part->fieldnr));
+ key_range min_range;
+ key_range max_range;
+ min_range.key= (byte*) key_val;
+ min_range.flag= HA_READ_KEY_EXACT;
+ max_range.key= (byte*) key_val;
+ max_range.flag= HA_READ_AFTER_KEY;
+ ha_rows prev_records= info->param->table->file->records;
+ DBUG_ENTER("ror_intersect_selectivity");
+
+ for (sel_arg= scan->sel_arg; sel_arg;
+ sel_arg= sel_arg->next_key_part)
+ {
+ DBUG_PRINT("info",("sel_arg step"));
+ cur_covered= test(bitmap_is_set(&info->covered_fields,
+ key_part[sel_arg->part].fieldnr));
+ if (cur_covered != prev_covered)
+ {
+ /* create (part1val, ..., part{n-1}val) tuple. */
+ ha_rows records;
+ if (!tuple_arg)
+ {
+ tuple_arg= scan->sel_arg;
+ /* Here we use the length of the first key part */
+ tuple_arg->store_min(key_part->store_length, &key_ptr, 0);
+ }
+ while (tuple_arg->next_key_part != sel_arg)
+ {
+ tuple_arg= tuple_arg->next_key_part;
+ tuple_arg->store_min(key_part[tuple_arg->part].store_length, &key_ptr, 0);
+ }
+ min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val);
+ records= (info->param->table->file->
+ records_in_range(scan->keynr, &min_range, &max_range));
+ if (cur_covered)
+ {
+ /* uncovered -> covered */
+ double tmp= rows2double(records)/rows2double(prev_records);
+ DBUG_PRINT("info", ("Selectivity multiplier: %g", tmp));
+ selectivity_mult *= tmp;
+ prev_records= HA_POS_ERROR;
+ }
+ else
+ {
+ /* covered -> uncovered */
+ prev_records= records;
+ }
+ }
+ prev_covered= cur_covered;
+ }
+ if (!prev_covered)
+ {
+ double tmp= rows2double(info->param->table->quick_rows[scan->keynr]) /
+ rows2double(prev_records);
+ DBUG_PRINT("info", ("Selectivity multiplier: %g", tmp));
+ selectivity_mult *= tmp;
+ }
+ DBUG_PRINT("info", ("Returning multiplier: %g", selectivity_mult));
+ DBUG_RETURN(selectivity_mult);
+}
+
+
+/*
+ Check if adding a ROR scan to a ROR-intersection reduces its cost of
+ ROR-intersection and if yes, update parameters of ROR-intersection,
+ including its cost.
+
+ SYNOPSIS
+ ror_intersect_add()
+ param Parameter from test_quick_select
+ info ROR-intersection structure to add the scan to.
+ ror_scan ROR scan info to add.
+ is_cpk_scan If TRUE, add the scan as CPK scan (this can be inferred
+ from other parameters and is passed separately only to
+ avoid duplicating the inference code)
+
+ NOTES
+ Adding a ROR scan to ROR-intersect "makes sense" iff the cost of ROR-
+ intersection decreases. The cost of ROR-intersection is calculated as
+ follows:
+
+ cost= SUM_i(key_scan_cost_i) + cost_of_full_rows_retrieval
+
+ When we add a scan the first increases and the second decreases.
+
+ cost_of_full_rows_retrieval=
+ (union of indexes used covers all needed fields) ?
+ cost_of_sweep_read(E(rows_to_retrieve), rows_in_table) :
+ 0
+
+ E(rows_to_retrieve) = #rows_in_table * ror_scan_selectivity(null, scan1) *
+ ror_scan_selectivity({scan1}, scan2) * ... *
+ ror_scan_selectivity({scan1,...}, scanN).
+ RETURN
+ TRUE ROR scan added to ROR-intersection, cost updated.
+ FALSE It doesn't make sense to add this ROR scan to this ROR-intersection.
+*/
+
+static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
+ ROR_SCAN_INFO* ror_scan, bool is_cpk_scan)
+{
+ double selectivity_mult= 1.0;
+
+ DBUG_ENTER("ror_intersect_add");
+ DBUG_PRINT("info", ("Current out_rows= %g", info->out_rows));
+ DBUG_PRINT("info", ("Adding scan on %s",
+ info->param->table->key_info[ror_scan->keynr].name));
+ DBUG_PRINT("info", ("is_cpk_scan=%d",is_cpk_scan));
+
+ selectivity_mult = ror_scan_selectivity(info, ror_scan);
+ if (selectivity_mult == 1.0)
+ {
+ /* Don't add this scan if it doesn't improve selectivity. */
+ DBUG_PRINT("info", ("The scan doesn't improve selectivity."));
+ DBUG_RETURN(FALSE);
+ }
+
+ info->out_rows *= selectivity_mult;
+ DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost));
+
+ if (is_cpk_scan)
+ {
+ /*
+ CPK scan is used to filter out rows. We apply filtering for
+ each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID
+ per check this gives us:
+ */
+ info->index_scan_costs += rows2double(info->index_records) /
+ TIME_FOR_COMPARE_ROWID;
+ }
+ else
+ {
+ info->index_records += info->param->table->quick_rows[ror_scan->keynr];
+ info->index_scan_costs += ror_scan->index_read_cost;
+ bitmap_union(&info->covered_fields, &ror_scan->covered_fields);
+ if (!info->is_covering && bitmap_is_subset(&info->param->needed_fields,
+ &info->covered_fields))
+ {
+ DBUG_PRINT("info", ("ROR-intersect is covering now"));
+ info->is_covering= TRUE;
+ }
+ }
+
+ info->total_cost= info->index_scan_costs;
+ DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost));
+ if (!info->is_covering)
+ {
+ info->total_cost +=
+ get_sweep_read_cost(info->param, double2rows(info->out_rows));
+ DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost));
+ }
+ DBUG_PRINT("info", ("New out_rows= %g", info->out_rows));
+ DBUG_PRINT("info", ("New cost= %g, %scovering", info->total_cost,
+ info->is_covering?"" : "non-"));
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Get best ROR-intersection plan using non-covering ROR-intersection search
+ algorithm. The returned plan may be covering.
+
+ SYNOPSIS
+ get_best_ror_intersect()
+ param Parameter from test_quick_select function.
+ tree Transformed restriction condition to be used to look
+ for ROR scans.
+ read_time Do not return read plans with cost > read_time.
+ are_all_covering [out] set to TRUE if union of all scans covers all
+ fields needed by the query (and it is possible to build
+ a covering ROR-intersection)
+
+ NOTES
+ get_key_scans_params must be called before this function can be called.
+
+ When this function is called by ROR-union construction algorithm it
+ assumes it is building an uncovered ROR-intersection (and thus # of full
+ records to be retrieved is wrong here). This is a hack.
+
+ IMPLEMENTATION
+ The approximate best non-covering plan search algorithm is as follows:
+
+ find_min_ror_intersection_scan()
+ {
+ R= select all ROR scans;
+ order R by (E(#records_matched) * key_record_length).
+
+ S= first(R); -- set of scans that will be used for ROR-intersection
+ R= R-first(S);
+ min_cost= cost(S);
+ min_scan= make_scan(S);
+ while (R is not empty)
+ {
+ firstR= R - first(R);
+ if (!selectivity(S + firstR < selectivity(S)))
+ continue;
+
+ S= S + first(R);
+ if (cost(S) < min_cost)
+ {
+ min_cost= cost(S);
+ min_scan= make_scan(S);
+ }
+ }
+ return min_scan;
+ }
+
+ See ror_intersect_add function for ROR intersection costs.
+
+ Special handling for Clustered PK scans
+ Clustered PK contains all table fields, so using it as a regular scan in
+ index intersection doesn't make sense: a range scan on CPK will be less
+ expensive in this case.
+ Clustered PK scan has special handling in ROR-intersection: it is not used
+ to retrieve rows, instead its condition is used to filter row references
+ we get from scans on other keys.
+
+ RETURN
+ ROR-intersection table read plan
+ NULL if out of memory or no suitable plan found.
+*/
+
+static
+TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
+ double read_time,
+ bool *are_all_covering)
+{
+ uint idx;
+ double min_cost= DBL_MAX;
+ DBUG_ENTER("get_best_ror_intersect");
+
+ if ((tree->n_ror_scans < 2) || !param->table->file->records)
+ DBUG_RETURN(NULL);
+
+ /*
+ Step1: Collect ROR-able SEL_ARGs and create ROR_SCAN_INFO for each of
+ them. Also find and save clustered PK scan if there is one.
+ */
+ ROR_SCAN_INFO **cur_ror_scan;
+ ROR_SCAN_INFO *cpk_scan= NULL;
+ uint cpk_no;
+ bool cpk_scan_used= FALSE;
+
+ if (!(tree->ror_scans= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
+ sizeof(ROR_SCAN_INFO*)*
+ param->keys)))
+ return NULL;
+ cpk_no= ((param->table->file->primary_key_is_clustered()) ?
+ param->table->s->primary_key : MAX_KEY);
+
+ for (idx= 0, cur_ror_scan= tree->ror_scans; idx < param->keys; idx++)
+ {
+ ROR_SCAN_INFO *scan;
+ if (!tree->ror_scans_map.is_set(idx))
+ continue;
+ if (!(scan= make_ror_scan(param, idx, tree->keys[idx])))
+ return NULL;
+ if (param->real_keynr[idx] == cpk_no)
+ {
+ cpk_scan= scan;
+ tree->n_ror_scans--;
+ }
+ else
+ *(cur_ror_scan++)= scan;
+ }
+
+ tree->ror_scans_end= cur_ror_scan;
+ DBUG_EXECUTE("info",print_ror_scans_arr(param->table, "original",
+ tree->ror_scans,
+ tree->ror_scans_end););
+ /*
+ Ok, [ror_scans, ror_scans_end) is array of ptrs to initialized
+ ROR_SCAN_INFO's.
+ Step 2: Get best ROR-intersection using an approximate algorithm.
+ */
+ qsort(tree->ror_scans, tree->n_ror_scans, sizeof(ROR_SCAN_INFO*),
+ (qsort_cmp)cmp_ror_scan_info);
+ DBUG_EXECUTE("info",print_ror_scans_arr(param->table, "ordered",
+ tree->ror_scans,
+ tree->ror_scans_end););
+
+ ROR_SCAN_INFO **intersect_scans; /* ROR scans used in index intersection */
+ ROR_SCAN_INFO **intersect_scans_end;
+ if (!(intersect_scans= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
+ sizeof(ROR_SCAN_INFO*)*
+ tree->n_ror_scans)))
+ return NULL;
+ intersect_scans_end= intersect_scans;
+
+ /* Create and incrementally update ROR intersection. */
+ ROR_INTERSECT_INFO *intersect, *intersect_best;
+ if (!(intersect= ror_intersect_init(param)) ||
+ !(intersect_best= ror_intersect_init(param)))
+ return NULL;
+
+ /* [intersect_scans,intersect_scans_best) will hold the best intersection */
+ ROR_SCAN_INFO **intersect_scans_best;
+ cur_ror_scan= tree->ror_scans;
+ intersect_scans_best= intersect_scans;
+ while (cur_ror_scan != tree->ror_scans_end && !intersect->is_covering)
+ {
+ /* S= S + first(R); R= R - first(R); */
+ if (!ror_intersect_add(intersect, *cur_ror_scan, FALSE))
+ {
+ cur_ror_scan++;
+ continue;
+ }
+
+ *(intersect_scans_end++)= *(cur_ror_scan++);
+
+ if (intersect->total_cost < min_cost)
+ {
+ /* Local minimum found, save it */
+ ror_intersect_cpy(intersect_best, intersect);
+ intersect_scans_best= intersect_scans_end;
+ min_cost = intersect->total_cost;
+ }
+ }
+
+ if (intersect_scans_best == intersect_scans)
+ {
+ DBUG_PRINT("info", ("None of scans increase selectivity"));
+ DBUG_RETURN(NULL);
+ }
+
+ DBUG_EXECUTE("info",print_ror_scans_arr(param->table,
+ "best ROR-intersection",
+ intersect_scans,
+ intersect_scans_best););
+
+ *are_all_covering= intersect->is_covering;
+ uint best_num= intersect_scans_best - intersect_scans;
+ ror_intersect_cpy(intersect, intersect_best);
+
+ /*
+ Ok, found the best ROR-intersection of non-CPK key scans.
+ Check if we should add a CPK scan. If the obtained ROR-intersection is
+ covering, it doesn't make sense to add CPK scan.
+ */
+ if (cpk_scan && !intersect->is_covering)
+ {
+ if (ror_intersect_add(intersect, cpk_scan, TRUE) &&
+ (intersect->total_cost < min_cost))
+ {
+ cpk_scan_used= TRUE;
+ intersect_best= intersect; //just set pointer here
+ }
+ }
+
+ /* Ok, return ROR-intersect plan if we have found one */
+ TRP_ROR_INTERSECT *trp= NULL;
+ if (min_cost < read_time && (cpk_scan_used || best_num > 1))
+ {
+ if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT))
+ DBUG_RETURN(trp);
+ if (!(trp->first_scan=
+ (ROR_SCAN_INFO**)alloc_root(param->mem_root,
+ sizeof(ROR_SCAN_INFO*)*best_num)))
+ DBUG_RETURN(NULL);
+ memcpy(trp->first_scan, intersect_scans, best_num*sizeof(ROR_SCAN_INFO*));
+ trp->last_scan= trp->first_scan + best_num;
+ trp->is_covering= intersect_best->is_covering;
+ trp->read_cost= intersect_best->total_cost;
+ /* Prevent divisons by zero */
+ ha_rows best_rows = double2rows(intersect_best->out_rows);
+ if (!best_rows)
+ best_rows= 1;
+ trp->records= best_rows;
+ trp->index_scan_costs= intersect_best->index_scan_costs;
+ trp->cpk_scan= cpk_scan_used? cpk_scan: NULL;
+ DBUG_PRINT("info", ("Returning non-covering ROR-intersect plan:"
+ "cost %g, records %lu",
+ trp->read_cost, (ulong) trp->records));
+ }
+ DBUG_RETURN(trp);
+}
+
+
+/*
+ Get best covering ROR-intersection.
+ SYNOPSIS
+ get_best_covering_ror_intersect()
+ param Parameter from test_quick_select function.
+ tree SEL_TREE with sets of intervals for different keys.
+ read_time Don't return table read plans with cost > read_time.
+
+ RETURN
+ Best covering ROR-intersection plan
+ NULL if no plan found.
+
+ NOTES
+ get_best_ror_intersect must be called for a tree before calling this
+ function for it.
+ This function invalidates tree->ror_scans member values.
+
+ The following approximate algorithm is used:
+ I=set of all covering indexes
+ F=set of all fields to cover
+ S={}
+
+ do {
+ Order I by (#covered fields in F desc,
+ #components asc,
+ number of first not covered component asc);
+ F=F-covered by first(I);
+ S=S+first(I);
+ I=I-first(I);
+ } while F is not empty.
+*/
+
+static
+TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
+ SEL_TREE *tree,
+ double read_time)
+{
+ ROR_SCAN_INFO **ror_scan_mark;
+ ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end;
+ DBUG_ENTER("get_best_covering_ror_intersect");
+ uint nbits= param->fields_bitmap_size*8;
+
+ for (ROR_SCAN_INFO **scan= tree->ror_scans; scan != ror_scans_end; ++scan)
+ (*scan)->key_components=
+ param->table->key_info[(*scan)->keynr].key_parts;
+
+ /*
+ Run covering-ROR-search algorithm.
+ Assume set I is [ror_scan .. ror_scans_end)
+ */
+
+ /*I=set of all covering indexes */
+ ror_scan_mark= tree->ror_scans;
+
+ uchar buf[MAX_KEY/8+1];
+ MY_BITMAP covered_fields;
+ if (bitmap_init(&covered_fields, buf, nbits, FALSE))
+ DBUG_RETURN(0);
+ bitmap_clear_all(&covered_fields);
+
+ double total_cost= 0.0f;
+ ha_rows records=0;
+ bool all_covered;
+
+ DBUG_PRINT("info", ("Building covering ROR-intersection"));
+ DBUG_EXECUTE("info", print_ror_scans_arr(param->table,
+ "building covering ROR-I",
+ ror_scan_mark, ror_scans_end););
+ do {
+ /*
+ Update changed sorting info:
+ #covered fields,
+ number of first not covered component
+ Calculate and save these values for each of remaining scans.
+ */
+ for (ROR_SCAN_INFO **scan= ror_scan_mark; scan != ror_scans_end; ++scan)
+ {
+ bitmap_subtract(&(*scan)->covered_fields, &covered_fields);
+ (*scan)->used_fields_covered=
+ bitmap_bits_set(&(*scan)->covered_fields);
+ (*scan)->first_uncovered_field=
+ bitmap_get_first(&(*scan)->covered_fields);
+ }
+
+ qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*),
+ (qsort_cmp)cmp_ror_scan_info_covering);
+
+ DBUG_EXECUTE("info", print_ror_scans_arr(param->table,
+ "remaining scans",
+ ror_scan_mark, ror_scans_end););
+
+ /* I=I-first(I) */
+ total_cost += (*ror_scan_mark)->index_read_cost;
+ records += (*ror_scan_mark)->records;
+ DBUG_PRINT("info", ("Adding scan on %s",
+ param->table->key_info[(*ror_scan_mark)->keynr].name));
+ if (total_cost > read_time)
+ DBUG_RETURN(NULL);
+ /* F=F-covered by first(I) */
+ bitmap_union(&covered_fields, &(*ror_scan_mark)->covered_fields);
+ all_covered= bitmap_is_subset(&param->needed_fields, &covered_fields);
+ } while (!all_covered && (++ror_scan_mark < ror_scans_end));
+
+ if (!all_covered)
+ DBUG_RETURN(NULL); /* should not happen actually */
+
+ /*
+ Ok, [tree->ror_scans .. ror_scan) holds covering index_intersection with
+ cost total_cost.
+ */
+ DBUG_PRINT("info", ("Covering ROR-intersect scans cost: %g", total_cost));
+ DBUG_EXECUTE("info", print_ror_scans_arr(param->table,
+ "creating covering ROR-intersect",
+ tree->ror_scans, ror_scan_mark););
+
+ /* Add priority queue use cost. */
+ total_cost += rows2double(records)*
+ log((double)(ror_scan_mark - tree->ror_scans)) /
+ (TIME_FOR_COMPARE_ROWID * M_LN2);
+ DBUG_PRINT("info", ("Covering ROR-intersect full cost: %g", total_cost));
+
+ if (total_cost > read_time)
+ DBUG_RETURN(NULL);
+
+ TRP_ROR_INTERSECT *trp;
+ if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT))
+ DBUG_RETURN(trp);
+ uint best_num= (ror_scan_mark - tree->ror_scans);
+ if (!(trp->first_scan= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
+ sizeof(ROR_SCAN_INFO*)*
+ best_num)))
+ DBUG_RETURN(NULL);
+ memcpy(trp->first_scan, ror_scan_mark, best_num*sizeof(ROR_SCAN_INFO*));
+ trp->last_scan= trp->first_scan + best_num;
+ trp->is_covering= TRUE;
+ trp->read_cost= total_cost;
+ trp->records= records;
+
+ DBUG_PRINT("info",
+ ("Returning covering ROR-intersect plan: cost %g, records %lu",
+ trp->read_cost, (ulong) trp->records));
+ DBUG_RETURN(trp);
+}
+
+
+/*
+ Get best "range" table read plan for given SEL_TREE.
+ Also update PARAM members and store ROR scans info in the SEL_TREE.
+ SYNOPSIS
+ get_key_scans_params
+ param parameters from test_quick_select
+ tree make range select for this SEL_TREE
+ index_read_must_be_used if TRUE, assume 'index only' option will be set
+ (except for clustered PK indexes)
+ read_time don't create read plans with cost > read_time.
+ RETURN
+ Best range read plan
+ NULL if no plan found or error occurred
+*/
+
+static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
+ bool index_read_must_be_used,
+ double read_time)
+{
+ int idx;
+ SEL_ARG **key,**end, **key_to_read= NULL;
+ ha_rows best_records;
+ TRP_RANGE* read_plan= NULL;
+ bool pk_is_clustered= param->table->file->primary_key_is_clustered();
+ DBUG_ENTER("get_key_scans_params");
+ LINT_INIT(best_records); /* protected by key_to_read */
+ /*
+ Note that there may be trees that have type SEL_TREE::KEY but contain no
+ key reads at all, e.g. tree for expression "key1 is not null" where key1
+ is defined as "not null".
+ */
+ DBUG_EXECUTE("info", print_sel_tree(param, tree, &tree->keys_map,
+ "tree scans"););
+ tree->ror_scans_map.clear_all();
+ tree->n_ror_scans= 0;
+ for (idx= 0,key=tree->keys, end=key+param->keys;
+ key != end ;
+ key++,idx++)
+ {
+ ha_rows found_records;
+ double found_read_time;
+ if (*key)
+ {
+ uint keynr= param->real_keynr[idx];
+ if ((*key)->type == SEL_ARG::MAYBE_KEY ||
+ (*key)->maybe_flag)
+ param->needed_reg->set_bit(keynr);
+
+ bool read_index_only= index_read_must_be_used ? TRUE :
+ (bool) param->table->used_keys.is_set(keynr);
+
+ found_records= check_quick_select(param, idx, *key);
+ if (param->is_ror_scan)
+ {
+ tree->n_ror_scans++;
+ tree->ror_scans_map.set_bit(idx);
+ }
+ double cpu_cost= (double) found_records / TIME_FOR_COMPARE;
+ if (found_records != HA_POS_ERROR && found_records > 2 &&
+ read_index_only &&
+ (param->table->file->index_flags(keynr, param->max_key_part,1) &
+ HA_KEYREAD_ONLY) &&
+ !(pk_is_clustered && keynr == param->table->s->primary_key))
+ {
+ /*
+ We can resolve this by only reading through this key.
+ 0.01 is added to avoid races between range and 'index' scan.
+ */
+ found_read_time= get_index_only_read_time(param,found_records,keynr) +
+ cpu_cost + 0.01;
+ }
+ else
+ {
+ /*
+ cost(read_through_index) = cost(disk_io) + cost(row_in_range_checks)
+ The row_in_range check is in QUICK_RANGE_SELECT::cmp_next function.
+ */
+ found_read_time= param->table->file->read_time(keynr,
+ param->range_count,
+ found_records) +
+ cpu_cost + 0.01;
+ }
+ DBUG_PRINT("info",("key %s: found_read_time: %g (cur. read_time: %g)",
+ param->table->key_info[keynr].name, found_read_time,
+ read_time));
+
+ if (read_time > found_read_time && found_records != HA_POS_ERROR
+ /*|| read_time == DBL_MAX*/ )
+ {
+ read_time= found_read_time;
+ best_records= found_records;
+ key_to_read= key;
+ }
+
+ }
+ }
+
+ DBUG_EXECUTE("info", print_sel_tree(param, tree, &tree->ror_scans_map,
+ "ROR scans"););
+ if (key_to_read)
+ {
+ idx= key_to_read - tree->keys;
+ if ((read_plan= new (param->mem_root) TRP_RANGE(*key_to_read, idx)))
+ {
+ read_plan->records= best_records;
+ read_plan->is_ror= tree->ror_scans_map.is_set(idx);
+ read_plan->read_cost= read_time;
+ DBUG_PRINT("info",
+ ("Returning range plan for key %s, cost %g, records %lu",
+ param->table->key_info[param->real_keynr[idx]].name,
+ read_plan->read_cost, (ulong) read_plan->records));
+ }
+ }
+ else
+ DBUG_PRINT("info", ("No 'range' table read plan found"));
+
+ DBUG_RETURN(read_plan);
+}
+
+
+QUICK_SELECT_I *TRP_INDEX_MERGE::make_quick(PARAM *param,
+ bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc)
+{
+ QUICK_INDEX_MERGE_SELECT *quick_imerge;
+ QUICK_RANGE_SELECT *quick;
+ /* index_merge always retrieves full rows, ignore retrieve_full_rows */
+ if (!(quick_imerge= new QUICK_INDEX_MERGE_SELECT(param->thd, param->table)))
+ return NULL;
+
+ quick_imerge->records= records;
+ quick_imerge->read_time= read_cost;
+ for (TRP_RANGE **range_scan= range_scans; range_scan != range_scans_end;
+ range_scan++)
+ {
+ if (!(quick= (QUICK_RANGE_SELECT*)
+ ((*range_scan)->make_quick(param, FALSE, &quick_imerge->alloc)))||
+ quick_imerge->push_quick_back(quick))
+ {
+ delete quick;
+ delete quick_imerge;
+ return NULL;
+ }
+ }
+ return quick_imerge;
+}
+
+QUICK_SELECT_I *TRP_ROR_INTERSECT::make_quick(PARAM *param,
+ bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc)
+{
+ QUICK_ROR_INTERSECT_SELECT *quick_intrsect;
+ QUICK_RANGE_SELECT *quick;
+ DBUG_ENTER("TRP_ROR_INTERSECT::make_quick");
+ MEM_ROOT *alloc;
+
+ if ((quick_intrsect=
+ new QUICK_ROR_INTERSECT_SELECT(param->thd, param->table,
+ retrieve_full_rows? (!is_covering):FALSE,
+ parent_alloc)))
+ {
+ DBUG_EXECUTE("info", print_ror_scans_arr(param->table,
+ "creating ROR-intersect",
+ first_scan, last_scan););
+ alloc= parent_alloc? parent_alloc: &quick_intrsect->alloc;
+ for (; first_scan != last_scan;++first_scan)
+ {
+ if (!(quick= get_quick_select(param, (*first_scan)->idx,
+ (*first_scan)->sel_arg, alloc)) ||
+ quick_intrsect->push_quick_back(quick))
+ {
+ delete quick_intrsect;
+ DBUG_RETURN(NULL);
+ }
+ }
+ if (cpk_scan)
+ {
+ if (!(quick= get_quick_select(param, cpk_scan->idx,
+ cpk_scan->sel_arg, alloc)))
+ {
+ delete quick_intrsect;
+ DBUG_RETURN(NULL);
+ }
+ quick->file= NULL;
+ quick_intrsect->cpk_quick= quick;
+ }
+ quick_intrsect->records= records;
+ quick_intrsect->read_time= read_cost;
+ }
+ DBUG_RETURN(quick_intrsect);
+}
+
+
+QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param,
+ bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc)
+{
+ QUICK_ROR_UNION_SELECT *quick_roru;
+ TABLE_READ_PLAN **scan;
+ QUICK_SELECT_I *quick;
+ DBUG_ENTER("TRP_ROR_UNION::make_quick");
+ /*
+ It is impossible to construct a ROR-union that will not retrieve full
+ rows, ignore retrieve_full_rows parameter.
+ */
+ if ((quick_roru= new QUICK_ROR_UNION_SELECT(param->thd, param->table)))
+ {
+ for (scan= first_ror; scan != last_ror; scan++)
+ {
+ if (!(quick= (*scan)->make_quick(param, FALSE, &quick_roru->alloc)) ||
+ quick_roru->push_quick_back(quick))
+ DBUG_RETURN(NULL);
+ }
+ quick_roru->records= records;
+ quick_roru->read_time= read_cost;
+ }
+ DBUG_RETURN(quick_roru);
+}
+
+
+/*
+ Build a SEL_TREE for <> or NOT BETWEEN predicate
+
+ SYNOPSIS
+ get_ne_mm_tree()
+ param PARAM from SQL_SELECT::test_quick_select
+ cond_func item for the predicate
+ field field in the predicate
+ lt_value constant that field should be smaller
+ gt_value constant that field should be greaterr
+ cmp_type compare type for the field
+
+ RETURN
+ # Pointer to tree built tree
+ 0 on error
+*/
+
+static SEL_TREE *get_ne_mm_tree(PARAM *param, Item_func *cond_func,
+ Field *field,
+ Item *lt_value, Item *gt_value,
+ Item_result cmp_type)
+{
+ SEL_TREE *tree;
+ tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
+ lt_value, cmp_type);
+ if (tree)
+ {
+ tree= tree_or(param, tree, get_mm_parts(param, cond_func, field,
+ Item_func::GT_FUNC,
+ gt_value, cmp_type));
+ }
+ return tree;
+}
+
+
+/*
+ Build a SEL_TREE for a simple predicate
+
+ SYNOPSIS
+ get_func_mm_tree()
+ param PARAM from SQL_SELECT::test_quick_select
+ cond_func item for the predicate
+ field field in the predicate
+ value constant in the predicate
+ cmp_type compare type for the field
+ inv TRUE <> NOT cond_func is considered
+ (makes sense only when cond_func is BETWEEN or IN)
+
+ RETURN
+ Pointer to the tree built tree
+*/
+
+static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func,
+ Field *field, Item *value,
+ Item_result cmp_type, bool inv)
+{
+ SEL_TREE *tree= 0;
+ DBUG_ENTER("get_func_mm_tree");
+
+ switch (cond_func->functype()) {
+
+ case Item_func::NE_FUNC:
+ tree= get_ne_mm_tree(param, cond_func, field, value, value, cmp_type);
+ break;
+
+ case Item_func::BETWEEN:
+ if (inv)
+ {
+ tree= get_ne_mm_tree(param, cond_func, field, cond_func->arguments()[1],
+ cond_func->arguments()[2], cmp_type);
+ }
+ else
+ {
+ tree= get_mm_parts(param, cond_func, field, Item_func::GE_FUNC,
+ cond_func->arguments()[1],cmp_type);
+ if (tree)
+ {
+ tree= tree_and(param, tree, get_mm_parts(param, cond_func, field,
+ Item_func::LE_FUNC,
+ cond_func->arguments()[2],
+ cmp_type));
+ }
+ }
+ break;
+
+ case Item_func::IN_FUNC:
+ {
+ Item_func_in *func=(Item_func_in*) cond_func;
+
+ if (inv)
+ {
+ tree= get_ne_mm_tree(param, cond_func, field,
+ func->arguments()[1], func->arguments()[1],
+ cmp_type);
+ if (tree)
+ {
+ Item **arg, **end;
+ for (arg= func->arguments()+2, end= arg+func->argument_count()-2;
+ arg < end ; arg++)
+ {
+ tree= tree_and(param, tree, get_ne_mm_tree(param, cond_func, field,
+ *arg, *arg, cmp_type));
+ }
+ }
+ }
+ else
+ {
+ tree= get_mm_parts(param, cond_func, field, Item_func::EQ_FUNC,
+ func->arguments()[1], cmp_type);
+ if (tree)
+ {
+ Item **arg, **end;
+ for (arg= func->arguments()+2, end= arg+func->argument_count()-2;
+ arg < end ; arg++)
+ {
+ tree= tree_or(param, tree, get_mm_parts(param, cond_func, field,
+ Item_func::EQ_FUNC,
+ *arg, cmp_type));
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ /*
+ Here the function for the following predicates are processed:
+ <, <=, =, >=, >, LIKE, IS NULL, IS NOT NULL.
+ If the predicate is of the form (value op field) it is handled
+ as the equivalent predicate (field rev_op value), e.g.
+ 2 <= a is handled as a >= 2.
+ */
+ Item_func::Functype func_type=
+ (value != cond_func->arguments()[0]) ? cond_func->functype() :
+ ((Item_bool_func2*) cond_func)->rev_functype();
+ tree= get_mm_parts(param, cond_func, field, func_type, value, cmp_type);
+ }
+ }
+
+ DBUG_RETURN(tree);
+
+}
+
/* make a select tree of all keys in condition */
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
{
SEL_TREE *tree=0;
+ SEL_TREE *ftree= 0;
+ Item_field *field_item= 0;
+ bool inv= FALSE;
+ Item *value;
DBUG_ENTER("get_mm_tree");
if (cond->type() == Item::COND_ITEM)
@@ -832,9 +3510,12 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
DBUG_RETURN(new SEL_TREE(SEL_TREE::IMPOSSIBLE));
}
- table_map ref_tables=cond->used_tables();
+ table_map ref_tables= 0;
+ table_map param_comp= ~(param->prev_tables | param->read_tables |
+ param->current_table);
if (cond->type() != Item::FUNC_ITEM)
{ // Should be a field
+ ref_tables= cond->used_tables();
if ((ref_tables & param->current_table) ||
(ref_tables & ~(param->prev_tables | param->read_tables)))
DBUG_RETURN(0);
@@ -842,103 +3523,120 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
}
Item_func *cond_func= (Item_func*) cond;
- if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
- DBUG_RETURN(0); // Can't be calculated
+ if (cond_func->functype() == Item_func::BETWEEN ||
+ cond_func->functype() == Item_func::IN_FUNC)
+ inv= ((Item_func_opt_neg *) cond_func)->negated;
+ else if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
+ DBUG_RETURN(0);
param->cond= cond;
- if (cond_func->functype() == Item_func::BETWEEN)
+ switch (cond_func->functype()) {
+ case Item_func::BETWEEN:
+ if (cond_func->arguments()[0]->type() != Item::FIELD_ITEM)
+ DBUG_RETURN(0);
+ field_item= (Item_field*) (cond_func->arguments()[0]);
+ value= NULL;
+ break;
+ case Item_func::IN_FUNC:
{
- if (!((Item_func_between *)(cond_func))->negated &&
- cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
+ Item_func_in *func=(Item_func_in*) cond_func;
+ if (func->key_item()->type() != Item::FIELD_ITEM)
+ DBUG_RETURN(0);
+ field_item= (Item_field*) (func->key_item());
+ value= NULL;
+ break;
+ }
+ case Item_func::MULT_EQUAL_FUNC:
+ {
+ Item_equal *item_equal= (Item_equal *) cond;
+ if (!(value= item_equal->get_const()))
+ DBUG_RETURN(0);
+ Item_equal_iterator it(*item_equal);
+ ref_tables= value->used_tables();
+ while ((field_item= it++))
{
- Field *field=((Item_field*) (cond_func->arguments()[0]))->field;
- Item_result cmp_type=field->cmp_type();
- DBUG_RETURN(tree_and(param,
- get_mm_parts(param, cond_func, field,
- Item_func::GE_FUNC,
- cond_func->arguments()[1], cmp_type),
- get_mm_parts(param, cond_func, field,
- Item_func::LE_FUNC,
- cond_func->arguments()[2], cmp_type)));
+ Field *field= field_item->field;
+ Item_result cmp_type= field->cmp_type();
+ if (!((ref_tables | field->table->map) & param_comp))
+ {
+ tree= get_mm_parts(param, cond, field, Item_func::EQ_FUNC,
+ value,cmp_type);
+ ftree= !ftree ? tree : tree_and(param, ftree, tree);
+ }
}
- DBUG_RETURN(0);
+
+ DBUG_RETURN(ftree);
}
- if (cond_func->functype() == Item_func::IN_FUNC)
- { // COND OR
- Item_func_in *func=(Item_func_in*) cond_func;
- if (!func->negated && func->key_item()->type() == Item::FIELD_ITEM)
- {
- Field *field=((Item_field*) (func->key_item()))->field;
- Item_result cmp_type=field->cmp_type();
- tree= get_mm_parts(param,cond_func,field,Item_func::EQ_FUNC,
- func->arguments()[1],cmp_type);
- if (!tree)
- DBUG_RETURN(tree); // Not key field
- for (uint i=2 ; i < func->argument_count(); i++)
- {
- SEL_TREE *new_tree=get_mm_parts(param,cond_func,field,
- Item_func::EQ_FUNC,
- func->arguments()[i],cmp_type);
- tree=tree_or(param,tree,new_tree);
- }
- DBUG_RETURN(tree);
- }
- DBUG_RETURN(0); // Can't optimize this IN
- }
-
- if (ref_tables & ~(param->prev_tables | param->read_tables |
- param->current_table))
- DBUG_RETURN(0); // Can't be calculated yet
- if (!(ref_tables & param->current_table))
- DBUG_RETURN(new SEL_TREE(SEL_TREE::MAYBE)); // This may be false or true
-
- /* check field op const */
- /* btw, ft_func's arguments()[0] isn't FIELD_ITEM. SerG*/
- if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
- {
- tree= get_mm_parts(param, cond_func,
- ((Item_field*) (cond_func->arguments()[0]))->field,
- cond_func->functype(),
- cond_func->arg_count > 1 ? cond_func->arguments()[1] :
- 0,
- ((Item_field*) (cond_func->arguments()[0]))->field->
- cmp_type());
- }
- /* check const op field */
- if (!tree &&
- cond_func->have_rev_func() &&
- cond_func->arguments()[1]->type() == Item::FIELD_ITEM)
- {
- DBUG_RETURN(get_mm_parts(param, cond_func,
- ((Item_field*)
- (cond_func->arguments()[1]))->field,
- ((Item_bool_func2*) cond_func)->rev_functype(),
- cond_func->arguments()[0],
- ((Item_field*)
- (cond_func->arguments()[1]))->field->cmp_type()
- ));
+ default:
+ if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
+ {
+ field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
+ value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : 0;
+ }
+ else if (cond_func->have_rev_func() &&
+ cond_func->arguments()[1]->real_item()->type() ==
+ Item::FIELD_ITEM)
+ {
+ field_item= (Item_field*) (cond_func->arguments()[1]->real_item());
+ value= cond_func->arguments()[0];
+ }
+ else
+ DBUG_RETURN(0);
}
- DBUG_RETURN(tree);
+
+ /*
+ If the where condition contains a predicate (ti.field op const),
+ then not only SELL_TREE for this predicate is built, but
+ the trees for the results of substitution of ti.field for
+ each tj.field belonging to the same multiple equality as ti.field
+ are built as well.
+ E.g. for WHERE t1.a=t2.a AND t2.a > 10
+ a SEL_TREE for t2.a > 10 will be built for quick select from t2
+ and
+ a SEL_TREE for t1.a > 10 will be built for quick select from t1.
+ */
+
+ for (uint i= 0; i < cond_func->arg_count; i++)
+ {
+ Item *arg= cond_func->arguments()[i]->real_item();
+ if (arg != field_item)
+ ref_tables|= arg->used_tables();
+ }
+ Field *field= field_item->field;
+ Item_result cmp_type= field->cmp_type();
+ if (!((ref_tables | field->table->map) & param_comp))
+ ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type, inv);
+ Item_equal *item_equal= field_item->item_equal;
+ if (item_equal)
+ {
+ Item_equal_iterator it(*item_equal);
+ Item_field *item;
+ while ((item= it++))
+ {
+ Field *f= item->field;
+ if (field->eq(f))
+ continue;
+ if (!((ref_tables | f->table->map) & param_comp))
+ {
+ tree= get_func_mm_tree(param, cond_func, f, value, cmp_type, inv);
+ ftree= !ftree ? tree : tree_and(param, ftree, tree);
+ }
+ }
+ }
+ DBUG_RETURN(ftree);
}
static SEL_TREE *
get_mm_parts(PARAM *param, COND *cond_func, Field *field,
- Item_func::Functype type,
+ Item_func::Functype type,
Item *value, Item_result cmp_type)
{
- bool ne_func= FALSE;
DBUG_ENTER("get_mm_parts");
if (field->table != param->table)
DBUG_RETURN(0);
- if (type == Item_func::NE_FUNC)
- {
- ne_func= TRUE;
- type= Item_func::LT_FUNC;
- }
-
KEY_PART *key_part = param->key_parts;
KEY_PART *end = param->key_parts_end;
SEL_TREE *tree=0;
@@ -961,30 +3659,21 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field,
if (sel_arg->type == SEL_ARG::IMPOSSIBLE)
{
tree->type=SEL_TREE::IMPOSSIBLE;
- /* If this is an NE_FUNC, we still need to check GT_FUNC. */
- if (!ne_func)
- DBUG_RETURN(tree);
+ DBUG_RETURN(tree);
}
}
else
{
// This key may be used later
- if (!(sel_arg= new SEL_ARG(SEL_ARG::MAYBE_KEY)))
+ if (!(sel_arg= new SEL_ARG(SEL_ARG::MAYBE_KEY)))
DBUG_RETURN(0); // OOM
}
sel_arg->part=(uchar) key_part->part;
tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg);
+ tree->keys_map.set_bit(key_part->key);
}
}
- if (ne_func)
- {
- SEL_TREE *tree2= get_mm_parts(param, cond_func,
- field, Item_func::GT_FUNC,
- value, cmp_type);
- /* tree_or() will return 0 if tree2 is 0 */
- tree= tree_or(param,tree,tree2);
- }
DBUG_RETURN(tree);
}
@@ -993,26 +3682,40 @@ static SEL_ARG *
get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
Item_func::Functype type,Item *value)
{
- uint maybe_null=(uint) field->real_maybe_null(), copies;
- uint field_length=field->pack_length()+maybe_null;
- SEL_ARG *tree;
- char *str, *str2;
+ uint maybe_null=(uint) field->real_maybe_null();
+ bool optimize_range;
+ SEL_ARG *tree= 0;
+ MEM_ROOT *alloc= param->mem_root;
+ char *str;
DBUG_ENTER("get_mm_leaf");
+ /*
+ We need to restore the runtime mem_root of the thread in this
+ function because it evaluates the value of its argument, while
+ the argument can be any, e.g. a subselect. The subselect
+ items, in turn, assume that all the memory allocated during
+ the evaluation has the same life span as the item itself.
+ TODO: opt_range.cc should not reset thd->mem_root at all.
+ */
+ param->thd->mem_root= param->old_root;
if (!value) // IS NULL or IS NOT NULL
{
- if (field->table->outer_join) // Can't use a key on this
- DBUG_RETURN(0);
+ if (field->table->maybe_null) // Can't use a key on this
+ goto end;
if (!maybe_null) // Not null field
- DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0);
- if (!(tree=new SEL_ARG(field,is_null_string,is_null_string)))
- DBUG_RETURN(0); // out of memory
+ {
+ if (type == Item_func::ISNULL_FUNC)
+ tree= &null_element;
+ goto end;
+ }
+ if (!(tree= new (alloc) SEL_ARG(field,is_null_string,is_null_string)))
+ goto end; // out of memory
if (type == Item_func::ISNOTNULL_FUNC)
{
tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */
tree->max_flag=NO_MAX_RANGE;
}
- DBUG_RETURN(tree);
+ goto end;
}
/*
@@ -1032,7 +3735,10 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
key_part->image_type == Field::itRAW &&
((Field_str*)field)->charset() != conf_func->compare_collation() &&
!(conf_func->compare_collation()->state & MY_CS_BINSORT))
- DBUG_RETURN(0);
+ goto end;
+
+ optimize_range= field->optimize_range(param->real_keynr[key_part->key],
+ key_part->part);
if (type == Item_func::LIKE_FUNC)
{
@@ -1040,12 +3746,15 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
char buff1[MAX_FIELD_WIDTH],*min_str,*max_str;
String tmp(buff1,sizeof(buff1),value->collation.collation),*res;
uint length,offset,min_length,max_length;
+ uint field_length= field->pack_length()+maybe_null;
- if (!field->optimize_range(param->real_keynr[key_part->key],
- key_part->part))
- DBUG_RETURN(0); // Can't optimize this
+ if (!optimize_range)
+ goto end;
if (!(res= value->val_str(&tmp)))
- DBUG_RETURN(&null_element);
+ {
+ tree= &null_element;
+ goto end;
+ }
/*
TODO:
@@ -1058,7 +3767,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
res= &tmp;
}
if (field->cmp_type() != STRING_RESULT)
- DBUG_RETURN(0); // Can only optimize strings
+ goto end; // Can only optimize strings
offset=maybe_null;
length=key_part->store_length;
@@ -1083,35 +3792,37 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
field_length= length;
}
length+=offset;
- if (!(min_str= (char*) alloc_root(param->mem_root, length*2)))
- DBUG_RETURN(0);
+ if (!(min_str= (char*) alloc_root(alloc, length*2)))
+ goto end;
+
max_str=min_str+length;
if (maybe_null)
max_str[0]= min_str[0]=0;
+ field_length-= maybe_null;
like_error= my_like_range(field->charset(),
res->ptr(), res->length(),
((Item_func_like*)(param->cond))->escape,
wild_one, wild_many,
- field_length-maybe_null,
+ field_length,
min_str+offset, max_str+offset,
&min_length, &max_length);
if (like_error) // Can't optimize with LIKE
- DBUG_RETURN(0);
+ goto end;
- if (offset != maybe_null) // Blob
+ if (offset != maybe_null) // BLOB or VARCHAR
{
int2store(min_str+maybe_null,min_length);
int2store(max_str+maybe_null,max_length);
}
- DBUG_RETURN(new SEL_ARG(field,min_str,max_str));
+ tree= new (alloc) SEL_ARG(field, min_str, max_str);
+ goto end;
}
- if (!field->optimize_range(param->real_keynr[key_part->key],
- key_part->part) &&
+ if (!optimize_range &&
type != Item_func::EQ_FUNC &&
type != Item_func::EQUAL_FUNC)
- DBUG_RETURN(0); // Can't optimize this
+ goto end; // Can't optimize this
/*
We can't always use indexes when comparing a string index to a number
@@ -1120,47 +3831,22 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
if (field->result_type() == STRING_RESULT &&
value->result_type() != STRING_RESULT &&
field->cmp_type() != value->result_type())
- DBUG_RETURN(0);
-
- if (value->save_in_field(field, 1) < 0)
+ goto end;
+
+ if (value->save_in_field_no_warnings(field, 1) < 0)
{
/* This happens when we try to insert a NULL field in a not null column */
- DBUG_RETURN(&null_element); // cmp with NULL is never true
- }
- /* Get local copy of key */
- copies= 1;
- if (field->key_type() == HA_KEYTYPE_VARTEXT)
- copies= 2;
- str= str2= (char*) alloc_root(param->mem_root,
- (key_part->store_length)*copies+1);
+ tree= &null_element; // cmp with NULL is never TRUE
+ goto end;
+ }
+ str= (char*) alloc_root(alloc, key_part->store_length+1);
if (!str)
- DBUG_RETURN(0);
+ goto end;
if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null
- field->get_key_image(str+maybe_null, key_part->length,
- field->charset(), key_part->image_type);
- if (copies == 2)
- {
- /*
- The key is stored as 2 byte length + key
- key doesn't match end space. In other words, a key 'X ' should match
- all rows between 'X' and 'X ...'
- */
- uint length= uint2korr(str+maybe_null);
- str2= str+ key_part->store_length;
- /* remove end space */
- while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ')
- length--;
- int2store(str+maybe_null, length);
- /* Create key that is space filled */
- memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null);
- my_fill_8bit(field->charset(),
- str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null,
- key_part->length-length, ' ');
- int2store(str2+maybe_null, key_part->length);
- }
- if (!(tree=new SEL_ARG(field,str,str2)))
- DBUG_RETURN(0); // out of memory
+ field->get_key_image(str+maybe_null, key_part->length, key_part->image_type);
+ if (!(tree= new (alloc) SEL_ARG(field, str, str)))
+ goto end; // out of memory
/*
Check if we are comparing an UNSIGNED integer with a negative constant.
@@ -1173,9 +3859,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
negative integers (which otherwise fails because at query execution time
negative integers are cast to unsigned if compared with unsigned).
*/
- Item_result field_result_type= field->result_type();
- Item_result value_result_type= value->result_type();
- if (field_result_type == INT_RESULT && value_result_type == INT_RESULT &&
+ if (field->result_type() == INT_RESULT &&
+ value->result_type() == INT_RESULT &&
((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag)
{
longlong item_val= value->val_int();
@@ -1184,10 +3869,13 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
if (type == Item_func::LT_FUNC || type == Item_func::LE_FUNC)
{
tree->type= SEL_ARG::IMPOSSIBLE;
- DBUG_RETURN(tree);
+ goto end;
}
if (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC)
- DBUG_RETURN(0);
+ {
+ tree= 0;
+ goto end;
+ }
}
}
@@ -1250,6 +3938,9 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
default:
break;
}
+
+end:
+ param->thd->mem_root= alloc;
DBUG_RETURN(tree);
}
@@ -1259,8 +3950,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
** If tree is 0 it means that the condition can't be tested. It refers
** to a non existent table or to a field in current table with isn't a key.
** The different tree flags:
-** IMPOSSIBLE: Condition is never true
-** ALWAYS: Condition is always true
+** IMPOSSIBLE: Condition is never TRUE
+** ALWAYS: Condition is always TRUE
** MAYBE: Condition may exists when tables are read
** MAYBE_KEY: Condition refers to a key that may be used in join loop
** KEY_RANGE: Condition uses a key
@@ -1330,6 +4021,8 @@ tree_and(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
DBUG_RETURN(tree1);
}
+ key_map result_keys;
+ result_keys.clear_all();
/* Join the trees key per key */
SEL_ARG **key1,**key2,**end;
for (key1= tree1->keys,key2= tree2->keys,end=key1+param->keys ;
@@ -1346,17 +4039,60 @@ tree_and(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
if (*key1 && (*key1)->type == SEL_ARG::IMPOSSIBLE)
{
tree1->type= SEL_TREE::IMPOSSIBLE;
+ DBUG_RETURN(tree1);
+ }
+ result_keys.set_bit(key1 - tree1->keys);
#ifdef EXTRA_DEBUG
+ if (*key1)
(*key1)->test_use_count(*key1);
#endif
- break;
- }
}
}
+ tree1->keys_map= result_keys;
+ /* dispose index_merge if there is a "range" option */
+ if (!result_keys.is_clear_all())
+ {
+ tree1->merges.empty();
+ DBUG_RETURN(tree1);
+ }
+
+ /* ok, both trees are index_merge trees */
+ imerge_list_and_list(&tree1->merges, &tree2->merges);
DBUG_RETURN(tree1);
}
+/*
+ Check if two SEL_TREES can be combined into one (i.e. a single key range
+ read can be constructed for "cond_of_tree1 OR cond_of_tree2" ) without
+ using index_merge.
+*/
+
+bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2, PARAM* param)
+{
+ key_map common_keys= tree1->keys_map;
+ DBUG_ENTER("sel_trees_can_be_ored");
+ common_keys.intersect(tree2->keys_map);
+
+ if (common_keys.is_clear_all())
+ DBUG_RETURN(FALSE);
+
+ /* trees have a common key, check if they refer to same key part */
+ SEL_ARG **key1,**key2;
+ for (uint key_no=0; key_no < param->keys; key_no++)
+ {
+ if (common_keys.is_set(key_no))
+ {
+ key1= tree1->keys + key_no;
+ key2= tree2->keys + key_no;
+ if ((*key1)->part == (*key2)->part)
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
static SEL_TREE *
tree_or(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
@@ -1373,19 +4109,62 @@ tree_or(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
if (tree2->type == SEL_TREE::MAYBE)
DBUG_RETURN(tree2);
- /* Join the trees key per key */
- SEL_ARG **key1,**key2,**end;
- SEL_TREE *result=0;
- for (key1= tree1->keys,key2= tree2->keys,end=key1+param->keys ;
- key1 != end ; key1++,key2++)
+ SEL_TREE *result= 0;
+ key_map result_keys;
+ result_keys.clear_all();
+ if (sel_trees_can_be_ored(tree1, tree2, param))
{
- *key1=key_or(*key1,*key2);
- if (*key1)
+ /* Join the trees key per key */
+ SEL_ARG **key1,**key2,**end;
+ for (key1= tree1->keys,key2= tree2->keys,end= key1+param->keys ;
+ key1 != end ; key1++,key2++)
{
- result=tree1; // Added to tree1
+ *key1=key_or(*key1,*key2);
+ if (*key1)
+ {
+ result=tree1; // Added to tree1
+ result_keys.set_bit(key1 - tree1->keys);
#ifdef EXTRA_DEBUG
- (*key1)->test_use_count(*key1);
+ (*key1)->test_use_count(*key1);
#endif
+ }
+ }
+ if (result)
+ result->keys_map= result_keys;
+ }
+ else
+ {
+ /* ok, two trees have KEY type but cannot be used without index merge */
+ if (tree1->merges.is_empty() && tree2->merges.is_empty())
+ {
+ SEL_IMERGE *merge;
+ /* both trees are "range" trees, produce new index merge structure */
+ if (!(result= new SEL_TREE()) || !(merge= new SEL_IMERGE()) ||
+ (result->merges.push_back(merge)) ||
+ (merge->or_sel_tree(param, tree1)) ||
+ (merge->or_sel_tree(param, tree2)))
+ result= NULL;
+ else
+ result->type= tree1->type;
+ }
+ else if (!tree1->merges.is_empty() && !tree2->merges.is_empty())
+ {
+ if (imerge_list_or_list(param, &tree1->merges, &tree2->merges))
+ result= new SEL_TREE(SEL_TREE::ALWAYS);
+ else
+ result= tree1;
+ }
+ else
+ {
+ /* one tree is index merge tree and another is range tree */
+ if (tree1->merges.is_empty())
+ swap_variables(SEL_TREE*, tree1, tree2);
+
+ /* add tree2 to tree1->merges, checking if it collapses to ALWAYS */
+ if (imerge_list_or_tree(param, &tree1->merges, tree2))
+ result= new SEL_TREE(SEL_TREE::ALWAYS);
+ else
+ result= tree1;
}
}
DBUG_RETURN(result);
@@ -1434,7 +4213,6 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
}
-
static SEL_ARG *
key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
{
@@ -1466,7 +4244,7 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
clone_flag=swap_clone_flag(clone_flag);
}
- // If one of the key is MAYBE_KEY then the found region may be smaller
+ /* If one of the key is MAYBE_KEY then the found region may be smaller */
if (key2->type == SEL_ARG::MAYBE_KEY)
{
if (key1->use_count > 1)
@@ -1504,6 +4282,13 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
return 0; // Can't optimize this
}
+ if ((key1->min_flag | key2->min_flag) & GEOM_FLAG)
+ {
+ key1->free_tree();
+ key2->free_tree();
+ return 0; // Can't optimize this
+ }
+
key1->use_count--;
key2->use_count--;
SEL_ARG *e1=key1->first(), *e2=key2->first(), *new_tree=0;
@@ -1928,7 +4713,7 @@ SEL_ARG::find_range(SEL_ARG *key)
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
@@ -2175,7 +4960,7 @@ SEL_ARG *rb_delete_fixup(SEL_ARG *root,SEL_ARG *key,SEL_ARG *par)
}
- /* Test that the proporties for a red-black tree holds */
+ /* Test that the properties for a red-black tree hold */
#ifdef EXTRA_DEBUG
int test_rb_tree(SEL_ARG *element,SEL_ARG *parent)
@@ -2248,7 +5033,7 @@ void SEL_ARG::test_use_count(SEL_ARG *root)
ulong count=count_key_part_usage(root,pos->next_key_part);
if (count > pos->next_key_part->use_count)
{
- sql_print_information("Use_count: Wrong count for key at %lx, %lu should be %lu",
+ sql_print_information("Use_count: Wrong count for key at 0x%lx, %lu should be %lu",
pos,pos->next_key_part->use_count,count);
return;
}
@@ -2256,68 +5041,167 @@ void SEL_ARG::test_use_count(SEL_ARG *root)
}
}
if (e_count != elements)
- sql_print_warning("Wrong use count: %u (should be %u) for tree at %lx",
+ sql_print_warning("Wrong use count: %u (should be %u) for tree at 0x%lx",
e_count, elements, (gptr) this);
}
#endif
+/*
+ Calculate estimate of number records that will be retrieved by a range
+ scan on given index using given SEL_ARG intervals tree.
+ SYNOPSIS
+ check_quick_select
+ param Parameter from test_quick_select
+ idx Number of index to use in PARAM::key SEL_TREE::key
+ tree Transformed selection condition, tree->key[idx] holds intervals
+ tree to be used for scanning.
+ NOTES
+ param->is_ror_scan is set to reflect if the key scan is a ROR (see
+ is_key_scan_ror function for more info)
+ param->table->quick_*, param->range_count (and maybe others) are
+ updated with data of given key scan, see check_quick_keys for details.
+
+ RETURN
+ Estimate # of records to be retrieved.
+ HA_POS_ERROR if estimate calculation failed due to table handler problems.
-/*****************************************************************************
-** Check how many records we will find by using the found tree
-*****************************************************************************/
+*/
static ha_rows
check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
{
ha_rows records;
+ bool cpk_scan;
+ uint key;
DBUG_ENTER("check_quick_select");
+ param->is_ror_scan= FALSE;
+
if (!tree)
DBUG_RETURN(HA_POS_ERROR); // Can't use it
param->max_key_part=0;
param->range_count=0;
+ key= param->real_keynr[idx];
+
if (tree->type == SEL_ARG::IMPOSSIBLE)
DBUG_RETURN(0L); // Impossible select. return
if (tree->type != SEL_ARG::KEY_RANGE || tree->part != 0)
DBUG_RETURN(HA_POS_ERROR); // Don't use tree
+
+ enum ha_key_alg key_alg= param->table->key_info[key].algorithm;
+ if ((key_alg != HA_KEY_ALG_BTREE) && (key_alg!= HA_KEY_ALG_UNDEF))
+ {
+ /* Records are not ordered by rowid for other types of indexes. */
+ cpk_scan= FALSE;
+ }
+ else
+ {
+ /*
+ Clustered PK scan is a special case, check_quick_keys doesn't recognize
+ CPK scans as ROR scans (while actually any CPK scan is a ROR scan).
+ */
+ cpk_scan= ((param->table->s->primary_key == param->real_keynr[idx]) &&
+ param->table->file->primary_key_is_clustered());
+ param->is_ror_scan= !cpk_scan;
+ }
+
records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0);
if (records != HA_POS_ERROR)
{
- uint key=param->real_keynr[idx];
param->table->quick_keys.set_bit(key);
param->table->quick_rows[key]=records;
param->table->quick_key_parts[key]=param->max_key_part+1;
+
+ if (cpk_scan)
+ param->is_ror_scan= TRUE;
}
DBUG_PRINT("exit", ("Records: %lu", (ulong) records));
DBUG_RETURN(records);
}
+/*
+ Recursively calculate estimate of # rows that will be retrieved by
+ key scan on key idx.
+ SYNOPSIS
+ check_quick_keys()
+ param Parameter from test_quick select function.
+ idx Number of key to use in PARAM::keys in list of used keys
+ (param->real_keynr[idx] holds the key number in table)
+ key_tree SEL_ARG tree being examined.
+ min_key Buffer with partial min key value tuple
+ min_key_flag
+ max_key Buffer with partial max key value tuple
+ max_key_flag
+
+ NOTES
+ The function does the recursive descent on the tree via SEL_ARG::left,
+ SEL_ARG::right, and SEL_ARG::next_key_part edges. The #rows estimates
+ are calculated using records_in_range calls at the leaf nodes and then
+ summed.
+
+ param->min_key and param->max_key are used to hold prefixes of key value
+ tuples.
+
+ The side effects are:
+
+ param->max_key_part is updated to hold the maximum number of key parts used
+ in scan minus 1.
+
+ param->range_count is incremented if the function finds a range that
+ wasn't counted by the caller.
+
+ param->is_ror_scan is cleared if the function detects that the key scan is
+ not a Rowid-Ordered Retrieval scan ( see comments for is_key_scan_ror
+ function for description of which key scans are ROR scans)
+*/
+
static ha_rows
check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
char *min_key,uint min_key_flag, char *max_key,
uint max_key_flag)
{
- ha_rows records=0,tmp;
+ ha_rows records=0, tmp;
+ uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length;
+ char *tmp_min_key, *tmp_max_key;
param->max_key_part=max(param->max_key_part,key_tree->part);
if (key_tree->left != &null_element)
{
+ /*
+ There are at least two intervals for current key part, i.e. condition
+ was converted to something like
+ (keyXpartY less/equals c1) OR (keyXpartY more/equals c2).
+ This is not a ROR scan if the key is not Clustered Primary Key.
+ */
+ param->is_ror_scan= FALSE;
records=check_quick_keys(param,idx,key_tree->left,min_key,min_key_flag,
max_key,max_key_flag);
if (records == HA_POS_ERROR) // Impossible
return records;
}
- uint tmp_min_flag,tmp_max_flag,keynr;
- char *tmp_min_key=min_key,*tmp_max_key=max_key;
-
+ tmp_min_key= min_key;
+ tmp_max_key= max_key;
key_tree->store(param->key[idx][key_tree->part].store_length,
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
- uint min_key_length= (uint) (tmp_min_key- param->min_key);
- uint max_key_length= (uint) (tmp_max_key- param->max_key);
+ min_key_length= (uint) (tmp_min_key- param->min_key);
+ max_key_length= (uint) (tmp_max_key- param->max_key);
+
+ if (param->is_ror_scan)
+ {
+ /*
+ If the index doesn't cover entire key, mark the scan as non-ROR scan.
+ Actually we're cutting off some ROR scans here.
+ */
+ uint16 fieldnr= param->table->key_info[param->real_keynr[idx]].
+ key_part[key_tree->part].fieldnr - 1;
+ if (param->table->field[fieldnr]->key_length() !=
+ param->key[idx][key_tree->part].length)
+ param->is_ror_scan= FALSE;
+ }
if (key_tree->next_key_part &&
key_tree->next_key_part->part == key_tree->part+1 &&
@@ -2332,6 +5216,12 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
tmp_max_key, max_key_flag | key_tree->max_flag);
goto end; // Ugly, but efficient
}
+ else
+ {
+ /* The interval for current key part is not c1 <= keyXpartY <= c1 */
+ param->is_ror_scan= FALSE;
+ }
+
tmp_min_flag=key_tree->min_flag;
tmp_max_flag=key_tree->max_flag;
if (!tmp_min_flag)
@@ -2360,6 +5250,24 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
tmp=1; // Max one record
else
{
+ if (param->is_ror_scan)
+ {
+ /*
+ If we get here, the condition on the key was converted to form
+ "(keyXpart1 = c1) AND ... AND (keyXpart{key_tree->part - 1} = cN) AND
+ somecond(keyXpart{key_tree->part})"
+ Check if
+ somecond is "keyXpart{key_tree->part} = const" and
+ uncovered "tail" of KeyX parts is either empty or is identical to
+ first members of clustered primary key.
+ */
+ if (!(min_key_length == max_key_length &&
+ !memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) &&
+ !key_tree->min_flag && !key_tree->max_flag &&
+ is_key_scan_ror(param, keynr, key_tree->part + 1)))
+ param->is_ror_scan= FALSE;
+ }
+
if (tmp_min_flag & GEOM_FLAG)
{
key_range min_range;
@@ -2396,6 +5304,13 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
records+=tmp;
if (key_tree->right != &null_element)
{
+ /*
+ There are at least two intervals for current key part, i.e. condition
+ was converted to something like
+ (keyXpartY less/equals c1) OR (keyXpartY more/equals c2).
+ This is not a ROR scan if the key is not Clustered Primary Key.
+ */
+ param->is_ror_scan= FALSE;
tmp=check_quick_keys(param,idx,key_tree->right,min_key,min_key_flag,
max_key,max_key_flag);
if (tmp == HA_POS_ERROR)
@@ -2406,22 +5321,110 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
}
-/****************************************************************************
-** change a tree to a structure to be used by quick_select
-** This uses it's own malloc tree
-****************************************************************************/
+/*
+ Check if key scan on given index with equality conditions on first n key
+ parts is a ROR scan.
+
+ SYNOPSIS
+ is_key_scan_ror()
+ param Parameter from test_quick_select
+ keynr Number of key in the table. The key must not be a clustered
+ primary key.
+ nparts Number of first key parts for which equality conditions
+ are present.
+
+ NOTES
+ ROR (Rowid Ordered Retrieval) key scan is a key scan that produces
+ ordered sequence of rowids (ha_xxx::cmp_ref is the comparison function)
+
+ An index scan is a ROR scan if it is done using a condition in form
+
+ "key1_1=c_1 AND ... AND key1_n=c_n" (1)
+
+ where the index is defined on (key1_1, ..., key1_N [,a_1, ..., a_n])
+
+ and the table has a clustered Primary Key
+
+ PRIMARY KEY(a_1, ..., a_n, b1, ..., b_k) with first key parts being
+ identical to uncovered parts ot the key being scanned (2)
-static QUICK_SELECT *
-get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree)
+ Scans on HASH indexes are not ROR scans,
+ any range scan on clustered primary key is ROR scan (3)
+
+ Check (1) is made in check_quick_keys()
+ Check (3) is made check_quick_select()
+ Check (2) is made by this function.
+
+ RETURN
+ TRUE If the scan is ROR-scan
+ FALSE otherwise
+*/
+
+static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts)
{
- QUICK_SELECT *quick;
+ KEY *table_key= param->table->key_info + keynr;
+ KEY_PART_INFO *key_part= table_key->key_part + nparts;
+ KEY_PART_INFO *key_part_end= (table_key->key_part +
+ table_key->key_parts);
+ uint pk_number;
+
+ if (key_part == key_part_end)
+ return TRUE;
+ pk_number= param->table->s->primary_key;
+ if (!param->table->file->primary_key_is_clustered() || pk_number == MAX_KEY)
+ return FALSE;
+
+ KEY_PART_INFO *pk_part= param->table->key_info[pk_number].key_part;
+ KEY_PART_INFO *pk_part_end= pk_part +
+ param->table->key_info[pk_number].key_parts;
+ for (;(key_part!=key_part_end) && (pk_part != pk_part_end);
+ ++key_part, ++pk_part)
+ {
+ if ((key_part->field != pk_part->field) ||
+ (key_part->length != pk_part->length))
+ return FALSE;
+ }
+ return (key_part == key_part_end);
+}
+
+
+/*
+ Create a QUICK_RANGE_SELECT from given key and SEL_ARG tree for that key.
+
+ SYNOPSIS
+ get_quick_select()
+ param
+ idx Index of used key in param->key.
+ key_tree SEL_ARG tree for the used key
+ parent_alloc If not NULL, use it to allocate memory for
+ quick select data. Otherwise use quick->alloc.
+ NOTES
+ The caller must call QUICK_SELECT::init for returned quick select
+
+ CAUTION! This function may change thd->mem_root to a MEM_ROOT which will be
+ deallocated when the returned quick select is deleted.
+
+ RETURN
+ NULL on error
+ otherwise created quick select
+*/
+
+QUICK_RANGE_SELECT *
+get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree,
+ MEM_ROOT *parent_alloc)
+{
+ QUICK_RANGE_SELECT *quick;
DBUG_ENTER("get_quick_select");
if (param->table->key_info[param->real_keynr[idx]].flags & HA_SPATIAL)
- quick=new QUICK_SELECT_GEOM(param->thd, param->table, param->real_keynr[idx],
- 0);
+ quick=new QUICK_RANGE_SELECT_GEOM(param->thd, param->table,
+ param->real_keynr[idx],
+ test(parent_alloc),
+ parent_alloc);
else
- quick=new QUICK_SELECT(param->thd, param->table, param->real_keynr[idx]);
+ quick=new QUICK_RANGE_SELECT(param->thd, param->table,
+ param->real_keynr[idx],
+ test(parent_alloc));
if (quick)
{
@@ -2435,9 +5438,10 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree)
else
{
quick->key_parts=(KEY_PART*)
- memdup_root(&quick->alloc,(char*) param->key[idx],
- sizeof(KEY_PART)*
- param->table->key_info[param->real_keynr[idx]].key_parts);
+ memdup_root(parent_alloc? parent_alloc : &quick->alloc,
+ (char*) param->key[idx],
+ sizeof(KEY_PART)*
+ param->table->key_info[param->real_keynr[idx]].key_parts);
}
}
DBUG_RETURN(quick);
@@ -2447,9 +5451,8 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree)
/*
** Fix this to get all possible sub_ranges
*/
-
-static bool
-get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
+bool
+get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
SEL_ARG *key_tree,char *min_key,uint min_key_flag,
char *max_key, uint max_key_flag)
{
@@ -2545,7 +5548,8 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
set_if_bigger(quick->max_used_key_length,range->min_length);
set_if_bigger(quick->max_used_key_length,range->max_length);
set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1);
- quick->ranges.push_back(range);
+ if (insert_dynamic(&quick->ranges, (gptr)&range))
+ return 1;
end:
if (key_tree->right != &null_element)
@@ -2559,12 +5563,12 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
Return 1 if there is only one range and this uses the whole primary key
*/
-bool QUICK_SELECT::unique_key_range()
+bool QUICK_RANGE_SELECT::unique_key_range()
{
if (ranges.elements == 1)
{
- QUICK_RANGE *tmp;
- if (((tmp=ranges.head())->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
+ QUICK_RANGE *tmp= *((QUICK_RANGE**)ranges.buffer);
+ if ((tmp->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
{
KEY *key=head->key_info+index;
return ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME &&
@@ -2575,11 +5579,11 @@ bool QUICK_SELECT::unique_key_range()
}
-/* Returns true if any part of the key is NULL */
+/* Returns TRUE if any part of the key is NULL */
static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
{
- for (const char *end=key+length ;
+ for (const char *end=key+length ;
key < end;
key+= key_part++->store_length)
{
@@ -2590,15 +5594,72 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
}
-/****************************************************************************
- Create a QUICK RANGE based on a key
-****************************************************************************/
+bool QUICK_SELECT_I::check_if_keys_used(List<Item> *fields)
+{
+ return check_if_key_used(head, index, *fields);
+}
+
+bool QUICK_INDEX_MERGE_SELECT::check_if_keys_used(List<Item> *fields)
+{
+ QUICK_RANGE_SELECT *quick;
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ while ((quick= it++))
+ {
+ if (check_if_key_used(head, quick->index, *fields))
+ return 1;
+ }
+ return 0;
+}
+
+bool QUICK_ROR_INTERSECT_SELECT::check_if_keys_used(List<Item> *fields)
+{
+ QUICK_RANGE_SELECT *quick;
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ while ((quick= it++))
+ {
+ if (check_if_key_used(head, quick->index, *fields))
+ return 1;
+ }
+ return 0;
+}
+
+bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List<Item> *fields)
+{
+ QUICK_SELECT_I *quick;
+ List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
+ while ((quick= it++))
+ {
+ if (quick->check_if_keys_used(fields))
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ Create quick select from ref/ref_or_null scan.
+ SYNOPSIS
+ get_quick_select_for_ref()
+ thd Thread handle
+ table Table to access
+ ref ref[_or_null] scan parameters
+ records Estimate of number of records (needed only to construct
+ quick select)
+ NOTES
+ This allocates things in a new memory root, as this may be called many
+ times during a query.
+
+ RETURN
+ Quick select that retrieves the same rows as passed ref scan
+ NULL on error.
+*/
-QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
+QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
+ TABLE_REF *ref, ha_rows records)
{
MEM_ROOT *old_root= thd->mem_root;
/* The following call may change thd->mem_root */
- QUICK_SELECT *quick= new QUICK_SELECT(thd, table, ref->key);
+ QUICK_RANGE_SELECT *quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0);
KEY *key_info = &table->key_info[ref->key];
KEY_PART *key_part;
QUICK_RANGE *range;
@@ -2606,15 +5667,16 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
if (!quick)
return 0; /* no ranges found */
- if (cp_buffer_from_ref(thd, ref))
+ if (quick->init())
{
- if (thd->is_fatal_error)
- goto err; // out of memory
- goto ok; // empty range
+ delete quick;
+ goto err;
}
+ quick->records= records;
- if (!(range= new QUICK_RANGE()))
- goto err; // out of memory
+ if (cp_buffer_from_ref(thd,ref) && thd->is_fatal_error ||
+ !(range= new QUICK_RANGE()))
+ goto err; // out of memory
range->min_key=range->max_key=(char*) ref->key_buff;
range->min_length=range->max_length=ref->key_length;
@@ -2634,10 +5696,10 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
key_part->store_length= key_info->key_part[part].store_length;
key_part->null_bit= key_info->key_part[part].null_bit;
}
- if (quick->ranges.push_back(range))
+ if (insert_dynamic(&quick->ranges,(gptr)&range))
goto err;
- /*
+ /*
Add a NULL range if REF_OR_NULL optimization is used.
For example:
if we have "WHERE A=2 OR A IS NULL" we created the (A=2) range above
@@ -2653,11 +5715,10 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
EQ_RANGE)))
goto err;
*ref->null_ref_key= 0; // Clear null byte
- if (quick->ranges.push_back(null_range))
+ if (insert_dynamic(&quick->ranges,(gptr)&null_range))
goto err;
}
-ok:
thd->mem_root= old_root;
return quick;
@@ -2667,11 +5728,490 @@ err:
return 0;
}
- /* get next possible record using quick-struct */
-int QUICK_SELECT::get_next()
+/*
+ Perform key scans for all used indexes (except CPK), get rowids and merge
+ them into an ordered non-recurrent sequence of rowids.
+
+ The merge/duplicate removal is performed using Unique class. We put all
+ rowids into Unique, get the sorted sequence and destroy the Unique.
+
+ If table has a clustered primary key that covers all rows (TRUE for bdb
+ and innodb currently) and one of the index_merge scans is a scan on PK,
+ then
+ rows that will be retrieved by PK scan are not put into Unique and
+ primary key scan is not performed here, it is performed later separately.
+
+ RETURN
+ 0 OK
+ other error
+*/
+
+int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
+{
+ List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it(quick_selects);
+ QUICK_RANGE_SELECT* cur_quick;
+ int result;
+ Unique *unique;
+ DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::prepare_unique");
+
+ /* We're going to just read rowids. */
+ if (head->file->extra(HA_EXTRA_KEYREAD))
+ DBUG_RETURN(1);
+
+ /*
+ Make innodb retrieve all PK member fields, so
+ * ha_innobase::position (which uses them) call works.
+ * We can filter out rows that will be retrieved by clustered PK.
+ (This also creates a deficiency - it is possible that we will retrieve
+ parts of key that are not used by current query at all.)
+ */
+ if (head->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY))
+ DBUG_RETURN(1);
+
+ cur_quick_it.rewind();
+ cur_quick= cur_quick_it++;
+ DBUG_ASSERT(cur_quick != 0);
+
+ /*
+ We reuse the same instance of handler so we need to call both init and
+ reset here.
+ */
+ if (cur_quick->init() || cur_quick->reset())
+ DBUG_RETURN(1);
+
+ unique= new Unique(refpos_order_cmp, (void *)head->file,
+ head->file->ref_length,
+ thd->variables.sortbuff_size);
+ if (!unique)
+ DBUG_RETURN(1);
+ for (;;)
+ {
+ while ((result= cur_quick->get_next()) == HA_ERR_END_OF_FILE)
+ {
+ cur_quick->range_end();
+ cur_quick= cur_quick_it++;
+ if (!cur_quick)
+ break;
+
+ if (cur_quick->file->inited != handler::NONE)
+ cur_quick->file->ha_index_end();
+ if (cur_quick->init() || cur_quick->reset())
+ DBUG_RETURN(1);
+ }
+
+ if (result)
+ {
+ if (result != HA_ERR_END_OF_FILE)
+ {
+ cur_quick->range_end();
+ DBUG_RETURN(result);
+ }
+ break;
+ }
+
+ if (thd->killed)
+ DBUG_RETURN(1);
+
+ /* skip row if it will be retrieved by clustered PK scan */
+ if (pk_quick_select && pk_quick_select->row_in_ranges())
+ continue;
+
+ cur_quick->file->position(cur_quick->record);
+ result= unique->unique_add((char*)cur_quick->file->ref);
+ if (result)
+ DBUG_RETURN(1);
+
+ }
+
+ /* ok, all row ids are in Unique */
+ result= unique->get(head);
+ delete unique;
+ doing_pk_scan= FALSE;
+ /* start table scan */
+ init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1, 1);
+ /* index_merge currently doesn't support "using index" at all */
+ head->file->extra(HA_EXTRA_NO_KEYREAD);
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Get next row for index_merge.
+ NOTES
+ The rows are read from
+ 1. rowids stored in Unique.
+ 2. QUICK_RANGE_SELECT with clustered primary key (if any).
+ The sets of rows retrieved in 1) and 2) are guaranteed to be disjoint.
+*/
+
+int QUICK_INDEX_MERGE_SELECT::get_next()
+{
+ int result;
+ DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::get_next");
+
+ if (doing_pk_scan)
+ DBUG_RETURN(pk_quick_select->get_next());
+
+ result= read_record.read_record(&read_record);
+
+ if (result == -1)
+ {
+ result= HA_ERR_END_OF_FILE;
+ end_read_record(&read_record);
+ /* All rows from Unique have been retrieved, do a clustered PK scan */
+ if (pk_quick_select)
+ {
+ doing_pk_scan= TRUE;
+ if ((result= pk_quick_select->init()) || (result= pk_quick_select->reset()))
+ DBUG_RETURN(result);
+ DBUG_RETURN(pk_quick_select->get_next());
+ }
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Retrieve next record.
+ SYNOPSIS
+ QUICK_ROR_INTERSECT_SELECT::get_next()
+
+ NOTES
+ Invariant on enter/exit: all intersected selects have retrieved all index
+ records with rowid <= some_rowid_val and no intersected select has
+ retrieved any index records with rowid > some_rowid_val.
+ We start fresh and loop until we have retrieved the same rowid in each of
+ the key scans or we got an error.
+
+ If a Clustered PK scan is present, it is used only to check if row
+ satisfies its condition (and never used for row retrieval).
+
+ RETURN
+ 0 - Ok
+ other - Error code if any error occurred.
+*/
+
+int QUICK_ROR_INTERSECT_SELECT::get_next()
+{
+ List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
+ QUICK_RANGE_SELECT* quick;
+ int error, cmp;
+ uint last_rowid_count=0;
+ DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::get_next");
+
+ /* Get a rowid for first quick and save it as a 'candidate' */
+ quick= quick_it++;
+ if (cpk_quick)
+ {
+ do {
+ error= quick->get_next();
+ }while (!error && !cpk_quick->row_in_ranges());
+ }
+ else
+ error= quick->get_next();
+
+ if (error)
+ DBUG_RETURN(error);
+
+ quick->file->position(quick->record);
+ memcpy(last_rowid, quick->file->ref, head->file->ref_length);
+ last_rowid_count= 1;
+
+ while (last_rowid_count < quick_selects.elements)
+ {
+ if (!(quick= quick_it++))
+ {
+ quick_it.rewind();
+ quick= quick_it++;
+ }
+
+ do {
+ if ((error= quick->get_next()))
+ DBUG_RETURN(error);
+ quick->file->position(quick->record);
+ cmp= head->file->cmp_ref(quick->file->ref, last_rowid);
+ } while (cmp < 0);
+
+ /* Ok, current select 'caught up' and returned ref >= cur_ref */
+ if (cmp > 0)
+ {
+ /* Found a row with ref > cur_ref. Make it a new 'candidate' */
+ if (cpk_quick)
+ {
+ while (!cpk_quick->row_in_ranges())
+ {
+ if ((error= quick->get_next()))
+ DBUG_RETURN(error);
+ }
+ }
+ memcpy(last_rowid, quick->file->ref, head->file->ref_length);
+ last_rowid_count= 1;
+ }
+ else
+ {
+ /* current 'candidate' row confirmed by this select */
+ last_rowid_count++;
+ }
+ }
+
+ /* We get here iff we got the same row ref in all scans. */
+ if (need_to_fetch_row)
+ error= head->file->rnd_pos(head->record[0], last_rowid);
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Retrieve next record.
+ SYNOPSIS
+ QUICK_ROR_UNION_SELECT::get_next()
+
+ NOTES
+ Enter/exit invariant:
+ For each quick select in the queue a {key,rowid} tuple has been
+ retrieved but the corresponding row hasn't been passed to output.
+
+ RETURN
+ 0 - Ok
+ other - Error code if any error occurred.
+*/
+
+int QUICK_ROR_UNION_SELECT::get_next()
+{
+ int error, dup_row;
+ QUICK_SELECT_I *quick;
+ byte *tmp;
+ DBUG_ENTER("QUICK_ROR_UNION_SELECT::get_next");
+
+ do
+ {
+ if (!queue.elements)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ /* Ok, we have a queue with >= 1 scans */
+
+ quick= (QUICK_SELECT_I*)queue_top(&queue);
+ memcpy(cur_rowid, quick->last_rowid, rowid_length);
+
+ /* put into queue rowid from the same stream as top element */
+ if ((error= quick->get_next()))
+ {
+ if (error != HA_ERR_END_OF_FILE)
+ DBUG_RETURN(error);
+ queue_remove(&queue, 0);
+ }
+ else
+ {
+ quick->save_last_pos();
+ queue_replaced(&queue);
+ }
+
+ if (!have_prev_rowid)
+ {
+ /* No rows have been returned yet */
+ dup_row= FALSE;
+ have_prev_rowid= TRUE;
+ }
+ else
+ dup_row= !head->file->cmp_ref(cur_rowid, prev_rowid);
+ }while (dup_row);
+
+ tmp= cur_rowid;
+ cur_rowid= prev_rowid;
+ prev_rowid= tmp;
+
+ error= head->file->rnd_pos(quick->record, prev_rowid);
+ DBUG_RETURN(error);
+}
+
+int QUICK_RANGE_SELECT::reset()
+{
+ uint mrange_bufsiz;
+ byte *mrange_buff;
+ DBUG_ENTER("QUICK_RANGE_SELECT::reset");
+ next=0;
+ range= NULL;
+ in_range= FALSE;
+ cur_range= (QUICK_RANGE**) ranges.buffer;
+
+ if (file->inited == handler::NONE && (error= file->ha_index_init(index)))
+ DBUG_RETURN(error);
+
+ /* Do not allocate the buffers twice. */
+ if (multi_range_length)
+ {
+ DBUG_ASSERT(multi_range_length == min(multi_range_count, ranges.elements));
+ DBUG_RETURN(0);
+ }
+
+ /* Allocate the ranges array. */
+ DBUG_ASSERT(ranges.elements);
+ multi_range_length= min(multi_range_count, ranges.elements);
+ DBUG_ASSERT(multi_range_length > 0);
+ while (multi_range_length && ! (multi_range= (KEY_MULTI_RANGE*)
+ my_malloc(multi_range_length *
+ sizeof(KEY_MULTI_RANGE),
+ MYF(MY_WME))))
+ {
+ /* Try to shrink the buffers until it is 0. */
+ multi_range_length/= 2;
+ }
+ if (! multi_range)
+ {
+ multi_range_length= 0;
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+
+ /* Allocate the handler buffer if necessary. */
+ if (file->table_flags() & HA_NEED_READ_RANGE_BUFFER)
+ {
+ mrange_bufsiz= min(multi_range_bufsiz,
+ (QUICK_SELECT_I::records + 1)* head->s->reclength);
+
+ while (mrange_bufsiz &&
+ ! my_multi_malloc(MYF(MY_WME),
+ &multi_range_buff, sizeof(*multi_range_buff),
+ &mrange_buff, mrange_bufsiz,
+ NullS))
+ {
+ /* Try to shrink the buffers until both are 0. */
+ mrange_bufsiz/= 2;
+ }
+ if (! multi_range_buff)
+ {
+ my_free((char*) multi_range, MYF(0));
+ multi_range= NULL;
+ multi_range_length= 0;
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+
+ /* Initialize the handler buffer. */
+ multi_range_buff->buffer= mrange_buff;
+ multi_range_buff->buffer_end= mrange_buff + mrange_bufsiz;
+ multi_range_buff->end_of_used_area= mrange_buff;
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Get next possible record using quick-struct.
+
+ SYNOPSIS
+ QUICK_RANGE_SELECT::get_next()
+
+ NOTES
+ Record is read into table->record[0]
+
+ RETURN
+ 0 Found row
+ HA_ERR_END_OF_FILE No (more) rows in range
+ # Error code
+*/
+
+int QUICK_RANGE_SELECT::get_next()
{
- DBUG_ENTER("get_next");
+ int result;
+ KEY_MULTI_RANGE *mrange;
+ key_range *start_key;
+ key_range *end_key;
+ DBUG_ENTER("QUICK_RANGE_SELECT::get_next");
+ DBUG_ASSERT(multi_range_length && multi_range &&
+ (cur_range >= (QUICK_RANGE**) ranges.buffer) &&
+ (cur_range <= (QUICK_RANGE**) ranges.buffer + ranges.elements));
+
+ for (;;)
+ {
+ if (in_range)
+ {
+ /* We did already start to read this key. */
+ result= file->read_multi_range_next(&mrange);
+ if (result != HA_ERR_END_OF_FILE)
+ {
+ in_range= ! result;
+ DBUG_RETURN(result);
+ }
+ }
+
+ uint count= min(multi_range_length, ranges.elements -
+ (cur_range - (QUICK_RANGE**) ranges.buffer));
+ if (count == 0)
+ {
+ /* Ranges have already been used up before. None is left for read. */
+ in_range= FALSE;
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
+ KEY_MULTI_RANGE *mrange_slot, *mrange_end;
+ for (mrange_slot= multi_range, mrange_end= mrange_slot+count;
+ mrange_slot < mrange_end;
+ mrange_slot++)
+ {
+ start_key= &mrange_slot->start_key;
+ end_key= &mrange_slot->end_key;
+ range= *(cur_range++);
+
+ start_key->key= (const byte*) range->min_key;
+ start_key->length= range->min_length;
+ start_key->flag= ((range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
+ (range->flag & EQ_RANGE) ?
+ HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
+ end_key->key= (const byte*) range->max_key;
+ end_key->length= range->max_length;
+ /*
+ We use HA_READ_AFTER_KEY here because if we are reading on a key
+ prefix. We want to find all keys with this prefix.
+ */
+ end_key->flag= (range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
+ HA_READ_AFTER_KEY);
+
+ mrange_slot->range_flag= range->flag;
+ }
+
+ result= file->read_multi_range_first(&mrange, multi_range, count,
+ sorted, multi_range_buff);
+ if (result != HA_ERR_END_OF_FILE)
+ {
+ in_range= ! result;
+ DBUG_RETURN(result);
+ }
+ in_range= FALSE; /* No matching rows; go to next set of ranges. */
+ }
+}
+
+
+/*
+ Get the next record with a different prefix.
+
+ SYNOPSIS
+ QUICK_RANGE_SELECT::get_next_prefix()
+ prefix_length length of cur_prefix
+ cur_prefix prefix of a key to be searched for
+
+ DESCRIPTION
+ Each subsequent call to the method retrieves the first record that has a
+ prefix with length prefix_length different from cur_prefix, such that the
+ record with the new prefix is within the ranges described by
+ this->ranges. The record found is stored into the buffer pointed by
+ this->record.
+ The method is useful for GROUP-BY queries with range conditions to
+ discover the prefix of the next group that satisfies the range conditions.
+
+ TODO
+ This method is a modified copy of QUICK_RANGE_SELECT::get_next(), so both
+ methods should be unified into a more general one to reduce code
+ duplication.
+
+ RETURN
+ 0 on success
+ HA_ERR_END_OF_FILE if returned all keys
+ other if some error occurred
+*/
+
+int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
+{
+ DBUG_ENTER("QUICK_RANGE_SELECT::get_next_prefix");
for (;;)
{
@@ -2679,22 +6219,30 @@ int QUICK_SELECT::get_next()
key_range start_key, end_key;
if (range)
{
- // Already read through key
- result= file->read_range_next();
- if (result != HA_ERR_END_OF_FILE)
- DBUG_RETURN(result);
+ /* Read the next record in the same range with prefix after cur_prefix. */
+ DBUG_ASSERT(cur_prefix != 0);
+ result= file->index_read(record, cur_prefix, prefix_length,
+ HA_READ_AFTER_KEY);
+ if (result || (file->compare_key(file->end_range) <= 0))
+ DBUG_RETURN(result);
}
- if (!(range= it++))
- DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
+ uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer);
+ if (count == 0)
+ {
+ /* Ranges have already been used up before. None is left for read. */
+ range= 0;
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
+ range= *(cur_range++);
start_key.key= (const byte*) range->min_key;
- start_key.length= range->min_length;
+ start_key.length= min(range->min_length, prefix_length);
start_key.flag= ((range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
(range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
end_key.key= (const byte*) range->max_key;
- end_key.length= range->max_length;
+ end_key.length= min(range->max_length, prefix_length);
/*
We use READ_AFTER_KEY here because if we are reading on a key
prefix we want to find all keys with this prefix
@@ -2718,9 +6266,9 @@ int QUICK_SELECT::get_next()
/* Get next for geometrical indexes */
-int QUICK_SELECT_GEOM::get_next()
+int QUICK_RANGE_SELECT_GEOM::get_next()
{
- DBUG_ENTER(" QUICK_SELECT_GEOM::get_next");
+ DBUG_ENTER("QUICK_RANGE_SELECT_GEOM::get_next");
for (;;)
{
@@ -2734,8 +6282,14 @@ int QUICK_SELECT_GEOM::get_next()
DBUG_RETURN(result);
}
- if (!(range= it++))
- DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
+ uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer);
+ if (count == 0)
+ {
+ /* Ranges have already been used up before. None is left for read. */
+ range= 0;
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
+ range= *(cur_range++);
result= file->index_read(record,
(byte*) range->min_key,
@@ -2749,6 +6303,46 @@ int QUICK_SELECT_GEOM::get_next()
/*
+ Check if current row will be retrieved by this QUICK_RANGE_SELECT
+
+ NOTES
+ It is assumed that currently a scan is being done on another index
+ which reads all necessary parts of the index that is scanned by this
+ quick select.
+ The implementation does a binary search on sorted array of disjoint
+ ranges, without taking size of range into account.
+
+ This function is used to filter out clustered PK scan rows in
+ index_merge quick select.
+
+ RETURN
+ TRUE if current row will be retrieved by this quick select
+ FALSE if not
+*/
+
+bool QUICK_RANGE_SELECT::row_in_ranges()
+{
+ QUICK_RANGE *range;
+ uint min= 0;
+ uint max= ranges.elements - 1;
+ uint mid= (max + min)/2;
+
+ while (min != max)
+ {
+ if (cmp_next(*(QUICK_RANGE**)dynamic_array_ptr(&ranges, mid)))
+ {
+ /* current row value > mid->max */
+ min= mid + 1;
+ }
+ else
+ max= mid;
+ mid= (min + max) / 2;
+ }
+ range= *(QUICK_RANGE**)dynamic_array_ptr(&ranges, mid);
+ return (!cmp_next(range) && !cmp_prev(range));
+}
+
+/*
This is a hack: we inherit from QUICK_SELECT so that we can use the
get_next() interface, but we have to hold a pointer to the original
QUICK_SELECT because its data are used all over the place. What
@@ -2758,16 +6352,17 @@ int QUICK_SELECT_GEOM::get_next()
for now, this seems to work right at least.
*/
-QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_SELECT *q, uint used_key_parts)
- : QUICK_SELECT(*q), rev_it(rev_ranges)
+QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q,
+ uint used_key_parts)
+ : QUICK_RANGE_SELECT(*q), rev_it(rev_ranges)
{
QUICK_RANGE *r;
- it.rewind();
- for (r = it++; r; r = it++)
- {
- rev_ranges.push_front(r);
- }
+ QUICK_RANGE **pr= (QUICK_RANGE**)ranges.buffer;
+ QUICK_RANGE **last_range= pr + ranges.elements;
+ 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++)
{
@@ -2860,10 +6455,51 @@ int QUICK_SELECT_DESC::get_next()
/*
+ Compare if found key is over max-value
+ Returns 0 if key <= range->max_key
+*/
+
+int QUICK_RANGE_SELECT::cmp_next(QUICK_RANGE *range_arg)
+{
+ if (range_arg->flag & NO_MAX_RANGE)
+ return 0; /* key can't be to large */
+
+ KEY_PART *key_part=key_parts;
+ uint store_length;
+
+ for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
+ key < end;
+ key+= store_length, key_part++)
+ {
+ int cmp;
+ store_length= key_part->store_length;
+ if (key_part->null_bit)
+ {
+ if (*key)
+ {
+ if (!key_part->field->is_null())
+ return 1;
+ continue;
+ }
+ else if (key_part->field->is_null())
+ return 0;
+ key++; // Skip null byte
+ store_length--;
+ }
+ if ((cmp=key_part->field->key_cmp((byte*) key, key_part->length)) < 0)
+ return 0;
+ if (cmp > 0)
+ return 1;
+ }
+ return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match
+}
+
+
+/*
Returns 0 if found key is inside range (found key >= range->min_key).
*/
-int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
+int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg)
{
int cmp;
if (range_arg->flag & NO_MIN_RANGE)
@@ -2878,7 +6514,7 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
/*
- * True if this range will require using HA_READ_AFTER_KEY
+ * TRUE if this range will require using HA_READ_AFTER_KEY
See comment in get_next() about this
*/
@@ -2890,7 +6526,7 @@ bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg)
}
-/* True if we are reading over a key that may have a NULL value */
+/* TRUE if we are reading over a key that may have a NULL value */
#ifdef NOT_USED
bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
@@ -2938,6 +6574,2230 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
#endif
+void QUICK_RANGE_SELECT::add_info_string(String *str)
+{
+ KEY *key_info= head->key_info + index;
+ str->append(key_info->name);
+}
+
+void QUICK_INDEX_MERGE_SELECT::add_info_string(String *str)
+{
+ QUICK_RANGE_SELECT *quick;
+ bool first= TRUE;
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ str->append("sort_union(");
+ while ((quick= it++))
+ {
+ if (!first)
+ str->append(',');
+ else
+ first= FALSE;
+ quick->add_info_string(str);
+ }
+ if (pk_quick_select)
+ {
+ str->append(',');
+ pk_quick_select->add_info_string(str);
+ }
+ str->append(')');
+}
+
+void QUICK_ROR_INTERSECT_SELECT::add_info_string(String *str)
+{
+ bool first= TRUE;
+ QUICK_RANGE_SELECT *quick;
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ str->append("intersect(");
+ while ((quick= it++))
+ {
+ KEY *key_info= head->key_info + quick->index;
+ if (!first)
+ str->append(',');
+ else
+ first= FALSE;
+ str->append(key_info->name);
+ }
+ if (cpk_quick)
+ {
+ KEY *key_info= head->key_info + cpk_quick->index;
+ str->append(',');
+ str->append(key_info->name);
+ }
+ str->append(')');
+}
+
+void QUICK_ROR_UNION_SELECT::add_info_string(String *str)
+{
+ bool first= TRUE;
+ QUICK_SELECT_I *quick;
+ List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
+ str->append("union(");
+ while ((quick= it++))
+ {
+ if (!first)
+ str->append(',');
+ else
+ first= FALSE;
+ quick->add_info_string(str);
+ }
+ str->append(')');
+}
+
+
+void QUICK_RANGE_SELECT::add_keys_and_lengths(String *key_names,
+ String *used_lengths)
+{
+ char buf[64];
+ uint length;
+ KEY *key_info= head->key_info + index;
+ key_names->append(key_info->name);
+ length= longlong2str(max_used_key_length, buf, 10) - buf;
+ used_lengths->append(buf, length);
+}
+
+void QUICK_INDEX_MERGE_SELECT::add_keys_and_lengths(String *key_names,
+ String *used_lengths)
+{
+ char buf[64];
+ uint length;
+ bool first= TRUE;
+ QUICK_RANGE_SELECT *quick;
+
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ while ((quick= it++))
+ {
+ if (first)
+ first= FALSE;
+ else
+ {
+ key_names->append(',');
+ used_lengths->append(',');
+ }
+
+ KEY *key_info= head->key_info + quick->index;
+ key_names->append(key_info->name);
+ length= longlong2str(quick->max_used_key_length, buf, 10) - buf;
+ used_lengths->append(buf, length);
+ }
+ if (pk_quick_select)
+ {
+ KEY *key_info= head->key_info + pk_quick_select->index;
+ key_names->append(',');
+ key_names->append(key_info->name);
+ length= longlong2str(pk_quick_select->max_used_key_length, buf, 10) - buf;
+ used_lengths->append(',');
+ used_lengths->append(buf, length);
+ }
+}
+
+void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names,
+ String *used_lengths)
+{
+ char buf[64];
+ uint length;
+ bool first= TRUE;
+ QUICK_RANGE_SELECT *quick;
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ while ((quick= it++))
+ {
+ KEY *key_info= head->key_info + quick->index;
+ if (first)
+ first= FALSE;
+ else
+ {
+ key_names->append(',');
+ used_lengths->append(',');
+ }
+ key_names->append(key_info->name);
+ length= longlong2str(quick->max_used_key_length, buf, 10) - buf;
+ used_lengths->append(buf, length);
+ }
+
+ if (cpk_quick)
+ {
+ KEY *key_info= head->key_info + cpk_quick->index;
+ key_names->append(',');
+ key_names->append(key_info->name);
+ length= longlong2str(cpk_quick->max_used_key_length, buf, 10) - buf;
+ used_lengths->append(',');
+ used_lengths->append(buf, length);
+ }
+}
+
+void QUICK_ROR_UNION_SELECT::add_keys_and_lengths(String *key_names,
+ String *used_lengths)
+{
+ bool first= TRUE;
+ QUICK_SELECT_I *quick;
+ List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
+ while ((quick= it++))
+ {
+ if (first)
+ first= FALSE;
+ else
+ {
+ used_lengths->append(',');
+ key_names->append(',');
+ }
+ quick->add_keys_and_lengths(key_names, used_lengths);
+ }
+}
+
+
+/*******************************************************************************
+* Implementation of QUICK_GROUP_MIN_MAX_SELECT
+*******************************************************************************/
+
+static inline uint get_field_keypart(KEY *index, Field *field);
+static inline SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree,
+ PARAM *param, uint *param_idx);
+static bool
+get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
+ KEY_PART_INFO *first_non_group_part,
+ KEY_PART_INFO *min_max_arg_part,
+ KEY_PART_INFO *last_part, THD *thd,
+ byte *key_infix, uint *key_infix_len,
+ KEY_PART_INFO **first_non_infix_part);
+static bool
+check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item,
+ Field::imagetype image_type);
+
+static void
+cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
+ uint group_key_parts, SEL_TREE *range_tree,
+ SEL_ARG *index_tree, ha_rows quick_prefix_records,
+ bool have_min, bool have_max,
+ double *read_cost, ha_rows *records);
+
+/*
+ Test if this access method is applicable to a GROUP query with MIN/MAX
+ functions, and if so, construct a new TRP object.
+
+ SYNOPSIS
+ get_best_group_min_max()
+ param Parameter from test_quick_select
+ sel_tree Range tree generated by get_mm_tree
+
+ DESCRIPTION
+ Test whether a query can be computed via a QUICK_GROUP_MIN_MAX_SELECT.
+ Queries computable via a QUICK_GROUP_MIN_MAX_SELECT must satisfy the
+ following conditions:
+ A) Table T has at least one compound index I of the form:
+ I = <A_1, ...,A_k, [B_1,..., B_m], C, [D_1,...,D_n]>
+ B) Query conditions:
+ B0. Q is over a single table T.
+ B1. The attributes referenced by Q are a subset of the attributes of I.
+ B2. All attributes QA in Q can be divided into 3 overlapping groups:
+ - SA = {S_1, ..., S_l, [C]} - from the SELECT clause, where C is
+ referenced by any number of MIN and/or MAX functions if present.
+ - WA = {W_1, ..., W_p} - from the WHERE clause
+ - GA = <G_1, ..., G_k> - from the GROUP BY clause (if any)
+ = SA - if Q is a DISTINCT query (based on the
+ equivalence of DISTINCT and GROUP queries.
+ - NGA = QA - (GA union C) = {NG_1, ..., NG_m} - the ones not in
+ GROUP BY and not referenced by MIN/MAX functions.
+ with the following properties specified below.
+ B3. If Q has a GROUP BY WITH ROLLUP clause the access method is not
+ applicable.
+
+ SA1. There is at most one attribute in SA referenced by any number of
+ MIN and/or MAX functions which, which if present, is denoted as C.
+ SA2. The position of the C attribute in the index is after the last A_k.
+ SA3. The attribute C can be referenced in the WHERE clause only in
+ predicates of the forms:
+ - (C {< | <= | > | >= | =} const)
+ - (const {< | <= | > | >= | =} C)
+ - (C between const_i and const_j)
+ - C IS NULL
+ - C IS NOT NULL
+ - C != const
+ SA4. If Q has a GROUP BY clause, there are no other aggregate functions
+ except MIN and MAX. For queries with DISTINCT, aggregate functions
+ are allowed.
+ SA5. The select list in DISTINCT queries should not contain expressions.
+ GA1. If Q has a GROUP BY clause, then GA is a prefix of I. That is, if
+ G_i = A_j => i = j.
+ GA2. If Q has a DISTINCT clause, then there is a permutation of SA that
+ forms a prefix of I. This permutation is used as the GROUP clause
+ when the DISTINCT query is converted to a GROUP query.
+ GA3. The attributes in GA may participate in arbitrary predicates, divided
+ into two groups:
+ - RNG(G_1,...,G_q ; where q <= k) is a range condition over the
+ attributes of a prefix of GA
+ - PA(G_i1,...G_iq) is an arbitrary predicate over an arbitrary subset
+ of GA. Since P is applied to only GROUP attributes it filters some
+ groups, and thus can be applied after the grouping.
+ GA4. There are no expressions among G_i, just direct column references.
+ NGA1.If in the index I there is a gap between the last GROUP attribute G_k,
+ and the MIN/MAX attribute C, then NGA must consist of exactly the index
+ attributes that constitute the gap. As a result there is a permutation
+ of NGA that coincides with the gap in the index <B_1, ..., B_m>.
+ NGA2.If BA <> {}, then the WHERE clause must contain a conjunction EQ of
+ equality conditions for all NG_i of the form (NG_i = const) or
+ (const = NG_i), such that each NG_i is referenced in exactly one
+ conjunct. Informally, the predicates provide constants to fill the
+ gap in the index.
+ WA1. There are no other attributes in the WHERE clause except the ones
+ referenced in predicates RNG, PA, PC, EQ defined above. Therefore
+ WA is subset of (GA union NGA union C) for GA,NGA,C that pass the above
+ tests. By transitivity then it also follows that each WA_i participates
+ in the index I (if this was already tested for GA, NGA and C).
+
+ C) Overall query form:
+ SELECT EXPR([A_1,...,A_k], [B_1,...,B_m], [MIN(C)], [MAX(C)])
+ FROM T
+ WHERE [RNG(A_1,...,A_p ; where p <= k)]
+ [AND EQ(B_1,...,B_m)]
+ [AND PC(C)]
+ [AND PA(A_i1,...,A_iq)]
+ GROUP BY A_1,...,A_k
+ [HAVING PH(A_1, ..., B_1,..., C)]
+ where EXPR(...) is an arbitrary expression over some or all SELECT fields,
+ or:
+ SELECT DISTINCT A_i1,...,A_ik
+ FROM T
+ WHERE [RNG(A_1,...,A_p ; where p <= k)]
+ [AND PA(A_i1,...,A_iq)];
+
+ NOTES
+ If the current query satisfies the conditions above, and if
+ (mem_root! = NULL), then the function constructs and returns a new TRP
+ object, that is later used to construct a new QUICK_GROUP_MIN_MAX_SELECT.
+ If (mem_root == NULL), then the function only tests whether the current
+ query satisfies the conditions above, and, if so, sets
+ is_applicable = TRUE.
+
+ Queries with DISTINCT for which index access can be used are transformed
+ into equivalent group-by queries of the form:
+
+ SELECT A_1,...,A_k FROM T
+ WHERE [RNG(A_1,...,A_p ; where p <= k)]
+ [AND PA(A_i1,...,A_iq)]
+ GROUP BY A_1,...,A_k;
+
+ The group-by list is a permutation of the select attributes, according
+ to their order in the index.
+
+ TODO
+ - What happens if the query groups by the MIN/MAX field, and there is no
+ other field as in: "select min(a) from t1 group by a" ?
+ - We assume that the general correctness of the GROUP-BY query was checked
+ before this point. Is this correct, or do we have to check it completely?
+ - Lift the limitation in condition (B3), that is, make this access method
+ applicable to ROLLUP queries.
+
+ RETURN
+ If mem_root != NULL
+ - valid TRP_GROUP_MIN_MAX object if this QUICK class can be used for
+ the query
+ - NULL o/w.
+ If mem_root == NULL
+ - NULL
+*/
+
+static TRP_GROUP_MIN_MAX *
+get_best_group_min_max(PARAM *param, SEL_TREE *tree)
+{
+ THD *thd= param->thd;
+ JOIN *join= thd->lex->select_lex.join;
+ TABLE *table= param->table;
+ bool have_min= FALSE; /* TRUE if there is a MIN function. */
+ bool have_max= FALSE; /* TRUE if there is a MAX function. */
+ Item_field *min_max_arg_item= NULL;/* The argument of all MIN/MAX functions.*/
+ KEY_PART_INFO *min_max_arg_part= NULL; /* The corresponding keypart. */
+ uint group_prefix_len= 0; /* Length (in bytes) of the key prefix. */
+ KEY *index_info= NULL; /* The index chosen for data access. */
+ uint index= 0; /* The id of the chosen index. */
+ uint group_key_parts= 0; /* Number of index key parts in the group prefix. */
+ uint used_key_parts= 0; /* Number of index key parts used for access. */
+ byte key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/
+ uint key_infix_len= 0; /* Length of key_infix. */
+ TRP_GROUP_MIN_MAX *read_plan= NULL; /* The eventually constructed TRP. */
+ uint key_part_nr;
+ ORDER *tmp_group;
+ Item *item;
+ Item_field *item_field;
+ DBUG_ENTER("get_best_group_min_max");
+
+ /* Perform few 'cheap' tests whether this access method is applicable. */
+ if (!join || (thd->lex->sql_command != SQLCOM_SELECT))
+ DBUG_RETURN(NULL); /* This is not a select statement. */
+ if ((join->tables != 1) || /* The query must reference one table. */
+ ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
+ (!join->select_distinct)) ||
+ (thd->lex->select_lex.olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */
+ DBUG_RETURN(NULL);
+ if (table->s->keys == 0) /* There are no indexes to use. */
+ DBUG_RETURN(NULL);
+
+ /* Analyze the query in more detail. */
+ List_iterator<Item> select_items_it(join->fields_list);
+
+ /* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/
+ if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
+ DBUG_RETURN(NULL);
+ if (join->sum_funcs[0])
+ {
+ Item_sum *min_max_item;
+ Item_sum **func_ptr= join->sum_funcs;
+ while ((min_max_item= *(func_ptr++)))
+ {
+ if (min_max_item->sum_func() == Item_sum::MIN_FUNC)
+ have_min= TRUE;
+ else if (min_max_item->sum_func() == Item_sum::MAX_FUNC)
+ have_max= TRUE;
+ else
+ DBUG_RETURN(NULL);
+
+ Item *expr= min_max_item->args[0]; /* The argument of MIN/MAX. */
+ if (expr->type() == Item::FIELD_ITEM) /* Is it an attribute? */
+ {
+ if (! min_max_arg_item)
+ min_max_arg_item= (Item_field*) expr;
+ else if (! min_max_arg_item->eq(expr, 1))
+ DBUG_RETURN(NULL);
+ }
+ else
+ DBUG_RETURN(NULL);
+ }
+ }
+
+ /* Check (SA5). */
+ if (join->select_distinct)
+ {
+ while ((item= select_items_it++))
+ {
+ if (item->type() != Item::FIELD_ITEM)
+ DBUG_RETURN(NULL);
+ }
+ }
+
+ /* Check (GA4) - that there are no expressions among the group attributes. */
+ for (tmp_group= join->group_list; tmp_group; tmp_group= tmp_group->next)
+ {
+ if ((*tmp_group->item)->type() != Item::FIELD_ITEM)
+ DBUG_RETURN(NULL);
+ }
+
+ /*
+ Check that table has at least one compound index such that the conditions
+ (GA1,GA2) are all TRUE. If there is more than one such index, select the
+ first one. Here we set the variables: group_prefix_len and index_info.
+ */
+ KEY *cur_index_info= table->key_info;
+ KEY *cur_index_info_end= cur_index_info + table->s->keys;
+ KEY_PART_INFO *cur_part= NULL;
+ KEY_PART_INFO *end_part; /* Last part for loops. */
+ /* Last index part. */
+ KEY_PART_INFO *last_part= NULL;
+ KEY_PART_INFO *first_non_group_part= NULL;
+ KEY_PART_INFO *first_non_infix_part= NULL;
+ uint key_infix_parts= 0;
+ uint cur_group_key_parts= 0;
+ uint cur_group_prefix_len= 0;
+ /* Cost-related variables for the best index so far. */
+ double best_read_cost= DBL_MAX;
+ ha_rows best_records= 0;
+ SEL_ARG *best_index_tree= NULL;
+ ha_rows best_quick_prefix_records= 0;
+ uint best_param_idx= 0;
+ double cur_read_cost= DBL_MAX;
+ ha_rows cur_records;
+ SEL_ARG *cur_index_tree= NULL;
+ ha_rows cur_quick_prefix_records= 0;
+ uint cur_param_idx;
+ key_map cur_used_key_parts;
+ uint pk= param->table->s->primary_key;
+
+ for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ;
+ cur_index_info++, cur_index++)
+ {
+ /* Check (B1) - if current index is covering. */
+ if (!table->used_keys.is_set(cur_index))
+ goto next_index;
+
+ /*
+ If the current storage manager is such that it appends the primary key to
+ each index, then the above condition is insufficient to check if the
+ index is covering. In such cases it may happen that some fields are
+ covered by the PK index, but not by the current index. Since we can't
+ use the concatenation of both indexes for index lookup, such an index
+ does not qualify as covering in our case. If this is the case, below
+ we check that all query fields are indeed covered by 'cur_index'.
+ */
+ if (pk < MAX_KEY && cur_index != pk &&
+ (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
+ {
+ /* For each table field */
+ for (uint i= 0; i < table->s->fields; i++)
+ {
+ Field *cur_field= table->field[i];
+ /*
+ If the field is used in the current query, check that the
+ field is covered by some keypart of the current index.
+ */
+ if (thd->query_id == cur_field->query_id)
+ {
+ bool is_covered= FALSE;
+ KEY_PART_INFO *key_part= cur_index_info->key_part;
+ KEY_PART_INFO *key_part_end= key_part + cur_index_info->key_parts;
+ for (; key_part != key_part_end ; key_part++)
+ {
+ if (key_part->field == cur_field)
+ {
+ is_covered= TRUE;
+ break;
+ }
+ }
+ if (!is_covered)
+ goto next_index;
+ }
+ }
+ }
+
+ /*
+ Check (GA1) for GROUP BY queries.
+ */
+ if (join->group_list)
+ {
+ cur_part= cur_index_info->key_part;
+ end_part= cur_part + cur_index_info->key_parts;
+ /* Iterate in parallel over the GROUP list and the index parts. */
+ for (tmp_group= join->group_list; tmp_group && (cur_part != end_part);
+ tmp_group= tmp_group->next, cur_part++)
+ {
+ /*
+ TODO:
+ tmp_group::item is an array of Item, is it OK to consider only the
+ first Item? If so, then why? What is the array for?
+ */
+ /* Above we already checked that all group items are fields. */
+ DBUG_ASSERT((*tmp_group->item)->type() == Item::FIELD_ITEM);
+ Item_field *group_field= (Item_field *) (*tmp_group->item);
+ if (group_field->field->eq(cur_part->field))
+ {
+ cur_group_prefix_len+= cur_part->store_length;
+ ++cur_group_key_parts;
+ }
+ else
+ goto next_index;
+ }
+ }
+ /*
+ Check (GA2) if this is a DISTINCT query.
+ If GA2, then Store a new ORDER object in group_fields_array at the
+ position of the key part of item_field->field. Thus we get the ORDER
+ objects for each field ordered as the corresponding key parts.
+ Later group_fields_array of ORDER objects is used to convert the query
+ to a GROUP query.
+ */
+ else if (join->select_distinct)
+ {
+ select_items_it.rewind();
+ cur_used_key_parts.clear_all();
+ while ((item= select_items_it++))
+ {
+ item_field= (Item_field*) item; /* (SA5) already checked above. */
+ /* Find the order of the key part in the index. */
+ key_part_nr= get_field_keypart(cur_index_info, item_field->field);
+ /*
+ Check if this attribute was already present in the select list.
+ If it was present, then its corresponding key part was alredy used.
+ */
+ if (cur_used_key_parts.is_set(key_part_nr))
+ continue;
+ if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
+ goto next_index;
+ cur_part= cur_index_info->key_part + key_part_nr - 1;
+ cur_group_prefix_len+= cur_part->store_length;
+ cur_used_key_parts.set_bit(key_part_nr);
+ ++cur_group_key_parts;
+ }
+ }
+ else
+ DBUG_ASSERT(FALSE);
+
+ /* Check (SA2). */
+ if (min_max_arg_item)
+ {
+ key_part_nr= get_field_keypart(cur_index_info, min_max_arg_item->field);
+ if (key_part_nr <= cur_group_key_parts)
+ goto next_index;
+ min_max_arg_part= cur_index_info->key_part + key_part_nr - 1;
+ }
+
+ /*
+ Check (NGA1, NGA2) and extract a sequence of constants to be used as part
+ of all search keys.
+ */
+
+ /*
+ If there is MIN/MAX, each keypart between the last group part and the
+ MIN/MAX part must participate in one equality with constants, and all
+ keyparts after the MIN/MAX part must not be referenced in the query.
+
+ If there is no MIN/MAX, the keyparts after the last group part can be
+ referenced only in equalities with constants, and the referenced keyparts
+ must form a sequence without any gaps that starts immediately after the
+ last group keypart.
+ */
+ last_part= cur_index_info->key_part + cur_index_info->key_parts;
+ first_non_group_part= (cur_group_key_parts < cur_index_info->key_parts) ?
+ cur_index_info->key_part + cur_group_key_parts :
+ NULL;
+ first_non_infix_part= min_max_arg_part ?
+ (min_max_arg_part < last_part) ?
+ min_max_arg_part + 1 :
+ NULL :
+ NULL;
+ if (first_non_group_part &&
+ (!min_max_arg_part || (min_max_arg_part - first_non_group_part > 0)))
+ {
+ if (tree)
+ {
+ uint dummy;
+ SEL_ARG *index_range_tree= get_index_range_tree(cur_index, tree, param,
+ &dummy);
+ if (!get_constant_key_infix(cur_index_info, index_range_tree,
+ first_non_group_part, min_max_arg_part,
+ last_part, thd, key_infix, &key_infix_len,
+ &first_non_infix_part))
+ goto next_index;
+ }
+ else if (min_max_arg_part &&
+ (min_max_arg_part - first_non_group_part > 0))
+ /*
+ There is a gap but no range tree, thus no predicates at all for the
+ non-group keyparts.
+ */
+ goto next_index;
+ }
+
+ /*
+ Test (WA1) partially - that no other keypart after the last infix part is
+ referenced in the query.
+ */
+ if (first_non_infix_part)
+ {
+ for (cur_part= first_non_infix_part; cur_part != last_part; cur_part++)
+ {
+ if (cur_part->field->query_id == thd->query_id)
+ goto next_index;
+ }
+ }
+
+ /* If we got to this point, cur_index_info passes the test. */
+ key_infix_parts= key_infix_len ?
+ (first_non_infix_part - first_non_group_part) : 0;
+ used_key_parts= cur_group_key_parts + key_infix_parts;
+
+ /* Compute the cost of using this index. */
+ if (tree)
+ {
+ /* Find the SEL_ARG sub-tree that corresponds to the chosen index. */
+ cur_index_tree= get_index_range_tree(cur_index, tree, param,
+ &cur_param_idx);
+ /* Check if this range tree can be used for prefix retrieval. */
+ cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
+ cur_index_tree);
+ }
+ cost_group_min_max(table, cur_index_info, used_key_parts,
+ cur_group_key_parts, tree, cur_index_tree,
+ cur_quick_prefix_records, have_min, have_max,
+ &cur_read_cost, &cur_records);
+ /*
+ If cur_read_cost is lower than best_read_cost use cur_index.
+ Do not compare doubles directly because they may have different
+ representations (64 vs. 80 bits).
+ */
+ if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost))
+ {
+ index_info= cur_index_info;
+ index= cur_index;
+ best_read_cost= cur_read_cost;
+ best_records= cur_records;
+ best_index_tree= cur_index_tree;
+ best_quick_prefix_records= cur_quick_prefix_records;
+ best_param_idx= cur_param_idx;
+ group_key_parts= cur_group_key_parts;
+ group_prefix_len= cur_group_prefix_len;
+ }
+
+ next_index:
+ cur_group_key_parts= 0;
+ cur_group_prefix_len= 0;
+ }
+ if (!index_info) /* No usable index found. */
+ DBUG_RETURN(NULL);
+
+ /* Check (SA3) for the where clause. */
+ if (join->conds && min_max_arg_item &&
+ !check_group_min_max_predicates(join->conds, min_max_arg_item,
+ (index_info->flags & HA_SPATIAL) ?
+ Field::itMBR : Field::itRAW))
+ DBUG_RETURN(NULL);
+
+ /* The query passes all tests, so construct a new TRP object. */
+ read_plan= new (param->mem_root)
+ TRP_GROUP_MIN_MAX(have_min, have_max, min_max_arg_part,
+ group_prefix_len, used_key_parts,
+ group_key_parts, index_info, index,
+ key_infix_len,
+ (key_infix_len > 0) ? key_infix : NULL,
+ tree, best_index_tree, best_param_idx,
+ best_quick_prefix_records);
+ if (read_plan)
+ {
+ if (tree && read_plan->quick_prefix_records == 0)
+ DBUG_RETURN(NULL);
+
+ read_plan->read_cost= best_read_cost;
+ read_plan->records= best_records;
+
+ DBUG_PRINT("info",
+ ("Returning group min/max plan: cost: %g, records: %lu",
+ read_plan->read_cost, (ulong) read_plan->records));
+ }
+
+ DBUG_RETURN(read_plan);
+}
+
+
+/*
+ Check that the MIN/MAX attribute participates only in range predicates
+ with constants.
+
+ SYNOPSIS
+ check_group_min_max_predicates()
+ cond tree (or subtree) describing all or part of the WHERE
+ clause being analyzed
+ min_max_arg_item the field referenced by the MIN/MAX function(s)
+ min_max_arg_part the keypart of the MIN/MAX argument if any
+
+ DESCRIPTION
+ The function walks recursively over the cond tree representing a WHERE
+ clause, and checks condition (SA3) - if a field is referenced by a MIN/MAX
+ aggregate function, it is referenced only by one of the following
+ predicates: {=, !=, <, <=, >, >=, between, is null, is not null}.
+
+ RETURN
+ TRUE if cond passes the test
+ FALSE o/w
+*/
+
+static bool
+check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item,
+ Field::imagetype image_type)
+{
+ DBUG_ENTER("check_group_min_max_predicates");
+ DBUG_ASSERT(cond && min_max_arg_item);
+
+ Item::Type cond_type= cond->type();
+ if (cond_type == Item::COND_ITEM) /* 'AND' or 'OR' */
+ {
+ DBUG_PRINT("info", ("Analyzing: %s", ((Item_func*) cond)->func_name()));
+ List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *and_or_arg;
+ while ((and_or_arg= li++))
+ {
+ if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item,
+ image_type))
+ DBUG_RETURN(FALSE);
+ }
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ TODO:
+ This is a very crude fix to handle sub-selects in the WHERE clause
+ (Item_subselect objects). With the test below we rule out from the
+ optimization all queries with subselects in the WHERE clause. What has to
+ be done, is that here we should analyze whether the subselect references
+ the MIN/MAX argument field, and disallow the optimization only if this is
+ so.
+ */
+ if (cond_type == Item::SUBSELECT_ITEM)
+ DBUG_RETURN(FALSE);
+
+ /* We presume that at this point there are no other Items than functions. */
+ DBUG_ASSERT(cond_type == Item::FUNC_ITEM);
+
+ /* Test if cond references only group-by or non-group fields. */
+ Item_func *pred= (Item_func*) cond;
+ Item **arguments= pred->arguments();
+ Item *cur_arg;
+ DBUG_PRINT("info", ("Analyzing: %s", pred->func_name()));
+ for (uint arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++)
+ {
+ cur_arg= arguments[arg_idx];
+ DBUG_PRINT("info", ("cur_arg: %s", cur_arg->full_name()));
+ if (cur_arg->type() == Item::FIELD_ITEM)
+ {
+ if (min_max_arg_item->eq(cur_arg, 1))
+ {
+ /*
+ If pred references the MIN/MAX argument, check whether pred is a range
+ condition that compares the MIN/MAX argument with a constant.
+ */
+ Item_func::Functype pred_type= pred->functype();
+ if (pred_type != Item_func::EQUAL_FUNC &&
+ pred_type != Item_func::LT_FUNC &&
+ pred_type != Item_func::LE_FUNC &&
+ pred_type != Item_func::GT_FUNC &&
+ pred_type != Item_func::GE_FUNC &&
+ pred_type != Item_func::BETWEEN &&
+ pred_type != Item_func::ISNULL_FUNC &&
+ pred_type != Item_func::ISNOTNULL_FUNC &&
+ pred_type != Item_func::EQ_FUNC &&
+ pred_type != Item_func::NE_FUNC)
+ DBUG_RETURN(FALSE);
+
+ /* Check that pred compares min_max_arg_item with a constant. */
+ Item *args[3];
+ bzero(args, 3 * sizeof(Item*));
+ bool inv;
+ /* Test if this is a comparison of a field and a constant. */
+ if (!simple_pred(pred, args, &inv))
+ DBUG_RETURN(FALSE);
+
+ /* Check for compatible string comparisons - similar to get_mm_leaf. */
+ if (args[0] && args[1] && !args[2] && // this is a binary function
+ min_max_arg_item->result_type() == STRING_RESULT &&
+ /*
+ Don't use an index when comparing strings of different collations.
+ */
+ ((args[1]->result_type() == STRING_RESULT &&
+ image_type == Field::itRAW &&
+ ((Field_str*) min_max_arg_item->field)->charset() !=
+ pred->compare_collation())
+ ||
+ /*
+ We can't always use indexes when comparing a string index to a
+ number.
+ */
+ (args[1]->result_type() != STRING_RESULT &&
+ min_max_arg_item->field->cmp_type() != args[1]->result_type())))
+ DBUG_RETURN(FALSE);
+ }
+ }
+ else if (cur_arg->type() == Item::FUNC_ITEM)
+ {
+ if (!check_group_min_max_predicates(cur_arg, min_max_arg_item,
+ image_type))
+ DBUG_RETURN(FALSE);
+ }
+ else if (cur_arg->const_item())
+ {
+ DBUG_RETURN(TRUE);
+ }
+ else
+ DBUG_RETURN(FALSE);
+ }
+
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Extract a sequence of constants from a conjunction of equality predicates.
+
+ SYNOPSIS
+ get_constant_key_infix()
+ index_info [in] Descriptor of the chosen index.
+ index_range_tree [in] Range tree for the chosen index
+ first_non_group_part [in] First index part after group attribute parts
+ min_max_arg_part [in] The keypart of the MIN/MAX argument if any
+ last_part [in] Last keypart of the index
+ thd [in] Current thread
+ key_infix [out] Infix of constants to be used for index lookup
+ key_infix_len [out] Lenghth of the infix
+ first_non_infix_part [out] The first keypart after the infix (if any)
+
+ DESCRIPTION
+ Test conditions (NGA1, NGA2) from get_best_group_min_max(). Namely,
+ for each keypart field NGF_i not in GROUP-BY, check that there is a
+ constant equality predicate among conds with the form (NGF_i = const_ci) or
+ (const_ci = NGF_i).
+ Thus all the NGF_i attributes must fill the 'gap' between the last group-by
+ attribute and the MIN/MAX attribute in the index (if present). If these
+ conditions hold, copy each constant from its corresponding predicate into
+ key_infix, in the order its NG_i attribute appears in the index, and update
+ key_infix_len with the total length of the key parts in key_infix.
+
+ RETURN
+ TRUE if the index passes the test
+ FALSE o/w
+*/
+
+static bool
+get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
+ KEY_PART_INFO *first_non_group_part,
+ KEY_PART_INFO *min_max_arg_part,
+ KEY_PART_INFO *last_part, THD *thd,
+ byte *key_infix, uint *key_infix_len,
+ KEY_PART_INFO **first_non_infix_part)
+{
+ SEL_ARG *cur_range;
+ KEY_PART_INFO *cur_part;
+ /* End part for the first loop below. */
+ KEY_PART_INFO *end_part= min_max_arg_part ? min_max_arg_part : last_part;
+
+ *key_infix_len= 0;
+ byte *key_ptr= key_infix;
+ for (cur_part= first_non_group_part; cur_part != end_part; cur_part++)
+ {
+ /*
+ Find the range tree for the current keypart. We assume that
+ index_range_tree points to the leftmost keypart in the index.
+ */
+ for (cur_range= index_range_tree; cur_range;
+ cur_range= cur_range->next_key_part)
+ {
+ if (cur_range->field->eq(cur_part->field))
+ break;
+ }
+ if (!cur_range)
+ {
+ if (min_max_arg_part)
+ return FALSE; /* The current keypart has no range predicates at all. */
+ else
+ {
+ *first_non_infix_part= cur_part;
+ return TRUE;
+ }
+ }
+
+ /* Check that the current range tree is a single point interval. */
+ if (cur_range->prev || cur_range->next)
+ return FALSE; /* This is not the only range predicate for the field. */
+ if ((cur_range->min_flag & NO_MIN_RANGE) ||
+ (cur_range->max_flag & NO_MAX_RANGE) ||
+ (cur_range->min_flag & NEAR_MIN) || (cur_range->max_flag & NEAR_MAX))
+ return FALSE;
+
+ uint field_length= cur_part->store_length;
+ if ((cur_range->maybe_null &&
+ cur_range->min_value[0] && cur_range->max_value[0])
+ ||
+ (memcmp(cur_range->min_value, cur_range->max_value, field_length) == 0))
+ { /* cur_range specifies 'IS NULL' or an equality condition. */
+ memcpy(key_ptr, cur_range->min_value, field_length);
+ key_ptr+= field_length;
+ *key_infix_len+= field_length;
+ }
+ else
+ return FALSE;
+ }
+
+ if (!min_max_arg_part && (cur_part == last_part))
+ *first_non_infix_part= last_part;
+
+ return TRUE;
+}
+
+
+/*
+ Find the key part referenced by a field.
+
+ SYNOPSIS
+ get_field_keypart()
+ index descriptor of an index
+ field field that possibly references some key part in index
+
+ NOTES
+ The return value can be used to get a KEY_PART_INFO pointer by
+ part= index->key_part + get_field_keypart(...) - 1;
+
+ RETURN
+ Positive number which is the consecutive number of the key part, or
+ 0 if field does not reference any index field.
+*/
+
+static inline uint
+get_field_keypart(KEY *index, Field *field)
+{
+ KEY_PART_INFO *part, *end;
+
+ for (part= index->key_part, end= part + index->key_parts; part < end; part++)
+ {
+ if (field->eq(part->field))
+ return part - index->key_part + 1;
+ }
+ return 0;
+}
+
+
+/*
+ Find the SEL_ARG sub-tree that corresponds to the chosen index.
+
+ SYNOPSIS
+ get_index_range_tree()
+ index [in] The ID of the index being looked for
+ range_tree[in] Tree of ranges being searched
+ param [in] PARAM from SQL_SELECT::test_quick_select
+ param_idx [out] Index in the array PARAM::key that corresponds to 'index'
+
+ DESCRIPTION
+
+ A SEL_TREE contains range trees for all usable indexes. This procedure
+ finds the SEL_ARG sub-tree for 'index'. The members of a SEL_TREE are
+ ordered in the same way as the members of PARAM::key, thus we first find
+ the corresponding index in the array PARAM::key. This index is returned
+ through the variable param_idx, to be used later as argument of
+ check_quick_select().
+
+ RETURN
+ Pointer to the SEL_ARG subtree that corresponds to index.
+*/
+
+SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree, PARAM *param,
+ uint *param_idx)
+{
+ uint idx= 0; /* Index nr in param->key_parts */
+ while (idx < param->keys)
+ {
+ if (index == param->real_keynr[idx])
+ break;
+ idx++;
+ }
+ *param_idx= idx;
+ return(range_tree->keys[idx]);
+}
+
+
+/*
+ Compute the cost of a quick_group_min_max_select for a particular index.
+
+ SYNOPSIS
+ cost_group_min_max()
+ table [in] The table being accessed
+ index_info [in] The index used to access the table
+ used_key_parts [in] Number of key parts used to access the index
+ group_key_parts [in] Number of index key parts in the group prefix
+ range_tree [in] Tree of ranges for all indexes
+ index_tree [in] The range tree for the current index
+ quick_prefix_records [in] Number of records retrieved by the internally
+ used quick range select if any
+ have_min [in] True if there is a MIN function
+ have_max [in] True if there is a MAX function
+ read_cost [out] The cost to retrieve rows via this quick select
+ records [out] The number of rows retrieved
+
+ DESCRIPTION
+ This method computes the access cost of a TRP_GROUP_MIN_MAX instance and
+ the number of rows returned. It updates this->read_cost and this->records.
+
+ NOTES
+ The cost computation distinguishes several cases:
+ 1) No equality predicates over non-group attributes (thus no key_infix).
+ If groups are bigger than blocks on the average, then we assume that it
+ is very unlikely that block ends are aligned with group ends, thus even
+ if we look for both MIN and MAX keys, all pairs of neighbor MIN/MAX
+ keys, except for the first MIN and the last MAX keys, will be in the
+ same block. If groups are smaller than blocks, then we are going to
+ read all blocks.
+ 2) There are equality predicates over non-group attributes.
+ In this case the group prefix is extended by additional constants, and
+ as a result the min/max values are inside sub-groups of the original
+ groups. The number of blocks that will be read depends on whether the
+ ends of these sub-groups will be contained in the same or in different
+ blocks. We compute the probability for the two ends of a subgroup to be
+ in two different blocks as the ratio of:
+ - the number of positions of the left-end of a subgroup inside a group,
+ such that the right end of the subgroup is past the end of the buffer
+ containing the left-end, and
+ - the total number of possible positions for the left-end of the
+ subgroup, which is the number of keys in the containing group.
+ We assume it is very unlikely that two ends of subsequent subgroups are
+ in the same block.
+ 3) The are range predicates over the group attributes.
+ Then some groups may be filtered by the range predicates. We use the
+ selectivity of the range predicates to decide how many groups will be
+ filtered.
+
+ TODO
+ - Take into account the optional range predicates over the MIN/MAX
+ argument.
+ - Check if we have a PK index and we use all cols - then each key is a
+ group, and it will be better to use an index scan.
+
+ RETURN
+ None
+*/
+
+void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
+ uint group_key_parts, SEL_TREE *range_tree,
+ SEL_ARG *index_tree, ha_rows quick_prefix_records,
+ bool have_min, bool have_max,
+ double *read_cost, ha_rows *records)
+{
+ uint table_records;
+ uint num_groups;
+ uint num_blocks;
+ uint keys_per_block;
+ uint keys_per_group;
+ uint keys_per_subgroup; /* Average number of keys in sub-groups */
+ /* formed by a key infix. */
+ double p_overlap; /* Probability that a sub-group overlaps two blocks. */
+ double quick_prefix_selectivity;
+ double io_cost;
+ double cpu_cost= 0; /* TODO: CPU cost of index_read calls? */
+ DBUG_ENTER("cost_group_min_max");
+
+ table_records= table->file->records;
+ keys_per_block= (table->file->block_size / 2 /
+ (index_info->key_length + table->file->ref_length)
+ + 1);
+ num_blocks= (table_records / keys_per_block) + 1;
+
+ /* Compute the number of keys in a group. */
+ keys_per_group= index_info->rec_per_key[group_key_parts - 1];
+ if (keys_per_group == 0) /* If there is no statistics try to guess */
+ /* each group contains 10% of all records */
+ keys_per_group= (table_records / 10) + 1;
+ num_groups= (table_records / keys_per_group) + 1;
+
+ /* Apply the selectivity of the quick select for group prefixes. */
+ if (range_tree && (quick_prefix_records != HA_POS_ERROR))
+ {
+ quick_prefix_selectivity= (double) quick_prefix_records /
+ (double) table_records;
+ num_groups= (uint) rint(num_groups * quick_prefix_selectivity);
+ }
+
+ if (used_key_parts > group_key_parts)
+ { /*
+ Compute the probability that two ends of a subgroup are inside
+ different blocks.
+ */
+ keys_per_subgroup= index_info->rec_per_key[used_key_parts - 1];
+ if (keys_per_subgroup >= keys_per_block) /* If a subgroup is bigger than */
+ p_overlap= 1.0; /* a block, it will overlap at least two blocks. */
+ else
+ {
+ double blocks_per_group= (double) num_blocks / (double) num_groups;
+ p_overlap= (blocks_per_group * (keys_per_subgroup - 1)) / keys_per_group;
+ p_overlap= min(p_overlap, 1.0);
+ }
+ io_cost= (double) min(num_groups * (1 + p_overlap), num_blocks);
+ }
+ else
+ io_cost= (keys_per_group > keys_per_block) ?
+ (have_min && have_max) ? (double) (num_groups + 1) :
+ (double) num_groups :
+ (double) num_blocks;
+
+ /*
+ TODO: If there is no WHERE clause and no other expressions, there should be
+ no CPU cost. We leave it here to make this cost comparable to that of index
+ scan as computed in SQL_SELECT::test_quick_select().
+ */
+ cpu_cost= (double) num_groups / TIME_FOR_COMPARE;
+
+ *read_cost= io_cost + cpu_cost;
+ *records= num_groups;
+
+ DBUG_PRINT("info",
+ ("table rows=%u, keys/block=%u, keys/group=%u, result rows=%u, blocks=%u",
+ table_records, keys_per_block, keys_per_group, *records,
+ num_blocks));
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Construct a new quick select object for queries with group by with min/max.
+
+ SYNOPSIS
+ TRP_GROUP_MIN_MAX::make_quick()
+ param Parameter from test_quick_select
+ retrieve_full_rows ignored
+ parent_alloc Memory pool to use, if any.
+
+ NOTES
+ Make_quick ignores the retrieve_full_rows parameter because
+ QUICK_GROUP_MIN_MAX_SELECT always performs 'index only' scans.
+ The other parameter are ignored as well because all necessary
+ data to create the QUICK object is computed at this TRP creation
+ time.
+
+ RETURN
+ New QUICK_GROUP_MIN_MAX_SELECT object if successfully created,
+ NULL o/w.
+*/
+
+QUICK_SELECT_I *
+TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc)
+{
+ QUICK_GROUP_MIN_MAX_SELECT *quick;
+ DBUG_ENTER("TRP_GROUP_MIN_MAX::make_quick");
+
+ quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
+ param->thd->lex->select_lex.join,
+ have_min, have_max, min_max_arg_part,
+ group_prefix_len, used_key_parts,
+ index_info, index, read_cost, records,
+ key_infix_len, key_infix,
+ parent_alloc);
+ if (!quick)
+ DBUG_RETURN(NULL);
+
+ if (quick->init())
+ {
+ delete quick;
+ DBUG_RETURN(NULL);
+ }
+
+ if (range_tree)
+ {
+ DBUG_ASSERT(quick_prefix_records > 0);
+ if (quick_prefix_records == HA_POS_ERROR)
+ quick->quick_prefix_select= NULL; /* Can't construct a quick select. */
+ else
+ /* Make a QUICK_RANGE_SELECT to be used for group prefix retrieval. */
+ quick->quick_prefix_select= get_quick_select(param, param_idx,
+ index_tree,
+ &quick->alloc);
+
+ /*
+ Extract the SEL_ARG subtree that contains only ranges for the MIN/MAX
+ attribute, and create an array of QUICK_RANGES to be used by the
+ new quick select.
+ */
+ if (min_max_arg_part)
+ {
+ SEL_ARG *min_max_range= index_tree;
+ while (min_max_range) /* Find the tree for the MIN/MAX key part. */
+ {
+ if (min_max_range->field->eq(min_max_arg_part->field))
+ break;
+ min_max_range= min_max_range->next_key_part;
+ }
+ /* Scroll to the leftmost interval for the MIN/MAX argument. */
+ while (min_max_range && min_max_range->prev)
+ min_max_range= min_max_range->prev;
+ /* Create an array of QUICK_RANGEs for the MIN/MAX argument. */
+ while (min_max_range)
+ {
+ if (quick->add_range(min_max_range))
+ {
+ delete quick;
+ quick= NULL;
+ DBUG_RETURN(NULL);
+ }
+ min_max_range= min_max_range->next;
+ }
+ }
+ }
+ else
+ quick->quick_prefix_select= NULL;
+
+ quick->update_key_stat();
+
+ DBUG_RETURN(quick);
+}
+
+
+/*
+ Construct new quick select for group queries with min/max.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::QUICK_GROUP_MIN_MAX_SELECT()
+ table The table being accessed
+ join Descriptor of the current query
+ have_min TRUE if the query selects a MIN function
+ have_max TRUE if the query selects a MAX function
+ min_max_arg_part The only argument field of all MIN/MAX functions
+ group_prefix_len Length of all key parts in the group prefix
+ prefix_key_parts All key parts in the group prefix
+ index_info The index chosen for data access
+ use_index The id of index_info
+ read_cost Cost of this access method
+ records Number of records returned
+ key_infix_len Length of the key infix appended to the group prefix
+ key_infix Infix of constants from equality predicates
+ parent_alloc Memory pool for this and quick_prefix_select data
+
+ RETURN
+ None
+*/
+
+QUICK_GROUP_MIN_MAX_SELECT::
+QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
+ bool have_max_arg,
+ KEY_PART_INFO *min_max_arg_part_arg,
+ uint group_prefix_len_arg,
+ uint used_key_parts_arg, KEY *index_info_arg,
+ uint use_index, double read_cost_arg,
+ ha_rows records_arg, uint key_infix_len_arg,
+ byte *key_infix_arg, MEM_ROOT *parent_alloc)
+ :join(join_arg), index_info(index_info_arg),
+ group_prefix_len(group_prefix_len_arg), have_min(have_min_arg),
+ have_max(have_max_arg), seen_first_key(FALSE),
+ min_max_arg_part(min_max_arg_part_arg), key_infix(key_infix_arg),
+ key_infix_len(key_infix_len_arg), min_functions_it(NULL),
+ max_functions_it(NULL)
+{
+ head= table;
+ file= head->file;
+ index= use_index;
+ record= head->record[0];
+ tmp_record= head->record[1];
+ read_time= read_cost_arg;
+ records= records_arg;
+ used_key_parts= used_key_parts_arg;
+ real_prefix_len= group_prefix_len + key_infix_len;
+ group_prefix= NULL;
+ min_max_arg_len= min_max_arg_part ? min_max_arg_part->store_length : 0;
+
+ /*
+ We can't have parent_alloc set as the init function can't handle this case
+ yet.
+ */
+ DBUG_ASSERT(!parent_alloc);
+ if (!parent_alloc)
+ {
+ init_sql_alloc(&alloc, join->thd->variables.range_alloc_block_size, 0);
+ join->thd->mem_root= &alloc;
+ }
+ else
+ bzero(&alloc, sizeof(MEM_ROOT)); // ensure that it's not used
+}
+
+
+/*
+ Do post-constructor initialization.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::init()
+
+ DESCRIPTION
+ The method performs initialization that cannot be done in the constructor
+ such as memory allocations that may fail. It allocates memory for the
+ group prefix and inifix buffers, and for the lists of MIN/MAX item to be
+ updated during execution.
+
+ RETURN
+ 0 OK
+ other Error code
+*/
+
+int QUICK_GROUP_MIN_MAX_SELECT::init()
+{
+ if (group_prefix) /* Already initialized. */
+ return 0;
+
+ if (!(last_prefix= (byte*) alloc_root(&alloc, group_prefix_len)))
+ return 1;
+ /*
+ We may use group_prefix to store keys with all select fields, so allocate
+ enough space for it.
+ */
+ if (!(group_prefix= (byte*) alloc_root(&alloc,
+ real_prefix_len + min_max_arg_len)))
+ return 1;
+
+ if (key_infix_len > 0)
+ {
+ /*
+ The memory location pointed to by key_infix will be deleted soon, so
+ allocate a new buffer and copy the key_infix into it.
+ */
+ byte *tmp_key_infix= (byte*) alloc_root(&alloc, key_infix_len);
+ if (!tmp_key_infix)
+ return 1;
+ memcpy(tmp_key_infix, this->key_infix, key_infix_len);
+ this->key_infix= tmp_key_infix;
+ }
+
+ if (min_max_arg_part)
+ {
+ if (my_init_dynamic_array(&min_max_ranges, sizeof(QUICK_RANGE*), 16, 16))
+ return 1;
+
+ if (have_min)
+ {
+ if (!(min_functions= new List<Item_sum>))
+ return 1;
+ }
+ else
+ min_functions= NULL;
+ if (have_max)
+ {
+ if (!(max_functions= new List<Item_sum>))
+ return 1;
+ }
+ else
+ max_functions= NULL;
+
+ Item_sum *min_max_item;
+ Item_sum **func_ptr= join->sum_funcs;
+ while ((min_max_item= *(func_ptr++)))
+ {
+ if (have_min && (min_max_item->sum_func() == Item_sum::MIN_FUNC))
+ min_functions->push_back(min_max_item);
+ else if (have_max && (min_max_item->sum_func() == Item_sum::MAX_FUNC))
+ max_functions->push_back(min_max_item);
+ }
+
+ if (have_min)
+ {
+ if (!(min_functions_it= new List_iterator<Item_sum>(*min_functions)))
+ return 1;
+ }
+
+ if (have_max)
+ {
+ if (!(max_functions_it= new List_iterator<Item_sum>(*max_functions)))
+ return 1;
+ }
+ }
+ else
+ min_max_ranges.elements= 0;
+
+ return 0;
+}
+
+
+QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT()
+{
+ DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT");
+ if (file->inited != handler::NONE)
+ file->ha_index_end();
+ if (min_max_arg_part)
+ delete_dynamic(&min_max_ranges);
+ free_root(&alloc,MYF(0));
+ delete min_functions_it;
+ delete max_functions_it;
+ delete quick_prefix_select;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Eventually create and add a new quick range object.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::add_range()
+ sel_range Range object from which a
+
+ NOTES
+ Construct a new QUICK_RANGE object from a SEL_ARG object, and
+ add it to the array min_max_ranges. If sel_arg is an infinite
+ range, e.g. (x < 5 or x > 4), then skip it and do not construct
+ a quick range.
+
+ RETURN
+ FALSE on success
+ TRUE otherwise
+*/
+
+bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
+{
+ QUICK_RANGE *range;
+ uint range_flag= sel_range->min_flag | sel_range->max_flag;
+
+ /* Skip (-inf,+inf) ranges, e.g. (x < 5 or x > 4). */
+ if ((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE))
+ return FALSE;
+
+ if (!(sel_range->min_flag & NO_MIN_RANGE) &&
+ !(sel_range->max_flag & NO_MAX_RANGE))
+ {
+ if (sel_range->maybe_null &&
+ sel_range->min_value[0] && sel_range->max_value[0])
+ range_flag|= NULL_RANGE; /* IS NULL condition */
+ else if (memcmp(sel_range->min_value, sel_range->max_value,
+ min_max_arg_len) == 0)
+ range_flag|= EQ_RANGE; /* equality condition */
+ }
+ range= new QUICK_RANGE(sel_range->min_value, min_max_arg_len,
+ sel_range->max_value, min_max_arg_len,
+ range_flag);
+ if (!range)
+ return TRUE;
+ if (insert_dynamic(&min_max_ranges, (gptr)&range))
+ return TRUE;
+ return FALSE;
+}
+
+
+/*
+ Determine the total number and length of the keys that will be used for
+ index lookup.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::update_key_stat()
+
+ DESCRIPTION
+ The total length of the keys used for index lookup depends on whether
+ there are any predicates referencing the min/max argument, and/or if
+ the min/max argument field can be NULL.
+ This function does an optimistic analysis whether the search key might
+ be extended by a constant for the min/max keypart. It is 'optimistic'
+ because during actual execution it may happen that a particular range
+ is skipped, and then a shorter key will be used. However this is data
+ dependent and can't be easily estimated here.
+
+ RETURN
+ None
+*/
+
+void QUICK_GROUP_MIN_MAX_SELECT::update_key_stat()
+{
+ max_used_key_length= real_prefix_len;
+ if (min_max_ranges.elements > 0)
+ {
+ QUICK_RANGE *cur_range;
+ if (have_min)
+ { /* Check if the right-most range has a lower boundary. */
+ get_dynamic(&min_max_ranges, (gptr)&cur_range,
+ min_max_ranges.elements - 1);
+ if (!(cur_range->flag & NO_MIN_RANGE))
+ {
+ max_used_key_length+= min_max_arg_len;
+ used_key_parts++;
+ return;
+ }
+ }
+ if (have_max)
+ { /* Check if the left-most range has an upper boundary. */
+ get_dynamic(&min_max_ranges, (gptr)&cur_range, 0);
+ if (!(cur_range->flag & NO_MAX_RANGE))
+ {
+ max_used_key_length+= min_max_arg_len;
+ used_key_parts++;
+ return;
+ }
+ }
+ }
+ else if (have_min && min_max_arg_part &&
+ min_max_arg_part->field->real_maybe_null())
+ {
+ /*
+ If a MIN/MAX argument value is NULL, we can quickly determine
+ that we're in the beginning of the next group, because NULLs
+ are always < any other value. This allows us to quickly
+ determine the end of the current group and jump to the next
+ group (see next_min()) and thus effectively increases the
+ usable key length.
+ */
+ max_used_key_length+= min_max_arg_len;
+ used_key_parts++;
+ }
+}
+
+
+/*
+ Initialize a quick group min/max select for key retrieval.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::reset()
+
+ DESCRIPTION
+ Initialize the index chosen for access and find and store the prefix
+ of the last group. The method is expensive since it performs disk access.
+
+ RETURN
+ 0 OK
+ other Error code
+*/
+
+int QUICK_GROUP_MIN_MAX_SELECT::reset(void)
+{
+ int result;
+ DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::reset");
+
+ file->extra(HA_EXTRA_KEYREAD); /* We need only the key attributes */
+ result= file->ha_index_init(index);
+ result= file->index_last(record);
+ if (result == HA_ERR_END_OF_FILE)
+ DBUG_RETURN(0);
+ if (result)
+ DBUG_RETURN(result);
+ if (quick_prefix_select && quick_prefix_select->reset())
+ DBUG_RETURN(1);
+ /* Save the prefix of the last group. */
+ key_copy(last_prefix, record, index_info, group_prefix_len);
+
+ DBUG_RETURN(0);
+}
+
+
+
+/*
+ Get the next key containing the MIN and/or MAX key for the next group.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::get_next()
+
+ DESCRIPTION
+ The method finds the next subsequent group of records that satisfies the
+ query conditions and finds the keys that contain the MIN/MAX values for
+ the key part referenced by the MIN/MAX function(s). Once a group and its
+ MIN/MAX values are found, store these values in the Item_sum objects for
+ the MIN/MAX functions. The rest of the values in the result row are stored
+ in the Item_field::result_field of each select field. If the query does
+ not contain MIN and/or MAX functions, then the function only finds the
+ group prefix, which is a query answer itself.
+
+ NOTES
+ If both MIN and MAX are computed, then we use the fact that if there is
+ no MIN key, there can't be a MAX key as well, so we can skip looking
+ for a MAX key in this case.
+
+ RETURN
+ 0 on success
+ HA_ERR_END_OF_FILE if returned all keys
+ other if some error occurred
+*/
+
+int QUICK_GROUP_MIN_MAX_SELECT::get_next()
+{
+ int min_res= 0;
+ int max_res= 0;
+#ifdef HPUX11
+ /*
+ volatile is required by a bug in the HP compiler due to which the
+ last test of result fails.
+ */
+ volatile int result;
+#else
+ int result;
+#endif
+ int is_last_prefix;
+
+ DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::get_next");
+
+ /*
+ Loop until a group is found that satisfies all query conditions or the last
+ group is reached.
+ */
+ do
+ {
+ result= next_prefix();
+ /*
+ Check if this is the last group prefix. Notice that at this point
+ this->record contains the current prefix in record format.
+ */
+ is_last_prefix= key_cmp(index_info->key_part, last_prefix,
+ group_prefix_len);
+ DBUG_ASSERT(is_last_prefix <= 0);
+ if (result == HA_ERR_KEY_NOT_FOUND)
+ continue;
+ else if (result)
+ break;
+
+ if (have_min)
+ {
+ min_res= next_min();
+ if (min_res == 0)
+ update_min_result();
+ }
+ /* If there is no MIN in the group, there is no MAX either. */
+ if ((have_max && !have_min) ||
+ (have_max && have_min && (min_res == 0)))
+ {
+ max_res= next_max();
+ if (max_res == 0)
+ update_max_result();
+ /* If a MIN was found, a MAX must have been found as well. */
+ DBUG_ASSERT((have_max && !have_min) ||
+ (have_max && have_min && (max_res == 0)));
+ }
+ /*
+ If this is just a GROUP BY or DISTINCT without MIN or MAX and there
+ are equality predicates for the key parts after the group, find the
+ first sub-group with the extended prefix.
+ */
+ if (!have_min && !have_max && key_infix_len > 0)
+ result= file->index_read(record, group_prefix, real_prefix_len,
+ HA_READ_KEY_EXACT);
+
+ result= have_min ? min_res : have_max ? max_res : result;
+ }
+ while (result == HA_ERR_KEY_NOT_FOUND && is_last_prefix != 0);
+
+ if (result == 0)
+ /*
+ Partially mimic the behavior of end_select_send. Copy the
+ field data from Item_field::field into Item_field::result_field
+ of each non-aggregated field (the group fields, and optionally
+ other fields in non-ANSI SQL mode).
+ */
+ copy_fields(&join->tmp_table_param);
+ else if (result == HA_ERR_KEY_NOT_FOUND)
+ result= HA_ERR_END_OF_FILE;
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Retrieve the minimal key in the next group.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::next_min()
+
+ DESCRIPTION
+ Find the minimal key within this group such that the key satisfies the query
+ conditions and NULL semantics. The found key is loaded into this->record.
+
+ IMPLEMENTATION
+ Depending on the values of min_max_ranges.elements, key_infix_len, and
+ whether there is a NULL in the MIN field, this function may directly
+ return without any data access. In this case we use the key loaded into
+ this->record by the call to this->next_prefix() just before this call.
+
+ RETURN
+ 0 on success
+ HA_ERR_KEY_NOT_FOUND if no MIN key was found that fulfills all conditions.
+ other if some error occurred
+*/
+
+int QUICK_GROUP_MIN_MAX_SELECT::next_min()
+{
+ int result= 0;
+ DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::next_min");
+
+ /* Find the MIN key using the eventually extended group prefix. */
+ if (min_max_ranges.elements > 0)
+ {
+ if ((result= next_min_in_range()))
+ DBUG_RETURN(result);
+ }
+ else
+ {
+ /* Apply the constant equality conditions to the non-group select fields */
+ if (key_infix_len > 0)
+ {
+ if ((result= file->index_read(record, group_prefix, real_prefix_len,
+ HA_READ_KEY_EXACT)))
+ DBUG_RETURN(result);
+ }
+
+ /*
+ If the min/max argument field is NULL, skip subsequent rows in the same
+ group with NULL in it. Notice that:
+ - if the first row in a group doesn't have a NULL in the field, no row
+ in the same group has (because NULL < any other value),
+ - min_max_arg_part->field->ptr points to some place in 'record'.
+ */
+ if (min_max_arg_part && min_max_arg_part->field->is_null())
+ {
+ /* Find the first subsequent record without NULL in the MIN/MAX field. */
+ key_copy(tmp_record, record, index_info, 0);
+ result= file->index_read(record, tmp_record,
+ real_prefix_len + min_max_arg_len,
+ HA_READ_AFTER_KEY);
+ /*
+ Check if the new record belongs to the current group by comparing its
+ prefix with the group's prefix. If it is from the next group, then the
+ whole group has NULLs in the MIN/MAX field, so use the first record in
+ the group as a result.
+ TODO:
+ It is possible to reuse this new record as the result candidate for the
+ next call to next_min(), and to save one lookup in the next call. For
+ this add a new member 'this->next_group_prefix'.
+ */
+ if (!result)
+ {
+ if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
+ key_restore(record, tmp_record, index_info, 0);
+ }
+ else if (result == HA_ERR_KEY_NOT_FOUND)
+ result= 0; /* There is a result in any case. */
+ }
+ }
+
+ /*
+ If the MIN attribute is non-nullable, this->record already contains the
+ MIN key in the group, so just return.
+ */
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Retrieve the maximal key in the next group.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::next_max()
+
+ DESCRIPTION
+ Lookup the maximal key of the group, and store it into this->record.
+
+ RETURN
+ 0 on success
+ HA_ERR_KEY_NOT_FOUND if no MAX key was found that fulfills all conditions.
+ other if some error occurred
+*/
+
+int QUICK_GROUP_MIN_MAX_SELECT::next_max()
+{
+ int result;
+
+ DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::next_max");
+
+ /* Get the last key in the (possibly extended) group. */
+ if (min_max_ranges.elements > 0)
+ result= next_max_in_range();
+ else
+ result= file->index_read(record, group_prefix, real_prefix_len,
+ HA_READ_PREFIX_LAST);
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Determine the prefix of the next group.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
+
+ DESCRIPTION
+ Determine the prefix of the next group that satisfies the query conditions.
+ If there is a range condition referencing the group attributes, use a
+ QUICK_RANGE_SELECT object to retrieve the *first* key that satisfies the
+ condition. If there is a key infix of constants, append this infix
+ immediately after the group attributes. The possibly extended prefix is
+ stored in this->group_prefix. The first key of the found group is stored in
+ this->record, on which relies this->next_min().
+
+ RETURN
+ 0 on success
+ HA_ERR_KEY_NOT_FOUND if there is no key with the formed prefix
+ HA_ERR_END_OF_FILE if there are no more keys
+ other if some error occurred
+*/
+int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
+{
+ int result;
+ DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::next_prefix");
+
+ if (quick_prefix_select)
+ {
+ byte *cur_prefix= seen_first_key ? group_prefix : NULL;
+ if ((result= quick_prefix_select->get_next_prefix(group_prefix_len,
+ cur_prefix)))
+ DBUG_RETURN(result);
+ seen_first_key= TRUE;
+ }
+ else
+ {
+ if (!seen_first_key)
+ {
+ result= file->index_first(record);
+ if (result)
+ DBUG_RETURN(result);
+ seen_first_key= TRUE;
+ }
+ else
+ {
+ /* Load the first key in this group into record. */
+ result= file->index_read(record, group_prefix, group_prefix_len,
+ HA_READ_AFTER_KEY);
+ if (result)
+ DBUG_RETURN(result);
+ }
+ }
+
+ /* Save the prefix of this group for subsequent calls. */
+ key_copy(group_prefix, record, index_info, group_prefix_len);
+ /* Append key_infix to group_prefix. */
+ if (key_infix_len > 0)
+ memcpy(group_prefix + group_prefix_len,
+ key_infix, key_infix_len);
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Find the minimal key in a group that satisfies some range conditions for the
+ min/max argument field.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
+
+ DESCRIPTION
+ Given the sequence of ranges min_max_ranges, find the minimal key that is
+ in the left-most possible range. If there is no such key, then the current
+ group does not have a MIN key that satisfies the WHERE clause. If a key is
+ found, its value is stored in this->record.
+
+ RETURN
+ 0 on success
+ HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of
+ the ranges
+ other if some error
+*/
+
+int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
+{
+ ha_rkey_function find_flag;
+ uint search_prefix_len;
+ QUICK_RANGE *cur_range;
+ bool found_null= FALSE;
+ int result= HA_ERR_KEY_NOT_FOUND;
+
+ DBUG_ASSERT(min_max_ranges.elements > 0);
+
+ for (uint range_idx= 0; range_idx < min_max_ranges.elements; range_idx++)
+ { /* Search from the left-most range to the right. */
+ get_dynamic(&min_max_ranges, (gptr)&cur_range, range_idx);
+
+ /*
+ If the current value for the min/max argument is bigger than the right
+ boundary of cur_range, there is no need to check this range.
+ */
+ if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) &&
+ (key_cmp(min_max_arg_part, (const byte*) cur_range->max_key,
+ min_max_arg_len) == 1))
+ continue;
+
+ if (cur_range->flag & NO_MIN_RANGE)
+ {
+ find_flag= HA_READ_KEY_EXACT;
+ search_prefix_len= real_prefix_len;
+ }
+ else
+ {
+ /* Extend the search key with the lower boundary for this range. */
+ memcpy(group_prefix + real_prefix_len, cur_range->min_key,
+ cur_range->min_length);
+ search_prefix_len= real_prefix_len + min_max_arg_len;
+ find_flag= (cur_range->flag & (EQ_RANGE | NULL_RANGE)) ?
+ HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MIN) ?
+ HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT;
+ }
+
+ result= file->index_read(record, group_prefix, search_prefix_len,
+ find_flag);
+ if ((result == HA_ERR_KEY_NOT_FOUND) &&
+ (cur_range->flag & (EQ_RANGE | NULL_RANGE)))
+ continue; /* Check the next range. */
+ else if (result)
+ {
+ /*
+ In all other cases (HA_ERR_*, HA_READ_KEY_EXACT with NO_MIN_RANGE,
+ HA_READ_AFTER_KEY, HA_READ_KEY_OR_NEXT) if the lookup failed for this
+ range, it can't succeed for any other subsequent range.
+ */
+ break;
+ }
+
+ /* A key was found. */
+ if (cur_range->flag & EQ_RANGE)
+ break; /* No need to perform the checks below for equal keys. */
+
+ if (cur_range->flag & NULL_RANGE)
+ {
+ /*
+ Remember this key, and continue looking for a non-NULL key that
+ satisfies some other condition.
+ */
+ memcpy(tmp_record, record, head->s->rec_buff_length);
+ found_null= TRUE;
+ continue;
+ }
+
+ /* Check if record belongs to the current group. */
+ if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
+ {
+ result = HA_ERR_KEY_NOT_FOUND;
+ continue;
+ }
+
+ /* If there is an upper limit, check if the found key is in the range. */
+ if ( !(cur_range->flag & NO_MAX_RANGE) )
+ {
+ /* Compose the MAX key for the range. */
+ byte *max_key= (byte*) my_alloca(real_prefix_len + min_max_arg_len);
+ memcpy(max_key, group_prefix, real_prefix_len);
+ memcpy(max_key + real_prefix_len, cur_range->max_key,
+ cur_range->max_length);
+ /* Compare the found key with max_key. */
+ int cmp_res= key_cmp(index_info->key_part, max_key,
+ real_prefix_len + min_max_arg_len);
+ if (!((cur_range->flag & NEAR_MAX) && (cmp_res == -1) ||
+ (cmp_res <= 0)))
+ {
+ result = HA_ERR_KEY_NOT_FOUND;
+ continue;
+ }
+ }
+ /* If we got to this point, the current key qualifies as MIN. */
+ DBUG_ASSERT(result == 0);
+ break;
+ }
+ /*
+ If there was a key with NULL in the MIN/MAX field, and there was no other
+ key without NULL from the same group that satisfies some other condition,
+ then use the key with the NULL.
+ */
+ if (found_null && result)
+ {
+ memcpy(record, tmp_record, head->s->rec_buff_length);
+ result= 0;
+ }
+ return result;
+}
+
+
+/*
+ Find the maximal key in a group that satisfies some range conditions for the
+ min/max argument field.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
+
+ DESCRIPTION
+ Given the sequence of ranges min_max_ranges, find the maximal key that is
+ in the right-most possible range. If there is no such key, then the current
+ group does not have a MAX key that satisfies the WHERE clause. If a key is
+ found, its value is stored in this->record.
+
+ RETURN
+ 0 on success
+ HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of
+ the ranges
+ other if some error
+*/
+
+int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
+{
+ ha_rkey_function find_flag;
+ uint search_prefix_len;
+ QUICK_RANGE *cur_range;
+ int result;
+
+ DBUG_ASSERT(min_max_ranges.elements > 0);
+
+ for (uint range_idx= min_max_ranges.elements; range_idx > 0; range_idx--)
+ { /* Search from the right-most range to the left. */
+ get_dynamic(&min_max_ranges, (gptr)&cur_range, range_idx - 1);
+
+ /*
+ If the current value for the min/max argument is smaller than the left
+ boundary of cur_range, there is no need to check this range.
+ */
+ if (range_idx != min_max_ranges.elements &&
+ !(cur_range->flag & NO_MIN_RANGE) &&
+ (key_cmp(min_max_arg_part, (const byte*) cur_range->min_key,
+ min_max_arg_len) == -1))
+ continue;
+
+ if (cur_range->flag & NO_MAX_RANGE)
+ {
+ find_flag= HA_READ_PREFIX_LAST;
+ search_prefix_len= real_prefix_len;
+ }
+ else
+ {
+ /* Extend the search key with the upper boundary for this range. */
+ memcpy(group_prefix + real_prefix_len, cur_range->max_key,
+ cur_range->max_length);
+ search_prefix_len= real_prefix_len + min_max_arg_len;
+ find_flag= (cur_range->flag & EQ_RANGE) ?
+ HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MAX) ?
+ HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV;
+ }
+
+ result= file->index_read(record, group_prefix, search_prefix_len,
+ find_flag);
+
+ if ((result == HA_ERR_KEY_NOT_FOUND) && (cur_range->flag & EQ_RANGE))
+ continue; /* Check the next range. */
+ if (result)
+ {
+ /*
+ In no key was found with this upper bound, there certainly are no keys
+ in the ranges to the left.
+ */
+ return result;
+ }
+ /* A key was found. */
+ if (cur_range->flag & EQ_RANGE)
+ return 0; /* No need to perform the checks below for equal keys. */
+
+ /* Check if record belongs to the current group. */
+ if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
+ continue; // Row not found
+
+ /* If there is a lower limit, check if the found key is in the range. */
+ if ( !(cur_range->flag & NO_MIN_RANGE) )
+ {
+ /* Compose the MIN key for the range. */
+ byte *min_key= (byte*) my_alloca(real_prefix_len + min_max_arg_len);
+ memcpy(min_key, group_prefix, real_prefix_len);
+ memcpy(min_key + real_prefix_len, cur_range->min_key,
+ cur_range->min_length);
+ /* Compare the found key with min_key. */
+ int cmp_res= key_cmp(index_info->key_part, min_key,
+ real_prefix_len + min_max_arg_len);
+ if (!((cur_range->flag & NEAR_MIN) && (cmp_res == 1) ||
+ (cmp_res >= 0)))
+ continue;
+ }
+ /* If we got to this point, the current key qualifies as MAX. */
+ return result;
+ }
+ return HA_ERR_KEY_NOT_FOUND;
+}
+
+
+/*
+ Update all MIN function results with the newly found value.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::update_min_result()
+
+ DESCRIPTION
+ The method iterates through all MIN functions and updates the result value
+ of each function by calling Item_sum::reset(), which in turn picks the new
+ result value from this->head->record[0], previously updated by
+ next_min(). The updated value is stored in a member variable of each of the
+ Item_sum objects, depending on the value type.
+
+ IMPLEMENTATION
+ The update must be done separately for MIN and MAX, immediately after
+ next_min() was called and before next_max() is called, because both MIN and
+ MAX take their result value from the same buffer this->head->record[0]
+ (i.e. this->record).
+
+ RETURN
+ None
+*/
+
+void QUICK_GROUP_MIN_MAX_SELECT::update_min_result()
+{
+ Item_sum *min_func;
+
+ min_functions_it->rewind();
+ while ((min_func= (*min_functions_it)++))
+ min_func->reset();
+}
+
+
+/*
+ Update all MAX function results with the newly found value.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::update_max_result()
+
+ DESCRIPTION
+ The method iterates through all MAX functions and updates the result value
+ of each function by calling Item_sum::reset(), which in turn picks the new
+ result value from this->head->record[0], previously updated by
+ next_max(). The updated value is stored in a member variable of each of the
+ Item_sum objects, depending on the value type.
+
+ IMPLEMENTATION
+ The update must be done separately for MIN and MAX, immediately after
+ next_max() was called, because both MIN and MAX take their result value
+ from the same buffer this->head->record[0] (i.e. this->record).
+
+ RETURN
+ None
+*/
+
+void QUICK_GROUP_MIN_MAX_SELECT::update_max_result()
+{
+ Item_sum *max_func;
+
+ max_functions_it->rewind();
+ while ((max_func= (*max_functions_it)++))
+ max_func->reset();
+}
+
+
+/*
+ Append comma-separated list of keys this quick select uses to key_names;
+ append comma-separated list of corresponding used lengths to used_lengths.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths()
+ key_names [out] Names of used indexes
+ used_lengths [out] Corresponding lengths of the index names
+
+ DESCRIPTION
+ This method is used by select_describe to extract the names of the
+ indexes used by a quick select.
+
+*/
+
+void QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names,
+ String *used_lengths)
+{
+ char buf[64];
+ uint length;
+ key_names->append(index_info->name);
+ length= longlong2str(max_used_key_length, buf, 10) - buf;
+ used_lengths->append(buf, length);
+}
+
+
+#ifndef DBUG_OFF
+
+static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
+ const char *msg)
+{
+ SEL_ARG **key,**end;
+ int idx;
+ char buff[1024];
+ DBUG_ENTER("print_sel_tree");
+ if (! _db_on_)
+ DBUG_VOID_RETURN;
+
+ String tmp(buff,sizeof(buff),&my_charset_bin);
+ tmp.length(0);
+ for (idx= 0,key=tree->keys, end=key+param->keys ;
+ key != end ;
+ key++,idx++)
+ {
+ if (tree_map->is_set(idx))
+ {
+ uint keynr= param->real_keynr[idx];
+ if (tmp.length())
+ tmp.append(',');
+ tmp.append(param->table->key_info[keynr].name);
+ }
+ }
+ if (!tmp.length())
+ tmp.append("(empty)");
+
+ DBUG_PRINT("info", ("SEL_TREE %p (%s) scans:%s", tree, msg, tmp.ptr()));
+
+ DBUG_VOID_RETURN;
+}
+
+
+static void print_ror_scans_arr(TABLE *table, const char *msg,
+ struct st_ror_scan_info **start,
+ struct st_ror_scan_info **end)
+{
+ DBUG_ENTER("print_ror_scans");
+ if (! _db_on_)
+ DBUG_VOID_RETURN;
+
+ char buff[1024];
+ String tmp(buff,sizeof(buff),&my_charset_bin);
+ tmp.length(0);
+ for (;start != end; start++)
+ {
+ if (tmp.length())
+ tmp.append(',');
+ tmp.append(table->key_info[(*start)->keynr].name);
+ }
+ if (!tmp.length())
+ tmp.append("(empty)");
+ DBUG_PRINT("info", ("ROR key scans (%s): %s", msg, tmp.ptr()));
+ DBUG_VOID_RETURN;
+}
+
+
/*****************************************************************************
** Print a quick range for debugging
** TODO:
@@ -2945,8 +8805,6 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
** of locking the DEBUG stream !
*****************************************************************************/
-#ifndef DBUG_OFF
-
static void
print_key(KEY_PART *key_part,const char *key,uint used_length)
{
@@ -2970,8 +8828,11 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
key++; // Skip null byte
store_length--;
}
- field->set_key_image((char*) key, key_part->length, field->charset());
- field->val_str(&tmp);
+ field->set_key_image((char*) key, key_part->length);
+ if (field->type() == MYSQL_TYPE_BIT)
+ (void) field->val_int_as_str(&tmp, 1);
+ else
+ field->val_str(&tmp);
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
if (key+store_length < key_end)
fputc('/',DBUG_FILE);
@@ -2979,51 +8840,169 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
}
-static void print_quick(QUICK_SELECT *quick,const key_map* needed_reg)
+static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg)
{
- QUICK_RANGE *range;
char buf[MAX_KEY/8+1];
- DBUG_ENTER("print_param");
+ DBUG_ENTER("print_quick");
if (! _db_on_ || !quick)
DBUG_VOID_RETURN;
+ DBUG_LOCK_FILE;
- List_iterator<QUICK_RANGE> li(quick->ranges);
+ quick->dbug_dump(0, TRUE);
+ fprintf(DBUG_FILE,"other_keys: 0x%s:\n", needed_reg->print(buf));
+
+ DBUG_UNLOCK_FILE;
+ DBUG_VOID_RETURN;
+}
+
+
+static void print_rowid(byte* val, int len)
+{
+ byte *pb;
DBUG_LOCK_FILE;
- fprintf(DBUG_FILE,"Used quick_range on key: %d (other_keys: 0x%s):\n",
- quick->index, needed_reg->print(buf));
- while ((range=li++))
+ fputc('\"', DBUG_FILE);
+ for (pb= val; pb!= val + len; ++pb)
+ fprintf(DBUG_FILE, "%c", *pb);
+ fprintf(DBUG_FILE, "\", hex: ");
+
+ for (pb= val; pb!= val + len; ++pb)
+ fprintf(DBUG_FILE, "%x ", *pb);
+ fputc('\n', DBUG_FILE);
+ DBUG_UNLOCK_FILE;
+}
+
+void QUICK_RANGE_SELECT::dbug_dump(int indent, bool verbose)
+{
+ fprintf(DBUG_FILE, "%*squick range select, key %s, length: %d\n",
+ indent, "", head->key_info[index].name, max_used_key_length);
+
+ if (verbose)
{
- if (!(range->flag & NO_MIN_RANGE))
+ QUICK_RANGE *range;
+ QUICK_RANGE **pr= (QUICK_RANGE**)ranges.buffer;
+ QUICK_RANGE **last_range= pr + ranges.elements;
+ for (; pr!=last_range; ++pr)
{
- print_key(quick->key_parts,range->min_key,range->min_length);
- if (range->flag & NEAR_MIN)
- fputs(" < ",DBUG_FILE);
- else
- fputs(" <= ",DBUG_FILE);
- }
- fputs("X",DBUG_FILE);
+ fprintf(DBUG_FILE, "%*s", indent + 2, "");
+ range= *pr;
+ if (!(range->flag & NO_MIN_RANGE))
+ {
+ print_key(key_parts,range->min_key,range->min_length);
+ if (range->flag & NEAR_MIN)
+ fputs(" < ",DBUG_FILE);
+ else
+ fputs(" <= ",DBUG_FILE);
+ }
+ fputs("X",DBUG_FILE);
- if (!(range->flag & NO_MAX_RANGE))
- {
- if (range->flag & NEAR_MAX)
- fputs(" < ",DBUG_FILE);
- else
- fputs(" <= ",DBUG_FILE);
- print_key(quick->key_parts,range->max_key,range->max_length);
+ if (!(range->flag & NO_MAX_RANGE))
+ {
+ if (range->flag & NEAR_MAX)
+ fputs(" < ",DBUG_FILE);
+ else
+ fputs(" <= ",DBUG_FILE);
+ print_key(key_parts,range->max_key,range->max_length);
+ }
+ fputs("\n",DBUG_FILE);
}
- fputs("\n",DBUG_FILE);
}
- DBUG_UNLOCK_FILE;
- DBUG_VOID_RETURN;
}
-#endif
+void QUICK_INDEX_MERGE_SELECT::dbug_dump(int indent, bool verbose)
+{
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ QUICK_RANGE_SELECT *quick;
+ fprintf(DBUG_FILE, "%*squick index_merge select\n", indent, "");
+ fprintf(DBUG_FILE, "%*smerged scans {\n", indent, "");
+ while ((quick= it++))
+ quick->dbug_dump(indent+2, verbose);
+ if (pk_quick_select)
+ {
+ fprintf(DBUG_FILE, "%*sclustered PK quick:\n", indent, "");
+ pk_quick_select->dbug_dump(indent+2, verbose);
+ }
+ fprintf(DBUG_FILE, "%*s}\n", indent, "");
+}
+
+void QUICK_ROR_INTERSECT_SELECT::dbug_dump(int indent, bool verbose)
+{
+ List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
+ QUICK_RANGE_SELECT *quick;
+ fprintf(DBUG_FILE, "%*squick ROR-intersect select, %scovering\n",
+ indent, "", need_to_fetch_row? "":"non-");
+ fprintf(DBUG_FILE, "%*smerged scans {\n", indent, "");
+ while ((quick= it++))
+ quick->dbug_dump(indent+2, verbose);
+ if (cpk_quick)
+ {
+ fprintf(DBUG_FILE, "%*sclustered PK quick:\n", indent, "");
+ cpk_quick->dbug_dump(indent+2, verbose);
+ }
+ fprintf(DBUG_FILE, "%*s}\n", indent, "");
+}
+
+void QUICK_ROR_UNION_SELECT::dbug_dump(int indent, bool verbose)
+{
+ List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
+ QUICK_SELECT_I *quick;
+ fprintf(DBUG_FILE, "%*squick ROR-union select\n", indent, "");
+ fprintf(DBUG_FILE, "%*smerged scans {\n", indent, "");
+ while ((quick= it++))
+ quick->dbug_dump(indent+2, verbose);
+ fprintf(DBUG_FILE, "%*s}\n", indent, "");
+}
+
+
+/*
+ Print quick select information to DBUG_FILE.
+
+ SYNOPSIS
+ QUICK_GROUP_MIN_MAX_SELECT::dbug_dump()
+ indent Indentation offset
+ verbose If TRUE show more detailed output.
+
+ DESCRIPTION
+ Print the contents of this quick select to DBUG_FILE. The method also
+ calls dbug_dump() for the used quick select if any.
+
+ IMPLEMENTATION
+ Caller is responsible for locking DBUG_FILE before this call and unlocking
+ it afterwards.
+
+ RETURN
+ None
+*/
+
+void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose)
+{
+ fprintf(DBUG_FILE,
+ "%*squick_group_min_max_select: index %s (%d), length: %d\n",
+ indent, "", index_info->name, index, max_used_key_length);
+ if (key_infix_len > 0)
+ {
+ fprintf(DBUG_FILE, "%*susing key_infix with length %d:\n",
+ indent, "", key_infix_len);
+ }
+ if (quick_prefix_select)
+ {
+ fprintf(DBUG_FILE, "%*susing quick_range_select:\n", indent, "");
+ quick_prefix_select->dbug_dump(indent + 2, verbose);
+ }
+ if (min_max_ranges.elements > 0)
+ {
+ fprintf(DBUG_FILE, "%*susing %d quick_ranges for MIN/MAX:\n",
+ indent, "", min_max_ranges.elements);
+ }
+}
+
+
+#endif /* NOT_USED */
/*****************************************************************************
-** Instansiate templates
+** Instantiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<QUICK_RANGE>;
template class List_iterator<QUICK_RANGE>;
#endif
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 87e0315a09e..37d77033c8d 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -24,16 +24,6 @@
#pragma interface /* gcc class implementation */
#endif
-#define NO_MIN_RANGE 1
-#define NO_MAX_RANGE 2
-#define NEAR_MIN 4
-#define NEAR_MAX 8
-#define UNIQUE_RANGE 16
-#define EQ_RANGE 32
-#define NULL_RANGE 64
-#define GEOM_FLAG 128
-
-
typedef struct st_key_part {
uint16 key,part, store_length, length;
uint8 null_bit;
@@ -66,61 +56,619 @@ class QUICK_RANGE :public Sql_alloc {
};
-class QUICK_SELECT {
+/*
+ Quick select interface.
+ This class is a parent for all QUICK_*_SELECT and FT_SELECT classes.
+
+ The usage scenario is as follows:
+ 1. Create quick select
+ quick= new QUICK_XXX_SELECT(...);
+
+ 2. Perform lightweight initialization. This can be done in 2 ways:
+ 2.a: Regular initialization
+ if (quick->init())
+ {
+ //the only valid action after failed init() call is delete
+ delete quick;
+ }
+ 2.b: Special initialization for quick selects merged by QUICK_ROR_*_SELECT
+ if (quick->init_ror_merged_scan())
+ delete quick;
+
+ 3. Perform zero, one, or more scans.
+ while (...)
+ {
+ // initialize quick select for scan. This may allocate
+ // buffers and/or prefetch rows.
+ if (quick->reset())
+ {
+ //the only valid action after failed reset() call is delete
+ delete quick;
+ //abort query
+ }
+
+ // perform the scan
+ do
+ {
+ res= quick->get_next();
+ } while (res && ...)
+ }
+
+ 4. Delete the select:
+ delete quick;
+
+*/
+
+class QUICK_SELECT_I
+{
+public:
+ bool sorted;
+ ha_rows records; /* estimate of # of records to be retrieved */
+ double read_time; /* time to perform this retrieval */
+ TABLE *head;
+ /*
+ Index this quick select uses, or MAX_KEY for quick selects
+ that use several indexes
+ */
+ uint index;
+
+ /*
+ Total length of first used_key_parts parts of the key.
+ Applicable if index!= MAX_KEY.
+ */
+ uint max_used_key_length;
+
+ /*
+ Max. number of (first) key parts this quick select uses for retrieval.
+ eg. for "(key1p1=c1 AND key1p2=c2) OR key1p1=c2" used_key_parts == 2.
+ Applicable if index!= MAX_KEY.
+ */
+ uint used_key_parts;
+
+ QUICK_SELECT_I();
+ virtual ~QUICK_SELECT_I(){};
+
+ /*
+ Do post-constructor initialization.
+ SYNOPSIS
+ init()
+
+ init() performs initializations that should have been in constructor if
+ it was possible to return errors from constructors. The join optimizer may
+ create and then delete quick selects without retrieving any rows so init()
+ must not contain any IO or CPU intensive code.
+
+ If init() call fails the only valid action is to delete this quick select,
+ reset() and get_next() must not be called.
+
+ RETURN
+ 0 OK
+ other Error code
+ */
+ virtual int init() = 0;
+
+ /*
+ Initialize quick select for row retrieval.
+ SYNOPSIS
+ reset()
+
+ reset() should be called when it is certain that row retrieval will be
+ necessary. This call may do heavyweight initialization like buffering first
+ N records etc. If reset() call fails get_next() must not be called.
+ Note that reset() may be called several times if
+ * the quick select is executed in a subselect
+ * a JOIN buffer is used
+
+ RETURN
+ 0 OK
+ other Error code
+ */
+ virtual int reset(void) = 0;
+
+ virtual int get_next() = 0; /* get next record to retrieve */
+
+ /* Range end should be called when we have looped over the whole index */
+ virtual void range_end() {}
+
+ virtual bool reverse_sorted() = 0;
+ virtual bool unique_key_range() { return false; }
+
+ enum {
+ QS_TYPE_RANGE = 0,
+ QS_TYPE_INDEX_MERGE = 1,
+ QS_TYPE_RANGE_DESC = 2,
+ QS_TYPE_FULLTEXT = 3,
+ QS_TYPE_ROR_INTERSECT = 4,
+ QS_TYPE_ROR_UNION = 5,
+ QS_TYPE_GROUP_MIN_MAX = 6
+ };
+
+ /* Get type of this quick select - one of the QS_TYPE_* values */
+ virtual int get_type() = 0;
+
+ /*
+ Initialize this quick select as a merged scan inside a ROR-union or a ROR-
+ intersection scan. The caller must not additionally call init() if this
+ function is called.
+ SYNOPSIS
+ init_ror_merged_scan()
+ reuse_handler If true, the quick select may use table->handler, otherwise
+ it must create and use a separate handler object.
+ RETURN
+ 0 Ok
+ other Error
+ */
+ virtual int init_ror_merged_scan(bool reuse_handler)
+ { DBUG_ASSERT(0); return 1; }
+
+ /*
+ Save ROWID of last retrieved row in file->ref. This used in ROR-merging.
+ */
+ virtual void save_last_pos(){};
+
+ /*
+ Append comma-separated list of keys this quick select uses to key_names;
+ append comma-separated list of corresponding used lengths to used_lengths.
+ This is used by select_describe.
+ */
+ virtual void add_keys_and_lengths(String *key_names,
+ String *used_lengths)=0;
+
+ /*
+ Append text representation of quick select structure (what and how is
+ merged) to str. The result is added to "Extra" field in EXPLAIN output.
+ This function is implemented only by quick selects that merge other quick
+ selects output and/or can produce output suitable for merging.
+ */
+ virtual void add_info_string(String *str) {};
+ /*
+ Return 1 if any index used by this quick select
+ a) uses field that is listed in passed field list or
+ b) is automatically updated (like a timestamp)
+ */
+ virtual bool check_if_keys_used(List<Item> *fields);
+
+ /*
+ rowid of last row retrieved by this quick select. This is used only when
+ doing ROR-index_merge selects
+ */
+ byte *last_rowid;
+
+ /*
+ Table record buffer used by this quick select.
+ */
+ byte *record;
+#ifndef DBUG_OFF
+ /*
+ Print quick select information to DBUG_FILE. Caller is responsible
+ for locking DBUG_FILE before this call and unlocking it afterwards.
+ */
+ virtual void dbug_dump(int indent, bool verbose)= 0;
+#endif
+};
+
+
+struct st_qsel_param;
+class SEL_ARG;
+
+/*
+ Quick select that does a range scan on a single key. The records are
+ returned in key order.
+*/
+class QUICK_RANGE_SELECT : public QUICK_SELECT_I
+{
+protected:
+ bool next,dont_free;
public:
- bool next,dont_free,sorted;
int error;
- uint index, max_used_key_length, used_key_parts;
- TABLE *head;
+protected:
handler *file;
- byte *record;
- List<QUICK_RANGE> ranges;
- List_iterator<QUICK_RANGE> it;
- QUICK_RANGE *range;
- MEM_ROOT alloc;
+ /*
+ If true, this quick select has its "own" handler object which should be
+ closed no later then this quick select is deleted.
+ */
+ bool free_file;
+ bool in_range;
+ uint multi_range_count; /* copy from thd->variables.multi_range_count */
+ uint multi_range_length; /* the allocated length for the array */
+ uint multi_range_bufsiz; /* copy from thd->variables.read_rnd_buff_size */
+ KEY_MULTI_RANGE *multi_range; /* the multi-range array (allocated and
+ freed by QUICK_RANGE_SELECT) */
+ HANDLER_BUFFER *multi_range_buff; /* the handler buffer (allocated and
+ freed by QUICK_RANGE_SELECT) */
+protected:
+ friend class TRP_ROR_INTERSECT;
+ friend
+ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
+ struct st_table_ref *ref,
+ ha_rows records);
+ friend bool get_quick_keys(struct st_qsel_param *param,
+ QUICK_RANGE_SELECT *quick,KEY_PART *key,
+ SEL_ARG *key_tree,
+ char *min_key, uint min_key_flag,
+ char *max_key, uint max_key_flag);
+ friend QUICK_RANGE_SELECT *get_quick_select(struct st_qsel_param*,uint idx,
+ SEL_ARG *key_tree,
+ MEM_ROOT *alloc);
+ friend class QUICK_SELECT_DESC;
+ friend class QUICK_INDEX_MERGE_SELECT;
+ friend class QUICK_ROR_INTERSECT_SELECT;
+
+ DYNAMIC_ARRAY ranges; /* ordered array of range ptrs */
+ QUICK_RANGE **cur_range; /* current element in ranges */
+
+ QUICK_RANGE *range;
KEY_PART *key_parts;
KEY_PART_INFO *key_part_info;
- ha_rows records;
- double read_time;
+ int cmp_next(QUICK_RANGE *range);
+ int cmp_prev(QUICK_RANGE *range);
+ bool row_in_ranges();
+public:
+ MEM_ROOT alloc;
- QUICK_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0);
- virtual ~QUICK_SELECT();
- void reset(void) { next=0; it.rewind(); }
- int init()
+ QUICK_RANGE_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0,
+ MEM_ROOT *parent_alloc=NULL);
+ ~QUICK_RANGE_SELECT();
+
+ int init();
+ int reset(void);
+ int get_next();
+ void range_end();
+ int get_next_prefix(uint prefix_length, byte *cur_prefix);
+ bool reverse_sorted() { return 0; }
+ bool unique_key_range();
+ int init_ror_merged_scan(bool reuse_handler);
+ void save_last_pos()
+ { file->position(record); }
+ int get_type() { return QS_TYPE_RANGE; }
+ void add_keys_and_lengths(String *key_names, String *used_lengths);
+ void add_info_string(String *str);
+#ifndef DBUG_OFF
+ void dbug_dump(int indent, bool verbose);
+#endif
+private:
+ /* Used only by QUICK_SELECT_DESC */
+ QUICK_RANGE_SELECT(const QUICK_RANGE_SELECT& org) : QUICK_SELECT_I()
{
- key_part_info= head->key_info[index].key_part;
- return error=file->ha_index_init(index);
+ bcopy(&org, this, sizeof(*this));
+ multi_range_length= 0;
+ multi_range= NULL;
+ multi_range_buff= NULL;
}
- virtual int get_next();
- virtual bool reverse_sorted() { return 0; }
- bool unique_key_range();
};
-class QUICK_SELECT_GEOM: public QUICK_SELECT
+class QUICK_RANGE_SELECT_GEOM: public QUICK_RANGE_SELECT
{
public:
- QUICK_SELECT_GEOM(THD *thd, TABLE *table, uint index_arg, bool no_alloc)
- :QUICK_SELECT(thd, table, index_arg, no_alloc)
+ QUICK_RANGE_SELECT_GEOM(THD *thd, TABLE *table, uint index_arg,
+ bool no_alloc, MEM_ROOT *parent_alloc)
+ :QUICK_RANGE_SELECT(thd, table, index_arg, no_alloc, parent_alloc)
{};
virtual int get_next();
};
-class QUICK_SELECT_DESC: public QUICK_SELECT
+/*
+ QUICK_INDEX_MERGE_SELECT - index_merge access method quick select.
+
+ QUICK_INDEX_MERGE_SELECT uses
+ * QUICK_RANGE_SELECTs to get rows
+ * Unique class to remove duplicate rows
+
+ INDEX MERGE OPTIMIZER
+ Current implementation doesn't detect all cases where index_merge could
+ be used, in particular:
+ * index_merge will never be used if range scan is possible (even if
+ range scan is more expensive)
+
+ * index_merge+'using index' is not supported (this the consequence of
+ the above restriction)
+
+ * If WHERE part contains complex nested AND and OR conditions, some ways
+ to retrieve rows using index_merge will not be considered. The choice
+ of read plan may depend on the order of conjuncts/disjuncts in WHERE
+ part of the query, see comments near imerge_list_or_list and
+ SEL_IMERGE::or_sel_tree_with_checks functions for details.
+
+ * There is no "index_merge_ref" method (but index_merge on non-first
+ table in join is possible with 'range checked for each record').
+
+ See comments around SEL_IMERGE class and test_quick_select for more
+ details.
+
+ ROW RETRIEVAL ALGORITHM
+
+ index_merge uses Unique class for duplicates removal. index_merge takes
+ advantage of Clustered Primary Key (CPK) if the table has one.
+ The index_merge algorithm consists of two phases:
+
+ Phase 1 (implemented in QUICK_INDEX_MERGE_SELECT::prepare_unique):
+ prepare()
+ {
+ activate 'index only';
+ while(retrieve next row for non-CPK scan)
+ {
+ if (there is a CPK scan and row will be retrieved by it)
+ skip this row;
+ else
+ put its rowid into Unique;
+ }
+ deactivate 'index only';
+ }
+
+ Phase 2 (implemented as sequence of QUICK_INDEX_MERGE_SELECT::get_next
+ calls):
+
+ fetch()
+ {
+ retrieve all rows from row pointers stored in Unique;
+ free Unique;
+ retrieve all rows for CPK scan;
+ }
+*/
+
+class QUICK_INDEX_MERGE_SELECT : public QUICK_SELECT_I
+{
+public:
+ QUICK_INDEX_MERGE_SELECT(THD *thd, TABLE *table);
+ ~QUICK_INDEX_MERGE_SELECT();
+
+ int init();
+ int reset(void);
+ int get_next();
+ bool reverse_sorted() { return false; }
+ bool unique_key_range() { return false; }
+ int get_type() { return QS_TYPE_INDEX_MERGE; }
+ void add_keys_and_lengths(String *key_names, String *used_lengths);
+ void add_info_string(String *str);
+ bool check_if_keys_used(List<Item> *fields);
+#ifndef DBUG_OFF
+ void dbug_dump(int indent, bool verbose);
+#endif
+
+ bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);
+
+ /* range quick selects this index_merge read consists of */
+ List<QUICK_RANGE_SELECT> quick_selects;
+
+ /* quick select that uses clustered primary key (NULL if none) */
+ QUICK_RANGE_SELECT* pk_quick_select;
+
+ /* true if this select is currently doing a clustered PK scan */
+ bool doing_pk_scan;
+
+ MEM_ROOT alloc;
+ THD *thd;
+ int read_keys_and_merge();
+
+ /* used to get rows collected in Unique */
+ READ_RECORD read_record;
+};
+
+
+/*
+ Rowid-Ordered Retrieval (ROR) index intersection quick select.
+ This quick select produces intersection of row sequences returned
+ by several QUICK_RANGE_SELECTs it "merges".
+
+ All merged QUICK_RANGE_SELECTs must return rowids in rowid order.
+ QUICK_ROR_INTERSECT_SELECT will return rows in rowid order, too.
+
+ All merged quick selects retrieve {rowid, covered_fields} tuples (not full
+ table records).
+ QUICK_ROR_INTERSECT_SELECT retrieves full records if it is not being used
+ by QUICK_ROR_INTERSECT_SELECT and all merged quick selects together don't
+ cover needed all fields.
+
+ If one of the merged quick selects is a Clustered PK range scan, it is
+ used only to filter rowid sequence produced by other merged quick selects.
+*/
+
+class QUICK_ROR_INTERSECT_SELECT : public QUICK_SELECT_I
+{
+public:
+ QUICK_ROR_INTERSECT_SELECT(THD *thd, TABLE *table,
+ bool retrieve_full_rows,
+ MEM_ROOT *parent_alloc);
+ ~QUICK_ROR_INTERSECT_SELECT();
+
+ int init();
+ int reset(void);
+ int get_next();
+ bool reverse_sorted() { return false; }
+ bool unique_key_range() { return false; }
+ int get_type() { return QS_TYPE_ROR_INTERSECT; }
+ void add_keys_and_lengths(String *key_names, String *used_lengths);
+ void add_info_string(String *str);
+ bool check_if_keys_used(List<Item> *fields);
+#ifndef DBUG_OFF
+ void dbug_dump(int indent, bool verbose);
+#endif
+ int init_ror_merged_scan(bool reuse_handler);
+ bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);
+
+ /*
+ Range quick selects this intersection consists of, not including
+ cpk_quick.
+ */
+ List<QUICK_RANGE_SELECT> quick_selects;
+
+ /*
+ Merged quick select that uses Clustered PK, if there is one. This quick
+ select is not used for row retrieval, it is used for row retrieval.
+ */
+ QUICK_RANGE_SELECT *cpk_quick;
+
+ MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */
+ THD *thd; /* current thread */
+ bool need_to_fetch_row; /* if true, do retrieve full table records. */
+ /* in top-level quick select, true if merged scans where initialized */
+ bool scans_inited;
+};
+
+
+/*
+ Rowid-Ordered Retrieval index union select.
+ This quick select produces union of row sequences returned by several
+ quick select it "merges".
+
+ All merged quick selects must return rowids in rowid order.
+ QUICK_ROR_UNION_SELECT will return rows in rowid order, too.
+
+ All merged quick selects are set not to retrieve full table records.
+ ROR-union quick select always retrieves full records.
+
+*/
+
+class QUICK_ROR_UNION_SELECT : public QUICK_SELECT_I
{
public:
- QUICK_SELECT_DESC(QUICK_SELECT *q, uint used_key_parts);
+ QUICK_ROR_UNION_SELECT(THD *thd, TABLE *table);
+ ~QUICK_ROR_UNION_SELECT();
+
+ int init();
+ int reset(void);
+ int get_next();
+ bool reverse_sorted() { return false; }
+ bool unique_key_range() { return false; }
+ int get_type() { return QS_TYPE_ROR_UNION; }
+ void add_keys_and_lengths(String *key_names, String *used_lengths);
+ void add_info_string(String *str);
+ bool check_if_keys_used(List<Item> *fields);
+#ifndef DBUG_OFF
+ void dbug_dump(int indent, bool verbose);
+#endif
+
+ bool push_quick_back(QUICK_SELECT_I *quick_sel_range);
+
+ List<QUICK_SELECT_I> quick_selects; /* Merged quick selects */
+
+ QUEUE queue; /* Priority queue for merge operation */
+ MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */
+
+ THD *thd; /* current thread */
+ byte *cur_rowid; /* buffer used in get_next() */
+ byte *prev_rowid; /* rowid of last row returned by get_next() */
+ bool have_prev_rowid; /* true if prev_rowid has valid data */
+ uint rowid_length; /* table rowid length */
+private:
+ static int queue_cmp(void *arg, byte *val1, byte *val2);
+ bool scans_inited;
+};
+
+
+/*
+ Index scan for GROUP-BY queries with MIN/MAX aggregate functions.
+
+ This class provides a specialized index access method for GROUP-BY queries
+ of the forms:
+
+ SELECT A_1,...,A_k, [B_1,...,B_m], [MIN(C)], [MAX(C)]
+ FROM T
+ WHERE [RNG(A_1,...,A_p ; where p <= k)]
+ [AND EQ(B_1,...,B_m)]
+ [AND PC(C)]
+ [AND PA(A_i1,...,A_iq)]
+ GROUP BY A_1,...,A_k;
+
+ or
+
+ SELECT DISTINCT A_i1,...,A_ik
+ FROM T
+ WHERE [RNG(A_1,...,A_p ; where p <= k)]
+ [AND PA(A_i1,...,A_iq)];
+
+ where all selected fields are parts of the same index.
+ The class of queries that can be processed by this quick select is fully
+ specified in the description of get_best_trp_group_min_max() in opt_range.cc.
+
+ The get_next() method directly produces result tuples, thus obviating the
+ need to call end_send_group() because all grouping is already done inside
+ get_next().
+
+ Since one of the requirements is that all select fields are part of the same
+ index, this class produces only index keys, and not complete records.
+*/
+
+class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I
+{
+private:
+ handler *file; /* The handler used to get data. */
+ JOIN *join; /* Descriptor of the current query */
+ KEY *index_info; /* The index chosen for data access */
+ byte *record; /* Buffer where the next record is returned. */
+ byte *tmp_record; /* Temporary storage for next_min(), next_max(). */
+ byte *group_prefix; /* Key prefix consisting of the GROUP fields. */
+ uint group_prefix_len; /* Length of the group prefix. */
+ byte *last_prefix; /* Prefix of the last group for detecting EOF. */
+ bool have_min; /* Specify whether we are computing */
+ bool have_max; /* a MIN, a MAX, or both. */
+ bool seen_first_key; /* Denotes whether the first key was retrieved.*/
+ KEY_PART_INFO *min_max_arg_part; /* The keypart of the only argument field */
+ /* of all MIN/MAX functions. */
+ uint min_max_arg_len; /* The length of the MIN/MAX argument field */
+ byte *key_infix; /* Infix of constants from equality predicates. */
+ uint key_infix_len;
+ DYNAMIC_ARRAY min_max_ranges; /* Array of range ptrs for the MIN/MAX field. */
+ uint real_prefix_len; /* Length of key prefix extended with key_infix. */
+ List<Item_sum> *min_functions;
+ List<Item_sum> *max_functions;
+ List_iterator<Item_sum> *min_functions_it;
+ List_iterator<Item_sum> *max_functions_it;
+public:
+ /*
+ The following two members are public to allow easy access from
+ TRP_GROUP_MIN_MAX::make_quick()
+ */
+ MEM_ROOT alloc; /* Memory pool for this and quick_prefix_select data. */
+ QUICK_RANGE_SELECT *quick_prefix_select;/* For retrieval of group prefixes. */
+private:
+ int next_prefix();
+ int next_min_in_range();
+ int next_max_in_range();
+ int next_min();
+ int next_max();
+ void update_min_result();
+ void update_max_result();
+public:
+ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min,
+ bool have_max, KEY_PART_INFO *min_max_arg_part,
+ uint group_prefix_len, uint used_key_parts,
+ KEY *index_info, uint use_index, double read_cost,
+ ha_rows records, uint key_infix_len,
+ byte *key_infix, MEM_ROOT *parent_alloc);
+ ~QUICK_GROUP_MIN_MAX_SELECT();
+ bool add_range(SEL_ARG *sel_range);
+ void update_key_stat();
+ bool alloc_buffers();
+ int init();
+ int reset();
+ int get_next();
+ bool reverse_sorted() { return false; }
+ bool unique_key_range() { return false; }
+ int get_type() { return QS_TYPE_GROUP_MIN_MAX; }
+ void add_keys_and_lengths(String *key_names, String *used_lengths);
+#ifndef DBUG_OFF
+ void dbug_dump(int indent, bool verbose);
+#endif
+};
+
+
+class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
+{
+public:
+ QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts);
int get_next();
bool reverse_sorted() { return 1; }
+ int get_type() { return QS_TYPE_RANGE_DESC; }
private:
- int cmp_prev(QUICK_RANGE *range);
bool range_reads_after_key(QUICK_RANGE *range);
#ifdef NOT_USED
bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts);
#endif
- void reset(void) { next=0; rev_it.rewind(); }
+ int reset(void) { next=0; rev_it.rewind(); return 0; }
List<QUICK_RANGE> rev_ranges;
List_iterator<QUICK_RANGE> rev_it;
};
@@ -128,7 +676,7 @@ private:
class SQL_SELECT :public Sql_alloc {
public:
- QUICK_SELECT *quick; // If quick-select used
+ QUICK_SELECT_I *quick; // If quick-select used
COND *cond; // where condition
TABLE *head;
IO_CACHE file; // Positions to used records
@@ -154,17 +702,18 @@ class SQL_SELECT :public Sql_alloc {
};
-class FT_SELECT: public QUICK_SELECT {
+class FT_SELECT: public QUICK_RANGE_SELECT {
public:
- FT_SELECT(THD *thd, TABLE *table, uint key):
- QUICK_SELECT (thd, table, key, 1) { init(); }
+ FT_SELECT(THD *thd, TABLE *table, uint key) :
+ QUICK_RANGE_SELECT (thd, table, key, 1) { init(); }
~FT_SELECT() { file->ft_end(); }
- int init() { return error= file->ft_init(); }
- int get_next() { return error= file->ft_read(record); }
+ int init() { return error=file->ft_init(); }
+ int reset() { return 0; }
+ int get_next() { return error=file->ft_read(record); }
+ int get_type() { return QS_TYPE_FULLTEXT; }
};
-
-QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
- struct st_table_ref *ref);
-
+QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
+ struct st_table_ref *ref,
+ ha_rows records);
#endif
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index cb8e3c2d273..33c8eadc065 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -59,9 +59,9 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
SYNOPSIS
opt_sum_query()
- tables Tables in query
- all_fields All fields to be returned
- conds WHERE clause
+ tables list of leaves of join table tree
+ all_fields All fields to be returned
+ conds WHERE clause
NOTE:
This function is only called for queries with sum functions and no
@@ -89,7 +89,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
where_tables= conds->used_tables();
/* Don't replace expression on a table that is part of an outer join */
- for (TABLE_LIST *tl=tables; tl ; tl= tl->next)
+ for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf)
{
if (tl->on_expr)
{
@@ -128,10 +128,10 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
{
longlong count= 1;
TABLE_LIST *table;
- for (table=tables ; table ; table=table->next)
+ for (table= tables; table; table= table->next_leaf)
{
if (outer_tables || (table->table->file->table_flags() &
- HA_NOT_EXACT_COUNT))
+ HA_NOT_EXACT_COUNT) || table->schema_table)
{
const_result= 0; // Can't optimize left join
break;
@@ -313,7 +313,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
removed_tables is != 0 if we have used MIN() or MAX().
*/
if (removed_tables && used_tables != removed_tables)
- const_result= 0; // We didn't remove all tables
+ const_result= 0; // We didn't remove all tables
return const_result;
}
@@ -323,20 +323,34 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
SYNOPSIS
simple_pred()
- func_item in: Predicate item
+ func_item Predicate item
args out: Here we store the field followed by constants
- inv_order out: Is set to 1 if the predicate is of the form 'const op field'
+ inv_order out: Is set to 1 if the predicate is of the form
+ 'const op field'
RETURN
- 0 func_item is a simple predicate: a field is compared with constants
+ 0 func_item is a simple predicate: a field is compared with
+ constants
1 Otherwise
*/
-static bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
+bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
{
Item *item;
*inv_order= 0;
switch (func_item->argument_count()) {
+ case 0:
+ /* MULT_EQUAL_FUNC */
+ {
+ Item_equal *item_equal= (Item_equal *) func_item;
+ Item_equal_iterator it(*item_equal);
+ args[0]= it++;
+ if (it++)
+ return 0;
+ if (!(args[1]= item_equal->get_const()))
+ return 0;
+ }
+ break;
case 1:
/* field IS NULL */
item= func_item->arguments()[0];
@@ -477,6 +491,9 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
case Item_func::BETWEEN:
between= 1;
break;
+ case Item_func::MULT_EQUAL_FUNC:
+ eq_type= 1;
+ break;
default:
return 0; // Can't optimize function
}
@@ -547,8 +564,7 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
store_val_in_field(part->field, args[between && max_fl ? 2 : 1]);
if (part->null_bit)
*key_ptr++= (byte) test(part->field->is_null());
- part->field->get_key_image((char*) key_ptr, part->length,
- part->field->charset(), Field::itRAW);
+ part->field->get_key_image((char*) key_ptr, part->length, Field::itRAW);
}
if (is_field_part)
{
@@ -629,7 +645,7 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
uint idx= 0;
KEY *keyinfo,*keyinfo_end;
- for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->keys ;
+ for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->s->keys ;
keyinfo != keyinfo_end;
keyinfo++,idx++)
{
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
new file mode 100644
index 00000000000..5c7053e6e2a
--- /dev/null
+++ b/sql/parse_file.cc
@@ -0,0 +1,885 @@
+/* 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 */
+
+// Text .frm files management routines
+
+#include "mysql_priv.h"
+#include <errno.h>
+#include <m_ctype.h>
+#include <my_sys.h>
+#include <my_dir.h>
+
+
+/*
+ write string with escaping
+
+ SYNOPSIS
+ write_escaped_string()
+ file - IO_CACHE for record
+ val_s - string for writing
+
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+static my_bool
+write_escaped_string(IO_CACHE *file, LEX_STRING *val_s)
+{
+ char *eos= val_s->str + val_s->length;
+ char *ptr= val_s->str;
+
+ for (; ptr < eos; ptr++)
+ {
+ /*
+ Should be in sync with read_escaped_string() and
+ parse_quoted_escaped_string()
+ */
+ switch(*ptr) {
+ case '\\': // escape character
+ if (my_b_append(file, (const byte *)"\\\\", 2))
+ return TRUE;
+ break;
+ case '\n': // parameter value delimiter
+ if (my_b_append(file, (const byte *)"\\n", 2))
+ return TRUE;
+ break;
+ case '\0': // problem for some string processing utilities
+ if (my_b_append(file, (const byte *)"\\0", 2))
+ return TRUE;
+ break;
+ case 26: // problem for windows utilities (Ctrl-Z)
+ if (my_b_append(file, (const byte *)"\\z", 2))
+ return TRUE;
+ break;
+ case '\'': // list of string delimiter
+ if (my_b_append(file, (const byte *)"\\\'", 2))
+ return TRUE;
+ break;
+ default:
+ if (my_b_append(file, (const byte *)ptr, 1))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/*
+ write parameter value to IO_CACHE
+
+ SYNOPSIS
+ write_parameter()
+ file pointer to IO_CACHE structure for writing
+ base pointer to data structure
+ parameter pointer to parameter descriptor
+ old_version for returning back old version number value
+
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+static my_bool
+write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
+ ulonglong *old_version)
+{
+ char num_buf[20]; // buffer for numeric operations
+ // string for numeric operations
+ String num(num_buf, sizeof(num_buf), &my_charset_bin);
+ DBUG_ENTER("write_parameter");
+
+ switch (parameter->type) {
+ case FILE_OPTIONS_STRING:
+ {
+ LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset);
+ if (my_b_append(file, (const byte *)val_s->str, val_s->length))
+ DBUG_RETURN(TRUE);
+ break;
+ }
+ case FILE_OPTIONS_ESTRING:
+ {
+ if (write_escaped_string(file, (LEX_STRING *)(base + parameter->offset)))
+ DBUG_RETURN(TRUE);
+ break;
+ }
+ case FILE_OPTIONS_ULONGLONG:
+ {
+ num.set(*((ulonglong *)(base + parameter->offset)), &my_charset_bin);
+ if (my_b_append(file, (const byte *)num.ptr(), num.length()))
+ DBUG_RETURN(TRUE);
+ break;
+ }
+ case FILE_OPTIONS_REV:
+ {
+ ulonglong *val_i= (ulonglong *)(base + parameter->offset);
+ *old_version= (*val_i)++;
+ num.set(*val_i, &my_charset_bin);
+ if (my_b_append(file, (const byte *)num.ptr(), num.length()))
+ DBUG_RETURN(TRUE);
+ break;
+ }
+ case FILE_OPTIONS_TIMESTAMP:
+ {
+ /* string have to be allocated already */
+ LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset);
+ time_t tm= time(NULL);
+
+ get_date(val_s->str, GETDATE_DATE_TIME|GETDATE_GMT|GETDATE_FIXEDLENGTH,
+ tm);
+ val_s->length= PARSE_FILE_TIMESTAMPLENGTH;
+ if (my_b_append(file, (const byte *)val_s->str,
+ PARSE_FILE_TIMESTAMPLENGTH))
+ DBUG_RETURN(TRUE);
+ break;
+ }
+ case FILE_OPTIONS_STRLIST:
+ {
+ List_iterator_fast<LEX_STRING> it(*((List<LEX_STRING>*)
+ (base + parameter->offset)));
+ bool first= 1;
+ LEX_STRING *str;
+ while ((str= it++))
+ {
+ // We need ' ' after string to detect list continuation
+ if ((!first && my_b_append(file, (const byte *)" ", 1)) ||
+ my_b_append(file, (const byte *)"\'", 1) ||
+ write_escaped_string(file, str) ||
+ my_b_append(file, (const byte *)"\'", 1))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ first= 0;
+ }
+ break;
+ }
+ case FILE_OPTIONS_ULLLIST:
+ {
+ List_iterator_fast<ulonglong> it(*((List<ulonglong>*)
+ (base + parameter->offset)));
+ bool first= 1;
+ ulonglong *val;
+ while ((val= it++))
+ {
+ num.set(*val, &my_charset_bin);
+ // We need ' ' after string to detect list continuation
+ if ((!first && my_b_append(file, (const byte *)" ", 1)) ||
+ my_b_append(file, (const byte *)num.ptr(), num.length()))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ first= 0;
+ }
+ break;
+ }
+ default:
+ DBUG_ASSERT(0); // never should happened
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ write new .frm
+
+ SYNOPSIS
+ sql_create_definition_file()
+ dir directory where put .frm
+ file .frm file name
+ type .frm type string (VIEW, TABLE)
+ base base address for parameter reading (structure like
+ TABLE)
+ parameters parameters description
+ max_versions number of versions to save
+
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+my_bool
+sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
+ const LEX_STRING *type,
+ gptr base, File_option *parameters,
+ uint max_versions)
+{
+ File handler;
+ IO_CACHE file;
+ char path[FN_REFLEN+1]; // +1 to put temporary file name for sure
+ ulonglong old_version= ULONGLONG_MAX;
+ int path_end;
+ File_option *param;
+ DBUG_ENTER("sql_create_definition_file");
+ DBUG_PRINT("enter", ("Dir: %s, file: %s, base 0x%lx",
+ dir->str, file_name->str, (ulong) base));
+
+ fn_format(path, file_name->str, dir->str, 0, MY_UNPACK_FILENAME);
+ path_end= strlen(path);
+
+ // temporary file name
+ path[path_end]='~';
+ path[path_end+1]= '\0';
+ if ((handler= my_create(path, CREATE_MODE, O_RDWR | O_TRUNC,
+ MYF(MY_WME))) <= 0)
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ if (init_io_cache(&file, handler, 0, SEQ_READ_APPEND, 0L, 0, MYF(MY_WME)))
+ goto err_w_file;
+
+ // write header (file signature)
+ if (my_b_append(&file, (const byte *)"TYPE=", 5) ||
+ my_b_append(&file, (const byte *)type->str, type->length) ||
+ my_b_append(&file, (const byte *)"\n", 1))
+ goto err_w_file;
+
+ // write parameters to temporary file
+ for (param= parameters; param->name.str; param++)
+ {
+ if (my_b_append(&file, (const byte *)param->name.str,
+ param->name.length) ||
+ my_b_append(&file, (const byte *)"=", 1) ||
+ write_parameter(&file, base, param, &old_version) ||
+ my_b_append(&file, (const byte *)"\n", 1))
+ goto err_w_cache;
+ }
+
+ if (end_io_cache(&file))
+ goto err_w_file;
+
+ if (my_close(handler, MYF(MY_WME)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ // archive copies management
+ path[path_end]='\0';
+ if (!access(path, F_OK))
+ {
+ if (old_version != ULONGLONG_MAX && max_versions != 0)
+ {
+ // save backup
+ char path_arc[FN_REFLEN];
+ // backup old version
+ char path_to[FN_REFLEN];
+
+ // check archive directory existence
+ fn_format(path_arc, "arc", dir->str, "", MY_UNPACK_FILENAME);
+ if (access(path_arc, F_OK))
+ {
+ if (my_mkdir(path_arc, 0777, MYF(MY_WME)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lu",
+ path_arc, file_name->str, (ulong) old_version);
+ if (my_rename(path, path_to, MYF(MY_WME)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ // remove very old version
+ if (old_version > max_versions)
+ {
+ my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lu",
+ path_arc, file_name->str,
+ (ulong)(old_version - max_versions));
+ if (!access(path_arc, F_OK) && my_delete(path_to, MYF(MY_WME)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ else
+ {
+ if (my_delete(path, MYF(MY_WME))) // no backups
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+
+ {
+ // rename temporary file
+ char path_to[FN_REFLEN];
+ memcpy(path_to, path, path_end+1);
+ path[path_end]='~';
+ if (my_rename(path, path_to, MYF(MY_WME)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ DBUG_RETURN(FALSE);
+err_w_cache:
+ end_io_cache(&file);
+err_w_file:
+ my_close(handler, MYF(MY_WME));
+ DBUG_RETURN(TRUE);
+}
+
+/*
+ Renames a frm file (including backups) in same schema
+
+ SYNOPSIS
+ rename_in_schema_file
+ schema name of given schema
+ old_name original file name
+ new_name new file name
+ revision revision number
+ num_view_backups number of backups
+
+ RETURN
+ 0 - OK
+ 1 - Error (only if renaming of frm failed)
+
+*/
+my_bool rename_in_schema_file(const char *schema, const char *old_name,
+ const char *new_name, ulonglong revision,
+ uint num_view_backups)
+{
+ char old_path[FN_REFLEN], new_path[FN_REFLEN], arc_path[FN_REFLEN];
+
+ strxnmov(old_path, FN_REFLEN, mysql_data_home, "/", schema, "/",
+ old_name, reg_ext, NullS);
+ (void) unpack_filename(old_path, old_path);
+
+ strxnmov(new_path, FN_REFLEN, mysql_data_home, "/", schema, "/",
+ new_name, reg_ext, NullS);
+ (void) unpack_filename(new_path, new_path);
+
+ if (my_rename(old_path, new_path, MYF(MY_WME)))
+ return 1;
+
+ /* check if arc_dir exists */
+ strxnmov(arc_path, FN_REFLEN, mysql_data_home, "/", schema, "/arc", NullS);
+ (void) unpack_filename(arc_path, arc_path);
+
+ if (revision > 0 && !access(arc_path, F_OK))
+ {
+ ulonglong limit= (revision > num_view_backups) ? revision - num_view_backups : 0;
+ while (revision > limit) {
+ my_snprintf(old_path, FN_REFLEN, "%s/%s%s-%04lu",
+ arc_path, old_name, reg_ext, (ulong)revision);
+ (void) unpack_filename(old_path, old_path);
+ my_snprintf(new_path, FN_REFLEN, "%s/%s%s-%04lu",
+ arc_path, new_name, reg_ext, (ulong)revision);
+ (void) unpack_filename(new_path, new_path);
+ my_rename(old_path, new_path, MYF(0));
+ revision--;
+ }
+ }
+ return 0;
+}
+
+/*
+ Prepare frm to parse (read to memory)
+
+ SYNOPSIS
+ sql_parse_prepare()
+ file_name - path & filename to .frm file
+ mem_root - MEM_ROOT for buffer allocation
+ bad_format_errors - send errors on bad content
+
+ RETURN
+ 0 - error
+ parser object
+
+ NOTE
+ returned pointer + 1 will be type of .frm
+*/
+
+File_parser *
+sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,
+ bool bad_format_errors)
+{
+ MY_STAT stat_info;
+ uint len;
+ char *end, *sign;
+ File_parser *parser;
+ File file;
+ DBUG_ENTER("sql__parse_prepare");
+
+ if (!my_stat(file_name->str, &stat_info, MYF(MY_WME)))
+ {
+ DBUG_RETURN(0);
+ }
+
+ if (stat_info.st_size > INT_MAX-1)
+ {
+ my_error(ER_FPARSER_TOO_BIG_FILE, MYF(0), file_name->str);
+ DBUG_RETURN(0);
+ }
+
+ if (!(parser= new(mem_root) File_parser))
+ {
+ DBUG_RETURN(0);
+ }
+
+ if (!(parser->buff= alloc_root(mem_root, stat_info.st_size+1)))
+ {
+ DBUG_RETURN(0);
+ }
+
+ if ((file= my_open(file_name->str, O_RDONLY | O_SHARE, MYF(MY_WME))) < 0)
+ {
+ DBUG_RETURN(0);
+ }
+
+ if ((len= my_read(file, (byte *)parser->buff,
+ stat_info.st_size, MYF(MY_WME))) ==
+ MY_FILE_ERROR)
+ {
+ my_close(file, MYF(MY_WME));
+ DBUG_RETURN(0);
+ }
+
+ if (my_close(file, MYF(MY_WME)))
+ {
+ DBUG_RETURN(0);
+ }
+
+ end= parser->end= parser->buff + len;
+ *end= '\0'; // barrier for more simple parsing
+
+ // 7 = 5 (TYPE=) + 1 (letter at least of type name) + 1 ('\n')
+ if (len < 7 ||
+ parser->buff[0] != 'T' ||
+ parser->buff[1] != 'Y' ||
+ parser->buff[2] != 'P' ||
+ parser->buff[3] != 'E' ||
+ parser->buff[4] != '=')
+ goto frm_error;
+
+ // skip signature;
+ parser->file_type.str= sign= parser->buff + 5;
+ while (*sign >= 'A' && *sign <= 'Z' && sign < end)
+ sign++;
+ if (*sign != '\n')
+ goto frm_error;
+ parser->file_type.length= sign - parser->file_type.str;
+ // EOS for file signature just for safety
+ *sign= '\0';
+
+ parser->start= sign + 1;
+ parser->content_ok= 1;
+
+ DBUG_RETURN(parser);
+
+frm_error:
+ if (bad_format_errors)
+ {
+ my_error(ER_FPARSER_BAD_HEADER, MYF(0), file_name->str);
+ DBUG_RETURN(0);
+ }
+ else
+ DBUG_RETURN(parser); // upper level have to check parser->ok()
+}
+
+
+/*
+ parse LEX_STRING
+
+ SYNOPSIS
+ parse_string()
+ ptr - pointer on string beginning
+ end - pointer on symbol after parsed string end (still owned
+ by buffer and can be accessed
+ mem_root - MEM_ROOT for parameter allocation
+ str - pointer on string, where results should be stored
+
+ RETURN
+ 0 - error
+ # - pointer on symbol after string
+*/
+
+static char *
+parse_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str)
+{
+ // get string length
+ char *eol= strchr(ptr, '\n');
+
+ if (eol >= end)
+ return 0;
+
+ str->length= eol - ptr;
+
+ if (!(str->str= alloc_root(mem_root, str->length+1)))
+ return 0;
+
+ memcpy(str->str, ptr, str->length);
+ str->str[str->length]= '\0'; // just for safety
+ return eol+1;
+}
+
+
+/*
+ read escaped string from ptr to eol in already allocated str
+
+ SYNOPSIS
+ parse_escaped_string()
+ ptr - pointer on string beginning
+ eol - pointer on character after end of string
+ str - target string
+
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+my_bool
+read_escaped_string(char *ptr, char *eol, LEX_STRING *str)
+{
+ char *write_pos= str->str;
+
+ for (; ptr < eol; ptr++, write_pos++)
+ {
+ char c= *ptr;
+ if (c == '\\')
+ {
+ ptr++;
+ if (ptr >= eol)
+ return TRUE;
+ /*
+ Should be in sync with write_escaped_string() and
+ parse_quoted_escaped_string()
+ */
+ switch(*ptr) {
+ case '\\':
+ *write_pos= '\\';
+ break;
+ case 'n':
+ *write_pos= '\n';
+ break;
+ case '0':
+ *write_pos= '\0';
+ break;
+ case 'z':
+ *write_pos= 26;
+ break;
+ case '\'':
+ *write_pos= '\'';
+ break;
+ default:
+ return TRUE;
+ }
+ }
+ else
+ *write_pos= c;
+ }
+ str->str[str->length= write_pos-str->str]= '\0'; // just for safety
+ return FALSE;
+}
+
+
+/*
+ parse \n delimited escaped string
+
+ SYNOPSIS
+ parse_escaped_string()
+ ptr - pointer on string beginning
+ end - pointer on symbol after parsed string end (still owned
+ by buffer and can be accessed
+ mem_root - MEM_ROOT for parameter allocation
+ str - pointer on string, where results should be stored
+
+ RETURN
+ 0 - error
+ # - pointer on symbol after string
+*/
+
+static char *
+parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str)
+{
+ char *eol= strchr(ptr, '\n');
+
+ if (eol == 0 || eol >= end ||
+ !(str->str= alloc_root(mem_root, (eol - ptr) + 1)) ||
+ read_escaped_string(ptr, eol, str))
+ return 0;
+
+ return eol+1;
+}
+
+
+/*
+ parse '' delimited escaped string
+
+ SYNOPSIS
+ parse_escaped_string()
+ ptr - pointer on string beginning
+ end - pointer on symbol after parsed string end (still owned
+ by buffer and can be accessed
+ mem_root - MEM_ROOT for parameter allocation
+ str - pointer on string, where results should be stored
+
+ RETURN
+ 0 - error
+ # - pointer on symbol after string
+*/
+
+static char *
+parse_quoted_escaped_string(char *ptr, char *end,
+ MEM_ROOT *mem_root, LEX_STRING *str)
+{
+ char *eol;
+ uint result_len= 0;
+ bool escaped= 0;
+
+ // starting '
+ if (*(ptr++) != '\'')
+ return 0;
+
+ // find ending '
+ for (eol= ptr; (*eol != '\'' || escaped) && eol < end; eol++)
+ {
+ if (!(escaped= (*eol == '\\' && !escaped)))
+ result_len++;
+ }
+
+ // process string
+ if (eol >= end ||
+ !(str->str= alloc_root(mem_root, result_len + 1)) ||
+ read_escaped_string(ptr, eol, str))
+ return 0;
+
+ return eol+1;
+}
+
+
+/*
+ parse parameters
+
+ SYNOPSIS
+ File_parser::parse()
+ base base address for parameter writing (structure like
+ TABLE)
+ mem_root MEM_ROOT for parameters allocation
+ parameters parameters description
+ required number of required parameters in above list
+
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+my_bool
+File_parser::parse(gptr base, MEM_ROOT *mem_root,
+ struct File_option *parameters, uint required)
+{
+ uint first_param= 0, found= 0;
+ register char *ptr= start;
+ char *eol;
+ LEX_STRING *str;
+ List<LEX_STRING> *list;
+ ulonglong *num;
+ List<ulonglong> *nlist;
+ DBUG_ENTER("File_parser::parse");
+
+ while (ptr < end && found < required)
+ {
+ char *line= ptr;
+ if (*ptr == '#')
+ {
+ // it is comment
+ if (!(ptr= strchr(ptr, '\n')))
+ {
+ my_error(ER_FPARSER_EOF_IN_COMMENT, MYF(0), line);
+ DBUG_RETURN(TRUE);
+ }
+ ptr++;
+ }
+ else
+ {
+ File_option *parameter= parameters+first_param,
+ *parameters_end= parameters+required;
+ int len= 0;
+ for (; parameter < parameters_end; parameter++)
+ {
+ len= parameter->name.length;
+ // check length
+ if (len < (end-ptr) && ptr[len] != '=')
+ continue;
+ // check keyword
+ if (memcmp(parameter->name.str, ptr, len) == 0)
+ break;
+ }
+
+ if (parameter < parameters_end)
+ {
+ found++;
+ /*
+ if we found first parameter, start search from next parameter
+ next time.
+ (this small optimisation should work, because they should be
+ written in same order)
+ */
+ if (parameter == parameters+first_param)
+ first_param++;
+
+ // get value
+ ptr+= (len+1);
+ switch (parameter->type) {
+ case FILE_OPTIONS_STRING:
+ {
+ if (!(ptr= parse_string(ptr, end, mem_root,
+ (LEX_STRING *)(base +
+ parameter->offset))))
+ {
+ my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
+ parameter->name.str, line);
+ DBUG_RETURN(TRUE);
+ }
+ break;
+ }
+ case FILE_OPTIONS_ESTRING:
+ {
+ if (!(ptr= parse_escaped_string(ptr, end, mem_root,
+ (LEX_STRING *)
+ (base + parameter->offset))))
+ {
+ my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
+ parameter->name.str, line);
+ DBUG_RETURN(TRUE);
+ }
+ break;
+ }
+ case FILE_OPTIONS_ULONGLONG:
+ case FILE_OPTIONS_REV:
+ if (!(eol= strchr(ptr, '\n')))
+ {
+ my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
+ parameter->name.str, line);
+ DBUG_RETURN(TRUE);
+ }
+ {
+ int not_used;
+ *((ulonglong*)(base + parameter->offset))=
+ my_strtoll10(ptr, 0, &not_used);
+ }
+ ptr= eol+1;
+ break;
+ case FILE_OPTIONS_TIMESTAMP:
+ {
+ /* string have to be allocated already */
+ LEX_STRING *val= (LEX_STRING *)(base + parameter->offset);
+ /* yyyy-mm-dd HH:MM:SS = 19(PARSE_FILE_TIMESTAMPLENGTH) characters */
+ if (ptr[PARSE_FILE_TIMESTAMPLENGTH] != '\n')
+ {
+ my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
+ parameter->name.str, line);
+ DBUG_RETURN(TRUE);
+ }
+ memcpy(val->str, ptr, PARSE_FILE_TIMESTAMPLENGTH);
+ val->str[val->length= PARSE_FILE_TIMESTAMPLENGTH]= '\0';
+ ptr+= (PARSE_FILE_TIMESTAMPLENGTH+1);
+ break;
+ }
+ case FILE_OPTIONS_STRLIST:
+ {
+ list= (List<LEX_STRING>*)(base + parameter->offset);
+
+ list->empty();
+ // list parsing
+ while (ptr < end)
+ {
+ if (!(str= (LEX_STRING*)alloc_root(mem_root,
+ sizeof(LEX_STRING))) ||
+ list->push_back(str, mem_root))
+ goto list_err;
+ if (!(ptr= parse_quoted_escaped_string(ptr, end, mem_root, str)))
+ goto list_err_w_message;
+ switch (*ptr) {
+ case '\n':
+ goto end_of_list;
+ case ' ':
+ // we cant go over buffer bounds, because we have \0 at the end
+ ptr++;
+ break;
+ default:
+ goto list_err_w_message;
+ }
+ }
+
+end_of_list:
+ if (*(ptr++) != '\n')
+ goto list_err;
+ break;
+
+list_err_w_message:
+ my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
+ parameter->name.str, line);
+list_err:
+ DBUG_RETURN(TRUE);
+ }
+ case FILE_OPTIONS_ULLLIST:
+ {
+ nlist= (List<ulonglong>*)(base + parameter->offset);
+ nlist->empty();
+ // list parsing
+ while (ptr < end)
+ {
+ int not_used;
+ char *num_end= end;
+ if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) ||
+ nlist->push_back(num, mem_root))
+ goto nlist_err;
+ *num= my_strtoll10(ptr, &num_end, &not_used);
+ ptr= num_end;
+ switch (*ptr) {
+ case '\n':
+ goto end_of_nlist;
+ case ' ':
+ // we cant go over buffer bounds, because we have \0 at the end
+ ptr++;
+ break;
+ default:
+ goto nlist_err_w_message;
+ }
+ }
+
+end_of_nlist:
+ if (*(ptr++) != '\n')
+ goto nlist_err;
+ break;
+
+nlist_err_w_message:
+ my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
+ parameter->name.str, line);
+nlist_err:
+ DBUG_RETURN(TRUE);
+
+ }
+ default:
+ DBUG_ASSERT(0); // never should happened
+ }
+ }
+ else
+ {
+ // skip unknown parameter
+ if (!(ptr= strchr(ptr, '\n')))
+ {
+ my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0), line);
+ DBUG_RETURN(TRUE);
+ }
+ ptr++;
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
diff --git a/sql/parse_file.h b/sql/parse_file.h
new file mode 100644
index 00000000000..b4199e4fbf1
--- /dev/null
+++ b/sql/parse_file.h
@@ -0,0 +1,74 @@
+/* -*- C++ -*- */
+/* 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 */
+
+#ifndef _PARSE_FILE_H_
+#define _PARSE_FILE_H_
+
+#define PARSE_FILE_TIMESTAMPLENGTH 19
+
+enum file_opt_type {
+ FILE_OPTIONS_STRING, /* String (LEX_STRING) */
+ FILE_OPTIONS_ESTRING, /* Escaped string (LEX_STRING) */
+ FILE_OPTIONS_ULONGLONG, /* ulonglong parameter (ulonglong) */
+ FILE_OPTIONS_REV, /* Revision version number (ulonglong) */
+ FILE_OPTIONS_TIMESTAMP, /* timestamp (LEX_STRING have to be
+ allocated with length 20 (19+1) */
+ FILE_OPTIONS_STRLIST, /* list of escaped strings
+ (List<LEX_STRING>) */
+ FILE_OPTIONS_ULLLIST /* list of ulonglong values
+ (List<ulonglong>) */
+};
+
+struct File_option
+{
+ LEX_STRING name; /* Name of the option */
+ int offset; /* offset to base address of value */
+ file_opt_type type; /* Option type */
+};
+
+class File_parser;
+File_parser *sql_parse_prepare(const LEX_STRING *file_name,
+ MEM_ROOT *mem_root, bool bad_format_errors);
+
+my_bool
+sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
+ const LEX_STRING *type,
+ gptr base, File_option *parameters, uint versions);
+my_bool rename_in_schema_file(const char *schema, const char *old_name,
+ const char *new_name, ulonglong revision,
+ uint num_view_backups);
+
+class File_parser: public Sql_alloc
+{
+ char *buff, *start, *end;
+ LEX_STRING file_type;
+ my_bool content_ok;
+public:
+ File_parser() :buff(0), start(0), end(0), content_ok(0)
+ { file_type.str= 0; file_type.length= 0; }
+
+ my_bool ok() { return content_ok; }
+ LEX_STRING *type() { return &file_type; }
+ my_bool parse(gptr base, MEM_ROOT *mem_root,
+ struct File_option *parameters, uint required);
+
+ friend File_parser *sql_parse_prepare(const LEX_STRING *file_name,
+ MEM_ROOT *mem_root,
+ bool bad_format_errors);
+};
+
+#endif /* _PARSE_FILE_H_ */
diff --git a/sql/password.c b/sql/password.c
index 04b3a46bd48..aa05be8c740 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -65,7 +65,7 @@
#include <sha1.h>
#include "mysql.h"
-/************ MySQL 3.23-4.0 authentification routines: untouched ***********/
+/************ MySQL 3.23-4.0 authentication routines: untouched ***********/
/*
New (MySQL 3.21+) random generation structure initialization
@@ -146,7 +146,7 @@ void hash_password(ulong *result, const char *password, uint password_len)
void make_scrambled_password_323(char *to, const char *password)
{
ulong hash_res[2];
- hash_password(hash_res, password, strlen(password));
+ hash_password(hash_res, password, (uint) strlen(password));
sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
}
@@ -172,7 +172,7 @@ void scramble_323(char *to, const char *message, const char *password)
{
char extra, *to_start=to;
const char *message_end= message + SCRAMBLE_LENGTH_323;
- hash_password(hash_pass,password, strlen(password));
+ hash_password(hash_pass,password, (uint) strlen(password));
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
hash_pass[1] ^ hash_message[1]);
@@ -281,7 +281,7 @@ void make_password_from_salt_323(char *to, const ulong *salt)
/*
- **************** MySQL 4.1.1 authentification routines *************
+ **************** MySQL 4.1.1 authentication routines *************
*/
/*
@@ -318,8 +318,8 @@ void create_random_string(char *to, uint length, struct rand_struct *rand_st)
str, len IN the beginning and the length of the input string
*/
-static void
-octet2hex(char *to, const uint8 *str, uint len)
+void
+octet2hex(char *to, const unsigned char *str, uint len)
{
const uint8 *str_end= str + len;
for (; str != str_end; ++str)
@@ -394,7 +394,7 @@ make_scrambled_password(char *to, const char *password)
sha1_reset(&sha1_context);
/* stage 1: hash password */
- sha1_input(&sha1_context, (uint8 *) password, strlen(password));
+ sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
sha1_result(&sha1_context, (uint8 *) to);
/* stage 2: hash stage1 output */
sha1_reset(&sha1_context);
@@ -433,7 +433,7 @@ scramble(char *to, const char *message, const char *password)
sha1_reset(&sha1_context);
/* stage 1: hash password */
- sha1_input(&sha1_context, (uint8 *) password, strlen(password));
+ sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
sha1_result(&sha1_context, hash_stage1);
/* stage 2: hash stage 1; note that hash_stage2 is stored in the database */
sha1_reset(&sha1_context);
diff --git a/sql/procedure.cc b/sql/procedure.cc
index a0042dd879e..554e2cd0565 100644
--- a/sql/procedure.cc
+++ b/sql/procedure.cc
@@ -41,6 +41,34 @@ static struct st_procedure_def {
{ "analyse",proc_analyse_init } // Analyse a result
};
+
+my_decimal *Item_proc_string::val_decimal(my_decimal *decimal_value)
+{
+ if (null_value)
+ return 0;
+ string2my_decimal(E_DEC_FATAL_ERROR, &str_value, decimal_value);
+ return (decimal_value);
+}
+
+
+my_decimal *Item_proc_int::val_decimal(my_decimal *decimal_value)
+{
+ if (null_value)
+ return 0;
+ int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_value);
+ return (decimal_value);
+}
+
+
+my_decimal *Item_proc_real::val_decimal(my_decimal *decimal_value)
+{
+ if (null_value)
+ return 0;
+ double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_value);
+ return (decimal_value);
+}
+
+
/*****************************************************************************
** Setup handling of procedure
** Return 0 if everything is ok
@@ -65,8 +93,7 @@ setup_procedure(THD *thd,ORDER *param,select_result *result,
DBUG_RETURN(proc);
}
}
- my_printf_error(ER_UNKNOWN_PROCEDURE,ER(ER_UNKNOWN_PROCEDURE),MYF(0),
- (*param->item)->name);
+ my_error(ER_UNKNOWN_PROCEDURE, MYF(0), (*param->item)->name);
*error=1;
DBUG_RETURN(0);
}
diff --git a/sql/procedure.h b/sql/procedure.h
index 0a1e9ddfa2f..aceadd10883 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -60,13 +60,18 @@ public:
void set(longlong nr) { value=(double) nr; }
void set(const char *str,uint length,CHARSET_INFO *cs)
{
- int err;
+ int err_not_used;
char *end_not_used;
- value= my_strntod(cs, (char*) str, length, &end_not_used, &err);
+ value= my_strntod(cs,(char*) str,length, &end_not_used, &err_not_used);
}
- double val() { return value; }
+ double val_real() { return value; }
longlong val_int() { return (longlong) value; }
- String *val_str(String *s) { s->set(value,decimals,default_charset()); return s; }
+ String *val_str(String *s)
+ {
+ s->set(value,decimals,default_charset());
+ return s;
+ }
+ my_decimal *val_decimal(my_decimal *);
unsigned int size_of() { return sizeof(*this);}
};
@@ -82,9 +87,10 @@ public:
void set(longlong nr) { value=nr; }
void set(const char *str,uint length, CHARSET_INFO *cs)
{ int err; value=my_strntoll(cs,str,length,10,NULL,&err); }
- double val() { return (double) value; }
+ double val_real() { return (double) value; }
longlong val_int() { return value; }
String *val_str(String *s) { s->set(value, default_charset()); return s; }
+ my_decimal *val_decimal(my_decimal *);
unsigned int size_of() { return sizeof(*this);}
};
@@ -95,18 +101,18 @@ public:
Item_proc_string(const char *name_par,uint length) :Item_proc(name_par)
{ this->max_length=length; }
enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
void set(double nr) { str_value.set(nr, 2, default_charset()); }
void set(longlong nr) { str_value.set(nr, default_charset()); }
void set(const char *str, uint length, CHARSET_INFO *cs)
{ str_value.copy(str,length,cs); }
- double val()
+ double val_real()
{
- int err;
- CHARSET_INFO *cs= str_value.charset();
+ int err_not_used;
char *end_not_used;
+ CHARSET_INFO *cs= str_value.charset();
return my_strntod(cs, (char*) str_value.ptr(), str_value.length(),
- &end_not_used, &err);
+ &end_not_used, &err_not_used);
}
longlong val_int()
{
@@ -118,6 +124,7 @@ public:
{
return null_value ? (String*) 0 : (String*) &str_value;
}
+ my_decimal *val_decimal(my_decimal *);
unsigned int size_of() { return sizeof(*this);}
};
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 6a17ae2f95b..ade94a483a8 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -24,9 +24,11 @@
#endif
#include "mysql_priv.h"
+#include "sp_rcontext.h"
#include <stdarg.h>
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
+static void write_eof_packet(THD *thd, NET *net);
#ifndef EMBEDDED_LIBRARY
bool Protocol::net_store_data(const char *from, uint length)
@@ -52,22 +54,30 @@ bool Protocol_prep::net_store_data(const char *from, uint length)
/* Send a error string to client */
-void send_error(THD *thd, uint sql_errno, const char *err)
+void net_send_error(THD *thd, uint sql_errno, const char *err)
{
#ifndef EMBEDDED_LIBRARY
uint length;
char buff[MYSQL_ERRMSG_SIZE+2], *pos;
#endif
- const char *orig_err= err;
NET *net= &thd->net;
- DBUG_ENTER("send_error");
+ bool generate_warning= thd->killed != THD::KILL_CONNECTION;
+ DBUG_ENTER("net_send_error");
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
err ? err : net->last_error[0] ?
net->last_error : "NULL"));
-#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
- query_cache_abort(net);
-#endif
+ if (net && net->no_send_error)
+ {
+ thd->clear_error();
+ DBUG_PRINT("info", ("sending error messages prohibited"));
+ DBUG_VOID_RETURN;
+ }
+ if (thd->spcont && thd->spcont->find_handler(sql_errno,
+ MYSQL_ERROR::WARN_LEVEL_ERROR))
+ {
+ DBUG_VOID_RETURN;
+ }
thd->query_error= 1; // needed to catch query errors during replication
if (!err)
{
@@ -76,14 +86,22 @@ void send_error(THD *thd, uint sql_errno, const char *err)
else
{
if ((err=net->last_error)[0])
+ {
sql_errno=net->last_errno;
+ generate_warning= 0; // This warning has already been given
+ }
else
{
sql_errno=ER_UNKNOWN_ERROR;
err=ER(sql_errno); /* purecov: inspected */
}
}
- orig_err= err;
+ }
+
+ if (generate_warning)
+ {
+ /* Error that we have not got with my_error() */
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno, err);
}
#ifdef EMBEDDED_LIBRARY
@@ -122,43 +140,14 @@ void send_error(THD *thd, uint sql_errno, const char *err)
}
VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
#endif /* EMBEDDED_LIBRARY*/
- if (!thd->killed)
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno,
- orig_err ? orig_err : ER(sql_errno));
thd->is_fatal_error=0; // Error message is given
thd->net.report_error= 0;
/* Abort multi-result sets */
- thd->lex->found_colon= 0;
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
DBUG_VOID_RETURN;
}
-
-/*
- Send a warning to the end user
-
- SYNOPSIS
- send_warning()
- thd Thread handler
- sql_errno Warning number (error message)
- err Error string. If not set, use ER(sql_errno)
-
- DESCRIPTION
- Register the warning so that the user can get it with mysql_warnings()
- Send an ok (+ warning count) to the end user.
-*/
-
-void send_warning(THD *thd, uint sql_errno, const char *err)
-{
- DBUG_ENTER("send_warning");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
- err ? err : ER(sql_errno));
- send_ok(thd);
- DBUG_VOID_RETURN;
-}
-
-
/*
Write error package and flush to client
It's a little too low level, but I don't want to use another buffer for
@@ -166,7 +155,7 @@ void send_warning(THD *thd, uint sql_errno, const char *err)
*/
void
-net_printf(THD *thd, uint errcode, ...)
+net_printf_error(THD *thd, uint errcode, ...)
{
va_list args;
uint length,offset;
@@ -179,17 +168,29 @@ net_printf(THD *thd, uint errcode, ...)
#endif
NET *net= &thd->net;
- DBUG_ENTER("net_printf");
+ DBUG_ENTER("net_printf_error");
DBUG_PRINT("enter",("message: %u",errcode));
+ if (net && net->no_send_error)
+ {
+ thd->clear_error();
+ DBUG_PRINT("info", ("sending error messages prohibited"));
+ DBUG_VOID_RETURN;
+ }
+
+ if (thd->spcont && thd->spcont->find_handler(errcode,
+ MYSQL_ERROR::WARN_LEVEL_ERROR))
+ {
+ DBUG_VOID_RETURN;
+ }
thd->query_error= 1; // needed to catch query errors during replication
#ifndef EMBEDDED_LIBRARY
query_cache_abort(net); // Safety
#endif
va_start(args,errcode);
/*
- The following is needed to make net_printf() work with 0 argument for
- errorcode and use the argument after that as the format string. This
+ The following is needed to make net_printf_error() work with 0 argument
+ for errorcode and use the argument after that as the format string. This
is useful for rare errors that are not worth the hassle to put in
errmsg.sys, but at the same time, the message is not fixed text
*/
@@ -252,7 +253,7 @@ net_printf(THD *thd, uint errcode, ...)
strmake(net->last_error, text_pos, length);
strmake(net->sqlstate, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH);
#endif
- if (!thd->killed)
+ if (thd->killed != THD::KILL_CONNECTION)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, errcode,
text_pos ? text_pos : ER(errcode));
thd->is_fatal_error=0; // Error message is given
@@ -294,7 +295,12 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
DBUG_ENTER("send_ok");
if (net->no_send_ok || !net->vio) // hack for re-parsing queries
+ {
+ DBUG_PRINT("info", ("no send ok: %s, vio present: %s",
+ (net->no_send_ok ? "YES" : "NO"),
+ (net->vio ? "YES" : "NO")));
DBUG_VOID_RETURN;
+ }
buff[0]=0; // No fields
pos=net_store_length(buff+1,(ulonglong) affected_rows);
@@ -326,6 +332,9 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
VOID(net_flush(net));
/* We can't anymore send an error to the client */
thd->net.report_error= 0;
+ thd->net.no_send_error= 1;
+ DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
+
DBUG_VOID_RETURN;
}
@@ -354,39 +363,52 @@ static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
*/
void
-send_eof(THD *thd, bool no_flush)
+send_eof(THD *thd)
{
NET *net= &thd->net;
DBUG_ENTER("send_eof");
- if (net->vio != 0)
+ if (net->vio != 0 && !net->no_send_eof)
{
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- uchar buff[5];
- uint tmp= min(thd->total_warn_count, 65535);
- buff[0]=254;
- int2store(buff+1, tmp);
- /*
- The following test should never be true, but it's better to do it
- because if 'is_fatal_error' is set the server is not going to execute
- other queries (see the if test in dispatch_command / COM_QUERY)
- */
- if (thd->is_fatal_error)
- thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
- int2store(buff+3, thd->server_status);
- VOID(my_net_write(net,(char*) buff,5));
- VOID(net_flush(net));
- }
- else
- {
- VOID(my_net_write(net,eof_buff,1));
- if (!no_flush)
- VOID(net_flush(net));
- }
+ write_eof_packet(thd, net);
+ VOID(net_flush(net));
+ thd->net.no_send_error= 1;
+ DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
}
DBUG_VOID_RETURN;
}
+
+/*
+ Format EOF packet according to the current protocol and
+ write it to the network output buffer.
+*/
+
+static void write_eof_packet(THD *thd, NET *net)
+{
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ uchar buff[5];
+ /*
+ Don't send warn count during SP execution, as the warn_list
+ is cleared between substatements, and mysqltest gets confused
+ */
+ uint tmp= (thd->spcont ? 0 : min(thd->total_warn_count, 65535));
+ buff[0]= 254;
+ int2store(buff+1, tmp);
+ /*
+ The following test should never be true, but it's better to do it
+ because if 'is_fatal_error' is set the server is not going to execute
+ other queries (see the if test in dispatch_command / COM_QUERY)
+ */
+ if (thd->is_fatal_error)
+ thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
+ int2store(buff+3, thd->server_status);
+ VOID(my_net_write(net, (char*) buff, 5));
+ }
+ else
+ VOID(my_net_write(net, eof_buff, 1));
+}
+
/*
Please client to send scrambled_password in old format.
SYNOPSYS
@@ -497,6 +519,7 @@ bool Protocol::flush()
flag Bit mask with the following functions:
1 send number of rows
2 send default values
+ 4 don't write eof packet
DESCRIPTION
Sum fields has table name empty and field_name.
@@ -507,7 +530,7 @@ bool Protocol::flush()
*/
#ifndef EMBEDDED_LIBRARY
-bool Protocol::send_fields(List<Item> *list, uint flag)
+bool Protocol::send_fields(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
@@ -518,7 +541,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
CHARSET_INFO *thd_charset= thd->variables.character_set_results;
DBUG_ENTER("send_fields");
- if (flag & 1)
+ if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
char *pos=net_store_length(buff, (uint) list->elements);
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
@@ -536,6 +559,11 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
CHARSET_INFO *cs= system_charset_info;
Send_field field;
item->make_field(&field);
+
+ /* Keep things compatible for old clients */
+ if (field.type == MYSQL_TYPE_VARCHAR)
+ field.type= MYSQL_TYPE_VAR_STRING;
+
prot.prepare_for_resend();
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -612,7 +640,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
}
}
local_packet->length((uint) (pos - local_packet->ptr()));
- if (flag & 2)
+ if (flags & SEND_DEFAULTS)
item->send(&prot, &tmp); // Send default value
if (prot.write())
break; /* purecov: inspected */
@@ -621,25 +649,17 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
#endif
}
- my_net_write(&thd->net, eof_buff, 1);
+ if (flags & SEND_EOF)
+ write_eof_packet(thd, &thd->net);
DBUG_RETURN(prepare_for_send(list));
err:
- send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
+ MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
-bool Protocol::send_records_num(List<Item> *list, ulonglong records)
-{
- char *pos;
- char buff[20];
- pos=net_store_length(buff, (uint) list->elements);
- pos=net_store_length(pos, records);
- return my_net_write(&thd->net, buff,(uint) (pos-buff));
-}
-
-
bool Protocol::write()
{
DBUG_ENTER("Protocol::write");
@@ -752,6 +772,8 @@ bool Protocol_simple::store(const char *from, uint length,
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
+ field_types[field_pos] == MYSQL_TYPE_BIT ||
+ field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
@@ -767,6 +789,8 @@ bool Protocol_simple::store(const char *from, uint length,
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
+ field_types[field_pos] == MYSQL_TYPE_BIT ||
+ field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
@@ -791,6 +815,7 @@ bool Protocol_simple::store_short(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_YEAR ||
field_types[field_pos] == MYSQL_TYPE_SHORT);
field_pos++;
#endif
@@ -829,6 +854,20 @@ bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
}
+bool Protocol_simple::store_decimal(const my_decimal *d)
+{
+#ifndef DEBUG_OFF
+ DBUG_ASSERT(field_types == 0 ||
+ field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
+ field_pos++;
+#endif
+ char buff[DECIMAL_MAX_STR_LENGTH];
+ String str(buff, sizeof(buff), &my_charset_bin);
+ (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
+ return net_store_data(str.ptr(), str.length());
+}
+
+
bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
@@ -980,12 +1019,6 @@ void Protocol_prep::prepare_for_resend()
bool Protocol_prep::store(const char *from, uint length, CHARSET_INFO *fromcs)
{
CHARSET_INFO *tocs= thd->variables.character_set_results;
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
- (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
- field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
-#endif
field_pos++;
return store_string_aux(from, length, fromcs, tocs);
}
@@ -993,12 +1026,6 @@ bool Protocol_prep::store(const char *from, uint length, CHARSET_INFO *fromcs)
bool Protocol_prep::store(const char *from,uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
- (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
- field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
-#endif
field_pos++;
return store_string_aux(from, length, fromcs, tocs);
}
@@ -1016,10 +1043,6 @@ bool Protocol_prep::store_null()
bool Protocol_prep::store_tiny(longlong from)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_TINY);
-#endif
char buff[1];
field_pos++;
buff[0]= (uchar) from;
@@ -1029,11 +1052,6 @@ bool Protocol_prep::store_tiny(longlong from)
bool Protocol_prep::store_short(longlong from)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_SHORT ||
- field_types[field_pos] == MYSQL_TYPE_YEAR);
-#endif
field_pos++;
char *to= packet->prep_append(2, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1045,11 +1063,6 @@ bool Protocol_prep::store_short(longlong from)
bool Protocol_prep::store_long(longlong from)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_INT24 ||
- field_types[field_pos] == MYSQL_TYPE_LONG);
-#endif
field_pos++;
char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1061,10 +1074,6 @@ bool Protocol_prep::store_long(longlong from)
bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_LONGLONG);
-#endif
field_pos++;
char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1073,13 +1082,21 @@ bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
return 0;
}
-
-bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
+bool Protocol_prep::store_decimal(const my_decimal *d)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_FLOAT);
+ field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
+ field_pos++;
#endif
+ char buff[DECIMAL_MAX_STR_LENGTH];
+ String str(buff, sizeof(buff), &my_charset_bin);
+ (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
+ return store(str.ptr(), str.length(), str.charset());
+}
+
+bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
+{
field_pos++;
char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1091,10 +1108,6 @@ bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
bool Protocol_prep::store(double from, uint32 decimals, String *buffer)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_DOUBLE);
-#endif
field_pos++;
char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
if (!to)
@@ -1118,12 +1131,6 @@ bool Protocol_prep::store(Field *field)
bool Protocol_prep::store(TIME *tm)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_DATETIME ||
- field_types[field_pos] == MYSQL_TYPE_DATE ||
- field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
-#endif
char buff[12],*pos;
uint length;
field_pos++;
@@ -1158,10 +1165,6 @@ bool Protocol_prep::store_date(TIME *tm)
bool Protocol_prep::store_time(TIME *tm)
{
-#ifndef DEBUG_OFF
- DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_TIME);
-#endif
char buff[13], *pos;
uint length;
field_pos++;
@@ -1188,12 +1191,3 @@ bool Protocol_prep::store_time(TIME *tm)
buff[0]=(char) length; // Length is stored first
return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
}
-
-#ifdef EMBEDDED_LIBRARY
-/* Should be removed when we define the Protocol_cursor's future */
-bool Protocol_cursor::write()
-{
- return Protocol_simple::write();
-}
-#endif
-
diff --git a/sql/protocol.h b/sql/protocol.h
index 32d6acccddf..2717d2258fa 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -50,17 +50,15 @@ public:
Protocol(THD *thd_arg) { init(thd_arg); }
virtual ~Protocol() {}
void init(THD* thd_arg);
- bool send_fields(List<Item> *list, uint flag);
- bool send_records_num(List<Item> *list, ulonglong records);
+
+ enum { SEND_NUM_ROWS= 1, SEND_DEFAULTS= 2, SEND_EOF= 4 };
+ virtual bool send_fields(List<Item> *list, uint flags);
+
bool store(I_List<i_string> *str_list);
bool store(const char *from, CHARSET_INFO *cs);
String *storage_packet() { return packet; }
inline void free() { packet->free(); }
-#ifndef EMBEDDED_LIBRARY
- bool write();
-#else
virtual bool write();
-#endif
inline bool store(uint32 from)
{ return store_long((longlong) from); }
inline bool store(longlong from)
@@ -83,6 +81,7 @@ public:
virtual bool store_short(longlong from)=0;
virtual bool store_long(longlong from)=0;
virtual bool store_longlong(longlong from, bool unsigned_flag)=0;
+ virtual bool store_decimal(const my_decimal *)=0;
virtual bool store(const char *from, uint length, CHARSET_INFO *cs)=0;
virtual bool store(const char *from, uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)=0;
@@ -108,6 +107,7 @@ public:
virtual bool store_short(longlong from);
virtual bool store_long(longlong from);
virtual bool store_longlong(longlong from, bool unsigned_flag);
+ virtual bool store_decimal(const my_decimal *);
virtual bool store(const char *from, uint length, CHARSET_INFO *cs);
virtual bool store(const char *from, uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
@@ -138,6 +138,7 @@ public:
virtual bool store_short(longlong from);
virtual bool store_long(longlong from);
virtual bool store_longlong(longlong from, bool unsigned_flag);
+ virtual bool store_decimal(const my_decimal *);
virtual bool store(const char *from,uint length, CHARSET_INFO *cs);
virtual bool store(const char *from, uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
@@ -158,24 +159,27 @@ public:
MYSQL_ROWS **prev_record;
ulong row_count;
- Protocol_cursor() {}
- Protocol_cursor(THD *thd_arg, MEM_ROOT *ini_alloc) :Protocol_simple(thd_arg), alloc(ini_alloc) {}
+ Protocol_cursor() :data(NULL) {}
+ Protocol_cursor(THD *thd_arg, MEM_ROOT *ini_alloc) :Protocol_simple(thd_arg), alloc(ini_alloc), data(NULL) {}
bool prepare_for_send(List<Item> *item_list)
{
+ row_count= 0;
fields= NULL;
data= NULL;
prev_record= &data;
return Protocol_simple::prepare_for_send(item_list);
}
- bool send_fields(List<Item> *list, uint flag);
+ bool send_fields(List<Item> *list, uint flags);
bool write();
+ uint get_field_count() { return field_count; }
};
void send_warning(THD *thd, uint sql_errno, const char *err=0);
-void net_printf(THD *thd,uint sql_errno, ...);
+void net_printf_error(THD *thd, uint sql_errno, ...);
+void net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0);
-void send_eof(THD *thd, bool no_flush=0);
+void send_eof(THD *thd);
bool send_old_password_request(THD *thd);
char *net_store_length(char *packet,uint length);
char *net_store_data(char *to,const char *from, uint length);
diff --git a/sql/protocol_cursor.cc b/sql/protocol_cursor.cc
index b225e06ed32..093a2bf2b90 100644
--- a/sql/protocol_cursor.cc
+++ b/sql/protocol_cursor.cc
@@ -26,22 +26,21 @@
#include "mysql_priv.h"
#include <mysql.h>
-bool Protocol_cursor::send_fields(List<Item> *list, uint flag)
+bool Protocol_cursor::send_fields(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
MYSQL_FIELD *client_field;
-
- DBUG_ENTER("send_fields");
+ DBUG_ENTER("Protocol_cursor::send_fields");
+
if (prepare_for_send(list))
- return FALSE;
+ return FALSE;
fields= (MYSQL_FIELD *)alloc_root(alloc, sizeof(MYSQL_FIELD) * field_count);
if (!fields)
goto err;
- client_field= fields;
- while ((item= it++))
+ for (client_field= fields; (item= it++) ; client_field++)
{
Send_field server_field;
item->make_field(&server_field);
@@ -51,6 +50,7 @@ bool Protocol_cursor::send_fields(List<Item> *list, uint flag)
client_field->name= strdup_root(alloc, server_field.col_name);
client_field->org_table= strdup_root(alloc, server_field.org_table_name);
client_field->org_name= strdup_root(alloc, server_field.org_col_name);
+ client_field->catalog= strdup_root(alloc, "");
client_field->length= server_field.length;
client_field->type= server_field.type;
client_field->flags= server_field.flags;
@@ -60,12 +60,13 @@ bool Protocol_cursor::send_fields(List<Item> *list, uint flag)
client_field->name_length= strlen(client_field->name);
client_field->org_name_length= strlen(client_field->org_name);
client_field->org_table_length= strlen(client_field->org_table);
+ client_field->catalog_length= 0;
client_field->charsetnr= server_field.charsetnr;
if (INTERNAL_NUM_FIELD(client_field))
client_field->flags|= NUM_FLAG;
- if (flag & 2)
+ if (flags & (uint) Protocol::SEND_DEFAULTS)
{
char buff[80];
String tmp(buff, sizeof(buff), default_charset_info), *res;
@@ -78,16 +79,19 @@ bool Protocol_cursor::send_fields(List<Item> *list, uint flag)
else
client_field->def=0;
client_field->max_length= 0;
- ++client_field;
}
DBUG_RETURN(FALSE);
- err:
- send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */
+
+err:
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
+ MYF(0)); /* purecov: inspected */
DBUG_RETURN(TRUE); /* purecov: inspected */
}
+
/* Get the length of next field. Change parameter to point at fieldstart */
+
bool Protocol_cursor::write()
{
byte *cp= (byte *)packet->ptr();
@@ -100,17 +104,17 @@ bool Protocol_cursor::write()
byte *to;
new_record= (MYSQL_ROWS *)alloc_root(alloc,
- sizeof(MYSQL_ROWS) + (field_count + 1)*sizeof(char *) + packet->length());
+ sizeof(MYSQL_ROWS) + (field_count + 2)*sizeof(char *) + packet->length());
if (!new_record)
goto err;
data_tmp= (byte **)(new_record + 1);
new_record->data= (char **)data_tmp;
- to= (byte *)(fields + field_count + 1);
+ to= (byte *)data_tmp + (field_count + 2)*sizeof(char *);
- for (; cur_field < fields_end; ++cur_field, ++data_tmp)
+ for (; cur_field < fields_end; cur_field++, data_tmp++)
{
- if ((len=net_field_length((uchar **)&cp)))
+ if ((len= net_field_length((uchar **)&cp)) == NULL_LENGTH)
{
*data_tmp= 0;
}
@@ -118,9 +122,10 @@ bool Protocol_cursor::write()
{
if ((long)len > (end_pos - cp))
{
-// TODO error signal send_error(thd, CR_MALFORMED_PACKET);
+ // TODO error signal send_error(thd, CR_MALFORMED_PACKET);
return TRUE;
}
+ *data_tmp= to;
memcpy(to,(char*) cp,len);
to[len]=0;
to+=len+1;
@@ -129,6 +134,8 @@ bool Protocol_cursor::write()
cur_field->max_length=len;
}
}
+ data_tmp[0]= to; // Pointer to last used byte
+ data_tmp[1]= 0;
*prev_record= new_record;
prev_record= &new_record->next;
@@ -136,8 +143,6 @@ bool Protocol_cursor::write()
row_count++;
return FALSE;
err:
-// TODO error signal send_error(thd, ER_OUT_OF_RESOURCES);
+ // TODO error signal send_error(thd, ER_OUT_OF_RESOURCES);
return TRUE;
}
-
-
diff --git a/sql/records.cc b/sql/records.cc
index e5a0d102b10..9b05dc3e291 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -26,7 +26,7 @@ static int rr_unpack_from_tempfile(READ_RECORD *info);
static int rr_unpack_from_buffer(READ_RECORD *info);
static int rr_from_pointers(READ_RECORD *info);
static int rr_from_cache(READ_RECORD *info);
-static int init_rr_cache(READ_RECORD *info);
+static int init_rr_cache(THD *thd, READ_RECORD *info);
static int rr_cmp(uchar *a,uchar *b);
/* init struct for read with info->read_record */
@@ -84,14 +84,15 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
!(table->file->table_flags() & HA_FAST_KEY_READ) &&
(table->db_stat & HA_READ_ONLY ||
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
- (ulonglong) table->reclength*(table->file->records+
- table->file->deleted) >
+ (ulonglong) table->s->reclength* (table->file->records+
+ table->file->deleted) >
(ulonglong) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
- info->io_cache->end_of_file/info->ref_length*table->reclength >
+ info->io_cache->end_of_file/info->ref_length * table->s->reclength >
(my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
- !table->blob_fields)
+ !table->s->blob_fields &&
+ info->ref_length <= MAX_REFLENGTH)
{
- if (! init_rr_cache(info))
+ if (! init_rr_cache(thd, info))
{
DBUG_PRINT("info",("using rr_from_cache"));
info->read_record=rr_from_cache;
@@ -101,9 +102,6 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
else if (select && select->quick)
{
DBUG_PRINT("info",("using rr_quick"));
-
- if (!table->file->inited)
- table->file->ha_index_init(select->quick->index);
info->read_record=rr_quick;
}
else if (table->sort.record_pointers)
@@ -125,12 +123,19 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
if (!table->no_cache &&
(use_record_cache > 0 ||
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
- !(table->db_options_in_use & HA_OPTION_PACK_RECORD) ||
+ !(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
(use_record_cache < 0 &&
!(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE))))
VOID(table->file->extra_opt(HA_EXTRA_CACHE,
thd->variables.read_buff_size));
}
+ /* Condition pushdown to storage engine */
+ if (thd->variables.engine_condition_pushdown &&
+ select && select->cond &&
+ (select->cond->used_tables() & table->map) &&
+ !table->file->pushed_cond)
+ table->file->cond_push(select->cond);
+
DBUG_VOID_RETURN;
} /* init_read_record */
@@ -189,7 +194,7 @@ static int rr_sequential(READ_RECORD *info)
{
if (info->thd->killed)
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0));
+ info->thd->send_kill_message();
return 1;
}
if (tmp != HA_ERR_RECORD_DELETED)
@@ -321,23 +326,21 @@ static int rr_unpack_from_buffer(READ_RECORD *info)
}
/* cacheing of records from a database */
-static int init_rr_cache(READ_RECORD *info)
+static int init_rr_cache(THD *thd, READ_RECORD *info)
{
uint rec_cache_size;
- THD *thd= current_thd;
-
DBUG_ENTER("init_rr_cache");
- info->struct_length=3+MAX_REFLENGTH;
- info->reclength=ALIGN_SIZE(info->table->reclength+1);
+ info->struct_length= 3+MAX_REFLENGTH;
+ info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
if (info->reclength < info->struct_length)
- info->reclength=ALIGN_SIZE(info->struct_length);
+ info->reclength= ALIGN_SIZE(info->struct_length);
- info->error_offset=info->table->reclength;
- info->cache_records= thd->variables.read_rnd_buff_size /
- (info->reclength+info->struct_length);
- rec_cache_size=info->cache_records*info->reclength;
- info->rec_cache_size=info->cache_records*info->ref_length;
+ info->error_offset= info->table->s->reclength;
+ info->cache_records= (thd->variables.read_rnd_buff_size /
+ (info->reclength+info->struct_length));
+ rec_cache_size= info->cache_records*info->reclength;
+ info->rec_cache_size= info->cache_records*info->ref_length;
// We have to allocate one more byte to use uint3korr (see comments for it)
if (info->cache_records <= 2 ||
@@ -346,7 +349,8 @@ static int init_rr_cache(READ_RECORD *info)
MYF(0))))
DBUG_RETURN(1);
#ifdef HAVE_purify
- bzero(info->cache,rec_cache_size); // Avoid warnings in qsort
+ // Avoid warnings in qsort
+ bzero(info->cache,rec_cache_size+info->cache_records* info->struct_length+1);
#endif
DBUG_PRINT("info",("Allocated buffert for %d records",info->cache_records));
info->read_positions=info->cache+rec_cache_size;
@@ -377,7 +381,8 @@ static int rr_from_cache(READ_RECORD *info)
else
{
error=0;
- memcpy(info->record,info->cache_pos,(size_t) info->table->reclength);
+ memcpy(info->record,info->cache_pos,
+ (size_t) info->table->s->reclength);
}
info->cache_pos+=info->reclength;
return ((int) error);
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 2d8e8a5bf81..59e29d1d80c 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -162,7 +162,7 @@ int register_slave(THD* thd, uchar* packet, uint packet_length)
SLAVE_INFO *si;
uchar *p= packet, *p_end= packet + packet_length;
- if (check_access(thd, REPL_SLAVE_ACL, any_db,0,0,0))
+ if (check_access(thd, REPL_SLAVE_ACL, any_db,0,0,0,0))
return 1;
if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
goto err2;
@@ -193,7 +193,6 @@ err:
my_message(ER_UNKNOWN_ERROR, "Wrong parameters to function register_slave",
MYF(0));
err2:
- send_error(thd);
return 1;
}
@@ -437,7 +436,7 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
This function is broken now. See comment for translate_master().
*/
-int show_new_master(THD* thd)
+bool show_new_master(THD* thd)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_new_master");
@@ -450,23 +449,24 @@ int show_new_master(THD* thd)
{
if (errmsg[0])
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
- "SHOW NEW MASTER", errmsg);
- DBUG_RETURN(-1);
+ "SHOW NEW MASTER", errmsg);
+ DBUG_RETURN(TRUE);
}
else
{
field_list.push_back(new Item_empty_string("Log_name", 20));
field_list.push_back(new Item_return_int("Log_pos", 10,
MYSQL_TYPE_LONGLONG));
- if (protocol->send_fields(&field_list, 1))
- DBUG_RETURN(-1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
protocol->store(lex_mi->log_file_name, &my_charset_bin);
protocol->store((ulonglong) lex_mi->pos);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
}
@@ -629,7 +629,7 @@ err:
}
-int show_slave_hosts(THD* thd)
+bool show_slave_hosts(THD* thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
@@ -649,8 +649,9 @@ int show_slave_hosts(THD* thd)
field_list.push_back(new Item_return_int("Master_id", 10,
MYSQL_TYPE_LONG));
- if (protocol->send_fields(&field_list, 1))
- DBUG_RETURN(-1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
pthread_mutex_lock(&LOCK_slave_list);
@@ -671,12 +672,12 @@ int show_slave_hosts(THD* thd)
if (protocol->write())
{
pthread_mutex_unlock(&LOCK_slave_list);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
pthread_mutex_unlock(&LOCK_slave_list);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -707,6 +708,7 @@ int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi)
if (!mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
mi->port, 0, 0))
DBUG_RETURN(1);
+ mysql->reconnect= 1;
DBUG_RETURN(0);
}
@@ -737,7 +739,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
{
bzero((char*) &table, sizeof(table)); //just for safe
table.db= (char*) db;
- table.real_name= (char*) table_name;
+ table.table_name= (char*) table_name;
table.updating= 1;
if (!tables_ok(thd, &table))
@@ -757,7 +759,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
- No active transaction (flush_relay_log_info would not work in this case)
*/
-int load_master_data(THD* thd)
+bool load_master_data(THD* thd)
{
MYSQL mysql;
MYSQL_RES* master_status_res = 0;
@@ -779,16 +781,15 @@ int load_master_data(THD* thd)
(error=terminate_slave_threads(active_mi,restart_thread_mask,
1 /*skip lock*/)))
{
- send_error(thd,error);
+ my_message(error, ER(error), MYF(0));
unlock_slave_threads(active_mi);
pthread_mutex_unlock(&LOCK_active_mi);
- return 1;
+ return TRUE;
}
if (connect_to_master(thd, &mysql, active_mi))
{
- net_printf(thd, error= ER_CONNECT_TO_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_CONNECT_TO_MASTER, MYF(0), mysql_error(&mysql));
goto err;
}
@@ -800,8 +801,7 @@ int load_master_data(THD* thd)
if (mysql_real_query(&mysql, "SHOW DATABASES", 14) ||
!(db_res = mysql_store_result(&mysql)))
{
- net_printf(thd, error = ER_QUERY_ON_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
goto err;
}
@@ -814,7 +814,7 @@ int load_master_data(THD* thd)
if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*))))
{
- net_printf(thd, error = ER_OUTOFMEMORY);
+ my_message(error = ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
goto err;
}
@@ -828,8 +828,7 @@ int load_master_data(THD* thd)
mysql_real_query(&mysql, "SHOW MASTER STATUS",18) ||
!(master_status_res = mysql_store_result(&mysql)))
{
- net_printf(thd, error = ER_QUERY_ON_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
goto err;
}
@@ -874,7 +873,6 @@ int load_master_data(THD* thd)
if (mysql_create_db(thd, db, &create_info, 1))
{
- send_error(thd, 0, 0);
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
goto err;
}
@@ -883,8 +881,7 @@ int load_master_data(THD* thd)
mysql_real_query(&mysql, "SHOW TABLES", 11) ||
!(*cur_table_res = mysql_store_result(&mysql)))
{
- net_printf(thd, error = ER_QUERY_ON_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
goto err;
}
@@ -922,7 +919,7 @@ int load_master_data(THD* thd)
if (init_master_info(active_mi, master_info_file, relay_log_info_file,
0, (SLAVE_IO | SLAVE_SQL)))
- send_error(thd, ER_MASTER_INFO);
+ my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
strmake(active_mi->master_log_name, row[0],
sizeof(active_mi->master_log_name));
active_mi->master_log_pos= my_strtoll10(row[1], (char**) 0, &error);
@@ -941,8 +938,7 @@ int load_master_data(THD* thd)
if (mysql_real_query(&mysql, "UNLOCK TABLES", 13))
{
- net_printf(thd, error = ER_QUERY_ON_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
goto err;
}
}
@@ -951,10 +947,10 @@ int load_master_data(THD* thd)
0 /* not only reset, but also reinit */,
&errmsg))
{
- send_error(thd, 0, "Failed purging old relay logs");
+ my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
unlock_slave_threads(active_mi);
pthread_mutex_unlock(&LOCK_active_mi);
- return 1;
+ return TRUE;
}
pthread_mutex_lock(&active_mi->rli.data_lock);
active_mi->rli.group_master_log_pos = active_mi->master_log_pos;
diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h
index ad0219bb735..dfaacf557e8 100644
--- a/sql/repl_failsafe.h
+++ b/sql/repl_failsafe.h
@@ -38,11 +38,11 @@ int update_slave_list(MYSQL* mysql, MASTER_INFO* mi);
extern HASH slave_list;
-int load_master_data(THD* thd);
+bool load_master_data(THD* thd);
int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi);
-int show_new_master(THD* thd);
-int show_slave_hosts(THD* thd);
+bool show_new_master(THD* thd);
+bool show_slave_hosts(THD* thd);
int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg);
void init_slave_list();
void end_slave_list();
diff --git a/sql/set_var.cc b/sql/set_var.cc
index e10bfda62b7..ebd278c60f0 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -28,7 +28,7 @@
- If the variable is thread specific, add it to 'system_variables' struct.
If not, add it to mysqld.cc and an declaration in 'mysql_priv.h'
- If the variable should be changed from the command line, add a definition
- of it in the my_option structure list in mysqld.dcc
+ of it in the my_option structure list in mysqld.cc
- Don't forget to initialize new fields in global_system_variables and
max_system_variables!
- If the variable should show up in 'show variables' add it to the
@@ -82,7 +82,7 @@ TYPELIB delay_key_write_typelib=
delay_key_write_type_names, NULL
};
-static int sys_check_charset(THD *thd, set_var *var);
+static int sys_check_charset(THD *thd, set_var *var);
static bool sys_update_charset(THD *thd, set_var *var);
static void sys_set_default_charset(THD *thd, enum_var_type type);
static int sys_check_ftb_syntax(THD *thd, set_var *var);
@@ -97,15 +97,17 @@ static bool set_option_autocommit(THD *thd, set_var *var);
static int check_log_update(THD *thd, set_var *var);
static bool set_log_update(THD *thd, set_var *var);
static int check_pseudo_thread_id(THD *thd, set_var *var);
+static bool set_log_bin(THD *thd, set_var *var);
static void fix_low_priority_updates(THD *thd, enum_var_type type);
static void fix_tx_isolation(THD *thd, enum_var_type type);
+static int check_completion_type(THD *thd, set_var *var);
+static void fix_completion_type(THD *thd, enum_var_type type);
static void fix_net_read_timeout(THD *thd, enum_var_type type);
static void fix_net_write_timeout(THD *thd, enum_var_type type);
static void fix_net_retry_count(THD *thd, enum_var_type type);
static void fix_max_join_size(THD *thd, enum_var_type type);
static void fix_query_cache_size(THD *thd, enum_var_type type);
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
-static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type);
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
static void fix_max_binlog_size(THD *thd, enum_var_type type);
static void fix_max_relay_log_size(THD *thd, enum_var_type type);
@@ -127,25 +129,34 @@ static byte *get_have_innodb(THD *thd);
alphabetic order
*/
+sys_var_thd_ulong sys_auto_increment_increment("auto_increment_increment",
+ &SV::auto_increment_increment);
+sys_var_thd_ulong sys_auto_increment_offset("auto_increment_offset",
+ &SV::auto_increment_offset);
+
+sys_var_bool_ptr sys_automatic_sp_privileges("automatic_sp_privileges",
+ &sp_automatic_privileges);
+
sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size",
&binlog_cache_size);
sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size",
&SV::bulk_insert_buff_size);
sys_var_character_set_server sys_character_set_server("character_set_server");
-sys_var_str sys_charset_system("character_set_system",
- sys_check_charset,
- sys_update_charset,
- sys_set_default_charset,
- (char *)my_charset_utf8_general_ci.name);
+sys_var_const_str sys_charset_system("character_set_system",
+ (char *)my_charset_utf8_general_ci.name);
sys_var_character_set_database sys_character_set_database("character_set_database");
sys_var_character_set_client sys_character_set_client("character_set_client");
sys_var_character_set_connection sys_character_set_connection("character_set_connection");
sys_var_character_set_results sys_character_set_results("character_set_results");
+sys_var_thd_ulong sys_completion_type("completion_type",
+ &SV::completion_type,
+ check_completion_type,
+ fix_completion_type);
sys_var_collation_connection sys_collation_connection("collation_connection");
sys_var_collation_database sys_collation_database("collation_database");
sys_var_collation_server sys_collation_server("collation_server");
-sys_var_bool_ptr sys_concurrent_insert("concurrent_insert",
- &myisam_concurrent_insert);
+sys_var_long_ptr sys_concurrent_insert("concurrent_insert",
+ &myisam_concurrent_insert);
sys_var_long_ptr sys_connect_timeout("connect_timeout",
&connect_timeout);
sys_var_enum sys_delay_key_write("delay_key_write",
@@ -189,6 +200,9 @@ 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_bool_ptr
+sys_trust_routine_creators("log_bin_trust_routine_creators",
+ &trust_routine_creators);
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);
@@ -244,15 +258,15 @@ sys_var_long_ptr sys_max_relay_log_size("max_relay_log_size",
fix_max_relay_log_size);
sys_var_thd_ulong sys_max_sort_length("max_sort_length",
&SV::max_sort_length);
-sys_var_long_ptr sys_max_user_connections("max_user_connections",
- &max_user_connections);
+sys_var_max_user_conn sys_max_user_connections("max_user_connections");
sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables",
&SV::max_tmp_tables);
sys_var_long_ptr sys_max_write_lock_count("max_write_lock_count",
&max_write_lock_count);
+sys_var_thd_ulong sys_multi_range_count("multi_range_count",
+ &SV::multi_range_count);
sys_var_long_ptr sys_myisam_data_pointer_size("myisam_data_pointer_size",
&myisam_data_pointer_size);
-sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size, fix_myisam_max_extra_sort_file_size, 1);
sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads);
sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
@@ -275,6 +289,10 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
0, fix_net_retry_count);
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords);
+sys_var_thd_ulong sys_optimizer_prune_level("optimizer_prune_level",
+ &SV::optimizer_prune_level);
+sys_var_thd_ulong sys_optimizer_search_depth("optimizer_search_depth",
+ &SV::optimizer_search_depth);
sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size",
&SV::preload_buff_size);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
@@ -282,6 +300,8 @@ sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
&SV::read_rnd_buff_size);
+sys_var_thd_ulong sys_div_precincrement("div_precision_increment",
+ &SV::div_precincrement);
#ifdef HAVE_REPLICATION
sys_var_bool_ptr sys_relay_log_purge("relay_log_purge",
&relay_log_purge);
@@ -336,6 +356,11 @@ sys_var_thd_ulong sys_sort_buffer("sort_buffer_size",
&SV::sortbuff_size);
sys_var_thd_sql_mode sys_sql_mode("sql_mode",
&SV::sql_mode);
+sys_var_thd_enum
+sys_updatable_views_with_limit("updatable_views_with_limit",
+ &SV::updatable_views_with_limit,
+ &updatable_views_with_limit_typelib);
+
sys_var_thd_table_type sys_table_type("table_type",
&SV::table_type);
sys_var_thd_storage_engine sys_storage_engine("storage_engine",
@@ -354,6 +379,8 @@ sys_var_thd_ulong sys_sync_replication_timeout(
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_table_lock_wait_timeout("table_lock_wait_timeout",
+ &table_lock_wait_timeout);
sys_var_long_ptr sys_thread_cache_size("thread_cache_size",
&thread_cache_size);
sys_var_thd_enum sys_tx_isolation("tx_isolation",
@@ -362,23 +389,44 @@ sys_var_thd_enum sys_tx_isolation("tx_isolation",
fix_tx_isolation);
sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
&SV::tmp_table_size);
+sys_var_bool_ptr sys_timed_mutexes("timed_mutexes",
+ &timed_mutexes);
sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
&SV::net_wait_timeout);
#ifdef HAVE_INNOBASE_DB
+sys_var_long_ptr sys_innodb_fast_shutdown("innodb_fast_shutdown",
+ &innobase_fast_shutdown);
sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct",
&srv_max_buf_pool_modified_pct);
sys_var_long_ptr sys_innodb_max_purge_lag("innodb_max_purge_lag",
&srv_max_purge_lag);
sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks",
&SV::innodb_table_locks);
+sys_var_thd_bool sys_innodb_support_xa("innodb_support_xa",
+ &SV::innodb_support_xa);
sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment",
&srv_auto_extend_increment);
+sys_var_long_ptr sys_innodb_sync_spin_loops("innodb_sync_spin_loops",
+ &srv_n_spin_wait_rounds);
+sys_var_long_ptr sys_innodb_concurrency_tickets("innodb_concurrency_tickets",
+ &srv_n_free_tickets_to_enter);
+sys_var_long_ptr sys_innodb_thread_sleep_delay("innodb_thread_sleep_delay",
+ &srv_thread_sleep_delay);
+sys_var_long_ptr sys_innodb_thread_concurrency("innodb_thread_concurrency",
+ &srv_thread_concurrency);
+sys_var_long_ptr sys_innodb_commit_concurrency("innodb_commit_concurrency",
+ &srv_commit_concurrency);
#endif
+/* Condition pushdown to storage engine */
+sys_var_thd_bool
+sys_engine_condition_pushdown("engine_condition_pushdown",
+ &SV::engine_condition_pushdown);
+
#ifdef HAVE_NDBCLUSTER_DB
/* ndb thread specific variable settings */
-sys_var_thd_ulong
+sys_var_thd_ulong
sys_ndb_autoincrement_prefetch_sz("ndb_autoincrement_prefetch_sz",
&SV::ndb_autoincrement_prefetch_sz);
sys_var_thd_bool
@@ -387,6 +435,8 @@ sys_var_thd_bool
sys_ndb_use_exact_count("ndb_use_exact_count", &SV::ndb_use_exact_count);
sys_var_thd_bool
sys_ndb_use_transactions("ndb_use_transactions", &SV::ndb_use_transactions);
+sys_var_long_ptr
+sys_ndb_cache_check_time("ndb_cache_check_time", &ndb_cache_check_time);
#endif
/* Time/date/datetime formats */
@@ -403,10 +453,10 @@ sys_var_thd_date_time_format sys_datetime_format("datetime_format",
/* Variables that are bits in THD */
-static sys_var_thd_bit sys_autocommit("autocommit", 0,
- set_option_autocommit,
- OPTION_NOT_AUTOCOMMIT,
- 1);
+sys_var_thd_bit sys_autocommit("autocommit", 0,
+ set_option_autocommit,
+ OPTION_NOT_AUTOCOMMIT,
+ 1);
static sys_var_thd_bit sys_big_tables("big_tables", 0,
set_option_bit,
OPTION_BIG_TABLES);
@@ -427,8 +477,8 @@ static sys_var_thd_bit sys_log_update("sql_log_update",
OPTION_UPDATE_LOG);
static sys_var_thd_bit sys_log_binlog("sql_log_bin",
check_log_update,
- set_log_update,
- OPTION_BIN_LOG);
+ set_log_bin,
+ OPTION_BIN_LOG);
static sys_var_thd_bit sys_sql_warnings("sql_warnings", 0,
set_option_bit,
OPTION_WARNINGS);
@@ -508,7 +558,10 @@ sys_var_const_str sys_license("license", STRINGIFY_ARG(LICENSE));
sys_var *sys_variables[]=
{
&sys_auto_is_null,
+ &sys_auto_increment_increment,
+ &sys_auto_increment_offset,
&sys_autocommit,
+ &sys_automatic_sp_privileges,
&sys_big_tables,
&sys_big_selects,
&sys_binlog_cache_size,
@@ -519,13 +572,16 @@ sys_var *sys_variables[]=
&sys_character_set_client,
&sys_character_set_connection,
&sys_character_set_results,
+ &sys_charset_system,
&sys_collation_connection,
&sys_collation_database,
&sys_collation_server,
+ &sys_completion_type,
&sys_concurrent_insert,
&sys_connect_timeout,
&sys_date_format,
&sys_datetime_format,
+ &sys_div_precincrement,
&sys_default_week_format,
&sys_delay_key_write,
&sys_delayed_insert_limit,
@@ -575,8 +631,8 @@ sys_var *sys_variables[]=
&sys_max_tmp_tables,
&sys_max_user_connections,
&sys_max_write_lock_count,
+ &sys_multi_range_count,
&sys_myisam_data_pointer_size,
- &sys_myisam_max_extra_sort_file_size,
&sys_myisam_max_sort_file_size,
&sys_myisam_repair_threads,
&sys_myisam_sort_buffer_size,
@@ -588,6 +644,8 @@ sys_var *sys_variables[]=
&sys_net_write_timeout,
&sys_new_mode,
&sys_old_passwords,
+ &sys_optimizer_prune_level,
+ &sys_optimizer_search_depth,
&sys_preload_buff_size,
&sys_pseudo_thread_id,
&sys_query_alloc_block_size,
@@ -637,9 +695,11 @@ sys_var *sys_variables[]=
#endif
&sys_sync_frm,
&sys_table_cache_size,
+ &sys_table_lock_wait_timeout,
&sys_table_type,
&sys_thread_cache_size,
&sys_time_format,
+ &sys_timed_mutexes,
&sys_timestamp,
&sys_time_zone,
&sys_tmp_table_size,
@@ -648,19 +708,30 @@ sys_var *sys_variables[]=
&sys_tx_isolation,
&sys_os,
#ifdef HAVE_INNOBASE_DB
+ &sys_innodb_fast_shutdown,
&sys_innodb_max_dirty_pages_pct,
&sys_innodb_max_purge_lag,
&sys_innodb_table_locks,
+ &sys_innodb_support_xa,
&sys_innodb_max_purge_lag,
&sys_innodb_autoextend_increment,
+ &sys_innodb_sync_spin_loops,
+ &sys_innodb_concurrency_tickets,
+ &sys_innodb_thread_sleep_delay,
+ &sys_innodb_thread_concurrency,
+ &sys_innodb_commit_concurrency,
#endif
+ &sys_trust_routine_creators,
+ &sys_engine_condition_pushdown,
#ifdef HAVE_NDBCLUSTER_DB
&sys_ndb_autoincrement_prefetch_sz,
+ &sys_ndb_cache_check_time,
&sys_ndb_force_send,
&sys_ndb_use_exact_count,
&sys_ndb_use_transactions,
#endif
&sys_unique_checks,
+ &sys_updatable_views_with_limit,
&sys_warning_count
};
@@ -670,6 +741,9 @@ sys_var *sys_variables[]=
*/
struct show_var_st init_vars[]= {
+ {"auto_increment_increment", (char*) &sys_auto_increment_increment, SHOW_SYS},
+ {"auto_increment_offset", (char*) &sys_auto_increment_offset, SHOW_SYS},
+ {sys_automatic_sp_privileges.name,(char*) &sys_automatic_sp_privileges, SHOW_SYS},
{"back_log", (char*) &back_log, SHOW_LONG},
{"basedir", mysql_home, SHOW_CHAR},
#ifdef HAVE_BERKELEY_DB
@@ -693,6 +767,7 @@ struct show_var_st init_vars[]= {
{sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS},
{sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS},
{sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS},
+ {sys_completion_type.name, (char*) &sys_completion_type, SHOW_SYS},
{sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS},
{sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS},
{"datadir", mysql_real_data_home, SHOW_CHAR},
@@ -703,6 +778,9 @@ struct show_var_st init_vars[]= {
{sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS},
{sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS},
{sys_delayed_queue_size.name,(char*) &sys_delayed_queue_size, SHOW_SYS},
+ {sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS},
+ {sys_engine_condition_pushdown.name,
+ (char*) &sys_engine_condition_pushdown, SHOW_SYS},
{sys_expire_logs_days.name, (char*) &sys_expire_logs_days, SHOW_SYS},
{sys_flush.name, (char*) &sys_flush, SHOW_SYS},
{sys_flush_time.name, (char*) &sys_flush_time, SHOW_SYS},
@@ -718,7 +796,8 @@ struct show_var_st init_vars[]= {
{"have_compress", (char*) &have_compress, SHOW_HAVE},
{"have_crypt", (char*) &have_crypt, SHOW_HAVE},
{"have_csv", (char*) &have_csv_db, SHOW_HAVE},
- {"have_example_engine", (char*) &have_example_db, SHOW_HAVE},
+ {"have_example_engine", (char*) &have_example_db, SHOW_HAVE},
+ {"have_federated_engine", (char*) &have_federated_db, SHOW_HAVE},
{"have_geometry", (char*) &have_geometry, SHOW_HAVE},
{"have_innodb", (char*) &have_innodb, SHOW_HAVE},
{"have_isam", (char*) &have_isam, SHOW_HAVE},
@@ -736,9 +815,13 @@ struct show_var_st init_vars[]= {
{sys_innodb_autoextend_increment.name, (char*) &sys_innodb_autoextend_increment, SHOW_SYS},
{"innodb_buffer_pool_awe_mem_mb", (char*) &innobase_buffer_pool_awe_mem_mb, SHOW_LONG },
{"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
+ {"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL},
+ {sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS},
+ {sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS},
{"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR},
{"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR},
- {"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL},
+ {"innodb_doublewrite", (char*) &innobase_use_doublewrite, SHOW_MY_BOOL},
+ {sys_innodb_fast_shutdown.name,(char*) &sys_innodb_fast_shutdown, SHOW_SYS},
{"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
{"innodb_file_per_table", (char*) &innobase_file_per_table, SHOW_MY_BOOL},
{"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT},
@@ -756,8 +839,11 @@ struct show_var_st init_vars[]= {
{sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS},
{"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
{"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG },
+ {sys_innodb_support_xa.name, (char*) &sys_innodb_support_xa, SHOW_SYS},
+ {sys_innodb_sync_spin_loops.name, (char*) &sys_innodb_sync_spin_loops, SHOW_SYS},
{sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS},
- {"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG },
+ {sys_innodb_thread_concurrency.name, (char*) &sys_innodb_thread_concurrency, SHOW_SYS},
+ {sys_innodb_thread_sleep_delay.name, (char*) &sys_innodb_thread_sleep_delay, SHOW_SYS},
#endif
{sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS},
{sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS},
@@ -770,6 +856,8 @@ struct show_var_st init_vars[]= {
SHOW_SYS},
{"language", language, SHOW_CHAR},
{"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
+ {"large_page_size", (char*) &opt_large_page_size, SHOW_INT},
+ {"large_pages", (char*) &opt_large_pages, SHOW_MY_BOOL},
{sys_license.name, (char*) &sys_license, SHOW_SYS},
{sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS},
#ifdef HAVE_MLOCKALL
@@ -777,12 +865,12 @@ struct show_var_st init_vars[]= {
#endif
{"log", (char*) &opt_log, SHOW_BOOL},
{"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
+ {sys_trust_routine_creators.name,(char*) &sys_trust_routine_creators, SHOW_SYS},
{"log_error", (char*) log_error_file, SHOW_CHAR},
#ifdef HAVE_REPLICATION
{"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL},
#endif
{"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL},
- {"log_update", (char*) &opt_update_log, SHOW_BOOL},
{sys_log_warnings.name, (char*) &sys_log_warnings, SHOW_SYS},
{sys_long_query_time.name, (char*) &sys_long_query_time, SHOW_SYS},
{sys_low_priority_updates.name, (char*) &sys_low_priority_updates, SHOW_SYS},
@@ -807,10 +895,8 @@ struct show_var_st init_vars[]= {
{sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
{sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS},
{sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS},
+ {sys_multi_range_count.name, (char*) &sys_multi_range_count, SHOW_SYS},
{sys_myisam_data_pointer_size.name, (char*) &sys_myisam_data_pointer_size, SHOW_SYS},
- {sys_myisam_max_extra_sort_file_size.name,
- (char*) &sys_myisam_max_extra_sort_file_size,
- SHOW_SYS},
{sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size,
SHOW_SYS},
{"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
@@ -829,6 +915,7 @@ struct show_var_st init_vars[]= {
{sys_ndb_force_send.name, (char*) &sys_ndb_force_send, SHOW_SYS},
{sys_ndb_use_exact_count.name,(char*) &sys_ndb_use_exact_count, SHOW_SYS},
{sys_ndb_use_transactions.name,(char*) &sys_ndb_use_transactions, SHOW_SYS},
+ {sys_ndb_cache_check_time.name,(char*) &sys_ndb_cache_check_time, SHOW_SYS},
#endif
{sys_net_buffer_length.name,(char*) &sys_net_buffer_length, SHOW_SYS},
{sys_net_read_timeout.name, (char*) &sys_net_read_timeout, SHOW_SYS},
@@ -837,6 +924,10 @@ struct show_var_st init_vars[]= {
{sys_new_mode.name, (char*) &sys_new_mode, SHOW_SYS},
{sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS},
{"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
+ {sys_optimizer_prune_level.name, (char*) &sys_optimizer_prune_level,
+ SHOW_SYS},
+ {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth,
+ SHOW_SYS},
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
{"port", (char*) &mysqld_port, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
@@ -873,7 +964,11 @@ struct show_var_st init_vars[]= {
{"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL},
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
#ifdef HAVE_REPLICATION
+ {sys_slave_compressed_protocol.name,
+ (char*) &sys_slave_compressed_protocol, SHOW_SYS},
+ {"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR},
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
+ {"slave_skip_errors", (char*) &slave_error_mask, SHOW_SLAVE_SKIP_ERRORS},
{sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS},
#endif
{sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS},
@@ -898,6 +993,7 @@ struct show_var_st init_vars[]= {
{"system_time_zone", system_time_zone, SHOW_CHAR},
#endif
{"table_cache", (char*) &table_cache_size, SHOW_LONG},
+ {"table_lock_wait_timeout", (char*) &table_lock_wait_timeout, SHOW_LONG },
{sys_table_type.name, (char*) &sys_table_type, SHOW_SYS},
{sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS},
#ifdef HAVE_THR_SETCONCURRENCY
@@ -906,12 +1002,15 @@ struct show_var_st init_vars[]= {
{"thread_stack", (char*) &thread_stack, SHOW_LONG},
{sys_time_format.name, (char*) &sys_time_format, SHOW_SYS},
{"time_zone", (char*) &sys_time_zone, SHOW_SYS},
+ {sys_timed_mutexes.name, (char*) &sys_timed_mutexes, 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,
SHOW_SYS},
{sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS},
{sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS},
+ {sys_updatable_views_with_limit.name,
+ (char*) &sys_updatable_views_with_limit,SHOW_SYS},
{"version", server_version, SHOW_CHAR},
#ifdef HAVE_BERKELEY_DB
{"version_bdb", (char*) DB_VERSION_STRING, SHOW_CHAR},
@@ -937,8 +1036,8 @@ bool sys_var_str::check(THD *thd, set_var *var)
return 0;
if ((res=(*check_func)(thd, var)) < 0)
- my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name,
- var->value->str_value.ptr());
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
+ name, var->value->str_value.ptr());
return res;
}
@@ -1026,27 +1125,6 @@ static void sys_default_ftb_syntax(THD *thd, enum_var_type type)
sizeof(ft_boolean_syntax)-1);
}
-/*
- The following 3 functions need to be changed in 4.1 when we allow
- one to change character sets
-*/
-
-static int sys_check_charset(THD *thd, set_var *var)
-{
- return 0;
-}
-
-
-static bool sys_update_charset(THD *thd, set_var *var)
-{
- return 0;
-}
-
-
-static void sys_set_default_charset(THD *thd, enum_var_type type)
-{
-}
-
/*
If one sets the LOW_PRIORIY UPDATES flag, we also must change the
@@ -1062,14 +1140,6 @@ static void fix_low_priority_updates(THD *thd, enum_var_type type)
static void
-fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type)
-{
- myisam_max_extra_temp_length=
- (my_off_t) global_system_variables.myisam_max_extra_sort_file_size;
-}
-
-
-static void
fix_myisam_max_sort_file_size(THD *thd, enum_var_type type)
{
myisam_max_temp_length=
@@ -1104,6 +1174,21 @@ static void fix_tx_isolation(THD *thd, enum_var_type type)
thd->variables.tx_isolation);
}
+static void fix_completion_type(THD *thd __attribute__(unused),
+ enum_var_type type __attribute__(unused)) {}
+
+static int check_completion_type(THD *thd, set_var *var)
+{
+ longlong val= var->value->val_int();
+ if (val < 0 || val > 2)
+ {
+ char buf[64];
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf));
+ return 1;
+ }
+ return 0;
+}
+
/*
If we are changing the thread variable, we have to copy it to NET too
@@ -1218,7 +1303,6 @@ static int check_max_delayed_threads(THD *thd, set_var *var)
return 0;
}
-
static void fix_max_connections(THD *thd, enum_var_type type)
{
#ifndef EMBEDDED_LIBRARY
@@ -1239,10 +1323,12 @@ static void fix_thd_mem_root(THD *thd, enum_var_type type)
static void fix_trans_mem_root(THD *thd, enum_var_type type)
{
+#ifdef USING_TRANSACTIONS
if (type != OPT_GLOBAL)
reset_root_defaults(&thd->transaction.mem_root,
thd->variables.trans_alloc_block_size,
thd->variables.trans_prealloc_size);
+#endif
}
@@ -1337,6 +1423,12 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var)
if ((ulong) tmp > max_system_variables.*offset)
tmp= max_system_variables.*offset;
+#if SIZEOF_LONG == 4
+ /* Avoid overflows on 32 bit systems */
+ if (tmp > (ulonglong) ~(ulong) 0)
+ tmp= ((ulonglong) ~(ulong) 0);
+#endif
+
if (option_limits)
tmp= (ulong) getopt_ull_limit_value(tmp, option_limits);
if (var->type == OPT_GLOBAL)
@@ -1487,7 +1579,7 @@ byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type,
bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
const char *value;
String str(buff, sizeof(buff), system_charset_info), *res;
@@ -1524,7 +1616,7 @@ err:
bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
{
bool not_used;
- char buff[80], *error= 0;
+ char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
uint error_len= 0;
String str(buff, sizeof(buff), system_charset_info), *res;
@@ -1584,13 +1676,21 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
var_type= OPT_GLOBAL;
}
switch (type()) {
+ case SHOW_INT:
+ {
+ uint value;
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ value= *(uint*) value_ptr(thd, var_type, base);
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ return new Item_uint((ulonglong) value);
+ }
case SHOW_LONG:
{
ulong value;
pthread_mutex_lock(&LOCK_global_system_variables);
value= *(ulong*) value_ptr(thd, var_type, base);
pthread_mutex_unlock(&LOCK_global_system_variables);
- return new Item_uint((int32) value);
+ return new Item_uint((ulonglong) value);
}
case SHOW_LONGLONG:
{
@@ -1729,7 +1829,7 @@ bool sys_var_thd_date_time_format::update(THD *thd, set_var *var)
bool sys_var_thd_date_time_format::check(THD *thd, set_var *var)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String str(buff,sizeof(buff), system_charset_info), *res;
DATE_TIME_FORMAT *format;
@@ -1833,7 +1933,7 @@ bool sys_var_collation::check(THD *thd, set_var *var)
if (var->value->result_type() == STRING_RESULT)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String str(buff,sizeof(buff), system_charset_info), *res;
if (!(res=var->value->val_str(&str)))
{
@@ -1867,7 +1967,7 @@ bool sys_var_character_set::check(THD *thd, set_var *var)
if (var->value->result_type() == STRING_RESULT)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String str(buff,sizeof(buff), system_charset_info), *res;
if (!(res=var->value->val_str(&str)))
{
@@ -2006,21 +2106,6 @@ 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)
{
@@ -2113,20 +2198,6 @@ 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)
{
@@ -2225,7 +2296,12 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
if (!tmp) // Zero size means delete
{
if (key_cache == dflt_key_cache)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_CANT_DROP_DEFAULT_KEYCACHE,
+ ER(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE));
goto end; // Ignore default key cache
+ }
if (key_cache->key_cache_inited) // If initied
{
@@ -2399,7 +2475,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
pthread_mutex_lock(&active_mi->rli.run_lock);
if (active_mi->rli.slave_running)
{
- my_error(ER_SLAVE_MUST_STOP, MYF(0));
+ my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
result=1;
}
pthread_mutex_unlock(&active_mi->rli.run_lock);
@@ -2434,14 +2510,6 @@ 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= (ulong) var->save_result.ulonglong_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 */
@@ -2461,23 +2529,12 @@ 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];
+ 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(res, thd->lex->time_zone_tables_used)))
+ my_tz_find(res, thd->lex->time_zone_tables_used)))
{
my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), res ? res->c_ptr() : "NULL");
return 1;
@@ -2511,7 +2568,18 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type,
if (type == OPT_GLOBAL)
return (byte *)(global_system_variables.time_zone->get_name()->ptr());
else
+ {
+ /*
+ This is an ugly fix for replication: we don't replicate properly queries
+ invoking system variables' values to update tables; but
+ CONVERT_TZ(,,@@session.time_zone) is so popular that we make it
+ replicable (i.e. we tell the binlog code to store the session
+ timezone). If it's the global value which was used we can't replicate
+ (binlog code stores session value only).
+ */
+ thd->time_zone_used= 1;
return (byte *)(thd->variables.time_zone->get_name()->ptr());
+ }
}
@@ -2538,6 +2606,51 @@ void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
pthread_mutex_unlock(&LOCK_global_system_variables);
}
+
+bool sys_var_max_user_conn::check(THD *thd, set_var *var)
+{
+ if (var->type == OPT_GLOBAL)
+ return sys_var_thd::check(thd, var);
+ else
+ {
+ /*
+ Per-session values of max_user_connections can't be set directly.
+ QQ: May be we should have a separate error message for this?
+ */
+ my_error(ER_GLOBAL_VARIABLE, MYF(0), name);
+ return TRUE;
+ }
+}
+
+bool sys_var_max_user_conn::update(THD *thd, set_var *var)
+{
+ DBUG_ASSERT(var->type == OPT_GLOBAL);
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ max_user_connections= (uint)var->save_result.ulonglong_value;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ return 0;
+}
+
+
+void sys_var_max_user_conn::set_default(THD *thd, enum_var_type type)
+{
+ DBUG_ASSERT(type == OPT_GLOBAL);
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ max_user_connections= (ulong) option_limits->def_value;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+}
+
+
+byte *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ if (type != OPT_GLOBAL &&
+ thd->user_connect && thd->user_connect->user_resources.user_conn)
+ return (byte*) &(thd->user_connect->user_resources.user_conn);
+ return (byte*) &(max_user_connections);
+}
+
+
/*
Functions to update thd->options bits
*/
@@ -2597,6 +2710,30 @@ static int check_log_update(THD *thd, set_var *var)
static bool set_log_update(THD *thd, set_var *var)
{
+ /*
+ The update log is not supported anymore since 5.0.
+ See sql/mysqld.cc/, comments in function init_server_components() for an
+ explaination of the different warnings we send below
+ */
+
+ if (opt_sql_bin_update)
+ {
+ ((sys_var_thd_bit*) var->var)->bit_flag|= (OPTION_BIN_LOG |
+ OPTION_UPDATE_LOG);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_UPDATE_LOG_DEPRECATED_TRANSLATED,
+ ER(ER_UPDATE_LOG_DEPRECATED_TRANSLATED));
+ }
+ else
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_UPDATE_LOG_DEPRECATED_IGNORED,
+ ER(ER_UPDATE_LOG_DEPRECATED_IGNORED));
+ set_option_bit(thd, var);
+ return 0;
+}
+
+static bool set_log_bin(THD *thd, set_var *var)
+{
if (opt_sql_bin_update)
((sys_var_thd_bit*) var->var)->bit_flag|= (OPTION_BIN_LOG |
OPTION_UPDATE_LOG);
@@ -2737,9 +2874,6 @@ void set_var_free()
length Length of variable. zero means that we should use strlen()
on the variable
- NOTE
- We have to use net_printf() as this is called during the parsing stage
-
RETURN VALUES
pointer pointer to variable definitions
0 Unknown variable (error message is given)
@@ -2752,7 +2886,7 @@ sys_var *find_sys_var(const char *str, uint length)
length ? length :
strlen(str));
if (!var)
- net_printf(current_thd, ER_UNKNOWN_SYSTEM_VARIABLE, (char*) str);
+ my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
return var;
}
@@ -2840,11 +2974,15 @@ bool not_all_support_one_shot(List<set_var_base> *var_list)
int set_var::check(THD *thd)
{
+ if (var->is_readonly())
+ {
+ my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name, "read only");
+ return -1;
+ }
if (var->check_type(type))
{
- my_error(type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE,
- MYF(0),
- var->name);
+ int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
+ my_error(err, MYF(0), var->name);
return -1;
}
if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
@@ -2860,8 +2998,8 @@ int set_var::check(THD *thd)
return 0;
}
- if ((!value->fixed &&
- value->fix_fields(thd, 0, &value)) || value->check_cols(1))
+ if ((!value->fixed &&
+ value->fix_fields(thd, &value)) || value->check_cols(1))
return -1;
if (var->check_update_type(value->result_type()))
{
@@ -2888,15 +3026,14 @@ int set_var::light_check(THD *thd)
{
if (var->check_type(type))
{
- my_error(type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE,
- MYF(0),
- var->name);
+ int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
+ my_error(err, MYF(0), var->name);
return -1;
}
if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
return 1;
- if (value && ((!value->fixed && value->fix_fields(thd, 0, &value)) ||
+ if (value && ((!value->fixed && value->fix_fields(thd, &value)) ||
value->check_cols(1)))
return -1;
return 0;
@@ -2925,7 +3062,7 @@ int set_var_user::check(THD *thd)
Item_func_set_user_var can't substitute something else on its place =>
0 can be passed as last argument (reference on item)
*/
- return (user_var_item->fix_fields(thd, 0, (Item**) 0) ||
+ return (user_var_item->fix_fields(thd, (Item**) 0) ||
user_var_item->check()) ? -1 : 0;
}
@@ -2948,7 +3085,7 @@ int set_var_user::light_check(THD *thd)
Item_func_set_user_var can't substitute something else on its place =>
0 can be passed as last argument (reference on item)
*/
- return (user_var_item->fix_fields(thd, 0, (Item**) 0));
+ return (user_var_item->fix_fields(thd, (Item**) 0));
}
@@ -2957,7 +3094,7 @@ int set_var_user::update(THD *thd)
if (user_var_item->update())
{
/* Give an error if it's not given already */
- my_error(ER_SET_CONSTANTS_ONLY, MYF(0));
+ my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
return -1;
}
return 0;
@@ -3011,7 +3148,7 @@ int set_var_password::update(THD *thd)
bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
const char *value;
String str(buff, sizeof(buff), &my_charset_latin1), *res;
@@ -3021,7 +3158,7 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
if (!(res=var->value->val_str(&str)) ||
!(var->save_result.ulong_value=
(ulong) (db_type= ha_resolve_by_name(res->ptr(), res->length()))) ||
- ha_checktype(db_type) != db_type)
+ ha_checktype(thd, db_type, 1, 0) != db_type)
{
value= res ? res->c_ptr() : "NULL";
goto err;
@@ -3032,7 +3169,7 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
err:
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value);
- return 1;
+ return 1;
}
@@ -3090,27 +3227,50 @@ bool sys_var_thd_table_type::update(THD *thd, set_var *var)
Functions to handle sql_mode
****************************************************************************/
-byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
- LEX_STRING *base)
+/*
+ Make string representation of mode
+
+ SYNOPSIS
+ thd in thread handler
+ val in sql_mode value
+ len out pointer on length of string
+
+ RETURN
+ pointer to string with sql_mode representation
+*/
+
+byte *sys_var_thd_sql_mode::symbolic_mode_representation(THD *thd, ulong val,
+ ulong *len)
{
- ulong val;
char buff[256];
String tmp(buff, sizeof(buff), &my_charset_latin1);
+ ulong length;
tmp.length(0);
- val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
- thd->variables.*offset);
for (uint i= 0; val; val>>= 1, i++)
{
if (val & 1)
{
- tmp.append(enum_names->type_names[i]);
+ tmp.append(sql_mode_typelib.type_names[i],
+ sql_mode_typelib.type_lengths[i]);
tmp.append(',');
}
}
- if (tmp.length())
- tmp.length(tmp.length() - 1);
- return (byte*) thd->strmake(tmp.ptr(), tmp.length());
+
+ if ((length= tmp.length()))
+ length--;
+ *len= length;
+ return (byte*) thd->strmake(tmp.ptr(), length);
+}
+
+
+byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ ulong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
+ thd->variables.*offset);
+ ulong length_unused;
+ return symbolic_mode_representation(thd, val, &length_unused);
}
@@ -3122,13 +3282,23 @@ void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
thd->variables.*offset= global_system_variables.*offset;
}
+
void fix_sql_mode_var(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
global_system_variables.sql_mode=
fix_sql_mode(global_system_variables.sql_mode);
else
+ {
thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode);
+ /*
+ Update thd->server_status
+ */
+ if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
+ thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
+ else
+ thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES;
+ }
}
/* Map database specific bits to function bits */
@@ -3154,7 +3324,7 @@ ulong fix_sql_mode(ulong sql_mode)
sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
MODE_IGNORE_SPACE |
MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
- MODE_NO_FIELD_OPTIONS);
+ MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
if (sql_mode & MODE_MSSQL)
sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
MODE_IGNORE_SPACE |
@@ -3174,11 +3344,15 @@ ulong fix_sql_mode(ulong sql_mode)
sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
MODE_IGNORE_SPACE |
MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
- MODE_NO_FIELD_OPTIONS);
+ MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
if (sql_mode & MODE_MYSQL40)
- sql_mode|= MODE_NO_FIELD_OPTIONS;
+ sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_HIGH_NOT_PRECEDENCE;
if (sql_mode & MODE_MYSQL323)
- sql_mode|= MODE_NO_FIELD_OPTIONS;
+ sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_HIGH_NOT_PRECEDENCE;
+ if (sql_mode & MODE_TRADITIONAL)
+ sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
+ MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
+ MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER);
return sql_mode;
}
@@ -3292,7 +3466,7 @@ bool process_key_caches(int (* func) (const char *name, KEY_CACHE *))
Used templates
****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<set_var_base>;
template class List_iterator_fast<set_var_base>;
template class I_List_iterator<NAMED_LIST>;
diff --git a/sql/set_var.h b/sql/set_var.h
index 2ac4fc2c260..854409c159e 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -44,20 +44,14 @@ public:
const char *name;
sys_after_update_func after_update;
-#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)
-#if MYSQL_VERSION_ID < 50000
, no_support_one_shot(1)
-#endif
{}
virtual ~sys_var() {}
virtual bool check(THD *thd, set_var *var);
@@ -76,6 +70,7 @@ public:
{ return option_limits == 0; }
Item *item(THD *thd, enum_var_type type, LEX_STRING *base);
virtual bool is_struct() { return 0; }
+ virtual bool is_readonly() const { return 0; }
};
@@ -195,6 +190,7 @@ public:
return 1;
}
bool check_default(enum_var_type type) { return 1; }
+ bool is_readonly() const { return 1; }
};
@@ -366,6 +362,8 @@ public:
}
void set_default(THD *thd, enum_var_type type);
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+ static byte *symbolic_mode_representation(THD *thd, ulong sql_mode,
+ ulong *length);
};
@@ -503,9 +501,7 @@ class sys_var_collation :public sys_var_thd
public:
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; }
@@ -525,13 +521,11 @@ public:
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; }
@@ -570,9 +564,6 @@ 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);
};
@@ -608,9 +599,6 @@ 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);
@@ -710,6 +698,7 @@ public:
return (*value_ptr_func)(thd);
}
SHOW_TYPE type() { return show_type; }
+ bool is_readonly() const { return 1; }
};
class sys_var_thd_time_zone :public sys_var_thd
@@ -718,9 +707,7 @@ 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; }
@@ -734,6 +721,23 @@ public:
virtual void set_default(THD *thd, enum_var_type type);
};
+
+class sys_var_max_user_conn : public sys_var_thd
+{
+public:
+ sys_var_max_user_conn(const char *name_arg):
+ sys_var_thd(name_arg) {}
+ bool check(THD *thd, set_var *var);
+ bool update(THD *thd, set_var *var);
+ bool check_default(enum_var_type type)
+ {
+ return type != OPT_GLOBAL || !option_limits;
+ }
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_INT; }
+ byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+};
+
/****************************************************************************
Classes for parsing of the SET command
****************************************************************************/
@@ -747,9 +751,7 @@ public:
virtual int update(THD *thd)=0; /* To set the value */
/* light check for PS */
virtual int light_check(THD *thd) { return check(thd); }
-#if MYSQL_VERSION_ID < 50000
virtual bool no_support_one_shot() { return 1; }
-#endif
};
@@ -771,7 +773,7 @@ public:
} save_result;
LEX_STRING base; /* for structs */
- set_var(enum_var_type type_arg, sys_var *var_arg, LEX_STRING *base_name_arg,
+ set_var(enum_var_type type_arg, sys_var *var_arg, const LEX_STRING *base_name_arg,
Item *value_arg)
:var(var_arg), type(type_arg), base(*base_name_arg)
{
@@ -782,7 +784,8 @@ public:
if (value_arg && value_arg->type() == Item::FIELD_ITEM)
{
Item_field *item= (Item_field*) value_arg;
- if (!(value=new Item_string(item->field_name, strlen(item->field_name),
+ if (!(value=new Item_string(item->field_name,
+ (uint) strlen(item->field_name),
item->collation.collation)))
value=value_arg; /* Give error message later */
}
@@ -792,9 +795,7 @@ 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
};
@@ -900,10 +901,11 @@ 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;
+extern sys_var_const_str sys_charset_system;
extern sys_var_str sys_init_connect;
extern sys_var_str sys_init_slave;
extern sys_var_thd_time_zone sys_time_zone;
+extern sys_var_thd_bit sys_autocommit;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
NAMED_LIST **found);
diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am
index f0207fdef03..2e23027f1f5 100644
--- a/sql/share/Makefile.am
+++ b/sql/share/Makefile.am
@@ -16,6 +16,8 @@
## Process this file with automake to create Makefile.in
+EXTRA_DIST= errmsg.txt
+
dist-hook:
for dir in charsets @AVAILABLE_LANGUAGES@; do \
test -d $(distdir)/$$dir || mkdir $(distdir)/$$dir; \
@@ -25,10 +27,14 @@ dist-hook:
$(INSTALL_DATA) $(srcdir)/charsets/README $(distdir)/charsets
$(INSTALL_DATA) $(srcdir)/charsets/Index.xml $(distdir)/charsets
-all-local: @AVAILABLE_LANGUAGES_ERRORS@
+all-local: english/errmsg.sys
+
+# Use the english errmsg.sys as a flag that all errmsg.sys needs to be
+# created. Normally these are created by extra/Makefile
-# this is ugly, but portable
-@AVAILABLE_LANGUAGES_ERRORS_RULES@
+english/errmsg.sys: errmsg.txt
+ rm -f $(top_builddir)/include/mysqld_error.h
+ (cd $(top_builddir)/extra && $(MAKE))
install-data-local:
for lang in @AVAILABLE_LANGUAGES@; \
@@ -36,18 +42,12 @@ install-data-local:
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/$$lang; \
$(INSTALL_DATA) $(srcdir)/$$lang/errmsg.sys \
$(DESTDIR)$(pkgdatadir)/$$lang/errmsg.sys; \
- $(INSTALL_DATA) $(srcdir)/$$lang/errmsg.txt \
- $(DESTDIR)$(pkgdatadir)/$$lang/errmsg.txt; \
done
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/charsets
+ $(INSTALL_DATA) $(srcdir)/errmsg.txt \
+ $(DESTDIR)$(pkgdatadir)/errmsg.txt; \
$(INSTALL_DATA) $(srcdir)/charsets/README $(DESTDIR)$(pkgdatadir)/charsets/README
$(INSTALL_DATA) $(srcdir)/charsets/*.xml $(DESTDIR)$(pkgdatadir)/charsets
-fix_errors:
- for lang in @AVAILABLE_LANGUAGES@; \
- do \
- ../../extra/comp_err -C$(srcdir)/charsets/ $(srcdir)/$$lang/errmsg.txt $(srcdir)/$$lang/errmsg.sys; \
- done
-
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml
index ff74de9a02d..32fd1618a8b 100644
--- a/sql/share/charsets/Index.xml
+++ b/sql/share/charsets/Index.xml
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding="utf-8"?>
-<charsets max-id="96">
+<charsets max-id="98">
<copyright>
Copyright (C) 2003 MySQL AB
@@ -559,13 +559,9 @@ To make maintaining easier please:
<charset name="cp932">
<family>Japanese</family>
<description>SJIS for Windows Japanese</description>
- <alias>windows-31j</alias>
- <alias>cswindows31j</alias>
- <alias>sjisms</alias>
- <alias>windows-95j</alias>
- <alias>x-sjis-cp932</alias>
- <alias>ms932</alias>
- <alias>sjisms</alias>
+ <alias>ms_cp932</alias>
+ <alias>sjis_cp932</alias>
+ <alias>sjis_ms</alias>
<collation name="cp932_japanese_ci" id="95" order="Japanese">
<flag>primary</flag>
<flag>compiled</flag>
@@ -576,5 +572,22 @@ To make maintaining easier please:
</collation>
</charset>
+<charset name="eucjpms">
+ <family>Japanese</family>
+ <description>UJIS for Windows Japanese</description>
+ <alias>eucjpms</alias>
+ <alias>eucJP_ms</alias>
+ <alias>ujis_ms</alias>
+ <alias>ujis_cp932</alias>
+ <collation name="eucjpms_japanese_ci" id="97" order="Japanese">
+ <flag>primary</flag>
+ <flag>compiled</flag>
+ </collation>
+ <collation name="eucjpms_bin" id="98" order="Japanese">
+ <flag>binary</flag>
+ <flag>compiled</flag>
+ </collation>
+</charset>
+
</charsets>
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
deleted file mode 100644
index 04f8fcc8dd4..00000000000
--- a/sql/share/czech/errmsg.txt
+++ /dev/null
@@ -1,334 +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 */
-
-/*
- Modifikoval Petr -B©najdr, snajdr@pvt.net, snajdr@cpress.cz v.0.01
- ISO LATIN-8852-2
- Dal-B¹í verze Jan Pazdziora, adelton@fi.muni.cz
- Tue Nov 18 17:53:55 MET 1997
- Tue Dec 2 19:08:54 MET 1997 podle 3.21.15c
- Thu May 7 17:40:49 MET DST 1998 podle 3.21.29
- Thu Apr 1 20:49:57 CEST 1999 podle 3.22.20
- Mon Aug 9 13:30:09 MET DST 1999 podle 3.23.2
- Thu Nov 30 14:02:52 MET 2000 podle 3.23.28
-*/
-
-character-set=latin2
-
-"hashchk",
-"isamchk",
-"NE",
-"ANO",
-"Nemohu vytvo-Bøit soubor '%-.64s' (chybový kód: %d)",
-"Nemohu vytvo-Bøit tabulku '%-.64s' (chybový kód: %d)",
-"Nemohu vytvo-Bøit databázi '%-.64s' (chybový kód: %d)",
-"Nemohu vytvo-Bøit databázi '%-.64s'; databáze ji¾ existuje",
-"Nemohu zru-B¹it databázi '%-.64s', databáze neexistuje",
-"Chyba p-Bøi ru¹ení databáze (nemohu vymazat '%-.64s', chyba %d)",
-"Chyba p-Bøi ru¹ení databáze (nemohu vymazat adresáø '%-.64s', chyba %d)",
-"Chyba p-Bøi výmazu '%-.64s' (chybový kód: %d)",
-"Nemohu -Bèíst záznam v systémové tabulce",
-"Nemohu z-Bískat stav '%-.64s' (chybový kód: %d)",
-"Chyba p-Bøi zji¹»ování pracovní adresáø (chybový kód: %d)",
-"Nemohu uzamknout soubor (chybov-Bý kód: %d)",
-"Nemohu otev-Bøít soubor '%-.64s' (chybový kód: %d)",
-"Nemohu naj-Bít soubor '%-.64s' (chybový kód: %d)",
-"Nemohu -Bèíst adresáø '%-.64s' (chybový kód: %d)",
-"Nemohu zm-Bìnit adresáø na '%-.64s' (chybový kód: %d)",
-"Z-Báznam byl zmìnìn od posledního ètení v tabulce '%-.64s'",
-"Disk je pln-Bý (%s), èekám na uvolnìní nìjakého místa ...",
-"Nemohu zapsat, zdvojen-Bý klíè v tabulce '%-.64s'",
-"Chyba p-Bøi zavírání '%-.64s' (chybový kód: %d)",
-"Chyba p-Bøi ètení souboru '%-.64s' (chybový kód: %d)",
-"Chyba p-Bøi pøejmenování '%-.64s' na '%-.64s' (chybový kód: %d)",
-"Chyba p-Bøi zápisu do souboru '%-.64s' (chybový kód: %d)",
-"'%-.64s' je zam-Bèen proti zmìnám",
-"T-Bøídìní pøeru¹eno",
-"Pohled '%-.64s' pro '%-.64s' neexistuje",
-"Obsluha tabulky vr-Bátila chybu %d",
-"Obsluha tabulky '%-.64s' nem-Bá tento parametr",
-"Nemohu naj-Bít záznam v '%-.64s'",
-"Nespr-Bávná informace v souboru '%-.64s'",
-"Nespr-Bávný klíè pro tabulku '%-.64s'; pokuste se ho opravit",
-"Star-Bý klíèový soubor pro '%-.64s'; opravte ho.",
-"'%-.64s' je jen pro -Bètení",
-"M-Bálo pamìti. Pøestartujte daemona a zkuste znovu (je potøeba %d bytù)",
-"M-Bálo pamìti pro tøídìní. Zvy¹te velikost tøídícího bufferu",
-"Neo-Bèekávaný konec souboru pøi ètení '%-.64s' (chybový kód: %d)",
-"P-Bøíli¹ mnoho spojení",
-"M-Bálo prostoru/pamìti pro thread",
-"Nemohu zjistit jm-Béno stroje pro Va¹i adresu",
-"Chyba p-Bøi ustavování spojení",
-"P-Bøístup pro u¾ivatele '%-.32s'@'%-.64s' k databázi '%-.64s' není povolen",
-"P-Bøístup pro u¾ivatele '%-.32s'@'%-.64s' (s heslem %s)",
-"Nebyla vybr-Bána ¾ádná databáze",
-"Nezn-Bámý pøíkaz",
-"Sloupec '%-.64s' nem-Bù¾e být null",
-"Nezn-Bámá databáze '%-.64s'",
-"Tabulka '%-.64s' ji-B¾ existuje",
-"Nezn-Bámá tabulka '%-.64s'",
-"Sloupec '%-.64s' v %s nen-Bí zcela jasný",
-"Prob-Bíhá ukonèování práce serveru",
-"Nezn-Bámý sloupec '%-.64s' v %s",
-"Pou-B¾ité '%-.64s' nebylo v group by",
-"Nemohu pou-B¾ít group na '%-.64s'",
-"P-Bøíkaz obsahuje zároveò funkci sum a sloupce",
-"Po-Bèet sloupcù neodpovídá zadané hodnotì",
-"Jm-Béno identifikátoru '%-.64s' je pøíli¹ dlouhé",
-"Zdvojen-Bé jméno sloupce '%-.64s'",
-"Zdvojen-Bé jméno klíèe '%-.64s'",
-"Zvojen-Bý klíè '%-.64s' (èíslo klíèe %d)",
-"Chybn-Bá specifikace sloupce '%-.64s'",
-"%s bl-Bízko '%-.64s' na øádku %d",
-"V-Býsledek dotazu je prázdný",
-"Nejednozna-Bèná tabulka/alias: '%-.64s'",
-"Chybn-Bá defaultní hodnota pro '%-.64s'",
-"Definov-Báno více primárních klíèù",
-"Zad-Báno pøíli¹ mnoho klíèù, je povoleno nejvíce %d klíèù",
-"Zad-Báno pøíli¹ mnoho èást klíèù, je povoleno nejvíce %d èástí",
-"Zadan-Bý klíè byl pøíli¹ dlouhý, nejvìt¹í délka klíèe je %d",
-"Kl-Bíèový sloupec '%-.64s' v tabulce neexistuje",
-"Blob sloupec '%-.64s' nem-Bù¾e být pou¾it jako klíè",
-"P-Bøíli¹ velká délka sloupce '%-.64s' (nejvíce %d). Pou¾ijte BLOB",
-"M-Bù¾ete mít pouze jedno AUTO pole a to musí být definováno jako klíè",
-"%s: p-Bøipraven na spojení",
-"%s: norm-Bální ukonèení\n",
-"%s: p-Bøijat signal %d, konèím\n",
-"%s: ukon-Bèení práce hotovo\n",
-"%s: n-Básilné uzavøení threadu %ld u¾ivatele '%-.64s'\n",
-"Nemohu vytvo-Bøit IP socket",
-"Tabulka '%-.64s' nem-Bá index odpovídající CREATE INDEX. Vytvoøte tabulku znovu",
-"Argument separ-Bátoru polo¾ek nebyl oèekáván. Pøeètìte si manuál",
-"Nen-Bí mo¾né pou¾ít pevný rowlength s BLOBem. Pou¾ijte 'fields terminated by'.",
-"Soubor '%-.64s' mus-Bí být v adresáøi databáze nebo èitelný pro v¹echny",
-"Soubor '%-.64s' ji-B¾ existuje",
-"Z-Báznamù: %ld Vymazáno: %ld Pøeskoèeno: %ld Varování: %ld",
-"Z-Báznamù: %ld Zdvojených: %ld",
-"Chybn-Bá podèást klíèe -- není to øetìzec nebo je del¹í ne¾ délka èásti klíèe",
-"Nen-Bí mo¾né vymazat v¹echny polo¾ky s ALTER TABLE. Pou¾ijte DROP TABLE",
-"Nemohu zru-B¹it '%-.64s' (provést DROP). Zkontrolujte, zda neexistují záznamy/klíèe",
-"Z-Báznamù: %ld Zdvojených: %ld Varování: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Nezn-Bámá identifikace threadu: %lu",
-"Nejste vlastn-Bíkem threadu %lu",
-"Nejsou pou-B¾ity ¾ádné tabulky",
-"P-Bøíli¹ mnoho øetìzcù pro sloupec %s a SET",
-"Nemohu vytvo-Bøit jednoznaèné jméno logovacího souboru %s.(1-999)\n",
-"Tabulka '%-.64s' byla zam-Bèena s READ a nemù¾e být zmìnìna",
-"Tabulka '%-.64s' nebyla zam-Bèena s LOCK TABLES",
-"Blob polo-B¾ka '%-.64s' nemù¾e mít defaultní hodnotu",
-"Nep-Bøípustné jméno databáze '%-.64s'",
-"Nep-Bøípustné jméno tabulky '%-.64s'",
-"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET SQL_BIG_SELECTS=1",
-"Nezn-Bámá chyba",
-"Nezn-Bámá procedura %s",
-"Chybn-Bý poèet parametrù procedury %s",
-"Chybn-Bé parametry procedury %s",
-"Nezn-Bámá tabulka '%-.64s' v %s",
-"Polo-B¾ka '%-.64s' je zadána dvakrát",
-"Nespr-Bávné pou¾ití funkce group",
-"Tabulka '%-.64s' pou-B¾ívá roz¹íøení, které v této verzi MySQL není",
-"Tabulka mus-Bí mít alespoò jeden sloupec",
-"Tabulka '%-.64s' je pln-Bá",
-"Nezn-Bámá znaková sada: '%-.64s'",
-"P-Bøíli¹ mnoho tabulek, MySQL jich mù¾e mít v joinu jen %d",
-"P-Bøíli¹ mnoho polo¾ek",
-"-BØádek je pøíli¹ velký. Maximální velikost øádku, nepoèítaje polo¾ky blob, je %d. Musíte zmìnit nìkteré polo¾ky na blob",
-"P-Bøeteèení zásobníku threadu: pou¾ito %ld z %ld. Pou¾ijte 'mysqld -O thread_stack=#' k zadání vìt¹ího zásobníku",
-"V OUTER JOIN byl nalezen k-Bøí¾ový odkaz. Provìøte ON podmínky",
-"Sloupec '%-.32s' je pou-B¾it s UNIQUE nebo INDEX, ale není definován jako NOT NULL",
-"Nemohu na-Bèíst funkci '%-.64s'",
-"Nemohu inicializovat funkci '%-.64s'; %-.80s",
-"Pro sd-Bílenou knihovnu nejsou povoleny cesty",
-"Funkce '%-.64s' ji-B¾ existuje",
-"Nemohu otev-Bøít sdílenou knihovnu '%-.64s' (errno: %d %s)",
-"Nemohu naj-Bít funkci '%-.64s' v knihovnì'",
-"Funkce '%-.64s' nen-Bí definována",
-"Stroj '%-.64s' je zablokov-Bán kvùli mnoha chybám pøi pøipojování. Odblokujete pou¾itím 'mysqladmin flush-hosts'",
-"Stroj '%-.64s' nem-Bá povoleno se k tomuto MySQL serveru pøipojit",
-"Pou-B¾íváte MySQL jako anonymní u¾ivatel a anonymní u¾ivatelé nemají povoleno mìnit hesla",
-"Na zm-Bìnu hesel ostatním musíte mít právo provést update tabulek v databázi mysql",
-"V tabulce user nen-Bí ¾ádný odpovídající øádek",
-"Nalezen-Bých øádkù: %ld Zmìnìno: %ld Varování: %ld",
-"Nemohu vytvo-Bøit nový thread (errno %d). Pokud je je¹tì nìjaká volná pamì», podívejte se do manuálu na èást o chybách specifických pro jednotlivé operaèní systémy",
-"Po-Bèet sloupcù neodpovídá poètu hodnot na øádku %ld",
-"Nemohu znovuotev-Bøít tabulku: '%-.64s",
-"Neplatn-Bé u¾ití hodnoty NULL",
-"Regul-Bární výraz vrátil chybu '%-.64s'",
-"Pokud nen-Bí ¾ádná GROUP BY klauzule, není dovoleno souèasné pou¾ití GROUP polo¾ek (MIN(),MAX(),COUNT()...) s ne GROUP polo¾kami",
-"Neexistuje odpov-Bídající grant pro u¾ivatele '%-.32s' na stroji '%-.64s'",
-"%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.32s'@'%-.64s' pro tabulku '%-.64s'",
-"%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.32s'@'%-.64s' pro sloupec '%-.64s' v tabulce '%-.64s'",
-"Neplatn-Bý pøíkaz GRANT/REVOKE. Prosím, pøeètìte si v manuálu, jaká privilegia je mo¾né pou¾ít.",
-"Argument p-Bøíkazu GRANT u¾ivatel nebo stroj je pøíli¹ dlouhý",
-"Tabulka '%-.64s.%s' neexistuje",
-"Neexistuje odpov-Bídající grant pro u¾ivatele '%-.32s' na stroji '%-.64s' pro tabulku '%-.64s'",
-"Pou-B¾itý pøíkaz není v této verzi MySQL povolen",
-"Va-B¹e syntaxe je nìjaká divná",
-"Zpo-B¾dìný insert threadu nebyl schopen získat po¾adovaný zámek pro tabulku %-.64s",
-"P-Bøíli¹ mnoho zpo¾dìných threadù",
-"Zru-B¹eno spojení %ld do databáze: '%-.64s' u¾ivatel: '%-.64s' (%s)",
-"Zji-B¹tìn pøíchozí packet del¹í ne¾ 'max_allowed_packet'",
-"Zji-B¹tìna chyba pøi ètení z roury spojení",
-"Zji-B¹tìna chyba fcntl()",
-"P-Bøíchozí packety v chybném poøadí",
-"Nemohu rozkomprimovat komunika-Bèní packet",
-"Zji-B¹tìna chyba pøi ètení komunikaèního packetu",
-"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'",
-"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",
-"Nespr-Bávné jméno sloupce '%-.100s'",
-"Handler pou-B¾ité tabulky neumí indexovat sloupce '%-.64s'",
-"V-B¹echny tabulky v MERGE tabulce nejsou definovány stejnì",
-"Kv-Bùli unique constraintu nemozu zapsat do tabulky '%-.64s'",
-"BLOB sloupec '%-.64s' je pou-B¾it ve specifikaci klíèe bez délky",
-"V-B¹echny èásti primárního klíèe musejí být NOT NULL; pokud potøebujete NULL, pou¾ijte UNIQUE",
-"V-Býsledek obsahuje více ne¾ jeden øádek",
-"Tento typ tabulky vy-B¾aduje primární klíè",
-"Tato verze MySQL nen-Bí zkompilována s podporou RAID",
-"Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno",
-"Kl-Bíè '%-.64s' v tabulce '%-.64s' neexistuje",
-"Nemohu otev-Bøít tabulku",
-"Handler tabulky nepodporuje %s",
-"Proveden-Bí tohoto pøíkazu není v transakci dovoleno",
-"Chyba %d p-Bøi COMMIT",
-"Chyba %d p-Bøi ROLLBACK",
-"Chyba %d p-Bøi FLUSH_LOGS",
-"Chyba %d p-Bøi CHECKPOINT",
-"Spojen-Bí %ld do databáze: '%-.64s' u¾ivatel: '%-.32s' stroj: `%-.64s' (%-.64s) bylo pøeru¹eno",
-"Handler tabulky nepodporuje bin-Bární dump",
-"Binlog uzav-Bøen pøi pokusu o FLUSH MASTER",
-"P-Bøebudování indexu dumpnuté tabulky '%-.64s' nebylo úspì¹né",
-"Chyba masteru: '%-.64s'",
-"S-Bí»ová chyba pøi ètení z masteru",
-"S-Bí»ová chyba pøi zápisu na master",
-"-B®ádný sloupec nemá vytvoøen fulltextový index",
-"Nemohu prov-Bést zadaný pøíkaz, proto¾e existují aktivní zamèené tabulky nebo aktivní transakce",
-"Nezn-Bámá systémová promìnná '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updatable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
deleted file mode 100644
index 4983d39714a..00000000000
--- a/sql/share/danish/errmsg.txt
+++ /dev/null
@@ -1,325 +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 */
-
-/* Knud Riishøjgård knudriis@post.tele.dk 99 &&
- Carsten H. Pedersen, carsten.pedersen@bitbybit.dk oct. 1999 / aug. 2001. */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NEJ",
-"JA",
-"Kan ikke oprette filen '%-.64s' (Fejlkode: %d)",
-"Kan ikke oprette tabellen '%-.64s' (Fejlkode: %d)",
-"Kan ikke oprette databasen '%-.64s' (Fejlkode: %d)",
-"Kan ikke oprette databasen '%-.64s'; databasen eksisterer",
-"Kan ikke slette (droppe) '%-.64s'; databasen eksisterer ikke",
-"Fejl ved sletning (drop) af databasen (kan ikke slette '%-.64s', Fejlkode %d)",
-"Fejl ved sletting af database (kan ikke slette folderen '%-.64s', Fejlkode %d)",
-"Fejl ved sletning af '%-.64s' (Fejlkode: %d)",
-"Kan ikke læse posten i systemfolderen",
-"Kan ikke læse status af '%-.64s' (Fejlkode: %d)",
-"Kan ikke læse aktive folder (Fejlkode: %d)",
-"Kan ikke låse fil (Fejlkode: %d)",
-"Kan ikke åbne fil: '%-.64s' (Fejlkode: %d)",
-"Kan ikke finde fila: '%-.64s' (Fejlkode: %d)",
-"Kan ikke læse folder '%-.64s' (Fejlkode: %d)",
-"Kan ikke skifte folder til '%-.64s' (Fejlkode: %d)",
-"Posten er ændret siden sidste læsning '%-.64s'",
-"Ikke mere diskplads (%s). Venter på at få frigjort plads...",
-"Kan ikke skrive, flere ens nøgler i tabellen '%-.64s'",
-"Fejl ved lukning af '%-.64s' (Fejlkode: %d)",
-"Fejl ved læsning af '%-.64s' (Fejlkode: %d)",
-"Fejl ved omdøbning af '%-.64s' til '%-.64s' (Fejlkode: %d)",
-"Fejl ved skriving av filen '%-.64s' (Fejlkode: %d)",
-"'%-.64s' er låst mod opdateringer",
-"Sortering afbrudt",
-"View '%-.64s' eksisterer ikke for '%-.64s'",
-"Modtog fejl %d fra tabel håndteringen",
-"Denne mulighed eksisterer ikke for tabeltypen '%-.64s'",
-"Kan ikke finde posten i '%-.64s'",
-"Forkert indhold i: '%-.64s'",
-"Fejl i indeksfilen til tabellen '%-.64s'; prøv at reparere den",
-"Gammel indeksfil for tabellen '%-.64s'; reparer den",
-"'%-.64s' er skrivebeskyttet",
-"Ikke mere hukommelse. Genstart serveren og prøv igen (mangler %d bytes)",
-"Ikke mere sorteringshukommelse. Øg sorteringshukommelse (sort buffer size) for serveren",
-"Uventet afslutning på fil (eof) ved læsning af filen '%-.64s' (Fejlkode: %d)",
-"For mange forbindelser (connections)",
-"Udgået for tråde/hukommelse",
-"Kan ikke få værtsnavn for din adresse",
-"Forkert håndtryk (handshake)",
-"Adgang nægtet bruger: '%-.32s'@'%-.64s' til databasen '%-.64s'",
-"Adgang nægtet bruger: '%-.32s'@'%-.64s' (Bruger adgangskode: %s)",
-"Ingen database valgt",
-"Ukendt kommando",
-"Kolonne '%-.64s' kan ikke være NULL",
-"Ukendt database '%-.64s'",
-"Tabellen '%-.64s' findes allerede",
-"Ukendt tabel '%-.64s'",
-"Felt: '%-.64s' i tabel %s er ikke entydigt",
-"Database nedlukning er i gang",
-"Ukendt kolonne '%-.64s' i tabel %s",
-"Brugte '%-.64s' som ikke var i group by",
-"Kan ikke gruppere på '%-.64s'",
-"Udtrykket har summer (sum) funktioner og kolonner i samme udtryk",
-"Kolonne tæller stemmer ikke med antallet af værdier",
-"Navnet '%-.64s' er for langt",
-"Feltnavnet '%-.64s' findes allerede",
-"Indeksnavnet '%-.64s' findes allerede",
-"Ens værdier '%-.64s' for indeks %d",
-"Forkert kolonnespecifikaton for felt '%-.64s'",
-"%s nær '%-.64s' på linje %d",
-"Forespørgsel var tom",
-"Tabellen/aliaset: '%-.64s' er ikke unikt",
-"Ugyldig standardværdi for '%-.64s'",
-"Flere primærnøgler specificeret",
-"For mange nøgler specificeret. Kun %d nøgler må bruges",
-"For mange nøgledele specificeret. Kun %d dele må bruges",
-"Specificeret nøgle var for lang. Maksimal nøglelængde er %d",
-"Nøglefeltet '%-.64s' eksisterer ikke i tabellen",
-"BLOB feltet '%-.64s' kan ikke bruges ved specifikation af indeks",
-"For stor feltlængde for kolonne '%-.64s' (maks = %d). Brug BLOB i stedet",
-"Der kan kun specificeres eet AUTO_INCREMENT-felt, og det skal være indekseret",
-"%s: klar til tilslutninger",
-"%s: Normal nedlukning\n",
-"%s: Fangede signal %d. Afslutter!!\n",
-"%s: Server lukket\n",
-"%s: Forceret nedlukning af tråd: %ld bruger: '%-.64s'\n",
-"Kan ikke oprette IP socket",
-"Tabellen '%-.64s' har ikke den nøgle, som blev brugt i CREATE INDEX. Genopret tabellen",
-"Felt adskiller er ikke som forventet, se dokumentationen",
-"Man kan ikke bruge faste feltlængder med BLOB. Brug i stedet 'fields terminated by'.",
-"Filen '%-.64s' skal være i database-folderen og kunne læses af alle",
-"Filen '%-.64s' eksisterer allerede",
-"Poster: %ld Fjernet: %ld Sprunget over: %ld Advarsler: %ld",
-"Poster: %ld Ens: %ld",
-"Forkert indeksdel. Den anvendte nøgledel er ikke en streng eller længden er større end nøglelængden",
-"Man kan ikke slette alle felter med ALTER TABLE. Brug DROP TABLE i stedet.",
-"Kan ikke udføre DROP '%-.64s'. Undersøg om feltet/nøglen eksisterer.",
-"Poster: %ld Ens: %ld Advarsler: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Ukendt tråd id: %lu",
-"Du er ikke ejer af tråden %lu",
-"Ingen tabeller i brug",
-"For mange tekststrenge til specifikationen af SET i kolonne %-.64s",
-"Kan ikke lave unikt log-filnavn %s.(1-999)\n",
-"Tabellen '%-.64s' var låst med READ lås og kan ikke opdateres",
-"Tabellen '%-.64s' var ikke låst med LOCK TABLES",
-"BLOB feltet '%-.64s' kan ikke have en standard værdi",
-"Ugyldigt database navn '%-.64s'",
-"Ugyldigt tabel navn '%-.64s'",
-"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET SQL_BIG_SELECTS=1 hvis udtrykket er korrekt",
-"Ukendt fejl",
-"Ukendt procedure %s",
-"Forkert antal parametre til proceduren %s",
-"Forkert(e) parametre til proceduren %s",
-"Ukendt tabel '%-.64s' i %s",
-"Feltet '%-.64s' er anvendt to gange",
-"Forkert brug af grupperings-funktion",
-"Tabellen '%-.64s' bruger et filtypenavn som ikke findes i denne MySQL version",
-"En tabel skal have mindst een kolonne",
-"Tabellen '%-.64s' er fuld",
-"Ukendt tegnsæt: '%-.64s'",
-"For mange tabeller. MySQL kan kun bruge %d tabeller i et join",
-"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",
-"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",
-"Angivelse af sti ikke tilladt for delt bibliotek",
-"Funktionen '%-.64s' findes allerede",
-"Kan ikke åbne delt bibliotek '%-.64s' (errno: %d %s)",
-"Kan ikke finde funktionen '%-.64s' i bibliotek'",
-"Funktionen '%-.64s' er ikke defineret",
-"Værten er blokeret på grund af mange fejlforespørgsler. Lås op med 'mysqladmin flush-hosts'",
-"Værten '%-.64s' kan ikke tilkoble denne MySQL-server",
-"Du bruger MySQL som anonym bruger. Anonyme brugere må ikke ændre adgangskoder",
-"Du skal have tilladelse til at opdatere tabeller i MySQL databasen for at ændre andres adgangskoder",
-"Kan ikke finde nogen tilsvarende poster i bruger tabellen",
-"Poster fundet: %ld Ændret: %ld Advarsler: %ld",
-"Kan ikke danne en ny tråd (fejl nr. %d). Hvis computeren ikke er løbet tør for hukommelse, kan du se i brugervejledningen for en mulig operativ-system - afhængig fejl",
-"Kolonne antallet stemmer ikke overens med antallet af værdier i post %ld",
-"Kan ikke genåbne tabel '%-.64s",
-"Forkert brug af nulværdi (NULL)",
-"Fik fejl '%-.64s' fra regexp",
-"Sammenblanding af GROUP kolonner (MIN(),MAX(),COUNT()...) uden GROUP kolonner er ikke tilladt, hvis der ikke er noget GROUP BY prædikat",
-"Denne tilladelse findes ikke for brugeren '%-.32s' på vært '%-.64s'",
-"%-.16s-kommandoen er ikke tilladt for brugeren '%-.32s'@'%-.64s' for tabellen '%-.64s'",
-"%-.16s-kommandoen er ikke tilladt for brugeren '%-.32s'@'%-.64s' for kolonne '%-.64s' in tabellen '%-.64s'",
-"Forkert GRANT/REVOKE kommando. Se i brugervejledningen hvilke privilegier der kan specificeres.",
-"Værts- eller brugernavn for langt til GRANT",
-"Tabellen '%-.64s.%-.64s' eksisterer ikke",
-"Denne tilladelse eksisterer ikke for brugeren '%-.32s' på vært '%-.64s' for tabellen '%-.64s'",
-"Den brugte kommando er ikke tilladt med denne udgave af MySQL",
-"Der er en fejl i SQL syntaksen",
-"Forsinket indsættelse tråden (delayed insert thread) kunne ikke opnå lås på tabellen %-.64s",
-"For mange slettede tråde (threads) i brug",
-"Afbrudt forbindelse %ld til database: '%-.64s' bruger: '%-.64s' (%-.64s)",
-"Modtog en datapakke som var større end 'max_allowed_packet'",
-"Fik læsefejl fra forbindelse (connection pipe)",
-"Fik fejlmeddelelse fra fcntl()",
-"Modtog ikke datapakker i korrekt rækkefølge",
-"Kunne ikke dekomprimere kommunikations-pakke (communication packet)",
-"Fik fejlmeddelelse ved læsning af kommunikations-pakker (communication packets)",
-"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'",
-"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",
-"Forkert kolonnenavn '%-.100s'",
-"Den brugte tabeltype kan ikke indeksere kolonnen '%-.64s'",
-"Tabellerne i MERGE er ikke defineret ens",
-"Kan ikke skrive til tabellen '%-.64s' fordi det vil bryde CONSTRAINT regler",
-"BLOB kolonnen '%-.64s' brugt i nøglespecifikation uden nøglelængde",
-"Alle dele af en PRIMARY KEY skal være NOT NULL; Hvis du skal bruge NULL i nøglen, brug UNIQUE istedet",
-"Resultatet bestod af mere end een række",
-"Denne tabeltype kræver en primærnøgle",
-"Denne udgave af MySQL er ikke oversat med understøttelse af RAID",
-"Du bruger sikker opdaterings modus ('safe update mode') og du forsøgte at opdatere en tabel uden en WHERE klausul, der gør brug af et KEY felt",
-"Nøglen '%-.64s' eksisterer ikke i tabellen '%-.64s'",
-"Kan ikke åbne tabellen",
-"Denne tabeltype understøtter ikke %s",
-"Du må ikke bruge denne kommando i en transaktion",
-"Modtog fejl %d mens kommandoen COMMIT blev udført",
-"Modtog fejl %d mens kommandoen ROLLBACK blev udført",
-"Modtog fejl %d mens kommandoen FLUSH_LOGS blev udført",
-"Modtog fejl %d mens kommandoen CHECKPOINT blev udført",
-"Afbrød forbindelsen %ld til databasen '%-.64s' bruger: '%-.32s' vært: `%-.64s' (%-.64s)",
-"Denne tabeltype unserstøtter ikke binært tabeldump",
-"Binlog blev lukket mens kommandoen FLUSH MASTER blev udført",
-"Kunne ikke genopbygge indekset for den dumpede tabel '%-.64s'",
-"Fejl fra master: '%-.64s'",
-"Netværksfejl ved læsning fra master",
-"Netværksfejl ved skrivning til master",
-"Kan ikke finde en FULLTEXT nøgle som svarer til kolonne listen",
-"Kan ikke udføre den givne kommando fordi der findes aktive, låste tabeller eller fordi der udføres en transaktion",
-"Ukendt systemvariabel '%-.64s'",
-"Tabellen '%-.64s' er markeret med fejl og bør repareres",
-"Tabellen '%-.64s' er markeret med fejl og sidste (automatiske?) REPAIR fejlede",
-"Advarsel: Visse data i tabeller der ikke understøtter transaktioner kunne ikke tilbagestilles",
-"Fler-udtryks transaktion krævede mere plads en 'max_binlog_cache_size' bytes. Forhøj værdien af denne variabel og prøv igen",
-"Denne handling kunne ikke udføres med kørende slave, brug først kommandoen STOP SLAVE",
-"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",
-"Brugeren %-.64s har allerede mere end 'max_user_connections' aktive forbindelser",
-"Du må kun bruge konstantudtryk med SET",
-"Lock wait timeout overskredet",
-"Det totale antal låse overstiger størrelsen på låse-tabellen",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
deleted file mode 100644
index 3f320dca750..00000000000
--- a/sql/share/dutch/errmsg.txt
+++ /dev/null
@@ -1,334 +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 */
-
-/*
- Dutch error messages (share/dutch/errmsg.txt)
- 2001-08-02 - Arjen Lentz (agl@bitbike.com)
- Completed earlier partial translation; worked on consistency and spelling.
- 2002-01-29 - Arjen Lentz (arjen@mysql.com)
- 2002-04-11 - Arjen Lentz (arjen@mysql.com)
- 2002-06-13 - Arjen Lentz (arjen@mysql.com)
- 2002-08-08 - Arjen Lentz (arjen@mysql.com)
- 2002-08-22 - Arjen Lentz (arjen@mysql.com)
- Translated new error messages.
-*/
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NEE",
-"JA",
-"Kan file '%-.64s' niet aanmaken (Errcode: %d)",
-"Kan tabel '%-.64s' niet aanmaken (Errcode: %d)",
-"Kan database '%-.64s' niet aanmaken (Errcode: %d)",
-"Kan database '%-.64s' niet aanmaken; database bestaat reeds",
-"Kan database '%-.64s' niet verwijderen; database bestaat niet",
-"Fout bij verwijderen database (kan '%-.64s' niet verwijderen, Errcode: %d)",
-"Fout bij verwijderen database (kan rmdir '%-.64s' niet uitvoeren, Errcode: %d)",
-"Fout bij het verwijderen van '%-.64s' (Errcode: %d)",
-"Kan record niet lezen in de systeem tabel",
-"Kan de status niet krijgen van '%-.64s' (Errcode: %d)",
-"Kan de werkdirectory niet krijgen (Errcode: %d)",
-"Kan de file niet blokeren (Errcode: %d)",
-"Kan de file '%-.64s' niet openen (Errcode: %d)",
-"Kan de file: '%-.64s' niet vinden (Errcode: %d)",
-"Kan de directory niet lezen van '%-.64s' (Errcode: %d)",
-"Kan de directory niet veranderen naar '%-.64s' (Errcode: %d)",
-"Record is veranderd sinds de laatste lees activiteit in de tabel '%-.64s'",
-"Schijf vol (%s). Aan het wachten totdat er ruimte vrij wordt gemaakt...",
-"Kan niet schrijven, dubbele zoeksleutel in tabel '%-.64s'",
-"Fout bij het sluiten van '%-.64s' (Errcode: %d)",
-"Fout bij het lezen van file '%-.64s' (Errcode: %d)",
-"Fout bij het hernoemen van '%-.64s' naar '%-.64s' (Errcode: %d)",
-"Fout bij het wegschrijven van file '%-.64s' (Errcode: %d)",
-"'%-.64s' is geblokeerd tegen veranderingen",
-"Sorteren afgebroken",
-"View '%-.64s' bestaat niet voor '%-.64s'",
-"Fout %d van tabel handler",
-"Tabel handler voor '%-.64s' heeft deze optie niet",
-"Kan record niet vinden in '%-.64s'",
-"Verkeerde info in file: '%-.64s'",
-"Verkeerde zoeksleutel file voor tabel: '%-.64s'; probeer het te repareren",
-"Oude zoeksleutel file voor tabel '%-.64s'; repareer het!",
-"'%-.64s' is alleen leesbaar",
-"Geen geheugen meer. Herstart server en probeer opnieuw (%d bytes nodig)",
-"Geen geheugen om te sorteren. Verhoog de server sort buffer size",
-"Onverwachte eof gevonden tijdens het lezen van file '%-.64s' (Errcode: %d)",
-"Te veel verbindingen",
-"Geen thread geheugen meer; controleer of mysqld of andere processen al het beschikbare geheugen gebruikt. Zo niet, dan moet u wellicht 'ulimit' gebruiken om mysqld toe te laten meer geheugen te benutten, of u kunt extra swap ruimte toevoegen",
-"Kan de hostname niet krijgen van uw adres",
-"Verkeerde handshake",
-"Toegang geweigerd voor gebruiker: '%-.32s'@'%-.64s' naar database '%-.64s'",
-"Toegang geweigerd voor gebruiker: '%-.32s'@'%-.64s' (Wachtwoord gebruikt: %s)",
-"Geen database geselecteerd",
-"Onbekend commando",
-"Kolom '%-.64s' kan niet null zijn",
-"Onbekende database '%-.64s'",
-"Tabel '%-.64s' bestaat al",
-"Onbekende tabel '%-.64s'",
-"Kolom: '%-.64s' in %s is niet eenduidig",
-"Bezig met het stoppen van de server",
-"Onbekende kolom '%-.64s' in %s",
-"Opdracht gebruikt '%-.64s' dat niet in de GROUP BY voorkomt",
-"Kan '%-.64s' niet groeperen",
-"Opdracht heeft totaliseer functies en kolommen in dezelfde opdracht",
-"Het aantal kolommen komt niet overeen met het aantal opgegeven waardes",
-"Naam voor herkenning '%-.64s' is te lang",
-"Dubbele kolom naam '%-.64s'",
-"Dubbele zoeksleutel naam '%-.64s'",
-"Dubbele ingang '%-.64s' voor zoeksleutel %d",
-"Verkeerde kolom specificatie voor kolom '%-.64s'",
-"%s bij '%-.64s' in regel %d",
-"Query was leeg",
-"Niet unieke waarde tabel/alias: '%-.64s'",
-"Foutieve standaard waarde voor '%-.64s'",
-"Meerdere primaire zoeksleutels gedefinieerd",
-"Teveel zoeksleutels gedefinieerd. Maximaal zijn %d zoeksleutels toegestaan",
-"Teveel zoeksleutel onderdelen gespecificeerd. Maximaal %d onderdelen toegestaan",
-"Gespecificeerde zoeksleutel was te lang. De maximale lengte is %d",
-"Zoeksleutel kolom '%-.64s' bestaat niet in tabel",
-"BLOB kolom '%-.64s' kan niet gebruikt worden bij zoeksleutel specificatie",
-"Te grote kolomlengte voor '%-.64s' (max = %d). Maak hiervoor gebruik van het type BLOB",
-"Er kan slechts 1 autofield zijn en deze moet als zoeksleutel worden gedefinieerd.",
-"%s: klaar voor verbindingen",
-"%s: Normaal afgesloten \n",
-"%s: Signaal %d. Systeem breekt af!\n",
-"%s: Afsluiten afgerond\n",
-"%s: Afsluiten afgedwongen van thread %ld gebruiker: '%-.64s'\n",
-"Kan IP-socket niet openen",
-"Tabel '%-.64s' heeft geen INDEX zoals deze gemaakt worden met CREATE INDEX. Maak de tabel opnieuw",
-"De argumenten om velden te scheiden zijn anders dan verwacht. Raadpleeg de handleiding",
-"Bij het gebruik van BLOBs is het niet mogelijk om vaste rijlengte te gebruiken. Maak s.v.p. gebruik van 'fields terminated by'.",
-"Het bestand '%-.64s' dient in de database directory voor the komen of leesbaar voor iedereen te zijn.",
-"Het bestand '%-.64s' bestaat reeds",
-"Records: %ld Verwijderd: %ld Overgeslagen: %ld Waarschuwingen: %ld",
-"Records: %ld Dubbel: %ld",
-"Foutief sub-gedeelte van de zoeksleutel. De gebruikte zoeksleutel is geen onderdeel van een string of of de gebruikte lengte is langer dan de zoeksleutel",
-"Het is niet mogelijk alle velden te verwijderen met ALTER TABLE. Gebruik a.u.b. DROP TABLE hiervoor!",
-"Kan '%-.64s' niet weggooien. Controleer of het veld of de zoeksleutel daadwerkelijk bestaat.",
-"Records: %ld Dubbel: %ld Waarschuwing: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Onbekend thread id: %lu",
-"U bent geen bezitter van thread %lu",
-"Geen tabellen gebruikt.",
-"Teveel strings voor kolom %s en SET",
-"Het is niet mogelijk een unieke naam te maken voor de logfile %s.(1-999)\n",
-"Tabel '%-.64s' was gelocked met een lock om te lezen. Derhalve kunnen geen wijzigingen worden opgeslagen.",
-"Tabel '%-.64s' was niet gelocked met LOCK TABLES",
-"Blob veld '%-.64s' can geen standaardwaarde bevatten",
-"Databasenaam '%-.64s' is niet getoegestaan",
-"Niet toegestane tabelnaam '%-.64s'",
-"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET SQL_BIG_SELECTS=1 als het stament in orde is.",
-"Onbekende Fout",
-"Onbekende procedure %s",
-"Foutief aantal parameters doorgegeven aan procedure %s",
-"Foutieve parameters voor procedure %s",
-"Onbekende tabel '%-.64s' in %s",
-"Veld '%-.64s' is dubbel gespecificeerd",
-"Ongeldig gebruik van GROUP-functie",
-"Tabel '%-.64s' gebruikt een extensie, die niet in deze MySQL-versie voorkomt.",
-"Een tabel moet minstens 1 kolom bevatten",
-"De tabel '%-.64s' is vol",
-"Onbekende character set: '%-.64s'",
-"Teveel tabellen. MySQL kan slechts %d tabellen in een join bevatten",
-"Te veel velden",
-"Rij-grootte is groter dan toegestaan. Maximale rij grootte, blobs niet meegeteld, is %d. U dient sommige velden in blobs te veranderen.",
-"Thread stapel overrun: Gebruikte: %ld van een %ld stack. Gebruik 'mysqld -O thread_stack=#' om een grotere stapel te definieren (indien noodzakelijk).",
-"Gekruiste afhankelijkheid gevonden in OUTER JOIN. Controleer uw ON-conditions",
-"Kolom '%-.64s' wordt gebruikt met UNIQUE of INDEX maar is niet gedefinieerd als NOT NULL",
-"Kan functie '%-.64s' niet laden",
-"Kan functie '%-.64s' niet initialiseren; %-.80s",
-"Geen pad toegestaan voor shared library",
-"Functie '%-.64s' bestaat reeds",
-"Kan shared library '%-.64s' niet openen (Errcode: %d %s)",
-"Kan functie '%-.64s' niet in library vinden",
-"Functie '%-.64s' is niet gedefinieerd",
-"Host '%-.64s' is geblokkeeerd vanwege te veel verbindings fouten. Deblokkeer met 'mysqladmin flush-hosts'",
-"Het is host '%-.64s' is niet toegestaan verbinding te maken met deze MySQL server",
-"U gebruikt MySQL als anonieme gebruiker en deze mogen geen wachtwoorden wijzigen",
-"U moet tabel update priveleges hebben in de mysql database om wachtwoorden voor anderen te mogen wijzigen",
-"Kan geen enkele passende rij vinden in de gebruikers tabel",
-"Passende rijen: %ld Gewijzigd: %ld Waarschuwingen: %ld",
-"Kan geen nieuwe thread aanmaken (Errcode: %d). Indien er geen tekort aan geheugen is kunt u de handleiding consulteren over een mogelijke OS afhankelijke fout",
-"Kolom aantal komt niet overeen met waarde aantal in rij %ld",
-"Kan tabel niet opnieuw openen: '%-.64s",
-"Foutief gebruik van de NULL waarde",
-"Fout '%-.64s' ontvangen van regexp",
-"Het mixen van GROUP kolommen (MIN(),MAX(),COUNT()...) met no-GROUP kolommen is foutief indien er geen GROUP BY clausule is",
-"Deze toegang (GRANT) is niet toegekend voor gebruiker '%-.32s' op host '%-.64s'",
-"%-.16s commando geweigerd voor gebruiker: '%-.32s'@'%-.64s' voor tabel '%-.64s'",
-"%-.16s commando geweigerd voor gebruiker: '%-.32s'@'%-.64s' voor kolom '%-.64s' in tabel '%-.64s'",
-"Foutief GRANT/REVOKE commando. Raadpleeg de handleiding welke priveleges gebruikt kunnen worden.",
-"De host of gebruiker parameter voor GRANT is te lang",
-"Tabel '%-.64s.%s' bestaat niet",
-"Deze toegang (GRANT) is niet toegekend voor gebruiker '%-.32s' op host '%-.64s' op tabel '%-.64s'",
-"Het used commando is niet toegestaan in deze MySQL versie",
-"Er is iets fout in de gebruikte syntax",
-"'Delayed insert' thread kon de aangevraagde 'lock' niet krijgen voor tabel %-.64s",
-"Te veel 'delayed' threads in gebruik",
-"Afgebroken verbinding %ld naar db: '%-.64s' gebruiker: '%-.64s' (%s)",
-"Groter pakket ontvangen dan 'max_allowed_packet'",
-"Kreeg leesfout van de verbindings pipe",
-"Kreeg fout van fcntl()",
-"Pakketten in verkeerde volgorde ontvangen",
-"Communicatiepakket kon niet worden gedecomprimeerd",
-"Fout bij het lezen van communicatiepakketten",
-"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'",
-"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",
-"Incorrecte kolom naam '%-.100s'",
-"De gebruikte tabel 'handler' kan kolom '%-.64s' niet indexeren",
-"Niet alle tabellen in de MERGE tabel hebben identieke gedefinities",
-"Kan niet opslaan naar table '%-.64s' vanwege 'unique' beperking",
-"BLOB kolom '%-.64s' gebruikt in zoeksleutel specificatie zonder zoeksleutel lengte",
-"Alle delen van een PRIMARY KEY moeten NOT NULL zijn; Indien u NULL in een zoeksleutel nodig heeft kunt u UNIQUE gebruiken",
-"Resultaat bevatte meer dan een rij",
-"Dit tabel type heeft een primaire zoeksleutel nodig",
-"Deze versie van MySQL is niet gecompileerd met RAID ondersteuning",
-"U gebruikt 'safe update mode' en u probeerde een tabel te updaten zonder een WHERE met een KEY kolom",
-"Zoeksleutel '%-.64s' bestaat niet in tabel '%-.64s'",
-"Kan tabel niet openen",
-"De 'handler' voor de tabel ondersteund geen %s",
-"Het is u niet toegestaan dit commando uit te voeren binnen een transactie",
-"Kreeg fout %d tijdens COMMIT",
-"Kreeg fout %d tijdens ROLLBACK",
-"Kreeg fout %d tijdens FLUSH_LOGS",
-"Kreeg fout %d tijdens CHECKPOINT",
-"Afgebroken verbinding %ld naar db: '%-.64s' gebruiker: '%-.32s' host: `%-.64s' (%-.64s)",
-"De 'handler' voor de tabel ondersteund geen binaire tabel dump",
-"Binlog gesloten tijdens FLUSH MASTER poging",
-"Gefaald tijdens heropbouw index van gedumpte tabel '%-.64s'",
-"Fout van master: '%-.64s'",
-"Net fout tijdens lezen van master",
-"Net fout tijdens schrijven naar master",
-"Kan geen FULLTEXT index vinden passend bij de kolom lijst",
-"Kan het gegeven commando niet uitvoeren, want u heeft actieve gelockte tabellen of een actieve transactie",
-"Onbekende systeem variabele '%-.64s'",
-"Tabel '%-.64s' staat als gecrashed gemarkeerd en dient te worden gerepareerd",
-"Tabel '%-.64s' staat als gecrashed gemarkeerd en de laatste (automatische?) reparatie poging mislukte",
-"Waarschuwing: Roll back mislukt voor sommige buiten transacties gewijzigde tabellen",
-"Multi-statement transactie vereist meer dan 'max_binlog_cache_size' bytes opslag. Verhoog deze mysqld variabele en probeer opnieuw",
-"Deze operatie kan niet worden uitgevoerd met een actieve slave, doe eerst STOP SLAVE",
-"Deze operatie vereist een actieve slave, configureer slave en doe dan START SLAVE",
-"De server is niet geconfigureerd als slave, fix in configuratie bestand of met CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Kon slave thread niet aanmaken, controleer systeem resources",
-"Gebruiker %-.64s heeft reeds meer dan 'max_user_connections' actieve verbindingen",
-"U mag alleen constante expressies gebruiken bij SET",
-"Lock wacht tijd overschreden",
-"Het totale aantal locks overschrijdt de lock tabel grootte",
-"Update locks kunnen niet worden verkregen tijdens een READ UNCOMMITTED transactie",
-"DROP DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit",
-"CREATE DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit",
-"Foutieve parameters voor %s",
-"'%-.32s'@'%-.64s' mag geen nieuwe gebruikers creeren",
-"Incorrecte tabel definitie; alle MERGE tabellen moeten tot dezelfde database behoren",
-"Deadlock gevonden tijdens lock-aanvraag poging; Probeer herstart van de transactie",
-"Het gebruikte tabel type ondersteund geen FULLTEXT indexen",
-"Kan foreign key beperking niet toevoegen",
-"Kan onderliggende rij niet toevoegen: foreign key beperking gefaald",
-"Kan bovenliggende rij nite verwijderen: foreign key beperking gefaald",
-"Fout bij opbouwen verbinding naar master: %-.128s",
-"Fout bij uitvoeren query op master: %-.128s",
-"Fout tijdens uitvoeren van commando %s: %-.128s",
-"Foutief gebruik van %s en %s",
-"De gebruikte SELECT commando's hebben een verschillend aantal kolommen",
-"Kan de query niet uitvoeren vanwege een conflicterende read lock",
-"Het combineren van transactionele en niet-transactionele tabellen is uitgeschakeld.",
-"Optie '%s' tweemaal gebruikt in opdracht",
-"Gebruiker '%-.64s' heeft het maximale gebruik van de '%s' faciliteit overschreden (huidige waarde: %ld)",
-"Toegang geweigerd. U moet het %-.128s privilege hebben voor deze operatie",
-"Variabele '%-.64s' is SESSION en kan niet worden gebruikt met SET GLOBAL",
-"Variabele '%-.64s' is GLOBAL en dient te worden gewijzigd met SET GLOBAL",
-"Variabele '%-.64s' heeft geen standaard waarde",
-"Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.64s'",
-"Foutief argumenttype voor variabele '%-.64s'",
-"Variabele '%-.64s' kan alleen worden gewijzigd, niet gelezen",
-"Foutieve toepassing/plaatsing van '%s'",
-"Deze versie van MySQL ondersteunt nog geen '%s'",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
deleted file mode 100644
index 763c984866b..00000000000
--- a/sql/share/english/errmsg.txt
+++ /dev/null
@@ -1,322 +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 */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NO",
-"YES",
-"Can't create file '%-.64s' (errno: %d)",
-"Can't create table '%-.64s' (errno: %d)",
-"Can't create database '%-.64s' (errno: %d)",
-"Can't create database '%-.64s'; database exists",
-"Can't drop database '%-.64s'; database doesn't exist",
-"Error dropping database (can't delete '%-.64s', errno: %d)",
-"Error dropping database (can't rmdir '%-.64s', errno: %d)",
-"Error on delete of '%-.64s' (errno: %d)",
-"Can't read record in system table",
-"Can't get status of '%-.64s' (errno: %d)",
-"Can't get working directory (errno: %d)",
-"Can't lock file (errno: %d)",
-"Can't open file: '%-.64s' (errno: %d)",
-"Can't find file: '%-.64s' (errno: %d)",
-"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'",
-"Error on close of '%-.64s' (errno: %d)",
-"Error reading file '%-.64s' (errno: %d)",
-"Error on rename of '%-.64s' to '%-.64s' (errno: %d)",
-"Error writing file '%-.64s' (errno: %d)",
-"'%-.64s' is locked against change",
-"Sort aborted",
-"View '%-.64s' doesn't exist for '%-.64s'",
-"Got error %d from storage engine",
-"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",
-"Old key file for table '%-.64s'; repair it!",
-"Table '%-.64s' is read only",
-"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",
-"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",
-"Unknown command",
-"Column '%-.64s' cannot be null",
-"Unknown database '%-.64s'",
-"Table '%-.64s' already exists",
-"Unknown table '%-.100s'",
-"Column '%-.64s' in %-.64s is ambiguous",
-"Server shutdown in progress",
-"Unknown column '%-.64s' in '%-.64s'",
-"'%-.64s' isn't in GROUP BY",
-"Can't group on '%-.64s'",
-"Statement has sum functions and columns in same statement",
-"Column count doesn't match value count",
-"Identifier name '%-.100s' is too long",
-"Duplicate column name '%-.64s'",
-"Duplicate key name '%-.64s'",
-"Duplicate entry '%-.64s' for key %d",
-"Incorrect column specifier for column '%-.64s'",
-"%s near '%-.80s' at line %d",
-"Query was empty",
-"Not unique table/alias: '%-.64s'",
-"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",
-"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",
-"Column length too big for column '%-.64s' (max = %d); use BLOB or TEXT 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",
-"%s: Normal shutdown\n",
-"%s: Got signal %d. Aborting!\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'",
-"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",
-"Records: %ld Duplicates: %ld Warnings: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Unknown thread id: %lu",
-"You are not owner of thread %lu",
-"No tables used",
-"Too many strings for column %-.64s and SET",
-"Can't generate a unique log-filename %-.64s.(1-999)\n",
-"Table '%-.64s' was locked with a READ lock and can't be updated",
-"Table '%-.64s' was not locked with LOCK TABLES",
-"BLOB/TEXT column '%-.64s' can't have a default value",
-"Incorrect database name '%-.100s'",
-"Incorrect table name '%-.100s'",
-"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'",
-"Incorrect parameters to procedure '%-.64s'",
-"Unknown table '%-.64s' in %-.32s",
-"Column '%-.64s' specified twice",
-"Invalid use of group function",
-"Table '%-.64s' uses an extension that doesn't exist in this MySQL version",
-"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 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",
-"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 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 not allowed to connect to this MySQL server",
-"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",
-"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",
-"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 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",
-"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' bytes",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Couldn't uncompress communication packet",
-"Got an error reading communication packets",
-"Got timeout reading communication packets",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
-"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",
-"Incorrect column name '%-.100s'",
-"The used storage engine can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The storage engine for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"Got error %d during FLUSH_LOGS",
-"Got error %d during CHECKPOINT",
-"Aborted connection %ld to db: '%-.64s' user: '%-.32s' host: `%-.64s' (%-.64s)",
-"The storage engine for the table does not support binary table dump",
-"Binlog closed, cannot RESET MASTER",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"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",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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",
-"Column '%-.64s' cannot be part of FULLTEXT index",
-"Unknown key cache '%-.100s'",
-"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",
-"The target table %-.100s of the %s is not updatable",
-"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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
new file mode 100644
index 00000000000..09589c98dce
--- /dev/null
+++ b/sql/share/errmsg.txt
@@ -0,0 +1,5417 @@
+languages czech=cze latin2, danish=dan latin1, dutch=nla latin1, english=eng latin1, estonian=est latin7, french=fre latin1, german=ger latin1, greek=greek greek, hungarian=hun latin2, italian=ita latin1, japanese=jpn ujis, japanese-sjis=jps sjis, korean=kor euckr, norwegian-ny=norwegian-ny latin1, norwegian=nor latin1, polish=pol latin2, portuguese=por latin1, romanian=rum latin2, russian=rus koi8r, serbian=serbian cp1250, slovak=slo latin2, spanish=spa latin1, swedish=swe latin1, ukrainian=ukr koi8u;
+
+default-language eng
+
+start-error-number 1000
+
+ER_HASHCHK
+ eng "hashchk"
+ER_NISAMCHK
+ eng "isamchk"
+ER_NO
+ cze "NE"
+ dan "NEJ"
+ nla "NEE"
+ eng "NO"
+ est "EI"
+ fre "NON"
+ ger "Nein"
+ greek "Ï×É"
+ hun "NEM"
+ kor "¾Æ´Ï¿À"
+ nor "NEI"
+ norwegian-ny "NEI"
+ pol "NIE"
+ por "NÃO"
+ rum "NU"
+ rus "îåô"
+ serbian "NE"
+ slo "NIE"
+ ukr "î¶"
+ER_YES
+ cze "ANO"
+ dan "JA"
+ nla "JA"
+ eng "YES"
+ est "JAH"
+ fre "OUI"
+ ger "Ja"
+ greek "ÍÁÉ"
+ hun "IGEN"
+ ita "SI"
+ kor "¿¹"
+ nor "JA"
+ norwegian-ny "JA"
+ pol "TAK"
+ por "SIM"
+ rum "DA"
+ rus "äá"
+ serbian "DA"
+ slo "Áno"
+ spa "SI"
+ ukr "ôáë"
+ER_CANT_CREATE_FILE
+ cze "Nemohu vytvo-Bøit soubor '%-.64s' (chybový kód: %d)"
+ dan "Kan ikke oprette filen '%-.64s' (Fejlkode: %d)"
+ nla "Kan file '%-.64s' niet aanmaken (Errcode: %d)"
+ eng "Can't create file '%-.64s' (errno: %d)"
+ est "Ei suuda luua faili '%-.64s' (veakood: %d)"
+ fre "Ne peut créer le fichier '%-.64s' (Errcode: %d)"
+ ger "Kann Datei '%-.64s' nicht erzeugen (Fehler: %d)"
+ greek "Áäýíáôç ç äçìéïõñãßá ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "A '%-.64s' file nem hozhato letre (hibakod: %d)"
+ ita "Impossibile creare il file '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Õ¥¡¥¤¥ë¤¬ºî¤ì¤Þ¤»¤ó (errno: %d)"
+ kor "È­ÀÏ '%-.64s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke opprette fila '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Kan ikkje opprette fila '%-.64s' (Feilkode: %d)"
+ pol "Nie mo¿na stworzyæ pliku '%-.64s' (Kod b³êdu: %d)"
+ por "Não pode criar o arquivo '%-.64s' (erro no. %d)"
+ rum "Nu pot sa creez fisierul '%-.64s' (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÆÁÊÌ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da kreiram file '%-.64s' (errno: %d)"
+ slo "Nemô¾em vytvori» súbor '%-.64s' (chybový kód: %d)"
+ spa "No puedo crear archivo '%-.64s' (Error: %d)"
+ swe "Kan inte skapa filen '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÆÁÊÌ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_CANT_CREATE_TABLE
+ cze "Nemohu vytvo-Bøit tabulku '%-.64s' (chybový kód: %d)"
+ dan "Kan ikke oprette tabellen '%-.64s' (Fejlkode: %d)"
+ nla "Kan tabel '%-.64s' niet aanmaken (Errcode: %d)"
+ eng "Can't create table '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒe[ƒuƒ‹‚ªì‚ê‚Ü‚¹‚ñ.(errno: %d)",
+ est "Ei suuda luua tabelit '%-.64s' (veakood: %d)"
+ fre "Ne peut créer la table '%-.64s' (Errcode: %d)"
+ ger "Kann Tabelle '%-.64s' nicht erzeugen (Fehler: %d)"
+ greek "Áäýíáôç ç äçìéïõñãßá ôïõ ðßíáêá '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "A '%-.64s' tabla nem hozhato letre (hibakod: %d)"
+ ita "Impossibile creare la tabella '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Æ¡¼¥Ö¥ë¤¬ºî¤ì¤Þ¤»¤ó.(errno: %d)"
+ kor "Å×À̺í '%-.64s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke opprette tabellen '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Kan ikkje opprette tabellen '%-.64s' (Feilkode: %d)"
+ pol "Nie mo¿na stworzyæ tabeli '%-.64s' (Kod b³êdu: %d)"
+ por "Não pode criar a tabela '%-.64s' (erro no. %d)"
+ rum "Nu pot sa creez tabla '%-.64s' (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÔÁÂÌÉÃÕ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da kreiram tabelu '%-.64s' (errno: %d)"
+ slo "Nemô¾em vytvori» tabuµku '%-.64s' (chybový kód: %d)"
+ spa "No puedo crear tabla '%-.64s' (Error: %d)"
+ swe "Kan inte skapa tabellen '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÔÁÂÌÉÃÀ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_CANT_CREATE_DB
+ cze "Nemohu vytvo-Bøit databázi '%-.64s' (chybový kód: %d)"
+ dan "Kan ikke oprette databasen '%-.64s' (Fejlkode: %d)"
+ nla "Kan database '%-.64s' niet aanmaken (Errcode: %d)"
+ eng "Can't create database '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒf[ƒ^ƒx[ƒX‚ªì‚ê‚Ü‚¹‚ñ (errno: %d)",
+ est "Ei suuda luua andmebaasi '%-.64s' (veakood: %d)"
+ fre "Ne peut créer la base '%-.64s' (Erreur %d)"
+ ger "Kann Datenbank '%-.64s' nicht erzeugen (Fehler: %d)"
+ greek "Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "Az '%-.64s' adatbazis nem hozhato letre (hibakod: %d)"
+ ita "Impossibile creare il database '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ºî¤ì¤Þ¤»¤ó (errno: %d)"
+ kor "µ¥ÀÌŸº£À̽º '%-.64s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù.. (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke opprette databasen '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Kan ikkje opprette databasen '%-.64s' (Feilkode: %d)"
+ pol "Nie mo¿na stworzyæ bazy danych '%-.64s' (Kod b³êdu: %d)"
+ por "Não pode criar o banco de dados '%-.64s' (erro no. %d)"
+ rum "Nu pot sa creez baza de date '%-.64s' (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da kreiram bazu '%-.64s' (errno: %d)"
+ slo "Nemô¾em vytvori» databázu '%-.64s' (chybový kód: %d)"
+ spa "No puedo crear base de datos '%-.64s' (Error: %d)"
+ swe "Kan inte skapa databasen '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_DB_CREATE_EXISTS
+ cze "Nemohu vytvo-Bøit databázi '%-.64s'; databáze ji¾ existuje"
+ dan "Kan ikke oprette databasen '%-.64s'; databasen eksisterer"
+ nla "Kan database '%-.64s' niet aanmaken; database bestaat reeds"
+ eng "Can't create database '%-.64s'; database exists"
+ jps "'%-.64s' ƒf[ƒ^ƒx[ƒX‚ªì‚ê‚Ü‚¹‚ñ.Šù‚É‚»‚̃f[ƒ^ƒx[ƒX‚ª‘¶Ý‚µ‚Ü‚·",
+ est "Ei suuda luua andmebaasi '%-.64s': andmebaas juba eksisteerib"
+ fre "Ne peut créer la base '%-.64s'; elle existe déjà"
+ ger "Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits"
+ greek "Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s'; Ç âÜóç äåäïìÝíùí õðÜñ÷åé Þäç"
+ hun "Az '%-.64s' adatbazis nem hozhato letre Az adatbazis mar letezik"
+ ita "Impossibile creare il database '%-.64s'; il database esiste"
+ jpn "'%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ºî¤ì¤Þ¤»¤ó.´û¤Ë¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬Â¸ºß¤·¤Þ¤¹"
+ kor "µ¥ÀÌŸº£À̽º '%-.64s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù.. µ¥ÀÌŸº£À̽º°¡ Á¸ÀçÇÔ"
+ nor "Kan ikke opprette databasen '%-.64s'; databasen eksisterer"
+ norwegian-ny "Kan ikkje opprette databasen '%-.64s'; databasen eksisterer"
+ pol "Nie mo¿na stworzyæ bazy danych '%-.64s'; baza danych ju¿ istnieje"
+ por "Não pode criar o banco de dados '%-.64s'; este banco de dados já existe"
+ rum "Nu pot sa creez baza de date '%-.64s'; baza de date exista deja"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s'. âÁÚÁ ÄÁÎÎÙÈ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ"
+ serbian "Ne mogu da kreiram bazu '%-.64s'; baza veæ postoji."
+ slo "Nemô¾em vytvori» databázu '%-.64s'; databáza existuje"
+ spa "No puedo crear base de datos '%-.64s'; la base de datos ya existe"
+ swe "Databasen '%-.64s' existerar redan"
+ ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s'. âÁÚÁ ÄÁÎÎÉÈ ¦ÓÎÕ¤"
+ER_DB_DROP_EXISTS
+ cze "Nemohu zru-B¹it databázi '%-.64s', databáze neexistuje"
+ dan "Kan ikke slette (droppe) '%-.64s'; databasen eksisterer ikke"
+ nla "Kan database '%-.64s' niet verwijderen; database bestaat niet"
+ eng "Can't drop database '%-.64s'; database doesn't exist"
+ jps "'%-.64s' ƒf[ƒ^ƒx[ƒX‚ð”jŠü‚Å‚«‚Ü‚¹‚ñ. ‚»‚̃f[ƒ^ƒx[ƒX‚ª‚È‚¢‚Ì‚Å‚·.",
+ est "Ei suuda kustutada andmebaasi '%-.64s': andmebaasi ei eksisteeri"
+ fre "Ne peut effacer la base '%-.64s'; elle n'existe pas"
+ ger "Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden"
+ greek "Áäýíáôç ç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí '%-.64s'. Ç âÜóç äåäïìÝíùí äåí õðÜñ÷åé"
+ hun "A(z) '%-.64s' adatbazis nem szuntetheto meg. Az adatbazis nem letezik"
+ ita "Impossibile cancellare '%-.64s'; il database non esiste"
+ jpn "'%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÇË´þ¤Ç¤­¤Þ¤»¤ó. ¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬¤Ê¤¤¤Î¤Ç¤¹."
+ kor "µ¥ÀÌŸº£À̽º '%-.64s'¸¦ Á¦°ÅÇÏÁö ¸øÇß½À´Ï´Ù. µ¥ÀÌŸº£À̽º°¡ Á¸ÀçÇÏÁö ¾ÊÀ½ "
+ nor "Kan ikke fjerne (drop) '%-.64s'; databasen eksisterer ikke"
+ norwegian-ny "Kan ikkje fjerne (drop) '%-.64s'; databasen eksisterer ikkje"
+ pol "Nie mo¿na usun?æ bazy danych '%-.64s'; baza danych nie istnieje"
+ por "Não pode eliminar o banco de dados '%-.64s'; este banco de dados não existe"
+ rum "Nu pot sa drop baza de date '%-.64s'; baza da date este inexistenta"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s'. ôÁËÏÊ ÂÁÚÙ ÄÁÎÎÙÈ ÎÅÔ"
+ serbian "Ne mogu da izbrišem bazu '%-.64s'; baza ne postoji."
+ slo "Nemô¾em zmaza» databázu '%-.64s'; databáza neexistuje"
+ spa "No puedo eliminar base de datos '%-.64s'; la base de datos no existe"
+ swe "Kan inte radera databasen '%-.64s'; databasen finns inte"
+ ukr "îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s'. âÁÚÁ ÄÁÎÎÉÈ ÎÅ ¦ÓÎÕ¤"
+ER_DB_DROP_DELETE
+ cze "Chyba p-Bøi ru¹ení databáze (nemohu vymazat '%-.64s', chyba %d)"
+ dan "Fejl ved sletning (drop) af databasen (kan ikke slette '%-.64s', Fejlkode %d)"
+ nla "Fout bij verwijderen database (kan '%-.64s' niet verwijderen, Errcode: %d)"
+ eng "Error dropping database (can't delete '%-.64s', errno: %d)"
+ jps "ƒf[ƒ^ƒx[ƒX”jŠüƒGƒ‰[ ('%-.64s' ‚ð휂ł«‚Ü‚¹‚ñ, errno: %d)",
+ est "Viga andmebaasi kustutamisel (ei suuda kustutada faili '%-.64s', veakood: %d)"
+ fre "Ne peut effacer la base '%-.64s' (erreur %d)"
+ ger "Fehler beim Löschen der Datenbank ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)"
+ greek "ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ '%-.64s', êùäéêüò ëÜèïõò: %d)"
+ hun "Adatbazis megszuntetesi hiba ('%-.64s' nem torolheto, hibakod: %d)"
+ ita "Errore durante la cancellazione del database (impossibile cancellare '%-.64s', errno: %d)"
+ jpn "¥Ç¡¼¥¿¥Ù¡¼¥¹ÇË´þ¥¨¥é¡¼ ('%-.64s' ¤òºï½ü¤Ç¤­¤Þ¤»¤ó, errno: %d)"
+ kor "µ¥ÀÌŸº£À̽º Á¦°Å ¿¡·¯('%-.64s'¸¦ »èÁ¦ÇÒ ¼ö ¾øÀ¾´Ï´Ù, ¿¡·¯¹øÈ£: %d)"
+ nor "Feil ved fjerning (drop) av databasen (kan ikke slette '%-.64s', feil %d)"
+ norwegian-ny "Feil ved fjerning (drop) av databasen (kan ikkje slette '%-.64s', feil %d)"
+ pol "B³?d podczas usuwania bazy danych (nie mo¿na usun?æ '%-.64s', b³?d %d)"
+ por "Erro ao eliminar banco de dados (não pode eliminar '%-.64s' - erro no. %d)"
+ rum "Eroare dropuind baza de date (nu pot sa sterg '%-.64s', Eroare: %d)"
+ rus "ïÛÉÂËÁ ÐÒÉ ÕÄÁÌÅÎÉÉ ÂÁÚÙ ÄÁÎÎÙÈ (ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ '%-.64s', ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da izbrišem bazu (ne mogu da izbrišem '%-.64s', errno: %d)"
+ slo "Chyba pri mazaní databázy (nemô¾em zmaza» '%-.64s', chybový kód: %d)"
+ spa "Error eliminando la base de datos(no puedo borrar '%-.64s', error %d)"
+ swe "Fel vid radering av databasen (Kan inte radera '%-.64s'. Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ (îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ '%-.64s', ÐÏÍÉÌËÁ: %d)"
+ER_DB_DROP_RMDIR
+ cze "Chyba p-Bøi ru¹ení databáze (nemohu vymazat adresáø '%-.64s', chyba %d)"
+ dan "Fejl ved sletting af database (kan ikke slette folderen '%-.64s', Fejlkode %d)"
+ nla "Fout bij verwijderen database (kan rmdir '%-.64s' niet uitvoeren, Errcode: %d)"
+ eng "Error dropping database (can't rmdir '%-.64s', errno: %d)"
+ jps "ƒf[ƒ^ƒx[ƒX”jŠüƒGƒ‰[ ('%-.64s' ‚ð rmdir ‚Å‚«‚Ü‚¹‚ñ, errno: %d)",
+ est "Viga andmebaasi kustutamisel (ei suuda kustutada kataloogi '%-.64s', veakood: %d)"
+ fre "Erreur en effaçant la base (rmdir '%-.64s', erreur %d)"
+ ger "Fehler beim Löschen der Datenbank (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)"
+ greek "ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ ôïõ öáêÝëëïõ '%-.64s', êùäéêüò ëÜèïõò: %d)"
+ hun "Adatbazis megszuntetesi hiba ('%-.64s' nem szuntetheto meg, hibakod: %d)"
+ ita "Errore durante la cancellazione del database (impossibile rmdir '%-.64s', errno: %d)"
+ jpn "¥Ç¡¼¥¿¥Ù¡¼¥¹ÇË´þ¥¨¥é¡¼ ('%-.64s' ¤ò rmdir ¤Ç¤­¤Þ¤»¤ó, errno: %d)"
+ kor "µ¥ÀÌŸº£À̽º Á¦°Å ¿¡·¯(rmdir '%-.64s'¸¦ ÇÒ ¼ö ¾øÀ¾´Ï´Ù, ¿¡·¯¹øÈ£: %d)"
+ nor "Feil ved sletting av database (kan ikke slette katalogen '%-.64s', feil %d)"
+ norwegian-ny "Feil ved sletting av database (kan ikkje slette katalogen '%-.64s', feil %d)"
+ pol "B³?d podczas usuwania bazy danych (nie mo¿na wykonaæ rmdir '%-.64s', b³?d %d)"
+ por "Erro ao eliminar banco de dados (não pode remover diretório '%-.64s' - erro no. %d)"
+ rum "Eroare dropuind baza de date (nu pot sa rmdir '%-.64s', Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ (ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ËÁÔÁÌÏÇ '%-.64s', ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da izbrišem bazu (ne mogu da izbrišem direktorijum '%-.64s', errno: %d)"
+ slo "Chyba pri mazaní databázy (nemô¾em vymaza» adresár '%-.64s', chybový kód: %d)"
+ spa "Error eliminando la base de datos (No puedo borrar directorio '%-.64s', error %d)"
+ swe "Fel vid radering av databasen (Kan inte radera biblioteket '%-.64s'. Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ (îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÔÅËÕ '%-.64s', ÐÏÍÉÌËÁ: %d)"
+ER_CANT_DELETE_FILE
+ cze "Chyba p-Bøi výmazu '%-.64s' (chybový kód: %d)"
+ dan "Fejl ved sletning af '%-.64s' (Fejlkode: %d)"
+ nla "Fout bij het verwijderen van '%-.64s' (Errcode: %d)"
+ eng "Error on delete of '%-.64s' (errno: %d)"
+ jps "'%-.64s' ‚Ì휂ªƒGƒ‰[ (errno: %d)",
+ est "Viga '%-.64s' kustutamisel (veakood: %d)"
+ fre "Erreur en effaçant '%-.64s' (Errcode: %d)"
+ ger "Fehler beim Löschen von '%-.64s' (Fehler: %d)"
+ greek "ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "Torlesi hiba: '%-.64s' (hibakod: %d)"
+ ita "Errore durante la cancellazione di '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¤Îºï½ü¤¬¥¨¥é¡¼ (errno: %d)"
+ kor "'%-.64s' »èÁ¦ Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)"
+ nor "Feil ved sletting av '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Feil ved sletting av '%-.64s' (Feilkode: %d)"
+ pol "B³?d podczas usuwania '%-.64s' (Kod b³êdu: %d)"
+ por "Erro na remoção de '%-.64s' (erro no. %d)"
+ rum "Eroare incercind sa delete '%-.64s' (Eroare: %d)"
+ rus "ïÛÉÂËÁ ÐÒÉ ÕÄÁÌÅÎÉÉ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Greška pri brisanju '%-.64s' (errno: %d)"
+ slo "Chyba pri mazaní '%-.64s' (chybový kód: %d)"
+ spa "Error en el borrado de '%-.64s' (Error: %d)"
+ swe "Kan inte radera filen '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_CANT_FIND_SYSTEM_REC
+ cze "Nemohu -Bèíst záznam v systémové tabulce"
+ dan "Kan ikke læse posten i systemfolderen"
+ nla "Kan record niet lezen in de systeem tabel"
+ eng "Can't read record in system table"
+ jps "system table ‚̃ŒƒR[ƒh‚ð“Ç‚ÞŽ–‚ª‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½",
+ est "Ei suuda lugeda kirjet süsteemsest tabelist"
+ fre "Ne peut lire un enregistrement de la table 'system'"
+ ger "Datensatz in der Systemtabelle nicht lesbar"
+ greek "Áäýíáôç ç áíÜãíùóç åããñáöÞò áðü ðßíáêá ôïõ óõóôÞìáôïò"
+ hun "Nem olvashato rekord a rendszertablaban"
+ ita "Impossibile leggere il record dalla tabella di sistema"
+ jpn "system table ¤Î¥ì¥³¡¼¥É¤òÆɤà»ö¤¬¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿"
+ kor "system Å×ÀÌºí¿¡¼­ ·¹Äڵ带 ÀÐÀ» ¼ö ¾ø½À´Ï´Ù."
+ nor "Kan ikke lese posten i systemkatalogen"
+ norwegian-ny "Kan ikkje lese posten i systemkatalogen"
+ pol "Nie mo¿na odczytaæ rekordu z tabeli systemowej"
+ por "Não pode ler um registro numa tabela do sistema"
+ rum "Nu pot sa citesc cimpurile in tabla de system (system table)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÚÁÐÉÓØ × ÓÉÓÔÅÍÎÏÊ ÔÁÂÌÉÃÅ"
+ serbian "Ne mogu da proèitam slog iz sistemske tabele"
+ slo "Nemô¾em èíta» záznam v systémovej tabuµke"
+ spa "No puedo leer el registro en la tabla del sistema"
+ swe "Hittar inte posten i systemregistret"
+ ukr "îÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ÚÁÐÉÓ Ú ÓÉÓÔÅÍÎϧ ÔÁÂÌÉæ"
+ER_CANT_GET_STAT
+ cze "Nemohu z-Bískat stav '%-.64s' (chybový kód: %d)"
+ dan "Kan ikke læse status af '%-.64s' (Fejlkode: %d)"
+ nla "Kan de status niet krijgen van '%-.64s' (Errcode: %d)"
+ eng "Can't get status of '%-.64s' (errno: %d)"
+ jps "'%-.64s' ‚̃XƒeƒCƒ^ƒX‚ª“¾‚ç‚ê‚Ü‚¹‚ñ. (errno: %d)",
+ est "Ei suuda lugeda '%-.64s' olekut (veakood: %d)"
+ fre "Ne peut obtenir le status de '%-.64s' (Errcode: %d)"
+ ger "Kann Status von '%-.64s' nicht ermitteln (Fehler: %d)"
+ greek "Áäýíáôç ç ëÞøç ðëçñïöïñéþí ãéá ôçí êáôÜóôáóç ôïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "A(z) '%-.64s' statusza nem allapithato meg (hibakod: %d)"
+ ita "Impossibile leggere lo stato di '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¤Î¥¹¥Æ¥¤¥¿¥¹¤¬ÆÀ¤é¤ì¤Þ¤»¤ó. (errno: %d)"
+ kor "'%-.64s'ÀÇ »óŸ¦ ¾òÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke lese statusen til '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Kan ikkje lese statusen til '%-.64s' (Feilkode: %d)"
+ pol "Nie mo¿na otrzymaæ statusu '%-.64s' (Kod b³êdu: %d)"
+ por "Não pode obter o status de '%-.64s' (erro no. %d)"
+ rum "Nu pot sa obtin statusul lui '%-.64s' (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÓÔÁÔÕÓÎÕÀ ÉÎÆÏÒÍÁÃÉÀ Ï '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da dobijem stanje file-a '%-.64s' (errno: %d)"
+ slo "Nemô¾em zisti» stav '%-.64s' (chybový kód: %d)"
+ spa "No puedo obtener el estado de '%-.64s' (Error: %d)"
+ swe "Kan inte läsa filinformationen (stat) från '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÏÔÒÉÍÁÔÉ ÓÔÁÔÕÓ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_CANT_GET_WD
+ cze "Chyba p-Bøi zji¹»ování pracovní adresáø (chybový kód: %d)"
+ dan "Kan ikke læse aktive folder (Fejlkode: %d)"
+ nla "Kan de werkdirectory niet krijgen (Errcode: %d)"
+ eng "Can't get working directory (errno: %d)"
+ jps "working directory ‚𓾂鎖‚ª‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½ (errno: %d)",
+ est "Ei suuda identifitseerida jooksvat kataloogi (veakood: %d)"
+ fre "Ne peut obtenir le répertoire de travail (Errcode: %d)"
+ ger "Kann Arbeitsverzeichnis nicht ermitteln (Fehler: %d)"
+ greek "Ï öÜêåëëïò åñãáóßáò äåí âñÝèçêå (êùäéêüò ëÜèïõò: %d)"
+ hun "A munkakonyvtar nem allapithato meg (hibakod: %d)"
+ ita "Impossibile leggere la directory di lavoro (errno: %d)"
+ jpn "working directory ¤òÆÀ¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿ (errno: %d)"
+ kor "¼öÇà µð·ºÅ丮¸¦ ãÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke lese aktiv katalog(Feilkode: %d)"
+ norwegian-ny "Kan ikkje lese aktiv katalog(Feilkode: %d)"
+ pol "Nie mo¿na rozpoznaæ aktualnego katalogu (Kod b³êdu: %d)"
+ por "Não pode obter o diretório corrente (erro no. %d)"
+ rum "Nu pot sa obtin directorul current (working directory) (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÐÒÅÄÅÌÉÔØ ÒÁÂÏÞÉÊ ËÁÔÁÌÏÇ (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da dobijem trenutni direktorijum (errno: %d)"
+ slo "Nemô¾em zisti» pracovný adresár (chybový kód: %d)"
+ spa "No puedo acceder al directorio (Error: %d)"
+ swe "Kan inte inte läsa aktivt bibliotek. (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ×ÉÚÎÁÞÉÔÉ ÒÏÂÏÞÕ ÔÅËÕ (ÐÏÍÉÌËÁ: %d)"
+ER_CANT_LOCK
+ cze "Nemohu uzamknout soubor (chybov-Bý kód: %d)"
+ dan "Kan ikke låse fil (Fejlkode: %d)"
+ nla "Kan de file niet blokeren (Errcode: %d)"
+ eng "Can't lock file (errno: %d)"
+ jps "ƒtƒ@ƒCƒ‹‚ðƒƒbƒN‚Å‚«‚Ü‚¹‚ñ (errno: %d)",
+ est "Ei suuda lukustada faili (veakood: %d)"
+ fre "Ne peut verrouiller le fichier (Errcode: %d)"
+ ger "Datei kann nicht gesperrt werden (Fehler: %d)"
+ greek "Ôï áñ÷åßï äåí ìðïñåß íá êëåéäùèåß (êùäéêüò ëÜèïõò: %d)"
+ hun "A file nem zarolhato. (hibakod: %d)"
+ ita "Impossibile il locking il file (errno: %d)"
+ jpn "¥Õ¥¡¥¤¥ë¤ò¥í¥Ã¥¯¤Ç¤­¤Þ¤»¤ó (errno: %d)"
+ kor "È­ÀÏÀ» Àá±×Áö(lock) ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke låse fila (Feilkode: %d)"
+ norwegian-ny "Kan ikkje låse fila (Feilkode: %d)"
+ pol "Nie mo¿na zablokowaæ pliku (Kod b³êdu: %d)"
+ por "Não pode travar o arquivo (erro no. %d)"
+ rum "Nu pot sa lock fisierul (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÐÏÓÔÁ×ÉÔØ ÂÌÏËÉÒÏ×ËÕ ÎÁ ÆÁÊÌÅ (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da zakljuèam file (errno: %d)"
+ slo "Nemô¾em zamknú» súbor (chybový kód: %d)"
+ spa "No puedo bloquear archivo: (Error: %d)"
+ swe "Kan inte låsa filen. (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÚÁÂÌÏËÕ×ÁÔÉ ÆÁÊÌ (ÐÏÍÉÌËÁ: %d)"
+ER_CANT_OPEN_FILE
+ cze "Nemohu otev-Bøít soubor '%-.64s' (chybový kód: %d)"
+ dan "Kan ikke åbne fil: '%-.64s' (Fejlkode: %d)"
+ nla "Kan de file '%-.64s' niet openen (Errcode: %d)"
+ eng "Can't open file: '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒtƒ@ƒCƒ‹‚ðŠJ‚­Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d)",
+ est "Ei suuda avada faili '%-.64s' (veakood: %d)"
+ fre "Ne peut ouvrir le fichier: '%-.64s' (Errcode: %d)"
+ ger "Datei '%-.64s' nicht öffnen (Fehler: %d)"
+ greek "Äåí åßíáé äõíáôü íá áíïé÷ôåß ôï áñ÷åßï: '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "A '%-.64s' file nem nyithato meg (hibakod: %d)"
+ ita "Impossibile aprire il file: '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Õ¥¡¥¤¥ë¤ò³«¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó (errno: %d)"
+ kor "È­ÀÏÀ» ¿­Áö ¸øÇß½À´Ï´Ù.: '%-.64s' (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke åpne fila: '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Kan ikkje åpne fila: '%-.64s' (Feilkode: %d)"
+ pol "Nie mo¿na otworzyæ pliku: '%-.64s' (Kod b³êdu: %d)"
+ por "Não pode abrir o arquivo '%-.64s' (erro no. %d)"
+ rum "Nu pot sa deschid fisierul: '%-.64s' (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ: '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da otvorim file: '%-.64s' (errno: %d)"
+ slo "Nemô¾em otvori» súbor: '%-.64s' (chybový kód: %d)"
+ spa "No puedo abrir archivo: '%-.64s' (Error: %d)"
+ swe "Kan inte använda '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÆÁÊÌ: '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_FILE_NOT_FOUND
+ cze "Nemohu naj-Bít soubor '%-.64s' (chybový kód: %d)"
+ dan "Kan ikke finde fila: '%-.64s' (Fejlkode: %d)"
+ nla "Kan de file: '%-.64s' niet vinden (Errcode: %d)"
+ eng "Can't find file: '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒtƒ@ƒCƒ‹‚ðŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ.(errno: %d)",
+ est "Ei suuda leida faili '%-.64s' (veakood: %d)"
+ fre "Ne peut trouver le fichier: '%-.64s' (Errcode: %d)"
+ ger "Kann Datei '%-.64s' nicht finden (Fehler: %d)"
+ greek "Äåí âñÝèçêå ôï áñ÷åßï: '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "A(z) '%-.64s' file nem talalhato (hibakod: %d)"
+ ita "Impossibile trovare il file: '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Õ¥¡¥¤¥ë¤ò¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó.(errno: %d)"
+ kor "È­ÀÏÀ» ãÁö ¸øÇß½À´Ï´Ù.: '%-.64s' (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke finne fila: '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Kan ikkje finne fila: '%-.64s' (Feilkode: %d)"
+ pol "Nie mo¿na znale¥æ pliku: '%-.64s' (Kod b³êdu: %d)"
+ por "Não pode encontrar o arquivo '%-.64s' (erro no. %d)"
+ rum "Nu pot sa gasesc fisierul: '%-.64s' (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÆÁÊÌ: '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da pronaðem file: '%-.64s' (errno: %d)"
+ slo "Nemô¾em nájs» súbor: '%-.64s' (chybový kód: %d)"
+ spa "No puedo encontrar archivo: '%-.64s' (Error: %d)"
+ swe "Hittar inte filen '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÁÊÌ: '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_CANT_READ_DIR
+ cze "Nemohu -Bèíst adresáø '%-.64s' (chybový kód: %d)"
+ dan "Kan ikke læse folder '%-.64s' (Fejlkode: %d)"
+ nla "Kan de directory niet lezen van '%-.64s' (Errcode: %d)"
+ eng "Can't read dir of '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒfƒBƒŒƒNƒgƒŠ‚ª“Ç‚ß‚Ü‚¹‚ñ.(errno: %d)",
+ est "Ei suuda lugeda kataloogi '%-.64s' (veakood: %d)"
+ fre "Ne peut lire le répertoire de '%-.64s' (Errcode: %d)"
+ ger "Verzeichnis von '%-.64s' nicht lesbar (Fehler: %d)"
+ greek "Äåí åßíáé äõíáôü íá äéáâáóôåß ï öÜêåëëïò ôïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "A(z) '%-.64s' konyvtar nem olvashato. (hibakod: %d)"
+ ita "Impossibile leggere la directory di '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Ç¥£¥ì¥¯¥È¥ê¤¬Æɤá¤Þ¤»¤ó.(errno: %d)"
+ kor "'%-.64s'µð·ºÅ丮¸¦ ÀÐÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke lese katalogen '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Kan ikkje lese katalogen '%-.64s' (Feilkode: %d)"
+ pol "Nie mo¿na odczytaæ katalogu '%-.64s' (Kod b³êdu: %d)"
+ por "Não pode ler o diretório de '%-.64s' (erro no. %d)"
+ rum "Nu pot sa citesc directorul '%-.64s' (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ËÁÔÁÌÏÇ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da proèitam direktorijum '%-.64s' (errno: %d)"
+ slo "Nemô¾em èíta» adresár '%-.64s' (chybový kód: %d)"
+ spa "No puedo leer el directorio de '%-.64s' (Error: %d)"
+ swe "Kan inte läsa från bibliotek '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_CANT_SET_WD
+ cze "Nemohu zm-Bìnit adresáø na '%-.64s' (chybový kód: %d)"
+ dan "Kan ikke skifte folder til '%-.64s' (Fejlkode: %d)"
+ nla "Kan de directory niet veranderen naar '%-.64s' (Errcode: %d)"
+ eng "Can't change dir to '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒfƒBƒŒƒNƒgƒŠ‚É chdir ‚Å‚«‚Ü‚¹‚ñ.(errno: %d)",
+ est "Ei suuda siseneda kataloogi '%-.64s' (veakood: %d)"
+ fre "Ne peut changer le répertoire pour '%-.64s' (Errcode: %d)"
+ ger "Kann nicht in das Verzeichnis '%-.64s' wechseln (Fehler: %d)"
+ greek "Áäýíáôç ç áëëáãÞ ôïõ ôñÝ÷ïíôïò êáôáëüãïõ óå '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "Konyvtarvaltas nem lehetseges a(z) '%-.64s'-ba. (hibakod: %d)"
+ ita "Impossibile cambiare la directory in '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Ç¥£¥ì¥¯¥È¥ê¤Ë chdir ¤Ç¤­¤Þ¤»¤ó.(errno: %d)"
+ kor "'%-.64s'µð·ºÅ丮·Î À̵¿ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)"
+ nor "Kan ikke skifte katalog til '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Kan ikkje skifte katalog til '%-.64s' (Feilkode: %d)"
+ pol "Nie mo¿na zmieniæ katalogu na '%-.64s' (Kod b³êdu: %d)"
+ por "Não pode mudar para o diretório '%-.64s' (erro no. %d)"
+ rum "Nu pot sa schimb directorul '%-.64s' (Eroare: %d)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÊÔÉ × ËÁÔÁÌÏÇ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Ne mogu da promenim direktorijum na '%-.64s' (errno: %d)"
+ slo "Nemô¾em vojs» do adresára '%-.64s' (chybový kód: %d)"
+ spa "No puedo cambiar al directorio de '%-.64s' (Error: %d)"
+ swe "Kan inte byta till '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ Õ ÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_CHECKREAD
+ cze "Z-Báznam byl zmìnìn od posledního ètení v tabulce '%-.64s'"
+ dan "Posten er ændret siden sidste læsning '%-.64s'"
+ nla "Record is veranderd sinds de laatste lees activiteit in de tabel '%-.64s'"
+ eng "Record has changed since last read in table '%-.64s'"
+ est "Kirje tabelis '%-.64s' on muutunud viimasest lugemisest saadik"
+ fre "Enregistrement modifié depuis sa dernière lecture dans la table '%-.64s'"
+ ger "Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%-.64s' geändert"
+ greek "Ç åããñáöÞ Ý÷åé áëëÜîåé áðü ôçí ôåëåõôáßá öïñÜ ðïõ áíáóýñèçêå áðü ôïí ðßíáêá '%-.64s'"
+ hun "A(z) '%-.64s' tablaban talalhato rekord megvaltozott az utolso olvasas ota"
+ ita "Il record e` cambiato dall'ultima lettura della tabella '%-.64s'"
+ kor "Å×À̺í '%-.64s'¿¡¼­ ¸¶Áö¸·À¸·Î ÀÐÀº ÈÄ Record°¡ º¯°æµÇ¾ú½À´Ï´Ù."
+ nor "Posten har blitt endret siden den ble lest '%-.64s'"
+ norwegian-ny "Posten har vorte endra sidan den sist vart lesen '%-.64s'"
+ pol "Rekord zosta³ zmieniony od ostaniego odczytania z tabeli '%-.64s'"
+ por "Registro alterado desde a última leitura da tabela '%-.64s'"
+ rum "Cimpul a fost schimbat de la ultima citire a tabelei '%-.64s'"
+ rus "úÁÐÉÓØ ÉÚÍÅÎÉÌÁÓØ Ó ÍÏÍÅÎÔÁ ÐÏÓÌÅÄÎÅÊ ×ÙÂÏÒËÉ × ÔÁÂÌÉÃÅ '%-.64s'"
+ serbian "Slog je promenjen od zadnjeg èitanja tabele '%-.64s'"
+ slo "Záznam bol zmenený od posledného èítania v tabuµke '%-.64s'"
+ spa "El registro ha cambiado desde la ultima lectura de la tabla '%-.64s'"
+ swe "Posten har förändrats sedan den lästes i register '%-.64s'"
+ ukr "úÁÐÉÓ ÂÕÌÏ ÚͦÎÅÎÏ Ú ÞÁÓÕ ÏÓÔÁÎÎØÏÇÏ ÞÉÔÁÎÎÑ Ú ÔÁÂÌÉæ '%-.64s'"
+ER_DISK_FULL
+ cze "Disk je pln-Bý (%s), èekám na uvolnìní nìjakého místa ..."
+ dan "Ikke mere diskplads (%s). Venter på at få frigjort plads..."
+ nla "Schijf vol (%s). Aan het wachten totdat er ruimte vrij wordt gemaakt..."
+ eng "Disk full (%s); waiting for someone to free some space..."
+ jps "Disk full (%s). ’N‚©‚ª‰½‚©‚ðŒ¸‚ç‚·‚Ü‚Å‚Ü‚Á‚Ä‚­‚¾‚³‚¢...",
+ est "Ketas täis (%s). Ootame kuni tekib vaba ruumi..."
+ fre "Disque plein (%s). J'attend que quelqu'un libère de l'espace..."
+ ger "Festplatte voll (%-.64s). Warte, bis jemand Platz schafft ..."
+ greek "Äåí õðÜñ÷åé ÷þñïò óôï äßóêï (%s). Ðáñáêáëþ, ðåñéìÝíåôå íá åëåõèåñùèåß ÷þñïò..."
+ hun "A lemez megtelt (%s)."
+ ita "Disco pieno (%s). In attesa che qualcuno liberi un po' di spazio..."
+ jpn "Disk full (%s). 狼¤¬²¿¤«¤ò¸º¤é¤¹¤Þ¤Ç¤Þ¤Ã¤Æ¤¯¤À¤µ¤¤..."
+ kor "Disk full (%s). ´Ù¸¥ »ç¶÷ÀÌ Áö¿ï¶§±îÁö ±â´Ù¸³´Ï´Ù..."
+ nor "Ikke mer diskplass (%s). Venter på å få frigjort plass..."
+ norwegian-ny "Ikkje meir diskplass (%s). Ventar på å få frigjort plass..."
+ pol "Dysk pe³ny (%s). Oczekiwanie na zwolnienie miejsca..."
+ por "Disco cheio (%s). Aguardando alguém liberar algum espaço..."
+ rum "Hard-disk-ul este plin (%s). Astept sa se elibereze ceva spatiu..."
+ rus "äÉÓË ÚÁÐÏÌÎÅÎ. (%s). ïÖÉÄÁÅÍ, ÐÏËÁ ËÔÏ-ÔÏ ÎÅ ÕÂÅÒÅÔ ÐÏÓÌÅ ÓÅÂÑ ÍÕÓÏÒ..."
+ serbian "Disk je pun (%s). Èekam nekoga da doðe i oslobodi nešto mesta..."
+ slo "Disk je plný (%s), èakám na uvoµnenie miesta..."
+ spa "Disco lleno (%s). Esperando para que se libere algo de espacio..."
+ swe "Disken är full (%s). Väntar tills det finns ledigt utrymme..."
+ ukr "äÉÓË ÚÁÐÏ×ÎÅÎÉÊ (%s). ÷ÉÞÉËÕÀ, ÄÏËÉ ÚצÌØÎÉÔØÓÑ ÔÒÏÈÉ Í¦ÓÃÑ..."
+ER_DUP_KEY 23000
+ cze "Nemohu zapsat, zdvojen-Bý klíè v tabulce '%-.64s'"
+ dan "Kan ikke skrive, flere ens nøgler i tabellen '%-.64s'"
+ nla "Kan niet schrijven, dubbele zoeksleutel in tabel '%-.64s'"
+ eng "Can't write; duplicate key in table '%-.64s'"
+ jps "table '%-.64s' ‚É key ‚ªd•¡‚µ‚Ä‚¢‚Ä‘‚«‚±‚ß‚Ü‚¹‚ñ",
+ est "Ei saa kirjutada, korduv võti tabelis '%-.64s'"
+ fre "Ecriture impossible, doublon dans une clé de la table '%-.64s'"
+ ger "Kann nicht speichern, Grund: doppelter Schlüssel in Tabelle '%-.64s'"
+ greek "Äåí åßíáé äõíáôÞ ç êáôá÷þñçóç, ç ôéìÞ õðÜñ÷åé Þäç óôïí ðßíáêá '%-.64s'"
+ hun "Irasi hiba, duplikalt kulcs a '%-.64s' tablaban."
+ ita "Scrittura impossibile: chiave duplicata nella tabella '%-.64s'"
+ jpn "table '%-.64s' ¤Ë key ¤¬½ÅÊ£¤·¤Æ¤¤¤Æ½ñ¤­¤³¤á¤Þ¤»¤ó"
+ kor "±â·ÏÇÒ ¼ö ¾øÀ¾´Ï´Ù., Å×À̺í '%-.64s'¿¡¼­ Áߺ¹ Å°"
+ nor "Kan ikke skrive, flere like nøkler i tabellen '%-.64s'"
+ norwegian-ny "Kan ikkje skrive, flere like nyklar i tabellen '%-.64s'"
+ pol "Nie mo¿na zapisaæ, powtórzone klucze w tabeli '%-.64s'"
+ por "Não pode gravar. Chave duplicada na tabela '%-.64s'"
+ rum "Nu pot sa scriu (can't write), cheie duplicata in tabela '%-.64s'"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÉÚ×ÅÓÔÉ ÚÁÐÉÓØ, ÄÕÂÌÉÒÕÀÝÉÊÓÑ ËÌÀÞ × ÔÁÂÌÉÃÅ '%-.64s'"
+ serbian "Ne mogu da pišem pošto postoji duplirani kljuè u tabeli '%-.64s'"
+ slo "Nemô¾em zapísa», duplikát kµúèa v tabuµke '%-.64s'"
+ spa "No puedo escribir, clave duplicada en la tabla '%-.64s'"
+ swe "Kan inte skriva, dubbel söknyckel i register '%-.64s'"
+ ukr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ, ÄÕÂÌÀÀÞÉÊÓÑ ËÌÀÞ × ÔÁÂÌÉæ '%-.64s'"
+ER_ERROR_ON_CLOSE
+ cze "Chyba p-Bøi zavírání '%-.64s' (chybový kód: %d)"
+ dan "Fejl ved lukning af '%-.64s' (Fejlkode: %d)"
+ nla "Fout bij het sluiten van '%-.64s' (Errcode: %d)"
+ eng "Error on close of '%-.64s' (errno: %d)"
+ est "Viga faili '%-.64s' sulgemisel (veakood: %d)"
+ fre "Erreur a la fermeture de '%-.64s' (Errcode: %d)"
+ ger "Fehler beim Schließen von '%-.64s' (Fehler: %d)"
+ greek "ÐáñïõóéÜóôçêå ðñüâëçìá êëåßíïíôáò ôï '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "Hiba a(z) '%-.64s' zarasakor. (hibakod: %d)"
+ ita "Errore durante la chiusura di '%-.64s' (errno: %d)"
+ kor "'%-.64s'´Ý´Â Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)"
+ nor "Feil ved lukking av '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Feil ved lukking av '%-.64s' (Feilkode: %d)"
+ pol "B³?d podczas zamykania '%-.64s' (Kod b³êdu: %d)"
+ por "Erro ao fechar '%-.64s' (erro no. %d)"
+ rum "Eroare inchizind '%-.64s' (errno: %d)"
+ rus "ïÛÉÂËÁ ÐÒÉ ÚÁËÒÙÔÉÉ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Greška pri zatvaranju '%-.64s' (errno: %d)"
+ slo "Chyba pri zatváraní '%-.64s' (chybový kód: %d)"
+ spa "Error en el cierre de '%-.64s' (Error: %d)"
+ swe "Fick fel vid stängning av '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÚÁËÒÉÔÉ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_ERROR_ON_READ
+ cze "Chyba p-Bøi ètení souboru '%-.64s' (chybový kód: %d)"
+ dan "Fejl ved læsning af '%-.64s' (Fejlkode: %d)"
+ nla "Fout bij het lezen van file '%-.64s' (Errcode: %d)"
+ eng "Error reading file '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒtƒ@ƒCƒ‹‚Ì“Ç‚Ýž‚݃Gƒ‰[ (errno: %d)",
+ est "Viga faili '%-.64s' lugemisel (veakood: %d)"
+ fre "Erreur en lecture du fichier '%-.64s' (Errcode: %d)"
+ ger "Fehler beim Lesen der Datei '%-.64s' (Fehler: %d)"
+ greek "Ðñüâëçìá êáôÜ ôçí áíÜãíùóç ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "Hiba a '%-.64s'file olvasasakor. (hibakod: %d)"
+ ita "Errore durante la lettura del file '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Õ¥¡¥¤¥ë¤ÎÆɤ߹þ¤ß¥¨¥é¡¼ (errno: %d)"
+ kor "'%-.64s'È­ÀÏ Àб⠿¡·¯ (¿¡·¯¹øÈ£: %d)"
+ nor "Feil ved lesing av '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Feil ved lesing av '%-.64s' (Feilkode: %d)"
+ pol "B³?d podczas odczytu pliku '%-.64s' (Kod b³êdu: %d)"
+ por "Erro ao ler arquivo '%-.64s' (erro no. %d)"
+ rum "Eroare citind fisierul '%-.64s' (errno: %d)"
+ rus "ïÛÉÂËÁ ÞÔÅÎÉÑ ÆÁÊÌÁ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Greška pri èitanju file-a '%-.64s' (errno: %d)"
+ slo "Chyba pri èítaní súboru '%-.64s' (chybový kód: %d)"
+ spa "Error leyendo el fichero '%-.64s' (Error: %d)"
+ swe "Fick fel vid läsning av '%-.64s' (Felkod %d)"
+ ukr "îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_ERROR_ON_RENAME
+ cze "Chyba p-Bøi pøejmenování '%-.64s' na '%-.64s' (chybový kód: %d)"
+ dan "Fejl ved omdøbning af '%-.64s' til '%-.64s' (Fejlkode: %d)"
+ nla "Fout bij het hernoemen van '%-.64s' naar '%-.64s' (Errcode: %d)"
+ eng "Error on rename of '%-.64s' to '%-.64s' (errno: %d)"
+ jps "'%-.64s' ‚ð '%-.64s' ‚É rename ‚Å‚«‚Ü‚¹‚ñ (errno: %d)",
+ est "Viga faili '%-.64s' ümbernimetamisel '%-.64s'-ks (veakood: %d)"
+ fre "Erreur en renommant '%-.64s' en '%-.64s' (Errcode: %d)"
+ ger "Fehler beim Umbenennen von '%-.64s' in '%-.64s' (Fehler: %d)"
+ greek "Ðñüâëçìá êáôÜ ôçí ìåôïíïìáóßá ôïõ áñ÷åßïõ '%-.64s' to '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "Hiba a '%-.64s' file atnevezesekor. (hibakod: %d)"
+ ita "Errore durante la rinominazione da '%-.64s' a '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¤ò '%-.64s' ¤Ë rename ¤Ç¤­¤Þ¤»¤ó (errno: %d)"
+ kor "'%-.64s'¸¦ '%-.64s'·Î À̸§ º¯°æÁß ¿¡·¯ (¿¡·¯¹øÈ£: %d)"
+ nor "Feil ved omdøping av '%-.64s' til '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Feil ved omdøyping av '%-.64s' til '%-.64s' (Feilkode: %d)"
+ pol "B³?d podczas zmieniania nazwy '%-.64s' na '%-.64s' (Kod b³êdu: %d)"
+ por "Erro ao renomear '%-.64s' para '%-.64s' (erro no. %d)"
+ rum "Eroare incercind sa renumesc '%-.64s' in '%-.64s' (errno: %d)"
+ rus "ïÛÉÂËÁ ÐÒÉ ÐÅÒÅÉÍÅÎÏ×ÁÎÉÉ '%-.64s' × '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Greška pri promeni imena '%-.64s' na '%-.64s' (errno: %d)"
+ slo "Chyba pri premenovávaní '%-.64s' na '%-.64s' (chybový kód: %d)"
+ spa "Error en el renombrado de '%-.64s' a '%-.64s' (Error: %d)"
+ swe "Kan inte byta namn från '%-.64s' till '%-.64s' (Felkod: %d)"
+ ukr "îÅ ÍÏÖÕ ÐÅÒÅÊÍÅÎÕ×ÁÔÉ '%-.64s' Õ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_ERROR_ON_WRITE
+ cze "Chyba p-Bøi zápisu do souboru '%-.64s' (chybový kód: %d)"
+ dan "Fejl ved skriving av filen '%-.64s' (Fejlkode: %d)"
+ nla "Fout bij het wegschrijven van file '%-.64s' (Errcode: %d)"
+ eng "Error writing file '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒtƒ@ƒCƒ‹‚ð‘‚­Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d)",
+ est "Viga faili '%-.64s' kirjutamisel (veakood: %d)"
+ fre "Erreur d'écriture du fichier '%-.64s' (Errcode: %d)"
+ ger "Fehler beim Speichern der Datei '%-.64s' (Fehler: %d)"
+ greek "Ðñüâëçìá êáôÜ ôçí áðïèÞêåõóç ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "Hiba a '%-.64s' file irasakor. (hibakod: %d)"
+ ita "Errore durante la scrittura del file '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Õ¥¡¥¤¥ë¤ò½ñ¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó (errno: %d)"
+ kor "'%-.64s'È­ÀÏ ±â·Ï Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)"
+ nor "Feil ved skriving av fila '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Feil ved skriving av fila '%-.64s' (Feilkode: %d)"
+ pol "B³?d podczas zapisywania pliku '%-.64s' (Kod b³êdu: %d)"
+ por "Erro ao gravar arquivo '%-.64s' (erro no. %d)"
+ rum "Eroare scriind fisierul '%-.64s' (errno: %d)"
+ rus "ïÛÉÂËÁ ÚÁÐÉÓÉ × ÆÁÊÌ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Greška pri upisu '%-.64s' (errno: %d)"
+ slo "Chyba pri zápise do súboru '%-.64s' (chybový kód: %d)"
+ spa "Error escribiendo el archivo '%-.64s' (Error: %d)"
+ swe "Fick fel vid skrivning till '%-.64s' (Felkod %d)"
+ ukr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ ÆÁÊÌ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_FILE_USED
+ cze "'%-.64s' je zam-Bèen proti zmìnám"
+ dan "'%-.64s' er låst mod opdateringer"
+ nla "'%-.64s' is geblokeerd tegen veranderingen"
+ eng "'%-.64s' is locked against change"
+ jps "'%-.64s' ‚̓ƒbƒN‚³‚ê‚Ä‚¢‚Ü‚·",
+ est "'%-.64s' on lukustatud muudatuste vastu"
+ fre "'%-.64s' est verrouillé contre les modifications"
+ ger "'%-.64s' ist für Änderungen gesperrt"
+ greek "'%-.64s' äåí åðéôñÝðïíôáé áëëáãÝò"
+ hun "'%-.64s' a valtoztatas ellen zarolva"
+ ita "'%-.64s' e` soggetto a lock contro i cambiamenti"
+ jpn "'%-.64s' ¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹"
+ kor "'%-.64s'°¡ º¯°æÇÒ ¼ö ¾øµµ·Ï Àá°ÜÀÖÀ¾´Ï´Ù."
+ nor "'%-.64s' er låst mot oppdateringer"
+ norwegian-ny "'%-.64s' er låst mot oppdateringar"
+ pol "'%-.64s' jest zablokowany na wypadek zmian"
+ por "'%-.64s' está com travamento contra alterações"
+ rum "'%-.64s' este blocat pentry schimbari (loccked against change)"
+ rus "'%-.64s' ÚÁÂÌÏËÉÒÏ×ÁÎ ÄÌÑ ÉÚÍÅÎÅÎÉÊ"
+ serbian "'%-.64s' je zakljuèan za upis"
+ slo "'%-.64s' je zamknutý proti zmenám"
+ spa "'%-.64s' esta bloqueado contra cambios"
+ swe "'%-.64s' är låst mot användning"
+ ukr "'%-.64s' ÚÁÂÌÏËÏ×ÁÎÉÊ ÎÁ ×ÎÅÓÅÎÎÑ ÚͦÎ"
+ER_FILSORT_ABORT
+ cze "T-Bøídìní pøeru¹eno"
+ dan "Sortering afbrudt"
+ nla "Sorteren afgebroken"
+ eng "Sort aborted"
+ jps "Sort ’†’f",
+ est "Sorteerimine katkestatud"
+ fre "Tri alphabétique abandonné"
+ ger "Sortiervorgang abgebrochen"
+ greek "Ç äéáäéêáóßá ôáîéíüìéóçò áêõñþèçêå"
+ hun "Sikertelen rendezes"
+ ita "Operazione di ordinamento abbandonata"
+ jpn "Sort ̾̂"
+ kor "¼ÒÆ®°¡ ÁߴܵǾú½À´Ï´Ù."
+ nor "Sortering avbrutt"
+ norwegian-ny "Sortering avbrote"
+ pol "Sortowanie przerwane"
+ por "Ordenação abortada"
+ rum "Sortare intrerupta"
+ rus "óÏÒÔÉÒÏ×ËÁ ÐÒÅÒ×ÁÎÁ"
+ serbian "Sortiranje je prekinuto"
+ slo "Triedenie preru¹ené"
+ spa "Ordeancion cancelada"
+ swe "Sorteringen avbruten"
+ ukr "óÏÒÔÕ×ÁÎÎÑ ÐÅÒÅÒ×ÁÎÏ"
+ER_FORM_NOT_FOUND
+ cze "Pohled '%-.64s' pro '%-.64s' neexistuje"
+ dan "View '%-.64s' eksisterer ikke for '%-.64s'"
+ nla "View '%-.64s' bestaat niet voor '%-.64s'"
+ eng "View '%-.64s' doesn't exist for '%-.64s'"
+ jps "View '%-.64s' ‚ª '%-.64s' ‚É’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
+ est "Vaade '%-.64s' ei eksisteeri '%-.64s' jaoks"
+ fre "La vue (View) '%-.64s' n'existe pas pour '%-.64s'"
+ ger "View '%-.64s' existiert für '%-.64s' nicht"
+ greek "Ôï View '%-.64s' äåí õðÜñ÷åé ãéá '%-.64s'"
+ hun "A(z) '%-.64s' nezet nem letezik a(z) '%-.64s'-hoz"
+ ita "La view '%-.64s' non esiste per '%-.64s'"
+ jpn "View '%-.64s' ¤¬ '%-.64s' ¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+ kor "ºä '%-.64s'°¡ '%-.64s'¿¡¼­´Â Á¸ÀçÇÏÁö ¾ÊÀ¾´Ï´Ù."
+ nor "View '%-.64s' eksisterer ikke for '%-.64s'"
+ norwegian-ny "View '%-.64s' eksisterar ikkje for '%-.64s'"
+ pol "Widok '%-.64s' nie istnieje dla '%-.64s'"
+ por "Visão '%-.64s' não existe para '%-.64s'"
+ rum "View '%-.64s' nu exista pentru '%-.64s'"
+ rus "ðÒÅÄÓÔÁ×ÌÅÎÉÅ '%-.64s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ ÄÌÑ '%-.64s'"
+ serbian "View '%-.64s' ne postoji za '%-.64s'"
+ slo "Pohµad '%-.64s' neexistuje pre '%-.64s'"
+ spa "La vista '%-.64s' no existe para '%-.64s'"
+ swe "Formulär '%-.64s' finns inte i '%-.64s'"
+ ukr "÷ÉÇÌÑÄ '%-.64s' ÎÅ ¦ÓÎÕ¤ ÄÌÑ '%-.64s'"
+ER_GET_ERRNO
+ cze "Obsluha tabulky vr-Bátila chybu %d"
+ dan "Modtog fejl %d fra tabel håndteringen"
+ nla "Fout %d van tabel handler"
+ eng "Got error %d from storage engine"
+ est "Tabeli handler tagastas vea %d"
+ fre "Reçu l'erreur %d du handler de la table"
+ ger "Fehler %d (Tabellenhandler)"
+ greek "ÅëÞöèç ìÞíõìá ëÜèïõò %d áðü ôïí ÷åéñéóôÞ ðßíáêá (table handler)"
+ hun "%d hibajelzes a tablakezelotol"
+ ita "Rilevato l'errore %d dal gestore delle tabelle"
+ jpn "Got error %d from table handler"
+ kor "Å×À̺í handler¿¡¼­ %d ¿¡·¯°¡ ¹ß»ý ÇÏ¿´½À´Ï´Ù."
+ nor "Mottok feil %d fra tabell håndterer"
+ norwegian-ny "Mottok feil %d fra tabell handterar"
+ pol "Otrzymano b³?d %d z obs³ugi tabeli"
+ por "Obteve erro %d no manipulador de tabelas"
+ rum "Eroarea %d obtinuta din handlerul tabelei"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d ÏÔ ÏÂÒÁÂÏÔÞÉËÁ ÔÁÂÌÉÃ"
+ serbian "Handler tabela je vratio grešku %d"
+ slo "Obsluha tabuµky vrátila chybu %d"
+ spa "Error %d desde el manejador de la tabla"
+ swe "Fick felkod %d från databashanteraren"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d ×¦Ä ÄÅÓËÒÉÐÔÏÒÁ ÔÁÂÌÉæ"
+ER_ILLEGAL_HA
+ cze "Obsluha tabulky '%-.64s' nem-Bá tento parametr"
+ dan "Denne mulighed eksisterer ikke for tabeltypen '%-.64s'"
+ nla "Tabel handler voor '%-.64s' heeft deze optie niet"
+ eng "Table storage engine for '%-.64s' doesn't have this option"
+ est "Tabeli '%-.64s' handler ei toeta antud operatsiooni"
+ fre "Le handler de la table '%-.64s' n'a pas cette option"
+ ger "Diese Option gibt es nicht (Tabellenhandler)"
+ greek "Ï ÷åéñéóôÞò ðßíáêá (table handler) ãéá '%-.64s' äåí äéáèÝôåé áõôÞ ôçí åðéëïãÞ"
+ hun "A(z) '%-.64s' tablakezelonek nincs ilyen opcioja"
+ ita "Il gestore delle tabelle per '%-.64s' non ha questa opzione"
+ jpn "Table handler for '%-.64s' doesn't have this option"
+ kor "'%-.64s'ÀÇ Å×À̺í handler´Â ÀÌ·¯ÇÑ ¿É¼ÇÀ» Á¦°øÇÏÁö ¾ÊÀ¾´Ï´Ù."
+ nor "Tabell håndtereren for '%-.64s' har ikke denne muligheten"
+ norwegian-ny "Tabell håndteraren for '%-.64s' har ikkje denne moglegheita"
+ pol "Obs³uga tabeli '%-.64s' nie posiada tej opcji"
+ por "Manipulador de tabela para '%-.64s' não tem esta opção"
+ rum "Handlerul tabelei pentru '%-.64s' nu are aceasta optiune"
+ rus "ïÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ '%-.64s' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÜÔÕ ×ÏÚÍÏÖÎÏÓÔØ"
+ serbian "Handler tabela za '%-.64s' nema ovu opciju"
+ slo "Obsluha tabuµky '%-.64s' nemá tento parameter"
+ spa "El manejador de la tabla de '%-.64s' no tiene esta opcion"
+ swe "Registrets databas har inte denna facilitet"
+ ukr "äÅÓËÒÉÐÔÏÒ ÔÁÂÌÉæ '%-.64s' ÎÅ ÍÁ¤ 椧 ×ÌÁÓÔÉ×ÏÓÔ¦"
+ER_KEY_NOT_FOUND
+ cze "Nemohu naj-Bít záznam v '%-.64s'"
+ dan "Kan ikke finde posten i '%-.64s'"
+ nla "Kan record niet vinden in '%-.64s'"
+ eng "Can't find record in '%-.64s'"
+ jps "'%-.64s'‚Ì‚È‚©‚ɃŒƒR[ƒh‚ªŒ©•t‚©‚è‚Ü‚¹‚ñ",
+ est "Ei suuda leida kirjet '%-.64s'-s"
+ fre "Ne peut trouver l'enregistrement dans '%-.64s'"
+ ger "Kann Datensatz nicht finden"
+ greek "Áäýíáôç ç áíåýñåóç åããñáöÞò óôï '%-.64s'"
+ hun "Nem talalhato a rekord '%-.64s'-ben"
+ ita "Impossibile trovare il record in '%-.64s'"
+ jpn "'%-.64s'¤Î¤Ê¤«¤Ë¥ì¥³¡¼¥É¤¬¸«ÉÕ¤«¤ê¤Þ¤»¤ó"
+ kor "'%-.64s'¿¡¼­ ·¹Äڵ带 ãÀ» ¼ö ¾øÀ¾´Ï´Ù."
+ nor "Kan ikke finne posten i '%-.64s'"
+ norwegian-ny "Kan ikkje finne posten i '%-.64s'"
+ pol "Nie mo¿na znale¥æ rekordu w '%-.64s'"
+ por "Não pode encontrar registro em '%-.64s'"
+ rum "Nu pot sa gasesc recordul in '%-.64s'"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÚÁÐÉÓØ × '%-.64s'"
+ serbian "Ne mogu da pronaðem slog u '%-.64s'"
+ slo "Nemô¾em nájs» záznam v '%-.64s'"
+ spa "No puedo encontrar el registro en '%-.64s'"
+ swe "Hittar inte posten"
+ ukr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ Õ '%-.64s'"
+ER_NOT_FORM_FILE
+ cze "Nespr-Bávná informace v souboru '%-.64s'"
+ dan "Forkert indhold i: '%-.64s'"
+ nla "Verkeerde info in file: '%-.64s'"
+ eng "Incorrect information in file: '%-.64s'"
+ jps "ƒtƒ@ƒCƒ‹ '%-.64s' ‚Ì info ‚ªŠÔˆá‚Á‚Ä‚¢‚é‚悤‚Å‚·",
+ est "Vigane informatsioon failis '%-.64s'"
+ fre "Information erronnée dans le fichier: '%-.64s'"
+ ger "Falsche Information in Datei '%-.64s'"
+ greek "ËÜèïò ðëçñïöïñßåò óôï áñ÷åßï: '%-.64s'"
+ hun "Ervenytelen info a file-ban: '%-.64s'"
+ ita "Informazione errata nel file: '%-.64s'"
+ jpn "¥Õ¥¡¥¤¥ë '%-.64s' ¤Î info ¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¤è¤¦¤Ç¤¹"
+ kor "È­ÀÏÀÇ ºÎÁ¤È®ÇÑ Á¤º¸: '%-.64s'"
+ nor "Feil informasjon i filen: '%-.64s'"
+ norwegian-ny "Feil informasjon i fila: '%-.64s'"
+ pol "Niew³a?ciwa informacja w pliku: '%-.64s'"
+ por "Informação incorreta no arquivo '%-.64s'"
+ rum "Informatie incorecta in fisierul: '%-.64s'"
+ rus "îÅËÏÒÒÅËÔÎÁÑ ÉÎÆÏÒÍÁÃÉÑ × ÆÁÊÌÅ '%-.64s'"
+ serbian "Pogrešna informacija u file-u: '%-.64s'"
+ slo "Nesprávna informácia v súbore: '%-.64s'"
+ spa "Informacion erronea en el archivo: '%-.64s'"
+ swe "Felaktig fil: '%-.64s'"
+ ukr "èÉÂÎÁ ¦ÎÆÏÒÍÁÃ¦Ñ Õ ÆÁÊ̦: '%-.64s'"
+ER_NOT_KEYFILE
+ cze "Nespr-Bávný klíè pro tabulku '%-.64s'; pokuste se ho opravit"
+ dan "Fejl i indeksfilen til tabellen '%-.64s'; prøv at reparere den"
+ nla "Verkeerde zoeksleutel file voor tabel: '%-.64s'; probeer het te repareren"
+ eng "Incorrect key file for table '%-.64s'; try to repair it"
+ jps "'%-.64s' ƒe[ƒuƒ‹‚Ì key file ‚ªŠÔˆá‚Á‚Ä‚¢‚é‚悤‚Å‚·. C•œ‚ð‚µ‚Ä‚­‚¾‚³‚¢",
+ est "Tabeli '%-.64s' võtmefail on vigane; proovi seda parandada"
+ fre "Index corrompu dans la table: '%-.64s'; essayez de le réparer"
+ ger "Falsche Schlüssel-Datei für Tabelle '%-.64s'. versuche zu reparieren"
+ greek "ËÜèïò áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá: '%-.64s'; Ðáñáêáëþ, äéïñèþóôå ôï!"
+ hun "Ervenytelen kulcsfile a tablahoz: '%-.64s'; probalja kijavitani!"
+ ita "File chiave errato per la tabella : '%-.64s'; prova a riparalo"
+ jpn "'%-.64s' ¥Æ¡¼¥Ö¥ë¤Î key file ¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¤è¤¦¤Ç¤¹. ½¤Éü¤ò¤·¤Æ¤¯¤À¤µ¤¤"
+ kor "'%-.64s' Å×À̺íÀÇ ºÎÁ¤È®ÇÑ Å° Á¸Àç. ¼öÁ¤ÇϽÿÀ!"
+ nor "Tabellen '%-.64s' har feil i nøkkelfilen; forsøk å reparer den"
+ norwegian-ny "Tabellen '%-.64s' har feil i nykkelfila; prøv å reparere den"
+ pol "Niew³a?ciwy plik kluczy dla tabeli: '%-.64s'; spróbuj go naprawiæ"
+ por "Arquivo de índice incorreto para tabela '%-.64s'; tente repará-lo"
+ rum "Cheia fisierului incorecta pentru tabela: '%-.64s'; incearca s-o repari"
+ rus "îÅËÏÒÒÅËÔÎÙÊ ÉÎÄÅËÓÎÙÊ ÆÁÊÌ ÄÌÑ ÔÁÂÌÉÃÙ: '%-.64s'. ðÏÐÒÏÂÕÊÔÅ ×ÏÓÓÔÁÎÏ×ÉÔØ ÅÇÏ"
+ serbian "Pogrešan key file za tabelu: '%-.64s'; probajte da ga ispravite"
+ slo "Nesprávny kµúè pre tabuµku '%-.64s'; pokúste sa ho opravi»"
+ spa "Clave de archivo erronea para la tabla: '%-.64s'; intente repararlo"
+ swe "Fatalt fel vid hantering av register '%-.64s'; kör en reparation"
+ ukr "èÉÂÎÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ: '%-.64s'; óÐÒÏÂÕÊÔÅ ÊÏÇÏ ×¦ÄÎÏ×ÉÔÉ"
+ER_OLD_KEYFILE
+ cze "Star-Bý klíèový soubor pro '%-.64s'; opravte ho."
+ dan "Gammel indeksfil for tabellen '%-.64s'; reparer den"
+ nla "Oude zoeksleutel file voor tabel '%-.64s'; repareer het!"
+ eng "Old key file for table '%-.64s'; repair it!"
+ jps "'%-.64s' ƒe[ƒuƒ‹‚͌¢Œ`Ž®‚Ì key file ‚̂悤‚Å‚·; C•œ‚ð‚µ‚Ä‚­‚¾‚³‚¢",
+ est "Tabeli '%-.64s' võtmefail on aegunud; paranda see!"
+ fre "Vieux fichier d'index pour la table '%-.64s'; réparez le!"
+ ger "Alte Schlüssel-Datei für Tabelle '%-.64s'. Bitte reparieren"
+ greek "Ðáëáéü áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá '%-.64s'; Ðáñáêáëþ, äéïñèþóôå ôï!"
+ hun "Regi kulcsfile a '%-.64s'tablahoz; probalja kijavitani!"
+ ita "File chiave vecchio per la tabella '%-.64s'; riparalo!"
+ jpn "'%-.64s' ¥Æ¡¼¥Ö¥ë¤Ï¸Å¤¤·Á¼°¤Î key file ¤Î¤è¤¦¤Ç¤¹; ½¤Éü¤ò¤·¤Æ¤¯¤À¤µ¤¤"
+ kor "'%-.64s' Å×À̺íÀÇ ÀÌÀü¹öÁ¯ÀÇ Å° Á¸Àç. ¼öÁ¤ÇϽÿÀ!"
+ nor "Gammel nøkkelfil for tabellen '%-.64s'; reparer den!"
+ norwegian-ny "Gammel nykkelfil for tabellen '%-.64s'; reparer den!"
+ pol "Plik kluczy dla tabeli '%-.64s' jest starego typu; napraw go!"
+ por "Arquivo de índice desatualizado para tabela '%-.64s'; repare-o!"
+ rum "Cheia fisierului e veche pentru tabela '%-.64s'; repar-o!"
+ rus "óÔÁÒÙÊ ÉÎÄÅËÓÎÙÊ ÆÁÊÌ ÄÌÑ ÔÁÂÌÉÃÙ '%-.64s'; ÏÔÒÅÍÏÎÔÉÒÕÊÔÅ ÅÇÏ!"
+ serbian "Zastareo key file za tabelu '%-.64s'; ispravite ga"
+ slo "Starý kµúèový súbor pre '%-.64s'; opravte ho!"
+ spa "Clave de archivo antigua para la tabla '%-.64s'; reparelo!"
+ swe "Gammal nyckelfil '%-.64s'; reparera registret"
+ ukr "óÔÁÒÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ '%-.64s'; ÷¦ÄÎÏצÔØ ÊÏÇÏ!"
+ER_OPEN_AS_READONLY
+ cze "'%-.64s' je jen pro -Bètení"
+ dan "'%-.64s' er skrivebeskyttet"
+ nla "'%-.64s' is alleen leesbaar"
+ eng "Table '%-.64s' is read only"
+ jps "'%-.64s' ‚Í“Ç‚Ýž‚Ýê—p‚Å‚·",
+ est "Tabel '%-.64s' on ainult lugemiseks"
+ fre "'%-.64s' est en lecture seulement"
+ ger "'%-.64s' ist nur lesbar"
+ greek "'%-.64s' åðéôñÝðåôáé ìüíï ç áíÜãíùóç"
+ hun "'%-.64s' irasvedett"
+ ita "'%-.64s' e` di sola lettura"
+ jpn "'%-.64s' ¤ÏÆɤ߹þ¤ßÀìÍѤǤ¹"
+ kor "Å×À̺í '%-.64s'´Â ÀбâÀü¿ë ÀÔ´Ï´Ù."
+ nor "'%-.64s' er skrivebeskyttet"
+ norwegian-ny "'%-.64s' er skrivetryggja"
+ pol "'%-.64s' jest tylko do odczytu"
+ por "Tabela '%-.64s' é somente para leitura"
+ rum "Tabela '%-.64s' e read-only"
+ rus "ôÁÂÌÉÃÁ '%-.64s' ÐÒÅÄÎÁÚÎÁÞÅÎÁ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ"
+ serbian "Tabelu '%-.64s' je dozvoljeno samo èitati"
+ slo "'%-.64s' is èíta» only"
+ spa "'%-.64s' es de solo lectura"
+ swe "'%-.64s' är skyddad mot förändring"
+ ukr "ôÁÂÌÉÃÑ '%-.64s' Ô¦ÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ"
+ER_OUTOFMEMORY HY001 S1001
+ cze "M-Bálo pamìti. Pøestartujte daemona a zkuste znovu (je potøeba %d bytù)"
+ dan "Ikke mere hukommelse. Genstart serveren og prøv igen (mangler %d bytes)"
+ nla "Geen geheugen meer. Herstart server en probeer opnieuw (%d bytes nodig)"
+ eng "Out of memory; restart server and try again (needed %d bytes)"
+ jps "Out of memory. ƒf[ƒ‚ƒ“‚ðƒŠƒXƒ^[ƒg‚µ‚Ä‚Ý‚Ä‚­‚¾‚³‚¢ (%d bytes •K—v)",
+ est "Mälu sai otsa. Proovi MySQL uuesti käivitada (puudu jäi %d baiti)"
+ fre "Manque de mémoire. Redémarrez le démon et ré-essayez (%d octets nécessaires)"
+ ger "Kein Speicher vorhanden (%d Bytes benötigt). Bitte Server neu starten"
+ greek "Äåí õðÜñ÷åé äéáèÝóéìç ìíÞìç. ÐñïóðáèÞóôå ðÜëé, åðáíåêéíþíôáò ôç äéáäéêáóßá (demon) (÷ñåéÜæïíôáé %d bytes)"
+ hun "Nincs eleg memoria. Inditsa ujra a demont, es probalja ismet. (%d byte szukseges.)"
+ ita "Memoria esaurita. Fai ripartire il demone e riprova (richiesti %d bytes)"
+ jpn "Out of memory. ¥Ç¡¼¥â¥ó¤ò¥ê¥¹¥¿¡¼¥È¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤ (%d bytes ɬÍ×)"
+ kor "Out of memory. µ¥¸óÀ» Àç ½ÇÇà ÈÄ ´Ù½Ã ½ÃÀÛÇϽÿÀ (needed %d bytes)"
+ nor "Ikke mer minne. Star på nytt tjenesten og prøv igjen (trengte %d byter)"
+ norwegian-ny "Ikkje meir minne. Start på nytt tenesten og prøv igjen (trengte %d bytar)"
+ pol "Zbyt ma³o pamiêci. Uruchom ponownie demona i spróbuj ponownie (potrzeba %d bajtów)"
+ por "Sem memória. Reinicie o programa e tente novamente (necessita de %d bytes)"
+ rum "Out of memory. Porneste daemon-ul din nou si incearca inca o data (e nevoie de %d bytes)"
+ rus "îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ. ðÅÒÅÚÁÐÕÓÔÉÔÅ ÓÅÒ×ÅÒ É ÐÏÐÒÏÂÕÊÔÅ ÅÝÅ ÒÁÚ (ÎÕÖÎÏ %d ÂÁÊÔ)"
+ serbian "Nema memorije. Restartujte MySQL server i probajte ponovo (potrebno je %d byte-ova)"
+ slo "Málo pamäti. Re¹tartujte daemona a skúste znova (je potrebných %d bytov)"
+ spa "Memoria insuficiente. Reinicie el demonio e intentelo otra vez (necesita %d bytes)"
+ swe "Oväntat slut på minnet, starta om programmet och försök på nytt (Behövde %d bytes)"
+ ukr "âÒÁË ÐÁÍ'ÑÔ¦. òÅÓÔÁÒÔÕÊÔÅ ÓÅÒ×ÅÒ ÔÁ ÓÐÒÏÂÕÊÔÅ ÚÎÏ×Õ (ÐÏÔÒ¦ÂÎÏ %d ÂÁÊÔ¦×)"
+ER_OUT_OF_SORTMEMORY HY001 S1001
+ cze "M-Bálo pamìti pro tøídìní. Zvy¹te velikost tøídícího bufferu"
+ dan "Ikke mere sorteringshukommelse. Øg sorteringshukommelse (sort buffer size) for serveren"
+ nla "Geen geheugen om te sorteren. Verhoog de server sort buffer size"
+ eng "Out of sort memory; increase server sort buffer size"
+ jps "Out of sort memory. sort buffer size ‚ª‘«‚è‚È‚¢‚悤‚Å‚·.",
+ est "Mälu sai sorteerimisel otsa. Suurenda MySQL-i sorteerimispuhvrit"
+ fre "Manque de mémoire pour le tri. Augmentez-la."
+ ger "Kein Speicher zum Sortieren vorhanden. sort_buffer_size sollte erhöht werden"
+ greek "Äåí õðÜñ÷åé äéáèÝóéìç ìíÞìç ãéá ôáîéíüìéóç. ÁõîÞóôå ôï sort buffer size ãéá ôç äéáäéêáóßá (demon)"
+ hun "Nincs eleg memoria a rendezeshez. Novelje a rendezo demon puffermeretet"
+ ita "Memoria per gli ordinamenti esaurita. Incrementare il 'sort_buffer' al demone"
+ jpn "Out of sort memory. sort buffer size ¤¬Â­¤ê¤Ê¤¤¤è¤¦¤Ç¤¹."
+ kor "Out of sort memory. daemon sort bufferÀÇ Å©±â¸¦ Áõ°¡½ÃÅ°¼¼¿ä"
+ nor "Ikke mer sorteringsminne. Øk sorteringsminnet (sort buffer size) for tjenesten"
+ norwegian-ny "Ikkje meir sorteringsminne. Auk sorteringsminnet (sorteringsbffer storleik) for tenesten"
+ pol "Zbyt ma³o pamiêci dla sortowania. Zwiêksz wielko?æ bufora demona dla sortowania"
+ por "Sem memória para ordenação. Aumente tamanho do 'buffer' de ordenação"
+ rum "Out of memory pentru sortare. Largeste marimea buffer-ului pentru sortare in daemon (sort buffer size)"
+ rus "îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ ÄÌÑ ÓÏÒÔÉÒÏ×ËÉ. õ×ÅÌÉÞØÔÅ ÒÁÚÍÅÒ ÂÕÆÅÒÁ ÓÏÒÔÉÒÏ×ËÉ ÎÁ ÓÅÒ×ÅÒÅ"
+ serbian "Nema memorije za sortiranje. Poveæajte velièinu sort buffer-a MySQL server-u"
+ slo "Málo pamäti pre triedenie, zvý¹te veµkos» triediaceho bufferu"
+ spa "Memoria de ordenacion insuficiente. Incremente el tamano del buffer de ordenacion"
+ swe "Sorteringsbufferten räcker inte till. Kontrollera startparametrarna"
+ ukr "âÒÁË ÐÁÍ'ÑÔ¦ ÄÌÑ ÓÏÒÔÕ×ÁÎÎÑ. ôÒÅÂÁ Ú¦ÌØÛÉÔÉ ÒÏÚÍ¦Ò ÂÕÆÅÒÁ ÓÏÒÔÕ×ÁÎÎÑ Õ ÓÅÒ×ÅÒÁ"
+ER_UNEXPECTED_EOF
+ cze "Neo-Bèekávaný konec souboru pøi ètení '%-.64s' (chybový kód: %d)"
+ dan "Uventet afslutning på fil (eof) ved læsning af filen '%-.64s' (Fejlkode: %d)"
+ nla "Onverwachte eof gevonden tijdens het lezen van file '%-.64s' (Errcode: %d)"
+ eng "Unexpected EOF found when reading file '%-.64s' (errno: %d)"
+ jps "'%-.64s' ƒtƒ@ƒCƒ‹‚ð“Ç‚Ýž‚Ý’†‚É EOF ‚ª—\Šú‚¹‚ÊŠ‚ÅŒ»‚ê‚Ü‚µ‚½. (errno: %d)",
+ est "Ootamatu faililõpumärgend faili '%-.64s' lugemisel (veakood: %d)"
+ fre "Fin de fichier inattendue en lisant '%-.64s' (Errcode: %d)"
+ ger "Unerwartetes Ende beim Lesen der Datei '%-.64s' (Fehler: %d)"
+ greek "ÊáôÜ ôç äéÜñêåéá ôçò áíÜãíùóçò, âñÝèçêå áðñïóäüêçôá ôï ôÝëïò ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)"
+ hun "Varatlan filevege-jel a '%-.64s'olvasasakor. (hibakod: %d)"
+ ita "Fine del file inaspettata durante la lettura del file '%-.64s' (errno: %d)"
+ jpn "'%-.64s' ¥Õ¥¡¥¤¥ë¤òÆɤ߹þ¤ßÃæ¤Ë EOF ¤¬Í½´ü¤»¤Ì½ê¤Ç¸½¤ì¤Þ¤·¤¿. (errno: %d)"
+ kor "'%-.64s' È­ÀÏÀ» Àд µµÁß À߸øµÈ eofÀ» ¹ß°ß (¿¡·¯¹øÈ£: %d)"
+ nor "Uventet slutt på fil (eof) ved lesing av filen '%-.64s' (Feilkode: %d)"
+ norwegian-ny "Uventa slutt på fil (eof) ved lesing av fila '%-.64s' (Feilkode: %d)"
+ pol "Nieoczekiwany 'eof' napotkany podczas czytania z pliku '%-.64s' (Kod b³êdu: %d)"
+ por "Encontrado fim de arquivo inesperado ao ler arquivo '%-.64s' (erro no. %d)"
+ rum "Sfirsit de fisier neasteptat in citirea fisierului '%-.64s' (errno: %d)"
+ rus "îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ '%-.64s' (ÏÛÉÂËÁ: %d)"
+ serbian "Neoèekivani kraj pri èitanju file-a '%-.64s' (errno: %d)"
+ slo "Neoèakávaný koniec súboru pri èítaní '%-.64s' (chybový kód: %d)"
+ spa "Inesperado fin de ficheroU mientras leiamos el archivo '%-.64s' (Error: %d)"
+ swe "Oväntat filslut vid läsning från '%-.64s' (Felkod: %d)"
+ ukr "èÉÂÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ '%-.64s' (ÐÏÍÉÌËÁ: %d)"
+ER_CON_COUNT_ERROR 08004
+ cze "P-Bøíli¹ mnoho spojení"
+ dan "For mange forbindelser (connections)"
+ nla "Te veel verbindingen"
+ eng "Too many connections"
+ jps "Ú‘±‚ª‘½‚·‚¬‚Ü‚·",
+ est "Liiga palju samaaegseid ühendusi"
+ fre "Trop de connections"
+ ger "Zu viele Verbindungen"
+ greek "ÕðÜñ÷ïõí ðïëëÝò óõíäÝóåéò..."
+ hun "Tul sok kapcsolat"
+ ita "Troppe connessioni"
+ jpn "Àܳ¤¬Â¿¤¹¤®¤Þ¤¹"
+ kor "³Ê¹« ¸¹Àº ¿¬°á... max_connectionÀ» Áõ°¡ ½ÃÅ°½Ã¿À..."
+ nor "For mange tilkoblinger (connections)"
+ norwegian-ny "For mange tilkoplingar (connections)"
+ pol "Zbyt wiele po³?czeñ"
+ por "Excesso de conexões"
+ rum "Prea multe conectiuni"
+ rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÓÏÅÄÉÎÅÎÉÊ"
+ serbian "Previše konekcija"
+ slo "Príli¹ mnoho spojení"
+ spa "Demasiadas conexiones"
+ swe "För många anslutningar"
+ ukr "úÁÂÁÇÁÔÏ Ú'¤ÄÎÁÎØ"
+ER_OUT_OF_RESOURCES
+ cze "M-Bálo prostoru/pamìti pro thread"
+ dan "Udgået for tråde/hukommelse"
+ nla "Geen thread geheugen meer; controleer of mysqld of andere processen al het beschikbare geheugen gebruikt. Zo niet, dan moet u wellicht 'ulimit' gebruiken om mysqld toe te laten meer geheugen te benutten, of u kunt extra swap ruimte toevoegen"
+ eng "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"
+ jps "Out of memory; mysqld ‚©‚»‚Ì‘¼‚̃vƒƒZƒX‚ªƒƒ‚ƒŠ[‚ð‘S‚ÄŽg‚Á‚Ä‚¢‚é‚©Šm”F‚µ‚Ä‚­‚¾‚³‚¢. ƒƒ‚ƒŠ[‚ðŽg‚¢Ø‚Á‚Ä‚¢‚È‚¢ê‡A'ulimit' ‚ðݒ肵‚Ä mysqld ‚̃ƒ‚ƒŠ[Žg—pŒÀŠE—ʂ𑽂­‚·‚é‚©Aswap space ‚ð‘‚₵‚Ä‚Ý‚Ä‚­‚¾‚³‚¢",
+ est "Mälu sai otsa. Võimalik, et aitab swap-i lisamine või käsu 'ulimit' abil MySQL-le rohkema mälu kasutamise lubamine"
+ fre "Manque de 'threads'/mémoire"
+ ger "Kein Speicher mehr vorhanden. Prüfen Sie, ob mysqld oder ein anderer Prozess allen Speicher verbraucht. Wenn nicht, sollten Sie mit 'ulimit' dafür sorgen, dass mysqld mehr Speicher benutzen darf, oder mehr Swap-Speicher einrichten"
+ greek "Ðñüâëçìá ìå ôç äéáèÝóéìç ìíÞìç (Out of thread space/memory)"
+ hun "Elfogyott a thread-memoria"
+ ita "Fine dello spazio/memoria per i thread"
+ jpn "Out of memory; mysqld ¤«¤½¤Î¾¤Î¥×¥í¥»¥¹¤¬¥á¥â¥ê¡¼¤òÁ´¤Æ»È¤Ã¤Æ¤¤¤ë¤«³Îǧ¤·¤Æ¤¯¤À¤µ¤¤. ¥á¥â¥ê¡¼¤ò»È¤¤ÀڤäƤ¤¤Ê¤¤¾ì¹ç¡¢'ulimit' ¤òÀßÄꤷ¤Æ mysqld ¤Î¥á¥â¥ê¡¼»ÈÍѸ³¦Î̤ò¿¤¯¤¹¤ë¤«¡¢swap space ¤òÁý¤ä¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤"
+ kor "Out of memory; mysqld³ª ¶Ç´Ù¸¥ ÇÁ·Î¼¼¼­¿¡¼­ »ç¿ë°¡´ÉÇÑ ¸Þ¸ð¸®¸¦ »ç¿ëÇÑÁö äũÇϽÿÀ. ¸¸¾à ±×·¸Áö ¾Ê´Ù¸é ulimit ¸í·ÉÀ» ÀÌ¿¿ëÇÏ¿© ´õ¸¹Àº ¸Þ¸ð¸®¸¦ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï Çϰųª ½º¿Ò ½ºÆÐÀ̽º¸¦ Áõ°¡½ÃÅ°½Ã¿À"
+ nor "Tomt for tråd plass/minne"
+ norwegian-ny "Tomt for tråd plass/minne"
+ pol "Zbyt ma³o miejsca/pamiêci dla w?tku"
+ por "Sem memória. Verifique se o mysqld ou algum outro processo está usando toda memória disponível. Se não, você pode ter que usar 'ulimit' para permitir ao mysqld usar mais memória ou você pode adicionar mais área de 'swap'"
+ rum "Out of memory; Verifica daca mysqld sau vreun alt proces foloseste toate memoria disponbila. Altfel, trebuie sa folosesi 'ulimit' ca sa permiti lui memoria disponbila. Altfel, trebuie sa folosesi 'ulimit' ca sa permiti lui mysqld sa foloseasca mai multa memorie ori adauga mai mult spatiu pentru swap (swap space)"
+ rus "îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ; ÕÄÏÓÔÏ×ÅÒØÔÅÓØ, ÞÔÏ mysqld ÉÌÉ ËÁËÏÊ-ÌÉÂÏ ÄÒÕÇÏÊ ÐÒÏÃÅÓÓ ÎÅ ÚÁÎÉÍÁÅÔ ×ÓÀ ÄÏÓÔÕÐÎÕÀ ÐÁÍÑÔØ. åÓÌÉ ÎÅÔ, ÔÏ ×Ù ÍÏÖÅÔÅ ÉÓÐÏÌØÚÏ×ÁÔØ ulimit, ÞÔÏÂÙ ×ÙÄÅÌÉÔØ ÄÌÑ mysqld ÂÏÌØÛÅ ÐÁÍÑÔÉ, ÉÌÉ Õ×ÅÌÉÞÉÔØ ÏÂßÅÍ ÆÁÊÌÁ ÐÏÄËÁÞËÉ"
+ serbian "Nema memorije; Proverite da li MySQL server ili neki drugi proces koristi svu slobodnu memoriju. (UNIX: Ako ne, probajte da upotrebite 'ulimit' komandu da biste dozvolili daemon-u da koristi više memorije ili probajte da dodate više swap memorije)"
+ slo "Málo miesta-pamäti pre vlákno"
+ spa "Memoria/espacio de tranpaso insuficiente"
+ swe "Fick slut på minnet. Kontrollera om mysqld eller någon annan process använder allt tillgängligt minne. Om inte, försök använda 'ulimit' eller allokera mera swap"
+ ukr "âÒÁË ÐÁÍ'ÑÔ¦; ðÅÒÅצÒÔÅ ÞÉ mysqld ÁÂÏ Ñ˦ÓØ ¦ÎÛ¦ ÐÒÏÃÅÓÉ ×ÉËÏÒÉÓÔÏ×ÕÀÔØ ÕÓÀ ÄÏÓÔÕÐÎÕ ÐÁÍ'ÑÔØ. ñË Î¦, ÔÏ ×É ÍÏÖÅÔÅ ÓËÏÒÉÓÔÁÔÉÓÑ 'ulimit', ÁÂÉ ÄÏÚ×ÏÌÉÔÉ mysqld ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ Â¦ÌØÛÅ ÐÁÍ'ÑÔ¦ ÁÂÏ ×É ÍÏÖÅÔÅ ÄÏÄÁÔÉ Â¦ÌØÛŠͦÓÃÑ Ð¦Ä Ó×ÁÐ"
+ER_BAD_HOST_ERROR 08S01
+ cze "Nemohu zjistit jm-Béno stroje pro Va¹i adresu"
+ dan "Kan ikke få værtsnavn for din adresse"
+ nla "Kan de hostname niet krijgen van uw adres"
+ eng "Can't get hostname for your address"
+ jps "‚»‚Ì address ‚Ì hostname ‚ªˆø‚¯‚Ü‚¹‚ñ.",
+ est "Ei suuda lahendada IP aadressi masina nimeks"
+ fre "Ne peut obtenir de hostname pour votre adresse"
+ ger "Kann Hostnamen für diese Adresse nicht erhalten"
+ greek "Äåí Ýãéíå ãíùóôü ôï hostname ãéá ôçí address óáò"
+ hun "A gepnev nem allapithato meg a cimbol"
+ ita "Impossibile risalire al nome dell'host dall'indirizzo (risoluzione inversa)"
+ jpn "¤½¤Î address ¤Î hostname ¤¬°ú¤±¤Þ¤»¤ó."
+ kor "´ç½ÅÀÇ ÄÄÇ»ÅÍÀÇ È£½ºÆ®À̸§À» ¾òÀ» ¼ö ¾øÀ¾´Ï´Ù."
+ nor "Kan ikke få tak i vertsnavn for din adresse"
+ norwegian-ny "Kan ikkje få tak i vertsnavn for di adresse"
+ pol "Nie mo¿na otrzymaæ nazwy hosta dla twojego adresu"
+ por "Não pode obter nome do 'host' para seu endereço"
+ rum "Nu pot sa obtin hostname-ul adresei tale"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÉÍÑ ÈÏÓÔÁ ÄÌÑ ×ÁÛÅÇÏ ÁÄÒÅÓÁ"
+ serbian "Ne mogu da dobijem ime host-a za vašu IP adresu"
+ slo "Nemô¾em zisti» meno hostiteµa pre va¹u adresu"
+ spa "No puedo obtener el nombre de maquina de tu direccion"
+ swe "Kan inte hitta 'hostname' för din adress"
+ ukr "îÅ ÍÏÖÕ ×ÉÚÎÁÞÉÔÉ ¦Í'Ñ ÈÏÓÔÕ ÄÌÑ ×ÁÛϧ ÁÄÒÅÓÉ"
+ER_HANDSHAKE_ERROR 08S01
+ cze "Chyba p-Bøi ustavování spojení"
+ dan "Forkert håndtryk (handshake)"
+ nla "Verkeerde handshake"
+ eng "Bad handshake"
+ est "Väär handshake"
+ fre "Mauvais 'handshake'"
+ ger "Schlechter Handshake"
+ greek "Ç áíáãíþñéóç (handshake) äåí Ýãéíå óùóôÜ"
+ hun "A kapcsolatfelvetel nem sikerult (Bad handshake)"
+ ita "Negoziazione impossibile"
+ nor "Feil håndtrykk (handshake)"
+ norwegian-ny "Feil handtrykk (handshake)"
+ pol "Z³y uchwyt(handshake)"
+ por "Negociação de acesso falhou"
+ rum "Prost inceput de conectie (bad handshake)"
+ rus "îÅËÏÒÒÅËÔÎÏÅ ÐÒÉ×ÅÔÓÔ×ÉÅ"
+ serbian "Loš poèetak komunikacije (handshake)"
+ slo "Chyba pri nadväzovaní spojenia"
+ spa "Protocolo erroneo"
+ swe "Fel vid initiering av kommunikationen med klienten"
+ ukr "îÅצÒÎÁ ÕÓÔÁÎÏ×ËÁ Ú×'ÑÚËÕ"
+ER_DBACCESS_DENIED_ERROR 42000
+ cze "P-Bøístup pro u¾ivatele '%-.32s'@'%-.64s' k databázi '%-.64s' není povolen"
+ dan "Adgang nægtet bruger: '%-.32s'@'%-.64s' til databasen '%-.64s'"
+ nla "Toegang geweigerd voor gebruiker: '%-.32s'@'%-.64s' naar database '%-.64s'"
+ eng "Access denied for user '%-.32s'@'%-.64s' to database '%-.64s'"
+ jps "ƒ†[ƒU[ '%-.32s'@'%-.64s' ‚Ì '%-.64s' ƒf[ƒ^ƒx[ƒX‚ւ̃AƒNƒZƒX‚ð‹‘”Û‚µ‚Ü‚·",
+ est "Ligipääs keelatud kasutajale '%-.32s'@'%-.64s' andmebaasile '%-.64s'"
+ fre "Accès refusé pour l'utilisateur: '%-.32s'@'@%-.64s'. Base '%-.64s'"
+ ger "Benutzer '%-.32s'@'%-.64s' hat keine Zugriffsberechtigung für Datenbank '%-.64s'"
+ greek "Äåí åðéôÝñåôáé ç ðñüóâáóç óôï ÷ñÞóôç: '%-.32s'@'%-.64s' óôç âÜóç äåäïìÝíùí '%-.64s'"
+ hun "A(z) '%-.32s'@'%-.64s' felhasznalo szamara tiltott eleres az '%-.64s' adabazishoz."
+ ita "Accesso non consentito per l'utente: '%-.32s'@'%-.64s' al database '%-.64s'"
+ jpn "¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ¤Î '%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥¢¥¯¥»¥¹¤òµñÈݤ·¤Þ¤¹"
+ kor "'%-.32s'@'%-.64s' »ç¿ëÀÚ´Â '%-.64s' µ¥ÀÌŸº£À̽º¿¡ Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù."
+ nor "Tilgang nektet for bruker: '%-.32s'@'%-.64s' til databasen '%-.64s' nektet"
+ norwegian-ny "Tilgang ikkje tillate for brukar: '%-.32s'@'%-.64s' til databasen '%-.64s' nekta"
+ por "Acesso negado para o usuário '%-.32s'@'%-.64s' ao banco de dados '%-.64s'"
+ rum "Acces interzis pentru utilizatorul: '%-.32s'@'%-.64s' la baza de date '%-.64s'"
+ rus "äÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s'@'%-.64s' ÄÏÓÔÕÐ Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.64s' ÚÁËÒÙÔ"
+ serbian "Pristup je zabranjen korisniku '%-.32s'@'%-.64s' za bazu '%-.64s'"
+ slo "Zakázaný prístup pre u¾ívateµa: '%-.32s'@'%-.64s' k databázi '%-.64s'"
+ spa "Acceso negado para usuario: '%-.32s'@'%-.64s' para la base de datos '%-.64s'"
+ swe "Användare '%-.32s'@'%-.64s' är ej berättigad att använda databasen %-.64s"
+ ukr "äÏÓÔÕÐ ÚÁÂÏÒÏÎÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ: '%-.32s'@'%-.64s' ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ '%-.64s'"
+ER_ACCESS_DENIED_ERROR 28000
+ cze "P-Bøístup pro u¾ivatele '%-.32s'@'%-.64s' (s heslem %s)"
+ dan "Adgang nægtet bruger: '%-.32s'@'%-.64s' (Bruger adgangskode: %s)"
+ nla "Toegang geweigerd voor gebruiker: '%-.32s'@'%-.64s' (Wachtwoord gebruikt: %s)"
+ eng "Access denied for user '%-.32s'@'%-.64s' (using password: %s)"
+ jps "ƒ†[ƒU[ '%-.32s'@'%-.64s' ‚ð‹‘”Û‚µ‚Ü‚·.uUsing password: %s)",
+ est "Ligipääs keelatud kasutajale '%-.32s'@'%-.64s' (kasutab parooli: %s)"
+ fre "Accès refusé pour l'utilisateur: '%-.32s'@'@%-.64s' (mot de passe: %s)"
+ ger "Benutzer '%-.32s'@'%-.64s' hat keine Zugriffsberechtigung (verwendetes Passwort: %-.64s)"
+ greek "Äåí åðéôÝñåôáé ç ðñüóâáóç óôï ÷ñÞóôç: '%-.32s'@'%-.64s' (÷ñÞóç password: %s)"
+ hun "A(z) '%-.32s'@'%-.64s' felhasznalo szamara tiltott eleres. (Hasznalja a jelszot: %s)"
+ ita "Accesso non consentito per l'utente: '%-.32s'@'%-.64s' (Password: %s)"
+ jpn "¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ¤òµñÈݤ·¤Þ¤¹.uUsing password: %s)"
+ kor "'%-.32s'@'%-.64s' »ç¿ëÀÚ´Â Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù. (using password: %s)"
+ nor "Tilgang nektet for bruker: '%-.32s'@'%-.64s' (Bruker passord: %s)"
+ norwegian-ny "Tilgang ikke tillate for brukar: '%-.32s'@'%-.64s' (Brukar passord: %s)"
+ por "Acesso negado para o usuário '%-.32s'@'%-.64s' (senha usada: %s)"
+ rum "Acces interzis pentru utilizatorul: '%-.32s'@'%-.64s' (Folosind parola: %s)"
+ rus "äÏÓÔÕÐ ÚÁËÒÙÔ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s'@'%-.64s' (ÂÙÌ ÉÓÐÏÌØÚÏ×ÁÎ ÐÁÒÏÌØ: %s)"
+ serbian "Pristup je zabranjen korisniku '%-.32s'@'%-.64s' (koristi lozinku: '%s')"
+ slo "Zakázaný prístup pre u¾ívateµa: '%-.32s'@'%-.64s' (pou¾itie hesla: %s)"
+ spa "Acceso negado para usuario: '%-.32s'@'%-.64s' (Usando clave: %s)"
+ swe "Användare '%-.32s'@'%-.64s' är ej berättigad att logga in (Använder lösen: %s)"
+ ukr "äÏÓÔÕÐ ÚÁÂÏÒÏÎÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ: '%-.32s'@'%-.64s' (÷ÉËÏÒÉÓÔÁÎÏ ÐÁÒÏÌØ: %s)"
+ER_NO_DB_ERROR 3D000
+ cze "Nebyla vybr-Bána ¾ádná databáze"
+ dan "Ingen database valgt"
+ nla "Geen database geselecteerd"
+ eng "No database selected"
+ jps "ƒf[ƒ^ƒx[ƒX‚ª‘I‘ð‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ.",
+ est "Andmebaasi ei ole valitud"
+ fre "Aucune base n'a été sélectionnée"
+ ger "Keine Datenbank ausgewählt"
+ greek "Äåí åðéëÝ÷èçêå âÜóç äåäïìÝíùí"
+ hun "Nincs kivalasztott adatbazis"
+ ita "Nessun database selezionato"
+ jpn "¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤Þ¤»¤ó."
+ kor "¼±ÅÃµÈ µ¥ÀÌŸº£À̽º°¡ ¾ø½À´Ï´Ù."
+ nor "Ingen database valgt"
+ norwegian-ny "Ingen database vald"
+ pol "Nie wybrano ¿adnej bazy danych"
+ por "Nenhum banco de dados foi selecionado"
+ rum "Nici o baza de data nu a fost selectata inca"
+ rus "âÁÚÁ ÄÁÎÎÙÈ ÎÅ ×ÙÂÒÁÎÁ"
+ serbian "Ni jedna baza nije selektovana"
+ slo "Nebola vybraná databáza"
+ spa "Base de datos no seleccionada"
+ swe "Ingen databas i användning"
+ ukr "âÁÚÕ ÄÁÎÎÉÈ ÎÅ ×ÉÂÒÁÎÏ"
+ER_UNKNOWN_COM_ERROR 08S01
+ cze "Nezn-Bámý pøíkaz"
+ dan "Ukendt kommando"
+ nla "Onbekend commando"
+ eng "Unknown command"
+ jps "‚»‚̃Rƒ}ƒ“ƒh‚͉½H",
+ est "Tundmatu käsk"
+ fre "Commande inconnue"
+ ger "Unbekannter Befehl"
+ greek "Áãíùóôç åíôïëÞ"
+ hun "Ervenytelen parancs"
+ ita "Comando sconosciuto"
+ jpn "¤½¤Î¥³¥Þ¥ó¥É¤Ï²¿¡©"
+ kor "¸í·É¾î°¡ ¹ºÁö ¸ð¸£°Ú¾î¿ä..."
+ nor "Ukjent kommando"
+ norwegian-ny "Ukjent kommando"
+ pol "Nieznana komenda"
+ por "Comando desconhecido"
+ rum "Comanda invalida"
+ rus "îÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ ËÏÍÍÕÎÉËÁÃÉÏÎÎÏÇÏ ÐÒÏÔÏËÏÌÁ"
+ serbian "Nepoznata komanda"
+ slo "Neznámy príkaz"
+ spa "Comando desconocido"
+ swe "Okänt commando"
+ ukr "îÅצÄÏÍÁ ËÏÍÁÎÄÁ"
+ER_BAD_NULL_ERROR 23000
+ cze "Sloupec '%-.64s' nem-Bù¾e být null"
+ dan "Kolonne '%-.64s' kan ikke være NULL"
+ nla "Kolom '%-.64s' kan niet null zijn"
+ eng "Column '%-.64s' cannot be null"
+ jps "Column '%-.64s' ‚Í null ‚É‚Í‚Å‚«‚È‚¢‚Ì‚Å‚·",
+ est "Tulp '%-.64s' ei saa omada nullväärtust"
+ fre "Le champ '%-.64s' ne peut être vide (null)"
+ ger "Feld '%-.64s' darf nicht NULL sein"
+ greek "Ôï ðåäßï '%-.64s' äåí ìðïñåß íá åßíáé êåíü (null)"
+ hun "A(z) '%-.64s' oszlop erteke nem lehet nulla"
+ ita "La colonna '%-.64s' non puo` essere nulla"
+ jpn "Column '%-.64s' ¤Ï null ¤Ë¤Ï¤Ç¤­¤Ê¤¤¤Î¤Ç¤¹"
+ kor "Ä®·³ '%-.64s'´Â ³Î(Null)ÀÌ µÇ¸é ¾ÈµË´Ï´Ù. "
+ nor "Kolonne '%-.64s' kan ikke vere null"
+ norwegian-ny "Kolonne '%-.64s' kan ikkje vere null"
+ pol "Kolumna '%-.64s' nie mo¿e byæ null"
+ por "Coluna '%-.64s' não pode ser vazia"
+ rum "Coloana '%-.64s' nu poate sa fie null"
+ rus "óÔÏÌÂÅà '%-.64s' ÎÅ ÍÏÖÅÔ ÐÒÉÎÉÍÁÔØ ×ÅÌÉÞÉÎÕ NULL"
+ serbian "Kolona '%-.64s' ne može biti NULL"
+ slo "Pole '%-.64s' nemô¾e by» null"
+ spa "La columna '%-.64s' no puede ser nula"
+ swe "Kolumn '%-.64s' får inte vara NULL"
+ ukr "óÔÏ×ÂÅÃØ '%-.64s' ÎÅ ÍÏÖÅ ÂÕÔÉ ÎÕÌØÏ×ÉÍ"
+ER_BAD_DB_ERROR 42000
+ cze "Nezn-Bámá databáze '%-.64s'"
+ dan "Ukendt database '%-.64s'"
+ nla "Onbekende database '%-.64s'"
+ eng "Unknown database '%-.64s'"
+ jps "'%-.64s' ‚È‚ñ‚ăf[ƒ^ƒx[ƒX‚Í’m‚è‚Ü‚¹‚ñ.",
+ est "Tundmatu andmebaas '%-.64s'"
+ fre "Base '%-.64s' inconnue"
+ ger "Unbekannte Datenbank '%-.64s'"
+ greek "Áãíùóôç âÜóç äåäïìÝíùí '%-.64s'"
+ hun "Ervenytelen adatbazis: '%-.64s'"
+ ita "Database '%-.64s' sconosciuto"
+ jpn "'%-.64s' ¤Ê¤ó¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÏÃΤê¤Þ¤»¤ó."
+ kor "µ¥ÀÌŸº£À̽º '%-.64s'´Â ¾Ë¼ö ¾øÀ½"
+ nor "Ukjent database '%-.64s'"
+ norwegian-ny "Ukjent database '%-.64s'"
+ pol "Nieznana baza danych '%-.64s'"
+ por "Banco de dados '%-.64s' desconhecido"
+ rum "Baza de data invalida '%-.64s'"
+ rus "îÅÉÚ×ÅÓÔÎÁÑ ÂÁÚÁ ÄÁÎÎÙÈ '%-.64s'"
+ serbian "Nepoznata baza '%-.64s'"
+ slo "Neznáma databáza '%-.64s'"
+ spa "Base de datos desconocida '%-.64s'"
+ swe "Okänd databas: '%-.64s'"
+ ukr "îÅצÄÏÍÁ ÂÁÚÁ ÄÁÎÎÉÈ '%-.64s'"
+ER_TABLE_EXISTS_ERROR 42S01
+ cze "Tabulka '%-.64s' ji-B¾ existuje"
+ dan "Tabellen '%-.64s' findes allerede"
+ nla "Tabel '%-.64s' bestaat al"
+ eng "Table '%-.64s' already exists"
+ jps "Table '%-.64s' ‚ÍŠù‚É‚ ‚è‚Ü‚·",
+ est "Tabel '%-.64s' juba eksisteerib"
+ fre "La table '%-.64s' existe déjà"
+ ger "Tabelle '%-.64s' bereits vorhanden"
+ greek "Ï ðßíáêáò '%-.64s' õðÜñ÷åé Þäç"
+ hun "A(z) '%-.64s' tabla mar letezik"
+ ita "La tabella '%-.64s' esiste gia`"
+ jpn "Table '%-.64s' ¤Ï´û¤Ë¤¢¤ê¤Þ¤¹"
+ kor "Å×À̺í '%-.64s'´Â ÀÌ¹Ì Á¸ÀçÇÔ"
+ nor "Tabellen '%-.64s' eksisterer allerede"
+ norwegian-ny "Tabellen '%-.64s' eksisterar allereide"
+ pol "Tabela '%-.64s' ju¿ istnieje"
+ por "Tabela '%-.64s' já existe"
+ rum "Tabela '%-.64s' exista deja"
+ rus "ôÁÂÌÉÃÁ '%-.64s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ"
+ serbian "Tabela '%-.64s' veæ postoji"
+ slo "Tabuµka '%-.64s' u¾ existuje"
+ spa "La tabla '%-.64s' ya existe"
+ swe "Tabellen '%-.64s' finns redan"
+ ukr "ôÁÂÌÉÃÑ '%-.64s' ×ÖÅ ¦ÓÎÕ¤"
+ER_BAD_TABLE_ERROR 42S02
+ cze "Nezn-Bámá tabulka '%-.100s'"
+ dan "Ukendt tabel '%-.100s'"
+ nla "Onbekende tabel '%-.100s'"
+ eng "Unknown table '%-.100s'"
+ jps "table '%-.100s' ‚Í‚ ‚è‚Ü‚¹‚ñ.",
+ est "Tundmatu tabel '%-.100s'"
+ fre "Table '%-.100s' inconnue"
+ ger "Unbekannte Tabelle '%-.100s'"
+ greek "Áãíùóôïò ðßíáêáò '%-.100s'"
+ hun "Ervenytelen tabla: '%-.100s'"
+ ita "Tabella '%-.100s' sconosciuta"
+ jpn "table '%-.100s' ¤Ï¤¢¤ê¤Þ¤»¤ó."
+ kor "Å×À̺í '%-.100s'´Â ¾Ë¼ö ¾øÀ½"
+ nor "Ukjent tabell '%-.100s'"
+ norwegian-ny "Ukjent tabell '%-.100s'"
+ pol "Nieznana tabela '%-.100s'"
+ por "Tabela '%-.100s' desconhecida"
+ rum "Tabela '%-.100s' este invalida"
+ rus "îÅÉÚ×ÅÓÔÎÁÑ ÔÁÂÌÉÃÁ '%-.100s'"
+ serbian "Nepoznata tabela '%-.100s'"
+ slo "Neznáma tabuµka '%-.100s'"
+ spa "Tabla '%-.100s' desconocida"
+ swe "Okänd tabell '%-.100s'"
+ ukr "îÅצÄÏÍÁ ÔÁÂÌÉÃÑ '%-.100s'"
+ER_NON_UNIQ_ERROR 23000
+ cze "Sloupec '%-.64s' v %s nen-Bí zcela jasný"
+ dan "Felt: '%-.64s' i tabel %s er ikke entydigt"
+ nla "Kolom: '%-.64s' in %s is niet eenduidig"
+ eng "Column '%-.64s' in %-.64s is ambiguous"
+ est "Väli '%-.64s' %-.64s-s ei ole ühene"
+ fre "Champ: '%-.64s' dans %s est ambigu"
+ ger "Spalte '%-.64s' in %-.64s ist nicht eindeutig"
+ greek "Ôï ðåäßï: '%-.64s' óå %-.64s äåí Ý÷åé êáèïñéóôåß"
+ hun "A(z) '%-.64s' oszlop %-.64s-ben ketertelmu"
+ ita "Colonna: '%-.64s' di %-.64s e` ambigua"
+ jpn "Column: '%-.64s' in %-.64s is ambiguous"
+ kor "Ä®·³: '%-.64s' in '%-.64s' ÀÌ ¸ðÈ£ÇÔ"
+ nor "Felt: '%-.64s' i tabell %s er ikke entydig"
+ norwegian-ny "Kolonne: '%-.64s' i tabell %s er ikkje eintydig"
+ pol "Kolumna: '%-.64s' w %s jest dwuznaczna"
+ por "Coluna '%-.64s' em '%-.64s' é ambígua"
+ rum "Coloana: '%-.64s' in %-.64s este ambigua"
+ rus "óÔÏÌÂÅÃ '%-.64s' × %-.64s ÚÁÄÁÎ ÎÅÏÄÎÏÚÎÁÞÎÏ"
+ serbian "Kolona '%-.64s' u %-.64s nije jedinstvena u kontekstu"
+ slo "Pole: '%-.64s' v %-.64s je nejasné"
+ spa "La columna: '%-.64s' en %s es ambigua"
+ swe "Kolumn '%-.64s' i %s är inte unik"
+ ukr "óÔÏ×ÂÅÃØ '%-.64s' Õ %-.64s ×ÉÚÎÁÞÅÎÉÊ ÎÅÏÄÎÏÚÎÁÞÎÏ"
+ER_SERVER_SHUTDOWN 08S01
+ cze "Prob-Bíhá ukonèování práce serveru"
+ dan "Database nedlukning er i gang"
+ nla "Bezig met het stoppen van de server"
+ eng "Server shutdown in progress"
+ jps "Server ‚ð shutdown ’†...",
+ est "Serveri seiskamine käib"
+ fre "Arrêt du serveur en cours"
+ ger "Der Server wird heruntergefahren"
+ greek "Åíáñîç äéáäéêáóßáò áðïóýíäåóçò ôïõ åîõðçñåôçôÞ (server shutdown)"
+ hun "A szerver leallitasa folyamatban"
+ ita "Shutdown del server in corso"
+ jpn "Server ¤ò shutdown Ãæ..."
+ kor "Server°¡ ¼Ë´Ù¿î ÁßÀÔ´Ï´Ù."
+ nor "Database nedkobling er i gang"
+ norwegian-ny "Tenar nedkopling er i gang"
+ pol "Trwa koñczenie dzia³ania serwera"
+ por "'Shutdown' do servidor em andamento"
+ rum "Terminarea serverului este in desfasurare"
+ rus "óÅÒ×ÅÒ ÎÁÈÏÄÉÔÓÑ × ÐÒÏÃÅÓÓÅ ÏÓÔÁÎÏ×ËÉ"
+ serbian "Gašenje servera je u toku"
+ slo "Prebieha ukonèovanie práce servera"
+ spa "Desconexion de servidor en proceso"
+ swe "Servern går nu ned"
+ ukr "úÁ×ÅÒÛÕ¤ÔØÓÑ ÒÁÂÏÔÁ ÓÅÒ×ÅÒÁ"
+ER_BAD_FIELD_ERROR 42S22 S0022
+ cze "Nezn-Bámý sloupec '%-.64s' v %s"
+ dan "Ukendt kolonne '%-.64s' i tabel %s"
+ nla "Onbekende kolom '%-.64s' in %s"
+ eng "Unknown column '%-.64s' in '%-.64s'"
+ jps "'%-.64s' column ‚Í '%-.64s' ‚É‚Í‚ ‚è‚Ü‚¹‚ñ.",
+ est "Tundmatu tulp '%-.64s' '%-.64s'-s"
+ fre "Champ '%-.64s' inconnu dans %s"
+ ger "Unbekanntes Tabellenfeld '%-.64s' in %-.64s"
+ greek "Áãíùóôï ðåäßï '%-.64s' óå '%-.64s'"
+ hun "A(z) '%-.64s' oszlop ervenytelen '%-.64s'-ben"
+ ita "Colonna sconosciuta '%-.64s' in '%-.64s'"
+ jpn "'%-.64s' column ¤Ï '%-.64s' ¤Ë¤Ï¤¢¤ê¤Þ¤»¤ó."
+ kor "Unknown Ä®·³ '%-.64s' in '%-.64s'"
+ nor "Ukjent kolonne '%-.64s' i tabell %s"
+ norwegian-ny "Ukjent felt '%-.64s' i tabell %s"
+ pol "Nieznana kolumna '%-.64s' w %s"
+ por "Coluna '%-.64s' desconhecida em '%-.64s'"
+ rum "Coloana invalida '%-.64s' in '%-.64s'"
+ rus "îÅÉÚ×ÅÓÔÎÙÊ ÓÔÏÌÂÅà '%-.64s' × '%-.64s'"
+ serbian "Nepoznata kolona '%-.64s' u '%-.64s'"
+ slo "Neznáme pole '%-.64s' v '%-.64s'"
+ spa "La columna '%-.64s' en %s es desconocida"
+ swe "Okänd kolumn '%-.64s' i %s"
+ ukr "îÅצÄÏÍÉÊ ÓÔÏ×ÂÅÃØ '%-.64s' Õ '%-.64s'"
+ER_WRONG_FIELD_WITH_GROUP 42000 S1009
+ cze "Pou-B¾ité '%-.64s' nebylo v group by"
+ dan "Brugte '%-.64s' som ikke var i group by"
+ nla "Opdracht gebruikt '%-.64s' dat niet in de GROUP BY voorkomt"
+ eng "'%-.64s' isn't in GROUP BY"
+ jps "'%-.64s' isn't in GROUP BY",
+ est "'%-.64s' puudub GROUP BY klauslis"
+ fre "'%-.64s' n'est pas dans 'group by'"
+ ger "'%-.64s' ist nicht in GROUP BY vorhanden"
+ greek "×ñçóéìïðïéÞèçêå '%-.64s' ðïõ äåí õðÞñ÷å óôï group by"
+ hun "Used '%-.64s' with wasn't in group by"
+ ita "Usato '%-.64s' che non e` nel GROUP BY"
+ kor "'%-.64s'Àº GROUP BY¼Ó¿¡ ¾øÀ½"
+ nor "Brukte '%-.64s' som ikke var i group by"
+ norwegian-ny "Brukte '%-.64s' som ikkje var i group by"
+ pol "U¿yto '%-.64s' bez umieszczenia w group by"
+ por "'%-.64s' não está em 'GROUP BY'"
+ rum "'%-.64s' nu exista in clauza GROUP BY"
+ rus "'%-.64s' ÎÅ ÐÒÉÓÕÔÓÔ×ÕÅÔ × GROUP BY"
+ serbian "Entitet '%-.64s' nije naveden u komandi 'GROUP BY'"
+ slo "Pou¾ité '%-.64s' nebolo v 'group by'"
+ spa "Usado '%-.64s' el cual no esta group by"
+ swe "'%-.64s' finns inte i GROUP BY"
+ ukr "'%-.64s' ÎÅ ¤ Õ GROUP BY"
+ER_WRONG_GROUP_FIELD 42000 S1009
+ cze "Nemohu pou-B¾ít group na '%-.64s'"
+ dan "Kan ikke gruppere på '%-.64s'"
+ nla "Kan '%-.64s' niet groeperen"
+ eng "Can't group on '%-.64s'"
+ est "Ei saa grupeerida '%-.64s' järgi"
+ fre "Ne peut regrouper '%-.64s'"
+ ger "Gruppierung über '%-.64s' nicht möglich"
+ greek "Áäýíáôç ç ïìáäïðïßçóç (group on) '%-.64s'"
+ hun "A group nem hasznalhato: '%-.64s'"
+ ita "Impossibile raggruppare per '%-.64s'"
+ kor "'%-.64s'¸¦ ±×·ìÇÒ ¼ö ¾øÀ½"
+ nor "Kan ikke gruppere på '%-.64s'"
+ norwegian-ny "Kan ikkje gruppere på '%-.64s'"
+ pol "Nie mo¿na grupowaæ po '%-.64s'"
+ por "Não pode agrupar em '%-.64s'"
+ rum "Nu pot sa grupez pe (group on) '%-.64s'"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÉÚ×ÅÓÔÉ ÇÒÕÐÐÉÒÏ×ËÕ ÐÏ '%-.64s'"
+ serbian "Ne mogu da grupišem po '%-.64s'"
+ slo "Nemô¾em pou¾i» 'group' na '%-.64s'"
+ spa "No puedo agrupar por '%-.64s'"
+ swe "Kan inte använda GROUP BY med '%-.64s'"
+ ukr "îÅ ÍÏÖÕ ÇÒÕÐÕ×ÁÔÉ ÐÏ '%-.64s'"
+ER_WRONG_SUM_SELECT 42000 S1009
+ cze "P-Bøíkaz obsahuje zároveò funkci sum a sloupce"
+ dan "Udtrykket har summer (sum) funktioner og kolonner i samme udtryk"
+ nla "Opdracht heeft totaliseer functies en kolommen in dezelfde opdracht"
+ eng "Statement has sum functions and columns in same statement"
+ est "Lauses on korraga nii tulbad kui summeerimisfunktsioonid"
+ fre "Vous demandez la fonction sum() et des champs dans la même commande"
+ ger "Die Verwendung von Summierungsfunktionen und Spalten im selben Befehl ist nicht erlaubt"
+ greek "Ç äéáôýðùóç ðåñéÝ÷åé sum functions êáé columns óôçí ßäéá äéáôýðùóç"
+ ita "Il comando ha una funzione SUM e una colonna non specificata nella GROUP BY"
+ kor "Statement °¡ sum±â´ÉÀ» µ¿ÀÛÁßÀÌ°í Ä®·³µµ µ¿ÀÏÇÑ statementÀÔ´Ï´Ù."
+ nor "Uttrykket har summer (sum) funksjoner og kolonner i samme uttrykk"
+ norwegian-ny "Uttrykket har summer (sum) funksjoner og kolonner i same uttrykk"
+ pol "Zapytanie ma funkcje sumuj?ce i kolumny w tym samym zapytaniu"
+ por "Cláusula contém funções de soma e colunas juntas"
+ rum "Comanda are functii suma si coloane in aceeasi comanda"
+ rus "÷ÙÒÁÖÅÎÉÅ ÓÏÄÅÒÖÉÔ ÇÒÕÐÐÏ×ÙÅ ÆÕÎËÃÉÉ É ÓÔÏÌÂÃÙ, ÎÏ ÎÅ ×ËÌÀÞÁÅÔ GROUP BY. á ËÁË ×Ù ÕÍÕÄÒÉÌÉÓØ ÐÏÌÕÞÉÔØ ÜÔÏ ÓÏÏÂÝÅÎÉÅ Ï ÏÛÉÂËÅ?"
+ serbian "Izraz ima 'SUM' agregatnu funkciju i kolone u isto vreme"
+ slo "Príkaz obsahuje zároveò funkciu 'sum' a poµa"
+ spa "El estamento tiene funciones de suma y columnas en el mismo estamento"
+ swe "Kommandot har både sum functions och enkla funktioner"
+ ukr "õ ×ÉÒÁÚ¦ ×ÉËÏÒÉÓÔÁÎÏ Ð¦ÄÓÕÍÏ×ÕÀÞ¦ ÆÕÎËæ§ ÐÏÒÑÄ Ú ¦ÍÅÎÁÍÉ ÓÔÏ×Âæ×"
+ER_WRONG_VALUE_COUNT 21S01
+ cze "Po-Bèet sloupcù neodpovídá zadané hodnotì"
+ dan "Kolonne tæller stemmer ikke med antallet af værdier"
+ nla "Het aantal kolommen komt niet overeen met het aantal opgegeven waardes"
+ eng "Column count doesn't match value count"
+ est "Tulpade arv erineb väärtuste arvust"
+ ger "Die Anzahl der Spalten entspricht nicht der Anzahl der Werte"
+ greek "Ôï Column count äåí ôáéñéÜæåé ìå ôï value count"
+ hun "Az oszlopban levo ertek nem egyezik meg a szamitott ertekkel"
+ ita "Il numero delle colonne non e` uguale al numero dei valori"
+ kor "Ä®·³ÀÇ Ä«¿îÆ®°¡ °ªÀÇ Ä«¿îÆ®¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù."
+ nor "Felt telling stemmer verdi telling"
+ norwegian-ny "Kolonne telling stemmer verdi telling"
+ pol "Liczba kolumn nie odpowiada liczbie warto?ci"
+ por "Contagem de colunas não confere com a contagem de valores"
+ rum "Numarul de coloane nu este acelasi cu numarul valoarei"
+ rus "ëÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ× ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ËÏÌÉÞÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ"
+ serbian "Broj kolona ne odgovara broju vrednosti"
+ slo "Poèet polí nezodpovedá zadanej hodnote"
+ spa "La columna con count no tiene valores para contar"
+ swe "Antalet kolumner motsvarar inte antalet värden"
+ ukr "ë¦ÌØ˦ÓÔØ ÓÔÏ×ÂÃ¦× ÎÅ ÓЦ×ÐÁÄÁ¤ Ú Ë¦ÌØ˦ÓÔÀ ÚÎÁÞÅÎØ"
+ER_TOO_LONG_IDENT 42000 S1009
+ cze "Jm-Béno identifikátoru '%-.64s' je pøíli¹ dlouhé"
+ dan "Navnet '%-.64s' er for langt"
+ nla "Naam voor herkenning '%-.64s' is te lang"
+ eng "Identifier name '%-.100s' is too long"
+ jps "Identifier name '%-.100s' ‚Í’·‚·‚¬‚Ü‚·",
+ est "Identifikaatori '%-.100s' nimi on liiga pikk"
+ fre "Le nom de l'identificateur '%-.64s' est trop long"
+ ger "Name des Bezeichners '%-.64s' ist zu lang"
+ greek "Ôï identifier name '%-.100s' åßíáé ðïëý ìåãÜëï"
+ hun "A(z) '%-.100s' azonositonev tul hosszu."
+ ita "Il nome dell'identificatore '%-.100s' e` troppo lungo"
+ jpn "Identifier name '%-.100s' ¤ÏŤ¹¤®¤Þ¤¹"
+ kor "Identifier '%-.100s'´Â ³Ê¹« ±æ±º¿ä."
+ nor "Identifikator '%-.64s' er for lang"
+ norwegian-ny "Identifikator '%-.64s' er for lang"
+ pol "Nazwa identyfikatora '%-.64s' jest zbyt d³uga"
+ por "Nome identificador '%-.100s' é longo demais"
+ rum "Numele indentificatorului '%-.100s' este prea lung"
+ rus "óÌÉÛËÏÍ ÄÌÉÎÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ '%-.100s'"
+ serbian "Ime '%-.100s' je predugaèko"
+ slo "Meno identifikátora '%-.100s' je príli¹ dlhé"
+ spa "El nombre del identificador '%-.64s' es demasiado grande"
+ swe "Kolumnnamn '%-.64s' är för långt"
+ ukr "¶Í'Ñ ¦ÄÅÎÔÉƦËÁÔÏÒÁ '%-.100s' ÚÁÄÏ×ÇÅ"
+ER_DUP_FIELDNAME 42S21 S1009
+ cze "Zdvojen-Bé jméno sloupce '%-.64s'"
+ dan "Feltnavnet '%-.64s' findes allerede"
+ nla "Dubbele kolom naam '%-.64s'"
+ eng "Duplicate column name '%-.64s'"
+ jps "'%-.64s' ‚Æ‚¢‚¤ column –¼‚Íd•¡‚µ‚Ä‚Ü‚·",
+ est "Kattuv tulba nimi '%-.64s'"
+ fre "Nom du champ '%-.64s' déjà utilisé"
+ ger "Doppelter Spaltenname vorhanden: '%-.64s'"
+ greek "ÅðáíÜëçøç column name '%-.64s'"
+ hun "Duplikalt oszlopazonosito: '%-.64s'"
+ ita "Nome colonna duplicato '%-.64s'"
+ jpn "'%-.64s' ¤È¤¤¤¦ column ̾¤Ï½ÅÊ£¤·¤Æ¤Þ¤¹"
+ kor "Áߺ¹µÈ Ä®·³ À̸§: '%-.64s'"
+ nor "Feltnavnet '%-.64s' eksisterte fra før"
+ norwegian-ny "Feltnamnet '%-.64s' eksisterte frå før"
+ pol "Powtórzona nazwa kolumny '%-.64s'"
+ por "Nome da coluna '%-.64s' duplicado"
+ rum "Numele coloanei '%-.64s' e duplicat"
+ rus "äÕÂÌÉÒÕÀÝÅÅÓÑ ÉÍÑ ÓÔÏÌÂÃÁ '%-.64s'"
+ serbian "Duplirano ime kolone '%-.64s'"
+ slo "Opakované meno poµa '%-.64s'"
+ spa "Nombre de columna duplicado '%-.64s'"
+ swe "Kolumnnamn '%-.64s finns flera gånger"
+ ukr "äÕÂÌÀÀÞÅ ¦Í'Ñ ÓÔÏ×ÂÃÑ '%-.64s'"
+ER_DUP_KEYNAME 42000 S1009
+ cze "Zdvojen-Bé jméno klíèe '%-.64s'"
+ dan "Indeksnavnet '%-.64s' findes allerede"
+ nla "Dubbele zoeksleutel naam '%-.64s'"
+ eng "Duplicate key name '%-.64s'"
+ jps "'%-.64s' ‚Æ‚¢‚¤ key ‚Ì–¼‘O‚Íd•¡‚µ‚Ä‚¢‚Ü‚·",
+ est "Kattuv võtme nimi '%-.64s'"
+ fre "Nom de clef '%-.64s' déjà utilisé"
+ ger "Doppelter Name für Schlüssel (Key) vorhanden: '%-.64s'"
+ greek "ÅðáíÜëçøç key name '%-.64s'"
+ hun "Duplikalt kulcsazonosito: '%-.64s'"
+ ita "Nome chiave duplicato '%-.64s'"
+ jpn "'%-.64s' ¤È¤¤¤¦ key ¤Î̾Á°¤Ï½ÅÊ£¤·¤Æ¤¤¤Þ¤¹"
+ kor "Áߺ¹µÈ Å° À̸§ : '%-.64s'"
+ nor "Nøkkelnavnet '%-.64s' eksisterte fra før"
+ norwegian-ny "Nøkkelnamnet '%-.64s' eksisterte frå før"
+ pol "Powtórzony nazwa klucza '%-.64s'"
+ por "Nome da chave '%-.64s' duplicado"
+ rum "Numele cheiei '%-.64s' e duplicat"
+ rus "äÕÂÌÉÒÕÀÝÅÅÓÑ ÉÍÑ ËÌÀÞÁ '%-.64s'"
+ serbian "Duplirano ime kljuèa '%-.64s'"
+ slo "Opakované meno kµúèa '%-.64s'"
+ spa "Nombre de clave duplicado '%-.64s'"
+ swe "Nyckelnamn '%-.64s' finns flera gånger"
+ ukr "äÕÂÌÀÀÞÅ ¦Í'Ñ ËÌÀÞÁ '%-.64s'"
+ER_DUP_ENTRY 23000 S1009
+ cze "Zvojen-Bý klíè '%-.64s' (èíslo klíèe %d)"
+ dan "Ens værdier '%-.64s' for indeks %d"
+ nla "Dubbele ingang '%-.64s' voor zoeksleutel %d"
+ eng "Duplicate entry '%-.64s' for key %d"
+ jps "'%-.64s' ‚Í key %d ‚É‚¨‚¢‚Äd•¡‚µ‚Ä‚¢‚Ü‚·",
+ est "Kattuv väärtus '%-.64s' võtmele %d"
+ fre "Duplicata du champ '%-.64s' pour la clef %d"
+ ger "Doppelter Eintrag '%-.64s' für Schlüssel %d"
+ greek "ÄéðëÞ åããñáöÞ '%-.64s' ãéá ôï êëåéäß %d"
+ hun "Duplikalt bejegyzes '%-.64s' a %d kulcs szerint."
+ ita "Valore duplicato '%-.64s' per la chiave %d"
+ jpn "'%-.64s' ¤Ï key %d ¤Ë¤ª¤¤¤Æ½ÅÊ£¤·¤Æ¤¤¤Þ¤¹"
+ kor "Áߺ¹µÈ ÀÔ·Â °ª '%-.64s': key %d"
+ nor "Like verdier '%-.64s' for nøkkel %d"
+ norwegian-ny "Like verdiar '%-.64s' for nykkel %d"
+ pol "Powtórzone wyst?pienie '%-.64s' dla klucza %d"
+ por "Entrada '%-.64s' duplicada para a chave %d"
+ rum "Cimpul '%-.64s' e duplicat pentru cheia %d"
+ rus "äÕÂÌÉÒÕÀÝÁÑÓÑ ÚÁÐÉÓØ '%-.64s' ÐÏ ËÌÀÞÕ %d"
+ serbian "Dupliran unos '%-.64s' za kljuè '%d'"
+ slo "Opakovaný kµúè '%-.64s' (èíslo kµúèa %d)"
+ spa "Entrada duplicada '%-.64s' para la clave %d"
+ swe "Dubbel nyckel '%-.64s' för nyckel %d"
+ ukr "äÕÂÌÀÀÞÉÊ ÚÁÐÉÓ '%-.64s' ÄÌÑ ËÌÀÞÁ %d"
+ER_WRONG_FIELD_SPEC 42000 S1009
+ cze "Chybn-Bá specifikace sloupce '%-.64s'"
+ dan "Forkert kolonnespecifikaton for felt '%-.64s'"
+ nla "Verkeerde kolom specificatie voor kolom '%-.64s'"
+ eng "Incorrect column specifier for column '%-.64s'"
+ est "Vigane tulba kirjeldus tulbale '%-.64s'"
+ fre "Mauvais paramètre de champ pour le champ '%-.64s'"
+ ger "Falsche Spaltenangaben für Spalte '%-.64s'"
+ greek "ÅóöáëìÝíï column specifier ãéá ôï ðåäßï '%-.64s'"
+ hun "Rossz oszlopazonosito: '%-.64s'"
+ ita "Specifica errata per la colonna '%-.64s'"
+ kor "Ä®·³ '%-.64s'ÀÇ ºÎÁ¤È®ÇÑ Ä®·³ Á¤ÀÇÀÚ"
+ nor "Feil kolonne spesifikator for felt '%-.64s'"
+ norwegian-ny "Feil kolonne spesifikator for kolonne '%-.64s'"
+ pol "B³êdna specyfikacja kolumny dla kolumny '%-.64s'"
+ por "Especificador de coluna incorreto para a coluna '%-.64s'"
+ rum "Specificandul coloanei '%-.64s' este incorect"
+ rus "îÅËÏÒÒÅËÔÎÙÊ ÏÐÒÅÄÅÌÉÔÅÌØ ÓÔÏÌÂÃÁ ÄÌÑ ÓÔÏÌÂÃÁ '%-.64s'"
+ serbian "Pogrešan naziv kolone za kolonu '%-.64s'"
+ slo "Chyba v ¹pecifikácii poµa '%-.64s'"
+ spa "Especificador de columna erroneo para la columna '%-.64s'"
+ swe "Felaktigt kolumntyp för kolumn '%-.64s'"
+ ukr "îÅצÒÎÉÊ ÓÐÅÃÉƦËÁÔÏÒ ÓÔÏ×ÂÃÑ '%-.64s'"
+ER_PARSE_ERROR 42000
+ cze "%s bl-Bízko '%-.64s' na øádku %d"
+ dan "%s nær '%-.64s' på linje %d"
+ nla "%s bij '%-.64s' in regel %d"
+ eng "%s near '%-.80s' at line %d"
+ jps "%s : '%-.80s' •t‹ß : %d s–Ú",
+ est "%s '%-.80s' ligidal real %d"
+ fre "%s près de '%-.64s' à la ligne %d"
+ ger "%s bei '%-.80s' in Zeile %d"
+ greek "%s ðëçóßïí '%-.80s' óôç ãñáììÞ %d"
+ hun "A %s a '%-.80s'-hez kozeli a %d sorban"
+ ita "%s vicino a '%-.80s' linea %d"
+ jpn "%s : '%-.80s' ÉÕ¶á : %d ¹ÔÌÜ"
+ kor "'%-.64s' ¿¡·¯ °°À¾´Ï´Ù. ('%-.80s' ¸í·É¾î ¶óÀÎ %d)"
+ nor "%s nær '%-.64s' på linje %d"
+ norwegian-ny "%s attmed '%-.64s' på line %d"
+ pol "%s obok '%-.64s' w linii %d"
+ por "%s próximo a '%-.80s' na linha %d"
+ rum "%s linga '%-.80s' pe linia %d"
+ rus "%s ÏËÏÌÏ '%-.80s' ÎÁ ÓÔÒÏËÅ %d"
+ serbian "'%s' u iskazu '%-.80s' na liniji %d"
+ slo "%s blízko '%-.80s' na riadku %d"
+ spa "%s cerca '%-.64s' en la linea %d"
+ swe "%s nära '%-.64s' på rad %d"
+ ukr "%s ¦ÌÑ '%-.80s' × ÓÔÒÏæ %d"
+ER_EMPTY_QUERY 42000
+ cze "V-Býsledek dotazu je prázdný"
+ dan "Forespørgsel var tom"
+ nla "Query was leeg"
+ eng "Query was empty"
+ jps "Query ‚ª‹ó‚Å‚·.",
+ est "Tühi päring"
+ fre "Query est vide"
+ ger "Leere Abfrage"
+ greek "Ôï åñþôçìá (query) ðïõ èÝóáôå Þôáí êåíü"
+ hun "Ures lekerdezes."
+ ita "La query e` vuota"
+ jpn "Query ¤¬¶õ¤Ç¤¹."
+ kor "Äõ¸®°á°ú°¡ ¾ø½À´Ï´Ù."
+ nor "Forespørsel var tom"
+ norwegian-ny "Førespurnad var tom"
+ pol "Zapytanie by³o puste"
+ por "Consulta (query) estava vazia"
+ rum "Query-ul a fost gol"
+ rus "úÁÐÒÏÓ ÏËÁÚÁÌÓÑ ÐÕÓÔÙÍ"
+ serbian "Upit je bio prazan"
+ slo "Výsledok po¾iadavky bol prázdny"
+ spa "La query estaba vacia"
+ swe "Frågan var tom"
+ ukr "ðÕÓÔÉÊ ÚÁÐÉÔ"
+ER_NONUNIQ_TABLE 42000 S1009
+ cze "Nejednozna-Bèná tabulka/alias: '%-.64s'"
+ dan "Tabellen/aliaset: '%-.64s' er ikke unikt"
+ nla "Niet unieke waarde tabel/alias: '%-.64s'"
+ eng "Not unique table/alias: '%-.64s'"
+ jps "'%-.64s' ‚͈êˆÓ‚Ì table/alias –¼‚Å‚Í‚ ‚è‚Ü‚¹‚ñ",
+ est "Ei ole unikaalne tabel/alias '%-.64s'"
+ fre "Table/alias: '%-.64s' non unique"
+ ger "Tabellenname/Alias '%-.64s' nicht eindeutig"
+ greek "Áäýíáôç ç áíåýñåóç unique table/alias: '%-.64s'"
+ hun "Nem egyedi tabla/alias: '%-.64s'"
+ ita "Tabella/alias non unico: '%-.64s'"
+ jpn "'%-.64s' ¤Ï°ì°Õ¤Î table/alias ̾¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+ kor "Unique ÇÏÁö ¾ÊÀº Å×À̺í/alias: '%-.64s'"
+ nor "Ikke unikt tabell/alias: '%-.64s'"
+ norwegian-ny "Ikkje unikt tabell/alias: '%-.64s'"
+ pol "Tabela/alias nie s? unikalne: '%-.64s'"
+ por "Tabela/alias '%-.64s' não única"
+ rum "Tabela/alias: '%-.64s' nu este unic"
+ rus "ðÏ×ÔÏÒÑÀÝÁÑÓÑ ÔÁÂÌÉÃÁ/ÐÓÅ×ÄÏÎÉÍ '%-.64s'"
+ serbian "Tabela ili alias nisu bili jedinstveni: '%-.64s'"
+ slo "Nie jednoznaèná tabuµka/alias: '%-.64s'"
+ spa "Tabla/alias: '%-.64s' es no unica"
+ swe "Icke unikt tabell/alias: '%-.64s'"
+ ukr "îÅÕΦËÁÌØÎÁ ÔÁÂÌÉÃÑ/ÐÓÅ×ÄÏΦÍ: '%-.64s'"
+ER_INVALID_DEFAULT 42000 S1009
+ cze "Chybn-Bá defaultní hodnota pro '%-.64s'"
+ dan "Ugyldig standardværdi for '%-.64s'"
+ nla "Foutieve standaard waarde voor '%-.64s'"
+ eng "Invalid default value for '%-.64s'"
+ est "Vigane vaikeväärtus '%-.64s' jaoks"
+ fre "Valeur par défaut invalide pour '%-.64s'"
+ ger "Fehlerhafter Vorgabewert (DEFAULT): '%-.64s'"
+ greek "ÅóöáëìÝíç ðñïêáèïñéóìÝíç ôéìÞ (default value) ãéá '%-.64s'"
+ hun "Ervenytelen ertek: '%-.64s'"
+ ita "Valore di default non valido per '%-.64s'"
+ kor "'%-.64s'ÀÇ À¯È¿ÇÏÁö ¸øÇÑ µðÆúÆ® °ªÀ» »ç¿ëÇϼ̽À´Ï´Ù."
+ nor "Ugyldig standardverdi for '%-.64s'"
+ norwegian-ny "Ugyldig standardverdi for '%-.64s'"
+ pol "Niew³a?ciwa warto?æ domy?lna dla '%-.64s'"
+ por "Valor padrão (default) inválido para '%-.64s'"
+ rum "Valoarea de default este invalida pentru '%-.64s'"
+ rus "îÅËÏÒÒÅËÔÎÏÅ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ '%-.64s'"
+ serbian "Loša default vrednost za '%-.64s'"
+ slo "Chybná implicitná hodnota pre '%-.64s'"
+ spa "Valor por defecto invalido para '%-.64s'"
+ swe "Ogiltigt DEFAULT värde för '%-.64s'"
+ ukr "îÅצÒÎÅ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ ÄÌÑ '%-.64s'"
+ER_MULTIPLE_PRI_KEY 42000 S1009
+ cze "Definov-Báno více primárních klíèù"
+ dan "Flere primærnøgler specificeret"
+ nla "Meerdere primaire zoeksleutels gedefinieerd"
+ eng "Multiple primary key defined"
+ jps "•¡”‚Ì primary key ‚ª’è‹`‚³‚ê‚Ü‚µ‚½",
+ est "Mitut primaarset võtit ei saa olla"
+ fre "Plusieurs clefs primaires définies"
+ ger "Mehrfacher Primärschlüssel (PRIMARY KEY) definiert"
+ greek "Ðåñéóóüôåñá áðü Ýíá primary key ïñßóôçêáí"
+ hun "Tobbszoros elsodleges kulcs definialas."
+ ita "Definite piu` chiave primarie"
+ jpn "Ê£¿ô¤Î primary key ¤¬ÄêµÁ¤µ¤ì¤Þ¤·¤¿"
+ kor "Multiple primary key°¡ Á¤ÀǵǾî ÀÖ½¿"
+ nor "Fleire primærnøkle spesifisert"
+ norwegian-ny "Fleire primærnyklar spesifisert"
+ pol "Zdefiniowano wiele kluczy podstawowych"
+ por "Definida mais de uma chave primária"
+ rum "Chei primare definite de mai multe ori"
+ rus "õËÁÚÁÎÏ ÎÅÓËÏÌØËÏ ÐÅÒ×ÉÞÎÙÈ ËÌÀÞÅÊ"
+ serbian "Definisani višestruki primarni kljuèevi"
+ slo "Zadefinovaných viac primárnych kµúèov"
+ spa "Multiples claves primarias definidas"
+ swe "Flera PRIMARY KEY använda"
+ ukr "ðÅÒ×ÉÎÎÏÇÏ ËÌÀÞÁ ×ÉÚÎÁÞÅÎÏ ÎÅÏÄÎÏÒÁÚÏ×Ï"
+ER_TOO_MANY_KEYS 42000 S1009
+ cze "Zad-Báno pøíli¹ mnoho klíèù, je povoleno nejvíce %d klíèù"
+ dan "For mange nøgler specificeret. Kun %d nøgler må bruges"
+ nla "Teveel zoeksleutels gedefinieerd. Maximaal zijn %d zoeksleutels toegestaan"
+ eng "Too many keys specified; max %d keys allowed"
+ jps "key ‚ÌŽw’肪‘½‚·‚¬‚Ü‚·. key ‚ÍÅ‘å %d ‚Ü‚Å‚Å‚·",
+ est "Liiga palju võtmeid. Maksimaalselt võib olla %d võtit"
+ fre "Trop de clefs sont définies. Maximum de %d clefs alloué"
+ ger "Zu viele Schlüssel definiert. Maximal %d Schlüssel erlaubt"
+ greek "ÐÜñá ðïëëÜ key ïñßóèçêáí. Ôï ðïëý %d åðéôñÝðïíôáé"
+ hun "Tul sok kulcs. Maximum %d kulcs engedelyezett."
+ ita "Troppe chiavi. Sono ammesse max %d chiavi"
+ jpn "key ¤Î»ØÄ꤬¿¤¹¤®¤Þ¤¹. key ¤ÏºÇÂç %d ¤Þ¤Ç¤Ç¤¹"
+ kor "³Ê¹« ¸¹Àº Å°°¡ Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù.. ÃÖ´ë %dÀÇ Å°°¡ °¡´ÉÇÔ"
+ nor "For mange nøkler spesifisert. Maks %d nøkler tillatt"
+ norwegian-ny "For mange nykler spesifisert. Maks %d nyklar tillatt"
+ pol "Okre?lono zbyt wiele kluczy. Dostêpnych jest maksymalnie %d kluczy"
+ por "Especificadas chaves demais. O máximo permitido são %d chaves"
+ rum "Prea multe chei. Numarul de chei maxim este %d"
+ rus "õËÁÚÁÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ ËÌÀÞÅÊ. òÁÚÒÅÛÁÅÔÓÑ ÕËÁÚÙ×ÁÔØ ÎÅ ÂÏÌÅÅ %d ËÌÀÞÅÊ"
+ serbian "Navedeno je previše kljuèeva. Maksimum %d kljuèeva je dozvoljeno"
+ slo "Zadaných ríli¹ veµa kµúèov. Najviac %d kµúèov je povolených"
+ spa "Demasiadas claves primarias declaradas. Un maximo de %d claves son permitidas"
+ swe "För många nycklar använda. Man får ha högst %d nycklar"
+ ukr "úÁÂÁÇÁÔÏ ËÌÀÞ¦× ÚÁÚÎÁÞÅÎÏ. äÏÚ×ÏÌÅÎÏ ÎŠ¦ÌØÛÅ %d ËÌÀÞ¦×"
+ER_TOO_MANY_KEY_PARTS 42000 S1009
+ cze "Zad-Báno pøíli¹ mnoho èást klíèù, je povoleno nejvíce %d èástí"
+ dan "For mange nøgledele specificeret. Kun %d dele må bruges"
+ nla "Teveel zoeksleutel onderdelen gespecificeerd. Maximaal %d onderdelen toegestaan"
+ eng "Too many key parts specified; max %d parts allowed"
+ est "Võti koosneb liiga paljudest osadest. Maksimaalselt võib olla %d osa"
+ fre "Trop de parties specifiées dans la clef. Maximum de %d parties"
+ ger "Zu viele Teilschlüssel definiert. Maximal sind %d Teilschlüssel erlaubt"
+ greek "ÐÜñá ðïëëÜ key parts ïñßóèçêáí. Ôï ðïëý %d åðéôñÝðïíôáé"
+ hun "Tul sok kulcsdarabot definialt. Maximum %d resz engedelyezett"
+ ita "Troppe parti di chiave specificate. Sono ammesse max %d parti"
+ kor "³Ê¹« ¸¹Àº Å° ºÎºÐ(parts)µéÀÌ Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù.. ÃÖ´ë %d ºÎºÐÀÌ °¡´ÉÇÔ"
+ nor "For mange nøkkeldeler spesifisert. Maks %d deler tillatt"
+ norwegian-ny "For mange nykkeldelar spesifisert. Maks %d delar tillatt"
+ pol "Okre?lono zbyt wiele czê?ci klucza. Dostêpnych jest maksymalnie %d czê?ci"
+ por "Especificadas partes de chave demais. O máximo permitido são %d partes"
+ rum "Prea multe chei. Numarul de chei maxim este %d"
+ rus "õËÁÚÁÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÞÁÓÔÅÊ ÓÏÓÔÁ×ÎÏÇÏ ËÌÀÞÁ. òÁÚÒÅÛÁÅÔÓÑ ÕËÁÚÙ×ÁÔØ ÎÅ ÂÏÌÅÅ %d ÞÁÓÔÅÊ"
+ serbian "Navedeno je previše delova kljuèa. Maksimum %d delova je dozvoljeno"
+ slo "Zadaných ríli¹ veµa èastí kµúèov. Je povolených najviac %d èastí"
+ spa "Demasiadas partes de clave declaradas. Un maximo de %d partes son permitidas"
+ swe "För många nyckeldelar använda. Man får ha högst %d nyckeldelar"
+ ukr "úÁÂÁÇÁÔÏ ÞÁÓÔÉÎ ËÌÀÞÁ ÚÁÚÎÁÞÅÎÏ. äÏÚ×ÏÌÅÎÏ ÎŠ¦ÌØÛÅ %d ÞÁÓÔÉÎ"
+ER_TOO_LONG_KEY 42000 S1009
+ cze "Zadan-Bý klíè byl pøíli¹ dlouhý, nejvìt¹í délka klíèe je %d"
+ dan "Specificeret nøgle var for lang. Maksimal nøglelængde er %d"
+ nla "Gespecificeerde zoeksleutel was te lang. De maximale lengte is %d"
+ eng "Specified key was too long; max key length is %d bytes"
+ jps "key ‚ª’·‚·‚¬‚Ü‚·. key ‚Ì’·‚³‚ÍÅ‘å %d ‚Å‚·",
+ est "Võti on liiga pikk. Maksimaalne võtmepikkus on %d"
+ fre "La clé est trop longue. Longueur maximale: %d"
+ ger "Schlüssel ist zu lang. Die maximale Schlüssellänge beträgt %d"
+ greek "Ôï êëåéäß ðïõ ïñßóèçêå åßíáé ðïëý ìåãÜëï. Ôï ìÝãéóôï ìÞêïò åßíáé %d"
+ hun "A megadott kulcs tul hosszu. Maximalis kulcshosszusag: %d"
+ ita "La chiave specificata e` troppo lunga. La max lunghezza della chiave e` %d"
+ jpn "key ¤¬Ä¹¤¹¤®¤Þ¤¹. key ¤ÎŤµ¤ÏºÇÂç %d ¤Ç¤¹"
+ kor "Á¤ÀÇµÈ Å°°¡ ³Ê¹« ±é´Ï´Ù. ÃÖ´ë Å°ÀÇ ±æÀÌ´Â %dÀÔ´Ï´Ù."
+ nor "Spesifisert nøkkel var for lang. Maks nøkkellengde er is %d"
+ norwegian-ny "Spesifisert nykkel var for lang. Maks nykkellengde er %d"
+ pol "Zdefinowany klucz jest zbyt d³ugi. Maksymaln? d³ugo?ci? klucza jest %d"
+ por "Chave especificada longa demais. O comprimento de chave máximo permitido é %d"
+ rum "Cheia specificata este prea lunga. Marimea maxima a unei chei este de %d"
+ rus "õËÁÚÁÎ ÓÌÉÛËÏÍ ÄÌÉÎÎÙÊ ËÌÀÞ. íÁËÓÉÍÁÌØÎÁÑ ÄÌÉÎÁ ËÌÀÞÁ ÓÏÓÔÁ×ÌÑÅÔ %d ÂÁÊÔ"
+ serbian "Navedeni kljuè je predug. Maksimalna dužina kljuèa je %d"
+ slo "Zadaný kµúè je príli¹ dlhý, najväè¹ia då¾ka kµúèa je %d"
+ spa "Declaracion de clave demasiado larga. La maxima longitud de clave es %d"
+ swe "För lång nyckel. Högsta tillåtna nyckellängd är %d"
+ ukr "úÁÚÎÁÞÅÎÉÊ ËÌÀÞ ÚÁÄÏ×ÇÉÊ. îÁʦÌØÛÁ ÄÏ×ÖÉÎÁ ËÌÀÞÁ %d ÂÁÊÔ¦×"
+ER_KEY_COLUMN_DOES_NOT_EXITS 42000 S1009
+ cze "Kl-Bíèový sloupec '%-.64s' v tabulce neexistuje"
+ dan "Nøglefeltet '%-.64s' eksisterer ikke i tabellen"
+ nla "Zoeksleutel kolom '%-.64s' bestaat niet in tabel"
+ eng "Key column '%-.64s' doesn't exist in table"
+ jps "Key column '%-.64s' ‚ªƒe[ƒuƒ‹‚É‚ ‚è‚Ü‚¹‚ñ.",
+ est "Võtme tulp '%-.64s' puudub tabelis"
+ fre "La clé '%-.64s' n'existe pas dans la table"
+ ger "In der Tabelle gibt es keine Schlüsselspalte '%-.64s'"
+ greek "Ôï ðåäßï êëåéäß '%-.64s' äåí õðÜñ÷åé óôïí ðßíáêá"
+ hun "A(z) '%-.64s'kulcsoszlop nem letezik a tablaban"
+ ita "La colonna chiave '%-.64s' non esiste nella tabella"
+ jpn "Key column '%-.64s' ¤¬¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ê¤Þ¤»¤ó."
+ kor "Key Ä®·³ '%-.64s'´Â Å×ÀÌºí¿¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù."
+ nor "Nøkkel felt '%-.64s' eksiterer ikke i tabellen"
+ norwegian-ny "Nykkel kolonne '%-.64s' eksiterar ikkje i tabellen"
+ pol "Kolumna '%-.64s' zdefiniowana w kluczu nie istnieje w tabeli"
+ por "Coluna chave '%-.64s' não existe na tabela"
+ rum "Coloana cheie '%-.64s' nu exista in tabela"
+ rus "ëÌÀÞÅ×ÏÊ ÓÔÏÌÂÅà '%-.64s' × ÔÁÂÌÉÃÅ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+ serbian "Kljuèna kolona '%-.64s' ne postoji u tabeli"
+ slo "Kµúèový ståpec '%-.64s' v tabuµke neexistuje"
+ spa "La columna clave '%-.64s' no existe en la tabla"
+ swe "Nyckelkolumn '%-.64s' finns inte"
+ ukr "ëÌÀÞÏ×ÉÊ ÓÔÏ×ÂÅÃØ '%-.64s' ÎÅ ¦ÓÎÕ¤ Õ ÔÁÂÌÉæ"
+ER_BLOB_USED_AS_KEY 42000 S1009
+ cze "Blob sloupec '%-.64s' nem-Bù¾e být pou¾it jako klíè"
+ dan "BLOB feltet '%-.64s' kan ikke bruges ved specifikation af indeks"
+ nla "BLOB kolom '%-.64s' kan niet gebruikt worden bij zoeksleutel specificatie"
+ eng "BLOB column '%-.64s' can't be used in key specification with the used table type"
+ est "BLOB-tüüpi tulpa '%-.64s' ei saa kasutada võtmena"
+ fre "Champ BLOB '%-.64s' ne peut être utilisé dans une clé"
+ ger "BLOB-Feld '%-.64s' kann beim verwendeten Tabellentyp nicht als Schlüssel verwendet werden"
+ greek "Ðåäßï ôýðïõ Blob '%-.64s' äåí ìðïñåß íá ÷ñçóéìïðïéçèåß óôïí ïñéóìü åíüò êëåéäéïý (key specification)"
+ hun "Blob objektum '%-.64s' nem hasznalhato kulcskent"
+ ita "La colonna BLOB '%-.64s' non puo` essere usata nella specifica della chiave"
+ kor "BLOB Ä®·³ '%-.64s'´Â Å° Á¤ÀÇ¿¡¼­ »ç¿ëµÉ ¼ö ¾ø½À´Ï´Ù."
+ nor "Blob felt '%-.64s' kan ikke brukes ved spesifikasjon av nøkler"
+ norwegian-ny "Blob kolonne '%-.64s' kan ikkje brukast ved spesifikasjon av nyklar"
+ pol "Kolumna typu Blob '%-.64s' nie mo¿e byæ u¿yta w specyfikacji klucza"
+ por "Coluna BLOB '%-.64s' não pode ser utilizada na especificação de chave para o tipo de tabela usado"
+ rum "Coloana de tip BLOB '%-.64s' nu poate fi folosita in specificarea cheii cu tipul de tabla folosit"
+ rus "óÔÏÌÂÅà ÔÉÐÁ BLOB '%-.64s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎ ËÁË ÚÎÁÞÅÎÉÅ ËÌÀÞÁ × ÔÁÂÌÉÃÅ ÔÁËÏÇÏ ÔÉÐÁ"
+ serbian "BLOB kolona '%-.64s' ne može biti upotrebljena za navoðenje kljuèa sa tipom tabele koji se trenutno koristi"
+ slo "Blob pole '%-.64s' nemô¾e by» pou¾ité ako kµúè"
+ spa "La columna Blob '%-.64s' no puede ser usada en una declaracion de clave"
+ swe "En BLOB '%-.64s' kan inte vara nyckel med den använda tabelltypen"
+ ukr "BLOB ÓÔÏ×ÂÅÃØ '%-.64s' ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÉÊ Õ ×ÉÚÎÁÞÅÎΦ ËÌÀÞÁ × ÃØÏÍÕ ÔÉЦ ÔÁÂÌÉæ"
+ER_TOO_BIG_FIELDLENGTH 42000 S1009
+ cze "P-Bøíli¹ velká délka sloupce '%-.64s' (nejvíce %d). Pou¾ijte BLOB"
+ dan "For stor feltlængde for kolonne '%-.64s' (maks = %d). Brug BLOB i stedet"
+ nla "Te grote kolomlengte voor '%-.64s' (max = %d). Maak hiervoor gebruik van het type BLOB"
+ eng "Column length too big for column '%-.64s' (max = %d); use BLOB or TEXT instead"
+ jps "column '%-.64s' ‚Í,Šm•Û‚·‚é column ‚Ì‘å‚«‚³‚ª‘½‚·‚¬‚Ü‚·. (Å‘å %d ‚Ü‚Å). BLOB ‚ð‚©‚í‚è‚ÉŽg—p‚µ‚Ä‚­‚¾‚³‚¢.",
+ est "Tulba '%-.64s' pikkus on liiga pikk (maksimaalne pikkus: %d). Kasuta BLOB väljatüüpi"
+ fre "Champ '%-.64s' trop long (max = %d). Utilisez un BLOB"
+ ger "Feldlänge für Feld '%-.64s' zu groß (maximal %d). BLOB-Feld verwenden!"
+ greek "Ðïëý ìåãÜëï ìÞêïò ãéá ôï ðåäßï '%-.64s' (max = %d). Ðáñáêáëþ ÷ñçóéìïðïéåßóôå ôïí ôýðï BLOB"
+ hun "A(z) '%-.64s' oszlop tul hosszu. (maximum = %d). Hasznaljon BLOB tipust inkabb."
+ ita "La colonna '%-.64s' e` troppo grande (max=%d). Utilizza un BLOB."
+ jpn "column '%-.64s' ¤Ï,³ÎÊݤ¹¤ë column ¤ÎÂ礭¤µ¤¬Â¿¤¹¤®¤Þ¤¹. (ºÇÂç %d ¤Þ¤Ç). BLOB ¤ò¤«¤ï¤ê¤Ë»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤."
+ kor "Ä®·³ '%-.64s'ÀÇ Ä®·³ ±æÀÌ°¡ ³Ê¹« ±é´Ï´Ù (ÃÖ´ë = %d). ´ë½Å¿¡ BLOB¸¦ »ç¿ëÇϼ¼¿ä."
+ nor "For stor nøkkellengde for kolonne '%-.64s' (maks = %d). Bruk BLOB istedenfor"
+ norwegian-ny "For stor nykkellengde for felt '%-.64s' (maks = %d). Bruk BLOB istadenfor"
+ pol "Zbyt du¿a d³ugo?æ kolumny '%-.64s' (maks. = %d). W zamian u¿yj typu BLOB"
+ por "Comprimento da coluna '%-.64s' grande demais (max = %d); use BLOB em seu lugar"
+ rum "Lungimea coloanei '%-.64s' este prea lunga (maximum = %d). Foloseste BLOB mai bine"
+ rus "óÌÉÛËÏÍ ÂÏÌØÛÁÑ ÄÌÉÎÁ ÓÔÏÌÂÃÁ '%-.64s' (ÍÁËÓÉÍÕÍ = %d). éÓÐÏÌØÚÕÊÔÅ ÔÉÐ BLOB ÉÌÉ TEXT ×ÍÅÓÔÏ ÔÅËÕÝÅÇÏ"
+ serbian "Previše podataka za kolonu '%-.64s' (maksimum je %d). Upotrebite BLOB polje"
+ slo "Príli¹ veµká då¾ka pre pole '%-.64s' (maximum = %d). Pou¾ite BLOB"
+ spa "Longitud de columna demasiado grande para la columna '%-.64s' (maximo = %d).Usar BLOB en su lugar"
+ swe "För stor kolumnlängd angiven för '%-.64s' (max= %d). Använd en BLOB instället"
+ ukr "úÁÄÏ×ÇÁ ÄÏ×ÖÉÎÁ ÓÔÏ×ÂÃÑ '%-.64s' (max = %d). ÷ÉËÏÒÉÓÔÁÊÔÅ ÔÉÐ BLOB"
+ER_WRONG_AUTO_KEY 42000 S1009
+ cze "M-Bù¾ete mít pouze jedno AUTO pole a to musí být definováno jako klíè"
+ dan "Der kan kun specificeres eet AUTO_INCREMENT-felt, og det skal være indekseret"
+ nla "Er kan slechts 1 autofield zijn en deze moet als zoeksleutel worden gedefinieerd."
+ eng "Incorrect table definition; there can be only one auto column and it must be defined as a key"
+ jps "ƒe[ƒuƒ‹‚Ì’è‹`‚ªˆá‚¢‚Ü‚·; there can be only one auto column and it must be defined as a key",
+ est "Vigane tabelikirjeldus; Tabelis tohib olla üks auto_increment tüüpi tulp ning see peab olema defineeritud võtmena"
+ fre "Un seul champ automatique est permis et il doit être indexé"
+ ger "Falsche Tabellendefinition. Es darf nur ein Auto-Feld geben und dieses muss als Schlüssel definiert werden"
+ greek "Ìðïñåß íá õðÜñ÷åé ìüíï Ýíá auto field êáé ðñÝðåé íá Ý÷åé ïñéóèåß óáí key"
+ hun "Csak egy auto mezo lehetseges, es azt kulcskent kell definialni."
+ ita "Puo` esserci solo un campo AUTO e deve essere definito come chiave"
+ jpn "¥Æ¡¼¥Ö¥ë¤ÎÄêµÁ¤¬°ã¤¤¤Þ¤¹; there can be only one auto column and it must be defined as a key"
+ kor "ºÎÁ¤È®ÇÑ Å×À̺í Á¤ÀÇ; Å×À̺íÀº ÇϳªÀÇ auto Ä®·³ÀÌ Á¸ÀçÇÏ°í Å°·Î Á¤ÀǵǾîÁ®¾ß ÇÕ´Ï´Ù."
+ nor "Bare ett auto felt kan være definert som nøkkel."
+ norwegian-ny "Bare eitt auto felt kan være definert som nøkkel."
+ pol "W tabeli mo¿e byæ tylko jedno pole auto i musi ono byæ zdefiniowane jako klucz"
+ por "Definição incorreta de tabela. Somente é permitido um único campo auto-incrementado e ele tem que ser definido como chave"
+ rum "Definitia tabelei este incorecta; Nu pot fi mai mult de o singura coloana de tip auto si aceasta trebuie definita ca cheie"
+ rus "îÅËÏÒÒÅËÔÎÏÅ ÏÐÒÅÄÅÌÅÎÉÅ ÔÁÂÌÉÃÙ: ÍÏÖÅÔ ÓÕÝÅÓÔ×Ï×ÁÔØ ÔÏÌØËÏ ÏÄÉÎ Á×ÔÏÉÎËÒÅÍÅÎÔÎÙÊ ÓÔÏÌÂÅÃ, É ÏÎ ÄÏÌÖÅÎ ÂÙÔØ ÏÐÒÅÄÅÌÅÎ ËÁË ËÌÀÞ"
+ serbian "Pogrešna definicija tabele; U tabeli može postojati samo jedna 'AUTO' kolona i ona mora biti istovremeno definisana kao kolona kljuèa"
+ slo "Mô¾ete ma» iba jedno AUTO pole a to musí by» definované ako kµúè"
+ spa "Puede ser solamente un campo automatico y este debe ser definido como una clave"
+ swe "Det får finnas endast ett AUTO_INCREMENT-fält och detta måste vara en nyckel"
+ ukr "îÅצÒÎÅ ×ÉÚÎÁÞÅÎÎÑ ÔÁÂÌÉæ; íÏÖÅ ÂÕÔÉ ÌÉÛÅ ÏÄÉÎ Á×ÔÏÍÁÔÉÞÎÉÊ ÓÔÏ×ÂÅÃØ, ÝÏ ÐÏ×ÉÎÅÎ ÂÕÔÉ ×ÉÚÎÁÞÅÎÉÊ ÑË ËÌÀÞ"
+ER_READY
+ cze "%s: p-Bøipraven na spojení"
+ dan "%s: klar til tilslutninger"
+ nla "%s: klaar voor verbindingen"
+ eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d"
+ jps "%s: €”õŠ®—¹",
+ est "%s: ootab ühendusi"
+ fre "%s: Prêt pour des connections"
+ ger "%-.64s: Bereit für Verbindungen"
+ greek "%s: óå áíáìïíÞ óõíäÝóåùí"
+ hun "%s: kapcsolatra kesz"
+ ita "%s: Pronto per le connessioni\n"
+ jpn "%s: ½àÈ÷´°Î»"
+ kor "%s: ¿¬°á ÁغñÁßÀÔ´Ï´Ù"
+ nor "%s: klar for tilkoblinger"
+ norwegian-ny "%s: klar for tilkoblingar"
+ pol "%s: gotowe do po³?czenia"
+ por "%s: Pronto para conexões"
+ rum "%s: sint gata pentru conectii"
+ rus "%s: çÏÔÏ× ÐÒÉÎÉÍÁÔØ ÓÏÅÄÉÎÅÎÉÑ.\n÷ÅÒÓÉÑ: '%s' ÓÏËÅÔ: '%s' ÐÏÒÔ: %d %s"
+ serbian "%s: Spreman za konekcije\n"
+ slo "%s: pripravený na spojenie"
+ spa "%s: preparado para conexiones"
+ swe "%s: klar att ta emot klienter"
+ ukr "%s: çÏÔÏ×ÉÊ ÄÌÑ Ú'¤ÄÎÁÎØ!"
+ER_NORMAL_SHUTDOWN
+ cze "%s: norm-Bální ukonèení\n"
+ dan "%s: Normal nedlukning\n"
+ nla "%s: Normaal afgesloten \n"
+ eng "%s: Normal shutdown\n"
+ est "%s: MySQL lõpetas\n"
+ fre "%s: Arrêt normal du serveur\n"
+ ger "%-.64s: Normal heruntergefahren\n"
+ greek "%s: ÖõóéïëïãéêÞ äéáäéêáóßá shutdown\n"
+ hun "%s: Normal leallitas\n"
+ ita "%s: Shutdown normale\n"
+ kor "%s: Á¤»óÀûÀÎ shutdown\n"
+ nor "%s: Normal avslutning\n"
+ norwegian-ny "%s: Normal nedkopling\n"
+ pol "%s: Standardowe zakoñczenie dzia³ania\n"
+ por "%s: 'Shutdown' normal\n"
+ rum "%s: Terminare normala\n"
+ rus "%s: ëÏÒÒÅËÔÎÁÑ ÏÓÔÁÎÏ×ËÁ\n"
+ serbian "%s: Normalno gašenje\n"
+ slo "%s: normálne ukonèenie\n"
+ spa "%s: Apagado normal\n"
+ swe "%s: Normal avslutning\n"
+ ukr "%s: îÏÒÍÁÌØÎÅ ÚÁ×ÅÒÛÅÎÎÑ\n"
+ER_GOT_SIGNAL
+ cze "%s: p-Bøijat signal %d, konèím\n"
+ dan "%s: Fangede signal %d. Afslutter!!\n"
+ nla "%s: Signaal %d. Systeem breekt af!\n"
+ eng "%s: Got signal %d. Aborting!\n"
+ jps "%s: Got signal %d. ’†’f!\n",
+ est "%s: sain signaali %d. Lõpetan!\n"
+ fre "%s: Reçu le signal %d. Abandonne!\n"
+ ger "%-.64s: Signal %d erhalten. Abbruch!\n"
+ greek "%s: ÅëÞöèç ôï ìÞíõìá %d. Ç äéáäéêáóßá åãêáôáëåßðåôáé!\n"
+ hun "%s: %d jelzes. Megszakitva!\n"
+ ita "%s: Ricevuto segnale %d. Interruzione!\n"
+ jpn "%s: Got signal %d. ̾̂!\n"
+ kor "%s: %d ½ÅÈ£°¡ µé¾î¿ÔÀ½. ÁßÁö!\n"
+ nor "%s: Oppdaget signal %d. Avslutter!\n"
+ norwegian-ny "%s: Oppdaga signal %d. Avsluttar!\n"
+ pol "%s: Otrzymano sygna³ %d. Koñczenie dzia³ania!\n"
+ por "%s: Obteve sinal %d. Abortando!\n"
+ rum "%s: Semnal %d obtinut. Aborting!\n"
+ rus "%s: ðÏÌÕÞÅÎ ÓÉÇÎÁÌ %d. ðÒÅËÒÁÝÁÅÍ!\n"
+ serbian "%s: Dobio signal %d. Prekidam!\n"
+ slo "%s: prijatý signál %d, ukonèenie (Abort)!\n"
+ spa "%s: Recibiendo signal %d. Abortando!\n"
+ swe "%s: Fick signal %d. Avslutar!\n"
+ ukr "%s: ïÔÒÉÍÁÎÏ ÓÉÇÎÁÌ %d. ðÅÒÅÒÉ×ÁÀÓØ!\n"
+ER_SHUTDOWN_COMPLETE
+ cze "%s: ukon-Bèení práce hotovo\n"
+ dan "%s: Server lukket\n"
+ nla "%s: Afsluiten afgerond\n"
+ eng "%s: Shutdown complete\n"
+ jps "%s: Shutdown Š®—¹\n",
+ est "%s: Lõpp\n"
+ fre "%s: Arrêt du serveur terminé\n"
+ ger "%-.64s: Heruntergefahren (shutdown)\n"
+ greek "%s: Ç äéáäéêáóßá Shutdown ïëïêëçñþèçêå\n"
+ hun "%s: A leallitas kesz\n"
+ ita "%s: Shutdown completato\n"
+ jpn "%s: Shutdown ´°Î»\n"
+ kor "%s: Shutdown ÀÌ ¿Ï·áµÊ!\n"
+ nor "%s: Avslutning komplett\n"
+ norwegian-ny "%s: Nedkopling komplett\n"
+ pol "%s: Zakoñczenie dzia³ania wykonane\n"
+ por "%s: 'Shutdown' completo\n"
+ rum "%s: Terminare completa\n"
+ rus "%s: ïÓÔÁÎÏ×ËÁ ÚÁ×ÅÒÛÅÎÁ\n"
+ serbian "%s: Gašenje završeno\n"
+ slo "%s: práca ukonèená\n"
+ spa "%s: Apagado completado\n"
+ swe "%s: Avslutning klar\n"
+ ukr "%s: òÏÂÏÔÕ ÚÁ×ÅÒÛÅÎÏ\n"
+ER_FORCING_CLOSE 08S01
+ cze "%s: n-Básilné uzavøení threadu %ld u¾ivatele '%-.64s'\n"
+ dan "%s: Forceret nedlukning af tråd: %ld bruger: '%-.64s'\n"
+ nla "%s: Afsluiten afgedwongen van thread %ld gebruiker: '%-.64s'\n"
+ eng "%s: Forcing close of thread %ld user: '%-.32s'\n"
+ jps "%s: ƒXƒŒƒbƒh %ld ‹­§I—¹ user: '%-.64s'\n",
+ est "%s: Sulgen jõuga lõime %ld kasutaja: '%-.32s'\n"
+ fre "%s: Arrêt forcé de la tâche (thread) %ld utilisateur: '%-.64s'\n"
+ ger "%s: Thread %ld zwangsweise beendet. Benutzer: '%-.32s'\n"
+ greek "%s: Ôï thread èá êëåßóåé %ld user: '%-.64s'\n"
+ hun "%s: A(z) %ld thread kenyszeritett zarasa. Felhasznalo: '%-.64s'\n"
+ ita "%s: Forzata la chiusura del thread %ld utente: '%-.64s'\n"
+ jpn "%s: ¥¹¥ì¥Ã¥É %ld ¶¯À©½ªÎ» user: '%-.64s'\n"
+ kor "%s: thread %ldÀÇ °­Á¦ Á¾·á user: '%-.64s'\n"
+ nor "%s: Påtvinget avslutning av tråd %ld bruker: '%-.64s'\n"
+ norwegian-ny "%s: Påtvinga avslutning av tråd %ld brukar: '%-.64s'\n"
+ pol "%s: Wymuszenie zamkniêcia w?tku %ld u¿ytkownik: '%-.64s'\n"
+ por "%s: Forçando finalização da 'thread' %ld - usuário '%-.32s'\n"
+ rum "%s: Terminare fortata a thread-ului %ld utilizatorului: '%-.32s'\n"
+ rus "%s: ðÒÉÎÕÄÉÔÅÌØÎÏ ÚÁËÒÙ×ÁÅÍ ÐÏÔÏË %ld ÐÏÌØÚÏ×ÁÔÅÌÑ: '%-.32s'\n"
+ serbian "%s: Usiljeno gašenje thread-a %ld koji pripada korisniku: '%-.32s'\n"
+ slo "%s: násilné ukonèenie vlákna %ld u¾ívateµa '%-.64s'\n"
+ spa "%s: Forzando a cerrar el thread %ld usuario: '%-.64s'\n"
+ swe "%s: Stänger av tråd %ld; användare: '%-.64s'\n"
+ ukr "%s: ðÒÉÓËÏÒÀÀ ÚÁËÒÉÔÔÑ Ç¦ÌËÉ %ld ËÏÒÉÓÔÕ×ÁÞÁ: '%-.32s'\n"
+ER_IPSOCK_ERROR 08S01
+ cze "Nemohu vytvo-Bøit IP socket"
+ dan "Kan ikke oprette IP socket"
+ nla "Kan IP-socket niet openen"
+ eng "Can't create IP socket"
+ jps "IP socket ‚ªì‚ê‚Ü‚¹‚ñ",
+ est "Ei suuda luua IP socketit"
+ fre "Ne peut créer la connection IP (socket)"
+ ger "Kann IP-Socket nicht erzeugen"
+ greek "Äåí åßíáé äõíáôÞ ç äçìéïõñãßá IP socket"
+ hun "Az IP socket nem hozhato letre"
+ ita "Impossibile creare il socket IP"
+ jpn "IP socket ¤¬ºî¤ì¤Þ¤»¤ó"
+ kor "IP ¼ÒÄÏÀ» ¸¸µéÁö ¸øÇß½À´Ï´Ù."
+ nor "Kan ikke opprette IP socket"
+ norwegian-ny "Kan ikkje opprette IP socket"
+ pol "Nie mo¿na stworzyæ socket'u IP"
+ por "Não pode criar o soquete IP"
+ rum "Nu pot crea IP socket"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ IP-ÓÏËÅÔ"
+ serbian "Ne mogu da kreiram IP socket"
+ slo "Nemô¾em vytvori» IP socket"
+ spa "No puedo crear IP socket"
+ swe "Kan inte skapa IP-socket"
+ ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ IP ÒÏÚ'¤Í"
+ER_NO_SUCH_INDEX 42S12 S1009
+ cze "Tabulka '%-.64s' nem-Bá index odpovídající CREATE INDEX. Vytvoøte tabulku znovu"
+ dan "Tabellen '%-.64s' har ikke den nøgle, som blev brugt i CREATE INDEX. Genopret tabellen"
+ nla "Tabel '%-.64s' heeft geen INDEX zoals deze gemaakt worden met CREATE INDEX. Maak de tabel opnieuw"
+ eng "Table '%-.64s' has no index like the one used in CREATE INDEX; recreate the table"
+ jps "Table '%-.64s' ‚Í‚»‚̂悤‚È index ‚ðŽ‚Á‚Ä‚¢‚Ü‚¹‚ñ(CREATE INDEX ŽÀsŽž‚ÉŽw’肳‚ê‚Ä‚¢‚Ü‚¹‚ñ). ƒe[ƒuƒ‹‚ðì‚è’¼‚µ‚Ä‚­‚¾‚³‚¢",
+ est "Tabelil '%-.64s' puuduvad võtmed. Loo tabel uuesti"
+ fre "La table '%-.64s' n'a pas d'index comme celle utilisée dans CREATE INDEX. Recréez la table"
+ ger "Tabelle '%-.64s' besitzt keinen wie den in CREATE INDEX verwendeten Index. Index neu anlegen"
+ greek "Ï ðßíáêáò '%-.64s' äåí Ý÷åé åõñåôÞñéï (index) óáí áõôü ðïõ ÷ñçóéìïðïéåßôå óôçí CREATE INDEX. Ðáñáêáëþ, îáíáäçìéïõñãÞóôå ôïí ðßíáêá"
+ hun "A(z) '%-.64s' tablahoz nincs meg a CREATE INDEX altal hasznalt index. Alakitsa at a tablat"
+ ita "La tabella '%-.64s' non ha nessun indice come quello specificatato dalla CREATE INDEX. Ricrea la tabella"
+ jpn "Table '%-.64s' ¤Ï¤½¤Î¤è¤¦¤Ê index ¤ò»ý¤Ã¤Æ¤¤¤Þ¤»¤ó(CREATE INDEX ¼Â¹Ô»þ¤Ë»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó). ¥Æ¡¼¥Ö¥ë¤òºî¤êľ¤·¤Æ¤¯¤À¤µ¤¤"
+ kor "Å×À̺í '%-.64s'´Â À妽º¸¦ ¸¸µéÁö ¾Ê¾Ò½À´Ï´Ù. alter Å×À̺í¸í·ÉÀ» ÀÌ¿ëÇÏ¿© Å×À̺íÀ» ¼öÁ¤Çϼ¼¿ä..."
+ nor "Tabellen '%-.64s' har ingen index som den som er brukt i CREATE INDEX. Gjenopprett tabellen"
+ norwegian-ny "Tabellen '%-.64s' har ingen index som den som er brukt i CREATE INDEX. Oprett tabellen på nytt"
+ pol "Tabela '%-.64s' nie ma indeksu takiego jak w CREATE INDEX. Stwórz tabelê"
+ por "Tabela '%-.64s' não possui um índice como o usado em CREATE INDEX. Recrie a tabela"
+ rum "Tabela '%-.64s' nu are un index ca acela folosit in CREATE INDEX. Re-creeaza tabela"
+ rus "÷ ÔÁÂÌÉÃÅ '%-.64s' ÎÅÔ ÔÁËÏÇÏ ÉÎÄÅËÓÁ, ËÁË × CREATE INDEX. óÏÚÄÁÊÔÅ ÔÁÂÌÉÃÕ ÚÁÎÏ×Ï"
+ serbian "Tabela '%-.64s' nema isti indeks kao onaj upotrebljen pri komandi 'CREATE INDEX'. Napravite tabelu ponovo"
+ slo "Tabuµka '%-.64s' nemá index zodpovedajúci CREATE INDEX. Vytvorte tabulku znova"
+ spa "La tabla '%-.64s' no tiene indice como el usado en CREATE INDEX. Crea de nuevo la tabla"
+ swe "Tabellen '%-.64s' har inget index som motsvarar det angivna i CREATE INDEX. Skapa om tabellen"
+ ukr "ôÁÂÌÉÃÑ '%-.64s' ÍÁ¤ ¦ÎÄÅËÓ, ÝÏ ÎÅ ÓЦ×ÐÁÄÁ¤ Ú ×ËÁÚÁÎÎÉÍ Õ CREATE INDEX. óÔ×ÏÒ¦ÔØ ÔÁÂÌÉÃÀ ÚÎÏ×Õ"
+ER_WRONG_FIELD_TERMINATORS 42000 S1009
+ cze "Argument separ-Bátoru polo¾ek nebyl oèekáván. Pøeètìte si manuál"
+ dan "Felt adskiller er ikke som forventet, se dokumentationen"
+ nla "De argumenten om velden te scheiden zijn anders dan verwacht. Raadpleeg de handleiding"
+ eng "Field separator argument is not what is expected; check the manual"
+ est "Väljade eraldaja erineb oodatust. Tutvu kasutajajuhendiga"
+ fre "Séparateur de champs inconnu. Vérifiez dans le manuel"
+ ger "Feldbegrenzer-Argument ist nicht in der erwarteten Form. Bitte im Handbuch nachlesen"
+ greek "Ï äéá÷ùñéóôÞò ðåäßùí äåí åßíáé áõôüò ðïõ áíáìåíüôáí. Ðáñáêáëþ áíáôñÝîôå óôï manual"
+ hun "A mezoelvalaszto argumentumok nem egyeznek meg a varttal. Nezze meg a kezikonyvben!"
+ ita "L'argomento 'Field separator' non e` quello atteso. Controlla il manuale"
+ kor "ÇÊµå ±¸ºÐÀÚ ÀμöµéÀÌ ¿ÏÀüÇÏÁö ¾Ê½À´Ï´Ù. ¸Þ´º¾óÀ» ã¾Æ º¸¼¼¿ä."
+ nor "Felt skiller argumentene er ikke som forventet, se dokumentasjonen"
+ norwegian-ny "Felt skiljer argumenta er ikkje som venta, sjå dokumentasjonen"
+ pol "Nie oczekiwano separatora. Sprawd¥ podrêcznik"
+ por "Argumento separador de campos não é o esperado. Cheque o manual"
+ rum "Argumentul pentru separatorul de cimpuri este diferit de ce ma asteptam. Verifica manualul"
+ rus "áÒÇÕÍÅÎÔ ÒÁÚÄÅÌÉÔÅÌÑ ÐÏÌÅÊ - ÎÅ ÔÏÔ, ËÏÔÏÒÙÊ ÏÖÉÄÁÌÓÑ. ïÂÒÁÝÁÊÔÅÓØ Ë ÄÏËÕÍÅÎÔÁÃÉÉ"
+ serbian "Argument separatora polja nije ono što se oèekivalo. Proverite uputstvo MySQL server-a"
+ slo "Argument oddeµovaè polí nezodpovedá po¾iadavkám. Skontrolujte v manuáli"
+ spa "Los separadores de argumentos del campo no son los especificados. Comprueba el manual"
+ swe "Fältseparatorerna är vad som förväntades. Kontrollera mot manualen"
+ ukr "èÉÂÎÉÊ ÒÏÚĦÌÀ×ÁÞ ÐÏ̦×. ðÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ"
+ER_BLOBS_AND_NO_TERMINATED 42000 S1009
+ cze "Nen-Bí mo¾né pou¾ít pevný rowlength s BLOBem. Pou¾ijte 'fields terminated by'."
+ dan "Man kan ikke bruge faste feltlængder med BLOB. Brug i stedet 'fields terminated by'."
+ nla "Bij het gebruik van BLOBs is het niet mogelijk om vaste rijlengte te gebruiken. Maak s.v.p. gebruik van 'fields terminated by'."
+ eng "You can't use fixed rowlength with BLOBs; please use 'fields terminated by'"
+ est "BLOB-tüüpi väljade olemasolul ei saa kasutada fikseeritud väljapikkust. Vajalik 'fields terminated by' määrang."
+ fre "Vous ne pouvez utiliser des lignes de longueur fixe avec des BLOBs. Utiliser 'fields terminated by'."
+ ger "Eine feste Zeilenlänge kann für BLOB-Felder nicht verwendet werden. Bitte 'fields terminated by' verwenden"
+ greek "Äåí ìðïñåßôå íá ÷ñçóéìïðïéÞóåôå fixed rowlength óå BLOBs. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå 'fields terminated by'."
+ hun "Fix hosszusagu BLOB-ok nem hasznalhatok. Hasznalja a 'mezoelvalaszto jelet' ."
+ ita "Non possono essere usate righe a lunghezza fissa con i BLOB. Usa 'FIELDS TERMINATED BY'."
+ jpn "You can't use fixed rowlength with BLOBs; please use 'fields terminated by'."
+ kor "BLOB·Î´Â °íÁ¤±æÀÌÀÇ lowlength¸¦ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù. 'fields terminated by'¸¦ »ç¿ëÇϼ¼¿ä."
+ nor "En kan ikke bruke faste feltlengder med BLOB. Vennlisgt bruk 'fields terminated by'."
+ norwegian-ny "Ein kan ikkje bruke faste feltlengder med BLOB. Vennlisgt bruk 'fields terminated by'."
+ pol "Nie mo¿na u¿yæ sta³ej d³ugo?ci wiersza z polami typu BLOB. U¿yj 'fields terminated by'."
+ por "Você não pode usar comprimento de linha fixo com BLOBs. Por favor, use campos com comprimento limitado."
+ rum "Nu poti folosi lungime de cimp fix pentru BLOB-uri. Foloseste 'fields terminated by'."
+ rus "æÉËÓÉÒÏ×ÁÎÎÙÊ ÒÁÚÍÅÒ ÚÁÐÉÓÉ Ó ÐÏÌÑÍÉ ÔÉÐÁ BLOB ÉÓÐÏÌØÚÏ×ÁÔØ ÎÅÌØÚÑ, ÐÒÉÍÅÎÑÊÔÅ 'fields terminated by'"
+ serbian "Ne možete koristiti fiksnu velièinu sloga kada imate BLOB polja. Molim koristite 'fields terminated by' opciju."
+ slo "Nie je mo¾né pou¾i» fixnú då¾ku s BLOBom. Pou¾ite 'fields terminated by'."
+ spa "No puedes usar longitudes de filas fijos con BLOBs. Por favor usa 'campos terminados por '."
+ swe "Man kan inte använda fast radlängd med blobs. Använd 'fields terminated by'"
+ ukr "îÅ ÍÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÓÔÁÌÕ ÄÏ×ÖÉÎÕ ÓÔÒÏËÉ Ú BLOB. úËÏÒÉÓÔÁÊÔÅÓÑ 'fields terminated by'"
+ER_TEXTFILE_NOT_READABLE
+ cze "Soubor '%-.64s' mus-Bí být v adresáøi databáze nebo èitelný pro v¹echny"
+ dan "Filen '%-.64s' skal være i database-folderen og kunne læses af alle"
+ nla "Het bestand '%-.64s' dient in de database directory voor the komen of leesbaar voor iedereen te zijn."
+ eng "The file '%-.64s' must be in the database directory or be readable by all"
+ jps "ƒtƒ@ƒCƒ‹ '%-.64s' ‚Í databse ‚Ì directory ‚É‚ ‚é‚©‘S‚Ẵ†[ƒU[‚ª“Ç‚ß‚é‚悤‚É‹–‰Â‚³‚ê‚Ä‚¢‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ.",
+ est "Fail '%-.64s' peab asuma andmebaasi kataloogis või olema kõigile loetav"
+ fre "Le fichier '%-.64s' doit être dans le répertoire de la base et lisible par tous"
+ ger "Datei '%-.64s' muss im Datenbank-Verzeichnis vorhanden und lesbar für alle sein"
+ greek "Ôï áñ÷åßï '%-.64s' ðñÝðåé íá õðÜñ÷åé óôï database directory Þ íá ìðïñåß íá äéáâáóôåß áðü üëïõò"
+ hun "A(z) '%-.64s'-nak az adatbazis konyvtarban kell lennie, vagy mindenki szamara olvashatonak"
+ ita "Il file '%-.64s' deve essere nella directory del database e deve essere leggibile da tutti"
+ jpn "¥Õ¥¡¥¤¥ë '%-.64s' ¤Ï databse ¤Î directory ¤Ë¤¢¤ë¤«Á´¤Æ¤Î¥æ¡¼¥¶¡¼¤¬Æɤá¤ë¤è¤¦¤Ëµö²Ä¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó."
+ kor "'%-.64s' È­ÀÏ´Â µ¥ÀÌŸº£À̽º µð·ºÅ丮¿¡ Á¸ÀçÇϰųª ¸ðµÎ¿¡°Ô Àб⠰¡´ÉÇÏ¿©¾ß ÇÕ´Ï´Ù."
+ nor "Filen '%-.64s' må være i database-katalogen for å være lesbar for alle"
+ norwegian-ny "Filen '%-.64s' må være i database-katalogen for å være lesbar for alle"
+ pol "Plik '%-.64s' musi znajdowaæ sie w katalogu bazy danych lub mieæ prawa czytania przez wszystkich"
+ por "Arquivo '%-.64s' tem que estar no diretório do banco de dados ou ter leitura possível para todos"
+ rum "Fisierul '%-.64s' trebuie sa fie in directorul bazei de data sau trebuie sa poata sa fie citit de catre toata lumea (verifica permisiile)"
+ rus "æÁÊÌ '%-.64s' ÄÏÌÖÅÎ ÎÁÈÏÄÉÔØÓÑ × ÔÏÍ ÖÅ ËÁÔÁÌÏÇÅ, ÞÔÏ É ÂÁÚÁ ÄÁÎÎÙÈ, ÉÌÉ ÂÙÔØ ÏÂÝÅÄÏÓÔÕÐÎÙÍ ÄÌÑ ÞÔÅÎÉÑ"
+ serbian "File '%-.64s' mora biti u direktorijumu gde su file-ovi baze i mora imati odgovarajuæa prava pristupa"
+ slo "Súbor '%-.64s' musí by» v adresári databázy, alebo èitateµný pre v¹etkých"
+ spa "El archivo '%-.64s' debe estar en el directorio de la base de datos o ser de lectura por todos"
+ swe "Textfilen '%.64s' måste finnas i databasbiblioteket eller vara läsbar för alla"
+ ukr "æÁÊÌ '%-.64s' ÐÏ×ÉÎÅÎ ÂÕÔÉ Õ ÔÅæ ÂÁÚÉ ÄÁÎÎÉÈ ÁÂÏ ÍÁÔÉ ×ÓÔÁÎÏ×ÌÅÎÅ ÐÒÁ×Ï ÎÁ ÞÉÔÁÎÎÑ ÄÌÑ ÕÓ¦È"
+ER_FILE_EXISTS_ERROR
+ cze "Soubor '%-.64s' ji-B¾ existuje"
+ dan "Filen '%-.64s' eksisterer allerede"
+ nla "Het bestand '%-.64s' bestaat reeds"
+ eng "File '%-.80s' already exists"
+ jps "File '%-.64s' ‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·",
+ est "Fail '%-.80s' juba eksisteerib"
+ fre "Le fichier '%-.64s' existe déjà"
+ ger "Datei '%-.64s' bereits vorhanden"
+ greek "Ôï áñ÷åßï '%-.64s' õðÜñ÷åé Þäç"
+ hun "A '%-.64s' file mar letezik."
+ ita "Il file '%-.64s' esiste gia`"
+ jpn "File '%-.64s' ¤Ï´û¤Ë¸ºß¤·¤Þ¤¹"
+ kor "'%-.64s' È­ÀÏÀº ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù."
+ nor "Filen '%-.64s' eksisterte allerede"
+ norwegian-ny "Filen '%-.64s' eksisterte allereide"
+ pol "Plik '%-.64s' ju¿ istnieje"
+ por "Arquivo '%-.80s' já existe"
+ rum "Fisierul '%-.80s' exista deja"
+ rus "æÁÊÌ '%-.80s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ"
+ serbian "File '%-.80s' veæ postoji"
+ slo "Súbor '%-.64s' u¾ existuje"
+ spa "El archivo '%-.64s' ya existe"
+ swe "Filen '%-.64s' existerar redan"
+ ukr "æÁÊÌ '%-.80s' ×ÖÅ ¦ÓÎÕ¤"
+ER_LOAD_INFO
+ cze "Z-Báznamù: %ld Vymazáno: %ld Pøeskoèeno: %ld Varování: %ld"
+ dan "Poster: %ld Fjernet: %ld Sprunget over: %ld Advarsler: %ld"
+ nla "Records: %ld Verwijderd: %ld Overgeslagen: %ld Waarschuwingen: %ld"
+ eng "Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld"
+ jps "ƒŒƒR[ƒh”: %ld íœ: %ld Skipped: %ld Warnings: %ld",
+ est "Kirjeid: %ld Kustutatud: %ld Vahele jäetud: %ld Hoiatusi: %ld"
+ fre "Enregistrements: %ld Effacés: %ld Non traités: %ld Avertissements: %ld"
+ ger "Datensätze: %ld Gelöscht: %ld Ausgelassen: %ld Warnungen: %ld"
+ greek "ÅããñáöÝò: %ld ÄéáãñáöÝò: %ld ÐáñåêÜìöèçóáí: %ld ÐñïåéäïðïéÞóåéò: %ld"
+ hun "Rekordok: %ld Torolve: %ld Skipped: %ld Warnings: %ld"
+ ita "Records: %ld Cancellati: %ld Saltati: %ld Avvertimenti: %ld"
+ jpn "¥ì¥³¡¼¥É¿ô: %ld ºï½ü: %ld Skipped: %ld Warnings: %ld"
+ kor "·¹ÄÚµå: %ld°³ »èÁ¦: %ld°³ ½ºÅµ: %ld°³ °æ°í: %ld°³"
+ nor "Poster: %ld Fjernet: %ld Hoppet over: %ld Advarsler: %ld"
+ norwegian-ny "Poster: %ld Fjerna: %ld Hoppa over: %ld Åtvaringar: %ld"
+ pol "Recordów: %ld Usuniêtych: %ld Pominiêtych: %ld Ostrze¿eñ: %ld"
+ por "Registros: %ld - Deletados: %ld - Ignorados: %ld - Avisos: %ld"
+ rum "Recorduri: %ld Sterse: %ld Sarite (skipped): %ld Atentionari (warnings): %ld"
+ rus "úÁÐÉÓÅÊ: %ld õÄÁÌÅÎÏ: %ld ðÒÏÐÕÝÅÎÏ: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld"
+ serbian "Slogova: %ld Izbrisano: %ld Preskoèeno: %ld Upozorenja: %ld"
+ slo "Záznamov: %ld Zmazaných: %ld Preskoèených: %ld Varovania: %ld"
+ spa "Registros: %ld Borrados: %ld Saltados: %ld Peligros: %ld"
+ swe "Rader: %ld Bortagna: %ld Dubletter: %ld Varningar: %ld"
+ ukr "úÁÐÉÓ¦×: %ld ÷ÉÄÁÌÅÎÏ: %ld ðÒÏÐÕÝÅÎÏ: %ld úÁÓÔÅÒÅÖÅÎØ: %ld"
+ER_ALTER_INFO
+ cze "Z-Báznamù: %ld Zdvojených: %ld"
+ dan "Poster: %ld Ens: %ld"
+ nla "Records: %ld Dubbel: %ld"
+ eng "Records: %ld Duplicates: %ld"
+ jps "ƒŒƒR[ƒh”: %ld d•¡: %ld",
+ est "Kirjeid: %ld Kattuvaid: %ld"
+ fre "Enregistrements: %ld Doublons: %ld"
+ ger "Datensätze: %ld Duplikate: %ld"
+ greek "ÅããñáöÝò: %ld ÅðáíáëÞøåéò: %ld"
+ hun "Rekordok: %ld Duplikalva: %ld"
+ ita "Records: %ld Duplicati: %ld"
+ jpn "¥ì¥³¡¼¥É¿ô: %ld ½ÅÊ£: %ld"
+ kor "·¹ÄÚµå: %ld°³ Áߺ¹: %ld°³"
+ nor "Poster: %ld Like: %ld"
+ norwegian-ny "Poster: %ld Like: %ld"
+ pol "Rekordów: %ld Duplikatów: %ld"
+ por "Registros: %ld - Duplicados: %ld"
+ rum "Recorduri: %ld Duplicate: %ld"
+ rus "úÁÐÉÓÅÊ: %ld äÕÂÌÉËÁÔÏ×: %ld"
+ serbian "Slogova: %ld Duplikata: %ld"
+ slo "Záznamov: %ld Opakovaných: %ld"
+ spa "Registros: %ld Duplicados: %ld"
+ swe "Rader: %ld Dubletter: %ld"
+ ukr "úÁÐÉÓ¦×: %ld äÕÂ̦ËÁÔ¦×: %ld"
+ER_WRONG_SUB_KEY
+ cze "Chybn-Bá podèást klíèe -- není to øetìzec nebo je del¹í ne¾ délka èásti klíèe"
+ dan "Forkert indeksdel. Den anvendte nøgledel er ikke en streng eller længden er større end nøglelængden"
+ nla "Foutief sub-gedeelte van de zoeksleutel. De gebruikte zoeksleutel is geen onderdeel van een string of of de gebruikte lengte is langer dan de zoeksleutel"
+ eng "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"
+ est "Vigane võtme osa. Kasutatud võtmeosa ei ole string tüüpi, määratud pikkus on pikem kui võtmeosa või tabelihandler ei toeta seda tüüpi võtmeid"
+ fre "Mauvaise sous-clef. Ce n'est pas un 'string' ou la longueur dépasse celle définie dans la clef"
+ ger "Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder der Tabellenhandler unterstützt keine Unterteilschlüssel"
+ greek "ÅóöáëìÝíï sub part key. Ôï ÷ñçóéìïðïéïýìåíï key part äåí åßíáé string Þ ôï ìÞêïò ôïõ åßíáé ìåãáëýôåñï"
+ hun "Rossz alkulcs. A hasznalt kulcsresz nem karaktersorozat vagy hosszabb, mint a kulcsresz"
+ ita "Sotto-parte della chiave errata. La parte di chiave utilizzata non e` una stringa o la lunghezza e` maggiore della parte di chiave."
+ jpn "Incorrect sub part key; the used key part isn't a string or the used length is longer than the key part"
+ kor "ºÎÁ¤È®ÇÑ ¼­¹ö ÆÄÆ® Å°. »ç¿ëµÈ Å° ÆÄÆ®°¡ ½ºÆ®¸µÀÌ ¾Æ´Ï°Å³ª Å° ÆÄÆ®ÀÇ ±æÀÌ°¡ ³Ê¹« ±é´Ï´Ù."
+ nor "Feil delnøkkel. Den brukte delnøkkelen er ikke en streng eller den oppgitte lengde er lengre enn nøkkel lengden"
+ norwegian-ny "Feil delnykkel. Den brukte delnykkelen er ikkje ein streng eller den oppgitte lengda er lengre enn nykkellengden"
+ pol "B³êdna podczê?æ klucza. U¿yta czê?æ klucza nie jest ³añcuchem lub u¿yta d³ugo?æ jest wiêksza ni¿ czê?æ klucza"
+ por "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"
+ rum "Componentul cheii este incorrect. Componentul folosit al cheii nu este un sir sau lungimea folosita este mai lunga decit lungimea cheii"
+ rus "îÅËÏÒÒÅËÔÎÁÑ ÞÁÓÔØ ËÌÀÞÁ. éÓÐÏÌØÚÕÅÍÁÑ ÞÁÓÔØ ËÌÀÞÁ ÎÅ Ñ×ÌÑÅÔÓÑ ÓÔÒÏËÏÊ, ÕËÁÚÁÎÎÁÑ ÄÌÉÎÁ ÂÏÌØÛÅ, ÞÅÍ ÄÌÉÎÁ ÞÁÓÔÉ ËÌÀÞÁ, ÉÌÉ ÏÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÕÎÉËÁÌØÎÙÅ ÞÁÓÔÉ ËÌÀÞÁ"
+ serbian "Pogrešan pod-kljuè dela kljuèa. Upotrebljeni deo kljuèa nije string, upotrebljena dužina je veæa od dela kljuèa ili handler tabela ne podržava jedinstvene pod-kljuèeve"
+ slo "Incorrect sub part key; the used key part isn't a string or the used length is longer than the key part"
+ spa "Parte de la clave es erronea. Una parte de la clave no es una cadena o la longitud usada es tan grande como la parte de la clave"
+ swe "Felaktig delnyckel. Nyckeldelen är inte en sträng eller den angivna längden är längre än kolumnlängden"
+ ukr "îÅצÒÎÁ ÞÁÓÔÉÎÁ ËÌÀÞÁ. ÷ÉËÏÒÉÓÔÁÎÁ ÞÁÓÔÉÎÁ ËÌÀÞÁ ÎÅ ¤ ÓÔÒÏËÏÀ, ÚÁÄÏ×ÇÁ ÁÂÏ ×ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ ÕΦËÁÌØÎÉÈ ÞÁÓÔÉÎ ËÌÀÞÅÊ"
+ER_CANT_REMOVE_ALL_FIELDS 42000
+ cze "Nen-Bí mo¾né vymazat v¹echny polo¾ky s ALTER TABLE. Pou¾ijte DROP TABLE"
+ dan "Man kan ikke slette alle felter med ALTER TABLE. Brug DROP TABLE i stedet."
+ nla "Het is niet mogelijk alle velden te verwijderen met ALTER TABLE. Gebruik a.u.b. DROP TABLE hiervoor!"
+ eng "You can't delete all columns with ALTER TABLE; use DROP TABLE instead"
+ jps "ALTER TABLE ‚Å‘S‚Ä‚Ì column ‚Í휂ł«‚Ü‚¹‚ñ. DROP TABLE ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢",
+ est "ALTER TABLE kasutades ei saa kustutada kõiki tulpasid. Kustuta tabel DROP TABLE abil"
+ fre "Vous ne pouvez effacer tous les champs avec ALTER TABLE. Utilisez DROP TABLE"
+ ger "Mit ALTER TABLE können nicht alle Felder auf einmal gelöscht werden. Dafür DROP TABLE verwenden"
+ greek "Äåí åßíáé äõíáôÞ ç äéáãñáöÞ üëùí ôùí ðåäßùí ìå ALTER TABLE. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå DROP TABLE"
+ hun "Az osszes mezo nem torolheto az ALTER TABLE-lel. Hasznalja a DROP TABLE-t helyette"
+ ita "Non si possono cancellare tutti i campi con una ALTER TABLE. Utilizzare DROP TABLE"
+ jpn "ALTER TABLE ¤ÇÁ´¤Æ¤Î column ¤Ïºï½ü¤Ç¤­¤Þ¤»¤ó. DROP TABLE ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤"
+ kor "ALTER TABLE ¸í·ÉÀ¸·Î´Â ¸ðµç Ä®·³À» Áö¿ï ¼ö ¾ø½À´Ï´Ù. DROP TABLE ¸í·ÉÀ» ÀÌ¿ëÇϼ¼¿ä."
+ nor "En kan ikke slette alle felt med ALTER TABLE. Bruk DROP TABLE isteden."
+ norwegian-ny "Ein kan ikkje slette alle felt med ALTER TABLE. Bruk DROP TABLE istadenfor."
+ pol "Nie mo¿na usun?æ wszystkich pól wykorzystuj?c ALTER TABLE. W zamian u¿yj DROP TABLE"
+ por "Você não pode deletar todas as colunas com ALTER TABLE; use DROP TABLE em seu lugar"
+ rum "Nu poti sterge toate coloanele cu ALTER TABLE. Foloseste DROP TABLE in schimb"
+ rus "îÅÌØÚÑ ÕÄÁÌÉÔØ ×ÓÅ ÓÔÏÌÂÃÙ Ó ÐÏÍÏÝØÀ ALTER TABLE. éÓÐÏÌØÚÕÊÔÅ DROP TABLE"
+ serbian "Ne možete da izbrišete sve kolone pomoæu komande 'ALTER TABLE'. Upotrebite komandu 'DROP TABLE' ako želite to da uradite"
+ slo "One nemô¾em zmaza» all fields with ALTER TABLE; use DROP TABLE instead"
+ spa "No puede borrar todos los campos con ALTER TABLE. Usa DROP TABLE para hacerlo"
+ swe "Man kan inte radera alla fält med ALTER TABLE. Använd DROP TABLE istället"
+ ukr "îÅ ÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ×Ó¦ ÓÔÏ×Âæ ÚÁ ÄÏÐÏÍÏÇÏÀ ALTER TABLE. äÌÑ ÃØÏÇÏ ÓËÏÒÉÓÔÁÊÔÅÓÑ DROP TABLE"
+ER_CANT_DROP_FIELD_OR_KEY 42000
+ cze "Nemohu zru-B¹it '%-.64s' (provést DROP). Zkontrolujte, zda neexistují záznamy/klíèe"
+ dan "Kan ikke udføre DROP '%-.64s'. Undersøg om feltet/nøglen eksisterer."
+ nla "Kan '%-.64s' niet weggooien. Controleer of het veld of de zoeksleutel daadwerkelijk bestaat."
+ eng "Can't DROP '%-.64s'; check that column/key exists"
+ jps "'%-.64s' ‚ð”jŠü‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½; check that column/key exists",
+ est "Ei suuda kustutada '%-.64s'. Kontrolli kas tulp/võti eksisteerib"
+ fre "Ne peut effacer (DROP) '%-.64s'. Vérifiez s'il existe"
+ ger "Kann '%-.64s' nicht löschen. Existiert das Feld / der Schlüssel?"
+ greek "Áäýíáôç ç äéáãñáöÞ (DROP) '%-.64s'. Ðáñáêáëþ åëÝãîôå áí ôï ðåäßï/êëåéäß õðÜñ÷åé"
+ hun "A DROP '%-.64s' nem lehetseges. Ellenorizze, hogy a mezo/kulcs letezik-e"
+ ita "Impossibile cancellare '%-.64s'. Controllare che il campo chiave esista"
+ jpn "'%-.64s' ¤òÇË´þ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿; check that column/key exists"
+ kor "'%-.64s'¸¦ DROPÇÒ ¼ö ¾ø½À´Ï´Ù. Ä®·³À̳ª Å°°¡ Á¸ÀçÇÏ´ÂÁö äũÇϼ¼¿ä."
+ nor "Kan ikke DROP '%-.64s'. Undersøk om felt/nøkkel eksisterer."
+ norwegian-ny "Kan ikkje DROP '%-.64s'. Undersøk om felt/nøkkel eksisterar."
+ pol "Nie mo¿na wykonaæ operacji DROP '%-.64s'. Sprawd¥, czy to pole/klucz istnieje"
+ por "Não se pode fazer DROP '%-.64s'. Confira se esta coluna/chave existe"
+ rum "Nu pot sa DROP '%-.64s'. Verifica daca coloana/cheia exista"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ (DROP) '%-.64s'. õÂÅÄÉÔÅÓØ ÞÔÏ ÓÔÏÌÂÅÃ/ËÌÀÞ ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÓÕÝÅÓÔ×ÕÅÔ"
+ serbian "Ne mogu da izvršim komandu drop 'DROP' na '%-.64s'. Proverite da li ta kolona (odnosno kljuè) postoji"
+ slo "Nemô¾em zru¹i» (DROP) '%-.64s'. Skontrolujte, èi neexistujú záznamy/kµúèe"
+ spa "No puedo ELIMINAR '%-.64s'. compuebe que el campo/clave existe"
+ swe "Kan inte ta bort '%-.64s'. Kontrollera att fältet/nyckel finns"
+ ukr "îÅ ÍÏÖÕ DROP '%-.64s'. ðÅÒÅצÒÔÅ, ÞÉ ÃÅÊ ÓÔÏ×ÂÅÃØ/ËÌÀÞ ¦ÓÎÕ¤"
+ER_INSERT_INFO
+ cze "Z-Báznamù: %ld Zdvojených: %ld Varování: %ld"
+ dan "Poster: %ld Ens: %ld Advarsler: %ld"
+ nla "Records: %ld Dubbel: %ld Waarschuwing: %ld"
+ eng "Records: %ld Duplicates: %ld Warnings: %ld"
+ jps "ƒŒƒR[ƒh”: %ld d•¡”: %ld Warnings: %ld",
+ est "Kirjeid: %ld Kattuvaid: %ld Hoiatusi: %ld"
+ fre "Enregistrements: %ld Doublons: %ld Avertissements: %ld"
+ ger "Datensätze: %ld Duplikate: %ld Warnungen: %ld"
+ greek "ÅããñáöÝò: %ld ÅðáíáëÞøåéò: %ld ÐñïåéäïðïéÞóåéò: %ld"
+ hun "Rekordok: %ld Duplikalva: %ld Warnings: %ld"
+ ita "Records: %ld Duplicati: %ld Avvertimenti: %ld"
+ jpn "¥ì¥³¡¼¥É¿ô: %ld ½ÅÊ£¿ô: %ld Warnings: %ld"
+ kor "·¹ÄÚµå: %ld°³ Áߺ¹: %ld°³ °æ°í: %ld°³"
+ nor "Poster: %ld Like: %ld Advarsler: %ld"
+ norwegian-ny "Postar: %ld Like: %ld Åtvaringar: %ld"
+ pol "Rekordów: %ld Duplikatów: %ld Ostrze¿eñ: %ld"
+ por "Registros: %ld - Duplicados: %ld - Avisos: %ld"
+ rum "Recorduri: %ld Duplicate: %ld Atentionari (warnings): %ld"
+ rus "úÁÐÉÓÅÊ: %ld äÕÂÌÉËÁÔÏ×: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld"
+ serbian "Slogova: %ld Duplikata: %ld Upozorenja: %ld"
+ slo "Záznamov: %ld Opakovaných: %ld Varovania: %ld"
+ spa "Registros: %ld Duplicados: %ld Peligros: %ld"
+ swe "Rader: %ld Dubletter: %ld Varningar: %ld"
+ ukr "úÁÐÉÓ¦×: %ld äÕÂ̦ËÁÔ¦×: %ld úÁÓÔÅÒÅÖÅÎØ: %ld"
+ER_UPDATE_TABLE_USED
+ eng "You can't specify target table '%-.64s' for update in FROM clause"
+ ger "Die Verwendung der zu aktualisierenden Zieltabelle '%-.64s' ist in der FROM-Klausel nicht zulässig."
+ rus "îÅ ÄÏÐÕÓËÁÅÔÓÑ ÕËÁÚÁÎÉÅ ÔÁÂÌÉÃÙ '%-.64s' × ÓÐÉÓËÅ ÔÁÂÌÉà FROM ÄÌÑ ×ÎÅÓÅÎÉÑ × ÎÅÅ ÉÚÍÅÎÅÎÉÊ"
+ swe "INSERT-table '%-.64s' får inte finnas i FROM tabell-listan"
+ ukr "ôÁÂÌÉÃÑ '%-.64s' ÝÏ ÚͦÎÀ¤ÔØÓÑ ÎÅ ÄÏÚ×ÏÌÅÎÁ Õ ÐÅÒÅ̦ËÕ ÔÁÂÌÉÃØ FROM"
+ER_NO_SUCH_THREAD
+ cze "Nezn-Bámá identifikace threadu: %lu"
+ dan "Ukendt tråd id: %lu"
+ nla "Onbekend thread id: %lu"
+ eng "Unknown thread id: %lu"
+ jps "thread id: %lu ‚Í‚ ‚è‚Ü‚¹‚ñ",
+ est "Tundmatu lõim: %lu"
+ fre "Numéro de tâche inconnu: %lu"
+ ger "Unbekannte Thread-ID: %lu"
+ greek "Áãíùóôï thread id: %lu"
+ hun "Ervenytelen szal (thread) id: %lu"
+ ita "Thread id: %lu sconosciuto"
+ jpn "thread id: %lu ¤Ï¤¢¤ê¤Þ¤»¤ó"
+ kor "¾Ë¼ö ¾ø´Â ¾²·¹µå id: %lu"
+ nor "Ukjent tråd id: %lu"
+ norwegian-ny "Ukjent tråd id: %lu"
+ pol "Nieznany identyfikator w?tku: %lu"
+ por "'Id' de 'thread' %lu desconhecido"
+ rum "Id-ul: %lu thread-ului este necunoscut"
+ rus "îÅÉÚ×ÅÓÔÎÙÊ ÎÏÍÅÒ ÐÏÔÏËÁ: %lu"
+ serbian "Nepoznat thread identifikator: %lu"
+ slo "Neznáma identifikácia vlákna: %lu"
+ spa "Identificador del thread: %lu desconocido"
+ swe "Finns ingen tråd med id %lu"
+ ukr "îÅצÄÏÍÉÊ ¦ÄÅÎÔÉƦËÁÔÏÒ Ç¦ÌËÉ: %lu"
+ER_KILL_DENIED_ERROR
+ cze "Nejste vlastn-Bíkem threadu %lu"
+ dan "Du er ikke ejer af tråden %lu"
+ nla "U bent geen bezitter van thread %lu"
+ eng "You are not owner of thread %lu"
+ jps "thread %lu ‚̃I[ƒi[‚Å‚Í‚ ‚è‚Ü‚¹‚ñ",
+ est "Ei ole lõime %lu omanik"
+ fre "Vous n'êtes pas propriétaire de la tâche no: %lu"
+ ger "Sie sind nicht Eigentümer von Thread %lu"
+ greek "Äåí åßóèå owner ôïõ thread %lu"
+ hun "A %lu thread-nek mas a tulajdonosa"
+ ita "Utente non proprietario del thread %lu"
+ jpn "thread %lu ¤Î¥ª¡¼¥Ê¡¼¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó"
+ kor "¾²·¹µå(Thread) %luÀÇ ¼ÒÀ¯ÀÚ°¡ ¾Æ´Õ´Ï´Ù."
+ nor "Du er ikke eier av tråden %lu"
+ norwegian-ny "Du er ikkje eigar av tråd %lu"
+ pol "Nie jeste? w³a?cicielem w?tku %lu"
+ por "Você não é proprietário da 'thread' %lu"
+ rum "Nu sinteti proprietarul threadului %lu"
+ rus "÷Ù ÎÅ Ñ×ÌÑÅÔÅÓØ ×ÌÁÄÅÌØÃÅÍ ÐÏÔÏËÁ %lu"
+ serbian "Vi niste vlasnik thread-a %lu"
+ slo "Nie ste vlastníkom vlákna %lu"
+ spa "Tu no eres el propietario del thread%lu"
+ swe "Du är inte ägare till tråd %lu"
+ ukr "÷É ÎÅ ×ÏÌÏÄÁÒ Ç¦ÌËÉ %lu"
+ER_NO_TABLES_USED
+ cze "Nejsou pou-B¾ity ¾ádné tabulky"
+ dan "Ingen tabeller i brug"
+ nla "Geen tabellen gebruikt."
+ eng "No tables used"
+ est "Ühtegi tabelit pole kasutusel"
+ fre "Aucune table utilisée"
+ ger "Keine Tabellen verwendet"
+ greek "Äåí ÷ñçóéìïðïéÞèçêáí ðßíáêåò"
+ hun "Nincs hasznalt tabla"
+ ita "Nessuna tabella usata"
+ kor "¾î¶² Å×ÀÌºíµµ »ç¿ëµÇÁö ¾Ê¾Ò½À´Ï´Ù."
+ nor "Ingen tabeller i bruk"
+ norwegian-ny "Ingen tabellar i bruk"
+ pol "Nie ma ¿adej u¿ytej tabeli"
+ por "Nenhuma tabela usada"
+ rum "Nici o tabela folosita"
+ rus "îÉËÁËÉÅ ÔÁÂÌÉÃÙ ÎÅ ÉÓÐÏÌØÚÏ×ÁÎÙ"
+ serbian "Nema upotrebljenih tabela"
+ slo "Nie je pou¾itá ¾iadna tabuµka"
+ spa "No ha tablas usadas"
+ swe "Inga tabeller angivna"
+ ukr "îÅ ×ÉËÏÒÉÓÔÁÎÏ ÔÁÂÌÉÃØ"
+ER_TOO_BIG_SET
+ cze "P-Bøíli¹ mnoho øetìzcù pro sloupec %s a SET"
+ dan "For mange tekststrenge til specifikationen af SET i kolonne %-.64s"
+ nla "Teveel strings voor kolom %s en SET"
+ eng "Too many strings for column %-.64s and SET"
+ est "Liiga palju string tulbale %-.64s tüübile SET"
+ fre "Trop de chaînes dans la colonne %s avec SET"
+ ger "Zu viele Strings für SET-Spalte %-.64s angegeben"
+ greek "ÐÜñá ðïëëÜ strings ãéá ôï ðåäßï %-.64s êáé SET"
+ hun "Tul sok karakter: %-.64s es SET"
+ ita "Troppe stringhe per la colonna %-.64s e la SET"
+ kor "Ä®·³ %-.64s¿Í SET¿¡¼­ ½ºÆ®¸µÀÌ ³Ê¹« ¸¹½À´Ï´Ù."
+ nor "For mange tekststrenger kolonne %s og SET"
+ norwegian-ny "For mange tekststrengar felt %s og SET"
+ pol "Zbyt wiele ³añcuchów dla kolumny %s i polecenia SET"
+ por "'Strings' demais para coluna '%-.64s' e SET"
+ rum "Prea multe siruri pentru coloana %-.64s si SET"
+ rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÚÎÁÞÅÎÉÊ ÄÌÑ ÓÔÏÌÂÃÁ %-.64s × SET"
+ serbian "Previše string-ova za kolonu '%-.64s' i komandu 'SET'"
+ slo "Príli¹ mnoho re»azcov pre pole %-.64s a SET"
+ spa "Muchas strings para columna %s y SET"
+ swe "För många alternativ till kolumn %s för SET"
+ ukr "úÁÂÁÇÁÔÏ ÓÔÒÏË ÄÌÑ ÓÔÏ×ÂÃÑ %-.64s ÔÁ SET"
+ER_NO_UNIQUE_LOGFILE
+ cze "Nemohu vytvo-Bøit jednoznaèné jméno logovacího souboru %s.(1-999)\n"
+ dan "Kan ikke lave unikt log-filnavn %s.(1-999)\n"
+ nla "Het is niet mogelijk een unieke naam te maken voor de logfile %s.(1-999)\n"
+ eng "Can't generate a unique log-filename %-.64s.(1-999)\n"
+ est "Ei suuda luua unikaalset logifaili nime %-.64s.(1-999)\n"
+ fre "Ne peut générer un unique nom de journal %s.(1-999)\n"
+ ger "Kann keinen eindeutigen Dateinamen für die Logdatei %-.64s erzeugen (1-999)\n"
+ greek "Áäýíáôç ç äçìéïõñãßá unique log-filename %-.64s.(1-999)\n"
+ hun "Egyedi log-filenev nem generalhato: %-.64s.(1-999)\n"
+ ita "Impossibile generare un nome del file log unico %-.64s.(1-999)\n"
+ kor "Unique ·Î±×È­ÀÏ '%-.64s'¸¦ ¸¸µé¼ö ¾ø½À´Ï´Ù.(1-999)\n"
+ nor "Kan ikke lage unikt loggfilnavn %s.(1-999)\n"
+ norwegian-ny "Kan ikkje lage unikt loggfilnavn %s.(1-999)\n"
+ pol "Nie mo¿na stworzyæ unikalnej nazwy pliku z logiem %s.(1-999)\n"
+ por "Não pode gerar um nome de arquivo de 'log' único '%-.64s'.(1-999)\n"
+ rum "Nu pot sa generez un nume de log unic %-.64s.(1-999)\n"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÕÎÉËÁÌØÎÏÅ ÉÍÑ ÆÁÊÌÁ ÖÕÒÎÁÌÁ %-.64s.(1-999)\n"
+ serbian "Ne mogu da generišem jedinstveno ime log-file-a: '%-.64s.(1-999)'\n"
+ slo "Nemô¾em vytvori» unikátne meno log-súboru %-.64s.(1-999)\n"
+ spa "No puede crear un unico archivo log %s.(1-999)\n"
+ swe "Kan inte generera ett unikt filnamn %s.(1-999)\n"
+ ukr "îÅ ÍÏÖÕ ÚÇÅÎÅÒÕ×ÁÔÉ ÕΦËÁÌØÎÅ ¦Í'Ñ log-ÆÁÊÌÕ %-.64s.(1-999)\n"
+ER_TABLE_NOT_LOCKED_FOR_WRITE
+ cze "Tabulka '%-.64s' byla zam-Bèena s READ a nemù¾e být zmìnìna"
+ dan "Tabellen '%-.64s' var låst med READ lås og kan ikke opdateres"
+ nla "Tabel '%-.64s' was gelocked met een lock om te lezen. Derhalve kunnen geen wijzigingen worden opgeslagen."
+ eng "Table '%-.64s' was locked with a READ lock and can't be updated"
+ jps "Table '%-.64s' ‚Í READ lock ‚É‚È‚Á‚Ä‚¢‚ÄAXV‚Í‚Å‚«‚Ü‚¹‚ñ",
+ est "Tabel '%-.64s' on lukustatud READ lukuga ning ei ole muudetav"
+ fre "Table '%-.64s' verrouillée lecture (READ): modification impossible"
+ ger "Tabelle '%-.64s' ist mit Lesesperre versehen und kann nicht aktualisiert werden"
+ greek "Ï ðßíáêáò '%-.64s' Ý÷åé êëåéäùèåß ìå READ lock êáé äåí åðéôñÝðïíôáé áëëáãÝò"
+ hun "A(z) '%-.64s' tabla zarolva lett (READ lock) es nem lehet frissiteni"
+ ita "La tabella '%-.64s' e` soggetta a lock in lettura e non puo` essere aggiornata"
+ jpn "Table '%-.64s' ¤Ï READ lock ¤Ë¤Ê¤Ã¤Æ¤¤¤Æ¡¢¹¹¿·¤Ï¤Ç¤­¤Þ¤»¤ó"
+ kor "Å×À̺í '%-.64s'´Â READ ¶ôÀÌ Àá°ÜÀ־ °»½ÅÇÒ ¼ö ¾ø½À´Ï´Ù."
+ nor "Tabellen '%-.64s' var låst med READ lås og kan ikke oppdateres"
+ norwegian-ny "Tabellen '%-.64s' var låst med READ lås og kan ikkje oppdaterast"
+ pol "Tabela '%-.64s' zosta³a zablokowana przez READ i nie mo¿e zostaæ zaktualizowana"
+ por "Tabela '%-.64s' foi travada com trava de leitura e não pode ser atualizada"
+ rum "Tabela '%-.64s' a fost locked cu un READ lock si nu poate fi actualizata"
+ rus "ôÁÂÌÉÃÁ '%-.64s' ÚÁÂÌÏËÉÒÏ×ÁÎÁ ÕÒÏ×ÎÅÍ READ lock É ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÁ"
+ serbian "Tabela '%-.64s' je zakljuèana READ lock-om; iz nje se može samo èitati ali u nju se ne može pisati"
+ slo "Tabuµka '%-.64s' bola zamknutá s READ a nemô¾e by» zmenená"
+ spa "Tabla '%-.64s' fue trabada con un READ lock y no puede ser actualizada"
+ swe "Tabell '%-.64s' kan inte uppdateras emedan den är låst för läsning"
+ ukr "ôÁÂÌÉÃÀ '%-.64s' ÚÁÂÌÏËÏ×ÁÎÏ Ô¦ÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ, ÔÏÍÕ §§ ÎÅ ÍÏÖÎÁ ÏÎÏ×ÉÔÉ"
+ER_TABLE_NOT_LOCKED
+ cze "Tabulka '%-.64s' nebyla zam-Bèena s LOCK TABLES"
+ dan "Tabellen '%-.64s' var ikke låst med LOCK TABLES"
+ nla "Tabel '%-.64s' was niet gelocked met LOCK TABLES"
+ eng "Table '%-.64s' was not locked with LOCK TABLES"
+ jps "Table '%-.64s' ‚Í LOCK TABLES ‚É‚æ‚Á‚ăƒbƒN‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
+ est "Tabel '%-.64s' ei ole lukustatud käsuga LOCK TABLES"
+ fre "Table '%-.64s' non verrouillée: utilisez LOCK TABLES"
+ ger "Tabelle '%-.64s' wurde nicht mit LOCK TABLES gesperrt"
+ greek "Ï ðßíáêáò '%-.64s' äåí Ý÷åé êëåéäùèåß ìå LOCK TABLES"
+ hun "A(z) '%-.64s' tabla nincs zarolva a LOCK TABLES-szel"
+ ita "Non e` stato impostato il lock per la tabella '%-.64s' con LOCK TABLES"
+ jpn "Table '%-.64s' ¤Ï LOCK TABLES ¤Ë¤è¤Ã¤Æ¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+ kor "Å×À̺í '%-.64s'´Â LOCK TABLES ¸í·ÉÀ¸·Î Àá±âÁö ¾Ê¾Ò½À´Ï´Ù."
+ nor "Tabellen '%-.64s' var ikke låst med LOCK TABLES"
+ norwegian-ny "Tabellen '%-.64s' var ikkje låst med LOCK TABLES"
+ pol "Tabela '%-.64s' nie zosta³a zablokowana poleceniem LOCK TABLES"
+ por "Tabela '%-.64s' não foi travada com LOCK TABLES"
+ rum "Tabela '%-.64s' nu a fost locked cu LOCK TABLES"
+ rus "ôÁÂÌÉÃÁ '%-.64s' ÎÅ ÂÙÌÁ ÚÁÂÌÏËÉÒÏ×ÁÎÁ Ó ÐÏÍÏÝØÀ LOCK TABLES"
+ serbian "Tabela '%-.64s' nije bila zakljuèana komandom 'LOCK TABLES'"
+ slo "Tabuµka '%-.64s' nebola zamknutá s LOCK TABLES"
+ spa "Tabla '%-.64s' no fue trabada con LOCK TABLES"
+ swe "Tabell '%-.64s' är inte låst med LOCK TABLES"
+ ukr "ôÁÂÌÉÃÀ '%-.64s' ÎÅ ÂÕÌÏ ÂÌÏËÏ×ÁÎÏ Ú LOCK TABLES"
+ER_BLOB_CANT_HAVE_DEFAULT 42000
+ cze "Blob polo-B¾ka '%-.64s' nemù¾e mít defaultní hodnotu"
+ dan "BLOB feltet '%-.64s' kan ikke have en standard værdi"
+ nla "Blob veld '%-.64s' can geen standaardwaarde bevatten"
+ eng "BLOB/TEXT column '%-.64s' can't have a default value"
+ est "BLOB-tüüpi tulp '%-.64s' ei saa omada vaikeväärtust"
+ fre "BLOB '%-.64s' ne peut avoir de valeur par défaut"
+ ger "BLOB-Feld '%-.64s' darf keinen Vorgabewert (DEFAULT) haben"
+ greek "Ôá Blob ðåäßá '%-.64s' äåí ìðïñïýí íá Ý÷ïõí ðñïêáèïñéóìÝíåò ôéìÝò (default value)"
+ hun "A(z) '%-.64s' blob objektumnak nem lehet alapertelmezett erteke"
+ ita "Il campo BLOB '%-.64s' non puo` avere un valore di default"
+ jpn "BLOB column '%-.64s' can't have a default value"
+ kor "BLOB Ä®·³ '%-.64s' ´Â µðÆúÆ® °ªÀ» °¡Áú ¼ö ¾ø½À´Ï´Ù."
+ nor "Blob feltet '%-.64s' kan ikke ha en standard verdi"
+ norwegian-ny "Blob feltet '%-.64s' kan ikkje ha ein standard verdi"
+ pol "Pole typu blob '%-.64s' nie mo¿e mieæ domy?lnej warto?ci"
+ por "Coluna BLOB '%-.64s' não pode ter um valor padrão (default)"
+ rum "Coloana BLOB '%-.64s' nu poate avea o valoare default"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÕËÁÚÙ×ÁÔØ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ ÓÔÏÌÂÃÁ BLOB '%-.64s'"
+ serbian "BLOB kolona '%-.64s' ne može imati default vrednost"
+ slo "Pole BLOB '%-.64s' nemô¾e ma» implicitnú hodnotu"
+ spa "Campo Blob '%-.64s' no puede tener valores patron"
+ swe "BLOB fält '%-.64s' kan inte ha ett DEFAULT-värde"
+ ukr "óÔÏ×ÂÅÃØ BLOB '%-.64s' ÎÅ ÍÏÖÅ ÍÁÔÉ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ"
+ER_WRONG_DB_NAME 42000
+ cze "Nep-Bøípustné jméno databáze '%-.64s'"
+ dan "Ugyldigt database navn '%-.64s'"
+ nla "Databasenaam '%-.64s' is niet getoegestaan"
+ eng "Incorrect database name '%-.100s'"
+ jps "Žw’肵‚½ database –¼ '%-.100s' ‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·",
+ est "Vigane andmebaasi nimi '%-.100s'"
+ fre "Nom de base de donnée illégal: '%-.64s'"
+ ger "Unerlaubter Datenbankname '%-.64s'"
+ greek "ËÜèïò üíïìá âÜóçò äåäïìÝíùí '%-.100s'"
+ hun "Hibas adatbazisnev: '%-.100s'"
+ ita "Nome database errato '%-.100s'"
+ jpn "»ØÄꤷ¤¿ database ̾ '%-.100s' ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹"
+ kor "'%-.100s' µ¥ÀÌŸº£À̽ºÀÇ À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù."
+ nor "Ugyldig database navn '%-.64s'"
+ norwegian-ny "Ugyldig database namn '%-.64s'"
+ pol "Niedozwolona nazwa bazy danych '%-.64s'"
+ por "Nome de banco de dados '%-.100s' incorreto"
+ rum "Numele bazei de date este incorect '%-.100s'"
+ rus "îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÂÁÚÙ ÄÁÎÎÙÈ '%-.100s'"
+ serbian "Pogrešno ime baze '%-.100s'"
+ slo "Neprípustné meno databázy '%-.100s'"
+ spa "Nombre de base de datos ilegal '%-.64s'"
+ swe "Felaktigt databasnamn '%-.64s'"
+ ukr "îÅצÒÎÅ ¦Í'Ñ ÂÁÚÉ ÄÁÎÎÉÈ '%-.100s'"
+ER_WRONG_TABLE_NAME 42000
+ cze "Nep-Bøípustné jméno tabulky '%-.64s'"
+ dan "Ugyldigt tabel navn '%-.64s'"
+ nla "Niet toegestane tabelnaam '%-.64s'"
+ eng "Incorrect table name '%-.100s'"
+ jps "Žw’肵‚½ table –¼ '%-.100s' ‚Í‚Ü‚¿‚ª‚Á‚Ä‚¢‚Ü‚·",
+ est "Vigane tabeli nimi '%-.100s'"
+ fre "Nom de table illégal: '%-.64s'"
+ ger "Unerlaubter Tabellenname '%-.64s'"
+ greek "ËÜèïò üíïìá ðßíáêá '%-.100s'"
+ hun "Hibas tablanev: '%-.100s'"
+ ita "Nome tabella errato '%-.100s'"
+ jpn "»ØÄꤷ¤¿ table ̾ '%-.100s' ¤Ï¤Þ¤Á¤¬¤Ã¤Æ¤¤¤Þ¤¹"
+ kor "'%-.100s' Å×À̺í À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù."
+ nor "Ugyldig tabell navn '%-.64s'"
+ norwegian-ny "Ugyldig tabell namn '%-.64s'"
+ pol "Niedozwolona nazwa tabeli '%-.64s'..."
+ por "Nome de tabela '%-.100s' incorreto"
+ rum "Numele tabelei este incorect '%-.100s'"
+ rus "îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÔÁÂÌÉÃÙ '%-.100s'"
+ serbian "Pogrešno ime tabele '%-.100s'"
+ slo "Neprípustné meno tabuµky '%-.100s'"
+ spa "Nombre de tabla ilegal '%-.64s'"
+ swe "Felaktigt tabellnamn '%-.64s'"
+ ukr "îÅצÒÎÅ ¦Í'Ñ ÔÁÂÌÉæ '%-.100s'"
+ER_TOO_BIG_SELECT 42000
+ cze "Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET SQL_BIG_SELECTS=1"
+ dan "SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET SQL_BIG_SELECTS=1 hvis udtrykket er korrekt"
+ nla "Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET SQL_BIG_SELECTS=1 als het stament in orde is."
+ eng "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"
+ est "SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1"
+ fre "SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien"
+ ger "Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange dauern. Bitte WHERE-Klausel überprüfen oder gegebenenfalls SET SQL_BIG_SELECTS=1 oder SET SQL_MAX_JOIN_SIZE=# verwenden"
+ greek "Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü"
+ hun "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"
+ ita "La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto."
+ kor "SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä."
+ nor "SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt"
+ norwegian-ny "SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt"
+ pol "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"
+ por "O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET SQL_BIG_SELECTS=1, se o SELECT estiver correto"
+ rum "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"
+ rus "äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET SQL_BIG_SELECTS=1"
+ serbian "Komanda 'SELECT' æe ispitati previše slogova i potrošiti previše vremena. Proverite vaš 'WHERE' filter i upotrebite 'SET OPTION SQL_BIG_SELECTS=1' ako želite baš ovakvu komandu"
+ slo "Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET SQL_BIG_SELECTS=1"
+ spa "El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET SQL_BIG_SELECTS=1 si el SELECT esta correcto"
+ swe "Den angivna frågan skulle läsa mer än MAX_JOIN_SIZE rader. Kontrollera din WHERE och använd SET SQL_BIG_SELECTS=1 eller SET MAX_JOIN_SIZE=# ifall du vill hantera stora joins"
+ ukr "úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ"
+ER_UNKNOWN_ERROR
+ cze "Nezn-Bámá chyba"
+ dan "Ukendt fejl"
+ nla "Onbekende Fout"
+ eng "Unknown error"
+ est "Tundmatu viga"
+ fre "Erreur inconnue"
+ ger "Unbekannter Fehler"
+ greek "ÐñïÝêõøå Üãíùóôï ëÜèïò"
+ hun "Ismeretlen hiba"
+ ita "Errore sconosciuto"
+ kor "¾Ë¼ö ¾ø´Â ¿¡·¯ÀÔ´Ï´Ù."
+ nor "Ukjent feil"
+ norwegian-ny "Ukjend feil"
+ por "Erro desconhecido"
+ rum "Eroare unknown"
+ rus "îÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ"
+ serbian "Nepoznata greška"
+ slo "Neznámá chyba"
+ spa "Error desconocido"
+ swe "Oidentifierat fel"
+ ukr "îÅצÄÏÍÁ ÐÏÍÉÌËÁ"
+ER_UNKNOWN_PROCEDURE 42000
+ cze "Nezn-Bámá procedura %s"
+ dan "Ukendt procedure %s"
+ nla "Onbekende procedure %s"
+ eng "Unknown procedure '%-.64s'"
+ est "Tundmatu protseduur '%-.64s'"
+ fre "Procédure %s inconnue"
+ ger "Unbekannte Prozedur '%-.64s'"
+ greek "Áãíùóôç äéáäéêáóßá '%-.64s'"
+ hun "Ismeretlen eljaras: '%-.64s'"
+ ita "Procedura '%-.64s' sconosciuta"
+ kor "¾Ë¼ö ¾ø´Â ¼öÇ๮ : '%-.64s'"
+ nor "Ukjent prosedyre %s"
+ norwegian-ny "Ukjend prosedyre %s"
+ pol "Unkown procedure %s"
+ por "'Procedure' '%-.64s' desconhecida"
+ rum "Procedura unknown '%-.64s'"
+ rus "îÅÉÚ×ÅÓÔÎÁÑ ÐÒÏÃÅÄÕÒÁ '%-.64s'"
+ serbian "Nepoznata procedura '%-.64s'"
+ slo "Neznámá procedúra '%-.64s'"
+ spa "Procedimiento desconocido %s"
+ swe "Okänd procedur: %s"
+ ukr "îÅצÄÏÍÁ ÐÒÏÃÅÄÕÒÁ '%-.64s'"
+ER_WRONG_PARAMCOUNT_TO_PROCEDURE 42000
+ cze "Chybn-Bý poèet parametrù procedury %s"
+ dan "Forkert antal parametre til proceduren %s"
+ nla "Foutief aantal parameters doorgegeven aan procedure %s"
+ eng "Incorrect parameter count to procedure '%-.64s'"
+ est "Vale parameetrite hulk protseduurile '%-.64s'"
+ fre "Mauvais nombre de paramètres pour la procedure %s"
+ ger "Falsche Parameterzahl für Prozedur '%-.64s'"
+ greek "ËÜèïò áñéèìüò ðáñáìÝôñùí óôç äéáäéêáóßá '%-.64s'"
+ hun "Rossz parameter a(z) '%-.64s'eljaras szamitasanal"
+ ita "Numero di parametri errato per la procedura '%-.64s'"
+ kor "'%-.64s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆĶó¸ÞÅÍ"
+ nor "Feil parameter antall til prosedyren %s"
+ norwegian-ny "Feil parameter tal til prosedyra %s"
+ pol "Incorrect parameter count to procedure %s"
+ por "Número de parâmetros incorreto para a 'procedure' '%-.64s'"
+ rum "Procedura '%-.64s' are un numar incorect de parametri"
+ rus "îÅËÏÒÒÅËÔÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.64s'"
+ serbian "Pogrešan broj parametara za proceduru '%-.64s'"
+ slo "Chybný poèet parametrov procedúry '%-.64s'"
+ spa "Equivocado parametro count para procedimiento %s"
+ swe "Felaktigt antal parametrar till procedur %s"
+ ukr "èÉÂÎÁ ˦ÌØ˦ÓÔØ ÐÁÒÁÍÅÔÒ¦× ÐÒÏÃÅÄÕÒÉ '%-.64s'"
+ER_WRONG_PARAMETERS_TO_PROCEDURE
+ cze "Chybn-Bé parametry procedury %s"
+ dan "Forkert(e) parametre til proceduren %s"
+ nla "Foutieve parameters voor procedure %s"
+ eng "Incorrect parameters to procedure '%-.64s'"
+ est "Vigased parameetrid protseduurile '%-.64s'"
+ fre "Paramètre erroné pour la procedure %s"
+ ger "Falsche Parameter für Prozedur '%-.64s'"
+ greek "ËÜèïò ðáñÜìåôñïé óôçí äéáäéêáóßá '%-.64s'"
+ hun "Rossz parameter a(z) '%-.64s' eljarasban"
+ ita "Parametri errati per la procedura '%-.64s'"
+ kor "'%-.64s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆĶó¸ÞÅÍ"
+ nor "Feil parametre til prosedyren %s"
+ norwegian-ny "Feil parameter til prosedyra %s"
+ pol "Incorrect parameters to procedure %s"
+ por "Parâmetros incorretos para a 'procedure' '%-.64s'"
+ rum "Procedura '%-.64s' are parametrii incorecti"
+ rus "îÅËÏÒÒÅËÔÎÙÅ ÐÁÒÁÍÅÔÒÙ ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.64s'"
+ serbian "Pogrešni parametri prosleðeni proceduri '%-.64s'"
+ slo "Chybné parametre procedúry '%-.64s'"
+ spa "Equivocados parametros para procedimiento %s"
+ swe "Felaktiga parametrar till procedur %s"
+ ukr "èÉÂÎÉÊ ÐÁÒÁÍÅÔÅÒ ÐÒÏÃÅÄÕÒÉ '%-.64s'"
+ER_UNKNOWN_TABLE 42S02
+ cze "Nezn-Bámá tabulka '%-.64s' v %s"
+ dan "Ukendt tabel '%-.64s' i %s"
+ nla "Onbekende tabel '%-.64s' in %s"
+ eng "Unknown table '%-.64s' in %-.32s"
+ est "Tundmatu tabel '%-.64s' %-.32s-s"
+ fre "Table inconnue '%-.64s' dans %s"
+ ger "Unbekannte Tabelle '%-.64s' in '%-.64s'"
+ greek "Áãíùóôïò ðßíáêáò '%-.64s' óå %s"
+ hun "Ismeretlen tabla: '%-.64s' %s-ban"
+ ita "Tabella '%-.64s' sconosciuta in %s"
+ jpn "Unknown table '%-.64s' in %s"
+ kor "¾Ë¼ö ¾ø´Â Å×À̺í '%-.64s' (µ¥ÀÌŸº£À̽º %s)"
+ nor "Ukjent tabell '%-.64s' i %s"
+ norwegian-ny "Ukjend tabell '%-.64s' i %s"
+ pol "Unknown table '%-.64s' in %s"
+ por "Tabela '%-.64s' desconhecida em '%-.32s'"
+ rum "Tabla '%-.64s' invalida in %-.32s"
+ rus "îÅÉÚ×ÅÓÔÎÁÑ ÔÁÂÌÉÃÁ '%-.64s' × %-.32s"
+ serbian "Nepoznata tabela '%-.64s' u '%-.32s'"
+ slo "Neznáma tabuµka '%-.64s' v %s"
+ spa "Tabla desconocida '%-.64s' in %s"
+ swe "Okänd tabell '%-.64s' i '%-.64s'"
+ ukr "îÅצÄÏÍÁ ÔÁÂÌÉÃÑ '%-.64s' Õ %-.32s"
+ER_FIELD_SPECIFIED_TWICE 42000
+ cze "Polo-B¾ka '%-.64s' je zadána dvakrát"
+ dan "Feltet '%-.64s' er anvendt to gange"
+ nla "Veld '%-.64s' is dubbel gespecificeerd"
+ eng "Column '%-.64s' specified twice"
+ est "Tulp '%-.64s' on määratletud topelt"
+ fre "Champ '%-.64s' spécifié deux fois"
+ ger "Feld '%-.64s' wurde zweimal angegeben"
+ greek "Ôï ðåäßï '%-.64s' Ý÷åé ïñéóèåß äýï öïñÝò"
+ hun "A(z) '%-.64s' mezot ketszer definialta"
+ ita "Campo '%-.64s' specificato 2 volte"
+ kor "Ä®·³ '%-.64s'´Â µÎ¹ø Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù."
+ nor "Feltet '%-.64s' er spesifisert to ganger"
+ norwegian-ny "Feltet '%-.64s' er spesifisert to gangar"
+ pol "Field '%-.64s' specified twice"
+ por "Coluna '%-.64s' especificada duas vezes"
+ rum "Coloana '%-.64s' specificata de doua ori"
+ rus "óÔÏÌÂÅà '%-.64s' ÕËÁÚÁÎ Ä×ÁÖÄÙ"
+ serbian "Kolona '%-.64s' je navedena dva puta"
+ slo "Pole '%-.64s' je zadané dvakrát"
+ spa "Campo '%-.64s' especificado dos veces"
+ swe "Fält '%-.64s' är redan använt"
+ ukr "óÔÏ×ÂÅÃØ '%-.64s' ÚÁÚÎÁÞÅÎÏ Äצަ"
+ER_INVALID_GROUP_FUNC_USE
+ cze "Nespr-Bávné pou¾ití funkce group"
+ dan "Forkert brug af grupperings-funktion"
+ nla "Ongeldig gebruik van GROUP-functie"
+ eng "Invalid use of group function"
+ est "Vigane grupeerimisfunktsiooni kasutus"
+ fre "Utilisation invalide de la clause GROUP"
+ ger "Falsche Verwendung einer Gruppierungsfunktion"
+ greek "ÅóöáëìÝíç ÷ñÞóç ôçò group function"
+ hun "A group funkcio ervenytelen hasznalata"
+ ita "Uso non valido di una funzione di raggruppamento"
+ kor "À߸øµÈ ±×·ì ÇÔ¼ö¸¦ »ç¿ëÇÏ¿´½À´Ï´Ù."
+ por "Uso inválido de função de agrupamento (GROUP)"
+ rum "Folosire incorecta a functiei group"
+ rus "îÅÐÒÁ×ÉÌØÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÇÒÕÐÐÏ×ÙÈ ÆÕÎËÃÉÊ"
+ serbian "Pogrešna upotreba 'GROUP' funkcije"
+ slo "Nesprávne pou¾itie funkcie GROUP"
+ spa "Invalido uso de función en grupo"
+ swe "Felaktig användning av SQL grupp function"
+ ukr "èÉÂÎÅ ×ÉËÏÒÉÓÔÁÎÎÑ ÆÕÎËæ§ ÇÒÕÐÕ×ÁÎÎÑ"
+ER_UNSUPPORTED_EXTENSION 42000
+ cze "Tabulka '%-.64s' pou-B¾ívá roz¹íøení, které v této verzi MySQL není"
+ dan "Tabellen '%-.64s' bruger et filtypenavn som ikke findes i denne MySQL version"
+ nla "Tabel '%-.64s' gebruikt een extensie, die niet in deze MySQL-versie voorkomt."
+ eng "Table '%-.64s' uses an extension that doesn't exist in this MySQL version"
+ est "Tabel '%-.64s' kasutab laiendust, mis ei eksisteeri antud MySQL versioonis"
+ fre "Table '%-.64s' : utilise une extension invalide pour cette version de MySQL"
+ ger "Tabelle '%-.64s' verwendet eine Extension, die in dieser MySQL-Version nicht verfügbar ist"
+ greek "Ï ðßíáêò '%-.64s' ÷ñçóéìïðïéåß êÜðïéï extension ðïõ äåí õðÜñ÷åé óôçí Ýêäïóç áõôÞ ôçò MySQL"
+ hun "A(z) '%-.64s' tabla olyan bovitest hasznal, amely nem letezik ebben a MySQL versioban."
+ ita "La tabella '%-.64s' usa un'estensione che non esiste in questa versione di MySQL"
+ kor "Å×À̺í '%-.64s'´Â È®Àå¸í·ÉÀ» ÀÌ¿ëÇÏÁö¸¸ ÇöÀçÀÇ MySQL ¹öÁ¯¿¡¼­´Â Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù."
+ nor "Table '%-.64s' uses a extension that doesn't exist in this MySQL version"
+ norwegian-ny "Table '%-.64s' uses a extension that doesn't exist in this MySQL version"
+ pol "Table '%-.64s' uses a extension that doesn't exist in this MySQL version"
+ por "Tabela '%-.64s' usa uma extensão que não existe nesta versão do MySQL"
+ rum "Tabela '%-.64s' foloseste o extensire inexistenta in versiunea curenta de MySQL"
+ rus "÷ ÔÁÂÌÉÃÅ '%-.64s' ÉÓÐÏÌØÚÕÀÔÓÑ ×ÏÚÍÏÖÎÏÓÔÉ, ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÍÙÅ × ÜÔÏÊ ×ÅÒÓÉÉ MySQL"
+ serbian "Tabela '%-.64s' koristi ekstenziju koje ne postoji u ovoj verziji MySQL-a"
+ slo "Tabuµka '%-.64s' pou¾íva roz¹írenie, ktoré v tejto verzii MySQL nie je"
+ spa "Tabla '%-.64s' usa una extensión que no existe en esta MySQL versión"
+ swe "Tabell '%-.64s' har en extension som inte finns i denna version av MySQL"
+ ukr "ôÁÂÌÉÃÑ '%-.64s' ×ÉËÏÒÉÓÔÏ×Õ¤ ÒÏÚÛÉÒÅÎÎÑ, ÝÏ ÎÅ ¦ÓÎÕ¤ Õ Ã¦Ê ×ÅÒÓ¦§ MySQL"
+ER_TABLE_MUST_HAVE_COLUMNS 42000
+ cze "Tabulka mus-Bí mít alespoò jeden sloupec"
+ dan "En tabel skal have mindst een kolonne"
+ nla "Een tabel moet minstens 1 kolom bevatten"
+ eng "A table must have at least 1 column"
+ jps "ƒe[ƒuƒ‹‚ÍÅ’á 1 ŒÂ‚Ì column ‚ª•K—v‚Å‚·",
+ est "Tabelis peab olema vähemalt üks tulp"
+ fre "Une table doit comporter au moins une colonne"
+ ger "Eine Tabelle muß mindestens 1 Spalte besitzen"
+ greek "Åíáò ðßíáêáò ðñÝðåé íá Ý÷åé ôïõëÜ÷éóôïí Ýíá ðåäßï"
+ hun "A tablanak legalabb egy oszlopot tartalmazni kell"
+ ita "Una tabella deve avere almeno 1 colonna"
+ jpn "¥Æ¡¼¥Ö¥ë¤ÏºÇÄã 1 ¸Ä¤Î column ¤¬É¬ÍפǤ¹"
+ kor "ÇϳªÀÇ Å×ÀÌºí¿¡¼­´Â Àû¾îµµ ÇϳªÀÇ Ä®·³ÀÌ Á¸ÀçÇÏ¿©¾ß ÇÕ´Ï´Ù."
+ por "Uma tabela tem que ter pelo menos uma (1) coluna"
+ rum "O tabela trebuie sa aiba cel putin o coloana"
+ rus "÷ ÔÁÂÌÉÃÅ ÄÏÌÖÅÎ ÂÙÔØ ËÁË ÍÉÎÉÍÕÍ ÏÄÉÎ ÓÔÏÌÂÅÃ"
+ serbian "Tabela mora imati najmanje jednu kolonu"
+ slo "Tabuµka musí ma» aspoò 1 pole"
+ spa "Una tabla debe tener al menos 1 columna"
+ swe "Tabeller måste ha minst 1 kolumn"
+ ukr "ôÁÂÌÉÃÑ ÐÏ×ÉÎÎÁ ÍÁÔÉ ÈÏÞÁ ÏÄÉÎ ÓÔÏ×ÂÅÃØ"
+ER_RECORD_FILE_FULL
+ cze "Tabulka '%-.64s' je pln-Bá"
+ dan "Tabellen '%-.64s' er fuld"
+ nla "De tabel '%-.64s' is vol"
+ eng "The table '%-.64s' is full"
+ jps "table '%-.64s' ‚Í‚¢‚Á‚Ï‚¢‚Å‚·",
+ est "Tabel '%-.64s' on täis"
+ fre "La table '%-.64s' est pleine"
+ ger "Tabelle '%-.64s' ist voll"
+ greek "Ï ðßíáêáò '%-.64s' åßíáé ãåìÜôïò"
+ hun "A '%-.64s' tabla megtelt"
+ ita "La tabella '%-.64s' e` piena"
+ jpn "table '%-.64s' ¤Ï¤¤¤Ã¤Ñ¤¤¤Ç¤¹"
+ kor "Å×À̺í '%-.64s'°¡ full³µ½À´Ï´Ù. "
+ por "Tabela '%-.64s' está cheia"
+ rum "Tabela '%-.64s' e plina"
+ rus "ôÁÂÌÉÃÁ '%-.64s' ÐÅÒÅÐÏÌÎÅÎÁ"
+ serbian "Tabela '%-.64s' je popunjena do kraja"
+ slo "Tabuµka '%-.64s' je plná"
+ spa "La tabla '%-.64s' está llena"
+ swe "Tabellen '%-.64s' är full"
+ ukr "ôÁÂÌÉÃÑ '%-.64s' ÚÁÐÏ×ÎÅÎÁ"
+ER_UNKNOWN_CHARACTER_SET 42000
+ cze "Nezn-Bámá znaková sada: '%-.64s'"
+ dan "Ukendt tegnsæt: '%-.64s'"
+ nla "Onbekende character set: '%-.64s'"
+ eng "Unknown character set: '%-.64s'"
+ jps "character set '%-.64s' ‚̓Tƒ|[ƒg‚µ‚Ä‚¢‚Ü‚¹‚ñ",
+ est "Vigane kooditabel '%-.64s'"
+ fre "Jeu de caractères inconnu: '%-.64s'"
+ ger "Unbekannter Zeichensatz: '%-.64s'"
+ greek "Áãíùóôï character set: '%-.64s'"
+ hun "Ervenytelen karakterkeszlet: '%-.64s'"
+ ita "Set di caratteri '%-.64s' sconosciuto"
+ jpn "character set '%-.64s' ¤Ï¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤»¤ó"
+ kor "¾Ë¼ö¾ø´Â ¾ð¾î Set: '%-.64s'"
+ por "Conjunto de caracteres '%-.64s' desconhecido"
+ rum "Set de caractere invalid: '%-.64s'"
+ rus "îÅÉÚ×ÅÓÔÎÁÑ ËÏÄÉÒÏ×ËÁ '%-.64s'"
+ serbian "Nepoznati karakter-set: '%-.64s'"
+ slo "Neznáma znaková sada: '%-.64s'"
+ spa "Juego de caracteres desconocido: '%-.64s'"
+ swe "Okänd teckenuppsättning: '%-.64s'"
+ ukr "îÅצÄÏÍÁ ËÏÄÏ×Á ÔÁÂÌÉÃÑ: '%-.64s'"
+ER_TOO_MANY_TABLES
+ cze "P-Bøíli¹ mnoho tabulek, MySQL jich mù¾e mít v joinu jen %d"
+ dan "For mange tabeller. MySQL kan kun bruge %d tabeller i et join"
+ nla "Teveel tabellen. MySQL kan slechts %d tabellen in een join bevatten"
+ eng "Too many tables; MySQL can only use %d tables in a join"
+ jps "ƒe[ƒuƒ‹‚ª‘½‚·‚¬‚Ü‚·; MySQL can only use %d tables in a join",
+ est "Liiga palju tabeleid. MySQL suudab JOINiga ühendada kuni %d tabelit"
+ fre "Trop de tables. MySQL ne peut utiliser que %d tables dans un JOIN"
+ ger "Zu viele Tabellen. MySQL kann in einem Join maximal %d Tabellen verwenden"
+ greek "Ðïëý ìåãÜëïò áñéèìüò ðéíÜêùí. Ç MySQL ìðïñåß íá ÷ñçóéìïðïéÞóåé %d ðßíáêåò óå äéáäéêáóßá join"
+ hun "Tul sok tabla. A MySQL csak %d tablat tud kezelni osszefuzeskor"
+ ita "Troppe tabelle. MySQL puo` usare solo %d tabelle in una join"
+ jpn "¥Æ¡¼¥Ö¥ë¤¬Â¿¤¹¤®¤Þ¤¹; MySQL can only use %d tables in a join"
+ kor "³Ê¹« ¸¹Àº Å×À̺íÀÌ JoinµÇ¾ú½À´Ï´Ù. MySQL¿¡¼­´Â JOIN½Ã %d°³ÀÇ Å×ÀÌºí¸¸ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù."
+ por "Tabelas demais. O MySQL pode usar somente %d tabelas em uma junção (JOIN)"
+ rum "Prea multe tabele. MySQL nu poate folosi mai mult de %d tabele intr-un join"
+ rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÔÁÂÌÉÃ. MySQL ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØ ÔÏÌØËÏ %d ÔÁÂÌÉÃ × ÓÏÅÄÉÎÅÎÉÉ"
+ serbian "Previše tabela. MySQL može upotrebiti maksimum %d tabela pri 'JOIN' operaciji"
+ slo "Príli¹ mnoho tabuliek. MySQL mô¾e pou¾i» len %d v JOIN-e"
+ spa "Muchas tablas. MySQL solamente puede usar %d tablas en un join"
+ swe "För många tabeller. MySQL can ha högst %d tabeller i en och samma join"
+ ukr "úÁÂÁÇÁÔÏ ÔÁÂÌÉÃØ. MySQL ÍÏÖÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÌÉÛÅ %d ÔÁÂÌÉÃØ Õ ÏÂ'¤ÄÎÁÎΦ"
+ER_TOO_MANY_FIELDS
+ cze "P-Bøíli¹ mnoho polo¾ek"
+ dan "For mange felter"
+ nla "Te veel velden"
+ eng "Too many columns"
+ jps "column ‚ª‘½‚·‚¬‚Ü‚·",
+ est "Liiga palju tulpasid"
+ fre "Trop de champs"
+ ger "Zu viele Spalten"
+ greek "Ðïëý ìåãÜëïò áñéèìüò ðåäßùí"
+ hun "Tul sok mezo"
+ ita "Troppi campi"
+ jpn "column ¤¬Â¿¤¹¤®¤Þ¤¹"
+ kor "Ä®·³ÀÌ ³Ê¹« ¸¹½À´Ï´Ù."
+ por "Colunas demais"
+ rum "Prea multe coloane"
+ rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÓÔÏÌÂÃÏ×"
+ serbian "Previše kolona"
+ slo "Príli¹ mnoho polí"
+ spa "Muchos campos"
+ swe "För många fält"
+ ukr "úÁÂÁÇÁÔÏ ÓÔÏ×Âæ×"
+ER_TOO_BIG_ROWSIZE 42000
+ cze "-BØádek je pøíli¹ velký. Maximální velikost øádku, nepoèítaje polo¾ky blob, je %d. Musíte zmìnit nìkteré polo¾ky na blob"
+ dan "For store poster. Max post størrelse, uden BLOB's, er %d. Du må lave nogle felter til BLOB's"
+ nla "Rij-grootte is groter dan toegestaan. Maximale rij grootte, blobs niet meegeteld, is %d. U dient sommige velden in blobs te veranderen."
+ eng "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"
+ jps "row size ‚ª‘å‚«‚·‚¬‚Ü‚·. BLOB ‚ðŠÜ‚Ü‚È‚¢ê‡‚Ì row size ‚ÌÅ‘å‚Í %d ‚Å‚·. ‚¢‚­‚‚©‚Ì field ‚ð BLOB ‚É•Ï‚¦‚Ä‚­‚¾‚³‚¢.",
+ est "Liiga pikk kirje. Kirje maksimumpikkus arvestamata BLOB-tüüpi välju on %d. Muuda mõned väljad BLOB-tüüpi väljadeks"
+ fre "Ligne trop grande. Le taille maximale d'une ligne, sauf les BLOBs, est %d. Changez le type de quelques colonnes en BLOB"
+ ger "Zeilenlänge zu groß. Die maximale Spaltenlänge für den verwendeten Tabellentyp (ohne BLOB-Felder) beträgt %d. Einige Felder müssen in BLOB oder TEXT umgewandelt werden"
+ greek "Ðïëý ìåãÜëï ìÝãåèïò åããñáöÞò. Ôï ìÝãéóôï ìÝãåèïò åããñáöÞò, ÷ùñßò íá õðïëïãßæïíôáé ôá blobs, åßíáé %d. ÐñÝðåé íá ïñßóåôå êÜðïéá ðåäßá óáí blobs"
+ hun "Tul nagy sormeret. A maximalis sormeret (nem szamolva a blob objektumokat) %d. Nehany mezot meg kell valtoztatnia"
+ ita "Riga troppo grande. La massima grandezza di una riga, non contando i BLOB, e` %d. Devi cambiare alcuni campi in BLOB"
+ jpn "row size ¤¬Â礭¤¹¤®¤Þ¤¹. BLOB ¤ò´Þ¤Þ¤Ê¤¤¾ì¹ç¤Î row size ¤ÎºÇÂç¤Ï %d ¤Ç¤¹. ¤¤¤¯¤Ä¤«¤Î field ¤ò BLOB ¤ËÊѤ¨¤Æ¤¯¤À¤µ¤¤."
+ kor "³Ê¹« Å« row »çÀÌÁîÀÔ´Ï´Ù. BLOB¸¦ °è»êÇÏÁö ¾Ê°í ÃÖ´ë row »çÀÌÁî´Â %dÀÔ´Ï´Ù. ¾ó¸¶°£ÀÇ ÇʵåµéÀ» BLOB·Î ¹Ù²Ù¼Å¾ß °Ú±º¿ä.."
+ por "Tamanho de linha grande demais. O máximo tamanho de linha, não contando BLOBs, é %d. Você tem que mudar alguns campos para BLOBs"
+ rum "Marimea liniei (row) prea mare. Marimea maxima a liniei, excluzind BLOB-urile este de %d. Trebuie sa schimbati unele cimpuri in BLOB-uri"
+ rus "óÌÉÛËÏÍ ÂÏÌØÛÏÊ ÒÁÚÍÅÒ ÚÁÐÉÓÉ. íÁËÓÉÍÁÌØÎÙÊ ÒÁÚÍÅÒ ÓÔÒÏËÉ, ÉÓËÌÀÞÁÑ ÐÏÌÑ BLOB, - %d. ÷ÏÚÍÏÖÎÏ, ×ÁÍ ÓÌÅÄÕÅÔ ÉÚÍÅÎÉÔØ ÔÉÐ ÎÅËÏÔÏÒÙÈ ÐÏÌÅÊ ÎÁ BLOB"
+ serbian "Prevelik slog. Maksimalna velièina sloga, ne raèunajuæi BLOB polja, je %d. Trebali bi da promenite tip nekih polja u BLOB"
+ slo "Riadok je príli¹ veµký. Maximálna veµkos» riadku, okrem 'BLOB', je %d. Musíte zmeni» niektoré polo¾ky na BLOB"
+ spa "Tamaño de línea muy grande. Máximo tamaño de línea, no contando blob, es %d. Tu tienes que cambiar algunos campos para blob"
+ swe "För stor total radlängd. Den högst tillåtna radlängden, förutom BLOBs, är %d. Ändra några av dina fält till BLOB"
+ ukr "úÁÄÏ×ÇÁ ÓÔÒÏËÁ. îÁʦÌØÛÏÀ ÄÏ×ÖÉÎÏÀ ÓÔÒÏËÉ, ÎÅ ÒÁÈÕÀÞÉ BLOB, ¤ %d. ÷ÁÍ ÐÏÔÒ¦ÂÎÏ ÐÒÉ×ÅÓÔÉ ÄÅÑ˦ ÓÔÏ×Âæ ÄÏ ÔÉÐÕ BLOB"
+ER_STACK_OVERRUN
+ cze "P-Bøeteèení zásobníku threadu: pou¾ito %ld z %ld. Pou¾ijte 'mysqld -O thread_stack=#' k zadání vìt¹ího zásobníku"
+ dan "Thread stack brugt: Brugt: %ld af en %ld stak. Brug 'mysqld -O thread_stack=#' for at allokere en større stak om nødvendigt"
+ nla "Thread stapel overrun: Gebruikte: %ld van een %ld stack. Gebruik 'mysqld -O thread_stack=#' om een grotere stapel te definieren (indien noodzakelijk)."
+ eng "Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed"
+ jps "Thread stack overrun: Used: %ld of a %ld stack. ƒXƒ^ƒbƒN—̈æ‚𑽂­‚Ƃ肽‚¢ê‡A'mysqld -O thread_stack=#' ‚ÆŽw’肵‚Ä‚­‚¾‚³‚¢",
+ fre "Débordement de la pile des tâches (Thread stack). Utilisées: %ld pour une pile de %ld. Essayez 'mysqld -O thread_stack=#' pour indiquer une plus grande valeur"
+ ger "Thread-Stack-Überlauf. Benutzt: %ld von %ld Stack. 'mysqld -O thread_stack=#' verwenen, um notfalls einen größeren Stack anzulegen"
+ greek "Stack overrun óôï thread: Used: %ld of a %ld stack. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå 'mysqld -O thread_stack=#' ãéá íá ïñßóåôå Ýíá ìåãáëýôåñï stack áí ÷ñåéÜæåôáé"
+ hun "Thread verem tullepes: Used: %ld of a %ld stack. Hasznalja a 'mysqld -O thread_stack=#' nagyobb verem definialasahoz"
+ ita "Thread stack overrun: Usati: %ld di uno stack di %ld. Usa 'mysqld -O thread_stack=#' per specificare uno stack piu` grande."
+ jpn "Thread stack overrun: Used: %ld of a %ld stack. ¥¹¥¿¥Ã¥¯Îΰè¤ò¿¤¯¤È¤ê¤¿¤¤¾ì¹ç¡¢'mysqld -O thread_stack=#' ¤È»ØÄꤷ¤Æ¤¯¤À¤µ¤¤"
+ kor "¾²·¹µå ½ºÅÃÀÌ ³ÑÃƽÀ´Ï´Ù. »ç¿ë: %ld°³ ½ºÅÃ: %ld°³. ¸¸¾à ÇÊ¿ä½Ã ´õÅ« ½ºÅÃÀ» ¿øÇÒ¶§¿¡´Â 'mysqld -O thread_stack=#' ¸¦ Á¤ÀÇÇϼ¼¿ä"
+ por "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"
+ rum "Stack-ul thread-ului a fost depasit (prea mic): Folositi: %ld intr-un stack de %ld. Folositi 'mysqld -O thread_stack=#' ca sa specifici un stack mai mare"
+ rus "óÔÅË ÐÏÔÏËÏ× ÐÅÒÅÐÏÌÎÅÎ: ÉÓÐÏÌØÚÏ×ÁÎÏ: %ld ÉÚ %ld ÓÔÅËÁ. ðÒÉÍÅÎÑÊÔÅ 'mysqld -O thread_stack=#' ÄÌÑ ÕËÁÚÁÎÉÑ ÂÏÌØÛÅÇÏ ÒÁÚÍÅÒÁ ÓÔÅËÁ, ÅÓÌÉ ÎÅÏÂÈÏÄÉÍÏ"
+ serbian "Prepisivanje thread stack-a: Upotrebljeno: %ld od %ld stack memorije. Upotrebite 'mysqld -O thread_stack=#' da navedete veæi stack ako je potrebno"
+ slo "Preteèenie zásobníku vlákna: pou¾ité: %ld z %ld. Pou¾ite 'mysqld -O thread_stack=#' k zadaniu väè¹ieho zásobníka"
+ spa "Sobrecarga de la pila de thread: Usada: %ld de una %ld pila. Use 'mysqld -O thread_stack=#' para especificar una mayor pila si necesario"
+ swe "Trådstacken tog slut: Har använt %ld av %ld bytes. Använd 'mysqld -O thread_stack=#' ifall du behöver en större stack"
+ ukr "óÔÅË Ç¦ÌÏË ÐÅÒÅÐÏ×ÎÅÎÏ: ÷ÉËÏÒÉÓÔÁÎÏ: %ld Ú %ld. ÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ 'mysqld -O thread_stack=#' ÁÂÉ ÚÁÚÎÁÞÉÔÉ Â¦ÌØÛÉÊ ÓÔÅË, ÑËÝÏ ÎÅÏÂȦÄÎÏ"
+ER_WRONG_OUTER_JOIN 42000
+ cze "V OUTER JOIN byl nalezen k-Bøí¾ový odkaz. Provìøte ON podmínky"
+ dan "Krydsreferencer fundet i OUTER JOIN; check dine ON conditions"
+ nla "Gekruiste afhankelijkheid gevonden in OUTER JOIN. Controleer uw ON-conditions"
+ eng "Cross dependency found in OUTER JOIN; examine your ON conditions"
+ est "Ristsõltuvus OUTER JOIN klauslis. Kontrolli oma ON tingimusi"
+ fre "Dépendance croisée dans une clause OUTER JOIN. Vérifiez la condition ON"
+ ger "OUTER JOIN enthält fehlerhafte Abhängigkeiten. In ON verwendete Bedingungen überprüfen"
+ greek "Cross dependency âñÝèçêå óå OUTER JOIN. Ðáñáêáëþ åîåôÜóôå ôéò óõíèÞêåò ðïõ èÝóáôå óôï ON"
+ hun "Keresztfuggoseg van az OUTER JOIN-ban. Ellenorizze az ON felteteleket"
+ ita "Trovata una dipendenza incrociata nella OUTER JOIN. Controlla le condizioni ON"
+ por "Dependência cruzada encontrada em junção externa (OUTER JOIN); examine as condições utilizadas nas cláusulas 'ON'"
+ rum "Dependinta incrucisata (cross dependency) gasita in OUTER JOIN. Examinati conditiile ON"
+ rus "÷ OUTER JOIN ÏÂÎÁÒÕÖÅÎÁ ÐÅÒÅËÒÅÓÔÎÁÑ ÚÁ×ÉÓÉÍÏÓÔØ. ÷ÎÉÍÁÔÅÌØÎÏ ÐÒÏÁÎÁÌÉÚÉÒÕÊÔÅ Ó×ÏÉ ÕÓÌÏ×ÉÑ ON"
+ serbian "Unakrsna zavisnost pronaðena u komandi 'OUTER JOIN'. Istražite vaše 'ON' uslove"
+ slo "V OUTER JOIN bol nájdený krí¾ový odkaz. Skontrolujte podmienky ON"
+ spa "Dependencia cruzada encontrada en OUTER JOIN. Examine su condición ON"
+ swe "Felaktigt referens i OUTER JOIN. Kontrollera ON-uttrycket"
+ ukr "ðÅÒÅÈÒÅÓÎÁ ÚÁÌÅÖΦÓÔØ Õ OUTER JOIN. ðÅÒÅצÒÔÅ ÕÍÏ×Õ ON"
+ER_NULL_COLUMN_IN_INDEX 42000
+ cze "Sloupec '%-.32s' je pou-B¾it s UNIQUE nebo INDEX, ale není definován jako NOT NULL"
+ dan "Kolonne '%-.32s' bruges som UNIQUE eller INDEX men er ikke defineret som NOT NULL"
+ nla "Kolom '%-.64s' wordt gebruikt met UNIQUE of INDEX maar is niet gedefinieerd als NOT NULL"
+ eng "Column '%-.64s' is used with UNIQUE or INDEX but is not defined as NOT NULL"
+ jps "Column '%-.64s' ‚ª UNIQUE ‚© INDEX ‚ÅŽg—p‚³‚ê‚Ü‚µ‚½. ‚±‚̃Jƒ‰ƒ€‚Í NOT NULL ‚Æ’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ.",
+ est "Tulp '%-.64s' on kasutusel indeksina, kuid ei ole määratletud kui NOT NULL"
+ fre "La colonne '%-.32s' fait partie d'un index UNIQUE ou INDEX mais n'est pas définie comme NOT NULL"
+ ger "Spalte '%-.64s' wurde mit UNIQUE oder INDEX benutzt, ist aber nicht als NOT NULL definiert"
+ greek "Ôï ðåäßï '%-.64s' ÷ñçóéìïðïéåßôáé óáí UNIQUE Þ INDEX áëëÜ äåí Ý÷åé ïñéóèåß óáí NOT NULL"
+ hun "A(z) '%-.64s' oszlop INDEX vagy UNIQUE (egyedi), de a definicioja szerint nem NOT NULL"
+ ita "La colonna '%-.64s' e` usata con UNIQUE o INDEX ma non e` definita come NOT NULL"
+ jpn "Column '%-.64s' ¤¬ UNIQUE ¤« INDEX ¤Ç»ÈÍѤµ¤ì¤Þ¤·¤¿. ¤³¤Î¥«¥é¥à¤Ï NOT NULL ¤ÈÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó."
+ kor "'%-.64s' Ä®·³ÀÌ UNIQUE³ª INDEX¸¦ »ç¿ëÇÏ¿´Áö¸¸ NOT NULLÀÌ Á¤ÀǵÇÁö ¾Ê¾Ò±º¿ä..."
+ nor "Column '%-.32s' is used with UNIQUE or INDEX but is not defined as NOT NULL"
+ norwegian-ny "Column '%-.32s' is used with UNIQUE or INDEX but is not defined as NOT NULL"
+ pol "Column '%-.32s' is used with UNIQUE or INDEX but is not defined as NOT NULL"
+ por "Coluna '%-.64s' é usada com única (UNIQUE) ou índice (INDEX), mas não está definida como não-nula (NOT NULL)"
+ rum "Coloana '%-.64s' e folosita cu UNIQUE sau INDEX dar fara sa fie definita ca NOT NULL"
+ rus "óÔÏÌÂÅÃ '%-.64s' ÉÓÐÏÌØÚÕÅÔÓÑ × UNIQUE ÉÌÉ × INDEX, ÎÏ ÎÅ ÏÐÒÅÄÅÌÅÎ ËÁË NOT NULL"
+ serbian "Kolona '%-.64s' je upotrebljena kao 'UNIQUE' ili 'INDEX' ali nije definisana kao 'NOT NULL'"
+ slo "Pole '%-.64s' je pou¾ité s UNIQUE alebo INDEX, ale nie je zadefinované ako NOT NULL"
+ spa "Columna '%-.32s' es usada con UNIQUE o INDEX pero no está definida como NOT NULL"
+ swe "Kolumn '%-.32s' är använd med UNIQUE eller INDEX men är inte definerad med NOT NULL"
+ ukr "óÔÏ×ÂÅÃØ '%-.64s' ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ Ú UNIQUE ÁÂÏ INDEX, ÁÌÅ ÎÅ ×ÉÚÎÁÞÅÎÉÊ ÑË NOT NULL"
+ER_CANT_FIND_UDF
+ cze "Nemohu na-Bèíst funkci '%-.64s'"
+ dan "Kan ikke læse funktionen '%-.64s'"
+ nla "Kan functie '%-.64s' niet laden"
+ eng "Can't load function '%-.64s'"
+ jps "function '%-.64s' ‚ð ƒ[ƒh‚Å‚«‚Ü‚¹‚ñ",
+ est "Ei suuda avada funktsiooni '%-.64s'"
+ fre "Imposible de charger la fonction '%-.64s'"
+ ger "Kann Funktion '%-.64s' nicht laden"
+ greek "Äåí åßíáé äõíáôÞ ç äéáäéêáóßá load ãéá ôç óõíÜñôçóç '%-.64s'"
+ hun "A(z) '%-.64s' fuggveny nem toltheto be"
+ ita "Impossibile caricare la funzione '%-.64s'"
+ jpn "function '%-.64s' ¤ò ¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó"
+ kor "'%-.64s' ÇÔ¼ö¸¦ ·ÎµåÇÏÁö ¸øÇß½À´Ï´Ù."
+ por "Não pode carregar a função '%-.64s'"
+ rum "Nu pot incarca functia '%-.64s'"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÚÁÇÒÕÚÉÔØ ÆÕÎËÃÉÀ '%-.64s'"
+ serbian "Ne mogu da uèitam funkciju '%-.64s'"
+ slo "Nemô¾em naèíta» funkciu '%-.64s'"
+ spa "No puedo cargar función '%-.64s'"
+ swe "Kan inte ladda funktionen '%-.64s'"
+ ukr "îÅ ÍÏÖÕ ÚÁ×ÁÎÔÁÖÉÔÉ ÆÕÎËæÀ '%-.64s'"
+ER_CANT_INITIALIZE_UDF
+ cze "Nemohu inicializovat funkci '%-.64s'; %-.80s"
+ dan "Kan ikke starte funktionen '%-.64s'; %-.80s"
+ nla "Kan functie '%-.64s' niet initialiseren; %-.80s"
+ eng "Can't initialize function '%-.64s'; %-.80s"
+ jps "function '%-.64s' ‚ð‰Šú‰»‚Å‚«‚Ü‚¹‚ñ; %-.80s",
+ est "Ei suuda algväärtustada funktsiooni '%-.64s'; %-.80s"
+ fre "Impossible d'initialiser la fonction '%-.64s'; %-.80s"
+ ger "Kann Funktion '%-.64s' nicht initialisieren: %-.80s"
+ greek "Äåí åßíáé äõíáôÞ ç Ýíáñîç ôçò óõíÜñôçóçò '%-.64s'; %-.80s"
+ hun "A(z) '%-.64s' fuggveny nem inicializalhato; %-.80s"
+ ita "Impossibile inizializzare la funzione '%-.64s'; %-.80s"
+ jpn "function '%-.64s' ¤ò½é´ü²½¤Ç¤­¤Þ¤»¤ó; %-.80s"
+ kor "'%-.64s' ÇÔ¼ö¸¦ ÃʱâÈ­ ÇÏÁö ¸øÇß½À´Ï´Ù.; %-.80s"
+ por "Não pode inicializar a função '%-.64s' - '%-.80s'"
+ rum "Nu pot initializa functia '%-.64s'; %-.80s"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÔØ ÆÕÎËÃÉÀ '%-.64s'; %-.80s"
+ serbian "Ne mogu da inicijalizujem funkciju '%-.64s'; %-.80s"
+ slo "Nemô¾em inicializova» funkciu '%-.64s'; %-.80s"
+ spa "No puedo inicializar función '%-.64s'; %-.80s"
+ swe "Kan inte initialisera funktionen '%-.64s'; '%-.80s'"
+ ukr "îÅ ÍÏÖÕ ¦Î¦Ã¦Á̦ÚÕ×ÁÔÉ ÆÕÎËæÀ '%-.64s'; %-.80s"
+ER_UDF_NO_PATHS
+ cze "Pro sd-Bílenou knihovnu nejsou povoleny cesty"
+ dan "Angivelse af sti ikke tilladt for delt bibliotek"
+ nla "Geen pad toegestaan voor shared library"
+ eng "No paths allowed for shared library"
+ jps "shared library ‚ւ̃pƒX‚ª’Ê‚Á‚Ä‚¢‚Ü‚¹‚ñ",
+ est "Teegi nimes ei tohi olla kataloogi"
+ fre "Chemin interdit pour les bibliothèques partagées"
+ ger "Keine Pfade gestattet für Shared Library"
+ greek "Äåí âñÝèçêáí paths ãéá ôçí shared library"
+ hun "Nincs ut a megosztott konyvtarakhoz (shared library)"
+ ita "Non sono ammessi path per le librerie condivisa"
+ jpn "shared library ¤Ø¤Î¥Ñ¥¹¤¬Ä̤äƤ¤¤Þ¤»¤ó"
+ kor "°øÀ¯ ¶óÀ̹ö·¯¸®¸¦ À§ÇÑ Æнº°¡ Á¤ÀǵǾî ÀÖÁö ¾Ê½À´Ï´Ù."
+ por "Não há caminhos (paths) permitidos para biblioteca compartilhada"
+ rum "Nici un paths nu e permis pentru o librarie shared"
+ rus "îÅÄÏÐÕÓÔÉÍÏ ÕËÁÚÙ×ÁÔØ ÐÕÔÉ ÄÌÑ ÄÉÎÁÍÉÞÅÓËÉÈ ÂÉÂÌÉÏÔÅË"
+ serbian "Ne postoje dozvoljene putanje do share-ovane biblioteke"
+ slo "Neprípustné ¾iadne cesty k zdieµanej kni¾nici"
+ spa "No pasos permitidos para librarias conjugadas"
+ swe "Man får inte ange sökväg för dynamiska bibliotek"
+ ukr "îÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÐÕÔ¦ ÄÌÑ ÒÏÚĦÌÀ×ÁÎÉÈ Â¦Â̦ÏÔÅË"
+ER_UDF_EXISTS
+ cze "Funkce '%-.64s' ji-B¾ existuje"
+ dan "Funktionen '%-.64s' findes allerede"
+ nla "Functie '%-.64s' bestaat reeds"
+ eng "Function '%-.64s' already exists"
+ jps "Function '%-.64s' ‚ÍŠù‚É’è‹`‚³‚ê‚Ä‚¢‚Ü‚·",
+ est "Funktsioon '%-.64s' juba eksisteerib"
+ fre "La fonction '%-.64s' existe déjà"
+ ger "Funktion '%-.64s' existiert schon"
+ greek "Ç óõíÜñôçóç '%-.64s' õðÜñ÷åé Þäç"
+ hun "A '%-.64s' fuggveny mar letezik"
+ ita "La funzione '%-.64s' esiste gia`"
+ jpn "Function '%-.64s' ¤Ï´û¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤¹"
+ kor "'%-.64s' ÇÔ¼ö´Â ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù."
+ por "Função '%-.64s' já existe"
+ rum "Functia '%-.64s' exista deja"
+ rus "æÕÎËÃÉÑ '%-.64s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ"
+ serbian "Funkcija '%-.64s' veæ postoji"
+ slo "Funkcia '%-.64s' u¾ existuje"
+ spa "Función '%-.64s' ya existe"
+ swe "Funktionen '%-.64s' finns redan"
+ ukr "æÕÎËÃ¦Ñ '%-.64s' ×ÖÅ ¦ÓÎÕ¤"
+ER_CANT_OPEN_LIBRARY
+ cze "Nemohu otev-Bøít sdílenou knihovnu '%-.64s' (errno: %d %s)"
+ dan "Kan ikke åbne delt bibliotek '%-.64s' (errno: %d %s)"
+ nla "Kan shared library '%-.64s' niet openen (Errcode: %d %s)"
+ eng "Can't open shared library '%-.64s' (errno: %d %-.64s)"
+ jps "shared library '%-.64s' ‚ðŠJ‚­Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d %s)",
+ est "Ei suuda avada jagatud teeki '%-.64s' (veakood: %d %-.64s)"
+ fre "Impossible d'ouvrir la bibliothèque partagée '%-.64s' (errno: %d %s)"
+ ger "Kann Shared Library '%-.64s' nicht öffnen (Fehler: %d %-.64s)"
+ greek "Äåí åßíáé äõíáôÞ ç áíÜãíùóç ôçò shared library '%-.64s' (êùäéêüò ëÜèïõò: %d %s)"
+ hun "A(z) '%-.64s' megosztott konyvtar nem hasznalhato (hibakod: %d %s)"
+ ita "Impossibile aprire la libreria condivisa '%-.64s' (errno: %d %s)"
+ jpn "shared library '%-.64s' ¤ò³«¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó (errno: %d %s)"
+ kor "'%-.64s' °øÀ¯ ¶óÀ̹ö·¯¸®¸¦ ¿­¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£: %d %s)"
+ nor "Can't open shared library '%-.64s' (errno: %d %s)"
+ norwegian-ny "Can't open shared library '%-.64s' (errno: %d %s)"
+ pol "Can't open shared library '%-.64s' (errno: %d %s)"
+ por "Não pode abrir biblioteca compartilhada '%-.64s' (erro no. '%d' - '%-.64s')"
+ rum "Nu pot deschide libraria shared '%-.64s' (Eroare: %d %-.64s)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÉÎÁÍÉÞÅÓËÕÀ ÂÉÂÌÉÏÔÅËÕ '%-.64s' (ÏÛÉÂËÁ: %d %-.64s)"
+ serbian "Ne mogu da otvorim share-ovanu biblioteku '%-.64s' (errno: %d %-.64s)"
+ slo "Nemô¾em otvori» zdieµanú kni¾nicu '%-.64s' (chybový kód: %d %s)"
+ spa "No puedo abrir libraria conjugada '%-.64s' (errno: %d %s)"
+ swe "Kan inte öppna det dynamiska biblioteket '%-.64s' (Felkod: %d %s)"
+ ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÒÏÚĦÌÀ×ÁÎÕ Â¦Â̦ÏÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d %-.64s)"
+ER_CANT_FIND_DL_ENTRY
+ cze "Nemohu naj-Bít funkci '%-.64s' v knihovnì'"
+ dan "Kan ikke finde funktionen '%-.64s' i bibliotek'"
+ nla "Kan functie '%-.64s' niet in library vinden"
+ eng "Can't find function '%-.64s' in library'"
+ jps "function '%-.64s' ‚ðƒ‰ƒCƒuƒ‰ƒŠ[’†‚ÉŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ",
+ est "Ei leia funktsiooni '%-.64s' antud teegis"
+ fre "Impossible de trouver la fonction '%-.64s' dans la bibliothèque'"
+ ger "Kann Funktion '%-.64s' in der Library nicht finden"
+ greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò óõíÜñôçóçò '%-.64s' óôçí âéâëéïèÞêç'"
+ hun "A(z) '%-.64s' fuggveny nem talalhato a konyvtarban"
+ ita "Impossibile trovare la funzione '%-.64s' nella libreria"
+ jpn "function '%-.64s' ¤ò¥é¥¤¥Ö¥é¥ê¡¼Ãæ¤Ë¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó"
+ kor "¶óÀ̹ö·¯¸®¿¡¼­ '%-.64s' ÇÔ¼ö¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù."
+ por "Não pode encontrar a função '%-.64s' na biblioteca"
+ rum "Nu pot gasi functia '%-.64s' in libraria"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÆÕÎËÃÉÀ '%-.64s' × ÂÉÂÌÉÏÔÅËÅ"
+ serbian "Ne mogu da pronadjem funkciju '%-.64s' u biblioteci"
+ slo "Nemô¾em nájs» funkciu '%-.64s' v kni¾nici'"
+ spa "No puedo encontrar función '%-.64s' en libraria'"
+ swe "Hittar inte funktionen '%-.64s' in det dynamiska biblioteket"
+ ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÕÎËæÀ '%-.64s' Õ Â¦Â̦ÏÔÅæ'"
+ER_FUNCTION_NOT_DEFINED
+ cze "Funkce '%-.64s' nen-Bí definována"
+ dan "Funktionen '%-.64s' er ikke defineret"
+ nla "Functie '%-.64s' is niet gedefinieerd"
+ eng "Function '%-.64s' is not defined"
+ jps "Function '%-.64s' ‚Í’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
+ est "Funktsioon '%-.64s' ei ole defineeritud"
+ fre "La fonction '%-.64s' n'est pas définie"
+ ger "Funktion '%-.64s' ist nicht definiert"
+ greek "Ç óõíÜñôçóç '%-.64s' äåí Ý÷åé ïñéóèåß"
+ hun "A '%-.64s' fuggveny nem definialt"
+ ita "La funzione '%-.64s' non e` definita"
+ jpn "Function '%-.64s' ¤ÏÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+ kor "'%-.64s' ÇÔ¼ö°¡ Á¤ÀǵǾî ÀÖÁö ¾Ê½À´Ï´Ù."
+ por "Função '%-.64s' não está definida"
+ rum "Functia '%-.64s' nu e definita"
+ rus "æÕÎËÃÉÑ '%-.64s' ÎÅ ÏÐÒÅÄÅÌÅÎÁ"
+ serbian "Funkcija '%-.64s' nije definisana"
+ slo "Funkcia '%-.64s' nie je definovaná"
+ spa "Función '%-.64s' no está definida"
+ swe "Funktionen '%-.64s' är inte definierad"
+ ukr "æÕÎËæÀ '%-.64s' ÎÅ ×ÉÚÎÁÞÅÎÏ"
+ER_HOST_IS_BLOCKED
+ cze "Stroj '%-.64s' je zablokov-Bán kvùli mnoha chybám pøi pøipojování. Odblokujete pou¾itím 'mysqladmin flush-hosts'"
+ dan "Værten er blokeret på grund af mange fejlforespørgsler. Lås op med 'mysqladmin flush-hosts'"
+ nla "Host '%-.64s' is geblokkeeerd vanwege te veel verbindings fouten. Deblokkeer met 'mysqladmin flush-hosts'"
+ eng "Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'"
+ jps "Host '%-.64s' ‚Í many connection error ‚Ì‚½‚ßA‹‘”Û‚³‚ê‚Ü‚µ‚½. 'mysqladmin flush-hosts' ‚ʼn𜂵‚Ä‚­‚¾‚³‚¢",
+ est "Masin '%-.64s' on blokeeritud hulgaliste ühendusvigade tõttu. Blokeeringu saab tühistada 'mysqladmin flush-hosts' käsuga"
+ fre "L'hôte '%-.64s' est bloqué à cause d'un trop grand nombre d'erreur de connection. Débloquer le par 'mysqladmin flush-hosts'"
+ ger "Host '%-.64s' blockiert wegen zu vieler Verbindungsfehler. Aufheben der Blockierung mit 'mysqladmin flush-hosts'"
+ greek "Ï õðïëïãéóôÞò Ý÷åé áðïêëåéóèåß ëüãù ðïëëáðëþí ëáèþí óýíäåóçò. ÐñïóðáèÞóôå íá äéïñþóåôå ìå 'mysqladmin flush-hosts'"
+ hun "A '%-.64s' host blokkolodott, tul sok kapcsolodasi hiba miatt. Hasznalja a 'mysqladmin flush-hosts' parancsot"
+ ita "Sistema '%-.64s' bloccato a causa di troppi errori di connessione. Per sbloccarlo: 'mysqladmin flush-hosts'"
+ jpn "Host '%-.64s' ¤Ï many connection error ¤Î¤¿¤á¡¢µñÈݤµ¤ì¤Þ¤·¤¿. 'mysqladmin flush-hosts' ¤Ç²ò½ü¤·¤Æ¤¯¤À¤µ¤¤"
+ kor "³Ê¹« ¸¹Àº ¿¬°á¿À·ù·Î ÀÎÇÏ¿© È£½ºÆ® '%-.64s'´Â ºí¶ôµÇ¾ú½À´Ï´Ù. 'mysqladmin flush-hosts'¸¦ ÀÌ¿ëÇÏ¿© ºí¶ôÀ» ÇØÁ¦Çϼ¼¿ä"
+ por "'Host' '%-.64s' está bloqueado devido a muitos erros de conexão. Desbloqueie com 'mysqladmin flush-hosts'"
+ rum "Host-ul '%-.64s' e blocat din cauza multelor erori de conectie. Poti deploca folosind 'mysqladmin flush-hosts'"
+ rus "èÏÓÔ '%-.64s' ÚÁÂÌÏËÉÒÏ×ÁÎ ÉÚ-ÚÁ ÓÌÉÛËÏÍ ÂÏÌØÛÏÇÏ ËÏÌÉÞÅÓÔ×Á ÏÛÉÂÏË ÓÏÅÄÉÎÅÎÉÑ. òÁÚÂÌÏËÉÒÏ×ÁÔØ ÅÇÏ ÍÏÖÎÏ Ó ÐÏÍÏÝØÀ 'mysqladmin flush-hosts'"
+ serbian "Host '%-.64s' je blokiran zbog previše grešaka u konekciji. Možete ga odblokirati pomoæu komande 'mysqladmin flush-hosts'"
+ spa "Servidor '%-.64s' está bloqueado por muchos errores de conexión. Desbloquear con 'mysqladmin flush-hosts'"
+ swe "Denna dator, '%-.64s', är blockerad pga många felaktig paket. Gör 'mysqladmin flush-hosts' för att ta bort alla blockeringarna"
+ ukr "èÏÓÔ '%-.64s' ÚÁÂÌÏËÏ×ÁÎÏ Ú ÐÒÉÞÉÎÉ ×ÅÌÉËϧ ˦ÌØËÏÓÔ¦ ÐÏÍÉÌÏË Ú'¤ÄÎÁÎÎÑ. äÌÑ ÒÏÚÂÌÏËÕ×ÁÎÎÑ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ 'mysqladmin flush-hosts'"
+ER_HOST_NOT_PRIVILEGED
+ cze "Stroj '%-.64s' nem-Bá povoleno se k tomuto MySQL serveru pøipojit"
+ dan "Værten '%-.64s' kan ikke tilkoble denne MySQL-server"
+ nla "Het is host '%-.64s' is niet toegestaan verbinding te maken met deze MySQL server"
+ eng "Host '%-.64s' is not allowed to connect to this MySQL server"
+ jps "Host '%-.64s' ‚Í MySQL server ‚ÉÚ‘±‚ð‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
+ est "Masinal '%-.64s' puudub ligipääs sellele MySQL serverile"
+ fre "Le hôte '%-.64s' n'est pas authorisé à se connecter à ce serveur MySQL"
+ ger "Host '%-.64s' hat keine Berechtigung, sich mit diesem MySQL-Server zu verbinden"
+ greek "Ï õðïëïãéóôÞò äåí Ý÷åé äéêáßùìá óýíäåóçò ìå ôïí MySQL server"
+ hun "A '%-.64s' host szamara nem engedelyezett a kapcsolodas ehhez a MySQL szerverhez"
+ ita "Al sistema '%-.64s' non e` consentita la connessione a questo server MySQL"
+ jpn "Host '%-.64s' ¤Ï MySQL server ¤ËÀܳ¤òµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+ kor "'%-.64s' È£½ºÆ®´Â ÀÌ MySQL¼­¹ö¿¡ Á¢¼ÓÇÒ Çã°¡¸¦ ¹ÞÁö ¸øÇß½À´Ï´Ù."
+ por "'Host' '%-.64s' não tem permissão para se conectar com este servidor MySQL"
+ rum "Host-ul '%-.64s' nu este permis a se conecta la aceste server MySQL"
+ rus "èÏÓÔÕ '%-.64s' ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÐÏÄËÌÀÞÁÔØÓÑ Ë ÜÔÏÍÕ ÓÅÒ×ÅÒÕ MySQL"
+ serbian "Host-u '%-.64s' nije dozvoljeno da se konektuje na ovaj MySQL server"
+ spa "Servidor '%-.64s' no está permitido para conectar con este servidor MySQL"
+ swe "Denna dator, '%-.64s', har inte privileger att använda denna MySQL server"
+ ukr "èÏÓÔÕ '%-.64s' ÎÅ ÄÏ×ÏÌÅÎÏ Ú×'ÑÚÕ×ÁÔÉÓØ Ú ÃÉÍ ÓÅÒ×ÅÒÏÍ MySQL"
+ER_PASSWORD_ANONYMOUS_USER 42000
+ cze "Pou-B¾íváte MySQL jako anonymní u¾ivatel a anonymní u¾ivatelé nemají povoleno mìnit hesla"
+ dan "Du bruger MySQL som anonym bruger. Anonyme brugere må ikke ændre adgangskoder"
+ nla "U gebruikt MySQL als anonieme gebruiker en deze mogen geen wachtwoorden wijzigen"
+ eng "You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords"
+ jps "MySQL ‚ð anonymous users ‚ÅŽg—p‚µ‚Ä‚¢‚éó‘Ô‚Å‚ÍAƒpƒXƒ[ƒh‚Ì•ÏX‚Í‚Å‚«‚Ü‚¹‚ñ",
+ est "Te kasutate MySQL-i anonüümse kasutajana, kelledel pole parooli muutmise õigust"
+ fre "Vous utilisez un utilisateur anonyme et les utilisateurs anonymes ne sont pas autorisés à changer les mots de passe"
+ ger "Sie benutzen MySQL als anonymer Benutzer und dürfen daher keine Passwörter ändern"
+ greek "×ñçóéìïðïéåßôå ôçí MySQL óáí anonymous user êáé Ýôóé äåí ìðïñåßôå íá áëëÜîåôå ôá passwords Üëëùí ÷ñçóôþí"
+ hun "Nevtelen (anonymous) felhasznalokent nem negedelyezett a jelszovaltoztatas"
+ ita "Impossibile cambiare la password usando MySQL come utente anonimo"
+ jpn "MySQL ¤ò anonymous users ¤Ç»ÈÍѤ·¤Æ¤¤¤ë¾õÂ֤Ǥϡ¢¥Ñ¥¹¥ï¡¼¥É¤ÎÊѹ¹¤Ï¤Ç¤­¤Þ¤»¤ó"
+ kor "´ç½ÅÀº MySQL¼­¹ö¿¡ À͸íÀÇ »ç¿ëÀÚ·Î Á¢¼ÓÀ» Çϼ̽À´Ï´Ù.À͸íÀÇ »ç¿ëÀÚ´Â ¾ÏÈ£¸¦ º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù."
+ por "Você está usando o MySQL como usuário anônimo e usuários anônimos não têm permissão para mudar senhas"
+ rum "Dumneavoastra folositi MySQL ca un utilizator anonim si utilizatorii anonimi nu au voie sa schime parolele"
+ rus "÷Ù ÉÓÐÏÌØÚÕÅÔÅ MySQL ÏÔ ÉÍÅÎÉ ÁÎÏÎÉÍÎÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ, Á ÁÎÏÎÉÍÎÙÍ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÍÅÎÑÔØ ÐÁÒÏÌÉ"
+ serbian "Vi koristite MySQL kao anonimni korisnik a anonimnim korisnicima nije dozvoljeno da menjaju lozinke"
+ spa "Tu estás usando MySQL como un usuario anonimo y usuarios anonimos no tienen permiso para cambiar las claves"
+ swe "Du använder MySQL som en anonym användare och som sådan får du inte ändra ditt lösenord"
+ ukr "÷É ×ÉËÏÒÉÓÔÏ×Õ¤ÔÅ MySQL ÑË ÁÎÏΦÍÎÉÊ ËÏÒÉÓÔÕ×ÁÞ, ÔÏÍÕ ×ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ÚͦÎÀ×ÁÔÉ ÐÁÒÏ̦"
+ER_PASSWORD_NOT_ALLOWED 42000
+ cze "Na zm-Bìnu hesel ostatním musíte mít právo provést update tabulek v databázi mysql"
+ dan "Du skal have tilladelse til at opdatere tabeller i MySQL databasen for at ændre andres adgangskoder"
+ nla "U moet tabel update priveleges hebben in de mysql database om wachtwoorden voor anderen te mogen wijzigen"
+ eng "You must have privileges to update tables in the mysql database to be able to change passwords for others"
+ jps "‘¼‚̃†[ƒU[‚̃pƒXƒ[ƒh‚ð•ÏX‚·‚邽‚ß‚É‚Í, mysql ƒf[ƒ^ƒx[ƒX‚ɑ΂µ‚Ä update ‚Ì‹–‰Â‚ª‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ.",
+ est "Teiste paroolide muutmiseks on nõutav tabelite muutmisõigus 'mysql' andmebaasis"
+ fre "Vous devez avoir le privilège update sur les tables de la base de donnée mysql pour pouvoir changer les mots de passe des autres"
+ ger "Sie benötigen die Berechtigung zum Aktualisieren von Tabellen in der Datenbank 'mysql', um die Passwörter anderer Benutzer ändern zu können"
+ greek "ÐñÝðåé íá Ý÷åôå äéêáßùìá äéüñèùóçò ðéíÜêùí (update) óôç âÜóç äåäïìÝíùí mysql ãéá íá ìðïñåßôå íá áëëÜîåôå ôá passwords Üëëùí ÷ñçóôþí"
+ hun "Onnek tabla-update joggal kell rendelkeznie a mysql adatbazisban masok jelszavanak megvaltoztatasahoz"
+ ita "E` necessario il privilegio di update sulle tabelle del database mysql per cambiare le password per gli altri utenti"
+ jpn "¾¤Î¥æ¡¼¥¶¡¼¤Î¥Ñ¥¹¥ï¡¼¥É¤òÊѹ¹¤¹¤ë¤¿¤á¤Ë¤Ï, mysql ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÂФ·¤Æ update ¤Îµö²Ä¤¬¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó."
+ kor "´ç½ÅÀº ´Ù¸¥»ç¿ëÀÚµéÀÇ ¾ÏÈ£¸¦ º¯°æÇÒ ¼ö ÀÖµµ·Ï µ¥ÀÌŸº£À̽º º¯°æ±ÇÇÑÀ» °¡Á®¾ß ÇÕ´Ï´Ù."
+ por "Você deve ter privilégios para atualizar tabelas no banco de dados mysql para ser capaz de mudar a senha de outros"
+ rum "Trebuie sa aveti privilegii sa actualizati tabelele in bazele de date mysql ca sa puteti sa schimati parolele altora"
+ rus "äÌÑ ÔÏÇÏ ÞÔÏÂÙ ÉÚÍÅÎÑÔØ ÐÁÒÏÌÉ ÄÒÕÇÉÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, Õ ×ÁÓ ÄÏÌÖÎÙ ÂÙÔØ ÐÒÉ×ÉÌÅÇÉÉ ÎÁ ÉÚÍÅÎÅÎÉÅ ÔÁÂÌÉÃ × ÂÁÚÅ ÄÁÎÎÙÈ mysql"
+ serbian "Morate imati privilegije da možete da update-ujete odreðene tabele ako želite da menjate lozinke za druge korisnike"
+ spa "Tu debes de tener permiso para actualizar tablas en la base de datos mysql para cambiar las claves para otros"
+ swe "För att ändra lösenord för andra måste du ha rättigheter att uppdatera mysql-databasen"
+ ukr "÷É ÐÏ×ÉΦ ÍÁÔÉ ÐÒÁ×Ï ÎÁ ÏÎÏ×ÌÅÎÎÑ ÔÁÂÌÉÃØ Õ ÂÁÚ¦ ÄÁÎÎÉÈ mysql, ÁÂÉ ÍÁÔÉ ÍÏÖÌÉצÓÔØ ÚͦÎÀ×ÁÔÉ ÐÁÒÏÌØ ¦ÎÛÉÍ"
+ER_PASSWORD_NO_MATCH 42000
+ cze "V tabulce user nen-Bí ¾ádný odpovídající øádek"
+ dan "Kan ikke finde nogen tilsvarende poster i bruger tabellen"
+ nla "Kan geen enkele passende rij vinden in de gebruikers tabel"
+ eng "Can't find any matching row in the user table"
+ est "Ei leia vastavat kirjet kasutajate tabelis"
+ fre "Impossible de trouver un enregistrement correspondant dans la table user"
+ ger "Kann keinen passenden Datensatz in Tabelle 'user' finden"
+ greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò áíôßóôïé÷çò åããñáöÞò óôïí ðßíáêá ôùí ÷ñçóôþí"
+ hun "Nincs megegyezo sor a user tablaban"
+ ita "Impossibile trovare la riga corrispondente nella tabella user"
+ kor "»ç¿ëÀÚ Å×ÀÌºí¿¡¼­ ÀÏÄ¡ÇÏ´Â °ÍÀ» ãÀ» ¼ö ¾øÀ¾´Ï´Ù."
+ por "Não pode encontrar nenhuma linha que combine na tabela usuário (user table)"
+ rum "Nu pot gasi nici o linie corespunzatoare in tabela utilizatorului"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÐÏÄÈÏÄÑÝÕÀ ÚÁÐÉÓØ × ÔÁÂÌÉÃÅ ÐÏÌØÚÏ×ÁÔÅÌÅÊ"
+ serbian "Ne mogu da pronaðem odgovarajuæi slog u 'user' tabeli"
+ spa "No puedo encontrar una línea correponsdiente en la tabla user"
+ swe "Hittade inte användaren i 'user'-tabellen"
+ ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ×¦ÄÐÏצÄÎÉÈ ÚÁÐÉÓ¦× Õ ÔÁÂÌÉæ ËÏÒÉÓÔÕ×ÁÞÁ"
+ER_UPDATE_INFO
+ cze "Nalezen-Bých øádkù: %ld Zmìnìno: %ld Varování: %ld"
+ dan "Poster fundet: %ld Ændret: %ld Advarsler: %ld"
+ nla "Passende rijen: %ld Gewijzigd: %ld Waarschuwingen: %ld"
+ eng "Rows matched: %ld Changed: %ld Warnings: %ld"
+ jps "ˆê’v”(Rows matched): %ld •ÏX: %ld Warnings: %ld",
+ est "Sobinud kirjeid: %ld Muudetud: %ld Hoiatusi: %ld"
+ fre "Enregistrements correspondants: %ld Modifiés: %ld Warnings: %ld"
+ ger "Datensätze gefunden: %ld Geändert: %ld Warnungen: %ld"
+ hun "Megegyezo sorok szama: %ld Valtozott: %ld Warnings: %ld"
+ ita "Rows riconosciute: %ld Cambiate: %ld Warnings: %ld"
+ jpn "°ìÃ׿ô(Rows matched): %ld Êѹ¹: %ld Warnings: %ld"
+ kor "ÀÏÄ¡ÇÏ´Â Rows : %ld°³ º¯°æµÊ: %ld°³ °æ°í: %ld°³"
+ por "Linhas que combinaram: %ld - Alteradas: %ld - Avisos: %ld"
+ rum "Linii identificate (matched): %ld Schimbate: %ld Atentionari (warnings): %ld"
+ rus "óÏ×ÐÁÌÏ ÚÁÐÉÓÅÊ: %ld éÚÍÅÎÅÎÏ: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld"
+ serbian "Odgovarajuæih slogova: %ld Promenjeno: %ld Upozorenja: %ld"
+ spa "Líneas correspondientes: %ld Cambiadas: %ld Avisos: %ld"
+ swe "Rader: %ld Uppdaterade: %ld Varningar: %ld"
+ ukr "úÁÐÉÓ¦× ×¦ÄÐÏצÄÁ¤: %ld úͦÎÅÎÏ: %ld úÁÓÔÅÒÅÖÅÎØ: %ld"
+ER_CANT_CREATE_THREAD
+ cze "Nemohu vytvo-Bøit nový thread (errno %d). Pokud je je¹tì nìjaká volná pamì», podívejte se do manuálu na èást o chybách specifických pro jednotlivé operaèní systémy"
+ dan "Kan ikke danne en ny tråd (fejl nr. %d). Hvis computeren ikke er løbet tør for hukommelse, kan du se i brugervejledningen for en mulig operativ-system - afhængig fejl"
+ nla "Kan geen nieuwe thread aanmaken (Errcode: %d). Indien er geen tekort aan geheugen is kunt u de handleiding consulteren over een mogelijke OS afhankelijke fout"
+ eng "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"
+ jps "V‹K‚ɃXƒŒƒbƒh‚ªì‚ê‚Ü‚¹‚ñ‚Å‚µ‚½ (errno %d). ‚à‚µÅ‘åŽg—p‹–‰Âƒƒ‚ƒŠ[”‚ð‰z‚¦‚Ä‚¢‚È‚¢‚̂ɃGƒ‰[‚ª”­¶‚µ‚Ä‚¢‚é‚È‚ç, ƒ}ƒjƒ…ƒAƒ‹‚Ì’†‚©‚ç 'possible OS-dependent bug' ‚Æ‚¢‚¤•¶Žš‚ð’T‚µ‚Ä‚­‚Ý‚Ä‚¾‚³‚¢.",
+ est "Ei suuda luua uut lõime (veakood %d). Kui mälu ei ole otsas, on tõenäoliselt tegemist operatsioonisüsteemispetsiifilise veaga"
+ fre "Impossible de créer une nouvelle tâche (errno %d). S'il reste de la mémoire libre, consultez le manual pour trouver un éventuel bug dépendant de l'OS"
+ ger "Kann keinen neuen Thread erzeugen (Fehler: %d). Sollte noch Speicher verfügbar sein, bitte im Handbuch wegen möglicher Fehler im Betriebssystem nachschlagen"
+ hun "Uj thread letrehozasa nem lehetseges (Hibakod: %d). Amenyiben van meg szabad memoria, olvassa el a kezikonyv operacios rendszerfuggo hibalehetosegekrol szolo reszet"
+ ita "Impossibile creare un nuovo thread (errno %d). Se non ci sono problemi di memoria disponibile puoi consultare il manuale per controllare possibili problemi dipendenti dal SO"
+ jpn "¿·µ¬¤Ë¥¹¥ì¥Ã¥É¤¬ºî¤ì¤Þ¤»¤ó¤Ç¤·¤¿ (errno %d). ¤â¤·ºÇÂç»ÈÍѵö²Ä¥á¥â¥ê¡¼¿ô¤ò±Û¤¨¤Æ¤¤¤Ê¤¤¤Î¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Æ¤¤¤ë¤Ê¤é, ¥Þ¥Ë¥å¥¢¥ë¤ÎÃ椫¤é 'possible OS-dependent bug' ¤È¤¤¤¦Ê¸»ú¤òõ¤·¤Æ¤¯¤ß¤Æ¤À¤µ¤¤."
+ kor "»õ·Î¿î ¾²·¹µå¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£ %d). ¸¸¾à ¿©À¯¸Þ¸ð¸®°¡ ÀÖ´Ù¸é OS-dependent¹ö±× ÀÇ ¸Þ´º¾ó ºÎºÐÀ» ã¾Æº¸½Ã¿À."
+ nor "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"
+ norwegian-ny "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"
+ pol "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"
+ por "Não pode criar uma nova 'thread' (erro no. %d). Se você não estiver sem memória disponível, você pode consultar o manual sobre um possível 'bug' dependente do sistema operacional"
+ rum "Nu pot crea un thread nou (Eroare %d). Daca mai aveti memorie disponibila in sistem, puteti consulta manualul - ar putea exista un potential bug in legatura cu sistemul de operare"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÎÏ×ÙÊ ÐÏÔÏË (ÏÛÉÂËÁ %d). åÓÌÉ ÜÔÏ ÎÅ ÓÉÔÕÁÃÉÑ, Ó×ÑÚÁÎÎÁÑ Ó ÎÅÈ×ÁÔËÏÊ ÐÁÍÑÔÉ, ÔÏ ×ÁÍ ÓÌÅÄÕÅÔ ÉÚÕÞÉÔØ ÄÏËÕÍÅÎÔÁÃÉÀ ÎÁ ÐÒÅÄÍÅÔ ÏÐÉÓÁÎÉÑ ×ÏÚÍÏÖÎÏÊ ÏÛÉÂËÉ ÒÁÂÏÔÙ × ËÏÎËÒÅÔÎÏÊ ïó"
+ serbian "Ne mogu da kreiram novi thread (errno %d). Ako imate još slobodne memorije, trebali biste da pogledate u priruèniku da li je ovo specifièna greška vašeg operativnog sistema"
+ spa "No puedo crear un nuevo thread (errno %d). Si tu está con falta de memoria disponible, tu puedes consultar el Manual para posibles problemas con SO"
+ swe "Kan inte skapa en ny tråd (errno %d)"
+ ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÎÏ×Õ Ç¦ÌËÕ (ÐÏÍÉÌËÁ %d). ñËÝÏ ×É ÎÅ ×ÉËÏÒÉÓÔÁÌÉ ÕÓÀ ÐÁÍ'ÑÔØ, ÔÏ ÐÒÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ ÄÏ ×ÁÛϧ ïó - ÍÏÖÌÉ×Ï ÃÅ ÐÏÍÉÌËÁ ïó"
+ER_WRONG_VALUE_COUNT_ON_ROW 21S01
+ cze "Po-Bèet sloupcù neodpovídá poètu hodnot na øádku %ld"
+ dan "Kolonne antallet stemmer ikke overens med antallet af værdier i post %ld"
+ nla "Kolom aantal komt niet overeen met waarde aantal in rij %ld"
+ eng "Column count doesn't match value count at row %ld"
+ est "Tulpade hulk erineb väärtuste hulgast real %ld"
+ ger "Anzahl der Spalten stimmt nicht mit der Anzahl der Werte in Zeile %ld überein"
+ hun "Az oszlopban talalhato ertek nem egyezik meg a %ld sorban szamitott ertekkel"
+ ita "Il numero delle colonne non corrisponde al conteggio alla riga %ld"
+ kor "Row %ld¿¡¼­ Ä®·³ Ä«¿îÆ®¿Í value Ä«¿îÅÍ¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù."
+ por "Contagem de colunas não confere com a contagem de valores na linha %ld"
+ rum "Numarul de coloane nu corespunde cu numarul de valori la linia %ld"
+ rus "ëÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ× ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ËÏÌÉÞÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ × ÚÁÐÉÓÉ %ld"
+ serbian "Broj kolona ne odgovara broju vrednosti u slogu %ld"
+ spa "El número de columnas no corresponde al número en la línea %ld"
+ swe "Antalet kolumner motsvarar inte antalet värden på rad: %ld"
+ ukr "ë¦ÌØ˦ÓÔØ ÓÔÏ×ÂÃ¦× ÎÅ ÓЦ×ÐÁÄÁ¤ Ú Ë¦ÌØ˦ÓÔÀ ÚÎÁÞÅÎØ Õ ÓÔÒÏæ %ld"
+ER_CANT_REOPEN_TABLE
+ cze "Nemohu znovuotev-Bøít tabulku: '%-.64s"
+ dan "Kan ikke genåbne tabel '%-.64s"
+ nla "Kan tabel niet opnieuw openen: '%-.64s"
+ eng "Can't reopen table: '%-.64s'"
+ est "Ei suuda taasavada tabelit '%-.64s'"
+ fre "Impossible de réouvrir la table: '%-.64s"
+ ger "Kann Tabelle'%-.64s' nicht erneut öffnen"
+ hun "Nem lehet ujra-megnyitni a tablat: '%-.64s"
+ ita "Impossibile riaprire la tabella: '%-.64s'"
+ kor "Å×À̺íÀ» ´Ù½Ã ¿­¼ö ¾ø±º¿ä: '%-.64s"
+ nor "Can't reopen table: '%-.64s"
+ norwegian-ny "Can't reopen table: '%-.64s"
+ pol "Can't reopen table: '%-.64s"
+ por "Não pode reabrir a tabela '%-.64s"
+ rum "Nu pot redeschide tabela: '%-.64s'"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÚÁÎÏ×Ï ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ '%-.64s'"
+ serbian "Ne mogu da ponovo otvorim tabelu '%-.64s'"
+ slo "Can't reopen table: '%-.64s"
+ spa "No puedo reabrir tabla: '%-.64s"
+ swe "Kunde inte stänga och öppna tabell '%-.64s"
+ ukr "îÅ ÍÏÖÕ ÐÅÒÅצÄËÒÉÔÉ ÔÁÂÌÉÃÀ: '%-.64s'"
+ER_INVALID_USE_OF_NULL 22004
+ cze "Neplatn-Bé u¾ití hodnoty NULL"
+ dan "Forkert brug af nulværdi (NULL)"
+ nla "Foutief gebruik van de NULL waarde"
+ eng "Invalid use of NULL value"
+ jps "NULL ’l‚ÌŽg—p•û–@‚ª•s“KØ‚Å‚·",
+ est "NULL väärtuse väärkasutus"
+ fre "Utilisation incorrecte de la valeur NULL"
+ ger "Unerlaubte Verwendung eines NULL-Werts"
+ hun "A NULL ervenytelen hasznalata"
+ ita "Uso scorretto del valore NULL"
+ jpn "NULL ÃͤλÈÍÑÊýË¡¤¬ÉÔŬÀڤǤ¹"
+ kor "NULL °ªÀ» À߸ø »ç¿ëÇϼ̱º¿ä..."
+ por "Uso inválido do valor NULL"
+ rum "Folosirea unei value NULL e invalida"
+ rus "îÅÐÒÁ×ÉÌØÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ×ÅÌÉÞÉÎÙ NULL"
+ serbian "Pogrešna upotreba vrednosti NULL"
+ spa "Invalido uso de valor NULL"
+ swe "Felaktig använding av NULL"
+ ukr "èÉÂÎÅ ×ÉËÏÒÉÓÔÁÎÎÑ ÚÎÁÞÅÎÎÑ NULL"
+ER_REGEXP_ERROR 42000
+ cze "Regul-Bární výraz vrátil chybu '%-.64s'"
+ dan "Fik fejl '%-.64s' fra regexp"
+ nla "Fout '%-.64s' ontvangen van regexp"
+ eng "Got error '%-.64s' from regexp"
+ est "regexp tagastas vea '%-.64s'"
+ fre "Erreur '%-.64s' provenant de regexp"
+ ger "regexp lieferte Fehler '%-.64s'"
+ hun "'%-.64s' hiba a regularis kifejezes hasznalata soran (regexp)"
+ ita "Errore '%-.64s' da regexp"
+ kor "regexp¿¡¼­ '%-.64s'°¡ ³µ½À´Ï´Ù."
+ por "Obteve erro '%-.64s' em regexp"
+ rum "Eroarea '%-.64s' obtinuta din expresia regulara (regexp)"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ '%-.64s' ÏÔ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ"
+ serbian "Funkcija regexp je vratila grešku '%-.64s'"
+ spa "Obtenido error '%-.64s' de regexp"
+ swe "Fick fel '%-.64s' från REGEXP"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ '%-.64s' ×¦Ä ÒÅÇÕÌÑÒÎÏÇÏ ×ÉÒÁÚÕ"
+ER_MIX_OF_GROUP_FUNC_AND_FIELDS 42000
+ cze "Pokud nen-Bí ¾ádná GROUP BY klauzule, není dovoleno souèasné pou¾ití GROUP polo¾ek (MIN(),MAX(),COUNT()...) s ne GROUP polo¾kami"
+ dan "Sammenblanding af GROUP kolonner (MIN(),MAX(),COUNT()...) uden GROUP kolonner er ikke tilladt, hvis der ikke er noget GROUP BY prædikat"
+ nla "Het mixen van GROUP kolommen (MIN(),MAX(),COUNT()...) met no-GROUP kolommen is foutief indien er geen GROUP BY clausule is"
+ eng "Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause"
+ est "GROUP tulpade (MIN(),MAX(),COUNT()...) kooskasutamine tavaliste tulpadega ilma GROUP BY klauslita ei ole lubatud"
+ fre "Mélanger les colonnes GROUP (MIN(),MAX(),COUNT()...) avec des colonnes normales est interdit s'il n'y a pas de clause GROUP BY"
+ ger "Das Vermischen von GROUP-Spalten (MIN(),MAX(),COUNT()...) mit Nicht-GROUP-Spalten ist nicht zulässig, wenn keine GROUP BY-Klausel vorhanden ist"
+ hun "A GROUP mezok (MIN(),MAX(),COUNT()...) kevert hasznalata nem lehetseges GROUP BY hivatkozas nelkul"
+ ita "Il mescolare funzioni di aggregazione (MIN(),MAX(),COUNT()...) e non e` illegale se non c'e` una clausula GROUP BY"
+ kor "Mixing of GROUP Ä®·³s (MIN(),MAX(),COUNT(),...) with no GROUP Ä®·³s is illegal if there is no GROUP BY clause"
+ por "Mistura de colunas agrupadas (com MIN(), MAX(), COUNT(), ...) com colunas não agrupadas é ilegal, se não existir uma cláusula de agrupamento (cláusula GROUP BY)"
+ rum "Amestecarea de coloane GROUP (MIN(),MAX(),COUNT()...) fara coloane GROUP este ilegala daca nu exista o clauza GROUP BY"
+ rus "ïÄÎÏ×ÒÅÍÅÎÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÓÇÒÕÐÐÉÒÏ×ÁÎÎÙÈ (GROUP) ÓÔÏÌÂÃÏ× (MIN(),MAX(),COUNT(),...) Ó ÎÅÓÇÒÕÐÐÉÒÏ×ÁÎÎÙÍÉ ÓÔÏÌÂÃÁÍÉ Ñ×ÌÑÅÔÓÑ ÎÅËÏÒÒÅËÔÎÙÍ, ÅÓÌÉ × ×ÙÒÁÖÅÎÉÉ ÅÓÔØ GROUP BY"
+ serbian "Upotreba agregatnih funkcija (MIN(),MAX(),COUNT()...) bez 'GROUP' kolona je pogrešna ako ne postoji 'GROUP BY' iskaz"
+ spa "Mezcla de columnas GROUP (MIN(),MAX(),COUNT()...) con no GROUP columnas es ilegal si no hat la clausula GROUP BY"
+ swe "Man får ha både GROUP-kolumner (MIN(),MAX(),COUNT()...) och fält i en fråga om man inte har en GROUP BY-del"
+ ukr "úͦÛÕ×ÁÎÎÑ GROUP ÓÔÏ×ÂÃ¦× (MIN(),MAX(),COUNT()...) Ú ÎÅ GROUP ÓÔÏ×ÂÃÑÍÉ ¤ ÚÁÂÏÒÏÎÅÎÉÍ, ÑËÝÏ ÎÅ ÍÁ¤ GROUP BY"
+ER_NONEXISTING_GRANT 42000
+ cze "Neexistuje odpov-Bídající grant pro u¾ivatele '%-.32s' na stroji '%-.64s'"
+ dan "Denne tilladelse findes ikke for brugeren '%-.32s' på vært '%-.64s'"
+ nla "Deze toegang (GRANT) is niet toegekend voor gebruiker '%-.32s' op host '%-.64s'"
+ eng "There is no such grant defined for user '%-.32s' on host '%-.64s'"
+ jps "ƒ†[ƒU[ '%-.32s' (ƒzƒXƒg '%-.64s' ‚̃†[ƒU[) ‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
+ est "Sellist õigust ei ole defineeritud kasutajale '%-.32s' masinast '%-.64s'"
+ fre "Un tel droit n'est pas défini pour l'utilisateur '%-.32s' sur l'hôte '%-.64s'"
+ ger "Für Benutzer '%-.32s' auf Host '%-.64s' gibt es keine solche Berechtigung"
+ hun "A '%-.32s' felhasznalonak nincs ilyen joga a '%-.64s' host-on"
+ ita "GRANT non definita per l'utente '%-.32s' dalla macchina '%-.64s'"
+ jpn "¥æ¡¼¥¶¡¼ '%-.32s' (¥Û¥¹¥È '%-.64s' ¤Î¥æ¡¼¥¶¡¼) ¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+ kor "»ç¿ëÀÚ '%-.32s' (È£½ºÆ® '%-.64s')¸¦ À§ÇÏ¿© Á¤ÀÇµÈ ±×·± ½ÂÀÎÀº ¾ø½À´Ï´Ù."
+ por "Não existe tal permissão (grant) definida para o usuário '%-.32s' no 'host' '%-.64s'"
+ rum "Nu exista un astfel de grant definit pentru utilzatorul '%-.32s' de pe host-ul '%-.64s'"
+ rus "ôÁËÉÅ ÐÒÁ×Á ÎÅ ÏÐÒÅÄÅÌÅÎÙ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' ÎÁ ÈÏÓÔÅ '%-.64s'"
+ serbian "Ne postoji odobrenje za pristup korisniku '%-.32s' na host-u '%-.64s'"
+ spa "No existe permiso definido para usuario '%-.32s' en el servidor '%-.64s'"
+ swe "Det finns inget privilegium definierat för användare '%-.32s' på '%-.64s'"
+ ukr "ðÏ×ÎÏ×ÁÖÅÎØ ÎÅ ×ÉÚÎÁÞÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ '%-.32s' Ú ÈÏÓÔÕ '%-.64s'"
+ER_TABLEACCESS_DENIED_ERROR 42000
+ cze "%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.32s'@'%-.64s' pro tabulku '%-.64s'"
+ dan "%-.16s-kommandoen er ikke tilladt for brugeren '%-.32s'@'%-.64s' for tabellen '%-.64s'"
+ nla "%-.16s commando geweigerd voor gebruiker: '%-.32s'@'%-.64s' voor tabel '%-.64s'"
+ eng "%-.16s command denied to user '%-.32s'@'%-.64s' for table '%-.64s'"
+ jps "ƒRƒ}ƒ“ƒh %-.16s ‚Í ƒ†[ƒU[ '%-.32s'@'%-.64s' ,ƒe[ƒuƒ‹ '%-.64s' ‚ɑ΂µ‚Ä‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
+ est "%-.16s käsk ei ole lubatud kasutajale '%-.32s'@'%-.64s' tabelis '%-.64s'"
+ fre "La commande '%-.16s' est interdite à l'utilisateur: '%-.32s'@'@%-.64s' sur la table '%-.64s'"
+ ger "%-.16s Befehl nicht erlaubt für Benutzer '%-.32s'@'%-.64s' und für Tabelle '%-.64s'"
+ hun "%-.16s parancs a '%-.32s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.64s' tablaban"
+ ita "Comando %-.16s negato per l'utente: '%-.32s'@'%-.64s' sulla tabella '%-.64s'"
+ jpn "¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ,¥Æ¡¼¥Ö¥ë '%-.64s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+ kor "'%-.16s' ¸í·ÉÀº ´ÙÀ½ »ç¿ëÀÚ¿¡°Ô °ÅºÎµÇ¾ú½À´Ï´Ù. : '%-.32s'@'%-.64s' for Å×À̺í '%-.64s'"
+ por "Comando '%-.16s' negado para o usuário '%-.32s'@'%-.64s' na tabela '%-.64s'"
+ rum "Comanda %-.16s interzisa utilizatorului: '%-.32s'@'%-.64s' pentru tabela '%-.64s'"
+ rus "ëÏÍÁÎÄÁ %-.16s ÚÁÐÒÅÝÅÎÁ ÐÏÌØÚÏ×ÁÔÅÌÀ '%-.32s'@'%-.64s' ÄÌÑ ÔÁÂÌÉÃÙ '%-.64s'"
+ serbian "%-.16s komanda zabranjena za korisnika '%-.32s'@'%-.64s' za tabelu '%-.64s'"
+ spa "%-.16s comando negado para usuario: '%-.32s'@'%-.64s' para tabla '%-.64s'"
+ swe "%-.16s ej tillåtet för '%-.32s'@'%-.64s' för tabell '%-.64s'"
+ ukr "%-.16s ËÏÍÁÎÄÁ ÚÁÂÏÒÏÎÅÎÁ ËÏÒÉÓÔÕ×ÁÞÕ: '%-.32s'@'%-.64s' Õ ÔÁÂÌÉæ '%-.64s'"
+ER_COLUMNACCESS_DENIED_ERROR 42000
+ cze "%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.32s'@'%-.64s' pro sloupec '%-.64s' v tabulce '%-.64s'"
+ dan "%-.16s-kommandoen er ikke tilladt for brugeren '%-.32s'@'%-.64s' for kolonne '%-.64s' in tabellen '%-.64s'"
+ nla "%-.16s commando geweigerd voor gebruiker: '%-.32s'@'%-.64s' voor kolom '%-.64s' in tabel '%-.64s'"
+ eng "%-.16s command denied to user '%-.32s'@'%-.64s' for column '%-.64s' in table '%-.64s'"
+ jps "ƒRƒ}ƒ“ƒh %-.16s ‚Í ƒ†[ƒU[ '%-.32s'@'%-.64s'\n ƒJƒ‰ƒ€ '%-.64s' ƒe[ƒuƒ‹ '%-.64s' ‚ɑ΂µ‚Ä‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
+ est "%-.16s käsk ei ole lubatud kasutajale '%-.32s'@'%-.64s' tulbale '%-.64s' tabelis '%-.64s'"
+ fre "La commande '%-.16s' est interdite à l'utilisateur: '%-.32s'@'@%-.64s' sur la colonne '%-.64s' de la table '%-.64s'"
+ ger "%-.16s Befehl nicht erlaubt für Benutzer '%-.32s'@'%-.64s' und Spalte '%-.64s' in Tabelle '%-.64s'"
+ hun "%-.16s parancs a '%-.32s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.64s' mezo eseten a '%-.64s' tablaban"
+ ita "Comando %-.16s negato per l'utente: '%-.32s'@'%-.64s' sulla colonna '%-.64s' della tabella '%-.64s'"
+ jpn "¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s'\n ¥«¥é¥à '%-.64s' ¥Æ¡¼¥Ö¥ë '%-.64s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó"
+ kor "'%-.16s' ¸í·ÉÀº ´ÙÀ½ »ç¿ëÀÚ¿¡°Ô °ÅºÎµÇ¾ú½À´Ï´Ù. : '%-.32s'@'%-.64s' for Ä®·³ '%-.64s' in Å×À̺í '%-.64s'"
+ por "Comando '%-.16s' negado para o usuário '%-.32s'@'%-.64s' na coluna '%-.64s', na tabela '%-.64s'"
+ rum "Comanda %-.16s interzisa utilizatorului: '%-.32s'@'%-.64s' pentru coloana '%-.64s' in tabela '%-.64s'"
+ rus "ëÏÍÁÎÄÁ %-.16s ÚÁÐÒÅÝÅÎÁ ÐÏÌØÚÏ×ÁÔÅÌÀ '%-.32s'@'%-.64s' ÄÌÑ ÓÔÏÌÂÃÁ '%-.64s' × ÔÁÂÌÉÃÅ '%-.64s'"
+ serbian "%-.16s komanda zabranjena za korisnika '%-.32s'@'%-.64s' za kolonu '%-.64s' iz tabele '%-.64s'"
+ spa "%-.16s comando negado para usuario: '%-.32s'@'%-.64s' para columna '%-.64s' en la tabla '%-.64s'"
+ swe "%-.16s ej tillåtet för '%-.32s'@'%-.64s' för kolumn '%-.64s' i tabell '%-.64s'"
+ ukr "%-.16s ËÏÍÁÎÄÁ ÚÁÂÏÒÏÎÅÎÁ ËÏÒÉÓÔÕ×ÁÞÕ: '%-.32s'@'%-.64s' ÄÌÑ ÓÔÏ×ÂÃÑ '%-.64s' Õ ÔÁÂÌÉæ '%-.64s'"
+ER_ILLEGAL_GRANT_FOR_TABLE 42000
+ cze "Neplatn-Bý pøíkaz GRANT/REVOKE. Prosím, pøeètìte si v manuálu, jaká privilegia je mo¾né pou¾ít."
+ dan "Forkert GRANT/REVOKE kommando. Se i brugervejledningen hvilke privilegier der kan specificeres."
+ nla "Foutief GRANT/REVOKE commando. Raadpleeg de handleiding welke priveleges gebruikt kunnen worden."
+ eng "Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used"
+ est "Vigane GRANT/REVOKE käsk. Tutvu kasutajajuhendiga"
+ fre "Commande GRANT/REVOKE incorrecte. Consultez le manuel."
+ ger "Unzulässiger GRANT- oder REVOKE-Befehl. Verfügbare Berechtigungen sind im Handbuch aufgeführt"
+ greek "Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used."
+ hun "Ervenytelen GRANT/REVOKE parancs. Kerem, nezze meg a kezikonyvben, milyen jogok lehetsegesek"
+ ita "Comando GRANT/REVOKE illegale. Prego consultare il manuale per sapere quali privilegi possono essere usati."
+ jpn "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used."
+ kor "À߸øµÈ GRANT/REVOKE ¸í·É. ¾î¶² ±Ç¸®¿Í ½ÂÀÎÀÌ »ç¿ëµÇ¾î Áú ¼ö ÀÖ´ÂÁö ¸Þ´º¾óÀ» º¸½Ã¿À."
+ nor "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used."
+ norwegian-ny "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used."
+ pol "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used."
+ por "Comando GRANT/REVOKE ilegal. Por favor consulte no manual quais privilégios podem ser usados."
+ rum "Comanda GRANT/REVOKE ilegala. Consultati manualul in privinta privilegiilor ce pot fi folosite."
+ rus "îÅ×ÅÒÎÁÑ ËÏÍÁÎÄÁ GRANT ÉÌÉ REVOKE. ïÂÒÁÔÉÔÅÓØ Ë ÄÏËÕÍÅÎÔÁÃÉÉ, ÞÔÏÂÙ ×ÙÑÓÎÉÔØ, ËÁËÉÅ ÐÒÉ×ÉÌÅÇÉÉ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ"
+ serbian "Pogrešna 'GRANT' odnosno 'REVOKE' komanda. Molim Vas pogledajte u priruèniku koje vrednosti mogu biti upotrebljene."
+ slo "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used."
+ spa "Ilegal comando GRANT/REVOKE. Por favor consulte el manual para cuales permisos pueden ser usados."
+ swe "Felaktigt GRANT-privilegium använt"
+ ukr "èÉÂÎÁ GRANT/REVOKE ËÏÍÁÎÄÁ; ÐÒÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ ÓÔÏÓÏ×ÎÏ ÔÏÇÏ, Ñ˦ ÐÒÁ×Á ÍÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ"
+ER_GRANT_WRONG_HOST_OR_USER 42000
+ cze "Argument p-Bøíkazu GRANT u¾ivatel nebo stroj je pøíli¹ dlouhý"
+ dan "Værts- eller brugernavn for langt til GRANT"
+ nla "De host of gebruiker parameter voor GRANT is te lang"
+ eng "The host or user argument to GRANT is too long"
+ est "Masina või kasutaja nimi GRANT lauses on liiga pikk"
+ fre "L'hôte ou l'utilisateur donné en argument à GRANT est trop long"
+ ger "Das Host- oder User-Argument für GRANT ist zu lang"
+ hun "A host vagy felhasznalo argumentuma tul hosszu a GRANT parancsban"
+ ita "L'argomento host o utente per la GRANT e` troppo lungo"
+ kor "½ÂÀÎ(GRANT)À» À§ÇÏ¿© »ç¿ëÇÑ »ç¿ëÀÚ³ª È£½ºÆ®ÀÇ °ªµéÀÌ ³Ê¹« ±é´Ï´Ù."
+ por "Argumento de 'host' ou de usuário para o GRANT é longo demais"
+ rum "Argumentul host-ului sau utilizatorului pentru GRANT e prea lung"
+ rus "óÌÉÛËÏÍ ÄÌÉÎÎÏÅ ÉÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ/ÈÏÓÔÁ ÄÌÑ GRANT"
+ serbian "Argument 'host' ili 'korisnik' prosleðen komandi 'GRANT' je predugaèak"
+ spa "El argumento para servidor o usuario para GRANT es demasiado grande"
+ swe "Felaktigt maskinnamn eller användarnamn använt med GRANT"
+ ukr "áÒÇÕÍÅÎÔ host ÁÂÏ user ÄÌÑ GRANT ÚÁÄÏ×ÇÉÊ"
+ER_NO_SUCH_TABLE 42S02
+ cze "Tabulka '%-.64s.%s' neexistuje"
+ dan "Tabellen '%-.64s.%-.64s' eksisterer ikke"
+ nla "Tabel '%-.64s.%s' bestaat niet"
+ eng "Table '%-.64s.%-.64s' doesn't exist"
+ est "Tabelit '%-.64s.%-.64s' ei eksisteeri"
+ fre "La table '%-.64s.%s' n'existe pas"
+ ger "Tabelle '%-.64s.%-.64s' existiert nicht"
+ hun "A '%-.64s.%s' tabla nem letezik"
+ ita "La tabella '%-.64s.%s' non esiste"
+ jpn "Table '%-.64s.%s' doesn't exist"
+ kor "Å×À̺í '%-.64s.%s' ´Â Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù."
+ nor "Table '%-.64s.%s' doesn't exist"
+ norwegian-ny "Table '%-.64s.%s' doesn't exist"
+ pol "Table '%-.64s.%s' doesn't exist"
+ por "Tabela '%-.64s.%-.64s' não existe"
+ rum "Tabela '%-.64s.%-.64s' nu exista"
+ rus "ôÁÂÌÉÃÁ '%-.64s.%-.64s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+ serbian "Tabela '%-.64s.%-.64s' ne postoji"
+ slo "Table '%-.64s.%s' doesn't exist"
+ spa "Tabla '%-.64s.%s' no existe"
+ swe "Det finns ingen tabell som heter '%-.64s.%s'"
+ ukr "ôÁÂÌÉÃÑ '%-.64s.%-.64s' ÎÅ ¦ÓÎÕ¤"
+ER_NONEXISTING_TABLE_GRANT 42000
+ cze "Neexistuje odpov-Bídající grant pro u¾ivatele '%-.32s' na stroji '%-.64s' pro tabulku '%-.64s'"
+ dan "Denne tilladelse eksisterer ikke for brugeren '%-.32s' på vært '%-.64s' for tabellen '%-.64s'"
+ nla "Deze toegang (GRANT) is niet toegekend voor gebruiker '%-.32s' op host '%-.64s' op tabel '%-.64s'"
+ eng "There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'"
+ est "Sellist õigust ei ole defineeritud kasutajale '%-.32s' masinast '%-.64s' tabelile '%-.64s'"
+ fre "Un tel droit n'est pas défini pour l'utilisateur '%-.32s' sur l'hôte '%-.64s' sur la table '%-.64s'"
+ ger "Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s' an Tabelle '%-.64s'"
+ hun "A '%-.32s' felhasznalo szamara a '%-.64s' host '%-.64s' tablajaban ez a parancs nem engedelyezett"
+ ita "GRANT non definita per l'utente '%-.32s' dalla macchina '%-.64s' sulla tabella '%-.64s'"
+ kor "»ç¿ëÀÚ '%-.32s'(È£½ºÆ® '%-.64s')´Â Å×À̺í '%-.64s'¸¦ »ç¿ëÇϱâ À§ÇÏ¿© Á¤ÀÇµÈ ½ÂÀÎÀº ¾ø½À´Ï´Ù. "
+ por "Não existe tal permissão (grant) definido para o usuário '%-.32s' no 'host' '%-.64s', na tabela '%-.64s'"
+ rum "Nu exista un astfel de privilegiu (grant) definit pentru utilizatorul '%-.32s' de pe host-ul '%-.64s' pentru tabela '%-.64s'"
+ rus "ôÁËÉÅ ÐÒÁ×Á ÎÅ ÏÐÒÅÄÅÌÅÎÙ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' ÎÁ ËÏÍÐØÀÔÅÒÅ '%-.64s' ÄÌÑ ÔÁÂÌÉÃÙ '%-.64s'"
+ serbian "Ne postoji odobrenje za pristup korisniku '%-.32s' na host-u '%-.64s' tabeli '%-.64s'"
+ spa "No existe tal permiso definido para usuario '%-.32s' en el servidor '%-.64s' en la tabla '%-.64s'"
+ swe "Det finns inget privilegium definierat för användare '%-.32s' på '%-.64s' för tabell '%-.64s'"
+ ukr "ðÏ×ÎÏ×ÁÖÅÎØ ÎÅ ×ÉÚÎÁÞÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ '%-.32s' Ú ÈÏÓÔÕ '%-.64s' ÄÌÑ ÔÁÂÌÉæ '%-.64s'"
+ER_NOT_ALLOWED_COMMAND 42000
+ cze "Pou-B¾itý pøíkaz není v této verzi MySQL povolen"
+ dan "Den brugte kommando er ikke tilladt med denne udgave af MySQL"
+ nla "Het used commando is niet toegestaan in deze MySQL versie"
+ eng "The used command is not allowed with this MySQL version"
+ est "Antud käsk ei ole lubatud käesolevas MySQL versioonis"
+ fre "Cette commande n'existe pas dans cette version de MySQL"
+ ger "Der verwendete Befehl ist in dieser MySQL-Version nicht zulässig"
+ hun "A hasznalt parancs nem engedelyezett ebben a MySQL verzioban"
+ ita "Il comando utilizzato non e` supportato in questa versione di MySQL"
+ kor "»ç¿ëµÈ ¸í·ÉÀº ÇöÀçÀÇ MySQL ¹öÁ¯¿¡¼­´Â ÀÌ¿ëµÇÁö ¾Ê½À´Ï´Ù."
+ por "Comando usado não é permitido para esta versão do MySQL"
+ rum "Comanda folosita nu este permisa pentru aceasta versiune de MySQL"
+ rus "üÔÁ ËÏÍÁÎÄÁ ÎÅ ÄÏÐÕÓËÁÅÔÓÑ × ÄÁÎÎÏÊ ×ÅÒÓÉÉ MySQL"
+ serbian "Upotrebljena komanda nije dozvoljena sa ovom verzijom MySQL servera"
+ spa "El comando usado no es permitido con esta versión de MySQL"
+ swe "Du kan inte använda detta kommando med denna MySQL version"
+ ukr "÷ÉËÏÒÉÓÔÏ×Õ×ÁÎÁ ËÏÍÁÎÄÁ ÎÅ ÄÏÚ×ÏÌÅÎÁ Õ Ã¦Ê ×ÅÒÓ¦§ MySQL"
+ER_SYNTAX_ERROR 42000
+ cze "Va-B¹e syntaxe je nìjaká divná"
+ dan "Der er en fejl i SQL syntaksen"
+ nla "Er is iets fout in de gebruikte syntax"
+ eng "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use"
+ est "Viga SQL süntaksis"
+ fre "Erreur de syntaxe"
+ ger "Fehler in der SQL-Syntax. Bitte die korrekte Syntax im Handbuch nachschlagen (diese kann für verschiedene Server-Versionen unterschiedlich sein)"
+ greek "You have an error in your SQL syntax"
+ hun "Szintaktikai hiba"
+ ita "Errore di sintassi nella query SQL"
+ jpn "Something is wrong in your syntax"
+ kor "SQL ±¸¹®¿¡ ¿À·ù°¡ ÀÖ½À´Ï´Ù."
+ nor "Something is wrong in your syntax"
+ norwegian-ny "Something is wrong in your syntax"
+ pol "Something is wrong in your syntax"
+ por "Você tem um erro de sintaxe no seu SQL"
+ rum "Aveti o eroare in sintaxa RSQL"
+ rus "õ ×ÁÓ ÏÛÉÂËÁ × ÚÁÐÒÏÓÅ. éÚÕÞÉÔÅ ÄÏËÕÍÅÎÔÁÃÉÀ ÐÏ ÉÓÐÏÌØÚÕÅÍÏÊ ×ÅÒÓÉÉ MySQL ÎÁ ÐÒÅÄÍÅÔ ËÏÒÒÅËÔÎÏÇÏ ÓÉÎÔÁËÓÉÓÁ"
+ serbian "Imate grešku u vašoj SQL sintaksi"
+ slo "Something is wrong in your syntax"
+ spa "Algo está equivocado en su sintax"
+ swe "Du har något fel i din syntax"
+ ukr "õ ×ÁÓ ÐÏÍÉÌËÁ Õ ÓÉÎÔÁËÓÉÓ¦ SQL"
+ER_DELAYED_CANT_CHANGE_LOCK
+ cze "Zpo-B¾dìný insert threadu nebyl schopen získat po¾adovaný zámek pro tabulku %-.64s"
+ dan "Forsinket indsættelse tråden (delayed insert thread) kunne ikke opnå lås på tabellen %-.64s"
+ nla "'Delayed insert' thread kon de aangevraagde 'lock' niet krijgen voor tabel %-.64s"
+ eng "Delayed insert thread couldn't get requested lock for table %-.64s"
+ est "INSERT DELAYED lõim ei suutnud saada soovitud lukku tabelile %-.64s"
+ fre "La tâche 'delayed insert' n'a pas pu obtenir le verrou démandé sur la table %-.64s"
+ ger "Verzögerter (DELAYED) Einfüge-Thread konnte die angeforderte Sperre für Tabelle '%-.64s' nicht erhalten"
+ hun "A kesleltetett beillesztes (delayed insert) thread nem kapott zatolast a %-.64s tablahoz"
+ ita "Il thread di inserimento ritardato non riesce ad ottenere il lock per la tabella %-.64s"
+ kor "Áö¿¬µÈ insert ¾²·¹µå°¡ Å×À̺í %-.64sÀÇ ¿ä±¸µÈ ¶ôÅ·À» ó¸®ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù."
+ por "'Thread' de inserção retardada (atrasada) pois não conseguiu obter a trava solicitada para tabela '%-.64s'"
+ rum "Thread-ul pentru inserarea aminata nu a putut obtine lacatul (lock) pentru tabela %-.64s"
+ rus "ðÏÔÏË, ÏÂÓÌÕÖÉ×ÁÀÝÉÊ ÏÔÌÏÖÅÎÎÕÀ ×ÓÔÁ×ËÕ (delayed insert), ÎÅ ÓÍÏÇ ÐÏÌÕÞÉÔØ ÚÁÐÒÁÛÉ×ÁÅÍÕÀ ÂÌÏËÉÒÏ×ËÕ ÎÁ ÔÁÂÌÉÃÕ %-.64s"
+ serbian "Prolongirani 'INSERT' thread nije mogao da dobije traženo zakljuèavanje tabele '%-.64s'"
+ spa "Thread de inserción retarda no pudiendo bloquear para la tabla %-.64s"
+ swe "DELAYED INSERT-tråden kunde inte låsa tabell '%-.64s'"
+ ukr "ç¦ÌËÁ ÄÌÑ INSERT DELAYED ÎÅ ÍÏÖÅ ÏÔÒÉÍÁÔÉ ÂÌÏËÕ×ÁÎÎÑ ÄÌÑ ÔÁÂÌÉæ %-.64s"
+ER_TOO_MANY_DELAYED_THREADS
+ cze "P-Bøíli¹ mnoho zpo¾dìných threadù"
+ dan "For mange slettede tråde (threads) i brug"
+ nla "Te veel 'delayed' threads in gebruik"
+ eng "Too many delayed threads in use"
+ est "Liiga palju DELAYED lõimesid kasutusel"
+ fre "Trop de tâche 'delayed' en cours"
+ ger "Zu viele verzögerte (DELAYED) Threads in Verwendung"
+ hun "Tul sok kesletetett thread (delayed)"
+ ita "Troppi threads ritardati in uso"
+ kor "³Ê¹« ¸¹Àº Áö¿¬ ¾²·¹µå¸¦ »ç¿ëÇÏ°í ÀÖ½À´Ï´Ù."
+ por "Excesso de 'threads' retardadas (atrasadas) em uso"
+ rum "Prea multe threaduri aminate care sint in uz"
+ rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÐÏÔÏËÏ×, ÏÂÓÌÕÖÉ×ÁÀÝÉÈ ÏÔÌÏÖÅÎÎÕÀ ×ÓÔÁ×ËÕ (delayed insert)"
+ serbian "Previše prolongiranih thread-ova je u upotrebi"
+ spa "Muchos threads retardados en uso"
+ swe "Det finns redan 'max_delayed_threads' trådar i använding"
+ ukr "úÁÂÁÇÁÔÏ ÚÁÔÒÉÍÁÎÉÈ Ç¦ÌÏË ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ"
+ER_ABORTING_CONNECTION 08S01
+ cze "Zru-B¹eno spojení %ld do databáze: '%-.64s' u¾ivatel: '%-.64s' (%s)"
+ dan "Afbrudt forbindelse %ld til database: '%-.64s' bruger: '%-.64s' (%-.64s)"
+ nla "Afgebroken verbinding %ld naar db: '%-.64s' gebruiker: '%-.64s' (%s)"
+ eng "Aborted connection %ld to db: '%-.64s' user: '%-.32s' (%-.64s)"
+ est "Ühendus katkestatud %ld andmebaasile: '%-.64s' kasutajale: '%-.32s' (%-.64s)"
+ fre "Connection %ld avortée vers la bd: '%-.64s' utilisateur: '%-.64s' (%s)"
+ ger "Abbruch der Verbindung %ld zur Datenbank '%-.64s'. Benutzer: '%-.64s' (%-.64s)"
+ hun "Megszakitott kapcsolat %ld db: '%-.64s' adatbazishoz, felhasznalo: '%-.64s' (%s)"
+ ita "Interrotta la connessione %ld al db: '%-.64s' utente: '%-.64s' (%s)"
+ jpn "Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)"
+ kor "µ¥ÀÌŸº£À̽º Á¢¼ÓÀ» À§ÇÑ ¿¬°á %ld°¡ Áß´ÜµÊ : '%-.64s' »ç¿ëÀÚ: '%-.64s' (%s)"
+ nor "Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)"
+ norwegian-ny "Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)"
+ pol "Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)"
+ por "Conexão %ld abortou para o banco de dados '%-.64s' - usuário '%-.32s' (%-.64s)"
+ rum "Conectie terminata %ld la baza de date: '%-.64s' utilizator: '%-.32s' (%-.64s)"
+ rus "ðÒÅÒ×ÁÎÏ ÓÏÅÄÉÎÅÎÉÅ %ld Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.64s' ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' (%-.64s)"
+ serbian "Prekinuta konekcija broj %ld ka bazi: '%-.64s' korisnik je bio: '%-.32s' (%-.64s)"
+ slo "Aborted connection %ld to db: '%-.64s' user: '%-.64s' (%s)"
+ spa "Conexión abortada %ld para db: '%-.64s' usuario: '%-.64s' (%s)"
+ swe "Avbröt länken för tråd %ld till db '%-.64s', användare '%-.64s' (%s)"
+ ukr "ðÅÒÅÒ×ÁÎÏ Ú'¤ÄÎÁÎÎÑ %ld ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ: '%-.64s' ËÏÒÉÓÔÕ×ÁÞÁ: '%-.32s' (%-.64s)"
+ER_NET_PACKET_TOO_LARGE 08S01
+ cze "Zji-B¹tìn pøíchozí packet del¹í ne¾ 'max_allowed_packet'"
+ dan "Modtog en datapakke som var større end 'max_allowed_packet'"
+ nla "Groter pakket ontvangen dan 'max_allowed_packet'"
+ eng "Got a packet bigger than 'max_allowed_packet' bytes"
+ est "Saabus suurem pakett kui lubatud 'max_allowed_packet' muutujaga"
+ fre "Paquet plus grand que 'max_allowed_packet' reçu"
+ ger "Empfangenes Paket ist größer als 'max_allowed_packet'"
+ hun "A kapott csomag nagyobb, mint a maximalisan engedelyezett: 'max_allowed_packet'"
+ ita "Ricevuto un pacchetto piu` grande di 'max_allowed_packet'"
+ kor "'max_allowed_packet'º¸´Ù ´õÅ« ÆÐŶÀ» ¹Þ¾Ò½À´Ï´Ù."
+ por "Obteve um pacote maior do que a taxa máxima de pacotes definida (max_allowed_packet)"
+ rum "Un packet mai mare decit 'max_allowed_packet' a fost primit"
+ rus "ðÏÌÕÞÅÎÎÙÊ ÐÁËÅÔ ÂÏÌØÛÅ, ÞÅÍ 'max_allowed_packet'"
+ serbian "Primio sam mrežni paket veæi od definisane vrednosti 'max_allowed_packet'"
+ spa "Obtenido un paquete mayor que 'max_allowed_packet'"
+ swe "Kommunkationspaketet är större än 'max_allowed_packet'"
+ ukr "ïÔÒÉÍÁÎÏ ÐÁËÅÔ Â¦ÌØÛÉÊ Î¦Ö max_allowed_packet"
+ER_NET_READ_ERROR_FROM_PIPE 08S01
+ cze "Zji-B¹tìna chyba pøi ètení z roury spojení"
+ dan "Fik læsefejl fra forbindelse (connection pipe)"
+ nla "Kreeg leesfout van de verbindings pipe"
+ eng "Got a read error from the connection pipe"
+ est "Viga ühendustoru lugemisel"
+ fre "Erreur de lecture reçue du pipe de connection"
+ ger "Lese-Fehler bei einer Kommunikations-Pipe"
+ hun "Olvasasi hiba a kapcsolat soran"
+ ita "Rilevato un errore di lettura dalla pipe di connessione"
+ kor "¿¬°á ÆÄÀÌÇÁ·ÎºÎÅÍ ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù."
+ por "Obteve um erro de leitura no 'pipe' da conexão"
+ rum "Eroare la citire din cauza lui 'connection pipe'"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÞÔÅÎÉÑ ÏÔ ÐÏÔÏËÁ ÓÏÅÄÉÎÅÎÉÑ (connection pipe)"
+ serbian "Greška pri èitanju podataka sa pipe-a"
+ spa "Obtenido un error de lectura de la conexión pipe"
+ swe "Fick läsfel från klienten vid läsning från 'PIPE'"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÞÉÔÁÎÎÑ Ú ËÏÍÕΦËÁæÊÎÏÇÏ ËÁÎÁÌÕ"
+ER_NET_FCNTL_ERROR 08S01
+ cze "Zji-B¹tìna chyba fcntl()"
+ dan "Fik fejlmeddelelse fra fcntl()"
+ nla "Kreeg fout van fcntl()"
+ eng "Got an error from fcntl()"
+ est "fcntl() tagastas vea"
+ fre "Erreur reçue de fcntl() "
+ ger "fcntl() lieferte einen Fehler"
+ hun "Hiba a fcntl() fuggvenyben"
+ ita "Rilevato un errore da fcntl()"
+ kor "fcntl() ÇÔ¼ö·ÎºÎÅÍ ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù."
+ por "Obteve um erro em fcntl()"
+ rum "Eroare obtinuta de la fcntl()"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÏÔ fcntl()"
+ serbian "Greška pri izvršavanju funkcije fcntl()"
+ spa "Obtenido un error de fcntl()"
+ swe "Fick fatalt fel från 'fcntl()'"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËËÕ ×¦Ä fcntl()"
+ER_NET_PACKETS_OUT_OF_ORDER 08S01
+ cze "P-Bøíchozí packety v chybném poøadí"
+ dan "Modtog ikke datapakker i korrekt rækkefølge"
+ nla "Pakketten in verkeerde volgorde ontvangen"
+ eng "Got packets out of order"
+ est "Paketid saabusid vales järjekorras"
+ fre "Paquets reçus dans le désordre"
+ ger "Pakete nicht in der richtigen Reihenfolge empfangen"
+ hun "Helytelen sorrendben erkezett adatcsomagok"
+ ita "Ricevuti pacchetti non in ordine"
+ kor "¼ø¼­°¡ ¸ÂÁö¾Ê´Â ÆÐŶÀ» ¹Þ¾Ò½À´Ï´Ù."
+ por "Obteve pacotes fora de ordem"
+ rum "Packets care nu sint ordonati au fost gasiti"
+ rus "ðÁËÅÔÙ ÐÏÌÕÞÅÎÙ × ÎÅ×ÅÒÎÏÍ ÐÏÒÑÄËÅ"
+ serbian "Primio sam mrežne pakete van reda"
+ spa "Obtenido paquetes desordenados"
+ swe "Kommunikationspaketen kom i fel ordning"
+ ukr "ïÔÒÉÍÁÎÏ ÐÁËÅÔÉ Õ ÎÅÎÁÌÅÖÎÏÍÕ ÐÏÒÑÄËÕ"
+ER_NET_UNCOMPRESS_ERROR 08S01
+ cze "Nemohu rozkomprimovat komunika-Bèní packet"
+ dan "Kunne ikke dekomprimere kommunikations-pakke (communication packet)"
+ nla "Communicatiepakket kon niet worden gedecomprimeerd"
+ eng "Couldn't uncompress communication packet"
+ est "Viga andmepaketi lahtipakkimisel"
+ fre "Impossible de décompresser le paquet reçu"
+ ger "Kommunikationspaket lässt sich nicht entpacken"
+ hun "A kommunikacios adatcsomagok nem tomorithetok ki"
+ ita "Impossibile scompattare i pacchetti di comunicazione"
+ kor "Åë½Å ÆÐŶÀÇ ¾ÐÃàÇØÁ¦¸¦ ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù."
+ por "Não conseguiu descomprimir pacote de comunicação"
+ rum "Nu s-a putut decompresa pachetul de comunicatie (communication packet)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÒÁÓÐÁËÏ×ÁÔØ ÐÁËÅÔ, ÐÏÌÕÞÅÎÎÙÊ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ"
+ serbian "Ne mogu da dekompresujem mrežne pakete"
+ spa "No puedo descomprimir paquetes de comunicación"
+ swe "Kunde inte packa up kommunikationspaketet"
+ ukr "îÅ ÍÏÖÕ ÄÅËÏÍÐÒÅÓÕ×ÁÔÉ ËÏÍÕΦËÁæÊÎÉÊ ÐÁËÅÔ"
+ER_NET_READ_ERROR 08S01
+ cze "Zji-B¹tìna chyba pøi ètení komunikaèního packetu"
+ dan "Fik fejlmeddelelse ved læsning af kommunikations-pakker (communication packets)"
+ nla "Fout bij het lezen van communicatiepakketten"
+ eng "Got an error reading communication packets"
+ est "Viga andmepaketi lugemisel"
+ fre "Erreur de lecture des paquets reçus"
+ ger "Fehler beim Lesen eines Kommunikationspakets"
+ hun "HIba a kommunikacios adatcsomagok olvasasa soran"
+ ita "Rilevato un errore ricevendo i pacchetti di comunicazione"
+ kor "Åë½Å ÆÐŶÀ» Àд Áß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù."
+ por "Obteve um erro na leitura de pacotes de comunicação"
+ rum "Eroare obtinuta citind pachetele de comunicatie (communication packets)"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ × ÐÒÏÃÅÓÓÅ ÐÏÌÕÞÅÎÉÑ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ "
+ serbian "Greška pri primanju mrežnih paketa"
+ spa "Obtenido un error leyendo paquetes de comunicación"
+ swe "Fick ett fel vid läsning från klienten"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÞÉÔÁÎÎÑ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×"
+ER_NET_READ_INTERRUPTED 08S01
+ cze "Zji-B¹tìn timeout pøi ètení komunikaèního packetu"
+ dan "Timeout-fejl ved læsning af kommunukations-pakker (communication packets)"
+ nla "Timeout bij het lezen van communicatiepakketten"
+ eng "Got timeout reading communication packets"
+ est "Kontrollaja ületamine andmepakettide lugemisel"
+ fre "Timeout en lecture des paquets reçus"
+ ger "Zeitüberschreitung beim Lesen eines Kommunikationspakets"
+ hun "Idotullepes a kommunikacios adatcsomagok olvasasa soran"
+ ita "Rilevato un timeout ricevendo i pacchetti di comunicazione"
+ kor "Åë½Å ÆÐŶÀ» Àд Áß timeoutÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù."
+ por "Obteve expiração de tempo (timeout) na leitura de pacotes de comunicação"
+ rum "Timeout obtinut citind pachetele de comunicatie (communication packets)"
+ rus "ðÏÌÕÞÅÎ ÔÁÊÍÁÕÔ ÏÖÉÄÁÎÉÑ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ "
+ serbian "Vremenski limit za èitanje mrežnih paketa je istekao"
+ spa "Obtenido timeout leyendo paquetes de comunicación"
+ swe "Fick 'timeout' vid läsning från klienten"
+ ukr "ïÔÒÉÍÁÎÏ ÚÁÔÒÉÍËÕ ÞÉÔÁÎÎÑ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×"
+ER_NET_ERROR_ON_WRITE 08S01
+ cze "Zji-B¹tìna chyba pøi zápisu komunikaèního packetu"
+ dan "Fik fejlmeddelelse ved skrivning af kommunukations-pakker (communication packets)"
+ nla "Fout bij het schrijven van communicatiepakketten"
+ eng "Got an error writing communication packets"
+ est "Viga andmepaketi kirjutamisel"
+ fre "Erreur d'écriture des paquets envoyés"
+ ger "Fehler beim Schreiben eines Kommunikationspakets"
+ hun "Hiba a kommunikacios csomagok irasa soran"
+ ita "Rilevato un errore inviando i pacchetti di comunicazione"
+ kor "Åë½Å ÆÐŶÀ» ±â·ÏÇÏ´Â Áß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù."
+ por "Obteve um erro na escrita de pacotes de comunicação"
+ rum "Eroare in scrierea pachetelor de comunicatie (communication packets)"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÐÒÉ ÐÅÒÅÄÁÞÅ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ "
+ serbian "Greška pri slanju mrežnih paketa"
+ spa "Obtenido un error de escribiendo paquetes de comunicación"
+ swe "Fick ett fel vid skrivning till klienten"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÚÁÐÉÓÕ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×"
+ER_NET_WRITE_INTERRUPTED 08S01
+ cze "Zji-B¹tìn timeout pøi zápisu komunikaèního packetu"
+ dan "Timeout-fejl ved skrivning af kommunukations-pakker (communication packets)"
+ nla "Timeout bij het schrijven van communicatiepakketten"
+ eng "Got timeout writing communication packets"
+ est "Kontrollaja ületamine andmepakettide kirjutamisel"
+ fre "Timeout d'écriture des paquets envoyés"
+ ger "Zeitüberschreitung beim Schreiben eines Kommunikationspakets"
+ hun "Idotullepes a kommunikacios csomagok irasa soran"
+ ita "Rilevato un timeout inviando i pacchetti di comunicazione"
+ kor "Åë½Å ÆÐÆÂÀ» ±â·ÏÇÏ´Â Áß timeoutÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù."
+ por "Obteve expiração de tempo ('timeout') na escrita de pacotes de comunicação"
+ rum "Timeout obtinut scriind pachetele de comunicatie (communication packets)"
+ rus "ðÏÌÕÞÅÎ ÔÁÊÍÁÕÔ × ÐÒÏÃÅÓÓÅ ÐÅÒÅÄÁÞÉ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ "
+ serbian "Vremenski limit za slanje mrežnih paketa je istekao"
+ spa "Obtenido timeout escribiendo paquetes de comunicación"
+ swe "Fick 'timeout' vid skrivning till klienten"
+ ukr "ïÔÒÉÍÁÎÏ ÚÁÔÒÉÍËÕ ÚÁÐÉÓÕ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×"
+ER_TOO_LONG_STRING 42000
+ cze "V-Býsledný øetìzec je del¹í ne¾ 'max_allowed_packet'"
+ dan "Strengen med resultater er større end 'max_allowed_packet'"
+ nla "Resultaat string is langer dan 'max_allowed_packet'"
+ eng "Result string is longer than 'max_allowed_packet' bytes"
+ est "Tulemus on pikem kui lubatud 'max_allowed_packet' muutujaga"
+ fre "La chaîne résultat est plus grande que 'max_allowed_packet'"
+ ger "Ergebnis ist länger als 'max_allowed_packet'"
+ hun "Ez eredmeny sztring nagyobb, mint a lehetseges maximum: 'max_allowed_packet'"
+ ita "La stringa di risposta e` piu` lunga di 'max_allowed_packet'"
+ por "'String' resultante é mais longa do que 'max_allowed_packet'"
+ rum "Sirul rezultat este mai lung decit 'max_allowed_packet'"
+ rus "òÅÚÕÌØÔÉÒÕÀÝÁÑ ÓÔÒÏËÁ ÂÏÌØÛÅ, ÞÅÍ 'max_allowed_packet'"
+ serbian "Rezultujuèi string je duži nego što to dozvoljava parametar servera 'max_allowed_packet'"
+ spa "La string resultante es mayor que max_allowed_packet"
+ swe "Resultatsträngen är längre än max_allowed_packet"
+ ukr "óÔÒÏËÁ ÒÅÚÕÌØÔÁÔÕ ÄÏ×ÛÁ Î¦Ö max_allowed_packet"
+ER_TABLE_CANT_HANDLE_BLOB 42000
+ cze "Typ pou-B¾ité tabulky nepodporuje BLOB/TEXT sloupce"
+ dan "Denne tabeltype understøtter ikke brug af BLOB og TEXT kolonner"
+ nla "Het gebruikte tabel type ondersteunt geen BLOB/TEXT kolommen"
+ eng "The used table type doesn't support BLOB/TEXT columns"
+ est "Valitud tabelitüüp ei toeta BLOB/TEXT tüüpi välju"
+ fre "Ce type de table ne supporte pas les colonnes BLOB/TEXT"
+ ger "Der verwendete Tabellentyp unterstützt keine BLOB- und TEXT-Spalten"
+ hun "A hasznalt tabla tipus nem tamogatja a BLOB/TEXT mezoket"
+ ita "Il tipo di tabella usata non supporta colonne di tipo BLOB/TEXT"
+ por "Tipo de tabela usado não permite colunas BLOB/TEXT"
+ rum "Tipul de tabela folosit nu suporta coloane de tip BLOB/TEXT"
+ rus "éÓÐÏÌØÚÕÅÍÁÑ ÔÁÂÌÉÃÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÔÉÐÙ BLOB/TEXT"
+ serbian "Iskorišteni tip tabele ne podržava kolone tipa 'BLOB' odnosno 'TEXT'"
+ spa "El tipo de tabla usada no permite soporte para columnas BLOB/TEXT"
+ swe "Den använda tabelltypen kan inte hantera BLOB/TEXT-kolumner"
+ ukr "÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ BLOB/TEXT ÓÔÏ×Âæ"
+ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 42000
+ cze "Typ pou-B¾ité tabulky nepodporuje AUTO_INCREMENT sloupce"
+ dan "Denne tabeltype understøtter ikke brug af AUTO_INCREMENT kolonner"
+ nla "Het gebruikte tabel type ondersteunt geen AUTO_INCREMENT kolommen"
+ eng "The used table type doesn't support AUTO_INCREMENT columns"
+ est "Valitud tabelitüüp ei toeta AUTO_INCREMENT tüüpi välju"
+ fre "Ce type de table ne supporte pas les colonnes AUTO_INCREMENT"
+ ger "Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT-Spalten"
+ hun "A hasznalt tabla tipus nem tamogatja az AUTO_INCREMENT tipusu mezoket"
+ ita "Il tipo di tabella usata non supporta colonne di tipo AUTO_INCREMENT"
+ por "Tipo de tabela usado não permite colunas AUTO_INCREMENT"
+ rum "Tipul de tabela folosit nu suporta coloane de tip AUTO_INCREMENT"
+ rus "éÓÐÏÌØÚÕÅÍÁÑ ÔÁÂÌÉÃÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ Á×ÔÏÉÎËÒÅÍÅÎÔÎÙÅ ÓÔÏÌÂÃÙ"
+ serbian "Iskorišteni tip tabele ne podržava kolone tipa 'AUTO_INCREMENT'"
+ spa "El tipo de tabla usada no permite soporte para columnas AUTO_INCREMENT"
+ swe "Den använda tabelltypen kan inte hantera AUTO_INCREMENT-kolumner"
+ ukr "÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ AUTO_INCREMENT ÓÔÏ×Âæ"
+ER_DELAYED_INSERT_TABLE_LOCKED
+ cze "INSERT DELAYED nen-Bí mo¾no s tabulkou '%-.64s' pou¾ít, proto¾e je zamèená pomocí LOCK TABLES"
+ dan "INSERT DELAYED kan ikke bruges med tabellen '%-.64s', fordi tabellen er låst med LOCK TABLES"
+ nla "INSERT DELAYED kan niet worden gebruikt bij table '%-.64s', vanwege een 'lock met LOCK TABLES"
+ eng "INSERT DELAYED can't be used with table '%-.64s' because it is locked with LOCK TABLES"
+ est "INSERT DELAYED ei saa kasutada tabeli '%-.64s' peal, kuna see on lukustatud LOCK TABLES käsuga"
+ fre "INSERT DELAYED ne peut être utilisé avec la table '%-.64s', car elle est verrouée avec LOCK TABLES"
+ ger "INSERT DELAYED kann nicht auf Tabelle '%-.64s' angewendet werden, da diese mit LOCK TABLES gesperrt ist"
+ greek "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES"
+ hun "Az INSERT DELAYED nem hasznalhato a '%-.64s' tablahoz, mert a tabla zarolt (LOCK TABLES)"
+ ita "L'inserimento ritardato (INSERT DELAYED) non puo` essere usato con la tabella '%-.64s', perche` soggetta a lock da 'LOCK TABLES'"
+ jpn "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES"
+ kor "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES"
+ nor "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES"
+ norwegian-ny "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES"
+ pol "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES"
+ por "INSERT DELAYED não pode ser usado com a tabela '%-.64s', porque ela está travada com LOCK TABLES"
+ rum "INSERT DELAYED nu poate fi folosit cu tabela '%-.64s', deoarece este locked folosing LOCK TABLES"
+ rus "îÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ INSERT DELAYED ÄÌÑ ÔÁÂÌÉÃÙ '%-.64s', ÐÏÔÏÍÕ ÞÔÏ ÏÎÁ ÚÁÂÌÏËÉÒÏ×ÁÎÁ Ó ÐÏÍÏÝØÀ LOCK TABLES"
+ serbian "Komanda 'INSERT DELAYED' ne može biti iskorištena u tabeli '%-.64s', zbog toga što je zakljuèana komandom 'LOCK TABLES'"
+ slo "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES"
+ spa "INSERT DELAYED no puede ser usado con tablas '%-.64s', porque esta bloqueada con LOCK TABLES"
+ swe "INSERT DELAYED kan inte användas med tabell '%-.64s', emedan den är låst med LOCK TABLES"
+ ukr "INSERT DELAYED ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÏ Ú ÔÁÂÌÉÃÅÀ '%-.64s', ÔÏÍÕ ÝÏ §§ ÚÁÂÌÏËÏ×ÁÎÏ Ú LOCK TABLES"
+ER_WRONG_COLUMN_NAME 42000
+ cze "Nespr-Bávné jméno sloupce '%-.100s'"
+ dan "Forkert kolonnenavn '%-.100s'"
+ nla "Incorrecte kolom naam '%-.100s'"
+ eng "Incorrect column name '%-.100s'"
+ est "Vigane tulba nimi '%-.100s'"
+ fre "Nom de colonne '%-.100s' incorrect"
+ ger "Falscher Spaltenname '%-.100s'"
+ hun "Ervenytelen mezonev: '%-.100s'"
+ ita "Nome colonna '%-.100s' non corretto"
+ por "Nome de coluna '%-.100s' incorreto"
+ rum "Nume increct de coloana '%-.100s'"
+ rus "îÅ×ÅÒÎÏÅ ÉÍÑ ÓÔÏÌÂÃÁ '%-.100s'"
+ serbian "Pogrešno ime kolone '%-.100s'"
+ spa "Incorrecto nombre de columna '%-.100s'"
+ swe "Felaktigt kolumnnamn '%-.100s'"
+ ukr "îÅצÒÎÅ ¦Í'Ñ ÓÔÏ×ÂÃÑ '%-.100s'"
+ER_WRONG_KEY_COLUMN 42000
+ cze "Handler pou-B¾ité tabulky neumí indexovat sloupce '%-.64s'"
+ dan "Den brugte tabeltype kan ikke indeksere kolonnen '%-.64s'"
+ nla "De gebruikte tabel 'handler' kan kolom '%-.64s' niet indexeren"
+ eng "The used storage engine can't index column '%-.64s'"
+ est "Tabelihandler ei oska indekseerida tulpa '%-.64s'"
+ fre "Le handler de la table ne peut indexé la colonne '%-.64s'"
+ ger "Der verwendete Tabellen-Handler kann die Spalte '%-.64s' nicht indizieren"
+ greek "The used table handler can't index column '%-.64s'"
+ hun "A hasznalt tablakezelo nem tudja a '%-.64s' mezot indexelni"
+ ita "Il gestore delle tabelle non puo` indicizzare la colonna '%-.64s'"
+ jpn "The used table handler can't index column '%-.64s'"
+ kor "The used table handler can't index column '%-.64s'"
+ nor "The used table handler can't index column '%-.64s'"
+ norwegian-ny "The used table handler can't index column '%-.64s'"
+ pol "The used table handler can't index column '%-.64s'"
+ por "O manipulador de tabela usado não pode indexar a coluna '%-.64s'"
+ rum "Handler-ul tabelei folosite nu poate indexa coloana '%-.64s'"
+ rus "éÓÐÏÌØÚÏ×ÁÎÎÙÊ ÏÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÍÏÖÅÔ ÐÒÏÉÎÄÅËÓÉÒÏ×ÁÔØ ÓÔÏÌÂÅà '%-.64s'"
+ serbian "Handler tabele ne može da indeksira kolonu '%-.64s'"
+ slo "The used table handler can't index column '%-.64s'"
+ spa "El manipulador de tabla usado no puede indexar columna '%-.64s'"
+ swe "Den använda tabelltypen kan inte indexera kolumn '%-.64s'"
+ ukr "÷ÉËÏÒÉÓÔÁÎÉÊ ×ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ÎÅ ÍÏÖÅ ¦ÎÄÅËÓÕ×ÁÔÉ ÓÔÏ×ÂÅÃØ '%-.64s'"
+ER_WRONG_MRG_TABLE
+ cze "V-B¹echny tabulky v MERGE tabulce nejsou definovány stejnì"
+ dan "Tabellerne i MERGE er ikke defineret ens"
+ nla "Niet alle tabellen in de MERGE tabel hebben identieke gedefinities"
+ eng "All tables in the MERGE table are not identically defined"
+ est "Kõik tabelid MERGE tabeli määratluses ei ole identsed"
+ fre "Toutes les tables de la table de type MERGE n'ont pas la même définition"
+ ger "Nicht alle Tabellen in der MERGE-Tabelle sind gleich definiert"
+ hun "A MERGE tablaban talalhato tablak definicioja nem azonos"
+ ita "Non tutte le tabelle nella tabella di MERGE sono definite in maniera identica"
+ jpn "All tables in the MERGE table are not defined identically"
+ kor "All tables in the MERGE table are not defined identically"
+ nor "All tables in the MERGE table are not defined identically"
+ norwegian-ny "All tables in the MERGE table are not defined identically"
+ pol "All tables in the MERGE table are not defined identically"
+ por "Todas as tabelas contidas na tabela fundida (MERGE) não estão definidas identicamente"
+ rum "Toate tabelele din tabela MERGE nu sint definite identic"
+ rus "îÅ ×ÓÅ ÔÁÂÌÉÃÙ × MERGE ÏÐÒÅÄÅÌÅÎÙ ÏÄÉÎÁËÏ×Ï"
+ serbian "Tabele iskorištene u 'MERGE' tabeli nisu definisane na isti naèin"
+ slo "All tables in the MERGE table are not defined identically"
+ spa "Todas las tablas en la MERGE tabla no estan definidas identicamente"
+ swe "Tabellerna i MERGE-tabellen är inte identiskt definierade"
+ ukr "ôÁÂÌÉæ Õ MERGE TABLE ÍÁÀÔØ Ò¦ÚÎÕ ÓÔÒÕËÔÕÒÕ"
+ER_DUP_UNIQUE 23000
+ cze "Kv-Bùli unique constraintu nemozu zapsat do tabulky '%-.64s'"
+ dan "Kan ikke skrive til tabellen '%-.64s' fordi det vil bryde CONSTRAINT regler"
+ nla "Kan niet opslaan naar table '%-.64s' vanwege 'unique' beperking"
+ eng "Can't write, because of unique constraint, to table '%-.64s'"
+ est "Ei suuda kirjutada tabelisse '%-.64s', kuna see rikub ühesuse kitsendust"
+ fre "Écriture impossible à cause d'un index UNIQUE sur la table '%-.64s'"
+ ger "Schreiben in Tabelle '%-.64s' nicht möglich wegen einer eindeutigen Beschränkung (unique constraint)"
+ hun "A '%-.64s' nem irhato, az egyedi mezok miatt"
+ ita "Impossibile scrivere nella tabella '%-.64s' per limitazione di unicita`"
+ por "Não pode gravar, devido à restrição UNIQUE, na tabela '%-.64s'"
+ rum "Nu pot scrie pe hard-drive, din cauza constraintului unic (unique constraint) pentru tabela '%-.64s'"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ × ÔÁÂÌÉÃÕ '%-.64s' ÉÚ-ÚÁ ÏÇÒÁÎÉÞÅÎÉÊ ÕÎÉËÁÌØÎÏÇÏ ËÌÀÞÁ"
+ serbian "Zbog provere jedinstvenosti ne mogu da upišem podatke u tabelu '%-.64s'"
+ spa "No puedo escribir, debido al único constraint, para tabla '%-.64s'"
+ swe "Kan inte skriva till tabell '%-.64s'; UNIQUE-test"
+ ukr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ ÄÏ ÔÁÂÌÉæ '%-.64s', Ú ÐÒÉÞÉÎÉ ×ÉÍÏÇ ÕΦËÁÌØÎÏÓÔ¦"
+ER_BLOB_KEY_WITHOUT_LENGTH 42000
+ cze "BLOB sloupec '%-.64s' je pou-B¾it ve specifikaci klíèe bez délky"
+ dan "BLOB kolonnen '%-.64s' brugt i nøglespecifikation uden nøglelængde"
+ nla "BLOB kolom '%-.64s' gebruikt in zoeksleutel specificatie zonder zoeksleutel lengte"
+ eng "BLOB/TEXT column '%-.64s' used in key specification without a key length"
+ est "BLOB-tüüpi tulp '%-.64s' on kasutusel võtmes ilma pikkust määratlemata"
+ fre "La colonne '%-.64s' de type BLOB est utilisée dans une définition d'index sans longueur d'index"
+ ger "BLOB- oder TEXT-Spalte '%-.64s' wird in der Schlüsseldefinition ohne Schlüssellängenangabe verwendet"
+ greek "BLOB column '%-.64s' used in key specification without a key length"
+ hun "BLOB mezo '%-.64s' hasznalt a mezo specifikacioban, a mezohossz megadasa nelkul"
+ ita "La colonna '%-.64s' di tipo BLOB e` usata in una chiave senza specificarne la lunghezza"
+ jpn "BLOB column '%-.64s' used in key specification without a key length"
+ kor "BLOB column '%-.64s' used in key specification without a key length"
+ nor "BLOB column '%-.64s' used in key specification without a key length"
+ norwegian-ny "BLOB column '%-.64s' used in key specification without a key length"
+ pol "BLOB column '%-.64s' used in key specification without a key length"
+ por "Coluna BLOB '%-.64s' usada na especificação de chave sem o comprimento da chave"
+ rum "Coloana BLOB '%-.64s' este folosita in specificarea unei chei fara ca o lungime de cheie sa fie folosita"
+ rus "óÔÏÌÂÅÃ ÔÉÐÁ BLOB '%-.64s' ÂÙÌ ÕËÁÚÁÎ × ÏÐÒÅÄÅÌÅÎÉÉ ËÌÀÞÁ ÂÅÚ ÕËÁÚÁÎÉÑ ÄÌÉÎÙ ËÌÀÞÁ"
+ serbian "BLOB kolona '%-.64s' je upotrebljena u specifikaciji kljuèa bez navoðenja dužine kljuèa"
+ slo "BLOB column '%-.64s' used in key specification without a key length"
+ spa "Columna BLOB column '%-.64s' usada en especificación de clave sin tamaño de la clave"
+ swe "Du har inte angett någon nyckellängd för BLOB '%-.64s'"
+ ukr "óÔÏ×ÂÅÃØ BLOB '%-.64s' ×ÉËÏÒÉÓÔÁÎÏ Õ ×ÉÚÎÁÞÅÎΦ ËÌÀÞÁ ÂÅÚ ×ËÁÚÁÎÎÑ ÄÏ×ÖÉÎÉ ËÌÀÞÁ"
+ER_PRIMARY_CANT_HAVE_NULL 42000
+ cze "V-B¹echny èásti primárního klíèe musejí být NOT NULL; pokud potøebujete NULL, pou¾ijte UNIQUE"
+ dan "Alle dele af en PRIMARY KEY skal være NOT NULL; Hvis du skal bruge NULL i nøglen, brug UNIQUE istedet"
+ nla "Alle delen van een PRIMARY KEY moeten NOT NULL zijn; Indien u NULL in een zoeksleutel nodig heeft kunt u UNIQUE gebruiken"
+ eng "All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead"
+ est "Kõik PRIMARY KEY peavad olema määratletud NOT NULL piiranguga; vajadusel kasuta UNIQUE tüüpi võtit"
+ fre "Toutes les parties d'un index PRIMARY KEY doivent être NOT NULL; Si vous avez besoin d'un NULL dans l'index, utilisez un index UNIQUE"
+ ger "Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein. Wenn NULL in einem Schlüssel verwendet wird, muss ein UNIQUE-Schlüssel verwendet werden"
+ hun "Az elsodleges kulcs teljes egeszeben csak NOT NULL tipusu lehet; Ha NULL mezot szeretne a kulcskent, hasznalja inkabb a UNIQUE-ot"
+ ita "Tutte le parti di una chiave primaria devono essere dichiarate NOT NULL; se necessitano valori NULL nelle chiavi utilizzare UNIQUE"
+ por "Todas as partes de uma chave primária devem ser não-nulas. Se você precisou usar um valor nulo (NULL) em uma chave, use a cláusula UNIQUE em seu lugar"
+ rum "Toate partile unei chei primare (PRIMARY KEY) trebuie sa fie NOT NULL; Daca aveti nevoie de NULL in vreo cheie, folositi UNIQUE in schimb"
+ rus "÷ÓÅ ÞÁÓÔÉ ÐÅÒ×ÉÞÎÏÇÏ ËÌÀÞÁ (PRIMARY KEY) ÄÏÌÖÎÙ ÂÙÔØ ÏÐÒÅÄÅÌÅÎÙ ËÁË NOT NULL; åÓÌÉ ×ÁÍ ÎÕÖÎÁ ÐÏÄÄÅÒÖËÁ ×ÅÌÉÞÉÎ NULL × ËÌÀÞÅ, ×ÏÓÐÏÌØÚÕÊÔÅÓØ ÉÎÄÅËÓÏÍ UNIQUE"
+ serbian "Svi delovi primarnog kljuèa moraju biti razlièiti od NULL; Ako Vam ipak treba NULL vrednost u kljuèu, upotrebite 'UNIQUE'"
+ spa "Todas las partes de un PRIMARY KEY deben ser NOT NULL; Si necesitas NULL en una clave, use UNIQUE"
+ swe "Alla delar av en PRIMARY KEY måste vara NOT NULL; Om du vill ha en nyckel med NULL, använd UNIQUE istället"
+ ukr "õÓ¦ ÞÁÓÔÉÎÉ PRIMARY KEY ÐÏ×ÉÎΦ ÂÕÔÉ NOT NULL; ñËÝÏ ×É ÐÏÔÒÅÂÕ¤ÔÅ NULL Õ ËÌÀÞ¦, ÓËÏÒÉÓÔÁÊÔÅÓÑ UNIQUE"
+ER_TOO_MANY_ROWS 42000
+ cze "V-Býsledek obsahuje více ne¾ jeden øádek"
+ dan "Resultatet bestod af mere end een række"
+ nla "Resultaat bevatte meer dan een rij"
+ eng "Result consisted of more than one row"
+ est "Tulemis oli rohkem kui üks kirje"
+ fre "Le résultat contient plus d'un enregistrement"
+ ger "Ergebnis besteht aus mehr als einer Zeile"
+ hun "Az eredmeny tobb, mint egy sort tartalmaz"
+ ita "Il risultato consiste di piu` di una riga"
+ por "O resultado consistiu em mais do que uma linha"
+ rum "Resultatul constista din mai multe linii"
+ rus "÷ ÒÅÚÕÌØÔÁÔÅ ×ÏÚ×ÒÁÝÅÎÁ ÂÏÌÅÅ ÞÅÍ ÏÄÎÁ ÓÔÒÏËÁ"
+ serbian "Rezultat je saèinjen od više slogova"
+ spa "Resultado compuesto de mas que una línea"
+ swe "Resultet bestod av mera än en rad"
+ ukr "òÅÚÕÌØÔÁÔ ÚÎÁÈÏÄÉÔØÓÑ Õ Â¦ÌØÛÅ Î¦Ö ÏÄÎ¦Ê ÓÔÒÏæ"
+ER_REQUIRES_PRIMARY_KEY 42000
+ cze "Tento typ tabulky vy-B¾aduje primární klíè"
+ dan "Denne tabeltype kræver en primærnøgle"
+ nla "Dit tabel type heeft een primaire zoeksleutel nodig"
+ eng "This table type requires a primary key"
+ est "Antud tabelitüüp nõuab primaarset võtit"
+ fre "Ce type de table nécessite une clé primaire (PRIMARY KEY)"
+ ger "Dieser Tabellentyp benötigt einen PRIMARY KEY"
+ hun "Az adott tablatipushoz elsodleges kulcs hasznalata kotelezo"
+ ita "Questo tipo di tabella richiede una chiave primaria"
+ por "Este tipo de tabela requer uma chave primária"
+ rum "Aceast tip de tabela are nevoie de o cheie primara"
+ rus "üÔÏÔ ÔÉÐ ÔÁÂÌÉÃÙ ÔÒÅÂÕÅÔ ÏÐÒÅÄÅÌÅÎÉÑ ÐÅÒ×ÉÞÎÏÇÏ ËÌÀÞÁ"
+ serbian "Ovaj tip tabele zahteva da imate definisan primarni kljuè"
+ spa "Este tipo de tabla necesita de una primary key"
+ swe "Denna tabelltyp kräver en PRIMARY KEY"
+ ukr "ãÅÊ ÔÉÐ ÔÁÂÌÉæ ÐÏÔÒÅÂÕ¤ ÐÅÒ×ÉÎÎÏÇÏ ËÌÀÞÁ"
+ER_NO_RAID_COMPILED
+ cze "Tato verze MySQL nen-Bí zkompilována s podporou RAID"
+ dan "Denne udgave af MySQL er ikke oversat med understøttelse af RAID"
+ nla "Deze versie van MySQL is niet gecompileerd met RAID ondersteuning"
+ eng "This version of MySQL is not compiled with RAID support"
+ est "Antud MySQL versioon on kompileeritud ilma RAID toeta"
+ fre "Cette version de MySQL n'est pas compilée avec le support RAID"
+ ger "Diese MySQL-Version ist nicht mit RAID-Unterstützung kompiliert"
+ hun "Ezen leforditott MySQL verzio nem tartalmaz RAID support-ot"
+ ita "Questa versione di MYSQL non e` compilata con il supporto RAID"
+ por "Esta versão do MySQL não foi compilada com suporte a RAID"
+ rum "Aceasta versiune de MySQL, nu a fost compilata cu suport pentru RAID"
+ rus "üÔÁ ×ÅÒÓÉÑ MySQL ÓËÏÍÐÉÌÉÒÏ×ÁÎÁ ÂÅÚ ÐÏÄÄÅÒÖËÉ RAID"
+ serbian "Ova verzija MySQL servera nije kompajlirana sa podrškom za RAID ureðaje"
+ spa "Esta versión de MySQL no es compilada con soporte RAID"
+ swe "Denna version av MySQL är inte kompilerad med RAID"
+ ukr "ãÑ ×ÅÒÓ¦Ñ MySQL ÎÅ ÚËÏÍЦÌØÏ×ÁÎÁ Ú Ð¦ÄÔÒÉÍËÏÀ RAID"
+ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
+ cze "Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno"
+ dan "Du bruger sikker opdaterings modus ('safe update mode') og du forsøgte at opdatere en tabel uden en WHERE klausul, der gør brug af et KEY felt"
+ nla "U gebruikt 'safe update mode' en u probeerde een tabel te updaten zonder een WHERE met een KEY kolom"
+ eng "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column"
+ est "Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita"
+ fre "Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index"
+ ger "MySQL läuft im sicheren Aktualisierungsmodus (safe update mode). Sie haben versucht, eine Tabelle zu aktualisieren, ohne in der WHERE-Klausel eine KEY-Spalte anzugeben"
+ hun "On a biztonsagos update modot hasznalja, es WHERE that uses a KEY column"
+ ita "In modalita` 'safe update' si e` cercato di aggiornare una tabella senza clausola WHERE su una chiave"
+ por "Você está usando modo de atualização seguro e tentou atualizar uma tabela sem uma cláusula WHERE que use uma coluna chave"
+ rus "÷Ù ÒÁÂÏÔÁÅÔÅ × ÒÅÖÉÍÅ ÂÅÚÏÐÁÓÎÙÈ ÏÂÎÏ×ÌÅÎÉÊ (safe update mode) É ÐÏÐÒÏÂÏ×ÁÌÉ ÉÚÍÅÎÉÔØ ÔÁÂÌÉÃÕ ÂÅÚ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ËÌÀÞÅ×ÏÇÏ ÓÔÏÌÂÃÁ × ÞÁÓÔÉ WHERE"
+ serbian "Vi koristite safe update mod servera, a probali ste da promenite podatke bez 'WHERE' komande koja koristi kolonu kljuèa"
+ spa "Tu estás usando modo de actualización segura y tentado actualizar una tabla sin un WHERE que usa una KEY columna"
+ swe "Du använder 'säker uppdateringsmod' och försökte uppdatera en tabell utan en WHERE-sats som använder sig av en nyckel"
+ ukr "÷É Õ ÒÅÖÉͦ ÂÅÚÐÅÞÎÏÇÏ ÏÎÏ×ÌÅÎÎÑ ÔÁ ÎÁÍÁÇÁ¤ÔÅÓØ ÏÎÏ×ÉÔÉ ÔÁÂÌÉÃÀ ÂÅÚ ÏÐÅÒÁÔÏÒÁ WHERE, ÝÏ ×ÉËÏÒÉÓÔÏ×Õ¤ KEY ÓÔÏ×ÂÅÃØ"
+ER_KEY_DOES_NOT_EXITS
+ cze "Kl-Bíè '%-.64s' v tabulce '%-.64s' neexistuje"
+ dan "Nøglen '%-.64s' eksisterer ikke i tabellen '%-.64s'"
+ nla "Zoeksleutel '%-.64s' bestaat niet in tabel '%-.64s'"
+ eng "Key '%-.64s' doesn't exist in table '%-.64s'"
+ est "Võti '%-.64s' ei eksisteeri tabelis '%-.64s'"
+ fre "L'index '%-.64s' n'existe pas sur la table '%-.64s'"
+ ger "Schlüssel '%-.64s' existiert in der Tabelle '%-.64s' nicht"
+ hun "A '%-.64s' kulcs nem letezik a '%-.64s' tablaban"
+ ita "La chiave '%-.64s' non esiste nella tabella '%-.64s'"
+ por "Chave '%-.64s' não existe na tabela '%-.64s'"
+ rus "ëÌÀÞ '%-.64s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ × ÔÁÂÌÉÃÅ '%-.64s'"
+ serbian "Kljuè '%-.64s' ne postoji u tabeli '%-.64s'"
+ spa "Clave '%-.64s' no existe en la tabla '%-.64s'"
+ swe "Nyckel '%-.64s' finns inte in tabell '%-.64s'"
+ ukr "ëÌÀÞ '%-.64s' ÎÅ ¦ÓÎÕ¤ × ÔÁÂÌÉæ '%-.64s'"
+ER_CHECK_NO_SUCH_TABLE 42000
+ cze "Nemohu otev-Bøít tabulku"
+ dan "Kan ikke åbne tabellen"
+ nla "Kan tabel niet openen"
+ eng "Can't open table"
+ est "Ei suuda avada tabelit"
+ fre "Impossible d'ouvrir la table"
+ ger "Kann Tabelle nicht öffnen"
+ hun "Nem tudom megnyitni a tablat"
+ ita "Impossibile aprire la tabella"
+ por "Não pode abrir a tabela"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ"
+ serbian "Ne mogu da otvorim tabelu"
+ spa "No puedo abrir tabla"
+ swe "Kan inte öppna tabellen"
+ ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÔÁÂÌÉÃÀ"
+ER_CHECK_NOT_IMPLEMENTED 42000
+ cze "Handler tabulky nepodporuje %s"
+ dan "Denne tabeltype understøtter ikke %s"
+ nla "De 'handler' voor de tabel ondersteund geen %s"
+ eng "The storage engine for the table doesn't support %s"
+ est "Antud tabelitüüp ei toeta %s käske"
+ fre "Ce type de table ne supporte pas les %s"
+ ger "Die Speicher-Engine für diese Tabelle unterstützt kein %s"
+ greek "The handler for the table doesn't support %s"
+ hun "A tabla kezeloje (handler) nem tamogatja az %s"
+ ita "Il gestore per la tabella non supporta il %s"
+ jpn "The handler for the table doesn't support %s"
+ kor "The handler for the table doesn't support %s"
+ nor "The handler for the table doesn't support %s"
+ norwegian-ny "The handler for the table doesn't support %s"
+ pol "The handler for the table doesn't support %s"
+ por "O manipulador de tabela não suporta %s"
+ rum "The handler for the table doesn't support %s"
+ rus "ïÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÜÔÏÇÏ: %s"
+ serbian "Handler za ovu tabelu ne dozvoljava 'check' odnosno 'repair' komande"
+ slo "The handler for the table doesn't support %s"
+ spa "El manipulador de la tabla no permite soporte para %s"
+ swe "Tabellhanteraren för denna tabell kan inte göra %s"
+ ukr "÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ %s"
+ER_CANT_DO_THIS_DURING_AN_TRANSACTION 25000
+ cze "Proveden-Bí tohoto pøíkazu není v transakci dovoleno"
+ dan "Du må ikke bruge denne kommando i en transaktion"
+ nla "Het is u niet toegestaan dit commando uit te voeren binnen een transactie"
+ eng "You are not allowed to execute this command in a transaction"
+ est "Seda käsku ei saa kasutada transaktsiooni sees"
+ fre "Vous n'êtes pas autorisé à exécute cette commande dans une transaction"
+ ger "Sie dürfen diesen Befehl nicht in einer Transaktion ausführen"
+ hun "Az On szamara nem engedelyezett a parancs vegrehajtasa a tranzakcioban"
+ ita "Non puoi eseguire questo comando in una transazione"
+ por "Não lhe é permitido executar este comando em uma transação"
+ rus "÷ÁÍ ÎÅ ÒÁÚÒÅÛÅÎÏ ×ÙÐÏÌÎÑÔØ ÜÔÕ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËÃÉÉ"
+ serbian "Nije Vam dozvoljeno da izvršite ovu komandu u transakciji"
+ spa "No tienes el permiso para ejecutar este comando en una transición"
+ swe "Du får inte utföra detta kommando i en transaktion"
+ ukr "÷ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÎÕ×ÁÔÉ ÃÀ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËæ§"
+ER_ERROR_DURING_COMMIT
+ cze "Chyba %d p-Bøi COMMIT"
+ dan "Modtog fejl %d mens kommandoen COMMIT blev udført"
+ nla "Kreeg fout %d tijdens COMMIT"
+ eng "Got error %d during COMMIT"
+ est "Viga %d käsu COMMIT täitmisel"
+ fre "Erreur %d lors du COMMIT"
+ ger "Fehler %d beim COMMIT"
+ hun "%d hiba a COMMIT vegrehajtasa soran"
+ ita "Rilevato l'errore %d durante il COMMIT"
+ por "Obteve erro %d durante COMMIT"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ COMMIT"
+ serbian "Greška %d za vreme izvršavanja komande 'COMMIT'"
+ spa "Obtenido error %d durante COMMIT"
+ swe "Fick fel %d vid COMMIT"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ COMMIT"
+ER_ERROR_DURING_ROLLBACK
+ cze "Chyba %d p-Bøi ROLLBACK"
+ dan "Modtog fejl %d mens kommandoen ROLLBACK blev udført"
+ nla "Kreeg fout %d tijdens ROLLBACK"
+ eng "Got error %d during ROLLBACK"
+ est "Viga %d käsu ROLLBACK täitmisel"
+ fre "Erreur %d lors du ROLLBACK"
+ ger "Fehler %d beim ROLLBACK"
+ hun "%d hiba a ROLLBACK vegrehajtasa soran"
+ ita "Rilevato l'errore %d durante il ROLLBACK"
+ por "Obteve erro %d durante ROLLBACK"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ ROLLBACK"
+ serbian "Greška %d za vreme izvršavanja komande 'ROLLBACK'"
+ spa "Obtenido error %d durante ROLLBACK"
+ swe "Fick fel %d vid ROLLBACK"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ ROLLBACK"
+ER_ERROR_DURING_FLUSH_LOGS
+ cze "Chyba %d p-Bøi FLUSH_LOGS"
+ dan "Modtog fejl %d mens kommandoen FLUSH_LOGS blev udført"
+ nla "Kreeg fout %d tijdens FLUSH_LOGS"
+ eng "Got error %d during FLUSH_LOGS"
+ est "Viga %d käsu FLUSH_LOGS täitmisel"
+ fre "Erreur %d lors du FLUSH_LOGS"
+ ger "Fehler %d bei FLUSH_LOGS"
+ hun "%d hiba a FLUSH_LOGS vegrehajtasa soran"
+ ita "Rilevato l'errore %d durante il FLUSH_LOGS"
+ por "Obteve erro %d durante FLUSH_LOGS"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ FLUSH_LOGS"
+ serbian "Greška %d za vreme izvršavanja komande 'FLUSH_LOGS'"
+ spa "Obtenido error %d durante FLUSH_LOGS"
+ swe "Fick fel %d vid FLUSH_LOGS"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ FLUSH_LOGS"
+ER_ERROR_DURING_CHECKPOINT
+ cze "Chyba %d p-Bøi CHECKPOINT"
+ dan "Modtog fejl %d mens kommandoen CHECKPOINT blev udført"
+ nla "Kreeg fout %d tijdens CHECKPOINT"
+ eng "Got error %d during CHECKPOINT"
+ est "Viga %d käsu CHECKPOINT täitmisel"
+ fre "Erreur %d lors du CHECKPOINT"
+ ger "Fehler %d bei CHECKPOINT"
+ hun "%d hiba a CHECKPOINT vegrehajtasa soran"
+ ita "Rilevato l'errore %d durante il CHECKPOINT"
+ por "Obteve erro %d durante CHECKPOINT"
+ rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ CHECKPOINT"
+ serbian "Greška %d za vreme izvršavanja komande 'CHECKPOINT'"
+ spa "Obtenido error %d durante CHECKPOINT"
+ swe "Fick fel %d vid CHECKPOINT"
+ ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ CHECKPOINT"
+ER_NEW_ABORTING_CONNECTION 08S01
+ cze "Spojen-Bí %ld do databáze: '%-.64s' u¾ivatel: '%-.32s' stroj: '%-.64s' (%-.64s) bylo pøeru¹eno"
+ dan "Afbrød forbindelsen %ld til databasen '%-.64s' bruger: '%-.32s' vært: '%-.64s' (%-.64s)"
+ nla "Afgebroken verbinding %ld naar db: '%-.64s' gebruiker: '%-.32s' host: '%-.64s' (%-.64s)"
+ eng "Aborted connection %ld to db: '%-.64s' user: '%-.32s' host: '%-.64s' (%-.64s)"
+ est "Ühendus katkestatud %ld andmebaas: '%-.64s' kasutaja: '%-.32s' masin: '%-.64s' (%-.64s)"
+ fre "Connection %ld avortée vers la bd: '%-.64s' utilisateur: '%-.32s' hôte: '%-.64s' (%-.64s)"
+ ger "Verbindungsabbruch %ld zur Datenbank '%-.64s'. Benutzer: '%-.32s', Host: '%-.64s' (%-.64s)"
+ ita "Interrotta la connessione %ld al db: ''%-.64s' utente: '%-.32s' host: '%-.64s' (%-.64s)"
+ por "Conexão %ld abortada para banco de dados '%-.64s' - usuário '%-.32s' - 'host' '%-.64s' ('%-.64s')"
+ rus "ðÒÅÒ×ÁÎÏ ÓÏÅÄÉÎÅÎÉÅ %ld Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.64s' ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' Ó ÈÏÓÔÁ '%-.64s' (%-.64s)"
+ serbian "Prekinuta konekcija broj %ld ka bazi: '%-.64s' korisnik je bio: '%-.32s' a host: '%-.64s' (%-.64s)"
+ spa "Abortada conexión %ld para db: '%-.64s' usuario: '%-.32s' servidor: '%-.64s' (%-.64s)"
+ swe "Avbröt länken för tråd %ld till db '%-.64s', användare '%-.32s', host '%-.64s' (%-.64s)"
+ ukr "ðÅÒÅÒ×ÁÎÏ Ú'¤ÄÎÁÎÎÑ %ld ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ: '%-.64s' ËÏÒÉÓÔÕ×ÁÞ: '%-.32s' ÈÏÓÔ: '%-.64s' (%-.64s)"
+ER_DUMP_NOT_IMPLEMENTED
+ cze "Handler tabulky nepodporuje bin-Bární dump"
+ dan "Denne tabeltype unserstøtter ikke binært tabeldump"
+ nla "De 'handler' voor de tabel ondersteund geen binaire tabel dump"
+ eng "The storage engine for the table does not support binary table dump"
+ fre "Ce type de table ne supporte pas les copies binaires"
+ ger "Die Speicher-Engine für die Tabelle unterstützt keinen binären Tabellen-Dump"
+ ita "Il gestore per la tabella non supporta il dump binario"
+ jpn "The handler for the table does not support binary table dump"
+ por "O manipulador de tabela não suporta 'dump' binário de tabela"
+ rum "The handler for the table does not support binary table dump"
+ rus "ïÂÒÁÂÏÔÞÉË ÜÔÏÊ ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ Ä×ÏÉÞÎÏÇÏ ÓÏÈÒÁÎÅÎÉÑ ÏÂÒÁÚÁ ÔÁÂÌÉÃÙ (dump)"
+ serbian "Handler tabele ne podržava binarni dump tabele"
+ spa "El manipulador de tabla no soporta dump para tabla binaria"
+ swe "Tabellhanteraren klarar inte en binär kopiering av tabellen"
+ ukr "ãÅÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ ¦ÎÁÒÎÕ ÐÅÒÅÄÁÞÕ ÔÁÂÌÉæ"
+ER_FLUSH_MASTER_BINLOG_CLOSED
+ eng "Binlog closed, cannot RESET MASTER"
+ ger "Binlog geschlossen. Kann RESET MASTER nicht ausführen"
+ por "Binlog fechado. Não pode fazer RESET MASTER"
+ rus "ä×ÏÉÞÎÙÊ ÖÕÒÎÁÌ ÏÂÎÏ×ÌÅÎÉÑ ÚÁËÒÙÔ, ÎÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ RESET MASTER"
+ serbian "Binarni log file zatvoren, ne mogu da izvršim komandu 'RESET MASTER'"
+ ukr "òÅÐ̦ËÁæÊÎÉÊ ÌÏÇ ÚÁËÒÉÔÏ, ÎÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ RESET MASTER"
+ER_INDEX_REBUILD
+ cze "P-Bøebudování indexu dumpnuté tabulky '%-.64s' nebylo úspì¹né"
+ dan "Kunne ikke genopbygge indekset for den dumpede tabel '%-.64s'"
+ nla "Gefaald tijdens heropbouw index van gedumpte tabel '%-.64s'"
+ eng "Failed rebuilding the index of dumped table '%-.64s'"
+ fre "La reconstruction de l'index de la table copiée '%-.64s' a échoué"
+ ger "Neuerstellung des Indizes der Dump-Tabelle '%-.64s' fehlgeschlagen"
+ greek "Failed rebuilding the index of dumped table '%-.64s'"
+ hun "Failed rebuilding the index of dumped table '%-.64s'"
+ ita "Fallita la ricostruzione dell'indice della tabella copiata '%-.64s'"
+ por "Falhou na reconstrução do índice da tabela 'dumped' '%-.64s'"
+ rus "ïÛÉÂËÁ ÐÅÒÅÓÔÒÏÊËÉ ÉÎÄÅËÓÁ ÓÏÈÒÁÎÅÎÎÏÊ ÔÁÂÌÉÃÙ '%-.64s'"
+ serbian "Izgradnja indeksa dump-ovane tabele '%-.64s' nije uspela"
+ spa "Falla reconstruyendo el indice de la tabla dumped '%-.64s'"
+ ukr "îÅ×ÄÁÌŠצÄÎÏ×ÌÅÎÎÑ ¦ÎÄÅËÓÁ ÐÅÒÅÄÁÎϧ ÔÁÂÌÉæ '%-.64s'"
+ER_MASTER
+ cze "Chyba masteru: '%-.64s'"
+ dan "Fejl fra master: '%-.64s'"
+ nla "Fout van master: '%-.64s'"
+ eng "Error from master: '%-.64s'"
+ fre "Erreur reçue du maître: '%-.64s'"
+ ger "Fehler vom Master: '%-.64s'"
+ ita "Errore dal master: '%-.64s"
+ por "Erro no 'master' '%-.64s'"
+ rus "ïÛÉÂËÁ ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ: '%-.64s'"
+ serbian "Greška iz glavnog servera '%-.64s' u klasteru"
+ spa "Error del master: '%-.64s'"
+ swe "Fick en master: '%-.64s'"
+ ukr "ðÏÍÉÌËÁ ×¦Ä ÇÏÌÏ×ÎÏÇÏ: '%-.64s'"
+ER_MASTER_NET_READ 08S01
+ cze "S-Bí»ová chyba pøi ètení z masteru"
+ dan "Netværksfejl ved læsning fra master"
+ nla "Net fout tijdens lezen van master"
+ eng "Net error reading from master"
+ fre "Erreur de lecture réseau reçue du maître"
+ ger "Netzfehler beim Lesen vom Master"
+ ita "Errore di rete durante la ricezione dal master"
+ por "Erro de rede lendo do 'master'"
+ rus "÷ÏÚÎÉËÌÁ ÏÛÉÂËÁ ÞÔÅÎÉÑ × ÐÒÏÃÅÓÓÅ ËÏÍÍÕÎÉËÁÃÉÉ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ"
+ serbian "Greška u primanju mrežnih paketa sa glavnog servera u klasteru"
+ spa "Error de red leyendo del master"
+ swe "Fick nätverksfel vid läsning från master"
+ ukr "íÅÒÅÖÅ×Á ÐÏÍÉÌËÁ ÞÉÔÁÎÎÑ ×¦Ä ÇÏÌÏ×ÎÏÇÏ"
+ER_MASTER_NET_WRITE 08S01
+ cze "S-Bí»ová chyba pøi zápisu na master"
+ dan "Netværksfejl ved skrivning til master"
+ nla "Net fout tijdens schrijven naar master"
+ eng "Net error writing to master"
+ fre "Erreur d'écriture réseau reçue du maître"
+ ger "Netzfehler beim Schreiben zum Master"
+ ita "Errore di rete durante l'invio al master"
+ por "Erro de rede gravando no 'master'"
+ rus "÷ÏÚÎÉËÌÁ ÏÛÉÂËÁ ÚÁÐÉÓÉ × ÐÒÏÃÅÓÓÅ ËÏÍÍÕÎÉËÁÃÉÉ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ"
+ serbian "Greška u slanju mrežnih paketa na glavni server u klasteru"
+ spa "Error de red escribiendo para el master"
+ swe "Fick nätverksfel vid skrivning till master"
+ ukr "íÅÒÅÖÅ×Á ÐÏÍÉÌËÁ ÚÁÐÉÓÕ ÄÏ ÇÏÌÏ×ÎÏÇÏ"
+ER_FT_MATCHING_KEY_NOT_FOUND
+ cze "-B®ádný sloupec nemá vytvoøen fulltextový index"
+ dan "Kan ikke finde en FULLTEXT nøgle som svarer til kolonne listen"
+ nla "Kan geen FULLTEXT index vinden passend bij de kolom lijst"
+ eng "Can't find FULLTEXT index matching the column list"
+ est "Ei suutnud leida FULLTEXT indeksit, mis kattuks kasutatud tulpadega"
+ fre "Impossible de trouver un index FULLTEXT correspondant à cette liste de colonnes"
+ ger "Kann keinen FULLTEXT-Index finden, der der Spaltenliste entspricht"
+ ita "Impossibile trovare un indice FULLTEXT che corrisponda all'elenco delle colonne"
+ por "Não pode encontrar um índice para o texto todo que combine com a lista de colunas"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÐÏÌÎÏÔÅËÓÔÏ×ÙÊ (FULLTEXT) ÉÎÄÅËÓ, ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÊ ÓÐÉÓËÕ ÓÔÏÌÂÃÏ×"
+ serbian "Ne mogu da pronaðem 'FULLTEXT' indeks koli odgovara listi kolona"
+ spa "No puedo encontrar índice FULLTEXT correspondiendo a la lista de columnas"
+ swe "Hittar inte ett FULLTEXT-index i kolumnlistan"
+ ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ FULLTEXT ¦ÎÄÅËÓ, ÝÏ ×¦ÄÐÏצÄÁ¤ ÐÅÒÅ̦ËÕ ÓÔÏ×Âæ×"
+ER_LOCK_OR_ACTIVE_TRANSACTION
+ cze "Nemohu prov-Bést zadaný pøíkaz, proto¾e existují aktivní zamèené tabulky nebo aktivní transakce"
+ dan "Kan ikke udføre den givne kommando fordi der findes aktive, låste tabeller eller fordi der udføres en transaktion"
+ nla "Kan het gegeven commando niet uitvoeren, want u heeft actieve gelockte tabellen of een actieve transactie"
+ eng "Can't execute the given command because you have active locked tables or an active transaction"
+ est "Ei suuda täita antud käsku kuna on aktiivseid lukke või käimasolev transaktsioon"
+ fre "Impossible d'exécuter la commande car vous avez des tables verrouillées ou une transaction active"
+ ger "Kann den angegebenen Befehl wegen einer aktiven Tabellensperre oder einer aktiven Transaktion nicht ausführen"
+ ita "Impossibile eseguire il comando richiesto: tabelle sotto lock o transazione in atto"
+ por "Não pode executar o comando dado porque você tem tabelas ativas travadas ou uma transação ativa"
+ rus "îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÕËÁÚÁÎÎÕÀ ËÏÍÁÎÄÕ, ÐÏÓËÏÌØËÕ Õ ×ÁÓ ÐÒÉÓÕÔÓÔ×ÕÀÔ ÁËÔÉ×ÎÏ ÚÁÂÌÏËÉÒÏ×ÁÎÎÙÅ ÔÁÂÌÉÃÁ ÉÌÉ ÏÔËÒÙÔÁÑ ÔÒÁÎÚÁËÃÉÑ"
+ serbian "Ne mogu da izvršim datu komandu zbog toga što su tabele zakljuèane ili je transakcija u toku"
+ spa "No puedo ejecutar el comando dado porque tienes tablas bloqueadas o una transición activa"
+ swe "Kan inte utföra kommandot emedan du har en låst tabell eller an aktiv transaktion"
+ ukr "îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ ÐÏÄÁÎÕ ËÏÍÁÎÄÕ ÔÏÍÕ, ÝÏ ÔÁÂÌÉÃÑ ÚÁÂÌÏËÏ×ÁÎÁ ÁÂÏ ×ÉËÏÎÕ¤ÔØÓÑ ÔÒÁÎÚÁËæÑ"
+ER_UNKNOWN_SYSTEM_VARIABLE
+ cze "Nezn-Bámá systémová promìnná '%-.64s'"
+ dan "Ukendt systemvariabel '%-.64s'"
+ nla "Onbekende systeem variabele '%-.64s'"
+ eng "Unknown system variable '%-.64s'"
+ est "Tundmatu süsteemne muutuja '%-.64s'"
+ fre "Variable système '%-.64s' inconnue"
+ ger "Unbekannte Systemvariable '%-.64s'"
+ ita "Variabile di sistema '%-.64s' sconosciuta"
+ por "Variável de sistema '%-.64s' desconhecida"
+ rus "îÅÉÚ×ÅÓÔÎÁÑ ÓÉÓÔÅÍÎÁÑ ÐÅÒÅÍÅÎÎÁÑ '%-.64s'"
+ serbian "Nepoznata sistemska promenljiva '%-.64s'"
+ spa "Desconocida variable de sistema '%-.64s'"
+ swe "Okänd systemvariabel: '%-.64s'"
+ ukr "îÅצÄÏÍÁ ÓÉÓÔÅÍÎÁ ÚͦÎÎÁ '%-.64s'"
+ER_CRASHED_ON_USAGE
+ cze "Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a mìla by být opravena"
+ dan "Tabellen '%-.64s' er markeret med fejl og bør repareres"
+ nla "Tabel '%-.64s' staat als gecrashed gemarkeerd en dient te worden gerepareerd"
+ eng "Table '%-.64s' is marked as crashed and should be repaired"
+ est "Tabel '%-.64s' on märgitud vigaseks ja tuleb parandada"
+ fre "La table '%-.64s' est marquée 'crashed' et devrait être réparée"
+ ger "Tabelle '%-.64s' ist als defekt markiert und sollte repariert werden"
+ ita "La tabella '%-.64s' e` segnalata come corrotta e deve essere riparata"
+ por "Tabela '%-.64s' está marcada como danificada e deve ser reparada"
+ rus "ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÄÏÌÖÎÁ ÐÒÏÊÔÉ ÐÒÏ×ÅÒËÕ É ÒÅÍÏÎÔ"
+ serbian "Tabela '%-.64s' je markirana kao ošteæena i trebala bi biti popravljena"
+ spa "Tabla '%-.64s' está marcada como crashed y debe ser reparada"
+ swe "Tabell '%-.64s' är trasig och bör repareras med REPAIR TABLE"
+ ukr "ôÁÂÌÉÃÀ '%-.64s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ §§ ÐÏÔÒ¦ÂÎÏ ×¦ÄÎÏ×ÉÔÉ"
+ER_CRASHED_ON_REPAIR
+ cze "Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila"
+ dan "Tabellen '%-.64s' er markeret med fejl og sidste (automatiske?) REPAIR fejlede"
+ nla "Tabel '%-.64s' staat als gecrashed gemarkeerd en de laatste (automatische?) reparatie poging mislukte"
+ eng "Table '%-.64s' is marked as crashed and last (automatic?) repair failed"
+ est "Tabel '%-.64s' on märgitud vigaseks ja viimane (automaatne?) parandus ebaõnnestus"
+ fre "La table '%-.64s' est marquée 'crashed' et le dernier 'repair' a échoué"
+ ger "Tabelle '%-.64s' ist als defekt markiert und der letzte (automatische?) Reparaturversuch schlug fehl"
+ ita "La tabella '%-.64s' e` segnalata come corrotta e l'ultima ricostruzione (automatica?) e` fallita"
+ por "Tabela '%-.64s' está marcada como danificada e a última reparação (automática?) falhou"
+ rus "ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÐÏÓÌÅÄÎÉÊ (Á×ÔÏÍÁÔÉÞÅÓËÉÊ?) ÒÅÍÏÎÔ ÎÅ ÂÙÌ ÕÓÐÅÛÎÙÍ"
+ serbian "Tabela '%-.64s' je markirana kao ošteæena, a zadnja (automatska?) popravka je bila neuspela"
+ spa "Tabla '%-.64s' está marcada como crashed y la última reparación (automactica?) falló"
+ swe "Tabell '%-.64s' är trasig och senast (automatiska?) reparation misslyckades"
+ ukr "ôÁÂÌÉÃÀ '%-.64s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ ÏÓÔÁÎΤ (Á×ÔÏÍÁÔÉÞÎÅ?) צÄÎÏ×ÌÅÎÎÑ ÎÅ ×ÄÁÌÏÓÑ"
+ER_WARNING_NOT_COMPLETE_ROLLBACK
+ dan "Advarsel: Visse data i tabeller der ikke understøtter transaktioner kunne ikke tilbagestilles"
+ nla "Waarschuwing: Roll back mislukt voor sommige buiten transacties gewijzigde tabellen"
+ eng "Some non-transactional changed tables couldn't be rolled back"
+ est "Hoiatus: mõnesid transaktsioone mittetoetavaid tabeleid ei suudetud tagasi kerida"
+ fre "Attention: certaines tables ne supportant pas les transactions ont été changées et elles ne pourront pas être restituées"
+ ger "Änderungen an einigen nicht transaktionalen Tabellen konnten nicht zurückgerollt werden"
+ ita "Attenzione: Alcune delle modifiche alle tabelle non transazionali non possono essere ripristinate (roll back impossibile)"
+ por "Aviso: Algumas tabelas não-transacionais alteradas não puderam ser reconstituídas (rolled back)"
+ rus "÷ÎÉÍÁÎÉÅ: ÐÏ ÎÅËÏÔÏÒÙÍ ÉÚÍÅÎÅÎÎÙÍ ÎÅÔÒÁÎÚÁËÃÉÏÎÎÙÍ ÔÁÂÌÉÃÁÍ ÎÅ×ÏÚÍÏÖÎÏ ÂÕÄÅÔ ÐÒÏÉÚ×ÅÓÔÉ ÏÔËÁÔ ÔÒÁÎÚÁËÃÉÉ"
+ serbian "Upozorenje: Neke izmenjene tabele ne podržavaju komandu 'ROLLBACK'"
+ spa "Aviso: Algunas tablas no transancionales no pueden tener rolled back"
+ swe "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK"
+ ukr "úÁÓÔÅÒÅÖÅÎÎÑ: äÅÑ˦ ÎÅÔÒÁÎÚÁËæÊΦ ÚͦÎÉ ÔÁÂÌÉÃØ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ÐÏ×ÅÒÎÕÔÉ"
+ER_TRANS_CACHE_FULL
+ dan "Fler-udtryks transaktion krævede mere plads en 'max_binlog_cache_size' bytes. Forhøj værdien af denne variabel og prøv igen"
+ nla "Multi-statement transactie vereist meer dan 'max_binlog_cache_size' bytes opslag. Verhoog deze mysqld variabele en probeer opnieuw"
+ eng "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again"
+ est "Mitme lausendiga transaktsioon nõudis rohkem ruumi kui lubatud 'max_binlog_cache_size' muutujaga. Suurenda muutuja väärtust ja proovi uuesti"
+ fre "Cette transaction à commandes multiples nécessite plus de 'max_binlog_cache_size' octets de stockage, augmentez cette variable de mysqld et réessayez"
+ ger "Transaktionen, die aus mehreren Befehlen bestehen, benötigen mehr als 'max_binlog_cache_size' Bytes an Speicher. Diese mysqld-Variable bitte vergrössern und erneut versuchen"
+ ita "La transazione a comandi multipli (multi-statement) ha richiesto piu` di 'max_binlog_cache_size' bytes di disco: aumentare questa variabile di mysqld e riprovare"
+ por "Transações multi-declaradas (multi-statement transactions) requeriram mais do que o valor limite (max_binlog_cache_size) de bytes para armazenagem. Aumente o valor desta variável do mysqld e tente novamente"
+ rus "ôÒÁÎÚÁËÃÉÉ, ×ËÌÀÞÁÀÝÅÊ ÂÏÌØÛÏÅ ËÏÌÉÞÅÓÔ×Ï ËÏÍÁÎÄ, ÐÏÔÒÅÂÏ×ÁÌÏÓØ ÂÏÌÅÅ ÞÅÍ 'max_binlog_cache_size' ÂÁÊÔ. õ×ÅÌÉÞØÔÅ ÜÔÕ ÐÅÒÅÍÅÎÎÕÀ ÓÅÒ×ÅÒÁ mysqld É ÐÏÐÒÏÂÕÊÔÅ ÅÝÅ ÒÁÚ"
+ spa "Multipla transición necesita mas que 'max_binlog_cache_size' bytes de almacenamiento. Aumente esta variable mysqld y tente de nuevo"
+ swe "Transaktionen krävde mera än 'max_binlog_cache_size' minne. Öka denna mysqld-variabel och försök på nytt"
+ ukr "ôÒÁÎÚÁËÃ¦Ñ Ú ÂÁÇÁÔØÍÁ ×ÉÒÁÚÁÍÉ ×ÉÍÁÇÁ¤ ¦ÌØÛÅ Î¦Ö 'max_binlog_cache_size' ÂÁÊÔ¦× ÄÌÑ ÚÂÅÒ¦ÇÁÎÎÑ. ú¦ÌØÛÔÅ ÃÀ ÚͦÎÎÕ mysqld ÔÁ ÓÐÒÏÂÕÊÔÅ ÚÎÏ×Õ"
+ER_SLAVE_MUST_STOP
+ dan "Denne handling kunne ikke udføres med kørende slave, brug først kommandoen STOP SLAVE"
+ nla "Deze operatie kan niet worden uitgevoerd met een actieve slave, doe eerst STOP SLAVE"
+ eng "This operation cannot be performed with a running slave; run STOP SLAVE first"
+ fre "Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord"
+ ger "Diese Operation kann nicht bei einem aktiven Slave durchgeführt werden. Bitte zuerst STOP SLAVE ausführen"
+ ita "Questa operazione non puo' essere eseguita con un database 'slave' che gira, lanciare prima STOP SLAVE"
+ por "Esta operação não pode ser realizada com um 'slave' em execução. Execute STOP SLAVE primeiro"
+ rus "üÔÕ ÏÐÅÒÁÃÉÀ ÎÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÐÒÉ ÒÁÂÏÔÁÀÝÅÍ ÐÏÔÏËÅ ÐÏÄÞÉÎÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ. óÎÁÞÁÌÁ ×ÙÐÏÌÎÉÔÅ STOP SLAVE"
+ serbian "Ova operacija ne može biti izvršena dok je aktivan podreðeni server. Zadajte prvo komandu 'STOP SLAVE' da zaustavite podreðeni server."
+ spa "Esta operación no puede ser hecha con el esclavo funcionando, primero use STOP SLAVE"
+ swe "Denna operation kan inte göras under replikering; Gör STOP SLAVE först"
+ ukr "ïÐÅÒÁÃ¦Ñ ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÎÁÎÁ Ú ÚÁÐÕÝÅÎÉÍ Ð¦ÄÌÅÇÌÉÍ, ÓÐÏÞÁÔËÕ ×ÉËÏÎÁÊÔÅ STOP SLAVE"
+ER_SLAVE_NOT_RUNNING
+ dan "Denne handling kræver en kørende slave. Konfigurer en slave og brug kommandoen START SLAVE"
+ nla "Deze operatie vereist een actieve slave, configureer slave en doe dan START SLAVE"
+ eng "This operation requires a running slave; configure slave and do START SLAVE"
+ fre "Cette opération nécessite un esclave actif, configurez les esclaves et faites START SLAVE"
+ ger "Diese Operation benötigt einen aktiven Slave. Bitte Slave konfigurieren und mittels START SLAVE aktivieren"
+ ita "Questa operaione richiede un database 'slave', configurarlo ed eseguire START SLAVE"
+ por "Esta operação requer um 'slave' em execução. Configure o 'slave' e execute START SLAVE"
+ rus "äÌÑ ÜÔÏÊ ÏÐÅÒÁÃÉÉ ÔÒÅÂÕÅÔÓÑ ÒÁÂÏÔÁÀÝÉÊ ÐÏÄÞÉÎÅÎÎÙÊ ÓÅÒ×ÅÒ. óÎÁÞÁÌÁ ×ÙÐÏÌÎÉÔÅ START SLAVE"
+ serbian "Ova operacija zahteva da je aktivan podreðeni server. Konfigurišite prvo podreðeni server i onda izvršite komandu 'START SLAVE'"
+ spa "Esta operación necesita el esclavo funcionando, configure esclavo y haga el START SLAVE"
+ swe "Denna operation kan endast göras under replikering; Konfigurera slaven och gör START SLAVE"
+ ukr "ïÐÅÒÁÃ¦Ñ ×ÉÍÁÇÁ¤ ÚÁÐÕÝÅÎÏÇÏ Ð¦ÄÌÅÇÌÏÇÏ, ÚËÏÎƦÇÕÒÕÊÔŠЦÄÌÅÇÌÏÇÏ ÔÁ ×ÉËÏÎÁÊÔÅ START SLAVE"
+ER_BAD_SLAVE
+ dan "Denne server er ikke konfigureret som slave. Ret in config-filen eller brug kommandoen CHANGE MASTER TO"
+ nla "De server is niet geconfigureerd als slave, fix in configuratie bestand of met CHANGE MASTER TO"
+ eng "The server is not configured as slave; fix in config file or with CHANGE MASTER TO"
+ fre "Le server n'est pas configuré comme un esclave, changez le fichier de configuration ou utilisez CHANGE MASTER TO"
+ ger "Der Server ist nicht als Slave konfiguriert. Bitte in der Konfigurationsdatei oder mittels CHANGE MASTER TO beheben"
+ ita "Il server non e' configurato come 'slave', correggere il file di configurazione cambiando CHANGE MASTER TO"
+ por "O servidor não está configurado como 'slave'. Acerte o arquivo de configuração ou use CHANGE MASTER TO"
+ rus "üÔÏÔ ÓÅÒ×ÅÒ ÎÅ ÎÁÓÔÒÏÅÎ ËÁË ÐÏÄÞÉÎÅÎÎÙÊ. ÷ÎÅÓÉÔÅ ÉÓÐÒÁ×ÌÅÎÉÑ × ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÍ ÆÁÊÌÅ ÉÌÉ Ó ÐÏÍÏÝØÀ CHANGE MASTER TO"
+ serbian "Server nije konfigurisan kao podreðeni server, ispravite konfiguracioni file ili na njemu izvršite komandu 'CHANGE MASTER TO'"
+ spa "El servidor no está configurado como esclavo, edite el archivo config file o con CHANGE MASTER TO"
+ swe "Servern är inte konfigurerade som en replikationsslav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO"
+ ukr "óÅÒ×ÅÒ ÎÅ ÚËÏÎƦÇÕÒÏ×ÁÎÏ ÑË Ð¦ÄÌÅÇÌÉÊ, ×ÉÐÒÁ×ÔÅ ÃÅ Õ ÆÁÊ̦ ËÏÎƦÇÕÒÁæ§ ÁÂÏ Ú CHANGE MASTER TO"
+ER_MASTER_INFO
+ eng "Could not initialize master info structure; more error messages can be found in the MySQL error log"
+ fre "Impossible d'initialiser les structures d'information de maître, vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MySQL"
+ serbian "Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info'"
+ swe "Kunde inte initialisera replikationsstrukturerna. See MySQL fel fil för mera information"
+ER_SLAVE_THREAD
+ dan "Kunne ikke danne en slave-tråd; check systemressourcerne"
+ nla "Kon slave thread niet aanmaken, controleer systeem resources"
+ eng "Could not create slave thread; check system resources"
+ fre "Impossible de créer une tâche esclave, vérifiez les ressources système"
+ ger "Konnte keinen Slave-Thread starten. Bitte System-Ressourcen überprüfen"
+ ita "Impossibile creare il thread 'slave', controllare le risorse di sistema"
+ por "Não conseguiu criar 'thread' de 'slave'. Verifique os recursos do sistema"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÐÏÔÏË ÐÏÄÞÉÎÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ. ðÒÏ×ÅÒØÔÅ ÓÉÓÔÅÍÎÙÅ ÒÅÓÕÒÓÙ"
+ serbian "Nisam mogao da startujem thread za podreðeni server, proverite sistemske resurse"
+ spa "No puedo crear el thread esclavo, verifique recursos del sistema"
+ swe "Kunde inte starta en tråd för replikering"
+ ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ Ð¦ÄÌÅÇÌÕ Ç¦ÌËÕ, ÐÅÒÅצÒÔÅ ÓÉÓÔÅÍΦ ÒÅÓÕÒÓÉ"
+ER_TOO_MANY_USER_CONNECTIONS 42000
+ dan "Brugeren %-.64s har allerede mere end 'max_user_connections' aktive forbindelser"
+ nla "Gebruiker %-.64s heeft reeds meer dan 'max_user_connections' actieve verbindingen"
+ eng "User %-.64s already has more than 'max_user_connections' active connections"
+ est "Kasutajal %-.64s on juba rohkem ühendusi kui lubatud 'max_user_connections' muutujaga"
+ fre "L'utilisateur %-.64s possède déjà plus de 'max_user_connections' connections actives"
+ ger "Benutzer '%-.64s' hat mehr als max_user_connections aktive Verbindungen"
+ ita "L'utente %-.64s ha gia' piu' di 'max_user_connections' connessioni attive"
+ por "Usuário '%-.64s' já possui mais que o valor máximo de conexões (max_user_connections) ativas"
+ rus "õ ÐÏÌØÚÏ×ÁÔÅÌÑ %-.64s ÕÖÅ ÂÏÌØÛÅ ÞÅÍ 'max_user_connections' ÁËÔÉ×ÎÙÈ ÓÏÅÄÉÎÅÎÉÊ"
+ serbian "Korisnik %-.64s veæ ima više aktivnih konekcija nego što je to odreðeno 'max_user_connections' promenljivom"
+ spa "Usario %-.64s ya tiene mas que 'max_user_connections' conexiones activas"
+ swe "Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar"
+ ukr "ëÏÒÉÓÔÕ×ÁÞ %-.64s ×ÖÅ ÍÁ¤ ¦ÌØÛÅ Î¦Ö 'max_user_connections' ÁËÔÉ×ÎÉÈ Ú'¤ÄÎÁÎØ"
+ER_SET_CONSTANTS_ONLY
+ dan "Du må kun bruge konstantudtryk med SET"
+ nla "U mag alleen constante expressies gebruiken bij SET"
+ eng "You may only use constant expressions with SET"
+ est "Ainult konstantsed suurused on lubatud SET klauslis"
+ fre "Seules les expressions constantes sont autorisées avec SET"
+ ger "Bei SET dürfen nur konstante Ausdrücke verwendet werden"
+ ita "Si possono usare solo espressioni costanti con SET"
+ por "Você pode usar apenas expressões constantes com SET"
+ rus "÷Ù ÍÏÖÅÔÅ ÉÓÐÏÌØÚÏ×ÁÔØ × SET ÔÏÌØËÏ ËÏÎÓÔÁÎÔÎÙÅ ×ÙÒÁÖÅÎÉÑ"
+ serbian "Možete upotrebiti samo konstantan iskaz sa komandom 'SET'"
+ spa "Tu solo debes usar expresiones constantes con SET"
+ swe "Man kan endast använda konstantuttryck med SET"
+ ukr "íÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÌÉÛÅ ×ÉÒÁÚÉ Ú¦ ÓÔÁÌÉÍÉ Õ SET"
+ER_LOCK_WAIT_TIMEOUT
+ dan "Lock wait timeout overskredet"
+ nla "Lock wacht tijd overschreden"
+ eng "Lock wait timeout exceeded; try restarting transaction"
+ est "Kontrollaeg ületatud luku järel ootamisel; Proovi transaktsiooni otsast alata"
+ fre "Timeout sur l'obtention du verrou"
+ ger "Beim Warten auf eine Sperre wurde die zulässige Wartezeit überschritten. Bitte versuchen Sie, die Transaktion neu zu starten"
+ ita "E' scaduto il timeout per l'attesa del lock"
+ por "Tempo de espera (timeout) de travamento excedido. Tente reiniciar a transação."
+ rus "ôÁÊÍÁÕÔ ÏÖÉÄÁÎÉÑ ÂÌÏËÉÒÏ×ËÉ ÉÓÔÅË; ÐÏÐÒÏÂÕÊÔÅ ÐÅÒÅÚÁÐÕÓÔÉÔØ ÔÒÁÎÚÁËÃÉÀ"
+ serbian "Vremenski limit za zakljuèavanje tabele je istekao; Probajte da ponovo startujete transakciju"
+ spa "Tiempo de bloqueo de espera excedido"
+ swe "Fick inte ett lås i tid ; Försök att starta om transaktionen"
+ ukr "úÁÔÒÉÍËÕ ÏÞ¦ËÕ×ÁÎÎÑ ÂÌÏËÕ×ÁÎÎÑ ×ÉÞÅÒÐÁÎÏ"
+ER_LOCK_TABLE_FULL
+ dan "Det totale antal låse overstiger størrelsen på låse-tabellen"
+ nla "Het totale aantal locks overschrijdt de lock tabel grootte"
+ eng "The total number of locks exceeds the lock table size"
+ est "Lukkude koguarv ületab lukutabeli suuruse"
+ fre "Le nombre total de verrou dépasse la taille de la table des verrous"
+ ger "Die Gesamtzahl der Sperren überschreitet die Größe der Sperrtabelle"
+ ita "Il numero totale di lock e' maggiore della grandezza della tabella di lock"
+ por "O número total de travamentos excede o tamanho da tabela de travamentos"
+ rus "ïÂÝÅÅ ËÏÌÉÞÅÓÔ×Ï ÂÌÏËÉÒÏ×ÏË ÐÒÅ×ÙÓÉÌÏ ÒÁÚÍÅÒÙ ÔÁÂÌÉÃÙ ÂÌÏËÉÒÏ×ÏË"
+ serbian "Broj totalnih zakljuèavanja tabele premašuje velièinu tabele zakljuèavanja"
+ spa "El número total de bloqueos excede el tamaño de bloqueo de la tabla"
+ swe "Antal lås överskrider antalet reserverade lås"
+ ukr "úÁÇÁÌØÎÁ ˦ÌØ˦ÓÔØ ÂÌÏËÕ×ÁÎØ ÐÅÒÅ×ÉÝÉÌÁ ÒÏÚÍ¦Ò ÂÌÏËÕ×ÁÎØ ÄÌÑ ÔÁÂÌÉæ"
+ER_READ_ONLY_TRANSACTION 25000
+ dan "Update lås kan ikke opnås under en READ UNCOMMITTED transaktion"
+ nla "Update locks kunnen niet worden verkregen tijdens een READ UNCOMMITTED transactie"
+ eng "Update locks cannot be acquired during a READ UNCOMMITTED transaction"
+ est "Uuenduslukke ei saa kasutada READ UNCOMMITTED transaktsiooni käigus"
+ fre "Un verrou en update ne peut être acquit pendant une transaction READ UNCOMMITTED"
+ ger "Während einer READ UNCOMMITED-Transaktion können keine UPDATE-Sperren angefordert werden"
+ ita "I lock di aggiornamento non possono essere acquisiti durante una transazione 'READ UNCOMMITTED'"
+ por "Travamentos de atualização não podem ser obtidos durante uma transação de tipo READ UNCOMMITTED"
+ rus "âÌÏËÉÒÏ×ËÉ ÏÂÎÏ×ÌÅÎÉÊ ÎÅÌØÚÑ ÐÏÌÕÞÉÔØ × ÐÒÏÃÅÓÓÅ ÞÔÅÎÉÑ ÎÅ ÐÒÉÎÑÔÏÊ (× ÒÅÖÉÍÅ READ UNCOMMITTED) ÔÒÁÎÚÁËÃÉÉ"
+ serbian "Zakljuèavanja izmena ne mogu biti realizovana sve dok traje 'READ UNCOMMITTED' transakcija"
+ spa "Bloqueos de actualización no pueden ser adqueridos durante una transición READ UNCOMMITTED"
+ swe "Updateringslås kan inte göras när man använder READ UNCOMMITTED"
+ ukr "ïÎÏ×ÉÔÉ ÂÌÏËÕ×ÁÎÎÑ ÎÅ ÍÏÖÌÉ×Ï ÎÁ ÐÒÏÔÑÚ¦ ÔÒÁÎÚÁËæ§ READ UNCOMMITTED"
+ER_DROP_DB_WITH_READ_LOCK
+ dan "DROP DATABASE er ikke tilladt mens en tråd holder på globalt read lock"
+ nla "DROP DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit"
+ eng "DROP DATABASE not allowed while thread is holding global read lock"
+ est "DROP DATABASE ei ole lubatud kui lõim omab globaalset READ lukku"
+ fre "DROP DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture"
+ ger "DROP DATABASE ist nicht erlaubt, solange der Thread eine globale Lesesperre hält"
+ ita "DROP DATABASE non e' permesso mentre il thread ha un lock globale di lettura"
+ por "DROP DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura"
+ rus "îÅ ÄÏÐÕÓËÁÅÔÓÑ DROP DATABASE, ÐÏËÁ ÐÏÔÏË ÄÅÒÖÉÔ ÇÌÏÂÁÌØÎÕÀ ÂÌÏËÉÒÏ×ËÕ ÞÔÅÎÉÑ"
+ serbian "Komanda 'DROP DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka"
+ spa "DROP DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global"
+ swe "DROP DATABASE är inte tillåtet när man har ett globalt läslås"
+ ukr "DROP DATABASE ÎÅ ÄÏÚ×ÏÌÅÎÏ ÄÏËÉ Ç¦ÌËÁ ÐÅÒÅÂÕ×Á¤ Ð¦Ä ÚÁÇÁÌØÎÉÍ ÂÌÏËÕ×ÁÎÎÑÍ ÞÉÔÁÎÎÑ"
+ER_CREATE_DB_WITH_READ_LOCK
+ dan "CREATE DATABASE er ikke tilladt mens en tråd holder på globalt read lock"
+ nla "CREATE DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit"
+ eng "CREATE DATABASE not allowed while thread is holding global read lock"
+ est "CREATE DATABASE ei ole lubatud kui lõim omab globaalset READ lukku"
+ fre "CREATE DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture"
+ ger "CREATE DATABASE ist nicht erlaubt, solange der Thread eine globale Lesesperre hält"
+ ita "CREATE DATABASE non e' permesso mentre il thread ha un lock globale di lettura"
+ por "CREATE DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura"
+ rus "îÅ ÄÏÐÕÓËÁÅÔÓÑ CREATE DATABASE, ÐÏËÁ ÐÏÔÏË ÄÅÒÖÉÔ ÇÌÏÂÁÌØÎÕÀ ÂÌÏËÉÒÏ×ËÕ ÞÔÅÎÉÑ"
+ serbian "Komanda 'CREATE DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka"
+ spa "CREATE DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global"
+ swe "CREATE DATABASE är inte tillåtet när man har ett globalt läslås"
+ ukr "CREATE DATABASE ÎÅ ÄÏÚ×ÏÌÅÎÏ ÄÏËÉ Ç¦ÌËÁ ÐÅÒÅÂÕ×Á¤ Ð¦Ä ÚÁÇÁÌØÎÉÍ ÂÌÏËÕ×ÁÎÎÑÍ ÞÉÔÁÎÎÑ"
+ER_WRONG_ARGUMENTS
+ nla "Foutieve parameters voor %s"
+ eng "Incorrect arguments to %s"
+ est "Vigased parameetrid %s-le"
+ fre "Mauvais arguments à %s"
+ ger "Falsche Argumente für %s"
+ ita "Argomenti errati a %s"
+ por "Argumentos errados para %s"
+ rus "îÅ×ÅÒÎÙÅ ÐÁÒÁÍÅÔÒÙ ÄÌÑ %s"
+ serbian "Pogrešni argumenti prosleðeni na %s"
+ spa "Argumentos errados para %s"
+ swe "Felaktiga argument till %s"
+ ukr "èÉÂÎÉÊ ÁÒÇÕÍÅÎÔ ÄÌÑ %s"
+ER_NO_PERMISSION_TO_CREATE_USER 42000
+ nla "'%-.32s'@'%-.64s' mag geen nieuwe gebruikers creeren"
+ eng "'%-.32s'@'%-.64s' is not allowed to create new users"
+ est "Kasutajal '%-.32s'@'%-.64s' ei ole lubatud luua uusi kasutajaid"
+ fre "'%-.32s'@'%-.64s' n'est pas autorisé à créer de nouveaux utilisateurs"
+ ger "'%-.32s'@'%-.64s' is nicht berechtigt, neue Benutzer hinzuzufügen"
+ ita "A '%-.32s'@'%-.64s' non e' permesso creare nuovi utenti"
+ por "Não é permitido a '%-.32s'@'%-.64s' criar novos usuários"
+ rus "'%-.32s'@'%-.64s' ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÓÏÚÄÁ×ÁÔØ ÎÏ×ÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ"
+ serbian "Korisniku '%-.32s'@'%-.64s' nije dozvoljeno da kreira nove korisnike"
+ spa "'%-.32s`@`%-.64s` no es permitido para crear nuevos usuarios"
+ swe "'%-.32s'@'%-.64s' har inte rättighet att skapa nya användare"
+ ukr "ëÏÒÉÓÔÕ×ÁÞÕ '%-.32s'@'%-.64s' ÎÅ ÄÏÚ×ÏÌÅÎÏ ÓÔ×ÏÒÀ×ÁÔÉ ÎÏ×ÉÈ ËÏÒÉÓÔÕ×ÁÞ¦×"
+ER_UNION_TABLES_IN_DIFFERENT_DIR
+ nla "Incorrecte tabel definitie; alle MERGE tabellen moeten tot dezelfde database behoren"
+ eng "Incorrect table definition; all MERGE tables must be in the same database"
+ est "Vigane tabelimääratlus; kõik MERGE tabeli liikmed peavad asuma samas andmebaasis"
+ fre "Définition de table incorrecte; toutes les tables MERGE doivent être dans la même base de donnée"
+ ger "Falsche Tabellendefinition. Alle MERGE-Tabellen müssen sich in derselben Datenbank befinden"
+ ita "Definizione della tabella errata; tutte le tabelle di tipo MERGE devono essere nello stesso database"
+ por "Definição incorreta da tabela. Todas as tabelas contidas na junção devem estar no mesmo banco de dados."
+ rus "îÅ×ÅÒÎÏÅ ÏÐÒÅÄÅÌÅÎÉÅ ÔÁÂÌÉÃÙ; ÷ÓÅ ÔÁÂÌÉÃÙ × MERGE ÄÏÌÖÎÙ ÐÒÉÎÁÄÌÅÖÁÔØ ÏÄÎÏÊ É ÔÏÊ ÖÅ ÂÁÚÅ ÄÁÎÎÙÈ"
+ serbian "Pogrešna definicija tabele; sve 'MERGE' tabele moraju biti u istoj bazi podataka"
+ spa "Incorrecta definición de la tabla; Todas las tablas MERGE deben estar en el mismo banco de datos"
+ swe "Felaktig tabelldefinition; alla tabeller i en MERGE-tabell måste vara i samma databas"
+ER_LOCK_DEADLOCK 40001
+ nla "Deadlock gevonden tijdens lock-aanvraag poging; Probeer herstart van de transactie"
+ eng "Deadlock found when trying to get lock; try restarting transaction"
+ est "Lukustamisel tekkis tupik (deadlock); alusta transaktsiooni otsast"
+ fre "Deadlock découvert en essayant d'obtenir les verrous : essayez de redémarrer la transaction"
+ ger "Beim Versuch, eine Sperre anzufordern, ist ein Deadlock aufgetreten. Versuchen Sie, die Transaktion erneut zu starten"
+ ita "Trovato deadlock durante il lock; Provare a far ripartire la transazione"
+ por "Encontrado um travamento fatal (deadlock) quando tentava obter uma trava. Tente reiniciar a transação."
+ rus "÷ÏÚÎÉËÌÁ ÔÕÐÉËÏ×ÁÑ ÓÉÔÕÁÃÉÑ × ÐÒÏÃÅÓÓÅ ÐÏÌÕÞÅÎÉÑ ÂÌÏËÉÒÏ×ËÉ; ðÏÐÒÏÂÕÊÔÅ ÐÅÒÅÚÁÐÕÓÔÉÔØ ÔÒÁÎÚÁËÃÉÀ"
+ serbian "Unakrsno zakljuèavanje pronaðeno kada sam pokušao da dobijem pravo na zakljuèavanje; Probajte da restartujete transakciju"
+ spa "Encontrado deadlock cuando tentando obtener el bloqueo; Tente recomenzar la transición"
+ swe "Fick 'DEADLOCK' vid låsförsök av block/rad. Försök att starta om transaktionen"
+ER_TABLE_CANT_HANDLE_FT
+ nla "Het gebruikte tabel type ondersteund geen FULLTEXT indexen"
+ eng "The used table type doesn't support FULLTEXT indexes"
+ est "Antud tabelitüüp ei toeta FULLTEXT indekseid"
+ fre "Le type de table utilisé ne supporte pas les index FULLTEXT"
+ ger "Der verwendete Tabellentyp unterstützt keine FULLTEXT-Indizes"
+ ita "La tabella usata non supporta gli indici FULLTEXT"
+ por "O tipo de tabela utilizado não suporta índices de texto completo (fulltext indexes)"
+ rus "éÓÐÏÌØÚÕÅÍÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÐÏÌÎÏÔÅËÓÔÏ×ÙÈ ÉÎÄÅËÓÏ×"
+ serbian "Upotrebljeni tip tabele ne podržava 'FULLTEXT' indekse"
+ spa "El tipo de tabla usada no soporta índices FULLTEXT"
+ swe "Tabelltypen har inte hantering av FULLTEXT-index"
+ ukr "÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ FULLTEXT ¦ÎÄÅËÓ¦×"
+ER_CANNOT_ADD_FOREIGN
+ nla "Kan foreign key beperking niet toevoegen"
+ eng "Cannot add foreign key constraint"
+ fre "Impossible d'ajouter des contraintes d'index externe"
+ ger "Fremdschlüssel-Beschränkung konnte nicht hinzugefügt werden"
+ ita "Impossibile aggiungere il vincolo di integrita' referenziale (foreign key constraint)"
+ por "Não pode acrescentar uma restrição de chave estrangeira"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÄÏÂÁ×ÉÔØ ÏÇÒÁÎÉÞÅÎÉÑ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ"
+ serbian "Ne mogu da dodam proveru spoljnog kljuèa"
+ spa "No puede adicionar clave extranjera constraint"
+ swe "Kan inte lägga till 'FOREIGN KEY constraint'"
+ER_NO_REFERENCED_ROW 23000
+ nla "Kan onderliggende rij niet toevoegen: foreign key beperking gefaald"
+ eng "Cannot add or update a child row: a foreign key constraint fails"
+ fre "Impossible d'ajouter un enregistrement fils : une constrainte externe l'empèche"
+ ger "Hinzufügen eines Kind-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl"
+ greek "Cannot add a child row: a foreign key constraint fails"
+ hun "Cannot add a child row: a foreign key constraint fails"
+ ita "Impossibile aggiungere la riga: un vincolo d'integrita' referenziale non e' soddisfatto"
+ norwegian-ny "Cannot add a child row: a foreign key constraint fails"
+ por "Não pode acrescentar uma linha filha: uma restrição de chave estrangeira falhou"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÄÏÂÁ×ÉÔØ ÉÌÉ ÏÂÎÏ×ÉÔØ ÄÏÞÅÒÎÀÀ ÓÔÒÏËÕ: ÐÒÏ×ÅÒËÁ ÏÇÒÁÎÉÞÅÎÉÊ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ ÎÅ ×ÙÐÏÌÎÑÅÔÓÑ"
+ spa "No puede adicionar una línea hijo: falla de clave extranjera constraint"
+ swe "FOREIGN KEY-konflikt: Kan inte skriva barn"
+ER_ROW_IS_REFERENCED 23000
+ eng "Cannot delete or update a parent row: a foreign key constraint fails"
+ fre "Impossible de supprimer un enregistrement père : une constrainte externe l'empèche"
+ ger "Löschen eines Eltern-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl"
+ greek "Cannot delete a parent row: a foreign key constraint fails"
+ hun "Cannot delete a parent row: a foreign key constraint fails"
+ ita "Impossibile cancellare la riga: un vincolo d'integrita' referenziale non e' soddisfatto"
+ por "Não pode apagar uma linha pai: uma restrição de chave estrangeira falhou"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÉÌÉ ÏÂÎÏ×ÉÔØ ÒÏÄÉÔÅÌØÓËÕÀ ÓÔÒÏËÕ: ÐÒÏ×ÅÒËÁ ÏÇÒÁÎÉÞÅÎÉÊ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ ÎÅ ×ÙÐÏÌÎÑÅÔÓÑ"
+ serbian "Ne mogu da izbrišem roditeljski slog: provera spoljnog kljuèa je neuspela"
+ spa "No puede deletar una línea padre: falla de clave extranjera constraint"
+ swe "FOREIGN KEY-konflikt: Kan inte radera fader"
+ER_CONNECT_TO_MASTER 08S01
+ nla "Fout bij opbouwen verbinding naar master: %-.128s"
+ eng "Error connecting to master: %-.128s"
+ ger "Fehler bei der Verbindung zum Master: %-.128s"
+ ita "Errore durante la connessione al master: %-.128s"
+ por "Erro conectando com o master: %-.128s"
+ rus "ïÛÉÂËÁ ÓÏÅÄÉÎÅÎÉÑ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ: %-.128s"
+ spa "Error de coneccion a master: %-.128s"
+ swe "Fick fel vid anslutning till master: %-.128s"
+ER_QUERY_ON_MASTER
+ nla "Fout bij uitvoeren query op master: %-.128s"
+ eng "Error running query on master: %-.128s"
+ ger "Beim Ausführen einer Abfrage auf dem Master trat ein Fehler auf: %-.128s"
+ ita "Errore eseguendo una query sul master: %-.128s"
+ por "Erro rodando consulta no master: %-.128s"
+ rus "ïÛÉÂËÁ ×ÙÐÏÌÎÅÎÉÑ ÚÁÐÒÏÓÁ ÎÁ ÇÏÌÏ×ÎÏÍ ÓÅÒ×ÅÒÅ: %-.128s"
+ spa "Error executando el query en master: %-.128s"
+ swe "Fick fel vid utförande av command på mastern: %-.128s"
+ER_ERROR_WHEN_EXECUTING_COMMAND
+ nla "Fout tijdens uitvoeren van commando %s: %-.128s"
+ eng "Error when executing command %s: %-.128s"
+ est "Viga käsu %s täitmisel: %-.128s"
+ ger "Fehler beim Ausführen des Befehls %s: %-.128s"
+ ita "Errore durante l'esecuzione del comando %s: %-.128s"
+ por "Erro quando executando comando %s: %-.128s"
+ rus "ïÛÉÂËÁ ÐÒÉ ×ÙÐÏÌÎÅÎÉÉ ËÏÍÁÎÄÙ %s: %-.128s"
+ serbian "Greška pri izvršavanju komande %s: %-.128s"
+ spa "Error de %s: %-.128s"
+ swe "Fick fel vid utförande av %s: %-.128s"
+ER_WRONG_USAGE
+ nla "Foutief gebruik van %s en %s"
+ eng "Incorrect usage of %s and %s"
+ est "Vigane %s ja %s kasutus"
+ ger "Falsche Verwendung von %s und %s"
+ ita "Uso errato di %s e %s"
+ por "Uso errado de %s e %s"
+ rus "îÅ×ÅÒÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ %s É %s"
+ serbian "Pogrešna upotreba %s i %s"
+ spa "Equivocado uso de %s y %s"
+ swe "Felaktig använding av %s and %s"
+ ukr "Wrong usage of %s and %s"
+ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 21000
+ nla "De gebruikte SELECT commando's hebben een verschillend aantal kolommen"
+ eng "The used SELECT statements have a different number of columns"
+ est "Tulpade arv kasutatud SELECT lausetes ei kattu"
+ ger "Die verwendeten SELECT-Befehle liefern eine unterschiedliche Anzahl von Spalten zurück"
+ ita "La SELECT utilizzata ha un numero di colonne differente"
+ por "Os comandos SELECT usados têm diferente número de colunas"
+ rus "éÓÐÏÌØÚÏ×ÁÎÎÙÅ ÏÐÅÒÁÔÏÒÙ ×ÙÂÏÒËÉ (SELECT) ÄÁÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×"
+ serbian "Upotrebljene 'SELECT' komande adresiraju razlièit broj kolona"
+ spa "El comando SELECT usado tiene diferente número de columnas"
+ swe "SELECT-kommandona har olika antal kolumner"
+ER_CANT_UPDATE_WITH_READLOCK
+ nla "Kan de query niet uitvoeren vanwege een conflicterende read lock"
+ eng "Can't execute the query because you have a conflicting read lock"
+ est "Ei suuda täita päringut konfliktse luku tõttu"
+ ger "Augrund eines READ LOCK-Konflikts kann die Abfrage nicht ausgeführt werden"
+ ita "Impossibile eseguire la query perche' c'e' un conflitto con in lock di lettura"
+ por "Não posso executar a consulta porque você tem um conflito de travamento de leitura"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÉÓÐÏÌÎÉÔØ ÚÁÐÒÏÓ, ÐÏÓËÏÌØËÕ Õ ×ÁÓ ÕÓÔÁÎÏ×ÌÅÎÙ ËÏÎÆÌÉËÔÕÀÝÉÅ ÂÌÏËÉÒÏ×ËÉ ÞÔÅÎÉÑ"
+ serbian "Ne mogu da izvršim upit zbog toga što imate zakljuèavanja èitanja podataka u konfliktu"
+ spa "No puedo ejecutar el query porque usted tiene conflicto de traba de lectura"
+ swe "Kan inte utföra kommandot emedan du har ett READ-lås"
+ER_MIXING_NOT_ALLOWED
+ nla "Het combineren van transactionele en niet-transactionele tabellen is uitgeschakeld."
+ eng "Mixing of transactional and non-transactional tables is disabled"
+ est "Transaktsioone toetavate ning mittetoetavate tabelite kooskasutamine ei ole lubatud"
+ ger "Die gleichzeitige Verwendung von Tabellen mit und ohne Transaktionsunterstützung ist deaktiviert"
+ ita "E' disabilitata la possibilita' di mischiare tabelle transazionali e non-transazionali"
+ por "Mistura de tabelas transacional e não-transacional está desabilitada"
+ rus "éÓÐÏÌØÚÏ×ÁÎÉÅ ÔÒÁÎÚÁËÃÉÏÎÎÙÈ ÔÁÂÌÉà ÎÁÒÑÄÕ Ó ÎÅÔÒÁÎÚÁËÃÉÏÎÎÙÍÉ ÚÁÐÒÅÝÅÎÏ"
+ serbian "Mešanje tabela koje podržavaju transakcije i onih koje ne podržavaju transakcije je iskljuèeno"
+ spa "Mezla de transancional y no-transancional tablas está deshabilitada"
+ swe "Blandning av transaktionella och icke-transaktionella tabeller är inaktiverat"
+ER_DUP_ARGUMENT
+ nla "Optie '%s' tweemaal gebruikt in opdracht"
+ eng "Option '%s' used twice in statement"
+ est "Määrangut '%s' on lauses kasutatud topelt"
+ ger "Option '%s' wird im Befehl zweimal verwendet"
+ ita "L'opzione '%s' e' stata usata due volte nel comando"
+ por "Opção '%s' usada duas vezes no comando"
+ rus "ïÐÃÉÑ '%s' Ä×ÁÖÄÙ ÉÓÐÏÌØÚÏ×ÁÎÁ × ×ÙÒÁÖÅÎÉÉ"
+ spa "Opción '%s' usada dos veces en el comando"
+ swe "Option '%s' användes två gånger"
+ER_USER_LIMIT_REACHED 42000
+ nla "Gebruiker '%-.64s' heeft het maximale gebruik van de '%s' faciliteit overschreden (huidige waarde: %ld)"
+ eng "User '%-.64s' has exceeded the '%s' resource (current value: %ld)"
+ ger "Benutzer '%-.64s' hat die Ressourcenbeschränkung '%s' überschritten (aktueller Wert: %ld)"
+ ita "L'utente '%-.64s' ha ecceduto la risorsa '%s' (valore corrente: %ld)"
+ por "Usuário '%-.64s' tem excedido o '%s' recurso (atual valor: %ld)"
+ rus "ðÏÌØÚÏ×ÁÔÅÌØ '%-.64s' ÐÒÅ×ÙÓÉÌ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÒÅÓÕÒÓÁ '%s' (ÔÅËÕÝÅÅ ÚÎÁÞÅÎÉÅ: %ld)"
+ spa "Usuario '%-.64s' ha excedido el recurso '%s' (actual valor: %ld)"
+ swe "Användare '%-.64s' har överskridit '%s' (nuvarande värde: %ld)"
+ER_SPECIFIC_ACCESS_DENIED_ERROR 42000
+ nla "Toegang geweigerd. U moet het %-.128s privilege hebben voor deze operatie"
+ eng "Access denied; you need the %-.128s privilege for this operation"
+ ger "Befehl nicht zulässig. Hierfür wird die Berechtigung %-.128s benötigt"
+ ita "Accesso non consentito. Serve il privilegio %-.128s per questa operazione"
+ por "Acesso negado. Você precisa o privilégio %-.128s para essa operação"
+ rus "÷ ÄÏÓÔÕÐÅ ÏÔËÁÚÁÎÏ. ÷ÁÍ ÎÕÖÎÙ ÐÒÉ×ÉÌÅÇÉÉ %-.128s ÄÌÑ ÜÔÏÊ ÏÐÅÒÁÃÉÉ"
+ spa "Acceso negado. Usted necesita el privilegio %-.128s para esta operación"
+ swe "Du har inte privlegiet '%-.128s' som behövs för denna operation"
+ ukr "Access denied. You need the %-.128s privilege for this operation"
+ER_LOCAL_VARIABLE
+ nla "Variabele '%-.64s' is SESSION en kan niet worden gebruikt met SET GLOBAL"
+ eng "Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL"
+ ger "Variable '%-.64s' ist eine lokale Variable und kann nicht mit SET GLOBAL verändert werden"
+ ita "La variabile '%-.64s' e' una variabile locale ( SESSION ) e non puo' essere cambiata usando SET GLOBAL"
+ por "Variável '%-.64s' é uma SESSION variável e não pode ser usada com SET GLOBAL"
+ rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÐÏÔÏËÏ×ÏÊ (SESSION) ÐÅÒÅÍÅÎÎÏÊ É ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÁ Ó ÐÏÍÏÝØÀ SET GLOBAL"
+ spa "Variable '%-.64s' es una SESSION variable y no puede ser usada con SET GLOBAL"
+ swe "Variabel '%-.64s' är en SESSION variabel och kan inte ändrad med SET GLOBAL"
+ER_GLOBAL_VARIABLE
+ nla "Variabele '%-.64s' is GLOBAL en dient te worden gewijzigd met SET GLOBAL"
+ eng "Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL"
+ ger "Variable '%-.64s' ist eine globale Variable und muss mit SET GLOBAL verändert werden"
+ ita "La variabile '%-.64s' e' una variabile globale ( GLOBAL ) e deve essere cambiata usando SET GLOBAL"
+ por "Variável '%-.64s' é uma GLOBAL variável e deve ser configurada com SET GLOBAL"
+ rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÇÌÏÂÁÌØÎÏÊ (GLOBAL) ÐÅÒÅÍÅÎÎÏÊ, É ÅÅ ÓÌÅÄÕÅÔ ÉÚÍÅÎÑÔØ Ó ÐÏÍÏÝØÀ SET GLOBAL"
+ spa "Variable '%-.64s' es una GLOBAL variable y no puede ser configurada con SET GLOBAL"
+ swe "Variabel '%-.64s' är en GLOBAL variabel och bör sättas med SET GLOBAL"
+ER_NO_DEFAULT 42000
+ nla "Variabele '%-.64s' heeft geen standaard waarde"
+ eng "Variable '%-.64s' doesn't have a default value"
+ ger "Variable '%-.64s' hat keinen Vorgabewert"
+ ita "La variabile '%-.64s' non ha un valore di default"
+ por "Variável '%-.64s' não tem um valor padrão"
+ rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÎÅ ÉÍÅÅÔ ÚÎÁÞÅÎÉÑ ÐÏ ÕÍÏÌÞÁÎÉÀ"
+ spa "Variable '%-.64s' no tiene un valor patrón"
+ swe "Variabel '%-.64s' har inte ett DEFAULT-värde"
+ER_WRONG_VALUE_FOR_VAR 42000
+ nla "Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.64s'"
+ eng "Variable '%-.64s' can't be set to the value of '%-.64s'"
+ ger "Variable '%-.64s' kann nicht auf '%-.64s' gesetzt werden"
+ ita "Alla variabile '%-.64s' non puo' essere assegato il valore '%-.64s'"
+ por "Variável '%-.64s' não pode ser configurada para o valor de '%-.64s'"
+ rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÕÓÔÁÎÏ×ÌÅÎÁ × ÚÎÁÞÅÎÉÅ '%-.64s'"
+ spa "Variable '%-.64s' no puede ser configurada para el valor de '%-.64s'"
+ swe "Variabel '%-.64s' kan inte sättas till '%-.64s'"
+ER_WRONG_TYPE_FOR_VAR 42000
+ nla "Foutief argumenttype voor variabele '%-.64s'"
+ eng "Incorrect argument type to variable '%-.64s'"
+ ger "Falscher Argumenttyp für Variable '%-.64s'"
+ ita "Tipo di valore errato per la variabile '%-.64s'"
+ por "Tipo errado de argumento para variável '%-.64s'"
+ rus "îÅ×ÅÒÎÙÊ ÔÉÐ ÁÒÇÕÍÅÎÔÁ ÄÌÑ ÐÅÒÅÍÅÎÎÏÊ '%-.64s'"
+ spa "Tipo de argumento equivocado para variable '%-.64s'"
+ swe "Fel typ av argument till variabel '%-.64s'"
+ER_VAR_CANT_BE_READ
+ nla "Variabele '%-.64s' kan alleen worden gewijzigd, niet gelezen"
+ eng "Variable '%-.64s' can only be set, not read"
+ ger "Variable '%-.64s' kann nur verändert, nicht gelesen werden"
+ ita "Alla variabile '%-.64s' e' di sola scrittura quindi puo' essere solo assegnato un valore, non letto"
+ por "Variável '%-.64s' somente pode ser configurada, não lida"
+ rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÍÏÖÅÔ ÂÙÔØ ÔÏÌØËÏ ÕÓÔÁÎÏ×ÌÅÎÁ, ÎÏ ÎÅ ÓÞÉÔÁÎÁ"
+ spa "Variable '%-.64s' solamente puede ser configurada, no leída"
+ swe "Variabeln '%-.64s' kan endast sättas, inte läsas"
+ER_CANT_USE_OPTION_HERE 42000
+ nla "Foutieve toepassing/plaatsing van '%s'"
+ eng "Incorrect usage/placement of '%s'"
+ ger "Falsche Verwendung oder Platzierung von '%s'"
+ ita "Uso/posizione di '%s' sbagliato"
+ por "Errado uso/colocação de '%s'"
+ rus "îÅ×ÅÒÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÉÌÉ × ÎÅ×ÅÒÎÏÍ ÍÅÓÔÅ ÕËÁÚÁÎ '%s'"
+ spa "Equivocado uso/colocación de '%s'"
+ swe "Fel använding/placering av '%s'"
+ER_NOT_SUPPORTED_YET 42000
+ nla "Deze versie van MySQL ondersteunt nog geen '%s'"
+ eng "This version of MySQL doesn't yet support '%s'"
+ ger "Diese MySQL-Version unterstützt '%s' nicht"
+ ita "Questa versione di MySQL non supporta ancora '%s'"
+ por "Esta versão de MySQL não suporta ainda '%s'"
+ rus "üÔÁ ×ÅÒÓÉÑ MySQL ÐÏËÁ ÅÝÅ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ '%s'"
+ spa "Esta versión de MySQL no soporta todavia '%s'"
+ swe "Denna version av MySQL kan ännu inte utföra '%s'"
+ER_MASTER_FATAL_ERROR_READING_BINLOG
+ nla "Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log"
+ eng "Got fatal error %d: '%-.128s' from master when reading data from binary log"
+ ger "Schwerer Fehler %d: '%-.128s vom Master beim Lesen des binären Logs aufgetreten"
+ ita "Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario"
+ por "Obteve fatal erro %d: '%-.128s' do master quando lendo dados do binary log"
+ rus "ðÏÌÕÞÅÎÁ ÎÅÉÓÐÒÁ×ÉÍÁÑ ÏÛÉÂËÁ %d: '%-.128s' ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ × ÐÒÏÃÅÓÓÅ ×ÙÂÏÒËÉ ÄÁÎÎÙÈ ÉÚ Ä×ÏÉÞÎÏÇÏ ÖÕÒÎÁÌÁ"
+ spa "Recibió fatal error %d: '%-.128s' del master cuando leyendo datos del binary log"
+ swe "Fick fatalt fel %d: '%-.128s' från master vid läsning av binärloggen"
+ER_SLAVE_IGNORED_TABLE
+ eng "Slave SQL thread ignored the query because of replicate-*-table rules"
+ ger "Slave-SQL-Thread hat die Abfrage aufgrund von replicate-*-table-Regeln ignoriert"
+ por "Slave SQL thread ignorado a consulta devido às normas de replicação-*-tabela"
+ spa "Slave SQL thread ignorado el query debido a las reglas de replicación-*-tabla"
+ swe "Slav SQL tråden ignorerade frågan pga en replicate-*-table regel"
+ER_INCORRECT_GLOBAL_LOCAL_VAR
+ eng "Variable '%-.64s' is a %s variable"
+ serbian "Incorrect foreign key definition for '%-.64s': %s"
+ spa "Variable '%-.64s' es una %s variable"
+ swe "Variabel '%-.64s' är av typ %s"
+ER_WRONG_FK_DEF 42000
+ eng "Incorrect foreign key definition for '%-.64s': %s"
+ ger "Falsche Fremdschlüssel-Definition für '%-64s': %s"
+ por "Definição errada da chave estrangeira para '%-.64s': %s"
+ spa "Equivocada definición de llave extranjera para '%-.64s': %s"
+ swe "Felaktig FOREIGN KEY-definition för '%-.64s': %s"
+ER_KEY_REF_DO_NOT_MATCH_TABLE_REF
+ eng "Key reference and table reference don't match"
+ ger "Schlüssel- und Tabellenverweis passen nicht zusammen"
+ por "Referência da chave e referência da tabela não coincidem"
+ spa "Referencia de llave y referencia de tabla no coinciden"
+ swe "Nyckelreferensen och tabellreferensen stämmer inte överens"
+ER_OPERAND_COLUMNS 21000
+ eng "Operand should contain %d column(s)"
+ ger "Operand solle %d Spalte(n) enthalten"
+ rus "ïÐÅÒÁÎÄ ÄÏÌÖÅÎ ÓÏÄÅÒÖÁÔØ %d ËÏÌÏÎÏË"
+ spa "Operando debe tener %d columna(s)"
+ ukr "ïÐÅÒÁÎÄ ÍÁ¤ ÓËÌÁÄÁÔÉÓÑ Ú %d ÓÔÏ×Âæ×"
+ER_SUBQUERY_NO_1_ROW 21000
+ eng "Subquery returns more than 1 row"
+ ger "Unterabfrage lieferte mehr als einen Datensatz zurück"
+ por "Subconsulta retorna mais que 1 registro"
+ rus "ðÏÄÚÁÐÒÏÓ ×ÏÚ×ÒÁÝÁÅÔ ÂÏÌÅÅ ÏÄÎÏÊ ÚÁÐÉÓÉ"
+ spa "Subconsulta retorna mas que 1 línea"
+ swe "Subquery returnerade mer än 1 rad"
+ ukr "ð¦ÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ ¦ÌØÛ ÎiÖ 1 ÚÁÐÉÓ"
+ER_UNKNOWN_STMT_HANDLER
+ dan "Unknown prepared statement handler (%.*s) given to %s"
+ eng "Unknown prepared statement handler (%.*s) given to %s"
+ ger "Unbekannter Prepared-Statement-Handler (%.*s) für %s angegeben"
+ por "Desconhecido manipulador de declaração preparado (%.*s) determinado para %s"
+ spa "Desconocido preparado comando handler (%.*s) dado para %s"
+ swe "Okänd PREPARED STATEMENT id (%.*s) var given till %s"
+ ukr "Unknown prepared statement handler (%.*s) given to %s"
+ER_CORRUPT_HELP_DB
+ eng "Help database is corrupt or does not exist"
+ ger "Die Hilfe-Datenbank ist beschädigt oder existiert nicht"
+ por "Banco de dado de ajuda corrupto ou não existente"
+ spa "Base de datos Help está corrupto o no existe"
+ swe "Hjälpdatabasen finns inte eller är skadad"
+ER_CYCLIC_REFERENCE
+ eng "Cyclic reference on subqueries"
+ ger "Zyklischer Verweis in Unterabfragen"
+ por "Referência cíclica em subconsultas"
+ rus "ãÉËÌÉÞÅÓËÁÑ ÓÓÙÌËÁ ÎÁ ÐÏÄÚÁÐÒÏÓ"
+ spa "Cíclica referencia en subconsultas"
+ swe "Cyklisk referens i subqueries"
+ ukr "ãÉË̦ÞÎÅ ÐÏÓÉÌÁÎÎÑ ÎÁ ЦÄÚÁÐÉÔ"
+ER_AUTO_CONVERT
+ eng "Converting column '%s' from %s to %s"
+ ger "Spalte '%s' wird von %s nach %s umgewandelt"
+ por "Convertendo coluna '%s' de %s para %s"
+ rus "ðÒÅÏÂÒÁÚÏ×ÁÎÉÅ ÐÏÌÑ '%s' ÉÚ %s × %s"
+ spa "Convirtiendo columna '%s' de %s para %s"
+ swe "Konvertar kolumn '%s' från %s till %s"
+ ukr "ðÅÒÅÔ×ÏÒÅÎÎÑ ÓÔÏ×ÂÃÁ '%s' Ú %s Õ %s"
+ER_ILLEGAL_REFERENCE 42S22
+ eng "Reference '%-.64s' not supported (%s)"
+ ger "Verweis '%-.64s' wird nicht unterstützt (%s)"
+ por "Referência '%-.64s' não suportada (%s)"
+ rus "óÓÙÌËÁ '%-.64s' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ (%s)"
+ spa "Referencia '%-.64s' no soportada (%s)"
+ swe "Referens '%-.64s' stöds inte (%s)"
+ ukr "ðÏÓÉÌÁÎÎÑ '%-.64s' ÎÅ ÐiÄÔÒÉÍÕÅÔÓÑ (%s)"
+ER_DERIVED_MUST_HAVE_ALIAS 42000
+ eng "Every derived table must have its own alias"
+ ger "Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden"
+ por "Cada tabela derivada deve ter seu próprio alias"
+ spa "Cada tabla derivada debe tener su propio alias"
+ swe "Varje 'derived table' måste ha sitt eget alias"
+ER_SELECT_REDUCED 01000
+ eng "Select %u was reduced during optimization"
+ ger "Select %u wurde während der Optimierung reduziert"
+ por "Select %u foi reduzido durante otimização"
+ rus "Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ"
+ spa "Select %u fué reducido durante optimización"
+ swe "Select %u reducerades vid optimiering"
+ ukr "Select %u was ÓËÁÓÏ×ÁÎÏ ÐÒÉ ÏÐÔÉÍiÚÁÃii"
+ER_TABLENAME_NOT_ALLOWED_HERE 42000
+ eng "Table '%-.64s' from one of the SELECTs cannot be used in %-.32s"
+ ger "Tabelle '%-.64s', die in einem der SELECT-Befehle verwendet wurde, kann nicht in %-.32s verwendet werden"
+ por "Tabela '%-.64s' de um dos SELECTs não pode ser usada em %-.32s"
+ spa "Tabla '%-.64s' de uno de los SELECT no puede ser usada en %-.32s"
+ swe "Tabell '%-.64s' från en SELECT kan inte användas i %-.32s"
+ER_NOT_SUPPORTED_AUTH_MODE 08004
+ eng "Client does not support authentication protocol requested by server; consider upgrading MySQL client"
+ ger "Client unterstützt das vom Server erwartete Authentifizierungsprotokoll nicht. Bitte aktualisieren Sie Ihren MySQL-Client"
+ por "Cliente não suporta o protocolo de autenticação exigido pelo servidor; considere a atualização do cliente MySQL"
+ spa "Cliente no soporta protocolo de autenticación solicitado por el servidor; considere actualizar el cliente MySQL"
+ swe "Klienten stöder inte autentiseringsprotokollet som begärts av servern; överväg uppgradering av klientprogrammet."
+ER_SPATIAL_CANT_HAVE_NULL 42000
+ eng "All parts of a SPATIAL index must be NOT NULL"
+ ger "Alle Teile eines SPATIAL index müssen als NOT NULL deklariert sein"
+ por "Todas as partes de uma SPATIAL index devem ser NOT NULL"
+ spa "Todas las partes de una SPATIAL index deben ser NOT NULL"
+ swe "Alla delar av en SPATIAL index måste vara NOT NULL"
+ER_COLLATION_CHARSET_MISMATCH 42000
+ eng "COLLATION '%s' is not valid for CHARACTER SET '%s'"
+ ger "COLLATION '%s' ist für CHARACTER SET '%s' ungültig"
+ por "COLLATION '%s' não é válida para CHARACTER SET '%s'"
+ spa "COLLATION '%s' no es válido para CHARACTER SET '%s'"
+ swe "COLLATION '%s' är inte tillåtet för CHARACTER SET '%s'"
+ER_SLAVE_WAS_RUNNING
+ eng "Slave is already running"
+ ger "Slave läuft bereits"
+ por "O slave já está rodando"
+ spa "Slave ya está funcionando"
+ swe "Slaven har redan startat"
+ER_SLAVE_WAS_NOT_RUNNING
+ eng "Slave already has been stopped"
+ ger "Slave wurde bereits angehalten"
+ por "O slave já está parado"
+ spa "Slave ya fué parado"
+ swe "Slaven har redan stoppat"
+ER_TOO_BIG_FOR_UNCOMPRESS
+ eng "Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)"
+ ger "Unkomprimierte Daten sind zu groß. Die maximale Größe beträgt %d"
+ por "Tamanho muito grande dos dados des comprimidos. O máximo tamanho é %d. (provavelmente, o comprimento dos dados descomprimidos está corrupto)"
+ spa "Tamaño demasiado grande para datos descomprimidos. El máximo tamaño es %d. (probablemente, extensión de datos descomprimidos fué corrompida)"
+ER_ZLIB_Z_MEM_ERROR
+ eng "ZLIB: Not enough memory"
+ ger "ZLIB: Steht nicht genug Speicher zur Verfügung"
+ por "ZLIB: Não suficiente memória disponível"
+ spa "Z_MEM_ERROR: No suficiente memoria para zlib"
+ER_ZLIB_Z_BUF_ERROR
+ eng "ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)"
+ ger "ZLIB: Im Ausgabepuffer ist nicht genug Platz vorhanden (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)"
+ por "ZLIB: Não suficiente espaço no buffer emissor (provavelmente, o comprimento dos dados descomprimidos está corrupto)"
+ spa "Z_BUF_ERROR: No suficiente espacio en el búfer de salida para zlib (probablemente, extensión de datos descomprimidos fué corrompida)"
+ER_ZLIB_Z_DATA_ERROR
+ eng "ZLIB: Input data corrupted"
+ ger "ZLIB: Eingabedaten beschädigt"
+ por "ZLIB: Dados de entrada está corrupto"
+ spa "ZLIB: Dato de entrada fué corrompido para zlib"
+ER_CUT_VALUE_GROUP_CONCAT
+ eng "%d line(s) were cut by GROUP_CONCAT()"
+ ger "%d Zeile(n) durch GROUP_CONCAT() abgeschnitten"
+ por "%d linha(s) foram cortada(s) por GROUP_CONCAT()"
+ spa "%d línea(s) fue(fueron) cortadas por group_concat()"
+ swe "%d rad(er) kapades av group_concat()"
+ ukr "%d line(s) was(were) cut by group_concat()"
+ER_WARN_TOO_FEW_RECORDS 01000
+ eng "Row %ld doesn't contain data for all columns"
+ ger "Anzahl der Datensätze in Zeile %ld geringer als Anzahl der Spalten"
+ por "Conta de registro é menor que a conta de coluna na linha %ld"
+ spa "Línea %ld no contiene datos para todas las columnas"
+ER_WARN_TOO_MANY_RECORDS 01000
+ eng "Row %ld was truncated; it contained more data than there were input columns"
+ ger "Anzahl der Datensätze in Zeile %ld größer als Anzahl der Spalten"
+ por "Conta de registro é maior que a conta de coluna na linha %ld"
+ spa "Línea %ld fué truncada; La misma contine mas datos que las que existen en las columnas de entrada"
+ER_WARN_NULL_TO_NOTNULL 22004
+ eng "Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld"
+ ger "Daten abgeschnitten, NULL für NOT NULL-Spalte '%s' in Zeile %ld angegeben"
+ por "Dado truncado, NULL fornecido para NOT NULL coluna '%s' na linha %ld"
+ spa "Datos truncado, NULL suministrado para NOT NULL columna '%s' en la línea %ld"
+ER_WARN_DATA_OUT_OF_RANGE 22003
+ eng "Out of range value adjusted for column '%s' at row %ld"
+ ger "Daten abgeschnitten, außerhalb des Wertebereichs für Spalte '%s' in Zeile %ld"
+ por "Dado truncado, fora de alcance para coluna '%s' na linha %ld"
+ spa "Datos truncados, fuera de gama para columna '%s' en la línea %ld"
+WARN_DATA_TRUNCATED 01000
+ eng "Data truncated for column '%s' at row %ld"
+ ger "Daten abgeschnitten für Spalte '%s' in Zeile %ld"
+ por "Dado truncado para coluna '%s' na linha %ld"
+ spa "Datos truncados para columna '%s' en la línea %ld"
+ER_WARN_USING_OTHER_HANDLER
+ eng "Using storage engine %s for table '%s'"
+ ger "Für Tabelle '%s' wird Speicher-Engine %s benutzt"
+ por "Usando engine de armazenamento %s para tabela '%s'"
+ spa "Usando motor de almacenamiento %s para tabla '%s'"
+ swe "Använder handler %s för tabell '%s'"
+ER_CANT_AGGREGATE_2COLLATIONS
+ eng "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'"
+ ger "Unerlaubte Vermischung der Kollationen (%s,%s) und (%s,%s) für die Operation '%s'"
+ por "Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'"
+ spa "Ilegal mezcla de collations (%s,%s) y (%s,%s) para operación '%s'"
+ER_DROP_USER
+ eng "Cannot drop one or more of the requested users"
+ ger "Kann einen oder mehrere der angegebenen Benutzer nicht löschen"
+ER_REVOKE_GRANTS
+ eng "Can't revoke all privileges, grant for one or more of the requested users"
+ ger "Kann nicht alle Berechtigungen widerrufen, grant for one or more of the requested users"
+ por "Não pode revocar todos os privilégios, grant para um ou mais dos usuários pedidos"
+ spa "No puede revocar todos los privilegios, derecho para uno o mas de los usuarios solicitados"
+ER_CANT_AGGREGATE_3COLLATIONS
+ eng "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'"
+ ger "Unerlaubte Vermischung der Kollationen (%s,%s), (%s,%s), (%s,%s) für die Operation '%s'"
+ por "Ilegal combinação de collations (%s,%s), (%s,%s), (%s,%s) para operação '%s'"
+ spa "Ilegal mezcla de collations (%s,%s), (%s,%s), (%s,%s) para operación '%s'"
+ER_CANT_AGGREGATE_NCOLLATIONS
+ eng "Illegal mix of collations for operation '%s'"
+ ger "Unerlaubte Vermischung der Kollationen für die Operation '%s'"
+ por "Ilegal combinação de collations para operação '%s'"
+ spa "Ilegal mezcla de collations para operación '%s'"
+ER_VARIABLE_IS_NOT_STRUCT
+ eng "Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)"
+ ger "Variable '%-.64s' ist keine Variablen-Komponenten (kann nicht als XXXX.variablen_name verwendet werden)"
+ por "Variável '%-.64s' não é uma variável componente (Não pode ser usada como XXXX.variável_nome)"
+ spa "Variable '%-.64s' no es una variable componente (No puede ser usada como XXXX.variable_name)"
+ER_UNKNOWN_COLLATION
+ eng "Unknown collation: '%-.64s'"
+ ger "Unbekannte Kollation: '%-.64s'"
+ por "Collation desconhecida: '%-.64s'"
+ spa "Collation desconocida: '%-.64s'"
+ER_SLAVE_IGNORED_SSL_PARAMS
+ eng "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"
+ ger "SSL-Parameter in CHANGE MASTER werden ignoriert, weil dieser MySQL-Slave ohne SSL-Unterstützung kompiliert wurde. Sie können aber später verwendet werden, wenn der MySQL-Slave mit SSL gestartet wird"
+ por "SSL parâmetros em CHANGE MASTER são ignorados porque este escravo MySQL foi compilado sem o SSL suporte. Os mesmos podem ser usados mais tarde quando o escravo MySQL com SSL seja iniciado."
+ spa "Parametros SSL en CHANGE MASTER son ignorados porque este slave MySQL fue compilado sin soporte SSL; pueden ser usados despues cuando el slave MySQL con SSL sea inicializado"
+ER_SERVER_IS_IN_SECURE_AUTH_MODE
+ eng "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"
+ ger "Server läuft im Modus --secure-auth, aber '%s'@'%s' hat ein Passwort im alten Format. Bitte Passwort ins neue Format ändern"
+ por "Servidor está rodando em --secure-auth modo, porêm '%s'@'%s' tem senha no formato antigo; por favor troque a senha para o novo formato"
+ rus "óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s'@'%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ"
+ spa "Servidor está rodando en modo --secure-auth, pero '%s'@'%s' tiene clave en el antiguo formato; por favor cambie la clave para el nuevo formato"
+ER_WARN_FIELD_RESOLVED
+ eng "Field or reference '%-.64s%s%-.64s%s%-.64s' of SELECT #%d was resolved in SELECT #%d"
+ ger "Feld oder Verweis '%-.64s%s%-.64s%s%-.64s' im SELECT-Befehl Nr. %d wurde im SELECT-Befehl Nr. %d aufgelöst"
+ por "Campo ou referência '%-.64s%s%-.64s%s%-.64s' de SELECT #%d foi resolvido em SELECT #%d"
+ rus "ðÏÌÅ ÉÌÉ ÓÓÙÌËÁ '%-.64s%s%-.64s%s%-.64s' ÉÚ SELECTÁ #%d ÂÙÌÁ ÎÁÊÄÅÎÁ × SELECTÅ #%d"
+ spa "Campo o referencia '%-.64s%s%-.64s%s%-.64s' de SELECT #%d fue resolvido en SELECT #%d"
+ ukr "óÔÏ×ÂÅÃØ ÁÂÏ ÐÏÓÉÌÁÎÎÑ '%-.64s%s%-.64s%s%-.64s' ¦Ú SELECTÕ #%d ÂÕÌÏ ÚÎÁÊÄÅÎÅ Õ SELECT¦ #%d"
+ER_BAD_SLAVE_UNTIL_COND
+ eng "Incorrect parameter or combination of parameters for START SLAVE UNTIL"
+ ger "Falscher Parameter oder falsche Kombination von Parametern für START SLAVE UNTIL"
+ por "Parâmetro ou combinação de parâmetros errado para START SLAVE UNTIL"
+ spa "Parametro equivocado o combinación de parametros para START SLAVE UNTIL"
+ER_MISSING_SKIP_SLAVE
+ eng "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"
+ ger "Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn der Slave-Server unerwartet neu startet"
+ por "É recomendado para rodar com --skip-slave-start quando fazendo replicação passo-por-passo com START SLAVE UNTIL, de outra forma você não está seguro em caso de inesperada reinicialição do mysqld escravo"
+ spa "Es recomendado rodar con --skip-slave-start cuando haciendo replicación step-by-step con START SLAVE UNTIL, a menos que usted no esté seguro en caso de inesperada reinicialización del mysqld slave"
+ER_UNTIL_COND_IGNORED
+ eng "SQL thread is not to be started so UNTIL options are ignored"
+ ger "SQL-Thread soll nicht gestartet werden. Daher werden UNTIL-Optionen ignoriert"
+ por "Thread SQL não pode ser inicializado tal que opções UNTIL são ignoradas"
+ spa "SQL thread no es inicializado tal que opciones UNTIL son ignoradas"
+ER_WRONG_NAME_FOR_INDEX 42000
+ eng "Incorrect index name '%-.100s'"
+ por "Incorreto nome de índice '%-.100s'"
+ spa "Nombre de índice incorrecto '%-.100s'"
+ swe "Felaktigt index namn '%-.100s'"
+ER_WRONG_NAME_FOR_CATALOG 42000
+ eng "Incorrect catalog name '%-.100s'"
+ por "Incorreto nome de catálogo '%-.100s'"
+ spa "Nombre de catalog incorrecto '%-.100s'"
+ swe "Felaktigt katalog namn '%-.100s'"
+ER_WARN_QC_RESIZE
+ eng "Query cache failed to set size %lu; new query cache size is %lu"
+ por "Falha em Query cache para configurar tamanho %lu, novo tamanho de query cache é %lu"
+ rus "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu"
+ spa "Query cache fallada para configurar tamaño %lu, nuevo tamaño de query cache es %lu"
+ swe "Storleken av "Query cache" kunde inte sättas till %lu, ny storlek är %lu"
+ ukr "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu"
+ER_BAD_FT_COLUMN
+ eng "Column '%-.64s' cannot be part of FULLTEXT index"
+ por "Coluna '%-.64s' não pode ser parte de índice FULLTEXT"
+ spa "Columna '%-.64s' no puede ser parte de FULLTEXT index"
+ swe "Kolumn '%-.64s' kan inte vara del av ett FULLTEXT index"
+ER_UNKNOWN_KEY_CACHE
+ eng "Unknown key cache '%-.100s'"
+ por "Key cache desconhecida '%-.100s'"
+ spa "Desconocida key cache '%-.100s'"
+ swe "Okänd nyckel cache '%-.100s'"
+ER_WARN_HOSTNAME_WONT_WORK
+ eng "MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work"
+ por "MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar"
+ spa "MySQL esta inicializado en modo --skip-name-resolve. Usted necesita reinicializarlo sin esta opción para este derecho funcionar"
+ER_UNKNOWN_STORAGE_ENGINE 42000
+ eng "Unknown table engine '%s'"
+ por "Motor de tabela desconhecido '%s'"
+ spa "Desconocido motor de tabla '%s'"
+ER_WARN_DEPRECATED_SYNTAX
+ eng "'%s' is deprecated; use '%s' instead"
+ por "'%s' é desatualizado. Use '%s' em seu lugar"
+ spa "'%s' está desaprobado, use '%s' en su lugar"
+ER_NON_UPDATABLE_TABLE
+ eng "The target table %-.100s of the %s is not updatable"
+ por "A tabela destino %-.100s do %s não é atualizável"
+ rus "ôÁÂÌÉÃÁ %-.100s × %s ÎÅ ÍÏÖÅÔ ÉÚÍÅÎÑÔÓÑ"
+ spa "La tabla destino %-.100s del %s no es actualizable"
+ swe "Tabell %-.100s använd med '%s' är inte uppdateringsbar"
+ ukr "ôÁÂÌÉÃÑ %-.100s Õ %s ÎÅ ÍÏÖÅ ÏÎÏ×ÌÀ×ÁÔÉÓØ"
+ER_FEATURE_DISABLED
+ eng "The '%s' feature is disabled; you need MySQL built with '%s' to have it working"
+ por "O recurso '%s' foi desativado; você necessita MySQL construído com '%s' para ter isto funcionando"
+ spa "El recurso '%s' fue deshabilitado; usted necesita construir MySQL con '%s' para tener eso funcionando"
+ swe "'%s' är inte aktiverad; För att aktivera detta måste du bygga om MySQL med '%s' definerad"
+ER_OPTION_PREVENTS_STATEMENT
+ eng "The MySQL server is running with the %s option so it cannot execute this statement"
+ por "O servidor MySQL está rodando com a opção %s razão pela qual não pode executar esse commando"
+ spa "El servidor MySQL está rodando con la opción %s tal que no puede ejecutar este comando"
+ swe "MySQL är startad med --skip-grant-tables. Pga av detta kan du inte använda detta kommando"
+ER_DUPLICATED_VALUE_IN_TYPE
+ eng "Column '%-.100s' has duplicated value '%-.64s' in %s"
+ por "Coluna '%-.100s' tem valor duplicado '%-.64s' em %s"
+ spa "Columna '%-.100s' tiene valor doblado '%-.64s' en %s"
+ER_TRUNCATED_WRONG_VALUE 22007
+ eng "Truncated incorrect %-.32s value: '%-.128s'"
+ por "Truncado errado %-.32s valor: '%-.128s'"
+ spa "Equivocado truncado %-.32s valor: '%-.128s'"
+ER_TOO_MUCH_AUTO_TIMESTAMP_COLS
+ eng "Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause"
+ por "Incorreta definição de tabela; Pode ter somente uma coluna TIMESTAMP com CURRENT_TIMESTAMP em DEFAULT ou ON UPDATE cláusula"
+ spa "Incorrecta definición de tabla; Solamente debe haber una columna TIMESTAMP con CURRENT_TIMESTAMP en DEFAULT o ON UPDATE cláusula"
+ER_INVALID_ON_UPDATE
+ eng "Invalid ON UPDATE clause for '%-.64s' column"
+ por "Inválida cláusula ON UPDATE para campo '%-.64s'"
+ spa "Inválido ON UPDATE cláusula para campo '%-.64s'"
+ER_UNSUPPORTED_PS
+ eng "This command is not supported in the prepared statement protocol yet"
+ER_GET_ERRMSG
+ dan "Modtog fejl %d '%-.100s' fra %s"
+ eng "Got error %d '%-.100s' from %s"
+ nor "Mottok feil %d '%-.100s' fa %s"
+ norwegian-ny "Mottok feil %d '%-.100s' fra %s"
+ER_GET_TEMPORARY_ERRMSG
+ dan "Modtog temporary fejl %d '%-.100s' fra %s"
+ eng "Got temporary error %d '%-.100s' from %s"
+ nor "Mottok temporary feil %d '%-.100s' fra %s"
+ norwegian-ny "Mottok temporary feil %d '%-.100s' fra %s"
+ER_UNKNOWN_TIME_ZONE
+ eng "Unknown or incorrect time zone: '%-.64s'"
+ER_WARN_INVALID_TIMESTAMP
+ eng "Invalid TIMESTAMP value in column '%s' at row %ld"
+ER_INVALID_CHARACTER_STRING
+ eng "Invalid %s character string: '%.64s'"
+ER_WARN_ALLOWED_PACKET_OVERFLOWED
+ eng "Result of %s() was larger than max_allowed_packet (%ld) - truncated"
+ER_CONFLICTING_DECLARATIONS
+ eng "Conflicting declarations: '%s%s' and '%s%s'"
+ER_SP_NO_RECURSIVE_CREATE 2F003
+ eng "Can't create a %s from within another stored routine"
+ER_SP_ALREADY_EXISTS 42000
+ eng "%s %s already exists"
+ER_SP_DOES_NOT_EXIST 42000
+ eng "%s %s does not exist"
+ER_SP_DROP_FAILED
+ eng "Failed to DROP %s %s"
+ER_SP_STORE_FAILED
+ eng "Failed to CREATE %s %s"
+ER_SP_LILABEL_MISMATCH 42000
+ eng "%s with no matching label: %s"
+ER_SP_LABEL_REDEFINE 42000
+ eng "Redefining label %s"
+ER_SP_LABEL_MISMATCH 42000
+ eng "End-label %s without match"
+ER_SP_UNINIT_VAR 01000
+ eng "Referring to uninitialized variable %s"
+ER_SP_BADSELECT 0A000
+ eng "PROCEDURE %s can't return a result set in the given context"
+ER_SP_BADRETURN 42000
+ eng "RETURN is only allowed in a FUNCTION"
+ER_SP_BADSTATEMENT 0A000
+ eng "%s is not allowed in stored procedures"
+ER_UPDATE_LOG_DEPRECATED_IGNORED 42000
+ eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored"
+ER_UPDATE_LOG_DEPRECATED_TRANSLATED 42000
+ eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN"
+ER_QUERY_INTERRUPTED 70100
+ eng "Query execution was interrupted"
+ER_SP_WRONG_NO_OF_ARGS 42000
+ eng "Incorrect number of arguments for %s %s; expected %u, got %u"
+ER_SP_COND_MISMATCH 42000
+ eng "Undefined CONDITION: %s"
+ER_SP_NORETURN 42000
+ eng "No RETURN found in FUNCTION %s"
+ER_SP_NORETURNEND 2F005
+ eng "FUNCTION %s ended without RETURN"
+ER_SP_BAD_CURSOR_QUERY 42000
+ eng "Cursor statement must be a SELECT"
+ER_SP_BAD_CURSOR_SELECT 42000
+ eng "Cursor SELECT must not have INTO"
+ER_SP_CURSOR_MISMATCH 42000
+ eng "Undefined CURSOR: %s"
+ER_SP_CURSOR_ALREADY_OPEN 24000
+ eng "Cursor is already open"
+ER_SP_CURSOR_NOT_OPEN 24000
+ eng "Cursor is not open"
+ER_SP_UNDECLARED_VAR 42000
+ eng "Undeclared variable: %s"
+ER_SP_WRONG_NO_OF_FETCH_ARGS
+ eng "Incorrect number of FETCH variables"
+ER_SP_FETCH_NO_DATA 02000
+ eng "No data to FETCH"
+ER_SP_DUP_PARAM 42000
+ eng "Duplicate parameter: %s"
+ER_SP_DUP_VAR 42000
+ eng "Duplicate variable: %s"
+ER_SP_DUP_COND 42000
+ eng "Duplicate condition: %s"
+ER_SP_DUP_CURS 42000
+ eng "Duplicate cursor: %s"
+ER_SP_CANT_ALTER
+ eng "Failed to ALTER %s %s"
+ER_SP_SUBSELECT_NYI 0A000
+ eng "Subselect value not supported"
+ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG 0A000
+ eng "%s is not allowed in stored function or trigger"
+ER_SP_VARCOND_AFTER_CURSHNDLR 42000
+ eng "Variable or condition declaration after cursor or handler declaration"
+ER_SP_CURSOR_AFTER_HANDLER 42000
+ eng "Cursor declaration after handler declaration"
+ER_SP_CASE_NOT_FOUND 20000
+ eng "Case not found for CASE statement"
+ER_FPARSER_TOO_BIG_FILE
+ eng "Configuration file '%-.64s' is too big"
+ rus "óÌÉÛËÏÍ ÂÏÌØÛÏÊ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÙÊ ÆÁÊÌ '%-.64s'"
+ ukr "úÁÎÁÄÔÏ ×ÅÌÉËÉÊ ËÏÎƦÇÕÒÁæÊÎÉÊ ÆÁÊÌ '%-.64s'"
+ER_FPARSER_BAD_HEADER
+ eng "Malformed file type header in file '%-.64s'"
+ rus "îÅ×ÅÒÎÙÊ ÚÁÇÏÌÏ×ÏË ÔÉÐÁ ÆÁÊÌÁ '%-.64s'"
+ ukr "îÅצÒÎÉÊ ÚÁÇÏÌÏ×ÏË ÔÉÐÕ Õ ÆÁÊ̦ '%-.64s'"
+ER_FPARSER_EOF_IN_COMMENT
+ eng "Unexpected end of file while parsing comment '%-.64s'"
+ rus "îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ × ËÏÍÅÎÔÁÒÉÉ '%-.64s'"
+ ukr "îÅÓÐÏĦ×ÁÎÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ Õ ËÏÍÅÎÔÁÒ¦ '%-.64s'"
+ER_FPARSER_ERROR_IN_PARAMETER
+ eng "Error while parsing parameter '%-.64s' (line: '%-.64s')"
+ rus "ïÛÉÂËÁ ÐÒÉ ÒÁÓÐÏÚÎÁ×ÁÎÉÉ ÐÁÒÁÍÅÔÒÁ '%-.64s' (ÓÔÒÏËÁ: '%-.64s')"
+ ukr "ðÏÍÉÌËÁ × ÒÏÓЦÚÎÁ×ÁÎΦ ÐÁÒÁÍÅÔÒÕ '%-.64s' (ÒÑÄÏË: '%-.64s')"
+ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER
+ eng "Unexpected end of file while skipping unknown parameter '%-.64s'"
+ rus "îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ ÐÒÉ ÐÒÏÐÕÓËÅ ÎÅÉÚ×ÅÓÔÎÏÇÏ ÐÁÒÁÍÅÔÒÁ '%-.64s'"
+ ukr "îÅÓÐÏĦ×ÁÎÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ Õ ÓÐÒϦ ÐÒÏÍÉÎÕÔÉ ÎÅצÄÏÍÉÊ ÐÁÒÁÍÅÔÒ '%-.64s'"
+ER_VIEW_NO_EXPLAIN
+ eng "EXPLAIN/SHOW can not be issued; lacking privileges for underlying table"
+ rus "EXPLAIN/SHOW ÎÅ ÍÏÖÅÔ ÂÙÔØ ×ÙÐÏÌÎÅÎÎÏ; ÎÅÄÏÓÔÁÔÏÞÎÏ ÐÒÁ× ÎÁ ÔÁËÂÌÉÃÙ ÚÁÐÒÏÓÁ"
+ ukr "EXPLAIN/SHOW ÎÅ ÍÏÖÅ ÂÕÔÉ ×¦ËÏÎÁÎÏ; ÎÅÍÁ¤ ÐÒÁ× ÎÁ ÔÉÂÌÉæ ÚÁÐÉÔÕ"
+ER_FRM_UNKNOWN_TYPE
+ eng "File '%-.64s' has unknown type '%-.64s' in its header"
+ rus "æÁÊÌ '%-.64s' ÓÏÄÅÒÖÉÔ ÎÅÉÚ×ÅÓÔÎÙÊ ÔÉÐ '%-.64s' × ÚÁÇÏÌÏ×ËÅ"
+ ukr "æÁÊÌ '%-.64s' ÍÁ¤ ÎÅצÄÏÍÉÊ ÔÉÐ '%-.64s' Õ ÚÁÇÏÌÏ×ËÕ"
+ER_WRONG_OBJECT
+ eng "'%-.64s.%-.64s' is not %s"
+ rus "'%-.64s.%-.64s' - ÎÅ %s"
+ ukr "'%-.64s.%-.64s' ÎÅ ¤ %s"
+ER_NONUPDATEABLE_COLUMN
+ eng "Column '%-.64s' is not updatable"
+ rus "óÔÏÌÂÅà '%-.64s' ÎÅ ÏÂÎÏ×ÌÑÅÍÙÊ"
+ ukr "óÔÏ×ÂÅÃØ '%-.64s' ÎÅ ÍÏÖÅ ÂÕÔÉ ÚÍÉÎÅÎÉÊ"
+ER_VIEW_SELECT_DERIVED
+ eng "View's SELECT contains a subquery in the FROM clause"
+ rus "View SELECT ÓÏÄÅÒÖÉÔ ÐÏÄÚÁÐÒÏÓ × ËÏÎÓÔÒÕËÃÉÉ FROM"
+ ukr "View SELECT ÍÁ¤ ЦÄÚÁÐÉÔ Õ ËÏÎÓÔÒÕËæ§ FROM"
+ER_VIEW_SELECT_CLAUSE
+ eng "View's SELECT contains a '%s' clause"
+ rus "View SELECT ÓÏÄÅÒÖÉÔ ËÏÎÓÔÒÕËÃÉÀ '%s'"
+ ukr "View SELECT ÍÁ¤ ËÏÎÓÔÒÕËæÀ '%s'"
+ER_VIEW_SELECT_VARIABLE
+ eng "View's SELECT contains a variable or parameter"
+ rus "View SELECT ÓÏÄÅÒÖÉÔ ÐÅÒÅÍÅÎÎÕÀ ÉÌÉ ÐÁÒÁÍÅÔÒ"
+ ukr "View SELECT ÍÁ¤ ÚÍÉÎÎÕ ÁÂÏ ÐÁÒÁÍÅÔÅÒ"
+ER_VIEW_SELECT_TMPTABLE
+ eng "View's SELECT refers to a temporary table '%-.64s'"
+ rus "View SELECT ÓÏÄÅÒÖÉÔ ÓÓÙÌËÕ ÎÁ ×ÒÅÍÅÎÎÕÀ ÔÁÂÌÉÃÕ '%-.64s'"
+ ukr "View SELECT ×ÉËÏÒÉÓÔÏ×Õ¤ ÔÉÍÞÁÓÏ×Õ ÔÁÂÌÉÃÀ '%-.64s'"
+ER_VIEW_WRONG_LIST
+ eng "View's SELECT and view's field list have different column counts"
+ rus "View SELECT É ÓÐÉÓÏË ÐÏÌÅÊ view ÉÍÅÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×"
+ ukr "View SELECT ¦ ÐÅÒÅÌ¦Ë ÓÔÏ×ÂÃ¦× view ÍÁÀÔØ Ò¦ÚÎÕ Ë¦ÌØ˦ÓÔØ ÓËÏ×Âæ×"
+ER_WARN_VIEW_MERGE
+ eng "View merge algorithm can't be used here for now (assumed undefined algorithm)"
+ rus "áÌÇÏÒÉÔÍ ÓÌÉÑÎÉÑ view ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎ ÓÅÊÞÁÓ (ÁÌÇÏÒÉÔÍ ÂÕÄÅÔ ÎÅÏÐÅÒÅÄÅÌÅÎÎÙÍ)"
+ ukr "áÌÇÏÒÉÔÍ ÚÌÉ×ÁÎÎÑ view ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÉÊ ÚÁÒÁÚ (ÁÌÇÏÒÉÔÍ ÂÕÄÅ ÎÅ×ÉÚÎÁÞÅÎÉÊ)"
+ER_WARN_VIEW_WITHOUT_KEY
+ eng "View being updated does not have complete key of underlying table in it"
+ rus "ïÂÎÏ×ÌÑÅÍÙÊ view ÎÅ ÓÏÄÅÒÖÉÔ ËÌÀÞÁ ÉÓÐÏÌØÚÏ×ÁÎÎÙÈ(ÏÊ) × ÎÅÍ ÔÁÂÌÉÃ(Ù)"
+ ukr "View, ÝÏ ÏÎÏ×ÌÀÅÔØÓÑ, ΊͦÓÔÉÔØ ÐÏ×ÎÏÇÏ ËÌÀÞÁ ÔÁÂÌÉæ(Ø), ÝÏ ×ÉËÏÒ¦ÓÔÁÎÁ × ÎØÀÏÍÕ"
+ER_VIEW_INVALID
+ eng "View '%-.64s.%-.64s' references invalid table(s) or column(s) or function(s)"
+ rus "View '%-.64s.%-.64s' ÓÓÙÌÁÅÔÓÑ ÎÁ ÎÅÓÕÝÅÓÔ×ÕÀÝÉÅ ÔÁÂÌÉÃÙ ÉÌÉ ÓÔÏÌÂÃÙ ÉÌÉ ÆÕÎËÃÉÉ"
+ER_SP_NO_DROP_SP
+ eng "Can't drop or alter a %s from within another stored routine"
+ER_SP_GOTO_IN_HNDLR
+ eng "GOTO is not allowed in a stored procedure handler"
+ER_TRG_ALREADY_EXISTS
+ eng "Trigger already exists"
+ER_TRG_DOES_NOT_EXIST
+ eng "Trigger does not exist"
+ER_TRG_ON_VIEW_OR_TEMP_TABLE
+ eng "Trigger's '%-.64s' is view or temporary table"
+ER_TRG_CANT_CHANGE_ROW
+ eng "Updating of %s row is not allowed in %strigger"
+ER_TRG_NO_SUCH_ROW_IN_TRG
+ eng "There is no %s row in %s trigger"
+ER_NO_DEFAULT_FOR_FIELD
+ eng "Field '%-.64s' doesn't have a default value"
+ER_DIVISION_BY_ZERO 22012
+ eng "Division by 0"
+ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
+ eng "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld"
+ER_ILLEGAL_VALUE_FOR_TYPE 22007
+ eng "Illegal %s '%-.64s' value found during parsing"
+ER_VIEW_NONUPD_CHECK
+ eng "CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
+ rus "CHECK OPTION ÄÌÑ ÎÅÏÂÎÏ×ÌÑÅÍÏÇÏ VIEW '%-.64s.%-.64s'"
+ ukr "CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÝÏ ÎÅ ÍÏÖÅ ÂÕÔÉ ÏÎÏ×ÌÅÎÎÉÍ"
+ER_VIEW_CHECK_FAILED
+ eng "CHECK OPTION failed '%-.64s.%-.64s'"
+ rus "ÐÒÏ×ÅÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÐÒÏ×ÁÌÉÌÁÓØ"
+ ukr "ðÅÒÅצÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÎÅ ÐÒÏÊÛÌÁ"
+ER_PROCACCESS_DENIED_ERROR 42000
+ eng "%-.16s command denied to user '%-.32s'@'%-.64s' for routine '%-.64s'"
+ER_RELAY_LOG_FAIL
+ eng "Failed purging old relay logs: %s"
+ER_PASSWD_LENGTH
+ eng "Password hash should be a %d-digit hexadecimal number"
+ER_UNKNOWN_TARGET_BINLOG
+ eng "Target log not found in binlog index"
+ER_IO_ERR_LOG_INDEX_READ
+ eng "I/O error reading log index file"
+ER_BINLOG_PURGE_PROHIBITED
+ eng "Server configuration does not permit binlog purge"
+ER_FSEEK_FAIL
+ eng "Failed on fseek()"
+ER_BINLOG_PURGE_FATAL_ERR
+ eng "Fatal error during log purge"
+ER_LOG_IN_USE
+ eng "A purgeable log is in use, will not purge"
+ER_LOG_PURGE_UNKNOWN_ERR
+ eng "Unknown error during log purge"
+ER_RELAY_LOG_INIT
+ eng "Failed initializing relay log position: %s"
+ER_NO_BINARY_LOGGING
+ eng "You are not using binary logging"
+ER_RESERVED_SYNTAX
+ eng "The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+ER_WSAS_FAILED
+ eng "WSAStartup Failed"
+ER_DIFF_GROUPS_PROC
+ eng "Can't handle procedures with differents groups yet"
+ER_NO_GROUP_FOR_PROC
+ eng "Select must have a group with this procedure"
+ER_ORDER_WITH_PROC
+ eng "Can't use ORDER clause with this procedure"
+ER_LOGGING_PROHIBIT_CHANGING_OF
+ eng "Binary logging and replication forbid changing the global server %s"
+ER_NO_FILE_MAPPING
+ eng "Can't map file: %-.64s, errno: %d"
+ER_WRONG_MAGIC
+ eng "Wrong magic in %-.64s"
+ER_PS_MANY_PARAM
+ eng "Prepared statement contains too many placeholders"
+ER_KEY_PART_0
+ eng "Key part '%-.64s' length cannot be 0"
+ER_VIEW_CHECKSUM
+ eng "View text checksum failed"
+ rus "ðÒÏ×ÅÒËÁ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ ÔÅËÓÔÁ VIEW ÐÒÏ×ÁÌÉÌÁÓØ"
+ ukr "ðÅÒÅצÒËÁ ËÏÎÔÒÏÌØÎϧ ÓÕÍÉ ÔÅËÓÔÕ VIEW ÎÅ ÐÒÏÊÛÌÁ"
+ER_VIEW_MULTIUPDATE
+ eng "Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+ rus "îÅÌØÚÑ ÉÚÍÅÎÉÔØ ÂÏÌØÛÅ ÞÅÍ ÏÄÎÕ ÂÁÚÏ×ÕÀ ÔÁÂÌÉÃÕ ÉÓÐÏÌØÚÕÑ ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.64s.%-.64s'"
+ ukr "îÅÍÏÖÌÉ×Ï ÏÎÏ×ÉÔÉ Â¦ÌØÛ ÎÉÖ ÏÄÎÕ ÂÁÚÏ×Õ ÔÁÂÌÉÃÀ ×ÙËÏÒÉÓÔÏ×ÕÀÞÉ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔ¦ÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ"
+ER_VIEW_NO_INSERT_FIELD_LIST
+ eng "Can not insert into join view '%-.64s.%-.64s' without fields list"
+ rus "îÅÌØÚÑ ×ÓÔÁ×ÌÑÔØ ÚÁÐÉÓÉ × ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.64s.%-.64s' ÂÅÚ ÓÐÉÓËÁ ÐÏÌÅÊ"
+ ukr "îÅÍÏÖÌÉ×Ï ÕÓÔÁ×ÉÔÉ ÒÑÄËÉ Õ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔÉÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ, ÂÅÚ ÓÐÉÓËÕ ÓÔÏ×Âæ×"
+ER_VIEW_DELETE_MERGE_VIEW
+ eng "Can not delete from join view '%-.64s.%-.64s'"
+ rus "îÅÌØÚÑ ÕÄÁÌÑÔØ ÉÚ ÍÎÏÇÏÔÁÂÌÉÞÎÏÇÏ VIEW '%-.64s.%-.64s'"
+ ukr "îÅÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ÒÑÄËÉ Õ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔÉÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ"
+ER_CANNOT_USER
+ eng "Operation %s failed for %.256s"
+ ger "Das Kommando %s scheiterte für %.256s"
+ norwegian-ny "Operation %s failed for '%.256s'"
+ER_XAER_NOTA XAE04
+ eng "XAER_NOTA: Unknown XID"
+ER_XAER_INVAL XAE05
+ eng "XAER_INVAL: Invalid arguments (or unsupported command)"
+ER_XAER_RMFAIL XAE07
+ eng "XAER_RMFAIL: The command cannot be executed in the %.64s state"
+ER_XAER_OUTSIDE XAE09
+ eng "XAER_OUTSIDE: Some work is done outside global transaction"
+ER_XAER_RMERR XAE03
+ eng "XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency"
+ER_XA_RBROLLBACK XA100
+ eng "XA_RBROLLBACK: Transaction branch was rolled back"
+ER_NONEXISTING_PROC_GRANT 42000
+ eng "There is no such grant defined for user '%-.32s' on host '%-.64s' on routine '%-.64s'"
+ER_PROC_AUTO_GRANT_FAIL
+ eng "Failed to grant EXECUTE and ALTER ROUTINE privileges"
+ER_PROC_AUTO_REVOKE_FAIL
+ eng "Failed to revoke all privileges to dropped routine"
+ER_DATA_TOO_LONG 22001
+ eng "Data too long for column '%s' at row %ld"
+ER_SP_BAD_SQLSTATE 42000
+ eng "Bad SQLSTATE: '%s'"
+ER_STARTUP
+ eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d %s"
+ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR
+ eng "Can't load value from file with fixed size rows to variable"
+ER_CANT_CREATE_USER_WITH_GRANT 42000
+ eng "You are not allowed to create a user with GRANT"
+ER_WRONG_VALUE_FOR_TYPE
+ eng "Incorrect %-.32s value: '%-.128s' for function %-.32s"
+ER_TABLE_DEF_CHANGED
+ eng "Table definition has changed, please retry transaction"
+ER_SP_DUP_HANDLER 42000
+ eng "Duplicate handler declared in the same block"
+ER_SP_NOT_VAR_ARG 42000
+ eng "OUT or INOUT argument %d for routine %s is not a variable"
+ER_SP_NO_RETSET 0A000
+ eng "Not allowed to return a result set from a %s"
+ER_CANT_CREATE_GEOMETRY_OBJECT 22003
+ eng "Cannot get geometry object from data you send to the GEOMETRY field"
+ER_FAILED_ROUTINE_BREAK_BINLOG
+ eng "A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes"
+ER_BINLOG_UNSAFE_ROUTINE
+ eng "This routine has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)"
+ER_BINLOG_CREATE_ROUTINE_NEED_SUPER
+ eng "You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)"
+ER_EXEC_STMT_WITH_OPEN_CURSOR
+ eng "You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it."
+ER_STMT_HAS_NO_OPEN_CURSOR
+ eng "The statement (%lu) has no open cursor."
+ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+ eng "Explicit or implicit commit is not allowed in stored function or trigger."
+ER_NO_DEFAULT_FOR_VIEW_FIELD
+ eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value"
+ER_SP_NO_RECURSION
+ eng "Recursive stored routines are not allowed."
+ER_TOO_BIG_SCALE 42000 S1009
+ eng "Too big scale %d specified for column '%-.64s'. Maximum is %d."
+ER_TOO_BIG_PRECISION 42000 S1009
+ eng "Too big precision %d specified for column '%-.64s'. Maximum is %d."
+ER_SCALE_BIGGER_THAN_PRECISION 42000 S1009
+ eng "Scale may not be larger than the precision (column '%-.64s')."
+ER_WRONG_LOCK_OF_SYSTEM_TABLE
+ eng "You can't combine write-locking of system '%-.64s.%-.64s' table with other tables"
+ER_CONNECT_TO_FOREIGN_DATA_SOURCE
+ eng "Unable to connect to foreign data source - database '%s'!"
+ER_QUERY_ON_FOREIGN_DATA_SOURCE
+ eng "There was a problem processing the query on the foreign data source. Data source error: '%-.64s'"
+ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST
+ eng "The foreign data source you are trying to reference does not exist. Data source error : '%-.64s'"
+ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE
+ eng "Can't create federated table. The data source connection string '%-.64s' is not in the correct format"
+ER_FOREIGN_DATA_STRING_INVALID
+ eng "The data source connection string '%-.64s' is not in the correct format"
+ER_CANT_CREATE_FEDERATED_TABLE
+ eng "Can't create federated table. Foreign data src error : '%-.64s'"
+ER_TRG_IN_WRONG_SCHEMA
+ eng "Trigger in wrong schema"
+ER_STACK_OVERRUN_NEED_MORE
+ eng "Thread stack overrun: %ld bytes used of a %ld byte stack, and %ld bytes needed. Use 'mysqld -O thread_stack=#' to specify a bigger stack."
+ER_TOO_LONG_BODY 42000 S1009
+ eng "Routine body for '%-.100s' is too long"
+ER_WARN_CANT_DROP_DEFAULT_KEYCACHE
+ eng "Cannot drop default keycache"
+ ger "Der Default-Keycache kann nicht gelöscht werden"
+ER_TOO_BIG_DISPLAYWIDTH 42000 S1009
+ eng "Display width out of range for column '%-.64s' (max = %d)"
+ER_XAER_DUPID XAE08
+ eng "XAER_DUPID: The XID already exists"
+ER_DATETIME_FUNCTION_OVERFLOW 22008
+ eng "Datetime function: %-.32s field overflow"
+ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+ eng "Can't update table '%-.64s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger."
+ER_VIEW_PREVENT_UPDATE
+ eng "The definition of table '%-.64s' prevents operation %s on table '%-.64s'."
+ER_PS_NO_RECURSION
+ eng "The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner"
+ER_SP_CANT_SET_AUTOCOMMIT
+ eng "Not allowed to set autocommit from a stored function or trigger"
+ER_NO_VIEW_USER
+ eng "View definer is not fully qualified"
+ER_VIEW_FRM_NO_USER
+ eng "View %-.64s.%-.64s has not definer information (old table format). Current user is used as definer. Please recreate view!"
+ER_VIEW_OTHER_USER
+ eng "You need the SUPER privilege for creation view with %-.64s@%-.64s definer"
+ER_NO_SUCH_USER
+ eng "There is not %-.64s@%-.64s registered"
+ER_FORBID_SCHEMA_CHANGE
+ eng "Changing schema from '%-.64s' to '%-.64s' is not allowed."
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
deleted file mode 100644
index b7557a37670..00000000000
--- a/sql/share/estonian/errmsg.txt
+++ /dev/null
@@ -1,327 +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 */
-
-/*
- Esialgne tõlge: Tõnu Samuel (tonu@spam.ee)
- Parandanud ja täiendanud: Indrek Siitan (tfr@mysql.com)
-*/
-
-character-set=latin7
-
-"hashchk",
-"isamchk",
-"EI",
-"JAH",
-"Ei suuda luua faili '%-.64s' (veakood: %d)",
-"Ei suuda luua tabelit '%-.64s' (veakood: %d)",
-"Ei suuda luua andmebaasi '%-.64s' (veakood: %d)",
-"Ei suuda luua andmebaasi '%-.64s': andmebaas juba eksisteerib",
-"Ei suuda kustutada andmebaasi '%-.64s': andmebaasi ei eksisteeri",
-"Viga andmebaasi kustutamisel (ei suuda kustutada faili '%-.64s', veakood: %d)",
-"Viga andmebaasi kustutamisel (ei suuda kustutada kataloogi '%-.64s', veakood: %d)",
-"Viga '%-.64s' kustutamisel (veakood: %d)",
-"Ei suuda lugeda kirjet süsteemsest tabelist",
-"Ei suuda lugeda '%-.64s' olekut (veakood: %d)",
-"Ei suuda identifitseerida jooksvat kataloogi (veakood: %d)",
-"Ei suuda lukustada faili (veakood: %d)",
-"Ei suuda avada faili '%-.64s' (veakood: %d)",
-"Ei suuda leida faili '%-.64s' (veakood: %d)",
-"Ei suuda lugeda kataloogi '%-.64s' (veakood: %d)",
-"Ei suuda siseneda kataloogi '%-.64s' (veakood: %d)",
-"Kirje tabelis '%-.64s' on muutunud viimasest lugemisest saadik",
-"Ketas täis (%s). Ootame kuni tekib vaba ruumi...",
-"Ei saa kirjutada, korduv võti tabelis '%-.64s'",
-"Viga faili '%-.64s' sulgemisel (veakood: %d)",
-"Viga faili '%-.64s' lugemisel (veakood: %d)",
-"Viga faili '%-.64s' ümbernimetamisel '%-.64s'-ks (veakood: %d)",
-"Viga faili '%-.64s' kirjutamisel (veakood: %d)",
-"'%-.64s' on lukustatud muudatuste vastu",
-"Sorteerimine katkestatud",
-"Vaade '%-.64s' ei eksisteeri '%-.64s' jaoks",
-"Tabeli handler tagastas vea %d",
-"Tabeli '%-.64s' handler ei toeta antud operatsiooni",
-"Ei suuda leida kirjet '%-.64s'-s",
-"Vigane informatsioon failis '%-.64s'",
-"Tabeli '%-.64s' võtmefail on vigane; proovi seda parandada",
-"Tabeli '%-.64s' võtmefail on aegunud; paranda see!",
-"Tabel '%-.64s' on ainult lugemiseks",
-"Mälu sai otsa. Proovi MySQL uuesti käivitada (puudu jäi %d baiti)",
-"Mälu sai sorteerimisel otsa. Suurenda MySQL-i sorteerimispuhvrit",
-"Ootamatu faililõpumärgend faili '%-.64s' lugemisel (veakood: %d)",
-"Liiga palju samaaegseid ühendusi",
-"Mälu sai otsa. Võimalik, et aitab swap-i lisamine või käsu 'ulimit' abil MySQL-le rohkema mälu kasutamise lubamine",
-"Ei suuda lahendada IP aadressi masina nimeks",
-"Väär handshake",
-"Ligipääs keelatud kasutajale '%-.32s'@'%-.64s' andmebaasile '%-.64s'",
-"Ligipääs keelatud kasutajale '%-.32s'@'%-.64s' (kasutab parooli: %s)",
-"Andmebaasi ei ole valitud",
-"Tundmatu käsk",
-"Tulp '%-.64s' ei saa omada nullväärtust",
-"Tundmatu andmebaas '%-.64s'",
-"Tabel '%-.64s' juba eksisteerib",
-"Tundmatu tabel '%-.64s'",
-"Väli '%-.64s' %-.64s-s ei ole ühene",
-"Serveri seiskamine käib",
-"Tundmatu tulp '%-.64s' '%-.64s'-s",
-"'%-.64s' puudub GROUP BY klauslis",
-"Ei saa grupeerida '%-.64s' järgi",
-"Lauses on korraga nii tulbad kui summeerimisfunktsioonid",
-"Tulpade arv erineb väärtuste arvust",
-"Identifikaatori '%-.100s' nimi on liiga pikk",
-"Kattuv tulba nimi '%-.64s'",
-"Kattuv võtme nimi '%-.64s'",
-"Kattuv väärtus '%-.64s' võtmele %d",
-"Vigane tulba kirjeldus tulbale '%-.64s'",
-"%s '%-.80s' ligidal real %d",
-"Tühi päring",
-"Ei ole unikaalne tabel/alias '%-.64s'",
-"Vigane vaikeväärtus '%-.64s' jaoks",
-"Mitut primaarset võtit ei saa olla",
-"Liiga palju võtmeid. Maksimaalselt võib olla %d võtit",
-"Võti koosneb liiga paljudest osadest. Maksimaalselt võib olla %d osa",
-"Võti on liiga pikk. Maksimaalne võtmepikkus on %d",
-"Võtme tulp '%-.64s' puudub tabelis",
-"BLOB-tüüpi tulpa '%-.64s' ei saa kasutada võtmena",
-"Tulba '%-.64s' pikkus on liiga pikk (maksimaalne pikkus: %d). Kasuta BLOB väljatüüpi",
-"Vigane tabelikirjeldus; Tabelis tohib olla üks auto_increment tüüpi tulp ning see peab olema defineeritud võtmena",
-"%s: ootab ühendusi",
-"%s: MySQL lõpetas\n",
-"%s: sain signaali %d. Lõpetan!\n",
-"%s: Lõpp\n",
-"%s: Sulgen jõuga lõime %ld kasutaja: '%-.32s'\n",
-"Ei suuda luua IP socketit",
-"Tabelil '%-.64s' puuduvad võtmed. Loo tabel uuesti",
-"Väljade eraldaja erineb oodatust. Tutvu kasutajajuhendiga",
-"BLOB-tüüpi väljade olemasolul ei saa kasutada fikseeritud väljapikkust. Vajalik 'fields terminated by' määrang.",
-"Fail '%-.64s' peab asuma andmebaasi kataloogis või olema kõigile loetav",
-"Fail '%-.80s' juba eksisteerib",
-"Kirjeid: %ld Kustutatud: %ld Vahele jäetud: %ld Hoiatusi: %ld",
-"Kirjeid: %ld Kattuvaid: %ld",
-"Vigane võtme osa. Kasutatud võtmeosa ei ole string tüüpi, määratud pikkus on pikem kui võtmeosa või tabelihandler ei toeta seda tüüpi võtmeid",
-"ALTER TABLE kasutades ei saa kustutada kõiki tulpasid. Kustuta tabel DROP TABLE abil",
-"Ei suuda kustutada '%-.64s'. Kontrolli kas tulp/võti eksisteerib",
-"Kirjeid: %ld Kattuvaid: %ld Hoiatusi: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Tundmatu lõim: %lu",
-"Ei ole lõime %lu omanik",
-"Ühtegi tabelit pole kasutusel",
-"Liiga palju string tulbale %-.64s tüübile SET",
-"Ei suuda luua unikaalset logifaili nime %-.64s.(1-999)\n",
-"Tabel '%-.64s' on lukustatud READ lukuga ning ei ole muudetav",
-"Tabel '%-.64s' ei ole lukustatud käsuga LOCK TABLES",
-"BLOB-tüüpi tulp '%-.64s' ei saa omada vaikeväärtust",
-"Vigane andmebaasi nimi '%-.100s'",
-"Vigane tabeli nimi '%-.100s'",
-"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1",
-"Tundmatu viga",
-"Tundmatu protseduur '%-.64s'",
-"Vale parameetrite hulk protseduurile '%-.64s'",
-"Vigased parameetrid protseduurile '%-.64s'",
-"Tundmatu tabel '%-.64s' %-.32s-s",
-"Tulp '%-.64s' on määratletud topelt",
-"Vigane grupeerimisfunktsiooni kasutus",
-"Tabel '%-.64s' kasutab laiendust, mis ei eksisteeri antud MySQL versioonis",
-"Tabelis peab olema vähemalt üks tulp",
-"Tabel '%-.64s' on täis",
-"Vigane kooditabel '%-.64s'",
-"Liiga palju tabeleid. MySQL suudab JOINiga ühendada kuni %d tabelit",
-"Liiga palju tulpasid",
-"Liiga pikk kirje. Kirje maksimumpikkus arvestamata BLOB-tüüpi välju on %d. Muuda mõned väljad BLOB-tüüpi väljadeks",
-"Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed",
-"Ristsõltuvus OUTER JOIN klauslis. Kontrolli oma ON tingimusi",
-"Tulp '%-.64s' on kasutusel indeksina, kuid ei ole määratletud kui NOT NULL",
-"Ei suuda avada funktsiooni '%-.64s'",
-"Ei suuda algväärtustada funktsiooni '%-.64s'; %-.80s",
-"Teegi nimes ei tohi olla kataloogi",
-"Funktsioon '%-.64s' juba eksisteerib",
-"Ei suuda avada jagatud teeki '%-.64s' (veakood: %d %-.64s)",
-"Ei leia funktsiooni '%-.64s' antud teegis",
-"Funktsioon '%-.64s' ei ole defineeritud",
-"Masin '%-.64s' on blokeeritud hulgaliste ühendusvigade tõttu. Blokeeringu saab tühistada 'mysqladmin flush-hosts' käsuga",
-"Masinal '%-.64s' puudub ligipääs sellele MySQL serverile",
-"Te kasutate MySQL-i anonüümse kasutajana, kelledel pole parooli muutmise õigust",
-"Teiste paroolide muutmiseks on nõutav tabelite muutmisõigus 'mysql' andmebaasis",
-"Ei leia vastavat kirjet kasutajate tabelis",
-"Sobinud kirjeid: %ld Muudetud: %ld Hoiatusi: %ld",
-"Ei suuda luua uut lõime (veakood %d). Kui mälu ei ole otsas, on tõenäoliselt tegemist operatsioonisüsteemispetsiifilise veaga",
-"Tulpade hulk erineb väärtuste hulgast real %ld",
-"Ei suuda taasavada tabelit '%-.64s'",
-"NULL väärtuse väärkasutus",
-"regexp tagastas vea '%-.64s'",
-"GROUP tulpade (MIN(),MAX(),COUNT()...) kooskasutamine tavaliste tulpadega ilma GROUP BY klauslita ei ole lubatud",
-"Sellist õigust ei ole defineeritud kasutajale '%-.32s' masinast '%-.64s'",
-"%-.16s käsk ei ole lubatud kasutajale '%-.32s'@'%-.64s' tabelis '%-.64s'",
-"%-.16s käsk ei ole lubatud kasutajale '%-.32s'@'%-.64s' tulbale '%-.64s' tabelis '%-.64s'",
-"Vigane GRANT/REVOKE käsk. Tutvu kasutajajuhendiga",
-"Masina või kasutaja nimi GRANT lauses on liiga pikk",
-"Tabelit '%-.64s.%-.64s' ei eksisteeri",
-"Sellist õigust ei ole defineeritud kasutajale '%-.32s' masinast '%-.64s' tabelile '%-.64s'",
-"Antud käsk ei ole lubatud käesolevas MySQL versioonis",
-"Viga SQL süntaksis",
-"INSERT DELAYED lõim ei suutnud saada soovitud lukku tabelile %-.64s",
-"Liiga palju DELAYED lõimesid kasutusel",
-"Ühendus katkestatud %ld andmebaasile: '%-.64s' kasutajale: '%-.32s' (%-.64s)",
-"Saabus suurem pakett kui lubatud 'max_allowed_packet' muutujaga",
-"Viga ühendustoru lugemisel",
-"fcntl() tagastas vea",
-"Paketid saabusid vales järjekorras",
-"Viga andmepaketi lahtipakkimisel",
-"Viga andmepaketi lugemisel",
-"Kontrollaja ületamine andmepakettide lugemisel",
-"Viga andmepaketi kirjutamisel",
-"Kontrollaja ületamine andmepakettide kirjutamisel",
-"Tulemus on pikem kui lubatud 'max_allowed_packet' muutujaga",
-"Valitud tabelitüüp ei toeta BLOB/TEXT tüüpi välju",
-"Valitud tabelitüüp ei toeta AUTO_INCREMENT tüüpi välju",
-"INSERT DELAYED ei saa kasutada tabeli '%-.64s' peal, kuna see on lukustatud LOCK TABLES käsuga",
-"Vigane tulba nimi '%-.100s'",
-"Tabelihandler ei oska indekseerida tulpa '%-.64s'",
-"Kõik tabelid MERGE tabeli määratluses ei ole identsed",
-"Ei suuda kirjutada tabelisse '%-.64s', kuna see rikub ühesuse kitsendust",
-"BLOB-tüüpi tulp '%-.64s' on kasutusel võtmes ilma pikkust määratlemata",
-"Kõik PRIMARY KEY peavad olema määratletud NOT NULL piiranguga; vajadusel kasuta UNIQUE tüüpi võtit",
-"Tulemis oli rohkem kui üks kirje",
-"Antud tabelitüüp nõuab primaarset võtit",
-"Antud MySQL versioon on kompileeritud ilma RAID toeta",
-"Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita",
-"Võti '%-.64s' ei eksisteeri tabelis '%-.64s'",
-"Ei suuda avada tabelit",
-"Antud tabelitüüp ei toeta %s käske",
-"Seda käsku ei saa kasutada transaktsiooni sees",
-"Viga %d käsu COMMIT täitmisel",
-"Viga %d käsu ROLLBACK täitmisel",
-"Viga %d käsu FLUSH_LOGS täitmisel",
-"Viga %d käsu CHECKPOINT täitmisel",
-"Ühendus katkestatud %ld andmebaas: '%-.64s' kasutaja: '%-.32s' masin: `%-.64s' (%-.64s)",
-"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'",
-"Net error reading from master",
-"Net error writing to master",
-"Ei suutnud leida FULLTEXT indeksit, mis kattuks kasutatud tulpadega",
-"Ei suuda täita antud käsku kuna on aktiivseid lukke või käimasolev transaktsioon",
-"Tundmatu süsteemne muutuja '%-.64s'",
-"Tabel '%-.64s' on märgitud vigaseks ja tuleb parandada",
-"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",
-"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",
-"Lukkude koguarv ületab lukutabeli suuruse",
-"Uuenduslukke ei saa kasutada READ UNCOMMITTED transaktsiooni käigus",
-"DROP DATABASE ei ole lubatud kui lõim omab globaalset READ lukku",
-"CREATE DATABASE ei ole lubatud kui lõim omab globaalset READ lukku",
-"Vigased parameetrid %s-le",
-"Kasutajal '%-.32s'@'%-.64s' ei ole lubatud luua uusi kasutajaid",
-"Vigane tabelimääratlus; kõik MERGE tabeli liikmed peavad asuma samas andmebaasis",
-"Lukustamisel tekkis tupik (deadlock); alusta transaktsiooni otsast",
-"Antud tabelitüüp ei toeta FULLTEXT indekseid",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Viga käsu %s täitmisel: %-.128s",
-"Vigane %s ja %s kasutus",
-"Tulpade arv kasutatud SELECT lausetes ei kattu",
-"Ei suuda täita päringut konfliktse luku tõttu",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
deleted file mode 100644
index 6f10a468e26..00000000000
--- a/sql/share/french/errmsg.txt
+++ /dev/null
@@ -1,322 +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 */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NON",
-"OUI",
-"Ne peut créer le fichier '%-.64s' (Errcode: %d)",
-"Ne peut créer la table '%-.64s' (Errcode: %d)",
-"Ne peut créer la base '%-.64s' (Erreur %d)",
-"Ne peut créer la base '%-.64s'; elle existe déjà",
-"Ne peut effacer la base '%-.64s'; elle n'existe pas",
-"Ne peut effacer la base '%-.64s' (erreur %d)",
-"Erreur en effaçant la base (rmdir '%-.64s', erreur %d)",
-"Erreur en effaçant '%-.64s' (Errcode: %d)",
-"Ne peut lire un enregistrement de la table 'system'",
-"Ne peut obtenir le status de '%-.64s' (Errcode: %d)",
-"Ne peut obtenir le répertoire de travail (Errcode: %d)",
-"Ne peut verrouiller le fichier (Errcode: %d)",
-"Ne peut ouvrir le fichier: '%-.64s' (Errcode: %d)",
-"Ne peut trouver le fichier: '%-.64s' (Errcode: %d)",
-"Ne peut lire le répertoire de '%-.64s' (Errcode: %d)",
-"Ne peut changer le répertoire pour '%-.64s' (Errcode: %d)",
-"Enregistrement modifié depuis sa dernière lecture dans la table '%-.64s'",
-"Disque plein (%s). J'attend que quelqu'un libère de l'espace...",
-"Ecriture impossible, doublon dans une clé de la table '%-.64s'",
-"Erreur a la fermeture de '%-.64s' (Errcode: %d)",
-"Erreur en lecture du fichier '%-.64s' (Errcode: %d)",
-"Erreur en renommant '%-.64s' en '%-.64s' (Errcode: %d)",
-"Erreur d'écriture du fichier '%-.64s' (Errcode: %d)",
-"'%-.64s' est verrouillé contre les modifications",
-"Tri alphabétique abandonné",
-"La vue (View) '%-.64s' n'existe pas pour '%-.64s'",
-"Reçu l'erreur %d du handler de la table",
-"Le handler de la table '%-.64s' n'a pas cette option",
-"Ne peut trouver l'enregistrement dans '%-.64s'",
-"Information erronnée dans le fichier: '%-.64s'",
-"Index corrompu dans la table: '%-.64s'; essayez de le réparer",
-"Vieux fichier d'index pour la table '%-.64s'; réparez le!",
-"'%-.64s' est en lecture seulement",
-"Manque de mémoire. Redémarrez le démon et ré-essayez (%d octets nécessaires)",
-"Manque de mémoire pour le tri. Augmentez-la.",
-"Fin de fichier inattendue en lisant '%-.64s' (Errcode: %d)",
-"Trop de connections",
-"Manque de 'threads'/mémoire",
-"Ne peut obtenir de hostname pour votre adresse",
-"Mauvais 'handshake'",
-"Accès refusé pour l'utilisateur: '%-.32s'@'@%-.64s'. Base '%-.64s'",
-"Accès refusé pour l'utilisateur: '%-.32s'@'@%-.64s' (mot de passe: %s)",
-"Aucune base n'a été sélectionnée",
-"Commande inconnue",
-"Le champ '%-.64s' ne peut être vide (null)",
-"Base '%-.64s' inconnue",
-"La table '%-.64s' existe déjà",
-"Table '%-.64s' inconnue",
-"Champ: '%-.64s' dans %s est ambigu",
-"Arrêt du serveur en cours",
-"Champ '%-.64s' inconnu dans %s",
-"'%-.64s' n'est pas dans 'group by'",
-"Ne peut regrouper '%-.64s'",
-"Vous demandez la fonction sum() et des champs dans la même commande",
-"Column count doesn't match value count",
-"Le nom de l'identificateur '%-.64s' est trop long",
-"Nom du champ '%-.64s' déjà utilisé",
-"Nom de clef '%-.64s' déjà utilisé",
-"Duplicata du champ '%-.64s' pour la clef %d",
-"Mauvais paramètre de champ pour le champ '%-.64s'",
-"%s près de '%-.64s' à la ligne %d",
-"Query est vide",
-"Table/alias: '%-.64s' non unique",
-"Valeur par défaut invalide pour '%-.64s'",
-"Plusieurs clefs primaires définies",
-"Trop de clefs sont définies. Maximum de %d clefs alloué",
-"Trop de parties specifiées dans la clef. Maximum de %d parties",
-"La clé est trop longue. Longueur maximale: %d",
-"La clé '%-.64s' n'existe pas dans la table",
-"Champ BLOB '%-.64s' ne peut être utilisé dans une clé",
-"Champ '%-.64s' trop long (max = %d). Utilisez un BLOB",
-"Un seul champ automatique est permis et il doit être indexé",
-"%s: Prêt pour des connections",
-"%s: Arrêt normal du serveur\n",
-"%s: Reçu le signal %d. Abandonne!\n",
-"%s: Arrêt du serveur terminé\n",
-"%s: Arrêt forcé de la tâche (thread) %ld utilisateur: '%-.64s'\n",
-"Ne peut créer la connection IP (socket)",
-"La table '%-.64s' n'a pas d'index comme celle utilisée dans CREATE INDEX. Recréez la table",
-"Séparateur de champs inconnu. Vérifiez dans le manuel",
-"Vous ne pouvez utiliser des lignes de longueur fixe avec des BLOBs. Utiliser 'fields terminated by'.",
-"Le fichier '%-.64s' doit être dans le répertoire de la base et lisible par tous",
-"Le fichier '%-.64s' existe déjà",
-"Enregistrements: %ld Effacés: %ld Non traités: %ld Avertissements: %ld",
-"Enregistrements: %ld Doublons: %ld",
-"Mauvaise sous-clef. Ce n'est pas un 'string' ou la longueur dépasse celle définie dans la clef",
-"Vous ne pouvez effacer tous les champs avec ALTER TABLE. Utilisez DROP TABLE",
-"Ne peut effacer (DROP) '%-.64s'. Vérifiez s'il existe",
-"Enregistrements: %ld Doublons: %ld Avertissements: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Numéro de tâche inconnu: %lu",
-"Vous n'êtes pas propriétaire de la tâche no: %lu",
-"Aucune table utilisée",
-"Trop de chaînes dans la colonne %s avec SET",
-"Ne peut générer un unique nom de journal %s.(1-999)\n",
-"Table '%-.64s' verrouillée lecture (READ): modification impossible",
-"Table '%-.64s' non verrouillée: utilisez LOCK TABLES",
-"BLOB '%-.64s' ne peut avoir de valeur par défaut",
-"Nom de base de donnée illégal: '%-.64s'",
-"Nom de table illégal: '%-.64s'",
-"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien",
-"Erreur inconnue",
-"Procédure %s inconnue",
-"Mauvais nombre de paramètres pour la procedure %s",
-"Paramètre erroné pour la procedure %s",
-"Table inconnue '%-.64s' dans %s",
-"Champ '%-.64s' spécifié deux fois",
-"Utilisation invalide de la clause GROUP",
-"Table '%-.64s' : utilise une extension invalide pour cette version de MySQL",
-"Une table doit comporter au moins une colonne",
-"La table '%-.64s' est pleine",
-"Jeu de caractères inconnu: '%-.64s'",
-"Trop de tables. MySQL ne peut utiliser que %d tables dans un JOIN",
-"Trop de champs",
-"Ligne trop grande. Le taille maximale d'une ligne, sauf les BLOBs, est %d. Changez le type de quelques colonnes en BLOB",
-"Débordement de la pile des tâches (Thread stack). Utilisées: %ld pour une pile de %ld. Essayez 'mysqld -O thread_stack=#' pour indiquer une plus grande valeur",
-"Dépendance croisée dans une clause OUTER JOIN. Vérifiez la condition ON",
-"La colonne '%-.32s' fait partie d'un index UNIQUE ou INDEX mais n'est pas définie comme NOT NULL",
-"Imposible de charger la fonction '%-.64s'",
-"Impossible d'initialiser la fonction '%-.64s'; %-.80s",
-"Chemin interdit pour les bibliothèques partagées",
-"La fonction '%-.64s' existe déjà",
-"Impossible d'ouvrir la bibliothèque partagée '%-.64s' (errno: %d %s)",
-"Impossible de trouver la fonction '%-.64s' dans la bibliothèque'",
-"La fonction '%-.64s' n'est pas définie",
-"L'hôte '%-.64s' est bloqué à cause d'un trop grand nombre d'erreur de connection. Débloquer le par 'mysqladmin flush-hosts'",
-"Le hôte '%-.64s' n'est pas authorisé à se connecter à ce serveur MySQL",
-"Vous utilisez un utilisateur anonyme et les utilisateurs anonymes ne sont pas autorisés à changer les mots de passe",
-"Vous devez avoir le privilège update sur les tables de la base de donnée mysql pour pouvoir changer les mots de passe des autres",
-"Impossible de trouver un enregistrement correspondant dans la table user",
-"Enregistrements correspondants: %ld Modifiés: %ld Warnings: %ld",
-"Impossible de créer une nouvelle tâche (errno %d). S'il reste de la mémoire libre, consultez le manual pour trouver un éventuel bug dépendant de l'OS",
-"Column count doesn't match value count at row %ld",
-"Impossible de réouvrir la table: '%-.64s",
-"Utilisation incorrecte de la valeur NULL",
-"Erreur '%-.64s' provenant de regexp",
-"Mélanger les colonnes GROUP (MIN(),MAX(),COUNT()...) avec des colonnes normales est interdit s'il n'y a pas de clause GROUP BY",
-"Un tel droit n'est pas défini pour l'utilisateur '%-.32s' sur l'hôte '%-.64s'",
-"La commande '%-.16s' est interdite à l'utilisateur: '%-.32s'@'@%-.64s' sur la table '%-.64s'",
-"La commande '%-.16s' est interdite à l'utilisateur: '%-.32s'@'@%-.64s' sur la colonne '%-.64s' de la table '%-.64s'",
-"Commande GRANT/REVOKE incorrecte. Consultez le manuel.",
-"L'hôte ou l'utilisateur donné en argument à GRANT est trop long",
-"La table '%-.64s.%s' n'existe pas",
-"Un tel droit n'est pas défini pour l'utilisateur '%-.32s' sur l'hôte '%-.64s' sur la table '%-.64s'",
-"Cette commande n'existe pas dans cette version de MySQL",
-"Erreur de syntaxe",
-"La tâche 'delayed insert' n'a pas pu obtenir le verrou démandé sur la table %-.64s",
-"Trop de tâche 'delayed' en cours",
-"Connection %ld avortée vers la bd: '%-.64s' utilisateur: '%-.64s' (%s)",
-"Paquet plus grand que 'max_allowed_packet' reçu",
-"Erreur de lecture reçue du pipe de connection",
-"Erreur reçue de fcntl() ",
-"Paquets reçus dans le désordre",
-"Impossible de décompresser le paquet reçu",
-"Erreur de lecture des paquets reçus",
-"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'",
-"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",
-"Nom de colonne '%-.100s' incorrect",
-"Le handler de la table ne peut indexé la colonne '%-.64s'",
-"Toutes les tables de la table de type MERGE n'ont pas la même définition",
-"Écriture impossible à cause d'un index UNIQUE sur la table '%-.64s'",
-"La colonne '%-.64s' de type BLOB est utilisée dans une définition d'index sans longueur d'index",
-"Toutes les parties d'un index PRIMARY KEY doivent être NOT NULL; Si vous avez besoin d'un NULL dans l'index, utilisez un index UNIQUE",
-"Le résultat contient plus d'un enregistrement",
-"Ce type de table nécessite une clé primaire (PRIMARY KEY)",
-"Cette version de MySQL n'est pas compilée avec le support RAID",
-"Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index",
-"L'index '%-.64s' n'existe pas sur la table '%-.64s'",
-"Impossible d'ouvrir la table",
-"Ce type de table ne supporte pas les %s",
-"Vous n'êtes pas autorisé à exécute cette commande dans une transaction",
-"Erreur %d lors du COMMIT",
-"Erreur %d lors du ROLLBACK",
-"Erreur %d lors du FLUSH_LOGS",
-"Erreur %d lors du CHECKPOINT",
-"Connection %ld avortée vers la bd: '%-.64s' utilisateur: '%-.32s' hôte: `%-.64s' (%-.64s)",
-"Ce type de table ne supporte pas les copies binaires",
-"Le 'binlog' a été fermé pendant l'exécution du FLUSH MASTER",
-"La reconstruction de l'index de la table copiée '%-.64s' a échoué",
-"Erreur reçue du maître: '%-.64s'",
-"Erreur de lecture réseau reçue du maître",
-"Erreur d'écriture réseau reçue du maître",
-"Impossible de trouver un index FULLTEXT correspondant à cette liste de colonnes",
-"Impossible d'exécuter la commande car vous avez des tables verrouillées ou une transaction active",
-"Variable système '%-.64s' inconnue",
-"La table '%-.64s' est marquée 'crashed' et devrait être réparée",
-"La table '%-.64s' est marquée 'crashed' et le dernier 'repair' a échoué",
-"Attention: certaines tables ne supportant pas les transactions ont été changées et elles ne pourront pas être restituées",
-"Cette transaction à commandes multiples nécessite plus de 'max_binlog_cache_size' octets de stockage, augmentez cette variable de mysqld et réessayez",
-"Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord",
-"Cette opération nécessite un esclave actif, configurez les esclaves et faites START SLAVE",
-"Le server n'est pas configuré comme un esclave, changez le fichier de configuration ou utilisez CHANGE MASTER TO",
-"Impossible d'initialiser les structures d'information de maître, vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MySQL",
-"Impossible de créer une tâche esclave, vérifiez les ressources système",
-"L'utilisateur %-.64s possède déjà plus de 'max_user_connections' connections actives",
-"Seules les expressions constantes sont autorisées avec SET",
-"Timeout sur l'obtention du verrou",
-"Le nombre total de verrou dépasse la taille de la table des verrous",
-"Un verrou en update ne peut être acquit pendant une transaction READ UNCOMMITTED",
-"DROP DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture",
-"CREATE DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture",
-"Mauvais arguments à %s",
-"'%-.32s'@'%-.64s' n'est pas autorisé à créer de nouveaux utilisateurs",
-"Définition de table incorrecte; toutes les tables MERGE doivent être dans la même base de donnée",
-"Deadlock découvert en essayant d'obtenir les verrous : essayez de redémarrer la transaction",
-"Le type de table utilisé ne supporte pas les index FULLTEXT",
-"Impossible d'ajouter des contraintes d'index externe",
-"Impossible d'ajouter un enregistrement fils : une constrainte externe l'empèche",
-"Impossible de supprimer un enregistrement père : une constrainte externe l'empèche",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
deleted file mode 100644
index c3d00ae06b4..00000000000
--- a/sql/share/german/errmsg.txt
+++ /dev/null
@@ -1,335 +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 */
-
-/*
- Dirk Munzinger (dmun@4t2.com)
- 2001-06-07
-
- Georg Richter (georg@php.net)
- fixed typos and translation
- translated new error messages
- 2002-12-11
-
- Stefan Hinz (stefan@mysql.com)
- 2003-10-01
-*/
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"Nein",
-"Ja",
-"Kann Datei '%-.64s' nicht erzeugen (Fehler: %d)",
-"Kann Tabelle '%-.64s' nicht erzeugen (Fehler: %d)",
-"Kann Datenbank '%-.64s' nicht erzeugen (Fehler: %d)",
-"Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits",
-"Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden",
-"Fehler beim Löschen der Datenbank ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)",
-"Fehler beim Löschen der Datenbank (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)",
-"Fehler beim Löschen von '%-.64s' (Fehler: %d)",
-"Datensatz in der Systemtabelle nicht lesbar",
-"Kann Status von '%-.64s' nicht ermitteln (Fehler: %d)",
-"Kann Arbeitsverzeichnis nicht ermitteln (Fehler: %d)",
-"Datei kann nicht gesperrt werden (Fehler: %d)",
-"Datei '%-.64s' nicht öffnen (Fehler: %d)",
-"Kann Datei '%-.64s' nicht finden (Fehler: %d)",
-"Verzeichnis von '%-.64s' nicht lesbar (Fehler: %d)",
-"Kann nicht in das Verzeichnis '%-.64s' wechseln (Fehler: %d)",
-"Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%-.64s' geändert",
-"Festplatte voll (%-.64s). Warte, bis jemand Platz schafft ...",
-"Kann nicht speichern, Grund: doppelter Schlüssel in Tabelle '%-.64s'",
-"Fehler beim Schließen von '%-.64s' (Fehler: %d)",
-"Fehler beim Lesen der Datei '%-.64s' (Fehler: %d)",
-"Fehler beim Umbenennen von '%-.64s' in '%-.64s' (Fehler: %d)",
-"Fehler beim Speichern der Datei '%-.64s' (Fehler: %d)",
-"'%-.64s' ist für Änderungen gesperrt",
-"Sortiervorgang abgebrochen",
-"View '%-.64s' existiert für '%-.64s' nicht",
-"Fehler %d (Tabellenhandler)",
-"Diese Option gibt es nicht (Tabellenhandler)",
-"Kann Datensatz nicht finden",
-"Falsche Information in Datei '%-.64s'",
-"Falsche Schlüssel-Datei für Tabelle '%-.64s'. versuche zu reparieren",
-"Alte Schlüssel-Datei für Tabelle '%-.64s'. Bitte reparieren",
-"'%-.64s' ist nur lesbar",
-"Kein Speicher vorhanden (%d Bytes benötigt). Bitte Server neu starten",
-"Kein Speicher zum Sortieren vorhanden. sort_buffer_size sollte erhöht werden",
-"Unerwartetes Ende beim Lesen der Datei '%-.64s' (Fehler: %d)",
-"Zu viele Verbindungen",
-"Kein Speicher mehr vorhanden. Prüfen Sie, ob mysqld oder ein anderer Prozess allen Speicher verbraucht. Wenn nicht, sollten Sie mit 'ulimit' dafür sorgen, dass mysqld mehr Speicher benutzen darf, oder mehr Swap-Speicher einrichten",
-"Kann Hostnamen für diese Adresse nicht erhalten",
-"Schlechter Handshake",
-"Benutzer '%-.32s'@'%-.64s' hat keine Zugriffsberechtigung für Datenbank '%-.64s'",
-"Benutzer '%-.32s'@'%-.64s' hat keine Zugriffsberechtigung (verwendetes Passwort: %-.64s)",
-"Keine Datenbank ausgewählt",
-"Unbekannter Befehl",
-"Feld '%-.64s' darf nicht NULL sein",
-"Unbekannte Datenbank '%-.64s'",
-"Tabelle '%-.64s' bereits vorhanden",
-"Unbekannte Tabelle '%-.64s'",
-"Spalte '%-.64s' in %-.64s ist nicht eindeutig",
-"Der Server wird heruntergefahren",
-"Unbekanntes Tabellenfeld '%-.64s' in %-.64s",
-"'%-.64s' ist nicht in GROUP BY vorhanden",
-"Gruppierung über '%-.64s' nicht möglich",
-"Die Verwendung von Summierungsfunktionen und Spalten im selben Befehl ist nicht erlaubt",
-"Die Anzahl der Spalten entspricht nicht der Anzahl der Werte",
-"Name des Bezeichners '%-.64s' ist zu lang",
-"Doppelter Spaltenname vorhanden: '%-.64s'",
-"Doppelter Name für Schlüssel (Key) vorhanden: '%-.64s'",
-"Doppelter Eintrag '%-.64s' für Schlüssel %d",
-"Falsche Spaltenangaben für Spalte '%-.64s'",
-"%s bei '%-.80s' in Zeile %d",
-"Leere Abfrage",
-"Tabellenname/Alias '%-.64s' nicht eindeutig",
-"Fehlerhafter Vorgabewert (DEFAULT): '%-.64s'",
-"Mehrfacher Primärschlüssel (PRIMARY KEY) definiert",
-"Zu viele Schlüssel definiert. Maximal %d Schlüssel erlaubt",
-"Zu viele Teilschlüssel definiert. Maximal sind %d Teilschlüssel erlaubt",
-"Schlüssel ist zu lang. Die maximale Schlüssellänge beträgt %d",
-"In der Tabelle gibt es keine Schlüsselspalte '%-.64s'",
-"BLOB-Feld '%-.64s' kann beim verwendeten Tabellentyp nicht als Schlüssel verwendet werden",
-"Feldlänge für Feld '%-.64s' zu groß (maximal %d). BLOB-Feld verwenden!",
-"Falsche Tabellendefinition. Es darf nur ein Auto-Feld geben und dieses muss als Schlüssel definiert werden",
-"%-.64s: Bereit für Verbindungen",
-"%-.64s: Normal heruntergefahren\n",
-"%-.64s: Signal %d erhalten. Abbruch!\n",
-"%-.64s: Heruntergefahren (shutdown)\n",
-"%s: Thread %ld zwangsweise beendet. Benutzer: '%-.32s'\n",
-"Kann IP-Socket nicht erzeugen",
-"Tabelle '%-.64s' besitzt keinen wie den in CREATE INDEX verwendeten Index. Index neu anlegen",
-"Feldbegrenzer-Argument ist nicht in der erwarteten Form. Bitte im Handbuch nachlesen",
-"Eine feste Zeilenlänge kann für BLOB-Felder nicht verwendet werden. Bitte 'fields terminated by' verwenden",
-"Datei '%-.64s' muss im Datenbank-Verzeichnis vorhanden und lesbar für alle sein",
-"Datei '%-.64s' bereits vorhanden",
-"Datensätze: %ld Gelöscht: %ld Ausgelassen: %ld Warnungen: %ld",
-"Datensätze: %ld Duplikate: %ld",
-"Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder der Tabellenhandler unterstützt keine Unterteilschlüssel",
-"Mit ALTER TABLE können nicht alle Felder auf einmal gelöscht werden. Dafür DROP TABLE verwenden",
-"Kann '%-.64s' nicht löschen. Existiert das Feld / der Schlüssel?",
-"Datensätze: %ld Duplikate: %ld Warnungen: %ld",
-"Die Verwendung der zu aktualisierenden Zieltabelle '%-.64s' ist in der FROM-Klausel nicht zulässig.",
-"Unbekannte Thread-ID: %lu",
-"Sie sind nicht Eigentümer von Thread %lu",
-"Keine Tabellen verwendet",
-"Zu viele Strings für SET-Spalte %-.64s angegeben",
-"Kann keinen eindeutigen Dateinamen für die Logdatei %-.64s erzeugen (1-999)\n",
-"Tabelle '%-.64s' ist mit Lesesperre versehen und kann nicht aktualisiert werden",
-"Tabelle '%-.64s' wurde nicht mit LOCK TABLES gesperrt",
-"BLOB-Feld '%-.64s' darf keinen Vorgabewert (DEFAULT) haben",
-"Unerlaubter Datenbankname '%-.64s'",
-"Unerlaubter Tabellenname '%-.64s'",
-"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange dauern. Bitte WHERE-Klausel überprüfen oder gegebenenfalls SET SQL_BIG_SELECTS=1 oder SET SQL_MAX_JOIN_SIZE=# verwenden",
-"Unbekannter Fehler",
-"Unbekannte Prozedur '%-.64s'",
-"Falsche Parameterzahl für Prozedur '%-.64s'",
-"Falsche Parameter für Prozedur '%-.64s'",
-"Unbekannte Tabelle '%-.64s' in '%-.64s'",
-"Feld '%-.64s' wurde zweimal angegeben",
-"Falsche Verwendung einer Gruppierungsfunktion",
-"Tabelle '%-.64s' verwendet eine Extension, die in dieser MySQL-Version nicht verfügbar ist",
-"Eine Tabelle muß mindestens 1 Spalte besitzen",
-"Tabelle '%-.64s' ist voll",
-"Unbekannter Zeichensatz: '%-.64s'",
-"Zu viele Tabellen. MySQL kann in einem Join maximal %d Tabellen verwenden",
-"Zu viele Spalten",
-"Zeilenlänge zu groß. Die maximale Spaltenlänge für den verwendeten Tabellentyp (ohne BLOB-Felder) beträgt %d. Einige Felder müssen in BLOB oder TEXT umgewandelt werden",
-"Thread-Stack-Überlauf. Benutzt: %ld von %ld Stack. 'mysqld -O thread_stack=#' verwenen, um notfalls einen größeren Stack anzulegen",
-"OUTER JOIN enthält fehlerhafte Abhängigkeiten. In ON verwendete Bedingungen überprüfen",
-"Spalte '%-.64s' wurde mit UNIQUE oder INDEX benutzt, ist aber nicht als NOT NULL definiert",
-"Kann Funktion '%-.64s' nicht laden",
-"Kann Funktion '%-.64s' nicht initialisieren: %-.80s",
-"Keine Pfade gestattet für Shared Library",
-"Funktion '%-.64s' existiert schon",
-"Kann Shared Library '%-.64s' nicht öffnen (Fehler: %d %-.64s)",
-"Kann Funktion '%-.64s' in der Library nicht finden",
-"Funktion '%-.64s' ist nicht definiert",
-"Host '%-.64s' blockiert wegen zu vieler Verbindungsfehler. Aufheben der Blockierung mit 'mysqladmin flush-hosts'",
-"Host '%-.64s' hat keine Berechtigung, sich mit diesem MySQL-Server zu verbinden",
-"Sie benutzen MySQL als anonymer Benutzer und dürfen daher keine Passwörter ändern",
-"Sie benötigen die Berechtigung zum Aktualisieren von Tabellen in der Datenbank 'mysql', um die Passwörter anderer Benutzer ändern zu können",
-"Kann keinen passenden Datensatz in Tabelle 'user' finden",
-"Datensätze gefunden: %ld Geändert: %ld Warnungen: %ld",
-"Kann keinen neuen Thread erzeugen (Fehler: %d). Sollte noch Speicher verfügbar sein, bitte im Handbuch wegen möglicher Fehler im Betriebssystem nachschlagen",
-"Anzahl der Spalten stimmt nicht mit der Anzahl der Werte in Zeile %ld überein",
-"Kann Tabelle'%-.64s' nicht erneut öffnen",
-"Unerlaubte Verwendung eines NULL-Werts",
-"regexp lieferte Fehler '%-.64s'",
-"Das Vermischen von GROUP-Spalten (MIN(),MAX(),COUNT()...) mit Nicht-GROUP-Spalten ist nicht zulässig, wenn keine GROUP BY-Klausel vorhanden ist",
-"Für Benutzer '%-.32s' auf Host '%-.64s' gibt es keine solche Berechtigung",
-"%-.16s Befehl nicht erlaubt für Benutzer '%-.32s'@'%-.64s' und für Tabelle '%-.64s'",
-"%-.16s Befehl nicht erlaubt für Benutzer '%-.32s'@'%-.64s' und Spalte '%-.64s' in Tabelle '%-.64s'",
-"Unzulässiger GRANT- oder REVOKE-Befehl. Verfügbare Berechtigungen sind im Handbuch aufgeführt",
-"Das Host- oder User-Argument für GRANT ist zu lang",
-"Tabelle '%-.64s.%-.64s' existiert nicht",
-"Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s' an Tabelle '%-.64s'",
-"Der verwendete Befehl ist in dieser MySQL-Version nicht zulässig",
-"Fehler in der SQL-Syntax. Bitte die korrekte Syntax im Handbuch nachschlagen (diese kann für verschiedene Server-Versionen unterschiedlich sein)",
-"Verzögerter (DELAYED) Einfüge-Thread konnte die angeforderte Sperre für Tabelle '%-.64s' nicht erhalten",
-"Zu viele verzögerte (DELAYED) Threads in Verwendung",
-"Abbruch der Verbindung %ld zur Datenbank '%-.64s'. Benutzer: '%-.64s' (%-.64s)",
-"Empfangenes Paket ist größer als 'max_allowed_packet'",
-"Lese-Fehler bei einer Kommunikations-Pipe",
-"fcntl() lieferte einen Fehler",
-"Pakete nicht in der richtigen Reihenfolge empfangen",
-"Kommunikationspaket lässt sich nicht entpacken",
-"Fehler beim Lesen eines Kommunikationspakets",
-"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'",
-"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",
-"Falscher Spaltenname '%-.100s'",
-"Der verwendete Tabellen-Handler kann die Spalte '%-.64s' nicht indizieren",
-"Nicht alle Tabellen in der MERGE-Tabelle sind gleich definiert",
-"Schreiben in Tabelle '%-.64s' nicht möglich wegen einer eindeutigen Beschränkung (unique constraint)",
-"BLOB- oder TEXT-Spalte '%-.64s' wird in der Schlüsseldefinition ohne Schlüssellängenangabe verwendet",
-"Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein. Wenn NULL in einem Schlüssel verwendet wird, muss ein UNIQUE-Schlüssel verwendet werden",
-"Ergebnis besteht aus mehr als einer Zeile",
-"Dieser Tabellentyp benötigt einen PRIMARY KEY",
-"Diese MySQL-Version ist nicht mit RAID-Unterstützung kompiliert",
-"MySQL läuft im sicheren Aktualisierungsmodus (safe update mode). Sie haben versucht, eine Tabelle zu aktualisieren, ohne in der WHERE-Klausel eine KEY-Spalte anzugeben",
-"Schlüssel '%-.64s' existiert in der Tabelle '%-.64s' nicht",
-"Kann Tabelle nicht öffnen",
-"Die Speicher-Engine für diese Tabelle unterstützt kein %s",
-"Sie dürfen diesen Befehl nicht in einer Transaktion ausführen",
-"Fehler %d beim COMMIT",
-"Fehler %d beim ROLLBACK",
-"Fehler %d bei FLUSH_LOGS",
-"Fehler %d bei CHECKPOINT",
-"Verbindungsabbruch %ld zur Datenbank '%-.64s'. Benutzer: '%-.32s', Host: `%-.64s' (%-.64s)",
-"Die Speicher-Engine für die Tabelle unterstützt keinen binären Tabellen-Dump",
-"Binlog geschlossen. Kann RESET MASTER nicht ausführen",
-"Neuerstellung des Indizes der Dump-Tabelle '%-.64s' fehlgeschlagen",
-"Fehler vom Master: '%-.64s'",
-"Netzfehler beim Lesen vom Master",
-"Netzfehler beim Schreiben zum Master",
-"Kann keinen FULLTEXT-Index finden, der der Spaltenliste entspricht",
-"Kann den angegebenen Befehl wegen einer aktiven Tabellensperre oder einer aktiven Transaktion nicht ausführen",
-"Unbekannte Systemvariable '%-.64s'",
-"Tabelle '%-.64s' ist als defekt markiert und sollte repariert werden",
-"Tabelle '%-.64s' ist als defekt markiert und der letzte (automatische?) Reparaturversuch schlug fehl",
-"Änderungen an einigen nicht transaktionalen Tabellen konnten nicht zurückgerollt werden",
-"Transaktionen, die aus mehreren Befehlen bestehen, benötigen mehr als 'max_binlog_cache_size' Bytes an Speicher. Diese mysqld-Variable bitte vergrössern und erneut versuchen",
-"Diese Operation kann nicht bei einem aktiven Slave durchgeführt werden. Bitte zuerst STOP SLAVE ausführen",
-"Diese Operation benötigt einen aktiven Slave. Bitte Slave konfigurieren und mittels START SLAVE aktivieren",
-"Der Server ist nicht als Slave konfiguriert. Bitte in der Konfigurationsdatei oder mittels CHANGE MASTER TO beheben",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Konnte keinen Slave-Thread starten. Bitte System-Ressourcen überprüfen",
-"Benutzer '%-.64s' hat mehr als max_user_connections aktive Verbindungen",
-"Bei SET dürfen nur konstante Ausdrücke verwendet werden",
-"Beim Warten auf eine Sperre wurde die zulässige Wartezeit überschritten. Bitte versuchen Sie, die Transaktion neu zu starten",
-"Die Gesamtzahl der Sperren überschreitet die Größe der Sperrtabelle",
-"Während einer READ UNCOMMITED-Transaktion können keine UPDATE-Sperren angefordert werden",
-"DROP DATABASE ist nicht erlaubt, solange der Thread eine globale Lesesperre hält",
-"CREATE DATABASE ist nicht erlaubt, solange der Thread eine globale Lesesperre hält",
-"Falsche Argumente für %s",
-"'%-.32s'@'%-.64s' is nicht berechtigt, neue Benutzer hinzuzufügen",
-"Falsche Tabellendefinition. Alle MERGE-Tabellen müssen sich in derselben Datenbank befinden",
-"Beim Versuch, eine Sperre anzufordern, ist ein Deadlock aufgetreten. Versuchen Sie, die Transaktion erneut zu starten",
-"Der verwendete Tabellentyp unterstützt keine FULLTEXT-Indizes",
-"Fremdschlüssel-Beschränkung konnte nicht hinzugefügt werden",
-"Hinzufügen eines Kind-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl",
-"Löschen eines Eltern-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl",
-"Fehler bei der Verbindung zum Master: %-.128s",
-"Beim Ausführen einer Abfrage auf dem Master trat ein Fehler auf: %-.128s",
-"Fehler beim Ausführen des Befehls %s: %-.128s",
-"Falsche Verwendung von %s und %s",
-"Die verwendeten SELECT-Befehle liefern eine unterschiedliche Anzahl von Spalten zurück",
-"Augrund eines READ LOCK-Konflikts kann die Abfrage nicht ausgeführt werden",
-"Die gleichzeitige Verwendung von Tabellen mit und ohne Transaktionsunterstützung ist deaktiviert",
-"Option '%s' wird im Befehl zweimal verwendet",
-"Benutzer '%-.64s' hat die Ressourcenbeschränkung '%s' überschritten (aktueller Wert: %ld)",
-"Befehl nicht zulässig. Hierfür wird die Berechtigung %-.128s benötigt",
-"Variable '%-.64s' ist eine lokale Variable und kann nicht mit SET GLOBAL verändert werden",
-"Variable '%-.64s' ist eine globale Variable und muss mit SET GLOBAL verändert werden",
-"Variable '%-.64s' hat keinen Vorgabewert",
-"Variable '%-.64s' kann nicht auf '%-.64s' gesetzt werden",
-"Falscher Argumenttyp für Variable '%-.64s'",
-"Variable '%-.64s' kann nur verändert, nicht gelesen werden",
-"Falsche Verwendung oder Platzierung von '%s'",
-"Diese MySQL-Version unterstützt '%s' nicht",
-"Schwerer Fehler %d: '%-.128s vom Master beim Lesen des binären Logs aufgetreten",
-"Slave-SQL-Thread hat die Abfrage aufgrund von replicate-*-table-Regeln ignoriert",
-"Variable '%-.64s' is a %s variable",
-"Falsche Fremdschlüssel-Definition für '%-64s': %s",
-"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 (%.*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",
-"Verweis '%-.64s' wird nicht unterstützt (%s)",
-"Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden",
-"Select %u wurde während der Optimierung reduziert",
-"Tabelle '%-.64s', die in einem der SELECT-Befehle verwendet wurde, kann nicht in %-.32s verwendet werden",
-"Client unterstützt das vom Server erwartete Authentifizierungsprotokoll nicht. Bitte aktualisieren Sie Ihren MySQL-Client",
-"Alle Teile eines SPATIAL KEY müssen als NOT NULL deklariert sein",
-"COLLATION '%s' ist für CHARACTER SET '%s' ungültig",
-"Slave läuft bereits",
-"Slave wurde bereits angehalten",
-"Unkomprimierte Daten sind zu groß. Die maximale Größe beträgt %d",
-"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",
-"Daten abgeschnitten, außerhalb des Wertebereichs für Spalte '%s' in Zeile %ld",
-"Daten abgeschnitten für Spalte '%s' in Zeile %ld",
-"Für Tabelle '%s' wird Speicher-Engine %s benutzt",
-"Unerlaubte Vermischung der Kollationen (%s,%s) und (%s,%s) für die Operation '%s'",
-"Kann einen oder mehrere der angegebenen Benutzer nicht löschen",
-"Kann nicht alle Berechtigungen widerrufen, grant for one or more of the requested users",
-"Unerlaubte Vermischung der Kollationen (%s,%s), (%s,%s), (%s,%s) für die Operation '%s'",
-"Unerlaubte Vermischung der Kollationen für die Operation '%s'",
-"Variable '%-.64s' ist keine Variablen-Komponenten (kann nicht als XXXX.variablen_name verwendet werden)",
-"Unbekannte Kollation: '%-.64s'",
-"SSL-Parameter in CHANGE MASTER werden ignoriert, weil dieser MySQL-Slave ohne SSL-Unterstützung kompiliert wurde. Sie können aber später verwendet werden, wenn der MySQL-Slave mit SSL gestartet wird",
-"Server läuft im Modus --secure-auth, aber '%s'@'%s' hat ein Passwort im alten Format. Bitte Passwort ins neue Format ändern",
-"Feld oder Verweis '%-.64s%s%-.64s%s%-.64s' im SELECT-Befehl Nr. %d wurde im SELECT-Befehl Nr. %d aufgelöst",
-"Falscher Parameter oder falsche Kombination von Parametern für START SLAVE UNTIL",
-"Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn der Slave-Server unerwartet neu startet",
-"SQL-Thread soll nicht gestartet werden. Daher werden UNTIL-Optionen ignoriert",
-"Incorrect index name '%-.100s'",
-"Incorrect catalog name '%-.100s'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
deleted file mode 100644
index 979091a566c..00000000000
--- a/sql/share/greek/errmsg.txt
+++ /dev/null
@@ -1,322 +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 */
-
-character-set=greek
-
-"hashchk",
-"isamchk",
-"Ï×É",
-"ÍÁÉ",
-"Áäýíáôç ç äçìéïõñãßá ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Áäýíáôç ç äçìéïõñãßá ôïõ ðßíáêá '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.64s'; Ç âÜóç äåäïìÝíùí õðÜñ÷åé Þäç",
-"Áäýíáôç ç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí '%-.64s'. Ç âÜóç äåäïìÝíùí äåí õðÜñ÷åé",
-"ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ '%-.64s', êùäéêüò ëÜèïõò: %d)",
-"ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ ôïõ öáêÝëëïõ '%-.64s', êùäéêüò ëÜèïõò: %d)",
-"ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Áäýíáôç ç áíÜãíùóç åããñáöÞò áðü ðßíáêá ôïõ óõóôÞìáôïò",
-"Áäýíáôç ç ëÞøç ðëçñïöïñéþí ãéá ôçí êáôÜóôáóç ôïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Ï öÜêåëëïò åñãáóßáò äåí âñÝèçêå (êùäéêüò ëÜèïõò: %d)",
-"Ôï áñ÷åßï äåí ìðïñåß íá êëåéäùèåß (êùäéêüò ëÜèïõò: %d)",
-"Äåí åßíáé äõíáôü íá áíïé÷ôåß ôï áñ÷åßï: '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Äåí âñÝèçêå ôï áñ÷åßï: '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Äåí åßíáé äõíáôü íá äéáâáóôåß ï öÜêåëëïò ôïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Áäýíáôç ç áëëáãÞ ôïõ ôñÝ÷ïíôïò êáôáëüãïõ óå '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Ç åããñáöÞ Ý÷åé áëëÜîåé áðü ôçí ôåëåõôáßá öïñÜ ðïõ áíáóýñèçêå áðü ôïí ðßíáêá '%-.64s'",
-"Äåí õðÜñ÷åé ÷þñïò óôï äßóêï (%s). Ðáñáêáëþ, ðåñéìÝíåôå íá åëåõèåñùèåß ÷þñïò...",
-"Äåí åßíáé äõíáôÞ ç êáôá÷þñçóç, ç ôéìÞ õðÜñ÷åé Þäç óôïí ðßíáêá '%-.64s'",
-"ÐáñïõóéÜóôçêå ðñüâëçìá êëåßíïíôáò ôï '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Ðñüâëçìá êáôÜ ôçí áíÜãíùóç ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Ðñüâëçìá êáôÜ ôçí ìåôïíïìáóßá ôïõ áñ÷åßïõ '%-.64s' to '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"Ðñüâëçìá êáôÜ ôçí áðïèÞêåõóç ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"'%-.64s' äåí åðéôñÝðïíôáé áëëáãÝò",
-"Ç äéáäéêáóßá ôáîéíüìéóçò áêõñþèçêå",
-"Ôï View '%-.64s' äåí õðÜñ÷åé ãéá '%-.64s'",
-"ÅëÞöèç ìÞíõìá ëÜèïõò %d áðü ôïí ÷åéñéóôÞ ðßíáêá (table handler)",
-"Ï ÷åéñéóôÞò ðßíáêá (table handler) ãéá '%-.64s' äåí äéáèÝôåé áõôÞ ôçí åðéëïãÞ",
-"Áäýíáôç ç áíåýñåóç åããñáöÞò óôï '%-.64s'",
-"ËÜèïò ðëçñïöïñßåò óôï áñ÷åßï: '%-.64s'",
-"ËÜèïò áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá: '%-.64s'; Ðáñáêáëþ, äéïñèþóôå ôï!",
-"Ðáëáéü áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá '%-.64s'; Ðáñáêáëþ, äéïñèþóôå ôï!",
-"'%-.64s' åðéôñÝðåôáé ìüíï ç áíÜãíùóç",
-"Äåí õðÜñ÷åé äéáèÝóéìç ìíÞìç. ÐñïóðáèÞóôå ðÜëé, åðáíåêéíþíôáò ôç äéáäéêáóßá (demon) (÷ñåéÜæïíôáé %d bytes)",
-"Äåí õðÜñ÷åé äéáèÝóéìç ìíÞìç ãéá ôáîéíüìéóç. ÁõîÞóôå ôï sort buffer size ãéá ôç äéáäéêáóßá (demon)",
-"ÊáôÜ ôç äéÜñêåéá ôçò áíÜãíùóçò, âñÝèçêå áðñïóäüêçôá ôï ôÝëïò ôïõ áñ÷åßïõ '%-.64s' (êùäéêüò ëÜèïõò: %d)",
-"ÕðÜñ÷ïõí ðïëëÝò óõíäÝóåéò...",
-"Ðñüâëçìá ìå ôç äéáèÝóéìç ìíÞìç (Out of thread space/memory)",
-"Äåí Ýãéíå ãíùóôü ôï hostname ãéá ôçí address óáò",
-"Ç áíáãíþñéóç (handshake) äåí Ýãéíå óùóôÜ",
-"Äåí åðéôÝñåôáé ç ðñüóâáóç óôï ÷ñÞóôç: '%-.32s'@'%-.64s' óôç âÜóç äåäïìÝíùí '%-.64s'",
-"Äåí åðéôÝñåôáé ç ðñüóâáóç óôï ÷ñÞóôç: '%-.32s'@'%-.64s' (÷ñÞóç password: %s)",
-"Äåí åðéëÝ÷èçêå âÜóç äåäïìÝíùí",
-"Áãíùóôç åíôïëÞ",
-"Ôï ðåäßï '%-.64s' äåí ìðïñåß íá åßíáé êåíü (null)",
-"Áãíùóôç âÜóç äåäïìÝíùí '%-.64s'",
-"Ï ðßíáêáò '%-.64s' õðÜñ÷åé Þäç",
-"Áãíùóôïò ðßíáêáò '%-.64s'",
-"Ôï ðåäßï: '%-.64s' óå %-.64s äåí Ý÷åé êáèïñéóôåß",
-"Åíáñîç äéáäéêáóßáò áðïóýíäåóçò ôïõ åîõðçñåôçôÞ (server shutdown)",
-"Áãíùóôï ðåäßï '%-.64s' óå '%-.64s'",
-"×ñçóéìïðïéÞèçêå '%-.64s' ðïõ äåí õðÞñ÷å óôï group by",
-"Áäýíáôç ç ïìáäïðïßçóç (group on) '%-.64s'",
-"Ç äéáôýðùóç ðåñéÝ÷åé sum functions êáé columns óôçí ßäéá äéáôýðùóç",
-"Ôï Column count äåí ôáéñéÜæåé ìå ôï value count",
-"Ôï identifier name '%-.100s' åßíáé ðïëý ìåãÜëï",
-"ÅðáíÜëçøç column name '%-.64s'",
-"ÅðáíÜëçøç key name '%-.64s'",
-"ÄéðëÞ åããñáöÞ '%-.64s' ãéá ôï êëåéäß %d",
-"ÅóöáëìÝíï column specifier ãéá ôï ðåäßï '%-.64s'",
-"%s ðëçóßïí '%-.80s' óôç ãñáììÞ %d",
-"Ôï åñþôçìá (query) ðïõ èÝóáôå Þôáí êåíü",
-"Áäýíáôç ç áíåýñåóç unique table/alias: '%-.64s'",
-"ÅóöáëìÝíç ðñïêáèïñéóìÝíç ôéìÞ (default value) ãéá '%-.64s'",
-"Ðåñéóóüôåñá áðü Ýíá primary key ïñßóôçêáí",
-"ÐÜñá ðïëëÜ key ïñßóèçêáí. Ôï ðïëý %d åðéôñÝðïíôáé",
-"ÐÜñá ðïëëÜ key parts ïñßóèçêáí. Ôï ðïëý %d åðéôñÝðïíôáé",
-"Ôï êëåéäß ðïõ ïñßóèçêå åßíáé ðïëý ìåãÜëï. Ôï ìÝãéóôï ìÞêïò åßíáé %d",
-"Ôï ðåäßï êëåéäß '%-.64s' äåí õðÜñ÷åé óôïí ðßíáêá",
-"Ðåäßï ôýðïõ Blob '%-.64s' äåí ìðïñåß íá ÷ñçóéìïðïéçèåß óôïí ïñéóìü åíüò êëåéäéïý (key specification)",
-"Ðïëý ìåãÜëï ìÞêïò ãéá ôï ðåäßï '%-.64s' (max = %d). Ðáñáêáëþ ÷ñçóéìïðïéåßóôå ôïí ôýðï BLOB",
-"Ìðïñåß íá õðÜñ÷åé ìüíï Ýíá auto field êáé ðñÝðåé íá Ý÷åé ïñéóèåß óáí key",
-"%s: óå áíáìïíÞ óõíäÝóåùí",
-"%s: ÖõóéïëïãéêÞ äéáäéêáóßá shutdown\n",
-"%s: ÅëÞöèç ôï ìÞíõìá %d. Ç äéáäéêáóßá åãêáôáëåßðåôáé!\n",
-"%s: Ç äéáäéêáóßá Shutdown ïëïêëçñþèçêå\n",
-"%s: Ôï thread èá êëåßóåé %ld user: '%-.64s'\n",
-"Äåí åßíáé äõíáôÞ ç äçìéïõñãßá IP socket",
-"Ï ðßíáêáò '%-.64s' äåí Ý÷åé åõñåôÞñéï (index) óáí áõôü ðïõ ÷ñçóéìïðïéåßôå óôçí CREATE INDEX. Ðáñáêáëþ, îáíáäçìéïõñãÞóôå ôïí ðßíáêá",
-"Ï äéá÷ùñéóôÞò ðåäßùí äåí åßíáé áõôüò ðïõ áíáìåíüôáí. Ðáñáêáëþ áíáôñÝîôå óôï manual",
-"Äåí ìðïñåßôå íá ÷ñçóéìïðïéÞóåôå fixed rowlength óå BLOBs. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå 'fields terminated by'.",
-"Ôï áñ÷åßï '%-.64s' ðñÝðåé íá õðÜñ÷åé óôï database directory Þ íá ìðïñåß íá äéáâáóôåß áðü üëïõò",
-"Ôï áñ÷åßï '%-.64s' õðÜñ÷åé Þäç",
-"ÅããñáöÝò: %ld ÄéáãñáöÝò: %ld ÐáñåêÜìöèçóáí: %ld ÐñïåéäïðïéÞóåéò: %ld",
-"ÅããñáöÝò: %ld ÅðáíáëÞøåéò: %ld",
-"ÅóöáëìÝíï sub part key. Ôï ÷ñçóéìïðïéïýìåíï key part äåí åßíáé string Þ ôï ìÞêïò ôïõ åßíáé ìåãáëýôåñï",
-"Äåí åßíáé äõíáôÞ ç äéáãñáöÞ üëùí ôùí ðåäßùí ìå ALTER TABLE. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå DROP TABLE",
-"Áäýíáôç ç äéáãñáöÞ (DROP) '%-.64s'. Ðáñáêáëþ åëÝãîôå áí ôï ðåäßï/êëåéäß õðÜñ÷åé",
-"ÅããñáöÝò: %ld ÅðáíáëÞøåéò: %ld ÐñïåéäïðïéÞóåéò: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Áãíùóôï thread id: %lu",
-"Äåí åßóèå owner ôïõ thread %lu",
-"Äåí ÷ñçóéìïðïéÞèçêáí ðßíáêåò",
-"ÐÜñá ðïëëÜ strings ãéá ôï ðåäßï %-.64s êáé SET",
-"Áäýíáôç ç äçìéïõñãßá unique log-filename %-.64s.(1-999)\n",
-"Ï ðßíáêáò '%-.64s' Ý÷åé êëåéäùèåß ìå READ lock êáé äåí åðéôñÝðïíôáé áëëáãÝò",
-"Ï ðßíáêáò '%-.64s' äåí Ý÷åé êëåéäùèåß ìå LOCK TABLES",
-"Ôá Blob ðåäßá '%-.64s' äåí ìðïñïýí íá Ý÷ïõí ðñïêáèïñéóìÝíåò ôéìÝò (default value)",
-"ËÜèïò üíïìá âÜóçò äåäïìÝíùí '%-.100s'",
-"ËÜèïò üíïìá ðßíáêá '%-.100s'",
-"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü",
-"ÐñïÝêõøå Üãíùóôï ëÜèïò",
-"Áãíùóôç äéáäéêáóßá '%-.64s'",
-"ËÜèïò áñéèìüò ðáñáìÝôñùí óôç äéáäéêáóßá '%-.64s'",
-"ËÜèïò ðáñÜìåôñïé óôçí äéáäéêáóßá '%-.64s'",
-"Áãíùóôïò ðßíáêáò '%-.64s' óå %s",
-"Ôï ðåäßï '%-.64s' Ý÷åé ïñéóèåß äýï öïñÝò",
-"ÅóöáëìÝíç ÷ñÞóç ôçò group function",
-"Ï ðßíáêò '%-.64s' ÷ñçóéìïðïéåß êÜðïéï extension ðïõ äåí õðÜñ÷åé óôçí Ýêäïóç áõôÞ ôçò MySQL",
-"Åíáò ðßíáêáò ðñÝðåé íá Ý÷åé ôïõëÜ÷éóôïí Ýíá ðåäßï",
-"Ï ðßíáêáò '%-.64s' åßíáé ãåìÜôïò",
-"Áãíùóôï character set: '%-.64s'",
-"Ðïëý ìåãÜëïò áñéèìüò ðéíÜêùí. Ç MySQL ìðïñåß íá ÷ñçóéìïðïéÞóåé %d ðßíáêåò óå äéáäéêáóßá join",
-"Ðïëý ìåãÜëïò áñéèìüò ðåäßùí",
-"Ðïëý ìåãÜëï ìÝãåèïò åããñáöÞò. Ôï ìÝãéóôï ìÝãåèïò åããñáöÞò, ÷ùñßò íá õðïëïãßæïíôáé ôá blobs, åßíáé %d. ÐñÝðåé íá ïñßóåôå êÜðïéá ðåäßá óáí blobs",
-"Stack overrun óôï thread: Used: %ld of a %ld stack. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå 'mysqld -O thread_stack=#' ãéá íá ïñßóåôå Ýíá ìåãáëýôåñï stack áí ÷ñåéÜæåôáé",
-"Cross dependency âñÝèçêå óå OUTER JOIN. Ðáñáêáëþ åîåôÜóôå ôéò óõíèÞêåò ðïõ èÝóáôå óôï ON",
-"Ôï ðåäßï '%-.64s' ÷ñçóéìïðïéåßôáé óáí UNIQUE Þ INDEX áëëÜ äåí Ý÷åé ïñéóèåß óáí NOT NULL",
-"Äåí åßíáé äõíáôÞ ç äéáäéêáóßá load ãéá ôç óõíÜñôçóç '%-.64s'",
-"Äåí åßíáé äõíáôÞ ç Ýíáñîç ôçò óõíÜñôçóçò '%-.64s'; %-.80s",
-"Äåí âñÝèçêáí paths ãéá ôçí shared library",
-"Ç óõíÜñôçóç '%-.64s' õðÜñ÷åé Þäç",
-"Äåí åßíáé äõíáôÞ ç áíÜãíùóç ôçò shared library '%-.64s' (êùäéêüò ëÜèïõò: %d %s)",
-"Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò óõíÜñôçóçò '%-.64s' óôçí âéâëéïèÞêç'",
-"Ç óõíÜñôçóç '%-.64s' äåí Ý÷åé ïñéóèåß",
-"Ï õðïëïãéóôÞò Ý÷åé áðïêëåéóèåß ëüãù ðïëëáðëþí ëáèþí óýíäåóçò. ÐñïóðáèÞóôå íá äéïñþóåôå ìå 'mysqladmin flush-hosts'",
-"Ï õðïëïãéóôÞò äåí Ý÷åé äéêáßùìá óýíäåóçò ìå ôïí MySQL server",
-"×ñçóéìïðïéåßôå ôçí MySQL óáí anonymous user êáé Ýôóé äåí ìðïñåßôå íá áëëÜîåôå ôá passwords Üëëùí ÷ñçóôþí",
-"ÐñÝðåé íá Ý÷åôå äéêáßùìá äéüñèùóçò ðéíÜêùí (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",
-"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",
-"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 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",
-"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' bytes",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Couldn't uncompress communication packet",
-"Got an error reading communication packets",
-"Got timeout reading communication packets",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
-"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",
-"Incorrect column name '%-.100s'",
-"The used table handler can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
deleted file mode 100644
index 5d32c5b9cc2..00000000000
--- a/sql/share/hungarian/errmsg.txt
+++ /dev/null
@@ -1,327 +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 */
-
-/*
- Translated by Feher Peter. Forditotta Feher Peter (feherp@mail.matav.hu) 1998
- Updated May, 2000
-*/
-
-character-set=latin2
-
-"hashchk",
-"isamchk",
-"NEM",
-"IGEN",
-"A '%-.64s' file nem hozhato letre (hibakod: %d)",
-"A '%-.64s' tabla nem hozhato letre (hibakod: %d)",
-"Az '%-.64s' adatbazis nem hozhato letre (hibakod: %d)",
-"Az '%-.64s' adatbazis nem hozhato letre Az adatbazis mar letezik",
-"A(z) '%-.64s' adatbazis nem szuntetheto meg. Az adatbazis nem letezik",
-"Adatbazis megszuntetesi hiba ('%-.64s' nem torolheto, hibakod: %d)",
-"Adatbazis megszuntetesi hiba ('%-.64s' nem szuntetheto meg, hibakod: %d)",
-"Torlesi hiba: '%-.64s' (hibakod: %d)",
-"Nem olvashato rekord a rendszertablaban",
-"A(z) '%-.64s' statusza nem allapithato meg (hibakod: %d)",
-"A munkakonyvtar nem allapithato meg (hibakod: %d)",
-"A file nem zarolhato. (hibakod: %d)",
-"A '%-.64s' file nem nyithato meg (hibakod: %d)",
-"A(z) '%-.64s' file nem talalhato (hibakod: %d)",
-"A(z) '%-.64s' konyvtar nem olvashato. (hibakod: %d)",
-"Konyvtarvaltas nem lehetseges a(z) '%-.64s'-ba. (hibakod: %d)",
-"A(z) '%-.64s' tablaban talalhato rekord megvaltozott az utolso olvasas ota",
-"A lemez megtelt (%s).",
-"Irasi hiba, duplikalt kulcs a '%-.64s' tablaban.",
-"Hiba a(z) '%-.64s' zarasakor. (hibakod: %d)",
-"Hiba a '%-.64s'file olvasasakor. (hibakod: %d)",
-"Hiba a '%-.64s' file atnevezesekor. (hibakod: %d)",
-"Hiba a '%-.64s' file irasakor. (hibakod: %d)",
-"'%-.64s' a valtoztatas ellen zarolva",
-"Sikertelen rendezes",
-"A(z) '%-.64s' nezet nem letezik a(z) '%-.64s'-hoz",
-"%d hibajelzes a tablakezelotol",
-"A(z) '%-.64s' tablakezelonek nincs ilyen opcioja",
-"Nem talalhato a rekord '%-.64s'-ben",
-"Ervenytelen info a file-ban: '%-.64s'",
-"Ervenytelen kulcsfile a tablahoz: '%-.64s'; probalja kijavitani!",
-"Regi kulcsfile a '%-.64s'tablahoz; probalja kijavitani!",
-"'%-.64s' irasvedett",
-"Nincs eleg memoria. Inditsa ujra a demont, es probalja ismet. (%d byte szukseges.)",
-"Nincs eleg memoria a rendezeshez. Novelje a rendezo demon puffermeretet",
-"Varatlan filevege-jel a '%-.64s'olvasasakor. (hibakod: %d)",
-"Tul sok kapcsolat",
-"Elfogyott a thread-memoria",
-"A gepnev nem allapithato meg a cimbol",
-"A kapcsolatfelvetel nem sikerult (Bad handshake)",
-"A(z) '%-.32s'@'%-.64s' felhasznalo szamara tiltott eleres az '%-.64s' adabazishoz.",
-"A(z) '%-.32s'@'%-.64s' felhasznalo szamara tiltott eleres. (Hasznalja a jelszot: %s)",
-"Nincs kivalasztott adatbazis",
-"Ervenytelen parancs",
-"A(z) '%-.64s' oszlop erteke nem lehet nulla",
-"Ervenytelen adatbazis: '%-.64s'",
-"A(z) '%-.64s' tabla mar letezik",
-"Ervenytelen tabla: '%-.64s'",
-"A(z) '%-.64s' oszlop %-.64s-ben ketertelmu",
-"A szerver leallitasa folyamatban",
-"A(z) '%-.64s' oszlop ervenytelen '%-.64s'-ben",
-"Used '%-.64s' with wasn't in group by",
-"A group nem hasznalhato: '%-.64s'",
-"Statement has sum functions and columns in same statement",
-"Az oszlopban levo ertek nem egyezik meg a szamitott ertekkel",
-"A(z) '%-.100s' azonositonev tul hosszu.",
-"Duplikalt oszlopazonosito: '%-.64s'",
-"Duplikalt kulcsazonosito: '%-.64s'",
-"Duplikalt bejegyzes '%-.64s' a %d kulcs szerint.",
-"Rossz oszlopazonosito: '%-.64s'",
-"A %s a '%-.80s'-hez kozeli a %d sorban",
-"Ures lekerdezes.",
-"Nem egyedi tabla/alias: '%-.64s'",
-"Ervenytelen ertek: '%-.64s'",
-"Tobbszoros elsodleges kulcs definialas.",
-"Tul sok kulcs. Maximum %d kulcs engedelyezett.",
-"Tul sok kulcsdarabot definialt. Maximum %d resz engedelyezett",
-"A megadott kulcs tul hosszu. Maximalis kulcshosszusag: %d",
-"A(z) '%-.64s'kulcsoszlop nem letezik a tablaban",
-"Blob objektum '%-.64s' nem hasznalhato kulcskent",
-"A(z) '%-.64s' oszlop tul hosszu. (maximum = %d). Hasznaljon BLOB tipust inkabb.",
-"Csak egy auto mezo lehetseges, es azt kulcskent kell definialni.",
-"%s: kapcsolatra kesz",
-"%s: Normal leallitas\n",
-"%s: %d jelzes. Megszakitva!\n",
-"%s: A leallitas kesz\n",
-"%s: A(z) %ld thread kenyszeritett zarasa. Felhasznalo: '%-.64s'\n",
-"Az IP socket nem hozhato letre",
-"A(z) '%-.64s' tablahoz nincs meg a CREATE INDEX altal hasznalt index. Alakitsa at a tablat",
-"A mezoelvalaszto argumentumok nem egyeznek meg a varttal. Nezze meg a kezikonyvben!",
-"Fix hosszusagu BLOB-ok nem hasznalhatok. Hasznalja a 'mezoelvalaszto jelet' .",
-"A(z) '%-.64s'-nak az adatbazis konyvtarban kell lennie, vagy mindenki szamara olvashatonak",
-"A '%-.64s' file mar letezik.",
-"Rekordok: %ld Torolve: %ld Skipped: %ld Warnings: %ld",
-"Rekordok: %ld Duplikalva: %ld",
-"Rossz alkulcs. A hasznalt kulcsresz nem karaktersorozat vagy hosszabb, mint a kulcsresz",
-"Az osszes mezo nem torolheto az ALTER TABLE-lel. Hasznalja a DROP TABLE-t helyette",
-"A DROP '%-.64s' nem lehetseges. Ellenorizze, hogy a mezo/kulcs letezik-e",
-"Rekordok: %ld Duplikalva: %ld Warnings: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Ervenytelen szal (thread) id: %lu",
-"A %lu thread-nek mas a tulajdonosa",
-"Nincs hasznalt tabla",
-"Tul sok karakter: %-.64s es SET",
-"Egyedi log-filenev nem generalhato: %-.64s.(1-999)\n",
-"A(z) '%-.64s' tabla zarolva lett (READ lock) es nem lehet frissiteni",
-"A(z) '%-.64s' tabla nincs zarolva a LOCK TABLES-szel",
-"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 okay",
-"Ismeretlen hiba",
-"Ismeretlen eljaras: '%-.64s'",
-"Rossz parameter a(z) '%-.64s'eljaras szamitasanal",
-"Rossz parameter a(z) '%-.64s' eljarasban",
-"Ismeretlen tabla: '%-.64s' %s-ban",
-"A(z) '%-.64s' mezot ketszer definialta",
-"A group funkcio ervenytelen hasznalata",
-"A(z) '%-.64s' tabla olyan bovitest hasznal, amely nem letezik ebben a MySQL versioban.",
-"A tablanak legalabb egy oszlopot tartalmazni kell",
-"A '%-.64s' tabla megtelt",
-"Ervenytelen karakterkeszlet: '%-.64s'",
-"Tul sok tabla. A MySQL csak %d tablat tud kezelni osszefuzeskor",
-"Tul sok mezo",
-"Tul nagy sormeret. A maximalis sormeret (nem szamolva a blob objektumokat) %d. Nehany mezot meg kell valtoztatnia",
-"Thread verem tullepes: Used: %ld of a %ld stack. Hasznalja a 'mysqld -O thread_stack=#' nagyobb verem definialasahoz",
-"Keresztfuggoseg van az OUTER JOIN-ban. Ellenorizze az ON felteteleket",
-"A(z) '%-.64s' oszlop INDEX vagy UNIQUE (egyedi), de a definicioja szerint nem NOT NULL",
-"A(z) '%-.64s' fuggveny nem toltheto be",
-"A(z) '%-.64s' fuggveny nem inicializalhato; %-.80s",
-"Nincs ut a megosztott konyvtarakhoz (shared library)",
-"A '%-.64s' fuggveny mar letezik",
-"A(z) '%-.64s' megosztott konyvtar nem hasznalhato (hibakod: %d %s)",
-"A(z) '%-.64s' fuggveny nem talalhato a konyvtarban",
-"A '%-.64s' fuggveny nem definialt",
-"A '%-.64s' host blokkolodott, tul sok kapcsolodasi hiba miatt. Hasznalja a 'mysqladmin flush-hosts' parancsot",
-"A '%-.64s' host szamara nem engedelyezett a kapcsolodas ehhez a MySQL szerverhez",
-"Nevtelen (anonymous) felhasznalokent nem negedelyezett a jelszovaltoztatas",
-"Onnek tabla-update joggal kell rendelkeznie a mysql adatbazisban masok jelszavanak megvaltoztatasahoz",
-"Nincs megegyezo sor a user tablaban",
-"Megegyezo sorok szama: %ld Valtozott: %ld Warnings: %ld",
-"Uj thread letrehozasa nem lehetseges (Hibakod: %d). Amenyiben van meg szabad memoria, olvassa el a kezikonyv operacios rendszerfuggo hibalehetosegekrol szolo reszet",
-"Az oszlopban talalhato ertek nem egyezik meg a %ld sorban szamitott ertekkel",
-"Nem lehet ujra-megnyitni a tablat: '%-.64s",
-"A NULL ervenytelen hasznalata",
-"'%-.64s' hiba a regularis kifejezes hasznalata soran (regexp)",
-"A GROUP mezok (MIN(),MAX(),COUNT()...) kevert hasznalata nem lehetseges GROUP BY hivatkozas nelkul",
-"A '%-.32s' felhasznalonak nincs ilyen joga a '%-.64s' host-on",
-"%-.16s parancs a '%-.32s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.64s' tablaban",
-"%-.16s parancs a '%-.32s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.64s' mezo eseten a '%-.64s' tablaban",
-"Ervenytelen GRANT/REVOKE parancs. Kerem, nezze meg a kezikonyvben, milyen jogok lehetsegesek",
-"A host vagy felhasznalo argumentuma tul hosszu a GRANT parancsban",
-"A '%-.64s.%s' tabla nem letezik",
-"A '%-.32s' felhasznalo szamara a '%-.64s' host '%-.64s' tablajaban ez a parancs nem engedelyezett",
-"A hasznalt parancs nem engedelyezett ebben a MySQL verzioban",
-"Szintaktikai hiba",
-"A kesleltetett beillesztes (delayed insert) thread nem kapott zatolast a %-.64s tablahoz",
-"Tul sok kesletetett thread (delayed)",
-"Megszakitott kapcsolat %ld db: '%-.64s' adatbazishoz, felhasznalo: '%-.64s' (%s)",
-"A kapott csomag nagyobb, mint a maximalisan engedelyezett: 'max_allowed_packet'",
-"Olvasasi hiba a kapcsolat soran",
-"Hiba a fcntl() fuggvenyben",
-"Helytelen sorrendben erkezett adatcsomagok",
-"A kommunikacios adatcsomagok nem tomorithetok ki",
-"HIba a kommunikacios adatcsomagok olvasasa soran",
-"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'",
-"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)",
-"Ervenytelen mezonev: '%-.100s'",
-"A hasznalt tablakezelo nem tudja a '%-.64s' mezot indexelni",
-"A MERGE tablaban talalhato tablak definicioja nem azonos",
-"A '%-.64s' nem irhato, az egyedi mezok miatt",
-"BLOB mezo '%-.64s' hasznalt a mezo specifikacioban, a mezohossz megadasa nelkul",
-"Az elsodleges kulcs teljes egeszeben csak NOT NULL tipusu lehet; Ha NULL mezot szeretne a kulcskent, hasznalja inkabb a UNIQUE-ot",
-"Az eredmeny tobb, mint egy sort tartalmaz",
-"Az adott tablatipushoz elsodleges kulcs hasznalata kotelezo",
-"Ezen leforditott MySQL verzio nem tartalmaz RAID support-ot",
-"On a biztonsagos update modot hasznalja, es WHERE that uses a KEY column",
-"A '%-.64s' kulcs nem letezik a '%-.64s' tablaban",
-"Nem tudom megnyitni a tablat",
-"A tabla kezeloje (handler) nem tamogatja az %s",
-"Az On szamara nem engedelyezett a parancs vegrehajtasa a tranzakcioban",
-"%d hiba a COMMIT vegrehajtasa soran",
-"%d hiba a ROLLBACK vegrehajtasa soran",
-"%d hiba a FLUSH_LOGS vegrehajtasa soran",
-"%d hiba a CHECKPOINT vegrehajtasa soran",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
deleted file mode 100644
index 556b90511b0..00000000000
--- a/sql/share/italian/errmsg.txt
+++ /dev/null
@@ -1,322 +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 */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NO",
-"SI",
-"Impossibile creare il file '%-.64s' (errno: %d)",
-"Impossibile creare la tabella '%-.64s' (errno: %d)",
-"Impossibile creare il database '%-.64s' (errno: %d)",
-"Impossibile creare il database '%-.64s'; il database esiste",
-"Impossibile cancellare '%-.64s'; il database non esiste",
-"Errore durante la cancellazione del database (impossibile cancellare '%-.64s', errno: %d)",
-"Errore durante la cancellazione del database (impossibile rmdir '%-.64s', errno: %d)",
-"Errore durante la cancellazione di '%-.64s' (errno: %d)",
-"Impossibile leggere il record dalla tabella di sistema",
-"Impossibile leggere lo stato di '%-.64s' (errno: %d)",
-"Impossibile leggere la directory di lavoro (errno: %d)",
-"Impossibile il locking il file (errno: %d)",
-"Impossibile aprire il file: '%-.64s' (errno: %d)",
-"Impossibile trovare il file: '%-.64s' (errno: %d)",
-"Impossibile leggere la directory di '%-.64s' (errno: %d)",
-"Impossibile cambiare la directory in '%-.64s' (errno: %d)",
-"Il record e` cambiato dall'ultima lettura della tabella '%-.64s'",
-"Disco pieno (%s). In attesa che qualcuno liberi un po' di spazio...",
-"Scrittura impossibile: chiave duplicata nella tabella '%-.64s'",
-"Errore durante la chiusura di '%-.64s' (errno: %d)",
-"Errore durante la lettura del file '%-.64s' (errno: %d)",
-"Errore durante la rinominazione da '%-.64s' a '%-.64s' (errno: %d)",
-"Errore durante la scrittura del file '%-.64s' (errno: %d)",
-"'%-.64s' e` soggetto a lock contro i cambiamenti",
-"Operazione di ordinamento abbandonata",
-"La view '%-.64s' non esiste per '%-.64s'",
-"Rilevato l'errore %d dal gestore delle tabelle",
-"Il gestore delle tabelle per '%-.64s' non ha questa opzione",
-"Impossibile trovare il record in '%-.64s'",
-"Informazione errata nel file: '%-.64s'",
-"File chiave errato per la tabella : '%-.64s'; prova a riparalo",
-"File chiave vecchio per la tabella '%-.64s'; riparalo!",
-"'%-.64s' e` di sola lettura",
-"Memoria esaurita. Fai ripartire il demone e riprova (richiesti %d bytes)",
-"Memoria per gli ordinamenti esaurita. Incrementare il 'sort_buffer' al demone",
-"Fine del file inaspettata durante la lettura del file '%-.64s' (errno: %d)",
-"Troppe connessioni",
-"Fine dello spazio/memoria per i thread",
-"Impossibile risalire al nome dell'host dall'indirizzo (risoluzione inversa)",
-"Negoziazione impossibile",
-"Accesso non consentito per l'utente: '%-.32s'@'%-.64s' al database '%-.64s'",
-"Accesso non consentito per l'utente: '%-.32s'@'%-.64s' (Password: %s)",
-"Nessun database selezionato",
-"Comando sconosciuto",
-"La colonna '%-.64s' non puo` essere nulla",
-"Database '%-.64s' sconosciuto",
-"La tabella '%-.64s' esiste gia`",
-"Tabella '%-.64s' sconosciuta",
-"Colonna: '%-.64s' di %-.64s e` ambigua",
-"Shutdown del server in corso",
-"Colonna sconosciuta '%-.64s' in '%-.64s'",
-"Usato '%-.64s' che non e` nel GROUP BY",
-"Impossibile raggruppare per '%-.64s'",
-"Il comando ha una funzione SUM e una colonna non specificata nella GROUP BY",
-"Il numero delle colonne non e` uguale al numero dei valori",
-"Il nome dell'identificatore '%-.100s' e` troppo lungo",
-"Nome colonna duplicato '%-.64s'",
-"Nome chiave duplicato '%-.64s'",
-"Valore duplicato '%-.64s' per la chiave %d",
-"Specifica errata per la colonna '%-.64s'",
-"%s vicino a '%-.80s' linea %d",
-"La query e` vuota",
-"Tabella/alias non unico: '%-.64s'",
-"Valore di default non valido per '%-.64s'",
-"Definite piu` chiave primarie",
-"Troppe chiavi. Sono ammesse max %d chiavi",
-"Troppe parti di chiave specificate. Sono ammesse max %d parti",
-"La chiave specificata e` troppo lunga. La max lunghezza della chiave e` %d",
-"La colonna chiave '%-.64s' non esiste nella tabella",
-"La colonna BLOB '%-.64s' non puo` essere usata nella specifica della chiave",
-"La colonna '%-.64s' e` troppo grande (max=%d). Utilizza un BLOB.",
-"Puo` esserci solo un campo AUTO e deve essere definito come chiave",
-"%s: Pronto per le connessioni\n",
-"%s: Shutdown normale\n",
-"%s: Ricevuto segnale %d. Interruzione!\n",
-"%s: Shutdown completato\n",
-"%s: Forzata la chiusura del thread %ld utente: '%-.64s'\n",
-"Impossibile creare il socket IP",
-"La tabella '%-.64s' non ha nessun indice come quello specificatato dalla CREATE INDEX. Ricrea la tabella",
-"L'argomento 'Field separator' non e` quello atteso. Controlla il manuale",
-"Non possono essere usate righe a lunghezza fissa con i BLOB. Usa 'FIELDS TERMINATED BY'.",
-"Il file '%-.64s' deve essere nella directory del database e deve essere leggibile da tutti",
-"Il file '%-.64s' esiste gia`",
-"Records: %ld Cancellati: %ld Saltati: %ld Avvertimenti: %ld",
-"Records: %ld Duplicati: %ld",
-"Sotto-parte della chiave errata. La parte di chiave utilizzata non e` una stringa o la lunghezza e` maggiore della parte di chiave.",
-"Non si possono cancellare tutti i campi con una ALTER TABLE. Utilizzare DROP TABLE",
-"Impossibile cancellare '%-.64s'. Controllare che il campo chiave esista",
-"Records: %ld Duplicati: %ld Avvertimenti: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Thread id: %lu sconosciuto",
-"Utente non proprietario del thread %lu",
-"Nessuna tabella usata",
-"Troppe stringhe per la colonna %-.64s e la SET",
-"Impossibile generare un nome del file log unico %-.64s.(1-999)\n",
-"La tabella '%-.64s' e` soggetta a lock in lettura e non puo` essere aggiornata",
-"Non e` stato impostato il lock per la tabella '%-.64s' con LOCK TABLES",
-"Il campo BLOB '%-.64s' non puo` avere un valore di default",
-"Nome database errato '%-.100s'",
-"Nome tabella errato '%-.100s'",
-"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto.",
-"Errore sconosciuto",
-"Procedura '%-.64s' sconosciuta",
-"Numero di parametri errato per la procedura '%-.64s'",
-"Parametri errati per la procedura '%-.64s'",
-"Tabella '%-.64s' sconosciuta in %s",
-"Campo '%-.64s' specificato 2 volte",
-"Uso non valido di una funzione di raggruppamento",
-"La tabella '%-.64s' usa un'estensione che non esiste in questa versione di MySQL",
-"Una tabella deve avere almeno 1 colonna",
-"La tabella '%-.64s' e` piena",
-"Set di caratteri '%-.64s' sconosciuto",
-"Troppe tabelle. MySQL puo` usare solo %d tabelle in una join",
-"Troppi campi",
-"Riga troppo grande. La massima grandezza di una riga, non contando i BLOB, e` %d. Devi cambiare alcuni campi in BLOB",
-"Thread stack overrun: Usati: %ld di uno stack di %ld. Usa 'mysqld -O thread_stack=#' per specificare uno stack piu` grande.",
-"Trovata una dipendenza incrociata nella OUTER JOIN. Controlla le condizioni ON",
-"La colonna '%-.64s' e` usata con UNIQUE o INDEX ma non e` definita come NOT NULL",
-"Impossibile caricare la funzione '%-.64s'",
-"Impossibile inizializzare la funzione '%-.64s'; %-.80s",
-"Non sono ammessi path per le librerie condivisa",
-"La funzione '%-.64s' esiste gia`",
-"Impossibile aprire la libreria condivisa '%-.64s' (errno: %d %s)",
-"Impossibile trovare la funzione '%-.64s' nella libreria",
-"La funzione '%-.64s' non e` definita",
-"Sistema '%-.64s' bloccato a causa di troppi errori di connessione. Per sbloccarlo: 'mysqladmin flush-hosts'",
-"Al sistema '%-.64s' non e` consentita la connessione a questo server MySQL",
-"Impossibile cambiare la password usando MySQL come utente anonimo",
-"E` necessario il privilegio di update sulle tabelle del database mysql per cambiare le password per gli altri utenti",
-"Impossibile trovare la riga corrispondente nella tabella user",
-"Rows riconosciute: %ld Cambiate: %ld Warnings: %ld",
-"Impossibile creare un nuovo thread (errno %d). Se non ci sono problemi di memoria disponibile puoi consultare il manuale per controllare possibili problemi dipendenti dal SO",
-"Il numero delle colonne non corrisponde al conteggio alla riga %ld",
-"Impossibile riaprire la tabella: '%-.64s'",
-"Uso scorretto del valore NULL",
-"Errore '%-.64s' da regexp",
-"Il mescolare funzioni di aggregazione (MIN(),MAX(),COUNT()...) e non e` illegale se non c'e` una clausula GROUP BY",
-"GRANT non definita per l'utente '%-.32s' dalla macchina '%-.64s'",
-"Comando %-.16s negato per l'utente: '%-.32s'@'%-.64s' sulla tabella '%-.64s'",
-"Comando %-.16s negato per l'utente: '%-.32s'@'%-.64s' sulla colonna '%-.64s' della tabella '%-.64s'",
-"Comando GRANT/REVOKE illegale. Prego consultare il manuale per sapere quali privilegi possono essere usati.",
-"L'argomento host o utente per la GRANT e` troppo lungo",
-"La tabella '%-.64s.%s' non esiste",
-"GRANT non definita per l'utente '%-.32s' dalla macchina '%-.64s' sulla tabella '%-.64s'",
-"Il comando utilizzato non e` supportato in questa versione di MySQL",
-"Errore di sintassi nella query SQL",
-"Il thread di inserimento ritardato non riesce ad ottenere il lock per la tabella %-.64s",
-"Troppi threads ritardati in uso",
-"Interrotta la connessione %ld al db: '%-.64s' utente: '%-.64s' (%s)",
-"Ricevuto un pacchetto piu` grande di 'max_allowed_packet'",
-"Rilevato un errore di lettura dalla pipe di connessione",
-"Rilevato un errore da fcntl()",
-"Ricevuti pacchetti non in ordine",
-"Impossibile scompattare i pacchetti di comunicazione",
-"Rilevato un errore ricevendo i pacchetti di comunicazione",
-"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'",
-"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'",
-"Nome colonna '%-.100s' non corretto",
-"Il gestore delle tabelle non puo` indicizzare la colonna '%-.64s'",
-"Non tutte le tabelle nella tabella di MERGE sono definite in maniera identica",
-"Impossibile scrivere nella tabella '%-.64s' per limitazione di unicita`",
-"La colonna '%-.64s' di tipo BLOB e` usata in una chiave senza specificarne la lunghezza",
-"Tutte le parti di una chiave primaria devono essere dichiarate NOT NULL; se necessitano valori NULL nelle chiavi utilizzare UNIQUE",
-"Il risultato consiste di piu` di una riga",
-"Questo tipo di tabella richiede una chiave primaria",
-"Questa versione di MYSQL non e` compilata con il supporto RAID",
-"In modalita` 'safe update' si e` cercato di aggiornare una tabella senza clausola WHERE su una chiave",
-"La chiave '%-.64s' non esiste nella tabella '%-.64s'",
-"Impossibile aprire la tabella",
-"Il gestore per la tabella non supporta il %s",
-"Non puoi eseguire questo comando in una transazione",
-"Rilevato l'errore %d durante il COMMIT",
-"Rilevato l'errore %d durante il ROLLBACK",
-"Rilevato l'errore %d durante il FLUSH_LOGS",
-"Rilevato l'errore %d durante il CHECKPOINT",
-"Interrotta la connessione %ld al db: ''%-.64s' utente: '%-.32s' host: '%-.64s' (%-.64s)",
-"Il gestore per la tabella non supporta il dump binario",
-"Binlog e` stato chiuso durante l'esecuzione del FLUSH MASTER",
-"Fallita la ricostruzione dell'indice della tabella copiata '%-.64s'",
-"Errore dal master: '%-.64s",
-"Errore di rete durante la ricezione dal master",
-"Errore di rete durante l'invio al master",
-"Impossibile trovare un indice FULLTEXT che corrisponda all'elenco delle colonne",
-"Impossibile eseguire il comando richiesto: tabelle sotto lock o transazione in atto",
-"Variabile di sistema '%-.64s' sconosciuta",
-"La tabella '%-.64s' e` segnalata come corrotta e deve essere riparata",
-"La tabella '%-.64s' e` segnalata come corrotta e l'ultima ricostruzione (automatica?) e` fallita",
-"Attenzione: Alcune delle modifiche alle tabelle non transazionali non possono essere ripristinate (roll back impossibile)",
-"La transazione a comandi multipli (multi-statement) ha richiesto piu` di 'max_binlog_cache_size' bytes di disco: aumentare questa variabile di mysqld e riprovare",
-"Questa operazione non puo' essere eseguita con un database 'slave' che gira, lanciare prima STOP SLAVE",
-"Questa operaione richiede un database 'slave', configurarlo ed eseguire START SLAVE",
-"Il server non e' configurato come 'slave', correggere il file di configurazione cambiando CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Impossibile creare il thread 'slave', controllare le risorse di sistema",
-"L'utente %-.64s ha gia' piu' di 'max_user_connections' connessioni attive",
-"Si possono usare solo espressioni costanti con SET",
-"E' scaduto il timeout per l'attesa del lock",
-"Il numero totale di lock e' maggiore della grandezza della tabella di lock",
-"I lock di aggiornamento non possono essere acquisiti durante una transazione 'READ UNCOMMITTED'",
-"DROP DATABASE non e' permesso mentre il thread ha un lock globale di lettura",
-"CREATE DATABASE non e' permesso mentre il thread ha un lock globale di lettura",
-"Argomenti errati a %s",
-"A '%-.32s'@'%-.64s' non e' permesso creare nuovi utenti",
-"Definizione della tabella errata; tutte le tabelle di tipo MERGE devono essere nello stesso database",
-"Trovato deadlock durante il lock; Provare a far ripartire la transazione",
-"La tabella usata non supporta gli indici FULLTEXT",
-"Impossibile aggiungere il vincolo di integrita' referenziale (foreign key constraint)",
-"Impossibile aggiungere la riga: un vincolo d'integrita' referenziale non e' soddisfatto",
-"Impossibile cancellare la riga: un vincolo d'integrita' referenziale non e' soddisfatto",
-"Errore durante la connessione al master: %-.128s",
-"Errore eseguendo una query sul master: %-.128s",
-"Errore durante l'esecuzione del comando %s: %-.128s",
-"Uso errato di %s e %s",
-"La SELECT utilizzata ha un numero di colonne differente",
-"Impossibile eseguire la query perche' c'e' un conflitto con in lock di lettura",
-"E' disabilitata la possibilita' di mischiare tabelle transazionali e non-transazionali",
-"L'opzione '%s' e' stata usata due volte nel comando",
-"L'utente '%-.64s' ha ecceduto la risorsa '%s' (valore corrente: %ld)",
-"Accesso non consentito. Serve il privilegio %-.128s per questa operazione",
-"La variabile '%-.64s' e' una variabile locale ( SESSION ) e non puo' essere cambiata usando SET GLOBAL",
-"La variabile '%-.64s' e' una variabile globale ( GLOBAL ) e deve essere cambiata usando SET GLOBAL",
-"La variabile '%-.64s' non ha un valore di default",
-"Alla variabile '%-.64s' non puo' essere assegato il valore '%-.64s'",
-"Tipo di valore errato per la variabile '%-.64s'",
-"Alla variabile '%-.64s' e' di sola scrittura quindi puo' essere solo assegnato un valore, non letto",
-"Uso/posizione di '%s' sbagliato",
-"Questa versione di MySQL non supporta ancora '%s'",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/japanese-sjis/errmsg.txt b/sql/share/japanese-sjis/errmsg.txt
deleted file mode 100644
index 1aa9ef74d5f..00000000000
--- a/sql/share/japanese-sjis/errmsg.txt
+++ /dev/null
@@ -1,326 +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 */
-
-/*
- Shift-JIS Japanese
-*/
-
-character-set=sjis
-
-"hashchk",
-"isamchk",
-"NO",
-"YES",
-"'%-.64s' ƒtƒ@ƒCƒ‹‚ªì‚ê‚Ü‚¹‚ñ (errno: %d)",
-"'%-.64s' ƒe[ƒuƒ‹‚ªì‚ê‚Ü‚¹‚ñ.(errno: %d)",
-"'%-.64s' ƒf[ƒ^ƒx[ƒX‚ªì‚ê‚Ü‚¹‚ñ (errno: %d)",
-"'%-.64s' ƒf[ƒ^ƒx[ƒX‚ªì‚ê‚Ü‚¹‚ñ.Šù‚É‚»‚̃f[ƒ^ƒx[ƒX‚ª‘¶Ý‚µ‚Ü‚·",
-"'%-.64s' ƒf[ƒ^ƒx[ƒX‚ð”jŠü‚Å‚«‚Ü‚¹‚ñ. ‚»‚̃f[ƒ^ƒx[ƒX‚ª‚È‚¢‚Ì‚Å‚·.",
-"ƒf[ƒ^ƒx[ƒX”jŠüƒGƒ‰[ ('%-.64s' ‚ð휂ł«‚Ü‚¹‚ñ, errno: %d)",
-"ƒf[ƒ^ƒx[ƒX”jŠüƒGƒ‰[ ('%-.64s' ‚ð rmdir ‚Å‚«‚Ü‚¹‚ñ, errno: %d)",
-"'%-.64s' ‚Ì휂ªƒGƒ‰[ (errno: %d)",
-"system table ‚̃ŒƒR[ƒh‚ð“Ç‚ÞŽ–‚ª‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½",
-"'%-.64s' ‚̃XƒeƒCƒ^ƒX‚ª“¾‚ç‚ê‚Ü‚¹‚ñ. (errno: %d)",
-"working directory ‚𓾂鎖‚ª‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½ (errno: %d)",
-"ƒtƒ@ƒCƒ‹‚ðƒƒbƒN‚Å‚«‚Ü‚¹‚ñ (errno: %d)",
-"'%-.64s' ƒtƒ@ƒCƒ‹‚ðŠJ‚­Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d)",
-"'%-.64s' ƒtƒ@ƒCƒ‹‚ðŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ.(errno: %d)",
-"'%-.64s' ƒfƒBƒŒƒNƒgƒŠ‚ª“Ç‚ß‚Ü‚¹‚ñ.(errno: %d)",
-"'%-.64s' ƒfƒBƒŒƒNƒgƒŠ‚É chdir ‚Å‚«‚Ü‚¹‚ñ.(errno: %d)",
-"Record has changed since last read in table '%-.64s'",
-"Disk full (%s). ’N‚©‚ª‰½‚©‚ðŒ¸‚ç‚·‚Ü‚Å‚Ü‚Á‚Ä‚­‚¾‚³‚¢...",
-"table '%-.64s' ‚É key ‚ªd•¡‚µ‚Ä‚¢‚Ä‘‚«‚±‚ß‚Ü‚¹‚ñ",
-"Error on close of '%-.64s' (errno: %d)",
-"'%-.64s' ƒtƒ@ƒCƒ‹‚Ì“Ç‚Ýž‚݃Gƒ‰[ (errno: %d)",
-"'%-.64s' ‚ð '%-.64s' ‚É rename ‚Å‚«‚Ü‚¹‚ñ (errno: %d)",
-"'%-.64s' ƒtƒ@ƒCƒ‹‚ð‘‚­Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d)",
-"'%-.64s' ‚̓ƒbƒN‚³‚ê‚Ä‚¢‚Ü‚·",
-"Sort ’†’f",
-"View '%-.64s' ‚ª '%-.64s' ‚É’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
-"Got error %d from table handler",
-"Table handler for '%-.64s' doesn't have this option",
-"'%-.64s'‚Ì‚È‚©‚ɃŒƒR[ƒh‚ªŒ©•t‚©‚è‚Ü‚¹‚ñ",
-"ƒtƒ@ƒCƒ‹ '%-.64s' ‚Ì info ‚ªŠÔˆá‚Á‚Ä‚¢‚é‚悤‚Å‚·",
-"'%-.64s' ƒe[ƒuƒ‹‚Ì key file ‚ªŠÔˆá‚Á‚Ä‚¢‚é‚悤‚Å‚·. C•œ‚ð‚µ‚Ä‚­‚¾‚³‚¢",
-"'%-.64s' ƒe[ƒuƒ‹‚͌¢Œ`Ž®‚Ì key file ‚̂悤‚Å‚·; C•œ‚ð‚µ‚Ä‚­‚¾‚³‚¢",
-"'%-.64s' ‚Í“Ç‚Ýž‚Ýê—p‚Å‚·",
-"Out of memory. ƒf[ƒ‚ƒ“‚ðƒŠƒXƒ^[ƒg‚µ‚Ä‚Ý‚Ä‚­‚¾‚³‚¢ (%d bytes •K—v)",
-"Out of sort memory. sort buffer size ‚ª‘«‚è‚È‚¢‚悤‚Å‚·.",
-"'%-.64s' ƒtƒ@ƒCƒ‹‚ð“Ç‚Ýž‚Ý’†‚É EOF ‚ª—\Šú‚¹‚ÊŠ‚ÅŒ»‚ê‚Ü‚µ‚½. (errno: %d)",
-"Ú‘±‚ª‘½‚·‚¬‚Ü‚·",
-"Out of memory; mysqld ‚©‚»‚Ì‘¼‚̃vƒƒZƒX‚ªƒƒ‚ƒŠ[‚ð‘S‚ÄŽg‚Á‚Ä‚¢‚é‚©Šm”F‚µ‚Ä‚­‚¾‚³‚¢. ƒƒ‚ƒŠ[‚ðŽg‚¢Ø‚Á‚Ä‚¢‚È‚¢ê‡A'ulimit' ‚ðݒ肵‚Ä mysqld ‚̃ƒ‚ƒŠ[Žg—pŒÀŠE—ʂ𑽂­‚·‚é‚©Aswap space ‚ð‘‚₵‚Ä‚Ý‚Ä‚­‚¾‚³‚¢",
-"‚»‚Ì address ‚Ì hostname ‚ªˆø‚¯‚Ü‚¹‚ñ.",
-"Bad handshake",
-"ƒ†[ƒU[ '%-.32s'@'%-.64s' ‚Ì '%-.64s' ƒf[ƒ^ƒx[ƒX‚ւ̃AƒNƒZƒX‚ð‹‘”Û‚µ‚Ü‚·",
-"ƒ†[ƒU[ '%-.32s'@'%-.64s' ‚ð‹‘”Û‚µ‚Ü‚·.uUsing password: %s)",
-"ƒf[ƒ^ƒx[ƒX‚ª‘I‘ð‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ.",
-"‚»‚̃Rƒ}ƒ“ƒh‚͉½H",
-"Column '%-.64s' ‚Í null ‚É‚Í‚Å‚«‚È‚¢‚Ì‚Å‚·",
-"'%-.64s' ‚È‚ñ‚ăf[ƒ^ƒx[ƒX‚Í’m‚è‚Ü‚¹‚ñ.",
-"Table '%-.64s' ‚ÍŠù‚É‚ ‚è‚Ü‚·",
-"table '%-.64s' ‚Í‚ ‚è‚Ü‚¹‚ñ.",
-"Column: '%-.64s' in %-.64s is ambiguous",
-"Server ‚ð shutdown ’†...",
-"'%-.64s' column ‚Í '%-.64s' ‚É‚Í‚ ‚è‚Ü‚¹‚ñ.",
-"'%-.64s' isn't in GROUP BY",
-"Can't group on '%-.64s'",
-"Statement has sum functions and columns in same statement",
-"Column count doesn't match value count",
-"Identifier name '%-.100s' ‚Í’·‚·‚¬‚Ü‚·",
-"'%-.64s' ‚Æ‚¢‚¤ column –¼‚Íd•¡‚µ‚Ä‚Ü‚·",
-"'%-.64s' ‚Æ‚¢‚¤ key ‚Ì–¼‘O‚Íd•¡‚µ‚Ä‚¢‚Ü‚·",
-"'%-.64s' ‚Í key %d ‚É‚¨‚¢‚Äd•¡‚µ‚Ä‚¢‚Ü‚·",
-"Incorrect column specifier for column '%-.64s'",
-"%s : '%-.80s' •t‹ß : %d s–Ú",
-"Query ‚ª‹ó‚Å‚·.",
-"'%-.64s' ‚͈êˆÓ‚Ì table/alias –¼‚Å‚Í‚ ‚è‚Ü‚¹‚ñ",
-"Invalid default value for '%-.64s'",
-"•¡”‚Ì primary key ‚ª’è‹`‚³‚ê‚Ü‚µ‚½",
-"key ‚ÌŽw’肪‘½‚·‚¬‚Ü‚·. key ‚ÍÅ‘å %d ‚Ü‚Å‚Å‚·",
-"Too many key parts specified; max %d parts allowed",
-"key ‚ª’·‚·‚¬‚Ü‚·. key ‚Ì’·‚³‚ÍÅ‘å %d ‚Å‚·",
-"Key column '%-.64s' ‚ªƒe[ƒuƒ‹‚É‚ ‚è‚Ü‚¹‚ñ.",
-"BLOB column '%-.64s' can't be used in key specification with the used table type",
-"column '%-.64s' ‚Í,Šm•Û‚·‚é column ‚Ì‘å‚«‚³‚ª‘½‚·‚¬‚Ü‚·. (Å‘å %d ‚Ü‚Å). BLOB ‚ð‚©‚í‚è‚ÉŽg—p‚µ‚Ä‚­‚¾‚³‚¢.",
-"ƒe[ƒuƒ‹‚Ì’è‹`‚ªˆá‚¢‚Ü‚·; there can be only one auto column and it must be defined as a key",
-"%s: €”õŠ®—¹",
-"%s: Normal shutdown\n",
-"%s: Got signal %d. ’†’f!\n",
-"%s: Shutdown Š®—¹\n",
-"%s: ƒXƒŒƒbƒh %ld ‹­§I—¹ user: '%-.64s'\n",
-"IP socket ‚ªì‚ê‚Ü‚¹‚ñ",
-"Table '%-.64s' ‚Í‚»‚̂悤‚È index ‚ðŽ‚Á‚Ä‚¢‚Ü‚¹‚ñ(CREATE INDEX ŽÀsŽž‚ÉŽw’肳‚ê‚Ä‚¢‚Ü‚¹‚ñ). ƒe[ƒuƒ‹‚ðì‚è’¼‚µ‚Ä‚­‚¾‚³‚¢",
-"Field separator argument is not what is expected; check the manual",
-"You can't use fixed rowlength with BLOBs; please use 'fields terminated by'.",
-"ƒtƒ@ƒCƒ‹ '%-.64s' ‚Í databse ‚Ì directory ‚É‚ ‚é‚©‘S‚Ẵ†[ƒU[‚ª“Ç‚ß‚é‚悤‚É‹–‰Â‚³‚ê‚Ä‚¢‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ.",
-"File '%-.64s' ‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·",
-"ƒŒƒR[ƒh”: %ld íœ: %ld Skipped: %ld Warnings: %ld",
-"ƒŒƒR[ƒh”: %ld d•¡: %ld",
-"Incorrect sub part key; the used key part isn't a string or the used length is longer than the key part",
-"ALTER TABLE ‚Å‘S‚Ä‚Ì column ‚Í휂ł«‚Ü‚¹‚ñ. DROP TABLE ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢",
-"'%-.64s' ‚ð”jŠü‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½; check that column/key exists",
-"ƒŒƒR[ƒh”: %ld d•¡”: %ld Warnings: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"thread id: %lu ‚Í‚ ‚è‚Ü‚¹‚ñ",
-"thread %lu ‚̃I[ƒi[‚Å‚Í‚ ‚è‚Ü‚¹‚ñ",
-"No tables used",
-"Too many strings for column %-.64s and SET",
-"Can't generate a unique log-filename %-.64s.(1-999)\n",
-"Table '%-.64s' ‚Í READ lock ‚É‚È‚Á‚Ä‚¢‚ÄAXV‚Í‚Å‚«‚Ü‚¹‚ñ",
-"Table '%-.64s' ‚Í LOCK TABLES ‚É‚æ‚Á‚ăƒbƒN‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
-"BLOB column '%-.64s' can't have a default value",
-"Žw’肵‚½ database –¼ '%-.100s' ‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·",
-"Žw’肵‚½ table –¼ '%-.100s' ‚Í‚Ü‚¿‚ª‚Á‚Ä‚¢‚Ü‚·",
-"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'",
-"Incorrect parameters to procedure '%-.64s'",
-"Unknown table '%-.64s' in %s",
-"Column '%-.64s' specified twice",
-"Invalid use of group function",
-"Table '%-.64s' uses an extension that doesn't exist in this MySQL version",
-"ƒe[ƒuƒ‹‚ÍÅ’á 1 ŒÂ‚Ì column ‚ª•K—v‚Å‚·",
-"table '%-.64s' ‚Í‚¢‚Á‚Ï‚¢‚Å‚·",
-"character set '%-.64s' ‚̓Tƒ|[ƒg‚µ‚Ä‚¢‚Ü‚¹‚ñ",
-"ƒe[ƒuƒ‹‚ª‘½‚·‚¬‚Ü‚·; 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. ƒXƒ^ƒbƒN—̈æ‚𑽂­‚Ƃ肽‚¢ê‡A'mysqld -O thread_stack=#' ‚ÆŽw’肵‚Ä‚­‚¾‚³‚¢",
-"Cross dependency found in OUTER JOIN; examine your ON conditions",
-"Column '%-.64s' ‚ª UNIQUE ‚© INDEX ‚ÅŽg—p‚³‚ê‚Ü‚µ‚½. ‚±‚̃Jƒ‰ƒ€‚Í NOT NULL ‚Æ’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ.",
-"function '%-.64s' ‚ð ƒ[ƒh‚Å‚«‚Ü‚¹‚ñ",
-"function '%-.64s' ‚ð‰Šú‰»‚Å‚«‚Ü‚¹‚ñ; %-.80s",
-"shared library ‚ւ̃pƒX‚ª’Ê‚Á‚Ä‚¢‚Ü‚¹‚ñ",
-"Function '%-.64s' ‚ÍŠù‚É’è‹`‚³‚ê‚Ä‚¢‚Ü‚·",
-"shared library '%-.64s' ‚ðŠJ‚­Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d %s)",
-"function '%-.64s' ‚ðƒ‰ƒCƒuƒ‰ƒŠ[’†‚ÉŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ",
-"Function '%-.64s' ‚Í’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
-"Host '%-.64s' ‚Í many connection error ‚Ì‚½‚ßA‹‘”Û‚³‚ê‚Ü‚µ‚½. 'mysqladmin flush-hosts' ‚ʼn𜂵‚Ä‚­‚¾‚³‚¢",
-"Host '%-.64s' ‚Í MySQL server ‚ÉÚ‘±‚ð‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
-"MySQL ‚ð anonymous users ‚ÅŽg—p‚µ‚Ä‚¢‚éó‘Ô‚Å‚ÍAƒpƒXƒ[ƒh‚Ì•ÏX‚Í‚Å‚«‚Ü‚¹‚ñ",
-"‘¼‚̃†[ƒU[‚̃pƒXƒ[ƒh‚ð•ÏX‚·‚邽‚ß‚É‚Í, mysql ƒf[ƒ^ƒx[ƒX‚ɑ΂µ‚Ä update ‚Ì‹–‰Â‚ª‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ.",
-"Can't find any matching row in the user table",
-"ˆê’v”(Rows matched): %ld •ÏX: %ld Warnings: %ld",
-"V‹K‚ɃXƒŒƒbƒh‚ªì‚ê‚Ü‚¹‚ñ‚Å‚µ‚½ (errno %d). ‚à‚µÅ‘åŽg—p‹–‰Âƒƒ‚ƒŠ[”‚ð‰z‚¦‚Ä‚¢‚È‚¢‚̂ɃGƒ‰[‚ª”­¶‚µ‚Ä‚¢‚é‚È‚ç, ƒ}ƒjƒ…ƒAƒ‹‚Ì’†‚©‚ç 'possible OS-dependent bug' ‚Æ‚¢‚¤•¶Žš‚ð’T‚µ‚Ä‚­‚Ý‚Ä‚¾‚³‚¢.",
-"Column count doesn't match value count at row %ld",
-"Can't reopen table: '%-.64s'",
-"NULL ’l‚ÌŽg—p•û–@‚ª•s“KØ‚Å‚·",
-"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",
-"ƒ†[ƒU[ '%-.32s' (ƒzƒXƒg '%-.64s' ‚̃†[ƒU[) ‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
-"ƒRƒ}ƒ“ƒh %-.16s ‚Í ƒ†[ƒU[ '%-.32s'@'%-.64s' ,ƒe[ƒuƒ‹ '%-.64s' ‚ɑ΂µ‚Ä‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ",
-"ƒRƒ}ƒ“ƒh %-.16s ‚Í ƒ†[ƒU[ '%-.32s'@'%-.64s'\n ƒJƒ‰ƒ€ '%-.64s' ƒe[ƒuƒ‹ '%-.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'",
-"The used command is not allowed with this MySQL version",
-"Something is wrong in your syntax",
-"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' bytes",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Couldn't uncompress communication packet",
-"Got an error reading communication packets",
-"Got timeout reading communication packets",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
-"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",
-"Incorrect column name '%-.100s'",
-"The used table handler can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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' 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
deleted file mode 100644
index 47adbf74b86..00000000000
--- a/sql/share/japanese/errmsg.txt
+++ /dev/null
@@ -1,326 +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 */
-
-/*
- 3.22.10-beta euc-japanese (ujis) text
-*/
-
-character-set=ujis
-
-"hashchk",
-"isamchk",
-"NO",
-"YES",
-"'%-.64s' ¥Õ¥¡¥¤¥ë¤¬ºî¤ì¤Þ¤»¤ó (errno: %d)",
-"'%-.64s' ¥Æ¡¼¥Ö¥ë¤¬ºî¤ì¤Þ¤»¤ó.(errno: %d)",
-"'%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ºî¤ì¤Þ¤»¤ó (errno: %d)",
-"'%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ºî¤ì¤Þ¤»¤ó.´û¤Ë¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬Â¸ºß¤·¤Þ¤¹",
-"'%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÇË´þ¤Ç¤­¤Þ¤»¤ó. ¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬¤Ê¤¤¤Î¤Ç¤¹.",
-"¥Ç¡¼¥¿¥Ù¡¼¥¹ÇË´þ¥¨¥é¡¼ ('%-.64s' ¤òºï½ü¤Ç¤­¤Þ¤»¤ó, errno: %d)",
-"¥Ç¡¼¥¿¥Ù¡¼¥¹ÇË´þ¥¨¥é¡¼ ('%-.64s' ¤ò rmdir ¤Ç¤­¤Þ¤»¤ó, errno: %d)",
-"'%-.64s' ¤Îºï½ü¤¬¥¨¥é¡¼ (errno: %d)",
-"system table ¤Î¥ì¥³¡¼¥É¤òÆɤà»ö¤¬¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿",
-"'%-.64s' ¤Î¥¹¥Æ¥¤¥¿¥¹¤¬ÆÀ¤é¤ì¤Þ¤»¤ó. (errno: %d)",
-"working directory ¤òÆÀ¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿ (errno: %d)",
-"¥Õ¥¡¥¤¥ë¤ò¥í¥Ã¥¯¤Ç¤­¤Þ¤»¤ó (errno: %d)",
-"'%-.64s' ¥Õ¥¡¥¤¥ë¤ò³«¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó (errno: %d)",
-"'%-.64s' ¥Õ¥¡¥¤¥ë¤ò¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó.(errno: %d)",
-"'%-.64s' ¥Ç¥£¥ì¥¯¥È¥ê¤¬Æɤá¤Þ¤»¤ó.(errno: %d)",
-"'%-.64s' ¥Ç¥£¥ì¥¯¥È¥ê¤Ë chdir ¤Ç¤­¤Þ¤»¤ó.(errno: %d)",
-"Record has changed since last read in table '%-.64s'",
-"Disk full (%s). 狼¤¬²¿¤«¤ò¸º¤é¤¹¤Þ¤Ç¤Þ¤Ã¤Æ¤¯¤À¤µ¤¤...",
-"table '%-.64s' ¤Ë key ¤¬½ÅÊ£¤·¤Æ¤¤¤Æ½ñ¤­¤³¤á¤Þ¤»¤ó",
-"Error on close of '%-.64s' (errno: %d)",
-"'%-.64s' ¥Õ¥¡¥¤¥ë¤ÎÆɤ߹þ¤ß¥¨¥é¡¼ (errno: %d)",
-"'%-.64s' ¤ò '%-.64s' ¤Ë rename ¤Ç¤­¤Þ¤»¤ó (errno: %d)",
-"'%-.64s' ¥Õ¥¡¥¤¥ë¤ò½ñ¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó (errno: %d)",
-"'%-.64s' ¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹",
-"Sort ̾̂",
-"View '%-.64s' ¤¬ '%-.64s' ¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
-"Got error %d from table handler",
-"Table handler for '%-.64s' doesn't have this option",
-"'%-.64s'¤Î¤Ê¤«¤Ë¥ì¥³¡¼¥É¤¬¸«ÉÕ¤«¤ê¤Þ¤»¤ó",
-"¥Õ¥¡¥¤¥ë '%-.64s' ¤Î info ¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¤è¤¦¤Ç¤¹",
-"'%-.64s' ¥Æ¡¼¥Ö¥ë¤Î key file ¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¤è¤¦¤Ç¤¹. ½¤Éü¤ò¤·¤Æ¤¯¤À¤µ¤¤",
-"'%-.64s' ¥Æ¡¼¥Ö¥ë¤Ï¸Å¤¤·Á¼°¤Î key file ¤Î¤è¤¦¤Ç¤¹; ½¤Éü¤ò¤·¤Æ¤¯¤À¤µ¤¤",
-"'%-.64s' ¤ÏÆɤ߹þ¤ßÀìÍѤǤ¹",
-"Out of memory. ¥Ç¡¼¥â¥ó¤ò¥ê¥¹¥¿¡¼¥È¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤ (%d bytes ɬÍ×)",
-"Out of sort memory. sort buffer size ¤¬Â­¤ê¤Ê¤¤¤è¤¦¤Ç¤¹.",
-"'%-.64s' ¥Õ¥¡¥¤¥ë¤òÆɤ߹þ¤ßÃæ¤Ë EOF ¤¬Í½´ü¤»¤Ì½ê¤Ç¸½¤ì¤Þ¤·¤¿. (errno: %d)",
-"Àܳ¤¬Â¿¤¹¤®¤Þ¤¹",
-"Out of memory; mysqld ¤«¤½¤Î¾¤Î¥×¥í¥»¥¹¤¬¥á¥â¥ê¡¼¤òÁ´¤Æ»È¤Ã¤Æ¤¤¤ë¤«³Îǧ¤·¤Æ¤¯¤À¤µ¤¤. ¥á¥â¥ê¡¼¤ò»È¤¤ÀڤäƤ¤¤Ê¤¤¾ì¹ç¡¢'ulimit' ¤òÀßÄꤷ¤Æ mysqld ¤Î¥á¥â¥ê¡¼»ÈÍѸ³¦Î̤ò¿¤¯¤¹¤ë¤«¡¢swap space ¤òÁý¤ä¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤",
-"¤½¤Î address ¤Î hostname ¤¬°ú¤±¤Þ¤»¤ó.",
-"Bad handshake",
-"¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ¤Î '%-.64s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥¢¥¯¥»¥¹¤òµñÈݤ·¤Þ¤¹",
-"¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ¤òµñÈݤ·¤Þ¤¹.uUsing password: %s)",
-"¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤Þ¤»¤ó.",
-"¤½¤Î¥³¥Þ¥ó¥É¤Ï²¿¡©",
-"Column '%-.64s' ¤Ï null ¤Ë¤Ï¤Ç¤­¤Ê¤¤¤Î¤Ç¤¹",
-"'%-.64s' ¤Ê¤ó¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÏÃΤê¤Þ¤»¤ó.",
-"Table '%-.64s' ¤Ï´û¤Ë¤¢¤ê¤Þ¤¹",
-"table '%-.64s' ¤Ï¤¢¤ê¤Þ¤»¤ó.",
-"Column: '%-.64s' in %-.64s is ambiguous",
-"Server ¤ò shutdown Ãæ...",
-"'%-.64s' column ¤Ï '%-.64s' ¤Ë¤Ï¤¢¤ê¤Þ¤»¤ó.",
-"'%-.64s' isn't in GROUP BY",
-"Can't group on '%-.64s'",
-"Statement has sum functions and columns in same statement",
-"Column count doesn't match value count",
-"Identifier name '%-.100s' ¤ÏŤ¹¤®¤Þ¤¹",
-"'%-.64s' ¤È¤¤¤¦ column ̾¤Ï½ÅÊ£¤·¤Æ¤Þ¤¹",
-"'%-.64s' ¤È¤¤¤¦ key ¤Î̾Á°¤Ï½ÅÊ£¤·¤Æ¤¤¤Þ¤¹",
-"'%-.64s' ¤Ï key %d ¤Ë¤ª¤¤¤Æ½ÅÊ£¤·¤Æ¤¤¤Þ¤¹",
-"Incorrect column specifier for column '%-.64s'",
-"%s : '%-.80s' ÉÕ¶á : %d ¹ÔÌÜ",
-"Query ¤¬¶õ¤Ç¤¹.",
-"'%-.64s' ¤Ï°ì°Õ¤Î table/alias ̾¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó",
-"Invalid default value for '%-.64s'",
-"Ê£¿ô¤Î primary key ¤¬ÄêµÁ¤µ¤ì¤Þ¤·¤¿",
-"key ¤Î»ØÄ꤬¿¤¹¤®¤Þ¤¹. key ¤ÏºÇÂç %d ¤Þ¤Ç¤Ç¤¹",
-"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 be only one auto column and it must be defined as a key",
-"%s: ½àÈ÷´°Î»",
-"%s: Normal shutdown\n",
-"%s: Got signal %d. ̾̂!\n",
-"%s: Shutdown ´°Î»\n",
-"%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'.",
-"¥Õ¥¡¥¤¥ë '%-.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",
-"ALTER TABLE ¤ÇÁ´¤Æ¤Î column ¤Ïºï½ü¤Ç¤­¤Þ¤»¤ó. DROP TABLE ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤",
-"'%-.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 ¤Ï¤¢¤ê¤Þ¤»¤ó",
-"thread %lu ¤Î¥ª¡¼¥Ê¡¼¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó",
-"No tables used",
-"Too many strings for column %-.64s and SET",
-"Can't generate a unique log-filename %-.64s.(1-999)\n",
-"Table '%-.64s' ¤Ï READ lock ¤Ë¤Ê¤Ã¤Æ¤¤¤Æ¡¢¹¹¿·¤Ï¤Ç¤­¤Þ¤»¤ó",
-"Table '%-.64s' ¤Ï LOCK TABLES ¤Ë¤è¤Ã¤Æ¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
-"BLOB column '%-.64s' can't have a default value",
-"»ØÄꤷ¤¿ database ̾ '%-.100s' ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹",
-"»ØÄꤷ¤¿ table ̾ '%-.100s' ¤Ï¤Þ¤Á¤¬¤Ã¤Æ¤¤¤Þ¤¹",
-"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'",
-"Incorrect parameters to procedure '%-.64s'",
-"Unknown table '%-.64s' in %s",
-"Column '%-.64s' specified twice",
-"Invalid use of group function",
-"Table '%-.64s' uses an extension that doesn't exist in this MySQL version",
-"¥Æ¡¼¥Ö¥ë¤ÏºÇÄã 1 ¸Ä¤Î column ¤¬É¬ÍפǤ¹",
-"table '%-.64s' ¤Ï¤¤¤Ã¤Ñ¤¤¤Ç¤¹",
-"character set '%-.64s' ¤Ï¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤»¤ó",
-"¥Æ¡¼¥Ö¥ë¤¬Â¿¤¹¤®¤Þ¤¹; 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",
-"Column '%-.64s' ¤¬ UNIQUE ¤« INDEX ¤Ç»ÈÍѤµ¤ì¤Þ¤·¤¿. ¤³¤Î¥«¥é¥à¤Ï NOT NULL ¤ÈÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó.",
-"function '%-.64s' ¤ò ¥í¡¼¥É¤Ç¤­¤Þ¤»¤ó",
-"function '%-.64s' ¤ò½é´ü²½¤Ç¤­¤Þ¤»¤ó; %-.80s",
-"shared library ¤Ø¤Î¥Ñ¥¹¤¬Ä̤äƤ¤¤Þ¤»¤ó",
-"Function '%-.64s' ¤Ï´û¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤¹",
-"shared library '%-.64s' ¤ò³«¤¯»ö¤¬¤Ç¤­¤Þ¤»¤ó (errno: %d %s)",
-"function '%-.64s' ¤ò¥é¥¤¥Ö¥é¥ê¡¼Ãæ¤Ë¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó",
-"Function '%-.64s' ¤ÏÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
-"Host '%-.64s' ¤Ï many connection error ¤Î¤¿¤á¡¢µñÈݤµ¤ì¤Þ¤·¤¿. 'mysqladmin flush-hosts' ¤Ç²ò½ü¤·¤Æ¤¯¤À¤µ¤¤",
-"Host '%-.64s' ¤Ï MySQL server ¤ËÀܳ¤òµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
-"MySQL ¤ò anonymous users ¤Ç»ÈÍѤ·¤Æ¤¤¤ë¾õÂ֤Ǥϡ¢¥Ñ¥¹¥ï¡¼¥É¤ÎÊѹ¹¤Ï¤Ç¤­¤Þ¤»¤ó",
-"¾¤Î¥æ¡¼¥¶¡¼¤Î¥Ñ¥¹¥ï¡¼¥É¤òÊѹ¹¤¹¤ë¤¿¤á¤Ë¤Ï, mysql ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÂФ·¤Æ update ¤Îµö²Ä¤¬¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó.",
-"Can't find any matching row in the user table",
-"°ìÃ׿ô(Rows matched): %ld Êѹ¹: %ld Warnings: %ld",
-"¿·µ¬¤Ë¥¹¥ì¥Ã¥É¤¬ºî¤ì¤Þ¤»¤ó¤Ç¤·¤¿ (errno %d). ¤â¤·ºÇÂç»ÈÍѵö²Ä¥á¥â¥ê¡¼¿ô¤ò±Û¤¨¤Æ¤¤¤Ê¤¤¤Î¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Æ¤¤¤ë¤Ê¤é, ¥Þ¥Ë¥å¥¢¥ë¤ÎÃ椫¤é 'possible OS-dependent bug' ¤È¤¤¤¦Ê¸»ú¤òõ¤·¤Æ¤¯¤ß¤Æ¤À¤µ¤¤.",
-"Column count doesn't match value count at row %ld",
-"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",
-"¥æ¡¼¥¶¡¼ '%-.32s' (¥Û¥¹¥È '%-.64s' ¤Î¥æ¡¼¥¶¡¼) ¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
-"¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s' ,¥Æ¡¼¥Ö¥ë '%-.64s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó",
-"¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.32s'@'%-.64s'\n ¥«¥é¥à '%-.64s' ¥Æ¡¼¥Ö¥ë '%-.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'",
-"The used command is not allowed with this MySQL version",
-"Something is wrong in your syntax",
-"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' bytes",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Couldn't uncompress communication packet",
-"Got an error reading communication packets",
-"Got timeout reading communication packets",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
-"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",
-"Incorrect column name '%-.100s'",
-"The used table handler can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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' 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
deleted file mode 100644
index aeafef9d159..00000000000
--- a/sql/share/korean/errmsg.txt
+++ /dev/null
@@ -1,322 +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 */
-
-character-set=euckr
-
-"hashchk",
-"isamchk",
-"¾Æ´Ï¿À",
-"¿¹",
-"È­ÀÏ '%-.64s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
-"Å×À̺í '%-.64s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
-"µ¥ÀÌŸº£À̽º '%-.64s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù.. (¿¡·¯¹øÈ£: %d)",
-"µ¥ÀÌŸº£À̽º '%-.64s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù.. µ¥ÀÌŸº£À̽º°¡ Á¸ÀçÇÔ",
-"µ¥ÀÌŸº£À̽º '%-.64s'¸¦ Á¦°ÅÇÏÁö ¸øÇß½À´Ï´Ù. µ¥ÀÌŸº£À̽º°¡ Á¸ÀçÇÏÁö ¾ÊÀ½ ",
-"µ¥ÀÌŸº£À̽º Á¦°Å ¿¡·¯('%-.64s'¸¦ »èÁ¦ÇÒ ¼ö ¾øÀ¾´Ï´Ù, ¿¡·¯¹øÈ£: %d)",
-"µ¥ÀÌŸº£À̽º Á¦°Å ¿¡·¯(rmdir '%-.64s'¸¦ ÇÒ ¼ö ¾øÀ¾´Ï´Ù, ¿¡·¯¹øÈ£: %d)",
-"'%-.64s' »èÁ¦ Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)",
-"system Å×ÀÌºí¿¡¼­ ·¹Äڵ带 ÀÐÀ» ¼ö ¾ø½À´Ï´Ù.",
-"'%-.64s'ÀÇ »óŸ¦ ¾òÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
-"¼öÇà µð·ºÅ丮¸¦ ãÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
-"È­ÀÏÀ» Àá±×Áö(lock) ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
-"È­ÀÏÀ» ¿­Áö ¸øÇß½À´Ï´Ù.: '%-.64s' (¿¡·¯¹øÈ£: %d)",
-"È­ÀÏÀ» ãÁö ¸øÇß½À´Ï´Ù.: '%-.64s' (¿¡·¯¹øÈ£: %d)",
-"'%-.64s'µð·ºÅ丮¸¦ ÀÐÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
-"'%-.64s'µð·ºÅ丮·Î À̵¿ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)",
-"Å×À̺í '%-.64s'¿¡¼­ ¸¶Áö¸·À¸·Î ÀÐÀº ÈÄ Record°¡ º¯°æµÇ¾ú½À´Ï´Ù.",
-"Disk full (%s). ´Ù¸¥ »ç¶÷ÀÌ Áö¿ï¶§±îÁö ±â´Ù¸³´Ï´Ù...",
-"±â·ÏÇÒ ¼ö ¾øÀ¾´Ï´Ù., Å×À̺í '%-.64s'¿¡¼­ Áߺ¹ Å°",
-"'%-.64s'´Ý´Â Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)",
-"'%-.64s'È­ÀÏ Àб⠿¡·¯ (¿¡·¯¹øÈ£: %d)",
-"'%-.64s'¸¦ '%-.64s'·Î À̸§ º¯°æÁß ¿¡·¯ (¿¡·¯¹øÈ£: %d)",
-"'%-.64s'È­ÀÏ ±â·Ï Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)",
-"'%-.64s'°¡ º¯°æÇÒ ¼ö ¾øµµ·Ï Àá°ÜÀÖÀ¾´Ï´Ù.",
-"¼ÒÆ®°¡ ÁߴܵǾú½À´Ï´Ù.",
-"ºä '%-.64s'°¡ '%-.64s'¿¡¼­´Â Á¸ÀçÇÏÁö ¾ÊÀ¾´Ï´Ù.",
-"Å×À̺í handler¿¡¼­ %d ¿¡·¯°¡ ¹ß»ý ÇÏ¿´½À´Ï´Ù.",
-"'%-.64s'ÀÇ Å×À̺í handler´Â ÀÌ·¯ÇÑ ¿É¼ÇÀ» Á¦°øÇÏÁö ¾ÊÀ¾´Ï´Ù.",
-"'%-.64s'¿¡¼­ ·¹Äڵ带 ãÀ» ¼ö ¾øÀ¾´Ï´Ù.",
-"È­ÀÏÀÇ ºÎÁ¤È®ÇÑ Á¤º¸: '%-.64s'",
-"'%-.64s' Å×À̺íÀÇ ºÎÁ¤È®ÇÑ Å° Á¸Àç. ¼öÁ¤ÇϽÿÀ!",
-"'%-.64s' Å×À̺íÀÇ ÀÌÀü¹öÁ¯ÀÇ Å° Á¸Àç. ¼öÁ¤ÇϽÿÀ!",
-"Å×À̺í '%-.64s'´Â ÀбâÀü¿ë ÀÔ´Ï´Ù.",
-"Out of memory. µ¥¸óÀ» Àç ½ÇÇà ÈÄ ´Ù½Ã ½ÃÀÛÇϽÿÀ (needed %d bytes)",
-"Out of sort memory. daemon sort bufferÀÇ Å©±â¸¦ Áõ°¡½ÃÅ°¼¼¿ä",
-"'%-.64s' È­ÀÏÀ» Àд µµÁß À߸øµÈ eofÀ» ¹ß°ß (¿¡·¯¹øÈ£: %d)",
-"³Ê¹« ¸¹Àº ¿¬°á... max_connectionÀ» Áõ°¡ ½ÃÅ°½Ã¿À...",
-"Out of memory; mysqld³ª ¶Ç´Ù¸¥ ÇÁ·Î¼¼¼­¿¡¼­ »ç¿ë°¡´ÉÇÑ ¸Þ¸ð¸®¸¦ »ç¿ëÇÑÁö äũÇϽÿÀ. ¸¸¾à ±×·¸Áö ¾Ê´Ù¸é ulimit ¸í·ÉÀ» ÀÌ¿¿ëÇÏ¿© ´õ¸¹Àº ¸Þ¸ð¸®¸¦ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï Çϰųª ½º¿Ò ½ºÆÐÀ̽º¸¦ Áõ°¡½ÃÅ°½Ã¿À",
-"´ç½ÅÀÇ ÄÄÇ»ÅÍÀÇ È£½ºÆ®À̸§À» ¾òÀ» ¼ö ¾øÀ¾´Ï´Ù.",
-"Bad handshake",
-"'%-.32s'@'%-.64s' »ç¿ëÀÚ´Â '%-.64s' µ¥ÀÌŸº£À̽º¿¡ Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù.",
-"'%-.32s'@'%-.64s' »ç¿ëÀÚ´Â Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù. (using password: %s)",
-"¼±ÅÃµÈ µ¥ÀÌŸº£À̽º°¡ ¾ø½À´Ï´Ù.",
-"¸í·É¾î°¡ ¹ºÁö ¸ð¸£°Ú¾î¿ä...",
-"Ä®·³ '%-.64s'´Â ³Î(Null)ÀÌ µÇ¸é ¾ÈµË´Ï´Ù. ",
-"µ¥ÀÌŸº£À̽º '%-.64s'´Â ¾Ë¼ö ¾øÀ½",
-"Å×À̺í '%-.64s'´Â ÀÌ¹Ì Á¸ÀçÇÔ",
-"Å×À̺í '%-.64s'´Â ¾Ë¼ö ¾øÀ½",
-"Ä®·³: '%-.64s' in '%-.64s' ÀÌ ¸ðÈ£ÇÔ",
-"Server°¡ ¼Ë´Ù¿î ÁßÀÔ´Ï´Ù.",
-"Unknown Ä®·³ '%-.64s' in '%-.64s'",
-"'%-.64s'Àº GROUP BY¼Ó¿¡ ¾øÀ½",
-"'%-.64s'¸¦ ±×·ìÇÒ ¼ö ¾øÀ½",
-"Statement °¡ sum±â´ÉÀ» µ¿ÀÛÁßÀÌ°í Ä®·³µµ µ¿ÀÏÇÑ statementÀÔ´Ï´Ù.",
-"Ä®·³ÀÇ Ä«¿îÆ®°¡ °ªÀÇ Ä«¿îÆ®¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù.",
-"Identifier '%-.100s'´Â ³Ê¹« ±æ±º¿ä.",
-"Áߺ¹µÈ Ä®·³ À̸§: '%-.64s'",
-"Áߺ¹µÈ Å° À̸§ : '%-.64s'",
-"Áߺ¹µÈ ÀÔ·Â °ª '%-.64s': key %d",
-"Ä®·³ '%-.64s'ÀÇ ºÎÁ¤È®ÇÑ Ä®·³ Á¤ÀÇÀÚ",
-"'%-.64s' ¿¡·¯ °°À¾´Ï´Ù. ('%-.80s' ¸í·É¾î ¶óÀÎ %d)",
-"Äõ¸®°á°ú°¡ ¾ø½À´Ï´Ù.",
-"Unique ÇÏÁö ¾ÊÀº Å×À̺í/alias: '%-.64s'",
-"'%-.64s'ÀÇ À¯È¿ÇÏÁö ¸øÇÑ µðÆúÆ® °ªÀ» »ç¿ëÇϼ̽À´Ï´Ù.",
-"Multiple primary key°¡ Á¤ÀǵǾî ÀÖ½¿",
-"³Ê¹« ¸¹Àº Å°°¡ Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù.. ÃÖ´ë %dÀÇ Å°°¡ °¡´ÉÇÔ",
-"³Ê¹« ¸¹Àº Å° ºÎºÐ(parts)µéÀÌ Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù.. ÃÖ´ë %d ºÎºÐÀÌ °¡´ÉÇÔ",
-"Á¤ÀÇµÈ Å°°¡ ³Ê¹« ±é´Ï´Ù. ÃÖ´ë Å°ÀÇ ±æÀÌ´Â %dÀÔ´Ï´Ù.",
-"Key Ä®·³ '%-.64s'´Â Å×ÀÌºí¿¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù.",
-"BLOB Ä®·³ '%-.64s'´Â Å° Á¤ÀÇ¿¡¼­ »ç¿ëµÉ ¼ö ¾ø½À´Ï´Ù.",
-"Ä®·³ '%-.64s'ÀÇ Ä®·³ ±æÀÌ°¡ ³Ê¹« ±é´Ï´Ù (ÃÖ´ë = %d). ´ë½Å¿¡ BLOB¸¦ »ç¿ëÇϼ¼¿ä.",
-"ºÎÁ¤È®ÇÑ Å×À̺í Á¤ÀÇ; Å×À̺íÀº ÇϳªÀÇ auto Ä®·³ÀÌ Á¸ÀçÇÏ°í Å°·Î Á¤ÀǵǾîÁ®¾ß ÇÕ´Ï´Ù.",
-"%s: ¿¬°á ÁغñÁßÀÔ´Ï´Ù",
-"%s: Á¤»óÀûÀÎ shutdown\n",
-"%s: %d ½ÅÈ£°¡ µé¾î¿ÔÀ½. ÁßÁö!\n",
-"%s: Shutdown ÀÌ ¿Ï·áµÊ!\n",
-"%s: thread %ldÀÇ °­Á¦ Á¾·á user: '%-.64s'\n",
-"IP ¼ÒÄÏÀ» ¸¸µéÁö ¸øÇß½À´Ï´Ù.",
-"Å×À̺í '%-.64s'´Â À妽º¸¦ ¸¸µéÁö ¾Ê¾Ò½À´Ï´Ù. alter Å×À̺í¸í·ÉÀ» ÀÌ¿ëÇÏ¿© Å×À̺íÀ» ¼öÁ¤Çϼ¼¿ä...",
-"ÇÊµå ±¸ºÐÀÚ ÀμöµéÀÌ ¿ÏÀüÇÏÁö ¾Ê½À´Ï´Ù. ¸Þ´º¾óÀ» ã¾Æ º¸¼¼¿ä.",
-"BLOB·Î´Â °íÁ¤±æÀÌÀÇ lowlength¸¦ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù. 'fields terminated by'¸¦ »ç¿ëÇϼ¼¿ä.",
-"'%-.64s' È­ÀÏ´Â µ¥ÀÌŸº£À̽º µð·ºÅ丮¿¡ Á¸ÀçÇϰųª ¸ðµÎ¿¡°Ô Àб⠰¡´ÉÇÏ¿©¾ß ÇÕ´Ï´Ù.",
-"'%-.64s' È­ÀÏÀº ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù.",
-"·¹ÄÚµå: %ld°³ »èÁ¦: %ld°³ ½ºÅµ: %ld°³ °æ°í: %ld°³",
-"·¹ÄÚµå: %ld°³ Áߺ¹: %ld°³",
-"ºÎÁ¤È®ÇÑ ¼­¹ö ÆÄÆ® Å°. »ç¿ëµÈ Å° ÆÄÆ®°¡ ½ºÆ®¸µÀÌ ¾Æ´Ï°Å³ª Å° ÆÄÆ®ÀÇ ±æÀÌ°¡ ³Ê¹« ±é´Ï´Ù.",
-"ALTER TABLE ¸í·ÉÀ¸·Î´Â ¸ðµç Ä®·³À» Áö¿ï ¼ö ¾ø½À´Ï´Ù. DROP TABLE ¸í·ÉÀ» ÀÌ¿ëÇϼ¼¿ä.",
-"'%-.64s'¸¦ DROPÇÒ ¼ö ¾ø½À´Ï´Ù. Ä®·³À̳ª Å°°¡ Á¸ÀçÇÏ´ÂÁö äũÇϼ¼¿ä.",
-"·¹ÄÚµå: %ld°³ Áߺ¹: %ld°³ °æ°í: %ld°³",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"¾Ë¼ö ¾ø´Â ¾²·¹µå id: %lu",
-"¾²·¹µå(Thread) %luÀÇ ¼ÒÀ¯ÀÚ°¡ ¾Æ´Õ´Ï´Ù.",
-"¾î¶² Å×ÀÌºíµµ »ç¿ëµÇÁö ¾Ê¾Ò½À´Ï´Ù.",
-"Ä®·³ %-.64s¿Í SET¿¡¼­ ½ºÆ®¸µÀÌ ³Ê¹« ¸¹½À´Ï´Ù.",
-"Unique ·Î±×È­ÀÏ '%-.64s'¸¦ ¸¸µé¼ö ¾ø½À´Ï´Ù.(1-999)\n",
-"Å×À̺í '%-.64s'´Â READ ¶ôÀÌ Àá°ÜÀ־ °»½ÅÇÒ ¼ö ¾ø½À´Ï´Ù.",
-"Å×À̺í '%-.64s'´Â LOCK TABLES ¸í·ÉÀ¸·Î Àá±âÁö ¾Ê¾Ò½À´Ï´Ù.",
-"BLOB Ä®·³ '%-.64s' ´Â µðÆúÆ® °ªÀ» °¡Áú ¼ö ¾ø½À´Ï´Ù.",
-"'%-.100s' µ¥ÀÌŸº£À̽ºÀÇ À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.",
-"'%-.100s' Å×À̺í À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.",
-"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.",
-"¾Ë¼ö ¾ø´Â ¿¡·¯ÀÔ´Ï´Ù.",
-"¾Ë¼ö ¾ø´Â ¼öÇ๮ : '%-.64s'",
-"'%-.64s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆĶó¸ÞÅÍ",
-"'%-.64s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆĶó¸ÞÅÍ",
-"¾Ë¼ö ¾ø´Â Å×À̺í '%-.64s' (µ¥ÀÌŸº£À̽º %s)",
-"Ä®·³ '%-.64s'´Â µÎ¹ø Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù.",
-"À߸øµÈ ±×·ì ÇÔ¼ö¸¦ »ç¿ëÇÏ¿´½À´Ï´Ù.",
-"Å×À̺í '%-.64s'´Â È®Àå¸í·ÉÀ» ÀÌ¿ëÇÏÁö¸¸ ÇöÀçÀÇ MySQL ¹öÁ¯¿¡¼­´Â Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù.",
-"ÇϳªÀÇ Å×ÀÌºí¿¡¼­´Â Àû¾îµµ ÇϳªÀÇ Ä®·³ÀÌ Á¸ÀçÇÏ¿©¾ß ÇÕ´Ï´Ù.",
-"Å×À̺í '%-.64s'°¡ full³µ½À´Ï´Ù. ",
-"¾Ë¼ö¾ø´Â ¾ð¾î Set: '%-.64s'",
-"³Ê¹« ¸¹Àº Å×À̺íÀÌ JoinµÇ¾ú½À´Ï´Ù. MySQL¿¡¼­´Â JOIN½Ã %d°³ÀÇ Å×ÀÌºí¸¸ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù.",
-"Ä®·³ÀÌ ³Ê¹« ¸¹½À´Ï´Ù.",
-"³Ê¹« Å« row »çÀÌÁîÀÔ´Ï´Ù. BLOB¸¦ °è»êÇÏÁö ¾Ê°í ÃÖ´ë row »çÀÌÁî´Â %dÀÔ´Ï´Ù. ¾ó¸¶°£ÀÇ ÇʵåµéÀ» BLOB·Î ¹Ù²Ù¼Å¾ß °Ú±º¿ä..",
-"¾²·¹µå ½ºÅÃÀÌ ³ÑÃƽÀ´Ï´Ù. »ç¿ë: %ld°³ ½ºÅÃ: %ld°³. ¸¸¾à ÇÊ¿ä½Ã ´õÅ« ½ºÅÃÀ» ¿øÇÒ¶§¿¡´Â 'mysqld -O thread_stack=#' ¸¦ Á¤ÀÇÇϼ¼¿ä",
-"Cross dependency found in OUTER JOIN; examine your ON conditions",
-"'%-.64s' Ä®·³ÀÌ UNIQUE³ª INDEX¸¦ »ç¿ëÇÏ¿´Áö¸¸ NOT NULLÀÌ Á¤ÀǵÇÁö ¾Ê¾Ò±º¿ä...",
-"'%-.64s' ÇÔ¼ö¸¦ ·ÎµåÇÏÁö ¸øÇß½À´Ï´Ù.",
-"'%-.64s' ÇÔ¼ö¸¦ ÃʱâÈ­ ÇÏÁö ¸øÇß½À´Ï´Ù.; %-.80s",
-"°øÀ¯ ¶óÀ̹ö·¯¸®¸¦ À§ÇÑ Æнº°¡ Á¤ÀǵǾî ÀÖÁö ¾Ê½À´Ï´Ù.",
-"'%-.64s' ÇÔ¼ö´Â ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù.",
-"'%-.64s' °øÀ¯ ¶óÀ̹ö·¯¸®¸¦ ¿­¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£: %d %s)",
-"¶óÀ̹ö·¯¸®¿¡¼­ '%-.64s' ÇÔ¼ö¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù.",
-"'%-.64s' ÇÔ¼ö°¡ Á¤ÀǵǾî ÀÖÁö ¾Ê½À´Ï´Ù.",
-"³Ê¹« ¸¹Àº ¿¬°á¿À·ù·Î ÀÎÇÏ¿© È£½ºÆ® '%-.64s'´Â ºí¶ôµÇ¾ú½À´Ï´Ù. 'mysqladmin flush-hosts'¸¦ ÀÌ¿ëÇÏ¿© ºí¶ôÀ» ÇØÁ¦Çϼ¼¿ä",
-"'%-.64s' È£½ºÆ®´Â ÀÌ MySQL¼­¹ö¿¡ Á¢¼ÓÇÒ Çã°¡¸¦ ¹ÞÁö ¸øÇß½À´Ï´Ù.",
-"´ç½ÅÀº MySQL¼­¹ö¿¡ À͸íÀÇ »ç¿ëÀÚ·Î Á¢¼ÓÀ» Çϼ̽À´Ï´Ù.À͸íÀÇ »ç¿ëÀÚ´Â ¾ÏÈ£¸¦ º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù.",
-"´ç½ÅÀº ´Ù¸¥»ç¿ëÀÚµéÀÇ ¾ÏÈ£¸¦ º¯°æÇÒ ¼ö ÀÖµµ·Ï µ¥ÀÌŸº£À̽º º¯°æ±ÇÇÑÀ» °¡Á®¾ß ÇÕ´Ï´Ù.",
-"»ç¿ëÀÚ Å×ÀÌºí¿¡¼­ ÀÏÄ¡ÇÏ´Â °ÍÀ» ãÀ» ¼ö ¾øÀ¾´Ï´Ù.",
-"ÀÏÄ¡ÇÏ´Â Rows : %ld°³ º¯°æµÊ: %ld°³ °æ°í: %ld°³",
-"»õ·Î¿î ¾²·¹µå¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£ %d). ¸¸¾à ¿©À¯¸Þ¸ð¸®°¡ ÀÖ´Ù¸é OS-dependent¹ö±× ÀÇ ¸Þ´º¾ó ºÎºÐÀ» ã¾Æº¸½Ã¿À.",
-"Row %ld¿¡¼­ Ä®·³ Ä«¿îÆ®¿Í value Ä«¿îÅÍ¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù.",
-"Å×À̺íÀ» ´Ù½Ã ¿­¼ö ¾ø±º¿ä: '%-.64s",
-"NULL °ªÀ» À߸ø »ç¿ëÇϼ̱º¿ä...",
-"regexp¿¡¼­ '%-.64s'°¡ ³µ½À´Ï´Ù.",
-"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'",
-"À߸øµÈ GRANT/REVOKE ¸í·É. ¾î¶² ±Ç¸®¿Í ½ÂÀÎÀÌ »ç¿ëµÇ¾î Áú ¼ö ÀÖ´ÂÁö ¸Þ´º¾óÀ» º¸½Ã¿À.",
-"½ÂÀÎ(GRANT)À» À§ÇÏ¿© »ç¿ëÇÑ »ç¿ëÀÚ³ª È£½ºÆ®ÀÇ °ªµéÀÌ ³Ê¹« ±é´Ï´Ù.",
-"Å×À̺í '%-.64s.%s' ´Â Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù.",
-"»ç¿ëÀÚ '%-.32s'(È£½ºÆ® '%-.64s')´Â Å×À̺í '%-.64s'¸¦ »ç¿ëÇϱâ À§ÇÏ¿© Á¤ÀÇµÈ ½ÂÀÎÀº ¾ø½À´Ï´Ù. ",
-"»ç¿ëµÈ ¸í·ÉÀº ÇöÀçÀÇ MySQL ¹öÁ¯¿¡¼­´Â ÀÌ¿ëµÇÁö ¾Ê½À´Ï´Ù.",
-"SQL ±¸¹®¿¡ ¿À·ù°¡ ÀÖ½À´Ï´Ù.",
-"Áö¿¬µÈ insert ¾²·¹µå°¡ Å×À̺í %-.64sÀÇ ¿ä±¸µÈ ¶ôÅ·À» ó¸®ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù.",
-"³Ê¹« ¸¹Àº Áö¿¬ ¾²·¹µå¸¦ »ç¿ëÇÏ°í ÀÖ½À´Ï´Ù.",
-"µ¥ÀÌŸº£À̽º Á¢¼ÓÀ» À§ÇÑ ¿¬°á %ld°¡ Áß´ÜµÊ : '%-.64s' »ç¿ëÀÚ: '%-.64s' (%s)",
-"'max_allowed_packet'º¸´Ù ´õÅ« ÆÐŶÀ» ¹Þ¾Ò½À´Ï´Ù.",
-"¿¬°á ÆÄÀÌÇÁ·ÎºÎÅÍ ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
-"fcntl() ÇÔ¼ö·ÎºÎÅÍ ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
-"¼ø¼­°¡ ¸ÂÁö¾Ê´Â ÆÐŶÀ» ¹Þ¾Ò½À´Ï´Ù.",
-"Åë½Å ÆÐŶÀÇ ¾ÐÃàÇØÁ¦¸¦ ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù.",
-"Åë½Å ÆÐŶÀ» Àд Áß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
-"Åë½Å ÆÐŶÀ» Àд Áß timeoutÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
-"Åë½Å ÆÐŶÀ» ±â·ÏÇÏ´Â Áß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
-"Åë½Å ÆÐÆÂÀ» ±â·ÏÇÏ´Â Áß timeoutÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù.",
-"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",
-"Incorrect column name '%-.100s'",
-"The used table handler can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
deleted file mode 100644
index 3f60876348f..00000000000
--- a/sql/share/norwegian-ny/errmsg.txt
+++ /dev/null
@@ -1,324 +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 */
-
-/* Roy-Magne Mo rmo@www.hivolda.no 97 */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NEI",
-"JA",
-"Kan ikkje opprette fila '%-.64s' (Feilkode: %d)",
-"Kan ikkje opprette tabellen '%-.64s' (Feilkode: %d)",
-"Kan ikkje opprette databasen '%-.64s' (Feilkode: %d)",
-"Kan ikkje opprette databasen '%-.64s'; databasen eksisterer",
-"Kan ikkje fjerne (drop) '%-.64s'; databasen eksisterer ikkje",
-"Feil ved fjerning (drop) av databasen (kan ikkje slette '%-.64s', feil %d)",
-"Feil ved sletting av database (kan ikkje slette katalogen '%-.64s', feil %d)",
-"Feil ved sletting av '%-.64s' (Feilkode: %d)",
-"Kan ikkje lese posten i systemkatalogen",
-"Kan ikkje lese statusen til '%-.64s' (Feilkode: %d)",
-"Kan ikkje lese aktiv katalog(Feilkode: %d)",
-"Kan ikkje låse fila (Feilkode: %d)",
-"Kan ikkje åpne fila: '%-.64s' (Feilkode: %d)",
-"Kan ikkje finne fila: '%-.64s' (Feilkode: %d)",
-"Kan ikkje lese katalogen '%-.64s' (Feilkode: %d)",
-"Kan ikkje skifte katalog til '%-.64s' (Feilkode: %d)",
-"Posten har vorte endra sidan den sist vart lesen '%-.64s'",
-"Ikkje meir diskplass (%s). Ventar på å få frigjort plass...",
-"Kan ikkje skrive, flere like nyklar i tabellen '%-.64s'",
-"Feil ved lukking av '%-.64s' (Feilkode: %d)",
-"Feil ved lesing av '%-.64s' (Feilkode: %d)",
-"Feil ved omdøyping av '%-.64s' til '%-.64s' (Feilkode: %d)",
-"Feil ved skriving av fila '%-.64s' (Feilkode: %d)",
-"'%-.64s' er låst mot oppdateringar",
-"Sortering avbrote",
-"View '%-.64s' eksisterar ikkje for '%-.64s'",
-"Mottok feil %d fra tabell handterar",
-"Tabell håndteraren for '%-.64s' har ikkje denne moglegheita",
-"Kan ikkje finne posten i '%-.64s'",
-"Feil informasjon i fila: '%-.64s'",
-"Tabellen '%-.64s' har feil i nykkelfila; prøv å reparere den",
-"Gammel nykkelfil for tabellen '%-.64s'; reparer den!",
-"'%-.64s' er skrivetryggja",
-"Ikkje meir minne. Start på nytt tenesten og prøv igjen (trengte %d bytar)",
-"Ikkje meir sorteringsminne. Auk sorteringsminnet (sorteringsbffer storleik) for tenesten",
-"Uventa slutt på fil (eof) ved lesing av fila '%-.64s' (Feilkode: %d)",
-"For mange tilkoplingar (connections)",
-"Tomt for tråd plass/minne",
-"Kan ikkje få tak i vertsnavn for di adresse",
-"Feil handtrykk (handshake)",
-"Tilgang ikkje tillate for brukar: '%-.32s'@'%-.64s' til databasen '%-.64s' nekta",
-"Tilgang ikke tillate for brukar: '%-.32s'@'%-.64s' (Brukar passord: %s)",
-"Ingen database vald",
-"Ukjent kommando",
-"Kolonne '%-.64s' kan ikkje vere null",
-"Ukjent database '%-.64s'",
-"Tabellen '%-.64s' eksisterar allereide",
-"Ukjent tabell '%-.64s'",
-"Kolonne: '%-.64s' i tabell %s er ikkje eintydig",
-"Tenar nedkopling er i gang",
-"Ukjent felt '%-.64s' i tabell %s",
-"Brukte '%-.64s' som ikkje var i group by",
-"Kan ikkje gruppere på '%-.64s'",
-"Uttrykket har summer (sum) funksjoner og kolonner i same uttrykk",
-"Kolonne telling stemmer verdi telling",
-"Identifikator '%-.64s' er for lang",
-"Feltnamnet '%-.64s' eksisterte frå før",
-"Nøkkelnamnet '%-.64s' eksisterte frå før",
-"Like verdiar '%-.64s' for nykkel %d",
-"Feil kolonne spesifikator for kolonne '%-.64s'",
-"%s attmed '%-.64s' på line %d",
-"Førespurnad var tom",
-"Ikkje unikt tabell/alias: '%-.64s'",
-"Ugyldig standardverdi for '%-.64s'",
-"Fleire primærnyklar spesifisert",
-"For mange nykler spesifisert. Maks %d nyklar tillatt",
-"For mange nykkeldelar spesifisert. Maks %d delar tillatt",
-"Spesifisert nykkel var for lang. Maks nykkellengde er %d",
-"Nykkel kolonne '%-.64s' eksiterar ikkje i tabellen",
-"Blob kolonne '%-.64s' kan ikkje brukast ved spesifikasjon av nyklar",
-"For stor nykkellengde for felt '%-.64s' (maks = %d). Bruk BLOB istadenfor",
-"Bare eitt auto felt kan være definert som nøkkel.",
-"%s: klar for tilkoblingar",
-"%s: Normal nedkopling\n",
-"%s: Oppdaga signal %d. Avsluttar!\n",
-"%s: Nedkopling komplett\n",
-"%s: Påtvinga avslutning av tråd %ld brukar: '%-.64s'\n",
-"Kan ikkje opprette IP socket",
-"Tabellen '%-.64s' har ingen index som den som er brukt i CREATE INDEX. Oprett tabellen på nytt",
-"Felt skiljer argumenta er ikkje som venta, sjå dokumentasjonen",
-"Ein kan ikkje bruke faste feltlengder med BLOB. Vennlisgt bruk 'fields terminated by'.",
-"Filen '%-.64s' må være i database-katalogen for å være lesbar for alle",
-"Filen '%-.64s' eksisterte allereide",
-"Poster: %ld Fjerna: %ld Hoppa over: %ld Åtvaringar: %ld",
-"Poster: %ld Like: %ld",
-"Feil delnykkel. Den brukte delnykkelen er ikkje ein streng eller den oppgitte lengda er lengre enn nykkellengden",
-"Ein kan ikkje slette alle felt med ALTER TABLE. Bruk DROP TABLE istadenfor.",
-"Kan ikkje DROP '%-.64s'. Undersøk om felt/nøkkel eksisterar.",
-"Postar: %ld Like: %ld Åtvaringar: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Ukjent tråd id: %lu",
-"Du er ikkje eigar av tråd %lu",
-"Ingen tabellar i bruk",
-"For mange tekststrengar felt %s og SET",
-"Kan ikkje lage unikt loggfilnavn %s.(1-999)\n",
-"Tabellen '%-.64s' var låst med READ lås og kan ikkje oppdaterast",
-"Tabellen '%-.64s' var ikkje låst med LOCK TABLES",
-"Blob feltet '%-.64s' kan ikkje ha ein standard verdi",
-"Ugyldig database namn '%-.64s'",
-"Ugyldig tabell namn '%-.64s'",
-"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt",
-"Ukjend feil",
-"Ukjend prosedyre %s",
-"Feil parameter tal til prosedyra %s",
-"Feil parameter til prosedyra %s",
-"Ukjend tabell '%-.64s' i %s",
-"Feltet '%-.64s' er spesifisert to gangar",
-"Invalid use of group function",
-"Table '%-.64s' uses a extension that doesn't exist in this MySQL version",
-"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 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",
-"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 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 not allowed to connect to this MySQL server",
-"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",
-"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",
-"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 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'",
-"The used command is not allowed with this MySQL version",
-"Something is wrong in your syntax",
-"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' bytes",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Couldn't uncompress communication packet",
-"Got an error reading communication packets",
-"Got timeout reading communication packets",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
-"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",
-"Incorrect column name '%-.100s'",
-"The used table handler can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
deleted file mode 100644
index badeed1c0dd..00000000000
--- a/sql/share/norwegian/errmsg.txt
+++ /dev/null
@@ -1,324 +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 */
-
-/* Roy-Magne Mo rmo@www.hivolda.no 97 */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NEI",
-"JA",
-"Kan ikke opprette fila '%-.64s' (Feilkode: %d)",
-"Kan ikke opprette tabellen '%-.64s' (Feilkode: %d)",
-"Kan ikke opprette databasen '%-.64s' (Feilkode: %d)",
-"Kan ikke opprette databasen '%-.64s'; databasen eksisterer",
-"Kan ikke fjerne (drop) '%-.64s'; databasen eksisterer ikke",
-"Feil ved fjerning (drop) av databasen (kan ikke slette '%-.64s', feil %d)",
-"Feil ved sletting av database (kan ikke slette katalogen '%-.64s', feil %d)",
-"Feil ved sletting av '%-.64s' (Feilkode: %d)",
-"Kan ikke lese posten i systemkatalogen",
-"Kan ikke lese statusen til '%-.64s' (Feilkode: %d)",
-"Kan ikke lese aktiv katalog(Feilkode: %d)",
-"Kan ikke låse fila (Feilkode: %d)",
-"Kan ikke åpne fila: '%-.64s' (Feilkode: %d)",
-"Kan ikke finne fila: '%-.64s' (Feilkode: %d)",
-"Kan ikke lese katalogen '%-.64s' (Feilkode: %d)",
-"Kan ikke skifte katalog til '%-.64s' (Feilkode: %d)",
-"Posten har blitt endret siden den ble lest '%-.64s'",
-"Ikke mer diskplass (%s). Venter på å få frigjort plass...",
-"Kan ikke skrive, flere like nøkler i tabellen '%-.64s'",
-"Feil ved lukking av '%-.64s' (Feilkode: %d)",
-"Feil ved lesing av '%-.64s' (Feilkode: %d)",
-"Feil ved omdøping av '%-.64s' til '%-.64s' (Feilkode: %d)",
-"Feil ved skriving av fila '%-.64s' (Feilkode: %d)",
-"'%-.64s' er låst mot oppdateringer",
-"Sortering avbrutt",
-"View '%-.64s' eksisterer ikke for '%-.64s'",
-"Mottok feil %d fra tabell håndterer",
-"Tabell håndtereren for '%-.64s' har ikke denne muligheten",
-"Kan ikke finne posten i '%-.64s'",
-"Feil informasjon i filen: '%-.64s'",
-"Tabellen '%-.64s' har feil i nøkkelfilen; forsøk å reparer den",
-"Gammel nøkkelfil for tabellen '%-.64s'; reparer den!",
-"'%-.64s' er skrivebeskyttet",
-"Ikke mer minne. Star på nytt tjenesten og prøv igjen (trengte %d byter)",
-"Ikke mer sorteringsminne. Øk sorteringsminnet (sort buffer size) for tjenesten",
-"Uventet slutt på fil (eof) ved lesing av filen '%-.64s' (Feilkode: %d)",
-"For mange tilkoblinger (connections)",
-"Tomt for tråd plass/minne",
-"Kan ikke få tak i vertsnavn for din adresse",
-"Feil håndtrykk (handshake)",
-"Tilgang nektet for bruker: '%-.32s'@'%-.64s' til databasen '%-.64s' nektet",
-"Tilgang nektet for bruker: '%-.32s'@'%-.64s' (Bruker passord: %s)",
-"Ingen database valgt",
-"Ukjent kommando",
-"Kolonne '%-.64s' kan ikke vere null",
-"Ukjent database '%-.64s'",
-"Tabellen '%-.64s' eksisterer allerede",
-"Ukjent tabell '%-.64s'",
-"Felt: '%-.64s' i tabell %s er ikke entydig",
-"Database nedkobling er i gang",
-"Ukjent kolonne '%-.64s' i tabell %s",
-"Brukte '%-.64s' som ikke var i group by",
-"Kan ikke gruppere på '%-.64s'",
-"Uttrykket har summer (sum) funksjoner og kolonner i samme uttrykk",
-"Felt telling stemmer verdi telling",
-"Identifikator '%-.64s' er for lang",
-"Feltnavnet '%-.64s' eksisterte fra før",
-"Nøkkelnavnet '%-.64s' eksisterte fra før",
-"Like verdier '%-.64s' for nøkkel %d",
-"Feil kolonne spesifikator for felt '%-.64s'",
-"%s nær '%-.64s' på linje %d",
-"Forespørsel var tom",
-"Ikke unikt tabell/alias: '%-.64s'",
-"Ugyldig standardverdi for '%-.64s'",
-"Fleire primærnøkle spesifisert",
-"For mange nøkler spesifisert. Maks %d nøkler tillatt",
-"For mange nøkkeldeler spesifisert. Maks %d deler tillatt",
-"Spesifisert nøkkel var for lang. Maks nøkkellengde er is %d",
-"Nøkkel felt '%-.64s' eksiterer ikke i tabellen",
-"Blob felt '%-.64s' kan ikke brukes ved spesifikasjon av nøkler",
-"For stor nøkkellengde for kolonne '%-.64s' (maks = %d). Bruk BLOB istedenfor",
-"Bare ett auto felt kan være definert som nøkkel.",
-"%s: klar for tilkoblinger",
-"%s: Normal avslutning\n",
-"%s: Oppdaget signal %d. Avslutter!\n",
-"%s: Avslutning komplett\n",
-"%s: Påtvinget avslutning av tråd %ld bruker: '%-.64s'\n",
-"Kan ikke opprette IP socket",
-"Tabellen '%-.64s' har ingen index som den som er brukt i CREATE INDEX. Gjenopprett tabellen",
-"Felt skiller argumentene er ikke som forventet, se dokumentasjonen",
-"En kan ikke bruke faste feltlengder med BLOB. Vennlisgt bruk 'fields terminated by'.",
-"Filen '%-.64s' må være i database-katalogen for å være lesbar for alle",
-"Filen '%-.64s' eksisterte allerede",
-"Poster: %ld Fjernet: %ld Hoppet over: %ld Advarsler: %ld",
-"Poster: %ld Like: %ld",
-"Feil delnøkkel. Den brukte delnøkkelen er ikke en streng eller den oppgitte lengde er lengre enn nøkkel lengden",
-"En kan ikke slette alle felt med ALTER TABLE. Bruk DROP TABLE isteden.",
-"Kan ikke DROP '%-.64s'. Undersøk om felt/nøkkel eksisterer.",
-"Poster: %ld Like: %ld Advarsler: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Ukjent tråd id: %lu",
-"Du er ikke eier av tråden %lu",
-"Ingen tabeller i bruk",
-"For mange tekststrenger kolonne %s og SET",
-"Kan ikke lage unikt loggfilnavn %s.(1-999)\n",
-"Tabellen '%-.64s' var låst med READ lås og kan ikke oppdateres",
-"Tabellen '%-.64s' var ikke låst med LOCK TABLES",
-"Blob feltet '%-.64s' kan ikke ha en standard verdi",
-"Ugyldig database navn '%-.64s'",
-"Ugyldig tabell navn '%-.64s'",
-"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt",
-"Ukjent feil",
-"Ukjent prosedyre %s",
-"Feil parameter antall til prosedyren %s",
-"Feil parametre til prosedyren %s",
-"Ukjent tabell '%-.64s' i %s",
-"Feltet '%-.64s' er spesifisert to ganger",
-"Invalid use of group function",
-"Table '%-.64s' uses a extension that doesn't exist in this MySQL version",
-"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 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",
-"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 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 not allowed to connect to this MySQL server",
-"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",
-"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",
-"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 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'",
-"The used command is not allowed with this MySQL version",
-"Something is wrong in your syntax",
-"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' bytes",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Couldn't uncompress communication packet",
-"Got an error reading communication packets",
-"Got timeout reading communication packets",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
-"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",
-"Incorrect column name '%-.100s'",
-"The used table handler can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
deleted file mode 100644
index 664a8e8e539..00000000000
--- a/sql/share/polish/errmsg.txt
+++ /dev/null
@@ -1,327 +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 */
-
-/*
- Changed by Jaroslaw Lewandowski <jotel@itnet.com.pl>
- Charset ISO-8859-2
-*/
-
-character-set=latin2
-
-"hashchk",
-"isamchk",
-"NIE",
-"TAK",
-"Nie mo¿na stworzyæ pliku '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na stworzyæ tabeli '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na stworzyæ bazy danych '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na stworzyæ bazy danych '%-.64s'; baza danych ju¿ istnieje",
-"Nie mo¿na usun?æ bazy danych '%-.64s'; baza danych nie istnieje",
-"B³?d podczas usuwania bazy danych (nie mo¿na usun?æ '%-.64s', b³?d %d)",
-"B³?d podczas usuwania bazy danych (nie mo¿na wykonaæ rmdir '%-.64s', b³?d %d)",
-"B³?d podczas usuwania '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na odczytaæ rekordu z tabeli systemowej",
-"Nie mo¿na otrzymaæ statusu '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na rozpoznaæ aktualnego katalogu (Kod b³êdu: %d)",
-"Nie mo¿na zablokowaæ pliku (Kod b³êdu: %d)",
-"Nie mo¿na otworzyæ pliku: '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na znale¥æ pliku: '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na odczytaæ katalogu '%-.64s' (Kod b³êdu: %d)",
-"Nie mo¿na zmieniæ katalogu na '%-.64s' (Kod b³êdu: %d)",
-"Rekord zosta³ zmieniony od ostaniego odczytania z tabeli '%-.64s'",
-"Dysk pe³ny (%s). Oczekiwanie na zwolnienie miejsca...",
-"Nie mo¿na zapisaæ, powtórzone klucze w tabeli '%-.64s'",
-"B³?d podczas zamykania '%-.64s' (Kod b³êdu: %d)",
-"B³?d podczas odczytu pliku '%-.64s' (Kod b³êdu: %d)",
-"B³?d podczas zmieniania nazwy '%-.64s' na '%-.64s' (Kod b³êdu: %d)",
-"B³?d podczas zapisywania pliku '%-.64s' (Kod b³êdu: %d)",
-"'%-.64s' jest zablokowany na wypadek zmian",
-"Sortowanie przerwane",
-"Widok '%-.64s' nie istnieje dla '%-.64s'",
-"Otrzymano b³?d %d z obs³ugi tabeli",
-"Obs³uga tabeli '%-.64s' nie posiada tej opcji",
-"Nie mo¿na znale¥æ rekordu w '%-.64s'",
-"Niew³a?ciwa informacja w pliku: '%-.64s'",
-"Niew³a?ciwy plik kluczy dla tabeli: '%-.64s'; spróbuj go naprawiæ",
-"Plik kluczy dla tabeli '%-.64s' jest starego typu; napraw go!",
-"'%-.64s' jest tylko do odczytu",
-"Zbyt ma³o pamiêci. Uruchom ponownie demona i spróbuj ponownie (potrzeba %d bajtów)",
-"Zbyt ma³o pamiêci dla sortowania. Zwiêksz wielko?æ bufora demona dla sortowania",
-"Nieoczekiwany 'eof' napotkany podczas czytania z pliku '%-.64s' (Kod b³êdu: %d)",
-"Zbyt wiele po³?czeñ",
-"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)",
-"Nie wybrano ¿adnej bazy danych",
-"Nieznana komenda",
-"Kolumna '%-.64s' nie mo¿e byæ null",
-"Nieznana baza danych '%-.64s'",
-"Tabela '%-.64s' ju¿ istnieje",
-"Nieznana tabela '%-.64s'",
-"Kolumna: '%-.64s' w %s jest dwuznaczna",
-"Trwa koñczenie dzia³ania serwera",
-"Nieznana kolumna '%-.64s' w %s",
-"U¿yto '%-.64s' bez umieszczenia w group by",
-"Nie mo¿na grupowaæ po '%-.64s'",
-"Zapytanie ma funkcje sumuj?ce i kolumny w tym samym zapytaniu",
-"Liczba kolumn nie odpowiada liczbie warto?ci",
-"Nazwa identyfikatora '%-.64s' jest zbyt d³uga",
-"Powtórzona nazwa kolumny '%-.64s'",
-"Powtórzony nazwa klucza '%-.64s'",
-"Powtórzone wyst?pienie '%-.64s' dla klucza %d",
-"B³êdna specyfikacja kolumny dla kolumny '%-.64s'",
-"%s obok '%-.64s' w linii %d",
-"Zapytanie by³o puste",
-"Tabela/alias nie s? unikalne: '%-.64s'",
-"Niew³a?ciwa warto?æ domy?lna dla '%-.64s'",
-"Zdefiniowano wiele kluczy podstawowych",
-"Okre?lono zbyt wiele kluczy. Dostêpnych jest maksymalnie %d kluczy",
-"Okre?lono zbyt wiele czê?ci klucza. Dostêpnych jest maksymalnie %d czê?ci",
-"Zdefinowany klucz jest zbyt d³ugi. Maksymaln? d³ugo?ci? klucza jest %d",
-"Kolumna '%-.64s' zdefiniowana w kluczu nie istnieje w tabeli",
-"Kolumna typu Blob '%-.64s' nie mo¿e byæ u¿yta w specyfikacji klucza",
-"Zbyt du¿a d³ugo?æ kolumny '%-.64s' (maks. = %d). W zamian u¿yj typu BLOB",
-"W tabeli mo¿e byæ tylko jedno pole auto i musi ono byæ zdefiniowane jako klucz",
-"%s: gotowe do po³?czenia",
-"%s: Standardowe zakoñczenie dzia³ania\n",
-"%s: Otrzymano sygna³ %d. Koñczenie dzia³ania!\n",
-"%s: Zakoñczenie dzia³ania wykonane\n",
-"%s: Wymuszenie zamkniêcia w?tku %ld u¿ytkownik: '%-.64s'\n",
-"Nie mo¿na stworzyæ socket'u IP",
-"Tabela '%-.64s' nie ma indeksu takiego jak w CREATE INDEX. Stwórz tabelê",
-"Nie oczekiwano separatora. Sprawd¥ podrêcznik",
-"Nie mo¿na u¿yæ sta³ej d³ugo?ci wiersza z polami typu BLOB. U¿yj 'fields terminated by'.",
-"Plik '%-.64s' musi znajdowaæ sie w katalogu bazy danych lub mieæ prawa czytania przez wszystkich",
-"Plik '%-.64s' ju¿ istnieje",
-"Recordów: %ld Usuniêtych: %ld Pominiêtych: %ld Ostrze¿eñ: %ld",
-"Rekordów: %ld Duplikatów: %ld",
-"B³êdna podczê?æ klucza. U¿yta czê?æ klucza nie jest ³añcuchem lub u¿yta d³ugo?æ jest wiêksza ni¿ czê?æ klucza",
-"Nie mo¿na usun?æ wszystkich pól wykorzystuj?c ALTER TABLE. W zamian u¿yj DROP TABLE",
-"Nie mo¿na wykonaæ operacji DROP '%-.64s'. Sprawd¥, czy to pole/klucz istnieje",
-"Rekordów: %ld Duplikatów: %ld Ostrze¿eñ: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Nieznany identyfikator w?tku: %lu",
-"Nie jeste? w³a?cicielem w?tku %lu",
-"Nie ma ¿adej u¿ytej tabeli",
-"Zbyt wiele ³añcuchów dla kolumny %s i polecenia SET",
-"Nie mo¿na stworzyæ unikalnej nazwy pliku z logiem %s.(1-999)\n",
-"Tabela '%-.64s' zosta³a zablokowana przez READ i nie mo¿e zostaæ zaktualizowana",
-"Tabela '%-.64s' nie zosta³a zablokowana poleceniem LOCK TABLES",
-"Pole typu blob '%-.64s' nie mo¿e mieæ domy?lnej warto?ci",
-"Niedozwolona nazwa bazy danych '%-.64s'",
-"Niedozwolona nazwa tabeli '%-.64s'...",
-"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",
-"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",
-"Table '%-.64s' uses a extension that doesn't exist in this MySQL version",
-"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 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",
-"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 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 not allowed to connect to this MySQL server",
-"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",
-"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",
-"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 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'",
-"The used command is not allowed with this MySQL version",
-"Something is wrong in your syntax",
-"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' bytes",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Couldn't uncompress communication packet",
-"Got an error reading communication packets",
-"Got timeout reading communication packets",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
-"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",
-"Incorrect column name '%-.100s'",
-"The used table handler can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
deleted file mode 100644
index 453c9dd5c18..00000000000
--- a/sql/share/portuguese/errmsg.txt
+++ /dev/null
@@ -1,324 +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 */
-
-/* Updated by Thiago Delgado Pinto - thiagodp@ieg.com.br - 06.07.2002 */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NÃO",
-"SIM",
-"Não pode criar o arquivo '%-.64s' (erro no. %d)",
-"Não pode criar a tabela '%-.64s' (erro no. %d)",
-"Não pode criar o banco de dados '%-.64s' (erro no. %d)",
-"Não pode criar o banco de dados '%-.64s'; este banco de dados já existe",
-"Não pode eliminar o banco de dados '%-.64s'; este banco de dados não existe",
-"Erro ao eliminar banco de dados (não pode eliminar '%-.64s' - erro no. %d)",
-"Erro ao eliminar banco de dados (não pode remover diretório '%-.64s' - erro no. %d)",
-"Erro na remoção de '%-.64s' (erro no. %d)",
-"Não pode ler um registro numa tabela do sistema",
-"Não pode obter o status de '%-.64s' (erro no. %d)",
-"Não pode obter o diretório corrente (erro no. %d)",
-"Não pode travar o arquivo (erro no. %d)",
-"Não pode abrir o arquivo '%-.64s' (erro no. %d)",
-"Não pode encontrar o arquivo '%-.64s' (erro no. %d)",
-"Não pode ler o diretório de '%-.64s' (erro no. %d)",
-"Não pode mudar para o diretório '%-.64s' (erro no. %d)",
-"Registro alterado desde a última leitura da tabela '%-.64s'",
-"Disco cheio (%s). Aguardando alguém liberar algum espaço...",
-"Não pode gravar. Chave duplicada na tabela '%-.64s'",
-"Erro ao fechar '%-.64s' (erro no. %d)",
-"Erro ao ler arquivo '%-.64s' (erro no. %d)",
-"Erro ao renomear '%-.64s' para '%-.64s' (erro no. %d)",
-"Erro ao gravar arquivo '%-.64s' (erro no. %d)",
-"'%-.64s' está com travamento contra alterações",
-"Ordenação abortada",
-"Visão '%-.64s' não existe para '%-.64s'",
-"Obteve erro %d no manipulador de tabelas",
-"Manipulador de tabela para '%-.64s' não tem esta opção",
-"Não pode encontrar registro em '%-.64s'",
-"Informação incorreta no arquivo '%-.64s'",
-"Arquivo de índice incorreto para tabela '%-.64s'; tente repará-lo",
-"Arquivo de índice desatualizado para tabela '%-.64s'; repare-o!",
-"Tabela '%-.64s' é somente para leitura",
-"Sem memória. Reinicie o programa e tente novamente (necessita de %d bytes)",
-"Sem memória para ordenação. Aumente tamanho do 'buffer' de ordenação",
-"Encontrado fim de arquivo inesperado ao ler arquivo '%-.64s' (erro no. %d)",
-"Excesso de conexões",
-"Sem memória. Verifique se o mysqld ou algum outro processo está usando toda memória disponível. Se não, você pode ter que usar 'ulimit' para permitir ao mysqld usar mais memória ou você pode adicionar mais área de 'swap'",
-"Não pode obter nome do 'host' para seu endereço",
-"Negociação de acesso falhou",
-"Acesso negado para o usuário '%-.32s'@'%-.64s' ao banco de dados '%-.64s'",
-"Acesso negado para o usuário '%-.32s'@'%-.64s' (senha usada: %s)",
-"Nenhum banco de dados foi selecionado",
-"Comando desconhecido",
-"Coluna '%-.64s' não pode ser vazia",
-"Banco de dados '%-.64s' desconhecido",
-"Tabela '%-.64s' já existe",
-"Tabela '%-.64s' desconhecida",
-"Coluna '%-.64s' em '%-.64s' é ambígua",
-"'Shutdown' do servidor em andamento",
-"Coluna '%-.64s' desconhecida em '%-.64s'",
-"'%-.64s' não está em 'GROUP BY'",
-"Não pode agrupar em '%-.64s'",
-"Cláusula contém funções de soma e colunas juntas",
-"Contagem de colunas não confere com a contagem de valores",
-"Nome identificador '%-.100s' é longo demais",
-"Nome da coluna '%-.64s' duplicado",
-"Nome da chave '%-.64s' duplicado",
-"Entrada '%-.64s' duplicada para a chave %d",
-"Especificador de coluna incorreto para a coluna '%-.64s'",
-"%s próximo a '%-.80s' na linha %d",
-"Consulta (query) estava vazia",
-"Tabela/alias '%-.64s' não única",
-"Valor padrão (default) inválido para '%-.64s'",
-"Definida mais de uma chave primária",
-"Especificadas chaves demais. O máximo permitido são %d chaves",
-"Especificadas partes de chave demais. O máximo permitido são %d partes",
-"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",
-"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",
-"%s: 'Shutdown' normal\n",
-"%s: Obteve sinal %d. Abortando!\n",
-"%s: 'Shutdown' completo\n",
-"%s: Forçando finalização da 'thread' %ld - usuário '%-.32s'\n",
-"Não pode criar o soquete IP",
-"Tabela '%-.64s' não possui um índice como o usado em CREATE INDEX. Recrie a tabela",
-"Argumento separador de campos não é o esperado. Cheque o manual",
-"Você não pode usar comprimento de linha fixo com BLOBs. Por favor, use campos com comprimento limitado.",
-"Arquivo '%-.64s' tem que estar no diretório do banco de dados ou ter leitura possível para todos",
-"Arquivo '%-.80s' já existe",
-"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",
-"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",
-"'Id' de 'thread' %lu desconhecido",
-"Você não é proprietário da 'thread' %lu",
-"Nenhuma tabela usada",
-"'Strings' demais para coluna '%-.64s' e SET",
-"Não pode gerar um nome de arquivo de 'log' único '%-.64s'.(1-999)\n",
-"Tabela '%-.64s' foi travada com trava de leitura e não pode ser atualizada",
-"Tabela '%-.64s' não foi travada com LOCK TABLES",
-"Coluna BLOB '%-.64s' não pode ter um valor padrão (default)",
-"Nome de banco de dados '%-.100s' incorreto",
-"Nome de tabela '%-.100s' incorreto",
-"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET SQL_BIG_SELECTS=1, se o SELECT estiver correto",
-"Erro desconhecido",
-"'Procedure' '%-.64s' desconhecida",
-"Número de parâmetros incorreto para a 'procedure' '%-.64s'",
-"Parâmetros incorretos para a 'procedure' '%-.64s'",
-"Tabela '%-.64s' desconhecida em '%-.32s'",
-"Coluna '%-.64s' especificada duas vezes",
-"Uso inválido de função de agrupamento (GROUP)",
-"Tabela '%-.64s' usa uma extensão que não existe nesta versão do MySQL",
-"Uma tabela tem que ter pelo menos uma (1) coluna",
-"Tabela '%-.64s' está cheia",
-"Conjunto de caracteres '%-.64s' desconhecido",
-"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'",
-"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'",
-"Não há caminhos (paths) permitidos para biblioteca compartilhada",
-"Função '%-.64s' já existe",
-"Não pode abrir biblioteca compartilhada '%-.64s' (erro no. '%d' - '%-.64s')",
-"Não pode encontrar a função '%-.64s' na biblioteca",
-"Função '%-.64s' não está definida",
-"'Host' '%-.64s' está bloqueado devido a muitos erros de conexão. Desbloqueie com 'mysqladmin flush-hosts'",
-"'Host' '%-.64s' não tem permissão para se conectar com este servidor MySQL",
-"Você está usando o MySQL como usuário anônimo e usuários anônimos não têm permissão para mudar senhas",
-"Você deve ter privilégios para atualizar tabelas no banco de dados mysql para ser capaz de mudar a senha de outros",
-"Não pode encontrar nenhuma linha que combine na tabela usuário (user table)",
-"Linhas que combinaram: %ld - Alteradas: %ld - Avisos: %ld",
-"Não pode criar uma nova 'thread' (erro no. %d). Se você não estiver sem memória disponível, você pode consultar o manual sobre um possível 'bug' dependente do sistema operacional",
-"Contagem de colunas não confere com a contagem de valores na linha %ld",
-"Não pode reabrir a tabela '%-.64s",
-"Uso inválido do valor NULL",
-"Obteve erro '%-.64s' em regexp",
-"Mistura de colunas agrupadas (com MIN(), MAX(), COUNT(), ...) com colunas não agrupadas é ilegal, se não existir uma cláusula de agrupamento (cláusula GROUP BY)",
-"Não existe tal permissão (grant) definida para o usuário '%-.32s' no 'host' '%-.64s'",
-"Comando '%-.16s' negado para o usuário '%-.32s'@'%-.64s' na tabela '%-.64s'",
-"Comando '%-.16s' negado para o usuário '%-.32s'@'%-.64s' na coluna '%-.64s', na tabela '%-.64s'",
-"Comando GRANT/REVOKE ilegal. Por favor consulte no manual quais privilégios podem ser usados.",
-"Argumento de 'host' ou de usuário para o GRANT é longo demais",
-"Tabela '%-.64s.%-.64s' não existe",
-"Não existe tal permissão (grant) definido para o usuário '%-.32s' no 'host' '%-.64s', na tabela '%-.64s'",
-"Comando usado não é permitido para esta versão do MySQL",
-"Você tem um erro de sintaxe no seu SQL",
-"'Thread' de inserção retardada (atrasada) pois não conseguiu obter a trava solicitada para tabela '%-.64s'",
-"Excesso de 'threads' retardadas (atrasadas) em uso",
-"Conexão %ld abortou para o banco de dados '%-.64s' - usuário '%-.32s' (%-.64s)",
-"Obteve um pacote maior do que a taxa máxima de pacotes definida (max_allowed_packet)",
-"Obteve um erro de leitura no 'pipe' da conexão",
-"Obteve um erro em fcntl()",
-"Obteve pacotes fora de ordem",
-"Não conseguiu descomprimir pacote de comunicação",
-"Obteve um erro na leitura de pacotes de comunicação",
-"Obteve expiração de tempo (timeout) na leitura de pacotes de comunicação",
-"Obteve um erro na escrita de pacotes de comunicação",
-"Obteve expiração de tempo ('timeout') na escrita de pacotes de comunicação",
-"'String' resultante é mais longa do que 'max_allowed_packet'",
-"Tipo de tabela usado não permite colunas BLOB/TEXT",
-"Tipo de tabela usado não permite colunas AUTO_INCREMENT",
-"INSERT DELAYED não pode ser usado com a tabela '%-.64s', porque ela está travada com LOCK TABLES",
-"Nome de coluna '%-.100s' incorreto",
-"O manipulador de tabela usado não pode indexar a coluna '%-.64s'",
-"Todas as tabelas contidas na tabela fundida (MERGE) não estão definidas identicamente",
-"Não pode gravar, devido à restrição UNIQUE, na tabela '%-.64s'",
-"Coluna BLOB '%-.64s' usada na especificação de chave sem o comprimento da chave",
-"Todas as partes de uma chave primária devem ser não-nulas. Se você precisou usar um valor nulo (NULL) em uma chave, use a cláusula UNIQUE em seu lugar",
-"O resultado consistiu em mais do que uma linha",
-"Este tipo de tabela requer uma chave primária",
-"Esta versão do MySQL não foi compilada com suporte a RAID",
-"Você está usando modo de atualização seguro e tentou atualizar uma tabela sem uma cláusula WHERE que use uma coluna chave",
-"Chave '%-.64s' não existe na tabela '%-.64s'",
-"Não pode abrir a tabela",
-"O manipulador de tabela não suporta %s",
-"Não lhe é permitido executar este comando em uma transação",
-"Obteve erro %d durante COMMIT",
-"Obteve erro %d durante ROLLBACK",
-"Obteve erro %d durante FLUSH_LOGS",
-"Obteve erro %d durante CHECKPOINT",
-"Conexão %ld abortada para banco de dados '%-.64s' - usuário '%-.32s' - 'host' `%-.64s' ('%-.64s')",
-"O manipulador de tabela não suporta 'dump' binário de tabela",
-"Binlog fechado. Não pode fazer RESET MASTER",
-"Falhou na reconstrução do índice da tabela 'dumped' '%-.64s'",
-"Erro no 'master' '%-.64s'",
-"Erro de rede lendo do 'master'",
-"Erro de rede gravando no 'master'",
-"Não pode encontrar um índice para o texto todo que combine com a lista de colunas",
-"Não pode executar o comando dado porque você tem tabelas ativas travadas ou uma transação ativa",
-"Variável de sistema '%-.64s' desconhecida",
-"Tabela '%-.64s' está marcada como danificada e deve ser reparada",
-"Tabela '%-.64s' está marcada como danificada e a última reparação (automática?) falhou",
-"Aviso: Algumas tabelas não-transacionais alteradas não puderam ser reconstituídas (rolled back)",
-"Transações multi-declaradas (multi-statement transactions) requeriram mais do que o valor limite (max_binlog_cache_size) de bytes para armazenagem. Aumente o valor desta variável do mysqld e tente novamente",
-"Esta operação não pode ser realizada com um 'slave' em execução. Execute STOP SLAVE primeiro",
-"Esta operação requer um 'slave' em execução. Configure o 'slave' e execute START SLAVE",
-"O servidor não está configurado como 'slave'. Acerte o arquivo de configuração ou use CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"Não conseguiu criar 'thread' de 'slave'. Verifique os recursos do sistema",
-"Usuário '%-.64s' já possui mais que o valor máximo de conexões (max_user_connections) ativas",
-"Você pode usar apenas expressões constantes com SET",
-"Tempo de espera (timeout) de travamento excedido. Tente reiniciar a transação.",
-"O número total de travamentos excede o tamanho da tabela de travamentos",
-"Travamentos de atualização não podem ser obtidos durante uma transação de tipo READ UNCOMMITTED",
-"DROP DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura",
-"CREATE DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura",
-"Argumentos errados para %s",
-"Não é permitido a '%-.32s'@'%-.64s' criar novos usuários",
-"Definição incorreta da tabela. Todas as tabelas contidas na junção devem estar no mesmo banco de dados.",
-"Encontrado um travamento fatal (deadlock) quando tentava obter uma trava. Tente reiniciar a transação.",
-"O tipo de tabela utilizado não suporta índices de texto completo (fulltext indexes)",
-"Não pode acrescentar uma restrição de chave estrangeira",
-"Não pode acrescentar uma linha filha: uma restrição de chave estrangeira falhou",
-"Não pode apagar uma linha pai: uma restrição de chave estrangeira falhou",
-"Erro conectando com o master: %-.128s",
-"Erro rodando consulta no master: %-.128s",
-"Erro quando executando comando %s: %-.128s",
-"Uso errado de %s e %s",
-"Os comandos SELECT usados têm diferente número de colunas",
-"Não posso executar a consulta porque você tem um conflito de travamento de leitura",
-"Mistura de tabelas transacional e não-transacional está desabilitada",
-"Opção '%s' usada duas vezes no comando",
-"Usuário '%-.64s' tem excedido o '%s' recurso (atual valor: %ld)",
-"Acesso negado. Você precisa o privilégio %-.128s para essa operação",
-"Variável '%-.64s' é uma SESSION variável e não pode ser usada com SET GLOBAL",
-"Variável '%-.64s' é uma GLOBAL variável e deve ser configurada com SET GLOBAL",
-"Variável '%-.64s' não tem um valor padrão",
-"Variável '%-.64s' não pode ser configurada para o valor de '%-.64s'",
-"Tipo errado de argumento para variável '%-.64s'",
-"Variável '%-.64s' somente pode ser configurada, não lida",
-"Errado uso/colocação de '%s'",
-"Esta versão de MySQL não suporta ainda '%s'",
-"Obteve fatal erro %d: '%-.128s' do master quando lendo dados do binary log",
-"Slave SQL thread ignorado a consulta devido às normas de replicação-*-tabela",
-"Variable '%-.64s' is a %s variable",
-"Definição errada da chave estrangeira para '%-.64s': %s",
-"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 (%.*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 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)",
-"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",
-"Dado truncado, fora de alcance para coluna '%s' na linha %ld",
-"Dado truncado para coluna '%s' na linha %ld",
-"Usando engine de armazenamento %s para tabela '%s'",
-"Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'",
-"Não pode remover um ou mais dos usuários pedidos",
-"Não pode revocar todos os privilégios, grant para um ou mais dos usuários pedidos",
-"Ilegal combinação de collations (%s,%s), (%s,%s), (%s,%s) para operação '%s'",
-"Ilegal combinação de collations para operação '%s'",
-"Variável '%-.64s' não é uma variável componente (Não pode ser usada como XXXX.variável_nome)",
-"Collation desconhecida: '%-.64s'",
-"SSL parâmetros em CHANGE MASTER são ignorados porque este escravo MySQL foi compilado sem o SSL suporte. Os mesmos podem ser usados mais tarde quando o escravo MySQL com SSL seja iniciado.",
-"Servidor está rodando em --secure-auth modo, porêm '%s'@'%s' tem senha no formato antigo; por favor troque a senha para o novo formato",
-"Campo ou referência '%-.64s%s%-.64s%s%-.64s' de SELECT #%d foi resolvido em SELECT #%d",
-"Parâmetro ou combinação de parâmetros errado para START SLAVE UNTIL",
-"É recomendado para rodar com --skip-slave-start quando fazendo replicação passo-por-passo com START SLAVE UNTIL, de outra forma você não está seguro em caso de inesperada reinicialição do mysqld escravo",
-"Thread SQL não pode ser inicializado tal que opções UNTIL são ignoradas",
-"Incorreto nome de índice '%-.100s'",
-"Incorreto nome de catálogo '%-.100s'",
-"Falha em Query cache para configurar tamanho %lu, novo tamanho de query cache é %lu",
-"Coluna '%-.64s' não pode ser parte de índice FULLTEXT",
-"Key cache desconhecida '%-.100s'",
-"MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar",
-"Motor de tabela desconhecido '%s'",
-"'%s' é desatualizado. Use '%s' em seu lugar",
-"A tabela destino %-.100s do %s não é atualizável",
-"O recurso '%s' foi desativado; você necessita MySQL construído com '%s' para ter isto funcionando",
-"O servidor MySQL está rodando com a opção %s razão pela qual não pode executar esse commando",
-"Coluna '%-.100s' tem valor duplicado '%-.64s' em %s"
-"Truncado errado %-.32s valor: '%-.128s'"
-"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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
deleted file mode 100644
index 0fcc2804326..00000000000
--- a/sql/share/romanian/errmsg.txt
+++ /dev/null
@@ -1,327 +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 */
-
-/*
- Translated into Romanian by Stefan Saroiu
- e-mail: tzoompy@cs.washington.edu
-*/
-
-character-set=latin2
-
-"hashchk",
-"isamchk",
-"NU",
-"DA",
-"Nu pot sa creez fisierul '%-.64s' (Eroare: %d)",
-"Nu pot sa creez tabla '%-.64s' (Eroare: %d)",
-"Nu pot sa creez baza de date '%-.64s' (Eroare: %d)",
-"Nu pot sa creez baza de date '%-.64s'; baza de date exista deja",
-"Nu pot sa drop baza de date '%-.64s'; baza da date este inexistenta",
-"Eroare dropuind baza de date (nu pot sa sterg '%-.64s', Eroare: %d)",
-"Eroare dropuind baza de date (nu pot sa rmdir '%-.64s', Eroare: %d)",
-"Eroare incercind sa delete '%-.64s' (Eroare: %d)",
-"Nu pot sa citesc cimpurile in tabla de system (system table)",
-"Nu pot sa obtin statusul lui '%-.64s' (Eroare: %d)",
-"Nu pot sa obtin directorul current (working directory) (Eroare: %d)",
-"Nu pot sa lock fisierul (Eroare: %d)",
-"Nu pot sa deschid fisierul: '%-.64s' (Eroare: %d)",
-"Nu pot sa gasesc fisierul: '%-.64s' (Eroare: %d)",
-"Nu pot sa citesc directorul '%-.64s' (Eroare: %d)",
-"Nu pot sa schimb directorul '%-.64s' (Eroare: %d)",
-"Cimpul a fost schimbat de la ultima citire a tabelei '%-.64s'",
-"Hard-disk-ul este plin (%s). Astept sa se elibereze ceva spatiu...",
-"Nu pot sa scriu (can't write), cheie duplicata in tabela '%-.64s'",
-"Eroare inchizind '%-.64s' (errno: %d)",
-"Eroare citind fisierul '%-.64s' (errno: %d)",
-"Eroare incercind sa renumesc '%-.64s' in '%-.64s' (errno: %d)",
-"Eroare scriind fisierul '%-.64s' (errno: %d)",
-"'%-.64s' este blocat pentry schimbari (loccked against change)",
-"Sortare intrerupta",
-"View '%-.64s' nu exista pentru '%-.64s'",
-"Eroarea %d obtinuta din handlerul tabelei",
-"Handlerul tabelei pentru '%-.64s' nu are aceasta optiune",
-"Nu pot sa gasesc recordul in '%-.64s'",
-"Informatie incorecta in fisierul: '%-.64s'",
-"Cheia fisierului incorecta pentru tabela: '%-.64s'; incearca s-o repari",
-"Cheia fisierului e veche pentru tabela '%-.64s'; repar-o!",
-"Tabela '%-.64s' e read-only",
-"Out of memory. Porneste daemon-ul din nou si incearca inca o data (e nevoie de %d bytes)",
-"Out of memory pentru sortare. Largeste marimea buffer-ului pentru sortare in daemon (sort buffer size)",
-"Sfirsit de fisier neasteptat in citirea fisierului '%-.64s' (errno: %d)",
-"Prea multe conectiuni",
-"Out of memory; Verifica daca mysqld sau vreun alt proces foloseste toate memoria disponbila. Altfel, trebuie sa folosesi 'ulimit' ca sa permiti lui memoria disponbila. Altfel, trebuie sa folosesi 'ulimit' ca sa permiti lui mysqld sa foloseasca mai multa memorie ori adauga mai mult spatiu pentru swap (swap space)",
-"Nu pot sa obtin hostname-ul adresei tale",
-"Prost inceput de conectie (bad handshake)",
-"Acces interzis pentru utilizatorul: '%-.32s'@'%-.64s' la baza de date '%-.64s'",
-"Acces interzis pentru utilizatorul: '%-.32s'@'%-.64s' (Folosind parola: %s)",
-"Nici o baza de data nu a fost selectata inca",
-"Comanda invalida",
-"Coloana '%-.64s' nu poate sa fie null",
-"Baza de data invalida '%-.64s'",
-"Tabela '%-.64s' exista deja",
-"Tabela '%-.64s' este invalida",
-"Coloana: '%-.64s' in %-.64s este ambigua",
-"Terminarea serverului este in desfasurare",
-"Coloana invalida '%-.64s' in '%-.64s'",
-"'%-.64s' nu exista in clauza GROUP BY",
-"Nu pot sa grupez pe (group on) '%-.64s'",
-"Comanda are functii suma si coloane in aceeasi comanda",
-"Numarul de coloane nu este acelasi cu numarul valoarei",
-"Numele indentificatorului '%-.100s' este prea lung",
-"Numele coloanei '%-.64s' e duplicat",
-"Numele cheiei '%-.64s' e duplicat",
-"Cimpul '%-.64s' e duplicat pentru cheia %d",
-"Specificandul coloanei '%-.64s' este incorect",
-"%s linga '%-.80s' pe linia %d",
-"Query-ul a fost gol",
-"Tabela/alias: '%-.64s' nu este unic",
-"Valoarea de default este invalida pentru '%-.64s'",
-"Chei primare definite de mai multe ori",
-"Prea multe chei. Numarul de chei maxim este %d",
-"Prea multe chei. Numarul de chei maxim este %d",
-"Cheia specificata este prea lunga. Marimea maxima a unei chei este de %d",
-"Coloana cheie '%-.64s' nu exista in tabela",
-"Coloana de tip BLOB '%-.64s' nu poate fi folosita in specificarea cheii cu tipul de tabla folosit",
-"Lungimea coloanei '%-.64s' este prea lunga (maximum = %d). Foloseste BLOB mai bine",
-"Definitia tabelei este incorecta; Nu pot fi mai mult de o singura coloana de tip auto si aceasta trebuie definita ca cheie",
-"%s: sint gata pentru conectii",
-"%s: Terminare normala\n",
-"%s: Semnal %d obtinut. Aborting!\n",
-"%s: Terminare completa\n",
-"%s: Terminare fortata a thread-ului %ld utilizatorului: '%-.32s'\n",
-"Nu pot crea IP socket",
-"Tabela '%-.64s' nu are un index ca acela folosit in CREATE INDEX. Re-creeaza tabela",
-"Argumentul pentru separatorul de cimpuri este diferit de ce ma asteptam. Verifica manualul",
-"Nu poti folosi lungime de cimp fix pentru BLOB-uri. Foloseste 'fields terminated by'.",
-"Fisierul '%-.64s' trebuie sa fie in directorul bazei de data sau trebuie sa poata sa fie citit de catre toata lumea (verifica permisiile)",
-"Fisierul '%-.80s' exista deja",
-"Recorduri: %ld Sterse: %ld Sarite (skipped): %ld Atentionari (warnings): %ld",
-"Recorduri: %ld Duplicate: %ld",
-"Componentul cheii este incorrect. Componentul folosit al cheii nu este un sir sau lungimea folosita este mai lunga decit lungimea cheii",
-"Nu poti sterge toate coloanele cu ALTER TABLE. Foloseste DROP TABLE in schimb",
-"Nu pot sa DROP '%-.64s'. Verifica daca coloana/cheia exista",
-"Recorduri: %ld Duplicate: %ld Atentionari (warnings): %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Id-ul: %lu thread-ului este necunoscut",
-"Nu sinteti proprietarul threadului %lu",
-"Nici o tabela folosita",
-"Prea multe siruri pentru coloana %-.64s si SET",
-"Nu pot sa generez un nume de log unic %-.64s.(1-999)\n",
-"Tabela '%-.64s' a fost locked cu un READ lock si nu poate fi actualizata",
-"Tabela '%-.64s' nu a fost locked cu LOCK TABLES",
-"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 okay",
-"Eroare unknown",
-"Procedura unknown '%-.64s'",
-"Procedura '%-.64s' are un numar incorect de parametri",
-"Procedura '%-.64s' are parametrii incorecti",
-"Tabla '%-.64s' invalida in %-.32s",
-"Coloana '%-.64s' specificata de doua ori",
-"Folosire incorecta a functiei group",
-"Tabela '%-.64s' foloseste o extensire inexistenta in versiunea curenta de MySQL",
-"O tabela trebuie sa aiba cel putin o coloana",
-"Tabela '%-.64s' e plina",
-"Set de caractere invalid: '%-.64s'",
-"Prea multe tabele. MySQL nu poate folosi mai mult de %d tabele intr-un join",
-"Prea multe coloane",
-"Marimea liniei (row) prea mare. Marimea maxima a liniei, excluzind BLOB-urile este de %d. Trebuie sa schimbati unele cimpuri in BLOB-uri",
-"Stack-ul thread-ului a fost depasit (prea mic): Folositi: %ld intr-un stack de %ld. Folositi 'mysqld -O thread_stack=#' ca sa specifici un stack mai mare",
-"Dependinta incrucisata (cross dependency) gasita in OUTER JOIN. Examinati conditiile ON",
-"Coloana '%-.64s' e folosita cu UNIQUE sau INDEX dar fara sa fie definita ca NOT NULL",
-"Nu pot incarca functia '%-.64s'",
-"Nu pot initializa functia '%-.64s'; %-.80s",
-"Nici un paths nu e permis pentru o librarie shared",
-"Functia '%-.64s' exista deja",
-"Nu pot deschide libraria shared '%-.64s' (Eroare: %d %-.64s)",
-"Nu pot gasi functia '%-.64s' in libraria",
-"Functia '%-.64s' nu e definita",
-"Host-ul '%-.64s' e blocat din cauza multelor erori de conectie. Poti deploca folosind 'mysqladmin flush-hosts'",
-"Host-ul '%-.64s' nu este permis a se conecta la aceste server MySQL",
-"Dumneavoastra folositi MySQL ca un utilizator anonim si utilizatorii anonimi nu au voie sa schime parolele",
-"Trebuie sa aveti privilegii sa actualizati tabelele in bazele de date mysql ca sa puteti sa schimati parolele altora",
-"Nu pot gasi nici o linie corespunzatoare in tabela utilizatorului",
-"Linii identificate (matched): %ld Schimbate: %ld Atentionari (warnings): %ld",
-"Nu pot crea un thread nou (Eroare %d). Daca mai aveti memorie disponibila in sistem, puteti consulta manualul - ar putea exista un potential bug in legatura cu sistemul de operare",
-"Numarul de coloane nu corespunde cu numarul de valori la linia %ld",
-"Nu pot redeschide tabela: '%-.64s'",
-"Folosirea unei value NULL e invalida",
-"Eroarea '%-.64s' obtinuta din expresia regulara (regexp)",
-"Amestecarea de coloane GROUP (MIN(),MAX(),COUNT()...) fara coloane GROUP este ilegala daca nu exista o clauza GROUP BY",
-"Nu exista un astfel de grant definit pentru utilzatorul '%-.32s' de pe host-ul '%-.64s'",
-"Comanda %-.16s interzisa utilizatorului: '%-.32s'@'%-.64s' pentru tabela '%-.64s'",
-"Comanda %-.16s interzisa utilizatorului: '%-.32s'@'%-.64s' pentru coloana '%-.64s' in tabela '%-.64s'",
-"Comanda GRANT/REVOKE ilegala. Consultati manualul in privinta privilegiilor ce pot fi folosite.",
-"Argumentul host-ului sau utilizatorului pentru GRANT e prea lung",
-"Tabela '%-.64s.%-.64s' nu exista",
-"Nu exista un astfel de privilegiu (grant) definit pentru utilizatorul '%-.32s' de pe host-ul '%-.64s' pentru tabela '%-.64s'",
-"Comanda folosita nu este permisa pentru aceasta versiune de MySQL",
-"Aveti o eroare in sintaxa RSQL",
-"Thread-ul pentru inserarea aminata nu a putut obtine lacatul (lock) pentru tabela %-.64s",
-"Prea multe threaduri aminate care sint in uz",
-"Conectie terminata %ld la baza de date: '%-.64s' utilizator: '%-.32s' (%-.64s)",
-"Un packet mai mare decit 'max_allowed_packet' a fost primit",
-"Eroare la citire din cauza lui 'connection pipe'",
-"Eroare obtinuta de la fcntl()",
-"Packets care nu sint ordonati au fost gasiti",
-"Nu s-a putut decompresa pachetul de comunicatie (communication packet)",
-"Eroare obtinuta citind pachetele de comunicatie (communication packets)",
-"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'",
-"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",
-"Nume increct de coloana '%-.100s'",
-"Handler-ul tabelei folosite nu poate indexa coloana '%-.64s'",
-"Toate tabelele din tabela MERGE nu sint definite identic",
-"Nu pot scrie pe hard-drive, din cauza constraintului unic (unique constraint) pentru tabela '%-.64s'",
-"Coloana BLOB '%-.64s' este folosita in specificarea unei chei fara ca o lungime de cheie sa fie folosita",
-"Toate partile unei chei primare (PRIMARY KEY) trebuie sa fie NOT NULL; Daca aveti nevoie de NULL in vreo cheie, folositi UNIQUE in schimb",
-"Resultatul constista din mai multe linii",
-"Aceast tip de tabela are nevoie de o cheie primara",
-"Aceasta versiune de MySQL, nu a fost compilata cu suport pentru RAID",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
deleted file mode 100644
index 1913fd3f1c1..00000000000
--- a/sql/share/russian/errmsg.txt
+++ /dev/null
@@ -1,327 +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 */
-
-/*
- Translation done in 2003 by Egor Egorov; Ensita.NET, http://www.ensita.net/
-*/
-/* charset: KOI8-R */
-
-character-set=koi8r
-
-"hashchk",
-"isamchk",
-"îåô",
-"äá",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÆÁÊÌ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÔÁÂÌÉÃÕ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s'. âÁÚÁ ÄÁÎÎÙÈ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ",
-"îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.64s'. ôÁËÏÊ ÂÁÚÙ ÄÁÎÎÙÈ ÎÅÔ",
-"ïÛÉÂËÁ ÐÒÉ ÕÄÁÌÅÎÉÉ ÂÁÚÙ ÄÁÎÎÙÈ (ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ '%-.64s', ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ (ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ËÁÔÁÌÏÇ '%-.64s', ÏÛÉÂËÁ: %d)",
-"ïÛÉÂËÁ ÐÒÉ ÕÄÁÌÅÎÉÉ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÚÁÐÉÓØ × ÓÉÓÔÅÍÎÏÊ ÔÁÂÌÉÃÅ",
-"îÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÓÔÁÔÕÓÎÕÀ ÉÎÆÏÒÍÁÃÉÀ Ï '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÏÐÒÅÄÅÌÉÔØ ÒÁÂÏÞÉÊ ËÁÔÁÌÏÇ (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÐÏÓÔÁ×ÉÔØ ÂÌÏËÉÒÏ×ËÕ ÎÁ ÆÁÊÌÅ (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ: '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÆÁÊÌ: '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ËÁÔÁÌÏÇ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÊÔÉ × ËÁÔÁÌÏÇ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"úÁÐÉÓØ ÉÚÍÅÎÉÌÁÓØ Ó ÍÏÍÅÎÔÁ ÐÏÓÌÅÄÎÅÊ ×ÙÂÏÒËÉ × ÔÁÂÌÉÃÅ '%-.64s'",
-"äÉÓË ÚÁÐÏÌÎÅÎ. (%s). ïÖÉÄÁÅÍ, ÐÏËÁ ËÔÏ-ÔÏ ÎÅ ÕÂÅÒÅÔ ÐÏÓÌÅ ÓÅÂÑ ÍÕÓÏÒ...",
-"îÅ×ÏÚÍÏÖÎÏ ÐÒÏÉÚ×ÅÓÔÉ ÚÁÐÉÓØ, ÄÕÂÌÉÒÕÀÝÉÊÓÑ ËÌÀÞ × ÔÁÂÌÉÃÅ '%-.64s'",
-"ïÛÉÂËÁ ÐÒÉ ÚÁËÒÙÔÉÉ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"ïÛÉÂËÁ ÞÔÅÎÉÑ ÆÁÊÌÁ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"ïÛÉÂËÁ ÐÒÉ ÐÅÒÅÉÍÅÎÏ×ÁÎÉÉ '%-.64s' × '%-.64s' (ÏÛÉÂËÁ: %d)",
-"ïÛÉÂËÁ ÚÁÐÉÓÉ × ÆÁÊÌ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"'%-.64s' ÚÁÂÌÏËÉÒÏ×ÁÎ ÄÌÑ ÉÚÍÅÎÅÎÉÊ",
-"óÏÒÔÉÒÏ×ËÁ ÐÒÅÒ×ÁÎÁ",
-"ðÒÅÄÓÔÁ×ÌÅÎÉÅ '%-.64s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ ÄÌÑ '%-.64s'",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d ÏÔ ÏÂÒÁÂÏÔÞÉËÁ ÔÁÂÌÉÃ",
-"ïÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ '%-.64s' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÜÔÕ ×ÏÚÍÏÖÎÏÓÔØ",
-"îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÚÁÐÉÓØ × '%-.64s'",
-"îÅËÏÒÒÅËÔÎÁÑ ÉÎÆÏÒÍÁÃÉÑ × ÆÁÊÌÅ '%-.64s'",
-"îÅËÏÒÒÅËÔÎÙÊ ÉÎÄÅËÓÎÙÊ ÆÁÊÌ ÄÌÑ ÔÁÂÌÉÃÙ: '%-.64s'. ðÏÐÒÏÂÕÊÔÅ ×ÏÓÓÔÁÎÏ×ÉÔØ ÅÇÏ",
-"óÔÁÒÙÊ ÉÎÄÅËÓÎÙÊ ÆÁÊÌ ÄÌÑ ÔÁÂÌÉÃÙ '%-.64s'; ÏÔÒÅÍÏÎÔÉÒÕÊÔÅ ÅÇÏ!",
-"ôÁÂÌÉÃÁ '%-.64s' ÐÒÅÄÎÁÚÎÁÞÅÎÁ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ",
-"îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ. ðÅÒÅÚÁÐÕÓÔÉÔÅ ÓÅÒ×ÅÒ É ÐÏÐÒÏÂÕÊÔÅ ÅÝÅ ÒÁÚ (ÎÕÖÎÏ %d ÂÁÊÔ)",
-"îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ ÄÌÑ ÓÏÒÔÉÒÏ×ËÉ. õ×ÅÌÉÞØÔÅ ÒÁÚÍÅÒ ÂÕÆÅÒÁ ÓÏÒÔÉÒÏ×ËÉ ÎÁ ÓÅÒ×ÅÒÅ",
-"îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ '%-.64s' (ÏÛÉÂËÁ: %d)",
-"óÌÉÛËÏÍ ÍÎÏÇÏ ÓÏÅÄÉÎÅÎÉÊ",
-"îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ; ÕÄÏÓÔÏ×ÅÒØÔÅÓØ, ÞÔÏ mysqld ÉÌÉ ËÁËÏÊ-ÌÉÂÏ ÄÒÕÇÏÊ ÐÒÏÃÅÓÓ ÎÅ ÚÁÎÉÍÁÅÔ ×ÓÀ ÄÏÓÔÕÐÎÕÀ ÐÁÍÑÔØ. åÓÌÉ ÎÅÔ, ÔÏ ×Ù ÍÏÖÅÔÅ ÉÓÐÏÌØÚÏ×ÁÔØ ulimit, ÞÔÏÂÙ ×ÙÄÅÌÉÔØ ÄÌÑ mysqld ÂÏÌØÛÅ ÐÁÍÑÔÉ, ÉÌÉ Õ×ÅÌÉÞÉÔØ ÏÂßÅÍ ÆÁÊÌÁ ÐÏÄËÁÞËÉ",
-"îÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÉÍÑ ÈÏÓÔÁ ÄÌÑ ×ÁÛÅÇÏ ÁÄÒÅÓÁ",
-"îÅËÏÒÒÅËÔÎÏÅ ÐÒÉ×ÅÔÓÔ×ÉÅ",
-"äÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s'@'%-.64s' ÄÏÓÔÕÐ Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.64s' ÚÁËÒÙÔ",
-"äÏÓÔÕÐ ÚÁËÒÙÔ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s'@'%-.64s' (ÂÙÌ ÉÓÐÏÌØÚÏ×ÁÎ ÐÁÒÏÌØ: %s)",
-"âÁÚÁ ÄÁÎÎÙÈ ÎÅ ×ÙÂÒÁÎÁ",
-"îÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ ËÏÍÍÕÎÉËÁÃÉÏÎÎÏÇÏ ÐÒÏÔÏËÏÌÁ",
-"óÔÏÌÂÅà '%-.64s' ÎÅ ÍÏÖÅÔ ÐÒÉÎÉÍÁÔØ ×ÅÌÉÞÉÎÕ NULL",
-"îÅÉÚ×ÅÓÔÎÁÑ ÂÁÚÁ ÄÁÎÎÙÈ '%-.64s'",
-"ôÁÂÌÉÃÁ '%-.64s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ",
-"îÅÉÚ×ÅÓÔÎÁÑ ÔÁÂÌÉÃÁ '%-.175s'",
-"óÔÏÌÂÅÃ '%-.64s' × %-.64s ÚÁÄÁÎ ÎÅÏÄÎÏÚÎÁÞÎÏ",
-"óÅÒ×ÅÒ ÎÁÈÏÄÉÔÓÑ × ÐÒÏÃÅÓÓÅ ÏÓÔÁÎÏ×ËÉ",
-"îÅÉÚ×ÅÓÔÎÙÊ ÓÔÏÌÂÅà '%-.64s' × '%-.64s'",
-"'%-.64s' ÎÅ ÐÒÉÓÕÔÓÔ×ÕÅÔ × GROUP BY",
-"îÅ×ÏÚÍÏÖÎÏ ÐÒÏÉÚ×ÅÓÔÉ ÇÒÕÐÐÉÒÏ×ËÕ ÐÏ '%-.64s'",
-"÷ÙÒÁÖÅÎÉÅ ÓÏÄÅÒÖÉÔ ÇÒÕÐÐÏ×ÙÅ ÆÕÎËÃÉÉ É ÓÔÏÌÂÃÙ, ÎÏ ÎÅ ×ËÌÀÞÁÅÔ GROUP BY. á ËÁË ×Ù ÕÍÕÄÒÉÌÉÓØ ÐÏÌÕÞÉÔØ ÜÔÏ ÓÏÏÂÝÅÎÉÅ Ï ÏÛÉÂËÅ?",
-"ëÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ× ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ËÏÌÉÞÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ",
-"óÌÉÛËÏÍ ÄÌÉÎÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ '%-.100s'",
-"äÕÂÌÉÒÕÀÝÅÅÓÑ ÉÍÑ ÓÔÏÌÂÃÁ '%-.64s'",
-"äÕÂÌÉÒÕÀÝÅÅÓÑ ÉÍÑ ËÌÀÞÁ '%-.64s'",
-"äÕÂÌÉÒÕÀÝÁÑÓÑ ÚÁÐÉÓØ '%-.64s' ÐÏ ËÌÀÞÕ %d",
-"îÅËÏÒÒÅËÔÎÙÊ ÏÐÒÅÄÅÌÉÔÅÌØ ÓÔÏÌÂÃÁ ÄÌÑ ÓÔÏÌÂÃÁ '%-.64s'",
-"%s ÏËÏÌÏ '%-.80s' ÎÁ ÓÔÒÏËÅ %d",
-"úÁÐÒÏÓ ÏËÁÚÁÌÓÑ ÐÕÓÔÙÍ",
-"ðÏ×ÔÏÒÑÀÝÁÑÓÑ ÔÁÂÌÉÃÁ/ÐÓÅ×ÄÏÎÉÍ '%-.64s'",
-"îÅËÏÒÒÅËÔÎÏÅ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ '%-.64s'",
-"õËÁÚÁÎÏ ÎÅÓËÏÌØËÏ ÐÅÒ×ÉÞÎÙÈ ËÌÀÞÅÊ",
-"õËÁÚÁÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ ËÌÀÞÅÊ. òÁÚÒÅÛÁÅÔÓÑ ÕËÁÚÙ×ÁÔØ ÎÅ ÂÏÌÅÅ %d ËÌÀÞÅÊ",
-"õËÁÚÁÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÞÁÓÔÅÊ ÓÏÓÔÁ×ÎÏÇÏ ËÌÀÞÁ. òÁÚÒÅÛÁÅÔÓÑ ÕËÁÚÙ×ÁÔØ ÎÅ ÂÏÌÅÅ %d ÞÁÓÔÅÊ",
-"õËÁÚÁÎ ÓÌÉÛËÏÍ ÄÌÉÎÎÙÊ ËÌÀÞ. íÁËÓÉÍÁÌØÎÁÑ ÄÌÉÎÁ ËÌÀÞÁ ÓÏÓÔÁ×ÌÑÅÔ %d ÂÁÊÔ",
-"ëÌÀÞÅ×ÏÊ ÓÔÏÌÂÅà '%-.64s' × ÔÁÂÌÉÃÅ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ",
-"óÔÏÌÂÅà ÔÉÐÁ BLOB '%-.64s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎ ËÁË ÚÎÁÞÅÎÉÅ ËÌÀÞÁ × ÔÁÂÌÉÃÅ ÔÁËÏÇÏ ÔÉÐÁ",
-"óÌÉÛËÏÍ ÂÏÌØÛÁÑ ÄÌÉÎÁ ÓÔÏÌÂÃÁ '%-.64s' (ÍÁËÓÉÍÕÍ = %d). éÓÐÏÌØÚÕÊÔÅ ÔÉÐ BLOB ×ÍÅÓÔÏ ÔÅËÕÝÅÇÏ",
-"îÅËÏÒÒÅËÔÎÏÅ ÏÐÒÅÄÅÌÅÎÉÅ ÔÁÂÌÉÃÙ: ÍÏÖÅÔ ÓÕÝÅÓÔ×Ï×ÁÔØ ÔÏÌØËÏ ÏÄÉÎ Á×ÔÏÉÎËÒÅÍÅÎÔÎÙÊ ÓÔÏÌÂÅÃ, É ÏÎ ÄÏÌÖÅÎ ÂÙÔØ ÏÐÒÅÄÅÌÅÎ ËÁË ËÌÀÞ",
-"%s: çÏÔÏ× ÐÒÉÎÉÍÁÔØ ÓÏÅÄÉÎÅÎÉÑ.\n÷ÅÒÓÉÑ: '%s' ÓÏËÅÔ: '%s' ÐÏÒÔ: %d",
-"%s: ëÏÒÒÅËÔÎÁÑ ÏÓÔÁÎÏ×ËÁ\n",
-"%s: ðÏÌÕÞÅÎ ÓÉÇÎÁÌ %d. ðÒÅËÒÁÝÁÅÍ!\n",
-"%s: ïÓÔÁÎÏ×ËÁ ÚÁ×ÅÒÛÅÎÁ\n",
-"%s: ðÒÉÎÕÄÉÔÅÌØÎÏ ÚÁËÒÙ×ÁÅÍ ÐÏÔÏË %ld ÐÏÌØÚÏ×ÁÔÅÌÑ: '%-.32s'\n",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ IP-ÓÏËÅÔ",
-"÷ ÔÁÂÌÉÃÅ '%-.64s' ÎÅÔ ÔÁËÏÇÏ ÉÎÄÅËÓÁ, ËÁË × CREATE INDEX. óÏÚÄÁÊÔÅ ÔÁÂÌÉÃÕ ÚÁÎÏ×Ï",
-"áÒÇÕÍÅÎÔ ÒÁÚÄÅÌÉÔÅÌÑ ÐÏÌÅÊ - ÎÅ ÔÏÔ, ËÏÔÏÒÙÊ ÏÖÉÄÁÌÓÑ. ïÂÒÁÝÁÊÔÅÓØ Ë ÄÏËÕÍÅÎÔÁÃÉÉ",
-"æÉËÓÉÒÏ×ÁÎÎÙÊ ÒÁÚÍÅÒ ÚÁÐÉÓÉ Ó ÐÏÌÑÍÉ ÔÉÐÁ BLOB ÉÓÐÏÌØÚÏ×ÁÔØ ÎÅÌØÚÑ, ÐÒÉÍÅÎÑÊÔÅ 'fields terminated by'",
-"æÁÊÌ '%-.64s' ÄÏÌÖÅÎ ÎÁÈÏÄÉÔØÓÑ × ÔÏÍ ÖÅ ËÁÔÁÌÏÇÅ, ÞÔÏ É ÂÁÚÁ ÄÁÎÎÙÈ, ÉÌÉ ÂÙÔØ ÏÂÝÅÄÏÓÔÕÐÎÙÍ ÄÌÑ ÞÔÅÎÉÑ",
-"æÁÊÌ '%-.80s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ",
-"úÁÐÉÓÅÊ: %ld õÄÁÌÅÎÏ: %ld ðÒÏÐÕÝÅÎÏ: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld",
-"úÁÐÉÓÅÊ: %ld äÕÂÌÉËÁÔÏ×: %ld",
-"îÅËÏÒÒÅËÔÎÁÑ ÞÁÓÔØ ËÌÀÞÁ. éÓÐÏÌØÚÕÅÍÁÑ ÞÁÓÔØ ËÌÀÞÁ ÎÅ Ñ×ÌÑÅÔÓÑ ÓÔÒÏËÏÊ, ÕËÁÚÁÎÎÁÑ ÄÌÉÎÁ ÂÏÌØÛÅ, ÞÅÍ ÄÌÉÎÁ ÞÁÓÔÉ ËÌÀÞÁ, ÉÌÉ ÏÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÕÎÉËÁÌØÎÙÅ ÞÁÓÔÉ ËÌÀÞÁ",
-"îÅÌØÚÑ ÕÄÁÌÉÔØ ×ÓÅ ÓÔÏÌÂÃÙ Ó ÐÏÍÏÝØÀ ALTER TABLE. éÓÐÏÌØÚÕÊÔÅ DROP TABLE",
-"îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ (DROP) '%-.64s'. õÂÅÄÉÔÅÓØ ÞÔÏ ÓÔÏÌÂÅÃ/ËÌÀÞ ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÓÕÝÅÓÔ×ÕÅÔ",
-"úÁÐÉÓÅÊ: %ld äÕÂÌÉËÁÔÏ×: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld",
-"îÅ ÄÏÐÕÓËÁÅÔÓÑ ÕËÁÚÁÎÉÅ ÔÁÂÌÉÃÙ '%-.64s' × ÓÐÉÓËÅ ÔÁÂÌÉà FROM ÄÌÑ ×ÎÅÓÅÎÉÑ × ÎÅÅ ÉÚÍÅÎÅÎÉÊ",
-"îÅÉÚ×ÅÓÔÎÙÊ ÎÏÍÅÒ ÐÏÔÏËÁ: %lu",
-"÷Ù ÎÅ Ñ×ÌÑÅÔÅÓØ ×ÌÁÄÅÌØÃÅÍ ÐÏÔÏËÁ %lu",
-"îÉËÁËÉÅ ÔÁÂÌÉÃÙ ÎÅ ÉÓÐÏÌØÚÏ×ÁÎÙ",
-"óÌÉÛËÏÍ ÍÎÏÇÏ ÚÎÁÞÅÎÉÊ ÄÌÑ ÓÔÏÌÂÃÁ %-.64s × SET",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÕÎÉËÁÌØÎÏÅ ÉÍÑ ÆÁÊÌÁ ÖÕÒÎÁÌÁ %-.64s.(1-999)\n",
-"ôÁÂÌÉÃÁ '%-.64s' ÚÁÂÌÏËÉÒÏ×ÁÎÁ ÕÒÏ×ÎÅÍ READ lock É ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÁ",
-"ôÁÂÌÉÃÁ '%-.64s' ÎÅ ÂÙÌÁ ÚÁÂÌÏËÉÒÏ×ÁÎÁ Ó ÐÏÍÏÝØÀ LOCK TABLES",
-"îÅ×ÏÚÍÏÖÎÏ ÕËÁÚÙ×ÁÔØ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ ÓÔÏÌÂÃÁ BLOB '%-.64s'",
-"îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÂÁÚÙ ÄÁÎÎÙÈ '%-.100s'",
-"îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÔÁÂÌÉÃÙ '%-.100s'",
-"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET SQL_BIG_SELECTS=1",
-"îÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ",
-"îÅÉÚ×ÅÓÔÎÁÑ ÐÒÏÃÅÄÕÒÁ '%-.64s'",
-"îÅËÏÒÒÅËÔÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.64s'",
-"îÅËÏÒÒÅËÔÎÙÅ ÐÁÒÁÍÅÔÒÙ ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.64s'",
-"îÅÉÚ×ÅÓÔÎÁÑ ÔÁÂÌÉÃÁ '%-.64s' × %-.32s",
-"óÔÏÌÂÅà '%-.64s' ÕËÁÚÁÎ Ä×ÁÖÄÙ",
-"îÅÐÒÁ×ÉÌØÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÇÒÕÐÐÏ×ÙÈ ÆÕÎËÃÉÊ",
-"÷ ÔÁÂÌÉÃÅ '%-.64s' ÉÓÐÏÌØÚÕÀÔÓÑ ×ÏÚÍÏÖÎÏÓÔÉ, ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÍÙÅ × ÜÔÏÊ ×ÅÒÓÉÉ MySQL",
-"÷ ÔÁÂÌÉÃÅ ÄÏÌÖÅÎ ÂÙÔØ ËÁË ÍÉÎÉÍÕÍ ÏÄÉÎ ÓÔÏÌÂÅÃ",
-"ôÁÂÌÉÃÁ '%-.64s' ÐÅÒÅÐÏÌÎÅÎÁ",
-"îÅÉÚ×ÅÓÔÎÁÑ ËÏÄÉÒÏ×ËÁ '%-.64s'",
-"óÌÉÛËÏÍ ÍÎÏÇÏ ÔÁÂÌÉÃ. MySQL ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØ ÔÏÌØËÏ %d ÔÁÂÌÉÃ × ÓÏÅÄÉÎÅÎÉÉ",
-"óÌÉÛËÏÍ ÍÎÏÇÏ ÓÔÏÌÂÃÏ×",
-"óÌÉÛËÏÍ ÂÏÌØÛÏÊ ÒÁÚÍÅÒ ÚÁÐÉÓÉ. íÁËÓÉÍÁÌØÎÙÊ ÒÁÚÍÅÒ ÓÔÒÏËÉ, ÉÓËÌÀÞÁÑ ÐÏÌÑ BLOB, - %d. ÷ÏÚÍÏÖÎÏ, ×ÁÍ ÓÌÅÄÕÅÔ ÉÚÍÅÎÉÔØ ÔÉÐ ÎÅËÏÔÏÒÙÈ ÐÏÌÅÊ ÎÁ BLOB",
-"óÔÅË ÐÏÔÏËÏ× ÐÅÒÅÐÏÌÎÅÎ: ÉÓÐÏÌØÚÏ×ÁÎÏ: %ld ÉÚ %ld ÓÔÅËÁ. ðÒÉÍÅÎÑÊÔÅ 'mysqld -O thread_stack=#' ÄÌÑ ÕËÁÚÁÎÉÑ ÂÏÌØÛÅÇÏ ÒÁÚÍÅÒÁ ÓÔÅËÁ, ÅÓÌÉ ÎÅÏÂÈÏÄÉÍÏ",
-"÷ OUTER JOIN ÏÂÎÁÒÕÖÅÎÁ ÐÅÒÅËÒÅÓÔÎÁÑ ÚÁ×ÉÓÉÍÏÓÔØ. ÷ÎÉÍÁÔÅÌØÎÏ ÐÒÏÁÎÁÌÉÚÉÒÕÊÔÅ Ó×ÏÉ ÕÓÌÏ×ÉÑ ON",
-"óÔÏÌÂÅÃ '%-.64s' ÉÓÐÏÌØÚÕÅÔÓÑ × UNIQUE ÉÌÉ × INDEX, ÎÏ ÎÅ ÏÐÒÅÄÅÌÅÎ ËÁË NOT NULL",
-"îÅ×ÏÚÍÏÖÎÏ ÚÁÇÒÕÚÉÔØ ÆÕÎËÃÉÀ '%-.64s'",
-"îÅ×ÏÚÍÏÖÎÏ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÔØ ÆÕÎËÃÉÀ '%-.64s'; %-.80s",
-"îÅÄÏÐÕÓÔÉÍÏ ÕËÁÚÙ×ÁÔØ ÐÕÔÉ ÄÌÑ ÄÉÎÁÍÉÞÅÓËÉÈ ÂÉÂÌÉÏÔÅË",
-"æÕÎËÃÉÑ '%-.64s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ",
-"îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÉÎÁÍÉÞÅÓËÕÀ ÂÉÂÌÉÏÔÅËÕ '%-.64s' (ÏÛÉÂËÁ: %d %-.64s)",
-"îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÆÕÎËÃÉÀ '%-.64s' × ÂÉÂÌÉÏÔÅËÅ",
-"æÕÎËÃÉÑ '%-.64s' ÎÅ ÏÐÒÅÄÅÌÅÎÁ",
-"èÏÓÔ '%-.64s' ÚÁÂÌÏËÉÒÏ×ÁÎ ÉÚ-ÚÁ ÓÌÉÛËÏÍ ÂÏÌØÛÏÇÏ ËÏÌÉÞÅÓÔ×Á ÏÛÉÂÏË ÓÏÅÄÉÎÅÎÉÑ. òÁÚÂÌÏËÉÒÏ×ÁÔØ ÅÇÏ ÍÏÖÎÏ Ó ÐÏÍÏÝØÀ 'mysqladmin flush-hosts'",
-"èÏÓÔÕ '%-.64s' ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÐÏÄËÌÀÞÁÔØÓÑ Ë ÜÔÏÍÕ ÓÅÒ×ÅÒÕ MySQL",
-"÷Ù ÉÓÐÏÌØÚÕÅÔÅ MySQL ÏÔ ÉÍÅÎÉ ÁÎÏÎÉÍÎÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ, Á ÁÎÏÎÉÍÎÙÍ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÍÅÎÑÔØ ÐÁÒÏÌÉ",
-"äÌÑ ÔÏÇÏ ÞÔÏÂÙ ÉÚÍÅÎÑÔØ ÐÁÒÏÌÉ ÄÒÕÇÉÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, Õ ×ÁÓ ÄÏÌÖÎÙ ÂÙÔØ ÐÒÉ×ÉÌÅÇÉÉ ÎÁ ÉÚÍÅÎÅÎÉÅ ÔÁÂÌÉÃ × ÂÁÚÅ ÄÁÎÎÙÈ mysql",
-"îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÐÏÄÈÏÄÑÝÕÀ ÚÁÐÉÓØ × ÔÁÂÌÉÃÅ ÐÏÌØÚÏ×ÁÔÅÌÅÊ",
-"óÏ×ÐÁÌÏ ÚÁÐÉÓÅÊ: %ld éÚÍÅÎÅÎÏ: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÎÏ×ÙÊ ÐÏÔÏË (ÏÛÉÂËÁ %d). åÓÌÉ ÜÔÏ ÎÅ ÓÉÔÕÁÃÉÑ, Ó×ÑÚÁÎÎÁÑ Ó ÎÅÈ×ÁÔËÏÊ ÐÁÍÑÔÉ, ÔÏ ×ÁÍ ÓÌÅÄÕÅÔ ÉÚÕÞÉÔØ ÄÏËÕÍÅÎÔÁÃÉÀ ÎÁ ÐÒÅÄÍÅÔ ÏÐÉÓÁÎÉÑ ×ÏÚÍÏÖÎÏÊ ÏÛÉÂËÉ ÒÁÂÏÔÙ × ËÏÎËÒÅÔÎÏÊ ïó",
-"ëÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ× ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ËÏÌÉÞÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ × ÚÁÐÉÓÉ %ld",
-"îÅ×ÏÚÍÏÖÎÏ ÚÁÎÏ×Ï ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ '%-.64s'",
-"îÅÐÒÁ×ÉÌØÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ×ÅÌÉÞÉÎÙ NULL",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ '%-.64s' ÏÔ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ",
-"ïÄÎÏ×ÒÅÍÅÎÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÓÇÒÕÐÐÉÒÏ×ÁÎÎÙÈ (GROUP) ÓÔÏÌÂÃÏ× (MIN(),MAX(),COUNT(),...) Ó ÎÅÓÇÒÕÐÐÉÒÏ×ÁÎÎÙÍÉ ÓÔÏÌÂÃÁÍÉ Ñ×ÌÑÅÔÓÑ ÎÅËÏÒÒÅËÔÎÙÍ, ÅÓÌÉ × ×ÙÒÁÖÅÎÉÉ ÅÓÔØ GROUP BY",
-"ôÁËÉÅ ÐÒÁ×Á ÎÅ ÏÐÒÅÄÅÌÅÎÙ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' ÎÁ ÈÏÓÔÅ '%-.64s'",
-"ëÏÍÁÎÄÁ %-.16s ÚÁÐÒÅÝÅÎÁ ÐÏÌØÚÏ×ÁÔÅÌÀ '%-.32s'@'%-.64s' ÄÌÑ ÔÁÂÌÉÃÙ '%-.64s'",
-"ëÏÍÁÎÄÁ %-.16s ÚÁÐÒÅÝÅÎÁ ÐÏÌØÚÏ×ÁÔÅÌÀ '%-.32s'@'%-.64s' ÄÌÑ ÓÔÏÌÂÃÁ '%-.64s' × ÔÁÂÌÉÃÅ '%-.64s'",
-"îÅ×ÅÒÎÁÑ ËÏÍÁÎÄÁ GRANT ÉÌÉ REVOKE. ïÂÒÁÔÉÔÅÓØ Ë ÄÏËÕÍÅÎÔÁÃÉÉ, ÞÔÏÂÙ ×ÙÑÓÎÉÔØ, ËÁËÉÅ ÐÒÉ×ÉÌÅÇÉÉ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ",
-"óÌÉÛËÏÍ ÄÌÉÎÎÏÅ ÉÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ/ÈÏÓÔÁ ÄÌÑ GRANT",
-"ôÁÂÌÉÃÁ '%-.64s.%-.64s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ",
-"ôÁËÉÅ ÐÒÁ×Á ÎÅ ÏÐÒÅÄÅÌÅÎÙ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' ÎÁ ËÏÍÐØÀÔÅÒÅ '%-.64s' ÄÌÑ ÔÁÂÌÉÃÙ '%-.64s'",
-"üÔÁ ËÏÍÁÎÄÁ ÎÅ ÄÏÐÕÓËÁÅÔÓÑ × ÄÁÎÎÏÊ ×ÅÒÓÉÉ MySQL",
-"õ ×ÁÓ ÏÛÉÂËÁ × ÚÁÐÒÏÓÅ. éÚÕÞÉÔÅ ÄÏËÕÍÅÎÔÁÃÉÀ ÐÏ ÉÓÐÏÌØÚÕÅÍÏÊ ×ÅÒÓÉÉ MySQL ÎÁ ÐÒÅÄÍÅÔ ËÏÒÒÅËÔÎÏÇÏ ÓÉÎÔÁËÓÉÓÁ",
-"ðÏÔÏË, ÏÂÓÌÕÖÉ×ÁÀÝÉÊ ÏÔÌÏÖÅÎÎÕÀ ×ÓÔÁ×ËÕ (delayed insert), ÎÅ ÓÍÏÇ ÐÏÌÕÞÉÔØ ÚÁÐÒÁÛÉ×ÁÅÍÕÀ ÂÌÏËÉÒÏ×ËÕ ÎÁ ÔÁÂÌÉÃÕ %-.64s",
-"óÌÉÛËÏÍ ÍÎÏÇÏ ÐÏÔÏËÏ×, ÏÂÓÌÕÖÉ×ÁÀÝÉÈ ÏÔÌÏÖÅÎÎÕÀ ×ÓÔÁ×ËÕ (delayed insert)",
-"ðÒÅÒ×ÁÎÏ ÓÏÅÄÉÎÅÎÉÅ %ld Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.64s' ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' (%-.64s)",
-"ðÏÌÕÞÅÎÎÙÊ ÐÁËÅÔ ÂÏÌØÛÅ, ÞÅÍ 'max_allowed_packet'",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÞÔÅÎÉÑ ÏÔ ÐÏÔÏËÁ ÓÏÅÄÉÎÅÎÉÑ (connection pipe)",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÏÔ fcntl()",
-"ðÁËÅÔÙ ÐÏÌÕÞÅÎÙ × ÎÅ×ÅÒÎÏÍ ÐÏÒÑÄËÅ",
-"îÅ×ÏÚÍÏÖÎÏ ÒÁÓÐÁËÏ×ÁÔØ ÐÁËÅÔ, ÐÏÌÕÞÅÎÎÙÊ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ × ÐÒÏÃÅÓÓÅ ÐÏÌÕÞÅÎÉÑ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ ",
-"ðÏÌÕÞÅÎ ÔÁÊÍÁÕÔ ÏÖÉÄÁÎÉÑ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ ",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÐÒÉ ÐÅÒÅÄÁÞÅ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ ",
-"ðÏÌÕÞÅÎ ÔÁÊÍÁÕÔ × ÐÒÏÃÅÓÓÅ ÐÅÒÅÄÁÞÉ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ ",
-"òÅÚÕÌØÔÉÒÕÀÝÁÑ ÓÔÒÏËÁ ÂÏÌØÛÅ, ÞÅÍ 'max_allowed_packet'",
-"éÓÐÏÌØÚÕÅÍÁÑ ÔÁÂÌÉÃÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÔÉÐÙ BLOB/TEXT",
-"éÓÐÏÌØÚÕÅÍÁÑ ÔÁÂÌÉÃÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ Á×ÔÏÉÎËÒÅÍÅÎÔÎÙÅ ÓÔÏÌÂÃÙ",
-"îÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ INSERT DELAYED ÄÌÑ ÔÁÂÌÉÃÙ '%-.64s', ÐÏÔÏÍÕ ÞÔÏ ÏÎÁ ÚÁÂÌÏËÉÒÏ×ÁÎÁ Ó ÐÏÍÏÝØÀ LOCK TABLES",
-"îÅ×ÅÒÎÏÅ ÉÍÑ ÓÔÏÌÂÃÁ '%-.100s'",
-"éÓÐÏÌØÚÏ×ÁÎÎÙÊ ÏÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÍÏÖÅÔ ÐÒÏÉÎÄÅËÓÉÒÏ×ÁÔØ ÓÔÏÌÂÅà '%-.64s'",
-"îÅ ×ÓÅ ÔÁÂÌÉÃÙ × MERGE ÏÐÒÅÄÅÌÅÎÙ ÏÄÉÎÁËÏ×Ï",
-"îÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ × ÔÁÂÌÉÃÕ '%-.64s' ÉÚ-ÚÁ ÏÇÒÁÎÉÞÅÎÉÊ ÕÎÉËÁÌØÎÏÇÏ ËÌÀÞÁ",
-"óÔÏÌÂÅÃ ÔÉÐÁ BLOB '%-.64s' ÂÙÌ ÕËÁÚÁÎ × ÏÐÒÅÄÅÌÅÎÉÉ ËÌÀÞÁ ÂÅÚ ÕËÁÚÁÎÉÑ ÄÌÉÎÙ ËÌÀÞÁ",
-"÷ÓÅ ÞÁÓÔÉ ÐÅÒ×ÉÞÎÏÇÏ ËÌÀÞÁ (PRIMARY KEY) ÄÏÌÖÎÙ ÂÙÔØ ÏÐÒÅÄÅÌÅÎÙ ËÁË NOT NULL; åÓÌÉ ×ÁÍ ÎÕÖÎÁ ÐÏÄÄÅÒÖËÁ ×ÅÌÉÞÉÎ NULL × ËÌÀÞÅ, ×ÏÓÐÏÌØÚÕÊÔÅÓØ ÉÎÄÅËÓÏÍ UNIQUE",
-"÷ ÒÅÚÕÌØÔÁÔÅ ×ÏÚ×ÒÁÝÅÎÁ ÂÏÌÅÅ ÞÅÍ ÏÄÎÁ ÓÔÒÏËÁ",
-"üÔÏÔ ÔÉÐ ÔÁÂÌÉÃÙ ÔÒÅÂÕÅÔ ÏÐÒÅÄÅÌÅÎÉÑ ÐÅÒ×ÉÞÎÏÇÏ ËÌÀÞÁ",
-"üÔÁ ×ÅÒÓÉÑ MySQL ÓËÏÍÐÉÌÉÒÏ×ÁÎÁ ÂÅÚ ÐÏÄÄÅÒÖËÉ RAID",
-"÷Ù ÒÁÂÏÔÁÅÔÅ × ÒÅÖÉÍÅ ÂÅÚÏÐÁÓÎÙÈ ÏÂÎÏ×ÌÅÎÉÊ (safe update mode) É ÐÏÐÒÏÂÏ×ÁÌÉ ÉÚÍÅÎÉÔØ ÔÁÂÌÉÃÕ ÂÅÚ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ËÌÀÞÅ×ÏÇÏ ÓÔÏÌÂÃÁ × ÞÁÓÔÉ WHERE",
-"ëÌÀÞ '%-.64s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ × ÔÁÂÌÉÃÅ '%-.64s'",
-"îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ",
-"ïÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÜÔÏÇÏ: %s",
-"÷ÁÍ ÎÅ ÒÁÚÒÅÛÅÎÏ ×ÙÐÏÌÎÑÔØ ÜÔÕ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËÃÉÉ",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ COMMIT",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ ROLLBACK",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ FLUSH_LOGS",
-"ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ CHECKPOINT",
-"ðÒÅÒ×ÁÎÏ ÓÏÅÄÉÎÅÎÉÅ %ld Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.64s' ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.32s' Ó ÈÏÓÔÁ `%-.64s' (%-.64s)",
-"ïÂÒÁÂÏÔÞÉË ÜÔÏÊ ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ Ä×ÏÉÞÎÏÇÏ ÓÏÈÒÁÎÅÎÉÑ ÏÂÒÁÚÁ ÔÁÂÌÉÃÙ (dump)",
-"ä×ÏÉÞÎÙÊ ÖÕÒÎÁÌ ÏÂÎÏ×ÌÅÎÉÑ ÚÁËÒÙÔ, ÎÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ RESET MASTER",
-"ïÛÉÂËÁ ÐÅÒÅÓÔÒÏÊËÉ ÉÎÄÅËÓÁ ÓÏÈÒÁÎÅÎÎÏÊ ÔÁÂÌÉÃÙ '%-.64s'",
-"ïÛÉÂËÁ ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ: '%-.64s'",
-"÷ÏÚÎÉËÌÁ ÏÛÉÂËÁ ÞÔÅÎÉÑ × ÐÒÏÃÅÓÓÅ ËÏÍÍÕÎÉËÁÃÉÉ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ",
-"÷ÏÚÎÉËÌÁ ÏÛÉÂËÁ ÚÁÐÉÓÉ × ÐÒÏÃÅÓÓÅ ËÏÍÍÕÎÉËÁÃÉÉ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ",
-"îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÐÏÌÎÏÔÅËÓÔÏ×ÙÊ (FULLTEXT) ÉÎÄÅËÓ, ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÊ ÓÐÉÓËÕ ÓÔÏÌÂÃÏ×",
-"îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÕËÁÚÁÎÎÕÀ ËÏÍÁÎÄÕ, ÐÏÓËÏÌØËÕ Õ ×ÁÓ ÐÒÉÓÕÔÓÔ×ÕÀÔ ÁËÔÉ×ÎÏ ÚÁÂÌÏËÉÒÏ×ÁÎÎÙÅ ÔÁÂÌÉÃÁ ÉÌÉ ÏÔËÒÙÔÁÑ ÔÒÁÎÚÁËÃÉÑ",
-"îÅÉÚ×ÅÓÔÎÁÑ ÓÉÓÔÅÍÎÁÑ ÐÅÒÅÍÅÎÎÁÑ '%-.64s'",
-"ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÄÏÌÖÎÁ ÐÒÏÊÔÉ ÐÒÏ×ÅÒËÕ É ÒÅÍÏÎÔ",
-"ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÐÏÓÌÅÄÎÉÊ (Á×ÔÏÍÁÔÉÞÅÓËÉÊ?) ÒÅÍÏÎÔ ÎÅ ÂÙÌ ÕÓÐÅÛÎÙÍ",
-"÷ÎÉÍÁÎÉÅ: ÐÏ ÎÅËÏÔÏÒÙÍ ÉÚÍÅÎÅÎÎÙÍ ÎÅÔÒÁÎÚÁËÃÉÏÎÎÙÍ ÔÁÂÌÉÃÁÍ ÎÅ×ÏÚÍÏÖÎÏ ÂÕÄÅÔ ÐÒÏÉÚ×ÅÓÔÉ ÏÔËÁÔ ÔÒÁÎÚÁËÃÉÉ",
-"ôÒÁÎÚÁËÃÉÉ, ×ËÌÀÞÁÀÝÅÊ ÂÏÌØÛÏÅ ËÏÌÉÞÅÓÔ×Ï ËÏÍÁÎÄ, ÐÏÔÒÅÂÏ×ÁÌÏÓØ ÂÏÌÅÅ ÞÅÍ 'max_binlog_cache_size' ÂÁÊÔ. õ×ÅÌÉÞØÔÅ ÜÔÕ ÐÅÒÅÍÅÎÎÕÀ ÓÅÒ×ÅÒÁ mysqld É ÐÏÐÒÏÂÕÊÔÅ ÅÝÅ ÒÁÚ",
-"üÔÕ ÏÐÅÒÁÃÉÀ ÎÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÐÒÉ ÒÁÂÏÔÁÀÝÅÍ ÐÏÔÏËÅ ÐÏÄÞÉÎÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ. óÎÁÞÁÌÁ ×ÙÐÏÌÎÉÔÅ STOP SLAVE",
-"äÌÑ ÜÔÏÊ ÏÐÅÒÁÃÉÉ ÔÒÅÂÕÅÔÓÑ ÒÁÂÏÔÁÀÝÉÊ ÐÏÄÞÉÎÅÎÎÙÊ ÓÅÒ×ÅÒ. óÎÁÞÁÌÁ ×ÙÐÏÌÎÉÔÅ START SLAVE",
-"üÔÏÔ ÓÅÒ×ÅÒ ÎÅ ÎÁÓÔÒÏÅÎ ËÁË ÐÏÄÞÉÎÅÎÎÙÊ. ÷ÎÅÓÉÔÅ ÉÓÐÒÁ×ÌÅÎÉÑ × ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÍ ÆÁÊÌÅ ÉÌÉ Ó ÐÏÍÏÝØÀ CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÐÏÔÏË ÐÏÄÞÉÎÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ. ðÒÏ×ÅÒØÔÅ ÓÉÓÔÅÍÎÙÅ ÒÅÓÕÒÓÙ",
-"õ ÐÏÌØÚÏ×ÁÔÅÌÑ %-.64s ÕÖÅ ÂÏÌØÛÅ ÞÅÍ 'max_user_connections' ÁËÔÉ×ÎÙÈ ÓÏÅÄÉÎÅÎÉÊ",
-"÷Ù ÍÏÖÅÔÅ ÉÓÐÏÌØÚÏ×ÁÔØ × SET ÔÏÌØËÏ ËÏÎÓÔÁÎÔÎÙÅ ×ÙÒÁÖÅÎÉÑ",
-"ôÁÊÍÁÕÔ ÏÖÉÄÁÎÉÑ ÂÌÏËÉÒÏ×ËÉ ÉÓÔÅË; ÐÏÐÒÏÂÕÊÔÅ ÐÅÒÅÚÁÐÕÓÔÉÔØ ÔÒÁÎÚÁËÃÉÀ",
-"ïÂÝÅÅ ËÏÌÉÞÅÓÔ×Ï ÂÌÏËÉÒÏ×ÏË ÐÒÅ×ÙÓÉÌÏ ÒÁÚÍÅÒÙ ÔÁÂÌÉÃÙ ÂÌÏËÉÒÏ×ÏË",
-"âÌÏËÉÒÏ×ËÉ ÏÂÎÏ×ÌÅÎÉÊ ÎÅÌØÚÑ ÐÏÌÕÞÉÔØ × ÐÒÏÃÅÓÓÅ ÞÔÅÎÉÑ ÎÅ ÐÒÉÎÑÔÏÊ (× ÒÅÖÉÍÅ READ UNCOMMITTED) ÔÒÁÎÚÁËÃÉÉ",
-"îÅ ÄÏÐÕÓËÁÅÔÓÑ DROP DATABASE, ÐÏËÁ ÐÏÔÏË ÄÅÒÖÉÔ ÇÌÏÂÁÌØÎÕÀ ÂÌÏËÉÒÏ×ËÕ ÞÔÅÎÉÑ",
-"îÅ ÄÏÐÕÓËÁÅÔÓÑ CREATE DATABASE, ÐÏËÁ ÐÏÔÏË ÄÅÒÖÉÔ ÇÌÏÂÁÌØÎÕÀ ÂÌÏËÉÒÏ×ËÕ ÞÔÅÎÉÑ",
-"îÅ×ÅÒÎÙÅ ÐÁÒÁÍÅÔÒÙ ÄÌÑ %s",
-"'%-.32s'@'%-.64s' ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÓÏÚÄÁ×ÁÔØ ÎÏ×ÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ",
-"îÅ×ÅÒÎÏÅ ÏÐÒÅÄÅÌÅÎÉÅ ÔÁÂÌÉÃÙ; ÷ÓÅ ÔÁÂÌÉÃÙ × MERGE ÄÏÌÖÎÙ ÐÒÉÎÁÄÌÅÖÁÔØ ÏÄÎÏÊ É ÔÏÊ ÖÅ ÂÁÚÅ ÄÁÎÎÙÈ",
-"÷ÏÚÎÉËÌÁ ÔÕÐÉËÏ×ÁÑ ÓÉÔÕÁÃÉÑ × ÐÒÏÃÅÓÓÅ ÐÏÌÕÞÅÎÉÑ ÂÌÏËÉÒÏ×ËÉ; ðÏÐÒÏÂÕÊÔÅ ÐÅÒÅÚÁÐÕÓÔÉÔØ ÔÒÁÎÚÁËÃÉÀ",
-"éÓÐÏÌØÚÕÅÍÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÐÏÌÎÏÔÅËÓÔÏ×ÙÈ ÉÎÄÅËÓÏ×",
-"îÅ×ÏÚÍÏÖÎÏ ÄÏÂÁ×ÉÔØ ÏÇÒÁÎÉÞÅÎÉÑ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ",
-"îÅ×ÏÚÍÏÖÎÏ ÄÏÂÁ×ÉÔØ ÉÌÉ ÏÂÎÏ×ÉÔØ ÄÏÞÅÒÎÀÀ ÓÔÒÏËÕ: ÐÒÏ×ÅÒËÁ ÏÇÒÁÎÉÞÅÎÉÊ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ ÎÅ ×ÙÐÏÌÎÑÅÔÓÑ",
-"îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÉÌÉ ÏÂÎÏ×ÉÔØ ÒÏÄÉÔÅÌØÓËÕÀ ÓÔÒÏËÕ: ÐÒÏ×ÅÒËÁ ÏÇÒÁÎÉÞÅÎÉÊ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ ÎÅ ×ÙÐÏÌÎÑÅÔÓÑ",
-"ïÛÉÂËÁ ÓÏÅÄÉÎÅÎÉÑ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ: %-.128s",
-"ïÛÉÂËÁ ×ÙÐÏÌÎÅÎÉÑ ÚÁÐÒÏÓÁ ÎÁ ÇÏÌÏ×ÎÏÍ ÓÅÒ×ÅÒÅ: %-.128s",
-"ïÛÉÂËÁ ÐÒÉ ×ÙÐÏÌÎÅÎÉÉ ËÏÍÁÎÄÙ %s: %-.128s",
-"îÅ×ÅÒÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ %s É %s",
-"éÓÐÏÌØÚÏ×ÁÎÎÙÅ ÏÐÅÒÁÔÏÒÙ ×ÙÂÏÒËÉ (SELECT) ÄÁÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×",
-"îÅ×ÏÚÍÏÖÎÏ ÉÓÐÏÌÎÉÔØ ÚÁÐÒÏÓ, ÐÏÓËÏÌØËÕ Õ ×ÁÓ ÕÓÔÁÎÏ×ÌÅÎÙ ËÏÎÆÌÉËÔÕÀÝÉÅ ÂÌÏËÉÒÏ×ËÉ ÞÔÅÎÉÑ",
-"éÓÐÏÌØÚÏ×ÁÎÉÅ ÔÒÁÎÚÁËÃÉÏÎÎÙÈ ÔÁÂÌÉà ÎÁÒÑÄÕ Ó ÎÅÔÒÁÎÚÁËÃÉÏÎÎÙÍÉ ÚÁÐÒÅÝÅÎÏ",
-"ïÐÃÉÑ '%s' Ä×ÁÖÄÙ ÉÓÐÏÌØÚÏ×ÁÎÁ × ×ÙÒÁÖÅÎÉÉ",
-"ðÏÌØÚÏ×ÁÔÅÌØ '%-.64s' ÐÒÅ×ÙÓÉÌ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÒÅÓÕÒÓÁ '%s' (ÔÅËÕÝÅÅ ÚÎÁÞÅÎÉÅ: %ld)",
-"÷ ÄÏÓÔÕÐÅ ÏÔËÁÚÁÎÏ. ÷ÁÍ ÎÕÖÎÙ ÐÒÉ×ÉÌÅÇÉÉ %-.128s ÄÌÑ ÜÔÏÊ ÏÐÅÒÁÃÉÉ",
-"ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÐÏÔÏËÏ×ÏÊ (SESSION) ÐÅÒÅÍÅÎÎÏÊ É ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÁ Ó ÐÏÍÏÝØÀ SET GLOBAL",
-"ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÇÌÏÂÁÌØÎÏÊ (GLOBAL) ÐÅÒÅÍÅÎÎÏÊ, É ÅÅ ÓÌÅÄÕÅÔ ÉÚÍÅÎÑÔØ Ó ÐÏÍÏÝØÀ SET GLOBAL",
-"ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÎÅ ÉÍÅÅÔ ÚÎÁÞÅÎÉÑ ÐÏ ÕÍÏÌÞÁÎÉÀ",
-"ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÕÓÔÁÎÏ×ÌÅÎÁ × ÚÎÁÞÅÎÉÅ '%-.64s'",
-"îÅ×ÅÒÎÙÊ ÔÉÐ ÁÒÇÕÍÅÎÔÁ ÄÌÑ ÐÅÒÅÍÅÎÎÏÊ '%-.64s'",
-"ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÍÏÖÅÔ ÂÙÔØ ÔÏÌØËÏ ÕÓÔÁÎÏ×ÌÅÎÁ, ÎÏ ÎÅ ÓÞÉÔÁÎÁ",
-"îÅ×ÅÒÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÉÌÉ × ÎÅ×ÅÒÎÏÍ ÍÅÓÔÅ ÕËÁÚÁÎ '%s'",
-"üÔÁ ×ÅÒÓÉÑ MySQL ÐÏËÁ ÅÝÅ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ '%s'",
-"ðÏÌÕÞÅÎÁ ÎÅÉÓÐÒÁ×ÉÍÁÑ ÏÛÉÂËÁ %d: '%-.128s' ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ × ÐÒÏÃÅÓÓÅ ×ÙÂÏÒËÉ ÄÁÎÎÙÈ ÉÚ Ä×ÏÉÞÎÏÇÏ ÖÕÒÎÁÌÁ",
-"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",
-"ïÐÅÒÁÎÄ ÄÏÌÖÅÎ ÓÏÄÅÒÖÁÔØ %d ËÏÌÏÎÏË",
-"ðÏÄÚÁÐÒÏÓ ×ÏÚ×ÒÁÝÁÅÔ ÂÏÌÅÅ ÏÄÎÏÊ ÚÁÐÉÓÉ",
-"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 its own alias",
-"Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ",
-"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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"ôÁÂÌÉÃÁ %-.100s × %s ÎÅ ÍÏÖÅÔ ÉÚÍÅÎÑÔÓÑ",
-"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
-"The MySQL server is running with the %s option so it cannot execute this statement",
-"Column '%-.100s' has duplicated value '%-.64s' in %s"
-"Truncated wrong %-.32s value: '%-.128s'"
-"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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
deleted file mode 100644
index adda7d7cf53..00000000000
--- a/sql/share/serbian/errmsg.txt
+++ /dev/null
@@ -1,315 +0,0 @@
-/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB
- This file is public domain and comes with NO WARRANTY of any kind */
-
-/* Serbian Translation, version 1.0:
- Copyright 2002 Vladimir Kraljevic, vladimir_kraljevic@yahoo.com
- This file is public domain and comes with NO WARRANTY of any kind.
- Charset: cp1250
-*/
-
-character-set=cp1250
-
-"hashchk",
-"isamchk",
-"NE",
-"DA",
-"Ne mogu da kreiram file '%-.64s' (errno: %d)",
-"Ne mogu da kreiram tabelu '%-.64s' (errno: %d)",
-"Ne mogu da kreiram bazu '%-.64s' (errno: %d)",
-"Ne mogu da kreiram bazu '%-.64s'; baza veæ postoji.",
-"Ne mogu da izbrišem bazu '%-.64s'; baza ne postoji.",
-"Ne mogu da izbrišem bazu (ne mogu da izbrišem '%-.64s', errno: %d)",
-"Ne mogu da izbrišem bazu (ne mogu da izbrišem direktorijum '%-.64s', errno: %d)",
-"Greška pri brisanju '%-.64s' (errno: %d)",
-"Ne mogu da proèitam slog iz sistemske tabele",
-"Ne mogu da dobijem stanje file-a '%-.64s' (errno: %d)",
-"Ne mogu da dobijem trenutni direktorijum (errno: %d)",
-"Ne mogu da zakljuèam file (errno: %d)",
-"Ne mogu da otvorim file: '%-.64s' (errno: %d)",
-"Ne mogu da pronaðem file: '%-.64s' (errno: %d)",
-"Ne mogu da proèitam direktorijum '%-.64s' (errno: %d)",
-"Ne mogu da promenim direktorijum na '%-.64s' (errno: %d)",
-"Slog je promenjen od zadnjeg èitanja tabele '%-.64s'",
-"Disk je pun (%s). Èekam nekoga da doðe i oslobodi nešto mesta...",
-"Ne mogu da pišem pošto postoji duplirani kljuè u tabeli '%-.64s'",
-"Greška pri zatvaranju '%-.64s' (errno: %d)",
-"Greška pri èitanju file-a '%-.64s' (errno: %d)",
-"Greška pri promeni imena '%-.64s' na '%-.64s' (errno: %d)",
-"Greška pri upisu '%-.64s' (errno: %d)",
-"'%-.64s' je zakljuèan za upis",
-"Sortiranje je prekinuto",
-"View '%-.64s' ne postoji za '%-.64s'",
-"Handler tabela je vratio grešku %d",
-"Handler tabela za '%-.64s' nema ovu opciju",
-"Ne mogu da pronaðem slog u '%-.64s'",
-"Pogrešna informacija u file-u: '%-.64s'",
-"Pogrešan key file za tabelu: '%-.64s'; probajte da ga ispravite",
-"Zastareo key file za tabelu '%-.64s'; ispravite ga",
-"Tabelu '%-.64s' je dozvoljeno samo èitati",
-"Nema memorije. Restartujte MySQL server i probajte ponovo (potrebno je %d byte-ova)",
-"Nema memorije za sortiranje. Poveæajte velièinu sort buffer-a MySQL server-u",
-"Neoèekivani kraj pri èitanju file-a '%-.64s' (errno: %d)",
-"Previše konekcija",
-"Nema memorije; Proverite da li MySQL server ili neki drugi proces koristi svu slobodnu memoriju. (UNIX: Ako ne, probajte da upotrebite 'ulimit' komandu da biste dozvolili daemon-u da koristi više memorije ili probajte da dodate više swap memorije)",
-"Ne mogu da dobijem ime host-a za vašu IP adresu",
-"Loš poèetak komunikacije (handshake)",
-"Pristup je zabranjen korisniku '%-.32s'@'%-.64s' za bazu '%-.64s'",
-"Pristup je zabranjen korisniku '%-.32s'@'%-.64s' (koristi lozinku: '%s')",
-"Ni jedna baza nije selektovana",
-"Nepoznata komanda",
-"Kolona '%-.64s' ne može biti NULL",
-"Nepoznata baza '%-.64s'",
-"Tabela '%-.64s' veæ postoji",
-"Nepoznata tabela '%-.64s'",
-"Kolona '%-.64s' u %-.64s nije jedinstvena u kontekstu",
-"Gašenje servera je u toku",
-"Nepoznata kolona '%-.64s' u '%-.64s'",
-"Entitet '%-.64s' nije naveden u komandi 'GROUP BY'",
-"Ne mogu da grupišem po '%-.64s'",
-"Izraz ima 'SUM' agregatnu funkciju i kolone u isto vreme",
-"Broj kolona ne odgovara broju vrednosti",
-"Ime '%-.100s' je predugaèko",
-"Duplirano ime kolone '%-.64s'",
-"Duplirano ime kljuèa '%-.64s'",
-"Dupliran unos '%-.64s' za kljuè '%d'",
-"Pogrešan naziv kolone za kolonu '%-.64s'",
-"'%s' u iskazu '%-.80s' na liniji %d",
-"Upit je bio prazan",
-"Tabela ili alias nisu bili jedinstveni: '%-.64s'",
-"Loša default vrednost za '%-.64s'",
-"Definisani višestruki primarni kljuèevi",
-"Navedeno je previše kljuèeva. Maksimum %d kljuèeva je dozvoljeno",
-"Navedeno je previše delova kljuèa. Maksimum %d delova je dozvoljeno",
-"Navedeni kljuè je predug. Maksimalna dužina kljuèa je %d",
-"Kljuèna kolona '%-.64s' ne postoji u tabeli",
-"BLOB kolona '%-.64s' ne može biti upotrebljena za navoðenje kljuèa sa tipom tabele koji se trenutno koristi",
-"Previše podataka za kolonu '%-.64s' (maksimum je %d). Upotrebite BLOB polje",
-"Pogrešna definicija tabele; U tabeli može postojati samo jedna 'AUTO' kolona i ona mora biti istovremeno definisana kao kolona kljuèa",
-"%s: Spreman za konekcije\n",
-"%s: Normalno gašenje\n",
-"%s: Dobio signal %d. Prekidam!\n",
-"%s: Gašenje završeno\n",
-"%s: Usiljeno gašenje thread-a %ld koji pripada korisniku: '%-.32s'\n",
-"Ne mogu da kreiram IP socket",
-"Tabela '%-.64s' nema isti indeks kao onaj upotrebljen pri komandi 'CREATE INDEX'. Napravite tabelu ponovo",
-"Argument separatora polja nije ono što se oèekivalo. Proverite uputstvo MySQL server-a",
-"Ne možete koristiti fiksnu velièinu sloga kada imate BLOB polja. Molim koristite 'fields terminated by' opciju.",
-"File '%-.64s' mora biti u direktorijumu gde su file-ovi baze i mora imati odgovarajuæa prava pristupa",
-"File '%-.80s' veæ postoji",
-"Slogova: %ld Izbrisano: %ld Preskoèeno: %ld Upozorenja: %ld",
-"Slogova: %ld Duplikata: %ld",
-"Pogrešan pod-kljuè dela kljuèa. Upotrebljeni deo kljuèa nije string, upotrebljena dužina je veæa od dela kljuèa ili handler tabela ne podržava jedinstvene pod-kljuèeve",
-"Ne možete da izbrišete sve kolone pomoæu komande 'ALTER TABLE'. Upotrebite komandu 'DROP TABLE' ako želite to da uradite",
-"Ne mogu da izvršim komandu drop 'DROP' na '%-.64s'. Proverite da li ta kolona (odnosno kljuè) postoji",
-"Slogova: %ld Duplikata: %ld Upozorenja: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Nepoznat thread identifikator: %lu",
-"Vi niste vlasnik thread-a %lu",
-"Nema upotrebljenih tabela",
-"Previše string-ova za kolonu '%-.64s' i komandu 'SET'",
-"Ne mogu da generišem jedinstveno ime log-file-a: '%-.64s.(1-999)'\n",
-"Tabela '%-.64s' je zakljuèana READ lock-om; iz nje se može samo èitati ali u nju se ne može pisati",
-"Tabela '%-.64s' nije bila zakljuèana komandom 'LOCK TABLES'",
-"BLOB kolona '%-.64s' ne može imati default vrednost",
-"Pogrešno ime baze '%-.100s'",
-"Pogrešno ime tabele '%-.100s'",
-"Komanda 'SELECT' æe ispitati previše slogova i potrošiti previše vremena. Proverite vaš 'WHERE' filter i upotrebite 'SET OPTION SQL_BIG_SELECTS=1' ako želite baš ovakvu komandu",
-"Nepoznata greška",
-"Nepoznata procedura '%-.64s'",
-"Pogrešan broj parametara za proceduru '%-.64s'",
-"Pogrešni parametri prosleðeni proceduri '%-.64s'",
-"Nepoznata tabela '%-.64s' u '%-.32s'",
-"Kolona '%-.64s' je navedena dva puta",
-"Pogrešna upotreba 'GROUP' funkcije",
-"Tabela '%-.64s' koristi ekstenziju koje ne postoji u ovoj verziji MySQL-a",
-"Tabela mora imati najmanje jednu kolonu",
-"Tabela '%-.64s' je popunjena do kraja",
-"Nepoznati karakter-set: '%-.64s'",
-"Previše tabela. MySQL može upotrebiti maksimum %d tabela pri 'JOIN' operaciji",
-"Previše kolona",
-"Prevelik slog. Maksimalna velièina sloga, ne raèunajuæi BLOB polja, je %d. Trebali bi da promenite tip nekih polja u BLOB",
-"Prepisivanje thread stack-a: Upotrebljeno: %ld od %ld stack memorije. Upotrebite 'mysqld -O thread_stack=#' da navedete veæi stack ako je potrebno",
-"Unakrsna zavisnost pronaðena u komandi 'OUTER JOIN'. Istražite vaše 'ON' uslove",
-"Kolona '%-.64s' je upotrebljena kao 'UNIQUE' ili 'INDEX' ali nije definisana kao 'NOT NULL'",
-"Ne mogu da uèitam funkciju '%-.64s'",
-"Ne mogu da inicijalizujem funkciju '%-.64s'; %-.80s",
-"Ne postoje dozvoljene putanje do share-ovane biblioteke",
-"Funkcija '%-.64s' veæ postoji",
-"Ne mogu da otvorim share-ovanu biblioteku '%-.64s' (errno: %d %-.64s)",
-"Ne mogu da pronadjem funkciju '%-.64s' u biblioteci",
-"Funkcija '%-.64s' nije definisana",
-"Host '%-.64s' je blokiran zbog previše grešaka u konekciji. Možete ga odblokirati pomoæu komande 'mysqladmin flush-hosts'",
-"Host-u '%-.64s' nije dozvoljeno da se konektuje na ovaj MySQL server",
-"Vi koristite MySQL kao anonimni korisnik a anonimnim korisnicima nije dozvoljeno da menjaju lozinke",
-"Morate imati privilegije da možete da update-ujete odreðene tabele ako želite da menjate lozinke za druge korisnike",
-"Ne mogu da pronaðem odgovarajuæi slog u 'user' tabeli",
-"Odgovarajuæih slogova: %ld Promenjeno: %ld Upozorenja: %ld",
-"Ne mogu da kreiram novi thread (errno %d). Ako imate još slobodne memorije, trebali biste da pogledate u priruèniku da li je ovo specifièna greška vašeg operativnog sistema",
-"Broj kolona ne odgovara broju vrednosti u slogu %ld",
-"Ne mogu da ponovo otvorim tabelu '%-.64s'",
-"Pogrešna upotreba vrednosti NULL",
-"Funkcija regexp je vratila grešku '%-.64s'",
-"Upotreba agregatnih funkcija (MIN(),MAX(),COUNT()...) bez 'GROUP' kolona je pogrešna ako ne postoji 'GROUP BY' iskaz",
-"Ne postoji odobrenje za pristup korisniku '%-.32s' na host-u '%-.64s'",
-"%-.16s komanda zabranjena za korisnika '%-.32s'@'%-.64s' za tabelu '%-.64s'",
-"%-.16s komanda zabranjena za korisnika '%-.32s'@'%-.64s' za kolonu '%-.64s' iz tabele '%-.64s'",
-"Pogrešna 'GRANT' odnosno 'REVOKE' komanda. Molim Vas pogledajte u priruèniku koje vrednosti mogu biti upotrebljene.",
-"Argument 'host' ili 'korisnik' prosleðen komandi 'GRANT' je predugaèak",
-"Tabela '%-.64s.%-.64s' ne postoji",
-"Ne postoji odobrenje za pristup korisniku '%-.32s' na host-u '%-.64s' tabeli '%-.64s'",
-"Upotrebljena komanda nije dozvoljena sa ovom verzijom MySQL servera",
-"Imate grešku u vašoj SQL sintaksi",
-"Prolongirani 'INSERT' thread nije mogao da dobije traženo zakljuèavanje tabele '%-.64s'",
-"Previše prolongiranih thread-ova je u upotrebi",
-"Prekinuta konekcija broj %ld ka bazi: '%-.64s' korisnik je bio: '%-.32s' (%-.64s)",
-"Primio sam mrežni paket veæi od definisane vrednosti 'max_allowed_packet'",
-"Greška pri èitanju podataka sa pipe-a",
-"Greška pri izvršavanju funkcije fcntl()",
-"Primio sam mrežne pakete van reda",
-"Ne mogu da dekompresujem mrežne pakete",
-"Greška pri primanju mrežnih paketa",
-"Vremenski limit za èitanje mrežnih paketa je istekao",
-"Greška pri slanju mrežnih paketa",
-"Vremenski limit za slanje mrežnih paketa je istekao",
-"Rezultujuèi string je duži nego što to dozvoljava parametar servera 'max_allowed_packet'",
-"Iskorišteni tip tabele ne podržava kolone tipa 'BLOB' odnosno 'TEXT'",
-"Iskorišteni tip tabele ne podržava kolone tipa 'AUTO_INCREMENT'",
-"Komanda 'INSERT DELAYED' ne može biti iskorištena u tabeli '%-.64s', zbog toga što je zakljuèana komandom 'LOCK TABLES'",
-"Pogrešno ime kolone '%-.100s'",
-"Handler tabele ne može da indeksira kolonu '%-.64s'",
-"Tabele iskorištene u 'MERGE' tabeli nisu definisane na isti naèin",
-"Zbog provere jedinstvenosti ne mogu da upišem podatke u tabelu '%-.64s'",
-"BLOB kolona '%-.64s' je upotrebljena u specifikaciji kljuèa bez navoðenja dužine kljuèa",
-"Svi delovi primarnog kljuèa moraju biti razlièiti od NULL; Ako Vam ipak treba NULL vrednost u kljuèu, upotrebite 'UNIQUE'",
-"Rezultat je saèinjen od više slogova",
-"Ovaj tip tabele zahteva da imate definisan primarni kljuè",
-"Ova verzija MySQL servera nije kompajlirana sa podrškom za RAID ureðaje",
-"Vi koristite safe update mod servera, a probali ste da promenite podatke bez 'WHERE' komande koja koristi kolonu kljuèa",
-"Kljuè '%-.64s' ne postoji u tabeli '%-.64s'",
-"Ne mogu da otvorim tabelu",
-"Handler za ovu tabelu ne dozvoljava 'check' odnosno 'repair' komande",
-"Nije Vam dozvoljeno da izvršite ovu komandu u transakciji",
-"Greška %d za vreme izvršavanja komande 'COMMIT'",
-"Greška %d za vreme izvršavanja komande 'ROLLBACK'",
-"Greška %d za vreme izvršavanja komande 'FLUSH_LOGS'",
-"Greška %d za vreme izvršavanja komande 'CHECKPOINT'",
-"Prekinuta konekcija broj %ld ka bazi: '%-.64s' korisnik je bio: '%-.32s' a host: `%-.64s' (%-.64s)",
-"Handler tabele ne podržava binarni dump tabele",
-"Binarni log file zatvoren, ne mogu da izvršim komandu 'RESET MASTER'",
-"Izgradnja indeksa dump-ovane tabele '%-.64s' nije uspela",
-"Greška iz glavnog servera '%-.64s' u klasteru",
-"Greška u primanju mrežnih paketa sa glavnog servera u klasteru",
-"Greška u slanju mrežnih paketa na glavni server u klasteru",
-"Ne mogu da pronaðem 'FULLTEXT' indeks koli odgovara listi kolona",
-"Ne mogu da izvršim datu komandu zbog toga što su tabele zakljuèane ili je transakcija u toku",
-"Nepoznata sistemska promenljiva '%-.64s'",
-"Tabela '%-.64s' je markirana kao ošteæena i trebala bi biti popravljena",
-"Tabela '%-.64s' je markirana kao ošteæena, a zadnja (automatska?) popravka je bila neuspela",
-"Upozorenje: Neke izmenjene tabele ne podržavaju komandu 'ROLLBACK'",
-"Transakcija sa više stavki zahtevala je više od 'max_binlog_cache_size' bajtova skladišnog prostora. Uveæajte ovu promenljivu servera i pokušajte ponovo',
-"Ova operacija ne može biti izvršena dok je aktivan podreðeni server. Zadajte prvo komandu 'STOP SLAVE' da zaustavite podreðeni server.",
-"Ova operacija zahteva da je aktivan podreðeni server. Konfigurišite prvo podreðeni server i onda izvršite komandu 'START SLAVE'",
-"Server nije konfigurisan kao podreðeni server, ispravite konfiguracioni file ili na njemu izvršite komandu 'CHANGE MASTER TO'",
-"Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info'",
-"Nisam mogao da startujem thread za podreðeni server, proverite sistemske resurse",
-"Korisnik %-.64s veæ ima više aktivnih konekcija nego što je to odreðeno 'max_user_connections' promenljivom",
-"Možete upotrebiti samo konstantan iskaz sa komandom 'SET'",
-"Vremenski limit za zakljuèavanje tabele je istekao; Probajte da ponovo startujete transakciju",
-"Broj totalnih zakljuèavanja tabele premašuje velièinu tabele zakljuèavanja",
-"Zakljuèavanja izmena ne mogu biti realizovana sve dok traje 'READ UNCOMMITTED' transakcija",
-"Komanda 'DROP DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka",
-"Komanda 'CREATE DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka",
-"Pogrešni argumenti prosleðeni na %s",
-"Korisniku '%-.32s'@'%-.64s' nije dozvoljeno da kreira nove korisnike",
-"Pogrešna definicija tabele; sve 'MERGE' tabele moraju biti u istoj bazi podataka",
-"Unakrsno zakljuèavanje pronaðeno kada sam pokušao da dobijem pravo na zakljuèavanje; Probajte da restartujete transakciju",
-"Upotrebljeni tip tabele ne podržava 'FULLTEXT' indekse",
-"Ne mogu da dodam proveru spoljnog kljuèa",
-"Ne mogu da dodam slog: provera spoljnog kljuèa je neuspela",
-"Ne mogu da izbrišem roditeljski slog: provera spoljnog kljuèa je neuspela",
-"Greška pri povezivanju sa glavnim serverom u klasteru: %-.128s",
-"Greška pri izvršavanju upita na glavnom serveru u klasteru: %-.128s",
-"Greška pri izvršavanju komande %s: %-.128s",
-"Pogrešna upotreba %s i %s",
-"Upotrebljene 'SELECT' komande adresiraju razlièit broj kolona",
-"Ne mogu da izvršim upit zbog toga što imate zakljuèavanja èitanja podataka u konfliktu",
-"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)",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updatable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
deleted file mode 100644
index fafab0c2716..00000000000
--- a/sql/share/slovak/errmsg.txt
+++ /dev/null
@@ -1,330 +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 */
-
-/*
- Translated from both E n g l i s h & C z e c h error messages
- by steve: (billik@sun.uniag.sk).
- Encoding: ISO LATIN-8852-2
- Server version: 3.21.25-gamma
- Date: Streda 11. November 1998 20:58:15
-*/
-
-character-set=latin2
-
-"hashchk",
-"isamchk",
-"NIE",
-"Áno",
-"Nemô¾em vytvori» súbor '%-.64s' (chybový kód: %d)",
-"Nemô¾em vytvori» tabuµku '%-.64s' (chybový kód: %d)",
-"Nemô¾em vytvori» databázu '%-.64s' (chybový kód: %d)",
-"Nemô¾em vytvori» databázu '%-.64s'; databáza existuje",
-"Nemô¾em zmaza» databázu '%-.64s'; databáza neexistuje",
-"Chyba pri mazaní databázy (nemô¾em zmaza» '%-.64s', chybový kód: %d)",
-"Chyba pri mazaní databázy (nemô¾em vymaza» adresár '%-.64s', chybový kód: %d)",
-"Chyba pri mazaní '%-.64s' (chybový kód: %d)",
-"Nemô¾em èíta» záznam v systémovej tabuµke",
-"Nemô¾em zisti» stav '%-.64s' (chybový kód: %d)",
-"Nemô¾em zisti» pracovný adresár (chybový kód: %d)",
-"Nemô¾em zamknú» súbor (chybový kód: %d)",
-"Nemô¾em otvori» súbor: '%-.64s' (chybový kód: %d)",
-"Nemô¾em nájs» súbor: '%-.64s' (chybový kód: %d)",
-"Nemô¾em èíta» adresár '%-.64s' (chybový kód: %d)",
-"Nemô¾em vojs» do adresára '%-.64s' (chybový kód: %d)",
-"Záznam bol zmenený od posledného èítania v tabuµke '%-.64s'",
-"Disk je plný (%s), èakám na uvoµnenie miesta...",
-"Nemô¾em zapísa», duplikát kµúèa v tabuµke '%-.64s'",
-"Chyba pri zatváraní '%-.64s' (chybový kód: %d)",
-"Chyba pri èítaní súboru '%-.64s' (chybový kód: %d)",
-"Chyba pri premenovávaní '%-.64s' na '%-.64s' (chybový kód: %d)",
-"Chyba pri zápise do súboru '%-.64s' (chybový kód: %d)",
-"'%-.64s' je zamknutý proti zmenám",
-"Triedenie preru¹ené",
-"Pohµad '%-.64s' neexistuje pre '%-.64s'",
-"Obsluha tabuµky vrátila chybu %d",
-"Obsluha tabuµky '%-.64s' nemá tento parameter",
-"Nemô¾em nájs» záznam v '%-.64s'",
-"Nesprávna informácia v súbore: '%-.64s'",
-"Nesprávny kµúè pre tabuµku '%-.64s'; pokúste sa ho opravi»",
-"Starý kµúèový súbor pre '%-.64s'; opravte ho!",
-"'%-.64s' is èíta» only",
-"Málo pamäti. Re¹tartujte daemona a skúste znova (je potrebných %d bytov)",
-"Málo pamäti pre triedenie, zvý¹te veµkos» triediaceho bufferu",
-"Neoèakávaný koniec súboru pri èítaní '%-.64s' (chybový kód: %d)",
-"Príli¹ mnoho spojení",
-"Málo miesta-pamäti pre vlákno",
-"Nemô¾em zisti» meno hostiteµa pre va¹u adresu",
-"Chyba pri nadväzovaní spojenia",
-"Zakázaný prístup pre u¾ívateµa: '%-.32s'@'%-.64s' k databázi '%-.64s'",
-"Zakázaný prístup pre u¾ívateµa: '%-.32s'@'%-.64s' (pou¾itie hesla: %s)",
-"Nebola vybraná databáza",
-"Neznámy príkaz",
-"Pole '%-.64s' nemô¾e by» null",
-"Neznáma databáza '%-.64s'",
-"Tabuµka '%-.64s' u¾ existuje",
-"Neznáma tabuµka '%-.64s'",
-"Pole: '%-.64s' v %-.64s je nejasné",
-"Prebieha ukonèovanie práce servera",
-"Neznáme pole '%-.64s' v '%-.64s'",
-"Pou¾ité '%-.64s' nebolo v 'group by'",
-"Nemô¾em pou¾i» 'group' na '%-.64s'",
-"Príkaz obsahuje zároveò funkciu 'sum' a poµa",
-"Poèet polí nezodpovedá zadanej hodnote",
-"Meno identifikátora '%-.100s' je príli¹ dlhé",
-"Opakované meno poµa '%-.64s'",
-"Opakované meno kµúèa '%-.64s'",
-"Opakovaný kµúè '%-.64s' (èíslo kµúèa %d)",
-"Chyba v ¹pecifikácii poµa '%-.64s'",
-"%s blízko '%-.80s' na riadku %d",
-"Výsledok po¾iadavky bol prázdny",
-"Nie jednoznaèná tabuµka/alias: '%-.64s'",
-"Chybná implicitná hodnota pre '%-.64s'",
-"Zadefinovaných viac primárnych kµúèov",
-"Zadaných ríli¹ veµa kµúèov. Najviac %d kµúèov je povolených",
-"Zadaných ríli¹ veµa èastí kµúèov. Je povolených najviac %d èastí",
-"Zadaný kµúè je príli¹ dlhý, najväè¹ia då¾ka kµúèa je %d",
-"Kµúèový ståpec '%-.64s' v tabuµke neexistuje",
-"Blob pole '%-.64s' nemô¾e by» pou¾ité ako kµúè",
-"Príli¹ veµká då¾ka pre pole '%-.64s' (maximum = %d). Pou¾ite BLOB",
-"Mô¾ete ma» iba jedno AUTO pole a to musí by» definované ako kµúè",
-"%s: pripravený na spojenie",
-"%s: normálne ukonèenie\n",
-"%s: prijatý signál %d, ukonèenie (Abort)!\n",
-"%s: práca ukonèená\n",
-"%s: násilné ukonèenie vlákna %ld u¾ívateµa '%-.64s'\n",
-"Nemô¾em vytvori» IP socket",
-"Tabuµka '%-.64s' nemá index zodpovedajúci CREATE INDEX. Vytvorte tabulku znova",
-"Argument oddeµovaè polí nezodpovedá po¾iadavkám. Skontrolujte v manuáli",
-"Nie je mo¾né pou¾i» fixnú då¾ku s BLOBom. Pou¾ite 'fields terminated by'.",
-"Súbor '%-.64s' musí by» v adresári databázy, alebo èitateµný pre v¹etkých",
-"Súbor '%-.64s' u¾ existuje",
-"Záznamov: %ld Zmazaných: %ld Preskoèených: %ld Varovania: %ld",
-"Záznamov: %ld Opakovaných: %ld",
-"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",
-"Neznáma identifikácia vlákna: %lu",
-"Nie ste vlastníkom vlákna %lu",
-"Nie je pou¾itá ¾iadna tabuµka",
-"Príli¹ mnoho re»azcov pre pole %-.64s a SET",
-"Nemô¾em vytvori» unikátne meno log-súboru %-.64s.(1-999)\n",
-"Tabuµka '%-.64s' bola zamknutá s READ a nemô¾e by» zmenená",
-"Tabuµka '%-.64s' nebola zamknutá s LOCK TABLES",
-"Pole BLOB '%-.64s' nemô¾e ma» implicitnú hodnotu",
-"Neprípustné meno databázy '%-.100s'",
-"Neprípustné meno tabuµky '%-.100s'",
-"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET SQL_BIG_SELECTS=1",
-"Neznámá chyba",
-"Neznámá procedúra '%-.64s'",
-"Chybný poèet parametrov procedúry '%-.64s'",
-"Chybné parametre procedúry '%-.64s'",
-"Neznáma tabuµka '%-.64s' v %s",
-"Pole '%-.64s' je zadané dvakrát",
-"Nesprávne pou¾itie funkcie GROUP",
-"Tabuµka '%-.64s' pou¾íva roz¹írenie, ktoré v tejto verzii MySQL nie je",
-"Tabuµka musí ma» aspoò 1 pole",
-"Tabuµka '%-.64s' je plná",
-"Neznáma znaková sada: '%-.64s'",
-"Príli¹ mnoho tabuliek. MySQL mô¾e pou¾i» len %d v JOIN-e",
-"Príli¹ mnoho polí",
-"Riadok je príli¹ veµký. Maximálna veµkos» riadku, okrem 'BLOB', je %d. Musíte zmeni» niektoré polo¾ky na BLOB",
-"Preteèenie zásobníku vlákna: pou¾ité: %ld z %ld. Pou¾ite 'mysqld -O thread_stack=#' k zadaniu väè¹ieho zásobníka",
-"V OUTER JOIN bol nájdený krí¾ový odkaz. Skontrolujte podmienky ON",
-"Pole '%-.64s' je pou¾ité s UNIQUE alebo INDEX, ale nie je zadefinované ako NOT NULL",
-"Nemô¾em naèíta» funkciu '%-.64s'",
-"Nemô¾em inicializova» funkciu '%-.64s'; %-.80s",
-"Neprípustné ¾iadne cesty k zdieµanej kni¾nici",
-"Funkcia '%-.64s' u¾ existuje",
-"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 not allowed to connect to this MySQL server",
-"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",
-"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",
-"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 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'",
-"The used command is not allowed with this MySQL version",
-"Something is wrong in your syntax",
-"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' bytes",
-"Got a read error from the connection pipe",
-"Got an error from fcntl()",
-"Got packets out of order",
-"Couldn't uncompress communication packet",
-"Got an error reading communication packets",
-"Got timeout reading communication packets",
-"Got an error writing communication packets",
-"Got timeout writing communication packets",
-"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",
-"Incorrect column name '%-.100s'",
-"The used table handler can't index column '%-.64s'",
-"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",
-"Result consisted of more than one row",
-"This table type requires a primary key",
-"This version of MySQL is not compiled with RAID support",
-"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
-"Key '%-.64s' doesn't exist in table '%-.64s'",
-"Can't open table",
-"The handler for the table doesn't support %s",
-"You are not allowed to execute this command in a transaction",
-"Got error %d during COMMIT",
-"Got error %d during ROLLBACK",
-"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",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Error from master: '%-.64s'",
-"Net error reading from master",
-"Net error writing to master",
-"Can't find FULLTEXT index matching the column list",
-"Can't execute the given command because you have active locked tables or an active transaction",
-"Unknown system variable '%-.64s'",
-"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",
-"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",
-"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",
-"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",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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 (%.*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 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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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'",
-"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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"The target table %-.100s of the %s is not updateable",
-"The '%s' feature was disabled; you need MySQL built with '%s' 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 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
deleted file mode 100644
index 3af8e7b97d1..00000000000
--- a/sql/share/spanish/errmsg.txt
+++ /dev/null
@@ -1,326 +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 */
-
-/*
- Traduccion por Miguel Angel Fernandez Roiz -- LoboCom Sistemas, s.l.
- From June 28, 2001 translated by Miguel Solorzano miguel@mysql.com */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NO",
-"SI",
-"No puedo crear archivo '%-.64s' (Error: %d)",
-"No puedo crear tabla '%-.64s' (Error: %d)",
-"No puedo crear base de datos '%-.64s' (Error: %d)",
-"No puedo crear base de datos '%-.64s'; la base de datos ya existe",
-"No puedo eliminar base de datos '%-.64s'; la base de datos no existe",
-"Error eliminando la base de datos(no puedo borrar '%-.64s', error %d)",
-"Error eliminando la base de datos (No puedo borrar directorio '%-.64s', error %d)",
-"Error en el borrado de '%-.64s' (Error: %d)",
-"No puedo leer el registro en la tabla del sistema",
-"No puedo obtener el estado de '%-.64s' (Error: %d)",
-"No puedo acceder al directorio (Error: %d)",
-"No puedo bloquear archivo: (Error: %d)",
-"No puedo abrir archivo: '%-.64s' (Error: %d)",
-"No puedo encontrar archivo: '%-.64s' (Error: %d)",
-"No puedo leer el directorio de '%-.64s' (Error: %d)",
-"No puedo cambiar al directorio de '%-.64s' (Error: %d)",
-"El registro ha cambiado desde la ultima lectura de la tabla '%-.64s'",
-"Disco lleno (%s). Esperando para que se libere algo de espacio...",
-"No puedo escribir, clave duplicada en la tabla '%-.64s'",
-"Error en el cierre de '%-.64s' (Error: %d)",
-"Error leyendo el fichero '%-.64s' (Error: %d)",
-"Error en el renombrado de '%-.64s' a '%-.64s' (Error: %d)",
-"Error escribiendo el archivo '%-.64s' (Error: %d)",
-"'%-.64s' esta bloqueado contra cambios",
-"Ordeancion cancelada",
-"La vista '%-.64s' no existe para '%-.64s'",
-"Error %d desde el manejador de la tabla",
-"El manejador de la tabla de '%-.64s' no tiene esta opcion",
-"No puedo encontrar el registro en '%-.64s'",
-"Informacion erronea en el archivo: '%-.64s'",
-"Clave de archivo erronea para la tabla: '%-.64s'; intente repararlo",
-"Clave de archivo antigua para la tabla '%-.64s'; reparelo!",
-"'%-.64s' es de solo lectura",
-"Memoria insuficiente. Reinicie el demonio e intentelo otra vez (necesita %d bytes)",
-"Memoria de ordenacion insuficiente. Incremente el tamano del buffer de ordenacion",
-"Inesperado fin de ficheroU mientras leiamos el archivo '%-.64s' (Error: %d)",
-"Demasiadas conexiones",
-"Memoria/espacio de tranpaso insuficiente",
-"No puedo obtener el nombre de maquina de tu direccion",
-"Protocolo erroneo",
-"Acceso negado para usuario: '%-.32s'@'%-.64s' para la base de datos '%-.64s'",
-"Acceso negado para usuario: '%-.32s'@'%-.64s' (Usando clave: %s)",
-"Base de datos no seleccionada",
-"Comando desconocido",
-"La columna '%-.64s' no puede ser nula",
-"Base de datos desconocida '%-.64s'",
-"La tabla '%-.64s' ya existe",
-"Tabla '%-.64s' desconocida",
-"La columna: '%-.64s' en %s es ambigua",
-"Desconexion de servidor en proceso",
-"La columna '%-.64s' en %s es desconocida",
-"Usado '%-.64s' el cual no esta group by",
-"No puedo agrupar por '%-.64s'",
-"El estamento tiene funciones de suma y columnas en el mismo estamento",
-"La columna con count no tiene valores para contar",
-"El nombre del identificador '%-.64s' es demasiado grande",
-"Nombre de columna duplicado '%-.64s'",
-"Nombre de clave duplicado '%-.64s'",
-"Entrada duplicada '%-.64s' para la clave %d",
-"Especificador de columna erroneo para la columna '%-.64s'",
-"%s cerca '%-.64s' en la linea %d",
-"La query estaba vacia",
-"Tabla/alias: '%-.64s' es no unica",
-"Valor por defecto invalido para '%-.64s'",
-"Multiples claves primarias definidas",
-"Demasiadas claves primarias declaradas. Un maximo de %d claves son permitidas",
-"Demasiadas partes de clave declaradas. Un maximo de %d partes son permitidas",
-"Declaracion de clave demasiado larga. La maxima longitud de clave es %d",
-"La columna clave '%-.64s' no existe en la tabla",
-"La columna Blob '%-.64s' no puede ser usada en una declaracion de clave",
-"Longitud de columna demasiado grande para la columna '%-.64s' (maximo = %d).Usar BLOB en su lugar",
-"Puede ser solamente un campo automatico y este debe ser definido como una clave",
-"%s: preparado para conexiones",
-"%s: Apagado normal\n",
-"%s: Recibiendo signal %d. Abortando!\n",
-"%s: Apagado completado\n",
-"%s: Forzando a cerrar el thread %ld usuario: '%-.64s'\n",
-"No puedo crear IP socket",
-"La tabla '%-.64s' no tiene indice como el usado en CREATE INDEX. Crea de nuevo la tabla",
-"Los separadores de argumentos del campo no son los especificados. Comprueba el manual",
-"No puedes usar longitudes de filas fijos con BLOBs. Por favor usa 'campos terminados por '.",
-"El archivo '%-.64s' debe estar en el directorio de la base de datos o ser de lectura por todos",
-"El archivo '%-.64s' ya existe",
-"Registros: %ld Borrados: %ld Saltados: %ld Peligros: %ld",
-"Registros: %ld Duplicados: %ld",
-"Parte de la clave es erronea. Una parte de la clave no es una cadena o la longitud usada es tan grande como la parte de la clave",
-"No puede borrar todos los campos con ALTER TABLE. Usa DROP TABLE para hacerlo",
-"No puedo ELIMINAR '%-.64s'. compuebe que el campo/clave existe",
-"Registros: %ld Duplicados: %ld Peligros: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
-"Identificador del thread: %lu desconocido",
-"Tu no eres el propietario del thread%lu",
-"No ha tablas usadas",
-"Muchas strings para columna %s y SET",
-"No puede crear un unico archivo log %s.(1-999)\n",
-"Tabla '%-.64s' fue trabada con un READ lock y no puede ser actualizada",
-"Tabla '%-.64s' no fue trabada con LOCK TABLES",
-"Campo Blob '%-.64s' no puede tener valores patron",
-"Nombre de base de datos ilegal '%-.64s'",
-"Nombre de tabla ilegal '%-.64s'",
-"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET SQL_BIG_SELECTS=1 si el SELECT esta correcto",
-"Error desconocido",
-"Procedimiento desconocido %s",
-"Equivocado parametro count para procedimiento %s",
-"Equivocados parametros para procedimiento %s",
-"Tabla desconocida '%-.64s' in %s",
-"Campo '%-.64s' especificado dos veces",
-"Invalido uso de función en grupo",
-"Tabla '%-.64s' usa una extensión que no existe en esta MySQL versión",
-"Una tabla debe tener al menos 1 columna",
-"La tabla '%-.64s' está llena",
-"Juego de caracteres desconocido: '%-.64s'",
-"Muchas tablas. MySQL solamente puede usar %d tablas en un join",
-"Muchos campos",
-"Tamaño de línea muy grande. Máximo tamaño de línea, no contando blob, es %d. Tu tienes que cambiar algunos campos para blob",
-"Sobrecarga de la pila de thread: Usada: %ld de una %ld pila. Use 'mysqld -O thread_stack=#' para especificar una mayor pila si necesario",
-"Dependencia cruzada encontrada en OUTER JOIN; examine su condición ON",
-"Columna '%-.32s' es usada con UNIQUE o INDEX pero no está definida como NOT NULL",
-"No puedo cargar función '%-.64s'",
-"No puedo inicializar función '%-.64s'; %-.80s",
-"No pasos permitidos para librarias conjugadas",
-"Función '%-.64s' ya existe",
-"No puedo abrir libraria conjugada '%-.64s' (errno: %d %s)",
-"No puedo encontrar función '%-.64s' en libraria'",
-"Función '%-.64s' no está definida",
-"Servidor '%-.64s' está bloqueado por muchos errores de conexión. Desbloquear con 'mysqladmin flush-hosts'",
-"Servidor '%-.64s' no está permitido para conectar con este servidor MySQL",
-"Tu estás usando MySQL como un usuario anonimo y usuarios anonimos no tienen permiso para cambiar las claves",
-"Tu debes de tener permiso para actualizar tablas en la base de datos mysql para cambiar las claves para otros",
-"No puedo encontrar una línea correponsdiente en la tabla user",
-"Líneas correspondientes: %ld Cambiadas: %ld Avisos: %ld",
-"No puedo crear un nuevo thread (errno %d). Si tu está con falta de memoria disponible, tu puedes consultar el Manual para posibles problemas con SO",
-"El número de columnas no corresponde al número en la línea %ld",
-"No puedo reabrir tabla: '%-.64s",
-"Invalido uso de valor NULL",
-"Obtenido error '%-.64s' de regexp",
-"Mezcla de columnas GROUP (MIN(),MAX(),COUNT()...) con no GROUP columnas es ilegal si no hat la clausula GROUP BY",
-"No existe permiso definido para usuario '%-.32s' en el servidor '%-.64s'",
-"%-.16s comando negado para usuario: '%-.32s'@'%-.64s' para tabla '%-.64s'",
-"%-.16s comando negado para usuario: '%-.32s'@'%-.64s' para columna '%-.64s' en la tabla '%-.64s'",
-"Ilegal comando GRANT/REVOKE. Por favor consulte el manual para cuales permisos pueden ser usados.",
-"El argumento para servidor o usuario para GRANT es demasiado grande",
-"Tabla '%-.64s.%s' no existe",
-"No existe tal permiso definido para usuario '%-.32s' en el servidor '%-.64s' en la tabla '%-.64s'",
-"El comando usado no es permitido con esta versión de MySQL",
-"Algo está equivocado en su sintax",
-"Thread de inserción retarda no pudiendo bloquear para la tabla %-.64s",
-"Muchos threads retardados en uso",
-"Conexión abortada %ld para db: '%-.64s' usuario: '%-.64s' (%s)",
-"Obtenido un paquete mayor que 'max_allowed_packet'",
-"Obtenido un error de lectura de la conexión pipe",
-"Obtenido un error de fcntl()",
-"Obtenido paquetes desordenados",
-"No puedo descomprimir paquetes de comunicación",
-"Obtenido un error leyendo paquetes de comunicación",
-"Obtenido timeout leyendo paquetes de comunicación",
-"Obtenido un error de escribiendo paquetes de comunicación",
-"Obtenido timeout escribiendo paquetes de comunicación",
-"La string resultante es mayor que 'max_allowed_packet'",
-"El tipo de tabla usada no permite soporte para columnas BLOB/TEXT",
-"El tipo de tabla usada no permite soporte para columnas AUTO_INCREMENT",
-"INSERT DELAYED no puede ser usado con tablas '%-.64s', porque esta bloqueada con LOCK TABLES",
-"Incorrecto nombre de columna '%-.100s'",
-"El manipulador de tabla usado no puede indexar columna '%-.64s'",
-"Todas las tablas en la MERGE tabla no estan definidas identicamente",
-"No puedo escribir, debido al único constraint, para tabla '%-.64s'",
-"Columna BLOB column '%-.64s' usada en especificación de clave sin tamaño de la clave",
-"Todas las partes de un PRIMARY KEY deben ser NOT NULL; Si necesitas NULL en una clave, use UNIQUE",
-"Resultado compuesto de mas que una línea",
-"Este tipo de tabla necesita de una primary key",
-"Esta versión de MySQL no es compilada con soporte RAID",
-"Tu estás usando modo de actualización segura y tentado actualizar una tabla sin un WHERE que usa una KEY columna",
-"Clave '%-.64s' no existe en la tabla '%-.64s'",
-"No puedo abrir tabla",
-"El manipulador de la tabla no permite soporte para %s",
-"No tienes el permiso para ejecutar este comando en una transición",
-"Obtenido error %d durante COMMIT",
-"Obtenido error %d durante ROLLBACK",
-"Obtenido error %d durante FLUSH_LOGS",
-"Obtenido error %d durante CHECKPOINT",
-"Abortada conexión %ld para db: '%-.64s' usuario: '%-.32s' servidor: `%-.64s' (%-.64s)",
-"El manipulador de tabla no soporta dump para tabla binaria",
-"Binlog cerrado mientras tentaba el FLUSH MASTER",
-"Falla reconstruyendo el indice de la tabla dumped '%-.64s'",
-"Error del master: '%-.64s'",
-"Error de red leyendo del master",
-"Error de red escribiendo para el master",
-"No puedo encontrar índice FULLTEXT correspondiendo a la lista de columnas",
-"No puedo ejecutar el comando dado porque tienes tablas bloqueadas o una transición activa",
-"Desconocida variable de sistema '%-.64s'",
-"Tabla '%-.64s' está marcada como crashed y debe ser reparada",
-"Tabla '%-.64s' está marcada como crashed y la última reparación (automactica?) falló",
-"Aviso: Algunas tablas no transancionales no pueden tener rolled back",
-"Multipla transición necesita mas que 'max_binlog_cache_size' bytes de almacenamiento. Aumente esta variable mysqld y tente de nuevo",
-"Esta operación no puede ser hecha con el esclavo funcionando, primero use STOP SLAVE",
-"Esta operación necesita el esclavo funcionando, configure esclavo y haga el START SLAVE",
-"El servidor no está configurado como esclavo, edite el archivo config file o con CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"No puedo crear el thread esclavo, verifique recursos del sistema",
-"Usario %-.64s ya tiene mas que 'max_user_connections' conexiones activas",
-"Tu solo debes usar expresiones constantes con SET",
-"Tiempo de bloqueo de espera excedido",
-"El número total de bloqueos excede el tamaño de bloqueo de la tabla",
-"Bloqueos de actualización no pueden ser adqueridos durante una transición READ UNCOMMITTED",
-"DROP DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global",
-"CREATE DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global",
-"Argumentos errados para %s",
-"'%-.32s`@`%-.64s` no es permitido para crear nuevos usuarios",
-"Incorrecta definición de la tabla; Todas las tablas MERGE deben estar en el mismo banco de datos",
-"Encontrado deadlock cuando tentando obtener el bloqueo; Tente recomenzar la transición",
-"El tipo de tabla usada no soporta índices FULLTEXT",
-"No puede adicionar clave extranjera constraint",
-"No puede adicionar una línea hijo: falla de clave extranjera constraint",
-"No puede deletar una línea padre: falla de clave extranjera constraint",
-"Error de coneccion a master: %-.128s",
-"Error executando el query en master: %-.128s",
-"Error de %s: %-.128s",
-"Equivocado uso de %s y %s",
-"El comando SELECT usado tiene diferente número de columnas",
-"No puedo ejecutar el query porque usted tiene conflicto de traba de lectura",
-"Mezla de transancional y no-transancional tablas está deshabilitada",
-"Opción '%s' usada dos veces en el comando",
-"Usuario '%-.64s' ha excedido el recurso '%s' (actual valor: %ld)",
-"Acceso negado. Usted necesita el privilegio %-.128s para esta operación",
-"Variable '%-.64s' es una SESSION variable y no puede ser usada con SET GLOBAL",
-"Variable '%-.64s' es una GLOBAL variable y no puede ser configurada con SET GLOBAL",
-"Variable '%-.64s' no tiene un valor patrón",
-"Variable '%-.64s' no puede ser configurada para el valor de '%-.64s'",
-"Tipo de argumento equivocado para variable '%-.64s'",
-"Variable '%-.64s' solamente puede ser configurada, no leída",
-"Equivocado uso/colocación de '%s'",
-"Esta versión de MySQL no soporta todavia '%s'",
-"Recibió fatal error %d: '%-.128s' del master cuando leyendo datos del binary log",
-"Slave SQL thread ignorado el query debido a las reglas de replicación-*-tabla",
-"Variable '%-.64s' es una %s variable",
-"Equivocada definición de llave extranjera para '%-.64s': %s",
-"Referencia de llave y referencia de tabla no coinciden",
-"Operando debe tener %d columna(s)",
-"Subconsulta retorna mas que 1 línea",
-"Desconocido preparado comando handler (%.*s) dado para %s",
-"Base de datos Help está corrupto o no existe",
-"Cíclica referencia en subconsultas",
-"Convirtiendo columna '%s' de %s para %s",
-"Referencia '%-.64s' no soportada (%s)",
-"Cada tabla derivada debe tener su propio alias",
-"Select %u fué reducido durante optimización",
-"Tabla '%-.64s' de uno de los SELECT no puede ser usada en %-.32s",
-"Cliente no soporta protocolo de autenticación solicitado por el servidor; considere actualizar el cliente MySQL",
-"Todas las partes de una SPATIAL index deben ser NOT NULL",
-"COLLATION '%s' no es válido para CHARACTER SET '%s'",
-"Slave ya está funcionando",
-"Slave ya fué parado",
-"Tamaño demasiado grande para datos descomprimidos. El máximo tamaño es %d. (probablemente, extensión de datos descomprimidos fué corrompida)",
-"ZLIB: No suficiente memoria",
-"ZLIB: No suficiente espacio en el búfer de salida (probablemente, extensión de datos descomprimidos fué corrompida)",
-"ZLIB: Dato de entrada fué corrompido",
-"%d línea(s) fueron cortadas por GROUP_CONCAT()",
-"Línea %ld no contiene datos para todas las columnas",
-"Línea %ld fué truncada; La misma contine mas datos que las que existen en las columnas de entrada",
-"Datos truncado, NULL suministrado para NOT NULL columna '%s' en la línea %ld",
-"Datos truncados, fuera de gama para columna '%s' en la línea %ld",
-"Datos truncados para columna '%s' en la línea %ld",
-"Usando motor de almacenamiento %s para tabla '%s'",
-"Ilegal mezcla de collations (%s,%s) y (%s,%s) para operación '%s'",
-"No puede remover uno o mas de los usuarios solicitados",
-"No puede revocar todos los privilegios, derecho para uno o mas de los usuarios solicitados",
-"Ilegal mezcla de collations (%s,%s), (%s,%s), (%s,%s) para operación '%s'",
-"Ilegal mezcla de collations para operación '%s'",
-"Variable '%-.64s' no es una variable componente (No puede ser usada como XXXX.variable_name)",
-"Collation desconocida: '%-.64s'",
-"Parametros SSL en CHANGE MASTER son ignorados porque este slave MySQL fue compilado sin soporte SSL; pueden ser usados despues cuando el slave MySQL con SSL sea inicializado",
-"Servidor está rodando en modo --secure-auth, pero '%s'@'%s' tiene clave en el antiguo formato; por favor cambie la clave para el nuevo formato",
-"Campo o referencia '%-.64s%s%-.64s%s%-.64s' de SELECT #%d fue resolvido en SELECT #%d",
-"Parametro equivocado o combinación de parametros para START SLAVE UNTIL",
-"Es recomendado rodar con --skip-slave-start cuando haciendo replicación step-by-step con START SLAVE UNTIL, a menos que usted no esté seguro en caso de inesperada reinicialización del mysqld slave",
-"SQL thread no es inicializado tal que opciones UNTIL son ignoradas",
-"Nombre de índice incorrecto '%-.100s'",
-"Nombre de catalog incorrecto '%-.100s'",
-"Query cache fallada para configurar tamaño %lu, nuevo tamaño de query cache es %lu",
-"Columna '%-.64s' no puede ser parte de FULLTEXT index",
-"Desconocida key cache '%-.100s'",
-"MySQL esta inicializado en modo --skip-name-resolve. Usted necesita reinicializarlo sin esta opción para este derecho funcionar",
-"Desconocido motor de tabla '%s'",
-"'%s' está desaprobado, use '%s' en su lugar",
-"La tabla destino %-.100s del %s no es actualizable",
-"El recurso '%s' fue deshabilitado; usted necesita construir MySQL con '%s' para tener eso funcionando",
-"El servidor MySQL está rodando con la opción %s tal que no puede ejecutar este comando",
-"Columna '%-.100s' tiene valor doblado '%-.64s' en %s"
-"Equivocado truncado %-.32s valor: '%-.128s'"
-"Incorrecta definición de tabla; Solamente debe haber una columna TIMESTAMP con CURRENT_TIMESTAMP en DEFAULT o ON UPDATE cláusula"
-"Inválido ON UPDATE cláusula 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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
deleted file mode 100644
index b552df08bf3..00000000000
--- a/sql/share/swedish/errmsg.txt
+++ /dev/null
@@ -1,322 +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 */
-
-character-set=latin1
-
-"hashchk",
-"isamchk",
-"NO",
-"YES",
-"Kan inte skapa filen '%-.64s' (Felkod: %d)",
-"Kan inte skapa tabellen '%-.64s' (Felkod: %d)",
-"Kan inte skapa databasen '%-.64s' (Felkod: %d)",
-"Databasen '%-.64s' existerar redan",
-"Kan inte radera databasen '%-.64s'; databasen finns inte",
-"Fel vid radering av databasen (Kan inte radera '%-.64s'. Felkod: %d)",
-"Fel vid radering av databasen (Kan inte radera biblioteket '%-.64s'. Felkod: %d)",
-"Kan inte radera filen '%-.64s' (Felkod: %d)",
-"Hittar inte posten i systemregistret",
-"Kan inte läsa filinformationen (stat) från '%-.64s' (Felkod: %d)",
-"Kan inte inte läsa aktivt bibliotek. (Felkod: %d)",
-"Kan inte låsa filen. (Felkod: %d)",
-"Kan inte använda '%-.64s' (Felkod: %d)",
-"Hittar inte filen '%-.64s' (Felkod: %d)",
-"Kan inte läsa från bibliotek '%-.64s' (Felkod: %d)",
-"Kan inte byta till '%-.64s' (Felkod: %d)",
-"Posten har förändrats sedan den lästes i register '%-.64s'",
-"Disken är full (%s). Väntar tills det finns ledigt utrymme...",
-"Kan inte skriva, dubbel söknyckel i register '%-.64s'",
-"Fick fel vid stängning av '%-.64s' (Felkod: %d)",
-"Fick fel vid läsning av '%-.64s' (Felkod %d)",
-"Kan inte byta namn från '%-.64s' till '%-.64s' (Felkod: %d)",
-"Fick fel vid skrivning till '%-.64s' (Felkod %d)",
-"'%-.64s' är låst mot användning",
-"Sorteringen avbruten",
-"Formulär '%-.64s' finns inte i '%-.64s'",
-"Fick felkod %d från databashanteraren",
-"Registrets databas har inte denna facilitet",
-"Hittar inte posten",
-"Felaktig fil: '%-.64s'",
-"Fatalt fel vid hantering av register '%-.64s'; kör en reparation",
-"Gammal nyckelfil '%-.64s'; reparera registret",
-"'%-.64s' är skyddad mot förändring",
-"Oväntat slut på minnet, starta om programmet och försök på nytt (Behövde %d bytes)",
-"Sorteringsbufferten räcker inte till. Kontrollera startparametrarna",
-"Oväntat filslut vid läsning från '%-.64s' (Felkod: %d)",
-"För många anslutningar",
-"Fick slut på minnet. Kontrollera om mysqld eller någon annan process använder allt tillgängligt minne. Om inte, försök använda 'ulimit' eller allokera mera swap",
-"Kan inte hitta 'hostname' för din adress",
-"Fel vid initiering av kommunikationen med klienten",
-"Användare '%-.32s'@'%-.64s' är ej berättigad att använda databasen %-.64s",
-"Användare '%-.32s'@'%-.64s' är ej berättigad att logga in (Använder lösen: %s)",
-"Ingen databas i användning",
-"Okänt commando",
-"Kolumn '%-.64s' får inte vara NULL",
-"Okänd databas: '%-.64s'",
-"Tabellen '%-.64s' finns redan",
-"Okänd tabell '%-.180s'",
-"Kolumn '%-.64s' i %s är inte unik",
-"Servern går nu ned",
-"Okänd kolumn '%-.64s' i %s",
-"'%-.64s' finns inte i GROUP BY",
-"Kan inte använda GROUP BY med '%-.64s'",
-"Kommandot har både sum functions och enkla funktioner",
-"Antalet kolumner motsvarar inte antalet värden",
-"Kolumnnamn '%-.64s' är för långt",
-"Kolumnnamn '%-.64s finns flera gånger",
-"Nyckelnamn '%-.64s' finns flera gånger",
-"Dubbel nyckel '%-.64s' för nyckel %d",
-"Felaktigt kolumntyp för kolumn '%-.64s'",
-"%s nära '%-.64s' på rad %d",
-"Frågan var tom",
-"Icke unikt tabell/alias: '%-.64s'",
-"Ogiltigt DEFAULT värde för '%-.64s'",
-"Flera PRIMARY KEY använda",
-"För många nycklar använda. Man får ha högst %d nycklar",
-"För många nyckeldelar använda. Man får ha högst %d nyckeldelar",
-"För lång nyckel. Högsta tillåtna nyckellängd är %d",
-"Nyckelkolumn '%-.64s' finns inte",
-"En BLOB '%-.64s' kan inte vara nyckel med den använda tabelltypen",
-"För stor kolumnlängd angiven för '%-.64s' (max= %d). Använd en BLOB instället",
-"Det får finnas endast ett AUTO_INCREMENT-fält och detta måste vara en nyckel",
-"%s: klar att ta emot klienter",
-"%s: Normal avslutning\n",
-"%s: Fick signal %d. Avslutar!\n",
-"%s: Avslutning klar\n",
-"%s: Stänger av tråd %ld; användare: '%-.64s'\n",
-"Kan inte skapa IP-socket",
-"Tabellen '%-.64s' har inget index som motsvarar det angivna i CREATE INDEX. Skapa om tabellen",
-"Fältseparatorerna är vad som förväntades. Kontrollera mot manualen",
-"Man kan inte använda fast radlängd med blobs. Använd 'fields terminated by'",
-"Textfilen '%.64s' måste finnas i databasbiblioteket eller vara läsbar för alla",
-"Filen '%-.64s' existerar redan",
-"Rader: %ld Bortagna: %ld Dubletter: %ld Varningar: %ld",
-"Rader: %ld Dubletter: %ld",
-"Felaktig delnyckel. Nyckeldelen är inte en sträng eller den angivna längden är längre än kolumnlängden",
-"Man kan inte radera alla fält med ALTER TABLE. Använd DROP TABLE istället",
-"Kan inte ta bort '%-.64s'. Kontrollera att fältet/nyckel finns",
-"Rader: %ld Dubletter: %ld Varningar: %ld",
-"INSERT-table '%-.64s' får inte finnas i FROM tabell-listan",
-"Finns ingen tråd med id %lu",
-"Du är inte ägare till tråd %lu",
-"Inga tabeller angivna",
-"För många alternativ till kolumn %s för SET",
-"Kan inte generera ett unikt filnamn %s.(1-999)\n",
-"Tabell '%-.64s' kan inte uppdateras emedan den är låst för läsning",
-"Tabell '%-.64s' är inte låst med LOCK TABLES",
-"BLOB fält '%-.64s' kan inte ha ett DEFAULT-värde",
-"Felaktigt databasnamn '%-.64s'",
-"Felaktigt tabellnamn '%-.64s'",
-"Den angivna frågan skulle läsa mer än MAX_JOIN_SIZE rader. Kontrollera din WHERE och använd SET SQL_BIG_SELECTS=1 eller SET MAX_JOIN_SIZE=# ifall du vill hantera stora joins",
-"Oidentifierat fel",
-"Okänd procedur: %s",
-"Felaktigt antal parametrar till procedur %s",
-"Felaktiga parametrar till procedur %s",
-"Okänd tabell '%-.64s' i '%-.64s'",
-"Fält '%-.64s' är redan använt",
-"Felaktig användning av SQL grupp function",
-"Tabell '%-.64s' har en extension som inte finns i denna version av MySQL",
-"Tabeller måste ha minst 1 kolumn",
-"Tabellen '%-.64s' är full",
-"Okänd teckenuppsättning: '%-.64s'",
-"För många tabeller. MySQL can ha högst %d tabeller i en och samma join",
-"För många fält",
-"För stor total radlängd. Den högst tillåtna radlängden, förutom BLOBs, är %d. Ändra några av dina fält till BLOB",
-"Trådstacken tog slut: Har använt %ld av %ld bytes. Använd 'mysqld -O thread_stack=#' ifall du behöver en större stack",
-"Felaktigt referens i OUTER JOIN. Kontrollera ON-uttrycket",
-"Kolumn '%-.32s' är använd med UNIQUE eller INDEX men är inte definerad med NOT NULL",
-"Kan inte ladda funktionen '%-.64s'",
-"Kan inte initialisera funktionen '%-.64s'; '%-.80s'",
-"Man får inte ange sökväg för dynamiska bibliotek",
-"Funktionen '%-.64s' finns redan",
-"Kan inte öppna det dynamiska biblioteket '%-.64s' (Felkod: %d %s)",
-"Hittar inte funktionen '%-.64s' in det dynamiska biblioteket",
-"Funktionen '%-.64s' är inte definierad",
-"Denna dator, '%-.64s', är blockerad pga många felaktig paket. Gör 'mysqladmin flush-hosts' för att ta bort alla blockeringarna",
-"Denna dator, '%-.64s', har inte privileger att använda denna MySQL server",
-"Du använder MySQL som en anonym användare och som sådan får du inte ändra ditt lösenord",
-"För att ändra lösenord för andra måste du ha rättigheter att uppdatera mysql-databasen",
-"Hittade inte användaren i 'user'-tabellen",
-"Rader: %ld Uppdaterade: %ld Varningar: %ld",
-"Kan inte skapa en ny tråd (errno %d)",
-"Antalet kolumner motsvarar inte antalet värden på rad: %ld",
-"Kunde inte stänga och öppna tabell '%-.64s",
-"Felaktig använding av NULL",
-"Fick fel '%-.64s' från REGEXP",
-"Man får ha både GROUP-kolumner (MIN(),MAX(),COUNT()...) och fält i en fråga om man inte har en GROUP BY-del",
-"Det finns inget privilegium definierat för användare '%-.32s' på '%-.64s'",
-"%-.16s ej tillåtet för '%-.32s'@'%-.64s' för tabell '%-.64s'",
-"%-.16s ej tillåtet för '%-.32s'@'%-.64s' för kolumn '%-.64s' i tabell '%-.64s'",
-"Felaktigt GRANT-privilegium använt",
-"Felaktigt maskinnamn eller användarnamn använt med GRANT",
-"Det finns ingen tabell som heter '%-.64s.%s'",
-"Det finns inget privilegium definierat för användare '%-.32s' på '%-.64s' för tabell '%-.64s'",
-"Du kan inte använda detta kommando med denna MySQL version",
-"Du har något fel i din syntax",
-"DELAYED INSERT-tråden kunde inte låsa tabell '%-.64s'",
-"Det finns redan 'max_delayed_threads' trådar i använding",
-"Avbröt länken för tråd %ld till db '%-.64s', användare '%-.64s' (%s)",
-"Kommunkationspaketet är större än 'max_allowed_packet'",
-"Fick läsfel från klienten vid läsning från 'PIPE'",
-"Fick fatalt fel från 'fcntl()'",
-"Kommunikationspaketen kom i fel ordning",
-"Kunde inte packa up kommunikationspaketet",
-"Fick ett fel vid läsning från klienten",
-"Fick 'timeout' vid läsning från klienten",
-"Fick ett fel vid skrivning till klienten",
-"Fick 'timeout' vid skrivning till klienten",
-"Resultatsträngen är längre än 'max_allowed_packet'",
-"Den använda tabelltypen kan inte hantera BLOB/TEXT-kolumner",
-"Den använda tabelltypen kan inte hantera AUTO_INCREMENT-kolumner",
-"INSERT DELAYED kan inte användas med tabell '%-.64s', emedan den är låst med LOCK TABLES",
-"Felaktigt kolumnnamn '%-.100s'",
-"Den använda tabelltypen kan inte indexera kolumn '%-.64s'",
-"Tabellerna i MERGE-tabellen är inte identiskt definierade",
-"Kan inte skriva till tabell '%-.64s'; UNIQUE-test",
-"Du har inte angett någon nyckellängd för BLOB '%-.64s'",
-"Alla delar av en PRIMARY KEY måste vara NOT NULL; Om du vill ha en nyckel med NULL, använd UNIQUE istället",
-"Resultet bestod av mera än en rad",
-"Denna tabelltyp kräver en PRIMARY KEY",
-"Denna version av MySQL är inte kompilerad med RAID",
-"Du använder 'säker uppdateringsmod' och försökte uppdatera en tabell utan en WHERE-sats som använder sig av en nyckel",
-"Nyckel '%-.64s' finns inte in tabell '%-.64s'",
-"Kan inte öppna tabellen",
-"Tabellhanteraren för denna tabell kan inte göra %s",
-"Du får inte utföra detta kommando i en transaktion",
-"Fick fel %d vid COMMIT",
-"Fick fel %d vid ROLLBACK",
-"Fick fel %d vid FLUSH_LOGS",
-"Fick fel %d vid CHECKPOINT",
-"Avbröt länken för tråd %ld till db '%-.64s', användare '%-.32s', host '%-.64s' (%-.64s)",
-"Tabellhanteraren klarar inte en binär kopiering av tabellen",
-"Binärloggen stängdes medan FLUSH MASTER utfördes",
-"Failed rebuilding the index of dumped table '%-.64s'",
-"Fick en master: '%-.64s'",
-"Fick nätverksfel vid läsning från master",
-"Fick nätverksfel vid skrivning till master",
-"Hittar inte ett FULLTEXT-index i kolumnlistan",
-"Kan inte utföra kommandot emedan du har en låst tabell eller an aktiv transaktion",
-"Okänd systemvariabel: '%-.64s'",
-"Tabell '%-.64s' är trasig och bör repareras med REPAIR TABLE",
-"Tabell '%-.64s' är trasig och senast (automatiska?) reparation misslyckades",
-"Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK",
-"Transaktionen krävde mera än 'max_binlog_cache_size' minne. Öka denna mysqld-variabel och försök på nytt",
-"Denna operation kan inte göras under replikering; Gör STOP SLAVE först",
-"Denna operation kan endast göras under replikering; Konfigurera slaven och gör START SLAVE",
-"Servern är inte konfigurerade som en replikationsslav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO",
-"Kunde inte initialisera replikationsstrukturerna. See MySQL fel fil för mera information",
-"Kunde inte starta en tråd för replikering",
-"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar",
-"Man kan endast använda konstantuttryck med SET",
-"Fick inte ett lås i tid ; Försök att starta om transaktionen",
-"Antal lås överskrider antalet reserverade lås",
-"Updateringslås kan inte göras när man använder READ UNCOMMITTED",
-"DROP DATABASE är inte tillåtet när man har ett globalt läslås",
-"CREATE DATABASE är inte tillåtet när man har ett globalt läslås",
-"Felaktiga argument till %s",
-"'%-.32s'@'%-.64s' har inte rättighet att skapa nya användare",
-"Felaktig tabelldefinition; alla tabeller i en MERGE-tabell måste vara i samma databas",
-"Fick 'DEADLOCK' vid låsförsök av block/rad. Försök att starta om transaktionen",
-"Tabelltypen har inte hantering av FULLTEXT-index",
-"Kan inte lägga till 'FOREIGN KEY constraint'",
-"FOREIGN KEY-konflikt: Kan inte skriva barn",
-"FOREIGN KEY-konflikt: Kan inte radera fader",
-"Fick fel vid anslutning till master: %-.128s",
-"Fick fel vid utförande av command på mastern: %-.128s",
-"Fick fel vid utförande av %s: %-.128s",
-"Felaktig använding av %s and %s",
-"SELECT-kommandona har olika antal kolumner",
-"Kan inte utföra kommandot emedan du har ett READ-lås",
-"Blandning av transaktionella och icke-transaktionella tabeller är inaktiverat",
-"Option '%s' användes två gånger",
-"Användare '%-.64s' har överskridit '%s' (nuvarande värde: %ld)",
-"Du har inte privlegiet '%-.128s' som behövs för denna operation",
-"Variabel '%-.64s' är en SESSION variabel och kan inte ändrad med SET GLOBAL",
-"Variabel '%-.64s' är en GLOBAL variabel och bör sättas med SET GLOBAL",
-"Variabel '%-.64s' har inte ett DEFAULT-värde",
-"Variabel '%-.64s' kan inte sättas till '%-.64s'",
-"Fel typ av argument till variabel '%-.64s'",
-"Variabeln '%-.64s' kan endast sättas, inte läsas",
-"Fel använding/placering av '%s'",
-"Denna version av MySQL kan ännu inte utföra '%s'",
-"Fick fatalt fel %d: '%-.128s' från master vid läsning av binärloggen",
-"Slav SQL tråden ignorerade frågan pga en replicate-*-table regel",
-"Variabel '%-.64s' är av typ %s",
-"Felaktig FOREIGN KEY-definition för '%-.64s': %s",
-"Nyckelreferensen och tabellreferensen stämmer inte överens",
-"Operand should contain %d column(s)",
-"Subquery returnerade mer än 1 rad",
-"Okänd PREPARED STATEMENT id (%.*s) var given till %s",
-"Hjälpdatabasen finns inte eller är skadad",
-"Cyklisk referens i subqueries",
-"Konvertar kolumn '%s' från %s till %s",
-"Referens '%-.64s' stöds inte (%s)",
-"Varje 'derived table' måste ha sitt eget alias",
-"Select %u reducerades vid optimiering",
-"Tabell '%-.64s' från en SELECT kan inte användas i %-.32s",
-"Klienten stöder inte autentiseringsprotokollet som begärts av servern; överväg uppgradering av klientprogrammet.",
-"Alla delar av en SPATIAL index måste vara NOT NULL",
-"COLLATION '%s' är inte tillåtet för CHARACTER SET '%s'",
-"Slaven har redan startat",
-"Slaven har redan stoppat",
-"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 rad(er) kapades av 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 for column '%s' at row %ld",
-"Använder handler %s för tabell '%s'",
-"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"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",
-"Felaktigt index namn '%-.100s'",
-"Felaktigt katalog namn '%-.100s'",
-"Storleken av "Query cache" kunde inte sättas till %lu, ny storlek är %lu",
-"Kolumn '%-.64s' kan inte vara del av ett FULLTEXT index",
-"Okänd nyckel cache '%-.100s'",
-"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"Tabel %-.100s använd med '%s' är inte uppdateringsbar",
-"'%s' är inte aktiverad; För att aktivera detta måste du bygga om MySQL med '%s' definerad",
-"MySQL är startad med --skip-grant-tables. Pga av detta kan du inte använda detta kommando",
-"Column '%-.100s' has duplicated value '%-.64s' in %s"
-"Truncated wrong %-.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",
-"Fick felkod %d '%-.100s' från %s",
-"Fick tilfällig felkod %d '%-.100s' från %s",
-"Unknown or incorrect time zone: '%-.64s'",
-"Invalid TIMESTAMP value in column '%s' at row %ld",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
deleted file mode 100644
index 9914846b1f8..00000000000
--- a/sql/share/ukrainian/errmsg.txt
+++ /dev/null
@@ -1,328 +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 */
-
-/*
- * Ukrainian translation by Roman Festchook <roma@orta.zt.ua>
- * Encoding: KOI8-U
- * Version: 13/09/2001 mysql-3.23.41
- */
-
-character-set=koi8u
-
-"hashchk",
-"isamchk",
-"î¶",
-"ôáë",
-"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÆÁÊÌ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÔÁÂÌÉÃÀ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s'. âÁÚÁ ÄÁÎÎÉÈ ¦ÓÎÕ¤",
-"îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.64s'. âÁÚÁ ÄÁÎÎÉÈ ÎÅ ¦ÓÎÕ¤",
-"îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ (îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ '%-.64s', ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ (îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÔÅËÕ '%-.64s', ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ÚÁÐÉÓ Ú ÓÉÓÔÅÍÎϧ ÔÁÂÌÉæ",
-"îÅ ÍÏÖÕ ÏÔÒÉÍÁÔÉ ÓÔÁÔÕÓ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ×ÉÚÎÁÞÉÔÉ ÒÏÂÏÞÕ ÔÅËÕ (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÚÁÂÌÏËÕ×ÁÔÉ ÆÁÊÌ (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÆÁÊÌ: '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÁÊÌ: '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ Õ ÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"úÁÐÉÓ ÂÕÌÏ ÚͦÎÅÎÏ Ú ÞÁÓÕ ÏÓÔÁÎÎØÏÇÏ ÞÉÔÁÎÎÑ Ú ÔÁÂÌÉæ '%-.64s'",
-"äÉÓË ÚÁÐÏ×ÎÅÎÉÊ (%s). ÷ÉÞÉËÕÀ, ÄÏËÉ ÚצÌØÎÉÔØÓÑ ÔÒÏÈÉ Í¦ÓÃÑ...",
-"îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ, ÄÕÂÌÀÀÞÉÊÓÑ ËÌÀÞ × ÔÁÂÌÉæ '%-.64s'",
-"îÅ ÍÏÖÕ ÚÁËÒÉÔÉ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÐÅÒÅÊÍÅÎÕ×ÁÔÉ '%-.64s' Õ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ ÆÁÊÌ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"'%-.64s' ÚÁÂÌÏËÏ×ÁÎÉÊ ÎÁ ×ÎÅÓÅÎÎÑ ÚͦÎ",
-"óÏÒÔÕ×ÁÎÎÑ ÐÅÒÅÒ×ÁÎÏ",
-"÷ÉÇÌÑÄ '%-.64s' ÎÅ ¦ÓÎÕ¤ ÄÌÑ '%-.64s'",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d ×¦Ä ÄÅÓËÒÉÐÔÏÒÁ ÔÁÂÌÉæ",
-"äÅÓËÒÉÐÔÏÒ ÔÁÂÌÉæ '%-.64s' ÎÅ ÍÁ¤ 椧 ×ÌÁÓÔÉ×ÏÓÔ¦",
-"îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ Õ '%-.64s'",
-"èÉÂÎÁ ¦ÎÆÏÒÍÁÃ¦Ñ Õ ÆÁÊ̦: '%-.64s'",
-"èÉÂÎÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ: '%-.64s'; óÐÒÏÂÕÊÔÅ ÊÏÇÏ ×¦ÄÎÏ×ÉÔÉ",
-"óÔÁÒÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ '%-.64s'; ÷¦ÄÎÏצÔØ ÊÏÇÏ!",
-"ôÁÂÌÉÃÑ '%-.64s' Ô¦ÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ",
-"âÒÁË ÐÁÍ'ÑÔ¦. òÅÓÔÁÒÔÕÊÔÅ ÓÅÒ×ÅÒ ÔÁ ÓÐÒÏÂÕÊÔÅ ÚÎÏ×Õ (ÐÏÔÒ¦ÂÎÏ %d ÂÁÊÔ¦×)",
-"âÒÁË ÐÁÍ'ÑÔ¦ ÄÌÑ ÓÏÒÔÕ×ÁÎÎÑ. ôÒÅÂÁ Ú¦ÌØÛÉÔÉ ÒÏÚÍ¦Ò ÂÕÆÅÒÁ ÓÏÒÔÕ×ÁÎÎÑ Õ ÓÅÒ×ÅÒÁ",
-"èÉÂÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ '%-.64s' (ÐÏÍÉÌËÁ: %d)",
-"úÁÂÁÇÁÔÏ Ú'¤ÄÎÁÎØ",
-"âÒÁË ÐÁÍ'ÑÔ¦; ðÅÒÅצÒÔÅ ÞÉ mysqld ÁÂÏ Ñ˦ÓØ ¦ÎÛ¦ ÐÒÏÃÅÓÉ ×ÉËÏÒÉÓÔÏ×ÕÀÔØ ÕÓÀ ÄÏÓÔÕÐÎÕ ÐÁÍ'ÑÔØ. ñË Î¦, ÔÏ ×É ÍÏÖÅÔÅ ÓËÏÒÉÓÔÁÔÉÓÑ 'ulimit', ÁÂÉ ÄÏÚ×ÏÌÉÔÉ mysqld ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ Â¦ÌØÛÅ ÐÁÍ'ÑÔ¦ ÁÂÏ ×É ÍÏÖÅÔÅ ÄÏÄÁÔÉ Â¦ÌØÛŠͦÓÃÑ Ð¦Ä Ó×ÁÐ",
-"îÅ ÍÏÖÕ ×ÉÚÎÁÞÉÔÉ ¦Í'Ñ ÈÏÓÔÕ ÄÌÑ ×ÁÛϧ ÁÄÒÅÓÉ",
-"îÅצÒÎÁ ÕÓÔÁÎÏ×ËÁ Ú×'ÑÚËÕ",
-"äÏÓÔÕÐ ÚÁÂÏÒÏÎÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ: '%-.32s'@'%-.64s' ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ '%-.64s'",
-"äÏÓÔÕÐ ÚÁÂÏÒÏÎÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ: '%-.32s'@'%-.64s' (÷ÉËÏÒÉÓÔÁÎÏ ÐÁÒÏÌØ: %s)",
-"âÁÚÕ ÄÁÎÎÉÈ ÎÅ ×ÉÂÒÁÎÏ",
-"îÅצÄÏÍÁ ËÏÍÁÎÄÁ",
-"óÔÏ×ÂÅÃØ '%-.64s' ÎÅ ÍÏÖÅ ÂÕÔÉ ÎÕÌØÏ×ÉÍ",
-"îÅצÄÏÍÁ ÂÁÚÁ ÄÁÎÎÉÈ '%-.64s'",
-"ôÁÂÌÉÃÑ '%-.64s' ×ÖÅ ¦ÓÎÕ¤",
-"îÅצÄÏÍÁ ÔÁÂÌÉÃÑ '%-.180s'",
-"óÔÏ×ÂÅÃØ '%-.64s' Õ %-.64s ×ÉÚÎÁÞÅÎÉÊ ÎÅÏÄÎÏÚÎÁÞÎÏ",
-"úÁ×ÅÒÛÕ¤ÔØÓÑ ÒÁÂÏÔÁ ÓÅÒ×ÅÒÁ",
-"îÅצÄÏÍÉÊ ÓÔÏ×ÂÅÃØ '%-.64s' Õ '%-.64s'",
-"'%-.64s' ÎÅ ¤ Õ GROUP BY",
-"îÅ ÍÏÖÕ ÇÒÕÐÕ×ÁÔÉ ÐÏ '%-.64s'",
-"õ ×ÉÒÁÚ¦ ×ÉËÏÒÉÓÔÁÎÏ Ð¦ÄÓÕÍÏ×ÕÀÞ¦ ÆÕÎËæ§ ÐÏÒÑÄ Ú ¦ÍÅÎÁÍÉ ÓÔÏ×Âæ×",
-"ë¦ÌØ˦ÓÔØ ÓÔÏ×ÂÃ¦× ÎÅ ÓЦ×ÐÁÄÁ¤ Ú Ë¦ÌØ˦ÓÔÀ ÚÎÁÞÅÎØ",
-"¶Í'Ñ ¦ÄÅÎÔÉƦËÁÔÏÒÁ '%-.100s' ÚÁÄÏ×ÇÅ",
-"äÕÂÌÀÀÞÅ ¦Í'Ñ ÓÔÏ×ÂÃÑ '%-.64s'",
-"äÕÂÌÀÀÞÅ ¦Í'Ñ ËÌÀÞÁ '%-.64s'",
-"äÕÂÌÀÀÞÉÊ ÚÁÐÉÓ '%-.64s' ÄÌÑ ËÌÀÞÁ %d",
-"îÅצÒÎÉÊ ÓÐÅÃÉƦËÁÔÏÒ ÓÔÏ×ÂÃÑ '%-.64s'",
-"%s ¦ÌÑ '%-.80s' × ÓÔÒÏæ %d",
-"ðÕÓÔÉÊ ÚÁÐÉÔ",
-"îÅÕΦËÁÌØÎÁ ÔÁÂÌÉÃÑ/ÐÓÅ×ÄÏΦÍ: '%-.64s'",
-"îÅצÒÎÅ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ ÄÌÑ '%-.64s'",
-"ðÅÒ×ÉÎÎÏÇÏ ËÌÀÞÁ ×ÉÚÎÁÞÅÎÏ ÎÅÏÄÎÏÒÁÚÏ×Ï",
-"úÁÂÁÇÁÔÏ ËÌÀÞ¦× ÚÁÚÎÁÞÅÎÏ. äÏÚ×ÏÌÅÎÏ ÎŠ¦ÌØÛÅ %d ËÌÀÞ¦×",
-"úÁÂÁÇÁÔÏ ÞÁÓÔÉÎ ËÌÀÞÁ ÚÁÚÎÁÞÅÎÏ. äÏÚ×ÏÌÅÎÏ ÎŠ¦ÌØÛÅ %d ÞÁÓÔÉÎ",
-"úÁÚÎÁÞÅÎÉÊ ËÌÀÞ ÚÁÄÏ×ÇÉÊ. îÁʦÌØÛÁ ÄÏ×ÖÉÎÁ ËÌÀÞÁ %d ÂÁÊÔ¦×",
-"ëÌÀÞÏ×ÉÊ ÓÔÏ×ÂÅÃØ '%-.64s' ÎÅ ¦ÓÎÕ¤ Õ ÔÁÂÌÉæ",
-"BLOB ÓÔÏ×ÂÅÃØ '%-.64s' ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÉÊ Õ ×ÉÚÎÁÞÅÎΦ ËÌÀÞÁ × ÃØÏÍÕ ÔÉЦ ÔÁÂÌÉæ",
-"úÁÄÏ×ÇÁ ÄÏ×ÖÉÎÁ ÓÔÏ×ÂÃÑ '%-.64s' (max = %d). ÷ÉËÏÒÉÓÔÁÊÔÅ ÔÉÐ BLOB",
-"îÅצÒÎÅ ×ÉÚÎÁÞÅÎÎÑ ÔÁÂÌÉæ; íÏÖÅ ÂÕÔÉ ÌÉÛÅ ÏÄÉÎ Á×ÔÏÍÁÔÉÞÎÉÊ ÓÔÏ×ÂÅÃØ, ÝÏ ÐÏ×ÉÎÅÎ ÂÕÔÉ ×ÉÚÎÁÞÅÎÉÊ ÑË ËÌÀÞ",
-"%s: çÏÔÏ×ÉÊ ÄÌÑ Ú'¤ÄÎÁÎØ!",
-"%s: îÏÒÍÁÌØÎÅ ÚÁ×ÅÒÛÅÎÎÑ\n",
-"%s: ïÔÒÉÍÁÎÏ ÓÉÇÎÁÌ %d. ðÅÒÅÒÉ×ÁÀÓØ!\n",
-"%s: òÏÂÏÔÕ ÚÁ×ÅÒÛÅÎÏ\n",
-"%s: ðÒÉÓËÏÒÀÀ ÚÁËÒÉÔÔÑ Ç¦ÌËÉ %ld ËÏÒÉÓÔÕ×ÁÞÁ: '%-.32s'\n",
-"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ IP ÒÏÚ'¤Í",
-"ôÁÂÌÉÃÑ '%-.64s' ÍÁ¤ ¦ÎÄÅËÓ, ÝÏ ÎÅ ÓЦ×ÐÁÄÁ¤ Ú ×ËÁÚÁÎÎÉÍ Õ CREATE INDEX. óÔ×ÏÒ¦ÔØ ÔÁÂÌÉÃÀ ÚÎÏ×Õ",
-"èÉÂÎÉÊ ÒÏÚĦÌÀ×ÁÞ ÐÏ̦×. ðÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ",
-"îÅ ÍÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÓÔÁÌÕ ÄÏ×ÖÉÎÕ ÓÔÒÏËÉ Ú BLOB. úËÏÒÉÓÔÁÊÔÅÓÑ 'fields terminated by'",
-"æÁÊÌ '%-.64s' ÐÏ×ÉÎÅÎ ÂÕÔÉ Õ ÔÅæ ÂÁÚÉ ÄÁÎÎÉÈ ÁÂÏ ÍÁÔÉ ×ÓÔÁÎÏ×ÌÅÎÅ ÐÒÁ×Ï ÎÁ ÞÉÔÁÎÎÑ ÄÌÑ ÕÓ¦È",
-"æÁÊÌ '%-.80s' ×ÖÅ ¦ÓÎÕ¤",
-"úÁÐÉÓ¦×: %ld ÷ÉÄÁÌÅÎÏ: %ld ðÒÏÐÕÝÅÎÏ: %ld úÁÓÔÅÒÅÖÅÎØ: %ld",
-"úÁÐÉÓ¦×: %ld äÕÂ̦ËÁÔ¦×: %ld",
-"îÅצÒÎÁ ÞÁÓÔÉÎÁ ËÌÀÞÁ. ÷ÉËÏÒÉÓÔÁÎÁ ÞÁÓÔÉÎÁ ËÌÀÞÁ ÎÅ ¤ ÓÔÒÏËÏÀ, ÚÁÄÏ×ÇÁ ÁÂÏ ×ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ ÕΦËÁÌØÎÉÈ ÞÁÓÔÉÎ ËÌÀÞÅÊ",
-"îÅ ÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ×Ó¦ ÓÔÏ×Âæ ÚÁ ÄÏÐÏÍÏÇÏÀ ALTER TABLE. äÌÑ ÃØÏÇÏ ÓËÏÒÉÓÔÁÊÔÅÓÑ DROP TABLE",
-"îÅ ÍÏÖÕ DROP '%-.64s'. ðÅÒÅצÒÔÅ, ÞÉ ÃÅÊ ÓÔÏ×ÂÅÃØ/ËÌÀÞ ¦ÓÎÕ¤",
-"úÁÐÉÓ¦×: %ld äÕÂ̦ËÁÔ¦×: %ld úÁÓÔÅÒÅÖÅÎØ: %ld",
-"ôÁÂÌÉÃÑ '%-.64s' ÝÏ ÚͦÎÀ¤ÔØÓÑ ÎÅ ÄÏÚ×ÏÌÅÎÁ Õ ÐÅÒÅ̦ËÕ ÔÁÂÌÉÃØ FROM",
-"îÅצÄÏÍÉÊ ¦ÄÅÎÔÉƦËÁÔÏÒ Ç¦ÌËÉ: %lu",
-"÷É ÎÅ ×ÏÌÏÄÁÒ Ç¦ÌËÉ %lu",
-"îÅ ×ÉËÏÒÉÓÔÁÎÏ ÔÁÂÌÉÃØ",
-"úÁÂÁÇÁÔÏ ÓÔÒÏË ÄÌÑ ÓÔÏ×ÂÃÑ %-.64s ÔÁ SET",
-"îÅ ÍÏÖÕ ÚÇÅÎÅÒÕ×ÁÔÉ ÕΦËÁÌØÎÅ ¦Í'Ñ log-ÆÁÊÌÕ %-.64s.(1-999)\n",
-"ôÁÂÌÉÃÀ '%-.64s' ÚÁÂÌÏËÏ×ÁÎÏ Ô¦ÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ, ÔÏÍÕ §§ ÎÅ ÍÏÖÎÁ ÏÎÏ×ÉÔÉ",
-"ôÁÂÌÉÃÀ '%-.64s' ÎÅ ÂÕÌÏ ÂÌÏËÏ×ÁÎÏ Ú LOCK TABLES",
-"óÔÏ×ÂÅÃØ BLOB '%-.64s' ÎÅ ÍÏÖÅ ÍÁÔÉ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ",
-"îÅצÒÎÅ ¦Í'Ñ ÂÁÚÉ ÄÁÎÎÉÈ '%-.100s'",
-"îÅצÒÎÅ ¦Í'Ñ ÔÁÂÌÉæ '%-.100s'",
-"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ",
-"îÅצÄÏÍÁ ÐÏÍÉÌËÁ",
-"îÅצÄÏÍÁ ÐÒÏÃÅÄÕÒÁ '%-.64s'",
-"èÉÂÎÁ ˦ÌØ˦ÓÔØ ÐÁÒÁÍÅÔÒ¦× ÐÒÏÃÅÄÕÒÉ '%-.64s'",
-"èÉÂÎÉÊ ÐÁÒÁÍÅÔÅÒ ÐÒÏÃÅÄÕÒÉ '%-.64s'",
-"îÅצÄÏÍÁ ÔÁÂÌÉÃÑ '%-.64s' Õ %-.32s",
-"óÔÏ×ÂÅÃØ '%-.64s' ÚÁÚÎÁÞÅÎÏ Äצަ",
-"èÉÂÎÅ ×ÉËÏÒÉÓÔÁÎÎÑ ÆÕÎËæ§ ÇÒÕÐÕ×ÁÎÎÑ",
-"ôÁÂÌÉÃÑ '%-.64s' ×ÉËÏÒÉÓÔÏ×Õ¤ ÒÏÚÛÉÒÅÎÎÑ, ÝÏ ÎÅ ¦ÓÎÕ¤ Õ Ã¦Ê ×ÅÒÓ¦§ MySQL",
-"ôÁÂÌÉÃÑ ÐÏ×ÉÎÎÁ ÍÁÔÉ ÈÏÞÁ ÏÄÉÎ ÓÔÏ×ÂÅÃØ",
-"ôÁÂÌÉÃÑ '%-.64s' ÚÁÐÏ×ÎÅÎÁ",
-"îÅצÄÏÍÁ ËÏÄÏ×Á ÔÁÂÌÉÃÑ: '%-.64s'",
-"úÁÂÁÇÁÔÏ ÔÁÂÌÉÃØ. MySQL ÍÏÖÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÌÉÛÅ %d ÔÁÂÌÉÃØ Õ ÏÂ'¤ÄÎÁÎΦ",
-"úÁÂÁÇÁÔÏ ÓÔÏ×Âæ×",
-"úÁÄÏ×ÇÁ ÓÔÒÏËÁ. îÁʦÌØÛÏÀ ÄÏ×ÖÉÎÏÀ ÓÔÒÏËÉ, ÎÅ ÒÁÈÕÀÞÉ BLOB, ¤ %d. ÷ÁÍ ÐÏÔÒ¦ÂÎÏ ÐÒÉ×ÅÓÔÉ ÄÅÑ˦ ÓÔÏ×Âæ ÄÏ ÔÉÐÕ BLOB",
-"óÔÅË Ç¦ÌÏË ÐÅÒÅÐÏ×ÎÅÎÏ: ÷ÉËÏÒÉÓÔÁÎÏ: %ld Ú %ld. ÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ 'mysqld -O thread_stack=#' ÁÂÉ ÚÁÚÎÁÞÉÔÉ Â¦ÌØÛÉÊ ÓÔÅË, ÑËÝÏ ÎÅÏÂȦÄÎÏ",
-"ðÅÒÅÈÒÅÓÎÁ ÚÁÌÅÖΦÓÔØ Õ OUTER JOIN. ðÅÒÅצÒÔÅ ÕÍÏ×Õ ON",
-"óÔÏ×ÂÅÃØ '%-.64s' ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ Ú UNIQUE ÁÂÏ INDEX, ÁÌÅ ÎÅ ×ÉÚÎÁÞÅÎÉÊ ÑË NOT NULL",
-"îÅ ÍÏÖÕ ÚÁ×ÁÎÔÁÖÉÔÉ ÆÕÎËæÀ '%-.64s'",
-"îÅ ÍÏÖÕ ¦Î¦Ã¦Á̦ÚÕ×ÁÔÉ ÆÕÎËæÀ '%-.64s'; %-.80s",
-"îÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÐÕÔ¦ ÄÌÑ ÒÏÚĦÌÀ×ÁÎÉÈ Â¦Â̦ÏÔÅË",
-"æÕÎËÃ¦Ñ '%-.64s' ×ÖÅ ¦ÓÎÕ¤",
-"îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÒÏÚĦÌÀ×ÁÎÕ Â¦Â̦ÏÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d %-.64s)",
-"îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÕÎËæÀ '%-.64s' Õ Â¦Â̦ÏÔÅæ'",
-"æÕÎËæÀ '%-.64s' ÎÅ ×ÉÚÎÁÞÅÎÏ",
-"èÏÓÔ '%-.64s' ÚÁÂÌÏËÏ×ÁÎÏ Ú ÐÒÉÞÉÎÉ ×ÅÌÉËϧ ˦ÌØËÏÓÔ¦ ÐÏÍÉÌÏË Ú'¤ÄÎÁÎÎÑ. äÌÑ ÒÏÚÂÌÏËÕ×ÁÎÎÑ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ 'mysqladmin flush-hosts'",
-"èÏÓÔÕ '%-.64s' ÎÅ ÄÏ×ÏÌÅÎÏ Ú×'ÑÚÕ×ÁÔÉÓØ Ú ÃÉÍ ÓÅÒ×ÅÒÏÍ MySQL",
-"÷É ×ÉËÏÒÉÓÔÏ×Õ¤ÔÅ MySQL ÑË ÁÎÏΦÍÎÉÊ ËÏÒÉÓÔÕ×ÁÞ, ÔÏÍÕ ×ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ÚͦÎÀ×ÁÔÉ ÐÁÒÏ̦",
-"÷É ÐÏ×ÉΦ ÍÁÔÉ ÐÒÁ×Ï ÎÁ ÏÎÏ×ÌÅÎÎÑ ÔÁÂÌÉÃØ Õ ÂÁÚ¦ ÄÁÎÎÉÈ mysql, ÁÂÉ ÍÁÔÉ ÍÏÖÌÉצÓÔØ ÚͦÎÀ×ÁÔÉ ÐÁÒÏÌØ ¦ÎÛÉÍ",
-"îÅ ÍÏÖÕ ÚÎÁÊÔÉ ×¦ÄÐÏצÄÎÉÈ ÚÁÐÉÓ¦× Õ ÔÁÂÌÉæ ËÏÒÉÓÔÕ×ÁÞÁ",
-"úÁÐÉÓ¦× ×¦ÄÐÏצÄÁ¤: %ld úͦÎÅÎÏ: %ld úÁÓÔÅÒÅÖÅÎØ: %ld",
-"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÎÏ×Õ Ç¦ÌËÕ (ÐÏÍÉÌËÁ %d). ñËÝÏ ×É ÎÅ ×ÉËÏÒÉÓÔÁÌÉ ÕÓÀ ÐÁÍ'ÑÔØ, ÔÏ ÐÒÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ ÄÏ ×ÁÛϧ ïó - ÍÏÖÌÉ×Ï ÃÅ ÐÏÍÉÌËÁ ïó",
-"ë¦ÌØ˦ÓÔØ ÓÔÏ×ÂÃ¦× ÎÅ ÓЦ×ÐÁÄÁ¤ Ú Ë¦ÌØ˦ÓÔÀ ÚÎÁÞÅÎØ Õ ÓÔÒÏæ %ld",
-"îÅ ÍÏÖÕ ÐÅÒÅצÄËÒÉÔÉ ÔÁÂÌÉÃÀ: '%-.64s'",
-"èÉÂÎÅ ×ÉËÏÒÉÓÔÁÎÎÑ ÚÎÁÞÅÎÎÑ NULL",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ '%-.64s' ×¦Ä ÒÅÇÕÌÑÒÎÏÇÏ ×ÉÒÁÚÕ",
-"úͦÛÕ×ÁÎÎÑ GROUP ÓÔÏ×ÂÃ¦× (MIN(),MAX(),COUNT()...) Ú ÎÅ GROUP ÓÔÏ×ÂÃÑÍÉ ¤ ÚÁÂÏÒÏÎÅÎÉÍ, ÑËÝÏ ÎÅ ÍÁ¤ GROUP BY",
-"ðÏ×ÎÏ×ÁÖÅÎØ ÎÅ ×ÉÚÎÁÞÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ '%-.32s' Ú ÈÏÓÔÕ '%-.64s'",
-"%-.16s ËÏÍÁÎÄÁ ÚÁÂÏÒÏÎÅÎÁ ËÏÒÉÓÔÕ×ÁÞÕ: '%-.32s'@'%-.64s' Õ ÔÁÂÌÉæ '%-.64s'",
-"%-.16s ËÏÍÁÎÄÁ ÚÁÂÏÒÏÎÅÎÁ ËÏÒÉÓÔÕ×ÁÞÕ: '%-.32s'@'%-.64s' ÄÌÑ ÓÔÏ×ÂÃÑ '%-.64s' Õ ÔÁÂÌÉæ '%-.64s'",
-"èÉÂÎÁ GRANT/REVOKE ËÏÍÁÎÄÁ; ÐÒÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ ÓÔÏÓÏ×ÎÏ ÔÏÇÏ, Ñ˦ ÐÒÁ×Á ÍÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ",
-"áÒÇÕÍÅÎÔ host ÁÂÏ user ÄÌÑ GRANT ÚÁÄÏ×ÇÉÊ",
-"ôÁÂÌÉÃÑ '%-.64s.%-.64s' ÎÅ ¦ÓÎÕ¤",
-"ðÏ×ÎÏ×ÁÖÅÎØ ÎÅ ×ÉÚÎÁÞÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ '%-.32s' Ú ÈÏÓÔÕ '%-.64s' ÄÌÑ ÔÁÂÌÉæ '%-.64s'",
-"÷ÉËÏÒÉÓÔÏ×Õ×ÁÎÁ ËÏÍÁÎÄÁ ÎÅ ÄÏÚ×ÏÌÅÎÁ Õ Ã¦Ê ×ÅÒÓ¦§ MySQL",
-"õ ×ÁÓ ÐÏÍÉÌËÁ Õ ÓÉÎÔÁËÓÉÓ¦ SQL",
-"ç¦ÌËÁ ÄÌÑ INSERT DELAYED ÎÅ ÍÏÖÅ ÏÔÒÉÍÁÔÉ ÂÌÏËÕ×ÁÎÎÑ ÄÌÑ ÔÁÂÌÉæ %-.64s",
-"úÁÂÁÇÁÔÏ ÚÁÔÒÉÍÁÎÉÈ Ç¦ÌÏË ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ",
-"ðÅÒÅÒ×ÁÎÏ Ú'¤ÄÎÁÎÎÑ %ld ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ: '%-.64s' ËÏÒÉÓÔÕ×ÁÞÁ: '%-.32s' (%-.64s)",
-"ïÔÒÉÍÁÎÏ ÐÁËÅÔ Â¦ÌØÛÉÊ Î¦Ö 'max_allowed_packet'",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÞÉÔÁÎÎÑ Ú ËÏÍÕΦËÁæÊÎÏÇÏ ËÁÎÁÌÕ",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËËÕ ×¦Ä fcntl()",
-"ïÔÒÉÍÁÎÏ ÐÁËÅÔÉ Õ ÎÅÎÁÌÅÖÎÏÍÕ ÐÏÒÑÄËÕ",
-"îÅ ÍÏÖÕ ÄÅËÏÍÐÒÅÓÕ×ÁÔÉ ËÏÍÕΦËÁæÊÎÉÊ ÐÁËÅÔ",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÞÉÔÁÎÎÑ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×",
-"ïÔÒÉÍÁÎÏ ÚÁÔÒÉÍËÕ ÞÉÔÁÎÎÑ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÚÁÐÉÓÕ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×",
-"ïÔÒÉÍÁÎÏ ÚÁÔÒÉÍËÕ ÚÁÐÉÓÕ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×",
-"óÔÒÏËÁ ÒÅÚÕÌØÔÁÔÕ ÄÏ×ÛÁ Î¦Ö 'max_allowed_packet'",
-"÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ BLOB/TEXT ÓÔÏ×Âæ",
-"÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ AUTO_INCREMENT ÓÔÏ×Âæ",
-"INSERT DELAYED ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÏ Ú ÔÁÂÌÉÃÅÀ '%-.64s', ÔÏÍÕ ÝÏ §§ ÚÁÂÌÏËÏ×ÁÎÏ Ú LOCK TABLES",
-"îÅצÒÎÅ ¦Í'Ñ ÓÔÏ×ÂÃÑ '%-.100s'",
-"÷ÉËÏÒÉÓÔÁÎÉÊ ×ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ÎÅ ÍÏÖÅ ¦ÎÄÅËÓÕ×ÁÔÉ ÓÔÏ×ÂÅÃØ '%-.64s'",
-"ôÁÂÌÉæ Õ MERGE TABLE ÍÁÀÔØ Ò¦ÚÎÕ ÓÔÒÕËÔÕÒÕ",
-"îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ ÄÏ ÔÁÂÌÉæ '%-.64s', Ú ÐÒÉÞÉÎÉ ×ÉÍÏÇ ÕΦËÁÌØÎÏÓÔ¦",
-"óÔÏ×ÂÅÃØ BLOB '%-.64s' ×ÉËÏÒÉÓÔÁÎÏ Õ ×ÉÚÎÁÞÅÎΦ ËÌÀÞÁ ÂÅÚ ×ËÁÚÁÎÎÑ ÄÏ×ÖÉÎÉ ËÌÀÞÁ",
-"õÓ¦ ÞÁÓÔÉÎÉ PRIMARY KEY ÐÏ×ÉÎΦ ÂÕÔÉ NOT NULL; ñËÝÏ ×É ÐÏÔÒÅÂÕ¤ÔÅ NULL Õ ËÌÀÞ¦, ÓËÏÒÉÓÔÁÊÔÅÓÑ UNIQUE",
-"òÅÚÕÌØÔÁÔ ÚÎÁÈÏÄÉÔØÓÑ Õ Â¦ÌØÛÅ Î¦Ö ÏÄÎ¦Ê ÓÔÒÏæ",
-"ãÅÊ ÔÉÐ ÔÁÂÌÉæ ÐÏÔÒÅÂÕ¤ ÐÅÒ×ÉÎÎÏÇÏ ËÌÀÞÁ",
-"ãÑ ×ÅÒÓ¦Ñ MySQL ÎÅ ÚËÏÍЦÌØÏ×ÁÎÁ Ú Ð¦ÄÔÒÉÍËÏÀ RAID",
-"÷É Õ ÒÅÖÉͦ ÂÅÚÐÅÞÎÏÇÏ ÏÎÏ×ÌÅÎÎÑ ÔÁ ÎÁÍÁÇÁ¤ÔÅÓØ ÏÎÏ×ÉÔÉ ÔÁÂÌÉÃÀ ÂÅÚ ÏÐÅÒÁÔÏÒÁ WHERE, ÝÏ ×ÉËÏÒÉÓÔÏ×Õ¤ KEY ÓÔÏ×ÂÅÃØ",
-"ëÌÀÞ '%-.64s' ÎÅ ¦ÓÎÕ¤ × ÔÁÂÌÉæ '%-.64s'",
-"îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÔÁÂÌÉÃÀ",
-"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ %s",
-"÷ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÎÕ×ÁÔÉ ÃÀ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËæ§",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ COMMIT",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ ROLLBACK",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ FLUSH_LOGS",
-"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ CHECKPOINT",
-"ðÅÒÅÒ×ÁÎÏ Ú'¤ÄÎÁÎÎÑ %ld ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ: '%-.64s' ËÏÒÉÓÔÕ×ÁÞ: '%-.32s' ÈÏÓÔ: `%-.64s' (%-.64s)",
-"ãÅÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ ¦ÎÁÒÎÕ ÐÅÒÅÄÁÞÕ ÔÁÂÌÉæ",
-"òÅÐ̦ËÁæÊÎÉÊ ÌÏÇ ÚÁËÒÉÔÏ, ÎÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ RESET MASTER",
-"îÅ×ÄÁÌŠצÄÎÏ×ÌÅÎÎÑ ¦ÎÄÅËÓÁ ÐÅÒÅÄÁÎϧ ÔÁÂÌÉæ '%-.64s'",
-"ðÏÍÉÌËÁ ×¦Ä ÇÏÌÏ×ÎÏÇÏ: '%-.64s'",
-"íÅÒÅÖÅ×Á ÐÏÍÉÌËÁ ÞÉÔÁÎÎÑ ×¦Ä ÇÏÌÏ×ÎÏÇÏ",
-"íÅÒÅÖÅ×Á ÐÏÍÉÌËÁ ÚÁÐÉÓÕ ÄÏ ÇÏÌÏ×ÎÏÇÏ",
-"îÅ ÍÏÖÕ ÚÎÁÊÔÉ FULLTEXT ¦ÎÄÅËÓ, ÝÏ ×¦ÄÐÏצÄÁ¤ ÐÅÒÅ̦ËÕ ÓÔÏ×Âæ×",
-"îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ ÐÏÄÁÎÕ ËÏÍÁÎÄÕ ÔÏÍÕ, ÝÏ ÔÁÂÌÉÃÑ ÚÁÂÌÏËÏ×ÁÎÁ ÁÂÏ ×ÉËÏÎÕ¤ÔØÓÑ ÔÒÁÎÚÁËæÑ",
-"îÅצÄÏÍÁ ÓÉÓÔÅÍÎÁ ÚͦÎÎÁ '%-.64s'",
-"ôÁÂÌÉÃÀ '%-.64s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ §§ ÐÏÔÒ¦ÂÎÏ ×¦ÄÎÏ×ÉÔÉ",
-"ôÁÂÌÉÃÀ '%-.64s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ ÏÓÔÁÎΤ (Á×ÔÏÍÁÔÉÞÎÅ?) צÄÎÏ×ÌÅÎÎÑ ÎÅ ×ÄÁÌÏÓÑ",
-"úÁÓÔÅÒÅÖÅÎÎÑ: äÅÑ˦ ÎÅÔÒÁÎÚÁËæÊΦ ÚͦÎÉ ÔÁÂÌÉÃØ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ÐÏ×ÅÒÎÕÔÉ",
-"ôÒÁÎÚÁËÃ¦Ñ Ú ÂÁÇÁÔØÍÁ ×ÉÒÁÚÁÍÉ ×ÉÍÁÇÁ¤ ¦ÌØÛÅ Î¦Ö 'max_binlog_cache_size' ÂÁÊÔ¦× ÄÌÑ ÚÂÅÒ¦ÇÁÎÎÑ. ú¦ÌØÛÔÅ ÃÀ ÚͦÎÎÕ mysqld ÔÁ ÓÐÒÏÂÕÊÔÅ ÚÎÏ×Õ",
-"ïÐÅÒÁÃ¦Ñ ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÎÁÎÁ Ú ÚÁÐÕÝÅÎÉÍ Ð¦ÄÌÅÇÌÉÍ, ÓÐÏÞÁÔËÕ ×ÉËÏÎÁÊÔÅ STOP SLAVE",
-"ïÐÅÒÁÃ¦Ñ ×ÉÍÁÇÁ¤ ÚÁÐÕÝÅÎÏÇÏ Ð¦ÄÌÅÇÌÏÇÏ, ÚËÏÎƦÇÕÒÕÊÔŠЦÄÌÅÇÌÏÇÏ ÔÁ ×ÉËÏÎÁÊÔÅ START SLAVE",
-"óÅÒ×ÅÒ ÎÅ ÚËÏÎƦÇÕÒÏ×ÁÎÏ ÑË Ð¦ÄÌÅÇÌÉÊ, ×ÉÐÒÁ×ÔÅ ÃÅ Õ ÆÁÊ̦ ËÏÎƦÇÕÒÁæ§ ÁÂÏ Ú CHANGE MASTER TO",
-"Could not initialize master info structure, more error messages can be found in the MySQL error log",
-"îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ Ð¦ÄÌÅÇÌÕ Ç¦ÌËÕ, ÐÅÒÅצÒÔÅ ÓÉÓÔÅÍΦ ÒÅÓÕÒÓÉ",
-"ëÏÒÉÓÔÕ×ÁÞ %-.64s ×ÖÅ ÍÁ¤ ¦ÌØÛÅ Î¦Ö 'max_user_connections' ÁËÔÉ×ÎÉÈ Ú'¤ÄÎÁÎØ",
-"íÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÌÉÛÅ ×ÉÒÁÚÉ Ú¦ ÓÔÁÌÉÍÉ Õ SET",
-"úÁÔÒÉÍËÕ ÏÞ¦ËÕ×ÁÎÎÑ ÂÌÏËÕ×ÁÎÎÑ ×ÉÞÅÒÐÁÎÏ",
-"úÁÇÁÌØÎÁ ˦ÌØ˦ÓÔØ ÂÌÏËÕ×ÁÎØ ÐÅÒÅ×ÉÝÉÌÁ ÒÏÚÍ¦Ò ÂÌÏËÕ×ÁÎØ ÄÌÑ ÔÁÂÌÉæ",
-"ïÎÏ×ÉÔÉ ÂÌÏËÕ×ÁÎÎÑ ÎÅ ÍÏÖÌÉ×Ï ÎÁ ÐÒÏÔÑÚ¦ ÔÒÁÎÚÁËæ§ READ UNCOMMITTED",
-"DROP DATABASE ÎÅ ÄÏÚ×ÏÌÅÎÏ ÄÏËÉ Ç¦ÌËÁ ÐÅÒÅÂÕ×Á¤ Ð¦Ä ÚÁÇÁÌØÎÉÍ ÂÌÏËÕ×ÁÎÎÑÍ ÞÉÔÁÎÎÑ",
-"CREATE DATABASE ÎÅ ÄÏÚ×ÏÌÅÎÏ ÄÏËÉ Ç¦ÌËÁ ÐÅÒÅÂÕ×Á¤ Ð¦Ä ÚÁÇÁÌØÎÉÍ ÂÌÏËÕ×ÁÎÎÑÍ ÞÉÔÁÎÎÑ",
-"èÉÂÎÉÊ ÁÒÇÕÍÅÎÔ ÄÌÑ %s",
-"ëÏÒÉÓÔÕ×ÁÞÕ '%-.32s'@'%-.64s' ÎÅ ÄÏÚ×ÏÌÅÎÏ ÓÔ×ÏÒÀ×ÁÔÉ ÎÏ×ÉÈ ËÏÒÉÓÔÕ×ÁÞ¦×",
-"Incorrect table definition; all MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; try restarting transaction",
-"÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ FULLTEXT ¦ÎÄÅËÓ¦×",
-"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",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"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",
-"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",
-"ïÐÅÒÁÎÄ ÍÁ¤ ÓËÌÁÄÁÔÉÓÑ Ú %d ÓÔÏ×Âæ×",
-"ð¦ÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ ¦ÌØÛ ÎiÖ 1 ÚÁÐÉÓ",
-"Unknown prepared statement handler (%.*s) given to %s",
-"Help database is corrupt or does not exist",
-"ãÉË̦ÞÎÅ ÐÏÓÉÌÁÎÎÑ ÎÁ ЦÄÚÁÐÉÔ",
-"ðÅÒÅÔ×ÏÒÅÎÎÑ ÓÔÏ×ÂÃÁ '%s' Ú %s Õ %s",
-"ðÏÓÉÌÁÎÎÑ '%-.64s' ÎÅ ÐiÄÔÒÉÍÕÅÔÓÑ (%s)",
-"Every derived table must have its own alias",
-"Select %u was ÓËÁÓÏ×ÁÎÏ ÐÒÉ ÏÐÔÉÍiÚÁÃii",
-"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 index must be NOT NULL",
-"COLLATION '%s' is not valid for CHARACTER SET '%s'",
-"Slave is already running",
-"Slave has already been stopped",
-"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 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'",
-"Can't drop one or more of the requested users",
-"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)",
-"Unknown collation: '%-.64s'",
-"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",
-"óÔÏ×ÂÅÃØ ÁÂÏ ÐÏÓÉÌÁÎÎÑ '%-.64s%s%-.64s%s%-.64s' ¦Ú SELECTÕ #%d ÂÕÌÏ ÚÎÁÊÄÅÎÅ Õ SELECT¦ #%d",
-"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'",
-"ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %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",
-"Unknown table engine '%s'",
-"'%s' is deprecated, use '%s' instead",
-"ôÁÂÌÉÃÑ %-.100s Õ %s ÎÅ ÍÏÖÅ ÏÎÏ×ÌÀ×ÁÔÉÓØ",
-"The '%s' feature was disabled; you need MySQL built with '%s' to have it working",
-"The MySQL server is running with the %s option so it cannot execute this statement",
-"Column '%-.100s' has duplicated value '%-.64s' in %s"
-"Truncated wrong %-.32s value: '%-.128s'"
-"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",
-"Invalid %s character string: '%.64s'",
-"Result of %s() was larger than max_allowed_packet (%ld) - truncated"
-"Conflicting declarations: '%s%s' and '%s%s'"
-
diff --git a/sql/slave.cc b/sql/slave.cc
index 1be3e3b4a17..0b9a9acb1fd 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000-2003 MySQL AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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 */
@@ -75,7 +75,6 @@ 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
@@ -160,7 +159,7 @@ int init_slave()
sql_print_error("Failed to allocate memory for the master info structure");
goto err;
}
-
+
if (init_master_info(active_mi,master_info_file,relay_log_info_file,
!master_host, (SLAVE_IO | SLAVE_SQL)))
{
@@ -219,6 +218,13 @@ static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
pos Position in relay log file
need_data_lock Set to 1 if this functions should do mutex locks
errmsg Store pointer to error message here
+ look_for_description_event
+ 1 if we should look for such an event. We only need
+ this when the SQL thread starts and opens an existing
+ relay log and has to execute it (possibly from an
+ offset >4); then we need to read the first event of
+ the relay log to be able to parse the events we have
+ to execute.
DESCRIPTION
- Close old open relay log files.
@@ -236,15 +242,35 @@ static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
ulonglong pos, bool need_data_lock,
- const char** errmsg)
+ const char** errmsg,
+ bool look_for_description_event)
{
DBUG_ENTER("init_relay_log_pos");
+ DBUG_PRINT("info", ("pos=%lu", pos));
*errmsg=0;
pthread_mutex_t *log_lock=rli->relay_log.get_log_lock();
if (need_data_lock)
pthread_mutex_lock(&rli->data_lock);
+
+ /*
+ Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER
+ is, too, and init_slave() too; these 2 functions allocate a description
+ event in init_relay_log_pos, which is not freed by the terminating SQL slave
+ thread as that thread is not started by these functions. So we have to free
+ the description_event here, in case, so that there is no memory leak in
+ running, say, CHANGE MASTER.
+ */
+ delete rli->relay_log.description_event_for_exec;
+ /*
+ By default the relay log is in binlog format 3 (4.0).
+ Even if format is 4, this will work enough to read the first event
+ (Format_desc) (remember that format 4 is just lenghtened compared to format
+ 3; format 3 is a prefix of format 4).
+ */
+ rli->relay_log.description_event_for_exec= new
+ Format_description_log_event(3);
pthread_mutex_lock(log_lock);
@@ -284,9 +310,8 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
In this case, we will use the same IO_CACHE pointer to
read data as the IO thread is using to write data.
*/
- rli->cur_log= rli->relay_log.get_log_file();
- if (my_b_tell(rli->cur_log) == 0 &&
- check_binlog_magic(rli->cur_log, errmsg))
+ my_b_seek((rli->cur_log=rli->relay_log.get_log_file()), (off_t)0);
+ if (check_binlog_magic(rli->cur_log,errmsg))
goto err;
rli->cur_log_old_open_count=rli->relay_log.get_open_count();
}
@@ -300,8 +325,85 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
goto err;
rli->cur_log = &rli->cache_buf;
}
- if (pos >= BIN_LOG_HEADER_SIZE)
+ /*
+ In all cases, check_binlog_magic() has been called so we're at offset 4 for
+ sure.
+ */
+ if (pos > BIN_LOG_HEADER_SIZE) /* If pos<=4, we stay at 4 */
+ {
+ Log_event* ev;
+ while (look_for_description_event)
+ {
+ /*
+ Read the possible Format_description_log_event; if position
+ was 4, no need, it will be read naturally.
+ */
+ DBUG_PRINT("info",("looking for a Format_description_log_event"));
+
+ if (my_b_tell(rli->cur_log) >= pos)
+ break;
+
+ /*
+ Because of we have rli->data_lock and log_lock, we can safely read an
+ event
+ */
+ if (!(ev=Log_event::read_log_event(rli->cur_log,0,
+ rli->relay_log.description_event_for_exec)))
+ {
+ DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d",
+ rli->cur_log->error));
+ if (rli->cur_log->error) /* not EOF */
+ {
+ *errmsg= "I/O error reading event at position 4";
+ goto err;
+ }
+ break;
+ }
+ else if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
+ {
+ DBUG_PRINT("info",("found Format_description_log_event"));
+ delete rli->relay_log.description_event_for_exec;
+ rli->relay_log.description_event_for_exec= (Format_description_log_event*) ev;
+ /*
+ As ev was returned by read_log_event, it has passed is_valid(), so
+ my_malloc() in ctor worked, no need to check again.
+ */
+ /*
+ Ok, we found a Format_description event. But it is not sure that this
+ describes the whole relay log; indeed, one can have this sequence
+ (starting from position 4):
+ Format_desc (of slave)
+ Rotate (of master)
+ Format_desc (of master)
+ So the Format_desc which really describes the rest of the relay log
+ is the 3rd event (it can't be further than that, because we rotate
+ the relay log when we queue a Rotate event from the master).
+ But what describes the Rotate is the first Format_desc.
+ So what we do is:
+ go on searching for Format_description events, until you exceed the
+ position (argument 'pos') or until you find another event than Rotate
+ or Format_desc.
+ */
+ }
+ else
+ {
+ DBUG_PRINT("info",("found event of another type=%d",
+ ev->get_type_code()));
+ look_for_description_event= (ev->get_type_code() == ROTATE_EVENT);
+ delete ev;
+ }
+ }
my_b_seek(rli->cur_log,(off_t)pos);
+#ifndef DBUG_OFF
+ {
+ char llbuf1[22], llbuf2[22];
+ DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
+ llstr(my_b_tell(rli->cur_log),llbuf1),
+ llstr(rli->event_relay_log_pos,llbuf2)));
+ }
+#endif
+
+ }
err:
/*
@@ -316,13 +418,15 @@ err:
if (need_data_lock)
pthread_mutex_unlock(&rli->data_lock);
+ if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg)
+ *errmsg= "Invalid Format_description log event; could be out of memory";
DBUG_RETURN ((*errmsg) ? 1 : 0);
}
/*
- Init functio to set up array for errors that should be skipped for slave
+ Init function to set up array for errors that should be skipped for slave
SYNOPSIS
init_slave_skip_errors()
@@ -361,16 +465,15 @@ void init_slave_skip_errors(const char* arg)
}
-void st_relay_log_info::inc_group_relay_log_pos(ulonglong val,
- ulonglong log_pos,
- bool skip_lock)
+void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
+ bool skip_lock)
{
if (!skip_lock)
pthread_mutex_lock(&data_lock);
- inc_event_relay_log_pos(val);
+ inc_event_relay_log_pos();
group_relay_log_pos= event_relay_log_pos;
strmake(group_relay_log_name,event_relay_log_name,
- sizeof(group_relay_log_name)-1);
+ sizeof(group_relay_log_name)-1);
notify_group_relay_log_name_update();
@@ -384,24 +487,31 @@ void st_relay_log_info::inc_group_relay_log_pos(ulonglong val,
not advance as it should on the non-transactional slave (it advances by
big leaps, whereas it should advance by small leaps).
*/
+ /*
+ In 4.x we used the event's len to compute the positions here. This is
+ wrong if the event was 3.23/4.0 and has been converted to 5.0, because
+ then the event's len is not what is was in the master's binlog, so this
+ will make a wrong group_master_log_pos (yes it's a bug in 3.23->4.0
+ replication: Exec_master_log_pos is wrong). Only way to solve this is to
+ have the original offset of the end of the event the relay log. This is
+ what we do in 5.0: log_pos has become "end_log_pos" (because the real use
+ of log_pos in 4.0 was to compute the end_log_pos; so better to store
+ end_log_pos instead of begin_log_pos.
+ If we had not done this fix here, the problem would also have appeared
+ when the slave and master are 5.0 but with different event length (for
+ example the slave is more recent than the master and features the event
+ UID). It would give false MASTER_POS_WAIT, false Exec_master_log_pos in
+ SHOW SLAVE STATUS, and so the user would do some CHANGE MASTER using this
+ value which would lead to badly broken replication.
+ Even the relay_log_pos will be corrupted in this case, because the len is
+ the relay log is not "val".
+ With the end_log_pos solution, we avoid computations involving lengthes.
+ */
+ DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",
+ (long) log_pos, (long) group_master_log_pos));
if (log_pos) // 3.23 binlogs don't have log_posx
{
-#if MYSQL_VERSION_ID < 50000
- /*
- If the event was converted from a 3.23 format, get_event_len() has
- grown by 6 bytes (at least for most events, except LOAD DATA INFILE
- which is already a big problem for 3.23->4.0 replication); 6 bytes is
- the difference between the header's size in 4.0 (LOG_EVENT_HEADER_LEN)
- and the header's size in 3.23 (OLD_HEADER_LEN). Note that using
- mi->old_format will not help if the I/O thread has not started yet.
- Yes this is a hack but it's just to make 3.23->4.x replication work;
- 3.23->5.0 replication is working much better.
- */
- group_master_log_pos= log_pos + val -
- (mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0);
-#else
- group_master_log_pos= log_pos+ val;
-#endif /* MYSQL_VERSION_ID < 5000 */
+ group_master_log_pos= log_pos;
}
pthread_cond_broadcast(&data_cond);
if (!skip_lock)
@@ -442,9 +552,9 @@ int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
/*
Even if rli->inited==0, we still try to empty rli->master_log_* variables.
Indeed, rli->inited==0 does not imply that they already are empty.
- It could be that slave's info initialization partly succeeded :
+ It could be that slave's info initialization partly succeeded :
for example if relay-log.info existed but *relay-bin*.*
- have been manually removed, init_relay_log_info reads the old
+ have been manually removed, init_relay_log_info reads the old
relay-log.info and fills rli->master_log_*, then init_relay_log_info
checks for the existence of the relay log, this fails and
init_relay_log_info leaves rli->inited to 0.
@@ -453,7 +563,7 @@ int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
MASTER, the callers of purge_relay_logs, will delete bogus *.info files
or replace them with correct files), however if the user does SHOW SLAVE
STATUS before START SLAVE, he will see old, confusing rli->master_log_*.
- In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS
+ In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS
to display fine in any case.
*/
@@ -482,13 +592,16 @@ int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
sizeof(rli->group_relay_log_name)-1);
strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(),
sizeof(rli->event_relay_log_name)-1);
- // Just first log with magic number and nothing else
- rli->log_space_total= BIN_LOG_HEADER_SIZE;
rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
- rli->relay_log.reset_bytes_written();
+ if (count_relay_log_space(rli))
+ {
+ *errmsg= "Error counting relay log space";
+ goto err;
+ }
if (!just_reset)
- error= init_relay_log_pos(rli, rli->group_relay_log_name, rli->group_relay_log_pos,
- 0 /* do not need data lock */, errmsg);
+ error= init_relay_log_pos(rli, rli->group_relay_log_name,
+ rli->group_relay_log_pos,
+ 0 /* do not need data lock */, errmsg, 0);
err:
#ifndef DBUG_OFF
@@ -548,24 +661,26 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
pthread_cond_t* term_cond,
volatile uint *slave_running)
{
+ DBUG_ENTER("terminate_slave_thread");
if (term_lock)
{
pthread_mutex_lock(term_lock);
if (!*slave_running)
{
pthread_mutex_unlock(term_lock);
- return ER_SLAVE_NOT_RUNNING;
+ DBUG_RETURN(ER_SLAVE_NOT_RUNNING);
}
}
DBUG_ASSERT(thd != 0);
+ THD_CHECK_SENTRY(thd);
/*
- Is is criticate to test if the slave is running. Otherwise, we might
+ Is is critical to test if the slave is running. Otherwise, we might
be referening freed memory trying to kick it
*/
- THD_CHECK_SENTRY(thd);
while (*slave_running) // Should always be true
{
+ DBUG_PRINT("loop", ("killing slave thread"));
KICK_SLAVE(thd);
/*
There is a small chance that slave thread might miss the first
@@ -577,7 +692,7 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
}
if (term_lock)
pthread_mutex_unlock(term_lock);
- return 0;
+ DBUG_RETURN(0);
}
@@ -636,7 +751,7 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock,
thd->exit_cond(old_msg);
pthread_mutex_lock(cond_lock); // re-acquire it as exit_cond() released
if (thd->killed)
- DBUG_RETURN(ER_SERVER_SHUTDOWN);
+ DBUG_RETURN(thd->killed_errno());
}
}
if (start_lock)
@@ -737,7 +852,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
SYNOPSIS
tables_ok()
- thd thread (SQL slave thread normally)
+ thd thread (SQL slave thread normally). Mustn't be null.
tables list of tables to check
NOTES
@@ -746,7 +861,11 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
rules (see code below). For that reason, users should not set conflicting
rules because they may get unpredicted results (precedence order is
explained in the manual).
-
+
+ Thought which arose from a question of a big customer "I want to include
+ all tables like "abc.%" except the "%.EFG"". This can't be done now. If we
+ supported Perl regexps we could do it with this pattern: /^abc\.(?!EFG)/
+ (I could not find an equivalent in the regex library MySQL uses).
RETURN VALUES
0 should not be logged/replicated
@@ -758,7 +877,24 @@ bool tables_ok(THD* thd, TABLE_LIST* tables)
bool some_tables_updating= 0;
DBUG_ENTER("tables_ok");
- for (; tables; tables = tables->next)
+ /*
+ In routine, can't reliably pick and choose substatements, so always
+ replicate.
+ We can't reliably know if one substatement should be executed or not:
+ consider the case of this substatement: a SELECT on a non-replicated
+ constant table; if we don't execute it maybe it was going to fill a
+ variable which was going to be used by the next substatement to update
+ a replicated table? If we execute it maybe the constant non-replicated
+ table does not exist (and so we'll fail) while there was no need to
+ execute this as this SELECT does not influence replicated tables in the
+ rest of the routine? In other words: users are used to replicate-*-table
+ specifying how to handle updates to tables, these options don't say
+ anything about reads to tables; we can't guess.
+ */
+ if (thd->spcont)
+ DBUG_RETURN(1);
+
+ for (; tables; tables= tables->next_global)
{
char hash_key[2*NAME_LEN+2];
char *end;
@@ -769,7 +905,7 @@ bool tables_ok(THD* thd, TABLE_LIST* tables)
some_tables_updating= 1;
end= strmov(hash_key, tables->db ? tables->db : thd->db);
*end++= '.';
- len= (uint) (strmov(end, tables->real_name) - hash_key);
+ len= (uint) (strmov(end, tables->table_name) - hash_key);
if (do_table_inited) // if there are any do's
{
if (hash_search(&replicate_do_table, (byte*) hash_key, len))
@@ -1157,29 +1293,86 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
return 1;
}
+/*
+ Note that we rely on the master's version (3.23, 4.0.14 etc) instead of
+ relying on the binlog's version. This is not perfect: imagine an upgrade
+ of the master without waiting that all slaves are in sync with the master;
+ then a slave could be fooled about the binlog's format. This is what happens
+ when people upgrade a 3.23 master to 4.0 without doing RESET MASTER: 4.0
+ slaves are fooled. So we do this only to distinguish between 3.23 and more
+ recent masters (it's too late to change things for 3.23).
+
+ RETURNS
+ 0 ok
+ 1 error
+*/
static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi)
{
const char* errmsg= 0;
-
+
/*
- Note the following switch will bug when we have MySQL branch 30 ;)
+ Free old description_event_for_queue (that is needed if we are in
+ a reconnection).
*/
- switch (*mysql->server_version) {
- case '3':
- mi->old_format =
- (strncmp(mysql->server_version, "3.23.57", 7) < 0) /* < .57 */ ?
- BINLOG_FORMAT_323_LESS_57 :
- BINLOG_FORMAT_323_GEQ_57 ;
- break;
- case '4':
- mi->old_format = BINLOG_FORMAT_CURRENT;
- break;
- default:
- /* 5.0 is not supported */
- errmsg = "Master reported an unrecognized MySQL version. Note that 4.1 \
-slaves can't replicate a 5.0 or newer master.";
- break;
+ delete mi->rli.relay_log.description_event_for_queue;
+ mi->rli.relay_log.description_event_for_queue= 0;
+
+ if (!my_isdigit(&my_charset_bin,*mysql->server_version))
+ errmsg = "Master reported unrecognized MySQL version";
+ else
+ {
+ /*
+ Note the following switch will bug when we have MySQL branch 30 ;)
+ */
+ switch (*mysql->server_version)
+ {
+ case '0':
+ case '1':
+ case '2':
+ errmsg = "Master reported unrecognized MySQL version";
+ break;
+ case '3':
+ mi->rli.relay_log.description_event_for_queue= new
+ Format_description_log_event(1, mysql->server_version);
+ break;
+ case '4':
+ mi->rli.relay_log.description_event_for_queue= new
+ Format_description_log_event(3, mysql->server_version);
+ break;
+ default:
+ /*
+ Master is MySQL >=5.0. Give a default Format_desc event, so that we can
+ take the early steps (like tests for "is this a 3.23 master") which we
+ have to take before we receive the real master's Format_desc which will
+ override this one. Note that the Format_desc we create below is garbage
+ (it has the format of the *slave*); it's only good to help know if the
+ master is 3.23, 4.0, etc.
+ */
+ mi->rli.relay_log.description_event_for_queue= new
+ Format_description_log_event(4, mysql->server_version);
+ break;
+ }
+ }
+
+ /*
+ This does not mean that a 5.0 slave will be able to read a 6.0 master; but
+ as we don't know yet, we don't want to forbid this for now. If a 5.0 slave
+ can't read a 6.0 master, this will show up when the slave can't read some
+ events sent by the master, and there will be error messages.
+ */
+
+ if (errmsg)
+ {
+ sql_print_error(errmsg);
+ return 1;
+ }
+
+ /* as we are here, we tried to allocate the event */
+ if (!mi->rli.relay_log.description_event_for_queue)
+ {
+ sql_print_error("Slave I/O thread failed to create a default Format_description_log_event");
+ return 1;
}
/*
@@ -1237,12 +1430,20 @@ not always make sense; please check the manual before using it).";
values of these 2 are never used (new connections don't use them).
We don't test equality of global collation_database either as it's is
going to be deprecated (made read-only) in 4.1 very soon.
- We don't do it for <3.23.57 because masters <3.23.50 hang on
- SELECT @@unknown_var (BUG#7965 - see changelog of 3.23.50).
+ The test is only relevant if master < 5.0.3 (we'll test only if it's older
+ than the 5 branch; < 5.0.3 was alpha...), as >= 5.0.3 master stores
+ charset info in each binlog event.
+ We don't do it for 3.23 because masters <3.23.50 hang on
+ SELECT @@unknown_var (BUG#7965 - see changelog of 3.23.50). So finally we
+ test only if master is 4.x.
*/
- if (mi->old_format == BINLOG_FORMAT_323_LESS_57)
+
+ /* redundant with rest of code but safer against later additions */
+ if (*mysql->server_version == '3')
goto err;
- if (!mysql_real_query(mysql, "SELECT @@GLOBAL.COLLATION_SERVER", 32) &&
+
+ if ((*mysql->server_version == '4') &&
+ !mysql_real_query(mysql, "SELECT @@GLOBAL.COLLATION_SERVER", 32) &&
(master_res= mysql_store_result(mysql)))
{
if ((master_row= mysql_fetch_row(master_res)) &&
@@ -1265,8 +1466,11 @@ be equal for replication to work";
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).
+ This check is only necessary for 4.x masters (and < 5.0.4 masters but
+ those were alpha).
*/
- if (!mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) &&
+ if ((*mysql->server_version == '4') &&
+ !mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) &&
(master_res= mysql_store_result(mysql)))
{
if ((master_row= mysql_fetch_row(master_res)) &&
@@ -1317,7 +1521,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
packet_len= my_net_read(net); // read create table statement
if (packet_len == packet_error)
{
- send_error(thd, ER_MASTER_NET_READ);
+ my_message(ER_MASTER_NET_READ, ER(ER_MASTER_NET_READ), MYF(0));
DBUG_RETURN(1);
}
if (net->read_pos[0] == 255) // error from master
@@ -1326,7 +1530,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
err_msg= (char*) net->read_pos + ((mysql->server_capabilities &
CLIENT_PROTOCOL_41) ?
3+SQLSTATE_LENGTH+1 : 3);
- net_printf(thd, ER_MASTER, err_msg);
+ my_error(ER_MASTER, MYF(0), err_msg);
DBUG_RETURN(1);
}
thd->command = COM_TABLE_DUMP;
@@ -1335,7 +1539,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
if (!(query = thd->strmake((char*) net->read_pos, packet_len)))
{
sql_print_error("create_table_from_dump: out of memory");
- net_printf(thd, ER_GET_ERRNO, "Out of memory");
+ my_message(ER_GET_ERRNO, "Out of memory", MYF(0));
DBUG_RETURN(1);
}
thd->query= query;
@@ -1344,12 +1548,11 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
bzero((char*) &tables,sizeof(tables));
tables.db = (char*)db;
- tables.alias= tables.real_name= (char*)table_name;
+ tables.alias= tables.table_name= (char*)table_name;
/* Drop the table if 'overwrite' is true */
if (overwrite && mysql_rm_table(thd,&tables,1,0)) /* drop if exists */
{
- send_error(thd);
sql_print_error("create_table_from_dump: failed to drop the table");
goto err;
}
@@ -1362,7 +1565,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
save_db = thd->db;
save_db_length= thd->db_length;
thd->db = (char*)db;
- DBUG_ASSERT(thd->db);
+ DBUG_ASSERT(thd->db != 0);
thd->db_length= strlen(thd->db);
mysql_parse(thd, thd->query, packet_len); // run create table
thd->db = save_db; // leave things the way the were before
@@ -1376,7 +1579,6 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
tables.lock_type = TL_WRITE;
if (!open_ltable(thd, &tables, TL_WRITE))
{
- send_error(thd,0,0); // Send error from open_ltable
sql_print_error("create_table_from_dump: could not open created table");
goto err;
}
@@ -1386,7 +1588,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
/* Copy the data file */
if (file->net_read_dump(net))
{
- net_printf(thd, ER_MASTER_NET_READ);
+ my_message(ER_MASTER_NET_READ, ER(ER_MASTER_NET_READ), MYF(0));
sql_print_error("create_table_from_dump: failed in\
handler::net_read_dump()");
goto err;
@@ -1406,7 +1608,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
error=file->repair(thd,&check_opt) != 0;
thd->net.vio = save_vio;
if (error)
- net_printf(thd, ER_INDEX_REBUILD,tables.table->real_name);
+ my_error(ER_INDEX_REBUILD, MYF(0), tables.table->s->table_name);
err:
close_thread_tables(thd);
@@ -1429,12 +1631,11 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
{
if (!(mysql = mysql_init(NULL)))
{
- send_error(thd); // EOM
DBUG_RETURN(1);
}
if (connect_to_master(thd, mysql, mi))
{
- net_printf(thd, ER_CONNECT_TO_MASTER, mysql_error(mysql));
+ my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql));
mysql_close(mysql);
DBUG_RETURN(1);
}
@@ -1458,7 +1659,7 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
if (!called_connected)
mysql_close(mysql);
if (errmsg && thd->vio_ok())
- send_error(thd, error, errmsg);
+ my_message(error, errmsg, MYF(0));
DBUG_RETURN(test(error)); // Return 1 on error
}
@@ -1482,7 +1683,8 @@ void end_master_info(MASTER_INFO* mi)
}
-int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
+static int init_relay_log_info(RELAY_LOG_INFO* rli,
+ const char* info_fname)
{
char fname[FN_REFLEN+128];
int info_fd;
@@ -1490,7 +1692,7 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
int error = 0;
DBUG_ENTER("init_relay_log_info");
- if (rli->inited) // Set if this function called
+ if (rli->inited) // Set if this function called
DBUG_RETURN(0);
fn_format(fname, info_fname, mysql_data_home, "", 4+32);
pthread_mutex_lock(&rli->data_lock);
@@ -1501,23 +1703,10 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
rli->log_space_limit= relay_log_space_limit;
rli->log_space_total= 0;
- // TODO: make this work with multi-master
- if (!opt_relay_logname)
- {
- char tmp[FN_REFLEN];
- /*
- TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
- */
- strmake(tmp,glob_hostname,FN_REFLEN-5);
- strmov(strcend(tmp,'.'),"-relay-bin");
- opt_relay_logname=my_strdup(tmp,MYF(MY_WME));
- }
-
/*
The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
- Note that the I/O thread flushes it to disk after writing every event, in
- flush_master_info(mi, 1).
+ Note that the I/O thread flushes it to disk after writing every
+ event, in flush_master_info(mi, 1).
*/
/*
@@ -1529,16 +1718,25 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
switch to using max_binlog_size for the relay log) and update
rli->relay_log.max_size (and mysql_bin_log.max_size).
*/
-
- if (open_log(&rli->relay_log, glob_hostname, opt_relay_logname,
- "-relay-bin", opt_relaylog_index_name,
- LOG_BIN, 1 /* read_append cache */,
- 1 /* no auto events */,
- max_relay_log_size ? max_relay_log_size : max_binlog_size))
{
- pthread_mutex_unlock(&rli->data_lock);
- sql_print_error("Failed in open_log() called from init_relay_log_info()");
- DBUG_RETURN(1);
+ char buf[FN_REFLEN];
+ const char *ln;
+ ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin",
+ 1, buf);
+
+ /*
+ note, that if open() fails, we'll still have index file open
+ but a destructor will take care of that
+ */
+ if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) ||
+ rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0,
+ (max_relay_log_size ? max_relay_log_size :
+ max_binlog_size), 1))
+ {
+ pthread_mutex_unlock(&rli->data_lock);
+ sql_print_error("Failed in open_log() called from init_relay_log_info()");
+ DBUG_RETURN(1);
+ }
}
/* if file does not exist */
@@ -1568,7 +1766,7 @@ file '%s', errno %d)", fname, my_errno);
/* Init relay log with first entry in the relay index file */
if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
- &msg))
+ &msg, 0))
{
sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
goto err;
@@ -1633,7 +1831,7 @@ Failed to open the existing relay log info file '%s' (errno %d)",
rli->group_relay_log_name,
rli->group_relay_log_pos,
0 /* no data lock*/,
- &msg))
+ &msg, 0))
{
char llbuf[22];
sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)",
@@ -1642,8 +1840,18 @@ Failed to open the existing relay log info file '%s' (errno %d)",
goto err;
}
}
- DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
- DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
+
+#ifndef DBUG_OFF
+ {
+ char llbuf1[22], llbuf2[22];
+ DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
+ llstr(my_b_tell(rli->cur_log),llbuf1),
+ llstr(rli->event_relay_log_pos,llbuf2)));
+ DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
+ DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
+ }
+#endif
+
/*
Now change the cache from READ to WRITE - must do this
before flush_relay_log_info
@@ -1791,9 +1999,9 @@ void clear_until_condition(RELAY_LOG_INFO* rli)
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
- const char* slave_info_fname,
- bool abort_if_no_master_info_file,
- int thread_mask)
+ const char* slave_info_fname,
+ bool abort_if_no_master_info_file,
+ int thread_mask)
{
int fd,error;
char fname[FN_REFLEN+128];
@@ -1807,7 +2015,7 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
last time. If this case pos_in_file would be set and we would
get a crash when trying to read the signature for the binary
relay log.
-
+
We only rewind the read position if we are starting the SQL
thread. The handle_slave_sql thread assumes that the read
position is at the beginning of the file, and will read the
@@ -1833,7 +2041,7 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
fd = mi->fd;
/* does master.info exist ? */
-
+
if (access(fname,F_OK))
{
if (abort_if_no_master_info_file)
@@ -1869,7 +2077,7 @@ file '%s')", fname);
{
if (fd >= 0)
reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
- else
+ else
{
if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 )
{
@@ -1889,52 +2097,52 @@ file '%s')", fname);
mi->fd = fd;
int port, connect_retry, master_log_pos, ssl= 0, lines;
char *first_non_digit;
-
+
/*
Starting from 4.1.x master.info has new format. Now its
- first line contains number of lines in file. By reading this
- number we will be always distinguish to which version our
- master.info corresponds to. We can't simply count lines in
+ first line contains number of lines in file. By reading this
+ number we will be always distinguish to which version our
+ master.info corresponds to. We can't simply count lines in
file since versions before 4.1.x could generate files with more
lines than needed.
- If first line doesn't contain a number or contain number less than
+ If first line doesn't contain a number or contain number less than
14 then such file is treated like file from pre 4.1.1 version.
- There is no ambiguity when reading an old master.info, as before
+ There is no ambiguity when reading an old master.info, as before
4.1.1, the first line contained the binlog's name, which is either
- empty or has an extension (contains a '.'), so can't be confused
+ empty or has an extension (contains a '.'), so can't be confused
with an integer.
- So we're just reading first line and trying to figure which version
+ So we're just reading first line and trying to figure which version
is this.
*/
-
- /*
- The first row is temporarily stored in mi->master_log_name,
- if it is line count and not binlog name (new format) it will be
+
+ /*
+ The first row is temporarily stored in mi->master_log_name,
+ if it is line count and not binlog name (new format) it will be
overwritten by the second row later.
*/
if (init_strvar_from_file(mi->master_log_name,
sizeof(mi->master_log_name), &mi->file,
""))
goto errwithmsg;
-
+
lines= strtoul(mi->master_log_name, &first_non_digit, 10);
- if (mi->master_log_name[0]!='\0' &&
+ if (mi->master_log_name[0]!='\0' &&
*first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
{ // Seems to be new format
- if (init_strvar_from_file(mi->master_log_name,
+ if (init_strvar_from_file(mi->master_log_name,
sizeof(mi->master_log_name), &mi->file, ""))
goto errwithmsg;
}
else
lines= 7;
-
+
if (init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
master_host) ||
init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
- master_user) ||
+ master_user) ||
init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
&mi->file, master_password) ||
init_intvar_from_file(&port, &mi->file, master_port) ||
@@ -1942,17 +2150,17 @@ file '%s')", fname);
master_connect_retry))
goto errwithmsg;
- /*
- If file has ssl part use it even if we have server without
- SSL support. But these option will be ignored later when
- slave will try connect to master, so in this case warning
+ /*
+ If file has ssl part use it even if we have server without
+ SSL support. But these option will be ignored later when
+ slave will try connect to master, so in this case warning
is printed.
*/
- if (lines >= LINES_IN_MASTER_INFO_WITH_SSL &&
+ if (lines >= LINES_IN_MASTER_INFO_WITH_SSL &&
(init_intvar_from_file(&ssl, &mi->file, master_ssl) ||
- init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
+ init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca),
&mi->file, master_ssl_ca) ||
- init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
+ init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath),
&mi->file, master_ssl_capath) ||
init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert),
&mi->file, master_ssl_cert) ||
@@ -1963,11 +2171,11 @@ file '%s')", fname);
goto errwithmsg;
#ifndef HAVE_OPENSSL
if (ssl)
- sql_print_error("SSL information in the master info file "
+ sql_print_warning("SSL information in the master info file "
"('%s') are ignored because this MySQL slave was compiled "
"without SSL support.", fname);
#endif /* HAVE_OPENSSL */
-
+
/*
This has to be handled here as init_intvar_from_file can't handle
my_off_t types
@@ -1987,15 +2195,15 @@ file '%s')", fname);
mi->inited = 1;
// now change cache READ -> WRITE - must do this before flush_master_info
- reinit_io_cache(&mi->file, WRITE_CACHE,0L,0,1);
+ reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1);
if ((error=test(flush_master_info(mi, 1))))
sql_print_error("Failed to flush master info file");
pthread_mutex_unlock(&mi->data_lock);
DBUG_RETURN(error);
-
+
errwithmsg:
sql_print_error("Error reading master configuration");
-
+
err:
if (fd >= 0)
{
@@ -2088,7 +2296,7 @@ void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a)
}
}
-int show_master_info(THD* thd, MASTER_INFO* mi)
+bool show_master_info(THD* thd, MASTER_INFO* mi)
{
// TODO: fix this for multi-master
List<Item> field_list;
@@ -2150,8 +2358,9 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
field_list.push_back(new Item_return_int("Seconds_Behind_Master", 10,
MYSQL_TYPE_LONGLONG));
- if (protocol->send_fields(&field_list, 1))
- DBUG_RETURN(-1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
if (mi->host[0])
{
@@ -2265,10 +2474,10 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
pthread_mutex_unlock(&mi->data_lock);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -2338,6 +2547,7 @@ st_relay_log_info::st_relay_log_info()
bzero((char*) &info_file, sizeof(info_file));
bzero((char*) &cache_buf, sizeof(cache_buf));
+ cached_charset_invalidate();
pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST);
@@ -2358,6 +2568,7 @@ st_relay_log_info::~st_relay_log_info()
pthread_cond_destroy(&start_cond);
pthread_cond_destroy(&stop_cond);
pthread_cond_destroy(&log_space_cond);
+ relay_log.cleanup();
}
/*
@@ -2395,17 +2606,16 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
ulong init_abort_pos_wait;
int error=0;
struct timespec abstime; // for timeout checking
- set_timespec(abstime,timeout);
-
+ const char *msg;
DBUG_ENTER("wait_for_pos");
- DBUG_PRINT("enter",("group_master_log_name: '%s' pos: %lu timeout: %ld",
- group_master_log_name, (ulong) group_master_log_pos,
- (long) timeout));
+ DBUG_PRINT("enter",("log_name: '%s' log_pos: %lu timeout: %lu",
+ log_name->c_ptr(), (ulong) log_pos, (ulong) timeout));
+ set_timespec(abstime,timeout);
pthread_mutex_lock(&data_lock);
- const char *msg= thd->enter_cond(&data_cond, &data_lock,
- "Waiting for the slave SQL thread to "
- "advance position");
+ msg= thd->enter_cond(&data_cond, &data_lock,
+ "Waiting for the slave SQL thread to "
+ "advance position");
/*
This function will abort when it notices that some CHANGE MASTER or
RESET MASTER has changed the master info.
@@ -2462,6 +2672,12 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
bool pos_reached;
int cmp_result= 0;
+ DBUG_PRINT("info",
+ ("init_abort_pos_wait: %ld abort_pos_wait: %ld",
+ init_abort_pos_wait, abort_pos_wait));
+ DBUG_PRINT("info",("group_master_log_name: '%s' pos: %lu",
+ group_master_log_name, (ulong) group_master_log_pos));
+
/*
group_master_log_name can be "", if we are just after a fresh
replication start or after a CHANGE MASTER TO MASTER_HOST/PORT
@@ -2530,7 +2746,7 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
else
pthread_cond_wait(&data_cond, &data_lock);
DBUG_PRINT("info",("Got signal of master update or timed out"));
- if (error == ETIMEDOUT || error == ETIME)
+ if (error == ETIMEDOUT)
{
error= -1;
break;
@@ -2544,7 +2760,7 @@ err:
thd->exit_cond(msg);
DBUG_PRINT("exit",("killed: %d abort: %d slave_running: %d \
improper_arguments: %d timed_out: %d",
- (int) thd->killed,
+ thd->killed_errno(),
(int) (init_abort_pos_wait != abort_pos_wait),
(int) slave_running,
(int) (error == -2),
@@ -2557,6 +2773,24 @@ improper_arguments: %d timed_out: %d",
DBUG_RETURN( error ? error : event_count );
}
+void set_slave_thread_options(THD* thd)
+{
+ thd->options = ((opt_log_slave_updates) ? OPTION_BIN_LOG:0) |
+ OPTION_AUTO_IS_NULL;
+ thd->variables.completion_type= 0;
+}
+
+void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli)
+{
+ thd->variables.character_set_client=
+ global_system_variables.character_set_client;
+ thd->variables.collation_connection=
+ global_system_variables.collation_connection;
+ thd->variables.collation_server=
+ global_system_variables.collation_server;
+ thd->update_charset();
+ rli->cached_charset_invalidate();
+}
/*
init_slave_thread()
@@ -2567,13 +2801,19 @@ 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;
+ /*
+ The two next lines are needed for replication of SP (CREATE PROCEDURE
+ needs a valid user to store in mysql.proc).
+ */
+ thd->priv_user= (char *) "";
+ thd->priv_host[0]= '\0';
thd->host_or_ip= "";
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
thd->net.read_timeout = slave_net_timeout;
thd->master_access= ~(ulong)0;
- thd->priv_user = 0;
thd->slave_thread = 1;
+ set_slave_thread_options(thd);
/*
It's nonsense to constrain the slave threads with max_join_size; if a
query succeeded on master, we HAVE to execute it. So set
@@ -2753,8 +2993,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings)
*suppress_warnings= TRUE;
}
else
- sql_print_error("Error reading packet from server: %s (\
-server_errno=%d)",
+ sql_print_error("Error reading packet from server: %s ( server_errno=%d)",
mysql_error(mysql), mysql_errno(mysql));
return packet_error;
}
@@ -2762,8 +3001,8 @@ server_errno=%d)",
/* Check if eof packet */
if (len < 8 && mysql->net.read_pos[0] == 254)
{
- sql_print_error("Slave: received end packet from server, apparent\
- master shutdown: %s",
+ sql_print_information("Slave: received end packet from server, apparent "
+ "master shutdown: %s",
mysql_error(mysql));
return packet_error;
}
@@ -2835,13 +3074,14 @@ bool st_relay_log_info::is_until_satisfied()
if (until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_UNKNOWN)
{
- /*
- We have no cached comaprison results so we should compare log names
- and cache result
+ /*
+ We have no cached comparison results so we should compare log names
+ and cache result.
+ If we are after RESET SLAVE, and the SQL slave thread has not processed
+ any event yet, it could be that group_master_log_name is "". In that case,
+ just wait for more events (as there is no sensible comparison to do).
*/
- DBUG_ASSERT(*log_name || log_pos == 0);
-
if (*log_name)
{
const char *basename= log_name + dirname_length(log_name);
@@ -2877,21 +3117,39 @@ bool st_relay_log_info::is_until_satisfied()
}
+void st_relay_log_info::cached_charset_invalidate()
+{
+ /* Full of zeroes means uninitialized. */
+ bzero(cached_charset, sizeof(cached_charset));
+}
+
+
+bool st_relay_log_info::cached_charset_compare(char *charset)
+{
+ if (bcmp(cached_charset, charset, sizeof(cached_charset)))
+ {
+ memcpy(cached_charset, charset, sizeof(cached_charset));
+ return 1;
+ }
+ return 0;
+}
+
+
static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
{
/*
We acquire this mutex since we need it for all operations except
- event execution. But we will release it in places where we will
+ event execution. But we will release it in places where we will
wait for something for example inside of next_event().
*/
pthread_mutex_lock(&rli->data_lock);
-
- if (rli->until_condition!=RELAY_LOG_INFO::UNTIL_NONE &&
- rli->is_until_satisfied())
+
+ if (rli->until_condition!=RELAY_LOG_INFO::UNTIL_NONE &&
+ rli->is_until_satisfied())
{
sql_print_error("Slave SQL thread stopped because it reached its"
" UNTIL position %ld", (long) rli->until_pos());
- /*
+ /*
Setting abort_slave flag because we do not want additional message about
error in query execution to be printed.
*/
@@ -2899,11 +3157,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
pthread_mutex_unlock(&rli->data_lock);
return 1;
}
-
+
Log_event * ev = next_event(rli);
-
+
DBUG_ASSERT(rli->sql_thd==thd);
-
+
if (sql_slave_killed(thd,rli))
{
pthread_mutex_unlock(&rli->data_lock);
@@ -2916,35 +3174,70 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
int exec_res;
/*
- Skip queries originating from this server or number of
- queries specified by the user in slave_skip_counter
- We can't however skip event's that has something to do with the
+ Queries originating from this server must be skipped.
+ Low-level events (Format_desc, Rotate, Stop) from this server
+ must also be skipped. But for those we don't want to modify
+ group_master_log_pos, because these events did not exist on the master.
+ Format_desc is not completely skipped.
+ Skip queries specified by the user in slave_skip_counter.
+ We can't however skip events that has something to do with the
log files themselves.
+ Filtering on own server id is extremely important, to ignore execution of
+ events created by the creation/rotation of the relay log (remember that
+ now the relay log starts with its Format_desc, has a Rotate etc).
*/
- if ((ev->server_id == (uint32) ::server_id && !replicate_same_server_id) ||
- (rli->slave_skip_counter && type_code != ROTATE_EVENT))
+ DBUG_PRINT("info",("type_code=%d, server_id=%d",type_code,ev->server_id));
+
+ if ((ev->server_id == (uint32) ::server_id &&
+ !replicate_same_server_id &&
+ type_code != FORMAT_DESCRIPTION_EVENT) ||
+ (rli->slave_skip_counter &&
+ type_code != ROTATE_EVENT && type_code != STOP_EVENT &&
+ type_code != START_EVENT_V3 && type_code!= FORMAT_DESCRIPTION_EVENT))
{
- /* TODO: I/O thread should not even log events with the same server id */
- rli->inc_group_relay_log_pos(ev->get_event_len(),
- type_code != STOP_EVENT ? ev->log_pos : LL(0),
- 1/* skip lock*/);
- flush_relay_log_info(rli);
+ DBUG_PRINT("info", ("event skipped"));
+ if (thd->options & OPTION_BEGIN)
+ rli->inc_event_relay_log_pos();
+ else
+ {
+ rli->inc_group_relay_log_pos((type_code == ROTATE_EVENT ||
+ type_code == STOP_EVENT ||
+ type_code == FORMAT_DESCRIPTION_EVENT) ?
+ LL(0) : ev->log_pos,
+ 1/* skip lock*/);
+ flush_relay_log_info(rli);
+ }
/*
- Protect against common user error of setting the counter to 1
- instead of 2 while recovering from an failed auto-increment insert
+ Protect against common user error of setting the counter to 1
+ instead of 2 while recovering from an insert which used auto_increment,
+ rand or user var.
*/
- if (rli->slave_skip_counter &&
- !((type_code == INTVAR_EVENT || type_code == STOP_EVENT) &&
- rli->slave_skip_counter == 1))
+ if (rli->slave_skip_counter &&
+ !((type_code == INTVAR_EVENT ||
+ type_code == RAND_EVENT ||
+ type_code == USER_VAR_EVENT) &&
+ rli->slave_skip_counter == 1) &&
+ /*
+ The events from ourselves which have something to do with the relay
+ log itself must be skipped, true, but they mustn't decrement
+ rli->slave_skip_counter, because the user is supposed to not see
+ these events (they are not in the master's binlog) and if we
+ decremented, START SLAVE would for example decrement when it sees
+ the Rotate, so the event which the user probably wanted to skip
+ would not be skipped.
+ */
+ !(ev->server_id == (uint32) ::server_id &&
+ (type_code == ROTATE_EVENT || type_code == STOP_EVENT ||
+ type_code == START_EVENT_V3 || type_code == FORMAT_DESCRIPTION_EVENT)))
--rli->slave_skip_counter;
pthread_mutex_unlock(&rli->data_lock);
- delete ev;
- return 0; // avoid infinite update loops
- }
+ delete ev;
+ return 0; // avoid infinite update loops
+ }
pthread_mutex_unlock(&rli->data_lock);
-
+
thd->server_id = ev->server_id; // use the original server id for logging
thd->set_time(); // time the query
thd->lex->current_select= 0;
@@ -2953,7 +3246,16 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
ev->thd = thd;
exec_res = ev->exec_event(rli);
DBUG_ASSERT(rli->sql_thd==thd);
- delete ev;
+ /*
+ Format_description_log_event should not be deleted because it will be
+ used to read info about the relay log's format; it will be deleted when
+ the SQL thread does not need it, i.e. when this thread terminates.
+ */
+ if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
+ {
+ DBUG_PRINT("info", ("Deleting the event after it has been executed"));
+ delete ev;
+ }
if (slave_trans_retries)
{
if (exec_res &&
@@ -2982,7 +3284,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
else if (init_relay_log_pos(rli,
rli->group_relay_log_name,
rli->group_relay_log_pos,
- 1, &errmsg))
+ 1, &errmsg, 1))
sql_print_error("Error initializing relay log position: %s",
errmsg);
else
@@ -3033,17 +3335,17 @@ extern "C" pthread_handler_decl(handle_slave_io,arg)
{
THD *thd; // needs to be first for thread_stack
MYSQL *mysql;
- MASTER_INFO *mi = (MASTER_INFO*)arg;
+ MASTER_INFO *mi = (MASTER_INFO*)arg;
char llbuff[22];
uint retry_count;
-
+
// needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
my_thread_init();
DBUG_ENTER("handle_slave_io");
#ifndef DBUG_OFF
slave_begin:
-#endif
+#endif
DBUG_ASSERT(mi->inited);
mysql= NULL ;
retry_count= 0;
@@ -3052,10 +3354,10 @@ slave_begin:
/* Inform waiting threads that slave has started */
mi->slave_run_id++;
-#ifndef DBUG_OFF
+#ifndef DBUG_OFF
mi->events_till_abort = abort_slave_event_count;
-#endif
-
+#endif
+
thd= new THD; // note that contructor of THD uses DBUG_ !
THD_CHECK_SENTRY(thd);
@@ -3076,17 +3378,16 @@ slave_begin:
mi->abort_slave = 0;
pthread_mutex_unlock(&mi->run_lock);
pthread_cond_broadcast(&mi->start_cond);
-
+
DBUG_PRINT("master_info",("log_file_name: '%s' position: %s",
mi->master_log_name,
llstr(mi->master_log_pos,llbuff)));
-
+
if (!(mi->mysql = mysql = mysql_init(NULL)))
{
sql_print_error("Slave I/O thread: error in mysql_init()");
goto err;
}
-
thd->proc_info = "Connecting to master";
// we can get killed during safe_connect
@@ -3098,7 +3399,7 @@ slave_begin:
llstr(mi->master_log_pos,llbuff));
else
{
- sql_print_error("Slave I/O thread killed while connecting to master");
+ sql_print_information("Slave I/O thread killed while connecting to master");
goto err;
}
@@ -3110,7 +3411,8 @@ connected:
thd->proc_info = "Checking master version";
if (get_master_version_and_clock(mysql, mi))
goto err;
- if (!mi->old_format)
+
+ if (mi->rli.relay_log.description_event_for_queue->binlog_version > 1)
{
/*
Register ourselves with the master.
@@ -3121,22 +3423,22 @@ connected:
if (register_slave_on_master(mysql) || update_slave_list(mysql, mi))
goto err;
}
-
+
DBUG_PRINT("info",("Starting reading binary log from master"));
while (!io_slave_killed(thd,mi))
{
- bool suppress_warnings= 0;
+ bool suppress_warnings= 0;
thd->proc_info = "Requesting binlog dump";
if (request_dump(mysql, mi, &suppress_warnings))
{
sql_print_error("Failed on request_dump()");
if (io_slave_killed(thd,mi))
{
- sql_print_error("Slave I/O thread killed while requesting master \
+ sql_print_information("Slave I/O thread killed while requesting master \
dump");
goto err;
}
-
+
mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
thd->proc_info= "Waiting to reconnect after a failed binlog dump request";
#ifdef SIGNAL_WITH_VIO_CLOSE
@@ -3157,7 +3459,7 @@ dump");
}
if (io_slave_killed(thd,mi))
{
- sql_print_error("Slave I/O thread killed while retrying master \
+ sql_print_information("Slave I/O thread killed while retrying master \
dump");
goto err;
}
@@ -3170,7 +3472,7 @@ reconnecting to try again, log '%s' at postion %s", IO_RPL_LOG_NAME,
if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
io_slave_killed(thd,mi))
{
- sql_print_error("Slave I/O thread killed during or \
+ sql_print_information("Slave I/O thread killed during or \
after reconnect");
goto err;
}
@@ -3180,22 +3482,22 @@ after reconnect");
while (!io_slave_killed(thd,mi))
{
- bool suppress_warnings= 0;
- /*
+ bool suppress_warnings= 0;
+ /*
We say "waiting" because read_event() will wait if there's nothing to
- read. But if there's something to read, it will not wait. The important
- thing is to not confuse users by saying "reading" whereas we're in fact
- receiving nothing.
+ read. But if there's something to read, it will not wait. The
+ important thing is to not confuse users by saying "reading" whereas
+ we're in fact receiving nothing.
*/
thd->proc_info = "Waiting for master to send event";
ulong event_len = read_event(mysql, mi, &suppress_warnings);
if (io_slave_killed(thd,mi))
{
if (global_system_variables.log_warnings)
- sql_print_error("Slave I/O thread killed while reading event");
+ sql_print_information("Slave I/O thread killed while reading event");
goto err;
}
-
+
if (event_len == packet_error)
{
uint mysql_error_number= mysql_errno(mysql);
@@ -3226,30 +3528,30 @@ max_allowed_packet",
goto err; // Don't retry forever
safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
(void*) mi);
- }
+ }
if (io_slave_killed(thd,mi))
{
if (global_system_variables.log_warnings)
- sql_print_error("Slave I/O thread killed while waiting to \
+ sql_print_information("Slave I/O thread killed while waiting to \
reconnect after a failed read");
goto err;
}
thd->proc_info = "Reconnecting after a failed master event read";
if (!suppress_warnings)
- sql_print_error("Slave I/O thread: Failed reading log event, \
+ sql_print_information("Slave I/O thread: Failed reading log event, \
reconnecting to retry, log '%s' position %s", IO_RPL_LOG_NAME,
llstr(mi->master_log_pos, llbuff));
if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
io_slave_killed(thd,mi))
{
if (global_system_variables.log_warnings)
- sql_print_error("Slave I/O thread killed during or after a \
+ sql_print_information("Slave I/O thread killed during or after a \
reconnect done to recover from failed read");
goto err;
}
goto connected;
} // if (event_len == packet_error)
-
+
retry_count=0; // ok event, reset retry counter
thd->proc_info = "Queueing master event to the relay log";
if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
@@ -3305,7 +3607,7 @@ log space");
// error = 0;
err:
// print the current replication position
- sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s",
+ sql_print_information("Slave I/O thread exiting, read up to log '%s', position %s",
IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety
@@ -3320,6 +3622,9 @@ err:
pthread_mutex_lock(&mi->run_lock);
mi->slave_running = 0;
mi->io_thd = 0;
+ /* Forget the relay log's format */
+ delete mi->rli.relay_log.description_event_for_queue;
+ mi->rli.relay_log.description_event_for_queue= 0;
// TODO: make rpl_status part of MASTER_INFO
change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE);
mi->abort_slave = 0; // TODO: check if this is needed
@@ -3425,15 +3730,38 @@ slave_begin:
if (init_relay_log_pos(rli,
rli->group_relay_log_name,
rli->group_relay_log_pos,
- 1 /*need data lock*/, &errmsg))
+ 1 /*need data lock*/, &errmsg,
+ 1 /*look for a description_event*/))
{
sql_print_error("Error initializing relay log position: %s",
errmsg);
goto err;
}
THD_CHECK_SENTRY(thd);
- DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
- DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
+#ifndef DBUG_OFF
+ {
+ char llbuf1[22], llbuf2[22];
+ DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s",
+ llstr(my_b_tell(rli->cur_log),llbuf1),
+ llstr(rli->event_relay_log_pos,llbuf2)));
+ DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE);
+ /*
+ Wonder if this is correct. I (Guilhem) wonder if my_b_tell() returns the
+ correct position when it's called just after my_b_seek() (the questionable
+ stuff is those "seek is done on next read" comments in the my_b_seek()
+ source code).
+ The crude reality is that this assertion randomly fails whereas
+ replication seems to work fine. And there is no easy explanation why it
+ fails (as we my_b_seek(rli->event_relay_log_pos) at the very end of
+ init_relay_log_pos() called above). Maybe the assertion would be
+ meaningful if we held rli->data_lock between the my_b_seek() and the
+ DBUG_ASSERT().
+ */
+#ifdef SHOULD_BE_CHECKED
+ DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos);
+#endif
+ }
+#endif
DBUG_ASSERT(rli->sql_thd == thd);
DBUG_PRINT("master_info",("log_file_name: %s position: %s",
@@ -3477,12 +3805,18 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
}
/* Thread stopped. Print the current replication position to the log */
- sql_print_information("Slave SQL thread exiting, replication stopped in log \
- '%s' at position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff));
+ sql_print_information("Slave SQL thread exiting, replication stopped in log "
+ "'%s' at position %s",
+ RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff));
err:
VOID(pthread_mutex_lock(&LOCK_thread_count));
- thd->query = thd->db = 0; // extra safety
+ /*
+ Some extra safety, which should not been needed (normally, event deletion
+ should already have done these assignments (each event which sets these
+ variables is supposed to set them to 0 before terminating)).
+ */
+ thd->query= thd->db= thd->catalog= 0;
thd->query_length= thd->db_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->proc_info = "Waiting for slave mutex on exit";
@@ -3492,16 +3826,16 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun
/* When master_pos_wait() wakes up it will check this and terminate */
rli->slave_running= 0;
- /*
- Going out of the transaction. Necessary to mark it, in case the user
- restarts replication from a non-transactional statement (with CHANGE
- MASTER).
- */
+ /* Forget the relay log's format */
+ delete rli->relay_log.description_event_for_exec;
+ rli->relay_log.description_event_for_exec= 0;
/* Wake up master_pos_wait() */
pthread_mutex_unlock(&rli->data_lock);
DBUG_PRINT("info",("Signaling possibly waiting master_pos_wait() functions"));
pthread_cond_broadcast(&rli->data_cond);
rli->ignore_log_space_limit= 0; /* don't need any lock */
+ /* we die so won't remember charset - re-update them on next thread start */
+ rli->cached_charset_invalidate();
rli->save_temporary_tables = thd->temporary_tables;
/*
@@ -3594,7 +3928,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
if (unlikely(cev_not_written))
break;
Execute_load_log_event xev(thd,0,0);
- xev.log_pos = mi->master_log_pos;
+ xev.log_pos = cev->log_pos;
if (unlikely(mi->rli.relay_log.append(&xev)))
{
sql_print_error("Slave I/O: error writing Exec_load event to \
@@ -3608,7 +3942,6 @@ relay log");
{
cev->block = (char*)net->read_pos;
cev->block_len = num_bytes;
- cev->log_pos = mi->master_log_pos;
if (unlikely(mi->rli.relay_log.append(cev)))
{
sql_print_error("Slave I/O: error writing Create_file event to \
@@ -3622,7 +3955,7 @@ relay log");
{
aev.block = (char*)net->read_pos;
aev.block_len = num_bytes;
- aev.log_pos = mi->master_log_pos;
+ aev.log_pos = cev->log_pos;
if (unlikely(mi->rli.relay_log.append(&aev)))
{
sql_print_error("Slave I/O: error writing Append_block event to \
@@ -3650,6 +3983,7 @@ err:
DESCRIPTION
Updates the master info with the place in the next binary
log where we should start reading.
+ Rotate the relay log to avoid mixed-format relay logs.
NOTES
We assume we already locked mi->data_lock
@@ -3680,21 +4014,34 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
if (disconnect_slave_event_count)
events_till_disconnect++;
#endif
+
+ /*
+ If description_event_for_queue is format <4, there is conversion in the
+ relay log to the slave's format (4). And Rotate can mean upgrade or
+ nothing. If upgrade, it's to 5.0 or newer, so we will get a Format_desc, so
+ no need to reset description_event_for_queue now. And if it's nothing (same
+ master version as before), no need (still using the slave's format).
+ */
+ if (mi->rli.relay_log.description_event_for_queue->binlog_version >= 4)
+ {
+ delete mi->rli.relay_log.description_event_for_queue;
+ /* start from format 3 (MySQL 4.0) again */
+ mi->rli.relay_log.description_event_for_queue= new
+ Format_description_log_event(3);
+ }
+ /*
+ Rotate the relay log makes binlog format detection easier (at next slave
+ start or mysqlbinlog)
+ */
+ rotate_relay_log(mi); /* will take the right mutexes */
DBUG_RETURN(0);
}
-
/*
- queue_old_event()
-
- Writes a 3.23 event to the relay log.
-
- TODO:
- Test this code before release - it has to be tested on a separate
- setup with 3.23 master
+ Reads a 3.23 event and converts it to the slave's format. This code was
+ copied from MySQL 4.0.
*/
-
-static int queue_old_event(MASTER_INFO *mi, const char *buf,
+static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf,
ulong event_len)
{
const char *errmsg = 0;
@@ -3702,7 +4049,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
bool ignore_event= 0;
char *tmp_buf = 0;
RELAY_LOG_INFO *rli= &mi->rli;
- DBUG_ENTER("queue_old_event");
+ DBUG_ENTER("queue_binlog_ver_1_event");
/*
If we get Load event, we need to pass a non-reusable buffer
@@ -3734,7 +4081,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
connected to the master).
*/
Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
- 1 /*old format*/ );
+ mi->rli.relay_log.description_event_for_queue);
if (unlikely(!ev))
{
sql_print_error("Read invalid event from master: '%s',\
@@ -3744,7 +4091,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
DBUG_RETURN(1);
}
pthread_mutex_lock(&mi->data_lock);
- ev->log_pos = mi->master_log_pos;
+ ev->log_pos= mi->master_log_pos; /* 3.23 events don't contain log_pos */
switch (ev->get_type_code()) {
case STOP_EVENT:
ignore_event= 1;
@@ -3768,14 +4115,12 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
*/
{
/* We come here when and only when tmp_buf != 0 */
- DBUG_ASSERT(tmp_buf);
+ DBUG_ASSERT(tmp_buf != 0);
+ inc_pos=event_len;
+ ev->log_pos+= inc_pos;
int error = process_io_create_file(mi,(Create_file_log_event*)ev);
delete ev;
- /*
- We had incremented event_len, but now when it is used to calculate the
- position in the master's log, we must use the original value.
- */
- mi->master_log_pos += --event_len;
+ mi->master_log_pos += inc_pos;
DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
pthread_mutex_unlock(&mi->data_lock);
my_free((char*)tmp_buf, MYF(0));
@@ -3787,6 +4132,12 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
}
if (likely(!ignore_event))
{
+ if (ev->log_pos)
+ /*
+ Don't do it for fake Rotate events (see comment in
+ Log_event::Log_event(const char* buf...) in log_event.cc).
+ */
+ ev->log_pos+= event_len; /* make log_pos be the pos of the end of the event */
if (unlikely(rli->relay_log.append(ev)))
{
delete ev;
@@ -3802,10 +4153,98 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
DBUG_RETURN(0);
}
+/*
+ Reads a 4.0 event and converts it to the slave's format. This code was copied
+ from queue_binlog_ver_1_event(), with some affordable simplifications.
+*/
+static int queue_binlog_ver_3_event(MASTER_INFO *mi, const char *buf,
+ ulong event_len)
+{
+ const char *errmsg = 0;
+ ulong inc_pos;
+ char *tmp_buf = 0;
+ RELAY_LOG_INFO *rli= &mi->rli;
+ DBUG_ENTER("queue_binlog_ver_3_event");
+
+ /* read_log_event() will adjust log_pos to be end_log_pos */
+ Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
+ mi->rli.relay_log.description_event_for_queue);
+ if (unlikely(!ev))
+ {
+ sql_print_error("Read invalid event from master: '%s',\
+ master could be corrupt but a more likely cause of this is a bug",
+ errmsg);
+ my_free((char*) tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(1);
+ }
+ pthread_mutex_lock(&mi->data_lock);
+ switch (ev->get_type_code()) {
+ case STOP_EVENT:
+ goto err;
+ case ROTATE_EVENT:
+ if (unlikely(process_io_rotate(mi,(Rotate_log_event*)ev)))
+ {
+ delete ev;
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_RETURN(1);
+ }
+ inc_pos= 0;
+ break;
+ default:
+ inc_pos= event_len;
+ break;
+ }
+ if (unlikely(rli->relay_log.append(ev)))
+ {
+ delete ev;
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_RETURN(1);
+ }
+ rli->relay_log.harvest_bytes_written(&rli->log_space_total);
+ delete ev;
+ mi->master_log_pos+= inc_pos;
+err:
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ pthread_mutex_unlock(&mi->data_lock);
+ DBUG_RETURN(0);
+}
+
+/*
+ queue_old_event()
+
+ Writes a 3.23 or 4.0 event to the relay log, after converting it to the 5.0
+ (exactly, slave's) format. To do the conversion, we create a 5.0 event from
+ the 3.23/4.0 bytes, then write this event to the relay log.
+
+ TODO:
+ Test this code before release - it has to be tested on a separate
+ setup with 3.23 master or 4.0 master
+*/
+
+static int queue_old_event(MASTER_INFO *mi, const char *buf,
+ ulong event_len)
+{
+ switch (mi->rli.relay_log.description_event_for_queue->binlog_version)
+ {
+ case 1:
+ return queue_binlog_ver_1_event(mi,buf,event_len);
+ case 3:
+ return queue_binlog_ver_3_event(mi,buf,event_len);
+ default: /* unsupported format; eg version 2 */
+ DBUG_PRINT("info",("unsupported binlog format %d in queue_old_event()",
+ mi->rli.relay_log.description_event_for_queue->binlog_version));
+ return 1;
+ }
+}
/*
queue_event()
+ If the event is 3.23/4.0, passes it to queue_old_event() which will convert
+ it. Otherwise, writes a 5.0 (or newer) event to the relay log. Then there is
+ no format conversion, it's pure read/write of bytes.
+ So a 5.0.0 slave's relay log can contain events in the slave's format or in
+ any >=5.0.0 format.
*/
int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
@@ -3815,7 +4254,8 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
RELAY_LOG_INFO *rli= &mi->rli;
DBUG_ENTER("queue_event");
- if (mi->old_format)
+ if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 &&
+ buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT /* a way to escape */)
DBUG_RETURN(queue_old_event(mi,buf,event_len));
pthread_mutex_lock(&mi->data_lock);
@@ -3832,7 +4272,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
master server shutdown. The only thing this does is cleaning. But
cleaning is already done on a per-master-thread basis (as the master
server is shutting down cleanly, it has written all DROP TEMPORARY TABLE
- and DO RELEASE_LOCK; prepared statements' deletion are TODO).
+ prepared statements' deletion are TODO only when we binlog prep stmts).
We don't even increment mi->master_log_pos, because we may be just after
a Rotate event. Btw, in a few milliseconds we are going to have a Start
@@ -3842,7 +4282,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
goto err;
case ROTATE_EVENT:
{
- Rotate_log_event rev(buf,event_len,0);
+ Rotate_log_event rev(buf,event_len,mi->rli.relay_log.description_event_for_queue);
if (unlikely(process_io_rotate(mi,&rev)))
{
error= 1;
@@ -3855,6 +4295,42 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
inc_pos= 0;
break;
}
+ case FORMAT_DESCRIPTION_EVENT:
+ {
+ /*
+ Create an event, and save it (when we rotate the relay log, we will have
+ to write this event again).
+ */
+ /*
+ We are the only thread which reads/writes description_event_for_queue.
+ The relay_log struct does not move (though some members of it can
+ change), so we needn't any lock (no rli->data_lock, no log lock).
+ */
+ Format_description_log_event* tmp;
+ const char* errmsg;
+ if (!(tmp= (Format_description_log_event*)
+ Log_event::read_log_event(buf, event_len, &errmsg,
+ mi->rli.relay_log.description_event_for_queue)))
+ {
+ error= 2;
+ goto err;
+ }
+ delete mi->rli.relay_log.description_event_for_queue;
+ mi->rli.relay_log.description_event_for_queue= tmp;
+ /*
+ Though this does some conversion to the slave's format, this will
+ preserve the master's binlog format version, and number of event types.
+ */
+ /*
+ If the event was not requested by the slave (the slave did not ask for
+ it), i.e. has end_log_pos=0, we do not increment mi->master_log_pos
+ */
+ inc_pos= uint4korr(buf+LOG_POS_OFFSET) ? event_len : 0;
+ DBUG_PRINT("info",("binlog format is now %d",
+ mi->rli.relay_log.description_event_for_queue->binlog_version));
+
+ }
+ break;
default:
inc_pos= event_len;
break;
@@ -3881,23 +4357,32 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
We still want to increment, so that we won't re-read this event from the
master if the slave IO thread is now stopped/restarted (more efficient if
the events we are ignoring are big LOAD DATA INFILE).
+ But events which were generated by this slave and which do not exist in
+ the master's binlog (i.e. Format_desc, Rotate & Stop) should not increment
+ mi->master_log_pos.
*/
- mi->master_log_pos+= inc_pos;
+ if (buf[EVENT_TYPE_OFFSET]!=FORMAT_DESCRIPTION_EVENT &&
+ buf[EVENT_TYPE_OFFSET]!=ROTATE_EVENT &&
+ buf[EVENT_TYPE_OFFSET]!=STOP_EVENT)
+ mi->master_log_pos+= inc_pos;
DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos));
}
else
{
/* write the event to the relay log */
- if (likely(!(error= rli->relay_log.appendv(buf,event_len,0))))
+ if (likely(!(rli->relay_log.appendv(buf,event_len,0))))
{
mi->master_log_pos+= inc_pos;
DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
}
+ else
+ error=3;
}
err:
pthread_mutex_unlock(&mi->data_lock);
+ DBUG_PRINT("info", ("error=%d", error));
DBUG_RETURN(error);
}
@@ -3922,6 +4407,7 @@ void end_relay_log_info(RELAY_LOG_INFO* rli)
}
rli->inited = 0;
rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+ rli->relay_log.harvest_bytes_written(&rli->log_space_total);
/*
Delete the slave's temporary tables from memory.
In the future there will be other actions than this, to ensure persistance
@@ -4050,6 +4536,7 @@ replication resumed in log '%s' at position %s", mi->user,
thd->set_active_vio(mysql->net.vio);
#endif
}
+ mysql->reconnect= 1;
DBUG_PRINT("exit",("slave_was_killed: %d", slave_was_killed));
DBUG_RETURN(slave_was_killed);
}
@@ -4143,6 +4630,7 @@ static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg)
relay_log_pos Current log pos
pending Number of bytes already processed from the event
*/
+ rli->event_relay_log_pos= max(rli->event_relay_log_pos, BIN_LOG_HEADER_SIZE);
my_b_seek(cur_log,rli->event_relay_log_pos);
DBUG_RETURN(cur_log);
}
@@ -4201,28 +4689,40 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
hot_log=0; // Using old binary log
}
}
+
#ifndef DBUG_OFF
{
+ /* This is an assertion which sometimes fails, let's try to track it */
char llbuf1[22], llbuf2[22];
+ DBUG_PRINT("info", ("my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
+ llstr(my_b_tell(cur_log),llbuf1),
+ llstr(rli->event_relay_log_pos,llbuf2)));
DBUG_ASSERT(my_b_tell(cur_log) >= BIN_LOG_HEADER_SIZE);
- /*
- The next assertion sometimes (very rarely) fails, let's try to track
- it
- */
- DBUG_PRINT("info", ("\
-Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
- llstr(my_b_tell(cur_log),llbuf1),
- llstr(rli->group_relay_log_pos,llbuf2)));
- DBUG_ASSERT(my_b_tell(cur_log) == rli->event_relay_log_pos);
+ DBUG_ASSERT(my_b_tell(cur_log) == rli->event_relay_log_pos);
}
#endif
/*
Relay log is always in new format - if the master is 3.23, the
- I/O thread will convert the format for us
+ I/O thread will convert the format for us.
+ A problem: the description event may be in a previous relay log. So if
+ the slave has been shutdown meanwhile, we would have to look in old relay
+ logs, which may even have been deleted. So we need to write this
+ description event at the beginning of the relay log.
+ When the relay log is created when the I/O thread starts, easy: the
+ master will send the description event and we will queue it.
+ But if the relay log is created by new_file(): then the solution is:
+ MYSQL_LOG::open() will write the buffered description event.
*/
- if ((ev=Log_event::read_log_event(cur_log,0,(bool)0 /* new format */)))
+ if ((ev=Log_event::read_log_event(cur_log,0,
+ rli->relay_log.description_event_for_exec)))
+
{
DBUG_ASSERT(thd==rli->sql_thd);
+ /*
+ read it while we have a lock, to avoid a mutex lock in
+ inc_event_relay_log_pos()
+ */
+ rli->future_event_relay_log_pos= my_b_tell(cur_log);
if (hot_log)
pthread_mutex_unlock(log_lock);
DBUG_RETURN(ev);
@@ -4379,8 +4879,8 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
{
#ifdef EXTRA_DEBUG
if (global_system_variables.log_warnings)
- sql_print_error("next log '%s' is currently active",
- rli->linfo.log_file_name);
+ sql_print_information("next log '%s' is currently active",
+ rli->linfo.log_file_name);
#endif
rli->cur_log= cur_log= rli->relay_log.get_log_file();
rli->cur_log_old_open_count= rli->relay_log.get_open_count();
@@ -4409,8 +4909,8 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
*/
#ifdef EXTRA_DEBUG
if (global_system_variables.log_warnings)
- sql_print_error("next log '%s' is not active",
- rli->linfo.log_file_name);
+ sql_print_information("next log '%s' is not active",
+ rli->linfo.log_file_name);
#endif
// open_binlog() will check the magic header
if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
@@ -4436,7 +4936,11 @@ event(errno: %d cur_log->error: %d)",
}
}
if (!errmsg && global_system_variables.log_warnings)
- errmsg = "slave SQL thread was killed";
+ {
+ sql_print_information("Error reading relay log event: %s",
+ "slave SQL thread was killed");
+ DBUG_RETURN(0);
+ }
err:
if (errmsg)
@@ -4456,9 +4960,9 @@ void rotate_relay_log(MASTER_INFO* mi)
DBUG_ENTER("rotate_relay_log");
RELAY_LOG_INFO* rli= &mi->rli;
- lock_slave_threads(mi);
- pthread_mutex_lock(&mi->data_lock);
- pthread_mutex_lock(&rli->data_lock);
+ /* We don't lock rli->run_lock. This would lead to deadlocks. */
+ pthread_mutex_lock(&mi->run_lock);
+
/*
We need to test inited because otherwise, new_file() will attempt to lock
LOCK_log, which may not be inited (if we're not a slave).
@@ -4487,14 +4991,12 @@ void rotate_relay_log(MASTER_INFO* mi)
*/
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
end:
- pthread_mutex_unlock(&rli->data_lock);
- pthread_mutex_unlock(&mi->data_lock);
- unlock_slave_threads(mi);
+ pthread_mutex_unlock(&mi->run_lock);
DBUG_VOID_RETURN;
}
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class I_List_iterator<i_string>;
template class I_List_iterator<i_string_pair>;
#endif
diff --git a/sql/slave.h b/sql/slave.h
index 5a85e26d9ad..c41234ab2ed 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -1,15 +1,15 @@
/* Copyright (C) 2000-2003 MySQL AB
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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 */
@@ -93,11 +93,6 @@ extern my_bool opt_log_slave_updates;
extern ulonglong relay_log_space_limit;
struct st_master_info;
-enum enum_binlog_formats {
- BINLOG_FORMAT_CURRENT=0, /* 0 is important for easy 'if (mi->old_format)' */
- BINLOG_FORMAT_323_LESS_57,
- BINLOG_FORMAT_323_GEQ_57 };
-
/*
3 possible values for MASTER_INFO::slave_running and
RELAY_LOG_INFO::slave_running.
@@ -214,6 +209,8 @@ typedef struct st_relay_log_info
ulonglong group_relay_log_pos;
char event_relay_log_name[FN_REFLEN];
ulonglong event_relay_log_pos;
+ ulonglong future_event_relay_log_pos;
+
/*
Original log name and position of the group we're currently executing
(whose coordinates are group_relay_log_name/pos in the relay log)
@@ -295,6 +292,7 @@ typedef struct st_relay_log_info
UNTIL_LOG_NAMES_CMP_EQUAL= 0, UNTIL_LOG_NAMES_CMP_GREATER= 1
} until_log_names_cmp_result;
+ char cached_charset[6];
/*
trans_retries varies between 0 to slave_transaction_retries and counts how
many times the slave has retried the present transaction; gets reset to 0
@@ -327,12 +325,14 @@ typedef struct st_relay_log_info
until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
}
- inline void inc_event_relay_log_pos(ulonglong val)
+ inline void inc_event_relay_log_pos()
{
- event_relay_log_pos+= val;
+ event_relay_log_pos= future_event_relay_log_pos;
}
- void inc_group_relay_log_pos(ulonglong val, ulonglong log_pos, bool skip_lock=0);
+ void inc_group_relay_log_pos(ulonglong log_pos,
+ bool skip_lock=0);
+
int wait_for_pos(THD* thd, String* log_name, longlong log_pos,
longlong timeout);
void close_temporary_tables();
@@ -344,6 +344,14 @@ typedef struct st_relay_log_info
return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos :
group_relay_log_pos);
}
+ /*
+ Last charset (6 bytes) seen by slave SQL thread is cached here; it helps
+ the thread save 3 get_charset() per Query_log_event if the charset is not
+ changing from event to event (common situation).
+ When the 6 bytes are equal to 0 is used to mean "cache is invalidated".
+ */
+ void cached_charset_invalidate();
+ bool cached_charset_compare(char *charset);
} RELAY_LOG_INFO;
@@ -392,11 +400,11 @@ typedef struct st_master_info
my_bool ssl; // enables use of SSL connection if true
char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
-
+
my_off_t master_log_pos;
File fd; // we keep the file open, so we need to remember the file pointer
IO_CACHE file;
-
+
pthread_mutex_t data_lock,run_lock;
pthread_cond_t data_cond,start_cond,stop_cond;
THD *io_thd;
@@ -409,11 +417,10 @@ typedef struct st_master_info
int events_till_abort;
#endif
bool inited;
- enum enum_binlog_formats old_format;
volatile bool abort_slave;
volatile uint slave_running;
volatile ulong slave_run_id;
- /*
+ /*
The difference in seconds between the clock of the master and the clock of
the slave (second - first). It must be signed as it may be <0 or >0.
clock_diff_with_master is computed when the I/O thread starts; for this the
@@ -422,16 +429,16 @@ typedef struct st_master_info
clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master
*/
- long clock_diff_with_master;
-
+ long clock_diff_with_master;
+
st_master_info()
- :ssl(0), fd(-1), io_thd(0), inited(0), old_format(BINLOG_FORMAT_CURRENT),
+ :ssl(0), fd(-1), io_thd(0), inited(0),
abort_slave(0),slave_running(0), slave_run_id(0)
{
host[0] = 0; user[0] = 0; password[0] = 0;
ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
ssl_cipher[0]= 0; ssl_key[0]= 0;
-
+
bzero((char*) &file, sizeof(file));
pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
@@ -518,8 +525,8 @@ int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
void table_rule_ent_hash_to_str(String* s, HASH* h);
void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a);
-int show_master_info(THD* thd, MASTER_INFO* mi);
-int show_binlog_info(THD* thd);
+bool show_master_info(THD* thd, MASTER_INFO* mi);
+bool show_binlog_info(THD* thd);
/* See if the query uses any tables that should not be replicated */
bool tables_ok(THD* thd, TABLE_LIST* tables);
@@ -551,16 +558,18 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
bool abort_if_no_master_info_file,
int thread_mask);
void end_master_info(MASTER_INFO* mi);
-int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname);
void end_relay_log_info(RELAY_LOG_INFO* rli);
void lock_slave_threads(MASTER_INFO* mi);
void unlock_slave_threads(MASTER_INFO* mi);
void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse);
int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos,
- bool need_data_lock, const char** errmsg);
+ bool need_data_lock, const char** errmsg,
+ bool look_for_description_event);
int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
const char** errmsg);
+void set_slave_thread_options(THD* thd);
+void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli);
void rotate_relay_log(MASTER_INFO* mi);
extern "C" pthread_handler_decl(handle_slave_io,arg);
diff --git a/sql/sp.cc b/sql/sp.cc
new file mode 100644
index 00000000000..80b18571d7d
--- /dev/null
+++ b/sql/sp.cc
@@ -0,0 +1,1675 @@
+/* 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 */
+
+
+#include "mysql_priv.h"
+#include "sp.h"
+#include "sp_head.h"
+#include "sp_cache.h"
+#include "sql_trigger.h"
+
+static bool
+create_string(THD *thd, String *buf,
+ int sp_type,
+ sp_name *name,
+ const char *params, ulong paramslen,
+ const char *returns, ulong returnslen,
+ const char *body, ulong bodylen,
+ st_sp_chistics *chistics);
+
+/*
+ *
+ * DB storage of Stored PROCEDUREs and FUNCTIONs
+ *
+ */
+
+enum
+{
+ MYSQL_PROC_FIELD_DB = 0,
+ MYSQL_PROC_FIELD_NAME,
+ MYSQL_PROC_FIELD_TYPE,
+ MYSQL_PROC_FIELD_SPECIFIC_NAME,
+ MYSQL_PROC_FIELD_LANGUAGE,
+ MYSQL_PROC_FIELD_ACCESS,
+ MYSQL_PROC_FIELD_DETERMINISTIC,
+ MYSQL_PROC_FIELD_SECURITY_TYPE,
+ MYSQL_PROC_FIELD_PARAM_LIST,
+ MYSQL_PROC_FIELD_RETURNS,
+ MYSQL_PROC_FIELD_BODY,
+ MYSQL_PROC_FIELD_DEFINER,
+ MYSQL_PROC_FIELD_CREATED,
+ MYSQL_PROC_FIELD_MODIFIED,
+ MYSQL_PROC_FIELD_SQL_MODE,
+ MYSQL_PROC_FIELD_COMMENT,
+ MYSQL_PROC_FIELD_COUNT
+};
+
+bool mysql_proc_table_exists= 1;
+
+/* Tells what SP_DEFAULT_ACCESS should be mapped to */
+#define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL
+
+
+/*
+ Close mysql.proc, opened with open_proc_table_for_read().
+
+ SYNOPSIS
+ close_proc_table()
+ thd Thread context
+ backup Pointer to Open_tables_state instance which holds
+ information about tables which were open before we
+ decided to access mysql.proc.
+*/
+
+void close_proc_table(THD *thd, Open_tables_state *backup)
+{
+ close_thread_tables(thd);
+ thd->restore_backup_open_tables_state(backup);
+}
+
+
+/*
+ Open the mysql.proc table for read.
+
+ SYNOPSIS
+ open_proc_table_for_read()
+ thd Thread context
+ backup Pointer to Open_tables_state instance where information about
+ currently open tables will be saved, and from which will be
+ restored when we will end work with mysql.proc.
+
+ NOTES
+ Thanks to restrictions which we put on opening and locking of
+ this table for writing, we can open and lock it for reading
+ even when we already have some other tables open and locked.
+ One must call close_proc_table() to close table opened with
+ this call.
+
+ RETURN
+ 0 Error
+ # Pointer to TABLE object of mysql.proc
+*/
+
+TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup)
+{
+ TABLE_LIST tables;
+ TABLE *table;
+ bool not_used;
+ DBUG_ENTER("open_proc_table");
+
+ /*
+ Speed up things if mysql.proc doesn't exists. mysql_proc_table_exists
+ is set when we create or read stored procedure or on flush privileges.
+ */
+ if (!mysql_proc_table_exists)
+ DBUG_RETURN(0);
+
+ thd->reset_n_backup_open_tables_state(backup);
+
+ bzero((char*) &tables, sizeof(tables));
+ tables.db= (char*) "mysql";
+ tables.table_name= tables.alias= (char*)"proc";
+ if (!(table= open_table(thd, &tables, thd->mem_root, &not_used,
+ MYSQL_LOCK_IGNORE_FLUSH)))
+ {
+ thd->restore_backup_open_tables_state(backup);
+ mysql_proc_table_exists= 0;
+ DBUG_RETURN(0);
+ }
+
+ DBUG_ASSERT(table->s->system_table);
+
+ table->reginfo.lock_type= TL_READ;
+ /*
+ We have to ensure we are not blocked by a flush tables, as this
+ could lead to a deadlock if we have other tables opened.
+ */
+ if (!(thd->lock= mysql_lock_tables(thd, &table, 1,
+ MYSQL_LOCK_IGNORE_FLUSH, &not_used)))
+ {
+ close_proc_table(thd, backup);
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(table);
+}
+
+
+/*
+ Open the mysql.proc table for update.
+
+ SYNOPSIS
+ open_proc_table_for_update()
+ thd Thread context
+
+ NOTES
+ Table opened with this call should closed using close_thread_tables().
+
+ RETURN
+ 0 Error
+ # Pointer to TABLE object of mysql.proc
+*/
+
+static TABLE *open_proc_table_for_update(THD *thd)
+{
+ TABLE_LIST tables;
+ TABLE *table;
+ DBUG_ENTER("open_proc_table");
+
+ bzero((char*) &tables, sizeof(tables));
+ tables.db= (char*) "mysql";
+ tables.table_name= tables.alias= (char*)"proc";
+ tables.lock_type= TL_WRITE;
+
+ table= open_ltable(thd, &tables, TL_WRITE);
+
+ /*
+ Under explicit LOCK TABLES or in prelocked mode we should not
+ say that mysql.proc table does not exist if we are unable to
+ open and lock it for writing since this condition may be
+ transient.
+ */
+ if (!(thd->locked_tables || thd->prelocked_mode) || table)
+ mysql_proc_table_exists= test(table);
+
+ DBUG_RETURN(table);
+}
+
+
+/*
+ Find row in open mysql.proc table representing stored routine.
+
+ SYNOPSIS
+ db_find_routine_aux()
+ thd Thread context
+ type Type of routine to find (function or procedure)
+ name Name of routine
+ table TABLE object for open mysql.proc table.
+
+ RETURN VALUE
+ SP_OK - Routine found
+ SP_KEY_NOT_FOUND- No routine with given name
+*/
+
+static int
+db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
+{
+ byte key[MAX_KEY_LENGTH]; // db, name, optional key length type
+ DBUG_ENTER("db_find_routine_aux");
+ DBUG_PRINT("enter", ("type: %d name: %*s",
+ type, name->m_name.length, name->m_name.str));
+
+ /*
+ Create key to find row. We have to use field->store() to be able to
+ handle VARCHAR and CHAR fields.
+ Assumption here is that the three first fields in the table are
+ 'db', 'name' and 'type' and the first key is the primary key over the
+ same fields.
+ */
+ if (name->m_name.length > table->field[1]->field_length)
+ DBUG_RETURN(SP_KEY_NOT_FOUND);
+ table->field[0]->store(name->m_db.str, name->m_db.length, &my_charset_bin);
+ table->field[1]->store(name->m_name.str, name->m_name.length,
+ &my_charset_bin);
+ table->field[2]->store((longlong) type, TRUE);
+ key_copy(key, table->record[0], table->key_info,
+ table->key_info->key_length);
+
+ if (table->file->index_read_idx(table->record[0], 0,
+ key, table->key_info->key_length,
+ HA_READ_KEY_EXACT))
+ DBUG_RETURN(SP_KEY_NOT_FOUND);
+
+ DBUG_RETURN(SP_OK);
+}
+
+
+/*
+ Find routine definition in mysql.proc table and create corresponding
+ sp_head object for it.
+
+ SYNOPSIS
+ db_find_routine()
+ thd Thread context
+ type Type of routine (TYPE_ENUM_PROCEDURE/...)
+ name Name of routine
+ sphp Out parameter in which pointer to created sp_head
+ object is returned (0 in case of error).
+
+ NOTE
+ This function may damage current LEX during execution, so it is good
+ idea to create temporary LEX and make it active before calling it.
+
+ RETURN VALUE
+ 0 - Success
+ non-0 - Error (may be one of special codes like SP_KEY_NOT_FOUND)
+*/
+
+static int
+db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
+{
+ extern int yyparse(void *thd);
+ TABLE *table;
+ const char *params, *returns, *body;
+ int ret;
+ const char *definer;
+ longlong created;
+ longlong modified;
+ st_sp_chistics chistics;
+ char *ptr;
+ uint length;
+ char buff[65];
+ String str(buff, sizeof(buff), &my_charset_bin);
+ ulong sql_mode;
+ Open_tables_state open_tables_state_backup;
+ DBUG_ENTER("db_find_routine");
+ DBUG_PRINT("enter", ("type: %d name: %*s",
+ type, name->m_name.length, name->m_name.str));
+
+ *sphp= 0; // In case of errors
+ if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup)))
+ DBUG_RETURN(SP_OPEN_TABLE_FAILED);
+
+ if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK)
+ goto done;
+
+ if (table->s->fields != MYSQL_PROC_FIELD_COUNT)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+
+ bzero((char *)&chistics, sizeof(chistics));
+ if ((ptr= get_field(thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+ switch (ptr[0]) {
+ case 'N':
+ chistics.daccess= SP_NO_SQL;
+ break;
+ case 'C':
+ chistics.daccess= SP_CONTAINS_SQL;
+ break;
+ case 'R':
+ chistics.daccess= SP_READS_SQL_DATA;
+ break;
+ case 'M':
+ chistics.daccess= SP_MODIFIES_SQL_DATA;
+ break;
+ default:
+ chistics.daccess= SP_DEFAULT_ACCESS_MAPPING;
+ }
+
+ if ((ptr= get_field(thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_DETERMINISTIC])) == NULL)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+ chistics.detistic= (ptr[0] == 'N' ? FALSE : TRUE);
+
+ if ((ptr= get_field(thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+ chistics.suid= (ptr[0] == 'I' ? SP_IS_NOT_SUID : SP_IS_SUID);
+
+ if ((params= get_field(thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_PARAM_LIST])) == NULL)
+ {
+ params= "";
+ }
+
+ if (type == TYPE_ENUM_PROCEDURE)
+ returns= "";
+ else if ((returns= get_field(thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_RETURNS])) == NULL)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+
+ if ((body= get_field(thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_BODY])) == NULL)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+
+ // Get additional information
+ if ((definer= get_field(thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+
+ modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int();
+ created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int();
+
+ sql_mode= (ulong) table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
+
+ table->field[MYSQL_PROC_FIELD_COMMENT]->val_str(&str, &str);
+
+ ptr= 0;
+ if ((length= str.length()))
+ ptr= thd->strmake(str.ptr(), length);
+ chistics.comment.str= ptr;
+ chistics.comment.length= length;
+
+ close_proc_table(thd, &open_tables_state_backup);
+ table= 0;
+
+ {
+ String defstr;
+ LEX *oldlex= thd->lex;
+ char olddb[128];
+ bool dbchanged;
+ enum enum_sql_command oldcmd= thd->lex->sql_command;
+ ulong old_sql_mode= thd->variables.sql_mode;
+ ha_rows select_limit= thd->variables.select_limit;
+
+ thd->variables.sql_mode= sql_mode;
+ thd->variables.select_limit= HA_POS_ERROR;
+
+ defstr.set_charset(system_charset_info);
+ if (!create_string(thd, &defstr,
+ type,
+ name,
+ params, strlen(params),
+ returns, strlen(returns),
+ body, strlen(body),
+ &chistics))
+ {
+ ret= SP_INTERNAL_ERROR;
+ goto done;
+ }
+
+ dbchanged= FALSE;
+ if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb),
+ 1, &dbchanged)))
+ goto done;
+
+ {
+ /* This is something of a kludge. We need to initialize some fields
+ * in thd->lex (the unit and master stuff), and the easiest way to
+ * do it is, is to call mysql_init_query(), but this unfortunately
+ * resets teh value_list where we keep the CALL parameters. So we
+ * copy the list and then restore it. (... and found_semicolon too).
+ */
+ List<Item> tmpvals= thd->lex->value_list;
+ char *tmpfsc= thd->lex->found_semicolon;
+
+ lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
+ thd->lex->value_list= tmpvals;
+ thd->lex->found_semicolon= tmpfsc;
+ }
+
+ if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
+ {
+ LEX *newlex= thd->lex;
+ sp_head *sp= newlex->sphead;
+
+ if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
+ goto done;
+ if (sp)
+ {
+ delete sp;
+ newlex->sphead= NULL;
+ }
+ ret= SP_PARSE_ERROR;
+ }
+ else
+ {
+ if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
+ goto done;
+ *sphp= thd->lex->sphead;
+ (*sphp)->set_info((char *)definer, (uint)strlen(definer),
+ created, modified, &chistics, sql_mode);
+ (*sphp)->optimize();
+ }
+ thd->lex->sql_command= oldcmd;
+ thd->variables.sql_mode= old_sql_mode;
+ thd->variables.select_limit= select_limit;
+ }
+
+ done:
+ if (table)
+ close_proc_table(thd, &open_tables_state_backup);
+ DBUG_RETURN(ret);
+}
+
+
+static void
+sp_returns_type(THD *thd, String &result, sp_head *sp)
+{
+ TABLE table;
+ Field *field;
+ bzero(&table, sizeof(table));
+ table.in_use= thd;
+ table.s = &table.share_not_to_be_used;
+ field= sp->make_field(0, 0, &table);
+ field->sql_type(result);
+ delete field;
+}
+
+static int
+db_create_routine(THD *thd, int type, sp_head *sp)
+{
+ int ret;
+ TABLE *table;
+ char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
+ char olddb[128];
+ bool dbchanged;
+ DBUG_ENTER("db_create_routine");
+ DBUG_PRINT("enter", ("type: %d name: %*s",type,sp->m_name.length,sp->m_name.str));
+
+ dbchanged= FALSE;
+ if ((ret= sp_use_new_db(thd, sp->m_db.str, olddb, sizeof(olddb),
+ 0, &dbchanged)))
+ {
+ ret= SP_NO_DB_ERROR;
+ goto done;
+ }
+
+ if (!(table= open_proc_table_for_update(thd)))
+ ret= SP_OPEN_TABLE_FAILED;
+ else
+ {
+ restore_record(table, s->default_values); // Get default values for fields
+ strxmov(definer, thd->priv_user, "@", thd->priv_host, NullS);
+
+ if (table->s->fields != MYSQL_PROC_FIELD_COUNT)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+ if (sp->m_name.length > table->field[MYSQL_PROC_FIELD_NAME]->field_length)
+ {
+ ret= SP_BAD_IDENTIFIER;
+ goto done;
+ }
+ if (sp->m_body.length > table->field[MYSQL_PROC_FIELD_BODY]->field_length)
+ {
+ ret= SP_BODY_TOO_LONG;
+ goto done;
+ }
+ table->field[MYSQL_PROC_FIELD_DB]->
+ store(sp->m_db.str, sp->m_db.length, system_charset_info);
+ table->field[MYSQL_PROC_FIELD_NAME]->
+ store(sp->m_name.str, sp->m_name.length, system_charset_info);
+ table->field[MYSQL_PROC_FIELD_TYPE]->
+ store((longlong)type);
+ table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
+ store(sp->m_name.str, sp->m_name.length, system_charset_info);
+ if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS)
+ table->field[MYSQL_PROC_FIELD_ACCESS]->
+ store((longlong)sp->m_chistics->daccess);
+ table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
+ store((longlong)(sp->m_chistics->detistic ? 1 : 2));
+ if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID)
+ table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
+ store((longlong)sp->m_chistics->suid);
+ table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
+ store(sp->m_params.str, sp->m_params.length, system_charset_info);
+ if (sp->m_type == TYPE_ENUM_FUNCTION)
+ {
+ String retstr(64);
+ sp_returns_type(thd, retstr, sp);
+ table->field[MYSQL_PROC_FIELD_RETURNS]->
+ store(retstr.ptr(), retstr.length(), system_charset_info);
+ }
+ table->field[MYSQL_PROC_FIELD_BODY]->
+ store(sp->m_body.str, sp->m_body.length, system_charset_info);
+ table->field[MYSQL_PROC_FIELD_DEFINER]->
+ store(definer, (uint)strlen(definer), system_charset_info);
+ ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
+ ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
+ table->field[MYSQL_PROC_FIELD_SQL_MODE]->
+ store((longlong)thd->variables.sql_mode);
+ if (sp->m_chistics->comment.str)
+ table->field[MYSQL_PROC_FIELD_COMMENT]->
+ store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
+ system_charset_info);
+
+ if (!trust_routine_creators && mysql_bin_log.is_open())
+ {
+ if (!sp->m_chistics->detistic)
+ {
+ /*
+ Note that for a _function_ this test is not enough; one could use
+ a non-deterministic read-only function in an update statement.
+ */
+ enum enum_sp_data_access access=
+ (sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
+ SP_DEFAULT_ACCESS_MAPPING : sp->m_chistics->daccess;
+ if (access == SP_CONTAINS_SQL ||
+ access == SP_MODIFIES_SQL_DATA)
+ {
+ my_message(ER_BINLOG_UNSAFE_ROUTINE,
+ ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
+ ret= SP_INTERNAL_ERROR;
+ goto done;
+ }
+ }
+ if (!(thd->master_access & SUPER_ACL))
+ {
+ my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,
+ ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0));
+ ret= SP_INTERNAL_ERROR;
+ goto done;
+ }
+ }
+
+ ret= SP_OK;
+ if (table->file->write_row(table->record[0]))
+ ret= SP_WRITE_ROW_FAILED;
+ else if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ /* Such a statement can always go directly to binlog, no trans cache */
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+
+ }
+
+done:
+ close_thread_tables(thd);
+ if (dbchanged)
+ (void)mysql_change_db(thd, olddb, 1);
+ DBUG_RETURN(ret);
+}
+
+
+static int
+db_drop_routine(THD *thd, int type, sp_name *name)
+{
+ TABLE *table;
+ int ret;
+ DBUG_ENTER("db_drop_routine");
+ DBUG_PRINT("enter", ("type: %d name: %*s",
+ type, name->m_name.length, name->m_name.str));
+
+ if (!(table= open_proc_table_for_update(thd)))
+ DBUG_RETURN(SP_OPEN_TABLE_FAILED);
+ if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
+ {
+ if (table->file->delete_row(table->record[0]))
+ ret= SP_DELETE_ROW_FAILED;
+ }
+ close_thread_tables(thd);
+ DBUG_RETURN(ret);
+}
+
+
+static int
+db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
+{
+ TABLE *table;
+ int ret;
+ bool opened;
+ DBUG_ENTER("db_update_routine");
+ DBUG_PRINT("enter", ("type: %d name: %*s",
+ type, name->m_name.length, name->m_name.str));
+
+ if (!(table= open_proc_table_for_update(thd)))
+ DBUG_RETURN(SP_OPEN_TABLE_FAILED);
+ if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
+ {
+ store_record(table,record[1]);
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+ ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
+ if (chistics->suid != SP_IS_DEFAULT_SUID)
+ table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
+ store((longlong)chistics->suid);
+ if (chistics->daccess != SP_DEFAULT_ACCESS)
+ table->field[MYSQL_PROC_FIELD_ACCESS]->
+ store((longlong)chistics->daccess);
+ if (chistics->comment.str)
+ table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str,
+ chistics->comment.length,
+ system_charset_info);
+ if ((table->file->update_row(table->record[1],table->record[0])))
+ ret= SP_WRITE_ROW_FAILED;
+ }
+ close_thread_tables(thd);
+ DBUG_RETURN(ret);
+}
+
+
+struct st_used_field
+{
+ const char *field_name;
+ uint field_length;
+ enum enum_field_types field_type;
+ Field *field;
+};
+
+static struct st_used_field init_fields[]=
+{
+ { "Db", NAME_LEN, MYSQL_TYPE_STRING, 0},
+ { "Name", NAME_LEN, MYSQL_TYPE_STRING, 0},
+ { "Type", 9, MYSQL_TYPE_STRING, 0},
+ { "Definer", 77, MYSQL_TYPE_STRING, 0},
+ { "Modified", 0, MYSQL_TYPE_TIMESTAMP, 0},
+ { "Created", 0, MYSQL_TYPE_TIMESTAMP, 0},
+ { "Security_type", 1, MYSQL_TYPE_STRING, 0},
+ { "Comment", NAME_LEN, MYSQL_TYPE_STRING, 0},
+ { 0, 0, MYSQL_TYPE_STRING, 0}
+};
+
+
+static int
+print_field_values(THD *thd, TABLE *table,
+ struct st_used_field *used_fields,
+ int type, const char *wild)
+{
+ Protocol *protocol= thd->protocol;
+
+ if (table->field[MYSQL_PROC_FIELD_TYPE]->val_int() == type)
+ {
+ String db_string;
+ String name_string;
+ struct st_used_field *used_field= used_fields;
+
+ if (get_field(thd->mem_root, used_field->field, &db_string))
+ db_string.set_ascii("", 0);
+ used_field+= 1;
+ get_field(thd->mem_root, used_field->field, &name_string);
+
+ if (!wild || !wild[0] || !wild_compare(name_string.ptr(), wild, 0))
+ {
+ protocol->prepare_for_resend();
+ protocol->store(&db_string);
+ protocol->store(&name_string);
+ for (used_field++;
+ used_field->field_name;
+ used_field++)
+ {
+ switch (used_field->field_type) {
+ case MYSQL_TYPE_TIMESTAMP:
+ {
+ TIME tmp_time;
+
+ bzero((char *)&tmp_time, sizeof(tmp_time));
+ ((Field_timestamp *) used_field->field)->get_time(&tmp_time);
+ protocol->store(&tmp_time);
+ }
+ break;
+ default:
+ {
+ String tmp_string;
+
+ get_field(thd->mem_root, used_field->field, &tmp_string);
+ protocol->store(&tmp_string);
+ }
+ break;
+ }
+ }
+ if (protocol->write())
+ return SP_INTERNAL_ERROR;
+ }
+ }
+ return SP_OK;
+}
+
+
+static int
+db_show_routine_status(THD *thd, int type, const char *wild)
+{
+ TABLE *table;
+ TABLE_LIST tables;
+ int res;
+ DBUG_ENTER("db_show_routine_status");
+
+ memset(&tables, 0, sizeof(tables));
+ tables.db= (char*)"mysql";
+ tables.table_name= tables.alias= (char*)"proc";
+
+ if (! (table= open_ltable(thd, &tables, TL_READ)))
+ {
+ res= SP_OPEN_TABLE_FAILED;
+ goto done;
+ }
+ else
+ {
+ Item *item;
+ List<Item> field_list;
+ struct st_used_field *used_field;
+ TABLE_LIST *leaves= 0;
+ st_used_field used_fields[array_elements(init_fields)];
+
+ memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields));
+ /* Init header */
+ for (used_field= &used_fields[0];
+ used_field->field_name;
+ used_field++)
+ {
+ switch (used_field->field_type) {
+ case MYSQL_TYPE_TIMESTAMP:
+ field_list.push_back(item=new Item_datetime(used_field->field_name));
+ break;
+ default:
+ field_list.push_back(item=new Item_empty_string(used_field->field_name,
+ used_field->
+ field_length));
+ break;
+ }
+ }
+ /* Print header */
+ if (thd->protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF))
+ {
+ res= SP_INTERNAL_ERROR;
+ goto err_case;
+ }
+
+ /*
+ Init fields
+
+ tables is not VIEW for sure => we can pass 0 as condition
+ */
+ thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
+ setup_tables(thd, &thd->lex->select_lex.context,
+ &thd->lex->select_lex.top_join_list,
+ &tables, 0, &leaves, FALSE);
+ for (used_field= &used_fields[0];
+ used_field->field_name;
+ used_field++)
+ {
+ Item_field *field= new Item_field(&thd->lex->select_lex.context,
+ "mysql", "proc",
+ used_field->field_name);
+ if (!field ||
+ !(used_field->field= find_field_in_tables(thd, field, &tables, NULL,
+ 0, REPORT_ALL_ERRORS, 1,
+ TRUE)))
+ {
+ res= SP_INTERNAL_ERROR;
+ goto err_case1;
+ }
+ }
+
+ table->file->ha_index_init(0);
+ if ((res= table->file->index_first(table->record[0])))
+ {
+ res= (res == HA_ERR_END_OF_FILE) ? 0 : SP_INTERNAL_ERROR;
+ goto err_case1;
+ }
+ if ((res= print_field_values(thd, table, used_fields, type, wild)))
+ goto err_case1;
+ while (!table->file->index_next(table->record[0]))
+ {
+ if ((res= print_field_values(thd, table, used_fields, type, wild)))
+ goto err_case1;
+ }
+ res= SP_OK;
+ }
+
+err_case1:
+ send_eof(thd);
+err_case:
+ table->file->ha_index_end();
+ close_thread_tables(thd);
+done:
+ DBUG_RETURN(res);
+}
+
+
+/* Drop all routines in database 'db' */
+int
+sp_drop_db_routines(THD *thd, char *db)
+{
+ TABLE *table;
+ byte key[64]; // db
+ uint keylen;
+ int ret;
+ DBUG_ENTER("sp_drop_db_routines");
+ DBUG_PRINT("enter", ("db: %s", db));
+
+ // Put the key used to read the row together
+ keylen= strlen(db);
+ if (keylen > 64)
+ keylen= 64;
+ memcpy(key, db, keylen);
+ memset(key+keylen, (int)' ', 64-keylen); // Pad with space
+ keylen= sizeof(key);
+
+ ret= SP_OPEN_TABLE_FAILED;
+ if (!(table= open_proc_table_for_update(thd)))
+ goto err;
+
+ ret= SP_OK;
+ table->file->ha_index_init(0);
+ if (! table->file->index_read(table->record[0],
+ key, keylen, HA_READ_KEY_EXACT))
+ {
+ int nxtres;
+ bool deleted= FALSE;
+
+ do
+ {
+ if (! table->file->delete_row(table->record[0]))
+ deleted= TRUE; /* We deleted something */
+ else
+ {
+ ret= SP_DELETE_ROW_FAILED;
+ nxtres= 0;
+ break;
+ }
+ } while (! (nxtres= table->file->index_next_same(table->record[0],
+ key, keylen)));
+ if (nxtres != HA_ERR_END_OF_FILE)
+ ret= SP_KEY_NOT_FOUND;
+ if (deleted)
+ sp_cache_invalidate();
+ }
+ table->file->ha_index_end();
+
+ close_thread_tables(thd);
+
+err:
+ DBUG_RETURN(ret);
+}
+
+
+/*****************************************************************************
+ PROCEDURE
+******************************************************************************/
+
+/*
+ Obtain object representing stored procedure by its name from
+ stored procedures cache and looking into mysql.proc if needed.
+
+ SYNOPSIS
+ sp_find_procedure()
+ thd - thread context
+ name - name of procedure
+ cache_only - if true perform cache-only lookup
+ (Don't look in mysql.proc).
+
+ TODO
+ We should consider merging of sp_find_procedure() and
+ sp_find_function() into one sp_find_routine() function
+ (the same applies to other similarly paired functions).
+
+ RETURN VALUE
+ Non-0 pointer to sp_head object for the procedure, or
+ 0 - in case of error.
+*/
+
+sp_head *
+sp_find_procedure(THD *thd, sp_name *name, bool cache_only)
+{
+ sp_head *sp;
+ DBUG_ENTER("sp_find_procedure");
+ DBUG_PRINT("enter", ("name: %*s.%*s",
+ name->m_db.length, name->m_db.str,
+ name->m_name.length, name->m_name.str));
+
+ if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name)) && !cache_only)
+ {
+ if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &sp) == SP_OK)
+ sp_cache_insert(&thd->sp_proc_cache, sp);
+ }
+
+ DBUG_RETURN(sp);
+}
+
+
+int
+sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
+{
+ TABLE_LIST *table;
+ bool result= 0;
+ DBUG_ENTER("sp_exists_routine");
+ for (table= tables; table; table= table->next_global)
+ {
+ sp_name *name;
+ LEX_STRING lex_db;
+ LEX_STRING lex_name;
+ lex_db.length= strlen(table->db);
+ lex_name.length= strlen(table->table_name);
+ lex_db.str= thd->strmake(table->db, lex_db.length);
+ lex_name.str= thd->strmake(table->table_name, lex_name.length);
+ name= new sp_name(lex_db, lex_name);
+ name->init_qname(thd);
+ if (sp_find_procedure(thd, name) != NULL ||
+ sp_find_function(thd, name) != NULL)
+ {
+ if (any)
+ DBUG_RETURN(1);
+ result= 1;
+ }
+ else if (!any)
+ {
+ if (!no_error)
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE",
+ table->table_name);
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(0);
+ }
+ }
+ DBUG_RETURN(result);
+}
+
+
+int
+sp_create_procedure(THD *thd, sp_head *sp)
+{
+ int ret;
+ DBUG_ENTER("sp_create_procedure");
+ DBUG_PRINT("enter", ("name: %*s", sp->m_name.length, sp->m_name.str));
+
+ ret= db_create_routine(thd, TYPE_ENUM_PROCEDURE, sp);
+ DBUG_RETURN(ret);
+}
+
+
+int
+sp_drop_procedure(THD *thd, sp_name *name)
+{
+ int ret;
+ DBUG_ENTER("sp_drop_procedure");
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
+
+ ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name);
+ if (!ret)
+ sp_cache_invalidate();
+ DBUG_RETURN(ret);
+}
+
+
+int
+sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics)
+{
+ int ret;
+ DBUG_ENTER("sp_update_procedure");
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
+
+ ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, chistics);
+ if (!ret)
+ sp_cache_invalidate();
+ DBUG_RETURN(ret);
+}
+
+
+int
+sp_show_create_procedure(THD *thd, sp_name *name)
+{
+ sp_head *sp;
+ DBUG_ENTER("sp_show_create_procedure");
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
+
+ if ((sp= sp_find_procedure(thd, name)))
+ {
+ int ret= sp->show_create_procedure(thd);
+
+ DBUG_RETURN(ret);
+ }
+
+ DBUG_RETURN(SP_KEY_NOT_FOUND);
+}
+
+
+int
+sp_show_status_procedure(THD *thd, const char *wild)
+{
+ int ret;
+ DBUG_ENTER("sp_show_status_procedure");
+
+ ret= db_show_routine_status(thd, TYPE_ENUM_PROCEDURE, wild);
+ DBUG_RETURN(ret);
+}
+
+
+/*****************************************************************************
+ FUNCTION
+******************************************************************************/
+
+/*
+ Obtain object representing stored function by its name from
+ stored functions cache and looking into mysql.proc if needed.
+
+ SYNOPSIS
+ sp_find_function()
+ thd - thread context
+ name - name of function
+ cache_only - if true perform cache-only lookup
+ (Don't look in mysql.proc).
+
+ NOTE
+ See TODO section for sp_find_procedure().
+
+ RETURN VALUE
+ Non-0 pointer to sp_head object for the function, or
+ 0 - in case of error.
+*/
+
+sp_head *
+sp_find_function(THD *thd, sp_name *name, bool cache_only)
+{
+ sp_head *sp;
+ DBUG_ENTER("sp_find_function");
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
+
+ if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name)) &&
+ !cache_only)
+ {
+ if (db_find_routine(thd, TYPE_ENUM_FUNCTION, name, &sp) == SP_OK)
+ sp_cache_insert(&thd->sp_func_cache, sp);
+ }
+ DBUG_RETURN(sp);
+}
+
+
+int
+sp_create_function(THD *thd, sp_head *sp)
+{
+ int ret;
+ DBUG_ENTER("sp_create_function");
+ DBUG_PRINT("enter", ("name: %*s", sp->m_name.length, sp->m_name.str));
+
+ ret= db_create_routine(thd, TYPE_ENUM_FUNCTION, sp);
+ DBUG_RETURN(ret);
+}
+
+
+int
+sp_drop_function(THD *thd, sp_name *name)
+{
+ int ret;
+ DBUG_ENTER("sp_drop_function");
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
+
+ ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name);
+ if (!ret)
+ sp_cache_invalidate();
+ DBUG_RETURN(ret);
+}
+
+
+int
+sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics)
+{
+ int ret;
+ DBUG_ENTER("sp_update_procedure");
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
+
+ ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, chistics);
+ if (!ret)
+ sp_cache_invalidate();
+ DBUG_RETURN(ret);
+}
+
+
+int
+sp_show_create_function(THD *thd, sp_name *name)
+{
+ sp_head *sp;
+ DBUG_ENTER("sp_show_create_function");
+ DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
+
+ if ((sp= sp_find_function(thd, name)))
+ {
+ int ret= sp->show_create_function(thd);
+
+ DBUG_RETURN(ret);
+ }
+ DBUG_RETURN(SP_KEY_NOT_FOUND);
+}
+
+
+int
+sp_show_status_function(THD *thd, const char *wild)
+{
+ int ret;
+ DBUG_ENTER("sp_show_status_function");
+ ret= db_show_routine_status(thd, TYPE_ENUM_FUNCTION, wild);
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Structure that represents element in the set of stored routines
+ used by statement or routine.
+*/
+struct Sroutine_hash_entry;
+
+struct Sroutine_hash_entry
+{
+ /* Set key consisting of one-byte routine type and quoted routine name. */
+ LEX_STRING key;
+ /*
+ Next element in list linking all routines in set. See also comments
+ for LEX::sroutine/sroutine_list and sp_head::m_sroutines.
+ */
+ Sroutine_hash_entry *next;
+};
+
+
+extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first)
+{
+ Sroutine_hash_entry *rn= (Sroutine_hash_entry *)ptr;
+ *plen= rn->key.length;
+ return (byte *)rn->key.str;
+}
+
+
+/*
+ Check if
+ - current statement (the one in thd->lex) needs table prelocking
+ - first routine in thd->lex->sroutines_list needs to execute its body in
+ prelocked mode.
+
+ SYNOPSIS
+ sp_get_prelocking_info()
+ thd Current thread, thd->lex is the statement to be
+ checked.
+ need_prelocking OUT TRUE - prelocked mode should be activated
+ before executing the statement
+ FALSE - Don't activate prelocking
+ first_no_prelocking OUT TRUE - Tables used by first routine in
+ thd->lex->sroutines_list should be
+ prelocked.
+ FALSE - Otherwise.
+ NOTES
+ This function assumes that for any "CALL proc(...)" statement routines_list
+ will have 'proc' as first element (it may have several, consider e.g.
+ "proc(sp_func(...)))". This property is currently guaranted by the parser.
+*/
+
+void sp_get_prelocking_info(THD *thd, bool *need_prelocking,
+ bool *first_no_prelocking)
+{
+ Sroutine_hash_entry *routine;
+ routine= (Sroutine_hash_entry*)thd->lex->sroutines_list.first;
+
+ DBUG_ASSERT(routine);
+ bool first_is_procedure= (routine->key.str[0] == TYPE_ENUM_PROCEDURE);
+
+ *first_no_prelocking= first_is_procedure;
+ *need_prelocking= !first_is_procedure || test(routine->next);
+}
+
+
+/*
+ Auxilary function that adds new element to the set of stored routines
+ used by statement.
+
+ SYNOPSIS
+ add_used_routine()
+ lex - LEX representing statement
+ arena - arena in which memory for new element will be allocated
+ key - key for the hash representing set
+
+ NOTES
+ Will also add element to end of 'LEX::sroutines_list' list.
+
+ In case when statement uses stored routines but does not need
+ prelocking (i.e. it does not use any tables) we will access the
+ elements of LEX::sroutines set on prepared statement re-execution.
+ Because of this we have to allocate memory for both hash element
+ and copy of its key in persistent arena.
+
+ TODO
+ When we will got rid of these accesses on re-executions we will be
+ able to allocate memory for hash elements in non-persitent arena
+ and directly use key values from sp_head::m_sroutines sets instead
+ of making their copies.
+
+ RETURN VALUE
+ TRUE - new element was added.
+ FALSE - element was not added (because it is already present in the set).
+*/
+
+static bool add_used_routine(LEX *lex, Query_arena *arena,
+ const LEX_STRING *key)
+{
+ if (!hash_search(&lex->sroutines, (byte *)key->str, key->length))
+ {
+ Sroutine_hash_entry *rn=
+ (Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) +
+ key->length);
+ if (!rn) // OOM. Error will be reported using fatal_error().
+ return FALSE;
+ rn->key.length= key->length;
+ rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry);
+ memcpy(rn->key.str, key->str, key->length);
+ my_hash_insert(&lex->sroutines, (byte *)rn);
+ lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
+ Add routine which is explicitly used by statement to the set of stored
+ routines used by this statement.
+
+ SYNOPSIS
+ sp_add_used_routine()
+ lex - LEX representing statement
+ arena - arena in which memory for new element of the set
+ will be allocated
+ rt - routine name
+ rt_type - routine type (one of TYPE_ENUM_PROCEDURE/...)
+
+ NOTES
+ Will also add element to end of 'LEX::sroutines_list' list (and will
+ take into account that this is explicitly used routine).
+
+ To be friendly towards prepared statements one should pass
+ persistent arena as second argument.
+*/
+
+void sp_add_used_routine(LEX *lex, Query_arena *arena,
+ sp_name *rt, char rt_type)
+{
+ rt->set_routine_type(rt_type);
+ (void)add_used_routine(lex, arena, &rt->m_sroutines_key);
+ lex->sroutines_list_own_last= lex->sroutines_list.next;
+ lex->sroutines_list_own_elements= lex->sroutines_list.elements;
+}
+
+
+/*
+ Remove routines which are only indirectly used by statement from
+ the set of routines used by this statement.
+
+ SYNOPSIS
+ sp_remove_not_own_routines()
+ lex LEX representing statement
+*/
+
+void sp_remove_not_own_routines(LEX *lex)
+{
+ Sroutine_hash_entry *not_own_rt, *next_rt;
+ for (not_own_rt= *(Sroutine_hash_entry **)lex->sroutines_list_own_last;
+ not_own_rt; not_own_rt= next_rt)
+ {
+ /*
+ It is safe to obtain not_own_rt->next after calling hash_delete() now
+ but we want to be more future-proof.
+ */
+ next_rt= not_own_rt->next;
+ hash_delete(&lex->sroutines, (byte *)not_own_rt);
+ }
+
+ *(Sroutine_hash_entry **)lex->sroutines_list_own_last= NULL;
+ lex->sroutines_list.next= lex->sroutines_list_own_last;
+ lex->sroutines_list.elements= lex->sroutines_list_own_elements;
+}
+
+
+/*
+ Merge contents of two hashes representing sets of routines used
+ by statements or by other routines.
+
+ SYNOPSIS
+ sp_update_sp_used_routines()
+ dst - hash to which elements should be added
+ src - hash from which elements merged
+
+ NOTE
+ This procedure won't create new Sroutine_hash_entry objects,
+ instead it will simply add elements from source to destination
+ hash. Thus time of life of elements in destination hash becomes
+ dependant on time of life of elements from source hash. It also
+ won't touch lists linking elements in source and destination
+ hashes.
+*/
+
+void sp_update_sp_used_routines(HASH *dst, HASH *src)
+{
+ for (uint i=0 ; i < src->records ; i++)
+ {
+ Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
+ if (!hash_search(dst, (byte *)rt->key.str, rt->key.length))
+ my_hash_insert(dst, (byte *)rt);
+ }
+}
+
+
+/*
+ Add contents of hash representing set of routines to the set of
+ routines used by statement.
+
+ SYNOPSIS
+ sp_update_stmt_used_routines()
+ thd - thread context
+ lex - LEX representing statement
+ src - hash representing set from which routines will be added
+
+ NOTE
+ It will also add elements to end of 'LEX::sroutines_list' list.
+*/
+
+static void sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src)
+{
+ for (uint i=0 ; i < src->records ; i++)
+ {
+ Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
+ (void)add_used_routine(lex, thd->stmt_arena, &rt->key);
+ }
+}
+
+
+/*
+ Add contents of list representing set of routines to the set of
+ routines used by statement.
+
+ SYNOPSIS
+ sp_update_stmt_used_routines()
+ thd Thread context
+ lex LEX representing statement
+ src List representing set from which routines will be added
+
+ NOTE
+ It will also add elements to end of 'LEX::sroutines_list' list.
+*/
+
+static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src)
+{
+ for (Sroutine_hash_entry *rt= (Sroutine_hash_entry *)src->first;
+ rt; rt= rt->next)
+ (void)add_used_routine(lex, thd->stmt_arena, &rt->key);
+}
+
+
+/*
+ Cache sub-set of routines used by statement, add tables used by these
+ routines to statement table list. Do the same for all routines used
+ by these routines.
+
+ SYNOPSIS
+ sp_cache_routines_and_add_tables_aux()
+ thd - thread context
+ lex - LEX representing statement
+ start - first routine from the list of routines to be cached
+ (this list defines mentioned sub-set).
+ first_no_prelock - If true, don't add tables or cache routines used by
+ the body of the first routine (i.e. *start)
+ will be executed in non-prelocked mode.
+ NOTE
+ If some function is missing this won't be reported here.
+ Instead this fact will be discovered during query execution.
+
+ RETURN VALUE
+ TRUE - some tables were added
+ FALSE - no tables were added.
+*/
+
+static bool
+sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
+ Sroutine_hash_entry *start,
+ bool first_no_prelock)
+{
+ bool result= FALSE;
+ bool first= TRUE;
+ DBUG_ENTER("sp_cache_routines_and_add_tables_aux");
+
+ for (Sroutine_hash_entry *rt= start; rt; rt= rt->next)
+ {
+ sp_name name(rt->key.str, rt->key.length);
+ int type= rt->key.str[0];
+ sp_head *sp;
+
+ if (!(sp= sp_cache_lookup((type == TYPE_ENUM_FUNCTION ?
+ &thd->sp_func_cache : &thd->sp_proc_cache),
+ &name)))
+ {
+ LEX *oldlex= thd->lex;
+ LEX *newlex= new st_lex;
+ thd->lex= newlex;
+ newlex->current_select= NULL;
+ name.m_name.str= strchr(name.m_qname.str, '.');
+ name.m_db.length= name.m_name.str - name.m_qname.str;
+ name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str,
+ name.m_db.length);
+ name.m_name.str+= 1;
+ name.m_name.length= name.m_qname.length - name.m_db.length - 1;
+
+ if (db_find_routine(thd, type, &name, &sp) == SP_OK)
+ {
+ if (type == TYPE_ENUM_FUNCTION)
+ sp_cache_insert(&thd->sp_func_cache, sp);
+ else
+ sp_cache_insert(&thd->sp_proc_cache, sp);
+ }
+ delete newlex;
+ thd->lex= oldlex;
+ }
+ if (sp)
+ {
+ if (!(first && first_no_prelock))
+ {
+ sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines);
+ result|= sp->add_used_tables_to_table_list(thd, &lex->query_tables_last);
+ }
+ }
+ first= FALSE;
+ }
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Cache all routines from the set of used by statement, add tables used
+ by those routines to statement table list. Do the same for all routines
+ used by those routines.
+
+ SYNOPSIS
+ sp_cache_routines_and_add_tables()
+ thd - thread context
+ lex - LEX representing statement
+ first_no_prelock - If true, don't add tables or cache routines used by
+ the body of the first routine (i.e. *start)
+
+ RETURN VALUE
+ TRUE - some tables were added
+ FALSE - no tables were added.
+*/
+
+bool
+sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock)
+{
+ return sp_cache_routines_and_add_tables_aux(thd, lex,
+ (Sroutine_hash_entry *)lex->sroutines_list.first,
+ first_no_prelock);
+}
+
+
+/*
+ Add all routines used by view to the set of routines used by statement.
+ Add tables used by those routines to statement table list. Do the same
+ for all routines used by these routines.
+
+ SYNOPSIS
+ sp_cache_routines_and_add_tables_for_view()
+ thd - thread context
+ lex - LEX representing statement
+ aux_lex - LEX representing view
+*/
+
+void
+sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex)
+{
+ Sroutine_hash_entry **last_cached_routine_ptr=
+ (Sroutine_hash_entry **)lex->sroutines_list.next;
+ sp_update_stmt_used_routines(thd, lex, &aux_lex->sroutines_list);
+ (void)sp_cache_routines_and_add_tables_aux(thd, lex,
+ *last_cached_routine_ptr, FALSE);
+}
+
+
+/*
+ Add triggers for table to the set of routines used by statement.
+ Add tables used by them to statement table list. Do the same for
+ all implicitly used routines.
+
+ SYNOPSIS
+ sp_cache_routines_and_add_tables_for_triggers()
+ thd - thread context
+ lex - LEX respresenting statement
+ triggers - triggers of the table
+*/
+
+void
+sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
+ Table_triggers_list *triggers)
+{
+ if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key))
+ {
+ Sroutine_hash_entry **last_cached_routine_ptr=
+ (Sroutine_hash_entry **)lex->sroutines_list.next;
+ for (int i= 0; i < (int)TRG_EVENT_MAX; i++)
+ {
+ for (int j= 0; j < (int)TRG_ACTION_MAX; j++)
+ {
+ if (triggers->bodies[i][j])
+ {
+ (void)triggers->bodies[i][j]->add_used_tables_to_table_list(thd,
+ &lex->query_tables_last);
+ sp_update_stmt_used_routines(thd, lex,
+ &triggers->bodies[i][j]->m_sroutines);
+ }
+ }
+ }
+ (void)sp_cache_routines_and_add_tables_aux(thd, lex,
+ *last_cached_routine_ptr,
+ FALSE);
+ }
+}
+
+
+/*
+ * Generates the CREATE... string from the table information.
+ * Returns TRUE on success, FALSE on (alloc) failure.
+ */
+static bool
+create_string(THD *thd, String *buf,
+ int type,
+ sp_name *name,
+ const char *params, ulong paramslen,
+ const char *returns, ulong returnslen,
+ const char *body, ulong bodylen,
+ st_sp_chistics *chistics)
+{
+ /* Make some room to begin with */
+ if (buf->alloc(100 + name->m_qname.length + paramslen + returnslen + bodylen +
+ chistics->comment.length))
+ return FALSE;
+
+ buf->append("CREATE ", 7);
+ if (type == TYPE_ENUM_FUNCTION)
+ buf->append("FUNCTION ", 9);
+ else
+ buf->append("PROCEDURE ", 10);
+ append_identifier(thd, buf, name->m_name.str, name->m_name.length);
+ buf->append('(');
+ buf->append(params, paramslen);
+ buf->append(')');
+ if (type == TYPE_ENUM_FUNCTION)
+ {
+ buf->append(" RETURNS ", 9);
+ buf->append(returns, returnslen);
+ }
+ buf->append('\n');
+ switch (chistics->daccess) {
+ case SP_NO_SQL:
+ buf->append(" NO SQL\n");
+ break;
+ case SP_READS_SQL_DATA:
+ buf->append(" READS SQL DATA\n");
+ break;
+ case SP_MODIFIES_SQL_DATA:
+ buf->append(" MODIFIES SQL DATA\n");
+ break;
+ case SP_DEFAULT_ACCESS:
+ case SP_CONTAINS_SQL:
+ /* Do nothing */
+ break;
+ }
+ if (chistics->detistic)
+ buf->append(" DETERMINISTIC\n", 18);
+ if (chistics->suid == SP_IS_NOT_SUID)
+ buf->append(" SQL SECURITY INVOKER\n", 25);
+ if (chistics->comment.length)
+ {
+ buf->append(" COMMENT ");
+ append_unescaped(buf, chistics->comment.str, chistics->comment.length);
+ buf->append('\n');
+ }
+ buf->append(body, bodylen);
+ return TRUE;
+}
+
+
+//
+// Utilities...
+//
+
+int
+sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen,
+ bool no_access_check, bool *dbchangedp)
+{
+ bool changeit;
+ DBUG_ENTER("sp_use_new_db");
+ DBUG_PRINT("enter", ("newdb: %s", newdb));
+
+ if (! newdb)
+ newdb= (char *)"";
+ if (thd->db && thd->db[0])
+ {
+ if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0)
+ changeit= 0;
+ else
+ {
+ changeit= 1;
+ strnmov(olddb, thd->db, olddblen);
+ }
+ }
+ else
+ { // thd->db empty
+ if (newdb[0])
+ changeit= 1;
+ else
+ changeit= 0;
+ olddb[0] = '\0';
+ }
+ if (!changeit)
+ {
+ *dbchangedp= FALSE;
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ int ret= mysql_change_db(thd, newdb, no_access_check);
+
+ if (! ret)
+ *dbchangedp= TRUE;
+ DBUG_RETURN(ret);
+ }
+}
diff --git a/sql/sp.h b/sql/sp.h
new file mode 100644
index 00000000000..933e5793e4c
--- /dev/null
+++ b/sql/sp.h
@@ -0,0 +1,116 @@
+/* -*- C++ -*- */
+/* 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 */
+
+#ifndef _SP_H_
+#define _SP_H_
+
+// Return codes from sp_create_*, sp_drop_*, and sp_show_*:
+#define SP_OK 0
+#define SP_KEY_NOT_FOUND -1
+#define SP_OPEN_TABLE_FAILED -2
+#define SP_WRITE_ROW_FAILED -3
+#define SP_DELETE_ROW_FAILED -4
+#define SP_GET_FIELD_FAILED -5
+#define SP_PARSE_ERROR -6
+#define SP_INTERNAL_ERROR -7
+#define SP_NO_DB_ERROR -8
+#define SP_BAD_IDENTIFIER -9
+#define SP_BODY_TOO_LONG -10
+
+/* Drop all routines in database 'db' */
+int
+sp_drop_db_routines(THD *thd, char *db);
+
+sp_head *
+sp_find_procedure(THD *thd, sp_name *name, bool cache_only = 0);
+
+int
+sp_exists_routine(THD *thd, TABLE_LIST *procs, bool any, bool no_error);
+
+int
+sp_create_procedure(THD *thd, sp_head *sp);
+
+int
+sp_drop_procedure(THD *thd, sp_name *name);
+
+
+int
+sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics);
+
+int
+sp_show_create_procedure(THD *thd, sp_name *name);
+
+int
+sp_show_status_procedure(THD *thd, const char *wild);
+
+sp_head *
+sp_find_function(THD *thd, sp_name *name, bool cache_only = 0);
+
+int
+sp_create_function(THD *thd, sp_head *sp);
+
+int
+sp_drop_function(THD *thd, sp_name *name);
+
+int
+sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics);
+
+int
+sp_show_create_function(THD *thd, sp_name *name);
+
+int
+sp_show_status_function(THD *thd, const char *wild);
+
+
+/*
+ Procedures for pre-caching of stored routines and building table list
+ for prelocking.
+*/
+void sp_get_prelocking_info(THD *thd, bool *need_prelocking,
+ bool *first_no_prelocking);
+void sp_add_used_routine(LEX *lex, Query_arena *arena,
+ sp_name *rt, char rt_type);
+void sp_remove_not_own_routines(LEX *lex);
+void sp_update_sp_used_routines(HASH *dst, HASH *src);
+bool sp_cache_routines_and_add_tables(THD *thd, LEX *lex,
+ bool first_no_prelock);
+void sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex,
+ LEX *aux_lex);
+void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
+ Table_triggers_list *triggers);
+
+extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first);
+
+/*
+ Routines which allow open/lock and close mysql.proc table even when
+ we already have some tables open and locked.
+*/
+TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup);
+void close_proc_table(THD *thd, Open_tables_state *backup);
+
+//
+// Utilities...
+//
+
+// Do a "use newdb". The current db is stored at olddb.
+// If newdb is the same as the current one, nothing is changed.
+// dbchangedp is set to true if the db was actually changed.
+int
+sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddbmax,
+ bool no_access_check, bool *dbchangedp);
+
+#endif /* _SP_H_ */
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
new file mode 100644
index 00000000000..495f969eeac
--- /dev/null
+++ b/sql/sp_cache.cc
@@ -0,0 +1,261 @@
+/* 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 */
+
+#include "mysql_priv.h"
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation
+#endif
+#include "sp_cache.h"
+#include "sp_head.h"
+
+static pthread_mutex_t Cversion_lock;
+static ulong volatile Cversion= 0;
+
+
+/*
+ Cache of stored routines.
+*/
+
+class sp_cache
+{
+public:
+ ulong version;
+
+ sp_cache();
+ ~sp_cache();
+
+ inline void insert(sp_head *sp)
+ {
+ /* TODO: why don't we check return value? */
+ my_hash_insert(&m_hashtable, (const byte *)sp);
+ }
+
+ inline sp_head *lookup(char *name, uint namelen)
+ {
+ return (sp_head *)hash_search(&m_hashtable, (const byte *)name, namelen);
+ }
+
+#ifdef NOT_USED
+ inline bool remove(char *name, uint namelen)
+ {
+ sp_head *sp= lookup(name, namelen);
+ if (sp)
+ {
+ hash_delete(&m_hashtable, (byte *)sp);
+ return TRUE;
+ }
+ return FALSE;
+ }
+#endif
+
+ inline void remove_all()
+ {
+ cleanup();
+ init();
+ }
+
+private:
+ void init();
+ void cleanup();
+
+ /* All routines in this cache */
+ HASH m_hashtable;
+}; // class sp_cache
+
+
+/* Initialize the SP caching once at startup */
+
+void sp_cache_init()
+{
+ pthread_mutex_init(&Cversion_lock, MY_MUTEX_INIT_FAST);
+}
+
+
+/*
+ Clear the cache *cp and set *cp to NULL.
+
+ SYNOPSIS
+ sp_cache_clear()
+ cp Pointer to cache to clear
+
+ NOTE
+ This function doesn't invalidate other caches.
+*/
+
+void sp_cache_clear(sp_cache **cp)
+{
+ sp_cache *c= *cp;
+
+ if (c)
+ {
+ delete c;
+ *cp= NULL;
+ }
+}
+
+
+/*
+ Insert a routine into the cache.
+
+ SYNOPSIS
+ sp_cache_insert()
+ cp The cache to put routine into
+ sp Routine to insert.
+
+ TODO: Perhaps it will be more straightforward if in case we returned an
+ error from this function when we couldn't allocate sp_cache. (right
+ now failure to put routine into cache will cause a 'SP not found'
+ error to be reported at some later time)
+*/
+
+void sp_cache_insert(sp_cache **cp, sp_head *sp)
+{
+ sp_cache *c;
+ ulong v;
+
+ if (!(c= *cp))
+ {
+ if (!(c= new sp_cache()))
+ return; // End of memory error
+ c->version= Cversion; // No need to lock when reading long variable
+ }
+ DBUG_PRINT("info",("sp_cache: inserting: %*s", sp->m_qname.length,
+ sp->m_qname.str));
+ c->insert(sp);
+ *cp= c; // Update *cp if it was NULL
+}
+
+
+/*
+ Look up a routine in the cache.
+ SYNOPSIS
+ sp_cache_lookup()
+ cp Cache to look into
+ name Name of rutine to find
+
+ NOTE
+ An obsolete (but not more obsolete then since last
+ sp_cache_flush_obsolete call) routine may be returned.
+
+ RETURN
+ The routine or
+ NULL if the routine not found.
+*/
+
+sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name)
+{
+ sp_cache *c= *cp;
+ if (! c)
+ return NULL;
+ return c->lookup(name->m_qname.str, name->m_qname.length);
+}
+
+
+/*
+ Invalidate all routines in all caches.
+
+ SYNOPSIS
+ sp_cache_invalidate()
+
+ NOTE
+ This is called when a VIEW definition is modifed. We can't destroy sp_head
+ objects here as one may modify VIEW definitions from prelocking-free SPs.
+*/
+
+void sp_cache_invalidate()
+{
+ DBUG_PRINT("info",("sp_cache: invalidating"));
+ thread_safe_increment(Cversion, &Cversion_lock);
+}
+
+
+/*
+ Remove out-of-date SPs from the cache.
+
+ SYNOPSIS
+ sp_cache_flush_obsolete()
+ cp Cache to flush
+
+ NOTE
+ This invalidates pointers to sp_head objects this thread uses.
+ In practice that means 'dont call this function when inside SP'.
+*/
+
+void sp_cache_flush_obsolete(sp_cache **cp)
+{
+ sp_cache *c= *cp;
+ if (c)
+ {
+ ulong v;
+ v= Cversion; // No need to lock when reading long variable
+ if (c->version < v)
+ {
+ DBUG_PRINT("info",("sp_cache: deleting all functions"));
+ /* We need to delete all elements. */
+ c->remove_all();
+ c->version= v;
+ }
+ }
+}
+
+
+/*************************************************************************
+ Internal functions
+ *************************************************************************/
+
+static byte *hash_get_key_for_sp_head(const byte *ptr, uint *plen,
+ my_bool first)
+{
+ sp_head *sp= (sp_head *)ptr;
+ *plen= sp->m_qname.length;
+ return (byte*) sp->m_qname.str;
+}
+
+
+static void
+hash_free_sp_head(void *p)
+{
+ sp_head *sp= (sp_head *)p;
+ delete sp;
+}
+
+
+sp_cache::sp_cache()
+{
+ init();
+}
+
+
+sp_cache::~sp_cache()
+{
+ hash_free(&m_hashtable);
+}
+
+
+void
+sp_cache::init()
+{
+ hash_init(&m_hashtable, system_charset_info, 0, 0, 0,
+ hash_get_key_for_sp_head, hash_free_sp_head, 0);
+ version= 0;
+}
+
+
+void
+sp_cache::cleanup()
+{
+ hash_free(&m_hashtable);
+}
diff --git a/sql/sp_cache.h b/sql/sp_cache.h
new file mode 100644
index 00000000000..1021d17b9e2
--- /dev/null
+++ b/sql/sp_cache.h
@@ -0,0 +1,63 @@
+/* -*- C++ -*- */
+/* 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 */
+
+#ifndef _SP_CACHE_H_
+#define _SP_CACHE_H_
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+/*
+ Stored procedures/functions cache. This is used as follows:
+ * Each thread has its own cache.
+ * Each sp_head object is put into its thread cache before it is used, and
+ then remains in the cache until deleted.
+*/
+
+class sp_head;
+class sp_cache;
+
+/*
+ Cache usage scenarios:
+ 1. Application-wide init:
+ sp_cache_init();
+
+ 2. SP execution in thread:
+ 2.1 While holding sp_head* pointers:
+
+ // look up a routine in the cache (no checks if it is up to date or not)
+ sp_cache_lookup();
+
+ sp_cache_insert();
+ sp_cache_invalidate();
+
+ 2.2 When not holding any sp_head* pointers:
+ sp_cache_flush_obsolete();
+
+ 3. Before thread exit:
+ sp_cache_clear();
+*/
+
+void sp_cache_init();
+void sp_cache_clear(sp_cache **cp);
+void sp_cache_insert(sp_cache **cp, sp_head *sp);
+sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name);
+void sp_cache_invalidate();
+void sp_cache_flush_obsolete(sp_cache **cp);
+
+#endif /* _SP_CACHE_H_ */
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
new file mode 100644
index 00000000000..1a7599d7bbc
--- /dev/null
+++ b/sql/sp_head.cc
@@ -0,0 +1,2924 @@
+/* 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 */
+
+#include "mysql_priv.h"
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation
+#endif
+#include "sp_head.h"
+#include "sp.h"
+#include "sp_pcontext.h"
+#include "sp_rcontext.h"
+#include "sp_cache.h"
+
+Item_result
+sp_map_result_type(enum enum_field_types type)
+{
+ switch (type)
+ {
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_INT24:
+ return INT_RESULT;
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ return DECIMAL_RESULT;
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ return REAL_RESULT;
+ default:
+ return STRING_RESULT;
+ }
+}
+
+/*
+ SYNOPSIS
+ sp_get_flags_for_command()
+
+ DESCRIPTION
+ Returns a combination of:
+ * sp_head::MULTI_RESULTS: added if the 'cmd' is a command that might
+ result in multiple result sets being sent back.
+ * sp_head::CONTAINS_DYNAMIC_SQL: added if 'cmd' is one of PREPARE,
+ EXECUTE, DEALLOCATE.
+*/
+
+uint
+sp_get_flags_for_command(LEX *lex)
+{
+ uint flags;
+
+ switch (lex->sql_command) {
+ case SQLCOM_SELECT:
+ if (lex->result)
+ {
+ flags= 0; /* This is a SELECT with INTO clause */
+ break;
+ }
+ /* fallthrough */
+ case SQLCOM_ANALYZE:
+ case SQLCOM_CHECKSUM:
+ case SQLCOM_HA_READ:
+ case SQLCOM_SHOW_BINLOGS:
+ case SQLCOM_SHOW_BINLOG_EVENTS:
+ case SQLCOM_SHOW_CHARSETS:
+ case SQLCOM_SHOW_COLLATIONS:
+ case SQLCOM_SHOW_COLUMN_TYPES:
+ case SQLCOM_SHOW_CREATE:
+ case SQLCOM_SHOW_CREATE_DB:
+ case SQLCOM_SHOW_CREATE_FUNC:
+ case SQLCOM_SHOW_CREATE_PROC:
+ case SQLCOM_SHOW_DATABASES:
+ case SQLCOM_SHOW_ERRORS:
+ case SQLCOM_SHOW_FIELDS:
+ case SQLCOM_SHOW_GRANTS:
+ case SQLCOM_SHOW_INNODB_STATUS:
+ case SQLCOM_SHOW_KEYS:
+ case SQLCOM_SHOW_LOGS:
+ case SQLCOM_SHOW_MASTER_STAT:
+ case SQLCOM_SHOW_MUTEX_STATUS:
+ case SQLCOM_SHOW_NEW_MASTER:
+ case SQLCOM_SHOW_OPEN_TABLES:
+ case SQLCOM_SHOW_PRIVILEGES:
+ case SQLCOM_SHOW_PROCESSLIST:
+ case SQLCOM_SHOW_SLAVE_HOSTS:
+ case SQLCOM_SHOW_SLAVE_STAT:
+ case SQLCOM_SHOW_STATUS:
+ case SQLCOM_SHOW_STATUS_FUNC:
+ case SQLCOM_SHOW_STATUS_PROC:
+ case SQLCOM_SHOW_STORAGE_ENGINES:
+ case SQLCOM_SHOW_TABLES:
+ case SQLCOM_SHOW_VARIABLES:
+ case SQLCOM_SHOW_WARNS:
+ flags= sp_head::MULTI_RESULTS;
+ break;
+ /*
+ EXECUTE statement may return a result set, but doesn't have to.
+ We can't, however, know it in advance, and therefore must add
+ this statement here. This is ok, as is equivalent to a result-set
+ statement within an IF condition.
+ */
+ case SQLCOM_EXECUTE:
+ flags= sp_head::MULTI_RESULTS | sp_head::CONTAINS_DYNAMIC_SQL;
+ break;
+ case SQLCOM_PREPARE:
+ case SQLCOM_DEALLOCATE_PREPARE:
+ flags= sp_head::CONTAINS_DYNAMIC_SQL;
+ break;
+ default:
+ flags= 0;
+ break;
+ }
+ return flags;
+}
+
+
+/*
+ Prepare Item for execution (call of fix_fields)
+
+ SYNOPSIS
+ sp_prepare_func_item()
+ thd thread handler
+ it_addr pointer on item refernce
+
+ RETURN
+ NULL error
+ prepared item
+*/
+
+static Item *
+sp_prepare_func_item(THD* thd, Item **it_addr)
+{
+ Item *it= *it_addr;
+ DBUG_ENTER("sp_prepare_func_item");
+ it_addr= it->this_item_addr(thd, it_addr);
+
+ if (!it->fixed && (*it_addr)->fix_fields(thd, it_addr))
+ {
+ DBUG_PRINT("info", ("fix_fields() failed"));
+ DBUG_RETURN(NULL);
+ }
+ DBUG_RETURN(*it_addr);
+}
+
+
+/* Macro to switch arena in sp_eval_func_item */
+#define CREATE_ON_CALLERS_ARENA(new_command, condition, backup_arena) \
+ do \
+ { \
+ if (condition) \
+ thd->set_n_backup_active_arena(thd->spcont->callers_arena, \
+ backup_arena); \
+ new_command; \
+ if (condition) \
+ thd->restore_active_arena(thd->spcont->callers_arena, \
+ backup_arena); \
+ } while(0)
+
+/*
+ Evaluate an item and store it in the returned item
+
+ SYNOPSIS
+ sp_eval_func_item()
+ name - current thread object
+ it_addr - pointer to the item to evaluate
+ type - type of the item we evaluating
+ reuse - used if we would like to reuse existing item
+ instead of allocation of the new one
+ use_callers_arena - TRUE if we want to use caller's arena
+ rather then current one.
+ DESCRIPTION
+ We use this function to evaluate result for stored functions
+ and stored procedure parameters. It is also used to evaluate and
+ (re) allocate variables.
+
+ RETURN VALUES
+ Evaluated item is returned
+*/
+
+Item *
+sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
+ Item *reuse, bool use_callers_arena)
+{
+ DBUG_ENTER("sp_eval_func_item");
+ Item *it= sp_prepare_func_item(thd, it_addr);
+ uint rsize;
+ Query_arena backup_arena;
+ DBUG_PRINT("info", ("type: %d", type));
+
+ if (!it)
+ {
+ DBUG_RETURN(NULL);
+ }
+
+ switch (sp_map_result_type(type)) {
+ case INT_RESULT:
+ {
+ longlong i= it->val_int();
+
+ if (it->null_value)
+ {
+ DBUG_PRINT("info", ("INT_RESULT: null"));
+ goto return_null_item;
+ }
+ DBUG_PRINT("info", ("INT_RESULT: %d", i));
+ CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_int(i),
+ use_callers_arena, &backup_arena);
+ break;
+ }
+ case REAL_RESULT:
+ {
+ double d= it->val_real();
+ uint8 decimals;
+ uint32 max_length;
+
+ if (it->null_value)
+ {
+ DBUG_PRINT("info", ("REAL_RESULT: null"));
+ goto return_null_item;
+ }
+
+ /*
+ There's some difference between Item::new_item() and the
+ constructor; the former crashes, the latter works... weird.
+ */
+ decimals= it->decimals;
+ max_length= it->max_length;
+ DBUG_PRINT("info", ("REAL_RESULT: %g", d));
+ CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_float(d),
+ use_callers_arena, &backup_arena);
+ it->decimals= decimals;
+ it->max_length= max_length;
+ break;
+ }
+ case DECIMAL_RESULT:
+ {
+ my_decimal value, *val= it->val_decimal(&value);
+ if (it->null_value)
+ goto return_null_item;
+ CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_decimal(val),
+ use_callers_arena, &backup_arena);
+#ifndef DBUG_OFF
+ {
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ DBUG_PRINT("info", ("DECIMAL_RESULT: %s",
+ dbug_decimal_as_string(dbug_buff, val)));
+ }
+#endif
+ break;
+ }
+ case STRING_RESULT:
+ {
+ char buffer[MAX_FIELD_WIDTH];
+ String tmp(buffer, sizeof(buffer), it->collation.collation);
+ String *s= it->val_str(&tmp);
+
+ if (type == MYSQL_TYPE_NULL || it->null_value)
+ {
+ DBUG_PRINT("info", ("STRING_RESULT: null"));
+ goto return_null_item;
+ }
+ DBUG_PRINT("info",("STRING_RESULT: %*s",
+ s->length(), s->c_ptr_quick()));
+ /*
+ Reuse mechanism in sp_eval_func_item() is only employed for assignments
+ to local variables and OUT/INOUT SP parameters repsesented by
+ Item_splocal. Usually we have some expression, which needs
+ to be calculated and stored into the local variable. However in the
+ case if "it" equals to "reuse", there is no "calculation" step. So,
+ no reason to employ reuse mechanism to save variable into itself.
+ */
+ if (it == reuse)
+ DBUG_RETURN(it);
+
+ CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize)
+ Item_string(it->collation.collation),
+ use_callers_arena, &backup_arena);
+ /*
+ We have to use special constructor and allocate string
+ on system heap here. This is because usual Item_string
+ constructor would allocate memory in the callers arena.
+ This would lead to the memory leak in SP loops.
+ See Bug #11333 "Stored Procedure: Memory blow up on
+ repeated SELECT ... INTO query" for sample of such SP.
+ TODO: Usage of the system heap gives significant overhead,
+ however usual "reuse" mechanism does not work here, as
+ Item_string has no max size. That is, if we have a loop, which
+ has string variable with constantly increasing size, we would have
+ to allocate new pieces of memory again and again on each iteration.
+ In future we should probably reserve some area of memory for
+ not-very-large strings and reuse it. But for large strings
+ we would have to use system heap anyway.
+ */
+ ((Item_string*) it)->set_str_with_copy(s->ptr(), s->length());
+ break;
+ }
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ it->rsize= rsize;
+
+ DBUG_RETURN(it);
+
+return_null_item:
+ CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_null(),
+ use_callers_arena, &backup_arena);
+ it->rsize= rsize;
+
+ DBUG_RETURN(it);
+}
+
+
+/*
+ *
+ * sp_name
+ *
+ */
+
+void
+sp_name::init_qname(THD *thd)
+{
+ m_sroutines_key.length= m_db.length + m_name.length + 2;
+ if (!(m_sroutines_key.str= thd->alloc(m_sroutines_key.length + 1)))
+ return;
+ m_qname.length= m_sroutines_key.length - 1;
+ m_qname.str= m_sroutines_key.str + 1;
+ sprintf(m_qname.str, "%*s.%*s",
+ m_db.length, (m_db.length ? m_db.str : ""),
+ m_name.length, m_name.str);
+}
+
+sp_name *
+sp_name_current_db_new(THD *thd, LEX_STRING name)
+{
+ sp_name *qname;
+
+ if (! thd->db)
+ qname= new sp_name(name);
+ else
+ {
+ LEX_STRING db;
+
+ db.length= strlen(thd->db);
+ db.str= thd->strmake(thd->db, db.length);
+ qname= new sp_name(db, name);
+ }
+ qname->init_qname(thd);
+ return qname;
+}
+
+
+/* ------------------------------------------------------------------ */
+
+
+/*
+ *
+ * sp_head
+ *
+ */
+
+void *
+sp_head::operator new(size_t size)
+{
+ DBUG_ENTER("sp_head::operator new");
+ MEM_ROOT own_root;
+ sp_head *sp;
+
+ init_alloc_root(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+ sp= (sp_head *) alloc_root(&own_root, size);
+ sp->main_mem_root= own_root;
+ DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root));
+ DBUG_RETURN(sp);
+}
+
+void
+sp_head::operator delete(void *ptr, size_t size)
+{
+ DBUG_ENTER("sp_head::operator delete");
+ MEM_ROOT own_root;
+ sp_head *sp= (sp_head *) ptr;
+
+ /* Make a copy of main_mem_root as free_root will free the sp */
+ own_root= sp->main_mem_root;
+ DBUG_PRINT("info", ("mem_root 0x%lx moved to 0x%lx",
+ (ulong) &sp->mem_root, (ulong) &own_root));
+ free_root(&own_root, MYF(0));
+
+ DBUG_VOID_RETURN;
+}
+
+
+sp_head::sp_head()
+ :Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
+ m_flags(0), m_returns_cs(NULL)
+{
+ extern byte *
+ sp_table_key(const byte *ptr, uint *plen, my_bool first);
+ DBUG_ENTER("sp_head::sp_head");
+
+ m_backpatch.empty();
+ m_lex.empty();
+ hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
+ hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0);
+ DBUG_VOID_RETURN;
+}
+
+
+void
+sp_head::init(LEX *lex)
+{
+ DBUG_ENTER("sp_head::init");
+
+ lex->spcont= m_pcont= new sp_pcontext(NULL);
+ /*
+ Altough trg_table_fields list is used only in triggers we init for all
+ types of stored procedures to simplify reset_lex()/restore_lex() code.
+ */
+ lex->trg_table_fields.empty();
+ my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
+ m_param_begin= m_param_end= m_body_begin= 0;
+ m_qname.str= m_db.str= m_name.str= m_params.str=
+ m_body.str= m_defstr.str= 0;
+ m_qname.length= m_db.length= m_name.length= m_params.length=
+ m_body.length= m_defstr.length= 0;
+ m_returns_cs= NULL;
+ DBUG_VOID_RETURN;
+}
+
+void
+sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
+{
+ DBUG_ENTER("sp_head::init_strings");
+ uint n; /* Counter for nul trimming */
+ /* During parsing, we must use thd->mem_root */
+ MEM_ROOT *root= thd->mem_root;
+
+ /* We have to copy strings to get them into the right memroot */
+ if (name)
+ {
+ m_db.length= name->m_db.length;
+ if (name->m_db.length == 0)
+ m_db.str= NULL;
+ else
+ m_db.str= strmake_root(root, name->m_db.str, name->m_db.length);
+ m_name.length= name->m_name.length;
+ m_name.str= strmake_root(root, name->m_name.str, name->m_name.length);
+
+ if (name->m_qname.length == 0)
+ name->init_qname(thd);
+ m_qname.length= name->m_qname.length;
+ m_qname.str= strmake_root(root, name->m_qname.str, m_qname.length);
+ }
+ else if (thd->db)
+ {
+ m_db.length= thd->db_length;
+ m_db.str= strmake_root(root, thd->db, m_db.length);
+ }
+
+ if (m_param_begin && m_param_end)
+ {
+ m_params.length= m_param_end - m_param_begin;
+ m_params.str= strmake_root(root,
+ (char *)m_param_begin, m_params.length);
+ }
+
+ m_body.length= lex->ptr - m_body_begin;
+ /* Trim nuls at the end */
+ n= 0;
+ while (m_body.length && m_body_begin[m_body.length-1] == '\0')
+ {
+ m_body.length-= 1;
+ n+= 1;
+ }
+ m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length);
+ m_defstr.length= lex->ptr - lex->buf;
+ m_defstr.length-= n;
+ m_defstr.str= strmake_root(root, (char *)lex->buf, m_defstr.length);
+ DBUG_VOID_RETURN;
+}
+
+TYPELIB *
+sp_head::create_typelib(List<String> *src)
+{
+ TYPELIB *result= NULL;
+ CHARSET_INFO *cs= m_returns_cs;
+ DBUG_ENTER("sp_head::clone_typelib");
+ if (src->elements)
+ {
+ result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
+ result->count= src->elements;
+ result->name= "";
+ if (!(result->type_names=(const char **)
+ alloc_root(mem_root,(sizeof(char *)+sizeof(int))*(result->count+1))))
+ return 0;
+ result->type_lengths= (unsigned int *)(result->type_names + result->count+1);
+ List_iterator<String> it(*src);
+ String conv;
+ for (uint i=0; i < result->count; i++)
+ {
+ uint32 dummy;
+ uint length;
+ String *tmp= it++;
+
+ if (String::needs_conversion(tmp->length(), tmp->charset(),
+ cs, &dummy))
+ {
+ uint cnv_errs;
+ conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
+
+ length= conv.length();
+ result->type_names[i]= (char*) strmake_root(mem_root, conv.ptr(),
+ length);
+ }
+ else
+ {
+ length= tmp->length();
+ result->type_names[i]= strmake_root(mem_root, tmp->ptr(), length);
+ }
+
+ // Strip trailing spaces.
+ length= cs->cset->lengthsp(cs, result->type_names[i], length);
+ result->type_lengths[i]= length;
+ ((uchar *)result->type_names[i])[length]= '\0';
+ }
+ result->type_names[result->count]= 0;
+ result->type_lengths[result->count]= 0;
+ }
+ return result;
+}
+
+int
+sp_head::create(THD *thd)
+{
+ DBUG_ENTER("sp_head::create");
+ int ret;
+
+ DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s",
+ m_type, m_name.str, m_params.str, m_body.str));
+
+#ifndef DBUG_OFF
+ optimize();
+ {
+ String s;
+ sp_instr *i;
+ uint ip= 0;
+ while ((i = get_instr(ip)))
+ {
+ char buf[8];
+
+ sprintf(buf, "%4u: ", ip);
+ s.append(buf);
+ i->print(&s);
+ s.append('\n');
+ ip+= 1;
+ }
+ s.append('\0');
+ DBUG_PRINT("info", ("Code %s\n%s", m_qname.str, s.ptr()));
+ }
+#endif
+
+ if (m_type == TYPE_ENUM_FUNCTION)
+ ret= sp_create_function(thd, this);
+ else
+ ret= sp_create_procedure(thd, this);
+
+ DBUG_RETURN(ret);
+}
+
+sp_head::~sp_head()
+{
+ destroy();
+ if (m_thd)
+ restore_thd_mem_root(m_thd);
+}
+
+void
+sp_head::destroy()
+{
+ sp_instr *i;
+ LEX *lex;
+ DBUG_ENTER("sp_head::destroy");
+ DBUG_PRINT("info", ("name: %s", m_name.str));
+
+ for (uint ip = 0 ; (i = get_instr(ip)) ; ip++)
+ delete i;
+ delete_dynamic(&m_instr);
+ m_pcont->destroy();
+ free_items();
+
+ /*
+ If we have non-empty LEX stack then we just came out of parser with
+ error. Now we should delete all auxilary LEXes and restore original
+ THD::lex (In this case sp_head::restore_thd_mem_root() was not called
+ too, so m_thd points to the current thread context).
+ It is safe to not update LEX::ptr because further query string parsing
+ and execution will be stopped anyway.
+ */
+ DBUG_ASSERT(m_lex.is_empty() || m_thd);
+ while ((lex= (LEX *)m_lex.pop()))
+ {
+ delete m_thd->lex;
+ m_thd->lex= lex;
+ }
+
+ hash_free(&m_sptabs);
+ hash_free(&m_sroutines);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ This is only used for result fields from functions (both during
+ fix_length_and_dec() and evaluation).
+*/
+
+Field *
+sp_head::make_field(uint max_length, const char *name, TABLE *dummy)
+{
+ Field *field;
+ DBUG_ENTER("sp_head::make_field");
+
+ field= ::make_field((char *)0,
+ !m_returns_len ? max_length : m_returns_len,
+ (uchar *)"", 0, m_returns_pack, m_returns, m_returns_cs,
+ m_geom_returns, Field::NONE,
+ m_returns_typelib,
+ name ? name : (const char *)m_name.str, dummy);
+ DBUG_RETURN(field);
+}
+
+
+int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b)
+{
+ return (int)((*a)->pos_in_query - (*b)->pos_in_query);
+}
+
+
+/*
+ StoredRoutinesBinlogging
+ Top-down overview:
+
+ 1. Statements
+
+ Statements that have is_update_query(stmt) == TRUE are written into the
+ binary log verbatim.
+ Examples:
+ UPDATE tbl SET tbl.x = spfunc_w_side_effects()
+ UPDATE tbl SET tbl.x=1 WHERE spfunc_w_side_effect_that_returns_false(tbl.y)
+
+ Statements that have is_update_query(stmt) == FALSE (e.g. SELECTs) are not
+ written into binary log. Instead we catch function calls the statement
+ makes and write it into binary log separately (see #3).
+
+ We actually can easily write SELECT statements into the binary log in the
+ right order (we don't have issues with const tables being unlocked early
+ because SELECTs that use FUNCTIONs unlock all tables at once) We don't do
+ it because replication slave thread currently can't execute SELECT
+ statements. Fixing this is on the TODO.
+
+ 2. PROCEDURE calls
+
+ CALL statements are not written into binary log. Instead
+ * Any FUNCTION invocation (in SET, IF, WHILE, OPEN CURSOR and other SP
+ instructions) is written into binlog separately.
+
+ * Each statement executed in SP is binlogged separately, according to rules
+ in #1, with the exception that we modify query string: we replace uses
+ of SP local variables with NAME_CONST('spvar_name', <spvar-value>) calls.
+ This substitution is done in subst_spvars().
+
+ 3. FUNCTION calls
+
+ In sp_head::execute_function(), we check
+ * If this function invocation is done from a statement that is written
+ into the binary log.
+ * If there were any attempts to write events to the binary log during
+ function execution (grep for start_union_events and stop_union_events)
+
+ If the answers are No and Yes, we write the function call into the binary
+ log as "DO spfunc(<param1value>, <param2value>, ...)"
+
+
+ 4. Miscellaneous issues.
+
+ 4.1 User variables.
+
+ When we call mysql_bin_log.write() for an SP statement, thd->user_var_events
+ must hold set<{var_name, value}> pairs for all user variables used during
+ the statement execution.
+ This set is produced by tracking user variable reads during statement
+ execution.
+
+ Fo SPs, this has the following implications:
+ 1) thd->user_var_events may contain events from several SP statements and
+ needs to be valid after exection of these statements was finished. In
+ order to achieve that, we
+ * Allocate user_var_events array elements on appropriate mem_root (grep
+ for user_var_events_alloc).
+ * Use is_query_in_union() to determine if user_var_event is created.
+
+ 2) We need to empty thd->user_var_events after we have wrote a function
+ call. This is currently done by making
+ reset_dynamic(&thd->user_var_events);
+ calls in several different places. (TODO cosider moving this into
+ mysql_bin_log.write() function)
+*/
+
+
+/*
+ Replace thd->query{_length} with a string that one can write to the binlog.
+
+ SYNOPSIS
+ subst_spvars()
+ thd Current thread.
+ instr Instruction (we look for Item_splocal instances in
+ instr->free_list)
+ query_str Original query string
+
+ DESCRIPTION
+
+ The binlog-suitable string is produced by replacing references to SP local
+ variables with NAME_CONST('sp_var_name', value) calls.
+
+ RETURN
+ 0 Ok, thd->query{_length} either has been appropriately replaced or
+ there is no need for replacements.
+ 1 Out of memory error.
+*/
+
+static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
+{
+ DBUG_ENTER("subst_spvars");
+ if (thd->prelocked_mode == NON_PRELOCKED && mysql_bin_log.is_open())
+ {
+ Dynamic_array<Item_splocal*> sp_vars_uses;
+ char *pbuf, *cur, buffer[512];
+ String qbuf(buffer, sizeof(buffer), &my_charset_bin);
+ int prev_pos, res;
+
+ /* Find all instances of item_splocal used in this statement */
+ for (Item *item= instr->free_list; item; item= item->next)
+ {
+ if (item->is_splocal())
+ {
+ Item_splocal *item_spl= (Item_splocal*)item;
+ if (item_spl->pos_in_query)
+ sp_vars_uses.append(item_spl);
+ }
+ }
+ if (!sp_vars_uses.elements())
+ DBUG_RETURN(0);
+
+ /* Sort SP var refs by their occurences in the query */
+ sp_vars_uses.sort(cmp_splocal_locations);
+
+ /*
+ Construct a statement string where SP local var refs are replaced
+ with "NAME_CONST(name, value)"
+ */
+ qbuf.length(0);
+ cur= query_str->str;
+ prev_pos= res= 0;
+ for (Item_splocal **splocal= sp_vars_uses.front();
+ splocal < sp_vars_uses.back(); splocal++)
+ {
+ Item *val;
+ /* append the text between sp ref occurences */
+ res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos);
+ prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length;
+
+ /* append the spvar substitute */
+ res|= qbuf.append(" NAME_CONST('");
+ res|= qbuf.append((*splocal)->m_name.str, (*splocal)->m_name.length);
+ res|= qbuf.append("',");
+ val= (*splocal)->this_item();
+ DBUG_PRINT("info", ("print %p", val));
+ val->print(&qbuf);
+ res|= qbuf.append(')');
+ if (res)
+ break;
+ }
+ res|= qbuf.append(cur + prev_pos, query_str->length - prev_pos);
+ if (res)
+ DBUG_RETURN(1);
+
+ if (!(pbuf= thd->strmake(qbuf.ptr(), qbuf.length())))
+ DBUG_RETURN(1);
+
+ thd->query= pbuf;
+ thd->query_length= qbuf.length();
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Execute the routine. The main instruction jump loop is there
+ Assume the parameters already set.
+
+ RETURN
+ -1 on error
+
+*/
+
+int sp_head::execute(THD *thd)
+{
+ DBUG_ENTER("sp_head::execute");
+ char olddb[128];
+ bool dbchanged;
+ sp_rcontext *ctx;
+ int ret= 0;
+ uint ip= 0;
+ ulong save_sql_mode;
+ Query_arena *old_arena;
+ /* per-instruction arena */
+ MEM_ROOT execute_mem_root;
+ Query_arena execute_arena(&execute_mem_root, INITIALIZED_FOR_SP),
+ backup_arena;
+ query_id_t old_query_id;
+ TABLE *old_derived_tables;
+ LEX *old_lex;
+ Item_change_list old_change_list;
+ String old_packet;
+
+ /* init per-instruction memroot */
+ init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
+
+
+ /* Use some extra margin for possible SP recursion and functions */
+ if (check_stack_overrun(thd, 4*STACK_MIN_SIZE, olddb))
+ {
+ DBUG_RETURN(-1);
+ }
+
+ if (m_flags & IS_INVOKED)
+ {
+ /*
+ We have to disable recursion for stored routines since in
+ many cases LEX structure and many Item's can't be used in
+ reentrant way now.
+
+ TODO: We can circumvent this problem by using separate
+ sp_head instances for each recursive invocation.
+
+ NOTE: Theoretically arguments of procedure can be evaluated
+ before its invocation so there should be no problem with
+ recursion. But since we perform cleanup for CALL statement
+ as for any other statement only after its execution, its LEX
+ structure is not reusable for recursive calls. Thus we have
+ to prohibit recursion for stored procedures too.
+ */
+ my_error(ER_SP_NO_RECURSION, MYF(0));
+ DBUG_RETURN(-1);
+ }
+ m_flags|= IS_INVOKED;
+
+ dbchanged= FALSE;
+ if (m_db.length &&
+ (ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged)))
+ goto done;
+
+ if ((ctx= thd->spcont))
+ ctx->clear_handler();
+ thd->query_error= 0;
+ old_arena= thd->stmt_arena;
+
+ /*
+ We have to save/restore this info when we are changing call level to
+ be able properly do close_thread_tables() in instructions.
+ */
+ old_query_id= thd->query_id;
+ old_derived_tables= thd->derived_tables;
+ thd->derived_tables= 0;
+ save_sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode= m_sql_mode;
+ /*
+ It is also more efficient to save/restore current thd->lex once when
+ do it in each instruction
+ */
+ old_lex= thd->lex;
+ /*
+ We should also save Item tree change list to avoid rollback something
+ too early in the calling query.
+ */
+ old_change_list= thd->change_list;
+ thd->change_list.empty();
+ /*
+ Cursors will use thd->packet, so they may corrupt data which was prepared
+ for sending by upper level. OTOH cursors in the same routine can share this
+ buffer safely so let use use routine-local packet instead of having own
+ packet buffer for each cursor.
+
+ It is probably safe to use same thd->convert_buff everywhere.
+ */
+ old_packet.swap(thd->packet);
+
+ /*
+ Switch to per-instruction arena here. We can do it since we cleanup
+ arena after every instruction.
+ */
+ thd->set_n_backup_active_arena(&execute_arena, &backup_arena);
+
+ /*
+ Save callers arena in order to store instruction results and out
+ parameters in it later during sp_eval_func_item()
+ */
+ thd->spcont->callers_arena= &backup_arena;
+
+ do
+ {
+ sp_instr *i;
+ uint hip; // Handler ip
+
+ i = get_instr(ip); // Returns NULL when we're done.
+ if (i == NULL)
+ break;
+ DBUG_PRINT("execute", ("Instruction %u", ip));
+ /* Don't change NOW() in FUNCTION or TRIGGER */
+ if (!thd->in_sub_stmt)
+ thd->set_time(); // Make current_time() et al work
+
+ /*
+ We have to set thd->stmt_arena before executing the instruction
+ to store in the instruction free_list all new items, created
+ during the first execution (for example expanding of '*' or the
+ items made during other permanent subquery transformations).
+ */
+ thd->stmt_arena= i;
+
+ /*
+ Will write this SP statement into binlog separately
+ (TODO: consider changing the condition to "not inside event union")
+ */
+ if (thd->prelocked_mode == NON_PRELOCKED)
+ thd->user_var_events_alloc= thd->mem_root;
+
+ ret= i->execute(thd, &ip);
+
+ /*
+ If this SP instruction have sent eof, it has caused no_send_error to be
+ set. Clear it back to allow the next instruction to send error. (multi-
+ statement execution code clears no_send_error between statements too)
+ */
+ thd->net.no_send_error= 0;
+ if (i->free_list)
+ cleanup_items(i->free_list);
+ i->state= Query_arena::EXECUTED;
+
+ /*
+ If we've set thd->user_var_events_alloc to mem_root of this SP
+ statement, clean all the events allocated in it.
+ */
+ if (thd->prelocked_mode == NON_PRELOCKED)
+ {
+ reset_dynamic(&thd->user_var_events);
+ thd->user_var_events_alloc= NULL;//DEBUG
+ }
+
+ /* we should cleanup free_list and memroot, used by instruction */
+ thd->free_items();
+ free_root(&execute_mem_root, MYF(0));
+
+ /*
+ Check if an exception has occurred and a handler has been found
+ Note: We havo to check even if ret==0, since warnings (and some
+ errors don't return a non-zero value.
+ We also have to check even if thd->killed != 0, since some
+ errors return with this even when a handler has been found
+ (e.g. "bad data").
+ */
+ if (ctx)
+ {
+ uint hf;
+
+ switch (ctx->found_handler(&hip, &hf)) {
+ case SP_HANDLER_NONE:
+ break;
+ case SP_HANDLER_CONTINUE:
+ thd->restore_active_arena(&execute_arena, &backup_arena);
+ ctx->save_variables(hf);
+ thd->set_n_backup_active_arena(&execute_arena, &backup_arena);
+ ctx->push_hstack(ip);
+ // Fall through
+ default:
+ ip= hip;
+ ret= 0;
+ ctx->clear_handler();
+ ctx->in_handler= TRUE;
+ thd->clear_error();
+ thd->killed= THD::NOT_KILLED;
+ continue;
+ }
+ }
+ } while (ret == 0 && !thd->killed);
+
+ thd->restore_active_arena(&execute_arena, &backup_arena);
+
+
+ /* Restore all saved */
+ old_packet.swap(thd->packet);
+ DBUG_ASSERT(thd->change_list.is_empty());
+ thd->change_list= old_change_list;
+ /* To avoid wiping out thd->change_list on old_change_list destruction */
+ old_change_list.empty();
+ thd->lex= old_lex;
+ thd->query_id= old_query_id;
+ DBUG_ASSERT(!thd->derived_tables);
+ thd->derived_tables= old_derived_tables;
+ thd->variables.sql_mode= save_sql_mode;
+
+ thd->stmt_arena= old_arena;
+ state= EXECUTED;
+
+ done:
+ DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
+ ret, thd->killed, thd->query_error));
+
+ if (thd->killed)
+ ret= -1;
+ /* If the DB has changed, the pointer has changed too, but the
+ original thd->db will then have been freed */
+ if (dbchanged)
+ {
+ if (! thd->killed)
+ ret= mysql_change_db(thd, olddb, 0);
+ }
+ m_flags&= ~IS_INVOKED;
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Execute a function:
+ - evaluate parameters
+ - call sp_head::execute
+ - evaluate the return value
+
+ SYNOPSIS
+ sp_head::execute_function()
+ thd Thread handle
+ argp Passed arguments (these are items from containing statement?)
+ argcount Number of passed arguments. We need to check if this is
+ correct.
+ resp OUT Put result item here (q: is it a constant Item always?)
+
+ RETURN
+ 0 on OK
+ other on error
+*/
+
+int
+sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
+{
+ Item **param_values;
+ ulonglong binlog_save_options;
+ bool need_binlog_call;
+ DBUG_ENTER("sp_head::execute_function");
+ DBUG_PRINT("info", ("function %s", m_name.str));
+ uint csize = m_pcont->max_pvars();
+ uint params = m_pcont->current_pvars();
+ uint hmax = m_pcont->max_handlers();
+ uint cmax = m_pcont->max_cursors();
+ sp_rcontext *octx = thd->spcont;
+ sp_rcontext *nctx = NULL;
+ uint i;
+ int ret= -1; // Assume error
+
+ if (argcount != params)
+ {
+ /*
+ Need to use my_error here, or it will not terminate the
+ invoking query properly.
+ */
+ my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0),
+ "FUNCTION", m_qname.str, params, argcount);
+ goto end;
+ }
+
+ if (!(param_values= (Item**)thd->alloc(sizeof(Item*)*argcount)))
+ DBUG_RETURN(-1);
+
+ // QQ Should have some error checking here? (types, etc...)
+ if (!(nctx= new sp_rcontext(csize, hmax, cmax)))
+ goto end;
+ for (i= 0 ; i < argcount ; i++)
+ {
+ sp_pvar_t *pvar = m_pcont->find_pvar(i);
+ Item *it= sp_eval_func_item(thd, argp++, pvar->type, NULL, FALSE);
+ param_values[i]= it;
+
+ if (!it)
+ goto end; // EOM error
+ nctx->push_item(it);
+ }
+
+
+ /*
+ The rest of the frame are local variables which are all IN.
+ Push NULLs to get the right size (and make the reuse mechanism work) -
+ the will be initialized by set instructions in each frame.
+ */
+ for (; i < csize ; i++)
+ nctx->push_item(NULL);
+
+ thd->spcont= nctx;
+
+ binlog_save_options= thd->options;
+ need_binlog_call= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG);
+ if (need_binlog_call)
+ {
+ reset_dynamic(&thd->user_var_events);
+ mysql_bin_log.start_union_events(thd);
+ }
+
+ thd->options&= ~OPTION_BIN_LOG;
+ ret= execute(thd);
+ thd->options= binlog_save_options;
+
+ if (need_binlog_call)
+ mysql_bin_log.stop_union_events(thd);
+
+ if (need_binlog_call && thd->binlog_evt_union.unioned_events)
+ {
+ char buf[256];
+ String bufstr(buf, sizeof(buf), &my_charset_bin);
+ bufstr.length(0);
+ bufstr.append("DO ", 3);
+ append_identifier(thd, &bufstr, m_name.str, m_name.length);
+ bufstr.append('(');
+ for (uint i=0; i < argcount; i++)
+ {
+ if (i)
+ bufstr.append(',');
+ param_values[i]->print(&bufstr);
+ }
+ bufstr.append(')');
+
+ Query_log_event qinfo(thd, bufstr.ptr(), bufstr.length(),
+ thd->binlog_evt_union.unioned_events_trans, FALSE);
+ if (mysql_bin_log.write(&qinfo) &&
+ thd->binlog_evt_union.unioned_events_trans)
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Invoked ROUTINE modified a transactional table but MySQL "
+ "failed to reflect this change in the binary log");
+ }
+ reset_dynamic(&thd->user_var_events);
+ }
+
+ if (m_type == TYPE_ENUM_FUNCTION && ret == 0)
+ {
+ /* We need result only in function but not in trigger */
+ Item *it= nctx->get_result();
+
+ if (it)
+ *resp= sp_eval_func_item(thd, &it, m_returns, NULL, FALSE);
+ else
+ {
+ my_error(ER_SP_NORETURNEND, MYF(0), m_name.str);
+ ret= -1;
+ }
+ }
+
+ nctx->pop_all_cursors(); // To avoid memory leaks after an error
+ delete nctx; // Doesn't do anything
+ thd->spcont= octx;
+
+end:
+ DBUG_RETURN(ret);
+}
+
+
+static Item_func_get_user_var *item_is_user_var(Item *it)
+{
+ if (it->type() == Item::FUNC_ITEM)
+ {
+ Item_func *fi= static_cast<Item_func*>(it);
+
+ if (fi->functype() == Item_func::GUSERVAR_FUNC)
+ return static_cast<Item_func_get_user_var*>(fi);
+ }
+ return NULL;
+}
+
+
+/*
+ Execute a procedure.
+ SYNOPSIS
+ sp_head::execute_procedure()
+ thd Thread handle
+ args List of values passed as arguments.
+
+ DESCRIPTION
+
+ The function does the following steps:
+ - Set all parameters
+ - call sp_head::execute
+ - copy back values of INOUT and OUT parameters
+
+ RETURN
+ 0 Ok
+ -1 Error
+*/
+
+int sp_head::execute_procedure(THD *thd, List<Item> *args)
+{
+ int ret= 0;
+ uint csize = m_pcont->max_pvars();
+ uint params = m_pcont->current_pvars();
+ uint hmax = m_pcont->max_handlers();
+ uint cmax = m_pcont->max_cursors();
+ sp_rcontext *save_spcont, *octx;
+ sp_rcontext *nctx = NULL;
+ DBUG_ENTER("sp_head::execute_procedure");
+ DBUG_PRINT("info", ("procedure %s", m_name.str));
+
+ if (args->elements != params)
+ {
+ my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "PROCEDURE",
+ m_qname.str, params, args->elements);
+ DBUG_RETURN(-1);
+ }
+
+ save_spcont= octx= thd->spcont;
+ if (! octx)
+ { // Create a temporary old context
+ if (!(octx= new sp_rcontext(csize, hmax, cmax)))
+ DBUG_RETURN(-1);
+ thd->spcont= octx;
+
+ /* set callers_arena to thd, for upper-level function to work */
+ thd->spcont->callers_arena= thd;
+ }
+
+ if (!(nctx= new sp_rcontext(csize, hmax, cmax)))
+ {
+ thd->spcont= save_spcont;
+ DBUG_RETURN(-1);
+ }
+
+ if (csize > 0 || hmax > 0 || cmax > 0)
+ {
+ Item_null *nit= NULL; // Re-use this, and only create if needed
+ uint i;
+ List_iterator<Item> li(*args);
+ Item *it;
+
+ /* Evaluate SP arguments (i.e. get the values passed as parameters) */
+ // QQ: Should do type checking?
+ DBUG_PRINT("info",(" %.*s: eval args", m_name.length, m_name.str));
+ for (i = 0 ; (it= li++) && i < params ; i++)
+ {
+ sp_pvar_t *pvar= m_pcont->find_pvar(i);
+
+ if (pvar)
+ {
+ if (pvar->mode != sp_param_in)
+ {
+ if (!it->is_splocal() && !item_is_user_var(it))
+ {
+ my_error(ER_SP_NOT_VAR_ARG, MYF(0), i+1, m_qname.str);
+ ret= -1;
+ break;
+ }
+ }
+ if (pvar->mode == sp_param_out)
+ {
+ if (! nit)
+ {
+ if (!(nit= new Item_null()))
+ {
+ ret= -1;
+ break;
+ }
+ }
+ nctx->push_item(nit); // OUT
+ }
+ else
+ {
+ Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type, NULL, FALSE);
+
+ if (!it2)
+ {
+ ret= -1; // Eval failed
+ break;
+ }
+ nctx->push_item(it2); // IN or INOUT
+ }
+ }
+ }
+
+ /*
+ Okay, got values for all arguments. Close tables that might be used by
+ arguments evaluation. If arguments evaluation required prelocking mode,
+ we'll leave it here.
+ */
+ if (!thd->in_sub_stmt)
+ close_thread_tables(thd, 0, 0);
+
+ DBUG_PRINT("info",(" %.*s: eval args done", m_name.length, m_name.str));
+
+ /*
+ The rest of the frame are local variables which are all IN.
+ Push NULLs to get the right size (and make the reuse mechanism work) -
+ the will be initialized by set instructions in each frame.
+ */
+ for (; i < csize ; i++)
+ nctx->push_item(NULL);
+ }
+
+ thd->spcont= nctx;
+
+ if (! ret)
+ ret= execute(thd);
+
+ /*
+ In the case when we weren't able to employ reuse mechanism for
+ OUT/INOUT paranmeters, we should reallocate memory. This
+ allocation should be done on the arena which will live through
+ all execution of calling routine.
+ */
+ thd->spcont->callers_arena= octx->callers_arena;
+
+ if (!ret && csize > 0)
+ {
+ List_iterator<Item> li(*args);
+ Item *it;
+
+ /*
+ Copy back all OUT or INOUT values to the previous frame, or
+ set global user variables
+ */
+ for (uint i = 0 ; (it= li++) && i < params ; i++)
+ {
+ sp_pvar_t *pvar= m_pcont->find_pvar(i);
+
+ if (pvar->mode != sp_param_in)
+ {
+ if (it->is_splocal())
+ {
+ // Have to copy the item to the caller's mem_root
+ Item *copy;
+ uint offset= static_cast<Item_splocal *>(it)->get_offset();
+ Item *val= nctx->get_item(i);
+ Item *orig= octx->get_item(offset);
+ Item *o_item_next;
+ /* we'll use callers_arena in sp_eval_func_item */
+ Item *o_free_list= thd->spcont->callers_arena->free_list;
+
+ LINT_INIT(o_item_next);
+
+ if (orig)
+ o_item_next= orig->next;
+
+ /*
+ We might need to allocate new item if we weren't able to
+ employ reuse mechanism. Then we should do it on the callers arena.
+ */
+ copy= sp_eval_func_item(thd, &val, pvar->type, orig, TRUE); // Copy
+
+ if (!copy)
+ {
+ ret= -1;
+ break;
+ }
+ if (copy != orig)
+ octx->set_item(offset, copy);
+ if (orig && copy == orig)
+ {
+ /*
+ A reused item slot, where the constructor put it in the
+ free_list, so we have to restore the list.
+ */
+ thd->spcont->callers_arena->free_list= o_free_list;
+ copy->next= o_item_next;
+ }
+ }
+ else
+ {
+ Item_func_get_user_var *guv= item_is_user_var(it);
+
+ if (guv)
+ {
+ Item *item= nctx->get_item(i);
+ Item_func_set_user_var *suv;
+
+ suv= new Item_func_set_user_var(guv->get_name(), item);
+ /*
+ we do not check suv->fixed, because it can't be fixed after
+ creation
+ */
+ suv->fix_fields(thd, &item);
+ suv->fix_length_and_dec();
+ suv->check();
+ suv->update();
+ }
+ }
+ }
+ }
+ }
+
+ if (!save_spcont)
+ delete octx; // Does nothing
+
+ nctx->pop_all_cursors(); // To avoid memory leaks after an error
+ delete nctx; // Does nothing
+ thd->spcont= save_spcont;
+
+ DBUG_RETURN(ret);
+}
+
+
+// Reset lex during parsing, before we parse a sub statement.
+void
+sp_head::reset_lex(THD *thd)
+{
+ DBUG_ENTER("sp_head::reset_lex");
+ LEX *sublex;
+ LEX *oldlex= thd->lex;
+ my_lex_states state= oldlex->next_state; // Keep original next_state
+
+ (void)m_lex.push_front(oldlex);
+ thd->lex= sublex= new st_lex;
+
+ /* Reset most stuff. The length arguments doesn't matter here. */
+ lex_start(thd, oldlex->buf, (ulong) (oldlex->end_of_query - oldlex->ptr));
+
+ /*
+ * next_state is normally the same (0), but it happens that we swap lex in
+ * "mid-sentence", so we must restore it.
+ */
+ sublex->next_state= state;
+ /* We must reset ptr and end_of_query again */
+ sublex->ptr= oldlex->ptr;
+ sublex->end_of_query= oldlex->end_of_query;
+ sublex->tok_start= oldlex->tok_start;
+ sublex->yylineno= oldlex->yylineno;
+ /* And keep the SP stuff too */
+ sublex->sphead= oldlex->sphead;
+ sublex->spcont= oldlex->spcont;
+ /* And trigger related stuff too */
+ sublex->trg_chistics= oldlex->trg_chistics;
+ sublex->trg_table_fields.empty();
+ sublex->sp_lex_in_use= FALSE;
+ DBUG_VOID_RETURN;
+}
+
+// Restore lex during parsing, after we have parsed a sub statement.
+void
+sp_head::restore_lex(THD *thd)
+{
+ DBUG_ENTER("sp_head::restore_lex");
+ LEX *sublex= thd->lex;
+ LEX *oldlex= (LEX *)m_lex.pop();
+
+ if (! oldlex)
+ return; // Nothing to restore
+
+ // Update some state in the old one first
+ oldlex->ptr= sublex->ptr;
+ oldlex->next_state= sublex->next_state;
+ oldlex->trg_table_fields.push_back(&sublex->trg_table_fields);
+
+ /*
+ Add routines which are used by statement to respective set for
+ this routine.
+ */
+ sp_update_sp_used_routines(&m_sroutines, &sublex->sroutines);
+ /*
+ Merge tables used by this statement (but not by its functions or
+ procedures) to multiset of tables used by this routine.
+ */
+ merge_table_list(thd, sublex->query_tables, sublex);
+ if (! sublex->sp_lex_in_use)
+ delete sublex;
+ thd->lex= oldlex;
+ DBUG_VOID_RETURN;
+}
+
+void
+sp_head::push_backpatch(sp_instr *i, sp_label_t *lab)
+{
+ bp_t *bp= (bp_t *)sql_alloc(sizeof(bp_t));
+
+ if (bp)
+ {
+ bp->lab= lab;
+ bp->instr= i;
+ (void)m_backpatch.push_front(bp);
+ }
+}
+
+void
+sp_head::backpatch(sp_label_t *lab)
+{
+ bp_t *bp;
+ uint dest= instructions();
+ List_iterator_fast<bp_t> li(m_backpatch);
+
+ while ((bp= li++))
+ {
+ if (bp->lab == lab ||
+ (bp->lab->type == SP_LAB_REF &&
+ my_strcasecmp(system_charset_info, bp->lab->name, lab->name) == 0))
+ {
+ if (bp->lab->type != SP_LAB_REF)
+ bp->instr->backpatch(dest, lab->ctx);
+ else
+ {
+ sp_label_t *dstlab= bp->lab->ctx->find_label(lab->name);
+
+ if (dstlab)
+ {
+ bp->lab= lab;
+ bp->instr->backpatch(dest, dstlab->ctx);
+ }
+ }
+ }
+ }
+}
+
+int
+sp_head::check_backpatch(THD *thd)
+{
+ bp_t *bp;
+ List_iterator_fast<bp_t> li(m_backpatch);
+
+ while ((bp= li++))
+ {
+ if (bp->lab->type == SP_LAB_REF)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "GOTO", bp->lab->name);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void
+sp_head::set_info(char *definer, uint definerlen,
+ longlong created, longlong modified,
+ st_sp_chistics *chistics, ulong sql_mode)
+{
+ char *p= strchr(definer, '@');
+ uint len;
+
+ if (! p)
+ p= definer; // Weird...
+ len= p-definer;
+ m_definer_user.str= strmake_root(mem_root, definer, len);
+ m_definer_user.length= len;
+ len= definerlen-len-1;
+ m_definer_host.str= strmake_root(mem_root, p+1, len);
+ m_definer_host.length= len;
+ m_created= created;
+ m_modified= modified;
+ m_chistics= (st_sp_chistics *) memdup_root(mem_root, (char*) chistics,
+ sizeof(*chistics));
+ if (m_chistics->comment.length == 0)
+ m_chistics->comment.str= 0;
+ else
+ m_chistics->comment.str= strmake_root(mem_root,
+ m_chistics->comment.str,
+ m_chistics->comment.length);
+ m_sql_mode= sql_mode;
+}
+
+void
+sp_head::reset_thd_mem_root(THD *thd)
+{
+ DBUG_ENTER("sp_head::reset_thd_mem_root");
+ m_thd_root= thd->mem_root;
+ thd->mem_root= &main_mem_root;
+ DBUG_PRINT("info", ("mem_root 0x%lx moved to thd mem root 0x%lx",
+ (ulong) &mem_root, (ulong) &thd->mem_root));
+ free_list= thd->free_list; // Keep the old list
+ thd->free_list= NULL; // Start a new one
+ /* Copy the db, since substatements will point to it */
+ m_thd_db= thd->db;
+ thd->db= thd->strmake(thd->db, thd->db_length);
+ m_thd= thd;
+ DBUG_VOID_RETURN;
+}
+
+void
+sp_head::restore_thd_mem_root(THD *thd)
+{
+ DBUG_ENTER("sp_head::restore_thd_mem_root");
+ Item *flist= free_list; // The old list
+ set_query_arena(thd); // Get new free_list and mem_root
+ state= INITIALIZED_FOR_SP;
+
+ DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx",
+ (ulong) &mem_root, (ulong) &thd->mem_root));
+ thd->free_list= flist; // Restore the old one
+ thd->db= m_thd_db; // Restore the original db pointer
+ thd->mem_root= m_thd_root;
+ m_thd= NULL;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Check if a user has access right to a routine
+
+ SYNOPSIS
+ check_show_routine_access()
+ thd Thread handler
+ sp SP
+ full_access Set to 1 if the user has SELECT right to the
+ 'mysql.proc' able or is the owner of the routine
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access)
+{
+ TABLE_LIST tables;
+ bzero((char*) &tables,sizeof(tables));
+ tables.db= (char*) "mysql";
+ tables.table_name= tables.alias= (char*) "proc";
+ *full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1) ||
+ (!strcmp(sp->m_definer_user.str, thd->priv_user) &&
+ !strcmp(sp->m_definer_host.str, thd->priv_host)));
+ if (!*full_access)
+ return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str,
+ sp->m_type == TYPE_ENUM_PROCEDURE);
+ return 0;
+}
+
+
+int
+sp_head::show_create_procedure(THD *thd)
+{
+ Protocol *protocol= thd->protocol;
+ char buff[2048];
+ String buffer(buff, sizeof(buff), system_charset_info);
+ int res;
+ List<Item> field_list;
+ byte *sql_mode_str;
+ ulong sql_mode_len;
+ bool full_access;
+
+ DBUG_ENTER("sp_head::show_create_procedure");
+ DBUG_PRINT("info", ("procedure %s", m_name.str));
+ LINT_INIT(sql_mode_str);
+ LINT_INIT(sql_mode_len);
+
+ if (check_show_routine_access(thd, this, &full_access))
+ return 1;
+
+ sql_mode_str=
+ sys_var_thd_sql_mode::symbolic_mode_representation(thd,
+ m_sql_mode,
+ &sql_mode_len);
+ field_list.push_back(new Item_empty_string("Procedure", NAME_LEN));
+ field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
+ // 1024 is for not to confuse old clients
+ field_list.push_back(new Item_empty_string("Create Procedure",
+ max(buffer.length(), 1024)));
+ if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF))
+ {
+ res= 1;
+ goto done;
+ }
+ protocol->prepare_for_resend();
+ protocol->store(m_name.str, m_name.length, system_charset_info);
+ protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
+ if (full_access)
+ protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
+ res= protocol->write();
+ send_eof(thd);
+
+ done:
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Add instruction to SP
+
+ SYNOPSIS
+ sp_head::add_instr()
+ instr Instruction
+*/
+
+void sp_head::add_instr(sp_instr *instr)
+{
+ instr->free_list= m_thd->free_list;
+ m_thd->free_list= 0;
+ /*
+ Memory root of every instruction is designated for permanent
+ transformations (optimizations) made on the parsed tree during
+ the first execution. It points to the memory root of the
+ entire stored procedure, as their life span is equal.
+ */
+ instr->mem_root= &main_mem_root;
+ insert_dynamic(&m_instr, (gptr)&instr);
+}
+
+
+int
+sp_head::show_create_function(THD *thd)
+{
+ Protocol *protocol= thd->protocol;
+ char buff[2048];
+ String buffer(buff, sizeof(buff), system_charset_info);
+ int res;
+ List<Item> field_list;
+ byte *sql_mode_str;
+ ulong sql_mode_len;
+ bool full_access;
+ DBUG_ENTER("sp_head::show_create_function");
+ DBUG_PRINT("info", ("procedure %s", m_name.str));
+ LINT_INIT(sql_mode_str);
+ LINT_INIT(sql_mode_len);
+
+ if (check_show_routine_access(thd, this, &full_access))
+ return 1;
+
+ sql_mode_str=
+ sys_var_thd_sql_mode::symbolic_mode_representation(thd,
+ m_sql_mode,
+ &sql_mode_len);
+ field_list.push_back(new Item_empty_string("Function",NAME_LEN));
+ field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
+ field_list.push_back(new Item_empty_string("Create Function",
+ max(buffer.length(),1024)));
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ {
+ res= 1;
+ goto done;
+ }
+ protocol->prepare_for_resend();
+ protocol->store(m_name.str, m_name.length, system_charset_info);
+ protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
+ if (full_access)
+ protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
+ res= protocol->write();
+ send_eof(thd);
+
+ done:
+ DBUG_RETURN(res);
+}
+
+
+/*
+ TODO: what does this do??
+*/
+
+void sp_head::optimize()
+{
+ List<sp_instr> bp;
+ sp_instr *i;
+ uint src, dst;
+
+ opt_mark(0);
+
+ bp.empty();
+ src= dst= 0;
+ while ((i= get_instr(src)))
+ {
+ if (! i->marked)
+ {
+ delete i;
+ src+= 1;
+ }
+ else
+ {
+ if (src != dst)
+ {
+ sp_instr *ibp;
+ List_iterator_fast<sp_instr> li(bp);
+
+ set_dynamic(&m_instr, (gptr)&i, dst);
+ while ((ibp= li++))
+ {
+ sp_instr_jump *ji= static_cast<sp_instr_jump *>(ibp);
+ if (ji->m_dest == src)
+ ji->m_dest= dst;
+ }
+ }
+ i->opt_move(dst, &bp);
+ src+= 1;
+ dst+= 1;
+ }
+ }
+ m_instr.elements= dst;
+ bp.empty();
+}
+
+void
+sp_head::opt_mark(uint ip)
+{
+ sp_instr *i;
+
+ while ((i= get_instr(ip)) && !i->marked)
+ ip= i->opt_mark(this);
+}
+
+
+/*
+ Prepare LEX and thread for execution of instruction, if requested open
+ and lock LEX's tables, execute instruction's core function, perform
+ cleanup afterwards.
+
+ SYNOPSIS
+ reset_lex_and_exec_core()
+ thd - thread context
+ nextp - out - next instruction
+ open_tables - if TRUE then check read access to tables in LEX's table
+ list and open and lock them (used in instructions which
+ need to calculate some expression and don't execute
+ complete statement).
+ sp_instr - instruction for which we prepare context, and which core
+ function execute by calling its exec_core() method.
+
+ NOTE
+ We are not saving/restoring some parts of THD which may need this because
+ we do this once for whole routine execution in sp_head::execute().
+
+ RETURN VALUE
+ 0/non-0 - Success/Failure
+*/
+
+int
+sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
+ bool open_tables, sp_instr* instr)
+{
+ int res= 0;
+
+ DBUG_ASSERT(!thd->derived_tables);
+ DBUG_ASSERT(thd->change_list.is_empty());
+ /*
+ Use our own lex.
+ We should not save old value since it is saved/restored in
+ sp_head::execute() when we are entering/leaving routine.
+ */
+ thd->lex= m_lex;
+
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query_id= next_query_id();
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+
+ if (thd->prelocked_mode == NON_PRELOCKED)
+ {
+ /*
+ This statement will enter/leave prelocked mode on its own.
+ Entering prelocked mode changes table list and related members
+ of LEX, so we'll need to restore them.
+ */
+ if (lex_query_tables_own_last)
+ {
+ /*
+ We've already entered/left prelocked mode with this statement.
+ Attach the list of tables that need to be prelocked and mark m_lex
+ as having such list attached.
+ */
+ *lex_query_tables_own_last= prelocking_tables;
+ m_lex->mark_as_requiring_prelocking(lex_query_tables_own_last);
+ }
+ }
+
+ reinit_stmt_before_use(thd, m_lex);
+ /*
+ If requested check whenever we have access to tables in LEX's table list
+ and open and lock them before executing instructtions core function.
+ */
+ if (open_tables &&
+ (check_table_access(thd, SELECT_ACL, m_lex->query_tables, 0) ||
+ open_and_lock_tables(thd, m_lex->query_tables)))
+ res= -1;
+
+ if (!res)
+ res= instr->exec_core(thd, nextp);
+
+ m_lex->unit.cleanup();
+
+ thd->proc_info="closing tables";
+ close_thread_tables(thd);
+ thd->proc_info= 0;
+
+ if (m_lex->query_tables_own_last)
+ {
+ /*
+ We've entered and left prelocking mode when executing statement
+ stored in m_lex.
+ m_lex->query_tables(->next_global)* list now has a 'tail' - a list
+ of tables that are added for prelocking. (If this is the first
+ execution, the 'tail' was added by open_tables(), otherwise we've
+ attached it above in this function).
+ Now we'll save the 'tail', and detach it.
+ */
+ lex_query_tables_own_last= m_lex->query_tables_own_last;
+ prelocking_tables= *lex_query_tables_own_last;
+ *lex_query_tables_own_last= NULL;
+ m_lex->mark_as_requiring_prelocking(NULL);
+ }
+ thd->rollback_item_tree_changes();
+
+ /*
+ Unlike for PS we should not call Item's destructors for newly created
+ items after execution of each instruction in stored routine. This is
+ because SP often create Item (like Item_int, Item_string etc...) when
+ they want to store some value in local variable, pass return value and
+ etc... So their life time should be longer than one instruction.
+
+ cleanup_items() is called in sp_head::execute()
+ */
+ return res;
+}
+
+
+/*
+ sp_instr class functions
+*/
+
+int sp_instr::exec_core(THD *thd, uint *nextp)
+{
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+/*
+ sp_instr_stmt class functions
+*/
+
+int
+sp_instr_stmt::execute(THD *thd, uint *nextp)
+{
+ char *query;
+ uint32 query_length;
+ int res;
+ DBUG_ENTER("sp_instr_stmt::execute");
+ DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command()));
+
+ query= thd->query;
+ query_length= thd->query_length;
+ if (!(res= alloc_query(thd, m_query.str, m_query.length+1)) &&
+ !(res=subst_spvars(thd, this, &m_query)))
+ {
+ /*
+ (the order of query cache and subst_spvars calls is irrelevant because
+ queries with SP vars can't be cached)
+ */
+ if (query_cache_send_result_to_client(thd,
+ thd->query, thd->query_length) <= 0)
+ {
+ res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this);
+ query_cache_end_of_result(thd);
+ }
+ else
+ *nextp= m_ip+1;
+ thd->query= query;
+ thd->query_length= query_length;
+ }
+ DBUG_RETURN(res);
+}
+
+void
+sp_instr_stmt::print(String *str)
+{
+ str->reserve(12);
+ str->append("stmt ");
+ str->qs_append((uint)m_lex_keeper.sql_command());
+}
+
+
+int
+sp_instr_stmt::exec_core(THD *thd, uint *nextp)
+{
+ int res= mysql_execute_command(thd);
+ *nextp= m_ip+1;
+ return res;
+}
+
+
+/*
+ sp_instr_set class functions
+*/
+
+int
+sp_instr_set::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_set::execute");
+ DBUG_PRINT("info", ("offset: %u", m_offset));
+
+ DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this));
+}
+
+
+int
+sp_instr_set::exec_core(THD *thd, uint *nextp)
+{
+ int res= thd->spcont->set_item_eval(thd, m_offset, &m_value, m_type);
+
+ *nextp = m_ip+1;
+ return res;
+}
+
+void
+sp_instr_set::print(String *str)
+{
+ str->reserve(12);
+ str->append("set ");
+ str->qs_append(m_offset);
+ str->append(' ');
+ m_value->print(str);
+}
+
+
+/*
+ sp_instr_set_trigger_field class functions
+*/
+
+int
+sp_instr_set_trigger_field::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_set_trigger_field::execute");
+ DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this));
+}
+
+
+int
+sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp)
+{
+ int res= 0;
+ Item *it= sp_prepare_func_item(thd, &value);
+ if (!it ||
+ !trigger_field->fixed && trigger_field->fix_fields(thd, 0) ||
+ (it->save_in_field(trigger_field->field, 0) < 0))
+ res= -1;
+ *nextp = m_ip+1;
+ return res;
+}
+
+void
+sp_instr_set_trigger_field::print(String *str)
+{
+ str->append("set ", 4);
+ trigger_field->print(str);
+ str->append(":=", 2);
+ value->print(str);
+}
+
+
+/*
+ sp_instr_jump class functions
+*/
+
+int
+sp_instr_jump::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_jump::execute");
+ DBUG_PRINT("info", ("destination: %u", m_dest));
+
+ *nextp= m_dest;
+ DBUG_RETURN(0);
+}
+
+void
+sp_instr_jump::print(String *str)
+{
+ str->reserve(12);
+ str->append("jump ");
+ str->qs_append(m_dest);
+}
+
+uint
+sp_instr_jump::opt_mark(sp_head *sp)
+{
+ m_dest= opt_shortcut_jump(sp, this);
+ if (m_dest != m_ip+1) /* Jumping to following instruction? */
+ marked= 1;
+ m_optdest= sp->get_instr(m_dest);
+ return m_dest;
+}
+
+uint
+sp_instr_jump::opt_shortcut_jump(sp_head *sp, sp_instr *start)
+{
+ uint dest= m_dest;
+ sp_instr *i;
+
+ while ((i= sp->get_instr(dest)))
+ {
+ uint ndest;
+
+ if (start == i || this == i)
+ break;
+ ndest= i->opt_shortcut_jump(sp, start);
+ if (ndest == dest)
+ break;
+ dest= ndest;
+ }
+ return dest;
+}
+
+void
+sp_instr_jump::opt_move(uint dst, List<sp_instr> *bp)
+{
+ if (m_dest > m_ip)
+ bp->push_back(this); // Forward
+ else if (m_optdest)
+ m_dest= m_optdest->m_ip; // Backward
+ m_ip= dst;
+}
+
+
+/*
+ sp_instr_jump_if class functions
+*/
+
+int
+sp_instr_jump_if::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_jump_if::execute");
+ DBUG_PRINT("info", ("destination: %u", m_dest));
+ DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this));
+}
+
+int
+sp_instr_jump_if::exec_core(THD *thd, uint *nextp)
+{
+ Item *it;
+ int res;
+
+ it= sp_prepare_func_item(thd, &m_expr);
+ if (!it)
+ res= -1;
+ else
+ {
+ res= 0;
+ if (it->val_bool())
+ *nextp = m_dest;
+ else
+ *nextp = m_ip+1;
+ }
+
+ return res;
+}
+
+void
+sp_instr_jump_if::print(String *str)
+{
+ str->reserve(12);
+ str->append("jump_if ");
+ str->qs_append(m_dest);
+ str->append(' ');
+ m_expr->print(str);
+}
+
+uint
+sp_instr_jump_if::opt_mark(sp_head *sp)
+{
+ sp_instr *i;
+
+ marked= 1;
+ if ((i= sp->get_instr(m_dest)))
+ {
+ m_dest= i->opt_shortcut_jump(sp, this);
+ m_optdest= sp->get_instr(m_dest);
+ }
+ sp->opt_mark(m_dest);
+ return m_ip+1;
+}
+
+
+/*
+ sp_instr_jump_if_not class functions
+*/
+
+int
+sp_instr_jump_if_not::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_jump_if_not::execute");
+ DBUG_PRINT("info", ("destination: %u", m_dest));
+ DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this));
+}
+
+
+int
+sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp)
+{
+ Item *it;
+ int res;
+
+ it= sp_prepare_func_item(thd, &m_expr);
+ if (! it)
+ res= -1;
+ else
+ {
+ res= 0;
+ if (! it->val_bool())
+ *nextp = m_dest;
+ else
+ *nextp = m_ip+1;
+ }
+
+ return res;
+}
+
+
+void
+sp_instr_jump_if_not::print(String *str)
+{
+ str->reserve(16);
+ str->append("jump_if_not ");
+ str->qs_append(m_dest);
+ str->append(' ');
+ m_expr->print(str);
+}
+
+
+uint
+sp_instr_jump_if_not::opt_mark(sp_head *sp)
+{
+ sp_instr *i;
+
+ marked= 1;
+ if ((i= sp->get_instr(m_dest)))
+ {
+ m_dest= i->opt_shortcut_jump(sp, this);
+ m_optdest= sp->get_instr(m_dest);
+ }
+ sp->opt_mark(m_dest);
+ return m_ip+1;
+}
+
+
+/*
+ sp_instr_freturn class functions
+*/
+
+int
+sp_instr_freturn::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_freturn::execute");
+ DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this));
+}
+
+
+int
+sp_instr_freturn::exec_core(THD *thd, uint *nextp)
+{
+ Item *it;
+ int res;
+
+ it= sp_eval_func_item(thd, &m_value, m_type, NULL, TRUE);
+ if (! it)
+ res= -1;
+ else
+ {
+ res= 0;
+ thd->spcont->set_result(it);
+ }
+ *nextp= UINT_MAX;
+
+ return res;
+}
+
+void
+sp_instr_freturn::print(String *str)
+{
+ str->reserve(12);
+ str->append("freturn ");
+ str->qs_append((uint)m_type);
+ str->append(' ');
+ m_value->print(str);
+}
+
+/*
+ sp_instr_hpush_jump class functions
+*/
+
+int
+sp_instr_hpush_jump::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_hpush_jump::execute");
+ List_iterator_fast<sp_cond_type_t> li(m_cond);
+ sp_cond_type_t *p;
+
+ while ((p= li++))
+ thd->spcont->push_handler(p, m_ip+1, m_type, m_frame);
+
+ *nextp= m_dest;
+ DBUG_RETURN(0);
+}
+
+void
+sp_instr_hpush_jump::print(String *str)
+{
+ str->reserve(32);
+ str->append("hpush_jump ");
+ str->qs_append(m_dest);
+ str->append(" t=");
+ str->qs_append(m_type);
+ str->append(" f=");
+ str->qs_append(m_frame);
+ str->append(" h=");
+ str->qs_append(m_ip+1);
+}
+
+uint
+sp_instr_hpush_jump::opt_mark(sp_head *sp)
+{
+ sp_instr *i;
+
+ marked= 1;
+ if ((i= sp->get_instr(m_dest)))
+ {
+ m_dest= i->opt_shortcut_jump(sp, this);
+ m_optdest= sp->get_instr(m_dest);
+ }
+ sp->opt_mark(m_dest);
+ return m_ip+1;
+}
+
+
+/*
+ sp_instr_hpop class functions
+*/
+
+int
+sp_instr_hpop::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_hpop::execute");
+ thd->spcont->pop_handlers(m_count);
+ *nextp= m_ip+1;
+ DBUG_RETURN(0);
+}
+
+void
+sp_instr_hpop::print(String *str)
+{
+ str->reserve(12);
+ str->append("hpop ");
+ str->qs_append(m_count);
+}
+
+void
+sp_instr_hpop::backpatch(uint dest, sp_pcontext *dst_ctx)
+{
+ m_count= m_ctx->diff_handlers(dst_ctx);
+}
+
+
+/*
+ sp_instr_hreturn class functions
+*/
+
+int
+sp_instr_hreturn::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_hreturn::execute");
+ if (m_dest)
+ *nextp= m_dest;
+ else
+ {
+ thd->spcont->restore_variables(m_frame);
+ *nextp= thd->spcont->pop_hstack();
+ }
+ thd->spcont->in_handler= FALSE;
+ DBUG_RETURN(0);
+}
+
+
+void
+sp_instr_hreturn::print(String *str)
+{
+ str->reserve(16);
+ str->append("hreturn ");
+ str->qs_append(m_frame);
+ if (m_dest)
+ str->qs_append(m_dest);
+}
+
+
+uint
+sp_instr_hreturn::opt_mark(sp_head *sp)
+{
+ if (m_dest)
+ return sp_instr_jump::opt_mark(sp);
+ else
+ {
+ marked= 1;
+ return UINT_MAX;
+ }
+}
+
+
+/*
+ sp_instr_cpush class functions
+*/
+
+int
+sp_instr_cpush::execute(THD *thd, uint *nextp)
+{
+ Query_arena backup_arena;
+ DBUG_ENTER("sp_instr_cpush::execute");
+
+ /*
+ We should create cursors in the callers arena, as
+ it could be (and usually is) used in several instructions.
+ */
+ thd->set_n_backup_active_arena(thd->spcont->callers_arena, &backup_arena);
+
+ thd->spcont->push_cursor(&m_lex_keeper, this);
+
+ thd->restore_active_arena(thd->spcont->callers_arena, &backup_arena);
+
+ *nextp= m_ip+1;
+
+ DBUG_RETURN(0);
+}
+
+
+void
+sp_instr_cpush::print(String *str)
+{
+ str->append("cpush");
+}
+
+
+/*
+ sp_instr_cpop class functions
+*/
+
+int
+sp_instr_cpop::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_cpop::execute");
+ thd->spcont->pop_cursors(m_count);
+ *nextp= m_ip+1;
+ DBUG_RETURN(0);
+}
+
+
+void
+sp_instr_cpop::print(String *str)
+{
+ str->reserve(12);
+ str->append("cpop ");
+ str->qs_append(m_count);
+}
+
+void
+sp_instr_cpop::backpatch(uint dest, sp_pcontext *dst_ctx)
+{
+ m_count= m_ctx->diff_cursors(dst_ctx);
+}
+
+
+/*
+ sp_instr_copen class functions
+*/
+
+int
+sp_instr_copen::execute(THD *thd, uint *nextp)
+{
+ sp_cursor *c= thd->spcont->get_cursor(m_cursor);
+ int res;
+ DBUG_ENTER("sp_instr_copen::execute");
+
+ if (! c)
+ res= -1;
+ else
+ {
+ sp_lex_keeper *lex_keeper= c->pre_open(thd);
+ if (!lex_keeper) // cursor already open or OOM
+ {
+ res= -1;
+ *nextp= m_ip+1;
+ }
+ else
+ {
+ Query_arena *old_arena= thd->stmt_arena;
+
+ /*
+ Get the Query_arena from the cpush instruction, which contains
+ the free_list of the query, so new items (if any) are stored in
+ the right free_list, and we can cleanup after each open.
+ */
+ thd->stmt_arena= c->get_instr();
+ res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this);
+ /* Cleanup the query's items */
+ if (thd->stmt_arena->free_list)
+ cleanup_items(thd->stmt_arena->free_list);
+ thd->stmt_arena= old_arena;
+ /*
+ Work around the fact that errors in selects are not returned properly
+ (but instead converted into a warning), so if a condition handler
+ caught, we have lost the result code.
+ */
+ if (!res)
+ {
+ uint dummy1, dummy2;
+
+ if (thd->spcont->found_handler(&dummy1, &dummy2))
+ res= -1;
+ }
+ c->post_open(thd, res ? FALSE : TRUE);
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+int
+sp_instr_copen::exec_core(THD *thd, uint *nextp)
+{
+ int res= mysql_execute_command(thd);
+ *nextp= m_ip+1;
+ return res;
+}
+
+void
+sp_instr_copen::print(String *str)
+{
+ str->reserve(12);
+ str->append("copen ");
+ str->qs_append(m_cursor);
+}
+
+
+/*
+ sp_instr_cclose class functions
+*/
+
+int
+sp_instr_cclose::execute(THD *thd, uint *nextp)
+{
+ sp_cursor *c= thd->spcont->get_cursor(m_cursor);
+ int res;
+ DBUG_ENTER("sp_instr_cclose::execute");
+
+ if (! c)
+ res= -1;
+ else
+ res= c->close(thd);
+ *nextp= m_ip+1;
+ DBUG_RETURN(res);
+}
+
+
+void
+sp_instr_cclose::print(String *str)
+{
+ str->reserve(12);
+ str->append("cclose ");
+ str->qs_append(m_cursor);
+}
+
+
+/*
+ sp_instr_cfetch class functions
+*/
+
+int
+sp_instr_cfetch::execute(THD *thd, uint *nextp)
+{
+ sp_cursor *c= thd->spcont->get_cursor(m_cursor);
+ int res;
+ Query_arena backup_arena;
+ DBUG_ENTER("sp_instr_cfetch::execute");
+
+ if (! c)
+ res= -1;
+ else
+ {
+ thd->set_n_backup_active_arena(thd->spcont->callers_arena, &backup_arena);
+ res= c->fetch(thd, &m_varlist);
+ thd->restore_active_arena(thd->spcont->callers_arena, &backup_arena);
+ }
+
+ *nextp= m_ip+1;
+ DBUG_RETURN(res);
+}
+
+
+void
+sp_instr_cfetch::print(String *str)
+{
+ List_iterator_fast<struct sp_pvar> li(m_varlist);
+ sp_pvar_t *pv;
+
+ str->reserve(12);
+ str->append("cfetch ");
+ str->qs_append(m_cursor);
+ while ((pv= li++))
+ {
+ str->reserve(8);
+ str->append(' ');
+ str->qs_append(pv->offset);
+ }
+}
+
+
+/*
+ sp_instr_error class functions
+*/
+
+int
+sp_instr_error::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_error::execute");
+
+ my_message(m_errcode, ER(m_errcode), MYF(0));
+ *nextp= m_ip+1;
+ DBUG_RETURN(-1);
+}
+
+
+void
+sp_instr_error::print(String *str)
+{
+ str->reserve(12);
+ str->append("error ");
+ str->qs_append(m_errcode);
+}
+
+
+/* ------------------------------------------------------------------ */
+
+/*
+ Security context swapping
+*/
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+void
+sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
+{
+ ctxp->changed= (sp->m_chistics->suid != SP_IS_NOT_SUID &&
+ (strcmp(sp->m_definer_user.str, thd->priv_user) ||
+ strcmp(sp->m_definer_host.str, thd->priv_host)));
+
+ if (ctxp->changed)
+ {
+ ctxp->master_access= thd->master_access;
+ ctxp->db_access= thd->db_access;
+ ctxp->priv_user= thd->priv_user;
+ strncpy(ctxp->priv_host, thd->priv_host, sizeof(ctxp->priv_host));
+ ctxp->user= thd->user;
+ ctxp->host= thd->host;
+ ctxp->ip= thd->ip;
+
+ /* Change thise just to do the acl_getroot_no_password */
+ thd->user= sp->m_definer_user.str;
+ thd->host= thd->ip = sp->m_definer_host.str;
+
+ if (acl_getroot_no_password(thd))
+ { // Failed, run as invoker for now
+ ctxp->changed= FALSE;
+ thd->master_access= ctxp->master_access;
+ thd->db_access= ctxp->db_access;
+ thd->priv_user= ctxp->priv_user;
+ strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host));
+ }
+
+ /* Restore these immiediately */
+ thd->user= ctxp->user;
+ thd->host= ctxp->host;
+ thd->ip= ctxp->ip;
+ }
+}
+
+void
+sp_restore_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
+{
+ if (ctxp->changed)
+ {
+ ctxp->changed= FALSE;
+ thd->master_access= ctxp->master_access;
+ thd->db_access= ctxp->db_access;
+ thd->priv_user= ctxp->priv_user;
+ strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host));
+ }
+}
+
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
+
+/*
+ Structure that represent all instances of one table
+ in optimized multi-set of tables used by routine.
+*/
+
+typedef struct st_sp_table
+{
+ LEX_STRING qname; /* Multi-set key: db_name\0table_name\0alias\0 */
+ uint db_length, table_name_length;
+ bool temp; /* true if corresponds to a temporary table */
+ thr_lock_type lock_type; /* lock type used for prelocking */
+ uint lock_count;
+ uint query_lock_count;
+} SP_TABLE;
+
+byte *
+sp_table_key(const byte *ptr, uint *plen, my_bool first)
+{
+ SP_TABLE *tab= (SP_TABLE *)ptr;
+ *plen= tab->qname.length;
+ return (byte *)tab->qname.str;
+}
+
+
+/*
+ Merge the list of tables used by some query into the multi-set of
+ tables used by routine.
+
+ SYNOPSIS
+ merge_table_list()
+ thd - thread context
+ table - table list
+ lex_for_tmp_check - LEX of the query for which we are merging
+ table list.
+
+ NOTE
+ This method will use LEX provided to check whenever we are creating
+ temporary table and mark it as such in target multi-set.
+
+ RETURN VALUE
+ TRUE - Success
+ FALSE - Error
+*/
+
+bool
+sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
+{
+ SP_TABLE *tab;
+
+ if (lex_for_tmp_check->sql_command == SQLCOM_DROP_TABLE &&
+ lex_for_tmp_check->drop_temporary)
+ return TRUE;
+
+ for (uint i= 0 ; i < m_sptabs.records ; i++)
+ {
+ tab= (SP_TABLE *)hash_element(&m_sptabs, i);
+ tab->query_lock_count= 0;
+ }
+
+ for (; table ; table= table->next_global)
+ if (!table->derived && !table->schema_table)
+ {
+ char tname[(NAME_LEN + 1) * 3]; // db\0table\0alias\0
+ uint tlen, alen;
+
+ tlen= table->db_length;
+ memcpy(tname, table->db, tlen);
+ tname[tlen++]= '\0';
+ memcpy(tname+tlen, table->table_name, table->table_name_length);
+ tlen+= table->table_name_length;
+ tname[tlen++]= '\0';
+ alen= strlen(table->alias);
+ memcpy(tname+tlen, table->alias, alen);
+ tlen+= alen;
+ tname[tlen]= '\0';
+
+ /*
+ It is safe to store pointer to table list elements in hash,
+ since they are supposed to have the same lifetime.
+ */
+ if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (byte *)tname, tlen)))
+ {
+ if (tab->lock_type < table->lock_type)
+ tab->lock_type= table->lock_type; // Use the table with the highest lock type
+ tab->query_lock_count++;
+ if (tab->query_lock_count > tab->lock_count)
+ tab->lock_count++;
+ }
+ else
+ {
+ if (!(tab= (SP_TABLE *)thd->calloc(sizeof(SP_TABLE))))
+ return FALSE;
+ tab->qname.length= tlen;
+ tab->qname.str= (char*) thd->memdup(tname, tab->qname.length + 1);
+ if (!tab->qname.str)
+ return FALSE;
+ if (lex_for_tmp_check->sql_command == SQLCOM_CREATE_TABLE &&
+ lex_for_tmp_check->query_tables == table &&
+ lex_for_tmp_check->create_info.options & HA_LEX_CREATE_TMP_TABLE)
+ tab->temp= TRUE;
+ tab->table_name_length= table->table_name_length;
+ tab->db_length= table->db_length;
+ tab->lock_type= table->lock_type;
+ tab->lock_count= tab->query_lock_count= 1;
+ my_hash_insert(&m_sptabs, (byte *)tab);
+ }
+ }
+ return TRUE;
+}
+
+
+/*
+ Add tables used by routine to the table list.
+
+ SYNOPSIS
+ add_used_tables_to_table_list()
+ thd - thread context
+ query_tables_last_ptr - (in/out) pointer the next_global member of last
+ element of the list where tables will be added
+ (or to its root).
+
+ DESCRIPTION
+ Converts multi-set of tables used by this routine to table list and adds
+ this list to the end of table list specified by 'query_tables_last_ptr'.
+
+ Elements of list will be allocated in PS memroot, so this list will be
+ persistent between PS executions.
+
+ RETURN VALUE
+ TRUE - if some elements were added, FALSE - otherwise.
+*/
+
+bool
+sp_head::add_used_tables_to_table_list(THD *thd,
+ TABLE_LIST ***query_tables_last_ptr)
+{
+ uint i;
+ Query_arena *arena, backup;
+ bool result= FALSE;
+ DBUG_ENTER("sp_head::add_used_tables_to_table_list");
+
+ /*
+ Use persistent arena for table list allocation to be PS friendly.
+ */
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+
+ for (i=0 ; i < m_sptabs.records ; i++)
+ {
+ char *tab_buff;
+ TABLE_LIST *table;
+ SP_TABLE *stab= (SP_TABLE *)hash_element(&m_sptabs, i);
+ if (stab->temp)
+ continue;
+
+ if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) *
+ stab->lock_count)))
+ DBUG_RETURN(FALSE);
+
+ for (uint j= 0; j < stab->lock_count; j++)
+ {
+ table= (TABLE_LIST *)tab_buff;
+
+ /*
+ It's enough to just copy the pointers as the data will not change
+ during the lifetime of the SP. If the SP is used by PS, we assume
+ that the PS will be invalidated if the functions is deleted or
+ changed.
+ */
+ table->db= stab->qname.str;
+ table->db_length= stab->db_length;
+ table->table_name= table->db + table->db_length + 1;
+ table->table_name_length= stab->table_name_length;
+ table->alias= table->table_name + table->table_name_length + 1;
+ table->lock_type= stab->lock_type;
+ table->cacheable_table= 1;
+ table->prelocking_placeholder= 1;
+
+ /* Everyting else should be zeroed */
+
+ **query_tables_last_ptr= table;
+ table->prev_global= *query_tables_last_ptr;
+ *query_tables_last_ptr= &table->next_global;
+
+ tab_buff+= ALIGN_SIZE(sizeof(TABLE_LIST));
+ result= TRUE;
+ }
+ }
+
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Simple function for adding an explicetly named (systems) table to
+ the global table list, e.g. "mysql", "proc".
+*/
+
+TABLE_LIST *
+sp_add_to_query_tables(THD *thd, LEX *lex,
+ const char *db, const char *name,
+ thr_lock_type locktype)
+{
+ TABLE_LIST *table;
+
+ if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(TABLE_LIST));
+ return NULL;
+ }
+ table->db_length= strlen(db);
+ table->db= thd->strmake(db, table->db_length);
+ table->table_name_length= strlen(name);
+ table->table_name= thd->strmake(name, table->table_name_length);
+ table->alias= thd->strdup(name);
+ table->lock_type= locktype;
+ table->select_lex= lex->current_select; // QQ?
+ table->cacheable_table= 1;
+
+ lex->add_to_query_tables(table);
+ return table;
+}
+
diff --git a/sql/sp_head.h b/sql/sp_head.h
new file mode 100644
index 00000000000..9888fe74149
--- /dev/null
+++ b/sql/sp_head.h
@@ -0,0 +1,1044 @@
+/* -*- C++ -*- */
+/* 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 */
+
+#ifndef _SP_HEAD_H_
+#define _SP_HEAD_H_
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+#include <stddef.h>
+
+// Values for the type enum. This reflects the order of the enum declaration
+// in the CREATE TABLE command.
+#define TYPE_ENUM_FUNCTION 1
+#define TYPE_ENUM_PROCEDURE 2
+#define TYPE_ENUM_TRIGGER 3
+
+Item_result
+sp_map_result_type(enum enum_field_types type);
+
+uint
+sp_get_flags_for_command(LEX *lex);
+
+struct sp_label;
+class sp_instr;
+struct sp_cond_type;
+struct sp_pvar;
+
+class sp_name : public Sql_alloc
+{
+public:
+
+ LEX_STRING m_db;
+ LEX_STRING m_name;
+ LEX_STRING m_qname;
+ /*
+ Key representing routine in the set of stored routines used by statement.
+ Consists of 1-byte routine type and m_qname (which usually refences to
+ same buffer). Note that one must complete initialization of the key by
+ calling set_routine_type().
+ */
+ LEX_STRING m_sroutines_key;
+
+ sp_name(LEX_STRING name)
+ : m_name(name)
+ {
+ m_db.str= m_qname.str= m_sroutines_key.str= 0;
+ m_db.length= m_qname.length= m_sroutines_key.length= 0;
+ }
+
+ sp_name(LEX_STRING db, LEX_STRING name)
+ : m_db(db), m_name(name)
+ {
+ m_qname.str= m_sroutines_key.str= 0;
+ m_qname.length= m_sroutines_key.length= 0;
+ }
+
+ /*
+ Creates temporary sp_name object from key, used mainly
+ for SP-cache lookups.
+ */
+ sp_name(char *key, uint key_len)
+ {
+ m_sroutines_key.str= key;
+ m_sroutines_key.length= key_len;
+ m_name.str= m_qname.str= key + 1;
+ m_name.length= m_qname.length= key_len - 1;
+ m_db.str= 0;
+ m_db.length= 0;
+ }
+
+ // Init. the qualified name from the db and name.
+ void init_qname(THD *thd); // thd for memroot allocation
+
+ void set_routine_type(char type)
+ {
+ m_sroutines_key.str[0]= type;
+ }
+
+ ~sp_name()
+ {}
+};
+
+sp_name *
+sp_name_current_db_new(THD *thd, LEX_STRING name);
+
+
+class sp_head :private Query_arena
+{
+ sp_head(const sp_head &); /* Prevent use of these */
+ void operator=(sp_head &);
+
+ MEM_ROOT main_mem_root;
+public:
+ /* Possible values of m_flags */
+ enum {
+ HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN
+ IN_SIMPLE_CASE= 2, // Is set if parsing a simple CASE
+ IN_HANDLER= 4, // Is set if the parser is in a handler body
+ MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s)
+ CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE
+ IS_INVOKED= 32, // Is set if this sp_head is being used
+ HAS_SET_AUTOCOMMIT_STMT = 64 // Is set if a procedure with 'set autocommit'
+ };
+
+ int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
+ uint m_flags; // Boolean attributes of a stored routine
+ enum enum_field_types m_returns; // For FUNCTIONs only
+ Field::geometry_type m_geom_returns;
+ CHARSET_INFO *m_returns_cs; // For FUNCTIONs only
+ TYPELIB *m_returns_typelib; // For FUNCTIONs only
+ uint m_returns_len; // For FUNCTIONs only
+ uint m_returns_pack; // For FUNCTIONs only
+ uchar *m_tmp_query; // Temporary pointer to sub query string
+ uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
+ st_sp_chistics *m_chistics;
+ ulong m_sql_mode; // For SHOW CREATE and execution
+ LEX_STRING m_qname; // db.name
+ LEX_STRING m_db;
+ LEX_STRING m_name;
+ LEX_STRING m_params;
+ LEX_STRING m_body;
+ LEX_STRING m_defstr;
+ LEX_STRING m_definer_user;
+ LEX_STRING m_definer_host;
+ longlong m_created;
+ longlong m_modified;
+ /*
+ Set containing names of stored routines used by this routine.
+ Note that unlike elements of similar set for statement elements of this
+ set are not linked in one list. Because of this we are able save memory
+ by using for this set same objects that are used in 'sroutines' sets
+ for statements of which this stored routine consists.
+ */
+ HASH m_sroutines;
+ // Pointers set during parsing
+ uchar *m_param_begin, *m_param_end, *m_body_begin;
+
+ static void *
+ operator new(size_t size);
+
+ static void
+ operator delete(void *ptr, size_t size);
+
+ sp_head();
+
+ // Initialize after we have reset mem_root
+ void
+ init(LEX *lex);
+
+ // Initialize strings after parsing header
+ void
+ init_strings(THD *thd, LEX *lex, sp_name *name);
+
+ TYPELIB *
+ create_typelib(List<String> *src);
+
+ int
+ create(THD *thd);
+
+ virtual ~sp_head();
+
+ // Free memory
+ void
+ destroy();
+
+ int
+ execute_function(THD *thd, Item **args, uint argcount, Item **resp);
+
+ int
+ execute_procedure(THD *thd, List<Item> *args);
+
+ int
+ show_create_procedure(THD *thd);
+
+ int
+ show_create_function(THD *thd);
+
+ void
+ add_instr(sp_instr *instr);
+
+ inline uint
+ instructions()
+ {
+ return m_instr.elements;
+ }
+
+ inline sp_instr *
+ last_instruction()
+ {
+ sp_instr *i;
+
+ get_dynamic(&m_instr, (gptr)&i, m_instr.elements-1);
+ return i;
+ }
+
+ // Resets lex in 'thd' and keeps a copy of the old one.
+ void
+ reset_lex(THD *thd);
+
+ // Restores lex in 'thd' from our copy, but keeps some status from the
+ // one in 'thd', like ptr, tables, fields, etc.
+ void
+ restore_lex(THD *thd);
+
+ // Put the instruction on the backpatch list, associated with the label.
+ void
+ push_backpatch(sp_instr *, struct sp_label *);
+
+ // Update all instruction with this label in the backpatch list to
+ // the current position.
+ void
+ backpatch(struct sp_label *);
+
+ // Check that no unresolved references exist.
+ // If none found, 0 is returned, otherwise errors have been issued
+ // and -1 is returned.
+ // This is called by the parser at the end of a create procedure/function.
+ int
+ check_backpatch(THD *thd);
+
+ char *name(uint *lenp = 0) const
+ {
+ if (lenp)
+ *lenp= m_name.length;
+ return m_name.str;
+ }
+
+ char *create_string(THD *thd, ulong *lenp);
+
+ Field *make_field(uint max_length, const char *name, TABLE *dummy);
+
+ void set_info(char *definer, uint definerlen,
+ longlong created, longlong modified,
+ st_sp_chistics *chistics, ulong sql_mode);
+
+ void reset_thd_mem_root(THD *thd);
+
+ void restore_thd_mem_root(THD *thd);
+
+ void optimize();
+ void opt_mark(uint ip);
+
+ inline sp_instr *
+ get_instr(uint i)
+ {
+ sp_instr *ip;
+
+ if (i < m_instr.elements)
+ get_dynamic(&m_instr, (gptr)&ip, i);
+ else
+ ip= NULL;
+ return ip;
+ }
+
+ /* Add tables used by routine to the table list. */
+ bool add_used_tables_to_table_list(THD *thd,
+ TABLE_LIST ***query_tables_last_ptr);
+
+ /*
+ Check if this stored routine contains statements disallowed
+ in a stored function or trigger, and set an appropriate error message
+ if this is the case.
+ */
+ bool is_not_allowed_in_function(const char *where)
+ {
+ if (m_flags & CONTAINS_DYNAMIC_SQL)
+ my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "Dynamic SQL");
+ else if (m_flags & MULTI_RESULTS)
+ my_error(ER_SP_NO_RETSET, MYF(0), where);
+ else if (m_flags & HAS_SET_AUTOCOMMIT_STMT)
+ my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0));
+ return test(m_flags &
+ (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT));
+ }
+private:
+
+ MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
+ THD *m_thd; // Set if we have reset mem_root
+ char *m_thd_db; // Original thd->db pointer
+
+ sp_pcontext *m_pcont; // Parse context
+ List<LEX> m_lex; // Temp. store for the other lex
+ DYNAMIC_ARRAY m_instr; // The "instructions"
+ typedef struct
+ {
+ struct sp_label *lab;
+ sp_instr *instr;
+ } bp_t;
+ List<bp_t> m_backpatch; // Instructions needing backpatching
+ /*
+ Multi-set representing optimized list of tables to be locked by this
+ routine. Does not include tables which are used by invoked routines.
+
+ Note: for prelocking-free SPs this multiset is constructed too.
+ We do so because the same instance of sp_head may be called both
+ in prelocked mode and in non-prelocked mode.
+ */
+ HASH m_sptabs;
+
+ int
+ execute(THD *thd);
+
+ /*
+ Merge the list of tables used by query into the multi-set of tables used
+ by routine.
+ */
+ bool merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check);
+}; // class sp_head : public Sql_alloc
+
+
+//
+// "Instructions"...
+//
+
+class sp_instr :public Query_arena, public Sql_alloc
+{
+ sp_instr(const sp_instr &); /* Prevent use of these */
+ void operator=(sp_instr &);
+
+public:
+
+ uint marked;
+ uint m_ip; // My index
+ sp_pcontext *m_ctx; // My parse context
+
+ // Should give each a name or type code for debugging purposes?
+ sp_instr(uint ip, sp_pcontext *ctx)
+ :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
+ {}
+
+ virtual ~sp_instr()
+ { free_items(); }
+
+
+ /*
+ Execute this instruction
+
+ SYNOPSIS
+ execute()
+ thd Thread handle
+ nextp OUT index of the next instruction to execute. (For most
+ instructions this will be the instruction following this
+ one).
+
+ RETURN
+ 0 on success,
+ other if some error occured
+ */
+
+ virtual int execute(THD *thd, uint *nextp) = 0;
+
+ /*
+ Execute core function of instruction after all preparations (e.g.
+ setting of proper LEX, saving part of the thread context have been
+ done).
+
+ Should be implemented for instructions using expressions or whole
+ statements (thus having to have own LEX). Used in concert with
+ sp_lex_keeper class and its descendants (there are none currently).
+ */
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str) = 0;
+
+ virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
+ {}
+
+ virtual uint opt_mark(sp_head *sp)
+ {
+ marked= 1;
+ return m_ip+1;
+ }
+
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
+ {
+ return m_ip;
+ }
+
+ virtual void opt_move(uint dst, List<sp_instr> *ibp)
+ {
+ m_ip= dst;
+ }
+
+}; // class sp_instr : public Sql_alloc
+
+
+/*
+ Auxilary class to which instructions delegate responsibility
+ for handling LEX and preparations before executing statement
+ or calculating complex expression.
+
+ Exist mainly to avoid having double hierarchy between instruction
+ classes.
+
+ TODO: Add ability to not store LEX and do any preparations if
+ expression used is simple.
+*/
+
+class sp_lex_keeper
+{
+ /* Prevent use of these */
+ sp_lex_keeper(const sp_lex_keeper &);
+ void operator=(sp_lex_keeper &);
+public:
+
+ sp_lex_keeper(LEX *lex, bool lex_resp)
+ : m_lex(lex), m_lex_resp(lex_resp),
+ lex_query_tables_own_last(NULL)
+ {
+ lex->sp_lex_in_use= TRUE;
+ }
+ virtual ~sp_lex_keeper()
+ {
+ if (m_lex_resp)
+ delete m_lex;
+ }
+
+ /*
+ Prepare execution of instruction using LEX, if requested check whenever
+ we have read access to tables used and open/lock them, call instruction's
+ exec_core() method, perform cleanup afterwards.
+ */
+ int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
+ sp_instr* instr);
+
+ inline uint sql_command() const
+ {
+ return (uint)m_lex->sql_command;
+ }
+
+ void disable_query_cache()
+ {
+ m_lex->safe_to_cache_query= 0;
+ }
+private:
+
+ LEX *m_lex;
+ /*
+ Indicates whenever this sp_lex_keeper instance responsible
+ for LEX deletion.
+ */
+ bool m_lex_resp;
+
+ /*
+ Support for being able to execute this statement in two modes:
+ a) inside prelocked mode set by the calling procedure or its ancestor.
+ b) outside of prelocked mode, when this statement enters/leaves
+ prelocked mode itself.
+ */
+
+ /*
+ List of additional tables this statement needs to lock when it
+ enters/leaves prelocked mode on its own.
+ */
+ TABLE_LIST *prelocking_tables;
+
+ /*
+ The value m_lex->query_tables_own_last should be set to this when the
+ statement enters/leaves prelocked mode on its own.
+ */
+ TABLE_LIST **lex_query_tables_own_last;
+};
+
+
+//
+// Call out to some prepared SQL statement.
+//
+class sp_instr_stmt : public sp_instr
+{
+ sp_instr_stmt(const sp_instr_stmt &); /* Prevent use of these */
+ void operator=(sp_instr_stmt &);
+
+public:
+
+ LEX_STRING m_query; // For thd->query
+
+ sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex)
+ : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
+ {
+ m_query.str= 0;
+ m_query.length= 0;
+ }
+
+ virtual ~sp_instr_stmt()
+ {};
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+private:
+
+ sp_lex_keeper m_lex_keeper;
+
+}; // class sp_instr_stmt : public sp_instr
+
+
+class sp_instr_set : public sp_instr
+{
+ sp_instr_set(const sp_instr_set &); /* Prevent use of these */
+ void operator=(sp_instr_set &);
+
+public:
+
+ sp_instr_set(uint ip, sp_pcontext *ctx,
+ uint offset, Item *val, enum enum_field_types type,
+ LEX *lex, bool lex_resp)
+ : sp_instr(ip, ctx), m_offset(offset), m_value(val), m_type(type),
+ m_lex_keeper(lex, lex_resp)
+ {}
+
+ virtual ~sp_instr_set()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+private:
+
+ uint m_offset; // Frame offset
+ Item *m_value;
+ enum enum_field_types m_type; // The declared type
+ sp_lex_keeper m_lex_keeper;
+
+}; // class sp_instr_set : public sp_instr
+
+
+/*
+ Set NEW/OLD row field value instruction. Used in triggers.
+*/
+class sp_instr_set_trigger_field : public sp_instr
+{
+ sp_instr_set_trigger_field(const sp_instr_set_trigger_field &);
+ void operator=(sp_instr_set_trigger_field &);
+
+public:
+
+ sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
+ Item_trigger_field *trg_fld,
+ Item *val, LEX *lex)
+ : sp_instr(ip, ctx),
+ trigger_field(trg_fld),
+ value(val), m_lex_keeper(lex, TRUE)
+ {}
+
+ virtual ~sp_instr_set_trigger_field()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+private:
+ Item_trigger_field *trigger_field;
+ Item *value;
+ sp_lex_keeper m_lex_keeper;
+}; // class sp_instr_trigger_field : public sp_instr
+
+
+class sp_instr_jump : public sp_instr
+{
+ sp_instr_jump(const sp_instr_jump &); /* Prevent use of these */
+ void operator=(sp_instr_jump &);
+
+public:
+
+ uint m_dest; // Where we will go
+
+ sp_instr_jump(uint ip, sp_pcontext *ctx)
+ : sp_instr(ip, ctx), m_dest(0), m_optdest(0)
+ {}
+
+ sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
+ : sp_instr(ip, ctx), m_dest(dest), m_optdest(0)
+ {}
+
+ virtual ~sp_instr_jump()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual uint opt_mark(sp_head *sp);
+
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start);
+
+ virtual void opt_move(uint dst, List<sp_instr> *ibp);
+
+ virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
+ {
+ if (m_dest == 0) // Don't reset
+ m_dest= dest;
+ }
+
+protected:
+
+ sp_instr *m_optdest; // Used during optimization
+
+}; // class sp_instr_jump : public sp_instr
+
+
+class sp_instr_jump_if : public sp_instr_jump
+{
+ sp_instr_jump_if(const sp_instr_jump_if &); /* Prevent use of these */
+ void operator=(sp_instr_jump_if &);
+
+public:
+
+ sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, LEX *lex)
+ : sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE)
+ {}
+
+ sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
+ : sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE)
+ {}
+
+ virtual ~sp_instr_jump_if()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual uint opt_mark(sp_head *sp);
+
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
+ {
+ return m_ip;
+ }
+
+private:
+
+ Item *m_expr; // The condition
+ sp_lex_keeper m_lex_keeper;
+
+}; // class sp_instr_jump_if : public sp_instr_jump
+
+
+class sp_instr_jump_if_not : public sp_instr_jump
+{
+ sp_instr_jump_if_not(const sp_instr_jump_if_not &); /* Prevent use of these */
+ void operator=(sp_instr_jump_if_not &);
+
+public:
+
+ sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex)
+ : sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE)
+ {}
+
+ sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
+ : sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE)
+ {}
+
+ virtual ~sp_instr_jump_if_not()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual uint opt_mark(sp_head *sp);
+
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
+ {
+ return m_ip;
+ }
+
+private:
+
+ Item *m_expr; // The condition
+ sp_lex_keeper m_lex_keeper;
+
+}; // class sp_instr_jump_if_not : public sp_instr_jump
+
+
+class sp_instr_freturn : public sp_instr
+{
+ sp_instr_freturn(const sp_instr_freturn &); /* Prevent use of these */
+ void operator=(sp_instr_freturn &);
+
+public:
+
+ sp_instr_freturn(uint ip, sp_pcontext *ctx,
+ Item *val, enum enum_field_types type, LEX *lex)
+ : sp_instr(ip, ctx), m_value(val), m_type(type), m_lex_keeper(lex, TRUE)
+ {}
+
+ virtual ~sp_instr_freturn()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual uint opt_mark(sp_head *sp)
+ {
+ marked= 1;
+ return UINT_MAX;
+ }
+
+protected:
+
+ Item *m_value;
+ enum enum_field_types m_type;
+ sp_lex_keeper m_lex_keeper;
+
+}; // class sp_instr_freturn : public sp_instr
+
+
+class sp_instr_hpush_jump : public sp_instr_jump
+{
+ sp_instr_hpush_jump(const sp_instr_hpush_jump &); /* Prevent use of these */
+ void operator=(sp_instr_hpush_jump &);
+
+public:
+
+ sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, int htype, uint fp)
+ : sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp)
+ {
+ m_cond.empty();
+ }
+
+ virtual ~sp_instr_hpush_jump()
+ {
+ m_cond.empty();
+ }
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual uint opt_mark(sp_head *sp);
+
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
+ {
+ return m_ip;
+ }
+
+ inline void add_condition(struct sp_cond_type *cond)
+ {
+ m_cond.push_front(cond);
+ }
+
+private:
+
+ int m_type; // Handler type
+ uint m_frame;
+ List<struct sp_cond_type> m_cond;
+
+}; // class sp_instr_hpush_jump : public sp_instr_jump
+
+
+class sp_instr_hpop : public sp_instr
+{
+ sp_instr_hpop(const sp_instr_hpop &); /* Prevent use of these */
+ void operator=(sp_instr_hpop &);
+
+public:
+
+ sp_instr_hpop(uint ip, sp_pcontext *ctx, uint count)
+ : sp_instr(ip, ctx), m_count(count)
+ {}
+
+ virtual ~sp_instr_hpop()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
+
+ virtual uint opt_mark(sp_head *sp)
+ {
+ if (m_count)
+ marked= 1;
+ return m_ip+1;
+ }
+
+private:
+
+ uint m_count;
+
+}; // class sp_instr_hpop : public sp_instr
+
+
+class sp_instr_hreturn : public sp_instr_jump
+{
+ sp_instr_hreturn(const sp_instr_hreturn &); /* Prevent use of these */
+ void operator=(sp_instr_hreturn &);
+
+public:
+
+ sp_instr_hreturn(uint ip, sp_pcontext *ctx, uint fp)
+ : sp_instr_jump(ip, ctx), m_frame(fp)
+ {}
+
+ virtual ~sp_instr_hreturn()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual uint opt_mark(sp_head *sp);
+
+private:
+
+ uint m_frame;
+
+}; // class sp_instr_hreturn : public sp_instr
+
+
+/* This is DECLARE CURSOR */
+class sp_instr_cpush : public sp_instr
+{
+ sp_instr_cpush(const sp_instr_cpush &); /* Prevent use of these */
+ void operator=(sp_instr_cpush &);
+
+public:
+
+ sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex)
+ : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
+ {}
+
+ virtual ~sp_instr_cpush()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+private:
+
+ sp_lex_keeper m_lex_keeper;
+
+}; // class sp_instr_cpush : public sp_instr
+
+
+class sp_instr_cpop : public sp_instr
+{
+ sp_instr_cpop(const sp_instr_cpop &); /* Prevent use of these */
+ void operator=(sp_instr_cpop &);
+
+public:
+
+ sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count)
+ : sp_instr(ip, ctx), m_count(count)
+ {}
+
+ virtual ~sp_instr_cpop()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
+
+ virtual uint opt_mark(sp_head *sp)
+ {
+ if (m_count)
+ marked= 1;
+ return m_ip+1;
+ }
+
+private:
+
+ uint m_count;
+
+}; // class sp_instr_cpop : public sp_instr
+
+
+class sp_instr_copen : public sp_instr
+{
+ sp_instr_copen(const sp_instr_copen &); /* Prevent use of these */
+ void operator=(sp_instr_copen &);
+
+public:
+
+ sp_instr_copen(uint ip, sp_pcontext *ctx, uint c)
+ : sp_instr(ip, ctx), m_cursor(c)
+ {}
+
+ virtual ~sp_instr_copen()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+private:
+
+ uint m_cursor; // Stack index
+
+}; // class sp_instr_copen : public sp_instr_stmt
+
+
+class sp_instr_cclose : public sp_instr
+{
+ sp_instr_cclose(const sp_instr_cclose &); /* Prevent use of these */
+ void operator=(sp_instr_cclose &);
+
+public:
+
+ sp_instr_cclose(uint ip, sp_pcontext *ctx, uint c)
+ : sp_instr(ip, ctx), m_cursor(c)
+ {}
+
+ virtual ~sp_instr_cclose()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+private:
+
+ uint m_cursor;
+
+}; // class sp_instr_cclose : public sp_instr
+
+
+class sp_instr_cfetch : public sp_instr
+{
+ sp_instr_cfetch(const sp_instr_cfetch &); /* Prevent use of these */
+ void operator=(sp_instr_cfetch &);
+
+public:
+
+ sp_instr_cfetch(uint ip, sp_pcontext *ctx, uint c)
+ : sp_instr(ip, ctx), m_cursor(c)
+ {
+ m_varlist.empty();
+ }
+
+ virtual ~sp_instr_cfetch()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ void add_to_varlist(struct sp_pvar *var)
+ {
+ m_varlist.push_back(var);
+ }
+
+private:
+
+ uint m_cursor;
+ List<struct sp_pvar> m_varlist;
+
+}; // class sp_instr_cfetch : public sp_instr
+
+
+class sp_instr_error : public sp_instr
+{
+ sp_instr_error(const sp_instr_error &); /* Prevent use of these */
+ void operator=(sp_instr_error &);
+
+public:
+
+ sp_instr_error(uint ip, sp_pcontext *ctx, int errcode)
+ : sp_instr(ip, ctx), m_errcode(errcode)
+ {}
+
+ virtual ~sp_instr_error()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+
+ virtual uint opt_mark(sp_head *sp)
+ {
+ marked= 1;
+ return UINT_MAX;
+ }
+
+private:
+
+ int m_errcode;
+
+}; // class sp_instr_error : public sp_instr
+
+
+struct st_sp_security_context
+{
+ bool changed;
+ uint master_access;
+ uint db_access;
+ char *priv_user;
+ char priv_host[MAX_HOSTNAME];
+ char *user;
+ char *host;
+ char *ip;
+};
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+void
+sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp);
+void
+sp_restore_security_context(THD *thd, sp_head *sp,st_sp_security_context *ctxp);
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
+
+TABLE_LIST *
+sp_add_to_query_tables(THD *thd, LEX *lex,
+ const char *db, const char *name,
+ thr_lock_type locktype);
+
+#endif /* _SP_HEAD_H_ */
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
new file mode 100644
index 00000000000..f873b676925
--- /dev/null
+++ b/sql/sp_pcontext.cc
@@ -0,0 +1,333 @@
+/* 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 */
+
+#include "mysql_priv.h"
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation
+#endif
+
+#if defined(WIN32) || defined(__WIN__)
+#undef SAFEMALLOC /* Problems with threads */
+#endif
+
+#include "sp_pcontext.h"
+#include "sp_head.h"
+
+/*
+ * Sanity check for SQLSTATEs. Will not check if it's really an existing
+ * state (there are just too many), but will check length and bad characters.
+ * Returns TRUE if it's ok, FALSE if it's bad.
+ */
+bool
+sp_cond_check(LEX_STRING *sqlstate)
+{
+ int i;
+ const char *p;
+
+ if (sqlstate->length != 5)
+ return FALSE;
+ for (p= sqlstate->str, i= 0 ; i < 5 ; i++)
+ {
+ char c = p[i];
+
+ if ((c < '0' || '9' < c) &&
+ (c < 'A' || 'Z' < c))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+sp_pcontext::sp_pcontext(sp_pcontext *prev)
+ : Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0),
+ m_handlers(0), m_parent(prev)
+{
+ VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
+ VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
+ VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8));
+ VOID(my_init_dynamic_array(&m_handler, sizeof(sp_cond_type_t *), 16, 8));
+ m_label.empty();
+ m_children.empty();
+ if (!prev)
+ m_poffset= m_coffset= 0;
+ else
+ {
+ m_poffset= prev->current_pvars();
+ m_coffset= prev->current_cursors();
+ }
+}
+
+void
+sp_pcontext::destroy()
+{
+ List_iterator_fast<sp_pcontext> li(m_children);
+ sp_pcontext *child;
+
+ while ((child= li++))
+ child->destroy();
+
+ m_children.empty();
+ m_label.empty();
+ delete_dynamic(&m_pvar);
+ delete_dynamic(&m_cond);
+ delete_dynamic(&m_cursor);
+ delete_dynamic(&m_handler);
+}
+
+sp_pcontext *
+sp_pcontext::push_context()
+{
+ sp_pcontext *child= new sp_pcontext(this);
+
+ if (child)
+ m_children.push_back(child);
+ return child;
+}
+
+sp_pcontext *
+sp_pcontext::pop_context()
+{
+ uint submax= max_pvars();
+
+ if (submax > m_parent->m_psubsize)
+ m_parent->m_psubsize= submax;
+ submax= max_handlers();
+ if (submax > m_parent->m_hsubsize)
+ m_parent->m_hsubsize= submax;
+ submax= max_cursors();
+ if (submax > m_parent->m_csubsize)
+ m_parent->m_csubsize= submax;
+ return m_parent;
+}
+
+uint
+sp_pcontext::diff_handlers(sp_pcontext *ctx)
+{
+ uint n= 0;
+ sp_pcontext *pctx= this;
+
+ while (pctx && pctx != ctx)
+ {
+ n+= pctx->m_handlers;
+ pctx= pctx->parent_context();
+ }
+ if (pctx)
+ return n;
+ return 0; // Didn't find ctx
+}
+
+uint
+sp_pcontext::diff_cursors(sp_pcontext *ctx)
+{
+ sp_pcontext *pctx= this;
+
+ while (pctx && pctx != ctx)
+ pctx= pctx->parent_context();
+ if (pctx)
+ return ctx->current_cursors() - pctx->current_cursors();
+ return 0; // Didn't find ctx
+}
+
+/* This does a linear search (from newer to older variables, in case
+** we have shadowed names).
+** It's possible to have a more efficient allocation and search method,
+** but it might not be worth it. The typical number of parameters and
+** variables will in most cases be low (a handfull).
+** ...and, this is only called during parsing.
+*/
+sp_pvar_t *
+sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
+{
+ uint i= m_pvar.elements;
+
+ while (i--)
+ {
+ sp_pvar_t *p;
+
+ get_dynamic(&m_pvar, (gptr)&p, i);
+ if (my_strnncoll(system_charset_info,
+ (const uchar *)name->str, name->length,
+ (const uchar *)p->name.str, p->name.length) == 0)
+ {
+ return p;
+ }
+ }
+ if (!scoped && m_parent)
+ return m_parent->find_pvar(name, scoped);
+ return NULL;
+}
+
+void
+sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
+ sp_param_mode_t mode)
+{
+ sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t));
+
+ if (p)
+ {
+ if (m_pvar.elements == m_psubsize)
+ m_psubsize+= 1;
+ p->name.str= name->str;
+ p->name.length= name->length;
+ p->type= type;
+ p->mode= mode;
+ p->offset= current_pvars();
+ p->dflt= NULL;
+ insert_dynamic(&m_pvar, (gptr)&p);
+ }
+}
+
+sp_label_t *
+sp_pcontext::push_label(char *name, uint ip)
+{
+ sp_label_t *lab = (sp_label_t *)sql_alloc(sizeof(sp_label_t));
+
+ if (lab)
+ {
+ lab->name= name;
+ lab->ip= ip;
+ lab->type= SP_LAB_GOTO;
+ lab->ctx= this;
+ m_label.push_front(lab);
+ }
+ return lab;
+}
+
+sp_label_t *
+sp_pcontext::find_label(char *name)
+{
+ List_iterator_fast<sp_label_t> li(m_label);
+ sp_label_t *lab;
+
+ while ((lab= li++))
+ if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
+ return lab;
+
+ if (m_parent)
+ return m_parent->find_label(name);
+ return NULL;
+}
+
+void
+sp_pcontext::push_cond(LEX_STRING *name, sp_cond_type_t *val)
+{
+ sp_cond_t *p= (sp_cond_t *)sql_alloc(sizeof(sp_cond_t));
+
+ if (p)
+ {
+ p->name.str= name->str;
+ p->name.length= name->length;
+ p->val= val;
+ insert_dynamic(&m_cond, (gptr)&p);
+ }
+}
+
+/*
+ * See comment for find_pvar() above
+ */
+sp_cond_type_t *
+sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
+{
+ uint i= m_cond.elements;
+
+ while (i--)
+ {
+ sp_cond_t *p;
+
+ get_dynamic(&m_cond, (gptr)&p, i);
+ if (my_strnncoll(system_charset_info,
+ (const uchar *)name->str, name->length,
+ (const uchar *)p->name.str, p->name.length) == 0)
+ {
+ return p->val;
+ }
+ }
+ if (!scoped && m_parent)
+ return m_parent->find_cond(name, scoped);
+ return NULL;
+}
+
+/*
+ * This only searches the current context, for error checking of
+ * duplicates.
+ * Returns TRUE if found.
+ */
+bool
+sp_pcontext::find_handler(sp_cond_type_t *cond)
+{
+ uint i= m_handler.elements;
+
+ while (i--)
+ {
+ sp_cond_type_t *p;
+
+ get_dynamic(&m_handler, (gptr)&p, i);
+ if (cond->type == p->type)
+ {
+ switch (p->type)
+ {
+ case sp_cond_type_t::number:
+ if (cond->mysqlerr == p->mysqlerr)
+ return TRUE;
+ break;
+ case sp_cond_type_t::state:
+ if (strcmp(cond->sqlstate, p->sqlstate) == 0)
+ return TRUE;
+ break;
+ default:
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+void
+sp_pcontext::push_cursor(LEX_STRING *name)
+{
+ LEX_STRING n;
+
+ if (m_cursor.elements == m_csubsize)
+ m_csubsize+= 1;
+ n.str= name->str;
+ n.length= name->length;
+ insert_dynamic(&m_cursor, (gptr)&n);
+}
+
+/*
+ * See comment for find_pvar() above
+ */
+my_bool
+sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
+{
+ uint i= m_cursor.elements;
+
+ while (i--)
+ {
+ LEX_STRING n;
+
+ get_dynamic(&m_cursor, (gptr)&n, i);
+ if (my_strnncoll(system_charset_info,
+ (const uchar *)name->str, name->length,
+ (const uchar *)n.str, n.length) == 0)
+ {
+ *poff= m_coffset + i;
+ return TRUE;
+ }
+ }
+ if (!scoped && m_parent)
+ return m_parent->find_cursor(name, poff, scoped);
+ return FALSE;
+}
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
new file mode 100644
index 00000000000..bd2259cb6fb
--- /dev/null
+++ b/sql/sp_pcontext.h
@@ -0,0 +1,303 @@
+/* -*- C++ -*- */
+/* 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 */
+
+#ifndef _SP_PCONTEXT_H_
+#define _SP_PCONTEXT_H_
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+typedef enum
+{
+ sp_param_in,
+ sp_param_out,
+ sp_param_inout
+} sp_param_mode_t;
+
+typedef struct sp_pvar
+{
+ LEX_STRING name;
+ enum enum_field_types type;
+ sp_param_mode_t mode;
+ uint offset; // Offset in current frame
+ Item *dflt;
+} sp_pvar_t;
+
+
+#define SP_LAB_REF 0 // Unresolved reference (for goto)
+#define SP_LAB_GOTO 1 // Free goto label
+#define SP_LAB_BEGIN 2 // Label at BEGIN
+#define SP_LAB_ITER 3 // Label at iteration control
+
+typedef struct sp_label
+{
+ char *name;
+ uint ip; // Instruction index
+ int type; // begin/iter or ref/free
+ sp_pcontext *ctx; // The label's context
+} sp_label_t;
+
+typedef struct sp_cond_type
+{
+ enum { number, state, warning, notfound, exception } type;
+ char sqlstate[6];
+ uint mysqlerr;
+} sp_cond_type_t;
+
+/* Sanity check for SQLSTATEs. Will not check if it's really an existing
+ * state (there are just too many), but will check length bad characters.
+ */
+extern bool
+sp_cond_check(LEX_STRING *sqlstate);
+
+typedef struct sp_cond
+{
+ LEX_STRING name;
+ sp_cond_type_t *val;
+} sp_cond_t;
+
+
+/*
+ This seems to be an "SP parsing context" or something.
+*/
+
+class sp_pcontext : public Sql_alloc
+{
+ sp_pcontext(const sp_pcontext &); /* Prevent use of these */
+ void operator=(sp_pcontext &);
+
+ public:
+
+ sp_pcontext(sp_pcontext *prev);
+
+ // Free memory
+ void
+ destroy();
+
+ sp_pcontext *
+ push_context();
+
+ // Returns the previous context, not the one we pop
+ sp_pcontext *
+ pop_context();
+
+ sp_pcontext *
+ parent_context()
+ {
+ return m_parent;
+ }
+
+ uint
+ diff_handlers(sp_pcontext *ctx);
+
+ uint
+ diff_cursors(sp_pcontext *ctx);
+
+
+ //
+ // Parameters and variables
+ //
+
+ inline uint
+ max_pvars()
+ {
+ return m_psubsize + m_pvar.elements;
+ }
+
+ inline uint
+ current_pvars()
+ {
+ return m_poffset + m_pvar.elements;
+ }
+
+ inline uint
+ context_pvars()
+ {
+ return m_pvar.elements;
+ }
+
+ inline uint
+ pvar_context2index(uint i)
+ {
+ return m_poffset + i;
+ }
+
+ inline void
+ set_type(uint i, enum enum_field_types type)
+ {
+ sp_pvar_t *p= find_pvar(i);
+
+ if (p)
+ p->type= type;
+ }
+
+ inline void
+ set_default(uint i, Item *it)
+ {
+ sp_pvar_t *p= find_pvar(i);
+
+ if (p)
+ p->dflt= it;
+ }
+
+ void
+ push_pvar(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode);
+
+ // Pop the last 'num' slots of the frame
+ inline void
+ pop_pvar(uint num = 1)
+ {
+ while (num--)
+ pop_dynamic(&m_pvar);
+ }
+
+ // Find by name
+ sp_pvar_t *
+ find_pvar(LEX_STRING *name, my_bool scoped=0);
+
+ // Find by index
+ sp_pvar_t *
+ find_pvar(uint i)
+ {
+ sp_pvar_t *p;
+
+ if (i < m_pvar.elements)
+ get_dynamic(&m_pvar, (gptr)&p, i);
+ else
+ p= NULL;
+ return p;
+ }
+
+ //
+ // Labels
+ //
+
+ sp_label_t *
+ push_label(char *name, uint ip);
+
+ sp_label_t *
+ find_label(char *name);
+
+ inline sp_label_t *
+ last_label()
+ {
+ sp_label_t *lab= m_label.head();
+
+ if (!lab && m_parent)
+ lab= m_parent->last_label();
+ return lab;
+ }
+
+ inline sp_label_t *
+ pop_label()
+ {
+ return m_label.pop();
+ }
+
+ //
+ // Conditions
+ //
+
+ void
+ push_cond(LEX_STRING *name, sp_cond_type_t *val);
+
+ inline void
+ pop_cond(uint num)
+ {
+ while (num--)
+ pop_dynamic(&m_cond);
+ }
+
+ sp_cond_type_t *
+ find_cond(LEX_STRING *name, my_bool scoped=0);
+
+ //
+ // Handlers
+ //
+
+ inline void
+ push_handler(sp_cond_type_t *cond)
+ {
+ insert_dynamic(&m_handler, (gptr)&cond);
+ }
+
+ bool
+ find_handler(sp_cond_type *cond);
+
+ inline uint
+ max_handlers()
+ {
+ return m_hsubsize + m_handlers;
+ }
+
+ inline void
+ add_handlers(uint n)
+ {
+ m_handlers+= n;
+ }
+
+ //
+ // Cursors
+ //
+
+ void
+ push_cursor(LEX_STRING *name);
+
+ my_bool
+ find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
+
+ inline uint
+ max_cursors()
+ {
+ return m_csubsize + m_cursor.elements;
+ }
+
+ inline uint
+ current_cursors()
+ {
+ return m_coffset + m_cursor.elements;
+ }
+
+protected:
+
+ // The maximum sub context's framesizes
+ uint m_psubsize;
+ uint m_csubsize;
+ uint m_hsubsize;
+ uint m_handlers; // No. of handlers in this context
+
+private:
+
+ sp_pcontext *m_parent; // Parent context
+
+ uint m_poffset; // Variable offset for this context
+ uint m_coffset; // Cursor offset for this context
+
+ DYNAMIC_ARRAY m_pvar; // Parameters/variables
+ DYNAMIC_ARRAY m_cond; // Conditions
+ DYNAMIC_ARRAY m_cursor; // Cursors
+ DYNAMIC_ARRAY m_handler; // Handlers, for checking of duplicates
+
+ List<sp_label_t> m_label; // The label list
+
+ List<sp_pcontext> m_children; // Children contexts, used for destruction
+
+}; // class sp_pcontext : public Sql_alloc
+
+
+#endif /* _SP_PCONTEXT_H_ */
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
new file mode 100644
index 00000000000..748c09f56c7
--- /dev/null
+++ b/sql/sp_rcontext.cc
@@ -0,0 +1,352 @@
+/* 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 */
+
+#include "mysql_priv.h"
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation
+#endif
+
+#if defined(WIN32) || defined(__WIN__)
+#undef SAFEMALLOC /* Problems with threads */
+#endif
+
+#include "mysql.h"
+#include "sp_head.h"
+#include "sp_rcontext.h"
+#include "sp_pcontext.h"
+
+sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax)
+ : m_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0),
+ m_hfound(-1), m_ccount(0)
+{
+ in_handler= FALSE;
+ m_frame= (Item **)sql_alloc(fsize * sizeof(Item*));
+ m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t));
+ m_hstack= (uint *)sql_alloc(hmax * sizeof(uint));
+ m_cstack= (sp_cursor **)sql_alloc(cmax * sizeof(sp_cursor *));
+ m_saved.empty();
+}
+
+
+int
+sp_rcontext::set_item_eval(THD *thd, uint idx, Item **item_addr,
+ enum_field_types type)
+{
+ extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type,
+ Item *reuse, bool use_callers_arena);
+ Item *it;
+ Item *reuse_it;
+ Item *old_item_next;
+ /* sp_eval_func_item will use callers_arena */
+ Item *old_free_list= thd->spcont->callers_arena->free_list;
+ int res;
+ LINT_INIT(old_item_next);
+
+ if ((reuse_it= get_item(idx)))
+ old_item_next= reuse_it->next;
+ it= sp_eval_func_item(thd, item_addr, type, reuse_it, TRUE);
+ if (! it)
+ res= -1;
+ else
+ {
+ res= 0;
+ if (reuse_it && it == reuse_it)
+ {
+ // A reused item slot, where the constructor put it in the free_list,
+ // so we have to restore the list.
+ thd->spcont->callers_arena->free_list= old_free_list;
+ it->next= old_item_next;
+ }
+ set_item(idx, it);
+ }
+
+ return res;
+}
+
+bool
+sp_rcontext::find_handler(uint sql_errno,
+ MYSQL_ERROR::enum_warning_level level)
+{
+ if (in_handler)
+ return 0; // Already executing a handler
+ if (m_hfound >= 0)
+ return 1; // Already got one
+
+ const char *sqlstate= mysql_errno_to_sqlstate(sql_errno);
+ int i= m_hcount, found= -1;
+
+ while (i--)
+ {
+ sp_cond_type_t *cond= m_handler[i].cond;
+
+ switch (cond->type)
+ {
+ case sp_cond_type_t::number:
+ if (sql_errno == cond->mysqlerr)
+ found= i; // Always the most specific
+ break;
+ case sp_cond_type_t::state:
+ if (strcmp(sqlstate, cond->sqlstate) == 0 &&
+ (found < 0 || m_handler[found].cond->type > sp_cond_type_t::state))
+ found= i;
+ break;
+ case sp_cond_type_t::warning:
+ if ((sqlstate[0] == '0' && sqlstate[1] == '1' ||
+ level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
+ found < 0)
+ found= i;
+ break;
+ case sp_cond_type_t::notfound:
+ if (sqlstate[0] == '0' && sqlstate[1] == '2' &&
+ found < 0)
+ found= i;
+ break;
+ case sp_cond_type_t::exception:
+ if ((sqlstate[0] != '0' || sqlstate[1] > '2') &&
+ level == MYSQL_ERROR::WARN_LEVEL_ERROR &&
+ found < 0)
+ found= i;
+ break;
+ }
+ }
+ if (found < 0)
+ return FALSE;
+ m_hfound= found;
+ return TRUE;
+}
+
+void
+sp_rcontext::save_variables(uint fp)
+{
+ while (fp < m_count)
+ {
+ m_saved.push_front(m_frame[fp]);
+ m_frame[fp++]= NULL; // Prevent reuse
+ }
+}
+
+void
+sp_rcontext::restore_variables(uint fp)
+{
+ uint i= m_count;
+
+ while (i-- > fp)
+ m_frame[i]= m_saved.pop();
+}
+
+void
+sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
+{
+ m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i);
+}
+
+void
+sp_rcontext::pop_cursors(uint count)
+{
+ while (count--)
+ {
+ delete m_cstack[--m_ccount];
+ }
+}
+
+
+/*
+ *
+ * sp_cursor
+ *
+ */
+
+sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
+ :m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL),
+ m_i(i)
+{
+ /*
+ currsor can't be stored in QC, so we should prevent opening QC for
+ try to write results which are absent.
+ */
+ lex_keeper->disable_query_cache();
+}
+
+
+/*
+ pre_open cursor
+
+ SYNOPSIS
+ pre_open()
+ THD Thread handler
+
+ NOTES
+ We have to open cursor in two steps to make it easy for sp_instr_copen
+ to reuse the sp_instr::exec_stmt() code.
+ If this function returns 0, post_open should not be called
+
+ RETURN
+ 0 ERROR
+*/
+
+sp_lex_keeper*
+sp_cursor::pre_open(THD *thd)
+{
+ if (m_isopen)
+ {
+ my_message(ER_SP_CURSOR_ALREADY_OPEN, ER(ER_SP_CURSOR_ALREADY_OPEN),
+ MYF(0));
+ return NULL;
+ }
+ init_alloc_root(&m_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+ if ((m_prot= new Protocol_cursor(thd, &m_mem_root)) == NULL)
+ return NULL;
+
+ /* Save for execution. Will be restored in post_open */
+ m_oprot= thd->protocol;
+ m_nseof= thd->net.no_send_eof;
+
+ /* Change protocol for execution */
+ thd->protocol= m_prot;
+ thd->net.no_send_eof= TRUE;
+ return m_lex_keeper;
+}
+
+
+void
+sp_cursor::post_open(THD *thd, my_bool was_opened)
+{
+ thd->net.no_send_eof= m_nseof; // Restore the originals
+ thd->protocol= m_oprot;
+ if ((m_isopen= was_opened))
+ m_current_row= m_prot->data;
+}
+
+
+int
+sp_cursor::close(THD *thd)
+{
+ if (! m_isopen)
+ {
+ my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
+ return -1;
+ }
+ destroy();
+ return 0;
+}
+
+
+void
+sp_cursor::destroy()
+{
+ if (m_prot)
+ {
+ delete m_prot;
+ m_prot= NULL;
+ free_root(&m_mem_root, MYF(0));
+ }
+ m_isopen= FALSE;
+}
+
+int
+sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
+{
+ List_iterator_fast<struct sp_pvar> li(*vars);
+ sp_pvar_t *pv;
+ MYSQL_ROW row;
+ uint fldcount;
+
+ if (! m_isopen)
+ {
+ my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
+ return -1;
+ }
+ if (m_current_row == NULL)
+ {
+ my_message(ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA), MYF(0));
+ return -1;
+ }
+
+ row= m_current_row->data;
+ for (fldcount= 0 ; (pv= li++) ; fldcount++)
+ {
+ Item *it;
+ Item *reuse;
+ uint rsize;
+ Item *old_item_next;
+ Item *old_free_list= thd->free_list;
+ const char *s;
+ LINT_INIT(old_item_next);
+
+ if (fldcount >= m_prot->get_field_count())
+ {
+ my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
+ ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
+ return -1;
+ }
+
+ if ((reuse= thd->spcont->get_item(pv->offset)))
+ old_item_next= reuse->next;
+
+ s= row[fldcount];
+ if (!s)
+ it= new(reuse, &rsize) Item_null();
+ else
+ {
+ /*
+ Length of data can be calculated as:
+ pointer_to_next_not_null_object - s -1
+ where the last -1 is to remove the end \0
+ */
+ uint len;
+ MYSQL_ROW next= row+fldcount+1;
+ while (!*next) // Skip nulls
+ next++;
+ len= (*next -s)-1;
+ switch (sp_map_result_type(pv->type)) {
+ case INT_RESULT:
+ it= new(reuse, &rsize) Item_int(s);
+ break;
+ case REAL_RESULT:
+ it= new(reuse, &rsize) Item_float(s, len);
+ break;
+ case DECIMAL_RESULT:
+ it= new(reuse, &rsize) Item_decimal(s, len, thd->db_charset);
+ break;
+ case STRING_RESULT:
+ /* TODO: Document why we do an extra copy of the string 's' here */
+ it= new(reuse, &rsize) Item_string(thd->strmake(s, len), len,
+ thd->db_charset);
+ break;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+ it->rsize= rsize;
+ if (reuse && it == reuse)
+ {
+ // A reused item slot, where the constructor put it in the free_list,
+ // so we have to restore the list.
+ thd->free_list= old_free_list;
+ it->next= old_item_next;
+ }
+ thd->spcont->set_item(pv->offset, it);
+ }
+ if (fldcount < m_prot->get_field_count())
+ {
+ my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
+ ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
+ return -1;
+ }
+ m_current_row= m_current_row->next;
+ return 0;
+}
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
new file mode 100644
index 00000000000..36380952e5d
--- /dev/null
+++ b/sql/sp_rcontext.h
@@ -0,0 +1,271 @@
+/* -*- C++ -*- */
+/* 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 */
+
+#ifndef _SP_RCONTEXT_H_
+#define _SP_RCONTEXT_H_
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+struct sp_cond_type;
+class sp_cursor;
+struct sp_pvar;
+class sp_lex_keeper;
+class sp_instr_cpush;
+
+#define SP_HANDLER_NONE 0
+#define SP_HANDLER_EXIT 1
+#define SP_HANDLER_CONTINUE 2
+#define SP_HANDLER_UNDO 3
+
+typedef struct
+{
+ struct sp_cond_type *cond;
+ uint handler; // Location of handler
+ int type;
+ uint foffset; // Frame offset for the handlers declare level
+} sp_handler_t;
+
+
+/*
+ This is a run context? of one SP ?
+ THis is
+ - a stack of cursors?
+ - a stack of handlers?
+ - a stack of Items ?
+ - a stack of instruction locations in SP?
+*/
+
+class sp_rcontext : public Sql_alloc
+{
+ sp_rcontext(const sp_rcontext &); /* Prevent use of these */
+ void operator=(sp_rcontext &);
+
+ public:
+
+ bool in_handler;
+ /*
+ Arena used to (re) allocate items on . E.g. reallocate INOUT/OUT
+ SP parameters when they don't fit into prealloced items. This
+ is common situation with String items. It is used mainly in
+ sp_eval_func_item().
+ */
+ Query_arena *callers_arena;
+
+ sp_rcontext(uint fsize, uint hmax, uint cmax);
+
+ ~sp_rcontext()
+ {
+ // Not needed?
+ //sql_element_free(m_frame);
+ //m_saved.empty();
+ }
+
+ inline void
+ push_item(Item *i)
+ {
+ if (m_count < m_fsize)
+ m_frame[m_count++]= i;
+ }
+
+ inline void
+ set_item(uint idx, Item *i)
+ {
+ if (idx < m_count)
+ m_frame[idx]= i;
+ }
+
+ /* Returns 0 on success, -1 on (eval) failure */
+ int
+ set_item_eval(THD *thd, uint idx, Item **i, enum_field_types type);
+
+ inline Item *
+ get_item(uint idx)
+ {
+ return m_frame[idx];
+ }
+
+ inline Item **
+ get_item_addr(uint idx)
+ {
+ return m_frame + idx;
+ }
+
+
+ inline void
+ set_result(Item *it)
+ {
+ m_result= it;
+ }
+
+ inline Item *
+ get_result()
+ {
+ return m_result;
+ }
+
+ inline void
+ push_handler(struct sp_cond_type *cond, uint h, int type, uint f)
+ {
+ m_handler[m_hcount].cond= cond;
+ m_handler[m_hcount].handler= h;
+ m_handler[m_hcount].type= type;
+ m_handler[m_hcount].foffset= f;
+ m_hcount+= 1;
+ }
+
+ inline void
+ pop_handlers(uint count)
+ {
+ m_hcount-= count;
+ }
+
+ // Returns 1 if a handler was found, 0 otherwise.
+ bool
+ find_handler(uint sql_errno,MYSQL_ERROR::enum_warning_level level);
+
+ // Returns handler type and sets *ip to location if one was found
+ inline int
+ found_handler(uint *ip, uint *fp)
+ {
+ if (m_hfound < 0)
+ return SP_HANDLER_NONE;
+ *ip= m_handler[m_hfound].handler;
+ *fp= m_handler[m_hfound].foffset;
+ return m_handler[m_hfound].type;
+ }
+
+ // Clears the handler find state
+ inline void
+ clear_handler()
+ {
+ m_hfound= -1;
+ }
+
+ inline void
+ push_hstack(uint h)
+ {
+ m_hstack[m_hsp++]= h;
+ }
+
+ inline uint
+ pop_hstack()
+ {
+ return m_hstack[--m_hsp];
+ }
+
+ // Save variables starting at fp and up
+ void
+ save_variables(uint fp);
+
+ // Restore variables down to fp
+ void
+ restore_variables(uint fp);
+
+ void
+ push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
+
+ void
+ pop_cursors(uint count);
+
+ void
+ pop_all_cursors()
+ {
+ pop_cursors(m_ccount);
+ }
+
+ inline sp_cursor *
+ get_cursor(uint i)
+ {
+ return m_cstack[i];
+ }
+
+private:
+
+ uint m_count;
+ uint m_fsize;
+ Item **m_frame;
+
+ Item *m_result; // For FUNCTIONs
+
+ sp_handler_t *m_handler;
+ uint m_hcount;
+ uint *m_hstack;
+ uint m_hsp;
+ int m_hfound; // Set by find_handler; -1 if not found
+ List<Item> m_saved; // Saved variables
+
+ sp_cursor **m_cstack;
+ uint m_ccount;
+
+}; // class sp_rcontext : public Sql_alloc
+
+
+class sp_cursor : public Sql_alloc
+{
+public:
+
+ sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
+
+ virtual ~sp_cursor()
+ {
+ destroy();
+ }
+
+ // We have split this in two to make it easy for sp_instr_copen
+ // to reuse the sp_instr::exec_stmt() code.
+ sp_lex_keeper *
+ pre_open(THD *thd);
+ void
+ post_open(THD *thd, my_bool was_opened);
+
+ int
+ close(THD *thd);
+
+ inline my_bool
+ is_open()
+ {
+ return m_isopen;
+ }
+
+ int
+ fetch(THD *, List<struct sp_pvar> *vars);
+
+ inline sp_instr_cpush *
+ get_instr()
+ {
+ return m_i;
+ }
+
+private:
+
+ MEM_ROOT m_mem_root; // My own mem_root
+ sp_lex_keeper *m_lex_keeper;
+ Protocol_cursor *m_prot;
+ my_bool m_isopen;
+ my_bool m_nseof; // Original no_send_eof
+ Protocol *m_oprot; // Original protcol
+ MYSQL_ROWS *m_current_row;
+ sp_instr_cpush *m_i; // My push instruction
+
+ void
+ destroy();
+
+}; // class sp_cursor : public Sql_alloc
+
+#endif /* _SP_RCONTEXT_H_ */
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 1afb7bb7dec..176f1f2fbfe 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -22,6 +22,8 @@
/***************************** Gis_class_info *******************************/
+String Geometry::bad_geometry_data("Bad object", &my_charset_bin);
+
Geometry::Class_info *Geometry::ci_collection[Geometry::wkb_end+1]=
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL
diff --git a/sql/spatial.h b/sql/spatial.h
index b96434831a1..b5ea7d641d1 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -173,6 +173,11 @@ public:
static void operator delete(void *ptr, void *buffer)
{}
+ static void operator delete(void *buffer)
+ {}
+
+ static String bad_geometry_data;
+
enum wkbType
{
wkb_point= 1,
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 1b5f69c7873..5e2fd17377a 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -17,8 +17,8 @@
/*
The privileges are saved in the following tables:
- mysql/user ; super user who are allowed to do almoust anything
- mysql/host ; host priviliges. This is used if host is empty in mysql/db.
+ mysql/user ; super user who are allowed to do almost anything
+ mysql/host ; host privileges. This is used if host is empty in mysql/db.
mysql/db ; database privileges / user
data in tables is sorted according to how many not-wild-cards there is
@@ -32,6 +32,8 @@
#endif
#include <m_ctype.h>
#include <stdarg.h>
+#include "sp_head.h"
+#include "sp.h"
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -58,11 +60,10 @@ static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs;
static MEM_ROOT mem, memex;
static bool initialized=0;
static bool allow_all_hosts=1;
-static HASH acl_check_hosts, column_priv_hash;
+static HASH acl_check_hosts, column_priv_hash, proc_priv_hash, func_priv_hash;
static DYNAMIC_ARRAY acl_wild_hosts;
static hash_filo *acl_cache;
-static uint grant_version=0;
-static uint priv_version=0; /* Version of priv tables. incremented by acl_load */
+static uint grant_version=0; /* Version of priv tables. incremented by acl_load */
static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0);
static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b);
static ulong get_sort(uint count,...);
@@ -195,7 +196,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
char tmp_name[NAME_LEN+1];
DBUG_ENTER("acl_load");
- priv_version++; /* Privileges updated */
+ grant_version++; /* Privileges updated */
+ mysql_proc_table_exists= 1; // Assume mysql.proc exists
acl_cache->clear(1); // Clear locked hostname cache
@@ -210,19 +212,17 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
if (lower_case_table_names && host.db)
{
/*
- We make a temporary copy of the database, force it to lower case,
- and then check it against the original name.
+ convert db to lower case and give a warning if the db wasn't
+ already in lower case
*/
- (void)strnmov(tmp_name, host.db, sizeof(tmp_name));
+ (void) strmov(tmp_name, host.db);
my_casedn_str(files_charset_info, host.db);
if (strcmp(host.db, tmp_name) != 0)
- {
sql_print_warning("'host' entry '%s|%s' had database in mixed "
"case that has been forced to lowercase because "
"lower_case_table_names is set. It will not be "
"possible to remove this privilege using REVOKE.",
host.host.hostname, host.db);
- }
}
host.access= get_access(table,2);
host.access= fix_rights_for_db(host.access);
@@ -235,7 +235,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
continue;
}
#ifndef TO_BE_REMOVED
- if (table->fields == 8)
+ if (table->s->fields == 8)
{ // Without grant
if (host.access & CREATE_ACL)
host.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL;
@@ -258,8 +258,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
}
DBUG_PRINT("info",("user table fields: %d, password length: %d",
- table->fields, table->field[2]->field_length));
-
+ table->s->fields, table->field[2]->field_length));
+
pthread_mutex_lock(&LOCK_global_system_variables);
if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH)
{
@@ -327,10 +327,34 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
{
uint next_field;
user.access= get_access(table,3,&next_field) & GLOBAL_ACLS;
+ /*
+ if it is pre 5.0.1 privilege table then map CREATE privilege on
+ CREATE VIEW & SHOW VIEW privileges
+ */
+ if (table->s->fields <= 31 && (user.access & CREATE_ACL))
+ user.access|= (CREATE_VIEW_ACL | SHOW_VIEW_ACL);
+
+ /*
+ if it is pre 5.0.2 privilege table then map CREATE/ALTER privilege on
+ CREATE PROCEDURE & ALTER PROCEDURE privileges
+ */
+ if (table->s->fields <= 33 && (user.access & CREATE_ACL))
+ user.access|= CREATE_PROC_ACL;
+ if (table->s->fields <= 33 && (user.access & ALTER_ACL))
+ user.access|= ALTER_PROC_ACL;
+
+ /*
+ pre 5.0.3 did not have CREATE_USER_ACL
+ */
+ if (table->s->fields <= 36 && (user.access & GRANT_ACL))
+ user.access|= CREATE_USER_ACL;
+
user.sort= get_sort(2,user.host.hostname,user.user);
user.hostname_length= (user.host.hostname ?
(uint) strlen(user.host.hostname) : 0);
- if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
+
+ /* Starting from 4.0.2 we have more fields */
+ if (table->s->fields >= 31)
{
char *ssl_type=get_field(&mem, table->field[next_field++]);
if (!ssl_type)
@@ -351,17 +375,26 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
ptr = get_field(&mem, table->field[next_field++]);
user.user_resource.updates=ptr ? atoi(ptr) : 0;
ptr = get_field(&mem, table->field[next_field++]);
- user.user_resource.connections=ptr ? atoi(ptr) : 0;
+ user.user_resource.conn_per_hour= ptr ? atoi(ptr) : 0;
if (user.user_resource.questions || user.user_resource.updates ||
- user.user_resource.connections)
+ user.user_resource.conn_per_hour)
mqh_used=1;
+
+ if (table->s->fields >= 36)
+ {
+ /* Starting from 5.0.3 we have max_user_connections field */
+ ptr= get_field(&mem, table->field[next_field++]);
+ user.user_resource.user_conn= ptr ? atoi(ptr) : 0;
+ }
+ else
+ user.user_resource.user_conn= 0;
}
else
{
user.ssl_type=SSL_TYPE_NONE;
bzero((char *)&(user.user_resource),sizeof(user.user_resource));
#ifndef TO_BE_REMOVED
- if (table->fields <= 13)
+ if (table->s->fields <= 13)
{ // Without grant
if (user.access & CREATE_ACL)
user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
@@ -410,10 +443,10 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
if (lower_case_table_names)
{
/*
- We make a temporary copy of the database, force it to lower case,
- and then check it against the original name.
+ convert db to lower case and give a warning if the db wasn't
+ already in lower case
*/
- (void)strnmov(tmp_name, db.db, sizeof(tmp_name));
+ (void)strmov(tmp_name, db.db);
my_casedn_str(files_charset_info, db.db);
if (strcmp(db.db, tmp_name) != 0)
{
@@ -426,7 +459,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
}
db.sort=get_sort(3,db.host.hostname,db.db,db.user);
#ifndef TO_BE_REMOVED
- if (table->fields <= 9)
+ if (table->s->fields <= 9)
{ // Without grant
if (db.access & CREATE_ACL)
db.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
@@ -506,12 +539,12 @@ my_bool acl_reload(THD *thd)
obtaining acl_cache->lock mutex.
*/
bzero((char*) tables, sizeof(tables));
- tables[0].alias=tables[0].real_name=(char*) "host";
- tables[1].alias=tables[1].real_name=(char*) "user";
- tables[2].alias=tables[2].real_name=(char*) "db";
- tables[0].db=tables[1].db=tables[2].db= (char*) "mysql";
- tables[0].next= tables+1;
- tables[1].next= tables+2;
+ tables[0].alias= tables[0].table_name= (char*) "host";
+ tables[1].alias= tables[1].table_name= (char*) "user";
+ tables[2].alias= tables[2].table_name= (char*) "db";
+ tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
+ tables[0].next_local= tables[0].next_global= tables+1;
+ tables[1].next_local= tables[1].next_global= tables+2;
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
if (simple_open_n_lock_tables(thd, tables))
@@ -560,8 +593,8 @@ end:
Get all access bits from table after fieldnr
IMPLEMENTATION
- We know that the access privileges ends when there is no more fields
- or the field is not an enum with two elements.
+ We know that the access privileges ends when there is no more fields
+ or the field is not an enum with two elements.
SYNOPSIS
get_access()
@@ -664,7 +697,7 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
thd->host, thd->ip, thd->user are used for checks.
mqh user resources; on success mqh is reset, else
unchanged
- passwd scrambled & crypted password, recieved from client
+ passwd scrambled & crypted password, received from client
(to check): thd->scramble or thd->scramble_323 is
used to decrypt passwd, so they must contain
original random string,
@@ -675,7 +708,7 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
RETURN VALUE
0 success: thd->priv_user, thd->priv_host, thd->master_access, mqh are
updated
- 1 user not found or authentification failure
+ 1 user not found or authentication failure
2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
-1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
*/
@@ -815,7 +848,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
break;
}
DBUG_PRINT("info",("checkpoint 2"));
- /* If X509 issuer is speified, we check it... */
+ /* If X509 issuer is specified, we check it... */
if (acl_user->x509_issuer)
{
DBUG_PRINT("info",("checkpoint 3"));
@@ -874,6 +907,85 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
}
+/*
+ * This is like acl_getroot() above, but it doesn't check password,
+ * and we don't care about the user resources.
+ * Used to get access rights for SQL SECURITY DEFINER invocation of
+ * stored procedures.
+ */
+int acl_getroot_no_password(THD *thd)
+{
+ int res= 1;
+ uint i;
+ ACL_USER *acl_user= 0;
+ DBUG_ENTER("acl_getroot_no_password");
+
+ if (!initialized)
+ {
+ /*
+ here if mysqld's been started with --skip-grant-tables option.
+ */
+ thd->priv_user= (char *) ""; // privileges for
+ *thd->priv_host= '\0'; // the user are unknown
+ thd->master_access= ~NO_ACCESS; // everything is allowed
+ DBUG_RETURN(0);
+ }
+
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ thd->master_access= 0;
+ thd->db_access= 0;
+
+ /*
+ Find acl entry in user database.
+ This is specially tailored to suit the check we do for CALL of
+ a stored procedure; thd->user is set to what is actually a
+ priv_user, which can be ''.
+ */
+ for (i=0 ; i < acl_users.elements ; i++)
+ {
+ acl_user= dynamic_element(&acl_users,i,ACL_USER*);
+ if ((!acl_user->user && (!thd->user || !thd->user[0])) ||
+ (acl_user->user && strcmp(thd->user, acl_user->user) == 0))
+ {
+ if (compare_hostname(&acl_user->host, thd->host, thd->ip))
+ {
+ res= 0;
+ break;
+ }
+ }
+ }
+
+ if (acl_user)
+ {
+ for (i=0 ; i < acl_dbs.elements ; i++)
+ {
+ ACL_DB *acl_db= dynamic_element(&acl_dbs, i, ACL_DB*);
+ if (!acl_db->user ||
+ (thd->user && thd->user[0] && !strcmp(thd->user, acl_db->user)))
+ {
+ if (compare_hostname(&acl_db->host, thd->host, thd->ip))
+ {
+ if (!acl_db->db || (thd->db && !strcmp(acl_db->db, thd->db)))
+ {
+ thd->db_access= acl_db->access;
+ break;
+ }
+ }
+ }
+ }
+ thd->master_access= acl_user->access;
+ thd->priv_user= acl_user->user ? thd->user : (char *) "";
+
+ if (acl_user->host.hostname)
+ strmake(thd->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
+ else
+ *thd->priv_host= 0;
+ }
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ DBUG_RETURN(res);
+}
+
static byte* check_get_key(ACL_USER *buff,uint *length,
my_bool not_used __attribute__((unused)))
{
@@ -900,15 +1012,17 @@ static void acl_update_user(const char *user, const char *host,
{
if (!acl_user->host.hostname && !host[0] ||
acl_user->host.hostname &&
- !my_strcasecmp(&my_charset_latin1, host, acl_user->host.hostname))
+ !my_strcasecmp(system_charset_info, host, acl_user->host.hostname))
{
acl_user->access=privileges;
- if (mqh->bits & 1)
+ if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
acl_user->user_resource.questions=mqh->questions;
- if (mqh->bits & 2)
+ if (mqh->specified_limits & USER_RESOURCES::UPDATES_PER_HOUR)
acl_user->user_resource.updates=mqh->updates;
- if (mqh->bits & 4)
- acl_user->user_resource.connections=mqh->connections;
+ if (mqh->specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR)
+ acl_user->user_resource.conn_per_hour= mqh->conn_per_hour;
+ if (mqh->specified_limits & USER_RESOURCES::USER_CONNECTIONS)
+ acl_user->user_resource.user_conn= mqh->user_conn;
if (ssl_type != SSL_TYPE_NOT_SPECIFIED)
{
acl_user->ssl_type= ssl_type;
@@ -979,7 +1093,7 @@ static void acl_update_db(const char *user, const char *host, const char *db,
{
if (!acl_db->host.hostname && !host[0] ||
acl_db->host.hostname &&
- !my_strcasecmp(&my_charset_latin1, host, acl_db->host.hostname))
+ !my_strcasecmp(system_charset_info, host, acl_db->host.hostname))
{
if (!acl_db->db && !db[0] ||
acl_db->db && !strcmp(db,acl_db->db))
@@ -1036,7 +1150,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)
{
- ulong host_access= ~(ulong)0,db_access= 0;
+ ulong host_access= ~(ulong)0, db_access= 0;
uint i,key_length;
char key[ACL_KEY_LENGTH],*tmp_db,*end;
acl_entry *entry;
@@ -1125,7 +1239,7 @@ static void init_check_host(void)
DBUG_ENTER("init_check_host");
VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip),
acl_users.elements,1));
- VOID(hash_init(&acl_check_hosts,&my_charset_latin1,acl_users.elements,0,0,
+ VOID(hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0,
(hash_get_key) check_get_key,0,0));
if (!allow_all_hosts)
{
@@ -1141,7 +1255,7 @@ static void init_check_host(void)
{ // Check if host already exists
acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,j,
acl_host_and_ip *);
- if (!my_strcasecmp(&my_charset_latin1,
+ if (!my_strcasecmp(system_charset_info,
acl_user->host.hostname, acl->hostname))
break; // already stored
}
@@ -1216,29 +1330,27 @@ bool check_change_password(THD *thd, const char *host, const char *user,
{
if (!initialized)
{
- net_printf(thd,ER_OPTION_PREVENTS_STATEMENT,
- "--skip-grant-tables");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
return(1);
}
if (!thd->slave_thread &&
(strcmp(thd->user,user) ||
- my_strcasecmp(&my_charset_latin1, host, thd->priv_host)))
+ my_strcasecmp(system_charset_info, host, thd->priv_host)))
{
- if (check_access(thd, UPDATE_ACL, "mysql",0,1,0))
+ if (check_access(thd, UPDATE_ACL, "mysql",0,1,0,0))
return(1);
}
if (!thd->slave_thread && !thd->user[0])
{
- send_error(thd, ER_PASSWORD_ANONYMOUS_USER);
+ my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER),
+ MYF(0));
return(1);
}
uint len=strlen(new_password);
if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
- net_printf(thd, 0,
- "Password hash should be a %d-digit hexadecimal number",
- SCRAMBLED_PASSWORD_CHAR_LENGTH);
+ my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
return -1;
}
return(0);
@@ -1279,7 +1391,7 @@ bool change_password(THD *thd, const char *host, const char *user,
DBUG_RETURN(1);
bzero((char*) &tables, sizeof(tables));
- tables.alias=tables.real_name= (char*) "user";
+ tables.alias= tables.table_name= (char*) "user";
tables.db= (char*) "mysql";
#ifdef HAVE_REPLICATION
@@ -1295,7 +1407,7 @@ bool change_password(THD *thd, const char *host, const char *user,
*/
tables.updating= 1;
/* Thanks to bzero, tables.next==0 */
- if (!tables_ok(0, &tables))
+ if (!tables_ok(thd, &tables))
DBUG_RETURN(0);
}
#endif
@@ -1308,7 +1420,7 @@ bool change_password(THD *thd, const char *host, const char *user,
if (!(acl_user= find_acl_user(host, user, TRUE)))
{
VOID(pthread_mutex_unlock(&acl_cache->lock));
- send_error(thd, ER_PASSWORD_NO_MATCH);
+ my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
goto end;
}
/* update loaded acl entry: */
@@ -1320,22 +1432,20 @@ bool change_password(THD *thd, const char *host, const char *user,
new_password, new_password_len))
{
VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */
- send_error(thd,0); /* purecov: deadcode */
goto end;
}
acl_cache->clear(1); // Clear locked hostname cache
VOID(pthread_mutex_unlock(&acl_cache->lock));
result= 0;
- query_length=
- my_sprintf(buff,
- (buff,"SET PASSWORD FOR \"%-.120s\"@\"%-.120s\"=\"%-.120s\"",
- acl_user->user ? acl_user->user : "",
- acl_user->host.hostname ? acl_user->host.hostname : "",
- new_password));
- mysql_update_log.write(thd, buff, query_length);
if (mysql_bin_log.is_open())
{
+ query_length=
+ my_sprintf(buff,
+ (buff,"SET PASSWORD FOR \"%-.120s\"@\"%-.120s\"=\"%-.120s\"",
+ acl_user->user ? acl_user->user : "",
+ acl_user->host.hostname ? acl_user->host.hostname : "",
+ new_password));
thd->clear_error();
Query_log_event qinfo(thd, buff, query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
@@ -1347,6 +1457,29 @@ end:
/*
+ Find user in ACL
+
+ SYNOPSIS
+ is_acl_user()
+ host host name
+ user user name
+
+ RETURN
+ FALSE user not fond
+ TRUE there are such user
+*/
+
+bool is_acl_user(const char *host, const char *user)
+{
+ bool res;
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+ res= find_acl_user(host, user, TRUE);
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ return res;
+}
+
+
+/*
Find first entry that matches the current user
*/
@@ -1431,7 +1564,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
return (tmp & host->ip_mask) == host->ip;
}
return (!host->hostname ||
- (hostname && !wild_case_compare(&my_charset_latin1,
+ (hostname && !wild_case_compare(system_charset_info,
hostname,host->hostname)) ||
(ip && !wild_compare(ip,host->hostname,0)));
}
@@ -1444,7 +1577,7 @@ bool hostname_requires_resolving(const char *hostname)
int namelen= strlen(hostname);
int lhlen= strlen(my_localhost);
if ((namelen == lhlen) &&
- !my_strnncoll(&my_charset_latin1, (const uchar *)hostname, namelen,
+ !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen,
(const uchar *)my_localhost, strlen(my_localhost)))
return FALSE;
for (; (cur=*hostname); hostname++)
@@ -1474,24 +1607,27 @@ static bool update_user_table(THD *thd, TABLE *table,
const char *host, const char *user,
const char *new_password, uint new_password_len)
{
+ char user_key[MAX_KEY_LENGTH];
int error;
DBUG_ENTER("update_user_table");
DBUG_PRINT("enter",("user: %s host: %s",user,host));
- table->field[0]->store(host,(uint) strlen(host), &my_charset_latin1);
- table->field[1]->store(user,(uint) strlen(user), &my_charset_latin1);
+ table->field[0]->store(host,(uint) strlen(host), system_charset_info);
+ table->field[1]->store(user,(uint) strlen(user), system_charset_info);
+ key_copy((byte *) user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- if (table->file->index_read_idx(table->record[0],0,
- (byte*) table->field[0]->ptr,
- table->key_info[0].key_length,
+ if (table->file->index_read_idx(table->record[0], 0,
+ (byte *) user_key, table->key_info->key_length,
HA_READ_KEY_EXACT))
{
- my_error(ER_PASSWORD_NO_MATCH,MYF(0)); /* purecov: deadcode */
+ my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
+ MYF(0)); /* purecov: deadcode */
DBUG_RETURN(1); /* purecov: deadcode */
}
store_record(table,record[1]);
- table->field[2]->store(new_password, new_password_len, &my_charset_latin1);
+ table->field[2]->store(new_password, new_password_len, system_charset_info);
if ((error=table->file->update_row(table->record[1],table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
@@ -1501,18 +1637,26 @@ static bool update_user_table(THD *thd, TABLE *table,
}
-/* Return 1 if we are allowed to create new users */
+/*
+ Return 1 if we are allowed to create new users
+ the logic here is: INSERT_ACL is sufficient.
+ It's also a requirement in opt_safe_user_create,
+ otherwise CREATE_USER_ACL is enough.
+*/
static bool test_if_create_new_users(THD *thd)
{
- bool create_new_users=1; // Assume that we are allowed to create new users
- if (opt_safe_user_create && !(thd->master_access & INSERT_ACL))
+ bool create_new_users= test(thd->master_access & INSERT_ACL) ||
+ (!opt_safe_user_create &&
+ test(thd->master_access & CREATE_USER_ACL));
+ if (!create_new_users)
{
TABLE_LIST tl;
ulong db_access;
bzero((char*) &tl,sizeof(tl));
tl.db= (char*) "mysql";
- tl.real_name= (char*) "user";
+ tl.table_name= (char*) "user";
+ create_new_users= 1;
db_access=acl_get(thd->host, thd->ip,
thd->priv_user, tl.db, 0);
@@ -1532,14 +1676,17 @@ static bool test_if_create_new_users(THD *thd)
static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
ulong rights, bool revoke_grant,
- bool create_user)
+ bool can_create_user, bool no_auto_create)
{
int error = -1;
bool old_row_exists=0;
const char *password= "";
uint password_len= 0;
char what= (revoke_grant) ? 'N' : 'Y';
+ byte user_key[MAX_KEY_LENGTH];
+ LEX *lex= thd->lex;
DBUG_ENTER("replace_user_table");
+
safe_mutex_assert_owner(&acl_cache->lock);
if (combo.password.str && combo.password.str[0])
@@ -1547,49 +1694,71 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
- my_printf_error(ER_UNKNOWN_ERROR,
- "Password hash should be a %d-digit hexadecimal number",
- MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
+ my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
DBUG_RETURN(-1);
}
password_len= combo.password.length;
password=combo.password.str;
}
- 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->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(combo.user.str,combo.user.length, system_charset_info);
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
+
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read_idx(table->record[0], 0,
- (byte*) table->field[0]->ptr,
- table->key_info[0].key_length,
- HA_READ_KEY_EXACT))
+ user_key, table->key_info->key_length,
+ HA_READ_KEY_EXACT))
{
- if (!create_user)
+ /* what == 'N' means revoke */
+ if (what == 'N')
{
- if (what == 'N')
- my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str);
- else
- my_error(ER_NO_PERMISSION_TO_CREATE_USER, MYF(0),
- thd->user, thd->host_or_ip);
+ my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str);
+ goto end;
+ }
+ /*
+ There are four options which affect the process of creation of
+ a new user (mysqld option --safe-create-user, 'insert' privilege
+ on 'mysql.user' table, using 'GRANT' with 'IDENTIFIED BY' and
+ SQL_MODE flag NO_AUTO_CREATE_USER). Below is the simplified rule
+ how it should work.
+ if (safe-user-create && ! INSERT_priv) => reject
+ else if (identified_by) => create
+ else if (no_auto_create_user) => reject
+ else create
+
+ see also test_if_create_new_users()
+ */
+ else if (!password_len && no_auto_create)
+ {
+ my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo.user.str, combo.host.str);
+ goto end;
+ }
+ else if (!can_create_user)
+ {
+ my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0),
+ thd->user, thd->host_or_ip);
goto end;
}
old_row_exists = 0;
- restore_record(table,default_values); // cp empty row from default_values
+ restore_record(table,s->default_values);
table->field[0]->store(combo.host.str,combo.host.length,
- &my_charset_latin1);
+ system_charset_info);
table->field[1]->store(combo.user.str,combo.user.length,
- &my_charset_latin1);
+ system_charset_info);
table->field[2]->store(password, password_len,
- &my_charset_latin1);
+ system_charset_info);
}
else
{
old_row_exists = 1;
store_record(table,record[1]); // Save copy for update
if (combo.password.str) // If password given
- table->field[2]->store(password, password_len, &my_charset_latin1);
- else if (!rights && !revoke_grant && thd->lex->ssl_type == SSL_TYPE_NOT_SPECIFIED &&
- !thd->lex->mqh.bits)
+ table->field[2]->store(password, password_len, system_charset_info);
+ else if (!rights && !revoke_grant &&
+ lex->ssl_type == SSL_TYPE_NOT_SPECIFIED &&
+ !lex->mqh.specified_limits)
{
DBUG_RETURN(0);
}
@@ -1609,11 +1778,11 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
(*tmp_field)->store(&what, 1, &my_charset_latin1);
}
rights= get_access(table, 3, &next_field);
- DBUG_PRINT("info",("table->fields: %d",table->fields));
- if (table->fields >= 31) /* From 4.0.0 we have more fields */
+ DBUG_PRINT("info",("table fields: %d",table->s->fields));
+ if (table->s->fields >= 31) /* From 4.0.0 we have more fields */
{
/* We write down SSL related ACL stuff */
- switch (thd->lex->ssl_type) {
+ switch (lex->ssl_type) {
case SSL_TYPE_ANY:
table->field[next_field]->store("ANY", 3, &my_charset_latin1);
table->field[next_field+1]->store("", 0, &my_charset_latin1);
@@ -1631,18 +1800,15 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
table->field[next_field+1]->store("", 0, &my_charset_latin1);
table->field[next_field+2]->store("", 0, &my_charset_latin1);
table->field[next_field+3]->store("", 0, &my_charset_latin1);
- if (thd->lex->ssl_cipher)
- table->field[next_field+1]->store(thd->lex->ssl_cipher,
- strlen(thd->lex->ssl_cipher),
- &my_charset_latin1);
- if (thd->lex->x509_issuer)
- table->field[next_field+2]->store(thd->lex->x509_issuer,
- strlen(thd->lex->x509_issuer),
- &my_charset_latin1);
- if (thd->lex->x509_subject)
- table->field[next_field+3]->store(thd->lex->x509_subject,
- strlen(thd->lex->x509_subject),
- &my_charset_latin1);
+ if (lex->ssl_cipher)
+ table->field[next_field+1]->store(lex->ssl_cipher,
+ strlen(lex->ssl_cipher), system_charset_info);
+ if (lex->x509_issuer)
+ table->field[next_field+2]->store(lex->x509_issuer,
+ strlen(lex->x509_issuer), system_charset_info);
+ if (lex->x509_subject)
+ table->field[next_field+3]->store(lex->x509_subject,
+ strlen(lex->x509_subject), system_charset_info);
break;
case SSL_TYPE_NOT_SPECIFIED:
break;
@@ -1653,18 +1819,19 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
table->field[next_field+3]->store("", 0, &my_charset_latin1);
break;
}
-
- /* Skip over SSL related fields to first user limits related field */
- next_field+= 4;
-
- USER_RESOURCES mqh= thd->lex->mqh;
- if (mqh.bits & 1)
- table->field[next_field]->store((longlong) mqh.questions);
- if (mqh.bits & 2)
- table->field[next_field+1]->store((longlong) mqh.updates);
- if (mqh.bits & 4)
- table->field[next_field+2]->store((longlong) mqh.connections);
- mqh_used = mqh_used || mqh.questions || mqh.updates || mqh.connections;
+ next_field+=4;
+
+ USER_RESOURCES mqh= lex->mqh;
+ if (mqh.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
+ table->field[next_field]->store((longlong) mqh.questions, TRUE);
+ if (mqh.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR)
+ table->field[next_field+1]->store((longlong) mqh.updates, TRUE);
+ if (mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR)
+ table->field[next_field+2]->store((longlong) mqh.conn_per_hour, TRUE);
+ if (table->s->fields >= 36 &&
+ (mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
+ table->field[next_field+3]->store((longlong) mqh.user_conn);
+ mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
}
if (old_row_exists)
{
@@ -1700,19 +1867,19 @@ end:
if (old_row_exists)
acl_update_user(combo.user.str, combo.host.str,
combo.password.str, password_len,
- thd->lex->ssl_type,
- thd->lex->ssl_cipher,
- thd->lex->x509_issuer,
- thd->lex->x509_subject,
- &thd->lex->mqh,
+ lex->ssl_type,
+ lex->ssl_cipher,
+ lex->x509_issuer,
+ lex->x509_subject,
+ &lex->mqh,
rights);
else
acl_insert_user(combo.user.str, combo.host.str, password, password_len,
- thd->lex->ssl_type,
- thd->lex->ssl_cipher,
- thd->lex->x509_issuer,
- thd->lex->x509_subject,
- &thd->lex->mqh,
+ lex->ssl_type,
+ lex->ssl_cipher,
+ lex->x509_issuer,
+ lex->x509_subject,
+ &lex->mqh,
rights);
}
DBUG_RETURN(error);
@@ -1732,6 +1899,7 @@ static int replace_db_table(TABLE *table, const char *db,
bool old_row_exists=0;
int error;
char what= (revoke_grant) ? 'N' : 'Y';
+ byte user_key[MAX_KEY_LENGTH];
DBUG_ENTER("replace_db_table");
if (!initialized)
@@ -1743,18 +1911,20 @@ static int replace_db_table(TABLE *table, const char *db,
/* Check if there is such a user in user table in memory? */
if (!find_acl_user(combo.host.str,combo.user.str, FALSE))
{
- my_error(ER_PASSWORD_NO_MATCH,MYF(0));
+ my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
DBUG_RETURN(-1);
}
- 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->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
+
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read_idx(table->record[0],0,
- (byte*) table->field[0]->ptr,
- table->key_info[0].key_length,
- HA_READ_KEY_EXACT))
+ user_key, table->key_info->key_length,
+ HA_READ_KEY_EXACT))
{
if (what == 'N')
{ // no row, no revoke
@@ -1762,10 +1932,10 @@ static int replace_db_table(TABLE *table, const char *db,
goto abort;
}
old_row_exists = 0;
- restore_record(table,default_values); // cp empty row from default_values
- 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);
+ restore_record(table, s->default_values);
+ table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
}
else
{
@@ -1774,7 +1944,7 @@ static int replace_db_table(TABLE *table, const char *db,
}
store_rights=get_rights_for_db(rights);
- for (i= 3, priv= 1; i < table->fields; i++, priv <<= 1)
+ for (i= 3, priv= 1; i < table->s->fields; i++, priv <<= 1)
{
if (priv & store_rights) // do it if priv is chosen
table->field [i]->store(&what,1, &my_charset_latin1);// set requested privileges
@@ -1841,27 +2011,40 @@ static byte* get_key_column(GRANT_COLUMN *buff,uint *length,
}
-class GRANT_TABLE :public Sql_alloc
+class GRANT_NAME :public Sql_alloc
{
public:
acl_host_and_ip host;
char *db, *user, *tname, *hash_key;
- ulong privs, cols;
+ ulong privs;
ulong sort;
uint key_length;
+ GRANT_NAME(const char *h, const char *d,const char *u,
+ const char *t, ulong p);
+ GRANT_NAME (TABLE *form);
+ virtual ~GRANT_NAME() {};
+ virtual bool ok() { return privs != 0; }
+};
+
+
+class GRANT_TABLE :public GRANT_NAME
+{
+public:
+ ulong cols;
HASH hash_columns;
GRANT_TABLE(const char *h, const char *d,const char *u,
const char *t, ulong p, ulong c);
GRANT_TABLE (TABLE *form, TABLE *col_privs);
+ ~GRANT_TABLE();
bool ok() { return privs != 0 || cols != 0; }
};
-GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u,
- const char *t, ulong p, ulong c)
- :privs(p), cols(c)
+GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u,
+ const char *t, ulong p)
+ :privs(p)
{
/* Host given by user */
update_hostname(&host, strdup_root(&memex, h));
@@ -1877,15 +2060,20 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u,
key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3;
hash_key = (char*) alloc_root(&memex,key_length);
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
- (void) hash_init(&hash_columns,&my_charset_latin1,
- 0,0,0, (hash_get_key) get_key_column,0,0);
}
-GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
+GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u,
+ const char *t, ulong p, ulong c)
+ :GRANT_NAME(h,d,u,t,p), cols(c)
{
- byte key[MAX_KEY_LENGTH];
+ (void) hash_init(&hash_columns,system_charset_info,
+ 0,0,0, (hash_get_key) get_key_column,0,0);
+}
+
+GRANT_NAME::GRANT_NAME(TABLE *form)
+{
update_hostname(&host, get_field(&memex, form->field[0]));
db= get_field(&memex,form->field[1]);
user= get_field(&memex,form->field[2]);
@@ -1896,7 +2084,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
if (!db || !tname)
{
/* Wrong table row; Ignore it */
- privs = cols = 0; /* purecov: inspected */
+ privs= 0;
return; /* purecov: inspected */
}
if (lower_case_table_names)
@@ -1909,31 +2097,49 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
hash_key = (char*) alloc_root(&memex,key_length);
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
privs = (ulong) form->field[6]->val_int();
- cols = (ulong) form->field[7]->val_int();
privs = fix_rights_for_table(privs);
+}
+
+
+GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
+ :GRANT_NAME(form)
+{
+ byte key[MAX_KEY_LENGTH];
+
+ if (!db || !tname)
+ {
+ /* Wrong table row; Ignore it */
+ hash_clear(&hash_columns); /* allow for destruction */
+ cols= 0;
+ return;
+ }
+ cols= (ulong) form->field[7]->val_int();
cols = fix_rights_for_column(cols);
- (void) hash_init(&hash_columns,&my_charset_latin1,
+ (void) hash_init(&hash_columns,system_charset_info,
0,0,0, (hash_get_key) get_key_column,0,0);
if (cols)
{
- int key_len;
+ uint key_prefix_len;
+ KEY_PART_INFO *key_part= col_privs->key_info->key_part;
col_privs->field[0]->store(host.hostname,
host.hostname ? (uint) strlen(host.hostname) : 0,
- &my_charset_latin1);
- col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
- col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1);
- col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1);
- key_len=(col_privs->field[0]->pack_length()+
- col_privs->field[1]->pack_length()+
- col_privs->field[2]->pack_length()+
- col_privs->field[3]->pack_length());
- key_copy(key,col_privs,0,key_len);
+ system_charset_info);
+ col_privs->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ col_privs->field[2]->store(user,(uint) strlen(user), system_charset_info);
+ col_privs->field[3]->store(tname,(uint) strlen(tname), system_charset_info);
+
+ key_prefix_len= (key_part[0].store_length +
+ key_part[1].store_length +
+ key_part[2].store_length +
+ key_part[3].store_length);
+ key_copy(key, col_privs->record[0], col_privs->key_info, key_prefix_len);
col_privs->field[4]->store("",0, &my_charset_latin1);
+
col_privs->file->ha_index_init(0);
if (col_privs->file->index_read(col_privs->record[0],
- (byte*) col_privs->field[0]->ptr,
- key_len, HA_READ_KEY_EXACT))
+ (byte*) key,
+ key_prefix_len, HA_READ_KEY_EXACT))
{
cols = 0; /* purecov: deadcode */
col_privs->file->ha_index_end();
@@ -1955,13 +2161,19 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
}
my_hash_insert(&hash_columns, (byte *) mem_check);
} while (!col_privs->file->index_next(col_privs->record[0]) &&
- !key_cmp_if_same(col_privs,key,0,key_len));
+ !key_cmp_if_same(col_privs,key,0,key_prefix_len));
col_privs->file->ha_index_end();
}
}
-static byte* get_grant_table(GRANT_TABLE *buff,uint *length,
+GRANT_TABLE::~GRANT_TABLE()
+{
+ hash_free(&hash_columns);
+}
+
+
+static byte* get_grant_table(GRANT_NAME *buff,uint *length,
my_bool not_used __attribute__((unused)))
{
*length=buff->key_length;
@@ -1977,39 +2189,58 @@ void free_grant_table(GRANT_TABLE *grant_table)
/* Search after a matching grant. Prefer exact grants before not exact ones */
-static GRANT_TABLE *table_hash_search(const char *host,const char* ip,
+static GRANT_NAME *name_hash_search(HASH *name_hash,
+ const char *host,const char* ip,
const char *db,
const char *user, const char *tname,
bool exact)
{
char helping [NAME_LEN*2+USERNAME_LENGTH+3];
uint len;
- GRANT_TABLE *grant_table,*found=0;
+ GRANT_NAME *grant_name,*found=0;
len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1;
- for (grant_table=(GRANT_TABLE*) hash_search(&column_priv_hash,
+ for (grant_name=(GRANT_NAME*) hash_search(name_hash,
(byte*) helping,
len) ;
- grant_table ;
- grant_table= (GRANT_TABLE*) hash_next(&column_priv_hash,(byte*) helping,
+ grant_name ;
+ grant_name= (GRANT_NAME*) hash_next(name_hash,(byte*) helping,
len))
{
if (exact)
{
- if (compare_hostname(&grant_table->host, host, ip))
- return grant_table;
+ if (compare_hostname(&grant_name->host, host, ip))
+ return grant_name;
}
else
{
- if (compare_hostname(&grant_table->host, host, ip) &&
- (!found || found->sort < grant_table->sort))
- found=grant_table; // Host ok
+ if (compare_hostname(&grant_name->host, host, ip) &&
+ (!found || found->sort < grant_name->sort))
+ found=grant_name; // Host ok
}
}
return found;
}
+inline GRANT_NAME *
+routine_hash_search(const char *host, const char *ip, const char *db,
+ const char *user, const char *tname, bool proc, bool exact)
+{
+ return (GRANT_TABLE*)
+ name_hash_search(proc ? &proc_priv_hash : &func_priv_hash,
+ host, ip, db, user, tname, exact);
+}
+
+
+inline GRANT_TABLE *
+table_hash_search(const char *host, const char *ip, const char *db,
+ const char *user, const char *tname, bool exact)
+{
+ return (GRANT_TABLE*) name_hash_search(&column_priv_hash, host, ip, db,
+ user, tname, exact);
+}
+
inline GRANT_COLUMN *
column_hash_search(GRANT_TABLE *t, const char *cname, uint length)
@@ -2025,50 +2256,65 @@ static int replace_column_table(GRANT_TABLE *g_t,
ulong rights, bool revoke_grant)
{
int error=0,result=0;
- uint key_length;
byte key[MAX_KEY_LENGTH];
+ uint key_prefix_length;
+ KEY_PART_INFO *key_part= table->key_info->key_part;
DBUG_ENTER("replace_column_table");
- 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->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1);
- key_length=(table->field[0]->pack_length()+ table->field[1]->pack_length()+
- table->field[2]->pack_length()+ table->field[3]->pack_length());
- key_copy(key,table,0,key_length);
+ table->field[0]->store(combo.host.str,combo.host.length,
+ system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db),
+ system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length,
+ system_charset_info);
+ table->field[3]->store(table_name,(uint) strlen(table_name),
+ system_charset_info);
- rights &= COL_ACLS; // Only ACL for columns
+ /* Get length of 3 first key parts */
+ key_prefix_length= (key_part[0].store_length + key_part[1].store_length +
+ key_part[2].store_length + key_part[3].store_length);
+ key_copy(key, table->record[0], table->key_info, key_prefix_length);
+
+ rights&= COL_ACLS; // Only ACL for columns
/* first fix privileges for all columns in column list */
List_iterator <LEX_COLUMN> iter(columns);
- class LEX_COLUMN *xx;
+ class LEX_COLUMN *column;
table->file->ha_index_init(0);
- while ((xx=iter++))
+ while ((column= iter++))
{
- ulong privileges = xx->rights;
+ ulong privileges= column->rights;
bool old_row_exists=0;
- key_restore(table,key,0,key_length);
- table->field[4]->store(xx->column.ptr(),xx->column.length(),
- &my_charset_latin1);
+ byte user_key[MAX_KEY_LENGTH];
+
+ key_restore(table->record[0],key,table->key_info,
+ key_prefix_length);
+ table->field[4]->store(column->column.ptr(), column->column.length(),
+ system_charset_info);
+ /* Get key for the first 4 columns */
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr,
- table->key_info[0].key_length,
- HA_READ_KEY_EXACT))
+ if (table->file->index_read(table->record[0], user_key,
+ table->key_info->key_length,
+ HA_READ_KEY_EXACT))
{
if (revoke_grant)
{
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
- combo.user.str, combo.host.str, table_name); /* purecov: inspected */
- result= -1; /* purecov: inspected */
- continue; /* purecov: inspected */
+ combo.user.str, combo.host.str,
+ table_name); /* purecov: inspected */
+ result= -1; /* purecov: inspected */
+ continue; /* purecov: inspected */
}
old_row_exists = 0;
- restore_record(table,default_values); // Get empty record
- key_restore(table,key,0,key_length);
- table->field[4]->store(xx->column.ptr(),xx->column.length(),
- &my_charset_latin1);
+ restore_record(table, s->default_values); // Get empty record
+ key_restore(table->record[0],key,table->key_info,
+ key_prefix_length);
+ table->field[4]->store(column->column.ptr(),column->column.length(),
+ system_charset_info);
}
else
{
@@ -2083,10 +2329,11 @@ static int replace_column_table(GRANT_TABLE *g_t,
store_record(table,record[1]); // copy original row
}
- table->field[6]->store((longlong) get_rights_for_column(privileges));
+ table->field[6]->store((longlong) get_rights_for_column(privileges), TRUE);
if (old_row_exists)
{
+ GRANT_COLUMN *grant_column;
if (privileges)
error=table->file->update_row(table->record[1],table->record[0]);
else
@@ -2097,21 +2344,21 @@ static int replace_column_table(GRANT_TABLE *g_t,
result= -1; /* purecov: inspected */
goto end; /* purecov: inspected */
}
- GRANT_COLUMN *grant_column = column_hash_search(g_t,
- xx->column.ptr(),
- xx->column.length());
+ grant_column= column_hash_search(g_t, column->column.ptr(),
+ column->column.length());
if (grant_column) // Should always be true
- grant_column->rights = privileges; // Update hash
+ grant_column->rights= privileges; // Update hash
}
else // new grant
{
+ GRANT_COLUMN *grant_column;
if ((error=table->file->write_row(table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
result= -1; /* purecov: inspected */
goto end; /* purecov: inspected */
}
- GRANT_COLUMN *grant_column = new GRANT_COLUMN(xx->column,privileges);
+ grant_column= new GRANT_COLUMN(column->column,privileges);
my_hash_insert(&g_t->hash_columns,(byte*) grant_column);
}
}
@@ -2123,10 +2370,14 @@ static int replace_column_table(GRANT_TABLE *g_t,
if (revoke_grant)
{
+ byte user_key[MAX_KEY_LENGTH];
+ key_copy(user_key, table->record[0], table->key_info,
+ key_prefix_length);
+
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- if (table->file->index_read(table->record[0], (byte*) table->field[0]->ptr,
- key_length,
- HA_READ_KEY_EXACT))
+ if (table->file->index_read(table->record[0], user_key,
+ key_prefix_length,
+ HA_READ_KEY_EXACT))
goto end;
/* Scan through all rows with the same host,db,user and table */
@@ -2140,11 +2391,12 @@ static int replace_column_table(GRANT_TABLE *g_t,
{
GRANT_COLUMN *grant_column = NULL;
char colum_name_buf[HOSTNAME_LENGTH+1];
- String column_name(colum_name_buf,sizeof(colum_name_buf),&my_charset_latin1);
+ String column_name(colum_name_buf,sizeof(colum_name_buf),
+ system_charset_info);
privileges&= ~rights;
table->field[6]->store((longlong)
- get_rights_for_column(privileges));
+ get_rights_for_column(privileges), TRUE);
table->field[4]->val_str(&column_name);
grant_column = column_hash_search(g_t,
column_name.ptr(),
@@ -2176,7 +2428,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
}
}
} while (!table->file->index_next(table->record[0]) &&
- !key_cmp_if_same(table,key,0,key_length));
+ !key_cmp_if_same(table, key, 0, key_prefix_length));
}
end:
@@ -2195,6 +2447,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
int old_row_exists = 1;
int error=0;
ulong store_table_rights, store_col_rights;
+ byte user_key[MAX_KEY_LENGTH];
DBUG_ENTER("replace_table_table");
strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS);
@@ -2205,20 +2458,23 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
*/
if (!find_acl_user(combo.host.str,combo.user.str, FALSE))
{
- my_error(ER_PASSWORD_NO_MATCH,MYF(0)); /* purecov: deadcode */
+ my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
+ MYF(0)); /* purecov: deadcode */
DBUG_RETURN(-1); /* purecov: deadcode */
}
- restore_record(table,default_values); // Get empty record
- 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->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1);
+ restore_record(table, s->default_values); // Get empty record
+ table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+ table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info);
store_record(table,record[1]); // store at pos 1
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
+
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- if (table->file->index_read_idx(table->record[0],0,
- (byte*) table->field[0]->ptr,
- table->key_info[0].key_length,
+ if (table->file->index_read_idx(table->record[0], 0,
+ user_key, table->key_info->key_length,
HA_READ_KEY_EXACT))
{
/*
@@ -2230,7 +2486,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
{ // no row, no revoke
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
combo.user.str, combo.host.str,
- table_name); /* purecov: deadcode */
+ table_name); /* purecov: deadcode */
DBUG_RETURN(-1); /* purecov: deadcode */
}
old_row_exists = 0;
@@ -2258,9 +2514,9 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
}
- table->field[4]->store(grantor,(uint) strlen(grantor), &my_charset_latin1);
- table->field[6]->store((longlong) store_table_rights);
- table->field[7]->store((longlong) store_col_rights);
+ table->field[4]->store(grantor,(uint) strlen(grantor), system_charset_info);
+ table->field[6]->store((longlong) store_table_rights, TRUE);
+ table->field[7]->store((longlong) store_col_rights, TRUE);
rights=fix_rights_for_table(store_table_rights);
col_rights=fix_rights_for_column(store_col_rights);
@@ -2299,6 +2555,121 @@ table_error:
}
+static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
+ TABLE *table, const LEX_USER &combo,
+ const char *db, const char *routine_name,
+ bool is_proc, ulong rights, bool revoke_grant)
+{
+ char grantor[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
+ int old_row_exists= 1;
+ int error=0;
+ ulong store_proc_rights;
+ DBUG_ENTER("replace_routine_table");
+
+ if (!initialized)
+ {
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
+ DBUG_RETURN(-1);
+ }
+
+ strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS);
+
+ /*
+ The following should always succeed as new users are created before
+ this function is called!
+ */
+ if (!find_acl_user(combo.host.str, combo.user.str, FALSE))
+ {
+ my_error(ER_PASSWORD_NO_MATCH,MYF(0));
+ DBUG_RETURN(-1);
+ }
+
+ restore_record(table, s->default_values); // Get empty record
+ 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->field[3]->store(routine_name,(uint) strlen(routine_name),
+ &my_charset_latin1);
+ table->field[4]->store((longlong)(is_proc ?
+ TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION),
+ TRUE);
+ store_record(table,record[1]); // store at pos 1
+
+ if (table->file->index_read_idx(table->record[0],0,
+ (byte*) table->field[0]->ptr,0,
+ HA_READ_KEY_EXACT))
+ {
+ /*
+ The following should never happen as we first check the in memory
+ grant tables for the user. There is however always a small change that
+ the user has modified the grant tables directly.
+ */
+ if (revoke_grant)
+ { // no row, no revoke
+ my_error(ER_NONEXISTING_PROC_GRANT, MYF(0),
+ combo.user.str, combo.host.str, routine_name);
+ DBUG_RETURN(-1);
+ }
+ old_row_exists= 0;
+ restore_record(table,record[1]); // Get saved record
+ }
+
+ store_proc_rights= get_rights_for_procedure(rights);
+ if (old_row_exists)
+ {
+ ulong j;
+ store_record(table,record[1]);
+ j= (ulong) table->field[6]->val_int();
+
+ if (revoke_grant)
+ {
+ /* column rights are already fixed in mysql_table_grant */
+ store_proc_rights=j & ~store_proc_rights;
+ }
+ else
+ {
+ store_proc_rights|= j;
+ }
+ }
+
+ table->field[5]->store(grantor,(uint) strlen(grantor), &my_charset_latin1);
+ table->field[6]->store((longlong) store_proc_rights, TRUE);
+ rights=fix_rights_for_procedure(store_proc_rights);
+
+ if (old_row_exists)
+ {
+ if (store_proc_rights)
+ {
+ if ((error=table->file->update_row(table->record[1],table->record[0])))
+ goto table_error;
+ }
+ else if ((error= table->file->delete_row(table->record[1])))
+ goto table_error;
+ }
+ else
+ {
+ error=table->file->write_row(table->record[0]);
+ if (error && error != HA_ERR_FOUND_DUPP_KEY)
+ goto table_error;
+ }
+
+ if (rights)
+ {
+ grant_name->privs= rights;
+ }
+ else
+ {
+ hash_delete(is_proc ? &proc_priv_hash : &func_priv_hash,(byte*) grant_name);
+ }
+ DBUG_RETURN(0);
+
+ /* This should never happen */
+table_error:
+ table->file->print_error(error,MYF(0));
+ DBUG_RETURN(-1);
+}
+
+
/*
Store table level and column level grants in the privilege tables
@@ -2312,11 +2683,11 @@ table_error:
revoke_grant Set to 1 if this is a REVOKE command
RETURN
- 0 ok
- 1 error
+ FALSE ok
+ TRUE error
*/
-int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
+bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
List <LEX_USER> &user_list,
List <LEX_COLUMN> &columns, ulong rights,
bool revoke_grant)
@@ -2326,45 +2697,48 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
LEX_USER *Str;
TABLE_LIST tables[3];
bool create_new_users=0;
+ char *db_name, *table_name;
DBUG_ENTER("mysql_table_grant");
if (!initialized)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-grant-tables"); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(TRUE); /* purecov: inspected */
}
if (rights & ~TABLE_ACLS)
{
- my_error(ER_ILLEGAL_GRANT_FOR_TABLE,MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
+ MYF(0));
+ DBUG_RETURN(TRUE);
}
if (!revoke_grant)
{
- if (columns.elements && !revoke_grant)
+ if (columns.elements)
{
- TABLE *table;
class LEX_COLUMN *column;
List_iterator <LEX_COLUMN> column_iter(columns);
- if (!(table=open_ltable(thd,table_list,TL_READ)))
- DBUG_RETURN(-1);
+ if (open_and_lock_tables(thd, table_list))
+ DBUG_RETURN(TRUE);
+
while ((column = column_iter++))
{
uint unused_field_idx= NO_CACHED_FIELD_INDEX;
- Field *f= find_field_in_table(thd,table,column->column.ptr(),
- column->column.length(),1,0,&unused_field_idx);
- if (!f)
+ TABLE_LIST *dummy;
+ Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(),
+ column->column.ptr(), NULL, NULL,
+ column->column.length(), 0, 1, 1, 0,
+ &unused_field_idx, FALSE, &dummy);
+ if (f == (Field*)0)
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
column->column.c_ptr(), table_list->alias);
- DBUG_RETURN(-1);
- }
- if (f == (Field*)-1)
- {
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
+ if (f == (Field *)-1)
+ DBUG_RETURN(TRUE);
column_priv|= column->rights;
}
close_thread_tables(thd);
@@ -2375,12 +2749,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
{
char buf[FN_REFLEN];
sprintf(buf,"%s/%s/%s.frm",mysql_data_home, table_list->db,
- table_list->real_name);
+ table_list->table_name);
fn_format(buf,buf,"","",4+16+32);
if (access(buf,F_OK))
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
if (table_list->grant.want_privilege)
@@ -2389,7 +2763,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
get_privilege_desc(command, sizeof(command),
table_list->grant.want_privilege);
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
- command, thd->priv_user, thd->host_or_ip, table_list->alias);
+ command, thd->priv_user, thd->host_or_ip, table_list->alias);
DBUG_RETURN(-1);
}
}
@@ -2398,14 +2772,16 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
/* open the mysql.tables_priv and mysql.columns_priv tables */
bzero((char*) &tables,sizeof(tables));
- tables[0].alias=tables[0].real_name= (char*) "user";
- tables[1].alias=tables[1].real_name= (char*) "tables_priv";
- tables[2].alias=tables[2].real_name= (char*) "columns_priv";
- tables[0].next=tables+1;
+ tables[0].alias=tables[0].table_name= (char*) "user";
+ tables[1].alias=tables[1].table_name= (char*) "tables_priv";
+ tables[2].alias=tables[2].table_name= (char*) "columns_priv";
+ tables[0].next_local= tables[0].next_global= tables+1;
/* Don't open column table if we don't need it ! */
- tables[1].next=((column_priv ||
- (revoke_grant && ((rights & COL_ACLS) || columns.elements)))
- ? tables+2 : 0);
+ tables[1].next_local=
+ tables[1].next_global= ((column_priv ||
+ (revoke_grant &&
+ ((rights & COL_ACLS) || columns.elements)))
+ ? tables+2 : 0);
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
@@ -2421,23 +2797,24 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
account in tests.
*/
tables[0].updating= tables[1].updating= tables[2].updating= 1;
- if (!tables_ok(0, tables))
- DBUG_RETURN(0);
+ if (!tables_ok(thd, tables))
+ DBUG_RETURN(FALSE);
}
#endif
if (simple_open_n_lock_tables(thd,tables))
{ // Should never happen
close_thread_tables(thd); /* purecov: deadcode */
- DBUG_RETURN(-1); /* purecov: deadcode */
+ DBUG_RETURN(TRUE); /* purecov: deadcode */
}
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
- int result=0;
+ bool result= FALSE;
rw_wrlock(&LOCK_grant);
MEM_ROOT *old_root= thd->mem_root;
thd->mem_root= &memex;
+ grant_version++;
while ((Str = str_list++))
{
@@ -2446,42 +2823,50 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
- my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0));
- result= -1;
+ my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
+ MYF(0));
+ result= TRUE;
continue;
}
/* Create user if needed */
pthread_mutex_lock(&acl_cache->lock);
error=replace_user_table(thd, tables[0].table, *Str,
- 0, revoke_grant, create_new_users);
+ 0, revoke_grant, create_new_users,
+ test(thd->variables.sql_mode &
+ MODE_NO_AUTO_CREATE_USER));
pthread_mutex_unlock(&acl_cache->lock);
if (error)
{
- result= -1; // Remember error
+ result= TRUE; // Remember error
continue; // Add next user
}
+ db_name= (table_list->view_db.length ?
+ table_list->view_db.str :
+ table_list->db);
+ table_name= (table_list->view_name.length ?
+ table_list->view_name.str :
+ table_list->table_name);
+
/* Find/create cached table grant */
- grant_table= table_hash_search(Str->host.str,NullS,table_list->db,
- Str->user.str,
- table_list->real_name,1);
+ grant_table= table_hash_search(Str->host.str, NullS, db_name,
+ Str->user.str, table_name, 1);
if (!grant_table)
{
if (revoke_grant)
{
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
- Str->user.str, Str->host.str, table_list->real_name);
- result= -1;
+ Str->user.str, Str->host.str, table_list->table_name);
+ result= TRUE;
continue;
}
- grant_table = new GRANT_TABLE (Str->host.str,table_list->db,
- Str->user.str,
- table_list->real_name,
+ grant_table = new GRANT_TABLE (Str->host.str, db_name,
+ Str->user.str, table_name,
rights,
column_priv);
if (!grant_table) // end of memory
{
- result= -1; /* purecov: deadcode */
+ result= TRUE; /* purecov: deadcode */
continue; /* purecov: deadcode */
}
my_hash_insert(&column_priv_hash,(byte*) grant_table);
@@ -2521,23 +2906,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
/* update table and columns */
- if (replace_table_table(thd,grant_table,tables[1].table,*Str,
- table_list->db,
- table_list->real_name,
+ if (replace_table_table(thd, grant_table, tables[1].table, *Str,
+ db_name, table_name,
rights, column_priv, revoke_grant))
{
/* Should only happen if table is crashed */
- result= -1; /* purecov: deadcode */
+ result= TRUE; /* purecov: deadcode */
}
else if (tables[2].table)
{
- if ((replace_column_table(grant_table,tables[2].table, *Str,
+ if ((replace_column_table(grant_table, tables[2].table, *Str,
columns,
- table_list->db,
- table_list->real_name,
+ db_name, table_name,
rights, revoke_grant)))
{
- result= -1;
+ result= TRUE;
}
}
}
@@ -2551,8 +2934,166 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
}
-int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
- ulong rights, bool revoke_grant)
+/*
+ Store routine level grants in the privilege tables
+
+ SYNOPSIS
+ mysql_routine_grant()
+ thd Thread handle
+ table_list List of routines to give grant
+ is_proc true indicates routine list are procedures
+ user_list List of users to give grant
+ rights Table level grant
+ revoke_grant Set to 1 if this is a REVOKE command
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
+ List <LEX_USER> &user_list, ulong rights,
+ bool revoke_grant, bool no_error)
+{
+ List_iterator <LEX_USER> str_list (user_list);
+ LEX_USER *Str;
+ TABLE_LIST tables[2];
+ bool create_new_users=0, result=0;
+ char *db_name, *table_name;
+ DBUG_ENTER("mysql_routine_grant");
+
+ if (!initialized)
+ {
+ if (!no_error)
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-grant-tables");
+ DBUG_RETURN(TRUE);
+ }
+ if (rights & ~PROC_ACLS)
+ {
+ if (!no_error)
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
+ MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!revoke_grant)
+ {
+ if (sp_exists_routine(thd, table_list, is_proc, no_error)<0)
+ DBUG_RETURN(TRUE);
+ }
+
+ /* open the mysql.user and mysql.procs_priv tables */
+
+ bzero((char*) &tables,sizeof(tables));
+ tables[0].alias=tables[0].table_name= (char*) "user";
+ tables[1].alias=tables[1].table_name= (char*) "procs_priv";
+ tables[0].next_local= tables[0].next_global= tables+1;
+ tables[0].lock_type=tables[1].lock_type=TL_WRITE;
+ tables[0].db=tables[1].db=(char*) "mysql";
+
+#ifdef HAVE_REPLICATION
+ /*
+ GRANT and REVOKE are applied the slave in/exclusion rules as they are
+ some kind of updates to the mysql.% tables.
+ */
+ if (thd->slave_thread && table_rules_on)
+ {
+ /*
+ The tables must be marked "updating" so that tables_ok() takes them into
+ account in tests.
+ */
+ tables[0].updating= tables[1].updating= 1;
+ if (!tables_ok(thd, tables))
+ DBUG_RETURN(FALSE);
+ }
+#endif
+
+ if (simple_open_n_lock_tables(thd,tables))
+ { // Should never happen
+ close_thread_tables(thd);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!revoke_grant)
+ create_new_users= test_if_create_new_users(thd);
+ rw_wrlock(&LOCK_grant);
+ MEM_ROOT *old_root= thd->mem_root;
+ thd->mem_root= &memex;
+
+ DBUG_PRINT("info",("now time to iterate and add users"));
+
+ while ((Str= str_list++))
+ {
+ int error;
+ GRANT_NAME *grant_name;
+ if (Str->host.length > HOSTNAME_LENGTH ||
+ Str->user.length > USERNAME_LENGTH)
+ {
+ if (!no_error)
+ my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
+ MYF(0));
+ result= TRUE;
+ continue;
+ }
+ /* Create user if needed */
+ pthread_mutex_lock(&acl_cache->lock);
+ error=replace_user_table(thd, tables[0].table, *Str,
+ 0, revoke_grant, create_new_users,
+ test(thd->variables.sql_mode &
+ MODE_NO_AUTO_CREATE_USER));
+ pthread_mutex_unlock(&acl_cache->lock);
+ if (error)
+ {
+ result= TRUE; // Remember error
+ continue; // Add next user
+ }
+
+ db_name= table_list->db;
+ table_name= table_list->table_name;
+
+ grant_name= routine_hash_search(Str->host.str, NullS, db_name,
+ Str->user.str, table_name, is_proc, 1);
+ if (!grant_name)
+ {
+ if (revoke_grant)
+ {
+ if (!no_error)
+ my_error(ER_NONEXISTING_PROC_GRANT, MYF(0),
+ Str->user.str, Str->host.str, table_name);
+ result= TRUE;
+ continue;
+ }
+ grant_name= new GRANT_NAME(Str->host.str, db_name,
+ Str->user.str, table_name,
+ rights);
+ if (!grant_name)
+ {
+ result= TRUE;
+ continue;
+ }
+ my_hash_insert(is_proc ? &proc_priv_hash : &func_priv_hash,(byte*) grant_name);
+ }
+
+ if (replace_routine_table(thd, grant_name, tables[1].table, *Str,
+ db_name, table_name, is_proc, rights, revoke_grant))
+ {
+ result= TRUE;
+ continue;
+ }
+ }
+ grant_option=TRUE;
+ thd->mem_root= old_root;
+ rw_unlock(&LOCK_grant);
+ if (!result && !no_error)
+ send_ok(thd);
+ /* Tables are automatically closed */
+ DBUG_RETURN(result);
+}
+
+
+bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
+ ulong rights, bool revoke_grant)
{
List_iterator <LEX_USER> str_list (list);
LEX_USER *Str;
@@ -2564,7 +3105,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-grant-tables"); /* purecov: tested */
- DBUG_RETURN(-1); /* purecov: tested */
+ DBUG_RETURN(TRUE); /* purecov: tested */
}
if (lower_case_table_names && db)
@@ -2576,13 +3117,11 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
/* open the mysql.user and mysql.db tables */
bzero((char*) &tables,sizeof(tables));
- tables[0].alias=tables[0].real_name=(char*) "user";
- tables[1].alias=tables[1].real_name=(char*) "db";
- tables[0].next=tables+1;
- tables[1].next=0;
+ tables[0].alias=tables[0].table_name=(char*) "user";
+ tables[1].alias=tables[1].table_name=(char*) "db";
+ tables[0].next_local= tables[0].next_global= tables+1;
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
tables[0].db=tables[1].db=(char*) "mysql";
- tables[0].table=tables[1].table=0;
#ifdef HAVE_REPLICATION
/*
@@ -2596,15 +3135,15 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
account in tests.
*/
tables[0].updating= tables[1].updating= 1;
- if (!tables_ok(0, tables))
- DBUG_RETURN(0);
+ if (!tables_ok(thd, tables))
+ DBUG_RETURN(FALSE);
}
#endif
if (simple_open_n_lock_tables(thd,tables))
{ // This should never happen
close_thread_tables(thd); /* purecov: deadcode */
- DBUG_RETURN(-1); /* purecov: deadcode */
+ DBUG_RETURN(TRUE); /* purecov: deadcode */
}
if (!revoke_grant)
@@ -2621,15 +3160,15 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
- my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0));
+ my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
+ MYF(0));
result= -1;
continue;
}
- if ((replace_user_table(thd,
- tables[0].table,
- *Str,
- (!db ? rights : 0), revoke_grant,
- create_new_users)))
+ if (replace_user_table(thd, tables[0].table, *Str,
+ (!db ? rights : 0), revoke_grant, create_new_users,
+ test(thd->variables.sql_mode &
+ MODE_NO_AUTO_CREATE_USER)))
result= -1;
else if (db)
{
@@ -2664,6 +3203,8 @@ void grant_free(void)
DBUG_ENTER("grant_free");
grant_option = FALSE;
hash_free(&column_priv_hash);
+ hash_free(&proc_priv_hash);
+ hash_free(&func_priv_hash);
free_root(&memex,MYF(0));
DBUG_VOID_RETURN;
}
@@ -2717,63 +3258,126 @@ static my_bool grant_load(TABLE_LIST *tables)
{
MEM_ROOT *memex_ptr;
my_bool return_val= 1;
- TABLE *t_table, *c_table;
+ TABLE *t_table, *c_table, *p_table;
bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE;
MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,
THR_MALLOC);
DBUG_ENTER("grant_load");
grant_option = FALSE;
- (void) hash_init(&column_priv_hash,&my_charset_latin1,
+ (void) hash_init(&column_priv_hash,system_charset_info,
0,0,0, (hash_get_key) get_grant_table,
(hash_free_key) free_grant_table,0);
+ (void) hash_init(&proc_priv_hash,system_charset_info,
+ 0,0,0, (hash_get_key) get_grant_table,
+ 0,0);
+ (void) hash_init(&func_priv_hash,system_charset_info,
+ 0,0,0, (hash_get_key) get_grant_table,
+ 0,0);
init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0);
t_table = tables[0].table; c_table = tables[1].table;
+ p_table= tables[2].table;
t_table->file->ha_index_init(0);
- if (t_table->file->index_first(t_table->record[0]))
+ p_table->file->ha_index_init(0);
+ if (!t_table->file->index_first(t_table->record[0]))
{
- return_val= 0;
- goto end_unlock;
- }
- grant_option= TRUE;
+ memex_ptr= &memex;
+ my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr);
+ do
+ {
+ GRANT_TABLE *mem_check;
+ if (!(mem_check=new GRANT_TABLE(t_table,c_table)))
+ {
+ /* This could only happen if we are out memory */
+ grant_option= FALSE;
+ goto end_unlock;
+ }
- memex_ptr= &memex;
- my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr);
- do
+ if (check_no_resolve)
+ {
+ if (hostname_requires_resolving(mem_check->host.hostname))
+ {
+ sql_print_warning("'tables_priv' entry '%s %s@%s' "
+ "ignored in --skip-name-resolve mode.",
+ mem_check->tname, mem_check->user,
+ mem_check->host, mem_check->host);
+ continue;
+ }
+ }
+
+ if (! mem_check->ok())
+ delete mem_check;
+ else if (my_hash_insert(&column_priv_hash,(byte*) mem_check))
+ {
+ delete mem_check;
+ grant_option= FALSE;
+ goto end_unlock;
+ }
+ }
+ while (!t_table->file->index_next(t_table->record[0]));
+ }
+ if (!p_table->file->index_first(p_table->record[0]))
{
- GRANT_TABLE *mem_check;
- if (!(mem_check=new GRANT_TABLE(t_table,c_table)))
+ memex_ptr= &memex;
+ my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr);
+ do
{
- /* This could only happen if we are out memory */
- grant_option= FALSE; /* purecov: deadcode */
- goto end_unlock;
- }
+ GRANT_NAME *mem_check;
+ HASH *hash;
+ if (!(mem_check=new GRANT_NAME(p_table)))
+ {
+ /* This could only happen if we are out memory */
+ grant_option= FALSE;
+ goto end_unlock;
+ }
- if (check_no_resolve)
- {
- if (hostname_requires_resolving(mem_check->host.hostname))
+ if (check_no_resolve)
{
- sql_print_warning("'tables_priv' entry '%s %s@%s' "
- "ignored in --skip-name-resolve mode.",
- mem_check->tname, mem_check->user,
- mem_check->host);
+ if (hostname_requires_resolving(mem_check->host.hostname))
+ {
+ sql_print_warning("'procs_priv' entry '%s %s@%s' "
+ "ignored in --skip-name-resolve mode.",
+ mem_check->tname, mem_check->user,
+ mem_check->host);
+ continue;
+ }
+ }
+ if (p_table->field[4]->val_int() == TYPE_ENUM_PROCEDURE)
+ {
+ hash= &proc_priv_hash;
+ }
+ else
+ if (p_table->field[4]->val_int() == TYPE_ENUM_FUNCTION)
+ {
+ hash= &func_priv_hash;
+ }
+ else
+ {
+ sql_print_warning("'procs_priv' entry '%s' "
+ "ignored, bad routine type",
+ mem_check->tname);
continue;
}
- }
- if (mem_check->ok() && my_hash_insert(&column_priv_hash,(byte*) mem_check))
- {
- grant_option= FALSE;
- goto end_unlock;
+ mem_check->privs= fix_rights_for_procedure(mem_check->privs);
+ if (! mem_check->ok())
+ delete mem_check;
+ else if (my_hash_insert(hash, (byte*) mem_check))
+ {
+ delete mem_check;
+ grant_option= FALSE;
+ goto end_unlock;
+ }
}
+ while (!p_table->file->index_next(p_table->record[0]));
}
- while (!t_table->file->index_next(t_table->record[0]));
-
+ grant_option= TRUE;
return_val=0; // Return ok
end_unlock:
t_table->file->ha_index_end();
+ p_table->file->ha_index_end();
my_pthread_setspecific_ptr(THR_MALLOC, save_mem_root_ptr);
DBUG_RETURN(return_val);
}
@@ -2799,8 +3403,8 @@ end_unlock:
my_bool grant_reload(THD *thd)
{
- TABLE_LIST tables[2];
- HASH old_column_priv_hash;
+ TABLE_LIST tables[3];
+ HASH old_column_priv_hash, old_proc_priv_hash, old_func_priv_hash;
bool old_grant_option;
MEM_ROOT old_mem;
my_bool return_val= 1;
@@ -2811,11 +3415,13 @@ my_bool grant_reload(THD *thd)
DBUG_RETURN(0);
bzero((char*) tables, sizeof(tables));
- tables[0].alias=tables[0].real_name= (char*) "tables_priv";
- tables[1].alias=tables[1].real_name= (char*) "columns_priv";
- tables[0].db=tables[1].db= (char *) "mysql";
- tables[0].next=tables+1;
- tables[0].lock_type=tables[1].lock_type=TL_READ;
+ tables[0].alias= tables[0].table_name= (char*) "tables_priv";
+ tables[1].alias= tables[1].table_name= (char*) "columns_priv";
+ tables[2].alias= tables[2].table_name= (char*) "procs_priv";
+ tables[0].db= tables[1].db= tables[2].db= (char *) "mysql";
+ tables[0].next_local= tables[0].next_global= tables+1;
+ tables[1].next_local= tables[1].next_global= tables+2;
+ tables[0].lock_type= tables[1].lock_type= tables[2].lock_type= TL_READ;
/*
To avoid deadlocks we should obtain table locks before
@@ -2827,6 +3433,8 @@ my_bool grant_reload(THD *thd)
rw_wrlock(&LOCK_grant);
grant_version++;
old_column_priv_hash= column_priv_hash;
+ old_proc_priv_hash= proc_priv_hash;
+ old_func_priv_hash= func_priv_hash;
old_grant_option= grant_option;
old_mem= memex;
@@ -2835,12 +3443,16 @@ my_bool grant_reload(THD *thd)
DBUG_PRINT("error",("Reverting to old privileges"));
grant_free(); /* purecov: deadcode */
column_priv_hash= old_column_priv_hash; /* purecov: deadcode */
+ proc_priv_hash= old_proc_priv_hash;
+ func_priv_hash= old_func_priv_hash;
grant_option= old_grant_option; /* purecov: deadcode */
memex= old_mem; /* purecov: deadcode */
}
else
{
hash_free(&old_column_priv_hash);
+ hash_free(&old_proc_priv_hash);
+ hash_free(&old_func_priv_hash);
free_root(&old_mem,MYF(0));
}
rw_unlock(&LOCK_grant);
@@ -2852,7 +3464,22 @@ end:
/****************************************************************************
Check table level grants
- All errors are written directly to the client if no_errors is given !
+
+ SYNOPSIS
+ bool check_grant()
+ thd Thread handler
+ want_access Bits of privileges user needs to have
+ tables List of tables to check. The user should have 'want_access'
+ to all tables in list.
+ show_table <> 0 if we are in show table. In this case it's enough to have
+ any privilege for the table
+ number Check at most this number of tables.
+ no_errors If 0 then we write an error. The error is sent directly to
+ the client
+
+ RETURN
+ 0 ok
+ 1 Error: User did not have the requested privileges
****************************************************************************/
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
@@ -2861,23 +3488,28 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
TABLE_LIST *table;
char *user = thd->priv_user;
DBUG_ENTER("check_grant");
+ DBUG_ASSERT(number > 0);
- want_access &= ~thd->master_access;
+ want_access&= ~thd->master_access;
if (!want_access)
DBUG_RETURN(0); // ok
rw_rdlock(&LOCK_grant);
- for (table= tables; table && number--; table= table->next)
+ for (table= tables; table && number--; table= table->next_global)
{
- if (!(~table->grant.privilege & want_access) || table->derived)
+ GRANT_TABLE *grant_table;
+ if (!(~table->grant.privilege & want_access) ||
+ table->derived || table->schema_table || table->belong_to_view)
{
- table->grant.want_privilege=0;
+ /*
+ It is subquery in the FROM clause. VIEW set table->derived after
+ table opening, but this function always called before table opening.
+ */
+ table->grant.want_privilege= 0;
continue; // Already checked
}
- GRANT_TABLE *grant_table = table_hash_search(thd->host,thd->ip,
- table->db,user,
- table->real_name,0);
- if (!grant_table)
+ if (!(grant_table= table_hash_search(thd->host,thd->ip,
+ table->db,user, table->table_name,0)))
{
want_access &= ~table->grant.privilege;
goto err; // No grants
@@ -2909,137 +3541,133 @@ err:
{
char command[128];
get_privilege_desc(command, sizeof(command), want_access);
- net_printf(thd,ER_TABLEACCESS_DENIED_ERROR,
- command,
- thd->priv_user,
- thd->host_or_ip,
- table ? table->real_name : "unknown");
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ command,
+ thd->priv_user,
+ thd->host_or_ip,
+ table ? table->table_name : "unknown");
}
DBUG_RETURN(1);
}
-bool check_grant_column(THD *thd,TABLE *table, const char *name,
- uint length, uint show_tables)
+bool check_grant_column(THD *thd, GRANT_INFO *grant,
+ const char *db_name, const char *table_name,
+ const char *name, uint length, uint show_tables)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
+ ulong want_access= grant->want_privilege & ~grant->privilege;
+ DBUG_ENTER("check_grant_column");
+ DBUG_PRINT("enter", ("table: %s want_access: %u", table_name, want_access));
- ulong want_access=table->grant.want_privilege;
if (!want_access)
- return 0; // Already checked
+ DBUG_RETURN(0); // Already checked
rw_rdlock(&LOCK_grant);
/* reload table if someone has modified any grants */
- if (table->grant.version != grant_version)
+ if (grant->version != grant_version)
{
- table->grant.grant_table=
- table_hash_search(thd->host, thd->ip, table->table_cache_key,
+ grant->grant_table=
+ table_hash_search(thd->host, thd->ip, db_name,
thd->priv_user,
- table->real_name, 0); /* purecov: inspected */
- table->grant.version=grant_version; /* purecov: inspected */
+ table_name, 0); /* purecov: inspected */
+ grant->version= grant_version; /* purecov: inspected */
}
- if (!(grant_table=table->grant.grant_table))
+ if (!(grant_table= grant->grant_table))
goto err; /* purecov: deadcode */
grant_column=column_hash_search(grant_table, name, length);
if (grant_column && !(~grant_column->rights & want_access))
{
rw_unlock(&LOCK_grant);
- return 0;
+ DBUG_RETURN(0);
}
#ifdef NOT_USED
- if (show_tables && (grant_column || table->grant.privilege & COL_ACLS))
+ if (show_tables && (grant_column || grant->privilege & COL_ACLS))
{
rw_unlock(&LOCK_grant); /* purecov: deadcode */
- return 0; /* purecov: deadcode */
+ DBUG_RETURN(0); /* purecov: deadcode */
}
#endif
- /* We must use my_printf_error() here! */
err:
rw_unlock(&LOCK_grant);
if (!show_tables)
{
char command[128];
get_privilege_desc(command, sizeof(command), want_access);
- my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
- ER(ER_COLUMNACCESS_DENIED_ERROR),
- MYF(0),
- command,
- thd->priv_user,
- thd->host_or_ip,
- name,
- table ? table->real_name : "unknown");
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ command,
+ thd->priv_user,
+ thd->host_or_ip,
+ name,
+ table_name);
}
- return 1;
+ DBUG_RETURN(1);
}
-bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
+bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
+ const char* db_name, const char *table_name,
+ Field_iterator *fields)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
- Field *field=0,**ptr;
- want_access &= ~table->grant.privilege;
+ want_access &= ~grant->privilege;
if (!want_access)
return 0; // Already checked
if (!grant_option)
- {
- field= table->field[0]; // To give a meaningful error message
goto err2;
- }
rw_rdlock(&LOCK_grant);
/* reload table if someone has modified any grants */
- if (table->grant.version != grant_version)
+ if (grant->version != grant_version)
{
- table->grant.grant_table=
- table_hash_search(thd->host, thd->ip, table->table_cache_key,
+ grant->grant_table=
+ table_hash_search(thd->host, thd->ip, db_name,
thd->priv_user,
- table->real_name,0); /* purecov: inspected */
- table->grant.version=grant_version; /* purecov: inspected */
+ table_name, 0); /* purecov: inspected */
+ grant->version= grant_version; /* purecov: inspected */
}
/* The following should always be true */
- if (!(grant_table=table->grant.grant_table))
+ if (!(grant_table= grant->grant_table))
goto err; /* purecov: inspected */
- for (ptr=table->field; (field= *ptr) ; ptr++)
+ for (; !fields->end_of_fields(); fields->next())
{
- grant_column=column_hash_search(grant_table, field->field_name,
- (uint) strlen(field->field_name));
+ const char *field_name= fields->name();
+ grant_column= column_hash_search(grant_table, field_name,
+ (uint) strlen(field_name));
if (!grant_column || (~grant_column->rights & want_access))
goto err;
}
rw_unlock(&LOCK_grant);
return 0;
- /* We must use my_printf_error() here! */
err:
rw_unlock(&LOCK_grant);
err2:
char command[128];
get_privilege_desc(command, sizeof(command), want_access);
- my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
- ER(ER_COLUMNACCESS_DENIED_ERROR),
- MYF(0),
- command,
- thd->priv_user,
- thd->host_or_ip,
- field ? field->field_name : "unknown",
- table->real_name);
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ command,
+ thd->priv_user,
+ thd->host_or_ip,
+ fields->name(),
+ table_name);
return 1;
}
/*
Check if a user has the right to access a database
- Access is accepted if he has a grant for any table in the database
+ Access is accepted if he has a grant for any table/routine in the database
Return 1 if access is denied
*/
@@ -3047,9 +3675,9 @@ bool check_grant_db(THD *thd,const char *db)
{
char helping [NAME_LEN+USERNAME_LENGTH+2];
uint len;
- bool error=1;
+ bool error= 1;
- len = (uint) (strmov(strmov(helping,thd->priv_user)+1,db)-helping)+ 1;
+ len= (uint) (strmov(strmov(helping,thd->priv_user)+1,db)-helping)+ 1;
rw_rdlock(&LOCK_grant);
for (uint idx=0 ; idx < column_priv_hash.records ; idx++)
@@ -3068,6 +3696,105 @@ bool check_grant_db(THD *thd,const char *db)
return error;
}
+
+/****************************************************************************
+ Check routine level grants
+
+ SYNPOSIS
+ bool check_grant_routine()
+ thd Thread handler
+ want_access Bits of privileges user needs to have
+ procs List of routines to check. The user should have 'want_access'
+ is_proc True if the list is all procedures, else functions
+ no_errors If 0 then we write an error. The error is sent directly to
+ the client
+
+ RETURN
+ 0 ok
+ 1 Error: User did not have the requested privielges
+****************************************************************************/
+
+bool check_grant_routine(THD *thd, ulong want_access,
+ TABLE_LIST *procs, bool is_proc, bool no_errors)
+{
+ TABLE_LIST *table;
+ char *user= thd->priv_user;
+ char *host= thd->priv_host;
+ DBUG_ENTER("check_grant_routine");
+
+ want_access&= ~thd->master_access;
+ if (!want_access)
+ DBUG_RETURN(0); // ok
+
+ rw_rdlock(&LOCK_grant);
+ for (table= procs; table; table= table->next_global)
+ {
+ GRANT_NAME *grant_proc;
+ if ((grant_proc= routine_hash_search(host,thd->ip, table->db, user,
+ table->table_name, is_proc, 0)))
+ table->grant.privilege|= grant_proc->privs;
+
+ if (want_access & ~table->grant.privilege)
+ {
+ want_access &= ~table->grant.privilege;
+ goto err;
+ }
+ }
+ rw_unlock(&LOCK_grant);
+ DBUG_RETURN(0);
+err:
+ rw_unlock(&LOCK_grant);
+ if (!no_errors)
+ {
+ char buff[1024];
+ const char *command="";
+ if (table)
+ strxmov(buff, table->db, ".", table->table_name, NullS);
+ if (want_access & EXECUTE_ACL)
+ command= "execute";
+ else if (want_access & ALTER_PROC_ACL)
+ command= "alter routine";
+ else if (want_access & GRANT_ACL)
+ command= "grant";
+ my_error(ER_PROCACCESS_DENIED_ERROR, MYF(0),
+ command, user, host, table ? buff : "unknown");
+ }
+ DBUG_RETURN(1);
+}
+
+
+/*
+ Check if routine has any of the
+ routine level grants
+
+ SYNPOSIS
+ bool check_routine_level_acl()
+ thd Thread handler
+ db Database name
+ name Routine name
+
+ RETURN
+ 0 Ok
+ 1 error
+*/
+
+bool check_routine_level_acl(THD *thd, const char *db, const char *name,
+ bool is_proc)
+{
+ bool no_routine_acl= 1;
+ if (grant_option)
+ {
+ GRANT_NAME *grant_proc;
+ rw_rdlock(&LOCK_grant);
+ if ((grant_proc= routine_hash_search(thd->priv_host, thd->ip, db,
+ thd->priv_user, name, is_proc, 0)))
+ no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS);
+ rw_unlock(&LOCK_grant);
+ }
+ return no_routine_acl;
+}
+
+
/*****************************************************************************
Functions to retrieve the grant for a table/column (for SHOW functions)
*****************************************************************************/
@@ -3084,7 +3811,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table)
grant_table= NULL;
#else
grant_table= table_hash_search(thd->host, thd->ip, db, user,
- table->real_name, 0);
+ table->table_name, 0);
#endif
table->grant.grant_table=grant_table; // Remember for column test
table->grant.version=grant_version;
@@ -3096,7 +3823,27 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table)
}
-ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
+/*
+ Determine the access priviliges for a field.
+
+ SYNOPSIS
+ get_column_grant()
+ thd thread handler
+ grant grants table descriptor
+ db_name name of database that the field belongs to
+ table_name name of table that the field belongs to
+ field_name name of field
+
+ DESCRIPTION
+ The procedure may also modify: grant->grant_table and grant->version.
+
+ RETURN
+ The access priviliges for the field db_name.table_name.field_name
+*/
+
+ulong get_column_grant(THD *thd, GRANT_INFO *grant,
+ const char *db_name, const char *table_name,
+ const char *field_name)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
@@ -3104,30 +3851,31 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
rw_rdlock(&LOCK_grant);
/* reload table if someone has modified any grants */
- if (table->grant.version != grant_version)
+ if (grant->version != grant_version)
{
- table->grant.grant_table=
- table_hash_search(thd->host, thd->ip, table->db,
+ grant->grant_table=
+ table_hash_search(thd->host, thd->ip, db_name,
thd->priv_user,
- table->real_name,0); /* purecov: inspected */
- table->grant.version=grant_version; /* purecov: inspected */
+ table_name, 0); /* purecov: inspected */
+ grant->version= grant_version; /* purecov: inspected */
}
- if (!(grant_table=table->grant.grant_table))
- priv=table->grant.privilege;
+ if (!(grant_table= grant->grant_table))
+ priv= grant->privilege;
else
{
- grant_column=column_hash_search(grant_table, field->field_name,
- (uint) strlen(field->field_name));
+ grant_column= column_hash_search(grant_table, field_name,
+ (uint) strlen(field_name));
if (!grant_column)
- priv=table->grant.privilege;
+ priv= (grant->privilege | grant_table->privs);
else
- priv=table->grant.privilege | grant_column->rights;
+ priv= (grant->privilege | grant_table->privs | grant_column->rights);
}
rw_unlock(&LOCK_grant);
return priv;
}
+
/* Help function for mysql_show_grants */
static void add_user_option(String *grant, ulong value, const char *name)
@@ -3145,18 +3893,26 @@ static void add_user_option(String *grant, ulong value, const char *name)
static const char *command_array[]=
{
- "SELECT", "INSERT","UPDATE","DELETE","CREATE", "DROP", "RELOAD","SHUTDOWN",
- "PROCESS","FILE","GRANT","REFERENCES","INDEX", "ALTER", "SHOW DATABASES",
- "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE",
- "REPLICATION SLAVE", "REPLICATION CLIENT",
+ "SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD",
+ "SHUTDOWN", "PROCESS","FILE", "GRANT", "REFERENCES", "INDEX",
+ "ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES",
+ "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT",
+ "CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE", "ALTER ROUTINE",
+ "CREATE USER"
};
static uint command_lengths[]=
{
- 6,6,6,6,6,4,6,8,7,4,5,10,5,5,14,5,23,11,7,17,18
+ 6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9,
+ 14, 13, 11
};
+static int show_routine_grants(THD *thd, LEX_USER *lex_user, HASH *hash,
+ const char *type, int typelen,
+ char *buff, int buffsize);
+
+
/*
SHOW GRANTS; Send grants for a user to the client
@@ -3164,7 +3920,7 @@ static uint command_lengths[]=
Send to client grant-like strings depicting user@host privileges
*/
-int mysql_show_grants(THD *thd,LEX_USER *lex_user)
+bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
ulong want_access;
uint counter,index;
@@ -3179,7 +3935,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (!initialized)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
if (!lex_user->host.str)
@@ -3190,8 +3946,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (lex_user->host.length > HOSTNAME_LENGTH ||
lex_user->user.length > USERNAME_LENGTH)
{
- my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
+ MYF(0));
+ DBUG_RETURN(TRUE);
}
for (counter=0 ; counter < acl_users.elements ; counter++)
@@ -3203,14 +3960,14 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (!(host=acl_user->host.hostname))
host= "";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host))
+ !my_strcasecmp(system_charset_info, lex_user->host.str, host))
break;
}
if (counter == acl_users.elements)
{
my_error(ER_NONEXISTING_GRANT, MYF(0),
lex_user->user.str, lex_user->host.str);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
Item_string *field=new Item_string("",0,&my_charset_latin1);
@@ -3220,8 +3977,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
strxmov(buff,"Grants for ",lex_user->user.str,"@",
lex_user->host.str,NullS);
field_list.push_back(field);
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(-1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -3256,7 +4014,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
global.append ("'@'",3);
- global.append(lex_user->host.str,lex_user->host.length);
+ global.append(lex_user->host.str,lex_user->host.length,
+ system_charset_info);
global.append ('\'');
if (acl_user->salt_len)
{
@@ -3290,7 +4049,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (ssl_options++)
global.append(' ');
global.append("SUBJECT \'",9);
- global.append(acl_user->x509_subject,strlen(acl_user->x509_subject));
+ global.append(acl_user->x509_subject,strlen(acl_user->x509_subject),
+ system_charset_info);
global.append('\'');
}
if (acl_user->ssl_cipher)
@@ -3298,13 +4058,16 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (ssl_options++)
global.append(' ');
global.append("CIPHER '",8);
- global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher));
+ global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher),
+ system_charset_info);
global.append('\'');
}
}
if ((want_access & GRANT_ACL) ||
- (acl_user->user_resource.questions | acl_user->user_resource.updates |
- acl_user->user_resource.connections))
+ (acl_user->user_resource.questions ||
+ acl_user->user_resource.updates ||
+ acl_user->user_resource.conn_per_hour ||
+ acl_user->user_resource.user_conn))
{
global.append(" WITH",5);
if (want_access & GRANT_ACL)
@@ -3313,8 +4076,10 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
"MAX_QUERIES_PER_HOUR");
add_user_option(&global, acl_user->user_resource.updates,
"MAX_UPDATES_PER_HOUR");
- add_user_option(&global, acl_user->user_resource.connections,
+ add_user_option(&global, acl_user->user_resource.conn_per_hour,
"MAX_CONNECTIONS_PER_HOUR");
+ add_user_option(&global, acl_user->user_resource.user_conn,
+ "MAX_USER_CONNECTIONS");
}
protocol->prepare_for_resend();
protocol->store(global.ptr(),global.length(),global.charset());
@@ -3337,7 +4102,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
host= "";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host))
+ !my_strcasecmp(system_charset_info, lex_user->host.str, host))
{
want_access=acl_db->access;
if (want_access)
@@ -3371,7 +4136,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
db.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
db.append ("'@'",3);
- db.append(lex_user->host.str, lex_user->host.length);
+ db.append(lex_user->host.str, lex_user->host.length,
+ system_charset_info);
db.append ('\'');
if (want_access & GRANT_ACL)
db.append(" WITH GRANT OPTION",18);
@@ -3397,7 +4163,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
user= "";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(&my_charset_latin1, lex_user->host.str,
+ !my_strcasecmp(system_charset_info, lex_user->host.str,
grant_table->host.hostname))
{
ulong table_access= grant_table->privs;
@@ -3477,7 +4243,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
global.append("'@'",3);
- global.append(lex_user->host.str,lex_user->host.length);
+ global.append(lex_user->host.str,lex_user->host.length,
+ system_charset_info);
global.append('\'');
if (table_access & GRANT_ACL)
global.append(" WITH GRANT OPTION",18);
@@ -3491,6 +4258,21 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
}
+
+ if (show_routine_grants(thd, lex_user, &proc_priv_hash,
+ "PROCEDURE", 9, buff, sizeof(buff)))
+ {
+ error= -1;
+ goto end;
+ }
+
+ if (show_routine_grants(thd, lex_user, &func_priv_hash,
+ "FUNCTION", 8, buff, sizeof(buff)))
+ {
+ error= -1;
+ goto end;
+ }
+
end:
VOID(pthread_mutex_unlock(&acl_cache->lock));
rw_unlock(&LOCK_grant);
@@ -3499,6 +4281,83 @@ end:
DBUG_RETURN(error);
}
+static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
+ const char *type, int typelen,
+ char *buff, int buffsize)
+{
+ uint counter, index;
+ int error= 0;
+ Protocol *protocol= thd->protocol;
+ /* Add routine access */
+ for (index=0 ; index < hash->records ; index++)
+ {
+ const char *user;
+ GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, index);
+
+ if (!(user=grant_proc->user))
+ user= "";
+
+ if (!strcmp(lex_user->user.str,user) &&
+ !my_strcasecmp(system_charset_info, lex_user->host.str,
+ grant_proc->host.hostname))
+ {
+ ulong proc_access= grant_proc->privs;
+ if (proc_access != 0)
+ {
+ String global(buff, buffsize, system_charset_info);
+ ulong test_access= proc_access & ~GRANT_ACL;
+
+ global.length(0);
+ global.append("GRANT ",6);
+
+ if (!test_access)
+ global.append("USAGE",5);
+ else
+ {
+ /* Add specific procedure access */
+ int found= 0;
+ ulong j;
+
+ for (counter= 0, j= SELECT_ACL; j <= PROC_ACLS; counter++, j<<= 1)
+ {
+ if (test_access & j)
+ {
+ if (found)
+ global.append(", ",2);
+ found= 1;
+ global.append(command_array[counter],command_lengths[counter]);
+ }
+ }
+ }
+ global.append(" ON ",4);
+ global.append(type,typelen);
+ global.append(' ');
+ append_identifier(thd, &global, grant_proc->db,
+ strlen(grant_proc->db));
+ global.append('.');
+ append_identifier(thd, &global, grant_proc->tname,
+ strlen(grant_proc->tname));
+ global.append(" TO '",5);
+ global.append(lex_user->user.str, lex_user->user.length,
+ system_charset_info);
+ global.append("'@'",3);
+ global.append(lex_user->host.str,lex_user->host.length,
+ system_charset_info);
+ global.append('\'');
+ if (proc_access & GRANT_ACL)
+ global.append(" WITH GRANT OPTION",18);
+ protocol->prepare_for_resend();
+ protocol->store(global.ptr(),global.length(),global.charset());
+ if (protocol->write())
+ {
+ error= -1;
+ break;
+ }
+ }
+ }
+ }
+ return error;
+}
/*
Make a clear-text version of the requested privilege.
@@ -3537,28 +4396,53 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc)
bzero((char*) &uc->user_resources, sizeof(uc->user_resources));
}
+/*
+ Open the grant tables.
+
+ SYNOPSIS
+ open_grant_tables()
+ thd The current thread.
+ tables (out) The 4 elements array for the opened tables.
+
+ DESCRIPTION
+ Tables are numbered as follows:
+ 0 user
+ 1 db
+ 2 tables_priv
+ 3 columns_priv
+
+ RETURN
+ 1 Skip GRANT handling during replication.
+ 0 OK.
+ < 0 Error.
+*/
+
+#define GRANT_TABLES 5
int open_grant_tables(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("open_grant_tables");
if (!initialized)
{
- net_printf(thd,ER_OPTION_PREVENTS_STATEMENT, "--skip-grant-tables");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
DBUG_RETURN(-1);
}
- bzero((char*) tables, 4*sizeof(*tables));
- tables->alias= tables->real_name= (char*) "user";
- (tables+1)->alias= (tables+1)->real_name= (char*) "db";
- (tables+2)->alias= (tables+2)->real_name= (char*) "tables_priv";
- (tables+3)->alias= (tables+3)->real_name= (char*) "columns_priv";
- tables->next= tables+1;
- (tables+1)->next= tables+2;
- (tables+2)->next= tables+3;
- (tables+3)->next= 0;
+ bzero((char*) tables, GRANT_TABLES*sizeof(*tables));
+ tables->alias= tables->table_name= (char*) "user";
+ (tables+1)->alias= (tables+1)->table_name= (char*) "db";
+ (tables+2)->alias= (tables+2)->table_name= (char*) "tables_priv";
+ (tables+3)->alias= (tables+3)->table_name= (char*) "columns_priv";
+ (tables+4)->alias= (tables+4)->table_name= (char*) "procs_priv";
+ tables->next_local= tables->next_global= tables+1;
+ (tables+1)->next_local= (tables+1)->next_global= tables+2;
+ (tables+2)->next_local= (tables+2)->next_global= tables+3;
+ (tables+3)->next_local= (tables+3)->next_global= tables+4;
tables->lock_type= (tables+1)->lock_type=
- (tables+2)->lock_type= (tables+3)->lock_type= TL_WRITE;
- tables->db= (tables+1)->db= (tables+2)->db= (tables+3)->db=(char*) "mysql";
+ (tables+2)->lock_type= (tables+3)->lock_type=
+ (tables+4)->lock_type= TL_WRITE;
+ tables->db= (tables+1)->db= (tables+2)->db=
+ (tables+3)->db= (tables+4)->db= (char*) "mysql";
#ifdef HAVE_REPLICATION
/*
@@ -3571,10 +4455,12 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
The tables must be marked "updating" so that tables_ok() takes them into
account in tests.
*/
- tables[0].updating=tables[1].updating=tables[2].updating=tables[3].updating=1;
- if (!tables_ok(0, tables))
+ tables[0].updating=tables[1].updating=tables[2].updating=
+ tables[3].updating=tables[4].updating=1;
+ if (!tables_ok(thd, tables))
DBUG_RETURN(1);
- tables[0].updating=tables[1].updating=tables[2].updating=tables[3].updating=0;
+ tables[0].updating=tables[1].updating=tables[2].updating=
+ tables[3].updating=tables[4].updating=0;;
}
#endif
@@ -3613,111 +4499,561 @@ ACL_USER *check_acl_user(LEX_USER *user_name,
}
-int mysql_drop_user(THD *thd, List <LEX_USER> &list)
+/*
+ Modify a privilege table.
+
+ SYNOPSIS
+ modify_grant_table()
+ table The table to modify.
+ host_field The host name field.
+ user_field The user name field.
+ user_to The new name for the user if to be renamed,
+ NULL otherwise.
+
+ DESCRIPTION
+ Update user/host in the current record if user_to is not NULL.
+ Delete the current record if user_to is NULL.
+
+ RETURN
+ 0 OK.
+ != 0 Error.
+*/
+
+static int modify_grant_table(TABLE *table, Field *host_field,
+ Field *user_field, LEX_USER *user_to)
{
- uint counter, acl_userd;
- int result;
- ACL_USER *acl_user;
- ACL_DB *acl_db;
- TABLE_LIST tables[4];
+ int error;
+ DBUG_ENTER("modify_grant_table");
- DBUG_ENTER("mysql_drop_user");
+ if (user_to)
+ {
+ /* rename */
+ store_record(table, record[1]);
+ host_field->store(user_to->host.str, user_to->host.length,
+ system_charset_info);
+ user_field->store(user_to->user.str, user_to->user.length,
+ system_charset_info);
+ if ((error= table->file->update_row(table->record[1], table->record[0])))
+ table->file->print_error(error, MYF(0));
+ }
+ else
+ {
+ /* delete */
+ if ((error=table->file->delete_row(table->record[0])))
+ table->file->print_error(error, MYF(0));
+ }
- if ((result= open_grant_tables(thd, tables)))
- DBUG_RETURN(result == 1 ? 0 : 1);
+ DBUG_RETURN(error);
+}
- rw_wrlock(&LOCK_grant);
- VOID(pthread_mutex_lock(&acl_cache->lock));
- LEX_USER *user_name;
- List_iterator <LEX_USER> user_list(list);
- while ((user_name=user_list++))
+/*
+ Handle a privilege table.
+
+ SYNOPSIS
+ handle_grant_table()
+ tables The array with the four open tables.
+ table_no The number of the table to handle (0..4).
+ drop If user_from is to be dropped.
+ user_from The the user to be searched/dropped/renamed.
+ user_to The new name for the user if to be renamed,
+ NULL otherwise.
+
+ DESCRIPTION
+ Scan through all records in a grant table and apply the requested
+ operation. For the "user" table, a single index access is sufficient,
+ since there is an unique index on (host, user).
+ Delete from grant table if drop is true.
+ Update in grant table if drop is false and user_to is not NULL.
+ Search in grant table if drop is false and user_to is NULL.
+ Tables are numbered as follows:
+ 0 user
+ 1 db
+ 2 tables_priv
+ 3 columns_priv
+ 4 procs_priv
+
+ RETURN
+ > 0 At least one record matched.
+ 0 OK, but no record matched.
+ < 0 Error.
+*/
+
+static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
+ LEX_USER *user_from, LEX_USER *user_to)
+{
+ int result= 0;
+ int error;
+ TABLE *table= tables[table_no].table;
+ Field *host_field= table->field[0];
+ Field *user_field= table->field[table_no ? 2 : 1];
+ char *host_str= user_from->host.str;
+ char *user_str= user_from->user.str;
+ const char *host;
+ const char *user;
+ byte user_key[MAX_KEY_LENGTH];
+ uint key_prefix_length;
+ DBUG_ENTER("handle_grant_table");
+
+ if (! table_no) // mysql.user table
{
- if (!(acl_user= check_acl_user(user_name, &counter)))
+ /*
+ The 'user' table has an unique index on (host, user).
+ Thus, we can handle everything with a single index access.
+ The host- and user fields are consecutive in the user table records.
+ So we set host- and user fields of table->record[0] and use the
+ pointer to the host field as key.
+ index_read_idx() will replace table->record[0] (its first argument)
+ by the searched record, if it exists.
+ */
+ DBUG_PRINT("info",("read table: '%s' search: '%s'@'%s'",
+ table->s->table_name, user_str, host_str));
+ host_field->store(host_str, user_from->host.length, system_charset_info);
+ user_field->store(user_str, user_from->user.length, system_charset_info);
+
+ key_prefix_length= (table->key_info->key_part[0].store_length +
+ table->key_info->key_part[1].store_length);
+ key_copy(user_key, table->record[0], table->key_info, key_prefix_length);
+
+ if ((error= table->file->index_read_idx(table->record[0], 0,
+ user_key, key_prefix_length,
+ HA_READ_KEY_EXACT)))
{
- sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; No such user",
- user_name->user.str,
- user_name->host.str);
- result= -1;
- continue;
+ if (error != HA_ERR_KEY_NOT_FOUND)
+ {
+ table->file->print_error(error, MYF(0));
+ result= -1;
+ }
}
- if ((acl_user->access & ~0))
+ else
{
- sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Global privileges exists",
- user_name->user.str,
- user_name->host.str);
+ /* If requested, delete or update the record. */
+ result= ((drop || user_to) &&
+ modify_grant_table(table, host_field, user_field, user_to)) ?
+ -1 : 1; /* Error or found. */
+ }
+ DBUG_PRINT("info",("read result: %d", result));
+ }
+ else
+ {
+ /*
+ The non-'user' table do not have indexes on (host, user).
+ And their host- and user fields are not consecutive.
+ Thus, we need to do a table scan to find all matching records.
+ */
+ if ((error= table->file->ha_rnd_init(1)))
+ {
+ table->file->print_error(error, MYF(0));
result= -1;
- continue;
}
- acl_userd= counter;
-
- for (counter= 0 ; counter < acl_dbs.elements ; counter++)
+ else
{
- const char *user,*host;
- acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*);
- if (!(user= acl_db->user))
- user= "";
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("info",("scan table: '%s' search: '%s'@'%s'",
+ table->s->table_name, user_str, host_str));
+#endif
+ while ((error= table->file->rnd_next(table->record[0])) !=
+ HA_ERR_END_OF_FILE)
+ {
+ if (error)
+ {
+ /* Most probable 'deleted record'. */
+ DBUG_PRINT("info",("scan error: %d", error));
+ continue;
+ }
+ if (! (host= get_field(&mem, host_field)))
+ host= "";
+ if (! (user= get_field(&mem, user_field)))
+ user= "";
+
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("loop",("scan fields: '%s'@'%s' '%s' '%s' '%s'",
+ user, host,
+ get_field(&mem, table->field[1]) /*db*/,
+ get_field(&mem, table->field[3]) /*table*/,
+ get_field(&mem, table->field[4]) /*column*/));
+#endif
+ if (strcmp(user_str, user) ||
+ my_strcasecmp(system_charset_info, host_str, host))
+ continue;
+
+ /* If requested, delete or update the record. */
+ result= ((drop || user_to) &&
+ modify_grant_table(table, host_field, user_field, user_to)) ?
+ -1 : result ? result : 1; /* Error or keep result or found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ break ;
+ }
+ (void) table->file->ha_rnd_end();
+ DBUG_PRINT("info",("scan result: %d", result));
+ }
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Handle an in-memory privilege structure.
+
+ SYNOPSIS
+ handle_grant_struct()
+ struct_no The number of the structure to handle (0..3).
+ drop If user_from is to be dropped.
+ user_from The the user to be searched/dropped/renamed.
+ user_to The new name for the user if to be renamed,
+ NULL otherwise.
+
+ DESCRIPTION
+ Scan through all elements in an in-memory grant structure and apply
+ the requested operation.
+ Delete from grant structure if drop is true.
+ Update in grant structure if drop is false and user_to is not NULL.
+ Search in grant structure if drop is false and user_to is NULL.
+ Structures are numbered as follows:
+ 0 acl_users
+ 1 acl_dbs
+ 2 column_priv_hash
+ 3 procs_priv_hash
+
+ RETURN
+ > 0 At least one element matched.
+ 0 OK, but no element matched.
+ -1 Wrong arguments to function
+*/
+
+static int handle_grant_struct(uint struct_no, bool drop,
+ LEX_USER *user_from, LEX_USER *user_to)
+{
+ int result= 0;
+ uint idx;
+ uint elements;
+ const char *user;
+ const char *host;
+ ACL_USER *acl_user;
+ ACL_DB *acl_db;
+ GRANT_NAME *grant_name;
+ DBUG_ENTER("handle_grant_struct");
+ DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'",
+ struct_no, user_from->user.str, user_from->host.str));
+
+ LINT_INIT(acl_user);
+ LINT_INIT(acl_db);
+ LINT_INIT(grant_name);
+
+ /* Get the number of elements in the in-memory structure. */
+ switch (struct_no) {
+ case 0:
+ elements= acl_users.elements;
+ break;
+ case 1:
+ elements= acl_dbs.elements;
+ break;
+ case 2:
+ elements= column_priv_hash.records;
+ break;
+ case 3:
+ elements= proc_priv_hash.records;
+ break;
+ default:
+ return -1;
+ }
+
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'",
+ struct_no, user_from->user.str, user_from->host.str));
+#endif
+ /* Loop over all elements. */
+ for (idx= 0; idx < elements; idx++)
+ {
+ /*
+ Get a pointer to the element.
+ Unfortunaltely, the host default differs for the structures.
+ */
+ switch (struct_no) {
+ case 0:
+ acl_user= dynamic_element(&acl_users, idx, ACL_USER*);
+ user= acl_user->user;
+ if (!(host= acl_user->host.hostname))
+ host= "%";
+ break;
+
+ case 1:
+ acl_db= dynamic_element(&acl_dbs, idx, ACL_DB*);
+ user= acl_db->user;
if (!(host= acl_db->host.hostname))
- host= "";
+ host= "%";
+ break;
+
+ case 2:
+ grant_name= (GRANT_NAME*) hash_element(&column_priv_hash, idx);
+ user= grant_name->user;
+ if (!(host= grant_name->host.hostname))
+ host= "%";
+ break;
+
+ case 3:
+ grant_name= (GRANT_NAME*) hash_element(&proc_priv_hash, idx);
+ user= grant_name->user;
+ if (!(host= grant_name->host.hostname))
+ host= "%";
+ break;
+ }
+ if (! user)
+ user= "";
+ if (! host)
+ host= "";
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'",
+ struct_no, idx, user, host));
+#endif
+ if (strcmp(user_from->user.str, user) ||
+ my_strcasecmp(system_charset_info, user_from->host.str, host))
+ continue;
+
+ result= 1; /* At least one element found. */
+ if ( drop )
+ {
+ switch ( struct_no )
+ {
+ case 0:
+ delete_dynamic_element(&acl_users, idx);
+ break;
+
+ case 1:
+ delete_dynamic_element(&acl_dbs, idx);
+ break;
+
+ case 2:
+ hash_delete(&column_priv_hash, (byte*) grant_name);
+ break;
- if (!strcmp(user_name->user.str,user) &&
- !my_strcasecmp(system_charset_info, user_name->host.str, host))
+ case 3:
+ hash_delete(&proc_priv_hash, (byte*) grant_name);
break;
+ }
+ elements--;
+ idx--;
}
- if (counter != acl_dbs.elements)
+ else if ( user_to )
{
- sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Database privileges exists",
- user_name->user.str,
- user_name->host.str);
- result= -1;
- continue;
+ switch ( struct_no ) {
+ case 0:
+ acl_user->user= strdup_root(&mem, user_to->user.str);
+ acl_user->host.hostname= strdup_root(&mem, user_to->host.str);
+ break;
+
+ case 1:
+ acl_db->user= strdup_root(&mem, user_to->user.str);
+ acl_db->host.hostname= strdup_root(&mem, user_to->host.str);
+ break;
+
+ case 2:
+ case 3:
+ grant_name->user= strdup_root(&mem, user_to->user.str);
+ update_hostname(&grant_name->host,
+ strdup_root(&mem, user_to->host.str));
+ break;
+ }
}
+ else
+ {
+ /* If search is requested, we do not need to search further. */
+ break;
+ }
+ }
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("loop",("scan struct: %u result %d", struct_no, result));
+#endif
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Handle all privilege tables and in-memory privilege structures.
+
+ SYNOPSIS
+ handle_grant_data()
+ tables The array with the four open tables.
+ drop If user_from is to be dropped.
+ user_from The the user to be searched/dropped/renamed.
+ user_to The new name for the user if to be renamed,
+ NULL otherwise.
+
+ DESCRIPTION
+ Go through all grant tables and in-memory grant structures and apply
+ the requested operation.
+ Delete from grant data if drop is true.
+ Update in grant data if drop is false and user_to is not NULL.
+ Search in grant data if drop is false and user_to is NULL.
+
+ RETURN
+ > 0 At least one element matched.
+ 0 OK, but no element matched.
+ < 0 Error.
+*/
- for (counter= 0 ; counter < column_priv_hash.records ; counter++)
+static int handle_grant_data(TABLE_LIST *tables, bool drop,
+ LEX_USER *user_from, LEX_USER *user_to)
+{
+ int result= 0;
+ int found;
+ DBUG_ENTER("handle_grant_data");
+
+ /* Handle user table. */
+ if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0)
+ {
+ /* Handle of table failed, don't touch the in-memory array. */
+ result= -1;
+ }
+ else
+ {
+ /* Handle user array. */
+ if ((handle_grant_struct(0, drop, user_from, user_to) && ! result) ||
+ found)
{
- const char *user,*host;
- GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
- counter);
- if (!(user=grant_table->user))
- user= "";
- if (!(host=grant_table->host.hostname))
- host= "";
+ result= 1; /* At least one record/element found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ goto end;
+ }
+ }
- if (!strcmp(user_name->user.str,user) &&
- !my_strcasecmp(system_charset_info, user_name->host.str, host))
- break;
+ /* Handle db table. */
+ if ((found= handle_grant_table(tables, 1, drop, user_from, user_to)) < 0)
+ {
+ /* Handle of table failed, don't touch the in-memory array. */
+ result= -1;
+ }
+ else
+ {
+ /* Handle db array. */
+ if (((handle_grant_struct(1, drop, user_from, user_to) && ! result) ||
+ found) && ! result)
+ {
+ result= 1; /* At least one record/element found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ goto end;
}
- if (counter != column_priv_hash.records)
+ }
+
+ /* Handle procedures table. */
+ if ((found= handle_grant_table(tables, 4, drop, user_from, user_to)) < 0)
+ {
+ /* Handle of table failed, don't touch in-memory array. */
+ result= -1;
+ }
+ else
+ {
+ /* Handle procs array. */
+ if (((handle_grant_struct(3, drop, user_from, user_to) && ! result) ||
+ found) && ! result)
+ {
+ result= 1; /* At least one record/element found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ goto end;
+ }
+ }
+
+ /* Handle tables table. */
+ if ((found= handle_grant_table(tables, 2, drop, user_from, user_to)) < 0)
+ {
+ /* Handle of table failed, don't touch columns and in-memory array. */
+ result= -1;
+ }
+ else
+ {
+ if (found && ! result)
{
- sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Table privileges exists",
- user_name->user.str,
- user_name->host.str);
+ result= 1; /* At least one record found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ goto end;
+ }
+
+ /* Handle columns table. */
+ if ((found= handle_grant_table(tables, 3, drop, user_from, user_to)) < 0)
+ {
+ /* Handle of table failed, don't touch the in-memory array. */
result= -1;
+ }
+ else
+ {
+ /* Handle columns hash. */
+ if (((handle_grant_struct(2, drop, user_from, user_to) && ! result) ||
+ found) && ! result)
+ result= 1; /* At least one record/element found. */
+ }
+ }
+ end:
+ DBUG_RETURN(result);
+}
+
+
+static void append_user(String *str, LEX_USER *user)
+{
+ if (str->length())
+ str->append(',');
+ str->append('\'');
+ str->append(user->user.str);
+ str->append("'@'");
+ str->append(user->host.str);
+ str->append('\'');
+}
+
+
+/*
+ Create a list of users.
+
+ SYNOPSIS
+ mysql_create_user()
+ thd The current thread.
+ list The users to create.
+
+ RETURN
+ FALSE OK.
+ TRUE Error.
+*/
+
+bool mysql_create_user(THD *thd, List <LEX_USER> &list)
+{
+ int result;
+ String wrong_users;
+ ulong sql_mode;
+ LEX_USER *user_name;
+ List_iterator <LEX_USER> user_list(list);
+ TABLE_LIST tables[GRANT_TABLES];
+ DBUG_ENTER("mysql_create_user");
+
+ /* CREATE USER may be skipped on replication client. */
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result != 1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ while ((user_name= user_list++))
+ {
+ /*
+ Search all in-memory structures and grant tables
+ for a mention of the new user name.
+ */
+ if (handle_grant_data(tables, 0, user_name, NULL))
+ {
+ append_user(&wrong_users, user_name);
+ result= TRUE;
continue;
}
- tables[0].table->field[0]->store(user_name->host.str,(uint)
- user_name->host.length,
- system_charset_info);
- tables[0].table->field[1]->store(user_name->user.str,(uint)
- user_name->user.length,
- system_charset_info);
- tables[0].table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- if (!tables[0].table->file->index_read_idx(tables[0].table->record[0],0,
- (byte*) tables[0].table->
- field[0]->ptr,
- tables[0].table->
- key_info[0].key_length,
- HA_READ_KEY_EXACT))
+ sql_mode= thd->variables.sql_mode;
+ if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0))
{
- int error;
- if ((error = tables[0].table->file->delete_row(tables[0].table->
- record[0])))
- {
- tables[0].table->file->print_error(error, MYF(0));
- DBUG_RETURN(-1);
- }
- delete_dynamic_element(&acl_users, acl_userd);
+ append_user(&wrong_users, user_name);
+ result= TRUE;
}
}
@@ -3725,20 +5061,138 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list)
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
- my_error(ER_DROP_USER, MYF(0));
+ my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe());
DBUG_RETURN(result);
}
-int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
+
+/*
+ Drop a list of users and all their privileges.
+
+ SYNOPSIS
+ mysql_drop_user()
+ thd The current thread.
+ list The users to drop.
+
+ RETURN
+ FALSE OK.
+ TRUE Error.
+*/
+
+bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
{
- uint counter, revoked;
+ int result;
+ String wrong_users;
+ LEX_USER *user_name;
+ List_iterator <LEX_USER> user_list(list);
+ TABLE_LIST tables[GRANT_TABLES];
+ DBUG_ENTER("mysql_drop_user");
+
+ /* DROP USER may be skipped on replication client. */
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result != 1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ while ((user_name= user_list++))
+ {
+ if (handle_grant_data(tables, 1, user_name, NULL) <= 0)
+ {
+ append_user(&wrong_users, user_name);
+ result= TRUE;
+ }
+ }
+
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+ close_thread_tables(thd);
+ if (result)
+ my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe());
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Rename a user.
+
+ SYNOPSIS
+ mysql_rename_user()
+ thd The current thread.
+ list The user name pairs: (from, to).
+
+ RETURN
+ FALSE OK.
+ TRUE Error.
+*/
+
+bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
+{
+ int result= 0;
+ String wrong_users;
+ LEX_USER *user_from;
+ LEX_USER *user_to;
+ List_iterator <LEX_USER> user_list(list);
+ TABLE_LIST tables[GRANT_TABLES];
+ DBUG_ENTER("mysql_rename_user");
+
+ /* RENAME USER may be skipped on replication client. */
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result != 1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ while ((user_from= user_list++))
+ {
+ user_to= user_list++;
+ DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */
+
+ /*
+ Search all in-memory structures and grant tables
+ for a mention of the new user name.
+ */
+ if (handle_grant_data(tables, 0, user_to, NULL) ||
+ handle_grant_data(tables, 0, user_from, user_to) <= 0)
+ {
+ append_user(&wrong_users, user_from);
+ result= TRUE;
+ }
+ }
+
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+ close_thread_tables(thd);
+ if (result)
+ my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe());
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Revoke all privileges from a list of users.
+
+ SYNOPSIS
+ mysql_revoke_all()
+ thd The current thread.
+ list The users to revoke all privileges from.
+
+ RETURN
+ > 0 Error. Error message already sent.
+ 0 OK.
+ < 0 Error. Error message not yet sent.
+*/
+
+bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
+{
+ uint counter, revoked, is_proc;
int result;
ACL_DB *acl_db;
- TABLE_LIST tables[4];
+ TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_revoke_all");
if ((result= open_grant_tables(thd, tables)))
- DBUG_RETURN(result == 1 ? 0 : 1);
+ DBUG_RETURN(result != 1);
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -3749,15 +5203,14 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
{
if (!check_acl_user(lex_user, &counter))
{
- sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' not exists",
- lex_user->user.str,
- lex_user->host.str);
+ sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not "
+ "exists", lex_user->user.str, lex_user->host.str);
result= -1;
continue;
}
if (replace_user_table(thd, tables[0].table,
- *lex_user, ~(ulong)0, 1, 0))
+ *lex_user, ~(ulong)0, 1, 0, 0))
{
result= -1;
continue;
@@ -3774,13 +5227,13 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
for (counter= 0, revoked= 0 ; counter < acl_dbs.elements ; )
{
const char *user,*host;
-
+
acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*);
if (!(user=acl_db->user))
user= "";
if (!(host=acl_db->host.hostname))
host= "";
-
+
if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host))
{
@@ -3811,7 +5264,7 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
user= "";
if (!(host=grant_table->host.hostname))
host= "";
-
+
if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host))
{
@@ -3845,15 +5298,173 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
counter++;
}
} while (revoked);
+
+ /* Remove procedure access */
+ for (is_proc=0; is_proc<2; is_proc++) do {
+ HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash;
+ for (counter= 0, revoked= 0 ; counter < hash->records ; )
+ {
+ const char *user,*host;
+ GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter);
+ if (!(user=grant_proc->user))
+ user= "";
+ if (!(host=grant_proc->host.hostname))
+ host= "";
+
+ if (!strcmp(lex_user->user.str,user) &&
+ !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ {
+ if (!replace_routine_table(thd,grant_proc,tables[4].table,*lex_user,
+ grant_proc->db,
+ grant_proc->tname,
+ is_proc,
+ ~(ulong)0, 1))
+ {
+ revoked= 1;
+ continue;
+ }
+ result= -1; // Something went wrong
+ }
+ counter++;
+ }
+ } while (revoked);
}
-
+
VOID(pthread_mutex_unlock(&acl_cache->lock));
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
-
+
if (result)
- my_error(ER_REVOKE_GRANTS, MYF(0));
+ my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0));
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Revoke privileges for all users on a stored procedure
+
+ SYNOPSIS
+ sp_revoke_privileges()
+ thd The current thread.
+ db DB of the stored procedure
+ name Name of the stored procedure
+
+ RETURN
+ 0 OK.
+ < 0 Error. Error message not yet sent.
+*/
+
+bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
+ bool is_proc)
+{
+ uint counter, revoked;
+ int result;
+ TABLE_LIST tables[GRANT_TABLES];
+ HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash;
+ DBUG_ENTER("sp_revoke_privileges");
+
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result != 1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ /* Remove procedure access */
+ do
+ {
+ for (counter= 0, revoked= 0 ; counter < hash->records ; )
+ {
+ GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter);
+ if (!my_strcasecmp(system_charset_info, grant_proc->db, sp_db) &&
+ !my_strcasecmp(system_charset_info, grant_proc->tname, sp_name))
+ {
+ LEX_USER lex_user;
+ lex_user.user.str= grant_proc->user;
+ lex_user.user.length= strlen(grant_proc->user);
+ lex_user.host.str= grant_proc->host.hostname;
+ lex_user.host.length= strlen(grant_proc->host.hostname);
+ if (!replace_routine_table(thd,grant_proc,tables[4].table,lex_user,
+ grant_proc->db, grant_proc->tname,
+ is_proc, ~(ulong)0, 1))
+ {
+ revoked= 1;
+ continue;
+ }
+ result= -1; // Something went wrong
+ }
+ counter++;
+ }
+ } while (revoked);
+
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+ close_thread_tables(thd);
+
+ if (result)
+ my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0));
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Grant EXECUTE,ALTER privilege for a stored procedure
+
+ SYNOPSIS
+ sp_grant_privileges()
+ thd The current thread.
+ db DB of the stored procedure
+ name Name of the stored procedure
+
+ RETURN
+ 0 OK.
+ < 0 Error. Error message not yet sent.
+*/
+
+bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
+ bool is_proc)
+{
+ LEX_USER *combo;
+ TABLE_LIST tables[1];
+ List<LEX_USER> user_list;
+ bool result;
+ DBUG_ENTER("sp_grant_privileges");
+
+ if (!(combo=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ DBUG_RETURN(TRUE);
+
+ combo->user.str= thd->user;
+ if (!find_acl_user(combo->host.str=(char*)thd->host_or_ip, combo->user.str,
+ FALSE) &&
+ !find_acl_user(combo->host.str=(char*)thd->host, combo->user.str,
+ FALSE) &&
+ !find_acl_user(combo->host.str=(char*)thd->ip, combo->user.str, FALSE) &&
+ !find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE))
+ DBUG_RETURN(TRUE);
+
+ bzero((char*)tables, sizeof(TABLE_LIST));
+ user_list.empty();
+
+ tables->db= (char*)sp_db;
+ tables->table_name= tables->alias= (char*)sp_name;
+
+ combo->host.length= strlen(combo->host.str);
+ combo->user.length= strlen(combo->user.str);
+ combo->host.str= thd->strmake(combo->host.str,combo->host.length);
+ combo->user.str= thd->strmake(combo->user.str,combo->user.length);
+ combo->password.str= (char*)"";
+ combo->password.length= 0;
+
+ if (user_list.push_back(combo))
+ DBUG_RETURN(TRUE);
+
+ thd->lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
+ bzero((char*) &thd->lex->mqh, sizeof(thd->lex->mqh));
+
+ result= mysql_routine_grant(thd, tables, is_proc, user_list,
+ DEFAULT_CREATE_PROC_ACLS, 0, 1);
DBUG_RETURN(result);
}
@@ -3862,7 +5473,7 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
Instantiate used templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List_iterator<LEX_COLUMN>;
template class List_iterator<LEX_USER>;
template class List<LEX_COLUMN>;
@@ -3915,3 +5526,329 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
DBUG_RETURN (*str != '\0');
}
+
+void update_schema_privilege(TABLE *table, char *buff, const char* db,
+ const char* t_name, const char* column,
+ uint col_length, const char *priv,
+ uint priv_length, const char* is_grantable)
+{
+ int i= 2;
+ CHARSET_INFO *cs= system_charset_info;
+ restore_record(table, s->default_values);
+ table->field[0]->store(buff, strlen(buff), cs);
+ if (db)
+ table->field[i++]->store(db, strlen(db), cs);
+ if (t_name)
+ table->field[i++]->store(t_name, strlen(t_name), cs);
+ if (column)
+ table->field[i++]->store(column, col_length, cs);
+ table->field[i++]->store(priv, priv_length, cs);
+ table->field[i]->store(is_grantable, strlen(is_grantable), cs);
+ table->file->write_row(table->record[0]);
+}
+
+
+int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint counter;
+ ACL_USER *acl_user;
+ ulong want_access;
+ char buff[100];
+ TABLE *table= tables->table;
+ bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0);
+ char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%";
+ DBUG_ENTER("fill_schema_user_privileges");
+
+ for (counter=0 ; counter < acl_users.elements ; counter++)
+ {
+ const char *user,*host, *is_grantable="YES";
+ acl_user=dynamic_element(&acl_users,counter,ACL_USER*);
+ if (!(user=acl_user->user))
+ user= "";
+ if (!(host=acl_user->host.hostname))
+ host= "";
+
+ if (no_global_access &&
+ (strcmp(thd->priv_user, user) ||
+ my_strcasecmp(system_charset_info, curr_host, host)))
+ continue;
+
+ want_access= acl_user->access;
+ if (!(want_access & GRANT_ACL))
+ is_grantable= "NO";
+
+ strxmov(buff,"'",user,"'@'",host,"'",NullS);
+ if (!(want_access & ~GRANT_ACL))
+ update_schema_privilege(table, buff, 0, 0, 0, 0, "USAGE", 5, is_grantable);
+ else
+ {
+ uint priv_id;
+ ulong j,test_access= want_access & ~GRANT_ACL;
+ for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1)
+ {
+ if (test_access & j)
+ update_schema_privilege(table, buff, 0, 0, 0, 0,
+ command_array[priv_id],
+ command_lengths[priv_id], is_grantable);
+ }
+ }
+ }
+ DBUG_RETURN(0);
+#else
+ return(0);
+#endif
+}
+
+
+int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint counter;
+ ACL_DB *acl_db;
+ ulong want_access;
+ char buff[100];
+ TABLE *table= tables->table;
+ bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0);
+ char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%";
+ DBUG_ENTER("fill_schema_schema_privileges");
+
+ for (counter=0 ; counter < acl_dbs.elements ; counter++)
+ {
+ const char *user, *host, *is_grantable="YES";
+
+ acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*);
+ if (!(user=acl_db->user))
+ user= "";
+ if (!(host=acl_db->host.hostname))
+ host= "";
+
+ if (no_global_access &&
+ (strcmp(thd->priv_user, user) ||
+ my_strcasecmp(system_charset_info, curr_host, host)))
+ continue;
+
+ want_access=acl_db->access;
+ if (want_access)
+ {
+ if (!(want_access & GRANT_ACL))
+ {
+ is_grantable= "NO";
+ }
+ strxmov(buff,"'",user,"'@'",host,"'",NullS);
+ if (!(want_access & ~GRANT_ACL))
+ update_schema_privilege(table, buff, acl_db->db, 0, 0,
+ 0, "USAGE", 5, is_grantable);
+ else
+ {
+ int cnt;
+ ulong j,test_access= want_access & ~GRANT_ACL;
+ for (cnt=0, j = SELECT_ACL; j <= DB_ACLS; cnt++,j <<= 1)
+ if (test_access & j)
+ update_schema_privilege(table, buff, acl_db->db, 0, 0, 0,
+ command_array[cnt], command_lengths[cnt],
+ is_grantable);
+ }
+ }
+ }
+ DBUG_RETURN(0);
+#else
+ return (0);
+#endif
+}
+
+
+int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint index;
+ char buff[100];
+ TABLE *table= tables->table;
+ bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0);
+ char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%";
+ DBUG_ENTER("fill_schema_table_privileges");
+
+ for (index=0 ; index < column_priv_hash.records ; index++)
+ {
+ const char *user, *is_grantable= "YES";
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ index);
+ if (!(user=grant_table->user))
+ user= "";
+
+ if (no_global_access &&
+ (strcmp(thd->priv_user, user) ||
+ my_strcasecmp(system_charset_info, curr_host,
+ grant_table->host.hostname)))
+ continue;
+
+ ulong table_access= grant_table->privs;
+ if (table_access)
+ {
+ ulong test_access= table_access & ~GRANT_ACL;
+ /*
+ We should skip 'usage' privilege on table if
+ we have any privileges on column(s) of this table
+ */
+ if (!test_access && grant_table->cols)
+ continue;
+ if (!(table_access & GRANT_ACL))
+ is_grantable= "NO";
+
+ strxmov(buff,"'",user,"'@'",grant_table->host.hostname,"'",NullS);
+ if (!test_access)
+ update_schema_privilege(table, buff, grant_table->db, grant_table->tname,
+ 0, 0, "USAGE", 5, is_grantable);
+ else
+ {
+ ulong j;
+ int cnt;
+ for (cnt= 0, j= SELECT_ACL; j <= TABLE_ACLS; cnt++, j<<= 1)
+ {
+ if (test_access & j)
+ update_schema_privilege(table, buff, grant_table->db,
+ grant_table->tname, 0, 0, command_array[cnt],
+ command_lengths[cnt], is_grantable);
+ }
+ }
+ }
+ }
+ DBUG_RETURN(0);
+#else
+ return (0);
+#endif
+}
+
+
+int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint index;
+ char buff[100];
+ TABLE *table= tables->table;
+ bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0);
+ char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%";
+ DBUG_ENTER("fill_schema_table_privileges");
+
+ for (index=0 ; index < column_priv_hash.records ; index++)
+ {
+ const char *user, *is_grantable= "YES";
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ index);
+ if (!(user=grant_table->user))
+ user= "";
+
+ if (no_global_access &&
+ (strcmp(thd->priv_user, user) ||
+ my_strcasecmp(system_charset_info, curr_host,
+ grant_table->host.hostname)))
+ continue;
+
+ ulong table_access= grant_table->cols;
+ if (table_access != 0)
+ {
+ if (!(grant_table->privs & GRANT_ACL))
+ is_grantable= "NO";
+
+ ulong test_access= table_access & ~GRANT_ACL;
+ strxmov(buff,"'",user,"'@'",grant_table->host.hostname,"'",NullS);
+ if (!test_access)
+ continue;
+ else
+ {
+ ulong j;
+ int cnt;
+ for (cnt= 0, j= SELECT_ACL; j <= TABLE_ACLS; cnt++, j<<= 1)
+ {
+ if (test_access & j)
+ {
+ for (uint col_index=0 ;
+ col_index < grant_table->hash_columns.records ;
+ col_index++)
+ {
+ GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
+ hash_element(&grant_table->hash_columns,col_index);
+ if ((grant_column->rights & j) && (table_access & j))
+ update_schema_privilege(table, buff, grant_table->db,
+ grant_table->tname,
+ grant_column->column,
+ grant_column->key_length,
+ command_array[cnt],
+ command_lengths[cnt], is_grantable);
+ }
+ }
+ }
+ }
+ }
+ }
+ DBUG_RETURN(0);
+#else
+ return (0);
+#endif
+}
+
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+/*
+ fill effective privileges for table
+
+ SYNOPSIS
+ fill_effective_table_privileges()
+ thd thread handler
+ grant grants table descriptor
+ db db name
+ table table name
+*/
+
+void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
+ const char *db, const char *table)
+{
+ /* --skip-grants */
+ if (!initialized)
+ {
+ grant->privilege= ~NO_ACCESS; // everything is allowed
+ return;
+ }
+
+ /* global privileges */
+ grant->privilege= thd->master_access;
+
+ if (!thd->priv_user)
+ return; // it is slave
+
+ /* db privileges */
+ grant->privilege|= acl_get(thd->host, thd->ip, thd->priv_user, db, 0);
+
+ if (!grant_option)
+ return;
+
+ /* table privileges */
+ if (grant->version != grant_version)
+ {
+ rw_rdlock(&LOCK_grant);
+ grant->grant_table=
+ table_hash_search(thd->host, thd->ip, db,
+ thd->priv_user,
+ table, 0); /* purecov: inspected */
+ grant->version= grant_version; /* purecov: inspected */
+ rw_unlock(&LOCK_grant);
+ }
+ if (grant->grant_table != 0)
+ {
+ grant->privilege|= grant->grant_table->privs;
+ }
+}
+
+#else /* NO_EMBEDDED_ACCESS_CHECKS */
+
+/****************************************************************************
+ Dummy wrappers when we don't have any access checks
+****************************************************************************/
+
+bool check_routine_level_acl(THD *thd, const char *db, const char *name,
+ bool is_proc)
+{
+ return FALSE;
+}
+
+#endif
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 256101ec7d8..344302de9be 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -35,54 +35,94 @@
#define EXECUTE_ACL (1L << 18)
#define REPL_SLAVE_ACL (1L << 19)
#define REPL_CLIENT_ACL (1L << 20)
-
+#define CREATE_VIEW_ACL (1L << 21)
+#define SHOW_VIEW_ACL (1L << 22)
+#define CREATE_PROC_ACL (1L << 23)
+#define ALTER_PROC_ACL (1L << 24)
+#define CREATE_USER_ACL (1L << 25)
/*
don't forget to update
- static struct show_privileges_st sys_privileges[]
- in sql_show.cc when adding new privileges!
+ 1. static struct show_privileges_st sys_privileges[]
+ 2. static const char *command_array[] and static uint command_lengths[]
+ 3. mysql_create_system_tables.sh, mysql_fix_privilege_tables.sql
+ 4. acl_init() or whatever - to define behaviour for old privilege tables
+ 5. sql_yacc.yy - for GRANT/REVOKE to work
*/
-
+#define EXTRA_ACL (1L << 29)
+#define NO_ACCESS (1L << 30)
#define DB_ACLS \
(UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
- GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL | LOCK_TABLES_ACL)
+ GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL | \
+ LOCK_TABLES_ACL | EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | \
+ CREATE_PROC_ACL | ALTER_PROC_ACL)
#define TABLE_ACLS \
(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
- GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL)
+ GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_VIEW_ACL | \
+ SHOW_VIEW_ACL)
#define COL_ACLS \
(SELECT_ACL | INSERT_ACL | UPDATE_ACL | REFERENCES_ACL)
+#define PROC_ACLS \
+(ALTER_PROC_ACL | EXECUTE_ACL | GRANT_ACL)
+
+#define SHOW_PROC_ACLS \
+(ALTER_PROC_ACL | EXECUTE_ACL | CREATE_PROC_ACL)
+
#define GLOBAL_ACLS \
(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL | GRANT_ACL | \
REFERENCES_ACL | INDEX_ACL | ALTER_ACL | SHOW_DB_ACL | SUPER_ACL | \
CREATE_TMP_ACL | LOCK_TABLES_ACL | REPL_SLAVE_ACL | REPL_CLIENT_ACL | \
- EXECUTE_ACL)
+ EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | CREATE_PROC_ACL | \
+ ALTER_PROC_ACL | CREATE_USER_ACL)
-#define EXTRA_ACL (1L << 29)
-#define NO_ACCESS (1L << 30)
+#define DEFAULT_CREATE_PROC_ACLS \
+(ALTER_PROC_ACL | EXECUTE_ACL)
/*
Defines to change the above bits to how things are stored in tables
This is needed as the 'host' and 'db' table is missing a few privileges
*/
-/* Continius bit-segments that needs to be shifted */
-#define DB_REL1 (RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL)
-#define DB_REL2 (GRANT_ACL | REFERENCES_ACL)
-
/* Privileges that needs to be reallocated (in continous chunks) */
+#define DB_CHUNK0 (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | \
+ CREATE_ACL | DROP_ACL)
#define DB_CHUNK1 (GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL)
#define DB_CHUNK2 (CREATE_TMP_ACL | LOCK_TABLES_ACL)
-
-#define fix_rights_for_db(A) (((A) & 63) | (((A) & DB_REL1) << 4) | (((A) & DB_REL2) << 6))
-#define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6))
-#define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4))
-#define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4))
+#define DB_CHUNK3 (CREATE_VIEW_ACL | SHOW_VIEW_ACL | \
+ CREATE_PROC_ACL | ALTER_PROC_ACL )
+#define DB_CHUNK4 (EXECUTE_ACL)
+
+#define fix_rights_for_db(A) (((A) & DB_CHUNK0) | \
+ (((A) << 4) & DB_CHUNK1) | \
+ (((A) << 6) & DB_CHUNK2) | \
+ (((A) << 9) & DB_CHUNK3) | \
+ (((A) << 2) & DB_CHUNK4))
+#define get_rights_for_db(A) (((A) & DB_CHUNK0) | \
+ (((A) & DB_CHUNK1) >> 4) | \
+ (((A) & DB_CHUNK2) >> 6) | \
+ (((A) & DB_CHUNK3) >> 9) | \
+ (((A) & DB_CHUNK4) >> 2))
+#define TBL_CHUNK0 DB_CHUNK0
+#define TBL_CHUNK1 DB_CHUNK1
+#define TBL_CHUNK2 (CREATE_VIEW_ACL | SHOW_VIEW_ACL)
+#define fix_rights_for_table(A) (((A) & TBL_CHUNK0) | \
+ (((A) << 4) & TBL_CHUNK1) | \
+ (((A) << 11) & TBL_CHUNK2))
+#define get_rights_for_table(A) (((A) & TBL_CHUNK0) | \
+ (((A) & TBL_CHUNK1) >> 4) | \
+ (((A) & TBL_CHUNK2) >> 11))
#define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8))
#define get_rights_for_column(A) (((A) & 7) | ((A) >> 8))
+#define fix_rights_for_procedure(A) ((((A) << 18) & EXECUTE_ACL) | \
+ (((A) << 23) & ALTER_PROC_ACL) | \
+ (((A) << 8) & GRANT_ACL))
+#define get_rights_for_procedure(A) ((((A) & EXECUTE_ACL) >> 18) | \
+ (((A) & ALTER_PROC_ACL) >> 23) | \
+ (((A) & GRANT_ACL) >> 8))
/* Classes */
@@ -141,33 +181,55 @@ ulong acl_get(const char *host, const char *ip,
const char *user, const char *db, my_bool db_is_pattern);
int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd,
uint passwd_len);
+int acl_getroot_no_password(THD *thd);
bool acl_check_host(const char *host, const char *ip);
bool check_change_password(THD *thd, const char *host, const char *user,
char *password, uint password_len);
bool change_password(THD *thd, const char *host, const char *user,
char *password);
-int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
- ulong rights, bool revoke);
-int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
- List <LEX_COLUMN> &column_list, ulong rights,
- bool revoke);
+bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
+ ulong rights, bool revoke);
+bool mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
+ List <LEX_COLUMN> &column_list, ulong rights,
+ bool revoke);
+bool mysql_routine_grant(THD *thd, TABLE_LIST *table, bool is_proc,
+ List <LEX_USER> &user_list, ulong rights,
+ bool revoke, bool no_error);
+ACL_USER *check_acl_user(LEX_USER *user_name, uint *acl_acl_userdx);
my_bool grant_init();
void grant_free(void);
my_bool grant_reload(THD *thd);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command, uint number, bool dont_print_error);
-bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length,
- uint show_command=0);
-bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table);
+bool check_grant_column (THD *thd, GRANT_INFO *grant,
+ const char *db_name, const char *table_name,
+ const char *name, uint length, uint show_command=0);
+bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
+ const char* db_name, const char *table_name,
+ Field_iterator *fields);
+bool check_grant_routine(THD *thd, ulong want_access,
+ TABLE_LIST *procs, bool is_proc, bool no_error);
bool check_grant_db(THD *thd,const char *db);
ulong get_table_grant(THD *thd, TABLE_LIST *table);
-ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field);
-int mysql_show_grants(THD *thd, LEX_USER *user);
+ulong get_column_grant(THD *thd, GRANT_INFO *grant,
+ const char *db_name, const char *table_name,
+ const char *field_name);
+bool mysql_show_grants(THD *thd, LEX_USER *user);
void get_privilege_desc(char *to, uint max_length, ulong access);
void get_mqh(const char *user, const char *host, USER_CONN *uc);
-int mysql_drop_user(THD *thd, List <LEX_USER> &list);
-int mysql_revoke_all(THD *thd, List <LEX_USER> &list);
-
+bool mysql_create_user(THD *thd, List <LEX_USER> &list);
+bool mysql_drop_user(THD *thd, List <LEX_USER> &list);
+bool mysql_rename_user(THD *thd, List <LEX_USER> &list);
+bool mysql_revoke_all(THD *thd, List <LEX_USER> &list);
+void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
+ const char *db, const char *table);
+bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
+ bool is_proc);
+bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
+ bool is_proc);
+bool check_routine_level_acl(THD *thd, const char *db, const char *name,
+ bool is_proc);
+bool is_acl_user(const char *host, const char *user);
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define check_grant(A,B,C,D,E,F) 0
#define check_grant_db(A,B) 0
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index d2237c24139..669f998cde5 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -59,7 +59,11 @@ int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
return compare_ulonglong(s,t);
}
-static bool append_escaped(String *to_str, String *from_str);
+int compare_decimal2(int* len, const char *s, const char *t)
+{
+ return memcmp(s, t, *len);
+}
+
Procedure *
proc_analyse_init(THD *thd, ORDER *param, select_result *result,
@@ -82,7 +86,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
{
// first parameter
if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val() < 0)
+ (*param->item)->val_real() < 0)
{
my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
goto err;
@@ -96,7 +100,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
}
// second parameter
if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val() < 0)
+ (*param->item)->val_real() < 0)
{
my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
goto err;
@@ -104,7 +108,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
pc->max_treemem = (uint) (*param->item)->val_int();
}
else if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val() < 0)
+ (*param->item)->val_real() < 0)
{
my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
goto err;
@@ -129,20 +133,30 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
Item *item;
while ((item = it++))
{
- if (item->result_type() == INT_RESULT)
- {
+ field_info *new_field;
+ switch (item->result_type()) {
+ case INT_RESULT:
// Check if fieldtype is ulonglong
if (item->type() == Item::FIELD_ITEM &&
((Item_field*) item)->field->type() == FIELD_TYPE_LONGLONG &&
((Field_longlong*) ((Item_field*) item)->field)->unsigned_flag)
- *f_info++ = new field_ulonglong(item, pc);
+ new_field= new field_ulonglong(item, pc);
else
- *f_info++ = new field_longlong(item, pc);
+ new_field= new field_longlong(item, pc);
+ break;
+ case REAL_RESULT:
+ new_field= new field_real(item, pc);
+ break;
+ case DECIMAL_RESULT:
+ new_field= new field_decimal(item, pc);
+ break;
+ case STRING_RESULT:
+ new_field= new field_str(item, pc);
+ break;
+ default:
+ goto err;
}
- if (item->result_type() == REAL_RESULT)
- *f_info++ = new field_real(item, pc);
- if (item->result_type() == STRING_RESULT)
- *f_info++ = new field_str(item, pc);
+ *f_info++= new_field;
}
}
DBUG_RETURN(pc);
@@ -262,7 +276,7 @@ bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num)
}
else // ulonglong is as big as bigint in MySQL
{
- if ((check_ulonglong(num, info->integers) == REAL_NUM))
+ if ((check_ulonglong(num, info->integers) == DECIMAL_NUM))
return 0;
ev_info->ullval = (ulonglong) max(ev_info->ullval, info->ullval);
ev_info->max_dval = (double) max(ev_info->max_dval, info->dval);
@@ -370,7 +384,7 @@ void field_str::add()
void field_real::add()
{
char buff[MAX_FIELD_WIDTH], *ptr, *end;
- double num = item->val();
+ double num= item->val_real();
uint length, zero_count, decs;
TREE_ELEMENT *element;
@@ -450,6 +464,83 @@ void field_real::add()
} // field_real::add
+void field_decimal::add()
+{
+ my_decimal dec_buf, *dec= item->val_decimal(&dec_buf);
+ uint length;
+ TREE_ELEMENT *element;
+
+ if (item->null_value)
+ {
+ nulls++;
+ return;
+ }
+
+ length= my_decimal_string_length(dec);
+
+ if (decimal_is_zero(dec))
+ empty++;
+
+ if (room_in_tree)
+ {
+ char buf[DECIMAL_MAX_FIELD_SIZE];
+ my_decimal2binary(E_DEC_FATAL_ERROR, dec, buf,
+ item->max_length, item->decimals);
+ if (!(element = tree_insert(&tree, (void*)buf, 0, tree.custom_arg)))
+ {
+ room_in_tree = 0; // Remove tree, out of RAM ?
+ delete_tree(&tree);
+ }
+ /*
+ if element->count == 1, this element can be found only once from tree
+ if element->count == 2, or more, this element is already in tree
+ */
+ else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
+ {
+ room_in_tree = 0; // Remove tree, too many elements
+ delete_tree(&tree);
+ }
+ }
+
+ if (!found)
+ {
+ found = 1;
+ min_arg = max_arg = sum[0] = *dec;
+ min_arg.fix_buffer_pointer();
+ max_arg.fix_buffer_pointer();
+ sum[0].fix_buffer_pointer();
+ my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, dec, dec);
+ cur_sum= 0;
+ min_length = max_length = length;
+ }
+ else if (!decimal_is_zero(dec))
+ {
+ int next_cur_sum= cur_sum ^ 1;
+ my_decimal sqr_buf;
+
+ my_decimal_add(E_DEC_FATAL_ERROR, sum+next_cur_sum, sum+cur_sum, dec);
+ my_decimal_mul(E_DEC_FATAL_ERROR, &sqr_buf, dec, dec);
+ my_decimal_add(E_DEC_FATAL_ERROR,
+ sum_sqr+next_cur_sum, sum_sqr+cur_sum, &sqr_buf);
+ cur_sum= next_cur_sum;
+ if (length < min_length)
+ min_length = length;
+ if (length > max_length)
+ max_length = length;
+ if (my_decimal_cmp(dec, &min_arg) < 0)
+ {
+ min_arg= *dec;
+ min_arg.fix_buffer_pointer();
+ }
+ if (my_decimal_cmp(dec, &max_arg) > 0)
+ {
+ max_arg= *dec;
+ max_arg.fix_buffer_pointer();
+ }
+ }
+}
+
+
void field_longlong::add()
{
char buff[MAX_FIELD_WIDTH];
@@ -890,6 +981,72 @@ void field_ulonglong::get_opt_type(String *answer,
} //field_ulonglong::get_opt_type
+void field_decimal::get_opt_type(String *answer,
+ ha_rows total_rows __attribute__((unused)))
+{
+ my_decimal zero;
+ char buff[MAX_FIELD_WIDTH];
+ uint length;
+
+ my_decimal_set_zero(&zero);
+ my_bool is_unsigned= (my_decimal_cmp(&zero, &min_arg) >= 0);
+
+ length= my_sprintf(buff, (buff, "DECIMAL(%d, %d)",
+ (int) (max_length - (item->decimals ? 1 : 0)),
+ item->decimals));
+ if (is_unsigned)
+ length= (uint) (strmov(buff+length, " UNSIGNED")- buff);
+ answer->append(buff, length);
+}
+
+
+String *field_decimal::get_min_arg(String *str)
+{
+ my_decimal2string(E_DEC_FATAL_ERROR, &min_arg, 0, 0, '0', str);
+ return str;
+}
+
+
+String *field_decimal::get_max_arg(String *str)
+{
+ my_decimal2string(E_DEC_FATAL_ERROR, &max_arg, 0, 0, '0', str);
+ return str;
+}
+
+
+String *field_decimal::avg(String *s, ha_rows rows)
+{
+ if (!(rows - nulls))
+ {
+ s->set((double) 0.0, 1,my_thd_charset);
+ return s;
+ }
+ my_decimal num, avg_val;
+ int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num);
+ my_decimal_div(E_DEC_FATAL_ERROR, &avg_val, sum+cur_sum, &num, 0);
+ my_decimal2string(E_DEC_FATAL_ERROR, &avg_val, 0, 0, '0', s);
+ return s;
+}
+
+
+String *field_decimal::std(String *s, ha_rows rows)
+{
+ if (!(rows - nulls))
+ {
+ s->set((double) 0.0, 1,my_thd_charset);
+ return s;
+ }
+ my_decimal num, std_val, sum2, sum2d;
+ int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num);
+ my_decimal_mul(E_DEC_FATAL_ERROR, &sum2, sum+cur_sum, sum+cur_sum);
+ my_decimal_div(E_DEC_FATAL_ERROR, &std_val, &sum2, &num, 0);
+ my_decimal_sub(E_DEC_FATAL_ERROR, &sum2, sum_sqr+cur_sum, &std_val);
+ my_decimal_div(E_DEC_FATAL_ERROR, &std_val, &sum2, &num, 0);
+ my_decimal2string(E_DEC_FATAL_ERROR, &std_val, 0, 0, '0', s);
+ return s;
+}
+
+
int collect_string(String *element,
element_count count __attribute__((unused)),
TREE_INFO *info)
@@ -924,6 +1081,28 @@ int collect_real(double *element, element_count count __attribute__((unused)),
} // collect_real
+int collect_decimal(char *element, element_count count,
+ TREE_INFO *info)
+{
+ char buff[DECIMAL_MAX_STR_LENGTH];
+ String s(buff, sizeof(buff),&my_charset_bin);
+
+ if (info->found)
+ info->str->append(',');
+ else
+ info->found = 1;
+ my_decimal dec;
+ binary2my_decimal(E_DEC_FATAL_ERROR, element, &dec,
+ info->item->max_length, info->item->decimals);
+
+ info->str->append('\'');
+ my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, '0', &s);
+ info->str->append(s);
+ info->str->append('\'');
+ return 0;
+}
+
+
int collect_longlong(longlong *element,
element_count count __attribute__((unused)),
TREE_INFO *info)
@@ -1025,12 +1204,12 @@ uint check_ulonglong(const char *str, uint length)
bigger = LONG_NUM;
}
else if (length > ulonglong_len)
- return REAL_NUM;
+ return DECIMAL_NUM;
else
{
cmp = ulonglong_str;
smaller = LONG_NUM;
- bigger = REAL_NUM;
+ bigger = DECIMAL_NUM;
}
while (*cmp && *cmp++ == *str++) ;
return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
@@ -1055,7 +1234,7 @@ uint check_ulonglong(const char *str, uint length)
1 Out of memory
*/
-static bool append_escaped(String *to_str, String *from_str)
+bool append_escaped(String *to_str, String *from_str)
{
char *from, *end, c;
diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h
index 8523b05a1de..9e5926fd9b1 100644
--- a/sql/sql_analyse.h
+++ b/sql/sql_analyse.h
@@ -61,6 +61,7 @@ int compare_longlong2(void* cmp_arg __attribute__((unused)),
int compare_ulonglong(const ulonglong *s, const ulonglong *t);
int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
const ulonglong *s, const ulonglong *t);
+int compare_decimal2(int* len, const char *s, const char *t);
Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result,
List<Item> &field_list);
void free_string(String*);
@@ -143,6 +144,36 @@ public:
};
+int collect_decimal(char *element, element_count count,
+ TREE_INFO *info);
+
+class field_decimal :public field_info
+{
+ my_decimal min_arg, max_arg;
+ my_decimal sum[2], sum_sqr[2];
+ int cur_sum;
+ int bin_size;
+public:
+ field_decimal(Item* a, analyse* b) :field_info(a,b)
+ {
+ bin_size= my_decimal_get_binary_size(a->max_length, a->decimals);
+ init_tree(&tree, 0, 0, bin_size, (qsort_cmp2)compare_decimal2,
+ 0, 0, (void *)&bin_size);
+ };
+
+ void add();
+ void get_opt_type(String*, ha_rows);
+ String *get_min_arg(String *);
+ String *get_max_arg(String *);
+ String *avg(String *s, ha_rows rows);
+ friend int collect_decimal(char *element, element_count count,
+ TREE_INFO *info);
+ tree_walk_action collect_enum()
+ { return (tree_walk_action) collect_decimal; }
+ String *std(String *s, ha_rows rows);
+};
+
+
int collect_real(double *element, element_count count, TREE_INFO *info);
class field_real: public field_info
diff --git a/sql/sql_array.h b/sql/sql_array.h
new file mode 100644
index 00000000000..c68caf74b25
--- /dev/null
+++ b/sql/sql_array.h
@@ -0,0 +1,69 @@
+/* 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 <my_sys.h>
+
+/*
+ A typesafe wrapper around DYNAMIC_ARRAY
+*/
+
+template <class Elem> class Dynamic_array
+{
+ DYNAMIC_ARRAY array;
+public:
+ Dynamic_array(uint prealloc=16, uint increment=16)
+ {
+ my_init_dynamic_array(&array, sizeof(Elem), prealloc, increment);
+ }
+
+ Elem& at(int idx)
+ {
+ return *(((Elem*)array.buffer) + idx);
+ }
+
+ Elem *front()
+ {
+ return (Elem*)array.buffer;
+ }
+
+ Elem *back()
+ {
+ return ((Elem*)array.buffer) + array.elements;
+ }
+
+ bool append(Elem &el)
+ {
+ return (insert_dynamic(&array, (gptr)&el));
+ }
+
+ int elements()
+ {
+ return array.elements;
+ }
+
+ ~Dynamic_array()
+ {
+ delete_dynamic(&array);
+ }
+
+ typedef int (*CMP_FUNC)(const Elem *el1, const Elem *el2);
+
+ void sort(CMP_FUNC cmp_func)
+ {
+ qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func);
+ }
+};
+
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b48f2537069..fb23093731a 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -19,30 +19,36 @@
#include "mysql_priv.h"
#include "sql_select.h"
+#include "sp_head.h"
+#include "sp.h"
+#include "sql_trigger.h"
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
-#include <nisam.h>
#ifdef __WIN__
#include <io.h>
#endif
TABLE *unused_tables; /* Used by mysql_test */
HASH open_cache; /* Used by mysql_test */
-HASH assign_cache;
-static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
- const char *name, const char *alias);
+static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
+ const char *name, const char *alias,
+ TABLE_LIST *table_list, MEM_ROOT *mem_root);
static void free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void);
-
+static my_bool open_new_frm(const char *path, const char *alias,
+ const char *db, const char *table_name,
+ uint db_stat, uint prgflag,
+ uint ha_open_flags, TABLE *outparam,
+ TABLE_LIST *table_desc, MEM_ROOT *mem_root);
extern "C" byte *table_cache_key(const byte *record,uint *length,
my_bool not_used __attribute__((unused)))
{
TABLE *entry=(TABLE*) record;
- *length=entry->key_length;
- return (byte*) entry->table_cache_key;
+ *length= entry->s->key_length;
+ return (byte*) entry->s->table_cache_key;
}
bool table_cache_init(void)
@@ -123,12 +129,11 @@ static void check_unused(void)
# Pointer to list of names of open tables.
*/
-OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
+OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild)
{
int result = 0;
OPEN_TABLE_LIST **start_list, *open_list;
TABLE_LIST table_list;
- char name[NAME_LEN*2];
DBUG_ENTER("list_open_tables");
VOID(pthread_mutex_lock(&LOCK_open));
@@ -140,20 +145,19 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
{
OPEN_TABLE_LIST *table;
TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
+ TABLE_SHARE *share= entry->s;
- DBUG_ASSERT(entry->real_name);
- if ((!entry->real_name)) // To be removed
+ DBUG_ASSERT(share->table_name != 0);
+ if ((!share->table_name)) // To be removed
continue; // Shouldn't happen
- if (wild)
- {
- strxmov(name,entry->table_cache_key,".",entry->real_name,NullS);
- if (wild_compare(name,wild,0))
- continue;
- }
+ if (db && my_strcasecmp(system_charset_info, db, share->db))
+ continue;
+ if (wild && wild_compare(share->table_name,wild,0))
+ continue;
/* Check if user has SELECT privilege for any column in the table */
- table_list.db= (char*) entry->table_cache_key;
- table_list.real_name= entry->real_name;
+ table_list.db= (char*) share->db;
+ table_list.table_name= (char*) share->table_name;
table_list.grant.privilege=0;
if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list,1))
@@ -161,8 +165,8 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
/* need to check if we haven't already listed it */
for (table= open_list ; table ; table=table->next)
{
- if (!strcmp(table->table,entry->real_name) &&
- !strcmp(table->db,entry->table_cache_key))
+ if (!strcmp(table->table,share->table_name) &&
+ !strcmp(table->db,entry->s->db))
{
if (entry->in_use)
table->in_use++;
@@ -174,15 +178,15 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
if (table)
continue;
if (!(*start_list = (OPEN_TABLE_LIST *)
- sql_alloc(sizeof(**start_list)+entry->key_length)))
+ sql_alloc(sizeof(**start_list)+share->key_length)))
{
open_list=0; // Out of memory
break;
}
strmov((*start_list)->table=
strmov(((*start_list)->db= (char*) ((*start_list)+1)),
- entry->table_cache_key)+1,
- entry->real_name);
+ entry->s->db)+1,
+ entry->s->table_name);
(*start_list)->in_use= entry->in_use ? 1 : 0;
(*start_list)->locked= entry->locked_by_name ? 1 : 0;
start_list= &(*start_list)->next;
@@ -200,6 +204,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
void intern_close_table(TABLE *table)
{ // Free all structures
free_io_cache(table);
+ delete table->triggers;
if (table->file)
VOID(closefrm(table)); // close file
}
@@ -282,9 +287,9 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
else
{
bool found=0;
- for (TABLE_LIST *table=tables ; table ; table=table->next)
+ for (TABLE_LIST *table= tables; table; table= table->next_local)
{
- if (remove_table_from_cache(thd, table->db, table->real_name,
+ if (remove_table_from_cache(thd, table->db, table->table_name,
RTFC_OWNED_BY_THD_FLAG))
found=1;
}
@@ -317,7 +322,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
for (uint idx=0 ; idx < open_cache.records ; idx++)
{
TABLE *table=(TABLE*) hash_element(&open_cache,idx);
- if ((table->version) < refresh_version && table->db_stat)
+ if ((table->s->version) < refresh_version && table->db_stat)
{
found=1;
pthread_cond_wait(&COND_refresh,&LOCK_open);
@@ -334,8 +339,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
result=reopen_tables(thd,1,1);
thd->in_lock_tables=0;
/* Set version for table */
- for (TABLE *table=thd->open_tables; table ; table=table->next)
- table->version=refresh_version;
+ for (TABLE *table=thd->open_tables; table ; table= table->next)
+ table->s->version= refresh_version;
}
VOID(pthread_mutex_unlock(&LOCK_open));
if (if_wait_for_refresh)
@@ -351,7 +356,30 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
/*
- Close all tables used by thread
+ Mark all tables in the list which were used by current substatement
+ as free for reuse.
+
+ SYNOPSIS
+ mark_used_tables_as_free_for_reuse()
+ thd - thread context
+ table - head of the list of tables
+
+ DESCRIPTION
+ Marks all tables in the list which were used by current substatement
+ (they are marked by its query_id) as free for reuse.
+*/
+
+static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table)
+{
+ for (; table ; table= table->next)
+ if (table->query_id == thd->query_id)
+ table->query_id= 0;
+}
+
+
+/*
+ Close all tables used by the current substatement, or all tables
+ used by this thread if we are on the upper level.
SYNOPSIS
close_thread_tables()
@@ -360,23 +388,42 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
LOCK_open
skip_derived Set to 1 (0 = default) if we should not free derived
tables.
+ stopper When closing tables from thd->open_tables(->next)*,
+ don't close/remove tables starting from stopper.
IMPLEMENTATION
Unlocks tables and frees derived tables.
Put all normal tables used by thread in free list.
+
+ When in prelocked mode it will only close/mark as free for reuse
+ tables opened by this substatement, it will also check if we are
+ closing tables after execution of complete query (i.e. we are on
+ upper level) and will leave prelocked mode if needed.
*/
void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
{
bool found_old_table;
+ prelocked_mode_type prelocked_mode= thd->prelocked_mode;
DBUG_ENTER("close_thread_tables");
+ /*
+ We are assuming here that thd->derived_tables contains ONLY derived
+ tables for this substatement. i.e. instead of approach which uses
+ query_id matching for determining which of the derived tables belong
+ to this substatement we rely on the ability of substatements to
+ save/restore thd->derived_tables during their execution.
+
+ TODO: Probably even better approach is to simply associate list of
+ derived tables with (sub-)statement instead of thread and destroy
+ them at the end of its execution.
+ */
if (thd->derived_tables && !skip_derived)
{
TABLE *table, *next;
/*
- Close all derived tables generated from questions like
- SELECT * from (select * from t1))
+ Close all derived tables generated in queries like
+ SELECT * FROM (SELECT * FROM t1)
*/
for (table= thd->derived_tables ; table ; table= next)
{
@@ -385,10 +432,55 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
}
thd->derived_tables= 0;
}
- if (thd->locked_tables)
+
+ if (prelocked_mode)
{
- ha_commit_stmt(thd); // If select statement
- DBUG_VOID_RETURN; // LOCK TABLES in use
+ /*
+ Mark all temporary tables used by this substatement as free for reuse.
+ */
+ mark_used_tables_as_free_for_reuse(thd, thd->temporary_tables);
+ }
+
+ if (thd->locked_tables || prelocked_mode)
+ {
+ /*
+ Let us commit transaction for statement. Since in 5.0 we only have
+ one statement transaction and don't allow several nested statement
+ transactions this call will do nothing if we are inside of stored
+ function or trigger (i.e. statement transaction is already active and
+ does not belong to statement for which we do close_thread_tables()).
+ TODO: This should be fixed in later releases.
+ */
+ ha_commit_stmt(thd);
+
+ /* We are under simple LOCK TABLES so should not do anything else. */
+ if (!prelocked_mode)
+ DBUG_VOID_RETURN;
+
+ if (!thd->lex->requires_prelocking())
+ {
+ /*
+ If we are executing one of substatements we have to mark
+ all tables which it used as free for reuse.
+ */
+ mark_used_tables_as_free_for_reuse(thd, thd->open_tables);
+ DBUG_VOID_RETURN;
+ }
+
+ DBUG_ASSERT(prelocked_mode);
+ /*
+ We are in prelocked mode, so we have to leave it now with doing
+ implicit UNLOCK TABLES if need.
+ */
+ DBUG_PRINT("info",("thd->prelocked_mode= NON_PRELOCKED"));
+ thd->prelocked_mode= NON_PRELOCKED;
+
+ if (prelocked_mode == PRELOCKED_UNDER_LOCK_TABLES)
+ DBUG_VOID_RETURN;
+
+ thd->lock= thd->locked_tables;
+ thd->locked_tables= 0;
+ /* Fallthrough */
}
if (thd->lock)
@@ -396,12 +488,24 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
+ /*
+ assume handlers auto-commit (if some doesn't - transaction handling
+ in MySQL should be redesigned to support it; it's a big change,
+ and it's not worth it - better to commit explicitly only writing
+ transactions, read-only ones should better take care of themselves.
+ saves some work in 2pc too)
+ see also sql_parse.cc - dispatch_command()
+ */
+ bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt));
+ if (!thd->active_transaction())
+ thd->transaction.xid_state.xid.null();
+
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */
if (!lock_in_use)
VOID(pthread_mutex_lock(&LOCK_open));
safe_mutex_assert_owner(&LOCK_open);
- DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables));
+ DBUG_PRINT("info", ("thd->open_tables: %p", thd->open_tables));
found_old_table= 0;
while (thd->open_tables)
@@ -420,6 +524,17 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
if (!lock_in_use)
VOID(pthread_mutex_unlock(&LOCK_open));
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */
+
+ if (prelocked_mode == PRELOCKED)
+ {
+ /*
+ If we are here then we are leaving normal prelocked mode, so it is
+ good idea to turn off OPTION_TABLE_LOCK flag.
+ */
+ DBUG_ASSERT(thd->lex->requires_prelocking());
+ thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+ }
+
DBUG_VOID_RETURN;
}
@@ -427,14 +542,14 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
bool close_thread_table(THD *thd, TABLE **table_ptr)
{
- DBUG_ENTER("close_thread_table");
-
bool found_old_table= 0;
TABLE *table= *table_ptr;
+ DBUG_ENTER("close_thread_table");
DBUG_ASSERT(table->key_read == 0);
+ DBUG_ASSERT(table->file->inited == handler::NONE);
*table_ptr=table->next;
- if (table->version != refresh_version ||
+ if (table->s->version != refresh_version ||
thd->version != refresh_version || !table->db_stat)
{
VOID(hash_delete(&open_cache,(byte*) table));
@@ -442,9 +557,9 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
}
else
{
- if (table->flush_version != flush_version)
+ if (table->s->flush_version != flush_version)
{
- table->flush_version=flush_version;
+ table->s->flush_version= flush_version;
table->file->extra(HA_EXTRA_FLUSH);
}
else
@@ -472,8 +587,8 @@ void close_temporary(TABLE *table,bool delete_table)
{
DBUG_ENTER("close_temporary");
char path[FN_REFLEN];
- db_type table_type=table->db_type;
- strmov(path,table->path);
+ db_type table_type=table->s->db_type;
+ strmov(path,table->s->path);
free_io_cache(table);
closefrm(table);
my_free((char*) table,MYF(0));
@@ -502,7 +617,7 @@ void close_temporary_tables(THD *thd)
enough; indeed it is enough, because table->key_length is greater (by 8,
because of server_id and thread_id) than db||table.
*/
- query_buf_size+= table->key_length+1;
+ query_buf_size+= table->s->key_length+1;
if ((query = alloc_root(thd->mem_root, query_buf_size)))
// Better add "if exists", in case a RESET MASTER has been done
@@ -513,17 +628,13 @@ void close_temporary_tables(THD *thd)
if (query) // we might be out of memory, but this is not fatal
{
// skip temporary tables not created directly by the user
- if (table->real_name[0] != '#')
+ if (table->s->table_name[0] != '#')
found_user_tables = 1;
- /*
- Here we assume table_cache_key always starts
- with \0 terminated db name
- */
- end = strxmov(end,"`",table->table_cache_key,"`.`",
- table->real_name,"`,", NullS);
+ end = strxmov(end,"`",table->s->db,"`.`",
+ table->s->table_name,"`,", NullS);
}
next=table->next;
- close_temporary(table);
+ close_temporary(table, 1);
}
if (query && found_user_tables && mysql_bin_log.is_open())
{
@@ -545,56 +656,178 @@ void close_temporary_tables(THD *thd)
thd->temporary_tables=0;
}
+
/*
- Find first suitable table by alias in given list.
+ Find table in list.
SYNOPSIS
find_table_in_list()
- table - pointer to table list
- db_name - data base name or 0 for any
- table_name - table name or 0 for any
+ table Pointer to table list
+ offset Offset to which list in table structure to use
+ db_name Data base name
+ table_name Table name
+
+ NOTES:
+ This is called by find_table_in_local_list() and
+ find_table_in_global_list().
RETURN VALUES
NULL Table not found
# Pointer to found table.
*/
-TABLE_LIST * find_table_in_list(TABLE_LIST *table,
- const char *db_name, const char *table_name)
+TABLE_LIST *find_table_in_list(TABLE_LIST *table,
+ uint offset,
+ const char *db_name,
+ const char *table_name)
{
- for (; table; table= table->next)
- if ((!db_name || !strcmp(table->db, db_name)) &&
- (!table_name || !my_strcasecmp(table_alias_charset,
- table->alias, table_name)))
+ for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
+ {
+ if ((table->table == 0 || table->table->s->tmp_table == NO_TMP_TABLE) &&
+ strcmp(table->db, db_name) == 0 &&
+ strcmp(table->table_name, table_name) == 0)
break;
+ }
return table;
}
+
/*
- Find real table in given list.
+ Test that table is unique (It's only exists once in the table list)
SYNOPSIS
- find_real_table_in_list()
- table - pointer to table list
- db_name - data base name
- table_name - table name
+ unique_table()
+ table table which should be checked
+ table_list list of tables
+
+ NOTE: to exclude derived tables from check we use following mechanism:
+ a) during derived table processing set THD::derived_tables_processing
+ b) JOIN::prepare set SELECT::exclude_from_table_unique_test if
+ THD::derived_tables_processing set. (we can't use JOIN::execute
+ because for PS we perform only JOIN::prepare, but we can't set this
+ flag in JOIN::prepare if we are not sure that we are in derived table
+ processing loop, because multi-update call fix_fields() for some its
+ items (which mean JOIN::prepare for subqueries) before unique_table
+ call to detect which tables should be locked for write).
+ c) unique_table skip all tables which belong to SELECT with
+ SELECT::exclude_from_table_unique_test set.
+ Also SELECT::exclude_from_table_unique_test used to exclude from check
+ tables of main SELECT of multi-delete and multi-update
+
+ TODO: when we will have table/view change detection we can do this check
+ only once for PS/SP
- RETURN VALUES
- NULL Table not found
- # Pointer to found table.
+ RETURN
+ found duplicate
+ 0 if table is unique
*/
-TABLE_LIST * find_real_table_in_list(TABLE_LIST *table,
- const char *db_name,
- const char *table_name)
+TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
{
- for (; table; table= table->next)
- if (!strcmp(table->db, db_name) &&
- !strcmp(table->real_name, table_name))
+ TABLE_LIST *res;
+ const char *d_name, *t_name;
+ DBUG_ENTER("unique_table");
+ DBUG_PRINT("enter", ("table alias: %s", table->alias));
+
+ /*
+ If this function called for query which update table (INSERT/UPDATE/...)
+ then we have in table->table pointer to TABLE object which we are
+ updating even if it is VIEW so we need TABLE_LIST of this TABLE object
+ to get right names (even if lower_case_table_names used).
+
+ If this function called for CREATE command that we have not opened table
+ (table->table equal to 0) and right names is in current TABLE_LIST
+ object.
+ */
+ if (table->table)
+ {
+ /* temporary table is always unique */
+ if (table->table && table->table->s->tmp_table != NO_TMP_TABLE)
+ DBUG_RETURN(0);
+ table= table->find_underlying_table(table->table);
+ /*
+ as far as we have table->table we have to find real TABLE_LIST of
+ it in underlying tables
+ */
+ DBUG_ASSERT(table);
+ }
+ d_name= table->db;
+ t_name= table->table_name;
+
+ DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name));
+ for (;;)
+ {
+ if (!(res= find_table_in_global_list(table_list, d_name, t_name)) ||
+ (!res->table || res->table != table->table) &&
+ (res->select_lex && !res->select_lex->exclude_from_table_unique_test))
break;
- return table;
+ /*
+ If we found entry of this table or or table of SELECT which already
+ processed in derived table or top select of multi-update/multi-delete
+ (exclude_from_table_unique_test).
+ */
+ table_list= res->next_global;
+ DBUG_PRINT("info",
+ ("found same copy of table or table which we should skip"));
+ }
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Issue correct error message in case we found 2 duplicate tables which
+ prevent some update operation
+
+ SYNOPSIS
+ update_non_unique_table_error()
+ update table which we try to update
+ operation name of update operation
+ duplicate duplicate table which we found
+
+ NOTE:
+ here we hide view underlying tables if we have them
+*/
+
+void update_non_unique_table_error(TABLE_LIST *update,
+ const char *operation,
+ TABLE_LIST *duplicate)
+{
+ update= update->top_table();
+ duplicate= duplicate->top_table();
+ if (!update->view || !duplicate->view ||
+ update->view == duplicate->view ||
+ update->view_name.length != duplicate->view_name.length ||
+ update->view_db.length != duplicate->view_db.length ||
+ my_strcasecmp(table_alias_charset,
+ update->view_name.str, duplicate->view_name.str) != 0 ||
+ my_strcasecmp(table_alias_charset,
+ update->view_db.str, duplicate->view_db.str) != 0)
+ {
+ /*
+ it is not the same view repeated (but it can be parts of the same copy
+ of view), so we have to hide underlying tables.
+ */
+ if (update->view)
+ {
+ if (update->view == duplicate->view)
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), update->alias, operation);
+ else
+ my_error(ER_VIEW_PREVENT_UPDATE, MYF(0),
+ (duplicate->view ? duplicate->alias : update->alias),
+ operation, update->alias);
+ return;
+ }
+ if (duplicate->view)
+ {
+ my_error(ER_VIEW_PREVENT_UPDATE, MYF(0), duplicate->alias, operation,
+ update->alias);
+ return;
+ }
+ }
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), update->alias);
}
+
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
{
char key[MAX_DBKEY_LENGTH];
@@ -609,8 +842,8 @@ TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
prev= &thd->temporary_tables;
for (table=thd->temporary_tables ; table ; table=table->next)
{
- if (table->key_length == key_length &&
- !memcmp(table->table_cache_key,key,key_length))
+ if (table->s->key_length == key_length &&
+ !memcmp(table->s->table_cache_key,key,key_length))
return prev;
prev= &table->next;
}
@@ -625,7 +858,7 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name)
return 1;
table= *prev;
*prev= table->next;
- close_temporary(table);
+ close_temporary(table, 1);
if (thd->slave_thread)
--slave_open_temp_tables;
return 0;
@@ -638,22 +871,26 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name)
Prepares a table cache key, which is the concatenation of db, table_name and
thd->slave_proxy_id, separated by '\0'.
*/
+
bool rename_temporary_table(THD* thd, TABLE *table, const char *db,
const char *table_name)
{
char *key;
+ TABLE_SHARE *share= table->s;
+
if (!(key=(char*) alloc_root(&table->mem_root,
(uint) strlen(db)+
(uint) strlen(table_name)+6+4)))
return 1; /* purecov: inspected */
- table->key_length=(uint)
- (strmov((table->real_name=strmov(table->table_cache_key=key,
- db)+1),
- table_name) - table->table_cache_key)+1;
- int4store(key+table->key_length,thd->server_id);
- table->key_length += 4;
- int4store(key+table->key_length,thd->variables.pseudo_thread_id);
- table->key_length += 4;
+ share->key_length= (uint)
+ (strmov((char*) (share->table_name= strmov(share->table_cache_key= key,
+ db)+1),
+ table_name) - share->table_cache_key)+1;
+ share->db= share->table_cache_key;
+ int4store(key+share->key_length, thd->server_id);
+ share->key_length+= 4;
+ int4store(key+share->key_length, thd->variables.pseudo_thread_id);
+ share->key_length+= 4;
return 0;
}
@@ -684,15 +921,16 @@ static void relink_unused(TABLE *table)
TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find)
{
char key[MAX_DBKEY_LENGTH];
- uint key_length=find->key_length;
+ uint key_length= find->s->key_length;
TABLE *start=list,**prev,*next;
prev= &start;
- memcpy(key,find->table_cache_key,key_length);
+
+ memcpy(key, find->s->table_cache_key, key_length);
for (; list ; list=next)
{
next=list->next;
- if (list->key_length == key_length &&
- !memcmp(list->table_cache_key,key,key_length))
+ if (list->s->key_length == key_length &&
+ !memcmp(list->s->table_cache_key, key, key_length))
{
if (thd->locked_tables)
mysql_lock_remove(thd, thd->locked_tables,list);
@@ -743,29 +981,34 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
DBUG_ENTER("reopen_name_locked_table");
if (thd->killed)
DBUG_RETURN(0);
- TABLE* table;
+ TABLE *table;
+ TABLE_SHARE *share;
if (!(table = table_list->table))
DBUG_RETURN(0);
char* db = thd->db ? thd->db : table_list->db;
- char* table_name = table_list->real_name;
+ char* table_name = table_list->table_name;
char key[MAX_DBKEY_LENGTH];
uint key_length;
key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
pthread_mutex_lock(&LOCK_open);
- if (open_unireg_entry(thd, table, db, table_name, table_name) ||
- !(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
- key_length)))
+ if (open_unireg_entry(thd, table, db, table_name, table_name, 0,
+ thd->mem_root) ||
+ !(table->s->table_cache_key= memdup_root(&table->mem_root, (char*) key,
+ key_length)))
{
+ delete table->triggers;
closefrm(table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0);
}
- table->key_length=key_length;
- table->version=0;
- table->flush_version=0;
+ share= table->s;
+ share->db= share->table_cache_key;
+ share->key_length=key_length;
+ share->version=0;
+ share->flush_version=0;
table->in_use = thd;
check_unused();
pthread_mutex_unlock(&LOCK_open);
@@ -774,30 +1017,47 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
- table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
+ table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
- table->keys_in_use_for_query= table->keys_in_use;
- table->used_keys= table->keys_for_keyread;
+ table->keys_in_use_for_query= share->keys_in_use;
+ table->used_keys= share->keys_for_keyread;
DBUG_RETURN(table);
}
-/******************************************************************************
-** open a table
-** Uses a cache of open tables to find a table not in use.
-** If refresh is a NULL pointer, then the is no version number checking and
-** the table is not put in the thread-open-list
-** If the return value is NULL and refresh is set then one must close
-** all tables and retry the open
-******************************************************************************/
+/*
+ Open a table.
+
+ SYNOPSIS
+ open_table()
+ thd Thread context.
+ table_list Open first table in list.
+ refresh INOUT Pointer to memory that will be set to 1 if
+ we need to close all tables and reopen them.
+ If this is a NULL pointer, then the table is not
+ put in the thread-open-list.
+ flags Bitmap of flags to modify how open works:
+ MYSQL_LOCK_IGNORE_FLUSH - Open table even if
+ someone has done a flush or namelock on it.
+ No version number checking is done.
+
+ IMPLEMENTATION
+ Uses a cache of open tables to find a table not in use.
+
+ RETURN
+ NULL Open failed. If refresh is set then one should close
+ all other tables and retry the open.
+ # Success. Pointer to TABLE object for open table.
+*/
-TABLE *open_table(THD *thd,const char *db,const char *table_name,
- const char *alias,bool *refresh)
+TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
+ bool *refresh, uint flags)
{
reg1 TABLE *table;
char key[MAX_DBKEY_LENGTH];
uint key_length;
+ char *alias= table_list->alias;
DBUG_ENTER("open_table");
/* find a unused table in the open table cache */
@@ -805,45 +1065,135 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
*refresh=0;
if (thd->killed)
DBUG_RETURN(0);
- key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
+ key_length= (uint) (strmov(strmov(key, table_list->db)+1,
+ table_list->table_name)-key)+1;
int4store(key + key_length, thd->server_id);
int4store(key + key_length + 4, thd->variables.pseudo_thread_id);
- for (table=thd->temporary_tables; table ; table=table->next)
+ if (!table_list->skip_temporary)
{
- if (table->key_length == key_length + TMP_TABLE_KEY_EXTRA &&
- !memcmp(table->table_cache_key, key,
- key_length + TMP_TABLE_KEY_EXTRA))
+ for (table= thd->temporary_tables; table ; table=table->next)
{
- if (table->query_id == thd->query_id)
+ if (table->s->key_length == key_length + TMP_TABLE_KEY_EXTRA &&
+ !memcmp(table->s->table_cache_key, key,
+ key_length + TMP_TABLE_KEY_EXTRA))
{
- my_printf_error(ER_CANT_REOPEN_TABLE,
- ER(ER_CANT_REOPEN_TABLE),MYF(0),table->table_name);
- DBUG_RETURN(0);
+ if (table->query_id == thd->query_id ||
+ thd->prelocked_mode && table->query_id)
+ {
+ my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
+ DBUG_RETURN(0);
+ }
+ table->query_id= thd->query_id;
+ table->clear_query_id= 1;
+ thd->tmp_table_used= 1;
+ DBUG_PRINT("info",("Using temporary table"));
+ goto reset;
}
- table->query_id=thd->query_id;
- table->clear_query_id=1;
- thd->tmp_table_used= 1;
- DBUG_PRINT("info",("Using temporary table"));
- goto reset;
}
}
- if (thd->locked_tables)
+ if (thd->locked_tables || thd->prelocked_mode)
{ // Using table locks
+ TABLE *best_table= 0;
+ int best_distance= INT_MIN;
+ bool check_if_used= thd->prelocked_mode &&
+ ((int) table_list->lock_type >=
+ (int) TL_WRITE_ALLOW_WRITE);
for (table=thd->open_tables; table ; table=table->next)
{
- if (table->key_length == key_length &&
- !memcmp(table->table_cache_key,key,key_length) &&
- !my_strcasecmp(system_charset_info, table->table_name, alias) &&
- table->query_id != thd->query_id)
+ if (table->s->key_length == key_length &&
+ !memcmp(table->s->table_cache_key, key, key_length))
+ {
+ if (check_if_used && table->query_id &&
+ table->query_id != thd->query_id)
+ {
+ /*
+ If we are in stored function or trigger we should ensure that
+ we won't change table that is already used by calling statement.
+ So if we are opening table for writing, we should check that it
+ is not already open by some calling stamement.
+ */
+ my_error(ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG, MYF(0),
+ table->s->table_name);
+ DBUG_RETURN(0);
+ }
+ if (!my_strcasecmp(system_charset_info, table->alias, alias) &&
+ table->query_id != thd->query_id && /* skip tables already used */
+ !(thd->prelocked_mode && table->query_id))
+ {
+ int distance= ((int) table->reginfo.lock_type -
+ (int) table_list->lock_type);
+ /*
+ Find a table that either has the exact lock type requested,
+ or has the best suitable lock. In case there is no locked
+ table that has an equal or higher lock than requested,
+ we us the closest matching lock to be able to produce an error
+ message about wrong lock mode on the table. The best_table
+ is changed if bd < 0 <= d or bd < d < 0 or 0 <= d < bd.
+
+ distance < 0 - No suitable lock found
+ distance > 0 - we have lock mode higher then we require
+ distance == 0 - we have lock mode exactly which we need
+ */
+ if (best_distance < 0 && distance > best_distance ||
+ distance >= 0 && distance < best_distance)
+ {
+ best_distance= distance;
+ best_table= table;
+ if (best_distance == 0 && !check_if_used)
+ {
+ /*
+ If we have found perfect match and we don't need to check that
+ table is not used by one of calling statements (assuming that
+ we are inside of function or trigger) we can finish iterating
+ through open tables list.
+ */
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (best_table)
+ {
+ table= best_table;
+ table->query_id= thd->query_id;
+ DBUG_PRINT("info",("Using locked table"));
+ goto reset;
+ }
+ /*
+ is it view?
+ (it is work around to allow to open view with locked tables,
+ real fix will be made after definition cache will be made)
+ */
+ {
+ char path[FN_REFLEN];
+ strxnmov(path, FN_REFLEN, mysql_data_home, "/", table_list->db, "/",
+ table_list->table_name, reg_ext, NullS);
+ (void) unpack_filename(path, path);
+ if (mysql_frm_type(path) == FRMTYPE_VIEW)
{
- table->query_id=thd->query_id;
- DBUG_PRINT("info",("Using locked table"));
- goto reset;
+ TABLE tab;// will not be used (because it's VIEW) but have to be passed
+ table= &tab;
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (open_unireg_entry(thd, table, table_list->db,
+ table_list->table_name,
+ alias, table_list, mem_root))
+ {
+ table->next=table->prev=table;
+ free_cache_entry(table);
+ }
+ else
+ {
+ DBUG_ASSERT(table_list->view != 0);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ DBUG_RETURN(0); // VIEW
+ }
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
}
- my_printf_error(ER_TABLE_NOT_LOCKED,ER(ER_TABLE_NOT_LOCKED),MYF(0),alias);
+ my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias);
DBUG_RETURN(0);
}
@@ -851,39 +1201,44 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
if (!thd->open_tables)
thd->version=refresh_version;
- else if (thd->version != refresh_version && refresh)
+ else if ((thd->version != refresh_version) &&
+ ! (flags & MYSQL_LOCK_IGNORE_FLUSH))
{
/* Someone did a refresh while thread was opening tables */
- *refresh=1;
+ if (refresh)
+ *refresh=1;
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(0);
}
/* close handler tables which are marked for flush */
- mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
+ if (thd->handler_tables)
+ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
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))
{
- if (table->version != refresh_version)
+ if (table->s->version != refresh_version)
{
- if (! refresh)
+ if (flags & MYSQL_LOCK_IGNORE_FLUSH)
{
- /* Ignore flush for now, but force close after usage. */
- thd->version= table->version;
+ /* Force close at once after usage */
+ thd->version= table->s->version;
continue;
}
/*
- ** There is a refresh in progress for this table
- ** Wait until the table is freed or the thread is killed.
+ There is a refresh in progress for this table
+ Wait until the table is freed or the thread is killed.
*/
close_old_data_files(thd,thd->open_tables,0,0);
if (table->in_use != thd)
wait_for_refresh(thd);
else
+ {
VOID(pthread_mutex_unlock(&LOCK_open));
+ }
if (refresh)
*refresh=1;
DBUG_RETURN(0);
@@ -899,10 +1254,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
}
table->prev->next=table->next; /* Remove from unused list */
table->next->prev=table->prev;
-
+ table->in_use= thd;
}
else
{
+ TABLE_SHARE *share;
/* Free cache if too big */
while (open_cache.records > table_cache_size && unused_tables)
VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */
@@ -913,25 +1269,35 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL);
}
- if (open_unireg_entry(thd, table,db,table_name,alias) ||
- !(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
- key_length)))
+ if (open_unireg_entry(thd, table, table_list->db, table_list->table_name,
+ alias, table_list, mem_root) ||
+ (!table_list->view &&
+ !(table->s->table_cache_key= memdup_root(&table->mem_root,
+ (char*) key,
+ key_length))))
{
table->next=table->prev=table;
free_cache_entry(table);
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL);
}
- table->key_length=key_length;
- table->version=refresh_version;
- table->flush_version=flush_version;
+ if (table_list->view)
+ {
+ my_free((gptr)table, MYF(0));
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ DBUG_RETURN(0); // VIEW
+ }
+ share= table->s;
+ share->db= share->table_cache_key;
+ share->key_length= key_length;
+ share->version= refresh_version;
+ share->flush_version= flush_version;
DBUG_PRINT("info", ("inserting table %p into the cache", table));
VOID(my_hash_insert(&open_cache,(byte*) table));
}
- table->in_use=thd;
check_unused(); // Debugging call
-
+
VOID(pthread_mutex_unlock(&LOCK_open));
if (refresh)
{
@@ -941,53 +1307,30 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->reginfo.lock_type=TL_READ; /* Assume read */
reset:
+ if (thd->lex->need_correct_ident())
+ table->alias_name_used= my_strcasecmp(table_alias_charset,
+ table->s->table_name, alias);
/* Fix alias if table name changes */
- if (strcmp(table->table_name,alias))
+ if (strcmp(table->alias, alias))
{
uint length=(uint) strlen(alias)+1;
- table->table_name= (char*) my_realloc(table->table_name,length,
- MYF(MY_WME));
- memcpy(table->table_name,alias,length);
- for (uint i=0 ; i < table->fields ; i++)
- table->field[i]->table_name=table->table_name;
- }
-#if MYSQL_VERSION_ID < 40100
- /*
- If per-connection "new" variable (represented by variables.new_mode)
- is set then we should pretend that the length of TIMESTAMP field is 19.
- The cheapest (from perfomance viewpoint) way to achieve that is to set
- field_length of all Field_timestamp objects in a table after opening
- it (to 19 if new_mode is true or to original field length otherwise).
- We save value of new_mode variable in TABLE::timestamp_mode to
- not perform this setup if new_mode value is the same between sequential
- table opens.
- */
- my_bool new_mode= thd->variables.new_mode;
- if (table->timestamp_mode != new_mode)
- {
- for (uint i=0 ; i < table->fields ; i++)
- {
- Field *field= table->field[i];
-
- if (field->type() == FIELD_TYPE_TIMESTAMP)
- field->field_length= new_mode ? 19 :
- ((Field_timestamp *)(field))->orig_field_length;
- }
- table->timestamp_mode= new_mode;
+ table->alias= (char*) my_realloc((char*) table->alias, length,
+ MYF(MY_WME));
+ memcpy((char*) table->alias, alias, length);
}
-#endif
/* These variables are also set in reopen_table() */
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
- table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
+ table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
- table->keys_in_use_for_query= table->keys_in_use;
- table->used_keys= table->keys_for_keyread;
+ table->keys_in_use_for_query= table->s->keys_in_use;
+ table->insert_values= 0;
+ table->used_keys= table->s->keys_for_keyread;
if (table->timestamp_field)
table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
+ table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
DBUG_ASSERT(table->key_read == 0);
- DBUG_ASSERT(table->insert_values == 0);
DBUG_RETURN(table);
}
@@ -999,8 +1342,8 @@ TABLE *find_locked_table(THD *thd, const char *db,const char *table_name)
for (TABLE *table=thd->open_tables; table ; table=table->next)
{
- if (table->key_length == key_length &&
- !memcmp(table->table_cache_key,key,key_length))
+ if (table->s->key_length == key_length &&
+ !memcmp(table->s->table_cache_key,key,key_length))
return table;
}
return(0);
@@ -1017,9 +1360,9 @@ TABLE *find_locked_table(THD *thd, const char *db,const char *table_name)
bool reopen_table(TABLE *table,bool locked)
{
TABLE tmp;
- char *db=table->table_cache_key;
- char *table_name=table->real_name;
- bool error=1;
+ char *db= table->s->table_cache_key;
+ const char *table_name= table->s->table_name;
+ bool error= 1;
Field **field;
uint key,part;
DBUG_ENTER("reopen_table");
@@ -1027,62 +1370,68 @@ bool reopen_table(TABLE *table,bool locked)
#ifdef EXTRA_DEBUG
if (table->db_stat)
sql_print_error("Table %s had a open data handler in reopen_table",
- table->table_name);
+ table->alias);
#endif
if (!locked)
VOID(pthread_mutex_lock(&LOCK_open));
safe_mutex_assert_owner(&LOCK_open);
- if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name))
+ if (open_unireg_entry(table->in_use, &tmp, db, table_name,
+ table->alias, 0, table->in_use->mem_root))
goto end;
free_io_cache(table);
- if (!(tmp.table_cache_key= memdup_root(&tmp.mem_root,db,
- table->key_length)))
+ if (!(tmp.s->table_cache_key= memdup_root(&tmp.mem_root,db,
+ table->s->key_length)))
{
+ delete tmp.triggers;
closefrm(&tmp); // End of memory
goto end;
}
+ tmp.s->db= tmp.s->table_cache_key;
/* This list copies variables set by open_table */
tmp.tablenr= table->tablenr;
tmp.used_fields= table->used_fields;
tmp.const_table= table->const_table;
- tmp.outer_join= table->outer_join;
tmp.null_row= table->null_row;
tmp.maybe_null= table->maybe_null;
tmp.status= table->status;
- tmp.keys_in_use_for_query= tmp.keys_in_use;
- tmp.used_keys= tmp.keys_for_keyread;
- tmp.force_index= tmp.force_index;
+ tmp.keys_in_use_for_query= tmp.s->keys_in_use;
+ tmp.used_keys= tmp.s->keys_for_keyread;
/* Get state */
- tmp.key_length= table->key_length;
+ tmp.s->key_length= table->s->key_length;
tmp.in_use= table->in_use;
tmp.reginfo.lock_type=table->reginfo.lock_type;
- tmp.version= refresh_version;
- tmp.tmp_table= table->tmp_table;
+ tmp.s->version= refresh_version;
+ tmp.s->tmp_table= table->s->tmp_table;
tmp.grant= table->grant;
/* Replace table in open list */
tmp.next= table->next;
tmp.prev= table->prev;
+ delete table->triggers;
if (table->file)
VOID(closefrm(table)); // close file, free everything
- *table=tmp;
+ *table= tmp;
+ table->s= &table->share_not_to_be_used;
table->file->change_table_ptr(table);
- DBUG_ASSERT(table->table_name);
+ DBUG_ASSERT(table->alias != 0);
for (field=table->field ; *field ; field++)
{
(*field)->table= (*field)->orig_table= table;
- (*field)->table_name=table->table_name;
+ (*field)->table_name= &table->alias;
}
- for (key=0 ; key < table->keys ; key++)
+ for (key=0 ; key < table->s->keys ; key++)
for (part=0 ; part < table->key_info[key].usable_key_parts ; part++)
table->key_info[key].key_part[part].field->table= table;
+ if (table->triggers)
+ table->triggers->set_table(table);
+
VOID(pthread_cond_broadcast(&COND_refresh));
error=0;
@@ -1104,8 +1453,8 @@ bool close_data_tables(THD *thd,const char *db, const char *table_name)
TABLE *table;
for (table=thd->open_tables; table ; table=table->next)
{
- if (!strcmp(table->real_name,table_name) &&
- !strcmp(table->table_cache_key,db))
+ if (!strcmp(table->s->table_name, table_name) &&
+ !strcmp(table->s->db, db))
{
mysql_lock_remove(thd, thd->locked_tables,table);
table->file->close();
@@ -1131,7 +1480,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
TABLE *table,*next,**prev;
TABLE **tables,**tables_ptr; // For locks
- bool error=0;
+ bool error=0, not_used;
if (get_locks)
{
/* The ptr is checked later */
@@ -1150,7 +1499,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
next=table->next;
if (!tables || (!db_stat && reopen_table(table,1)))
{
- my_error(ER_CANT_REOPEN_TABLE,MYF(0),table->table_name);
+ my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
VOID(hash_delete(&open_cache,(byte*) table));
error=1;
}
@@ -1162,7 +1511,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
*tables_ptr++= table; // need new lock on this
if (in_refresh)
{
- table->version=0;
+ table->s->version=0;
table->locked_by_flush=0;
}
}
@@ -1172,7 +1521,8 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
MYSQL_LOCK *lock;
/* We should always get these locks */
thd->some_tables_deleted=0;
- if ((lock= mysql_lock_tables(thd, tables, (uint) (tables_ptr-tables), 0)))
+ if ((lock= mysql_lock_tables(thd, tables, (uint) (tables_ptr - tables),
+ 0, &not_used)))
{
thd->locked_tables=mysql_lock_merge(thd->locked_tables,lock);
}
@@ -1201,11 +1551,11 @@ void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
bool found=send_refresh;
for (; table ; table=table->next)
{
- if (table->version != refresh_version)
+ if (table->s->version != refresh_version)
{
found=1;
if (!abort_locks) // If not from flush tables
- table->version = refresh_version; // Let other threads use table
+ table->s->version= refresh_version; // Let other threads use table
if (table->db_stat)
{
if (abort_locks)
@@ -1235,8 +1585,8 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
{
do
{
- char *key= table->table_cache_key;
- uint key_length=table->key_length;
+ char *key= table->s->table_cache_key;
+ uint key_length= table->s->key_length;
for (TABLE *search=(TABLE*) hash_search(&open_cache,
(byte*) key,key_length) ;
search ;
@@ -1244,7 +1594,7 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
{
if (search->locked_by_flush ||
search->locked_by_name && wait_for_name_lock ||
- search->db_stat && search->version < refresh_version)
+ search->db_stat && search->s->version < refresh_version)
return 1; // Table is used
}
} while ((table=table->next));
@@ -1292,11 +1642,11 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name)
TABLE *table,*next,**prev;
bool found=0;
prev= &thd->open_tables;
- for (table=thd->open_tables; table ; table=next)
+ for (table= thd->open_tables; table ; table=next)
{
next=table->next;
- if (!strcmp(table->real_name,table_name) &&
- !strcmp(table->table_cache_key,db))
+ if (!strcmp(table->s->table_name, table_name) &&
+ !strcmp(table->s->db, db))
{
mysql_lock_remove(thd, thd->locked_tables,table);
VOID(hash_delete(&open_cache,(byte*) table));
@@ -1331,8 +1681,8 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
TABLE *table;
for (table= thd->open_tables; table ; table= table->next)
{
- if (!strcmp(table->real_name,table_name) &&
- !strcmp(table->table_cache_key,db))
+ if (!strcmp(table->s->table_name,table_name) &&
+ !strcmp(table->s->db, db))
{
mysql_lock_abort(thd,table);
break;
@@ -1351,6 +1701,8 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
db Database name
name Table name
alias Alias name
+ table_desc TABLE_LIST descriptor (used with views)
+ mem_root temporary mem_root for parsing
NOTES
Extra argument for open is taken from thd->open_options
@@ -1359,9 +1711,9 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
0 ok
# Error
*/
-
static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
- const char *name, const char *alias)
+ const char *name, const char *alias,
+ TABLE_LIST *table_desc, MEM_ROOT *mem_root)
{
char path[FN_REFLEN];
int error;
@@ -1369,19 +1721,28 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
DBUG_ENTER("open_unireg_entry");
strxmov(path, mysql_data_home, "/", db, "/", name, NullS);
- while (openfrm(path,alias,
- (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
- HA_TRY_READ_ONLY),
- READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
- thd->open_options, entry))
+ while ((error= openfrm(thd, path, alias,
+ (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
+ HA_GET_INDEX | HA_TRY_READ_ONLY |
+ NO_ERR_ON_NEW_FRM),
+ READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
+ thd->open_options, entry)) &&
+ (error != 5 ||
+ (fn_format(path, path, 0, reg_ext, MY_UNPACK_FILENAME),
+ open_new_frm(path, alias, db, name,
+ (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
+ HA_GET_INDEX | HA_TRY_READ_ONLY),
+ READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
+ thd->open_options, entry, table_desc, mem_root))))
+
{
- if (!entry->crashed)
+ if (!entry->s || !entry->s->crashed)
{
/*
- Frm file could not be found on disk
- Since it does not exist, no one can be using it
- LOCK_open has been locked to protect from someone else
- trying to discover the table at the same time.
+ Frm file could not be found on disk
+ Since it does not exist, no one can be using it
+ LOCK_open has been locked to protect from someone else
+ trying to discover the table at the same time.
*/
if (discover_retry_count++ != 0)
goto err;
@@ -1389,7 +1750,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
{
/* Give right error message */
thd->clear_error();
- DBUG_PRINT("error", ("Dicovery of %s/%s failed", db, name));
+ DBUG_PRINT("error", ("Discovery of %s/%s failed", db, name));
my_printf_error(ER_UNKNOWN_ERROR,
"Failed to open '%-.64s', error while "
"unpacking from engine",
@@ -1398,7 +1759,8 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
goto err;
}
- thd->clear_error(); // Clear error message
+ mysql_reset_errors(thd, 1); // Clear warnings
+ thd->clear_error(); // Clear error message
continue;
}
@@ -1406,7 +1768,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
TABLE_LIST table_list;
bzero((char*) &table_list, sizeof(table_list)); // just for safe
table_list.db=(char*) db;
- table_list.real_name=(char*) name;
+ table_list.table_name=(char*) name;
safe_mutex_assert_owner(&LOCK_open);
@@ -1425,7 +1787,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
pthread_mutex_unlock(&LOCK_open);
thd->clear_error(); // Clear error message
error= 0;
- if (openfrm(path,alias,
+ if (openfrm(thd, path, alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
@@ -1450,6 +1812,22 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
goto err;
break;
}
+
+ if (error == 5)
+ DBUG_RETURN(0); // we have just opened VIEW
+
+ /*
+ We can't mark all tables in 'mysql' database as system since we don't
+ allow to lock such tables for writing with any other tables (even with
+ other system tables) and some privilege tables need this.
+ */
+ if (!my_strcasecmp(system_charset_info, db, "mysql") &&
+ !my_strcasecmp(system_charset_info, name, "proc"))
+ entry->s->system_table= 1;
+
+ if (Table_triggers_list::check_n_load(thd, db, name, entry, 0))
+ goto err;
+
/*
If we are here, there was no fatal error (but error may be still
unitialized).
@@ -1478,6 +1856,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
*/
sql_print_error("When opening HEAP table, could not allocate \
memory to write 'DELETE FROM `%s`.`%s`' to the binary log",db,name);
+ delete entry->triggers;
if (entry->file)
closefrm(entry);
goto err;
@@ -1486,49 +1865,161 @@ memory to write 'DELETE FROM `%s`.`%s`' to the binary log",db,name);
}
DBUG_RETURN(0);
err:
+ /* Hide "Table doesn't exist" errors if table belong to view */
+ if (thd->net.last_errno == ER_NO_SUCH_TABLE &&
+ table_desc && table_desc->belong_to_view)
+ {
+ TABLE_LIST *view= table_desc->belong_to_view;
+ thd->clear_error();
+ my_error(ER_VIEW_INVALID, MYF(0), view->view_db.str, view->view_name.str);
+ }
DBUG_RETURN(1);
}
+
/*
Open all tables in list
SYNOPSIS
open_tables()
thd - thread handler
- start - list of tables
+ start - list of tables in/out
counter - number of opened tables will be return using this parameter
+ flags - bitmap of flags to modify how the tables will be open:
+ MYSQL_LOCK_IGNORE_FLUSH - open table even if someone has
+ done a flush or namelock on it.
+
+ NOTE
+ Unless we are already in prelocked mode, this function will also precache
+ all SP/SFs explicitly or implicitly (via views and triggers) used by the
+ query and add tables needed for their execution to table list. If resulting
+ tables list will be non empty it will mark query as requiring precaching.
+ Prelocked mode will be enabled for such query during lock_tables() call.
+
+ If query for which we are opening tables is already marked as requiring
+ prelocking it won't do such precaching and will simply reuse table list
+ which is already built.
RETURN
0 - OK
-1 - error
*/
-int open_tables(THD *thd, TABLE_LIST *start, uint *counter)
+int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
{
TABLE_LIST *tables;
bool refresh;
int result=0;
+ MEM_ROOT new_frm_mem;
+ /* Also used for indicating that prelocking is need */
+ TABLE_LIST **query_tables_last_own;
DBUG_ENTER("open_tables");
+ /*
+ temporary mem_root for new .frm parsing.
+ TODO: variables for size
+ */
+ init_alloc_root(&new_frm_mem, 8024, 8024);
thd->current_tablenr= 0;
restart:
*counter= 0;
+ query_tables_last_own= 0;
thd->proc_info="Opening tables";
- for (tables=start ; tables ; tables=tables->next)
+
+ /*
+ If we are not already executing prelocked statement and don't have
+ statement for which table list for prelocking is already built, let
+ us cache routines and try to build such table list.
+
+ NOTE: We can't delay prelocking until we will met some sub-statement
+ which really uses tables, since this will imply that we have to restore
+ its table list to be able execute it in some other context.
+ And current views implementation assumes that view tables are added to
+ global table list only once during PS preparing/first SP execution.
+ Also locking at earlier stage is probably faster altough may decrease
+ concurrency a bit.
+
+ NOTE: We will mark statement as requiring prelocking only if we will
+ have non empty table list. But this does not guarantee that in prelocked
+ mode we will have some locked tables, because queries which use only
+ derived/information schema tables and views possible. Thus "counter"
+ may be still zero for prelocked statement...
+
+ NOTE: The above notes may be out of date. Please wait for psergey to
+ document new prelocked behavior.
+ */
+
+ if (!thd->prelocked_mode && !thd->lex->requires_prelocking() &&
+ thd->lex->sroutines_list.elements)
+ {
+ bool first_no_prelocking, need_prelocking;
+ TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
+
+ DBUG_ASSERT(thd->lex->query_tables == *start);
+ sp_get_prelocking_info(thd, &need_prelocking, &first_no_prelocking);
+
+ if ((sp_cache_routines_and_add_tables(thd, thd->lex,
+ first_no_prelocking) ||
+ *start) && need_prelocking)
+ {
+ query_tables_last_own= save_query_tables_last;
+ *start= thd->lex->query_tables;
+ }
+ }
+
+ for (tables= *start; tables ;tables= tables->next_global)
{
/*
Ignore placeholders for derived tables. After derived tables
processing, link to created temporary table will be put here.
+ If this is derived table for view then we still want to process
+ routines used by this view.
*/
if (tables->derived)
+ {
+ if (tables->view)
+ goto process_view_routines;
continue;
+ }
+ if (tables->schema_table)
+ {
+ if (!mysql_schema_table(thd, thd->lex, tables))
+ continue;
+ DBUG_RETURN(-1);
+ }
(*counter)++;
+
if (!tables->table &&
- !(tables->table= open_table(thd,
- tables->db,
- tables->real_name,
- tables->alias, &refresh)))
+ !(tables->table= open_table(thd, tables, &new_frm_mem, &refresh, flags)))
{
+ free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC));
+
+ if (tables->view)
+ {
+ /* VIEW placeholder */
+ (*counter)--;
+
+ /*
+ tables->next_global list consists of two parts:
+ 1) Query tables and underlying tables of views.
+ 2) Tables used by all stored routines that this statement invokes on
+ execution.
+ We need to know where the bound between these two parts is. If we've
+ just opened a view, which was the last table in part #1, and it
+ has added its base tables after itself, adjust the boundary pointer
+ accordingly.
+ */
+ if (query_tables_last_own == &(tables->next_global) &&
+ tables->view->query_tables)
+ query_tables_last_own= tables->view->query_tables_last;
+ /*
+ Let us free memory used by 'sroutines' hash here since we never
+ call destructor for this LEX.
+ */
+ hash_free(&tables->view->sroutines);
+ goto process_view_routines;
+ }
+
if (refresh) // Refresh in progress
{
/* close all 'old' tables used by this thread */
@@ -1538,12 +2029,12 @@ int open_tables(THD *thd, TABLE_LIST *start, uint *counter)
thd->version=refresh_version;
TABLE **prev_table= &thd->open_tables;
bool found=0;
- for (TABLE_LIST *tmp=start ; tmp ; tmp=tmp->next)
+ for (TABLE_LIST *tmp= *start; tmp; tmp= tmp->next_global)
{
/* Close normal (not temporary) changed tables */
- if (tmp->table && ! tmp->table->tmp_table)
+ if (tmp->table && ! tmp->table->s->tmp_table)
{
- if (tmp->table->version != refresh_version ||
+ if (tmp->table->s->version != refresh_version ||
! tmp->table->db_stat)
{
VOID(hash_delete(&open_cache,(byte*) tmp->table));
@@ -1561,16 +2052,70 @@ int open_tables(THD *thd, TABLE_LIST *start, uint *counter)
pthread_mutex_unlock(&LOCK_open);
if (found)
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
+ /*
+ Let us prepare for recalculation of set of prelocked tables.
+ First we pretend that we have finished calculation which we
+ were doing currently. Then we restore list of tables to be
+ opened and set of used routines to the state in which they were
+ before first open_tables() call for this statement (i.e. before
+ we have calculated current set of tables for prelocking).
+ */
+ if (query_tables_last_own)
+ thd->lex->mark_as_requiring_prelocking(query_tables_last_own);
+ thd->lex->chop_off_not_own_tables();
+ sp_remove_not_own_routines(thd->lex);
goto restart;
}
result= -1; // Fatal error
break;
}
+ else
+ {
+ /*
+ If we are not already in prelocked mode and extended table list is not
+ yet built and we have trigger for table being opened then we should
+ cache all routines used by its triggers and add their tables to
+ prelocking list.
+ If we lock table for reading we won't update it so there is no need to
+ process its triggers since they never will be activated.
+ */
+ if (!thd->prelocked_mode && !thd->lex->requires_prelocking() &&
+ tables->table->triggers &&
+ tables->lock_type >= TL_WRITE_ALLOW_WRITE)
+ {
+ if (!query_tables_last_own)
+ query_tables_last_own= thd->lex->query_tables_last;
+ sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex,
+ tables->table->triggers);
+ }
+ free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC));
+ }
+
if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables)
tables->table->reginfo.lock_type=tables->lock_type;
tables->table->grant= tables->grant;
+
+process_view_routines:
+ /*
+ Again we may need cache all routines used by this view and add
+ tables used by them to table list.
+ */
+ if (tables->view && !thd->prelocked_mode &&
+ !thd->lex->requires_prelocking() &&
+ tables->view->sroutines_list.elements)
+ {
+ /* We have at least one table in TL here. */
+ if (!query_tables_last_own)
+ query_tables_last_own= thd->lex->query_tables_last;
+ sp_cache_routines_and_add_tables_for_view(thd, thd->lex, tables->view);
+ }
}
thd->proc_info=0;
+ free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
+
+ if (query_tables_last_own)
+ thd->lex->mark_as_requiring_prelocking(query_tables_last_own);
+
DBUG_RETURN(result);
}
@@ -1598,9 +2143,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
(int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
{
- my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
- ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
- MYF(0),table->table_name);
+ my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),table->alias);
DBUG_RETURN(1);
}
if ((error=table->file->start_stmt(thd)))
@@ -1621,6 +2164,11 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
table_list Table to open is first table in this list
lock_type Lock to use for open
+ NOTE
+ This function don't do anything like SP/SF/views/triggers analysis done
+ in open_tables(). It is intended for opening of only one concrete table.
+ And used only in special contexts.
+
RETURN VALUES
table Opened table
0 Error
@@ -1638,9 +2186,11 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
thd->proc_info="Opening table";
thd->current_tablenr= 0;
- while (!(table=open_table(thd,table_list->db,
- table_list->real_name,table_list->alias,
- &refresh)) && refresh) ;
+ /* open_ltable can be used only for BASIC TABLEs */
+ table_list->required_type= FRMTYPE_TABLE;
+ while (!(table= open_table(thd, table_list, thd->mem_root, &refresh, 0)) &&
+ refresh)
+ ;
if (table)
{
@@ -1663,7 +2213,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
{
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
- if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1, 0)))
+ if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1, 0,
+ &refresh)))
table= 0;
}
}
@@ -1686,15 +2237,25 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
-1 - error
NOTE
- The lock will automaticly be freed by close_thread_tables()
+ The lock will automaticaly be freed by close_thread_tables()
*/
int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
{
- DBUG_ENTER("simple_open_n_lock_tables");
uint counter;
- if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
- DBUG_RETURN(-1); /* purecov: inspected */
+ bool need_reopen;
+ DBUG_ENTER("simple_open_n_lock_tables");
+
+ for ( ; ; )
+ {
+ if (open_tables(thd, &tables, &counter, 0))
+ DBUG_RETURN(-1);
+ if (!lock_tables(thd, tables, counter, &need_reopen))
+ break;
+ if (!need_reopen)
+ DBUG_RETURN(-1);
+ close_tables_for_reopen(thd, tables);
+ }
DBUG_RETURN(0);
}
@@ -1709,21 +2270,34 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
tables - list of tables for open&locking
RETURN
- 0 - ok
- -1 - error
+ FALSE - ok
+ TRUE - error
NOTE
- The lock will automaticly be freed by close_thread_tables()
+ The lock will automaticaly be freed by close_thread_tables()
*/
-int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
+bool open_and_lock_tables(THD *thd, TABLE_LIST *tables)
{
- DBUG_ENTER("open_and_lock_tables");
uint counter;
- if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
- DBUG_RETURN(-1); /* purecov: inspected */
- relink_tables_for_derived(thd);
- DBUG_RETURN(mysql_handle_derived(thd->lex));
+ bool need_reopen;
+ DBUG_ENTER("open_and_lock_tables");
+
+ for ( ; ; )
+ {
+ if (open_tables(thd, &tables, &counter, 0))
+ DBUG_RETURN(-1);
+ if (!lock_tables(thd, tables, counter, &need_reopen))
+ break;
+ if (!need_reopen)
+ DBUG_RETURN(-1);
+ close_tables_for_reopen(thd, tables);
+ }
+ if (mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
+ (thd->fill_derived_tables() &&
+ mysql_handle_derived(thd->lex, &mysql_derived_filling)))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ DBUG_RETURN(0);
}
@@ -1734,6 +2308,9 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
open_normal_and_derived_tables
thd - thread handler
tables - list of tables for open
+ flags - bitmap of flags to modify how the tables will be open:
+ MYSQL_LOCK_IGNORE_FLUSH - open table even if someone has
+ done a flush or namelock on it.
RETURN
FALSE - ok
@@ -1744,36 +2321,36 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
data from the tables.
*/
-int open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables)
+bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags)
{
uint counter;
DBUG_ENTER("open_normal_and_derived_tables");
- if (open_tables(thd, tables, &counter))
- DBUG_RETURN(-1); /* purecov: inspected */
- relink_tables_for_derived(thd);
- DBUG_RETURN(mysql_handle_derived(thd->lex));
+ DBUG_ASSERT(!thd->fill_derived_tables());
+ if (open_tables(thd, &tables, &counter, flags) ||
+ mysql_handle_derived(thd->lex, &mysql_derived_prepare))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ DBUG_RETURN(0);
}
/*
- Let us propagate pointers to open tables from global table list
- to table lists in particular selects if needed.
+ Mark all real tables in the list as free for reuse.
+
+ SYNOPSIS
+ mark_real_tables_as_free_for_reuse()
+ thd - thread context
+ table - head of the list of tables
+
+ DESCRIPTION
+ Marks all real tables in the list (i.e. not views, derived
+ or schema tables) as free for reuse.
*/
-void relink_tables_for_derived(THD *thd)
+static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table)
{
- if (thd->lex->all_selects_list->next_select_in_list() ||
- thd->lex->time_zone_tables_used)
- {
- for (SELECT_LEX *sl= thd->lex->all_selects_list;
- sl;
- sl= sl->next_select_in_list())
- for (TABLE_LIST *cursor= (TABLE_LIST *) sl->table_list.first;
- cursor;
- cursor=cursor->next)
- if (cursor->table_list)
- cursor->table= cursor->table_list->table;
- }
+ for (; table; table= table->next_global)
+ if (!table->placeholder() && !table->schema_table)
+ table->table->query_id= 0;
}
@@ -1784,51 +2361,177 @@ void relink_tables_for_derived(THD *thd)
lock_tables()
thd Thread handler
tables Tables to lock
- count umber of opened tables
+ count Number of opened tables
+ need_reopen Out parameter which if TRUE indicates that some
+ tables were dropped or altered during this call
+ and therefore invoker should reopen tables and
+ try to lock them once again (in this case
+ lock_tables() will also return error).
NOTES
You can't call lock_tables twice, as this would break the dead-lock-free
handling thr_lock gives us. You most always get all needed locks at
once.
+ If query for which we are calling this function marked as requring
+ prelocking, this function will do implicit LOCK TABLES and change
+ thd::prelocked_mode accordingly.
+
RETURN VALUES
0 ok
-1 Error
*/
-int lock_tables(THD *thd, TABLE_LIST *tables, uint count)
+int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
{
TABLE_LIST *table;
+
+ DBUG_ENTER("lock_tables");
+ /*
+ We can't meet statement requiring prelocking if we already
+ in prelocked mode.
+ */
+ DBUG_ASSERT(!thd->prelocked_mode || !thd->lex->requires_prelocking());
+ /*
+ If statement requires prelocking then it has non-empty table list.
+ So it is safe to shortcut.
+ */
+ DBUG_ASSERT(!thd->lex->requires_prelocking() || tables);
+
+ *need_reopen= FALSE;
+
if (!tables)
- return 0;
+ DBUG_RETURN(0);
- if (!thd->locked_tables)
+ /*
+ We need this extra check for thd->prelocked_mode because we want to avoid
+ attempts to lock tables in substatements. Checking for thd->locked_tables
+ is not enough in some situations. For example for SP containing
+ "drop table t3; create temporary t3 ..; insert into t3 ...;"
+ thd->locked_tables may be 0 after drop tables, and without this extra
+ check insert will try to lock temporary table t3, that will lead
+ to memory leak...
+ */
+ if (!thd->locked_tables && !thd->prelocked_mode)
{
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
TABLE **start,**ptr;
- if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count)))
- return -1;
- for (table = tables ; table ; table=table->next)
+
+ if (!(ptr=start=(TABLE**) thd->alloc(sizeof(TABLE*)*count)))
+ DBUG_RETURN(-1);
+ for (table= tables; table; table= table->next_global)
{
- if (!table->derived)
+ if (!table->placeholder() && !table->schema_table)
*(ptr++)= table->table;
}
- if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start), 0)))
- return -1; /* purecov: inspected */
+
+ /* We have to emulate LOCK TABLES if we are statement needs prelocking. */
+ if (thd->lex->requires_prelocking())
+ {
+ thd->in_lock_tables=1;
+ thd->options|= OPTION_TABLE_LOCK;
+ }
+
+ if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start),
+ MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+ need_reopen)))
+ {
+ if (thd->lex->requires_prelocking())
+ {
+ thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+ thd->in_lock_tables=0;
+ }
+ DBUG_RETURN(-1);
+ }
+ if (thd->lex->requires_prelocking() &&
+ thd->lex->sql_command != SQLCOM_LOCK_TABLES)
+ {
+ TABLE_LIST *first_not_own= thd->lex->first_not_own_table();
+ /*
+ We just have done implicit LOCK TABLES, and now we have
+ to emulate first open_and_lock_tables() after it.
+
+ Note that "LOCK TABLES" can also be marked as requiring prelocking
+ (e.g. if one locks view which uses functions). We should not emulate
+ such open_and_lock_tables() in this case. We also should not set
+ THD::prelocked_mode or first close_thread_tables() call will do
+ "UNLOCK TABLES".
+ */
+ thd->locked_tables= thd->lock;
+ thd->lock= 0;
+ thd->in_lock_tables=0;
+
+ for (table= tables; table != first_not_own; table= table->next_global)
+ {
+ if (!table->placeholder() && !table->schema_table)
+ {
+ table->table->query_id= thd->query_id;
+ if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
+ {
+ ha_rollback_stmt(thd);
+ mysql_unlock_tables(thd, thd->locked_tables);
+ thd->locked_tables= 0;
+ thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+ DBUG_RETURN(-1);
+ }
+ }
+ }
+ /*
+ Let us mark all tables which don't belong to the statement itself,
+ and was marked as occupied during open_tables() as free for reuse.
+ */
+ mark_real_tables_as_free_for_reuse(first_not_own);
+ DBUG_PRINT("info",("prelocked_mode= PRELOCKED"));
+ thd->prelocked_mode= PRELOCKED;
+ }
}
else
{
- for (table = tables ; table ; table=table->next)
+ TABLE_LIST *first_not_own= thd->lex->first_not_own_table();
+ for (table= tables; table != first_not_own; table= table->next_global)
{
- if (!table->derived &&
+ if (!table->placeholder() && !table->schema_table &&
check_lock_and_start_stmt(thd, table->table, table->lock_type))
{
ha_rollback_stmt(thd);
- return -1;
+ DBUG_RETURN(-1);
}
}
+ /*
+ If we are under explicit LOCK TABLES and our statement requires
+ prelocking, we should mark all "additional" tables as free for use
+ and enter prelocked mode.
+ */
+ if (thd->lex->requires_prelocking())
+ {
+ mark_real_tables_as_free_for_reuse(first_not_own);
+ DBUG_PRINT("info", ("thd->prelocked_mode= PRELOCKED_UNDER_LOCK_TABLES"));
+ thd->prelocked_mode= PRELOCKED_UNDER_LOCK_TABLES;
+ }
}
- return 0;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Prepare statement for reopening of tables and recalculation of set of
+ prelocked tables.
+
+ SYNOPSIS
+ close_tables_for_reopen()
+ thd Thread context
+ tables List of tables which we were trying to open and lock
+
+*/
+
+void close_tables_for_reopen(THD *thd, TABLE_LIST *tables)
+{
+ thd->lex->chop_off_not_own_tables();
+ sp_remove_not_own_routines(thd->lex);
+ for (TABLE_LIST *tmp= tables; tmp; tmp= tmp->next_global)
+ if (tmp->table && !tmp->table->s->tmp_table)
+ tmp->table= 0;
+ close_thread_tables(thd);
}
@@ -1842,6 +2545,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list)
{
TABLE *tmp_table;
+ TABLE_SHARE *share;
DBUG_ENTER("open_temporary_table");
/*
@@ -1856,7 +2560,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
MYF(MY_WME))))
DBUG_RETURN(0); /* purecov: inspected */
- if (openfrm(path, table_name,
+ if (openfrm(thd, path, table_name,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options,
@@ -1866,21 +2570,22 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
DBUG_RETURN(0);
}
+ share= tmp_table->s;
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);
- tmp_table->key_length= (uint) (strmov((tmp_table->real_name=
- strmov(tmp_table->table_cache_key,db)
- +1), table_name)
- - tmp_table->table_cache_key)+1;
- int4store(tmp_table->table_cache_key + tmp_table->key_length,
- thd->server_id);
- tmp_table->key_length += 4;
- int4store(tmp_table->table_cache_key + tmp_table->key_length,
+ share->tmp_table= (tmp_table->file->has_transactions() ?
+ TRANSACTIONAL_TMP_TABLE : TMP_TABLE);
+ share->table_cache_key= (char*) (tmp_table+1);
+ share->db= share->table_cache_key;
+ share->key_length= (uint) (strmov(((char*) (share->table_name=
+ strmov(share->table_cache_key,
+ db)+1)),
+ table_name) -
+ share->table_cache_key) +1;
+ int4store(share->table_cache_key + share->key_length, thd->server_id);
+ share->key_length+= 4;
+ int4store(share->table_cache_key + share->key_length,
thd->variables.pseudo_thread_id);
- tmp_table->key_length += 4;
+ share->key_length+= 4;
if (link_in_list)
{
@@ -1916,31 +2621,278 @@ bool rm_temporary_table(enum db_type base, char *path)
/*****************************************************************************
-** find field in list or tables. if field is unqualifed and unique,
-** return unique field
+* The following find_field_in_XXX procedures implement the core of the
+* name resolution functionality. The entry point to resolve a column name in a
+* list of tables is 'find_field_in_tables'. It calls 'find_field_in_table_ref'
+* for each table reference. In turn, depending on the type of table reference,
+* 'find_field_in_table_ref' calls one of the 'find_field_in_XXX' procedures
+* below specific for the type of table reference.
******************************************************************************/
+/* Special Field pointers as return values of find_field_in_XXX functions. */
+Field *not_found_field= (Field*) 0x1;
+Field *view_ref_found= (Field*) 0x2;
+
#define WRONG_GRANT (Field*) -1
-Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
- bool check_grants, bool allow_rowid,
- uint *cached_field_index_ptr)
+static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
+{
+ if (thd->set_query_id)
+ {
+ if (field->query_id != thd->query_id)
+ {
+ field->query_id= thd->query_id;
+ table->used_fields++;
+ table->used_keys.intersect(field->part_of_key);
+ }
+ else
+ thd->dupp_field= field;
+ }
+}
+
+
+/*
+ Find a field by name in a view that uses merge algorithm.
+
+ SYNOPSIS
+ find_field_in_view()
+ thd thread handler
+ table_list view to search for 'name'
+ name name of field
+ item_name name of item if it will be created (VIEW)
+ length length of name
+ ref expression substituted in VIEW should be passed
+ using this reference (return view_ref_found)
+ check_grants do check columns grants for view?
+ register_tree_change TRUE if ref is not stack variable and we
+ need register changes in item tree
+
+ RETURN
+ 0 field is not found
+ view_ref_found found value in VIEW (real result is in *ref)
+ # pointer to field - only for schema table fields
+*/
+
+static Field *
+find_field_in_view(THD *thd, TABLE_LIST *table_list,
+ const char *name, const char *item_name,
+ uint length, Item **ref, bool check_grants,
+ bool register_tree_change)
+{
+ DBUG_ENTER("find_field_in_view");
+ DBUG_PRINT("enter",
+ ("view: '%s', field name: '%s', item name: '%s', ref 0x%lx",
+ table_list->alias, name, item_name, (ulong) ref));
+ Field_iterator_view field_it;
+ field_it.set(table_list);
+ Query_arena *arena, backup;
+
+ DBUG_ASSERT(table_list->schema_table_reformed ||
+ (ref != 0 && table_list->view != 0));
+ for (; !field_it.end_of_fields(); field_it.next())
+ {
+ if (!my_strcasecmp(system_charset_info, field_it.name(), name))
+ {
+ if (table_list->schema_table_reformed)
+ /*
+ Translation table items are always Item_fields and fixed already
+ ('mysql_schema_table' function). So we can return ->field. It is
+ used only for 'show & where' commands.
+ */
+ DBUG_RETURN(((Item_field*) (field_it.item()))->field);
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (check_grants &&
+ check_grant_column(thd, &table_list->grant,
+ table_list->view_db.str,
+ table_list->view_name.str,
+ name, length))
+ DBUG_RETURN(WRONG_GRANT);
+#endif
+ // in PS use own arena or data will be freed after prepare
+ if (register_tree_change)
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+ Item *item= field_it.create_item(thd);
+ if (register_tree_change && arena)
+ thd->restore_active_arena(arena, &backup);
+
+ if (!item)
+ DBUG_RETURN(0);
+ /*
+ *ref != NULL means that *ref contains the item that we need to
+ replace. If the item was aliased by the user, set the alias to
+ the replacing item.
+ We need to set alias on both ref itself and on ref real item.
+ */
+ if (*ref && !(*ref)->is_autogenerated_name)
+ {
+ item->set_name((*ref)->name, (*ref)->name_length,
+ system_charset_info);
+ item->real_item()->set_name((*ref)->name, (*ref)->name_length,
+ system_charset_info);
+ }
+ if (register_tree_change)
+ thd->change_item_tree(ref, item);
+ else
+ *ref= item;
+ DBUG_RETURN((Field*) view_ref_found);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Find field by name in a NATURAL/USING join table reference.
+
+ SYNOPSIS
+ find_field_in_natural_join()
+ thd [in] thread handler
+ table_ref [in] table reference to search
+ name [in] name of field
+ length [in] length of name
+ ref [in/out] if 'name' is resolved to a view field, ref is
+ set to point to the found view field
+ check_grants [in] do check columns grants?
+ register_tree_change [in] TRUE if ref is not stack variable and we
+ need register changes in item tree
+ actual_table [out] the original table reference where the field
+ belongs - differs from 'table_list' only for
+ NATURAL/USING joins
+
+ DESCRIPTION
+ Search for a field among the result fields of a NATURAL/USING join.
+ Notice that this procedure is called only for non-qualified field
+ names. In the case of qualified fields, we search directly the base
+ tables of a natural join.
+
+ RETURN
+ NULL if the field was not found
+ WRONG_GRANT if no access rights to the found field
+ # Pointer to the found Field
+*/
+
+static Field *
+find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
+ uint length, Item **ref, bool check_grants,
+ bool register_tree_change,
+ TABLE_LIST **actual_table)
+{
+ List_iterator_fast<Natural_join_column>
+ field_it(*(table_ref->join_columns));
+ Natural_join_column *nj_col;
+ Field *found_field;
+ Query_arena *arena, backup;
+
+ DBUG_ENTER("find_field_in_natural_join");
+ DBUG_PRINT("enter", ("field name: '%s', ref 0x%lx",
+ name, (ulong) ref));
+ DBUG_ASSERT(table_ref->is_natural_join && table_ref->join_columns);
+ DBUG_ASSERT(*actual_table == NULL);
+
+ LINT_INIT(found_field);
+
+ for (;;)
+ {
+ if (!(nj_col= field_it++))
+ DBUG_RETURN(NULL);
+
+ if (!my_strcasecmp(system_charset_info, nj_col->name(), name))
+ break;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (check_grants && nj_col->check_grants(thd, name, length))
+ DBUG_RETURN(WRONG_GRANT);
+#endif
+
+ if (nj_col->view_field)
+ {
+ /*
+ The found field is a view field, we do as in find_field_in_view()
+ and return a pointer to pointer to the Item of that field.
+ */
+ if (register_tree_change)
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+
+ Item *item= nj_col->create_item(thd);
+
+ if (register_tree_change && arena)
+ thd->restore_active_arena(arena, &backup);
+
+ if (!item)
+ DBUG_RETURN(NULL);
+ DBUG_ASSERT(nj_col->table_field == NULL);
+ if (nj_col->table_ref->schema_table_reformed)
+ {
+ /*
+ Translation table items are always Item_fields and fixed
+ already('mysql_schema_table' function). So we can return
+ ->field. It is used only for 'show & where' commands.
+ */
+ DBUG_RETURN(((Item_field*) (nj_col->view_field->item))->field);
+ }
+ if (register_tree_change)
+ thd->change_item_tree(ref, item);
+ else
+ *ref= item;
+ found_field= (Field*) view_ref_found;
+ }
+ else
+ {
+ /* This is a base table. */
+ DBUG_ASSERT(nj_col->view_field == NULL);
+ DBUG_ASSERT(nj_col->table_ref->table == nj_col->table_field->table);
+ found_field= nj_col->table_field;
+ update_field_dependencies(thd, found_field, nj_col->table_ref->table);
+ }
+
+ *actual_table= nj_col->table_ref;
+
+ DBUG_RETURN(found_field);
+}
+
+
+/*
+ Find field by name in a base table or a view with temp table algorithm.
+
+ SYNOPSIS
+ find_field_in_table()
+ thd thread handler
+ table table where to search for the field
+ name name of field
+ length length of name
+ check_grants do check columns grants?
+ allow_rowid do allow finding of "_rowid" field?
+ cached_field_index_ptr cached position in field list (used to speedup
+ lookup for fields in prepared tables)
+
+ RETURN
+ 0 field is not found
+ # pointer to field
+*/
+
+Field *
+find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
+ bool check_grants, bool allow_rowid,
+ uint *cached_field_index_ptr)
{
Field **field_ptr, *field;
uint cached_field_index= *cached_field_index_ptr;
+ DBUG_ENTER("find_field_in_table");
+ DBUG_PRINT("enter", ("table: '%s', field name: '%s'", table->alias, name));
/* We assume here that table->field < NO_CACHED_FIELD_INDEX = UINT_MAX */
- if (cached_field_index < table->fields &&
+ if (cached_field_index < table->s->fields &&
!my_strcasecmp(system_charset_info,
table->field[cached_field_index]->field_name, name))
field_ptr= table->field + cached_field_index;
- else if (table->name_hash.records)
- field_ptr= (Field**)hash_search(&table->name_hash,(byte*) name,
- length);
+ else if (table->s->name_hash.records)
+ field_ptr= (Field**) hash_search(&table->s->name_hash, (byte*) name,
+ length);
else
{
if (!(field_ptr= table->field))
- return (Field *)0;
+ DBUG_RETURN((Field *)0);
for (; *field_ptr; ++field_ptr)
if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name, name))
break;
@@ -1956,25 +2908,149 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
if (!allow_rowid ||
my_strcasecmp(system_charset_info, name, "_rowid") ||
!(field=table->rowid_field))
- return (Field*) 0;
+ DBUG_RETURN((Field*) 0);
}
- if (thd->set_query_id)
+ update_field_dependencies(thd, field, table);
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (check_grants && check_grant_column(thd, &table->grant,
+ table->s->db,
+ table->s->table_name, name, length))
+ field= WRONG_GRANT;
+#endif
+ DBUG_RETURN(field);
+}
+
+
+/*
+ Find field in a table reference.
+
+ SYNOPSIS
+ find_field_in_table_ref()
+ thd [in] thread handler
+ table_list [in] table reference to search
+ name [in] name of field
+ item_name [in] name of item if it will be created (VIEW)
+ table_name [in] optional table name that qualifies the field
+ db_name [in] optional database name that qualifies the
+ length [in] field length of name
+ ref [in/out] if 'name' is resolved to a view field, ref
+ is set to point to the found view field
+ check_grants_table [in] do check columns grants for table?
+ check_grants_view [in] do check columns grants for view?
+ allow_rowid [in] do allow finding of "_rowid" field?
+ cached_field_index_ptr [in] cached position in field list (used to
+ speedup lookup for fields in prepared tables)
+ register_tree_change [in] TRUE if ref is not stack variable and we
+ need register changes in item tree
+ actual_table [out] the original table reference where the field
+ belongs - differs from 'table_list' only for
+ NATURAL_USING joins.
+
+ RETURN
+ 0 field is not found
+ view_ref_found found value in VIEW (real result is in *ref)
+ # pointer to field
+*/
+
+Field *
+find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
+ const char *name, const char *item_name,
+ const char *table_name, const char *db_name,
+ uint length, Item **ref,
+ bool check_grants_table, bool check_grants_view,
+ bool allow_rowid, uint *cached_field_index_ptr,
+ bool register_tree_change, TABLE_LIST **actual_table)
+{
+ Field *fld;
+ DBUG_ENTER("find_field_in_table_ref");
+ DBUG_PRINT("enter",
+ ("table: '%s' field name: '%s' item name: '%s' ref 0x%lx",
+ table_list->alias, name, item_name, (ulong) ref));
+
+ /*
+ Check that the table and database that qualify the current field name
+ are the same as the table we are going to search for the field.
+ This is done differently for NATURAL/USING joins or nested joins that
+ are operands of NATURAL/USING joins because there we can't simply
+ compare the qualifying table and database names with the ones of
+ 'table_list' because each field in such a join may originate from a
+ different table.
+ TODO: Ensure that table_name, db_name and tables->db always points to
+ something !
+ */
+ if (!(table_list->nested_join && table_list->join_columns) &&
+ table_name && table_name[0] &&
+ (my_strcasecmp(table_alias_charset, table_list->alias, table_name) ||
+ (db_name && db_name[0] && table_list->db && table_list->db[0] &&
+ strcmp(db_name, table_list->db))))
+ DBUG_RETURN(0);
+
+ *actual_table= NULL;
+ if (table_list->field_translation)
{
- if (field->query_id != thd->query_id)
+ if ((fld= find_field_in_view(thd, table_list, name, item_name, length,
+ ref, check_grants_view,
+ register_tree_change)))
+ *actual_table= table_list;
+ }
+ else if (table_list->nested_join && table_list->join_columns)
+ {
+ /*
+ If this is a NATURAL/USING join, or an operand of such join which is a
+ join itself, and the field name is qualified, then search for the field
+ in the operands of the join.
+ */
+ if (table_name && table_name[0])
{
- field->query_id=thd->query_id;
- table->used_fields++;
- table->used_keys.intersect(field->part_of_key);
+ /*
+ Qualified field; Search for it in the tables used by the natural join.
+ */
+ List_iterator<TABLE_LIST> it(table_list->nested_join->join_list);
+ TABLE_LIST *table;
+ while ((table= it++))
+ {
+ if ((fld= find_field_in_table_ref(thd, table, name, item_name,
+ table_name, db_name, length, ref,
+ check_grants_table,
+ check_grants_view,
+ allow_rowid, cached_field_index_ptr,
+ register_tree_change, actual_table)))
+ DBUG_RETURN(fld);
+ }
+ DBUG_RETURN(0);
}
- else
- thd->dupp_field=field;
+ /*
+ Non-qualified field, search directly in the result columns of the
+ natural join. The condition of the outer IF is true for the top-most
+ natural join, thus if the field is not qualified, we will search
+ directly the top-most NATURAL/USING join.
+ */
+ fld= find_field_in_natural_join(thd, table_list, name, length, ref,
+ /* TIMOUR_TODO: check this with Sanja */
+ check_grants_table || check_grants_view,
+ register_tree_change, actual_table);
}
+ else
+ {
+ if ((fld= find_field_in_table(thd, table_list->table, name, length,
+ check_grants_table, allow_rowid,
+ cached_field_index_ptr)))
+ *actual_table= table_list;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (check_grants && check_grant_column(thd,table,name,length))
- return WRONG_GRANT;
+ /* check for views with temporary table algorithm */
+ if (check_grants_view && table_list->view &&
+ fld && fld != WRONG_GRANT &&
+ check_grant_column(thd, &table_list->grant,
+ table_list->view_db.str,
+ table_list->view_name.str,
+ name, length))
+ fld= WRONG_GRANT;
#endif
- return field;
+ }
+
+ DBUG_RETURN(fld);
}
@@ -1983,58 +3059,109 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
SYNOPSIS
find_field_in_tables()
- thd Pointer to current thread structure
- item Field item that should be found
- tables Tables for scanning
- where Table where field found will be returned via
- this parameter
- report_error If FALSE then do not report error if item not found
- and return not_found_field
+ thd pointer to current thread structure
+ item field item that should be found
+ first_table list of tables to be searched for item
+ last_table end of the list of tables to search for item. If NULL
+ then search to the end of the list 'first_table'.
+ ref if 'item' is resolved to a view field, ref is set to
+ point to the found view field
+ report_error Degree of error reporting:
+ - IGNORE_ERRORS then do not report any error
+ - IGNORE_EXCEPT_NON_UNIQUE report only non-unique
+ fields, suppress all other errors
+ - REPORT_EXCEPT_NON_UNIQUE report all other errors
+ except when non-unique fields were found
+ - REPORT_ALL_ERRORS
+ check_privileges need to check privileges
+ register_tree_change TRUE if ref is not a stack variable and we
+ to need register changes in item tree
RETURN VALUES
- 0 Field is not found or field is not unique- error
- message is reported
- not_found_field Function was called with report_error == FALSE and
- field was not found. no error message reported.
- found field
+ 0 If error: the found field is not unique, or there are
+ no sufficient access priviliges for the found field,
+ or the field is qualified with non-existing table.
+ not_found_field The function was called with report_error ==
+ (IGNORE_ERRORS || IGNORE_EXCEPT_NON_UNIQUE) and a
+ field was not found.
+ view_ref_found View field is found, item passed through ref parameter
+ found field If a item was resolved to some field
*/
-// Special Field pointer for find_field_in_tables returning
-const Field *not_found_field= (Field*) 0x1;
-
Field *
-find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
- TABLE_LIST **where, bool report_error)
+find_field_in_tables(THD *thd, Item_ident *item,
+ TABLE_LIST *first_table, TABLE_LIST *last_table,
+ Item **ref, find_item_error_report_type report_error,
+ bool check_privileges, bool register_tree_change)
{
Field *found=0;
- const char *db=item->db_name;
- const char *table_name=item->table_name;
- const char *name=item->field_name;
+ const char *db= item->db_name;
+ const char *table_name= item->table_name;
+ const char *name= item->field_name;
uint length=(uint) strlen(name);
char name_buff[NAME_LEN+1];
+ TABLE_LIST *cur_table= first_table;
+ TABLE_LIST *actual_table;
bool allow_rowid;
+ if (!table_name || !table_name[0])
+ {
+ table_name= 0; // For easier test
+ db= 0;
+ }
+
+ allow_rowid= table_name || (cur_table && !cur_table->next_local);
+
if (item->cached_table)
{
/*
- This shortcut is used by prepared statements. We assuming that
- TABLE_LIST *tables is not changed during query execution (which
- is true for all queries except RENAME but luckily RENAME doesn't
+ This shortcut is used by prepared statements. We assume that
+ TABLE_LIST *first_table is not changed during query execution (which
+ is true for all queries except RENAME but luckily RENAME doesn't
use fields...) so we can rely on reusing pointer to its member.
- With this optimisation we also miss case when addition of one more
- field makes some prepared query ambiguous and so erronous, but we
+ With this optimization we also miss case when addition of one more
+ field makes some prepared query ambiguous and so erroneous, but we
accept this trade off.
*/
- found= find_field_in_table(thd, item->cached_table->table, name, length,
- test(item->cached_table->
- table->grant.want_privilege),
- 1, &(item->cached_field_index));
-
+ TABLE_LIST *table_ref= item->cached_table;
+ /*
+ The condition (table_ref->view == NULL) ensures that we will call
+ find_field_in_table even in the case of information schema tables
+ when table_ref->field_translation != NULL.
+ */
+ if (table_ref->table && !table_ref->view)
+ found= find_field_in_table(thd, table_ref->table, name, length,
+ test(table_ref->table->
+ grant.want_privilege) &&
+ check_privileges,
+ 1, &(item->cached_field_index));
+ else
+ found= find_field_in_table_ref(thd, table_ref, name, item->name,
+ NULL, NULL, length, ref,
+ (table_ref->table &&
+ test(table_ref->table->grant.
+ want_privilege) &&
+ check_privileges),
+ (test(table_ref->grant.want_privilege) &&
+ check_privileges),
+ 1, &(item->cached_field_index),
+ register_tree_change,
+ &actual_table);
if (found)
{
- (*where)= tables;
if (found == WRONG_GRANT)
- return (Field*) 0;
+ return (Field*) 0;
+ {
+ SELECT_LEX *current_sel= thd->lex->current_select;
+ SELECT_LEX *last_select= table_ref->select_lex;
+ /*
+ If the field was an outer referencee, mark all selects using this
+ sub query as dependent on the outer query
+ */
+ if (current_sel != last_select)
+ mark_select_range_as_dependent(thd, last_select, current_sel,
+ found, *ref, item);
+ }
return found;
}
}
@@ -2042,7 +3169,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (db && lower_case_table_names)
{
/*
- convert database to lower case for comparision.
+ convert database to lower case for comparison.
We can't do this in Item_field as this would change the
'name' of the item which may be used in the select list
*/
@@ -2051,99 +3178,89 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
db= name_buff;
}
- if (table_name && table_name[0])
- { /* Qualified field */
- bool found_table=0;
- for (; tables ; tables=tables->next)
- {
- if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) &&
- (!db || !tables->db || !tables->db[0] || !strcmp(db,tables->db)))
- {
- found_table=1;
- Field *find=find_field_in_table(thd,tables->table,name,length,
- test(tables->table->grant.
- want_privilege),
- 1, &(item->cached_field_index));
- if (find)
- {
- (*where)= item->cached_table= tables;
- if (!tables->cacheable_table)
- item->cached_table= 0;
- if (find == WRONG_GRANT)
- return (Field*) 0;
- if (db || !thd->where)
- return find;
- if (found)
- {
- my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
- item->full_name(),thd->where);
- return (Field*) 0;
- }
- found=find;
- }
- }
- }
- if (found)
- return found;
- if (!found_table && report_error)
- {
- char buff[NAME_LEN*2+1];
- if (db && db[0])
- {
- strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
- table_name=buff;
- }
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- table_name, thd->where);
- }
- else
- if (report_error)
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
- item->full_name(),thd->where);
- else
- return (Field*) not_found_field;
- return (Field*) 0;
- }
- allow_rowid= tables && !tables->next; // Only one table
- for (; tables ; tables=tables->next)
- {
- if (!tables->table)
- {
- if (report_error)
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
- item->full_name(),thd->where);
- return (Field*) not_found_field;
- }
+ if (last_table)
+ last_table= last_table->next_name_resolution_table;
- Field *field=find_field_in_table(thd,tables->table,name,length,
- test(tables->table->grant.want_privilege),
- allow_rowid, &(item->cached_field_index));
- if (field)
+ for (; cur_table != last_table ;
+ cur_table= cur_table->next_name_resolution_table)
+ {
+ Field *cur_field= find_field_in_table_ref(thd, cur_table, name, item->name,
+ table_name, db,
+ length, ref,
+ (cur_table->table &&
+ test(cur_table->table->grant.
+ want_privilege) &&
+ check_privileges),
+ (test(cur_table->grant.
+ want_privilege)
+ && check_privileges),
+ allow_rowid,
+ &(item->cached_field_index),
+ register_tree_change,
+ &actual_table);
+ if (cur_field)
{
- if (field == WRONG_GRANT)
+ if (cur_field == WRONG_GRANT)
return (Field*) 0;
- (*where)= item->cached_table= tables;
- if (!tables->cacheable_table)
- item->cached_table= 0;
+
+ /*
+ Store the original table of the field, which may be different from
+ cur_table in the case of NATURAL/USING join.
+ */
+ item->cached_table= (!actual_table->cacheable_table || found) ?
+ 0 : actual_table;
+
+ DBUG_ASSERT(thd->where);
+ /*
+ If we found a fully qualified field we return it directly as it can't
+ have duplicates.
+ */
+ if (db)
+ return cur_field;
+
if (found)
{
- if (!thd->where) // Returns first found
- break;
- my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
- name,thd->where);
+ if (report_error == REPORT_ALL_ERRORS ||
+ report_error == IGNORE_EXCEPT_NON_UNIQUE)
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ table_name ? item->full_name() : name, thd->where);
return (Field*) 0;
}
- found= field;
+ found= cur_field;
}
}
+
if (found)
return found;
- if (report_error)
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
- MYF(0), item->full_name(), thd->where);
+
+ /*
+ If the field was qualified and there were no tables to search, issue
+ an error that an unknown table was given. The situation is detected
+ as follows: if there were no tables we wouldn't go through the loop
+ and cur_table wouldn't be updated by the loop increment part, so it
+ will be equal to the first table.
+ */
+ if (table_name && (cur_table == first_table) &&
+ (report_error == REPORT_ALL_ERRORS ||
+ report_error == REPORT_EXCEPT_NON_UNIQUE))
+ {
+ char buff[NAME_LEN*2+1];
+ if (db && db[0])
+ {
+ strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
+ table_name=buff;
+ }
+ my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, thd->where);
+ }
else
- return (Field*) not_found_field;
- return (Field*) 0;
+ {
+ if (report_error == REPORT_ALL_ERRORS ||
+ report_error == REPORT_EXCEPT_NON_UNIQUE)
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), thd->where);
+ else
+ found= not_found_field;
+ }
+ return found;
}
@@ -2177,8 +3294,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
found field
*/
-// Special Item pointer for find_item_in_list returning
-const Item **not_found_item= (const Item**) 0x1;
+/* Special Item pointer to serve as a return value from find_item_in_list(). */
+Item **not_found_item= (Item**) 0x1;
Item **
@@ -2193,7 +3310,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
bool found_unaliased_non_uniq= 0;
uint unaliased_counter;
- LINT_INIT(unaliased_counter);
+ LINT_INIT(unaliased_counter); // Dependent on found_unaliased
+
*unaliased= FALSE;
if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM)
@@ -2253,8 +3371,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
unaliased names only and will have duplicate error anyway.
*/
if (report_error != IGNORE_ERRORS)
- my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR),
- MYF(0), find->full_name(), current_thd->where);
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
return (Item**) 0;
}
found_unaliased= li.ref();
@@ -2278,8 +3396,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
if ((*found)->eq(item, 0))
continue; // Same field twice
if (report_error != IGNORE_ERRORS)
- my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR),
- MYF(0), find->full_name(), current_thd->where);
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
return (Item**) 0;
}
found= li.ref();
@@ -2322,8 +3440,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
if (found_unaliased_non_uniq)
{
if (report_error != IGNORE_ERRORS)
- my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR), MYF(0),
- find->full_name(), current_thd->where);
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
return (Item **) 0;
}
if (found_unaliased)
@@ -2338,14 +3456,678 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
if (report_error != REPORT_EXCEPT_NOT_FOUND)
{
if (report_error == REPORT_ALL_ERRORS)
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
- find->full_name(), current_thd->where);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
return (Item **) 0;
}
else
return (Item **) not_found_item;
}
+
+/*
+ Test if a string is a member of a list of strings.
+
+ SYNOPSIS
+ test_if_string_in_list()
+ find the string to look for
+ str_list a list of strings to be searched
+
+ DESCRIPTION
+ Sequentially search a list of strings for a string, and test whether
+ the list contains the same string.
+
+ RETURN
+ TRUE if find is in str_list
+ FALSE otherwise
+*/
+
+static bool
+test_if_string_in_list(const char *find, List<String> *str_list)
+{
+ List_iterator<String> str_list_it(*str_list);
+ String *curr_str;
+ size_t find_length= strlen(find);
+ while ((curr_str= str_list_it++))
+ {
+ if (find_length != curr_str->length())
+ continue;
+ if (!my_strcasecmp(system_charset_info, find, curr_str->ptr()))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
+ Create a new name resolution context for an item so that it is
+ being resolved in a specific table reference.
+
+ SYNOPSIS
+ set_new_item_local_context()
+ thd pointer to current thread
+ item item for which new context is created and set
+ table_ref table ref where an item showld be resolved
+
+ DESCRIPTION
+ Create a new name resolution context for an item, so that the item
+ is resolved only the supplied 'table_ref'.
+
+ RETURN
+ FALSE if all OK
+ TRUE otherwise
+*/
+
+static bool
+set_new_item_local_context(THD *thd, Item_ident *item, TABLE_LIST *table_ref)
+{
+ Name_resolution_context *context;
+ if (!(context= new (thd->mem_root) Name_resolution_context))
+ return TRUE;
+ context->init();
+ context->first_name_resolution_table=
+ context->last_name_resolution_table= table_ref;
+ item->context= context;
+ return FALSE;
+}
+
+
+/*
+ Find and mark the common columns of two table references.
+
+ SYNOPSIS
+ mark_common_columns()
+ thd [in] current thread
+ table_ref_1 [in] the first (left) join operand
+ table_ref_2 [in] the second (right) join operand
+ using_fields [in] if the join is JOIN...USING - the join columns,
+ if NATURAL join, then NULL
+ found_using_fields [out] number of fields from the USING clause that were
+ found among the common fields
+
+ DESCRIPTION
+ The procedure finds the common columns of two relations (either
+ tables or intermediate join results), and adds an equi-join condition
+ to the ON clause of 'table_ref_2' for each pair of matching columns.
+ If some of table_ref_XXX represents a base table or view, then we
+ create new 'Natural_join_column' instances for each column
+ reference and store them in the 'join_columns' of the table
+ reference.
+
+ IMPLEMENTATION
+ The procedure assumes that store_natural_using_join_columns() was
+ called for the previous level of NATURAL/USING joins.
+
+ RETURN
+ TRUE error when some common column is non-unique, or out of memory
+ FALSE OK
+*/
+
+static bool
+mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
+ List<String> *using_fields, uint *found_using_fields)
+{
+ Field_iterator_table_ref it_1, it_2;
+ Natural_join_column *nj_col_1, *nj_col_2;
+ const char *field_name_1;
+ Query_arena *arena, backup;
+ bool add_columns= TRUE;
+ bool result= TRUE;
+
+ DBUG_ENTER("mark_common_columns");
+ DBUG_PRINT("info", ("operand_1: %s operand_2: %s",
+ table_ref_1->alias, table_ref_2->alias));
+
+ *found_using_fields= 0;
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+
+ /*
+ TABLE_LIST::join_columns could be allocated by the previous call to
+ store_natural_using_join_columns() for the lower level of nested tables.
+ */
+ if (!table_ref_1->join_columns)
+ {
+ if (!(table_ref_1->join_columns= new List<Natural_join_column>))
+ goto err;
+ table_ref_1->is_join_columns_complete= FALSE;
+ }
+ if (!table_ref_2->join_columns)
+ {
+ if (!(table_ref_2->join_columns= new List<Natural_join_column>))
+ goto err;
+ table_ref_2->is_join_columns_complete= FALSE;
+ }
+
+ for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next())
+ {
+ bool is_created_1;
+ bool found= FALSE;
+ if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created_1)))
+ goto err;
+ field_name_1= nj_col_1->name();
+
+ /* If nj_col_1 was just created add it to the list of join columns. */
+ if (is_created_1)
+ table_ref_1->join_columns->push_back(nj_col_1);
+
+ /*
+ Find a field with the same name in table_ref_2.
+
+ Note that for the second loop, it_2.set() will iterate over
+ table_ref_2->join_columns and not generate any new elements or
+ lists.
+ */
+ nj_col_2= NULL;
+ for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next())
+ {
+ bool is_created_2;
+ Natural_join_column *cur_nj_col_2;
+ const char *cur_field_name_2;
+ if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, &is_created_2)))
+ goto err;
+ cur_field_name_2= cur_nj_col_2->name();
+
+ /* If nj_col_1 was just created add it to the list of join columns. */
+ if (add_columns && is_created_2)
+ table_ref_2->join_columns->push_back(cur_nj_col_2);
+
+ /*
+ Compare the two columns and check for duplicate common fields.
+ A common field is duplicate either if it was already found in
+ table_ref_2 (then found == TRUE), or if a field in table_ref_2
+ was already matched by some previous field in table_ref_1
+ (then cur_nj_col_2->is_common == TRUE).
+ */
+ if (!my_strcasecmp(system_charset_info, field_name_1, cur_field_name_2))
+ {
+ if (found || cur_nj_col_2->is_common)
+ {
+ my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, thd->where);
+ goto err;
+ }
+ nj_col_2= cur_nj_col_2;
+ found= TRUE;
+ }
+ }
+ /* Force it_2.set() to use table_ref_2->join_columns. */
+ table_ref_2->is_join_columns_complete= TRUE;
+ add_columns= FALSE;
+ if (!found)
+ continue; // No matching field
+
+ /*
+ field_1 and field_2 have the same names. Check if they are in the USING
+ clause (if present), mark them as common fields, and add a new
+ equi-join condition to the ON clause.
+ */
+ if (nj_col_2 &&
+ (!using_fields ||
+ test_if_string_in_list(field_name_1, using_fields)))
+ {
+ Item *item_1= nj_col_1->create_item(thd);
+ Item *item_2= nj_col_2->create_item(thd);
+ Field *field_1= nj_col_1->field();
+ Field *field_2= nj_col_2->field();
+ Item_ident *item_ident_1, *item_ident_2;
+ Item_func_eq *eq_cond;
+
+ if (!item_1 || !item_2)
+ goto err; // out of memory
+
+ /*
+ The following assert checks that the two created items are of
+ type Item_ident.
+ */
+ DBUG_ASSERT(!thd->lex->current_select->no_wrap_view_item);
+ /*
+ In the case of no_wrap_view_item == 0, the created items must be
+ of sub-classes of Item_ident.
+ */
+ DBUG_ASSERT(item_1->type() == Item::FIELD_ITEM ||
+ item_1->type() == Item::REF_ITEM);
+ DBUG_ASSERT(item_2->type() == Item::FIELD_ITEM ||
+ item_2->type() == Item::REF_ITEM);
+
+ /*
+ We need to cast item_1,2 to Item_ident, because we need to hook name
+ resolution contexts specific to each item.
+ */
+ item_ident_1= (Item_ident*) item_1;
+ item_ident_2= (Item_ident*) item_2;
+ /*
+ Create and hook special name resolution contexts to each item in the
+ new join condition . We need this to both speed-up subsequent name
+ resolution of these items, and to enable proper name resolution of
+ the items during the execute phase of PS.
+ */
+ if (set_new_item_local_context(thd, item_ident_1, nj_col_1->table_ref) ||
+ set_new_item_local_context(thd, item_ident_2, nj_col_2->table_ref))
+ goto err;
+
+ if (!(eq_cond= new Item_func_eq(item_ident_1, item_ident_2)))
+ goto err; /* Out of memory. */
+
+ /*
+ Add the new equi-join condition to the ON clause. Notice that
+ fix_fields() is applied to all ON conditions in setup_conds()
+ so we don't do it here.
+ */
+ add_join_on((table_ref_1->outer_join & JOIN_TYPE_RIGHT ?
+ table_ref_1 : table_ref_2),
+ eq_cond);
+
+ nj_col_1->is_common= nj_col_2->is_common= TRUE;
+
+ if (field_1)
+ {
+ /* Mark field_1 used for table cache. */
+ field_1->query_id= thd->query_id;
+ nj_col_1->table_ref->table->used_keys.intersect(field_1->part_of_key);
+ }
+ if (field_2)
+ {
+ /* Mark field_2 used for table cache. */
+ field_2->query_id= thd->query_id;
+ nj_col_2->table_ref->table->used_keys.intersect(field_2->part_of_key);
+ }
+
+ if (using_fields != NULL)
+ ++(*found_using_fields);
+ }
+ }
+ table_ref_1->is_join_columns_complete= TRUE;
+
+ /*
+ Everything is OK.
+ Notice that at this point there may be some column names in the USING
+ clause that are not among the common columns. This is an SQL error and
+ we check for this error in store_natural_using_join_columns() when
+ (found_using_fields < length(join_using_fields)).
+ */
+ result= FALSE;
+
+err:
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ DBUG_RETURN(result);
+}
+
+
+
+/*
+ Materialize and store the row type of NATURAL/USING join.
+
+ SYNOPSIS
+ store_natural_using_join_columns()
+ thd current thread
+ natural_using_join the table reference of the NATURAL/USING join
+ table_ref_1 the first (left) operand (of a NATURAL/USING join).
+ table_ref_2 the second (right) operand (of a NATURAL/USING join).
+ using_fields if the join is JOIN...USING - the join columns,
+ if NATURAL join, then NULL
+ found_using_fields number of fields from the USING clause that were
+ found among the common fields
+
+ DESCRIPTION
+ Iterate over the columns of both join operands and sort and store
+ all columns into the 'join_columns' list of natural_using_join
+ where the list is formed by three parts:
+ part1: The coalesced columns of table_ref_1 and table_ref_2,
+ sorted according to the column order of the first table.
+ part2: The other columns of the first table, in the order in
+ which they were defined in CREATE TABLE.
+ part3: The other columns of the second table, in the order in
+ which they were defined in CREATE TABLE.
+ Time complexity - O(N1+N2), where Ni = length(table_ref_i).
+
+ IMPLEMENTATION
+ The procedure assumes that mark_common_columns() has been called
+ for the join that is being processed.
+
+ RETURN
+ TRUE error: Some common column is ambiguous
+ FALSE OK
+*/
+
+static bool
+store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
+ TABLE_LIST *table_ref_1,
+ TABLE_LIST *table_ref_2,
+ List<String> *using_fields,
+ uint found_using_fields)
+{
+ Field_iterator_table_ref it_1, it_2;
+ Natural_join_column *nj_col_1, *nj_col_2;
+ bool is_created;
+ Query_arena *arena, backup;
+ bool result= TRUE;
+ List<Natural_join_column> *non_join_columns;
+ DBUG_ENTER("store_natural_using_join_columns");
+
+ DBUG_ASSERT(!natural_using_join->join_columns);
+
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+
+ if (!(non_join_columns= new List<Natural_join_column>) ||
+ !(natural_using_join->join_columns= new List<Natural_join_column>))
+ goto err;
+
+ /* Append the columns of the first join operand. */
+ for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next())
+ {
+ if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created)))
+ goto err;
+ /*
+ The following assert checks that mark_common_columns() was run and
+ we created the list table_ref_1->join_columns.
+ */
+ DBUG_ASSERT(!is_created);
+ if (nj_col_1->is_common)
+ {
+ natural_using_join->join_columns->push_back(nj_col_1);
+ /* Reset the common columns for the next call to mark_common_columns. */
+ nj_col_1->is_common= FALSE;
+ }
+ else
+ non_join_columns->push_back(nj_col_1);
+ }
+
+ /*
+ Check that all columns in the USING clause are among the common
+ columns. If this is not the case, report the first one that was
+ not found in an error.
+ */
+ if (using_fields && found_using_fields < using_fields->elements)
+ {
+ String *using_field_name;
+ List_iterator_fast<String> using_fields_it(*using_fields);
+ while ((using_field_name= using_fields_it++))
+ {
+ const char *using_field_name_ptr= using_field_name->c_ptr();
+ List_iterator_fast<Natural_join_column>
+ it(*(natural_using_join->join_columns));
+ Natural_join_column *common_field;
+
+ for (;;)
+ {
+ /* If reached the end of fields, and none was found, report error. */
+ if (!(common_field= it++))
+ {
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), using_field_name_ptr,
+ current_thd->where);
+ goto err;
+ }
+ if (!my_strcasecmp(system_charset_info,
+ common_field->name(), using_field_name_ptr))
+ break; // Found match
+ }
+ }
+ }
+
+ /* Append the non-equi-join columns of the second join operand. */
+ for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next())
+ {
+ if (!(nj_col_2= it_2.get_or_create_column_ref(thd, &is_created)))
+ goto err;
+ /*
+ The following assert checks that mark_common_columns() was run and
+ we created the list table_ref_2->join_columns.
+ */
+ DBUG_ASSERT(!is_created);
+ if (!nj_col_2->is_common)
+ non_join_columns->push_back(nj_col_2);
+ else
+ {
+ /* Reset the common columns for the next call to mark_common_columns. */
+ nj_col_2->is_common= FALSE;
+ }
+ }
+
+ if (non_join_columns->elements > 0)
+ natural_using_join->join_columns->concat(non_join_columns);
+ natural_using_join->is_join_columns_complete= TRUE;
+
+ result= FALSE;
+
+err:
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Precompute and store the row types of the top-most NATURAL/USING joins.
+
+ SYNOPSIS
+ store_top_level_join_columns()
+ thd current thread
+ table_ref nested join or table in a FROM clause
+ left_neighbor neighbor table reference to the left of table_ref at the
+ same level in the join tree
+ right_neighbor neighbor table reference to the right of table_ref at the
+ same level in the join tree
+
+ DESCRIPTION
+ The procedure performs a post-order traversal of a nested join tree
+ and materializes the row types of NATURAL/USING joins in a
+ bottom-up manner until it reaches the TABLE_LIST elements that
+ represent the top-most NATURAL/USING joins. The procedure should be
+ applied to each element of SELECT_LEX::top_join_list (i.e. to each
+ top-level element of the FROM clause).
+
+ IMPLEMENTATION
+ Notice that the table references in the list nested_join->join_list
+ are in reverse order, thus when we iterate over it, we are moving
+ from the right to the left in the FROM clause.
+
+ RETURN
+ TRUE Error
+ FALSE OK
+*/
+
+static bool
+store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref,
+ TABLE_LIST *left_neighbor,
+ TABLE_LIST *right_neighbor)
+{
+ Query_arena *arena, backup;
+ bool result= TRUE;
+
+ DBUG_ENTER("store_top_level_join_columns");
+
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+
+ /* Call the procedure recursively for each nested table reference. */
+ if (table_ref->nested_join)
+ {
+ List_iterator_fast<TABLE_LIST> nested_it(table_ref->nested_join->join_list);
+ TABLE_LIST *cur_left_neighbor= nested_it++;
+ TABLE_LIST *cur_right_neighbor= NULL;
+
+ while (cur_left_neighbor)
+ {
+ TABLE_LIST *cur_table_ref= cur_left_neighbor;
+ cur_left_neighbor= nested_it++;
+ /*
+ The order of RIGHT JOIN operands is reversed in 'join list' to
+ transform it into a LEFT JOIN. However, in this procedure we need
+ the join operands in their lexical order, so below we reverse the
+ join operands. Notice that this happens only in the first loop, and
+ not in the second one, as in the second loop cur_left_neighbor == NULL.
+ This is the correct behavior, because the second loop
+ sets cur_table_ref reference correctly after the join operands are
+ swapped in the first loop.
+ */
+ if (cur_left_neighbor &&
+ cur_table_ref->outer_join & JOIN_TYPE_RIGHT)
+ {
+ /* This can happen only for JOIN ... ON. */
+ DBUG_ASSERT(table_ref->nested_join->join_list.elements == 2);
+ swap_variables(TABLE_LIST*, cur_left_neighbor, cur_table_ref);
+ }
+
+ if (cur_table_ref->nested_join &&
+ store_top_level_join_columns(thd, cur_table_ref,
+ cur_left_neighbor, cur_right_neighbor))
+ goto err;
+ cur_right_neighbor= cur_table_ref;
+ }
+ }
+
+ /*
+ If this is a NATURAL/USING join, materialize its result columns and
+ convert to a JOIN ... ON.
+ */
+ if (table_ref->is_natural_join)
+ {
+ DBUG_ASSERT(table_ref->nested_join &&
+ table_ref->nested_join->join_list.elements == 2);
+ List_iterator_fast<TABLE_LIST> operand_it(table_ref->nested_join->join_list);
+ /*
+ Notice that the order of join operands depends on whether table_ref
+ represents a LEFT or a RIGHT join. In a RIGHT join, the operands are
+ in inverted order.
+ */
+ TABLE_LIST *table_ref_2= operand_it++; /* Second NATURAL join operand.*/
+ TABLE_LIST *table_ref_1= operand_it++; /* First NATURAL join operand. */
+ List<String> *using_fields= table_ref->join_using_fields;
+ uint found_using_fields;
+
+ /*
+ The two join operands were interchanged in the parser, change the order
+ back for 'mark_common_columns'.
+ */
+ if (table_ref_2->outer_join & JOIN_TYPE_RIGHT)
+ swap_variables(TABLE_LIST*, table_ref_1, table_ref_2);
+ if (mark_common_columns(thd, table_ref_1, table_ref_2,
+ using_fields, &found_using_fields))
+ goto err;
+
+ /*
+ Swap the join operands back, so that we pick the columns of the second
+ one as the coalesced columns. In this way the coalesced columns are the
+ same as of an equivalent LEFT JOIN.
+ */
+ if (table_ref_1->outer_join & JOIN_TYPE_RIGHT)
+ swap_variables(TABLE_LIST*, table_ref_1, table_ref_2);
+ if (store_natural_using_join_columns(thd, table_ref, table_ref_1,
+ table_ref_2, using_fields,
+ found_using_fields))
+ goto err;
+
+ /*
+ Change NATURAL JOIN to JOIN ... ON. We do this for both operands
+ because either one of them or the other is the one with the
+ natural join flag because RIGHT joins are transformed into LEFT,
+ and the two tables may be reordered.
+ */
+ table_ref_1->natural_join= table_ref_2->natural_join= NULL;
+
+ /* Add a TRUE condition to outer joins that have no common columns. */
+ if (table_ref_2->outer_join &&
+ !table_ref_1->on_expr && !table_ref_2->on_expr)
+ table_ref_2->on_expr= new Item_int((longlong) 1,1); /* Always true. */
+
+ /* Change this table reference to become a leaf for name resolution. */
+ if (left_neighbor)
+ {
+ TABLE_LIST *last_leaf_on_the_left;
+ last_leaf_on_the_left= left_neighbor->last_leaf_for_name_resolution();
+ last_leaf_on_the_left->next_name_resolution_table= table_ref;
+ }
+ if (right_neighbor)
+ {
+ TABLE_LIST *first_leaf_on_the_right;
+ first_leaf_on_the_right= right_neighbor->first_leaf_for_name_resolution();
+ table_ref->next_name_resolution_table= first_leaf_on_the_right;
+ }
+ else
+ table_ref->next_name_resolution_table= NULL;
+ }
+ result= FALSE; /* All is OK. */
+
+err:
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Compute and store the row types of the top-most NATURAL/USING joins
+ in a FROM clause.
+
+ SYNOPSIS
+ setup_natural_join_row_types()
+ thd current thread
+ from_clause list of top-level table references in a FROM clause
+
+ DESCRIPTION
+ Apply the procedure 'store_top_level_join_columns' to each of the
+ top-level table referencs of the FROM clause. Adjust the list of tables
+ for name resolution - context->first_name_resolution_table to the
+ top-most, lef-most NATURAL/USING join.
+
+ IMPLEMENTATION
+ Notice that the table references in 'from_clause' are in reverse
+ order, thus when we iterate over it, we are moving from the right
+ to the left in the FROM clause.
+
+ RETURN
+ TRUE Error
+ FALSE OK
+*/
+static bool setup_natural_join_row_types(THD *thd,
+ List<TABLE_LIST> *from_clause,
+ Name_resolution_context *context)
+{
+ thd->where= "from clause";
+ if (from_clause->elements == 0)
+ return FALSE; /* We come here in the case of UNIONs. */
+
+ /* For stored procedures do not redo work if already done. */
+ if (!context->select_lex->first_execution)
+ return FALSE;
+
+ List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause);
+ TABLE_LIST *table_ref; /* Current table reference. */
+ /* Table reference to the left of the current. */
+ TABLE_LIST *left_neighbor;
+ /* Table reference to the right of the current. */
+ TABLE_LIST *right_neighbor= NULL;
+
+ /* Note that tables in the list are in reversed order */
+ for (left_neighbor= table_ref_it++; left_neighbor ; )
+ {
+ table_ref= left_neighbor;
+ left_neighbor= table_ref_it++;
+ if (store_top_level_join_columns(thd, table_ref,
+ left_neighbor, right_neighbor))
+ return TRUE;
+ if (left_neighbor)
+ {
+ TABLE_LIST *first_leaf_on_the_right;
+ first_leaf_on_the_right= table_ref->first_leaf_for_name_resolution();
+ left_neighbor->next_name_resolution_table= first_leaf_on_the_right;
+ }
+ right_neighbor= table_ref;
+ }
+
+ /*
+ Store the top-most, left-most NATURAL/USING join, so that we start
+ the search from that one instead of context->table_list. At this point
+ right_neighbor points to the left-most top-level table reference in the
+ FROM clause.
+ */
+ DBUG_ASSERT(right_neighbor);
+ context->first_name_resolution_table=
+ right_neighbor->first_leaf_for_name_resolution();
+
+ return FALSE;
+}
+
+
/****************************************************************************
** Expand all '*' in given fields
****************************************************************************/
@@ -2354,27 +4136,29 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list,
uint wild_num)
{
- DBUG_ENTER("setup_wild");
if (!wild_num)
- DBUG_RETURN(0);
+ return(0);
- reg2 Item *item;
+ Item *item;
List_iterator<Item> it(fields);
- Item_arena *arena, backup;
+ Query_arena *arena, backup;
+ DBUG_ENTER("setup_wild");
+
/*
- If we are in preparing prepared statement phase then we have change
- temporary mem_root to statement mem root to save changes of SELECT list
+ Don't use arena if we are not in prepared statements or stored procedures
+ For PS/SP we have to use arena to remember the changes
*/
- arena= thd->change_arena_if_needed(&backup);
+ arena= thd->activate_stmt_arena_if_needed(&backup);
while (wild_num && (item= it++))
- {
+ {
if (item->type() == Item::FIELD_ITEM &&
((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*' &&
!((Item_field*) item)->field)
{
uint elem= fields.elements;
+ bool any_privileges= ((Item_field *) item)->any_privileges;
Item_subselect *subsel= thd->lex->current_select->master_unit()->item;
if (subsel &&
subsel->substype() == Item_subselect::EXISTS_SUBS)
@@ -2386,11 +4170,13 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
*/
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))
+ else if (insert_fields(thd, ((Item_field*) item)->context,
+ ((Item_field*) item)->db_name,
+ ((Item_field*) item)->table_name, &it,
+ any_privileges))
{
- if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
DBUG_RETURN(-1);
}
if (sum_func_list)
@@ -2406,7 +4192,14 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
}
}
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ {
+ /* make * substituting permanent */
+ SELECT_LEX *select_lex= thd->lex->current_select;
+ select_lex->with_wild= 0;
+ select_lex->item_list= fields;
+
+ thd->restore_active_arena(arena, &backup);
+ }
DBUG_RETURN(0);
}
@@ -2414,11 +4207,12 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
** Check that all given fields exists and fill struct with current data
****************************************************************************/
-int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
- List<Item> &fields, bool set_query_id,
- List<Item> *sum_func_list, bool allow_sum_func)
+bool setup_fields(THD *thd, Item **ref_pointer_array,
+ List<Item> &fields, bool set_query_id,
+ List<Item> *sum_func_list, bool allow_sum_func)
{
reg2 Item *item;
+ bool save_set_query_id= thd->set_query_id;
List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields");
@@ -2443,51 +4237,113 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
Item **ref= ref_pointer_array;
while ((item= it++))
{
- if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
+ if (!item->fixed && item->fix_fields(thd, it.ref()) ||
(item= *(it.ref()))->check_cols(1))
- DBUG_RETURN(-1); /* purecov: inspected */
+ {
+ thd->set_query_id= save_set_query_id;
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ }
if (ref)
*(ref++)= item;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(thd, ref_pointer_array, *sum_func_list);
- thd->used_tables|=item->used_tables();
+ thd->used_tables|= item->used_tables();
}
+ thd->set_query_id= save_set_query_id;
DBUG_RETURN(test(thd->net.report_error));
}
/*
+ make list of leaves of join table tree
+
+ SYNOPSIS
+ make_leaves_list()
+ list pointer to pointer on list first element
+ tables table list
+
+ RETURN pointer on pointer to next_leaf of last element
+*/
+
+TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
+{
+ for (TABLE_LIST *table= tables; table; table= table->next_local)
+ {
+ if (table->view && table->effective_algorithm == VIEW_ALGORITHM_MERGE)
+ list= make_leaves_list(list, table->ancestor);
+ else
+ {
+ *list= table;
+ list= &table->next_leaf;
+ }
+ }
+ return list;
+}
+
+/*
prepare tables
SYNOPSIS
setup_tables()
- tables table list
-
+ thd Thread handler
+ context name resolution contest to setup table list there
+ from_clause Top-level list of table references in the FROM clause
+ tables Table list (select_lex->table_list)
+ conds Condition of current SELECT (can be changed by VIEW)
+ leaves List of join table leaves list (select_lex->leaf_tables)
+ refresh It is onle refresh for subquery
+ select_insert It is SELECT ... INSERT command
- NOTE
- Remap table numbers if INSERT ... SELECT
- Check also that the 'used keys' and 'ignored keys' exists and set up the
- table structure accordingly
+ NOTE
+ Check also that the 'used keys' and 'ignored keys' exists and set up the
+ table structure accordingly.
+ Create a list of leaf tables. For queries with NATURAL/USING JOINs,
+ compute the row types of the top most natural/using join table references
+ and link these into a list of table references for name resolution.
- This has to be called for all tables that are used by items, as otherwise
- table->map is not set and all Item_field will be regarded as const items.
+ This has to be called for all tables that are used by items, as otherwise
+ table->map is not set and all Item_field will be regarded as const items.
- RETURN
- 0 ok; In this case *map will includes the choosed index
- 1 error
+ RETURN
+ FALSE ok; In this case *map will includes the chosen index
+ TRUE error
*/
-bool setup_tables(TABLE_LIST *tables)
+bool setup_tables(THD *thd, Name_resolution_context *context,
+ List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
+ Item **conds, TABLE_LIST **leaves, bool select_insert)
{
+ uint tablenr= 0;
DBUG_ENTER("setup_tables");
- uint tablenr=0;
- for (TABLE_LIST *table_list=tables ; table_list ;
- table_list=table_list->next,tablenr++)
+
+ context->table_list= context->first_name_resolution_table= tables;
+
+ /*
+ this is used for INSERT ... SELECT.
+ For select we setup tables except first (and its underlying tables)
+ */
+ TABLE_LIST *first_select_table= (select_insert ?
+ tables->next_local:
+ 0);
+ if (!(*leaves))
+ make_leaves_list(leaves, tables);
+
+ TABLE_LIST *table_list;
+ for (table_list= *leaves;
+ table_list;
+ table_list= table_list->next_leaf, tablenr++)
{
TABLE *table= table_list->table;
+ if (first_select_table &&
+ table_list->top_table() == first_select_table)
+ {
+ /* new counting for SELECT of INSERT ... SELECT command */
+ first_select_table= 0;
+ tablenr= 0;
+ }
setup_table_map(table, table_list, tablenr);
- table->used_keys= table->keys_for_keyread;
+ table->used_keys= table->s->keys_for_keyread;
if (table_list->use_index)
{
key_map map;
@@ -2511,6 +4367,31 @@ bool setup_tables(TABLE_LIST *tables)
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
DBUG_RETURN(1);
}
+ for (table_list= tables;
+ table_list;
+ table_list= table_list->next_local)
+ {
+ if (table_list->ancestor)
+ {
+ DBUG_ASSERT(table_list->view);
+ Query_arena *arena= thd->stmt_arena, backup;
+ bool res;
+ if (arena->is_conventional())
+ arena= 0; // For easier test
+ else
+ thd->set_n_backup_active_arena(arena, &backup);
+ res= table_list->setup_ancestor(thd);
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ if (res)
+ DBUG_RETURN(1);
+ }
+ }
+
+ /* Precompute and store the row types of NATURAL/USING joins. */
+ if (setup_natural_join_row_types(thd, from_clause, context))
+ DBUG_RETURN(1);
+
DBUG_RETURN(0);
}
@@ -2539,11 +4420,13 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
map->clear_all();
while ((name=it++))
{
- if ((pos= find_type(&table->keynames, name->ptr(), name->length(), 1)) <=
- 0)
+ if (table->s->keynames.type_names == 0 ||
+ (pos= find_type(&table->s->keynames, name->ptr(),
+ name->length(), 1)) <=
+ 0)
{
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), name->c_ptr(),
- table->real_name);
+ table->s->table_name);
map->set_all();
return 1;
}
@@ -2553,18 +4436,34 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
}
-/****************************************************************************
- This just drops in all fields instead of current '*' field
- Returns pointer to last inserted field if ok
-****************************************************************************/
+/*
+ Drops in all fields instead of current '*' field
+
+ SYNOPSIS
+ insert_fields()
+ thd Thread handler
+ context Context for name resolution
+ db_name Database name in case of 'database_name.table_name.*'
+ table_name Table name in case of 'table_name.*'
+ it Pointer to '*'
+ any_privileges 0 If we should ensure that we have SELECT privileges
+ for all columns
+ 1 If any privilege is ok
+ RETURN
+ 0 ok 'it' is updated to point at last inserted
+ 1 error. Error message is generated but not sent to client
+*/
bool
-insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
- const char *table_name, List_iterator<Item> *it)
+insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
+ const char *table_name, List_iterator<Item> *it,
+ bool any_privileges)
{
+ Field_iterator_table_ref field_iterator;
+ bool found;
char name_buff[NAME_LEN+1];
- uint found;
DBUG_ENTER("insert_fields");
+ DBUG_PRINT("arena", ("stmt arena: 0x%lx", (ulong)thd->stmt_arena));
if (db_name && lower_case_table_names)
{
@@ -2578,216 +4477,289 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
db_name= name_buff;
}
+ found= FALSE;
- found=0;
- for (; tables ; tables=tables->next)
+ /*
+ If table names are qualified, then loop over all tables used in the query,
+ else treat natural joins as leaves and do not iterate over their underlying
+ tables.
+ */
+ for (TABLE_LIST *tables= (table_name ? context->table_list :
+ context->first_name_resolution_table);
+ tables;
+ tables= (table_name ? tables->next_local :
+ tables->next_name_resolution_table)
+ )
{
- TABLE *table=tables->table;
- if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
- tables->alias) &&
- (!db_name || !strcmp(tables->db,db_name))))
- {
+ Field *field;
+ TABLE *table= tables->table;
+
+ DBUG_ASSERT(tables->is_leaf_for_name_resolution());
+
+ if (table_name && my_strcasecmp(table_alias_charset, table_name,
+ tables->alias) ||
+ (db_name && strcmp(tables->db,db_name)))
+ continue;
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Ensure that we have access right to all columns */
- if (!(table->grant.privilege & SELECT_ACL) &&
- check_grant_all_columns(thd,SELECT_ACL,table))
- DBUG_RETURN(-1);
+ /* Ensure that we have access rights to all fields to be inserted. */
+ if (!((table && (table->grant.privilege & SELECT_ACL) ||
+ tables->view && (tables->grant.privilege & SELECT_ACL))) &&
+ !any_privileges)
+ {
+ field_iterator.set(tables);
+ if (check_grant_all_columns(thd, SELECT_ACL, field_iterator.grant(),
+ field_iterator.db_name(),
+ field_iterator.table_name(),
+ &field_iterator))
+ DBUG_RETURN(TRUE);
+ }
#endif
- Field **ptr=table->field,*field;
- TABLE *natural_join_table= 0;
- thd->used_tables|=table->map;
- if (!table->outer_join &&
- tables->natural_join &&
- !tables->natural_join->table->outer_join)
- natural_join_table= tables->natural_join->table;
- while ((field = *ptr++))
+ /*
+ Update the tables used in the query based on the referenced fields. For
+ views and natural joins this update is performed inside the loop below.
+ */
+ if (table)
+ thd->used_tables|= table->map;
+
+ /*
+ Initialize a generic field iterator for the current table reference.
+ Notice that it is guaranteed that this iterator will iterate over the
+ fields of a single table reference, because 'tables' is a leaf (for
+ name resolution purposes).
+ */
+ field_iterator.set(tables);
+
+ for (; !field_iterator.end_of_fields(); field_iterator.next())
+ {
+ Item *item;
+
+ if (!(item= field_iterator.create_item(thd)))
+ DBUG_RETURN(TRUE);
+
+ if (!found)
{
- uint not_used_field_index= NO_CACHED_FIELD_INDEX;
- /* Skip duplicate field names if NATURAL JOIN is used */
- if (!natural_join_table ||
- !find_field_in_table(thd, natural_join_table, field->field_name,
- strlen(field->field_name), 0, 0,
- &not_used_field_index))
+ found= TRUE;
+ it->replace(item); /* Replace '*' with the first found item. */
+ }
+ else
+ it->after(item); /* Add 'item' to the SELECT list. */
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /*
+ Set privilege information for the fields of newly created views.
+ We have that (any_priviliges == TRUE) if and only if we are creating
+ a view. In the time of view creation we can't use the MERGE algorithm,
+ therefore if 'tables' is itself a view, it is represented by a
+ temporary table. Thus in this case we can be sure that 'item' is an
+ Item_field.
+ */
+ if (any_privileges)
+ {
+ DBUG_ASSERT(tables->field_translation == NULL && table ||
+ tables->is_natural_join);
+ DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
+ Item_field *fld= (Item_field*) item;
+ const char *field_table_name= field_iterator.table_name();
+
+ if (!tables->schema_table &&
+ !(fld->have_privileges=
+ (get_column_grant(thd, field_iterator.grant(),
+ field_iterator.db_name(),
+ field_table_name, fld->field_name) &
+ VIEW_ANY_ACL)))
{
- Item_field *item= new Item_field(thd, field);
- if (!found++)
- (void) it->replace(item); // Replace '*'
- else
- it->after(item);
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "ANY",
+ thd->priv_user, thd->host_or_ip,
+ fld->field_name, field_table_name);
+ DBUG_RETURN(TRUE);
}
- /*
- Mark if field used before in this select.
- Used by 'insert' to verify if a field name is used twice
- */
- if (field->query_id == thd->query_id)
- thd->dupp_field=field;
- field->query_id=thd->query_id;
- table->used_keys.intersect(field->part_of_key);
}
- /* All fields are used */
- table->used_fields=table->fields;
+#endif
+
+ if ((field= field_iterator.field()))
+ {
+ /*
+ Mark if field used before in this select.
+ Used by 'insert' to verify if a field name is used twice.
+ */
+ if (field->query_id == thd->query_id)
+ thd->dupp_field= field;
+ field->query_id= thd->query_id;
+
+ if (table)
+ table->used_keys.intersect(field->part_of_key);
+
+ if (tables->is_natural_join)
+ {
+ bool is_created;
+ TABLE *field_table;
+ /*
+ In this case we are sure that the column ref will not be created
+ because it was already created and stored with the natural join.
+ */
+ Natural_join_column *nj_col;
+ if (!(nj_col= field_iterator.get_or_create_column_ref(thd,
+ &is_created)))
+ DBUG_RETURN(TRUE);
+ DBUG_ASSERT(nj_col->table_field && !is_created);
+ field_table= nj_col->table_ref->table;
+ if (field_table)
+ {
+ thd->used_tables|= field_table->map;
+ field_table->used_keys.intersect(field->part_of_key);
+ field_table->used_fields++;
+ }
+ }
+ }
+ else
+ {
+ thd->used_tables|= item->used_tables();
+ item->walk(&Item::reset_query_id_processor,
+ (byte *)(&thd->query_id));
+ }
}
+ /*
+ In case of stored tables, all fields are considered as used,
+ while in the case of views, the fields considered as used are the
+ ones marked in setup_tables during fix_fields of view columns.
+ For NATURAL joins, used_tables is updated in the IF above.
+ */
+ if (table)
+ table->used_fields= table->s->fields;
}
- if (!found)
- {
- if (!table_name)
- my_error(ER_NO_TABLES_USED,MYF(0));
- else
- my_error(ER_BAD_TABLE_ERROR,MYF(0),table_name);
- }
- DBUG_RETURN(!found);
+ if (found)
+ DBUG_RETURN(FALSE);
+
+ /*
+ TODO: in the case when we skipped all columns because there was a
+ qualified '*', and all columns were coalesced, we have to give a more
+ meaningful message than ER_BAD_TABLE_ERROR.
+ */
+ if (!table_name)
+ my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0));
+ else
+ my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name);
+
+ DBUG_RETURN(TRUE);
}
/*
-** Fix all conditions and outer join expressions
+ Fix all conditions and outer join expressions.
+
+ SYNOPSIS
+ setup_conds()
+ thd thread handler
+ tables list of tables for name resolving (select_lex->table_list)
+ leaves list of leaves of join table tree (select_lex->leaf_tables)
+ conds WHERE clause
+
+ DESCRIPTION
+ TODO
+
+ RETURN
+ TRUE if some error occured (e.g. out of memory)
+ FALSE if all is OK
*/
-int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
+int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
+ COND **conds)
{
- table_map not_null_tables= 0;
- Item_arena *arena= 0, backup;
+ SELECT_LEX *select_lex= thd->lex->current_select;
+ Query_arena *arena= thd->stmt_arena, backup;
+ TABLE_LIST *table= NULL; // For HP compilers
+ /*
+ it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
+ which belong to LEX, i.e. most up SELECT) will be updated by
+ INSERT/UPDATE/LOAD
+ NOTE: using this condition helps to prevent call of prepare_check_option()
+ from subquery of VIEW, because tables of subquery belongs to VIEW
+ (see condition before prepare_check_option() call)
+ */
+ bool it_is_update= (select_lex == &thd->lex->select_lex) &&
+ thd->lex->which_check_option_applicable();
DBUG_ENTER("setup_conds");
+ if (select_lex->conds_processed_with_permanent_arena ||
+ arena->is_conventional())
+ arena= 0; // For easier test
+
thd->set_query_id=1;
- thd->lex->current_select->cond_count= 0;
+ select_lex->cond_count= 0;
+
+ for (table= tables; table; table= table->next_local)
+ {
+ if (table->prepare_where(thd, conds, FALSE))
+ goto err_no_arena;
+ }
+
if (*conds)
{
thd->where="where clause";
- if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) ||
+ if (!(*conds)->fixed && (*conds)->fix_fields(thd, conds) ||
(*conds)->check_cols(1))
- DBUG_RETURN(1);
- not_null_tables= (*conds)->not_null_tables();
+ goto err_no_arena;
}
-
- /* Check if we are using outer joins */
- for (TABLE_LIST *table=tables ; table ; table=table->next)
+ /*
+ Apply fix_fields() to all ON clauses at all levels of nesting,
+ including the ones inside view definitions.
+ */
+ for (table= leaves; table; table= table->next_leaf)
{
- if (table->on_expr)
+ TABLE_LIST *embedded; /* The table at the current level of nesting. */
+ TABLE_LIST *embedding= table; /* The parent nested table reference. */
+ do
{
- /* Make a join an a expression */
- thd->where="on clause";
-
- if (!table->on_expr->fixed &&
- table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
- table->on_expr->check_cols(1))
- DBUG_RETURN(1);
- thd->lex->current_select->cond_count++;
-
- /*
- If it's a normal join or a LEFT JOIN which can be optimized away
- add the ON/USING expression to the WHERE
- */
- if (!table->outer_join ||
- ((table->table->map & not_null_tables) &&
- !(specialflag & SPECIAL_NO_NEW_FUNC)))
+ embedded= embedding;
+ if (embedded->on_expr)
{
- table->outer_join= 0;
- arena= thd->change_arena_if_needed(&backup);
- *conds= and_conds(*conds, table->on_expr);
- table->on_expr=0;
- if (arena)
- {
- thd->restore_backup_item_arena(arena, &backup);
- arena= 0; // Safety if goto err
- }
- if ((*conds) && !(*conds)->fixed &&
- (*conds)->fix_fields(thd, tables, conds))
- DBUG_RETURN(1);
+ /* Make a join an a expression */
+ thd->where="on clause";
+ if (!embedded->on_expr->fixed &&
+ embedded->on_expr->fix_fields(thd, &embedded->on_expr) ||
+ embedded->on_expr->check_cols(1))
+ goto err_no_arena;
+ select_lex->cond_count++;
}
+ embedding= embedded->embedding;
}
- if (table->natural_join)
- {
- arena= thd->change_arena_if_needed(&backup);
- /* Make a join of all fields with have the same name */
- TABLE *t1= table->table;
- TABLE *t2= table->natural_join->table;
- Item_cond_and *cond_and= new Item_cond_and();
- if (!cond_and) // If not out of memory
- goto err;
- cond_and->top_level_item();
-
- Field **t1_field, *t2_field;
- for (t1_field= t1->field; (*t1_field); t1_field++)
- {
- const char *t1_field_name= (*t1_field)->field_name;
- uint not_used_field_index= NO_CACHED_FIELD_INDEX;
-
- if ((t2_field= find_field_in_table(thd, t2, t1_field_name,
- strlen(t1_field_name), 0, 0,
- &not_used_field_index)))
- {
- Item_func_eq *tmp=new Item_func_eq(new Item_field(thd, *t1_field),
- new Item_field(thd, t2_field));
- if (!tmp)
- goto err;
- /* Mark field used for table cache */
- (*t1_field)->query_id= t2_field->query_id= thd->query_id;
- cond_and->list.push_back(tmp);
- t1->used_keys.intersect((*t1_field)->part_of_key);
- t2->used_keys.intersect(t2_field->part_of_key);
- }
- }
- thd->lex->current_select->cond_count+= cond_and->list.elements;
-
- // to prevent natural join processing during PS re-execution
- table->natural_join= 0;
+ while (embedding &&
+ embedding->nested_join->join_list.head() == embedded);
- if (cond_and->list.elements)
- {
- if (!table->outer_join) // Not left join
- {
- *conds= and_conds(*conds, cond_and);
- // fix_fields() should be made with temporary memory pool
- if (arena)
- thd->restore_backup_item_arena(arena, &backup);
- if (*conds && !(*conds)->fixed)
- {
- if (!(*conds)->fixed &&
- (*conds)->fix_fields(thd, tables, conds))
- DBUG_RETURN(1);
- }
- }
- else
- {
- table->on_expr= and_conds(table->on_expr, cond_and);
- // fix_fields() should be made with temporary memory pool
- if (arena)
- thd->restore_backup_item_arena(arena, &backup);
- if (table->on_expr && !table->on_expr->fixed)
- {
- if (!table->on_expr->fixed &&
- table->on_expr->fix_fields(thd, tables, &table->on_expr))
- DBUG_RETURN(1);
- }
- }
- }
- else if (arena)
+ /* process CHECK OPTION */
+ if (it_is_update)
+ {
+ TABLE_LIST *view= table->top_table();
+ if (view->effective_with_check)
{
- thd->restore_backup_item_arena(arena, &backup);
- arena= 0; // Safety if goto err
+ if (view->prepare_check_option(thd))
+ goto err_no_arena;
+ thd->change_item_tree(&table->check_option, view->check_option);
}
}
}
- if (thd->current_arena->is_stmt_prepare())
+ if (!thd->stmt_arena->is_conventional())
{
/*
We are in prepared statement preparation code => we should store
WHERE clause changing for next executions.
- We do this ON -> WHERE transformation only once per PS statement.
+ We do this ON -> WHERE transformation only once per PS/SP statement.
*/
- thd->lex->current_select->where= *conds;
+ select_lex->where= *conds;
+ select_lex->conds_processed_with_permanent_arena= 1;
}
DBUG_RETURN(test(thd->net.report_error));
err:
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ thd->restore_active_arena(arena, &backup);
+err_no_arena:
DBUG_RETURN(1);
}
@@ -2797,8 +4769,25 @@ err:
** Returns : 1 if some field has wrong type
******************************************************************************/
-int
-fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors)
+
+/*
+ Fill fields with given items.
+
+ SYNOPSIS
+ fill_record()
+ thd thread handler
+ fields Item_fields list to be filled
+ values values to fill with
+ ignore_errors TRUE if we should ignore errors
+
+ RETURN
+ FALSE OK
+ TRUE error occured
+*/
+
+static bool
+fill_record(THD * thd, List<Item> &fields, List<Item> &values,
+ bool ignore_errors)
{
List_iterator_fast<Item> f(fields),v(values);
Item *value;
@@ -2813,14 +4802,67 @@ fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors)
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
- DBUG_RETURN(1);
+ {
+ my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
+ DBUG_RETURN(TRUE);
+ }
}
- DBUG_RETURN(0);
+ DBUG_RETURN(thd->net.report_error);
}
-int
-fill_record(Field **ptr,List<Item> &values, bool ignore_errors)
+/*
+ Fill fields in list with values from the list of items and invoke
+ before triggers.
+
+ SYNOPSIS
+ fill_record_n_invoke_before_triggers()
+ thd thread context
+ fields Item_fields list to be filled
+ values values to fill with
+ ignore_errors TRUE if we should ignore errors
+ triggers object holding list of triggers to be invoked
+ event event type for triggers to be invoked
+
+ NOTE
+ This function assumes that fields which values will be set and triggers
+ to be invoked belong to the same table, and that TABLE::record[0] and
+ record[1] buffers correspond to new and old versions of row respectively.
+
+ RETURN
+ FALSE OK
+ TRUE error occured
+*/
+
+bool
+fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
+ List<Item> &values, bool ignore_errors,
+ Table_triggers_list *triggers,
+ enum trg_event_type event)
+{
+ return (fill_record(thd, fields, values, ignore_errors) ||
+ triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE));
+}
+
+
+/*
+ Fill field buffer with values from Field list
+
+ SYNOPSIS
+ fill_record()
+ thd thread handler
+ ptr pointer on pointer to record
+ values list of fields
+ ignore_errors TRUE if we should ignore errors
+
+ RETURN
+ FALSE OK
+ TRUE error occured
+*/
+
+bool
+fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
Item *value;
@@ -2833,10 +4875,45 @@ fill_record(Field **ptr,List<Item> &values, bool ignore_errors)
TABLE *table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
- if ((value->save_in_field(field, 0) < 0) && !ignore_errors)
- DBUG_RETURN(1);
+ if (value->save_in_field(field, 0) == -1)
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(thd->net.report_error);
+}
+
+
+/*
+ Fill fields in array with values from the list of items and invoke
+ before triggers.
+
+ SYNOPSIS
+ fill_record_n_invoke_before_triggers()
+ thd thread context
+ ptr NULL-ended array of fields to be filled
+ values values to fill with
+ ignore_errors TRUE if we should ignore errors
+ triggers object holding list of triggers to be invoked
+ event event type for triggers to be invoked
+
+ NOTE
+ This function assumes that fields which values will be set and triggers
+ to be invoked belong to the same table, and that TABLE::record[0] and
+ record[1] buffers correspond to new and old versions of row respectively.
+
+ RETURN
+ FALSE OK
+ TRUE error occured
+*/
+
+bool
+fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
+ List<Item> &values, bool ignore_errors,
+ Table_triggers_list *triggers,
+ enum trg_event_type event)
+{
+ return (fill_record(thd, ptr, values, ignore_errors) ||
+ triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE));
}
@@ -2884,34 +4961,31 @@ static void mysql_rm_tmp_tables(void)
*****************************************************************************/
/*
-** Invalidate any cache entries that are for some DB
-** We can't use hash_delete when looping hash_elements. We mark them first
-** and afterwards delete those marked unused.
+ Invalidate any cache entries that are for some DB
+
+ SYNOPSIS
+ remove_db_from_cache()
+ db Database name. This will be in lower case if
+ lower_case_table_name is set
+
+ NOTE:
+ We can't use hash_delete when looping hash_elements. We mark them first
+ and afterwards delete those marked unused.
*/
void remove_db_from_cache(const char *db)
{
- char name_buff[NAME_LEN+1];
- if (db && lower_case_table_names)
- {
- /*
- convert database to lower case for comparision.
- */
- strmake(name_buff, db, sizeof(name_buff)-1);
- my_casedn_str(files_charset_info, name_buff);
- db= name_buff;
- }
for (uint idx=0 ; idx < open_cache.records ; idx++)
{
TABLE *table=(TABLE*) hash_element(&open_cache,idx);
- if (!strcmp(table->table_cache_key,db))
+ if (!strcmp(table->s->db, db))
{
- table->version=0L; /* Free when thread is ready */
+ table->s->version= 0L; /* Free when thread is ready */
if (!table->in_use)
relink_unused(table);
}
}
- while (unused_tables && !unused_tables->version)
+ while (unused_tables && !unused_tables->s->version)
VOID(hash_delete(&open_cache,(byte*) unused_tables));
}
@@ -2964,7 +5038,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
{
THD *in_use;
- table->version=0L; /* Free when thread is ready */
+ table->s->version=0L; /* Free when thread is ready */
if (!(in_use=table->in_use))
{
DBUG_PRINT("info",("Table was not in use"));
@@ -2979,7 +5053,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) &&
! in_use->killed)
{
- in_use->killed=1;
+ in_use->killed= THD::KILL_CONNECTION;
pthread_mutex_lock(&in_use->mysys_var->mutex);
if (in_use->mysys_var->current_cond)
{
@@ -3005,7 +5079,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
else
result= result || (flags & RTFC_OWNED_BY_THD_FLAG);
}
- while (unused_tables && !unused_tables->version)
+ while (unused_tables && !unused_tables->s->version)
VOID(hash_delete(&open_cache,(byte*) unused_tables));
if (result && (flags & RTFC_WAIT_OTHER_THREAD_FLAG))
{
@@ -3075,3 +5149,68 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
}
return 0;
}
+
+
+/*
+ open new .frm format table
+
+ SYNOPSIS
+ open_new_frm()
+ path path to .frm
+ alias alias for table
+ db database
+ table_name name of table
+ db_stat open flags (for example HA_OPEN_KEYFILE|HA_OPEN_RNDFILE..)
+ can be 0 (example in ha_example_table)
+ prgflag READ_ALL etc..
+ ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
+ outparam result table
+ table_desc TABLE_LIST descriptor
+ mem_root temporary MEM_ROOT for parsing
+*/
+
+static my_bool
+open_new_frm(const char *path, const char *alias,
+ const char *db, const char *table_name,
+ uint db_stat, uint prgflag,
+ uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc,
+ MEM_ROOT *mem_root)
+{
+ LEX_STRING pathstr;
+ File_parser *parser;
+ DBUG_ENTER("open_new_frm");
+
+ pathstr.str= (char*) path;
+ pathstr.length= strlen(path);
+
+ if ((parser= sql_parse_prepare(&pathstr, mem_root, 1)))
+ {
+ if (is_equal(&view_type, parser->type()))
+ {
+ if (table_desc == 0 || table_desc->required_type == FRMTYPE_TABLE)
+ {
+ my_error(ER_WRONG_OBJECT, MYF(0), db, table_name, "BASE TABLE");
+ goto err;
+ }
+ if (mysql_make_view(parser, table_desc))
+ goto err;
+ }
+ else
+ {
+ /* only VIEWs are supported now */
+ my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), path, parser->type()->str);
+ goto err;
+ }
+ DBUG_RETURN(0);
+ }
+
+err:
+ bzero(outparam, sizeof(TABLE)); // do not run repair
+ DBUG_RETURN(1);
+}
+
+
+bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
+{
+ return a->length == b->length && !strncmp(a->str, b->str, a->length);
+}
diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h
index 2fd603d9381..0f5b6dcd35e 100644
--- a/sql/sql_bitmap.h
+++ b/sql/sql_bitmap.h
@@ -28,7 +28,7 @@ template <uint default_width> class Bitmap
uchar buffer[(default_width+7)/8];
public:
Bitmap() { init(); }
- Bitmap(Bitmap& from) { *this=from; }
+ Bitmap(const Bitmap& from) { *this=from; }
explicit Bitmap(uint prefix_to_set) { init(prefix_to_set); }
void init() { bitmap_init(&map, buffer, default_width, 0); }
void init(uint prefix_to_set) { init(); set_prefix(prefix_to_set); }
@@ -51,6 +51,14 @@ public:
bitmap_init(&map2, (uchar *)&map2buff, sizeof(ulonglong)*8, 0);
bitmap_intersect(&map, &map2);
}
+ /* Use highest bit for all bits above sizeof(ulonglong)*8. */
+ void intersect_extended(ulonglong map2buff)
+ {
+ intersect(map2buff);
+ if (map.bitmap_size > sizeof(ulonglong))
+ bitmap_set_above(&map, sizeof(ulonglong),
+ test(map2buff & (LL(1) << (sizeof(ulonglong) * 8 - 1))));
+ }
void subtract(Bitmap& map2) { bitmap_subtract(&map, &map2.map); }
void merge(Bitmap& map2) { bitmap_union(&map, &map2.map); }
my_bool is_set(uint n) const { return bitmap_is_set(&map, n); }
@@ -61,18 +69,17 @@ public:
my_bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); }
char *print(char *buf) const
{
- char *s=buf; int i;
- for (i=sizeof(buffer)-1; i>=0 ; i--)
- {
- if ((*s=_dig_vec_upper[buffer[i] >> 4]) != '0')
- break;
- if ((*s=_dig_vec_upper[buffer[i] & 15]) != '0')
- break;
- }
- for (s++, i-- ; i>=0 ; i--)
+ char *s=buf;
+ const uchar *e=buffer, *b=e+sizeof(buffer)-1;
+ while (!*b && b>e)
+ b--;
+ if ((*s=_dig_vec_upper[*b >> 4]) != '0')
+ s++;
+ *s++=_dig_vec_upper[*b & 15];
+ while (--b>=e)
{
- *s++=_dig_vec_upper[buffer[i] >> 4];
- *s++=_dig_vec_upper[buffer[i] & 15];
+ *s++=_dig_vec_upper[*b >> 4];
+ *s++=_dig_vec_upper[*b & 15];
}
*s=0;
return buf;
@@ -82,7 +89,7 @@ public:
if (sizeof(buffer) >= 8)
return uint8korr(buffer);
DBUG_ASSERT(sizeof(buffer) >= 4);
- uint4korr(buffer);
+ return (ulonglong) uint4korr(buffer);
}
};
@@ -117,6 +124,7 @@ public:
void clear_all() { map=(ulonglong)0; }
void intersect(Bitmap<64>& map2) { map&= map2.map; }
void intersect(ulonglong map2) { map&= map2; }
+ void intersect_extended(ulonglong map2) { map&= map2; }
void subtract(Bitmap<64>& map2) { map&= ~map2.map; }
void merge(Bitmap<64>& map2) { map|= map2.map; }
my_bool is_set(uint n) const { return test(map & (((ulonglong)1) << n)); }
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 4214c9a7c07..04663c5b096 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -278,7 +278,6 @@ TODO list:
- Move MRG_MYISAM table type processing to handlers, something like:
tables_used->table->file->register_used_filenames(callback,
first_argument);
- - Make derived tables cachable.
- QC improvement suggested by Monty:
- Add a counter in open_table() for how many MERGE (ISAM or MyISAM)
tables are cached in the table cache.
@@ -311,7 +310,7 @@ TODO list:
#include "emb_qcache.h"
#endif
-#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
+#if !defined(EXTRA_DBUG) && !defined(DBUG_OFF)
#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
pthread_mutex_lock(M);}
#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
@@ -615,6 +614,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
DBUG_VOID_RETURN;
}
header->result(result);
+ header->last_pkt_nr= net->pkt_nr;
BLOCK_UNLOCK_WR(query_block);
}
else
@@ -796,10 +796,11 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
Query_cache_query_flags flags;
// fill all gaps between fields with 0 to get repeatable key
bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
- flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ?
- 1 : 0);
- flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ?
- 1 : 0);
+ flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG);
+ flags.client_protocol_41= test(thd->client_capabilities &
+ CLIENT_PROTOCOL_41);
+ flags.more_results_exists= test(thd->server_status &
+ SERVER_MORE_RESULTS_EXISTS);
flags.character_set_client_num=
thd->variables.character_set_client->number;
flags.character_set_results_num=
@@ -813,6 +814,20 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
flags.sql_mode= thd->variables.sql_mode;
flags.max_sort_length= thd->variables.max_sort_length;
flags.group_concat_max_len= thd->variables.group_concat_max_len;
+ DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, \
+CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
+sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
+ (int)flags.client_long_flag,
+ (int)flags.client_protocol_41,
+ (int)flags.more_results_exists,
+ flags.character_set_client_num,
+ flags.character_set_results_num,
+ flags.collation_connection_num,
+ flags.limit,
+ (ulong)flags.time_zone,
+ flags.sql_mode,
+ flags.max_sort_length,
+ flags.group_concat_max_len));
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size == 0)
@@ -930,17 +945,21 @@ end:
0 The query was cached and user was sent the result.
-1 The query was cached but we didn't have rights to use it.
No error is sent to the client yet.
+
+ NOTE
+ This method requires that sql points to allocated memory of size:
+ tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
*/
int
Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
{
+ ulonglong engine_data;
Query_cache_query *query;
Query_cache_block *first_result_block, *result_block;
Query_cache_block_table *block_table, *block_table_end;
ulong tot_length;
Query_cache_query_flags flags;
- bool check_tables;
DBUG_ENTER("Query_cache::send_result_to_client");
if (query_cache_size == 0 || thd->locked_tables ||
@@ -958,11 +977,16 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
/*
Test if the query is a SELECT
- (pre-space is removed in dispatch_command)
+ (pre-space is removed in dispatch_command).
+
+ First '/' looks like comment before command it is not
+ frequently appeared in real lihe, consequently we can
+ check all such queries, too.
*/
- if (my_toupper(system_charset_info, sql[0]) != 'S' ||
- my_toupper(system_charset_info, sql[1]) != 'E' ||
- my_toupper(system_charset_info,sql[2]) !='L')
+ if ((my_toupper(system_charset_info, sql[0]) != 'S' ||
+ my_toupper(system_charset_info, sql[1]) != 'E' ||
+ my_toupper(system_charset_info,sql[2]) !='L') &&
+ sql[0] != '/')
{
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
goto err;
@@ -990,10 +1014,11 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
// fill all gaps between fields with 0 to get repeatable key
bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
- flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ?
- 1 : 0);
- flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ?
- 1 : 0);
+ flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG);
+ flags.client_protocol_41= test(thd->client_capabilities &
+ CLIENT_PROTOCOL_41);
+ flags.more_results_exists= test(thd->server_status &
+ SERVER_MORE_RESULTS_EXISTS);
flags.character_set_client_num= thd->variables.character_set_client->number;
flags.character_set_results_num=
(thd->variables.character_set_results ?
@@ -1005,6 +1030,20 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
flags.sql_mode= thd->variables.sql_mode;
flags.max_sort_length= thd->variables.max_sort_length;
flags.group_concat_max_len= thd->variables.group_concat_max_len;
+ DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, \
+CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
+sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
+ (int)flags.client_long_flag,
+ (int)flags.client_protocol_41,
+ (int)flags.more_results_exists,
+ flags.character_set_client_num,
+ flags.character_set_results_num,
+ flags.collation_connection_num,
+ flags.limit,
+ (ulong)flags.time_zone,
+ flags.sql_mode,
+ flags.max_sort_length,
+ flags.group_concat_max_len));
memcpy((void *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
&flags, QUERY_CACHE_FLAGS_SIZE);
query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
@@ -1043,7 +1082,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
goto err_unlock;
}
- check_tables= query->tables_type() & HA_CACHE_TBL_ASKTRANSACT;
// Check access;
block_table= query_block->table(0);
block_table_end= block_table+query_block->n_tables;
@@ -1051,7 +1089,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
{
TABLE_LIST table_list;
TABLE *tmptable;
-
Query_cache_table *table = block_table->parent;
/*
@@ -1062,8 +1099,9 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
*/
for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next)
{
- if (tmptable->key_length - TMP_TABLE_KEY_EXTRA == table->key_length() &&
- !memcmp(tmptable->table_cache_key, table->data(),
+ if (tmptable->s->key_length - TMP_TABLE_KEY_EXTRA ==
+ table->key_length() &&
+ !memcmp(tmptable->s->table_cache_key, table->data(),
table->key_length()))
{
DBUG_PRINT("qcache",
@@ -1083,7 +1121,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
bzero((char*) &table_list,sizeof(table_list));
table_list.db = table->db();
- table_list.alias= table_list.real_name= table->table();
+ table_list.alias= table_list.table_name= table->table();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_table_access(thd,SELECT_ACL,&table_list,1))
{
@@ -1104,19 +1142,30 @@ 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 && !ha_caching_allowed(thd, table->db(),
- table->key_length(),
- table->type()))
+ engine_data= table->engine_data();
+ if (table->callback() &&
+ !(*table->callback())(thd, table->db(),
+ table->key_length(),
+ &engine_data))
{
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
table_list.db, table_list.alias));
BLOCK_UNLOCK_RD(query_block);
- thd->lex->safe_to_cache_query= 0; // Don't try to cache this
+ if (engine_data != table->engine_data())
+ {
+ DBUG_PRINT("qcache",
+ ("Handler require invalidation queries of %s.%s %lld-%lld",
+ table_list.db, table_list.alias,
+ engine_data, table->engine_data()));
+ invalidate_table((byte *) table->db(), table->key_length());
+ }
+ else
+ thd->lex->safe_to_cache_query= 0; // Don't try to cache this
goto err_unlock; // Parse query
}
else
- DBUG_PRINT("qcache", ("handler allow caching (%d) %s,%s",
- check_tables, table_list.db, table_list.alias));
+ DBUG_PRINT("qcache", ("handler allow caching %s,%s",
+ table_list.db, table_list.alias));
}
move_to_query_list_end(query_block);
hits++;
@@ -1140,6 +1189,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
ALIGN_SIZE(sizeof(Query_cache_result))))
break; // Client aborted
result_block = result_block->next;
+ thd->net.pkt_nr= query->last_pkt_nr; // Keep packet number updated
} while (result_block != first_result_block);
#else
{
@@ -1178,7 +1228,7 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
using_transactions = using_transactions &&
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
- for (; tables_used; tables_used=tables_used->next)
+ for (; tables_used; tables_used= tables_used->next_local)
{
DBUG_ASSERT(!using_transactions || tables_used->table!=0);
if (tables_used->derived)
@@ -1210,7 +1260,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
if (query_cache_size > 0)
{
DUMP(this);
- for (; tables_used; tables_used=tables_used->next)
+ for (; tables_used; tables_used= tables_used->next)
{
invalidate_table((byte*) tables_used->key, tables_used->key_length);
DBUG_PRINT("qcache", (" db %s, table %s", tables_used->key,
@@ -1243,7 +1293,7 @@ void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
if (query_cache_size > 0)
{
DUMP(this);
- for (; tables_used; tables_used= tables_used->next)
+ for (; tables_used; tables_used= tables_used->next_local)
{
if (tables_used->lock_type & (TL_WRITE_LOW_PRIORITY | TL_WRITE))
invalidate_table(tables_used->table);
@@ -2045,7 +2095,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
*/
data_len= len - new_block->length;
prev_block= new_block;
- } while(1);
+ } while (1);
DBUG_RETURN(TRUE);
}
@@ -2068,7 +2118,7 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
uint key_length;
Query_cache_block *table_block;
key_length=(uint) (strmov(strmov(key,table_list->db)+1,
- table_list->real_name) -key)+ 1;
+ table_list->table_name) -key)+ 1;
// We don't store temporary tables => no key_length+=4 ...
if ((table_block = (Query_cache_block*)
@@ -2079,7 +2129,7 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
void Query_cache::invalidate_table(TABLE *table)
{
- invalidate_table((byte*) table->table_cache_key, table->key_length);
+ invalidate_table((byte*) table->s->table_cache_key, table->s->key_length);
}
void Query_cache::invalidate_table(byte * key, uint32 key_length)
@@ -2101,6 +2151,112 @@ void Query_cache::invalidate_table(Query_cache_block *table_block)
}
}
+
+/*
+ Register given table list begining with given position in tables table of
+ block
+
+ SYNOPSIS
+ Query_cache::register_tables_from_list
+ tables_used given table list
+ counter number current position in table of tables of block
+ block_table pointer to current position in tables table of block
+
+ RETURN
+ 0 error
+ number of next position of table entry in table of tables of block
+*/
+
+TABLE_COUNTER_TYPE
+Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
+ TABLE_COUNTER_TYPE counter,
+ Query_cache_block_table *block_table)
+{
+ TABLE_COUNTER_TYPE n;
+ DBUG_ENTER("Query_cache::register_tables_from_list");
+ for (n= counter;
+ tables_used;
+ tables_used= tables_used->next_global, n++, block_table++)
+ {
+ if (tables_used->derived)
+ {
+ DBUG_PRINT("qcache", ("derived table skipped"));
+ n--;
+ block_table--;
+ continue;
+ }
+ block_table->n= n;
+ if (tables_used->view)
+ {
+ char key[MAX_DBKEY_LENGTH];
+ uint key_length;
+ DBUG_PRINT("qcache", ("view %s, db %s",
+ tables_used->view_name.str,
+ tables_used->view_db.str));
+ key_length= (uint) (strmov(strmov(key, tables_used->view_db.str) + 1,
+ tables_used->view_name.str) - key) + 1;
+ /*
+ There are not callback function for for VIEWs
+ */
+ if (!insert_table(key_length, key, block_table,
+ tables_used->view_db.length + 1,
+ HA_CACHE_TBL_NONTRANSACT, 0, 0))
+ DBUG_RETURN(0);
+ {
+ TABLE_COUNTER_TYPE inc= register_tables_from_list(tables_used->ancestor,
+ n + 1,
+ block_table + 1);
+ if (!inc)
+ DBUG_RETURN(0);
+ n+= inc;
+ block_table+= inc;
+ }
+ }
+ else
+ {
+ DBUG_PRINT("qcache",
+ ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
+ tables_used->table->s->table_name,
+ tables_used->table->s->table_cache_key,
+ (ulong) tables_used->table,
+ tables_used->table->s->key_length,
+ (ulong) tables_used->table->s->table_cache_key));
+ if (!insert_table(tables_used->table->s->key_length,
+ tables_used->table->s->table_cache_key, block_table,
+ tables_used->db_length,
+ tables_used->table->file->table_cache_type(),
+ tables_used->callback_func,
+ tables_used->engine_data))
+ DBUG_RETURN(0);
+
+ if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
+ {
+ ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
+ MYRG_INFO *file = handler->myrg_info();
+ for (MYRG_TABLE *table = file->open_tables;
+ table != file->end_table ;
+ table++)
+ {
+ char key[MAX_DBKEY_LENGTH];
+ uint32 db_length;
+ uint key_length= filename_2_table_key(key, table->table->filename,
+ &db_length);
+ (++block_table)->n= ++n;
+ /*
+ There are not callback function for for MyISAM, and engine data
+ */
+ if (!insert_table(key_length, key, block_table,
+ db_length,
+ tables_used->table->file->table_cache_type(),
+ 0, 0))
+ DBUG_RETURN(0);
+ }
+ }
+ }
+ }
+ DBUG_RETURN(n - counter);
+}
+
/*
Store all used tables
@@ -2122,51 +2278,9 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
Query_cache_block_table *block_table = block->table(0);
- for (n=0; tables_used; tables_used=tables_used->next, n++, block_table++)
- {
- if (tables_used->derived)
- {
- DBUG_PRINT("qcache", ("derived table skipped"));
- n--;
- block_table--;
- continue;
- }
- DBUG_PRINT("qcache",
- ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
- tables_used->real_name, tables_used->db,
- (ulong) tables_used->table,
- tables_used->table->key_length,
- (ulong) tables_used->table->table_cache_key));
- block_table->n=n;
- if (!insert_table(tables_used->table->key_length,
- tables_used->table->table_cache_key, block_table,
- tables_used->db_length,
- tables_used->table->file->table_cache_type()))
- break;
+ n= register_tables_from_list(tables_used, 0, block_table);
- if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
- {
- ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
- MYRG_INFO *file = handler->myrg_info();
- for (MYRG_TABLE *table = file->open_tables;
- table != file->end_table ;
- table++)
- {
- char key[MAX_DBKEY_LENGTH];
- uint32 db_length;
- uint key_length= filename_2_table_key(key, table->table->filename,
- &db_length);
- (++block_table)->n= ++n;
- if (!insert_table(key_length, key, block_table,
- db_length,
- tables_used->table->file->table_cache_type()))
- goto err;
- }
- }
- }
-
-err:
- if (tables_used)
+ if (n)
{
DBUG_PRINT("qcache", ("failed at table %d", (int) n));
/* Unlink the tables we allocated above */
@@ -2175,7 +2289,7 @@ err:
tmp++)
unlink_table(tmp);
}
- return (tables_used == 0);
+ return (n);
}
/*
@@ -2186,7 +2300,9 @@ err:
my_bool
Query_cache::insert_table(uint key_len, char *key,
Query_cache_block_table *node,
- uint32 db_length, uint8 cache_type)
+ uint32 db_length, uint8 cache_type,
+ qc_engine_callback callback,
+ ulonglong engine_data)
{
DBUG_ENTER("Query_cache::insert_table");
DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
@@ -2196,6 +2312,23 @@ Query_cache::insert_table(uint key_len, char *key,
hash_search(&tables, (byte*) key,
key_len));
+ if (table_block &&
+ table_block->table()->engine_data() != engine_data)
+ {
+ DBUG_PRINT("qcache",
+ ("Handler require invalidation queries of %s.%s %lld-%lld",
+ table_block->table()->db(),
+ table_block->table()->table(),
+ engine_data,
+ table_block->table()->engine_data()));
+ /*
+ as far as we delete all queries with this table, table block will be
+ deleted, too
+ */
+ invalidate_table(table_block);
+ table_block= 0;
+ }
+
if (table_block == 0)
{
DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)",
@@ -2226,6 +2359,8 @@ Query_cache::insert_table(uint key_len, char *key,
header->table(db + db_length + 1);
header->key_length(key_len);
header->type(cache_type);
+ header->callback(callback);
+ header->engine_data(engine_data);
}
Query_cache_block_table *list_root = table_block->table(0);
@@ -2664,6 +2799,84 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
*****************************************************************************/
/*
+ Collect information about table types, check that tables are cachable and
+ count them
+
+ SYNOPSIS
+ process_and_count_tables()
+ tables_used table list for processing
+ tables_type pointer to variable for table types collection
+
+ RETURN
+ 0 error
+ >0 number of tables
+*/
+
+static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used,
+ uint8 *tables_type)
+{
+ DBUG_ENTER("process_and_count_tables");
+ TABLE_COUNTER_TYPE table_count = 0;
+ for (; tables_used; tables_used= tables_used->next_global)
+ {
+ table_count++;
+ if (tables_used->view)
+ {
+ DBUG_PRINT("qcache", ("view %s, db %s",
+ tables_used->view_name.str,
+ tables_used->view_db.str));
+ *tables_type|= HA_CACHE_TBL_NONTRANSACT;
+ {
+ TABLE_COUNTER_TYPE subcount;
+ if (!(subcount= process_and_count_tables(tables_used->ancestor,
+ tables_type)))
+ DBUG_RETURN(0);
+ table_count+= subcount;
+ }
+ }
+ else
+ {
+ DBUG_PRINT("qcache", ("table %s, db %s, type %u",
+ tables_used->table->s->table_name,
+ tables_used->table->s->table_cache_key,
+ tables_used->table->s->db_type));
+ if (tables_used->derived)
+ {
+ table_count--;
+ DBUG_PRINT("qcache", ("derived table skipped"));
+ continue;
+ }
+ *tables_type|= tables_used->table->file->table_cache_type();
+
+ /*
+ table_alias_charset used here because it depends of
+ lower_case_table_names variable
+ */
+ if (tables_used->table->s->tmp_table != NO_TMP_TABLE ||
+ (*tables_type & HA_CACHE_TBL_NOCACHE) ||
+ (tables_used->db_length == 5 &&
+ my_strnncoll(table_alias_charset,
+ (uchar*)tables_used->table->s->table_cache_key, 6,
+ (uchar*)"mysql",6) == 0))
+ {
+ DBUG_PRINT("qcache",
+ ("select not cacheable: temporary, system or \
+ other non-cacheable table(s)"));
+ DBUG_RETURN(0);
+ }
+ if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
+ {
+ ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
+ MYRG_INFO *file = handler->myrg_info();
+ table_count+= (file->end_table - file->open_tables);
+ }
+ }
+ }
+ DBUG_RETURN(table_count);
+}
+
+
+/*
If query is cacheable return number tables in query
(query without tables are not cached)
*/
@@ -2674,7 +2887,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
TABLE_LIST *tables_used,
uint8 *tables_type)
{
- TABLE_COUNTER_TYPE table_count = 0;
+ TABLE_COUNTER_TYPE table_count;
DBUG_ENTER("Query_cache::is_cacheable");
if (lex->sql_command == SQLCOM_SELECT &&
@@ -2688,42 +2901,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
lex->select_lex.options,
(int) thd->variables.query_cache_type));
- for (; tables_used; tables_used= tables_used->next)
- {
- table_count++;
- DBUG_PRINT("qcache", ("table %s, db %s, type %u",
- tables_used->real_name,
- tables_used->db, tables_used->table->db_type));
- *tables_type|= tables_used->table->file->table_cache_type();
-
- /*
- table_alias_charset used here because it depends of
- lower_case_table_names variable
- */
- if ((tables_used->table->tmp_table != NO_TMP_TABLE &&
- !tables_used->derived) ||
- (*tables_type & HA_CACHE_TBL_NOCACHE) ||
- (tables_used->db_length == 5 &&
- my_strnncoll(table_alias_charset, (uchar*)tables_used->db, 6,
- (uchar*)"mysql",6) == 0))
- {
- DBUG_PRINT("qcache",
- ("select not cacheable: temporary, system or \
-other non-cacheable table(s)"));
- DBUG_RETURN(0);
- }
- if (tables_used->derived)
- {
- table_count--;
- DBUG_PRINT("qcache", ("derived table skipped"));
- }
- else if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
- {
- ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
- MYRG_INFO *file = handler->myrg_info();
- table_count+= (file->end_table - file->open_tables);
- }
- }
+ if (!(table_count= process_and_count_tables(tables_used, tables_type)))
+ DBUG_RETURN(0);
if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
((*tables_type)&HA_CACHE_TBL_TRANSACT))
@@ -2761,12 +2940,16 @@ my_bool Query_cache::ask_handler_allowance(THD *thd,
{
DBUG_ENTER("Query_cache::ask_handler_allowance");
- for (; tables_used; tables_used= tables_used->next)
+ for (; tables_used; tables_used= tables_used->next_global)
{
- TABLE *table= tables_used->table;
- if (!ha_caching_allowed(thd, table->table_cache_key,
- table->key_length,
- table->file->table_cache_type()))
+ TABLE *table;
+ if (!(table= tables_used->table))
+ continue;
+ handler *handler= table->file;
+ if (!handler->register_query_cache_table(thd, table->s->table_cache_key,
+ table->s->key_length,
+ &tables_used->callback_func,
+ &tables_used->engine_data))
{
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
tables_used->db, tables_used->alias));
@@ -3222,7 +3405,7 @@ void Query_cache::wreck(uint line, const char *message)
DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
DBUG_PRINT("warning", ("=================================="));
if (thd)
- thd->killed = 1;
+ thd->killed= THD::KILL_CONNECTION;
cache_dump();
/* check_integrity(0); */ /* Can't call it here because of locks */
bins_dump();
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index b0a045a8aad..123d16b606d 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -112,6 +112,7 @@ struct Query_cache_query
NET *wri;
ulong len;
uint8 tbls_type;
+ unsigned int last_pkt_nr;
inline void init_n_lock();
void unlock_n_destroy();
@@ -145,6 +146,10 @@ struct Query_cache_table
char *tbl;
uint32 key_len;
uint8 table_type;
+ /* unique for every engine reference */
+ qc_engine_callback callback_func;
+ /* data need by some engines */
+ ulonglong engine_data_buff;
inline char *db() { return (char *) data(); }
inline char *table() { return tbl; }
@@ -153,6 +158,10 @@ struct Query_cache_table
inline void key_length(uint32 len) { key_len= len; }
inline uint8 type() { return table_type; }
inline void type(uint8 t) { table_type= t; }
+ inline qc_engine_callback callback() { return callback_func; }
+ inline void callback(qc_engine_callback fn){ callback_func= fn; }
+ inline ulonglong engine_data() { return engine_data_buff; }
+ inline void engine_data(ulonglong data) { engine_data_buff= data; }
inline gptr data()
{
return (gptr)(((byte*)this)+
@@ -276,12 +285,18 @@ protected:
void invalidate_table(TABLE *table);
void invalidate_table(byte *key, uint32 key_length);
void invalidate_table(Query_cache_block *table_block);
+ TABLE_COUNTER_TYPE
+ register_tables_from_list(TABLE_LIST *tables_used,
+ TABLE_COUNTER_TYPE counter,
+ Query_cache_block_table *block_table);
my_bool register_all_tables(Query_cache_block *block,
TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE tables);
my_bool insert_table(uint key_len, char *key,
Query_cache_block_table *node,
- uint32 db_length, uint8 cache_type);
+ uint32 db_length, uint8 cache_type,
+ qc_engine_callback callback,
+ ulonglong engine_data);
void unlink_table(Query_cache_block_table *node);
Query_cache_block *get_free_block (ulong len, my_bool not_less,
ulong min);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 11b45b848c8..2699a4fa628 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -35,6 +35,9 @@
#endif
#include <mysys_err.h>
+#include "sp_rcontext.h"
+#include "sp_cache.h"
+
/*
The following is used to initialise Table_ident with a internal
table name
@@ -46,7 +49,7 @@ char internal_table_name[2]= "*";
** Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
/* Used templates */
template class List<Key>;
template class List_iterator<Key>;
@@ -154,26 +157,42 @@ bool foreign_key_prefix(Key *a, Key *b)
** Thread specific functions
****************************************************************************/
-THD::THD()
- :user_time(0), global_read_lock(0), is_fatal_error(0),
- last_insert_id_used(0),
- insert_id_used(0), rand_used(0), time_zone_used(0),
- in_lock_tables(0), bootstrap(0)
+Open_tables_state::Open_tables_state(ulong version_arg)
+ :version(version_arg)
{
- current_arena= this;
- host= user= priv_user= db= ip=0;
+ reset_open_tables_state();
+}
+
+
+/*
+ Pass nominal parameters to Statement constructor only to ensure that
+ the destructor works OK in case of error. The main_mem_root will be
+ re-initialized in init().
+*/
+
+THD::THD()
+ :Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0),
+ Open_tables_state(refresh_version),
+ lock_id(&main_lock_id),
+ user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0),
+ rand_used(0), time_zone_used(0),
+ last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0),
+ in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE),
+ spcont(NULL)
+{
+ stmt_arena= this;
+ host= user= priv_user= db= ip= 0;
+ catalog= (char*)"std"; // the only catalog we have for now
host_or_ip= "connecting host";
locked=some_tables_deleted=no_errors=password= 0;
- killed=0;
query_start_used= 0;
count_cuted_fields= CHECK_FIELD_IGNORE;
- db_length= col_access= 0;
+ killed= NOT_KILLED;
+ db_length= col_access=0;
query_error= tmp_table_used= 0;
next_insert_id=last_insert_id=0;
- open_tables= temporary_tables= handler_tables= derived_tables= 0;
hash_clear(&handler_tables_hash);
tmp_table=0;
- lock=locked_tables=0;
used_tables=0;
cuted_fields= sent_row_count= 0L;
limit_found_rows= 0;
@@ -186,26 +205,29 @@ THD::THD()
variables.pseudo_thread_id= 0;
one_shot_set= 0;
file_id = 0;
+ query_id= 0;
warn_id= 0;
db_charset= global_system_variables.collation_database;
+ bzero(ha_data, sizeof(ha_data));
mysys_var=0;
+ binlog_evt_union.do_union= FALSE;
#ifndef DBUG_OFF
dbug_sentry=THD_SENTRY_MAGIC;
#endif
-#ifndef EMBEDDED_LIBRARY
+#ifndef EMBEDDED_LIBRARY
net.vio=0;
#endif
- net.last_error[0]=0; // If error on boot
+ net.last_error[0]=0; // If error on boot
+ net.query_cache_query=0; // If error on boot
ull=0;
- system_thread=cleanup_done=0;
+ system_thread= cleanup_done= abort_on_warning= no_warnings_for_error= 0;
peer_port= 0; // For SHOW PROCESSLIST
- transaction.changed_tables = 0;
#ifdef __WIN__
real_id = 0;
#endif
#ifdef SIGNAL_WITH_VIO_CLOSE
active_vio = 0;
-#endif
+#endif
pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
/* Variables with default values */
@@ -217,23 +239,23 @@ THD::THD()
#ifndef NO_EMBEDDED_ACCESS_CHECKS
db_access=NO_ACCESS;
#endif
- version=refresh_version; // For boot
*scramble= '\0';
init();
/* Initialize sub structures */
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
user_connect=(USER_CONN *)0;
- hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0,
+ hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
- (hash_free_key) free_user_var,0);
+ (hash_free_key) free_user_var, 0);
+
+ sp_proc_cache= NULL;
+ sp_func_cache= NULL;
/* For user vars replication*/
if (opt_bin_log)
my_init_dynamic_array(&user_var_events,
- sizeof(BINLOG_USER_VAR_EVENT *),
- 16,
- 16);
+ sizeof(BINLOG_USER_VAR_EVENT *), 16, 16);
else
bzero((char*) &user_var_events, sizeof(user_var_events));
@@ -243,26 +265,10 @@ THD::THD()
protocol_prep.init(this);
tablespace_op=FALSE;
-#ifdef USING_TRANSACTIONS
- bzero((char*) &transaction,sizeof(transaction));
- /*
- Binlog is always open (if needed) before a THD is created (including
- bootstrap).
- */
- if (opt_using_transactions && mysql_bin_log.is_open())
- {
- if (open_cached_file(&transaction.trans_log,
- mysql_tmpdir, LOG_PREFIX, binlog_cache_size,
- MYF(MY_WME)))
- killed=1;
- transaction.trans_log.end_of_file= max_binlog_cache_size;
- }
-#endif
- init_sql_alloc(&transaction.mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
- {
- ulong tmp=sql_rnd_with_mutex();
- randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
- }
+ ulong tmp=sql_rnd_with_mutex();
+ randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
+ thr_lock_info_init(&lock_info); /* safety: will be reset after start */
+ thr_lock_owner_init(&main_lock_id, &lock_info);
}
@@ -285,6 +291,8 @@ void THD::init(void)
#endif
pthread_mutex_unlock(&LOCK_global_system_variables);
server_status= SERVER_STATUS_AUTOCOMMIT;
+ if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
+ server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
options= thd_startup_options;
open_options=ha_open_options;
update_lock_default= (variables.low_priority_updates ?
@@ -295,6 +303,7 @@ void THD::init(void)
bzero((char*) warn_count, sizeof(warn_count));
total_warn_count= 0;
update_charset();
+ bzero((char *) &status_var, sizeof(status_var));
}
@@ -310,9 +319,13 @@ void THD::init_for_queries()
reset_root_defaults(mem_root, variables.query_alloc_block_size,
variables.query_prealloc_size);
+#ifdef USING_TRANSACTIONS
reset_root_defaults(&transaction.mem_root,
variables.trans_alloc_block_size,
variables.trans_prealloc_size);
+#endif
+ transaction.xid_state.xid.null();
+ transaction.xid_state.in_thd=1;
}
@@ -333,9 +346,11 @@ void THD::change_user(void)
cleanup_done= 0;
init();
stmt_map.reset();
- hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0,
+ hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
(hash_free_key) free_user_var, 0);
+ sp_cache_clear(&sp_proc_cache);
+ sp_cache_clear(&sp_func_cache);
}
@@ -344,7 +359,16 @@ void THD::change_user(void)
void THD::cleanup(void)
{
DBUG_ENTER("THD::cleanup");
- ha_rollback(this);
+#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
+ if (transaction.xid_state.xa_state == XA_PREPARED)
+ {
+#error xid_state in the cache should be replaced by the allocated value
+ }
+#endif
+ {
+ ha_rollback(this);
+ xid_cache_delete(&transaction.xid_state);
+ }
if (locked_tables)
{
lock=locked_tables; locked_tables=0;
@@ -359,6 +383,10 @@ void THD::cleanup(void)
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
+
+ sp_cache_clear(&sp_proc_cache);
+ sp_cache_clear(&sp_func_cache);
+
if (global_read_lock)
unlock_global_read_lock(this);
if (ull)
@@ -368,6 +396,7 @@ void THD::cleanup(void)
pthread_mutex_unlock(&LOCK_user_locks);
ull= 0;
}
+
cleanup_done=1;
DBUG_VOID_RETURN;
}
@@ -380,24 +409,22 @@ THD::~THD()
/* Ensure that no one is using THD */
pthread_mutex_lock(&LOCK_delete);
pthread_mutex_unlock(&LOCK_delete);
+ add_to_status(&global_status_var, &status_var);
/* Close connection */
-#ifndef EMBEDDED_LIBRARY
+#ifndef EMBEDDED_LIBRARY
if (net.vio)
{
vio_delete(net.vio);
- net_end(&net);
+ net_end(&net);
}
#endif
+ stmt_map.destroy(); /* close all prepared statements */
+ DBUG_ASSERT(lock_info.n_cursors == 0);
if (!cleanup_done)
cleanup();
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
- {
- close_cached_file(&transaction.trans_log);
- ha_close_connection(this);
- }
-#endif
+
+ ha_close_connection(this);
DBUG_PRINT("info", ("freeing host"));
if (host != my_localhost) // If not pointer to constant
@@ -407,26 +434,48 @@ THD::~THD()
safeFree(ip);
safeFree(db);
free_root(&warn_root,MYF(0));
+#ifdef USING_TRANSACTIONS
free_root(&transaction.mem_root,MYF(0));
+#endif
mysys_var=0; // Safety (shouldn't be needed)
pthread_mutex_destroy(&LOCK_delete);
#ifndef DBUG_OFF
- dbug_sentry = THD_SENTRY_GONE;
+ dbug_sentry= THD_SENTRY_GONE;
#endif
- /* Reset stmt_backup.mem_root to not double-free memory from thd.mem_root */
- clear_alloc_root(&stmt_backup.main_mem_root);
DBUG_VOID_RETURN;
}
-void THD::awake(bool prepare_to_die)
+/*
+ Add to one status variable another status variable
+
+ NOTES
+ This function assumes that all variables are long/ulong.
+ If this assumption will change, then we have to explictely add
+ the other variables after the while loop
+*/
+
+void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
+{
+ ulong *end= (ulong*) ((byte*) to_var + offsetof(STATUS_VAR,
+ last_system_status_var) +
+ sizeof(ulong));
+ ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
+
+ while (to != end)
+ *(to++)+= *(from++);
+ /* it doesn't make sense to add last_query_cost values */
+}
+
+
+void THD::awake(THD::killed_state state_to_set)
{
THD_CHECK_SENTRY(this);
safe_mutex_assert_owner(&LOCK_delete);
- if (prepare_to_die)
- killed = 1;
- thr_alarm_kill(real_id);
+ killed= state_to_set;
+ if (state_to_set != THD::KILL_QUERY)
+ thr_alarm_kill(real_id);
#ifdef SIGNAL_WITH_VIO_CLOSE
close_active_vio();
#endif
@@ -481,10 +530,28 @@ bool THD::store_globals()
if this is the slave SQL thread.
*/
variables.pseudo_thread_id= thread_id;
+ /*
+ We have to call thr_lock_info_init() again here as THD may have been
+ created in another thread
+ */
+ thr_lock_info_init(&lock_info);
return 0;
}
+/* Cleanup after a query */
+
+void THD::cleanup_after_query()
+{
+ if (clear_next_insert_id)
+ {
+ clear_next_insert_id= 0;
+ next_insert_id= 0;
+ }
+ /* Free Items that were created during this execution */
+ free_items();
+}
+
/*
Convert a string to another character set
@@ -592,7 +659,7 @@ void THD::add_changed_table(TABLE *table)
DBUG_ASSERT((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
table->file->has_transactions());
- add_changed_table(table->table_cache_key, table->key_length);
+ add_changed_table(table->s->table_cache_key, table->s->key_length);
DBUG_VOID_RETURN;
}
@@ -646,8 +713,8 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
if (!new_table)
{
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
- ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
- killed= 1;
+ ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
+ killed= KILL_CONNECTION;
return 0;
}
@@ -676,8 +743,8 @@ int THD::send_explain_fields(select_result *result)
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("key", NAME_LEN, cs));
item->maybe_null=1;
- field_list.push_back(item=new Item_return_int("key_len",3,
- MYSQL_TYPE_LONGLONG));
+ field_list.push_back(item=new Item_empty_string("key_len",
+ NAME_LEN*MAX_KEY));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("ref",
NAME_LEN*MAX_REF_PARTS, cs));
@@ -686,7 +753,8 @@ int THD::send_explain_fields(select_result *result)
MYSQL_TYPE_LONGLONG));
item->maybe_null= 1;
field_list.push_back(new Item_empty_string("Extra", 255, cs));
- return (result->send_fields(field_list,1));
+ return (result->send_fields(field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
}
#ifdef SIGNAL_WITH_VIO_CLOSE
@@ -720,7 +788,7 @@ struct Item_change_record: public ilink
/*
Register an item tree tree transformation, performed by the query
optimizer. We need a pointer to runtime_memroot because it may be !=
- thd->mem_root (due to possible set_n_backup_item_arena called for thd).
+ thd->mem_root (due to possible set_n_backup_active_arena called for thd).
*/
void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
@@ -735,7 +803,10 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
if (change_mem == 0)
{
- fatal_error();
+ /*
+ OOM, thd->fatal_error() is called by the error handler of the
+ memroot. Just return.
+ */
return;
}
change= new (change_mem) Item_change_record;
@@ -749,10 +820,13 @@ void THD::rollback_item_tree_changes()
{
I_List_iterator<Item_change_record> it(change_list);
Item_change_record *change;
+ DBUG_ENTER("rollback_item_tree_changes");
+
while ((change= it++))
*change->place= change->old_value;
/* We can forget about changes memory: it's allocated in runtime memroot */
change_list.empty();
+ DBUG_VOID_RETURN;
}
@@ -767,7 +841,7 @@ select_result::select_result()
void select_result::send_error(uint errcode,const char *err)
{
- ::send_error(thd, errcode, err);
+ my_message(errcode, err, MYF(0));
}
@@ -789,11 +863,36 @@ sql_exchange::sql_exchange(char *name,bool flag)
escaped= &default_escaped;
}
-bool select_send::send_fields(List<Item> &list,uint flag)
+bool select_send::send_fields(List<Item> &list, uint flags)
{
- return thd->protocol->send_fields(&list,flag);
+ bool res;
+ if (!(res= thd->protocol->send_fields(&list, flags)))
+ status= 1;
+ return res;
+}
+
+void select_send::abort()
+{
+ DBUG_ENTER("select_send::abort");
+ if (status && thd->spcont &&
+ thd->spcont->find_handler(thd->net.last_errno,
+ MYSQL_ERROR::WARN_LEVEL_ERROR))
+ {
+ /*
+ Executing stored procedure without a handler.
+ Here we should actually send an error to the client,
+ but as an error will break a multiple result set, the only thing we
+ can do for now is to nicely end the current data set and remembering
+ the error so that the calling routine will abort
+ */
+ thd->net.report_error= 0;
+ send_eof();
+ thd->net.report_error= 1; // Abort SP
+ }
+ DBUG_VOID_RETURN;
}
+
/* Send data to client. Returns 0 if ok */
bool select_send::send_data(List<Item> &items)
@@ -810,7 +909,6 @@ bool select_send::send_data(List<Item> &items)
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
by thd
*/
- if (thd->transaction.all.innobase_tid)
ha_release_temporary_latches(thd);
#endif
@@ -845,7 +943,6 @@ bool select_send::send_eof()
/* We may be passing the control from mysqld to the client: release the
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
by thd */
- if (thd->transaction.all.innobase_tid)
ha_release_temporary_latches(thd);
#endif
@@ -858,6 +955,7 @@ bool select_send::send_eof()
if (!thd->net.report_error)
{
::send_eof(thd);
+ status= 0;
return 0;
}
else
@@ -871,7 +969,7 @@ bool select_send::send_eof()
void select_to_file::send_error(uint errcode,const char *err)
{
- ::send_error(thd,errcode,err);
+ my_message(errcode, err, MYF(0));
if (file > 0)
{
(void) end_io_cache(&cache);
@@ -1195,7 +1293,7 @@ bool select_dump::send_data(List<Item> &items)
}
if (row_count++ > 1)
{
- my_error(ER_TOO_MANY_ROWS, MYF(0));
+ my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
goto err;
}
while ((item=li++))
@@ -1208,7 +1306,7 @@ bool select_dump::send_data(List<Item> &items)
}
else if (my_b_write(&cache,(byte*) res->ptr(),res->length()))
{
- my_error(ER_ERROR_ON_WRITE,MYF(0), path, my_errno);
+ my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
goto err;
}
}
@@ -1284,6 +1382,9 @@ bool select_max_min_finder_subselect::send_data(List<Item> &items)
case STRING_RESULT:
op= &select_max_min_finder_subselect::cmp_str;
break;
+ case DECIMAL_RESULT:
+ op= &select_max_min_finder_subselect::cmp_decimal;
+ break;
case ROW_RESULT:
// This case should never be choosen
DBUG_ASSERT(0);
@@ -1300,15 +1401,14 @@ bool select_max_min_finder_subselect::send_data(List<Item> &items)
bool select_max_min_finder_subselect::cmp_real()
{
Item *maxmin= ((Item_singlerow_subselect *)item)->el(0);
- double val1= cache->val(), val2= maxmin->val();
+ double val1= cache->val_real(), val2= maxmin->val_real();
if (fmax)
return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
val1 > val2);
- else
- return (maxmin->null_value && !cache->null_value) ||
- (!cache->null_value && !maxmin->null_value &&
- val1 < val2);
+ return (maxmin->null_value && !cache->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ val1 < val2);
}
bool select_max_min_finder_subselect::cmp_int()
@@ -1319,10 +1419,23 @@ bool select_max_min_finder_subselect::cmp_int()
return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
val1 > val2);
- else
- return (maxmin->null_value && !cache->null_value) ||
+ return (maxmin->null_value && !cache->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ val1 < val2);
+}
+
+bool select_max_min_finder_subselect::cmp_decimal()
+{
+ Item *maxmin= ((Item_singlerow_subselect *)item)->el(0);
+ my_decimal cval, *cvalue= cache->val_decimal(&cval);
+ my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
+ if (fmax)
+ return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
- val1 < val2);
+ my_decimal_cmp(cvalue, mvalue) > 0) ;
+ return (maxmin->null_value && !cache->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ my_decimal_cmp(cvalue,mvalue) < 0);
}
bool select_max_min_finder_subselect::cmp_str()
@@ -1339,10 +1452,9 @@ bool select_max_min_finder_subselect::cmp_str()
return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
sortcmp(val1, val2, cache->collation.collation) > 0) ;
- else
- return (maxmin->null_value && !cache->null_value) ||
- (!cache->null_value && !maxmin->null_value &&
- sortcmp(val1, val2, cache->collation.collation) < 0);
+ return (maxmin->null_value && !cache->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ sortcmp(val1, val2, cache->collation.collation) < 0);
}
bool select_exists_subselect::send_data(List<Item> &items)
@@ -1367,27 +1479,37 @@ bool select_exists_subselect::send_data(List<Item> &items)
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
List_iterator_fast<Item> li(list);
- List_iterator_fast<LEX_STRING> gl(var_list);
+ List_iterator_fast<my_var> gl(var_list);
Item *item;
- LEX_STRING *ls;
+
+ local_vars.empty(); // Clear list if SP
+ unit= u;
+ row_count= 0;
+
if (var_list.elements != list.elements)
{
- my_error(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, MYF(0));
+ my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
+ ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
return 1;
}
- unit=u;
while ((item=li++))
{
- ls= gl++;
- Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
- /*
- Item_func_set_user_var can't substitute something else on its place =>
- 0 can be passed as last argument (reference on item)
- */
- xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first,
- 0);
- xx->fix_length_and_dec();
- vars.push_back(xx);
+ my_var *mv= gl++;
+ if (mv->local)
+ (void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
+ else
+ {
+ Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item);
+ /*
+ Item_func_set_user_var can't substitute something else on its place =>
+ 0 can be passed as last argument (reference on item)
+ Item_func_set_user_var can't be fixed after creation, so we do not
+ check var->fixed
+ */
+ var->fix_fields(thd, 0);
+ var->fix_length_and_dec();
+ vars.push_back(var);
+ }
}
return 0;
}
@@ -1400,56 +1522,25 @@ void select_dumpvar::cleanup()
}
-/*
- Create arena for already constructed THD.
-
- SYNOPSYS
- Item_arena()
- thd - thread for which arena is created
-
- DESCRIPTION
- Create arena for already existing THD using its variables as parameters
- for memory root initialization.
-*/
-Item_arena::Item_arena(THD* thd)
- :free_list(0), mem_root(&main_mem_root),
- state(INITIALIZED)
+Query_arena::Type Query_arena::type() const
{
- init_sql_alloc(&main_mem_root,
- thd->variables.query_alloc_block_size,
- thd->variables.query_prealloc_size);
-}
-
-
-/*
- Create arena and optionally initialize memory root.
-
- SYNOPSYS
- Item_arena()
- init_mem_root - whenever we need to initialize memory root
-
- DESCRIPTION
- Create arena and optionally initialize memory root with minimal
- possible parameters.
-
- NOTE
- We use this constructor when arena is part of THD, but reinitialize
- its memory root in THD::init_for_queries() before execution of real
- statements.
-*/
-Item_arena::Item_arena(bool init_mem_root)
- :free_list(0), mem_root(&main_mem_root),
- state(CONVENTIONAL_EXECUTION)
-{
- if (init_mem_root)
- init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+ DBUG_ASSERT(0); /* Should never be called */
+ return STATEMENT;
}
-Item_arena::Type Item_arena::type() const
+void Query_arena::free_items()
{
- DBUG_ASSERT("Item_arena::type()" == "abstract");
- return STATEMENT;
+ Item *next;
+ DBUG_ENTER("Query_arena::free_items");
+ /* This works because items are allocated with sql_alloc() */
+ for (; free_list; free_list= next)
+ {
+ next= free_list->next;
+ free_list->delete_self();
+ }
+ /* Postcondition: free_list is 0 */
+ DBUG_VOID_RETURN;
}
@@ -1457,37 +1548,23 @@ Item_arena::Type Item_arena::type() const
Statement functions
*/
-Statement::Statement(THD *thd)
- :Item_arena(thd),
- id(++thd->statement_id_counter),
+Statement::Statement(enum enum_state state_arg, ulong id_arg,
+ ulong alloc_block_size, ulong prealloc_size)
+ :Query_arena(&main_mem_root, state_arg),
+ id(id_arg),
set_query_id(1),
allow_sum_func(0),
lex(&main_lex),
query(0),
- query_length(0)
+ query_length(0),
+ cursor(0)
{
name.str= NULL;
-}
-
-/*
- This constructor is called when statement is a subobject of THD:
- Some variables are initialized in THD::init due to locking problems
- This statement object will be used to
-*/
-
-Statement::Statement()
- :Item_arena((bool)TRUE),
- id(0),
- set_query_id(1),
- allow_sum_func(0), /* initialized later */
- lex(&main_lex),
- query(0), /* these two are set */
- query_length(0) /* in alloc_query() */
-{
+ init_sql_alloc(&main_mem_root, alloc_block_size, prealloc_size);
}
-Item_arena::Type Statement::type() const
+Query_arena::Type Statement::type() const
{
return STATEMENT;
}
@@ -1501,21 +1578,32 @@ void Statement::set_statement(Statement *stmt)
lex= stmt->lex;
query= stmt->query;
query_length= stmt->query_length;
+ cursor= stmt->cursor;
}
void
Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
{
+ DBUG_ENTER("Statement::set_n_backup_statement");
backup->set_statement(this);
set_statement(stmt);
+ DBUG_VOID_RETURN;
}
void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
{
+ DBUG_ENTER("Statement::restore_backup_statement");
stmt->set_statement(this);
set_statement(backup);
+ DBUG_VOID_RETURN;
+}
+
+
+void Statement::close_cursor()
+{
+ DBUG_ASSERT("Statement::close_cursor()" == "not implemented");
}
@@ -1525,8 +1613,8 @@ void THD::end_statement()
lex_end(lex);
delete lex->result;
lex->result= 0;
- free_items(free_list);
- free_list= 0;
+ /* Note that free_list is freed in cleanup_after_query() */
+
/*
Don't free mem_root, as mem_root is freed in the end of dispatch_command
(once for any command).
@@ -1534,34 +1622,33 @@ void THD::end_statement()
}
-void Item_arena::set_n_backup_item_arena(Item_arena *set, Item_arena *backup)
+void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup)
{
- DBUG_ENTER("Item_arena::set_n_backup_item_arena");
- backup->set_item_arena(this);
- set_item_arena(set);
+ DBUG_ENTER("THD::set_n_backup_active_arena");
+ DBUG_ASSERT(backup->is_backup_arena == FALSE);
+
+ backup->set_query_arena(this);
+ set_query_arena(set);
+#ifndef DBUG_OFF
+ backup->is_backup_arena= TRUE;
+#endif
DBUG_VOID_RETURN;
}
-void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup)
+void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
{
- DBUG_ENTER("Item_arena::restore_backup_item_arena");
- set->set_item_arena(this);
- set_item_arena(backup);
-#ifdef NOT_NEEDED_NOW
- /*
- Reset backup mem_root to avoid its freeing.
- Since Item_arena's mem_root is freed only when it is part of Statement
- we need this only if we use some Statement's arena as backup storage.
- But we do this only with THD::stmt_backup and this Statement is specially
- handled in this respect. So this code is not really needed now.
- */
- clear_alloc_root(&backup->mem_root);
+ DBUG_ENTER("THD::restore_active_arena");
+ DBUG_ASSERT(backup->is_backup_arena);
+ set->set_query_arena(this);
+ set_query_arena(backup);
+#ifndef DBUG_OFF
+ backup->is_backup_arena= FALSE;
#endif
DBUG_VOID_RETURN;
}
-void Item_arena::set_item_arena(Item_arena *set)
+void Query_arena::set_query_arena(Query_arena *set)
{
mem_root= set->mem_root;
free_list= set->free_list;
@@ -1570,6 +1657,11 @@ void Item_arena::set_item_arena(Item_arena *set)
Statement::~Statement()
{
+ /*
+ We must free `main_mem_root', not `mem_root' (pointer), to work
+ correctly if this statement is used as a backup statement,
+ for which `mem_root' may point to some other statement.
+ */
free_root(&main_mem_root, MYF(0));
}
@@ -1614,32 +1706,44 @@ Statement_map::Statement_map() :
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);
}
+ if (rc == 0)
+ last_found_statement= statement;
return rc;
}
+void Statement_map::close_transient_cursors()
+{
+ Statement *stmt;
+ while ((stmt= transient_cursor_list.head()))
+ stmt->close_cursor(); /* deletes itself from the list */
+}
+
+
bool select_dumpvar::send_data(List<Item> &items)
{
List_iterator_fast<Item_func_set_user_var> li(vars);
+ List_iterator_fast<Item_splocal> var_li(local_vars);
+ List_iterator_fast<my_var> my_li(var_list);
+ List_iterator<Item> it(items);
Item_func_set_user_var *xx;
+ Item_splocal *yy;
+ my_var *zz;
DBUG_ENTER("send_data");
+ if (unit->offset_limit_cnt)
+ { // using limit offset,count
+ unit->offset_limit_cnt--;
+ DBUG_RETURN(0);
+ }
if (unit->offset_limit_cnt)
{ // Using limit offset,count
@@ -1648,29 +1752,39 @@ bool select_dumpvar::send_data(List<Item> &items)
}
if (row_count++)
{
- my_error(ER_TOO_MANY_ROWS, MYF(0));
+ my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
DBUG_RETURN(1);
}
- while ((xx=li++))
+ while ((zz=my_li++) && (it++))
{
- xx->check();
- xx->update();
+ if (zz->local)
+ {
+ if ((yy=var_li++))
+ {
+ if (thd->spcont->set_item_eval(current_thd,
+ yy->get_offset(), it.ref(), zz->type))
+ DBUG_RETURN(1);
+ }
+ }
+ else
+ {
+ if ((xx=li++))
+ {
+ xx->check();
+ xx->update();
+ }
+ }
}
DBUG_RETURN(0);
}
bool select_dumpvar::send_eof()
{
- if (row_count)
- {
- ::send_ok(thd,row_count);
- return 0;
- }
- else
- {
- my_error(ER_EMPTY_QUERY,MYF(0));
- return 1;
- }
+ if (! row_count)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
+ ::send_ok(thd,row_count);
+ return 0;
}
/****************************************************************************
@@ -1682,4 +1796,235 @@ void TMP_TABLE_PARAM::init()
field_count= sum_func_count= func_count= hidden_field_count= 0;
group_parts= group_length= group_null_parts= 0;
quick_group= 1;
+ table_charset= 0;
+}
+
+
+void thd_increment_bytes_sent(ulong length)
+{
+ THD *thd=current_thd;
+ if (likely(thd != 0))
+ { /* current_thd==0 when close_connection() calls net_send_error() */
+ thd->status_var.bytes_sent+= length;
+ }
+}
+
+
+void thd_increment_bytes_received(ulong length)
+{
+ current_thd->status_var.bytes_received+= length;
+}
+
+
+void thd_increment_net_big_packet_count(ulong length)
+{
+ current_thd->status_var.net_big_packet_count+= length;
+}
+
+
+void THD::set_status_var_init()
+{
+ bzero((char*) &status_var, sizeof(status_var));
+}
+
+/****************************************************************************
+ Handling of open and locked tables states.
+
+ This is used when we want to open/lock (and then close) some tables when
+ we already have a set of tables open and locked. We use these methods for
+ access to mysql.proc table to find definitions of stored routines.
+****************************************************************************/
+
+void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
+{
+ DBUG_ENTER("reset_n_backup_open_tables_state");
+ backup->set_open_tables_state(this);
+ reset_open_tables_state();
+ DBUG_VOID_RETURN;
}
+
+
+void THD::restore_backup_open_tables_state(Open_tables_state *backup)
+{
+ DBUG_ENTER("restore_backup_open_tables_state");
+ /*
+ Before we will throw away current open tables state we want
+ to be sure that it was properly cleaned up.
+ */
+ DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 &&
+ handler_tables == 0 && derived_tables == 0 &&
+ lock == 0 && locked_tables == 0 &&
+ prelocked_mode == NON_PRELOCKED);
+ set_open_tables_state(backup);
+ DBUG_VOID_RETURN;
+}
+
+
+
+/****************************************************************************
+ Handling of statement states in functions and triggers.
+
+ This is used to ensure that the function/trigger gets a clean state
+ to work with and does not cause any side effects of the calling statement.
+
+ It also allows most stored functions and triggers to replicate even
+ if they are used items that would normally be stored in the binary
+ replication (like last_insert_id() etc...)
+
+ The following things is done
+ - Disable binary logging for the duration of the statement
+ - Disable multi-result-sets for the duration of the statement
+ - Value of last_insert_id() is reset and restored
+ - Value set by 'SET INSERT_ID=#' is reset and restored
+ - Value for found_rows() is reset and restored
+ - examined_row_count is added to the total
+ - cuted_fields is added to the total
+
+ NOTES:
+ Seed for random() is saved for the first! usage of RAND()
+ We reset examined_row_count and cuted_fields and add these to the
+ result to ensure that if we have a bug that would reset these within
+ a function, we are not loosing any rows from the main statement.
+****************************************************************************/
+
+void THD::reset_sub_statement_state(Sub_statement_state *backup,
+ uint new_state)
+{
+ backup->options= options;
+ backup->in_sub_stmt= in_sub_stmt;
+ backup->no_send_ok= net.no_send_ok;
+ backup->enable_slow_log= enable_slow_log;
+ backup->last_insert_id= last_insert_id;
+ backup->next_insert_id= next_insert_id;
+ backup->insert_id_used= insert_id_used;
+ backup->limit_found_rows= limit_found_rows;
+ backup->examined_row_count= examined_row_count;
+ backup->sent_row_count= sent_row_count;
+ backup->cuted_fields= cuted_fields;
+ backup->client_capabilities= client_capabilities;
+
+ if (!lex->requires_prelocking() || is_update_query(lex->sql_command))
+ options&= ~OPTION_BIN_LOG;
+ /* Disable result sets */
+ client_capabilities &= ~CLIENT_MULTI_RESULTS;
+ in_sub_stmt|= new_state;
+ last_insert_id= 0;
+ next_insert_id= 0;
+ insert_id_used= 0;
+ examined_row_count= 0;
+ sent_row_count= 0;
+ cuted_fields= 0;
+
+#ifndef EMBEDDED_LIBRARY
+ /* Surpress OK packets in case if we will execute statements */
+ net.no_send_ok= TRUE;
+#endif
+}
+
+
+void THD::restore_sub_statement_state(Sub_statement_state *backup)
+{
+ options= backup->options;
+ in_sub_stmt= backup->in_sub_stmt;
+ net.no_send_ok= backup->no_send_ok;
+ enable_slow_log= backup->enable_slow_log;
+ last_insert_id= backup->last_insert_id;
+ next_insert_id= backup->next_insert_id;
+ insert_id_used= backup->insert_id_used;
+ limit_found_rows= backup->limit_found_rows;
+ sent_row_count= backup->sent_row_count;
+ client_capabilities= backup->client_capabilities;
+
+ /*
+ The following is added to the old values as we are interested in the
+ total complexity of the query
+ */
+ examined_row_count+= backup->examined_row_count;
+ cuted_fields+= backup->cuted_fields;
+}
+
+
+/***************************************************************************
+ Handling of XA id cacheing
+***************************************************************************/
+
+pthread_mutex_t LOCK_xid_cache;
+HASH xid_cache;
+
+static byte *xid_get_hash_key(const byte *ptr,uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length=((XID_STATE*)ptr)->xid.length();
+ return (byte *)&((XID_STATE*)ptr)->xid;
+}
+
+static void xid_free_hash (void *ptr)
+{
+ if (!((XID_STATE*)ptr)->in_thd)
+ my_free((gptr)ptr, MYF(0));
+}
+
+bool xid_cache_init()
+{
+ pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
+ return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
+ xid_get_hash_key, xid_free_hash, 0) != 0;
+}
+
+void xid_cache_free()
+{
+ if (hash_inited(&xid_cache))
+ {
+ hash_free(&xid_cache);
+ pthread_mutex_destroy(&LOCK_xid_cache);
+ }
+}
+
+XID_STATE *xid_cache_search(XID *xid)
+{
+ pthread_mutex_lock(&LOCK_xid_cache);
+ XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, (byte *)xid, xid->length());
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ return res;
+}
+
+
+bool xid_cache_insert(XID *xid, enum xa_states xa_state)
+{
+ XID_STATE *xs;
+ my_bool res;
+ pthread_mutex_lock(&LOCK_xid_cache);
+ if (hash_search(&xid_cache, (byte *)xid, xid->length()))
+ res=0;
+ else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
+ res=1;
+ else
+ {
+ xs->xa_state=xa_state;
+ xs->xid.set(xid);
+ xs->in_thd=0;
+ res=my_hash_insert(&xid_cache, (byte*)xs);
+ }
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ return res;
+}
+
+
+bool xid_cache_insert(XID_STATE *xid_state)
+{
+ pthread_mutex_lock(&LOCK_xid_cache);
+ DBUG_ASSERT(hash_search(&xid_cache, (byte *)&xid_state->xid,
+ xid_state->xid.length())==0);
+ my_bool res=my_hash_insert(&xid_cache, (byte*)xid_state);
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ return res;
+}
+
+
+void xid_cache_delete(XID_STATE *xid_state)
+{
+ pthread_mutex_lock(&LOCK_xid_cache);
+ hash_delete(&xid_cache, (byte *)xid_state);
+ pthread_mutex_unlock(&LOCK_xid_cache);
+}
+
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 41170192892..b3eb371b4e8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -26,6 +26,9 @@
class Query_log_event;
class Load_log_event;
class Slave_log_event;
+class Format_description_log_event;
+class sp_rcontext;
+class sp_cache;
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
@@ -38,6 +41,98 @@ enum enum_check_fields { CHECK_FIELD_IGNORE, CHECK_FIELD_WARN,
CHECK_FIELD_ERROR_FOR_NULL };
extern char internal_table_name[2];
+extern const char **errmesg;
+
+#define TC_LOG_PAGE_SIZE 8192
+#define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE)
+
+#define TC_HEURISTIC_RECOVER_COMMIT 1
+#define TC_HEURISTIC_RECOVER_ROLLBACK 2
+extern uint tc_heuristic_recover;
+
+/*
+ Transaction Coordinator log - a base abstract class
+ for two different implementations
+*/
+class TC_LOG
+{
+ public:
+ int using_heuristic_recover();
+ TC_LOG() {}
+ virtual ~TC_LOG() {}
+
+ virtual int open(const char *opt_name)=0;
+ virtual void close()=0;
+ virtual int log(THD *thd, my_xid xid)=0;
+ virtual void unlog(ulong cookie, my_xid xid)=0;
+};
+
+class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
+{
+ public:
+ int open(const char *opt_name) { return 0; }
+ void close() { }
+ int log(THD *thd, my_xid xid) { return 1; }
+ void unlog(ulong cookie, my_xid xid) { }
+};
+
+#ifdef HAVE_MMAP
+class TC_LOG_MMAP: public TC_LOG
+{
+ public: // only to keep Sun Forte on sol9x86 happy
+ typedef enum {
+ POOL, // page is in pool
+ ERROR, // last sync failed
+ DIRTY // new xids added since last sync
+ } PAGE_STATE;
+
+ private:
+ typedef struct st_page {
+ struct st_page *next; // page a linked in a fifo queue
+ my_xid *start, *end; // usable area of a page
+ my_xid *ptr; // next xid will be written here
+ int size, free; // max and current number of free xid slots on the page
+ int waiters; // number of waiters on condition
+ PAGE_STATE state; // see above
+ pthread_mutex_t lock; // to access page data or control structure
+ pthread_cond_t cond; // to wait for a sync
+ } PAGE;
+
+ char logname[FN_REFLEN];
+ File fd;
+ my_off_t file_length;
+ uint npages, inited;
+ uchar *data;
+ struct st_page *pages, *syncing, *active, *pool, *pool_last;
+ /*
+ note that, e.g. LOCK_active is only used to protect
+ 'active' pointer, to protect the content of the active page
+ one has to use active->lock.
+ Same for LOCK_pool and LOCK_sync
+ */
+ pthread_mutex_t LOCK_active, LOCK_pool, LOCK_sync;
+ pthread_cond_t COND_pool, COND_active;
+
+ public:
+ TC_LOG_MMAP(): inited(0) {}
+ int open(const char *opt_name);
+ void close();
+ int log(THD *thd, my_xid xid);
+ void unlog(ulong cookie, my_xid xid);
+ int recover();
+
+ private:
+ void get_active_from_pool();
+ int sync();
+ int overflow();
+};
+#else
+#define TC_LOG_MMAP TC_LOG_DUMMY
+#endif
+
+extern TC_LOG *tc_log;
+extern TC_LOG_MMAP tc_log_mmap;
+extern TC_LOG_DUMMY tc_log_dummy;
/* log info errors */
#define LOG_INFO_EOF -1
@@ -75,10 +170,23 @@ typedef struct st_user_var_events
uint charset_number;
} BINLOG_USER_VAR_EVENT;
+#define RP_LOCK_LOG_IS_ALREADY_LOCKED 1
+#define RP_FORCE_ROTATE 2
+
class Log_event;
-class MYSQL_LOG
- {
+/*
+ TODO split MYSQL_LOG into base MYSQL_LOG and
+ MYSQL_QUERY_LOG, MYSQL_SLOW_LOG, MYSQL_BIN_LOG
+ most of the code from MYSQL_LOG should be in the MYSQL_BIN_LOG
+ only (TC_LOG included)
+
+ TODO use mmap instead of IO_CACHE for binlog
+ (mmap+fsync is two times faster than write+fsync)
+*/
+
+class MYSQL_LOG: public TC_LOG
+{
private:
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
pthread_mutex_t LOCK_log, LOCK_index;
@@ -97,8 +205,15 @@ class MYSQL_LOG
enum cache_type io_cache_type;
bool write_error, inited;
bool need_start_event;
- bool no_auto_events; // For relay binlog
- /*
+ /*
+ no_auto_events means we don't want any of these automatic events :
+ Start/Rotate/Stop. That is, in 4.x when we rotate a relay log, we don't want
+ a Rotate_log event to be written to the relay log. When we start a relay log
+ etc. So in 4.x this is 1 for relay logs, 0 for binlogs.
+ In 5.0 it's 0 for relay logs too!
+ */
+ bool no_auto_events;
+ /*
The max size before rotation (usable only if log_type == LOG_BIN: binary
logs and relay logs).
For a binlog, max_size should be max_binlog_size.
@@ -106,14 +221,40 @@ class MYSQL_LOG
max_binlog_size otherwise.
max_size is set in init(), and dynamically changed (when one does SET
GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and
- fix_max_relay_log_size).
+ fix_max_relay_log_size).
*/
ulong max_size;
+
+ ulong prepared_xids; /* for tc log - number of xids to remember */
+ pthread_mutex_t LOCK_prep_xids;
+ pthread_cond_t COND_prep_xids;
friend class Log_event;
public:
MYSQL_LOG();
- ~MYSQL_LOG();
+ /*
+ note that there's no destructor ~MYSQL_LOG() !
+ The reason is that we don't want it to be automatically called
+ on exit() - but only during the correct shutdown process
+ */
+
+ int open(const char *opt_name);
+ void close();
+ int log(THD *thd, my_xid xid);
+ void unlog(ulong cookie, my_xid xid);
+ int recover(IO_CACHE *log, Format_description_log_event *fdle);
+
+ /*
+ These describe the log's format. This is used only for relay logs.
+ _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
+ necessary to have 2 distinct objects, because the I/O thread may be reading
+ events in a different format from what the SQL thread is reading (consider
+ the case of a master which has been upgraded from 5.0 to 5.1 without doing
+ RESET MASTER, or from 4.x to 5.0).
+ */
+ Format_description_log_event *description_event_for_exec,
+ *description_event_for_queue;
+
void reset_bytes_written()
{
bytes_written = 0;
@@ -122,7 +263,7 @@ public:
{
#ifndef DBUG_OFF
char buf1[22],buf2[22];
-#endif
+#endif
DBUG_ENTER("harvest_bytes_written");
(*counter)+=bytes_written;
DBUG_PRINT("info",("counter: %s bytes_written: %s", llstr(*counter,buf1),
@@ -139,17 +280,40 @@ public:
bool no_auto_events_arg, ulong max_size);
void init_pthread_objects();
void cleanup();
- bool open(const char *log_name,enum_log_type log_type,
- const char *new_name, const char *index_file_name_arg,
+ bool open(const char *log_name,
+ enum_log_type log_type,
+ const char *new_name,
enum cache_type io_cache_type_arg,
- bool no_auto_events_arg, ulong max_size);
- void new_file(bool need_lock= 1);
+ bool no_auto_events_arg, ulong max_size,
+ bool null_created);
+ const char *generate_name(const char *log_name, const char *suffix,
+ bool strip_ext, char *buff);
+ /* simplified open_xxx wrappers for the gigantic open above */
+ bool open_query_log(const char *log_name)
+ {
+ char buf[FN_REFLEN];
+ return open(generate_name(log_name, ".log", 0, buf),
+ LOG_NORMAL, 0, WRITE_CACHE, 0, 0, 0);
+ }
+ bool open_slow_log(const char *log_name)
+ {
+ char buf[FN_REFLEN];
+ return open(generate_name(log_name, "-slow.log", 0, buf),
+ LOG_NORMAL, 0, WRITE_CACHE, 0, 0, 0);
+ }
+ bool open_index_file(const char *index_file_name_arg,
+ const char *log_name);
+ void new_file(bool need_lock);
bool write(THD *thd, enum enum_server_command command,
const char *format,...);
bool write(THD *thd, const char *query, uint query_length,
time_t query_start=0);
bool write(Log_event* event_info); // binary log write
- bool write(THD *thd, IO_CACHE *cache, bool commit_or_rollback);
+ bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event);
+
+ void start_union_events(THD *thd);
+ void stop_union_events(THD *thd);
+ bool is_query_in_union(THD *thd, query_id_t query_id_param);
/*
v stands for vector
@@ -157,20 +321,20 @@ public:
*/
bool appendv(const char* buf,uint len,...);
bool append(Log_event* ev);
-
+
int generate_new_name(char *new_name,const char *old_name);
void make_log_name(char* buf, const char* log_ident);
bool is_active(const char* log_file_name);
int update_log_index(LOG_INFO* linfo, bool need_update_threads);
- int purge_logs(const char *to_log, bool included,
+ void rotate_and_purge(uint flags);
+ bool flush_and_sync();
+ int purge_logs(const char *to_log, bool included,
bool need_mutex, bool need_update_threads,
ulonglong *decrease_log_space);
int purge_logs_before_date(time_t purge_time);
- int purge_first_log(struct st_relay_log_info* rli, bool included);
+ 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,
@@ -181,6 +345,7 @@ public:
inline bool is_open() { return log_type != LOG_CLOSED; }
inline char* get_index_fname() { return index_file_name;}
inline char* get_log_fname() { return log_file_name; }
+ inline char* get_name() { return name; }
inline pthread_mutex_t* get_log_lock() { return &LOCK_log; }
inline IO_CACHE* get_log_file() { return &log_file; }
@@ -190,8 +355,6 @@ public:
inline uint32 get_open_count() { return open_count; }
};
-/* character conversion tables */
-
typedef struct st_copy_info {
ha_rows records;
@@ -205,6 +368,8 @@ typedef struct st_copy_info {
/* for INSERT ... UPDATE */
List<Item> *update_fields;
List<Item> *update_values;
+ /* for VIEW ... WITH CHECK OPTION */
+ TABLE_LIST *view;
} COPY_INFO;
@@ -316,27 +481,6 @@ public:
};
-class MYSQL_ERROR: public Sql_alloc
-{
-public:
- enum enum_warning_level
- { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
-
- uint code;
- enum_warning_level level;
- char *msg;
-
- MYSQL_ERROR(THD *thd, uint code_arg, enum_warning_level level_arg,
- const char *msg_arg)
- :code(code_arg), level(level_arg)
- {
- if (msg_arg)
- set_msg(thd, msg_arg);
- }
- void set_msg(THD *thd, const char *msg_arg);
-};
-
-
class delayed_insert;
class select_result;
@@ -351,6 +495,7 @@ struct system_variables
ulonglong myisam_max_sort_file_size;
ha_rows select_limit;
ha_rows max_join_size;
+ ulong auto_increment_increment, auto_increment_offset;
ulong bulk_insert_buff_size;
ulong join_buff_size;
ulong long_query_time;
@@ -361,6 +506,7 @@ struct system_variables
ulong max_sort_length;
ulong max_tmp_tables;
ulong max_insert_delayed_threads;
+ ulong multi_range_count;
ulong myisam_repair_threads;
ulong myisam_sort_buff_size;
ulong myisam_stats_method;
@@ -370,16 +516,22 @@ struct system_variables
ulong net_retry_count;
ulong net_wait_timeout;
ulong net_write_timeout;
+ ulong optimizer_prune_level;
+ ulong optimizer_search_depth;
ulong preload_buff_size;
ulong query_cache_type;
ulong read_buff_size;
ulong read_rnd_buff_size;
+ ulong div_precincrement;
ulong sortbuff_size;
ulong table_type;
ulong tmp_table_size;
ulong tx_isolation;
+ ulong completion_type;
/* Determines which non-standard SQL behaviour should be enabled */
ulong sql_mode;
+ /* check of key presence in updatable view */
+ ulong updatable_views_with_limit;
ulong default_week_format;
ulong max_seeks_for_key;
ulong range_alloc_block_size;
@@ -398,6 +550,7 @@ struct system_variables
my_bool low_priority_updates;
my_bool new_mode;
my_bool query_cache_wlock_invalidate;
+ my_bool engine_condition_pushdown;
#ifdef HAVE_REPLICATION
ulong sync_replication;
ulong sync_replication_slave_id;
@@ -405,6 +558,7 @@ struct system_variables
#endif /* HAVE_REPLICATION */
#ifdef HAVE_INNOBASE_DB
my_bool innodb_table_locks;
+ my_bool innodb_support_xa;
#endif /* HAVE_INNOBASE_DB */
#ifdef HAVE_NDBCLUSTER_DB
ulong ndb_autoincrement_prefetch_sz;
@@ -413,11 +567,11 @@ struct system_variables
my_bool ndb_use_transactions;
#endif /* HAVE_NDBCLUSTER_DB */
my_bool old_passwords;
-
+
/* Only charset part of these variables is sensible */
- CHARSET_INFO *character_set_client;
+ CHARSET_INFO *character_set_client;
CHARSET_INFO *character_set_results;
-
+
/* Both charset and collation parts of these variables are important */
CHARSET_INFO *collation_server;
CHARSET_INFO *collation_database;
@@ -431,10 +585,86 @@ struct system_variables
DATE_TIME_FORMAT *time_format;
};
+
+/* per thread status variables */
+
+typedef struct system_status_var
+{
+ ulong bytes_received;
+ ulong bytes_sent;
+ ulong com_other;
+ ulong com_stat[(uint) SQLCOM_END];
+ ulong created_tmp_disk_tables;
+ ulong created_tmp_tables;
+ ulong ha_commit_count;
+ ulong ha_delete_count;
+ ulong ha_read_first_count;
+ ulong ha_read_last_count;
+ ulong ha_read_key_count;
+ ulong ha_read_next_count;
+ ulong ha_read_prev_count;
+ ulong ha_read_rnd_count;
+ ulong ha_read_rnd_next_count;
+ ulong ha_rollback_count;
+ ulong ha_update_count;
+ ulong ha_write_count;
+ ulong ha_prepare_count;
+ ulong ha_discover_count;
+ ulong ha_savepoint_count;
+ ulong ha_savepoint_rollback_count;
+
+ /* KEY_CACHE parts. These are copies of the original */
+ ulong key_blocks_changed;
+ ulong key_blocks_used;
+ ulong key_cache_r_requests;
+ ulong key_cache_read;
+ ulong key_cache_w_requests;
+ ulong key_cache_write;
+ /* END OF KEY_CACHE parts */
+
+ ulong net_big_packet_count;
+ ulong opened_tables;
+ ulong select_full_join_count;
+ ulong select_full_range_join_count;
+ ulong select_range_count;
+ ulong select_range_check_count;
+ ulong select_scan_count;
+ ulong long_query_count;
+ ulong filesort_merge_passes;
+ ulong filesort_range_count;
+ ulong filesort_rows;
+ ulong filesort_scan_count;
+ /* Prepared statements and binary protocol */
+ ulong com_stmt_prepare;
+ ulong com_stmt_execute;
+ ulong com_stmt_send_long_data;
+ ulong com_stmt_fetch;
+ ulong com_stmt_reset;
+ ulong com_stmt_close;
+
+ double last_query_cost;
+} STATUS_VAR;
+
+/*
+ This is used for 'show status'. It must be updated to the last ulong
+ variable in system_status_var
+*/
+
+#define last_system_status_var com_stmt_close
+
+
void free_tmp_table(THD *thd, TABLE *entry);
-class Item_arena
+/* The following macro is to make init of Query_arena simpler */
+#ifndef DBUG_OFF
+#define INIT_ARENA_DBUG_INFO is_backup_arena= 0
+#else
+#define INIT_ARENA_DBUG_INFO
+#endif
+
+
+class Query_arena
{
public:
/*
@@ -442,14 +672,16 @@ public:
itself to the list on creation (see Item::Item() for details))
*/
Item *free_list;
- MEM_ROOT main_mem_root;
MEM_ROOT *mem_root; // Pointer to current memroot
- enum enum_state
+#ifndef DBUG_OFF
+ bool is_backup_arena; /* True if this arena is used for backup. */
+#endif
+ enum enum_state
{
- INITIALIZED= 0, PREPARED= 1, EXECUTED= 3, CONVENTIONAL_EXECUTION= 2,
- ERROR= -1
+ INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2,
+ CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1
};
-
+
enum_state state;
/* We build without RTTI, so dynamic_cast can't be used. */
@@ -458,30 +690,29 @@ public:
STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE
};
+ Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
+ free_list(0), mem_root(mem_root_arg), state(state_arg)
+ { INIT_ARENA_DBUG_INFO; }
/*
- This constructor is used only when Item_arena is created as
- backup storage for another instance of Item_arena.
- */
- Item_arena() {};
- /*
- Create arena for already constructed THD using its variables as
- parameters for memory root initialization.
+ This constructor is used only when Query_arena is created as
+ backup storage for another instance of Query_arena.
*/
- Item_arena(THD *thd);
- /*
- Create arena and optionally init memory root with minimal values.
- Particularly used if Item_arena is part of Statement.
- */
- Item_arena(bool init_mem_root);
+ Query_arena() { INIT_ARENA_DBUG_INFO; }
+
virtual Type type() const;
- virtual ~Item_arena() {};
+ virtual ~Query_arena() {};
- inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; }
+ inline bool is_stmt_prepare() const { return state == INITIALIZED; }
+ inline bool is_first_sp_execute() const
+ { return state == INITIALIZED_FOR_SP; }
+ inline bool is_stmt_prepare_or_first_sp_execute() const
+ { return (int)state < (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; }
inline bool is_stmt_execute() const
{ return state == PREPARED || state == EXECUTED; }
- inline bool is_conventional_execution() const
+ inline bool is_conventional() const
{ return state == CONVENTIONAL_EXECUTION; }
+
inline gptr alloc(unsigned int size) { return alloc_root(mem_root,size); }
inline gptr calloc(unsigned int size)
{
@@ -504,12 +735,14 @@ public:
return ptr;
}
- void set_n_backup_item_arena(Item_arena *set, Item_arena *backup);
- void restore_backup_item_arena(Item_arena *set, Item_arena *backup);
- void set_item_arena(Item_arena *set);
+ void set_query_arena(Query_arena *set);
+
+ void free_items();
};
+class Cursor;
+
/*
State of a single command executed against this connection.
One connection can contain a lot of simultaneously running statements,
@@ -524,12 +757,13 @@ public:
be used explicitly.
*/
-class Statement: public Item_arena
+class Statement: public ilink, public Query_arena
{
Statement(const Statement &rhs); /* not implemented: */
Statement &operator=(const Statement &rhs); /* non-copyable */
public:
- /* FIXME: must be private */
+ /* FIXME: these must be protected */
+ MEM_ROOT main_mem_root;
LEX main_lex;
/*
@@ -583,16 +817,15 @@ public:
*/
char *query;
uint32 query_length; // current query length
+ Cursor *cursor;
public:
- /*
- This constructor is called when statement is a subobject of THD:
- some variables are initialized in THD::init due to locking problems
- */
- Statement();
+ /* This constructor is called for backup statements */
+ Statement() { clear_alloc_root(&main_mem_root); }
- Statement(THD *thd);
+ Statement(enum enum_state state_arg, ulong id_arg,
+ ulong alloc_block_size, ulong prealloc_size);
virtual ~Statement();
/* Assign execution context (note: not all members) of given stmt to self */
@@ -601,6 +834,8 @@ public:
void restore_backup_statement(Statement *stmt, Statement *backup);
/* return class type */
virtual Type type() const;
+ /* Close the cursor open for this statement, if there is one */
+ virtual void close_cursor();
};
@@ -652,15 +887,25 @@ public:
}
hash_delete(&st_hash, (byte *) statement);
}
+ void add_transient_cursor(Statement *stmt)
+ { transient_cursor_list.append(stmt); }
+ void erase_transient_cursor(Statement *stmt) { stmt->unlink(); }
+ /*
+ Close all cursors of this connection that use tables of a storage
+ engine that has transaction-specific state and therefore can not
+ survive COMMIT or ROLLBACK. Currently all but MyISAM cursors are closed.
+ */
+ void close_transient_cursors();
/* Erase all statements (calls Statement destructor) */
void reset()
{
my_hash_reset(&names_hash);
my_hash_reset(&st_hash);
+ transient_cursor_list.empty();
last_found_statement= 0;
}
- ~Statement_map()
+ void destroy()
{
hash_free(&names_hash);
hash_free(&st_hash);
@@ -668,9 +913,34 @@ public:
private:
HASH st_hash;
HASH names_hash;
+ I_List<Statement> transient_cursor_list;
Statement *last_found_statement;
};
+struct st_savepoint {
+ struct st_savepoint *prev;
+ char *name;
+ uint length, nht;
+};
+
+enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED};
+extern const char *xa_state_names[];
+
+typedef struct st_xid_state {
+ /* For now, this is only used to catch duplicated external xids */
+ XID xid; // transaction identifier
+ enum xa_states xa_state; // used by external XA only
+ bool in_thd;
+} XID_STATE;
+
+extern pthread_mutex_t LOCK_xid_cache;
+extern HASH xid_cache;
+bool xid_cache_init(void);
+void xid_cache_free(void);
+XID_STATE *xid_cache_search(XID *xid);
+bool xid_cache_insert(XID *xid, enum xa_states xa_state);
+bool xid_cache_insert(XID_STATE *xid_state);
+void xid_cache_delete(XID_STATE *xid_state);
/*
A registry for item tree transformations performed during
@@ -684,12 +954,128 @@ typedef I_List<Item_change_record> Item_change_list;
/*
+ Type of prelocked mode.
+ See comment for THD::prelocked_mode for complete description.
+*/
+
+enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1,
+ PRELOCKED_UNDER_LOCK_TABLES= 2};
+
+
+/*
+ Class that holds information about tables which were opened and locked
+ by the thread. It is also used to save/restore this information in
+ push_open_tables_state()/pop_open_tables_state().
+*/
+
+class Open_tables_state
+{
+public:
+ /*
+ open_tables - list of regular tables in use by this thread
+ temporary_tables - list of temp tables in use by this thread
+ handler_tables - list of tables that were opened with HANDLER OPEN
+ and are still in use by this thread
+ */
+ TABLE *open_tables, *temporary_tables, *handler_tables, *derived_tables;
+ /*
+ During a MySQL session, one can lock tables in two modes: automatic
+ or manual. In automatic mode all necessary tables are locked just before
+ statement execution, and all acquired locks are stored in 'lock'
+ member. Unlocking takes place automatically as well, when the
+ statement ends.
+ Manual mode comes into play when a user issues a 'LOCK TABLES'
+ statement. In this mode the user can only use the locked tables.
+ Trying to use any other tables will give an error. The locked tables are
+ stored in 'locked_tables' member. Manual locking is described in
+ the 'LOCK_TABLES' chapter of the MySQL manual.
+ See also lock_tables() for details.
+ */
+ MYSQL_LOCK *lock;
+ /*
+ Tables that were locked with explicit or implicit LOCK TABLES.
+ (Implicit LOCK TABLES happens when we are prelocking tables for
+ execution of statement which uses stored routines. See description
+ THD::prelocked_mode for more info.)
+ */
+ MYSQL_LOCK *locked_tables;
+ /*
+ prelocked_mode_type enum and prelocked_mode member are used for
+ indicating whenever "prelocked mode" is on, and what type of
+ "prelocked mode" is it.
+
+ Prelocked mode is used for execution of queries which explicitly
+ or implicitly (via views or triggers) use functions, thus may need
+ some additional tables (mentioned in query table list) for their
+ execution.
+
+ First open_tables() call for such query will analyse all functions
+ used by it and add all additional tables to table its list. It will
+ also mark this query as requiring prelocking. After that lock_tables()
+ will issue implicit LOCK TABLES for the whole table list and change
+ thd::prelocked_mode to non-0. All queries called in functions invoked
+ by the main query will use prelocked tables. Non-0 prelocked_mode
+ will also surpress mentioned analysys in those queries thus saving
+ cycles. Prelocked mode will be turned off once close_thread_tables()
+ for the main query will be called.
+
+ Note: Since not all "tables" present in table list are really locked
+ thd::prelocked_mode does not imply thd::locked_tables.
+ */
+ prelocked_mode_type prelocked_mode;
+ ulong version;
+ uint current_tablenr;
+
+ /*
+ This constructor serves for creation of Open_tables_state instances
+ which are used as backup storage.
+ */
+ Open_tables_state() {};
+
+ Open_tables_state(ulong version_arg);
+
+ void set_open_tables_state(Open_tables_state *state)
+ {
+ *this= *state;
+ }
+
+ void reset_open_tables_state()
+ {
+ open_tables= temporary_tables= handler_tables= derived_tables= 0;
+ lock= locked_tables= 0;
+ prelocked_mode= NON_PRELOCKED;
+ }
+};
+
+
+/* class to save context when executing a function or trigger */
+
+/* Defines used for Sub_statement_state::in_sub_stmt */
+
+#define SUB_STMT_TRIGGER 1
+#define SUB_STMT_FUNCTION 2
+
+class Sub_statement_state
+{
+public:
+ ulonglong options;
+ ulonglong last_insert_id, next_insert_id;
+ ulonglong limit_found_rows;
+ ha_rows cuted_fields, sent_row_count, examined_row_count;
+ ulong client_capabilities;
+ uint in_sub_stmt;
+ bool enable_slow_log, insert_id_used;
+ my_bool no_send_ok;
+};
+
+
+/*
For each client connection we create a separate thread with THD serving as
a thread/connection descriptor
*/
-class THD :public ilink,
- public Statement
+class THD :public Statement,
+ public Open_tables_state
{
public:
#ifdef EMBEDDED_LIBRARY
@@ -713,14 +1099,14 @@ public:
struct sockaddr_in remote; // client socket address
struct rand_struct rand; // used for authentication
struct system_variables variables; // Changeable local variables
+ struct system_status_var status_var; // Per thread statistic vars
+ THR_LOCK_INFO lock_info; // Locking info of this thread
+ THR_LOCK_OWNER main_lock_id; // To use for conventional queries
+ THR_LOCK_OWNER *lock_id; // If not main_lock_id, points to
+ // the lock_id of a cursor.
pthread_mutex_t LOCK_delete; // Locked before thd is deleted
/* all prepared statements and cursors of this connection */
- Statement_map stmt_map;
- /*
- keeps THD state while it is used for active statement
- Note: we perform special cleanup for it in THD destructor.
- */
- Statement stmt_backup;
+ Statement_map stmt_map;
/*
A pointer to the stack frame of handle_one_connection(),
which is called first in the thread for handling a client
@@ -733,9 +1119,17 @@ public:
the connection
priv_user - The user privilege we are using. May be '' for anonymous user.
db - currently selected database
+ catalog - currently selected catalog
ip - client IP
+ WARNING: some members of THD (currently 'db', 'catalog' and 'query') are
+ set and alloced by the slave SQL thread (for the THD of that thread); that
+ thread is (and must remain, for now) the only responsible for freeing these
+ 3 members. If you add members here, and you add code to set them in
+ replication, don't forget to free_them_and_set_them_to_0 in replication
+ properly. For details see the 'err:' label of the pthread_handler_decl of
+ the slave SQL thread, in sql/slave.cc.
*/
- char *host,*user,*priv_user,*db,*ip;
+ char *host,*user,*priv_user,*db,*catalog,*ip;
char priv_host[MAX_HOSTNAME];
/* remote (peer) port */
uint16 peer_port;
@@ -753,28 +1147,6 @@ public:
ulong master_access; /* Global privileges from mysql.user */
ulong db_access; /* Privileges for current db */
- /*
- open_tables - list of regular tables in use by this thread
- temporary_tables - list of temp tables in use by this thread
- handler_tables - list of tables that were opened with HANDLER OPEN
- and are still in use by this thread
- */
- TABLE *open_tables,*temporary_tables, *handler_tables, *derived_tables;
- /*
- During a MySQL session, one can lock tables in two modes: automatic
- or manual. In automatic mode all necessary tables are locked just before
- statement execution, and all acquired locks are stored in 'lock'
- member. Unlocking takes place automatically as well, when the
- statement ends.
- Manual mode comes into play when a user issues a 'LOCK TABLES'
- statement. In this mode the user can only use the locked tables.
- Trying to use any other tables will give an error. The locked tables are
- stored in 'locked_tables' member. Manual locking is described in
- the 'LOCK_TABLES' chapter of the MySQL manual.
- See also lock_tables() for details.
- */
- MYSQL_LOCK *lock; /* Current locks */
- MYSQL_LOCK *locked_tables; /* Tables locked with LOCK */
HASH handler_tables_hash;
/*
One thread can hold up to one named user-level lock. This variable
@@ -787,7 +1159,7 @@ public:
#endif
struct st_my_thread_var *mysys_var;
/*
- Type of current query: COM_PREPARE, COM_QUERY, etc. Set from
+ Type of current query: COM_STMT_PREPARE, COM_QUERY, etc. Set from
first byte of the packet in do_command()
*/
enum enum_server_command command;
@@ -803,16 +1175,18 @@ public:
time_t connect_time,thr_create_time; // track down slow pthread_create
thr_lock_type update_lock_default;
delayed_insert *di;
- my_bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */
+
+ /* <> 0 if we are inside of trigger or stored function. */
+ uint in_sub_stmt;
+
+ /* container for handler's private per-connection data */
+ void *ha_data[MAX_HA];
struct st_transactions {
- IO_CACHE trans_log; // Inited ONLY if binlog is open !
+ SAVEPOINT *savepoints;
THD_TRANS all; // Trans since BEGIN WORK
THD_TRANS stmt; // Trans for current statement
- uint bdb_lock_count;
-#ifdef HAVE_NDBCLUSTER_DB
- void* thd_ndb;
-#endif
- bool on;
+ bool on; // see ha_enable_transaction()
+ XID_STATE xid_state;
/*
Tables changed in transaction (that must be invalidated in query cache).
List contain only transactional tables, that not invalidated in query
@@ -822,9 +1196,20 @@ public:
MEM_ROOT mem_root; // Transaction-life memory allocation pool
void cleanup()
{
- changed_tables = 0;
+ changed_tables= 0;
+ savepoints= 0;
+#ifdef USING_TRANSACTIONS
free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
+#endif
+ }
+#ifdef USING_TRANSACTIONS
+ st_transactions()
+ {
+ bzero((char*)this, sizeof(*this));
+ xid_state.xid.null();
+ init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
}
+#endif
} transaction;
Field *dupp_field;
#ifndef __WIN__
@@ -837,19 +1222,31 @@ public:
This is to track items changed during execution of a prepared
statement/stored procedure. It's created by
register_item_tree_change() in memory root of THD, and freed in
- rollback_item_tree_changes(). For conventional execution it's always 0.
+ rollback_item_tree_changes(). For conventional execution it's always
+ empty.
*/
Item_change_list change_list;
/*
- Current prepared Item_arena if there one, or 0
+ A permanent memory area of the statement. For conventional
+ execution, the parsed tree and execution runtime reside in the same
+ memory root. In this case stmt_arena points to THD. In case of
+ a prepared statement or a stored procedure statement, thd->mem_root
+ conventionally points to runtime memory, and thd->stmt_arena
+ points to the memory of the PS/SP, where the parsed tree of the
+ statement resides. Whenever you need to perform a permanent
+ transformation of a parsed tree, you should allocate new memory in
+ stmt_arena, to allow correct re-execution of PS/SP.
+ Note: in the parser, stmt_arena == thd, even for PS/SP.
*/
- Item_arena *current_arena;
+ Query_arena *stmt_arena;
/*
next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc
*/
ulonglong next_insert_id;
+ /* Remember last next_insert_id to reset it if something went wrong */
+ ulonglong prev_insert_id;
/*
The insert_id used for the last statement or set by SET LAST_INSERT_ID=#
or SELECT LAST_INSERT_ID(#). Used for binary log and returned by
@@ -862,12 +1259,19 @@ public:
*/
ulonglong current_insert_id;
ulonglong limit_found_rows;
+ ulonglong options; /* Bitmap of states */
+ longlong row_count_func; /* For the ROW_COUNT() function */
ha_rows cuted_fields,
sent_row_count, examined_row_count;
+ /*
+ The set of those tables whose fields are referenced in all subqueries
+ of the query.
+ TODO: possibly this it is incorrect to have used tables in THD because
+ with more than one subquery, it is not clear what does the field mean.
+ */
table_map used_tables;
USER_CONN *user_connect;
CHARSET_INFO *db_charset;
- List<TABLE> temporary_tables_should_be_free; // list of temporary tables
/*
FIXME: this, and some other variables like 'count_cuted_fields'
maybe should be statement/cursor local, that is, moved to Statement
@@ -885,8 +1289,8 @@ public:
from table are necessary for this select, to check if it's necessary to
update auto-updatable fields (like auto_increment and timestamp).
*/
- ulong query_id;
- ulong warn_id, version, options, thread_id, col_access;
+ query_id_t query_id, warn_id;
+ ulong thread_id, col_access;
/* Statement id is thread-wide. This counter is used to generate ids */
ulong statement_id_counter;
@@ -894,15 +1298,19 @@ public:
ulong row_count; // Row counter, mainly for errors and warnings
long dbug_thread_id;
pthread_t real_id;
- uint current_tablenr,tmp_table,global_read_lock;
+ uint tmp_table, global_read_lock;
uint server_status,open_options,system_thread;
uint32 db_length;
uint select_number; //number of select (used for EXPLAIN)
/* variables.transaction_isolation is reset to this after each commit */
enum_tx_isolation session_tx_isolation;
enum_check_fields count_cuted_fields;
- /* for user variables replication*/
- DYNAMIC_ARRAY user_var_events;
+
+ DYNAMIC_ARRAY user_var_events; /* For user variables replication */
+ MEM_ROOT *user_var_events_alloc; /* Allocate above array elements here */
+
+ enum killed_state { NOT_KILLED=0, KILL_BAD_DATA=1, KILL_CONNECTION=ER_SERVER_SHUTDOWN, KILL_QUERY=ER_QUERY_INTERRUPTED };
+ killed_state volatile killed;
/* scramble - random string sent to client on handshake */
char scramble[SCRAMBLE_LENGTH+1];
@@ -911,14 +1319,23 @@ public:
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 query_start_used, rand_used, time_zone_used;
+ bool last_insert_id_used,insert_id_used, clear_next_insert_id;
bool in_lock_tables;
bool query_error, bootstrap, cleanup_done;
bool tmp_table_used;
bool charset_is_system_charset, charset_is_collation_connection;
bool enable_slow_log; /* enable slow log for current statement */
- my_bool volatile killed;
+ bool no_trans_update, abort_on_warning;
+ bool got_warning; /* Set on call to push_warning() */
+ bool no_warnings_for_error; /* no warnings on call to my_error() */
+ /* set during loop of derived table processing */
+ bool derived_tables_processing;
+ my_bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */
+
+ sp_rcontext *spcont; // SP runtime context
+ sp_cache *sp_proc_cache;
+ sp_cache *sp_func_cache;
/*
If we do a purge of binary logs, log index info of the threads
@@ -933,7 +1350,33 @@ public:
my_bool my_bool_value;
long long_value;
} sys_var_tmp;
-
+
+ struct {
+ /*
+ If true, mysql_bin_log::write(Log_event) call will not write events to
+ binlog, and maintain 2 below variables instead (use
+ mysql_bin_log.start_union_events to turn this on)
+ */
+ bool do_union;
+ /*
+ If TRUE, at least one mysql_bin_log::write(Log_event) call has been
+ made after last mysql_bin_log.start_union_events() call.
+ */
+ bool unioned_events;
+ /*
+ If TRUE, at least one mysql_bin_log::write(Log_event e), where
+ e.cache_stmt == TRUE call has been made after last
+ mysql_bin_log.start_union_events() call.
+ */
+ bool unioned_events_trans;
+
+ /*
+ 'queries' (actually SP statements) that run under inside this binlog
+ union have thd->query_id >= first_query_id.
+ */
+ query_id_t first_query_id;
+ } binlog_evt_union;
+
THD();
~THD();
@@ -950,6 +1393,7 @@ public:
void init_for_queries();
void change_user(void);
void cleanup(void);
+ void cleanup_after_query();
bool store_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE
inline void set_active_vio(Vio* vio)
@@ -965,18 +1409,18 @@ public:
pthread_mutex_unlock(&LOCK_delete);
}
void close_active_vio();
-#endif
- void awake(bool prepare_to_die);
+#endif
+ void awake(THD::killed_state state_to_set);
/*
For enter_cond() / exit_cond() to work the mutex must be got before
- enter_cond() (in 4.1 an assertion will soon ensure this); this mutex is
- then released by exit_cond(). Use must be:
- lock mutex; enter_cond(); your code; exit_cond().
+ enter_cond(); this mutex is then released by exit_cond().
+ Usage must be: lock mutex; enter_cond(); your code; exit_cond().
*/
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
const char* msg)
{
const char* old_msg = proc_info;
+ safe_mutex_assert_owner(mutex);
mysys_var->current_mutex = mutex;
mysys_var->current_cond = cond;
proc_info = msg;
@@ -1010,7 +1454,7 @@ public:
inline ulonglong insert_id(void)
{
if (!last_insert_id_used)
- {
+ {
last_insert_id_used=1;
current_insert_id=last_insert_id;
}
@@ -1019,19 +1463,21 @@ public:
inline ulonglong found_rows(void)
{
return limit_found_rows;
- }
+ }
inline bool active_transaction()
{
-#ifdef USING_TRANSACTIONS
- return (transaction.all.bdb_tid != 0 ||
- transaction.all.innodb_active_trans != 0 ||
- transaction.all.ndb_tid != 0);
+#ifdef USING_TRANSACTIONS
+ return server_status & SERVER_STATUS_IN_TRANS;
#else
return 0;
#endif
}
- inline gptr trans_alloc(unsigned int size)
- {
+ inline bool fill_derived_tables()
+ {
+ return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure();
+ }
+ inline gptr trans_alloc(unsigned int size)
+ {
return alloc_root(&transaction.mem_root,size);
}
@@ -1051,6 +1497,7 @@ public:
net.last_error[0]= 0;
net.last_errno= 0;
net.report_error= 0;
+ query_error= 0;
}
inline bool vio_ok() const { return net.vio != 0; }
#else
@@ -1060,23 +1507,22 @@ public:
inline void fatal_error()
{
is_fatal_error= 1;
- net.report_error= 1;
+ net.report_error= 1;
DBUG_PRINT("error",("Fatal error set"));
}
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
- inline Item_arena *change_arena_if_needed(Item_arena *backup)
+ inline Query_arena *activate_stmt_arena_if_needed(Query_arena *backup)
{
/*
- use new arena if we are in a prepared statements and we have not
- already changed to use this arena.
+ Use the persistent arena if we are in a prepared statement or a stored
+ procedure statement and we have not already changed to use this arena.
*/
- if (current_arena->is_stmt_prepare() &&
- mem_root != &current_arena->main_mem_root)
+ if (!stmt_arena->is_conventional() && mem_root != stmt_arena->mem_root)
{
- set_n_backup_item_arena(current_arena, backup);
- return current_arena;
+ set_n_backup_active_arena(stmt_arena, backup);
+ return stmt_arena;
}
return 0;
}
@@ -1084,7 +1530,7 @@ public:
void change_item_tree(Item **place, Item *new_value)
{
/* TODO: check for OOM condition here */
- if (!current_arena->is_conventional_execution())
+ if (!stmt_arena->is_conventional())
nocheck_register_item_tree_change(place, *place, mem_root);
*place= new_value;
}
@@ -1097,13 +1543,40 @@ public:
state after execution of a non-prepared SQL statement.
*/
void end_statement();
+ inline int killed_errno() const
+ {
+ return killed != KILL_BAD_DATA ? killed : 0;
+ }
+ inline void send_kill_message() const
+ {
+ int err= killed_errno();
+ if (err)
+ my_message(err, ER(err), MYF(0));
+ }
+ /* return TRUE if we will abort query if we make a warning now */
+ inline bool really_abort_on_warning()
+ {
+ return (abort_on_warning &&
+ (!no_trans_update ||
+ (variables.sql_mode & MODE_STRICT_ALL_TABLES)));
+ }
+ void set_status_var_init();
+ bool is_context_analysis_only()
+ { return stmt_arena->is_stmt_prepare() || lex->view_prepare_mode; }
+ void reset_n_backup_open_tables_state(Open_tables_state *backup);
+ void restore_backup_open_tables_state(Open_tables_state *backup);
+ void reset_sub_statement_state(Sub_statement_state *backup, uint new_state);
+ void restore_sub_statement_state(Sub_statement_state *backup);
+ void set_n_backup_active_arena(Query_arena *set, Query_arena *backup);
+ void restore_active_arena(Query_arena *set, Query_arena *backup);
};
+
#define tmp_disable_binlog(A) \
- ulong save_options= (A)->options; \
- (A)->options&= ~OPTION_BIN_LOG;
+ {ulonglong tmp_disable_binlog__save_options= (A)->options; \
+ (A)->options&= ~OPTION_BIN_LOG
-#define reenable_binlog(A) (A)->options= save_options;
+#define reenable_binlog(A) (A)->options= tmp_disable_binlog__save_options;}
/* Flags for the THD::system_thread (bitmap) variable */
#define SYSTEM_THREAD_DELAYED_INSERT 1
@@ -1135,8 +1608,6 @@ public:
class JOIN;
-void send_error(THD *thd, uint sql_errno=0, const char *err=0);
-
class select_result :public Sql_alloc {
protected:
THD *thd;
@@ -1149,6 +1620,7 @@ public:
unit= u;
return 0;
}
+ virtual int prepare2(void) { return 0; }
/*
Because of peculiarities of prepared statements protocol
we need to know number of columns in the result set (if
@@ -1156,17 +1628,19 @@ public:
*/
virtual uint field_count(List<Item> &fields) const
{ return fields.elements; }
- virtual bool send_fields(List<Item> &list,uint flag)=0;
+ virtual bool send_fields(List<Item> &list, uint flags)=0;
virtual bool send_data(List<Item> &items)=0;
virtual bool initialize_tables (JOIN *join=0) { return 0; }
virtual void send_error(uint errcode,const char *err);
virtual bool send_eof()=0;
+ virtual bool simple_select() { return 0; }
virtual void abort() {}
/*
Cleanup instance of this class for next execution of a prepared
statement/stored procedure.
*/
virtual void cleanup();
+ void set_thd(THD *thd_arg) { thd= thd_arg; }
};
@@ -1185,11 +1659,14 @@ public:
class select_send :public select_result {
+ int status;
public:
- select_send() {}
- bool send_fields(List<Item> &list,uint flag);
+ select_send() :status(0) {}
+ bool send_fields(List<Item> &list, uint flags);
bool send_data(List<Item> &items);
bool send_eof();
+ bool simple_select() { return 1; }
+ void abort();
};
@@ -1233,40 +1710,20 @@ public:
class select_insert :public select_result_interceptor {
public:
+ TABLE_LIST *table_list;
TABLE *table;
List<Item> *fields;
ulonglong last_insert_id;
COPY_INFO info;
- TABLE_LIST *insert_table_list;
- TABLE_LIST *dup_table_list;
+ bool insert_into_view;
- select_insert(TABLE *table_par, List<Item> *fields_par,
- enum_duplicates duplic, bool ignore)
- :table(table_par), fields(fields_par), last_insert_id(0),
- insert_table_list(0), dup_table_list(0)
- {
- bzero((char*) &info,sizeof(info));
- info.ignore= ignore;
- info.handle_duplicates=duplic;
- }
- select_insert(TABLE *table_par,
- TABLE_LIST *insert_table_list_par,
- TABLE_LIST *dup_table_list_par,
- List<Item> *fields_par,
+ select_insert(TABLE_LIST *table_list_par,
+ TABLE *table_par, List<Item> *fields_par,
List<Item> *update_fields, List<Item> *update_values,
- enum_duplicates duplic, bool ignore)
- :table(table_par), fields(fields_par), last_insert_id(0),
- insert_table_list(insert_table_list_par),
- dup_table_list(dup_table_list_par)
- {
- bzero((char*) &info,sizeof(info));
- info.ignore= ignore;
- info.handle_duplicates= duplic;
- info.update_fields= update_fields;
- info.update_values= update_values;
- }
+ enum_duplicates duplic, bool ignore);
~select_insert();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
+ int prepare2(void);
bool send_data(List<Item> &items);
virtual void store_values(List<Item> &values);
void send_error(uint errcode,const char *err);
@@ -1278,22 +1735,21 @@ class select_insert :public select_result_interceptor {
class select_create: public select_insert {
ORDER *group;
- const char *db;
- const char *name;
+ TABLE_LIST *create_table;
List<create_field> *extra_fields;
List<Key> *keys;
HA_CREATE_INFO *create_info;
MYSQL_LOCK *lock;
Field **field;
public:
- select_create(const char *db_name, const char *table_name,
- HA_CREATE_INFO *create_info_par,
- List<create_field> &fields_par,
- List<Key> &keys_par,
- List<Item> &select_fields,enum_duplicates duplic, bool ignore)
- :select_insert (NULL, &select_fields, duplic, ignore), db(db_name),
- name(table_name), extra_fields(&fields_par),keys(&keys_par),
- create_info(create_info_par), lock(0)
+ select_create (TABLE_LIST *table,
+ HA_CREATE_INFO *create_info_par,
+ List<create_field> &fields_par,
+ List<Key> &keys_par,
+ List<Item> &select_fields,enum_duplicates duplic, bool ignore)
+ :select_insert (NULL, NULL, &select_fields, 0, 0, duplic, ignore), create_table(table),
+ extra_fields(&fields_par),keys(&keys_par), create_info(create_info_par),
+ lock(0)
{}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
void store_values(List<Item> &values);
@@ -1334,10 +1790,13 @@ public:
bool using_indirect_summary_function;
/* If >0 convert all blob fields to varchar(convert_blob_length) */
uint convert_blob_length;
+ CHARSET_INFO *table_charset;
+ bool schema_table;
TMP_TABLE_PARAM()
:copy_field(0), group_parts(0),
- group_length(0), group_null_parts(0), convert_blob_length(0)
+ group_length(0), group_null_parts(0), convert_blob_length(0),
+ schema_table(0)
{}
~TMP_TABLE_PARAM()
{
@@ -1357,7 +1816,6 @@ public:
class select_union :public select_result_interceptor {
public:
TABLE *table;
- COPY_INFO info;
TMP_TABLE_PARAM tmp_table_param;
select_union(TABLE *table_par);
@@ -1402,6 +1860,7 @@ public:
bool send_data(List<Item> &items);
bool cmp_real();
bool cmp_int();
+ bool cmp_decimal();
bool cmp_str();
};
@@ -1472,17 +1931,24 @@ class user_var_entry
public:
LEX_STRING name;
char *value;
- ulong length, update_query_id, used_query_id;
+ ulong length;
+ query_id_t update_query_id, used_query_id;
Item_result type;
- double val(my_bool *null_value);
+ double val_real(my_bool *null_value);
longlong val_int(my_bool *null_value);
String *val_str(my_bool *null_value, String *str, uint decimals);
+ my_decimal *val_decimal(my_bool *null_value, my_decimal *result);
DTCollation collation;
};
-
-/* Class for unique (removing of duplicates) */
+/*
+ Unique -- class for unique (removing of duplicates).
+ Puts all values to the TREE. If the tree becomes too big,
+ it's dumped to the file. User can request sorted values, or
+ just iterate through them. In the last case tree merging is performed in
+ memory simultaneously with iteration, so it should be ~2-3x faster.
+ */
class Unique :public Sql_alloc
{
@@ -1496,17 +1962,32 @@ class Unique :public Sql_alloc
public:
ulong elements;
- Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
+ Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
uint size_arg, ulong max_in_memory_size_arg);
~Unique();
- inline bool unique_add(gptr ptr)
+ ulong elements_in_tree() { return tree.elements_in_tree; }
+ inline bool unique_add(void *ptr)
{
+ DBUG_ENTER("unique_add");
+ DBUG_PRINT("info", ("tree %u - %u", tree.elements_in_tree, max_elements));
if (tree.elements_in_tree > max_elements && flush())
- return 1;
- return !tree_insert(&tree, ptr, 0, tree.custom_arg);
+ DBUG_RETURN(1);
+ DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg));
}
bool get(TABLE *table);
+ static double get_use_cost(uint *buffer, uint nkeys, uint key_size,
+ ulong max_in_memory_size);
+ inline static int get_cost_calc_buff_size(ulong nkeys, uint key_size,
+ ulong max_in_memory_size)
+ {
+ register ulong max_elems_in_tree=
+ (1 + max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size));
+ return sizeof(uint)*(1 + nkeys/max_elems_in_tree);
+ }
+
+ void reset();
+ bool walk(tree_walk_action action, void *walk_action_arg);
friend int unique_write_to_file(gptr key, element_count count, Unique *unique);
friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique);
@@ -1517,27 +1998,33 @@ class multi_delete :public select_result_interceptor
{
TABLE_LIST *delete_tables, *table_being_deleted;
Unique **tempfiles;
- THD *thd;
ha_rows deleted, found;
uint num_of_tables;
int error;
- bool do_delete, transactional_tables, log_delayed, normal_tables;
+ bool do_delete;
+ /* True if at least one table we delete from is transactional */
+ bool transactional_tables;
+ /* True if at least one table we delete from is not transactional */
+ bool normal_tables;
+ bool delete_while_scanning;
+
public:
- multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
+ multi_delete(TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
void send_error(uint errcode,const char *err);
- int do_deletes (bool from_send_error);
+ int do_deletes();
bool send_eof();
};
class multi_update :public select_result_interceptor
{
- TABLE_LIST *all_tables, *update_tables, *table_being_updated;
- THD *thd;
+ TABLE_LIST *all_tables; /* query/update command tables */
+ TABLE_LIST *leaves; /* list of leves of join table tree */
+ TABLE_LIST *update_tables, *table_being_updated;
TABLE **tmp_tables, *main_table, *table_to_update;
TMP_TABLE_PARAM *tmp_table_param;
ha_rows updated, found;
@@ -1546,11 +2033,15 @@ class multi_update :public select_result_interceptor
uint table_count;
Copy_field *copy_field;
enum enum_duplicates handle_duplicates;
- bool do_update, trans_safe, transactional_tables, log_delayed, ignore;
+ bool do_update, trans_safe;
+ /* True if the update operation has made a change in a transactional table */
+ bool transactional_tables;
+ bool ignore;
public:
- multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> *fields,
- List<Item> *values, enum_duplicates handle_duplicates, bool ignore);
+ multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list,
+ List<Item> *fields, List<Item> *values,
+ enum_duplicates handle_duplicates, bool ignore);
~multi_update();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
@@ -1560,16 +2051,32 @@ public:
bool send_eof();
};
+class my_var : public Sql_alloc {
+public:
+ LEX_STRING s;
+ bool local;
+ uint offset;
+ enum_field_types type;
+ my_var (LEX_STRING& j, bool i, uint o, enum_field_types t)
+ :s(j), local(i), offset(o), type(t)
+ {}
+ ~my_var() {}
+};
class select_dumpvar :public select_result_interceptor {
ha_rows row_count;
public:
- List<LEX_STRING> var_list;
+ List<my_var> var_list;
List<Item_func_set_user_var> vars;
- select_dumpvar(void) { var_list.empty(); vars.empty(); row_count=0;}
+ List<Item_splocal> local_vars;
+ select_dumpvar(void) { var_list.empty(); local_vars.empty(); vars.empty(); row_count=0;}
~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
bool send_eof();
void cleanup();
};
+
+/* Functions in sql_class.cc */
+
+void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 7c834c91183..69ccbe690db 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -19,6 +19,7 @@
#include "mysql_priv.h"
#include <mysys_err.h>
+#include "sp.h"
#include <my_dir.h>
#include <m_ctype.h>
#ifdef __WIN__
@@ -35,6 +36,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
const char *db, const char *path, uint level,
TABLE_LIST **dropped_tables);
+static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path);
+static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error);
/* Database options hash */
static HASH dboptions;
static my_bool dboptions_init= 0;
@@ -389,13 +392,13 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
In this case the entry should not be logged.
RETURN VALUES
- 0 ok
- -1 Error
+ FALSE ok
+ TRUE Error
*/
-int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
- bool silent)
+bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
+ bool silent)
{
char path[FN_REFLEN+16];
long result= 1;
@@ -404,6 +407,13 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
uint create_options= create_info ? create_info->options : 0;
uint path_len;
DBUG_ENTER("mysql_create_db");
+
+ /* do not create 'information_schema' db */
+ if (!my_strcasecmp(system_charset_info, db, information_schema_name.str))
+ {
+ my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
+ DBUG_RETURN(-1);
+ }
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
@@ -423,7 +433,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
{
if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
{
- my_error(ER_DB_CREATE_EXISTS,MYF(0),db);
+ my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
error= -1;
goto exit;
}
@@ -437,12 +447,12 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
{
if (my_errno != ENOENT)
{
- my_error(EE_STAT, MYF(0),path,my_errno);
+ my_error(EE_STAT, MYF(0), path, my_errno);
goto exit;
}
if (my_mkdir(path,0777,MYF(0)) < 0)
{
- my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
+ my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
error= -1;
goto exit;
}
@@ -485,7 +495,6 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
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,
@@ -526,7 +535,7 @@ exit2:
/* db-name is already validated when we come here */
-int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
+bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
{
char path[FN_REFLEN+16];
long result=1;
@@ -557,7 +566,6 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
thd->variables.collation_database= thd->db_charset;
}
- mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
@@ -580,7 +588,7 @@ exit:
start_waiting_global_read_lock(thd);
exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
- DBUG_RETURN(error ? -1 : 0); /* -1 to delegate send_error() */
+ DBUG_RETURN(error);
}
@@ -591,20 +599,21 @@ exit2:
mysql_rm_db()
thd Thread handle
db Database name in the case given by user
- It's already validated when we come here
+ It's already validated and set to lower case
+ (if needed) when we come here
if_exists Don't give error if database doesn't exists
silent Don't generate errors
RETURN
- 0 ok (Database dropped)
- -1 Error generated
+ FALSE ok (Database dropped)
+ ERROR Error
*/
-int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
+bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
{
long deleted=0;
int error= 0;
- char path[FN_REFLEN+16], tmp_db[NAME_LEN+1];
+ char path[FN_REFLEN+16];
MY_DIR *dirp;
uint length;
TABLE_LIST* dropped_tables= 0;
@@ -631,7 +640,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
if (!if_exists)
{
error= -1;
- my_error(ER_DB_DROP_EXISTS,MYF(0),db);
+ my_error(ER_DB_DROP_EXISTS, MYF(0), db);
goto exit;
}
else
@@ -654,13 +663,6 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
error = 0;
}
}
- if (lower_case_table_names)
- {
- /* Convert database to lower case */
- strmov(tmp_db, db);
- my_casedn_str(files_charset_info, tmp_db);
- db= tmp_db;
- }
if (!silent && deleted>=0)
{
const char *query;
@@ -677,7 +679,6 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
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,
@@ -709,12 +710,12 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
query_end= query + MAX_DROP_TABLE_Q_LEN;
db_len= strlen(db);
- for (tbl= dropped_tables; tbl; tbl= tbl->next)
+ for (tbl= dropped_tables; tbl; tbl= tbl->next_local)
{
uint tbl_name_len;
/* 3 for the quotes and the comma*/
- tbl_name_len= strlen(tbl->real_name) + 3;
+ tbl_name_len= strlen(tbl->table_name) + 3;
if (query_pos + tbl_name_len + 1 >= query_end)
{
write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
@@ -722,7 +723,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
}
*query_pos++ = '`';
- query_pos= strmov(query_pos,tbl->real_name);
+ query_pos= strmov(query_pos,tbl->table_name);
*query_pos++ = '`';
*query_pos++ = ',';
}
@@ -734,6 +735,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
}
exit:
+ (void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
start_waiting_global_read_lock(thd);
/*
If this database was the client's selected database, we silently change the
@@ -803,9 +805,9 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
continue;
/* Check if file is a raid directory */
- if ((my_isdigit(&my_charset_latin1, file->name[0]) ||
+ if ((my_isdigit(system_charset_info, file->name[0]) ||
(file->name[0] >= 'a' && file->name[0] <= 'f')) &&
- (my_isdigit(&my_charset_latin1, file->name[1]) ||
+ (my_isdigit(system_charset_info, file->name[1]) ||
(file->name[1] >= 'a' && file->name[1] <= 'f')) &&
!file->name[2] && !level)
{
@@ -831,6 +833,24 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
found_other_files++;
continue;
}
+ else if (file->name[0] == 'a' && file->name[1] == 'r' &&
+ file->name[2] == 'c' && file->name[3] == '\0')
+ {
+ /* .frm archive */
+ char newpath[FN_REFLEN];
+ MY_DIR *new_dirp;
+ strxmov(newpath, org_path, "/", "arc", NullS);
+ (void) unpack_filename(newpath, newpath);
+ if ((new_dirp = my_dir(newpath, MYF(MY_DONT_SORT))))
+ {
+ DBUG_PRINT("my",("Archive subdir found: %s", newpath));
+ if ((mysql_rm_arc_files(thd, new_dirp, newpath)) < 0)
+ goto err;
+ continue;
+ }
+ found_other_files++;
+ continue;
+ }
extension= fn_ext(file->name);
if (find_type(extension, &deletable_extentions,1+2) <= 0)
{
@@ -849,11 +869,11 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
if (!table_list)
goto err;
table_list->db= (char*) (table_list+1);
- strmov(table_list->real_name= strmov(table_list->db,db)+1, file->name);
- table_list->alias= table_list->real_name; // If lower_case_table_names=2
+ strmov(table_list->table_name= strmov(table_list->db,db)+1, file->name);
+ table_list->alias= table_list->table_name; // If lower_case_table_names=2
/* Link into list */
(*tot_list_next)= table_list;
- tot_list_next= &table_list->next;
+ tot_list_next= &table_list->next_local;
deleted++;
}
else
@@ -893,44 +913,141 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
}
else
{
- char tmp_path[FN_REFLEN], *pos;
- char *path= tmp_path;
- unpack_filename(tmp_path,org_path);
+ /* Don't give errors if we can't delete 'RAID' directory */
+ if (rm_dir_w_symlink(org_path, level == 0))
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(deleted);
+
+err:
+ my_dirend(dirp);
+ DBUG_RETURN(-1);
+}
+
+
+/*
+ Remove directory with symlink
+
+ SYNOPSIS
+ rm_dir_w_symlink()
+ org_path path of derictory
+ send_error send errors
+ RETURN
+ 0 OK
+ 1 ERROR
+*/
+
+static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error)
+{
+ char tmp_path[FN_REFLEN], *pos;
+ char *path= tmp_path;
+ DBUG_ENTER("rm_dir_w_symlink");
+ unpack_filename(tmp_path, org_path);
#ifdef HAVE_READLINK
- int error;
-
- /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
- pos=strend(path);
- if (pos > path && pos[-1] == FN_LIBCHAR)
- *--pos=0;
+ int error;
+ char tmp2_path[FN_REFLEN];
- if ((error=my_readlink(filePath, path, MYF(MY_WME))) < 0)
- DBUG_RETURN(-1);
- if (!error)
+ /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
+ pos= strend(path);
+ if (pos > path && pos[-1] == FN_LIBCHAR)
+ *--pos=0;
+
+ if ((error= my_readlink(tmp2_path, path, MYF(MY_WME))) < 0)
+ DBUG_RETURN(1);
+ if (!error)
+ {
+ if (my_delete(path, MYF(send_error ? MY_WME : 0)))
{
- if (my_delete(path,MYF(!level ? MY_WME : 0)))
- {
- /* Don't give errors if we can't delete 'RAID' directory */
- if (level)
- DBUG_RETURN(deleted);
- DBUG_RETURN(-1);
- }
- /* Delete directory symbolic link pointed at */
- path= filePath;
+ DBUG_RETURN(send_error);
}
+ /* Delete directory symbolic link pointed at */
+ path= tmp2_path;
+ }
#endif
- /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
- pos=strend(path);
+ /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
+ pos= strend(path);
- if (pos > path && pos[-1] == FN_LIBCHAR)
- *--pos=0;
- /* Don't give errors if we can't delete 'RAID' directory */
- if (rmdir(path) < 0 && !level)
+ if (pos > path && pos[-1] == FN_LIBCHAR)
+ *--pos=0;
+ if (rmdir(path) < 0 && send_error)
+ {
+ my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Remove .frm archives from directory
+
+ SYNOPSIS
+ thd thread handler
+ dirp list of files in archive directory
+ db data base name
+ org_path path of archive directory
+
+ RETURN
+ > 0 number of removed files
+ -1 error
+*/
+static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp,
+ const char *org_path)
+{
+ long deleted= 0;
+ ulong found_other_files= 0;
+ char filePath[FN_REFLEN];
+ DBUG_ENTER("mysql_rm_arc_files");
+ DBUG_PRINT("enter", ("path: %s", org_path));
+
+ for (uint idx=0 ;
+ idx < (uint) dirp->number_off_files && !thd->killed ;
+ idx++)
+ {
+ FILEINFO *file=dirp->dir_entry+idx;
+ char *extension, *revision;
+ DBUG_PRINT("info",("Examining: %s", file->name));
+
+ /* skiping . and .. */
+ if (file->name[0] == '.' && (!file->name[1] ||
+ (file->name[1] == '.' && !file->name[2])))
+ continue;
+
+ extension= fn_ext(file->name);
+ if (extension[0] != '.' ||
+ extension[1] != 'f' || extension[2] != 'r' ||
+ extension[3] != 'm' || extension[4] != '-')
{
- my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
- DBUG_RETURN(-1);
+ found_other_files++;
+ continue;
+ }
+ revision= extension+5;
+ while (*revision && my_isdigit(system_charset_info, *revision))
+ revision++;
+ if (*revision)
+ {
+ found_other_files++;
+ continue;
+ }
+ strxmov(filePath, org_path, "/", file->name, NullS);
+ if (my_delete_with_symlink(filePath,MYF(MY_WME)))
+ {
+ goto err;
}
}
+ if (thd->killed)
+ goto err;
+
+ my_dirend(dirp);
+
+ /*
+ If the directory is a symbolic link, remove the link first, then
+ remove the directory the symbolic link pointed at
+ */
+ if (!found_other_files &&
+ rm_dir_w_symlink(org_path, 0))
+ DBUG_RETURN(-1);
DBUG_RETURN(deleted);
err:
@@ -944,8 +1061,9 @@ err:
SYNOPSIS
mysql_change_db()
- thd Thread handler
- name Databasename
+ thd Thread handler
+ name Databasename
+ no_access_check True don't do access check. In this case name may be ""
DESCRIPTION
Becasue the database name may have been given directly from the
@@ -957,53 +1075,80 @@ err:
replication slave SQL thread (for that thread, setting of thd->db is done
in ::exec_event() methods of log_event.cc).
+ This function does not send anything, including error messages to the
+ client, if that should be sent to the client, call net_send_error after
+ this function.
+
RETURN VALUES
0 ok
1 error
*/
-bool mysql_change_db(THD *thd, const char *name)
+bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
{
int length, db_length;
char *dbname=my_strdup((char*) name,MYF(MY_WME));
char path[FN_REFLEN];
HA_CREATE_INFO create;
+ bool system_db= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
ulong db_access;
#endif
DBUG_ENTER("mysql_change_db");
+ DBUG_PRINT("enter",("name: '%s'",name));
+ /* dbname can only be NULL if malloc failed */
if (!dbname || !(db_length= strlen(dbname)))
{
+ if (no_access_check && dbname)
+ {
+ /* Called from SP when orignal database was not set */
+ system_db= 1;
+ goto end;
+ }
x_free(dbname); /* purecov: inspected */
- send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
+ MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
if (check_db_name(dbname))
{
- net_printf(thd, ER_WRONG_DB_NAME, dbname);
+ my_error(ER_WRONG_DB_NAME, MYF(0), dbname);
x_free(dbname);
DBUG_RETURN(1);
}
DBUG_PRINT("info",("Use database: %s", dbname));
+ if (!my_strcasecmp(system_charset_info, dbname, information_schema_name.str))
+ {
+ system_db= 1;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (test_all_bits(thd->master_access,DB_ACLS))
- db_access=DB_ACLS;
- else
- db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
- thd->master_access);
- if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
+ db_access= SELECT_ACL;
+#endif
+ goto end;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (!no_access_check)
{
- net_printf(thd,ER_DBACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- dbname);
- mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
- thd->priv_user,
- thd->priv_host,
- dbname);
- my_free(dbname,MYF(0));
- DBUG_RETURN(1);
+ if (test_all_bits(thd->master_access,DB_ACLS))
+ db_access=DB_ACLS;
+ else
+ db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
+ thd->master_access);
+ if (!(db_access & DB_ACLS) && (!grant_option ||
+ check_grant_db(thd,dbname)))
+ {
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user,
+ thd->priv_host,
+ dbname);
+ mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
+ thd->priv_user,
+ thd->priv_host,
+ dbname);
+ my_free(dbname,MYF(0));
+ DBUG_RETURN(1);
+ }
}
#endif
(void) sprintf(path,"%s/%s",mysql_data_home,dbname);
@@ -1012,22 +1157,31 @@ bool mysql_change_db(THD *thd, const char *name)
path[length-1]=0; // remove ending '\'
if (my_access(path,F_OK))
{
- net_printf(thd,ER_BAD_DB_ERROR,dbname);
+ my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
}
- send_ok(thd);
+end:
x_free(thd->db);
thd->db=dbname; // THD::~THD will free this
thd->db_length=db_length;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- thd->db_access=db_access;
+ if (!no_access_check)
+ thd->db_access=db_access;
#endif
- strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
- load_db_opt(thd, path, &create);
- thd->db_charset= create.default_table_charset ?
- create.default_table_charset :
- thd->variables.collation_server;
- thd->variables.collation_database= thd->db_charset;
+ if (system_db)
+ {
+ thd->db_charset= system_charset_info;
+ thd->variables.collation_database= system_charset_info;
+ }
+ else
+ {
+ strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
+ load_db_opt(thd, path, &create);
+ thd->db_charset= create.default_table_charset ?
+ create.default_table_charset :
+ thd->variables.collation_server;
+ thd->variables.collation_database= thd->db_charset;
+ }
DBUG_RETURN(0);
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 7248adf6993..7fb9f9eccdd 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -14,54 +14,66 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
/*
Delete of records and truncate of tables.
Multi-table deletes were introduced by Monty and Sinisa
*/
-
-
#include "mysql_priv.h"
#include "ha_innodb.h"
#include "sql_select.h"
+#include "sp_head.h"
+#include "sql_trigger.h"
-int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
- ha_rows limit, ulong options)
+bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
+ SQL_LIST *order, ha_rows limit, ulonglong options,
+ bool reset_auto_increment)
{
int error;
TABLE *table;
SQL_SELECT *select=0;
READ_RECORD info;
- bool using_limit=limit != HA_POS_ERROR;
- bool transactional_table, log_delayed, safe_update, const_cond;
+ bool using_limit=limit != HA_POS_ERROR;
+ bool transactional_table, safe_update, const_cond;
ha_rows deleted;
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_delete");
- if ((open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(-1);
- table= table_list->table;
+ if (open_and_lock_tables(thd, table_list))
+ DBUG_RETURN(TRUE);
+ if (!(table= table_list->table))
+ {
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
table->map=1;
- if ((error= mysql_prepare_delete(thd, table_list, &conds)))
- DBUG_RETURN(error);
+ if (mysql_prepare_delete(thd, table_list, &conds))
+ DBUG_RETURN(TRUE);
const_cond= (!conds || conds->const_item());
safe_update=test(thd->options & OPTION_SAFE_UPDATES);
if (safe_update && const_cond)
{
- send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
+ DBUG_RETURN(TRUE);
}
- thd->lex->select_lex.no_error= thd->lex->ignore;
+ select_lex->no_error= thd->lex->ignore;
- /* Test if the user wants to delete all rows */
+ /*
+ Test if the user wants to delete all rows and deletion doesn't have
+ any side-effects (because of triggers), so we can use optimized
+ handler::delete_all_rows() method.
+ */
if (!using_limit && const_cond && (!conds || conds->val_int()) &&
- !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
+ !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
+ !(table->triggers && table->triggers->has_delete_triggers()))
{
deleted= table->file->records;
if (!(error=table->file->delete_all_rows()))
@@ -80,14 +92,22 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
table->used_keys.clear_all();
table->quick_keys.clear_all(); // Can't use 'only index'
- select=make_select(table,0,0,conds,&error);
+ select=make_select(table, 0, 0, conds, 0, &error);
if (error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, select_lex);
+ thd->row_count_func= 0;
send_ok(thd,0L);
+
+ /*
+ We don't need to call reset_auto_increment in this case, because
+ mysql_truncate always gives a NULL conds argument, hence we never
+ get here.
+ */
+
DBUG_RETURN(0); // Nothing to delete
}
@@ -98,9 +118,10 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
if (safe_update && !using_limit)
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
- send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
+ free_underlaid_joins(thd, select_lex);
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
+ DBUG_RETURN(TRUE);
}
}
if (options & OPTION_QUICK)
@@ -121,8 +142,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
- if (thd->lex->select_lex.setup_ref_array(thd, order->elements) ||
- setup_order(thd, thd->lex->select_lex.ref_pointer_array, &tables,
+ if (select_lex->setup_ref_array(thd, order->elements) ||
+ setup_order(thd, select_lex->ref_pointer_array, &tables,
fields, all_fields, (ORDER*) order->first) ||
!(sortorder=make_unireg_sortorder((ORDER*) order->first, &length)) ||
(table->sort.found_records = filesort(thd, table, sortorder, length,
@@ -131,8 +152,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
== HA_POS_ERROR)
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
- DBUG_RETURN(-1); // This will force out message
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(TRUE);
}
/*
Filesort has already found and selected the rows we want to delete,
@@ -142,9 +163,16 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
select= 0;
}
+ /* If quick select is used, initialize it before retrieving rows. */
+ if (select && select->quick && select->quick->reset())
+ {
+ delete select;
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(TRUE);
+ }
init_read_record(&info,thd,table,select,1,1);
deleted=0L;
- init_ftfuncs(thd, &thd->lex->select_lex, 1);
+ init_ftfuncs(thd, select_lex, 1);
thd->proc_info="updating";
while (!(error=info.read_record(&info)) && !thd->killed &&
!thd->net.report_error)
@@ -152,9 +180,25 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
// thd->net.report_error is tested to disallow delete row on error
if (!(select && select->skip_record())&& !thd->net.report_error )
{
+
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+ TRG_ACTION_BEFORE, FALSE))
+ {
+ error= 1;
+ break;
+ }
+
if (!(error=table->file->delete_row(table->record[0])))
{
deleted++;
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER, FALSE))
+ {
+ error= 1;
+ break;
+ }
if (!--limit && using_limit)
{
error= -1;
@@ -187,6 +231,21 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
if (options & OPTION_QUICK)
(void) table->file->extra(HA_EXTRA_NORMAL);
+ if (reset_auto_increment && (error < 0))
+ {
+ /*
+ We're really doing a truncate and need to reset the table's
+ auto-increment counter.
+ */
+ int error2= table->file->reset_auto_increment(0);
+
+ if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
+ {
+ table->file->print_error(error2, MYF(0));
+ error= 1;
+ }
+ }
+
cleanup:
/*
Invalidate the table in the query cache if something changed. This must
@@ -199,7 +258,6 @@ cleanup:
delete select;
transactional_table= table->file->has_transactions();
- log_delayed= (transactional_table || table->tmp_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
@@ -210,17 +268,16 @@ cleanup:
*/
if ((deleted || (error < 0)) && (error <= 0 || !transactional_table))
{
- mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
if (error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed, FALSE);
+ transactional_table, FALSE);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!log_delayed)
+ if (!transactional_table)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (transactional_table)
@@ -234,15 +291,14 @@ cleanup:
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
- free_underlaid_joins(thd, &thd->lex->select_lex);
- if (error >= 0 || thd->net.report_error)
- send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
- else
+ free_underlaid_joins(thd, select_lex);
+ if (error < 0)
{
+ thd->row_count_func= deleted;
send_ok(thd,deleted);
DBUG_PRINT("info",("%d records deleted",deleted));
}
- DBUG_RETURN(0);
+ DBUG_RETURN(error >= 0 || thd->net.report_error);
}
@@ -252,30 +308,40 @@ cleanup:
SYNOPSIS
mysql_prepare_delete()
thd - thread handler
- table_list - global table list
+ table_list - global/local table list
conds - conditions
RETURN VALUE
- 0 - OK
- 1 - error (message is sent to user)
- -1 - error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
+bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
{
- TABLE_LIST *delete_table_list= ((TABLE_LIST*) thd->lex->
- select_lex.table_list.first);
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_delete");
- if (setup_conds(thd, delete_table_list, conds) ||
- setup_ftfuncs(&thd->lex->select_lex))
- DBUG_RETURN(-1);
- if (find_real_table_in_list(table_list->next,
- table_list->db, table_list->real_name))
+ if (setup_tables(thd, &thd->lex->select_lex.context,
+ &thd->lex->select_lex.top_join_list,
+ table_list, conds, &select_lex->leaf_tables,
+ FALSE) ||
+ setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
+ setup_ftfuncs(select_lex))
+ DBUG_RETURN(TRUE);
+ if (!table_list->updatable || check_key_in_view(thd, table_list))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
- DBUG_RETURN(-1);
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ {
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(table_list, table_list->next_global)))
+ {
+ update_non_unique_table_error(table_list, "DELETE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ select_lex->fix_prepare_information(thd, conds);
+ DBUG_RETURN(FALSE);
}
@@ -285,19 +351,97 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
-extern "C" int refposcmp2(void* arg, const void *a,const void *b)
+extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
{
- /* arg is a pointer to file->ref_length */
- return memcmp(a,b, *(int*) arg);
+ handler *file= (handler*)arg;
+ return file->cmp_ref((const byte*)a, (const byte*)b);
}
-multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
- uint num_of_tables_arg)
- : delete_tables(dt), thd(thd_arg), deleted(0), found(0),
+/*
+ make delete specific preparation and checks after opening tables
+
+ SYNOPSIS
+ mysql_multi_delete_prepare()
+ thd thread handler
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+bool mysql_multi_delete_prepare(THD *thd)
+{
+ LEX *lex= thd->lex;
+ TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxilliary_table_list.first;
+ TABLE_LIST *target_tbl;
+ DBUG_ENTER("mysql_multi_delete_prepare");
+
+ /*
+ setup_tables() need for VIEWs. JOIN::prepare() will not do it second
+ time.
+
+ lex->query_tables also point on local list of DELETE SELECT_LEX
+ */
+ if (setup_tables(thd, &thd->lex->select_lex.context,
+ &thd->lex->select_lex.top_join_list,
+ lex->query_tables, &lex->select_lex.where,
+ &lex->select_lex.leaf_tables, FALSE))
+ DBUG_RETURN(TRUE);
+
+
+ /*
+ Multi-delete can't be constructed over-union => we always have
+ single SELECT on top and have to check underlying SELECTs of it
+ */
+ lex->select_lex.exclude_from_table_unique_test= TRUE;
+ /* Fix tables-to-be-deleted-from list to point at opened tables */
+ for (target_tbl= (TABLE_LIST*) aux_tables;
+ target_tbl;
+ target_tbl= target_tbl->next_local)
+ {
+ if (!(target_tbl->table= target_tbl->correspondent_table->table))
+ {
+ DBUG_ASSERT(target_tbl->correspondent_table->view &&
+ target_tbl->correspondent_table->ancestor &&
+ target_tbl->correspondent_table->ancestor->next_local);
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ target_tbl->correspondent_table->view_db.str,
+ target_tbl->correspondent_table->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!target_tbl->correspondent_table->updatable ||
+ check_key_in_view(thd, target_tbl->correspondent_table))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
+ target_tbl->table_name, "DELETE");
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ Check that table from which we delete is not used somewhere
+ inside subqueries/view.
+ */
+ {
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(target_tbl->correspondent_table,
+ lex->query_tables)))
+ {
+ update_non_unique_table_error(target_tbl->correspondent_table,
+ "DELETE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
+ : delete_tables(dt), deleted(0), found(0),
num_of_tables(num_of_tables_arg), error(0),
- do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
+ do_delete(0), transactional_tables(0), normal_tables(0)
{
- tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
+ tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
}
@@ -323,10 +467,11 @@ multi_delete::initialize_tables(JOIN *join)
DBUG_RETURN(1);
table_map tables_to_delete_from=0;
- for (walk= delete_tables ; walk ; walk=walk->next)
+ for (walk= delete_tables; walk; walk= walk->next_local)
tables_to_delete_from|= walk->table->map;
walk= delete_tables;
+ delete_while_scanning= 1;
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
tab < end;
tab++)
@@ -335,27 +480,40 @@ multi_delete::initialize_tables(JOIN *join)
{
/* We are going to delete from this table */
TABLE *tbl=walk->table=tab->table;
- walk=walk->next;
+ walk= walk->next_local;
/* Don't use KEYREAD optimization on this table */
tbl->no_keyread=1;
/* Don't use record cache */
tbl->no_cache= 1;
tbl->used_keys.clear_all();
if (tbl->file->has_transactions())
- log_delayed= transactional_tables= 1;
- else if (tbl->tmp_table != NO_TMP_TABLE)
- log_delayed= 1;
+ transactional_tables= 1;
else
normal_tables= 1;
}
+ else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
+ walk == delete_tables)
+ {
+ /*
+ We are not deleting from the table we are scanning. In this
+ case send_data() shouldn't delete any rows a we may touch
+ the rows in the deleted table many times
+ */
+ delete_while_scanning= 0;
+ }
}
walk= delete_tables;
tempfiles_ptr= tempfiles;
- for (walk=walk->next ; walk ; walk=walk->next)
+ if (delete_while_scanning)
+ {
+ table_being_deleted= delete_tables;
+ walk= walk->next_local;
+ }
+ for (;walk ;walk= walk->next_local)
{
TABLE *table=walk->table;
- *tempfiles_ptr++= new Unique (refposcmp2,
- (void *) &table->file->ref_length,
+ *tempfiles_ptr++= new Unique (refpos_order_cmp,
+ (void *) table->file,
table->file->ref_length,
MEM_STRIP_BUF_SIZE);
}
@@ -366,16 +524,16 @@ multi_delete::initialize_tables(JOIN *join)
multi_delete::~multi_delete()
{
- for (table_being_deleted=delete_tables ;
- table_being_deleted ;
- table_being_deleted=table_being_deleted->next)
+ for (table_being_deleted= delete_tables;
+ table_being_deleted;
+ table_being_deleted= table_being_deleted->next_local)
{
- TABLE *t=table_being_deleted->table;
- free_io_cache(t); // Alloced by unique
- t->no_keyread=0;
+ TABLE *table= table_being_deleted->table;
+ free_io_cache(table); // Alloced by unique
+ table->no_keyread=0;
}
- for (uint counter= 0; counter < num_of_tables-1; counter++)
+ for (uint counter= 0; counter < num_of_tables; counter++)
{
if (tempfiles[counter])
delete tempfiles[counter];
@@ -385,14 +543,15 @@ multi_delete::~multi_delete()
bool multi_delete::send_data(List<Item> &values)
{
- int secure_counter= -1;
+ int secure_counter= delete_while_scanning ? -1 : 0;
+ TABLE_LIST *del_table;
DBUG_ENTER("multi_delete::send_data");
- for (table_being_deleted=delete_tables ;
- table_being_deleted ;
- table_being_deleted=table_being_deleted->next, secure_counter++)
+ for (del_table= delete_tables;
+ del_table;
+ del_table= del_table->next_local, secure_counter++)
{
- TABLE *table=table_being_deleted->table;
+ TABLE *table= del_table->table;
/* Check if we are using outer join and we didn't find the row */
if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
@@ -403,11 +562,22 @@ bool multi_delete::send_data(List<Item> &values)
if (secure_counter < 0)
{
- /* If this is the table we are scanning */
+ /* We are scanning the current table */
+ DBUG_ASSERT(del_table == table_being_deleted);
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+ TRG_ACTION_BEFORE, FALSE))
+ DBUG_RETURN(1);
table->status|= STATUS_DELETED;
if (!(error=table->file->delete_row(table->record[0])))
+ {
deleted++;
- else if (!table_being_deleted->next || table_being_deleted->table->file->has_transactions())
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER, FALSE))
+ DBUG_RETURN(1);
+ }
+ else
{
table->file->print_error(error,MYF(0));
DBUG_RETURN(1);
@@ -418,7 +588,7 @@ bool multi_delete::send_data(List<Item> &values)
error=tempfiles[secure_counter]->unique_add((char*) table->file->ref);
if (error)
{
- error=-1;
+ error= 1; // Fatal error
DBUG_RETURN(1);
}
}
@@ -432,7 +602,7 @@ void multi_delete::send_error(uint errcode,const char *err)
DBUG_ENTER("multi_delete::send_error");
/* First send error what ever it is ... */
- ::send_error(thd,errcode,err);
+ my_message(errcode, err, MYF(0));
/* If nothing deleted return */
if (!deleted)
@@ -441,22 +611,24 @@ void multi_delete::send_error(uint errcode,const char *err)
/* Something already deleted so we have to invalidate cache */
query_cache_invalidate3(thd, delete_tables, 1);
- /* Below can happen when thread is killed early ... */
- if (!table_being_deleted)
- table_being_deleted=delete_tables;
-
/*
If rows from the first table only has been deleted and it is
transactional, just do rollback.
The same if all tables are transactional, regardless of where we are.
In all other cases do attempt deletes ...
*/
- if ((table_being_deleted->table->file->has_transactions() &&
- table_being_deleted == delete_tables) || !normal_tables)
+ if ((table_being_deleted == delete_tables &&
+ table_being_deleted->table->file->has_transactions()) ||
+ !normal_tables)
ha_rollback_stmt(thd);
else if (do_delete)
{
- VOID(do_deletes(1));
+ /*
+ We have to execute the recorded do_deletes() and write info into the
+ error log
+ */
+ error= 1;
+ send_eof();
}
DBUG_VOID_RETURN;
}
@@ -469,28 +641,21 @@ void multi_delete::send_error(uint errcode,const char *err)
1 error
*/
-int multi_delete::do_deletes(bool from_send_error)
+int multi_delete::do_deletes()
{
int local_error= 0, counter= 0;
DBUG_ENTER("do_deletes");
+ DBUG_ASSERT(do_delete);
- if (from_send_error)
- {
- /* Found out table number for 'table_being_deleted*/
- for (TABLE_LIST *aux=delete_tables;
- aux != table_being_deleted;
- aux=aux->next)
- counter++;
- }
- else
- table_being_deleted = delete_tables;
-
- do_delete= 0;
+ do_delete= 0; // Mark called
if (!found)
DBUG_RETURN(0);
- for (table_being_deleted=table_being_deleted->next;
- table_being_deleted ;
- table_being_deleted=table_being_deleted->next, counter++)
+
+ table_being_deleted= (delete_while_scanning ? delete_tables->next_local :
+ delete_tables);
+
+ for (; table_being_deleted;
+ table_being_deleted= table_being_deleted->next_local, counter++)
{
TABLE *table = table_being_deleted->table;
if (tempfiles[counter]->get(table))
@@ -508,12 +673,26 @@ int multi_delete::do_deletes(bool from_send_error)
info.ignore_not_found_rows= 1;
while (!(local_error=info.read_record(&info)) && !thd->killed)
{
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+ TRG_ACTION_BEFORE, FALSE))
+ {
+ local_error= 1;
+ break;
+ }
if ((local_error=table->file->delete_row(table->record[0])))
{
table->file->print_error(local_error,MYF(0));
break;
}
deleted++;
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER, FALSE))
+ {
+ local_error= 1;
+ break;
+ }
}
end_read_record(&info);
if (thd->killed && !local_error)
@@ -537,7 +716,7 @@ bool multi_delete::send_eof()
thd->proc_info="deleting from reference tables";
/* Does deletes for the last n - 1 tables, returns 0 if ok */
- int local_error= do_deletes(0); // returns 0 if success
+ int local_error= do_deletes(); // returns 0 if success
/* reset used flags */
thd->proc_info="end";
@@ -547,7 +726,9 @@ bool multi_delete::send_eof()
ha_autocommit_...
*/
if (deleted)
+ {
query_cache_invalidate3(thd, delete_tables, 1);
+ }
/*
Write the SQL statement to the binlog if we deleted
@@ -557,30 +738,30 @@ bool multi_delete::send_eof()
Note that if we deleted nothing we don't write to the binlog (TODO:
fix this).
*/
- if (deleted && (error <= 0 || normal_tables))
+ if (deleted && ((error <= 0 && !local_error) || normal_tables))
{
- mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- if (error <= 0)
+ if (error <= 0 && !local_error)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed, FALSE);
+ transactional_tables, FALSE);
if (mysql_bin_log.write(&qinfo) && !normal_tables)
local_error=1; // Log write failed: roll back the SQL statement
}
- if (!log_delayed)
+ if (!transactional_tables)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- /* Commit or rollback the current SQL statement */
+ /* Commit or rollback the current SQL statement */
if (transactional_tables)
if (ha_autocommit_or_rollback(thd,local_error > 0))
local_error=1;
- if (local_error)
- ::send_error(thd);
- else
+ if (!local_error)
+ {
+ thd->row_count_func= deleted;
::send_ok(thd, deleted);
+ }
return 0;
}
@@ -601,74 +782,73 @@ bool multi_delete::send_eof()
- If we want to have a name lock on the table on exit without errors.
*/
-int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
+bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
{
HA_CREATE_INFO create_info;
char path[FN_REFLEN];
TABLE **table_ptr;
- int error;
+ bool error;
DBUG_ENTER("mysql_truncate");
bzero((char*) &create_info,sizeof(create_info));
/* If it is a temporary table, close and regenerate it */
if (!dont_send_ok && (table_ptr=find_temporary_table(thd,table_list->db,
- table_list->real_name)))
+ table_list->table_name)))
{
TABLE *table= *table_ptr;
table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
- db_type table_type=table->db_type;
+ db_type table_type= table->s->db_type;
if (!ha_supports_generate(table_type))
goto trunc_by_del;
- strmov(path,table->path);
+ strmov(path, table->s->path);
*table_ptr= table->next; // Unlink table from list
close_temporary(table,0);
*fn_ext(path)=0; // Remove the .frm extension
ha_create_table(path, &create_info,1);
// We don't need to call invalidate() because this table is not in cache
if ((error= (int) !(open_temporary_table(thd, path, table_list->db,
- table_list->real_name, 1))))
+ table_list->table_name, 1))))
(void) rm_temporary_table(table_type, path);
/*
If we return here we will not have logged the truncation to the bin log
and we will not send_ok() to the client.
*/
- goto end;
+ goto end;
}
(void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
- table_list->real_name,reg_ext);
+ table_list->table_name,reg_ext);
fn_format(path, path, "", "", MY_UNPACK_FILENAME);
if (!dont_send_ok)
{
db_type table_type;
- if ((table_type=get_table_type(path)) == DB_TYPE_UNKNOWN)
+ if ((table_type=get_table_type(thd, path)) == DB_TYPE_UNKNOWN)
{
- my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db,
- table_list->real_name);
- DBUG_RETURN(-1);
+ my_error(ER_NO_SUCH_TABLE, MYF(0),
+ table_list->db, table_list->table_name);
+ DBUG_RETURN(TRUE);
}
- if (!ha_supports_generate(table_type))
+ if (!ha_supports_generate(table_type) || thd->lex->sphead)
goto trunc_by_del;
if (lock_and_wait_for_table_name(thd, table_list))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
*fn_ext(path)=0; // Remove the .frm extension
- error= ha_create_table(path,&create_info,1) ? -1 : 0;
- query_cache_invalidate3(thd, table_list, 0);
+ error= ha_create_table(path,&create_info,1);
+ query_cache_invalidate3(thd, table_list, 0);
end:
if (!dont_send_ok)
{
if (!error)
{
- mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- thd->tmp_table, FALSE);
+ 0, FALSE);
mysql_bin_log.write(&qinfo);
}
send_ok(thd); // This should return record count
@@ -683,7 +863,7 @@ end:
unlock_table_name(thd, table_list);
VOID(pthread_mutex_unlock(&LOCK_open));
}
- DBUG_RETURN(error ? -1 : 0);
+ DBUG_RETURN(error);
trunc_by_del:
/* Probably InnoDB table */
@@ -691,8 +871,9 @@ end:
table_list->lock_type= TL_WRITE;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
ha_enable_transaction(thd, FALSE);
+ mysql_init_select(thd->lex);
error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
- HA_POS_ERROR, 0);
+ HA_POS_ERROR, LL(0), TRUE);
ha_enable_transaction(thd, TRUE);
thd->options= save_options;
DBUG_RETURN(error);
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index e9f9b432c21..7b9191cd841 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -24,15 +24,15 @@
#include "mysql_priv.h"
#include "sql_select.h"
-static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s,
- TABLE_LIST *t);
+
/*
- Resolve derived tables in all queries
+ call given derived table processor (preparing or filling tables)
SYNOPSIS
mysql_handle_derived()
lex LEX for this thread
+ processor procedure of derived table processing
RETURN
0 ok
@@ -41,25 +41,22 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s,
*/
int
-mysql_handle_derived(LEX *lex)
+mysql_handle_derived(LEX *lex, int (*processor)(THD*, LEX*, TABLE_LIST*))
{
+ int res= 0;
if (lex->derived_tables)
{
+ lex->thd->derived_tables_processing= TRUE;
for (SELECT_LEX *sl= lex->all_selects_list;
sl;
sl= sl->next_select_in_list())
{
for (TABLE_LIST *cursor= sl->get_table_list();
cursor;
- cursor= cursor->next)
+ cursor= cursor->next_local)
{
- int res;
- if (cursor->derived && (res=mysql_derived(lex->thd, lex,
- cursor->derived,
- cursor)))
- {
- return res;
- }
+ if ((res= (*processor)(lex->thd, lex, cursor)))
+ goto out;
}
if (lex->describe)
{
@@ -72,25 +69,23 @@ mysql_handle_derived(LEX *lex)
}
}
}
- return 0;
+out:
+ lex->thd->derived_tables_processing= FALSE;
+ return res;
}
/*
- Resolve derived tables in all queries
+ Create temporary table structure (but do not fill it)
SYNOPSIS
- mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
+ mysql_derived_prepare()
thd Thread handle
lex LEX for this thread
- unit node that contains all SELECT's for derived tables
- t TABLE_LIST for the upper SELECT
+ orig_table_list TABLE_LIST for the upper SELECT
IMPLEMENTATION
- Derived table is resolved with temporary table. It is created based on the
- queries defined. After temporary table is created, if this is not EXPLAIN,
- then the entire unit / node is deleted. unit is deleted if UNION is used
- for derived table and node is deleted is it is a simple SELECT.
+ Derived table is resolved with temporary table.
After table creation, the above TABLE_LIST is updated with a new table.
@@ -104,78 +99,169 @@ mysql_handle_derived(LEX *lex)
0 ok
1 Error
-1 Error and error message given
-*/
-
+ */
-static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
- TABLE_LIST *org_table_list)
+int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
{
- SELECT_LEX *first_select= unit->first_select();
- TABLE *table;
- int res;
- select_union *derived_result;
- bool is_union= first_select->next_select() &&
- first_select->next_select()->linkage == UNION_TYPE;
- SELECT_LEX *save_current_select= lex->current_select;
- DBUG_ENTER("mysql_derived");
-
- if (!(derived_result= new select_union(0)))
- DBUG_RETURN(1); // out of memory
-
- // st_select_lex_unit::prepare correctly work for single select
- if ((res= unit->prepare(thd, derived_result, 0, org_table_list->alias)))
- goto exit;
-
-
- derived_result->tmp_table_param.init();
- derived_result->tmp_table_param.field_count= unit->types.elements;
- /*
- Temp table is created so that it hounours if UNION without ALL is to be
- processed
-
- As 'distinct' parameter we always pass FALSE (0), because underlying
- query will control distinct condition by itself. Correct test of
- distinct underlying query will be is_union &&
- !unit->union_distinct->next_select() (i.e. it is union and last distinct
- SELECT is last SELECT of UNION).
- */
- if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
- unit->types, (ORDER*) 0,
- FALSE, 1,
- (first_select->options | thd->options |
- TMP_TABLE_ALL_COLUMNS),
- HA_POS_ERROR,
- org_table_list->alias)))
+ SELECT_LEX_UNIT *unit= orig_table_list->derived;
+ int res= 0;
+ DBUG_ENTER("mysql_derived_prepare");
+ if (unit)
{
- res= -1;
- goto exit;
+ SELECT_LEX *first_select= unit->first_select();
+ TABLE *table= 0;
+ select_union *derived_result;
+ bool is_union= first_select->next_select() &&
+ first_select->next_select()->linkage == UNION_TYPE;
+
+ /* prevent name resolving out of derived table */
+ for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
+ sl->context.outer_context= 0;
+
+ if (!(derived_result= new select_union(0)))
+ DBUG_RETURN(1); // out of memory
+
+ // st_select_lex_unit::prepare correctly work for single select
+ if ((res= unit->prepare(thd, derived_result, 0, orig_table_list->alias)))
+ goto exit;
+
+ if (check_duplicate_names(unit->types, 0))
+ {
+ res= -1;
+ goto exit;
+ }
+
+ derived_result->tmp_table_param.init();
+ derived_result->tmp_table_param.field_count= unit->types.elements;
+ /*
+ Temp table is created so that it hounours if UNION without ALL is to be
+ processed
+
+ As 'distinct' parameter we always pass FALSE (0), because underlying
+ query will control distinct condition by itself. Correct test of
+ distinct underlying query will be is_union &&
+ !unit->union_distinct->next_select() (i.e. it is union and last distinct
+ SELECT is last SELECT of UNION).
+ */
+ if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
+ unit->types, (ORDER*) 0,
+ FALSE, 1,
+ (first_select->options | thd->options |
+ TMP_TABLE_ALL_COLUMNS),
+ HA_POS_ERROR,
+ orig_table_list->alias)))
+ {
+ res= -1;
+ goto exit;
+ }
+ derived_result->set_table(table);
+
+exit:
+ /* Hide "Unknown column" or "Unknown function" error */
+ if (orig_table_list->view)
+ {
+ if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
+ thd->net.last_errno == ER_SP_DOES_NOT_EXIST)
+ {
+ thd->clear_error();
+ my_error(ER_VIEW_INVALID, MYF(0), orig_table_list->db,
+ orig_table_list->table_name);
+ }
+ }
+
+ /*
+ if it is preparation PS only or commands that need only VIEW structure
+ then we do not need real data and we can skip execution (and parameters
+ is not defined, too)
+ */
+ if (res)
+ {
+ if (table)
+ free_tmp_table(thd, table);
+ delete derived_result;
+ }
+ else
+ {
+ if (!thd->fill_derived_tables())
+ {
+ delete derived_result;
+ derived_result= NULL;
+ }
+ orig_table_list->derived_result= derived_result;
+ orig_table_list->table= table;
+ orig_table_list->table_name= (char*) table->s->table_name;
+ orig_table_list->table_name_length= strlen((char*)table->s->table_name);
+ table->derived_select_number= first_select->select_number;
+ table->s->tmp_table= TMP_TABLE;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ table->grant.privilege= SELECT_ACL;
+#endif
+ orig_table_list->db= (char *)"";
+ orig_table_list->db_length= 0;
+ // Force read of table stats in the optimizer
+ table->file->info(HA_STATUS_VARIABLE);
+ /* Add new temporary table to list of open derived tables */
+ table->next= thd->derived_tables;
+ thd->derived_tables= table;
+ }
}
- derived_result->set_table(table);
+ else if (orig_table_list->ancestor)
+ orig_table_list->set_ancestor();
+ DBUG_RETURN(res);
+}
- /*
- if it is preparation PS only then we do not need real data and we
- can skip execution (and parameters is not defined, too)
+
+/*
+ fill derived table
+
+ SYNOPSIS
+ mysql_derived_filling()
+ thd Thread handle
+ lex LEX for this thread
+ unit node that contains all SELECT's for derived tables
+ orig_table_list TABLE_LIST for the upper SELECT
+
+ IMPLEMENTATION
+ Derived table is resolved with temporary table. It is created based on the
+ queries defined. After temporary table is filled, if this is not EXPLAIN,
+ then the entire unit / node is deleted. unit is deleted if UNION is used
+ for derived table and node is deleted is it is a simple SELECT.
+ If you use this function, make sure it's not called at prepare.
+ Due to evaluation of LIMIT clause it can not be used at prepared stage.
+
+ RETURN
+ 0 ok
+ 1 Error
+ -1 Error and error message given
*/
- if (! thd->current_arena->is_stmt_prepare())
+
+int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
+{
+ TABLE *table= orig_table_list->table;
+ SELECT_LEX_UNIT *unit= orig_table_list->derived;
+ int res= 0;
+
+ /*check that table creation pass without problem and it is derived table */
+ if (table && unit)
{
+ SELECT_LEX *first_select= unit->first_select();
+ select_union *derived_result= orig_table_list->derived_result;
+ SELECT_LEX *save_current_select= lex->current_select;
+ bool is_union= first_select->next_select() &&
+ first_select->next_select()->linkage == UNION_TYPE;
if (is_union)
{
// execute union without clean up
- if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK, "")))
- res= unit->exec();
+ res= unit->exec();
}
else
{
- unit->offset_limit_cnt= first_select->offset_limit;
- unit->select_limit_cnt= first_select->select_limit+
- first_select->offset_limit;
- if (unit->select_limit_cnt < first_select->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR;
+ unit->set_limit(first_select);
if (unit->select_limit_cnt == HA_POS_ERROR)
first_select->options&= ~OPTION_FOUND_ROWS;
lex->current_select= first_select;
- res= mysql_select(thd, &first_select->ref_pointer_array,
+ res= mysql_select(thd, &first_select->ref_pointer_array,
(TABLE_LIST*) first_select->table_list.first,
first_select->with_wild,
first_select->item_list, first_select->where,
@@ -188,54 +274,22 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
SELECT_NO_UNLOCK),
derived_result, unit, first_select);
}
- }
- if (!res)
- {
- /*
- Here we entirely fix both TABLE_LIST and list of SELECT's as
- there were no derived tables
- */
- if (derived_result->flush())
- res= 1;
- else
+ if (!res)
{
- org_table_list->real_name= table->real_name;
- org_table_list->table= table;
- if (org_table_list->table_list)
- {
- org_table_list->table_list->real_name= table->real_name;
- org_table_list->table_list->table= table;
- }
- table->derived_select_number= first_select->select_number;
- table->tmp_table= TMP_TABLE;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table->grant.privilege= SELECT_ACL;
-#endif
- org_table_list->db= (char *)"";
- // Force read of table stats in the optimizer
- table->file->info(HA_STATUS_VARIABLE);
- }
+ /*
+ Here we entirely fix both TABLE_LIST and list of SELECT's as
+ there were no derived tables
+ */
+ if (derived_result->flush())
+ res= 1;
- if (!lex->describe)
- unit->cleanup();
- if (res)
- free_tmp_table(thd, table);
- else
- {
- /* Add new temporary table to list of open derived tables */
- table->next= thd->derived_tables;
- thd->derived_tables= table;
+ if (!lex->describe)
+ unit->cleanup();
}
+ else
+ unit->cleanup();
+ lex->current_select= save_current_select;
}
- else
- {
- free_tmp_table(thd, table);
- unit->cleanup();
- }
-
-exit:
- delete derived_result;
- lex->current_select= save_current_select;
- DBUG_RETURN(res);
+ return res;
}
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index af72632199f..08388dee516 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -19,17 +19,17 @@
#include "mysql_priv.h"
-int mysql_do(THD *thd, List<Item> &values)
+bool mysql_do(THD *thd, List<Item> &values)
{
List_iterator<Item> li(values);
Item *value;
DBUG_ENTER("mysql_do");
- if (setup_fields(thd, 0, 0, values, 0, 0, 0))
- DBUG_RETURN(-1);
+ if (setup_fields(thd, 0, values, 0, 0, 0))
+ DBUG_RETURN(TRUE);
while ((value = li++))
value->val_int();
free_underlaid_joins(thd, &thd->lex->select_lex);
thd->clear_error(); // DO always is OK
send_ok(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index b24d15b6e3b..2e262569386 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -43,6 +43,7 @@ This file contains the implementation of error and warnings related
***********************************************************************/
#include "mysql_priv.h"
+#include "sp_rcontext.h"
/*
Store a new message in an error object
@@ -63,6 +64,7 @@ void MYSQL_ERROR::set_msg(THD *thd, const char *msg_arg)
SYNOPSIS
mysql_reset_errors()
thd Thread handle
+ force Reset warnings even if it has been done before
IMPLEMENTATION
Don't reset warnings if this has already been called for this query.
@@ -70,14 +72,16 @@ void MYSQL_ERROR::set_msg(THD *thd, const char *msg_arg)
in which case push_warnings() has already called this function.
*/
-void mysql_reset_errors(THD *thd)
+void mysql_reset_errors(THD *thd, bool force)
{
DBUG_ENTER("mysql_reset_errors");
- if (thd->query_id != thd->warn_id)
+ if (thd->query_id != thd->warn_id || force)
{
thd->warn_id= thd->query_id;
free_root(&thd->warn_root,MYF(0));
bzero((char*) thd->warn_count, sizeof(thd->warn_count));
+ if (force)
+ thd->total_warn_count= 0;
thd->warn_list.empty();
thd->row_count= 1; // by default point to row 1
}
@@ -105,13 +109,45 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
MYSQL_ERROR *err= 0;
DBUG_ENTER("push_warning");
- if (level == MYSQL_ERROR::WARN_LEVEL_NOTE && !(thd->options & OPTION_SQL_NOTES))
- return(0);
+ if (level == MYSQL_ERROR::WARN_LEVEL_NOTE &&
+ !(thd->options & OPTION_SQL_NOTES))
+ DBUG_RETURN(0);
+ if (thd->query_id != thd->warn_id && !thd->spcont)
+ mysql_reset_errors(thd, 0);
+ thd->got_warning= 1;
+
+ /* Abort if we are using strict mode and we are not using IGNORE */
+ if ((int) level >= (int) MYSQL_ERROR::WARN_LEVEL_WARN &&
+ thd->really_abort_on_warning())
+ {
+ /* Avoid my_message() calling push_warning */
+ bool no_warnings_for_error= thd->no_warnings_for_error;
+ sp_rcontext *spcont= thd->spcont;
+
+ thd->no_warnings_for_error= 1;
+ thd->spcont= 0;
+
+ thd->killed= THD::KILL_BAD_DATA;
+ my_message(code, msg, MYF(0));
+
+ thd->spcont= spcont;
+ thd->no_warnings_for_error= no_warnings_for_error;
+ /* Store error in error list (as my_message() didn't do it) */
+ level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+ }
+
+ if (thd->spcont &&
+ thd->spcont->find_handler(code,
+ ((int) level >=
+ (int) MYSQL_ERROR::WARN_LEVEL_WARN &&
+ thd->really_abort_on_warning()) ?
+ MYSQL_ERROR::WARN_LEVEL_ERROR : level))
+ {
+ DBUG_RETURN(NULL);
+ }
query_cache_abort(&thd->net);
- if (thd->query_id != thd->warn_id)
- mysql_reset_errors(thd);
if (thd->warn_list.elements < thd->variables.max_error_count)
{
@@ -121,8 +157,7 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
*/
MEM_ROOT *old_root= thd->mem_root;
thd->mem_root= &thd->warn_root;
- err= new MYSQL_ERROR(thd, code, level, msg);
- if (err)
+ if ((err= new MYSQL_ERROR(thd, code, level, msg)))
thd->warn_list.push_back(err);
thd->mem_root= old_root;
}
@@ -170,14 +205,14 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
Takes into account the current LIMIT
RETURN VALUES
- 0 ok
- 1 Error sending data to client
+ FALSE ok
+ TRUE Error sending data to client
*/
static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
static int warning_level_length[]= { 4, 7, 5, 1 };
-my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
+bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_warnings");
@@ -186,26 +221,27 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));
- if (thd->protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
+ if (thd->protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
MYSQL_ERROR *err;
SELECT_LEX *sel= &thd->lex->select_lex;
- ha_rows offset= sel->offset_limit, limit= sel->select_limit;
+ SELECT_LEX_UNIT *unit= &thd->lex->unit;
+ ha_rows idx= 0;
Protocol *protocol=thd->protocol;
-
+
+ unit->set_limit(sel);
+
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
while ((err= it++))
{
/* Skip levels that the user is not interested in */
if (!(levels_to_show & ((ulong) 1 << err->level)))
continue;
- if (offset)
- {
- offset--;
+ if (++idx <= unit->offset_limit_cnt)
continue;
- }
- if (limit-- == 0)
+ if (idx > unit->select_limit_cnt)
break;
protocol->prepare_for_resend();
protocol->store(warning_level_names[err->level],
@@ -213,8 +249,8 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
protocol->store((uint32) err->code);
protocol->store(err->msg, strlen(err->msg), system_charset_info);
if (protocol->write())
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
- send_eof(thd);
- DBUG_RETURN(0);
+ send_eof(thd);
+ DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_error.h b/sql/sql_error.h
new file mode 100644
index 00000000000..223b50be744
--- /dev/null
+++ b/sql/sql_error.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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 */
+
+class MYSQL_ERROR: public Sql_alloc
+{
+public:
+ enum enum_warning_level
+ { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
+
+ uint code;
+ enum_warning_level level;
+ char *msg;
+
+ MYSQL_ERROR(THD *thd, uint code_arg, enum_warning_level level_arg,
+ const char *msg_arg)
+ :code(code_arg), level(level_arg)
+ {
+ if (msg_arg)
+ set_msg(thd, msg_arg);
+ }
+ void set_msg(THD *thd, const char *msg_arg);
+};
+
+MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *msg);
+void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *format, ...);
+void mysql_reset_errors(THD *thd, bool force);
+bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 491b82c1c1d..cc45a7001cd 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -64,7 +64,7 @@
#define HANDLER_TABLES_HASH_SIZE 120
static enum enum_ha_read_modes rkey_to_rnext[]=
- { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
+{ RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
#define HANDLER_TABLES_HACK(thd) { \
TABLE *tmp=thd->open_tables; \
@@ -140,19 +140,19 @@ static void mysql_ha_hash_free(TABLE_LIST *tables)
error messages.
RETURN
- 0 ok
- != 0 error
+ FALSE OK
+ TRUE Error
*/
-int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
+bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
TABLE_LIST *hash_tables;
char *db, *name, *alias;
uint dblen, namelen, aliaslen, counter;
- int err;
+ int error;
DBUG_ENTER("mysql_ha_open");
DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d",
- tables->db, tables->real_name, tables->alias,
+ tables->db, tables->table_name, tables->alias,
(int) reopen));
if (! hash_inited(&thd->handler_tables_hash))
@@ -173,8 +173,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
DBUG_PRINT("info",("duplicate '%s'", tables->alias));
if (! reopen)
- my_printf_error(ER_NONUNIQ_TABLE, ER(ER_NONUNIQ_TABLE),
- MYF(0), tables->alias);
+ my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
goto err;
}
}
@@ -185,16 +184,20 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
*/
DBUG_ASSERT(! tables->table);
HANDLER_TABLES_HACK(thd);
- err=open_tables(thd, tables, &counter);
+
+ /* for now HANDLER can be used only for real TABLES */
+ tables->required_type= FRMTYPE_TABLE;
+ error= open_tables(thd, &tables, &counter, 0);
+
HANDLER_TABLES_HACK(thd);
- if (err)
+ if (error)
goto err;
/* There can be only one table in '*tables'. */
if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
{
if (! reopen)
- my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias);
+ my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
mysql_ha_close(thd, tables);
goto err;
}
@@ -203,7 +206,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
/* copy the TABLE_LIST struct */
dblen= strlen(tables->db) + 1;
- namelen= strlen(tables->real_name) + 1;
+ namelen= strlen(tables->table_name) + 1;
aliaslen= strlen(tables->alias) + 1;
if (!(my_multi_malloc(MYF(MY_WME),
&hash_tables, sizeof(*hash_tables),
@@ -215,10 +218,10 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
/* structure copy */
*hash_tables= *tables;
hash_tables->db= db;
- hash_tables->real_name= name;
+ hash_tables->table_name= name;
hash_tables->alias= alias;
memcpy(hash_tables->db, tables->db, dblen);
- memcpy(hash_tables->real_name, tables->real_name, namelen);
+ memcpy(hash_tables->table_name, tables->table_name, namelen);
memcpy(hash_tables->alias, tables->alias, aliaslen);
/* add to hash */
@@ -232,11 +235,11 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
if (! reopen)
send_ok(thd);
DBUG_PRINT("exit",("OK"));
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
DBUG_PRINT("exit",("ERROR"));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
@@ -253,17 +256,17 @@ err:
will be closed. Broadcasts a COND_refresh condition.
RETURN
- 0 ok
- != 0 error
+ FALSE ok
+ TRUE error
*/
-int mysql_ha_close(THD *thd, TABLE_LIST *tables)
+bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
{
TABLE_LIST *hash_tables;
TABLE **table_ptr;
DBUG_ENTER("mysql_ha_close");
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
- tables->db, tables->real_name, tables->alias));
+ tables->db, tables->table_name, tables->alias));
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
(byte*) tables->alias,
@@ -277,54 +280,32 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables)
*/
for (table_ptr= &(thd->handler_tables);
*table_ptr && (*table_ptr != hash_tables->table);
- table_ptr= &(*table_ptr)->next);
+ table_ptr= &(*table_ptr)->next)
+ ;
-#if MYSQL_VERSION_ID < 40100
- if (*tables->db && strcmp(hash_tables->db, tables->db))
- {
- DBUG_PRINT("info",("wrong db"));
- hash_tables= NULL;
- }
- else
-#endif
+ if (*table_ptr)
{
- if (*table_ptr)
+ (*table_ptr)->file->ha_index_or_rnd_end();
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (close_thread_table(thd, table_ptr))
{
- (*table_ptr)->file->ha_index_or_rnd_end();
- 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));
+ /* Tell threads waiting for refresh that something has happened */
+ VOID(pthread_cond_broadcast(&COND_refresh));
}
-
- hash_delete(&thd->handler_tables_hash, (byte*) hash_tables);
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
+ hash_delete(&thd->handler_tables_hash, (byte*) hash_tables);
}
-
- if (! hash_tables)
+ else
{
-#if MYSQL_VERSION_ID < 40100
- char buff[MAX_DBKEY_LENGTH];
- if (*tables->db)
- strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS);
- else
- strncpy(buff, tables->alias, sizeof(buff));
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- buff, "HANDLER");
-#else
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- tables->alias, "HANDLER");
-#endif
+ my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
DBUG_PRINT("exit",("ERROR"));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_ok(thd);
DBUG_PRINT("exit", ("OK"));
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -340,18 +321,19 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables)
key_expr
ha_rkey_mode
cond
- select_limit
- offset_limit
+ select_limit_cnt
+ offset_limit_cnt
RETURN
- 0 ok
- != 0 error
+ FALSE ok
+ TRUE error
*/
-int mysql_ha_read(THD *thd, TABLE_LIST *tables,
- enum enum_ha_read_modes mode, char *keyname, List<Item> *key_expr,
- enum ha_rkey_function ha_rkey_mode, Item *cond,
- ha_rows select_limit,ha_rows offset_limit)
+bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
+ enum enum_ha_read_modes mode, char *keyname,
+ List<Item> *key_expr,
+ enum ha_rkey_function ha_rkey_mode, Item *cond,
+ ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
{
TABLE_LIST *hash_tables;
TABLE *table;
@@ -360,18 +342,21 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
Protocol *protocol= thd->protocol;
char buff[MAX_FIELD_WIDTH];
String buffer(buff, sizeof(buff), system_charset_info);
- int err, keyno= -1;
+ int error, keyno= -1;
uint num_rows;
byte *key;
uint key_len;
+ bool not_used;
DBUG_ENTER("mysql_ha_read");
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
- tables->db, tables->real_name, tables->alias));
+ tables->db, tables->table_name, tables->alias));
LINT_INIT(key);
LINT_INIT(key_len);
- list.push_front(new Item_field(NULL,NULL,"*"));
+ thd->lex->select_lex.context.resolve_in_table_list_only(tables);
+ list.push_front(new Item_field(&thd->lex->select_lex.context,
+ NULL, NULL, "*"));
List_iterator<Item> it(list);
it++;
@@ -381,7 +366,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
{
table= hash_tables->table;
DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p",
- hash_tables->db, hash_tables->real_name,
+ hash_tables->db, hash_tables->table_name,
hash_tables->alias, table));
if (!table)
{
@@ -396,7 +381,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
table= hash_tables->table;
DBUG_PRINT("info",("re-opened '%s'.'%s' as '%s' tab %p",
- hash_tables->db, hash_tables->real_name,
+ hash_tables->db, hash_tables->table_name,
hash_tables->alias, table));
}
@@ -416,45 +401,42 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
#if MYSQL_VERSION_ID < 40100
char buff[MAX_DBKEY_LENGTH];
if (*tables->db)
- strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS);
+ strxnmov(buff, sizeof(buff), tables->db, ".", tables->table_name, NullS);
else
strncpy(buff, tables->alias, sizeof(buff));
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- buff, "HANDLER");
+ my_error(ER_UNKNOWN_TABLE, MYF(0), buff, "HANDLER");
#else
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- tables->alias, "HANDLER");
+ my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
#endif
goto err0;
}
tables->table=table;
if (cond && ((!cond->fixed &&
- cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1)))
+ cond->fix_fields(thd, &cond)) || cond->check_cols(1)))
goto err0;
if (keyname)
{
- if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0)
+ if ((keyno=find_type(keyname, &table->s->keynames, 1+2)-1)<0)
{
- my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0),
- keyname,tables->alias);
+ my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), keyname, tables->alias);
goto err0;
}
}
- if (insert_fields(thd,tables,tables->db,tables->alias,&it))
+ if (insert_fields(thd, &thd->lex->select_lex.context,
+ tables->db, tables->alias, &it, 0))
goto err0;
- select_limit+=offset_limit;
- protocol->send_fields(&list,1);
+ protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
HANDLER_TABLES_HACK(thd);
- lock= mysql_lock_tables(thd, &tables->table, 1, 0);
+ lock= mysql_lock_tables(thd, &tables->table, 1, 0, &not_used);
HANDLER_TABLES_HACK(thd);
if (!lock)
- goto err0; // mysql_lock_tables() printed error message already
+ goto err0; // mysql_lock_tables() printed error message already
/*
In ::external_lock InnoDB resets the fields which tell it that
@@ -464,13 +446,13 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
table->file->init_table_handle_for_HANDLER();
- for (num_rows=0; num_rows < select_limit; )
+ for (num_rows=0; num_rows < select_limit_cnt; )
{
switch (mode) {
case RNEXT:
if (table->file->inited != handler::NONE)
{
- err=keyname ?
+ error=keyname ?
table->file->index_next(table->record[0]) :
table->file->rnd_next(table->record[0]);
break;
@@ -481,13 +463,13 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
{
table->file->ha_index_or_rnd_end();
table->file->ha_index_init(keyno);
- err=table->file->index_first(table->record[0]);
+ error= table->file->index_first(table->record[0]);
}
else
{
table->file->ha_index_or_rnd_end();
- if (!(err=table->file->ha_rnd_init(1)))
- err=table->file->rnd_next(table->record[0]);
+ if (!(error= table->file->ha_rnd_init(1)))
+ error= table->file->rnd_next(table->record[0]);
}
mode=RNEXT;
break;
@@ -495,7 +477,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
DBUG_ASSERT(keyname != 0);
if (table->file->inited != handler::NONE)
{
- err=table->file->index_prev(table->record[0]);
+ error=table->file->index_prev(table->record[0]);
break;
}
/* else fall through */
@@ -503,13 +485,13 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
DBUG_ASSERT(keyname != 0);
table->file->ha_index_or_rnd_end();
table->file->ha_index_init(keyno);
- err=table->file->index_last(table->record[0]);
+ error= table->file->index_last(table->record[0]);
mode=RPREV;
break;
case RNEXT_SAME:
/* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */
DBUG_ASSERT(keyname != 0);
- err= table->file->index_next_same(table->record[0], key, key_len);
+ error= table->file->index_next_same(table->record[0], key, key_len);
break;
case RKEY:
{
@@ -518,8 +500,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
KEY_PART_INFO *key_part=keyinfo->key_part;
if (key_expr->elements > keyinfo->key_parts)
{
- my_printf_error(ER_TOO_MANY_KEY_PARTS,ER(ER_TOO_MANY_KEY_PARTS),
- MYF(0),keyinfo->key_parts);
+ my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), keyinfo->key_parts);
goto err;
}
List_iterator<Item> it_ke(*key_expr);
@@ -527,8 +508,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
for (key_len=0 ; (item=it_ke++) ; key_part++)
{
// 'item' can be changed by fix_fields() call
- if ((!item->fixed &&
- item->fix_fields(thd, tables, it_ke.ref())) ||
+ if ((!item->fixed &&
+ item->fix_fields(thd, it_ke.ref())) ||
(item= *it_ke.ref())->check_cols(1))
goto err;
if (item->used_tables() & ~RAND_TABLE_BIT)
@@ -540,39 +521,36 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
key_len+=key_part->store_length;
}
if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
- {
- send_error(thd,ER_OUTOFMEMORY);
goto err;
- }
- key_copy(key, table, keyno, key_len);
table->file->ha_index_or_rnd_end();
table->file->ha_index_init(keyno);
- err=table->file->index_read(table->record[0],
+ key_copy(key, table->record[0], table->key_info + keyno, key_len);
+ error= table->file->index_read(table->record[0],
key,key_len,ha_rkey_mode);
mode=rkey_to_rnext[(int)ha_rkey_mode];
break;
}
default:
- send_error(thd,ER_ILLEGAL_HA);
+ my_message(ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), MYF(0));
goto err;
}
- if (err == HA_ERR_RECORD_DELETED)
- continue;
- if (err)
+ if (error)
{
- if (err != HA_ERR_KEY_NOT_FOUND && err != HA_ERR_END_OF_FILE)
+ if (error == HA_ERR_RECORD_DELETED)
+ continue;
+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
sql_print_error("mysql_ha_read: Got error %d when reading table '%s'",
- err, tables->real_name);
- table->file->print_error(err,MYF(0));
+ error, tables->table_name);
+ table->file->print_error(error,MYF(0));
goto err;
}
goto ok;
}
if (cond && !cond->val_int())
continue;
- if (num_rows >= offset_limit)
+ if (num_rows >= offset_limit_cnt)
{
Item *item;
protocol->prepare_for_resend();
@@ -582,7 +560,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (item->send(thd->protocol, &buffer))
{
protocol->free(); // Free used
- my_error(ER_OUT_OF_RESOURCES,MYF(0));
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
goto err;
}
}
@@ -594,13 +572,13 @@ ok:
mysql_unlock_tables(thd,lock);
send_eof(thd);
DBUG_PRINT("exit",("OK"));
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
mysql_unlock_tables(thd,lock);
err0:
DBUG_PRINT("exit",("ERROR"));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
@@ -643,25 +621,25 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
if (tables)
{
/* Close all tables in the list. */
- for (tmp_tables= tables ; tmp_tables; tmp_tables= tmp_tables->next)
+ for (tmp_tables= tables ; tmp_tables; tmp_tables= tmp_tables->next_local)
{
DBUG_PRINT("info-in-tables-list",("'%s'.'%s' as '%s'",
- tmp_tables->db, tmp_tables->real_name,
+ tmp_tables->db, tmp_tables->table_name,
tmp_tables->alias));
/* Close all currently open handler tables with the same base table. */
table_ptr= &(thd->handler_tables);
while (*table_ptr)
{
- if ((! *tmp_tables->db ||
- ! my_strcasecmp(&my_charset_latin1, (*table_ptr)->table_cache_key,
+ if ((!*tmp_tables->db ||
+ !my_strcasecmp(&my_charset_latin1, (*table_ptr)->s->db,
tmp_tables->db)) &&
- ! my_strcasecmp(&my_charset_latin1, (*table_ptr)->real_name,
- tmp_tables->real_name))
+ ! my_strcasecmp(&my_charset_latin1, (*table_ptr)->s->table_name,
+ tmp_tables->table_name))
{
DBUG_PRINT("info",("*table_ptr '%s'.'%s' as '%s'",
- (*table_ptr)->table_cache_key,
- (*table_ptr)->real_name,
- (*table_ptr)->table_name));
+ (*table_ptr)->s->db,
+ (*table_ptr)->s->table_name,
+ (*table_ptr)->alias));
mysql_ha_flush_table(thd, table_ptr, mode_flags);
continue;
}
@@ -678,7 +656,7 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
while (*table_ptr)
{
if ((mode_flags & MYSQL_HA_FLUSH_ALL) ||
- ((*table_ptr)->version != refresh_version))
+ ((*table_ptr)->s->version != refresh_version))
{
mysql_ha_flush_table(thd, table_ptr, mode_flags);
continue;
@@ -714,12 +692,12 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
TABLE *table= *table_ptr;
DBUG_ENTER("mysql_ha_flush_table");
DBUG_PRINT("enter",("'%s'.'%s' as '%s' flags: 0x%02x",
- table->table_cache_key, table->real_name,
- table->table_name, mode_flags));
+ table->s->db, table->s->table_name,
+ table->alias, mode_flags));
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
- (byte*) (*table_ptr)->table_name,
- strlen((*table_ptr)->table_name) + 1)))
+ (byte*) (*table_ptr)->alias,
+ strlen((*table_ptr)->alias) + 1)))
{
if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE))
{
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 0e0d32a922d..f4d835541cf 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -75,21 +75,24 @@ enum enum_used_fields
RETURN VALUES
0 all ok
- 1 one of the fileds didn't finded
+ 1 one of the fileds was not found
*/
static bool init_fields(THD *thd, TABLE_LIST *tables,
struct st_find_field *find_fields, uint count)
{
+ Name_resolution_context *context= &thd->lex->select_lex.context;
DBUG_ENTER("init_fields");
+ context->resolve_in_table_list_only(tables);
for (; count-- ; find_fields++)
{
- TABLE_LIST *not_used;
/* 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,
+ Item_field *field= new Item_field(context,
+ "mysql", find_fields->table_name,
find_fields->field_name);
- if (!(find_fields->field= find_field_in_tables(thd, field, tables,
- &not_used, TRUE)))
+ if (!(find_fields->field= find_field_in_tables(thd, field, tables, NULL,
+ 0, REPORT_ALL_ERRORS, 1,
+ TRUE)))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -273,11 +276,11 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
DBUG_ENTER("get_topics_for_keyword");
if ((iindex_topic= find_type((char*) primary_key_name,
- &topics->keynames, 1+2)-1)<0 ||
+ &topics->s->keynames, 1+2)-1)<0 ||
(iindex_relations= find_type((char*) primary_key_name,
- &relations->keynames, 1+2)-1)<0)
+ &relations->s->keynames, 1+2)-1)<0)
{
- send_error(thd,ER_CORRUPT_HELP_DB);
+ my_message(ER_CORRUPT_HELP_DB, ER(ER_CORRUPT_HELP_DB), MYF(0));
DBUG_RETURN(-1);
}
rtopic_id= find_fields[help_relation_help_topic_id].field;
@@ -286,9 +289,8 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *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);
+ rkey_id->store((longlong) key_id, TRUE);
+ rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW);
int key_res= relations->file->index_read(relations->record[0],
(byte *)buff, rkey_id->pack_length(),
HA_READ_KEY_EXACT);
@@ -300,9 +302,8 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
char topic_id_buff[8];
longlong topic_id= rtopic_id->val_int();
Field *field= find_fields[help_topic_help_topic_id].field;
- field->store((longlong) topic_id);
- field->get_key_image(topic_id_buff, field->pack_length(), field->charset(),
- Field::itRAW);
+ field->store((longlong) topic_id, TRUE);
+ field->get_key_image(topic_id_buff, field->pack_length(), Field::itRAW);
if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff,
field->pack_length(), HA_READ_KEY_EXACT))
@@ -427,7 +428,8 @@ int send_answer_1(Protocol *protocol, String *s1, String *s2, String *s3)
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))
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(1);
protocol->prepare_for_resend();
@@ -469,7 +471,8 @@ int send_header_2(Protocol *protocol, bool for_category)
field_list.push_back(new Item_empty_string("source_category_name",64));
field_list.push_back(new Item_empty_string("name",64));
field_list.push_back(new Item_empty_string("is_it_category",1));
- DBUG_RETURN(protocol->send_fields(&field_list,1));
+ DBUG_RETURN(protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF));
}
/*
@@ -545,7 +548,6 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
prepare_simple_select()
thd Thread handler
cond WHERE part of select
- tables list of tables, used in WHERE
table goal table
error code of error (out)
@@ -554,13 +556,18 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
# 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 *table, int *error)
{
if (!cond->fixed)
- cond->fix_fields(thd, tables, &cond); // can never fail
- SQL_SELECT *res= make_select(table,0,0,cond,error);
- if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)))
+ cond->fix_fields(thd, &cond); // can never fail
+
+ /* Assume that no indexes cover all required fields */
+ table->used_keys.clear_all();
+
+ SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error);
+ if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) ||
+ (res->quick && res->quick->reset()))
{
delete res;
res=0;
@@ -595,7 +602,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
new Item_string("\\",1,&my_charset_latin1));
if (thd->is_fatal_error)
return 0; // OOM
- return prepare_simple_select(thd,cond,tables,table,error);
+ return prepare_simple_select(thd, cond, table, error);
}
@@ -607,66 +614,62 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
thd Thread handler
RETURN VALUES
- 0 Success
- 1 Error and send_error already commited
- -1 error && send_error should be issued (normal case)
+ FALSE Success
+ TRUE Error and send_error already commited
*/
-int mysqld_help(THD *thd, const char *mask)
+bool mysqld_help(THD *thd, const char *mask)
{
Protocol *protocol= thd->protocol;
SQL_SELECT *select;
st_find_field used_fields[array_elements(init_used_fields)];
+ TABLE_LIST *leaves= 0;
+ TABLE_LIST tables[4];
+ List<String> topics_list, categories_list, subcategories_list;
+ String name, description, example;
+ int count_topics, count_categories, error;
+ uint mlen= strlen(mask);
+ size_t i;
+ MEM_ROOT *mem_root= thd->mem_root;
DBUG_ENTER("mysqld_help");
- TABLE_LIST tables[4];
bzero((gptr)tables,sizeof(tables));
- tables[0].alias= tables[0].real_name= (char*) "help_topic";
+ tables[0].alias= tables[0].table_name= (char*) "help_topic";
tables[0].lock_type= TL_READ;
- tables[0].next= &tables[1];
- tables[1].alias= tables[1].real_name= (char*) "help_category";
+ tables[0].next_global= tables[0].next_local=
+ tables[0].next_name_resolution_table= &tables[1];
+ tables[1].alias= tables[1].table_name= (char*) "help_category";
tables[1].lock_type= TL_READ;
- tables[1].next= &tables[2];
- tables[2].alias= tables[2].real_name= (char*) "help_relation";
+ tables[1].next_global= tables[1].next_local=
+ tables[1].next_name_resolution_table= &tables[2];
+ tables[2].alias= tables[2].table_name= (char*) "help_relation";
tables[2].lock_type= TL_READ;
- tables[2].next= &tables[3];
- tables[3].alias= tables[3].real_name= (char*) "help_keyword";
+ tables[2].next_global= tables[2].next_local=
+ tables[2].next_name_resolution_table= &tables[3];
+ tables[3].alias= tables[3].table_name= (char*) "help_keyword";
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;
- goto end;
- }
- /* Init tables and fields to be usable from items */
- setup_tables(tables);
+ goto error;
+ /*
+ Init tables and fields to be usable from items
+ tables do not contain VIEWs => we can pass 0 as conds
+ */
+ setup_tables(thd, &thd->lex->select_lex.context,
+ &thd->lex->select_lex.top_join_list,
+ tables, 0, &leaves, FALSE);
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
- {
- res= -1;
- goto end;
- }
- size_t i;
+ goto error;
for (i=0; i<sizeof(tables)/sizeof(TABLE_LIST); i++)
tables[i].table->file->init_table_handle_for_HANDLER();
if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[0].table,
used_fields[help_topic_name].field,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
- res= 1;
count_topics= search_topics(thd,tables[0].table,used_fields,
select,&topics_list,
&name, &description, &example);
@@ -678,10 +681,8 @@ int mysqld_help(THD *thd, const char *mask)
if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[3].table,
used_fields[help_keyword_name].field,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
+
count_topics=search_keyword(thd,tables[3].table,used_fields,select,&key_id);
delete select;
count_topics= (count_topics != 1) ? 0 :
@@ -697,10 +698,7 @@ int mysqld_help(THD *thd, const char *mask)
if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
used_fields[help_category_name].field,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
count_categories= search_categories(thd, tables[1].table, used_fields,
select,
@@ -709,13 +707,13 @@ int mysqld_help(THD *thd, const char *mask)
if (!count_categories)
{
if (send_header_2(protocol,FALSE))
- goto end;
+ goto error;
}
else if (count_categories > 1)
{
if (send_header_2(protocol,FALSE) ||
send_variant_2_list(mem_root,protocol,&categories_list,"Y",0))
- goto end;
+ goto error;
}
else
{
@@ -726,22 +724,16 @@ 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= prepare_simple_select(thd,cond_topic_by_cat,
- tables,tables[0].table,&error)))
- {
- res= -1;
- goto end;
- }
+ if (!(select= prepare_simple_select(thd, cond_topic_by_cat,
+ tables[0].table, &error)))
+ goto error;
get_all_items_for_category(thd,tables[0].table,
used_fields[help_topic_name].field,
select,&topics_list);
delete select;
- if (!(select= prepare_simple_select(thd,cond_cat_by_cat,tables,
- tables[1].table,&error)))
- {
- res= -1;
- goto end;
- }
+ if (!(select= prepare_simple_select(thd, cond_cat_by_cat,
+ tables[1].table, &error)))
+ goto error;
get_all_items_for_category(thd,tables[1].table,
used_fields[help_category_name].field,
select,&subcategories_list);
@@ -750,39 +742,35 @@ int mysqld_help(THD *thd, const char *mask)
if (send_header_2(protocol, TRUE) ||
send_variant_2_list(mem_root,protocol,&topics_list, "N",cat) ||
send_variant_2_list(mem_root,protocol,&subcategories_list,"Y",cat))
- goto end;
+ goto error;
}
}
else if (count_topics == 1)
{
if (send_answer_1(protocol,&name,&description,&example))
- goto end;
+ goto error;
}
else
{
/* First send header and functions */
if (send_header_2(protocol, FALSE) ||
send_variant_2_list(mem_root,protocol, &topics_list, "N", 0))
- goto end;
+ goto error;
if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
used_fields[help_category_name].field,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
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;
+ goto error;
}
- res= 0;
-
send_eof(thd);
-end:
- DBUG_RETURN(res);
+ DBUG_RETURN(FALSE);
+error:
+ DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 8c6fed26f8e..f548a917bf8 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -18,16 +18,20 @@
/* Insert of records */
#include "mysql_priv.h"
+#include "sp_head.h"
+#include "sql_trigger.h"
+#include "sql_select.h"
static int check_null_fields(THD *thd,TABLE *entry);
#ifndef EMBEDDED_LIBRARY
static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup, bool ignore,
- char *query, uint query_length, int log_on);
+ char *query, uint query_length, bool log_on);
static void end_delayed_insert(THD *thd);
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
static void unlink_blobs(register TABLE *table);
#endif
+static bool check_view_insertability(THD *thd, TABLE_LIST *view);
/* Define to force use of my_malloc() if the allocated memory block is big */
@@ -39,9 +43,6 @@ static void unlink_blobs(register TABLE *table);
#define my_safe_afree(ptr, size, min_length) if (size > min_length) my_free(ptr,MYF(0))
#endif
-#define DELAYED_LOG_UPDATE 1
-#define DELAYED_LOG_BIN 2
-
/*
Check if insert fields are correct.
@@ -52,6 +53,7 @@ static void unlink_blobs(register TABLE *table);
table The table for insert.
fields The insert fields.
values The insert values.
+ check_unique If duplicate values should be rejected.
NOTE
Clears TIMESTAMP_AUTO_SET_ON_INSERT from table->timestamp_field_type
@@ -63,50 +65,118 @@ static void unlink_blobs(register TABLE *table);
-1 Error
*/
-static int check_insert_fields(THD *thd, TABLE *table, List<Item> &fields,
- List<Item> &values)
+static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
+ List<Item> &fields, List<Item> &values,
+ bool check_unique)
{
+ TABLE *table= table_list->table;
+
+ if (!table_list->updatable)
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
+ return -1;
+ }
+
if (fields.elements == 0 && values.elements != 0)
{
- if (values.elements != table->fields)
+ if (!table)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0), 1L);
+ my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
return -1;
}
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (grant_option &&
- check_grant_all_columns(thd,INSERT_ACL,table))
+ if (values.elements != table->s->fields)
+ {
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
return -1;
+ }
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (grant_option)
+ {
+ Field_iterator_table fields;
+ fields.set_table(table);
+ if (check_grant_all_columns(thd, INSERT_ACL, &table->grant,
+ table->s->db, table->s->table_name,
+ &fields))
+ return -1;
+ }
#endif
clear_timestamp_auto_bits(table->timestamp_field_type,
TIMESTAMP_AUTO_SET_ON_INSERT);
}
else
{ // Part field list
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
+ Name_resolution_context *context= &select_lex->context;
+ TABLE_LIST *save_next_local;
+ TABLE_LIST *save_table_list;
+ TABLE_LIST *save_first_name_resolution_table;
+ TABLE_LIST *save_next_name_resolution_table;
+ bool save_resolve_in_select_list;
+ int res;
+
if (fields.elements != values.elements)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0), 1L);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
return -1;
}
- TABLE_LIST table_list;
- bzero((char*) &table_list,sizeof(table_list));
- table_list.db= table->table_cache_key;
- table_list.real_name= table_list.alias= table->table_name;
- table_list.table=table;
- table_list.grant=table->grant;
thd->dupp_field=0;
- if (setup_tables(&table_list) ||
- setup_fields(thd, 0, &table_list,fields,1,0,0))
+ select_lex->no_wrap_view_item= TRUE;
+
+ /* Save the state of the current name resolution context. */
+ save_table_list= context->table_list;
+ save_first_name_resolution_table= context->first_name_resolution_table;
+ save_next_name_resolution_table= (context->first_name_resolution_table) ?
+ context->first_name_resolution_table->
+ next_name_resolution_table :
+ NULL;
+ save_resolve_in_select_list= context->resolve_in_select_list;
+ save_next_local= table_list->next_local;
+
+ /*
+ Perform name resolution only in the first table - 'table_list',
+ which is the table that is inserted into.
+ */
+ table_list->next_local= 0;
+ context->resolve_in_table_list_only(table_list);
+ res= setup_fields(thd, 0, fields, 1, 0, 0);
+
+ /* Restore the current context. */
+ table_list->next_local= save_next_local;
+ context->table_list= save_table_list;
+ context->first_name_resolution_table= save_first_name_resolution_table;
+ if (context->first_name_resolution_table)
+ context->first_name_resolution_table->
+ next_name_resolution_table= save_next_name_resolution_table;
+ context->resolve_in_select_list= save_resolve_in_select_list;
+ thd->lex->select_lex.no_wrap_view_item= FALSE;
+
+ if (res)
return -1;
- if (thd->dupp_field)
+ if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
- my_error(ER_FIELD_SPECIFIED_TWICE,MYF(0), thd->dupp_field->field_name);
+ /* it is join view => we need to find table for update */
+ List_iterator_fast<Item> it(fields);
+ Item *item;
+ TABLE_LIST *tbl= 0; // reset for call to check_single_table()
+ table_map map= 0;
+
+ while ((item= it++))
+ map|= item->used_tables();
+ if (table_list->check_single_table(&tbl, map, table_list) || tbl == 0)
+ {
+ my_error(ER_VIEW_MULTIUPDATE, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ return -1;
+ }
+ table_list->table= table= tbl->table;
+ }
+
+ if (check_unique && thd->dupp_field)
+ {
+ my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dupp_field->field_name);
return -1;
}
if (table->timestamp_field && // Don't set timestamp if used
@@ -116,8 +186,17 @@ static int check_insert_fields(THD *thd, TABLE *table, List<Item> &fields,
}
// For the values we need select_priv
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
+ table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
#endif
+
+ if (check_key_in_view(thd, table_list) ||
+ (table_list->view &&
+ check_view_insertability(thd, table_list)))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
+ return -1;
+ }
+
return 0;
}
@@ -141,11 +220,11 @@ static int check_insert_fields(THD *thd, TABLE *table, List<Item> &fields,
-1 Error
*/
-static int check_update_fields(THD *thd, TABLE *table,
- TABLE_LIST *insert_table_list,
+static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
List<Item> &update_fields)
{
- ulong timestamp_query_id;
+ TABLE *table= insert_table_list->table;
+ query_id_t timestamp_query_id;
LINT_INIT(timestamp_query_id);
/*
@@ -155,14 +234,14 @@ static int check_update_fields(THD *thd, TABLE *table,
if (table->timestamp_field)
{
timestamp_query_id= table->timestamp_field->query_id;
- table->timestamp_field->query_id= thd->query_id-1;
+ table->timestamp_field->query_id= thd->query_id - 1;
}
/*
Check the fields we are going to modify. This will set the query_id
of all used fields to the threads query_id.
*/
- if (setup_fields(thd, 0, insert_table_list, update_fields, 1, 0, 0))
+ if (setup_fields(thd, 0, update_fields, 1, 0, 0))
return -1;
if (table->timestamp_field)
@@ -179,13 +258,13 @@ static int check_update_fields(THD *thd, TABLE *table,
}
-int mysql_insert(THD *thd,TABLE_LIST *table_list,
- List<Item> &fields,
- List<List_item> &values_list,
- List<Item> &update_fields,
- List<Item> &update_values,
- enum_duplicates duplic,
- bool ignore)
+bool mysql_insert(THD *thd,TABLE_LIST *table_list,
+ List<Item> &fields,
+ List<List_item> &values_list,
+ List<Item> &update_fields,
+ List<Item> &update_values,
+ enum_duplicates duplic,
+ bool ignore)
{
int error, res;
/*
@@ -193,27 +272,27 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
By default, both logs are enabled (this won't cause problems if the server
runs without --log-update or --log-bin).
*/
- int log_on= DELAYED_LOG_UPDATE | DELAYED_LOG_BIN ;
- bool transactional_table, log_delayed;
+ bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->master_access & SUPER_ACL));
+ bool transactional_table;
uint value_count;
ulong counter = 1;
ulonglong id;
COPY_INFO info;
- TABLE *table;
+ TABLE *table= 0;
+ TABLE_LIST *save_table_list;
+ TABLE_LIST *save_next_local;
+ TABLE_LIST *save_first_name_resolution_table;
+ TABLE_LIST *save_next_name_resolution_table;
List_iterator_fast<List_item> its(values_list);
List_item *values;
+ Name_resolution_context *context;
#ifndef EMBEDDED_LIBRARY
char *query= thd->query;
#endif
thr_lock_type lock_type = table_list->lock_type;
- TABLE_LIST *insert_table_list= (TABLE_LIST*)
- thd->lex->select_lex.table_list.first;
+ Item *unused_conds= 0;
DBUG_ENTER("mysql_insert");
- if (!(thd->options & OPTION_UPDATE_LOG))
- log_on&= ~(int) DELAYED_LOG_UPDATE;
- if (!(thd->options & OPTION_BIN_LOG))
- log_on&= ~(int) DELAYED_LOG_BIN;
/*
in safe mode or with skip-new change delayed insert to be regular
if we are told to replace duplicates, the insert cannot be concurrent
@@ -239,19 +318,26 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
{
if (find_locked_table(thd,
table_list->db ? table_list->db : thd->db,
- table_list->real_name))
+ table_list->table_name))
{
- my_printf_error(ER_DELAYED_INSERT_TABLE_LOCKED,
- ER(ER_DELAYED_INSERT_TABLE_LOCKED),
- MYF(0), table_list->real_name);
- DBUG_RETURN(-1);
+ my_error(ER_DELAYED_INSERT_TABLE_LOCKED, MYF(0),
+ table_list->table_name);
+ DBUG_RETURN(TRUE);
}
}
if ((table= delayed_get_table(thd,table_list)) && !thd->is_fatal_error)
{
- res= 0;
- if (table_list->next) /* if sub select */
- res= open_and_lock_tables(thd, table_list->next);
+ /*
+ Open tables used for sub-selects or in stored functions, will also
+ cache these functions.
+ */
+ res= open_and_lock_tables(thd, table_list->next_global);
+ /*
+ First is not processed by open_and_lock_tables() => we need set
+ updateability flags "by hands".
+ */
+ if (!table_list->derived && !table_list->view)
+ table_list->updatable= 1; // usual table
}
else
{
@@ -264,34 +350,58 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
#endif /* EMBEDDED_LIBRARY */
res= open_and_lock_tables(thd, table_list);
if (res || thd->is_fatal_error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
- table= table_list->table;
thd->proc_info="init";
thd->used_tables=0;
values= its++;
- if (mysql_prepare_insert(thd, table_list, insert_table_list,
- insert_table_list, table,
- fields, values, update_fields,
- update_values, duplic))
+ if (mysql_prepare_insert(thd, table_list, table, fields, values,
+ update_fields, update_values, duplic, &unused_conds,
+ FALSE))
goto abort;
+ /* mysql_prepare_insert set table_list->table if it was not set */
+ table= table_list->table;
+
+ context= &thd->lex->select_lex.context;
+ /* Save the state of the current name resolution context. */
+ save_table_list= context->table_list;
+ save_first_name_resolution_table= context->first_name_resolution_table;
+ save_next_name_resolution_table= (context->first_name_resolution_table) ?
+ context->first_name_resolution_table->
+ next_name_resolution_table :
+ NULL;
+ save_next_local= table_list->next_local;
+
+ /*
+ Perform name resolution only in the first table - 'table_list',
+ which is the table that is inserted into.
+ */
+ table_list->next_local= 0;
+ context->resolve_in_table_list_only(table_list);
+
value_count= values->elements;
while ((values= its++))
{
counter++;
if (values->elements != value_count)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0),counter);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto abort;
}
- if (setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0))
+ if (setup_fields(thd, 0, *values, 0, 0, 0))
goto abort;
}
its.rewind ();
+
+ /* Restore the current context. */
+ table_list->next_local= save_next_local;
+ context->first_name_resolution_table= save_first_name_resolution_table;
+ if (context->first_name_resolution_table)
+ context->first_name_resolution_table->
+ next_name_resolution_table= save_next_name_resolution_table;
+
/*
Fill in the given fields and dump it to the table file
*/
@@ -301,12 +411,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
info.handle_duplicates=duplic;
info.update_fields= &update_fields;
info.update_values= &update_values;
+ info.view= (table_list->view ? table_list : 0);
+
/*
Count warnings for all inserts.
For single line insert, generate an error if try to set a NOT NULL field
- to NULL
+ to NULL.
*/
- thd->count_cuted_fields= ((values_list.elements == 1) ?
+ thd->count_cuted_fields= ((values_list.elements == 1 &&
+ !ignore) ?
CHECK_FIELD_ERROR_FOR_NULL :
CHECK_FIELD_WARN);
thd->cuted_fields = 0L;
@@ -328,19 +441,42 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
if (lock_type != TL_WRITE_DELAYED)
table->file->start_bulk_insert(values_list.elements);
+ thd->no_trans_update= 0;
+ thd->abort_on_warning= (!ignore &&
+ (thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES)));
+
+ if ((fields.elements || !value_count) &&
+ check_that_all_fields_are_given_values(thd, table, table_list))
+ {
+ /* thd->net.report_error is now set, which will abort the next loop */
+ error= 1;
+ }
+
+ if (table_list->prepare_where(thd, 0, TRUE) ||
+ table_list->prepare_check_option(thd))
+ error= 1;
+
while ((values= its++))
{
if (fields.elements || !value_count)
{
- restore_record(table,default_values); // Get empty record
- if (fill_record(fields, *values, 0)|| thd->net.report_error ||
- check_null_fields(thd,table))
+ restore_record(table,s->default_values); // Get empty record
+ if (fill_record_n_invoke_before_triggers(thd, fields, *values, 0,
+ table->triggers,
+ TRG_EVENT_INSERT))
{
if (values_list.elements != 1 && !thd->net.report_error)
{
info.records++;
continue;
}
+ /*
+ TODO: set thd->abort_on_warning if values_list.elements == 1
+ and check that all items return warning in case of problem with
+ storing field.
+ */
error=1;
break;
}
@@ -348,10 +484,19 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
else
{
if (thd->used_tables) // Column used in values()
- restore_record(table,default_values); // Get empty record
+ restore_record(table,s->default_values); // Get empty record
else
- table->record[0][0]=table->default_values[0]; // Fix delete marker
- if (fill_record(table->field,*values, 0) || thd->net.report_error)
+ {
+ /*
+ Fix delete marker. No need to restore rest of record since it will
+ be overwritten by fill_record() anyway (and fill_record() does not
+ use default values in this case).
+ */
+ table->record[0][0]= table->s->default_values[0];
+ }
+ if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0,
+ table->triggers,
+ TRG_EVENT_INSERT))
{
if (values_list.elements != 1 && ! thd->net.report_error)
{
@@ -362,6 +507,18 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
break;
}
}
+
+ if ((res= table_list->view_check_option(thd,
+ (values_list.elements == 1 ?
+ 0 :
+ ignore))) ==
+ VIEW_CHECK_SKIP)
+ continue;
+ else if (res == VIEW_CHECK_ERROR)
+ {
+ error= 1;
+ break;
+ }
#ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED)
{
@@ -370,9 +527,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
}
else
#endif
- error=write_record(table,&info);
- if (error)
- break;
+ error=write_record(thd, table ,&info);
/*
If auto_increment values are used, save the first one
for LAST_INSERT_ID() and for the update log.
@@ -383,6 +538,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
{ // Get auto increment value
id= thd->last_insert_id;
}
+ if (error)
+ break;
thd->row_count++;
}
@@ -417,28 +574,28 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
/*
Invalidate the table in the query cache if something changed.
For the transactional algorithm to work the invalidation must be
- before binlog writing and ha_autocommit_...
+ before binlog writing and ha_autocommit_or_rollback
*/
if (info.copied || info.deleted || info.updated)
+ {
query_cache_invalidate3(thd, table_list, 1);
+ }
transactional_table= table->file->has_transactions();
- log_delayed= (transactional_table || table->tmp_table);
if ((info.copied || info.deleted || info.updated) &&
(error <= 0 || !transactional_table))
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
if (error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed, FALSE);
+ transactional_table, FALSE);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!log_delayed)
+ if (!transactional_table)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (transactional_table)
@@ -467,7 +624,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
goto abort;
if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) ||
!thd->cuted_fields))
- send_ok(thd,info.copied+info.deleted+info.updated,id);
+ {
+ thd->row_count_func= info.copied+info.deleted+info.updated;
+ send_ok(thd, (ulong) thd->row_count_func, id);
+ }
else
{
char buff[160];
@@ -478,11 +638,12 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields);
- ::send_ok(thd,info.copied+info.deleted+info.updated,(ulonglong)id,buff);
+ thd->row_count_func= info.copied+info.deleted+info.updated;
+ ::send_ok(thd, (ulong) thd->row_count_func, id, buff);
}
free_underlaid_joins(thd, &thd->lex->select_lex);
- table->insert_values=0;
- DBUG_RETURN(0);
+ thd->abort_on_warning= 0;
+ DBUG_RETURN(FALSE);
abort:
#ifndef EMBEDDED_LIBRARY
@@ -490,8 +651,130 @@ abort:
end_delayed_insert(thd);
#endif
free_underlaid_joins(thd, &thd->lex->select_lex);
- table->insert_values=0;
- DBUG_RETURN(-1);
+ thd->abort_on_warning= 0;
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Additional check for insertability for VIEW
+
+ SYNOPSIS
+ check_view_insertability()
+ thd - thread handler
+ view - reference on VIEW
+
+ IMPLEMENTATION
+ A view is insertable if the folloings are true:
+ - All columns in the view are columns from a table
+ - All not used columns in table have a default values
+ - All field in view are unique (not referring to the same column)
+
+ RETURN
+ FALSE - OK
+ view->contain_auto_increment is 1 if and only if the view contains an
+ auto_increment field
+
+ TRUE - can't be used for insert
+*/
+
+static bool check_view_insertability(THD * thd, TABLE_LIST *view)
+{
+ uint num= view->view->select_lex.item_list.elements;
+ TABLE *table= view->table;
+ Field_translator *trans_start= view->field_translation,
+ *trans_end= trans_start + num;
+ Field_translator *trans;
+ Field **field_ptr= table->field;
+ uint used_fields_buff_size= (table->s->fields + 7) / 8;
+ uchar *used_fields_buff= (uchar*)thd->alloc(used_fields_buff_size);
+ MY_BITMAP used_fields;
+ DBUG_ENTER("check_key_in_view");
+
+ if (!used_fields_buff)
+ DBUG_RETURN(TRUE); // EOM
+
+ DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
+
+ bitmap_init(&used_fields, used_fields_buff, used_fields_buff_size * 8, 0);
+ bitmap_clear_all(&used_fields);
+
+ view->contain_auto_increment= 0;
+ /* check simplicity and prepare unique test of view */
+ for (trans= trans_start; trans != trans_end; trans++)
+ {
+ if (!trans->item->fixed && trans->item->fix_fields(thd, &trans->item))
+ return TRUE;
+ Item_field *field;
+ /* simple SELECT list entry (field without expression) */
+ if (!(field= trans->item->filed_for_view_update()))
+ DBUG_RETURN(TRUE);
+ if (field->field->unireg_check == Field::NEXT_NUMBER)
+ view->contain_auto_increment= 1;
+ /* prepare unique test */
+ /*
+ remove collation (or other transparent for update function) if we have
+ it
+ */
+ trans->item= field;
+ }
+ /* unique test */
+ for (trans= trans_start; trans != trans_end; trans++)
+ {
+ /* Thanks to test above, we know that all columns are of type Item_field */
+ Item_field *field= (Item_field *)trans->item;
+ /* check fields belong to table in which we are inserting */
+ if (field->field->table == table &&
+ bitmap_fast_test_and_set(&used_fields, field->field->field_index))
+ DBUG_RETURN(TRUE);
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Check if table can be updated
+
+ SYNOPSIS
+ mysql_prepare_insert_check_table()
+ thd Thread handle
+ table_list Table list
+ fields List of fields to be updated
+ where Pointer to where clause
+ select_insert Check is making for SELECT ... INSERT
+
+ RETURN
+ FALSE ok
+ TRUE ERROR
+*/
+
+static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
+ List<Item> &fields, COND **where,
+ bool select_insert)
+{
+ bool insert_into_view= (table_list->view != 0);
+ DBUG_ENTER("mysql_prepare_insert_check_table");
+
+ if (setup_tables(thd, &thd->lex->select_lex.context,
+ &thd->lex->select_lex.top_join_list,
+ table_list, where, &thd->lex->select_lex.leaf_tables,
+ select_insert))
+ DBUG_RETURN(TRUE);
+
+ if (insert_into_view && !fields.elements)
+ {
+ thd->lex->empty_field_list_on_rset= 1;
+ if (!table_list->table)
+ {
+ my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(insert_view_fields(thd, &fields, table_list));
+ }
+
+ DBUG_RETURN(FALSE);
}
@@ -500,15 +783,12 @@ abort:
SYNOPSIS
mysql_prepare_insert()
- thd thread handler
- table_list global table list (not including first table for
- INSERT ... SELECT)
- insert_table_list Table we are inserting into (for INSERT ... SELECT)
- dup_table_list Tables to be used in ON DUPLICATE KEY
- It's either all global tables or only the table we
- insert into, depending on if we are using GROUP BY
- in the SELECT clause).
- values Values to insert. NULL for INSERT ... SELECT
+ thd Thread handler
+ table_list Global/local table list
+ table Table to insert into (can be NULL if table should
+ be taken from table_list->table)
+ where Where clause (for insert ... select)
+ select_insert TRUE if INSERT ... SELECT statement
TODO (in far future)
In cases of:
@@ -519,51 +799,136 @@ abort:
WARNING
You MUST set table->insert_values to 0 after calling this function
before releasing the table object.
-
+
RETURN VALUE
- 0 OK
- -1 error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
- TABLE_LIST *insert_table_list,
- TABLE_LIST *dup_table_list,
- TABLE *table,
- List<Item> &fields, List_item *values,
- List<Item> &update_fields, List<Item> &update_values,
- enum_duplicates duplic)
+bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
+ TABLE *table, List<Item> &fields, List_item *values,
+ List<Item> &update_fields, List<Item> &update_values,
+ enum_duplicates duplic,
+ COND **where, bool select_insert)
{
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
+ Name_resolution_context *context= &select_lex->context;
+ TABLE_LIST *save_table_list;
+ TABLE_LIST *save_next_local;
+ TABLE_LIST *save_first_name_resolution_table;
+ TABLE_LIST *save_next_name_resolution_table;
+ bool save_resolve_in_select_list;
+ bool insert_into_view= (table_list->view != 0);
+ bool res= 0;
DBUG_ENTER("mysql_prepare_insert");
+ DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
+ (ulong)table_list, (ulong)table,
+ (int)insert_into_view));
- if (duplic == DUP_UPDATE && !table->insert_values)
+ /*
+ For subqueries in VALUES() we should not see the table in which we are
+ inserting (for INSERT ... SELECT this is done by changing table_list,
+ because INSERT ... SELECT share SELECT_LEX it with SELECT.
+ */
+ if (!select_insert)
+ {
+ for (SELECT_LEX_UNIT *un= select_lex->first_inner_unit();
+ un;
+ un= un->next_unit())
+ {
+ for (SELECT_LEX *sl= un->first_select();
+ sl;
+ sl= sl->next_select())
+ {
+ sl->context.outer_context= 0;
+ }
+ }
+ }
+
+ if (duplic == DUP_UPDATE)
{
/* it should be allocated before Item::fix_fields() */
- table->insert_values=
- (byte *)alloc_root(thd->mem_root, table->rec_buff_length);
- if (!table->insert_values)
- DBUG_RETURN(-1);
+ if (table_list->set_insert_values(thd->mem_root))
+ DBUG_RETURN(TRUE);
}
- if (setup_tables(insert_table_list))
- DBUG_RETURN(-1);
- if (values)
- {
- if (check_insert_fields(thd, table, fields, *values) ||
- setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) ||
- (duplic == DUP_UPDATE &&
- (check_update_fields(thd, table, insert_table_list, update_fields) ||
- setup_fields(thd, 0, dup_table_list, update_values, 1, 0, 0))))
- DBUG_RETURN(-1);
- if (find_real_table_in_list(table_list->next, table_list->db,
- table_list->real_name))
+
+ if (mysql_prepare_insert_check_table(thd, table_list, fields, where,
+ select_insert))
+ DBUG_RETURN(TRUE);
+
+ /* Save the state of the current name resolution context. */
+ save_table_list= context->table_list;
+ /* Here first_name_resolution_table points to the first select table. */
+ save_first_name_resolution_table= context->first_name_resolution_table;
+ save_next_name_resolution_table= (context->first_name_resolution_table) ?
+ context->first_name_resolution_table->
+ next_name_resolution_table :
+ NULL;
+ save_resolve_in_select_list= context->resolve_in_select_list;
+ save_next_local= table_list->next_local;
+
+ /*
+ Perform name resolution only in the first table - 'table_list',
+ which is the table that is inserted into.
+ */
+ table_list->next_local= 0;
+ context->resolve_in_table_list_only(table_list);
+
+ /* Prepare the fields in the statement. */
+ if (values &&
+ !(res= check_insert_fields(thd, context->table_list, fields, *values,
+ !insert_into_view) ||
+ setup_fields(thd, 0, *values, 0, 0, 0)) &&
+ duplic == DUP_UPDATE)
+ {
+ select_lex->no_wrap_view_item= TRUE;
+ res= check_update_fields(thd, context->table_list, update_fields);
+ select_lex->no_wrap_view_item= FALSE;
+ /*
+ When we are not using GROUP BY we can refer to other tables in the
+ ON DUPLICATE KEY part.
+ */
+ if (select_lex->group_list.elements == 0)
+ {
+ context->table_list->next_local= save_next_local;
+ /* first_name_resolution_table was set by resolve_in_table_list_only() */
+ context->first_name_resolution_table->
+ next_name_resolution_table= save_next_local;
+ }
+ if (!res)
+ res= setup_fields(thd, 0, update_values, 1, 0, 0);
+ }
+
+ /* Restore the current context. */
+ table_list->next_local= save_next_local;
+ context->table_list= save_table_list;
+ context->first_name_resolution_table= save_first_name_resolution_table;
+ if (context->first_name_resolution_table)
+ context->first_name_resolution_table->
+ next_name_resolution_table= save_next_name_resolution_table;
+ context->resolve_in_select_list= save_resolve_in_select_list;
+
+ if (res)
+ DBUG_RETURN(res);
+
+ if (!table)
+ table= table_list->table;
+
+ if (!select_insert)
+ {
+ Item *fake_conds= 0;
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(table_list, table_list->next_global)))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
- DBUG_RETURN(-1);
+ update_non_unique_table_error(table_list, "INSERT", duplicate);
+ DBUG_RETURN(TRUE);
}
+ select_lex->fix_prepare_information(thd, &fake_conds);
+ select_lex->first_execution= 0;
}
if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
-
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -571,7 +936,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
static int last_uniq_key(TABLE *table,uint keynr)
{
- while (++keynr < table->keys)
+ while (++keynr < table->s->keys)
if (table->key_info[keynr].flags & HA_NOSAME)
return 0;
return 1;
@@ -579,13 +944,35 @@ static int last_uniq_key(TABLE *table,uint keynr)
/*
- Write a record to table with optional deleting of conflicting records
+ Write a record to table with optional deleting of conflicting records,
+ invoke proper triggers if needed.
+
+ SYNOPSIS
+ write_record()
+ thd - thread context
+ table - table to which record should be written
+ info - COPY_INFO structure describing handling of duplicates
+ and which is used for counting number of records inserted
+ and deleted.
+
+ NOTE
+ Once this record will be written to table after insert trigger will
+ be invoked. If instead of inserting new record we will update old one
+ then both on update triggers will work instead. Similarly both on
+ delete triggers will be invoked if we will delete conflicting records.
+
+ Sets thd->no_trans_update if table which is updated didn't have
+ transactions.
+
+ RETURN VALUE
+ 0 - success
+ non-0 - error
*/
-int write_record(TABLE *table,COPY_INFO *info)
+int write_record(THD *thd, TABLE *table,COPY_INFO *info)
{
- int error;
+ int error, trg_error= 0;
char *key=0;
DBUG_ENTER("write_record");
@@ -595,9 +982,10 @@ int write_record(TABLE *table,COPY_INFO *info)
{
while ((error=table->file->write_row(table->record[0])))
{
+ uint key_nr;
if (error != HA_WRITE_SKIP)
goto err;
- uint key_nr;
+ table->file->restore_auto_increment();
if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
{
error=HA_WRITE_SKIP; /* Database can't find key */
@@ -610,7 +998,7 @@ int write_record(TABLE *table,COPY_INFO *info)
*/
if (info->handle_duplicates == DUP_REPLACE &&
table->next_number_field &&
- key_nr == table->next_number_index &&
+ key_nr == table->s->next_number_index &&
table->file->auto_increment_column_changed)
goto err;
if (table->file->table_flags() & HA_DUPP_POS)
@@ -628,14 +1016,14 @@ int write_record(TABLE *table,COPY_INFO *info)
if (!key)
{
- if (!(key=(char*) my_safe_alloca(table->max_unique_length,
+ if (!(key=(char*) my_safe_alloca(table->s->max_unique_length,
MAX_KEY_LENGTH)))
{
error=ENOMEM;
goto err;
}
}
- key_copy((byte*) key,table,key_nr,0);
+ key_copy((byte*) key,table->record[0],table->key_info+key_nr,0);
if ((error=(table->file->index_read_idx(table->record[1],key_nr,
(byte*) key,
table->key_info[key_nr].
@@ -645,24 +1033,50 @@ int write_record(TABLE *table,COPY_INFO *info)
}
if (info->handle_duplicates == DUP_UPDATE)
{
- /* we don't check for other UNIQUE keys - the first row
- that matches, is updated. If update causes a conflict again,
- an error is returned
+ int res= 0;
+ /*
+ We don't check for other UNIQUE keys - the first row
+ that matches, is updated. If update causes a conflict again,
+ an error is returned
*/
DBUG_ASSERT(table->insert_values != NULL);
store_record(table,insert_values);
restore_record(table,record[1]);
- DBUG_ASSERT(info->update_fields->elements==info->update_values->elements);
- if (fill_record(*info->update_fields, *info->update_values, 0))
- goto err;
+ DBUG_ASSERT(info->update_fields->elements ==
+ info->update_values->elements);
+ if (fill_record_n_invoke_before_triggers(thd, *info->update_fields,
+ *info->update_values, 0,
+ table->triggers,
+ TRG_EVENT_UPDATE))
+ goto before_trg_err;
+
+ /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
+ if (info->view &&
+ (res= info->view->view_check_option(current_thd, info->ignore)) ==
+ VIEW_CHECK_SKIP)
+ goto ok_or_after_trg_err;
+ if (res == VIEW_CHECK_ERROR)
+ goto before_trg_err;
+
+ if (thd->clear_next_insert_id)
+ {
+ /* Reset auto-increment cacheing if we do an update */
+ thd->clear_next_insert_id= 0;
+ thd->next_insert_id= 0;
+ }
if ((error=table->file->update_row(table->record[1],table->record[0])))
{
if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore)
- break;
+ goto ok_or_after_trg_err;
goto err;
}
info->updated++;
- break;
+
+ trg_error= (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER, TRUE));
+ info->copied++;
+ goto ok_or_after_trg_err;
}
else /* DUP_REPLACE */
{
@@ -679,63 +1093,130 @@ int write_record(TABLE *table,COPY_INFO *info)
(table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
{
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
+ TRG_ACTION_BEFORE, TRUE))
+ goto before_trg_err;
+ if (thd->clear_next_insert_id)
+ {
+ /* Reset auto-increment cacheing if we do an update */
+ thd->clear_next_insert_id= 0;
+ thd->next_insert_id= 0;
+ }
if ((error=table->file->update_row(table->record[1],
table->record[0])))
goto err;
info->deleted++;
- break; /* Update logfile and count */
+ trg_error= (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER,
+ TRUE));
+ /* Update logfile and count */
+ info->copied++;
+ goto ok_or_after_trg_err;
+ }
+ else
+ {
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+ TRG_ACTION_BEFORE, TRUE))
+ goto before_trg_err;
+ if ((error=table->file->delete_row(table->record[1])))
+ goto err;
+ info->deleted++;
+ if (!table->file->has_transactions())
+ thd->no_trans_update= 1;
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER, TRUE))
+ {
+ trg_error= 1;
+ goto ok_or_after_trg_err;
+ }
+ /* Let us attempt do write_row() once more */
}
- else if ((error=table->file->delete_row(table->record[1])))
- goto err;
- info->deleted++;
}
}
info->copied++;
+ trg_error= (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
+ TRG_ACTION_AFTER, TRUE));
}
else if ((error=table->file->write_row(table->record[0])))
{
if (!info->ignore ||
(error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE))
goto err;
+ table->file->restore_auto_increment();
}
else
+ {
info->copied++;
+ trg_error= (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
+ TRG_ACTION_AFTER, TRUE));
+ }
+
+ok_or_after_trg_err:
if (key)
- my_safe_afree(key,table->max_unique_length,MAX_KEY_LENGTH);
- DBUG_RETURN(0);
+ my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH);
+ if (!table->file->has_transactions())
+ thd->no_trans_update= 1;
+ DBUG_RETURN(trg_error);
err:
- if (key)
- my_safe_afree(key,table->max_unique_length,MAX_KEY_LENGTH);
info->last_errno= error;
+ /* current_select is NULL if this is a delayed insert */
+ if (thd->lex->current_select)
+ thd->lex->current_select->no_error= 0; // Give error
table->file->print_error(error,MYF(0));
+
+before_trg_err:
+ if (key)
+ my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH);
DBUG_RETURN(1);
}
/******************************************************************************
Check that all fields with arn't null_fields are used
- If DONT_USE_DEFAULT_FIELDS isn't defined use default value for not set
- fields.
******************************************************************************/
-static int check_null_fields(THD *thd __attribute__((unused)),
- TABLE *entry __attribute__((unused)))
+int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
+ TABLE_LIST *table_list)
{
-#ifdef DONT_USE_DEFAULT_FIELDS
+ int err= 0;
for (Field **field=entry->field ; *field ; field++)
{
- if ((*field)->query_id != thd->query_id && !(*field)->maybe_null() &&
- *field != entry->timestamp_field &&
- *field != entry->next_number_field)
+ if ((*field)->query_id != thd->query_id &&
+ ((*field)->flags & NO_DEFAULT_VALUE_FLAG) &&
+ ((*field)->real_type() != FIELD_TYPE_ENUM))
{
- my_printf_error(ER_BAD_NULL_ERROR, ER(ER_BAD_NULL_ERROR),MYF(0),
- (*field)->field_name);
- return 1;
+ bool view= FALSE;
+ if (table_list)
+ {
+ table_list= table_list->top_table();
+ view= test(table_list->view);
+ }
+ if (view)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_NO_DEFAULT_FOR_VIEW_FIELD,
+ ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
+ table_list->view_db.str,
+ table_list->view_name.str);
+ }
+ else
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_NO_DEFAULT_FOR_FIELD,
+ ER(ER_NO_DEFAULT_FOR_FIELD),
+ (*field)->field_name);
+ }
+ err= 1;
}
}
-#endif
- return 0;
+ return thd->abort_on_warning ? err : 0;
}
/*****************************************************************************
@@ -750,14 +1231,13 @@ public:
char *record,*query;
enum_duplicates dup;
time_t start_time;
- bool query_start_used,last_insert_id_used,insert_id_used, ignore;
- int log_query;
+ bool query_start_used,last_insert_id_used,insert_id_used, ignore, log_query;
ulonglong last_insert_id;
timestamp_auto_set_type timestamp_field_type;
uint query_length;
- delayed_row(enum_duplicates dup_arg, bool ignore_arg, int log_query_arg)
- :record(0),query(0),dup(dup_arg),ignore(ignore_arg),log_query(log_query_arg) {}
+ delayed_row(enum_duplicates dup_arg, bool ignore_arg, bool log_query_arg)
+ :record(0), query(0), dup(dup_arg), ignore(ignore_arg), log_query(log_query_arg) {}
~delayed_row()
{
x_free(record);
@@ -864,7 +1344,7 @@ delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
while ((tmp=it++))
{
if (!strcmp(tmp->thd.db,table_list->db) &&
- !strcmp(table_list->real_name,tmp->table->real_name))
+ !strcmp(table_list->table_name,tmp->table->s->table_name))
{
tmp->lock();
break;
@@ -923,15 +1403,15 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
thread_count++;
pthread_mutex_unlock(&LOCK_thread_count);
if (!(tmp->thd.db=my_strdup(table_list->db,MYF(MY_WME))) ||
- !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_WME))))
+ !(tmp->thd.query=my_strdup(table_list->table_name,MYF(MY_WME))))
{
delete tmp;
- my_error(ER_OUT_OF_RESOURCES,MYF(0));
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
goto err1;
}
tmp->table_list= *table_list; // Needed to open table
tmp->table_list.db= tmp->thd.db;
- tmp->table_list.alias= tmp->table_list.real_name=tmp->thd.query;
+ tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query;
tmp->lock();
pthread_mutex_lock(&tmp->mutex);
if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib,
@@ -943,7 +1423,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
pthread_mutex_unlock(&tmp->mutex);
tmp->unlock();
delete tmp;
- net_printf(thd,ER_CANT_CREATE_THREAD,error);
+ my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
goto err1;
}
@@ -982,7 +1462,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
}
pthread_mutex_lock(&tmp->mutex);
- table=tmp->get_local_table(thd);
+ table= tmp->get_local_table(thd);
pthread_mutex_unlock(&tmp->mutex);
if (table)
thd->di=tmp;
@@ -1042,17 +1522,19 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
client_thd->proc_info="allocating local table";
copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
- (table->fields+1)*sizeof(Field**)+
- table->reclength);
+ (table->s->fields+1)*sizeof(Field**)+
+ table->s->reclength);
if (!copy)
goto error;
*copy= *table;
- bzero((char*) &copy->name_hash,sizeof(copy->name_hash)); // No name hashing
+ copy->s= &copy->share_not_to_be_used;
+ // No name hashing
+ bzero((char*) &copy->s->name_hash,sizeof(copy->s->name_hash));
/* We don't need to change the file handler here */
field=copy->field=(Field**) (copy+1);
- copy->record[0]=(byte*) (field+table->fields+1);
- memcpy((char*) copy->record[0],(char*) table->record[0],table->reclength);
+ copy->record[0]=(byte*) (field+table->s->fields+1);
+ memcpy((char*) copy->record[0],(char*) table->record[0],table->s->reclength);
/* Make a copy of all fields */
@@ -1075,7 +1557,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
{
/* Restore offset as this may have been reset in handle_inserts */
copy->timestamp_field=
- (Field_timestamp*) copy->field[table->timestamp_field_offset];
+ (Field_timestamp*) copy->field[table->s->timestamp_field_offset];
copy->timestamp_field->unireg_check= table->timestamp_field->unireg_check;
copy->timestamp_field_type= copy->timestamp_field->get_auto_set_type();
}
@@ -1100,7 +1582,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
/* Put a question in queue */
static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool ignore,
- char *query, uint query_length, int log_on)
+ char *query, uint query_length, bool log_on)
{
delayed_row *row=0;
delayed_insert *di=thd->di;
@@ -1117,13 +1599,13 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool igno
if (!query)
query_length=0;
- if (!(row->record= (char*) my_malloc(table->reclength+query_length+1,
+ if (!(row->record= (char*) my_malloc(table->s->reclength+query_length+1,
MYF(MY_WME))))
goto err;
- memcpy(row->record,table->record[0],table->reclength);
+ memcpy(row->record, table->record[0], table->s->reclength);
if (query_length)
{
- row->query=row->record+table->reclength;
+ row->query= row->record+table->s->reclength;
memcpy(row->query,query,query_length+1);
}
row->query_length= query_length;
@@ -1137,7 +1619,7 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool igno
di->rows.push_back(row);
di->stacked_inserts++;
di->status=1;
- if (table->blob_fields)
+ if (table->s->blob_fields)
unlink_blobs(table);
pthread_cond_signal(&di->cond);
@@ -1180,7 +1662,7 @@ void kill_delayed_threads(void)
{
/* Ensure that the thread doesn't kill itself while we are looking at it */
pthread_mutex_lock(&tmp->mutex);
- tmp->thd.killed=1;
+ tmp->thd.killed= THD::KILL_CONNECTION;
if (tmp->thd.mysys_var)
{
pthread_mutex_lock(&tmp->thd.mysys_var->mutex);
@@ -1219,7 +1701,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
thd->thread_id=thread_id++;
thd->end_time();
threads.append(thd);
- thd->killed=abort_loop;
+ thd->killed=abort_loop ? THD::KILL_CONNECTION : THD::NOT_KILLED;
pthread_mutex_unlock(&LOCK_thread_count);
/*
@@ -1262,7 +1744,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
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);
+ my_error(ER_ILLEGAL_HA, MYF(0), di->table_list.table_name);
goto end;
}
di->table->copy_blobs=1;
@@ -1280,7 +1762,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
for (;;)
{
- if (thd->killed)
+ if (thd->killed == THD::KILL_CONNECTION)
{
uint lock_count;
/*
@@ -1326,9 +1808,9 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
#endif
if (thd->killed || di->status)
break;
- if (error == ETIME || error == ETIMEDOUT)
+ if (error == ETIMEDOUT)
{
- thd->killed=1;
+ thd->killed= THD::KILL_CONNECTION;
break;
}
}
@@ -1344,6 +1826,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
if (di->tables_in_use && ! thd->lock)
{
+ bool not_used;
/*
Request for new delayed insert.
Lock the table, but avoid to be blocked by a global read lock.
@@ -1355,10 +1838,12 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
inserts are done.
*/
if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1,
- MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK)))
+ MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK,
+ &not_used)))
{
- di->dead= 1; // Some fatal error
- thd->killed= 1;
+ /* Fatal error */
+ di->dead= 1;
+ thd->killed= THD::KILL_CONNECTION;
}
pthread_cond_broadcast(&di->cond_client);
}
@@ -1366,8 +1851,9 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
{
if (di->handle_inserts())
{
- di->dead= 1; // Some fatal error
- thd->killed= 1;
+ /* Some fatal error */
+ di->dead= 1;
+ thd->killed= THD::KILL_CONNECTION;
}
}
di->status=0;
@@ -1397,7 +1883,7 @@ end:
close_thread_tables(thd); // Free the table
di->table=0;
di->dead= 1; // If error
- thd->killed= 1;
+ thd->killed= THD::KILL_CONNECTION; // If error
pthread_cond_broadcast(&di->cond_client); // Safety
pthread_mutex_unlock(&di->mutex);
@@ -1458,15 +1944,15 @@ bool delayed_insert::handle_inserts(void)
if (thr_upgrade_write_delay_lock(*thd.lock->locks))
{
/* This can only happen if thread is killed by shutdown */
- sql_print_error(ER(ER_DELAYED_CANT_CHANGE_LOCK),table->real_name);
+ sql_print_error(ER(ER_DELAYED_CANT_CHANGE_LOCK),table->s->table_name);
goto err;
}
thd.proc_info="insert";
max_rows= delayed_insert_limit;
- if (thd.killed || table->version != refresh_version)
+ if (thd.killed || table->s->version != refresh_version)
{
- thd.killed=1;
+ thd.killed= THD::KILL_CONNECTION;
max_rows= ~(ulong)0; // Do as much as possible
}
@@ -1482,7 +1968,7 @@ bool delayed_insert::handle_inserts(void)
{
stacked_inserts--;
pthread_mutex_unlock(&mutex);
- memcpy(table->record[0],row->record,table->reclength);
+ memcpy(table->record[0],row->record,table->s->reclength);
thd.start_time=row->start_time;
thd.query_start_used=row->query_start_used;
@@ -1500,7 +1986,7 @@ bool delayed_insert::handle_inserts(void)
using_ignore=1;
}
thd.clear_error(); // reset error for binlog
- if (write_record(table,&info))
+ if (write_record(&thd, table, &info))
{
info.error_count++; // Ignore errors
thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status);
@@ -1511,17 +1997,12 @@ bool delayed_insert::handle_inserts(void)
using_ignore=0;
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
}
- if (row->query)
+ if (row->query && row->log_query && using_bin_log)
{
- if (row->log_query & DELAYED_LOG_UPDATE)
- mysql_update_log.write(&thd,row->query, row->query_length);
- if (row->log_query & DELAYED_LOG_BIN && using_bin_log)
- {
- Query_log_event qinfo(&thd, row->query, row->query_length,0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
}
- if (table->blob_fields)
+ if (table->s->blob_fields)
free_delayed_insert_blobs(table);
thread_safe_sub(delayed_rows_in_use,1,&LOCK_delayed_status);
thread_safe_increment(delayed_insert_writes,&LOCK_delayed_status);
@@ -1535,7 +2016,7 @@ bool delayed_insert::handle_inserts(void)
on this table until all entries has been processed
*/
if (group_count++ >= max_rows && (row= rows.head()) &&
- (!(row->log_query & DELAYED_LOG_BIN && using_bin_log) ||
+ (!(row->log_query & using_bin_log) ||
row->query))
{
group_count=0;
@@ -1556,7 +2037,7 @@ bool delayed_insert::handle_inserts(void)
if (thr_reschedule_write_lock(*thd.lock->locks))
{
/* This should never happen */
- sql_print_error(ER(ER_DELAYED_CANT_CHANGE_LOCK),table->real_name);
+ sql_print_error(ER(ER_DELAYED_CANT_CHANGE_LOCK),table->s->table_name);
}
if (!using_bin_log)
table->file->extra(HA_EXTRA_WRITE_CACHE);
@@ -1599,13 +2080,83 @@ bool delayed_insert::handle_inserts(void)
Store records in INSERT ... SELECT *
***************************************************************************/
+
+/*
+ make insert specific preparation and checks after opening tables
+
+ SYNOPSIS
+ mysql_insert_select_prepare()
+ thd thread handler
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+bool mysql_insert_select_prepare(THD *thd)
+{
+ LEX *lex= thd->lex;
+ SELECT_LEX *select_lex= &lex->select_lex;
+ TABLE_LIST *first_select_leaf_table;
+ DBUG_ENTER("mysql_insert_select_prepare");
+
+ /*
+ SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
+ clause if table is VIEW
+ */
+
+ if (mysql_prepare_insert(thd, lex->query_tables,
+ lex->query_tables->table, lex->field_list, 0,
+ lex->update_list, lex->value_list,
+ lex->duplicates,
+ &select_lex->where, TRUE))
+ DBUG_RETURN(TRUE);
+
+ /*
+ exclude first table from leaf tables list, because it belong to
+ INSERT
+ */
+ DBUG_ASSERT(select_lex->leaf_tables != 0);
+ lex->leaf_tables_insert= select_lex->leaf_tables;
+ /* skip all leaf tables belonged to view where we are insert */
+ for (first_select_leaf_table= select_lex->leaf_tables->next_leaf;
+ first_select_leaf_table &&
+ first_select_leaf_table->belong_to_view &&
+ first_select_leaf_table->belong_to_view ==
+ lex->leaf_tables_insert->belong_to_view;
+ first_select_leaf_table= first_select_leaf_table->next_leaf)
+ {}
+ select_lex->leaf_tables= first_select_leaf_table;
+ DBUG_RETURN(FALSE);
+}
+
+
+select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par,
+ List<Item> *fields_par,
+ List<Item> *update_fields,
+ List<Item> *update_values,
+ enum_duplicates duplic,
+ bool ignore_check_option_errors)
+ :table_list(table_list_par), table(table_par), fields(fields_par),
+ last_insert_id(0),
+ insert_into_view(table_list_par && table_list_par->view != 0)
+{
+ bzero((char*) &info,sizeof(info));
+ info.handle_duplicates= duplic;
+ info.ignore= ignore_check_option_errors;
+ info.update_fields= update_fields;
+ info.update_values= update_values;
+ if (table_list_par)
+ info.view= (table_list_par->view ? table_list_par : 0);
+}
+
+
int
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
- int res;
LEX *lex= thd->lex;
+ int res;
SELECT_LEX *lex_current_select_save= lex->current_select;
- bool lex_select_no_error= lex->select_lex.no_error;
DBUG_ENTER("select_insert::prepare");
unit= u;
@@ -1613,29 +2164,128 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
Since table in which we are going to insert is added to the first
select, LEX::current_select should point to the first select while
we are fixing fields from insert list.
- Since these checks may cause the query to fail, we don't want the
- error messages to be converted into warnings, must force no_error=0
*/
lex->current_select= &lex->select_lex;
- lex->select_lex.no_error= 0;
- res=
- check_insert_fields(thd, table, *fields, values) ||
- setup_fields(thd, 0, insert_table_list, values, 0, 0, 0) ||
- (info.handle_duplicates == DUP_UPDATE &&
- (check_update_fields(thd, table, insert_table_list, *info.update_fields) ||
- setup_fields(thd, 0, dup_table_list, *info.update_values, 1, 0, 0)));
+ res= check_insert_fields(thd, table_list, *fields, values,
+ !insert_into_view) ||
+ setup_fields(thd, 0, values, 0, 0, 0);
+
+ if (info.handle_duplicates == DUP_UPDATE)
+ {
+ /* Save the state of the current name resolution context. */
+ Name_resolution_context *context= &lex->select_lex.context;
+ TABLE_LIST *save_table_list;
+ TABLE_LIST *save_next_local;
+ TABLE_LIST *save_first_name_resolution_table;
+ TABLE_LIST *save_next_name_resolution_table;
+ save_table_list= context->table_list;
+ save_first_name_resolution_table= context->first_name_resolution_table;
+ save_next_name_resolution_table= (context->first_name_resolution_table) ?
+ context->first_name_resolution_table->
+ next_name_resolution_table :
+ NULL;
+ save_next_local= table_list->next_local;
+
+ /* Perform name resolution only in the first table - 'table_list'. */
+ table_list->next_local= 0;
+ context->resolve_in_table_list_only(table_list);
+
+ lex->select_lex.no_wrap_view_item= TRUE;
+ res= res || check_update_fields(thd, context->table_list,
+ *info.update_fields);
+ lex->select_lex.no_wrap_view_item= FALSE;
+ /*
+ When we are not using GROUP BY we can refer to other tables in the
+ ON DUPLICATE KEY part
+ */
+ if (lex->select_lex.group_list.elements == 0)
+ {
+ context->table_list->next_local= save_next_local;
+ /* first_name_resolution_table was set by resolve_in_table_list_only() */
+ context->first_name_resolution_table->
+ next_name_resolution_table= save_next_local;
+ }
+ res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0);
+
+ /* Restore the current context. */
+ table_list->next_local= save_next_local;
+ context->first_name_resolution_table= save_first_name_resolution_table;
+ if (context->first_name_resolution_table)
+ context->first_name_resolution_table->
+ next_name_resolution_table= save_next_name_resolution_table;
+
+ }
+
lex->current_select= lex_current_select_save;
- lex->select_lex.no_error= lex_select_no_error;
if (res)
DBUG_RETURN(1);
+ /*
+ if it is INSERT into join view then check_insert_fields already found
+ real table for insert
+ */
+ table= table_list->table;
- restore_record(table,default_values); // Get empty record
+ /*
+ Is table which we are changing used somewhere in other parts of
+ query
+ */
+ if (!(lex->current_select->options & OPTION_BUFFER_RESULT) &&
+ unique_table(table_list, table_list->next_global))
+ {
+ /* Using same table for INSERT and SELECT */
+ lex->current_select->options|= OPTION_BUFFER_RESULT;
+ lex->current_select->join->select_options|= OPTION_BUFFER_RESULT;
+ }
+ else
+ {
+ /*
+ We must not yet prepare the result table if it is the same as one of the
+ source tables (INSERT SELECT). The preparation may disable
+ indexes on the result table, which may be used during the select, if it
+ is the same table (Bug #6034). Do the preparation after the select phase
+ in select_insert::prepare2().
+ */
+ table->file->start_bulk_insert((ha_rows) 0);
+ }
+ restore_record(table,s->default_values); // Get empty record
table->next_number_field=table->found_next_number_field;
thd->cuted_fields=0;
- if (info.ignore ||
- info.handle_duplicates != DUP_ERROR)
+ if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- table->file->start_bulk_insert((ha_rows) 0);
+ thd->no_trans_update= 0;
+ thd->abort_on_warning= (!info.ignore &&
+ (thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES)));
+ res= ((fields->elements &&
+ check_that_all_fields_are_given_values(thd, table, table_list)) ||
+ table_list->prepare_where(thd, 0, TRUE) ||
+ table_list->prepare_check_option(thd));
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Finish the preparation of the result table.
+
+ SYNOPSIS
+ select_insert::prepare2()
+ void
+
+ DESCRIPTION
+ If the result table is the same as one of the source tables (INSERT SELECT),
+ the result table is not finally prepared at the join prepair phase.
+ Do the final preparation now.
+
+ RETURN
+ 0 OK
+*/
+
+int select_insert::prepare2(void)
+{
+ DBUG_ENTER("select_insert::prepare2");
+ if (thd->lex->current_select->options & OPTION_BUFFER_RESULT)
+ table->file->start_bulk_insert((ha_rows) 0);
DBUG_RETURN(0);
}
@@ -1648,12 +2298,15 @@ void select_insert::cleanup()
select_insert::~select_insert()
{
+ DBUG_ENTER("~select_insert");
if (table)
{
table->next_number_field=0;
table->file->reset();
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+ thd->abort_on_warning= 0;
+ DBUG_VOID_RETURN;
}
@@ -1666,25 +2319,44 @@ bool select_insert::send_data(List<Item> &values)
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
- thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
+
+ thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
store_values(values);
- error=thd->net.report_error || write_record(table,&info);
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
-
- if (!error)
+ if (thd->net.report_error)
+ DBUG_RETURN(1);
+ if (table_list) // Not CREATE ... SELECT
{
- /*
- Restore fields of the record since it is possible that they were
- changed by ON DUPLICATE KEY UPDATE clause.
- */
- if (info.handle_duplicates == DUP_UPDATE)
- restore_record(table, default_values);
-
- if (table->next_number_field) // Clear for next record
+ switch (table_list->view_check_option(thd, info.ignore)) {
+ case VIEW_CHECK_SKIP:
+ DBUG_RETURN(0);
+ case VIEW_CHECK_ERROR:
+ DBUG_RETURN(1);
+ }
+ }
+ if (!(error= write_record(thd, table, &info)))
+ {
+ if (table->triggers || info.handle_duplicates == DUP_UPDATE)
{
+ /*
+ Restore fields of the record since it is possible that they were
+ changed by ON DUPLICATE KEY UPDATE clause.
+
+ If triggers exist then whey can modify some fields which were not
+ originally touched by INSERT ... SELECT, so we have to restore
+ their original values for the next row.
+ */
+ restore_record(table, s->default_values);
+ }
+ if (table->next_number_field)
+ {
+ /*
+ Clear auto-increment field for the next record, if triggers are used
+ we will clear it twice, but this should be cheap.
+ */
table->next_number_field->reset();
- if (! last_insert_id && thd->insert_id_used)
- last_insert_id=thd->insert_id();
+ if (!last_insert_id && thd->insert_id_used)
+ last_insert_id= thd->insert_id();
}
}
DBUG_RETURN(error);
@@ -1694,17 +2366,18 @@ bool select_insert::send_data(List<Item> &values)
void select_insert::store_values(List<Item> &values)
{
if (fields->elements)
- fill_record(*fields, values, 1);
+ fill_record_n_invoke_before_triggers(thd, *fields, values, 1,
+ table->triggers, TRG_EVENT_INSERT);
else
- fill_record(table->field, values, 1);
+ fill_record_n_invoke_before_triggers(thd, table->field, values, 1,
+ table->triggers, TRG_EVENT_INSERT);
}
void select_insert::send_error(uint errcode,const char *err)
{
DBUG_ENTER("select_insert::send_error");
- /* TODO error should be sent at the query processing end */
- ::send_error(thd,errcode,err);
+ my_message(errcode, err, MYF(0));
if (!table)
{
@@ -1726,18 +2399,19 @@ void select_insert::send_error(uint errcode,const char *err)
{
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log
- mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
table->file->has_transactions(), FALSE);
mysql_bin_log.write(&qinfo);
}
- if (!table->tmp_table)
+ if (!table->s->tmp_table)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (info.copied || info.deleted || info.updated)
+ {
query_cache_invalidate3(thd, table, 1);
+ }
ha_rollback_stmt(thd);
DBUG_VOID_RETURN;
}
@@ -1753,20 +2427,19 @@ bool select_insert::send_eof()
/*
We must invalidate the table in the query cache before binlog writing
- and ha_autocommit_...
+ and ha_autocommit_or_rollback
*/
if (info.copied || info.deleted || info.updated)
{
query_cache_invalidate3(thd, table, 1);
- if (!(table->file->has_transactions() || table->tmp_table))
+ if (!(table->file->has_transactions() || table->s->tmp_table))
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log
/* Write to binlog before commiting transaction */
- mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
if (!error)
@@ -1780,8 +2453,6 @@ bool select_insert::send_eof()
if (error)
{
table->file->print_error(error,MYF(0));
- //TODO error should be sent at the query processing end
- ::send_error(thd);
DBUG_RETURN(1);
}
char buff[160];
@@ -1791,7 +2462,8 @@ bool select_insert::send_eof()
else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields);
- ::send_ok(thd,info.copied+info.deleted+info.updated,last_insert_id,buff);
+ thd->row_count_func= info.copied+info.deleted+info.updated;
+ ::send_ok(thd, (ulong) thd->row_count_func, last_insert_id, buff);
DBUG_RETURN(0);
}
@@ -1806,40 +2478,44 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
DBUG_ENTER("select_create::prepare");
unit= u;
- table= create_table_from_items(thd, create_info, db, name,
+ table= create_table_from_items(thd, create_info, create_table,
extra_fields, keys, &values, &lock);
if (!table)
DBUG_RETURN(-1); // abort() deletes table
- if (table->fields < values.elements)
+ if (table->s->fields < values.elements)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0),1);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
DBUG_RETURN(-1);
}
/* First field to copy */
- field=table->field+table->fields - values.elements;
+ field=table->field+table->s->fields - values.elements;
/* Don't set timestamp if used */
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
table->next_number_field=table->found_next_number_field;
- restore_record(table,default_values); // Get empty record
+ restore_record(table,s->default_values); // Get empty record
thd->cuted_fields=0;
- if (info.ignore ||
- info.handle_duplicates != DUP_ERROR)
+ if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
table->file->start_bulk_insert((ha_rows) 0);
- DBUG_RETURN(0);
+ thd->no_trans_update= 0;
+ thd->abort_on_warning= (!info.ignore &&
+ (thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES)));
+ DBUG_RETURN(check_that_all_fields_are_given_values(thd, table,
+ table_list));
}
void select_create::store_values(List<Item> &values)
{
- fill_record(field, values, 1);
+ fill_record_n_invoke_before_triggers(thd, field, values, 1,
+ table->triggers, TRG_EVENT_INSERT);
}
@@ -1870,9 +2546,9 @@ bool select_create::send_eof()
Check if we can remove the following two rows.
We should be able to just keep the table in the table cache.
*/
- if (!table->tmp_table)
+ if (!table->s->tmp_table)
{
- ulong version= table->version;
+ ulong version= table->s->version;
hash_delete(&open_cache,(byte*) table);
/* Tell threads waiting for refresh that something has happened */
if (version != refresh_version)
@@ -1896,19 +2572,19 @@ void select_create::abort()
if (table)
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
- enum db_type table_type=table->db_type;
- if (!table->tmp_table)
+ enum db_type table_type=table->s->db_type;
+ if (!table->s->tmp_table)
{
- ulong version= table->version;
+ ulong version= table->s->version;
hash_delete(&open_cache,(byte*) table);
if (!create_info->table_existed)
- quick_rm_table(table_type, db, name);
+ quick_rm_table(table_type, create_table->db, create_table->table_name);
/* Tell threads waiting for refresh that something has happened */
if (version != refresh_version)
VOID(pthread_cond_broadcast(&COND_refresh));
}
else if (!create_info->table_existed)
- close_temporary_table(thd, db, name);
+ close_temporary_table(thd, create_table->db, create_table->table_name);
table=0;
}
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -1919,11 +2595,11 @@ void select_create::abort()
Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List_iterator_fast<List_item>;
#ifndef EMBEDDED_LIBRARY
template class I_List<delayed_insert>;
template class I_List_iterator<delayed_insert>;
template class I_List<delayed_row>;
#endif /* EMBEDDED_LIBRARY */
-#endif /* __GNUC__ */
+#endif /* HAVE_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 8636b6542fc..b7a2b6b0624 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -21,16 +21,14 @@
#include "item_create.h"
#include <m_ctype.h>
#include <hash.h>
-
+#include "sp.h"
+#include "sp_head.h"
/*
- Fake table list object, pointer to which is used as special value for
- st_lex::time_zone_tables_used indicating that we implicitly use time
- zone tables in this statement but real table list was not yet created.
- Pointer to it is also returned by my_tz_get_tables_list() as indication
- of transient error;
+ We are using pointer to this variable for distinguishing between assignment
+ to NEW row field (when parsing trigger definition) and structured variable.
*/
-TABLE_LIST fake_time_zone_tables_list;
+sys_var_long_ptr trg_new_row_fake_var(0, 0);
/* Macros to look like lex */
@@ -42,10 +40,6 @@ TABLE_LIST fake_time_zone_tables_list;
#define yySkip() lex->ptr++
#define yyLength() ((uint) (lex->ptr - lex->tok_start)-1)
-#if MYSQL_VERSION_ID < 32300
-#define FLOAT_NUM REAL_NUM
-#endif
-
pthread_key(LEX*,THR_LEX);
/* Longest standard keyword name */
@@ -56,7 +50,8 @@ pthread_key(LEX*,THR_LEX);
used when comparing keywords
*/
-uchar to_upper_lex[] = {
+static uchar to_upper_lex[]=
+{
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,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -117,14 +112,23 @@ void lex_free(void)
void lex_start(THD *thd, uchar *buf,uint length)
{
LEX *lex= thd->lex;
+ DBUG_ENTER("lex_start");
+
+ lex->thd= lex->unit.thd= thd;
+ lex->buf= lex->ptr= buf;
+ lex->end_of_query= buf+length;
+
+ lex->context_stack.empty();
lex->unit.init_query();
lex->unit.init_select();
- lex->thd= thd;
- lex->unit.thd= thd;
+ /* 'parent_lex' is used in init_query() so it must be before it. */
+ lex->select_lex.parent_lex= lex;
lex->select_lex.init_query();
lex->value_list.empty();
lex->update_list.empty();
lex->param_list.empty();
+ lex->view_list.empty();
+ lex->prepared_stmt_params.empty();
lex->unit.next= lex->unit.master=
lex->unit.link_next= lex->unit.return_to= 0;
lex->unit.prev= lex->unit.link_prev= 0;
@@ -135,15 +139,23 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
lex->select_lex.options= 0;
+ lex->select_lex.init_order();
+ lex->select_lex.group_list.empty();
lex->describe= 0;
- lex->subqueries= lex->derived_tables= FALSE;
+ lex->subqueries= FALSE;
+ lex->view_prepare_mode= FALSE;
+ lex->stmt_prepare_mode= FALSE;
+ lex->derived_tables= 0;
lex->lock_option= TL_READ;
- lex->found_colon= 0;
+ lex->found_semicolon= 0;
lex->safe_to_cache_query= 1;
lex->time_zone_tables_used= 0;
+ lex->leaf_tables_insert= lex->query_tables= 0;
+ lex->query_tables_last= &lex->query_tables;
+ lex->variables_used= 0;
+ lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1;
lex->next_state=MY_LEX_START;
- lex->end_of_query=(lex->ptr=buf)+length;
lex->yylineno = 1;
lex->in_comment=0;
lex->length=0;
@@ -156,18 +168,24 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->current_select= &lex->select_lex;
lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
- lex->sql_command=SQLCOM_END;
+ lex->sql_command= lex->orig_sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
+ lex->sphead= NULL;
+ lex->spcont= NULL;
lex->proc_list.first= 0;
+ lex->query_tables_own_last= 0;
+
+ if (lex->sroutines.records)
+ my_hash_reset(&lex->sroutines);
+ lex->sroutines_list.empty();
+ lex->sroutines_list_own_last= lex->sroutines_list.next;
+ lex->sroutines_list_own_elements= 0;
+ DBUG_VOID_RETURN;
}
void lex_end(LEX *lex)
{
- for (SELECT_LEX *sl= lex->all_selects_list;
- sl;
- sl= sl->next_select_in_list())
- sl->expr_list.delete_elements(); // If error when parsing sql-varargs
x_free(lex->yacc_yyss);
x_free(lex->yacc_yyvs);
}
@@ -183,29 +201,16 @@ static int find_keyword(LEX *lex, uint len, bool function)
lex->yylval->symbol.symbol=symbol;
lex->yylval->symbol.str= (char*) tok;
lex->yylval->symbol.length=len;
+
+ if ((symbol->tok == NOT_SYM) &&
+ (lex->thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
+ return NOT2_SYM;
+ if ((symbol->tok == OR_OR_SYM) &&
+ !(lex->thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
+ return OR2_SYM;
+
return symbol->tok;
}
-#ifdef HAVE_DLOPEN
- udf_func *udf;
- if (function && using_udf_functions && (udf=find_udf((char*) tok, len)))
- {
- lex->safe_to_cache_query=0;
- lex->yylval->udf=udf;
- switch (udf->returns) {
- case STRING_RESULT:
- return (udf->type == UDFTYPE_FUNCTION) ? UDF_CHAR_FUNC : UDA_CHAR_SUM;
- case REAL_RESULT:
- return (udf->type == UDFTYPE_FUNCTION) ? UDF_FLOAT_FUNC : UDA_FLOAT_SUM;
- case INT_RESULT:
- return (udf->type == UDFTYPE_FUNCTION) ? UDF_INT_FUNC : UDA_INT_SUM;
- case ROW_RESULT:
- default:
- // This case should never be choosen
- DBUG_ASSERT(0);
- return 0;
- }
- }
-#endif
return 0;
}
@@ -290,7 +295,8 @@ static char *get_text(LEX *lex)
continue;
}
#endif
- if (c == '\\')
+ if (c == '\\' &&
+ !(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
{ // Escaped character
found_escape=1;
if (lex->ptr == lex->end_of_query)
@@ -351,7 +357,9 @@ static char *get_text(LEX *lex)
continue;
}
#endif
- if (!found_escape && *str == '\\' && str+1 != end)
+ if (!found_escape &&
+ !(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
+ *str == '\\' && str+1 != end)
{
switch(*++str) {
case 'n':
@@ -455,12 +463,12 @@ static inline uint int_token(const char *str,uint length)
else if (length < signed_longlong_len)
return LONG_NUM;
else if (length > signed_longlong_len)
- return REAL_NUM;
+ return DECIMAL_NUM;
else
{
cmp=signed_longlong_str+1;
smaller=LONG_NUM; // If <= signed_longlong_str
- bigger=REAL_NUM;
+ bigger=DECIMAL_NUM;
}
}
else
@@ -476,10 +484,10 @@ static inline uint int_token(const char *str,uint length)
else if (length > longlong_len)
{
if (length > unsigned_longlong_len)
- return REAL_NUM;
+ return DECIMAL_NUM;
cmp=unsigned_longlong_str;
smaller=ULONGLONG_NUM;
- bigger=REAL_NUM;
+ bigger=DECIMAL_NUM;
}
else
{
@@ -513,6 +521,10 @@ int yylex(void *arg, void *yythd)
uchar *ident_map= cs->ident_map;
lex->yylval=yylval; // The global state
+
+ lex->tok_end_prev= lex->tok_end;
+ lex->tok_start_prev= lex->tok_start;
+
lex->tok_start=lex->tok_end=lex->ptr;
state=lex->next_state;
lex->next_state=MY_LEX_OPERATOR_OR_IDENT;
@@ -560,8 +572,7 @@ int yylex(void *arg, void *yythd)
its value in a query for the binlog, the query must stay
grammatically correct.
*/
- else if (c == '?' && ((THD*) yythd)->command == COM_PREPARE &&
- !ident_map[yyPeek()])
+ else if (c == '?' && lex->stmt_prepare_mode && !ident_map[yyPeek()])
return(PARAM_MARKER);
return((int) c);
@@ -591,8 +602,12 @@ int yylex(void *arg, void *yythd)
state= MY_LEX_HEX_NUMBER;
break;
}
- /* Fall through */
- case MY_LEX_IDENT_OR_BIN: // TODO: Add binary string handling
+ case MY_LEX_IDENT_OR_BIN:
+ if (yyPeek() == '\'')
+ { // Found b'bin-number'
+ state= MY_LEX_BIN_NUMBER;
+ break;
+ }
case MY_LEX_IDENT:
uchar *start;
#if defined(USE_MB) && defined(USE_MB_IDENT)
@@ -713,6 +728,20 @@ int yylex(void *arg, void *yythd)
}
yyUnget();
}
+ else if (c == 'b' && (lex->ptr - lex->tok_start) == 2 &&
+ lex->tok_start[0] == '0' )
+ { // b'bin-number'
+ while (my_isxdigit(cs,(c = yyGet()))) ;
+ if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c])
+ {
+ yylval->lex_str= get_token(lex, yyLength());
+ yylval->lex_str.str+= 2; // Skip 0x
+ yylval->lex_str.length-= 2;
+ lex->yytoklen-= 2;
+ return (BIN_NUM);
+ }
+ yyUnget();
+ }
// fall through
case MY_LEX_IDENT_START: // We come here after '.'
result_state= IDENT;
@@ -808,7 +837,7 @@ int yylex(void *arg, void *yythd)
return(FLOAT_NUM);
}
yylval->lex_str=get_token(lex,yyLength());
- return(REAL_NUM);
+ return(DECIMAL_NUM);
case MY_LEX_HEX_NUMBER: // Found x'hexstring'
yyGet(); // Skip '
@@ -825,6 +854,19 @@ int yylex(void *arg, void *yythd)
lex->yytoklen-=3;
return (HEX_NUM);
+ case MY_LEX_BIN_NUMBER: // Found b'bin-string'
+ yyGet(); // Skip '
+ while ((c= yyGet()) == '0' || c == '1');
+ length= (lex->ptr - lex->tok_start); // Length of bin-num + 3
+ if (c != '\'')
+ return(ABORT_SYM); // Illegal hex constant
+ yyGet(); // get_token makes an unget
+ yylval->lex_str= get_token(lex, length);
+ yylval->lex_str.str+= 2; // Skip b'
+ yylval->lex_str.length-= 3; // Don't count b' and last '
+ lex->yytoklen-= 3;
+ return (BIN_NUM);
+
case MY_LEX_CMP_OP: // Incomplete comparison operator
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
@@ -942,16 +984,15 @@ int yylex(void *arg, void *yythd)
{
THD* thd= (THD*)yythd;
if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) &&
- (thd->command != COM_PREPARE))
+ !lex->stmt_prepare_mode)
{
- lex->safe_to_cache_query=0;
- lex->found_colon=(char*)lex->ptr;
- thd->server_status |= SERVER_MORE_RESULTS_EXISTS;
- lex->next_state=MY_LEX_END;
- return(END_OF_INPUT);
+ lex->safe_to_cache_query= 0;
+ lex->found_semicolon=(char*) lex->ptr;
+ thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
+ lex->next_state= MY_LEX_END;
+ return (END_OF_INPUT);
}
- else
- state=MY_LEX_CHAR; // Return ';'
+ state= MY_LEX_CHAR; // Return ';'
break;
}
/* fall true */
@@ -1065,31 +1106,45 @@ void st_select_lex_unit::init_query()
cleaned= 0;
item_list.empty();
describe= 0;
+ found_rows_for_union= 0;
}
void st_select_lex::init_query()
{
st_select_lex_node::init_query();
table_list.empty();
+ top_join_list.empty();
+ join_list= &top_join_list;
+ embedding= leaf_tables= 0;
item_list.empty();
join= 0;
- where= 0;
+ having= where= prep_where= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
- resolve_mode= NOMATTER_MODE;
+ context.select_lex= this;
+ context.init();
+ /*
+ Add the name resolution context of the current (sub)query to the
+ stack of contexts for the whole query.
+ */
+ parent_lex->push_context(&context);
cond_count= with_wild= 0;
+ conds_processed_with_permanent_arena= 0;
ref_pointer_array= 0;
select_n_having_items= 0;
- prep_where= 0;
subquery_in_having= explicit_limit= 0;
+ first_execution= 1;
+ first_cond_optimization= 1;
parsing_place= NO_MATTER;
+ exclude_from_table_unique_test= no_wrap_view_item= FALSE;
+ link_next= 0;
}
void st_select_lex::init_select()
{
st_select_lex_node::init_select();
group_list.empty();
- type= db= db1= table1= db2= table2= 0;
+ type= db= 0;
having= 0;
use_index_ptr= ignore_index_ptr= 0;
table_join_options= 0;
@@ -1106,8 +1161,9 @@ void st_select_lex::init_select()
order_list.elements= 0;
order_list.first= 0;
order_list.next= (byte**) &order_list.first;
- select_limit= HA_POS_ERROR;
- offset_limit= 0;
+ /* Set limit and offset to default values */
+ select_limit= 0; /* denotes the default limit = HA_POS_ERROR */
+ offset_limit= 0; /* denotes the default offset = 0 */
with_sum_func= 0;
}
@@ -1331,160 +1387,17 @@ ulong st_select_lex_node::get_table_join_options()
*/
bool st_select_lex::test_limit()
{
- if (select_limit != HA_POS_ERROR)
+ if (select_limit != 0)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- "LIMIT & IN/ALL/ANY/SOME subquery");
+ "LIMIT & IN/ALL/ANY/SOME subquery");
return(1);
}
- // We need only 1 row to determinate existence
- select_limit= 1;
// no sense in ORDER BY without LIMIT
order_list.empty();
return(0);
}
-/*
- Interface method of table list creation for query
-
- SYNOPSIS
- st_select_lex_unit::create_total_list()
- thd THD pointer
- result pointer on result list of tables pointer
- check_derived force derived table chacking (used for creating
- table list for derived query)
- DESCRIPTION
- This is used for UNION & subselect to create a new table list of all used
- tables.
- The table_list->table entry in all used tables are set to point
- to the entries in this list.
-
- RETURN
- 0 - OK
- !0 - error
-*/
-bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
- TABLE_LIST **result_arg)
-{
- *result_arg= 0;
- if (!(res= create_total_list_n_last_return(thd_arg, lex, &result_arg)))
- {
- /*
- If time zone tables were used implicitly in statement we should add
- them to global table list.
- */
- if (lex->time_zone_tables_used)
- {
- /*
- Altough we are modifying lex data, it won't raise any problem in
- case when this lex belongs to some prepared statement or stored
- procedure: such modification does not change any invariants imposed
- by requirement to reuse the same lex for multiple executions.
- */
- if ((lex->time_zone_tables_used= my_tz_get_table_list(thd)) !=
- &fake_time_zone_tables_list)
- {
- *result_arg= lex->time_zone_tables_used;
- }
- else
- {
- send_error(thd, 0);
- res= 1;
- }
- }
- }
- return res;
-}
-
-/*
- Table list creation for query
-
- SYNOPSIS
- st_select_lex_unit::create_total_list()
- thd THD pointer
- lex pointer on LEX stricture
- result pointer on pointer on result list of tables pointer
-
- DESCRIPTION
- This is used for UNION & subselect to create a new table list of all used
- tables.
- The table_list->table_list in all tables of global list are set to point
- to the local SELECT_LEX entries.
-
- RETURN
- 0 - OK
- !0 - error
-*/
-bool st_select_lex_unit::
-create_total_list_n_last_return(THD *thd_arg,
- st_lex *lex,
- TABLE_LIST ***result_arg)
-{
- TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
- TABLE_LIST **new_table_list= *result_arg, *aux;
- SELECT_LEX *sl= (SELECT_LEX*)slave;
-
- /*
- iterate all inner selects + fake_select (if exists),
- fake_select->next_select() always is 0
- */
- for (;
- sl;
- sl= (sl->next_select() ?
- sl->next_select() :
- (sl == fake_select_lex ?
- 0 :
- fake_select_lex)))
- {
- // check usage of ORDER BY in union
- if (sl->order_list.first && sl->next_select() && !sl->braces &&
- sl->linkage != GLOBAL_OPTIONS_TYPE)
- {
- net_printf(thd_arg,ER_WRONG_USAGE,"UNION","ORDER BY");
- return 1;
- }
-
- for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
- inner;
- inner= inner->next_unit())
- {
- if (inner->create_total_list_n_last_return(thd, lex,
- &slave_list_last))
- return 1;
- }
-
- if ((aux= (TABLE_LIST*) sl->table_list.first))
- {
- TABLE_LIST *next_table;
- for (; aux; aux= next_table)
- {
- TABLE_LIST *cursor;
- next_table= aux->next;
- /* Add to the total table list */
- if (!(cursor= (TABLE_LIST *) thd->memdup((char*) aux,
- sizeof(*aux))))
- {
- send_error(thd,0);
- return 1;
- }
- *new_table_list= cursor;
- cursor->table_list= aux;
- new_table_list= &cursor->next;
- *new_table_list= 0; // end result list
- aux->table_list= cursor;
- }
- }
- }
-
- if (slave_list_first)
- {
- *new_table_list= slave_list_first;
- new_table_list= slave_list_last;
- }
- *result_arg= new_table_list;
- return 0;
-}
-
st_select_lex_unit* st_select_lex_unit::master_unit()
{
@@ -1506,7 +1419,9 @@ bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
{
- return item_list.push_back(item);
+ DBUG_ENTER("st_select_lex::add_item_to_list");
+ DBUG_PRINT("info", ("Item: %p", item));
+ DBUG_RETURN(item_list.push_back(item));
}
@@ -1592,95 +1507,27 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
We have to create array in prepared statement memory if it is
prepared statement
*/
- Item_arena *arena= thd->current_arena;
- return (ref_pointer_array=
- (Item **)arena->alloc(sizeof(Item*) *
- (item_list.elements +
- select_n_having_items +
- order_group_num)* 5)) == 0;
-}
-
-
-/*
- Find db.table which will be updated in this unit
-
- SYNOPSIS
- st_select_lex_unit::check_updateable()
- db - data base name
- table - real table name
-
- RETURN
- 1 - found
- 0 - OK (table did not found)
-*/
-
-bool st_select_lex_unit::check_updateable(char *db, char *table)
-{
- for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
- if (sl->check_updateable(db, table))
- return 1;
- return 0;
-}
-
-
-/*
- Find db.table which will be updated in this select and
- underlying ones (except derived tables)
-
- SYNOPSIS
- st_select_lex::check_updateable()
- db - data base name
- table - real table name
-
- RETURN
- 1 - found
- 0 - OK (table did not found)
-*/
-
-bool st_select_lex::check_updateable(char *db, char *table)
-{
- if (find_real_table_in_list(get_table_list(), db, table))
- return 1;
-
- return check_updateable_in_subqueries(db, table);
-}
-
-/*
- Find db.table which will be updated in underlying subqueries
-
- SYNOPSIS
- st_select_lex::check_updateable_in_subqueries()
- db - data base name
- table - real table name
-
- RETURN
- 1 - found
- 0 - OK (table did not found)
-*/
-
-bool st_select_lex::check_updateable_in_subqueries(char *db, char *table)
-{
- for (SELECT_LEX_UNIT *un= first_inner_unit();
- un;
- un= un->next_unit())
- {
- if (un->first_select()->linkage != DERIVED_TABLE_TYPE &&
- un->check_updateable(db, table))
- return 1;
- }
- return 0;
+ Query_arena *arena= thd->stmt_arena;
+ return (ref_pointer_array=
+ (Item **)arena->alloc(sizeof(Item*) *
+ (item_list.elements +
+ select_n_having_items +
+ order_group_num)* 5)) == 0;
}
void st_select_lex_unit::print(String *str)
{
+ bool union_all= !union_distinct;
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
if (sl != first_select())
{
str->append(" union ", 7);
- if (!union_distinct)
+ if (union_all)
str->append("all ", 4);
+ else if (union_distinct == sl)
+ union_all= TRUE;
}
if (sl->braces)
str->append('(');
@@ -1706,7 +1553,14 @@ void st_select_lex::print_order(String *str, ORDER *order)
{
for (; order; order= order->next)
{
- (*order->item)->print(str);
+ if (order->counter_used)
+ {
+ char buffer[20];
+ uint length= my_snprintf(buffer, 20, "%d", order->counter);
+ str->append(buffer, length);
+ }
+ else
+ (*order->item)->print(str);
if (!order->asc)
str->append(" desc", 5);
if (order->next)
@@ -1717,96 +1571,510 @@ void st_select_lex::print_order(String *str, ORDER *order)
void st_select_lex::print_limit(THD *thd, String *str)
{
+ SELECT_LEX_UNIT *unit= master_unit();
+ Item_subselect *item= unit->item;
+ if (item && unit->global_parameters == this &&
+ (item->substype() == Item_subselect::EXISTS_SUBS ||
+ item->substype() == Item_subselect::IN_SUBS ||
+ item->substype() == Item_subselect::ALL_SUBS))
+ {
+ DBUG_ASSERT(!item->fixed ||
+ select_limit->val_int() == LL(1) && offset_limit == 0);
+ return;
+ }
+
if (explicit_limit)
{
str->append(" limit ", 7);
- char buff[20];
- // latin1 is good enough for numbers
- String st(buff, sizeof(buff), &my_charset_latin1);
- st.set((ulonglong)select_limit, &my_charset_latin1);
- str->append(st);
if (offset_limit)
{
+ offset_limit->print(str);
str->append(',');
- st.set((ulonglong)select_limit, &my_charset_latin1);
- str->append(st);
}
+ select_limit->print(str);
}
}
+/*
+ Initialize LEX object.
+
+ SYNOPSIS
+ st_lex::st_lex()
+
+ NOTE
+ LEX object initialized with this constructor can be used as part of
+ THD object for which one can safely call open_tables(), lock_tables()
+ and close_thread_tables() functions. But it is not yet ready for
+ statement parsing. On should use lex_start() function to prepare LEX
+ for this.
+*/
+
st_lex::st_lex()
- :result(0)
-{}
+ :result(0), sql_command(SQLCOM_END), query_tables_own_last(0)
+{
+ hash_init(&sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0);
+ sroutines_list.empty();
+ sroutines_list_own_last= sroutines_list.next;
+ sroutines_list_own_elements= 0;
+}
/*
- Unlink first table from global table list and first table from outer select
- list (lex->select_lex)
+ Check whether the merging algorithm can be used on this VIEW
SYNOPSIS
- unlink_first_table()
- tables Global table list
- global_first Save first global table here
- local_first Save first local table here
+ st_lex::can_be_merged()
- NOTES
- This function assumes that outer select list is non-empty.
+ DESCRIPTION
+ We can apply merge algorithm if it is single SELECT view with
+ subqueries only in WHERE clause (we do not count SELECTs of underlying
+ views, and second level subqueries) and we have not grpouping, ordering,
+ HAVING clause, aggregate functions, DISTINCT clause, LIMIT clause and
+ several underlying tables.
RETURN
- global list without first table
+ FALSE - only temporary table algorithm can be used
+ TRUE - merge algorithm can be used
+*/
+
+bool st_lex::can_be_merged()
+{
+ // TODO: do not forget implement case when select_lex.table_list.elements==0
+
+ /* find non VIEW subqueries/unions */
+ bool selects_allow_merge= select_lex.next_select() == 0;
+ if (selects_allow_merge)
+ {
+ for (SELECT_LEX_UNIT *unit= select_lex.first_inner_unit();
+ unit;
+ unit= unit->next_unit())
+ {
+ if (unit->first_select()->parent_lex == this &&
+ (unit->item == 0 || unit->item->place() != IN_WHERE))
+ {
+ selects_allow_merge= 0;
+ break;
+ }
+ }
+ }
+
+ return (selects_allow_merge &&
+ select_lex.order_list.elements == 0 &&
+ select_lex.group_list.elements == 0 &&
+ select_lex.having == 0 &&
+ select_lex.with_sum_func == 0 &&
+ select_lex.table_list.elements >= 1 &&
+ !(select_lex.options & SELECT_DISTINCT) &&
+ select_lex.select_limit == 0);
+}
+
+
+/*
+ check if command can use VIEW with MERGE algorithm (for top VIEWs)
+
+ SYNOPSIS
+ st_lex::can_use_merged()
+
+ DESCRIPTION
+ Only listed here commands can use merge algorithm in top level
+ SELECT_LEX (for subqueries will be used merge algorithm if
+ st_lex::can_not_use_merged() is not TRUE).
+ RETURN
+ FALSE - command can't use merged VIEWs
+ TRUE - VIEWs with MERGE algorithms can be used
+*/
+
+bool st_lex::can_use_merged()
+{
+ switch (sql_command)
+ {
+ case SQLCOM_SELECT:
+ case SQLCOM_CREATE_TABLE:
+ case SQLCOM_UPDATE:
+ case SQLCOM_UPDATE_MULTI:
+ case SQLCOM_DELETE:
+ case SQLCOM_DELETE_MULTI:
+ case SQLCOM_INSERT:
+ case SQLCOM_INSERT_SELECT:
+ case SQLCOM_REPLACE:
+ case SQLCOM_REPLACE_SELECT:
+ case SQLCOM_LOAD:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/*
+ Check if command can't use merged views in any part of command
+
+ SYNOPSIS
+ st_lex::can_not_use_merged()
+
+ DESCRIPTION
+ Temporary table algorithm will be used on all SELECT levels for queries
+ listed here (see also st_lex::can_use_merged()).
+
+ RETURN
+ FALSE - command can't use merged VIEWs
+ TRUE - VIEWs with MERGE algorithms can be used
*/
-TABLE_LIST *st_lex::unlink_first_table(TABLE_LIST *tables,
- TABLE_LIST **global_first,
- TABLE_LIST **local_first)
+
+bool st_lex::can_not_use_merged()
{
- DBUG_ASSERT(select_lex.table_list.first != 0);
+ switch (sql_command)
+ {
+ case SQLCOM_CREATE_VIEW:
+ case SQLCOM_SHOW_CREATE:
/*
- Save pointers to first elements of global table list and list
- of tables used in outer select. It does not harm if these lists
- are the same.
+ SQLCOM_SHOW_FIELDS is necessary to make
+ information schema tables working correctly with views.
+ see get_schema_tables_result function
*/
- *global_first= tables;
- *local_first= (TABLE_LIST*)select_lex.table_list.first;
-
- /* Exclude first elements from these lists */
- select_lex.table_list.first= (byte*) (*local_first)->next;
- tables= tables->next;
- (*global_first)->next= 0;
- return tables;
+ case SQLCOM_SHOW_FIELDS:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/*
+ Detect that we need only table structure of derived table/view
+
+ SYNOPSIS
+ only_view_structure()
+
+ RETURN
+ TRUE yes, we need only structure
+ FALSE no, we need data
+*/
+
+bool st_lex::only_view_structure()
+{
+ switch (sql_command) {
+ case SQLCOM_SHOW_CREATE:
+ case SQLCOM_SHOW_TABLES:
+ case SQLCOM_SHOW_FIELDS:
+ case SQLCOM_REVOKE_ALL:
+ case SQLCOM_REVOKE:
+ case SQLCOM_GRANT:
+ case SQLCOM_CREATE_VIEW:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+
+/*
+ Should Items_ident be printed correctly
+
+ SYNOPSIS
+ need_correct_ident()
+
+ RETURN
+ TRUE yes, we need only structure
+ FALSE no, we need data
+*/
+
+
+bool st_lex::need_correct_ident()
+{
+ switch(sql_command)
+ {
+ case SQLCOM_SHOW_CREATE:
+ case SQLCOM_SHOW_TABLES:
+ case SQLCOM_CREATE_VIEW:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/*
+ Get effective type of CHECK OPTION for given view
+
+ SYNOPSIS
+ get_effective_with_check()
+ view given view
+
+ NOTE
+ It have not sense to set CHECK OPTION for SELECT satement or subqueries,
+ so we do not.
+
+ RETURN
+ VIEW_CHECK_NONE no need CHECK OPTION
+ VIEW_CHECK_LOCAL CHECK OPTION LOCAL
+ VIEW_CHECK_CASCADED CHECK OPTION CASCADED
+*/
+
+uint8 st_lex::get_effective_with_check(st_table_list *view)
+{
+ if (view->select_lex->master_unit() == &unit &&
+ which_check_option_applicable())
+ return (uint8)view->with_check;
+ return VIEW_CHECK_NONE;
}
/*
- Link table which was unlinked with unlink_first_table() back.
+ initialize limit counters
+
+ SYNOPSIS
+ st_select_lex_unit::set_limit()
+ values - SELECT_LEX with initial values for counters
+*/
+
+void st_select_lex_unit::set_limit(SELECT_LEX *sl)
+{
+ ha_rows select_limit_val;
+
+ DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare());
+ select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() :
+ HA_POS_ERROR);
+ offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() :
+ ULL(0));
+ select_limit_cnt= select_limit_val + offset_limit_cnt;
+ if (select_limit_cnt < select_limit_val)
+ select_limit_cnt= HA_POS_ERROR; // no limit
+}
+
+
+/*
+ Unlink the first table from the global table list and the first table from
+ outer select (lex->select_lex) local list
+
+ SYNOPSIS
+ unlink_first_table()
+ link_to_local Set to 1 if caller should link this table to local list
+
+ NOTES
+ We assume that first tables in both lists is the same table or the local
+ list is empty.
+
+ RETURN
+ 0 If 'query_tables' == 0
+ unlinked table
+ In this case link_to_local is set.
+
+*/
+TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
+{
+ TABLE_LIST *first;
+ if ((first= query_tables))
+ {
+ /*
+ Exclude from global table list
+ */
+ if ((query_tables= query_tables->next_global))
+ query_tables->prev_global= &query_tables;
+ else
+ query_tables_last= &query_tables;
+ first->next_global= 0;
+
+ /*
+ and from local list if it is not empty
+ */
+ if ((*link_to_local= test(select_lex.table_list.first)))
+ {
+ select_lex.context.table_list=
+ select_lex.context.first_name_resolution_table= first->next_local;
+ select_lex.table_list.first= (byte*) (first->next_local);
+ select_lex.table_list.elements--; //safety
+ first->next_local= 0;
+ /*
+ Ensure that the global list has the same first table as the local
+ list.
+ */
+ first_lists_tables_same();
+ }
+ }
+ return first;
+}
+
+
+/*
+ Bring first local table of first most outer select to first place in global
+ table list
+
+ SYNOPSYS
+ st_lex::first_lists_tables_same()
+
+ NOTES
+ In many cases (for example, usual INSERT/DELETE/...) the first table of
+ main SELECT_LEX have special meaning => check that it is the first table
+ in global list and re-link to be first in the global list if it is
+ necessary. We need such re-linking only for queries with sub-queries in
+ the select list, as only in this case tables of sub-queries will go to
+ the global list first.
+*/
+
+void st_lex::first_lists_tables_same()
+{
+ TABLE_LIST *first_table= (TABLE_LIST*) select_lex.table_list.first;
+ if (query_tables != first_table && first_table != 0)
+ {
+ TABLE_LIST *next;
+ if (query_tables_last == &first_table->next_global)
+ query_tables_last= first_table->prev_global;
+
+ if ((next= *first_table->prev_global= first_table->next_global))
+ next->prev_global= first_table->prev_global;
+ /* include in new place */
+ first_table->next_global= query_tables;
+ /*
+ We are sure that query_tables is not 0, because first_table was not
+ first table in the global list => we can use
+ query_tables->prev_global without check of query_tables
+ */
+ query_tables->prev_global= &first_table->next_global;
+ first_table->prev_global= &query_tables;
+ query_tables= first_table;
+ }
+}
+
+
+/*
+ Add implicitly used time zone description tables to global table list
+ (if needed).
+
+ SYNOPSYS
+ st_lex::add_time_zone_tables_to_query_tables()
+ thd - pointer to current thread context
+
+ RETURN VALUE
+ TRUE - error
+ FALSE - success
+*/
+
+bool st_lex::add_time_zone_tables_to_query_tables(THD *thd)
+{
+ /* We should not add these tables twice */
+ if (!time_zone_tables_used)
+ {
+ time_zone_tables_used= my_tz_get_table_list(thd, &query_tables_last);
+ if (time_zone_tables_used == &fake_time_zone_tables_list)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ Link table back that was unlinked with unlink_first_table()
SYNOPSIS
link_first_table_back()
- tables Global table list
- global_first Saved first global table
- local_first Saved first local table
+ link_to_local do we need link this table to local
RETURN
global list
*/
-TABLE_LIST *st_lex::link_first_table_back(TABLE_LIST *tables,
- TABLE_LIST *global_first,
- TABLE_LIST *local_first)
+
+void st_lex::link_first_table_back(TABLE_LIST *first,
+ bool link_to_local)
{
- global_first->next= tables;
- select_lex.table_list.first= (byte*) local_first;
- return global_first;
+ if (first)
+ {
+ if ((first->next_global= query_tables))
+ query_tables->prev_global= &first->next_global;
+ else
+ query_tables_last= &first->next_global;
+ query_tables= first;
+
+ if (link_to_local)
+ {
+ first->next_local= (TABLE_LIST*) select_lex.table_list.first;
+ select_lex.context.table_list= first;
+ select_lex.table_list.first= (byte*) first;
+ select_lex.table_list.elements++; //safety
+ }
+ }
+}
+
+
+
+/*
+ cleanup lex for case when we open table by table for processing
+
+ SYNOPSIS
+ st_lex::cleanup_after_one_table_open()
+*/
+
+void st_lex::cleanup_after_one_table_open()
+{
+ /*
+ thd->lex->derived_tables & additional units may be set if we open
+ a view. It is necessary to clear thd->lex->derived_tables flag
+ to prevent processing of derived tables during next open_and_lock_tables
+ if next table is a real table and cleanup & remove underlying units
+ NOTE: all units will be connected to thd->lex->select_lex, because we
+ have not UNION on most upper level.
+ */
+ if (all_selects_list != &select_lex)
+ {
+ derived_tables= 0;
+ /* cleunup underlying units (units of VIEW) */
+ for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit();
+ un;
+ un= un->next_unit())
+ un->cleanup();
+ /* reduce all selects list to default state */
+ all_selects_list= &select_lex;
+ /* remove underlying units (units of VIEW) subtree */
+ select_lex.cut_subtree();
+ }
+ time_zone_tables_used= 0;
+ if (sroutines.records)
+ my_hash_reset(&sroutines);
+ sroutines_list.empty();
+ sroutines_list_own_last= sroutines_list.next;
+ sroutines_list_own_elements= 0;
}
+
/*
- There are st_select_lex::add_table_to_list &
+ fix some structures at the end of preparation
+
+ SYNOPSIS
+ st_select_lex::fix_prepare_information
+ thd thread handler
+ conds pointer on conditions which will be used for execution statement
+*/
+
+void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
+{
+ if (!thd->stmt_arena->is_conventional() && first_execution)
+ {
+ first_execution= 0;
+ if (*conds)
+ {
+ prep_where= *conds;
+ *conds= where= prep_where->copy_andor_structure(thd);
+ }
+ for (TABLE_LIST *tbl= (TABLE_LIST *)table_list.first;
+ tbl;
+ tbl= tbl->next_local)
+ {
+ if (tbl->on_expr)
+ {
+ tbl->prep_on_expr= tbl->on_expr;
+ tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
+ }
+ }
+ }
+}
+
+/*
+ There are st_select_lex::add_table_to_list &
st_select_lex::set_lock_for_tables are in sql_parse.cc
- st_select_lex::print is in sql_select.h
+ st_select_lex::print is in sql_select.cc
st_select_lex_unit::prepare, st_select_lex_unit::exec,
st_select_lex_unit::cleanup, st_select_lex_unit::reinit_exec_mechanism,
st_select_lex_unit::change_result
are in sql_union.cc
*/
+
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 07b5c9d8edf..76ea7f5c270 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -21,6 +21,10 @@
class Table_ident;
class sql_exchange;
class LEX_COLUMN;
+class sp_head;
+class sp_name;
+class sp_instr;
+class sp_pcontext;
/*
The following hack is needed because mysql_yacc.cc does not define
@@ -49,21 +53,22 @@ enum enum_sql_command {
SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
- SQLCOM_SHOW_INNODB_STATUS,
+ SQLCOM_SHOW_INNODB_STATUS, SQLCOM_SHOW_MUTEX_STATUS,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
- SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB,
+ SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
+ SQLCOM_SHOW_TRIGGERS,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT,
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
- SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
+ SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
- SQLCOM_COMMIT, SQLCOM_SAVEPOINT,
+ SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT,
SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
@@ -74,10 +79,19 @@ enum enum_sql_command {
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
- SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
-
+ SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER,
+ SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
+ SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL,
+ SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION,
+ SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC,
+ SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STATUS_FUNC,
SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE,
+ SQLCOM_CREATE_VIEW, SQLCOM_DROP_VIEW,
+ SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
+ SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
+ SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
/* This should be the last !!! */
+
SQLCOM_END
};
@@ -85,6 +99,47 @@ enum enum_sql_command {
#define DESCRIBE_NORMAL 1
#define DESCRIBE_EXTENDED 2
+enum enum_sp_suid_behaviour
+{
+ SP_IS_DEFAULT_SUID= 0,
+ SP_IS_NOT_SUID,
+ SP_IS_SUID
+};
+
+enum enum_sp_data_access
+{
+ SP_DEFAULT_ACCESS= 0,
+ SP_CONTAINS_SQL,
+ SP_NO_SQL,
+ SP_READS_SQL_DATA,
+ SP_MODIFIES_SQL_DATA
+};
+
+const LEX_STRING sp_data_access_name[]=
+{
+ { (char*) STRING_WITH_LEN("") },
+ { (char*) STRING_WITH_LEN("CONTAINS SQL") },
+ { (char*) STRING_WITH_LEN("NO SQL") },
+ { (char*) STRING_WITH_LEN("READS SQL DATA") },
+ { (char*) STRING_WITH_LEN("MODIFIES SQL DATA") }
+};
+
+#define DERIVED_SUBQUERY 1
+#define DERIVED_VIEW 2
+
+enum enum_view_create_mode
+{
+ VIEW_CREATE_NEW, // check that there are not such VIEW/table
+ VIEW_ALTER, // check that VIEW .frm with such name exists
+ VIEW_CREATE_OR_REPLACE // check only that there are not such table
+};
+
+enum enum_drop_mode
+{
+ DROP_DEFAULT, // mode is not specified
+ DROP_CASCADE, // CASCADE option
+ DROP_RESTRICT // RESTRICT option
+};
typedef List<Item> List_item;
@@ -250,7 +305,7 @@ protected:
*link_next, **link_prev; /* list of whole SELECT_LEX */
public:
- ulong options;
+ ulonglong options;
/*
result of this query can't be cached, bit field, can be :
UNCACHEABLE_DEPENDENT
@@ -270,7 +325,7 @@ public:
}
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
- static void operator delete(void *ptr,size_t size) {}
+ static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {}
virtual ~st_select_lex_node() {}
@@ -306,6 +361,8 @@ public:
friend class st_select_lex_unit;
friend bool mysql_new_select(struct st_lex *lex, bool move_down);
+ friend my_bool mysql_make_view (File_parser *parser,
+ TABLE_LIST *table);
private:
void fast_exclude();
};
@@ -315,7 +372,6 @@ typedef class st_select_lex_node SELECT_LEX_NODE;
SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group
SELECT_LEXs
*/
-struct st_lex;
class THD;
class select_result;
class JOIN;
@@ -328,8 +384,8 @@ protected:
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
- int res;
ulong found_rows_for_union;
+ bool res;
bool prepared, // prepare phase already performed for UNION (unit)
optimized, // optimize phase already performed for UNION (unit)
executed, // already executed
@@ -370,7 +426,6 @@ public:
Procedure *last_procedure; /* Pointer to procedure, if such exists */
void init_query();
- bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
st_select_lex_unit* master_unit();
st_select_lex* outer_select();
st_select_lex* first_select()
@@ -390,25 +445,23 @@ public:
void exclude_tree();
/* UNION methods */
- int prepare(THD *thd, select_result *result, ulong additional_options,
- const char *tmp_table_alias);
- int exec();
- int cleanup();
+ bool prepare(THD *thd, select_result *result, ulong additional_options,
+ const char *tmp_table_alias);
+ bool exec();
+ bool cleanup();
inline void unclean() { cleaned= 0; }
void reinit_exec_mechanism();
- bool check_updateable(char *db, char *table);
void print(String *str);
- ulong init_prepare_fake_select_lex(THD *thd);
- int change_result(select_subselect *result, select_subselect *old_result);
+ void init_prepare_fake_select_lex(THD *thd);
inline bool is_prepared() { return prepared; }
+ bool change_result(select_subselect *result, select_subselect *old_result);
+ void set_limit(st_select_lex *values);
+ void set_thd(THD *thd_arg) { thd= thd_arg; }
friend void lex_start(THD *thd, uchar *buf, uint length);
friend int subselect_union_engine::exec();
-private:
- bool create_total_list_n_last_return(THD *thd, st_lex *lex,
- TABLE_LIST ***result);
};
typedef class st_select_lex_unit SELECT_LEX_UNIT;
@@ -418,12 +471,17 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT;
class st_select_lex: public st_select_lex_node
{
public:
- char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
+ Name_resolution_context context;
+ char *db;
Item *where, *having; /* WHERE & HAVING clauses */
Item *prep_where; /* saved WHERE clause for prepared statement processing */
+ /* point on lex in which it was created, used in view subquery detection */
+ st_lex *parent_lex;
enum olap_type olap;
- SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
- List<Item> item_list; /* list of fields & expressions */
+ /* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */
+ SQL_LIST table_list;
+ SQL_LIST group_list; /* GROUP BY clause. */
+ List<Item> item_list; /* list of fields & expressions */
List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr;
/*
@@ -433,13 +491,22 @@ public:
List<Item_func_match> *ftfunc_list;
List<Item_func_match> ftfunc_list_alloc;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
- const char *type; /* type of select for EXPLAIN */
+ List<TABLE_LIST> top_join_list; /* join list of the top level */
+ List<TABLE_LIST> *join_list; /* list for the currently parsed join */
+ TABLE_LIST *embedding; /* table embedding to the above list */
+ /*
+ Beginning of the list of leaves in a FROM clause, where the leaves
+ inlcude all base tables including view tables. The tables are connected
+ by TABLE_LIST::next_leaf, so leaf_tables points to the left-most leaf.
+ */
+ TABLE_LIST *leaf_tables;
+ const char *type; /* type of select for EXPLAIN */
SQL_LIST order_list; /* ORDER clause */
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */
SQL_LIST *gorder_list;
- ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
+ Item *select_limit, *offset_limit; /* LIMIT clause parameters */
// Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array;
@@ -452,6 +519,11 @@ public:
uint cond_count; /* number of arguments of and/or/xor in where/having */
enum_parsing_place parsing_place; /* where we are parsing expression */
bool with_sum_func; /* sum function indicator */
+ /*
+ PS or SP cond natural joins was alredy processed with permanent
+ arena and all additional items which we need alredy stored in it
+ */
+ bool conds_processed_with_permanent_arena;
ulong table_join_options;
uint in_sum_expr;
@@ -467,27 +539,24 @@ public:
query processing end even if we use temporary table
*/
bool subquery_in_having;
-
- /*
- SELECT for SELECT command st_select_lex. Used to privent scaning
- item_list of non-SELECT st_select_lex (no sense find to finding
- reference in it (all should be in tables, it is dangerouse due
- to order of fix_fields calling for non-SELECTs commands (item list
- can be not fix_fieldsd)). This value will be assigned for
- primary select (sql_yac.yy) and for any subquery and
- UNION SELECT (sql_parse.cc mysql_new_select())
-
-
- INSERT for primary st_select_lex structure of simple INSERT/REPLACE
- (used for name resolution, see Item_fiels & Item_ref fix_fields,
- FALSE for INSERT/REPLACE ... SELECT, because it's
- st_select_lex->table_list will be preprocessed (first table removed)
- before passing to handle_select)
-
- NOMATTER for other
+ /*
+ This variable is required to ensure proper work of subqueries and
+ stored procedures. Generally, one should use the states of
+ Query_arena to determine if it's a statement prepare or first
+ execution of a stored procedure. However, in case when there was an
+ error during the first execution of a stored procedure, the SP body
+ is not expelled from the SP cache. Therefore, a deeply nested
+ subquery might be left unoptimized. So we need this per-subquery
+ variable to inidicate the optimization/execution state of every
+ subquery. Prepared statements work OK in that regard, as in
+ case of an error during prepare the PS is not created.
*/
- enum {NOMATTER_MODE, SELECT_MODE, INSERT_MODE} resolve_mode;
-
+ bool first_execution;
+ bool first_cond_optimization;
+ /* do not wrap view fields with Item_ref */
+ bool no_wrap_view_item;
+ /* exclude this select from check of unique_table() */
+ bool exclude_from_table_unique_test;
void init_query();
void init_select();
@@ -529,6 +598,11 @@ public:
List<String> *ignore_index= 0,
LEX_STRING *option= 0);
TABLE_LIST* get_table_list();
+ bool init_nested_join(THD *thd);
+ TABLE_LIST *end_nested_join(THD *thd);
+ TABLE_LIST *nest_last_join(THD *thd);
+ void add_joined_table(TABLE_LIST *table);
+ TABLE_LIST *convert_right_join();
List<Item>* get_item_list();
List<String>* get_use_index();
List<String>* get_ignore_index();
@@ -540,7 +614,13 @@ public:
order_list.first= 0;
order_list.next= (byte**) &order_list.first;
}
-
+ /*
+ This method created for reiniting LEX in mysql_admin_table() and can be
+ used only if you are going remove all SELECT_LEX & units except belonger
+ to LEX (LEX::unit & LEX::select, for other purposes there are
+ SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree
+ */
+ void cut_subtree() { slave= 0; }
bool test_limit();
friend void lex_start(THD *thd, uchar *buf, uint length);
@@ -551,11 +631,15 @@ public:
init_select();
}
bool setup_ref_array(THD *thd, uint order_group_num);
- bool check_updateable(char *db, char *table);
- bool check_updateable_in_subqueries(char *db, char *table);
void print(THD *thd, String *str);
static void print_order(String *str, ORDER *order);
void print_limit(THD *thd, String *str);
+ void fix_prepare_information(THD *thd, Item **conds);
+ /*
+ Destroy the used execution plan (JOIN) of this subtree (this
+ SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs).
+ */
+ bool cleanup();
};
typedef class st_select_lex SELECT_LEX;
@@ -567,6 +651,10 @@ typedef class st_select_lex SELECT_LEX;
#define ALTER_RENAME 32
#define ALTER_ORDER 64
#define ALTER_OPTIONS 128
+#define ALTER_CHANGE_COLUMN_DEFAULT 256
+#define ALTER_KEYS_ONOFF 512
+#define ALTER_CONVERT 1024
+#define ALTER_FORCE 2048
typedef struct st_alter_info
{
@@ -575,13 +663,32 @@ typedef struct st_alter_info
uint flags;
enum enum_enable_or_disable keys_onoff;
enum tablespace_op_type tablespace_op;
- bool is_simple;
st_alter_info(){clear();}
void clear(){keys_onoff= LEAVE_AS_IS;tablespace_op= NO_TABLESPACE_OP;}
void reset(){drop_list.empty();alter_list.empty();clear();}
} ALTER_INFO;
+struct st_sp_chistics
+{
+ LEX_STRING comment;
+ enum enum_sp_suid_behaviour suid;
+ bool detistic;
+ enum enum_sp_data_access daccess;
+};
+
+
+struct st_trg_chistics
+{
+ enum trg_action_time_type action_time;
+ enum trg_event_type event;
+};
+
+extern sys_var_long_ptr trg_new_row_fake_var;
+
+enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE,
+ XA_SUSPEND, XA_FOR_MIGRATE};
+
/* The state of the lex parsing. This is saved in the THD struct */
typedef struct st_lex
@@ -594,23 +701,40 @@ typedef struct st_lex
SELECT_LEX *current_select;
/* list of all SELECT_LEX */
SELECT_LEX *all_selects_list;
+ uchar *buf; /* The beginning of string, used by SPs */
uchar *ptr,*tok_start,*tok_end,*end_of_query;
+
+ /* The values of tok_start/tok_end as they were one call of yylex before */
+ uchar *tok_start_prev, *tok_end_prev;
+
char *length,*dec,*change,*name;
char *help_arg;
char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */
- time_t purge_time; /* For PURGE MASTER LOGS BEFORE */
char* x509_subject,*x509_issuer,*ssl_cipher;
- char* found_colon; /* For multi queries - next query */
+ char* found_semicolon; /* For multi queries - next query */
String *wild;
sql_exchange *exchange;
select_result *result;
Item *default_value, *on_update_value;
- LEX_STRING *comment, name_and_length;
+ LEX_STRING comment, ident;
LEX_USER *grant_user;
+ XID *xid;
gptr yacc_yyss,yacc_yyvs;
THD *thd;
CHARSET_INFO *charset;
+ TABLE_LIST *query_tables; /* global list of all tables in this query */
+ /*
+ last element next_global of previous list (used only for list building
+ during parsing and VIEW processing. This pointer could be invalid during
+ processing of information schema tables(see get_schema_tables_result
+ function)
+ */
+ TABLE_LIST **query_tables_last;
+ /* store original leaf_tables for INSERT SELECT and PS/SP */
+ TABLE_LIST *leaf_tables_insert;
+ st_lex_user *create_view_definer;
+ char *create_view_select_start;
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
@@ -623,53 +747,157 @@ typedef struct st_lex
List<List_item> many_values;
List<set_var_base> var_list;
List<Item_param> param_list;
+ List<LEX_STRING> view_list; // view list (list of field names in view)
+ /*
+ A stack of name resolution contexts for the query. This stack is used
+ at parse time to set local name resolution contexts for various parts
+ of a query. For example, in a JOIN ... ON (some_condition) clause the
+ Items in 'some_condition' must be resolved only against the operands
+ of the the join, and not against the whole clause. Similarly, Items in
+ subqueries should be resolved against the subqueries (and outer queries).
+ The stack is used in the following way: when the parser detects that
+ all Items in some clause need a local context, it creates a new context
+ and pushes it on the stack. All newly created Items always store the
+ top-most context in the stack. Once the parser leaves the clause that
+ required a local context, the parser pops the top-most context.
+ */
+ List<Name_resolution_context> context_stack;
+
SQL_LIST proc_list, auxilliary_table_list, save_list;
create_field *last_field;
- char *savepoint_name; // Transaction savepoint id
udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options
HA_CREATE_INFO create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
USER_RESOURCES mqh;
- ulong thread_id,type;
- enum_sql_command sql_command;
- thr_lock_type lock_option, multi_lock_option;
+ ulong type;
+ enum_sql_command sql_command, orig_sql_command;
+ thr_lock_type lock_option;
enum SSL_type ssl_type; /* defined in violite.h */
enum my_lex_states next_state;
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
enum enum_ha_read_modes ha_read_mode;
- enum ha_rkey_function ha_rkey_mode;
+ union {
+ enum ha_rkey_function ha_rkey_mode;
+ enum xa_option_words xa_opt;
+ };
enum enum_var_type option_type;
+ enum enum_view_create_mode create_view_mode;
+ enum enum_drop_mode drop_mode;
uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
uint slave_thd_opt, start_transaction_opt;
+ /*
+ In LEX representing update which were transformed to multi-update
+ stores total number of tables. For LEX representing multi-delete
+ holds number of tables from which we will delete records.
+ */
+ uint table_count;
uint8 describe;
+ uint8 derived_tables;
+ uint8 create_view_algorithm;
+ uint8 create_view_check;
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 tx_chain, tx_release;
+ /*
+ Special JOIN::prepare mode: changing of query is prohibited.
+ When creating a view, we need to just check its syntax omitting
+ any optimizations: afterwards definition of the view will be
+ reconstructed by means of ::print() methods and written to
+ to an .frm file. We need this definition to stay untouched.
+ */
+ bool view_prepare_mode;
+ /*
+ TRUE if we're parsing a prepared statement: in this mode
+ we should allow placeholders and disallow multistatements.
+ */
+ bool stmt_prepare_mode;
bool safe_to_cache_query;
bool subqueries, ignore;
+ bool variables_used;
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;
+ 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;
+ List<LEX_STRING> prepared_stmt_params;
/*
- If points to fake_time_zone_tables_list indicates that time zone
- tables are implicitly used by statement, also is used for holding
- list of those tables after they are opened.
+ Points to part of global table list which contains time zone tables
+ implicitly used by the statement.
*/
TABLE_LIST *time_zone_tables_used;
+ sp_head *sphead;
+ sp_name *spname;
+ bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
+ bool all_privileges;
+ sp_pcontext *spcont;
+ /* Set of stored routines called by statement. */
+ HASH sroutines;
+ /*
+ List linking elements of 'sroutines' set. Allows you to add new elements
+ to this set as you iterate through the list of existing elements.
+ 'sroutines_list_own_last' is pointer to ::next member of last element of
+ this list which represents routine which is explicitly used by query.
+ 'sroutines_list_own_elements' number of explicitly used routines.
+ We use these two members for restoring of 'sroutines_list' to the state
+ in which it was right after query parsing.
+ */
+ SQL_LIST sroutines_list;
+ byte **sroutines_list_own_last;
+ uint sroutines_list_own_elements;
+
+ st_sp_chistics sp_chistics;
+ bool only_view; /* used for SHOW CREATE TABLE/VIEW */
+ /*
+ field_list was created for view and should be removed before PS/SP
+ rexecuton
+ */
+ bool empty_field_list_on_rset;
+ /*
+ view created to be run from definer (standard behaviour)
+ */
+ bool create_view_suid;
+ /* Characterstics of trigger being created */
+ st_trg_chistics trg_chistics;
+ /*
+ List of all items (Item_trigger_field objects) representing fields in
+ old/new version of row in trigger. We use this list for checking whenever
+ all such fields are valid at trigger creation time and for binding these
+ fields to TABLE object at table open (altough for latter pointer to table
+ being opened is probably enough).
+ */
+ SQL_LIST trg_table_fields;
+
+ /*
+ If non-0 then indicates that query requires prelocking and points to
+ next_global member of last own element in query table list (i.e. last
+ table which was not added to it as part of preparation to prelocking).
+ 0 - indicates that this query does not need prelocking.
+ */
+ TABLE_LIST **query_tables_own_last;
+
+ /*
+ Pointers to part of LOAD DATA statement that should be rewritten
+ during replication ("LOCAL 'filename' REPLACE INTO" part).
+ */
+ uchar *fname_start, *fname_end;
+
st_lex();
+
+ virtual ~st_lex()
+ {
+ hash_free(&sroutines);
+ }
+
inline void uncacheable(uint8 cause)
{
safe_to_cache_query= 0;
@@ -689,20 +917,106 @@ typedef struct st_lex
un->uncacheable|= cause;
}
}
- TABLE_LIST *unlink_first_table(TABLE_LIST *tables,
- TABLE_LIST **global_first,
- TABLE_LIST **local_first);
- TABLE_LIST *link_first_table_back(TABLE_LIST *tables,
- TABLE_LIST *global_first,
- TABLE_LIST *local_first);
+ TABLE_LIST *unlink_first_table(bool *link_to_local);
+ void link_first_table_back(TABLE_LIST *first, bool link_to_local);
+ void first_lists_tables_same();
+ inline void add_to_query_tables(TABLE_LIST *table)
+ {
+ *(table->prev_global= query_tables_last)= table;
+ query_tables_last= &table->next_global;
+ }
+ bool add_time_zone_tables_to_query_tables(THD *thd);
+
+ bool can_be_merged();
+ bool can_use_merged();
+ bool can_not_use_merged();
+ bool only_view_structure();
+ bool need_correct_ident();
+ uint8 get_effective_with_check(st_table_list *view);
+ /*
+ Is this update command where 'WHITH CHECK OPTION' clause is important
+
+ SYNOPSIS
+ st_lex::which_check_option_applicable()
+
+ RETURN
+ TRUE have to take 'WHITH CHECK OPTION' clause into account
+ FALSE 'WHITH CHECK OPTION' clause do not need
+ */
+ inline bool which_check_option_applicable()
+ {
+ switch (sql_command) {
+ case SQLCOM_UPDATE:
+ case SQLCOM_UPDATE_MULTI:
+ case SQLCOM_INSERT:
+ case SQLCOM_INSERT_SELECT:
+ case SQLCOM_LOAD:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ }
+ inline bool requires_prelocking()
+ {
+ return test(query_tables_own_last);
+ }
+ inline void mark_as_requiring_prelocking(TABLE_LIST **tables_own_last)
+ {
+ query_tables_own_last= tables_own_last;
+ }
+ /* Return pointer to first not-own table in query-tables or 0 */
+ TABLE_LIST* first_not_own_table()
+ {
+ return ( query_tables_own_last ? *query_tables_own_last : 0);
+ }
+ void chop_off_not_own_tables()
+ {
+ if (query_tables_own_last)
+ {
+ *query_tables_own_last= 0;
+ query_tables_last= query_tables_own_last;
+ query_tables_own_last= 0;
+ }
+ }
+ void cleanup_after_one_table_open();
+
+ void push_context(Name_resolution_context *context)
+ {
+ context_stack.push_front(context);
+ }
+
+ void pop_context()
+ {
+ context_stack.pop();
+ }
+
+ Name_resolution_context *current_context()
+ {
+ return context_stack.head();
+ }
} LEX;
-extern TABLE_LIST fake_time_zone_tables_list;
+struct st_lex_local: public st_lex
+{
+ static void *operator new(size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ {
+ return (void*) alloc_root(mem_root, (uint) size);
+ }
+ static void operator delete(void *ptr,size_t size)
+ { TRASH(ptr, size); }
+ static void operator delete(void *ptr, MEM_ROOT *mem_root)
+ { /* Never called */ }
+};
-void lex_init(void);
-void lex_free(void);
-void lex_start(THD *thd, uchar *buf,uint length);
-void lex_end(LEX *lex);
+extern void lex_init(void);
+extern void lex_free(void);
+extern void lex_start(THD *thd, uchar *buf,uint length);
+extern void lex_end(LEX *lex);
+extern int yylex(void *arg, void *yythd);
extern pthread_key(LEX*,THR_LEX);
diff --git a/sql/sql_list.h b/sql/sql_list.h
index e799ecf3d6e..e4a34cc0aa1 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -21,12 +21,6 @@
/* mysql standard class memory allocator */
-#ifdef SAFEMALLOC
-#define TRASH(XX,YY) bfill((XX), (YY), 0x8F)
-#else
-#define TRASH(XX,YY) /* no-op */
-#endif
-
class Sql_alloc
{
public:
@@ -113,6 +107,16 @@ public:
}
return 1;
}
+ inline bool push_back(void *info, MEM_ROOT *mem_root)
+ {
+ if (((*last)=new (mem_root) list_node(info, &end_of_list)))
+ {
+ last= &(*last)->next;
+ elements++;
+ return 0;
+ }
+ return 1;
+ }
inline bool push_front(void *info)
{
list_node *node=new list_node(info,first);
@@ -129,32 +133,12 @@ public:
void remove(list_node **prev)
{
list_node *node=(*prev)->next;
- if (&(*prev)->next == last)
- {
- /*
- We're removing the last element from the list. Adjust "last" to point
- to the previous element.
- The other way to fix this would be to change this function to
- remove_next() and have base_list_iterator save ptr to previous node
- (one extra assignment in iterator++) but as the remove() of the last
- element isn't a common operation it's faster to just walk through the
- list from the beginning here.
- */
- list_node *cur= first;
- if (cur == *prev)
- {
- last= &first;
- }
- else
- {
- while (cur->next != *prev)
- cur= cur->next;
- last= &(cur->next);
- }
- }
+ if (!--elements)
+ last= &first;
+ else if (last == &(*prev)->next)
+ last= prev;
delete *prev;
*prev=node;
- elements--;
}
inline void concat(base_list *list)
{
@@ -174,6 +158,30 @@ public:
last= &first;
return tmp->info;
}
+ inline void disjoin(base_list *list)
+ {
+ list_node **prev= &first;
+ list_node *node= first;
+ list_node *list_first= list->first;
+ elements=0;
+ while (node && node != list_first)
+ {
+ prev= &node->next;
+ node= node->next;
+ elements++;
+ }
+ *prev= *last;
+ last= prev;
+ }
+ inline void prepand(base_list *list)
+ {
+ if (!list->is_empty())
+ {
+ *list->last= first;
+ first= list->first;
+ elements+= list->elements;
+ }
+ }
inline list_node* last_node() { return *last; }
inline list_node* first_node() { return first;}
inline void *head() { return first->info; }
@@ -328,10 +336,15 @@ public:
inline List() :base_list() {}
inline List(const List<T> &tmp) :base_list(tmp) {}
inline bool push_back(T *a) { return base_list::push_back(a); }
+ inline bool push_back(T *a, MEM_ROOT *mem_root)
+ { return base_list::push_back(a, mem_root); }
inline bool push_front(T *a) { return base_list::push_front(a); }
inline T* head() {return (T*) base_list::head(); }
inline T** head_ref() {return (T**) base_list::head_ref(); }
inline T* pop() {return (T*) base_list::pop(); }
+ inline void concat(List<T> *list) { base_list::concat(list); }
+ inline void disjoin(List<T> *list) { base_list::disjoin(list); }
+ inline void prepand(List<T> *list) { base_list::prepand(list); }
void delete_elements(void)
{
list_node *element,*next;
@@ -352,6 +365,8 @@ public:
inline T* operator++(int) { return (T*) base_list_iterator::next(); }
inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); }
inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
+ inline void rewind(void) { base_list_iterator::rewind(); }
+ inline void remove() { base_list_iterator::remove(); }
inline void after(T *a) { base_list_iterator::after(a); }
inline T** ref(void) { return (T**) base_list_iterator::ref(); }
};
@@ -411,9 +426,14 @@ struct ilink
template <class T> class I_List_iterator;
+/*
+ WARNING: copy constructor of this class does not create a usable
+ copy, as its members may point at each other.
+*/
+
class base_ilist
{
- public:
+public:
struct ilink *first,last;
inline void empty() { first= &last; last.prev= &first; }
base_ilist() { empty(); }
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 7b963c7ea31..fadc31f7aee 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -21,6 +21,8 @@
#include <my_dir.h>
#include <m_ctype.h>
#include "sql_repl.h"
+#include "sp_head.h"
+#include "sql_trigger.h"
class READ_INFO {
File file;
@@ -71,17 +73,47 @@ public:
void set_io_cache_arg(void* arg) { cache.arg = arg; }
};
-static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,
- List<Item> &fields, READ_INFO &read_info,
- ulong skip_lines);
-static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
- List<Item> &fields, READ_INFO &read_info,
- String &enclosed, ulong skip_lines);
-
-int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
- List<Item> &fields, enum enum_duplicates handle_duplicates,
- bool ignore,
- bool read_file_from_client,thr_lock_type lock_type)
+static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
+ List<Item> &fields_vars, List<Item> &set_fields,
+ List<Item> &set_values, READ_INFO &read_info,
+ ulong skip_lines,
+ bool ignore_check_option_errors);
+static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
+ List<Item> &fields_vars, List<Item> &set_fields,
+ List<Item> &set_values, READ_INFO &read_info,
+ String &enclosed, ulong skip_lines,
+ bool ignore_check_option_errors);
+static bool write_execute_load_query_log_event(THD *thd,
+ bool duplicates, bool ignore,
+ bool transactional_table);
+
+
+/*
+ Execute LOAD DATA query
+
+ SYNOPSYS
+ mysql_load()
+ thd - current thread
+ ex - sql_exchange object representing source file and its parsing rules
+ table_list - list of tables to which we are loading data
+ fields_vars - list of fields and variables to which we read
+ data from file
+ set_fields - list of fields mentioned in set clause
+ set_values - expressions to assign to fields in previous list
+ handle_duplicates - indicates whenever we should emit error or
+ replace row if we will meet duplicates.
+ ignore - - indicates whenever we should ignore duplicates
+ read_file_from_client - is this LOAD DATA LOCAL ?
+
+ RETURN VALUES
+ TRUE - error / FALSE - success
+*/
+
+bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
+ List<Item> &fields_vars, List<Item> &set_fields,
+ List<Item> &set_values,
+ enum enum_duplicates handle_duplicates, bool ignore,
+ bool read_file_from_client)
{
char name[FN_REFLEN];
File file;
@@ -89,6 +121,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
int error;
String *field_term=ex->field_term,*escaped=ex->escaped;
String *enclosed=ex->enclosed;
+ Item *unused_conds= 0;
bool is_fifo=0;
#ifndef EMBEDDED_LIBRARY
LOAD_FILE_INFO lf_info;
@@ -100,8 +133,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
loaded is located
*/
char *tdb= thd->db ? thd->db : db; // Result is never null
- bool transactional_table, log_delayed;
ulong skip_lines= ex->skip_lines;
+ bool transactional_table;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@@ -112,60 +145,116 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
MYF(0));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
/*
This needs to be done before external_lock
*/
ha_enable_transaction(thd, FALSE);
- if (!(table = open_ltable(thd,table_list,lock_type)))
- DBUG_RETURN(-1);
+ if (open_and_lock_tables(thd, table_list))
+ DBUG_RETURN(TRUE);
+ if (setup_tables(thd, &thd->lex->select_lex.context,
+ &thd->lex->select_lex.top_join_list,
+ table_list, &unused_conds,
+ &thd->lex->select_lex.leaf_tables, FALSE))
+ DBUG_RETURN(-1);
+ if (!table_list->table || // do not suport join view
+ !table_list->updatable || // and derived tables
+ check_key_in_view(thd, table_list))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD");
+ DBUG_RETURN(TRUE);
+ }
+ if (table_list->prepare_where(thd, 0, TRUE) ||
+ table_list->prepare_check_option(thd))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ Let us emit an error if we are loading data to table which is used
+ in subselect in SET clause like we do it for INSERT.
+
+ The main thing to fix to remove this restriction is to ensure that the
+ table is marked to be 'used for insert' in which case we should never
+ mark this table as as 'const table' (ie, one that has only one row).
+ */
+ if (unique_table(table_list, table_list->next_global))
+ {
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
+ DBUG_RETURN(TRUE);
+ }
+
+ table= table_list->table;
transactional_table= table->file->has_transactions();
- log_delayed= (transactional_table || table->tmp_table);
- if (!fields.elements)
+ if (!fields_vars.elements)
{
Field **field;
for (field=table->field; *field ; field++)
- fields.push_back(new Item_field(*field));
+ fields_vars.push_back(new Item_field(*field));
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+ /*
+ Let us also prepare SET clause, altough it is probably empty
+ in this case.
+ */
+ if (setup_fields(thd, 0, set_fields, 1, 0, 0) ||
+ setup_fields(thd, 0, set_values, 1, 0, 0))
+ DBUG_RETURN(TRUE);
}
else
{ // Part field list
- thd->dupp_field=0;
- if (setup_tables(table_list) ||
- setup_fields(thd, 0, table_list, fields, 1, 0, 0))
- DBUG_RETURN(-1);
- if (thd->dupp_field)
- {
- my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dupp_field->field_name);
- DBUG_RETURN(-1);
- }
+ /* TODO: use this conds for 'WITH CHECK OPTIONS' */
+ if (setup_fields(thd, 0, fields_vars, 1, 0, 0) ||
+ setup_fields(thd, 0, set_fields, 1, 0, 0) ||
+ check_that_all_fields_are_given_values(thd, table, table_list))
+ DBUG_RETURN(TRUE);
+ /*
+ Check whenever TIMESTAMP field with auto-set feature specified
+ explicitly.
+ */
+ if (table->timestamp_field &&
+ table->timestamp_field->query_id == thd->query_id)
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+ /*
+ Fix the expressions in SET clause. This should be done after
+ check_that_all_fields_are_given_values() and setting use_timestamp
+ since it may update query_id for some fields.
+ */
+ if (setup_fields(thd, 0, set_values, 1, 0, 0))
+ DBUG_RETURN(TRUE);
}
uint tot_length=0;
- bool use_blobs=0,use_timestamp=0;
- List_iterator_fast<Item> it(fields);
+ bool use_blobs= 0, use_vars= 0;
+ List_iterator_fast<Item> it(fields_vars);
+ Item *item;
- Item_field *field;
- while ((field=(Item_field*) it++))
+ while ((item= it++))
{
- if (field->field->flags & BLOB_FLAG)
+ if (item->type() == Item::FIELD_ITEM)
{
- use_blobs=1;
- tot_length+=256; // Will be extended if needed
+ Field *field= ((Item_field*)item)->field;
+ if (field->flags & BLOB_FLAG)
+ {
+ use_blobs= 1;
+ tot_length+= 256; // Will be extended if needed
+ }
+ else
+ tot_length+= field->field_length;
}
else
- tot_length+=field->field->field_length;
- if (!field_term->length() && !(field->field->flags & NOT_NULL_FLAG))
- field->field->set_notnull();
- if (field->field == table->timestamp_field)
- use_timestamp=1;
+ use_vars= 1;
}
if (use_blobs && !ex->line_term->length() && !field_term->length())
{
my_message(ER_BLOBS_AND_NO_TERMINATED,ER(ER_BLOBS_AND_NO_TERMINATED),
MYF(0));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
+ }
+ if (use_vars && !field_term->length() && !enclosed->length())
+ {
+ my_error(ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR, MYF(0));
+ DBUG_RETURN(TRUE);
}
/* We can't give an error in the middle when using LOCAL files */
@@ -197,7 +286,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
#if !defined(__WIN__) && !defined(OS2) && ! defined(__NETWARE__)
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(MY_WME)))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
// if we are not in slave thread, the file must be:
if (!thd->slave_thread &&
@@ -208,15 +297,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
((stat_info.st_mode & S_IFREG) == S_IFREG ||
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
{
- my_error(ER_TEXTFILE_NOT_READABLE,MYF(0),name);
- DBUG_RETURN(-1);
+ my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
+ DBUG_RETURN(TRUE);
}
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
is_fifo = 1;
#endif
}
if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
COPY_INFO info;
@@ -232,28 +321,20 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
if (file >= 0)
my_close(file,MYF(0)); // no files in net reading
- DBUG_RETURN(-1); // Can't allocate buffers
+ DBUG_RETURN(TRUE); // Can't allocate buffers
}
#ifndef EMBEDDED_LIBRARY
if (mysql_bin_log.is_open())
{
lf_info.thd = thd;
- lf_info.ex = ex;
- lf_info.db = db;
- lf_info.table_name = table_list->real_name;
- lf_info.fields = &fields;
- lf_info.ignore= ignore;
- lf_info.handle_dup = handle_duplicates;
lf_info.wrote_create_file = 0;
lf_info.last_pos_in_file = HA_POS_ERROR;
- lf_info.log_delayed= log_delayed;
+ lf_info.log_delayed= transactional_table;
read_info.set_io_cache_arg((void*) &lf_info);
}
#endif /*!EMBEDDED_LIBRARY*/
- restore_record(table,default_values);
-
thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
thd->cuted_fields=0L;
/* Skip lines if there is a line terminator */
@@ -270,8 +351,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (!(error=test(read_info.error)))
{
- if (use_timestamp)
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
table->next_number_field=table->found_next_number_field;
if (ignore ||
@@ -279,12 +358,21 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
table->file->start_bulk_insert((ha_rows) 0);
table->copy_blobs=1;
+
+ thd->no_trans_update= 0;
+ thd->abort_on_warning= (!ignore &&
+ (thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES)));
+
if (!field_term->length() && !enclosed->length())
- error=read_fixed_length(thd,info,table,fields,read_info,
- skip_lines);
+ error= read_fixed_length(thd, info, table_list, fields_vars,
+ set_fields, set_values, read_info,
+ skip_lines, ignore);
else
- error=read_sep_field(thd,info,table,fields,read_info,*enclosed,
- skip_lines);
+ error= read_sep_field(thd, info, table_list, fields_vars,
+ set_fields, set_values, read_info,
+ *enclosed, skip_lines, ignore);
if (table->file->end_bulk_insert())
error=1; /* purecov: inspected */
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
@@ -340,8 +428,14 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
/* If the file was not empty, wrote_create_file is true */
if (lf_info.wrote_create_file)
{
- Delete_file_log_event d(thd, db, log_delayed);
- mysql_bin_log.write(&d);
+ if ((info.copied || info.deleted) && !transactional_table)
+ write_execute_load_query_log_event(thd, handle_duplicates,
+ ignore, transactional_table);
+ else
+ {
+ Delete_file_log_event d(thd, db, transactional_table);
+ mysql_bin_log.write(&d);
+ }
}
}
#endif /*!EMBEDDED_LIBRARY*/
@@ -351,63 +445,77 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
send_ok(thd,info.copied+info.deleted,0L,name);
- // on the slave thd->query is never initialized
- if (!thd->slave_thread)
- mysql_update_log.write(thd,thd->query,thd->query_length);
- if (!log_delayed)
+ if (!transactional_table)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
#ifndef EMBEDDED_LIBRARY
if (mysql_bin_log.is_open())
{
/*
As already explained above, we need to call end_io_cache() or the last
- block will be logged only after Execute_load_log_event (which is wrong),
- when read_info is destroyed.
+ block will be logged only after Execute_load_query_log_event (which is
+ wrong), when read_info is destroyed.
*/
- read_info.end_io_cache();
+ read_info.end_io_cache();
if (lf_info.wrote_create_file)
- {
- Execute_load_log_event e(thd, db, log_delayed);
- mysql_bin_log.write(&e);
- }
+ write_execute_load_query_log_event(thd, handle_duplicates,
+ ignore, transactional_table);
}
#endif /*!EMBEDDED_LIBRARY*/
if (transactional_table)
- error=ha_autocommit_or_rollback(thd,error);
+ error=ha_autocommit_or_rollback(thd,error);
+
err:
if (thd->lock)
{
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
+ thd->abort_on_warning= 0;
DBUG_RETURN(error);
}
+
+/* Not a very useful function; just to avoid duplication of code */
+static bool write_execute_load_query_log_event(THD *thd,
+ bool duplicates, bool ignore,
+ bool transactional_table)
+{
+ Execute_load_query_log_event
+ e(thd, thd->query, thd->query_length,
+ (char*)thd->lex->fname_start - (char*)thd->query,
+ (char*)thd->lex->fname_end - (char*)thd->query,
+ (duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
+ (ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
+ transactional_table, FALSE);
+ return mysql_bin_log.write(&e);
+}
+
+
/****************************************************************************
** Read of rows of fixed size + optional garage + optonal newline
****************************************************************************/
static int
-read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
- READ_INFO &read_info, ulong skip_lines)
+read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
+ List<Item> &fields_vars, List<Item> &set_fields,
+ List<Item> &set_values, READ_INFO &read_info,
+ ulong skip_lines, bool ignore_check_option_errors)
{
- List_iterator_fast<Item> it(fields);
+ List_iterator_fast<Item> it(fields_vars);
Item_field *sql_field;
+ TABLE *table= table_list->table;
ulonglong id;
+ bool no_trans_update;
DBUG_ENTER("read_fixed_length");
id= 0;
-
- /* No fields can be null in this format. mark all fields as not null */
- while ((sql_field= (Item_field*) it++))
- sql_field->field->set_notnull();
-
+
while (!read_info.read_fixed_length())
{
if (thd->killed)
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0));
+ thd->send_kill_message();
DBUG_RETURN(1);
}
if (skip_lines)
@@ -426,16 +534,29 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
#ifdef HAVE_purify
read_info.row_end[0]=0;
#endif
+ no_trans_update= !table->file->has_transactions();
+
+ restore_record(table, s->default_values);
+ /*
+ There is no variables in fields_vars list in this format so
+ this conversion is safe.
+ */
while ((sql_field= (Item_field*) it++))
{
Field *field= sql_field->field;
+ /*
+ No fields specified in fields_vars list can be null in this format.
+ Mark field as not null, we should do this for each row because of
+ restore_record...
+ */
+ field->set_notnull();
+
if (pos == read_info.row_end)
{
thd->cuted_fields++; /* Not enough fields */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
- field->reset();
}
else
{
@@ -445,7 +566,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
field->field_length)
length=field->field_length;
save_chr=pos[length]; pos[length]='\0'; // Safeguard aganst malloc
- field->store((char*) pos,length,read_info.read_charset);
+ field->store((char*) pos,length,read_info.read_charset);
pos[length]=save_chr;
if ((pos+=length) > read_info.row_end)
pos= read_info.row_end; /* Fills rest with space */
@@ -458,8 +579,27 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
ER_WARN_TOO_MANY_RECORDS,
ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
}
- if (write_record(table,&info))
+
+ if (thd->killed ||
+ fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
+ ignore_check_option_errors,
+ table->triggers,
+ TRG_EVENT_INSERT))
+ DBUG_RETURN(1);
+
+ switch (table_list->view_check_option(thd,
+ ignore_check_option_errors)) {
+ case VIEW_CHECK_SKIP:
+ read_info.next_line();
+ goto continue_loop;
+ case VIEW_CHECK_ERROR:
+ DBUG_RETURN(-1);
+ }
+
+ if (write_record(thd, table, &info))
DBUG_RETURN(1);
+ thd->no_trans_update= no_trans_update;
+
/*
If auto_increment values are used, save the first one
for LAST_INSERT_ID() and for the binary/update log.
@@ -468,8 +608,10 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
*/
if (!id && thd->insert_id_used)
id= thd->last_insert_id;
- if (table->next_number_field)
- table->next_number_field->reset(); // Clear for next record
+ /*
+ We don't need to reset auto-increment field since we are restoring
+ its default value at the beginning of each loop iteration.
+ */
if (read_info.next_line()) // Skip to next line
break;
if (read_info.line_cuted)
@@ -480,6 +622,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
}
thd->row_count++;
+continue_loop:;
}
if (id && !read_info.error)
thd->insert_id(id); // For binary/update log
@@ -489,80 +632,135 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
static int
-read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
- List<Item> &fields, READ_INFO &read_info,
- String &enclosed, ulong skip_lines)
+read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
+ List<Item> &fields_vars, List<Item> &set_fields,
+ List<Item> &set_values, READ_INFO &read_info,
+ String &enclosed, ulong skip_lines,
+ bool ignore_check_option_errors)
{
- List_iterator_fast<Item> it(fields);
- Item_field *sql_field;
+ List_iterator_fast<Item> it(fields_vars);
+ Item *item;
+ TABLE *table= table_list->table;
uint enclosed_length;
ulonglong id;
+ bool no_trans_update;
DBUG_ENTER("read_sep_field");
enclosed_length=enclosed.length();
id= 0;
+ no_trans_update= !table->file->has_transactions();
for (;;it.rewind())
{
if (thd->killed)
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0));
+ thd->send_kill_message();
DBUG_RETURN(1);
}
- while ((sql_field=(Item_field*) it++))
+
+ restore_record(table, s->default_values);
+
+ while ((item= it++))
{
uint length;
byte *pos;
if (read_info.read_field())
break;
+
+ /* If this line is to be skipped we don't want to fill field or var */
+ if (skip_lines)
+ continue;
+
pos=read_info.row_start;
length=(uint) (read_info.row_end-pos);
- Field *field=sql_field->field;
if (!read_info.enclosed &&
(enclosed_length && length == 4 && !memcmp(pos,"NULL",4)) ||
(length == 1 && read_info.found_null))
{
- field->reset();
- field->set_null();
- if (!field->maybe_null())
- {
- if (field->type() == FIELD_TYPE_TIMESTAMP)
- ((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, 1);
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ Field *field= ((Item_field *)item)->field;
+ field->reset();
+ field->set_null();
+ if (!field->maybe_null())
+ {
+ if (field->type() == FIELD_TYPE_TIMESTAMP)
+ ((Field_timestamp*) field)->set_time();
+ else if (field != table->next_number_field)
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_NULL_TO_NOTNULL, 1);
+ }
}
+ else
+ ((Item_user_var_as_out_param *)item)->set_null_value(
+ read_info.read_charset);
continue;
}
- field->set_notnull();
- read_info.row_end[0]=0; // Safe to change end marker
- field->store((char*) read_info.row_start,length,read_info.read_charset);
+
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ Field *field= ((Item_field *)item)->field;
+ field->set_notnull();
+ read_info.row_end[0]=0; // Safe to change end marker
+ field->store((char*) pos, length, read_info.read_charset);
+ }
+ else
+ ((Item_user_var_as_out_param *)item)->set_value((char*) pos, length,
+ read_info.read_charset);
}
if (read_info.error)
break;
if (skip_lines)
{
- if (!--skip_lines)
- thd->cuted_fields= 0L; // Reset warnings
+ skip_lines--;
continue;
}
- if (sql_field)
- { // Last record
- if (sql_field == (Item_field*) fields.head())
+ if (item)
+ {
+ /* Have not read any field, thus input file is simply ended */
+ if (item == fields_vars.head())
break;
- for (; sql_field ; sql_field=(Item_field*) it++)
+ for (; item ; item= it++)
{
- sql_field->field->set_null();
- sql_field->field->reset();
- thd->cuted_fields++;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_TOO_FEW_RECORDS,
- ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ /*
+ QQ: We probably should not throw warning for each field.
+ But how about intention to always have the same number
+ of warnings in THD::cuted_fields (and get rid of cuted_fields
+ in the end ?)
+ */
+ thd->cuted_fields++;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_TOO_FEW_RECORDS,
+ ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
+ }
+ else
+ ((Item_user_var_as_out_param *)item)->set_null_value(
+ read_info.read_charset);
}
}
- if (write_record(table,&info))
+
+ if (thd->killed ||
+ fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
+ ignore_check_option_errors,
+ table->triggers,
+ TRG_EVENT_INSERT))
+ DBUG_RETURN(1);
+
+ switch (table_list->view_check_option(thd,
+ ignore_check_option_errors)) {
+ case VIEW_CHECK_SKIP:
+ read_info.next_line();
+ goto continue_loop;
+ case VIEW_CHECK_ERROR:
+ DBUG_RETURN(-1);
+ }
+
+
+ if (write_record(thd, table, &info))
DBUG_RETURN(1);
/*
If auto_increment values are used, save the first one
@@ -572,8 +770,11 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
*/
if (!id && thd->insert_id_used)
id= thd->last_insert_id;
- if (table->next_number_field)
- table->next_number_field->reset(); // Clear for next record
+ /*
+ We don't need to reset auto-increment field since we are restoring
+ its default value at the beginning of each loop iteration.
+ */
+ thd->no_trans_update= no_trans_update;
if (read_info.next_line()) // Skip to next line
break;
if (read_info.line_cuted)
@@ -582,8 +783,11 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
thd->row_count);
+ if (thd->killed)
+ DBUG_RETURN(1);
}
thd->row_count++;
+continue_loop:;
}
if (id && !read_info.error)
thd->insert_id(id); // For binary/update log
@@ -672,12 +876,11 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs,
my_free((gptr) buffer,MYF(0)); /* purecov: inspected */
error=1;
}
- else
+ else
{
/*
init_io_cache() will not initialize read_function member
- if the cache is READ_NET. The reason is explained in
- mysys/mf_iocache.c. So we work around the problem with a
+ if the cache is READ_NET. So we work around the problem with a
manual assignment
*/
need_end_io_cache = 1;
diff --git a/sql/sql_map.cc b/sql/sql_map.cc
index aac44949d89..56b4b765355 100644
--- a/sql/sql_map.cc
+++ b/sql/sql_map.cc
@@ -20,9 +20,9 @@
#endif
#include "mysql_priv.h"
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
#include <sys/stat.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
#endif
#ifndef MAP_NORESERVE
@@ -42,19 +42,18 @@ mapped_files::mapped_files(const my_string filename,byte *magic,uint magic_lengt
struct stat stat_buf;
if (!fstat(file,&stat_buf))
{
- if (!(map=(byte*) mmap(0,(size=(ulong) stat_buf.st_size),PROT_READ,
+ if (!(map=(byte*) my_mmap(0,(size=(ulong) stat_buf.st_size),PROT_READ,
MAP_SHARED | MAP_NORESERVE,file,
0L)))
{
error=errno;
- my_printf_error(0,"Can't map file: %s, errno: %d",MYF(0),
- (my_string) name,error);
+ my_error(ER_NO_FILE_MAPPING, MYF(0), (my_string) name, error);
}
}
if (map && memcmp(map,magic,magic_length))
{
- my_printf_error(0,"Wrong magic in %s",MYF(0),name);
- VOID(munmap(map,size));
+ my_error(ER_WRONG_MAGIC, MYF(0), name);
+ VOID(my_munmap(map,size));
map=0;
}
if (!map)
@@ -72,7 +71,7 @@ mapped_files::~mapped_files()
#ifdef HAVE_MMAP
if (file >= 0)
{
- VOID(munmap((caddr_t) map,size));
+ VOID(my_munmap(map,size));
VOID(my_close(file,MYF(0)));
file= -1; map=0;
}
@@ -112,8 +111,7 @@ mapped_files *map_file(const my_string name,byte *magic,uint magic_length)
{
map->use_count++;
if (!map->map)
- my_printf_error(0,"Can't map file: %s, error: %d",MYF(0),path,
- map->error);
+ my_error(ER_NO_FILE_MAPPING, MYF(0), path, map->error);
}
VOID(pthread_mutex_unlock(&LOCK_mapped_file));
return map;
@@ -140,7 +138,7 @@ void unmap_file(mapped_files *map)
** Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
/* Used templates */
template class I_List<mapped_files>;
template class I_List_iterator<mapped_files>;
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
index 024abb6c74b..b457ff5a6d6 100644
--- a/sql/sql_olap.cc
+++ b/sql/sql_olap.cc
@@ -77,7 +77,8 @@ static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new
{
not_found= 0;
((Item_field*)new_item)->db_name=iif->db_name;
- Item_field *new_one=new Item_field(iif->db_name, iif->table_name, iif->field_name);
+ Item_field *new_one=new Item_field(&select_lex->context,
+ iif->db_name, iif->table_name, iif->field_name);
privlist.push_back(new_one);
if (add_to_list(new_select->group_list,new_one,1))
return 1;
@@ -152,11 +153,11 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
List<Item> all_fields(select_lex->item_list);
- if (setup_tables((TABLE_LIST *)select_lex->table_list.first) ||
- setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
- select_lex->item_list, 1, &all_fields,1) ||
- setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
- item_list_copy, 1, &all_fields, 1))
+ if (setup_tables(lex->thd, &select_lex->context, &select_lex->top_join_list,
+ (TABLE_LIST *)select_lex->table_list.first
+ &select_lex->where, &select_lex->leaf_tables, FALSE) ||
+ setup_fields(lex->thd, 0, select_lex->item_list, 1, &all_fields,1) ||
+ setup_fields(lex->thd, 0, item_list_copy, 1, &all_fields, 1))
return -1;
if (select_lex->olap == CUBE_TYPE)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a2df59e56c7..8c3f9090529 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -25,6 +25,10 @@
#include "ha_innodb.h"
#endif
+#include "sp_head.h"
+#include "sp.h"
+#include "sp_cache.h"
+
#ifdef HAVE_OPENSSL
/*
Without SSL the handshake consists of one packet. This packet
@@ -43,6 +47,16 @@
#define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */
+/* Used in error handling only */
+#define SP_TYPE_STRING(LP) \
+ ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE")
+#define SP_COM_STRING(LP) \
+ ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \
+ (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \
+ (LP)->sql_command == SQLCOM_SHOW_CREATE_FUNC || \
+ (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \
+ "FUNCTION" : "PROCEDURE")
+
#ifdef SOLARIS
extern "C" int gethostname(char *name, int namelen);
#endif
@@ -53,15 +67,11 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
#endif
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
-static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
- List<Item> *fields, SELECT_LEX *select_lex);
+static bool check_multi_update_lock(THD *thd);
static void remove_escape(char *name);
static void refresh_status(void);
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name);
-
-static TABLE_LIST* get_table_by_alias(TABLE_LIST* tl, const char* db,
- const char* alias);
const char *any_db="*any*"; // Special symbol for check_access
@@ -71,10 +81,14 @@ const char *command_name[]={
"Connect","Kill","Debug","Ping","Time","Delayed insert","Change user",
"Binlog Dump","Table Dump", "Connect Out", "Register Slave",
"Prepare", "Execute", "Long Data", "Close stmt",
- "Reset stmt", "Set option",
+ "Reset stmt", "Set option", "Fetch",
"Error" // Last command number
};
+const char *xa_state_names[]={
+ "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
+};
+
static char empty_c_string[1]= {0}; // Used for not defined 'db'
#ifdef __WIN__
@@ -101,7 +115,7 @@ static void unlock_locked_tables(THD *thd)
if (thd->locked_tables)
{
thd->lock=thd->locked_tables;
- thd->locked_tables=0; // Will be automaticly closed
+ thd->locked_tables=0; // Will be automatically closed
close_thread_tables(thd); // Free tables
}
}
@@ -110,17 +124,54 @@ static void unlock_locked_tables(THD *thd)
static bool end_active_trans(THD *thd)
{
int error=0;
+ DBUG_ENTER("end_active_trans");
+ if (unlikely(thd->in_sub_stmt))
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ DBUG_RETURN(1);
+ }
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
OPTION_TABLE_LOCK))
{
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ DBUG_PRINT("info",("options: 0x%lx", (ulong) thd->options));
+ /* Safety if one did "drop table" on locked tables */
+ if (!thd->locked_tables)
+ thd->options&= ~OPTION_TABLE_LOCK;
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (ha_commit(thd))
error=1;
+ thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
}
- return error;
+ DBUG_RETURN(error);
}
+static bool begin_trans(THD *thd)
+{
+ int error=0;
+ if (unlikely(thd->in_sub_stmt))
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ return 1;
+ }
+ if (thd->locked_tables)
+ {
+ thd->lock=thd->locked_tables;
+ thd->locked_tables=0; // Will be automatically closed
+ close_thread_tables(thd); // Free tables
+ }
+ if (end_active_trans(thd))
+ error= -1;
+ else
+ {
+ LEX *lex= thd->lex;
+ thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
+ OPTION_BEGIN);
+ thd->server_status|= SERVER_STATUS_IN_TRANS;
+ if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
+ error= ha_start_consistent_snapshot(thd);
+ }
+ return error;
+}
#ifdef HAVE_REPLICATION
/*
@@ -128,7 +179,7 @@ static bool end_active_trans(THD *thd)
*/
inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
{
- return (table_rules_on && tables && !tables_ok(thd,tables));
+ return table_rules_on && tables && !tables_ok(thd,tables);
}
#endif
@@ -158,23 +209,21 @@ static int get_or_create_user_conn(THD *thd, const char *user,
my_malloc(sizeof(struct user_conn) + temp_len+1,
MYF(MY_WME)))))
{
- send_error(thd, 0, NullS); // Out of memory
+ net_send_error(thd, 0, NullS); // Out of memory
return_val= 1;
goto end;
}
uc->user=(char*) (uc+1);
memcpy(uc->user,temp_user,temp_len+1);
- uc->user_len= user_len;
- uc->host= uc->user + uc->user_len + 1;
+ uc->host= uc->user + user_len + 1;
uc->len= temp_len;
- uc->connections= 0;
- uc->questions= uc->updates= uc->conn_per_hour=0;
+ uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
uc->user_resources= *mqh;
uc->intime= thd->thr_create_time;
if (my_hash_insert(&hash_user_connections, (byte*) uc))
{
my_free((char*) uc,0);
- send_error(thd, 0, NullS); // Out of memory
+ net_send_error(thd, 0, NullS); // Out of memory
return_val= 1;
goto end;
}
@@ -189,20 +238,21 @@ end:
/*
- Check if user exist and password supplied is correct.
+ Check if user exist and password supplied is correct.
+
SYNOPSIS
check_user()
thd thread handle, thd->{host,user,ip} are used
command originator of the check: now check_user is called
during connect and change user procedures; used for
logging.
- passwd scrambled password recieved from client
+ passwd scrambled password received from client
passwd_len length of scrambled password
db database name to connect to, may be NULL
check_count dont know exactly
Note, that host, user and passwd may point to communication buffer.
- Current implementation does not depened on that, but future changes
+ Current implementation does not depend on that, but future changes
should be done with this in mind; 'thd' is INOUT, all other params
are 'IN'.
@@ -221,20 +271,25 @@ int check_user(THD *thd, enum enum_server_command command,
#ifdef NO_EMBEDDED_ACCESS_CHECKS
thd->master_access= GLOBAL_ACLS; // Full rights
- /* Change database if necessary: OK or FAIL is sent in mysql_change_db */
+ /* Change database if necessary */
if (db && db[0])
{
+ /*
+ thd->db is saved in caller and needs to be freed by caller if this
+ function returns 0
+ */
thd->db= 0;
thd->db_length= 0;
- if (mysql_change_db(thd, db))
+ if (mysql_change_db(thd, db, FALSE))
{
+ /* Send the error to the client */
+ net_send_error(thd);
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
DBUG_RETURN(-1);
}
}
- else
- send_ok(thd);
+ send_ok(thd);
DBUG_RETURN(0);
#else
@@ -249,7 +304,7 @@ int check_user(THD *thd, enum enum_server_command command,
*/
if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
{
- net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
mysql_log.write(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
DBUG_RETURN(-1);
}
@@ -260,7 +315,7 @@ int check_user(THD *thd, enum enum_server_command command,
/*
Clear thd->db as it points to something, that will be freed when
- connection is closed. We don't want to accidently free a wrong pointer
+ connection is closed. We don't want to accidentally free a wrong pointer
if connect failed. Also in case of 'CHANGE USER' failure, current
database will be switched to 'no database selected'.
*/
@@ -281,15 +336,16 @@ int check_user(THD *thd, enum enum_server_command command,
NET *net= &thd->net;
if (opt_secure_auth_local)
{
- net_printf(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
- thd->user, thd->host_or_ip);
+ net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
+ thd->user, thd->host_or_ip);
mysql_log.write(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
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);
}
@@ -301,7 +357,7 @@ int check_user(THD *thd, enum enum_server_command command,
/* here res is always >= 0 */
if (res == 0)
{
- if (!(thd->master_access & NO_ACCESS)) // authentification is OK
+ if (!(thd->master_access & NO_ACCESS)) // authentication is OK
{
DBUG_PRINT("info",
("Capabilities: %d packet_length: %ld Host: '%s' "
@@ -315,12 +371,12 @@ int check_user(THD *thd, enum enum_server_command command,
if (check_count)
{
VOID(pthread_mutex_lock(&LOCK_thread_count));
- bool count_ok= thread_count < max_connections + delayed_insert_threads
+ bool count_ok= thread_count <= max_connections + delayed_insert_threads
|| (thd->master_access & SUPER_ACL);
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (!count_ok)
- { // too many connections
- send_error(thd, ER_CON_COUNT_ERROR);
+ { // too many connections
+ net_send_error(thd, ER_CON_COUNT_ERROR);
DBUG_RETURN(-1);
}
}
@@ -341,28 +397,33 @@ int check_user(THD *thd, enum enum_server_command command,
thd->db_access=0;
/* Don't allow user to connect if he has done too many queries */
- if ((ur.questions || ur.updates || ur.connections ||
+ if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
max_user_connections) &&
- get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur))
+ get_or_create_user_conn(thd,
+ opt_old_style_user_limits ? thd->user : thd->priv_user,
+ opt_old_style_user_limits ? thd->host_or_ip : thd->priv_host,
+ &ur))
DBUG_RETURN(-1);
if (thd->user_connect &&
- (thd->user_connect->user_resources.connections ||
+ (thd->user_connect->user_resources.conn_per_hour ||
+ thd->user_connect->user_resources.user_conn ||
max_user_connections) &&
check_for_max_user_connections(thd, thd->user_connect))
DBUG_RETURN(-1);
- /* Change database if necessary: OK or FAIL is sent in mysql_change_db */
+ /* Change database if necessary */
if (db && db[0])
{
- if (mysql_change_db(thd, db))
+ if (mysql_change_db(thd, db, FALSE))
{
+ /* Send error to the client */
+ net_send_error(thd);
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
DBUG_RETURN(-1);
}
}
- else
- send_ok(thd);
+ send_ok(thd);
thd->password= test(passwd_len); // remember for error messages
/* Ready to handle queries */
DBUG_RETURN(0);
@@ -370,14 +431,14 @@ int check_user(THD *thd, enum enum_server_command command,
}
else if (res == 2) // client gave short hash, server has long hash
{
- net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
DBUG_RETURN(-1);
}
- net_printf(thd, ER_ACCESS_DENIED_ERROR,
- thd->user,
- thd->host_or_ip,
- passwd_len ? ER(ER_YES) : ER(ER_NO));
+ net_printf_error(thd, ER_ACCESS_DENIED_ERROR,
+ thd->user,
+ thd->host_or_ip,
+ passwd_len ? ER(ER_YES) : ER(ER_NO));
mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
thd->user,
thd->host_or_ip,
@@ -437,20 +498,29 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
DBUG_ENTER("check_for_max_user_connections");
(void) pthread_mutex_lock(&LOCK_user_conn);
- if (max_user_connections &&
+ if (max_user_connections && !uc->user_resources.user_conn &&
max_user_connections < (uint) uc->connections)
{
- net_printf(thd,ER_TOO_MANY_USER_CONNECTIONS, uc->user);
+ net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user);
error=1;
goto end;
}
time_out_user_resource_limits(thd, uc);
- if (uc->user_resources.connections &&
- uc->user_resources.connections <= uc->conn_per_hour)
+ if (uc->user_resources.user_conn &&
+ uc->user_resources.user_conn < uc->connections)
{
- net_printf(thd, ER_USER_LIMIT_REACHED, uc->user,
- "max_connections_per_hour",
- (long) uc->user_resources.connections);
+ net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
+ "max_user_connections",
+ (long) uc->user_resources.user_conn);
+ error= 1;
+ goto end;
+ }
+ if (uc->user_resources.conn_per_hour &&
+ uc->user_resources.conn_per_hour <= uc->conn_per_hour)
+ {
+ net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
+ "max_connections_per_hour",
+ (long) uc->user_resources.conn_per_hour);
error=1;
goto end;
}
@@ -509,6 +579,12 @@ void free_max_user_conn(void)
sql_command is actually set to SQLCOM_END sometimes
so we need the +1 to include it in the array.
+
+ numbers are:
+ 0 - read-only query
+ != 0 - query that may change a table
+ 2 - query that returns meaningful ROW_COUNT() -
+ a number of modified rows
*/
char uc_update_queries[SQLCOM_END+1];
@@ -520,29 +596,31 @@ void init_update_queries(void)
uc_update_queries[SQLCOM_CREATE_TABLE]=1;
uc_update_queries[SQLCOM_CREATE_INDEX]=1;
uc_update_queries[SQLCOM_ALTER_TABLE]=1;
- uc_update_queries[SQLCOM_UPDATE]=1;
- uc_update_queries[SQLCOM_INSERT]=1;
- uc_update_queries[SQLCOM_INSERT_SELECT]=1;
- uc_update_queries[SQLCOM_DELETE]=1;
+ uc_update_queries[SQLCOM_UPDATE]=2;
+ uc_update_queries[SQLCOM_UPDATE_MULTI]=2;
+ uc_update_queries[SQLCOM_INSERT]=2;
+ uc_update_queries[SQLCOM_INSERT_SELECT]=2;
+ uc_update_queries[SQLCOM_DELETE]=2;
+ uc_update_queries[SQLCOM_DELETE_MULTI]=2;
uc_update_queries[SQLCOM_TRUNCATE]=1;
uc_update_queries[SQLCOM_DROP_TABLE]=1;
uc_update_queries[SQLCOM_LOAD]=1;
uc_update_queries[SQLCOM_CREATE_DB]=1;
uc_update_queries[SQLCOM_DROP_DB]=1;
- uc_update_queries[SQLCOM_REPLACE]=1;
- uc_update_queries[SQLCOM_REPLACE_SELECT]=1;
+ uc_update_queries[SQLCOM_REPLACE]=2;
+ uc_update_queries[SQLCOM_REPLACE_SELECT]=2;
uc_update_queries[SQLCOM_RENAME_TABLE]=1;
uc_update_queries[SQLCOM_BACKUP_TABLE]=1;
uc_update_queries[SQLCOM_RESTORE_TABLE]=1;
- uc_update_queries[SQLCOM_DELETE_MULTI]=1;
uc_update_queries[SQLCOM_DROP_INDEX]=1;
- uc_update_queries[SQLCOM_UPDATE_MULTI]=1;
+ uc_update_queries[SQLCOM_CREATE_VIEW]=1;
+ uc_update_queries[SQLCOM_DROP_VIEW]=1;
}
bool is_update_query(enum enum_sql_command command)
{
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
- return uc_update_queries[command];
+ return uc_update_queries[command] != 0;
}
/*
@@ -598,8 +676,8 @@ static bool check_mqh(THD *thd, uint check_command)
if (uc->user_resources.questions &&
uc->questions++ >= uc->user_resources.questions)
{
- net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
- (long) uc->user_resources.questions);
+ net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
+ (long) uc->user_resources.questions);
error=1;
goto end;
}
@@ -609,8 +687,8 @@ static bool check_mqh(THD *thd, uint check_command)
if (uc->user_resources.updates && uc_update_queries[check_command] &&
uc->updates++ >= uc->user_resources.updates)
{
- net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
- (long) uc->user_resources.updates);
+ net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
+ (long) uc->user_resources.updates);
error=1;
goto end;
}
@@ -624,7 +702,7 @@ end:
}
-static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
+static void reset_mqh(LEX_USER *lu, bool get_them= 0)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
(void) pthread_mutex_lock(&LOCK_user_conn);
@@ -646,8 +724,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,
@@ -738,7 +817,7 @@ static int check_connection(THD *thd)
#endif /* HAVE_COMPRESS */
#ifdef HAVE_OPENSSL
if (ssl_acceptor_fd)
- client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
+ client_flags |= CLIENT_SSL; /* Wow, SSL is available! */
#endif /* HAVE_OPENSSL */
end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
@@ -786,17 +865,6 @@ static int check_connection(THD *thd)
return(ER_OUT_OF_RESOURCES);
thd->client_capabilities=uint2korr(net->read_pos);
-#ifdef TO_BE_REMOVED_IN_4_1_RELEASE
- /*
- This is just a safety check against any client that would use the old
- CLIENT_CHANGE_USER flag
- */
- if ((thd->client_capabilities & CLIENT_PROTOCOL_41) &&
- !(thd->client_capabilities & (CLIENT_RESERVED |
- CLIENT_SECURE_CONNECTION |
- CLIENT_MULTI_RESULTS)))
- thd->client_capabilities&= ~CLIENT_PROTOCOL_41;
-#endif
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
@@ -853,8 +921,7 @@ static int check_connection(THD *thd)
DBUG_PRINT("info", ("IO layer change in progress..."));
if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout))
{
- DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
- pkt_len));
+ DBUG_PRINT("error", ("Failed to accept new SSL connection"));
inc_host_errors(&thd->remote.sin_addr);
return(ER_HANDSHAKE_ERROR);
}
@@ -946,6 +1013,7 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var,
*/
save_vio= thd->net.vio;
thd->net.vio= 0;
+ thd->net.no_send_error= 0;
dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1);
rw_unlock(var_mutex);
thd->client_capabilities= save_client_capabilities;
@@ -964,7 +1032,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);
@@ -983,10 +1051,10 @@ 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 ?
+ init_signals();
#elif !defined(OS2) && !defined(__NETWARE__)
sigset_t set;
VOID(sigemptyset(&set)); // Get mask in use
@@ -1005,11 +1073,12 @@ pthread_handler_decl(handle_one_connection,arg)
int error;
NET *net= &thd->net;
thd->thread_stack= (char*) &thd;
+ net->no_send_error= 0;
if ((error=check_connection(thd)))
{ // Wrong permissions
if (error > 0)
- net_printf(thd,error,thd->host_or_ip);
+ net_printf_error(thd, error, thd->host_or_ip);
#ifdef __NT__
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
my_sleep(1000); /* must wait after eof() */
@@ -1027,32 +1096,39 @@ pthread_handler_decl(handle_one_connection,arg)
thd->version= refresh_version;
thd->proc_info= 0;
+ thd->command= COM_SLEEP;
thd->set_time();
thd->init_for_queries();
+
if (sys_init_connect.value_length && !(thd->master_access & SUPER_ACL))
{
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
if (thd->query_error)
- thd->killed= 1;
+ thd->killed= THD::KILL_CONNECTION;
+ thd->proc_info=0;
+ thd->set_time();
+ thd->init_for_queries();
}
- while (!net->error && net->vio != 0 && !thd->killed)
+
+ while (!net->error && net->vio != 0 &&
+ !(thd->killed == THD::KILL_CONNECTION))
{
+ net->no_send_error= 0;
if (do_command(thd))
break;
}
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
- free_root(thd->mem_root,MYF(0));
if (net->error && net->vio != 0 && net->report_error)
{
if (!thd->killed && thd->variables.log_warnings > 1)
- sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
+ sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
thd->thread_id,(thd->db ? thd->db : "unconnected"),
thd->user ? thd->user : "unauthenticated",
thd->host_or_ip,
(net->last_errno ? ER(net->last_errno) :
ER(ER_UNKNOWN_ERROR)));
- send_error(thd,net->last_errno,NullS);
+ net_send_error(thd, net->last_errno, NullS);
statistic_increment(aborted_threads,&LOCK_status);
}
else if (thd->killed)
@@ -1118,50 +1194,57 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
thd->init_for_queries();
while (fgets(buff, thd->net.max_packet, file))
{
- ulong length= (ulong) strlen(buff);
- while (buff[length-1] != '\n' && !feof(file))
- {
- /*
- We got only a part of the current string. Will try to increase
- net buffer then read the rest of the current string.
- */
- if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
- {
- send_error(thd, thd->net.last_errno, NullS);
- thd->is_fatal_error= 1;
- break;
- }
- buff= (char*) thd->net.buff;
- fgets(buff + length, thd->net.max_packet - length, file);
- length+= (ulong) strlen(buff + length);
- }
- if (thd->is_fatal_error)
- break;
+ ulong length= (ulong) strlen(buff);
+ while (buff[length-1] != '\n' && !feof(file))
+ {
+ /*
+ We got only a part of the current string. Will try to increase
+ net buffer then read the rest of the current string.
+ */
+ if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
+ {
+ net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS);
+ thd->fatal_error();
+ break;
+ }
+ buff= (char*) thd->net.buff;
+ fgets(buff + length, thd->net.max_packet - length, file);
+ length+= (ulong) strlen(buff + length);
+ }
+ if (thd->is_fatal_error)
+ break;
+
while (length && (my_isspace(thd->charset(), buff[length-1]) ||
buff[length-1] == ';'))
length--;
buff[length]=0;
thd->query_length=length;
- thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1);
+ thd->query= thd->memdup_w_gap(buff, length+1,
+ thd->db_length+1+QUERY_CACHE_FLAGS_SIZE);
thd->query[length] = '\0';
- thd->query_id=query_id++;
- if (mqh_used && thd->user_connect && check_mqh(thd, SQLCOM_END))
- {
- thd->net.error = 0;
- close_thread_tables(thd); // Free tables
- free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
- break;
- }
+ /*
+ We don't need to obtain LOCK_thread_count here because in bootstrap
+ mode we have only one thread.
+ */
+ thd->query_id=next_query_id();
mysql_parse(thd,thd->query,length);
close_thread_tables(thd); // Free tables
if (thd->is_fatal_error)
break;
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
+#ifdef USING_TRANSACTIONS
free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
+#endif
}
/* thd->fatal_error should be set in case something went wrong */
end:
+ bootstrap_error= thd->is_fatal_error;
+
+ net_end(&thd->net);
+ thd->cleanup();
+ delete thd;
+
#ifndef EMBEDDED_LIBRARY
(void) pthread_mutex_lock(&LOCK_thread_count);
thread_count--;
@@ -1170,23 +1253,31 @@ end:
my_thread_end();
pthread_exit(0);
#endif
- DBUG_RETURN(0); // Never reached
+ DBUG_RETURN(0);
}
/* This works because items are allocated with sql_alloc() */
void free_items(Item *item)
{
- for (; item ; item=item->next)
+ Item *next;
+ DBUG_ENTER("free_items");
+ for (; item ; item=next)
+ {
+ next=item->next;
item->delete_self();
+ }
+ DBUG_VOID_RETURN;
}
/* This works because items are allocated with sql_alloc() */
void cleanup_items(Item *item)
{
+ DBUG_ENTER("cleanup_items");
for (; item ; item=item->next)
item->cleanup();
+ DBUG_VOID_RETURN;
}
int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
@@ -1198,19 +1289,19 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
db = (db && db[0]) ? db : thd->db;
if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(1); // out of memory
- table_list->db = db;
- table_list->real_name = table_list->alias = tbl_name;
- table_list->lock_type = TL_READ_NO_INSERT;
- table_list->next = 0;
+ table_list->db= db;
+ table_list->table_name= table_list->alias= tbl_name;
+ table_list->lock_type= TL_READ_NO_INSERT;
+ table_list->prev_global= &table_list; // can be removed after merge with 4.1
if (!db || check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
+ my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL");
goto err;
}
if (lower_case_table_names)
my_casedn_str(files_charset_info, tbl_name);
- remove_escape(table_list->real_name);
+ remove_escape(table_list->table_name);
if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
DBUG_RETURN(1);
@@ -1220,7 +1311,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
thd->free_list = 0;
thd->query_length=(uint) strlen(tbl_name);
thd->query = tbl_name;
- if ((error = mysqld_dump_create_info(thd, table, -1)))
+ if ((error = mysqld_dump_create_info(thd, table_list, -1)))
{
my_error(ER_GET_ERRNO, MYF(0), my_errno);
goto err;
@@ -1230,10 +1321,76 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
my_error(ER_GET_ERRNO, MYF(0), error);
err:
- close_thread_tables(thd);
DBUG_RETURN(error);
}
+/*
+ Ends the current transaction and (maybe) begin the next
+
+ SYNOPSIS
+ end_trans()
+ thd Current thread
+ completion Completion type
+
+ RETURN
+ 0 - OK
+*/
+
+int end_trans(THD *thd, enum enum_mysql_completiontype completion)
+{
+ bool do_release= 0;
+ int res= 0;
+ DBUG_ENTER("end_trans");
+
+ if (unlikely(thd->in_sub_stmt))
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ DBUG_RETURN(1);
+ }
+ switch (completion) {
+ case COMMIT:
+ /*
+ We don't use end_active_trans() here to ensure that this works
+ even if there is a problem with the OPTION_AUTO_COMMIT flag
+ (Which of course should never happen...)
+ */
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ res= ha_commit(thd);
+ thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ break;
+ case COMMIT_RELEASE:
+ do_release= 1; /* fall through */
+ case COMMIT_AND_CHAIN:
+ res= end_active_trans(thd);
+ if (!res && completion == COMMIT_AND_CHAIN)
+ res= begin_trans(thd);
+ break;
+ case ROLLBACK_RELEASE:
+ do_release= 1; /* fall through */
+ case ROLLBACK:
+ case ROLLBACK_AND_CHAIN:
+ {
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ if (ha_rollback(thd))
+ res= -1;
+ thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ if (!res && (completion == ROLLBACK_AND_CHAIN))
+ res= begin_trans(thd);
+ break;
+ }
+ default:
+ res= -1;
+ my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
+ DBUG_RETURN(-1);
+ }
+
+ if (res < 0)
+ my_error(thd->killed_errno(), MYF(0));
+ else if ((res == 0) && do_release)
+ thd->killed= THD::KILL_CONNECTION;
+
+ DBUG_RETURN(res);
+}
#ifndef EMBEDDED_LIBRARY
@@ -1265,7 +1422,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
@@ -1281,7 +1438,7 @@ bool do_command(THD *thd)
statistic_increment(aborted_threads,&LOCK_status);
DBUG_RETURN(TRUE); // We have to close it.
}
- send_error(thd,net->last_errno,NullS);
+ net_send_error(thd, net->last_errno, NullS);
net->error= 0;
DBUG_RETURN(FALSE);
}
@@ -1309,8 +1466,10 @@ bool do_command(THD *thd)
}
#endif /* EMBEDDED_LIBRARY */
+
/*
Perform one connection-level (COM_XXXX) command.
+
SYNOPSIS
dispatch_command()
thd connection handle
@@ -1332,17 +1491,21 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
bool error= 0;
DBUG_ENTER("dispatch_command");
+ if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
+ thd->killed= THD::NOT_KILLED;
+
thd->command=command;
/*
Commands which always take a long time are logged into
the slow log only if opt_log_slow_admin_statements is set.
*/
thd->enable_slow_log= TRUE;
+ thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
thd->set_time();
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id=query_id;
if (command != COM_STATISTICS && command != COM_PING)
- query_id++;
+ next_query_id();
thread_running++;
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
VOID(pthread_mutex_unlock(&LOCK_thread_count));
@@ -1353,11 +1516,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_INIT_DB:
{
LEX_STRING tmp;
- statistic_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
+ statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB],
+ &LOCK_status);
thd->convert_string(&tmp, system_charset_info,
packet, strlen(packet), thd->charset());
- if (!mysql_change_db(thd, tmp.str))
+ if (!mysql_change_db(thd, tmp.str, FALSE))
+ {
mysql_log.write(thd,command,"%s",thd->db);
+ send_ok(thd);
+ }
break;
}
#ifdef HAVE_REPLICATION
@@ -1374,13 +1541,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint db_len= *(uchar*) packet;
uint tbl_len= *(uchar*) (packet + db_len + 1);
- statistic_increment(com_other, &LOCK_status);
+ statistic_increment(thd->status_var.com_other, &LOCK_status);
thd->enable_slow_log= opt_log_slow_admin_statements;
db= thd->alloc(db_len + tbl_len + 2);
tbl_name= strmake(db, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len);
- if (mysql_table_dump(thd, db, tbl_name, -1))
- send_error(thd); // dump to NET
+ mysql_table_dump(thd, db, tbl_name, -1);
break;
}
case COM_CHANGE_USER:
@@ -1388,7 +1554,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->change_user();
thd->clear_error(); // if errors from rollback
- statistic_increment(com_other, &LOCK_status);
+ statistic_increment(thd->status_var.com_other, &LOCK_status);
char *user= (char*) packet;
char *passwd= strend(user)+1;
/*
@@ -1402,10 +1568,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
*passwd++ : strlen(passwd);
db+= passwd_len + 1;
#ifndef EMBEDDED_LIBRARY
- /* Small check for incomming packet */
+ /* Small check for incoming packet */
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
{
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
break;
}
#endif
@@ -1428,7 +1594,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (!(thd->user= my_strdup(user, MYF(0))))
{
thd->user= save_user;
- send_error(thd, ER_OUT_OF_RESOURCES);
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
break;
}
@@ -1438,9 +1604,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (res)
{
- /* authentification failure, we shall restore old user */
+ /* authentication failure, we shall restore old user */
if (res > 0)
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
x_free(thd->user);
thd->user= save_user;
thd->priv_user= save_priv_user;
@@ -1460,27 +1626,32 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
break;
}
- case COM_EXECUTE:
+ case COM_STMT_EXECUTE:
{
mysql_stmt_execute(thd, packet, packet_length);
break;
}
- case COM_LONG_DATA:
+ case COM_STMT_FETCH:
+ {
+ mysql_stmt_fetch(thd, packet, packet_length);
+ break;
+ }
+ case COM_STMT_SEND_LONG_DATA:
{
mysql_stmt_get_longdata(thd, packet, packet_length);
break;
}
- case COM_PREPARE:
+ case COM_STMT_PREPARE:
{
mysql_stmt_prepare(thd, packet, packet_length);
break;
}
- case COM_CLOSE_STMT:
+ case COM_STMT_CLOSE:
{
- mysql_stmt_free(thd, packet);
+ mysql_stmt_close(thd, packet);
break;
}
- case COM_RESET_STMT:
+ case COM_STMT_RESET:
{
mysql_stmt_reset(thd, packet);
break;
@@ -1492,17 +1663,23 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
char *packet_end= thd->query + thd->query_length;
mysql_log.write(thd,command,"%s",thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
+
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+
mysql_parse(thd,thd->query, thd->query_length);
- while (!thd->killed && !thd->is_fatal_error && thd->lex->found_colon)
+ while (!thd->killed && thd->lex->found_semicolon && !thd->net.report_error)
{
- char *packet= thd->lex->found_colon;
+ char *packet= thd->lex->found_semicolon;
+ net->no_send_error= 0;
/*
Multiple queries exits, execute them individually
in embedded server - just store them to be executed later
*/
#ifndef EMBEDDED_LIBRARY
- if (thd->lock || thd->open_tables || thd->derived_tables)
+ if (thd->lock || thd->open_tables || thd->derived_tables ||
+ thd->prelocked_mode)
close_thread_tables(thd);
#endif
ulong length= (ulong)(packet_end-packet);
@@ -1518,7 +1695,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_length= length;
thd->query= packet;
- thd->query_id= query_id++;
+ thd->query_id= next_query_id();
thd->set_time(); /* Reset the query start time. */
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
VOID(pthread_mutex_unlock(&LOCK_thread_count));
@@ -1550,44 +1727,70 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_FIELD_LIST: // This isn't actually needed
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
break;
#else
{
char *fields, *pend;
+ /* Locked closure of all tables */
+ TABLE_LIST *locked_tables= NULL;
TABLE_LIST table_list;
LEX_STRING conv_name;
+ /* Saved variable value */
+ my_bool old_innodb_table_locks=
+ IF_INNOBASE_DB(thd->variables.innodb_table_locks, FALSE);
+
- statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
+ statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
+ &LOCK_status);
bzero((char*) &table_list,sizeof(table_list));
if (!(table_list.db=thd->db))
{
- send_error(thd,ER_NO_DB_ERROR);
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
break;
}
- thd->free_list=0;
pend= strend(packet);
thd->convert_string(&conv_name, system_charset_info,
packet, (uint) (pend-packet), thd->charset());
- table_list.alias= table_list.real_name= conv_name.str;
+ table_list.alias= table_list.table_name= conv_name.str;
packet= pend+1;
+
+ if (!my_strcasecmp(system_charset_info, table_list.db,
+ information_schema_name.str))
+ {
+ ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias);
+ if (schema_table)
+ table_list.schema_table= schema_table;
+ }
+
thd->query_length= strlen(packet); // for simplicity: don't optimize
if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1)))
break;
- mysql_log.write(thd,command,"%s %s",table_list.real_name,fields);
+ mysql_log.write(thd,command,"%s %s",table_list.table_name, fields);
if (lower_case_table_names)
- my_casedn_str(files_charset_info, table_list.real_name);
- remove_escape(table_list.real_name); // This can't have wildcards
+ my_casedn_str(files_charset_info, table_list.table_name);
+ remove_escape(table_list.table_name); // This can't have wildcards
if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
- 0, 0))
+ 0, 0, test(table_list.schema_table)))
break;
if (grant_option &&
check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
break;
+ /* init structures for VIEW processing */
+ table_list.select_lex= &(thd->lex->select_lex);
+ mysql_init_query(thd, (uchar*)"", 0);
+ thd->lex->
+ select_lex.table_list.link_in_list((byte*) &table_list,
+ (byte**) &table_list.next_local);
+ thd->lex->add_to_query_tables(&table_list);
+
+ /* switch on VIEW optimisation: do not fill temporary tables */
+ thd->lex->sql_command= SQLCOM_SHOW_FIELDS;
mysqld_list_fields(thd,&table_list,fields);
- free_items(thd->free_list);
- thd->free_list= 0;
+ thd->lex->unit.cleanup();
+ thd->cleanup_after_query();
break;
}
#endif
@@ -1603,43 +1806,43 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
char *db=thd->strdup(packet), *alias;
HA_CREATE_INFO create_info;
- statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
+ statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB],
+ &LOCK_status);
// 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");
+ my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL");
break;
}
- if (check_access(thd,CREATE_ACL,db,0,1,0))
+ if (check_access(thd,CREATE_ACL,db,0,1,0,is_schema_db(db)))
break;
mysql_log.write(thd,command,packet);
bzero(&create_info, sizeof(create_info));
- if (mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db),
- &create_info, 0) < 0)
- send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db),
+ &create_info, 0);
break;
}
case COM_DROP_DB: // QQ: To be removed
{
- statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
- char *db=thd->strdup(packet), *alias;
- // null test to handle EOM
- if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
+ statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB],
+ &LOCK_status);
+ char *db=thd->strdup(packet);
+ /* null test to handle EOM */
+ if (!db || check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
+ my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL");
break;
}
- if (check_access(thd,DROP_ACL,db,0,1,0))
+ if (check_access(thd,DROP_ACL,db,0,1,0,is_schema_db(db)))
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
break;
}
mysql_log.write(thd,command,db);
- if (mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db),
- 0, 0) < 0)
- send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ mysql_rm_db(thd, db, 0, 0);
break;
}
#ifndef EMBEDDED_LIBRARY
@@ -1649,7 +1852,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
ushort flags;
uint32 slave_server_id;
- statistic_increment(com_other,&LOCK_status);
+ statistic_increment(thd->status_var.com_other,&LOCK_status);
thd->enable_slow_log= opt_log_slow_admin_statements;
if (check_global_access(thd, REPL_SLAVE_ACL))
break;
@@ -1666,29 +1869,29 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
(long) pos);
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;
}
#endif
case COM_REFRESH:
- {
- statistic_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
- ulong options= (ulong) (uchar) packet[0];
- if (check_global_access(thd,RELOAD_ACL))
- break;
- mysql_log.write(thd,command,NullS);
- if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, NULL))
- send_error(thd, 0);
- else
- send_ok(thd);
+ {
+ bool not_used;
+ statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH],
+ &LOCK_status);
+ ulong options= (ulong) (uchar) packet[0];
+ if (check_global_access(thd,RELOAD_ACL))
break;
- }
+ mysql_log.write(thd,command,NullS);
+ if (!reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, &not_used))
+ send_ok(thd);
+ break;
+ }
#ifndef EMBEDDED_LIBRARY
case COM_SHUTDOWN:
{
- statistic_increment(com_other,&LOCK_status);
+ statistic_increment(thd->status_var.com_other, &LOCK_status);
if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */
/*
@@ -1705,7 +1908,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
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));
@@ -1719,8 +1921,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif
close_connection(thd, 0, 1);
close_thread_tables(thd); // Free before kill
- free_root(thd->mem_root,MYF(0));
- free_root(&thd->transaction.mem_root,MYF(0));
kill_mysql();
error=TRUE;
break;
@@ -1729,7 +1929,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_STATISTICS:
{
mysql_log.write(thd,command,NullS);
- statistic_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
+ statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS],
+ &LOCK_status);
#ifndef EMBEDDED_LIBRARY
char buff[200];
#else
@@ -1737,11 +1938,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif
ulong uptime = (ulong) (thd->start_time - start_time);
sprintf((char*) buff,
- "Uptime: %ld Threads: %d Questions: %lu Slow queries: %ld Opens: %ld Flush tables: %ld Open tables: %u Queries per second avg: %.3f",
+ "Uptime: %lu Threads: %d Questions: %lu Slow queries: %lu Opens: %lu Flush tables: %lu Open tables: %u Queries per second avg: %.3f",
uptime,
- (int) thread_count,thd->query_id,long_query_count,
- opened_tables,refresh_version, cached_tables(),
- uptime ? (float)thd->query_id/(float)uptime : 0);
+ (int) thread_count, (ulong) thd->query_id,
+ (ulong) thd->status_var.long_query_count,
+ thd->status_var.opened_tables, refresh_version, cached_tables(),
+ (uptime ? (ulonglong2double(thd->query_id) / (double) uptime) :
+ (double) 0));
#ifdef SAFEMALLOC
if (sf_malloc_cur_memory) // Using SAFEMALLOC
sprintf(strend(buff), " Memory in use: %ldK Max memory used: %ldK",
@@ -1755,11 +1958,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_PING:
- statistic_increment(com_other,&LOCK_status);
+ statistic_increment(thd->status_var.com_other, &LOCK_status);
send_ok(thd); // Tell client we are alive
break;
case COM_PROCESS_INFO:
- statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
+ statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST],
+ &LOCK_status);
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
mysql_log.write(thd,command,NullS);
@@ -1769,14 +1973,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
case COM_PROCESS_KILL:
{
- statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status);
+ statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status);
ulong id=(ulong) uint4korr(packet);
- kill_one_thread(thd,id);
+ kill_one_thread(thd,id,false);
break;
}
case COM_SET_OPTION:
{
- statistic_increment(com_stat[SQLCOM_SET_OPTION], &LOCK_status);
+ statistic_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION],
+ &LOCK_status);
enum_mysql_set_option command= (enum_mysql_set_option) uint2korr(packet);
switch (command) {
case MYSQL_OPTION_MULTI_STATEMENTS_ON:
@@ -1788,16 +1993,16 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
send_eof(thd);
break;
default:
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
break;
}
break;
}
case COM_DEBUG:
- statistic_increment(com_other,&LOCK_status);
+ statistic_increment(thd->status_var.com_other, &LOCK_status);
if (check_global_access(thd, SUPER_ACL))
break; /* purecov: inspected */
- mysql_print_status(thd);
+ mysql_print_status();
mysql_log.write(thd,command,NullS);
send_eof(thd);
break;
@@ -1807,17 +2012,32 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_DELAYED_INSERT:
case COM_END:
default:
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
break;
}
- if (thd->lock || thd->open_tables || thd->derived_tables)
+ if (thd->lock || thd->open_tables || thd->derived_tables ||
+ thd->prelocked_mode)
{
thd->proc_info="closing tables";
close_thread_tables(thd); /* Free tables */
}
+ /*
+ assume handlers auto-commit (if some doesn't - transaction handling
+ in MySQL should be redesigned to support it; it's a big change,
+ and it's not worth it - better to commit explicitly only writing
+ transactions, read-only ones should better take care of themselves.
+ saves some work in 2pc too)
+ see also sql_base.cc - close_thread_tables()
+ */
+ bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt));
+ if (!thd->active_transaction())
+ thd->transaction.xid_state.xid.null();
- if (thd->is_fatal_error)
- send_error(thd,0); // End of memory ?
+ /* report error issued during command execution */
+ if (thd->killed_errno() && !thd->net.report_error)
+ thd->send_kill_message();
+ if (thd->net.report_error)
+ net_send_error(thd);
log_slow_statement(thd);
@@ -1837,7 +2057,17 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
void log_slow_statement(THD *thd)
{
- time_t start_of_query=thd->start_time;
+ time_t start_of_query;
+
+ /*
+ The following should never be true with our current code base,
+ but better to keep this here so we don't accidently try to log a
+ statement in a trigger or stored function
+ */
+ if (unlikely(thd->in_sub_stmt))
+ return; // Don't set time for sub stmt
+
+ start_of_query= thd->start_time;
thd->end_time(); // Set start time
/*
@@ -1854,16 +2084,136 @@ void log_slow_statement(THD *thd)
(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
(specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES)))
{
- long_query_count++;
+ thd->status_var.long_query_count++;
mysql_slow_log.write(thd, thd->query, thd->query_length, start_of_query);
}
}
}
+int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
+ enum enum_schema_tables schema_table_idx)
+{
+ DBUG_ENTER("prepare_schema_table");
+ SELECT_LEX *sel= 0;
+ switch (schema_table_idx) {
+ case SCH_SCHEMATA:
+#if defined(DONT_ALLOW_SHOW_COMMANDS)
+ my_message(ER_NOT_ALLOWED_COMMAND,
+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
+ DBUG_RETURN(1);
+#else
+ if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
+ check_global_access(thd, SHOW_DB_ACL))
+ DBUG_RETURN(1);
+ break;
+#endif
+ case SCH_TABLE_NAMES:
+ case SCH_TABLES:
+ case SCH_VIEWS:
+ case SCH_TRIGGERS:
+#ifdef DONT_ALLOW_SHOW_COMMANDS
+ my_message(ER_NOT_ALLOWED_COMMAND,
+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
+ DBUG_RETURN(1);
+#else
+ {
+ char *db= lex->select_lex.db ? lex->select_lex.db : thd->db;
+ if (!db)
+ {
+ my_message(ER_NO_DB_ERROR,
+ ER(ER_NO_DB_ERROR), MYF(0)); /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
+ }
+ remove_escape(db); // Fix escaped '_'
+ if (check_db_name(db))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db);
+ DBUG_RETURN(1);
+ }
+ if (check_access(thd, SELECT_ACL, db, &thd->col_access, 0, 0,
+ is_schema_db(db)))
+ DBUG_RETURN(1); /* purecov: inspected */
+ if (!thd->col_access && check_grant_db(thd,db))
+ {
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user, thd->priv_host, db);
+ DBUG_RETURN(1);
+ }
+ /*
+ We need to do a copy to make this prepared statement safe if this
+ was thd->db
+ */
+ lex->select_lex.db= thd->strdup(db);
+ break;
+ }
+#endif
+ case SCH_COLUMNS:
+ case SCH_STATISTICS:
+#ifdef DONT_ALLOW_SHOW_COMMANDS
+ my_message(ER_NOT_ALLOWED_COMMAND,
+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
+ DBUG_RETURN(1);
+#else
+ if (table_ident)
+ {
+ TABLE_LIST **query_tables_last= lex->query_tables_last;
+ sel= new SELECT_LEX();
+ /* 'parent_lex' is used in init_query() so it must be before it. */
+ sel->parent_lex= lex;
+ sel->init_query();
+ if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
+ (List<String> *) 0, (List<String> *) 0))
+ DBUG_RETURN(1);
+ lex->query_tables_last= query_tables_last;
+ TABLE_LIST *table_list= (TABLE_LIST*) sel->table_list.first;
+ char *db= table_list->db;
+ remove_escape(db); // Fix escaped '_'
+ remove_escape(table_list->table_name);
+ if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
+ &table_list->grant.privilege, 0, 0,
+ test(table_list->schema_table)))
+ DBUG_RETURN(1); /* purecov: inspected */
+ if (grant_option && check_grant(thd, SELECT_ACL, table_list, 2,
+ UINT_MAX, 0))
+ DBUG_RETURN(1);
+ break;
+ }
+#endif
+ case SCH_OPEN_TABLES:
+ case SCH_VARIABLES:
+ case SCH_STATUS:
+ case SCH_PROCEDURES:
+ case SCH_CHARSETS:
+ case SCH_COLLATIONS:
+ case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
+ case SCH_USER_PRIVILEGES:
+ case SCH_SCHEMA_PRIVILEGES:
+ case SCH_TABLE_PRIVILEGES:
+ case SCH_COLUMN_PRIVILEGES:
+ case SCH_TABLE_CONSTRAINTS:
+ case SCH_KEY_COLUMN_USAGE:
+ default:
+ break;
+ }
+
+ SELECT_LEX *select_lex= lex->current_select;
+ if (make_schema_select(thd, select_lex, schema_table_idx))
+ {
+ DBUG_RETURN(1);
+ }
+ TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
+ table_list->schema_select_lex= sel;
+ table_list->schema_table_reformed= 1;
+ statistic_increment(thd->status_var.com_stat[lex->orig_sql_command],
+ &LOCK_status);
+ DBUG_RETURN(0);
+}
+
+
/*
Read query from packet and store in thd->query
- Used in COM_QUERY and COM_PREPARE
+ Used in COM_QUERY and COM_STMT_PREPARE
DESCRIPTION
Sets the following THD variables:
@@ -1871,11 +2221,11 @@ void log_slow_statement(THD *thd)
query_length
RETURN VALUES
- 0 ok
- 1 error; In this case thd->fatal_error is set
+ FALSE ok
+ TRUE error; In this case thd->fatal_error is set
*/
-bool alloc_query(THD *thd, char *packet, ulong packet_length)
+bool alloc_query(THD *thd, const char *packet, uint packet_length)
{
packet_length--; // Remove end null
/* Remove garbage at start and end of query */
@@ -1884,7 +2234,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
packet++;
packet_length--;
}
- char *pos=packet+packet_length; // Point at end null
+ const char *pos= packet + packet_length; // Point at end null
while (packet_length > 0 &&
(pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1])))
{
@@ -1897,7 +2247,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
packet_length,
thd->db_length+ 1 +
QUERY_CACHE_FLAGS_SIZE)))
- return 1;
+ return TRUE;
thd->query[packet_length]=0;
thd->query_length= packet_length;
@@ -1905,9 +2255,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
thd->packet.shrink(thd->variables.net_buffer_length);
thd->convert_buffer.shrink(thd->variables.net_buffer_length);
- if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),QUERY_PRIOR);
- return 0;
+ return FALSE;
}
static void reset_one_shot_variables(THD *thd)
@@ -1932,37 +2280,60 @@ static void reset_one_shot_variables(THD *thd)
** Execute command saved in thd and current_lex->sql_command
****************************************************************************/
-void
+bool
mysql_execute_command(THD *thd)
{
- int res= 0;
+ bool res= FALSE;
+ int result= 0;
LEX *lex= thd->lex;
+ /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
+ SELECT_LEX *select_lex= &lex->select_lex;
bool slave_fake_lock= 0;
MYSQL_LOCK *fake_prev_lock= 0;
- SELECT_LEX *select_lex= &lex->select_lex;
- TABLE_LIST *tables= (TABLE_LIST*) select_lex->table_list.first;
+ /* first table of first SELECT_LEX */
+ TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
+ /* list of all tables in query */
+ TABLE_LIST *all_tables;
+ /* most outer SELECT_LEX_UNIT of query */
SELECT_LEX_UNIT *unit= &lex->unit;
+ /* Saved variable value */
DBUG_ENTER("mysql_execute_command");
+ thd->net.no_send_error= 0;
+
+ /*
+ In many cases first table of main SELECT_LEX have special meaning =>
+ check that it is first table in global list and relink it first in
+ queries_tables list if it is necessary (we need such relinking only
+ for queries with subqueries in select list, in this case tables of
+ subqueries will go to global list first)
+
+ all_tables will differ from first_table only if most upper SELECT_LEX
+ do not contain tables.
+
+ Because of above in place where should be at least one table in most
+ outer SELECT_LEX we have following check:
+ DBUG_ASSERT(first_table == all_tables);
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ */
+ lex->first_lists_tables_same();
+ /* should be assigned after making first tables same */
+ all_tables= lex->query_tables;
+ /* set context for commands which do not use setup_tables */
+ select_lex->
+ context.resolve_in_table_list_only((TABLE_LIST*)select_lex->
+ table_list.first);
/*
Reset warning count for each query that uses tables
A better approach would be to reset this for any commands
that is not a SHOW command or a select that only access local
variables, but for now this is probably good enough.
+ Don't reset warnings when executing a stored routine.
*/
- if (tables || &lex->select_lex != lex->all_selects_list ||
+ if ((all_tables || &lex->select_lex != lex->all_selects_list ||
+ lex->sroutines.records) && !thd->spcont ||
lex->time_zone_tables_used)
- mysql_reset_errors(thd);
-
- /*
- When subselects or time_zone info is used in a query
- we create a new TABLE_LIST containing all referenced tables
- and set local variable 'tables' to point to this list.
- */
- if ((&lex->select_lex != lex->all_selects_list ||
- lex->time_zone_tables_used) &&
- lex->unit.create_total_list(thd, lex, &tables))
- DBUG_VOID_RETURN;
+ mysql_reset_errors(thd, 0);
#ifdef HAVE_REPLICATION
if (thd->slave_thread)
@@ -1971,8 +2342,7 @@ mysql_execute_command(THD *thd)
{
DBUG_PRINT("info",("need faked locked tables"));
- if (check_multi_update_lock(thd, tables, &select_lex->item_list,
- select_lex))
+ if (check_multi_update_lock(thd))
goto error;
/* Fix for replication, the tables are opened and locked,
@@ -1998,12 +2368,12 @@ mysql_execute_command(THD *thd)
if (!(lex->sql_command == SQLCOM_SET_OPTION) &&
!(lex->sql_command == SQLCOM_DROP_TABLE &&
lex->drop_temporary && lex->drop_if_exists) &&
- all_tables_not_ok(thd,tables))
+ all_tables_not_ok(thd, all_tables))
{
/* we warn the slave SQL thread */
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
reset_one_shot_variables(thd);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
#ifndef TO_BE_DELETED
/*
@@ -2026,13 +2396,15 @@ mysql_execute_command(THD *thd)
*/
if (opt_readonly &&
!(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
- (uc_update_queries[lex->sql_command] > 0))
+ uc_update_queries[lex->sql_command])
{
- net_printf(thd, ER_OPTION_PREVENTS_STATEMENT, "--read-only");
- DBUG_VOID_RETURN;
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
+ DBUG_RETURN(-1);
}
+ if(lex->orig_sql_command == SQLCOM_END)
+ statistic_increment(thd->status_var.com_stat[lex->sql_command],
+ &LOCK_status);
- statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
@@ -2040,47 +2412,39 @@ mysql_execute_command(THD *thd)
{
SELECT_LEX *param= lex->unit.global_parameters;
if (!param->explicit_limit)
- param->select_limit= thd->variables.select_limit;
+ param->select_limit=
+ new Item_int((ulonglong)thd->variables.select_limit);
}
select_result *result=lex->result;
- if (tables)
+ if (all_tables)
{
- res=check_table_access(thd,
- lex->exchange ? SELECT_ACL | FILE_ACL :
- SELECT_ACL,
- tables,0);
+ if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC &&
+ lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC)
+ res= check_table_access(thd,
+ lex->exchange ? SELECT_ACL | FILE_ACL :
+ SELECT_ACL,
+ all_tables, 0);
}
else
- res=check_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
- any_db,0,0,0);
+ res= check_access(thd,
+ lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
+ any_db, 0, 0, 0, 0);
if (res)
- {
- res=0;
- break; // Error message is given
- }
- /*
- In case of single SELECT unit->global_parameters points on first SELECT
- TODO: move counters to SELECT_LEX
- */
- unit->offset_limit_cnt= (ha_rows) unit->global_parameters->offset_limit;
- unit->select_limit_cnt= (ha_rows) (unit->global_parameters->select_limit+
- unit->global_parameters->offset_limit);
- if (unit->select_limit_cnt <
- (ha_rows) unit->global_parameters->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // no limit
- if (unit->select_limit_cnt == HA_POS_ERROR && !select_lex->next_select())
- select_lex->options&= ~OPTION_FOUND_ROWS;
+ goto error;
- if (!(res=open_and_lock_tables(thd,tables)))
+ if (!(res= open_and_lock_tables(thd, all_tables)))
{
if (lex->describe)
{
+ /*
+ We always use select_send for EXPLAIN, even if it's an EXPLAIN
+ for SELECT ... INTO OUTFILE: a user application should be able
+ to prepend EXPLAIN to any query and receive output for it,
+ even if the query itself redirects the output.
+ */
if (!(result= new select_send()))
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_VOID_RETURN;
- }
+ goto error;
else
thd->send_explain_fields(result);
res= mysql_explain_union(thd, &thd->lex->unit, result);
@@ -2100,12 +2464,9 @@ mysql_execute_command(THD *thd)
else
{
if (!result && !(result= new select_send()))
- {
- res= -1;
- break;
- }
- query_cache_store_query(thd, tables);
- res= handle_select(thd, lex, result);
+ goto error;
+ query_cache_store_query(thd, all_tables);
+ res= handle_select(thd, lex, result, 0);
if (result != lex->result)
delete result;
}
@@ -2114,127 +2475,25 @@ mysql_execute_command(THD *thd)
}
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;
- String *pstr= &str;
- 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)
- {
- my_bool is_var_null;
- pstr= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC);
- /*
- NULL value of variable checked early as entry->value so here
- we can't get NULL in normal conditions
- */
- DBUG_ASSERT(!is_var_null);
- if (!pstr)
- {
- res= -1;
- break; // EOM (error should be reported by allocator)
- }
- }
- else
- {
- /*
- variable absent or equal to NULL, so we need to set variable to
- something reasonable to get readable error message during parsing
- */
- str.set("NULL", 4, &my_charset_latin1);
- }
-
- need_conversion=
- String::needs_conversion(pstr->length(), pstr->charset(),
- to_cs, &unused);
-
- query_len= need_conversion? (pstr->length() * to_cs->mbmaxlen) :
- pstr->length();
- if (!(query_str= alloc_root(thd->mem_root, query_len+1)))
- {
- res= -1;
- break; // EOM (error should be reported by allocator)
- }
-
- if (need_conversion)
- {
- uint dummy_errors;
- query_len= copy_and_convert(query_str, query_len, to_cs,
- pstr->ptr(), pstr->length(),
- pstr->charset(), &dummy_errors);
- }
- else
- memcpy(query_str, pstr->ptr(), pstr->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");
+ mysql_sql_stmt_prepare(thd);
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();
+ mysql_sql_stmt_execute(thd);
break;
}
case SQLCOM_DEALLOCATE_PREPARE:
{
- Statement* stmt;
- DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n",
- lex->prepared_stmt_name.length,
- lex->prepared_stmt_name.str));
- /* We account deallocate in the same manner as mysql_stmt_close */
- statistic_increment(com_stmt_close, &LOCK_status);
- 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");
- }
+ mysql_sql_stmt_close(thd);
break;
}
case SQLCOM_DO:
- if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
- (res= open_and_lock_tables(thd,tables))))
- break;
+ if (check_table_access(thd, SELECT_ACL, all_tables, 0) ||
+ open_and_lock_tables(thd, all_tables))
+ goto error;
res= mysql_do(thd, *lex->insert_list);
- if (thd->net.report_error)
- res= -1;
break;
case SQLCOM_EMPTY_QUERY:
@@ -2250,16 +2509,31 @@ 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;
}
case SQLCOM_PURGE_BEFORE:
{
+ Item *it;
+
if (check_global_access(thd, SUPER_ACL))
goto error;
- // PURGE MASTER LOGS BEFORE 'data'
- res = purge_master_logs_before_date(thd, lex->purge_time);
+ /* PURGE MASTER LOGS BEFORE 'data' */
+ it= (Item *)lex->value_list.head();
+ if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
+ it->check_cols(1))
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
+ goto error;
+ }
+ it= new Item_func_unix_timestamp(it);
+ /*
+ it is OK only emulate fix_fieds, because we need only
+ value of constant
+ */
+ it->quick_fix_field();
+ res = purge_master_logs_before_date(thd, (ulong)it->val_int());
break;
}
#endif
@@ -2284,12 +2558,12 @@ mysql_execute_command(THD *thd)
goto error;
/* This query don't work now. See comment in repl_failsafe.cc */
#ifndef WORKING_NEW_MASTER
- net_printf(thd, ER_NOT_SUPPORTED_YET, "SHOW NEW MASTER");
- res= 1;
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "SHOW NEW MASTER");
+ goto error;
#else
res = show_new_master(thd);
-#endif
break;
+#endif
}
#ifdef HAVE_REPLICATION
@@ -2304,48 +2578,54 @@ mysql_execute_command(THD *thd)
{
if (check_global_access(thd, REPL_SLAVE_ACL))
goto error;
- res = show_binlog_events(thd);
+ res = mysql_show_binlog_events(thd);
break;
}
#endif
case SQLCOM_BACKUP_TABLE:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL, tables,0) ||
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL, all_tables, 0) ||
check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
- res = mysql_backup_table(thd, tables);
+ res = mysql_backup_table(thd, first_table);
break;
}
case SQLCOM_RESTORE_TABLE:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd, INSERT_ACL, tables,0) ||
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, INSERT_ACL, all_tables, 0) ||
check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
- res = mysql_restore_table(thd, tables);
+ res = mysql_restore_table(thd, first_table);
break;
}
case SQLCOM_ASSIGN_TO_KEYCACHE:
{
- if (check_db_used(thd, tables) ||
- check_access(thd, INDEX_ACL, tables->db,
- &tables->grant.privilege, 0, 0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_access(thd, INDEX_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0,
+ test(first_table->schema_table)))
goto error;
- res= mysql_assign_to_keycache(thd, tables, &lex->name_and_length);
+ res= mysql_assign_to_keycache(thd, first_table, &lex->ident);
break;
}
case SQLCOM_PRELOAD_KEYS:
{
- if (check_db_used(thd, tables) ||
- check_access(thd, INDEX_ACL, tables->db,
- &tables->grant.privilege, 0, 0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_access(thd, INDEX_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0,
+ test(first_table->schema_table)))
goto error;
- res = mysql_preload_keys(thd, tables);
+ res = mysql_preload_keys(thd, first_table);
break;
}
#ifdef HAVE_REPLICATION
@@ -2381,7 +2661,7 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd, SUPER_ACL))
goto error;
if (end_active_trans(thd))
- res= -1;
+ goto error;
else
res = load_master_data(thd);
break;
@@ -2394,23 +2674,33 @@ mysql_execute_command(THD *thd)
res = innodb_show_status(thd);
break;
}
+ case SQLCOM_SHOW_MUTEX_STATUS:
+ {
+ if (check_global_access(thd, SUPER_ACL))
+ goto error;
+ res = innodb_mutex_show_status(thd);
+ break;
+ }
#endif
#ifdef HAVE_REPLICATION
case SQLCOM_LOAD_MASTER_TABLE:
{
- if (!tables->db)
- tables->db=thd->db;
- if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege,0,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (!first_table->db)
+ first_table->db= thd->db;
+ if (check_access(thd, CREATE_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0,
+ test(first_table->schema_table)))
goto error; /* purecov: inspected */
if (grant_option)
{
/* Check that the first table has CREATE privilege */
- if (check_grant(thd, CREATE_ACL, tables, 0, 1, 0))
+ if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
goto error;
}
- if (strlen(tables->real_name) > NAME_LEN)
+ if (strlen(first_table->table_name) > NAME_LEN)
{
- net_printf(thd,ER_WRONG_TABLE_NAME, tables->real_name);
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), first_table->table_name);
break;
}
pthread_mutex_lock(&LOCK_active_mi);
@@ -2418,7 +2708,7 @@ mysql_execute_command(THD *thd)
fetch_master_table will send the error to the client on failure.
Give error if the table already exists.
*/
- if (!fetch_master_table(thd, tables->db, tables->real_name,
+ if (!fetch_master_table(thd, first_table->db, first_table->table_name,
active_mi, 0, 0))
{
send_ok(thd);
@@ -2444,29 +2734,27 @@ mysql_execute_command(THD *thd)
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
}
- /* Skip first table, which is the table we are creating */
- TABLE_LIST *create_table, *create_table_local;
- tables= lex->unlink_first_table(tables, &create_table,
- &create_table_local);
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ bool link_to_local;
+ // Skip first table, which is the table we are creating
+ TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
+ TABLE_LIST *select_tables= lex->query_tables;
- if ((res= create_table_precheck(thd, tables, create_table)))
- goto unsent_create_error;
+ if ((res= create_table_precheck(thd, select_tables, create_table)))
+ goto end_with_restore_list;
#ifndef HAVE_READLINK
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
#else
/* Fix names if symlinked tables */
if (append_file_to_dir(thd, &lex->create_info.data_file_name,
- create_table->real_name) ||
- append_file_to_dir(thd,&lex->create_info.index_file_name,
- create_table->real_name))
- {
- res=-1;
- goto unsent_create_error;
- }
+ create_table->table_name) ||
+ append_file_to_dir(thd, &lex->create_info.index_file_name,
+ create_table->table_name))
+ goto end_with_restore_list;
#endif
/*
- If we are using SET CHARSET without DEFAULT, add an implicite
+ If we are using SET CHARSET without DEFAULT, add an implicit
DEFAULT to not confuse old users. (This may change).
*/
if ((lex->create_info.used_fields &
@@ -2493,79 +2781,108 @@ mysql_execute_command(THD *thd)
*/
if (wait_if_global_read_lock(thd, 0, 1))
{
- res= -1;
- goto unsent_create_error;
+ res= 1;
+ goto end_with_restore_list;
}
if (select_lex->item_list.elements) // With select
{
select_result *result;
select_lex->options|= SELECT_NO_UNLOCK;
- unit->offset_limit_cnt= select_lex->offset_limit;
- unit->select_limit_cnt= select_lex->select_limit+
- select_lex->offset_limit;
- if (unit->select_limit_cnt < select_lex->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // No limit
+ unit->set_limit(select_lex);
- if (!(res=open_and_lock_tables(thd,tables)))
+ if (!(res= open_and_lock_tables(thd, select_tables)))
{
- res= -1; // If error
- if ((result=new select_create(create_table->db,
- create_table->real_name,
- &lex->create_info,
- lex->create_list,
- lex->key_list,
- select_lex->item_list, lex->duplicates,
- lex->ignore)))
+ /*
+ Is table which we are changing used somewhere in other parts
+ of query
+ */
+ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
+ {
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(create_table, select_tables)))
+ {
+ update_non_unique_table_error(create_table, "CREATE", duplicate);
+ res= 1;
+ goto end_with_restart_wait;
+ }
+ }
+ /* If we create merge table, we have to test tables in merge, too */
+ if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
+ {
+ TABLE_LIST *tab;
+ for (tab= (TABLE_LIST*) lex->create_info.merge_list.first;
+ tab;
+ tab= tab->next_local)
+ {
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(tab, select_tables)))
+ {
+ update_non_unique_table_error(tab, "CREATE", duplicate);
+ res= 1;
+ goto end_with_restart_wait;
+ }
+ }
+ }
+
+ if ((result= new select_create(create_table,
+ &lex->create_info,
+ lex->create_list,
+ lex->key_list,
+ select_lex->item_list,
+ lex->duplicates,
+ lex->ignore)))
{
/*
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);
- select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
+ res= handle_select(thd, lex, result, 0);
+ delete result;
}
- //reset for PS
+ /* 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);
else
{
- res= mysql_create_table(thd,create_table->db,
- create_table->real_name, &lex->create_info,
- lex->create_list,
- lex->key_list,0,0);
+ res= mysql_create_table(thd, create_table->db,
+ create_table->table_name, &lex->create_info,
+ lex->create_list,
+ lex->key_list, 0, 0);
}
if (!res)
send_ok(thd);
}
+
+end_with_restart_wait:
/*
Release the protection against the global read lock and wake
everyone, who might want to set a global read lock.
*/
start_waiting_global_read_lock(thd);
-unsent_create_error:
- // put tables back for PS rexecuting
- tables= lex->link_first_table_back(tables, create_table,
- create_table_local);
+ /* put tables back for PS rexecuting */
+end_with_restore_list:
+ lex->link_first_table_back(create_table, link_to_local);
break;
}
case SQLCOM_CREATE_INDEX:
- if (check_one_table_access(thd, INDEX_ACL, tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
if (end_active_trans(thd))
- res= -1;
+ goto error;
else
- res = mysql_create_index(thd, tables, lex->key_list);
+ res = mysql_create_index(thd, first_table, lex->key_list);
break;
#ifdef HAVE_REPLICATION
@@ -2592,8 +2909,9 @@ unsent_create_error:
*/
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
- break;
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
+ goto error;
}
{
pthread_mutex_lock(&LOCK_active_mi);
@@ -2604,17 +2922,18 @@ unsent_create_error:
#endif /* HAVE_REPLICATION */
case SQLCOM_ALTER_TABLE:
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
#if defined(DONT_ALLOW_SHOW_COMMANDS)
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- break;
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
+ goto error;
#else
{
ulong priv=0;
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
{
- net_printf(thd, ER_WRONG_TABLE_NAME, lex->name);
- res= 1;
- break;
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
+ goto error;
}
if (!select_lex->db)
{
@@ -2627,29 +2946,32 @@ unsent_create_error:
{
if (! thd->db)
{
- send_error(thd,ER_NO_DB_ERROR);
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
goto error;
}
select_lex->db= thd->db;
}
else
- select_lex->db=tables->db;
+ select_lex->db= first_table->db;
}
- if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege,0,0) ||
- check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)||
- check_merge_table_access(thd, tables->db,
+ if (check_access(thd, ALTER_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0,
+ test(first_table->schema_table)) ||
+ check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0,
+ is_schema_db(select_lex->db))||
+ check_merge_table_access(thd, first_table->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto error; /* purecov: inspected */
if (grant_option)
{
- if (check_grant(thd, ALTER_ACL, tables, 0, UINT_MAX, 0))
+ if (check_grant(thd, ALTER_ACL, all_tables, 0, UINT_MAX, 0))
goto error;
if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
TABLE_LIST tmp_table;
bzero((char*) &tmp_table,sizeof(tmp_table));
- tmp_table.real_name=lex->name;
+ tmp_table.table_name=lex->name;
tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
@@ -2661,63 +2983,63 @@ unsent_create_error:
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
- res= -1;
+ goto error;
else
{
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_alter_table(thd, select_lex->db, lex->name,
&lex->create_info,
- tables, lex->create_list,
+ first_table, lex->create_list,
lex->key_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
- lex->duplicates, lex->ignore, &lex->alter_info);
+ lex->duplicates, lex->ignore, &lex->alter_info,
+ 1);
}
break;
}
#endif /*DONT_ALLOW_SHOW_COMMANDS*/
case SQLCOM_RENAME_TABLE:
{
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *table;
- if (check_db_used(thd,tables))
+ if (check_db_used(thd, all_tables))
goto error;
- for (table=tables ; table ; table=table->next->next)
+ for (table= first_table; table; table= table->next_local->next_local)
{
if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
- &table->grant.privilege,0,0) ||
- check_access(thd, INSERT_ACL | CREATE_ACL, table->next->db,
- &table->next->grant.privilege,0,0))
+ &table->grant.privilege,0,0, test(table->schema_table)) ||
+ check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db,
+ &table->next_local->grant.privilege, 0, 0,
+ test(table->next_local->schema_table)))
goto error;
if (grant_option)
{
- TABLE_LIST old_list,new_list;
+ TABLE_LIST old_list, new_list;
/*
we do not need initialize old_list and new_list because we will
come table[0] and table->next[0] there
*/
- old_list=table[0];
- new_list=table->next[0];
- old_list.next=new_list.next=0;
- if (check_grant(thd, ALTER_ACL, &old_list, 0, UINT_MAX, 0) ||
- (!test_all_bits(table->next->grant.privilege,
+ old_list= table[0];
+ new_list= table->next_local[0];
+ if (check_grant(thd, ALTER_ACL, &old_list, 0, 1, 0) ||
+ (!test_all_bits(table->next_local->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
- check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0,
- UINT_MAX, 0)))
+ check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
goto error;
}
}
- query_cache_invalidate3(thd, tables, 0);
- if (end_active_trans(thd))
- res= -1;
- else if (mysql_rename_tables(thd,tables))
- res= -1;
+ query_cache_invalidate3(thd, first_table, 0);
+ if (end_active_trans(thd) || mysql_rename_tables(thd, first_table))
+ goto error;
break;
}
#ifndef EMBEDDED_LIBRARY
case SQLCOM_SHOW_BINLOGS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- DBUG_VOID_RETURN;
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
+ goto error;
#else
{
if (check_global_access(thd, SUPER_ACL))
@@ -2728,40 +3050,48 @@ unsent_create_error:
#endif
#endif /* EMBEDDED_LIBRARY */
case SQLCOM_SHOW_CREATE:
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- DBUG_VOID_RETURN;
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
+ goto error;
#else
{
- if (check_db_used(thd, tables) ||
- check_access(thd, SELECT_ACL | EXTRA_ACL, tables->db,
- &tables->grant.privilege,0,0))
+ /* Ignore temporary tables if this is "SHOW CREATE VIEW" */
+ if (lex->only_view)
+ first_table->skip_temporary= 1;
+
+ if (check_db_used(thd, all_tables) ||
+ check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db,
+ &first_table->grant.privilege, 0, 0,
+ test(first_table->schema_table)))
goto error;
- if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0))
+ if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0))
goto error;
- res= mysqld_show_create(thd, tables);
+ res= mysqld_show_create(thd, first_table);
break;
}
#endif
case SQLCOM_CHECKSUM:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0))
goto error; /* purecov: inspected */
- res = mysql_checksum_table(thd, tables, &lex->check_opt);
+ res = mysql_checksum_table(thd, first_table, &lex->check_opt);
break;
}
case SQLCOM_REPAIR:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
- res = mysql_repair_table(thd, tables, &lex->check_opt);
+ res= mysql_repair_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -2773,24 +3103,25 @@ unsent_create_error:
}
case SQLCOM_CHECK:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
- res = mysql_check_table(thd, tables, &lex->check_opt);
+ res = mysql_check_table(thd, first_table, &lex->check_opt);
break;
}
case SQLCOM_ANALYZE:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
- res = mysql_analyze_table(thd, tables, &lex->check_opt);
+ res = mysql_analyze_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -2803,17 +3134,17 @@ unsent_create_error:
case SQLCOM_OPTIMIZE:
{
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
- mysql_recreate_table(thd, tables, 1) :
- mysql_optimize_table(thd, tables, &lex->check_opt);
+ mysql_recreate_table(thd, first_table, 1) :
+ mysql_optimize_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -2824,116 +3155,105 @@ unsent_create_error:
break;
}
case SQLCOM_UPDATE:
- if (update_precheck(thd, tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (update_precheck(thd, all_tables))
break;
- res= mysql_update(thd,tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- select_lex->order_list.elements,
- (ORDER *) select_lex->order_list.first,
- select_lex->select_limit,
- lex->duplicates, lex->ignore);
- if (thd->net.report_error)
- res= -1;
- break;
- case SQLCOM_UPDATE_MULTI:
- {
- if ((res= multi_update_precheck(thd, tables)))
+ DBUG_ASSERT(select_lex->offset_limit == 0);
+ unit->set_limit(select_lex);
+ res= (result= mysql_update(thd, all_tables,
+ select_lex->item_list,
+ lex->value_list,
+ select_lex->where,
+ select_lex->order_list.elements,
+ (ORDER *) select_lex->order_list.first,
+ unit->select_limit_cnt,
+ lex->duplicates, lex->ignore));
+ /* mysql_update return 2 if we need to switch to multi-update */
+ if (result != 2)
break;
- res= mysql_multi_update(thd,tables,
- &select_lex->item_list,
- &lex->value_list,
- select_lex->where,
- select_lex->options,
- lex->duplicates, lex->ignore, unit, select_lex);
+ case SQLCOM_UPDATE_MULTI:
+ {
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ /* if we switched from normal update, rights are checked */
+ if (result != 2)
+ {
+ if ((res= multi_update_precheck(thd, all_tables)))
+ break;
+ }
+ else
+ res= 0;
+
+ res= mysql_multi_update(thd, all_tables,
+ &select_lex->item_list,
+ &lex->value_list,
+ select_lex->where,
+ select_lex->options,
+ lex->duplicates, lex->ignore, unit, select_lex);
break;
}
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
{
- if ((res= insert_precheck(thd, tables)))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if ((res= insert_precheck(thd, all_tables)))
break;
- res= mysql_insert(thd,tables,lex->field_list,lex->many_values,
- lex->update_list, lex->value_list,
+ /* Skip first table, which is the table we are inserting in */
+ select_lex->context.table_list= first_table->next_local;
+ res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
+ lex->update_list, lex->value_list,
lex->duplicates, lex->ignore);
- if (thd->net.report_error)
- res= -1;
+ if (first_table->view && !first_table->contain_auto_increment)
+ thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
break;
}
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
{
- TABLE_LIST *first_local_table= (TABLE_LIST *) select_lex->table_list.first;
- TABLE_LIST dup_tables;
- TABLE *insert_table;
- if ((res= insert_precheck(thd, tables)))
+ select_result *result;
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if ((res= insert_precheck(thd, all_tables)))
break;
/* Fix lock for first table */
- if (tables->lock_type == TL_WRITE_DELAYED)
- tables->lock_type= TL_WRITE;
+ if (first_table->lock_type == TL_WRITE_DELAYED)
+ first_table->lock_type= TL_WRITE;
/* Don't unlock tables until command is written to binary log */
select_lex->options|= SELECT_NO_UNLOCK;
- select_result *result;
- unit->offset_limit_cnt= select_lex->offset_limit;
- unit->select_limit_cnt= select_lex->select_limit+select_lex->offset_limit;
- if (unit->select_limit_cnt < select_lex->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // No limit
-
- if (find_real_table_in_list(tables->next, tables->db, tables->real_name))
- {
- /* Using same table for INSERT and SELECT */
- select_lex->options |= OPTION_BUFFER_RESULT;
- }
-
- if ((res= open_and_lock_tables(thd, tables)))
- break;
-
- insert_table= tables->table;
- /* Skip first table, which is the table we are inserting in */
- select_lex->table_list.first= (byte*) first_local_table->next;
- tables= (TABLE_LIST *) select_lex->table_list.first;
- dup_tables= *first_local_table;
- first_local_table->next= 0;
- if (select_lex->group_list.elements != 0)
- {
- /*
- When we are using GROUP BY we can't refere to other tables in the
- ON DUPLICATE KEY part
- */
- dup_tables.next= 0;
- }
-
- if (!(res= mysql_prepare_insert(thd, tables, first_local_table,
- &dup_tables, insert_table,
- lex->field_list, 0,
- lex->update_list, lex->value_list,
- lex->duplicates)) &&
- (result= new select_insert(insert_table, first_local_table,
- &dup_tables, &lex->field_list,
- &lex->update_list, &lex->value_list,
- lex->duplicates, lex->ignore)))
- {
- /*
- 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);
+ unit->set_limit(select_lex);
+ if (!(res= open_and_lock_tables(thd, all_tables)))
+ {
+ /* Skip first table, which is the table we are inserting in */
+ TABLE_LIST *second_table= first_table->next_local;
+ select_lex->table_list.first= (byte*) second_table;
+ select_lex->context.table_list=
+ select_lex->context.first_name_resolution_table= second_table;
+ res= mysql_insert_select_prepare(thd);
+ if (!res && (result= new select_insert(first_table, first_table->table,
+ &lex->field_list,
+ &lex->update_list,
+ &lex->value_list,
+ lex->duplicates, lex->ignore)))
+ {
+ /*
+ Skip first table, which is the table we are inserting in.
+ Below we set context.table_list again because the call above to
+ mysql_insert_select_prepare() calls resolve_in_table_list_only(),
+ which in turn resets context.table_list and
+ context.first_name_resolution_table.
+ */
+ select_lex->context.table_list=
+ select_lex->context.first_name_resolution_table= second_table;
+ res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
+ delete result;
+ }
/* revert changes for SP */
- lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
- delete result;
- if (thd->net.report_error)
- res= -1;
+ select_lex->table_list.first= (byte*) first_table;
}
- else
- res= -1;
- insert_table->insert_values= 0; // Set by mysql_prepare_insert()
- first_local_table->next= tables;
- lex->select_lex.table_list.first= (byte*) first_local_table;
+
+ if (first_table->view && !first_table->contain_auto_increment)
+ thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
break;
}
case SQLCOM_TRUNCATE:
@@ -2942,76 +3262,60 @@ unsent_create_error:
res= -1;
break;
}
- if (check_one_table_access(thd, DELETE_ACL, tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_one_table_access(thd, DELETE_ACL, all_tables))
goto error;
/*
Don't allow this within a transaction because we want to use
re-generate table
*/
- if (thd->locked_tables || thd->active_transaction())
+ if ((thd->locked_tables && !lex->sphead) || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
- res=mysql_truncate(thd, tables, 0);
+
+ res= mysql_truncate(thd, first_table, 0);
break;
case SQLCOM_DELETE:
{
- if ((res= delete_precheck(thd, tables)))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if ((res= delete_precheck(thd, all_tables)))
break;
- res = mysql_delete(thd,tables, select_lex->where,
+ DBUG_ASSERT(select_lex->offset_limit == 0);
+ unit->set_limit(select_lex);
+ res = mysql_delete(thd, all_tables, select_lex->where,
&select_lex->order_list,
- select_lex->select_limit, select_lex->options);
- if (thd->net.report_error)
- res= -1;
+ unit->select_limit_cnt, select_lex->options,
+ FALSE);
break;
}
case SQLCOM_DELETE_MULTI:
{
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
- TABLE_LIST *target_tbl;
- uint table_count;
multi_delete *result;
- if ((res= multi_delete_precheck(thd, tables, &table_count)))
+ if ((res= multi_delete_precheck(thd, all_tables)))
break;
/* condition will be TRUE on SP re-excuting */
if (select_lex->item_list.elements != 0)
select_lex->item_list.empty();
if (add_item_to_list(thd, new Item_null()))
- {
- res= -1;
- break;
- }
+ goto error;
thd->proc_info="init";
- if ((res=open_and_lock_tables(thd,tables)))
+ if ((res= open_and_lock_tables(thd, all_tables)))
break;
- /* Fix tables-to-be-deleted-from list to point at opened tables */
- for (target_tbl= (TABLE_LIST*) aux_tables;
- target_tbl;
- target_tbl= target_tbl->next)
- {
- TABLE_LIST *orig= target_tbl->table_list;
- target_tbl->table= orig->table;
- /*
- Multi-delete can't be constructed over-union => we always have
- single SELECT on top and have to check underlying SELECTs of it
- */
- if (lex->select_lex.check_updateable_in_subqueries(orig->db,
- orig->real_name))
- {
- my_error(ER_UPDATE_TABLE_USED, MYF(0),
- orig->real_name);
- res= -1;
- break;
- }
- }
- if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
- table_count)))
+ if ((res= mysql_multi_delete_prepare(thd)))
+ goto error;
+
+ if (!thd->is_fatal_error && (result= new multi_delete(aux_tables,
+ lex->table_count)))
{
res= mysql_select(thd, &select_lex->ref_pointer_array,
select_lex->get_table_list(),
@@ -3021,28 +3325,24 @@ unsent_create_error:
0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
(ORDER *)NULL,
select_lex->options | thd->options |
- SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
+ OPTION_SETUP_TABLES_DONE,
result, unit, select_lex);
- if (thd->net.report_error)
- res= -1;
delete result;
}
else
- res= -1; // Error is not sent
- close_thread_tables(thd);
+ res= TRUE; // Error
break;
}
case SQLCOM_DROP_TABLE:
{
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (!lex->drop_temporary)
{
- if (check_table_access(thd,DROP_ACL,tables,0))
+ if (check_table_access(thd, DROP_ACL, all_tables, 0))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
- {
- res= -1;
- break;
- }
+ goto error;
}
else
{
@@ -3060,28 +3360,19 @@ unsent_create_error:
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
}
- res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary);
+ res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
+ lex->drop_temporary);
}
break;
case SQLCOM_DROP_INDEX:
- if (check_one_table_access(thd, INDEX_ACL, tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
- res= -1;
- else
- res = mysql_drop_index(thd, tables, &lex->alter_info);
- break;
- case SQLCOM_SHOW_DATABASES:
-#if defined(DONT_ALLOW_SHOW_COMMANDS)
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- DBUG_VOID_RETURN;
-#else
- if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
- check_global_access(thd, SHOW_DB_ACL))
goto error;
- res= mysqld_show_dbs(thd, (lex->wild ? lex->wild->ptr() : NullS));
+ else
+ res = mysql_drop_index(thd, first_table, &lex->alter_info);
break;
-#endif
case SQLCOM_SHOW_PROCESSLIST:
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
@@ -3098,155 +3389,60 @@ unsent_create_error:
case SQLCOM_SHOW_COLUMN_TYPES:
res= mysqld_show_column_types(thd);
break;
- case SQLCOM_SHOW_STATUS:
- res= mysqld_show(thd,(lex->wild ? lex->wild->ptr() : NullS),status_vars,
- OPT_GLOBAL, &LOCK_status);
- break;
- case SQLCOM_SHOW_VARIABLES:
- res= mysqld_show(thd, (lex->wild ? lex->wild->ptr() : NullS),
- init_vars, lex->option_type,
- &LOCK_global_system_variables);
- break;
case SQLCOM_SHOW_LOGS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- DBUG_VOID_RETURN;
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
+ goto error;
#else
{
- if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0))
+ if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0,0))
goto error;
res= mysqld_show_logs(thd);
break;
}
#endif
- case SQLCOM_SHOW_TABLES:
- /* FALL THROUGH */
-#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- DBUG_VOID_RETURN;
-#else
- {
- char *db=select_lex->db ? select_lex->db : thd->db;
- if (!db)
- {
- send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
- goto error; /* purecov: inspected */
- }
- remove_escape(db); // Fix escaped '_'
- if (check_db_name(db))
- {
- net_printf(thd,ER_WRONG_DB_NAME, db);
- goto error;
- }
- if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0))
- goto error; /* purecov: inspected */
- if (!thd->col_access && check_grant_db(thd,db))
- {
- net_printf(thd, ER_DBACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- db);
- goto error;
- }
- /* grant is checked in mysqld_show_tables */
- if (lex->describe)
- res= mysqld_extend_show_tables(thd,db,
- (lex->wild ? lex->wild->ptr() : NullS));
- else
- res= mysqld_show_tables(thd,db,
- (lex->wild ? lex->wild->ptr() : NullS));
- break;
- }
-#endif
- case SQLCOM_SHOW_OPEN_TABLES:
- res= mysqld_show_open_tables(thd,(lex->wild ? lex->wild->ptr() : NullS));
- break;
- case SQLCOM_SHOW_CHARSETS:
- res= mysqld_show_charsets(thd,(lex->wild ? lex->wild->ptr() : NullS));
- break;
- case SQLCOM_SHOW_COLLATIONS:
- res= mysqld_show_collations(thd,(lex->wild ? lex->wild->ptr() : NullS));
- break;
- case SQLCOM_SHOW_FIELDS:
-#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- DBUG_VOID_RETURN;
-#else
- {
- char *db=tables->db;
- remove_escape(db); // Fix escaped '_'
- remove_escape(tables->real_name);
- if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
- &tables->grant.privilege, 0, 0))
- goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0))
- goto error;
- res= mysqld_show_fields(thd,tables,
- (lex->wild ? lex->wild->ptr() : NullS),
- lex->verbose);
- break;
- }
-#endif
- case SQLCOM_SHOW_KEYS:
-#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- DBUG_VOID_RETURN;
-#else
- {
- char *db=tables->db;
- remove_escape(db); // Fix escaped '_'
- remove_escape(tables->real_name);
- if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
- &tables->grant.privilege, 0, 0))
- goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0))
- goto error;
- res= mysqld_show_keys(thd,tables);
- break;
- }
-#endif
case SQLCOM_CHANGE_DB:
- mysql_change_db(thd,select_lex->db);
+ if (!mysql_change_db(thd,select_lex->db,FALSE))
+ send_ok(thd);
break;
case SQLCOM_LOAD:
{
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
uint privilege= (lex->duplicates == DUP_REPLACE ?
- INSERT_ACL | DELETE_ACL : INSERT_ACL);
+ INSERT_ACL | DELETE_ACL : INSERT_ACL) |
+ (lex->local_file ? 0 : FILE_ACL);
- if (!lex->local_file)
- {
- if (check_access(thd,privilege | FILE_ACL,tables->db,0,0,0))
- goto error;
- }
- else
+ if (lex->local_file)
{
if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) ||
- ! opt_local_infile)
+ !opt_local_infile)
{
- send_error(thd,ER_NOT_ALLOWED_COMMAND);
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), MYF(0));
goto error;
}
- if (check_one_table_access(thd, privilege, tables))
- goto error;
}
- res=mysql_load(thd, lex->exchange, tables, lex->field_list,
- lex->duplicates, lex->ignore, (bool) lex->local_file, lex->lock_option);
+
+ if (check_one_table_access(thd, privilege, all_tables))
+ goto error;
+
+ res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
+ lex->update_list, lex->value_list, lex->duplicates,
+ lex->ignore, (bool) lex->local_file);
break;
}
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 ((check_table_access(thd, SELECT_ACL, all_tables, 0) ||
+ open_and_lock_tables(thd, all_tables)))
+ goto error;
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;
+ my_error(ER_RESERVED_SYNTAX, MYF(0), "SET ONE_SHOT");
+ goto error;
}
if (!(res= sql_set_variables(thd, lex_var_list)))
{
@@ -3257,8 +3453,6 @@ purposes internal to the MySQL server", MYF(0));
thd->one_shot_set|= lex->one_shot_set;
send_ok(thd);
}
- if (thd->net.report_error)
- res= -1;
break;
}
@@ -3281,17 +3475,18 @@ purposes internal to the MySQL server", MYF(0));
break;
case SQLCOM_LOCK_TABLES:
unlock_locked_tables(thd);
- if (check_db_used(thd,tables) || end_active_trans(thd))
+ if (check_db_used(thd, all_tables) || end_active_trans(thd))
goto error;
- if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables,0))
+ if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0))
goto error;
thd->in_lock_tables=1;
thd->options|= OPTION_TABLE_LOCK;
- if (!(res= open_and_lock_tables(thd, tables)))
+
+ if (!(res= simple_open_n_lock_tables(thd, all_tables)))
{
#ifdef HAVE_QUERY_CACHE
if (thd->variables.query_cache_wlock_invalidate)
- query_cache.invalidate_locked_for_write(tables);
+ query_cache.invalidate_locked_for_write(first_table);
#endif /*HAVE_QUERY_CACHE*/
thd->locked_tables=thd->lock;
thd->lock=0;
@@ -3311,26 +3506,26 @@ purposes internal to the MySQL server", MYF(0));
char *alias;
if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
{
- net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
break;
}
/*
If in a slave thread :
CREATE DATABASE DB was certainly not preceded by USE DB.
- For that reason, db_ok() in sql/slave.cc did not check the
+ For that reason, db_ok() in sql/slave.cc did not check the
do_db/ignore_db. And as this query involves no tables, tables_ok()
above was not called. So we have to check rules again here.
*/
#ifdef HAVE_REPLICATION
- if (thd->slave_thread &&
+ if (thd->slave_thread &&
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
!db_ok_with_wild_table(lex->name)))
{
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
- if (check_access(thd,CREATE_ACL,lex->name,0,1,0))
+ if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
break;
res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
&lex->create_info, 0);
@@ -3343,10 +3538,9 @@ purposes internal to the MySQL server", MYF(0));
res= -1;
break;
}
- char *alias;
- if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
+ if (check_db_name(lex->name))
{
- net_printf(thd, ER_WRONG_DB_NAME, lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
break;
}
/*
@@ -3361,19 +3555,19 @@ purposes internal to the MySQL server", MYF(0));
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
!db_ok_with_wild_table(lex->name)))
{
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
- if (check_access(thd,DROP_ACL,lex->name,0,1,0))
+ if (check_access(thd,DROP_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
- res=mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : lex->name),
- lex->drop_if_exists, 0);
+ res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0);
break;
}
case SQLCOM_ALTER_DB:
@@ -3381,12 +3575,12 @@ purposes internal to the MySQL server", MYF(0));
char *db= lex->name ? lex->name : thd->db;
if (!db)
{
- send_error(thd, ER_NO_DB_ERROR);
- goto error;
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
+ break;
}
if (!strip_sp(db) || check_db_name(db))
{
- net_printf(thd, ER_WRONG_DB_NAME, db);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
break;
}
/*
@@ -3401,15 +3595,16 @@ purposes internal to the MySQL server", MYF(0));
(!db_ok(db, replicate_do_db, replicate_ignore_db) ||
!db_ok_with_wild_table(db)))
{
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
- if (check_access(thd, ALTER_ACL, db, 0, 1, 0))
+ if (check_access(thd, ALTER_ACL, db, 0, 1, 0, is_schema_db(db)))
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
res= mysql_alter_db(thd, db, &lex->create_info);
@@ -3419,47 +3614,76 @@ purposes internal to the MySQL server", MYF(0));
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
break;
}
- if (check_access(thd,SELECT_ACL,lex->name,0,1,0))
+ if (check_access(thd,SELECT_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
break;
res=mysqld_show_create_db(thd,lex->name,&lex->create_info);
break;
}
- case SQLCOM_CREATE_FUNCTION:
- if (check_access(thd,INSERT_ACL,"mysql",0,1,0))
+ case SQLCOM_CREATE_FUNCTION: // UDF function
+ {
+ if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
break;
#ifdef HAVE_DLOPEN
- if (!(res = mysql_create_function(thd,&lex->udf)))
+ if (sp_find_function(thd, lex->spname))
+ {
+ my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str);
+ goto error;
+ }
+ if (!(res = mysql_create_function(thd, &lex->udf)))
send_ok(thd);
#else
- net_printf(thd, ER_CANT_OPEN_LIBRARY, lex->udf.dl, 0, "feature disabled");
- res= -1;
+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0), lex->udf.dl, 0, "feature disabled");
+ res= TRUE;
#endif
break;
- case SQLCOM_DROP_FUNCTION:
- if (check_access(thd,DELETE_ACL,"mysql",0,1,0))
+ }
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ case SQLCOM_CREATE_USER:
+ {
+ if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1, 0) &&
+ check_global_access(thd,CREATE_USER_ACL))
break;
-#ifdef HAVE_DLOPEN
- if (!(res = mysql_drop_function(thd,&lex->udf.name)))
+ if (!(res= mysql_create_user(thd, lex->users_list)))
+ {
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
send_ok(thd);
-#else
- res= -1;
-#endif
+ }
break;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ }
case SQLCOM_DROP_USER:
{
- if (check_access(thd, GRANT_ACL,"mysql",0,1,0))
+ if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1, 0) &&
+ check_global_access(thd,CREATE_USER_ACL))
break;
if (!(res= mysql_drop_user(thd, lex->users_list)))
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd);
+ }
+ break;
+ }
+ case SQLCOM_RENAME_USER:
+ {
+ if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
+ check_global_access(thd,CREATE_USER_ACL))
+ break;
+ if (!(res= mysql_rename_user(thd, lex->users_list)))
+ {
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
}
send_ok(thd);
}
@@ -3467,11 +3691,11 @@ purposes internal to the MySQL server", MYF(0));
}
case SQLCOM_REVOKE_ALL:
{
- if (check_access(thd, GRANT_ACL ,"mysql",0,1,0))
+ if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
+ check_global_access(thd,CREATE_USER_ACL))
break;
if (!(res = mysql_revoke_all(thd, lex->users_list)))
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
@@ -3485,95 +3709,104 @@ purposes internal to the MySQL server", MYF(0));
case SQLCOM_GRANT:
{
if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
- tables ? tables->db : select_lex->db,
- tables ? &tables->grant.privilege : 0,
- tables ? 0 : 1, 0))
+ first_table ? first_table->db : select_lex->db,
+ first_table ? &first_table->grant.privilege : 0,
+ first_table ? 0 : 1, 0,
+ first_table ? (bool) first_table->schema_table :
+ select_lex->db ? is_schema_db(select_lex->db) : 0))
goto error;
- /*
- Check that the user isn't trying to change a password for another
- user if he doesn't have UPDATE privilege to the MySQL database
- */
-
if (thd->user) // If not replication
{
LEX_USER *user;
+ uint counter;
+
List_iterator <LEX_USER> user_list(lex->users_list);
- while ((user=user_list++))
+ while ((user= user_list++))
{
- if (user->password.str &&
- (strcmp(thd->user,user->user.str) ||
- user->host.str &&
- my_strcasecmp(&my_charset_latin1,
- user->host.str, thd->host_or_ip)))
- {
- if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1))
- {
- send_error(thd, ER_PASSWORD_NOT_ALLOWED);
- goto error;
- }
- break; // We are allowed to do global changes
- }
+ if (specialflag & SPECIAL_NO_RESOLVE &&
+ hostname_requires_resolving(user->host.str))
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_HOSTNAME_WONT_WORK,
+ ER(ER_WARN_HOSTNAME_WONT_WORK),
+ user->host.str);
+ // Are we trying to change a password of another user
+ DBUG_ASSERT(user->host.str != 0);
+ if (strcmp(thd->user, user->user.str) ||
+ my_strcasecmp(system_charset_info,
+ user->host.str, thd->host_or_ip))
+ {
+ // TODO: use check_change_password()
+ if (check_acl_user(user, &counter) && user->password.str &&
+ check_access(thd, UPDATE_ACL,"mysql",0,1,1,0))
+ {
+ my_message(ER_PASSWORD_NOT_ALLOWED,
+ ER(ER_PASSWORD_NOT_ALLOWED), MYF(0));
+ goto error;
+ }
+ }
}
}
- if (specialflag & SPECIAL_NO_RESOLVE)
+ if (first_table)
{
- LEX_USER *user;
- List_iterator <LEX_USER> user_list(lex->users_list);
- while ((user=user_list++))
+ if (lex->type == TYPE_ENUM_PROCEDURE ||
+ lex->type == TYPE_ENUM_FUNCTION)
{
- if (hostname_requires_resolving(user->host.str))
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_HOSTNAME_WONT_WORK,
- ER(ER_WARN_HOSTNAME_WONT_WORK),
- user->host.str);
+ uint grants= lex->all_privileges
+ ? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
+ : lex->grant;
+ if (grant_option &&
+ check_grant_routine(thd, grants | GRANT_ACL, all_tables,
+ lex->type == TYPE_ENUM_PROCEDURE, 0))
+ goto error;
+ res= mysql_routine_grant(thd, all_tables,
+ lex->type == TYPE_ENUM_PROCEDURE,
+ lex->users_list, grants,
+ lex->sql_command == SQLCOM_REVOKE, 0);
}
- }
- if (tables)
- {
- if (grant_option && check_grant(thd,
- (lex->grant | lex->grant_tot_col |
- GRANT_ACL),
- tables, 0, UINT_MAX, 0))
- goto error;
- if (!(res = mysql_table_grant(thd,tables,lex->users_list, lex->columns,
- lex->grant,
- lex->sql_command == SQLCOM_REVOKE)))
+ else
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ if (grant_option && check_grant(thd,
+ (lex->grant | lex->grant_tot_col |
+ GRANT_ACL),
+ all_tables, 0, UINT_MAX, 0))
+ goto error;
+ res= mysql_table_grant(thd, all_tables, lex->users_list,
+ lex->columns, lex->grant,
+ lex->sql_command == SQLCOM_REVOKE);
+ }
+ if (!res && mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
}
}
else
{
- if (lex->columns.elements)
+ if (lex->columns.elements || lex->type)
{
- send_error(thd,ER_ILLEGAL_GRANT_FOR_TABLE);
- res=1;
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
+ MYF(0));
+ goto error;
}
else
res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
if (!res)
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
- if (mqh_used && lex->sql_command == SQLCOM_GRANT)
+ if (lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
LEX_USER *user;
while ((user=str_list++))
- reset_mqh(thd,user);
+ reset_mqh(user);
}
}
}
@@ -3581,23 +3814,21 @@ purposes internal to the MySQL server", MYF(0));
}
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
case SQLCOM_RESET:
- /*
- RESET commands are never written to the binary log, so we have to
- initialize this variable because RESET shares the same code as FLUSH
+ /*
+ RESET commands are never written to the binary log, so we have to
+ initialize this variable because RESET shares the same code as FLUSH
*/
lex->no_write_to_binlog= 1;
case SQLCOM_FLUSH:
{
- if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, tables))
+ bool write_to_binlog;
+ if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, all_tables))
goto error;
/*
reload_acl_and_cache() will tell us if we are allowed to write to the
binlog or not.
*/
- bool write_to_binlog;
- if (reload_acl_and_cache(thd, lex->type, tables, &write_to_binlog))
- send_error(thd, 0);
- else
+ if (!reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog))
{
/*
We WANT to write and we CAN write.
@@ -3605,7 +3836,6 @@ purposes internal to the MySQL server", MYF(0));
*/
if (!lex->no_write_to_binlog && write_to_binlog)
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
@@ -3617,125 +3847,860 @@ purposes internal to the MySQL server", MYF(0));
break;
}
case SQLCOM_KILL:
- kill_one_thread(thd,lex->thread_id);
+ {
+ Item *it= (Item *)lex->value_list.head();
+
+ if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
+ {
+ my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
+ MYF(0));
+ goto error;
+ }
+ kill_one_thread(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
break;
+ }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_SHOW_GRANTS:
- res=0;
if ((thd->priv_user &&
!strcmp(thd->priv_user,lex->grant_user->user.str)) ||
- !check_access(thd, SELECT_ACL, "mysql",0,1,0))
+ !check_access(thd, SELECT_ACL, "mysql",0,1,0,0))
{
res = mysql_show_grants(thd,lex->grant_user);
}
break;
#endif
case SQLCOM_HA_OPEN:
- if (check_db_used(thd,tables) ||
- check_table_access(thd,SELECT_ACL, tables,0))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables) ||
+ check_table_access(thd, SELECT_ACL, all_tables, 0))
goto error;
- res = mysql_ha_open(thd, tables);
+ res= mysql_ha_open(thd, first_table, 0);
break;
case SQLCOM_HA_CLOSE:
- if (check_db_used(thd,tables))
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ if (check_db_used(thd, all_tables))
goto error;
- res = mysql_ha_close(thd, tables);
+ res= mysql_ha_close(thd, first_table);
break;
case SQLCOM_HA_READ:
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
/*
There is no need to check for table permissions here, because
if a user has no permissions to read a table, he won't be
able to open it (with SQLCOM_HA_OPEN) in the first place.
*/
- if (check_db_used(thd,tables))
+ if (check_db_used(thd, all_tables))
goto error;
- res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir,
- lex->insert_list, lex->ha_rkey_mode, select_lex->where,
- select_lex->select_limit, select_lex->offset_limit);
+ unit->set_limit(select_lex);
+ res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str,
+ lex->insert_list, lex->ha_rkey_mode, select_lex->where,
+ unit->select_limit_cnt, unit->offset_limit_cnt);
break;
case SQLCOM_BEGIN:
- if (thd->locked_tables)
+ if (begin_trans(thd))
+ goto error;
+ send_ok(thd);
+ break;
+ case SQLCOM_COMMIT:
+ if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE :
+ lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT))
+ goto error;
+ send_ok(thd);
+ break;
+ case SQLCOM_ROLLBACK:
+ if (end_trans(thd, lex->tx_release ? ROLLBACK_RELEASE :
+ lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK))
+ goto error;
+ send_ok(thd);
+ break;
+ case SQLCOM_RELEASE_SAVEPOINT:
+ {
+ SAVEPOINT *sv;
+ for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
{
- thd->lock=thd->locked_tables;
- thd->locked_tables=0; // Will be automaticly closed
- close_thread_tables(thd); // Free tables
+ if (my_strnncoll(system_charset_info,
+ (uchar *)lex->ident.str, lex->ident.length,
+ (uchar *)sv->name, sv->length) == 0)
+ break;
}
- if (end_active_trans(thd))
+ if (sv)
{
- res= -1;
+ if (ha_release_savepoint(thd, sv))
+ res= TRUE; // cannot happen
+ else
+ send_ok(thd);
+ thd->transaction.savepoints=sv->prev;
}
else
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
+ break;
+ }
+ case SQLCOM_ROLLBACK_TO_SAVEPOINT:
+ {
+ SAVEPOINT *sv;
+ for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
+ {
+ if (my_strnncoll(system_charset_info,
+ (uchar *)lex->ident.str, lex->ident.length,
+ (uchar *)sv->name, sv->length) == 0)
+ break;
+ }
+ if (sv)
{
- thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
- OPTION_BEGIN);
- thd->server_status|= SERVER_STATUS_IN_TRANS;
- if (!(lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) ||
- !(res= ha_start_consistent_snapshot(thd)))
+ if (ha_rollback_to_savepoint(thd, sv))
+ res= TRUE; // cannot happen
+ else
+ {
+ if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
+ !thd->slave_thread)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NOT_COMPLETE_ROLLBACK,
+ ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
send_ok(thd);
+ }
+ thd->transaction.savepoints=sv;
}
+ else
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
break;
- case SQLCOM_COMMIT:
- /*
- We don't use end_active_trans() here to ensure that this works
- even if there is a problem with the OPTION_AUTO_COMMIT flag
- (Which of course should never happen...)
- */
+ }
+ case SQLCOM_SAVEPOINT:
+ if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) ||
+ !opt_using_transactions)
+ send_ok(thd);
+ else
+ {
+ SAVEPOINT **sv, *newsv;
+ for (sv=&thd->transaction.savepoints; *sv; sv=&(*sv)->prev)
+ {
+ if (my_strnncoll(system_charset_info,
+ (uchar *)lex->ident.str, lex->ident.length,
+ (uchar *)(*sv)->name, (*sv)->length) == 0)
+ break;
+ }
+ if (*sv) /* old savepoint of the same name exists */
+ {
+ newsv=*sv;
+ ha_release_savepoint(thd, *sv); // it cannot fail
+ *sv=(*sv)->prev;
+ }
+ else if ((newsv=(SAVEPOINT *) alloc_root(&thd->transaction.mem_root,
+ savepoint_alloc_size)) == 0)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ break;
+ }
+ newsv->name=strmake_root(&thd->transaction.mem_root,
+ lex->ident.str, lex->ident.length);
+ newsv->length=lex->ident.length;
+ /*
+ if we'll get an error here, don't add new savepoint to the list.
+ we'll lose a little bit of memory in transaction mem_root, but it'll
+ be free'd when transaction ends anyway
+ */
+ if (ha_savepoint(thd, newsv))
+ res= TRUE;
+ else
+ {
+ newsv->prev=thd->transaction.savepoints;
+ thd->transaction.savepoints=newsv;
+ send_ok(thd);
+ }
+ }
+ break;
+ case SQLCOM_CREATE_PROCEDURE:
+ case SQLCOM_CREATE_SPFUNCTION:
{
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- if (!ha_commit(thd))
+ uint namelen;
+ char *name, *db;
+ int result;
+
+ DBUG_ASSERT(lex->sphead != 0);
+
+ if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
+ is_schema_db(lex->sphead->m_db.str)))
{
+ delete lex->sphead;
+ lex->sphead= 0;
+ goto error;
+ }
+
+ if (end_active_trans(thd))
+ goto error;
+
+ if (!lex->sphead->m_db.str || !lex->sphead->m_db.str[0])
+ {
+ lex->sphead->m_db.length= strlen(thd->db);
+ lex->sphead->m_db.str= strmake_root(thd->mem_root, thd->db,
+ lex->sphead->m_db.length);
+ }
+
+ name= lex->sphead->name(&namelen);
+#ifdef HAVE_DLOPEN
+ if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
+ {
+ udf_func *udf = find_udf(name, namelen);
+
+ if (udf)
+ {
+ my_error(ER_UDF_EXISTS, MYF(0), name);
+ delete lex->sphead;
+ lex->sphead= 0;
+ goto error;
+ }
+ }
+#endif
+ if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
+ !(lex->sphead->m_flags & sp_head::HAS_RETURN))
+ {
+ my_error(ER_SP_NORETURN, MYF(0), name);
+ delete lex->sphead;
+ lex->sphead= 0;
+ goto error;
+ }
+
+ name= thd->strdup(name);
+ db= thd->strmake(lex->sphead->m_db.str, lex->sphead->m_db.length);
+ res= (result= lex->sphead->create(thd));
+ if (result == SP_OK)
+ {
+ lex->unit.cleanup();
+ delete lex->sphead;
+ lex->sphead= 0;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* only add privileges if really neccessary */
+ if (sp_automatic_privileges && !opt_noacl &&
+ check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
+ db, name,
+ lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
+ {
+ close_thread_tables(thd);
+ if (sp_grant_privileges(thd, db, name,
+ lex->sql_command == SQLCOM_CREATE_PROCEDURE))
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_PROC_AUTO_GRANT_FAIL,
+ ER(ER_PROC_AUTO_GRANT_FAIL));
+ }
+#endif
send_ok(thd);
}
else
- res= -1;
+ {
+ switch (result) {
+ case SP_WRITE_ROW_FAILED:
+ my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
+ break;
+ case SP_NO_DB_ERROR:
+ my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
+ break;
+ case SP_BAD_IDENTIFIER:
+ my_error(ER_TOO_LONG_IDENT, MYF(0), name);
+ break;
+ case SP_BODY_TOO_LONG:
+ my_error(ER_TOO_LONG_BODY, MYF(0), name);
+ break;
+ default:
+ my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
+ break;
+ }
+ lex->unit.cleanup();
+ delete lex->sphead;
+ lex->sphead= 0;
+ goto error;
+ }
break;
}
- case SQLCOM_ROLLBACK:
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- if (!ha_rollback(thd))
+ case SQLCOM_CALL:
{
+ sp_head *sp;
+
+ /*
+ This will cache all SP and SF and open and lock all tables
+ required for execution.
+ */
+ if (check_table_access(thd, SELECT_ACL, all_tables, 0) ||
+ open_and_lock_tables(thd, all_tables))
+ goto error;
+
/*
- If a non-transactional table was updated, warn; don't warn if this is a
- slave thread (because when a slave thread executes a ROLLBACK, it has
- been read from the binary log, so it's 100% sure and normal to produce
- error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
- slave SQL thread, it would not stop the thread but just be printed in
- the error log; but we don't want users to wonder why they have this
- message in the error log, so we don't send it.
+ By this moment all needed SPs should be in cache so no need to look
+ into DB.
*/
- if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
- send_warning(thd,ER_WARNING_NOT_COMPLETE_ROLLBACK,0);
+ if (!(sp= sp_find_procedure(thd, lex->spname, TRUE)))
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
+ lex->spname->m_qname.str);
+ goto error;
+ }
+ else
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ st_sp_security_context save_ctx;
+#endif
+ ha_rows select_limit;
+ /* bits that should be cleared in thd->server_status */
+ uint bits_to_be_cleared= 0;
+ /*
+ Check that the stored procedure doesn't contain Dynamic SQL
+ and doesn't return result sets: such stored procedures can't
+ be called from a function or trigger.
+ */
+ if (thd->in_sub_stmt)
+ {
+ const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ?
+ "trigger" : "function");
+ if (sp->is_not_allowed_in_function(where))
+ goto error;
+ }
+
+#ifndef EMBEDDED_LIBRARY
+ my_bool nsok= thd->net.no_send_ok;
+ thd->net.no_send_ok= TRUE;
+#endif
+ if (sp->m_flags & sp_head::MULTI_RESULTS)
+ {
+ if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
+ {
+ /*
+ The client does not support multiple result sets being sent
+ back
+ */
+ my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
+#ifndef EMBEDDED_LIBRARY
+ thd->net.no_send_ok= nsok;
+#endif
+ goto error;
+ }
+ /*
+ If SERVER_MORE_RESULTS_EXISTS is not set,
+ then remember that it should be cleared
+ */
+ bits_to_be_cleared= (~thd->server_status &
+ SERVER_MORE_RESULTS_EXISTS);
+ thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (check_routine_access(thd, EXECUTE_ACL,
+ sp->m_db.str, sp->m_name.str, TRUE, 0))
+ {
+#ifndef EMBEDDED_LIBRARY
+ thd->net.no_send_ok= nsok;
+#endif
+ goto error;
+ }
+ sp_change_security_context(thd, sp, &save_ctx);
+ if (save_ctx.changed &&
+ check_routine_access(thd, EXECUTE_ACL,
+ sp->m_db.str, sp->m_name.str, TRUE, 0))
+ {
+#ifndef EMBEDDED_LIBRARY
+ thd->net.no_send_ok= nsok;
+#endif
+ sp_restore_security_context(thd, sp, &save_ctx);
+ goto error;
+ }
+
+#endif
+ select_limit= thd->variables.select_limit;
+ thd->variables.select_limit= HA_POS_ERROR;
+
+ thd->row_count_func= 0;
+
+ /*
+ We never write CALL statements into binlog:
+ - If the mode is non-prelocked, each statement will be logged
+ separately.
+ - If the mode is prelocked, the invoking statement will care
+ about writing into binlog.
+ So just execute the statement.
+ */
+ res= sp->execute_procedure(thd, &lex->value_list);
+ if (mysql_bin_log.is_open() &&
+ (sp->m_chistics->daccess == SP_CONTAINS_SQL ||
+ sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA))
+ {
+ if (res)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_FAILED_ROUTINE_BREAK_BINLOG,
+ ER(ER_FAILED_ROUTINE_BREAK_BINLOG));
+ else
+ thd->clear_error();
+ }
+
+ /*
+ If warnings have been cleared, we have to clear total_warn_count
+ too, otherwise the clients get confused.
+ */
+ if (thd->warn_list.is_empty())
+ thd->total_warn_count= 0;
+
+ thd->variables.select_limit= select_limit;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ sp_restore_security_context(thd, sp, &save_ctx);
+#endif
+
+#ifndef EMBEDDED_LIBRARY
+ thd->net.no_send_ok= nsok;
+#endif
+ thd->server_status&= ~bits_to_be_cleared;
+
+ if (!res)
+ send_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 :
+ thd->row_count_func));
+ else
+ goto error; // Substatement should already have sent error
+ }
+ break;
+ }
+ case SQLCOM_ALTER_PROCEDURE:
+ case SQLCOM_ALTER_FUNCTION:
+ {
+ int result;
+ sp_head *sp;
+ st_sp_chistics chistics;
+
+ memcpy(&chistics, &lex->sp_chistics, sizeof(chistics));
+ if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
+ sp= sp_find_procedure(thd, lex->spname);
+ else
+ sp= sp_find_function(thd, lex->spname);
+ mysql_reset_errors(thd, 0);
+ if (! sp)
+ {
+ if (lex->spname->m_db.str)
+ result= SP_KEY_NOT_FOUND;
+ else
+ {
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
+ goto error;
+ }
+ }
else
+ {
+ if (check_routine_access(thd, ALTER_PROC_ACL, sp->m_db.str,
+ sp->m_name.str,
+ lex->sql_command == SQLCOM_ALTER_PROCEDURE, 0))
+ goto error;
+
+ if (end_active_trans(thd))
+ goto error;
+ memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics));
+ if (!trust_routine_creators && mysql_bin_log.is_open() &&
+ !sp->m_chistics->detistic &&
+ (chistics.daccess == SP_CONTAINS_SQL ||
+ chistics.daccess == SP_MODIFIES_SQL_DATA))
+ {
+ my_message(ER_BINLOG_UNSAFE_ROUTINE,
+ ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
+ result= SP_INTERNAL_ERROR;
+ }
+ else
+ {
+ if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
+ result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
+ else
+ result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
+ }
+ }
+ switch (result)
+ {
+ case SP_OK:
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
send_ok(thd);
+ break;
+ case SP_KEY_NOT_FOUND:
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_qname.str);
+ goto error;
+ default:
+ my_error(ER_SP_CANT_ALTER, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_qname.str);
+ goto error;
+ }
+ break;
+ }
+ case SQLCOM_DROP_PROCEDURE:
+ case SQLCOM_DROP_FUNCTION:
+ {
+ sp_head *sp;
+ int result;
+ char *db, *name;
+
+ if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
+ sp= sp_find_procedure(thd, lex->spname);
+ else
+ sp= sp_find_function(thd, lex->spname);
+ mysql_reset_errors(thd, 0);
+ if (sp)
+ {
+ db= thd->strdup(sp->m_db.str);
+ name= thd->strdup(sp->m_name.str);
+ if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
+ lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
+ goto error;
+
+ if (end_active_trans(thd))
+ goto error;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (sp_automatic_privileges && !opt_noacl &&
+ sp_revoke_privileges(thd, db, name,
+ lex->sql_command == SQLCOM_DROP_PROCEDURE))
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_PROC_AUTO_REVOKE_FAIL,
+ ER(ER_PROC_AUTO_REVOKE_FAIL));
+ }
+#endif
+ if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
+ result= sp_drop_procedure(thd, lex->spname);
+ else
+ result= sp_drop_function(thd, lex->spname);
+ }
+ else
+ {
+#ifdef HAVE_DLOPEN
+ if (lex->sql_command == SQLCOM_DROP_FUNCTION)
+ {
+ udf_func *udf = find_udf(lex->spname->m_name.str,
+ lex->spname->m_name.length);
+ if (udf)
+ {
+ if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0))
+ goto error;
+ if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
+ {
+ send_ok(thd);
+ break;
+ }
+ }
+ }
+#endif
+ if (lex->spname->m_db.str)
+ result= SP_KEY_NOT_FOUND;
+ else
+ {
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
+ goto error;
+ }
+ }
+ res= result;
+ switch (result)
+ {
+ case SP_OK:
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd);
+ break;
+ case SP_KEY_NOT_FOUND:
+ if (lex->drop_if_exists)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
+ SP_COM_STRING(lex), lex->spname->m_name.str);
+ res= FALSE;
+ send_ok(thd);
+ break;
+ }
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_qname.str);
+ goto error;
+ default:
+ my_error(ER_SP_DROP_FAILED, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_qname.str);
+ goto error;
+ }
+ break;
+ }
+ case SQLCOM_SHOW_CREATE_PROC:
+ {
+ if (lex->spname->m_name.length > NAME_LEN)
+ {
+ my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
+ goto error;
+ }
+ if (sp_show_create_procedure(thd, lex->spname) != SP_OK)
+ { /* We don't distinguish between errors for now */
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_name.str);
+ goto error;
+ }
+ break;
+ }
+ case SQLCOM_SHOW_CREATE_FUNC:
+ {
+ if (lex->spname->m_name.length > NAME_LEN)
+ {
+ my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
+ goto error;
+ }
+ if (sp_show_create_function(thd, lex->spname) != SP_OK)
+ { /* We don't distinguish between errors for now */
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_name.str);
+ goto error;
+ }
+ break;
+ }
+ case SQLCOM_SHOW_STATUS_PROC:
+ {
+ res= sp_show_status_procedure(thd, (lex->wild ?
+ lex->wild->ptr() : NullS));
+ break;
+ }
+ case SQLCOM_SHOW_STATUS_FUNC:
+ {
+ res= sp_show_status_function(thd, (lex->wild ?
+ lex->wild->ptr() : NullS));
+ break;
+ }
+ case SQLCOM_CREATE_VIEW:
+ {
+ if (!(res= mysql_create_view(thd, thd->lex->create_view_mode)) &&
+ mysql_bin_log.is_open())
+ {
+ String buff;
+ LEX_STRING command[3]=
+ {{STRING_WITH_LEN("CREATE ")},
+ {STRING_WITH_LEN("ALTER ")},
+ {STRING_WITH_LEN("CREATE OR REPLACE ")}};
+ thd->clear_error();
+
+ buff.append(command[thd->lex->create_view_mode].str,
+ command[thd->lex->create_view_mode].length);
+ view_store_options(thd, first_table, &buff);
+ buff.append("VIEW ", 5);
+ if (!first_table->current_db_used)
+ {
+ append_identifier(thd, &buff, first_table->db,
+ first_table->db_length);
+ buff.append('.');
+ }
+ append_identifier(thd, &buff, first_table->table_name,
+ first_table->table_name_length);
+ buff.append(" AS ", 4);
+ buff.append(first_table->source.str, first_table->source.length);
+
+ Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ break;
+ }
+ case SQLCOM_DROP_VIEW:
+ {
+ if (check_table_access(thd, DROP_ACL, all_tables, 0) ||
+ end_active_trans(thd))
+ goto error;
+ if (!(res= mysql_drop_view(thd, first_table, thd->lex->drop_mode)) &&
+ mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ break;
+ }
+ case SQLCOM_CREATE_TRIGGER:
+ {
+ res= mysql_create_or_drop_trigger(thd, all_tables, 1);
+
+ /* We don't care about trigger body after this point */
+ delete lex->sphead;
+ lex->sphead= 0;
+ break;
+ }
+ case SQLCOM_DROP_TRIGGER:
+ {
+ res= mysql_create_or_drop_trigger(thd, all_tables, 0);
+ break;
+ }
+ case SQLCOM_XA_START:
+ if (thd->transaction.xid_state.xa_state == XA_IDLE &&
+ thd->lex->xa_opt == XA_RESUME)
+ {
+ if (! thd->transaction.xid_state.xid.eq(thd->lex->xid))
+ {
+ my_error(ER_XAER_NOTA, MYF(0));
+ break;
+ }
+ thd->transaction.xid_state.xa_state=XA_ACTIVE;
+ send_ok(thd);
+ break;
+ }
+ if (thd->lex->xa_opt != XA_NONE)
+ { // JOIN is not supported yet. TODO
+ my_error(ER_XAER_INVAL, MYF(0));
+ break;
+ }
+ if (thd->transaction.xid_state.xa_state != XA_NOTR)
+ {
+ my_error(ER_XAER_RMFAIL, MYF(0),
+ xa_state_names[thd->transaction.xid_state.xa_state]);
+ break;
+ }
+ if (thd->active_transaction() || thd->locked_tables)
+ {
+ my_error(ER_XAER_OUTSIDE, MYF(0));
+ break;
+ }
+ if (xid_cache_search(thd->lex->xid))
+ {
+ my_error(ER_XAER_DUPID, MYF(0));
+ break;
+ }
+ DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
+ thd->transaction.xid_state.xa_state=XA_ACTIVE;
+ thd->transaction.xid_state.xid.set(thd->lex->xid);
+ xid_cache_insert(&thd->transaction.xid_state);
+ thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
+ OPTION_BEGIN);
+ thd->server_status|= SERVER_STATUS_IN_TRANS;
+ send_ok(thd);
+ break;
+ case SQLCOM_XA_END:
+ /* fake it */
+ if (thd->lex->xa_opt != XA_NONE)
+ { // SUSPEND and FOR MIGRATE are not supported yet. TODO
+ my_error(ER_XAER_INVAL, MYF(0));
+ break;
+ }
+ if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
+ {
+ my_error(ER_XAER_RMFAIL, MYF(0),
+ xa_state_names[thd->transaction.xid_state.xa_state]);
+ break;
+ }
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+ {
+ my_error(ER_XAER_NOTA, MYF(0));
+ break;
+ }
+ thd->transaction.xid_state.xa_state=XA_IDLE;
+ send_ok(thd);
+ break;
+ case SQLCOM_XA_PREPARE:
+ if (thd->transaction.xid_state.xa_state != XA_IDLE)
+ {
+ my_error(ER_XAER_RMFAIL, MYF(0),
+ xa_state_names[thd->transaction.xid_state.xa_state]);
+ break;
+ }
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+ {
+ my_error(ER_XAER_NOTA, MYF(0));
+ break;
+ }
+ if (ha_prepare(thd))
+ {
+ my_error(ER_XA_RBROLLBACK, MYF(0));
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state=XA_NOTR;
+ break;
+ }
+ thd->transaction.xid_state.xa_state=XA_PREPARED;
+ send_ok(thd);
+ break;
+ case SQLCOM_XA_COMMIT:
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+ {
+ XID_STATE *xs=xid_cache_search(thd->lex->xid);
+ if (!xs || xs->in_thd)
+ my_error(ER_XAER_NOTA, MYF(0));
+ else
+ {
+ ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
+ xid_cache_delete(xs);
+ send_ok(thd);
+ }
+ break;
+ }
+ if (thd->transaction.xid_state.xa_state == XA_IDLE &&
+ thd->lex->xa_opt == XA_ONE_PHASE)
+ {
+ int r;
+ if ((r= ha_commit(thd)))
+ my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
+ else
+ send_ok(thd);
+ }
+ else if (thd->transaction.xid_state.xa_state == XA_PREPARED &&
+ thd->lex->xa_opt == XA_NONE)
+ {
+ if (wait_if_global_read_lock(thd, 0, 0))
+ {
+ ha_rollback(thd);
+ my_error(ER_XAER_RMERR, MYF(0));
+ }
+ else
+ {
+ if (ha_commit_one_phase(thd, 1))
+ my_error(ER_XAER_RMERR, MYF(0));
+ else
+ send_ok(thd);
+ start_waiting_global_read_lock(thd);
+ }
}
else
- res= -1;
+ {
+ my_error(ER_XAER_RMFAIL, MYF(0),
+ xa_state_names[thd->transaction.xid_state.xa_state]);
+ break;
+ }
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state=XA_NOTR;
break;
- case SQLCOM_ROLLBACK_TO_SAVEPOINT:
- if (!ha_rollback_to_savepoint(thd, lex->savepoint_name))
+ case SQLCOM_XA_ROLLBACK:
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
- if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
- send_warning(thd, ER_WARNING_NOT_COMPLETE_ROLLBACK, 0);
+ XID_STATE *xs=xid_cache_search(thd->lex->xid);
+ if (!xs || xs->in_thd)
+ my_error(ER_XAER_NOTA, MYF(0));
else
- send_ok(thd);
+ {
+ ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
+ xid_cache_delete(xs);
+ send_ok(thd);
+ }
+ break;
}
+ if (thd->transaction.xid_state.xa_state != XA_IDLE &&
+ thd->transaction.xid_state.xa_state != XA_PREPARED)
+ {
+ my_error(ER_XAER_RMFAIL, MYF(0),
+ xa_state_names[thd->transaction.xid_state.xa_state]);
+ break;
+ }
+ if (ha_rollback(thd))
+ my_error(ER_XAER_RMERR, MYF(0));
else
- res= -1;
- break;
- case SQLCOM_SAVEPOINT:
- if (!ha_savepoint(thd, lex->savepoint_name))
send_ok(thd);
- else
- res= -1;
+ thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state=XA_NOTR;
break;
- default: /* Impossible */
+ case SQLCOM_XA_RECOVER:
+ res= mysql_xa_recover(thd);
+ break;
+ default:
+ DBUG_ASSERT(0); /* Impossible */
send_ok(thd);
break;
}
- thd->proc_info="query end"; // QQ
+ thd->proc_info="query end";
+ /* Two binlog-related cleanups: */
/*
Reset system variables temporarily modified by SET ONE SHOT.
@@ -3749,10 +4714,20 @@ purposes internal to the MySQL server", MYF(0));
if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION)
reset_one_shot_variables(thd);
- if (res < 0)
- send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
+
+ /*
+ The return value for ROW_COUNT() is "implementation dependent" if
+ the statement is not DELETE, INSERT or UPDATE (or a CALL executing
+ such a statement), but -1 is what JDBC and ODBC wants.
+ */
+ if (lex->sql_command != SQLCOM_CALL && uc_update_queries[lex->sql_command]<2)
+ thd->row_count_func= -1;
+ goto cleanup;
error:
+ res= 1;
+
+cleanup:
if (unlikely(slave_fake_lock))
{
DBUG_PRINT("info",("undoing faked lock"));
@@ -3761,7 +4736,7 @@ error:
if (thd->lock == thd->locked_tables)
thd->lock= 0;
}
- DBUG_VOID_RETURN;
+ DBUG_RETURN(res || thd->net.report_error);
}
@@ -3772,28 +4747,30 @@ error:
SYNOPSIS
check_one_table_access()
thd Thread handler
- privilege requested privelage
- tables table list of command
+ privilege requested privilege
+ all_tables global table list of query
RETURN
0 - OK
1 - access denied, error is sent to client
*/
-int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables)
+bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
{
- if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0))
+ if (check_access(thd, privilege, all_tables->db,
+ &all_tables->grant.privilege, 0, 0,
+ test(all_tables->schema_table)))
return 1;
/* Show only 1 table for check_grant */
- if (grant_option && check_grant(thd, privilege, tables, 0, 1, 0))
+ if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0))
return 1;
/* Check rights on tables of subselects and implictly opened tables */
TABLE_LIST *subselects_tables;
- if ((subselects_tables= tables->next))
+ if ((subselects_tables= all_tables->next_global))
{
- if ((check_table_access(thd, SELECT_ACL, subselects_tables,0)))
+ if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
return 1;
}
return 0;
@@ -3821,16 +4798,17 @@ int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables)
bool
check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
- bool dont_check_global_grants, bool no_errors)
+ bool dont_check_global_grants, bool no_errors, bool schema_db)
{
- DBUG_ENTER("check_access");
- DBUG_PRINT("enter",("db: '%s' want_access: %lu master_access: %lu",
- db ? db : "", want_access, thd->master_access));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
ulong db_access;
bool db_is_pattern= test(want_access & GRANT_ACL);
#endif
ulong dummy;
+ const char *db_name;
+ DBUG_ENTER("check_access");
+ DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu",
+ db ? db : "", want_access, thd->master_access));
if (save_priv)
*save_priv=0;
else
@@ -3838,11 +4816,30 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
{
+ DBUG_PRINT("error",("No database"));
if (!no_errors)
- send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
+ MYF(0)); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
+ db_name= db ? db : thd->db;
+ if (schema_db)
+ {
+ if (want_access & ~(SELECT_ACL | EXTRA_ACL))
+ {
+ if (!no_errors)
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user, thd->priv_host, db_name);
+ DBUG_RETURN(TRUE);
+ }
+ else
+ {
+ *save_priv= SELECT_ACL;
+ DBUG_RETURN(FALSE);
+ }
+ }
+
#ifdef NO_EMBEDDED_ACCESS_CHECKS
DBUG_RETURN(0);
#else
@@ -3863,11 +4860,14 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
! db && dont_check_global_grants)
{ // We can never grant this
+ DBUG_PRINT("error",("No possible access"));
if (!no_errors)
- net_printf(thd,ER_ACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
+ my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user,
+ thd->priv_host,
+ (thd->password ?
+ ER(ER_YES) :
+ ER(ER_NO))); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
@@ -3881,18 +4881,24 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_PRINT("info",("db_access: %lu", db_access));
/* Remove SHOW attribute and access rights we already have */
want_access &= ~(thd->master_access | EXTRA_ACL);
+ DBUG_PRINT("info",("db_access: %lu want_access: %lu",
+ db_access, want_access));
db_access= ((*save_priv=(db_access | thd->master_access)) & want_access);
/* grant_option is set if there exists a single table or column grant */
if (db_access == want_access ||
- ((grant_option && !dont_check_global_grants) &&
- !(want_access & ~(db_access | TABLE_ACLS))))
+ (grant_option && !dont_check_global_grants &&
+ !(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS))))
DBUG_RETURN(FALSE); /* Ok */
+
+ DBUG_PRINT("error",("Access denied"));
if (!no_errors)
- net_printf(thd,ER_DBACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user,
+ thd->priv_host,
+ (db ? db : (thd->db ?
+ thd->db :
+ "unknown"))); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
@@ -3907,7 +4913,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
want_access Use should have any of these global rights
WARNING
- One gets access rigth if one has ANY of the rights in want_access
+ One gets access right if one has ANY of the rights in want_access
This is useful as one in most cases only need one global right,
but in some case we want to check if the user has SUPER or
REPL_CLIENT_ACL rights.
@@ -3926,8 +4932,7 @@ bool check_global_access(THD *thd, ulong want_access)
if ((thd->master_access & want_access))
return 0;
get_privilege_desc(command, sizeof(command), want_access);
- net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR,
- command);
+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command);
return 1;
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
@@ -3945,10 +4950,19 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
uint found=0;
ulong found_access=0;
TABLE_LIST *org_tables=tables;
- for (; tables ; tables=tables->next)
+ for (; tables; tables= tables->next_global)
{
- if (tables->derived ||
- (tables->table && (int)tables->table->tmp_table) ||
+ if (tables->schema_table &&
+ (want_access & ~(SELECT_ACL | EXTRA_ACL)))
+ {
+ if (!no_errors)
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user, thd->priv_host,
+ information_schema_name.str);
+ return TRUE;
+ }
+ if (tables->derived || tables->schema_table || tables->belong_to_view ||
+ (tables->table && (int)tables->table->s->tmp_table) ||
my_tz_check_n_skip_implicit_tables(&tables,
thd->lex->time_zone_tables_used))
continue;
@@ -3962,14 +4976,14 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
else
{
if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
- 0, no_errors))
+ 0, no_errors, test(tables->schema_table)))
return TRUE; // Access denied
found_access=tables->grant.privilege;
found=1;
}
}
else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
- 0, no_errors))
+ 0, no_errors, test(tables->schema_table)))
return TRUE;
}
if (grant_option)
@@ -3978,6 +4992,99 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
return FALSE;
}
+
+bool
+check_routine_access(THD *thd, ulong want_access,char *db, char *name,
+ bool is_proc, bool no_errors)
+{
+ TABLE_LIST tables[1];
+
+ bzero((char *)tables, sizeof(TABLE_LIST));
+ tables->db= db;
+ tables->table_name= tables->alias= name;
+
+ if ((thd->master_access & want_access) == want_access && !thd->db)
+ tables->grant.privilege= want_access;
+ else if (check_access(thd,want_access,db,&tables->grant.privilege,
+ 0, no_errors, test(tables->schema_table)))
+ return TRUE;
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (grant_option)
+ return check_grant_routine(thd, want_access, tables, is_proc, no_errors);
+#endif
+
+ return FALSE;
+}
+
+
+/*
+ Check if the routine has any of the routine privileges
+
+ SYNOPSIS
+ check_some_routine_access()
+ thd Thread handler
+ db Database name
+ name Routine name
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool check_some_routine_access(THD *thd, const char *db, const char *name,
+ bool is_proc)
+{
+ ulong save_priv;
+ if (thd->master_access & SHOW_PROC_ACLS)
+ return FALSE;
+ /*
+ There are no routines in information_schema db. So we can safely
+ pass zero to last paramter of check_access function
+ */
+ if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1, 0) ||
+ (save_priv & SHOW_PROC_ACLS))
+ return FALSE;
+ return check_routine_level_acl(thd, db, name, is_proc);
+}
+
+
+/*
+ Check if the given table has any of the asked privileges
+
+ SYNOPSIS
+ check_some_access()
+ thd Thread handler
+ want_access Bitmap of possible privileges to check for
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+
+bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
+{
+ ulong access;
+ DBUG_ENTER("check_some_access");
+
+ /* This loop will work as long as we have less than 32 privileges */
+ for (access= 1; access < want_access ; access<<= 1)
+ {
+ if (access & want_access)
+ {
+ if (!check_access(thd, access, table->db,
+ &table->grant.privilege, 0, 1,
+ test(table->schema_table)) &&
+ !grant_option || !check_grant(thd, access, table, 0, 1, 1))
+ DBUG_RETURN(0);
+ }
+ }
+ DBUG_PRINT("exit",("no matching access rights"));
+ DBUG_RETURN(1);
+}
+
+
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list)
{
@@ -3986,7 +5093,7 @@ bool check_merge_table_access(THD *thd, char *db,
{
/* Check that all tables use the current database */
TABLE_LIST *tmp;
- for (tmp=table_list; tmp ; tmp=tmp->next)
+ for (tmp= table_list; tmp; tmp= tmp->next_local)
{
if (!tmp->db || !tmp->db[0])
tmp->db=db;
@@ -4000,13 +5107,14 @@ bool check_merge_table_access(THD *thd, char *db,
static bool check_db_used(THD *thd,TABLE_LIST *tables)
{
- for (; tables ; tables=tables->next)
+ for (; tables; tables= tables->next_global)
{
if (!tables->db)
{
if (!(tables->db=thd->db))
{
- send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
+ MYF(0)); /* purecov: tested */
return TRUE; /* purecov: tested */
}
}
@@ -4014,6 +5122,7 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables)
return FALSE;
}
+
/****************************************************************************
Check stack size; Send error if there isn't enough stack to continue
****************************************************************************/
@@ -4029,14 +5138,22 @@ long max_stack_used;
#endif
#ifndef EMBEDDED_LIBRARY
-bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
+/*
+ Note: The 'buf' parameter is necessary, even if it is unused here.
+ - fix_fields functions has a "dummy" buffer large enough for the
+ corresponding exec. (Thus we only have to check in fix_fields.)
+ - Passing to check_stack_overrun() prevents the compiler from removing it.
+ */
+bool check_stack_overrun(THD *thd, long margin,
+ char *buf __attribute__((unused)))
{
long stack_used;
if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
- (long) thread_stack_min)
+ (long) (thread_stack - margin))
{
- sprintf(errbuff[0],ER(ER_STACK_OVERRUN),stack_used,thread_stack);
- my_message(ER_STACK_OVERRUN,errbuff[0],MYF(0));
+ sprintf(errbuff[0],ER(ER_STACK_OVERRUN_NEED_MORE),
+ stack_used,thread_stack,margin);
+ my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(0));
thd->fatal_error();
return 1;
}
@@ -4078,6 +5195,7 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
return 0;
}
+
/****************************************************************************
Initialize global thd variables needed for query
****************************************************************************/
@@ -4110,17 +5228,24 @@ void mysql_reset_thd_for_next_command(THD *thd)
DBUG_ENTER("mysql_reset_thd_for_next_command");
thd->free_list= 0;
thd->select_number= 1;
- 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= thd->time_zone_used= 0;
+ thd->is_fatal_error= thd->time_zone_used= 0;
thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
- SERVER_QUERY_NO_INDEX_USED |
- SERVER_QUERY_NO_GOOD_INDEX_USED);
+ SERVER_QUERY_NO_INDEX_USED |
+ SERVER_QUERY_NO_GOOD_INDEX_USED);
thd->tmp_table_used= 0;
- if (opt_bin_log)
- reset_dynamic(&thd->user_var_events);
- thd->clear_error();
+ if (!thd->in_sub_stmt)
+ {
+ if (opt_bin_log)
+ {
+ reset_dynamic(&thd->user_var_events);
+ thd->user_var_events_alloc= thd->mem_root;
+ }
+ thd->clear_error();
+ thd->total_warn_count=0; // Warnings for this query
+ thd->rand_used= 0;
+ thd->sent_row_count= thd->examined_row_count= 0;
+ }
DBUG_VOID_RETURN;
}
@@ -4130,7 +5255,7 @@ mysql_init_select(LEX *lex)
{
SELECT_LEX *select_lex= lex->current_select;
select_lex->init_select();
- select_lex->select_limit= HA_POS_ERROR;
+ lex->wild= 0;
if (select_lex == &lex->select_lex)
{
DBUG_ASSERT(lex->result == 0);
@@ -4143,9 +5268,13 @@ bool
mysql_new_select(LEX *lex, bool move_down)
{
SELECT_LEX *select_lex;
- if (!(select_lex= new(lex->thd->mem_root) SELECT_LEX()))
- return 1;
- select_lex->select_number= ++lex->thd->select_number;
+ THD *thd= lex->thd;
+ DBUG_ENTER("mysql_new_select");
+
+ if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
+ DBUG_RETURN(1);
+ select_lex->select_number= ++thd->select_number;
+ select_lex->parent_lex= lex; /* Used in init_query. */
select_lex->init_query();
select_lex->init_select();
/*
@@ -4153,30 +5282,45 @@ mysql_new_select(LEX *lex, bool move_down)
it's a constant one. The flag is switched off in the end of
mysql_stmt_prepare.
*/
- if (lex->thd->current_arena->is_stmt_prepare())
+ if (thd->stmt_arena->is_stmt_prepare())
select_lex->uncacheable|= UNCACHEABLE_PREPARE;
-
if (move_down)
{
+ SELECT_LEX_UNIT *unit;
lex->subqueries= TRUE;
/* first select_lex of subselect or derived table */
- SELECT_LEX_UNIT *unit;
- if (!(unit= new(lex->thd->mem_root) SELECT_LEX_UNIT()))
- return 1;
+ if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
+ DBUG_RETURN(1);
unit->init_query();
unit->init_select();
- unit->thd= lex->thd;
+ unit->thd= thd;
unit->include_down(lex->current_select);
unit->link_next= 0;
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
+ /*
+ By default we assume that it is usual subselect and we have outer name
+ resolution context, if no we will assign it to 0 later
+ */
+ select_lex->context.outer_context= &select_lex->outer_select()->context;
}
else
{
+ Name_resolution_context *outer_context;
+ if (lex->current_select->order_list.first && !lex->current_select->braces)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
+ DBUG_RETURN(1);
+ }
select_lex->include_neighbour(lex->current_select);
+ /*
+ we are not sure that we have one level of SELECTs above, so we take
+ outer_context address from first select of unit
+ */
+ outer_context=
+ select_lex->master_unit()->first_select()->context.outer_context;
SELECT_LEX_UNIT *unit= select_lex->master_unit();
SELECT_LEX *fake= unit->fake_select_lex;
if (!fake)
@@ -4185,22 +5329,38 @@ mysql_new_select(LEX *lex, bool move_down)
as far as we included SELECT_LEX for UNION unit should have
fake SELECT_LEX for UNION processing
*/
- if (!(fake= unit->fake_select_lex= new(lex->thd->mem_root) SELECT_LEX()))
- return 1;
+ if (!(fake= unit->fake_select_lex= new (thd->mem_root) SELECT_LEX()))
+ DBUG_RETURN(1);
fake->include_standalone(unit,
(SELECT_LEX_NODE**)&unit->fake_select_lex);
fake->select_number= INT_MAX;
+ fake->parent_lex= lex; /* Used in init_query. */
fake->make_empty_select();
fake->linkage= GLOBAL_OPTIONS_TYPE;
- fake->select_limit= HA_POS_ERROR;
+ fake->select_limit= 0;
+
+ fake->context.outer_context= outer_context;
+ /* allow item list resolving in fake select for ORDER BY */
+ fake->context.resolve_in_select_list= TRUE;
+ fake->context.select_lex= fake;
+ /*
+ Remove the name resolution context of the fake select from the
+ context stack.
+ */
+ lex->pop_context();
}
+ select_lex->context.outer_context= outer_context;
}
select_lex->master_unit()->global_parameters= select_lex;
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
lex->current_select= select_lex;
- select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
- return 0;
+ /*
+ in subquery is SELECT query and we allow resolution of names in SELECT
+ list
+ */
+ select_lex->context.resolve_in_select_list= TRUE;
+ DBUG_RETURN(0);
}
/*
@@ -4245,49 +5405,17 @@ void create_select_for_variable(const char *var_name)
DBUG_VOID_RETURN;
}
-static TABLE_LIST* get_table_by_alias(TABLE_LIST* tl, const char* db,
- const char* alias)
-{
- for (;tl;tl= tl->next)
- {
- if (!strcmp(db,tl->db) &&
- tl->alias && !my_strcasecmp(table_alias_charset,tl->alias,alias))
- return tl;
- }
-
- return 0;
-}
-
-/* Sets up lex->auxilliary_table_list */
-void fix_multi_delete_lex(LEX* lex)
-{
- TABLE_LIST *tl;
- TABLE_LIST *good_list= (TABLE_LIST*)lex->select_lex.table_list.first;
-
- for (tl= (TABLE_LIST*)lex->auxilliary_table_list.first; tl; tl= tl->next)
- {
- TABLE_LIST* good_table= get_table_by_alias(good_list,tl->db,tl->alias);
- if (good_table && !good_table->derived)
- {
- /*
- real_name points to a member of Table_ident which is
- allocated via thd->strmake() from THD memroot
- */
- tl->real_name= good_table->real_name;
- tl->real_name_length= good_table->real_name_length;
- good_table->updating= tl->updating;
- }
- }
-}
void mysql_init_multi_delete(LEX *lex)
{
lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex);
- lex->select_lex.select_limit= lex->unit.select_limit_cnt=
- HA_POS_ERROR;
+ lex->select_lex.select_limit= 0;
+ lex->unit.select_limit_cnt= HA_POS_ERROR;
lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list);
lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ;
+ lex->query_tables= 0;
+ lex->query_tables_last= &lex->query_tables;
}
@@ -4299,11 +5427,14 @@ void mysql_init_multi_delete(LEX *lex)
void mysql_parse(THD *thd, char *inBuf, uint length)
{
DBUG_ENTER("mysql_parse");
-
mysql_init_query(thd, (uchar*) inBuf, length);
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
{
LEX *lex= thd->lex;
+
+ sp_cache_flush_obsolete(&thd->sp_proc_cache);
+ sp_cache_flush_obsolete(&thd->sp_func_cache);
+
if (!yyparse((void *)thd) && ! thd->is_fatal_error)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -4316,7 +5447,13 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
#endif
{
if (thd->net.report_error)
- send_error(thd, 0, NullS);
+ {
+ if (thd->lex->sphead)
+ {
+ delete thd->lex->sphead;
+ thd->lex->sphead= NULL;
+ }
+ }
else
{
/*
@@ -4329,23 +5466,32 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
PROCESSLIST.
Note that we don't need LOCK_thread_count to modify query_length.
*/
- if (lex->found_colon &&
- (thd->query_length= (ulong)(lex->found_colon - thd->query)))
+ if (lex->found_semicolon &&
+ (thd->query_length= (ulong)(lex->found_semicolon - thd->query)))
thd->query_length--;
/* Actually execute the query */
mysql_execute_command(thd);
query_cache_end_of_result(thd);
}
}
+ lex->unit.cleanup();
}
else
{
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error));
query_cache_abort(&thd->net);
+ lex->unit.cleanup();
+ if (thd->lex->sphead)
+ {
+ /* Clean up after failed stored procedure/function */
+ delete thd->lex->sphead;
+ thd->lex->sphead= NULL;
+ }
}
thd->proc_info="freeing items";
thd->end_statement();
+ thd->cleanup_after_query();
DBUG_ASSERT(thd->change_list.is_empty());
}
DBUG_VOID_RETURN;
@@ -4366,17 +5512,20 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
{
LEX *lex= thd->lex;
bool error= 0;
+ DBUG_ENTER("mysql_test_parse_for_slave");
mysql_init_query(thd, (uchar*) inBuf, length);
if (!yyparse((void*) thd) && ! thd->is_fatal_error &&
all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
- error= 1; /* Ignore question */
+ error= 1; /* Ignore question */
thd->end_statement();
- return error;
+ thd->cleanup_after_query();
+ DBUG_RETURN(error);
}
#endif
+
/*****************************************************************************
** Store field definition for create
** Return 0 if ok
@@ -4393,13 +5542,11 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{
register create_field *new_field;
LEX *lex= thd->lex;
- uint allowed_type_modifier=0;
- char warn_buff[MYSQL_ERRMSG_SIZE];
DBUG_ENTER("add_field_to_list");
if (strlen(field_name) > NAME_LEN)
{
- net_printf(thd, ER_TOO_LONG_IDENT, field_name); /* purecov: inspected */
+ my_error(ER_TOO_LONG_IDENT, MYF(0), field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
if (type_modifier & PRI_KEY_FLAG)
@@ -4430,7 +5577,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
!(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC &&
type == FIELD_TYPE_TIMESTAMP))
{
- net_printf(thd, ER_INVALID_DEFAULT, field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
DBUG_RETURN(1);
}
else if (default_value->type() == Item::NULL_ITEM)
@@ -4439,60 +5586,102 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
NOT_NULL_FLAG)
{
- net_printf(thd,ER_INVALID_DEFAULT,field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
DBUG_RETURN(1);
}
}
else if (type_modifier & AUTO_INCREMENT_FLAG)
{
- net_printf(thd, ER_INVALID_DEFAULT, field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
DBUG_RETURN(1);
}
}
if (on_update_value && type != FIELD_TYPE_TIMESTAMP)
{
- net_printf(thd, ER_INVALID_ON_UPDATE, field_name);
+ my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name);
DBUG_RETURN(1);
}
-
- if (!(new_field=new create_field()))
+
+ if (type == FIELD_TYPE_TIMESTAMP && length)
+ {
+ /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1.
+ In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4),
+ and so on, the display width is ignored.
+ */
+ char buf[32];
+ my_snprintf(buf, sizeof(buf),
+ "TIMESTAMP(%s)", length, system_charset_info);
+ push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER(ER_WARN_DEPRECATED_SYNTAX),
+ buf, "TIMESTAMP");
+ }
+
+ if (!(new_field= new_create_field(thd, field_name, type, length, decimals,
+ type_modifier, default_value, on_update_value,
+ comment, change, interval_list, cs, uint_geom_type)))
DBUG_RETURN(1);
+
+ lex->create_list.push_back(new_field);
+ lex->last_field=new_field;
+ DBUG_RETURN(0);
+}
+
+/*****************************************************************************
+** Create field definition for create
+** Return 0 on failure, otherwise return create_field instance
+******************************************************************************/
+
+create_field *
+new_create_field(THD *thd, char *field_name, enum_field_types type,
+ char *length, char *decimals,
+ uint type_modifier,
+ Item *default_value, Item *on_update_value,
+ LEX_STRING *comment,
+ char *change, List<String> *interval_list, CHARSET_INFO *cs,
+ uint uint_geom_type)
+{
+ register create_field *new_field;
+ uint sign_len, allowed_type_modifier=0;
+ ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
+ DBUG_ENTER("new_create_field");
+
+ if (!(new_field=new create_field()))
+ DBUG_RETURN(NULL);
new_field->field=0;
new_field->field_name=field_name;
new_field->def= default_value;
new_field->flags= type_modifier;
new_field->unireg_check= (type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
- new_field->decimals= decimals ? (uint) set_zone(atoi(decimals),0,
- NOT_FIXED_DEC-1) : 0;
+ new_field->decimals= decimals ? (uint)atoi(decimals) : 0;
+ if (new_field->decimals >= NOT_FIXED_DEC)
+ {
+ my_error(ER_TOO_BIG_SCALE, MYF(0), new_field->decimals, field_name,
+ NOT_FIXED_DEC-1);
+ DBUG_RETURN(NULL);
+ }
+
new_field->sql_type=type;
new_field->length=0;
new_field->change=change;
new_field->interval=0;
- new_field->pack_length=0;
+ new_field->pack_length= new_field->key_length= 0;
new_field->charset=cs;
new_field->geom_type= (Field::geometry_type) uint_geom_type;
- if (!comment)
- {
- new_field->comment.str=0;
- new_field->comment.length=0;
- }
- else
- {
- /* In this case comment is always of type Item_string */
- new_field->comment.str= (char*) comment->str;
- new_field->comment.length=comment->length;
- }
+ new_field->comment=*comment;
+ /*
+ Set flag if this field doesn't have a default value
+ */
+ if (!default_value && !(type_modifier & AUTO_INCREMENT_FLAG) &&
+ (type_modifier & NOT_NULL_FLAG) && type != FIELD_TYPE_TIMESTAMP)
+ new_field->flags|= NO_DEFAULT_VALUE_FLAG;
+
if (length && !(new_field->length= (uint) atoi(length)))
length=0; /* purecov: inspected */
- uint sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
-
- if (new_field->length && new_field->decimals &&
- new_field->length < new_field->decimals+1 &&
- new_field->decimals != NOT_FIXED_DEC)
- new_field->length=new_field->decimals+1; /* purecov: inspected */
+ sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
switch (type) {
case FIELD_TYPE_TINY:
@@ -4517,59 +5706,49 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
break;
case FIELD_TYPE_NULL:
break;
- case FIELD_TYPE_DECIMAL:
+ case FIELD_TYPE_NEWDECIMAL:
if (!length)
+ new_field->length= 10;
+ if (new_field->length > DECIMAL_MAX_PRECISION)
{
- if ((new_field->length= new_field->decimals))
- new_field->length++;
- else
- new_field->length= 10; // Default length for DECIMAL
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), new_field->length, field_name,
+ DECIMAL_MAX_PRECISION);
+ DBUG_RETURN(NULL);
}
- if (new_field->length < MAX_FIELD_WIDTH) // Skip wrong argument
+ if (new_field->length < new_field->decimals)
{
- new_field->length+=sign_len;
- if (new_field->decimals)
- new_field->length++;
+ my_error(ER_SCALE_BIGGER_THAN_PRECISION, MYF(0), field_name);
+ DBUG_RETURN(NULL);
}
+ new_field->length=
+ my_decimal_precision_to_length(new_field->length, new_field->decimals,
+ type_modifier & UNSIGNED_FLAG);
+ new_field->pack_length=
+ my_decimal_get_binary_size(new_field->length, new_field->decimals);
+ break;
+ case MYSQL_TYPE_VARCHAR:
+ /*
+ Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
+ if they don't have a default value
+ */
+ max_field_charlength= MAX_FIELD_VARCHARLENGTH;
+ break;
+ case MYSQL_TYPE_STRING:
break;
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
- if (new_field->length <= MAX_FIELD_CHARLENGTH || default_value)
- break;
- /* Convert long CHAR() and VARCHAR columns to TEXT or BLOB */
- new_field->sql_type= FIELD_TYPE_BLOB;
- sprintf(warn_buff, ER(ER_AUTO_CONVERT), field_name, "CHAR",
- (cs == &my_charset_bin) ? "BLOB" : "TEXT");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_AUTO_CONVERT,
- warn_buff);
- /* fall through */
case FIELD_TYPE_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_GEOMETRY:
- if (new_field->length)
- {
- /* The user has given a length to the blob column */
- if (new_field->length < 256)
- type= FIELD_TYPE_TINY_BLOB;
- else if (new_field->length < 65536)
- type= FIELD_TYPE_BLOB;
- else if (new_field->length < 256L*256L*256L)
- type= FIELD_TYPE_MEDIUM_BLOB;
- else
- type= FIELD_TYPE_LONG_BLOB;
- new_field->length= 0;
- }
- new_field->sql_type= type;
if (default_value) // Allow empty as default value
{
String str,*res;
res=default_value->val_str(&str);
if (res->length())
{
- net_printf(thd,ER_BLOB_CANT_HAVE_DEFAULT,field_name); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
+ my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
+ field_name); /* purecov: inspected */
+ DBUG_RETURN(NULL);
}
new_field->def=0;
}
@@ -4588,8 +5767,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
uint tmp_length=new_field->length;
if (tmp_length > PRECISION_FOR_DOUBLE)
{
- net_printf(thd,ER_WRONG_FIELD_SPEC,field_name);
- DBUG_RETURN(1);
+ my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
+ DBUG_RETURN(NULL);
}
else if (tmp_length > PRECISION_FOR_FLOAT)
{
@@ -4661,11 +5840,11 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
If we have TIMESTAMP NULL column without explicit DEFAULT value
we treat it as having DEFAULT NULL attribute.
*/
- new_field->unireg_check= on_update_value ?
- Field::TIMESTAMP_UN_FIELD :
- (new_field->flags & NOT_NULL_FLAG ?
- Field::TIMESTAMP_OLD_FIELD:
- Field::NONE);
+ new_field->unireg_check= (on_update_value ?
+ Field::TIMESTAMP_UN_FIELD :
+ (new_field->flags & NOT_NULL_FLAG ?
+ Field::TIMESTAMP_OLD_FIELD:
+ Field::NONE));
}
break;
case FIELD_TYPE_DATE: // Old date type
@@ -4685,8 +5864,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{
if (interval_list->elements > sizeof(longlong)*8)
{
- net_printf(thd,ER_TOO_BIG_SET,field_name); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
+ my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */
+ DBUG_RETURN(NULL);
}
new_field->pack_length= get_set_pack_length(interval_list->elements);
@@ -4700,8 +5879,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
when we know the character set of the column
*/
new_field->length= 1;
+ break;
}
- break;
case FIELD_TYPE_ENUM:
{
// Should be safe
@@ -4712,37 +5891,53 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
while ((tmp= it++))
new_field->interval_list.push_back(tmp);
new_field->length= 1; // See comment for FIELD_TYPE_SET above.
- }
+ break;
+ }
+ case MYSQL_TYPE_VAR_STRING:
+ DBUG_ASSERT(0); // Impossible
break;
+ case MYSQL_TYPE_BIT:
+ {
+ if (!length)
+ new_field->length= 1;
+ if (new_field->length > MAX_BIT_FIELD_LENGTH)
+ {
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name,
+ MAX_BIT_FIELD_LENGTH);
+ DBUG_RETURN(NULL);
+ }
+ new_field->pack_length= (new_field->length + 7) / 8;
+ break;
+ }
+ case FIELD_TYPE_DECIMAL:
+ DBUG_ASSERT(0); /* Was obsolete */
}
- if ((new_field->length > MAX_FIELD_CHARLENGTH && type != FIELD_TYPE_SET &&
- type != FIELD_TYPE_ENUM) ||
- (!new_field->length && !(new_field->flags & BLOB_FLAG) &&
- type != FIELD_TYPE_STRING &&
- type != FIELD_TYPE_VAR_STRING && type != FIELD_TYPE_GEOMETRY))
+ if (!(new_field->flags & BLOB_FLAG) &&
+ ((new_field->length > max_field_charlength && type != FIELD_TYPE_SET &&
+ type != FIELD_TYPE_ENUM &&
+ (type != MYSQL_TYPE_VARCHAR || default_value)) ||
+ (!new_field->length &&
+ type != MYSQL_TYPE_STRING &&
+ type != MYSQL_TYPE_VARCHAR && type != FIELD_TYPE_GEOMETRY)))
{
- net_printf(thd,ER_TOO_BIG_FIELDLENGTH,field_name,
- MAX_FIELD_CHARLENGTH); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
+ my_error((type == MYSQL_TYPE_VAR_STRING || type == MYSQL_TYPE_VARCHAR ||
+ type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
+ ER_TOO_BIG_DISPLAYWIDTH,
+ MYF(0),
+ field_name, max_field_charlength); /* purecov: inspected */
+ DBUG_RETURN(NULL);
}
type_modifier&= AUTO_INCREMENT_FLAG;
if ((~allowed_type_modifier) & type_modifier)
{
- net_printf(thd,ER_WRONG_FIELD_SPEC,field_name);
- DBUG_RETURN(1);
+ my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
+ DBUG_RETURN(NULL);
}
- if (!new_field->pack_length)
- new_field->pack_length=calc_pack_length(new_field->sql_type ==
- FIELD_TYPE_VAR_STRING ?
- FIELD_TYPE_STRING :
- new_field->sql_type,
- new_field->length);
- lex->create_list.push_back(new_field);
- lex->last_field=new_field;
- DBUG_RETURN(0);
+ DBUG_RETURN(new_field);
}
+
/* Store position for column in ALTER TABLE .. ADD column */
void store_position_for_column(const char *name)
@@ -4781,7 +5976,6 @@ static void remove_escape(char *name)
{
#ifdef USE_MB
int l;
-/* if ((l = ismbchar(name, name+MBMAXLEN))) { Wei He: I think it's wrong */
if (use_mb(system_charset_info) &&
(l = my_ismbchar(system_charset_info, name, strend)))
{
@@ -4814,6 +6008,7 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc)
order->asc = asc;
order->free_me=0;
order->used=0;
+ order->counter_used= 0;
list.link_in_list((byte*) order,(byte**) &order->next);
DBUG_RETURN(0);
}
@@ -4848,8 +6043,11 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
LEX_STRING *option)
{
register TABLE_LIST *ptr;
+ TABLE_LIST *previous_table_ref; /* The table preceding the current one. */
char *alias_str;
+ LEX *lex= thd->lex;
DBUG_ENTER("add_table_to_list");
+ LINT_INIT(previous_table_ref);
if (!table)
DBUG_RETURN(0); // End of memory
@@ -4857,7 +6055,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (check_table_name(table->table.str,table->table.length) ||
table->db.str && check_db_name(table->db.str))
{
- net_printf(thd, ER_WRONG_TABLE_NAME, table->table.str);
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
DBUG_RETURN(0);
}
@@ -4865,7 +6063,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
{
if (table->sel)
{
- net_printf(thd,ER_DERIVED_MUST_HAVE_ALIAS);
+ my_message(ER_DERIVED_MUST_HAVE_ALIAS,
+ ER(ER_DERIVED_MUST_HAVE_ALIAS), MYF(0));
DBUG_RETURN(0);
}
if (!(alias_str=thd->memdup(alias_str,table->table.length+1)))
@@ -4882,26 +6081,44 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
{
ptr->db= thd->db;
ptr->db_length= thd->db_length;
+ ptr->current_db_used= 1;
}
else
{
/* The following can't be "" as we may do 'casedn_str()' on it */
ptr->db= empty_c_string;
ptr->db_length= 0;
+ ptr->current_db_used= 1;
}
- if (thd->current_arena->is_stmt_prepare())
+ if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
ptr->db= thd->strdup(ptr->db);
ptr->alias= alias_str;
if (lower_case_table_names && table->table.length)
my_casedn_str(files_charset_info, table->table.str);
- ptr->real_name=table->table.str;
- ptr->real_name_length=table->table.length;
+ ptr->table_name=table->table.str;
+ ptr->table_name_length=table->table.length;
ptr->lock_type= lock_type;
ptr->updating= test(table_options & TL_OPTION_UPDATING);
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
ptr->derived= table->sel;
+ if (!my_strcasecmp(system_charset_info, ptr->db,
+ information_schema_name.str))
+ {
+ ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name);
+ if (!schema_table ||
+ (schema_table->hidden &&
+ lex->orig_sql_command == SQLCOM_END)) // not a 'show' command
+ {
+ my_error(ER_UNKNOWN_TABLE, MYF(0),
+ ptr->table_name, information_schema_name.str);
+ DBUG_RETURN(0);
+ }
+ ptr->schema_table_name= ptr->table_name;
+ ptr->schema_table= schema_table;
+ }
+ ptr->select_lex= lex->current_select;
ptr->cacheable_table= 1;
if (use_index_arg)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg,
@@ -4913,24 +6130,277 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
/* check that used name is unique */
if (lock_type != TL_IGNORE)
{
- for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ;
+ TABLE_LIST *first_table= (TABLE_LIST*) table_list.first;
+ if (lex->sql_command == SQLCOM_CREATE_VIEW)
+ first_table= first_table ? first_table->next_local : NULL;
+ for (TABLE_LIST *tables= first_table ;
tables ;
- tables=tables->next)
+ tables=tables->next_local)
{
if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
!strcmp(ptr->db, tables->db))
{
- net_printf(thd,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */
+ my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
DBUG_RETURN(0); /* purecov: tested */
}
}
}
- table_list.link_in_list((byte*) ptr, (byte**) &ptr->next);
+ /* Store the table reference preceding the current one. */
+ if (table_list.elements > 0)
+ {
+ /*
+ table_list.next points to the last inserted TABLE_LIST->next_local'
+ element
+ */
+ previous_table_ref= (TABLE_LIST*) (table_list.next -
+ offsetof(TABLE_LIST, next_local));
+ DBUG_ASSERT(previous_table_ref);
+ /*
+ Set next_name_resolution_table of the previous table reference to point
+ to the current table reference. In effect the list
+ TABLE_LIST::next_name_resolution_table coincides with
+ TABLE_LIST::next_local. Later this may be changed in
+ store_top_level_join_columns() for NATURAL/USING joins.
+ */
+ previous_table_ref->next_name_resolution_table= ptr;
+ }
+
+ /*
+ Link the current table reference in a local list (list for current select).
+ Notice that as a side effect here we set the next_local field of the
+ previous table reference to 'ptr'. Here we also add one element to the
+ list 'table_list'.
+ */
+ table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local);
+ ptr->next_name_resolution_table= NULL;
+ /* Link table in global list (all used tables) */
+ lex->add_to_query_tables(ptr);
+ DBUG_RETURN(ptr);
+}
+
+
+/*
+ Initialize a new table list for a nested join
+
+ SYNOPSIS
+ init_nested_join()
+ thd current thread
+
+ DESCRIPTION
+ The function initializes a structure of the TABLE_LIST type
+ for a nested join. It sets up its nested join list as empty.
+ The created structure is added to the front of the current
+ join list in the st_select_lex object. Then the function
+ changes the current nest level for joins to refer to the newly
+ created empty list after having saved the info on the old level
+ in the initialized structure.
+
+ RETURN VALUE
+ 0, if success
+ 1, otherwise
+*/
+
+bool st_select_lex::init_nested_join(THD *thd)
+{
+ TABLE_LIST *ptr;
+ NESTED_JOIN *nested_join;
+ DBUG_ENTER("init_nested_join");
+
+ if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
+ sizeof(NESTED_JOIN))))
+ DBUG_RETURN(1);
+ nested_join= ptr->nested_join=
+ ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
+
+ join_list->push_front(ptr);
+ ptr->embedding= embedding;
+ ptr->join_list= join_list;
+ embedding= ptr;
+ join_list= &nested_join->join_list;
+ join_list->empty();
+ DBUG_RETURN(0);
+}
+
+
+/*
+ End a nested join table list
+
+ SYNOPSIS
+ end_nested_join()
+ thd current thread
+
+ DESCRIPTION
+ The function returns to the previous join nest level.
+ If the current level contains only one member, the function
+ moves it one level up, eliminating the nest.
+
+ RETURN VALUE
+ Pointer to TABLE_LIST element added to the total table list, if success
+ 0, otherwise
+*/
+
+TABLE_LIST *st_select_lex::end_nested_join(THD *thd)
+{
+ TABLE_LIST *ptr;
+ NESTED_JOIN *nested_join;
+ DBUG_ENTER("end_nested_join");
+
+ DBUG_ASSERT(embedding);
+ ptr= embedding;
+ join_list= ptr->join_list;
+ embedding= ptr->embedding;
+ nested_join= ptr->nested_join;
+ if (nested_join->join_list.elements == 1)
+ {
+ TABLE_LIST *embedded= nested_join->join_list.head();
+ join_list->pop();
+ embedded->join_list= join_list;
+ embedded->embedding= embedding;
+ join_list->push_front(embedded);
+ ptr= embedded;
+ }
+ else if (nested_join->join_list.elements == 0)
+ {
+ join_list->pop();
+ ptr= 0; // return value
+ }
+ DBUG_RETURN(ptr);
+}
+
+
+/*
+ Nest last join operation
+
+ SYNOPSIS
+ nest_last_join()
+ thd current thread
+
+ DESCRIPTION
+ The function nest last join operation as if it was enclosed in braces.
+
+ RETURN VALUE
+ 0 Error
+ # Pointer to TABLE_LIST element created for the new nested join
+
+*/
+
+TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
+{
+ TABLE_LIST *ptr;
+ NESTED_JOIN *nested_join;
+ List<TABLE_LIST> *embedded_list;
+ DBUG_ENTER("nest_last_join");
+
+ if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
+ sizeof(NESTED_JOIN))))
+ DBUG_RETURN(0);
+ nested_join= ptr->nested_join=
+ ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
+
+ ptr->embedding= embedding;
+ ptr->join_list= join_list;
+ embedded_list= &nested_join->join_list;
+ embedded_list->empty();
+
+ for (uint i=0; i < 2; i++)
+ {
+ TABLE_LIST *table= join_list->pop();
+ table->join_list= embedded_list;
+ table->embedding= ptr;
+ embedded_list->push_back(table);
+ if (table->natural_join)
+ {
+ ptr->is_natural_join= TRUE;
+ /*
+ If this is a JOIN ... USING, move the list of joined fields to the
+ table reference that describes the join.
+ */
+ if (table->join_using_fields)
+ {
+ ptr->join_using_fields= table->join_using_fields;
+ table->join_using_fields= NULL;
+ }
+ }
+ }
+ join_list->push_front(ptr);
+ nested_join->used_tables= nested_join->not_null_tables= (table_map) 0;
DBUG_RETURN(ptr);
}
/*
+ Add a table to the current join list
+
+ SYNOPSIS
+ add_joined_table()
+ table the table to add
+
+ DESCRIPTION
+ The function puts a table in front of the current join list
+ of st_select_lex object.
+ Thus, joined tables are put into this list in the reverse order
+ (the most outer join operation follows first).
+
+ RETURN VALUE
+ None
+*/
+
+void st_select_lex::add_joined_table(TABLE_LIST *table)
+{
+ DBUG_ENTER("add_joined_table");
+ join_list->push_front(table);
+ table->join_list= join_list;
+ table->embedding= embedding;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Convert a right join into equivalent left join
+
+ SYNOPSIS
+ convert_right_join()
+ thd current thread
+
+ DESCRIPTION
+ The function takes the current join list t[0],t[1] ... and
+ effectively converts it into the list t[1],t[0] ...
+ Although the outer_join flag for the new nested table contains
+ JOIN_TYPE_RIGHT, it will be handled as the inner table of a left join
+ operation.
+
+ EXAMPLES
+ SELECT * FROM t1 RIGHT JOIN t2 ON on_expr =>
+ SELECT * FROM t2 LEFT JOIN t1 ON on_expr
+
+ SELECT * FROM t1,t2 RIGHT JOIN t3 ON on_expr =>
+ SELECT * FROM t1,t3 LEFT JOIN t2 ON on_expr
+
+ SELECT * FROM t1,t2 RIGHT JOIN (t3,t4) ON on_expr =>
+ SELECT * FROM t1,(t3,t4) LEFT JOIN t2 ON on_expr
+
+ SELECT * FROM t1 LEFT JOIN t2 ON on_expr1 RIGHT JOIN t3 ON on_expr2 =>
+ SELECT * FROM t3 LEFT JOIN (t1 LEFT JOIN t2 ON on_expr2) ON on_expr1
+
+ RETURN
+ Pointer to the table representing the inner table, if success
+ 0, otherwise
+*/
+
+TABLE_LIST *st_select_lex::convert_right_join()
+{
+ TABLE_LIST *tab2= join_list->pop();
+ TABLE_LIST *tab1= join_list->pop();
+ DBUG_ENTER("convert_right_join");
+
+ join_list->push_front(tab2);
+ join_list->push_front(tab1);
+ tab1->outer_join|= JOIN_TYPE_RIGHT;
+
+ DBUG_RETURN(tab1);
+}
+
+/*
Set lock for all tables in current select level
SYNOPSIS:
@@ -4950,9 +6420,9 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
for_update));
- for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first ;
- tables ;
- tables=tables->next)
+ for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first;
+ tables;
+ tables= tables->next_local)
{
tables->lock_type= lock_type;
tables->updating= for_update;
@@ -4961,16 +6431,70 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
}
-void add_join_on(TABLE_LIST *b,Item *expr)
+/*
+ Create a new name resolution context for a JOIN ... ON clause.
+
+ SYNOPSIS
+ make_join_on_context()
+ thd pointer to current thread
+ left_op left operand of the JOIN
+ right_op rigth operand of the JOIN
+
+ DESCRIPTION
+ Create a new name resolution context for a JOIN ... ON clause,
+ and set the first and last leaves of the list of table references
+ to be used for name resolution.
+
+ RETURN
+ A new context if all is OK
+ NULL - if a memory allocation error occured
+*/
+
+Name_resolution_context *
+make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op)
+{
+ Name_resolution_context *on_context;
+ if (!(on_context= new (thd->mem_root) Name_resolution_context))
+ return NULL;
+ on_context->init();
+ on_context->first_name_resolution_table=
+ left_op->first_leaf_for_name_resolution();
+ on_context->last_name_resolution_table=
+ right_op->last_leaf_for_name_resolution();
+ return on_context;
+}
+
+
+/*
+ Add an ON condition to the second operand of a JOIN ... ON.
+
+ SYNOPSIS
+ add_join_on
+ b the second operand of a JOIN ... ON
+ expr the condition to be added to the ON clause
+
+ DESCRIPTION
+ Add an ON condition to the right operand of a JOIN ... ON clause.
+
+ RETURN
+ FALSE if there was some error
+ TRUE if all is OK
+*/
+
+void add_join_on(TABLE_LIST *b, Item *expr)
{
if (expr)
{
if (!b->on_expr)
- b->on_expr=expr;
+ b->on_expr= expr;
else
{
- // This only happens if you have both a right and left join
- b->on_expr=new Item_cond_and(b->on_expr,expr);
+ /*
+ If called from the parser, this happens if you have both a
+ right and left join. If called later, it happens if we add more
+ than one condition to the ON clause.
+ */
+ b->on_expr= new Item_cond_and(b->on_expr,expr);
}
b->on_expr->top_level_item();
}
@@ -4978,46 +6502,67 @@ void add_join_on(TABLE_LIST *b,Item *expr)
/*
- Mark that we have a NATURAL JOIN between two tables
+ Mark that there is a NATURAL JOIN or JOIN ... USING between two
+ tables.
SYNOPSIS
add_join_natural()
- a Table to do normal join with
- b Do normal join with this table
+ a Left join argument
+ b Right join argument
+ using_fields Field names from USING clause
IMPLEMENTATION
- This function just marks that table b should be joined with a.
- The function setup_cond() will create in b->on_expr a list
- of equal condition between all fields of the same name.
-
+ This function marks that table b should be joined with a either via
+ a NATURAL JOIN or via JOIN ... USING. Both join types are special
+ cases of each other, so we treat them together. The function
+ setup_conds() creates a list of equal condition between all fields
+ of the same name for NATURAL JOIN or the fields in 'using_fields'
+ for JOIN ... USING. The list of equality conditions is stored
+ either in b->on_expr, or in JOIN::conds, depending on whether there
+ was an outer join.
+
+ EXAMPLE
SELECT * FROM t1 NATURAL LEFT JOIN t2
<=>
SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
+
+ SELECT * FROM t1 NATURAL JOIN t2 WHERE <some_cond>
+ <=>
+ SELECT * FROM t1, t2 WHERE (t1.i=t2.i and t1.j=t2.j and <some_cond>)
+
+ SELECT * FROM t1 JOIN t2 USING(j) WHERE <some_cond>
+ <=>
+ SELECT * FROM t1, t2 WHERE (t1.j=t2.j and <some_cond>)
+
+ RETURN
+ None
*/
-void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
+void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields)
{
- b->natural_join=a;
+ b->natural_join= a;
+ b->join_using_fields= using_fields;
}
+
/*
Reload/resets privileges and the different caches.
SYNOPSIS
reload_acl_and_cache()
- thd Thread handler
+ thd Thread handler (can be NULL!)
options What should be reset/reloaded (tables, privileges,
slave...)
tables Tables to flush (if any)
write_to_binlog Depending on 'options', it may be very bad to write the
query to the binlog (e.g. FLUSH SLAVE); this is a
- pointer where, if it is not NULL, reload_acl_and_cache()
- will put 0 if it thinks we really should not write to
- the binlog. Otherwise it will put 1.
+ pointer where reload_acl_and_cache() will put 0 if
+ it thinks we really should not write to the binlog.
+ Otherwise it will put 1.
RETURN
0 ok
- !=0 error
+ !=0 error. thd->killed or thd->net.report_error is set
*/
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
@@ -5026,6 +6571,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool result=0;
select_errors=0; /* Write if more errors */
bool tmp_write_to_binlog= 1;
+
+ if (thd && thd->in_sub_stmt)
+ {
+ my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH");
+ return 1;
+ }
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (options & REFRESH_GRANT)
{
@@ -5040,8 +6592,6 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
{
(void)acl_reload(thd);
(void)grant_reload(thd);
- if (mqh_used)
- reset_mqh(thd, (LEX_USER *) NULL, TRUE);
}
if (tmp_thd)
{
@@ -5050,6 +6600,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
my_pthread_setspecific_ptr(THR_THD, 0);
thd= 0;
}
+ reset_mqh((LEX_USER *)NULL, TRUE);
}
#endif
if (options & REFRESH_LOG)
@@ -5060,23 +6611,16 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
*/
/*
- Writing this command to the binlog may result in infinite loops when
- doing mysqlbinlog|mysql, and anyway it does not really make sense to
- log it automatically (would cause more trouble to users than it would
- help them)
+ Writing this command to the binlog may result in infinite loops
+ when doing mysqlbinlog|mysql, and anyway it does not really make
+ sense to log it automatically (would cause more trouble to users
+ than it would help them)
*/
tmp_write_to_binlog= 0;
mysql_log.new_file(1);
- mysql_update_log.new_file(1);
- mysql_bin_log.new_file(1);
mysql_slow_log.new_file(1);
+ mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
#ifdef HAVE_REPLICATION
- if (mysql_bin_log.is_open() && expire_logs_days)
- {
- long purge_time= time(0) - expire_logs_days*24*60*60;
- if (purge_time >= 0)
- mysql_bin_log.purge_logs_before_date(purge_time);
- }
pthread_mutex_lock(&LOCK_active_mi);
rotate_relay_log(active_mi);
pthread_mutex_unlock(&LOCK_active_mi);
@@ -5090,7 +6634,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))
{
@@ -5130,10 +6674,15 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
*/
tmp_write_to_binlog= 0;
if (lock_global_read_lock(thd))
- return 1;
+ return 1; // Killed
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1,
tables);
- make_global_read_lock_block_commit(thd);
+ if (make_global_read_lock_block_commit(thd)) // Killed
+ {
+ /* Don't leave things in a half-locked state */
+ unlock_global_read_lock(thd);
+ return 1;
+ }
}
else
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables);
@@ -5141,7 +6690,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
}
if (options & REFRESH_HOSTS)
hostname_cache_refresh();
- if (options & REFRESH_STATUS)
+ if (thd && (options & REFRESH_STATUS))
refresh_status();
if (options & REFRESH_THREADS)
flush_thread_cache();
@@ -5150,7 +6699,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
{
tmp_write_to_binlog= 0;
if (reset_master(thd))
+ {
result=1;
+ thd->fatal_error(); // Ensure client get error
+ }
}
#endif
#ifdef OPENSSL
@@ -5171,9 +6723,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
}
#endif
if (options & REFRESH_USER_RESOURCES)
- reset_mqh(thd,(LEX_USER *) NULL);
- if (write_to_binlog)
- *write_to_binlog= tmp_write_to_binlog;
+ reset_mqh((LEX_USER *) NULL);
+ *write_to_binlog= tmp_write_to_binlog;
return result;
}
@@ -5189,7 +6740,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
This is written such that we have a short lock on LOCK_thread_count
*/
-void kill_one_thread(THD *thd, ulong id)
+void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
{
THD *tmp;
uint error=ER_NO_SUCH_THREAD;
@@ -5209,7 +6760,7 @@ void kill_one_thread(THD *thd, ulong id)
if ((thd->master_access & SUPER_ACL) ||
!strcmp(thd->user,tmp->user))
{
- tmp->awake(1 /*prepare to die*/);
+ tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION);
error=0;
}
else
@@ -5220,7 +6771,7 @@ void kill_one_thread(THD *thd, ulong id)
if (!error)
send_ok(thd);
else
- net_printf(thd,error,id);
+ my_error(error, MYF(0), id);
}
@@ -5233,6 +6784,13 @@ static void refresh_status(void)
{
if (ptr->type == SHOW_LONG)
*(ulong*) ptr->value= 0;
+ else if (ptr->type == SHOW_LONG_STATUS)
+ {
+ THD *thd= current_thd;
+ /* We must update the global status before cleaning up the thread */
+ add_to_status(&global_status_var, &thd->status_var);
+ bzero((char*) &thd->status_var, sizeof(thd->status_var));
+ }
}
/* Reset the counters of all key caches (default and named). */
process_key_caches(reset_key_cache_counters);
@@ -5281,12 +6839,13 @@ static bool append_file_to_dir(THD *thd, const char **filename_ptr,
bool check_simple_select()
{
THD *thd= current_thd;
- if (thd->lex->current_select != &thd->lex->select_lex)
+ LEX *lex= thd->lex;
+ if (lex->current_select != &lex->select_lex)
{
char command[80];
- strmake(command, thd->lex->yylval->symbol.str,
- min(thd->lex->yylval->symbol.length, sizeof(command)-1));
- net_printf(thd, ER_CANT_USE_OPTION_HERE, command);
+ strmake(command, lex->yylval->symbol.str,
+ min(lex->yylval->symbol.length, sizeof(command)-1));
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
return 1;
}
return 0;
@@ -5303,18 +6862,16 @@ bool check_simple_select()
SYNOPSIS
check_multi_update_lock()
thd Current thread
- tables List of user-supplied tables
- fields List of fields requiring update
RETURN VALUES
0 ok
1 error
*/
-static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
- List<Item> *fields, SELECT_LEX *select_lex)
+static bool check_multi_update_lock(THD *thd)
{
bool res= 1;
- TABLE_LIST *table;
+ LEX *lex= thd->lex;
+ TABLE_LIST *table, *tables= lex->query_tables;
DBUG_ENTER("check_multi_update_lock");
if (check_db_used(thd, tables))
@@ -5324,18 +6881,19 @@ static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
Ensure that we have UPDATE or SELECT privilege for each table
The exact privilege is checked in mysql_multi_update()
*/
- for (table= tables ; table ; table= table->next)
+ for (table= tables ; table ; table= table->next_local)
{
- TABLE_LIST *save= table->next;
- table->next= 0;
- if ((check_access(thd, UPDATE_ACL, table->db, &table->grant.privilege,0,1) ||
- (grant_option && check_grant(thd, UPDATE_ACL, table,0,1,1))) &&
+ TABLE_LIST *save= table->next_local;
+ table->next_local= 0;
+ if ((check_access(thd, UPDATE_ACL, table->db,
+ &table->grant.privilege,0,1, test(table->schema_table)) ||
+ (grant_option && check_grant(thd, UPDATE_ACL, table,0,1,1))) &&
check_one_table_access(thd, SELECT_ACL, table))
- goto error;
- table->next= save;
+ goto error;
+ table->next_local= save;
}
- if (mysql_multi_update_lock(thd, tables, fields, select_lex))
+ if (mysql_multi_update_prepare(thd))
goto error;
res= 0;
@@ -5426,25 +6984,24 @@ Item * all_any_subquery_creator(Item *left_expr,
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
-int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
+bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
List<create_field> fields;
ALTER_INFO alter_info;
alter_info.flags= ALTER_ADD_INDEX;
- alter_info.is_simple= 0;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
- DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
+ DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
&create_info, table_list,
fields, keys, 0, (ORDER*)0,
- DUP_ERROR, 0, &alter_info));
+ DUP_ERROR, 0, &alter_info, 1));
}
-int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
+bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
{
List<create_field> fields;
List<Key> keys;
@@ -5455,11 +7012,10 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
create_info.default_table_charset= thd->variables.collation_database;
alter_info->clear();
alter_info->flags= ALTER_DROP_INDEX;
- alter_info->is_simple= 0;
- DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
+ DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
&create_info, table_list,
fields, keys, 0, (ORDER*)0,
- DUP_ERROR, 0, alter_info));
+ DUP_ERROR, 0, alter_info, 1));
}
@@ -5469,51 +7025,46 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
SYNOPSIS
multi_update_precheck()
thd Thread handler
- tables Global table list
+ tables Global/local table list (have to be the same)
RETURN VALUE
- 0 OK
- 1 Error (message is sent to user)
- -1 Error (message is not sent to user)
+ FALSE OK
+ TRUE Error
*/
-int multi_update_precheck(THD *thd, TABLE_LIST *tables)
+bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
{
- DBUG_ENTER("multi_update_precheck");
const char *msg= 0;
TABLE_LIST *table;
LEX *lex= thd->lex;
SELECT_LEX *select_lex= &lex->select_lex;
- TABLE_LIST *update_list= (TABLE_LIST*)select_lex->table_list.first;
+ DBUG_ENTER("multi_update_precheck");
if (select_lex->item_list.elements != lex->value_list.elements)
{
- my_error(ER_WRONG_VALUE_COUNT, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
+ DBUG_RETURN(TRUE);
}
/*
Ensure that we have UPDATE or SELECT privilege for each table
The exact privilege is checked in mysql_multi_update()
*/
- for (table= update_list; table; table= table->next)
+ for (table= tables; table; table= table->next_local)
{
if (table->derived)
table->grant.privilege= SELECT_ACL;
else if ((check_access(thd, UPDATE_ACL, table->db,
- &table->grant.privilege, 0, 1) ||
+ &table->grant.privilege, 0, 1,
+ test(table->schema_table)) ||
grant_option &&
check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
- (check_access(thd, SELECT_ACL, table->db,
- &table->grant.privilege, 0, 0) ||
- grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
- DBUG_RETURN(1);
+ (check_access(thd, SELECT_ACL, table->db,
+ &table->grant.privilege, 0, 0,
+ test(table->schema_table)) ||
+ grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
+ DBUG_RETURN(TRUE);
- /*
- We assign following flag only to copy of table, because it will
- be checked only if query contains subqueries i.e. only if copy exists
- */
- if (table->table_list)
- table->table_list->table_in_update_from_clause= 1;
+ table->table_in_first_from_clause= 1;
}
/*
Is there tables of subqueries?
@@ -5521,42 +7072,31 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (&lex->select_lex != lex->all_selects_list || lex->time_zone_tables_used)
{
DBUG_PRINT("info",("Checking sub query list"));
- for (table= tables; table; table= table->next)
+ for (table= tables; table; table= table->next_global)
{
- if (my_tz_check_n_skip_implicit_tables(&table,
- lex->time_zone_tables_used))
- continue;
- else if (table->table_in_update_from_clause)
- {
- /*
- If we check table by local TABLE_LIST copy then we should copy
- grants to global table list, because it will be used for table
- opening.
- */
- if (table->table_list)
- table->grant= table->table_list->grant;
- }
- else if (!table->derived)
+ if (!my_tz_check_n_skip_implicit_tables(&table,
+ lex->time_zone_tables_used) &&
+ !table->table_in_first_from_clause)
{
if (check_access(thd, SELECT_ACL, table->db,
- &table->grant.privilege, 0, 0) ||
+ &table->grant.privilege, 0, 0,
+ test(table->schema_table)) ||
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
}
if (select_lex->order_list.elements)
msg= "ORDER BY";
- else if (select_lex->select_limit && select_lex->select_limit !=
- HA_POS_ERROR)
+ else if (select_lex->select_limit)
msg= "LIMIT";
if (msg)
{
my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
/*
@@ -5565,67 +7105,83 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
SYNOPSIS
multi_delete_precheck()
thd Thread handler
- tables Global table list
- table_count Pointer to table counter
+ tables Global/local table list
RETURN VALUE
- 0 OK
- 1 error (message is sent to user)
- -1 error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
+bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
{
- DBUG_ENTER("multi_delete_precheck");
SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
- TABLE_LIST *delete_tables= (TABLE_LIST *)select_lex->table_list.first;
- TABLE_LIST *target_tbl;
-
- *table_count= 0;
+ DBUG_ENTER("multi_delete_precheck");
/* sql_yacc guarantees that tables and aux_tables are not zero */
DBUG_ASSERT(aux_tables != 0);
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
check_table_access(thd,SELECT_ACL, tables,0) ||
check_table_access(thd,DELETE_ACL, aux_tables,0))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
{
- my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
+ DBUG_RETURN(TRUE);
}
- for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next)
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Link tables in auxilary table list of multi-delete with corresponding
+ elements in main table list, and set proper locks for them.
+
+ SYNOPSIS
+ multi_delete_set_locks_and_link_aux_tables()
+ lex - pointer to LEX representing multi-delete
+
+ RETURN VALUE
+ FALSE - success
+ TRUE - error
+*/
+
+bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
+{
+ TABLE_LIST *tables= (TABLE_LIST*)lex->select_lex.table_list.first;
+ TABLE_LIST *target_tbl;
+ DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables");
+
+ lex->table_count= 0;
+
+ for (target_tbl= (TABLE_LIST *)lex->auxilliary_table_list.first;
+ target_tbl; target_tbl= target_tbl->next_local)
{
- (*table_count)++;
+ lex->table_count++;
/* All tables in aux_tables must be found in FROM PART */
TABLE_LIST *walk;
- walk= get_table_by_alias(delete_tables,target_tbl->db,target_tbl->alias);
- if (!walk)
+ for (walk= tables; walk; walk= walk->next_local)
{
- my_error(ER_UNKNOWN_TABLE, MYF(0), target_tbl->real_name,
- "MULTI DELETE");
- DBUG_RETURN(-1);
+ if (!my_strcasecmp(table_alias_charset,
+ target_tbl->alias, walk->alias) &&
+ !strcmp(walk->db, target_tbl->db))
+ break;
}
- if (walk->derived)
+ if (!walk)
{
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), target_tbl->real_name,
- "DELETE");
- DBUG_RETURN(-1);
+ my_error(ER_UNKNOWN_TABLE, MYF(0),
+ target_tbl->table_name, "MULTI DELETE");
+ DBUG_RETURN(TRUE);
}
+ target_tbl->table_name= walk->table_name;
+ target_tbl->table_name_length= walk->table_name_length;
+ walk->updating= target_tbl->updating;
walk->lock_type= target_tbl->lock_type;
- target_tbl->table_list= walk; // Remember corresponding table
-
- /* in case of subselects, we need to set lock_type in
- * corresponding table in list of all tables */
- if (walk->table_list)
- {
- target_tbl->table_list= walk->table_list;
- walk->table_list->lock_type= walk->lock_type;
- }
+ target_tbl->correspondent_table= walk; // Remember corresponding table
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -5638,21 +7194,20 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
tables Global table list
RETURN VALUE
- 0 OK
- 1 Error (message is sent to user)
- -1 Error (message is not sent to user)
+ FALSE OK
+ TRUE Error
*/
-int update_precheck(THD *thd, TABLE_LIST *tables)
+bool update_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("update_precheck");
if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements)
{
- my_error(ER_WRONG_VALUE_COUNT, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN((check_db_used(thd, tables) ||
- check_one_table_access(thd, UPDATE_ACL, tables)) ? 1 : 0);
+ DBUG_RETURN(check_db_used(thd, tables) ||
+ check_one_table_access(thd, UPDATE_ACL, tables));
}
@@ -5665,19 +7220,18 @@ int update_precheck(THD *thd, TABLE_LIST *tables)
tables Global table list
RETURN VALUE
- 0 OK
- 1 error (message is sent to user)
- -1 error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int delete_precheck(THD *thd, TABLE_LIST *tables)
+bool delete_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("delete_precheck");
if (check_one_table_access(thd, DELETE_ACL, tables))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
/* Set privilege for the WHERE clause */
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -5690,12 +7244,11 @@ int delete_precheck(THD *thd, TABLE_LIST *tables)
tables Global table list
RETURN VALUE
- 0 OK
- 1 error (message is sent to user)
- -1 error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int insert_precheck(THD *thd, TABLE_LIST *tables)
+bool insert_precheck(THD *thd, TABLE_LIST *tables)
{
LEX *lex= thd->lex;
DBUG_ENTER("insert_precheck");
@@ -5704,19 +7257,19 @@ int insert_precheck(THD *thd, TABLE_LIST *tables)
Check that we have modify privileges for the first table and
select privileges for the rest
*/
- ulong privilege= INSERT_ACL |
- (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) |
- (lex->duplicates == DUP_UPDATE ? UPDATE_ACL : 0);
+ ulong privilege= (INSERT_ACL |
+ (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) |
+ (lex->value_list.elements ? UPDATE_ACL : 0));
if (check_one_table_access(thd, privilege, tables))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
if (lex->update_list.elements != lex->value_list.elements)
{
- my_error(ER_WRONG_VALUE_COUNT, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -5730,24 +7283,25 @@ int insert_precheck(THD *thd, TABLE_LIST *tables)
create_table Table which will be created
RETURN VALUE
- 0 OK
- 1 Error (message is sent to user)
+ FALSE OK
+ TRUE Error
*/
-int create_table_precheck(THD *thd, TABLE_LIST *tables,
- TABLE_LIST *create_table)
+bool create_table_precheck(THD *thd, TABLE_LIST *tables,
+ TABLE_LIST *create_table)
{
LEX *lex= thd->lex;
SELECT_LEX *select_lex= &lex->select_lex;
ulong want_priv;
- int error= 1; // Error message is given
+ bool error= TRUE; // Error message is given
DBUG_ENTER("create_table_precheck");
want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
CREATE_TMP_ACL : CREATE_ACL);
lex->create_info.alias= create_table->alias;
if (check_access(thd, want_priv, create_table->db,
- &create_table->grant.privilege, 0, 0) ||
+ &create_table->grant.privilege, 0, 0,
+ test(create_table->schema_table)) ||
check_merge_table_access(thd, create_table->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
@@ -5760,38 +7314,31 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables,
{
/* Check permissions for used tables in CREATE TABLE ... SELECT */
+#ifdef NOT_NECESSARY_TO_CHECK_CREATE_TABLE_EXIST_WHEN_PREPARING_STATEMENT
+ /* This code throws an ill error for CREATE TABLE t1 SELECT * FROM t1 */
/*
- For temporary tables or PREPARED STATEMETNS we don't have to check
- if the created table exists
+ Only do the check for PS, becasue we on execute we have to check that
+ against the opened tables to ensure we don't use a table that is part
+ of the view (which can only be done after the table has been opened).
*/
- if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- ! thd->current_arena->is_stmt_prepare() &&
- find_real_table_in_list(tables, create_table->db,
- create_table->real_name))
- {
- net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name);
-
- goto err;
- }
- if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
+ if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
{
- TABLE_LIST *tab;
- for (tab= tables; tab; tab= tab->next)
+ /*
+ For temporary tables we don't have to check if the created table exists
+ */
+ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
+ find_table_in_global_list(tables, create_table->db,
+ create_table->table_name))
{
- if (find_real_table_in_list((TABLE_LIST*) lex->create_info.
- merge_list.first,
- tables->db, tab->real_name))
- {
- net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name);
- goto err;
- }
- }
- }
-
+ error= FALSE;
+ goto err;
+ }
+ }
+#endif
if (tables && check_table_access(thd, SELECT_ACL, tables,0))
goto err;
}
- error= 0;
+ error= FALSE;
err:
DBUG_RETURN(error);
@@ -5803,7 +7350,7 @@ err:
SYNOPSIS
negate_expression()
- thd therad handler
+ thd thread handler
expr expression for negation
RETURN
@@ -5832,3 +7379,34 @@ Item *negate_expression(THD *thd, Item *expr)
return negated;
return new Item_func_not(expr);
}
+
+
+/*
+ Assign as view definer current user
+
+ SYNOPSIS
+ default_definer()
+ thd thread handler
+ definer structure where it should be assigned
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+bool default_view_definer(THD *thd, st_lex_user *definer)
+{
+ definer->user.str= thd->priv_user;
+ definer->user.length= strlen(thd->priv_user);
+ if (*thd->priv_host != 0)
+ {
+ definer->host.str= thd->priv_host;
+ definer->host.length= strlen(thd->priv_host);
+ }
+ else
+ {
+ my_error(ER_NO_VIEW_USER, MYF(0));
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 8a50d0bd50e..6eea101de8f 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -15,77 +15,85 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/**********************************************************************
-This file contains the implementation of prepare and executes.
+This file contains the implementation of prepared statements.
-Prepare:
+When one prepares a statement:
- - Server gets the query from client with command 'COM_PREPARE';
+ - Server gets the query from client with command 'COM_STMT_PREPARE';
in the following format:
- [COM_PREPARE:1] [query]
- - Parse the query and recognize any parameter markers '?' and
+ [COM_STMT_PREPARE:1] [query]
+ - Parse the query and recognize any parameter markers '?' and
store its information list in lex->param_list
- - Allocate a new statement for this prepare; and keep this in
- 'thd->prepared_statements' pool.
- - Without executing the query, return back to client the total
+ - Allocate a new statement for this prepare; and keep this in
+ 'thd->stmt_map'.
+ - Without executing the query, return back to client the total
number of parameters along with result-set metadata information
(if any) in the following format:
[STMT_ID:4]
[Column_count:2]
[Param_count:2]
+ [Params meta info (stubs only for now)] (if Param_count > 0)
[Columns meta info] (if Column_count > 0)
- [Params meta info] (if Param_count > 0 ) (TODO : 4.1.1)
-
-Prepare-execute:
-
- - Server gets the command 'COM_EXECUTE' to execute the
- previously prepared query. If there is any param markers; then client
- will send the data in the following format:
- [COM_EXECUTE:1]
+
+When one executes a statement:
+
+ - Server gets the command 'COM_STMT_EXECUTE' to execute the
+ previously prepared query. If there are any parameter markers, then the
+ client will send the data in the following format:
+ [COM_STMT_EXECUTE:1]
[STMT_ID:4]
[NULL_BITS:(param_count+7)/8)]
[TYPES_SUPPLIED_BY_CLIENT(0/1):1]
[[length]data]
- [[length]data] .. [[length]data].
- (Note: Except for string/binary types; all other types will not be
+ [[length]data] .. [[length]data].
+ (Note: Except for string/binary types; all other types will not be
supplied with length field)
- - Replace the param items with this new data. If it is a first execute
- or types altered by client; then setup the conversion routines.
- - Execute the query without re-parsing and send back the results
+ - If it is a first execute or types of parameters were altered by client,
+ then setup the conversion routines.
+ - Assign parameter items from the supplied data.
+ - Execute the query without re-parsing and send back the results
to client
-Long data handling:
+When one supplies long data for a placeholder:
- - Server gets the long data in pieces with command type 'COM_LONG_DATA'.
+ - Server gets the long data in pieces with command type
+ 'COM_STMT_SEND_LONG_DATA'.
- The packet recieved will have the format as:
- [COM_LONG_DATA:1][STMT_ID:4][parameter_number:2][data]
- - data from the packet is appended to long data value buffer for this
+ [COM_STMT_SEND_LONG_DATA:1][STMT_ID:4][parameter_number:2][data]
+ - data from the packet is appended to the long data value buffer for this
placeholder.
- - It's up to the client to check for read data ended. The server doesn't
- care; and also server doesn't notify to the client that it got the
- data or not; if there is any error; then during execute; the error
- will be returned
+ - It's up to the client to stop supplying data chunks at any point. The
+ server doesn't care; also, the server doesn't notify the client whether
+ it got the data or not; if there is any error, then it will be returned
+ at statement execute.
***********************************************************************/
#include "mysql_priv.h"
#include "sql_select.h" // for JOIN
-#include <m_ctype.h> // for isspace()
+#include "sp_head.h"
+#include "sp.h"
+#include "sp_cache.h"
#ifdef EMBEDDED_LIBRARY
/* include MYSQL_BIND headers */
#include <mysql.h>
+#else
+#include <mysql_com.h>
#endif
/******************************************************************************
- Prepared_statement: statement which can contain placeholders
+ Prepared_statement: a statement that can contain placeholders
******************************************************************************/
class Prepared_statement: public Statement
{
public:
THD *thd;
+ Protocol *protocol;
Item_param **param_array;
uint param_count;
uint last_errno;
+ uint flags;
char last_error[MYSQL_ERRMSG_SIZE];
#ifndef EMBEDDED_LIBRARY
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
@@ -93,18 +101,34 @@ public:
#else
bool (*set_params_data)(Prepared_statement *st, String *expanded_query);
#endif
- bool (*set_params_from_vars)(Prepared_statement *stmt,
+ bool (*set_params_from_vars)(Prepared_statement *stmt,
List<LEX_STRING>& varnames,
String *expanded_query);
public:
- Prepared_statement(THD *thd_arg);
+ Prepared_statement(THD *thd_arg, Protocol *protocol_arg);
virtual ~Prepared_statement();
void setup_set_params();
- virtual Item_arena::Type type() const;
+ virtual Query_arena::Type type() const;
+ virtual void close_cursor();
+ bool set_name(LEX_STRING *name);
+
+ bool prepare(const char *packet, uint packet_length);
+ bool execute(String *expanded_query, bool open_cursor);
+ /* Destroy this statement */
+ bool deallocate();
+
+ /* Possible values of flags */
+#if defined(_MSC_VER) && _MSC_VER < 1300
+ static const int IS_IN_USE;
+#else
+ static const int IS_IN_USE= 1;
+#endif
};
-static void execute_stmt(THD *thd, Prepared_statement *stmt,
- String *expanded_query, bool set_context);
+/* VC6 can't handle initializing in declaration */
+#if defined(_MSC_VER) && _MSC_VER < 1300
+const int Prepared_statement::IS_IN_USE= 1;
+#endif
/******************************************************************************
Implementation
@@ -118,25 +142,38 @@ inline bool is_param_null(const uchar *pos, ulong param_no)
enum { STMT_QUERY_LOG_LENGTH= 8192 };
-enum enum_send_error { DONT_SEND_ERROR= 0, SEND_ERROR };
-
/*
- Seek prepared statement in statement map by id: returns zero if statement
- was not found, pointer otherwise.
+ Find a prepared statement in the statement map by id.
+
+ SYNOPSIS
+ find_prepared_statement()
+ thd thread handle
+ id statement id
+ where the place from which this function is called (for
+ error reporting).
+
+ DESCRIPTION
+ Try to find a prepared statement and set THD error if it's not found.
+
+ RETURN VALUE
+ 0 if the statement was not found, a pointer otherwise.
*/
static Prepared_statement *
-find_prepared_statement(THD *thd, ulong id, const char *where,
- enum enum_send_error se)
+find_prepared_statement(THD *thd, ulong id, const char *where)
{
+ /*
+ To strictly separate namespaces of SQL prepared statements and C API
+ prepared statements find() will return 0 if there is a named prepared
+ statement with such id.
+ */
Statement *stmt= thd->stmt_map.find(id);
- if (stmt == 0 || stmt->type() != Item_arena::PREPARED_STATEMENT)
+ if (stmt == 0 || stmt->type() != Query_arena::PREPARED_STATEMENT)
{
char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where);
- if (se == SEND_ERROR)
- send_error(thd);
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf), llstr(id, llbuf),
+ where);
return 0;
}
return (Prepared_statement *) stmt;
@@ -144,29 +181,40 @@ find_prepared_statement(THD *thd, ulong id, const char *where,
/*
- Send prepared stmt info to client after prepare
+ Send prepared statement id and metadata to the client after prepare.
+
+ SYNOPSIS
+ send_prep_stmt()
+
+ RETURN VALUE
+ 0 in case of success, 1 otherwise
*/
#ifndef EMBEDDED_LIBRARY
static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
{
NET *net= &stmt->thd->net;
- char buff[9];
+ char buff[12];
+ uint tmp;
DBUG_ENTER("send_prep_stmt");
buff[0]= 0; /* OK packet indicator */
int4store(buff+1, stmt->id);
int2store(buff+5, columns);
int2store(buff+7, stmt->param_count);
+ buff[9]= 0; // Guard against a 4.1 client
+ tmp= min(stmt->thd->total_warn_count, 65535);
+ int2store(buff+10, tmp);
+
/*
Send types and names of placeholders to the client
XXX: fix this nasty upcast from List<Item_param> to List<Item>
*/
- DBUG_RETURN(my_net_write(net, buff, sizeof(buff)) ||
+ DBUG_RETURN(my_net_write(net, buff, sizeof(buff)) ||
(stmt->param_count &&
stmt->thd->protocol_simple.send_fields((List<Item> *)
&stmt->lex->param_list,
- 0)));
+ Protocol::SEND_EOF)));
}
#else
static bool send_prep_stmt(Prepared_statement *stmt,
@@ -176,7 +224,7 @@ static bool send_prep_stmt(Prepared_statement *stmt,
thd->client_stmt_id= stmt->id;
thd->client_param_count= stmt->param_count;
- thd->net.last_errno= 0;
+ thd->clear_error();
return 0;
}
@@ -184,8 +232,20 @@ static bool send_prep_stmt(Prepared_statement *stmt,
/*
- Read the length of the parameter data and return back to
- caller by positing the pointer to param data.
+ Read the length of the parameter data and return it back to
+ the caller.
+
+ SYNOPSIS
+ get_param_length()
+ packet a pointer to the data
+ len remaining packet length
+
+ DESCRIPTION
+ Read data length, position the packet to the first byte after it,
+ and return the length to the caller.
+
+ RETURN VALUE
+ Length of data piece.
*/
#ifndef EMBEDDED_LIBRARY
@@ -215,7 +275,7 @@ static ulong get_param_length(uchar **packet, ulong len)
}
if (len < 5)
return 0;
- (*packet)+=9; // Must be 254 when here
+ (*packet)+=9; // Must be 254 when here
/*
In our client-server protocol all numbers bigger than 2^24
stored as 8 bytes with uint8korr. Here we always know that
@@ -230,19 +290,21 @@ static ulong get_param_length(uchar **packet, ulong len)
#endif /*!EMBEDDED_LIBRARY*/
/*
- Data conversion routines
+ Data conversion routines.
+
SYNOPSIS
- set_param_xx()
- param parameter item
- pos input data buffer
- len length of data in the buffer
+ set_param_xx()
+ param parameter item
+ pos input data buffer
+ len length of data in the buffer
- All these functions read the data from pos, convert it to requested type
- and assign to param; pos is advanced to predefined length.
+ DESCRIPTION
+ All these functions read the data from pos, convert it to requested
+ type and assign to param; pos is advanced to predefined length.
- Make a note that the NULL handling is examined at first execution
- (i.e. when input types altered) and for all subsequent executions
- we don't read any values for this.
+ Make a note that the NULL handling is examined at first execution
+ (i.e. when input types altered) and for all subsequent executions
+ we don't read any values for this.
RETURN VALUE
none
@@ -255,7 +317,7 @@ static void set_param_tiny(Item_param *param, uchar **pos, ulong len)
return;
#endif
int8 value= (int8) **pos;
- param->set_int(param->unsigned_flag ? (longlong) ((uint8) value) :
+ param->set_int(param->unsigned_flag ? (longlong) ((uint8) value) :
(longlong) value, 4);
*pos+= 1;
}
@@ -332,6 +394,13 @@ static void set_param_double(Item_param *param, uchar **pos, ulong len)
*pos+= 8;
}
+static void set_param_decimal(Item_param *param, uchar **pos, ulong len)
+{
+ ulong length= get_param_length(pos, len);
+ param->set_decimal((char*)*pos, length);
+ *pos+= len;
+}
+
#ifndef EMBEDDED_LIBRARY
/*
@@ -403,6 +472,7 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
*pos+= length;
}
+
static void set_param_date(Item_param *param, uchar **pos, ulong len)
{
MYSQL_TIME tm;
@@ -471,7 +541,7 @@ static void set_param_str(Item_param *param, uchar **pos, ulong len)
}
-#undef get_param_length
+#undef get_param_length
static void setup_one_conversion_function(THD *thd, Item_param *param,
uchar param_type)
@@ -507,6 +577,12 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
param->item_type= Item::REAL_ITEM;
param->item_result_type= REAL_RESULT;
break;
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ param->set_param_func= set_param_decimal;
+ param->item_type= Item::DECIMAL_ITEM;
+ param->item_result_type= DECIMAL_RESULT;
+ break;
case MYSQL_TYPE_TIME:
param->set_param_func= set_param_time;
param->item_type= Item::STRING_ITEM;
@@ -571,25 +647,52 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
#ifndef EMBEDDED_LIBRARY
/*
- Update the parameter markers by reading data from client packet
- and if binary/update log is set, generate the valid query.
+ Routines to assign parameters from data supplied by the client.
+
+ DESCRIPTION
+ Update the parameter markers by reading data from the packet and
+ and generate a valid query for logging.
+
+ NOTES
+ This function, along with other _withlog functions is called when one of
+ binary, slow or general logs is open. Logging of prepared statements in
+ all cases is performed by means of conventional queries: if parameter
+ data was supplied from C API, each placeholder in the query is
+ replaced with its actual value; if we're logging a [Dynamic] SQL
+ prepared statement, parameter markers are replaced with variable names.
+ Example:
+ mysql_stmt_prepare("UPDATE t1 SET a=a*1.25 WHERE a=?")
+ --> general logs gets [Prepare] UPDATE t1 SET a*1.25 WHERE a=?"
+ mysql_stmt_execute(stmt);
+ --> general and binary logs get
+ [Execute] UPDATE t1 SET a*1.25 WHERE a=1"
+ If a statement has been prepared using SQL syntax:
+ PREPARE stmt FROM "UPDATE t1 SET a=a*1.25 WHERE a=?"
+ --> general log gets
+ [Query] PREPARE stmt FROM "UPDATE ..."
+ EXECUTE stmt USING @a
+ --> general log gets
+ [Query] EXECUTE stmt USING @a;
+
+ RETURN VALUE
+ 0 if success, 1 otherwise
*/
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;
+ String str;
const String *res;
- DBUG_ENTER("insert_params_withlog");
+ DBUG_ENTER("insert_params_withlog");
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;
@@ -610,7 +713,7 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
if (query->replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
-
+
length+= res->length()-1;
}
DBUG_RETURN(0);
@@ -618,13 +721,13 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
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;
- DBUG_ENTER("insert_params");
+ DBUG_ENTER("insert_params");
for (Item_param **it= begin; it < end; ++it)
{
@@ -658,7 +761,7 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
if (*read_pos++) //types supplied / first execute
{
/*
- First execute or types altered by the client, setup the
+ First execute or types altered by the client, setup the
conversion routines for all parameters (one time)
*/
Item_param **it= stmt->param_array;
@@ -684,6 +787,17 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
#else
+/*
+ Embedded counterparts of parameter assignment routines.
+
+ DESCRIPTION
+ The main difference between the embedded library and the server is
+ that in embedded case we don't serialize/deserialize parameters data.
+ Additionally, for unknown reason, the client-side flag raised for
+ changed types of placeholders is ignored and we simply setup conversion
+ functions at each execute (TODO: fix).
+*/
+
static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query)
{
THD *thd= stmt->thd;
@@ -706,8 +820,8 @@ static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query)
uchar *buff= (uchar*) client_param->buffer;
param->unsigned_flag= client_param->is_unsigned;
param->set_param_func(param, &buff,
- client_param->length ?
- *client_param->length :
+ client_param->length ?
+ *client_param->length :
client_param->buffer_length);
}
}
@@ -733,7 +847,7 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query)
if (query->copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
-
+
for (; it < end; ++it, ++client_param)
{
Item_param *param= *it;
@@ -745,10 +859,10 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query)
else
{
uchar *buff= (uchar*)client_param->buffer;
- param->unsigned_flag= client_param->is_unsigned;
+ param->unsigned_flag= client_param->is_unsigned;
param->set_param_func(param, &buff,
- client_param->length ?
- *client_param->length :
+ client_param->length ?
+ *client_param->length :
client_param->buffer_length);
}
}
@@ -768,7 +882,8 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query)
/*
- Set prepared statement parameters from user variables.
+ Assign prepared statement parameters from user variables.
+
SYNOPSIS
insert_params_from_vars()
stmt Statement
@@ -806,12 +921,14 @@ static bool insert_params_from_vars(Prepared_statement *stmt,
/*
Do the same as insert_params_from_vars but also construct query text for
binary log.
+
SYNOPSIS
insert_params_from_vars()
- stmt Statement
+ stmt Prepared 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
+ query The query with parameter markers replaced with corresponding
+ user variables that were used to execute the query.
*/
static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
@@ -822,12 +939,13 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
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 buf;
const String *val;
uint32 length= 0;
+
+ DBUG_ENTER("insert_params_from_vars");
+
if (query->copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
@@ -835,7 +953,8 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
{
Item_param *param= *it;
varname= var_it++;
- if (get_var_with_binlog(stmt->thd, *varname, &entry))
+ if (get_var_with_binlog(stmt->thd, stmt->lex->sql_command,
+ *varname, &entry))
DBUG_RETURN(1);
if (param->set_from_user_var(stmt->thd, entry))
@@ -852,7 +971,8 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
*ptr++= '@';
*ptr++= '\'';
ptr+= escape_string_for_mysql(&my_charset_utf8_general_ci,
- ptr, entry->name.str, entry->name.length);
+ ptr, 0, entry->name.str,
+ entry->name.length);
*ptr++= '\'';
buf.length(ptr - begin);
val= &buf;
@@ -871,86 +991,91 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
}
/*
- Validate INSERT statement:
+ Validate INSERT statement.
SYNOPSIS
mysql_test_insert()
- stmt prepared statemen handler
- tables list of tables queries
+ stmt prepared statement
+ tables global/local table list
RETURN VALUE
- 0 ok
- 1 error, sent to the client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, error message is set in THD
*/
-static int mysql_test_insert(Prepared_statement *stmt,
- TABLE_LIST *table_list,
- List<Item> &fields,
- List<List_item> &values_list,
- List<Item> &update_fields,
- List<Item> &update_values,
- enum_duplicates duplic)
+
+static bool mysql_test_insert(Prepared_statement *stmt,
+ TABLE_LIST *table_list,
+ List<Item> &fields,
+ List<List_item> &values_list,
+ List<Item> &update_fields,
+ List<Item> &update_values,
+ enum_duplicates duplic)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
List_iterator_fast<List_item> its(values_list);
List_item *values;
- int res= -1;
- TABLE_LIST *insert_table_list=
- (TABLE_LIST*) lex->select_lex.table_list.first;
DBUG_ENTER("mysql_test_insert");
- if ((res= insert_precheck(thd, table_list)))
- DBUG_RETURN(res);
+ if (insert_precheck(thd, table_list))
+ goto error;
/*
- open temporary memory pool for temporary data allocated by derived
- tables & preparation procedure
- Note that this is done without locks (should not be needed as we will not
- access any data here)
- If we would use locks, then we have to ensure we are not using
- TL_WRITE_DELAYED as having two such locks can cause table corruption.
+ open temporary memory pool for temporary data allocated by derived
+ tables & preparation procedure
+ Note that this is done without locks (should not be needed as we will not
+ access any data here)
+ If we would use locks, then we have to ensure we are not using
+ TL_WRITE_DELAYED as having two such locks can cause table corruption.
*/
- if (open_normal_and_derived_tables(thd, table_list))
- {
- DBUG_RETURN(-1);
- }
+ if (open_normal_and_derived_tables(thd, table_list, 0))
+ goto error;
if ((values= its++))
{
uint value_count;
ulong counter= 0;
+ Item *unused_conds= 0;
+
+ if (table_list->table)
+ {
+ // don't allocate insert_values
+ table_list->table->insert_values=(byte *)1;
+ }
- table_list->table->insert_values=(byte *)1; // don't allocate insert_values
- if ((res= mysql_prepare_insert(thd, table_list, insert_table_list,
- insert_table_list,
- table_list->table, fields, values,
- update_fields, update_values, duplic)))
+ if (mysql_prepare_insert(thd, table_list, table_list->table,
+ fields, values, update_fields, update_values,
+ duplic, &unused_conds, FALSE))
goto error;
value_count= values->elements;
its.rewind();
+ if (table_list->lock_type == TL_WRITE_DELAYED &&
+ !(table_list->table->file->table_flags() & HA_CAN_INSERT_DELAYED))
+ {
+ my_error(ER_ILLEGAL_HA, MYF(0), (table_list->view ?
+ table_list->view_name.str :
+ table_list->table_name));
+ goto error;
+ }
while ((values= its++))
{
counter++;
if (values->elements != value_count)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0), counter);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto error;
}
- if (setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0))
- goto error;
+ if (setup_fields(thd, 0, *values, 0, 0, 0))
+ goto error;
}
}
+ DBUG_RETURN(FALSE);
- res= 0;
error:
- lex->unit.cleanup();
- table_list->table->insert_values=0;
- DBUG_RETURN(res);
+ /* insert_values is cleared in open_table */
+ DBUG_RETURN(TRUE);
}
@@ -959,211 +1084,240 @@ error:
SYNOPSIS
mysql_test_update()
- stmt prepared statemen handler
- tables list of tables queries
+ stmt prepared statement
+ tables list of tables used in this query
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ 0 success
+ 1 error, error message is set in THD
+ 2 convert to multi_update
*/
+
static int mysql_test_update(Prepared_statement *stmt,
- TABLE_LIST *table_list)
+ TABLE_LIST *table_list)
{
int res;
THD *thd= stmt->thd;
+ uint table_count= 0;
SELECT_LEX *select= &stmt->lex->select_lex;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint want_privilege;
+#endif
+ bool need_reopen;
DBUG_ENTER("mysql_test_update");
- if ((res= update_precheck(thd, table_list)))
- DBUG_RETURN(res);
+ if (update_precheck(thd, table_list))
+ goto error;
- if (open_and_lock_tables(thd, table_list))
- res= -1;
- else
+ for ( ; ; )
{
- TABLE_LIST *update_table_list= (TABLE_LIST *)select->table_list.first;
- if (!(res= mysql_prepare_update(thd, table_list,
- update_table_list,
- &select->where,
- select->order_list.elements,
- (ORDER *) select->order_list.first)))
+ if (open_tables(thd, &table_list, &table_count, 0))
+ goto error;
+
+ if (table_list->multitable_view)
{
- if (setup_fields(thd, 0, update_table_list,
- select->item_list, 1, 0, 0) ||
- setup_fields(thd, 0, update_table_list,
- stmt->lex->value_list, 0, 0, 0))
- res= -1;
+ DBUG_ASSERT(table_list->view != 0);
+ DBUG_PRINT("info", ("Switch to multi-update"));
+ /* pass counter value */
+ thd->lex->table_count= table_count;
+ /* convert to multiupdate */
+ DBUG_RETURN(2);
}
- stmt->lex->unit.cleanup();
+
+ if (!lock_tables(thd, table_list, table_count, &need_reopen))
+ break;
+ if (!need_reopen)
+ goto error;
+ close_tables_for_reopen(thd, table_list);
}
- /* TODO: here we should send types of placeholders to the client. */
- DBUG_RETURN(res);
+
+ /*
+ thd->fill_derived_tables() is false here for sure (because it is
+ preparation of PS, so we even do not check it).
+ */
+ if (mysql_handle_derived(thd->lex, &mysql_derived_prepare))
+ goto error;
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* TABLE_LIST contain right privilages request */
+ want_privilege= table_list->grant.want_privilege;
+#endif
+
+ if (mysql_prepare_update(thd, table_list, &select->where,
+ select->order_list.elements,
+ (ORDER *) select->order_list.first))
+ goto error;
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ table_list->grant.want_privilege= want_privilege;
+ table_list->table->grant.want_privilege= want_privilege;
+#endif
+ thd->lex->select_lex.no_wrap_view_item= TRUE;
+ res= setup_fields(thd, 0, select->item_list, 1, 0, 0);
+ thd->lex->select_lex.no_wrap_view_item= FALSE;
+ if (res)
+ goto error;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* Check values */
+ table_list->grant.want_privilege=
+ table_list->table->grant.want_privilege=
+ (SELECT_ACL & ~table_list->table->grant.privilege);
+#endif
+ if (setup_fields(thd, 0, stmt->lex->value_list, 0, 0, 0))
+ goto error;
+ /* TODO: here we should send types of placeholders to the client. */
+ DBUG_RETURN(0);
+error:
+ DBUG_RETURN(1);
}
/*
- Validate DELETE statement
+ Validate DELETE statement.
SYNOPSIS
mysql_test_delete()
- stmt prepared statemen handler
- tables list of tables queries
+ stmt prepared statement
+ tables list of tables used in this query
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, error message is set in THD
*/
-static int mysql_test_delete(Prepared_statement *stmt,
- TABLE_LIST *table_list)
+
+static bool mysql_test_delete(Prepared_statement *stmt,
+ TABLE_LIST *table_list)
{
- int res;
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
DBUG_ENTER("mysql_test_delete");
- if ((res= delete_precheck(thd, table_list)))
- DBUG_RETURN(res);
+ if (delete_precheck(thd, table_list) ||
+ open_and_lock_tables(thd, table_list))
+ goto error;
- if (open_and_lock_tables(thd, table_list))
- res= -1;
- else
+ if (!table_list->table)
{
- res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
- lex->unit.cleanup();
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ goto error;
}
- /* TODO: here we should send types of placeholders to the client. */
- DBUG_RETURN(res);
+
+ DBUG_RETURN(mysql_prepare_delete(thd, table_list, &lex->select_lex.where));
+error:
+ DBUG_RETURN(TRUE);
}
/*
Validate SELECT statement.
- In case of success, if this query is not EXPLAIN, send column list info
- back to client.
SYNOPSIS
mysql_test_select()
- stmt prepared statemen handler
- tables list of tables queries
+ stmt prepared statement
+ tables list of tables used in the query
+
+ DESCRIPTION
+ In case of success, if this query is not EXPLAIN, send column list info
+ back to the client.
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ 0 success
+ 1 error, error message is set in THD
+ 2 success, and statement metadata has been sent
*/
static int mysql_test_select(Prepared_statement *stmt,
- TABLE_LIST *tables, bool text_protocol)
+ TABLE_LIST *tables, bool text_protocol)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
SELECT_LEX_UNIT *unit= &lex->unit;
- int result= 1;
DBUG_ENTER("mysql_test_select");
+ lex->select_lex.context.resolve_in_select_list= TRUE;
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
if (tables)
{
if (check_table_access(thd, privilege, tables,0))
- DBUG_RETURN(1);
+ goto error;
}
- else if (check_access(thd, privilege, any_db,0,0,0))
- DBUG_RETURN(1);
+ else if (check_access(thd, privilege, any_db,0,0,0,0))
+ goto error;
#endif
if (!lex->result && !(lex->result= new (stmt->mem_root) select_send))
{
- send_error(thd);
- goto err;
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(select_send));
+ goto error;
}
if (open_and_lock_tables(thd, tables))
- {
- send_error(thd);
- goto err;
- }
+ goto error;
thd->used_tables= 0; // Updated by setup_fields
- // JOIN::prepare calls
+ /*
+ JOIN::prepare calls
+ It is not SELECT COMMAND for sure, so setup_tables will be called as
+ usual, and we pass 0 as setup_tables_done_option
+ */
if (unit->prepare(thd, 0, 0, ""))
+ goto error;
+ if (!lex->describe && !text_protocol)
{
- send_error(thd);
- goto err_prep;
- }
- if (!text_protocol)
- {
- if (lex->describe)
- {
- if (send_prep_stmt(stmt, 0) || thd->protocol->flush())
- goto err_prep;
- }
- else
- {
- /* Make copy of item list, as change_columns may change it */
- List<Item> fields(lex->select_lex.item_list);
+ /* Make copy of item list, as change_columns may change it */
+ List<Item> fields(lex->select_lex.item_list);
- /* Change columns if a procedure like analyse() */
- if (unit->last_procedure &&
- unit->last_procedure->change_columns(fields))
- goto err_prep;
+ /* Change columns if a procedure like analyse() */
+ if (unit->last_procedure && unit->last_procedure->change_columns(fields))
+ goto error;
- /*
- We can use lex->result as it should've been
- prepared in unit->prepare call above.
- */
- if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
- lex->result->send_fields(fields, 0) ||
- thd->protocol->flush())
- goto err_prep;
- }
+ /*
+ We can use lex->result as it should've been prepared in
+ unit->prepare call above.
+ */
+ if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
+ lex->result->send_fields(fields, Protocol::SEND_EOF) ||
+ thd->protocol->flush())
+ goto error;
+ DBUG_RETURN(2);
}
- result= 0; // ok
-
-err_prep:
- unit->cleanup();
-err:
- DBUG_RETURN(result);
+ DBUG_RETURN(0);
+error:
+ DBUG_RETURN(1);
}
/*
- Validate and prepare for execution DO statement expressions
+ Validate and prepare for execution DO statement expressions.
SYNOPSIS
mysql_test_do_fields()
- stmt prepared statemen handler
- tables list of tables queries
- values list of expressions
+ stmt prepared statement
+ tables list of tables used in this query
+ values list of expressions
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, error message is set in THD
*/
-static int mysql_test_do_fields(Prepared_statement *stmt,
- TABLE_LIST *tables,
- List<Item> *values)
+static bool mysql_test_do_fields(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ List<Item> *values)
{
- DBUG_ENTER("mysql_test_do_fields");
THD *thd= stmt->thd;
- int res= 0;
- if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
- DBUG_RETURN(res);
- if (tables && (res= open_and_lock_tables(thd, tables)))
- {
- DBUG_RETURN(res);
- }
- res= setup_fields(thd, 0, 0, *values, 0, 0, 0);
- stmt->lex->unit.cleanup();
- if (res)
- DBUG_RETURN(-1);
- DBUG_RETURN(0);
+ DBUG_ENTER("mysql_test_do_fields");
+ if (tables && check_table_access(thd, SELECT_ACL, tables, 0))
+ DBUG_RETURN(TRUE);
+
+ if (open_and_lock_tables(thd, tables))
+ DBUG_RETURN(TRUE);
+ DBUG_RETURN(setup_fields(thd, 0, *values, 0, 0, 0));
}
@@ -1172,42 +1326,36 @@ static int mysql_test_do_fields(Prepared_statement *stmt,
SYNOPSIS
mysql_test_set_fields()
- stmt prepared statemen handler
- tables list of tables queries
- values list of expressions
+ stmt prepared statement
+ tables list of tables used in this query
+ values list of expressions
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, error message is set in THD
*/
-static int mysql_test_set_fields(Prepared_statement *stmt,
- TABLE_LIST *tables,
- List<set_var_base> *var_list)
+
+static bool mysql_test_set_fields(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ List<set_var_base> *var_list)
{
DBUG_ENTER("mysql_test_set_fields");
List_iterator_fast<set_var_base> it(*var_list);
THD *thd= stmt->thd;
set_var_base *var;
- int res= 0;
-
- if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
- DBUG_RETURN(res);
- if (tables && (res= open_and_lock_tables(thd, tables)))
+ if (tables && check_table_access(thd, SELECT_ACL, tables, 0) ||
+ open_and_lock_tables(thd, tables))
goto error;
+
while ((var= it++))
{
if (var->light_check(thd))
- {
- stmt->lex->unit.cleanup();
- res= -1;
goto error;
- }
}
+ DBUG_RETURN(FALSE);
error:
- stmt->lex->unit.cleanup();
- DBUG_RETURN(res);
+ DBUG_RETURN(TRUE);
}
@@ -1215,36 +1363,76 @@ error:
Check internal SELECT of the prepared command
SYNOPSIS
- select_like_statement_test()
- stmt - prepared table handler
- tables - global list of tables
+ select_like_stmt_test()
+ stmt prepared statement
+ specific_prepare function of command specific prepare
+ setup_tables_done_option options to be passed to LEX::unit.prepare()
+
+ NOTE
+ This function won't directly open tables used in select. They should
+ be opened either by calling function (and in this case you probably
+ should use select_like_stmt_test_with_open_n_lock()) or by
+ "specific_prepare" call (like this happens in case of multi-update).
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, error message is set in THD
*/
-static int select_like_statement_test(Prepared_statement *stmt,
- TABLE_LIST *tables)
+
+static bool select_like_stmt_test(Prepared_statement *stmt,
+ bool (*specific_prepare)(THD *thd),
+ ulong setup_tables_done_option)
{
- DBUG_ENTER("select_like_statement_test");
+ DBUG_ENTER("select_like_stmt_test");
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
- int res= 0;
- if (tables && (res= open_and_lock_tables(thd, tables)))
- goto end;
+ lex->select_lex.context.resolve_in_select_list= TRUE;
+
+ if (specific_prepare && (*specific_prepare)(thd))
+ DBUG_RETURN(TRUE);
thd->used_tables= 0; // Updated by setup_fields
- // JOIN::prepare calls
- if (lex->unit.prepare(thd, 0, 0, ""))
- {
- res= thd->net.report_error ? -1 : 1;
- }
-end:
- lex->unit.cleanup();
- DBUG_RETURN(res);
+ /* Calls JOIN::prepare */
+ DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option, ""));
+}
+
+/*
+ Check internal SELECT of the prepared command (with opening and
+ locking of used tables).
+
+ SYNOPSIS
+ select_like_stmt_test_with_open_n_lock()
+ stmt prepared statement
+ tables list of tables to be opened and locked
+ before calling specific_prepare function
+ specific_prepare function of command specific prepare
+ setup_tables_done_option options to be passed to LEX::unit.prepare()
+
+ RETURN VALUE
+ FALSE success
+ TRUE error
+*/
+
+static bool
+select_like_stmt_test_with_open_n_lock(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ bool (*specific_prepare)(THD *thd),
+ ulong setup_tables_done_option)
+{
+ DBUG_ENTER("select_like_stmt_test_with_open_n_lock");
+
+ /*
+ We should not call LEX::unit.cleanup() after this open_and_lock_tables()
+ call because we don't allow prepared EXPLAIN yet so derived tables will
+ clean up after themself.
+ */
+ if (open_and_lock_tables(stmt->thd, tables))
+ DBUG_RETURN(TRUE);
+
+ DBUG_RETURN(select_like_stmt_test(stmt, specific_prepare,
+ setup_tables_done_option));
}
@@ -1253,168 +1441,240 @@ end:
SYNOPSIS
mysql_test_create_table()
- stmt prepared statemen handler
- tables list of tables queries
+ stmt prepared statement
+ tables list of tables used in this query
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, error message is set in THD
*/
-static int mysql_test_create_table(Prepared_statement *stmt,
- TABLE_LIST *tables)
+
+static bool 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;
-
+ bool res= FALSE;
/* Skip first table, which is the table we are creating */
- TABLE_LIST *create_table, *create_table_local;
- tables= lex->unlink_first_table(tables, &create_table,
- &create_table_local);
+ bool link_to_local;
+ TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
+ TABLE_LIST *tables= lex->query_tables;
+
+ if (create_table_precheck(thd, tables, create_table))
+ DBUG_RETURN(TRUE);
- if (!(res= create_table_precheck(thd, tables, create_table)) &&
- select_lex->item_list.elements)
+ if (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;
+ select_lex->context.resolve_in_select_list= TRUE;
+ res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0);
}
/* put tables back for PS rexecuting */
- tables= lex->link_first_table_back(tables, create_table,
- create_table_local);
+ lex->link_first_table_back(create_table, link_to_local);
DBUG_RETURN(res);
}
/*
- Validate and prepare for execution multi update statement
+ Validate and prepare for execution a multi update statement.
SYNOPSIS
mysql_test_multiupdate()
- stmt prepared statemen handler
- tables list of tables queries
+ stmt prepared statement
+ tables list of tables used in this query
+ converted converted to multi-update from usual update
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, error message is set in THD
*/
-static int mysql_test_multiupdate(Prepared_statement *stmt,
- TABLE_LIST *tables)
+
+static bool mysql_test_multiupdate(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ bool converted)
{
- int res;
- if ((res= multi_update_precheck(stmt->thd, tables)))
- return res;
- return select_like_statement_test(stmt, tables);
+ /* if we switched from normal update, rights are checked */
+ if (!converted && multi_update_precheck(stmt->thd, tables))
+ return TRUE;
+
+ return select_like_stmt_test(stmt, &mysql_multi_update_prepare,
+ OPTION_SETUP_TABLES_DONE);
}
/*
- Validate and prepare for execution multi delete statement
+ Validate and prepare for execution a multi delete statement.
SYNOPSIS
mysql_test_multidelete()
- stmt prepared statemen handler
- tables list of tables queries
+ stmt prepared statement
+ tables list of tables used in this query
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, error message in THD is set.
*/
-static int mysql_test_multidelete(Prepared_statement *stmt,
- TABLE_LIST *tables)
+
+static bool mysql_test_multidelete(Prepared_statement *stmt,
+ TABLE_LIST *tables)
{
- int res;
stmt->thd->lex->current_select= &stmt->thd->lex->select_lex;
if (add_item_to_list(stmt->thd, new Item_null()))
- return -1;
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), 0);
+ goto error;
+ }
- uint fake_counter;
- if ((res= multi_delete_precheck(stmt->thd, tables, &fake_counter)))
- return res;
- return select_like_statement_test(stmt, tables);
+ if (multi_delete_precheck(stmt->thd, tables) ||
+ select_like_stmt_test_with_open_n_lock(stmt, tables,
+ &mysql_multi_delete_prepare,
+ OPTION_SETUP_TABLES_DONE))
+ goto error;
+ if (!tables->table)
+ {
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ tables->view_db.str, tables->view_name.str);
+ goto error;
+ }
+ return FALSE;
+error:
+ return TRUE;
}
/*
- Validate and prepare for execution INSERT ... SELECT statement
+ Wrapper for mysql_insert_select_prepare, to make change of local tables
+ after open_and_lock_tables() call.
SYNOPSIS
- mysql_test_insert_select()
- stmt prepared statemen handler
- tables list of tables queries
+ mysql_insert_select_prepare_tester()
+ thd thread handle
- RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ NOTE
+ We need to remove the first local table after open_and_lock_tables,
+ because mysql_handle_derived uses local tables lists.
*/
-static int mysql_test_insert_select(Prepared_statement *stmt,
- TABLE_LIST *tables)
+
+static bool mysql_insert_select_prepare_tester(THD *thd)
{
- int res;
- LEX *lex= stmt->lex;
- if ((res= insert_precheck(stmt->thd, tables)))
- return res;
- TABLE_LIST *first_local_table=
- (TABLE_LIST *)lex->select_lex.table_list.first;
+ TABLE_LIST *first;
+ bool res;
+ SELECT_LEX *first_select= &thd->lex->select_lex;
/* Skip first table, which is the table we are inserting in */
- lex->select_lex.table_list.first= (byte*) first_local_table->next;
+ first_select->table_list.first= (byte*)(first=
+ ((TABLE_LIST*)first_select->
+ table_list.first)->next_local);
+ res= mysql_insert_select_prepare(thd);
/*
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*/
+ thd->lex->select_lex.context.resolve_in_select_list= TRUE;
+ thd->lex->select_lex.context.table_list= first;
+ return res;
+}
+
+
+/*
+ Validate and prepare for execution INSERT ... SELECT statement.
+
+ SYNOPSIS
+ mysql_test_insert_select()
+ stmt prepared statement
+ tables list of tables used in this query
+
+ RETURN VALUE
+ FALSE success
+ TRUE error, error message is set in THD
+*/
+
+static bool mysql_test_insert_select(Prepared_statement *stmt,
+ TABLE_LIST *tables)
+{
+ int res;
+ LEX *lex= stmt->lex;
+ TABLE_LIST *first_local_table;
+
+ if (tables->table)
+ {
+ // don't allocate insert_values
+ tables->table->insert_values=(byte *)1;
+ }
+
+ if (insert_precheck(stmt->thd, tables))
+ return 1;
+
+ /* store it, because mysql_insert_select_prepare_tester change it */
+ first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
+ DBUG_ASSERT(first_local_table != 0);
+
+ res=
+ select_like_stmt_test_with_open_n_lock(stmt, tables,
+ &mysql_insert_select_prepare_tester,
+ OPTION_SETUP_TABLES_DONE);
+ /* revert changes made by mysql_insert_select_prepare_tester */
lex->select_lex.table_list.first= (byte*) first_local_table;
- lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
return res;
}
/*
- Send the prepare query results back to client
+ Perform semantic analysis of the parsed tree and send a response packet
+ to the client.
+
SYNOPSIS
- send_prepare_results()
- stmt prepared statement
+ check_prepared_statement()
+ stmt prepared statement
+
+ DESCRIPTION
+ This function
+ - opens all tables and checks access rights
+ - validates semantics of statement columns and SQL functions
+ by calling fix_fields.
+
RETURN VALUE
- 0 success
- 1 error, sent to client
+ FALSE success, statement metadata is sent to client
+ TRUE error, error message is set in THD (but not sent)
*/
-static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
-{
+
+static bool check_prepared_statement(Prepared_statement *stmt,
+ bool text_protocol)
+{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
SELECT_LEX *select_lex= &lex->select_lex;
- TABLE_LIST *tables=(TABLE_LIST*) select_lex->table_list.first;
+ TABLE_LIST *tables;
enum enum_sql_command sql_command= lex->sql_command;
int res= 0;
- DBUG_ENTER("send_prepare_results");
+ DBUG_ENTER("check_prepared_statement");
DBUG_PRINT("enter",("command: %d, param_count: %ld",
sql_command, stmt->param_count));
- if ((&lex->select_lex != lex->all_selects_list ||
- lex->time_zone_tables_used) &&
- lex->unit.create_total_list(thd, lex, &tables))
- DBUG_RETURN(1);
+ lex->first_lists_tables_same();
+ tables= lex->query_tables;
+
+ /* set context for commands which do not use setup_tables */
+ lex->select_lex.context.resolve_in_table_list_only(select_lex->
+ get_table_list());
switch (sql_command) {
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
res= mysql_test_insert(stmt, tables, lex->field_list,
- lex->many_values,
- select_lex->item_list, lex->value_list,
- lex->duplicates);
+ lex->many_values,
+ select_lex->item_list, lex->value_list,
+ lex->duplicates);
break;
case SQLCOM_UPDATE:
res= mysql_test_update(stmt, tables);
+ /* mysql_test_update returns 2 if we need to switch to multi-update */
+ if (res != 2)
+ break;
+
+ case SQLCOM_UPDATE_MULTI:
+ res= mysql_test_multiupdate(stmt, tables, res == 2);
break;
case SQLCOM_DELETE:
@@ -1422,15 +1682,17 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
break;
case SQLCOM_SELECT:
- if ((res= mysql_test_select(stmt, tables, text_protocol)))
- goto error;
- /* Statement and field info has already been sent */
- DBUG_RETURN(0);
-
+ res= mysql_test_select(stmt, tables, text_protocol);
+ if (res == 2)
+ {
+ /* Statement and field info has already been sent */
+ DBUG_RETURN(FALSE);
+ }
+ break;
case SQLCOM_CREATE_TABLE:
- res= mysql_test_create_table(stmt, tables);
+ res= mysql_test_create_table(stmt);
break;
-
+
case SQLCOM_DO:
res= mysql_test_do_fields(stmt, tables, lex->insert_list);
break;
@@ -1442,10 +1704,6 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
case SQLCOM_DELETE_MULTI:
res= mysql_test_multidelete(stmt, tables);
break;
-
- case SQLCOM_UPDATE_MULTI:
- res= mysql_test_multiupdate(stmt, tables);
- break;
case SQLCOM_INSERT_SELECT:
case SQLCOM_REPLACE_SELECT:
@@ -1470,23 +1728,25 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
case SQLCOM_SHOW_GRANTS:
case SQLCOM_DROP_TABLE:
case SQLCOM_RENAME_TABLE:
+ case SQLCOM_ALTER_TABLE:
+ case SQLCOM_COMMIT:
+ case SQLCOM_CREATE_INDEX:
+ case SQLCOM_DROP_INDEX:
+ case SQLCOM_ROLLBACK:
+ case SQLCOM_TRUNCATE:
+ case SQLCOM_CALL:
break;
default:
- /*
- All other is not supported yet
- */
- res= -1;
- my_error(ER_UNSUPPORTED_PS, MYF(0));
+ /* All other statements are not supported yet. */
+ my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0));
goto error;
}
if (res == 0)
- DBUG_RETURN(text_protocol? 0 : (send_prep_stmt(stmt, 0) ||
- thd->protocol->flush()));
+ DBUG_RETURN(text_protocol? FALSE : (send_prep_stmt(stmt, 0) ||
+ thd->protocol->flush()));
error:
- if (res < 0)
- send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
/*
@@ -1498,15 +1758,13 @@ error:
static bool init_param_array(Prepared_statement *stmt)
{
LEX *lex= stmt->lex;
- THD *thd= stmt->thd;
if ((stmt->param_count= lex->param_list.elements))
{
if (stmt->param_count > (uint) UINT_MAX16)
{
/* Error code to be defined in 5.0 */
- send_error(thd, ER_UNKNOWN_ERROR,
- "Prepared statement contains too many placeholders.");
- return 1;
+ my_message(ER_PS_MANY_PARAM, ER(ER_PS_MANY_PARAM), MYF(0));
+ return TRUE;
}
Item_param **to;
List_iterator<Item_param> param_iterator(lex->param_list);
@@ -1515,10 +1773,7 @@ static bool init_param_array(Prepared_statement *stmt)
alloc_root(stmt->thd->mem_root,
sizeof(Item_param*) * stmt->param_count);
if (!stmt->param_array)
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
- return 1;
- }
+ return TRUE;
for (to= stmt->param_array;
to < stmt->param_array + stmt->param_count;
++to)
@@ -1526,227 +1781,366 @@ static bool init_param_array(Prepared_statement *stmt)
*to= param_iterator++;
}
}
- return 0;
+ return FALSE;
+}
+
+
+/* Cleanup PS after execute/prepare and restore THD state */
+
+static void cleanup_stmt_and_thd_after_use(Statement *stmt, THD *thd)
+{
+ DBUG_ENTER("cleanup_stmt_and_thd_after_use");
+ stmt->lex->unit.cleanup();
+ cleanup_items(stmt->free_list);
+ thd->rollback_item_tree_changes();
+ thd->cleanup_after_query();
+ DBUG_VOID_RETURN;
}
+
/*
- Given a query string with parameter markers, create a Prepared Statement
- from it and send PS info back to the client.
-
+ COM_STMT_PREPARE handler.
+
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
-
+ packet query to be prepared
+ packet_length query string length, including ignored
+ trailing NULL or quote char.
+
+ DESCRIPTION
+ Given a query string with parameter markers, create a prepared
+ statement from it and send PS info back to the client.
+
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.
+ 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
+ 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.
-
+
+ RETURN VALUE
+ none: in case of success a new statement id and metadata is sent
+ to the client, otherwise an error message is set in THD.
*/
-int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
- LEX_STRING *name)
+void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
{
- LEX *lex;
- Prepared_statement *stmt= new Prepared_statement(thd);
- int error;
+ Prepared_statement *stmt= new Prepared_statement(thd, &thd->protocol_prep);
+ bool rc;
DBUG_ENTER("mysql_stmt_prepare");
DBUG_PRINT("prep_query", ("%s", packet));
- /*
- If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql.
- However, it seems handy if com_stmt_prepare is increased always,
- no matter what kind of prepare is processed.
- */
- statistic_increment(com_stmt_prepare, &LOCK_status);
-
if (stmt == 0)
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
- 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);
- }
- }
+ DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */
if (thd->stmt_map.insert(stmt))
{
delete stmt;
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_RETURN(1);
- }
-
- thd->set_n_backup_statement(stmt, &thd->stmt_backup);
- thd->set_n_backup_item_arena(stmt, &thd->stmt_backup);
-
- if (alloc_query(thd, packet, packet_length))
- {
- thd->restore_backup_statement(stmt, &thd->stmt_backup);
- thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
- /* Statement map deletes statement on erase */
- thd->stmt_map.erase(stmt);
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_RETURN(1);
+ DBUG_VOID_RETURN; /* out of memory */
}
- mysql_log.write(thd, thd->command, "[%lu] %s", stmt->id, packet);
-
- thd->current_arena= stmt;
- mysql_init_query(thd, (uchar *) thd->query, thd->query_length);
+ mysql_reset_thd_for_next_command(thd);
/* Reset warnings from previous command */
- mysql_reset_errors(thd);
- lex= thd->lex;
- lex->safe_to_cache_query= 0;
+ mysql_reset_errors(thd, 0);
+ sp_cache_flush_obsolete(&thd->sp_proc_cache);
+ sp_cache_flush_obsolete(&thd->sp_func_cache);
- error= yyparse((void *)thd) || thd->is_fatal_error ||
- thd->net.report_error || init_param_array(stmt);
- /*
- While doing context analysis of the query (in send_prepare_results) we
- allocate a lot of additional memory: for open tables, JOINs, derived
- tables, etc. Let's save a snapshot of current parse tree to the
- statement and restore original THD. In cases when some tree
- transformation can be reused on execute, we set again thd->mem_root from
- stmt->mem_root (see setup_wild for one place where we do that).
- */
- thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
- if (!error)
- error= send_prepare_results(stmt, test(name));
+ rc= stmt->prepare(packet, packet_length);
- /* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
- lex_end(lex);
- thd->restore_backup_statement(stmt, &thd->stmt_backup);
- cleanup_items(stmt->free_list);
- close_thread_tables(thd);
- free_items(thd->free_list);
- thd->rollback_item_tree_changes();
- thd->free_list= 0;
- thd->current_arena= thd;
- if (error)
+ if (rc)
{
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
- stmt= NULL;
- if (thd->net.report_error)
- send_error(thd);
- /* otherwise the error is sent inside yyparse/send_prepare_results */
}
else
+ mysql_log.write(thd, COM_STMT_PREPARE, "[%lu] %s", stmt->id, packet);
+
+ /* check_prepared_statemnt sends the metadata packet in case of success */
+ DBUG_VOID_RETURN;
+}
+
+/*
+ SYNOPSIS
+ get_dynamic_sql_string()
+ lex in main lex
+ query_len out length of the SQL statement (is set only
+ in case of success)
+
+ DESCRIPTION
+ Get an SQL statement text from a user variable or from plain
+ text. If the statement is plain text, just assign the
+ pointers, otherwise allocate memory in thd->mem_root and copy
+ the contents of the variable, possibly with character
+ set conversion.
+
+ RETURN VALUE
+ non-zero success, 0 in case of error (out of memory)
+*/
+
+static const char *get_dynamic_sql_string(LEX *lex, uint *query_len)
+{
+ THD *thd= lex->thd;
+ char *query_str= 0;
+
+ if (lex->prepared_stmt_code_is_varref)
{
- stmt->setup_set_params();
- SELECT_LEX *sl= stmt->lex->all_selects_list;
- for (; sl; sl= sl->next_select_in_list())
+ /* This is PREPARE stmt FROM or EXECUTE IMMEDIATE @var. */
+ String str;
+ CHARSET_INFO *to_cs= thd->variables.collation_connection;
+ bool needs_conversion;
+ user_var_entry *entry;
+ String *pstr= &str;
+ uint32 unused, len;
+ /*
+ 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 be uniform.
+ */
+ if ((entry=
+ (user_var_entry*)hash_search(&thd->user_vars,
+ (byte*)lex->prepared_stmt_code.str,
+ lex->prepared_stmt_code.length))
+ && entry->value)
{
+ my_bool is_var_null;
+ pstr= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC);
/*
- Save WHERE clause pointers, because they may be changed
- during query optimisation.
+ NULL value of variable checked early as entry->value so here
+ we can't get NULL in normal conditions
*/
- sl->prep_where= sl->where;
+ DBUG_ASSERT(!is_var_null);
+ if (!pstr)
+ goto end;
+ }
+ else
+ {
/*
- Switch off a temporary flag that prevents evaluation of
- subqueries in statement prepare.
+ variable absent or equal to NULL, so we need to set variable to
+ something reasonable to get a readable error message during parsing
*/
- sl->uncacheable&= ~UNCACHEABLE_PREPARE;
+ str.set("NULL", 4, &my_charset_latin1);
}
- stmt->state= Item_arena::PREPARED;
- }
- DBUG_RETURN(!stmt);
+ needs_conversion= String::needs_conversion(pstr->length(),
+ pstr->charset(), to_cs, &unused);
+
+ len= needs_conversion ? pstr->length() * to_cs->mbmaxlen : pstr->length();
+ if (!(query_str= alloc_root(thd->mem_root, len+1)))
+ goto end;
+
+ if (needs_conversion)
+ {
+ uint dummy_errors;
+ len= copy_and_convert(query_str, len, to_cs, pstr->ptr(), pstr->length(),
+ pstr->charset(), &dummy_errors);
+ }
+ else
+ memcpy(query_str, pstr->ptr(), pstr->length());
+ query_str[len]= '\0';
+ *query_len= len;
+ }
+ else
+ {
+ query_str= lex->prepared_stmt_code.str;
+ *query_len= lex->prepared_stmt_code.length;
+ }
+end:
+ return query_str;
}
-/* Reinit statement before execution */
-static void reset_stmt_for_execute(Prepared_statement *stmt)
+/* Init PS/SP specific parse tree members. */
+
+static void init_stmt_after_parse(LEX *lex)
{
- THD *thd= stmt->thd;
- LEX *lex= stmt->lex;
SELECT_LEX *sl= lex->all_selects_list;
-
+ /*
+ Switch off a temporary flag that prevents evaluation of
+ subqueries in statement prepare.
+ */
for (; sl; sl= sl->next_select_in_list())
+ sl->uncacheable&= ~UNCACHEABLE_PREPARE;
+}
+
+/*
+ SQLCOM_PREPARE implementation.
+
+ SYNOPSIS
+ mysql_sql_stmt_prepare()
+ thd thread handle
+
+ DESCRIPTION
+ Prepare an SQL prepared statement. This is called from
+ mysql_execute_command and should therefore behave like an
+ ordinary query (e.g. should not reset any global THD data).
+
+ RETURN VALUE
+ none: in case of success, OK packet is sent to the client,
+ otherwise an error message is set in THD
+*/
+
+void mysql_sql_stmt_prepare(THD *thd)
+{
+ LEX *lex= thd->lex;
+ LEX_STRING *name= &lex->prepared_stmt_name;
+ Prepared_statement *stmt;
+ const char *query;
+ uint query_len;
+
+ DBUG_ENTER("mysql_sql_stmt_prepare");
+
+ DBUG_ASSERT(thd->protocol == &thd->protocol_simple);
+ if ((stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
{
- /* remove option which was put by mysql_explain_union() */
- sl->options&= ~SELECT_DESCRIBE;
/*
- Copy WHERE clause pointers to avoid damaging they by optimisation
+ If there is a statement with the same name, remove it. It is ok to
+ remove old and fail to insert a new one at the same time.
*/
- if (sl->prep_where)
- {
- sl->where= sl->prep_where->copy_andor_structure(thd);
- sl->where->cleanup();
- }
- DBUG_ASSERT(sl->join == 0);
- ORDER *order;
- /* Fix GROUP list */
- for (order= (ORDER *)sl->group_list.first; order; order= order->next)
- order->item= &order->item_ptr;
- /* Fix ORDER list */
- for (order= (ORDER *)sl->order_list.first; order; order= order->next)
- order->item= &order->item_ptr;
+ if (stmt->deallocate())
+ DBUG_VOID_RETURN;
+ }
- /*
- TODO: When the new table structure is ready, then have a status bit
- to indicate the table is altered, and re-do the setup_*
- and open the tables back.
- */
- for (TABLE_LIST *tables= (TABLE_LIST*) sl->table_list.first;
- tables;
- tables= tables->next)
+ if (! (query= get_dynamic_sql_string(lex, &query_len)) ||
+ ! (stmt= new Prepared_statement(thd, &thd->protocol_simple)))
+ {
+ DBUG_VOID_RETURN; /* out of memory */
+ }
+
+ if (stmt->set_name(name) || thd->stmt_map.insert(stmt))
+ {
+ delete stmt;
+ DBUG_VOID_RETURN;
+ }
+
+ if (stmt->prepare(query, query_len+1))
+ {
+ /* Statement map deletes the statement on erase */
+ thd->stmt_map.erase(stmt);
+ }
+ else
+ send_ok(thd, 0L, 0L, "Statement prepared");
+
+ DBUG_VOID_RETURN;
+}
+
+/* Reinit prepared statement/stored procedure before execution */
+
+void reinit_stmt_before_use(THD *thd, LEX *lex)
+{
+ SELECT_LEX *sl= lex->all_selects_list;
+ DBUG_ENTER("reinit_stmt_before_use");
+
+ /*
+ We have to update "thd" pointer in LEX, all its units and in LEX::result,
+ since statements which belong to trigger body are associated with TABLE
+ object and because of this can be used in different threads.
+ */
+ lex->thd= thd;
+
+ if (lex->empty_field_list_on_rset)
+ {
+ lex->empty_field_list_on_rset= 0;
+ lex->field_list.empty();
+ }
+ for (; sl; sl= sl->next_select_in_list())
+ {
+ if (!sl->first_execution)
{
+ /* remove option which was put by mysql_explain_union() */
+ sl->options&= ~SELECT_DESCRIBE;
+
+ /* see unique_table() */
+ sl->exclude_from_table_unique_test= FALSE;
+
/*
- Reset old pointers to TABLEs: they are not valid since the tables
- were closed in the end of previous prepare or execute call.
+ Copy WHERE clause pointers to avoid damaging they by optimisation
*/
- tables->table= 0;
- tables->table_list= 0;
+ if (sl->prep_where)
+ {
+ sl->where= sl->prep_where->copy_andor_structure(thd);
+ sl->where->cleanup();
+ }
+ DBUG_ASSERT(sl->join == 0);
+ ORDER *order;
+ /* Fix GROUP list */
+ for (order= (ORDER *)sl->group_list.first; order; order= order->next)
+ order->item= &order->item_ptr;
+ /* Fix ORDER list */
+ for (order= (ORDER *)sl->order_list.first; order; order= order->next)
+ order->item= &order->item_ptr;
}
-
{
SELECT_LEX_UNIT *unit= sl->master_unit();
unit->unclean();
unit->types.empty();
/* for derived tables & PS (which can't be reset by Item_subquery) */
unit->reinit_exec_mechanism();
+ unit->set_thd(thd);
+ }
+ }
+
+ /*
+ TODO: When the new table structure is ready, then have a status bit
+ to indicate the table is altered, and re-do the setup_*
+ and open the tables back.
+ */
+ /*
+ NOTE: We should reset whole table list here including all tables added
+ by prelocking algorithm (it is not a problem for substatements since
+ they have their own table list).
+ */
+ for (TABLE_LIST *tables= lex->query_tables;
+ tables;
+ tables= tables->next_global)
+ {
+ /*
+ Reset old pointers to TABLEs: they are not valid since the tables
+ were closed in the end of previous prepare or execute call.
+ */
+ tables->table= 0;
+ if (tables->nested_join)
+ tables->nested_join->counter= 0;
+
+ if (tables->prep_on_expr)
+ {
+ tables->on_expr= tables->prep_on_expr->copy_andor_structure(thd);
+ tables->on_expr->cleanup();
}
}
lex->current_select= &lex->select_lex;
+
+ /* restore original list used in INSERT ... SELECT */
+ if (lex->leaf_tables_insert)
+ lex->select_lex.leaf_tables= lex->leaf_tables_insert;
+
if (lex->result)
+ {
lex->result->cleanup();
+ lex->result->set_thd(thd);
+ }
+
+ DBUG_VOID_RETURN;
}
-/*
- Clears parameters from data left from previous execution or long data
-
+/*
+ Clears parameters from data left from previous execution or long data
+
SYNOPSIS
reset_stmt_params()
- stmt - prepared statement for which parameters should be reset
+ stmt prepared statement for which parameters should
+ be reset
*/
static void reset_stmt_params(Prepared_statement *stmt)
@@ -1759,48 +2153,50 @@ 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.
+ COM_STMT_EXECUTE handler: execute a previously prepared statement.
+
SYNOPSIS
mysql_stmt_execute()
- thd Current thread
- packet Query string
- packet_length Query string length, including terminator character.
+ thd current thread
+ packet parameter types and data, if any
+ packet_length packet length, including the terminator character.
+
+ DESCRIPTION
+ If there are any parameters, then replace parameter markers with the
+ data supplied from the client, and then execute the statement.
+ This function uses binary protocol to send a possible result set
+ to the client.
+
+ RETURN VALUE
+ none: in case of success OK packet or a result set is sent to the
+ client, otherwise an error message is set in THD.
*/
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.
- */
+ ulong flags= (ulong) ((uchar) packet[4]);
+ /* Query text for binary, general or slow log, if any of them is open */
String expanded_query;
#ifndef EMBEDDED_LIBRARY
uchar *packet_end= (uchar *) packet + packet_length - 1;
#endif
Prepared_statement *stmt;
+ bool rc;
DBUG_ENTER("mysql_stmt_execute");
packet+= 9; /* stmt_id + 5 bytes of flags */
- statistic_increment(com_stmt_execute, &LOCK_status);
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute",
- SEND_ERROR)))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
DBUG_VOID_RETURN;
- DBUG_PRINT("exec_query:", ("%s", stmt->query));
-
- /* Check if we got an error when sending long data */
- if (stmt->state == Item_arena::ERROR)
- {
- send_error(thd, stmt->last_errno, stmt->last_error);
- DBUG_VOID_RETURN;
- }
+ DBUG_PRINT("exec_query", ("%s", stmt->query));
+ DBUG_PRINT("info",("stmt: %p", stmt));
- DBUG_ASSERT(thd->free_list == NULL);
mysql_reset_thd_for_next_command(thd);
+ sp_cache_flush_obsolete(&thd->sp_proc_cache);
+ sp_cache_flush_obsolete(&thd->sp_func_cache);
+
#ifndef EMBEDDED_LIBRARY
if (stmt->param_count)
{
@@ -1812,138 +2208,155 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
}
#else
/*
- In embedded library we re-install conversion routines each time
- we set params, and also we don't need to parse packet.
+ In embedded library we re-install conversion routines each time
+ we set params, and also we don't need to parse packet.
So we do it in one function.
*/
if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query))
goto set_params_data_err;
#endif
- thd->protocol= &thd->protocol_prep; // Switch to binary protocol
- execute_stmt(thd, stmt, &expanded_query, TRUE);
- thd->protocol= &thd->protocol_simple; // Use normal protocol
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+ rc= stmt->execute(&expanded_query,
+ test(flags & (ulong) CURSOR_TYPE_READ_ONLY));
+ if (!(specialflag & SPECIAL_NO_PRIOR))
+ my_pthread_setprio(pthread_self(), WAIT_PRIOR);
+ if (rc)
+ goto err;
+
+ mysql_log.write(thd, COM_STMT_EXECUTE, "[%lu] %s", stmt->id, thd->query);
+
DBUG_VOID_RETURN;
set_params_data_err:
- reset_stmt_params(stmt);
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_execute");
- send_error(thd);
+err:
+ reset_stmt_params(stmt);
DBUG_VOID_RETURN;
}
/*
- Execute prepared statement using parameter values from
- lex->prepared_stmt_params and send result to the client using text protocol.
+ SQLCOM_EXECUTE implementation.
+
+ SYNOPSIS
+ mysql_sql_stmt_execute()
+ thd thread handle
+
+ DESCRIPTION
+ Execute prepared statement using parameter values from
+ lex->prepared_stmt_params and send result to the client using
+ text protocol. This is called from mysql_execute_command and
+ therefore should behave like an ordinary query (e.g. not change
+ global THD data, such as warning count, server status, etc).
+ This function uses text protocol to send a possible result set.
+
+ RETURN
+ none: in case of success, OK (or result set) packet is sent to the
+ client, otherwise an error is set in THD
*/
-void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
+void mysql_sql_stmt_execute(THD *thd)
{
+ LEX *lex= thd->lex;
Prepared_statement *stmt;
- /*
- Query text for binary log, or empty string if the query is not put into
- binary log.
- */
+ LEX_STRING *name= &lex->prepared_stmt_name;
+ /* Query text for binary, general or slow log, if any of them is open */
String expanded_query;
+
DBUG_ENTER("mysql_sql_stmt_execute");
- /* See comment for statistics_increment in mysql_stmt_prepare */
- statistic_increment(com_stmt_execute, &LOCK_status);
- if (!(stmt= (Prepared_statement*)thd->stmt_map.find_by_name(stmt_name)))
+ DBUG_PRINT("info", ("EXECUTE: %.*s\n", name->length, name->str));
+
+ if (!(stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
{
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_name->length,
- stmt_name->str, "EXECUTE");
- send_error(thd);
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
+ name->length, name->str, "EXECUTE");
DBUG_VOID_RETURN;
}
- if (stmt->param_count != thd->lex->prepared_stmt_params.elements)
+ if (stmt->param_count != lex->prepared_stmt_params.elements)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
- send_error(thd);
DBUG_VOID_RETURN;
}
- DBUG_ASSERT(thd->free_list == NULL);
- /* Must go before setting variables, as it clears thd->user_var_events */
- mysql_reset_thd_for_next_command(thd);
- thd->set_n_backup_statement(stmt, &thd->stmt_backup);
- if (stmt->set_params_from_vars(stmt,
- thd->stmt_backup.lex->prepared_stmt_params,
+ DBUG_PRINT("info",("stmt: %p", stmt));
+
+ if (stmt->set_params_from_vars(stmt, lex->prepared_stmt_params,
&expanded_query))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
- send_error(thd);
+ DBUG_VOID_RETURN;
}
- thd->command= COM_EXECUTE; /* For nice messages in general log */
- execute_stmt(thd, stmt, &expanded_query, FALSE);
+
+ (void) stmt->execute(&expanded_query, FALSE);
+
DBUG_VOID_RETURN;
}
/*
- Execute prepared statement.
+ COM_STMT_FETCH handler: fetches requested amount of rows from cursor
+
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.
+ mysql_stmt_fetch()
+ thd Thread handle
+ packet Packet from client (with stmt_id & num_rows)
+ packet_length Length of packet
*/
-static void execute_stmt(THD *thd, Prepared_statement *stmt,
- String *expanded_query, bool set_context)
+void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
{
- DBUG_ENTER("execute_stmt");
- if (set_context)
- thd->set_n_backup_statement(stmt, &thd->stmt_backup);
- reset_stmt_for_execute(stmt);
+ /* assume there is always place for 8-16 bytes */
+ ulong stmt_id= uint4korr(packet);
+ ulong num_rows= uint4korr(packet+4);
+ Prepared_statement *stmt;
+ Statement stmt_backup;
+ Cursor *cursor;
+ DBUG_ENTER("mysql_stmt_fetch");
- if (expanded_query->length() &&
- alloc_query(thd, (char *)expanded_query->ptr(),
- expanded_query->length()+1))
+ statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status);
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch")))
+ DBUG_VOID_RETURN;
+
+ cursor= stmt->cursor;
+ if (!cursor || !cursor->is_open())
{
- my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
+ my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0), stmt_id);
DBUG_VOID_RETURN;
}
- mysql_log.write(thd, thd->command, "[%lu] %s", stmt->id, thd->query);
- /*
- At first execution of prepared statement we will perform logical
- transformations of the query tree (i.e. negations elimination).
- This should be done permanently on the parse tree of this statement.
- */
- thd->current_arena= stmt;
+
+ thd->stmt_arena= stmt;
+ thd->set_n_backup_statement(stmt, &stmt_backup);
if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),QUERY_PRIOR);
- mysql_execute_command(thd);
- thd->lex->unit.cleanup();
+ my_pthread_setprio(pthread_self(), QUERY_PRIOR);
+
+ thd->protocol= stmt->protocol; // Switch to binary protocol
+ cursor->fetch(num_rows);
+ thd->protocol= &thd->protocol_simple; // Use normal protocol
+
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
- /*
- 'start_time' is set in dispatch_command, but THD::query will
- be freed when we return from this function. So let's log the slow
- query here.
- */
- log_slow_statement(thd);
- /* Prevent from second logging in the end of dispatch_command */
- thd->enable_slow_log= FALSE;
-
- /* Free Items that were created during this execution of the PS. */
- free_items(thd->free_list);
- thd->free_list= 0;
- if (stmt->state == Item_arena::PREPARED)
- stmt->state= Item_arena::EXECUTED;
- thd->current_arena= thd;
- cleanup_items(stmt->free_list);
- thd->rollback_item_tree_changes();
- reset_stmt_params(stmt);
- close_thread_tables(thd); // to close derived tables
- thd->set_statement(&thd->stmt_backup);
+
+ if (!cursor->is_open())
+ {
+ /* We're done with the fetch: reset PS for next execution */
+ cleanup_stmt_and_thd_after_use(stmt, thd);
+ reset_stmt_params(stmt);
+ /*
+ Must be the last, as some memory is still needed for
+ the previous calls.
+ */
+ free_root(cursor->mem_root, MYF(0));
+ if (cursor->close_at_commit)
+ thd->stmt_map.erase_transient_cursor(stmt);
+ }
+
+ thd->restore_backup_statement(stmt, &stmt_backup);
+ thd->stmt_arena= thd;
+
DBUG_VOID_RETURN;
}
@@ -1952,8 +2365,8 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
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.
@@ -1961,6 +2374,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
- clear an error happened during mysql_stmt_send_long_data
- cancel long data stream for all placeholders without
having to call mysql_stmt_execute.
+ - close an open cursor
Sends 'OK' packet in case of success (statement was reset)
or 'ERROR' packet (unrecoverable error/statement not found/etc).
*/
@@ -1970,70 +2384,96 @@ void mysql_stmt_reset(THD *thd, char *packet)
/* There is always space for 4 bytes in buffer */
ulong stmt_id= uint4korr(packet);
Prepared_statement *stmt;
-
+ Cursor *cursor;
DBUG_ENTER("mysql_stmt_reset");
- statistic_increment(com_stmt_reset, &LOCK_status);
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset",
- SEND_ERROR)))
+ statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status);
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
DBUG_VOID_RETURN;
- stmt->state= Item_arena::PREPARED;
+ stmt->close_cursor(); /* will reset statement params */
- /*
- Clear parameters from data which could be set by
- mysql_stmt_send_long_data() call.
- */
- reset_stmt_params(stmt);
+ stmt->state= Query_arena::PREPARED;
mysql_reset_thd_for_next_command(thd);
send_ok(thd);
-
+
DBUG_VOID_RETURN;
}
/*
Delete a prepared statement from memory.
- Note: we don't send any reply to that command.
+ Note: we don't send any reply to this command.
*/
-void mysql_stmt_free(THD *thd, char *packet)
+void mysql_stmt_close(THD *thd, char *packet)
{
/* There is always space for 4 bytes in packet buffer */
ulong stmt_id= uint4korr(packet);
Prepared_statement *stmt;
- DBUG_ENTER("mysql_stmt_free");
+ DBUG_ENTER("mysql_stmt_close");
- statistic_increment(com_stmt_close, &LOCK_status);
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close",
- DONT_SEND_ERROR)))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close")))
DBUG_VOID_RETURN;
- /* Statement map deletes statement on erase */
- thd->stmt_map.erase(stmt);
+ /*
+ The only way currently a statement can be deallocated when it's
+ in use is from within Dynamic SQL.
+ */
+ DBUG_ASSERT(! (stmt->flags & Prepared_statement::IS_IN_USE));
+ (void) stmt->deallocate();
+
DBUG_VOID_RETURN;
}
/*
- Long data in pieces from client
+ SQLCOM_DEALLOCATE implementation.
+
+ DESCRIPTION
+ Close an SQL prepared statement. As this can be called from Dynamic
+ SQL, we should be careful to not close a statement that is currently
+ being executed.
+
+ RETURN VALUE
+ none: OK packet is sent in case of success, otherwise an error
+ message is set in THD
+*/
+
+void mysql_sql_stmt_close(THD *thd)
+{
+ Prepared_statement* stmt;
+ LEX_STRING *name= &thd->lex->prepared_stmt_name;
+ DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", name->length, name->str));
+
+ if (! (stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
+ {
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
+ name->length, name->str, "DEALLOCATE PREPARE");
+ return;
+ }
+
+ if (stmt->deallocate() == 0)
+ send_ok(thd);
+}
+
+/*
+ Handle long data in pieces from client.
SYNOPSIS
mysql_stmt_get_longdata()
- thd Thread handle
- pos String to append
- packet_length Length of string
+ thd Thread handle
+ packet String to append
+ packet_length Length of string
DESCRIPTION
- Get a part of a long data.
- To make the protocol efficient, we are not sending any return packages
- here.
- If something goes wrong, then we will send the error on 'execute'
-
- We assume that the client takes care of checking that all parts are sent
- to the server. (No checking that we get a 'end of column' in the server)
+ Get a part of a long data. To make the protocol efficient, we are
+ not sending any return packets here. If something goes wrong, then
+ we will send the error on 'execute' We assume that the client takes
+ care of checking that all parts are sent to the server. (No checking
+ that we get a 'end of column' in the server is performed).
*/
void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
@@ -2043,10 +2483,10 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
Prepared_statement *stmt;
Item_param *param;
char *packet_end= packet + packet_length - 1;
-
+
DBUG_ENTER("mysql_stmt_get_longdata");
- statistic_increment(com_stmt_send_long_data, &LOCK_status);
+ statistic_increment(thd->status_var.com_stmt_send_long_data, &LOCK_status);
#ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */
if ((ulong) (packet_end - packet) < MYSQL_LONG_DATA_HEADER)
@@ -2059,8 +2499,8 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
stmt_id= uint4korr(packet);
packet+= 4;
- if (!(stmt=find_prepared_statement(thd, stmt_id, "mysql_stmt_send_long_data",
- DONT_SEND_ERROR)))
+ if (!(stmt=find_prepared_statement(thd, stmt_id,
+ "mysql_stmt_send_long_data")))
DBUG_VOID_RETURN;
param_number= uint2korr(packet);
@@ -2069,7 +2509,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
if (param_number >= stmt->param_count)
{
/* Error will be sent in execute call */
- stmt->state= Item_arena::ERROR;
+ stmt->state= Query_arena::ERROR;
stmt->last_errno= ER_WRONG_ARGUMENTS;
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
"mysql_stmt_send_long_data");
@@ -2085,7 +2525,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
if (param->set_longdata(thd->extra_data, thd->extra_length))
#endif
{
- stmt->state= Item_arena::ERROR;
+ stmt->state= Query_arena::ERROR;
stmt->last_errno= ER_OUTOFMEMORY;
sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0);
}
@@ -2093,12 +2533,16 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
}
-Prepared_statement::Prepared_statement(THD *thd_arg)
- :Statement(thd_arg),
+Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg)
+ :Statement(INITIALIZED, ++thd_arg->statement_id_counter,
+ thd_arg->variables.query_alloc_block_size,
+ thd_arg->variables.query_prealloc_size),
thd(thd_arg),
+ protocol(protocol_arg),
param_array(0),
param_count(0),
- last_errno(0)
+ last_errno(0),
+ flags(IS_IN_USE)
{
*last_error= '\0';
}
@@ -2129,15 +2573,344 @@ void Prepared_statement::setup_set_params()
}
+/*
+ DESCRIPTION
+ Destroy this prepared statement, cleaning up all used memory
+ and resources. This is called from ::deallocate() to
+ handle COM_STMT_CLOSE and DEALLOCATE PREPARE or when
+ THD ends and all prepared statements are freed.
+*/
+
Prepared_statement::~Prepared_statement()
{
- free_items(free_list);
+ DBUG_ENTER("Prepared_statement::~Prepared_statement");
+ DBUG_PRINT("enter",("stmt: %p cursor: %p", this, cursor));
+ if (cursor)
+ {
+ if (cursor->is_open())
+ {
+ cursor->close(FALSE);
+ cleanup_items(free_list);
+ thd->rollback_item_tree_changes();
+ free_root(cursor->mem_root, MYF(0));
+ }
+ cursor->Cursor::~Cursor();
+ }
+ /*
+ We have to call free on the items even if cleanup is called as some items,
+ like Item_param, don't free everything until free_items()
+ */
+ free_items();
delete lex->result;
+ DBUG_VOID_RETURN;
}
-Item_arena::Type Prepared_statement::type() const
+Query_arena::Type Prepared_statement::type() const
{
return PREPARED_STATEMENT;
}
+
+void Prepared_statement::close_cursor()
+{
+ DBUG_ENTER("Prepared_statement::close_cursor");
+ DBUG_PRINT("enter",("stmt: %p", this));
+
+ if (cursor && cursor->is_open())
+ {
+ thd->change_list= cursor->change_list;
+ cursor->close(FALSE);
+ cleanup_stmt_and_thd_after_use(this, thd);
+ free_root(cursor->mem_root, MYF(0));
+ if (cursor->close_at_commit)
+ thd->stmt_map.erase_transient_cursor(this);
+ }
+ /*
+ Clear parameters from data which could be set by
+ mysql_stmt_send_long_data() call.
+ */
+ reset_stmt_params(this);
+ DBUG_VOID_RETURN;
+}
+
+
+bool Prepared_statement::set_name(LEX_STRING *name_arg)
+{
+ name.length= name_arg->length;
+ name.str= memdup_root(mem_root, (char*) name_arg->str, name_arg->length);
+ return name.str == 0;
+}
+
+/**************************************************************************
+ Common parts of mysql_[sql]_stmt_prepare, mysql_[sql]_stmt_execute.
+ Essentially, these functions do all the magic of preparing/executing
+ a statement, leaving network communication, input data handling and
+ global THD state management to the caller.
+***************************************************************************/
+
+/*
+ Parse statement text, validate the statement, and prepare it for execution.
+
+ SYNOPSIS
+ Prepared_statement::prepare()
+ packet statement text
+ packet_len
+
+ DESCRIPTION
+ You should not change global THD state in this function, if at all
+ possible: it may be called from any context, e.g. when executing
+ a COM_* command, and SQLCOM_* command, or a stored procedure.
+
+ NOTES
+ Precondition.
+ -------------
+ The caller must ensure that thd->change_list and thd->free_list
+ is empty: this function will not back them up but will free
+ in the end of its execution.
+
+ Postcondition.
+ --------------
+ thd->mem_root contains unused memory allocated during validation.
+*/
+
+bool Prepared_statement::prepare(const char *packet, uint packet_len)
+{
+ bool rc;
+ Statement stmt_backup;
+ Query_arena *old_stmt_arena;
+ DBUG_ENTER("Prepared_statement::prepare");
+ /*
+ If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql.
+ However, it seems handy if com_stmt_prepare is increased always,
+ no matter what kind of prepare is processed.
+ */
+ statistic_increment(thd->status_var.com_stmt_prepare, &LOCK_status);
+
+ /*
+ alloc_query() uses thd->memroot && thd->query, so we should call
+ both of backup_statement() and backup_query_arena() here.
+ */
+ thd->set_n_backup_statement(this, &stmt_backup);
+ thd->set_n_backup_active_arena(this, &stmt_backup);
+
+ if (alloc_query(thd, packet, packet_len))
+ {
+ thd->restore_backup_statement(this, &stmt_backup);
+ thd->restore_active_arena(this, &stmt_backup);
+ DBUG_RETURN(TRUE);
+ }
+
+ old_stmt_arena= thd->stmt_arena;
+ thd->stmt_arena= this;
+ lex_start(thd, (uchar*) thd->query, thd->query_length);
+ lex->safe_to_cache_query= FALSE;
+ lex->stmt_prepare_mode= TRUE;
+
+ rc= yyparse((void *)thd) || thd->is_fatal_error ||
+ thd->net.report_error || init_param_array(this);
+ /*
+ While doing context analysis of the query (in check_prepared_statement)
+ we allocate a lot of additional memory: for open tables, JOINs, derived
+ tables, etc. Let's save a snapshot of current parse tree to the
+ statement and restore original THD. In cases when some tree
+ transformation can be reused on execute, we set again thd->mem_root from
+ stmt->mem_root (see setup_wild for one place where we do that).
+ */
+ thd->restore_active_arena(this, &stmt_backup);
+
+ /*
+ If called from a stored procedure, ensure that we won't rollback
+ external changes when cleaning up after validation.
+ */
+ DBUG_ASSERT(thd->change_list.is_empty());
+ /*
+ If the free_list is not empty, we'll wrongly free some externally
+ allocated items when cleaning up after validation of the prepared
+ statement.
+ */
+ DBUG_ASSERT(thd->free_list == NULL);
+
+ if (rc == 0)
+ rc= check_prepared_statement(this, name.str != 0);
+
+ if (rc && thd->lex->sphead)
+ {
+ delete thd->lex->sphead;
+ thd->lex->sphead= NULL;
+ }
+ lex_end(lex);
+ close_thread_tables(thd);
+ cleanup_stmt_and_thd_after_use(this, thd);
+ thd->restore_backup_statement(this, &stmt_backup);
+ thd->stmt_arena= old_stmt_arena;
+
+ if (rc == 0)
+ {
+ setup_set_params();
+ init_stmt_after_parse(lex);
+ state= Query_arena::PREPARED;
+ flags&= ~IS_IN_USE;
+ }
+ DBUG_RETURN(rc);
+}
+
+/*
+ Execute a prepared statement.
+
+ SYNOPSIS
+ Prepared_statement::execute()
+ expanded_query A query for binlogging which has all parameter
+ markers ('?') replaced with their actual values.
+ open_cursor True if an attempt to open a cursor should be made.
+ Currenlty used only in the binary protocol.
+
+ DESCRIPTION
+ You should not change global THD state in this function, if at all
+ possible: it may be called from any context, e.g. when executing
+ a COM_* command, and SQLCOM_* command, or a stored procedure.
+
+ NOTES
+ Preconditions, postconditions.
+ ------------------------------
+ See the comment for Prepared_statement::prepare().
+*/
+
+bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
+{
+ Statement stmt_backup;
+ Query_arena *old_stmt_arena;
+ Item *old_free_list;
+ bool rc= 1;
+
+ statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status);
+
+ /* Check if we got an error when sending long data */
+ if (state == Query_arena::ERROR)
+ {
+ my_message(last_errno, last_error, MYF(0));
+ return 1;
+ }
+ if (flags & IS_IN_USE)
+ {
+ my_error(ER_PS_NO_RECURSION, MYF(0));
+ return 1;
+ }
+ /* In case the command has a call to SP which re-uses this statement name */
+ flags|= IS_IN_USE;
+
+ if (cursor && cursor->is_open())
+ close_cursor();
+
+ /*
+ If the free_list is not empty, we'll wrongly free some externally
+ allocated items when cleaning up after execution of this statement.
+ */
+ DBUG_ASSERT(thd->change_list.is_empty());
+ DBUG_ASSERT(thd->free_list == NULL);
+ if (open_cursor)
+ {
+ if (!lex->result || !lex->result->simple_select())
+ {
+ DBUG_PRINT("info",("Cursor asked for not SELECT stmt"));
+ /*
+ If lex->result is set in the parser, this is not a SELECT
+ statement: we can't open a cursor for it.
+ */
+ my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
+ goto error;
+ }
+
+ DBUG_PRINT("info",("Using READ_ONLY cursor"));
+ if (!cursor && !(cursor= new (mem_root) Cursor(thd)))
+ goto error;
+ /* If lex->result is set, mysql_execute_command will use it */
+ lex->result= &cursor->result;
+ protocol= &cursor->protocol;
+ thd->lock_id= &cursor->lock_id;
+ /*
+ Currently cursors can be used only from C API, so
+ we don't have to create an own memory root for them:
+ the one in THD is clean and can be used.
+ */
+ }
+ thd->set_n_backup_statement(this, &stmt_backup);
+ if (expanded_query->length() &&
+ alloc_query(thd, (char*) expanded_query->ptr(),
+ expanded_query->length()+1))
+ {
+ my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
+ goto error;
+ }
+ /*
+ Expanded query is needed for slow logging, so we want thd->query
+ to point at it even after we restore from backup. This is ok, as
+ expanded query was allocated in thd->mem_root.
+ */
+ stmt_backup.query= thd->query;
+ stmt_backup.query_length= thd->query_length;
+
+ /*
+ At first execution of prepared statement we may perform logical
+ transformations of the query tree. Such changes should be performed
+ on the parse tree of current prepared statement and new items should
+ be allocated in its memory root. Set the appropriate pointer in THD
+ to the arena of the statement.
+ */
+ old_stmt_arena= thd->stmt_arena;
+ thd->stmt_arena= this;
+ reinit_stmt_before_use(thd, lex);
+
+ thd->protocol= protocol; /* activate stmt protocol */
+ mysql_execute_command(thd);
+ thd->protocol= &thd->protocol_simple; /* use normal protocol */
+
+ if (cursor && cursor->is_open())
+ {
+ /*
+ It's safer if we grab THD state after mysql_execute_command is
+ finished and not in Cursor::open(), because currently the call to
+ Cursor::open is buried deep in JOIN::exec of the top level join.
+ */
+ cursor->init_from_thd(thd);
+
+ if (cursor->close_at_commit)
+ thd->stmt_map.add_transient_cursor(this);
+ }
+ else
+ {
+ close_thread_tables(thd);
+ cleanup_stmt_and_thd_after_use(this, thd);
+ reset_stmt_params(this);
+ }
+
+ thd->set_statement(&stmt_backup);
+ thd->lock_id= &thd->main_lock_id;
+ thd->stmt_arena= old_stmt_arena;
+
+ if (state == Query_arena::PREPARED)
+ state= Query_arena::EXECUTED;
+
+ rc= 0;
+error:
+ thd->lock_id= &thd->main_lock_id;
+ flags&= ~IS_IN_USE;
+ return rc;
+}
+
+
+/* Common part of DEALLOCATE PREPARE and mysql_stmt_close */
+
+bool Prepared_statement::deallocate()
+{
+ /* We account deallocate in the same manner as mysql_stmt_close */
+ statistic_increment(thd->status_var.com_stmt_close, &LOCK_status);
+ if (flags & IS_IN_USE)
+ {
+ my_error(ER_PS_NO_RECURSION, MYF(0));
+ return TRUE;
+ }
+ /* Statement map calls delete stmt on erase */
+ thd->stmt_map.erase(this);
+ return FALSE;
+}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 388034e0f1a..154e828b47e 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -44,7 +44,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
if (thd->locked_tables || thd->active_transaction())
{
- my_error(ER_LOCK_OR_ACTIVE_TRANSACTION,MYF(0));
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
DBUG_RETURN(1);
}
@@ -64,10 +65,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
table_list= reverse_table_list(table_list);
/* Find the last renamed table */
- for (table=table_list ;
- table->next != ren_table ;
- table=table->next->next) ;
- table=table->next->next; // Skip error table
+ for (table= table_list;
+ table->next_local != ren_table ;
+ table= table->next_local->next_local) ;
+ table= table->next_local->next_local; // Skip error table
/* Revert to old names */
rename_tables(thd, table, 1);
@@ -80,7 +81,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
/* Lets hope this doesn't fail as the result will be messy */
if (!error)
{
- mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
@@ -90,7 +90,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
send_ok(thd);
}
- unlock_table_names(thd,table_list);
+ unlock_table_names(thd, table_list, (TABLE_LIST*) 0);
err:
pthread_mutex_unlock(&LOCK_open);
@@ -115,8 +115,8 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list)
while (table_list)
{
- TABLE_LIST *next= table_list->next;
- table_list->next= prev;
+ TABLE_LIST *next= table_list->next_local;
+ table_list->next_local= prev;
prev= table_list;
table_list= next;
}
@@ -133,15 +133,16 @@ static TABLE_LIST *
rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
{
TABLE_LIST *ren_table,*new_table;
+ frm_type_enum frm_type;
DBUG_ENTER("rename_tables");
- for (ren_table=table_list ; ren_table ; ren_table=new_table->next)
+ for (ren_table= table_list; ren_table; ren_table= new_table->next_local)
{
- db_type table_type;
+ int rc= 1;
char name[FN_REFLEN];
const char *new_alias, *old_alias;
- new_table=ren_table->next;
+ new_table= ren_table->next_local;
if (lower_case_table_names == 2)
{
old_alias= ren_table->alias;
@@ -149,34 +150,51 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
}
else
{
- old_alias= ren_table->real_name;
- new_alias= new_table->real_name;
+ old_alias= ren_table->table_name;
+ new_alias= new_table->table_name;
}
sprintf(name,"%s/%s/%s%s",mysql_data_home,
new_table->db, new_alias, reg_ext);
unpack_filename(name, name);
if (!access(name,F_OK))
{
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_alias);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
DBUG_RETURN(ren_table); // This can't be skipped
}
sprintf(name,"%s/%s/%s%s",mysql_data_home,
ren_table->db, old_alias,
reg_ext);
unpack_filename(name, name);
- if ((table_type=get_table_type(name)) == DB_TYPE_UNKNOWN)
- {
- my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
- if (!skip_error)
- DBUG_RETURN(ren_table);
- }
- else if (mysql_rename_table(table_type,
- ren_table->db, old_alias,
- new_table->db, new_alias))
+
+ frm_type= mysql_frm_type(name);
+ switch (frm_type)
{
- if (!skip_error)
- DBUG_RETURN(ren_table);
+ case FRMTYPE_TABLE:
+ {
+ db_type table_type;
+ if ((table_type= get_table_type(thd, name)) == DB_TYPE_UNKNOWN)
+ my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
+ else
+ rc= mysql_rename_table(table_type, ren_table->db, old_alias,
+ new_table->db, new_alias);
+ break;
+ }
+ case FRMTYPE_VIEW:
+ /* change of schema is not allowed */
+ if (strcmp(ren_table->db, new_table->db))
+ my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db,
+ new_table->db);
+ else
+ rc= mysql_rename_view(thd, new_alias, ren_table);
+ break;
+ default:
+ DBUG_ASSERT(0); // should never happen
+ case FRMTYPE_ERROR:
+ my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
+ break;
}
+ if (rc && !skip_error)
+ DBUG_RETURN(ren_table);
}
DBUG_RETURN(0);
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 963c4ccf5a6..98f47d13eee 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -25,43 +25,46 @@ int max_binlog_dump_events = 0; // unlimited
my_bool opt_sporadic_binlog_dump_fail = 0;
static int binlog_dump_count = 0;
-int check_binlog_magic(IO_CACHE* log, const char** errmsg)
-{
- char magic[4];
- DBUG_ASSERT(my_b_tell(log) == 0);
-
- if (my_b_read(log, (byte*) magic, sizeof(magic)))
- {
- *errmsg = "I/O error reading the header from the binary log";
- sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
- log->error);
- return 1;
- }
- if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
- {
- *errmsg = "Binlog has bad magic number; It's not a binary log file that can be used by this version of MySQL";
- return 1;
- }
- return 0;
-}
+/*
+ fake_rotate_event() builds a fake (=which does not exist physically in any
+ binlog) Rotate event, which contains the name of the binlog we are going to
+ send to the slave (because the slave may not know it if it just asked for
+ MASTER_LOG_FILE='', MASTER_LOG_POS=4).
+ < 4.0.14, fake_rotate_event() was called only if the requested pos was 4.
+ After this version we always call it, so that a 3.23.58 slave can rely on
+ it to detect if the master is 4.0 (and stop) (the _fake_ Rotate event has
+ zeros in the good positions which, by chance, make it possible for the 3.23
+ slave to detect that this event is unexpected) (this is luck which happens
+ because the master and slave disagree on the size of the header of
+ Log_event).
+
+ Relying on the event length of the Rotate event instead of these
+ well-placed zeros was not possible as Rotate events have a variable-length
+ part.
+*/
static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
- ulonglong position, const char**errmsg)
+ ulonglong position, const char** errmsg)
{
- char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN];
- memset(header, 0, 4); // when does not matter
+ DBUG_ENTER("fake_rotate_event");
+ char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN+100];
+ /*
+ 'when' (the timestamp) is set to 0 so that slave could distinguish between
+ real and fake Rotate events (if necessary)
+ */
+ memset(header, 0, 4);
header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
char* p = log_file_name+dirname_length(log_file_name);
uint ident_len = (uint) strlen(p);
- ulong event_len = ident_len + ROTATE_EVENT_OVERHEAD;
+ ulong event_len = ident_len + LOG_EVENT_HEADER_LEN + ROTATE_HEADER_LEN;
int4store(header + SERVER_ID_OFFSET, server_id);
int4store(header + EVENT_LEN_OFFSET, event_len);
int2store(header + FLAGS_OFFSET, 0);
-
+
// TODO: check what problems this may cause and fix them
int4store(header + LOG_POS_OFFSET, 0);
-
+
packet->append(header, sizeof(header));
int8store(buf+R_POS_OFFSET,position);
packet->append(buf, ROTATE_HEADER_LEN);
@@ -69,9 +72,9 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
if (my_net_write(net, (char*)packet->ptr(), packet->length()))
{
*errmsg = "failed on my_net_write()";
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
static int send_file(THD *thd)
@@ -146,42 +149,6 @@ static int send_file(THD *thd)
}
-File open_binlog(IO_CACHE *log, const char *log_file_name,
- const char **errmsg)
-{
- File file;
- DBUG_ENTER("open_binlog");
-
- if ((file = my_open(log_file_name, O_RDONLY | O_BINARY | O_SHARE,
- MYF(MY_WME))) < 0)
- {
- sql_print_error("Failed to open log (\
-file '%s', errno %d)", log_file_name, my_errno);
- *errmsg = "Could not open log file"; // This will not be sent
- goto err;
- }
- if (init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
- MYF(MY_WME | MY_DONT_CHECK_FILESIZE)))
- {
- sql_print_error("Failed to create a cache on log (\
-file '%s')", log_file_name);
- *errmsg = "Could not open log file"; // This will not be sent
- goto err;
- }
- if (check_binlog_magic(log,errmsg))
- goto err;
- DBUG_RETURN(file);
-
-err:
- if (file >= 0)
- {
- my_close(file,MYF(0));
- end_io_cache(log);
- }
- DBUG_RETURN(-1);
-}
-
-
/*
Adjust the position pointer in the binary log file for all running slaves
@@ -258,41 +225,39 @@ bool log_in_use(const char* log_name)
return result;
}
-int purge_error_message(THD* thd, int res)
+bool purge_error_message(THD* thd, int res)
{
- const char *errmsg= 0;
+ uint errmsg= 0;
switch (res) {
case 0: break;
- case LOG_INFO_EOF: errmsg= "Target log not found in binlog index"; break;
- case LOG_INFO_IO: errmsg= "I/O error reading log index file"; break;
- case LOG_INFO_INVALID:
- errmsg= "Server configuration does not permit binlog purge"; break;
- case LOG_INFO_SEEK: errmsg= "Failed on fseek()"; break;
- case LOG_INFO_MEM: errmsg= "Out of memory"; break;
- case LOG_INFO_FATAL: errmsg= "Fatal error during purge"; break;
- case LOG_INFO_IN_USE: errmsg= "A purgeable log is in use, will not purge";
- break;
- default: errmsg= "Unknown error during purge"; break;
+ case LOG_INFO_EOF: errmsg= ER_UNKNOWN_TARGET_BINLOG; break;
+ case LOG_INFO_IO: errmsg= ER_IO_ERR_LOG_INDEX_READ; break;
+ case LOG_INFO_INVALID:errmsg= ER_BINLOG_PURGE_PROHIBITED; break;
+ case LOG_INFO_SEEK: errmsg= ER_FSEEK_FAIL; break;
+ case LOG_INFO_MEM: errmsg= ER_OUT_OF_RESOURCES; break;
+ case LOG_INFO_FATAL: errmsg= ER_BINLOG_PURGE_FATAL_ERR; break;
+ case LOG_INFO_IN_USE: errmsg= ER_LOG_IN_USE; break;
+ default: errmsg= ER_LOG_PURGE_UNKNOWN_ERR; break;
}
if (errmsg)
{
- send_error(thd, 0, errmsg);
- return 1;
+ my_message(errmsg, ER(errmsg), MYF(0));
+ return TRUE;
}
send_ok(thd);
- return 0;
+ return FALSE;
}
-int purge_master_logs(THD* thd, const char* to_log)
+bool purge_master_logs(THD* thd, const char* to_log)
{
char search_file_name[FN_REFLEN];
if (!mysql_bin_log.is_open())
{
send_ok(thd);
- return 0;
+ return FALSE;
}
mysql_bin_log.make_log_name(search_file_name, to_log);
@@ -302,7 +267,7 @@ int purge_master_logs(THD* thd, const char* to_log)
}
-int purge_master_logs_before_date(THD* thd, time_t purge_time)
+bool purge_master_logs_before_date(THD* thd, time_t purge_time)
{
if (!mysql_bin_log.is_open())
{
@@ -313,6 +278,36 @@ int purge_master_logs_before_date(THD* thd, time_t purge_time)
mysql_bin_log.purge_logs_before_date(purge_time));
}
+int test_for_non_eof_log_read_errors(int error, const char **errmsg)
+{
+ if (error == LOG_READ_EOF)
+ return 0;
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ switch (error) {
+ case LOG_READ_BOGUS:
+ *errmsg = "bogus data in log event";
+ break;
+ case LOG_READ_TOO_LARGE:
+ *errmsg = "log event entry exceeded max_allowed_packet; \
+Increase max_allowed_packet on master";
+ break;
+ case LOG_READ_IO:
+ *errmsg = "I/O error reading log event";
+ break;
+ case LOG_READ_MEM:
+ *errmsg = "memory allocation failed reading log event";
+ break;
+ case LOG_READ_TRUNC:
+ *errmsg = "binlog truncated in the middle of event";
+ break;
+ default:
+ *errmsg = "unknown error reading log event on the master";
+ break;
+ }
+ return error;
+}
+
+
/*
TODO: Clean up loop to only have one call to send_file()
*/
@@ -329,6 +324,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
int error;
const char *errmsg = "Unknown error";
NET* net = &thd->net;
+ pthread_mutex_t *log_lock;
+ bool binlog_can_be_corrupted= FALSE;
#ifndef DBUG_OFF
int left_events = max_binlog_dump_events;
#endif
@@ -388,43 +385,128 @@ impossible position";
goto err;
}
- my_b_seek(&log, pos); // Seek will done on next read
+ if (thd->variables.sync_replication)
+ ha_repl_report_sent_binlog(thd, log_file_name, pos);
+
/*
We need to start a packet with something other than 255
- to distiquish it from error
+ to distinguish it from error
*/
- packet->set("\0", 1, &my_charset_bin);
+ packet->set("\0", 1, &my_charset_bin); /* This is the start of a new packet */
/*
- Before 4.0.14 we called fake_rotate_event below only if
- (pos == BIN_LOG_HEADER_SIZE), because if this is false then the slave
+ Tell the client about the log name with a fake Rotate event;
+ this is needed even if we also send a Format_description_log_event
+ just after, because that event does not contain the binlog's name.
+ Note that as this Rotate event is sent before
+ Format_description_log_event, the slave cannot have any info to
+ understand this event's format, so the header len of
+ Rotate_log_event is FROZEN (so in 5.0 it will have a header shorter
+ than other events except FORMAT_DESCRIPTION_EVENT).
+ Before 4.0.14 we called fake_rotate_event below only if (pos ==
+ BIN_LOG_HEADER_SIZE), because if this is false then the slave
already knows the binlog's name.
- Now we always call fake_rotate_event; if the slave already knew the log's
- name (ex: CHANGE MASTER TO MASTER_LOG_FILE=...) this is useless but does
- not harm much. It is nice for 3.23 (>=.58) slaves which test Rotate events
- to see if the master is 4.0 (then they choose to stop because they can't
- replicate 4.0); by always calling fake_rotate_event we are sure that
- 3.23.58 and newer will detect the problem as soon as replication starts
- (BUG#198).
+ Since, we always call fake_rotate_event; if the slave already knew
+ the log's name (ex: CHANGE MASTER TO MASTER_LOG_FILE=...) this is
+ useless but does not harm much. It is nice for 3.23 (>=.58) slaves
+ which test Rotate events to see if the master is 4.0 (then they
+ choose to stop because they can't replicate 4.0); by always calling
+ fake_rotate_event we are sure that 3.23.58 and newer will detect the
+ problem as soon as replication starts (BUG#198).
Always calling fake_rotate_event makes sending of normal
- (=from-binlog) Rotate events a priori unneeded, but it is not so simple:
- the 2 Rotate events are not equivalent, the normal one is before the Stop
- event, the fake one is after. If we don't send the normal one, then the
- Stop event will be interpreted (by existing 4.0 slaves) as "the master
- stopped", which is wrong. So for safety, given that we want minimum
- modification of 4.0, we send the normal and fake Rotates.
+ (=from-binlog) Rotate events a priori unneeded, but it is not so
+ simple: the 2 Rotate events are not equivalent, the normal one is
+ before the Stop event, the fake one is after. If we don't send the
+ normal one, then the Stop event will be interpreted (by existing 4.0
+ slaves) as "the master stopped", which is wrong. So for safety,
+ given that we want minimum modification of 4.0, we send the normal
+ and fake Rotates.
*/
if (fake_rotate_event(net, packet, log_file_name, pos, &errmsg))
{
+ /*
+ This error code is not perfect, as fake_rotate_event() does not
+ read anything from the binlog; if it fails it's because of an
+ error in my_net_write(), fortunately it will say so in errmsg.
+ */
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
packet->set("\0", 1, &my_charset_bin);
- while (!net->error && net->vio != 0 && !thd->killed)
+ /*
+ We can set log_lock now, it does not move (it's a member of
+ mysql_bin_log, and it's already inited, and it will be destroyed
+ only at shutdown).
+ */
+ log_lock = mysql_bin_log.get_log_lock();
+ if (pos > BIN_LOG_HEADER_SIZE)
{
- pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
+ /*
+ Try to find a Format_description_log_event at the beginning of
+ the binlog
+ */
+ if (!(error = Log_event::read_log_event(&log, packet, log_lock)))
+ {
+ /*
+ The packet has offsets equal to the normal offsets in a binlog
+ event +1 (the first character is \0).
+ */
+ DBUG_PRINT("info",
+ ("Looked for a Format_description_log_event, found event type %d",
+ (*packet)[EVENT_TYPE_OFFSET+1]));
+ if ((*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT)
+ {
+ binlog_can_be_corrupted= test((*packet)[FLAGS_OFFSET+1] &
+ LOG_EVENT_BINLOG_IN_USE_F);
+ (*packet)[FLAGS_OFFSET+1] &= ~LOG_EVENT_BINLOG_IN_USE_F;
+ /*
+ mark that this event with "log_pos=0", so the slave
+ should not increment master's binlog position
+ (rli->group_master_log_pos)
+ */
+ int4store((char*) packet->ptr()+LOG_POS_OFFSET+1, 0);
+ /* send it */
+ if (my_net_write(net, (char*)packet->ptr(), packet->length()))
+ {
+ errmsg = "Failed on my_net_write()";
+ my_errno= ER_UNKNOWN_ERROR;
+ goto err;
+ }
+
+ if (thd->variables.sync_replication)
+ ha_repl_report_sent_binlog(thd, log_file_name, my_b_tell(&log));
+
+ /*
+ No need to save this event. We are only doing simple reads
+ (no real parsing of the events) so we don't need it. And so
+ we don't need the artificial Format_description_log_event of
+ 3.23&4.x.
+ */
+ }
+ }
+ else
+ {
+ if (test_for_non_eof_log_read_errors(error, &errmsg))
+ goto err;
+ /*
+ It's EOF, nothing to do, go on reading next events, the
+ Format_description_log_event will be found naturally if it is written.
+ */
+ }
+ /* reset the packet as we wrote to it in any case */
+ packet->set("\0", 1, &my_charset_bin);
+ } /* end of if (pos > BIN_LOG_HEADER_SIZE); */
+ else
+ {
+ /* The Format_description_log_event event will be found naturally. */
+ }
+
+ /* seek to the requested position, to start the requested dump */
+ my_b_seek(&log, pos); // Seek will done on next read
+ while (!net->error && net->vio != 0 && !thd->killed)
+ {
while (!(error = Log_event::read_log_event(&log, packet, log_lock)))
{
#ifndef DBUG_OFF
@@ -436,12 +518,26 @@ impossible position";
goto err;
}
#endif
- if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
+
+ if ((*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT)
+ {
+ binlog_can_be_corrupted= test((*packet)[FLAGS_OFFSET+1] &
+ LOG_EVENT_BINLOG_IN_USE_F);
+ (*packet)[FLAGS_OFFSET+1] &= ~LOG_EVENT_BINLOG_IN_USE_F;
+ }
+ else if ((*packet)[EVENT_TYPE_OFFSET+1] == STOP_EVENT)
+ binlog_can_be_corrupted= FALSE;
+
+ if (my_net_write(net, (char*)packet->ptr(), packet->length()))
{
errmsg = "Failed on my_net_write()";
my_errno= ER_UNKNOWN_ERROR;
goto err;
}
+
+ if (thd->variables.sync_replication)
+ ha_repl_report_sent_binlog(thd, log_file_name, my_b_tell(&log));
+
DBUG_PRINT("info", ("log event code %d",
(*packet)[LOG_EVENT_OFFSET+1] ));
if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
@@ -455,39 +551,25 @@ impossible position";
}
packet->set("\0", 1, &my_charset_bin);
}
+
+ /*
+ here we were reading binlog that was not closed properly (as a result
+ of a crash ?). treat any corruption as EOF
+ */
+ if (binlog_can_be_corrupted && error != LOG_READ_MEM)
+ error=LOG_READ_EOF;
/*
TODO: now that we are logging the offset, check to make sure
- the recorded offset and the actual match
+ the recorded offset and the actual match.
+ Guilhem 2003-06: this is not true if this master is a slave
+ <4.0.15 running with --log-slave-updates, because then log_pos may
+ be the offset in the-master-of-this-master's binlog.
*/
- if (error != LOG_READ_EOF)
- {
- my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
- switch (error) {
- case LOG_READ_BOGUS:
- errmsg = "bogus data in log event";
- break;
- case LOG_READ_TOO_LARGE:
- errmsg = "log event entry exceeded max_allowed_packet; \
-Increase max_allowed_packet on master";
- break;
- case LOG_READ_IO:
- errmsg = "I/O error reading log event";
- break;
- case LOG_READ_MEM:
- errmsg = "memory allocation failed reading log event";
- break;
- case LOG_READ_TRUNC:
- errmsg = "binlog truncated in the middle of event";
- break;
- default:
- errmsg = "unknown error reading log event on the master";
- break;
- }
+ if (test_for_non_eof_log_read_errors(error, &errmsg))
goto err;
- }
if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
- mysql_bin_log.is_active(log_file_name))
+ mysql_bin_log.is_active(log_file_name))
{
/*
Block until there is more data in the log
@@ -523,9 +605,9 @@ Increase max_allowed_packet on master";
now, but we'll be quick and just read one record
TODO:
- Add an counter that is incremented for each time we update
- the binary log. We can avoid the following read if the counter
- has not been updated since last read.
+ Add an counter that is incremented for each time we update the
+ binary log. We can avoid the following read if the counter
+ has not been updated since last read.
*/
pthread_mutex_lock(log_lock);
@@ -569,6 +651,9 @@ Increase max_allowed_packet on master";
goto err;
}
+ if (thd->variables.sync_replication)
+ ha_repl_report_sent_binlog(thd, log_file_name, my_b_tell(&log));
+
if ((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
{
if (send_file(thd))
@@ -618,21 +703,34 @@ Increase max_allowed_packet on master";
(void) my_close(file, MYF(MY_WME));
/*
- Even if the previous log contained a Rotate_log_event, we still fake
- one.
+ Call fake_rotate_event() in case the previous log (the one which
+ we have just finished reading) did not contain a Rotate event
+ (for example (I don't know any other example) the previous log
+ was the last one before the master was shutdown & restarted).
+ This way we tell the slave about the new log's name and
+ position. If the binlog is 5.0, the next event we are going to
+ read and send is Format_description_log_event.
*/
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 ||
- fake_rotate_event(net, packet, log_file_name, BIN_LOG_HEADER_SIZE, &errmsg))
+ fake_rotate_event(net, packet, log_file_name, BIN_LOG_HEADER_SIZE,
+ &errmsg))
{
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
+
+ if (thd->variables.sync_replication)
+ ha_repl_report_sent_binlog(thd, log_file_name, 0);
+
packet->length(0);
packet->append('\0');
}
}
end:
+ if (thd->variables.sync_replication)
+ ha_repl_report_replication_stop(thd);
+
end_io_cache(&log);
(void)my_close(file, MYF(MY_WME));
@@ -644,6 +742,9 @@ end:
DBUG_VOID_RETURN;
err:
+ if (thd->variables.sync_replication)
+ ha_repl_report_replication_stop(thd);
+
thd->proc_info = "Waiting to finalize termination";
end_io_cache(&log);
/*
@@ -658,7 +759,7 @@ err:
pthread_mutex_unlock(&LOCK_thread_count);
if (file >= 0)
(void) my_close(file, MYF(MY_WME));
- send_error(thd, my_errno, errmsg);
+ my_message(my_errno, errmsg, MYF(0));
DBUG_VOID_RETURN;
}
@@ -667,17 +768,17 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
int slave_errno= 0;
int thread_mask;
DBUG_ENTER("start_slave");
-
- if (check_access(thd, SUPER_ACL, any_db,0,0,0))
+
+ if (check_access(thd, SUPER_ACL, any_db,0,0,0,0))
DBUG_RETURN(1);
lock_slave_threads(mi); // this allows us to cleanly read slave_running
// Get a mask of _stopped_ threads
init_thread_mask(&thread_mask,mi,1 /* inverse */);
/*
- Below we will start all stopped threads.
- But if the user wants to start only one thread, do as if the other thread
- was running (as we don't wan't to touch the other thread), so set the
- bit to 0 for the other thread
+ Below we will start all stopped threads. But if the user wants to
+ start only one thread, do as if the other thread was running (as we
+ don't wan't to touch the other thread), so set the bit to 0 for the
+ other thread
*/
if (thd->lex->slave_thd_opt)
thread_mask&= thd->lex->slave_thd_opt;
@@ -688,10 +789,10 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
slave_errno=ER_MASTER_INFO;
else if (server_id_supplied && *mi->host)
{
- /*
- If we will start SQL thread we will care about UNTIL options
- If not and they are specified we will ignore them and warn user
- about this fact.
+ /*
+ If we will start SQL thread we will care about UNTIL options If
+ not and they are specified we will ignore them and warn user
+ about this fact.
*/
if (thread_mask & SLAVE_SQL)
{
@@ -701,19 +802,19 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
{
mi->rli.until_condition= RELAY_LOG_INFO::UNTIL_MASTER_POS;
mi->rli.until_log_pos= thd->lex->mi.pos;
- /*
- We don't check thd->lex->mi.log_file_name for NULL here
+ /*
+ We don't check thd->lex->mi.log_file_name for NULL here
since it is checked in sql_yacc.yy
*/
strmake(mi->rli.until_log_name, thd->lex->mi.log_file_name,
- sizeof(mi->rli.until_log_name)-1);
- }
+ sizeof(mi->rli.until_log_name)-1);
+ }
else if (thd->lex->mi.relay_log_pos)
{
mi->rli.until_condition= RELAY_LOG_INFO::UNTIL_RELAY_POS;
mi->rli.until_log_pos= thd->lex->mi.relay_log_pos;
strmake(mi->rli.until_log_name, thd->lex->mi.relay_log_name,
- sizeof(mi->rli.until_log_name)-1);
+ sizeof(mi->rli.until_log_name)-1);
}
else
clear_until_condition(&mi->rli);
@@ -731,30 +832,30 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
p_end points to the first invalid character. If it equals
to p, no digits were found, error. If it contains '\0' it
means conversion went ok.
- */
+ */
if (p_end==p || *p_end)
slave_errno=ER_BAD_SLAVE_UNTIL_COND;
}
else
slave_errno=ER_BAD_SLAVE_UNTIL_COND;
-
+
/* mark the cached result of the UNTIL comparison as "undefined" */
- mi->rli.until_log_names_cmp_result=
+ mi->rli.until_log_names_cmp_result=
RELAY_LOG_INFO::UNTIL_LOG_NAMES_CMP_UNKNOWN;
/* Issuing warning then started without --skip-slave-start */
if (!opt_skip_slave_start)
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_MISSING_SKIP_SLAVE,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_MISSING_SKIP_SLAVE,
ER(ER_MISSING_SKIP_SLAVE));
}
-
+
pthread_mutex_unlock(&mi->rli.data_lock);
}
else if (thd->lex->mi.pos || thd->lex->mi.relay_log_pos)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_UNTIL_COND_IGNORED,
- ER(ER_UNTIL_COND_IGNORED));
-
-
+ ER(ER_UNTIL_COND_IGNORED));
+
if (!slave_errno)
slave_errno = start_slave_threads(0 /*no mutex */,
1 /* wait for start */,
@@ -766,16 +867,18 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
slave_errno = ER_BAD_SLAVE;
}
else
- //no error if all threads are already started, only a warning
+ {
+ /* no error if all threads are already started, only a warning */
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SLAVE_WAS_RUNNING,
ER(ER_SLAVE_WAS_RUNNING));
+ }
unlock_slave_threads(mi);
-
+
if (slave_errno)
{
if (net_report)
- send_error(thd, slave_errno);
+ my_message(slave_errno, ER(slave_errno), MYF(0));
DBUG_RETURN(1);
}
else if (net_report)
@@ -791,7 +894,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
if (!thd)
thd = current_thd;
- if (check_access(thd, SUPER_ACL, any_db,0,0,0))
+ if (check_access(thd, SUPER_ACL, any_db,0,0,0,0))
return 1;
thd->proc_info = "Killing slave";
int thread_mask;
@@ -825,7 +928,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
if (slave_errno)
{
if (net_report)
- send_error(thd, slave_errno);
+ my_message(slave_errno, ER(slave_errno), MYF(0));
return 1;
}
else if (net_report)
@@ -871,7 +974,7 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
1 /* just reset */,
&errmsg)))
goto err;
-
+
/*
Clear master's log coordinates and reset host/user/etc to the values
specified in mysqld's options (only for good display of SHOW SLAVE STATUS;
@@ -880,13 +983,13 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
STATUS; before doing START SLAVE;
*/
init_master_info_with_options(mi);
- /*
+ /*
Reset errors (the idea is that we forget about the
old master).
*/
clear_slave_error(&mi->rli);
clear_until_condition(&mi->rli);
-
+
// close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0
end_master_info(mi);
// and delete these two files
@@ -906,7 +1009,7 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
err:
unlock_slave_threads(mi);
- if (error)
+ if (error)
my_error(sql_errno, MYF(0), errmsg);
DBUG_RETURN(error);
}
@@ -954,13 +1057,13 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
it will be slow because it will iterate through the list
again. We just to do kill the thread ourselves.
*/
- tmp->awake(1/*prepare to die*/);
+ tmp->awake(THD::KILL_QUERY);
pthread_mutex_unlock(&tmp->LOCK_delete);
}
}
-int change_master(THD* thd, MASTER_INFO* mi)
+bool change_master(THD* thd, MASTER_INFO* mi)
{
int thread_mask;
const char* errmsg= 0;
@@ -971,9 +1074,9 @@ int change_master(THD* thd, MASTER_INFO* mi)
init_thread_mask(&thread_mask,mi,0 /*not inverse*/);
if (thread_mask) // We refuse if any slave thread is running
{
- net_printf(thd,ER_SLAVE_MUST_STOP);
+ my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
unlock_slave_threads(mi);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
thd->proc_info = "Changing master";
@@ -982,9 +1085,9 @@ int change_master(THD* thd, MASTER_INFO* mi)
if (init_master_info(mi, master_info_file, relay_log_info_file, 0,
thread_mask))
{
- send_error(thd, ER_MASTER_INFO);
+ my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
unlock_slave_threads(mi);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
/*
@@ -1101,9 +1204,9 @@ int change_master(THD* thd, MASTER_INFO* mi)
0 /* not only reset, but also reinit */,
&errmsg))
{
- net_printf(thd, 0, "Failed purging old relay logs: %s",errmsg);
+ my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
unlock_slave_threads(mi);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
else
@@ -1115,11 +1218,11 @@ int change_master(THD* thd, MASTER_INFO* mi)
mi->rli.group_relay_log_name,
mi->rli.group_relay_log_pos,
0 /*no data lock*/,
- &msg))
+ &msg, 0))
{
- net_printf(thd,0,"Failed initializing relay log position: %s",msg);
+ my_error(ER_RELAY_LOG_INIT, MYF(0), msg);
unlock_slave_threads(mi);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
mi->rli.group_master_log_pos = mi->master_log_pos;
@@ -1161,14 +1264,15 @@ int change_master(THD* thd, MASTER_INFO* mi)
unlock_slave_threads(mi);
thd->proc_info = 0;
send_ok(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
int reset_master(THD* thd)
{
if (!mysql_bin_log.is_open())
{
- my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(ME_BELL+ME_WAITTANG));
+ my_message(ER_FLUSH_MASTER_BINLOG_CLOSED,
+ ER(ER_FLUSH_MASTER_BINLOG_CLOSED), MYF(ME_BELL+ME_WAITTANG));
return 1;
}
return mysql_bin_log.reset_logs(thd);
@@ -1192,22 +1296,27 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
}
-int show_binlog_events(THD* thd)
+bool mysql_show_binlog_events(THD* thd)
{
Protocol *protocol= thd->protocol;
- DBUG_ENTER("show_binlog_events");
+ DBUG_ENTER("mysql_show_binlog_events");
List<Item> field_list;
const char *errmsg = 0;
+ bool ret = TRUE;
IO_CACHE log;
File file = -1;
+ Format_description_log_event *description_event= new
+ Format_description_log_event(3); /* MySQL 4.0 by default */
Log_event::init_show_field_list(&field_list);
- if (protocol-> send_fields(&field_list, 1))
- DBUG_RETURN(-1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
if (mysql_bin_log.is_open())
{
LEX_MASTER_INFO *lex_mi= &thd->lex->mi;
+ SELECT_LEX_UNIT *unit= &thd->lex->unit;
ha_rows event_count, limit_start, limit_end;
my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly
char search_file_name[FN_REFLEN], *name;
@@ -1215,9 +1324,10 @@ int show_binlog_events(THD* thd)
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
LOG_INFO linfo;
Log_event* ev;
-
- limit_start= thd->lex->current_select->offset_limit;
- limit_end= thd->lex->current_select->select_limit + limit_start;
+
+ unit->set_limit(thd->lex->current_select);
+ limit_start= unit->offset_limit_cnt;
+ limit_end= unit->select_limit_cnt;
name= search_file_name;
if (log_file_name)
@@ -1238,10 +1348,38 @@ int show_binlog_events(THD* thd)
goto err;
pthread_mutex_lock(log_lock);
+
+ /*
+ open_binlog() sought to position 4.
+ Read the first event in case it's a Format_description_log_event, to
+ know the format. If there's no such event, we are 3.23 or 4.x. This
+ code, like before, can't read 3.23 binlogs.
+ This code will fail on a mixed relay log (one which has Format_desc then
+ Rotate then Format_desc).
+ */
+
+ ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,description_event);
+ if (ev)
+ {
+ if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
+ {
+ delete description_event;
+ description_event= (Format_description_log_event*) ev;
+ }
+ else
+ delete ev;
+ }
+
my_b_seek(&log, pos);
+ if (!description_event->is_valid())
+ {
+ errmsg="Invalid Format_description event; could be out of memory";
+ goto err;
+ }
+
for (event_count = 0;
- (ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,0)); )
+ (ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,description_event)); )
{
if (event_count >= limit_start &&
ev->net_send(protocol, linfo.log_file_name, pos))
@@ -1269,7 +1407,10 @@ int show_binlog_events(THD* thd)
pthread_mutex_unlock(log_lock);
}
+ ret= FALSE;
+
err:
+ delete description_event;
if (file >= 0)
{
end_io_cache(&log);
@@ -1279,19 +1420,19 @@ err:
if (errmsg)
{
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
- "SHOW BINLOG EVENTS", errmsg);
- DBUG_RETURN(-1);
+ "SHOW BINLOG EVENTS", errmsg);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_RETURN(0);
+ DBUG_RETURN(ret);
}
-int show_binlog_info(THD* thd)
+bool show_binlog_info(THD* thd)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_info");
@@ -1302,8 +1443,9 @@ int show_binlog_info(THD* thd)
field_list.push_back(new Item_empty_string("Binlog_Do_DB",255));
field_list.push_back(new Item_empty_string("Binlog_Ignore_DB",255));
- if (protocol->send_fields(&field_list, 1))
- DBUG_RETURN(-1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
if (mysql_bin_log.is_open())
@@ -1316,10 +1458,10 @@ int show_binlog_info(THD* thd)
protocol->store(&binlog_do_db);
protocol->store(&binlog_ignore_db);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -1331,11 +1473,11 @@ int show_binlog_info(THD* thd)
thd Thread specific variable
RETURN VALUES
- 0 ok
- 1 error (Error message sent to client)
+ FALSE OK
+ TRUE error
*/
-int show_binlogs(THD* thd)
+bool show_binlogs(THD* thd)
{
IO_CACHE *index_file;
LOG_INFO cur;
@@ -1349,16 +1491,16 @@ int show_binlogs(THD* thd)
if (!mysql_bin_log.is_open())
{
- //TODO: Replace with ER() error message
- send_error(thd, 0, "You are not using binary logging");
+ my_message(ER_NO_BINARY_LOGGING, ER(ER_NO_BINARY_LOGGING), MYF(0));
return 1;
}
field_list.push_back(new Item_empty_string("Log_name", 255));
field_list.push_back(new Item_return_int("File_size", 20,
MYSQL_TYPE_LONGLONG));
- if (protocol->send_fields(&field_list, 1))
- DBUG_RETURN(1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
mysql_bin_log.lock_index();
index_file=mysql_bin_log.get_index_file();
@@ -1397,11 +1539,11 @@ int show_binlogs(THD* thd)
}
mysql_bin_log.unlock_index();
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
mysql_bin_log.unlock_index();
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
@@ -1421,17 +1563,16 @@ int log_loaded_block(IO_CACHE* file)
lf_info->last_pos_in_file = file->pos_in_file;
if (lf_info->wrote_create_file)
{
- Append_block_log_event a(lf_info->thd, lf_info->db, buffer, block_len,
- lf_info->log_delayed);
+ Append_block_log_event a(lf_info->thd, lf_info->thd->db, buffer,
+ block_len, lf_info->log_delayed);
mysql_bin_log.write(&a);
}
else
{
- Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
- lf_info->table_name, *lf_info->fields,
- lf_info->handle_dup, lf_info->ignore, buffer,
- block_len, lf_info->log_delayed);
- mysql_bin_log.write(&c);
+ Begin_load_query_log_event b(lf_info->thd, lf_info->thd->db,
+ buffer, block_len,
+ lf_info->log_delayed);
+ mysql_bin_log.write(&b);
lf_info->wrote_create_file = 1;
DBUG_SYNC_POINT("debug_lock.created_file_event",10);
}
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 21b3d2955f7..9eb6456ee20 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -36,24 +36,25 @@ extern I_List<i_string> binlog_do_db, binlog_ignore_db;
extern int max_binlog_dump_events;
extern my_bool opt_sporadic_binlog_dump_fail;
-#define KICK_SLAVE(thd) { pthread_mutex_lock(&(thd)->LOCK_delete); (thd)->awake(0 /* do not prepare to die*/); pthread_mutex_unlock(&(thd)->LOCK_delete); }
-
-File open_binlog(IO_CACHE *log, const char *log_file_name,
- const char **errmsg);
+#define KICK_SLAVE(thd) do { \
+ pthread_mutex_lock(&(thd)->LOCK_delete); \
+ (thd)->awake(THD::NOT_KILLED); \
+ pthread_mutex_unlock(&(thd)->LOCK_delete); \
+ } while(0)
int start_slave(THD* thd, MASTER_INFO* mi, bool net_report);
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report);
-int change_master(THD* thd, MASTER_INFO* mi);
-int show_binlog_events(THD* thd);
+bool change_master(THD* thd, MASTER_INFO* mi);
+bool mysql_show_binlog_events(THD* thd);
int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
const char* log_file_name2, ulonglong log_pos2);
int reset_slave(THD *thd, MASTER_INFO* mi);
int reset_master(THD* thd);
-int purge_master_logs(THD* thd, const char* to_log);
-int purge_master_logs_before_date(THD* thd, time_t purge_time);
+bool purge_master_logs(THD* thd, const char* to_log);
+bool purge_master_logs_before_date(THD* thd, time_t purge_time);
bool log_in_use(const char* log_name);
void adjust_linfo_offsets(my_off_t purge_offset);
-int show_binlogs(THD* thd);
+bool show_binlogs(THD* thd);
extern int init_master_info(MASTER_INFO* mi);
void kill_zombie_dump_threads(uint32 slave_server_id);
int check_binlog_magic(IO_CACHE* log, const char** errmsg);
@@ -62,12 +63,7 @@ typedef struct st_load_file_info
{
THD* thd;
my_off_t last_pos_in_file;
- sql_exchange* ex;
- List <Item> *fields;
- enum enum_duplicates handle_dup;
- char* db;
- char* table_name;
- bool wrote_create_file, log_delayed, ignore;
+ bool wrote_create_file, log_delayed;
} LOAD_FILE_INFO;
int log_loaded_block(IO_CACHE* file);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 59b82b53b32..3916509db69 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -30,21 +30,42 @@
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
"MAYBE_REF","ALL","range","index","fulltext",
- "ref_or_null","unique_subquery","index_subquery"
+ "ref_or_null","unique_subquery","index_subquery",
+ "index_merge"
};
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
-static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
+static bool make_join_statistics(JOIN *join, TABLE_LIST *leaves, COND *conds,
DYNAMIC_ARRAY *keyuse);
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
JOIN_TAB *join_tab,
uint tables, COND *conds,
+ COND_EQUAL *cond_equal,
table_map table_map, SELECT_LEX *select_lex);
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
table_map used_tables);
-static void find_best_combination(JOIN *join,table_map rest_tables);
+static void choose_plan(JOIN *join,table_map join_tables);
+
+static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd,
+ table_map remaining_tables, uint idx,
+ double record_count, double read_time);
+static void optimize_straight_join(JOIN *join, table_map join_tables);
+static void greedy_search(JOIN *join, table_map remaining_tables,
+ uint depth, uint prune_level);
+static void best_extension_by_limited_search(JOIN *join,
+ table_map remaining_tables,
+ uint idx, double record_count,
+ double read_time, uint depth,
+ uint prune_level);
+static uint determine_search_depth(JOIN* join);
+static int join_tab_cmp(const void* ptr1, const void* ptr2);
+static int join_tab_cmp_straight(const void* ptr1, const void* ptr2);
+/*
+ TODO: 'find_best' is here only temporarily until 'greedy_search' is
+ tested and approved.
+*/
static void find_best(JOIN *join,table_map rest_tables,uint index,
double record_count,double read_time);
static uint cache_record_length(JOIN *join,uint index);
@@ -55,6 +76,7 @@ static store_key *get_store_key(THD *thd,
KEY_PART_INFO *key_part, char *key_buff,
uint maybe_null);
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
+static void make_outerjoin_info(JOIN *join);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void make_join_readinfo(JOIN *join,uint options);
static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
@@ -63,32 +85,57 @@ static void update_depend_map(JOIN *join, ORDER *order);
static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
bool change_list, bool *simple_order);
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
- List<Item> &fields, bool send_row,
- uint select_options, const char *info,
- Item *having, Procedure *proc,
- SELECT_LEX_UNIT *unit);
-static COND *optimize_cond(THD *thd, COND *conds,
+ List<Item> &fields, bool send_row,
+ uint select_options, const char *info,
+ Item *having);
+static COND *build_equal_items(THD *thd, COND *cond,
+ COND_EQUAL *inherited,
+ List<TABLE_LIST> *join_list,
+ COND_EQUAL **cond_equal_ref);
+static COND* substitute_for_best_equal_field(COND *cond,
+ COND_EQUAL *cond_equal,
+ void *table_join_idx);
+static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
+ COND *conds, bool top);
+static COND *optimize_cond(JOIN *join, COND *conds,
+ List<TABLE_LIST> *join_list,
Item::cond_result *cond_value);
+static bool resolve_nested_join (TABLE_LIST *table);
static COND *remove_eq_conds(THD *thd, COND *cond,
Item::cond_result *cond_value);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
ulong options);
+static Next_select_func setup_end_select_func(JOIN *join);
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
Procedure *proc);
-static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
-static int sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
-static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last);
-static int end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
-static int end_send_group(JOIN *join, JOIN_TAB *join_tab,bool end_of_records);
-static int end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
-static int end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
-static int end_unique_update(JOIN *join,JOIN_TAB *join_tab,
- bool end_of_records);
-static int end_write_group(JOIN *join, JOIN_TAB *join_tab,
- bool end_of_records);
-static int test_if_group_changed(List<Item_buff> &list);
+
+static enum_nested_loop_state
+sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
+ int error, my_bool *report_error);
+static enum_nested_loop_state
+evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab);
+static enum_nested_loop_state
+sub_select(JOIN *join,JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+flush_cached_records(JOIN *join, JOIN_TAB *join_tab, bool skip_last);
+static enum_nested_loop_state
+end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_unique_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_write_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+
+static int test_if_group_changed(List<Cached_item> &list);
static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
static int join_read_system(JOIN_TAB *tab);
static int join_read_const(JOIN_TAB *tab);
@@ -113,7 +160,7 @@ static int join_read_next_same_or_null(READ_RECORD *info);
static COND *make_cond_for_table(COND *cond,table_map table,
table_map used_table);
static Item* part_of_refkey(TABLE *form,Field *field);
-static uint find_shortest_key(TABLE *table, const key_map *usable_keys);
+uint find_shortest_key(TABLE *table, const key_map *usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit, bool no_changes);
static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
@@ -124,6 +171,7 @@ 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,
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);
@@ -132,8 +180,8 @@ 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,
- List<Item> &all_fields,ORDER *new_order);
+static bool setup_new_fields(THD *thd, List<Item> &fields,
+ List<Item> &all_fields, ORDER *new_order);
static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array,
ORDER *order, List<Item> &fields,
bool *all_order_by_fields_used);
@@ -156,26 +204,37 @@ static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
+static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
bool distinct, const char *message=NullS);
static Item *remove_additional_cond(Item* conds);
+static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab);
/*
This handles SELECT with and without UNION
*/
-int handle_select(THD *thd, LEX *lex, select_result *result)
+bool handle_select(THD *thd, LEX *lex, select_result *result,
+ ulong setup_tables_done_option)
{
- int res;
+ bool res;
register SELECT_LEX *select_lex = &lex->select_lex;
DBUG_ENTER("handle_select");
if (select_lex->next_select())
- res=mysql_union(thd, lex, result, &lex->unit);
+ res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option);
else
+ {
+ SELECT_LEX_UNIT *unit= &lex->unit;
+ unit->set_limit(unit->global_parameters);
+ /*
+ 'options' of mysql_select will be set in JOIN, as far as JOIN for
+ every PS/SP execution new, we will not need reset this flag if
+ setup_tables_done_option changed for next rexecution
+ */
res= mysql_select(thd, &select_lex->ref_pointer_array,
(TABLE_LIST*) select_lex->table_list.first,
select_lex->with_wild, select_lex->item_list,
@@ -186,17 +245,18 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
(ORDER*) select_lex->group_list.first,
select_lex->having,
(ORDER*) lex->proc_list.first,
- select_lex->options | thd->options,
- result, &(lex->unit), &(lex->select_lex));
-
- /* Don't set res if it's -1 as we may want this later */
+ select_lex->options | thd->options |
+ setup_tables_done_option,
+ result, unit, select_lex);
+ }
DBUG_PRINT("info",("res: %d report_error: %d", res,
thd->net.report_error));
- if (thd->net.report_error || res<0)
+ res|= thd->net.report_error;
+ if (unlikely(res))
{
- result->send_error(0, NullS);
+ /* If we had a another error reported earlier then this will be ignored */
+ result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
result->abort();
- res= 1; // Error sent to client
}
DBUG_RETURN(res);
}
@@ -207,6 +267,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
*/
inline int setup_without_group(THD *thd, Item **ref_pointer_array,
TABLE_LIST *tables,
+ TABLE_LIST *leaves,
List<Item> &fields,
List<Item> &all_fields,
COND **conds,
@@ -219,11 +280,14 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
save_allow_sum_func= thd->allow_sum_func;
thd->allow_sum_func= 0;
- res= (setup_conds(thd, tables, conds) ||
- setup_order(thd, ref_pointer_array, tables, fields, all_fields,
- order) ||
- setup_group(thd, ref_pointer_array, tables, fields, all_fields,
- group, hidden_group_fields));
+ res= setup_conds(thd, tables, leaves, conds);
+
+ thd->allow_sum_func= save_allow_sum_func;
+ res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
+ order);
+ thd->allow_sum_func= 0;
+ res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
+ group, hidden_group_fields);
thd->allow_sum_func= save_allow_sum_func;
DBUG_RETURN(res);
}
@@ -261,17 +325,29 @@ JOIN::prepare(Item ***rref_pointer_array,
tables_list= tables_init;
select_lex= select_lex_arg;
select_lex->join= this;
+ join_list= &select_lex->top_join_list;
union_part= (unit_arg->first_select()->next_select() != 0);
+ /*
+ If we have already executed SELECT, then it have not sense to prevent
+ its table from update (see unique_table())
+ */
+ if (thd->derived_tables_processing)
+ select_lex->exclude_from_table_unique_test= TRUE;
+
/* Check that all tables, fields, conds and order are ok */
- if (setup_tables(tables_list) ||
+ if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
+ setup_tables(thd, &select_lex->context, join_list,
+ tables_list, &conds, &select_lex->leaf_tables,
+ FALSE)) ||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) ||
- setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
+ setup_fields(thd, (*rref_pointer_array), fields_list, 1,
&all_fields, 1) ||
- setup_without_group(thd, (*rref_pointer_array), tables_list, fields_list,
- all_fields, &conds, order, group_list,
+ setup_without_group(thd, (*rref_pointer_array), tables_list,
+ select_lex->leaf_tables, fields_list,
+ all_fields, &conds, order, group_list,
&hidden_group_fields))
DBUG_RETURN(-1); /* purecov: inspected */
@@ -283,7 +359,7 @@ JOIN::prepare(Item ***rref_pointer_array,
thd->allow_sum_func=1;
select_lex->having_fix_field= 1;
bool having_fix_rc= (!having->fixed &&
- (having->fix_fields(thd, tables_list, &having) ||
+ (having->fix_fields(thd, &having) ||
having->check_cols(1)));
select_lex->having_fix_field= 0;
if (having_fix_rc || thd->net.report_error)
@@ -292,15 +368,19 @@ JOIN::prepare(Item ***rref_pointer_array,
having->split_sum_func(thd, ref_pointer_array, all_fields);
}
- // Is it subselect
+ if (!thd->lex->view_prepare_mode)
{
Item_subselect *subselect;
+ /* Is it subselect? */
if ((subselect= select_lex->master_unit()->item))
{
Item_subselect::trans_res res;
if ((res= subselect->select_transformer(this)) !=
Item_subselect::RES_OK)
+ {
+ select_lex->fix_prepare_information(thd, &conds);
DBUG_RETURN((res == Item_subselect::RES_ERROR));
+ }
}
}
@@ -329,12 +409,15 @@ JOIN::prepare(Item ***rref_pointer_array,
}
if (flag == 3)
{
- my_error(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,MYF(0));
+ my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
+ ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
DBUG_RETURN(-1);
}
}
TABLE_LIST *table_ptr;
- for (table_ptr= tables_list ; table_ptr ; table_ptr= table_ptr->next)
+ for (table_ptr= select_lex->leaf_tables;
+ table_ptr;
+ table_ptr= table_ptr->next_leaf)
tables++;
}
{
@@ -349,28 +432,29 @@ JOIN::prepare(Item ***rref_pointer_array,
goto err; /* purecov: inspected */
if (procedure)
{
- if (setup_new_fields(thd, tables_list, fields_list, all_fields,
+ if (setup_new_fields(thd, fields_list, all_fields,
procedure->param_fields))
goto err; /* purecov: inspected */
if (procedure->group)
{
if (!test_if_subpart(procedure->group,group_list))
{ /* purecov: inspected */
- my_message(0,"Can't handle procedures with differents groups yet",
- MYF(0)); /* purecov: inspected */
+ my_message(ER_DIFF_GROUPS_PROC, ER(ER_DIFF_GROUPS_PROC),
+ MYF(0)); /* purecov: inspected */
goto err; /* purecov: inspected */
}
}
#ifdef NOT_NEEDED
else if (!group_list && procedure->flags & PROC_GROUP)
{
- my_message(0,"Select must have a group with this procedure",MYF(0));
+ my_message(ER_NO_GROUP_FOR_PROC, MYF(0));
goto err;
}
#endif
if (order && (procedure->flags & PROC_NO_SORT))
{ /* purecov: inspected */
- my_message(0,"Can't use order with this procedure",MYF(0)); /* purecov: inspected */
+ my_message(ER_ORDER_WITH_PROC, ER(ER_ORDER_WITH_PROC),
+ MYF(0)); /* purecov: inspected */
goto err; /* purecov: inspected */
}
}
@@ -379,13 +463,6 @@ JOIN::prepare(Item ***rref_pointer_array,
count_field_types(&tmp_table_param, all_fields, 0);
ref_pointer_array_size= all_fields.elements*sizeof(Item*);
this->group= group_list != 0;
- row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
- unit_arg->select_limit_cnt);
- /* select_limit is used to decide if we are likely to scan the whole table */
- select_limit= unit_arg->select_limit_cnt;
- if (having || (select_options & OPTION_FOUND_ROWS))
- select_limit= HA_POS_ERROR;
- do_send_rows = (unit_arg->select_limit_cnt) ? 1 : 0;
unit= unit_arg;
#ifdef RESTRICTED_GROUP
@@ -395,16 +472,7 @@ JOIN::prepare(Item ***rref_pointer_array,
goto err;
}
#endif
- /*
- We must not yet prepare the result table if it is the same as one of the
- source tables (INSERT SELECT). This is checked in mysql_execute_command()
- and OPTION_BUFFER_RESULT is added to the select_options. A temporary
- table is then used to hold the result. The preparation may disable
- indexes on the result table, which may be used during the select, if it
- is the same table (Bug #6034). Do the preparation after the select phase.
- */
- if (! procedure && ! test(select_options & OPTION_BUFFER_RESULT) &&
- result && result->prepare(fields_list, unit_arg))
+ if (!procedure && result && result->prepare(fields_list, unit_arg))
goto err; /* purecov: inspected */
if (select_lex->olap == ROLLUP_TYPE && rollup_init())
@@ -412,6 +480,7 @@ JOIN::prepare(Item ***rref_pointer_array,
if (alloc_func_list())
goto err;
+ select_lex->fix_prepare_information(thd, &conds);
DBUG_RETURN(0); // All OK
err:
@@ -457,7 +526,6 @@ bool JOIN::test_in_subselect(Item **where)
return 0;
}
-
/*
global select optimisation.
return 0 - success
@@ -473,6 +541,13 @@ JOIN::optimize()
DBUG_RETURN(0);
optimized= 1;
+ row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
+ unit->select_limit_cnt);
+ /* select_limit is used to decide if we are likely to scan the whole table */
+ select_limit= unit->select_limit_cnt;
+ if (having || (select_options & OPTION_FOUND_ROWS))
+ select_limit= HA_POS_ERROR;
+ do_send_rows = (unit->select_limit_cnt) ? 1 : 0;
// Ignore errors of execution if option IGNORE present
if (thd->lex->ignore)
thd->lex->current_select->no_error= 1;
@@ -487,15 +562,43 @@ JOIN::optimize()
}
else if ((conds=new Item_cond_and(conds,having)))
{
- conds->fix_fields(thd, tables_list, &conds);
+ /*
+ Item_cond_and can't be fixed after creation, so we do not check
+ conds->fixed
+ */
+ conds->fix_fields(thd, &conds);
conds->change_ref_to_fields(thd, tables_list);
conds->top_level_item();
having= 0;
}
}
#endif
+ SELECT_LEX *sel= thd->lex->current_select;
+ if (sel->first_cond_optimization)
+ {
+ /*
+ The following code will allocate the new items in a permanent
+ MEMROOT for prepared statements and stored procedures.
+ */
+
+ Query_arena *arena= thd->stmt_arena, backup;
+ if (arena->is_conventional())
+ arena= 0; // For easier test
+ else
+ thd->set_n_backup_active_arena(arena, &backup);
+
+ sel->first_cond_optimization= 0;
+
+ /* Convert all outer joins to inner joins if possible */
+ conds= simplify_joins(this, join_list, conds, TRUE);
+
+ sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
- conds= optimize_cond(thd, conds, &cond_value);
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ }
+
+ conds= optimize_cond(this, conds, join_list, &cond_value);
if (thd->net.report_error)
{
error= 1;
@@ -506,6 +609,7 @@ JOIN::optimize()
if (cond_value == Item::COND_FALSE ||
(!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
{ /* Impossible cond */
+ DBUG_PRINT("info", ("Impossible WHERE"));
zero_result_cause= "Impossible WHERE";
error= 0;
DBUG_RETURN(0);
@@ -519,33 +623,37 @@ JOIN::optimize()
opt_sum_query() returns -1 if no rows match to the WHERE conditions,
or 1 if all items were resolved, or 0, or an error number HA_ERR_...
*/
- if ((res=opt_sum_query(tables_list, all_fields, conds)))
+ if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
{
if (res > 1)
{
+ DBUG_PRINT("error",("Error from opt_sum_query"));
DBUG_RETURN(1);
}
if (res < 0)
{
+ DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
error=0;
DBUG_RETURN(0);
}
+ DBUG_PRINT("info",("Select tables optimized away"));
zero_result_cause= "Select tables optimized away";
tables_list= 0; // All tables resolved
}
}
if (!tables_list)
{
+ DBUG_PRINT("info",("No tables"));
error= 0;
DBUG_RETURN(0);
}
error= -1; // Error is sent to client
- sort_by_table= get_sort_by_table(order, group_list, tables_list);
+ sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
/* Calculate how to do the join */
thd->proc_info= "statistics";
- if (make_join_statistics(this, tables_list, conds, &keyuse) ||
+ if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
thd->is_fatal_error)
{
DBUG_PRINT("error",("Error: make_join_statistics() failed"));
@@ -582,20 +690,49 @@ JOIN::optimize()
if (const_tables && !thd->locked_tables &&
!(select_options & SELECT_NO_UNLOCK))
mysql_unlock_some_tables(thd, table, const_tables);
-
if (!conds && outer_join)
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
conds=new Item_int((longlong) 1,1); // Always true
}
- select=make_select(*table, const_table_map,
- const_table_map, conds, &error);
+ select= make_select(*table, const_table_map,
+ const_table_map, conds, 1, &error);
if (error)
{ /* purecov: inspected */
error= -1; /* purecov: inspected */
DBUG_PRINT("error",("Error: make_select() failed"));
DBUG_RETURN(1);
}
+
+ make_outerjoin_info(this);
+
+ /*
+ Among the equal fields belonging to the same multiple equality
+ choose the one that is to be retrieved first and substitute
+ all references to these in where condition for a reference for
+ the selected field.
+ */
+ if (conds)
+ {
+ conds= substitute_for_best_equal_field(conds, cond_equal, map2table);
+ conds->update_used_tables();
+ DBUG_EXECUTE("where", print_where(conds, "after substitute_best_equal"););
+ }
+ /*
+ Permorm the the optimization on fields evaluation mentioned above
+ for all on expressions.
+ */
+ for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables ; tab++)
+ {
+ if (*tab->on_expr_ref)
+ {
+ *tab->on_expr_ref= substitute_for_best_equal_field(*tab->on_expr_ref,
+ tab->cond_equal,
+ map2table);
+ (*tab->on_expr_ref)->update_used_tables();
+ }
+ }
+
if (make_join_select(this, select, conds))
{
zero_result_cause=
@@ -823,32 +960,35 @@ JOIN::optimize()
#endif
DBUG_EXECUTE("info",TEST_join(this););
- /*
- Because filesort always does a full table scan or a quick range scan
- we must add the removed reference to the select for the table.
- We only need to do this when we have a simple_order or simple_group
- as in other cases the join is done before the sort.
- */
- if (const_tables != tables &&
- (order || group_list) &&
- join_tab[const_tables].type != JT_ALL &&
- join_tab[const_tables].type != JT_FT &&
- join_tab[const_tables].type != JT_REF_OR_NULL &&
- (order && simple_order || group_list && simple_group))
- {
- if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
- DBUG_RETURN(1);
- }
- if (!(select_options & SELECT_BIG_RESULT) &&
- ((group_list && const_tables != tables &&
- (!simple_group ||
- !test_if_skip_sort_order(&join_tab[const_tables], group_list,
- unit->select_limit_cnt, 0))) ||
- select_distinct) &&
- tmp_table_param.quick_group && !procedure)
+ if (const_tables != tables)
{
- need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
+ /*
+ Because filesort always does a full table scan or a quick range scan
+ we must add the removed reference to the select for the table.
+ We only need to do this when we have a simple_order or simple_group
+ as in other cases the join is done before the sort.
+ */
+ if ((order || group_list) &&
+ join_tab[const_tables].type != JT_ALL &&
+ join_tab[const_tables].type != JT_FT &&
+ join_tab[const_tables].type != JT_REF_OR_NULL &&
+ (order && simple_order || group_list && simple_group))
+ {
+ if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
+ DBUG_RETURN(1);
+ }
+
+ if (!(select_options & SELECT_BIG_RESULT) &&
+ ((group_list &&
+ (!simple_group ||
+ !test_if_skip_sort_order(&join_tab[const_tables], group_list,
+ unit->select_limit_cnt, 0))) ||
+ select_distinct) &&
+ tmp_table_param.quick_group && !procedure)
+ {
+ need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
+ }
}
tmp_having= having;
@@ -904,13 +1044,15 @@ JOIN::optimize()
if (create_sort_index(thd, this, group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
alloc_group_fields(this, group_list) ||
- make_sum_func_list(all_fields, fields_list, 1))
+ make_sum_func_list(all_fields, fields_list, 1) ||
+ setup_sum_funcs(thd, sum_funcs))
DBUG_RETURN(1);
group_list=0;
}
else
{
- if (make_sum_func_list(all_fields, fields_list, 0))
+ if (make_sum_func_list(all_fields, fields_list, 0) ||
+ setup_sum_funcs(thd, sum_funcs))
DBUG_RETURN(1);
if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{
@@ -948,9 +1090,10 @@ JOIN::optimize()
order=0;
}
}
-
- if (thd->lex->subqueries)
+
+ if (select_lex->uncacheable && !is_top_level_join())
{
+ /* If this join belongs to an uncacheable subquery */
if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
DBUG_RETURN(-1);
error= 0; // Ensure that tmp_join.error= 0
@@ -976,18 +1119,6 @@ int
JOIN::reinit()
{
DBUG_ENTER("JOIN::reinit");
- /* TODO move to unit reinit */
- unit->offset_limit_cnt =select_lex->offset_limit;
- unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit;
- if (unit->select_limit_cnt < select_lex->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // no limit
- if (unit->select_limit_cnt == HA_POS_ERROR)
- select_lex->options&= ~OPTION_FOUND_ROWS;
-
- if (!optimized && setup_tables(tables_list))
- DBUG_RETURN(1);
-
- /* Reset of sum functions */
first_record= 0;
if (exec_tmp_table1)
@@ -1013,6 +1144,7 @@ JOIN::reinit()
if (tmp_join)
restore_tmp();
+ /* Reset of sum functions */
if (sum_funcs)
{
Item_sum *func, **func_ptr= sum_funcs;
@@ -1045,7 +1177,7 @@ JOIN::exec()
{
int tmp_error;
DBUG_ENTER("JOIN::exec");
-
+
error= 0;
if (procedure)
{
@@ -1056,13 +1188,7 @@ JOIN::exec()
DBUG_VOID_RETURN;
}
}
- else if (test(select_options & OPTION_BUFFER_RESULT) &&
- result && result->prepare(fields_list, unit))
- {
- error= 1;
- thd->limit_found_rows= thd->examined_row_count= 0;
- DBUG_VOID_RETURN;
- }
+ (void) result->prepare2(); // Currently, this cannot fail.
if (!tables_list)
{ // Only test of functions
@@ -1071,7 +1197,8 @@ JOIN::exec()
(zero_result_cause?zero_result_cause:"No tables used"));
else
{
- result->send_fields(fields_list,1);
+ result->send_fields(fields_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
/*
We have to test for 'conds' here as the WHERE may not be constant
even if we don't have any tables for prepared statements or if
@@ -1107,12 +1234,11 @@ JOIN::exec()
if (zero_result_cause)
{
- (void) return_zero_rows(this, result, tables_list, fields_list,
+ (void) return_zero_rows(this, result, select_lex->leaf_tables, fields_list,
send_row_on_empty_set(),
select_options,
zero_result_cause,
- having, procedure,
- unit);
+ having);
DBUG_VOID_RETURN;
}
@@ -1151,16 +1277,30 @@ JOIN::exec()
List<Item> *curr_fields_list= &fields_list;
TABLE *curr_tmp_table= 0;
+ if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
+ get_schema_tables_result(curr_join))
+ {
+ DBUG_VOID_RETURN;
+ }
+
/* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp)
{
if (tmp_join)
+ {
+ /*
+ We are in a non cacheable sub query. Get the saved join structure
+ after optimization.
+ (curr_join may have been modified during last exection and we need
+ to reset it)
+ */
curr_join= tmp_join;
+ }
curr_tmp_table= exec_tmp_table1;
/* Copy data to the temporary table */
thd->proc_info= "Copying to tmp table";
-
+ DBUG_PRINT("info", ("%s", thd->proc_info));
if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
{
error= tmp_error;
@@ -1287,6 +1427,7 @@ JOIN::exec()
}
thd->proc_info="Copying to group table";
+ DBUG_PRINT("info", ("%s", thd->proc_info));
tmp_error= -1;
if (curr_join != this)
{
@@ -1303,17 +1444,18 @@ JOIN::exec()
}
}
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
- 1))
+ 1, TRUE))
DBUG_VOID_RETURN;
curr_join->group_list= 0;
- if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
+ if (setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
+ (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
0)))
{
error= tmp_error;
DBUG_VOID_RETURN;
}
end_read_record(&curr_join->join_tab->read_record);
- curr_join->const_tables= curr_join->tables; // Mark free for join_free()
+ curr_join->const_tables= curr_join->tables; // Mark free for cleanup()
curr_join->join_tab[0].table= 0; // Table is freed
// No sum funcs anymore
@@ -1393,7 +1535,9 @@ JOIN::exec()
curr_join->set_items_ref_array(items3);
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
- 1) || thd->is_fatal_error)
+ 1, TRUE) ||
+ setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
+ thd->is_fatal_error)
DBUG_VOID_RETURN;
}
if (curr_join->group_list || curr_join->order)
@@ -1459,11 +1603,9 @@ JOIN::exec()
/*
table->keyuse is set in the case there was an original WHERE clause
on the table that was optimized away.
- table->on_expr tells us that it was a LEFT JOIN and there will be
- at least one row generated from the table.
*/
if (curr_table->select_cond ||
- (curr_table->keyuse && !curr_table->on_expr))
+ (curr_table->keyuse && !curr_table->first_inner))
{
/* We have to sort all rows */
curr_join->select_limit= HA_POS_ERROR;
@@ -1493,12 +1635,46 @@ JOIN::exec()
DBUG_VOID_RETURN;
}
}
+ /* XXX: When can we have here thd->net.report_error not zero? */
+ if (thd->net.report_error)
+ {
+ error= thd->net.report_error;
+ DBUG_VOID_RETURN;
+ }
curr_join->having= curr_join->tmp_having;
- thd->proc_info="Sending data";
- error= thd->net.report_error ? -1 :
- do_select(curr_join, curr_fields_list, NULL, procedure);
- thd->limit_found_rows= curr_join->send_records;
- thd->examined_row_count= curr_join->examined_rows;
+ curr_join->fields= curr_fields_list;
+ curr_join->procedure= procedure;
+
+ if (is_top_level_join() && thd->cursor && tables != const_tables)
+ {
+ /*
+ We are here if this is JOIN::exec for the last select of the main unit
+ and the client requested to open a cursor.
+ We check that not all tables are constant because this case is not
+ handled by do_select() separately, and this case is not implemented
+ for cursors yet.
+ */
+ DBUG_ASSERT(error == 0);
+ /*
+ curr_join is used only for reusable joins - that is,
+ to perform SELECT for each outer row (like in subselects).
+ This join is main, so we know for sure that curr_join == join.
+ */
+ DBUG_ASSERT(curr_join == this);
+ /* Open cursor for the last join sweep */
+ error= thd->cursor->open(this);
+ }
+ else
+ {
+ thd->proc_info="Sending data";
+ DBUG_PRINT("info", ("%s", thd->proc_info));
+ result->send_fields(*curr_fields_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
+ error= do_select(curr_join, curr_fields_list, NULL, procedure);
+ thd->limit_found_rows= curr_join->send_records;
+ thd->examined_row_count= curr_join->examined_rows;
+ }
+
DBUG_VOID_RETURN;
}
@@ -1508,9 +1684,9 @@ JOIN::exec()
*/
int
-JOIN::cleanup()
+JOIN::destroy()
{
- DBUG_ENTER("JOIN::cleanup");
+ DBUG_ENTER("JOIN::destroy");
select_lex->join= 0;
if (tmp_join)
@@ -1525,11 +1701,11 @@ JOIN::cleanup()
}
tmp_join->tmp_join= 0;
tmp_table_param.copy_field=0;
- DBUG_RETURN(tmp_join->cleanup());
+ DBUG_RETURN(tmp_join->destroy());
}
+ cond_equal= 0;
- lock=0; // It's faster to unlock later
- join_free(1);
+ cleanup(1);
if (exec_tmp_table1)
free_tmp_table(thd, exec_tmp_table1);
if (exec_tmp_table2)
@@ -1537,17 +1713,311 @@ JOIN::cleanup()
delete select;
delete_dynamic(&keyuse);
delete procedure;
- for (SELECT_LEX_UNIT *lex_unit= select_lex->first_inner_unit();
- lex_unit != 0;
- lex_unit= lex_unit->next_unit())
+ DBUG_RETURN(error);
+}
+
+
+/************************* Cursor ******************************************/
+
+Cursor::Cursor(THD *thd)
+ :Query_arena(&main_mem_root, INITIALIZED),
+ join(0), unit(0),
+ protocol(thd),
+ close_at_commit(FALSE)
+{
+ /* We will overwrite it at open anyway. */
+ init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+ thr_lock_owner_init(&lock_id, &thd->lock_info);
+ bzero((void*) ht_info, sizeof(ht_info));
+}
+
+
+void
+Cursor::init_from_thd(THD *thd)
+{
+ Engine_info *info;
+ /*
+ We need to save and reset thd->mem_root, otherwise it'll be freed
+ later in mysql_parse.
+
+ We can't just change the thd->mem_root here as we want to keep the
+ things that are already allocated in thd->mem_root for Cursor::fetch()
+ */
+ main_mem_root= *thd->mem_root;
+ state= thd->stmt_arena->state;
+ /* Allocate new memory root for thd */
+ init_sql_alloc(thd->mem_root,
+ thd->variables.query_alloc_block_size,
+ thd->variables.query_prealloc_size);
+
+ /*
+ The same is true for open tables and lock: save tables and zero THD
+ pointers to prevent table close in close_thread_tables (This is a part
+ of the temporary solution to make cursors work with minimal changes to
+ the current source base).
+ */
+ derived_tables= thd->derived_tables;
+ open_tables= thd->open_tables;
+ lock= thd->lock;
+ query_id= thd->query_id;
+ free_list= thd->free_list;
+ change_list= thd->change_list;
+ reset_thd(thd);
+ /* Now we have an active cursor and can cause a deadlock */
+ thd->lock_info.n_cursors++;
+
+ close_at_commit= FALSE; /* reset in case we're reusing the cursor */
+ info= &ht_info[0];
+ for (handlerton **pht= thd->transaction.stmt.ht; *pht; pht++)
{
- error|= lex_unit->cleanup();
+ const handlerton *ht= *pht;
+ close_at_commit|= test(ht->flags & HTON_CLOSE_CURSORS_AT_COMMIT);
+ if (ht->create_cursor_read_view)
+ {
+ info->ht= ht;
+ info->read_view= (ht->create_cursor_read_view)();
+ ++info;
+ }
}
- DBUG_RETURN(error);
+ /*
+ XXX: thd->locked_tables is not changed.
+ What problems can we have with it if cursor is open?
+ TODO: must be fixed because of the prelocked mode.
+ */
+}
+
+
+void
+Cursor::reset_thd(THD *thd)
+{
+ thd->derived_tables= 0;
+ thd->open_tables= 0;
+ thd->lock= 0;
+ thd->free_list= 0;
+ thd->change_list.empty();
}
int
+Cursor::open(JOIN *join_arg)
+{
+ join= join_arg;
+ THD *thd= join->thd;
+ /* First non-constant table */
+ JOIN_TAB *join_tab= join->join_tab + join->const_tables;
+ DBUG_ENTER("Cursor::open");
+
+ /*
+ Send fields description to the client; server_status is sent
+ in 'EOF' packet, which ends send_fields().
+ */
+ thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
+ join->result->send_fields(*join->fields, Protocol::SEND_NUM_ROWS);
+ ::send_eof(thd);
+ thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
+
+ /* Prepare JOIN for reading rows. */
+ join->tmp_table= 0;
+ join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
+ join->send_records= 0;
+ join->fetch_limit= join->unit->offset_limit_cnt;
+
+ /* Disable JOIN CACHE as it is not working with cursors yet */
+ for (JOIN_TAB *tab= join_tab;
+ tab != join->join_tab + join->tables - 1;
+ tab++)
+ {
+ if (tab->next_select == sub_select_cache)
+ tab->next_select= sub_select;
+ }
+
+ DBUG_ASSERT(join_tab->table->reginfo.not_exists_optimize == 0);
+ DBUG_ASSERT(join_tab->not_used_in_distinct == 0);
+ /*
+ null_row is set only if row not found and it's outer join: should never
+ happen for the first table in join_tab list
+ */
+ DBUG_ASSERT(join_tab->table->null_row == 0);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ DESCRIPTION
+ Fetch next num_rows rows from the cursor and sent them to the client
+ PRECONDITION:
+ Cursor is open
+ RETURN VALUES:
+ none, this function will send error or OK to network if necessary.
+*/
+
+void
+Cursor::fetch(ulong num_rows)
+{
+ THD *thd= join->thd;
+ JOIN_TAB *join_tab= join->join_tab + join->const_tables;
+ enum_nested_loop_state error= NESTED_LOOP_OK;
+ Query_arena backup_arena;
+ Engine_info *info;
+ DBUG_ENTER("Cursor::fetch");
+ DBUG_PRINT("enter",("rows: %lu", num_rows));
+
+ DBUG_ASSERT(thd->derived_tables == 0 && thd->open_tables == 0 &&
+ thd->lock == 0);
+
+ thd->derived_tables= derived_tables;
+ thd->open_tables= open_tables;
+ thd->lock= lock;
+ thd->query_id= query_id;
+ thd->change_list= change_list;
+ /* save references to memory, allocated during fetch */
+ thd->set_n_backup_active_arena(this, &backup_arena);
+
+ for (info= ht_info; info->read_view ; info++)
+ (info->ht->set_cursor_read_view)(info->read_view);
+
+ join->fetch_limit+= num_rows;
+
+ error= sub_select(join, join_tab, 0);
+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
+ error= sub_select(join,join_tab,1);
+ if (error == NESTED_LOOP_QUERY_LIMIT)
+ error= NESTED_LOOP_OK; /* select_limit used */
+ if (error == NESTED_LOOP_CURSOR_LIMIT)
+ join->resume_nested_loop= TRUE;
+
+#ifdef USING_TRANSACTIONS
+ ha_release_temporary_latches(thd);
+#endif
+ /* Grab free_list here to correctly free it in close */
+ thd->restore_active_arena(this, &backup_arena);
+
+ for (info= ht_info; info->read_view; info++)
+ (info->ht->set_cursor_read_view)(0);
+
+ if (error == NESTED_LOOP_CURSOR_LIMIT)
+ {
+ /* Fetch limit worked, possibly more rows are there */
+ thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
+ ::send_eof(thd);
+ thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
+ change_list= thd->change_list;
+ reset_thd(thd);
+ }
+ else
+ {
+ close(TRUE);
+ if (error == NESTED_LOOP_OK)
+ {
+ thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
+ ::send_eof(thd);
+ thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
+ }
+ else if (error != NESTED_LOOP_KILLED)
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void
+Cursor::close(bool is_active)
+{
+ THD *thd= join->thd;
+ DBUG_ENTER("Cursor::close");
+
+ /*
+ In case of UNIONs JOIN is freed inside of unit->cleanup(),
+ otherwise in select_lex->cleanup().
+ */
+ if (unit)
+ (void) unit->cleanup();
+ else
+ (void) join->select_lex->cleanup();
+
+ for (Engine_info *info= ht_info; info->read_view; info++)
+ {
+ (info->ht->close_cursor_read_view)(info->read_view);
+ info->read_view= 0;
+ info->ht= 0;
+ }
+
+ if (is_active)
+ close_thread_tables(thd);
+ else
+ {
+ /* XXX: Another hack: closing tables used in the cursor */
+ DBUG_ASSERT(lock || open_tables || derived_tables);
+
+ TABLE *tmp_derived_tables= thd->derived_tables;
+ MYSQL_LOCK *tmp_lock= thd->lock;
+
+ thd->open_tables= open_tables;
+ thd->derived_tables= derived_tables;
+ thd->lock= lock;
+ close_thread_tables(thd);
+
+ thd->open_tables= tmp_derived_tables;
+ thd->derived_tables= tmp_derived_tables;
+ thd->lock= tmp_lock;
+ }
+ thd->lock_info.n_cursors--; /* Decrease the number of active cursors */
+ join= 0;
+ unit= 0;
+ free_items();
+ change_list.empty();
+ DBUG_VOID_RETURN;
+}
+
+
+/*********************************************************************/
+
+/*
+ An entry point to single-unit select (a select without UNION).
+
+ SYNOPSIS
+ mysql_select()
+
+ thd thread handler
+ rref_pointer_array a reference to ref_pointer_array of
+ the top-level select_lex for this query
+ tables list of all tables used in this query.
+ The tables have been pre-opened.
+ wild_num number of wildcards used in the top level
+ select of this query.
+ For example statement
+ SELECT *, t1.*, catalog.t2.* FROM t0, t1, t2;
+ has 3 wildcards.
+ fields list of items in SELECT list of the top-level
+ select
+ e.g. SELECT a, b, c FROM t1 will have Item_field
+ for a, b and c in this list.
+ conds top level item of an expression representing
+ WHERE clause of the top level select
+ og_num total number of ORDER BY and GROUP BY clauses
+ arguments
+ order linked list of ORDER BY agruments
+ group linked list of GROUP BY arguments
+ having top level item of HAVING expression
+ proc_param list of PROCEDUREs
+ select_options select options (BIG_RESULT, etc)
+ result an instance of result set handling class.
+ This object is responsible for send result
+ set rows to the client or inserting them
+ into a table.
+ select_lex the only SELECT_LEX of this query
+ unit top-level UNIT of this query
+ UNIT is an artificial object created by the parser
+ for every SELECT clause.
+ e.g. SELECT * FROM t1 WHERE a1 IN (SELECT * FROM t2)
+ has 2 unions.
+
+ RETURN VALUE
+ FALSE success
+ TRUE an error
+*/
+
+bool
mysql_select(THD *thd, Item ***rref_pointer_array,
TABLE_LIST *tables, uint wild_num, List<Item> &fields,
COND *conds, uint og_num, ORDER *order, ORDER *group,
@@ -1555,15 +2025,19 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex)
{
- int err;
+ bool err;
bool free_join= 1;
DBUG_ENTER("mysql_select");
+ select_lex->context.resolve_in_select_list= TRUE;
JOIN *join;
if (select_lex->join != 0)
{
join= select_lex->join;
- // is it single SELECT in derived table, called in derived table creation
+ /*
+ is it single SELECT in derived table, called in derived table
+ creation
+ */
if (select_lex->linkage != DERIVED_TABLE_TYPE ||
(select_options & SELECT_DESCRIBE))
{
@@ -1572,7 +2046,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
//here is EXPLAIN of subselect or derived table
if (join->change_result(result))
{
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
else
@@ -1591,7 +2065,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
else
{
if (!(join= new JOIN(thd, fields, select_options, result)))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
if (join->prepare(rref_pointer_array, tables, wild_num,
@@ -1618,6 +2092,16 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
join->exec();
+ if (thd->cursor && thd->cursor->is_open())
+ {
+ /*
+ A cursor was opened for the last sweep in exec().
+ We are here only if this is mysql_select for top-level SELECT_LEX_UNIT
+ and there were no error.
+ */
+ free_join= 0;
+ }
+
if (thd->lex->describe & DESCRIBE_EXTENDED)
{
select_lex->where= join->conds_history;
@@ -1628,11 +2112,8 @@ err:
if (free_join)
{
thd->proc_info="end";
- err= join->cleanup();
- if (thd->net.report_error)
- err= -1;
- delete join;
- DBUG_RETURN(err);
+ err= select_lex->cleanup();
+ DBUG_RETURN(err || thd->net.report_error);
}
DBUG_RETURN(join->error);
}
@@ -1675,10 +2156,11 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
*/
static bool
-make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
+make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
DYNAMIC_ARRAY *keyuse_array)
{
int error;
+ TABLE *table;
uint i,table_count,const_count,key;
table_map found_const_table_map, all_table_map, found_ref, refs;
key_map const_ref, eq_part;
@@ -1702,47 +2184,60 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
found_const_table_map= all_table_map=0;
const_count=0;
- for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++)
+ for (s= stat, i= 0;
+ tables;
+ s++, tables= tables->next_leaf, i++)
{
- TABLE *table;
+ TABLE_LIST *embedding= tables->embedding;
stat_vector[i]=s;
s->keys.init();
s->const_keys.init();
s->checked_keys.init();
s->needed_reg.init();
table_vector[i]=s->table=table=tables->table;
+ table->pos_in_table_list= tables;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);// record count
table->quick_keys.clear_all();
table->reginfo.join_tab=s;
table->reginfo.not_exists_optimize=0;
- bzero((char*) table->const_key_parts, sizeof(key_part_map)*table->keys);
+ bzero((char*) table->const_key_parts, sizeof(key_part_map)*table->s->keys);
all_table_map|= table->map;
s->join=join;
s->info=0; // For describe
- if ((s->on_expr=tables->on_expr))
+
+ s->dependent= tables->dep_tables;
+ s->key_dependent= 0;
+ if (tables->schema_table)
+ table->file->records= 2;
+
+ s->on_expr_ref= &tables->on_expr;
+ if (*s->on_expr_ref)
{
- /* Left join */
- if (!table->file->records)
+ /* s is the only inner table of an outer join */
+ if (!table->file->records && !embedding)
{ // Empty table
- s->key_dependent=s->dependent=0; // Ignore LEFT JOIN depend.
+ s->dependent= 0; // Ignore LEFT JOIN depend.
set_position(join,const_count++,s,(KEYUSE*) 0);
continue;
}
- s->key_dependent=s->dependent=
- s->on_expr->used_tables() & ~(table->map);
- if (table->outer_join & JOIN_TYPE_LEFT)
- s->dependent|=stat_vector[i-1]->dependent | table_vector[i-1]->map;
- if (tables->outer_join & JOIN_TYPE_RIGHT)
- s->dependent|=tables->next->table->map;
- outer_join|=table->map;
+ outer_join|= table->map;
continue;
}
- if (tables->straight) // We don't have to move this
- s->dependent= table_vector[i-1]->map | stat_vector[i-1]->dependent;
- else
- s->dependent=(table_map) 0;
- s->key_dependent=(table_map) 0;
- if ((table->system || table->file->records <= 1) && ! s->dependent &&
+ if (embedding)
+ {
+ /* s belongs to a nested join, maybe to several embedded joins */
+ do
+ {
+ NESTED_JOIN *nested_join= embedding->nested_join;
+ s->dependent|= embedding->dep_tables;
+ embedding= embedding->embedding;
+ outer_join|= nested_join->used_tables;
+ }
+ while (embedding);
+ continue;
+ }
+
+ if ((table->s->system || table->file->records <= 1) && ! s->dependent &&
!(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
!table->fulltext_searched)
{
@@ -1752,45 +2247,44 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
stat_vector[i]=0;
join->outer_join=outer_join;
- /*
- If outer join: Re-arrange tables in stat_vector so that outer join
- tables are after all tables it is dependent of.
- For example: SELECT * from A LEFT JOIN B ON B.c=C.c, C WHERE A.C=C.C
- Will shift table B after table C.
- */
- if (outer_join)
+ if (join->outer_join)
{
- table_map used_tables=0L;
- for (i=0 ; i < join->tables-1 ; i++)
+ /*
+ Build transitive closure for relation 'to be dependent on'.
+ This will speed up the plan search for many cases with outer joins,
+ as well as allow us to catch illegal cross references/
+ Warshall's algorithm is used to build the transitive closure.
+ As we use bitmaps to represent the relation the complexity
+ of the algorithm is O((number of tables)^2).
+ */
+ for (i= 0, s= stat ; i < table_count ; i++, s++)
{
- if (stat_vector[i]->dependent & ~used_tables)
+ for (uint j= 0 ; j < table_count ; j++)
{
- JOIN_TAB *save= stat_vector[i];
- uint j;
- for (j=i+1;
- j < join->tables && stat_vector[j]->dependent & ~used_tables;
- j++)
- {
- JOIN_TAB *tmp=stat_vector[j]; // Move element up
- stat_vector[j]=save;
- save=tmp;
- }
- if (j == join->tables)
- {
- join->tables=0; // Don't use join->table
- my_error(ER_WRONG_OUTER_JOIN,MYF(0));
- DBUG_RETURN(1);
- }
- stat_vector[i]=stat_vector[j];
- stat_vector[j]=save;
+ table= stat[j].table;
+ if (s->dependent & table->map)
+ s->dependent |= table->reginfo.join_tab->dependent;
}
- used_tables|= stat_vector[i]->table->map;
+ if (s->dependent)
+ s->table->maybe_null= 1;
+ }
+ /* Catch illegal cross references for outer joins */
+ for (i= 0, s= stat ; i < table_count ; i++, s++)
+ {
+ if (s->dependent & s->table->map)
+ {
+ join->tables=0; // Don't use join->table
+ my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
+ DBUG_RETURN(1);
+ }
+ s->key_dependent= s->dependent;
}
}
if (conds || outer_join)
if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
- conds, ~outer_join, join->select_lex))
+ conds, join->cond_equal,
+ ~outer_join, join->select_lex))
DBUG_RETURN(1);
/* Read tables with 0 or 1 rows (system tables) */
@@ -1827,14 +2321,15 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
for (JOIN_TAB **pos=stat_vector+const_count ; (s= *pos) ; pos++)
{
- TABLE *table=s->table;
+ table=s->table;
if (s->dependent) // If dependent on some table
{
// All dep. must be constants
if (s->dependent & ~(found_const_table_map))
continue;
if (table->file->records <= 1L &&
- !(table->file->table_flags() & HA_NOT_EXACT_COUNT))
+ !(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
+ !table->pos_in_table_list->embedding)
{ // system table
int tmp= 0;
s->type=JT_SYSTEM;
@@ -1933,14 +2428,23 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
if (s->worst_seeks < 2.0) // Fix for small tables
s->worst_seeks=2.0;
- if (! s->const_keys.is_clear_all())
+ /*
+ Add to stat->const_keys those indexes for which all group fields or
+ all select distinct fields participate in one index.
+ */
+ add_group_and_distinct_keys(join, s);
+
+ if (!s->const_keys.is_clear_all() &&
+ !s->table->pos_in_table_list->embedding)
{
ha_rows records;
SQL_SELECT *select;
select= make_select(s->table, found_const_table_map,
found_const_table_map,
- s->on_expr ? s->on_expr : conds,
- &error);
+ *s->on_expr_ref ? *s->on_expr_ref : conds,
+ 1, &error);
+ if (!select)
+ DBUG_RETURN(1);
records= get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit);
s->quick=select->quick;
@@ -1957,7 +2461,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->const_table_map|= s->table->map;
set_position(join,const_count++,s,(KEYUSE*) 0);
s->type= JT_CONST;
- if (s->on_expr)
+ if (*s->on_expr_ref)
{
/* Generate empty row */
s->info= "Impossible ON condition";
@@ -1975,17 +2479,17 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
}
}
- /* Find best combination and return it */
join->join_tab=stat;
join->map2table=stat_ref;
join->table= join->all_tables=table_vector;
join->const_tables=const_count;
join->found_const_table_map=found_const_table_map;
+ /* Find an optimal join order of the non-constant tables. */
if (join->const_tables != join->tables)
{
optimize_keyuse(join, keyuse_array);
- find_best_combination(join,all_table_map & ~join->const_table_map);
+ choose_plan(join, all_table_map & ~join->const_table_map);
}
else
{
@@ -1993,6 +2497,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
sizeof(POSITION)*join->const_tables);
join->best_read=1.0;
}
+ /* Generate an execution plan from the found optimal join order. */
DBUG_RETURN(join->thd->killed || get_best_combination(join));
}
@@ -2137,6 +2642,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
add_key_field()
key_fields Pointer to add key, if usable
and_level And level, to be stored in KEY_FIELD
+ cond Condition predicate
field Field used in comparision
eq_func True if we used =, <=> or IS NULL
value Value used for comparison with field
@@ -2153,7 +2659,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
static void
add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
- Field *field,bool eq_func,Item **value, uint num_values,
+ Field *field, bool eq_func, Item **value, uint num_values,
table_map usable_tables)
{
uint exists_optimize= 0;
@@ -2229,7 +2735,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
We can't use indexes if the effective collation
of the operation differ from the field collation.
- We can also not used index on a text column, as the column may
+ We also cannot use index on a text column, as the column may
contain 'x' 'x\t' 'x ' and 'read_next_same' will stop after
'x' when searching for WHERE col='x '
*/
@@ -2262,21 +2768,62 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
'othertbl.field IS NOT NULL' to tab->select_cond.
*/
(*key_fields)->null_rejecting= ((cond->functype() == Item_func::EQ_FUNC) &&
- ((*value)->type() == Item::FIELD_ITEM) &&
+ ((*value)->type() == Item::FIELD_ITEM) &&
((Item_field*)*value)->field->maybe_null());
(*key_fields)++;
}
/*
- SYNOPSIS
- add_key_fields()
- key_fields Add KEY_FIELD entries to this array (and move the
- pointer)
- and_level AND-level (a value that is different for every n-way
- AND operation)
- cond Condition to analyze
- usable_tables Value to pass to add_key_field
+ Add possible keys to array of possible keys originated from a simple predicate
+
+ SYNPOSIS
+ add_key_equal_fields()
+ key_fields Pointer to add key, if usable
+ and_level And level, to be stored in KEY_FIELD
+ cond Condition predicate
+ field Field used in comparision
+ eq_func True if we used =, <=> or IS NULL
+ value Value used for comparison with field
+ Is NULL for BETWEEN and IN
+ usable_tables Tables which can be used for key optimization
+
+ NOTES
+ If field items f1 and f2 belong to the same multiple equality and
+ a key is added for f1, the the same key is added for f2.
+
+ RETURN
+ *key_fields is incremented if we stored a key in the array
*/
+
+static void
+add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
+ Item_func *cond, Item_field *field_item,
+ bool eq_func, Item **val,
+ uint num_values, table_map usable_tables)
+{
+ Field *field= field_item->field;
+ add_key_field(key_fields, and_level, cond, field,
+ eq_func, val, num_values, usable_tables);
+ Item_equal *item_equal= field_item->item_equal;
+ if (item_equal)
+ {
+ /*
+ Add to the set of possible key values every substitution of
+ the field for an equal field included into item_equal
+ */
+ Item_equal_iterator it(*item_equal);
+ Item_field *item;
+ while ((item= it++))
+ {
+ if (!field->eq(item->field))
+ {
+ add_key_field(key_fields, and_level, cond, item->field,
+ eq_func, val, num_values, usable_tables);
+ }
+ }
+ }
+}
+
static void
add_key_fields(KEY_FIELD **key_fields,uint *and_level,
COND *cond, table_map usable_tables)
@@ -2319,16 +2866,26 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
case Item_func::OPTIMIZE_NONE:
break;
case Item_func::OPTIMIZE_KEY:
- // BETWEEN, IN, NOT
+ {
+ // BETWEEN, IN, NE
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,
- cond_func->argument_count() == 2 &&
- cond_func->functype() == Item_func::IN_FUNC,
- cond_func->arguments()+1, cond_func->argument_count()-1,
- usable_tables);
+ {
+ Item **values= cond_func->arguments()+1;
+ if (cond_func->functype() == Item_func::NE_FUNC &&
+ cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
+ !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
+ values--;
+ DBUG_ASSERT(cond_func->functype() != Item_func::IN_FUNC ||
+ cond_func->argument_count() != 2);
+ add_key_equal_fields(key_fields, *and_level, cond_func,
+ (Item_field*) (cond_func->key_item()->real_item()),
+ 0, values,
+ cond_func->argument_count()-1,
+ usable_tables);
+ }
break;
+ }
case Item_func::OPTIMIZE_OP:
{
bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC ||
@@ -2337,21 +2894,19 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
{
- add_key_field(key_fields,*and_level,cond_func,
- ((Item_field*) (cond_func->arguments()[0])->real_item())
- ->field,
- equal_func,
- cond_func->arguments()+1, 1, usable_tables);
+ add_key_equal_fields(key_fields, *and_level, cond_func,
+ (Item_field*) (cond_func->arguments()[0])->real_item(),
+ equal_func,
+ cond_func->arguments()+1, 1, usable_tables);
}
if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
cond_func->functype() != Item_func::LIKE_FUNC &&
!(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
{
- add_key_field(key_fields,*and_level,cond_func,
- ((Item_field*) (cond_func->arguments()[1])->real_item())
- ->field,
- equal_func,
- cond_func->arguments(),1,usable_tables);
+ add_key_equal_fields(key_fields, *and_level, cond_func,
+ (Item_field*) (cond_func->arguments()[1])->real_item(),
+ equal_func,
+ cond_func->arguments(),1,usable_tables);
}
break;
}
@@ -2363,15 +2918,55 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
Item *tmp=new Item_null;
if (unlikely(!tmp)) // Should never be true
return;
- add_key_field(key_fields,*and_level,cond_func,
- ((Item_field*) (cond_func->arguments()[0])->real_item())
- ->field,
+ add_key_equal_fields(key_fields, *and_level, cond_func,
+ (Item_field*) (cond_func->arguments()[0])->real_item(),
cond_func->functype() == Item_func::ISNULL_FUNC,
&tmp, 1, usable_tables);
}
break;
+ case Item_func::OPTIMIZE_EQUAL:
+ Item_equal *item_equal= (Item_equal *) cond;
+ Item *const_item= item_equal->get_const();
+ Item_equal_iterator it(*item_equal);
+ Item_field *item;
+ if (const_item)
+ {
+ /*
+ For each field field1 from item_equal consider the equality
+ field1=const_item as a condition allowing an index access of the table
+ with field1 by the keys value of field1.
+ */
+ while ((item= it++))
+ {
+ add_key_field(key_fields, *and_level, cond_func, item->field,
+ TRUE, &const_item, 1, usable_tables);
+ }
+ }
+ else
+ {
+ /*
+ Consider all pairs of different fields included into item_equal.
+ For each of them (field1, field1) consider the equality
+ field1=field2 as a condition allowing an index access of the table
+ with field1 by the keys value of field2.
+ */
+ Item_equal_iterator fi(*item_equal);
+ while ((item= fi++))
+ {
+ Field *field= item->field;
+ while ((item= it++))
+ {
+ if (!field->eq(item->field))
+ {
+ add_key_field(key_fields, *and_level, cond_func, field,
+ TRUE, (Item **) &item, 1, usable_tables);
+ }
+ }
+ it.rewind();
+ }
+ }
+ break;
}
- return;
}
/*
@@ -2396,7 +2991,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
if (key_field->eq_func && !(key_field->optimize & KEY_OPTIMIZE_EXISTS))
{
- for (uint key=0 ; key < form->keys ; key++)
+ for (uint key=0 ; key < form->s->keys ; key++)
{
if (!(form->keys_in_use_for_query.is_set(key)))
continue;
@@ -2446,14 +3041,14 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
Item_func *arg0=(Item_func *)(func->arguments()[0]),
*arg1=(Item_func *)(func->arguments()[1]);
if (arg1->const_item() &&
- ((functype == Item_func::GE_FUNC && arg1->val()> 0) ||
- (functype == Item_func::GT_FUNC && arg1->val()>=0)) &&
+ ((functype == Item_func::GE_FUNC && arg1->val_real() > 0) ||
+ (functype == Item_func::GT_FUNC && arg1->val_real() >=0)) &&
arg0->type() == Item::FUNC_ITEM &&
arg0->functype() == Item_func::FT_FUNC)
cond_func=(Item_func_match *) arg0;
else if (arg0->const_item() &&
- ((functype == Item_func::LE_FUNC && arg0->val()> 0) ||
- (functype == Item_func::LT_FUNC && arg0->val()>=0)) &&
+ ((functype == Item_func::LE_FUNC && arg0->val_real() > 0) ||
+ (functype == Item_func::LT_FUNC && arg0->val_real() >=0)) &&
arg1->type() == Item::FUNC_ITEM &&
arg1->functype() == Item_func::FT_FUNC)
cond_func=(Item_func_match *) arg1;
@@ -2529,15 +3124,19 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
static bool
update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
- uint tables, COND *cond, table_map normal_tables,
- SELECT_LEX *select_lex)
+ uint tables, COND *cond, COND_EQUAL *cond_equal,
+ table_map normal_tables, SELECT_LEX *select_lex)
{
uint and_level,i,found_eq_constant;
KEY_FIELD *key_fields, *end, *field;
+ uint m= 1;
+
+ if (cond_equal && cond_equal->max_members)
+ m= cond_equal->max_members;
if (!(key_fields=(KEY_FIELD*)
thd->alloc(sizeof(key_fields[0])*
- (thd->lex->current_select->cond_count+1)*2)))
+ (thd->lex->current_select->cond_count+1)*2*m)))
return TRUE; /* purecov: inspected */
and_level= 0;
field= end= key_fields;
@@ -2557,11 +3156,32 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
}
for (i=0 ; i < tables ; i++)
{
- if (join_tab[i].on_expr)
- {
- add_key_fields(&end,&and_level,join_tab[i].on_expr,
+ /*
+ Block the creation of keys for inner tables of outer joins.
+ Here only the outer joins that can not be converted to
+ inner joins are left and all nests that can be eliminated
+ are flattened.
+ In the future when we introduce conditional accesses
+ for inner tables in outer joins these keys will be taken
+ into account as well.
+ */
+ if (*join_tab[i].on_expr_ref)
+ {
+ add_key_fields(&end,&and_level,*join_tab[i].on_expr_ref,
join_tab[i].table->map);
}
+ else
+ {
+ TABLE_LIST *tab= join_tab[i].table->pos_in_table_list;
+ TABLE_LIST *embedding= tab->embedding;
+ if (embedding)
+ {
+ NESTED_JOIN *nested_join= embedding->nested_join;
+ if (nested_join->join_list.head() == tab)
+ add_key_fields(&end, &and_level, embedding->on_expr,
+ nested_join->used_tables);
+ }
+ }
}
/* fill keyuse with found key parts */
for ( ; field != end ; field++)
@@ -2573,10 +3193,14 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
}
/*
- Special treatment for ft-keys.
- Remove the following things from KEYUSE:
+ Sort the array of possible keys and remove the following key parts:
- ref if there is a keypart which is a ref and a const.
- - keyparts without previous keyparts.
+ (e.g. if there is a key(a,b) and the clause is a=3 and b=7 and b=t2.d,
+ then we skip the key part corresponding to b=t2.d)
+ - keyparts without previous keyparts
+ (e.g. if there is a key(a,b,c) but only b < 5 (or a=2 and c < 3) is
+ used in the query, we drop the partial key parts from consideration).
+ Special treatment for ft-keys.
*/
if (keyuse->elements)
{
@@ -2624,7 +3248,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
}
/*
- Update some values in keyuse for faster find_best_combination() loop
+ Update some values in keyuse for faster choose_plan() loop
*/
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
@@ -2665,6 +3289,68 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
}
+/*
+ Discover the indexes that can be used for GROUP BY or DISTINCT queries.
+
+ SYNOPSIS
+ add_group_and_distinct_keys()
+ join
+ join_tab
+
+ DESCRIPTION
+ If the query has a GROUP BY clause, find all indexes that contain all
+ GROUP BY fields, and add those indexes to join->const_keys.
+ If the query has a DISTINCT clause, find all indexes that contain all
+ SELECT fields, and add those indexes to join->const_keys.
+ This allows later on such queries to be processed by a
+ QUICK_GROUP_MIN_MAX_SELECT.
+
+ RETURN
+ None
+*/
+
+static void
+add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
+{
+ List<Item_field> indexed_fields;
+ List_iterator<Item_field> indexed_fields_it(indexed_fields);
+ ORDER *cur_group;
+ Item_field *cur_item;
+ key_map possible_keys(0);
+
+ if (join->group_list)
+ { /* Collect all query fields referenced in the GROUP clause. */
+ for (cur_group= join->group_list; cur_group; cur_group= cur_group->next)
+ (*cur_group->item)->walk(&Item::collect_item_field_processor,
+ (byte*) &indexed_fields);
+ }
+ else if (join->select_distinct)
+ { /* Collect all query fields referenced in the SELECT clause. */
+ List<Item> &select_items= join->fields_list;
+ List_iterator<Item> select_items_it(select_items);
+ Item *item;
+ while ((item= select_items_it++))
+ item->walk(&Item::collect_item_field_processor, (byte*) &indexed_fields);
+ }
+ else
+ return;
+
+ if (indexed_fields.elements == 0)
+ return;
+
+ /* Intersect the keys of all group fields. */
+ cur_item= indexed_fields_it++;
+ possible_keys.merge(cur_item->field->part_of_key);
+ while ((cur_item= indexed_fields_it++))
+ {
+ possible_keys.intersect(cur_item->field->part_of_key);
+ }
+
+ if (!possible_keys.is_clear_all())
+ join_tab->const_keys.merge(possible_keys);
+}
+
+
/*****************************************************************************
Go through all combinations of not marked tables and find the one
which uses least records
@@ -2692,16 +3378,983 @@ set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
}
+/*
+ Find the best access path for an extension of a partial execution plan and
+ add this path to the plan.
+
+ SYNOPSIS
+ best_access_path()
+ join pointer to the structure providing all context info
+ for the query
+ s the table to be joined by the function
+ thd thread for the connection that submitted the query
+ remaining_tables set of tables not included into the partial plan yet
+ idx the length of the partial plan
+ record_count estimate for the number of records returned by the partial
+ plan
+ read_time the cost of the partial plan
+
+ DESCRIPTION
+ The function finds the best access path to table 's' from the passed
+ partial plan where an access path is the general term for any means to
+ access the data in 's'. An access path may use either an index or a scan,
+ whichever is cheaper. The input partial plan is passed via the array
+ 'join->positions' of length 'idx'. The chosen access method for 's' and its
+ cost are stored in 'join->positions[idx]'.
+
+ RETURN
+ None
+*/
+
static void
-find_best_combination(JOIN *join, table_map rest_tables)
+best_access_path(JOIN *join,
+ JOIN_TAB *s,
+ THD *thd,
+ table_map remaining_tables,
+ uint idx,
+ double record_count,
+ double read_time)
+{
+ KEYUSE *best_key= 0;
+ uint best_max_key_part= 0;
+ my_bool found_constraint= 0;
+ double best= DBL_MAX;
+ double best_time= DBL_MAX;
+ double records= DBL_MAX;
+ double tmp;
+ ha_rows rec;
+
+ DBUG_ENTER("best_access_path");
+
+ if (s->keyuse)
+ { /* Use key if possible */
+ TABLE *table= s->table;
+ KEYUSE *keyuse,*start_key=0;
+ double best_records= DBL_MAX;
+ uint max_key_part=0;
+
+ /* Test how we can use keys */
+ rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; // Assumed records/key
+ for (keyuse=s->keyuse ; keyuse->table == table ;)
+ {
+ key_part_map found_part= 0;
+ table_map found_ref= 0;
+ uint found_ref_or_null= 0;
+ uint key= keyuse->key;
+ KEY *keyinfo= table->key_info+key;
+ bool ft_key= (keyuse->keypart == FT_KEYPART);
+
+ /* Calculate how many key segments of the current key we can use */
+ start_key= keyuse;
+ do
+ { /* for each keypart */
+ uint keypart= keyuse->keypart;
+ uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL;
+ do
+ {
+ if (!(remaining_tables & keyuse->used_tables) &&
+ !(found_ref_or_null & keyuse->optimize))
+ {
+ found_part|= keyuse->keypart_map;
+ found_ref|= keyuse->used_tables;
+ if (rec > keyuse->ref_table_rows)
+ rec= keyuse->ref_table_rows;
+ found_part_ref_or_null&= keyuse->optimize;
+ }
+ keyuse++;
+ found_ref_or_null|= found_part_ref_or_null;
+ } while (keyuse->table == table && keyuse->key == key &&
+ keyuse->keypart == keypart);
+ } while (keyuse->table == table && keyuse->key == key);
+
+ /*
+ Assume that that each key matches a proportional part of table.
+ */
+ if (!found_part && !ft_key)
+ continue; // Nothing usable found
+
+ if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
+ rec= MATCHING_ROWS_IN_OTHER_TABLE; // Fix for small tables
+
+ /*
+ ft-keys require special treatment
+ */
+ if (ft_key)
+ {
+ /*
+ Really, there should be records=0.0 (yes!)
+ but 1.0 would be probably safer
+ */
+ tmp= prev_record_reads(join, found_ref);
+ records= 1.0;
+ }
+ else
+ {
+ found_constraint= 1;
+ /*
+ Check if we found full key
+ */
+ if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
+ !found_ref_or_null)
+ { /* use eq key */
+ max_key_part= (uint) ~0;
+ if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
+ {
+ tmp = prev_record_reads(join, found_ref);
+ records=1.0;
+ }
+ else
+ {
+ if (!found_ref)
+ { /* We found a const key */
+ if (table->quick_keys.is_set(key))
+ records= (double) table->quick_rows[key];
+ else
+ {
+ /* quick_range couldn't use key! */
+ records= (double) s->records/rec;
+ }
+ }
+ else
+ {
+ if (!(records=keyinfo->rec_per_key[keyinfo->key_parts-1]))
+ { /* Prefer longer keys */
+ records=
+ ((double) s->records / (double) rec *
+ (1.0 +
+ ((double) (table->s->max_key_length-keyinfo->key_length) /
+ (double) table->s->max_key_length)));
+ if (records < 2.0)
+ records=2.0; /* Can't be as good as a unique */
+ }
+ }
+ /* Limit the number of matched rows */
+ tmp = records;
+ set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
+ if (table->used_keys.is_set(key))
+ {
+ /* we can use only index tree */
+ uint keys_per_block= table->file->block_size/2/
+ (keyinfo->key_length+table->file->ref_length)+1;
+ tmp = record_count*(tmp+keys_per_block-1)/keys_per_block;
+ }
+ else
+ tmp = record_count*min(tmp,s->worst_seeks);
+ }
+ }
+ else
+ {
+ /*
+ Use as much key-parts as possible and a uniq key is better
+ than a not unique key
+ Set tmp to (previous record count) * (records / combination)
+ */
+ if ((found_part & 1) &&
+ (!(table->file->index_flags(key, 0, 0) & HA_ONLY_WHOLE_INDEX) ||
+ found_part == PREV_BITS(uint,keyinfo->key_parts)))
+ {
+ max_key_part=max_part_bit(found_part);
+ /*
+ Check if quick_range could determinate how many rows we
+ will match
+ */
+ if (table->quick_keys.is_set(key) &&
+ table->quick_key_parts[key] == max_key_part)
+ tmp= records= (double) table->quick_rows[key];
+ else
+ {
+ /* Check if we have statistic about the distribution */
+ if ((records = keyinfo->rec_per_key[max_key_part-1]))
+ tmp = records;
+ else
+ {
+ /*
+ Assume that the first key part matches 1% of the file
+ and that the whole key matches 10 (duplicates) or 1
+ (unique) records.
+ Assume also that more key matches proportionally more
+ records
+ This gives the formula:
+ records = (x * (b-a) + a*c-b)/(c-1)
+
+ b = records matched by whole key
+ a = records matched by first key part (1% of all records?)
+ c = number of key parts in key
+ x = used key parts (1 <= x <= c)
+ */
+ double rec_per_key;
+ if (!(rec_per_key=(double)
+ keyinfo->rec_per_key[keyinfo->key_parts-1]))
+ rec_per_key=(double) s->records/rec+1;
+
+ if (!s->records)
+ tmp = 0;
+ else if (rec_per_key/(double) s->records >= 0.01)
+ tmp = rec_per_key;
+ else
+ {
+ double a=s->records*0.01;
+ if (keyinfo->key_parts > 1)
+ tmp= (max_key_part * (rec_per_key - a) +
+ a*keyinfo->key_parts - rec_per_key)/
+ (keyinfo->key_parts-1);
+ else
+ tmp= a;
+ set_if_bigger(tmp,1.0);
+ }
+ records = (ulong) tmp;
+ }
+ /*
+ If quick_select was used on a part of this key, we know
+ the maximum number of rows that the key can match.
+ */
+ if (table->quick_keys.is_set(key) &&
+ table->quick_key_parts[key] <= max_key_part &&
+ records > (double) table->quick_rows[key])
+ tmp= records= (double) table->quick_rows[key];
+ else if (found_ref_or_null)
+ {
+ /* We need to do two key searches to find key */
+ tmp *= 2.0;
+ records *= 2.0;
+ }
+ }
+ /* Limit the number of matched rows */
+ set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
+ if (table->used_keys.is_set(key))
+ {
+ /* we can use only index tree */
+ uint keys_per_block= table->file->block_size/2/
+ (keyinfo->key_length+table->file->ref_length)+1;
+ tmp = record_count*(tmp+keys_per_block-1)/keys_per_block;
+ }
+ else
+ tmp = record_count*min(tmp,s->worst_seeks);
+ }
+ else
+ tmp = best_time; // Do nothing
+ }
+ } /* not ft_key */
+ if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
+ {
+ best_time= tmp + records/(double) TIME_FOR_COMPARE;
+ best= tmp;
+ best_records= records;
+ best_key= start_key;
+ best_max_key_part= max_key_part;
+ }
+ }
+ records= best_records;
+ }
+
+ /*
+ Don't test table scan if it can't be better.
+ Prefer key lookup if we would use the same key for scanning.
+
+ Don't do a table scan on InnoDB tables, if we can read the used
+ parts of the row from any of the used index.
+ This is because table scans uses index and we would not win
+ anything by using a table scan.
+ */
+ if ((records >= s->found_records || best > s->read_time) &&
+ !(s->quick && best_key && s->quick->index == best_key->key &&
+ best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
+ !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
+ ! s->table->used_keys.is_clear_all() && best_key) &&
+ !(s->table->force_index && best_key))
+ { // Check full join
+ ha_rows rnd_records= s->found_records;
+ /*
+ If there is a restriction on the table, assume that 25% of the
+ rows can be skipped on next part.
+ This is to force tables that this table depends on before this
+ table
+ */
+ if (found_constraint)
+ rnd_records-= rnd_records/4;
+
+ /*
+ Range optimizer never proposes a RANGE if it isn't better
+ than FULL: so if RANGE is present, it's always preferred to FULL.
+ Here we estimate its cost.
+ */
+ if (s->quick)
+ {
+ /*
+ For each record we:
+ - read record range through 'quick'
+ - skip rows which does not satisfy WHERE constraints
+ */
+ tmp= record_count *
+ (s->quick->read_time +
+ (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
+ }
+ else
+ {
+ /* Estimate cost of reading table. */
+ tmp= s->table->file->scan_time();
+ if (s->table->map & join->outer_join) // Can't use join cache
+ {
+ /*
+ For each record we have to:
+ - read the whole table record
+ - skip rows which does not satisfy join condition
+ */
+ tmp= record_count *
+ (tmp +
+ (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
+ }
+ else
+ {
+ /* We read the table as many times as join buffer becomes full. */
+ tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
+ record_count /
+ (double) thd->variables.join_buff_size));
+ /*
+ We don't make full cartesian product between rows in the scanned
+ table and existing records because we skip all rows from the
+ scanned table, which does not satisfy join condition when
+ we read the table (see flush_cached_records for details). Here we
+ take into account cost to read and skip these records.
+ */
+ tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+ }
+ }
+
+ /*
+ We estimate the cost of evaluating WHERE clause for found records
+ as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
+ tmp give us total cost of using TABLE SCAN
+ */
+ if (best == DBL_MAX ||
+ (tmp + record_count/(double) TIME_FOR_COMPARE*rnd_records <
+ best + record_count/(double) TIME_FOR_COMPARE*records))
+ {
+ /*
+ If the table has a range (s->quick is set) make_join_select()
+ will ensure that this will be used
+ */
+ best= tmp;
+ records= rows2double(rnd_records);
+ best_key= 0;
+ }
+ }
+
+ /* Update the cost information for the current partial plan */
+ join->positions[idx].records_read= records;
+ join->positions[idx].read_time= best;
+ join->positions[idx].key= best_key;
+ join->positions[idx].table= s;
+
+ if (!best_key &&
+ idx == join->const_tables &&
+ s->table == join->sort_by_table &&
+ join->unit->select_limit_cnt >= records)
+ join->sort_by_table= (TABLE*) 1; // Must use temporary table
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Selects and invokes a search strategy for an optimal query plan.
+
+ SYNOPSIS
+ choose_plan()
+ join pointer to the structure providing all context info for
+ the query
+ join_tables set of the tables in the query
+
+ DESCRIPTION
+ The function checks user-configurable parameters that control the search
+ strategy for an optimal plan, selects the search method and then invokes
+ it. Each specific optimization procedure stores the final optimal plan in
+ the array 'join->best_positions', and the cost of the plan in
+ 'join->best_read'.
+
+ RETURN
+ None
+*/
+
+static void
+choose_plan(JOIN *join, table_map join_tables)
+{
+ uint search_depth= join->thd->variables.optimizer_search_depth;
+ uint prune_level= join->thd->variables.optimizer_prune_level;
+ bool straight_join= join->select_options & SELECT_STRAIGHT_JOIN;
+ DBUG_ENTER("choose_plan");
+
+ /*
+ if (SELECT_STRAIGHT_JOIN option is set)
+ reorder tables so dependent tables come after tables they depend
+ on, otherwise keep tables in the order they were specified in the query
+ else
+ Apply heuristic: pre-sort all access plans with respect to the number of
+ records accessed.
+ */
+ qsort(join->best_ref + join->const_tables, join->tables - join->const_tables,
+ sizeof(JOIN_TAB*), straight_join?join_tab_cmp_straight:join_tab_cmp);
+
+ if (straight_join)
+ {
+ optimize_straight_join(join, join_tables);
+ }
+ else
+ {
+ if (search_depth == MAX_TABLES+2)
+ { /*
+ TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
+ the greedy version. Will be removed when greedy_search is approved.
+ */
+ join->best_read= DBL_MAX;
+ find_best(join, join_tables, join->const_tables, 1.0, 0.0);
+ }
+ else
+ {
+ if (search_depth == 0)
+ /* Automatically determine a reasonable value for 'search_depth' */
+ search_depth= determine_search_depth(join);
+ greedy_search(join, join_tables, search_depth, prune_level);
+ }
+ }
+
+ /*
+ Store the cost of this query into a user variable
+ Don't update last_query_cost for 'show status' command
+ */
+ if (join->thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
+ join->thd->status_var.last_query_cost= join->best_read;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Compare two JOIN_TAB objects based on the number of accessed records.
+
+ SYNOPSIS
+ join_tab_cmp()
+ ptr1 pointer to first JOIN_TAB object
+ ptr2 pointer to second JOIN_TAB object
+
+ RETURN
+ 1 if first is bigger
+ -1 if second is bigger
+ 0 if equal
+*/
+
+static int
+join_tab_cmp(const void* ptr1, const void* ptr2)
+{
+ JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
+ JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
+
+ if (jt1->dependent & jt2->table->map)
+ return 1;
+ if (jt2->dependent & jt1->table->map)
+ return -1;
+ if (jt1->found_records > jt2->found_records)
+ return 1;
+ if (jt1->found_records < jt2->found_records)
+ return -1;
+ return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
+}
+
+
+/*
+ Same as join_tab_cmp, but for use with SELECT_STRAIGHT_JOIN.
+*/
+
+static int
+join_tab_cmp_straight(const void* ptr1, const void* ptr2)
+{
+ JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
+ JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
+
+ if (jt1->dependent & jt2->table->map)
+ return 1;
+ if (jt2->dependent & jt1->table->map)
+ return -1;
+ return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
+}
+
+/*
+ Heuristic procedure to automatically guess a reasonable degree of
+ exhaustiveness for the greedy search procedure.
+
+ SYNOPSIS
+ determine_search_depth()
+ join pointer to the structure providing all context info for the query
+
+ DESCRIPTION
+ The procedure estimates the optimization time and selects a search depth
+ big enough to result in a near-optimal QEP, that doesn't take too long to
+ find. If the number of tables in the query exceeds some constant, then
+ search_depth is set to this constant.
+
+ NOTES
+ This is an extremely simplistic implementation that serves as a stub for a
+ more advanced analysis of the join. Ideally the search depth should be
+ determined by learning from previous query optimizations, because it will
+ depend on the CPU power (and other factors).
+
+ RETURN
+ A positive integer that specifies the search depth (and thus the
+ exhaustiveness) of the depth-first search algorithm used by
+ 'greedy_search'.
+*/
+
+static uint
+determine_search_depth(JOIN *join)
+{
+ uint table_count= join->tables - join->const_tables;
+ uint search_depth;
+ /* TODO: this value should be determined dynamically, based on statistics: */
+ uint max_tables_for_exhaustive_opt= 7;
+
+ if (table_count <= max_tables_for_exhaustive_opt)
+ search_depth= table_count+1; // use exhaustive for small number of tables
+ else
+ /*
+ TODO: this value could be determined by some mapping of the form:
+ depth : table_count -> [max_tables_for_exhaustive_opt..MAX_EXHAUSTIVE]
+ */
+ search_depth= max_tables_for_exhaustive_opt; // use greedy search
+
+ return search_depth;
+}
+
+
+/*
+ Select the best ways to access the tables in a query without reordering them.
+
+ SYNOPSIS
+ optimize_straight_join()
+ join pointer to the structure providing all context info for
+ the query
+ join_tables set of the tables in the query
+
+ DESCRIPTION
+ Find the best access paths for each query table and compute their costs
+ according to their order in the array 'join->best_ref' (thus without
+ reordering the join tables). The function calls sequentially
+ 'best_access_path' for each table in the query to select the best table
+ access method. The final optimal plan is stored in the array
+ 'join->best_positions', and the corresponding cost in 'join->best_read'.
+
+ NOTES
+ This function can be applied to:
+ - queries with STRAIGHT_JOIN
+ - internally to compute the cost of an arbitrary QEP
+ Thus 'optimize_straight_join' can be used at any stage of the query
+ optimization process to finalize a QEP as it is.
+
+ RETURN
+ None
+*/
+
+static void
+optimize_straight_join(JOIN *join, table_map join_tables)
{
- DBUG_ENTER("find_best_combination");
- join->best_read=DBL_MAX;
- find_best(join,rest_tables, join->const_tables,1.0,0.0);
+ JOIN_TAB *s;
+ uint idx= join->const_tables;
+ double record_count= 1.0;
+ double read_time= 0.0;
+
+ for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
+ {
+ /* Find the best access method from 's' to the current partial plan */
+ best_access_path(join, s, join->thd, join_tables, idx, record_count, read_time);
+ /* compute the cost of the new plan extended with 's' */
+ record_count*= join->positions[idx].records_read;
+ read_time+= join->positions[idx].read_time;
+ join_tables&= ~(s->table->map);
+ ++idx;
+ }
+
+ read_time+= record_count / (double) TIME_FOR_COMPARE;
+ if (join->sort_by_table &&
+ join->sort_by_table != join->positions[join->const_tables].table->table)
+ read_time+= record_count; // We have to make a temp table
+ memcpy((gptr) join->best_positions, (gptr) join->positions,
+ sizeof(POSITION)*idx);
+ join->best_read= read_time;
+}
+
+
+/*
+ Find a good, possibly optimal, query execution plan (QEP) by a greedy search.
+
+ SYNOPSIS
+ join pointer to the structure providing all context info
+ for the query
+ remaining_tables set of tables not included into the partial plan yet
+ search_depth controlls the exhaustiveness of the search
+ prune_level the pruning heuristics that should be applied during
+ search
+
+ DESCRIPTION
+ The search procedure uses a hybrid greedy/exhaustive search with controlled
+ exhaustiveness. The search is performed in N = card(remaining_tables)
+ steps. Each step evaluates how promising is each of the unoptimized tables,
+ selects the most promising table, and extends the current partial QEP with
+ that table. Currenly the most 'promising' table is the one with least
+ expensive extension.
+ There are two extreme cases:
+ 1. When (card(remaining_tables) < search_depth), the estimate finds the best
+ complete continuation of the partial QEP. This continuation can be
+ used directly as a result of the search.
+ 2. When (search_depth == 1) the 'best_extension_by_limited_search'
+ consideres the extension of the current QEP with each of the remaining
+ unoptimized tables.
+ All other cases are in-between these two extremes. Thus the parameter
+ 'search_depth' controlls the exhaustiveness of the search. The higher the
+ value, the longer the optimizaton time and possibly the better the
+ resulting plan. The lower the value, the fewer alternative plans are
+ estimated, but the more likely to get a bad QEP.
+
+ All intermediate and final results of the procedure are stored in 'join':
+ join->positions modified for every partial QEP that is explored
+ join->best_positions modified for the current best complete QEP
+ join->best_read modified for the current best complete QEP
+ join->best_ref might be partially reordered
+ The final optimal plan is stored in 'join->best_positions', and its
+ corresponding cost in 'join->best_read'.
+
+ NOTES
+ The following pseudocode describes the algorithm of 'greedy_search':
+
+ procedure greedy_search
+ input: remaining_tables
+ output: pplan;
+ {
+ pplan = <>;
+ do {
+ (t, a) = best_extension(pplan, remaining_tables);
+ pplan = concat(pplan, (t, a));
+ remaining_tables = remaining_tables - t;
+ } while (remaining_tables != {})
+ return pplan;
+ }
+
+ where 'best_extension' is a placeholder for a procedure that selects the
+ most "promising" of all tables in 'remaining_tables'.
+ Currently this estimate is performed by calling
+ 'best_extension_by_limited_search' to evaluate all extensions of the
+ current QEP of size 'search_depth', thus the complexity of 'greedy_search'
+ mainly depends on that of 'best_extension_by_limited_search'.
+
+ If 'best_extension()' == 'best_extension_by_limited_search()', then the
+ worst-case complexity of this algorithm is <=
+ O(N*N^search_depth/search_depth). When serch_depth >= N, then the
+ complexity of greedy_search is O(N!).
+
+ In the future, 'greedy_search' might be extended to support other
+ implementations of 'best_extension', e.g. some simpler quadratic procedure.
+
+ RETURN
+ None
+*/
+
+static void
+greedy_search(JOIN *join,
+ table_map remaining_tables,
+ uint search_depth,
+ uint prune_level)
+{
+ double record_count= 1.0;
+ double read_time= 0.0;
+ uint idx= join->const_tables; // index into 'join->best_ref'
+ uint best_idx;
+ uint rem_size; // cardinality of remaining_tables
+ POSITION best_pos;
+ JOIN_TAB *best_table; // the next plan node to be added to the curr QEP
+
+ DBUG_ENTER("greedy_search");
+
+ /* number of tables that remain to be optimized */
+ rem_size= my_count_bits(remaining_tables);
+
+ do {
+ /* Find the extension of the current QEP with the lowest cost */
+ join->best_read= DBL_MAX;
+ best_extension_by_limited_search(join, remaining_tables, idx, record_count,
+ read_time, search_depth, prune_level);
+
+ if (rem_size <= search_depth)
+ {
+ /*
+ 'join->best_positions' contains a complete optimal extension of the
+ current partial QEP.
+ */
+ DBUG_EXECUTE("opt", print_plan(join, read_time, record_count,
+ join->tables, "optimal"););
+ DBUG_VOID_RETURN;
+ }
+
+ /* select the first table in the optimal extension as most promising */
+ best_pos= join->best_positions[idx];
+ best_table= best_pos.table;
+ /*
+ Each subsequent loop of 'best_extension_by_limited_search' uses
+ 'join->positions' for cost estimates, therefore we have to update its
+ value.
+ */
+ join->positions[idx]= best_pos;
+
+ /* find the position of 'best_table' in 'join->best_ref' */
+ best_idx= idx;
+ JOIN_TAB *pos= join->best_ref[best_idx];
+ while (pos && best_table != pos)
+ pos= join->best_ref[++best_idx];
+ DBUG_ASSERT((pos != NULL)); // should always find 'best_table'
+ /* move 'best_table' at the first free position in the array of joins */
+ swap_variables(JOIN_TAB*, join->best_ref[idx], join->best_ref[best_idx]);
+
+ /* compute the cost of the new plan extended with 'best_table' */
+ record_count*= join->positions[idx].records_read;
+ read_time+= join->positions[idx].read_time;
+
+ remaining_tables&= ~(best_table->table->map);
+ --rem_size;
+ ++idx;
+
+ DBUG_EXECUTE("opt",
+ print_plan(join, read_time, record_count, idx, "extended"););
+ } while (TRUE);
+}
+
+
+/*
+ Find a good, possibly optimal, query execution plan (QEP) by a possibly
+ exhaustive search.
+
+ SYNOPSIS
+ best_extension_by_limited_search()
+ join pointer to the structure providing all context info for
+ the query
+ remaining_tables set of tables not included into the partial plan yet
+ idx length of the partial QEP in 'join->positions';
+ since a depth-first search is used, also corresponds to
+ the current depth of the search tree;
+ also an index in the array 'join->best_ref';
+ record_count estimate for the number of records returned by the best
+ partial plan
+ read_time the cost of the best partial plan
+ search_depth maximum depth of the recursion and thus size of the found
+ optimal plan (0 < search_depth <= join->tables+1).
+ prune_level pruning heuristics that should be applied during optimization
+ (values: 0 = EXHAUSTIVE, 1 = PRUNE_BY_TIME_OR_ROWS)
+
+ DESCRIPTION
+ The procedure searches for the optimal ordering of the query tables in set
+ 'remaining_tables' of size N, and the corresponding optimal access paths to each
+ table. The choice of a table order and an access path for each table
+ constitutes a query execution plan (QEP) that fully specifies how to
+ execute the query.
+
+ The maximal size of the found plan is controlled by the parameter
+ 'search_depth'. When search_depth == N, the resulting plan is complete and
+ can be used directly as a QEP. If search_depth < N, the found plan consists
+ of only some of the query tables. Such "partial" optimal plans are useful
+ only as input to query optimization procedures, and cannot be used directly
+ to execute a query.
+
+ The algorithm begins with an empty partial plan stored in 'join->positions'
+ and a set of N tables - 'remaining_tables'. Each step of the algorithm
+ evaluates the cost of the partial plan extended by all access plans for
+ each of the relations in 'remaining_tables', expands the current partial
+ plan with the access plan that results in lowest cost of the expanded
+ partial plan, and removes the corresponding relation from
+ 'remaining_tables'. The algorithm continues until it either constructs a
+ complete optimal plan, or constructs an optimal plartial plan with size =
+ search_depth.
+
+ The final optimal plan is stored in 'join->best_positions'. The
+ corresponding cost of the optimal plan is in 'join->best_read'.
+
+ NOTES
+ The procedure uses a recursive depth-first search where the depth of the
+ recursion (and thus the exhaustiveness of the search) is controlled by the
+ parameter 'search_depth'.
+
+ The pseudocode below describes the algorithm of
+ 'best_extension_by_limited_search'. The worst-case complexity of this
+ algorithm is O(N*N^search_depth/search_depth). When serch_depth >= N, then
+ the complexity of greedy_search is O(N!).
+
+ procedure best_extension_by_limited_search(
+ pplan in, // in, partial plan of tables-joined-so-far
+ pplan_cost, // in, cost of pplan
+ remaining_tables, // in, set of tables not referenced in pplan
+ best_plan_so_far, // in/out, best plan found so far
+ best_plan_so_far_cost,// in/out, cost of best_plan_so_far
+ search_depth) // in, maximum size of the plans being considered
+ {
+ for each table T from remaining_tables
+ {
+ // Calculate the cost of using table T as above
+ cost = complex-series-of-calculations;
+
+ // Add the cost to the cost so far.
+ pplan_cost+= cost;
+
+ if (pplan_cost >= best_plan_so_far_cost)
+ // pplan_cost already too great, stop search
+ continue;
+
+ pplan= expand pplan by best_access_method;
+ remaining_tables= remaining_tables - table T;
+ if (remaining_tables is not an empty set
+ and
+ search_depth > 1)
+ {
+ best_extension_by_limited_search(pplan, pplan_cost,
+ remaining_tables,
+ best_plan_so_far,
+ best_plan_so_far_cost,
+ search_depth - 1);
+ }
+ else
+ {
+ best_plan_so_far_cost= pplan_cost;
+ best_plan_so_far= pplan;
+ }
+ }
+ }
+
+ IMPLEMENTATION
+ When 'best_extension_by_limited_search' is called for the first time,
+ 'join->best_read' must be set to the largest possible value (e.g. DBL_MAX).
+ The actual implementation provides a way to optionally use pruning
+ heuristic (controlled by the parameter 'prune_level') to reduce the search
+ space by skipping some partial plans.
+ The parameter 'search_depth' provides control over the recursion
+ depth, and thus the size of the resulting optimal plan.
+
+ RETURN
+ None
+*/
+
+static void
+best_extension_by_limited_search(JOIN *join,
+ table_map remaining_tables,
+ uint idx,
+ double record_count,
+ double read_time,
+ uint search_depth,
+ uint prune_level)
+{
+ THD *thd= join->thd;
+ if (thd->killed) // Abort
+ return;
+
+ DBUG_ENTER("best_extension_by_limited_search");
+
+ /*
+ 'join' is a partial plan with lower cost than the best plan so far,
+ so continue expanding it further with the tables in 'remaining_tables'.
+ */
+ JOIN_TAB *s;
+ double best_record_count= DBL_MAX;
+ double best_read_time= DBL_MAX;
+
+ DBUG_EXECUTE("opt",
+ print_plan(join, read_time, record_count, idx, "part_plan"););
+
+ for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
+ {
+ table_map real_table_bit= s->table->map;
+ if ((remaining_tables & real_table_bit) && !(remaining_tables & s->dependent))
+ {
+ double current_record_count, current_read_time;
+
+ /* Find the best access method from 's' to the current partial plan */
+ best_access_path(join, s, thd, remaining_tables, idx, record_count, read_time);
+ /* Compute the cost of extending the plan with 's' */
+ current_record_count= record_count * join->positions[idx].records_read;
+ current_read_time= read_time + join->positions[idx].read_time;
+
+ /* Expand only partial plans with lower cost than the best QEP so far */
+ if ((current_read_time +
+ current_record_count / (double) TIME_FOR_COMPARE) >= join->best_read)
+ {
+ DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
+ "prune_by_cost"););
+ continue;
+ }
+
+ /*
+ Prune some less promising partial plans. This heuristic may miss
+ the optimal QEPs, thus it results in a non-exhaustive search.
+ */
+ if (prune_level == 1)
+ {
+ if (best_record_count > current_record_count ||
+ best_read_time > current_read_time ||
+ idx == join->const_tables && // 's' is the first table in the QEP
+ s->table == join->sort_by_table)
+ {
+ if (best_record_count >= current_record_count &&
+ best_read_time >= current_read_time &&
+ /* TODO: What is the reasoning behind this condition? */
+ (!(s->key_dependent & remaining_tables) ||
+ join->positions[idx].records_read < 2.0))
+ {
+ best_record_count= current_record_count;
+ best_read_time= current_read_time;
+ }
+ }
+ else
+ {
+ DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
+ "pruned_by_heuristic"););
+ continue;
+ }
+ }
+
+ if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) )
+ { /* Recursively expand the current partial plan */
+ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
+ best_extension_by_limited_search(join,
+ remaining_tables & ~real_table_bit,
+ idx + 1,
+ current_record_count,
+ current_read_time,
+ search_depth - 1,
+ prune_level);
+ if (thd->killed)
+ DBUG_VOID_RETURN;
+ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
+ }
+ else
+ { /*
+ 'join' is either the best partial QEP with 'search_depth' relations,
+ or the best complete QEP so far, whichever is smaller.
+ */
+ current_read_time+= current_record_count / (double) TIME_FOR_COMPARE;
+ if (join->sort_by_table &&
+ join->sort_by_table != join->positions[join->const_tables].table->table)
+ /* We have to make a temp table */
+ current_read_time+= current_record_count;
+ if ((search_depth == 1) || (current_read_time < join->best_read))
+ {
+ memcpy((gptr) join->best_positions, (gptr) join->positions,
+ sizeof(POSITION) * (idx + 1));
+ join->best_read= current_read_time - 0.001;
+ }
+ DBUG_EXECUTE("opt",
+ print_plan(join, current_read_time, current_record_count, idx, "full_plan"););
+ }
+ }
+ }
DBUG_VOID_RETURN;
}
+/*
+ TODO: this function is here only temporarily until 'greedy_search' is
+ tested and accepted.
+*/
static void
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
double read_time)
@@ -2724,7 +4377,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
memcpy((gptr) join->best_positions,(gptr) join->positions,
sizeof(POSITION)*idx);
- join->best_read=read_time;
+ join->best_read= read_time - 0.001;
}
return;
}
@@ -2853,8 +4506,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
records=
((double) s->records / (double) rec *
(1.0 +
- ((double) (table->max_key_length-keyinfo->key_length) /
- (double) table->max_key_length)));
+ ((double) (table->s->max_key_length-keyinfo->key_length) /
+ (double) table->s->max_key_length)));
if (records < 2.0)
records=2.0; // Can't be as good as a unique
}
@@ -2901,7 +4554,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
/*
Assume that the first key part matches 1% of the file
- and that the hole key matches 10 (duplicates) or 1
+ and that the whole key matches 10 (duplicates) or 1
(unique) records.
Assume also that more key matches proportionally more
records
@@ -3020,7 +4673,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
/* Estimate cost of reading table. */
tmp= s->table->file->scan_time();
- if (s->on_expr) // Can't use join cache
+ if (s->table->map & join->outer_join) // Can't use join cache
{
/*
For each record we have to:
@@ -3129,13 +4782,13 @@ static void calc_used_field_length(THD *thd, JOIN_TAB *join_tab)
}
}
if (null_fields)
- rec_length+=(join_tab->table->null_fields+7)/8;
+ rec_length+=(join_tab->table->s->null_fields+7)/8;
if (join_tab->table->maybe_null)
rec_length+=sizeof(my_bool);
if (blobs)
{
uint blob_length=(uint) (join_tab->table->file->mean_rec_length-
- (join_tab->table->reclength- rec_length));
+ (join_tab->table->s->reclength- rec_length));
rec_length+=(uint) max(4,blob_length);
}
join_tab->used_fields=fields;
@@ -3194,11 +4847,12 @@ get_best_combination(JOIN *join)
KEYUSE *keyuse;
uint table_count;
THD *thd=join->thd;
+ DBUG_ENTER("get_best_combination");
table_count=join->tables;
if (!(join->join_tab=join_tab=
(JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
- return TRUE;
+ DBUG_RETURN(TRUE);
join->full_join=0;
@@ -3210,8 +4864,9 @@ get_best_combination(JOIN *join)
form=join->table[tablenr]=j->table;
used_tables|= form->map;
form->reginfo.join_tab=j;
- if (!j->on_expr)
+ if (!*j->on_expr_ref)
form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN
+ DBUG_PRINT("info",("type: %d", j->type));
if (j->type == JT_CONST)
continue; // Handled in make_join_stat..
@@ -3227,13 +4882,13 @@ get_best_combination(JOIN *join)
join->full_join=1;
}
else if (create_ref_for_key(join, j, keyuse, used_tables))
- return TRUE; // Something went wrong
+ DBUG_RETURN(TRUE); // Something went wrong
}
for (i=0 ; i < table_count ; i++)
join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i;
update_depend_map(join);
- return 0;
+ DBUG_RETURN(0);
}
@@ -3246,6 +4901,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
uint keyparts,length,key;
TABLE *table;
KEY *keyinfo;
+ DBUG_ENTER("create_ref_for_key");
/* Use best key from find_best */
table=j->table;
@@ -3295,7 +4951,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
(keyparts+1)))) ||
!(j->ref.items= (Item**) thd->alloc(sizeof(Item*)*keyparts)))
{
- return TRUE;
+ DBUG_RETURN(TRUE);
}
j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
j->ref.key_err=1;
@@ -3309,7 +4965,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
{
j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
if (keyuse->used_tables)
- return TRUE; // not supported yet. SerG
+ DBUG_RETURN(TRUE); // not supported yet. SerG
j->type=JT_FT;
}
@@ -3335,7 +4991,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
maybe_null ? (char*) key_buff : 0,
keyinfo->key_part[i].length, keyuse->val);
if (thd->is_fatal_error)
- return TRUE;
+ DBUG_RETURN(TRUE);
tmp.copy();
}
else
@@ -3344,7 +5000,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
&keyinfo->key_part[i],
(char*) key_buff,maybe_null);
/*
- Remeber if we are going to use REF_OR_NULL
+ Remember if we are going to use REF_OR_NULL
But only if field _really_ can be null i.e. we force JT_REF
instead of JT_REF_OR_NULL in case if field can't be null
*/
@@ -3355,7 +5011,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
} /* not ftkey */
*ref_key=0; // end_marker
if (j->type == JT_FT)
- return 0;
+ DBUG_RETURN(0);
if (j->type == JT_CONST)
j->table->const_table= 1;
else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
@@ -3379,7 +5035,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
}
else
j->type=JT_EQ_REF;
- return 0;
+ DBUG_RETURN(0);
}
@@ -3422,7 +5078,7 @@ bool
store_val_in_field(Field *field,Item *item)
{
bool error;
- THD *thd=current_thd;
+ THD *thd= field->table->in_use;
ha_rows cuted_fields=thd->cuted_fields;
/*
we should restore old value of count_cuted_fields because
@@ -3442,10 +5098,11 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
{
TABLE **tableptr;
JOIN_TAB *join_tab;
+ DBUG_ENTER("make_simple_join");
if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) ||
!(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
- return TRUE;
+ DBUG_RETURN(TRUE);
join->join_tab=join_tab;
join->table=tableptr; tableptr[0]=tmp_table;
join->tables=1;
@@ -3469,15 +5126,18 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join_tab->keys.init();
join_tab->keys.set_all(); /* test everything in quick */
join_tab->info=0;
- join_tab->on_expr=0;
+ join_tab->on_expr_ref=0;
+ join_tab->last_inner= 0;
+ join_tab->first_unmatched= 0;
join_tab->ref.key = -1;
join_tab->not_used_in_distinct=0;
join_tab->read_first_record= join_init_read_record;
join_tab->join=join;
+ join_tab->ref.key_parts= 0;
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
tmp_table->status=0;
tmp_table->null_row=0;
- return FALSE;
+ DBUG_RETURN(FALSE);
}
@@ -3583,10 +5243,10 @@ static void add_not_null_conds(JOIN *join)
when it is called from make_join_select after this function is
called.
*/
- if (notnull->fix_fields(join->thd, join->tables_list, &notnull))
+ if (notnull->fix_fields(join->thd, &notnull))
DBUG_VOID_RETURN;
DBUG_EXECUTE("where",print_where(notnull,
- referred_tab->table->table_name););
+ referred_tab->table->alias););
add_cond_and_fix(&referred_tab->select_cond, notnull);
}
}
@@ -3595,28 +5255,187 @@ static void add_not_null_conds(JOIN *join)
DBUG_VOID_RETURN;
}
+/*
+ Build a predicate guarded by match variables for embedding outer joins
+
+ SYNOPSIS
+ add_found_match_trig_cond()
+ tab the first inner table for most nested outer join
+ cond the predicate to be guarded
+ root_tab the first inner table to stop
+
+ DESCRIPTION
+ The function recursively adds guards for predicate cond
+ assending from tab to the first inner table next embedding
+ nested outer join and so on until it reaches root_tab
+ (root_tab can be 0).
+
+ RETURN VALUE
+ pointer to the guarded predicate, if success
+ 0, otherwise
+*/
+
+static COND*
+add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
+{
+ COND *tmp;
+ if (tab == root_tab || !cond)
+ return cond;
+ if ((tmp= add_found_match_trig_cond(tab->first_upper, cond, root_tab)))
+ {
+ tmp= new Item_func_trig_cond(tmp, &tab->found);
+ }
+ if (tmp)
+ {
+ tmp->quick_fix_field();
+ tmp->update_used_tables();
+ }
+ return tmp;
+}
+
+
+/*
+ Fill in outer join related info for the execution plan structure
+
+ SYNOPSIS
+ make_outerjoin_info()
+ join - reference to the info fully describing the query
+
+ DESCRIPTION
+ For each outer join operation left after simplification of the
+ original query the function set up the following pointers in the linear
+ structure join->join_tab representing the selected execution plan.
+ The first inner table t0 for the operation is set to refer to the last
+ inner table tk through the field t0->last_inner.
+ Any inner table ti for the operation are set to refer to the first
+ inner table ti->first_inner.
+ The first inner table t0 for the operation is set to refer to the
+ first inner table of the embedding outer join operation, if there is any,
+ through the field t0->first_upper.
+ The on expression for the outer join operation is attached to the
+ corresponding first inner table through the field t0->on_expr_ref.
+ Here ti are structures of the JOIN_TAB type.
+
+ EXAMPLE
+ For the query:
+ SELECT * FROM t1
+ LEFT JOIN
+ (t2, t3 LEFT JOIN t4 ON t3.a=t4.a)
+ ON (t1.a=t2.a AND t1.b=t3.b)
+ WHERE t1.c > 5,
+ given the execution plan with the table order t1,t2,t3,t4
+ is selected, the following references will be set;
+ t4->last_inner=[t4], t4->first_inner=[t4], t4->first_upper=[t2]
+ t2->last_inner=[t4], t2->first_inner=t3->first_inner=[t2],
+ on expression (t1.a=t2.a AND t1.b=t3.b) will be attached to
+ *t2->on_expr_ref, while t3.a=t4.a will be attached to *t4->on_expr_ref.
+
+ NOTES
+ The function assumes that the simplification procedure has been
+ already applied to the join query (see simplify_joins).
+ This function can be called only after the execution plan
+ has been chosen.
+*/
+
+static void
+make_outerjoin_info(JOIN *join)
+{
+ DBUG_ENTER("make_outerjoin_info");
+ for (uint i=join->const_tables ; i < join->tables ; i++)
+ {
+ JOIN_TAB *tab=join->join_tab+i;
+ TABLE *table=tab->table;
+ TABLE_LIST *tbl= table->pos_in_table_list;
+ TABLE_LIST *embedding= tbl->embedding;
+
+ if (tbl->outer_join)
+ {
+ /*
+ Table tab is the only one inner table for outer join.
+ (Like table t4 for the table reference t3 LEFT JOIN t4 ON t3.a=t4.a
+ is in the query above.)
+ */
+ tab->last_inner= tab->first_inner= tab;
+ tab->on_expr_ref= &tbl->on_expr;
+ tab->cond_equal= tbl->cond_equal;
+ if (embedding)
+ tab->first_upper= embedding->nested_join->first_nested;
+ }
+ for ( ; embedding ; embedding= embedding->embedding)
+ {
+ NESTED_JOIN *nested_join= embedding->nested_join;
+ if (!nested_join->counter)
+ {
+ /*
+ Table tab is the first inner table for nested_join.
+ Save reference to it in the nested join structure.
+ */
+ nested_join->first_nested= tab;
+ tab->on_expr_ref= &embedding->on_expr;
+ tab->cond_equal= tbl->cond_equal;
+ if (embedding->embedding)
+ tab->first_upper= embedding->embedding->nested_join->first_nested;
+ }
+ if (!tab->first_inner)
+ tab->first_inner= nested_join->first_nested;
+ if (++nested_join->counter < nested_join->join_list.elements)
+ break;
+ /* Table tab is the last inner table for nested join. */
+ nested_join->first_nested->last_inner= tab;
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+
static bool
make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{
+ THD *thd= join->thd;
DBUG_ENTER("make_join_select");
if (select)
{
add_not_null_conds(join);
table_map used_tables;
- if (join->tables > 1)
- cond->update_used_tables(); // Tablenr may have changed
- if (join->const_tables == join->tables &&
- join->thd->lex->current_select->master_unit() ==
- &join->thd->lex->unit) // not upper level SELECT
- join->const_table_map|=RAND_TABLE_BIT;
- { // Check const tables
- COND *const_cond=
- make_cond_for_table(cond,join->const_table_map,(table_map) 0);
- DBUG_EXECUTE("where",print_where(const_cond,"constants"););
- if (const_cond && !const_cond->val_int())
- {
- DBUG_PRINT("info",("Found impossible WHERE condition"));
- DBUG_RETURN(1); // Impossible const condition
+ if (cond) /* Because of QUICK_GROUP_MIN_MAX_SELECT */
+ { /* there may be a select without a cond. */
+ if (join->tables > 1)
+ cond->update_used_tables(); // Tablenr may have changed
+ if (join->const_tables == join->tables &&
+ thd->lex->current_select->master_unit() ==
+ &thd->lex->unit) // not upper level SELECT
+ join->const_table_map|=RAND_TABLE_BIT;
+ { // Check const tables
+ COND *const_cond=
+ make_cond_for_table(cond,join->const_table_map,(table_map) 0);
+ DBUG_EXECUTE("where",print_where(const_cond,"constants"););
+ for (JOIN_TAB *tab= join->join_tab+join->const_tables;
+ tab < join->join_tab+join->tables ; tab++)
+ {
+ if (*tab->on_expr_ref)
+ {
+ JOIN_TAB *cond_tab= tab->first_inner;
+ COND *tmp= make_cond_for_table(*tab->on_expr_ref,
+ join->const_table_map,
+ ( table_map) 0);
+ if (!tmp)
+ continue;
+ tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl);
+ if (!tmp)
+ DBUG_RETURN(1);
+ tmp->quick_fix_field();
+ cond_tab->select_cond= !cond_tab->select_cond ? tmp :
+ new Item_cond_and(cond_tab->select_cond,tmp);
+ if (!cond_tab->select_cond)
+ DBUG_RETURN(1);
+ cond_tab->select_cond->quick_fix_field();
+ }
+ }
+ if (const_cond && !const_cond->val_int())
+ {
+ DBUG_PRINT("info",("Found impossible WHERE condition"));
+ DBUG_RETURN(1); // Impossible const condition
+ }
}
}
used_tables=((select->const_tables=join->const_table_map) |
@@ -3624,14 +5443,17 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
for (uint i=join->const_tables ; i < join->tables ; i++)
{
JOIN_TAB *tab=join->join_tab+i;
+ JOIN_TAB *first_inner_tab= tab->first_inner;
table_map current_map= tab->table->map;
+ bool use_quick_range=0;
+ COND *tmp;
+
/*
Following force including random expression in last table condition.
It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
*/
if (i == join->tables-1)
current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
- bool use_quick_range=0;
used_tables|=current_map;
if (tab->type == JT_REF && tab->quick &&
@@ -3647,32 +5469,83 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
join->best_positions[i].records_read= rows2double(tab->quick->records);
}
- COND *tmp=make_cond_for_table(cond,used_tables,current_map);
- if (!tmp && tab->quick)
+ tmp= NULL;
+ if (cond)
+ tmp= make_cond_for_table(cond,used_tables,current_map);
+ if (cond && !tmp && tab->quick)
{ // Outer join
- /*
- Hack to handle the case where we only refer to a table
- in the ON part of an OUTER JOIN.
- */
- tmp=new Item_int((longlong) 1,1); // Always true
+ if (tab->type != JT_ALL)
+ {
+ /*
+ Don't use the quick method
+ We come here in the case where we have 'key=constant' and
+ the test is removed by make_cond_for_table()
+ */
+ delete tab->quick;
+ tab->quick= 0;
+ }
+ else
+ {
+ /*
+ Hack to handle the case where we only refer to a table
+ in the ON part of an OUTER JOIN. In this case we want the code
+ below to check if we should use 'quick' instead.
+ */
+ DBUG_PRINT("info", ("Item_int"));
+ tmp= new Item_int((longlong) 1,1); // Always true
+ DBUG_PRINT("info", ("Item_int 0x%lx", (ulong)tmp));
+ }
+
}
- if (tmp)
+ if (tmp || !cond)
{
+ DBUG_EXECUTE("where",print_where(tmp,tab->table->alias););
SQL_SELECT *sel=tab->select=(SQL_SELECT*)
- join->thd->memdup((gptr) select, sizeof(SQL_SELECT));
+ thd->memdup((gptr) select, sizeof(SQL_SELECT));
if (!sel)
DBUG_RETURN(1); // End of memory
- add_cond_and_fix(&tab->select_cond, tmp);
- sel->cond= tab->select_cond;
+ /*
+ If tab is an inner table of an outer join operation,
+ add a match guard to the pushed down predicate.
+ The guard will turn the predicate on only after
+ the first match for outer tables is encountered.
+ */
+ if (cond)
+ {
+ /*
+ Because of QUICK_GROUP_MIN_MAX_SELECT there may be a select without
+ a cond, so neutralize the hack above.
+ */
+ if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0)))
+ DBUG_RETURN(1);
+ tab->select_cond=sel->cond=tmp;
+ /* Push condition to storage engine if this is enabled
+ and the condition is not guarded */
+ tab->table->file->pushed_cond= NULL;
+ if (thd->variables.engine_condition_pushdown)
+ {
+ COND *push_cond=
+ make_cond_for_table(tmp, current_map, current_map);
+ if (push_cond)
+ {
+ /* Push condition to handler */
+ if (!tab->table->file->cond_push(push_cond))
+ tab->table->file->pushed_cond= push_cond;
+ }
+ }
+ }
+ else
+ tab->select_cond= sel->cond= NULL;
+
sel->head=tab->table;
- DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name););
+ DBUG_EXECUTE("where",print_where(tmp,tab->table->alias););
if (tab->quick)
{
/* Use quick key read if it's a constant and it's not used
with key reading */
if (tab->needed_reg.is_clear_all() && tab->type != JT_EQ_REF
&& tab->type != JT_FT && (tab->type != JT_REF ||
- (uint) tab->ref.key == tab->quick->index))
+ (uint) tab->ref.key == tab->quick->index))
{
sel->quick=tab->quick; // Use value from get_quick_...
sel->quick_keys.clear_all();
@@ -3703,7 +5576,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
the index if we are using limit and this is the first table
*/
- if ((!tab->keys.is_subset(tab->const_keys) && i > 0) ||
+ if (cond &&
+ (!tab->keys.is_subset(tab->const_keys) && i > 0) ||
(!tab->const_keys.is_clear_all() && i == join->const_tables &&
join->unit->select_limit_cnt <
join->best_positions[i].records_read &&
@@ -3711,7 +5585,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{
/* Join with outer join condition */
COND *orig_cond=sel->cond;
- sel->cond= and_conds(sel->cond, tab->on_expr);
+ sel->cond= and_conds(sel->cond, *tab->on_expr_ref);
/*
We can't call sel->cond->fix_fields,
@@ -3723,7 +5597,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if (sel->cond && !sel->cond->fixed)
sel->cond->quick_fix_field();
- if (sel->test_quick_select(join->thd, tab->keys,
+ if (sel->test_quick_select(thd, tab->keys,
used_tables & ~ current_map,
(join->select_options &
OPTION_FOUND_ROWS ?
@@ -3735,8 +5609,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
we have to check isn't it only "impossible ON" instead
*/
sel->cond=orig_cond;
- if (!tab->on_expr ||
- sel->test_quick_select(join->thd, tab->keys,
+ if (!*tab->on_expr_ref ||
+ sel->test_quick_select(thd, tab->keys,
used_tables & ~ current_map,
(join->select_options &
OPTION_FOUND_ROWS ?
@@ -3770,30 +5644,89 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
}
if (i != join->const_tables && tab->use_quick != 2)
{ /* Read with cache */
- if ((tmp=make_cond_for_table(cond,
+ if (cond &&
+ (tmp=make_cond_for_table(cond,
join->const_table_map |
current_map,
current_map)))
{
DBUG_EXECUTE("where",print_where(tmp,"cache"););
tab->cache.select=(SQL_SELECT*)
- join->thd->memdup((gptr) sel, sizeof(SQL_SELECT));
+ thd->memdup((gptr) sel, sizeof(SQL_SELECT));
tab->cache.select->cond=tmp;
tab->cache.select->read_tables=join->const_table_map;
}
}
}
}
+
+ /*
+ Push down all predicates from on expressions.
+ Each of these predicated are guarded by a variable
+ that turns if off just before null complemented row for
+ outer joins is formed. Thus, the predicates from an
+ 'on expression' are guaranteed not to be checked for
+ the null complemented row.
+ */
+ JOIN_TAB *last_tab= tab;
+ while (first_inner_tab && first_inner_tab->last_inner == last_tab)
+ {
+ /*
+ Table tab is the last inner table of an outer join.
+ An on expression is always attached to it.
+ */
+ COND *on_expr= *first_inner_tab->on_expr_ref;
+
+ table_map used_tables= join->const_table_map |
+ OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
+ for (tab= join->join_tab+join->const_tables; tab <= last_tab ; tab++)
+ {
+ current_map= tab->table->map;
+ used_tables|= current_map;
+ COND *tmp= make_cond_for_table(on_expr, used_tables, current_map);
+ if (tmp)
+ {
+ JOIN_TAB *cond_tab= tab < first_inner_tab ? first_inner_tab : tab;
+ /*
+ First add the guards for match variables of
+ all embedding outer join operations.
+ */
+ if (!(tmp= add_found_match_trig_cond(cond_tab->first_inner,
+ tmp, first_inner_tab)))
+ DBUG_RETURN(1);
+ /*
+ Now add the guard turning the predicate off for
+ the null complemented row.
+ */
+ DBUG_PRINT("info", ("Item_func_trig_cond"));
+ tmp= new Item_func_trig_cond(tmp,
+ &first_inner_tab->not_null_compl);
+ DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx", (ulong) tmp));
+ if (tmp)
+ tmp->quick_fix_field();
+ /* Add the predicate to other pushed down predicates */
+ DBUG_PRINT("info", ("Item_cond_and"));
+ cond_tab->select_cond= !cond_tab->select_cond ? tmp :
+ new Item_cond_and(cond_tab->select_cond,tmp);
+ DBUG_PRINT("info", ("Item_cond_and 0x%lx",
+ (ulong)cond_tab->select_cond));
+ if (!cond_tab->select_cond)
+ DBUG_RETURN(1);
+ cond_tab->select_cond->quick_fix_field();
+ }
+ }
+ first_inner_tab= first_inner_tab->first_upper;
+ }
}
}
DBUG_RETURN(0);
}
-
static void
make_join_readinfo(JOIN *join, uint options)
{
uint i;
+
bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
DBUG_ENTER("make_join_readinfo");
@@ -3877,7 +5810,7 @@ make_join_readinfo(JOIN *join, uint options)
*/
table->status=STATUS_NO_RECORD;
if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
- tab->use_quick != 2 && !tab->on_expr)
+ tab->use_quick != 2 && !tab->first_inner)
{
if ((options & SELECT_DESCRIBE) ||
!join_init_cache(join->thd,join->join_tab+join->const_tables,
@@ -3892,7 +5825,8 @@ make_join_readinfo(JOIN *join, uint options)
join->thd->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED;
tab->read_first_record= join_init_quick_read_record;
if (statistics)
- statistic_increment(select_range_check_count, &LOCK_status);
+ statistic_increment(join->thd->status_var.select_range_check_count,
+ &LOCK_status);
}
else
{
@@ -3902,13 +5836,15 @@ make_join_readinfo(JOIN *join, uint options)
if (tab->select && tab->select->quick)
{
if (statistics)
- statistic_increment(select_range_count, &LOCK_status);
+ statistic_increment(join->thd->status_var.select_range_count,
+ &LOCK_status);
}
else
{
join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
if (statistics)
- statistic_increment(select_scan_count, &LOCK_status);
+ statistic_increment(join->thd->status_var.select_scan_count,
+ &LOCK_status);
}
}
else
@@ -3916,18 +5852,21 @@ make_join_readinfo(JOIN *join, uint options)
if (tab->select && tab->select->quick)
{
if (statistics)
- statistic_increment(select_full_range_join_count, &LOCK_status);
+ statistic_increment(join->thd->status_var.select_full_range_join_count,
+ &LOCK_status);
}
else
{
join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
if (statistics)
- statistic_increment(select_full_join_count, &LOCK_status);
+ statistic_increment(join->thd->status_var.select_full_join_count,
+ &LOCK_status);
}
}
if (!table->no_keyread)
{
if (tab->select && tab->select->quick &&
+ tab->select->quick->index != MAX_KEY && //not index_merge
table->used_keys.is_set(tab->select->quick->index))
{
table->key_read=1;
@@ -3980,7 +5919,8 @@ bool error_if_full_join(JOIN *join)
{
if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
{
- my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
return(1);
}
}
@@ -4021,29 +5961,68 @@ void JOIN_TAB::cleanup()
}
+void JOIN::join_free(bool full)
+{
+ SELECT_LEX_UNIT *unit;
+ SELECT_LEX *sl;
+ DBUG_ENTER("JOIN::join_free");
+
+ /*
+ Optimization: if not EXPLAIN and we are done with the JOIN,
+ free all tables.
+ */
+ full= full || (!select_lex->uncacheable && !thd->lex->describe);
+
+ cleanup(full);
+
+ for (unit= select_lex->first_inner_unit(); unit; unit= unit->next_unit())
+ for (sl= unit->first_select_in_union(); sl; sl= sl->next_select())
+ {
+ JOIN *join= sl->join;
+ if (join)
+ join->join_free(full);
+ }
+
+ /*
+ We are not using tables anymore
+ Unlock all tables. We may be in an INSERT .... SELECT statement.
+ */
+ if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
+ !select_lex->subquery_in_having &&
+ (select_lex == (thd->lex->unit.fake_select_lex ?
+ thd->lex->unit.fake_select_lex : &thd->lex->select_lex)))
+ {
+ /*
+ TODO: unlock tables even if the join isn't top level select in the
+ tree.
+ */
+ mysql_unlock_read_tables(thd, lock); // Don't free join->lock
+ lock= 0;
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
/*
Free resources of given join
SYNOPSIS
- JOIN::join_free()
+ JOIN::cleanup()
fill - true if we should free all resources, call with full==1 should be
last, before it this function can be called with full==0
NOTE: with subquery this function definitely will be called several times,
but even for simple query it can be called several times.
*/
-void
-JOIN::join_free(bool full)
-{
- JOIN_TAB *tab,*end;
- DBUG_ENTER("JOIN::join_free");
- full= full || (!select_lex->uncacheable &&
- !thd->lex->subqueries &&
- !thd->lex->describe); // do not cleanup too early on EXPLAIN
+void JOIN::cleanup(bool full)
+{
+ DBUG_ENTER("JOIN::cleanup");
if (table)
{
+ JOIN_TAB *tab,*end;
/*
Only a sorted table may be cached. This sorted table is always the
first non const table in join->table
@@ -4054,16 +6033,6 @@ JOIN::join_free(bool full)
filesort_free_buffers(table[const_tables]);
}
- for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit;
- unit= unit->next_unit())
- {
- JOIN *join;
- for (SELECT_LEX *sl= unit->first_select_in_union(); sl;
- sl= sl->next_select())
- if ((join= sl->join))
- join->join_free(full);
- }
-
if (full)
{
for (tab= join_tab, end= tab+tables; tab != end; tab++)
@@ -4080,25 +6049,14 @@ JOIN::join_free(bool full)
}
}
}
-
/*
We are not using tables anymore
Unlock all tables. We may be in an INSERT .... SELECT statement.
*/
- if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
- !select_lex->subquery_in_having)
- {
- // TODO: unlock tables even if the join isn't top level select in the tree
- if (select_lex == (thd->lex->unit.fake_select_lex ?
- thd->lex->unit.fake_select_lex : &thd->lex->select_lex))
- {
- mysql_unlock_read_tables(thd, lock); // Don't free join->lock
- lock=0;
- }
- }
-
if (full)
{
+ if (tmp_join)
+ tmp_table_param.copy_field= 0;
group_fields.delete_elements();
/*
We can't call delete_elements() on copy_funcs as this will cause
@@ -4278,7 +6236,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
DBUG_ENTER("remove_const");
prev_ptr= &first_order;
- *simple_order= join->join_tab[join->const_tables].on_expr ? 0 : 1;
+ *simple_order= *join->join_tab[join->const_tables].on_expr_ref ? 0 : 1;
/* NOTE: A variable of not_const_tables ^ first_table; breaks gcc 2.7 */
@@ -4333,8 +6291,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
static int
return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
List<Item> &fields, bool send_row, uint select_options,
- const char *info, Item *having, Procedure *procedure,
- SELECT_LEX_UNIT *unit)
+ const char *info, Item *having)
{
DBUG_ENTER("return_zero_rows");
@@ -4348,12 +6305,13 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
if (send_row)
{
- for (TABLE_LIST *table=tables; table ; table=table->next)
+ for (TABLE_LIST *table= tables; table; table= table->next_leaf)
mark_as_null_row(table->table); // All fields are NULL
if (having && having->val_int() == 0)
send_row=0;
}
- if (!(result->send_fields(fields,1)))
+ if (!(result->send_fields(fields,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
{
if (send_row)
{
@@ -4388,22 +6346,832 @@ static void clear_tables(JOIN *join)
class COND_CMP :public ilink {
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
static void operator delete(void *ptr __attribute__((unused)),
- size_t size __attribute__((unused))) {} /*lint -e715 */
+ size_t size __attribute__((unused)))
+ { TRASH(ptr, size); }
Item *and_level;
Item_func *cmp_func;
COND_CMP(Item *a,Item_func *b) :and_level(a),cmp_func(b) {}
};
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class I_List<COND_CMP>;
template class I_List_iterator<COND_CMP>;
template class List<Item_func_match>;
template class List_iterator<Item_func_match>;
#endif
+
+/*
+ Find the multiple equality predicate containing a field
+
+ SYNOPSIS
+ find_item_equal()
+ cond_equal multiple equalities to search in
+ field field to look for
+ inherited_fl :out set up to TRUE if multiple equality is found
+ on upper levels (not on current level of cond_equal)
+
+ DESCRIPTION
+ The function retrieves the multiple equalities accessed through
+ the con_equal structure from current level and up looking for
+ an equality containing field. It stops retrieval as soon as the equality
+ is found and set up inherited_fl to TRUE if it's found on upper levels.
+
+ RETURN
+ Item_equal for the found multiple equality predicate if a success;
+ NULL - otherwise.
+*/
+
+Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
+ bool *inherited_fl)
+{
+ Item_equal *item= 0;
+ bool in_upper_level= FALSE;
+ while (cond_equal)
+ {
+ List_iterator_fast<Item_equal> li(cond_equal->current_level);
+ while ((item= li++))
+ {
+ if (item->contains(field))
+ goto finish;
+ }
+ in_upper_level= TRUE;
+ cond_equal= cond_equal->upper_levels;
+ }
+ in_upper_level= FALSE;
+finish:
+ *inherited_fl= in_upper_level;
+ return item;
+}
+
+
+/*
+ Check whether an item is a simple equality predicate and if so
+ create/find a multiple equality for this predicate
+
+ SYNOPSIS
+ check_equality()
+ item item to check
+ cond_equal multiple equalities that must hold together with the predicate
+
+ DESCRIPTION
+ This function first checks whether an item is a simple equality i.e.
+ the one that equates a field with another field or a constant
+ (item=constant_item or item=field_item).
+ If this is the case the function looks a for a multiple equality
+ in the lists referenced directly or indirectly by cond_equal inferring
+ the given simple equality. If it doesn't find any, it builds a multiple
+ equality that covers the predicate, i.e. the predicate can be inferred
+ from it.
+ The built multiple equality could be obtained in such a way:
+ create a binary multiple equality equivalent to the predicate, then
+ merge it, if possible, with one of old multiple equalities.
+ This guarantees that the set of multiple equalities covering equality
+ predicates will
+ be minimal.
+
+ EXAMPLE
+ For the where condition
+ WHERE a=b AND b=c AND
+ (b=2 OR f=e)
+ the check_equality will be called for the following equality
+ predicates a=b, b=c, b=2 and f=e.
+ For a=b it will be called with *cond_equal=(0,[]) and will transform
+ *cond_equal into (0,[Item_equal(a,b)]).
+ For b=c it will be called with *cond_equal=(0,[Item_equal(a,b)])
+ and will transform *cond_equal into CE=(0,[Item_equal(a,b,c)]).
+ For b=2 it will be called with *cond_equal=(ptr(CE),[])
+ and will transform *cond_equal into (ptr(CE),[Item_equal(2,a,b,c)]).
+ For f=e it will be called with *cond_equal=(ptr(CE), [])
+ and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]).
+
+ NOTES
+ Now only fields that have the same type defintions (verified by
+ the Field::eq_def method) are placed to the same multiple equalities.
+ Because of this some equality predicates are not eliminated and
+ can be used in the constant propagation procedure.
+ We could weeken the equlity test as soon as at least one of the
+ equal fields is to be equal to a constant. It would require a
+ more complicated implementation: we would have to store, in
+ general case, its own constant for each fields from the multiple
+ equality. But at the same time it would allow us to get rid
+ of constant propagation completely: it would be done by the call
+ to build_equal_items_for_cond.
+
+ IMPLEMENTATION
+ The implementation does not follow exactly the above rules to
+ build a new multiple equality for the equality predicate.
+ If it processes the equality of the form field1=field2, it
+ looks for multiple equalities me1 containig field1 and me2 containing
+ field2. If only one of them is found the fuction expands it with
+ the lacking field. If multiple equalities for both fields are
+ found they are merged. If both searches fail a new multiple equality
+ containing just field1 and field2 is added to the existing
+ multiple equalities.
+ If the function processes the predicate of the form field1=const,
+ it looks for a multiple equality containing field1. If found, the
+ function checks the constant of the multiple equality. If the value
+ is unknown, it is setup to const. Otherwise the value is compared with
+ const and the evaluation of the equality predicate is performed.
+ When expanding/merging equality predicates from the upper levels
+ the function first copies them for the current level. It looks
+ acceptable, as this happens rarely. The implementation without
+ copying would be much more complicated.
+
+ RETURN
+ TRUE - if the predicate is a simple equality predicate
+ FALSE - otherwise
+*/
+
+static bool check_equality(Item *item, COND_EQUAL *cond_equal)
+{
+ if (item->type() == Item::FUNC_ITEM &&
+ ((Item_func*) item)->functype() == Item_func::EQ_FUNC)
+ {
+ Item *left_item= ((Item_func*) item)->arguments()[0];
+ Item *right_item= ((Item_func*) item)->arguments()[1];
+ if (left_item->type() == Item::FIELD_ITEM &&
+ right_item->type() == Item::FIELD_ITEM &&
+ !((Item_field*)left_item)->depended_from &&
+ !((Item_field*)right_item)->depended_from)
+ {
+ /* The predicate the form field1=field2 is processed */
+
+ Field *left_field= ((Item_field*) left_item)->field;
+ Field *right_field= ((Item_field*) right_item)->field;
+
+ if (!left_field->eq_def(right_field))
+ return FALSE;
+
+ if (left_field->eq(right_field)) /* f = f */
+ return TRUE;
+
+ /* Search for multiple equalities containing field1 and/or field2 */
+ bool left_copyfl, right_copyfl;
+ Item_equal *left_item_equal=
+ find_item_equal(cond_equal, left_field, &left_copyfl);
+ Item_equal *right_item_equal=
+ find_item_equal(cond_equal, right_field, &right_copyfl);
+
+ if (left_item_equal && left_item_equal == right_item_equal)
+ {
+ /*
+ The equality predicate is inference of one of the existing
+ multiple equalities, i.e the condition is already covered
+ by upper level equalities
+ */
+ return TRUE;
+ }
+
+ /* Copy the found multiple equalities at the current level if needed */
+ if (left_copyfl)
+ {
+ /* left_item_equal of an upper level contains left_item */
+ left_item_equal= new Item_equal(left_item_equal);
+ cond_equal->current_level.push_back(left_item_equal);
+ }
+ if (right_copyfl)
+ {
+ /* right_item_equal of an upper level contains right_item */
+ right_item_equal= new Item_equal(right_item_equal);
+ cond_equal->current_level.push_back(right_item_equal);
+ }
+
+ if (left_item_equal)
+ {
+ /* left item was found in the current or one of the upper levels */
+ if (! right_item_equal)
+ left_item_equal->add((Item_field *) right_item);
+ else
+ {
+ /* Merge two multiple equalities forming a new one */
+ left_item_equal->merge(right_item_equal);
+ /* Remove the merged multiple equality from the list */
+ List_iterator<Item_equal> li(cond_equal->current_level);
+ while ((li++) != right_item_equal);
+ li.remove();
+ }
+ }
+ else
+ {
+ /* left item was not found neither the current nor in upper levels */
+ if (right_item_equal)
+ right_item_equal->add((Item_field *) left_item);
+ else
+ {
+ /* None of the fields was found in multiple equalities */
+ Item_equal *item= new Item_equal((Item_field *) left_item,
+ (Item_field *) right_item);
+ cond_equal->current_level.push_back(item);
+ }
+ }
+ return TRUE;
+ }
+
+ {
+ /* The predicate of the form field=const/const=field is processed */
+ Item *const_item= 0;
+ Item_field *field_item= 0;
+ if (left_item->type() == Item::FIELD_ITEM &&
+ !((Item_field*)left_item)->depended_from &&
+ right_item->const_item())
+ {
+ field_item= (Item_field*) left_item;
+ const_item= right_item;
+ }
+ else if (right_item->type() == Item::FIELD_ITEM &&
+ !((Item_field*)right_item)->depended_from &&
+ left_item->const_item())
+ {
+ field_item= (Item_field*) right_item;
+ const_item= left_item;
+ }
+ if (const_item &&
+ field_item->result_type() == const_item->result_type())
+ {
+ bool copyfl;
+
+ if (field_item->result_type() == STRING_RESULT)
+ {
+ CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset();
+ if ((cs != ((Item_cond *) item)->compare_collation()) ||
+ !cs->coll->propagate(cs, 0, 0))
+ return FALSE;
+ }
+
+ Item_equal *item_equal = find_item_equal(cond_equal,
+ field_item->field, &copyfl);
+ if (copyfl)
+ {
+ item_equal= new Item_equal(item_equal);
+ cond_equal->current_level.push_back(item_equal);
+ }
+ if (item_equal)
+ {
+ /*
+ The flag cond_false will be set to 1 after this, if item_equal
+ already contains a constant and its value is not equal to
+ the value of const_item.
+ */
+ item_equal->add(const_item);
+ }
+ else
+ {
+ item_equal= new Item_equal(const_item, field_item);
+ cond_equal->current_level.push_back(item_equal);
+ }
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+ Replace all equality predicates in a condition by multiple equality items
+
+ SYNOPSIS
+ build_equal_items_for_cond()
+ cond condition(expression) where to make replacement
+ inherited path to all inherited multiple equality items
+
+ DESCRIPTION
+ At each 'and' level the function detects items for equality predicates
+ and replaced them by a set of multiple equality items of class Item_equal,
+ taking into account inherited equalities from upper levels.
+ If an equality predicate is used not in a conjunction it's just
+ replaced by a multiple equality predicate.
+ For each 'and' level the function set a pointer to the inherited
+ multiple equalities in the cond_equal field of the associated
+ object of the type Item_cond_and.
+ The function also traverses the cond tree and and for each field reference
+ sets a pointer to the multiple equality item containing the field, if there
+ is any. If this multiple equality equates fields to a constant the
+ function replace the field reference by the constant.
+ The function also determines the maximum number of members in
+ equality lists of each Item_cond_and object assigning it to
+ cond_equal->max_members of this object and updating accordingly
+ the upper levels COND_EQUAL structures.
+
+ NOTES
+ Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of
+ f1=f2, .., fn-1=fn. It substitutes any inference from these
+ equality predicates that is equivalent to the conjunction.
+ Thus, =(a1,a2,a3) can substitute for ((a1=a3) AND (a2=a3) AND (a2=a1)) as
+ it is equivalent to ((a1=a2) AND (a2=a3)).
+ The function always makes a substitution of all equality predicates occured
+ in a conjuction for a minimal set of multiple equality predicates.
+ This set can be considered as a canonical representation of the
+ sub-conjunction of the equality predicates.
+ E.g. (t1.a=t2.b AND t2.b>5 AND t1.a=t3.c) is replaced by
+ (=(t1.a,t2.b,t3.c) AND t2.b>5), not by
+ (=(t1.a,t2.b) AND =(t1.a,t3.c) AND t2.b>5);
+ while (t1.a=t2.b AND t2.b>5 AND t3.c=t4.d) is replaced by
+ (=(t1.a,t2.b) AND =(t3.c=t4.d) AND t2.b>5),
+ but if additionally =(t4.d,t2.b) is inherited, it
+ will be replaced by (=(t1.a,t2.b,t3.c,t4.d) AND t2.b>5)
+
+ IMPLEMENTATION
+ The function performs the substitution in a recursive descent by
+ the condtion tree, passing to the next AND level a chain of multiple
+ equality predicates which have been built at the upper levels.
+ The Item_equal items built at the level are attached to other
+ non-equality conjucts as a sublist. The pointer to the inherited
+ multiple equalities is saved in the and condition object (Item_cond_and).
+ This chain allows us for any field reference occurence easyly to find a
+ multiple equality that must be held for this occurence.
+ For each AND level we do the following:
+ - scan it for all equality predicate (=) items
+ - join them into disjoint Item_equal() groups
+ - process the included OR conditions recursively to do the same for
+ lower AND levels.
+ We need to do things in this order as lower AND levels need to know about
+ all possible Item_equal objects in upper levels.
+
+ RETURN
+ pointer to the transformed condition
+*/
+
+static COND *build_equal_items_for_cond(COND *cond,
+ COND_EQUAL *inherited)
+{
+ Item_equal *item_equal;
+ uint members;
+ COND_EQUAL cond_equal;
+ cond_equal.upper_levels= inherited;
+
+ if (cond->type() == Item::COND_ITEM)
+ {
+ bool and_level= ((Item_cond*) cond)->functype() ==
+ Item_func::COND_AND_FUNC;
+ List<Item> *args= ((Item_cond*) cond)->argument_list();
+
+ List_iterator<Item> li(*args);
+ Item *item;
+
+ if (and_level)
+ {
+ /*
+ Retrieve all conjucts of this level detecting the equality
+ that are subject to substitution by multiple equality items and
+ removing each such predicate from the conjunction after having
+ found/created a multiple equality whose inference the predicate is.
+ */
+ while ((item= li++))
+ {
+ /*
+ PS/SP note: we can safely remove a node from AND-OR
+ structure here because it's restored before each
+ re-execution of any prepared statement/stored procedure.
+ */
+ if (check_equality(item, &cond_equal))
+ li.remove();
+ }
+
+ List_iterator_fast<Item_equal> it(cond_equal.current_level);
+ while ((item_equal= it++))
+ {
+ item_equal->fix_length_and_dec();
+ item_equal->update_used_tables();
+ members= item_equal->members();
+ if (cond_equal.max_members < members)
+ cond_equal.max_members= members;
+ }
+ members= cond_equal.max_members;
+ if (inherited && inherited->max_members < members)
+ {
+ do
+ {
+ inherited->max_members= members;
+ inherited= inherited->upper_levels;
+ }
+ while (inherited);
+ }
+
+ ((Item_cond_and*)cond)->cond_equal= cond_equal;
+ inherited= &(((Item_cond_and*)cond)->cond_equal);
+ }
+ /*
+ Make replacement of equality predicates for lower levels
+ of the condition expression.
+ */
+ li.rewind();
+ while ((item= li++))
+ {
+ Item *new_item;
+ if ((new_item = build_equal_items_for_cond(item, inherited))!= item)
+ {
+ /* This replacement happens only for standalone equalities */
+ /*
+ This is ok with PS/SP as the replacement is done for
+ arguments of an AND/OR item, which are restored for each
+ execution of PS/SP.
+ */
+ li.replace(new_item);
+ }
+ }
+ if (and_level)
+ args->concat((List<Item> *)&cond_equal.current_level);
+ }
+ else if (cond->type() == Item::FUNC_ITEM)
+ {
+ /*
+ If an equality predicate forms the whole and level,
+ we call it standalone equality and it's processed here.
+ E.g. in the following where condition
+ WHERE a=5 AND (b=5 or a=c)
+ (b=5) and (a=c) are standalone equalities.
+ In general we can't leave alone standalone eqalities:
+ for WHERE a=b AND c=d AND (b=c OR d=5)
+ b=c is replaced by =(a,b,c,d).
+ */
+ if (check_equality(cond, &cond_equal) &&
+ (item_equal= cond_equal.current_level.pop()))
+ {
+ item_equal->fix_length_and_dec();
+ item_equal->update_used_tables();
+ return item_equal;
+ }
+ /*
+ For each field reference in cond, not from equalitym predicates,
+ set a pointer to the multiple equality if belongs to (if there is any)
+ */
+ cond= cond->transform(&Item::equal_fields_propagator,
+ (byte *) inherited);
+ cond->update_used_tables();
+ }
+ return cond;
+}
+
+
+/*
+ Build multiple equalities for a condition and all on expressions that
+ inherit these multiple equalities
+
+ SYNOPSIS
+ build_equal_items()
+ thd Thread handler
+ cond condition to build the multiple equalities for
+ inherited path to all inherited multiple equality items
+ join_list list of join tables to which the condition refers to
+ cond_equal_ref :out pointer to the structure to place built equalities in
+
+ DESCRIPTION
+ The function first applies the build_equal_items_for_cond function
+ to build all multiple equalities for condition cond utilizing equalities
+ referred through the parameter inherited. The extended set of
+ equalities is returned in the structure referred by the cond_equal_ref
+ parameter. After this the function calls itself recursively for
+ all on expressions whose direct references can be found in join_list
+ and who inherit directly the multiple equalities just having built.
+
+ NOTES
+ The on expression used in an outer join operation inherits all equalities
+ from the on expression of the embedding join, if there is any, or
+ otherwise - from the where condition.
+ This fact is not obvious, but presumably can be proved.
+ Consider the following query:
+ SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t2.a=t4.a
+ WHERE t1.a=t2.a;
+ If the on expression in the query inherits =(t1.a,t2.a), then we
+ can build the multiple equality =(t1.a,t2.a,t3.a,t4.a) that infers
+ the equality t3.a=t4.a. Although the on expression
+ t1.a=t3.a AND t2.a=t4.a AND t3.a=t4.a is not equivalent to the one
+ in the query the latter can be replaced by the former: the new query
+ will return the same result set as the original one.
+
+ Interesting that multiple equality =(t1.a,t2.a,t3.a,t4.a) allows us
+ to use t1.a=t3.a AND t3.a=t4.a under the on condition:
+ SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a
+ WHERE t1.a=t2.a
+ This query equivalent to:
+ SELECT * FROM (t1 LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a),t2
+ WHERE t1.a=t2.a
+ Similarly the original query can be rewritten to the query:
+ SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t2.a=t4.a AND t3.a=t4.a
+ WHERE t1.a=t2.a
+ that is equivalent to:
+ SELECT * FROM (t2 LEFT JOIN (t3,t4)ON t2.a=t4.a AND t3.a=t4.a), t1
+ WHERE t1.a=t2.a
+ Thus, applying equalities from the where condition we basically
+ can get more freedom in performing join operations.
+ Althogh we don't use this property now, it probably makes sense to use
+ it in the future.
+
+ RETURN
+ pointer to the transformed condition containing multiple equalities
+*/
+
+static COND *build_equal_items(THD *thd, COND *cond,
+ COND_EQUAL *inherited,
+ List<TABLE_LIST> *join_list,
+ COND_EQUAL **cond_equal_ref)
+{
+ COND_EQUAL *cond_equal= 0;
+
+ if (cond)
+ {
+ cond= build_equal_items_for_cond(cond, inherited);
+ cond->update_used_tables();
+ if (cond->type() == Item::COND_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ cond_equal= &((Item_cond_and*) cond)->cond_equal;
+ else if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ cond_equal= new COND_EQUAL;
+ cond_equal->current_level.push_back((Item_equal *) cond);
+ }
+ }
+ if (cond_equal)
+ {
+ cond_equal->upper_levels= inherited;
+ inherited= cond_equal;
+ }
+ *cond_equal_ref= cond_equal;
+
+ if (join_list)
+ {
+ TABLE_LIST *table;
+ List_iterator<TABLE_LIST> li(*join_list);
+
+ while ((table= li++))
+ {
+ if (table->on_expr)
+ {
+ List<TABLE_LIST> *join_list= table->nested_join ?
+ &table->nested_join->join_list : NULL;
+ /*
+ We can modify table->on_expr because its old value will
+ be restored before re-execution of PS/SP.
+ */
+ table->on_expr= build_equal_items(thd, table->on_expr, inherited,
+ join_list, &table->cond_equal);
+ }
+ }
+ }
+
+ return cond;
+}
+
+
+/*
+ Compare field items by table order in the execution plan
+
+ SYNOPSIS
+ compare_fields_by_table_order()
+ field1 first field item to compare
+ field2 second field item to compare
+ table_join_idx index to tables determining table order
+
+ DESCRIPTION
+ field1 considered as better than field2 if the table containing
+ field1 is accessed earlier than the table containing field2.
+ The function finds out what of two fields is better according
+ this criteria.
+
+ RETURN
+ 1, if field1 is better than field2
+ -1, if field2 is better than field1
+ 0, otherwise
+*/
+
+static int compare_fields_by_table_order(Item_field *field1,
+ Item_field *field2,
+ void *table_join_idx)
+{
+ int cmp= 0;
+ bool outer_ref= 0;
+ if (field2->used_tables() & OUTER_REF_TABLE_BIT)
+ {
+ outer_ref= 1;
+ cmp= -1;
+ }
+ if (field2->used_tables() & OUTER_REF_TABLE_BIT)
+ {
+ outer_ref= 1;
+ cmp++;
+ }
+ if (outer_ref)
+ return cmp;
+ JOIN_TAB **idx= (JOIN_TAB **) table_join_idx;
+ cmp= idx[field2->field->table->tablenr]-idx[field1->field->table->tablenr];
+ return cmp < 0 ? -1 : (cmp ? 1 : 0);
+}
+
+
+/*
+ Generate minimal set of simple equalities equivalent to a multiple equality
+
+ SYNOPSIS
+ eliminate_item_equal()
+ cond condition to add the generated equality to
+ upper_levels structure to access multiple equality of upper levels
+ item_equal multiple equality to generate simple equality from
+
+ DESCRIPTION
+ The function retrieves the fields of the multiple equality item
+ item_equal and for each field f:
+ - if item_equal contains const it generates the equality f=const_item;
+ - otherwise, if f is not the first field, generates the equality
+ f=item_equal->get_first().
+ All generated equality are added to the cond conjunction.
+
+ NOTES
+ Before generating an equality function checks that it has not
+ been generated for multiple equalies of the upper levels.
+ E.g. for the following where condition
+ WHERE a=5 AND ((a=b AND b=c) OR c>4)
+ the upper level AND condition will contain =(5,a),
+ while the lower level AND condition will contain =(5,a,b,c).
+ When splitting =(5,a,b,c) into a separate equality predicates
+ we should omit 5=a, as we have it already in the upper level.
+ The following where condition gives us a more complicated case:
+ WHERE t1.a=t2.b AND t3.c=t4.d AND (t2.b=t3.c OR t4.e>5 ...) AND ...
+ Given the tables are accessed in the order t1->t2->t3->t4 for
+ the selected query execution plan the lower level multiple
+ equality =(t1.a,t2.b,t3.c,t4.d) formally should be converted to
+ t1.a=t2.b AND t1.a=t3.c AND t1.a=t4.d. But t1.a=t2.a will be
+ generated for the upper level. Also t3.c=t4.d will be generated there.
+ So only t1.a=t3.c should be left in the lower level.
+ If cond is equal to 0, then not more then one equality is generated
+ and a pointer to it is returned as the result of the function.
+
+ RETURN
+ The condition with generated simple equalities or
+ a pointer to the simple generated equality, if success.
+ 0, otherwise.
+*/
+
+static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
+ Item_equal *item_equal)
+{
+ List<Item> eq_list;
+ Item_func_eq *eq_item= 0;
+ if (((Item *) item_equal)->const_item() && !item_equal->val_int())
+ return new Item_int((longlong) 0,1);
+ Item *item_const= item_equal->get_const();
+ Item_equal_iterator it(*item_equal);
+ Item *head;
+ if (item_const)
+ head= item_const;
+ else
+ {
+ head= item_equal->get_first();
+ it++;
+ }
+ Item_field *item_field;
+ while ((item_field= it++))
+ {
+ Item_equal *upper= item_field->find_item_equal(upper_levels);
+ Item_field *item= item_field;
+ if (upper)
+ {
+ if (item_const && upper->get_const())
+ item= 0;
+ else
+ {
+ Item_equal_iterator li(*item_equal);
+ while ((item= li++) != item_field)
+ {
+ if (item->find_item_equal(upper_levels) == upper)
+ break;
+ }
+ }
+ }
+ if (item == item_field)
+ {
+ if (eq_item)
+ eq_list.push_back(eq_item);
+ eq_item= new Item_func_eq(item_field, head);
+ if (!eq_item)
+ return 0;
+ eq_item->set_cmp_func();
+ eq_item->quick_fix_field();
+ }
+ }
+
+ if (!cond && !eq_list.head())
+ {
+ if (!eq_item)
+ return new Item_int((longlong) 1,1);
+ return eq_item;
+ }
+
+ if (eq_item)
+ eq_list.push_back(eq_item);
+ if (!cond)
+ cond= new Item_cond_and(eq_list);
+ else
+ ((Item_cond *) cond)->add_at_head(&eq_list);
+
+ cond->quick_fix_field();
+ cond->update_used_tables();
+
+ return cond;
+}
+
+
+/*
+ Substitute every field reference in a condition by the best equal field
+ and eliminate all multiplle equality predicates
+
+ SYNOPSIS
+ substitute_for_best_equal_field()
+ cond condition to process
+ cond_equal multiple equalities to take into consideration
+ table_join_idx index to tables determining field preference
+
+ DESCRIPTION
+ The function retrieves the cond condition and for each encountered
+ multiple equality predicate it sorts the field references in it
+ according to the order of tables specified by the table_join_idx
+ parameter. Then it eliminates the multiple equality predicate it
+ replacing it by the conjunction of simple equality predicates
+ equating every field from the multiple equality to the first
+ field in it, or to the constant, if there is any.
+ After this the function retrieves all other conjuncted
+ predicates substitute every field reference by the field reference
+ to the first equal field or equal constant if there are any.
+
+ NOTES
+ At the first glance full sort of fields in multiple equality
+ seems to be an overkill. Yet it's not the case due to possible
+ new fields in multiple equality item of lower levels. We want
+ the order in them to comply with the order of upper levels.
+
+ RETURN
+ The transformed condition
+*/
+
+static COND* substitute_for_best_equal_field(COND *cond,
+ COND_EQUAL *cond_equal,
+ void *table_join_idx)
+{
+ Item_equal *item_equal;
+
+ if (cond->type() == Item::COND_ITEM)
+ {
+ List<Item> *cond_list= ((Item_cond*) cond)->argument_list();
+
+ bool and_level= ((Item_cond*) cond)->functype() ==
+ Item_func::COND_AND_FUNC;
+ if (and_level)
+ {
+ cond_equal= &((Item_cond_and *) cond)->cond_equal;
+ cond_list->disjoin((List<Item> *) &cond_equal->current_level);
+
+ List_iterator_fast<Item_equal> it(cond_equal->current_level);
+ while ((item_equal= it++))
+ {
+ item_equal->sort(&compare_fields_by_table_order, table_join_idx);
+ }
+ }
+
+ List_iterator<Item> li(*cond_list);
+ Item *item;
+ while ((item= li++))
+ {
+ Item *new_item =substitute_for_best_equal_field(item, cond_equal,
+ table_join_idx);
+ /*
+ This works OK with PS/SP re-execution as changes are made to
+ the arguments of AND/OR items only
+ */
+ if (new_item != item)
+ li.replace(new_item);
+ }
+
+ if (and_level)
+ {
+ List_iterator_fast<Item_equal> it(cond_equal->current_level);
+ while ((item_equal= it++))
+ {
+ cond= eliminate_item_equal(cond, cond_equal->upper_levels, item_equal);
+ }
+ }
+ }
+ else if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ item_equal= (Item_equal *) cond;
+ item_equal->sort(&compare_fields_by_table_order, table_join_idx);
+ if (cond_equal && cond_equal->current_level.head() == item_equal)
+ cond_equal= 0;
+ return eliminate_item_equal(0, cond_equal, item_equal);
+ }
+ else
+ cond->transform(&Item::replace_equal_field, 0);
+ return cond;
+}
+
+
/*
change field = field to field = const for each found field = const in the
and_level
@@ -4576,28 +7344,286 @@ propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list,
}
+/*
+ Simplify joins replacing outer joins by inner joins whenever it's possible
+
+ SYNOPSIS
+ simplify_joins()
+ join reference to the query info
+ join_list list representation of the join to be converted
+ conds conditions to add on expressions for converted joins
+ top true <=> conds is the where condition
+
+ DESCRIPTION
+ The function, during a retrieval of join_list, eliminates those
+ outer joins that can be converted into inner join, possibly nested.
+ It also moves the on expressions for the converted outer joins
+ and from inner joins to conds.
+ The function also calculates some attributes for nested joins:
+ - used_tables
+ - not_null_tables
+ - dep_tables.
+ - on_expr_dep_tables
+ The first two attributes are used to test whether an outer join can
+ be substituted for an inner join. The third attribute represents the
+ relation 'to be dependent on' for tables. If table t2 is dependent
+ on table t1, then in any evaluated execution plan table access to
+ table t2 must precede access to table t2. This relation is used also
+ to check whether the query contains invalid cross-references.
+ The forth attribute is an auxiliary one and is used to calculate
+ dep_tables.
+ As the attribute dep_tables qualifies possibles orders of tables in the
+ execution plan, the dependencies required by the straight join
+ modifiers are reflected in this attribute as well.
+ The function also removes all braces that can be removed from the join
+ expression without changing its meaning.
+
+ NOTES
+ An outer join can be replaced by an inner join if the where condition
+ or the on expression for an embedding nested join contains a conjunctive
+ predicate rejecting null values for some attribute of the inner tables.
+
+ E.g. in the query:
+ SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a WHERE t2.b < 5
+ the predicate t2.b < 5 rejects nulls.
+ The query is converted first to:
+ SELECT * FROM t1 INNER JOIN t2 ON t2.a=t1.a WHERE t2.b < 5
+ then to the equivalent form:
+ SELECT * FROM t1, t2 ON t2.a=t1.a WHERE t2.b < 5 AND t2.a=t1.a.
+
+ Similarly the following query:
+ SELECT * from t1 LEFT JOIN (t2, t3) ON t2.a=t1.a t3.b=t1.b
+ WHERE t2.c < 5
+ is converted to:
+ SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a t3.b=t1.b
+
+ One conversion might trigger another:
+ SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a
+ LEFT JOIN t3 ON t3.b=t2.b
+ WHERE t3 IS NOT NULL =>
+ SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a, t3
+ WHERE t3 IS NOT NULL AND t3.b=t2.b =>
+ SELECT * FROM t1, t2, t3
+ WHERE t3 IS NOT NULL AND t3.b=t2.b AND t2.a=t1.a
+
+ The function removes all unnecessary braces from the expression
+ produced by the conversions.
+ E.g. SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b
+ finally is converted to:
+ SELECT * FROM t1, t2, t3 WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b
+
+ It also will remove braces from the following queries:
+ SELECT * from (t1 LEFT JOIN t2 ON t2.a=t1.a) LEFT JOIN t3 ON t3.b=t2.b
+ SELECT * from (t1, (t2,t3)) WHERE t1.a=t2.a AND t2.b=t3.b.
+
+ The benefit of this simplification procedure is that it might return
+ a query for which the optimizer can evaluate execution plan with more
+ join orders. With a left join operation the optimizer does not
+ consider any plan where one of the inner tables is before some of outer
+ tables.
+
+ IMPLEMENTATION.
+ The function is implemented by a recursive procedure. On the recursive
+ ascent all attributes are calculated, all outer joins that can be
+ converted are replaced and then all unnecessary braces are removed.
+ As join list contains join tables in the reverse order sequential
+ elimination of outer joins does not requite extra recursive calls.
+
+ EXAMPLES
+ Here is an example of a join query with invalid cross references:
+ SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN ON t3.b=t1.b
+
+ RETURN VALUE
+ The new condition, if success
+ 0, otherwise
+*/
+
static COND *
-optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
+simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
{
- SELECT_LEX *select= thd->lex->current_select;
+ TABLE_LIST *table;
+ NESTED_JOIN *nested_join;
+ TABLE_LIST *prev_table= 0;
+ List_iterator<TABLE_LIST> li(*join_list);
+ DBUG_ENTER("simplify_joins");
+
+ /*
+ Try to simplify join operations from join_list.
+ The most outer join operation is checked for conversion first.
+ */
+ while ((table= li++))
+ {
+ table_map used_tables;
+ table_map not_null_tables= (table_map) 0;
+
+ if ((nested_join= table->nested_join))
+ {
+ /*
+ If the element of join_list is a nested join apply
+ the procedure to its nested join list first.
+ */
+ if (table->on_expr)
+ {
+ Item *expr= table->prep_on_expr ? table->prep_on_expr : table->on_expr;
+ /*
+ If an on expression E is attached to the table,
+ check all null rejected predicates in this expression.
+ If such a predicate over an attribute belonging to
+ an inner table of an embedded outer join is found,
+ the outer join is converted to an inner join and
+ the corresponding on expression is added to E.
+ */
+ expr= simplify_joins(join, &nested_join->join_list,
+ expr, FALSE);
+ table->prep_on_expr= table->on_expr= expr;
+ }
+ nested_join->used_tables= (table_map) 0;
+ nested_join->not_null_tables=(table_map) 0;
+ conds= simplify_joins(join, &nested_join->join_list, conds, top);
+ used_tables= nested_join->used_tables;
+ not_null_tables= nested_join->not_null_tables;
+ }
+ else
+ {
+ if (!(table->prep_on_expr))
+ table->prep_on_expr= table->on_expr;
+ used_tables= table->table->map;
+ if (conds)
+ not_null_tables= conds->not_null_tables();
+ }
+
+ if (table->embedding)
+ {
+ table->embedding->nested_join->used_tables|= used_tables;
+ table->embedding->nested_join->not_null_tables|= not_null_tables;
+ }
+
+ if (!table->outer_join || (used_tables & not_null_tables))
+ {
+ /*
+ For some of the inner tables there are conjunctive predicates
+ that reject nulls => the outer join can be replaced by an inner join.
+ */
+ table->outer_join= 0;
+ if (table->on_expr)
+ {
+ /* Add on expression to the where condition. */
+ if (conds)
+ {
+ conds= and_conds(conds, table->on_expr);
+ conds->top_level_item();
+ /* conds is always a new item as both cond and on_expr existed */
+ DBUG_ASSERT(!conds->fixed);
+ conds->fix_fields(join->thd, &conds);
+ }
+ else
+ conds= table->on_expr;
+ table->prep_on_expr= table->on_expr= 0;
+ }
+ }
+
+ if (!top)
+ continue;
+
+ /*
+ Only inner tables of non-convertible outer joins
+ remain with on_expr.
+ */
+ if (table->on_expr)
+ {
+ table->dep_tables|= table->on_expr->used_tables();
+ if (table->embedding)
+ {
+ table->dep_tables&= ~table->embedding->nested_join->used_tables;
+ /*
+ Embedding table depends on tables used
+ in embedded on expressions.
+ */
+ table->embedding->on_expr_dep_tables|= table->on_expr->used_tables();
+ }
+ else
+ table->dep_tables&= ~table->table->map;
+ }
+
+ if (prev_table)
+ {
+ /* The order of tables is reverse: prev_table follows table */
+ if (prev_table->straight)
+ prev_table->dep_tables|= used_tables;
+ if (prev_table->on_expr)
+ {
+ prev_table->dep_tables|= table->on_expr_dep_tables;
+ table_map prev_used_tables= prev_table->nested_join ?
+ prev_table->nested_join->used_tables :
+ prev_table->table->map;
+ /*
+ If on expression contains only references to inner tables
+ we still make the inner tables dependent on the outer tables.
+ It would be enough to set dependency only on one outer table
+ for them. Yet this is really a rare case.
+ */
+ if (!(prev_table->on_expr->used_tables() & ~prev_used_tables))
+ prev_table->dep_tables|= used_tables;
+ }
+ }
+ prev_table= table;
+ }
+
+ /* Flatten nested joins that can be flattened. */
+ li.rewind();
+ while ((table= li++))
+ {
+ nested_join= table->nested_join;
+ if (nested_join && !table->on_expr)
+ {
+ TABLE_LIST *tbl;
+ List_iterator<TABLE_LIST> it(nested_join->join_list);
+ while ((tbl= it++))
+ {
+ tbl->embedding= table->embedding;
+ tbl->join_list= table->join_list;
+ }
+ li.replace(nested_join->join_list);
+ }
+ }
+ DBUG_RETURN(conds);
+}
+
+
+static COND *
+optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
+ Item::cond_result *cond_value)
+{
+ THD *thd= join->thd;
+ SELECT_LEX *select= thd->lex->current_select;
DBUG_ENTER("optimize_cond");
- if (conds)
+
+ if (!conds)
+ *cond_value= Item::COND_TRUE;
+ else
{
+ /*
+ Build all multiple equality predicates and eliminate equality
+ predicates that can be inferred from these multiple equalities.
+ For each reference of a field included into a multiple equality
+ that occurs in a function set a pointer to the multiple equality
+ predicate. Substitute a constant instead of this field if the
+ multiple equality contains a constant.
+ */
DBUG_EXECUTE("where", print_where(conds, "original"););
+ conds= build_equal_items(join->thd, conds, NULL, join_list,
+ &join->cond_equal);
+ DBUG_EXECUTE("where",print_where(conds,"after equal_items"););
+
/* change field = field to field = const for each found field = const */
propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
/*
Remove all instances of item == item
Remove all and-levels where CONST item != CONST item
*/
- DBUG_EXECUTE("where", print_where(conds, "after const change"););
- conds= remove_eq_conds(thd, conds, cond_value);
- DBUG_EXECUTE("info", print_where(conds, "after remove"););
- }
- else
- {
- *cond_value= Item::COND_TRUE;
- select->prep_where= 0;
+ DBUG_EXECUTE("where",print_where(conds,"after const change"););
+ conds= remove_eq_conds(thd, conds, cond_value) ;
+ DBUG_EXECUTE("info",print_where(conds,"after remove"););
}
DBUG_RETURN(conds);
}
@@ -4704,7 +7730,12 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
21))))
{
cond=new_cond;
- cond->fix_fields(thd, 0, &cond);
+ /*
+ Item_func_eq can't be fixed after creation so we do not check
+ cond->fixed, also it do not need tables so we use 0 as second
+ argument.
+ */
+ cond->fix_fields(thd, &cond);
}
thd->insert_id(0); // Clear for next request
}
@@ -4718,10 +7749,20 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
{
cond=new_cond;
- cond->fix_fields(thd, 0, &cond);
+ /*
+ Item_func_eq can't be fixed after creation so we do not check
+ cond->fixed, also it do not need tables so we use 0 as second
+ argument.
+ */
+ cond->fix_fields(thd, &cond);
}
}
}
+ if (cond->const_item())
+ {
+ *cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
+ return (COND*) 0;
+ }
}
else if (cond->const_item())
{
@@ -4801,7 +7842,6 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
return 0;
}
-
/****************************************************************************
Create internal temporary table
****************************************************************************/
@@ -4814,7 +7854,6 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
thd Thread handler
org_field field from which new field will be created
name New field name
- item Item to create a field for
table Temporary table
item !=NULL if item->result_field should point to new field.
This is relevant for how fill_record() is going to work:
@@ -4830,15 +7869,15 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
new_created field
*/
-static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
- const char *name, TABLE *table,
- Item_field *item,
- uint convert_blob_length)
+Field* create_tmp_field_from_field(THD *thd, Field* org_field,
+ const char *name, TABLE *table,
+ Item_field *item, uint convert_blob_length)
{
Field *new_field;
- if (convert_blob_length && org_field->flags & BLOB_FLAG)
- new_field= new Field_varstring(convert_blob_length, org_field->maybe_null(),
+ if (convert_blob_length && (org_field->flags & BLOB_FLAG))
+ new_field= new Field_varstring(convert_blob_length,
+ org_field->maybe_null(),
org_field->field_name, table,
org_field->charset());
else
@@ -4851,8 +7890,9 @@ static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
new_field->field_name= name;
if (org_field->maybe_null() || (item && item->maybe_null))
new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
- if (org_field->type() == FIELD_TYPE_VAR_STRING)
- table->db_create_options|= HA_OPTION_PACK_RECORD;
+ if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
+ org_field->type() == MYSQL_TYPE_VARCHAR)
+ table->s->db_create_options|= HA_OPTION_PACK_RECORD;
}
return new_field;
}
@@ -4881,7 +7921,8 @@ static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
0 on error
new_created field
*/
-static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
+
+static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
Item ***copy_func, bool modify_item,
uint convert_blob_length)
{
@@ -4909,22 +7950,20 @@ static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
if ((type= item->field_type()) == MYSQL_TYPE_DATETIME ||
type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE)
new_field= item->tmp_table_field_from_field_type(table);
- else if (item->max_length/item->collation.collation->mbmaxlen > 255)
- {
- if (convert_blob_length)
- new_field= new Field_varstring(convert_blob_length, maybe_null,
- item->name, table,
- item->collation.collation);
- else
- new_field= new Field_blob(item->max_length, maybe_null, item->name,
- table, item->collation.collation);
- }
+ else if (item->max_length/item->collation.collation->mbmaxlen > 255 &&
+ convert_blob_length)
+ new_field= new Field_varstring(convert_blob_length, maybe_null,
+ item->name, table,
+ item->collation.collation);
else
- new_field= new Field_string(item->max_length, maybe_null, item->name,
- table, item->collation.collation);
+ new_field= item->make_string_field(table);
+ break;
+ case DECIMAL_RESULT:
+ new_field= new Field_new_decimal(item->max_length, maybe_null, item->name,
+ table, item->decimals, item->unsigned_flag);
break;
- case ROW_RESULT:
- default:
+ case ROW_RESULT:
+ default:
// This case should never be choosen
DBUG_ASSERT(0);
new_field= 0; // to satisfy compiler (uninitialized variable)
@@ -4937,6 +7976,36 @@ static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
return new_field;
}
+
+/*
+ Create field for information schema table
+
+ SYNOPSIS
+ create_tmp_field_for_schema()
+ thd Thread handler
+ table Temporary table
+ item Item to create a field for
+
+ RETURN
+ 0 on error
+ new_created field
+*/
+
+Field *create_tmp_field_for_schema(THD *thd, Item *item, TABLE *table)
+{
+ if (item->field_type() == MYSQL_TYPE_VARCHAR)
+ {
+ if (item->max_length > MAX_FIELD_VARCHARLENGTH /
+ item->collation.collation->mbmaxlen)
+ return new Field_blob(item->max_length, item->maybe_null,
+ item->name, table, item->collation.collation);
+ return new Field_varstring(item->max_length, item->maybe_null, item->name,
+ table, item->collation.collation);
+ }
+ return item->tmp_table_field_from_field_type(table);
+}
+
+
/*
Create field for temporary table
@@ -4968,80 +8037,65 @@ static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field,
- bool group, bool modify_item, uint convert_blob_length)
+ bool group, bool modify_item,
+ bool table_cant_handle_bit_fields,
+ uint convert_blob_length)
{
+ Item::Type orig_type= type;
+ Item *orig_item;
+
+ if (type != Item::FIELD_ITEM &&
+ item->real_item()->type() == Item::FIELD_ITEM &&
+ (item->type() != Item::REF_ITEM ||
+ !((Item_ref *) item)->depended_from))
+ {
+ orig_item= item;
+ item= item->real_item();
+ type= Item::FIELD_ITEM;
+ }
switch (type) {
case Item::SUM_FUNC_ITEM:
{
Item_sum *item_sum=(Item_sum*) item;
- bool maybe_null=item_sum->maybe_null;
- switch (item_sum->sum_func()) {
- case Item_sum::AVG_FUNC: /* Place for sum & count */
- if (group)
- return new Field_string(sizeof(double)+sizeof(longlong),
- 0, item->name,table,&my_charset_bin);
- else
- return new Field_double(item_sum->max_length,maybe_null,
- item->name, table, item_sum->decimals);
- case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
- case Item_sum::STD_FUNC:
- if (group)
- return new Field_string(sizeof(double)*2+sizeof(longlong),
- 0, item->name,table,&my_charset_bin);
- else
- return new Field_double(item_sum->max_length, maybe_null,
- item->name,table,item_sum->decimals);
- case Item_sum::UNIQUE_USERS_FUNC:
- return new Field_long(9,maybe_null,item->name,table,1);
- case Item_sum::MIN_FUNC:
- case Item_sum::MAX_FUNC:
- if (item_sum->args[0]->type() == Item::FIELD_ITEM)
- {
- *from_field= ((Item_field*) item_sum->args[0])->field;
- return create_tmp_field_from_field(thd, *from_field, item->name, table,
- NULL, convert_blob_length);
- }
- /* fall through */
- default:
- switch (item_sum->result_type()) {
- case REAL_RESULT:
- return new Field_double(item_sum->max_length,maybe_null,
- item->name,table,item_sum->decimals);
- case INT_RESULT:
- return new Field_longlong(item_sum->max_length,maybe_null,
- item->name,table,item->unsigned_flag);
- case STRING_RESULT:
- if (item_sum->max_length > 255)
- {
- if (convert_blob_length)
- return new Field_varstring(convert_blob_length, maybe_null,
- item->name, table,
- item->collation.collation);
- else
- return new Field_blob(item_sum->max_length, maybe_null, item->name,
- table, item->collation.collation);
- }
- return new Field_string(item_sum->max_length,maybe_null,
- item->name,table,item->collation.collation);
- case ROW_RESULT:
- default:
- // This case should never be choosen
- DBUG_ASSERT(0);
- thd->fatal_error();
- return 0;
- }
- }
- /* We never come here */
+ Field *result= item_sum->create_tmp_field(group, table, convert_blob_length);
+ if (!result)
+ thd->fatal_error();
+ return result;
}
case Item::FIELD_ITEM:
case Item::DEFAULT_VALUE_ITEM:
{
Item_field *field= (Item_field*) item;
- return create_tmp_field_from_field(thd, (*from_field= field->field),
+ bool orig_modify= modify_item;
+ Field *result;
+ if (orig_type == Item::REF_ITEM)
+ modify_item= 0;
+ /*
+ If item have to be able to store NULLs but underlaid field can't do it,
+ create_tmp_field_from_field() can't be used for tmp field creation.
+ */
+ if (field->maybe_null && !field->field->maybe_null())
+ {
+ result= create_tmp_field_from_item(thd, item, table, NULL,
+ modify_item, convert_blob_length);
+ *from_field= field->field;
+ if (result && modify_item)
+ ((Item_field*)item)->result_field= result;
+ }
+ else if (table_cant_handle_bit_fields && field->field->type() == FIELD_TYPE_BIT)
+ result= create_tmp_field_from_item(thd, item, table, copy_func,
+ modify_item, convert_blob_length);
+ else
+ result= create_tmp_field_from_field(thd, (*from_field= field->field),
item->name, table,
- modify_item ? (Item_field*) item : NULL,
+ modify_item ? (Item_field*) item :
+ NULL,
convert_blob_length);
+ if (orig_type == Item::REF_ITEM && orig_modify)
+ ((Item_ref*)orig_item)->set_result_field(result);
+ return result;
}
+ /* Fall through */
case Item::FUNC_ITEM:
case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM:
@@ -5051,6 +8105,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::PROC_ITEM:
case Item::INT_ITEM:
case Item::REAL_ITEM:
+ case Item::DECIMAL_ITEM:
case Item::STRING_ITEM:
case Item::REF_ITEM:
case Item::NULL_ITEM:
@@ -5072,35 +8127,43 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
for send_fields
*/
+#define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128
+#define AVG_STRING_LENGTH_TO_PACK_ROWS 64
+#define RATIO_TO_PACK_ROWS 2
+#define MIN_STRING_LENGTH_TO_PACK_ROWS 10
+
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
- ulong select_options, ha_rows rows_limit,
+ ulonglong select_options, ha_rows rows_limit,
char *table_alias)
{
TABLE *table;
- uint i,field_count,reclength,null_count,null_pack_length,
- hidden_null_count, hidden_null_pack_length, hidden_field_count,
- blob_count,group_null_items;
- bool using_unique_constraint=0;
+ uint i,field_count,null_count,null_pack_length;
+ uint hidden_null_count, hidden_null_pack_length, hidden_field_count;
+ uint blob_count,group_null_items, string_count;
+ uint temp_pool_slot=MY_BIT_NONE;
+ ulong reclength, string_total_length;
+ bool using_unique_constraint= 0;
+ bool use_packed_rows= 0;
bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
char *tmpname,path[FN_REFLEN];
byte *pos,*group_buff;
uchar *null_flags;
- Field **reg_field, **from_field, **blob_field;
+ Field **reg_field, **from_field;
+ uint *blob_field;
Copy_field *copy=0;
KEY *keyinfo;
KEY_PART_INFO *key_part_info;
Item **copy_func;
MI_COLUMNDEF *recinfo;
- uint temp_pool_slot=MY_BIT_NONE;
-
+ uint total_uneven_bit_length= 0;
DBUG_ENTER("create_tmp_table");
DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d",
(int) distinct, (int) save_sum_fields,
(ulong) rows_limit,test(group)));
- statistic_increment(created_tmp_tables, &LOCK_status);
+ statistic_increment(thd->status_var.created_tmp_tables, &LOCK_status);
if (use_temp_pool)
temp_pool_slot = bitmap_set_next(&temp_pool);
@@ -5108,15 +8171,19 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (temp_pool_slot != MY_BIT_NONE) // we got a slot
sprintf(path, "%s_%lx_%i", tmp_file_prefix,
current_pid, temp_pool_slot);
- else // if we run out of slots or we are not using tempool
+ else
+ {
+ /* if we run out of slots or we are not using tempool */
sprintf(path,"%s%lx_%lx_%x", tmp_file_prefix,current_pid,
thd->thread_id, thd->tmp_table++);
+ }
+ /*
+ No need to change table name to lower case as we are only creating
+ MyISAM or HEAP tables here
+ */
fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME);
- if (lower_case_table_names)
- my_casedn_str(files_charset_info, path);
-
if (group)
{
if (!param->quick_group)
@@ -5124,7 +8191,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
{
(*tmp->item)->marker=4; // Store null in key
- if ((*tmp->item)->max_length >= MAX_CHAR_WIDTH)
+ if ((*tmp->item)->max_length >= CONVERT_IF_BIGGER_TO_BLOB)
using_unique_constraint=1;
}
if (param->group_length >= MAX_BLOB_WIDTH)
@@ -5138,7 +8205,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!my_multi_malloc(MYF(MY_WME),
&table,sizeof(*table),
&reg_field, sizeof(Field*)*(field_count+1),
- &blob_field, sizeof(Field*)*(field_count+1),
+ &blob_field, sizeof(uint)*(field_count+1),
&from_field, sizeof(Field*)*field_count,
&copy_func,sizeof(*copy_func)*(param->func_count+1),
&param->keyinfo,sizeof(*param->keyinfo),
@@ -5168,28 +8235,35 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
bzero((char*) reg_field,sizeof(Field*)*(field_count+1));
bzero((char*) from_field,sizeof(Field*)*field_count);
table->field=reg_field;
- table->blob_field= (Field_blob**) blob_field;
- table->real_name=table->path=tmpname;
- table->table_name= table_alias;
+ table->alias= table_alias;
table->reginfo.lock_type=TL_WRITE; /* Will be updated */
table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE;
- table->blob_ptr_size=mi_portable_sizeof_char_ptr;
table->map=1;
- table->tmp_table= TMP_TABLE;
- 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();
table->quick_keys.init();
table->used_keys.init();
table->keys_in_use_for_query.init();
+ table->s= &table->share_not_to_be_used;
+ table->s->blob_field= blob_field;
+ table->s->table_name= table->s->path= tmpname;
+ table->s->db= "";
+ table->s->blob_ptr_size= mi_portable_sizeof_char_ptr;
+ table->s->tmp_table= TMP_TABLE;
+ table->s->db_low_byte_first=1; // True for HEAP and MyISAM
+ table->s->table_charset= param->table_charset;
+ table->s->keys_for_keyread.init();
+ table->s->keys_in_use.init();
+ /* For easier error reporting */
+ table->s->table_cache_key= (char*) (table->s->db= "");
+
+
/* Calculate which type of fields we will store in the temporary table */
- reclength=blob_count=null_count=hidden_null_count=group_null_items=0;
+ reclength= string_total_length= 0;
+ blob_count= string_count= null_count= hidden_null_count= group_null_items= 0;
param->using_indirect_summary_function=0;
List_iterator_fast<Item> li(fields);
@@ -5225,17 +8299,25 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
Field *new_field=
create_tmp_field(thd, table, arg, arg->type(), &copy_func,
tmp_from_field, group != 0,not_all_columns,
+ group || distinct,
param->convert_blob_length);
if (!new_field)
goto err; // Should be OOM
tmp_from_field++;
- *(reg_field++)= new_field;
reclength+=new_field->pack_length();
if (new_field->flags & BLOB_FLAG)
{
- *blob_field++= new_field;
+ *blob_field++= (uint) (reg_field - table->field);
blob_count++;
}
+ new_field->field_index= (uint) (reg_field - table->field);
+ *(reg_field++)= new_field;
+ if (new_field->real_type() == MYSQL_TYPE_STRING ||
+ new_field->real_type() == MYSQL_TYPE_VARCHAR)
+ {
+ string_count++;
+ string_total_length+= new_field->pack_length();
+ }
thd->change_item_tree(argp, new Item_field(new_field));
if (!(new_field->flags & NOT_NULL_FLAG))
{
@@ -5246,6 +8328,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*/
(*argp)->maybe_null=1;
}
+ new_field->query_id= thd->query_id;
}
}
}
@@ -5261,10 +8344,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
We here distinguish between UNION and multi-table-updates by the fact
that in the later case group is set to the row pointer.
*/
- Field *new_field= create_tmp_field(thd, table, item, type, &copy_func,
- tmp_from_field, group != 0,
- not_all_columns || group !=0,
- param->convert_blob_length);
+ Field *new_field= (param->schema_table) ?
+ create_tmp_field_for_schema(thd, item, table) :
+ create_tmp_field(thd, table, item, type, &copy_func,
+ tmp_from_field, group != 0,
+ not_all_columns || group != 0, 0,
+ param->convert_blob_length);
+
if (!new_field)
{
if (thd->is_fatal_error)
@@ -5277,9 +8363,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
reclength+=new_field->pack_length();
if (!(new_field->flags & NOT_NULL_FLAG))
null_count++;
+ if (new_field->type() == FIELD_TYPE_BIT)
+ total_uneven_bit_length+= new_field->field_length & 7;
if (new_field->flags & BLOB_FLAG)
{
- *blob_field++= new_field;
+ *blob_field++= (uint) (reg_field - table->field);
blob_count++;
}
if (item->marker == 4 && item->maybe_null)
@@ -5287,6 +8375,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
group_null_items++;
new_field->flags|= GROUP_FLAG;
}
+ new_field->query_id= thd->query_id;
+ new_field->field_index= (uint) (reg_field - table->field);
*(reg_field++) =new_field;
}
if (!--hidden_field_count)
@@ -5299,9 +8389,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
/* If result table is small; use a heap */
if (blob_count || using_unique_constraint ||
(select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
- OPTION_BIG_TABLES ||(select_options & TMP_TABLE_FORCE_MYISAM))
+ OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM))
{
- table->file=get_new_handler(table,table->db_type=DB_TYPE_MYISAM);
+ table->file=get_new_handler(table,table->s->db_type= DB_TYPE_MYISAM);
if (group &&
(param->group_parts > table->file->max_key_parts() ||
param->group_length > table->file->max_key_length()))
@@ -5309,13 +8399,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
else
{
- table->file=get_new_handler(table,table->db_type=DB_TYPE_HEAP);
+ table->file=get_new_handler(table,table->s->db_type= DB_TYPE_HEAP);
}
if (!using_unique_constraint)
reclength+= group_null_items; // null flag is stored separately
- table->blob_fields=blob_count;
+ table->s->blob_fields= blob_count;
if (blob_count == 0)
{
/* We need to ensure that first byte is not 0 for the delete link */
@@ -5325,20 +8415,27 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_count++;
}
hidden_null_pack_length=(hidden_null_count+7)/8;
- null_pack_length=hidden_null_count+(null_count+7)/8;
+ null_pack_length= hidden_null_count +
+ (null_count + total_uneven_bit_length + 7) / 8;
reclength+=null_pack_length;
if (!reclength)
reclength=1; // Dummy select
+ /* Use packed rows if there is blobs or a lot of space to gain */
+ if (blob_count ||
+ string_total_length >= STRING_TOTAL_LENGTH_TO_PACK_ROWS &&
+ (reclength / string_total_length <= RATIO_TO_PACK_ROWS ||
+ string_total_length / string_count >= AVG_STRING_LENGTH_TO_PACK_ROWS))
+ use_packed_rows= 1;
- table->fields=field_count;
- table->reclength=reclength;
+ table->s->fields= field_count;
+ table->s->reclength= reclength;
{
uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1);
- table->rec_buff_length=alloc_length;
+ table->s->rec_buff_length= alloc_length;
if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
goto err;
table->record[1]= table->record[0]+alloc_length;
- table->default_values= table->record[1]+alloc_length;
+ table->s->default_values= table->record[1]+alloc_length;
}
copy_func[0]=0; // End marker
@@ -5354,8 +8451,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
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;
+ table->s->null_fields= null_count+ hidden_null_count;
+ table->s->null_bytes= null_pack_length;
}
null_count= (blob_count == 0) ? 1 : 0;
hidden_field_count=param->hidden_field_count;
@@ -5390,6 +8487,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
else
field->move_field((char*) pos,(uchar*) 0,0);
+ if (field->type() == FIELD_TYPE_BIT)
+ {
+ /* We have to reserve place for extra bits among null bits */
+ ((Field_bit*) field)->set_bit_ptr(null_flags + null_count / 8,
+ null_count & 7);
+ null_count+= (field->field_length & 7);
+ }
field->reset();
if (from_field[i])
{ /* Not a table Item */
@@ -5403,10 +8507,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
recinfo->length=length;
if (field->flags & BLOB_FLAG)
recinfo->type= (int) FIELD_BLOB;
- else if (!field->zero_pack() &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING) &&
- length >= 10 && blob_count)
+ else if (use_packed_rows &&
+ field->real_type() == MYSQL_TYPE_STRING &&
+ length >= MIN_STRING_LENGTH_TO_PACK_ROWS)
recinfo->type=FIELD_SKIP_ENDSPACE;
else
recinfo->type=FIELD_NORMAL;
@@ -5414,30 +8517,30 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_count=(null_count+7) & ~7; // move to next byte
// fix table name in field entry
- field->table_name= table->table_name;
+ field->table_name= &table->alias;
}
param->copy_field_end=copy;
param->recinfo=recinfo;
- store_record(table,default_values); // Make empty default record
+ store_record(table,s->default_values); // Make empty default record
if (thd->variables.tmp_table_size == ~(ulong) 0) // No limit
- table->max_rows= ~(ha_rows) 0;
+ table->s->max_rows= ~(ha_rows) 0;
else
- table->max_rows=(((table->db_type == DB_TYPE_HEAP) ?
- min(thd->variables.tmp_table_size,
- thd->variables.max_heap_table_size) :
- thd->variables.tmp_table_size)/ table->reclength);
- set_if_bigger(table->max_rows,1); // For dummy start options
- keyinfo=param->keyinfo;
+ table->s->max_rows= (((table->s->db_type == DB_TYPE_HEAP) ?
+ min(thd->variables.tmp_table_size,
+ thd->variables.max_heap_table_size) :
+ thd->variables.tmp_table_size)/ table->s->reclength);
+ set_if_bigger(table->s->max_rows,1); // For dummy start options
+ keyinfo= param->keyinfo;
if (group)
{
DBUG_PRINT("info",("Creating group key in temporary table"));
table->group=group; /* Table is grouped by key */
param->group_buff=group_buff;
- table->keys=1;
- table->uniques= test(using_unique_constraint);
+ table->s->keys=1;
+ table->s->uniques= test(using_unique_constraint);
table->key_info=keyinfo;
keyinfo->key_part=key_part_info;
keyinfo->flags=HA_NOSAME;
@@ -5445,6 +8548,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->key_length=0;
keyinfo->rec_per_key=0;
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
+ keyinfo->name= (char*) "group_key";
for (; group ; group=group->next,key_part_info++)
{
Field *field=(*group->item)->get_tmp_table_field();
@@ -5452,35 +8556,40 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
key_part_info->null_bit=0;
key_part_info->field= field;
key_part_info->offset= field->offset();
- key_part_info->length= (uint16) field->pack_length();
+ key_part_info->length= (uint16) field->key_length();
key_part_info->type= (uint8) field->key_type();
key_part_info->key_type =
((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
- (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT) ?
+ (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
+ (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
0 : FIELDFLAG_BINARY;
if (!using_unique_constraint)
{
group->buff=(char*) group_buff;
- if (!(group->field=field->new_field(thd->mem_root,table)))
+ if (!(group->field= field->new_key_field(thd->mem_root,table,
+ (char*) group_buff +
+ test(maybe_null),
+ field->null_ptr,
+ field->null_bit)))
goto err; /* purecov: inspected */
if (maybe_null)
{
/*
- To be able to group on NULL, we reserve place in group_buff
- for the NULL flag just before the column.
+ To be able to group on NULL, we reserved place in group_buff
+ for the NULL flag just before the column. (see above).
The field data is after this flag.
- The NULL flag is updated by 'end_update()' and 'end_write()'
+ The NULL flag is updated in 'end_update()' and 'end_write()'
*/
keyinfo->flags|= HA_NULL_ARE_EQUAL; // def. that NULL == NULL
key_part_info->null_bit=field->null_bit;
key_part_info->null_offset= (uint) (field->null_ptr -
(uchar*) table->record[0]);
- group->field->move_field((char*) ++group->buff);
- group_buff++;
+ group->buff++; // Pointer to field data
+ group_buff++; // Skipp null flag
}
- else
- group->field->move_field((char*) group_buff);
- group_buff+= key_part_info->length;
+ /* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */
+ key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL;
+ group_buff+= group->field->pack_length();
}
keyinfo->key_length+= key_part_info->length;
}
@@ -5499,14 +8608,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_pack_length-=hidden_null_pack_length;
keyinfo->key_parts= ((field_count-param->hidden_field_count)+
test(null_pack_length));
- set_if_smaller(table->max_rows, rows_limit);
+ set_if_smaller(table->s->max_rows, rows_limit);
param->end_write_records= rows_limit;
- table->distinct=1;
- table->keys=1;
+ table->distinct= 1;
+ table->s->keys= 1;
if (blob_count)
{
using_unique_constraint=1;
- table->uniques=1;
+ table->s->uniques= 1;
}
if (!(key_part_info= (KEY_PART_INFO*)
sql_calloc((keyinfo->key_parts)*sizeof(KEY_PART_INFO))))
@@ -5515,7 +8624,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->key_part=key_part_info;
keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
keyinfo->key_length=(uint16) reclength;
- keyinfo->name=(char*) "tmp";
+ keyinfo->name= (char*) "distinct_key";
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
keyinfo->rec_per_key=0;
if (null_pack_length)
@@ -5545,14 +8654,15 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
key_part_info->type= (uint8) (*reg_field)->key_type();
key_part_info->key_type =
((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
- (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT) ?
+ (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
+ (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
0 : FIELDFLAG_BINARY;
}
}
if (thd->is_fatal_error) // If end of memory
goto err; /* purecov: inspected */
- table->db_record_offset=1;
- if (table->db_type == DB_TYPE_MYISAM)
+ table->s->db_record_offset= 1;
+ if (table->s->db_type == DB_TYPE_MYISAM)
{
if (create_myisam_tmp_table(table,param,select_options))
goto err;
@@ -5561,21 +8671,128 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
DBUG_RETURN(table);
err:
- /*
- Hack to ensure that free_blobs() doesn't fail if blob_field is not yet
- complete
- */
- *table->blob_field= 0;
free_tmp_table(thd,table); /* purecov: inspected */
bitmap_clear_bit(&temp_pool, temp_pool_slot);
DBUG_RETURN(NULL); /* purecov: inspected */
}
+/****************************************************************************/
+
+/*
+ Create a reduced TABLE object with properly set up Field list from a
+ list of field definitions.
+
+ SYNOPSIS
+ create_virtual_tmp_table()
+ thd connection handle
+ field_list list of column definitions
+
+ DESCRIPTION
+ The created table doesn't have a table handler assotiated with
+ it, has no keys, no group/distinct, no copy_funcs array.
+ The sole purpose of this TABLE object is to use the power of Field
+ class to read/write data to/from table->record[0]. Then one can store
+ the record in any container (RB tree, hash, etc).
+ The table is created in THD mem_root, so are the table's fields.
+ Consequently, if you don't BLOB fields, you don't need to free it.
+
+ RETURN
+ 0 if out of memory, TABLE object in case of success
+*/
+
+TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
+{
+ uint field_count= field_list.elements;
+ Field **field;
+ create_field *cdef; /* column definition */
+ uint record_length= 0;
+ uint null_count= 0; /* number of columns which may be null */
+ uint null_pack_length; /* NULL representation array length */
+ TABLE_SHARE *s;
+ /* Create the table and list of all fields */
+ TABLE *table= (TABLE*) thd->calloc(sizeof(*table));
+ field= (Field**) thd->alloc((field_count + 1) * sizeof(Field*));
+ if (!table || !field)
+ return 0;
+
+ table->field= field;
+ table->s= s= &table->share_not_to_be_used;
+ s->fields= field_count;
+
+ /* Create all fields and calculate the total length of record */
+ List_iterator_fast<create_field> it(field_list);
+ while ((cdef= it++))
+ {
+ *field= make_field(0, cdef->length,
+ (uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
+ f_maybe_null(cdef->pack_flag) ? 1 : 0,
+ cdef->pack_flag, cdef->sql_type, cdef->charset,
+ cdef->geom_type, cdef->unireg_check,
+ cdef->interval, cdef->field_name, table);
+ if (!*field)
+ goto error;
+ record_length+= (**field).pack_length();
+ if (! ((**field).flags & NOT_NULL_FLAG))
+ ++null_count;
+ ++field;
+ }
+ *field= NULL; /* mark the end of the list */
+
+ null_pack_length= (null_count + 7)/8;
+ s->reclength= record_length + null_pack_length;
+ s->rec_buff_length= ALIGN_SIZE(s->reclength + 1);
+ table->record[0]= (byte*) thd->alloc(s->rec_buff_length);
+ if (!table->record[0])
+ goto error;
+
+ if (null_pack_length)
+ {
+ table->null_flags= (uchar*) table->record[0];
+ s->null_fields= null_count;
+ s->null_bytes= null_pack_length;
+ }
+
+ table->in_use= thd; /* field->reset() may access table->in_use */
+ {
+ /* Set up field pointers */
+ byte *null_pos= table->record[0];
+ byte *field_pos= null_pos + s->null_bytes;
+ uint null_bit= 1;
+
+ for (field= table->field; *field; ++field)
+ {
+ Field *cur_field= *field;
+ if ((cur_field->flags & NOT_NULL_FLAG))
+ cur_field->move_field((char*) field_pos);
+ else
+ {
+ cur_field->move_field((char*) field_pos, (uchar*) null_pos, null_bit);
+ null_bit<<= 1;
+ if (null_bit == (1 << 8))
+ {
+ ++null_pos;
+ null_bit= 1;
+ }
+ }
+ cur_field->reset();
+
+ field_pos+= cur_field->pack_length();
+ }
+ }
+ return table;
+error:
+ for (field= table->field; *field; ++field)
+ delete *field; /* just invokes field destructor */
+ return 0;
+}
+
+
static bool open_tmp_table(TABLE *table)
{
int error;
- if ((error=table->file->ha_open(table->real_name,O_RDWR,HA_OPEN_TMP_TABLE)))
+ if ((error=table->file->ha_open(table->s->table_name,O_RDWR,
+ HA_OPEN_TMP_TABLE)))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
table->db_stat=0;
@@ -5593,9 +8810,9 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
MI_KEYDEF keydef;
MI_UNIQUEDEF uniquedef;
KEY *keyinfo=param->keyinfo;
-
DBUG_ENTER("create_myisam_tmp_table");
- if (table->keys)
+
+ if (table->s->keys)
{ // Get keys for ni_create
bool using_unique_constraint=0;
HA_KEYSEG *seg= (HA_KEYSEG*) sql_calloc(sizeof(*seg) *
@@ -5605,11 +8822,11 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
if (keyinfo->key_length >= table->file->max_key_length() ||
keyinfo->key_parts > table->file->max_key_parts() ||
- table->uniques)
+ table->s->uniques)
{
/* Can't create a key; Make a unique constraint instead of a key */
- table->keys=0;
- table->uniques=1;
+ table->s->keys= 0;
+ table->s->uniques= 1;
using_unique_constraint=1;
bzero((char*) &uniquedef,sizeof(uniquedef));
uniquedef.keysegs=keyinfo->key_parts;
@@ -5621,7 +8838,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
param->recinfo->type= FIELD_CHECK;
param->recinfo->length=MI_UNIQUE_HASH_LENGTH;
param->recinfo++;
- table->reclength+=MI_UNIQUE_HASH_LENGTH;
+ table->s->reclength+=MI_UNIQUE_HASH_LENGTH;
}
else
{
@@ -5642,21 +8859,18 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
{
seg->type=
((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
- HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT);
- seg->bit_start=seg->length - table->blob_ptr_size;
+ HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
+ seg->bit_start= (uint8)(field->pack_length() - table->s->blob_ptr_size);
seg->flag= HA_BLOB_PART;
seg->length=0; // Whole blob in unique constraint
}
else
{
- seg->type=
- ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
- HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT);
- if (!(field->flags & ZEROFILL_FLAG) &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING) &&
+ seg->type= keyinfo->key_part[i].type;
+ /* Tell handler if it can do suffic space compression */
+ if (field->real_type() == MYSQL_TYPE_STRING &&
keyinfo->key_part[i].length > 4)
- seg->flag|=HA_SPACE_PACK;
+ seg->flag|= HA_SPACE_PACK;
}
if (!(field->flags & NOT_NULL_FLAG))
{
@@ -5665,7 +8879,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
/*
We are using a GROUP BY on something that contains NULL
In this case we have to tell MyISAM that two NULL should
- on INSERT be compared as equal
+ on INSERT be regarded at the same value
*/
if (!using_unique_constraint)
keydef.flag|= HA_NULL_ARE_EQUAL;
@@ -5679,10 +8893,10 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
OPTION_BIG_TABLES)
create_info.data_file_length= ~(ulonglong) 0;
- if ((error=mi_create(table->real_name,table->keys,&keydef,
+ if ((error=mi_create(table->s->table_name,table->s->keys,&keydef,
(uint) (param->recinfo-param->start_recinfo),
param->start_recinfo,
- table->uniques, &uniquedef,
+ table->s->uniques, &uniquedef,
&create_info,
HA_CREATE_TMP_TABLE)))
{
@@ -5690,8 +8904,9 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
table->db_stat=0;
goto err;
}
- statistic_increment(created_tmp_disk_tables, &LOCK_status);
- table->db_record_offset=1;
+ statistic_increment(table->in_use->status_var.created_tmp_disk_tables,
+ &LOCK_status);
+ table->s->db_record_offset= 1;
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
@@ -5703,7 +8918,7 @@ free_tmp_table(THD *thd, TABLE *entry)
{
const char *save_proc_info;
DBUG_ENTER("free_tmp_table");
- DBUG_PRINT("enter",("table: %s",entry->table_name));
+ DBUG_PRINT("enter",("table: %s",entry->alias));
save_proc_info=thd->proc_info;
thd->proc_info="removing tmp table";
@@ -5719,8 +8934,9 @@ free_tmp_table(THD *thd, TABLE *entry)
here and we have to ensure that delete_table gets the table name in
the original case.
*/
- if (!(test_flags & TEST_KEEP_TMP_TABLES) || entry->db_type == DB_TYPE_HEAP)
- entry->file->delete_table(entry->real_name);
+ if (!(test_flags & TEST_KEEP_TMP_TABLES) ||
+ entry->s->db_type == DB_TYPE_HEAP)
+ entry->file->delete_table(entry->s->table_name);
delete entry->file;
}
@@ -5750,14 +8966,15 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
int write_err;
DBUG_ENTER("create_myisam_from_heap");
- if (table->db_type != DB_TYPE_HEAP || error != HA_ERR_RECORD_FILE_FULL)
+ if (table->s->db_type != DB_TYPE_HEAP || error != HA_ERR_RECORD_FILE_FULL)
{
table->file->print_error(error,MYF(0));
DBUG_RETURN(1);
}
new_table= *table;
- new_table.db_type=DB_TYPE_MYISAM;
- if (!(new_table.file=get_new_handler(&new_table,DB_TYPE_MYISAM)))
+ new_table.s= &new_table.share_not_to_be_used;
+ new_table.s->db_type= DB_TYPE_MYISAM;
+ if (!(new_table.file= get_new_handler(&new_table,DB_TYPE_MYISAM)))
DBUG_RETURN(1); // End of memory
save_proc_info=thd->proc_info;
@@ -5807,13 +9024,15 @@ 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->ha_rnd_end();
(void) table->file->close();
- (void) table->file->delete_table(table->real_name);
+ (void) table->file->delete_table(table->s->table_name);
delete table->file;
table->file=0;
- *table =new_table;
+ *table= new_table;
+ table->s= &table->share_not_to_be_used;
table->file->change_table_ptr(table);
- thd->proc_info= (!strcmp(save_proc_info,"Copying to tmp table") ?
- "Copying to tmp table on disk" : save_proc_info);
+ if (save_proc_info)
+ thd->proc_info= (!strcmp(save_proc_info,"Copying to tmp table") ?
+ "Copying to tmp table on disk" : save_proc_info);
DBUG_RETURN(0);
err:
@@ -5822,7 +9041,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
(void) table->file->ha_rnd_end();
(void) new_table.file->close();
err1:
- new_table.file->delete_table(new_table.real_name);
+ new_table.file->delete_table(new_table.s->table_name);
delete new_table.file;
err2:
thd->proc_info=save_proc_info;
@@ -5830,46 +9049,33 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
}
-/****************************************************************************
- Make a join of all tables and write it on socket or to table
- Return: 0 if ok
- 1 if error is sent
- -1 if error should be sent
-****************************************************************************/
+/*
+ SYNOPSIS
+ setup_end_select_func()
+ join join to setup the function for.
-static int
-do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
-{
- int error= 0;
- JOIN_TAB *join_tab;
- int (*end_select)(JOIN *, struct st_join_table *,bool);
- DBUG_ENTER("do_select");
+ DESCRIPTION
+ Rows produced by a join sweep may end up in a temporary table or be sent
+ to a client. Setup the function of the nested loop join algorithm which
+ handles final fully constructed and matched records.
- join->procedure=procedure;
- /*
- Tell the client how many fields there are in a row
- */
- if (!table)
- join->result->send_fields(*fields,1);
- else
- {
- VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
- empty_record(table);
- }
- join->tmp_table= table; /* Save for easy recursion */
- join->fields= fields;
+ RETURN
+ end_select function to use. This function can't fail.
+*/
+static Next_select_func setup_end_select_func(JOIN *join)
+{
+ TABLE *table= join->tmp_table;
+ Next_select_func end_select;
/* Set up select_end */
if (table)
{
if (table->group && join->tmp_table_param.sum_func_count)
{
- if (table->keys)
+ if (table->s->keys)
{
DBUG_PRINT("info",("Using end_update"));
end_select=end_update;
- if (!table->file->inited)
- table->file->ha_index_init(0);
}
else
{
@@ -5890,42 +9096,88 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
}
else
{
- if (join->sort_and_group || (join->procedure &&
- join->procedure->flags & PROC_GROUP))
- end_select=end_send_group;
+ /* Test if data is accessed via QUICK_GROUP_MIN_MAX_SELECT. */
+ bool is_using_quick_group_min_max_select=
+ (join->join_tab->select && join->join_tab->select->quick &&
+ (join->join_tab->select->quick->get_type() ==
+ QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX));
+
+ if ((join->sort_and_group ||
+ (join->procedure && join->procedure->flags & PROC_GROUP)) &&
+ !is_using_quick_group_min_max_select)
+ end_select= end_send_group;
else
- end_select=end_send;
+ end_select= end_send;
}
- join->join_tab[join->tables-1].next_select=end_select;
+ return end_select;
+}
+
+
+/****************************************************************************
+ Make a join of all tables and write it on socket or to table
+ Return: 0 if ok
+ 1 if error is sent
+ -1 if error should be sent
+****************************************************************************/
+
+static int
+do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
+{
+ int rc= 0;
+ enum_nested_loop_state error= NESTED_LOOP_OK;
+ JOIN_TAB *join_tab;
+ DBUG_ENTER("do_select");
+
+ join->procedure=procedure;
+ join->tmp_table= table; /* Save for easy recursion */
+ join->fields= fields;
+
+ if (table)
+ {
+ VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
+ empty_record(table);
+ if (table->group && join->tmp_table_param.sum_func_count &&
+ table->s->keys && !table->file->inited)
+ table->file->ha_index_init(0);
+ }
+ /* Set up select_end */
+ join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
join_tab=join->join_tab+join->const_tables;
join->send_records=0;
if (join->tables == join->const_tables)
{
/*
- HAVING will be chcked after processing aggregate functions,
+ HAVING will be checked after processing aggregate functions,
But WHERE should checkd here (we alredy have read tables)
*/
if (!join->conds || join->conds->val_int())
{
- if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
- error=(*end_select)(join,join_tab,1);
+ Next_select_func end_select= join->join_tab[join->tables-1].next_select;
+ error= (*end_select)(join,join_tab,0);
+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_QUERY_LIMIT)
+ error= (*end_select)(join,join_tab,1);
}
else if (join->send_row_on_empty_set())
- error= join->result->send_data(*join->fields);
+ rc= join->result->send_data(*join->fields);
}
else
{
error= sub_select(join,join_tab,0);
- if (error >= 0)
+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
error= sub_select(join,join_tab,1);
- if (error == -3)
- error= 0; /* select_limit used */
+ if (error == NESTED_LOOP_QUERY_LIMIT)
+ error= NESTED_LOOP_OK; /* select_limit used */
}
+ if (error == NESTED_LOOP_NO_MORE_ROWS)
+ error= NESTED_LOOP_OK;
- if (error >= 0)
+ if (error == NESTED_LOOP_OK)
{
- error=0;
+ /*
+ Sic: this branch works even if rc != 0, e.g. when
+ send_data above returns an error.
+ */
if (!table) // If sending data to client
{
/*
@@ -5934,152 +9186,439 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
*/
join->join_free(0); // Unlock all cursors
if (join->result->send_eof())
- error= 1; // Don't send error
+ rc= 1; // Don't send error
}
DBUG_PRINT("info",("%ld records output",join->send_records));
}
+ else
+ rc= -1;
if (table)
{
- int tmp;
+ int tmp, new_errno= 0;
if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
{
DBUG_PRINT("error",("extra(HA_EXTRA_NO_CACHE) failed"));
- my_errno= tmp;
- error= -1;
+ new_errno= tmp;
}
if ((tmp=table->file->ha_index_or_rnd_end()))
{
DBUG_PRINT("error",("ha_index_or_rnd_end() failed"));
- my_errno= tmp;
- error= -1;
+ new_errno= tmp;
}
- if (error == -1)
- table->file->print_error(my_errno,MYF(0));
+ if (new_errno)
+ table->file->print_error(new_errno,MYF(0));
}
#ifndef DBUG_OFF
- if (error)
+ if (rc)
{
DBUG_PRINT("error",("Error: do_select() failed"));
}
#endif
- DBUG_RETURN(join->thd->net.report_error ? -1 : error);
+ DBUG_RETURN(join->thd->net.report_error ? -1 : rc);
}
-static int
+static enum_nested_loop_state
sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
- int error;
+ enum_nested_loop_state rc;
if (end_of_records)
{
- if ((error=flush_cached_records(join,join_tab,FALSE)) < 0)
- return error; /* purecov: inspected */
- return sub_select(join,join_tab,end_of_records);
+ rc= flush_cached_records(join,join_tab,FALSE);
+ if (rc == NESTED_LOOP_OK || rc == NESTED_LOOP_NO_MORE_ROWS)
+ rc= sub_select(join,join_tab,end_of_records);
+ return rc;
}
if (join->thd->killed) // If aborted by user
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
- return -2; /* purecov: inspected */
+ join->thd->send_kill_message();
+ return NESTED_LOOP_KILLED; /* purecov: inspected */
}
if (join_tab->use_quick != 2 || test_if_quick_select(join_tab) <= 0)
{
if (!store_record_in_cache(&join_tab->cache))
- return 0; // There is more room in cache
+ return NESTED_LOOP_OK; // There is more room in cache
return flush_cached_records(join,join_tab,FALSE);
}
- if ((error=flush_cached_records(join,join_tab,TRUE)) < 0)
- return error; /* purecov: inspected */
- return sub_select(join,join_tab,end_of_records); /* Use ordinary select */
+ rc= flush_cached_records(join, join_tab, TRUE);
+ if (rc == NESTED_LOOP_OK || rc == NESTED_LOOP_NO_MORE_ROWS)
+ rc= sub_select(join, join_tab, end_of_records);
+ return rc;
}
+/*
+ Retrieve records ends with a given beginning from the result of a join
+
+ SYNPOSIS
+ sub_select()
+ join pointer to the structure providing all context info for the query
+ join_tab the first next table of the execution plan to be retrieved
+ end_records true when we need to perform final steps of retrival
-static int
+ DESCRIPTION
+ For a given partial join record consisting of records from the tables
+ preceding the table join_tab in the execution plan, the function
+ retrieves all matching full records from the result set and
+ send them to the result set stream.
+
+ NOTES
+ The function effectively implements the final (n-k) nested loops
+ of nested loops join algorithm, where k is the ordinal number of
+ the join_tab table and n is the total number of tables in the join query.
+ It performs nested loops joins with all conjunctive predicates from
+ the where condition pushed as low to the tables as possible.
+ E.g. for the query
+ SELECT * FROM t1,t2,t3
+ WHERE t1.a=t2.a AND t2.b=t3.b AND t1.a BETWEEN 5 AND 9
+ the predicate (t1.a BETWEEN 5 AND 9) will be pushed to table t1,
+ given the selected plan prescribes to nest retrievals of the
+ joined tables in the following order: t1,t2,t3.
+ A pushed down predicate are attached to the table which it pushed to,
+ at the field select_cond.
+ When executing a nested loop of level k the function runs through
+ the rows of 'join_tab' and for each row checks the pushed condition
+ attached to the table.
+ If it is false the function moves to the next row of the
+ table. If the condition is true the function recursively executes (n-k-1)
+ remaining embedded nested loops.
+ The situation becomes more complicated if outer joins are involved in
+ the execution plan. In this case the pushed down predicates can be
+ checked only at certain conditions.
+ Suppose for the query
+ SELECT * FROM t1 LEFT JOIN (t2,t3) ON t3.a=t1.a
+ WHERE t1>2 AND (t2.b>5 OR t2.b IS NULL)
+ the optimizer has chosen a plan with the table order t1,t2,t3.
+ The predicate P1=t1>2 will be pushed down to the table t1, while the
+ predicate P2=(t2.b>5 OR t2.b IS NULL) will be attached to the table
+ t2. But the second predicate can not be unconditionally tested right
+ after a row from t2 has been read. This can be done only after the
+ first row with t3.a=t1.a has been encountered.
+ Thus, the second predicate P2 is supplied with a guarded value that are
+ stored in the field 'found' of the first inner table for the outer join
+ (table t2). When the first row with t3.a=t1.a for the current row
+ of table t1 appears, the value becomes true. For now on the predicate
+ is evaluated immediately after the row of table t2 has been read.
+ When the first row with t3.a=t1.a has been encountered all
+ conditions attached to the inner tables t2,t3 must be evaluated.
+ Only when all of them are true the row is sent to the output stream.
+ If not, the function returns to the lowest nest level that has a false
+ attached condition.
+ The predicates from on expressions are also pushed down. If in the
+ the above example the on expression were (t3.a=t1.a AND t2.a=t1.a),
+ then t1.a=t2.a would be pushed down to table t2, and without any
+ guard.
+ If after the run through all rows of table t2, the first inner table
+ for the outer join operation, it turns out that no matches are
+ found for the current row of t1, then current row from table t1
+ is complemented by nulls for t2 and t3. Then the pushed down predicates
+ are checked for the composed row almost in the same way as it had
+ been done for the first row with a match. The only difference is
+ the predicates from on expressions are not checked.
+
+ IMPLEMENTATION
+ The function forms output rows for a current partial join of k
+ tables tables recursively.
+ For each partial join record ending with a certain row from
+ join_tab it calls sub_select that builds all possible matching
+ tails from the result set.
+ To be able check predicates conditionally items of the class
+ Item_func_trig_cond are employed.
+ An object of this class is constructed from an item of class COND
+ and a pointer to a guarding boolean variable.
+ When the value of the guard variable is true the value of the object
+ is the same as the value of the predicate, otherwise it's just returns
+ true.
+ To carry out a return to a nested loop level of join table t the pointer
+ to t is remembered in the field 'return_tab' of the join structure.
+ Consider the following query:
+ SELECT * FROM t1,
+ LEFT JOIN
+ (t2, t3 LEFT JOIN (t4,t5) ON t5.a=t3.a)
+ ON t4.a=t2.a
+ WHERE (t2.b=5 OR t2.b IS NULL) AND (t4.b=2 OR t4.b IS NULL)
+ Suppose the chosen execution plan dictates the order t1,t2,t3,t4,t5
+ and suppose for a given joined rows from tables t1,t2,t3 there are
+ no rows in the result set yet.
+ When first row from t5 that satisfies the on condition
+ t5.a=t3.a is found, the pushed down predicate t4.b=2 OR t4.b IS NULL
+ becomes 'activated', as well the predicate t4.a=t2.a. But
+ the predicate (t2.b=5 OR t2.b IS NULL) can not be checked until
+ t4.a=t2.a becomes true.
+ In order not to re-evaluate the predicates that were already evaluated
+ as attached pushed down predicates, a pointer to the the first
+ most inner unmatched table is maintained in join_tab->first_unmatched.
+ Thus, when the first row from t5 with t5.a=t3.a is found
+ this pointer for t5 is changed from t4 to t2.
+
+ STRUCTURE NOTES
+ join_tab->first_unmatched points always backwards to the first inner
+ table of the embedding nested join, if any.
+
+ RETURN
+ return one of enum_nested_loop_state, except NESTED_LOOP_NO_MORE_ROWS.
+*/
+
+static enum_nested_loop_state
sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
-
join_tab->table->null_row=0;
if (end_of_records)
return (*join_tab->next_select)(join,join_tab+1,end_of_records);
- /* Cache variables for faster loop */
int error;
- bool found=0;
- COND *on_expr=join_tab->on_expr, *select_cond=join_tab->select_cond;
+ enum_nested_loop_state rc;
my_bool *report_error= &(join->thd->net.report_error);
+ READ_RECORD *info= &join_tab->read_record;
- if (!(error=(*join_tab->read_first_record)(join_tab)))
+ if (join->resume_nested_loop)
{
- bool not_exists_optimize= join_tab->table->reginfo.not_exists_optimize;
- bool not_used_in_distinct=join_tab->not_used_in_distinct;
- ha_rows found_records=join->found_records;
- READ_RECORD *info= &join_tab->read_record;
+ /* If not the last table, plunge down the nested loop */
+ if (join_tab < join->join_tab + join->tables - 1)
+ rc= (*join_tab->next_select)(join, join_tab + 1, 0);
+ else
+ {
+ join->resume_nested_loop= FALSE;
+ rc= NESTED_LOOP_OK;
+ }
+ }
+ else
+ {
+ join->return_tab= join_tab;
+
+ if (join_tab->last_inner)
+ {
+ /* join_tab is the first inner table for an outer join operation. */
+ /* Set initial state of guard variables for this table.*/
+ join_tab->found=0;
+ join_tab->not_null_compl= 1;
+
+ /* Set first_unmatched for the last inner table of this group */
+ join_tab->last_inner->first_unmatched= join_tab;
+ }
join->thd->row_count= 0;
- do
+
+ error= (*join_tab->read_first_record)(join_tab);
+ rc= evaluate_join_record(join, join_tab, error, report_error);
+ }
+
+ while (rc == NESTED_LOOP_OK)
+ {
+ error= info->read_record(info);
+ rc= evaluate_join_record(join, join_tab, error, report_error);
+ }
+
+ if (rc == NESTED_LOOP_NO_MORE_ROWS &&
+ join_tab->last_inner && !join_tab->found)
+ rc= evaluate_null_complemented_join_record(join, join_tab);
+
+ if (rc == NESTED_LOOP_NO_MORE_ROWS)
+ rc= NESTED_LOOP_OK;
+ return rc;
+}
+
+
+/*
+ Process one record of the nested loop join.
+
+ DESCRIPTION
+ This function will evaluate parts of WHERE/ON clauses that are
+ applicable to the partial record on hand and in case of success
+ submit this record to the next level of the nested loop.
+*/
+
+static enum_nested_loop_state
+evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
+ int error, my_bool *report_error)
+{
+ bool not_exists_optimize= join_tab->table->reginfo.not_exists_optimize;
+ bool not_used_in_distinct=join_tab->not_used_in_distinct;
+ ha_rows found_records=join->found_records;
+ COND *select_cond= join_tab->select_cond;
+
+ if (error > 0 || (*report_error)) // Fatal error
+ return NESTED_LOOP_ERROR;
+ if (error < 0)
+ return NESTED_LOOP_NO_MORE_ROWS;
+ if (join->thd->killed) // Aborted by user
+ {
+ join->thd->send_kill_message();
+ return NESTED_LOOP_KILLED; /* purecov: inspected */
+ }
+ DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
+ if (!select_cond || select_cond->val_int())
+ {
+ /*
+ There is no select condition or the attached pushed down
+ condition is true => a match is found.
+ */
+ bool found= 1;
+ while (join_tab->first_unmatched && found)
{
- if (join->thd->killed) // Aborted by user
- {
- my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
- return -2; /* purecov: inspected */
- }
- join->examined_rows++;
- join->thd->row_count++;
- if (!on_expr || on_expr->val_int())
+ /*
+ The while condition is always false if join_tab is not
+ the last inner join table of an outer join operation.
+ */
+ JOIN_TAB *first_unmatched= join_tab->first_unmatched;
+ /*
+ Mark that a match for current outer table is found.
+ This activates push down conditional predicates attached
+ to the all inner tables of the outer join.
+ */
+ first_unmatched->found= 1;
+ for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
{
- found=1;
- if (not_exists_optimize)
- break; // Searching after not null columns
- if (!select_cond || select_cond->val_int())
- {
- if ((error=(*join_tab->next_select)(join,join_tab+1,0)) < 0)
- return error;
- /*
- Test if this was a SELECT DISTINCT query on a table that
- was not in the field list; In this case we can abort if
- we found a row, as no new rows can be added to the result.
- */
- if (not_used_in_distinct && found_records != join->found_records)
- return 0;
- }
- else
+ /* Check all predicates that has just been activated. */
+ /*
+ Actually all predicates non-guarded by first_unmatched->found
+ will be re-evaluated again. It could be fixed, but, probably,
+ it's not worth doing now.
+ */
+ if (tab->select_cond && !tab->select_cond->val_int())
{
- /*
- This row failed selection, release lock on it.
- XXX: There is no table handler in MySQL which makes use of this
- call. It's kept from Gemini times. A lot of new code was added
- recently (i. e. subselects) without having it in mind.
- */
- info->file->unlock_row();
+ /* The condition attached to table tab is false */
+ if (tab == join_tab)
+ found= 0;
+ else
+ {
+ /*
+ Set a return point if rejected predicate is attached
+ not to the last table of the current nest level.
+ */
+ join->return_tab= tab;
+ return NESTED_LOOP_OK;
+ }
}
}
- } while (!(error=info->read_record(info)) && !(*report_error));
+ /*
+ Check whether join_tab is not the last inner table
+ for another embedding outer join.
+ */
+ if ((first_unmatched= first_unmatched->first_upper) &&
+ first_unmatched->last_inner != join_tab)
+ first_unmatched= 0;
+ join_tab->first_unmatched= first_unmatched;
+ }
+
+ /*
+ It was not just a return to lower loop level when one
+ of the newly activated predicates is evaluated as false
+ (See above join->return_tab= tab).
+ */
+ join->examined_rows++;
+ join->thd->row_count++;
+
+ if (found)
+ {
+ enum enum_nested_loop_state rc;
+ if (not_exists_optimize)
+ return NESTED_LOOP_NO_MORE_ROWS;
+ /* A match from join_tab is found for the current partial join. */
+ rc= (*join_tab->next_select)(join, join_tab+1, 0);
+ if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
+ return rc;
+ if (join->return_tab < join_tab)
+ return NESTED_LOOP_OK;
+ /*
+ Test if this was a SELECT DISTINCT query on a table that
+ was not in the field list; In this case we can abort if
+ we found a row, as no new rows can be added to the result.
+ */
+ if (not_used_in_distinct && found_records != join->found_records)
+ return NESTED_LOOP_OK;
+ }
+ else
+ join_tab->read_record.file->unlock_row();
}
- if (error > 0 || (*report_error)) // Fatal error
- return -1;
+ else
+ {
+ /*
+ The condition pushed down to the table join_tab rejects all rows
+ with the beginning coinciding with the current partial join.
+ */
+ join->examined_rows++;
+ join->thd->row_count++;
+ }
+ return NESTED_LOOP_OK;
+}
+
- if (!found && on_expr)
- { // OUTER JOIN
- restore_record(join_tab->table,default_values); // Make empty record
- mark_as_null_row(join_tab->table); // For group by without error
- if (!select_cond || select_cond->val_int())
+/*
+ DESCRIPTION
+ Construct a NULL complimented partial join record and feed it to the next
+ level of the nested loop. This function is used in case we have
+ an OUTER join and no matching record was found.
+*/
+
+static enum_nested_loop_state
+evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab)
+{
+ /*
+ The table join_tab is the first inner table of a outer join operation
+ and no matches has been found for the current outer row.
+ */
+ JOIN_TAB *last_inner_tab= join_tab->last_inner;
+ /* Cache variables for faster loop */
+ COND *select_cond;
+ for ( ; join_tab <= last_inner_tab ; join_tab++)
+ {
+ /* Change the the values of guard predicate variables. */
+ join_tab->found= 1;
+ join_tab->not_null_compl= 0;
+ /* The outer row is complemented by nulls for each inner tables */
+ restore_record(join_tab->table,s->default_values); // Make empty record
+ mark_as_null_row(join_tab->table); // For group by without error
+ select_cond= join_tab->select_cond;
+ /* Check all attached conditions for inner table rows. */
+ if (select_cond && !select_cond->val_int())
+ return NESTED_LOOP_OK;
+ }
+ join_tab--;
+ /*
+ The row complemented by nulls might be the first row
+ of embedding outer joins.
+ If so, perform the same actions as in the code
+ for the first regular outer join row above.
+ */
+ for ( ; ; )
+ {
+ JOIN_TAB *first_unmatched= join_tab->first_unmatched;
+ if ((first_unmatched= first_unmatched->first_upper) &&
+ first_unmatched->last_inner != join_tab)
+ first_unmatched= 0;
+ join_tab->first_unmatched= first_unmatched;
+ if (!first_unmatched)
+ break;
+ first_unmatched->found= 1;
+ for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
{
- if ((error=(*join_tab->next_select)(join,join_tab+1,0)) < 0)
- return error; /* purecov: inspected */
+ if (tab->select_cond && !tab->select_cond->val_int())
+ {
+ join->return_tab= tab;
+ return NESTED_LOOP_OK;
+ }
}
}
- return 0;
+ /*
+ The row complemented by nulls satisfies all conditions
+ attached to inner tables.
+ Send the row complemented by nulls to be joined with the
+ remaining tables.
+ */
+ return (*join_tab->next_select)(join, join_tab+1, 0);
}
-static int
+static enum_nested_loop_state
flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
{
+ enum_nested_loop_state rc= NESTED_LOOP_OK;
int error;
READ_RECORD *info;
if (!join_tab->cache.records)
- return 0; /* Nothing to do */
+ return NESTED_LOOP_OK; /* Nothing to do */
if (skip_last)
(void) store_record_in_cache(&join_tab->cache); // Must save this for later
if (join_tab->use_quick == 2)
@@ -6094,7 +9633,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
if ((error=join_init_read_record(join_tab)))
{
reset_cache_write(&join_tab->cache);
- return -error; /* No records or error */
+ return error < 0 ? NESTED_LOOP_NO_MORE_ROWS: NESTED_LOOP_ERROR;
}
for (JOIN_TAB *tmp=join->join_tab; tmp != join_tab ; tmp++)
@@ -6108,12 +9647,12 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
{
if (join->thd->killed)
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
- return -2; // Aborted by user /* purecov: inspected */
+ join->thd->send_kill_message();
+ return NESTED_LOOP_KILLED; // Aborted by user /* purecov: inspected */
}
SQL_SELECT *select=join_tab->select;
- if (!error && (!join_tab->cache.select ||
- !join_tab->cache.select->skip_record()))
+ if (rc == NESTED_LOOP_OK &&
+ (!join_tab->cache.select || !join_tab->cache.select->skip_record()))
{
uint i;
reset_cache_read(&join_tab->cache);
@@ -6121,11 +9660,14 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
{
read_cached_record(join_tab);
if (!select || !select->skip_record())
- if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
+ {
+ rc= (join_tab->next_select)(join,join_tab+1,0);
+ if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
{
reset_cache_write(&join_tab->cache);
- return error; /* purecov: inspected */
+ return rc;
}
+ }
}
}
} while (!(error=info->read_record(info)));
@@ -6134,10 +9676,10 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
read_cached_record(join_tab); // Restore current record
reset_cache_write(&join_tab->cache);
if (error > 0) // Fatal error
- return -1; /* purecov: inspected */
+ return NESTED_LOOP_ERROR; /* purecov: inspected */
for (JOIN_TAB *tmp2=join->join_tab; tmp2 != join_tab ; tmp2++)
tmp2->table->status=tmp2->status;
- return 0;
+ return NESTED_LOOP_OK;
}
@@ -6161,7 +9703,7 @@ int report_error(TABLE *table, int error)
*/
if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
sql_print_error("Got error %d when reading table '%s'",
- error, table->path);
+ error, table->s->path);
table->file->print_error(error,MYF(0));
return 1;
}
@@ -6196,7 +9738,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
tab->info="const row not found";
/* Mark for EXPLAIN that the row was not found */
pos->records_read=0.0;
- if (!table->outer_join || error > 0)
+ if (!table->maybe_null || error > 0)
DBUG_RETURN(error);
}
}
@@ -6210,23 +9752,24 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
table->file->extra(HA_EXTRA_KEYREAD);
tab->index= tab->ref.key;
}
- if ((error=join_read_const(tab)))
+ error=join_read_const(tab);
+ if (table->key_read)
+ {
+ table->key_read=0;
+ table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
+ if (error)
{
tab->info="unique row not found";
/* Mark for EXPLAIN that the row was not found */
pos->records_read=0.0;
- if (!table->outer_join || error > 0)
+ if (!table->maybe_null || 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)
+ if (*tab->on_expr_ref && !table->null_row)
{
- if ((table->null_row= test(tab->on_expr->val_int() == 0)))
+ if ((table->null_row= test((*tab->on_expr_ref)->val_int() == 0)))
mark_as_null_row(table);
}
if (!table->null_row)
@@ -6243,7 +9786,7 @@ join_read_system(JOIN_TAB *tab)
if (table->status & STATUS_GARBAGE) // If first read
{
if ((error=table->file->read_first_row(table->record[0],
- table->primary_key)))
+ table->s->primary_key)))
{
if (error != HA_ERR_END_OF_FILE)
return report_error(table, error);
@@ -6260,6 +9803,19 @@ join_read_system(JOIN_TAB *tab)
}
+/*
+ Read a table when there is at most one matching row
+
+ SYNOPSIS
+ join_read_const()
+ tab Table to read
+
+ RETURN
+ 0 Row was found
+ -1 Row was not found
+ 1 Got an error (other than row not found) during read
+*/
+
static int
join_read_const(JOIN_TAB *tab)
{
@@ -6267,6 +9823,7 @@ join_read_const(JOIN_TAB *tab)
TABLE *table= tab->table;
if (table->status & STATUS_GARBAGE) // If first read
{
+ table->status= 0;
if (cp_buffer_from_ref(tab->join->thd, &tab->ref))
error=HA_ERR_KEY_NOT_FOUND;
else
@@ -6277,6 +9834,7 @@ join_read_const(JOIN_TAB *tab)
}
if (error)
{
+ table->status= STATUS_NOT_FOUND;
mark_as_null_row(tab->table);
empty_record(table);
if (error != HA_ERR_KEY_NOT_FOUND)
@@ -6445,8 +10003,8 @@ test_if_quick_select(JOIN_TAB *tab)
static int
join_init_read_record(JOIN_TAB *tab)
{
- if (tab->select && tab->select->quick)
- tab->select->quick->reset();
+ if (tab->select && tab->select->quick && tab->select->quick->reset())
+ return 1;
init_read_record(&tab->read_record, tab->join->thd, tab->table,
tab->select,1,1);
return (*tab->read_record.read_record)(&tab->read_record);
@@ -6593,13 +10151,32 @@ join_read_next_same_or_null(READ_RECORD *info)
/*****************************************************************************
- The different end of select functions
- These functions returns < 0 when end is reached, 0 on ok and > 0 if a
- fatal error (like table corruption) was detected
+ DESCRIPTION
+ Functions that end one nested loop iteration. Different functions
+ are used to support GROUP BY clause and to redirect records
+ to a table (e.g. in case of SELECT into a temporary table) or to the
+ network client.
+
+ RETURN VALUES
+ NESTED_LOOP_OK - the record has been successfully handled
+ NESTED_LOOP_ERROR - a fatal error (like table corruption)
+ was detected
+ NESTED_LOOP_KILLED - thread shutdown was requested while processing
+ the record
+ NESTED_LOOP_QUERY_LIMIT - the record has been successfully handled;
+ additionally, the nested loop produced the
+ number of rows specified in the LIMIT clause
+ for the query
+ NESTED_LOOP_CURSOR_LIMIT - the record has been successfully handled;
+ additionally, there is a cursor and the nested
+ loop algorithm produced the number of rows
+ that is specified for current cursor fetch
+ operation.
+ All return values except NESTED_LOOP_OK abort the nested loop.
*****************************************************************************/
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
@@ -6608,14 +10185,14 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
int error;
if (join->having && join->having->val_int() == 0)
- DBUG_RETURN(0); // Didn't match having
+ DBUG_RETURN(NESTED_LOOP_OK); // Didn't match having
error=0;
if (join->procedure)
error=join->procedure->send_row(*join->fields);
else if (join->do_send_rows)
error=join->result->send_data(*join->fields);
if (error)
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
if (++join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
@@ -6648,28 +10225,37 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
join->do_send_rows= 0;
if (join->unit->fake_select_lex)
- join->unit->fake_select_lex->select_limit= HA_POS_ERROR;
- DBUG_RETURN(0);
+ join->unit->fake_select_lex->select_limit= 0;
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
- DBUG_RETURN(-3); // Abort nicely
+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
+ }
+ else if (join->send_records >= join->fetch_limit)
+ {
+ /*
+ There is a server side cursor and all rows for
+ this fetch request are sent.
+ */
+ DBUG_RETURN(NESTED_LOOP_CURSOR_LIMIT);
}
}
else
{
if (join->procedure && join->procedure->end_of_records())
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
int idx= -1;
+ enum_nested_loop_state ok_code= NESTED_LOOP_OK;
DBUG_ENTER("end_send_group");
if (!join->first_record || end_of_records ||
@@ -6717,57 +10303,72 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
}
if (error > 0)
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
if (join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (!(join->select_options & OPTION_FOUND_ROWS))
- DBUG_RETURN(-3); // Abort nicely
+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
join->do_send_rows=0;
join->unit->select_limit_cnt = HA_POS_ERROR;
}
+ else if (join->send_records >= join->fetch_limit)
+ {
+ /*
+ There is a server side cursor and all rows
+ for this fetch request are sent.
+ */
+ /*
+ Preventing code duplication. When finished with the group reset
+ the group functions and copy_fields. We fall through. bug #11904
+ */
+ ok_code= NESTED_LOOP_CURSOR_LIMIT;
+ }
}
}
else
{
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
join->first_record=1;
VOID(test_if_group_changed(join->group_fields));
}
if (idx < (int) join->send_group_parts)
{
+ /*
+ This branch is executed also for cursors which have finished their
+ fetch limit - the reason for ok_code.
+ */
copy_fields(&join->tmp_table_param);
if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure)
join->procedure->add();
- DBUG_RETURN(0);
+ DBUG_RETURN(ok_code);
}
}
if (update_sum_func(join->sum_funcs))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure)
join->procedure->add();
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
TABLE *table=join->tmp_table;
- int error;
DBUG_ENTER("end_write");
if (join->thd->killed) // Aborted by user
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-2); /* purecov: inspected */
+ join->thd->send_kill_message();
+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
if (!end_of_records)
{
@@ -6792,6 +10393,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
#endif
if (!join->having || join->having->val_int())
{
+ int error;
join->found_records++;
if ((error=table->file->write_row(table->record[0])))
{
@@ -6800,28 +10402,28 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
goto end;
if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
error,1))
- DBUG_RETURN(-1); // Not a table_is_full error
- table->uniques=0; // To ensure rows are the same
+ DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error
+ table->s->uniques=0; // To ensure rows are the same
}
if (++join->send_records >= join->tmp_table_param.end_write_records &&
join->do_send_rows)
{
if (!(join->select_options & OPTION_FOUND_ROWS))
- DBUG_RETURN(-3);
+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT);
join->do_send_rows=0;
join->unit->select_limit_cnt = HA_POS_ERROR;
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
}
end:
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* Group by searching after group record and updating it if possible */
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
@@ -6831,11 +10433,11 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_ENTER("end_update");
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
if (join->thd->killed) // Aborted by user
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-2); /* purecov: inspected */
+ join->thd->send_kill_message();
+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
join->found_records++;
@@ -6845,9 +10447,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
Item *item= *group->item;
item->save_org_in_field(group->field);
-#ifdef EMBEDDED_LIBRARY
- join->thd->net.last_errno= 0;
-#endif
/* Store in the used key if the field was 0 */
if (item->maybe_null)
group->buff[-1]=item->null_value ? 1 : 0;
@@ -6862,36 +10461,43 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
- /* The null bits are already set */
+ /*
+ Copy null bits from group key to table
+ We can't copy all data as the key may have different format
+ as the row data (for example as with VARCHAR keys)
+ */
KEY_PART_INFO *key_part;
for (group=table->group,key_part=table->key_info[0].key_part;
group ;
group=group->next,key_part++)
- memcpy(table->record[0]+key_part->offset, group->buff, key_part->length);
-
+ {
+ if (key_part->null_bit)
+ memcpy(table->record[0]+key_part->offset, group->buff, 1);
+ }
init_tmptable_sum_functions(join->sum_funcs);
copy_funcs(join->tmp_table_param.items_to_copy);
if ((error=table->file->write_row(table->record[0])))
{
if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
error, 0))
- DBUG_RETURN(-1); // Not a table_is_full error
+ DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error
/* Change method to update rows */
table->file->ha_index_init(0);
join->join_tab[join->tables-1].next_select=end_unique_update;
}
join->send_records++;
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
+
/* Like end_update, but this is done with unique constraints instead of keys */
-static int
+static enum_nested_loop_state
end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
@@ -6900,11 +10506,11 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_ENTER("end_unique_update");
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
if (join->thd->killed) // Aborted by user
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-2); /* purecov: inspected */
+ join->thd->send_kill_message();
+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
init_tmptable_sum_functions(join->sum_funcs);
@@ -6918,12 +10524,12 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if ((int) table->file->get_dup_key(error) < 0)
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
if (table->file->rnd_pos(table->record[1],table->file->dupp_ref))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
restore_record(table,record[1]);
update_tmptable_sum_func(join->sum_funcs,table);
@@ -6931,27 +10537,26 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
}
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
TABLE *table=join->tmp_table;
- int error;
int idx= -1;
DBUG_ENTER("end_write_group");
if (join->thd->killed)
{ // Aborted by user
- my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-2); /* purecov: inspected */
+ join->thd->send_kill_message();
+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
if (!join->first_record || end_of_records ||
(idx=test_if_group_changed(join->group_fields)) >= 0)
@@ -6970,35 +10575,27 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
copy_sum_funcs(join->sum_funcs,
join->sum_funcs_end[send_group_parts]);
- if (join->having && join->having->val_int() == 0)
- error= -1;
- else if ((error=table->file->write_row(table->record[0])))
+ if (!join->having || join->having->val_int())
{
- if (create_myisam_from_heap(join->thd, table,
- &join->tmp_table_param,
- error, 0))
- DBUG_RETURN(-1);
- /*
- If table->file->write_row() was failed because of 'out of memory'
- and tmp table succesfully created, reset error.
- */
- error=0;
+ int error= table->file->write_row(table->record[0]);
+ if (error && create_myisam_from_heap(join->thd, table,
+ &join->tmp_table_param,
+ error, 0))
+ DBUG_RETURN(NESTED_LOOP_ERROR);
}
- if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
+ if (join->rollup.state != ROLLUP::STATE_NONE)
{
if (join->rollup_write_data((uint) (idx+1), table))
- error= 1;
+ DBUG_RETURN(NESTED_LOOP_ERROR);
}
- if (error > 0)
- DBUG_RETURN(-1);
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
else
{
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
join->first_record=1;
VOID(test_if_group_changed(join->group_fields));
}
@@ -7007,17 +10604,17 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
copy_fields(&join->tmp_table_param);
copy_funcs(join->tmp_table_param.items_to_copy);
if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure)
join->procedure->add();
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
if (update_sum_func(join->sum_funcs))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure)
join->procedure->add();
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
@@ -7047,11 +10644,11 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
/*
We can remove binary fields and numerical fields except float,
as float comparison isn't 100 % secure
- We have to keep binary strings to be able to check for end spaces
+ We have to keep normal strings to be able to check for end spaces
*/
if (field->binary() &&
- field->real_type() != FIELD_TYPE_STRING &&
- field->real_type() != FIELD_TYPE_VAR_STRING &&
+ field->real_type() != MYSQL_TYPE_STRING &&
+ field->real_type() != MYSQL_TYPE_VARCHAR &&
(field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
{
return !store_val_in_field(field,right_item);
@@ -7241,13 +10838,13 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
}
-static uint find_shortest_key(TABLE *table, const key_map *usable_keys)
+uint find_shortest_key(TABLE *table, const key_map *usable_keys)
{
uint min_length= (uint) ~0;
uint best= MAX_KEY;
if (!usable_keys->is_clear_all())
{
- for (uint nr=0; nr < table->keys ; nr++)
+ for (uint nr=0; nr < table->s->keys ; nr++)
{
if (usable_keys->is_set(nr))
{
@@ -7313,7 +10910,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part;
KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts;
- for (nr= 0 ; nr < table->keys ; nr++)
+ for (nr= 0 ; nr < table->s->keys ; nr++)
{
if (usable_keys->is_set(nr) &&
table->key_info[nr].key_length < min_length &&
@@ -7356,13 +10953,13 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
usable_keys.set_all();
for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
{
- if ((*tmp_order->item)->type() != Item::FIELD_ITEM)
+ Item *item= (*tmp_order->item)->real_item();
+ if (item->type() != Item::FIELD_ITEM)
{
usable_keys.clear_all();
DBUG_RETURN(0);
}
- usable_keys.intersect(((Item_field*) (*tmp_order->item))->
- field->part_of_sortkey);
+ usable_keys.intersect(((Item_field*) item)->field->part_of_sortkey);
if (usable_keys.is_clear_all())
DBUG_RETURN(0); // No usable keys
}
@@ -7378,6 +10975,17 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
}
else if (select && select->quick) // Range found by opt_range
{
+ int quick_type= select->quick->get_type();
+ /*
+ assume results are not ordered when index merge is used
+ TODO: sergeyp: Results of all index merge selects actually are ordered
+ by clustered PK values.
+ */
+
+ if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
+ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
+ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT)
+ DBUG_RETURN(0);
ref_key= select->quick->index;
ref_key_parts= select->quick->used_key_parts;
}
@@ -7462,8 +11070,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/
if (!select->quick->reverse_sorted())
{
- // ORDER BY range_key DESC
- QUICK_SELECT_DESC *tmp=new QUICK_SELECT_DESC(select->quick,
+ int quick_type= select->quick->get_type();
+ if (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 ||
+ quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
+ DBUG_RETURN(0); // Use filesort
+
+ /* ORDER BY range_key DESC */
+ QUICK_SELECT_DESC *tmp=new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick),
used_key_parts);
if (!tmp || tmp->error)
{
@@ -7521,7 +11136,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
else
keys= usable_keys;
- for (nr=0; nr < table->keys ; nr++)
+ for (nr=0; nr < table->s->keys ; nr++)
{
uint not_used;
if (keys.is_set(nr))
@@ -7611,8 +11226,11 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
{
select->quick=tab->quick;
tab->quick=0;
- /* We can only use 'Only index' if quick key is same as ref_key */
- if (table->key_read && (uint) tab->ref.key != select->quick->index)
+ /*
+ We can only use 'Only index' if quick key is same as ref_key
+ and in index_merge 'Only index' cannot be used
+ */
+ if (table->key_read && ((uint) tab->ref.key != select->quick->index))
{
table->key_read=0;
table->file->extra(HA_EXTRA_NO_KEYREAD);
@@ -7628,11 +11246,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
*/
if (!(select->quick= (tab->type == JT_FT ?
new FT_SELECT(thd, table, tab->ref.key) :
- get_quick_select_for_ref(thd, table, &tab->ref))))
+ get_quick_select_for_ref(thd, table, &tab->ref,
+ tab->found_records))))
goto err;
}
}
- if (table->tmp_table)
+ if (table->s->tmp_table)
table->file->info(HA_STATUS_VARIABLE); // Get record count
table->sort.found_records=filesort(thd, table,sortorder, length,
select, filesort_limit, &examined_rows);
@@ -7643,6 +11262,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
tab->select= 0;
}
tab->select_cond=0;
+ tab->last_inner= 0;
+ tab->first_unmatched= 0;
tab->type=JT_ALL; // Read with normal read_record
tab->read_first_record= join_init_read_record;
tab->join->examined_rows+=examined_rows;
@@ -7679,8 +11300,7 @@ static bool fix_having(JOIN *join, Item **having)
else // This should never happen
if (!(table->select->cond= new Item_cond_and(table->select->cond,
sort_table_cond)) ||
- table->select->cond->fix_fields(join->thd, join->tables_list,
- &table->select->cond))
+ table->select->cond->fix_fields(join->thd, &table->select->cond))
return 1;
table->select_cond=table->select->cond;
table->select_cond->top_level_item();
@@ -7706,7 +11326,7 @@ static bool compare_record(TABLE *table, Field **ptr)
{
for (; *ptr ; ptr++)
{
- if ((*ptr)->cmp_offset(table->rec_buff_length))
+ if ((*ptr)->cmp_offset(table->s->rec_buff_length))
return 1;
}
return 0;
@@ -7759,15 +11379,15 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
join->unit->select_limit_cnt= 1; // Only send first row
DBUG_RETURN(0);
}
- Field **first_field=entry->field+entry->fields - field_count;
+ Field **first_field=entry->field+entry->s->fields - field_count;
offset= field_count ?
- entry->field[entry->fields - field_count]->offset() : 0;
- reclength=entry->reclength-offset;
+ entry->field[entry->s->fields - field_count]->offset() : 0;
+ reclength=entry->s->reclength-offset;
free_io_cache(entry); // Safety
entry->file->info(HA_STATUS_VARIABLE);
- if (entry->db_type == DB_TYPE_HEAP ||
- (!entry->blob_fields &&
+ if (entry->s->db_type == DB_TYPE_HEAP ||
+ (!entry->s->blob_fields &&
((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->records <
thd->variables.sortbuff_size)))
error=remove_dup_with_hash_index(join->thd, entry,
@@ -7789,7 +11409,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
char *org_record,*new_record;
byte *record;
int error;
- ulong reclength=table->reclength-offset;
+ ulong reclength= table->s->reclength-offset;
DBUG_ENTER("remove_dup_with_compare");
org_record=(char*) (record=table->record[0])+offset;
@@ -7801,7 +11421,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
{
if (thd->killed)
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0));
+ thd->send_kill_message();
error=0;
goto err;
}
@@ -7822,7 +11442,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
}
if (copy_blobs(first_field))
{
- my_error(ER_OUTOFMEMORY,MYF(0));
+ my_message(ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
error=0;
goto err;
}
@@ -7925,7 +11545,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
byte *org_key_pos;
if (thd->killed)
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0));
+ thd->send_kill_message();
error=0;
goto err;
}
@@ -8044,6 +11664,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
}
if (!(cache->field=(CACHE_FIELD*)
sql_alloc(sizeof(CACHE_FIELD)*(cache->fields+table_count*2)+(blobs+1)*
+
sizeof(CACHE_FIELD*))))
{
my_free((gptr) cache->buff,MYF(0)); /* purecov: inspected */
@@ -8077,10 +11698,10 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
}
}
/* Copy null bits from table */
- if (null_fields && tables[i].table->null_fields)
+ if (null_fields && tables[i].table->s->null_fields)
{ /* must copy null bits */
copy->str=(char*) tables[i].table->null_flags;
- copy->length=tables[i].table->null_bytes;
+ copy->length= tables[i].table->s->null_bytes;
copy->strip=0;
copy->blob_field=0;
length+=copy->length;
@@ -8295,71 +11916,164 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref)
*****************************************************************************/
/*
- Find order/group item in requested columns and change the item to point at
- it. If item doesn't exists, add it first in the field list
- Return 0 if ok.
+ Resolve an ORDER BY or GROUP BY column reference.
+
+ SYNOPSIS
+ find_order_in_list()
+ thd [in] Pointer to current thread structure
+ ref_pointer_array [in/out] All select, group and order by fields
+ tables [in] List of tables to search in (usually FROM clause)
+ order [in] Column reference to be resolved
+ fields [in] List of fields to search in (usually SELECT list)
+ all_fields [in/out] All select, group and order by fields
+ is_group_field [in] True if order is a GROUP field, false if
+ ORDER by field
+
+ DESCRIPTION
+ Given a column reference (represented by 'order') from a GROUP BY or ORDER
+ BY clause, find the actual column it represents. If the column being
+ resolved is from the GROUP BY clause, the procedure searches the SELECT
+ list 'fields' and the columns in the FROM list 'tables'. If 'order' is from
+ the ORDER BY clause, only the SELECT list is being searched.
+
+ If 'order' is resolved to an Item, then order->item is set to the found
+ Item. If there is no item for the found column (that is, it was resolved
+ into a table field), order->item is 'fixed' and is added to all_fields and
+ ref_pointer_array.
+
+ RETURN
+ FALSE if OK
+ TRUE if error occurred
+
+ ref_pointer_array and all_fields are updated
*/
-static int
-find_order_in_list(THD *thd, Item **ref_pointer_array,
- TABLE_LIST *tables,ORDER *order, List<Item> &fields,
- List<Item> &all_fields)
+static bool
+find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ ORDER *order, List<Item> &fields, List<Item> &all_fields,
+ bool is_group_field)
{
- Item *it= *order->item;
- if (it->type() == Item::INT_ITEM)
+ Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */
+ Item::Type order_item_type;
+ Item **select_item; /* The corresponding item from the SELECT clause. */
+ Field *from_field; /* The corresponding field from the FROM clause. */
+
+ if (order_item->type() == Item::INT_ITEM)
{ /* Order by position */
- uint count= (uint) it->val_int();
+ uint count= (uint) order_item->val_int();
if (!count || count > fields.elements)
{
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
- MYF(0), it->full_name(), thd->where);
- return 1;
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ order_item->full_name(), thd->where);
+ return TRUE;
}
- order->item= ref_pointer_array + count-1;
+ order->item= ref_pointer_array + count - 1;
order->in_field_list= 1;
- return 0;
+ order->counter= count;
+ order->counter_used= 1;
+ return FALSE;
}
+ /* Lookup the current GROUP/ORDER field in the SELECT clause. */
uint counter;
bool unaliased;
- Item **item= find_item_in_list(it, fields, &counter,
+ select_item= find_item_in_list(order_item, fields, &counter,
REPORT_EXCEPT_NOT_FOUND, &unaliased);
- if (!item)
- return 1;
+ if (!select_item)
+ return TRUE; /* The item is not unique, or some other error occured. */
+
- if (item != (Item **)not_found_item)
+ /* Check whether the resolved field is not ambiguos. */
+ if (select_item != not_found_item)
{
+ Item *view_ref= NULL;
/*
If we have found field not by its alias in select list but by its
original field name, we should additionaly check if we have conflict
for this name (in case if we would perform lookup in all tables).
*/
- if (unaliased && !it->fixed && it->fix_fields(thd, tables, order->item))
- return 1;
-
- order->item= ref_pointer_array + counter;
- order->in_field_list=1;
- return 0;
+ if (unaliased && !order_item->fixed &&
+ order_item->fix_fields(thd, order->item))
+ return TRUE;
+
+ /* Lookup the current GROUP field in the FROM clause. */
+ order_item_type= order_item->type();
+ from_field= (Field*) not_found_field;
+ if (is_group_field &&
+ order_item_type == Item::FIELD_ITEM ||
+ order_item_type == Item::REF_ITEM)
+ {
+ from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables,
+ NULL, &view_ref, IGNORE_ERRORS, TRUE,
+ FALSE);
+ if (!from_field)
+ from_field= (Field*) not_found_field;
+ }
+
+ if (from_field == not_found_field ||
+ (from_field != view_ref_found ?
+ /* it is field of base table => check that fields are same */
+ ((*select_item)->type() == Item::FIELD_ITEM &&
+ ((Item_field*) (*select_item))->field->eq(from_field)) :
+ /*
+ in is field of view table => check that references on translation
+ table are same
+ */
+ ((*select_item)->type() == Item::REF_ITEM &&
+ view_ref->type() == Item::REF_ITEM &&
+ ((Item_ref *) (*select_item))->ref ==
+ ((Item_ref *) view_ref)->ref)))
+ {
+ /*
+ If there is no such field in the FROM clause, or it is the same field
+ as the one found in the SELECT clause, then use the Item created for
+ the SELECT field. As a result if there was a derived field that
+ 'shadowed' a table field with the same name, the table field will be
+ chosen over the derived field.
+ */
+ order->item= ref_pointer_array + counter;
+ order->in_field_list=1;
+ return FALSE;
+ }
+ else
+ {
+ /*
+ There is a field with the same name in the FROM clause. This
+ is the field that will be chosen. In this case we issue a
+ warning so the user knows that the field from the FROM clause
+ overshadows the column reference from the SELECT list.
+ */
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
+ ER(ER_NON_UNIQ_ERROR), from_field->field_name,
+ current_thd->where);
+ }
}
order->in_field_list=0;
/*
- We check it->fixed because Item_func_group_concat can put
+ The call to order_item->fix_fields() means that here we resolve
+ 'order_item' to a column from a table in the list 'tables', or to
+ a column in some outer query. Exactly because of the second case
+ we come to this point even if (select_item == not_found_item),
+ inspite of that fix_fields() calls find_item_in_list() one more
+ time.
+
+ We check order_item->fixed because Item_func_group_concat can put
arguments for which fix_fields already was called.
-
- 'it' reassigned in if condition because fix_field can change it.
*/
- if (!it->fixed &&
- (it->fix_fields(thd, tables, order->item) ||
- (it= *order->item)->check_cols(1) ||
+ if (!order_item->fixed &&
+ (order_item->fix_fields(thd, order->item) ||
+ (order_item= *order->item)->check_cols(1) ||
thd->is_fatal_error))
- return 1; // Wrong field
+ return TRUE; /* Wrong field. */
+
uint el= all_fields.elements;
- all_fields.push_front(it); // Add new field to field list
- ref_pointer_array[el]= it;
+ all_fields.push_front(order_item); /* Add new field to field list. */
+ ref_pointer_array[el]= order_item;
order->item= ref_pointer_array + el;
- return 0;
+ return FALSE;
}
+
/*
Change order to point at item in select list. If item isn't a number
and doesn't exits in the select list, add it the the field list.
@@ -8372,7 +12086,7 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
for (; order; order=order->next)
{
if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
- all_fields))
+ all_fields, FALSE))
return 1;
}
return 0;
@@ -8386,7 +12100,7 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
setup_group()
thd Thread handler
ref_pointer_array We store references to all fields that was not in
- 'fields' here.
+ 'fields' here.
fields All fields in the select part. Any item in 'order'
that is part of these list is replaced by a pointer
to this fields.
@@ -8424,13 +12138,12 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
for (; order; order=order->next)
{
if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
- all_fields))
+ all_fields, TRUE))
return 1;
(*order->item)->marker=1; /* Mark found */
if ((*order->item)->with_sum_func)
{
- my_printf_error(ER_WRONG_GROUP_FIELD, ER(ER_WRONG_GROUP_FIELD),MYF(0),
- (*order->item)->full_name());
+ my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*order->item)->full_name());
return 1;
}
}
@@ -8445,9 +12158,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
!item->const_item())
{
- my_printf_error(ER_WRONG_FIELD_WITH_GROUP,
- ER(ER_WRONG_FIELD_WITH_GROUP),
- MYF(0),item->full_name());
+ my_error(ER_WRONG_FIELD_WITH_GROUP, MYF(0), item->full_name());
return 1;
}
}
@@ -8462,7 +12173,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
*/
static bool
-setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
+setup_new_fields(THD *thd, List<Item> &fields,
List<Item> &all_fields, ORDER *new_field)
{
Item **item;
@@ -8479,7 +12190,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
else
{
thd->where="procedure list";
- if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
+ if ((*new_field->item)->fix_fields(thd, new_field->item))
DBUG_RETURN(1); /* purecov: inspected */
all_fields.push_front(*new_field->item);
new_field->item=all_fields.head_ref();
@@ -8502,7 +12213,6 @@ create_distinct_group(THD *thd, Item **ref_pointer_array,
List_iterator<Item> li(fields);
Item *item;
ORDER *order,*group,**prev;
- uint index= 0;
*all_order_by_fields_used= 1;
while ((item=li++))
@@ -8537,12 +12247,12 @@ create_distinct_group(THD *thd, Item **ref_pointer_array,
simple indexing of ref_pointer_array (order in the array and in the
list are same)
*/
- ord->item= ref_pointer_array + index;
+ ord->item= ref_pointer_array;
ord->asc=1;
*prev=ord;
prev= &ord->next;
}
- index++;
+ ref_pointer_array++;
}
*prev=0;
return group;
@@ -8565,7 +12275,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
param->quick_group=1;
while ((field=li++))
{
- Item::Type type=field->type();
+ Item::Type type=field->real_item()->type();
if (type == Item::FIELD_ITEM)
param->field_count++;
else if (type == Item::SUM_FUNC_ITEM)
@@ -8579,7 +12289,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
for (uint i=0 ; i < sum_item->arg_count ; i++)
{
- if (sum_item->args[0]->type() == Item::FIELD_ITEM)
+ if (sum_item->args[0]->real_item()->type() == Item::FIELD_ITEM)
param->field_count++;
else
param->func_count++;
@@ -8641,7 +12351,7 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
DBUG_RETURN(0);
- for (; !(map & tables->table->map) ; tables=tables->next) ;
+ for (; !(map & tables->table->map); tables= tables->next_leaf);
if (map != tables->table->map)
DBUG_RETURN(0); // More than one table
DBUG_PRINT("exit",("sort by table: %d",tables->table->tablenr));
@@ -8660,22 +12370,47 @@ calc_group_buffer(JOIN *join,ORDER *group)
join->group= 1;
for (; group ; group=group->next)
{
- Field *field=(*group->item)->get_tmp_table_field();
+ Item *group_item= *group->item;
+ Field *field= group_item->get_tmp_table_field();
if (field)
{
if (field->type() == FIELD_TYPE_BLOB)
key_length+=MAX_BLOB_WIDTH; // Can't be used as a key
+ else if (field->type() == MYSQL_TYPE_VARCHAR)
+ key_length+= field->field_length + HA_KEY_BLOB_LENGTH;
else
- key_length+=field->pack_length();
+ key_length+= field->pack_length();
}
- else if ((*group->item)->result_type() == REAL_RESULT)
- key_length+=sizeof(double);
- else if ((*group->item)->result_type() == INT_RESULT)
- key_length+=sizeof(longlong);
else
- key_length+=(*group->item)->max_length;
+ {
+ switch (group_item->result_type()) {
+ case REAL_RESULT:
+ key_length+= sizeof(double);
+ break;
+ case INT_RESULT:
+ key_length+= sizeof(longlong);
+ break;
+ case DECIMAL_RESULT:
+ key_length+= my_decimal_get_binary_size(group_item->max_length -
+ (group_item->decimals ? 1 : 0),
+ group_item->decimals);
+ break;
+ case STRING_RESULT:
+ /*
+ Group strings are taken as varstrings and require an length field.
+ A field is not yet created by create_tmp_field()
+ and the sizes should match up.
+ */
+ key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
+ break;
+ default:
+ /* This case should never be choosen */
+ DBUG_ASSERT(0);
+ join->thd->fatal_error();
+ }
+ }
parts++;
- if ((*group->item)->maybe_null)
+ if (group_item->maybe_null)
null_parts++;
}
join->tmp_table_param.group_length=key_length+null_parts;
@@ -8727,7 +12462,7 @@ alloc_group_fields(JOIN *join,ORDER *group)
{
for (; group ; group=group->next)
{
- Item_buff *tmp=new_Item_buff(join->thd, *group->item);
+ Cached_item *tmp=new_Cached_item(join->thd, *group->item);
if (!tmp || join->group_fields.push_front(tmp))
return TRUE;
}
@@ -8738,12 +12473,12 @@ alloc_group_fields(JOIN *join,ORDER *group)
static int
-test_if_group_changed(List<Item_buff> &list)
+test_if_group_changed(List<Cached_item> &list)
{
DBUG_ENTER("test_if_group_changed");
- List_iterator<Item_buff> li(list);
+ List_iterator<Cached_item> li(list);
int idx= -1,i;
- Item_buff *buff;
+ Cached_item *buff;
for (i=(int) list.elements-1 ; (buff=li++) ; i--)
{
@@ -8801,9 +12536,10 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
param->copy_funcs.empty();
for (i= 0; (pos= li++); i++)
{
- if (pos->type() == Item::FIELD_ITEM)
+ if (pos->real_item()->type() == Item::FIELD_ITEM)
{
Item_field *item;
+ pos= pos->real_item();
if (!(item= new Item_field(thd, ((Item_field*) pos))))
goto err;
pos= item;
@@ -8834,9 +12570,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp)
goto err;
- copy->set(tmp, item->result_field);
- item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
- copy++;
+ if (copy)
+ {
+ copy->set(tmp, item->result_field);
+ item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
+ copy++;
+ }
}
}
else if ((pos->type() == Item::FUNC_ITEM ||
@@ -8880,7 +12619,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
err:
if (copy)
- delete [] param->copy_field;
+ delete [] param->copy_field; // This is never 0
param->copy_field=0;
err2:
DBUG_RETURN(TRUE);
@@ -8958,9 +12697,7 @@ bool JOIN::alloc_func_list()
field_list All items
send_fields Items in select list
before_group_by Set to 1 if this is called before GROUP BY handling
-
- NOTES
- Calls ::setup() for all item_sum objects in field_list
+ recompute Set to TRUE if sum_funcs must be recomputed
RETURN
0 ok
@@ -8968,23 +12705,21 @@ bool JOIN::alloc_func_list()
*/
bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
- bool before_group_by)
+ bool before_group_by, bool recompute)
{
List_iterator_fast<Item> it(field_list);
Item_sum **func;
Item *item;
DBUG_ENTER("make_sum_func_list");
+ if (*sum_funcs && !recompute)
+ DBUG_RETURN(FALSE); /* We have already initialized sum_funcs. */
+
func= sum_funcs;
while ((item=it++))
{
if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
- {
*func++= (Item_sum*) item;
- /* let COUNT(DISTINCT) create the temporary table */
- if (((Item_sum*) item)->setup(thd))
- DBUG_RETURN(TRUE);
- }
}
if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
{
@@ -9029,6 +12764,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
{
List_iterator_fast<Item> it(all_fields);
Item *item_field,*item;
+ DBUG_ENTER("change_to_use_tmp_fields");
+
res_selected_fields.empty();
res_all_fields.empty();
@@ -9052,8 +12789,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
else
item_field= (Item*) new Item_field(field);
if (!item_field)
- return TRUE; // Fatal error
- item_field->name= item->name; /*lint -e613 */
+ DBUG_RETURN(TRUE); // Fatal error
+ item_field->name= item->name;
#ifndef DBUG_OFF
if (_db_on_ && !item_field->name)
{
@@ -9077,7 +12814,7 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
for (i= 0; i < border; i++)
itr++;
itr.sublist(res_selected_fields, elements);
- return FALSE;
+ DBUG_RETURN(FALSE);
}
@@ -9131,6 +12868,33 @@ change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
Code for calculating functions
******************************************************************************/
+
+/*
+ Call ::setup for all sum functions
+
+ SYNOPSIS
+ setup_sum_funcs()
+ thd thread handler
+ func_ptr sum function list
+
+ RETURN
+ FALSE ok
+ TRUE error
+*/
+
+static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
+{
+ Item_sum *func;
+ DBUG_ENTER("setup_sum_funcs");
+ while ((func= *(func_ptr++)))
+ {
+ if (func->setup(thd))
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
static void
init_tmptable_sum_functions(Item_sum **func_ptr)
{
@@ -9230,13 +12994,14 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
DBUG_RETURN(TRUE);
if (!cond->fixed)
- cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond);
+ cond->fix_fields(thd, (Item**)&cond);
if (join_tab->select)
{
error=(int) cond->add(join_tab->select->cond);
join_tab->select_cond=join_tab->select->cond=cond;
}
- else if ((join_tab->select=make_select(join_tab->table, 0, 0, cond,&error)))
+ else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,
+ &error)))
join_tab->select_cond=cond;
DBUG_RETURN(error ? TRUE : FALSE);
@@ -9271,8 +13036,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
thd reference to the context
expr expression to make replacement
group_list list of references to group by items
- changed out: returns 1 if item contains a replaced field item
-
+ changed out: returns 1 if item contains a replaced field item
+
DESCRIPTION
The function replaces occurrences of group by fields in expr
by ref objects for these fields unless they are under aggregate
@@ -9306,6 +13071,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
{
if (expr->arg_count)
{
+ Name_resolution_context *context= &thd->lex->current_select->context;
Item **arg,**arg_end;
bool arg_changed= FALSE;
for (arg= expr->arguments(),
@@ -9320,8 +13086,9 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
{
if (item->eq(*group_tmp->item,0))
{
- Item *new_item;
- if(!(new_item= new Item_ref(group_tmp->item, 0, item->name)))
+ Item *new_item;
+ if (!(new_item= new Item_ref(context, group_tmp->item, 0,
+ item->name)))
return 1; // fatal_error is set
thd->change_item_tree(arg, new_item);
arg_changed= TRUE;
@@ -9505,8 +13272,6 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
*/
item= item->copy_or_same(thd);
((Item_sum*) item)->make_unique();
- if (((Item_sum*) item)->setup(thd))
- return 1;
*(*func)= (Item_sum*) item;
(*func)++;
}
@@ -9523,9 +13288,10 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
This is an element that is used by the GROUP BY and should be
set to NULL in this level
*/
- Item_null_result *null_item;
+ Item_null_result *null_item= new (thd->mem_root) Item_null_result();
+ if (!null_item)
+ return 1;
item->maybe_null= 1; // Value will be null sometimes
- null_item= rollup.null_items[i];
null_item->result_field= item->get_tmp_table_field();
item= null_item;
break;
@@ -9675,6 +13441,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
select_result *result=join->result;
Item *item_null= new Item_null();
CHARSET_INFO *cs= system_charset_info;
+ int quick_type;
DBUG_ENTER("select_describe");
DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
(ulong)join->select_lex, join->select_lex->type,
@@ -9766,14 +13533,20 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
{
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
- char buff[512],*buff_ptr=buff;
- char buff1[512], buff2[512];
+ char buff[512];
+ char buff1[512], buff2[512], buff3[512];
+ char keylen_str_buf[64];
+ String extra(buff, sizeof(buff),cs);
char table_name_buffer[NAME_LEN];
String tmp1(buff1,sizeof(buff1),cs);
String tmp2(buff2,sizeof(buff2),cs);
+ String tmp3(buff3,sizeof(buff3),cs);
+ extra.length(0);
tmp1.length(0);
tmp2.length(0);
+ tmp3.length(0);
+ quick_type= -1;
item_list.empty();
/* id */
item_list.push_back(new Item_uint((uint32)
@@ -9783,7 +13556,15 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
strlen(join->select_lex->type),
cs));
if (tab->type == JT_ALL && tab->select && tab->select->quick)
- tab->type= JT_RANGE;
+ {
+ quick_type= tab->select->quick->get_type();
+ if ((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))
+ tab->type = JT_INDEX_MERGE;
+ else
+ tab->type = JT_RANGE;
+ }
/* table */
if (table->derived_select_number)
{
@@ -9794,18 +13575,18 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(table_name_buffer, len, cs));
}
else
- item_list.push_back(new Item_string(table->table_name,
- strlen(table->table_name),
+ item_list.push_back(new Item_string(table->alias,
+ strlen(table->alias),
cs));
/* type */
item_list.push_back(new Item_string(join_type_str[tab->type],
strlen(join_type_str[tab->type]),
cs));
- uint j;
- /* possible_keys */
+ /* Build "possible_keys" value and add it to item_list */
if (!tab->keys.is_clear_all())
{
- for (j=0 ; j < table->keys ; j++)
+ uint j;
+ for (j=0 ; j < table->s->keys ; j++)
{
if (tab->keys.is_set(j))
{
@@ -9821,14 +13602,19 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
else
item_list.push_back(item_null);
- /* key key_len ref */
+
+ /* Build "key", "key_len", and "ref" values and add them to item_list */
if (tab->ref.key_parts)
{
KEY *key_info=table->key_info+ tab->ref.key;
+ register uint length;
item_list.push_back(new Item_string(key_info->name,
strlen(key_info->name),
system_charset_info));
- item_list.push_back(new Item_int((int32) tab->ref.key_length));
+ length= longlong2str(tab->ref.key_length, keylen_str_buf, 10) -
+ keylen_str_buf;
+ item_list.push_back(new Item_string(keylen_str_buf, length,
+ system_charset_info));
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
{
if (tmp2.length())
@@ -9841,18 +13627,21 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
else if (tab->type == JT_NEXT)
{
KEY *key_info=table->key_info+ tab->index;
+ register uint length;
item_list.push_back(new Item_string(key_info->name,
strlen(key_info->name),cs));
- item_list.push_back(new Item_int((int32) key_info->key_length));
+ length= longlong2str(key_info->key_length, keylen_str_buf, 10) -
+ keylen_str_buf;
+ item_list.push_back(new Item_string(keylen_str_buf,
+ length,
+ system_charset_info));
item_list.push_back(item_null);
}
else if (tab->select && tab->select->quick)
{
- KEY *key_info=table->key_info+ tab->select->quick->index;
- item_list.push_back(new Item_string(key_info->name,
- strlen(key_info->name),cs));
- item_list.push_back(new Item_int((int32) tab->select->quick->
- max_used_key_length));
+ tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
+ item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
+ item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
item_list.push_back(item_null);
}
else
@@ -9861,52 +13650,87 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(item_null);
item_list.push_back(item_null);
}
- /* rows */
+ /* Add "rows" field to item_list. */
item_list.push_back(new Item_int((longlong) (ulonglong)
join->best_positions[i]. records_read,
21));
- /* extra */
+ /* Build "Extra" field and add it to item_list. */
my_bool key_read=table->key_read;
if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
table->used_keys.is_set(tab->index))
key_read=1;
-
+ if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
+ !((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
+ key_read=1;
+
if (tab->info)
item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
else
{
+ if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
+ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
+ quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
+ {
+ extra.append("; Using ");
+ tab->select->quick->add_info_string(&extra);
+ }
if (tab->select)
{
if (tab->use_quick == 2)
{
char buf[MAX_KEY/8+1];
- sprintf(buff_ptr,"; Range checked for each record (index map: 0x%s)",
- tab->keys.print(buf));
- buff_ptr=strend(buff_ptr);
+ extra.append("; Range checked for each record (index map: 0x");
+ extra.append(tab->keys.print(buf));
+ extra.append(')');
}
- else
- buff_ptr=strmov(buff_ptr,"; Using where");
+ else if (tab->select->cond)
+ {
+ const COND *pushed_cond= tab->table->file->pushed_cond;
+
+ if (thd->variables.engine_condition_pushdown && pushed_cond)
+ {
+ extra.append("; Using where with pushed condition");
+ if (thd->lex->describe & DESCRIBE_EXTENDED)
+ {
+ extra.append(": ");
+ ((COND *)pushed_cond)->print(&extra);
+ }
+ }
+ else
+ extra.append("; Using where");
+ }
}
if (key_read)
- buff_ptr= strmov(buff_ptr,"; Using index");
+ {
+ if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
+ extra.append("; Using index for group-by");
+ else
+ extra.append("; Using index");
+ }
if (table->reginfo.not_exists_optimize)
- buff_ptr= strmov(buff_ptr,"; Not exists");
+ extra.append("; Not exists");
if (need_tmp_table)
{
need_tmp_table=0;
- buff_ptr= strmov(buff_ptr,"; Using temporary");
+ extra.append("; Using temporary");
}
if (need_order)
{
need_order=0;
- buff_ptr= strmov(buff_ptr,"; Using filesort");
+ extra.append("; Using filesort");
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
- buff_ptr= strmov(buff_ptr,"; Distinct");
- if (buff_ptr == buff)
- buff_ptr+= 2; // Skip inital "; "
- item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2,
- cs));
+ extra.append("; Distinct");
+
+ /* Skip initial "; "*/
+ const char *str= extra.ptr();
+ uint32 len= extra.length();
+ if (len)
+ {
+ str += 2;
+ len -= 2;
+ }
+ item_list.push_back(new Item_string(str, len, cs));
}
// For next iteration
used_tables|=table->map;
@@ -9925,10 +13749,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
-int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
+bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{
DBUG_ENTER("mysql_explain_union");
- int res= 0;
+ bool res= 0;
SELECT_LEX *first= unit->first_select();
for (SELECT_LEX *sl= first;
@@ -9966,6 +13790,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
else
{
thd->lex->current_select= first;
+ unit->set_limit(unit->global_parameters);
res= mysql_select(thd, &first->ref_pointer_array,
(TABLE_LIST*) first->table_list.first,
first->with_wild, first->item_list,
@@ -9979,20 +13804,136 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
first->options | thd->options | SELECT_DESCRIBE,
result, unit, first);
}
- if (res > 0 || thd->net.report_error)
- res= -1; // mysql_explain_select do not report error
- DBUG_RETURN(res);
+ DBUG_RETURN(res || thd->net.report_error);
+}
+
+
+/*
+ Print joins from the FROM clause
+
+ SYNOPSIS
+ print_join()
+ thd thread handler
+ str string where table should be printed
+ tables list of tables in join
+*/
+
+static void print_join(THD *thd, String *str, List<TABLE_LIST> *tables)
+{
+ /* List is reversed => we should reverse it before using */
+ List_iterator_fast<TABLE_LIST> ti(*tables);
+ TABLE_LIST **table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) *
+ tables->elements);
+ if (table == 0)
+ return; // out of memory
+
+ for (TABLE_LIST **t= table + (tables->elements - 1); t >= table; t--)
+ *t= ti++;
+
+ DBUG_ASSERT(tables->elements >= 1);
+ (*table)->print(thd, str);
+
+ TABLE_LIST **end= table + tables->elements;
+ for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++)
+ {
+ TABLE_LIST *curr= *tbl;
+ if (curr->outer_join)
+ str->append(" left join ", 11); // MySQL converts right to left joins
+ else if (curr->straight)
+ str->append(" straight_join ", 15);
+ else
+ str->append(" join ", 6);
+ curr->print(thd, str);
+ if (curr->on_expr)
+ {
+ str->append(" on(", 4);
+ curr->on_expr->print(str);
+ str->append(')');
+ }
+ }
+}
+
+
+/*
+ Print table as it should be in join list
+
+ SYNOPSIS
+ st_table_list::print();
+ str string where table should bbe printed
+*/
+
+void st_table_list::print(THD *thd, String *str)
+{
+ if (nested_join)
+ {
+ str->append('(');
+ print_join(thd, str, &nested_join->join_list);
+ str->append(')');
+ }
+ else
+ {
+ const char *cmp_name; // Name to compare with alias
+ if (view_name.str)
+ {
+ // A view
+
+ if (!(belong_to_view &&
+ belong_to_view->compact_view_format))
+ {
+ append_identifier(thd, str, view_db.str, view_db.length);
+ str->append('.');
+ }
+ append_identifier(thd, str, view_name.str, view_name.length);
+ cmp_name= view_name.str;
+ }
+ else if (derived)
+ {
+ // A derived table
+ str->append('(');
+ derived->print(str);
+ str->append(')');
+ cmp_name= ""; // Force printing of alias
+ }
+ else
+ {
+ // A normal table
+
+ if (!(belong_to_view &&
+ belong_to_view->compact_view_format))
+ {
+ append_identifier(thd, str, db, db_length);
+ str->append('.');
+ }
+ if (schema_table)
+ {
+ append_identifier(thd, str, schema_table_name,
+ strlen(schema_table_name));
+ cmp_name= schema_table_name;
+ }
+ else
+ {
+ append_identifier(thd, str, table_name, table_name_length);
+ cmp_name= table_name;
+ }
+ }
+ if (my_strcasecmp(table_alias_charset, cmp_name, alias))
+ {
+ str->append(' ');
+ append_identifier(thd, str, alias, strlen(alias));
+ }
+ }
}
void st_select_lex::print(THD *thd, String *str)
{
+ /* QQ: thd may not be set for sub queries, but this should be fixed */
if (!thd)
thd= current_thd;
str->append("select ", 7);
-
- //options
+
+ /* First add options */
if (options & SELECT_STRAIGHT_JOIN)
str->append("straight_join ", 14);
if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) &&
@@ -10033,60 +13974,8 @@ void st_select_lex::print(THD *thd, String *str)
if (table_list.elements)
{
str->append(" from ", 6);
- Item *next_on= 0;
- for (TABLE_LIST *table= (TABLE_LIST *) table_list.first;
- table;
- table= table->next)
- {
- if (table->derived)
- {
- str->append('(');
- table->derived->print(str);
- str->append(") ");
- str->append(table->alias);
- }
- else
- {
- str->append(table->db);
- str->append('.');
- str->append(table->real_name);
- if (my_strcasecmp(table_alias_charset, table->real_name, table->alias))
- {
- str->append(' ');
- str->append(table->alias);
- }
- }
-
- if (table->on_expr && ((table->outer_join & JOIN_TYPE_LEFT) ||
- !(table->outer_join & JOIN_TYPE_RIGHT)))
- next_on= table->on_expr;
-
- if (next_on)
- {
- str->append(" on(", 4);
- next_on->print(str);
- str->append(')');
- next_on= 0;
- }
-
- TABLE_LIST *next_table;
- if ((next_table= table->next))
- {
- if (table->outer_join & JOIN_TYPE_RIGHT)
- {
- str->append(" right join ", 12);
- if (!(table->outer_join & JOIN_TYPE_LEFT) &&
- table->on_expr)
- next_on= table->on_expr;
- }
- else if (next_table->straight)
- str->append(" straight_join ", 15);
- else if (next_table->outer_join & JOIN_TYPE_LEFT)
- str->append(" left join ", 11);
- else
- str->append(" join ", 6);
- }
- }
+ /* go through join tree */
+ print_join(thd, str, &top_join_list);
}
// Where
@@ -10149,17 +14038,18 @@ void st_select_lex::print(THD *thd, String *str)
res new select_result object
RETURN
- 0 - OK
- -1 - error
+ FALSE - OK
+ TRUE - error
*/
-int JOIN::change_result(select_result *res)
+bool JOIN::change_result(select_result *res)
{
DBUG_ENTER("JOIN::change_result");
result= res;
- if (!procedure && result->prepare(fields_list, select_lex->master_unit()))
+ if (!procedure && (result->prepare(fields_list, select_lex->master_unit()) ||
+ result->prepare2()))
{
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index c7440fe4c3a..47906c2697e 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -85,23 +85,41 @@ typedef struct st_join_cache {
/*
** The structs which holds the join connections and join states
*/
-
enum join_type { JT_UNKNOWN,JT_SYSTEM,JT_CONST,JT_EQ_REF,JT_REF,JT_MAYBE_REF,
JT_ALL, JT_RANGE, JT_NEXT, JT_FT, JT_REF_OR_NULL,
- JT_UNIQUE_SUBQUERY, JT_INDEX_SUBQUERY};
+ JT_UNIQUE_SUBQUERY, JT_INDEX_SUBQUERY, JT_INDEX_MERGE};
class JOIN;
+enum enum_nested_loop_state
+{
+ NESTED_LOOP_KILLED= -2, NESTED_LOOP_ERROR= -1,
+ NESTED_LOOP_OK= 0, NESTED_LOOP_NO_MORE_ROWS= 1,
+ NESTED_LOOP_QUERY_LIMIT= 3, NESTED_LOOP_CURSOR_LIMIT= 4
+};
+
+typedef enum_nested_loop_state
+(*Next_select_func)(JOIN *, struct st_join_table *, bool);
+typedef int (*Read_record_func)(struct st_join_table *tab);
+
+
typedef struct st_join_table {
TABLE *table;
KEYUSE *keyuse; /* pointer to first used key */
SQL_SELECT *select;
COND *select_cond;
- QUICK_SELECT *quick;
- Item *on_expr;
+ QUICK_SELECT_I *quick;
+ Item **on_expr_ref; /* pointer to the associated on expression */
+ COND_EQUAL *cond_equal; /* multiple equalities for the on expression */
+ st_join_table *first_inner; /* first inner table for including outerjoin */
+ bool found; /* true after all matches or null complement */
+ bool not_null_compl;/* true before null complement is added */
+ st_join_table *last_inner; /* last table table for embedding outer join */
+ st_join_table *first_upper; /* first inner table for embedding outer join */
+ st_join_table *first_unmatched; /* used for optimization purposes only */
const char *info;
- int (*read_first_record)(struct st_join_table *tab);
- int (*next_select)(JOIN *,struct st_join_table *,bool);
+ Read_record_func read_first_record;
+ Next_select_func next_select;
READ_RECORD read_record;
double worst_seeks;
key_map const_keys; /* Keys with constant part */
@@ -126,6 +144,7 @@ typedef struct st_join_table {
typedef struct st_position /* Used in find_best */
{
double records_read;
+ double read_time;
JOIN_TAB *table;
KEYUSE *key;
} POSITION;
@@ -143,19 +162,35 @@ typedef struct st_rollup
class JOIN :public Sql_alloc
{
public:
- JOIN_TAB *join_tab,**best_ref,**map2table;
- JOIN_TAB *join_tab_save; //saved join_tab for subquery reexecution
+ JOIN_TAB *join_tab,**best_ref;
+ JOIN_TAB **map2table; // mapping between table indexes and JOIN_TABs
+ JOIN_TAB *join_tab_save; // saved join_tab for subquery reexecution
TABLE **table,**all_tables,*sort_by_table;
uint tables,const_tables;
uint send_group_parts;
bool sort_and_group,first_record,full_join,group, no_field_update;
bool do_send_rows;
+ /*
+ TRUE when we want to resume nested loop iterations when
+ fetching data from a cursor
+ */
+ bool resume_nested_loop;
table_map const_table_map,found_const_table_map,outer_join;
ha_rows send_records,found_records,examined_rows,row_limit, select_limit;
+ /*
+ Used to fetch no more than given amount of rows per one
+ fetch operation of server side cursor.
+ The value is checked in end_send and end_send_group in fashion, similar
+ to offset_limit_cnt:
+ - fetch_limit= HA_POS_ERROR if there is no cursor.
+ - when we open a cursor, we set fetch_limit to 0,
+ - on each fetch iteration we add num_rows to fetch to fetch_limit
+ */
+ ha_rows fetch_limit;
POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
double best_read;
List<Item> *fields;
- List<Item_buff> group_fields, group_fields_cache;
+ List<Cached_item> group_fields, group_fields_cache;
TABLE *tmp_table;
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
@@ -167,7 +202,7 @@ class JOIN :public Sql_alloc
Item *having;
Item *tmp_having; // To store having when processed temporary table
Item *having_history; // Store having for explain
- uint select_options;
+ ulonglong select_options;
select_result *result;
TMP_TABLE_PARAM tmp_table_param;
MYSQL_LOCK *lock;
@@ -195,7 +230,7 @@ class JOIN :public Sql_alloc
/* Is set if we have a GROUP BY and we have ORDER BY on a constant. */
bool skip_sort_order;
- bool need_tmp, hidden_group_fields, buffer_result;
+ bool need_tmp, hidden_group_fields;
DYNAMIC_ARRAY keyuse;
Item::cond_result cond_value;
List<Item> all_fields; // to store all fields that used in query
@@ -209,8 +244,11 @@ class JOIN :public Sql_alloc
ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
COND *conds; // ---"---
Item *conds_history; // store WHERE for explain
- TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec
+ TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_select
+ List<TABLE_LIST> *join_list; // list of joined tables in reverse order
+ COND_EQUAL *cond_equal;
SQL_SELECT *select; //created in optimisation phase
+ JOIN_TAB *return_tab; //used only for outer joins
Item **ref_pointer_array; //used pointer reference for this select
// Copy of above to be used with different lists
Item **items0, **items1, **items2, **items3, **current_ref_pointer_array;
@@ -220,25 +258,28 @@ class JOIN :public Sql_alloc
bool union_part; // this subselect is part of union
bool optimized; // flag to avoid double optimization in EXPLAIN
- JOIN(THD *thd_arg, List<Item> &fields_arg, ulong select_options_arg,
+ JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg)
:fields_list(fields_arg)
{
init(thd_arg, fields_arg, select_options_arg, result_arg);
}
- void init(THD *thd_arg, List<Item> &fields_arg, ulong select_options_arg,
+ void init(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg)
{
join_tab= join_tab_save= 0;
table= 0;
tables= 0;
const_tables= 0;
+ join_list= 0;
sort_and_group= 0;
first_record= 0;
do_send_rows= 1;
+ resume_nested_loop= FALSE;
send_records= 0;
found_records= 0;
+ fetch_limit= HA_POS_ERROR;
examined_rows= 0;
exec_tmp_table1= 0;
exec_tmp_table2= 0;
@@ -258,17 +299,16 @@ class JOIN :public Sql_alloc
skip_sort_order= 0;
need_tmp= 0;
hidden_group_fields= 0; /*safety*/
- buffer_result= test(select_options & OPTION_BUFFER_RESULT) &&
- !test(select_options & OPTION_FOUND_ROWS);
- all_fields= fields_arg;
- fields_list= fields_arg;
error= 0;
select= 0;
+ return_tab= 0;
ref_pointer_array= items0= items1= items2= items3= 0;
ref_pointer_array_size= 0;
zero_result_cause= 0;
optimized= 0;
+ cond_equal= 0;
+ all_fields= fields_arg;
fields_list= fields_arg;
bzero((char*) &keyuse,sizeof(keyuse));
tmp_table_param.copy_field=0;
@@ -283,11 +323,11 @@ class JOIN :public Sql_alloc
int optimize();
int reinit();
void exec();
- int cleanup();
+ int destroy();
void restore_tmp();
bool alloc_func_list();
bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
- bool before_group_by);
+ bool before_group_by, bool recompute= FALSE);
inline void set_items_ref_array(Item **ptr)
{
@@ -307,7 +347,15 @@ class JOIN :public Sql_alloc
int rollup_send_data(uint idx);
int rollup_write_data(uint idx, TABLE *table);
bool test_in_subselect(Item **where);
+ /*
+ Release memory and, if possible, the open tables held by this execution
+ plan (and nested plans). It's used to release some tables before
+ the end of execution in order to increase concurrency and reduce
+ memory consumption.
+ */
void join_free(bool full);
+ /* Cleanup this JOIN, possibly for reuse */
+ void cleanup(bool full);
void clear();
bool save_join_tab();
bool send_row_on_empty_set()
@@ -315,7 +363,64 @@ class JOIN :public Sql_alloc
return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
!group_list);
}
- int change_result(select_result *result);
+ bool change_result(select_result *result);
+ bool is_top_level_join() const
+ {
+ return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
+ select_lex == unit->fake_select_lex));
+ }
+};
+
+
+/*
+ Server-side cursor (now stands only for basic read-only cursor)
+ See class implementation in sql_select.cc
+ A cursor has its own runtime state - list of used items and memory root of
+ used memory - which is different from Prepared statement runtime: it must
+ be different at least for the purpose of reusing the same prepared
+ statement for many cursors.
+*/
+
+class Cursor: public Sql_alloc, public Query_arena
+{
+ MEM_ROOT main_mem_root;
+ JOIN *join;
+ SELECT_LEX_UNIT *unit;
+
+ TABLE *open_tables;
+ MYSQL_LOCK *lock;
+ TABLE *derived_tables;
+ /* List of items created during execution */
+ query_id_t query_id;
+ struct Engine_info
+ {
+ const handlerton *ht;
+ void *read_view;
+ };
+ Engine_info ht_info[MAX_HA];
+public:
+ Protocol_prep protocol;
+ Item_change_list change_list;
+ select_send result;
+ THR_LOCK_OWNER lock_id;
+ my_bool close_at_commit;
+
+ /* Temporary implementation as now we replace THD state by value */
+ /* Save THD state into cursor */
+ void init_from_thd(THD *thd);
+ /* bzero cursor state in THD */
+ void reset_thd(THD *thd);
+
+ int open(JOIN *join);
+ void fetch(ulong num_rows);
+ void reset() { join= 0; }
+ bool is_open() const { return join != 0; }
+
+ void close(bool is_active);
+
+ void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
+ Cursor(THD *thd);
+ ~Cursor() {}
};
@@ -330,8 +435,9 @@ void TEST_join(JOIN *join);
bool store_val_in_field(Field *field,Item *val);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
- ulong select_options, ha_rows rows_limit,
+ ulonglong select_options, ha_rows rows_limit,
char* alias);
+TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list);
void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func);
@@ -343,10 +449,18 @@ void copy_fields(TMP_TABLE_PARAM *param);
void copy_funcs(Item **func_ptr);
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
int error, bool ignore_last_dupp_error);
-
+uint find_shortest_key(TABLE *table, const key_map *usable_keys);
+Field* create_tmp_field_from_field(THD *thd, Field* org_field,
+ const char *name, TABLE *table,
+ Item_field *item, uint convert_blob_length);
+
/* functions from opt_sum.cc */
+bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);
+/* from sql_delete.cc, used by opt_range.cc */
+extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b);
+
/* class to copying an field/item to a key struct */
class store_key :public Sql_alloc
@@ -361,15 +475,15 @@ class store_key :public Sql_alloc
:null_ptr(null),err(0)
{
if (field_arg->type() == FIELD_TYPE_BLOB)
- to_field=new Field_varstring(ptr, length, (uchar*) null, 1,
+ {
+ /* Key segments are always packed with a 2 byte length prefix */
+ to_field=new Field_varstring(ptr, length, 2, (uchar*) null, 1,
Field::NONE, field_arg->field_name,
field_arg->table, field_arg->charset());
- else
- {
- to_field=field_arg->new_field(thd->mem_root,field_arg->table);
- if (to_field)
- to_field->move_field(ptr, (uchar*) null, 1);
}
+ else
+ to_field=field_arg->new_key_field(thd->mem_root, field_arg->table,
+ ptr, (uchar*) null, 1);
}
virtual ~store_key() {} /* Not actually needed */
virtual enum store_key_result copy()=0;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c3c28535954..2b941474de8 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -20,6 +20,9 @@
#include "mysql_priv.h"
#include "sql_select.h" // For select_describe
#include "repl_failsafe.h"
+#include "sp.h"
+#include "sp_head.h"
+#include "sql_trigger.h"
#include <my_dir.h>
#ifdef HAVE_BERKELEY_DB
@@ -37,141 +40,17 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
#endif
static int
-store_create_info(THD *thd, TABLE *table, String *packet);
-
-
-/*
- Report list of databases
- A database is a directory in the mysql_data_home directory
-*/
-
-int
-mysqld_show_dbs(THD *thd,const char *wild)
-{
- Item_string *field=new Item_string("",0,thd->charset());
- List<Item> field_list;
- char *end;
- List<char> files;
- char *file_name;
- Protocol *protocol= thd->protocol;
- DBUG_ENTER("mysqld_show_dbs");
-
- field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0));
- field->max_length=NAME_LEN;
- end=strmov(field->name,"Database");
- if (wild && wild[0])
- strxmov(end," (",wild,")",NullS);
- field_list.push_back(field);
-
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
- if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
- DBUG_RETURN(1);
- List_iterator_fast<char> it(files);
-
- while ((file_name=it++))
- {
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
- acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) ||
- (grant_option && !check_grant_db(thd, file_name)))
-#endif
- {
- protocol->prepare_for_resend();
- protocol->store(file_name, system_charset_info);
- if (protocol->write())
- DBUG_RETURN(-1);
- }
- }
- send_eof(thd);
- DBUG_RETURN(0);
-}
-
-
-/***************************************************************************
- List all open tables in a database
-***************************************************************************/
-
-int mysqld_show_open_tables(THD *thd,const char *wild)
-{
- List<Item> field_list;
- OPEN_TABLE_LIST *open_list;
- Protocol *protocol= thd->protocol;
- DBUG_ENTER("mysqld_show_open_tables");
-
- field_list.push_back(new Item_empty_string("Database",NAME_LEN));
- field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_return_int("In_use", 1, MYSQL_TYPE_TINY));
- field_list.push_back(new Item_return_int("Name_locked", 4, MYSQL_TYPE_TINY));
-
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
-
- if (!(open_list=list_open_tables(thd,wild)) && thd->is_fatal_error)
- DBUG_RETURN(-1);
-
- for (; open_list ; open_list=open_list->next)
- {
- protocol->prepare_for_resend();
- protocol->store(open_list->db, system_charset_info);
- protocol->store(open_list->table, system_charset_info);
- protocol->store_tiny((longlong) open_list->in_use);
- protocol->store_tiny((longlong) open_list->locked);
- if (protocol->write())
- {
- DBUG_RETURN(-1);
- }
- }
- send_eof(thd);
- DBUG_RETURN(0);
-}
-
-
-/***************************************************************************
-** List all tables in a database (fast version)
-** A table is a .frm file in the current databasedir
-***************************************************************************/
+store_create_info(THD *thd, TABLE_LIST *table_list, String *packet);
+static int
+view_store_create_info(THD *thd, TABLE_LIST *table, String *buff);
+static bool schema_table_store_record(THD *thd, TABLE *table);
-int mysqld_show_tables(THD *thd,const char *db,const char *wild)
-{
- Item_string *field=new Item_string("",0,thd->charset());
- List<Item> field_list;
- char path[FN_LEN],*end;
- List<char> files;
- char *file_name;
- Protocol *protocol= thd->protocol;
- DBUG_ENTER("mysqld_show_tables");
-
- field->name=(char*) thd->alloc(20+(uint) strlen(db)+
- (wild ? (uint) strlen(wild)+4:0));
- end=strxmov(field->name,"Tables_in_",db,NullS);
- if (wild && wild[0])
- strxmov(end," (",wild,")",NullS);
- field->max_length=NAME_LEN;
- (void) sprintf(path,"%s/%s",mysql_data_home,db);
- (void) unpack_dirname(path,path);
- field_list.push_back(field);
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
- if (mysql_find_files(thd,&files,db,path,wild,0))
- DBUG_RETURN(-1);
- List_iterator_fast<char> it(files);
- while ((file_name=it++))
- {
- protocol->prepare_for_resend();
- protocol->store(file_name, system_charset_info);
- if (protocol->write())
- DBUG_RETURN(-1);
- }
- send_eof(thd);
- DBUG_RETURN(0);
-}
/***************************************************************************
** List all table types supported
***************************************************************************/
-int mysqld_show_storage_engines(THD *thd)
+bool mysqld_show_storage_engines(THD *thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
@@ -181,8 +60,9 @@ int mysqld_show_storage_engines(THD *thd)
field_list.push_back(new Item_empty_string("Support",10));
field_list.push_back(new Item_empty_string("Comment",80));
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
const char *default_type_name=
ha_get_storage_engine((enum db_type)thd->variables.table_type);
@@ -200,10 +80,10 @@ int mysqld_show_storage_engines(THD *thd)
protocol->store(option_name, system_charset_info);
protocol->store(types->comment, system_charset_info);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -220,12 +100,17 @@ struct show_privileges_st {
static struct show_privileges_st sys_privileges[]=
{
{"Alter", "Tables", "To alter the table"},
- {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
+ {"Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"},
{"Create", "Databases,Tables,Indexes", "To create new databases and tables"},
+ {"Create routine","Functions,Procedures","To use CREATE FUNCTION/PROCEDURE"},
+ {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
+ {"Create view", "Tables", "To create new views"},
+ {"Create user", "Server Admin", "To create new users"},
{"Delete", "Tables", "To delete existing rows"},
- {"Drop", "Databases,Tables", "To drop databases and tables"},
+ {"Drop", "Databases,Tables", "To drop databases, tables, and views"},
+ {"Execute", "Functions,Procedures", "To execute stored routines"},
{"File", "File access on server", "To read and write files on the server"},
- {"Grant option", "Databases,Tables", "To give to other users those privileges you possess"},
+ {"Grant option", "Databases,Tables,Functions,Procedures", "To give to other users those privileges you possess"},
{"Index", "Tables", "To create or drop indexes"},
{"Insert", "Tables", "To insert data into tables"},
{"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"},
@@ -236,14 +121,15 @@ static struct show_privileges_st sys_privileges[]=
{"Replication slave","Server Admin","To read binary log events from the master"},
{"Select", "Tables", "To retrieve rows from table"},
{"Show databases","Server Admin","To see all databases with SHOW DATABASES"},
- {"Shutdown","Server Admin", "To shutdown the server"},
+ {"Show view","Tables","To see views with SHOW CREATE VIEW"},
+ {"Shutdown","Server Admin", "To shut down the server"},
{"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."},
{"Update", "Tables", "To update existing rows"},
{"Usage","Server Admin","No privileges - allow connect only"},
{NullS, NullS, NullS}
};
-int mysqld_show_privileges(THD *thd)
+bool mysqld_show_privileges(THD *thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
@@ -253,8 +139,9 @@ int mysqld_show_privileges(THD *thd)
field_list.push_back(new Item_empty_string("Context",15));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
show_privileges_st *privilege= sys_privileges;
for (privilege= sys_privileges; privilege->privilege ; privilege++)
@@ -264,10 +151,10 @@ int mysqld_show_privileges(THD *thd)
protocol->store(privilege->context, system_charset_info);
protocol->store(privilege->comment, system_charset_info);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -307,7 +194,7 @@ static struct show_column_type_st sys_column_types[]=
"A very small integer"},
};
-int mysqld_show_column_types(THD *thd)
+bool mysqld_show_column_types(THD *thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
@@ -328,8 +215,9 @@ int mysqld_show_column_types(THD *thd)
field_list.push_back(new Item_empty_string("Default",NAME_LEN));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
/* TODO: Change the loop to not use 'i' */
for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
@@ -350,10 +238,10 @@ int mysqld_show_column_types(THD *thd)
protocol->store(sys_column_types[i].default_value, system_charset_info);
protocol->store(sys_column_types[i].comment, system_charset_info);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -376,8 +264,14 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
bzero((char*) &table_list,sizeof(table_list));
- if (!(dirp = my_dir(path,MYF(MY_WME | (dir ? MY_WANT_STAT : 0)))))
+ if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0))))
+ {
+ if (my_errno == ENOENT)
+ my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db);
+ else
+ my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno);
DBUG_RETURN(-1);
+ }
for (i=0 ; i < (uint) dirp->number_off_files ; i++)
{
@@ -427,7 +321,9 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
if (db && !(col_access & TABLE_ACLS))
{
table_list.db= (char*) db;
- table_list.real_name=file->name;
+ table_list.db_length= strlen(db);
+ table_list.table_name= file->name;
+ table_list.table_name_length= strlen(file->name);
table_list.grant.privilege=col_access;
if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1))
continue;
@@ -448,398 +344,76 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
}
-/***************************************************************************
- Extended version of mysqld_show_tables
-***************************************************************************/
-
-int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
-{
- Item *item;
- List<char> files;
- List<Item> field_list;
- char path[FN_LEN];
- char *file_name;
- TABLE *table;
- Protocol *protocol= thd->protocol;
- TIME time;
- DBUG_ENTER("mysqld_extend_show_tables");
-
- (void) sprintf(path,"%s/%s",mysql_data_home,db);
- (void) unpack_dirname(path,path);
- 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));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Avg_row_length",(int32) 0,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Data_length",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Max_data_length",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Index_length",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Data_free",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Auto_increment",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_datetime("Create_time"));
- item->maybe_null=1;
- field_list.push_back(item=new Item_datetime("Update_time"));
- item->maybe_null=1;
- field_list.push_back(item=new Item_datetime("Check_time"));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Collation",32));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Create_options",255));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Comment",80));
- item->maybe_null=1;
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
-
- if (mysql_find_files(thd,&files,db,path,wild,0))
- DBUG_RETURN(-1);
- List_iterator_fast<char> it(files);
- while ((file_name=it++))
- {
- TABLE_LIST table_list;
- bzero((char*) &table_list,sizeof(table_list));
- protocol->prepare_for_resend();
- protocol->store(file_name, system_charset_info);
- table_list.db=(char*) db;
- table_list.real_name= table_list.alias= file_name;
- if (lower_case_table_names)
- my_casedn_str(files_charset_info, file_name);
- if (!(table = open_ltable(thd, &table_list, TL_READ)))
- {
- for (uint i=2 ; i < field_list.elements ; i++)
- protocol->store_null();
- // Send error to Comment field
- protocol->store(thd->net.last_error, system_charset_info);
- thd->clear_error();
- }
- else
- {
- 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) ?
- "Dynamic" : "Fixed");
- protocol->store(str, system_charset_info);
- protocol->store((ulonglong) file->records);
- protocol->store((ulonglong) file->mean_rec_length);
- protocol->store((ulonglong) file->data_file_length);
- if (file->max_data_file_length)
- protocol->store((ulonglong) file->max_data_file_length);
- else
- protocol->store_null();
- protocol->store((ulonglong) file->index_file_length);
- protocol->store((ulonglong) file->delete_length);
- if (table->found_next_number_field)
- {
- table->next_number_field=table->found_next_number_field;
- table->next_number_field->reset();
- file->update_auto_increment();
- protocol->store(table->next_number_field->val_int());
- table->next_number_field=0;
- }
- else
- protocol->store_null();
- if (!file->create_time)
- protocol->store_null();
- else
- {
- thd->variables.time_zone->gmt_sec_to_TIME(&time, file->create_time);
- protocol->store(&time);
- }
- if (!file->update_time)
- protocol->store_null();
- else
- {
- thd->variables.time_zone->gmt_sec_to_TIME(&time, file->update_time);
- protocol->store(&time);
- }
- if (!file->check_time)
- protocol->store_null();
- else
- {
- thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
- protocol->store(&time);
- }
- str= (table->table_charset ? table->table_charset->name : "default");
- protocol->store(str, system_charset_info);
- if (file->table_flags() & HA_HAS_CHECKSUM)
- protocol->store((ulonglong)file->checksum());
- else
- protocol->store_null(); // Checksum
- {
- char option_buff[350],*ptr;
- ptr=option_buff;
- if (table->min_rows)
- {
- ptr=strmov(ptr," min_rows=");
- ptr=longlong10_to_str(table->min_rows,ptr,10);
- }
- if (table->max_rows)
- {
- ptr=strmov(ptr," max_rows=");
- ptr=longlong10_to_str(table->max_rows,ptr,10);
- }
- if (table->avg_row_length)
- {
- ptr=strmov(ptr," avg_row_length=");
- ptr=longlong10_to_str(table->avg_row_length,ptr,10);
- }
- if (table->db_create_options & HA_OPTION_PACK_KEYS)
- ptr=strmov(ptr," pack_keys=1");
- if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
- ptr=strmov(ptr," pack_keys=0");
- if (table->db_create_options & HA_OPTION_CHECKSUM)
- ptr=strmov(ptr," checksum=1");
- if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
- ptr=strmov(ptr," delay_key_write=1");
- if (table->row_type != ROW_TYPE_DEFAULT)
- ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) table->row_type],
- NullS);
- if (file->raid_type)
- {
- char buff[100];
- sprintf(buff," raid_type=%s raid_chunks=%d raid_chunksize=%ld",
- my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
- ptr=strmov(ptr,buff);
- }
- protocol->store(option_buff+1,
- (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1)
- , system_charset_info);
- }
- {
- char *comment=table->file->update_table_comment(table->comment);
- protocol->store(comment, system_charset_info);
- if (comment != table->comment)
- my_free(comment,MYF(0));
- }
- close_thread_tables(thd,0);
- }
- if (protocol->write())
- DBUG_RETURN(-1);
- }
- send_eof(thd);
- DBUG_RETURN(0);
-}
-
-
-/***************************************************************************
-** List all columns in a table_list->real_name
-***************************************************************************/
-
-int
-mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
- bool verbose)
-{
- TABLE *table;
- handler *file;
- char tmp[MAX_FIELD_WIDTH];
- char tmp1[MAX_FIELD_WIDTH];
- Item *item;
- Protocol *protocol= thd->protocol;
- DBUG_ENTER("mysqld_show_fields");
- DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
- table_list->real_name));
-
- if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
- {
- send_error(thd);
- DBUG_RETURN(1);
- }
- file=table->file;
- file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- (void) get_table_grant(thd, table_list);
-#endif
- List<Item> field_list;
- field_list.push_back(new Item_empty_string("Field",NAME_LEN));
- field_list.push_back(new Item_empty_string("Type", 40));
- if (verbose)
- field_list.push_back(new Item_empty_string("Collation",40));
- field_list.push_back(new Item_empty_string("Null",1));
- field_list.push_back(new Item_empty_string("Key",3));
- field_list.push_back(item=new Item_empty_string("Default",NAME_LEN));
- item->maybe_null=1;
- field_list.push_back(new Item_empty_string("Extra",20));
- if (verbose)
- {
- field_list.push_back(new Item_empty_string("Privileges",80));
- field_list.push_back(new Item_empty_string("Comment",255));
- }
- // Send first number of fields and records
- if (protocol->send_records_num(&field_list, (ulonglong)file->records) ||
- protocol->send_fields(&field_list,0))
- DBUG_RETURN(1);
- restore_record(table,default_values); // Get empty record
-
- Field **ptr,*field;
- for (ptr=table->field; (field= *ptr) ; ptr++)
- {
- if (!wild || !wild[0] ||
- !wild_case_compare(system_charset_info, field->field_name,wild))
- {
- {
- byte *pos;
- uint flags=field->flags;
- String type(tmp,sizeof(tmp), system_charset_info);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- uint col_access;
-#endif
- protocol->prepare_for_resend();
- protocol->store(field->field_name, system_charset_info);
- field->sql_type(type);
- protocol->store(type.ptr(), type.length(), system_charset_info);
- if (verbose)
- protocol->store(field->has_charset() ? field->charset()->name : "NULL",
- system_charset_info);
- /*
- Even if TIMESTAMP field can't contain NULL as its value it
- will accept NULL if you will try to insert such value and will
- convert NULL value to current TIMESTAMP. So YES here means
- that NULL is allowed for assignment (but may be won't be
- returned).
- */
- pos=(byte*) ((flags & NOT_NULL_FLAG) &&
- field->type() != FIELD_TYPE_TIMESTAMP ?
- "" : "YES");
- protocol->store((const char*) pos, system_charset_info);
- pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
- (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
- (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
- protocol->store((char*) pos, system_charset_info);
-
- if (table->timestamp_field == field &&
- field->unireg_check != Field::TIMESTAMP_UN_FIELD)
- {
- /*
- We have NOW() as default value but we use CURRENT_TIMESTAMP form
- because it is more SQL standard comatible
- */
- protocol->store("CURRENT_TIMESTAMP", system_charset_info);
- }
- else if (field->unireg_check != Field::NEXT_NUMBER &&
- !field->is_null())
- { // Not null by default
- /*
- Note: we have to convert the default value into
- system_charset_info before sending.
- This is necessary for "SET NAMES binary":
- If the client character set is binary, we want to
- send metadata in UTF8 rather than in the column's
- character set.
- This conversion also makes "SHOW COLUMNS" and
- "SHOW CREATE TABLE" output consistent. Without
- this conversion the default values were displayed
- differently.
- */
- String def(tmp1,sizeof(tmp1), system_charset_info);
- type.set(tmp, sizeof(tmp), field->charset());
- field->val_str(&type);
- uint dummy_errors;
- def.copy(type.ptr(), type.length(), type.charset(),
- system_charset_info, &dummy_errors);
- protocol->store(def.ptr(), def.length(), def.charset());
- }
- else if (field->unireg_check == Field::NEXT_NUMBER ||
- field->maybe_null())
- protocol->store_null(); // Null as default
- else
- protocol->store("",0, system_charset_info); // empty string
-
- char *end=tmp;
- if (field->unireg_check == Field::NEXT_NUMBER)
- end=strmov(tmp,"auto_increment");
- protocol->store(tmp,(uint) (end-tmp), system_charset_info);
-
- if (verbose)
- {
- /* Add grant options & comments */
- end=tmp;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
- for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
- {
- if (col_access & 1)
- {
- *end++=',';
- end=strmov(end,grant_types.type_names[bitnr]);
- }
- }
-#else
- end=strmov(end,"");
-#endif
- protocol->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1),
- system_charset_info);
- protocol->store(field->comment.str, field->comment.length,
- system_charset_info);
- }
- if (protocol->write())
- DBUG_RETURN(1);
- }
- }
- }
- send_eof(thd);
- DBUG_RETURN(0);
-}
-
-
-int
+bool
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
- TABLE *table;
Protocol *protocol= thd->protocol;
char buff[2048];
String buffer(buff, sizeof(buff), system_charset_info);
DBUG_ENTER("mysqld_show_create");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
- table_list->real_name));
+ table_list->table_name));
- /* Only one table for now */
- if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
+ /* We want to preserve the tree for views. */
+ thd->lex->view_prepare_mode= TRUE;
+
+ /* Only one table for now, but VIEW can involve several tables */
+ if (open_normal_and_derived_tables(thd, table_list, 0))
+ DBUG_RETURN(TRUE);
+
+ /* TODO: add environment variables show when it become possible */
+ if (thd->lex->only_view && !table_list->view)
{
- send_error(thd);
- DBUG_RETURN(1);
+ my_error(ER_WRONG_OBJECT, MYF(0),
+ table_list->db, table_list->table_name, "VIEW");
+ DBUG_RETURN(TRUE);
}
buffer.length(0);
- if (store_create_info(thd, table, &buffer))
- DBUG_RETURN(-1);
+ if ((table_list->view ?
+ view_store_create_info(thd, table_list, &buffer) :
+ store_create_info(thd, table_list, &buffer)))
+ DBUG_RETURN(TRUE);
List<Item> field_list;
- field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- // 1024 is for not to confuse old clients
- field_list.push_back(new Item_empty_string("Create Table",
- max(buffer.length(),1024)));
+ if (table_list->view)
+ {
+ field_list.push_back(new Item_empty_string("View",NAME_LEN));
+ field_list.push_back(new Item_empty_string("Create View",
+ max(buffer.length(),1024)));
+ }
+ else
+ {
+ field_list.push_back(new Item_empty_string("Table",NAME_LEN));
+ // 1024 is for not to confuse old clients
+ field_list.push_back(new Item_empty_string("Create Table",
+ max(buffer.length(),1024)));
+ }
- if (protocol->send_fields(&field_list, 1))
- DBUG_RETURN(1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
- protocol->store(table->table_name, system_charset_info);
+ if (table_list->view)
+ protocol->store(table_list->view_name.str, system_charset_info);
+ else
+ {
+ if (table_list->schema_table)
+ protocol->store(table_list->schema_table->table_name,
+ system_charset_info);
+ else
+ protocol->store(table_list->table->alias, system_charset_info);
+ }
protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
+
if (protocol->write())
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
-int mysqld_show_create_db(THD *thd, char *dbname,
- HA_CREATE_INFO *create_info)
+bool mysqld_show_create_db(THD *thd, char *dbname,
+ HA_CREATE_INFO *create_info)
{
int length;
char path[FN_REFLEN];
@@ -856,8 +430,8 @@ int mysqld_show_create_db(THD *thd, char *dbname,
if (check_db_name(dbname))
{
- net_printf(thd,ER_WRONG_DB_NAME, dbname);
- DBUG_RETURN(1);
+ my_error(ER_WRONG_DB_NAME, MYF(0), dbname);
+ DBUG_RETURN(TRUE);
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -868,38 +442,46 @@ int mysqld_show_create_db(THD *thd, char *dbname,
thd->master_access);
if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
{
- net_printf(thd,ER_DBACCESS_DENIED_ERROR,
- thd->priv_user, thd->host_or_ip, dbname);
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user, thd->host_or_ip, dbname);
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
thd->priv_user, thd->host_or_ip, dbname);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
#endif
-
- (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
- length=unpack_dirname(path,path); // Convert if not unix
- found_libchar= 0;
- if (length && path[length-1] == FN_LIBCHAR)
+ if (!my_strcasecmp(system_charset_info, dbname,
+ information_schema_name.str))
{
- found_libchar= 1;
- path[length-1]=0; // remove ending '\'
+ dbname= information_schema_name.str;
+ create.default_table_charset= system_charset_info;
}
- if (access(path,F_OK))
+ else
{
- net_printf(thd,ER_BAD_DB_ERROR,dbname);
- DBUG_RETURN(1);
+ (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
+ length=unpack_dirname(path,path); // Convert if not unix
+ found_libchar= 0;
+ if (length && path[length-1] == FN_LIBCHAR)
+ {
+ found_libchar= 1;
+ path[length-1]=0; // remove ending '\'
+ }
+ if (access(path,F_OK))
+ {
+ my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
+ DBUG_RETURN(TRUE);
+ }
+ if (found_libchar)
+ path[length-1]= FN_LIBCHAR;
+ strmov(path+length, MY_DB_OPT_FILE);
+ load_db_opt(thd, path, &create);
}
- if (found_libchar)
- path[length-1]= FN_LIBCHAR;
- strmov(path+length, MY_DB_OPT_FILE);
- load_db_opt(thd, path, &create);
-
List<Item> field_list;
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
field_list.push_back(new Item_empty_string("Create Database",1024));
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
protocol->store(dbname, strlen(dbname), system_charset_info);
@@ -924,12 +506,12 @@ int mysqld_show_create_db(THD *thd, char *dbname,
protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
if (protocol->write())
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
-int
+bool
mysqld_show_logs(THD *thd)
{
List<Item> field_list;
@@ -940,113 +522,17 @@ mysqld_show_logs(THD *thd)
field_list.push_back(new Item_empty_string("Type",10));
field_list.push_back(new Item_empty_string("Status",10));
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
#ifdef HAVE_BERKELEY_DB
if ((have_berkeley_db == SHOW_OPTION_YES) && berkeley_show_logs(protocol))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
#endif
send_eof(thd);
- DBUG_RETURN(0);
-}
-
-
-int
-mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
-{
- TABLE *table;
- Protocol *protocol= thd->protocol;
- DBUG_ENTER("mysqld_show_keys");
- DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
- table_list->real_name));
-
- if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
- {
- send_error(thd);
- DBUG_RETURN(1);
- }
-
- List<Item> field_list;
- Item *item;
- field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
- field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
- field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
- field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
- field_list.push_back(item=new Item_empty_string("Collation",1));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Cardinality",0,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_return_int("Sub_part",3,
- MYSQL_TYPE_SHORT));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Packed",10));
- item->maybe_null=1;
- field_list.push_back(new Item_empty_string("Null",3));
- field_list.push_back(new Item_empty_string("Index_type",16));
- field_list.push_back(new Item_empty_string("Comment",255));
- item->maybe_null=1;
-
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1);
-
- KEY *key_info=table->key_info;
- table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
- for (uint i=0 ; i < table->keys ; i++,key_info++)
- {
- KEY_PART_INFO *key_part= key_info->key_part;
- const char *str;
- for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
- {
- protocol->prepare_for_resend();
- protocol->store(table->table_name, system_charset_info);
- protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
- protocol->store(key_info->name, system_charset_info);
- protocol->store_tiny((longlong) (j+1));
- str=(key_part->field ? key_part->field->field_name :
- "?unknown field?");
- protocol->store(str, system_charset_info);
- if (table->file->index_flags(i, j, 0) & HA_READ_ORDER)
- protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
- "D" : "A"), 1, system_charset_info);
- else
- protocol->store_null(); /* purecov: inspected */
- KEY *key=table->key_info+i;
- if (key->rec_per_key[j])
- {
- ha_rows records=(table->file->records / key->rec_per_key[j]);
- protocol->store((ulonglong) records);
- }
- else
- protocol->store_null();
-
- /* Check if we have a key part that only uses part of the field */
- if (!(key_info->flags & HA_FULLTEXT) && (!key_part->field ||
- key_part->length != table->field[key_part->fieldnr-1]->key_length()))
- protocol->store_short((longlong) key_part->length /
- key_part->field->charset()->mbmaxlen);
- else
- protocol->store_null();
- protocol->store_null(); // No pack_information yet
-
- /* Null flag */
- uint flags= key_part->field ? key_part->field->flags : 0;
- char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
- protocol->store((const char*) pos, system_charset_info);
- protocol->store(table->file->index_type(i), system_charset_info);
- /* Comment */
- if (!table->keys_in_use.is_set(i))
- protocol->store("disabled",8, system_charset_info);
- else
- protocol->store("", 0, system_charset_info);
- if (protocol->write())
- DBUG_RETURN(1); /* purecov: inspected */
- }
- }
- send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -1060,13 +546,12 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
{
TABLE *table;
DBUG_ENTER("mysqld_list_fields");
- DBUG_PRINT("enter",("table: %s",table_list->real_name));
+ DBUG_PRINT("enter",("table: %s",table_list->table_name));
- if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
- {
- send_error(thd);
+ if (open_normal_and_derived_tables(thd, table_list, 0))
DBUG_VOID_RETURN;
- }
+ table= table_list->table;
+
List<Item> field_list;
Field **ptr,*field;
@@ -1076,8 +561,9 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
!wild_case_compare(system_charset_info, field->field_name,wild))
field_list.push_back(new Item_field(field));
}
- restore_record(table,default_values); // Get empty record
- if (thd->protocol->send_fields(&field_list,2))
+ restore_record(table, s->default_values); // Get empty record
+ if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS |
+ Protocol::SEND_EOF))
DBUG_VOID_RETURN;
thd->protocol->flush();
DBUG_VOID_RETURN;
@@ -1085,15 +571,15 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
int
-mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
+mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd)
{
Protocol *protocol= thd->protocol;
String *packet= protocol->storage_packet();
DBUG_ENTER("mysqld_dump_create_info");
- DBUG_PRINT("enter",("table: %s",table->real_name));
+ DBUG_PRINT("enter",("table: %s",table_list->table->s->table_name));
protocol->prepare_for_resend();
- if (store_create_info(thd, table, packet))
+ if (store_create_info(thd, table_list, packet))
DBUG_RETURN(-1);
if (fd < 0)
@@ -1113,7 +599,7 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
/*
Go through all character combinations and ensure that sql_lex.cc can
- parse it as an identifer.
+ parse it as an identifier.
SYNOPSIS
require_quotes()
@@ -1130,7 +616,7 @@ static const char *require_quotes(const char *name, uint name_length)
uint length;
const char *end= name + name_length;
- for ( ; name < end ; name++)
+ for (; name < end ; name++)
{
uchar chr= (uchar) *name;
length= my_mbcharlen(system_charset_info, chr);
@@ -1228,14 +714,17 @@ static void append_directory(THD *thd, String *packet, const char *dir_type,
packet->append(dir_type);
packet->append(" DIRECTORY='", 12);
#ifdef __WIN__
- char *winfilename = thd->memdup(filename, length);
- for (uint i=0; i < length; i++)
- if (winfilename[i] == '\\')
- winfilename[i] = '/';
- packet->append(winfilename, length);
-#else
- packet->append(filename, length);
+ /* Convert \ to / to be able to create table on unix */
+ char *winfilename= (char*) thd->memdup(filename, length);
+ char *pos, *end;
+ for (pos= winfilename, end= pos+length ; pos < end ; pos++)
+ {
+ if (*pos == '\\')
+ *pos = '/';
+ }
+ filename= winfilename;
#endif
+ packet->append(filename, length);
packet->append('\'');
}
}
@@ -1244,15 +733,18 @@ static void append_directory(THD *thd, String *packet, const char *dir_type,
#define LIST_PROCESS_HOST_LEN 64
static int
-store_create_info(THD *thd, TABLE *table, String *packet)
+store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
{
List<Item> field_list;
- char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, *alias;
+ char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end;
+ const char *alias;
String type(tmp, sizeof(tmp), system_charset_info);
Field **ptr,*field;
uint primary_key;
KEY *key_info;
+ TABLE *table= table_list->table;
handler *file= table->file;
+ TABLE_SHARE *share= table->s;
HA_CREATE_INFO create_info;
my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
MODE_ORACLE |
@@ -1263,18 +755,20 @@ store_create_info(THD *thd, TABLE *table, String *packet)
my_bool limited_mysql_mode= (thd->variables.sql_mode &
(MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
MODE_MYSQL40)) != 0;
-
DBUG_ENTER("store_create_info");
- DBUG_PRINT("enter",("table: %s",table->real_name));
+ DBUG_PRINT("enter",("table: %s", table->s->table_name));
- restore_record(table,default_values); // Get empty record
+ restore_record(table, s->default_values); // Get empty record
- if (table->tmp_table)
+ if (share->tmp_table)
packet->append("CREATE TEMPORARY TABLE ", 23);
else
packet->append("CREATE TABLE ", 13);
- alias= (lower_case_table_names == 2 ? table->table_name :
- table->real_name);
+ if (table_list->schema_table)
+ alias= table_list->schema_table->table_name;
+ else
+ alias= (lower_case_table_names == 2 ? table->alias :
+ share->table_name);
append_identifier(thd, packet, alias, strlen(alias));
packet->append(" (\n", 3);
@@ -1301,7 +795,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
if (field->has_charset() && !limited_mysql_mode && !foreign_db_mode)
{
- if (field->charset() != table->table_charset)
+ if (field->charset() != share->table_charset)
{
packet->append(" character set ", 15);
packet->append(field->charset()->csname);
@@ -1336,6 +830,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
field->unireg_check != Field::TIMESTAMP_UN_FIELD;
has_default= (field->type() != FIELD_TYPE_BLOB &&
+ !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
field->unireg_check != Field::NEXT_NUMBER &&
!((foreign_db_mode || limited_mysql_mode) &&
has_now_default));
@@ -1386,9 +881,9 @@ store_create_info(THD *thd, TABLE *table, String *packet)
file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
bzero((char*) &create_info, sizeof(create_info));
file->update_create_info(&create_info);
- primary_key= table->primary_key;
+ primary_key= share->primary_key;
- for (uint i=0 ; i < table->keys ; i++,key_info++)
+ for (uint i=0 ; i < share->keys ; i++,key_info++)
{
KEY_PART_INFO *key_part= key_info->key_part;
bool found_primary=0;
@@ -1414,17 +909,17 @@ store_create_info(THD *thd, TABLE *table, String *packet)
!limited_mysql_mode && !foreign_db_mode)
{
if (key_info->algorithm == HA_KEY_ALG_BTREE)
- packet->append(" USING BTREE", 12);
-
+ packet->append(" USING BTREE", 12);
+
if (key_info->algorithm == HA_KEY_ALG_HASH)
- packet->append(" USING HASH", 11);
-
+ packet->append(" USING HASH", 11);
+
// +BAR: send USING only in non-default case: non-spatial rtree
if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
!(key_info->flags & HA_SPATIAL))
- packet->append(" USING RTREE", 12);
+ packet->append(" USING RTREE", 12);
- // No need to send TYPE FULLTEXT, it is sent as FULLTEXT KEY
+ // No need to send USING FULLTEXT, it is sent as FULLTEXT KEY
}
packet->append(" (", 2);
@@ -1472,58 +967,58 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(" ENGINE=", 8);
packet->append(file->table_type());
- if (table->table_charset &&
+ if (share->table_charset &&
!(thd->variables.sql_mode & MODE_MYSQL323) &&
!(thd->variables.sql_mode & MODE_MYSQL40))
{
packet->append(" DEFAULT CHARSET=", 17);
- packet->append(table->table_charset->csname);
- if (!(table->table_charset->state & MY_CS_PRIMARY))
+ packet->append(share->table_charset->csname);
+ if (!(share->table_charset->state & MY_CS_PRIMARY))
{
packet->append(" COLLATE=", 9);
- packet->append(table->table_charset->name);
+ packet->append(table->s->table_charset->name);
}
}
- if (table->min_rows)
+ if (share->min_rows)
{
packet->append(" MIN_ROWS=", 10);
- end= longlong10_to_str(table->min_rows, buff, 10);
+ end= longlong10_to_str(share->min_rows, buff, 10);
packet->append(buff, (uint) (end- buff));
}
- if (table->max_rows)
+ if (share->max_rows && !table_list->schema_table)
{
packet->append(" MAX_ROWS=", 10);
- end= longlong10_to_str(table->max_rows, buff, 10);
+ end= longlong10_to_str(share->max_rows, buff, 10);
packet->append(buff, (uint) (end - buff));
}
- if (table->avg_row_length)
+ if (share->avg_row_length)
{
packet->append(" AVG_ROW_LENGTH=", 16);
- end= longlong10_to_str(table->avg_row_length, buff,10);
+ end= longlong10_to_str(share->avg_row_length, buff,10);
packet->append(buff, (uint) (end - buff));
}
- if (table->db_create_options & HA_OPTION_PACK_KEYS)
+ if (share->db_create_options & HA_OPTION_PACK_KEYS)
packet->append(" PACK_KEYS=1", 12);
- if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
+ if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
packet->append(" PACK_KEYS=0", 12);
- if (table->db_create_options & HA_OPTION_CHECKSUM)
+ if (share->db_create_options & HA_OPTION_CHECKSUM)
packet->append(" CHECKSUM=1", 11);
- if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
+ if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
packet->append(" DELAY_KEY_WRITE=1",18);
- if (table->row_type != ROW_TYPE_DEFAULT)
+ if (share->row_type != ROW_TYPE_DEFAULT)
{
packet->append(" ROW_FORMAT=",12);
- packet->append(ha_row_type[(uint) table->row_type]);
+ packet->append(ha_row_type[(uint) share->row_type]);
}
table->file->append_create_info(packet);
- if (table->comment && table->comment[0])
+ if (share->comment && share->comment[0])
{
packet->append(" COMMENT=", 9);
- append_unescaped(packet, table->comment, strlen(table->comment));
+ append_unescaped(packet, share->comment, strlen(share->comment));
}
if (file->raid_type)
{
@@ -1540,6 +1035,97 @@ store_create_info(THD *thd, TABLE *table, String *packet)
DBUG_RETURN(0);
}
+void
+view_store_options(THD *thd, TABLE_LIST *table, String *buff)
+{
+ buff->append("ALGORITHM=", 10);
+ switch ((int8)table->algorithm) {
+ case VIEW_ALGORITHM_UNDEFINED:
+ buff->append("UNDEFINED ", 10);
+ break;
+ case VIEW_ALGORITHM_TMPTABLE:
+ buff->append("TEMPTABLE ", 10);
+ break;
+ case VIEW_ALGORITHM_MERGE:
+ buff->append("MERGE ", 6);
+ break;
+ default:
+ DBUG_ASSERT(0); // never should happen
+ }
+ buff->append("DEFINER=", 8);
+ append_identifier(thd, buff,
+ table->definer.user.str, table->definer.user.length);
+ buff->append('@');
+ append_identifier(thd, buff,
+ table->definer.host.str, table->definer.host.length);
+ if (table->view_suid)
+ buff->append(" SQL SECURITY DEFINER ", 22);
+ else
+ buff->append(" SQL SECURITY INVOKER ", 22);
+}
+
+static int
+view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
+{
+ my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
+ MODE_ORACLE |
+ MODE_MSSQL |
+ MODE_DB2 |
+ MODE_MAXDB |
+ MODE_ANSI)) != 0;
+ /*
+ Compact output format for view can be used
+ - if user has db of this view as current db
+ - if this view only references table inside it's own db
+ */
+ if (!thd->db || strcmp(thd->db, table->view_db.str))
+ table->compact_view_format= FALSE;
+ else
+ {
+ TABLE_LIST *tbl;
+ table->compact_view_format= TRUE;
+ for (tbl= thd->lex->query_tables;
+ tbl;
+ tbl= tbl->next_global)
+ {
+ if (strcmp(table->view_db.str, tbl->view ? tbl->view_db.str :tbl->db)!= 0)
+ {
+ table->compact_view_format= FALSE;
+ break;
+ }
+ }
+ }
+
+ buff->append("CREATE ", 7);
+ if (!foreign_db_mode)
+ {
+ view_store_options(thd, table, buff);
+ }
+ buff->append("VIEW ", 5);
+ if (!table->compact_view_format)
+ {
+ append_identifier(thd, buff, table->view_db.str, table->view_db.length);
+ buff->append('.');
+ }
+ append_identifier(thd, buff, table->view_name.str, table->view_name.length);
+ buff->append(" AS ", 4);
+
+ /*
+ We can't just use table->query, because our SQL_MODE may trigger
+ a different syntax, like when ANSI_QUOTES is defined.
+ */
+ table->view->unit.print(buff);
+
+ if (table->with_check != VIEW_CHECK_NONE)
+ {
+ if (table->with_check == VIEW_CHECK_LOCAL)
+ buff->append(" WITH LOCAL CHECK OPTION", 24);
+ else
+ buff->append(" WITH CASCADED CHECK OPTION", 27);
+ }
+ return 0;
+}
+
/****************************************************************************
Return info about all processes
@@ -1548,9 +1134,13 @@ store_create_info(THD *thd, TABLE *table, String *packet)
class thread_info :public ilink {
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
static void operator delete(void *ptr __attribute__((unused)),
- size_t size __attribute__((unused))) {} /*lint -e715 */
+ size_t size __attribute__((unused)))
+ { TRASH(ptr, size); }
ulong thread_id;
time_t start_time;
@@ -1559,7 +1149,7 @@ public:
char *query;
};
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class I_List<thread_info>;
#endif
@@ -1584,7 +1174,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
field->maybe_null=1;
field_list.push_back(field=new Item_empty_string("Info",max_query_length));
field->maybe_null=1;
- if (protocol->send_fields(&field_list,1))
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_VOID_RETURN;
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
@@ -1617,7 +1208,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
thd_info->command=(int) tmp->command;
if ((mysys_var= tmp->mysys_var))
pthread_mutex_lock(&mysys_var->mutex);
- thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
+ thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
#ifndef EMBEDDED_LIBRARY
thd_info->state_info= (char*) (tmp->locked ? "Locked" :
tmp->net.reading_or_writing ?
@@ -1691,431 +1282,2833 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
Status functions
*****************************************************************************/
-static bool write_collation(Protocol *protocol, CHARSET_INFO *cs)
+
+static bool show_status_array(THD *thd, const char *wild,
+ show_var_st *variables,
+ enum enum_var_type value_type,
+ struct system_status_var *status_var,
+ const char *prefix, TABLE *table)
{
- protocol->prepare_for_resend();
- protocol->store(cs->name, system_charset_info);
- protocol->store(cs->csname, system_charset_info);
- protocol->store_short((longlong) cs->number);
- protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info);
- protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info);
- protocol->store_short((longlong) cs->strxfrm_multiply);
- return protocol->write();
+ char buff[1024], *prefix_end;
+ /* the variable name should not be longer then 80 characters */
+ char name_buffer[80];
+ int len;
+ LEX_STRING null_lex_str;
+ DBUG_ENTER("show_status_array");
+
+ null_lex_str.str= 0; // For sys_var->value_ptr()
+ null_lex_str.length= 0;
+
+ prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
+ len=name_buffer + sizeof(name_buffer) - prefix_end;
+
+ for (; variables->name; variables++)
+ {
+ strnmov(prefix_end, variables->name, len);
+ name_buffer[sizeof(name_buffer)-1]=0; /* Safety */
+ SHOW_TYPE show_type=variables->type;
+ if (show_type == SHOW_VARS)
+ {
+ show_status_array(thd, wild, (show_var_st *) variables->value,
+ value_type, status_var, variables->name, table);
+ }
+ else
+ {
+ if (!(wild && wild[0] && wild_case_compare(system_charset_info,
+ name_buffer, wild)))
+ {
+ char *value=variables->value;
+ const char *pos, *end; // We assign a lot of const's
+ long nr;
+ if (show_type == SHOW_SYS)
+ {
+ show_type= ((sys_var*) value)->type();
+ value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
+ &null_lex_str);
+ }
+
+ pos= end= buff;
+ switch (show_type) {
+ case SHOW_LONG_STATUS:
+ case SHOW_LONG_CONST_STATUS:
+ value= ((char *) status_var + (ulong) value);
+ /* fall through */
+ case SHOW_LONG:
+ case SHOW_LONG_CONST:
+ end= int10_to_str(*(long*) value, buff, 10);
+ break;
+ case SHOW_LONGLONG:
+ end= longlong10_to_str(*(longlong*) value, buff, 10);
+ break;
+ case SHOW_HA_ROWS:
+ end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
+ break;
+ case SHOW_BOOL:
+ end= strmov(buff, *(bool*) value ? "ON" : "OFF");
+ break;
+ case SHOW_MY_BOOL:
+ end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
+ break;
+ case SHOW_INT_CONST:
+ case SHOW_INT:
+ end= int10_to_str((long) *(uint32*) value, buff, 10);
+ break;
+ case SHOW_HAVE:
+ {
+ SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
+ pos= show_comp_option_name[(int) tmp];
+ end= strend(pos);
+ break;
+ }
+ case SHOW_CHAR:
+ {
+ if (!(pos= value))
+ pos= "";
+ end= strend(pos);
+ break;
+ }
+ case SHOW_STARTTIME:
+ nr= (long) (thd->query_start() - start_time);
+ end= int10_to_str(nr, buff, 10);
+ break;
+ case SHOW_QUESTION:
+ end= int10_to_str((long) thd->query_id, buff, 10);
+ break;
+#ifdef HAVE_REPLICATION
+ case SHOW_RPL_STATUS:
+ end= strmov(buff, rpl_status_type[(int)rpl_status]);
+ break;
+ case SHOW_SLAVE_RUNNING:
+ {
+ pthread_mutex_lock(&LOCK_active_mi);
+ end= strmov(buff, (active_mi->slave_running &&
+ active_mi->rli.slave_running) ? "ON" : "OFF");
+ pthread_mutex_unlock(&LOCK_active_mi);
+ break;
+ }
+ case SHOW_SLAVE_RETRIED_TRANS:
+ {
+ /*
+ TODO: in 5.1 with multimaster, have one such counter per line in
+ SHOW SLAVE STATUS, and have the sum over all lines here.
+ */
+ pthread_mutex_lock(&LOCK_active_mi);
+ pthread_mutex_lock(&active_mi->rli.data_lock);
+ end= int10_to_str(active_mi->rli.retried_trans, buff, 10);
+ pthread_mutex_unlock(&active_mi->rli.data_lock);
+ pthread_mutex_unlock(&LOCK_active_mi);
+ break;
+ }
+ case SHOW_SLAVE_SKIP_ERRORS:
+ {
+ MY_BITMAP *bitmap= (MY_BITMAP *)value;
+ if (!use_slave_mask || bitmap_is_clear_all(bitmap))
+ {
+ end= strmov(buff, "OFF");
+ }
+ else if (bitmap_is_set_all(bitmap))
+ {
+ end= strmov(buff, "ALL");
+ }
+ else
+ {
+ /* 10 is enough assuming errors are max 4 digits */
+ int i;
+ for (i= 1;
+ i < MAX_SLAVE_ERROR && (uint) (end-buff) < sizeof(buff)-10;
+ i++)
+ {
+ if (bitmap_is_set(bitmap, i))
+ {
+ end= int10_to_str(i, (char*) end, 10);
+ *(char*) end++= ',';
+ }
+ }
+ if (end != buff)
+ end--; // Remove last ','
+ if (i < MAX_SLAVE_ERROR)
+ end= strmov((char*) end, "..."); // Couldn't show all errors
+ }
+ break;
+ }
+#endif /* HAVE_REPLICATION */
+ case SHOW_OPENTABLES:
+ end= int10_to_str((long) cached_tables(), buff, 10);
+ break;
+ case SHOW_CHAR_PTR:
+ {
+ if (!(pos= *(char**) value))
+ pos= "";
+ end= strend(pos);
+ break;
+ }
+ case SHOW_DOUBLE_STATUS:
+ {
+ value= ((char *) status_var + (ulong) value);
+ end= buff + sprintf(buff, "%f", *(double*) value);
+ break;
+ }
+#ifdef HAVE_OPENSSL
+ /* First group - functions relying on CTX */
+ case SHOW_SSL_CTX_SESS_ACCEPT:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_good(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_good(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_CB_HITS:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_HITS:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_hits(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_CACHE_FULL:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cache_full(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_MISSES:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_misses(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_TIMEOUTS:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_SESS_NUMBER:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_GET_VERIFY_MODE:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
+ if (!ssl_acceptor_fd)
+ {
+ pos= "NONE";
+ end= pos+4;
+ break;
+ }
+ switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
+ {
+ case SSL_SESS_CACHE_OFF:
+ pos= "OFF";
+ break;
+ case SSL_SESS_CACHE_CLIENT:
+ pos= "CLIENT";
+ break;
+ case SSL_SESS_CACHE_SERVER:
+ pos= "SERVER";
+ break;
+ case SSL_SESS_CACHE_BOTH:
+ pos= "BOTH";
+ break;
+ case SSL_SESS_CACHE_NO_AUTO_CLEAR:
+ pos= "NO_AUTO_CLEAR";
+ break;
+ case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
+ pos= "NO_INTERNAL_LOOKUP";
+ break;
+ default:
+ pos= "Unknown";
+ break;
+ }
+ end= strend(pos);
+ break;
+ /* First group - functions relying on SSL */
+ case SHOW_SSL_GET_VERSION:
+ pos= (thd->net.vio->ssl_arg ?
+ SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
+ end= strend(pos);
+ break;
+ case SHOW_SSL_SESSION_REUSED:
+ end= int10_to_str((long) (thd->net.vio->ssl_arg ?
+ SSL_session_reused((SSL*) thd->net.vio->
+ ssl_arg) :
+ 0),
+ buff, 10);
+ break;
+ case SHOW_SSL_GET_DEFAULT_TIMEOUT:
+ end= int10_to_str((long) (thd->net.vio->ssl_arg ?
+ SSL_get_default_timeout((SSL*) thd->net.vio->
+ ssl_arg) :
+ 0),
+ buff, 10);
+ break;
+ case SHOW_SSL_GET_VERIFY_MODE:
+ end= int10_to_str((long) (thd->net.vio->ssl_arg ?
+ SSL_get_verify_mode((SSL*) thd->net.vio->
+ ssl_arg):
+ 0),
+ buff, 10);
+ break;
+ case SHOW_SSL_GET_VERIFY_DEPTH:
+ end= int10_to_str((long) (thd->net.vio->ssl_arg ?
+ SSL_get_verify_depth((SSL*) thd->net.vio->
+ ssl_arg):
+ 0),
+ buff, 10);
+ break;
+ case SHOW_SSL_GET_CIPHER:
+ pos= (thd->net.vio->ssl_arg ?
+ SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" );
+ end= strend(pos);
+ break;
+ case SHOW_SSL_GET_CIPHER_LIST:
+ if (thd->net.vio->ssl_arg)
+ {
+ char *to= buff;
+ for (int i=0 ; i++ ;)
+ {
+ const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i);
+ if (p == NULL)
+ break;
+ to= strmov(to, p);
+ *to++= ':';
+ }
+ if (to != buff)
+ to--; // Remove last ':'
+ end= to;
+ }
+ break;
+
+#endif /* HAVE_OPENSSL */
+ case SHOW_KEY_CACHE_LONG:
+ case SHOW_KEY_CACHE_CONST_LONG:
+ value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache;
+ end= int10_to_str(*(long*) value, buff, 10);
+ break;
+ case SHOW_KEY_CACHE_LONGLONG:
+ value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache;
+ end= longlong10_to_str(*(longlong*) value, buff, 10);
+ break;
+ case SHOW_UNDEF: // Show never happen
+ case SHOW_SYS:
+ break; // Return empty string
+ default:
+ break;
+ }
+ restore_record(table, s->default_values);
+ table->field[0]->store(name_buffer, strlen(name_buffer),
+ system_charset_info);
+ table->field[1]->store(pos, (uint32) (end - pos), system_charset_info);
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+
+ DBUG_RETURN(FALSE);
}
-int mysqld_show_collations(THD *thd, const char *wild)
+
+/* collect status for all running threads */
+
+void calc_sum_of_all_status(STATUS_VAR *to)
{
- char buff[8192];
- String packet2(buff,sizeof(buff),thd->charset());
- List<Item> field_list;
- CHARSET_INFO **cs;
- Protocol *protocol= thd->protocol;
+ DBUG_ENTER("calc_sum_of_all_status");
+
+ /* Ensure that thread id not killed during loop */
+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
+
+ I_List_iterator<THD> it(threads);
+ THD *tmp;
+
+ /* Get global values as base */
+ *to= global_status_var;
+
+ /* Add to this status from existing threads */
+ while ((tmp= it++))
+ add_to_status(to, &tmp->status_var);
+
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ DBUG_VOID_RETURN;
+}
+
+
+LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
+ const char* str, uint length,
+ bool allocate_lex_string)
+{
+ MEM_ROOT *mem= thd->mem_root;
+ if (allocate_lex_string)
+ lex_str= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
+ lex_str->str= strmake_root(mem, str, length);
+ lex_str->length= length;
+ return lex_str;
+}
+
+
+/* INFORMATION_SCHEMA name */
+LEX_STRING information_schema_name= {(char*)"information_schema", 18};
+
+/* This is only used internally, but we need it here as a forward reference */
+extern ST_SCHEMA_TABLE schema_tables[];
+
+typedef struct st_index_field_values
+{
+ const char *db_value, *table_value;
+} INDEX_FIELD_VALUES;
+
+
+/*
+ Store record to I_S table, convert HEAP table
+ to MyISAM if necessary
+
+ SYNOPSIS
+ schema_table_store_record()
+ thd thread handler
+ table Information schema table to be updated
+
+ RETURN
+ 0 success
+ 1 error
+*/
+
+static bool schema_table_store_record(THD *thd, TABLE *table)
+{
+ int error;
+ if ((error= table->file->write_row(table->record[0])))
+ {
+ if (create_myisam_from_heap(thd, table,
+ table->pos_in_table_list->schema_table_param,
+ error, 0))
+ return 1;
+ }
+ return 0;
+}
+
+
+void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values)
+{
+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
+ switch (lex->orig_sql_command) {
+ case SQLCOM_SHOW_DATABASES:
+ index_field_values->db_value= wild;
+ break;
+ case SQLCOM_SHOW_TABLES:
+ case SQLCOM_SHOW_TABLE_STATUS:
+ case SQLCOM_SHOW_TRIGGERS:
+ index_field_values->db_value= lex->select_lex.db;
+ index_field_values->table_value= wild;
+ break;
+ default:
+ index_field_values->db_value= NullS;
+ index_field_values->table_value= NullS;
+ break;
+ }
+}
+
+
+int make_table_list(THD *thd, SELECT_LEX *sel,
+ char *db, char *table)
+{
+ Table_ident *table_ident;
+ LEX_STRING ident_db, ident_table;
+ ident_db.str= db;
+ ident_db.length= strlen(db);
+ ident_table.str= table;
+ ident_table.length= strlen(table);
+ table_ident= new Table_ident(thd, ident_db, ident_table, 1);
+ sel->init_query();
+ if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
+ (List<String> *) 0, (List<String> *) 0))
+ return 1;
+ return 0;
+}
+
+
+bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
+{
+ if (item->type() == Item::FUNC_ITEM)
+ {
+ Item_func *item_func= (Item_func*)item;
+ Item **child;
+ Item **item_end= (item_func->arguments()) + item_func->argument_count();
+ for (child= item_func->arguments(); child != item_end; child++)
+ {
+ if (!uses_only_table_name_fields(*child, table))
+ return 0;
+ }
+ }
+ else if (item->type() == Item::FIELD_ITEM)
+ {
+ Item_field *item_field= (Item_field*)item;
+ CHARSET_INFO *cs= system_charset_info;
+ ST_SCHEMA_TABLE *schema_table= table->schema_table;
+ ST_FIELD_INFO *field_info= schema_table->fields_info;
+ const char *field_name1= schema_table->idx_field1 >= 0 ? field_info[schema_table->idx_field1].field_name : "";
+ const char *field_name2= schema_table->idx_field2 >= 0 ? field_info[schema_table->idx_field2].field_name : "";
+ if (table->table != item_field->field->table ||
+ (cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
+ (uchar *) item_field->field_name,
+ strlen(item_field->field_name), 0) &&
+ cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2),
+ (uchar *) item_field->field_name,
+ strlen(item_field->field_name), 0)))
+ return 0;
+ }
+ else if (item->type() == Item::REF_ITEM)
+ return uses_only_table_name_fields(item->real_item(), table);
+ if (item->type() == Item::SUBSELECT_ITEM &&
+ !item->const_item())
+ return 0;
+
+ return 1;
+}
- DBUG_ENTER("mysqld_show_charsets");
- field_list.push_back(new Item_empty_string("Collation",30));
- field_list.push_back(new Item_empty_string("Charset",30));
- field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
- field_list.push_back(new Item_empty_string("Default",30));
- field_list.push_back(new Item_empty_string("Compiled",30));
- field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT));
+static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table)
+{
+ if (!cond)
+ return (COND*) 0;
+ if (cond->type() == Item::COND_ITEM)
+ {
+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ /* Create new top level AND item */
+ Item_cond_and *new_cond=new Item_cond_and;
+ if (!new_cond)
+ return (COND*) 0;
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ Item *fix= make_cond_for_info_schema(item, table);
+ if (fix)
+ new_cond->argument_list()->push_back(fix);
+ }
+ switch (new_cond->argument_list()->elements) {
+ case 0:
+ return (COND*) 0;
+ case 1:
+ return new_cond->argument_list()->head();
+ default:
+ new_cond->quick_fix_field();
+ return new_cond;
+ }
+ }
+ else
+ { // Or list
+ Item_cond_or *new_cond=new Item_cond_or;
+ if (!new_cond)
+ return (COND*) 0;
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ Item *fix=make_cond_for_info_schema(item, table);
+ if (!fix)
+ return (COND*) 0;
+ new_cond->argument_list()->push_back(fix);
+ }
+ new_cond->quick_fix_field();
+ new_cond->top_level_item();
+ return new_cond;
+ }
+ }
+
+ if (!uses_only_table_name_fields(cond, table))
+ return (COND*) 0;
+ return cond;
+}
+
+
+enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
+{
+ return (enum enum_schema_tables) (schema_table - &schema_tables[0]);
+}
- if (protocol->send_fields(&field_list, 1))
+
+/*
+ Create db names list. Information schema name always is first in list
+
+ SYNOPSIS
+ make_db_list()
+ thd thread handler
+ files list of db names
+ wild wild string
+ idx_field_vals idx_field_vals->db_name contains db name or
+ wild string
+ with_i_schema returns 1 if we added 'IS' name to list
+ otherwise returns 0
+ is_wild_value if value is 1 then idx_field_vals->db_name is
+ wild string otherwise it's db name;
+
+ RETURN
+ 1 error
+ 0 success
+*/
+
+int make_db_list(THD *thd, List<char> *files,
+ INDEX_FIELD_VALUES *idx_field_vals,
+ bool *with_i_schema, bool is_wild_value)
+{
+ LEX *lex= thd->lex;
+ *with_i_schema= 0;
+ get_index_field_values(lex, idx_field_vals);
+ if (is_wild_value)
+ {
+ /*
+ This part of code is only for SHOW DATABASES command.
+ idx_field_vals->db_value can be 0 when we don't use
+ LIKE clause (see also get_index_field_values() function)
+ */
+ if (!idx_field_vals->db_value ||
+ !wild_case_compare(system_charset_info,
+ information_schema_name.str,
+ idx_field_vals->db_value))
+ {
+ *with_i_schema= 1;
+ if (files->push_back(thd->strdup(information_schema_name.str)))
+ return 1;
+ }
+ return mysql_find_files(thd, files, NullS, mysql_data_home,
+ idx_field_vals->db_value, 1);
+ }
+
+ /*
+ This part of code is for SHOW TABLES, SHOW TABLE STATUS commands.
+ idx_field_vals->db_value can't be 0 (see get_index_field_values()
+ function). lex->orig_sql_command can be not equal to SQLCOM_END
+ only in case of executing of SHOW commands.
+ */
+ if (lex->orig_sql_command != SQLCOM_END)
+ {
+ if (!my_strcasecmp(system_charset_info, information_schema_name.str,
+ idx_field_vals->db_value))
+ {
+ *with_i_schema= 1;
+ return files->push_back(thd->strdup(information_schema_name.str));
+ }
+ return files->push_back(thd->strdup(idx_field_vals->db_value));
+ }
+
+ /*
+ Create list of existing databases. It is used in case
+ of select from information schema table
+ */
+ if (files->push_back(thd->strdup(information_schema_name.str)))
+ return 1;
+ *with_i_schema= 1;
+ return mysql_find_files(thd, files, NullS, mysql_data_home, NullS, 1);
+}
+
+
+int schema_tables_add(THD *thd, List<char> *files, const char *wild)
+{
+ ST_SCHEMA_TABLE *tmp_schema_table= schema_tables;
+ for (; tmp_schema_table->table_name; tmp_schema_table++)
+ {
+ if (tmp_schema_table->hidden)
+ continue;
+ if (wild)
+ {
+ if (lower_case_table_names)
+ {
+ if (wild_case_compare(files_charset_info,
+ tmp_schema_table->table_name,
+ wild))
+ continue;
+ }
+ else if (wild_compare(tmp_schema_table->table_name, wild, 0))
+ continue;
+ }
+ if (files->push_back(thd->strdup(tmp_schema_table->table_name)))
+ return 1;
+ }
+ return 0;
+}
+
+
+int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ LEX *lex= thd->lex;
+ TABLE *table= tables->table;
+ SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *old_all_select_lex= lex->all_selects_list;
+ TABLE_LIST **save_query_tables_last= lex->query_tables_last;
+ enum_sql_command save_sql_command= lex->sql_command;
+ SELECT_LEX *lsel= tables->schema_select_lex;
+ ST_SCHEMA_TABLE *schema_table= tables->schema_table;
+ SELECT_LEX sel;
+ INDEX_FIELD_VALUES idx_field_vals;
+ char path[FN_REFLEN], *end, *base_name, *file_name;
+ uint len;
+ bool with_i_schema;
+ enum enum_schema_tables schema_table_idx;
+ List<char> bases;
+ List_iterator_fast<char> it(bases);
+ COND *partial_cond;
+ uint derived_tables= lex->derived_tables;
+ int error= 1;
+ Open_tables_state open_tables_state_backup;
+ DBUG_ENTER("get_all_tables");
+
+ LINT_INIT(end);
+ LINT_INIT(len);
+
+ /*
+ Let us set fake sql_command so views won't try to merge
+ themselves into main statement.
+ */
+ lex->sql_command= SQLCOM_SHOW_FIELDS;
+
+ /*
+ We should not introduce deadlocks even if we already have some
+ tables open and locked, since we won't lock tables which we will
+ open and will ignore possible name-locks for these tables.
+ */
+ thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
+
+ if (lsel)
+ {
+ TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first;
+ bool res;
+
+ lex->all_selects_list= lsel;
+ res= open_normal_and_derived_tables(thd, show_table_list,
+ MYSQL_LOCK_IGNORE_FLUSH);
+ /*
+ get_all_tables() returns 1 on failure and 0 on success thus
+ return only these and not the result code of ::process_table()
+
+ We should use show_table_list->alias instead of
+ show_table_list->table_name because table_name
+ could be changed during opening of I_S tables. It's safe
+ to use alias because alias contains original table name
+ in this case(this part of code is used only for
+ 'show columns' & 'show statistics' commands).
+ */
+ error= test(schema_table->process_table(thd, show_table_list,
+ table, res,
+ (show_table_list->view ?
+ show_table_list->view_db.str :
+ show_table_list->db),
+ show_table_list->alias));
+ close_thread_tables(thd);
+ show_table_list->table= 0;
+ goto err;
+ }
+
+ schema_table_idx= get_schema_table_idx(schema_table);
+
+ if (make_db_list(thd, &bases, &idx_field_vals,
+ &with_i_schema, 0))
+ goto err;
+
+ partial_cond= make_cond_for_info_schema(cond, tables);
+ it.rewind(); /* To get access to new elements in basis list */
+ while ((base_name= it++) ||
+ /*
+ generate error for non existing database.
+ (to save old behaviour for SHOW TABLES FROM db)
+ */
+ ((lex->orig_sql_command == SQLCOM_SHOW_TABLES ||
+ lex->orig_sql_command == SQLCOM_SHOW_TABLE_STATUS) &&
+ (base_name= select_lex->db) && !bases.elements))
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (!check_access(thd,SELECT_ACL, base_name,
+ &thd->col_access, 0, 1, with_i_schema) ||
+ thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
+ acl_get(thd->host, thd->ip, thd->priv_user, base_name,0) ||
+ (grant_option && !check_grant_db(thd, base_name)))
+#endif
+ {
+ List<char> files;
+ if (with_i_schema) // information schema table names
+ {
+ if (schema_tables_add(thd, &files, idx_field_vals.table_value))
+ goto err;
+ }
+ else
+ {
+ strxmov(path, mysql_data_home, "/", base_name, NullS);
+ end= path + (len= unpack_dirname(path,path));
+ len= FN_LEN - len;
+ if (mysql_find_files(thd, &files, base_name,
+ path, idx_field_vals.table_value, 0))
+ goto err;
+ }
+
+ List_iterator_fast<char> it_files(files);
+ while ((file_name= it_files++))
+ {
+ restore_record(table, s->default_values);
+ table->field[schema_table->idx_field1]->
+ store(base_name, strlen(base_name), system_charset_info);
+ table->field[schema_table->idx_field2]->
+ store(file_name, strlen(file_name),system_charset_info);
+ if (!partial_cond || partial_cond->val_int())
+ {
+ if (schema_table_idx == SCH_TABLE_NAMES)
+ {
+ if (lex->verbose || lex->orig_sql_command == SQLCOM_END)
+ {
+ if (with_i_schema)
+ {
+ table->field[3]->store("SYSTEM VIEW", 11, system_charset_info);
+ }
+ else
+ {
+ my_snprintf(end, len, "/%s%s", file_name, reg_ext);
+ switch (mysql_frm_type(path)) {
+ case FRMTYPE_ERROR:
+ table->field[3]->store("ERROR", 5, system_charset_info);
+ break;
+ case FRMTYPE_TABLE:
+ table->field[3]->store("BASE TABLE", 10, system_charset_info);
+ break;
+ case FRMTYPE_VIEW:
+ table->field[3]->store("VIEW", 4, system_charset_info);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+ }
+ if (schema_table_store_record(thd, table))
+ goto err;
+ }
+ else
+ {
+ int res;
+ /*
+ Set the parent lex of 'sel' because it is needed by sel.init_query()
+ which is called inside make_table_list.
+ */
+ sel.parent_lex= lex;
+ if (make_table_list(thd, &sel, base_name, file_name))
+ goto err;
+ TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first;
+ lex->all_selects_list= &sel;
+ lex->derived_tables= 0;
+ res= open_normal_and_derived_tables(thd, show_table_list,
+ MYSQL_LOCK_IGNORE_FLUSH);
+ /*
+ We should use show_table_list->alias instead of
+ show_table_list->table_name because table_name
+ could be changed during opening of I_S tables. It's safe
+ to use alias because alias contains original table name
+ in this case.
+ */
+ res= schema_table->process_table(thd, show_table_list, table,
+ res, base_name,
+ show_table_list->alias);
+ close_thread_tables(thd);
+ if (res)
+ goto err;
+ }
+ }
+ }
+ /*
+ If we have information schema its always the first table and only
+ the first table. Reset for other tables.
+ */
+ with_i_schema= 0;
+ }
+ }
+
+ error= 0;
+err:
+ thd->restore_backup_open_tables_state(&open_tables_state_backup);
+ lex->derived_tables= derived_tables;
+ lex->all_selects_list= old_all_select_lex;
+ lex->query_tables_last= save_query_tables_last;
+ *save_query_tables_last= 0;
+ lex->sql_command= save_sql_command;
+ DBUG_RETURN(error);
+}
+
+
+bool store_schema_shemata(THD* thd, TABLE *table, const char *db_name,
+ CHARSET_INFO *cs)
+{
+ restore_record(table, s->default_values);
+ table->field[1]->store(db_name, strlen(db_name), system_charset_info);
+ table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info);
+ table->field[3]->store(cs->name, strlen(cs->name), system_charset_info);
+ return schema_table_store_record(thd, table);
+}
+
+
+int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ char path[FN_REFLEN];
+ bool found_libchar;
+ INDEX_FIELD_VALUES idx_field_vals;
+ List<char> files;
+ char *file_name;
+ uint length;
+ bool with_i_schema;
+ HA_CREATE_INFO create;
+ TABLE *table= tables->table;
+ DBUG_ENTER("fill_schema_shemata");
+
+ if (make_db_list(thd, &files, &idx_field_vals,
+ &with_i_schema, 1))
DBUG_RETURN(1);
- for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
+ List_iterator_fast<char> it(files);
+ while ((file_name=it++))
{
- CHARSET_INFO **cl;
- if (!cs[0] || !(cs[0]->state & MY_CS_AVAILABLE) ||
- !(cs[0]->state & MY_CS_PRIMARY))
+ if (with_i_schema) // information schema name is always first in list
+ {
+ if (store_schema_shemata(thd, table, file_name,
+ system_charset_info))
+ DBUG_RETURN(1);
+ with_i_schema= 0;
continue;
- for ( cl= all_charsets; cl < all_charsets+255 ;cl ++)
+ }
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
+ acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) ||
+ (grant_option && !check_grant_db(thd, file_name)))
+#endif
{
- if (!cl[0] || !(cl[0]->state & MY_CS_AVAILABLE) ||
- !my_charset_same(cs[0],cl[0]))
- continue;
- if (!(wild && wild[0] &&
- wild_case_compare(system_charset_info,cl[0]->name,wild)))
+ strxmov(path, mysql_data_home, "/", file_name, NullS);
+ length=unpack_dirname(path,path); // Convert if not unix
+ found_libchar= 0;
+ if (length && path[length-1] == FN_LIBCHAR)
{
- if (write_collation(protocol, cl[0]))
- goto err;
+ found_libchar= 1;
+ path[length-1]=0; // remove ending '\'
}
+
+ if (found_libchar)
+ path[length-1]= FN_LIBCHAR;
+ strmov(path+length, MY_DB_OPT_FILE);
+ load_db_opt(thd, path, &create);
+ if (store_schema_shemata(thd, table, file_name,
+ create.default_table_charset))
+ DBUG_RETURN(1);
}
}
- send_eof(thd);
DBUG_RETURN(0);
-err:
- DBUG_RETURN(1);
}
-static bool write_charset(Protocol *protocol, CHARSET_INFO *cs)
+
+static int get_schema_tables_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
{
- protocol->prepare_for_resend();
- protocol->store(cs->csname, system_charset_info);
- protocol->store(cs->comment ? cs->comment : "", system_charset_info);
- protocol->store(cs->name, system_charset_info);
- protocol->store_short((longlong) cs->mbmaxlen);
- return protocol->write();
+ const char *tmp_buff;
+ TIME time;
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("get_schema_tables_record");
+
+ restore_record(table, s->default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(file_name, strlen(file_name), cs);
+ if (res)
+ {
+ /*
+ there was errors during opening tables
+ */
+ const char *error= thd->net.last_error;
+ table->field[20]->store(error, strlen(error), cs);
+ thd->clear_error();
+ }
+ else if (tables->view)
+ {
+ table->field[3]->store("VIEW", 4, cs);
+ table->field[20]->store("VIEW", 4, cs);
+ }
+ else
+ {
+ TABLE *show_table= tables->table;
+ TABLE_SHARE *share= show_table->s;
+ handler *file= show_table->file;
+
+ file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO |
+ HA_STATUS_NO_LOCK);
+ if (share->tmp_table == SYSTEM_TMP_TABLE)
+ table->field[3]->store("SYSTEM VIEW", 11, cs);
+ else if (share->tmp_table)
+ table->field[3]->store("LOCAL TEMPORARY", 15, cs);
+ else
+ table->field[3]->store("BASE TABLE", 10, cs);
+
+ for (int i= 4; i < 20; i++)
+ {
+ if (i == 7 || (i > 12 && i < 17) || i == 18)
+ continue;
+ table->field[i]->set_notnull();
+ }
+ tmp_buff= file->table_type();
+ table->field[4]->store(tmp_buff, strlen(tmp_buff), cs);
+ table->field[5]->store((longlong) share->frm_version, TRUE);
+ enum row_type row_type = file->get_row_type();
+ switch (row_type) {
+ case ROW_TYPE_NOT_USED:
+ case ROW_TYPE_DEFAULT:
+ tmp_buff= ((share->db_options_in_use &
+ HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
+ (share->db_options_in_use & HA_OPTION_PACK_RECORD) ?
+ "Dynamic" : "Fixed");
+ break;
+ case ROW_TYPE_FIXED:
+ tmp_buff= "Fixed";
+ break;
+ case ROW_TYPE_DYNAMIC:
+ tmp_buff= "Dynamic";
+ break;
+ case ROW_TYPE_COMPRESSED:
+ tmp_buff= "Compressed";
+ break;
+ case ROW_TYPE_REDUNDANT:
+ tmp_buff= "Redundant";
+ break;
+ case ROW_TYPE_COMPACT:
+ tmp_buff= "Compact";
+ break;
+ }
+ table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
+ if (!tables->schema_table)
+ {
+ table->field[7]->store((longlong) file->records, TRUE);
+ table->field[7]->set_notnull();
+ }
+ table->field[8]->store((longlong) file->mean_rec_length);
+ table->field[9]->store((longlong) file->data_file_length);
+ if (file->max_data_file_length)
+ {
+ table->field[10]->store((longlong) file->max_data_file_length);
+ }
+ table->field[11]->store((longlong) file->index_file_length);
+ table->field[12]->store((longlong) file->delete_length);
+ if (show_table->found_next_number_field)
+ {
+ table->field[13]->store((longlong) file->auto_increment_value, TRUE);
+ table->field[13]->set_notnull();
+ }
+ if (file->create_time)
+ {
+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
+ file->create_time);
+ table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ table->field[14]->set_notnull();
+ }
+ if (file->update_time)
+ {
+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
+ file->update_time);
+ table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ table->field[15]->set_notnull();
+ }
+ if (file->check_time)
+ {
+ thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
+ table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ table->field[16]->set_notnull();
+ }
+ tmp_buff= (share->table_charset ?
+ share->table_charset->name : "default");
+ table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
+ if (file->table_flags() & (ulong) HA_HAS_CHECKSUM)
+ {
+ table->field[18]->store((longlong) file->checksum(), TRUE);
+ table->field[18]->set_notnull();
+ }
+
+ char option_buff[350],*ptr;
+ ptr=option_buff;
+ if (share->min_rows)
+ {
+ ptr=strmov(ptr," min_rows=");
+ ptr=longlong10_to_str(share->min_rows,ptr,10);
+ }
+ if (share->max_rows)
+ {
+ ptr=strmov(ptr," max_rows=");
+ ptr=longlong10_to_str(share->max_rows,ptr,10);
+ }
+ if (share->avg_row_length)
+ {
+ ptr=strmov(ptr," avg_row_length=");
+ ptr=longlong10_to_str(share->avg_row_length,ptr,10);
+ }
+ if (share->db_create_options & HA_OPTION_PACK_KEYS)
+ ptr=strmov(ptr," pack_keys=1");
+ if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
+ ptr=strmov(ptr," pack_keys=0");
+ if (share->db_create_options & HA_OPTION_CHECKSUM)
+ ptr=strmov(ptr," checksum=1");
+ if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
+ ptr=strmov(ptr," delay_key_write=1");
+ if (share->row_type != ROW_TYPE_DEFAULT)
+ ptr=strxmov(ptr, " row_format=",
+ ha_row_type[(uint) share->row_type],
+ NullS);
+ if (file->raid_type)
+ {
+ char buff[100];
+ my_snprintf(buff,sizeof(buff),
+ " raid_type=%s raid_chunks=%d raid_chunksize=%ld",
+ my_raid_type(file->raid_type), file->raid_chunks,
+ file->raid_chunksize/RAID_BLOCK_SIZE);
+ ptr=strmov(ptr,buff);
+ }
+ table->field[19]->store(option_buff+1,
+ (ptr == option_buff ? 0 :
+ (uint) (ptr-option_buff)-1), cs);
+ {
+ char *comment;
+ comment= show_table->file->update_table_comment(share->comment);
+ if (comment)
+ {
+ table->field[20]->store(comment, strlen(comment), cs);
+ if (comment != share->comment)
+ my_free(comment, MYF(0));
+ }
+ }
+ }
+ DBUG_RETURN(schema_table_store_record(thd, table));
}
-int mysqld_show_charsets(THD *thd, const char *wild)
+
+static int get_schema_column_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ LEX *lex= thd->lex;
+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
+ CHARSET_INFO *cs= system_charset_info;
+ TABLE *show_table;
+ handler *file;
+ Field **ptr,*field;
+ int count;
+ uint base_name_length, file_name_length;
+ DBUG_ENTER("get_schema_column_record");
+
+ if (res)
+ {
+ if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS)
+ {
+ /*
+ I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
+ rather than in SHOW COLUMNS
+ */
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd->net.last_errno, thd->net.last_error);
+ thd->clear_error();
+ res= 0;
+ }
+ DBUG_RETURN(res);
+ }
+
+ show_table= tables->table;
+ file= show_table->file;
+ count= 0;
+ file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ restore_record(show_table, s->default_values);
+ base_name_length= strlen(base_name);
+ file_name_length= strlen(file_name);
+
+ for (ptr=show_table->field; (field= *ptr) ; ptr++)
+ {
+ const char *tmp_buff;
+ byte *pos;
+ bool is_blob;
+ uint flags=field->flags;
+ char tmp[MAX_FIELD_WIDTH];
+ char tmp1[MAX_FIELD_WIDTH];
+ String type(tmp,sizeof(tmp), system_charset_info);
+ char *end;
+ int decimals, field_length;
+
+ if (wild && wild[0] &&
+ wild_case_compare(system_charset_info, field->field_name,wild))
+ continue;
+
+ flags= field->flags;
+ count++;
+ /* Get default row, with all NULL fields set to NULL */
+ restore_record(table, s->default_values);
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint col_access;
+ check_access(thd,SELECT_ACL | EXTRA_ACL, base_name,
+ &tables->grant.privilege, 0, 0, test(tables->schema_table));
+ col_access= get_column_grant(thd, &tables->grant,
+ base_name, file_name,
+ field->field_name) & COL_ACLS;
+ if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS &&
+ !tables->schema_table && !col_access)
+ continue;
+ end= tmp;
+ for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
+ {
+ if (col_access & 1)
+ {
+ *end++=',';
+ end=strmov(end,grant_types.type_names[bitnr]);
+ }
+ }
+ table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
+
+#endif
+ table->field[1]->store(base_name, base_name_length, cs);
+ table->field[2]->store(file_name, file_name_length, cs);
+ table->field[3]->store(field->field_name, strlen(field->field_name),
+ cs);
+ table->field[4]->store((longlong) count, TRUE);
+ field->sql_type(type);
+ table->field[14]->store(type.ptr(), type.length(), cs);
+ tmp_buff= strchr(type.ptr(), '(');
+ table->field[7]->store(type.ptr(),
+ (tmp_buff ? tmp_buff - type.ptr() :
+ type.length()), cs);
+ if (show_table->timestamp_field == field &&
+ field->unireg_check != Field::TIMESTAMP_UN_FIELD)
+ {
+ table->field[5]->store("CURRENT_TIMESTAMP", 17, cs);
+ table->field[5]->set_notnull();
+ }
+ else if (field->unireg_check != Field::NEXT_NUMBER &&
+ !field->is_null() &&
+ !(field->flags & NO_DEFAULT_VALUE_FLAG))
+ {
+ String def(tmp1,sizeof(tmp1), cs);
+ type.set(tmp, sizeof(tmp), field->charset());
+ field->val_str(&type);
+ uint dummy_errors;
+ def.copy(type.ptr(), type.length(), type.charset(), cs, &dummy_errors);
+ table->field[5]->store(def.ptr(), def.length(), def.charset());
+ table->field[5]->set_notnull();
+ }
+ else if (field->unireg_check == Field::NEXT_NUMBER ||
+ lex->orig_sql_command != SQLCOM_SHOW_FIELDS ||
+ field->maybe_null())
+ table->field[5]->set_null(); // Null as default
+ else
+ {
+ table->field[5]->store("",0, cs);
+ table->field[5]->set_notnull();
+ }
+ pos=(byte*) ((flags & NOT_NULL_FLAG) &&
+ field->type() != FIELD_TYPE_TIMESTAMP ?
+ "NO" : "YES");
+ table->field[6]->store((const char*) pos,
+ strlen((const char*) pos), cs);
+ is_blob= (field->type() == FIELD_TYPE_BLOB);
+ if (field->has_charset() || is_blob)
+ {
+ longlong c_octet_len= is_blob ? (longlong) field->max_length() :
+ (longlong) field->max_length()/field->charset()->mbmaxlen;
+ table->field[8]->store(c_octet_len, TRUE);
+ table->field[8]->set_notnull();
+ table->field[9]->store((longlong) field->max_length());
+ table->field[9]->set_notnull();
+ }
+
+ /*
+ Calculate field_length and decimals.
+ They are set to -1 if they should not be set (we should return NULL)
+ */
+
+ decimals= field->decimals();
+ switch (field->type()) {
+ case FIELD_TYPE_NEWDECIMAL:
+ field_length= ((Field_new_decimal*) field)->precision;
+ break;
+ case FIELD_TYPE_DECIMAL:
+ field_length= field->field_length - (decimals ? 2 : 1);
+ break;
+ case FIELD_TYPE_TINY:
+ case FIELD_TYPE_SHORT:
+ case FIELD_TYPE_LONG:
+ case FIELD_TYPE_LONGLONG:
+ case FIELD_TYPE_INT24:
+ field_length= field->max_length() - 1;
+ break;
+ case FIELD_TYPE_BIT:
+ field_length= field->max_length();
+ decimals= -1; // return NULL
+ break;
+ case FIELD_TYPE_FLOAT:
+ case FIELD_TYPE_DOUBLE:
+ field_length= field->field_length;
+ if (decimals == NOT_FIXED_DEC)
+ decimals= -1; // return NULL
+ break;
+ default:
+ field_length= decimals= -1;
+ break;
+ }
+
+ if (field_length >= 0)
+ {
+ table->field[10]->store((longlong) field_length);
+ table->field[10]->set_notnull();
+ }
+ if (decimals >= 0)
+ {
+ table->field[11]->store((longlong) decimals, TRUE);
+ table->field[11]->set_notnull();
+ }
+
+ if (field->has_charset())
+ {
+ pos=(byte*) field->charset()->csname;
+ table->field[12]->store((const char*) pos,
+ strlen((const char*) pos), cs);
+ table->field[12]->set_notnull();
+ pos=(byte*) field->charset()->name;
+ table->field[13]->store((const char*) pos,
+ strlen((const char*) pos), cs);
+ table->field[13]->set_notnull();
+ }
+ pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
+ (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
+ (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
+ table->field[15]->store((const char*) pos,
+ strlen((const char*) pos), cs);
+
+ end= tmp;
+ if (field->unireg_check == Field::NEXT_NUMBER)
+ end=strmov(tmp,"auto_increment");
+ table->field[16]->store(tmp, (uint) (end-tmp), cs);
+
+ table->field[18]->store(field->comment.str, field->comment.length, cs);
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+
+int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
{
- char buff[8192];
- String packet2(buff,sizeof(buff),thd->charset());
- List<Item> field_list;
CHARSET_INFO **cs;
- Protocol *protocol= thd->protocol;
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
+ TABLE *table= tables->table;
+ CHARSET_INFO *scs= system_charset_info;
- DBUG_ENTER("mysqld_show_charsets");
+ for (cs= all_charsets ; cs < all_charsets+255 ; cs++)
+ {
+ CHARSET_INFO *tmp_cs= cs[0];
+ if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) &&
+ (tmp_cs->state & MY_CS_AVAILABLE) &&
+ !(wild && wild[0] &&
+ wild_case_compare(scs, tmp_cs->csname,wild)))
+ {
+ const char *comment;
+ restore_record(table, s->default_values);
+ table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs);
+ table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs);
+ comment= tmp_cs->comment ? tmp_cs->comment : "";
+ table->field[2]->store(comment, strlen(comment), scs);
+ table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE);
+ if (schema_table_store_record(thd, table))
+ return 1;
+ }
+ }
+ return 0;
+}
- field_list.push_back(new Item_empty_string("Charset",30));
- field_list.push_back(new Item_empty_string("Description",60));
- field_list.push_back(new Item_empty_string("Default collation",60));
- field_list.push_back(new Item_return_int("Maxlen",3, FIELD_TYPE_SHORT));
- if (protocol->send_fields(&field_list, 1))
+int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ CHARSET_INFO **cs;
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
+ TABLE *table= tables->table;
+ CHARSET_INFO *scs= system_charset_info;
+ for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
+ {
+ CHARSET_INFO **cl;
+ CHARSET_INFO *tmp_cs= cs[0];
+ if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
+ !(tmp_cs->state & MY_CS_PRIMARY))
+ continue;
+ for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
+ {
+ CHARSET_INFO *tmp_cl= cl[0];
+ if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
+ !my_charset_same(tmp_cs, tmp_cl))
+ continue;
+ if (!(wild && wild[0] &&
+ wild_case_compare(scs, tmp_cl->name,wild)))
+ {
+ const char *tmp_buff;
+ restore_record(table, s->default_values);
+ table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
+ table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
+ table->field[2]->store((longlong) tmp_cl->number, TRUE);
+ tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : "";
+ table->field[3]->store(tmp_buff, strlen(tmp_buff), scs);
+ tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
+ table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
+ table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE);
+ if (schema_table_store_record(thd, table))
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ CHARSET_INFO **cs;
+ TABLE *table= tables->table;
+ CHARSET_INFO *scs= system_charset_info;
+ for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
+ {
+ CHARSET_INFO **cl;
+ CHARSET_INFO *tmp_cs= cs[0];
+ if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
+ !(tmp_cs->state & MY_CS_PRIMARY))
+ continue;
+ for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
+ {
+ CHARSET_INFO *tmp_cl= cl[0];
+ if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
+ !my_charset_same(tmp_cs,tmp_cl))
+ continue;
+ restore_record(table, s->default_values);
+ table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
+ table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
+ if (schema_table_store_record(thd, table))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
+ const char *wild, bool full_access, const char *sp_user)
+{
+ String tmp_string;
+ TIME time;
+ LEX *lex= thd->lex;
+ CHARSET_INFO *cs= system_charset_info;
+ const char *sp_db, *sp_name, *definer;
+ sp_db= get_field(thd->mem_root, proc_table->field[0]);
+ sp_name= get_field(thd->mem_root, proc_table->field[1]);
+ definer= get_field(thd->mem_root, proc_table->field[11]);
+ if (!full_access)
+ full_access= !strcmp(sp_user, definer);
+ if (!full_access && check_some_routine_access(thd, sp_db, sp_name,
+ proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE))
+ return 0;
+
+ if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC &&
+ proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE ||
+ lex->orig_sql_command == SQLCOM_SHOW_STATUS_FUNC &&
+ proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION ||
+ lex->orig_sql_command == SQLCOM_END)
+ {
+ restore_record(table, s->default_values);
+ if (!wild || !wild[0] || !wild_compare(sp_name, wild, 0))
+ {
+ int enum_idx= proc_table->field[5]->val_int();
+ table->field[3]->store(sp_name, strlen(sp_name), cs);
+ get_field(thd->mem_root, proc_table->field[3], &tmp_string);
+ table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[2]->store(sp_db, strlen(sp_db), cs);
+ get_field(thd->mem_root, proc_table->field[2], &tmp_string);
+ table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION)
+ {
+ get_field(thd->mem_root, proc_table->field[9], &tmp_string);
+ table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[5]->set_notnull();
+ }
+ if (full_access)
+ {
+ get_field(thd->mem_root, proc_table->field[10], &tmp_string);
+ table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ }
+ table->field[6]->store("SQL", 3, cs);
+ table->field[10]->store("SQL", 3, cs);
+ get_field(thd->mem_root, proc_table->field[6], &tmp_string);
+ table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[12]->store(sp_data_access_name[enum_idx].str,
+ sp_data_access_name[enum_idx].length , cs);
+ get_field(thd->mem_root, proc_table->field[7], &tmp_string);
+ table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ bzero((char *)&time, sizeof(time));
+ ((Field_timestamp *) proc_table->field[12])->get_time(&time);
+ table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ bzero((char *)&time, sizeof(time));
+ ((Field_timestamp *) proc_table->field[13])->get_time(&time);
+ table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ get_field(thd->mem_root, proc_table->field[14], &tmp_string);
+ table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ get_field(thd->mem_root, proc_table->field[15], &tmp_string);
+ table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[19]->store(definer, strlen(definer), cs);
+ return schema_table_store_record(thd, table);
+ }
+ }
+ return 0;
+}
+
+
+int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ TABLE *proc_table;
+ TABLE_LIST proc_tables;
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
+ int res= 0;
+ TABLE *table= tables->table;
+ bool full_access;
+ char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
+ Open_tables_state open_tables_state_backup;
+ DBUG_ENTER("fill_schema_proc");
+
+ strxmov(definer, thd->priv_user, "@", thd->priv_host, NullS);
+ /* We use this TABLE_LIST instance only for checking of privileges. */
+ bzero((char*) &proc_tables,sizeof(proc_tables));
+ proc_tables.db= (char*) "mysql";
+ proc_tables.db_length= 5;
+ proc_tables.table_name= proc_tables.alias= (char*) "proc";
+ proc_tables.table_name_length= 4;
+ proc_tables.lock_type= TL_READ;
+ full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1);
+ if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
+ {
DBUG_RETURN(1);
+ }
+ proc_table->file->ha_index_init(0);
+ if ((res= proc_table->file->index_first(proc_table->record[0])))
+ {
+ res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
+ goto err;
+ }
+ if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
+ {
+ res= 1;
+ goto err;
+ }
+ while (!proc_table->file->index_next(proc_table->record[0]))
+ {
+ if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
+ {
+ res= 1;
+ goto err;
+ }
+ }
+
+err:
+ proc_table->file->ha_index_end();
+ close_proc_table(thd, &open_tables_state_backup);
+ DBUG_RETURN(res);
+}
- for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
+
+static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("get_schema_stat_record");
+ if (res)
{
- if (cs[0] && (cs[0]->state & MY_CS_PRIMARY) &&
- (cs[0]->state & MY_CS_AVAILABLE) &&
- !(wild && wild[0] &&
- wild_case_compare(system_charset_info,cs[0]->csname,wild)))
+ if (thd->lex->orig_sql_command != SQLCOM_SHOW_KEYS)
{
- if (write_charset(protocol, cs[0]))
- goto err;
+ /*
+ I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
+ rather than in SHOW KEYS
+ */
+ if (!tables->view)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd->net.last_errno, thd->net.last_error);
+ thd->clear_error();
+ res= 0;
}
+ DBUG_RETURN(res);
+ }
+ else if (!tables->view)
+ {
+ TABLE *show_table= tables->table;
+ KEY *key_info=show_table->key_info;
+ show_table->file->info(HA_STATUS_VARIABLE |
+ HA_STATUS_NO_LOCK |
+ HA_STATUS_TIME);
+ for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
+ {
+ KEY_PART_INFO *key_part= key_info->key_part;
+ const char *str;
+ for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
+ {
+ restore_record(table, s->default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(file_name, strlen(file_name), cs);
+ table->field[3]->store((longlong) ((key_info->flags &
+ HA_NOSAME) ? 0 : 1), TRUE);
+ table->field[4]->store(base_name, strlen(base_name), cs);
+ table->field[5]->store(key_info->name, strlen(key_info->name), cs);
+ table->field[6]->store((longlong) (j+1), TRUE);
+ str=(key_part->field ? key_part->field->field_name :
+ "?unknown field?");
+ table->field[7]->store(str, strlen(str), cs);
+ if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
+ {
+ table->field[8]->store(((key_part->key_part_flag &
+ HA_REVERSE_SORT) ?
+ "D" : "A"), 1, cs);
+ table->field[8]->set_notnull();
+ }
+ KEY *key=show_table->key_info+i;
+ if (key->rec_per_key[j])
+ {
+ ha_rows records=(show_table->file->records /
+ key->rec_per_key[j]);
+ table->field[9]->store((longlong) records, TRUE);
+ table->field[9]->set_notnull();
+ }
+ if (!(key_info->flags & HA_FULLTEXT) &&
+ (!key_part->field ||
+ key_part->length !=
+ show_table->field[key_part->fieldnr-1]->key_length()))
+ {
+ table->field[10]->store((longlong) key_part->length /
+ key_part->field->charset()->mbmaxlen);
+ table->field[10]->set_notnull();
+ }
+ uint flags= key_part->field ? key_part->field->flags : 0;
+ const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
+ table->field[12]->store(pos, strlen(pos), cs);
+ pos= show_table->file->index_type(i);
+ table->field[13]->store(pos, strlen(pos), cs);
+ if (!show_table->s->keys_in_use.is_set(i))
+ table->field[14]->store("disabled", 8, cs);
+ else
+ table->field[14]->store("", 0, cs);
+ table->field[14]->set_notnull();
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(1);
+ }
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+static int get_schema_views_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("get_schema_views_record");
+ char definer[HOSTNAME_LENGTH + USERNAME_LENGTH + 2];
+ uint definer_len;
+ if (!res)
+ {
+ if (tables->view)
+ {
+ restore_record(table, s->default_values);
+ table->field[1]->store(tables->view_db.str, tables->view_db.length, cs);
+ table->field[2]->store(tables->view_name.str, tables->view_name.length,
+ cs);
+ table->field[3]->store(tables->query.str, tables->query.length, cs);
+
+ if (tables->with_check != VIEW_CHECK_NONE)
+ {
+ if (tables->with_check == VIEW_CHECK_LOCAL)
+ table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs);
+ else
+ table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs);
+ }
+ else
+ table->field[4]->store(STRING_WITH_LEN("NONE"), cs);
+
+ if (tables->updatable_view)
+ table->field[5]->store(STRING_WITH_LEN("YES"), cs);
+ else
+ table->field[5]->store(STRING_WITH_LEN("NO"), cs);
+ definer_len= (strxmov(definer, tables->definer.user.str, "@",
+ tables->definer.host.str, NullS) - definer);
+ table->field[6]->store(definer, definer_len, cs);
+ if (tables->view_suid)
+ table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs);
+ else
+ table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs);
+ DBUG_RETURN(schema_table_store_record(thd, table));
+ }
+ }
+ else
+ {
+ if (tables->view)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd->net.last_errno, thd->net.last_error);
+ thd->clear_error();
}
- send_eof(thd);
DBUG_RETURN(0);
-err:
- DBUG_RETURN(1);
}
-
-int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
- enum enum_var_type value_type,
- pthread_mutex_t *mutex)
+bool store_constraints(THD *thd, TABLE *table, const char *db,
+ const char *tname, const char *key_name,
+ uint key_len, const char *con_type, uint con_len)
{
- char buff[1024];
- List<Item> field_list;
- Protocol *protocol= thd->protocol;
- LEX_STRING null_lex_str;
- DBUG_ENTER("mysqld_show");
+ CHARSET_INFO *cs= system_charset_info;
+ restore_record(table, s->default_values);
+ table->field[1]->store(db, strlen(db), cs);
+ table->field[2]->store(key_name, key_len, cs);
+ table->field[3]->store(db, strlen(db), cs);
+ table->field[4]->store(tname, strlen(tname), cs);
+ table->field[5]->store(con_type, con_len, cs);
+ return schema_table_store_record(thd, table);
+}
- field_list.push_back(new Item_empty_string("Variable_name",30));
- field_list.push_back(new Item_empty_string("Value",256));
- if (protocol->send_fields(&field_list,1))
- DBUG_RETURN(1); /* purecov: inspected */
- null_lex_str.str= 0; // For sys_var->value_ptr()
- null_lex_str.length= 0;
- pthread_mutex_lock(mutex);
- for (; variables->name; variables++)
+static int get_schema_constraints_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ DBUG_ENTER("get_schema_constraints_record");
+ if (res)
+ {
+ if (!tables->view)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd->net.last_errno, thd->net.last_error);
+ thd->clear_error();
+ DBUG_RETURN(0);
+ }
+ else if (!tables->view)
{
- if (!(wild && wild[0] && wild_case_compare(system_charset_info,
- variables->name,wild)))
+ List<FOREIGN_KEY_INFO> f_key_list;
+ TABLE *show_table= tables->table;
+ KEY *key_info=show_table->key_info;
+ uint primary_key= show_table->s->primary_key;
+ show_table->file->info(HA_STATUS_VARIABLE |
+ HA_STATUS_NO_LOCK |
+ HA_STATUS_TIME);
+ for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
{
- protocol->prepare_for_resend();
- protocol->store(variables->name, system_charset_info);
- SHOW_TYPE show_type=variables->type;
- char *value=variables->value;
- const char *pos, *end;
- long nr;
+ if (i != primary_key && !(key_info->flags & HA_NOSAME))
+ continue;
- if (show_type == SHOW_SYS)
+ if (i == primary_key && !strcmp(key_info->name, primary_key_name))
+ {
+ if (store_constraints(thd, table, base_name, file_name, key_info->name,
+ strlen(key_info->name), "PRIMARY KEY", 11))
+ DBUG_RETURN(1);
+ }
+ else if (key_info->flags & HA_NOSAME)
{
- show_type= ((sys_var*) value)->type();
- value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
- &null_lex_str);
+ if (store_constraints(thd, table, base_name, file_name, key_info->name,
+ strlen(key_info->name), "UNIQUE", 6))
+ DBUG_RETURN(1);
}
+ }
- pos= end= buff;
- switch (show_type) {
- case SHOW_LONG:
- case SHOW_LONG_CONST:
- end= int10_to_str(*(long*) value, buff, 10);
- break;
- case SHOW_LONGLONG:
- end= longlong10_to_str(*(longlong*) value, buff, 10);
- break;
- case SHOW_HA_ROWS:
- end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
- break;
- case SHOW_BOOL:
- end= strmov(buff, *(bool*) value ? "ON" : "OFF");
- break;
- case SHOW_MY_BOOL:
- end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
- break;
- case SHOW_INT_CONST:
- case SHOW_INT:
- end= int10_to_str((long) *(uint32*) value, buff, 10);
- break;
- case SHOW_HAVE:
+ show_table->file->get_foreign_key_list(thd, &f_key_list);
+ FOREIGN_KEY_INFO *f_key_info;
+ List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
+ while ((f_key_info=it++))
+ {
+ if (store_constraints(thd, table, base_name, file_name,
+ f_key_info->forein_id->str,
+ strlen(f_key_info->forein_id->str),
+ "FOREIGN KEY", 11))
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+static bool store_trigger(THD *thd, TABLE *table, const char *db,
+ const char *tname, LEX_STRING *trigger_name,
+ enum trg_event_type event,
+ enum trg_action_time_type timing,
+ LEX_STRING *trigger_stmt,
+ ulong sql_mode)
+{
+ CHARSET_INFO *cs= system_charset_info;
+ byte *sql_mode_str;
+ ulong sql_mode_len;
+
+ restore_record(table, s->default_values);
+ table->field[1]->store(db, strlen(db), cs);
+ table->field[2]->store(trigger_name->str, trigger_name->length, cs);
+ table->field[3]->store(trg_event_type_names[event].str,
+ trg_event_type_names[event].length, cs);
+ table->field[5]->store(db, strlen(db), cs);
+ table->field[6]->store(tname, strlen(tname), cs);
+ table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs);
+ table->field[10]->store("ROW", 3, cs);
+ table->field[11]->store(trg_action_time_type_names[timing].str,
+ trg_action_time_type_names[timing].length, cs);
+ table->field[14]->store("OLD", 3, cs);
+ table->field[15]->store("NEW", 3, cs);
+
+ sql_mode_str=
+ sys_var_thd_sql_mode::symbolic_mode_representation(thd,
+ sql_mode,
+ &sql_mode_len);
+ table->field[17]->store((const char*)sql_mode_str, sql_mode_len, cs);
+ return schema_table_store_record(thd, table);
+}
+
+
+static int get_schema_triggers_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ DBUG_ENTER("get_schema_triggers_record");
+ /*
+ res can be non zero value when processed table is a view or
+ error happened during opening of processed table.
+ */
+ if (res)
+ {
+ if (!tables->view)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd->net.last_errno, thd->net.last_error);
+ thd->clear_error();
+ DBUG_RETURN(0);
+ }
+ if (!tables->view && tables->table->triggers)
+ {
+ Table_triggers_list *triggers= tables->table->triggers;
+ int event, timing;
+ for (event= 0; event < (int)TRG_EVENT_MAX; event++)
+ {
+ for (timing= 0; timing < (int)TRG_ACTION_MAX; timing++)
{
- SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
- pos= show_comp_option_name[(int) tmp];
- end= strend(pos);
- break;
+ LEX_STRING trigger_name;
+ LEX_STRING trigger_stmt;
+ ulong sql_mode;
+ if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
+ (enum trg_action_time_type)timing,
+ &trigger_name, &trigger_stmt,
+ &sql_mode))
+ continue;
+ if (store_trigger(thd, table, base_name, file_name, &trigger_name,
+ (enum trg_event_type) event,
+ (enum trg_action_time_type) timing, &trigger_stmt,
+ sql_mode))
+ DBUG_RETURN(1);
}
- case SHOW_CHAR:
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+void store_key_column_usage(TABLE *table, const char*db, const char *tname,
+ const char *key_name, uint key_len,
+ const char *con_type, uint con_len, longlong idx)
+{
+ CHARSET_INFO *cs= system_charset_info;
+ table->field[1]->store(db, strlen(db), cs);
+ table->field[2]->store(key_name, key_len, cs);
+ table->field[4]->store(db, strlen(db), cs);
+ table->field[5]->store(tname, strlen(tname), cs);
+ table->field[6]->store(con_type, con_len, cs);
+ table->field[7]->store((longlong) idx, TRUE);
+}
+
+
+static int get_schema_key_column_usage_record(THD *thd,
+ struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ DBUG_ENTER("get_schema_key_column_usage_record");
+ if (res)
+ {
+ if (!tables->view)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd->net.last_errno, thd->net.last_error);
+ thd->clear_error();
+ DBUG_RETURN(0);
+ }
+ else if (!tables->view)
+ {
+ List<FOREIGN_KEY_INFO> f_key_list;
+ TABLE *show_table= tables->table;
+ KEY *key_info=show_table->key_info;
+ uint primary_key= show_table->s->primary_key;
+ show_table->file->info(HA_STATUS_VARIABLE |
+ HA_STATUS_NO_LOCK |
+ HA_STATUS_TIME);
+ for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
+ {
+ if (i != primary_key && !(key_info->flags & HA_NOSAME))
+ continue;
+ uint f_idx= 0;
+ KEY_PART_INFO *key_part= key_info->key_part;
+ for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
- if (!(pos= value))
- pos= "";
- end= strend(pos);
- break;
- }
- case SHOW_STARTTIME:
- nr= (long) (thd->query_start() - start_time);
- end= int10_to_str(nr, buff, 10);
- break;
- case SHOW_QUESTION:
- end= int10_to_str((long) thd->query_id, buff, 10);
- break;
-#ifdef HAVE_REPLICATION
- case SHOW_RPL_STATUS:
- end= strmov(buff, rpl_status_type[(int)rpl_status]);
- break;
- case SHOW_SLAVE_RUNNING:
+ if (key_part->field)
+ {
+ f_idx++;
+ restore_record(table, s->default_values);
+ store_key_column_usage(table, base_name, file_name,
+ key_info->name,
+ strlen(key_info->name),
+ key_part->field->field_name,
+ strlen(key_part->field->field_name),
+ (longlong) f_idx);
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(1);
+ }
+ }
+ }
+
+ show_table->file->get_foreign_key_list(thd, &f_key_list);
+ FOREIGN_KEY_INFO *f_key_info;
+ List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
+ while ((f_key_info= it++))
+ {
+ LEX_STRING *f_info;
+ LEX_STRING *r_info;
+ List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
+ it1(f_key_info->referenced_fields);
+ uint f_idx= 0;
+ while ((f_info= it++))
{
- pthread_mutex_lock(&LOCK_active_mi);
- end= strmov(buff, (active_mi->slave_running &&
- active_mi->rli.slave_running) ? "ON" : "OFF");
- pthread_mutex_unlock(&LOCK_active_mi);
- break;
+ r_info= it1++;
+ f_idx++;
+ restore_record(table, s->default_values);
+ store_key_column_usage(table, base_name, file_name,
+ f_key_info->forein_id->str,
+ f_key_info->forein_id->length,
+ f_info->str, f_info->length,
+ (longlong) f_idx);
+ table->field[8]->store((longlong) f_idx, TRUE);
+ table->field[8]->set_notnull();
+ table->field[9]->store(f_key_info->referenced_db->str,
+ f_key_info->referenced_db->length,
+ system_charset_info);
+ table->field[9]->set_notnull();
+ table->field[10]->store(f_key_info->referenced_table->str,
+ f_key_info->referenced_table->length,
+ system_charset_info);
+ table->field[10]->set_notnull();
+ table->field[11]->store(r_info->str, r_info->length,
+ system_charset_info);
+ table->field[11]->set_notnull();
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(1);
}
- case SHOW_SLAVE_RETRIED_TRANS:
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ DBUG_ENTER("fill_open_tables");
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
+ TABLE *table= tables->table;
+ CHARSET_INFO *cs= system_charset_info;
+ OPEN_TABLE_LIST *open_list;
+ if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild))
+ && thd->is_fatal_error)
+ DBUG_RETURN(1);
+
+ for (; open_list ; open_list=open_list->next)
+ {
+ restore_record(table, s->default_values);
+ table->field[0]->store(open_list->db, strlen(open_list->db), cs);
+ table->field[1]->store(open_list->table, strlen(open_list->table), cs);
+ table->field[2]->store((longlong) open_list->in_use, TRUE);
+ table->field[3]->store((longlong) open_list->locked, TRUE);
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ DBUG_ENTER("fill_variables");
+ int res= 0;
+ LEX *lex= thd->lex;
+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ res= show_status_array(thd, wild, init_vars,
+ lex->option_type, 0, "", tables->table);
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ DBUG_RETURN(res);
+}
+
+
+int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ DBUG_ENTER("fill_status");
+ LEX *lex= thd->lex;
+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
+ int res= 0;
+ STATUS_VAR tmp;
+ ha_update_statistics(); /* Export engines statistics */
+ pthread_mutex_lock(&LOCK_status);
+ if (lex->option_type == OPT_GLOBAL)
+ calc_sum_of_all_status(&tmp);
+ res= show_status_array(thd, wild, status_vars, OPT_GLOBAL,
+ (lex->option_type == OPT_GLOBAL ?
+ &tmp: &thd->status_var), "",tables->table);
+ pthread_mutex_unlock(&LOCK_status);
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Find schema_tables elment by name
+
+ SYNOPSIS
+ find_schema_table()
+ thd thread handler
+ table_name table name
+
+ RETURN
+ 0 table not found
+ # pointer to 'shema_tables' element
+*/
+
+ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name)
+{
+ ST_SCHEMA_TABLE *schema_table= schema_tables;
+ for (; schema_table->table_name; schema_table++)
+ {
+ if (!my_strcasecmp(system_charset_info,
+ schema_table->table_name,
+ table_name))
+ return schema_table;
+ }
+ return 0;
+}
+
+
+ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
+{
+ return &schema_tables[schema_table_idx];
+}
+
+
+/*
+ Create information_schema table using schema_table data
+
+ SYNOPSIS
+ create_schema_table()
+ thd thread handler
+ schema_table pointer to 'shema_tables' element
+
+ RETURN
+ # Pointer to created table
+ 0 Can't create table
+*/
+
+TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
+{
+ int field_count= 0;
+ Item *item;
+ TABLE *table;
+ List<Item> field_list;
+ ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
+ ST_FIELD_INFO *fields_info= schema_table->fields_info;
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("create_schema_table");
+
+ for (; fields_info->field_name; fields_info++)
+ {
+ switch (fields_info->field_type) {
+ case MYSQL_TYPE_LONG:
+ if (!(item= new Item_int(fields_info->field_name,
+ fields_info->value,
+ fields_info->field_length)))
{
- /*
- TODO: in 5.1 with multimaster, have one such counter per line in SHOW
- SLAVE STATUS, and have the sum over all lines here.
- */
- pthread_mutex_lock(&LOCK_active_mi);
- pthread_mutex_lock(&active_mi->rli.data_lock);
- end= int10_to_str(active_mi->rli.retried_trans, buff, 10);
- pthread_mutex_unlock(&active_mi->rli.data_lock);
- pthread_mutex_unlock(&LOCK_active_mi);
- break;
+ DBUG_RETURN(0);
}
-#endif /* HAVE_REPLICATION */
- case SHOW_OPENTABLES:
- end= int10_to_str((long) cached_tables(), buff, 10);
- break;
- case SHOW_CHAR_PTR:
+ break;
+ case MYSQL_TYPE_TIMESTAMP:
+ if (!(item=new Item_datetime(fields_info->field_name)))
{
- if (!(pos= *(char**) value))
- pos= "";
- end= strend(pos);
- break;
+ DBUG_RETURN(0);
}
-#ifdef HAVE_OPENSSL
- /* First group - functions relying on CTX */
- case SHOW_SSL_CTX_SESS_ACCEPT:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_good(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_good(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_CB_HITS:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_HITS:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_hits(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_CACHE_FULL:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cache_full(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_MISSES:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_misses(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_TIMEOUTS:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_SESS_NUMBER:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_SESS_CONNECT:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_GET_VERIFY_MODE:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
- if (!ssl_acceptor_fd)
- {
- pos= "NONE";
- end= pos+4;
- break;
- }
- switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
- {
- case SSL_SESS_CACHE_OFF:
- pos= "OFF";
- break;
- case SSL_SESS_CACHE_CLIENT:
- pos= "CLIENT";
- break;
- case SSL_SESS_CACHE_SERVER:
- pos= "SERVER";
- break;
- case SSL_SESS_CACHE_BOTH:
- pos= "BOTH";
- break;
- case SSL_SESS_CACHE_NO_AUTO_CLEAR:
- pos= "NO_AUTO_CLEAR";
- break;
- case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
- pos= "NO_INTERNAL_LOOKUP";
- break;
- default:
- pos= "Unknown";
- break;
- }
- end= strend(pos);
- break;
- /* First group - functions relying on SSL */
- case SHOW_SSL_GET_VERSION:
- pos= (thd->net.vio->ssl_arg ?
- SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
- end= strend(pos);
- break;
- case SHOW_SSL_SESSION_REUSED:
- end= int10_to_str((long) (thd->net.vio->ssl_arg ?
- SSL_session_reused((SSL*) thd->net.vio->
- ssl_arg) :
- 0),
- buff, 10);
- break;
- case SHOW_SSL_GET_DEFAULT_TIMEOUT:
- end= int10_to_str((long) (thd->net.vio->ssl_arg ?
- SSL_get_default_timeout((SSL*) thd->net.vio->
- ssl_arg) :
- 0),
- buff, 10);
- break;
- case SHOW_SSL_GET_VERIFY_MODE:
- end= int10_to_str((long) (thd->net.vio->ssl_arg ?
- SSL_get_verify_mode((SSL*) thd->net.vio->
- ssl_arg):
- 0),
- buff, 10);
- break;
- case SHOW_SSL_GET_VERIFY_DEPTH:
- end= int10_to_str((long) (thd->net.vio->ssl_arg ?
- SSL_get_verify_depth((SSL*) thd->net.vio->
- ssl_arg):
- 0),
- buff, 10);
- break;
- case SHOW_SSL_GET_CIPHER:
- pos= (thd->net.vio->ssl_arg ?
- SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" );
- end= strend(pos);
- break;
- case SHOW_SSL_GET_CIPHER_LIST:
- if (thd->net.vio->ssl_arg)
- {
- char *to= buff;
- for (int i=0 ; i++ ;)
- {
- const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i);
- if (p == NULL)
- break;
- to= strmov(to, p);
- *to++= ':';
- }
- if (to != buff)
- to--; // Remove last ':'
- end= to;
- }
- break;
+ break;
+ default:
+ /* this should be changed when Item_empty_string is fixed(in 4.1) */
+ if (!(item= new Item_empty_string("", 0, cs)))
+ {
+ DBUG_RETURN(0);
+ }
+ item->max_length= fields_info->field_length * cs->mbmaxlen;
+ item->set_name(fields_info->field_name,
+ strlen(fields_info->field_name), cs);
+ break;
+ }
+ field_list.push_back(item);
+ item->maybe_null= fields_info->maybe_null;
+ field_count++;
+ }
+ TMP_TABLE_PARAM *tmp_table_param =
+ (TMP_TABLE_PARAM*) (thd->calloc(sizeof(TMP_TABLE_PARAM)));
+ tmp_table_param->init();
+ tmp_table_param->table_charset= cs;
+ tmp_table_param->field_count= field_count;
+ tmp_table_param->schema_table= 1;
+ SELECT_LEX *select_lex= thd->lex->current_select;
+ if (!(table= create_tmp_table(thd, tmp_table_param,
+ field_list, (ORDER*) 0, 0, 0,
+ (select_lex->options | thd->options |
+ TMP_TABLE_ALL_COLUMNS),
+ HA_POS_ERROR, table_list->alias)))
+ DBUG_RETURN(0);
+ table_list->schema_table_param= tmp_table_param;
+ DBUG_RETURN(table);
+}
-#endif /* HAVE_OPENSSL */
- case SHOW_KEY_CACHE_LONG:
- case SHOW_KEY_CACHE_CONST_LONG:
- value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache;
- end= int10_to_str(*(long*) value, buff, 10);
- break;
- case SHOW_KEY_CACHE_LONGLONG:
- value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache;
- end= longlong10_to_str(*(longlong*) value, buff, 10);
- break;
- case SHOW_UNDEF: // Show never happen
- case SHOW_SYS:
- break; // Return empty string
- default:
- break;
+
+/*
+ For old SHOW compatibility. It is used when
+ old SHOW doesn't have generated column names
+ Make list of fields for SHOW
+
+ SYNOPSIS
+ make_old_format()
+ thd thread handler
+ schema_table pointer to 'schema_tables' element
+
+ RETURN
+ -1 errror
+ 0 success
+*/
+
+int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ ST_FIELD_INFO *field_info= schema_table->fields_info;
+ Name_resolution_context *context= &thd->lex->select_lex.context;
+ for (; field_info->field_name; field_info++)
+ {
+ if (field_info->old_name)
+ {
+ Item_field *field= new Item_field(context,
+ NullS, NullS, field_info->field_name);
+ if (field)
+ {
+ field->set_name(field_info->old_name,
+ strlen(field_info->old_name),
+ system_charset_info);
+ if (add_item_to_list(thd, field))
+ return 1;
}
- if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
- protocol->write())
- goto err; /* purecov: inspected */
}
}
- pthread_mutex_unlock(mutex);
- send_eof(thd);
+ return 0;
+}
+
+
+int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ char tmp[128];
+ LEX *lex= thd->lex;
+ SELECT_LEX *sel= lex->current_select;
+ Name_resolution_context *context= &sel->context;
+
+ if (!sel->item_list.elements)
+ {
+ ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
+ String buffer(tmp,sizeof(tmp), system_charset_info);
+ Item_field *field= new Item_field(context,
+ NullS, NullS, field_info->field_name);
+ if (!field || add_item_to_list(thd, field))
+ return 1;
+ buffer.length(0);
+ buffer.append(field_info->old_name);
+ if (lex->wild && lex->wild->ptr())
+ {
+ buffer.append(" (");
+ buffer.append(lex->wild->ptr());
+ buffer.append(")");
+ }
+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
+ }
+ return 0;
+}
+
+
+int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ char tmp[128];
+ String buffer(tmp,sizeof(tmp), thd->charset());
+ LEX *lex= thd->lex;
+ Name_resolution_context *context= &lex->select_lex.context;
+
+ ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
+ buffer.length(0);
+ buffer.append(field_info->old_name);
+ buffer.append(lex->select_lex.db);
+ if (lex->wild && lex->wild->ptr())
+ {
+ buffer.append(" (");
+ buffer.append(lex->wild->ptr());
+ buffer.append(")");
+ }
+ Item_field *field= new Item_field(context,
+ NullS, NullS, field_info->field_name);
+ if (add_item_to_list(thd, field))
+ return 1;
+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
+ if (thd->lex->verbose)
+ {
+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
+ field_info= &schema_table->fields_info[3];
+ field= new Item_field(context, NullS, NullS, field_info->field_name);
+ if (add_item_to_list(thd, field))
+ return 1;
+ field->set_name(field_info->old_name, strlen(field_info->old_name),
+ system_charset_info);
+ }
+ return 0;
+}
+
+
+int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
+ int *field_num= fields_arr;
+ ST_FIELD_INFO *field_info;
+ Name_resolution_context *context= &thd->lex->select_lex.context;
+
+ for (; *field_num >= 0; field_num++)
+ {
+ field_info= &schema_table->fields_info[*field_num];
+ if (!thd->lex->verbose && (*field_num == 13 ||
+ *field_num == 17 ||
+ *field_num == 18))
+ continue;
+ Item_field *field= new Item_field(context,
+ NullS, NullS, field_info->field_name);
+ if (field)
+ {
+ field->set_name(field_info->old_name,
+ strlen(field_info->old_name),
+ system_charset_info);
+ if (add_item_to_list(thd, field))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ int fields_arr[]= {0, 2, 1, 3, -1};
+ int *field_num= fields_arr;
+ ST_FIELD_INFO *field_info;
+ Name_resolution_context *context= &thd->lex->select_lex.context;
+
+ for (; *field_num >= 0; field_num++)
+ {
+ field_info= &schema_table->fields_info[*field_num];
+ Item_field *field= new Item_field(context,
+ NullS, NullS, field_info->field_name);
+ if (field)
+ {
+ field->set_name(field_info->old_name,
+ strlen(field_info->old_name),
+ system_charset_info);
+ if (add_item_to_list(thd, field))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1};
+ int *field_num= fields_arr;
+ ST_FIELD_INFO *field_info;
+ Name_resolution_context *context= &thd->lex->select_lex.context;
+
+ for (; *field_num >= 0; field_num++)
+ {
+ field_info= &schema_table->fields_info[*field_num];
+ Item_field *field= new Item_field(context,
+ NullS, NullS, field_info->field_name);
+ if (field)
+ {
+ field->set_name(field_info->old_name,
+ strlen(field_info->old_name),
+ system_charset_info);
+ if (add_item_to_list(thd, field))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ Create information_schema table
+
+ SYNOPSIS
+ mysql_schema_table()
+ thd thread handler
+ lex pointer to LEX
+ table_list pointer to table_list
+
+ RETURN
+ 0 success
+ 1 error
+*/
+
+int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
+{
+ TABLE *table;
+ DBUG_ENTER("mysql_schema_table");
+ if (!(table= table_list->schema_table->create_table(thd, table_list)))
+ {
+ DBUG_RETURN(1);
+ }
+ table->s->tmp_table= SYSTEM_TMP_TABLE;
+ table->grant.privilege= SELECT_ACL;
+ /*
+ This test is necessary to make
+ case insensitive file systems +
+ upper case table names(information schema tables) +
+ views
+ working correctly
+ */
+ if (table_list->schema_table_name)
+ table->alias_name_used= my_strcasecmp(table_alias_charset,
+ table_list->schema_table_name,
+ table_list->alias);
+ table_list->table_name= (char*) table->s->table_name;
+ table_list->table_name_length= strlen(table->s->table_name);
+ table_list->table= table;
+ table->next= thd->derived_tables;
+ thd->derived_tables= table;
+ table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
+ lex->safe_to_cache_query= 0;
+
+ if (table_list->schema_table_reformed) // show command
+ {
+ SELECT_LEX *sel= lex->current_select;
+ Item *item;
+ Field_translator *transl, *org_transl;
+
+ if (table_list->field_translation)
+ {
+ Field_translator *end= table_list->field_translation_end;
+ for (transl= table_list->field_translation; transl < end; transl++)
+ {
+ if (!transl->item->fixed &&
+ transl->item->fix_fields(thd, &transl->item))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+ }
+ List_iterator_fast<Item> it(sel->item_list);
+ if (!(transl=
+ (Field_translator*)(thd->stmt_arena->
+ alloc(sel->item_list.elements *
+ sizeof(Field_translator)))))
+ {
+ DBUG_RETURN(1);
+ }
+ for (org_transl= transl; (item= it++); transl++)
+ {
+ transl->item= item;
+ transl->name= item->name;
+ if (!item->fixed && item->fix_fields(thd, &transl->item))
+ {
+ DBUG_RETURN(1);
+ }
+ }
+ table_list->field_translation= org_transl;
+ table_list->field_translation_end= transl;
+ }
+
DBUG_RETURN(0);
+}
- err:
- pthread_mutex_unlock(mutex);
- DBUG_RETURN(1);
+
+/*
+ Generate select from information_schema table
+
+ SYNOPSIS
+ make_schema_select()
+ thd thread handler
+ sel pointer to SELECT_LEX
+ schema_table_idx index of 'schema_tables' element
+
+ RETURN
+ 0 success
+ 1 error
+*/
+
+int make_schema_select(THD *thd, SELECT_LEX *sel,
+ enum enum_schema_tables schema_table_idx)
+{
+ ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
+ LEX_STRING db, table;
+ DBUG_ENTER("mysql_schema_select");
+ /*
+ We have to make non const db_name & table_name
+ because of lower_case_table_names
+ */
+ make_lex_string(thd, &db, information_schema_name.str,
+ information_schema_name.length, 0);
+ make_lex_string(thd, &table, schema_table->table_name,
+ strlen(schema_table->table_name), 0);
+ if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
+ !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
+ 0, 0, TL_READ, (List<String> *) 0,
+ (List<String> *) 0))
+ {
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Fill temporary schema tables before SELECT
+
+ SYNOPSIS
+ get_schema_tables_result()
+ join join which use schema tables
+
+ RETURN
+ FALSE success
+ TRUE error
+*/
+
+bool get_schema_tables_result(JOIN *join)
+{
+ JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
+ THD *thd= join->thd;
+ LEX *lex= thd->lex;
+ bool result= 0;
+ DBUG_ENTER("get_schema_tables_result");
+
+ thd->no_warnings_for_error= 1;
+ for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
+ {
+ if (!tab->table || !tab->table->pos_in_table_list)
+ break;
+
+ TABLE_LIST *table_list= tab->table->pos_in_table_list;
+ if (table_list->schema_table && thd->fill_derived_tables())
+ {
+ if (&lex->unit != lex->current_select->master_unit()) // is subselect
+ {
+ table_list->table->file->extra(HA_EXTRA_RESET_STATE);
+ table_list->table->file->delete_all_rows();
+ free_io_cache(table_list->table);
+ filesort_free_buffers(table_list->table);
+ }
+ else
+ table_list->table->file->records= 0;
+
+ if (table_list->schema_table->fill_table(thd, table_list,
+ tab->select_cond))
+ result= 1;
+ }
+ }
+ thd->no_warnings_for_error= 0;
+ DBUG_RETURN(result);
}
-#ifdef __GNUC__
+
+ST_FIELD_INFO schema_fields_info[]=
+{
+ {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"},
+ {"DEFAULT_CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"DEFAULT_COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO tables_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
+ {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine"},
+ {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"},
+ {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"},
+ {"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"},
+ {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"},
+ {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"},
+ {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"},
+ {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"},
+ {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"},
+ {"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, "Auto_increment"},
+ {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"},
+ {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"},
+ {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"},
+ {"TABLE_COLLATION", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"},
+ {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"},
+ {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options"},
+ {"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO columns_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field"},
+ {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
+ {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"},
+ {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
+ {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
+ {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
+ {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
+ {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
+ {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"},
+ {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type"},
+ {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key"},
+ {"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, "Extra"},
+ {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges"},
+ {"COLUMN_COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO charsets_fields_info[]=
+{
+ {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset"},
+ {"DEFAULT_COLLATE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Default collation"},
+ {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description"},
+ {"MAXLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Maxlen"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO collation_fields_info[]=
+{
+ {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Collation"},
+ {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset"},
+ {"ID", 11, MYSQL_TYPE_LONG, 0, 0, "Id"},
+ {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default"},
+ {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled"},
+ {"SORTLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Sortlen"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO coll_charset_app_fields_info[]=
+{
+ {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO proc_fields_info[]=
+{
+ {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"ROUTINE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"},
+ {"ROUTINE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
+ {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"},
+ {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"SQL_DATA_ACCESS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"SQL_PATH", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type"},
+ {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Created"},
+ {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Modified"},
+ {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment"},
+ {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO stat_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
+ {"NON_UNIQUE", 1, MYSQL_TYPE_LONG, 0, 0, "Non_unique"},
+ {"INDEX_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name"},
+ {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONG, 0, 0, "Seq_in_index"},
+ {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name"},
+ {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation"},
+ {"CARDINALITY", 21, MYSQL_TYPE_LONG, 0, 1, "Cardinality"},
+ {"SUB_PART", 3, MYSQL_TYPE_LONG, 0, 1, "Sub_part"},
+ {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed"},
+ {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
+ {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type"},
+ {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO view_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO user_privileges_fields_info[]=
+{
+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO schema_privileges_fields_info[]=
+{
+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO table_privileges_fields_info[]=
+{
+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO column_privileges_fields_info[]=
+{
+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO table_constraints_fields_info[]=
+{
+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CONSTRAINT_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO key_column_usage_fields_info[]=
+{
+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONG, 0, 0, 0},
+ {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONG, 0, 1, 0},
+ {"REFERENCED_TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"REFERENCED_TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"REFERENCED_COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO table_names_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_"},
+ {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO open_tables_fields_info[]=
+{
+ {"Database", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"},
+ {"Table",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
+ {"In_use", 1, MYSQL_TYPE_LONG, 0, 0, "In_use"},
+ {"Name_locked", 4, MYSQL_TYPE_LONG, 0, 0, "Name_locked"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO triggers_fields_info[]=
+{
+ {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TRIGGER_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TRIGGER_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger"},
+ {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event"},
+ {"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"EVENT_OBJECT_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"EVENT_OBJECT_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
+ {"ACTION_ORDER", 4, MYSQL_TYPE_LONG, 0, 0, 0},
+ {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement"},
+ {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing"},
+ {"ACTION_REFERENCE_OLD_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"ACTION_REFERENCE_NEW_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"},
+ {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO variables_fields_info[]=
+{
+ {"Variable_name", 80, MYSQL_TYPE_STRING, 0, 0, "Variable_name"},
+ {"Value", 255, MYSQL_TYPE_STRING, 0, 0, "Value"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+/*
+ Description of ST_FIELD_INFO in table.h
+*/
+
+ST_SCHEMA_TABLE schema_tables[]=
+{
+ {"CHARACTER_SETS", charsets_fields_info, create_schema_table,
+ fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0},
+ {"COLLATIONS", collation_fields_info, create_schema_table,
+ fill_schema_collation, make_old_format, 0, -1, -1, 0},
+ {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
+ create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0},
+ {"COLUMNS", columns_fields_info, create_schema_table,
+ get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0},
+ {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table,
+ fill_schema_column_privileges, 0, 0, -1, -1, 0},
+ {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
+ get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0},
+ {"OPEN_TABLES", open_tables_fields_info, create_schema_table,
+ fill_open_tables, make_old_format, 0, -1, -1, 1},
+ {"ROUTINES", proc_fields_info, create_schema_table,
+ fill_schema_proc, make_proc_old_format, 0, -1, -1, 0},
+ {"SCHEMATA", schema_fields_info, create_schema_table,
+ fill_schema_shemata, make_schemata_old_format, 0, 1, -1, 0},
+ {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
+ fill_schema_schema_privileges, 0, 0, -1, -1, 0},
+ {"STATISTICS", stat_fields_info, create_schema_table,
+ get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0},
+ {"STATUS", variables_fields_info, create_schema_table, fill_status,
+ make_old_format, 0, -1, -1, 1},
+ {"TABLES", tables_fields_info, create_schema_table,
+ get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0},
+ {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,
+ get_all_tables, 0, get_schema_constraints_record, 3, 4, 0},
+ {"TABLE_NAMES", table_names_fields_info, create_schema_table,
+ get_all_tables, make_table_names_old_format, 0, 1, 2, 1},
+ {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
+ fill_schema_table_privileges, 0, 0, -1, -1, 0},
+ {"TRIGGERS", triggers_fields_info, create_schema_table,
+ get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0},
+ {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
+ make_old_format, 0, -1, -1, 1},
+ {"VIEWS", view_fields_info, create_schema_table,
+ get_all_tables, 0, get_schema_views_record, 1, 2, 0},
+ {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table,
+ fill_schema_user_privileges, 0, 0, -1, -1, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List_iterator_fast<char>;
template class List<char>;
#endif
diff --git a/sql/sql_sort.h b/sql/sql_sort.h
index 9f95ffa4884..1831c4a2f3d 100644
--- a/sql/sql_sort.h
+++ b/sql/sql_sort.h
@@ -78,3 +78,4 @@ int merge_buffers(SORTPARAM *param,IO_CACHE *from_file,
IO_CACHE *to_file, uchar *sort_buffer,
BUFFPEK *lastbuff,BUFFPEK *Fb,
BUFFPEK *Tb,int flag);
+void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length);
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index ab2db4aaf53..51f802e7465 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -684,6 +684,19 @@ void String::qs_append(double *d)
qs_append(ld);
}
+void String::qs_append(int i)
+{
+ char *buff= Ptr + str_length;
+ char *end= int10_to_str(i, buff, -10);
+ str_length+= (int) (end-buff);
+}
+
+void String::qs_append(uint i)
+{
+ char *buff= Ptr + str_length;
+ char *end= int10_to_str(i, buff, 10);
+ str_length+= (int) (end-buff);
+}
/*
Compare strings according to collation, without end space.
@@ -707,8 +720,8 @@ void String::qs_append(double *d)
int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
{
return cs->coll->strnncollsp(cs,
- (unsigned char *) s->ptr(),s->length(),
- (unsigned char *) t->ptr(),t->length());
+ (unsigned char *) s->ptr(),s->length(),
+ (unsigned char *) t->ptr(),t->length(), 0);
}
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 31cdd6efb8a..ddae6368228 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -72,9 +72,9 @@ public:
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr_arg,size_t size)
- {}
+ { TRASH(ptr_arg, size); }
static void operator delete(void *ptr_arg, MEM_ROOT *mem_root)
- {}
+ { /* never called */ }
~String() { free(); }
inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; }
@@ -84,6 +84,7 @@ public:
inline char& operator [] (uint32 i) const { return Ptr[i]; }
inline void length(uint32 len) { str_length=len ; }
inline bool is_empty() { return (str_length == 0); }
+ inline void mark_as_const() { Alloced_length= 0;}
inline const char *ptr() const { return Ptr; }
inline char *c_ptr()
{
@@ -141,6 +142,34 @@ public:
bool set(longlong num, CHARSET_INFO *cs);
bool set(ulonglong num, CHARSET_INFO *cs);
bool set(double num,uint decimals, CHARSET_INFO *cs);
+
+ /*
+ PMG 2004.11.12
+ This is a method that works the same as perl's "chop". It simply
+ drops the last character of a string. This is useful in the case
+ of the federated storage handler where I'm building a unknown
+ number, list of values and fields to be used in a sql insert
+ statement to be run on the remote server, and have a comma after each.
+ When the list is complete, I "chop" off the trailing comma
+
+ ex.
+ String stringobj;
+ stringobj.append("VALUES ('foo', 'fi', 'fo',");
+ stringobj.chop();
+ stringobj.append(")");
+
+ In this case, the value of string was:
+
+ VALUES ('foo', 'fi', 'fo',
+ VALUES ('foo', 'fi', 'fo'
+ VALUES ('foo', 'fi', 'fo')
+
+ */
+ inline void chop()
+ {
+ Ptr[str_length--]= '\0';
+ }
+
inline void free()
{
if (alloced)
@@ -177,10 +206,6 @@ public:
}
}
}
- inline void shrink_to_length()
- {
- Alloced_length= str_length;
- }
bool is_alloced() { return alloced; }
inline String& operator = (const String &s)
{
@@ -236,8 +261,6 @@ public:
}
bool fill(uint32 max_length,char fill);
void strip_sp();
- inline void caseup() { my_caseup(str_charset,Ptr,str_length); }
- inline void casedn() { my_casedn(str_charset,Ptr,str_length); }
friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
friend int stringcmp(const String *a,const String *b);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
@@ -293,6 +316,8 @@ public:
Ptr[str_length]= c;
str_length++;
}
+ void qs_append(int i);
+ void qs_append(uint i);
/* Inline (general) functions used by the protocol functions */
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 01126043764..635b512fe23 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
/* drop and alter of tables */
#include "mysql_priv.h"
@@ -24,6 +23,8 @@
#include <hash.h>
#include <myisam.h>
#include <my_dir.h>
+#include "sp_head.h"
+#include "sql_trigger.h"
#ifdef __WIN__
#include <io.h>
@@ -39,6 +40,9 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
+static bool prepare_blob_field(THD *thd, create_field *sql_field);
+static bool check_engine(THD *thd, const char *table_name,
+ enum db_type *new_engine);
/*
@@ -86,15 +90,15 @@ static uint build_table_path(char *buff, size_t bufflen, const char *db,
Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set.
RETURN
- 0 ok. In this case ok packet is sent to user
- -1 Error (Error message given but not sent to user)
+ FALSE OK. In this case ok packet is sent to user
+ TRUE Error
*/
-int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
- my_bool drop_temporary)
+bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
+ my_bool drop_temporary)
{
- int error= 0;
+ bool error= FALSE, need_start_waiters= FALSE;
DBUG_ENTER("mysql_rm_table");
/* mark for close and remove all cached entries */
@@ -103,24 +107,19 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
- if (!drop_temporary && global_read_lock)
+ if (!drop_temporary)
{
- if (thd->global_read_lock)
+ if ((error= wait_if_global_read_lock(thd, 0, 1)))
{
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
- tables->real_name);
- error= 1;
+ my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
goto err;
}
- while (global_read_lock && ! thd->killed)
- {
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- }
-
+ else
+ need_start_waiters= TRUE;
}
- error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, 0);
+ error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
- err:
+err:
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&thd->mysys_var->mutex);
@@ -128,10 +127,13 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
thd->mysys_var->current_cond= 0;
pthread_mutex_unlock(&thd->mysys_var->mutex);
+ if (need_start_waiters)
+ start_waiting_global_read_lock(thd);
+
if (error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
send_ok(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -139,11 +141,12 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
delete (drop) tables.
SYNOPSIS
- mysql_rm_table_part2_with_lock()
- thd Thread handle
- tables List of tables to delete
- if_exists If 1, don't give error if one table doesn't exists
- dont_log_query Don't write query to log files
+ mysql_rm_table_part2_with_lock()
+ thd Thread handle
+ tables List of tables to delete
+ if_exists If 1, don't give error if one table doesn't exists
+ dont_log_query Don't write query to log files. This will also not
+ generate warnings if the handler files doesn't exists
NOTES
Works like documented in mysql_rm_table(), but don't check
@@ -163,8 +166,8 @@ int mysql_rm_table_part2_with_lock(THD *thd,
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
- error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary,
- dont_log_query);
+ error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 1,
+ dont_log_query);
pthread_mutex_unlock(&LOCK_open);
@@ -186,7 +189,9 @@ int mysql_rm_table_part2_with_lock(THD *thd,
if_exists If set, don't give an error if table doesn't exists.
In this case we give an warning of level 'NOTE'
drop_temporary Only drop temporary tables
- dont_log_query Don't log the query
+ drop_view Allow to delete VIEW .frm
+ dont_log_query Don't write query to log files. This will also not
+ generate warnings if the handler files doesn't exists
TODO:
When logging to the binary log, we should log
@@ -205,7 +210,8 @@ int mysql_rm_table_part2_with_lock(THD *thd,
*/
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
- bool drop_temporary, bool dont_log_query)
+ bool drop_temporary, bool drop_view,
+ bool dont_log_query)
{
TABLE_LIST *table;
char path[FN_REFLEN], *alias;
@@ -217,11 +223,14 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if (lock_table_names(thd, tables))
DBUG_RETURN(1);
- for (table=tables ; table ; table=table->next)
+ /* Don't give warnings for not found errors, as we already generate notes */
+ thd->no_warnings_for_error= 1;
+
+ for (table= tables; table; table= table->next_local)
{
char *db=table->db;
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
- if (!close_temporary_table(thd, db, table->real_name))
+ if (!close_temporary_table(thd, db, table->table_name))
{
tmp_table_deleted=1;
continue; // removed temporary table
@@ -230,55 +239,66 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
error=0;
if (!drop_temporary)
{
- abort_locked_tables(thd,db,table->real_name);
- remove_table_from_cache(thd,db,table->real_name,
- RTFC_WAIT_OTHER_THREAD_FLAG |
- RTFC_CHECK_KILLED_FLAG);
- drop_locked_tables(thd,db,table->real_name);
+ abort_locked_tables(thd, db, table->table_name);
+ remove_table_from_cache(thd, db, table->table_name,
+ RTFC_WAIT_OTHER_THREAD_FLAG |
+ RTFC_CHECK_KILLED_FLAG);
+ drop_locked_tables(thd, db, table->table_name);
if (thd->killed)
+ {
+ thd->no_warnings_for_error= 0;
DBUG_RETURN(-1);
- alias= (lower_case_table_names == 2) ? table->alias : table->real_name;
+ }
+ alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
/* remove form file and isam files */
build_table_path(path, sizeof(path), db, alias, reg_ext);
}
if (drop_temporary ||
- (access(path,F_OK) &&
- ha_create_table_from_engine(thd, db, alias)))
+ (access(path,F_OK) &&
+ ha_create_table_from_engine(thd,db,alias)) ||
+ (!drop_view && mysql_frm_type(path) != FRMTYPE_TABLE))
{
// Table was not found on disk and table can't be created from engine
if (if_exists)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
- table->real_name);
+ table->table_name);
else
error= 1;
}
else
{
char *end;
- db_type table_type= get_table_type(path);
+ db_type table_type= get_table_type(thd, path);
*(end=fn_ext(path))=0; // Remove extension for delete
- error=ha_delete_table(table_type, path);
- if (error == ENOENT && if_exists)
- error = 0;
+ error= ha_delete_table(thd, table_type, path, table->table_name,
+ !dont_log_query);
+ if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
+ error= 0;
if (error == HA_ERR_ROW_IS_REFERENCED)
{
/* the table is referenced by a foreign key constraint */
foreign_key_error=1;
}
- if (!error || error == ENOENT)
+ if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
{
+ int new_error;
/* Delete the table definition file */
strmov(end,reg_ext);
- if (!(error=my_delete(path,MYF(MY_WME))))
+ if (!(new_error=my_delete(path,MYF(MY_WME))))
+ {
some_tables_deleted=1;
+ new_error= Table_triggers_list::drop_all_triggers(thd, db,
+ table->table_name);
+ }
+ error|= new_error;
}
}
if (error)
{
if (wrong_tables.length())
wrong_tables.append(',');
- wrong_tables.append(String(table->real_name,system_charset_info));
+ wrong_tables.append(String(table->table_name,system_charset_info));
}
}
thd->tmp_table_used= tmp_table_deleted;
@@ -287,31 +307,26 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
{
if (!foreign_key_error)
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
- wrong_tables.c_ptr());
+ wrong_tables.c_ptr());
else
- my_error(ER_ROW_IS_REFERENCED, MYF(0));
+ my_message(ER_ROW_IS_REFERENCED, ER(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)
+ if (!dont_log_query && mysql_bin_log.is_open())
{
- mysql_update_log.write(thd, thd->query,thd->query_length);
- if (mysql_bin_log.is_open())
- {
- if (!error)
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length,
- tmp_table_deleted && !some_tables_deleted,
- FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ if (!error)
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+ mysql_bin_log.write(&qinfo);
}
}
- unlock_table_names(thd, tables);
+ unlock_table_names(thd, tables, (TABLE_LIST*) 0);
+ thd->no_warnings_for_error= 0;
DBUG_RETURN(error);
}
@@ -325,7 +340,7 @@ int quick_rm_table(enum db_type base,const char *db,
if (my_delete(path,MYF(0)))
error=1; /* purecov: inspected */
*fn_ext(path)= 0; // Remove reg_ext
- return ha_delete_table(base,path) || error;
+ return ha_delete_table(current_thd, base, path, table_name, 0) || error;
}
/*
@@ -448,6 +463,171 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
/*
+ Prepare a create_table instance for packing
+
+ SYNOPSIS
+ prepare_create_field()
+ sql_field field to prepare for packing
+ blob_columns count for BLOBs
+ timestamps count for timestamps
+ table_flags table flags
+
+ DESCRIPTION
+ This function prepares a create_field instance.
+ Fields such as pack_flag are valid after this call.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error
+*/
+
+int prepare_create_field(create_field *sql_field,
+ uint *blob_columns,
+ int *timestamps, int *timestamps_with_niladic,
+ uint table_flags)
+{
+ DBUG_ENTER("prepare_field");
+
+ /*
+ This code came from mysql_prepare_table.
+ Indent preserved to make patching easier
+ */
+ DBUG_ASSERT(sql_field->charset);
+
+ switch (sql_field->sql_type) {
+ case FIELD_TYPE_BLOB:
+ case FIELD_TYPE_MEDIUM_BLOB:
+ case FIELD_TYPE_TINY_BLOB:
+ case FIELD_TYPE_LONG_BLOB:
+ sql_field->pack_flag=FIELDFLAG_BLOB |
+ pack_length_to_packflag(sql_field->pack_length -
+ portable_sizeof_char_ptr);
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->length=8; // Unireg field length
+ sql_field->unireg_check=Field::BLOB_FIELD;
+ (*blob_columns)++;
+ break;
+ case FIELD_TYPE_GEOMETRY:
+#ifdef HAVE_SPATIAL
+ if (!(table_flags & HA_CAN_GEOMETRY))
+ {
+ my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
+ MYF(0), "GEOMETRY");
+ DBUG_RETURN(1);
+ }
+ sql_field->pack_flag=FIELDFLAG_GEOM |
+ pack_length_to_packflag(sql_field->pack_length -
+ portable_sizeof_char_ptr);
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->length=8; // Unireg field length
+ sql_field->unireg_check=Field::BLOB_FIELD;
+ (*blob_columns)++;
+ break;
+#else
+ my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
+ DBUG_RETURN(1);
+#endif /*HAVE_SPATIAL*/
+ case MYSQL_TYPE_VARCHAR:
+#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
+ if (table_flags & HA_NO_VARCHAR)
+ {
+ /* convert VARCHAR to CHAR because handler is not yet up to date */
+ sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
+ sql_field->pack_length= calc_pack_length(sql_field->sql_type,
+ (uint) sql_field->length);
+ if ((sql_field->length / sql_field->charset->mbmaxlen) >
+ MAX_FIELD_CHARLENGTH)
+ {
+ my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
+ MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
+ DBUG_RETURN(1);
+ }
+ }
+#endif
+ /* fall through */
+ case FIELD_TYPE_STRING:
+ sql_field->pack_flag=0;
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ break;
+ case FIELD_TYPE_ENUM:
+ sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
+ FIELDFLAG_INTERVAL;
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->unireg_check=Field::INTERVAL_FIELD;
+ check_duplicates_in_interval("ENUM",sql_field->field_name,
+ sql_field->interval,
+ sql_field->charset);
+ break;
+ case FIELD_TYPE_SET:
+ sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
+ FIELDFLAG_BITFIELD;
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->unireg_check=Field::BIT_FIELD;
+ check_duplicates_in_interval("SET",sql_field->field_name,
+ sql_field->interval,
+ sql_field->charset);
+ break;
+ case FIELD_TYPE_DATE: // Rest of string types
+ case FIELD_TYPE_NEWDATE:
+ case FIELD_TYPE_TIME:
+ case FIELD_TYPE_DATETIME:
+ case FIELD_TYPE_NULL:
+ sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
+ break;
+ case FIELD_TYPE_BIT:
+ /*
+ We have sql_field->pack_flag already set here, see mysql_prepare_table().
+ */
+ break;
+ case FIELD_TYPE_NEWDECIMAL:
+ sql_field->pack_flag=(FIELDFLAG_NUMBER |
+ (sql_field->flags & UNSIGNED_FLAG ? 0 :
+ FIELDFLAG_DECIMAL) |
+ (sql_field->flags & ZEROFILL_FLAG ?
+ FIELDFLAG_ZEROFILL : 0) |
+ (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
+ break;
+ case FIELD_TYPE_TIMESTAMP:
+ /* We should replace old TIMESTAMP fields with their newer analogs */
+ if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
+ {
+ if (!*timestamps)
+ {
+ sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
+ (*timestamps_with_niladic)++;
+ }
+ else
+ sql_field->unireg_check= Field::NONE;
+ }
+ else if (sql_field->unireg_check != Field::NONE)
+ (*timestamps_with_niladic)++;
+
+ (*timestamps)++;
+ /* fall-through */
+ default:
+ sql_field->pack_flag=(FIELDFLAG_NUMBER |
+ (sql_field->flags & UNSIGNED_FLAG ? 0 :
+ FIELDFLAG_DECIMAL) |
+ (sql_field->flags & ZEROFILL_FLAG ?
+ FIELDFLAG_ZEROFILL : 0) |
+ f_settype((uint) sql_field->sql_type) |
+ (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
+ break;
+ }
+ if (!(sql_field->flags & NOT_NULL_FLAG))
+ sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
+ if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
+ sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
+ DBUG_RETURN(0);
+}
+
+/*
Preparation for table creation
SYNOPSIS
@@ -460,34 +640,43 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
DESCRIPTION
Prepares the table and key structures for table creation.
+ NOTES
+ sets create_info->varchar if the table has a varchar
+
RETURN VALUES
0 ok
-1 error
*/
-int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
- List<create_field> &fields,
- List<Key> &keys, bool tmp_table, uint &db_options,
- handler *file, KEY *&key_info_buffer,
- uint *key_count, int select_field_count)
+static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
+ List<create_field> *fields,
+ List<Key> *keys, bool tmp_table,
+ uint *db_options,
+ handler *file, KEY **key_info_buffer,
+ uint *key_count, int select_field_count)
{
const char *key_name;
create_field *sql_field,*dup_field;
- uint field,null_fields,blob_columns;
+ uint field,null_fields,blob_columns,max_key_length;
ulong record_offset= 0;
KEY *key_info;
KEY_PART_INFO *key_part_info;
int timestamps= 0, timestamps_with_niladic= 0;
int field_no,dup_no;
int select_field_pos,auto_increment=0;
+ List_iterator<create_field> it(*fields),it2(*fields);
+ uint total_uneven_bit_length= 0;
DBUG_ENTER("mysql_prepare_table");
- List_iterator<create_field> it(fields),it2(fields);
- select_field_pos=fields.elements - select_field_count;
+ select_field_pos= fields->elements - select_field_count;
null_fields=blob_columns=0;
+ create_info->varchar= 0;
+ max_key_length= file->max_key_length();
for (field_no=0; (sql_field=it++) ; field_no++)
{
+ CHARSET_INFO *save_cs;
+
if (!sql_field->charset)
sql_field->charset= create_info->default_table_charset;
/*
@@ -499,13 +688,13 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
sql_field->charset= create_info->table_charset;
- CHARSET_INFO *savecs= sql_field->charset;
+ save_cs= sql_field->charset;
if ((sql_field->flags & BINCMP_FLAG) &&
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
MY_CS_BINSORT,MYF(0))))
{
char tmp[64];
- strmake(strmake(tmp, savecs->csname, sizeof(tmp)-4), "_bin", 4);
+ strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), "_bin", 4);
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
DBUG_RETURN(-1);
}
@@ -529,21 +718,20 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
String conv, *tmp;
for (uint i= 0; (tmp= it++); i++)
{
+ uint lengthsp;
if (String::needs_conversion(tmp->length(), tmp->charset(),
cs, &dummy))
{
uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
- char *buf= (char*) sql_alloc(conv.length()+1);
- memcpy(buf, conv.ptr(), conv.length());
- buf[conv.length()]= '\0';
- interval->type_names[i]= buf;
+ interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
+ conv.length());
interval->type_lengths[i]= conv.length();
}
// Strip trailing spaces.
- uint lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
- interval->type_lengths[i]);
+ lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
+ interval->type_lengths[i]);
interval->type_lengths[i]= lengthsp;
((uchar *)interval->type_names[i])[lengthsp]= '\0';
}
@@ -567,6 +755,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (sql_field->sql_type == FIELD_TYPE_SET)
{
+ uint32 field_length;
if (sql_field->def)
{
char *not_used;
@@ -582,11 +771,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(-1);
}
}
- calculate_interval_lengths(cs, interval, &dummy, &sql_field->length);
- sql_field->length+= (interval->count - 1);
+ calculate_interval_lengths(cs, interval, &dummy, &field_length);
+ sql_field->length= field_length + (interval->count - 1);
}
else /* FIELD_TYPE_ENUM */
{
+ uint32 field_length;
if (sql_field->def)
{
String str, *def= sql_field->def->val_str(&str);
@@ -597,20 +787,25 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(-1);
}
}
- calculate_interval_lengths(cs, interval, &sql_field->length, &dummy);
+ calculate_interval_lengths(cs, interval, &field_length, &dummy);
+ sql_field->length= field_length;
}
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
}
+ if (sql_field->sql_type == FIELD_TYPE_BIT)
+ {
+ sql_field->pack_flag= FIELDFLAG_NUMBER;
+ if (file->table_flags() & HA_CAN_BIT_FIELD)
+ total_uneven_bit_length+= sql_field->length & 7;
+ else
+ sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
+ }
+
sql_field->create_length_to_internal_length();
+ if (prepare_blob_field(thd, sql_field))
+ DBUG_RETURN(-1);
- /* Don't pack keys in old tables if the user has requested this */
- if ((sql_field->flags & BLOB_FLAG) ||
- sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
- create_info->row_type != ROW_TYPE_FIXED)
- {
- db_options|=HA_OPTION_PACK_RECORD;
- }
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
@@ -633,7 +828,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
*/
if (field_no < select_field_pos || dup_no >= select_field_pos)
{
- my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name);
+ my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
DBUG_RETURN(-1);
}
else
@@ -645,6 +840,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
create_info->default_table_charset);
sql_field->length= dup_field->length;
sql_field->pack_length= dup_field->pack_length;
+ sql_field->key_length= dup_field->key_length;
sql_field->create_length_to_internal_length();
sql_field->decimals= dup_field->decimals;
sql_field->flags= dup_field->flags;
@@ -655,115 +851,29 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
}
+ /* Don't pack rows in old tables if the user has requested this */
+ if ((sql_field->flags & BLOB_FLAG) ||
+ sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
+ create_info->row_type != ROW_TYPE_FIXED)
+ (*db_options)|= HA_OPTION_PACK_RECORD;
it2.rewind();
}
/* record_offset will be increased with 'length-of-null-bits' later */
record_offset= 0;
+ null_fields+= total_uneven_bit_length;
it.rewind();
while ((sql_field=it++))
{
- DBUG_ASSERT(sql_field->charset);
-
- switch (sql_field->sql_type) {
- case FIELD_TYPE_BLOB:
- case FIELD_TYPE_MEDIUM_BLOB:
- case FIELD_TYPE_TINY_BLOB:
- case FIELD_TYPE_LONG_BLOB:
- sql_field->pack_flag=FIELDFLAG_BLOB |
- pack_length_to_packflag(sql_field->pack_length -
- portable_sizeof_char_ptr);
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->length=8; // Unireg field length
- sql_field->unireg_check=Field::BLOB_FIELD;
- blob_columns++;
- break;
- case FIELD_TYPE_GEOMETRY:
-#ifdef HAVE_SPATIAL
- if (!(file->table_flags() & HA_CAN_GEOMETRY))
- {
- my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
- MYF(0), "GEOMETRY");
- DBUG_RETURN(-1);
- }
- sql_field->pack_flag=FIELDFLAG_GEOM |
- pack_length_to_packflag(sql_field->pack_length -
- portable_sizeof_char_ptr);
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->length=8; // Unireg field length
- sql_field->unireg_check=Field::BLOB_FIELD;
- blob_columns++;
- break;
-#else
- my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- DBUG_RETURN(-1);
-#endif /*HAVE_SPATIAL*/
- case FIELD_TYPE_VAR_STRING:
- case FIELD_TYPE_STRING:
- sql_field->pack_flag=0;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- break;
- case FIELD_TYPE_ENUM:
- sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
- FIELDFLAG_INTERVAL;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->unireg_check=Field::INTERVAL_FIELD;
- check_duplicates_in_interval("ENUM",sql_field->field_name,
- sql_field->interval,
- sql_field->charset);
- break;
- case FIELD_TYPE_SET:
- sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
- FIELDFLAG_BITFIELD;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->unireg_check=Field::BIT_FIELD;
- check_duplicates_in_interval("SET",sql_field->field_name,
- sql_field->interval,
- sql_field->charset);
- break;
- case FIELD_TYPE_DATE: // Rest of string types
- case FIELD_TYPE_NEWDATE:
- case FIELD_TYPE_TIME:
- case FIELD_TYPE_DATETIME:
- case FIELD_TYPE_NULL:
- sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
- break;
- case FIELD_TYPE_TIMESTAMP:
- /* We should replace old TIMESTAMP fields with their newer analogs */
- if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
- {
- if (!timestamps)
- {
- sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
- timestamps_with_niladic++;
- }
- else
- sql_field->unireg_check= Field::NONE;
- }
- else if (sql_field->unireg_check != Field::NONE)
- timestamps_with_niladic++;
+ DBUG_ASSERT(sql_field->charset != 0);
- timestamps++;
- /* fall-through */
- default:
- sql_field->pack_flag=(FIELDFLAG_NUMBER |
- (sql_field->flags & UNSIGNED_FLAG ? 0 :
- FIELDFLAG_DECIMAL) |
- (sql_field->flags & ZEROFILL_FLAG ?
- FIELDFLAG_ZEROFILL : 0) |
- f_settype((uint) sql_field->sql_type) |
- (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
- break;
- }
- if (!(sql_field->flags & NOT_NULL_FLAG))
- sql_field->pack_flag|=FIELDFLAG_MAYBE_NULL;
+ if (prepare_create_field(sql_field, &blob_columns,
+ &timestamps, &timestamps_with_niladic,
+ file->table_flags()))
+ DBUG_RETURN(-1);
+ if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
+ create_info->varchar= 1;
sql_field->offset= record_offset;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++;
@@ -771,30 +881,33 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
if (timestamps_with_niladic > 1)
{
- my_error(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,MYF(0));
+ my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
+ ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment > 1)
{
- my_error(ER_WRONG_AUTO_KEY,MYF(0));
+ my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment &&
(file->table_flags() & HA_NO_AUTO_INCREMENT))
{
- my_error(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,MYF(0));
+ my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
+ ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
DBUG_RETURN(-1);
}
if (blob_columns && (file->table_flags() & HA_NO_BLOBS))
{
- my_error(ER_TABLE_CANT_HANDLE_BLOB,MYF(0));
+ my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
+ MYF(0));
DBUG_RETURN(-1);
}
/* Create keys */
- List_iterator<Key> key_iterator(keys), key_iterator2(keys);
+ List_iterator<Key> key_iterator(*keys), key_iterator2(*keys);
uint key_parts=0, fk_key_count=0;
bool primary_key=0,unique_key=0;
Key *key, *key2;
@@ -814,9 +927,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (fk_key->ref_columns.elements &&
fk_key->ref_columns.elements != fk_key->columns.elements)
{
- my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name :
- "foreign key without name",
- ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
+ my_error(ER_WRONG_FK_DEF, MYF(0),
+ (fk_key->name ? fk_key->name : "foreign key without name"),
+ ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
DBUG_RETURN(-1);
}
continue;
@@ -881,9 +994,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(-1);
}
- key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)* *key_count);
+ (*key_info_buffer) = key_info= (KEY*) sql_calloc(sizeof(KEY)* *key_count);
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
- if (!key_info_buffer || ! key_part_info)
+ if (!*key_info_buffer || ! key_part_info)
DBUG_RETURN(-1); // Out of memory
key_iterator.rewind();
@@ -915,8 +1028,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags= HA_SPATIAL;
break;
#else
- my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(-1);
#endif
case Key::FOREIGN_KEY:
@@ -938,7 +1051,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (!(file->table_flags() & HA_CAN_FULLTEXT))
{
- my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
+ my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
+ MYF(0));
DBUG_RETURN(-1);
}
}
@@ -955,8 +1069,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (key_info->key_parts != 1)
{
- my_printf_error(ER_WRONG_ARGUMENTS,
- ER(ER_WRONG_ARGUMENTS),MYF(0),"SPATIAL INDEX");
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
DBUG_RETURN(-1);
}
}
@@ -965,17 +1078,15 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
#ifdef HAVE_RTREE_KEYS
if ((key_info->key_parts & 1) == 1)
{
- my_printf_error(ER_WRONG_ARGUMENTS,
- ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
DBUG_RETURN(-1);
}
/* TODO: To be deleted */
- my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
- MYF(0), "RTREE INDEX");
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
DBUG_RETURN(-1);
#else
- my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
- sym_group_rtree.name, sym_group_rtree.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_rtree.name, sym_group_rtree.needed_define);
DBUG_RETURN(-1);
#endif
}
@@ -984,6 +1095,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{
+ uint length;
key_part_spec *dup_column;
it.rewind();
@@ -995,9 +1107,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
field++;
if (!sql_field)
{
- my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS,
- ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0),
- column->field_name);
+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
while ((dup_column= cols2++) != column)
@@ -1014,15 +1124,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
cols2.rewind();
if (key->type == Key::FULLTEXT)
{
- if ((sql_field->sql_type != FIELD_TYPE_STRING &&
- sql_field->sql_type != FIELD_TYPE_VAR_STRING &&
+ if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
+ sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
!f_is_blob(sql_field->pack_flag)) ||
sql_field->charset == &my_charset_bin ||
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),
- column->field_name);
+ my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
ft_key_charset=sql_field->charset;
@@ -1043,28 +1152,25 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
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);
+ my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
if (!column->length)
{
- my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
- ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0),
- column->field_name);
+ my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
}
#ifdef HAVE_SPATIAL
- if (key->type == Key::SPATIAL)
+ if (key->type == Key::SPATIAL)
{
- if (!column->length )
+ if (!column->length)
{
/*
- BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
- Lately we'll extend this code to support more dimensions
+ 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
+ Lately we'll extend this code to support more dimensions
*/
- column->length=4*sizeof(double);
+ column->length= 4*sizeof(double);
}
}
#endif
@@ -1081,13 +1187,13 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags|= HA_NULL_PART_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);
+ my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
if (key->type == Key::SPATIAL)
{
- my_error(ER_SPATIAL_CANT_HAVE_NULL, MYF(0));
+ my_message(ER_SPATIAL_CANT_HAVE_NULL,
+ ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
DBUG_RETURN(-1);
}
}
@@ -1101,15 +1207,16 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_part_info->fieldnr= field;
key_part_info->offset= (uint16) sql_field->offset;
key_part_info->key_type=sql_field->pack_flag;
- uint length=sql_field->pack_length;
+ length= sql_field->key_length;
+
if (column->length)
{
if (f_is_blob(sql_field->pack_flag))
{
- if ((length=column->length) > file->max_key_length() ||
+ if ((length=column->length) > max_key_length ||
length > file->max_key_part_length())
{
- length=min(file->max_key_length(), file->max_key_part_length());
+ length=min(max_key_length, file->max_key_part_length());
if (key->type == Key::MULTIPLE)
{
/* not a critical problem */
@@ -1133,7 +1240,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
(key_info->flags & HA_NOSAME))) &&
column->length != length)))
{
- my_error(ER_WRONG_SUB_KEY,MYF(0));
+ my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
DBUG_RETURN(-1);
}
else if (!(file->table_flags() & HA_NO_PREFIX_CHAR_KEYS))
@@ -1141,8 +1248,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
else if (length == 0)
{
- my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0),
- column->field_name);
+ my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
if (length > file->max_key_part_length())
@@ -1165,14 +1271,15 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
key_part_info->length=(uint16) length;
/* Use packed keys for long strings on the first column */
- if (!(db_options & HA_OPTION_NO_PACK_KEYS) &&
+ if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
(length >= KEY_DEFAULT_PACK_LENGTH &&
- (sql_field->sql_type == FIELD_TYPE_STRING ||
- sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
+ (sql_field->sql_type == MYSQL_TYPE_STRING ||
+ sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
sql_field->pack_flag & FIELDFLAG_BLOB)))
{
- if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB))
- key_info->flags|= HA_BINARY_PACK_KEY;
+ if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB) ||
+ sql_field->sql_type == MYSQL_TYPE_VARCHAR)
+ key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
else
key_info->flags|= HA_PACK_KEY;
}
@@ -1186,7 +1293,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (primary_key)
{
- my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
+ my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
+ MYF(0));
DBUG_RETURN(-1);
}
key_name=primary_key_name;
@@ -1194,10 +1302,10 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
else if (!(key_name = key->name))
key_name=make_unique_key_name(sql_field->field_name,
- key_info_buffer,key_info);
- if (check_if_keyname_exists(key_name,key_info_buffer,key_info))
+ *key_info_buffer, key_info);
+ if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
{
- my_error(ER_DUP_KEYNAME,MYF(0),key_name);
+ my_error(ER_DUP_KEYNAME, MYF(0), key_name);
DBUG_RETURN(-1);
}
key_info->name=(char*) key_name;
@@ -1211,7 +1319,6 @@ 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= 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);
@@ -1222,16 +1329,16 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (!unique_key && !primary_key &&
(file->table_flags() & HA_REQUIRE_PRIMARY_KEY))
{
- my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0));
+ my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment > 0)
{
- my_error(ER_WRONG_AUTO_KEY,MYF(0));
+ my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
DBUG_RETURN(-1);
}
/* Sort keys in optimized order */
- qsort((gptr) key_info_buffer, *key_count, sizeof(KEY),
+ qsort((gptr) *key_info_buffer, *key_count, sizeof(KEY),
(qsort_cmp) sort_keys);
create_info->null_bits= null_fields;
@@ -1240,6 +1347,109 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
/*
+ Extend long VARCHAR fields to blob & prepare field if it's a blob
+
+ SYNOPSIS
+ prepare_blob_field()
+ sql_field Field to check
+
+ RETURN
+ 0 ok
+ 1 Error (sql_field can't be converted to blob)
+ In this case the error is given
+*/
+
+static bool prepare_blob_field(THD *thd, create_field *sql_field)
+{
+ DBUG_ENTER("prepare_blob_field");
+
+ if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
+ !(sql_field->flags & BLOB_FLAG))
+ {
+ /* Convert long VARCHAR columns to TEXT or BLOB */
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+
+ if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES)))
+ {
+ my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
+ MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
+ DBUG_RETURN(1);
+ }
+ sql_field->sql_type= FIELD_TYPE_BLOB;
+ sql_field->flags|= BLOB_FLAG;
+ sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
+ (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
+ (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
+ warn_buff);
+ }
+
+ if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
+ {
+ if (sql_field->sql_type == FIELD_TYPE_BLOB)
+ {
+ /* The user has given a length to the blob column */
+ sql_field->sql_type= get_blob_type_from_length(sql_field->length);
+ sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
+ }
+ sql_field->length= 0;
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Preparation of create_field for SP function return values.
+ Based on code used in the inner loop of mysql_prepare_table() above
+
+ SYNOPSIS
+ sp_prepare_create_field()
+ thd Thread object
+ sql_field Field to prepare
+
+ DESCRIPTION
+ Prepares the field structures for field creation.
+
+*/
+
+void sp_prepare_create_field(THD *thd, create_field *sql_field)
+{
+ if (sql_field->sql_type == FIELD_TYPE_SET ||
+ sql_field->sql_type == FIELD_TYPE_ENUM)
+ {
+ uint32 field_length, dummy;
+ if (sql_field->sql_type == FIELD_TYPE_SET)
+ {
+ calculate_interval_lengths(sql_field->charset,
+ sql_field->interval, &dummy,
+ &field_length);
+ sql_field->length= field_length +
+ (sql_field->interval->count - 1);
+ }
+ else /* FIELD_TYPE_ENUM */
+ {
+ calculate_interval_lengths(sql_field->charset,
+ sql_field->interval,
+ &field_length, &dummy);
+ sql_field->length= field_length;
+ }
+ set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
+ }
+
+ if (sql_field->sql_type == FIELD_TYPE_BIT)
+ {
+ sql_field->pack_flag= FIELDFLAG_NUMBER |
+ FIELDFLAG_TREAT_BIT_AS_CHAR;
+ }
+ sql_field->create_length_to_internal_length();
+ DBUG_ASSERT(sql_field->def == 0);
+ /* Can't go wrong as sql_field->def is not defined */
+ (void) prepare_blob_field(thd, sql_field);
+}
+
+
+/*
Create a table
SYNOPSIS
@@ -1250,11 +1460,11 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
- tmp_table Set to 1 if this is an internal temporary table
+ internal_tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE)
DESCRIPTION
- If one creates a temporary table, this is automaticly opened
+ If one creates a temporary table, this is automatically opened
no_log is needed for the case of CREATE ... SELECT,
as the logging will be done later in sql_insert.cc
@@ -1262,42 +1472,34 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
and must be zero for standard create of table.
RETURN VALUES
- 0 ok
- -1 error
+ FALSE OK
+ TRUE error
*/
-int mysql_create_table(THD *thd,const char *db, const char *table_name,
- HA_CREATE_INFO *create_info,
- List<create_field> &fields,
- List<Key> &keys,bool tmp_table,
- uint select_field_count)
+bool mysql_create_table(THD *thd,const char *db, const char *table_name,
+ HA_CREATE_INFO *create_info,
+ List<create_field> &fields,
+ List<Key> &keys,bool internal_tmp_table,
+ uint select_field_count)
{
char path[FN_REFLEN];
const char *alias;
- int error= -1;
uint db_options, key_count;
KEY *key_info_buffer;
handler *file;
- enum db_type new_db_type;
+ bool error= TRUE;
DBUG_ENTER("mysql_create_table");
/* Check for duplicate fields and check type of table to create */
if (!fields.elements)
{
- my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
- DBUG_RETURN(-1);
- }
- if ((new_db_type= ha_checktype(create_info->db_type)) !=
- create_info->db_type)
- {
- create_info->db_type= new_db_type;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_USING_OTHER_HANDLER,
- ER(ER_WARN_USING_OTHER_HANDLER),
- ha_get_storage_engine(new_db_type),
- table_name);
+ my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
+ MYF(0));
+ DBUG_RETURN(TRUE);
}
- db_options=create_info->table_options;
+ if (check_engine(thd, table_name, &create_info->db_type))
+ DBUG_RETURN(TRUE);
+ db_options= create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
alias= table_case_name(create_info, table_name);
@@ -1314,8 +1516,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
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);
+ my_error(ER_ILLEGAL_HA, MYF(0), table_name);
+ DBUG_RETURN(TRUE);
}
#endif
@@ -1334,11 +1536,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
create_info->default_table_charset= db_info.default_table_charset;
}
- if (mysql_prepare_table(thd, create_info, fields,
- keys, tmp_table, db_options, file,
- key_info_buffer, &key_count,
+ if (mysql_prepare_table(thd, create_info, &fields,
+ &keys, internal_tmp_table, &db_options, file,
+ &key_info_buffer, &key_count,
select_field_count))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
/* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -1363,15 +1565,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
if (wait_if_global_read_lock(thd, 0, 1))
DBUG_RETURN(error);
VOID(pthread_mutex_lock(&LOCK_open));
- if (!tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
+ if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
if (!access(path,F_OK))
{
@@ -1427,22 +1629,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
thd->tmp_table_used= 1;
}
- if (!tmp_table)
+ if (!internal_tmp_table && mysql_bin_log.is_open())
{
- // Must be written before unlock
- mysql_update_log.write(thd,thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length,
- test(create_info->options &
- HA_LEX_CREATE_TMP_TABLE),
- FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+ mysql_bin_log.write(&qinfo);
}
- error=0;
- goto end;
+ error= FALSE;
+ goto end;
warn:
error= 0;
@@ -1502,7 +1696,7 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
****************************************************************************/
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
- const char *db, const char *name,
+ TABLE_LIST *create_table,
List<create_field> *extra_fields,
List<Key> *keys,
List<Item> *items,
@@ -1510,19 +1704,22 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
{
TABLE tmp_table; // Used during 'create_field()'
TABLE *table= 0;
- tmp_table.table_name=0;
uint select_field_count= items->elements;
- DBUG_ENTER("create_table_from_items");
-
/* Add selected items to field list */
List_iterator_fast<Item> it(*items);
Item *item;
Field *tmp_field;
- tmp_table.db_create_options=0;
+ bool not_used;
+ DBUG_ENTER("create_table_from_items");
+
+ tmp_table.alias= 0;
+ tmp_table.timestamp_field= 0;
+ tmp_table.s= &tmp_table.share_not_to_be_used;
+ tmp_table.s->db_create_options=0;
+ tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
+ tmp_table.s->db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM ||
+ create_info->db_type == DB_TYPE_HEAP);
tmp_table.null_row=tmp_table.maybe_null=0;
- tmp_table.blob_ptr_size=portable_sizeof_char_ptr;
- tmp_table.db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM ||
- create_info->db_type == DB_TYPE_HEAP);
while ((item=it++))
{
@@ -1532,42 +1729,60 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
field=item->tmp_table_field(&tmp_table);
else
field=create_tmp_field(thd, &tmp_table, item, item->type(),
- (Item ***) 0, &tmp_field, 0, 0, 0);
+ (Item ***) 0, &tmp_field, 0, 0, 0, 0);
if (!field ||
!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
((Item_field *)item)->field :
(Field*) 0))))
DBUG_RETURN(0);
+ if (item->maybe_null)
+ cr_field->flags &= ~NOT_NULL_FLAG;
extra_fields->push_back(cr_field);
}
- /* create and lock table */
- /* QQ: create and open should be done atomic ! */
/*
+ create and lock table
+
We don't log the statement, it will be logged later.
+
If this is a HEAP table, the automatic DELETE FROM which is written to the
binlog when a HEAP table is opened for the first time since startup, must
not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we
don't want to delete from it) 2) it would be written before the CREATE
TABLE, which is a wrong order. So we keep binary logging disabled when we
open_table().
+ TODO: create and open should be done atomic !
*/
- tmp_disable_binlog(thd);
- if (!mysql_create_table(thd,db,name,create_info,*extra_fields,
- *keys,0,select_field_count))
{
- if (!(table=open_table(thd,db,name,name,(bool*) 0)))
- quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
+ tmp_disable_binlog(thd);
+ if (!mysql_create_table(thd, create_table->db, create_table->table_name,
+ create_info, *extra_fields, *keys, 0,
+ select_field_count))
+ {
+ if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0,
+ MYSQL_LOCK_IGNORE_FLUSH)))
+ quick_rm_table(create_info->db_type, create_table->db,
+ table_case_name(create_info, create_table->table_name));
+ }
+ reenable_binlog(thd);
+ if (!table) // open failed
+ DBUG_RETURN(0);
}
- reenable_binlog(thd);
- if (!table)
- DBUG_RETURN(0);
+
+ /*
+ FIXME: What happens if trigger manages to be created while we are
+ obtaining this lock ? May be it is sensible just to disable
+ trigger execution in this case ? Or will MYSQL_LOCK_IGNORE_FLUSH
+ save us from that ?
+ */
table->reginfo.lock_type=TL_WRITE;
- if (! ((*lock)= mysql_lock_tables(thd, &table, 1, MYSQL_LOCK_IGNORE_FLUSH)))
+ if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
+ MYSQL_LOCK_IGNORE_FLUSH, &not_used)))
{
VOID(pthread_mutex_lock(&LOCK_open));
hash_delete(&open_cache,(byte*) table);
VOID(pthread_mutex_unlock(&LOCK_open));
- quick_rm_table(create_info->db_type,db,table_case_name(create_info, name));
+ quick_rm_table(create_info->db_type, create_table->db,
+ table_case_name(create_info, create_table->table_name));
DBUG_RETURN(0);
}
table->file->extra(HA_EXTRA_WRITE_CACHE);
@@ -1589,7 +1804,7 @@ mysql_rename_table(enum db_type base,
char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
char *from_base= from, *to_base= to;
char tmp_name[NAME_LEN+1];
- handler *file=get_new_handler((TABLE*) 0, base);
+ handler *file=(base == DB_TYPE_UNKNOWN ? 0 : get_new_handler((TABLE*) 0, base));
int error=0;
DBUG_ENTER("mysql_rename_table");
@@ -1601,7 +1816,8 @@ mysql_rename_table(enum db_type base,
file system) and the storage is not HA_FILE_BASED, we need to provide
a lowercase file name, but we leave the .frm in mixed case.
*/
- if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
+ if (lower_case_table_names == 2 && file &&
+ !(file->table_flags() & HA_FILE_BASED))
{
strmov(tmp_name, old_name);
my_casedn_str(files_charset_info, tmp_name);
@@ -1614,13 +1830,14 @@ mysql_rename_table(enum db_type base,
to_base= lc_to;
}
- if (!(error=file->rename_table(from_base, to_base)))
+ if (!file || !(error=file->rename_table(from_base, to_base)))
{
if (rename_file_ext(from,to,reg_ext))
{
error=my_errno;
/* Restore old file name */
- file->rename_table(to_base, from_base);
+ if (file)
+ file->rename_table(to_base, from_base);
}
}
delete file;
@@ -1651,7 +1868,7 @@ mysql_rename_table(enum db_type base,
static void wait_while_table_is_used(THD *thd,TABLE *table,
enum ha_extra_function function)
{
- DBUG_PRINT("enter",("table: %s", table->real_name));
+ DBUG_PRINT("enter",("table: %s", table->s->table_name));
DBUG_ENTER("wait_while_table_is_used");
safe_mutex_assert_owner(&LOCK_open);
@@ -1660,8 +1877,8 @@ static void wait_while_table_is_used(THD *thd,TABLE *table,
mysql_lock_abort(thd, table); // end threads waiting on lock
/* Wait until all there are no other threads that has this table open */
- remove_table_from_cache(thd,table->table_cache_key,
- table->real_name, RTFC_WAIT_OTHER_THREAD_FLAG);
+ remove_table_from_cache(thd, table->s->db,
+ table->s->table_name, RTFC_WAIT_OTHER_THREAD_FLAG);
DBUG_VOID_RETURN;
}
@@ -1682,7 +1899,7 @@ static void wait_while_table_is_used(THD *thd,TABLE *table,
Win32 clients must also have a WRITE LOCK on the table !
*/
-static bool close_cached_table(THD *thd, TABLE *table)
+void close_cached_table(THD *thd, TABLE *table)
{
DBUG_ENTER("close_cached_table");
@@ -1698,7 +1915,7 @@ static bool close_cached_table(THD *thd, TABLE *table)
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
- DBUG_RETURN(0);
+ DBUG_VOID_RETURN;
}
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
@@ -1711,7 +1928,7 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table,
protocol->store((char*) operator_name, system_charset_info);
protocol->store("error", 5, system_charset_info);
protocol->store(errmsg, system_charset_info);
- thd->net.last_error[0]=0;
+ thd->clear_error();
if (protocol->write())
return -1;
return 1;
@@ -1733,7 +1950,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
{
char* backup_dir= thd->lex->backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
- char* table_name = table->real_name;
+ char* table_name = table->table_name;
char* db = thd->db ? thd->db : table->db;
if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
@@ -1794,8 +2011,8 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
{
char name[FN_REFLEN];
build_table_path(name, sizeof(name), table_list->db,
- table_list->real_name, "");
- if (openfrm(name, "", 0, 0, 0, &tmp_table))
+ table_list->table_name, "");
+ if (openfrm(thd, name, "", 0, 0, 0, &tmp_table))
DBUG_RETURN(0); // Can't open frm file
table= &tmp_table;
}
@@ -1821,7 +2038,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
if (!ext[0] || !ext[1])
goto end; // No data file
- strxmov(from, table->path, ext[1], NullS); // Name of data file
+ strxmov(from, table->s->path, ext[1], NullS); // Name of data file
if (!my_stat(from, &stat_info, MYF(0)))
goto end; // Can't use USE_FRM flag
@@ -1886,27 +2103,33 @@ end:
}
+
/*
RETURN VALUES
- 0 Message sent to net (admin operation went ok)
- -1 Message should be sent by caller
- (admin operation or network communication failed)
+ FALSE Message sent to net (admin operation went ok)
+ TRUE Message should be sent by caller
+ (admin operation or network communication failed)
*/
-static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
- HA_CHECK_OPT* check_opt,
- const char *operator_name,
- thr_lock_type lock_type,
- bool open_for_modify,
- uint extra_open_options,
- int (*prepare_func)(THD *, TABLE_LIST *,
- HA_CHECK_OPT *),
- int (handler::*operator_func)
- (THD *, HA_CHECK_OPT *))
+static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
+ HA_CHECK_OPT* check_opt,
+ const char *operator_name,
+ thr_lock_type lock_type,
+ bool open_for_modify,
+ bool no_warnings_for_error,
+ uint extra_open_options,
+ int (*prepare_func)(THD *, TABLE_LIST *,
+ HA_CHECK_OPT *),
+ int (handler::*operator_func)(THD *,
+ HA_CHECK_OPT *),
+ int (view_operator_func)(THD *, TABLE_LIST*))
{
- TABLE_LIST *table;
+ TABLE_LIST *table, *save_next_global, *save_next_local;
+ SELECT_LEX *select= &thd->lex->select_lex;
List<Item> field_list;
Item *item;
Protocol *protocol= thd->protocol;
+ LEX *lex= thd->lex;
+ int result_code;
DBUG_ENTER("mysql_admin_table");
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
@@ -1917,22 +2140,46 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Msg_text", 255));
item->maybe_null = 1;
- if (protocol->send_fields(&field_list, 1))
- DBUG_RETURN(-1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
- for (table = tables; table; table = table->next)
+ for (table= tables; table; table= table->next_local)
{
char table_name[NAME_LEN*2+2];
char* db = table->db;
bool fatal_error=0;
- strxmov(table_name, db, ".", table->real_name, NullS);
+ strxmov(table_name, db, ".", table->table_name, NullS);
thd->open_options|= extra_open_options;
- table->table = open_ltable(thd, table, lock_type);
-#ifdef EMBEDDED_LIBRARY
- thd->net.last_errno= 0; // these errors shouldn't get client
-#endif
+ table->lock_type= lock_type;
+ /* open only one table from local list of command */
+ save_next_global= table->next_global;
+ table->next_global= 0;
+ save_next_local= table->next_local;
+ table->next_local= 0;
+ select->table_list.first= (byte*)table;
+ /*
+ Time zone tables and SP tables can be add to lex->query_tables list,
+ so it have to be prepared.
+ TODO: Investigate if we can put extra tables into argument instead of
+ using lex->query_tables
+ */
+ lex->query_tables= table;
+ lex->query_tables_last= &table->next_global;
+ lex->query_tables_own_last= 0;;
+ thd->no_warnings_for_error= no_warnings_for_error;
+ open_and_lock_tables(thd, table);
+ thd->no_warnings_for_error= 0;
+ table->next_global= save_next_global;
+ table->next_local= save_next_local;
+ /* if view are unsupported */
+ if (table->view && view_operator_func == NULL)
+ {
+ result_code= HA_ADMIN_NOT_IMPLEMENTED;
+ goto send_result;
+ }
thd->open_options&= ~extra_open_options;
if (prepare_func)
@@ -1948,8 +2195,17 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
}
+ /*
+ CHECK TABLE command is only command where VIEW allowed here and this
+ command use only temporary teble method for VIEWs resolving => there
+ can't be VIEW tree substitition of join view => if opening table
+ succeed then table->table will have real TABLE pointer as value (in
+ case of join view substitution table->table can be 0, but here it is
+ impossible)
+ */
if (!table->table)
{
+ char buf[ERRMSGSIZE+ERRMSGSIZE+2];
const char *err_msg;
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@@ -1957,22 +2213,44 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store("error",5, system_charset_info);
if (!(err_msg=thd->net.last_error))
err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
+ /* if it was a view will check md5 sum */
+ if (table->view &&
+ view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
+ {
+ strxmov(buf, err_msg, "; ", ER(ER_VIEW_CHECKSUM), NullS);
+ err_msg= (const char *)buf;
+ }
protocol->store(err_msg, system_charset_info);
- thd->net.last_error[0]=0;
+ lex->cleanup_after_one_table_open();
+ thd->clear_error();
+ /*
+ View opening can be interrupted in the middle of process so some
+ tables can be left opening
+ */
+ close_thread_tables(thd);
if (protocol->write())
goto err;
continue;
}
+
+ if (table->view)
+ {
+ result_code= (*view_operator_func)(thd, table);
+ goto send_result;
+ }
+
table->table->pos_in_table_list= table;
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
+ uint length;
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store("error", 5, system_charset_info);
- my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY), table_name);
- protocol->store(buff, system_charset_info);
+ length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
+ table_name);
+ protocol->store(buff, length, system_charset_info);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
@@ -1981,14 +2259,14 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
/* Close all instances of the table to allow repair to rename files */
- if (lock_type == TL_WRITE && table->table->version)
+ if (lock_type == TL_WRITE && table->table->s->version)
{
pthread_mutex_lock(&LOCK_open);
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
"Waiting to get writelock");
mysql_lock_abort(thd,table->table);
- remove_table_from_cache(thd, table->table->table_cache_key,
- table->table->real_name,
+ remove_table_from_cache(thd, table->table->s->db,
+ table->table->s->table_name,
RTFC_WAIT_OTHER_THREAD_FLAG |
RTFC_CHECK_KILLED_FLAG);
thd->exit_cond(old_message);
@@ -1999,10 +2277,23 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
open_for_modify= 0;
}
- int result_code = (table->table->file->*operator_func)(thd, check_opt);
-#ifdef EMBEDDED_LIBRARY
- thd->net.last_errno= 0; // these errors shouldn't get client
-#endif
+ if (table->table->s->crashed && operator_func == &handler::check)
+ {
+ protocol->prepare_for_resend();
+ protocol->store(table_name, system_charset_info);
+ protocol->store(operator_name, system_charset_info);
+ protocol->store("warning", 7, system_charset_info);
+ protocol->store("Table is marked as crashed", 26, system_charset_info);
+ if (protocol->write())
+ goto err;
+ }
+
+ result_code = (table->table->file->*operator_func)(thd, check_opt);
+
+send_result:
+
+ lex->cleanup_after_one_table_open();
+ thd->clear_error(); // these errors shouldn't get client
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
@@ -2061,8 +2352,9 @@ send_result_message:
reopen the table and do ha_innobase::analyze() on it.
*/
close_thread_tables(thd);
- TABLE_LIST *save_next= table->next;
- table->next= 0;
+ TABLE_LIST *save_next_local= table->next_local,
+ *save_next_global= table->next_global;
+ table->next_local= table->next_global= 0;
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table, 0);
reenable_binlog(thd);
@@ -2096,24 +2388,37 @@ send_result_message:
}
}
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
- table->next= save_next;
+ table->next_local= save_next_local;
+ table->next_global= save_next_global;
goto send_result_message;
}
+ case HA_ADMIN_WRONG_CHECKSUM:
+ {
+ protocol->store("note", 4, system_charset_info);
+ protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
+ system_charset_info);
+ break;
+ }
default: // Probably HA_ADMIN_INTERNAL_ERROR
- protocol->store("error", 5, system_charset_info);
- protocol->store("Unknown - internal error during operation", 41
- , system_charset_info);
- fatal_error=1;
- break;
+ {
+ char buf[ERRMSGSIZE+20];
+ uint length=my_snprintf(buf, ERRMSGSIZE,
+ "Unknown - internal error %d during operation",
+ result_code);
+ protocol->store("error", 5, system_charset_info);
+ protocol->store(buf, length, system_charset_info);
+ fatal_error=1;
+ break;
+ }
}
if (fatal_error)
- table->table->version=0; // Force close of table
+ table->table->s->version=0; // Force close of table
else if (open_for_modify)
{
pthread_mutex_lock(&LOCK_open);
- remove_table_from_cache(thd, table->table->table_cache_key,
- table->table->real_name, RTFC_NO_FLAG);
+ remove_table_from_cache(thd, table->table->s->db,
+ table->table->s->table_name, RTFC_NO_FLAG);
pthread_mutex_unlock(&LOCK_open);
/* May be something modified consequently we have to invalidate cache */
query_cache_invalidate3(thd, table->table, 0);
@@ -2125,50 +2430,52 @@ send_result_message:
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
-int mysql_backup_table(THD* thd, TABLE_LIST* table_list)
+bool mysql_backup_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_backup_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
- "backup", TL_READ, 0, 0, 0,
- &handler::backup));
+ "backup", TL_READ, 0, 0, 0, 0,
+ &handler::backup, 0));
}
-int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
+bool mysql_restore_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_restore_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
- "restore", TL_WRITE, 1, 0,
+ "restore", TL_WRITE, 1, 1, 0,
&prepare_for_restore,
- &handler::restore));
+ &handler::restore, 0));
}
-int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_repair_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR,
+ "repair", TL_WRITE, 1,
+ test(check_opt->sql_flags & TT_USEFRM),
+ HA_OPEN_FOR_REPAIR,
&prepare_for_repair,
- &handler::repair));
+ &handler::repair, 0));
}
-int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_optimize_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "optimize", TL_WRITE, 1,0,0,
- &handler::optimize));
+ "optimize", TL_WRITE, 1,0,0,0,
+ &handler::optimize, 0));
}
@@ -2181,11 +2488,11 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
tables Table list (one table only)
RETURN VALUES
- 0 ok
- -1 error
+ FALSE ok
+ TRUE error
*/
-int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
+bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
LEX_STRING *key_cache_name)
{
HA_CHECK_OPT check_opt;
@@ -2198,13 +2505,13 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
{
pthread_mutex_unlock(&LOCK_global_system_variables);
my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
pthread_mutex_unlock(&LOCK_global_system_variables);
check_opt.key_cache= key_cache;
DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
- "assign_to_keycache", TL_READ_NO_INSERT, 0,
- 0, 0, &handler::assign_to_keycache));
+ "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
+ 0, 0, &handler::assign_to_keycache, 0));
}
@@ -2256,16 +2563,16 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
tables Table list (one table only)
RETURN VALUES
- 0 ok
- -1 error
+ FALSE ok
+ TRUE error
*/
-int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
+bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
{
DBUG_ENTER("mysql_preload_keys");
DBUG_RETURN(mysql_admin_table(thd, tables, 0,
- "preload_keys", TL_READ, 0, 0, 0,
- &handler::preload_keys));
+ "preload_keys", TL_READ, 0, 0, 0, 0,
+ &handler::preload_keys, 0));
}
@@ -2280,21 +2587,22 @@ int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
table_ident Src table_ident
RETURN VALUES
- 0 ok
- -1 error
+ FALSE OK
+ TRUE error
*/
-int mysql_create_like_table(THD* thd, TABLE_LIST* table,
- HA_CREATE_INFO *create_info,
- Table_ident *table_ident)
+bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *table_ident)
{
TABLE **tmp_table;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char *db= table->db;
- char *table_name= table->real_name;
+ char *table_name= table->table_name;
char *src_db;
char *src_table= table_ident->table.str;
- int err, res= -1;
+ int err;
+ bool res= TRUE;
TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table");
src_db= table_ident->db.str ? table_ident->db.str : thd->db;
@@ -2307,7 +2615,7 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
check_table_name(src_table,table_ident->table.length)))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
if (!src_db || check_db_name(src_db))
{
@@ -2315,15 +2623,15 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
DBUG_RETURN(-1);
}
+ bzero((gptr)&src_tables_list, sizeof(src_tables_list));
src_tables_list.db= src_db;
- src_tables_list.real_name= src_table;
- src_tables_list.next= 0;
+ src_tables_list.table_name= src_table;
if (lock_and_wait_for_table_name(thd, &src_tables_list))
goto err;
if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
- strxmov(src_path, (*tmp_table)->path, reg_ext, NullS);
+ strxmov(src_path, (*tmp_table)->s->path, reg_ext, NullS);
else
{
strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
@@ -2339,6 +2647,15 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
}
}
+ /*
+ create like should be not allowed for Views, Triggers, ...
+ */
+ if (mysql_frm_type(src_path) != FRMTYPE_TABLE)
+ {
+ my_error(ER_WRONG_OBJECT, MYF(0), src_db, src_table, "BASE TABLE");
+ goto err;
+ }
+
/*
Validate the destination table
@@ -2402,17 +2719,13 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
}
// Must be written before unlock
- mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length,
- test(create_info->options &
- HA_LEX_CREATE_TMP_TABLE),
- FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
mysql_bin_log.write(&qinfo);
}
- res= 0;
+ res= FALSE;
goto err;
table_exists:
@@ -2421,9 +2734,9 @@ table_exists:
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff),
ER(ER_TABLE_EXISTS_ERROR), table_name);
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR,warn_buff);
- res= 0;
+ res= FALSE;
}
else
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
@@ -2436,7 +2749,7 @@ err:
}
-int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
#ifdef OS2
thr_lock_type lock_type = TL_WRITE;
@@ -2446,12 +2759,12 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_analyze_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "analyze", lock_type, 1,0,0,
- &handler::analyze));
+ "analyze", lock_type, 1, 0, 0, 0,
+ &handler::analyze, 0));
}
-int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
+bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
{
#ifdef OS2
thr_lock_type lock_type = TL_WRITE;
@@ -2462,8 +2775,8 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_check_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"check", lock_type,
- 0, HA_OPEN_FOR_REPAIR, 0,
- &handler::check));
+ 0, HA_OPEN_FOR_REPAIR, 0, 0,
+ &handler::check, &view_checksum));
}
@@ -2517,24 +2830,23 @@ mysql_discard_or_import_tablespace(THD *thd,
error=1;
if (error)
goto err;
- mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
mysql_bin_log.write(&qinfo);
}
err:
close_thread_tables(thd);
thd->tablespace_op=FALSE;
+
if (error == 0)
{
send_ok(thd);
DBUG_RETURN(0);
}
- if (error == HA_ERR_ROW_IS_REFERENCED)
- my_error(ER_ROW_IS_REFERENCED, MYF(0));
-
+ table->file->print_error(error, MYF(0));
+
DBUG_RETURN(-1);
}
@@ -2589,9 +2901,9 @@ int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
db_options= 0;
- if (mysql_prepare_table(thd, &create_info, fields,
- keys, /*tmp_table*/ 0, db_options, table->file,
- key_info_buffer, key_count,
+ if (mysql_prepare_table(thd, &create_info, &fields,
+ &keys, /*tmp_table*/ 0, &db_options, table->file,
+ &key_info_buffer, key_count,
/*select_field_count*/ 0))
DBUG_RETURN(-1);
@@ -2614,7 +2926,7 @@ int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.default_table_charset= thd->variables.collation_database;
/* Cleanup the fields list. We do not want to create existing fields. */
fields.delete_elements();
- if (real_alter_table(thd, table_list->db, table_list->real_name,
+ if (real_alter_table(thd, table_list->db, table_list->table_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_ADD_INDEX, DUP_ERROR))
@@ -2626,7 +2938,7 @@ int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
if (table->file->add_index(table, key_info_buffer, key_count)||
build_table_path(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
- table_list->alias : table_list->real_name,
+ table_list->alias : table_list->table_name,
reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
@@ -2710,7 +3022,7 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
if ((drop_key)|| (drop.elements<= 0))
{
- if (real_alter_table(thd, table_list->db, table_list->real_name,
+ if (real_alter_table(thd, table_list->db, table_list->table_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_DROP_INDEX, DUP_ERROR))
@@ -2721,13 +3033,13 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
{
db_options= 0;
if (table->file->drop_index(table, key_numbers, key_count)||
- mysql_prepare_table(thd, &create_info, fields,
- keys, /*tmp_table*/ 0, db_options, table->file,
- key_info_buffer, key_count,
+ mysql_prepare_table(thd, &create_info, &fields,
+ &keys, /*tmp_table*/ 0, &db_options, table->file,
+ &key_info_buffer, key_count,
/*select_field_count*/ 0)||
build_table_path(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
- table_list->alias : table_list->real_name,
+ table_list->alias : table_list->table_name,
reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
@@ -2745,15 +3057,15 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
Alter table
*/
-int mysql_alter_table(THD *thd,char *new_db, char *new_name,
- HA_CREATE_INFO *create_info,
- TABLE_LIST *table_list,
- List<create_field> &fields, List<Key> &keys,
- uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates, bool ignore,
- ALTER_INFO *alter_info, bool do_send_ok)
+bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ List<create_field> &fields, List<Key> &keys,
+ uint order_num, ORDER *order,
+ enum enum_duplicates handle_duplicates, bool ignore,
+ ALTER_INFO *alter_info, bool do_send_ok)
{
- TABLE *table,*new_table;
+ TABLE *table,*new_table=0;
int error;
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
@@ -2762,10 +3074,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
ulonglong next_insert_id;
uint db_create_options, used_fields;
enum db_type old_db_type,new_db_type;
+ bool need_copy_table;
DBUG_ENTER("mysql_alter_table");
thd->proc_info="init";
- table_name=table_list->real_name;
+ table_name=table_list->table_name;
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
db=table_list->db;
@@ -2779,7 +3092,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
alter_info->tablespace_op));
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
/* Check that we are not trying to rename to an existing table */
if (new_name)
@@ -2806,12 +3119,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
else
{
- if (table->tmp_table)
+ if (table->s->tmp_table)
{
if (find_temporary_table(thd,new_db,new_name_buff))
{
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
- DBUG_RETURN(-1);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
+ DBUG_RETURN(TRUE);
}
}
else
@@ -2822,8 +3135,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
F_OK))
{
/* Table will be closed in do_command() */
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias);
- DBUG_RETURN(-1);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
+ DBUG_RETURN(TRUE);
}
}
}
@@ -2834,24 +3147,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
new_name= table_name;
}
- old_db_type=table->db_type;
+ old_db_type= table->s->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT)
- create_info->db_type=old_db_type;
- if ((new_db_type= ha_checktype(create_info->db_type)) !=
- create_info->db_type)
- {
- create_info->db_type= new_db_type;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_USING_OTHER_HANDLER,
- ER(ER_WARN_USING_OTHER_HANDLER),
- ha_get_storage_engine(new_db_type),
- new_name);
- }
+ create_info->db_type= old_db_type;
+ if (check_engine(thd, new_name, &create_info->db_type))
+ DBUG_RETURN(TRUE);
+ new_db_type= create_info->db_type;
if (create_info->row_type == ROW_TYPE_NOT_USED)
- create_info->row_type=table->row_type;
+ create_info->row_type= table->s->row_type;
thd->proc_info="setup";
- if (alter_info->is_simple && !table->tmp_table)
+ if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
+ !table->s->tmp_table) // no need to touch frm
{
error=0;
if (new_name != table_name || new_db != db)
@@ -2862,7 +3169,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
error=0;
if (!access(new_name_buff,F_OK))
{
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
error= -1;
}
else
@@ -2879,37 +3186,37 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
switch (alter_info->keys_onoff) {
case LEAVE_AS_IS:
- break;
+ break;
case ENABLE:
- VOID(pthread_mutex_lock(&LOCK_open));
- wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
- error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
- /* COND_refresh will be signaled in close_thread_tables() */
- break;
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+ /* COND_refresh will be signaled in close_thread_tables() */
+ break;
case DISABLE:
- VOID(pthread_mutex_lock(&LOCK_open));
- wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
- error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
- /* COND_refresh will be signaled in close_thread_tables() */
- break;
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+ /* COND_refresh will be signaled in close_thread_tables() */
+ break;
}
}
+
if (error == HA_ERR_WRONG_COMMAND)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
- table->table_name);
+ table->alias);
error=0;
}
if (!error)
{
- mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
mysql_bin_log.write(&qinfo);
}
if (do_send_ok)
@@ -2927,17 +3234,17 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* Full alter table */
- /* let new create options override the old ones */
+ /* Let new create options override the old ones */
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
- create_info->min_rows=table->min_rows;
+ create_info->min_rows= table->s->min_rows;
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
- create_info->max_rows=table->max_rows;
+ create_info->max_rows= table->s->max_rows;
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
- create_info->avg_row_length=table->avg_row_length;
+ create_info->avg_row_length= table->s->avg_row_length;
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
- create_info->default_table_charset= table->table_charset;
+ create_info->default_table_charset= table->s->table_charset;
- restore_record(table,default_values); // Empty record for DEFAULT
+ restore_record(table, s->default_values); // Empty record for DEFAULT
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<create_field> def_it(fields);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
@@ -3006,8 +3313,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (def->sql_type == FIELD_TYPE_BLOB)
{
- my_error(ER_BLOB_CANT_HAVE_DEFAULT,MYF(0),def->change);
- DBUG_RETURN(-1);
+ my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
+ DBUG_RETURN(TRUE);
}
def->def=alter->def; // Use new default
alter_it.remove();
@@ -3020,8 +3327,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (def->change && ! def->field)
{
- my_error(ER_BAD_FIELD_ERROR,MYF(0),def->change,table_name);
- DBUG_RETURN(-1);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name);
+ DBUG_RETURN(TRUE);
}
if (!def->after)
create_list.push_back(def);
@@ -3038,22 +3345,23 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
if (!find)
{
- my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name);
- DBUG_RETURN(-1);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table_name);
+ DBUG_RETURN(TRUE);
}
find_it.after(def); // Put element after this
}
}
if (alter_info->alter_list.elements)
{
- my_error(ER_BAD_FIELD_ERROR,MYF(0),alter_info->alter_list.head()->name,
- table_name);
- DBUG_RETURN(-1);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ alter_info->alter_list.head()->name, table_name);
+ DBUG_RETURN(TRUE);
}
if (!create_list.elements)
{
- my_error(ER_CANT_REMOVE_ALL_FIELDS,MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
+ MYF(0));
+ DBUG_RETURN(TRUE);
}
/*
@@ -3066,7 +3374,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<key_part_spec> key_parts;
KEY *key_info=table->key_info;
- for (uint i=0 ; i < table->keys ; i++,key_info++)
+ for (uint i=0 ; i < table->s->keys ; i++,key_info++)
{
char *key_name= key_info->name;
Alter_drop *drop;
@@ -3108,12 +3416,26 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
continue; // Field is removed
uint key_part_length=key_part->length;
if (cfield->field) // Not new field
- { // Check if sub key
- if (cfield->field->type() != FIELD_TYPE_BLOB &&
- (cfield->field->pack_length() == key_part_length ||
- cfield->length <= key_part_length /
- key_part->field->charset()->mbmaxlen))
- key_part_length=0; // Use whole field
+ {
+ /*
+ If the field can't have only a part used in a key according to its
+ new type, or should not be used partially according to its
+ previous type, or the field length is less than the key part
+ length, unset the key part length.
+
+ We also unset the key part length if it is the same as the
+ old field's length, so the whole new field will be used.
+
+ BLOBs may have cfield->length == 0, which is why we test it before
+ checking whether cfield->length < key_part_length (in chars).
+ */
+ if (!Field::type_can_have_key_part(cfield->field->type()) ||
+ !Field::type_can_have_key_part(cfield->sql_type) ||
+ (cfield->field->field_length == key_part_length &&
+ !f_is_blob(key_part->key_type)) ||
+ (cfield->length && (cfield->length < key_part_length /
+ key_part->field->charset()->mbmaxlen)))
+ key_part_length= 0; // Use whole field
}
key_part_length /= key_part->field->charset()->mbmaxlen;
key_parts.push_back(new key_part_spec(cfield->field_name,
@@ -3142,25 +3464,25 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
{
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
}
if (alter_info->drop_list.elements)
{
- my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),
- alter_info->drop_list.head()->name);
+ my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
+ alter_info->drop_list.head()->name);
goto err;
}
if (alter_info->alter_list.elements)
{
- my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),
- alter_info->alter_list.head()->name);
+ my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
+ alter_info->alter_list.head()->name);
goto err;
}
- db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD);
+ db_create_options= table->s->db_create_options & ~(HA_OPTION_PACK_RECORD);
my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
current_pid, thd->thread_id);
/* Safety fix for innodb */
@@ -3172,7 +3494,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
create_info->db_type=new_db_type;
if (!create_info->comment)
- create_info->comment=table->comment;
+ create_info->comment= table->s->comment;
table->file->update_create_info(create_info);
if ((create_info->table_options &
@@ -3188,10 +3510,22 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
HA_OPTION_NO_DELAY_KEY_WRITE);
create_info->table_options|= db_create_options;
- if (table->tmp_table)
+ if (table->s->tmp_table)
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
/*
+ better have a negative test here, instead of positive, like
+ alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|...
+ so that ALTER TABLE won't break when somebody will add new flag
+ */
+ need_copy_table= (alter_info->flags &
+ ~(ALTER_CHANGE_COLUMN_DEFAULT|ALTER_OPTIONS) ||
+ (create_info->used_fields &
+ ~(HA_CREATE_USED_COMMENT|HA_CREATE_USED_PASSWORD)) ||
+ table->s->tmp_table);
+ create_info->frm_only= !need_copy_table;
+
+ /*
Handling of symlinked tables:
If no rename:
Create new data file and index file on the same disk as the
@@ -3237,8 +3571,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
else
create_info->data_file_name=create_info->index_file_name=0;
+
+ /* We don't log the statement, it will be logged later. */
{
- /* We don't log the statement, it will be logged later. */
tmp_disable_binlog(thd);
error= mysql_create_table(thd, new_db, tmp_name,
create_info,create_list,key_list,1,0);
@@ -3246,37 +3581,50 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (error)
DBUG_RETURN(error);
}
- if (table->tmp_table)
- new_table=open_table(thd,new_db,tmp_name,tmp_name,0);
- else
- {
- char path[FN_REFLEN];
- build_table_path(path, sizeof(path), new_db, tmp_name, "");
- new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
- }
- if (!new_table)
+ if (need_copy_table)
{
- VOID(quick_rm_table(new_db_type,new_db,tmp_name));
- goto err;
+ if (table->s->tmp_table)
+ {
+ TABLE_LIST tbl;
+ bzero((void*) &tbl, sizeof(tbl));
+ tbl.db= new_db;
+ tbl.table_name= tbl.alias= tmp_name;
+ new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
+ MYSQL_LOCK_IGNORE_FLUSH);
+ }
+ else
+ {
+ char path[FN_REFLEN];
+ my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
+ new_db, tmp_name);
+ fn_format(path,path,"","",4);
+ new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
+ }
+ if (!new_table)
+ {
+ VOID(quick_rm_table(new_db_type,new_db,tmp_name));
+ goto err;
+ }
}
-
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
- new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- new_table->next_number_field=new_table->found_next_number_field;
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0L;
thd->proc_info="copy to tmp table";
- next_insert_id=thd->next_insert_id; // Remember for loggin
+ next_insert_id=thd->next_insert_id; // Remember for logging
copied=deleted=0;
- if (!new_table->is_view)
+ if (new_table && !new_table->s->is_view)
+ {
+ new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+ new_table->next_number_field=new_table->found_next_number_field;
error=copy_data_between_tables(table,new_table,create_list,
handle_duplicates, ignore,
order_num, order, &copied, &deleted);
+ }
thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
- if (table->tmp_table)
+ if (table->s->tmp_table)
{
/* We changed a temporary table */
if (error)
@@ -3295,7 +3643,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
thd->lock=0;
}
/* Remove link to old table and rename the new one */
- close_temporary_table(thd,table->table_cache_key,table_name);
+ close_temporary_table(thd, table->s->db, table_name);
/* Should pass the 'new_name' as we store table name in the cache */
if (rename_temporary_table(thd, new_table, new_db, new_name))
{ // Fatal error
@@ -3303,18 +3651,20 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
my_free((gptr) new_table,MYF(0));
goto err;
}
- mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
mysql_bin_log.write(&qinfo);
}
goto end_temporary;
}
- intern_close_table(new_table); /* close temporary table */
- my_free((gptr) new_table,MYF(0));
+ if (new_table)
+ {
+ intern_close_table(new_table); /* close temporary table */
+ my_free((gptr) new_table,MYF(0));
+ }
VOID(pthread_mutex_lock(&LOCK_open));
if (error)
{
@@ -3326,7 +3676,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
/*
Data is copied. Now we rename the old table to a temp name,
rename the new one to the old name, remove all entries from the old table
- from the cash, free all locks, close the old table and remove it.
+ from the cache, free all locks, close the old table and remove it.
*/
thd->proc_info="rename result table";
@@ -3339,7 +3689,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!access(new_name_buff,F_OK))
{
error=1;
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
@@ -3355,12 +3705,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
close the original table at before doing the rename
*/
table_name=thd->strdup(table_name); // must be saved
- if (close_cached_table(thd, table))
- { // Aborted
- VOID(quick_rm_table(new_db_type,new_db,tmp_name));
- VOID(pthread_mutex_unlock(&LOCK_open));
- goto err;
- }
+ close_cached_table(thd, table);
table=0; // Marker that table is closed
}
#if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
@@ -3370,6 +3715,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
error=0;
+ if (!need_copy_table)
+ new_db_type=old_db_type=DB_TYPE_UNKNOWN; // this type cannot happen in regular ALTER
if (mysql_rename_table(old_db_type,db,table_name,db,old_name))
{
error=1;
@@ -3440,11 +3787,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err;
}
thd->proc_info="end";
- mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
mysql_bin_log.write(&qinfo);
}
VOID(pthread_cond_broadcast(&COND_refresh));
@@ -3481,10 +3827,10 @@ end_temporary:
if (do_send_ok)
send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0;
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
@@ -3522,11 +3868,18 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if (error)
DBUG_RETURN(-1);
- if (!(copy= new Copy_field[to->fields]))
+ if (!(copy= new Copy_field[to->s->fields]))
DBUG_RETURN(-1); /* purecov: inspected */
if (to->file->external_lock(thd, F_WRLCK))
DBUG_RETURN(-1);
+
+ /* We can abort alter table for any table type */
+ thd->no_trans_update= 0;
+ thd->abort_on_warning= !ignore && test(thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES));
+
from->file->info(HA_STATUS_VARIABLE);
to->file->start_bulk_insert(from->file->records);
@@ -3564,9 +3917,9 @@ copy_data_between_tables(TABLE *from,TABLE *to,
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
bzero((char*) &tables,sizeof(tables));
- tables.table = from;
- tables.alias = tables.real_name= from->real_name;
- tables.db = from->table_cache_key;
+ tables.table= from;
+ tables.alias= tables.table_name= (char*) from->s->table_name;
+ tables.db= (char*) from->s->db;
error=1;
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
@@ -3575,25 +3928,28 @@ copy_data_between_tables(TABLE *from,TABLE *to,
!(sortorder=make_unireg_sortorder(order, &length)) ||
(from->sort.found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
- &examined_rows))
- == HA_POS_ERROR)
+ &examined_rows)) ==
+ HA_POS_ERROR)
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 */
+ /*
+ 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 (ignore ||
handle_duplicates == DUP_REPLACE)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
thd->row_count= 0;
+ restore_record(to, s->default_values); // Create empty record
while (!(error=info.read_record(&info)))
{
if (thd->killed)
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0));
+ thd->send_kill_message();
error= 1;
break;
}
@@ -3605,6 +3961,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
else
to->next_number_field->reset();
}
+
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
{
copy_ptr->do_copy(copy_ptr);
@@ -3619,6 +3976,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
to->file->print_error(error,MYF(0));
break;
}
+ to->file->restore_auto_increment();
delete_count++;
}
else
@@ -3628,7 +3986,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
free_io_cache(from);
delete [] copy; // This is never 0
- if (to->file->end_bulk_insert() && !error)
+ if (to->file->end_bulk_insert() && error <= 0)
{
to->file->print_error(my_errno,MYF(0));
error=1;
@@ -3648,6 +4006,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
err:
thd->variables.sql_mode= save_sql_mode;
+ thd->abort_on_warning= 0;
free_io_cache(from);
*copied= found_count;
*deleted=delete_count;
@@ -3669,8 +4028,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
RETURN
Like mysql_alter_table().
*/
-int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
- bool do_send_ok)
+bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
+ bool do_send_ok)
{
DBUG_ENTER("mysql_recreate_table");
LEX *lex= thd->lex;
@@ -3679,11 +4038,12 @@ int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
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.row_type=ROW_TYPE_NOT_USED;
create_info.default_table_charset=default_charset_info;
+ /* Force alter table to recreate table */
+ lex->alter_info.flags= ALTER_CHANGE_COLUMN;
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
table_list, lex->create_list,
lex->key_list, 0, (ORDER *) 0,
@@ -3691,7 +4051,7 @@ int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
}
-int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
+bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
{
TABLE_LIST *table;
List<Item> field_list;
@@ -3703,15 +4063,16 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
item->maybe_null= 1;
field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
item->maybe_null= 1;
- if (protocol->send_fields(&field_list, 1))
- DBUG_RETURN(-1);
+ if (protocol->send_fields(&field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE);
- for (table= tables; table; table= table->next)
+ for (table= tables; table; table= table->next_local)
{
char table_name[NAME_LEN*2+2];
TABLE *t;
- strxmov(table_name, table->db ,".", table->real_name, NullS);
+ strxmov(table_name, table->db ,".", table->table_name, NullS);
t= table->table= open_ltable(thd, table, TL_READ_NO_INSERT);
thd->clear_error(); // these errors shouldn't get client
@@ -3723,7 +4084,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
{
/* Table didn't exist */
protocol->store_null();
- thd->net.last_error[0]=0;
+ thd->clear_error();
}
else
{
@@ -3763,7 +4124,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
row_crc= my_checksum(row_crc, t->record[0],
((byte*) t->field[0]->ptr) - t->record[0]);
- for (uint i= 0; i < t->fields; i++ )
+ for (uint i= 0; i < t->s->fields; i++ )
{
Field *f= t->field[i];
if (f->type() == FIELD_TYPE_BLOB)
@@ -3792,11 +4153,32 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
+}
+
+static bool check_engine(THD *thd, const char *table_name,
+ enum db_type *new_engine)
+{
+ enum db_type req_engine= *new_engine;
+ bool no_substitution=
+ test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION);
+ if ((*new_engine=
+ ha_checktype(thd, req_engine, no_substitution, 1)) == DB_TYPE_UNKNOWN)
+ return TRUE;
+
+ if (req_engine != *new_engine)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_USING_OTHER_HANDLER,
+ ER(ER_WARN_USING_OTHER_HANDLER),
+ ha_get_storage_engine(*new_engine),
+ table_name);
+ }
+ return FALSE;
}
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index d6afc888be2..1bd298dda04 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -79,7 +79,7 @@ void print_cached_tables(void)
{
TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
printf("%-14.14s %-32s%6ld%8ld%10ld%6d %s\n",
- entry->table_cache_key,entry->real_name,entry->version,
+ entry->s->db, entry->s->table_name, entry->s->version,
entry->in_use ? entry->in_use->thread_id : 0L,
entry->in_use ? entry->in_use->dbug_thread_id : 0L,
entry->db_stat ? 1 : 0, entry->in_use ? lock_descriptions[(int)entry->reginfo.lock_type] : "Not in use");
@@ -131,7 +131,7 @@ void TEST_filesort(SORT_FIELD *sortorder,uint s_length)
{
if (sortorder->field->table_name)
{
- out.append(sortorder->field->table_name);
+ out.append(*sortorder->field->table_name);
out.append('.');
}
out.append(sortorder->field->field_name ? sortorder->field->field_name:
@@ -167,7 +167,7 @@ TEST_join(JOIN *join)
TABLE *form=tab->table;
char key_map_buff[128];
fprintf(DBUG_FILE,"%-16.16s type: %-7s q_keys: %s refs: %d key: %d len: %d\n",
- form->table_name,
+ form->alias,
join_type_str[tab->type],
tab->keys.print(key_map_buff),
tab->ref.key_parts,
@@ -181,9 +181,10 @@ TEST_join(JOIN *join)
" quick select checked for each record (keys: %s)\n",
tab->select->quick_keys.print(buf));
else if (tab->select->quick)
- fprintf(DBUG_FILE," quick select used on key %s, length: %d\n",
- form->key_info[tab->select->quick->index].name,
- tab->select->quick->max_used_key_length);
+ {
+ fprintf(DBUG_FILE, " quick select used:\n");
+ tab->select->quick->dbug_dump(18, FALSE);
+ }
else
VOID(fputs(" select used\n",DBUG_FILE));
}
@@ -202,6 +203,104 @@ TEST_join(JOIN *join)
DBUG_VOID_RETURN;
}
+
+/*
+ Print the current state during query optimization.
+
+ SYNOPSIS
+ print_plan()
+ join pointer to the structure providing all context info for
+ the query
+ read_time the cost of the best partial plan
+ record_count estimate for the number of records returned by the best
+ partial plan
+ idx length of the partial QEP in 'join->positions';
+ also an index in the array 'join->best_ref';
+ info comment string to appear above the printout
+
+ DESCRIPTION
+ This function prints to the log file DBUG_FILE the members of 'join' that
+ are used during query optimization (join->positions, join->best_positions,
+ and join->best_ref) and few other related variables (read_time,
+ record_count).
+ Useful to trace query optimizer functions.
+
+ RETURN
+ None
+*/
+
+void
+print_plan(JOIN* join, double read_time, double record_count,
+ uint idx, const char *info)
+{
+ uint i;
+ POSITION pos;
+ JOIN_TAB *join_table;
+ JOIN_TAB **plan_nodes;
+ TABLE* table;
+
+ if (info == 0)
+ info= "";
+
+ DBUG_LOCK_FILE;
+ if (join->best_read == DBL_MAX)
+ {
+ fprintf(DBUG_FILE,"%s; idx:%u, best: DBL_MAX, current:%g\n",
+ info, idx, read_time);
+ }
+ else
+ {
+ fprintf(DBUG_FILE,"%s; idx: %u, best: %g, current: %g\n",
+ info, idx, join->best_read, read_time);
+ }
+
+ /* Print the tables in JOIN->positions */
+ fputs(" POSITIONS: ", DBUG_FILE);
+ for (i= 0; i < idx ; i++)
+ {
+ pos = join->positions[i];
+ table= pos.table->table;
+ if (table)
+ fputs(table->s->table_name, DBUG_FILE);
+ fputc(' ', DBUG_FILE);
+ }
+ fputc('\n', DBUG_FILE);
+
+ /*
+ Print the tables in JOIN->best_positions only if at least one complete plan
+ has been found. An indicator for this is the value of 'join->best_read'.
+ */
+ fputs("BEST_POSITIONS: ", DBUG_FILE);
+ if (join->best_read < DBL_MAX)
+ {
+ for (i= 0; i < idx ; i++)
+ {
+ pos= join->best_positions[i];
+ table= pos.table->table;
+ if (table)
+ fputs(table->s->table_name, DBUG_FILE);
+ fputc(' ', DBUG_FILE);
+ }
+ }
+ fputc('\n', DBUG_FILE);
+
+ /* Print the tables in JOIN->best_ref */
+ fputs(" BEST_REF: ", DBUG_FILE);
+ for (plan_nodes= join->best_ref ; *plan_nodes ; plan_nodes++)
+ {
+ join_table= (*plan_nodes);
+ fputs(join_table->table->s->table_name, DBUG_FILE);
+ fprintf(DBUG_FILE, "(%lu,%lu,%lu)",
+ (ulong) join_table->found_records,
+ (ulong) join_table->records,
+ (ulong) join_table->read_time);
+ fputc(' ', DBUG_FILE);
+ }
+ fputc('\n', DBUG_FILE);
+
+ DBUG_UNLOCK_FILE;
+}
+
#endif
typedef struct st_debug_lock
@@ -233,12 +332,12 @@ static void push_locks_into_array(DYNAMIC_ARRAY *ar, THR_LOCK_DATA *data,
if (data)
{
TABLE *table=(TABLE *)data->debug_print_param;
- if (table && table->tmp_table == NO_TMP_TABLE)
+ if (table && table->s->tmp_table == NO_TMP_TABLE)
{
TABLE_LOCK_INFO table_lock_info;
- table_lock_info.thread_id=table->in_use->thread_id;
- memcpy(table_lock_info.table_name, table->table_cache_key,
- table->key_length);
+ table_lock_info.thread_id= table->in_use->thread_id;
+ memcpy(table_lock_info.table_name, table->s->table_cache_key,
+ table->s->key_length);
table_lock_info.table_name[strlen(table_lock_info.table_name)]='.';
table_lock_info.waiting=wait;
table_lock_info.lock_text=text;
@@ -344,29 +443,24 @@ reads: %10s\n\n",
}
-void mysql_print_status(THD *thd)
+void mysql_print_status()
{
char current_dir[FN_REFLEN];
+ STATUS_VAR tmp;
+
+ calc_sum_of_all_status(&tmp);
printf("\nStatus information:\n\n");
my_getwd(current_dir, sizeof(current_dir),MYF(0));
printf("Current dir: %s\n", current_dir);
printf("Running threads: %d Stack size: %ld\n", thread_count,
(long) thread_stack);
- if (thd)
- thd->proc_info="locks";
thr_print_locks(); // Write some debug info
#ifndef DBUG_OFF
- if (thd)
- thd->proc_info="table cache";
print_cached_tables();
#endif
/* Print key cache status */
- if (thd)
- thd->proc_info="key cache";
puts("\nKey caches:");
process_key_caches(print_key_cache_status);
- if (thd)
- thd->proc_info="status";
pthread_mutex_lock(&LOCK_status);
printf("\nhandler status:\n\
read_key: %10lu\n\
@@ -376,16 +470,20 @@ read_first: %10lu\n\
write: %10lu\n\
delete %10lu\n\
update: %10lu\n",
- ha_read_key_count, ha_read_next_count,
- ha_read_rnd_count, ha_read_first_count,
- ha_write_count, ha_delete_count, ha_update_count);
+ tmp.ha_read_key_count,
+ tmp.ha_read_next_count,
+ tmp.ha_read_rnd_count,
+ tmp.ha_read_first_count,
+ tmp.ha_write_count,
+ tmp.ha_delete_count,
+ tmp.ha_update_count);
pthread_mutex_unlock(&LOCK_status);
printf("\nTable status:\n\
Opened tables: %10lu\n\
Open tables: %10lu\n\
Open files: %10lu\n\
Open streams: %10lu\n",
- opened_tables,
+ tmp.opened_tables,
(ulong) cached_tables(),
(ulong) my_file_opened,
(ulong) my_stream_opened);
@@ -403,8 +501,6 @@ Next alarm time: %lu\n",
#endif
display_table_locks();
fflush(stdout);
- if (thd)
- thd->proc_info="malloc";
my_checkmalloc();
TERMINATE(stdout); // Write malloc information
@@ -435,6 +531,4 @@ Estimated memory (with thread stack): %ld\n",
(long) (thread_count * thread_stack + info.hblkhd + info.arena));
#endif
puts("");
- if (thd)
- thd->proc_info=0;
}
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
new file mode 100644
index 00000000000..7342c146045
--- /dev/null
+++ b/sql/sql_trigger.cc
@@ -0,0 +1,926 @@
+/* Copyright (C) 2004-2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include "mysql_priv.h"
+#include "sp_head.h"
+#include "sql_trigger.h"
+#include "parse_file.h"
+
+static const LEX_STRING triggers_file_type= {(char *)"TRIGGERS", 8};
+
+const char * const triggers_file_ext= ".TRG";
+
+/*
+ Table of .TRG file field descriptors.
+ We have here only one field now because in nearest future .TRG
+ files will be merged into .FRM files (so we don't need something
+ like md5 or created fields).
+*/
+static File_option triggers_file_parameters[]=
+{
+ {{(char*)"triggers", 8},
+ offsetof(class Table_triggers_list, definitions_list),
+ FILE_OPTIONS_STRLIST},
+ {{(char*)"sql_modes", 13},
+ offsetof(class Table_triggers_list, definition_modes_list),
+ FILE_OPTIONS_ULLLIST},
+ {{0, 0}, 0, FILE_OPTIONS_STRING}
+};
+
+
+/*
+ Structure representing contents of .TRN file which are used to support
+ database wide trigger namespace.
+*/
+
+struct st_trigname
+{
+ LEX_STRING trigger_table;
+};
+
+static const LEX_STRING trigname_file_type= {(char *)"TRIGGERNAME", 11};
+
+const char * const trigname_file_ext= ".TRN";
+
+static File_option trigname_file_parameters[]=
+{
+ {{(char*)"trigger_table", 15}, offsetof(struct st_trigname, trigger_table),
+ FILE_OPTIONS_ESTRING},
+ {{0, 0}, 0, FILE_OPTIONS_STRING}
+};
+
+
+const LEX_STRING trg_action_time_type_names[]=
+{
+ { (char *) STRING_WITH_LEN("BEFORE") },
+ { (char *) STRING_WITH_LEN("AFTER") }
+};
+
+const LEX_STRING trg_event_type_names[]=
+{
+ { (char *) STRING_WITH_LEN("INSERT") },
+ { (char *) STRING_WITH_LEN("UPDATE") },
+ { (char *) STRING_WITH_LEN("DELETE") }
+};
+
+
+static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig);
+
+
+/*
+ Create or drop trigger for table.
+
+ SYNOPSIS
+ mysql_create_or_drop_trigger()
+ thd - current thread context (including trigger definition in LEX)
+ tables - table list containing one table for which trigger is created.
+ create - whenever we create (TRUE) or drop (FALSE) trigger
+
+ NOTE
+ This function is mainly responsible for opening and locking of table and
+ invalidation of all its instances in table cache after trigger creation.
+ Real work on trigger creation/dropping is done inside Table_triggers_list
+ methods.
+
+ RETURN VALUE
+ FALSE Success
+ TRUE error
+*/
+bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
+{
+ TABLE *table;
+ bool result= 0;
+
+ DBUG_ENTER("mysql_create_or_drop_trigger");
+
+ /*
+ QQ: This function could be merged in mysql_alter_table() function
+ But do we want this ?
+ */
+
+ if (!create &&
+ !(tables= add_table_for_trigger(thd, thd->lex->spname)))
+ DBUG_RETURN(TRUE);
+
+ /* We should have only one table in table list. */
+ DBUG_ASSERT(tables->next_global == 0);
+
+ if (!(table= open_ltable(thd, tables, tables->lock_type)))
+ DBUG_RETURN(TRUE);
+
+ /*
+ TODO: We should check if user has TRIGGER privilege for table here.
+ Now we just require SUPER privilege for creating/dropping because
+ we don't have proper privilege checking for triggers in place yet.
+ */
+ if (check_global_access(thd, SUPER_ACL))
+ DBUG_RETURN(TRUE);
+
+ /*
+ We do not allow creation of triggers on temporary tables. We also don't
+ allow creation of triggers on views but fulfilment of this restriction
+ is guaranteed by open_ltable(). It is better to have this check here
+ than do it in Table_triggers_list::create_trigger() and mess with table
+ cache.
+ */
+ if (table->s->tmp_table != NO_TMP_TABLE)
+ {
+ my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!table->triggers)
+ {
+ if (!create)
+ {
+ my_message(ER_TRG_DOES_NOT_EXIST, ER(ER_TRG_DOES_NOT_EXIST), MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!(table->triggers= new (&table->mem_root) Table_triggers_list(table)))
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ We don't want perform our operations while global read lock is held
+ so we have to wait until its end and then prevent it from occuring
+ again until we are done. (Acquiring LOCK_open is not enough because
+ global read lock is held without helding LOCK_open).
+ */
+ if (wait_if_global_read_lock(thd, 0, 0))
+ DBUG_RETURN(TRUE);
+
+ /*
+ There is no DETERMINISTIC clause for triggers, so can't check it.
+ But a trigger can in theory be used to do nasty things (if it supported
+ DROP for example) so we do the check for privileges. For now there is
+ already a stronger test above (see start of the function); but when this
+ stronger test will be removed, the test below will hold.
+ */
+ if (!trust_routine_creators && mysql_bin_log.is_open() &&
+ !(thd->master_access & SUPER_ACL))
+ {
+ my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,
+ ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
+ VOID(pthread_mutex_lock(&LOCK_open));
+ result= (create ?
+ table->triggers->create_trigger(thd, tables):
+ table->triggers->drop_trigger(thd, tables));
+
+ /* It is sensible to invalidate table in any case */
+ close_cached_table(thd, table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ start_waiting_global_read_lock(thd);
+
+ if (!result)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ /* Such a statement can always go directly to binlog, no trans cache */
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd);
+ }
+
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Create trigger for table.
+
+ SYNOPSIS
+ create_trigger()
+ thd - current thread context (including trigger definition in LEX)
+ tables - table list containing one open table for which trigger is
+ created.
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
+{
+ LEX *lex= thd->lex;
+ TABLE *table= tables->table;
+ char dir_buff[FN_REFLEN], file_buff[FN_REFLEN], trigname_buff[FN_REFLEN],
+ trigname_path[FN_REFLEN];
+ LEX_STRING dir, file, trigname_file;
+ LEX_STRING *trg_def, *name;
+ ulonglong *trg_sql_mode;
+ Item_trigger_field *trg_field;
+ struct st_trigname trigname;
+
+
+ /* Trigger must be in the same schema as target table. */
+ if (my_strcasecmp(table_alias_charset, table->s->db,
+ lex->spname->m_db.str ? lex->spname->m_db.str :
+ thd->db))
+ {
+ my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0));
+ return 1;
+ }
+
+ /* We don't allow creation of several triggers of the same type yet */
+ if (bodies[lex->trg_chistics.event][lex->trg_chistics.action_time])
+ {
+ my_message(ER_TRG_ALREADY_EXISTS, ER(ER_TRG_ALREADY_EXISTS), MYF(0));
+ return 1;
+ }
+
+ /*
+ Let us check if all references to fields in old/new versions of row in
+ this trigger are ok.
+
+ NOTE: We do it here more from ease of use standpoint. We still have to
+ do some checks on each execution. E.g. we can catch privilege changes
+ only during execution. Also in near future, when we will allow access
+ to other tables from trigger we won't be able to catch changes in other
+ tables...
+
+ Since we don't plan to access to contents of the fields it does not
+ matter that we choose for both OLD and NEW values the same versions
+ of Field objects here.
+ */
+ old_field= new_field= table->field;
+
+ for (trg_field= (Item_trigger_field *)(lex->trg_table_fields.first);
+ trg_field; trg_field= trg_field->next_trg_field)
+ {
+ trg_field->setup_field(thd, table);
+ if (!trg_field->fixed &&
+ trg_field->fix_fields(thd, (Item **)0))
+ return 1;
+ }
+
+ /*
+ Here we are creating file with triggers and save all triggers in it.
+ sql_create_definition_file() files handles renaming and backup of older
+ versions
+ */
+ strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", tables->db, "/", NullS);
+ dir.length= unpack_filename(dir_buff, dir_buff);
+ dir.str= dir_buff;
+ file.length= strxnmov(file_buff, FN_REFLEN, tables->table_name,
+ triggers_file_ext, NullS) - file_buff;
+ file.str= file_buff;
+ trigname_file.length= strxnmov(trigname_buff, FN_REFLEN,
+ lex->spname->m_name.str,
+ trigname_file_ext, NullS) - trigname_buff;
+ trigname_file.str= trigname_buff;
+ strxnmov(trigname_path, FN_REFLEN, dir_buff, trigname_buff, NullS);
+
+ /* Use the filesystem to enforce trigger namespace constraints. */
+ if (!access(trigname_path, F_OK))
+ {
+ my_error(ER_TRG_ALREADY_EXISTS, MYF(0));
+ return 1;
+ }
+
+ trigname.trigger_table.str= tables->table_name;
+ trigname.trigger_table.length= tables->table_name_length;
+
+ if (sql_create_definition_file(&dir, &trigname_file, &trigname_file_type,
+ (gptr)&trigname, trigname_file_parameters, 0))
+ return 1;
+
+ /*
+ Soon we will invalidate table object and thus Table_triggers_list object
+ so don't care about place to which trg_def->ptr points and other
+ invariants (e.g. we don't bother to update names_list)
+
+ QQ: Hmm... probably we should not care about setting up active thread
+ mem_root too.
+ */
+ if (!(trg_def= (LEX_STRING *)alloc_root(&table->mem_root,
+ sizeof(LEX_STRING))) ||
+ definitions_list.push_back(trg_def, &table->mem_root) ||
+ !(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root,
+ sizeof(ulonglong))) ||
+ definition_modes_list.push_back(trg_sql_mode, &table->mem_root))
+ goto err_with_cleanup;
+
+ trg_def->str= thd->query;
+ trg_def->length= thd->query_length;
+ *trg_sql_mode= thd->variables.sql_mode;
+
+ if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
+ (gptr)this, triggers_file_parameters, 3))
+ return 0;
+
+err_with_cleanup:
+ my_delete(trigname_path, MYF(MY_WME));
+ return 1;
+}
+
+
+/*
+ Deletes the .TRG file for a table
+
+ SYNOPSIS
+ rm_trigger_file()
+ path - char buffer of size FN_REFLEN to be used
+ for constructing path to .TRG file.
+ db - table's database name
+ table_name - table's name
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+
+static bool rm_trigger_file(char *path, char *db, char *table_name)
+{
+ strxnmov(path, FN_REFLEN, mysql_data_home, "/", db, "/", table_name,
+ triggers_file_ext, NullS);
+ unpack_filename(path, path);
+ return my_delete(path, MYF(MY_WME));
+}
+
+
+/*
+ Deletes the .TRN file for a trigger
+
+ SYNOPSIS
+ rm_trigname_file()
+ path - char buffer of size FN_REFLEN to be used
+ for constructing path to .TRN file.
+ db - trigger's database name
+ table_name - trigger's name
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+
+static bool rm_trigname_file(char *path, char *db, char *trigger_name)
+{
+ strxnmov(path, FN_REFLEN, mysql_data_home, "/", db, "/", trigger_name,
+ trigname_file_ext, NullS);
+ unpack_filename(path, path);
+ return my_delete(path, MYF(MY_WME));
+}
+
+
+/*
+ Drop trigger for table.
+
+ SYNOPSIS
+ drop_trigger()
+ thd - current thread context (including trigger definition in LEX)
+ tables - table list containing one open table for which trigger is
+ dropped.
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
+{
+ LEX *lex= thd->lex;
+ LEX_STRING *name;
+ List_iterator_fast<LEX_STRING> it_name(names_list);
+ List_iterator<LEX_STRING> it_def(definitions_list);
+ List_iterator<ulonglong> it_mod(definition_modes_list);
+ char path[FN_REFLEN];
+
+ while ((name= it_name++))
+ {
+ it_def++;
+ it_mod++;
+
+ if (my_strcasecmp(table_alias_charset, lex->spname->m_name.str,
+ name->str) == 0)
+ {
+ /*
+ Again we don't care much about other things required for
+ clean trigger removing since table will be reopened anyway.
+ */
+ it_def.remove();
+ it_mod.remove();
+
+ if (definitions_list.is_empty())
+ {
+ /*
+ TODO: Probably instead of removing .TRG file we should move
+ to archive directory but this should be done as part of
+ parse_file.cc functionality (because we will need it
+ elsewhere).
+ */
+ if (rm_trigger_file(path, tables->db, tables->table_name))
+ return 1;
+ }
+ else
+ {
+ char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
+ LEX_STRING dir, file;
+
+ strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", tables->db,
+ "/", NullS);
+ dir.length= unpack_filename(dir_buff, dir_buff);
+ dir.str= dir_buff;
+ file.length= strxnmov(file_buff, FN_REFLEN, tables->table_name,
+ triggers_file_ext, NullS) - file_buff;
+ file.str= file_buff;
+
+ if (sql_create_definition_file(&dir, &file, &triggers_file_type,
+ (gptr)this, triggers_file_parameters,
+ 3))
+ return 1;
+ }
+
+ if (rm_trigname_file(path, tables->db, lex->spname->m_name.str))
+ return 1;
+ return 0;
+ }
+ }
+
+ my_message(ER_TRG_DOES_NOT_EXIST, ER(ER_TRG_DOES_NOT_EXIST), MYF(0));
+ return 1;
+}
+
+
+Table_triggers_list::~Table_triggers_list()
+{
+ for (int i= 0; i < (int)TRG_EVENT_MAX; i++)
+ for (int j= 0; j < (int)TRG_ACTION_MAX; j++)
+ delete bodies[i][j];
+
+ if (record1_field)
+ for (Field **fld_ptr= record1_field; *fld_ptr; fld_ptr++)
+ delete *fld_ptr;
+}
+
+
+/*
+ Prepare array of Field objects referencing to TABLE::record[1] instead
+ of record[0] (they will represent OLD.* row values in ON UPDATE trigger
+ and in ON DELETE trigger which will be called during REPLACE execution).
+
+ SYNOPSIS
+ prepare_record1_accessors()
+ table - pointer to TABLE object for which we are creating fields.
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+bool Table_triggers_list::prepare_record1_accessors(TABLE *table)
+{
+ Field **fld, **old_fld;
+
+ if (!(record1_field= (Field **)alloc_root(&table->mem_root,
+ (table->s->fields + 1) *
+ sizeof(Field*))))
+ return 1;
+
+ for (fld= table->field, old_fld= record1_field; *fld; fld++, old_fld++)
+ {
+ /*
+ QQ: it is supposed that it is ok to use this function for field
+ cloning...
+ */
+ if (!(*old_fld= (*fld)->new_field(&table->mem_root, table)))
+ return 1;
+ (*old_fld)->move_field((my_ptrdiff_t)(table->record[1] -
+ table->record[0]));
+ }
+ *old_fld= 0;
+
+ return 0;
+}
+
+
+/*
+ Adjust Table_triggers_list with new TABLE pointer.
+
+ SYNOPSIS
+ set_table()
+ new_table - new pointer to TABLE instance
+*/
+
+void Table_triggers_list::set_table(TABLE *new_table)
+{
+ table= new_table;
+ for (Field **field= table->triggers->record1_field ; *field ; field++)
+ {
+ (*field)->table= (*field)->orig_table= new_table;
+ (*field)->table_name= &new_table->alias;
+ }
+}
+
+
+/*
+ Check whenever .TRG file for table exist and load all triggers it contains.
+
+ SYNOPSIS
+ check_n_load()
+ thd - current thread context
+ db - table's database name
+ table_name - table's name
+ table - pointer to table object
+ names_only - stop after loading trigger names
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+
+bool Table_triggers_list::check_n_load(THD *thd, const char *db,
+ const char *table_name, TABLE *table,
+ bool names_only)
+{
+ char path_buff[FN_REFLEN];
+ LEX_STRING path;
+ File_parser *parser;
+ LEX_STRING save_db;
+
+ DBUG_ENTER("Table_triggers_list::check_n_load");
+
+ strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", db, "/", table_name,
+ triggers_file_ext, NullS);
+ path.length= unpack_filename(path_buff, path_buff);
+ path.str= path_buff;
+
+ // QQ: should we analyze errno somehow ?
+ if (access(path_buff, F_OK))
+ DBUG_RETURN(0);
+
+ /*
+ File exists so we got to load triggers
+ FIXME: A lot of things to do here e.g. how about other funcs and being
+ more paranoical ?
+ */
+
+ if ((parser= sql_parse_prepare(&path, &table->mem_root, 1)))
+ {
+ if (is_equal(&triggers_file_type, parser->type()))
+ {
+ Table_triggers_list *triggers=
+ new (&table->mem_root) Table_triggers_list(table);
+
+ if (!triggers)
+ DBUG_RETURN(1);
+
+ /*
+ We don't have sql_modes in old versions of .TRG file, so we should
+ initialize list for safety.
+ */
+ triggers->definition_modes_list.empty();
+
+ if (parser->parse((gptr)triggers, &table->mem_root,
+ triggers_file_parameters, 2))
+ DBUG_RETURN(1);
+
+ List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
+ LEX_STRING *trg_create_str, *trg_name_str;
+ ulonglong *trg_sql_mode;
+
+ if (triggers->definition_modes_list.is_empty() &&
+ !triggers->definitions_list.is_empty())
+ {
+ /*
+ It is old file format => we should fill list of sql_modes.
+
+ We use one mode (current) for all triggers, because we have not
+ information about mode in old format.
+ */
+ if (!(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root,
+ sizeof(ulonglong))))
+ {
+ DBUG_RETURN(1); // EOM
+ }
+ *trg_sql_mode= global_system_variables.sql_mode;
+ while ((trg_create_str= it++))
+ {
+ if (triggers->definition_modes_list.push_back(trg_sql_mode,
+ &table->mem_root))
+ {
+ DBUG_RETURN(1); // EOM
+ }
+ }
+ it.rewind();
+ }
+
+ DBUG_ASSERT(triggers->definition_modes_list.elements ==
+ triggers->definitions_list.elements);
+ table->triggers= triggers;
+
+ /*
+ Construct key that will represent triggers for this table in the set
+ of routines used by statement.
+ */
+ triggers->sroutines_key.length= 1+strlen(db)+1+strlen(table_name)+1;
+ if (!(triggers->sroutines_key.str=
+ alloc_root(&table->mem_root, triggers->sroutines_key.length)))
+ DBUG_RETURN(1);
+ triggers->sroutines_key.str[0]= TYPE_ENUM_TRIGGER;
+ strxmov(triggers->sroutines_key.str+1, db, ".", table_name, NullS);
+
+ /*
+ TODO: This could be avoided if there is no triggers
+ for UPDATE and DELETE.
+ */
+ if (!names_only && triggers->prepare_record1_accessors(table))
+ DBUG_RETURN(1);
+
+ char *trg_name_buff;
+ List_iterator_fast<ulonglong> itm(triggers->definition_modes_list);
+ LEX *old_lex= thd->lex, lex;
+ ulong save_sql_mode= thd->variables.sql_mode;
+
+ thd->lex= &lex;
+
+ save_db.str= thd->db;
+ save_db.length= thd->db_length;
+ thd->db_length= strlen(db);
+ thd->db= (char *) db;
+ while ((trg_create_str= it++))
+ {
+ trg_sql_mode= itm++;
+ thd->variables.sql_mode= (ulong)*trg_sql_mode;
+ lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
+
+ if (yyparse((void *)thd) || thd->is_fatal_error)
+ {
+ /*
+ Free lex associated resources
+ QQ: Do we really need all this stuff here ?
+ */
+ delete lex.sphead;
+ goto err_with_lex_cleanup;
+ }
+
+ lex.sphead->m_sql_mode= *trg_sql_mode;
+ triggers->bodies[lex.trg_chistics.event]
+ [lex.trg_chistics.action_time]= lex.sphead;
+ if (triggers->names_list.push_back(&lex.sphead->m_name,
+ &table->mem_root))
+ goto err_with_lex_cleanup;
+
+ if (names_only)
+ {
+ lex_end(&lex);
+ continue;
+ }
+
+ /*
+ Let us bind Item_trigger_field objects representing access to fields
+ in old/new versions of row in trigger to Field objects in table being
+ opened.
+
+ We ignore errors here, because if even something is wrong we still
+ will be willing to open table to perform some operations (e.g.
+ SELECT)...
+ Anyway some things can be checked only during trigger execution.
+ */
+ for (Item_trigger_field *trg_field=
+ (Item_trigger_field *)(lex.trg_table_fields.first);
+ trg_field;
+ trg_field= trg_field->next_trg_field)
+ trg_field->setup_field(thd, table);
+
+ lex_end(&lex);
+ }
+ thd->db= save_db.str;
+ thd->db_length= save_db.length;
+ thd->lex= old_lex;
+ thd->variables.sql_mode= save_sql_mode;
+
+ DBUG_RETURN(0);
+
+err_with_lex_cleanup:
+ // QQ: anything else ?
+ lex_end(&lex);
+ thd->lex= old_lex;
+ thd->variables.sql_mode= save_sql_mode;
+ thd->db= save_db.str;
+ thd->db_length= save_db.length;
+ DBUG_RETURN(1);
+ }
+
+ /*
+ We don't care about this error message much because .TRG files will
+ be merged into .FRM anyway.
+ */
+ my_error(ER_WRONG_OBJECT, MYF(0),
+ table_name, triggers_file_ext+1, "TRIGGER");
+ DBUG_RETURN(1);
+ }
+
+ DBUG_RETURN(1);
+}
+
+
+/*
+ Obtains and returns trigger metadata
+
+ SYNOPSIS
+ get_trigger_info()
+ thd - current thread context
+ event - trigger event type
+ time_type - trigger action time
+ name - returns name of trigger
+ stmt - returns statement of trigger
+ sql_mode - returns sql_mode of trigger
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+
+bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
+ trg_action_time_type time_type,
+ LEX_STRING *trigger_name,
+ LEX_STRING *trigger_stmt,
+ ulong *sql_mode)
+{
+ sp_head *body;
+ DBUG_ENTER("get_trigger_info");
+ if ((body= bodies[event][time_type]))
+ {
+ *trigger_name= body->m_name;
+ *trigger_stmt= body->m_body;
+ *sql_mode= body->m_sql_mode;
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(1);
+}
+
+
+/*
+ Find trigger's table from trigger identifier and add it to
+ the statement table list.
+
+ SYNOPSIS
+ mysql_table_for_trigger()
+ thd - current thread context
+ trig - identifier for trigger
+
+ RETURN VALUE
+ 0 - error
+ # - pointer to TABLE_LIST object for the table
+*/
+
+static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
+{
+ const char *db= !trig->m_db.str ? thd->db : trig->m_db.str;
+ LEX *lex= thd->lex;
+ char path_buff[FN_REFLEN];
+ LEX_STRING path;
+ File_parser *parser;
+ struct st_trigname trigname;
+ DBUG_ENTER("add_table_for_trigger");
+
+ strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", db, "/",
+ trig->m_name.str, trigname_file_ext, NullS);
+ path.length= unpack_filename(path_buff, path_buff);
+ path.str= path_buff;
+
+ if (access(path_buff, F_OK))
+ {
+ my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
+ DBUG_RETURN(0);
+ }
+
+ if (!(parser= sql_parse_prepare(&path, thd->mem_root, 1)))
+ DBUG_RETURN(0);
+
+ if (!is_equal(&trigname_file_type, parser->type()))
+ {
+ my_error(ER_WRONG_OBJECT, MYF(0), trig->m_name.str, trigname_file_ext+1,
+ "TRIGGERNAME");
+ DBUG_RETURN(0);
+ }
+
+ if (parser->parse((gptr)&trigname, thd->mem_root,
+ trigname_file_parameters, 1))
+ DBUG_RETURN(0);
+
+ /* We need to reset statement table list to be PS/SP friendly. */
+ lex->query_tables= 0;
+ lex->query_tables_last= &lex->query_tables;
+ DBUG_RETURN(sp_add_to_query_tables(thd, lex, db,
+ trigname.trigger_table.str, TL_WRITE));
+}
+
+
+/*
+ Drop all triggers for table.
+
+ SYNOPSIS
+ drop_all_triggers()
+ thd - current thread context
+ db - schema for table
+ name - name for table
+
+ NOTE
+ The calling thread should hold the LOCK_open mutex;
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+
+bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name)
+{
+ TABLE table;
+ char path[FN_REFLEN];
+ bool result= 0;
+ DBUG_ENTER("drop_all_triggers");
+
+ bzero(&table, sizeof(table));
+ init_alloc_root(&table.mem_root, 8192, 0);
+
+ safe_mutex_assert_owner(&LOCK_open);
+
+ if (Table_triggers_list::check_n_load(thd, db, name, &table, 1))
+ {
+ result= 1;
+ goto end;
+ }
+ if (table.triggers)
+ {
+ LEX_STRING *trigger;
+ List_iterator_fast<LEX_STRING> it_name(table.triggers->names_list);
+
+ while ((trigger= it_name++))
+ {
+ if (rm_trigname_file(path, db, trigger->str))
+ {
+ /*
+ Instead of immediately bailing out with error if we were unable
+ to remove .TRN file we will try to drop other files.
+ */
+ result= 1;
+ continue;
+ }
+ }
+
+ if (rm_trigger_file(path, db, name))
+ {
+ result= 1;
+ goto end;
+ }
+ }
+end:
+ if (table.triggers)
+ delete table.triggers;
+ free_root(&table.mem_root, MYF(0));
+ DBUG_RETURN(result);
+}
+
+
+
+bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
+ trg_action_time_type time_type,
+ bool old_row_is_record1)
+{
+ int res= 0;
+
+ if (bodies[event][time_type])
+ {
+ Sub_statement_state statement_state;
+
+ if (old_row_is_record1)
+ {
+ old_field= record1_field;
+ new_field= table->field;
+ }
+ else
+ {
+ new_field= record1_field;
+ old_field= table->field;
+ }
+
+ /*
+ FIXME: We should juggle with security context here (because trigger
+ should be invoked with creator rights).
+ */
+
+ thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
+ res= bodies[event][time_type]->execute_function(thd, 0, 0, 0);
+ thd->restore_sub_statement_state(&statement_state);
+ }
+
+ return res;
+}
diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h
new file mode 100644
index 00000000000..c1d1f8d0e9e
--- /dev/null
+++ b/sql/sql_trigger.h
@@ -0,0 +1,112 @@
+/* Copyright (C) 2004-2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/*
+ This class holds all information about triggers of table.
+
+ QQ: Will it be merged into TABLE in future ?
+*/
+
+class Table_triggers_list: public Sql_alloc
+{
+ /* Triggers as SPs grouped by event, action_time */
+ sp_head *bodies[TRG_EVENT_MAX][TRG_ACTION_MAX];
+ /*
+ Copy of TABLE::Field array with field pointers set to TABLE::record[1]
+ buffer instead of TABLE::record[0] (used for OLD values in on UPDATE
+ trigger and DELETE trigger when it is called for REPLACE).
+ */
+ Field **record1_field;
+ /*
+ During execution of trigger new_field and old_field should point to the
+ array of fields representing new or old version of row correspondingly
+ (so it can point to TABLE::field or to Tale_triggers_list::record1_field)
+ */
+ Field **new_field;
+ Field **old_field;
+ /* TABLE instance for which this triggers list object was created */
+ TABLE *table;
+ /*
+ Names of triggers.
+ Should correspond to order of triggers on definitions_list,
+ used in CREATE/DROP TRIGGER for looking up trigger by name.
+ */
+ List<LEX_STRING> names_list;
+ /*
+ Key representing triggers for this table in set of all stored
+ routines used by statement.
+ TODO: We won't need this member once triggers namespace will be
+ database-wide instead of table-wide because then we will be able
+ to use key based on sp_name as for other stored routines.
+ */
+ LEX_STRING sroutines_key;
+
+public:
+ /*
+ Field responsible for storing triggers definitions in file.
+ It have to be public because we are using it directly from parser.
+ */
+ List<LEX_STRING> definitions_list;
+ /*
+ List of sql modes for triggers
+ */
+ List<ulonglong> definition_modes_list;
+
+ Table_triggers_list(TABLE *table_arg):
+ record1_field(0), table(table_arg)
+ {
+ bzero((char *)bodies, sizeof(bodies));
+ }
+ ~Table_triggers_list();
+
+ bool create_trigger(THD *thd, TABLE_LIST *table);
+ bool drop_trigger(THD *thd, TABLE_LIST *table);
+ bool process_triggers(THD *thd, trg_event_type event,
+ trg_action_time_type time_type,
+ bool old_row_is_record1);
+ bool get_trigger_info(THD *thd, trg_event_type event,
+ trg_action_time_type time_type,
+ LEX_STRING *trigger_name, LEX_STRING *trigger_stmt,
+ ulong *sql_mode);
+
+ static bool check_n_load(THD *thd, const char *db, const char *table_name,
+ TABLE *table, bool names_only);
+ static bool drop_all_triggers(THD *thd, char *db, char *table_name);
+
+ bool has_delete_triggers()
+ {
+ return (bodies[TRG_EVENT_DELETE][TRG_ACTION_BEFORE] ||
+ bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER]);
+ }
+
+ bool has_before_update_triggers()
+ {
+ return test(bodies[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE]);
+ }
+
+ void set_table(TABLE *new_table);
+
+ friend class Item_trigger_field;
+ friend void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
+ Table_triggers_list *triggers);
+
+private:
+ bool prepare_record1_accessors(TABLE *table);
+};
+
+extern const LEX_STRING trg_action_time_type_names[];
+extern const LEX_STRING trg_event_type_names[];
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 0b84d1b5fb3..ba3c598a784 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -17,15 +17,15 @@
/* This implements 'user defined functions' */
/*
-** Known bugs:
-**
-** Memory for functions are never freed!
-** Shared libraries are not closed before mysqld exists;
-** - This is because we can't be sure if some threads is using
-** a functions.
-**
-** The buggs only affects applications that creates and frees a lot of
-** dynamic functions, so this shouldn't be a real problem.
+ Known bugs:
+
+ Memory for functions is never freed!
+ Shared libraries are not closed before mysqld exits;
+ - This is because we can't be sure if some threads are using
+ a function.
+
+ The bugs only affect applications that create and free a lot of
+ dynamic functions, so this shouldn't be a real problem.
*/
#ifdef USE_PRAGMA_IMPLEMENTATION
@@ -110,15 +110,15 @@ static char *init_syms(udf_func *tmp, char *nm)
*/
if (!tmp->func_init && !tmp->func_deinit && tmp->type != UDFTYPE_AGGREGATE)
{
- if (opt_allow_suspicious_udfs)
- sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), nm);
- else
+ if (!opt_allow_suspicious_udfs)
return nm;
+ if (current_thd->variables.log_warnings)
+ sql_print_warning(ER(ER_CANT_FIND_DL_ENTRY), nm);
}
-
return 0;
}
+
extern "C" byte* get_hash_key(const byte *buff,uint *length,
my_bool not_used __attribute__((unused)))
{
@@ -127,9 +127,10 @@ extern "C" byte* get_hash_key(const byte *buff,uint *length,
return (byte*) udf->name.str;
}
+
/*
-** Read all predeclared functions from mysql.func and accept all that
-** can be used.
+ Read all predeclared functions from mysql.func and accept all that
+ can be used.
*/
void udf_init()
@@ -163,7 +164,7 @@ void udf_init()
new_thd->db_length=5;
bzero((gptr) &tables,sizeof(tables));
- tables.alias= tables.real_name= (char*) "func";
+ tables.alias= tables.table_name= (char*) "func";
tables.lock_type = TL_READ;
tables.db=new_thd->db;
@@ -185,7 +186,7 @@ void udf_init()
char *dl_name= get_field(&mem, table->field[2]);
bool new_dl=0;
Item_udftype udftype=UDFTYPE_FUNCTION;
- if (table->fields >= 4) // New func table
+ if (table->s->fields >= 4) // New func table
udftype=(Item_udftype) table->field[3]->val_int();
/*
@@ -402,7 +403,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
if (!initialized)
{
- send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
DBUG_RETURN(1);
}
@@ -413,19 +414,19 @@ int mysql_create_function(THD *thd,udf_func *udf)
*/
if (strchr(udf->dl, '/') || IF_WIN(strchr(udf->dl, '\\'),0))
{
- send_error(thd, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS));
+ my_message(ER_UDF_NO_PATHS, ER(ER_UDF_NO_PATHS), MYF(0));
DBUG_RETURN(1);
}
if (udf->name.length > NAME_LEN)
{
- net_printf(thd, ER_TOO_LONG_IDENT,udf->name);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), udf->name);
DBUG_RETURN(1);
}
rw_wrlock(&THR_LOCK_udf);
if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length)))
{
- net_printf(thd, ER_UDF_EXISTS, udf->name);
+ my_error(ER_UDF_EXISTS, MYF(0), udf->name);
goto err;
}
if (!(dl = find_udf_dl(udf->dl)))
@@ -434,7 +435,8 @@ int mysql_create_function(THD *thd,udf_func *udf)
{
DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)",
udf->dl,errno,dlerror()));
- net_printf(thd, ER_CANT_OPEN_LIBRARY, udf->dl, errno, dlerror());
+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0),
+ udf->dl, errno, dlerror());
goto err;
}
new_dl=1;
@@ -444,17 +446,14 @@ int mysql_create_function(THD *thd,udf_func *udf)
char buf[NAME_LEN+16], *missing;
if ((missing= init_syms(udf, buf)))
{
- net_printf(thd, ER_CANT_FIND_DL_ENTRY, missing);
+ my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), missing);
goto err;
}
}
udf->name.str=strdup_root(&mem,udf->name.str);
udf->dl=strdup_root(&mem,udf->dl);
if (!(u_d=add_udf(&udf->name,udf->returns,udf->dl,udf->type)))
- {
- send_error(thd,0); // End of memory
goto err;
- }
u_d->dlhandle = dl;
u_d->func=udf->func;
u_d->func_init=udf->func_init;
@@ -466,23 +465,23 @@ int mysql_create_function(THD *thd,udf_func *udf)
bzero((char*) &tables,sizeof(tables));
tables.db= (char*) "mysql";
- tables.real_name= tables.alias= (char*) "func";
+ tables.table_name= tables.alias= (char*) "func";
/* Allow creation of functions even if we can't open func table */
if (!(table = open_ltable(thd,&tables,TL_WRITE)))
goto err;
- restore_record(table,default_values); // Default values for fields
+ restore_record(table, s->default_values); // Default values for fields
table->field[0]->store(u_d->name.str, u_d->name.length, system_charset_info);
- table->field[1]->store((longlong) u_d->returns);
+ table->field[1]->store((longlong) u_d->returns, TRUE);
table->field[2]->store(u_d->dl,(uint) strlen(u_d->dl), system_charset_info);
- if (table->fields >= 4) // If not old func format
- table->field[3]->store((longlong) u_d->type);
+ if (table->s->fields >= 4) // If not old func format
+ table->field[3]->store((longlong) u_d->type, TRUE);
error = table->file->write_row(table->record[0]);
close_thread_tables(thd);
if (error)
{
- net_printf(thd, ER_ERROR_ON_WRITE, "mysql.func",error);
+ my_error(ER_ERROR_ON_WRITE, MYF(0), "mysql.func", error);
del_udf(u_d);
goto err;
}
@@ -505,14 +504,14 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
DBUG_ENTER("mysql_drop_function");
if (!initialized)
{
- send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
DBUG_RETURN(1);
}
rw_wrlock(&THR_LOCK_udf);
if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name->str,
(uint) udf_name->length)))
{
- net_printf(thd, ER_FUNCTION_NOT_DEFINED, udf_name->str);
+ my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str);
goto err;
}
del_udf(udf);
@@ -525,7 +524,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
bzero((char*) &tables,sizeof(tables));
tables.db=(char*) "mysql";
- tables.real_name= tables.alias= (char*) "func";
+ tables.table_name= tables.alias= (char*) "func";
if (!(table = open_ltable(thd,&tables,TL_WRITE)))
goto err;
table->field[0]->store(udf_name->str, udf_name->length, system_charset_info);
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index ca00901ea67..d588572a762 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -65,8 +65,8 @@ class udf_handler :public Sql_alloc
Item_result result_type () const
{ return u_d ? u_d->returns : STRING_RESULT;}
bool get_arguments();
- bool fix_fields(THD *thd,struct st_table_list *tlist,Item_result_field *item,
- uint arg_count,Item **args);
+ bool fix_fields(THD *thd, Item_result_field *item,
+ uint arg_count, Item **args);
void cleanup();
double val(my_bool *null_value)
{
@@ -104,6 +104,7 @@ class udf_handler :public Sql_alloc
*null_value=0;
return tmp;
}
+ my_decimal *val_decimal(my_bool *null_value, my_decimal *dec_buf);
void clear()
{
is_null= 0;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 8bb53f7b573..556493f4fc8 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -24,14 +24,20 @@
#include "mysql_priv.h"
#include "sql_select.h"
-int mysql_union(THD *thd, LEX *lex, select_result *result,
- SELECT_LEX_UNIT *unit)
+bool mysql_union(THD *thd, LEX *lex, select_result *result,
+ SELECT_LEX_UNIT *unit, ulong setup_tables_done_option)
{
DBUG_ENTER("mysql_union");
- int res= 0;
- if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK, "")))
+ bool res;
+ if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
+ setup_tables_done_option, "")))
res= unit->exec();
- res|= unit->cleanup();
+ if (!res && thd->cursor && thd->cursor->is_open())
+ {
+ thd->cursor->set_unit(unit);
+ }
+ else
+ res|= unit->cleanup();
DBUG_RETURN(res);
}
@@ -43,12 +49,6 @@ int mysql_union(THD *thd, LEX *lex, select_result *result,
select_union::select_union(TABLE *table_par)
:table(table_par)
{
- bzero((char*) &info,sizeof(info));
- /*
- We can always use IGNORE because the temporary table will only
- contain a unique key if we are using not using UNION ALL
- */
- info.ignore= 1;
}
select_union::~select_union()
@@ -65,22 +65,21 @@ int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
bool select_union::send_data(List<Item> &values)
{
+ int error= 0;
if (unit->offset_limit_cnt)
{ // using limit offset,count
unit->offset_limit_cnt--;
return 0;
}
- fill_record(table->field, values, 1);
- if (thd->net.report_error || write_record(table,&info))
+ fill_record(thd, table->field, values, 1);
+ if (thd->net.report_error)
+ return 1;
+
+ if ((error= table->file->write_row(table->record[0])))
{
- if (thd->net.last_errno == ER_RECORD_FILE_FULL)
- {
- thd->clear_error(); // do not report user about table overflow
- if (create_myisam_from_heap(thd, table, &tmp_table_param,
- info.last_errno, 1))
- return 1;
- }
- else
+ /* create_myisam_from_heap will generate error if needed */
+ if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE &&
+ create_myisam_from_heap(thd, table, &tmp_table_param, error, 1))
return 1;
}
return 0;
@@ -98,8 +97,7 @@ bool select_union::flush()
int error;
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{
- table->file->print_error(error,MYF(0));
- ::send_error(thd);
+ table->file->print_error(error, MYF(0));
return 1;
}
return 0;
@@ -117,31 +115,26 @@ bool select_union::flush()
options of SELECT
*/
-ulong
+void
st_select_lex_unit::init_prepare_fake_select_lex(THD *thd)
{
- ulong options_tmp= thd->options | fake_select_lex->options;
thd->lex->current_select= fake_select_lex;
- offset_limit_cnt= global_parameters->offset_limit;
- select_limit_cnt= global_parameters->select_limit +
- global_parameters->offset_limit;
-
- if (select_limit_cnt < global_parameters->select_limit)
- select_limit_cnt= HA_POS_ERROR; // no limit
- if (select_limit_cnt == HA_POS_ERROR)
- options_tmp&= ~OPTION_FOUND_ROWS;
- else if (found_rows_for_union && !thd->lex->describe)
- options_tmp|= OPTION_FOUND_ROWS;
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
(byte **)
- &result_table_list.next);
- return options_tmp;
+ &result_table_list.next_local);
+ for (ORDER *order= (ORDER *)global_parameters->order_list.first;
+ order;
+ order=order->next)
+ {
+ (*order->item)->walk(&Item::change_context_processor,
+ (byte *) &fake_select_lex->context);
+ }
}
-int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
- ulong additional_options,
- const char *tmp_table_alias)
+bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
+ ulong additional_options,
+ const char *tmp_table_alias)
{
SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
SELECT_LEX *sl, *first_select;
@@ -171,16 +164,16 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (!sl->join->procedure &&
result->prepare(sl->join->fields_list, this))
{
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
sl->join->select_options|= SELECT_DESCRIBE;
sl->join->reinit();
}
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
prepared= 1;
- res= 0;
+ res= FALSE;
thd_arg->lex->current_select= sl= first_select= first_select_in_union();
found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;
@@ -199,6 +192,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
else
tmp_result= sel_result;
+ sl->context.resolve_in_select_list= TRUE;
+
for (;sl; sl= sl->next_select())
{
bool can_skip_order_by;
@@ -206,22 +201,24 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
JOIN *join= new JOIN(thd_arg, sl->item_list,
sl->options | thd_arg->options | additional_options,
tmp_result);
+ /*
+ setup_tables_done_option should be set only for very first SELECT,
+ because it protect from secont setup_tables call for select-like non
+ select commands (DELETE/INSERT/...) and they use only very first
+ SELECT (for union it can be only INSERT ... SELECT).
+ */
+ additional_options&= ~OPTION_SETUP_TABLES_DONE;
if (!join)
goto err;
thd_arg->lex->current_select= sl;
- offset_limit_cnt= sl->offset_limit;
- select_limit_cnt= sl->select_limit+sl->offset_limit;
- if (select_limit_cnt < sl->select_limit)
- select_limit_cnt= HA_POS_ERROR; // no limit
- can_skip_order_by= is_union &&
- (!sl->braces || select_limit_cnt == HA_POS_ERROR);
+ can_skip_order_by= is_union && !(sl->braces && sl->explicit_limit);
res= join->prepare(&sl->ref_pointer_array,
(TABLE_LIST*) sl->table_list.first, sl->with_wild,
sl->where,
- (can_skip_order_by ? 0 : sl->order_list.elements) +
+ (can_skip_order_by ? 0 : sl->order_list.elements) +
sl->group_list.elements,
can_skip_order_by ?
(ORDER*) 0 : (ORDER *)sl->order_list.first,
@@ -233,9 +230,16 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
/* There are no * in the statement anymore (for PS) */
sl->with_wild= 0;
last_procedure= join->procedure;
- if (res || thd_arg->is_fatal_error)
+
+ if ((res= (res || thd_arg->is_fatal_error)))
goto err;
- if (sl == first_select)
+ /*
+ Use items list of underlaid select for derived tables to preserve
+ information about fields lengths and exact types
+ */
+ if (!is_union)
+ types= first_select_in_union()->item_list;
+ else if (sl == first_select)
{
/*
We need to create an empty table object. It is used
@@ -271,7 +275,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
while ((type= tp++, item_tmp= it++))
{
if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
}
@@ -283,9 +287,9 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
all collations together for UNION.
*/
List_iterator_fast<Item> tp(types);
- Item_arena *arena= thd->current_arena;
+ Query_arena *arena= thd->stmt_arena;
Item *type;
- ulong create_options;
+ ulonglong create_options;
while ((type= tp++))
{
@@ -312,49 +316,49 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (!(table= create_tmp_table(thd_arg,
&union_result->tmp_table_param, types,
(ORDER*) 0, (bool) union_distinct, 1,
- create_options, HA_POS_ERROR,
+ create_options, HA_POS_ERROR,
(char *) tmp_table_alias)))
goto err;
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
bzero((char*) &result_table_list, sizeof(result_table_list));
result_table_list.db= (char*) "";
- result_table_list.real_name= result_table_list.alias= (char*) "union";
+ result_table_list.table_name= result_table_list.alias= (char*) "union";
result_table_list.table= table;
union_result->set_table(table);
thd_arg->lex->current_select= lex_select_save;
if (!item_list.elements)
{
- /*
- We're in statement prepare or in execution
- of a conventional statement.
- */
- Item_arena *tmp_arena,backup;
- tmp_arena= thd->change_arena_if_needed(&backup);
-
Field **field;
+ Query_arena *tmp_arena,backup;
+ tmp_arena= thd->activate_stmt_arena_if_needed(&backup);
+
for (field= table->field; *field; field++)
{
Item_field *item= new Item_field(*field);
if (!item || item_list.push_back(item))
{
if (tmp_arena)
- thd->restore_backup_item_arena(tmp_arena, &backup);
- DBUG_RETURN(-1);
+ thd->restore_active_arena(tmp_arena, &backup);
+ DBUG_RETURN(TRUE);
}
}
if (tmp_arena)
- thd->restore_backup_item_arena(tmp_arena, &backup);
- if (arena->is_stmt_prepare())
+ thd->restore_active_arena(tmp_arena, &backup);
+ if (arena->is_stmt_prepare_or_first_sp_execute())
{
/* prepare fake select to initialize it correctly */
- (void) init_prepare_fake_select_lex(thd);
+ init_prepare_fake_select_lex(thd);
+ /*
+ Should be done only once (the only item_list per statement).
+ */
+ DBUG_ASSERT(fake_select_lex->join == 0);
if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
result)))
{
fake_select_lex->table_list.empty();
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
fake_select_lex->item_list= item_list;
@@ -371,17 +375,17 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
fake_select_lex->table_list.empty();
}
}
- else if (arena->is_stmt_execute())
+ else if (!arena->is_conventional())
{
/*
- We're in execution of a prepared statement: reset field items
- to point at fields from the created temporary table.
+ We're in execution of a prepared statement or stored procedure:
+ reset field items to point at fields from the created temporary table.
*/
List_iterator_fast<Item> it(item_list);
for (Field **field= table->field; *field; field++)
{
Item_field *item_field= (Item_field*) it++;
- DBUG_ASSERT(item_field);
+ DBUG_ASSERT(item_field != 0);
item_field->reset_field(*field);
}
}
@@ -389,15 +393,15 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= lex_select_save;
- DBUG_RETURN(res || thd_arg->is_fatal_error ? 1 : 0);
+ DBUG_RETURN(res || thd_arg->is_fatal_error);
err:
thd_arg->lex->current_select= lex_select_save;
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
-int st_select_lex_unit::exec()
+bool st_select_lex_unit::exec()
{
SELECT_LEX *lex_select_save= thd->lex->current_select;
SELECT_LEX *select_cursor=first_select_in_union();
@@ -406,7 +410,7 @@ int st_select_lex_unit::exec()
DBUG_ENTER("st_select_lex_unit::exec");
if (executed && !uncacheable && !describe)
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
executed= 1;
if (uncacheable || !item || !item->assigned() || describe)
@@ -434,12 +438,8 @@ int st_select_lex_unit::exec()
res= sl->join->reinit();
else
{
- if (sl != global_parameters && !describe)
- {
- offset_limit_cnt= sl->offset_limit;
- select_limit_cnt= sl->select_limit+sl->offset_limit;
- }
- else
+ set_limit(sl);
+ if (sl == global_parameters || describe)
{
offset_limit_cnt= 0;
/*
@@ -448,11 +448,7 @@ int st_select_lex_unit::exec()
*/
if (sl->order_list.first || describe)
select_limit_cnt= HA_POS_ERROR;
- else
- select_limit_cnt= sl->select_limit+sl->offset_limit;
- }
- if (select_limit_cnt < sl->select_limit)
- select_limit_cnt= HA_POS_ERROR; // no limit
+ }
/*
When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
@@ -471,11 +467,13 @@ int st_select_lex_unit::exec()
if (sl == union_distinct)
{
if (table->file->disable_indexes(HA_KEY_SWITCH_ALL))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
table->no_keyread=1;
}
res= sl->join->error;
- offset_limit_cnt= sl->offset_limit;
+ offset_limit_cnt= (ha_rows)(sl->offset_limit ?
+ sl->offset_limit->val_uint() :
+ 0);
if (!res)
{
examined_rows+= thd->examined_row_count;
@@ -510,14 +508,15 @@ int st_select_lex_unit::exec()
optimized= 1;
/* Send result to 'result' */
- res= -1;
+ res= TRUE;
{
List<Item_func_match> empty_list;
empty_list.empty();
if (!thd->is_fatal_error) // Check if EOM
{
- ulong options_tmp= init_prepare_fake_select_lex(thd);
+ set_limit(global_parameters);
+ init_prepare_fake_select_lex(thd);
JOIN *join= fake_select_lex->join;
if (!join)
{
@@ -525,11 +524,11 @@ int st_select_lex_unit::exec()
allocate JOIN for fake select only once (prevent
mysql_select automatic allocation)
*/
- if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
- result)))
+ if (!(fake_select_lex->join= new JOIN(thd, item_list,
+ fake_select_lex->options, result)))
{
fake_select_lex->table_list.empty();
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
/*
@@ -541,12 +540,14 @@ int st_select_lex_unit::exec()
else
{
JOIN_TAB *tab,*end;
- for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
+ for (tab=join->join_tab, end=tab+join->tables ;
+ tab && tab != end ;
+ tab++)
{
delete tab->select;
delete tab->quick;
}
- join->init(thd, item_list, thd->options, result);
+ join->init(thd, item_list, fake_select_lex->options, result);
}
res= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list,
@@ -554,7 +555,7 @@ int st_select_lex_unit::exec()
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
- options_tmp | SELECT_NO_UNLOCK,
+ fake_select_lex->options | SELECT_NO_UNLOCK,
result, this, fake_select_lex);
fake_select_lex->table_list.empty();
@@ -574,14 +575,14 @@ int st_select_lex_unit::exec()
}
-int st_select_lex_unit::cleanup()
+bool st_select_lex_unit::cleanup()
{
int error= 0;
DBUG_ENTER("st_select_lex_unit::cleanup");
if (cleaned)
{
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
cleaned= 1;
@@ -593,33 +594,21 @@ int st_select_lex_unit::cleanup()
free_tmp_table(thd, table);
table= 0; // Safety
}
- JOIN *join;
- SELECT_LEX *sl= first_select_in_union();
- for (; sl; sl= sl->next_select())
+
+ for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
+ error|= sl->cleanup();
+
+ if (fake_select_lex)
{
- if ((join= sl->join))
- {
- error|= sl->join->cleanup();
- delete join;
- }
- else
+ JOIN *join;
+ if ((join= fake_select_lex->join))
{
- // it can be DO/SET with subqueries
- for (SELECT_LEX_UNIT *lex_unit= sl->first_inner_unit();
- lex_unit != 0;
- lex_unit= lex_unit->next_unit())
- {
- error|= lex_unit->cleanup();
- }
+ join->tables_list= 0;
+ join->tables= 0;
}
+ error|= fake_select_lex->cleanup();
}
- if (fake_select_lex && (join= fake_select_lex->join))
- {
- join->tables_list= 0;
- join->tables= 0;
- error|= join->cleanup();
- delete join;
- }
+
DBUG_RETURN(error);
}
@@ -655,21 +644,43 @@ void st_select_lex_unit::reinit_exec_mechanism()
old_result old select_result object
RETURN
- 0 - OK
- -1 - error
+ FALSE - OK
+ TRUE - error
*/
-int st_select_lex_unit::change_result(select_subselect *result,
- select_subselect *old_result)
+bool st_select_lex_unit::change_result(select_subselect *result,
+ select_subselect *old_result)
{
- int res= 0;
+ bool res= FALSE;
for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
{
if (sl->join && sl->join->result == old_result)
- if ((res= sl->join->change_result(result)))
- return (res);
+ if (sl->join->change_result(result))
+ return TRUE;
}
if (fake_select_lex && fake_select_lex->join)
res= fake_select_lex->join->change_result(result);
return (res);
}
+
+
+bool st_select_lex::cleanup()
+{
+ bool error= FALSE;
+ DBUG_ENTER("st_select_lex::cleanup()");
+
+ if (join)
+ {
+ DBUG_ASSERT((st_select_lex*)join->select_lex == this);
+ error= join->destroy();
+ delete join;
+ join= 0;
+ }
+ for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ;
+ lex_unit= lex_unit->next_unit())
+ {
+ error= (bool) ((uint) error | (uint) lex_unit->cleanup());
+ }
+ DBUG_RETURN(error);
+}
+
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6c12381b4bd..a75eef9324c 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -22,31 +22,92 @@
#include "mysql_priv.h"
#include "sql_select.h"
+#include "sp_head.h"
+#include "sql_trigger.h"
static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields);
/* Return 0 if row hasn't changed */
-static bool compare_record(TABLE *table, ulong query_id)
+static bool compare_record(TABLE *table, query_id_t query_id)
{
- if (!table->blob_fields)
+ if (table->s->blob_fields + table->s->varchar_fields == 0)
return cmp_record(table,record[1]);
/* Compare null bits */
if (memcmp(table->null_flags,
- table->null_flags+table->rec_buff_length,
- table->null_bytes))
- return 1; // Diff in NULL value
+ table->null_flags+table->s->rec_buff_length,
+ table->s->null_bytes))
+ return TRUE; // Diff in NULL value
/* Compare updated fields */
for (Field **ptr=table->field ; *ptr ; ptr++)
{
if ((*ptr)->query_id == query_id &&
- (*ptr)->cmp_binary_offset(table->rec_buff_length))
- return 1;
+ (*ptr)->cmp_binary_offset(table->s->rec_buff_length))
+ return TRUE;
}
- return 0;
+ return FALSE;
}
+/*
+ check that all fields are real fields
+
+ SYNOPSIS
+ check_fields()
+ thd thread handler
+ items Items for check
+
+ RETURN
+ TRUE Items can't be used in UPDATE
+ FALSE Items are OK
+*/
+
+static bool check_fields(THD *thd, List<Item> &items)
+{
+ List_iterator<Item> it(items);
+ Item *item;
+ Item_field *field;
+ Name_resolution_context *context= &thd->lex->select_lex.context;
+
+ while ((item= it++))
+ {
+ if (!(field= item->filed_for_view_update()))
+ {
+ /* item has name, because it comes from VIEW SELECT list */
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
+ return TRUE;
+ }
+ /*
+ we make temporary copy of Item_field, to avoid influence of changing
+ result_field on Item_ref which refer on this field
+ */
+ thd->change_item_tree(it.ref(), new Item_field(thd, field));
+ }
+ return FALSE;
+}
+
+
+/*
+ Process usual UPDATE
+
+ SYNOPSIS
+ mysql_update()
+ thd thread handler
+ fields fields for update
+ values values of fields for update
+ conds WHERE clause expression
+ order_num number of elemen in ORDER BY clause
+ order ORDER BY clause list
+ limit limit clause
+ handle_duplicates how to handle duplicates
+
+ RETURN
+ 0 - OK
+ 2 - privilege check and openning table passed, but we need to convert to
+ multi-update because of view substitution
+ 1 - error
+*/
+
int mysql_update(THD *thd,
TABLE_LIST *table_list,
List<Item> &fields,
@@ -54,45 +115,70 @@ int mysql_update(THD *thd,
COND *conds,
uint order_num, ORDER *order,
ha_rows limit,
- enum enum_duplicates handle_duplicates,
- bool ignore)
+ enum enum_duplicates handle_duplicates, bool ignore)
{
- bool using_limit=limit != HA_POS_ERROR;
+ bool using_limit= limit != HA_POS_ERROR;
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
- bool used_key_is_modified, transactional_table, log_delayed;
+ bool used_key_is_modified, transactional_table;
+ int res;
int error=0;
uint used_index;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint want_privilege;
#endif
- ulong query_id=thd->query_id, timestamp_query_id;
+ uint table_count= 0;
+ query_id_t query_id=thd->query_id, timestamp_query_id;
ha_rows updated, found;
key_map old_used_keys;
TABLE *table;
SQL_SELECT *select;
READ_RECORD info;
- TABLE_LIST *update_table_list= ((TABLE_LIST*)
- thd->lex->select_lex.table_list.first);
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
+ bool need_reopen;
DBUG_ENTER("mysql_update");
LINT_INIT(timestamp_query_id);
- if ((open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(-1);
+ for ( ; ; )
+ {
+ if (open_tables(thd, &table_list, &table_count, 0))
+ DBUG_RETURN(1);
+
+ if (table_list->multitable_view)
+ {
+ DBUG_ASSERT(table_list->view != 0);
+ DBUG_PRINT("info", ("Switch to multi-update"));
+ /* pass counter value */
+ thd->lex->table_count= table_count;
+ /* convert to multiupdate */
+ DBUG_RETURN(2);
+ }
+ if (!lock_tables(thd, table_list, table_count, &need_reopen))
+ break;
+ if (!need_reopen)
+ DBUG_RETURN(1);
+ close_tables_for_reopen(thd, table_list);
+ }
+
+ if (mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
+ (thd->fill_derived_tables() &&
+ mysql_handle_derived(thd->lex, &mysql_derived_filling)))
+ DBUG_RETURN(1);
+
thd->proc_info="init";
table= table_list->table;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
/* Calculate "table->used_keys" based on the WHERE */
- table->used_keys=table->keys_in_use;
+ table->used_keys= table->s->keys_in_use;
table->quick_keys.clear_all();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- want_privilege= table->grant.want_privilege;
+ /* TABLE_LIST contain right privilages request */
+ want_privilege= table_list->grant.want_privilege;
#endif
- if ((error= mysql_prepare_update(thd, table_list, update_table_list,
- &conds, order_num, order)))
- DBUG_RETURN(error);
+ if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
+ DBUG_RETURN(1);
old_used_keys= table->used_keys; // Keys used in WHERE
/*
@@ -107,10 +193,19 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table->grant.want_privilege=want_privilege;
+ table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
#endif
- if (setup_fields(thd, 0, update_table_list, fields, 1, 0, 0))
- DBUG_RETURN(-1); /* purecov: inspected */
+ if (setup_fields_with_no_wrap(thd, 0, fields, 1, 0, 0))
+ DBUG_RETURN(1); /* purecov: inspected */
+ if (table_list->view && check_fields(thd, fields))
+ {
+ DBUG_RETURN(1);
+ }
+ if (!table_list->updatable || check_key_in_view(thd, table_list))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
+ DBUG_RETURN(1);
+ }
if (table->timestamp_field)
{
// Don't set timestamp column if this is modified
@@ -122,25 +217,26 @@ int mysql_update(THD *thd,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */
- table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
+ table_list->grant.want_privilege= table->grant.want_privilege=
+ (SELECT_ACL & ~table->grant.privilege);
#endif
- if (setup_fields(thd, 0, update_table_list, values, 1, 0, 0))
+ if (setup_fields(thd, 0, values, 1, 0, 0))
{
- free_underlaid_joins(thd, &thd->lex->select_lex);
- DBUG_RETURN(-1); /* purecov: inspected */
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(1); /* purecov: inspected */
}
// Don't count on usage of 'only index' when calculating which key to use
table->used_keys.clear_all();
- select=make_select(table,0,0,conds,&error);
+ select= make_select(table, 0, 0, conds, 0, &error);
if (error ||
(select && select->check_quick(thd, safe_update, limit)) || !limit)
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, select_lex);
if (error)
{
- DBUG_RETURN(-1); // Error in where
+ DBUG_RETURN(1); // Error in where
}
send_ok(thd); // No matching records
DBUG_RETURN(0);
@@ -156,21 +252,20 @@ int mysql_update(THD *thd,
goto err;
}
}
- init_ftfuncs(thd, &thd->lex->select_lex, 1);
+ init_ftfuncs(thd, select_lex, 1);
/* Check if we are modifying a key that we are used to search with */
+
if (select && select->quick)
{
- used_index=select->quick->index;
+ used_index= select->quick->index;
used_key_is_modified= (!select->quick->unique_key_range() &&
- check_if_key_used(table, used_index, fields));
+ select->quick->check_if_keys_used(&fields));
}
else if ((used_index=table->file->key_used_on_scan) < MAX_KEY)
used_key_is_modified=check_if_key_used(table, used_index, fields);
else
- {
used_key_is_modified=0;
- used_index= MAX_KEY;
- }
+
if (used_key_is_modified || order)
{
/*
@@ -224,8 +319,12 @@ int mysql_update(THD *thd,
if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
DISK_BUFFER_SIZE, MYF(MY_WME)))
goto err;
-
+
+ /* If quick select is used, initialize it before retrieving rows. */
+ if (select && select->quick && select->quick->reset())
+ goto err;
init_read_record(&info,thd,table,select,0,1);
+
thd->proc_info="Searching rows for update";
uint tmp_limit= limit;
@@ -246,6 +345,8 @@ int mysql_update(THD *thd,
break;
}
}
+ else
+ table->file->unlock_row();
}
if (thd->killed && !error)
error= 1; // Aborted
@@ -280,6 +381,9 @@ int mysql_update(THD *thd,
if (ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+
+ if (select && select->quick && select->quick->reset())
+ goto err;
init_read_record(&info,thd,table,select,0,1);
updated= found= 0;
@@ -288,22 +392,54 @@ int mysql_update(THD *thd,
thd->proc_info="Updating";
query_id=thd->query_id;
+ transactional_table= table->file->has_transactions();
+ thd->no_trans_update= 0;
+ thd->abort_on_warning= test(!ignore &&
+ (thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES)));
+
while (!(error=info.read_record(&info)) && !thd->killed)
{
if (!(select && select->skip_record()))
{
store_record(table,record[1]);
- if (fill_record(fields,values, 0) || thd->net.report_error)
+ if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
+ table->triggers,
+ TRG_EVENT_UPDATE))
break; /* purecov: inspected */
+
found++;
+
if (compare_record(table, query_id))
{
+ if ((res= table_list->view_check_option(thd, ignore)) !=
+ VIEW_CHECK_OK)
+ {
+ found--;
+ if (res == VIEW_CHECK_SKIP)
+ continue;
+ else if (res == VIEW_CHECK_ERROR)
+ {
+ error= 1;
+ break;
+ }
+ }
if (!(error=table->file->update_row((byte*) table->record[1],
(byte*) table->record[0])))
{
updated++;
+ thd->no_trans_update= !transactional_table;
+
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER, TRUE))
+ {
+ error= 1;
+ break;
+ }
}
- else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
+ else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
{
thd->fatal_error(); // Force error message
table->file->print_error(error,MYF(0));
@@ -311,6 +447,7 @@ int mysql_update(THD *thd,
break;
}
}
+
if (!--limit && using_limit)
{
error= -1; // Simulate end of file
@@ -334,23 +471,22 @@ int mysql_update(THD *thd,
This must be before binlog writing and ha_autocommit_...
*/
if (updated)
+ {
query_cache_invalidate3(thd, table_list, 1);
+ }
- transactional_table= table->file->has_transactions();
- log_delayed= (transactional_table || table->tmp_table);
if ((updated || (error < 0)) && (error <= 0 || !transactional_table))
{
- mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
if (error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed, FALSE);
+ transactional_table, FALSE);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1; // Rollback update
}
- if (!log_delayed)
+ if (!transactional_table)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (transactional_table)
@@ -365,32 +501,33 @@ int mysql_update(THD *thd,
thd->lock=0;
}
- free_underlaid_joins(thd, &thd->lex->select_lex);
- if (error >= 0)
- send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
- else
+ free_underlaid_joins(thd, select_lex);
+ if (error < 0)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
(ulong) thd->cuted_fields);
- send_ok(thd,
- (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
+ thd->row_count_func=
+ (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
+ send_ok(thd, (ulong) thd->row_count_func,
thd->insert_id_used ? thd->insert_id() : 0L,buff);
DBUG_PRINT("info",("%d records updated",updated));
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
+ thd->abort_on_warning= 0;
free_io_cache(table);
- DBUG_RETURN(0);
+ DBUG_RETURN((error >= 0 || thd->net.report_error) ? 1 : 0);
err:
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, select_lex);
if (table->key_read)
{
table->key_read=0;
table->file->extra(HA_EXTRA_NO_KEYREAD);
}
- DBUG_RETURN(-1);
+ thd->abort_on_warning= 0;
+ DBUG_RETURN(1);
}
/*
@@ -399,51 +536,55 @@ err:
SYNOPSIS
mysql_prepare_update()
thd - thread handler
- table_list - global table list
- update_table_list - local table list of UPDATE SELECT_LEX
+ table_list - global/local table list
conds - conditions
order_num - number of ORDER BY list entries
order - ORDER BY clause list
RETURN VALUE
- 0 - OK
- 1 - error (message is sent to user)
- -1 - error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- TABLE_LIST *update_table_list,
+bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
Item **conds, uint order_num, ORDER *order)
{
TABLE *table= table_list->table;
TABLE_LIST tables;
List<Item> all_fields;
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_update");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
+ table_list->grant.want_privilege= table->grant.want_privilege=
+ (SELECT_ACL & ~table->grant.privilege);
#endif
bzero((char*) &tables,sizeof(tables)); // For ORDER BY
tables.table= table;
tables.alias= table_list->alias;
- if (setup_tables(update_table_list) ||
- setup_conds(thd, update_table_list, conds) ||
- thd->lex->select_lex.setup_ref_array(thd, order_num) ||
- setup_order(thd, thd->lex->select_lex.ref_pointer_array,
- update_table_list, all_fields, all_fields, order) ||
- setup_ftfuncs(&thd->lex->select_lex))
- DBUG_RETURN(-1);
+ if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
+ table_list, conds, &select_lex->leaf_tables,
+ FALSE) ||
+ setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
+ select_lex->setup_ref_array(thd, order_num) ||
+ setup_order(thd, select_lex->ref_pointer_array,
+ table_list, all_fields, all_fields, order) ||
+ setup_ftfuncs(select_lex))
+ DBUG_RETURN(TRUE);
/* Check that we are not using table that we are updating in a sub select */
- if (find_real_table_in_list(table_list->next,
- table_list->db, table_list->real_name))
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
- DBUG_RETURN(-1);
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(table_list, table_list->next_global)))
+ {
+ update_non_unique_table_error(table_list, "UPDATE", duplicate);
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
+ DBUG_RETURN(TRUE);
+ }
}
-
- DBUG_RETURN(0);
+ select_lex->fix_prepare_information(thd, conds);
+ DBUG_RETURN(FALSE);
}
@@ -469,247 +610,266 @@ static table_map get_table_map(List<Item> *items)
/*
- Prepare tables for multi-update
- Analyse which tables need specific privileges and perform locking
- as required
+ make update specific preparation and checks after opening tables
+
+ SYNOPSIS
+ mysql_multi_update_prepare()
+ thd thread handler
+
+ RETURN
+ FALSE OK
+ TRUE Error
*/
-int mysql_multi_update_lock(THD *thd,
- TABLE_LIST *table_list,
- List<Item> *fields,
- SELECT_LEX *select_lex)
+bool mysql_multi_update_prepare(THD *thd)
{
- int res;
- TABLE_LIST *tl;
- TABLE_LIST *update_list= (TABLE_LIST*) thd->lex->select_lex.table_list.first;
+ LEX *lex= thd->lex;
+ TABLE_LIST *table_list= lex->query_tables;
+ TABLE_LIST *tl, *leaves;
+ List<Item> *fields= &lex->select_lex.item_list;
+ table_map tables_for_update;
+ bool update_view= 0;
+ /*
+ if this multi-update was converted from usual update, here is table
+ counter else junk will be assigned here, but then replaced with real
+ count in open_tables()
+ */
+ uint table_count= lex->table_count;
const bool using_lock_tables= thd->locked_tables != 0;
- bool initialized_dervied= 0;
- DBUG_ENTER("mysql_multi_update_lock");
+ bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI);
+ bool need_reopen= FALSE;
+ DBUG_ENTER("mysql_multi_update_prepare");
+
+ /* following need for prepared statements, to run next time multi-update */
+ thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
+
+reopen_tables:
+ /* open tables and create derived ones, but do not lock and fill them */
+ if (((original_multiupdate || need_reopen) &&
+ open_tables(thd, &table_list, &table_count, 0)) ||
+ mysql_handle_derived(lex, &mysql_derived_prepare))
+ DBUG_RETURN(TRUE);
/*
- The following loop is here to to ensure that we only lock tables
- that we are going to update with a write lock
+ setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
+ second time, but this call will do nothing (there are check for second
+ call in setup_tables()).
*/
- for (;;)
- {
- table_map update_tables, derived_tables=0;
- uint tnr, table_count;
-
- if ((res=open_tables(thd, table_list, &table_count)))
- DBUG_RETURN(res);
- /* Only need to call lock_tables if we are not using LOCK TABLES */
- if (!using_lock_tables &&
- ((res= lock_tables(thd, table_list, table_count))))
- DBUG_RETURN(res);
+ if (setup_tables(thd, &lex->select_lex.context,
+ &lex->select_lex.top_join_list,
+ table_list, &lex->select_lex.where,
+ &lex->select_lex.leaf_tables, FALSE))
+ DBUG_RETURN(TRUE);
- if (!initialized_dervied)
- {
- initialized_dervied= 1;
- relink_tables_for_derived(thd);
- if ((res= mysql_handle_derived(thd->lex)))
- DBUG_RETURN(res);
- }
+ if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0))
+ DBUG_RETURN(TRUE);
- /*
- Ensure that we have update privilege for all tables and columns in the
- SET part
- While we are here, initialize the table->map field to check which
- tables are updated and updatability of derived tables
- */
- for (tl= update_list, tnr=0 ; tl ; tl=tl->next)
+ for (tl= table_list; tl ; tl= tl->next_local)
+ {
+ if (tl->view)
{
- TABLE *table= tl->table;
- /*
- Update of derived tables is checked later
- We don't check privileges here, becasue then we would get error
- "UPDATE command denided .. for column N" instead of
- "Target table ... is not updatable"
- */
- if (!tl->derived)
- table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege);
- table->map= (table_map) 1 << (tnr++);
+ update_view= 1;
+ break;
}
+ }
- if (setup_fields(thd, 0, update_list, *fields, 1, 0, 0))
- DBUG_RETURN(-1);
+ if (update_view && check_fields(thd, *fields))
+ {
+ DBUG_RETURN(TRUE);
+ }
- update_tables= get_table_map(fields);
+ tables_for_update= get_table_map(fields);
- /* Unlock the tables in preparation for relocking */
- if (!using_lock_tables)
- {
- mysql_unlock_tables(thd, thd->lock);
- thd->lock= 0;
- }
+ /*
+ Setup timestamp handling and locking mode
+ */
+ leaves= lex->select_lex.leaf_tables;
+ for (tl= leaves; tl; tl= tl->next_leaf)
+ {
+ TABLE *table= tl->table;
+ /* Only set timestamp column if this is not modified */
+ if (table->timestamp_field &&
+ table->timestamp_field->query_id == thd->query_id)
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- /*
- Count tables and setup timestamp handling
- Set also the table locking strategy according to the update map
- */
- for (tl= update_list; tl; tl= tl->next)
+ /* if table will be updated then check that it is unique */
+ if (table->map & tables_for_update)
{
- TABLE_LIST *save= tl->next;
- TABLE *table= tl->table;
- uint wants;
- /* if table will be updated then check that it is unique */
- if (table->map & update_tables)
- {
- /*
- Multi-update can't be constructed over-union => we always have
- single SELECT on top and have to check underlaying SELECTs of it
- */
- if (select_lex->check_updateable_in_subqueries(tl->db,
- tl->real_name))
- {
- my_error(ER_UPDATE_TABLE_USED, MYF(0),
- tl->real_name);
- DBUG_RETURN(-1);
- }
- DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
- tl->lock_type= thd->lex->multi_lock_option;
- tl->updating= 1;
- wants= UPDATE_ACL;
- }
- else
+ if (!tl->updatable || check_key_in_view(thd, tl))
{
- DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias));
- // If we are using the binary log, we need TL_READ_NO_INSERT to get
- // correct order of statements. Otherwise, we use a TL_READ lock to
- // improve performance.
- tl->lock_type= using_update_log ? TL_READ_NO_INSERT : TL_READ;
- tl->updating= 0;
- wants= SELECT_ACL;
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), tl->alias, "UPDATE");
+ DBUG_RETURN(TRUE);
}
- if (tl->derived)
- derived_tables|= table->map;
- else
- {
- tl->next= 0;
- if (!using_lock_tables)
- tl->table->reginfo.lock_type= tl->lock_type;
- if (check_access(thd, wants, tl->db, &tl->grant.privilege, 0, 0) ||
- (grant_option && check_grant(thd, wants, tl, 0, 0, 0)))
- {
- tl->next= save;
- DBUG_RETURN(1);
- }
- tl->next= save;
- }
+ DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
+ /*
+ If table will be updated we should not downgrade lock for it and
+ leave it as is.
+ */
}
+ else
+ {
+ DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias));
+ /*
+ If we are using the binary log, we need TL_READ_NO_INSERT to get
+ correct order of statements. Otherwise, we use a TL_READ lock to
+ improve performance.
+ */
+ tl->lock_type= using_update_log ? TL_READ_NO_INSERT : TL_READ;
+ tl->updating= 0;
+ /* Update TABLE::lock_type accordingly. */
+ if (!tl->placeholder() && !tl->schema_table && !using_lock_tables)
+ tl->table->reginfo.lock_type= tl->lock_type;
+ }
+ }
+ for (tl= table_list; tl; tl= tl->next_local)
+ {
+ /* Check access privileges for table */
+ if (!tl->derived)
+ {
+ uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL;
+ if (check_access(thd, want_privilege,
+ tl->db, &tl->grant.privilege, 0, 0,
+ test(tl->schema_table)) ||
+ (grant_option && check_grant(thd, want_privilege, tl, 0, 1, 0)))
+ DBUG_RETURN(TRUE);
+ }
+ }
- if (thd->lex->derived_tables && (update_tables & derived_tables))
+ /* check single table update for view compound from several tables */
+ for (tl= table_list; tl; tl= tl->next_local)
+ {
+ if (tl->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
- // find derived table which cause error
- for (tl= update_list; tl; tl= tl->next)
+ TABLE_LIST *for_update= 0;
+ if (tl->check_single_table(&for_update, tables_for_update, tl))
{
- if (tl->derived && (update_tables & tl->table->map))
- {
- my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE),
- MYF(0), tl->alias, "UPDATE");
- DBUG_RETURN(-1);
- }
+ my_error(ER_VIEW_MULTIUPDATE, MYF(0),
+ tl->view_db.str, tl->view_name.str);
+ DBUG_RETURN(-1);
}
}
+ }
- /* Relock the tables with the correct modes */
- res= lock_tables(thd, table_list, table_count);
- if (using_lock_tables)
- break; // Don't have to do setup_field()
+ /* now lock and fill tables */
+ if (lock_tables(thd, table_list, table_count, &need_reopen))
+ {
+ if (!need_reopen)
+ DBUG_RETURN(TRUE);
/*
- We must setup fields again as the file may have been reopened
- during lock_tables
+ We have to reopen tables since some of them were altered or dropped
+ during lock_tables() or something was done with their triggers.
+ Let us do some cleanups to be able do setup_table() and setup_fields()
+ once again.
*/
- {
- List_iterator_fast<Item> field_it(*fields);
- Item_field *item;
+ List_iterator_fast<Item> it(*fields);
+ Item *item;
+ while ((item= it++))
+ item->cleanup();
+
+ /* We have to cleanup translation tables of views. */
+ for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global)
+ tbl->cleanup_items();
+
+ close_tables_for_reopen(thd, table_list);
+ goto reopen_tables;
+ }
- while ((item= (Item_field *) field_it++))
+ /*
+ Check that we are not using table that we are updating, but we should
+ skip all tables of UPDATE SELECT itself
+ */
+ lex->select_lex.exclude_from_table_unique_test= TRUE;
+ /* We only need SELECT privilege for columns in the values list */
+ for (tl= leaves; tl; tl= tl->next_leaf)
+ {
+ TABLE *table= tl->table;
+ TABLE_LIST *tlist;
+ if (!(tlist= tl->top_table())->derived)
+ {
+ tlist->grant.want_privilege=
+ (SELECT_ACL & ~tlist->grant.privilege);
+ table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
+ }
+ DBUG_PRINT("info", ("table: %s want_privilege: %u", tl->alias,
+ (uint) table->grant.want_privilege));
+ if (tl->lock_type != TL_READ &&
+ tl->lock_type != TL_READ_NO_INSERT)
+ {
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(tl, table_list)))
{
- item->field->query_id= 0;
- item->cleanup();
+ update_non_unique_table_error(table_list, "UPDATE", duplicate);
+ DBUG_RETURN(TRUE);
}
}
- if (setup_fields(thd, 0, update_list, *fields, 1, 0, 0))
- DBUG_RETURN(-1);
- /*
- If lock succeded and the table map didn't change since the above lock
- we can continue.
- */
- if (!res && update_tables == get_table_map(fields))
- break;
-
- /*
- There was some very unexpected changes in the table definition between
- open tables and lock tables. Close tables and try again.
- */
- close_thread_tables(thd);
}
-
- DBUG_RETURN(res);
+
+ if (thd->fill_derived_tables() &&
+ mysql_handle_derived(lex, &mysql_derived_filling))
+ DBUG_RETURN(TRUE);
+
+ DBUG_RETURN (FALSE);
}
+
/*
Setup multi-update handling and call SELECT to do the join
*/
-int mysql_multi_update(THD *thd,
- TABLE_LIST *table_list,
- List<Item> *fields,
- List<Item> *values,
- COND *conds,
- ulong options,
- enum enum_duplicates handle_duplicates, bool ignore,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
+bool mysql_multi_update(THD *thd,
+ TABLE_LIST *table_list,
+ List<Item> *fields,
+ List<Item> *values,
+ COND *conds,
+ ulonglong options,
+ enum enum_duplicates handle_duplicates, bool ignore,
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
{
- int res;
- TABLE_LIST *tl;
- TABLE_LIST *update_list= (TABLE_LIST*) thd->lex->select_lex.table_list.first;
- List<Item> total_list;
multi_update *result;
DBUG_ENTER("mysql_multi_update");
- if ((res= mysql_multi_update_lock(thd, table_list, fields, select_lex)))
- DBUG_RETURN(res);
+ if (mysql_multi_update_prepare(thd))
+ DBUG_RETURN(TRUE);
- /* Setup timestamp handling */
- for (tl= update_list; tl; tl= tl->next)
- {
- TABLE *table= tl->table;
- /* Only set timestamp column if this is not modified */
- if (table->timestamp_field &&
- table->timestamp_field->query_id == thd->query_id)
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+ if (!(result= new multi_update(table_list,
+ thd->lex->select_lex.leaf_tables,
+ fields, values,
+ handle_duplicates, ignore)))
+ DBUG_RETURN(TRUE);
- /* We only need SELECT privilege for columns in the values list */
- table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
- }
+ thd->no_trans_update= 0;
+ thd->abort_on_warning= test(thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES));
- if (!(result=new multi_update(thd, update_list, fields, values,
- handle_duplicates, ignore)))
- DBUG_RETURN(-1);
-
- res= mysql_select(thd, &select_lex->ref_pointer_array,
- select_lex->get_table_list(), select_lex->with_wild,
- total_list,
- conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
- (ORDER *)NULL,
- options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
- result, unit, select_lex);
+ List<Item> total_list;
+ (void) mysql_select(thd, &select_lex->ref_pointer_array,
+ table_list, select_lex->with_wild,
+ total_list,
+ conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
+ (ORDER *)NULL,
+ options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
+ OPTION_SETUP_TABLES_DONE,
+ result, unit, select_lex);
delete result;
- DBUG_RETURN(res);
+ thd->abort_on_warning= 0;
+ DBUG_RETURN(FALSE);
}
-multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
+multi_update::multi_update(TABLE_LIST *table_list,
+ TABLE_LIST *leaves_list,
List<Item> *field_list, List<Item> *value_list,
- enum enum_duplicates handle_duplicates_arg, bool ignore_arg)
- :all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0),
- updated(0), found(0), fields(field_list), values(value_list),
- table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg),
- do_update(1), trans_safe(0), transactional_tables(1), ignore(ignore_arg)
+ enum enum_duplicates handle_duplicates_arg,
+ bool ignore_arg)
+ :all_tables(table_list), leaves(leaves_list), update_tables(0),
+ tmp_tables(0), updated(0), found(0), fields(field_list),
+ values(value_list), table_count(0), copy_field(0),
+ handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0),
+ transactional_tables(1), ignore(ignore_arg)
{}
@@ -737,7 +897,7 @@ int multi_update::prepare(List<Item> &not_used_values,
if (!tables_to_update)
{
- my_error(ER_NO_TABLES_USED, MYF(0));
+ my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0));
DBUG_RETURN(1);
}
@@ -746,7 +906,7 @@ int multi_update::prepare(List<Item> &not_used_values,
reference tables
*/
- if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0))
+ if (setup_fields(thd, 0, *values, 1, 0, 0))
DBUG_RETURN(1);
/*
@@ -756,8 +916,9 @@ int multi_update::prepare(List<Item> &not_used_values,
*/
update.empty();
- for (table_ref= all_tables; table_ref; table_ref=table_ref->next)
+ for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
{
+ /* TODO: add support of view of join support */
TABLE *table=table_ref->table;
if (tables_to_update & table->map)
{
@@ -765,7 +926,7 @@ int multi_update::prepare(List<Item> &not_used_values,
sizeof(*tl));
if (!tl)
DBUG_RETURN(1);
- update.link_in_list((byte*) tl, (byte**) &tl->next);
+ update.link_in_list((byte*) tl, (byte**) &tl->next_local);
tl->shared= table_count++;
table->no_keyread=1;
table->used_keys.clear_all();
@@ -777,7 +938,7 @@ int multi_update::prepare(List<Item> &not_used_values,
table_count= update.elements;
update_tables= (TABLE_LIST*) update.first;
- tmp_tables = (TABLE **) thd->calloc(sizeof(TABLE *) * table_count);
+ tmp_tables = (TABLE**) thd->calloc(sizeof(TABLE *) * table_count);
tmp_table_param = (TMP_TABLE_PARAM*) thd->calloc(sizeof(TMP_TABLE_PARAM) *
table_count);
fields_for_table= (List_item **) thd->alloc(sizeof(List_item *) *
@@ -824,12 +985,12 @@ int multi_update::prepare(List<Item> &not_used_values,
which will cause an error when reading a row.
(This issue is mostly relevent for MyISAM tables)
*/
- for (table_ref= all_tables; table_ref; table_ref=table_ref->next)
+ for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
{
TABLE *table=table_ref->table;
- if (!(tables_to_update & table->map) &&
- find_real_table_in_list(update_tables, table_ref->db,
- table_ref->real_name))
+ if (!(tables_to_update & table->map) &&
+ find_table_in_local_list(update_tables, table_ref->db,
+ table_ref->table_name))
table->no_cache= 1; // Disable row cache
}
DBUG_RETURN(thd->is_fatal_error != 0);
@@ -855,11 +1016,10 @@ multi_update::initialize_tables(JOIN *join)
DBUG_RETURN(1);
main_table=join->join_tab->table;
trans_safe= transactional_tables= main_table->file->has_transactions();
- log_delayed= trans_safe || main_table->tmp_table != NO_TMP_TABLE;
table_to_update= 0;
/* Create a temporary table for keys to all tables, except main table */
- for (table_ref= update_tables; table_ref; table_ref=table_ref->next)
+ for (table_ref= update_tables; table_ref; table_ref= table_ref->next_local)
{
TABLE *table=table_ref->table;
uint cnt= table_ref->shared;
@@ -925,8 +1085,8 @@ multi_update::initialize_tables(JOIN *join)
NOTES
We can update the first table in join on the fly if we know that
- a row in this tabel will never be read twice. This is true under
- the folloing conditions:
+ a row in this table will never be read twice. This is true under
+ the following conditions:
- We are doing a table scan and the data is in a separate file (MyISAM) or
if we don't update a clustered key.
@@ -934,6 +1094,10 @@ multi_update::initialize_tables(JOIN *join)
- We are doing a range scan and we don't update the scan key or
the primary key for a clustered table handler.
+ When checking for above cases we also should take into account that
+ BEFORE UPDATE trigger potentially may change value of any field in row
+ being updated.
+
WARNING
This code is a bit dependent of how make_join_readinfo() works.
@@ -949,30 +1113,36 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
case JT_SYSTEM:
case JT_CONST:
case JT_EQ_REF:
- return 1; // At most one matching row
+ return TRUE; // At most one matching row
case JT_REF:
- return !check_if_key_used(table, join_tab->ref.key, *fields);
+ case JT_REF_OR_NULL:
+ return !check_if_key_used(table, join_tab->ref.key, *fields) &&
+ !(table->triggers &&
+ table->triggers->has_before_update_triggers());
case JT_ALL:
/* If range search on index */
if (join_tab->quick)
- return !check_if_key_used(table, join_tab->quick->index,
- *fields);
+ return !join_tab->quick->check_if_keys_used(fields) &&
+ !(table->triggers &&
+ table->triggers->has_before_update_triggers());
/* If scanning in clustered key */
if ((table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
- table->primary_key < MAX_KEY)
- return !check_if_key_used(table, table->primary_key, *fields);
- return 1;
+ table->s->primary_key < MAX_KEY)
+ return !check_if_key_used(table, table->s->primary_key, *fields) &&
+ !(table->triggers &&
+ table->triggers->has_before_update_triggers());
+ return TRUE;
default:
break; // Avoid compler warning
}
- return 0;
+ return FALSE;
}
multi_update::~multi_update()
{
TABLE_LIST *table;
- for (table= update_tables ; table; table= table->next)
+ for (table= update_tables ; table; table= table->next_local)
table->table->no_keyread= table->table->no_cache= 0;
if (tmp_tables)
@@ -999,7 +1169,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
TABLE_LIST *cur_table;
DBUG_ENTER("multi_update::send_data");
- for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
+ for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
{
TABLE *table= cur_table->table;
/*
@@ -1023,12 +1193,25 @@ bool multi_update::send_data(List<Item> &not_used_values)
{
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
- if (fill_record(*fields_for_table[offset], *values_for_table[offset], 0))
+ if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset],
+ *values_for_table[offset], 0,
+ table->triggers,
+ TRG_EVENT_UPDATE))
DBUG_RETURN(1);
+
found++;
if (compare_record(table, thd->query_id))
{
int error;
+ if ((error= cur_table->view_check_option(thd, ignore)) !=
+ VIEW_CHECK_OK)
+ {
+ found--;
+ if (error == VIEW_CHECK_SKIP)
+ continue;
+ else if (error == VIEW_CHECK_ERROR)
+ DBUG_RETURN(1);
+ }
if (!updated++)
{
/*
@@ -1042,20 +1225,29 @@ bool multi_update::send_data(List<Item> &not_used_values)
table->record[0])))
{
updated--;
- if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
+ if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
{
thd->fatal_error(); // Force error message
table->file->print_error(error,MYF(0));
DBUG_RETURN(1);
}
}
+ else
+ {
+ if (!table->file->has_transactions())
+ thd->no_trans_update= 1;
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER, TRUE))
+ DBUG_RETURN(1);
+ }
}
}
else
{
int error;
TABLE *tmp_table= tmp_tables[offset];
- fill_record(tmp_table->field+1, *values_for_table[offset], 1);
+ fill_record(thd, tmp_table->field+1, *values_for_table[offset], 1);
found++;
/* Store pointer to row */
memcpy((char*) tmp_table->field[0]->ptr,
@@ -1081,7 +1273,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
void multi_update::send_error(uint errcode,const char *err)
{
/* First send error what ever it is ... */
- ::send_error(thd,errcode,err);
+ my_error(errcode, MYF(0), err);
/* If nothing updated return */
if (!updated)
@@ -1116,7 +1308,7 @@ int multi_update::do_updates(bool from_send_error)
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)
+ for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
{
byte *ref_pos;
@@ -1169,6 +1361,11 @@ int multi_update::do_updates(bool from_send_error)
copy_field_ptr++)
(*copy_field_ptr->do_copy)(copy_field_ptr);
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
+ TRG_ACTION_BEFORE, TRUE))
+ goto err2;
+
if (compare_record(table, thd->query_id))
{
if ((local_error=table->file->update_row(table->record[1],
@@ -1178,17 +1375,18 @@ int multi_update::do_updates(bool from_send_error)
goto err;
}
updated++;
- if (table->tmp_table != NO_TMP_TABLE)
- log_delayed= 1;
+
+ if (table->triggers &&
+ table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER, TRUE))
+ goto err2;
}
}
if (updated != org_updated)
{
- if (table->tmp_table != NO_TMP_TABLE)
- log_delayed= 1; // Tmp tables forces delay log
if (table->file->has_transactions())
- log_delayed= transactional_tables= 1;
+ transactional_tables= 1;
else
trans_safe= 0; // Can't do safe rollback
}
@@ -1204,15 +1402,14 @@ err:
table->file->print_error(local_error,MYF(0));
}
+err2:
(void) table->file->ha_rnd_end();
(void) tmp_table->file->ha_rnd_end();
if (updated != org_updated)
{
- if (table->tmp_table != NO_TMP_TABLE)
- log_delayed= 1;
if (table->file->has_transactions())
- log_delayed= transactional_tables= 1;
+ transactional_tables= 1;
else
trans_safe= 0;
}
@@ -1224,7 +1421,7 @@ err:
bool multi_update::send_eof()
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
thd->proc_info="updating reference tables";
/* Does updates for the last n - 1 tables, returns 0 if ok */
@@ -1249,17 +1446,16 @@ bool multi_update::send_eof()
if (updated && (local_error <= 0 || !trans_safe))
{
- mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
if (local_error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed, FALSE);
+ transactional_tables, FALSE);
if (mysql_bin_log.write(&qinfo) && trans_safe)
local_error= 1; // Rollback update
}
- if (!log_delayed)
+ if (!transactional_tables)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
@@ -1274,15 +1470,15 @@ bool multi_update::send_eof()
/* Safety: If we haven't got an error before (should not happen) */
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update",
MYF(0));
- ::send_error(thd);
- return 1;
+ return TRUE;
}
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
(ulong) thd->cuted_fields);
- ::send_ok(thd,
- (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
+ thd->row_count_func=
+ (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
+ ::send_ok(thd, (ulong) thd->row_count_func,
thd->insert_id_used ? thd->insert_id() : 0L,buff);
- return 0;
+ return FALSE;
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
new file mode 100644
index 00000000000..4190e6ad7bc
--- /dev/null
+++ b/sql/sql_view.cc
@@ -0,0 +1,1449 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "mysql_priv.h"
+#include "sql_select.h"
+#include "parse_file.h"
+#include "sp.h"
+#include "sp_head.h"
+#include "sp_cache.h"
+
+#define MD5_BUFF_LENGTH 33
+
+const LEX_STRING view_type= { (char*) STRING_WITH_LEN("VIEW") };
+
+static int mysql_register_view(THD *thd, TABLE_LIST *view,
+ enum_view_create_mode mode);
+
+const char *updatable_views_with_limit_names[]= { "NO", "YES", NullS };
+TYPELIB updatable_views_with_limit_typelib=
+{
+ array_elements(updatable_views_with_limit_names)-1, "",
+ updatable_views_with_limit_names,
+ 0
+};
+
+
+/*
+ Make a unique name for an anonymous view column
+ SYNOPSIS
+ target reference to the item for which a new name has to be made
+ item_list list of items within which we should check uniqueness of
+ the created name
+ last_element the last element of the list above
+
+ NOTE
+ Unique names are generated by adding 'My_exp_' to the old name of the
+ column. In case the name that was created this way already exists, we
+ add a numeric postfix to its end (i.e. "1") and increase the number
+ until the name becomes unique. If the generated name is longer than
+ NAME_LEN, it is truncated.
+*/
+
+static void make_unique_view_field_name(Item *target,
+ List<Item> &item_list,
+ Item *last_element)
+{
+ char *name= (target->orig_name ?
+ target->orig_name :
+ target->name);
+ uint name_len, attempt;
+ char buff[NAME_LEN+1];
+ List_iterator_fast<Item> itc(item_list);
+
+ for (attempt= 0;; attempt++)
+ {
+ Item *check;
+ bool ok= TRUE;
+
+ if (attempt)
+ name_len= my_snprintf(buff, NAME_LEN, "My_exp_%d_%s", attempt, name);
+ else
+ name_len= my_snprintf(buff, NAME_LEN, "My_exp_%s", name);
+
+ do
+ {
+ check= itc++;
+ if (check != target &&
+ my_strcasecmp(system_charset_info, buff, check->name) == 0)
+ {
+ ok= FALSE;
+ break;
+ }
+ } while (check != last_element);
+ if (ok)
+ break;
+ itc.rewind();
+ }
+
+ target->orig_name= target->name;
+ target->set_name(buff, name_len, system_charset_info);
+}
+
+
+/*
+ Check if items with same names are present in list and possibly
+ generate unique names for them.
+
+ SYNOPSIS
+ item_list list of Items which should be checked for duplicates
+ gen_unique_view_name flag: generate unique name or return with error when
+ duplicate names are found.
+
+ DESCRIPTION
+ This function is used on view creation and preparation of derived tables.
+ It checks item_list for items with duplicate names. If it founds two
+ items with same name and conversion to unique names isn't allowed, or
+ names for both items are set by user - function fails.
+ Otherwise it generates unique name for one item with autogenerated name
+ using make_unique_view_field_name()
+
+ RETURN VALUE
+ FALSE no duplicate names found, or they are converted to unique ones
+ TRUE duplicate names are found and they can't be converted or conversion
+ isn't allowed
+*/
+
+bool check_duplicate_names(List<Item> &item_list, bool gen_unique_view_name)
+{
+ Item *item;
+ List_iterator_fast<Item> it(item_list);
+ List_iterator_fast<Item> itc(item_list);
+ DBUG_ENTER("check_duplicate_names");
+
+ while ((item= it++))
+ {
+ Item *check;
+ /* treat underlying fields like set by user names */
+ if (item->real_item()->type() == Item::FIELD_ITEM)
+ item->is_autogenerated_name= FALSE;
+ itc.rewind();
+ while ((check= itc++) && check != item)
+ {
+ if (my_strcasecmp(system_charset_info, item->name, check->name) == 0)
+ {
+ if (!gen_unique_view_name)
+ goto err;
+ if (item->is_autogenerated_name)
+ make_unique_view_field_name(item, item_list, item);
+ else if (check->is_autogenerated_name)
+ make_unique_view_field_name(check, item_list, item);
+ else
+ goto err;
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+
+err:
+ my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Creating/altering VIEW procedure
+
+ SYNOPSIS
+ mysql_create_view()
+ thd - thread handler
+ mode - VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
+
+ RETURN VALUE
+ FALSE OK
+ TRUE Error
+*/
+
+bool mysql_create_view(THD *thd,
+ enum_view_create_mode mode)
+{
+ LEX *lex= thd->lex;
+ bool link_to_local;
+ /* first table in list is target VIEW name => cut off it */
+ TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
+ TABLE_LIST *tables= lex->query_tables;
+ TABLE_LIST *tbl;
+ SELECT_LEX *select_lex= &lex->select_lex;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ SELECT_LEX *sl;
+#endif
+ SELECT_LEX_UNIT *unit= &lex->unit;
+ bool res= FALSE;
+ DBUG_ENTER("mysql_create_view");
+
+ if (lex->proc_list.first ||
+ lex->result)
+ {
+ my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), (lex->result ?
+ "INTO" :
+ "PROCEDURE"));
+ res= TRUE;
+ goto err;
+ }
+ if (lex->derived_tables ||
+ lex->variables_used || lex->param_list.elements)
+ {
+ int err= (lex->derived_tables ?
+ ER_VIEW_SELECT_DERIVED :
+ ER_VIEW_SELECT_VARIABLE);
+ my_message(err, ER(err), MYF(0));
+ res= TRUE;
+ goto err;
+ }
+
+ if (mode != VIEW_CREATE_NEW)
+ sp_cache_invalidate();
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /*
+ check definer of view:
+ - same as current user
+ - current user has SUPER_ACL
+ */
+ if (strcmp(lex->create_view_definer->user.str, thd->priv_user) != 0 ||
+ my_strcasecmp(system_charset_info,
+ lex->create_view_definer->host.str,
+ thd->priv_host) != 0)
+ {
+ if (!(thd->master_access & SUPER_ACL))
+ {
+ my_error(ER_VIEW_OTHER_USER, MYF(0), lex->create_view_definer->user.str,
+ lex->create_view_definer->host.str);
+ res= TRUE;
+ goto err;
+ }
+ else
+ {
+ if (!is_acl_user(lex->create_view_definer->host.str,
+ lex->create_view_definer->user.str))
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_NO_SUCH_USER,
+ ER(ER_NO_SUCH_USER),
+ lex->create_view_definer->user.str,
+ lex->create_view_definer->host.str);
+ }
+ }
+ }
+ /*
+ Privilege check for view creation:
+ - user has CREATE VIEW privilege on view table
+ - user has DROP privilege in case of ALTER VIEW or CREATE OR REPLACE
+ VIEW
+ - user has some (SELECT/UPDATE/INSERT/DELETE) privileges on columns of
+ underlying tables used on top of SELECT list (because it can be
+ (theoretically) updated, so it is enough to have UPDATE privilege on
+ them, for example)
+ - user has SELECT privilege on columns used in expressions of VIEW select
+ - for columns of underly tables used on top of SELECT list also will be
+ checked that we have not more privileges on correspondent column of view
+ table (i.e. user will not get some privileges by view creation)
+ */
+ if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege,
+ 0, 0, is_schema_db(view->db)) ||
+ grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) ||
+ (mode != VIEW_CREATE_NEW &&
+ (check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
+ 0, 0, is_schema_db(view->db)) ||
+ grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0))))
+ {
+ res= TRUE;
+ goto err;
+ }
+ for (sl= select_lex; sl; sl= sl->next_select())
+ {
+ for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local)
+ {
+ /*
+ Ensure that we have some privileges on this table, more strict check
+ will be done on column level after preparation,
+ */
+ if (check_some_access(thd, VIEW_ANY_ACL, tbl))
+ {
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ "ANY", thd->priv_user, thd->host_or_ip, tbl->table_name);
+ res= TRUE;
+ goto err;
+ }
+ /*
+ Mark this table as a table which will be checked after the prepare
+ phase
+ */
+ tbl->table_in_first_from_clause= 1;
+
+ /*
+ We need to check only SELECT_ACL for all normal fields, fields for
+ which we need "any" (SELECT/UPDATE/INSERT/DELETE) privilege will be
+ checked later
+ */
+ tbl->grant.want_privilege= SELECT_ACL;
+ /*
+ Make sure that all rights are loaded to the TABLE::grant field.
+
+ tbl->table_name will be correct name of table because VIEWs are
+ not opened yet.
+ */
+ fill_effective_table_privileges(thd, &tbl->grant, tbl->db,
+ tbl->table_name);
+ }
+ }
+
+ if (&lex->select_lex != lex->all_selects_list)
+ {
+ /* check tables of subqueries */
+ for (tbl= tables; tbl; tbl= tbl->next_global)
+ {
+ if (!tbl->table_in_first_from_clause)
+ {
+ if (check_access(thd, SELECT_ACL, tbl->db,
+ &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
+ grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
+ {
+ res= TRUE;
+ goto err;
+ }
+ }
+ }
+ }
+ /*
+ Mark fields for special privilege check ("any" privilege)
+ */
+ for (sl= select_lex; sl; sl= sl->next_select())
+ {
+ List_iterator_fast<Item> it(sl->item_list);
+ Item *item;
+ while ((item= it++))
+ {
+ Item_field *field;
+ if ((field= item->filed_for_view_update()))
+ field->any_privileges= 1;
+ }
+ }
+#endif
+
+ if (open_and_lock_tables(thd, tables))
+ {
+ res= TRUE;
+ goto err;
+ }
+
+ /*
+ check that tables are not temporary and this VIEW do not used in query
+ (it is possible with ALTERing VIEW).
+ open_and_lock_tables can change the value of tables,
+ e.g. it may happen if before the function call tables was equal to 0.
+ */
+ for (tbl= lex->query_tables; tbl; tbl= tbl->next_global)
+ {
+ /* is this table temporary and is not view? */
+ if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view &&
+ !tbl->schema_table)
+ {
+ my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias);
+ res= TRUE;
+ goto err;
+ }
+
+ /* is this table view and the same view which we creates now? */
+ if (tbl->view &&
+ strcmp(tbl->view_db.str, view->db) == 0 &&
+ strcmp(tbl->view_name.str, view->table_name) == 0)
+ {
+ my_error(ER_NO_SUCH_TABLE, MYF(0), tbl->view_db.str, tbl->view_name.str);
+ res= TRUE;
+ goto err;
+ }
+
+ /*
+ Copy the privileges of the underlying VIEWs which were filled by
+ fill_effective_table_privileges
+ (they were not copied at derived tables processing)
+ */
+ tbl->table->grant.privilege= tbl->grant.privilege;
+ }
+
+ /* prepare select to resolve all fields */
+ lex->view_prepare_mode= 1;
+ if (unit->prepare(thd, 0, 0, view->view_name.str))
+ {
+ /*
+ some errors from prepare are reported to user, if is not then
+ it will be checked after err: label
+ */
+ res= TRUE;
+ goto err;
+ }
+
+ /* view list (list of view fields names) */
+ if (lex->view_list.elements)
+ {
+ List_iterator_fast<Item> it(select_lex->item_list);
+ List_iterator_fast<LEX_STRING> nm(lex->view_list);
+ Item *item;
+ LEX_STRING *name;
+
+ if (lex->view_list.elements != select_lex->item_list.elements)
+ {
+ my_message(ER_VIEW_WRONG_LIST, ER(ER_VIEW_WRONG_LIST), MYF(0));
+ res= TRUE;
+ goto err;
+ }
+ while ((item= it++, name= nm++))
+ {
+ item->set_name(name->str, name->length, system_charset_info);
+ item->is_autogenerated_name= FALSE;
+ }
+ }
+
+ if (check_duplicate_names(select_lex->item_list, 1))
+ {
+ res= TRUE;
+ goto err;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /*
+ Compare/check grants on view with grants of underlying tables
+ */
+ for (sl= select_lex; sl; sl= sl->next_select())
+ {
+ char *db= view->db ? view->db : thd->db;
+ List_iterator_fast<Item> it(sl->item_list);
+ Item *item;
+ fill_effective_table_privileges(thd, &view->grant, db,
+ view->table_name);
+ while ((item= it++))
+ {
+ Item_field *fld;
+ uint priv= (get_column_grant(thd, &view->grant, db,
+ view->table_name, item->name) &
+ VIEW_ANY_ACL);
+ if ((fld= item->filed_for_view_update()))
+ {
+ /*
+ Do we have more privileges on view field then underlying table field?
+ */
+ if (!fld->field->table->s->tmp_table && (~fld->have_privileges & priv))
+ {
+ /* VIEW column has more privileges */
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ "create view", thd->priv_user, thd->host_or_ip, item->name,
+ view->table_name);
+ res= TRUE;
+ goto err;
+ }
+ }
+ }
+ }
+#endif
+
+ if (wait_if_global_read_lock(thd, 0, 0))
+ {
+ res= TRUE;
+ goto err;
+ }
+ VOID(pthread_mutex_lock(&LOCK_open));
+ res= mysql_register_view(thd, view, mode);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ if (view->revision != 1)
+ query_cache_invalidate3(thd, view, 0);
+ start_waiting_global_read_lock(thd);
+ if (res)
+ goto err;
+
+ send_ok(thd);
+ lex->link_first_table_back(view, link_to_local);
+ DBUG_RETURN(0);
+
+err:
+ thd->proc_info= "end";
+ lex->link_first_table_back(view, link_to_local);
+ unit->cleanup();
+ DBUG_RETURN(res || thd->net.report_error);
+}
+
+
+/* index of revision number in following table */
+static const int revision_number_position= 8;
+/* index of source */
+static const int source_number_position= 11;
+/* index of last required parameter for making view */
+static const int required_view_parameters= 10;
+/* number of backups */
+static const int num_view_backups= 3;
+
+/*
+ table of VIEW .frm field descriptors
+
+ Note that one should NOT change the order for this, as it's used by
+ parse()
+*/
+static File_option view_parameters[]=
+{{{(char*) STRING_WITH_LEN("query")},
+ offsetof(TABLE_LIST, query),
+ FILE_OPTIONS_STRING},
+ {{(char*) STRING_WITH_LEN("md5")},
+ offsetof(TABLE_LIST, md5),
+ FILE_OPTIONS_STRING},
+ {{(char*) STRING_WITH_LEN("updatable")},
+ offsetof(TABLE_LIST, updatable_view),
+ FILE_OPTIONS_ULONGLONG},
+ {{(char*) STRING_WITH_LEN("algorithm")},
+ offsetof(TABLE_LIST, algorithm),
+ FILE_OPTIONS_ULONGLONG},
+ {{(char*) STRING_WITH_LEN("definer_user")},
+ offsetof(TABLE_LIST, definer.user),
+ FILE_OPTIONS_STRING},
+ {{(char*) STRING_WITH_LEN("definer_host")},
+ offsetof(TABLE_LIST, definer.host),
+ FILE_OPTIONS_STRING},
+ {{(char*) STRING_WITH_LEN("suid")},
+ offsetof(TABLE_LIST, view_suid),
+ FILE_OPTIONS_ULONGLONG},
+ {{(char*) STRING_WITH_LEN("with_check_option")},
+ offsetof(TABLE_LIST, with_check),
+ FILE_OPTIONS_ULONGLONG},
+ {{(char*) STRING_WITH_LEN("revision")},
+ offsetof(TABLE_LIST, revision),
+ FILE_OPTIONS_REV},
+ {{(char*) STRING_WITH_LEN("timestamp")},
+ offsetof(TABLE_LIST, timestamp),
+ FILE_OPTIONS_TIMESTAMP},
+ {{(char*)STRING_WITH_LEN("create-version")},
+ offsetof(TABLE_LIST, file_version),
+ FILE_OPTIONS_ULONGLONG},
+ {{(char*) STRING_WITH_LEN("source")},
+ offsetof(TABLE_LIST, source),
+ FILE_OPTIONS_ESTRING},
+ {{NullS, 0}, 0,
+ FILE_OPTIONS_STRING}
+};
+
+static LEX_STRING view_file_type[]= {{(char*) STRING_WITH_LEN("VIEW") }};
+
+
+/*
+ Register VIEW (write .frm & process .frm's history backups)
+
+ SYNOPSIS
+ mysql_register_view()
+ thd - thread handler
+ view - view description
+ mode - VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
+
+ RETURN
+ 0 OK
+ -1 Error
+ 1 Error and error message given
+*/
+
+static int mysql_register_view(THD *thd, TABLE_LIST *view,
+ enum_view_create_mode mode)
+{
+ LEX *lex= thd->lex;
+ char buff[4096];
+ String str(buff,(uint32) sizeof(buff), system_charset_info);
+ char md5[MD5_BUFF_LENGTH];
+ bool can_be_merged;
+ char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
+ LEX_STRING dir, file;
+ DBUG_ENTER("mysql_register_view");
+
+ /* print query */
+ str.length(0);
+ {
+ ulong sql_mode= thd->variables.sql_mode & MODE_ANSI_QUOTES;
+ thd->variables.sql_mode&= ~MODE_ANSI_QUOTES;
+ lex->unit.print(&str);
+ thd->variables.sql_mode|= sql_mode;
+ }
+ str.append('\0');
+ DBUG_PRINT("info", ("View: %s", str.ptr()));
+
+ /* print file name */
+ (void) my_snprintf(dir_buff, FN_REFLEN, "%s/%s/",
+ mysql_data_home, view->db);
+ unpack_filename(dir_buff, dir_buff);
+ dir.str= dir_buff;
+ dir.length= strlen(dir_buff);
+
+ file.str= file_buff;
+ file.length= (strxnmov(file_buff, FN_REFLEN, view->table_name, reg_ext,
+ NullS) - file_buff);
+ /* init timestamp */
+ if (!view->timestamp.str)
+ view->timestamp.str= view->timestamp_buffer;
+
+ /* check old .frm */
+ {
+ char path_buff[FN_REFLEN];
+ LEX_STRING path;
+ File_parser *parser;
+
+ path.str= path_buff;
+ fn_format(path_buff, file.str, dir.str, 0, MY_UNPACK_FILENAME);
+ path.length= strlen(path_buff);
+
+ if (!access(path.str, F_OK))
+ {
+ if (mode == VIEW_CREATE_NEW)
+ {
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias);
+ DBUG_RETURN(-1);
+ }
+
+ if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0)))
+ DBUG_RETURN(1);
+
+ if (!parser->ok() || !is_equal(&view_type, parser->type()))
+ {
+ my_error(ER_WRONG_OBJECT, MYF(0),
+ (view->db ? view->db : thd->db), view->table_name, "VIEW");
+ DBUG_RETURN(-1);
+ }
+
+ /*
+ read revision number
+
+ TODO: read dependence list, too, to process cascade/restrict
+ TODO: special cascade/restrict procedure for alter?
+ */
+ if (parser->parse((gptr)view, thd->mem_root,
+ view_parameters + revision_number_position, 1))
+ {
+ DBUG_RETURN(thd->net.report_error? -1 : 0);
+ }
+ }
+ else
+ {
+ if (mode == VIEW_ALTER)
+ {
+ my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias);
+ DBUG_RETURN(-1);
+ }
+ }
+ }
+ /* fill structure */
+ view->query.str= (char*)str.ptr();
+ view->query.length= str.length()-1; // we do not need last \0
+ view->source.str= thd->lex->create_view_select_start;
+ view->source.length= (thd->query_length -
+ (thd->lex->create_view_select_start - thd->query));
+ view->file_version= 1;
+ view->calc_md5(md5);
+ view->md5.str= md5;
+ view->md5.length= 32;
+ can_be_merged= lex->can_be_merged();
+ if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE &&
+ !lex->can_be_merged())
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE,
+ ER(ER_WARN_VIEW_MERGE));
+ lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
+ }
+ view->algorithm= lex->create_view_algorithm;
+ view->definer.user= lex->create_view_definer->user;
+ view->definer.host= lex->create_view_definer->host;
+ view->view_suid= lex->create_view_suid;
+ view->with_check= lex->create_view_check;
+ if ((view->updatable_view= (can_be_merged &&
+ view->algorithm != VIEW_ALGORITHM_TMPTABLE)))
+ {
+ /* TODO: change here when we will support UNIONs */
+ for (TABLE_LIST *tbl= (TABLE_LIST *)lex->select_lex.table_list.first;
+ tbl;
+ tbl= tbl->next_local)
+ {
+ if ((tbl->view && !tbl->updatable_view) || tbl->schema_table)
+ {
+ view->updatable_view= 0;
+ break;
+ }
+ for (TABLE_LIST *up= tbl; up; up= up->embedding)
+ {
+ if (up->outer_join)
+ {
+ view->updatable_view= 0;
+ goto loop_out;
+ }
+ }
+ }
+ }
+loop_out:
+ /*
+ Check that table of main select do not used in subqueries.
+
+ This test can catch only very simple cases of such non-updateable views,
+ all other will be detected before updating commands execution.
+ (it is more optimisation then real check)
+
+ NOTE: this skip cases of using table via VIEWs, joined VIEWs, VIEWs with
+ UNION
+ */
+ if (view->updatable_view &&
+ !lex->select_lex.next_select() &&
+ !((TABLE_LIST*)lex->select_lex.table_list.first)->next_local &&
+ find_table_in_global_list(lex->query_tables->next_global,
+ lex->query_tables->db,
+ lex->query_tables->table_name))
+ {
+ view->updatable_view= 0;
+ }
+
+ if (view->with_check != VIEW_CHECK_NONE &&
+ !view->updatable_view)
+ {
+ my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db, view->table_name);
+ DBUG_RETURN(-1);
+ }
+
+ if (sql_create_definition_file(&dir, &file, view_file_type,
+ (gptr)view, view_parameters, num_view_backups))
+ {
+ DBUG_RETURN(thd->net.report_error? -1 : 1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ read VIEW .frm and create structures
+
+ SYNOPSIS
+ mysql_make_view()
+ parser - parser object;
+ table - TABLE_LIST structure for filling
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+my_bool
+mysql_make_view(File_parser *parser, TABLE_LIST *table)
+{
+ DBUG_ENTER("mysql_make_view");
+ DBUG_PRINT("info", ("table=%p (%s)", table, table->table_name));
+
+ if (table->view)
+ {
+ DBUG_PRINT("info",
+ ("VIEW %s.%s is already processed on previous PS/SP execution",
+ table->view_db.str, table->view_name.str));
+ DBUG_RETURN(0);
+ }
+
+ SELECT_LEX *end;
+ THD *thd= current_thd;
+ LEX *old_lex= thd->lex, *lex;
+ SELECT_LEX *view_select;
+ int res= 0;
+
+ /*
+ For now we assume that tables will not be changed during PS life (it
+ will be TRUE as far as we make new table cache).
+ */
+ Query_arena *arena= thd->stmt_arena, backup;
+ if (arena->is_conventional())
+ arena= 0;
+ else
+ thd->set_n_backup_active_arena(arena, &backup);
+
+ /* init timestamp */
+ if (!table->timestamp.str)
+ table->timestamp.str= table->timestamp_buffer;
+ /* prepare default values for old format */
+ table->view_suid= 1;
+ table->definer.user.str= table->definer.host.str= 0;
+ table->definer.user.length= table->definer.host.length= 0;
+
+ /*
+ TODO: when VIEWs will be stored in cache, table mem_root should
+ be used here
+ */
+ if (parser->parse((gptr)table, thd->mem_root, view_parameters,
+ required_view_parameters))
+ goto err;
+
+ /*
+ check old format view .frm
+ */
+ if (!table->definer.user.str)
+ {
+ DBUG_ASSERT(!table->definer.host.str &&
+ !table->definer.user.length &&
+ !table->definer.host.length);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER),
+ table->db, table->table_name);
+ if (default_view_definer(thd, &table->definer))
+ goto err;
+ }
+
+ /*
+ Save VIEW parameters, which will be wiped out by derived table
+ processing
+ */
+ table->view_db.str= table->db;
+ table->view_db.length= table->db_length;
+ table->view_name.str= table->table_name;
+ table->view_name.length= table->table_name_length;
+
+ /*TODO: md5 test here and warning if it is differ */
+
+ /*
+ TODO: TABLE mem root should be used here when VIEW will be stored in
+ TABLE cache
+
+ now Lex placed in statement memory
+ */
+ table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
+ lex_start(thd, (uchar*)table->query.str, table->query.length);
+ view_select= &lex->select_lex;
+ view_select->select_number= ++thd->select_number;
+ {
+ ulong save_mode= thd->variables.sql_mode;
+ /* switch off modes which can prevent normal parsing of VIEW
+ - MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing
+ + MODE_PIPES_AS_CONCAT affect expression parsing
+ + MODE_ANSI_QUOTES affect expression parsing
+ + MODE_IGNORE_SPACE affect expression parsing
+ - MODE_NOT_USED not used :)
+ * MODE_ONLY_FULL_GROUP_BY affect execution
+ * MODE_NO_UNSIGNED_SUBTRACTION affect execution
+ - MODE_NO_DIR_IN_CREATE affect table creation only
+ - MODE_POSTGRESQL compounded from other modes
+ - MODE_ORACLE compounded from other modes
+ - MODE_MSSQL compounded from other modes
+ - MODE_DB2 compounded from other modes
+ - MODE_MAXDB affect only CREATE TABLE parsing
+ - MODE_NO_KEY_OPTIONS affect only SHOW
+ - MODE_NO_TABLE_OPTIONS affect only SHOW
+ - MODE_NO_FIELD_OPTIONS affect only SHOW
+ - MODE_MYSQL323 affect only SHOW
+ - MODE_MYSQL40 affect only SHOW
+ - MODE_ANSI compounded from other modes
+ (+ transaction mode)
+ ? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs
+ + MODE_NO_BACKSLASH_ESCAPES affect expression parsing
+ */
+ thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
+ CHARSET_INFO *save_cs= thd->variables.character_set_client;
+ thd->variables.character_set_client= system_charset_info;
+ res= yyparse((void *)thd);
+ thd->variables.character_set_client= save_cs;
+ thd->variables.sql_mode= save_mode;
+ }
+ if (!res && !thd->is_fatal_error)
+ {
+ TABLE_LIST *top_view= table->top_table();
+ TABLE_LIST *view_tables= lex->query_tables;
+ TABLE_LIST *view_tables_tail= 0;
+ TABLE_LIST *tbl;
+
+ /*
+ Check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show
+ underlying tables.
+ Skip this step if we are opening view for prelocking only.
+ */
+ if (!table->prelocking_placeholder &&
+ (old_lex->sql_command == SQLCOM_SELECT && old_lex->describe))
+ {
+ if (check_table_access(thd, SELECT_ACL, view_tables, 1) &&
+ check_table_access(thd, SHOW_VIEW_ACL, table, 1))
+ {
+ my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0));
+ goto err;
+ }
+ }
+ else if (!table->prelocking_placeholder &&
+ old_lex->sql_command == SQLCOM_SHOW_CREATE)
+ {
+ if (check_table_access(thd, SHOW_VIEW_ACL, table, 0))
+ goto err;
+ }
+
+ /*
+ mark to avoid temporary table using and put view reference and find
+ last view table
+ */
+ for (tbl= view_tables;
+ tbl;
+ tbl= (view_tables_tail= tbl)->next_global)
+ {
+ tbl->skip_temporary= 1;
+ tbl->belong_to_view= top_view;
+ }
+
+ /*
+ Put tables of VIEW after VIEW TABLE_LIST
+
+ NOTE: It is important for UPDATE/INSERT/DELETE checks to have this
+ tables just after VIEW instead of tail of list, to be able check that
+ table is unique. Also we store old next table for the same purpose.
+ */
+ if (view_tables)
+ {
+ if (table->next_global)
+ {
+ view_tables_tail->next_global= table->next_global;
+ table->next_global->prev_global= &view_tables_tail->next_global;
+ }
+ else
+ {
+ old_lex->query_tables_last= &view_tables_tail->next_global;
+ }
+ view_tables->prev_global= &table->next_global;
+ table->next_global= view_tables;
+ }
+
+ /*
+ Let us set proper lock type for tables of the view's main select
+ since we may want to perform update or insert on view. This won't
+ work for view containing union. But this is ok since we don't
+ allow insert and update on such views anyway.
+ */
+ if (!lex->select_lex.next_select())
+ for (tbl= lex->select_lex.get_table_list(); tbl; tbl= tbl->next_local)
+ tbl->lock_type= table->lock_type;
+
+ /*
+ If we are opening this view as part of implicit LOCK TABLES, then
+ this view serves as simple placeholder and we should not continue
+ further processing.
+ */
+ if (table->prelocking_placeholder)
+ goto ok2;
+
+ old_lex->derived_tables|= DERIVED_VIEW;
+
+ /* move SQL_NO_CACHE & Co to whole query */
+ old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
+ lex->safe_to_cache_query);
+ /* move SQL_CACHE to whole query */
+ if (view_select->options & OPTION_TO_QUERY_CACHE)
+ old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+
+ /*
+ check MERGE algorithm ability
+ - algorithm is not explicit TEMPORARY TABLE
+ - VIEW SELECT allow merging
+ - VIEW used in subquery or command support MERGE algorithm
+ */
+ if (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
+ lex->can_be_merged() &&
+ (table->select_lex->master_unit() != &old_lex->unit ||
+ old_lex->can_use_merged()) &&
+ !old_lex->can_not_use_merged())
+ {
+ List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list);
+ /* lex should contain at least one table */
+ DBUG_ASSERT(view_tables != 0);
+
+ table->effective_algorithm= VIEW_ALGORITHM_MERGE;
+ DBUG_PRINT("info", ("algorithm: MERGE"));
+ table->updatable= (table->updatable_view != 0);
+ table->effective_with_check=
+ old_lex->get_effective_with_check(table);
+
+ /* prepare view context */
+ lex->select_lex.context.resolve_in_table_list_only(table->ancestor=
+ view_tables);
+ lex->select_lex.context.outer_context= 0;
+ lex->select_lex.context.select_lex= table->select_lex;
+ lex->select_lex.select_n_having_items+=
+ table->select_lex->select_n_having_items;
+
+ /* do not check privileges & hide errors for view underlyings */
+ for (SELECT_LEX *sl= lex->all_selects_list;
+ sl;
+ sl= sl->next_select_in_list())
+ {
+ sl->context.check_privileges= FALSE;
+ sl->context.error_processor= &view_error_processor;
+ sl->context.error_processor_data= (void *)table;
+ }
+ /*
+ Tables of the main select of the view should be marked as belonging
+ to the same select as original view (again we can use LEX::select_lex
+ for this purprose because we don't support MERGE algorithm for views
+ with unions).
+ */
+ for (tbl= lex->select_lex.get_table_list(); tbl; tbl= tbl->next_local)
+ tbl->select_lex= table->select_lex;
+
+ {
+ if (view_tables->next_local)
+ {
+ table->multitable_view= TRUE;
+ if (table->belong_to_view)
+ table->belong_to_view->multitable_view= TRUE;
+ }
+ /* make nested join structure for view tables */
+ NESTED_JOIN *nested_join;
+ if (!(nested_join= table->nested_join=
+ (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN))))
+ goto err;
+ nested_join->join_list= view_select->top_join_list;
+
+ /* re-nest tables of VIEW */
+ ti.rewind();
+ while ((tbl= ti++))
+ {
+ tbl->join_list= &nested_join->join_list;
+ tbl->embedding= table;
+ }
+ }
+
+ /* Store WHERE clause for post-processing in setup_ancestor */
+ table->where= view_select->where;
+ /*
+ Add subqueries units to SELECT into which we merging current view.
+ unit(->next)* chain starts with subqueries that are used by this
+ view and continues with subqueries that are used by other views.
+ We must not add any subquery twice (otherwise we'll form a loop),
+ to do this we remember in end_unit the first subquery that has
+ been already added.
+
+ NOTE: we do not support UNION here, so we take only one select
+ */
+ SELECT_LEX_NODE *end_unit= table->select_lex->slave;
+ SELECT_LEX_UNIT *next_unit;
+ for (SELECT_LEX_UNIT *unit= lex->select_lex.first_inner_unit();
+ unit;
+ unit= next_unit)
+ {
+ if (unit == end_unit)
+ break;
+ SELECT_LEX_NODE *save_slave= unit->slave;
+ next_unit= unit->next_unit();
+ unit->include_down(table->select_lex);
+ unit->slave= save_slave; // fix include_down initialisation
+ }
+
+ /*
+ This SELECT_LEX will be linked in global SELECT_LEX list
+ to make it processed by mysql_handle_derived(),
+ but it will not be included to SELECT_LEX tree, because it
+ will not be executed
+ */
+ goto ok;
+ }
+
+ table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE;
+ DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
+ view_select->linkage= DERIVED_TABLE_TYPE;
+ table->updatable= 0;
+ table->effective_with_check= VIEW_CHECK_NONE;
+ old_lex->subqueries= TRUE;
+
+ /* SELECT tree link */
+ lex->unit.include_down(table->select_lex);
+ lex->unit.slave= view_select; // fix include_down initialisation
+
+ table->derived= &lex->unit;
+ }
+ else
+ goto err;
+
+ok:
+ /* global SELECT list linking */
+ end= view_select; // primary SELECT_LEX is always last
+ end->link_next= old_lex->all_selects_list;
+ old_lex->all_selects_list->link_prev= &end->link_next;
+ old_lex->all_selects_list= lex->all_selects_list;
+ lex->all_selects_list->link_prev=
+ (st_select_lex_node**)&old_lex->all_selects_list;
+
+ok2:
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ if (!old_lex->time_zone_tables_used && thd->lex->time_zone_tables_used)
+ old_lex->time_zone_tables_used= thd->lex->time_zone_tables_used;
+ thd->lex= old_lex;
+ DBUG_RETURN(0);
+
+err:
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ delete table->view;
+ table->view= 0; // now it is not VIEW placeholder
+ thd->lex= old_lex;
+ DBUG_RETURN(1);
+}
+
+
+/*
+ drop view
+
+ SYNOPSIS
+ mysql_drop_view()
+ thd - thread handler
+ views - views to delete
+ drop_mode - cascade/check
+
+ RETURN VALUE
+ FALSE OK
+ TRUE Error
+*/
+
+bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
+{
+ DBUG_ENTER("mysql_drop_view");
+ char path[FN_REFLEN];
+ TABLE_LIST *view;
+ bool type= 0;
+
+ for (view= views; view; view= view->next_local)
+ {
+ strxnmov(path, FN_REFLEN, mysql_data_home, "/", view->db, "/",
+ view->table_name, reg_ext, NullS);
+ (void) unpack_filename(path, path);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (access(path, F_OK) || (type= (mysql_frm_type(path) != FRMTYPE_VIEW)))
+ {
+ char name[FN_REFLEN];
+ my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name);
+ if (thd->lex->drop_if_exists)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
+ name);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ continue;
+ }
+ if (type)
+ my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW");
+ else
+ my_error(ER_BAD_TABLE_ERROR, MYF(0), name);
+ goto err;
+ }
+ if (my_delete(path, MYF(MY_WME)))
+ goto err;
+ query_cache_invalidate3(thd, view, 0);
+ sp_cache_invalidate();
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ }
+ send_ok(thd);
+ DBUG_RETURN(FALSE);
+
+err:
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ DBUG_RETURN(TRUE);
+
+}
+
+
+/*
+ Check type of .frm if we are not going to parse it
+
+ SYNOPSIS
+ mysql_frm_type()
+ path path to file
+
+ RETURN
+ FRMTYPE_ERROR error
+ FRMTYPE_TABLE table
+ FRMTYPE_VIEW view
+*/
+
+frm_type_enum mysql_frm_type(char *path)
+{
+ File file;
+ char header[10]; //"TYPE=VIEW\n" it is 10 characters
+ int length;
+ DBUG_ENTER("mysql_frm_type");
+
+ if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)
+ {
+ DBUG_RETURN(FRMTYPE_ERROR);
+ }
+ length= my_read(file, (byte*) header, sizeof(header), MYF(MY_WME));
+ my_close(file, MYF(MY_WME));
+ if (length == (int) MY_FILE_ERROR)
+ DBUG_RETURN(FRMTYPE_ERROR);
+ if (length < (int) sizeof(header) ||
+ !strncmp(header, "TYPE=VIEW\n", sizeof(header)))
+ DBUG_RETURN(FRMTYPE_VIEW);
+ DBUG_RETURN(FRMTYPE_TABLE); // Is probably a .frm table
+}
+
+
+/*
+ check of key (primary or unique) presence in updatable view
+
+ SYNOPSIS
+ check_key_in_view()
+ thd thread handler
+ view view for check with opened table
+
+ DESCRIPTION
+ If it is VIEW and query have LIMIT clause then check that undertlying
+ table of viey contain one of following:
+ 1) primary key of underlying table
+ 2) unique key underlying table with fields for which NULL value is
+ impossible
+ 3) all fields of underlying table
+
+ RETURN
+ FALSE OK
+ TRUE view do not contain key or all fields
+*/
+
+bool check_key_in_view(THD *thd, TABLE_LIST *view)
+{
+ TABLE *table;
+ Field_translator *trans, *end_of_trans;
+ KEY *key_info, *key_info_end;
+ uint i;
+ DBUG_ENTER("check_key_in_view");
+
+ /*
+ we do not support updatable UNIONs in VIEW, so we can check just limit of
+ LEX::select_lex
+ */
+ if ((!view->view && !view->belong_to_view) ||
+ thd->lex->sql_command == SQLCOM_INSERT ||
+ thd->lex->select_lex.select_limit == 0)
+ DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
+ table= view->table;
+ view= view->top_table();
+ trans= view->field_translation;
+ key_info_end= (key_info= table->key_info)+ table->s->keys;
+
+ end_of_trans= view->field_translation_end;
+ DBUG_ASSERT(table != 0 && view->field_translation != 0);
+
+ {
+ /*
+ We should be sure that all fields are ready to get keys from them, but
+ this operation should not have influence on Field::query_id, to avoid
+ marking as used fields which are not used
+ */
+ bool save_set_query_id= thd->set_query_id;
+ thd->set_query_id= 0;
+ for (Field_translator *fld= trans; fld < end_of_trans; fld++)
+ {
+ if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item))
+ {
+ thd->set_query_id= save_set_query_id;
+ return TRUE;
+ }
+ }
+ thd->set_query_id= save_set_query_id;
+ }
+ /* Loop over all keys to see if a unique-not-null key is used */
+ for (;key_info != key_info_end ; key_info++)
+ {
+ if ((key_info->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
+ {
+ KEY_PART_INFO *key_part= key_info->key_part;
+ KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
+
+ /* check that all key parts are used */
+ for (;;)
+ {
+ Field_translator *k;
+ for (k= trans; k < end_of_trans; k++)
+ {
+ Item_field *field;
+ if ((field= k->item->filed_for_view_update()) &&
+ field->field == key_part->field)
+ break;
+ }
+ if (k == end_of_trans)
+ break; // Key is not possible
+ if (++key_part == key_part_end)
+ DBUG_RETURN(FALSE); // Found usable key
+ }
+ }
+ }
+
+ DBUG_PRINT("info", ("checking if all fields of table are used"));
+ /* check all fields presence */
+ {
+ Field **field_ptr;
+ Field_translator *fld;
+ for (field_ptr= table->field; *field_ptr; field_ptr++)
+ {
+ for (fld= trans; fld < end_of_trans; fld++)
+ {
+ Item_field *field;
+ if ((field= fld->item->filed_for_view_update()) &&
+ field->field == *field_ptr)
+ break;
+ }
+ if (fld == end_of_trans) // If field didn't exists
+ {
+ /*
+ Keys or all fields of underlying tables are not found => we have
+ to check variable updatable_views_with_limit to decide should we
+ issue an error or just a warning
+ */
+ if (thd->variables.updatable_views_with_limit)
+ {
+ /* update allowed, but issue warning */
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY));
+ DBUG_RETURN(FALSE);
+ }
+ /* prohibit update */
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ insert fields from VIEW (MERGE algorithm) into given list
+
+ SYNOPSIS
+ insert_view_fields()
+ thd thread handler
+ list list for insertion
+ view view for processing
+
+ RETURN
+ FALSE OK
+ TRUE error (is not sent to cliet)
+*/
+
+bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view)
+{
+ Field_translator *trans_end;
+ Field_translator *trans;
+ DBUG_ENTER("insert_view_fields");
+
+ if (!(trans= view->field_translation))
+ DBUG_RETURN(FALSE);
+ trans_end= view->field_translation_end;
+
+ for (Field_translator *entry= trans; entry < trans_end; entry++)
+ {
+ Item_field *fld;
+ if ((fld= entry->item->filed_for_view_update()))
+ list->push_back(fld);
+ else
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT");
+ DBUG_RETURN(TRUE);
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+/*
+ checking view md5 check suum
+
+ SINOPSYS
+ view_checksum()
+ thd threar handler
+ view view for check
+
+ RETUIRN
+ HA_ADMIN_OK OK
+ HA_ADMIN_NOT_IMPLEMENTED it is not VIEW
+ HA_ADMIN_WRONG_CHECKSUM check sum is wrong
+*/
+
+int view_checksum(THD *thd, TABLE_LIST *view)
+{
+ char md5[MD5_BUFF_LENGTH];
+ if (!view->view || view->md5.length != 32)
+ return HA_ADMIN_NOT_IMPLEMENTED;
+ view->calc_md5(md5);
+ return (strncmp(md5, view->md5.str, 32) ?
+ HA_ADMIN_WRONG_CHECKSUM :
+ HA_ADMIN_OK);
+}
+
+/*
+ rename view
+
+ Synopsis:
+ renames a view
+
+ Parameters:
+ thd thread handler
+ new_name new name of view
+ view view
+
+ Return values:
+ FALSE Ok
+ TRUE Error
+*/
+bool
+mysql_rename_view(THD *thd,
+ const char *new_name,
+ TABLE_LIST *view)
+{
+ LEX_STRING pathstr, file;
+ File_parser *parser;
+ char view_path[FN_REFLEN];
+
+ DBUG_ENTER("mysql_rename_view");
+
+ strxnmov(view_path, FN_REFLEN, mysql_data_home, "/", view->db, "/",
+ view->table_name, reg_ext, NullS);
+ (void) unpack_filename(view_path, view_path);
+
+ pathstr.str= (char *)view_path;
+ pathstr.length= strlen(view_path);
+
+ if ((parser= sql_parse_prepare(&pathstr, thd->mem_root, 1)) &&
+ is_equal(&view_type, parser->type())) {
+ char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
+
+ /* get view definition and source */
+ if (mysql_make_view(parser, view) ||
+ parser->parse((gptr)view, thd->mem_root,
+ view_parameters + source_number_position, 1))
+ DBUG_RETURN(1);
+
+ /* rename view and it's backups */
+ if (rename_in_schema_file(view->db, view->table_name, new_name,
+ view->revision - 1, num_view_backups))
+ DBUG_RETURN(1);
+
+ strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", view->db, "/", NullS);
+ (void) unpack_filename(dir_buff, dir_buff);
+
+ pathstr.str= (char*)dir_buff;
+ pathstr.length= strlen(dir_buff);
+
+ file.str= file_buff;
+ file.length= (strxnmov(file_buff, FN_REFLEN, new_name, reg_ext, NullS)
+ - file_buff);
+
+ if (sql_create_definition_file(&pathstr, &file, view_file_type,
+ (gptr)view, view_parameters, num_view_backups)) {
+ /* restore renamed view in case of error */
+ rename_in_schema_file(view->db, new_name, view->table_name,
+ view->revision - 1, num_view_backups);
+ DBUG_RETURN(1);
+ }
+ } else
+ DBUG_RETURN(1);
+
+ /* remove cache entries */
+ query_cache_invalidate3(thd, view, 0);
+ sp_cache_invalidate();
+ DBUG_RETURN(0);
+}
diff --git a/sql/sql_view.h b/sql/sql_view.h
new file mode 100644
index 00000000000..4cc9eb454fb
--- /dev/null
+++ b/sql/sql_view.h
@@ -0,0 +1,40 @@
+/* -*- C++ -*- */
+/* 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
+*/
+
+bool mysql_create_view(THD *thd,
+ enum_view_create_mode mode);
+
+my_bool mysql_make_view(File_parser *parser, TABLE_LIST *table);
+
+bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
+
+bool check_key_in_view(THD *thd, TABLE_LIST * view);
+
+bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view);
+
+frm_type_enum mysql_frm_type(char *path);
+
+int view_checksum(THD *thd, TABLE_LIST *view);
+
+extern TYPELIB updatable_views_with_limit_typelib;
+
+bool check_duplicate_names(List<Item>& item_list, bool gen_unique_view_names);
+bool mysql_rename_view(THD *thd, const char *new_name, TABLE_LIST *view);
+
+#define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL)
+
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e29aaac8f94..20a9d945a87 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -34,22 +34,38 @@
#include "slave.h"
#include "lex_symbol.h"
#include "item_create.h"
+#include "sp_head.h"
+#include "sp_pcontext.h"
+#include "sp_rcontext.h"
+#include "sp.h"
#include <myisam.h>
#include <myisammrg.h>
int yylex(void *yylval, void *yythd);
-#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; }}
+const LEX_STRING null_lex_str={0,0};
-#define WARN_DEPRECATED(A,B) \
- push_warning_printf(((THD *)yythd), MYSQL_ERROR::WARN_LEVEL_WARN, \
- ER_WARN_DEPRECATED_SYNTAX, \
- ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B));
+#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; }}
-inline Item *or_or_concat(THD *thd, Item* A, Item* B)
+#define WARN_DEPRECATED(A,B) \
+ push_warning_printf(((THD *)yythd), MYSQL_ERROR::WARN_LEVEL_WARN, \
+ ER_WARN_DEPRECATED_SYNTAX, \
+ ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B));
+
+#define YYERROR_UNLESS(A) \
+ if (!(A)) \
+ { \
+ yyerror(ER(ER_SYNTAX_ERROR)); \
+ YYABORT; \
+ }
+
+/* Helper for parsing "IS [NOT] truth_value" */
+inline Item *is_truth_value(Item *A, bool v1, bool v2)
{
- return (thd->variables.sql_mode & MODE_PIPES_AS_CONCAT ?
- (Item*) new Item_func_concat(A,B) : (Item*) new Item_cond_or(A,B));
+ return new Item_func_if(create_func_ifnull(A,
+ new Item_int((char *) (v2 ? "TRUE" : "FALSE"), v2, 1)),
+ new Item_int((char *) (v1 ? "TRUE" : "FALSE"), v1, 1),
+ new Item_int((char *) (v1 ? "FALSE" : "TRUE"),!v1, 1));
}
%}
@@ -72,6 +88,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
udf_func *udf;
LEX_USER *lex_user;
struct sys_var_with_base variable;
+ enum enum_var_type var_type;
Key::Keytype key_type;
enum ha_key_alg key_alg;
enum db_type db_type;
@@ -82,10 +99,14 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
enum Item_udftype udf_type;
CHARSET_INFO *charset;
thr_lock_type lock_type;
- interval_type interval;
+ interval_type interval, interval_time_st;
timestamp_type date_time_type;
st_select_lex *select_lex;
chooser_compare_func_creator boolfunc2creator;
+ struct sp_cond_type *spcondtype;
+ struct { int vars, conds, hndlrs, curs; } spblock;
+ sp_name *spname;
+ struct st_lex *lex;
}
%{
@@ -94,495 +115,557 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%pure_parser /* We have threads */
-%token END_OF_INPUT
-
-%token CLOSE_SYM
-%token HANDLER_SYM
-%token LAST_SYM
-%token NEXT_SYM
-%token PREV_SYM
-
-%token DIV_SYM
-%token EQ
-%token EQUAL_SYM
-%token SOUNDS_SYM
-%token GE
-%token GT_SYM
-%token LE
-%token LT
-%token NE
-%token IS
-%token MOD_SYM
-%token SHIFT_LEFT
-%token SHIFT_RIGHT
-%token SET_VAR
-
-%token ABORT_SYM
-%token ADD
-%token AFTER_SYM
-%token ALTER
-%token ANALYZE_SYM
-%token ANY_SYM
-%token AVG_SYM
-%token BEGIN_SYM
-%token BINLOG_SYM
-%token CHANGE
-%token CLIENT_SYM
-%token COMMENT_SYM
-%token COMMIT_SYM
+%token END_OF_INPUT
+
+%token ABORT_SYM
+%token ACTION
+%token ADD
+%token ADDDATE_SYM
+%token AFTER_SYM
+%token AGAINST
+%token AGGREGATE_SYM
+%token ALGORITHM_SYM
+%token ALL
+%token ALTER
+%token ANALYZE_SYM
+%token AND_AND_SYM
+%token AND_SYM
+%token ANY_SYM
+%token AS
+%token ASC
+%token ASCII_SYM
+%token ASENSITIVE_SYM
+%token ATAN
+%token AUTO_INC
+%token AVG_ROW_LENGTH
+%token AVG_SYM
+%token BACKUP_SYM
+%token BEFORE_SYM
+%token BEGIN_SYM
+%token BENCHMARK_SYM
+%token BERKELEY_DB_SYM
+%token BIGINT
+%token BINARY
+%token BINLOG_SYM
+%token BIN_NUM
+%token BIT_AND
+%token BIT_OR
+%token BIT_SYM
+%token BIT_XOR
+%token BLOB_SYM
+%token BOOLEAN_SYM
+%token BOOL_SYM
+%token BOTH
+%token BTREE_SYM
+%token BY
+%token BYTE_SYM
+%token CACHE_SYM
+%token CALL_SYM
+%token CASCADE
+%token CASCADED
+%token CAST_SYM
+%token CHAIN_SYM
+%token CHANGE
+%token CHANGED
+%token CHARSET
+%token CHAR_SYM
+%token CHECKSUM_SYM
+%token CHECK_SYM
+%token CIPHER_SYM
+%token CLIENT_SYM
+%token CLOSE_SYM
+%token COALESCE
+%token COLLATE_SYM
+%token COLLATION_SYM
+%token COLUMNS
+%token COLUMN_SYM
+%token COMMENT_SYM
+%token COMMITTED_SYM
+%token COMMIT_SYM
+%token COMPACT_SYM
+%token COMPRESSED_SYM
+%token CONCAT
+%token CONCAT_WS
+%token CONCURRENT
+%token CONDITION_SYM
+%token CONNECTION_SYM
%token CONSISTENT_SYM
-%token COUNT_SYM
-%token CREATE
-%token CROSS
+%token CONSTRAINT
+%token CONTAINS_SYM
+%token CONTINUE_SYM
+%token CONVERT_SYM
+%token CONVERT_TZ_SYM
+%token COUNT_SYM
+%token CREATE
+%token CROSS
%token CUBE_SYM
-%token DELETE_SYM
-%token DUAL_SYM
-%token DO_SYM
-%token DROP
-%token EVENTS_SYM
-%token EXECUTE_SYM
-%token EXPANSION_SYM
-%token FLUSH_SYM
-%token HELP_SYM
-%token INSERT
-%token RELAY_THREAD
-%token KILL_SYM
-%token LOAD
-%token LOCKS_SYM
-%token LOCK_SYM
-%token MASTER_SYM
-%token MAX_SYM
-%token MIN_SYM
-%token NONE_SYM
-%token OPTIMIZE
-%token PURGE
-%token REPAIR
-%token REPLICATION
-%token RESET_SYM
-%token ROLLBACK_SYM
-%token ROLLUP_SYM
-%token SAVEPOINT_SYM
-%token SELECT_SYM
-%token SHOW
-%token SLAVE
-%token SNAPSHOT_SYM
-%token SQL_THREAD
-%token START_SYM
-%token STD_SYM
-%token VARIANCE_SYM
-%token STOP_SYM
-%token SUM_SYM
-%token ADDDATE_SYM
-%token SUPER_SYM
-%token TRUNCATE_SYM
-%token UNLOCK_SYM
-%token UNTIL_SYM
-%token UPDATE_SYM
-
-%token ACTION
-%token AGGREGATE_SYM
-%token ALL
-%token AND_SYM
-%token AS
-%token ASC
-%token AUTO_INC
-%token AVG_ROW_LENGTH
-%token BACKUP_SYM
-%token BERKELEY_DB_SYM
-%token BINARY
-%token BIT_SYM
-%token BOOL_SYM
-%token BOOLEAN_SYM
-%token BOTH
-%token BTREE_SYM
-%token BY
-%token BYTE_SYM
-%token CACHE_SYM
-%token CASCADE
-%token CAST_SYM
-%token CHARSET
-%token CHECKSUM_SYM
-%token CHECK_SYM
-%token COMMITTED_SYM
-%token COLLATE_SYM
-%token COLLATION_SYM
-%token COLUMNS
-%token COLUMN_SYM
-%token CONCURRENT
-%token CONSTRAINT
-%token CONVERT_SYM
+%token CURDATE
%token CURRENT_USER
-%token DATABASES
-%token DATA_SYM
-%token DEFAULT
-%token DELAYED_SYM
-%token DELAY_KEY_WRITE_SYM
-%token DESC
-%token DESCRIBE
-%token DES_KEY_FILE
-%token DISABLE_SYM
-%token DISCARD
-%token DISTINCT
+%token CURSOR_SYM
+%token CURTIME
+%token DATABASE
+%token DATABASES
+%token DATA_SYM
+%token DATETIME
+%token DATE_ADD_INTERVAL
+%token DATE_SUB_INTERVAL
+%token DATE_SYM
+%token DAY_HOUR_SYM
+%token DAY_MICROSECOND_SYM
+%token DAY_MINUTE_SYM
+%token DAY_SECOND_SYM
+%token DAY_SYM
+%token DEALLOCATE_SYM
+%token DECIMAL_NUM
+%token DECIMAL_SYM
+%token DECLARE_SYM
+%token DECODE_SYM
+%token DEFAULT
+%token DEFINER_SYM
+%token DELAYED_SYM
+%token DELAY_KEY_WRITE_SYM
+%token DELETE_SYM
+%token DESC
+%token DESCRIBE
+%token DES_DECRYPT_SYM
+%token DES_ENCRYPT_SYM
+%token DES_KEY_FILE
+%token DETERMINISTIC_SYM
+%token DIRECTORY_SYM
+%token DISABLE_SYM
+%token DISCARD
+%token DISTINCT
+%token DIV_SYM
+%token DOUBLE_SYM
+%token DO_SYM
+%token DROP
+%token DUAL_SYM
+%token DUMPFILE
%token DUPLICATE_SYM
-%token DYNAMIC_SYM
-%token ENABLE_SYM
-%token ENCLOSED
-%token ESCAPED
-%token DIRECTORY_SYM
-%token ESCAPE_SYM
-%token EXISTS
-%token EXTENDED_SYM
-%token FALSE_SYM
-%token FILE_SYM
-%token FIRST_SYM
-%token FIXED_SYM
-%token FLOAT_NUM
-%token FORCE_SYM
-%token FOREIGN
-%token FROM
-%token FULL
-%token FULLTEXT_SYM
-%token GLOBAL_SYM
-%token GRANT
-%token GRANTS
-%token GREATEST_SYM
-%token GROUP
-%token HAVING
-%token HASH_SYM
-%token HEX_NUM
-%token HIGH_PRIORITY
-%token HOSTS_SYM
-%token IDENT
-%token IDENT_QUOTED
-%token IGNORE_SYM
-%token IMPORT
-%token INDEX_SYM
-%token INDEXES
-%token INFILE
-%token INNER_SYM
-%token INNOBASE_SYM
-%token INTO
-%token IN_SYM
-%token ISOLATION
-%token JOIN_SYM
-%token KEYS
-%token KEY_SYM
-%token LEADING
-%token LEAST_SYM
-%token LEAVES
-%token LEVEL_SYM
-%token LEX_HOSTNAME
-%token LIKE
-%token LINES
-%token LOCAL_SYM
-%token LOG_SYM
-%token LOGS_SYM
-%token LONG_NUM
-%token LONG_SYM
-%token LOW_PRIORITY
-%token MASTER_HOST_SYM
-%token MASTER_USER_SYM
-%token MASTER_LOG_FILE_SYM
-%token MASTER_LOG_POS_SYM
-%token MASTER_PASSWORD_SYM
-%token MASTER_PORT_SYM
-%token MASTER_CONNECT_RETRY_SYM
-%token MASTER_SERVER_ID_SYM
-%token MASTER_SSL_SYM
-%token MASTER_SSL_CA_SYM
-%token MASTER_SSL_CAPATH_SYM
-%token MASTER_SSL_CERT_SYM
-%token MASTER_SSL_CIPHER_SYM
-%token MASTER_SSL_KEY_SYM
-%token RELAY_LOG_FILE_SYM
-%token RELAY_LOG_POS_SYM
-%token MATCH
-%token MAX_ROWS
-%token MAX_CONNECTIONS_PER_HOUR
-%token MAX_QUERIES_PER_HOUR
-%token MAX_UPDATES_PER_HOUR
-%token MEDIUM_SYM
-%token MIN_ROWS
-%token NAMES_SYM
-%token NATIONAL_SYM
-%token NATURAL
-%token NDBCLUSTER_SYM
-%token NEW_SYM
-%token NCHAR_SYM
-%token NCHAR_STRING
-%token NVARCHAR_SYM
-%token NOT
-%token NO_SYM
-%token NULL_SYM
-%token NUM
-%token OFFSET_SYM
-%token ON
-%token ONE_SHOT_SYM
-%token OPEN_SYM
-%token OPTION
-%token OPTIONALLY
-%token OR_SYM
-%token OR_OR_CONCAT
-%token ORDER_SYM
-%token OUTER
-%token OUTFILE
-%token DUMPFILE
-%token PACK_KEYS_SYM
-%token PARTIAL
-%token PRIMARY_SYM
-%token PRIVILEGES
-%token PROCESS
-%token PROCESSLIST_SYM
-%token QUERY_SYM
-%token RAID_0_SYM
-%token RAID_STRIPED_SYM
-%token RAID_TYPE
-%token RAID_CHUNKS
-%token RAID_CHUNKSIZE
-%token READ_SYM
-%token REAL_NUM
-%token REFERENCES
-%token REGEXP
-%token RELOAD
-%token RENAME
-%token REPEATABLE_SYM
-%token REQUIRE_SYM
-%token RESOURCES
-%token RESTORE_SYM
-%token RESTRICT
-%token REVOKE
-%token ROWS_SYM
-%token ROW_FORMAT_SYM
-%token ROW_SYM
-%token RTREE_SYM
-%token SET
-%token SEPARATOR_SYM
-%token SERIAL_SYM
-%token SERIALIZABLE_SYM
-%token SESSION_SYM
-%token SIMPLE_SYM
-%token SHUTDOWN
-%token SPATIAL_SYM
-%token SSL_SYM
-%token STARTING
-%token STATUS_SYM
-%token STORAGE_SYM
-%token STRAIGHT_JOIN
-%token SUBJECT_SYM
-%token TABLES
-%token TABLE_SYM
-%token TABLESPACE
-%token TEMPORARY
-%token TERMINATED
-%token TEXT_STRING
-%token TO_SYM
-%token TRAILING
-%token TRANSACTION_SYM
-%token TRUE_SYM
-%token TYPE_SYM
-%token TYPES_SYM
-%token FUNC_ARG0
-%token FUNC_ARG1
-%token FUNC_ARG2
-%token FUNC_ARG3
-%token UDF_RETURNS_SYM
-%token UDF_SONAME_SYM
-%token UDF_SYM
-%token UNCOMMITTED_SYM
-%token UNDERSCORE_CHARSET
-%token UNICODE_SYM
-%token UNION_SYM
-%token UNIQUE_SYM
-%token USAGE
-%token USE_FRM
-%token USE_SYM
-%token USING
-%token VALUE_SYM
-%token VALUES
-%token VARIABLES
-%token WHERE
-%token WITH
-%token WRITE_SYM
-%token NO_WRITE_TO_BINLOG
-%token X509_SYM
-%token XOR
-%token COMPRESSED_SYM
-
+%token DYNAMIC_SYM
+%token EACH_SYM
+%token ELSEIF_SYM
+%token ELT_FUNC
+%token ENABLE_SYM
+%token ENCLOSED
+%token ENCODE_SYM
+%token ENCRYPT
+%token END
+%token ENGINES_SYM
+%token ENGINE_SYM
+%token ENUM
+%token EQ
+%token EQUAL_SYM
%token ERRORS
-%token WARNINGS
-
-%token ASCII_SYM
-%token BIGINT
-%token BLOB_SYM
-%token CHAR_SYM
-%token CHANGED
-%token COALESCE
-%token DATETIME
-%token DATE_SYM
-%token DECIMAL_SYM
-%token DOUBLE_SYM
-%token ENUM
-%token FAST_SYM
-%token FLOAT_SYM
-%token GEOMETRY_SYM
-%token INT_SYM
-%token LIMIT
-%token LONGBLOB
-%token LONGTEXT
-%token MEDIUMBLOB
-%token MEDIUMINT
-%token MEDIUMTEXT
-%token NUMERIC_SYM
-%token PRECISION
-%token PREPARE_SYM
-%token DEALLOCATE_SYM
-%token QUICK
-%token REAL
-%token SIGNED_SYM
-%token SMALLINT
-%token STRING_SYM
-%token TEXT_SYM
-%token TIMESTAMP
-%token TIME_SYM
-%token TINYBLOB
-%token TINYINT
-%token TINYTEXT
-%token ULONGLONG_NUM
-%token UNSIGNED
-%token VARBINARY
-%token VARCHAR
-%token VARYING
-%token ZEROFILL
-
-%token ADDDATE_SYM
-%token AGAINST
-%token ATAN
-%token BETWEEN_SYM
-%token BIT_AND
-%token BIT_OR
-%token BIT_XOR
-%token CASE_SYM
-%token CONCAT
-%token CONCAT_WS
-%token CONVERT_TZ_SYM
-%token CURDATE
-%token CURTIME
-%token DATABASE
-%token DATE_ADD_INTERVAL
-%token DATE_SUB_INTERVAL
-%token DAY_HOUR_SYM
-%token DAY_MICROSECOND_SYM
-%token DAY_MINUTE_SYM
-%token DAY_SECOND_SYM
-%token DAY_SYM
-%token DECODE_SYM
-%token DES_ENCRYPT_SYM
-%token DES_DECRYPT_SYM
-%token ELSE
-%token ELT_FUNC
-%token ENCODE_SYM
-%token ENGINE_SYM
-%token ENGINES_SYM
-%token ENCRYPT
-%token EXPORT_SET
-%token EXTRACT_SYM
-%token FIELD_FUNC
-%token FORMAT_SYM
-%token FOR_SYM
-%token FROM_UNIXTIME
-%token GEOMCOLLFROMTEXT
-%token GEOMFROMTEXT
-%token GEOMFROMWKB
+%token ESCAPED
+%token ESCAPE_SYM
+%token EVENTS_SYM
+%token EXECUTE_SYM
+%token EXISTS
+%token EXIT_SYM
+%token EXPANSION_SYM
+%token EXPORT_SET
+%token EXTENDED_SYM
+%token EXTRACT_SYM
+%token FALSE_SYM
+%token FAST_SYM
+%token FETCH_SYM
+%token FIELD_FUNC
+%token FILE_SYM
+%token FIRST_SYM
+%token FIXED_SYM
+%token FLOAT_NUM
+%token FLOAT_SYM
+%token FLUSH_SYM
+%token FORCE_SYM
+%token FOREIGN
+%token FORMAT_SYM
+%token FOR_SYM
+%token FOUND_SYM
+%token FRAC_SECOND_SYM
+%token FROM
+%token FROM_UNIXTIME
+%token FULL
+%token FULLTEXT_SYM
+%token FUNCTION_SYM
+%token FUNC_ARG0
+%token FUNC_ARG1
+%token FUNC_ARG2
+%token FUNC_ARG3
+%token GE
+%token GEOMCOLLFROMTEXT
%token GEOMETRYCOLLECTION
-%token GROUP_CONCAT_SYM
-%token GROUP_UNIQUE_USERS
+%token GEOMETRY_SYM
+%token GEOMFROMTEXT
+%token GEOMFROMWKB
%token GET_FORMAT
-%token HOUR_MICROSECOND_SYM
-%token HOUR_MINUTE_SYM
-%token HOUR_SECOND_SYM
-%token HOUR_SYM
-%token IDENTIFIED_SYM
-%token IF
-%token INSERT_METHOD
-%token INTERVAL_SYM
-%token LAST_INSERT_ID
-%token LEFT
-%token LINEFROMTEXT
+%token GLOBAL_SYM
+%token GOTO_SYM
+%token GRANT
+%token GRANTS
+%token GREATEST_SYM
+%token GROUP
+%token GROUP_CONCAT_SYM
+%token GROUP_UNIQUE_USERS
+%token GT_SYM
+%token HANDLER_SYM
+%token HASH_SYM
+%token HAVING
+%token HELP_SYM
+%token HEX_NUM
+%token HIGH_PRIORITY
+%token HOSTS_SYM
+%token HOUR_MICROSECOND_SYM
+%token HOUR_MINUTE_SYM
+%token HOUR_SECOND_SYM
+%token HOUR_SYM
+%token IDENT
+%token IDENTIFIED_SYM
+%token IDENT_QUOTED
+%token IF
+%token IGNORE_SYM
+%token IMPORT
+%token INDEXES
+%token INDEX_SYM
+%token INFILE
+%token INNER_SYM
+%token INNOBASE_SYM
+%token INOUT_SYM
+%token INSENSITIVE_SYM
+%token INSERT
+%token INSERT_METHOD
+%token INTERVAL_SYM
+%token INTO
+%token INT_SYM
+%token INVOKER_SYM
+%token IN_SYM
+%token IS
+%token ISOLATION
+%token ISSUER_SYM
+%token ITERATE_SYM
+%token JOIN_SYM
+%token KEYS
+%token KEY_SYM
+%token KILL_SYM
+%token LABEL_SYM
+%token LANGUAGE_SYM
+%token LAST_INSERT_ID
+%token LAST_SYM
+%token LE
+%token LEADING
+%token LEAST_SYM
+%token LEAVES
+%token LEAVE_SYM
+%token LEFT
+%token LEVEL_SYM
+%token LEX_HOSTNAME
+%token LIKE
+%token LIMIT
+%token LINEFROMTEXT
+%token LINES
%token LINESTRING
-%token LOCATE
-%token MAKE_SET_SYM
-%token MASTER_POS_WAIT
+%token LOAD
+%token LOCAL_SYM
+%token LOCATE
+%token LOCATOR_SYM
+%token LOCKS_SYM
+%token LOCK_SYM
+%token LOGS_SYM
+%token LOG_SYM
+%token LONGBLOB
+%token LONGTEXT
+%token LONG_NUM
+%token LONG_SYM
+%token LOOP_SYM
+%token LOW_PRIORITY
+%token LT
+%token MAKE_SET_SYM
+%token MASTER_CONNECT_RETRY_SYM
+%token MASTER_HOST_SYM
+%token MASTER_LOG_FILE_SYM
+%token MASTER_LOG_POS_SYM
+%token MASTER_PASSWORD_SYM
+%token MASTER_PORT_SYM
+%token MASTER_POS_WAIT
+%token MASTER_SERVER_ID_SYM
+%token MASTER_SSL_CAPATH_SYM
+%token MASTER_SSL_CA_SYM
+%token MASTER_SSL_CERT_SYM
+%token MASTER_SSL_CIPHER_SYM
+%token MASTER_SSL_KEY_SYM
+%token MASTER_SSL_SYM
+%token MASTER_SYM
+%token MASTER_USER_SYM
+%token MATCH
+%token MAX_CONNECTIONS_PER_HOUR
+%token MAX_QUERIES_PER_HOUR
+%token MAX_ROWS
+%token MAX_SYM
+%token MAX_UPDATES_PER_HOUR
+%token MAX_USER_CONNECTIONS_SYM
+%token MEDIUMBLOB
+%token MEDIUMINT
+%token MEDIUMTEXT
+%token MEDIUM_SYM
+%token MERGE_SYM
%token MICROSECOND_SYM
-%token MINUTE_MICROSECOND_SYM
-%token MINUTE_SECOND_SYM
-%token MINUTE_SYM
-%token MODE_SYM
-%token MODIFY_SYM
-%token MONTH_SYM
-%token MLINEFROMTEXT
-%token MPOINTFROMTEXT
-%token MPOLYFROMTEXT
+%token MIGRATE_SYM
+%token MINUTE_MICROSECOND_SYM
+%token MINUTE_SECOND_SYM
+%token MINUTE_SYM
+%token MIN_ROWS
+%token MIN_SYM
+%token MLINEFROMTEXT
+%token MODE_SYM
+%token MODIFIES_SYM
+%token MODIFY_SYM
+%token MOD_SYM
+%token MONTH_SYM
+%token MPOINTFROMTEXT
+%token MPOLYFROMTEXT
%token MULTILINESTRING
%token MULTIPOINT
%token MULTIPOLYGON
-%token NOW_SYM
-%token OLD_PASSWORD
-%token PASSWORD
+%token MUTEX_SYM
+%token NAMES_SYM
+%token NAME_SYM
+%token NATIONAL_SYM
+%token NATURAL
+%token NCHAR_STRING
+%token NCHAR_SYM
+%token NDBCLUSTER_SYM
+%token NE
+%token NEW_SYM
+%token NEXT_SYM
+%token NONE_SYM
+%token NOT2_SYM
+%token NOT_SYM
+%token NOW_SYM
+%token NO_SYM
+%token NO_WRITE_TO_BINLOG
+%token NULL_SYM
+%token NUM
+%token NUMERIC_SYM
+%token NVARCHAR_SYM
+%token OFFSET_SYM
+%token OLD_PASSWORD
+%token ON
+%token ONE_SHOT_SYM
+%token ONE_SYM
+%token OPEN_SYM
+%token OPTIMIZE
+%token OPTION
+%token OPTIONALLY
+%token OR2_SYM
+%token ORDER_SYM
+%token OR_OR_SYM
+%token OR_SYM
+%token OUTER
+%token OUTFILE
+%token OUT_SYM
+%token PACK_KEYS_SYM
+%token PARTIAL
+%token PASSWORD
%token PARAM_MARKER
-%token POINTFROMTEXT
-%token POINT_SYM
-%token POLYFROMTEXT
+%token PHASE_SYM
+%token POINTFROMTEXT
+%token POINT_SYM
+%token POLYFROMTEXT
%token POLYGON
-%token POSITION_SYM
-%token PROCEDURE
-%token RAND
-%token REPLACE
-%token RIGHT
-%token ROUND
-%token SECOND_SYM
-%token SECOND_MICROSECOND_SYM
-%token SHARE_SYM
-%token SUBDATE_SYM
-%token SUBSTRING
-%token SUBSTRING_INDEX
-%token TRIM
-%token UDA_CHAR_SUM
-%token UDA_FLOAT_SUM
-%token UDA_INT_SUM
-%token UDF_CHAR_FUNC
-%token UDF_FLOAT_FUNC
-%token UDF_INT_FUNC
-%token UNIQUE_USERS
-%token UNIX_TIMESTAMP
-%token USER
-%token UTC_DATE_SYM
-%token UTC_TIME_SYM
-%token UTC_TIMESTAMP_SYM
-%token WEEK_SYM
-%token WHEN_SYM
-%token WORK_SYM
-%token YEAR_MONTH_SYM
-%token YEAR_SYM
-%token YEARWEEK
-%token BENCHMARK_SYM
-%token END
-%token THEN_SYM
-
-%token SQL_BIG_RESULT
-%token SQL_CACHE_SYM
-%token SQL_CALC_FOUND_ROWS
-%token SQL_NO_CACHE_SYM
-%token SQL_SMALL_RESULT
+%token POSITION_SYM
+%token PRECISION
+%token PREPARE_SYM
+%token PREV_SYM
+%token PRIMARY_SYM
+%token PRIVILEGES
+%token PROCEDURE
+%token PROCESS
+%token PROCESSLIST_SYM
+%token PURGE
+%token QUARTER_SYM
+%token QUERY_SYM
+%token QUICK
+%token RAID_0_SYM
+%token RAID_CHUNKS
+%token RAID_CHUNKSIZE
+%token RAID_STRIPED_SYM
+%token RAID_TYPE
+%token RAND
+%token READS_SYM
+%token READ_SYM
+%token REAL
+%token RECOVER_SYM
+%token REDUNDANT_SYM
+%token REFERENCES
+%token REGEXP
+%token RELAY_LOG_FILE_SYM
+%token RELAY_LOG_POS_SYM
+%token RELAY_THREAD
+%token RELEASE_SYM
+%token RELOAD
+%token RENAME
+%token REPAIR
+%token REPEATABLE_SYM
+%token REPEAT_SYM
+%token REPLACE
+%token REPLICATION
+%token REQUIRE_SYM
+%token RESET_SYM
+%token RESOURCES
+%token RESTORE_SYM
+%token RESTRICT
+%token RESUME_SYM
+%token RETURNS_SYM
+%token RETURN_SYM
+%token REVOKE
+%token RIGHT
+%token ROLLBACK_SYM
+%token ROLLUP_SYM
+%token ROUND
+%token ROUTINE_SYM
+%token ROWS_SYM
+%token ROW_COUNT_SYM
+%token ROW_FORMAT_SYM
+%token ROW_SYM
+%token RTREE_SYM
+%token SAVEPOINT_SYM
+%token SECOND_MICROSECOND_SYM
+%token SECOND_SYM
+%token SECURITY_SYM
+%token SELECT_SYM
+%token SENSITIVE_SYM
+%token SEPARATOR_SYM
+%token SERIALIZABLE_SYM
+%token SERIAL_SYM
+%token SESSION_SYM
+%token SET
+%token SET_VAR
+%token SHARE_SYM
+%token SHIFT_LEFT
+%token SHIFT_RIGHT
+%token SHOW
+%token SHUTDOWN
+%token SIGNED_SYM
+%token SIMPLE_SYM
+%token SLAVE
+%token SMALLINT
+%token SNAPSHOT_SYM
+%token SOUNDS_SYM
+%token SPATIAL_SYM
+%token SPECIFIC_SYM
+%token SQLEXCEPTION_SYM
+%token SQLSTATE_SYM
+%token SQLWARNING_SYM
+%token SQL_BIG_RESULT
%token SQL_BUFFER_RESULT
-
-%token ISSUER_SYM
+%token SQL_CACHE_SYM
+%token SQL_CALC_FOUND_ROWS
+%token SQL_NO_CACHE_SYM
+%token SQL_SMALL_RESULT
+%token SQL_SYM
+%token SQL_THREAD
+%token SSL_SYM
+%token STARTING
+%token START_SYM
+%token STATUS_SYM
+%token STD_SYM
+%token STDDEV_SAMP_SYM
+%token STOP_SYM
+%token STORAGE_SYM
+%token STRAIGHT_JOIN
+%token STRING_SYM
+%token SUBDATE_SYM
%token SUBJECT_SYM
-%token CIPHER_SYM
-
-%token BEFORE_SYM
+%token SUBSTRING
+%token SUBSTRING_INDEX
+%token SUM_SYM
+%token SUPER_SYM
+%token SUSPEND_SYM
+%token SYSDATE
+%token TABLES
+%token TABLESPACE
+%token TABLE_SYM
+%token TEMPORARY
+%token TEMPTABLE_SYM
+%token TERMINATED
+%token TEXT_STRING
+%token TEXT_SYM
+%token TIMESTAMP
+%token TIMESTAMP_ADD
+%token TIMESTAMP_DIFF
+%token TIME_SYM
+%token TINYBLOB
+%token TINYINT
+%token TINYTEXT
+%token TO_SYM
+%token TRAILING
+%token TRANSACTION_SYM
+%token TRIGGER_SYM
+%token TRIGGERS_SYM
+%token TRIM
+%token TRUE_SYM
+%token TRUNCATE_SYM
+%token TYPES_SYM
+%token TYPE_SYM
+%token UDF_RETURNS_SYM
+%token UDF_SONAME_SYM
+%token ULONGLONG_NUM
+%token UNCOMMITTED_SYM
+%token UNDEFINED_SYM
+%token UNDERSCORE_CHARSET
+%token UNDO_SYM
+%token UNICODE_SYM
+%token UNION_SYM
+%token UNIQUE_SYM
+%token UNIQUE_USERS
+%token UNIX_TIMESTAMP
+%token UNKNOWN_SYM
+%token UNLOCK_SYM
+%token UNLOCK_SYM
+%token UNSIGNED
+%token UNTIL_SYM
+%token UNTIL_SYM
+%token UPDATE_SYM
+%token UPDATE_SYM
+%token USAGE
+%token USER
+%token USE_FRM
+%token USE_SYM
+%token USING
+%token UTC_DATE_SYM
+%token UTC_TIMESTAMP_SYM
+%token UTC_TIME_SYM
+%token VAR_SAMP_SYM
+%token VALUES
+%token VALUE_SYM
+%token VARBINARY
+%token VARCHAR
+%token VARIABLES
+%token VARIANCE_SYM
+%token VARYING
+%token VIEW_SYM
+%token WARNINGS
+%token WEEK_SYM
+%token WHEN_SYM
+%token WHERE
+%token WHILE_SYM
+%token WITH
+%token WORK_SYM
+%token WRITE_SYM
+%token X509_SYM
+%token XA_SYM
+%token XOR
+%token YEARWEEK
+%token YEAR_MONTH_SYM
+%token YEAR_SYM
+%token ZEROFILL
+
+%left JOIN_SYM
+/* A dummy token to force the priority of table_ref production in a join. */
+%left TABLE_REF_PRIORITY
%left SET_VAR
-%left OR_OR_CONCAT OR_SYM XOR
-%left AND_SYM
+%left OR_OR_SYM OR_SYM OR2_SYM XOR
+%left AND_SYM AND_AND_SYM
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
%left EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM
%left '|'
@@ -592,20 +675,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left '*' '/' '%' DIV_SYM MOD_SYM
%left '^'
%left NEG '~'
-%right NOT
+%right NOT_SYM NOT2_SYM
%right BINARY COLLATE_SYM
%type <lex_str>
- IDENT IDENT_QUOTED TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM
+ IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name
+ sp_opt_label BIN_NUM label_ident
%type <lex_str_ptr>
opt_table_alias
%type <table>
- table_ident table_ident_nodb references
+ table_ident table_ident_nodb references xid
%type <simple_string>
remember_name remember_end opt_ident opt_db text_or_password
@@ -615,15 +699,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
text_string opt_gconcat_separator
%type <num>
- type int_type real_type order_dir opt_field_spec lock_option
+ type int_type real_type order_dir lock_option
udf_type if_exists opt_local opt_table_options table_options
- table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type
- opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct
+ table_option opt_if_not_exists opt_no_write_to_binlog
+ delete_option opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option
- start_transaction_opts
+ start_transaction_opts opt_chain opt_release
+ union_opt select_derived_init option_type2
%type <ulong_num>
- ULONG_NUM raid_types merge_insert_types
+ ulong_num raid_types merge_insert_types
%type <ulonglong_number>
ulonglong_num
@@ -634,17 +719,26 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
- table_wild no_in_expr expr_expr simple_expr no_and_expr
- using_list expr_or_default set_expr_or_default interval_expr
+ bool_term bool_factor bool_test bool_pri
+ predicate bit_expr bit_term bit_factor value_expr term factor
+ table_wild simple_expr udf_expr
+ 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 opt_escape
+ sp_opt_default
+ simple_ident_nospvar simple_ident_q
+ field_or_var limit_option
%type <item_num>
NUM_literal
%type <item_list>
- expr_list udf_expr_list when_list ident_list ident_list_arg
+ expr_list udf_expr_list udf_expr_list2 when_list
+ ident_list ident_list_arg
+
+%type <var_type>
+ option_type opt_var_type opt_var_ident_type
%type <key_type>
key_type opt_unique_or_fulltext constraint_key_type
@@ -653,21 +747,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
key_alg opt_btree_or_rtree
%type <string_list>
- key_usage_list
+ key_usage_list using_list
%type <key_part>
key_part
%type <table_list>
join_table_list join_table
-
-%type <udf>
- UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC
- UDA_CHAR_SUM UDA_FLOAT_SUM UDA_INT_SUM
+ table_factor table_ref
+ select_derived derived_table_list
%type <date_time_type> date_time_type;
%type <interval> interval
+%type <interval_time_st> interval_time_st
+
%type <db_type> storage_engines
%type <row_type> row_types
@@ -680,7 +774,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <udf_type> udf_func_type
-%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword
+%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
%type <lex_user> user grant_user
@@ -696,6 +790,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <variable> internal_variable_name
%type <select_lex> in_subselect in_subselect_init
+ get_select_lex
%type <boolfunc2creator> comp_op
@@ -703,7 +798,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename
show describe load alter optimize keycache preload flush
- reset purge begin commit rollback savepoint
+ reset purge begin commit rollback savepoint release
slave master_def master_defs master_file_def slave_until_opts
repair restore backup analyze check start checksum
field_list field_list_item field_spec kill column_def key_def
@@ -711,7 +806,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
- when_list2 expr_list2 handler
+ when_list2 expr_list2 udf_expr_list3 handler
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock
@@ -719,9 +814,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name opt_option opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
- opt_column_list grant_privileges opt_table user_list grant_option
- grant_privilege grant_privilege_list
- flush_options flush_option
+ opt_column_list grant_privileges grant_ident grant_list grant_option
+ object_privilege object_privilege_list user_list rename_list
+ clear_privileges flush_options flush_option
equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as
@@ -731,13 +826,24 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *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
+ prepare prepare_src execute deallocate
+ statement sp_suid opt_view_list view_list or_replace algorithm
+ sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
+ load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
+ view_user view_suid
END_OF_INPUT
+%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
+%type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list
+%type <spcondtype> sp_cond sp_hcond
+%type <spblock> sp_decls sp_decl
+%type <lex> sp_cursor_stmt
+%type <spname> sp_name
+
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
- ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_CONCAT BETWEEN_SYM CASE_SYM
- THEN_SYM WHEN_SYM DIV_SYM MOD_SYM
+ ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
+ THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM
%%
@@ -748,7 +854,7 @@ query:
if (!thd->bootstrap &&
(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
{
- send_error(thd,ER_EMPTY_QUERY);
+ my_message(ER_EMPTY_QUERY, ER(ER_EMPTY_QUERY), MYF(0));
YYABORT;
}
else
@@ -759,10 +865,16 @@ query:
| verb_clause END_OF_INPUT {};
verb_clause:
+ statement
+ | begin
+ ;
+
+/* Verb clauses, except begin */
+statement:
alter
| analyze
| backup
- | begin
+ | call
| change
| check
| checksum
@@ -787,6 +899,7 @@ verb_clause:
| preload
| prepare
| purge
+ | release
| rename
| repair
| replace
@@ -804,6 +917,7 @@ verb_clause:
| unlock
| update
| use
+ | xa
;
deallocate:
@@ -811,7 +925,7 @@ deallocate:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
- if (thd->command == COM_PREPARE)
+ if (lex->stmt_prepare_mode)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
@@ -831,7 +945,7 @@ prepare:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
- if (thd->command == COM_PREPARE)
+ if (lex->stmt_prepare_mode)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
@@ -861,7 +975,7 @@ execute:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
- if (thd->command == COM_PREPARE)
+ if (lex->stmt_prepare_mode)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
@@ -895,11 +1009,19 @@ execute_var_ident: '@' ident_or_text
/* help */
help:
- HELP_SYM ident_or_text
+ HELP_SYM
+ {
+ if (Lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "HELP");
+ YYABORT;
+ }
+ }
+ ident_or_text
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_HELP;
- lex->help_arg= $2.str;
+ lex->help_arg= $3.str;
};
/* change master */
@@ -935,16 +1057,16 @@ master_def:
Lex->mi.password = $3.str;
}
|
- MASTER_PORT_SYM EQ ULONG_NUM
+ MASTER_PORT_SYM EQ ulong_num
{
Lex->mi.port = $3;
}
|
- MASTER_CONNECT_RETRY_SYM EQ ULONG_NUM
+ MASTER_CONNECT_RETRY_SYM EQ ulong_num
{
Lex->mi.connect_retry = $3;
}
- | MASTER_SSL_SYM EQ ULONG_NUM
+ | MASTER_SSL_SYM EQ ulong_num
{
Lex->mi.ssl= $3 ?
LEX_MASTER_INFO::SSL_ENABLE : LEX_MASTER_INFO::SSL_DISABLE;
@@ -998,7 +1120,7 @@ master_file_def:
{
Lex->mi.relay_log_name = $3.str;
}
- | RELAY_LOG_POS_SYM EQ ULONG_NUM
+ | RELAY_LOG_POS_SYM EQ ulong_num
{
Lex->mi.relay_log_pos = $3;
/* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
@@ -1035,6 +1157,11 @@ create:
| CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident
{
LEX *lex=Lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
lex->sql_command= SQLCOM_CREATE_INDEX;
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
TL_OPTION_UPDATING))
@@ -1063,19 +1190,1345 @@ create:
lex->name=$4.str;
lex->create_info.options=$3;
}
- | CREATE udf_func_type UDF_SYM IDENT_sys
+ | CREATE udf_func_type FUNCTION_SYM sp_name
{
LEX *lex=Lex;
- lex->sql_command = SQLCOM_CREATE_FUNCTION;
- lex->udf.name = $4;
+ lex->spname= $4;
lex->udf.type= $2;
}
- UDF_RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
+ create_function_tail
+ {}
+ | CREATE PROCEDURE sp_name
+ {
+ LEX *lex= Lex;
+ sp_head *sp;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
+ YYABORT;
+ }
+ /* Order is important here: new - reset - init */
+ sp= new sp_head();
+ sp->reset_thd_mem_root(YYTHD);
+ sp->init(lex);
+
+ sp->m_type= TYPE_ENUM_PROCEDURE;
+ lex->sphead= sp;
+ /*
+ * We have to turn of CLIENT_MULTI_QUERIES while parsing a
+ * stored procedure, otherwise yylex will chop it into pieces
+ * at each ';'.
+ */
+ sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
+ YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
+ }
+ '('
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->m_param_begin= lex->tok_start+1;
+ }
+ sp_pdparam_list
+ ')'
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->m_param_end= lex->tok_start;
+ bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+ }
+ sp_c_chistics
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->m_chistics= &lex->sp_chistics;
+ lex->sphead->m_body_begin= lex->tok_start;
+ }
+ sp_proc_stmt
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+
+ if (sp->check_backpatch(YYTHD))
+ YYABORT;
+ sp->init_strings(YYTHD, lex, $3);
+ lex->sql_command= SQLCOM_CREATE_PROCEDURE;
+ /* Restore flag if it was cleared above */
+ if (sp->m_old_cmq)
+ YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
+ sp->restore_thd_mem_root(YYTHD);
+ }
+ | CREATE or_replace algorithm view_user view_suid VIEW_SYM table_ident
+ {
+ THD *thd= YYTHD;
+ LEX *lex= thd->lex;
+ lex->sql_command= SQLCOM_CREATE_VIEW;
+ /* first table in list is target VIEW name */
+ if (!lex->select_lex.add_table_to_list(thd, $7, NULL, 0))
+ YYABORT;
+ }
+ opt_view_list AS select_view_init check_option
+ {}
+ | CREATE TRIGGER_SYM sp_name trg_action_time trg_event
+ ON table_ident FOR_SYM EACH_SYM ROW_SYM
+ {
+ LEX *lex= Lex;
+ sp_head *sp;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
+ YYABORT;
+ }
+
+ if (!(sp= new sp_head()))
+ YYABORT;
+ sp->reset_thd_mem_root(YYTHD);
+ sp->init(lex);
+
+ sp->m_type= TYPE_ENUM_TRIGGER;
+ lex->sphead= sp;
+ lex->spname= $3;
+ /*
+ We have to turn of CLIENT_MULTI_QUERIES while parsing a
+ stored procedure, otherwise yylex will chop it into pieces
+ at each ';'.
+ */
+ sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
+ YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
+
+ bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+ lex->sphead->m_chistics= &lex->sp_chistics;
+ lex->sphead->m_body_begin= lex->ptr;
+ }
+ sp_proc_stmt
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+
+ lex->sql_command= SQLCOM_CREATE_TRIGGER;
+ sp->init_strings(YYTHD, lex, $3);
+ /* Restore flag if it was cleared above */
+ if (sp->m_old_cmq)
+ YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
+ sp->restore_thd_mem_root(YYTHD);
+
+ if (sp->is_not_allowed_in_function("trigger"))
+ YYABORT;
+
+ /*
+ We have to do it after parsing trigger body, because some of
+ sp_proc_stmt alternatives are not saving/restoring LEX, so
+ lex->query_tables can be wiped out.
+
+ QQ: What are other consequences of this?
+
+ QQ: Could we loosen lock type in certain cases ?
+ */
+ if (!lex->select_lex.add_table_to_list(YYTHD, $7,
+ (LEX_STRING*) 0,
+ TL_OPTION_UPDATING,
+ TL_WRITE))
+ YYABORT;
+ }
+ | CREATE USER clear_privileges grant_list
+ {
+ Lex->sql_command = SQLCOM_CREATE_USER;
+ }
+ ;
+
+clear_privileges:
+ /* Nothing */
+ {
+ LEX *lex=Lex;
+ lex->users_list.empty();
+ lex->columns.empty();
+ lex->grant= lex->grant_tot_col= 0;
+ lex->all_privileges= 0;
+ lex->select_lex.db= 0;
+ lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
+ lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
+ bzero((char *)&(lex->mqh),sizeof(lex->mqh));
+ }
+ ;
+
+sp_name:
+ ident '.' ident
+ {
+ $$= new sp_name($1, $3);
+ $$->init_qname(YYTHD);
+ }
+ | ident
+ {
+ $$= sp_name_current_db_new(YYTHD, $1);
+ }
+ ;
+
+create_function_tail:
+ RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
{
LEX *lex=Lex;
- lex->udf.returns=(Item_result) $7;
- lex->udf.dl=$9.str;
+ lex->sql_command = SQLCOM_CREATE_FUNCTION;
+ lex->udf.name = lex->spname->m_name;
+ lex->udf.returns=(Item_result) $2;
+ lex->udf.dl=$4.str;
+ }
+ | '('
+ {
+ LEX *lex= Lex;
+ sp_head *sp;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
+ YYABORT;
+ }
+ /* Order is important here: new - reset - init */
+ sp= new sp_head();
+ sp->reset_thd_mem_root(YYTHD);
+ sp->init(lex);
+
+ sp->m_type= TYPE_ENUM_FUNCTION;
+ lex->sphead= sp;
+ /*
+ * We have to turn of CLIENT_MULTI_QUERIES while parsing a
+ * stored procedure, otherwise yylex will chop it into pieces
+ * at each ';'.
+ */
+ sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
+ YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
+ lex->sphead->m_param_begin= lex->tok_start+1;
+ }
+ sp_fdparam_list ')'
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->m_param_end= lex->tok_start;
+ }
+ RETURNS_SYM
+ {
+ LEX *lex= Lex;
+ lex->charset= NULL;
+ lex->length= lex->dec= NULL;
+ lex->interval_list.empty();
+ lex->type= 0;
+ }
+ type
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ LEX_STRING cmt = { 0, 0 };
+ create_field *new_field;
+ uint unused1= 0;
+ int unused2= 0;
+
+ if (!(new_field= new_create_field(YYTHD, (char*) "",
+ (enum enum_field_types)$8,
+ lex->length, lex->dec, lex->type,
+ (Item *)0, (Item *) 0, &cmt, 0,
+ &lex->interval_list,
+ (lex->charset ? lex->charset :
+ default_charset_info),
+ lex->uint_geom_type)))
+ YYABORT;
+
+ sp->m_returns_cs= new_field->charset;
+
+ if (new_field->interval_list.elements)
+ {
+ new_field->interval=
+ sp->create_typelib(&new_field->interval_list);
+ }
+ sp_prepare_create_field(YYTHD, new_field);
+
+ if (prepare_create_field(new_field, &unused1, &unused2, &unused2,
+ HA_CAN_GEOMETRY))
+ YYABORT;
+
+ sp->m_returns= new_field->sql_type;
+ sp->m_returns_cs= new_field->charset;
+ sp->m_returns_len= new_field->length;
+ sp->m_returns_pack= new_field->pack_flag;
+ sp->m_returns_typelib= new_field->interval;
+ sp->m_geom_returns= new_field->geom_type;
+ new_field->interval= NULL;
+
+ bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+ }
+ sp_c_chistics
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->m_chistics= &lex->sp_chistics;
+ lex->sphead->m_body_begin= lex->tok_start;
+ }
+ sp_proc_stmt
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+
+ if (sp->is_not_allowed_in_function("function"))
+ YYABORT;
+
+ if (sp->check_backpatch(YYTHD))
+ YYABORT;
+ lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
+ sp->init_strings(YYTHD, lex, lex->spname);
+ /* Restore flag if it was cleared above */
+ if (sp->m_old_cmq)
+ YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
+ sp->restore_thd_mem_root(YYTHD);
+ }
+ ;
+
+sp_a_chistics:
+ /* Empty */ {}
+ | sp_a_chistics sp_chistic {}
+ ;
+
+sp_c_chistics:
+ /* Empty */ {}
+ | sp_c_chistics sp_c_chistic {}
+ ;
+
+/* Characteristics for both create and alter */
+sp_chistic:
+ COMMENT_SYM TEXT_STRING_sys
+ { Lex->sp_chistics.comment= $2; }
+ | LANGUAGE_SYM SQL_SYM
+ { /* Just parse it, we only have one language for now. */ }
+ | NO_SYM SQL_SYM
+ { Lex->sp_chistics.daccess= SP_NO_SQL; }
+ | CONTAINS_SYM SQL_SYM
+ { Lex->sp_chistics.daccess= SP_CONTAINS_SQL; }
+ | READS_SYM SQL_SYM DATA_SYM
+ { Lex->sp_chistics.daccess= SP_READS_SQL_DATA; }
+ | MODIFIES_SYM SQL_SYM DATA_SYM
+ { Lex->sp_chistics.daccess= SP_MODIFIES_SQL_DATA; }
+ | sp_suid
+ { }
+ ;
+
+/* Create characteristics */
+sp_c_chistic:
+ sp_chistic { }
+ | DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; }
+ | not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; }
+ ;
+
+sp_suid:
+ SQL_SYM SECURITY_SYM DEFINER_SYM
+ {
+ Lex->sp_chistics.suid= SP_IS_SUID;
+ }
+ | SQL_SYM SECURITY_SYM INVOKER_SYM
+ {
+ Lex->sp_chistics.suid= SP_IS_NOT_SUID;
}
+ ;
+
+call:
+ CALL_SYM sp_name
+ {
+ LEX *lex = Lex;
+
+ lex->sql_command= SQLCOM_CALL;
+ lex->spname= $2;
+ lex->value_list.empty();
+ sp_add_used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE);
+ }
+ '(' sp_cparam_list ')' {}
+ ;
+
+/* CALL parameters */
+sp_cparam_list:
+ /* Empty */
+ | sp_cparams
+ ;
+
+sp_cparams:
+ sp_cparams ',' expr
+ {
+ Lex->value_list.push_back($3);
+ }
+ | expr
+ {
+ Lex->value_list.push_back($1);
+ }
+ ;
+
+/* Stored FUNCTION parameter declaration list */
+sp_fdparam_list:
+ /* Empty */
+ | sp_fdparams
+ ;
+
+sp_fdparams:
+ sp_fdparams ',' sp_fdparam
+ | sp_fdparam
+ ;
+
+sp_fdparam:
+ ident type
+ {
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+
+ if (spc->find_pvar(&$1, TRUE))
+ {
+ my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
+ YYABORT;
+ }
+ spc->push_pvar(&$1, (enum enum_field_types)$2, sp_param_in);
+ }
+ ;
+
+/* Stored PROCEDURE parameter declaration list */
+sp_pdparam_list:
+ /* Empty */
+ | sp_pdparams
+ ;
+
+sp_pdparams:
+ sp_pdparams ',' sp_pdparam
+ | sp_pdparam
+ ;
+
+sp_pdparam:
+ sp_opt_inout ident type
+ {
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+
+ if (spc->find_pvar(&$2, TRUE))
+ {
+ my_error(ER_SP_DUP_PARAM, MYF(0), $2.str);
+ YYABORT;
+ }
+ spc->push_pvar(&$2, (enum enum_field_types)$3,
+ (sp_param_mode_t)$1);
+ }
+ ;
+
+sp_opt_inout:
+ /* Empty */ { $$= sp_param_in; }
+ | IN_SYM { $$= sp_param_in; }
+ | OUT_SYM { $$= sp_param_out; }
+ | INOUT_SYM { $$= sp_param_inout; }
+ ;
+
+sp_proc_stmts:
+ /* Empty */ {}
+ | sp_proc_stmts sp_proc_stmt ';'
+ ;
+
+sp_proc_stmts1:
+ sp_proc_stmt ';' {}
+ | sp_proc_stmts1 sp_proc_stmt ';'
+ ;
+
+sp_decls:
+ /* Empty */
+ {
+ $$.vars= $$.conds= $$.hndlrs= $$.curs= 0;
+ }
+ | sp_decls sp_decl ';'
+ {
+ /* We check for declarations out of (standard) order this way
+ because letting the grammar rules reflect it caused tricky
+ shift/reduce conflicts with the wrong result. (And we get
+ better error handling this way.) */
+ if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs))
+ { /* Variable or condition following cursor or handler */
+ my_message(ER_SP_VARCOND_AFTER_CURSHNDLR,
+ ER(ER_SP_VARCOND_AFTER_CURSHNDLR), MYF(0));
+ YYABORT;
+ }
+ if ($2.curs && $1.hndlrs)
+ { /* Cursor following handler */
+ my_message(ER_SP_CURSOR_AFTER_HANDLER,
+ ER(ER_SP_CURSOR_AFTER_HANDLER), MYF(0));
+ YYABORT;
+ }
+ $$.vars= $1.vars + $2.vars;
+ $$.conds= $1.conds + $2.conds;
+ $$.hndlrs= $1.hndlrs + $2.hndlrs;
+ $$.curs= $1.curs + $2.curs;
+ }
+ ;
+
+sp_decl:
+ DECLARE_SYM sp_decl_idents type
+ { Lex->sphead->reset_lex(YYTHD); }
+ sp_opt_default
+ {
+ LEX *lex= Lex;
+ sp_pcontext *ctx= lex->spcont;
+ uint max= ctx->context_pvars();
+ enum enum_field_types type= (enum enum_field_types)$3;
+ Item *it= $5;
+ bool has_default= (it != NULL);
+
+ for (uint i = max-$2 ; i < max ; i++)
+ {
+ sp_instr_set *in;
+
+ ctx->set_type(i, type);
+ if (! has_default)
+ it= new Item_null(); /* QQ Set to the type with null_value? */
+ in = new sp_instr_set(lex->sphead->instructions(),
+ ctx,
+ ctx->pvar_context2index(i),
+ it, type, lex,
+ (i == max - 1));
+
+ /*
+ The last instruction is assigned to be responsible for
+ freeing LEX.
+ */
+ lex->sphead->add_instr(in);
+ ctx->set_default(i, it);
+ }
+ lex->sphead->restore_lex(YYTHD);
+ $$.vars= $2;
+ $$.conds= $$.hndlrs= $$.curs= 0;
+ }
+ | DECLARE_SYM ident CONDITION_SYM FOR_SYM sp_cond
+ {
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+
+ if (spc->find_cond(&$2, TRUE))
+ {
+ my_error(ER_SP_DUP_COND, MYF(0), $2.str);
+ YYABORT;
+ }
+ YYTHD->lex->spcont->push_cond(&$2, $5);
+ $$.vars= $$.hndlrs= $$.curs= 0;
+ $$.conds= 1;
+ }
+ | DECLARE_SYM sp_handler_type HANDLER_SYM FOR_SYM
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ sp_instr_hpush_jump *i=
+ new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
+ ctx->current_pvars());
+
+ sp->add_instr(i);
+ sp->push_backpatch(i, ctx->push_label((char *)"", 0));
+ sp->m_flags|= sp_head::IN_HANDLER;
+ }
+ sp_hcond_list sp_proc_stmt
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */
+ sp_instr_hreturn *i;
+
+ if ($2 == SP_HANDLER_CONTINUE)
+ {
+ i= new sp_instr_hreturn(sp->instructions(), ctx,
+ ctx->current_pvars());
+ sp->add_instr(i);
+ }
+ else
+ { /* EXIT or UNDO handler, just jump to the end of the block */
+ i= new sp_instr_hreturn(sp->instructions(), ctx, 0);
+
+ sp->add_instr(i);
+ sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
+ }
+ lex->sphead->backpatch(hlab);
+ sp->m_flags&= ~sp_head::IN_HANDLER;
+ $$.vars= $$.conds= $$.curs= 0;
+ $$.hndlrs= $6;
+ ctx->add_handlers($6);
+ }
+ | DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ uint offp;
+ sp_instr_cpush *i;
+
+ if (ctx->find_cursor(&$2, &offp, TRUE))
+ {
+ my_error(ER_SP_DUP_CURS, MYF(0), $2.str);
+ delete $5;
+ YYABORT;
+ }
+ i= new sp_instr_cpush(sp->instructions(), ctx, $5);
+ sp->add_instr(i);
+ ctx->push_cursor(&$2);
+ $$.vars= $$.conds= $$.hndlrs= 0;
+ $$.curs= 1;
+ }
+ ;
+
+sp_cursor_stmt:
+ {
+ Lex->sphead->reset_lex(YYTHD);
+
+ /* We use statement here just be able to get a better
+ error message. Using 'select' works too, but will then
+ result in a generic "syntax error" if a non-select
+ statement is given. */
+ }
+ statement
+ {
+ LEX *lex= Lex;
+
+ if (lex->sql_command != SQLCOM_SELECT)
+ {
+ my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY),
+ MYF(0));
+ YYABORT;
+ }
+ if (lex->result)
+ {
+ my_message(ER_SP_BAD_CURSOR_SELECT, ER(ER_SP_BAD_CURSOR_SELECT),
+ MYF(0));
+ YYABORT;
+ }
+ lex->sp_lex_in_use= TRUE;
+ $$= lex;
+ lex->sphead->restore_lex(YYTHD);
+ }
+ ;
+
+sp_handler_type:
+ EXIT_SYM { $$= SP_HANDLER_EXIT; }
+ | CONTINUE_SYM { $$= SP_HANDLER_CONTINUE; }
+/* | UNDO_SYM { QQ No yet } */
+ ;
+
+sp_hcond_list:
+ sp_hcond
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+
+ if (ctx->find_handler($1))
+ {
+ my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0));
+ YYABORT;
+ }
+ else
+ {
+ sp_instr_hpush_jump *i=
+ (sp_instr_hpush_jump *)sp->last_instruction();
+
+ i->add_condition($1);
+ ctx->push_handler($1);
+ $$= 1;
+ }
+ }
+ | sp_hcond_list ',' sp_hcond
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+
+ if (ctx->find_handler($3))
+ {
+ my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0));
+ YYABORT;
+ }
+ else
+ {
+ sp_instr_hpush_jump *i=
+ (sp_instr_hpush_jump *)sp->last_instruction();
+
+ i->add_condition($3);
+ ctx->push_handler($3);
+ $$= $1 + 1;
+ }
+ }
+ ;
+
+sp_cond:
+ ulong_num
+ { /* mysql errno */
+ $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
+ $$->type= sp_cond_type_t::number;
+ $$->mysqlerr= $1;
+ }
+ | SQLSTATE_SYM opt_value TEXT_STRING_literal
+ { /* SQLSTATE */
+ if (!sp_cond_check(&$3))
+ {
+ my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str);
+ YYABORT;
+ }
+ $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
+ $$->type= sp_cond_type_t::state;
+ memcpy($$->sqlstate, $3.str, 5);
+ $$->sqlstate[5]= '\0';
+ }
+ ;
+
+opt_value:
+ /* Empty */ {}
+ | VALUE_SYM {}
+ ;
+
+sp_hcond:
+ sp_cond
+ {
+ $$= $1;
+ }
+ | ident /* CONDITION name */
+ {
+ $$= Lex->spcont->find_cond(&$1);
+ if ($$ == NULL)
+ {
+ my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
+ YYABORT;
+ }
+ }
+ | SQLWARNING_SYM /* SQLSTATEs 01??? */
+ {
+ $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
+ $$->type= sp_cond_type_t::warning;
+ }
+ | not FOUND_SYM /* SQLSTATEs 02??? */
+ {
+ $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
+ $$->type= sp_cond_type_t::notfound;
+ }
+ | SQLEXCEPTION_SYM /* All other SQLSTATEs */
+ {
+ $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
+ $$->type= sp_cond_type_t::exception;
+ }
+ ;
+
+sp_decl_idents:
+ ident
+ {
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+
+ if (spc->find_pvar(&$1, TRUE))
+ {
+ my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
+ YYABORT;
+ }
+ spc->push_pvar(&$1, (enum_field_types)0, sp_param_in);
+ $$= 1;
+ }
+ | sp_decl_idents ',' ident
+ {
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+
+ if (spc->find_pvar(&$3, TRUE))
+ {
+ my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
+ YYABORT;
+ }
+ spc->push_pvar(&$3, (enum_field_types)0, sp_param_in);
+ $$= $1 + 1;
+ }
+ ;
+
+sp_opt_default:
+ /* Empty */ { $$ = NULL; }
+ | DEFAULT expr { $$ = $2; }
+ ;
+
+sp_proc_stmt:
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->reset_lex(YYTHD);
+ lex->sphead->m_tmp_query= lex->tok_start;
+ }
+ statement
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+
+ sp->m_flags|= sp_get_flags_for_command(lex);
+ if (lex->sql_command == SQLCOM_CHANGE_DB)
+ { /* "USE db" doesn't work in a procedure */
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "USE");
+ YYABORT;
+ }
+ /*
+ Don't add an instruction for SET statements, since all
+ instructions for them were already added during processing
+ of "set" rule.
+ */
+ DBUG_ASSERT(lex->sql_command != SQLCOM_SET_OPTION ||
+ lex->var_list.is_empty());
+ if (lex->sql_command != SQLCOM_SET_OPTION)
+ {
+ sp_instr_stmt *i=new sp_instr_stmt(sp->instructions(),
+ lex->spcont, lex);
+
+ /* Extract the query statement from the tokenizer:
+ The end is either lex->tok_end or tok->ptr. */
+ if (lex->ptr - lex->tok_end > 1)
+ i->m_query.length= lex->ptr - sp->m_tmp_query;
+ else
+ i->m_query.length= lex->tok_end - sp->m_tmp_query;
+ i->m_query.str= strmake_root(YYTHD->mem_root,
+ (char *)sp->m_tmp_query,
+ i->m_query.length);
+ sp->add_instr(i);
+ }
+ sp->restore_lex(YYTHD);
+ }
+ | RETURN_SYM
+ { Lex->sphead->reset_lex(YYTHD); }
+ expr
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+
+ if (sp->m_type == TYPE_ENUM_PROCEDURE)
+ {
+ my_message(ER_SP_BADRETURN, ER(ER_SP_BADRETURN), MYF(0));
+ YYABORT;
+ }
+ else
+ {
+ sp_instr_freturn *i;
+
+ i= new sp_instr_freturn(sp->instructions(), lex->spcont,
+ $3, sp->m_returns, lex);
+ sp->add_instr(i);
+ sp->m_flags|= sp_head::HAS_RETURN;
+ }
+ sp->restore_lex(YYTHD);
+ }
+ | IF sp_if END IF {}
+ | CASE_SYM WHEN_SYM
+ {
+ Lex->sphead->m_flags&= ~sp_head::IN_SIMPLE_CASE;
+ }
+ sp_case END CASE_SYM {}
+ | CASE_SYM
+ { Lex->sphead->reset_lex(YYTHD); }
+ expr WHEN_SYM
+ {
+ /* We "fake" this by using an anonymous variable which we
+ set to the expression. Note that all WHENs are evaluate
+ at the same frame level, so we then know that it's the
+ top-most variable in the frame. */
+ LEX *lex= Lex;
+ uint offset= lex->spcont->current_pvars();
+ sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(),
+ lex->spcont, offset, $3,
+ MYSQL_TYPE_STRING, lex, TRUE);
+ LEX_STRING dummy={(char*)"", 0};
+
+ lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in);
+ lex->sphead->add_instr(i);
+ lex->sphead->m_flags|= sp_head::IN_SIMPLE_CASE;
+ lex->sphead->restore_lex(YYTHD);
+ }
+ sp_case END CASE_SYM
+ {
+ Lex->spcont->pop_pvar();
+ }
+ | sp_labeled_control
+ {}
+ | { /* Unlabeled controls get a secret label. */
+ LEX *lex= Lex;
+
+ lex->spcont->push_label((char *)"", lex->sphead->instructions());
+ }
+ sp_unlabeled_control
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->backpatch(lex->spcont->pop_label());
+ }
+ | LEAVE_SYM label_ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp = lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *lab= ctx->find_label($2.str);
+
+ if (! lab)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str);
+ YYABORT;
+ }
+ else
+ {
+ uint ip= sp->instructions();
+ sp_instr_jump *i;
+ sp_instr_hpop *ih;
+ sp_instr_cpop *ic;
+
+ ih= new sp_instr_hpop(ip++, ctx, 0);
+ sp->push_backpatch(ih, lab);
+ sp->add_instr(ih);
+ ic= new sp_instr_cpop(ip++, ctx, 0);
+ sp->push_backpatch(ic, lab);
+ sp->add_instr(ic);
+ i= new sp_instr_jump(ip, ctx);
+ sp->push_backpatch(i, lab); /* Jumping forward */
+ sp->add_instr(i);
+ }
+ }
+ | ITERATE_SYM label_ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *lab= ctx->find_label($2.str);
+
+ if (! lab || lab->type != SP_LAB_ITER)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str);
+ YYABORT;
+ }
+ else
+ {
+ sp_instr_jump *i;
+ uint ip= sp->instructions();
+ uint n;
+
+ n= ctx->diff_handlers(lab->ctx);
+ if (n)
+ sp->add_instr(new sp_instr_hpop(ip++, ctx, n));
+ n= ctx->diff_cursors(lab->ctx);
+ if (n)
+ sp->add_instr(new sp_instr_cpop(ip++, ctx, n));
+ i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
+ sp->add_instr(i);
+ }
+ }
+ | LABEL_SYM IDENT
+ {
+#ifdef SP_GOTO
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *lab= ctx->find_label($2.str);
+
+ if (lab)
+ {
+ my_error(ER_SP_LABEL_REDEFINE, MYF(0), $2.str);
+ YYABORT;
+ }
+ else
+ {
+ lab= ctx->push_label($2.str, sp->instructions());
+ lab->type= SP_LAB_GOTO;
+ lab->ctx= ctx;
+ sp->backpatch(lab);
+ }
+#else
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+#endif
+ }
+ | GOTO_SYM IDENT
+ {
+#ifdef SP_GOTO
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ uint ip= lex->sphead->instructions();
+ sp_label_t *lab;
+ sp_instr_jump *i;
+ sp_instr_hpop *ih;
+ sp_instr_cpop *ic;
+
+ if (sp->m_in_handler)
+ {
+ my_message(ER_SP_GOTO_IN_HNDLR, ER(ER_SP_GOTO_IN_HNDLR), MYF(0));
+ YYABORT;
+ }
+ lab= ctx->find_label($2.str);
+ if (! lab)
+ {
+ lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t));
+ lab->name= $2.str;
+ lab->ip= 0;
+ lab->type= SP_LAB_REF;
+ lab->ctx= ctx;
+
+ ih= new sp_instr_hpop(ip++, ctx, 0);
+ sp->push_backpatch(ih, lab);
+ sp->add_instr(ih);
+ ic= new sp_instr_cpop(ip++, ctx, 0);
+ sp->add_instr(ic);
+ sp->push_backpatch(ic, lab);
+ i= new sp_instr_jump(ip, ctx);
+ sp->push_backpatch(i, lab); /* Jumping forward */
+ sp->add_instr(i);
+ }
+ else
+ {
+ uint n;
+
+ n= ctx->diff_handlers(lab->ctx);
+ if (n)
+ {
+ ih= new sp_instr_hpop(ip++, ctx, n);
+ sp->add_instr(ih);
+ }
+ n= ctx->diff_cursors(lab->ctx);
+ if (n)
+ {
+ ic= new sp_instr_cpop(ip++, ctx, n);
+ sp->add_instr(ic);
+ }
+ i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
+ sp->add_instr(i);
+ }
+#else
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+#endif
+ }
+ | OPEN_SYM ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ uint offset;
+ sp_instr_copen *i;
+
+ if (! lex->spcont->find_cursor(&$2, &offset))
+ {
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
+ YYABORT;
+ }
+ i= new sp_instr_copen(sp->instructions(), lex->spcont, offset);
+ sp->add_instr(i);
+ }
+ | FETCH_SYM sp_opt_fetch_noise ident INTO
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ uint offset;
+ sp_instr_cfetch *i;
+
+ if (! lex->spcont->find_cursor(&$3, &offset))
+ {
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $3.str);
+ YYABORT;
+ }
+ i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
+ sp->add_instr(i);
+ }
+ sp_fetch_list
+ { }
+ | CLOSE_SYM ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ uint offset;
+ sp_instr_cclose *i;
+
+ if (! lex->spcont->find_cursor(&$2, &offset))
+ {
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
+ YYABORT;
+ }
+ i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset);
+ sp->add_instr(i);
+ }
+ ;
+
+sp_opt_fetch_noise:
+ /* Empty */
+ | NEXT_SYM FROM
+ | FROM
+ ;
+
+sp_fetch_list:
+ ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *spc= lex->spcont;
+ sp_pvar_t *spv;
+
+ if (!spc || !(spv = spc->find_pvar(&$1)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
+ YYABORT;
+ }
+ else
+ {
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+
+ i->add_to_varlist(spv);
+ }
+ }
+ |
+ sp_fetch_list ',' ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *spc= lex->spcont;
+ sp_pvar_t *spv;
+
+ if (!spc || !(spv = spc->find_pvar(&$3)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
+ YYABORT;
+ }
+ else
+ {
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+
+ i->add_to_varlist(spv);
+ }
+ }
+ ;
+
+sp_if:
+ { Lex->sphead->reset_lex(YYTHD); }
+ expr THEN_SYM
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ uint ip= sp->instructions();
+ sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx,
+ $2, lex);
+
+ sp->push_backpatch(i, ctx->push_label((char *)"", 0));
+ sp->add_instr(i);
+ sp->restore_lex(YYTHD);
+ }
+ sp_proc_stmts1
+ {
+ sp_head *sp= Lex->sphead;
+ sp_pcontext *ctx= Lex->spcont;
+ uint ip= sp->instructions();
+ sp_instr_jump *i = new sp_instr_jump(ip, ctx);
+
+ sp->add_instr(i);
+ sp->backpatch(ctx->pop_label());
+ sp->push_backpatch(i, ctx->push_label((char *)"", 0));
+ }
+ sp_elseifs
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->backpatch(lex->spcont->pop_label());
+ }
+ ;
+
+sp_elseifs:
+ /* Empty */
+ | ELSEIF_SYM sp_if
+ | ELSE sp_proc_stmts1
+ ;
+
+sp_case:
+ { Lex->sphead->reset_lex(YYTHD); }
+ expr THEN_SYM
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= Lex->spcont;
+ uint ip= sp->instructions();
+ sp_instr_jump_if_not *i;
+
+ if (! (sp->m_flags & sp_head::IN_SIMPLE_CASE))
+ i= new sp_instr_jump_if_not(ip, ctx, $2, lex);
+ else
+ { /* Simple case: <caseval> = <whenval> */
+ LEX_STRING ivar;
+
+ ivar.str= (char *)"_tmp_";
+ ivar.length= 5;
+ Item *var= (Item*) new Item_splocal(ivar,
+ ctx->current_pvars()-1);
+ Item *expr= new Item_func_eq(var, $2);
+
+ i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
+ lex->variables_used= 1;
+ }
+ sp->push_backpatch(i, ctx->push_label((char *)"", 0));
+ sp->add_instr(i);
+ sp->restore_lex(YYTHD);
+ }
+ sp_proc_stmts1
+ {
+ sp_head *sp= Lex->sphead;
+ sp_pcontext *ctx= Lex->spcont;
+ uint ip= sp->instructions();
+ sp_instr_jump *i = new sp_instr_jump(ip, ctx);
+
+ sp->add_instr(i);
+ sp->backpatch(ctx->pop_label());
+ sp->push_backpatch(i, ctx->push_label((char *)"", 0));
+ }
+ sp_whens
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->backpatch(lex->spcont->pop_label());
+ }
+ ;
+
+sp_whens:
+ /* Empty */
+ {
+ sp_head *sp= Lex->sphead;
+ uint ip= sp->instructions();
+ sp_instr_error *i= new sp_instr_error(ip, Lex->spcont,
+ ER_SP_CASE_NOT_FOUND);
+
+ sp->add_instr(i);
+ }
+ | ELSE sp_proc_stmts1 {}
+ | WHEN_SYM sp_case {}
+ ;
+
+sp_labeled_control:
+ label_ident ':'
+ {
+ LEX *lex= Lex;
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *lab= ctx->find_label($1.str);
+
+ if (lab)
+ {
+ my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str);
+ YYABORT;
+ }
+ else
+ {
+ lab= lex->spcont->push_label($1.str,
+ lex->sphead->instructions());
+ lab->type= SP_LAB_ITER;
+ }
+ }
+ sp_unlabeled_control sp_opt_label
+ {
+ LEX *lex= Lex;
+
+ if ($5.str)
+ {
+ sp_label_t *lab= lex->spcont->find_label($5.str);
+
+ if (!lab ||
+ my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
+ {
+ my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
+ YYABORT;
+ }
+ }
+ lex->sphead->backpatch(lex->spcont->pop_label());
+ }
+ ;
+
+sp_opt_label:
+ /* Empty */ { $$= null_lex_str; }
+ | label_ident { $$= $1; }
+ ;
+
+sp_unlabeled_control:
+ BEGIN_SYM
+ { /* QQ This is just a dummy for grouping declarations and statements
+ together. No [[NOT] ATOMIC] yet, and we need to figure out how
+ make it coexist with the existing BEGIN COMMIT/ROLLBACK. */
+ LEX *lex= Lex;
+ sp_label_t *lab= lex->spcont->last_label();
+
+ lab->type= SP_LAB_BEGIN;
+ lex->spcont= lex->spcont->push_context();
+ }
+ sp_decls
+ sp_proc_stmts
+ END
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+
+ sp->backpatch(ctx->last_label()); /* We always have a label */
+ if ($3.hndlrs)
+ sp->add_instr(new sp_instr_hpop(sp->instructions(), ctx,
+ $3.hndlrs));
+ if ($3.curs)
+ sp->add_instr(new sp_instr_cpop(sp->instructions(), ctx,
+ $3.curs));
+ lex->spcont= ctx->pop_context();
+ }
+ | LOOP_SYM
+ sp_proc_stmts1 END LOOP_SYM
+ {
+ LEX *lex= Lex;
+ uint ip= lex->sphead->instructions();
+ sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
+
+ lex->sphead->add_instr(i);
+ }
+ | WHILE_SYM
+ { Lex->sphead->reset_lex(YYTHD); }
+ expr DO_SYM
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ uint ip= sp->instructions();
+ sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
+ $3, lex);
+
+ /* Jumping forward */
+ sp->push_backpatch(i, lex->spcont->last_label());
+ sp->add_instr(i);
+ sp->restore_lex(YYTHD);
+ }
+ sp_proc_stmts1 END WHILE_SYM
+ {
+ LEX *lex= Lex;
+ uint ip= lex->sphead->instructions();
+ sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
+
+ lex->sphead->add_instr(i);
+ }
+ | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM
+ { Lex->sphead->reset_lex(YYTHD); }
+ expr END REPEAT_SYM
+ {
+ LEX *lex= Lex;
+ uint ip= lex->sphead->instructions();
+ sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
+ $5, lab->ip,
+ lex);
+ lex->sphead->add_instr(i);
+ lex->sphead->restore_lex(YYTHD);
+ }
+ ;
+
+trg_action_time:
+ BEFORE_SYM
+ { Lex->trg_chistics.action_time= TRG_ACTION_BEFORE; }
+ | AFTER_SYM
+ { Lex->trg_chistics.action_time= TRG_ACTION_AFTER; }
+ ;
+
+trg_event:
+ INSERT
+ { Lex->trg_chistics.event= TRG_EVENT_INSERT; }
+ | UPDATE_SYM
+ { Lex->trg_chistics.event= TRG_EVENT_UPDATE; }
+ | DELETE_SYM
+ { Lex->trg_chistics.event= TRG_EVENT_DELETE; }
;
create2:
@@ -1117,6 +2570,10 @@ create_select:
lex->sql_command= SQLCOM_INSERT_SELECT;
else if (lex->sql_command == SQLCOM_REPLACE)
lex->sql_command= SQLCOM_REPLACE_SELECT;
+ /*
+ The following work only with the local list, the global list
+ is created correctly in this case
+ */
lex->current_select->table_list.save_and_clear(&lex->save_list);
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
@@ -1126,7 +2583,13 @@ create_select:
Select->parsing_place= NO_MATTER;
}
opt_select_from
- { Lex->current_select->table_list.push_front(&Lex->save_list); }
+ {
+ /*
+ The following work only with the local list, the global list
+ is created correctly in this case
+ */
+ Lex->current_select->table_list.push_front(&Lex->save_list);
+ }
;
opt_as:
@@ -1158,7 +2621,7 @@ table_option:
opt_if_not_exists:
/* empty */ { $$= 0; }
- | IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
+ | IF not EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
opt_create_table_options:
/* empty */
@@ -1174,22 +2637,41 @@ create_table_options:
| create_table_option ',' create_table_options;
create_table_option:
- ENGINE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; }
- | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine"); }
+ ENGINE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; }
+ | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine"); Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; }
| MAX_ROWS opt_equal ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;}
| MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
- | AVG_ROW_LENGTH opt_equal ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
- | PASSWORD opt_equal TEXT_STRING_sys { Lex->create_info.password=$3.str; }
- | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3.str; }
+ | AVG_ROW_LENGTH opt_equal ulong_num { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
+ | PASSWORD opt_equal TEXT_STRING_sys { Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; }
+ | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; }
| AUTO_INC opt_equal ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
- | PACK_KEYS_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
- | PACK_KEYS_SYM opt_equal DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;}
- | CHECKSUM_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; }
- | DELAY_KEY_WRITE_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; }
- | ROW_FORMAT_SYM opt_equal row_types { Lex->create_info.row_type= $3; }
+ | PACK_KEYS_SYM opt_equal ulong_num
+ {
+ switch($3) {
+ case 0:
+ Lex->create_info.table_options|= HA_OPTION_NO_PACK_KEYS;
+ break;
+ case 1:
+ Lex->create_info.table_options|= HA_OPTION_PACK_KEYS;
+ break;
+ default:
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
+ }
+ | PACK_KEYS_SYM opt_equal DEFAULT
+ {
+ Lex->create_info.table_options&=
+ ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
+ Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
+ }
+ | CHECKSUM_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; }
+ | DELAY_KEY_WRITE_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE; }
+ | ROW_FORMAT_SYM opt_equal row_types { Lex->create_info.row_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT; }
| RAID_TYPE opt_equal raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
- | RAID_CHUNKS opt_equal ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
- | RAID_CHUNKSIZE opt_equal ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
+ | RAID_CHUNKS opt_equal ulong_num { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
+ | RAID_CHUNKSIZE opt_equal ulong_num { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;}
| UNION_SYM opt_equal '(' table_list ')'
{
/* Move the union list to the merge_list */
@@ -1197,18 +2679,21 @@ create_table_option:
TABLE_LIST *table_list= lex->select_lex.get_table_list();
lex->create_info.merge_list= lex->select_lex.table_list;
lex->create_info.merge_list.elements--;
- lex->create_info.merge_list.first= (byte*) (table_list->next);
+ lex->create_info.merge_list.first=
+ (byte*) (table_list->next_local);
lex->select_lex.table_list.elements=1;
- lex->select_lex.table_list.next= (byte**) &(table_list->next);
- table_list->next=0;
+ lex->select_lex.table_list.next=
+ (byte**) &(table_list->next_local);
+ table_list->next_local= 0;
lex->create_info.used_fields|= HA_CREATE_USED_UNION;
}
| default_charset
| default_collation
| 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_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; };
+ | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.data_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR; }
+ | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR; }
+ | CONNECTION_SYM opt_equal TEXT_STRING_sys { Lex->create_info.connect_string.str= $3.str; Lex->create_info.connect_string.length= $3.length; Lex->create_info.used_fields|= HA_CREATE_USED_CONNECTION; }
+ ;
default_charset:
opt_default charset opt_equal charset_name_or_default
@@ -1218,9 +2703,9 @@ default_charset:
cinfo->default_table_charset && $4 &&
!my_charset_same(cinfo->default_table_charset,$4))
{
- net_printf(YYTHD, ER_CONFLICTING_DECLARATIONS,
- "CHARACTER SET ", cinfo->default_table_charset->csname,
- "CHARACTER SET ", $4->csname);
+ my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
+ "CHARACTER SET ", cinfo->default_table_charset->csname,
+ "CHARACTER SET ", $4->csname);
YYABORT;
}
Lex->create_info.default_table_charset= $4;
@@ -1235,8 +2720,8 @@ default_collation:
cinfo->default_table_charset && $4 &&
!my_charset_same(cinfo->default_table_charset,$4))
{
- net_printf(YYTHD,ER_COLLATION_CHARSET_MISMATCH,
- $4->name, cinfo->default_table_charset->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $4->name, cinfo->default_table_charset->csname);
YYABORT;
}
Lex->create_info.default_table_charset= $4;
@@ -1248,7 +2733,7 @@ storage_engines:
{
$$ = ha_resolve_by_name($1.str,$1.length);
if ($$ == DB_TYPE_UNKNOWN) {
- net_printf(YYTHD, ER_UNKNOWN_STORAGE_ENGINE, $1.str);
+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
YYABORT;
}
};
@@ -1257,12 +2742,14 @@ row_types:
DEFAULT { $$= ROW_TYPE_DEFAULT; }
| FIXED_SYM { $$= ROW_TYPE_FIXED; }
| DYNAMIC_SYM { $$= ROW_TYPE_DYNAMIC; }
- | COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; };
+ | COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; }
+ | REDUNDANT_SYM { $$= ROW_TYPE_REDUNDANT; }
+ | COMPACT_SYM { $$= ROW_TYPE_COMPACT; };
raid_types:
RAID_STRIPED_SYM { $$= RAID_TYPE_0; }
| RAID_0_SYM { $$= RAID_TYPE_0; }
- | ULONG_NUM { $$=$1;};
+ | ulong_num { $$=$1;};
merge_insert_types:
NO_SYM { $$= MERGE_INSERT_DISABLED; }
@@ -1280,6 +2767,7 @@ udf_func_type:
udf_type:
STRING_SYM {$$ = (int) STRING_RESULT; }
| REAL {$$ = (int) REAL_RESULT; }
+ | DECIMAL_SYM {$$ = (int) DECIMAL_RESULT; }
| INT_SYM {$$ = (int) INT_RESULT; };
field_list:
@@ -1363,7 +2851,7 @@ field_spec:
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0;
lex->default_value= lex->on_update_value= 0;
- lex->comment=0;
+ lex->comment=null_lex_str;
lex->charset=NULL;
}
type opt_attribute
@@ -1373,7 +2861,7 @@ field_spec:
(enum enum_field_types) $3,
lex->length,lex->dec,lex->type,
lex->default_value, lex->on_update_value,
- lex->comment,
+ &lex->comment,
lex->change,&lex->interval_list,lex->charset,
lex->uint_geom_type))
YYABORT;
@@ -1383,8 +2871,10 @@ type:
int_type opt_len field_options { $$=$1; }
| real_type opt_precision field_options { $$=$1; }
| FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; }
- | BIT_SYM opt_len { Lex->length=(char*) "1";
- $$=FIELD_TYPE_TINY; }
+ | BIT_SYM { Lex->length= (char*) "1";
+ $$=FIELD_TYPE_BIT; }
+ | BIT_SYM '(' NUM ')' { Lex->length= $3.str;
+ $$=FIELD_TYPE_BIT; }
| BOOL_SYM { Lex->length=(char*) "1";
$$=FIELD_TYPE_TINY; }
| BOOLEAN_SYM { Lex->length=(char*) "1";
@@ -1393,10 +2883,10 @@ type:
$$=FIELD_TYPE_STRING; }
| char opt_binary { Lex->length=(char*) "1";
$$=FIELD_TYPE_STRING; }
- | nchar '(' NUM ')' { Lex->length=$3.str;
+ | nchar '(' NUM ')' opt_bin_mod { Lex->length=$3.str;
$$=FIELD_TYPE_STRING;
Lex->charset=national_charset_info; }
- | nchar { Lex->length=(char*) "1";
+ | nchar opt_bin_mod { Lex->length=(char*) "1";
$$=FIELD_TYPE_STRING;
Lex->charset=national_charset_info; }
| BINARY '(' NUM ')' { Lex->length=$3.str;
@@ -1406,13 +2896,13 @@ type:
Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_STRING; }
| varchar '(' NUM ')' opt_binary { Lex->length=$3.str;
- $$=FIELD_TYPE_VAR_STRING; }
- | nvarchar '(' NUM ')' { Lex->length=$3.str;
- $$=FIELD_TYPE_VAR_STRING;
+ $$= MYSQL_TYPE_VARCHAR; }
+ | nvarchar '(' NUM ')' opt_bin_mod { Lex->length=$3.str;
+ $$= MYSQL_TYPE_VARCHAR;
Lex->charset=national_charset_info; }
| VARBINARY '(' NUM ')' { Lex->length=$3.str;
Lex->charset=&my_charset_bin;
- $$=FIELD_TYPE_VAR_STRING; }
+ $$= MYSQL_TYPE_VARCHAR; }
| YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; }
| DATE_SYM { $$=FIELD_TYPE_DATE; }
| TIME_SYM { $$=FIELD_TYPE_TIME; }
@@ -1434,18 +2924,18 @@ type:
$$=FIELD_TYPE_TINY_BLOB; }
| BLOB_SYM opt_len { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_BLOB; }
- | spatial_type {
+ | spatial_type
+ {
#ifdef HAVE_SPATIAL
- Lex->charset=&my_charset_bin;
- Lex->uint_geom_type= (uint)$1;
- $$=FIELD_TYPE_GEOMETRY;
+ Lex->charset=&my_charset_bin;
+ Lex->uint_geom_type= (uint)$1;
+ $$=FIELD_TYPE_GEOMETRY;
#else
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- sym_group_geom.name,
- sym_group_geom.needed_define);
- YYABORT;
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
+ YYABORT;
#endif
- }
+ }
| MEDIUMBLOB { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_MEDIUM_BLOB; }
| LONGBLOB { Lex->charset=&my_charset_bin;
@@ -1458,11 +2948,11 @@ type:
| MEDIUMTEXT opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
| LONGTEXT opt_binary { $$=FIELD_TYPE_LONG_BLOB; }
| DECIMAL_SYM float_options field_options
- { $$=FIELD_TYPE_DECIMAL;}
+ { $$=FIELD_TYPE_NEWDECIMAL;}
| NUMERIC_SYM float_options field_options
- { $$=FIELD_TYPE_DECIMAL;}
+ { $$=FIELD_TYPE_NEWDECIMAL;}
| FIXED_SYM float_options field_options
- { $$=FIELD_TYPE_DECIMAL;}
+ { $$=FIELD_TYPE_NEWDECIMAL;}
| ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary
{ $$=FIELD_TYPE_ENUM; }
| SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary
@@ -1524,8 +3014,8 @@ real_type:
float_options:
- /* empty */ {}
- | '(' NUM ')' { Lex->length=$2.str; }
+ /* empty */ { Lex->dec=Lex->length= (char*)0; }
+ | '(' NUM ')' { Lex->length=$2.str; Lex->dec= (char*)0; }
| precision {};
precision:
@@ -1566,7 +3056,7 @@ opt_attribute_list:
attribute:
NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; }
- | NOT NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
+ | not NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
| ON UPDATE_SYM NOW_SYM optional_braces
{ Lex->on_update_value= new Item_func_now_local(); }
@@ -1595,14 +3085,13 @@ attribute:
lex->type|= UNIQUE_KEY_FLAG;
lex->alter_info.flags|= ALTER_ADD_INDEX;
}
- | COMMENT_SYM TEXT_STRING_sys { Lex->comment= &$2; }
- | BINARY { Lex->type|= BINCMP_FLAG; }
+ | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
| COLLATE_SYM collation_name
{
if (Lex->charset && !my_charset_same(Lex->charset,$2))
{
- net_printf(YYTHD,ER_COLLATION_CHARSET_MISMATCH,
- $2->name,Lex->charset->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $2->name,Lex->charset->csname);
YYABORT;
}
else
@@ -1627,7 +3116,7 @@ charset_name:
{
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))))
{
- net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,$1.str);
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
YYABORT;
}
}
@@ -1645,7 +3134,7 @@ old_or_new_charset_name:
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))) &&
!($$=get_old_charset_by_name($1.str)))
{
- net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,$1.str);
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
YYABORT;
}
}
@@ -1661,7 +3150,7 @@ collation_name:
{
if (!($$=get_charset_by_name($1.str,MYF(0))))
{
- net_printf(YYTHD,ER_UNKNOWN_COLLATION,$1.str);
+ my_error(ER_UNKNOWN_COLLATION, MYF(0), $1.str);
YYABORT;
}
};
@@ -1681,13 +3170,33 @@ opt_default:
opt_binary:
/* empty */ { Lex->charset=NULL; }
- | ASCII_SYM { Lex->charset=&my_charset_latin1; }
+ | ASCII_SYM opt_bin_mod { Lex->charset=&my_charset_latin1; }
| BYTE_SYM { Lex->charset=&my_charset_bin; }
+ | UNICODE_SYM opt_bin_mod
+ {
+ if (!(Lex->charset=get_charset_by_csname("ucs2",
+ MY_CS_PRIMARY,MYF(0))))
+ {
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
+ YYABORT;
+ }
+ }
+ | charset charset_name opt_bin_mod { Lex->charset=$2; }
+ | BINARY opt_bin_charset { Lex->type|= BINCMP_FLAG; };
+
+opt_bin_mod:
+ /* empty */ { }
+ | BINARY { Lex->type|= BINCMP_FLAG; };
+
+opt_bin_charset:
+ /* empty */ { }
+ | ASCII_SYM { Lex->charset=&my_charset_latin1; }
| UNICODE_SYM
{
- if (!(Lex->charset=get_charset_by_csname("ucs2",MY_CS_PRIMARY,MYF(0))))
+ if (!(Lex->charset=get_charset_by_csname("ucs2",
+ MY_CS_PRIMARY,MYF(0))))
{
- net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,"ucs2");
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
YYABORT;
}
}
@@ -1749,8 +3258,8 @@ key_type:
#ifdef HAVE_SPATIAL
$$= Key::SPATIAL;
#else
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
};
@@ -1782,8 +3291,8 @@ opt_unique_or_fulltext:
#ifdef HAVE_SPATIAL
$$= Key::SPATIAL;
#else
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
}
@@ -1811,14 +3320,10 @@ key_part:
| ident '(' NUM ')'
{
int key_part_len= atoi($3.str);
-#if MYSQL_VERSION_ID < 50000
if (!key_part_len)
{
- my_printf_error(ER_UNKNOWN_ERROR,
- "Key part '%s' length cannot be 0",
- MYF(0), $1.str);
+ my_error(ER_KEY_PART_0, MYF(0), $1.str);
}
-#endif
$$=new key_part_spec($1.str,(uint) key_part_len);
};
@@ -1827,8 +3332,8 @@ opt_ident:
| field_ident { $$=$1.str; };
opt_component:
- /* empty */ { $$.str= 0; $$.length= 0; }
- | '.' ident { $$=$2; };
+ /* empty */ { $$= null_lex_str; }
+ | '.' ident { $$= $2; };
string_list:
text_string { Lex->interval_list.push_back($1); }
@@ -1843,6 +3348,11 @@ alter:
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
lex->sql_command= SQLCOM_ALTER_TABLE;
lex->name= 0;
lex->duplicates= DUP_ERROR;
@@ -1858,8 +3368,7 @@ alter:
lex->create_info.db_type= DB_TYPE_DEFAULT;
lex->create_info.default_table_charset= NULL;
lex->create_info.row_type= ROW_TYPE_NOT_USED;
- lex->alter_info.reset();
- lex->alter_info.is_simple= 1;
+ lex->alter_info.reset();
lex->alter_info.flags= 0;
}
alter_list
@@ -1874,14 +3383,60 @@ alter:
LEX *lex=Lex;
lex->sql_command=SQLCOM_ALTER_DB;
lex->name= $3;
- };
+ }
+ | ALTER PROCEDURE sp_name
+ {
+ LEX *lex= Lex;
+ if (lex->sphead)
+ {
+ my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
+ YYABORT;
+ }
+ bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+ }
+ sp_a_chistics
+ {
+ LEX *lex=Lex;
+
+ lex->sql_command= SQLCOM_ALTER_PROCEDURE;
+ lex->spname= $3;
+ }
+ | ALTER FUNCTION_SYM sp_name
+ {
+ LEX *lex= Lex;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
+ YYABORT;
+ }
+ bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+ }
+ sp_a_chistics
+ {
+ LEX *lex=Lex;
+
+ lex->sql_command= SQLCOM_ALTER_FUNCTION;
+ lex->spname= $3;
+ }
+ | ALTER algorithm view_user view_suid VIEW_SYM table_ident
+ {
+ THD *thd= YYTHD;
+ LEX *lex= thd->lex;
+ lex->sql_command= SQLCOM_CREATE_VIEW;
+ lex->create_view_mode= VIEW_ALTER;
+ /* first table in list is target VIEW name */
+ lex->select_lex.add_table_to_list(thd, $6, NULL, 0);
+ }
+ opt_view_list AS select_view_init check_option
+ {}
+ ;
ident_or_empty:
/* empty */ { $$= 0; }
| ident { $$= $1.str; };
-
alter_list:
| DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; }
| IMPORT TABLESPACE { Lex->alter_info.tablespace_op= IMPORT_TABLESPACE; }
@@ -1889,27 +3444,27 @@ alter_list:
| alter_list ',' alter_list_item;
add_column:
- ADD opt_column
+ ADD opt_column
{
LEX *lex=Lex;
- lex->change=0;
- lex->alter_info.flags|= ALTER_ADD_COLUMN;
+ lex->change=0;
+ lex->alter_info.flags|= ALTER_ADD_COLUMN;
};
alter_list_item:
- add_column column_def opt_place { Lex->alter_info.is_simple= 0; }
- | ADD key_def
- {
- LEX *lex=Lex;
- lex->alter_info.is_simple= 0;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ add_column column_def opt_place { }
+ | ADD key_def
+ {
+ Lex->alter_info.flags|= ALTER_ADD_INDEX;
}
- | add_column '(' field_list ')' { Lex->alter_info.is_simple= 0; }
+ | add_column '(' field_list ')'
+ {
+ Lex->alter_info.flags|= ALTER_ADD_COLUMN | ALTER_ADD_INDEX;
+ }
| CHANGE opt_column field_ident
{
LEX *lex=Lex;
- lex->change= $3.str;
- lex->alter_info.is_simple= 0;
+ lex->change= $3.str;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
}
field_spec opt_place
@@ -1918,9 +3473,8 @@ alter_list_item:
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0;
lex->default_value= lex->on_update_value= 0;
- lex->comment=0;
+ lex->comment=null_lex_str;
lex->charset= NULL;
- lex->alter_info.is_simple= 0;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
}
type opt_attribute
@@ -1930,7 +3484,7 @@ alter_list_item:
(enum enum_field_types) $5,
lex->length,lex->dec,lex->type,
lex->default_value, lex->on_update_value,
- lex->comment,
+ &lex->comment,
$3.str, &lex->interval_list, lex->charset,
lex->uint_geom_type))
YYABORT;
@@ -1940,17 +3494,18 @@ alter_list_item:
{
LEX *lex=Lex;
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
- $3.str));
- lex->alter_info.is_simple= 0;
+ $3.str));
lex->alter_info.flags|= ALTER_DROP_COLUMN;
}
- | DROP FOREIGN KEY_SYM opt_ident { Lex->alter_info.is_simple= 0; }
+ | DROP FOREIGN KEY_SYM opt_ident
+ {
+ Lex->alter_info.flags|= ALTER_DROP_INDEX;
+ }
| DROP PRIMARY_SYM KEY_SYM
{
LEX *lex=Lex;
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
primary_key_name));
- lex->alter_info.is_simple= 0;
lex->alter_info.flags|= ALTER_DROP_INDEX;
}
| DROP key_or_index field_ident
@@ -1958,25 +3513,32 @@ alter_list_item:
LEX *lex=Lex;
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str));
- lex->alter_info.is_simple= 0;
lex->alter_info.flags|= ALTER_DROP_INDEX;
}
- | DISABLE_SYM KEYS { Lex->alter_info.keys_onoff= DISABLE; }
- | ENABLE_SYM KEYS { Lex->alter_info.keys_onoff= ENABLE; }
+ | DISABLE_SYM KEYS
+ {
+ LEX *lex=Lex;
+ lex->alter_info.keys_onoff= DISABLE;
+ lex->alter_info.flags|= ALTER_KEYS_ONOFF;
+ }
+ | ENABLE_SYM KEYS
+ {
+ LEX *lex=Lex;
+ lex->alter_info.keys_onoff= ENABLE;
+ lex->alter_info.flags|= ALTER_KEYS_ONOFF;
+ }
| ALTER opt_column field_ident SET DEFAULT signed_literal
{
LEX *lex=Lex;
lex->alter_info.alter_list.push_back(new Alter_column($3.str,$6));
- lex->alter_info.is_simple= 0;
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
}
| ALTER opt_column field_ident DROP DEFAULT
{
LEX *lex=Lex;
lex->alter_info.alter_list.push_back(new Alter_column($3.str,
(Item*) 0));
- lex->alter_info.is_simple= 0;
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
}
| RENAME opt_to table_ident
{
@@ -1986,7 +3548,7 @@ alter_list_item:
if (check_table_name($3->table.str,$3->table.length) ||
$3->db.str && check_db_name($3->db.str))
{
- net_printf(lex->thd,ER_WRONG_TABLE_NAME,$3->table.str);
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
YYABORT;
}
lex->alter_info.flags|= ALTER_RENAME;
@@ -2001,27 +3563,29 @@ alter_list_item:
$5= $5 ? $5 : $4;
if (!my_charset_same($4,$5))
{
- net_printf(YYTHD,ER_COLLATION_CHARSET_MISMATCH,
- $5->name,$4->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $5->name, $4->csname);
YYABORT;
}
LEX *lex= Lex;
- lex->create_info.table_charset=
+ lex->create_info.table_charset=
lex->create_info.default_table_charset= $5;
lex->create_info.used_fields|= (HA_CREATE_USED_CHARSET |
HA_CREATE_USED_DEFAULT_CHARSET);
- lex->alter_info.is_simple= 0;
+ lex->alter_info.flags|= ALTER_CONVERT;
}
- | create_table_options_space_separated
+ | create_table_options_space_separated
{
LEX *lex=Lex;
- lex->alter_info.is_simple= 0;
lex->alter_info.flags|= ALTER_OPTIONS;
}
- | order_clause
+ | FORCE_SYM
+ {
+ Lex->alter_info.flags|= ALTER_FORCE;
+ }
+ | order_clause
{
LEX *lex=Lex;
- lex->alter_info.is_simple= 0;
lex->alter_info.flags|= ALTER_ORDER;
};
@@ -2035,9 +3599,10 @@ opt_ignore:
;
opt_restrict:
- /* empty */ {}
- | RESTRICT {}
- | CASCADE {};
+ /* empty */ { Lex->drop_mode= DROP_DEFAULT; }
+ | RESTRICT { Lex->drop_mode= DROP_RESTRICT; }
+ | CASCADE { Lex->drop_mode= DROP_CASCADE; }
+ ;
opt_place:
/* empty */ {}
@@ -2055,7 +3620,7 @@ opt_to:
*/
slave:
- START_SYM SLAVE slave_thread_opts
+ START_SYM SLAVE slave_thread_opts
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_SLAVE_START;
@@ -2095,8 +3660,14 @@ slave:
start:
START_SYM TRANSACTION_SYM start_transaction_opts
{
- Lex->sql_command = SQLCOM_BEGIN;
- Lex->start_transaction_opt= $3;
+ LEX *lex= Lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_BEGIN;
+ lex->start_transaction_opt= $3;
}
;
@@ -2135,7 +3706,8 @@ slave_until:
!((lex->mi.log_file_name && lex->mi.pos) ||
(lex->mi.relay_log_name && lex->mi.relay_log_pos)))
{
- send_error(lex->thd, ER_BAD_SLAVE_UNTIL_COND);
+ my_message(ER_BAD_SLAVE_UNTIL_COND,
+ ER(ER_BAD_SLAVE_UNTIL_COND), MYF(0));
YYABORT;
}
@@ -2223,9 +3795,15 @@ analyze:
check:
CHECK_SYM table_or_tables
{
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_CHECK;
- lex->check_opt.init();
+ LEX *lex=Lex;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK");
+ YYABORT;
+ }
+ lex->sql_command = SQLCOM_CHECK;
+ lex->check_opt.init();
}
table_list opt_mi_check_type
{}
@@ -2250,6 +3828,11 @@ optimize:
OPTIMIZE opt_no_write_to_binlog table_or_tables
{
LEX *lex=Lex;
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "OPTIMIZE TABLE");
+ YYABORT;
+ }
lex->sql_command = SQLCOM_OPTIMIZE;
lex->no_write_to_binlog= $2;
lex->check_opt.init();
@@ -2267,12 +3850,35 @@ opt_no_write_to_binlog:
rename:
RENAME table_or_tables
{
- Lex->sql_command=SQLCOM_RENAME_TABLE;
+ LEX *lex= Lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
+ lex->sql_command=SQLCOM_RENAME_TABLE;
}
table_to_table_list
{}
+ | RENAME USER clear_privileges rename_list
+ {
+ Lex->sql_command = SQLCOM_RENAME_USER;
+ }
;
+rename_list:
+ user TO_SYM user
+ {
+ if (Lex->users_list.push_back($1) || Lex->users_list.push_back($3))
+ YYABORT;
+ }
+ | rename_list ',' user TO_SYM user
+ {
+ if (Lex->users_list.push_back($3) || Lex->users_list.push_back($5))
+ YYABORT;
+ }
+ ;
+
table_to_table_list:
table_to_table
| table_to_table_list ',' table_to_table;
@@ -2294,7 +3900,7 @@ keycache:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE;
- lex->name_and_length= $5;
+ lex->ident= $5;
}
;
@@ -2382,7 +3988,6 @@ select:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT;
- lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
}
;
@@ -2392,6 +3997,18 @@ select_init:
|
'(' select_paren ')' union_opt;
+select_view_init:
+ SELECT_SYM remember_name select_init2
+ {
+ Lex->create_view_select_start= $2;
+ }
+ |
+ '(' remember_name select_paren ')' union_opt
+ {
+ Lex->create_view_select_start= $2;
+ }
+ ;
+
select_paren:
SELECT_SYM select_part2
{
@@ -2472,11 +4089,11 @@ select_options:
{
if (test_all_bits(Select->options, SELECT_ALL | SELECT_DISTINCT))
{
- net_printf(Lex->thd, ER_WRONG_USAGE, "ALL", "DISTINCT");
+ my_error(ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT");
YYABORT;
}
}
- ;
+ ;
select_option_list:
select_option_list select_option
@@ -2536,7 +4153,10 @@ select_item_list:
| '*'
{
THD *thd= YYTHD;
- if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
+ if (add_item_to_list(thd,
+ new Item_field(&thd->lex->current_select->
+ context,
+ NULL, NULL, "*")))
YYABORT;
(thd->lex->current_select->with_wild)++;
};
@@ -2548,9 +4168,16 @@ select_item:
if (add_item_to_list(YYTHD, $2))
YYABORT;
if ($4.str)
- $2->set_name($4.str,$4.length,system_charset_info);
- else if (!$2->name)
- $2->set_name($1,(uint) ($3 - $1), YYTHD->charset());
+ {
+ $2->set_name($4.str, $4.length, system_charset_info);
+ $2->is_autogenerated_name= FALSE;
+ }
+ else if (!$2->name) {
+ char *str = $1;
+ if (str[-1] == '`')
+ str--;
+ $2->set_name(str,(uint) ($3 - str), YYTHD->charset());
+ }
};
remember_name:
@@ -2564,7 +4191,7 @@ select_item2:
| expr { $$=$1; };
select_alias:
- /* empty */ { $$.str=0;}
+ /* empty */ { $$=null_lex_str;}
| AS ident { $$=$2; }
| AS TEXT_STRING_sys { $$=$2; }
| ident { $$=$1; }
@@ -2577,206 +4204,176 @@ optional_braces:
/* all possible expressions */
expr:
- expr_expr { $$= $1; }
- | simple_expr { $$= $1; }
- ;
-
-comp_op: EQ { $$ = &comp_eq_creator; }
- | GE { $$ = &comp_ge_creator; }
- | GT_SYM { $$ = &comp_gt_creator; }
- | LE { $$ = &comp_le_creator; }
- | LT { $$ = &comp_lt_creator; }
- | NE { $$ = &comp_ne_creator; }
+ bool_term { Select->expr_list.push_front(new List<Item>); }
+ bool_or_expr
+ {
+ List<Item> *list= Select->expr_list.pop();
+ if (list->elements)
+ {
+ list->push_front($1);
+ $$= new Item_cond_or(*list);
+ /* optimize construction of logical OR to reduce
+ amount of objects for complex expressions */
+ }
+ else
+ $$= $1;
+ delete list;
+ }
;
-all_or_any: ALL { $$ = 1; }
- | ANY_SYM { $$ = 0; }
+bool_or_expr:
+ /* empty */
+ | bool_or_expr or bool_term
+ { Select->expr_list.head()->push_back($3); }
;
-/* expressions that begin with 'expr' */
-expr_expr:
- expr IN_SYM '(' expr_list ')'
- { $4->push_front($1); $$= new Item_func_in(*$4); }
- | expr NOT IN_SYM '(' expr_list ')'
- {
- $5->push_front($1);
- Item_func_in *item= new Item_func_in(*$5);
- item->negate();
- $$= item;
- }
- | expr IN_SYM in_subselect
- { $$= new Item_in_subselect($1, $3); }
- | expr NOT IN_SYM in_subselect
+bool_term:
+ bool_term XOR bool_term { $$= new Item_cond_xor($1,$3); }
+ | bool_factor { Select->expr_list.push_front(new List<Item>); }
+ bool_and_expr
{
- $$= new Item_func_not(new Item_in_subselect($1, $4));
+ List<Item> *list= Select->expr_list.pop();
+ if (list->elements)
+ {
+ list->push_front($1);
+ $$= new Item_cond_and(*list);
+ /* optimize construction of logical AND to reduce
+ amount of objects for complex expressions */
+ }
+ else
+ $$= $1;
+ delete list;
}
- | expr BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_between($1,$3,$5); }
- | expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
- {
- Item_func_between *item= new Item_func_between($1,$4,$6);
- item->negate();
- $$= item;
- }
- | expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
- | expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
- | expr XOR expr { $$= new Item_cond_xor($1,$3); }
- | expr AND_SYM expr { $$= new Item_cond_and($1,$3); }
- | expr SOUNDS_SYM LIKE expr
- {
- $$= new Item_func_eq(new Item_func_soundex($1),
- new Item_func_soundex($4));
- }
- | expr LIKE simple_expr opt_escape
- { $$= new Item_func_like($1,$3,$4); }
- | expr NOT LIKE simple_expr opt_escape
- { $$= new Item_func_not(new Item_func_like($1,$4,$5));}
- | expr REGEXP expr { $$= new Item_func_regex($1,$3); }
- | expr NOT REGEXP expr
- { $$= new Item_func_not(new Item_func_regex($1,$4)); }
- | expr IS NULL_SYM { $$= new Item_func_isnull($1); }
- | expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
- | expr comp_op all_or_any in_subselect %prec EQ
- {
- $$= all_any_subquery_creator($1, $2, $3, $4);
- }
- | expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
- | expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
- | expr '+' expr { $$= new Item_func_plus($1,$3); }
- | expr '-' expr { $$= new Item_func_minus($1,$3); }
- | expr '*' expr { $$= new Item_func_mul($1,$3); }
- | expr '/' expr { $$= new Item_func_div($1,$3); }
- | expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
- | expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
- | expr '|' expr { $$= new Item_func_bit_or($1,$3); }
- | expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
- | expr '&' expr { $$= new Item_func_bit_and($1,$3); }
- | expr '%' expr { $$= new Item_func_mod($1,$3); }
- | expr '+' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,0); }
- | expr '-' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,1); }
;
-/* expressions that begin with 'expr' that do NOT follow IN_SYM */
-no_in_expr:
- no_in_expr BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_between($1,$3,$5); }
- | no_in_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
- {
- Item_func_between *item= new Item_func_between($1,$4,$6);
- item->negate();
- $$= item;
- }
- | no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
- | no_in_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
- | no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
- | no_in_expr AND_SYM expr { $$= new Item_cond_and($1,$3); }
- | no_in_expr SOUNDS_SYM LIKE expr
- {
- $$= new Item_func_eq(new Item_func_soundex($1),
- new Item_func_soundex($4));
- }
- | no_in_expr LIKE simple_expr opt_escape
- { $$= new Item_func_like($1,$3,$4); }
- | no_in_expr NOT LIKE simple_expr opt_escape
- { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
- | no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
- | no_in_expr NOT REGEXP expr
- { $$= new Item_func_not(new Item_func_regex($1,$4)); }
- | no_in_expr IS NULL_SYM { $$= new Item_func_isnull($1); }
- | no_in_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | no_in_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | no_in_expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
- | no_in_expr comp_op all_or_any in_subselect %prec EQ
- {
- all_any_subquery_creator($1, $2, $3, $4);
- }
- | no_in_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
- | no_in_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
- | no_in_expr '+' expr { $$= new Item_func_plus($1,$3); }
- | no_in_expr '-' expr { $$= new Item_func_minus($1,$3); }
- | no_in_expr '*' expr { $$= new Item_func_mul($1,$3); }
- | no_in_expr '/' expr { $$= new Item_func_div($1,$3); }
- | no_in_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
- | no_in_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
- | no_in_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
- | no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
- | no_in_expr '%' expr { $$= new Item_func_mod($1,$3); }
- | no_in_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
- | no_in_expr '+' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,0); }
- | no_in_expr '-' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,1); }
- | simple_expr;
+bool_and_expr:
+ /* empty */
+ | bool_and_expr and bool_factor
+ { Select->expr_list.head()->push_back($3); }
+ ;
-/* expressions that begin with 'expr' that does NOT follow AND */
-no_and_expr:
- no_and_expr IN_SYM '(' expr_list ')'
- { $4->push_front($1); $$= new Item_func_in(*$4); }
- | no_and_expr NOT IN_SYM '(' expr_list ')'
- {
- $5->push_front($1);
- Item_func_in *item= new Item_func_in(*$5);
- item->negate();
- $$= item;
- }
- | no_and_expr IN_SYM in_subselect
- { $$= new Item_in_subselect($1, $3); }
- | no_and_expr NOT IN_SYM in_subselect
+bool_factor:
+ NOT_SYM bool_factor { $$= negate_expression(YYTHD, $2); }
+ | bool_test ;
+
+bool_test:
+ bool_pri IS TRUE_SYM { $$= is_truth_value($1,1,0); }
+ | bool_pri IS not TRUE_SYM { $$= is_truth_value($1,0,0); }
+ | bool_pri IS FALSE_SYM { $$= is_truth_value($1,0,1); }
+ | bool_pri IS not FALSE_SYM { $$= is_truth_value($1,1,1); }
+ | bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); }
+ | bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); }
+ | bool_pri ;
+
+bool_pri:
+ bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); }
+ | bool_pri IS not NULL_SYM { $$= new Item_func_isnotnull($1); }
+ | bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); }
+ | bool_pri comp_op predicate %prec EQ
+ { $$= (*$2)(0)->create($1,$3); }
+ | bool_pri comp_op all_or_any in_subselect %prec EQ
+ { $$= all_any_subquery_creator($1, $2, $3, $4); }
+ | predicate ;
+
+predicate:
+ bit_expr IN_SYM '(' expr_list ')'
+ {
+ if ($4->elements == 1)
+ $$= new Item_func_eq($1, $4->head());
+ else
+ {
+ $4->push_front($1);
+ $$= new Item_func_in(*$4);
+ }
+ }
+ | bit_expr not IN_SYM '(' expr_list ')'
{
- $$= new Item_func_not(new Item_in_subselect($1, $4));
+ if ($5->elements == 1)
+ $$= new Item_func_ne($1, $5->head());
+ else
+ {
+ $5->push_front($1);
+ Item_func_in *item = new Item_func_in(*$5);
+ item->negate();
+ $$= item;
+ }
}
- | no_and_expr BETWEEN_SYM no_and_expr AND_SYM expr
+ | bit_expr IN_SYM in_subselect
+ { $$= new Item_in_subselect($1, $3); }
+ | bit_expr not IN_SYM in_subselect
+ { $$= negate_expression(YYTHD, new Item_in_subselect($1, $4)); }
+ | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
{ $$= new Item_func_between($1,$3,$5); }
- | no_and_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
+ | bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
{
Item_func_between *item= new Item_func_between($1,$4,$6);
item->negate();
$$= item;
}
- | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
- | no_and_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
- | no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
- | no_and_expr SOUNDS_SYM LIKE expr
- {
- $$= new Item_func_eq(new Item_func_soundex($1),
- new Item_func_soundex($4));
- }
- | no_and_expr LIKE simple_expr opt_escape
- { $$= new Item_func_like($1,$3,$4); }
- | no_and_expr NOT LIKE simple_expr opt_escape
- { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
- | no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
- | no_and_expr NOT REGEXP expr
- { $$= new Item_func_not(new Item_func_regex($1,$4)); }
- | no_and_expr IS NULL_SYM { $$= new Item_func_isnull($1); }
- | no_and_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | no_and_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | no_and_expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
- | no_and_expr comp_op all_or_any in_subselect %prec EQ
- {
- all_any_subquery_creator($1, $2, $3, $4);
- }
- | no_and_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
- | no_and_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
- | no_and_expr '+' expr { $$= new Item_func_plus($1,$3); }
- | no_and_expr '-' expr { $$= new Item_func_minus($1,$3); }
- | no_and_expr '*' expr { $$= new Item_func_mul($1,$3); }
- | no_and_expr '/' expr { $$= new Item_func_div($1,$3); }
- | no_and_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
- | no_and_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
- | no_and_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
- | no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
- | no_and_expr '%' expr { $$= new Item_func_mod($1,$3); }
- | no_and_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
- | no_and_expr '+' interval_expr interval
+ | bit_expr SOUNDS_SYM LIKE bit_expr
+ { $$= new Item_func_eq(new Item_func_soundex($1),
+ new Item_func_soundex($4)); }
+ | bit_expr LIKE simple_expr opt_escape
+ { $$= new Item_func_like($1,$3,$4); }
+ | bit_expr not LIKE simple_expr opt_escape
+ { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
+ | bit_expr REGEXP bit_expr { $$= new Item_func_regex($1,$3); }
+ | bit_expr not REGEXP bit_expr
+ { $$= negate_expression(YYTHD, new Item_func_regex($1,$4)); }
+ | bit_expr ;
+
+bit_expr:
+ bit_expr '|' bit_term { $$= new Item_func_bit_or($1,$3); }
+ | bit_term ;
+
+bit_term:
+ bit_term '&' bit_factor { $$= new Item_func_bit_and($1,$3); }
+ | bit_factor ;
+
+bit_factor:
+ bit_factor SHIFT_LEFT value_expr
+ { $$= new Item_func_shift_left($1,$3); }
+ | bit_factor SHIFT_RIGHT value_expr
+ { $$= new Item_func_shift_right($1,$3); }
+ | value_expr ;
+
+value_expr:
+ value_expr '+' term { $$= new Item_func_plus($1,$3); }
+ | value_expr '-' term { $$= new Item_func_minus($1,$3); }
+ | value_expr '+' interval_expr interval
{ $$= new Item_date_add_interval($1,$3,$4,0); }
- | no_and_expr '-' interval_expr interval
+ | value_expr '-' interval_expr interval
{ $$= new Item_date_add_interval($1,$3,$4,1); }
- | simple_expr;
+ | term ;
+
+term:
+ term '*' factor { $$= new Item_func_mul($1,$3); }
+ | term '/' factor { $$= new Item_func_div($1,$3); }
+ | term '%' factor { $$= new Item_func_mod($1,$3); }
+ | term DIV_SYM factor { $$= new Item_func_int_div($1,$3); }
+ | term MOD_SYM factor { $$= new Item_func_mod($1,$3); }
+ | factor ;
+
+factor:
+ factor '^' simple_expr { $$= new Item_func_bit_xor($1,$3); }
+ | simple_expr ;
+
+or: OR_SYM | OR2_SYM;
+and: AND_SYM | AND_AND_SYM;
+not: NOT_SYM | NOT2_SYM;
+not2: '!' | NOT2_SYM;
+
+comp_op: EQ { $$ = &comp_eq_creator; }
+ | GE { $$ = &comp_ge_creator; }
+ | GT_SYM { $$ = &comp_gt_creator; }
+ | LE { $$ = &comp_le_creator; }
+ | LT { $$ = &comp_lt_creator; }
+ | NE { $$ = &comp_ne_creator; }
+ ;
+
+all_or_any: ALL { $$ = 1; }
+ | ANY_SYM { $$ = 0; }
+ ;
interval_expr:
INTERVAL_SYM expr { $$=$2; }
@@ -2796,12 +4393,16 @@ simple_expr:
| '@' ident_or_text SET_VAR expr
{
$$= new Item_func_set_user_var($2,$4);
- Lex->uncacheable(UNCACHEABLE_RAND);
+ LEX *lex= Lex;
+ lex->uncacheable(UNCACHEABLE_RAND);
+ lex->variables_used= 1;
}
| '@' ident_or_text
{
$$= new Item_func_get_user_var($2);
- Lex->uncacheable(UNCACHEABLE_RAND);
+ LEX *lex= Lex;
+ lex->uncacheable(UNCACHEABLE_RAND);
+ lex->variables_used= 1;
}
| '@' '@' opt_var_ident_type ident_or_text opt_component
{
@@ -2811,21 +4412,17 @@ simple_expr:
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
- if (!($$= get_system_var(YYTHD, (enum_var_type) $3, $4, $5)))
+ if (!($$= get_system_var(YYTHD, $3, $4, $5)))
YYABORT;
+ Lex->variables_used= 1;
}
| sum_expr
- | '+' expr %prec NEG { $$= $2; }
- | '-' expr %prec NEG { $$= new Item_func_neg($2); }
- | '~' expr %prec NEG { $$= new Item_func_bit_neg($2); }
- | NOT expr %prec NEG
- {
- $$= negate_expression(YYTHD, $2);
- }
- | '!' expr %prec NEG
- {
- $$= negate_expression(YYTHD, $2);
- }
+ | simple_expr OR_OR_SYM simple_expr
+ { $$= new Item_func_concat($1, $3); }
+ | '+' simple_expr %prec NEG { $$= $2; }
+ | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); }
+ | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); }
+ | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); }
| '(' expr ')' { $$= $2; }
| '(' expr ',' expr_list ')'
{
@@ -2840,20 +4437,22 @@ simple_expr:
| EXISTS exists_subselect { $$= $2; }
| singlerow_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
- | MATCH ident_list_arg AGAINST '(' expr fulltext_options ')'
+ | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
{ $2->push_front($5);
Select->add_ftfunc_to_list((Item_func_match*)
($$=new Item_func_match(*$2,$6))); }
| ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); }
- | BINARY expr %prec NEG
+ | BINARY simple_expr %prec NEG
{
- $$= create_func_cast($2, ITEM_CAST_CHAR, -1, &my_charset_bin);
+ $$= create_func_cast($2, ITEM_CAST_CHAR, -1, 0, &my_charset_bin);
}
| CAST_SYM '(' expr AS cast_type ')'
{
+ LEX *lex= Lex;
$$= create_func_cast($3, $5,
- Lex->length ? atoi(Lex->length) : -1,
- Lex->charset);
+ lex->length ? atoi(lex->length) : -1,
+ lex->dec ? atoi(lex->dec) : 0,
+ lex->charset);
}
| CASE_SYM opt_expr WHEN_SYM when_list opt_else END
{ $$= new Item_func_case(* $4, $2, $5 ); }
@@ -2861,21 +4460,33 @@ simple_expr:
{
$$= create_func_cast($3, $5,
Lex->length ? atoi(Lex->length) : -1,
+ Lex->dec ? atoi(Lex->dec) : 0,
Lex->charset);
}
| CONVERT_SYM '(' expr USING charset_name ')'
{ $$= new Item_func_conv_charset($3,$5); }
| DEFAULT '(' simple_ident ')'
- { $$= new Item_default_value($3); }
+ {
+ if ($3->is_splocal())
+ {
+ LEX_STRING *name;
+ Item_splocal *il= static_cast<Item_splocal *>($3);
+
+ name= il->my_name(NULL);
+ my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str);
+ YYABORT;
+ }
+ $$= new Item_default_value(Lex->current_context(), $3);
+ }
| VALUES '(' simple_ident ')'
- { $$= new Item_insert_value($3); }
+ { $$= new Item_insert_value(Lex->current_context(), $3); }
| FUNC_ARG0 '(' ')'
{
if (!$1.symbol->create_func)
{
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- $1.symbol->group->name,
- $1.symbol->group->needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ $1.symbol->group->name,
+ $1.symbol->group->needed_define);
YYABORT;
}
$$= ((Item*(*)(void))($1.symbol->create_func))();
@@ -2884,9 +4495,9 @@ simple_expr:
{
if (!$1.symbol->create_func)
{
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- $1.symbol->group->name,
- $1.symbol->group->needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ $1.symbol->group->name,
+ $1.symbol->group->needed_define);
YYABORT;
}
$$= ((Item*(*)(Item*))($1.symbol->create_func))($3);
@@ -2895,9 +4506,9 @@ simple_expr:
{
if (!$1.symbol->create_func)
{
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- $1.symbol->group->name,
- $1.symbol->group->needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ $1.symbol->group->name,
+ $1.symbol->group->needed_define);
YYABORT;
}
$$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);
@@ -2906,9 +4517,9 @@ simple_expr:
{
if (!$1.symbol->create_func)
{
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- $1.symbol->group->name,
- $1.symbol->group->needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ $1.symbol->group->name,
+ $1.symbol->group->needed_define);
YYABORT;
}
$$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);
@@ -2917,6 +4528,8 @@ simple_expr:
{ $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);}
| ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
{ $$= new Item_date_add_interval($3, $6, $7, 0); }
+ | REPEAT_SYM '(' expr ',' expr ')'
+ { $$= new Item_func_repeat($3,$5); }
| ATAN '(' expr ')'
{ $$= new Item_func_atan($3); }
| ATAN '(' expr ',' expr ')'
@@ -2935,7 +4548,8 @@ simple_expr:
{ $5->push_front($3); $$= new Item_func_concat_ws(*$5); }
| CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')'
{
- Lex->time_zone_tables_used= &fake_time_zone_tables_list;
+ if (Lex->add_time_zone_tables_to_query_tables(YYTHD))
+ YYABORT;
$$= new Item_func_convert_tz($3, $5, $7);
}
| CURDATE optional_braces
@@ -3005,8 +4619,8 @@ simple_expr:
#ifdef HAVE_SPATIAL
$$= $1;
#else
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
}
@@ -3084,8 +4698,10 @@ simple_expr:
}
| OLD_PASSWORD '(' expr ')'
{ $$= new Item_func_old_password($3); }
- | POSITION_SYM '(' no_in_expr IN_SYM expr ')'
+ | POSITION_SYM '(' bit_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
+ | QUARTER_SYM '(' expr ')'
+ { $$ = new Item_func_quarter($3); }
| RAND '(' expr ')'
{ $$= new Item_func_rand($3); Lex->uncacheable(UNCACHEABLE_RAND);}
| RAND '(' ')'
@@ -3097,6 +4713,11 @@ simple_expr:
| ROUND '(' expr ')'
{ $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); }
| ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); }
+ | ROW_COUNT_SYM '(' ')'
+ {
+ $$= new Item_func_row_count();
+ Lex->safe_to_cache_query= 0;
+ }
| SUBDATE_SYM '(' expr ',' expr ')'
{ $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);}
| SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
@@ -3113,12 +4734,20 @@ simple_expr:
{ $$= new Item_func_substr($3,$5); }
| SUBSTRING_INDEX '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_substr_index($3,$5,$7); }
+ | SYSDATE optional_braces
+ { $$= new Item_func_sysdate_local(); Lex->safe_to_cache_query=0;}
+ | SYSDATE '(' expr ')'
+ { $$= new Item_func_sysdate_local($3); Lex->safe_to_cache_query=0;}
| TIME_SYM '(' expr ')'
{ $$= new Item_time_typecast($3); }
| TIMESTAMP '(' expr ')'
{ $$= new Item_datetime_typecast($3); }
| TIMESTAMP '(' expr ',' expr ')'
{ $$= new Item_func_add_time($3, $5, 1, 0); }
+ | TIMESTAMP_ADD '(' interval_time_st ',' expr ',' expr ')'
+ { $$= new Item_date_add_interval($7,$5,$3,0); }
+ | TIMESTAMP_DIFF '(' interval_time_st ',' expr ',' expr ')'
+ { $$= new Item_func_timestamp_diff($5,$7,$3); }
| TRIM '(' expr ')'
{ $$= new Item_func_trim($3); }
| TRIM '(' LEADING expr FROM expr ')'
@@ -3137,48 +4766,110 @@ simple_expr:
{ $$= new Item_func_trim($5,$3); }
| TRUNCATE_SYM '(' expr ',' expr ')'
{ $$= new Item_func_round($3,$5,1); }
- | UDA_CHAR_SUM '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_sum_udf_str($1, *$3);
- else
- $$ = new Item_sum_udf_str($1);
- }
- | UDA_FLOAT_SUM '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_sum_udf_float($1, *$3);
- else
- $$ = new Item_sum_udf_float($1);
- }
- | UDA_INT_SUM '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_sum_udf_int($1, *$3);
- else
- $$ = new Item_sum_udf_int($1);
- }
- | UDF_CHAR_FUNC '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_func_udf_str($1, *$3);
- else
- $$ = new Item_func_udf_str($1);
- }
- | UDF_FLOAT_FUNC '(' udf_expr_list ')'
- {
- if ($3 != NULL)
- $$ = new Item_func_udf_float($1, *$3);
- else
- $$ = new Item_func_udf_float($1);
- }
- | UDF_INT_FUNC '(' udf_expr_list ')'
+ | ident '.' ident '(' udf_expr_list ')'
{
- if ($3 != NULL)
- $$ = new Item_func_udf_int($1, *$3);
+ LEX *lex= Lex;
+ sp_name *name= new sp_name($1, $3);
+
+ name->init_qname(YYTHD);
+ sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
+ if ($5)
+ $$= new Item_func_sp(Lex->current_context(), name, *$5);
else
- $$ = new Item_func_udf_int($1);
+ $$= new Item_func_sp(Lex->current_context(), name);
+ lex->safe_to_cache_query=0;
}
+ | IDENT_sys '(' udf_expr_list ')'
+ {
+#ifdef HAVE_DLOPEN
+ udf_func *udf;
+ SELECT_LEX *sel= Select;
+
+ if (using_udf_functions && (udf=find_udf($1.str, $1.length)))
+ {
+ switch (udf->returns) {
+ case STRING_RESULT:
+ if (udf->type == UDFTYPE_FUNCTION)
+ {
+ if ($3 != NULL)
+ $$ = new Item_func_udf_str(udf, *$3);
+ else
+ $$ = new Item_func_udf_str(udf);
+ }
+ else
+ {
+ if ($3 != NULL)
+ $$ = new Item_sum_udf_str(udf, *$3);
+ else
+ $$ = new Item_sum_udf_str(udf);
+ }
+ break;
+ case REAL_RESULT:
+ if (udf->type == UDFTYPE_FUNCTION)
+ {
+ if ($3 != NULL)
+ $$ = new Item_func_udf_float(udf, *$3);
+ else
+ $$ = new Item_func_udf_float(udf);
+ }
+ else
+ {
+ if ($3 != NULL)
+ $$ = new Item_sum_udf_float(udf, *$3);
+ else
+ $$ = new Item_sum_udf_float(udf);
+ }
+ break;
+ case INT_RESULT:
+ if (udf->type == UDFTYPE_FUNCTION)
+ {
+ if ($3 != NULL)
+ $$ = new Item_func_udf_int(udf, *$3);
+ else
+ $$ = new Item_func_udf_int(udf);
+ }
+ else
+ {
+ if ($3 != NULL)
+ $$ = new Item_sum_udf_int(udf, *$3);
+ else
+ $$ = new Item_sum_udf_int(udf);
+ }
+ break;
+ case DECIMAL_RESULT:
+ if (udf->type == UDFTYPE_FUNCTION)
+ {
+ if ($3 != NULL)
+ $$ = new Item_func_udf_decimal(udf, *$3);
+ else
+ $$ = new Item_func_udf_decimal(udf);
+ }
+ else
+ {
+ if ($3 != NULL)
+ $$ = new Item_sum_udf_decimal(udf, *$3);
+ else
+ $$ = new Item_sum_udf_decimal(udf);
+ }
+ break;
+ default:
+ YYABORT;
+ }
+ }
+ else
+#endif /* HAVE_DLOPEN */
+ {
+ LEX *lex= Lex;
+ sp_name *name= sp_name_current_db_new(YYTHD, $1);
+
+ sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
+ if ($3)
+ $$= new Item_func_sp(Lex->current_context(), name, *$3);
+ else
+ $$= new Item_func_sp(Lex->current_context(), name);
+ lex->safe_to_cache_query=0;
+ }
+ }
| UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')'
{
$$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9);
@@ -3191,7 +4882,7 @@ simple_expr:
| UNIX_TIMESTAMP '(' expr ')'
{ $$= new Item_func_unix_timestamp($3); }
| USER '(' ')'
- { $$= new Item_func_user(); Lex->safe_to_cache_query=0; }
+ { $$= new Item_func_user(FALSE); Lex->safe_to_cache_query=0; }
| UTC_DATE_SYM optional_braces
{ $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;}
| UTC_TIME_SYM optional_braces
@@ -3211,7 +4902,7 @@ simple_expr:
{ $$= new Item_func_yearweek($3,new Item_int((char*) "0",0,1)); }
| YEARWEEK '(' expr ',' expr ')'
{ $$= new Item_func_yearweek($3, $5); }
- | BENCHMARK_SYM '(' ULONG_NUM ',' expr ')'
+ | BENCHMARK_SYM '(' ulong_num ',' expr ')'
{
$$=new Item_func_benchmark($3,$5);
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -3220,7 +4911,9 @@ simple_expr:
{ $$=new Item_extract( $3, $5); };
geometry_function:
- GEOMFROMTEXT '(' expr ')'
+ CONTAINS_SYM '(' expr ',' expr ')'
+ { $$= GEOM_NEW(Item_func_spatial_rel($3, $5, Item_func::SP_CONTAINS_FUNC)); }
+ | GEOMFROMTEXT '(' expr ')'
{ $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
| GEOMFROMTEXT '(' expr ',' expr ')'
{ $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
@@ -3286,12 +4979,46 @@ fulltext_options:
;
udf_expr_list:
- /* empty */ { $$= NULL; }
- | expr_list { $$= $1;};
+ /* empty */ { $$= NULL; }
+ | udf_expr_list2 { $$= $1;}
+ ;
+
+udf_expr_list2:
+ { Select->expr_list.push_front(new List<Item>); }
+ udf_expr_list3
+ { $$= Select->expr_list.pop(); }
+ ;
+
+udf_expr_list3:
+ udf_expr
+ {
+ Select->expr_list.head()->push_back($1);
+ }
+ | udf_expr_list3 ',' udf_expr
+ {
+ Select->expr_list.head()->push_back($3);
+ }
+ ;
+
+udf_expr:
+ remember_name expr remember_end select_alias
+ {
+ if ($4.str)
+ {
+ $2->set_name($4.str, $4.length, system_charset_info);
+ $2->is_autogenerated_name= FALSE;
+ }
+ else
+ $2->set_name($1, (uint) ($3 - $1), YYTHD->charset());
+ $$= $2;
+ }
+ ;
sum_expr:
AVG_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_avg($3); }
+ | AVG_SYM '(' DISTINCT in_sum_expr ')'
+ { $$=new Item_sum_avg_distinct($4); }
| BIT_AND '(' in_sum_expr ')'
{ $$=new Item_sum_and($3); }
| BIT_OR '(' in_sum_expr ')'
@@ -3312,22 +5039,39 @@ sum_expr:
{ $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); }
| MIN_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_min($3); }
+/*
+ According to ANSI SQL, DISTINCT is allowed and has
+ no sence inside MIN and MAX grouping functions; so MIN|MAX(DISTINCT ...)
+ is processed like an ordinary MIN | MAX()
+ */
+ | MIN_SYM '(' DISTINCT in_sum_expr ')'
+ { $$=new Item_sum_min($4); }
| MAX_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_max($3); }
+ | MAX_SYM '(' DISTINCT in_sum_expr ')'
+ { $$=new Item_sum_max($4); }
| STD_SYM '(' in_sum_expr ')'
- { $$=new Item_sum_std($3); }
+ { $$=new Item_sum_std($3, 0); }
| VARIANCE_SYM '(' in_sum_expr ')'
- { $$=new Item_sum_variance($3); }
+ { $$=new Item_sum_variance($3, 0); }
+ | STDDEV_SAMP_SYM '(' in_sum_expr ')'
+ { $$=new Item_sum_std($3, 1); }
+ | VAR_SAMP_SYM '(' in_sum_expr ')'
+ { $$=new Item_sum_variance($3, 1); }
| SUM_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_sum($3); }
+ | SUM_SYM '(' DISTINCT in_sum_expr ')'
+ { $$=new Item_sum_sum_distinct($4); }
| GROUP_CONCAT_SYM '(' opt_distinct
{ Select->in_sum_expr++; }
expr_list opt_gorder_clause
opt_gconcat_separator
')'
{
- Select->in_sum_expr--;
- $$=new Item_func_group_concat($3,$5,Select->gorder_list,$7);
+ SELECT_LEX *sel= Select;
+ sel->in_sum_expr--;
+ $$=new Item_func_group_concat(Lex->current_context(), $3, $5,
+ sel->gorder_list, $7);
$5->empty();
};
@@ -3372,16 +5116,17 @@ in_sum_expr:
};
cast_type:
- BINARY opt_len { $$=ITEM_CAST_CHAR; Lex->charset= &my_charset_bin; }
- | CHAR_SYM opt_len opt_binary { $$=ITEM_CAST_CHAR; }
- | NCHAR_SYM opt_len { $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; }
- | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; }
- | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; }
- | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; }
- | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; }
- | DATE_SYM { $$=ITEM_CAST_DATE; Lex->charset= NULL; Lex->length= (char*)0; }
- | TIME_SYM { $$=ITEM_CAST_TIME; Lex->charset= NULL; Lex->length= (char*)0; }
- | DATETIME { $$=ITEM_CAST_DATETIME; Lex->charset= NULL; Lex->length= (char*)0; }
+ BINARY opt_len { $$=ITEM_CAST_CHAR; Lex->charset= &my_charset_bin; Lex->dec= 0; }
+ | CHAR_SYM opt_len opt_binary { $$=ITEM_CAST_CHAR; Lex->dec= 0; }
+ | NCHAR_SYM opt_len { $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; }
+ | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
+ | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
+ | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
+ | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
+ | DATE_SYM { $$=ITEM_CAST_DATE; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
+ | TIME_SYM { $$=ITEM_CAST_TIME; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
+ | DATETIME { $$=ITEM_CAST_DATETIME; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
+ | DECIMAL_SYM float_options { $$=ITEM_CAST_DECIMAL; Lex->charset= NULL; }
;
expr_list:
@@ -3433,58 +5178,151 @@ when_list2:
sel->when_list.head()->push_back($5);
};
+/* Warning - may return NULL in case of incomplete SELECT */
+table_ref:
+ table_factor { $$=$1; }
+ | join_table { $$=$1; }
+ {
+ LEX *lex= Lex;
+ if (!($$= lex->current_select->nest_last_join(lex->thd)))
+ YYABORT;
+ }
+ ;
+
join_table_list:
- join_table { $$=$1; }
- | join_table_list ',' join_table_list { $$=$3; }
- | join_table_list normal_join join_table_list { $$=$3; }
- | join_table_list STRAIGHT_JOIN join_table_list
- { $$=$3 ; $1->next->straight=1; }
- | join_table_list normal_join join_table_list ON expr
- { add_join_on($3,$5); $$=$3; }
- | join_table_list normal_join join_table_list
+ derived_table_list { YYERROR_UNLESS($$=$1); }
+ ;
+
+/* Warning - may return NULL in case of incomplete SELECT */
+derived_table_list:
+ table_ref { $$=$1; }
+ | derived_table_list ',' table_ref
+ {
+ YYERROR_UNLESS($1 && ($$=$3));
+ }
+ ;
+
+join_table:
+ /*
+ Evaluate production 'table_ref' before 'normal_join' so that
+ [INNER | CROSS] JOIN is properly nested as other left-associative
+ joins.
+ */
+ table_ref %prec TABLE_REF_PRIORITY normal_join table_ref
+ { YYERROR_UNLESS($1 && ($$=$3)); }
+ | table_ref STRAIGHT_JOIN table_factor
+ { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; }
+ | table_ref normal_join table_ref
+ ON
+ {
+ YYERROR_UNLESS($1 && ($$=$3));
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr
+ {
+ add_join_on($3,$6);
+ Lex->pop_context();
+ }
+ | table_ref STRAIGHT_JOIN table_factor
+ ON
+ {
+ YYERROR_UNLESS($1 && ($$=$3));
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr
+ {
+ $3->straight=1;
+ add_join_on($3,$6);
+ Lex->pop_context();
+ }
+ | table_ref normal_join table_ref
USING
{
SELECT_LEX *sel= Select;
- sel->db1=$1->db; sel->table1=$1->alias;
- sel->db2=$3->db; sel->table2=$3->alias;
+ YYERROR_UNLESS($1 && $3);
}
'(' using_list ')'
- { add_join_on($3,$7); $$=$3; }
-
- | join_table_list LEFT opt_outer JOIN_SYM join_table_list ON expr
- { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
- | join_table_list LEFT opt_outer JOIN_SYM join_table_list
+ { add_join_natural($1,$3,$7); $$=$3; }
+ | table_ref LEFT opt_outer JOIN_SYM table_ref
+ ON
+ {
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr
+ {
+ YYERROR_UNLESS($1 && $5);
+ add_join_on($5,$8);
+ Lex->pop_context();
+ $5->outer_join|=JOIN_TYPE_LEFT;
+ $$=$5;
+ }
+ | table_ref LEFT opt_outer JOIN_SYM table_factor
{
SELECT_LEX *sel= Select;
- sel->db1=$1->db; sel->table1=$1->alias;
- sel->db2=$5->db; sel->table2=$5->alias;
+ YYERROR_UNLESS($1 && $5);
}
USING '(' using_list ')'
- { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
- | join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table_list
+ { add_join_natural($1,$5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
+ | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
{
- add_join_natural($1,$1->next);
- $1->next->outer_join|=JOIN_TYPE_LEFT;
+ YYERROR_UNLESS($1 && $6);
+ add_join_natural($1,$6,NULL);
+ $6->outer_join|=JOIN_TYPE_LEFT;
$$=$6;
}
- | join_table_list RIGHT opt_outer JOIN_SYM join_table_list ON expr
- { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; }
- | join_table_list RIGHT opt_outer JOIN_SYM join_table_list
+ | table_ref RIGHT opt_outer JOIN_SYM table_ref
+ ON
+ {
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr
+ {
+ LEX *lex= Lex;
+ YYERROR_UNLESS($1 && $5);
+ if (!($$= lex->current_select->convert_right_join()))
+ YYABORT;
+ add_join_on($$, $8);
+ Lex->pop_context();
+ }
+ | table_ref RIGHT opt_outer JOIN_SYM table_factor
{
SELECT_LEX *sel= Select;
- sel->db1=$1->db; sel->table1=$1->alias;
- sel->db2=$5->db; sel->table2=$5->alias;
+ YYERROR_UNLESS($1 && $5);
}
USING '(' using_list ')'
- { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; }
- | join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table_list
+ {
+ LEX *lex= Lex;
+ if (!($$= lex->current_select->convert_right_join()))
+ YYABORT;
+ add_join_natural($$,$5,$9);
+ }
+ | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
{
- add_join_natural($1->next,$1);
- $1->outer_join|=JOIN_TYPE_RIGHT;
- $$=$6;
+ YYERROR_UNLESS($1 && $6);
+ add_join_natural($6,$1,NULL);
+ LEX *lex= Lex;
+ if (!($$= lex->current_select->convert_right_join()))
+ YYABORT;
}
- | join_table_list NATURAL JOIN_SYM join_table_list
- { add_join_natural($1,$1->next); $$=$4; };
+ | table_ref NATURAL JOIN_SYM table_factor
+ { YYERROR_UNLESS($1 && ($$=$4)); add_join_natural($1,$4,NULL); };
+
normal_join:
JOIN_SYM {}
@@ -3492,7 +5330,8 @@ normal_join:
| CROSS JOIN_SYM {}
;
-join_table:
+/* Warning - may return NULL in case of incomplete SELECT */
+table_factor:
{
SELECT_LEX *sel= Select;
sel->use_index_ptr=sel->ignore_index_ptr=0;
@@ -3508,44 +5347,120 @@ join_table:
sel->get_use_index(),
sel->get_ignore_index())))
YYABORT;
+ sel->add_joined_table($$);
}
- | '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}'
- { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
- | '(' select_derived union_opt ')' opt_table_alias
+ | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref
+ ON
+ {
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$3,$7)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr '}'
+ {
+ YYERROR_UNLESS($3 && $7);
+ add_join_on($7,$10);
+ Lex->pop_context();
+ $7->outer_join|=JOIN_TYPE_LEFT;
+ $$=$7;
+ }
+ | select_derived_init get_select_lex select_derived2
+ {
+ LEX *lex= Lex;
+ SELECT_LEX *sel= lex->current_select;
+ if ($1)
+ {
+ if (sel->set_braces(1))
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ /* select in braces, can't contain global parameters */
+ if (sel->master_unit()->fake_select_lex)
+ sel->master_unit()->global_parameters=
+ sel->master_unit()->fake_select_lex;
+ }
+ if ($2->init_nested_join(lex->thd))
+ YYABORT;
+ $$= 0;
+ /* incomplete derived tables return NULL, we must be
+ nested in select_derived rule to be here. */
+ }
+ | '(' get_select_lex select_derived union_opt ')' opt_table_alias
{
- LEX *lex=Lex;
- SELECT_LEX_UNIT *unit= lex->current_select->master_unit();
- lex->current_select= unit->outer_select();
- if (!($$= lex->current_select->
- add_table_to_list(lex->thd, new Table_ident(unit), $5, 0,
- TL_READ,(List<String> *)0,
- (List<String> *)0)))
+ /* Use $2 instead of Lex->current_select as derived table will
+ alter value of Lex->current_select. */
+
+ if (!($3 || $6) && $2->embedding &&
+ !$2->embedding->nested_join->join_list.elements)
+ {
+ /* we have a derived table ($3 == NULL) but no alias,
+ Since we are nested in further parentheses so we
+ can pass NULL to the outer level parentheses
+ Permits parsing of "((((select ...))) as xyz)" */
+ $$= 0;
+ }
+ else
+ if (!$3)
+ {
+ /* Handle case of derived table, alias may be NULL if there
+ are no outer parentheses, add_table_to_list() will throw
+ error in this case */
+ LEX *lex=Lex;
+ SELECT_LEX *sel= lex->current_select;
+ SELECT_LEX_UNIT *unit= sel->master_unit();
+ lex->current_select= sel= unit->outer_select();
+ if (!($$= sel->
+ add_table_to_list(lex->thd, new Table_ident(unit), $6, 0,
+ TL_READ,(List<String> *)0,
+ (List<String> *)0)))
+ YYABORT;
+ sel->add_joined_table($$);
+ lex->pop_context();
+ }
+ else
+ if ($4 || $6)
+ {
+ /* simple nested joins cannot have aliases or unions */
+ yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
+ }
+ else
+ $$= $3;
}
- | '(' join_table_list ')' { $$=$2; };
+ ;
+/* handle contents of parentheses in join expression */
select_derived:
- SELECT_SYM select_derived2
- | '(' select_derived ')'
+ get_select_lex
{
- LEX *lex= Lex;
- SELECT_LEX * sel= lex->current_select;
- if (sel->set_braces(1))
- {
+ LEX *lex= Lex;
+ if ($1->init_nested_join(lex->thd))
+ YYABORT;
+ }
+ derived_table_list
+ {
+ LEX *lex= Lex;
+ /* for normal joins, $3 != NULL and end_nested_join() != NULL,
+ for derived tables, both must equal NULL */
+
+ if (!($$= $1->end_nested_join(lex->thd)) && $3)
+ YYABORT;
+ if (!$3 && $$)
+ {
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
- }
- /* select in braces, can't contain global parameters */
- if (sel->master_unit()->fake_select_lex)
- sel->master_unit()->global_parameters=
- sel->master_unit()->fake_select_lex;
- };
+ }
+ }
+ ;
select_derived2:
{
LEX *lex= Lex;
- lex->derived_tables= 1;
+ lex->derived_tables|= DERIVED_SUBQUERY;
if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN &&
lex->sql_command <= (int)SQLCOM_HA_READ) ||
lex->sql_command == (int)SQLCOM_KILL)
@@ -3567,6 +5482,29 @@ select_derived2:
opt_select_from
;
+get_select_lex:
+ /* Empty */ { $$= Select; }
+ ;
+
+select_derived_init:
+ SELECT_SYM
+ {
+ LEX *lex= Lex;
+ SELECT_LEX *sel= lex->current_select;
+ TABLE_LIST *embedding;
+ if (!sel->embedding || sel->end_nested_join(lex->thd))
+ {
+ /* we are not in parentheses */
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ embedding= Select->embedding;
+ $$= embedding &&
+ !embedding->nested_join->join_list.elements;
+ /* return true if we are deeply nested */
+ }
+ ;
+
opt_outer:
/* empty */ {}
| OUTER {};
@@ -3621,38 +5559,44 @@ key_usage_list2:
using_list:
ident
{
- SELECT_LEX *sel= Select;
- if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1,
- $1.str),
- new Item_field(sel->db2, sel->table2,
- $1.str))))
+ if (!($$= new List<String>))
YYABORT;
+ $$->push_back(new (YYTHD->mem_root)
+ String((const char *) $1.str, $1.length,
+ system_charset_info));
}
| using_list ',' ident
{
- SELECT_LEX *sel= Select;
- if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
- YYABORT;
+ $1->push_back(new (YYTHD->mem_root)
+ String((const char *) $3.str, $3.length,
+ system_charset_info));
+ $$= $1;
};
interval:
- DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; }
+ interval_time_st {}
+ | DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; }
| DAY_MICROSECOND_SYM { $$=INTERVAL_DAY_MICROSECOND; }
| DAY_MINUTE_SYM { $$=INTERVAL_DAY_MINUTE; }
| DAY_SECOND_SYM { $$=INTERVAL_DAY_SECOND; }
- | DAY_SYM { $$=INTERVAL_DAY; }
| HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; }
| HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; }
| HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; }
- | HOUR_SYM { $$=INTERVAL_HOUR; }
| MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; }
| MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; }
| MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; }
+ | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
+ | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; };
+
+interval_time_st:
+ DAY_SYM { $$=INTERVAL_DAY; }
+ | WEEK_SYM { $$=INTERVAL_WEEK; }
+ | HOUR_SYM { $$=INTERVAL_HOUR; }
+ | FRAC_SECOND_SYM { $$=INTERVAL_MICROSECOND; }
| MINUTE_SYM { $$=INTERVAL_MINUTE; }
| MONTH_SYM { $$=INTERVAL_MONTH; }
- | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
+ | QUARTER_SYM { $$=INTERVAL_QUARTER; }
| SECOND_SYM { $$=INTERVAL_SECOND; }
- | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }
| YEAR_SYM { $$=INTERVAL_YEAR; }
;
@@ -3713,8 +5657,11 @@ having_clause:
opt_escape:
ESCAPE_SYM simple_expr { $$= $2; }
| /* empty */
- {
- $$= new Item_string("\\", 1, &my_charset_latin1);
+ {
+
+ $$= ((YYTHD->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ?
+ new Item_string("", 0, &my_charset_latin1) :
+ new Item_string("\\", 1, &my_charset_latin1));
}
;
@@ -3740,12 +5687,12 @@ olap_opt:
LEX *lex=Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
- net_printf(lex->thd, ER_WRONG_USAGE, "WITH CUBE",
+ my_error(ER_WRONG_USAGE, MYF(0), "WITH CUBE",
"global union parameters");
YYABORT;
}
lex->current_select->olap= CUBE_TYPE;
- net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE");
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "CUBE");
YYABORT; /* To be deleted in 5.1 */
}
| WITH ROLLUP_SYM
@@ -3753,7 +5700,7 @@ olap_opt:
LEX *lex= Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
- net_printf(lex->thd, ER_WRONG_USAGE, "WITH ROLLUP",
+ my_error(ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
"global union parameters");
YYABORT;
}
@@ -3777,9 +5724,8 @@ order_clause:
lex->current_select->olap !=
UNSPECIFIED_OLAP_TYPE)
{
- net_printf(lex->thd, ER_WRONG_USAGE,
- "CUBE/ROLLUP",
- "ORDER BY");
+ my_error(ER_WRONG_USAGE, MYF(0),
+ "CUBE/ROLLUP", "ORDER BY");
YYABORT;
}
} order_list;
@@ -3801,8 +5747,8 @@ opt_limit_clause_init:
{
LEX *lex= Lex;
SELECT_LEX *sel= lex->current_select;
- sel->offset_limit= 0L;
- sel->select_limit= HA_POS_ERROR;
+ sel->offset_limit= 0;
+ sel->select_limit= 0;
}
| limit_clause {}
;
@@ -3817,21 +5763,21 @@ limit_clause:
;
limit_options:
- ULONG_NUM
+ limit_option
{
SELECT_LEX *sel= Select;
sel->select_limit= $1;
- sel->offset_limit= 0L;
+ sel->offset_limit= 0;
sel->explicit_limit= 1;
}
- | ULONG_NUM ',' ULONG_NUM
+ | limit_option ',' limit_option
{
SELECT_LEX *sel= Select;
sel->select_limit= $3;
sel->offset_limit= $1;
sel->explicit_limit= 1;
}
- | ULONG_NUM OFFSET_SYM ULONG_NUM
+ | limit_option OFFSET_SYM limit_option
{
SELECT_LEX *sel= Select;
sel->select_limit= $1;
@@ -3839,26 +5785,32 @@ limit_options:
sel->explicit_limit= 1;
}
;
-
+limit_option:
+ param_marker
+ | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); }
+ | LONG_NUM { $$= new Item_uint($1.str, $1.length); }
+ | NUM { $$= new Item_uint($1.str, $1.length); }
+ ;
delete_limit_clause:
/* empty */
{
LEX *lex=Lex;
- lex->current_select->select_limit= HA_POS_ERROR;
+ lex->current_select->select_limit= 0;
}
- | LIMIT ulonglong_num
+ | LIMIT limit_option
{
SELECT_LEX *sel= Select;
- sel->select_limit= (ha_rows) $2;
+ sel->select_limit= $2;
sel->explicit_limit= 1;
};
-ULONG_NUM:
- NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ulong_num:
+ NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ | HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
| LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
| ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | REAL_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ | DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
| FLOAT_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
;
@@ -3866,7 +5818,7 @@ ulonglong_num:
NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
| ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
| LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | REAL_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
+ | DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
| FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
;
@@ -3877,15 +5829,16 @@ procedure_clause:
LEX *lex=Lex;
if (&lex->select_lex != lex->current_select)
{
- net_printf(lex->thd, ER_WRONG_USAGE,
- "PROCEDURE",
- "subquery");
+ my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
YYABORT;
}
lex->proc_list.elements=0;
lex->proc_list.first=0;
lex->proc_list.next= (byte**) &lex->proc_list.first;
- if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str)))
+ if (add_proc_to_list(lex->thd, new Item_field(&lex->
+ current_select->
+ context,
+ NULL,NULL,$2.str)))
YYABORT;
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
}
@@ -3907,7 +5860,8 @@ procedure_item:
if (add_proc_to_list(lex->thd, $2))
YYABORT;
if (!$2->name)
- $2->set_name($1,(uint) ((char*) lex->tok_end - $1), YYTHD->charset());
+ $2->set_name($1,(uint) ((char*) lex->tok_end - $1),
+ YYTHD->charset());
}
;
@@ -3927,12 +5881,32 @@ select_var_list:
| select_var_ident {}
;
-select_var_ident: '@' ident_or_text
+select_var_ident:
+ '@' ident_or_text
{
LEX *lex=Lex;
- if (lex->result && ((select_dumpvar *)lex->result)->var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING))))
+ if (lex->result)
+ ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($2,0,0,(enum_field_types)0));
+ else
YYABORT;
}
+ | ident_or_text
+ {
+ LEX *lex=Lex;
+ sp_pvar_t *t;
+
+ if (!lex->spcont || !(t=lex->spcont->find_pvar(&$1)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
+ YYABORT;
+ }
+ if (! lex->result)
+ YYABORT;
+ else
+ {
+ ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset,t->type));
+ }
+ }
;
into:
@@ -3990,10 +5964,21 @@ drop:
lex->sql_command = SQLCOM_DROP_TABLE;
lex->drop_temporary= $2;
lex->drop_if_exists= $4;
+ if (!lex->drop_temporary && lex->sphead &&
+ lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
}
| DROP INDEX_SYM ident ON table_ident {}
{
LEX *lex=Lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
lex->sql_command= SQLCOM_DROP_INDEX;
lex->alter_info.drop_list.empty();
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
@@ -4009,22 +5994,53 @@ drop:
lex->drop_if_exists=$3;
lex->name=$4.str;
}
- | DROP UDF_SYM IDENT_sys
+ | DROP FUNCTION_SYM if_exists sp_name
{
LEX *lex=Lex;
+ if (lex->sphead)
+ {
+ my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
+ YYABORT;
+ }
lex->sql_command = SQLCOM_DROP_FUNCTION;
- lex->udf.name = $3;
+ lex->drop_if_exists= $3;
+ lex->spname= $4;
}
- | DROP USER
+ | DROP PROCEDURE if_exists sp_name
{
LEX *lex=Lex;
- lex->sql_command = SQLCOM_DROP_USER;
- lex->users_list.empty();
+ if (lex->sphead)
+ {
+ my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
+ YYABORT;
+ }
+ lex->sql_command = SQLCOM_DROP_PROCEDURE;
+ lex->drop_if_exists= $3;
+ lex->spname= $4;
}
- user_list
- {}
- ;
-
+ | DROP USER clear_privileges user_list
+ {
+ Lex->sql_command = SQLCOM_DROP_USER;
+ }
+ | DROP VIEW_SYM if_exists table_list opt_restrict
+ {
+ THD *thd= YYTHD;
+ LEX *lex= thd->lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_DROP_VIEW;
+ lex->drop_if_exists= $3;
+ }
+ | DROP TRIGGER_SYM sp_name
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DROP_TRIGGER;
+ lex->spname= $3;
+ }
+ ;
table_list:
table_name
@@ -4056,11 +6072,10 @@ insert:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_INSERT;
- lex->duplicates= DUP_ERROR;
- mysql_init_select(lex);
+ lex->duplicates= DUP_ERROR;
+ mysql_init_select(lex);
/* for subselects */
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
- lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
} insert_lock_option
opt_ignore insert2
{
@@ -4077,8 +6092,7 @@ replace:
LEX *lex=Lex;
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
- mysql_init_select(lex);
- lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
+ mysql_init_select(lex);
}
replace_lock_option insert2
{
@@ -4126,11 +6140,6 @@ insert_field_spec:
}
ident_eq_list;
-opt_field_spec:
- /* empty */ { }
- | '(' fields ')' { }
- | '(' ')' { };
-
fields:
fields ',' insert_ident { Lex->field_list.push_back($3); }
| insert_ident { Lex->field_list.push_back($1); };
@@ -4152,7 +6161,7 @@ ident_eq_list:
ident_eq_value;
ident_eq_value:
- simple_ident equal expr_or_default
+ simple_ident_nospvar equal expr_or_default
{
LEX *lex=Lex;
if (lex->field_list.push_back($1) ||
@@ -4201,7 +6210,7 @@ values:
expr_or_default:
expr { $$= $1;}
- | DEFAULT {$$= new Item_default_value(); }
+ | DEFAULT {$$= new Item_default_value(Lex->current_context()); }
;
opt_insert_update:
@@ -4226,19 +6235,20 @@ update:
{
LEX *lex= Lex;
if (lex->select_lex.table_list.elements > 1)
- {
lex->sql_command= SQLCOM_UPDATE_MULTI;
- lex->multi_lock_option= $3;
- }
else if (lex->select_lex.get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
- net_printf(lex->thd, ER_NON_UPDATABLE_TABLE,
- lex->select_lex.get_table_list()->alias, "UPDATE");
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
+ lex->select_lex.get_table_list()->alias, "UPDATE");
YYABORT;
}
- else
- Select->set_lock_for_tables($3);
+ /*
+ In case of multi-update setting write lock for all tables may
+ be too pessimistic. We will decrease lock level if possible in
+ mysql_multi_update().
+ */
+ Select->set_lock_for_tables($3);
}
where_clause opt_order_clause delete_limit_clause {}
;
@@ -4248,7 +6258,7 @@ update_list:
| update_elem;
update_elem:
- simple_ident equal expr_or_default
+ simple_ident_nospvar equal expr_or_default
{
if (add_item_to_list(YYTHD, $1) || add_value_to_list(YYTHD, $3))
YYABORT;
@@ -4259,13 +6269,13 @@ insert_update_list:
| insert_update_elem;
insert_update_elem:
- simple_ident equal expr_or_default
- {
+ simple_ident_nospvar equal expr_or_default
+ {
LEX *lex= Lex;
if (lex->update_list.push_back($1) ||
lex->value_list.push_back($3))
- YYABORT;
- };
+ YYABORT;
+ };
opt_low_priority:
/* empty */ { $$= YYTHD->update_lock_default; }
@@ -4278,7 +6288,7 @@ delete:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_DELETE;
- mysql_init_select(lex);
+ mysql_init_select(lex);
lex->lock_option= lex->thd->update_lock_default;
lex->ignore= 0;
lex->select_lex.init_order();
@@ -4295,11 +6305,20 @@ single_multi:
}
where_clause opt_order_clause
delete_limit_clause {}
- | table_wild_list {mysql_init_multi_delete(Lex);}
- FROM join_table_list {fix_multi_delete_lex(Lex);} where_clause
- | FROM table_wild_list { mysql_init_multi_delete(Lex);}
- USING join_table_list {fix_multi_delete_lex(Lex);} where_clause
- {}
+ | table_wild_list
+ { mysql_init_multi_delete(Lex); }
+ FROM join_table_list where_clause
+ {
+ if (multi_delete_set_locks_and_link_aux_tables(Lex))
+ YYABORT;
+ }
+ | FROM table_wild_list
+ { mysql_init_multi_delete(Lex); }
+ USING join_table_list where_clause
+ {
+ if (multi_delete_set_locks_and_link_aux_tables(Lex))
+ YYABORT;
+ }
;
table_wild_list:
@@ -4357,6 +6376,9 @@ show: SHOW
{
LEX *lex=Lex;
lex->wild=0;
+ lex->lock_option= TL_READ;
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
}
show_param
@@ -4364,42 +6386,67 @@ show: SHOW
;
show_param:
- DATABASES wild
- { Lex->sql_command= SQLCOM_SHOW_DATABASES; }
- | TABLES opt_db wild
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select_lex.db= $2;
- }
- | TABLE_SYM STATUS_SYM opt_db wild
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->describe= DESCRIBE_EXTENDED;
- lex->select_lex.db= $3;
- }
- | OPEN_SYM TABLES opt_db wild
+ DATABASES wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_DATABASES;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_SCHEMATA))
+ YYABORT;
+ }
+ | opt_full TABLES opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_TABLES;
+ lex->select_lex.db= $3;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES))
+ YYABORT;
+ }
+ | opt_full TRIGGERS_SYM opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_TRIGGERS;
+ lex->select_lex.db= $3;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
+ YYABORT;
+ }
+ | TABLE_SYM STATUS_SYM opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_TABLE_STATUS;
+ lex->select_lex.db= $3;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLES))
+ YYABORT;
+ }
+ | OPEN_SYM TABLES opt_db wild_and_where
{
LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_OPEN_TABLES;
lex->select_lex.db= $3;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
+ YYABORT;
}
| ENGINE_SYM storage_engines
{ Lex->create_info.db_type= $2; }
show_engine_param
- | opt_full COLUMNS from_or_in table_ident opt_db wild
+ | opt_full COLUMNS from_or_in table_ident opt_db wild_and_where
{
- Lex->sql_command= SQLCOM_SHOW_FIELDS;
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
if ($5)
$4->change_db($5);
- if (!Select->add_table_to_list(YYTHD, $4, NULL, 0))
+ if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS))
YYABORT;
}
| NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
TEXT_STRING_sys AND_SYM MASTER_LOG_POS_SYM EQ ulonglong_num
AND_SYM MASTER_SERVER_ID_SYM EQ
- ULONG_NUM
+ ulong_num
{
Lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
Lex->mi.log_file_name = $8.str;
@@ -4419,13 +6466,15 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
} opt_limit_clause_init
- | keys_or_index from_or_in table_ident opt_db
- {
- Lex->sql_command= SQLCOM_SHOW_KEYS;
+ | keys_or_index from_or_in table_ident opt_db where_clause
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_KEYS;
if ($4)
$3->change_db($4);
- if (!Select->add_table_to_list(YYTHD, $3, NULL, 0))
- YYABORT;
+ if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS))
+ YYABORT;
}
| COLUMN_SYM TYPES_SYM
{
@@ -4456,22 +6505,46 @@ show_param:
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
| ERRORS opt_limit_clause_init
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
- | STATUS_SYM wild
- { Lex->sql_command= SQLCOM_SHOW_STATUS; }
+ | opt_var_type STATUS_SYM wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_STATUS;
+ lex->option_type= $1;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS))
+ YYABORT;
+ }
| INNOBASE_SYM STATUS_SYM
{ Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS; WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS"); }
+ | MUTEX_SYM STATUS_SYM
+ { Lex->sql_command = SQLCOM_SHOW_MUTEX_STATUS; }
| opt_full PROCESSLIST_SYM
{ Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
- | opt_var_type VARIABLES wild
+ | opt_var_type VARIABLES wild_and_where
{
- THD *thd= YYTHD;
- thd->lex->sql_command= SQLCOM_SHOW_VARIABLES;
- thd->lex->option_type= (enum_var_type) $1;
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_VARIABLES;
+ lex->option_type= $1;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_VARIABLES))
+ YYABORT;
}
- | charset wild
- { Lex->sql_command= SQLCOM_SHOW_CHARSETS; }
- | COLLATION_SYM wild
- { Lex->sql_command= SQLCOM_SHOW_COLLATIONS; }
+ | charset wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_CHARSETS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_CHARSETS))
+ YYABORT;
+ }
+ | COLLATION_SYM wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_COLLATIONS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_COLLATIONS))
+ YYABORT;
+ }
| BERKELEY_DB_SYM LOGS_SYM
{ Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW BDB LOGS", "SHOW ENGINE BDB LOGS"); }
| LOGS_SYM
@@ -4496,7 +6569,7 @@ show_param:
curr_user->host.str= (char *) "%";
curr_user->host.length= 1;
}
- curr_user->password.str=NullS;
+ curr_user->password=null_lex_str;
lex->grant_user= curr_user;
}
| GRANTS FOR_SYM user
@@ -4504,7 +6577,7 @@ show_param:
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_GRANTS;
lex->grant_user=$3;
- lex->grant_user->password.str=NullS;
+ lex->grant_user->password=null_lex_str;
}
| CREATE DATABASE opt_if_not_exists ident
{
@@ -4514,9 +6587,19 @@ show_param:
}
| CREATE TABLE_SYM table_ident
{
- Lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!Select->add_table_to_list(YYTHD, $3, NULL,0))
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_SHOW_CREATE;
+ if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL,0))
+ YYABORT;
+ lex->only_view= 0;
+ }
+ | CREATE VIEW_SYM table_ident
+ {
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_SHOW_CREATE;
+ if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0))
YYABORT;
+ lex->only_view= 1;
}
| MASTER_SYM STATUS_SYM
{
@@ -4525,7 +6608,41 @@ show_param:
| SLAVE STATUS_SYM
{
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
- };
+ }
+ | CREATE PROCEDURE sp_name
+ {
+ LEX *lex= Lex;
+
+ lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
+ lex->spname= $3;
+ }
+ | CREATE FUNCTION_SYM sp_name
+ {
+ LEX *lex= Lex;
+
+ lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
+ lex->spname= $3;
+ }
+ | PROCEDURE STATUS_SYM wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_STATUS_PROC;
+ if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
+ YYABORT;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
+ YYABORT;
+ }
+ | FUNCTION_SYM STATUS_SYM wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_STATUS_FUNC;
+ if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
+ YYABORT;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
+ YYABORT;
+ };
show_engine_param:
STATUS_SYM
@@ -4535,7 +6652,7 @@ show_engine_param:
Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;
break;
default:
- net_printf(YYTHD, ER_NOT_SUPPORTED_YET, "STATUS");
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS");
YYABORT;
}
}
@@ -4546,7 +6663,7 @@ show_engine_param:
Lex->sql_command = SQLCOM_SHOW_LOGS;
break;
default:
- net_printf(YYTHD, ER_NOT_SUPPORTED_YET, "LOGS");
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "LOGS");
YYABORT;
}
};
@@ -4563,12 +6680,6 @@ opt_db:
/* empty */ { $$= 0; }
| from_or_in ident { $$= $2.str; };
-wild:
- /* empty */
- | LIKE TEXT_STRING_sys
- { Lex->wild= new (YYTHD->mem_root) String($2.str, $2.length,
- system_charset_info); };
-
opt_full:
/* empty */ { Lex->verbose=0; }
| FULL { Lex->verbose=1; };
@@ -4585,16 +6696,33 @@ binlog_from:
/* empty */ { Lex->mi.pos = 4; /* skip magic number */ }
| FROM ulonglong_num { Lex->mi.pos = $2; };
+wild_and_where:
+ /* empty */
+ | LIKE TEXT_STRING_sys
+ { Lex->wild= new (YYTHD->mem_root) String($2.str, $2.length,
+ system_charset_info); }
+ | WHERE expr
+ {
+ Select->where= $2;
+ if ($2)
+ $2->top_level_item();
+ }
+ ;
+
/* A Oracle compatible synonym for show */
describe:
describe_command table_ident
{
- LEX *lex=Lex;
- lex->wild=0;
- lex->verbose=0;
- lex->sql_command=SQLCOM_SHOW_FIELDS;
- if (!Select->add_table_to_list(lex->thd, $2, NULL,0))
+ LEX *lex= Lex;
+ lex->lock_option= TL_READ;
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
+ lex->select_lex.db= 0;
+ lex->verbose= 0;
+ if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS))
YYABORT;
}
opt_describe_column {}
@@ -4629,6 +6757,16 @@ flush:
FLUSH_SYM opt_no_write_to_binlog
{
LEX *lex=Lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ /*
+ Note that both FLUSH TABLES and FLUSH PRIVILEGES will break
+ execution in prelocked mode. So it is better to disable
+ FLUSH in stored functions and triggers completely.
+ */
+ my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH");
+ YYABORT;
+ }
lex->sql_command= SQLCOM_FLUSH; lex->type=0;
lex->no_write_to_binlog= $2;
}
@@ -4696,37 +6834,29 @@ purge_option:
}
| BEFORE_SYM expr
{
- if ($2->check_cols(1) || $2->fix_fields(Lex->thd, 0, &$2))
- {
- net_printf(Lex->thd, ER_WRONG_ARGUMENTS, "PURGE LOGS BEFORE");
- YYABORT;
- }
- Item *tmp= new Item_func_unix_timestamp($2);
- /*
- it is OK only emulate fix_fieds, because we need only
- value of constant
- */
- tmp->quick_fix_field();
- Lex->sql_command = SQLCOM_PURGE_BEFORE;
- Lex->purge_time= (ulong) tmp->val_int();
+ LEX *lex= Lex;
+ lex->value_list.empty();
+ lex->value_list.push_front($2);
+ lex->sql_command= SQLCOM_PURGE_BEFORE;
}
;
/* kill threads */
kill:
- KILL_SYM expr
+ KILL_SYM kill_option expr
{
LEX *lex=Lex;
- if ($2->fix_fields(lex->thd, 0, &$2) || $2->check_cols(1))
- {
- send_error(lex->thd, ER_SET_CONSTANTS_ONLY);
- YYABORT;
- }
- lex->sql_command=SQLCOM_KILL;
- lex->thread_id= (ulong) $2->val_int();
+ lex->value_list.empty();
+ lex->value_list.push_front($3);
+ lex->sql_command= SQLCOM_KILL;
};
+kill_option:
+ /* empty */ { Lex->type= 0; }
+ | CONNECTION_SYM { Lex->type= 0; }
+ | QUERY_SYM { Lex->type= ONLY_KILL_QUERY; };
+
/* change database */
use: USE_SYM ident
@@ -4738,34 +6868,64 @@ use: USE_SYM ident
/* import, export of files */
-load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING_sys
+load: LOAD DATA_SYM
+ {
+ LEX *lex=Lex;
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
+ YYABORT;
+ }
+ lex->fname_start= lex->ptr;
+ }
+ load_data
+ {}
+ |
+ LOAD TABLE_SYM table_ident FROM MASTER_SYM
+ {
+ LEX *lex=Lex;
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD TABLE");
+ YYABORT;
+ }
+ lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
+ if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
+ YYABORT;
+ };
+
+load_data:
+ load_data_lock opt_local INFILE TEXT_STRING_sys
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD;
- lex->lock_option= $3;
- lex->local_file= $4;
+ lex->lock_option= $1;
+ lex->local_file= $2;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
- if (!(lex->exchange= new sql_exchange($6.str,0)))
- YYABORT;
- lex->field_list.empty();
- }
- opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
- opt_ignore_lines opt_field_spec
- {
- if (!Select->add_table_to_list(YYTHD, $11, NULL, TL_OPTION_UPDATING))
+ if (!(lex->exchange= new sql_exchange($4.str, 0)))
YYABORT;
+ }
+ opt_duplicate INTO
+ {
+ LEX *lex=Lex;
+ lex->fname_end= lex->ptr;
}
- |
- LOAD TABLE_SYM table_ident FROM MASTER_SYM
+ TABLE_SYM table_ident
{
- Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
- if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
- YYABORT;
-
+ LEX *lex=Lex;
+ if (!Select->add_table_to_list(YYTHD, $10, NULL, TL_OPTION_UPDATING,
+ lex->lock_option))
+ YYABORT;
+ lex->field_list.empty();
+ lex->update_list.empty();
+ lex->value_list.empty();
}
+ opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
+ opt_load_data_set_spec
+ {}
|
- LOAD DATA_SYM FROM MASTER_SYM
+ FROM MASTER_SYM
{
Lex->sql_command = SQLCOM_LOAD_MASTER_DATA;
};
@@ -4796,24 +6956,24 @@ field_term_list:
field_term:
TERMINATED BY text_string
{
- DBUG_ASSERT(Lex->exchange);
+ DBUG_ASSERT(Lex->exchange != 0);
Lex->exchange->field_term= $3;
}
| OPTIONALLY ENCLOSED BY text_string
{
LEX *lex= Lex;
- DBUG_ASSERT(lex->exchange);
+ DBUG_ASSERT(lex->exchange != 0);
lex->exchange->enclosed= $4;
lex->exchange->opt_enclosed= 1;
}
| ENCLOSED BY text_string
{
- DBUG_ASSERT(Lex->exchange);
+ DBUG_ASSERT(Lex->exchange != 0);
Lex->exchange->enclosed= $3;
}
| ESCAPED BY text_string
{
- DBUG_ASSERT(Lex->exchange);
+ DBUG_ASSERT(Lex->exchange != 0);
Lex->exchange->escaped= $3;
};
@@ -4828,12 +6988,12 @@ line_term_list:
line_term:
TERMINATED BY text_string
{
- DBUG_ASSERT(Lex->exchange);
+ DBUG_ASSERT(Lex->exchange != 0);
Lex->exchange->line_term= $3;
}
| STARTING BY text_string
{
- DBUG_ASSERT(Lex->exchange);
+ DBUG_ASSERT(Lex->exchange != 0);
Lex->exchange->line_start= $3;
};
@@ -4841,10 +7001,33 @@ opt_ignore_lines:
/* empty */
| IGNORE_SYM NUM LINES
{
- DBUG_ASSERT(Lex->exchange);
+ DBUG_ASSERT(Lex->exchange != 0);
Lex->exchange->skip_lines= atol($2.str);
};
+opt_field_or_var_spec:
+ /* empty */ { }
+ | '(' fields_or_vars ')' { }
+ | '(' ')' { };
+
+fields_or_vars:
+ fields_or_vars ',' field_or_var
+ { Lex->field_list.push_back($3); }
+ | field_or_var
+ { Lex->field_list.push_back($1); }
+ ;
+
+field_or_var:
+ simple_ident_nospvar {$$= $1;}
+ | '@' ident_or_text
+ { $$= new Item_user_var_as_out_param($2); }
+ ;
+
+opt_load_data_set_spec:
+ /* empty */ { }
+ | SET insert_update_list { };
+
+
/* Common definitions */
text_literal:
@@ -4866,15 +7049,25 @@ text_string:
{ $$= new (YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); }
| HEX_NUM
{
- Item *tmp = new Item_varbinary($1.str,$1.length);
+ Item *tmp= new Item_hex_string($1.str, $1.length);
/*
- it is OK only emulate fix_fieds, because we need only
+ it is OK only emulate fix_fields, because we need only
value of constant
*/
$$= tmp ?
tmp->quick_fix_field(), tmp->val_str((String*) 0) :
(String*) 0;
}
+ | BIN_NUM
+ {
+ Item *tmp= new Item_bin_string($1.str, $1.length);
+ /*
+ it is OK only emulate fix_fields, because we need only
+ value of constant
+ */
+ $$= tmp ? tmp->quick_fix_field(), tmp->val_str((String*) 0) :
+ (String*) 0;
+ }
;
param_marker:
@@ -4886,7 +7079,7 @@ param_marker:
(uchar *) thd->query));
if (!($$= item) || lex->param_list.push_back(item))
{
- send_error(thd, ER_OUT_OF_RESOURCES);
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
YYABORT;
}
}
@@ -4910,10 +7103,11 @@ literal:
Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;}
| FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); }
| TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); }
- | HEX_NUM { $$ = new Item_varbinary($1.str,$1.length);}
+ | HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);}
+ | BIN_NUM { $$= new Item_bin_string($1.str, $1.length); }
| UNDERSCORE_CHARSET HEX_NUM
{
- Item *tmp= new Item_varbinary($2.str,$2.length);
+ Item *tmp= new Item_hex_string($2.str, $2.length);
/*
it is OK only emulate fix_fieds, because we need only
value of constant
@@ -4925,6 +7119,20 @@ literal:
str ? str->length() : 0,
Lex->charset);
}
+ | UNDERSCORE_CHARSET BIN_NUM
+ {
+ Item *tmp= new Item_bin_string($2.str, $2.length);
+ /*
+ it is OK only emulate fix_fieds, because we need only
+ value of constant
+ */
+ String *str= tmp ?
+ tmp->quick_fix_field(), tmp->val_str((String*) 0) :
+ (String*) 0;
+ $$= new Item_string(str ? str->ptr() : "",
+ str ? str->length() : 0,
+ Lex->charset);
+ }
| DATE_SYM text_literal { $$ = $2; }
| TIME_SYM text_literal { $$ = $2; }
| TIMESTAMP text_literal { $$ = $2; };
@@ -4933,30 +7141,46 @@ NUM_literal:
NUM { int error; $$ = new Item_int($1.str, (longlong) my_strtoll10($1.str, NULL, &error), $1.length); }
| LONG_NUM { int error; $$ = new Item_int($1.str, (longlong) my_strtoll10($1.str, NULL, &error), $1.length); }
| ULONGLONG_NUM { $$ = new Item_uint($1.str, $1.length); }
- | REAL_NUM { $$ = new Item_real($1.str, $1.length); }
- | FLOAT_NUM { $$ = new Item_float($1.str, $1.length); }
+ | DECIMAL_NUM
+ {
+ $$= new Item_decimal($1.str, $1.length, YYTHD->charset());
+ if (YYTHD->net.report_error)
+ {
+ YYABORT;
+ }
+ }
+ | FLOAT_NUM
+ {
+ $$ = new Item_float($1.str, $1.length);
+ if (YYTHD->net.report_error)
+ {
+ YYABORT;
+ }
+ }
;
-
+
/**********************************************************************
-** Createing different items.
+** Creating different items.
**********************************************************************/
insert_ident:
- simple_ident { $$=$1; }
+ simple_ident_nospvar { $$=$1; }
| table_wild { $$=$1; };
table_wild:
ident '.' '*'
{
- $$ = new Item_field(NullS,$1.str,"*");
- Lex->current_select->with_wild++;
+ SELECT_LEX *sel= Select;
+ $$ = new Item_field(Lex->current_context(), NullS, $1.str, "*");
+ sel->with_wild++;
}
| ident '.' ident '.' '*'
{
- $$ = new Item_field((YYTHD->client_capabilities &
- CLIENT_NO_SCHEMA ? NullS : $1.str),
- $3.str,"*");
- Lex->current_select->with_wild++;
+ SELECT_LEX *sel= Select;
+ $$ = new Item_field(Lex->current_context(), (YYTHD->client_capabilities &
+ CLIENT_NO_SCHEMA ? NullS : $1.str),
+ $3.str,"*");
+ sel->with_wild++;
}
;
@@ -4966,28 +7190,105 @@ order_ident:
simple_ident:
ident
{
+ sp_pvar_t *spv;
+ LEX *lex = Lex;
+ sp_pcontext *spc = lex->spcont;
+ if (spc && (spv = spc->find_pvar(&$1)))
+ {
+ /* We're compiling a stored procedure and found a variable */
+ Item_splocal *splocal;
+ splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev -
+ lex->sphead->m_tmp_query);
+ $$ = (Item*) splocal;
+ lex->variables_used= 1;
+ lex->safe_to_cache_query=0;
+ }
+ else
+ {
+ SELECT_LEX *sel=Select;
+ $$= (sel->parsing_place != IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) :
+ (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str);
+ }
+ }
+ | simple_ident_q { $$= $1; }
+ ;
+
+simple_ident_nospvar:
+ ident
+ {
SELECT_LEX *sel=Select;
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field(NullS,NullS,$1.str) :
- (Item*) new Item_ref(NullS, NullS, $1.str);
+ (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) :
+ (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str);
}
- | ident '.' ident
+ | simple_ident_q { $$= $1; }
+ ;
+
+simple_ident_q:
+ ident '.' ident
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
- SELECT_LEX *sel= lex->current_select;
- if (sel->no_table_names_allowed)
- {
- my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- ER(ER_TABLENAME_NOT_ALLOWED_HERE),
- MYF(0), $1.str, thd->where);
- }
- $$= (sel->parsing_place != IN_HAVING ||
- sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field(NullS,$1.str,$3.str) :
- (Item*) new Item_ref(NullS, $1.str, $3.str);
- }
+
+ /*
+ FIXME This will work ok in simple_ident_nospvar case because
+ we can't meet simple_ident_nospvar in trigger now. But it
+ should be changed in future.
+ */
+ if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER &&
+ (!my_strcasecmp(system_charset_info, $1.str, "NEW") ||
+ !my_strcasecmp(system_charset_info, $1.str, "OLD")))
+ {
+ Item_trigger_field *trg_fld;
+ bool new_row= ($1.str[0]=='N' || $1.str[0]=='n');
+
+ if (lex->trg_chistics.event == TRG_EVENT_INSERT &&
+ !new_row)
+ {
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
+ YYABORT;
+ }
+
+ if (lex->trg_chistics.event == TRG_EVENT_DELETE &&
+ new_row)
+ {
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
+ YYABORT;
+ }
+
+ if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
+ new_row ?
+ Item_trigger_field::NEW_ROW:
+ Item_trigger_field::OLD_ROW,
+ $3.str)))
+ YYABORT;
+
+ /*
+ Let us add this item to list of all Item_trigger_field objects
+ in trigger.
+ */
+ lex->trg_table_fields.link_in_list((byte *)trg_fld,
+ (byte**)&trg_fld->next_trg_field);
+
+ $$= (Item *)trg_fld;
+ }
+ else
+ {
+ SELECT_LEX *sel= lex->current_select;
+ if (sel->no_table_names_allowed)
+ {
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ MYF(0), $1.str, thd->where);
+ }
+ $$= (sel->parsing_place != IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field(Lex->current_context(), NullS, $1.str, $3.str) :
+ (Item*) new Item_ref(Lex->current_context(), NullS, $1.str, $3.str);
+ }
+ }
| '.' ident '.' ident
{
THD *thd= YYTHD;
@@ -4995,14 +7296,13 @@ simple_ident:
SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
{
- my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- ER(ER_TABLENAME_NOT_ALLOWED_HERE),
- MYF(0), $2.str, thd->where);
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ MYF(0), $2.str, thd->where);
}
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field(NullS,$2.str,$4.str) :
- (Item*) new Item_ref(NullS, $2.str, $4.str);
+ (Item*) new Item_field(Lex->current_context(), NullS, $2.str, $4.str) :
+ (Item*) new Item_ref(Lex->current_context(), NullS, $2.str, $4.str);
}
| ident '.' ident '.' ident
{
@@ -5011,16 +7311,17 @@ simple_ident:
SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
{
- my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- ER(ER_TABLENAME_NOT_ALLOWED_HERE),
- MYF(0), $3.str, thd->where);
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ MYF(0), $3.str, thd->where);
}
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field((YYTHD->client_capabilities &
+ (Item*) new Item_field(Lex->current_context(),
+ (YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str, $5.str) :
- (Item*) new Item_ref((YYTHD->client_capabilities &
+ (Item*) new Item_ref(Lex->current_context(),
+ (YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str, $5.str);
};
@@ -5033,12 +7334,13 @@ field_ident:
TABLE_LIST *table= (TABLE_LIST*) Select->table_list.first;
if (my_strcasecmp(table_alias_charset, $1.str, table->db))
{
- net_printf(YYTHD, ER_WRONG_DB_NAME, $1.str);
+ my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
YYABORT;
}
- if (my_strcasecmp(table_alias_charset, $3.str, table->real_name))
+ if (my_strcasecmp(table_alias_charset, $3.str,
+ table->table_name))
{
- net_printf(YYTHD, ER_WRONG_TABLE_NAME, $3.str);
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), $3.str);
YYABORT;
}
$$=$5;
@@ -5048,7 +7350,7 @@ field_ident:
TABLE_LIST *table= (TABLE_LIST*) Select->table_list.first;
if (my_strcasecmp(table_alias_charset, $1.str, table->alias))
{
- net_printf(YYTHD, ER_WRONG_TABLE_NAME, $1.str);
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), $1.str);
YYABORT;
}
$$=$3;
@@ -5079,8 +7381,8 @@ IDENT_sys:
$1.length, &dummy_error);
if (wlen < $1.length)
{
- net_printf(YYTHD, ER_INVALID_CHARACTER_STRING, cs->csname,
- $1.str + wlen);
+ my_error(ER_INVALID_CHARACTER_STRING, MYF(0),
+ cs->csname, $1.str + wlen);
YYABORT;
}
$$= $1;
@@ -5126,8 +7428,18 @@ ident:
}
;
+label_ident:
+ IDENT_sys { $$=$1; }
+ | keyword_sp
+ {
+ THD *thd= YYTHD;
+ $$.str= thd->strmake($1.str, $1.length);
+ $$.length= $1.length;
+ }
+ ;
+
ident_or_text:
- ident { $$=$1;}
+ ident { $$=$1;}
| TEXT_STRING_sys { $$=$1;}
| LEX_HOSTNAME { $$=$1;};
@@ -5167,39 +7479,78 @@ user:
}
};
-/* Keyword that we allow for identifiers */
-
+/* Keyword that we allow for identifiers (except SP labels) */
keyword:
+ keyword_sp {}
+ | ASCII_SYM {}
+ | BACKUP_SYM {}
+ | BEGIN_SYM {}
+ | BYTE_SYM {}
+ | CACHE_SYM {}
+ | CHARSET {}
+ | CHECKSUM_SYM {}
+ | CLOSE_SYM {}
+ | COMMENT_SYM {}
+ | COMMIT_SYM {}
+ | CONTAINS_SYM {}
+ | DEALLOCATE_SYM {}
+ | DO_SYM {}
+ | END {}
+ | EXECUTE_SYM {}
+ | FLUSH_SYM {}
+ | HANDLER_SYM {}
+ | HELP_SYM {}
+ | LANGUAGE_SYM {}
+ | NO_SYM {}
+ | OPEN_SYM {}
+ | PREPARE_SYM {}
+ | REPAIR {}
+ | RESET_SYM {}
+ | RESTORE_SYM {}
+ | ROLLBACK_SYM {}
+ | SAVEPOINT_SYM {}
+ | SECURITY_SYM {}
+ | SIGNED_SYM {}
+ | SLAVE {}
+ | START_SYM {}
+ | STOP_SYM {}
+ | TRUNCATE_SYM {}
+ | UNICODE_SYM {}
+ | XA_SYM {}
+ ;
+
+/*
+ * Keywords that we allow for labels in SPs.
+ * Anything that's the beginning of a statement or characteristics
+ * must be in keyword above, otherwise we get (harmful) shift/reduce
+ * conflicts.
+ */
+keyword_sp:
ACTION {}
| ADDDATE_SYM {}
| AFTER_SYM {}
| AGAINST {}
| AGGREGATE_SYM {}
+ | ALGORITHM_SYM {}
| ANY_SYM {}
- | ASCII_SYM {}
| AUTO_INC {}
| AVG_ROW_LENGTH {}
| AVG_SYM {}
- | BACKUP_SYM {}
- | BEGIN_SYM {}
| BERKELEY_DB_SYM {}
| BINLOG_SYM {}
| BIT_SYM {}
| BOOL_SYM {}
| BOOLEAN_SYM {}
- | BYTE_SYM {}
| BTREE_SYM {}
- | CACHE_SYM {}
+ | CASCADED {}
+ | CHAIN_SYM {}
| CHANGED {}
- | CHARSET {}
- | CHECKSUM_SYM {}
| CIPHER_SYM {}
| CLIENT_SYM {}
- | CLOSE_SYM {}
| COLLATION_SYM {}
- | COMMENT_SYM {}
+ | COLUMNS {}
| COMMITTED_SYM {}
- | COMMIT_SYM {}
+ | COMPACT_SYM {}
| COMPRESSED_SYM {}
| CONCURRENT {}
| CONSISTENT_SYM {}
@@ -5208,44 +7559,41 @@ keyword:
| DATETIME {}
| DATE_SYM {}
| DAY_SYM {}
- | DEALLOCATE_SYM {}
+ | DEFINER_SYM {}
| DELAY_KEY_WRITE_SYM {}
| DES_KEY_FILE {}
| DIRECTORY_SYM {}
| DISCARD {}
- | DO_SYM {}
| DUMPFILE {}
| DUPLICATE_SYM {}
| DYNAMIC_SYM {}
- | END {}
| ENUM {}
| ENGINE_SYM {}
| ENGINES_SYM {}
| ERRORS {}
| ESCAPE_SYM {}
| EVENTS_SYM {}
- | EXECUTE_SYM {}
| EXPANSION_SYM {}
| EXTENDED_SYM {}
| FAST_SYM {}
+ | FOUND_SYM {}
| DISABLE_SYM {}
| ENABLE_SYM {}
| FULL {}
| FILE_SYM {}
| FIRST_SYM {}
| FIXED_SYM {}
- | FLUSH_SYM {}
+ | FRAC_SECOND_SYM {}
| GEOMETRY_SYM {}
| GEOMETRYCOLLECTION {}
| GET_FORMAT {}
| GRANTS {}
| GLOBAL_SYM {}
- | HANDLER_SYM {}
| HASH_SYM {}
- | HELP_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
+ | INVOKER_SYM {}
| IMPORT {}
| INDEXES {}
| ISOLATION {}
@@ -5279,8 +7627,11 @@ keyword:
| MAX_CONNECTIONS_PER_HOUR {}
| MAX_QUERIES_PER_HOUR {}
| MAX_UPDATES_PER_HOUR {}
+ | MAX_USER_CONNECTIONS_SYM {}
| MEDIUM_SYM {}
+ | MERGE_SYM {}
| MICROSECOND_SYM {}
+ | MIGRATE_SYM {}
| MINUTE_SYM {}
| MIN_ROWS {}
| MODIFY_SYM {}
@@ -5289,28 +7640,31 @@ keyword:
| MULTILINESTRING {}
| MULTIPOINT {}
| MULTIPOLYGON {}
+ | MUTEX_SYM {}
+ | NAME_SYM {}
| NAMES_SYM {}
| NATIONAL_SYM {}
| NCHAR_SYM {}
| NDBCLUSTER_SYM {}
| NEXT_SYM {}
| NEW_SYM {}
- | NO_SYM {}
| NONE_SYM {}
| NVARCHAR_SYM {}
| OFFSET_SYM {}
| OLD_PASSWORD {}
| ONE_SHOT_SYM {}
- | OPEN_SYM {}
+ | ONE_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
| PASSWORD {}
+ | PHASE_SYM {}
| POINT_SYM {}
| POLYGON {}
- | PREPARE_SYM {}
| PREV_SYM {}
+ | PRIVILEGES {}
| PROCESS {}
| PROCESSLIST_SYM {}
+ | QUARTER_SYM {}
| QUERY_SYM {}
| QUICK {}
| RAID_0_SYM {}
@@ -5318,64 +7672,68 @@ keyword:
| RAID_CHUNKSIZE {}
| RAID_STRIPED_SYM {}
| RAID_TYPE {}
+ | RECOVER_SYM {}
+ | REDUNDANT_SYM {}
| RELAY_LOG_FILE_SYM {}
| RELAY_LOG_POS_SYM {}
| RELOAD {}
- | REPAIR {}
| REPEATABLE_SYM {}
| REPLICATION {}
- | RESET_SYM {}
| RESOURCES {}
- | RESTORE_SYM {}
- | ROLLBACK_SYM {}
+ | RESUME_SYM {}
+ | RETURNS_SYM {}
| ROLLUP_SYM {}
+ | ROUTINE_SYM {}
| ROWS_SYM {}
| ROW_FORMAT_SYM {}
| ROW_SYM {}
| RTREE_SYM {}
- | SAVEPOINT_SYM {}
| SECOND_SYM {}
| SERIAL_SYM {}
| SERIALIZABLE_SYM {}
| SESSION_SYM {}
- | SIGNED_SYM {}
| SIMPLE_SYM {}
| SHARE_SYM {}
| SHUTDOWN {}
- | SLAVE {}
| SNAPSHOT_SYM {}
| SOUNDS_SYM {}
| SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {}
| SQL_THREAD {}
- | START_SYM {}
| STATUS_SYM {}
- | STOP_SYM {}
| STORAGE_SYM {}
| STRING_SYM {}
| SUBDATE_SYM {}
| SUBJECT_SYM {}
| SUPER_SYM {}
+ | SUSPEND_SYM {}
+ | TABLES {}
| TABLESPACE {}
| TEMPORARY {}
+ | TEMPTABLE_SYM {}
| TEXT_SYM {}
| TRANSACTION_SYM {}
- | TRUNCATE_SYM {}
+ | TRIGGERS_SYM {}
| TIMESTAMP {}
+ | TIMESTAMP_ADD {}
+ | TIMESTAMP_DIFF {}
| TIME_SYM {}
- | TYPE_SYM {}
| TYPES_SYM {}
+ | TYPE_SYM {}
| UDF_RETURNS_SYM {}
- | UDF_SYM {}
+ | FUNCTION_SYM {}
| UNCOMMITTED_SYM {}
- | UNICODE_SYM {}
+ | UNDEFINED_SYM {}
+ | UNKNOWN_SYM {}
| UNTIL_SYM {}
| USER {}
| USE_FRM {}
| VARIABLES {}
+ | VIEW_SYM {}
| VALUE_SYM {}
| WARNINGS {}
+ | WEEK_SYM {}
| WORK_SYM {}
| X509_SYM {}
| YEAR_SYM {}
@@ -5388,7 +7746,7 @@ set:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SET_OPTION;
- mysql_init_select(lex);
+ mysql_init_select(lex);
lex->option_type=OPT_SESSION;
lex->var_list.empty();
lex->one_shot_set= 0;
@@ -5402,25 +7760,87 @@ opt_option:
| OPTION {};
option_value_list:
- option_value_ext
- | option_value_list ',' option_value_ext;
+ option_type_value
+ | option_value_list ',' option_type_value;
-option_value_ext:
- option_type_ext sys_option_value {}
- | option_type option_value {}
- ;
+option_type_value:
+ {
+ if (Lex->sphead)
+ {
+ /*
+ If we are in SP we want have own LEX for each assignment.
+ This is mostly because it is hard for several sp_instr_set
+ and sp_instr_set_trigger instructions share one LEX.
+ (Well, it is theoretically possible but adds some extra
+ overhead on preparation for execution stage and IMO less
+ robust).
+
+ QQ: May be we should simply prohibit group assignments in SP?
+ */
+ LEX *lex;
+ Lex->sphead->reset_lex(YYTHD);
+ lex= Lex;
+
+ /* Set new LEX as if we at start of set rule. */
+ lex->sql_command= SQLCOM_SET_OPTION;
+ mysql_init_select(lex);
+ lex->option_type=OPT_SESSION;
+ lex->var_list.empty();
+ lex->one_shot_set= 0;
+ lex->sphead->m_tmp_query= lex->tok_start;
+ }
+ }
+ ext_option_value
+ {
+ LEX *lex= Lex;
-option_type_ext:
- option_type {}
- | GLOBAL_SYM { Lex->option_type= OPT_GLOBAL; }
- | LOCAL_SYM { Lex->option_type= OPT_SESSION; }
- | SESSION_SYM { Lex->option_type= OPT_SESSION; }
- ;
+ if (lex->sphead)
+ {
+ sp_head *sp= lex->sphead;
+
+ if (!lex->var_list.is_empty())
+ {
+ /*
+ We have assignment to user or system variable or
+ option setting, so we should construct sp_instr_stmt
+ for it.
+ */
+ LEX_STRING qbuff;
+ sp_instr_stmt *i;
+
+ if (!(i= new sp_instr_stmt(sp->instructions(), lex->spcont,
+ lex)))
+ YYABORT;
+
+ if (lex->ptr - lex->tok_end > 1)
+ qbuff.length= lex->ptr - sp->m_tmp_query;
+ else
+ qbuff.length= lex->tok_end - sp->m_tmp_query;
+
+ if (!(qbuff.str= alloc_root(YYTHD->mem_root, qbuff.length + 5)))
+ YYABORT;
+
+ strmake(strmake(qbuff.str, "SET ", 4), (char *)sp->m_tmp_query,
+ qbuff.length);
+ qbuff.length+= 4;
+ i->m_query= qbuff;
+ sp->add_instr(i);
+ }
+ lex->sphead->restore_lex(YYTHD);
+ }
+ };
option_type:
- /* empty */ {}
- | ONE_SHOT_SYM { Lex->option_type= OPT_SESSION; Lex->one_shot_set= 1; }
- ;
+ option_type2 {}
+ | GLOBAL_SYM { $$=OPT_GLOBAL; }
+ | LOCAL_SYM { $$=OPT_SESSION; }
+ | SESSION_SYM { $$=OPT_SESSION; }
+ ;
+
+option_type2:
+ /* empty */ { $$= OPT_DEFAULT; }
+ | ONE_SHOT_SYM { Lex->one_shot_set= 1; $$= OPT_SESSION; }
+ ;
opt_var_type:
/* empty */ { $$=OPT_SESSION; }
@@ -5436,37 +7856,109 @@ opt_var_ident_type:
| SESSION_SYM '.' { $$=OPT_SESSION; }
;
+ext_option_value:
+ sys_option_value
+ | option_type2 option_value;
+
sys_option_value:
- internal_variable_name equal set_expr_or_default
+ option_type internal_variable_name equal set_expr_or_default
{
LEX *lex=Lex;
- lex->var_list.push_back(new set_var(lex->option_type, $1.var,
- &$1.base_name, $3));
+
+ if ($2.var == &trg_new_row_fake_var)
+ {
+ /* We are in trigger and assigning value to field of new row */
+ Item *it;
+ Item_trigger_field *trg_fld;
+ sp_instr_set_trigger_field *sp_fld;
+ LINT_INIT(sp_fld);
+ if ($1)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ if ($4)
+ it= $4;
+ else
+ {
+ /* QQ: Shouldn't this be field's default value ? */
+ it= new Item_null();
+ }
+
+ if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
+ Item_trigger_field::NEW_ROW,
+ $2.base_name.str)) ||
+ !(sp_fld= new sp_instr_set_trigger_field(lex->sphead->
+ instructions(),
+ lex->spcont,
+ trg_fld,
+ it, lex)))
+ YYABORT;
+
+ /*
+ Let us add this item to list of all Item_trigger_field
+ objects in trigger.
+ */
+ lex->trg_table_fields.link_in_list((byte *)trg_fld,
+ (byte **)&trg_fld->next_trg_field);
+
+ lex->sphead->add_instr(sp_fld);
+ }
+ else if ($2.var)
+ { /* System variable */
+ if ($1)
+ lex->option_type= $1;
+ lex->var_list.push_back(new set_var(lex->option_type, $2.var,
+ &$2.base_name, $4));
+ }
+ else
+ {
+ /* An SP local variable */
+ sp_pcontext *ctx= lex->spcont;
+ sp_pvar_t *spv;
+ sp_instr_set *sp_set;
+ Item *it;
+ if ($1)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+
+ spv= ctx->find_pvar(&$2.base_name);
+
+ if ($4)
+ it= $4;
+ else if (spv->dflt)
+ it= spv->dflt;
+ else
+ it= new Item_null();
+ sp_set= new sp_instr_set(lex->sphead->instructions(), ctx,
+ spv->offset, it, spv->type, lex, TRUE);
+ lex->sphead->add_instr(sp_set);
+ }
}
- | TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types
- {
- LEX *lex=Lex;
- LEX_STRING tmp;
- tmp.str=0;
- tmp.length=0;
- lex->var_list.push_back(new set_var(lex->option_type,
+ | option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types
+ {
+ LEX *lex=Lex;
+ if ($1)
+ lex->option_type= $1;
+ lex->var_list.push_back(new set_var(lex->option_type,
find_sys_var("tx_isolation"),
- &tmp,
- new Item_int((int32) $4)));
- }
+ &null_lex_str,
+ new Item_int((int32) $5)));
+ }
;
option_value:
'@' ident_or_text equal expr
{
- Lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4)));
+ Lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4)));
}
| '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default
- {
- LEX *lex=Lex;
- lex->var_list.push_back(new set_var((enum_var_type) $3, $4.var,
- &$4.base_name, $6));
- }
+ {
+ LEX *lex=Lex;
+ lex->var_list.push_back(new set_var($3, $4.var, &$4.base_name, $6));
+ }
| charset old_or_new_charset_name_or_default
{
THD *thd= YYTHD;
@@ -5476,13 +7968,13 @@ option_value:
}
| NAMES_SYM charset_name_or_default opt_collate
{
- THD *thd= YYTHD;
LEX *lex= Lex;
$2= $2 ? $2 : global_system_variables.character_set_client;
$3= $3 ? $3 : $2;
if (!my_charset_same($2,$3))
{
- net_printf(thd,ER_COLLATION_CHARSET_MISMATCH,$3->name,$2->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $3->name, $2->csname);
YYABORT;
}
lex->var_list.push_back(new set_var_collation_client($3,$3,$3));
@@ -5493,7 +7985,7 @@ option_value:
LEX_USER *user;
if (!(user=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
YYABORT;
- user->host.str=0;
+ user->host=null_lex_str;
user->user.str=thd->priv_user;
thd->lex->var_list.push_back(new set_var_password(user, $3));
}
@@ -5506,33 +7998,84 @@ option_value:
internal_variable_name:
ident
{
- sys_var *tmp=find_sys_var($1.str, $1.length);
- if (!tmp)
- YYABORT;
- $$.var= tmp;
- $$.base_name.str=0;
- $$.base_name.length=0;
- /*
- If this is time_zone variable we should open time zone
- describing tables
- */
- if (tmp == &sys_time_zone)
- Lex->time_zone_tables_used= &fake_time_zone_tables_list;
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+ sp_pvar_t *spv;
+
+ /* We have to lookup here since local vars can shadow sysvars */
+ if (!spc || !(spv = spc->find_pvar(&$1)))
+ {
+ /* Not an SP local variable */
+ sys_var *tmp=find_sys_var($1.str, $1.length);
+ if (!tmp)
+ YYABORT;
+ $$.var= tmp;
+ $$.base_name= null_lex_str;
+ /*
+ If this is time_zone variable we should open time zone
+ describing tables
+ */
+ if (tmp == &sys_time_zone &&
+ lex->add_time_zone_tables_to_query_tables(YYTHD))
+ YYABORT;
+ else if (spc && tmp == &sys_autocommit)
+ {
+ /*
+ We don't allow setting AUTOCOMMIT from a stored function
+ or trigger.
+ */
+ lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
+ }
+ }
+ else
+ {
+ /* An SP local variable */
+ $$.var= NULL;
+ $$.base_name= $1;
+ }
}
| ident '.' ident
{
+ LEX *lex= Lex;
if (check_reserved_words(&$1))
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
- sys_var *tmp=find_sys_var($3.str, $3.length);
- if (!tmp)
- YYABORT;
- if (!tmp->is_struct())
- net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
- $$.var= tmp;
- $$.base_name= $1;
+ if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER &&
+ (!my_strcasecmp(system_charset_info, $1.str, "NEW") ||
+ !my_strcasecmp(system_charset_info, $1.str, "OLD")))
+ {
+ if ($1.str[0]=='O' || $1.str[0]=='o')
+ {
+ my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", "");
+ YYABORT;
+ }
+ if (lex->trg_chistics.event == TRG_EVENT_DELETE)
+ {
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0),
+ "NEW", "on DELETE");
+ YYABORT;
+ }
+ if (lex->trg_chistics.action_time == TRG_ACTION_AFTER)
+ {
+ my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
+ YYABORT;
+ }
+ /* This special combination will denote field of NEW row */
+ $$.var= &trg_new_row_fake_var;
+ $$.base_name= $3;
+ }
+ else
+ {
+ sys_var *tmp=find_sys_var($3.str, $3.length);
+ if (!tmp)
+ YYABORT;
+ if (!tmp->is_struct())
+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str);
+ $$.var= tmp;
+ $$.base_name= $1;
+ }
}
| DEFAULT '.' ident
{
@@ -5540,7 +8083,7 @@ internal_variable_name:
if (!tmp)
YYABORT;
if (!tmp->is_struct())
- net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str);
$$.var= tmp;
$$.base_name.str= (char*) "default";
$$.base_name.length= 7;
@@ -5585,7 +8128,14 @@ set_expr_or_default:
lock:
LOCK_SYM table_or_tables
{
- Lex->sql_command=SQLCOM_LOCK_TABLES;
+ LEX *lex= Lex;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "LOCK");
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_LOCK_TABLES;
}
table_lock_list
{}
@@ -5615,7 +8165,19 @@ lock_option:
;
unlock:
- UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
+ UNLOCK_SYM
+ {
+ LEX *lex= Lex;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "UNLOCK");
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_UNLOCK_TABLES;
+ }
+ table_or_tables
+ {}
;
@@ -5627,6 +8189,11 @@ handler:
HANDLER_SYM table_ident OPEN_SYM opt_table_alias
{
LEX *lex= Lex;
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
+ YYABORT;
+ }
lex->sql_command = SQLCOM_HA_OPEN;
if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
YYABORT;
@@ -5634,6 +8201,11 @@ handler:
| HANDLER_SYM table_ident_nodb CLOSE_SYM
{
LEX *lex= Lex;
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
+ YYABORT;
+ }
lex->sql_command = SQLCOM_HA_CLOSE;
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT;
@@ -5641,10 +8213,15 @@ handler:
| HANDLER_SYM table_ident_nodb READ_SYM
{
LEX *lex=Lex;
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
+ YYABORT;
+ }
lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
- lex->current_select->select_limit= 1;
- lex->current_select->offset_limit= 0L;
+ lex->current_select->select_limit= new Item_int((int32) 1);
+ lex->current_select->offset_limit= 0;
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT;
}
@@ -5652,8 +8229,8 @@ handler:
;
handler_read_or_scan:
- handler_scan_function { Lex->backup_dir= 0; }
- | ident handler_rkey_function { Lex->backup_dir= $1.str; }
+ handler_scan_function { Lex->ident= null_lex_str; }
+ | ident handler_rkey_function { Lex->ident= $1; }
;
handler_scan_function:
@@ -5687,53 +8264,101 @@ handler_rkey_mode:
/* GRANT / REVOKE */
revoke:
- REVOKE
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_REVOKE;
- lex->users_list.empty();
- lex->columns.empty();
- lex->grant= lex->grant_tot_col=0;
- lex->select_lex.db=0;
- lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
- lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
- bzero((char*) &lex->mqh, sizeof(lex->mqh));
- }
- revoke_command
+ REVOKE clear_privileges revoke_command
{}
;
revoke_command:
- grant_privileges ON opt_table FROM user_list
- {}
+ grant_privileges ON opt_table grant_ident FROM grant_list
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= 0;
+ }
+ |
+ grant_privileges ON FUNCTION_SYM grant_ident FROM grant_list
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= TYPE_ENUM_FUNCTION;
+
+ }
|
- ALL opt_privileges ',' GRANT OPTION FROM user_list
+ grant_privileges ON PROCEDURE grant_ident FROM grant_list
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= TYPE_ENUM_PROCEDURE;
+ }
+ |
+ ALL opt_privileges ',' GRANT OPTION FROM grant_list
{
Lex->sql_command = SQLCOM_REVOKE_ALL;
}
;
grant:
- GRANT
+ GRANT clear_privileges grant_command
+ {}
+ ;
+
+grant_command:
+ grant_privileges ON opt_table grant_ident TO_SYM grant_list
+ require_clause grant_options
{
- LEX *lex=Lex;
- lex->users_list.empty();
- lex->columns.empty();
- lex->sql_command = SQLCOM_GRANT;
- lex->grant= lex->grant_tot_col= 0;
- lex->select_lex.db= 0;
- lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
- lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
- bzero((char *)&(lex->mqh),sizeof(lex->mqh));
- }
- grant_privileges ON opt_table TO_SYM user_list
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= 0;
+ }
+ |
+ grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list
require_clause grant_options
- {}
- ;
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= TYPE_ENUM_FUNCTION;
+ }
+ |
+ grant_privileges ON PROCEDURE grant_ident TO_SYM grant_list
+ require_clause grant_options
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= TYPE_ENUM_PROCEDURE;
+ }
+ ;
+opt_table:
+ /* Empty */
+ | TABLE_SYM ;
+
grant_privileges:
- grant_privilege_list {}
- | ALL opt_privileges { Lex->grant = GLOBAL_ACLS;}
+ object_privilege_list { }
+ | ALL opt_privileges
+ {
+ Lex->all_privileges= 1;
+ Lex->grant= GLOBAL_ACLS;
+ }
;
opt_privileges:
@@ -5741,11 +8366,11 @@ opt_privileges:
| PRIVILEGES
;
-grant_privilege_list:
- grant_privilege
- | grant_privilege_list ',' grant_privilege;
+object_privilege_list:
+ object_privilege
+ | object_privilege_list ',' object_privilege;
-grant_privilege:
+object_privilege:
SELECT_SYM { Lex->which_columns = SELECT_ACL;} opt_column_list {}
| INSERT { Lex->which_columns = INSERT_ACL;} opt_column_list {}
| UPDATE_SYM { Lex->which_columns = UPDATE_ACL; } opt_column_list {}
@@ -5766,8 +8391,13 @@ grant_privilege:
| SUPER_SYM { Lex->grant |= SUPER_ACL;}
| CREATE TEMPORARY TABLES { Lex->grant |= CREATE_TMP_ACL;}
| LOCK_SYM TABLES { Lex->grant |= LOCK_TABLES_ACL; }
- | REPLICATION SLAVE { Lex->grant |= REPL_SLAVE_ACL;}
- | REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL;}
+ | REPLICATION SLAVE { Lex->grant |= REPL_SLAVE_ACL; }
+ | REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL; }
+ | CREATE VIEW_SYM { Lex->grant |= CREATE_VIEW_ACL; }
+ | SHOW VIEW_SYM { Lex->grant |= SHOW_VIEW_ACL; }
+ | CREATE ROUTINE_SYM { Lex->grant |= CREATE_PROC_ACL; }
+ | ALTER ROUTINE_SYM { Lex->grant |= ALTER_PROC_ACL; }
+ | CREATE USER { Lex->grant |= CREATE_USER_ACL; }
;
@@ -5787,7 +8417,7 @@ require_list_element:
LEX *lex=Lex;
if (lex->x509_subject)
{
- net_printf(lex->thd,ER_DUP_ARGUMENT, "SUBJECT");
+ my_error(ER_DUP_ARGUMENT, MYF(0), "SUBJECT");
YYABORT;
}
lex->x509_subject=$2.str;
@@ -5797,7 +8427,7 @@ require_list_element:
LEX *lex=Lex;
if (lex->x509_issuer)
{
- net_printf(lex->thd,ER_DUP_ARGUMENT, "ISSUER");
+ my_error(ER_DUP_ARGUMENT, MYF(0), "ISSUER");
YYABORT;
}
lex->x509_issuer=$2.str;
@@ -5807,14 +8437,14 @@ require_list_element:
LEX *lex=Lex;
if (lex->ssl_cipher)
{
- net_printf(lex->thd,ER_DUP_ARGUMENT, "CIPHER");
+ my_error(ER_DUP_ARGUMENT, MYF(0), "CIPHER");
YYABORT;
}
lex->ssl_cipher=$2.str;
}
;
-opt_table:
+grant_ident:
'*'
{
LEX *lex= Lex;
@@ -5823,7 +8453,8 @@ opt_table:
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
+ ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
YYABORT;
}
}
@@ -5835,7 +8466,8 @@ opt_table:
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
+ ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
YYABORT;
}
}
@@ -5847,7 +8479,8 @@ opt_table:
lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
+ ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
YYABORT;
}
}
@@ -5863,8 +8496,18 @@ opt_table:
user_list:
+ user { if (Lex->users_list.push_back($1)) YYABORT;}
+ | user_list ',' user
+ {
+ if (Lex->users_list.push_back($3))
+ YYABORT;
+ }
+ ;
+
+
+grant_list:
grant_user { if (Lex->users_list.push_back($1)) YYABORT;}
- | user_list ',' grant_user
+ | grant_list ',' grant_user
{
if (Lex->users_list.push_back($3))
YYABORT;
@@ -5899,9 +8542,9 @@ grant_user:
}
}
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
- { $$=$1; $1->password=$5 ; }
+ { $$= $1; $1->password= $5; }
| user
- { $$=$1; $1->password.str=NullS; }
+ { $$= $1; $1->password= null_lex_str; }
;
@@ -5969,52 +8612,124 @@ grant_option_list:
grant_option:
GRANT OPTION { Lex->grant |= GRANT_ACL;}
- | MAX_QUERIES_PER_HOUR ULONG_NUM
+ | MAX_QUERIES_PER_HOUR ulong_num
{
- Lex->mqh.questions=$2;
- Lex->mqh.bits |= 1;
+ LEX *lex=Lex;
+ lex->mqh.questions=$2;
+ lex->mqh.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR;
}
- | MAX_UPDATES_PER_HOUR ULONG_NUM
+ | MAX_UPDATES_PER_HOUR ulong_num
{
- Lex->mqh.updates=$2;
- Lex->mqh.bits |= 2;
+ LEX *lex=Lex;
+ lex->mqh.updates=$2;
+ lex->mqh.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR;
}
- | MAX_CONNECTIONS_PER_HOUR ULONG_NUM
+ | MAX_CONNECTIONS_PER_HOUR ulong_num
{
- Lex->mqh.connections=$2;
- Lex->mqh.bits |= 4;
+ LEX *lex=Lex;
+ lex->mqh.conn_per_hour= $2;
+ lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR;
+ }
+ | MAX_USER_CONNECTIONS_SYM ulong_num
+ {
+ LEX *lex=Lex;
+ lex->mqh.user_conn= $2;
+ lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS;
}
;
begin:
- BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN; Lex->start_transaction_opt= 0;} opt_work {}
+ BEGIN_SYM
+ {
+ LEX *lex=Lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
+ lex->sql_command = SQLCOM_BEGIN;
+ lex->start_transaction_opt= 0;
+ }
+ opt_work {}
;
opt_work:
/* empty */ {}
- | WORK_SYM {;}
+ | WORK_SYM {}
;
+opt_chain:
+ /* empty */ { $$= (YYTHD->variables.completion_type == 1); }
+ | AND_SYM NO_SYM CHAIN_SYM { $$=0; }
+ | AND_SYM CHAIN_SYM { $$=1; }
+ ;
+
+opt_release:
+ /* empty */ { $$= (YYTHD->variables.completion_type == 2); }
+ | RELEASE_SYM { $$=1; }
+ | NO_SYM RELEASE_SYM { $$=0; }
+ ;
+
+opt_savepoint:
+ /* empty */ {}
+ | SAVEPOINT_SYM {}
+ ;
+
commit:
- COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;};
+ COMMIT_SYM opt_work opt_chain opt_release
+ {
+ LEX *lex=Lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_COMMIT;
+ lex->tx_chain= $3;
+ lex->tx_release= $4;
+ }
+ ;
rollback:
- ROLLBACK_SYM
+ ROLLBACK_SYM opt_work opt_chain opt_release
{
- Lex->sql_command = SQLCOM_ROLLBACK;
+ LEX *lex=Lex;
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_ROLLBACK;
+ lex->tx_chain= $3;
+ lex->tx_release= $4;
}
- | ROLLBACK_SYM TO_SYM SAVEPOINT_SYM ident
+ | ROLLBACK_SYM opt_work
+ TO_SYM opt_savepoint ident
{
- Lex->sql_command = SQLCOM_ROLLBACK_TO_SAVEPOINT;
- Lex->savepoint_name = $4.str;
- };
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_ROLLBACK_TO_SAVEPOINT;
+ lex->ident= $5;
+ }
+ ;
+
savepoint:
SAVEPOINT_SYM ident
{
- Lex->sql_command = SQLCOM_SAVEPOINT;
- Lex->savepoint_name = $2.str;
- };
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SAVEPOINT;
+ lex->ident= $2;
+ }
+ ;
+release:
+ RELEASE_SYM SAVEPOINT_SYM ident
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_RELEASE_SAVEPOINT;
+ lex->ident= $3;
+ }
+ ;
+
/*
UNIONS : glue selects together
*/
@@ -6032,7 +8747,7 @@ union_list:
if (lex->exchange)
{
/* Only the last SELECT can have INTO...... */
- net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "INTO");
+ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
YYABORT;
}
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
@@ -6048,17 +8763,23 @@ union_list:
lex->current_select->master_unit()->union_distinct=
lex->current_select;
}
- select_init {}
+ select_init
+ {
+ /*
+ Remove from the name resolution context stack the context of the
+ last select in the union.
+ */
+ Lex->pop_context();
+ }
;
union_opt:
- union_list {}
- | optional_order_or_limit {}
+ /* Empty */ { $$= 0; }
+ | union_list { $$= 1; }
+ | union_order_or_limit { $$= 1; }
;
-optional_order_or_limit:
- /* Empty */ {}
- |
+union_order_or_limit:
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
@@ -6153,6 +8874,174 @@ subselect_end:
')'
{
LEX *lex=Lex;
+ lex->pop_context();
lex->current_select = lex->current_select->return_after_parsing();
};
+opt_view_list:
+ /* empty */ {}
+ | '(' view_list ')'
+ ;
+
+view_list:
+ ident
+ {
+ Lex->view_list.push_back((LEX_STRING*)
+ sql_memdup(&$1, sizeof(LEX_STRING)));
+ }
+ | view_list ',' ident
+ {
+ Lex->view_list.push_back((LEX_STRING*)
+ sql_memdup(&$3, sizeof(LEX_STRING)));
+ }
+ ;
+
+or_replace:
+ /* empty */ { Lex->create_view_mode= VIEW_CREATE_NEW; }
+ | OR_SYM REPLACE { Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; }
+ ;
+
+algorithm:
+ /* empty */
+ { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
+ | ALGORITHM_SYM EQ UNDEFINED_SYM
+ { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
+ | ALGORITHM_SYM EQ MERGE_SYM
+ { Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
+ | ALGORITHM_SYM EQ TEMPTABLE_SYM
+ { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; }
+ ;
+
+view_user:
+ /* empty */
+ {
+ THD *thd= YYTHD;
+ if (!(thd->lex->create_view_definer=
+ (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ YYABORT;
+ if (default_view_definer(thd, thd->lex->create_view_definer))
+ YYABORT;
+ }
+ | CURRENT_USER optional_braces
+ {
+ THD *thd= YYTHD;
+ if (!(thd->lex->create_view_definer=
+ (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ YYABORT;
+ if (default_view_definer(thd, thd->lex->create_view_definer))
+ YYABORT;
+ }
+ | DEFINER_SYM EQ ident_or_text '@' ident_or_text
+ {
+ THD *thd= YYTHD;
+ st_lex_user *view_user;
+ if (!(thd->lex->create_view_definer= view_user=
+ (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ YYABORT;
+ view_user->user = $3; view_user->host=$5;
+ if (strchr(view_user->host.str, wild_many) ||
+ strchr(view_user->host.str, wild_one))
+ {
+ my_error(ER_NO_VIEW_USER, MYF(0));
+ YYABORT;
+ }
+ }
+ ;
+
+view_suid:
+ /* empty */
+ { Lex->create_view_suid= TRUE; }
+ |
+ SQL_SYM SECURITY_SYM DEFINER_SYM
+ { Lex->create_view_suid= TRUE; }
+ | SQL_SYM SECURITY_SYM INVOKER_SYM
+ { Lex->create_view_suid= FALSE; }
+ ;
+
+check_option:
+ /* empty */
+ { Lex->create_view_check= VIEW_CHECK_NONE; }
+ | WITH CHECK_SYM OPTION
+ { Lex->create_view_check= VIEW_CHECK_CASCADED; }
+ | WITH CASCADED CHECK_SYM OPTION
+ { Lex->create_view_check= VIEW_CHECK_CASCADED; }
+ | WITH LOCAL_SYM CHECK_SYM OPTION
+ { Lex->create_view_check= VIEW_CHECK_LOCAL; }
+ ;
+
+xa: XA_SYM begin_or_start xid opt_join_or_resume
+ {
+ Lex->sql_command = SQLCOM_XA_START;
+ }
+ | XA_SYM END xid opt_suspend
+ {
+ Lex->sql_command = SQLCOM_XA_END;
+ }
+ | XA_SYM PREPARE_SYM xid
+ {
+ Lex->sql_command = SQLCOM_XA_PREPARE;
+ }
+ | XA_SYM COMMIT_SYM xid opt_one_phase
+ {
+ Lex->sql_command = SQLCOM_XA_COMMIT;
+ }
+ | XA_SYM ROLLBACK_SYM xid
+ {
+ Lex->sql_command = SQLCOM_XA_ROLLBACK;
+ }
+ | XA_SYM RECOVER_SYM
+ {
+ Lex->sql_command = SQLCOM_XA_RECOVER;
+ }
+ ;
+
+xid: text_string
+ {
+ YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE);
+ if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+ YYABORT;
+ Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0);
+ }
+ | text_string ',' text_string
+ {
+ YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+ if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+ YYABORT;
+ Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length());
+ }
+ | text_string ',' text_string ',' ulong_num
+ {
+ YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+ if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+ YYABORT;
+ Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length());
+ }
+ ;
+
+begin_or_start: BEGIN_SYM {}
+ | START_SYM {}
+ ;
+
+opt_join_or_resume:
+ /* nothing */ { Lex->xa_opt=XA_NONE; }
+ | JOIN_SYM { Lex->xa_opt=XA_JOIN; }
+ | RESUME_SYM { Lex->xa_opt=XA_RESUME; }
+ ;
+
+opt_one_phase:
+ /* nothing */ { Lex->xa_opt=XA_NONE; }
+ | ONE_SYM PHASE_SYM { Lex->xa_opt=XA_ONE_PHASE; }
+ ;
+
+opt_suspend:
+ /* nothing */ { Lex->xa_opt=XA_NONE; }
+ | SUSPEND_SYM { Lex->xa_opt=XA_SUSPEND; }
+ opt_migrate
+ ;
+
+opt_migrate:
+ /* nothing */ { }
+ | FOR_SYM MIGRATE_SYM { Lex->xa_opt=XA_FOR_MIGRATE; }
+ ;
+
+
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index 81aca092cec..c822d10af46 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -147,10 +147,10 @@ uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match)
uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs)
{
- int find,pos;
+ int pos;
const char *j;
DBUG_ENTER("find_type2");
- DBUG_PRINT("enter",("x: '%s' lib: 0x%lx",x,typelib));
+ DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, typelib));
if (!typelib->count)
{
@@ -158,7 +158,7 @@ uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs)
DBUG_RETURN(0);
}
- for (find=0, pos=0 ; (j=typelib->type_names[pos]) ; pos++)
+ for (pos=0 ; (j=typelib->type_names[pos]) ; pos++)
{
if (!my_strnncoll(cs, (const uchar*) x, length,
(const uchar*) j, typelib->type_lengths[pos]))
diff --git a/sql/structs.h b/sql/structs.h
index 081ada88bf7..e490a2de60c 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -20,6 +20,8 @@
struct st_table;
class Field;
+#define STRING_WITH_LEN(X) X, (sizeof(X)-1)
+
typedef struct st_lex_string
{
char *str;
@@ -74,7 +76,7 @@ typedef struct st_key_part_info { /* Info about a key part */
uint16 store_length;
uint16 key_type;
uint16 fieldnr; /* Fieldnum in UNIREG */
- uint8 key_part_flag; /* 0 or HA_REVERSE_SORT */
+ uint16 key_part_flag; /* 0 or HA_REVERSE_SORT */
uint8 type;
uint8 null_bit; /* Position to null_bit */
} KEY_PART_INFO ;
@@ -98,6 +100,7 @@ typedef struct st_key {
union {
int bdb_return_if_eq;
} handler;
+ struct st_table *table;
} KEY;
@@ -163,9 +166,11 @@ typedef struct st_known_date_time_format {
enum SHOW_TYPE
{
SHOW_UNDEF,
- SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_BOOL,
- SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION,
+ SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR,
+ SHOW_DOUBLE_STATUS,
+ SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION,
SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS,
+ SHOW_VARS,
#ifdef HAVE_OPENSSL
SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD,
SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE,
@@ -181,7 +186,8 @@ enum SHOW_TYPE
SHOW_SSL_GET_CIPHER_LIST,
#endif /* HAVE_OPENSSL */
SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING, SHOW_SLAVE_RETRIED_TRANS,
- SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG, SHOW_KEY_CACHE_LONGLONG
+ SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG, SHOW_KEY_CACHE_LONGLONG,
+ SHOW_LONG_STATUS, SHOW_LONG_CONST_STATUS, SHOW_SLAVE_SKIP_ERRORS
};
enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED};
@@ -203,16 +209,65 @@ typedef struct st_lex_user {
} LEX_USER;
+/*
+ This structure specifies the maximum amount of resources which
+ can be consumed by each account. Zero value of a member means
+ there is no limit.
+*/
typedef struct user_resources {
- uint questions, updates, connections, bits;
+ /* Maximum number of queries/statements per hour. */
+ uint questions;
+ /*
+ Maximum number of updating statements per hour (which statements are
+ updating is defined by uc_update_queries array).
+ */
+ uint updates;
+ /* Maximum number of connections established per hour. */
+ uint conn_per_hour;
+ /* Maximum number of concurrent connections. */
+ uint user_conn;
+ /*
+ Values of this enum and specified_limits member are used by the
+ parser to store which user limits were specified in GRANT statement.
+ */
+ enum {QUERIES_PER_HOUR= 1, UPDATES_PER_HOUR= 2, CONNECTIONS_PER_HOUR= 4,
+ USER_CONNECTIONS= 8};
+ uint specified_limits;
} USER_RESOURCES;
+
+/*
+ This structure is used for counting resources consumed and for checking
+ them against specified user limits.
+*/
typedef struct user_conn {
- char *user, *host;
- uint len, connections, conn_per_hour, updates, questions, user_len;
+ /*
+ Pointer to user+host key (pair separated by '\0') defining the entity
+ for which resources are counted (By default it is user account thus
+ priv_user/priv_host pair is used. If --old-style-user-limits option
+ is enabled, resources are counted for each user+host separately).
+ */
+ char *user;
+ /* Pointer to host part of the key. */
+ char *host;
+ /* Total length of the key. */
+ uint len;
+ /* Current amount of concurrent connections for this account. */
+ uint connections;
+ /*
+ Current number of connections per hour, number of updating statements
+ per hour and total number of statements per hour for this account.
+ */
+ uint conn_per_hour, updates, questions;
+ /* Maximum amount of resources which account is allowed to consume. */
USER_RESOURCES user_resources;
+ /*
+ The moment of time when per hour counters were reset last time
+ (i.e. start of "hour" for conn_per_hour, updates, questions counters).
+ */
time_t intime;
} USER_CONN;
+
/* Bits in form->update */
#define REG_MAKE_DUPP 1 /* Make a copy of record when read */
#define REG_NEW_RECORD 2 /* Write a new record if not found */
diff --git a/sql/table.cc b/sql/table.cc
index 04d1a95cd9b..67d4ebd713b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -20,7 +20,7 @@
#include "mysql_priv.h"
#include <errno.h>
#include <m_ctype.h>
-
+#include "md5.h"
/* Functions defined in this file */
@@ -62,8 +62,8 @@ static byte* get_field_name(Field **buff,uint *length,
6 Unknown .frm version
*/
-int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
- uint ha_open_flags, TABLE *outparam)
+int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
+ uint prgflag, uint ha_open_flags, TABLE *outparam)
{
reg1 uint i;
reg2 uchar *strpos;
@@ -71,60 +71,78 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
uint rec_buff_length,n_length,int_length,records,key_parts,keys,
interval_count,interval_parts,read_length,db_create_options;
uint key_info_length, com_length;
- ulong pos;
+ ulong pos, record_offset;
char index_file[FN_REFLEN], *names, *keynames, *comment_pos;
uchar head[288],*disk_buff,new_field_pack_flag;
my_string record;
const char **int_array;
bool use_hash, null_field_first;
+ bool error_reported= FALSE;
File file;
Field **field_ptr,*reg_field;
KEY *keyinfo;
KEY_PART_INFO *key_part;
uchar *null_pos;
- uint null_bit, new_frm_ver, field_pack_length;
+ uint null_bit_pos, new_frm_ver, field_pack_length;
SQL_CRYPT *crypted=0;
MEM_ROOT **root_ptr, *old_root;
+ TABLE_SHARE *share;
DBUG_ENTER("openfrm");
- DBUG_PRINT("enter",("name: '%s' form: %lx",name,outparam));
-
- bzero((char*) outparam,sizeof(*outparam));
- outparam->blob_ptr_size=sizeof(char*);
- disk_buff=NULL; record= NULL; keynames=NullS;
- outparam->db_stat = db_stat;
- error=1;
+ DBUG_PRINT("enter",("name: '%s' form: 0x%lx",name,outparam));
- init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
+ error= 1;
+ disk_buff= NULL;
root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
old_root= *root_ptr;
- *root_ptr= &outparam->mem_root;
- outparam->real_name=strdup_root(&outparam->mem_root,
- name+dirname_length(name));
- outparam->table_name=my_strdup(alias,MYF(MY_WME));
- if (!outparam->real_name || !outparam->table_name)
- goto err_end;
- *fn_ext(outparam->real_name)='\0'; // Remove extension
+ bzero((char*) outparam,sizeof(*outparam));
+ outparam->in_use= thd;
+ outparam->s= share= &outparam->share_not_to_be_used;
- if ((file=my_open(fn_format(index_file,name,"",reg_ext,MY_UNPACK_FILENAME),
+ if ((file=my_open(fn_format(index_file, name, "", reg_ext,
+ MY_UNPACK_FILENAME),
O_RDONLY | O_SHARE,
MYF(0)))
< 0)
+ goto err;
+
+ error= 4;
+ if (my_read(file,(byte*) head,64,MYF(MY_NABP)))
+ goto err;
+
+ if (memcmp(head, "TYPE=", 5) == 0)
{
- goto err_end; /* purecov: inspected */
+ // new .frm
+ my_close(file,MYF(MY_WME));
+
+ if (db_stat & NO_ERR_ON_NEW_FRM)
+ DBUG_RETURN(5);
+ file= -1;
+ // caller can't process new .frm
+ goto err;
}
- error=4;
- if (!(outparam->path= strdup_root(&outparam->mem_root,name)))
- goto err_not_open;
- *fn_ext(outparam->path)='\0'; // Remove extension
- if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open;
+ share->blob_ptr_size= sizeof(char*);
+ outparam->db_stat= db_stat;
+ init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
+ *root_ptr= &outparam->mem_root;
+
+ share->table_name= strdup_root(&outparam->mem_root,
+ name+dirname_length(name));
+ share->path= strdup_root(&outparam->mem_root, name);
+ outparam->alias= my_strdup(alias, MYF(MY_WME));
+ if (!share->table_name || !share->path || !outparam->alias)
+ goto err;
+ *fn_ext(share->table_name)='\0'; // Remove extension
+ *fn_ext(share->path)='\0'; // Remove extension
+
if (head[0] != (uchar) 254 || head[1] != 1)
- goto err_not_open; /* purecov: inspected */
- if (head[2] != FRM_VER && head[2] != FRM_VER+1 && head[2] != FRM_VER+3)
+ goto err; /* purecov: inspected */
+ if (head[2] != FRM_VER && head[2] != FRM_VER+1 &&
+ ! (head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4))
{
error= 6;
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
new_field_pack_flag=head[27];
new_frm_ver= (head[2] - FRM_VER);
@@ -132,25 +150,35 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
error=3;
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* 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;
- null_field_first=0;
+ share->frm_version= head[2];
+ /*
+ Check if .frm file created by MySQL 5.0. In this case we want to
+ display CHAR fields as CHAR and not as VARCHAR.
+ We do it this way as we want to keep the old frm version to enable
+ MySQL 4.1 to read these files.
+ */
+ if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5)
+ share->frm_version= FRM_VER_TRUE_VARCHAR;
+
+ share->db_type= ha_checktype(thd,(enum db_type) (uint) *(head+3),0,0);
+ share->db_create_options= db_create_options=uint2korr(head+30);
+ share->db_options_in_use= share->db_create_options;
+ share->mysql_version= uint4korr(head+51);
+ null_field_first= 0;
if (!head[32]) // New frm file in 3.23
{
- outparam->avg_row_length=uint4korr(head+34);
- outparam->row_type=(row_type) head[40];
- outparam->raid_type= head[41];
- outparam->raid_chunks= head[42];
- outparam->raid_chunksize= uint4korr(head+43);
- outparam->table_charset=get_charset((uint) head[38],MYF(0));
- null_field_first=1;
+ share->avg_row_length= uint4korr(head+34);
+ share-> row_type= (row_type) head[40];
+ share->raid_type= head[41];
+ share->raid_chunks= head[42];
+ share->raid_chunksize= uint4korr(head+43);
+ share->table_charset= get_charset((uint) head[38],MYF(0));
+ null_field_first= 1;
}
- if (!outparam->table_charset)
+ if (!share->table_charset)
{
/* unknown charset in head[38] or pre-3.23 frm */
if (use_mb(default_charset_info))
@@ -161,35 +189,34 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
"so character column sizes may have changed",
name);
}
- outparam->table_charset=default_charset_info;
+ share->table_charset= default_charset_info;
}
- outparam->db_record_offset=1;
+ share->db_record_offset= 1;
if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
- outparam->blob_ptr_size=portable_sizeof_char_ptr;
- /* Set temporaryly a good value for db_low_byte_first */
- outparam->db_low_byte_first=test(outparam->db_type != DB_TYPE_ISAM);
+ share->blob_ptr_size= portable_sizeof_char_ptr;
+ /* Set temporarily a good value for db_low_byte_first */
+ share->db_low_byte_first= test(share->db_type != DB_TYPE_ISAM);
error=4;
- outparam->max_rows=uint4korr(head+18);
- outparam->min_rows=uint4korr(head+22);
+ share->max_rows= uint4korr(head+18);
+ share->min_rows= uint4korr(head+22);
/* Read keyinformation */
key_info_length= (uint) uint2korr(head+28);
VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0)));
if (read_string(file,(gptr*) &disk_buff,key_info_length))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
if (disk_buff[0] & 0x80)
{
- outparam->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
- outparam->key_parts= key_parts= uint2korr(disk_buff+2);
+ share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
+ share->key_parts= key_parts= uint2korr(disk_buff+2);
}
else
{
- outparam->keys= keys= disk_buff[0];
- outparam->key_parts= key_parts= disk_buff[1];
+ share->keys= keys= disk_buff[0];
+ share->key_parts= key_parts= disk_buff[1];
}
- outparam->keys_for_keyread.init(0);
- outparam->keys_in_use.init(keys);
- outparam->read_only_keys.init(keys);
+ share->keys_for_keyread.init(0);
+ share->keys_in_use.init(keys);
outparam->quick_keys.init();
outparam->used_keys.init();
outparam->keys_in_use_for_query.init();
@@ -197,7 +224,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
if (!(keyinfo = (KEY*) alloc_root(&outparam->mem_root,
n_length+uint2korr(disk_buff+4))))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
bzero((char*) keyinfo,n_length);
outparam->key_info=keyinfo;
key_part= my_reinterpret_cast(KEY_PART_INFO*) (keyinfo+keys);
@@ -206,11 +233,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
ulong *rec_per_key;
if (!(rec_per_key= (ulong*) alloc_root(&outparam->mem_root,
sizeof(ulong*)*key_parts)))
- goto err_not_open;
+ goto err;
for (i=0 ; i < keys ; i++, keyinfo++)
{
- if (new_frm_ver == 3)
+ keyinfo->table= outparam;
+ if (new_frm_ver >= 3)
{
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
keyinfo->key_length= (uint) uint2korr(strpos+2);
@@ -259,9 +287,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
keynames=(char*) key_part;
strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
- outparam->reclength = uint2korr((head+16));
+ share->reclength = uint2korr((head+16));
if (*(head+26) == 1)
- outparam->system=1; /* one-record-database */
+ share->system= 1; /* one-record-database */
#ifdef HAVE_CRYPTED_FRM
else if (*(head+26) == 2)
{
@@ -273,84 +301,111 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
#endif
/* Allocate handler */
- if (!(outparam->file= get_new_handler(outparam,outparam->db_type)))
- goto err_not_open;
+ if (!(outparam->file= get_new_handler(outparam, share->db_type)))
+ goto err;
error=4;
outparam->reginfo.lock_type= TL_UNLOCK;
outparam->current_lock=F_UNLCK;
- if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN)) records=2;
- else records=1;
- if (prgflag & (READ_ALL+EXTRA_RECORD)) records++;
+ if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
+ records=2;
+ else
+ records=1;
+ if (prgflag & (READ_ALL+EXTRA_RECORD))
+ records++;
/* QQ: TODO, remove the +1 from below */
- rec_buff_length=ALIGN_SIZE(outparam->reclength+1+
- outparam->file->extra_rec_buf_length());
- if (!(outparam->record[0]= (byte*)
- (record = (char *) alloc_root(&outparam->mem_root,
- rec_buff_length * records))))
- goto err_not_open; /* purecov: inspected */
- record[outparam->reclength]=0; // For purify and ->c_ptr()
- outparam->rec_buff_length=rec_buff_length;
- if (my_pread(file,(byte*) record,(uint) outparam->reclength,
- (ulong) (uint2korr(head+6)+
- ((uint2korr(head+14) == 0xffff ?
- uint4korr(head+47) : uint2korr(head+14)))),
- MYF(MY_NABP)))
- goto err_not_open; /* purecov: inspected */
- /* HACK: table->record[2] is used instead of table->default_values here */
- for (i=0 ; i < records ; i++, record+=rec_buff_length)
- {
- outparam->record[i]=(byte*) record;
- if (i)
- memcpy(record,record-rec_buff_length,(uint) outparam->reclength);
- }
-
- if (records == 2)
- { /* fix for select */
- outparam->default_values=outparam->record[1];
- if (db_stat & HA_READ_ONLY)
- outparam->record[1]=outparam->record[0]; /* purecov: inspected */
- }
- outparam->insert_values=0; /* for INSERT ... UPDATE */
+ rec_buff_length= ALIGN_SIZE(share->reclength + 1 +
+ outparam->file->extra_rec_buf_length());
+ share->rec_buff_length= rec_buff_length;
+ if (!(record= (char *) alloc_root(&outparam->mem_root,
+ rec_buff_length * records)))
+ goto err; /* purecov: inspected */
+ share->default_values= (byte *) record;
+
+ record_offset= (ulong) (uint2korr(head+6)+
+ ((uint2korr(head+14) == 0xffff ?
+ uint4korr(head+47) : uint2korr(head+14))));
+ if (my_pread(file,(byte*) record, (uint) share->reclength,
+ record_offset, MYF(MY_NABP)))
+ goto err; /* purecov: inspected */
+
+ if (records == 1)
+ {
+ /* We are probably in hard repair, and the buffers should not be used */
+ outparam->record[0]= outparam->record[1]= share->default_values;
+ }
+ else
+ {
+ outparam->record[0]= (byte *) record+ rec_buff_length;
+ if (records > 2)
+ outparam->record[1]= (byte *) record+ rec_buff_length*2;
+ else
+ outparam->record[1]= outparam->record[0]; // Safety
+ }
+
+ if ((n_length= uint2korr(head+55)))
+ {
+ /* Read extra block information */
+ char *buff;
+ if (!(buff= alloc_root(&outparam->mem_root, n_length)))
+ goto err;
+ if (my_pread(file, buff, n_length, record_offset + share->reclength,
+ MYF(MY_NABP)))
+ goto err;
+ share->connect_string.length= uint2korr(buff);
+ share->connect_string.str= buff+2;
+ }
+#ifdef HAVE_purify
+ /*
+ We need this because when we read var-length rows, we are not updating
+ bytes after end of varchar
+ */
+ if (records > 1)
+ {
+ memcpy(outparam->record[0], share->default_values, rec_buff_length);
+ if (records > 2)
+ memcpy(outparam->record[1], share->default_values, rec_buff_length);
+ }
+#endif
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
- if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open;
+ if (my_read(file,(byte*) head,288,MYF(MY_NABP)))
+ goto err;
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
crypted->decode((char*) head+256,288-256);
if (sint2korr(head+284) != 0) // Should be 0
- goto err_not_open; // Wrong password
+ goto err; // Wrong password
}
#endif
- outparam->fields= uint2korr(head+258);
- pos=uint2korr(head+260); /* Length of all screens */
- n_length=uint2korr(head+268);
- interval_count=uint2korr(head+270);
- interval_parts=uint2korr(head+272);
- int_length=uint2korr(head+274);
- outparam->null_fields=uint2korr(head+282);
- com_length=uint2korr(head+284);
- outparam->comment=strdup_root(&outparam->mem_root,
- (char*) head+47);
+ share->fields= uint2korr(head+258);
+ pos= uint2korr(head+260); /* Length of all screens */
+ n_length= uint2korr(head+268);
+ interval_count= uint2korr(head+270);
+ interval_parts= uint2korr(head+272);
+ int_length= uint2korr(head+274);
+ share->null_fields= uint2korr(head+282);
+ com_length= uint2korr(head+284);
+ share->comment= strdup_root(&outparam->mem_root, (char*) head+47);
- DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, outparam->keys,n_length,int_length, com_length));
+ DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length));
if (!(field_ptr = (Field **)
alloc_root(&outparam->mem_root,
- (uint) ((outparam->fields+1)*sizeof(Field*)+
+ (uint) ((share->fields+1)*sizeof(Field*)+
interval_count*sizeof(TYPELIB)+
- (outparam->fields+interval_parts+
+ (share->fields+interval_parts+
keys+3)*sizeof(my_string)+
(n_length+int_length+com_length)))))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
outparam->field=field_ptr;
- read_length=(uint) (outparam->fields * field_pack_length +
+ read_length=(uint) (share->fields * field_pack_length +
pos+ (uint) (n_length+int_length+com_length));
if (read_string(file,(gptr*) &disk_buff,read_length))
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
@@ -361,31 +416,31 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
#endif
strpos= disk_buff+pos;
- outparam->intervals= (TYPELIB*) (field_ptr+outparam->fields+1);
- int_array= (const char **) (outparam->intervals+interval_count);
- names= (char*) (int_array+outparam->fields+interval_parts+keys+3);
+ share->intervals= (TYPELIB*) (field_ptr+share->fields+1);
+ int_array= (const char **) (share->intervals+interval_count);
+ names= (char*) (int_array+share->fields+interval_parts+keys+3);
if (!interval_count)
- outparam->intervals=0; // For better debugging
- memcpy((char*) names, strpos+(outparam->fields*field_pack_length),
+ share->intervals= 0; // For better debugging
+ memcpy((char*) names, strpos+(share->fields*field_pack_length),
(uint) (n_length+int_length));
- comment_pos=names+(n_length+int_length);
+ comment_pos= names+(n_length+int_length);
memcpy(comment_pos, disk_buff+read_length-com_length, com_length);
- fix_type_pointers(&int_array,&outparam->fieldnames,1,&names);
- fix_type_pointers(&int_array,outparam->intervals,interval_count,
+ fix_type_pointers(&int_array, &share->fieldnames, 1, &names);
+ fix_type_pointers(&int_array, share->intervals, interval_count,
&names);
{
/* Set ENUM and SET lengths */
TYPELIB *interval;
- for (interval= outparam->intervals;
- interval < outparam->intervals + interval_count;
+ for (interval= share->intervals;
+ interval < share->intervals + interval_count;
interval++)
{
uint count= (uint) (interval->count + 1) * sizeof(uint);
if (!(interval->type_lengths= (uint *) alloc_root(&outparam->mem_root,
count)))
- goto err_not_open;
+ goto err;
for (count= 0; count < interval->count; count++)
interval->type_lengths[count]= strlen(interval->type_names[count]);
interval->type_lengths[count]= 0;
@@ -393,33 +448,36 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
if (keynames)
- fix_type_pointers(&int_array,&outparam->keynames,1,&keynames);
+ fix_type_pointers(&int_array, &share->keynames, 1, &keynames);
VOID(my_close(file,MYF(MY_WME)));
file= -1;
- record=(char*) outparam->record[0]-1; /* Fieldstart = 1 */
+ record= (char*) outparam->record[0]-1; /* Fieldstart = 1 */
if (null_field_first)
{
outparam->null_flags=null_pos=(uchar*) record+1;
- null_bit= (db_create_options & HA_OPTION_PACK_RECORD) ? 1 : 2;
- outparam->null_bytes=(outparam->null_fields+null_bit+6)/8;
+ null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
+ /* null_bytes below is only correct under the condition that
+ there are no bit fields. Correct values is set below after the
+ table struct is initialized */
+ share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
}
else
{
- outparam->null_bytes=(outparam->null_fields+7)/8;
- outparam->null_flags=null_pos=
- (uchar*) (record+1+outparam->reclength-outparam->null_bytes);
- null_bit=1;
+ share->null_bytes= (share->null_fields+7)/8;
+ outparam->null_flags= null_pos=
+ (uchar*) (record+1+share->reclength-share->null_bytes);
+ null_bit_pos= 0;
}
- use_hash= outparam->fields >= MAX_FIELDS_BEFORE_HASH;
+ use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
if (use_hash)
- use_hash= !hash_init(&outparam->name_hash,
+ use_hash= !hash_init(&share->name_hash,
system_charset_info,
- outparam->fields,0,0,
+ share->fields,0,0,
(hash_get_key) get_field_name,0,0);
- for (i=0 ; i < outparam->fields; i++, strpos+=field_pack_length, field_ptr++)
+ for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
{
uint pack_flag, interval_nr, unireg_type, recpos, field_length;
enum_field_types field_type;
@@ -427,7 +485,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
LEX_STRING comment;
- if (new_frm_ver == 3)
+ if (new_frm_ver >= 3)
{
/* new frm file in 4.1 */
field_length= uint2korr(strpos+3);
@@ -435,11 +493,10 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
pack_flag= uint2korr(strpos+8);
unireg_type= (uint) strpos[10];
interval_nr= (uint) strpos[12];
-
uint comment_length=uint2korr(strpos+15);
field_type=(enum_field_types) (uint) strpos[13];
- // charset and geometry_type share the same byte in frm
+ /* charset and geometry_type share the same byte in frm */
if (field_type == FIELD_TYPE_GEOMETRY)
{
#ifdef HAVE_SPATIAL
@@ -447,7 +504,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
charset= &my_charset_bin;
#else
error= 4; // unsupported field type
- goto err_not_open;
+ goto err;
#endif
}
else
@@ -458,7 +515,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{
error= 5; // Unknown or unavailable charset
errarg= (int) strpos[14];
- goto err_not_open;
+ goto err;
}
}
if (!comment_length)
@@ -478,6 +535,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
field_length= (uint) strpos[3];
recpos= uint2korr(strpos+4),
pack_flag= uint2korr(strpos+6);
+ pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
unireg_type= (uint) strpos[8];
interval_nr= (uint) strpos[10];
@@ -494,7 +552,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (!f_is_blob(pack_flag))
{
// 3.23 or 4.0 string
- if (!(charset= get_charset_by_csname(outparam->table_charset->csname,
+ if (!(charset= get_charset_by_csname(share->table_charset->csname,
MY_CS_BINSORT, MYF(0))))
charset= &my_charset_bin;
}
@@ -502,51 +560,80 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
charset= &my_charset_bin;
}
else
- charset= outparam->table_charset;
+ charset= share->table_charset;
bzero((char*) &comment, sizeof(comment));
}
if (interval_nr && charset->mbminlen > 1)
{
/* Unescape UCS2 intervals from HEX notation */
- TYPELIB *interval= outparam->intervals + interval_nr - 1;
+ TYPELIB *interval= share->intervals + interval_nr - 1;
unhex_type2(interval);
}
+#ifndef TO_BE_DELETED_ON_PRODUCTION
+ if (field_type == FIELD_TYPE_NEWDECIMAL && !share->mysql_version)
+ {
+ /*
+ Fix pack length of old decimal values from 5.0.3 -> 5.0.4
+ The difference is that in the old version we stored precision
+ in the .frm table while we now store the display_length
+ */
+ uint decimals= f_decimals(pack_flag);
+ field_length= my_decimal_precision_to_length(field_length,
+ decimals,
+ f_is_dec(pack_flag) == 0);
+ sql_print_error("Found incompatible DECIMAL field '%s' in %s; Please do \"ALTER TABLE '%s' FORCE\" to fix it!", share->fieldnames.type_names[i], name, share->table_name);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_CRASHED_ON_USAGE,
+ "Found incompatible DECIMAL field '%s' in %s; Please do \"ALTER TABLE '%s' FORCE\" to fix it!", share->fieldnames.type_names[i], name, share->table_name);
+ share->crashed= 1; // Marker for CHECK TABLE
+ }
+#endif
+
*field_ptr=reg_field=
make_field(record+recpos,
(uint32) field_length,
- null_pos,null_bit,
+ null_pos, null_bit_pos,
pack_flag,
field_type,
charset,
geom_type,
(Field::utype) MTYP_TYPENR(unireg_type),
(interval_nr ?
- outparam->intervals+interval_nr-1 :
+ share->intervals+interval_nr-1 :
(TYPELIB*) 0),
- outparam->fieldnames.type_names[i],
+ share->fieldnames.type_names[i],
outparam);
if (!reg_field) // Not supported field type
{
error= 4;
- goto err_not_open; /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
+
+ reg_field->field_index= i;
reg_field->comment=comment;
- if (!(reg_field->flags & NOT_NULL_FLAG))
+ if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag))
{
- if ((null_bit<<=1) == 256)
+ if ((null_bit_pos+= field_length & 7) > 7)
{
- null_pos++;
- null_bit=1;
+ null_pos++;
+ null_bit_pos-= 8;
}
}
+ if (!(reg_field->flags & NOT_NULL_FLAG))
+ {
+ if (!(null_bit_pos= (null_bit_pos + 1) & 7))
+ null_pos++;
+ }
+ if (f_no_default(pack_flag))
+ reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
if (reg_field->unireg_check == Field::NEXT_NUMBER)
outparam->found_next_number_field= reg_field;
if (outparam->timestamp_field == reg_field)
- outparam->timestamp_field_offset=i;
+ share->timestamp_field_offset= i;
if (use_hash)
- (void) my_hash_insert(&outparam->name_hash,(byte*) field_ptr); // Will never fail
+ (void) my_hash_insert(&share->name_hash,(byte*) field_ptr); // never fail
}
*field_ptr=0; // End marker
@@ -554,15 +641,15 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (key_parts)
{
uint primary_key=(uint) (find_type((char*) primary_key_name,
- &outparam->keynames, 3) - 1);
+ &share->keynames, 3) - 1);
uint ha_option=outparam->file->table_flags();
keyinfo=outparam->key_info;
key_part=keyinfo->key_part;
- for (uint key=0 ; key < outparam->keys ; key++,keyinfo++)
+ for (uint key=0 ; key < share->keys ; key++,keyinfo++)
{
uint usable_parts=0;
- keyinfo->name=(char*) outparam->keynames.type_names[key];
+ keyinfo->name=(char*) share->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;
@@ -595,8 +682,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
(uint) key_part->offset,
(uint) key_part->length);
#ifdef EXTRA_DEBUG
- if (key_part->fieldnr > outparam->fields)
- goto err_not_open; // sanity check
+ if (key_part->fieldnr > share->fields)
+ goto err; // sanity check
#endif
if (key_part->fieldnr)
{ // Should always be true !
@@ -612,10 +699,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
}
if (field->type() == FIELD_TYPE_BLOB ||
- field->real_type() == FIELD_TYPE_VAR_STRING)
+ field->real_type() == MYSQL_TYPE_VARCHAR)
{
if (field->type() == FIELD_TYPE_BLOB)
key_part->key_part_flag|= HA_BLOB_PART;
+ else
+ key_part->key_part_flag|= HA_VAR_LENGTH_PART;
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
key_part->store_length+=HA_KEY_BLOB_LENGTH;
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
@@ -626,11 +715,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (!(field->flags & BINARY_FLAG))
keyinfo->flags|= HA_END_SPACE_KEY;
}
+ if (field->type() == MYSQL_TYPE_BIT)
+ key_part->key_part_flag|= HA_BIT_PART;
+
if (i == 0 && key != primary_key)
- field->flags |=
- ((keyinfo->flags & HA_NOSAME) &&
- field->key_length() ==
- keyinfo->key_length ? UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
+ field->flags |= ((keyinfo->flags & HA_NOSAME) &&
+ (keyinfo->key_parts == 1)) ?
+ UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG;
if (i == 0)
field->key_start.set_bit(key);
if (field->key_length() == key_part->length &&
@@ -638,8 +729,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{
if (outparam->file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
{
- outparam->read_only_keys.clear_bit(key);
- outparam->keys_for_keyread.set_bit(key);
+ share->keys_for_keyread.set_bit(key);
field->part_of_key.set_bit(key);
}
if (outparam->file->index_flags(key, i, 1) & HA_READ_ORDER)
@@ -657,10 +747,33 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
the primary key, then we can use any key to find this column
*/
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
- field->part_of_key= outparam->keys_in_use;
+ field->part_of_key= share->keys_in_use;
}
if (field->key_length() != key_part->length)
{
+#ifndef TO_BE_DELETED_ON_PRODUCTION
+ if (field->type() == FIELD_TYPE_NEWDECIMAL)
+ {
+ /*
+ Fix a fatal error in decimal key handling that causes crashes
+ on Innodb. We fix it by reducing the key length so that
+ InnoDB never gets a too big key when searching.
+ This allows the end user to do an ALTER TABLE to fix the
+ error.
+ */
+ keyinfo->key_length-= (key_part->length - field->key_length());
+ key_part->store_length-= (uint16)(key_part->length -
+ field->key_length());
+ key_part->length= (uint16)field->key_length();
+ sql_print_error("Found wrong key definition in %s; Please do \"ALTER TABLE '%s' FORCE \" to fix it!", name, share->table_name);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_CRASHED_ON_USAGE,
+ "Found wrong key definition in %s; Please do \"ALTER TABLE '%s' FORCE\" to fix it!", name, share->table_name);
+
+ share->crashed= 1; // Marker for CHECK TABLE
+ goto to_be_deleted;
+ }
+#endif
key_part->key_part_flag|= HA_PART_KEY_SEG;
if (!(field->flags & BLOB_FLAG))
{ // Create a new field
@@ -669,6 +782,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
field->field_length=key_part->length;
}
}
+
+ to_be_deleted:
+
/*
If the field can be NULL, don't optimize away the test
key_part_column = expression from the WHERE clause
@@ -685,21 +801,21 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
keyinfo->usable_key_parts=usable_parts; // Filesort
- set_if_bigger(outparam->max_key_length,keyinfo->key_length+
- keyinfo->key_parts);
- outparam->total_key_length+= keyinfo->key_length;
+ set_if_bigger(share->max_key_length,keyinfo->key_length+
+ keyinfo->key_parts);
+ share->total_key_length+= keyinfo->key_length;
/*
MERGE tables do not have unique indexes. But every key could be
an unique index on the underlying MyISAM table. (Bug #10400)
*/
if ((keyinfo->flags & HA_NOSAME) ||
(ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
- set_if_bigger(outparam->max_unique_length,keyinfo->key_length);
+ set_if_bigger(share->max_unique_length,keyinfo->key_length);
}
if (primary_key < MAX_KEY &&
- (outparam->keys_in_use.is_set(primary_key)))
+ (share->keys_in_use.is_set(primary_key)))
{
- outparam->primary_key=primary_key;
+ share->primary_key= primary_key;
/*
If we are using an integer as the primary key then allow the user to
refer to it as '_rowid'
@@ -712,27 +828,25 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
}
else
- outparam->primary_key = MAX_KEY; // we do not have a primary key
+ share->primary_key = MAX_KEY; // we do not have a primary key
}
else
- outparam->primary_key= MAX_KEY;
+ share->primary_key= MAX_KEY;
x_free((gptr) disk_buff);
disk_buff=0;
if (new_field_pack_flag <= 1)
- { /* Old file format with default null */
- uint null_length=(outparam->null_fields+7)/8;
- bfill(outparam->null_flags,null_length,255);
- bfill(outparam->null_flags+outparam->rec_buff_length,null_length,255);
- if (records > 2)
- bfill(outparam->null_flags+outparam->rec_buff_length*2,null_length,255);
+ {
+ /* Old file format with default as not null */
+ uint null_length= (share->null_fields+7)/8;
+ bfill(share->default_values + (outparam->null_flags - (uchar*) record),
+ null_length, 255);
}
-
if ((reg_field=outparam->found_next_number_field))
{
- if ((int) (outparam->next_number_index= (uint)
+ if ((int) (share->next_number_index= (uint)
find_ref_key(outparam,reg_field,
- &outparam->next_number_key_offset)) < 0)
+ &share->next_number_key_offset)) < 0)
{
reg_field->unireg_check=Field::NONE; /* purecov: inspected */
outparam->found_next_number_field=0;
@@ -741,84 +855,88 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
reg_field->flags|=AUTO_INCREMENT_FLAG;
}
- if (outparam->blob_fields)
+ if (share->blob_fields)
{
Field **ptr;
- Field_blob **save;
-
- if (!(outparam->blob_field=save=
- (Field_blob**) alloc_root(&outparam->mem_root,
- (uint) (outparam->blob_fields+1)*
- sizeof(Field_blob*))))
- goto err_not_open;
- for (ptr=outparam->field ; *ptr ; ptr++)
+ uint i, *save;
+
+ /* Store offsets to blob fields to find them fast */
+ if (!(share->blob_field= save=
+ (uint*) alloc_root(&outparam->mem_root,
+ (uint) (share->blob_fields* sizeof(uint)))))
+ goto err;
+ for (i=0, ptr= outparam->field ; *ptr ; ptr++, i++)
{
if ((*ptr)->flags & BLOB_FLAG)
- (*save++)= (Field_blob*) *ptr;
+ (*save++)= i;
}
- *save=0; // End marker
}
- else
- outparam->blob_field=
- (Field_blob**) (outparam->field+outparam->fields); // Point at null ptr
- /* The table struct is now initialzed; Open the table */
+ /* the correct null_bytes can now be set, since bitfields have been taken into account */
+ share->null_bytes= null_pos - (uchar*) outparam->null_flags + (null_bit_pos + 7) / 8;
+
+ /* The table struct is now initialized; Open the table */
error=2;
if (db_stat)
{
- int err;
+ int ha_err;
unpack_filename(index_file,index_file);
- if ((err=(outparam->file->
- ha_open(index_file,
- (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
- (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
- ((db_stat & HA_WAIT_IF_LOCKED) ||
- (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
- HA_OPEN_WAIT_IF_LOCKED :
- (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
- HA_OPEN_ABORT_IF_LOCKED :
- HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
+ if ((ha_err= (outparam->file->
+ ha_open(index_file,
+ (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
+ (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
+ ((db_stat & HA_WAIT_IF_LOCKED) ||
+ (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
+ HA_OPEN_WAIT_IF_LOCKED :
+ (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
+ HA_OPEN_ABORT_IF_LOCKED :
+ HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
{
/* Set a flag if the table is crashed and it can be auto. repaired */
- outparam->crashed=((err == HA_ERR_CRASHED_ON_USAGE) &&
- outparam->file->auto_repair() &&
- !(ha_open_flags & HA_OPEN_FOR_REPAIR));
+ share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
+ outparam->file->auto_repair() &&
+ !(ha_open_flags & HA_OPEN_FOR_REPAIR));
- if (err==HA_ERR_NO_SUCH_TABLE)
+ if (ha_err == HA_ERR_NO_SUCH_TABLE)
{
/* The table did not exists in storage engine, use same error message
as if the .frm file didn't exist */
error= 1;
my_errno= ENOENT;
}
- goto err_not_open; /* purecov: inspected */
+ else
+ {
+ outparam->file->print_error(ha_err, MYF(0));
+ error_reported= TRUE;
+ }
+ goto err; /* purecov: inspected */
}
}
- outparam->db_low_byte_first=outparam->file->low_byte_first();
+ share->db_low_byte_first= outparam->file->low_byte_first();
*root_ptr= old_root;
- opened_tables++;
+ thd->status_var.opened_tables++;
#ifndef DBUG_OFF
if (use_hash)
- (void) hash_check(&outparam->name_hash);
+ (void) hash_check(&share->name_hash);
#endif
DBUG_RETURN (0);
- err_not_open:
+ err:
x_free((gptr) disk_buff);
if (file > 0)
VOID(my_close(file,MYF(MY_WME)));
- err_end: /* Here when no file */
delete crypted;
*root_ptr= old_root;
- frm_error(error, outparam, name, ME_ERROR + ME_WAITTANG, errarg);
+ if (! error_reported)
+ frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG, errarg);
delete outparam->file;
- outparam->file=0; // For easyer errorchecking
+ outparam->file=0; // For easier errorchecking
outparam->db_stat=0;
- hash_free(&outparam->name_hash);
- free_root(&outparam->mem_root,MYF(0));
- my_free(outparam->table_name,MYF(MY_ALLOW_ZERO_PTR));
+ hash_free(&share->name_hash);
+ free_root(&outparam->mem_root, MYF(0)); // Safe to call on bzero'd root
+ my_free((char*) outparam->alias, MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN (error);
} /* openfrm */
@@ -831,21 +949,18 @@ int closefrm(register TABLE *table)
DBUG_ENTER("closefrm");
if (table->db_stat)
error=table->file->close();
- if (table->table_name)
- {
- my_free(table->table_name,MYF(0));
- table->table_name=0;
- }
- if (table->fields)
+ my_free((char*) table->alias, MYF(MY_ALLOW_ZERO_PTR));
+ table->alias= 0;
+ if (table->field)
{
for (Field **ptr=table->field ; *ptr ; ptr++)
delete *ptr;
- table->fields=0;
+ table->field= 0;
}
delete table->file;
- table->file=0; /* For easyer errorchecking */
- hash_free(&table->name_hash);
- free_root(&table->mem_root,MYF(0));
+ table->file= 0; /* For easier errorchecking */
+ hash_free(&table->s->name_hash);
+ free_root(&table->mem_root, MYF(0));
DBUG_RETURN(error);
}
@@ -854,8 +969,11 @@ int closefrm(register TABLE *table)
void free_blobs(register TABLE *table)
{
- for (Field_blob **ptr=table->blob_field ; *ptr ; ptr++)
- (*ptr)->free();
+ uint *ptr, *end;
+ for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
+ ptr != end ;
+ ptr++)
+ ((Field_blob*) table->field[*ptr])->free();
}
@@ -1003,6 +1121,7 @@ static void frm_error(int error, TABLE *form, const char *name,
int err_no;
char buff[FN_REFLEN];
const char *form_dev="",*datext;
+ const char *real_name= (char*) name+dirname_length(name);
DBUG_ENTER("frm_error");
switch (error) {
@@ -1013,11 +1132,11 @@ static void frm_error(int error, TABLE *form, const char *name,
uint length=dirname_part(buff,name);
buff[length-1]=0;
db=buff+dirname_length(buff);
- my_error(ER_NO_SUCH_TABLE,MYF(0),db,form->real_name);
+ my_error(ER_NO_SUCH_TABLE, MYF(0), db, real_name);
}
else
- my_error(ER_FILE_NOT_FOUND,errortype,
- fn_format(buff,name,form_dev,reg_ext,0),my_errno);
+ my_error(ER_FILE_NOT_FOUND, errortype,
+ fn_format(buff, name, form_dev, reg_ext, 0), my_errno);
break;
case 2:
{
@@ -1026,7 +1145,7 @@ static void frm_error(int error, TABLE *form, const char *name,
err_no= (my_errno == ENOENT) ? ER_FILE_NOT_FOUND : (my_errno == EAGAIN) ?
ER_FILE_USED : ER_CANT_OPEN_FILE;
my_error(err_no,errortype,
- fn_format(buff,form->real_name,form_dev,datext,2),my_errno);
+ fn_format(buff,real_name,form_dev,datext,2),my_errno);
break;
}
case 5:
@@ -1040,7 +1159,7 @@ static void frm_error(int error, TABLE *form, const char *name,
}
my_printf_error(ER_UNKNOWN_COLLATION,
"Unknown collation '%s' in table '%-.64s' definition",
- MYF(0), csname, form->real_name);
+ MYF(0), csname, real_name);
break;
}
case 6:
@@ -1051,8 +1170,8 @@ static void frm_error(int error, TABLE *form, const char *name,
break;
default: /* Better wrong error than none */
case 4:
- my_error(ER_NOT_FORM_FILE,errortype,
- fn_format(buff,name,form_dev,reg_ext,0));
+ my_error(ER_NOT_FORM_FILE, errortype,
+ fn_format(buff, name, form_dev, reg_ext, 0));
break;
}
DBUG_VOID_RETURN;
@@ -1061,7 +1180,7 @@ static void frm_error(int error, TABLE *form, const char *name,
/*
** fix a str_type to a array type
- ** typeparts sepearated with some char. differents types are separated
+ ** typeparts separated with some char. differents types are separated
** with a '\0'
*/
@@ -1123,22 +1242,27 @@ TYPELIB *typelib(List<String> &strings)
}
- /*
- ** Search after a field with given start & length
- ** If an exact field isn't found, return longest field with starts
- ** at right position.
- ** Return 0 on error, else field number+1
- ** This is needed because in some .frm fields 'fieldnr' was saved wrong
- */
+/*
+ Search after a field with given start & length
+ If an exact field isn't found, return longest field with starts
+ at right position.
+
+ NOTES
+ This is needed because in some .frm fields 'fieldnr' was saved wrong
+
+ RETURN
+ 0 error
+ # field number +1
+*/
static uint find_field(TABLE *form,uint start,uint length)
{
Field **field;
- uint i,pos;
+ uint i, pos, fields;
pos=0;
-
- for (field=form->field, i=1 ; i<= form->fields ; i++,field++)
+ fields= form->s->fields;
+ for (field=form->field, i=1 ; i<= fields ; i++,field++)
{
if ((*field)->offset() == start)
{
@@ -1153,7 +1277,7 @@ static uint find_field(TABLE *form,uint start,uint length)
}
- /* Check that the integer is in the internvall */
+ /* Check that the integer is in the internal */
int set_zone(register int nr, int min_zone, int max_zone)
{
@@ -1217,7 +1341,7 @@ void append_unescaped(String *res, const char *pos, uint length)
res->append('n');
break;
case '\r':
- res->append('\\'); /* This gives better readbility */
+ res->append('\\'); /* This gives better readability */
res->append('r');
break;
case '\\':
@@ -1238,19 +1362,23 @@ void append_unescaped(String *res, const char *pos, uint length)
/* Create a .frm file */
-File create_frm(register my_string name, const char *db, const char *table,
- uint reclength, uchar *fileinfo,
+File create_frm(THD *thd, my_string name, const char *db,
+ const char *table, uint reclength, uchar *fileinfo,
HA_CREATE_INFO *create_info, uint keys)
{
register File file;
- uint key_length;
ulong length;
char fill[IO_SIZE];
int create_flags= O_RDWR | O_TRUNC;
+ uint extra_size;
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= O_EXCL | O_NOFOLLOW;
+ extra_size= 0;
+ if (create_info->connect_string.length)
+ extra_size= 2+create_info->connect_string.length;
+
#if SIZEOF_OFF_T > 4
/* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */
if (create_info->max_rows > ~(ulong) 0)
@@ -1266,16 +1394,22 @@ File create_frm(register my_string name, const char *db, const char *table,
if ((file= my_create(name, CREATE_MODE, create_flags, MYF(0))) >= 0)
{
+ uint key_length, tmp_key_length;
+ uint tmp;
bzero((char*) fileinfo,64);
- fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+3; // Header
- fileinfo[3]= (uchar) ha_checktype(create_info->db_type);
+ /* header */
+ fileinfo[0]=(uchar) 254;
+ fileinfo[1]= 1;
+ fileinfo[2]= FRM_VER+3+ test(create_info->varchar);
+
+ fileinfo[3]= (uchar) ha_checktype(thd,create_info->db_type,0,0);
fileinfo[4]=1;
int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16;
- length=(ulong) next_io_size((ulong) (IO_SIZE+key_length+reclength));
+ length= next_io_size((ulong) (IO_SIZE+key_length+reclength+extra_size));
int4store(fileinfo+10,length);
- if (key_length > 0xffff) key_length=0xffff;
- int2store(fileinfo+14,key_length);
+ tmp_key_length= (key_length < 0xffff) ? key_length : 0xffff;
+ int2store(fileinfo+14,tmp_key_length);
int2store(fileinfo+16,reclength);
int4store(fileinfo+18,create_info->max_rows);
int4store(fileinfo+22,create_info->min_rows);
@@ -1283,6 +1417,7 @@ File create_frm(register my_string name, const char *db, const char *table,
create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers
int2store(fileinfo+30,create_info->table_options);
fileinfo[32]=0; // No filename anymore
+ fileinfo[33]=5; // Mark for 5.0 frm file
int4store(fileinfo+34,create_info->avg_row_length);
fileinfo[38]= (create_info->default_table_charset ?
create_info->default_table_charset->number : 0);
@@ -1290,6 +1425,10 @@ File create_frm(register my_string name, const char *db, const char *table,
fileinfo[41]= (uchar) create_info->raid_type;
fileinfo[42]= (uchar) create_info->raid_chunks;
int4store(fileinfo+43,create_info->raid_chunksize);
+ int4store(fileinfo+47, key_length);
+ tmp= MYSQL_VERSION_ID; // Store to avoid warning from int4store
+ int4store(fileinfo+51, tmp);
+ int2store(fileinfo+55, extra_size);
bzero(fill,IO_SIZE);
for (; length > IO_SIZE ; length-= IO_SIZE)
{
@@ -1314,17 +1453,20 @@ File create_frm(register my_string name, const char *db, const char *table,
void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
{
+ TABLE_SHARE *share= table->s;
DBUG_ENTER("update_create_info_from_table");
- create_info->max_rows=table->max_rows;
- create_info->min_rows=table->min_rows;
- create_info->table_options=table->db_create_options;
- create_info->avg_row_length=table->avg_row_length;
- create_info->row_type=table->row_type;
- create_info->raid_type=table->raid_type;
- create_info->raid_chunks=table->raid_chunks;
- create_info->raid_chunksize=table->raid_chunksize;
- create_info->default_table_charset=table->table_charset;
+
+ create_info->max_rows= share->max_rows;
+ create_info->min_rows= share->min_rows;
+ create_info->table_options= share->db_create_options;
+ create_info->avg_row_length= share->avg_row_length;
+ create_info->row_type= share->row_type;
+ create_info->raid_type= share->raid_type;
+ create_info->raid_chunks= share->raid_chunks;
+ create_info->raid_chunksize= share->raid_chunksize;
+ create_info->default_table_charset= share->table_charset;
create_info->table_charset= 0;
+
DBUG_VOID_RETURN;
}
@@ -1360,8 +1502,12 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res)
field->val_str(&str);
if (!(length= str.length()))
+ {
+ res->length(0);
return 1;
- to= strmake_root(mem, str.ptr(), length);
+ }
+ if (!(to= strmake_root(mem, str.ptr(), length)))
+ length= 0; // Safety fix
res->set(to, length, ((Field_str*)field)->charset());
return 0;
}
@@ -1427,7 +1573,7 @@ bool check_db_name(char *name)
if (use_mb(system_charset_info))
{
int len=my_ismbchar(system_charset_info, name,
- name+system_charset_info->mbmaxlen);
+ name+system_charset_info->mbmaxlen);
if (len)
{
name += len;
@@ -1496,7 +1642,7 @@ bool check_column_name(const char *name)
{
const char *start= name;
bool last_char_is_space= TRUE;
-
+
while (*name)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
@@ -1504,7 +1650,7 @@ bool check_column_name(const char *name)
if (use_mb(system_charset_info))
{
int len=my_ismbchar(system_charset_info, name,
- name+system_charset_info->mbmaxlen);
+ name+system_charset_info->mbmaxlen);
if (len)
{
name += len;
@@ -1526,7 +1672,7 @@ bool check_column_name(const char *name)
** Get type of table from .frm file
*/
-db_type get_table_type(const char *name)
+db_type get_table_type(THD *thd, const char *name)
{
File file;
uchar head[4];
@@ -1539,9 +1685,1033 @@ db_type get_table_type(const char *name)
error=my_read(file,(byte*) head,4,MYF(MY_NABP));
my_close(file,MYF(0));
if (error || head[0] != (uchar) 254 || head[1] != 1 ||
- (head[2] != FRM_VER && head[2] != FRM_VER+1 && head[2] != FRM_VER+3))
+ (head[2] != FRM_VER && head[2] != FRM_VER+1 &&
+ (head[2] < FRM_VER+3 || head[2] > FRM_VER+4)))
DBUG_RETURN(DB_TYPE_UNKNOWN);
- DBUG_RETURN(ha_checktype((enum db_type) (uint) *(head+3)));
+ DBUG_RETURN(ha_checktype(thd,(enum db_type) (uint) *(head+3),0,0));
+}
+
+
+/*
+ calculate md5 of query
+
+ SYNOPSIS
+ st_table_list::calc_md5()
+ buffer buffer for md5 writing
+*/
+
+void st_table_list::calc_md5(char *buffer)
+{
+ my_MD5_CTX context;
+ uchar digest[16];
+ my_MD5Init(&context);
+ my_MD5Update(&context,(uchar *) query.str, query.length);
+ my_MD5Final(digest, &context);
+ sprintf((char *) buffer,
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ digest[0], digest[1], digest[2], digest[3],
+ digest[4], digest[5], digest[6], digest[7],
+ digest[8], digest[9], digest[10], digest[11],
+ digest[12], digest[13], digest[14], digest[15]);
+}
+
+
+/*
+ set ancestor TABLE for table place holder of VIEW
+
+ DESCRIPTION
+ Replace all views that only uses one table with the table itself.
+ This allows us to treat the view as a simple table and even update
+ it
+
+ SYNOPSIS
+ st_table_list::set_ancestor()
+*/
+
+void st_table_list::set_ancestor()
+{
+ TABLE_LIST *tbl;
+
+ if ((tbl= ancestor))
+ {
+ /* This is a view. Process all tables of view */
+ DBUG_ASSERT(view);
+ do
+ {
+ if (tbl->ancestor) // This is a view
+ {
+ /*
+ This is the only case where set_ancestor is called on an object
+ that may not be a view (in which case ancestor is 0)
+ */
+ tbl->ancestor->set_ancestor();
+ }
+ } while ((tbl= tbl->next_local));
+
+ if (!multitable_view)
+ {
+ table= ancestor->table;
+ schema_table= ancestor->schema_table;
+ }
+ }
+}
+
+
+/*
+ setup fields of placeholder of merged VIEW
+
+ SYNOPSIS
+ st_table_list::setup_ancestor()
+ thd - thread handler
+
+ NOTES
+ ancestor is list of tables and views used by view (underlying tables/views)
+
+ DESCRIPTION
+ It is:
+ - preparing translation table for view columns
+ If there are underlying view(s) procedure first will be called for them.
+
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+bool st_table_list::setup_ancestor(THD *thd)
+{
+ DBUG_ENTER("st_table_list::setup_ancestor");
+ if (!field_translation)
+ {
+ Field_translator *transl;
+ SELECT_LEX *select= &view->select_lex;
+ Item *item;
+ TABLE_LIST *tbl;
+ List_iterator_fast<Item> it(select->item_list);
+ uint field_count= 0;
+
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&field_count))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ for (tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->ancestor &&
+ tbl->setup_ancestor(thd))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ /* Create view fields translation table */
+
+ if (!(transl=
+ (Field_translator*)(thd->stmt_arena->
+ alloc(select->item_list.elements *
+ sizeof(Field_translator)))))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ while ((item= it++))
+ {
+ transl[field_count].name= item->name;
+ transl[field_count++].item= item;
+ }
+ field_translation= transl;
+ field_translation_end= transl + field_count;
+ /* TODO: use hash for big number of fields */
+
+ /* full text function moving to current select */
+ if (view->select_lex.ftfunc_list->elements)
+ {
+ Item_func_match *ifm;
+ SELECT_LEX *current_select= thd->lex->current_select;
+ List_iterator_fast<Item_func_match>
+ li(*(view->select_lex.ftfunc_list));
+ while ((ifm= li++))
+ current_select->ftfunc_list->push_front(ifm);
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Prepare where expression of view
+
+ SYNOPSIS
+ st_table_list::prep_where()
+ thd - thread handler
+ conds - condition of this JOIN
+ no_where_clause - do not build WHERE or ON outer qwery do not need it
+ (it is INSERT), we do not need conds if this flag is set
+
+ NOTE: have to be called befor CHECK OPTION preparation, because it makes
+ fix_fields for view WHERE clause
+
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+bool st_table_list::prep_where(THD *thd, Item **conds,
+ bool no_where_clause)
+{
+ DBUG_ENTER("st_table_list::prep_where");
+
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->view && tbl->prep_where(thd, conds, no_where_clause))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ if (where)
+ {
+ if (!where->fixed && where->fix_fields(thd, &where))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ check that it is not VIEW in which we insert with INSERT SELECT
+ (in this case we can't add view WHERE condition to main SELECT_LEX)
+ */
+ if (!no_where_clause && !where_processed)
+ {
+ TABLE_LIST *tbl= this;
+ Query_arena *arena= thd->stmt_arena, backup;
+ arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test
+
+ /* Go up to join tree and try to find left join */
+ for (; tbl; tbl= tbl->embedding)
+ {
+ if (tbl->outer_join)
+ {
+ /*
+ Store WHERE condition to ON expression for outer join, because
+ we can't use WHERE to correctly execute left joins on VIEWs and
+ this expression will not be moved to WHERE condition (i.e. will
+ be clean correctly for PS/SP)
+ */
+ tbl->on_expr= and_conds(tbl->on_expr, where);
+ break;
+ }
+ }
+ if (tbl == 0)
+ *conds= and_conds(*conds, where);
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ where_processed= TRUE;
+ }
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Prepare check option expression of table
+
+ SYNOPSIS
+ st_table_list::prep_check_option()
+ thd - thread handler
+ check_opt_type - WITH CHECK OPTION type (VIEW_CHECK_NONE,
+ VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED)
+ we use this parameter instead of direct check of
+ effective_with_check to change type of underlying
+ views to VIEW_CHECK_CASCADED if outer view have
+ such option and prevent processing of underlying
+ view check options if outer view have just
+ VIEW_CHECK_LOCAL option.
+
+ NOTE
+ This method build check options for every call
+ (usual execution or every SP/PS call)
+ This method have to be called after WHERE preparation
+ (st_table_list::prep_where)
+
+ RETURN
+ FALSE - OK
+ TRUE - error
+*/
+
+bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type)
+{
+ DBUG_ENTER("st_table_list::prep_check_option");
+
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ /* see comment of check_opt_type parameter */
+ if (tbl->view &&
+ tbl->prep_check_option(thd,
+ ((check_opt_type == VIEW_CHECK_CASCADED) ?
+ VIEW_CHECK_CASCADED :
+ VIEW_CHECK_NONE)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ if (check_opt_type)
+ {
+ Item *item= 0;
+ if (where)
+ {
+ DBUG_ASSERT(where->fixed);
+ item= where->copy_andor_structure(thd);
+ }
+ if (check_opt_type == VIEW_CHECK_CASCADED)
+ {
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->check_option)
+ item= and_conds(item, tbl->check_option);
+ }
+ }
+ if (item)
+ thd->change_item_tree(&check_option, item);
+ }
+
+ if (check_option)
+ {
+ const char *save_where= thd->where;
+ thd->where= "check option";
+ if (!check_option->fixed &&
+ check_option->fix_fields(thd, &check_option) ||
+ check_option->check_cols(1))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ thd->where= save_where;
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Hide errors which show view underlying table information
+
+ SYNOPSIS
+ st_table_list::hide_view_error()
+ thd thread handler
+
+*/
+
+void st_table_list::hide_view_error(THD *thd)
+{
+ /* Hide "Unknown column" or "Unknown function" error */
+ if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
+ thd->net.last_errno == ER_SP_DOES_NOT_EXIST)
+ {
+ thd->clear_error();
+ my_error(ER_VIEW_INVALID, MYF(0), view_db.str, view_name.str);
+ }
+ else if (thd->net.last_errno == ER_NO_DEFAULT_FOR_FIELD)
+ {
+ thd->clear_error();
+ // TODO: make correct error message
+ my_error(ER_NO_DEFAULT_FOR_VIEW_FIELD, MYF(0), view_db.str, view_name.str);
+ }
+}
+
+
+/*
+ Find underlying base tables (TABLE_LIST) which represent given
+ table_to_find (TABLE)
+
+ SYNOPSIS
+ st_table_list::find_underlying_table()
+ table_to_find table to find
+
+ RETURN
+ 0 table is not found
+ found table reference
+*/
+
+st_table_list *st_table_list::find_underlying_table(TABLE *table_to_find)
+{
+ /* is this real table and table which we are looking for? */
+ if (table == table_to_find && ancestor == 0)
+ return this;
+
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ TABLE_LIST *result;
+ if ((result= tbl->find_underlying_table(table_to_find)))
+ return result;
+ }
+ return 0;
+}
+
+/*
+ cleunup items belonged to view fields translation table
+
+ SYNOPSIS
+ st_table_list::cleanup_items()
+*/
+
+void st_table_list::cleanup_items()
+{
+ if (!field_translation)
+ return;
+
+ for (Field_translator *transl= field_translation;
+ transl < field_translation_end;
+ transl++)
+ transl->item->walk(&Item::cleanup_processor, 0);
+}
+
+
+/*
+ check CHECK OPTION condition
+
+ SYNOPSIS
+ check_option()
+ ignore_failure ignore check option fail
+
+ RETURN
+ VIEW_CHECK_OK OK
+ VIEW_CHECK_ERROR FAILED
+ VIEW_CHECK_SKIP FAILED, but continue
+*/
+
+int st_table_list::view_check_option(THD *thd, bool ignore_failure)
+{
+ if (check_option && check_option->val_int() == 0)
+ {
+ TABLE_LIST *view= top_table();
+ if (ignore_failure)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_VIEW_CHECK_FAILED, ER(ER_VIEW_CHECK_FAILED),
+ view->view_db.str, view->view_name.str);
+ return(VIEW_CHECK_SKIP);
+ }
+ else
+ {
+ my_error(ER_VIEW_CHECK_FAILED, MYF(0), view->view_db.str, view->view_name.str);
+ return(VIEW_CHECK_ERROR);
+ }
+ }
+ return(VIEW_CHECK_OK);
+}
+
+
+/*
+ Find table in underlying tables by mask and check that only this
+ table belong to given mask
+
+ SYNOPSIS
+ st_table_list::check_single_table()
+ table reference on variable where to store found table
+ (should be 0 on call, to find table, or point to table for
+ unique test)
+ map bit mask of tables
+ view view for which we are looking table
+
+ RETURN
+ FALSE table not found or found only one
+ TRUE found several tables
+*/
+
+bool st_table_list::check_single_table(st_table_list **table, table_map map,
+ st_table_list *view)
+{
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->table)
+ {
+ if (tbl->table->map & map)
+ {
+ if (*table)
+ return TRUE;
+ *table= tbl;
+ tbl->check_option= view->check_option;
+ }
+ }
+ else if (tbl->check_single_table(table, map, view))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
+ Set insert_values buffer
+
+ SYNOPSIS
+ set_insert_values()
+ mem_root memory pool for allocating
+
+ RETURN
+ FALSE - OK
+ TRUE - out of memory
+*/
+
+bool st_table_list::set_insert_values(MEM_ROOT *mem_root)
+{
+ if (table)
+ {
+ if (!table->insert_values &&
+ !(table->insert_values= (byte *)alloc_root(mem_root,
+ table->s->rec_buff_length)))
+ return TRUE;
+ }
+ else
+ {
+ DBUG_ASSERT(view && ancestor);
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ if (tbl->set_insert_values(mem_root))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
+ Test if this is a leaf with respect to name resolution.
+
+ SYNOPSIS
+ st_table_list::is_leaf_for_name_resolution()
+
+ DESCRIPTION
+ A table reference is a leaf with respect to name resolution if
+ it is either a leaf node in a nested join tree (table, view,
+ schema table, subquery), or an inner node that represents a
+ NATURAL/USING join, or a nested join with materialized join
+ columns.
+
+ RETURN
+ TRUE if a leaf, FALSE otherwise.
+*/
+bool st_table_list::is_leaf_for_name_resolution()
+{
+ return (view || is_natural_join || is_join_columns_complete ||
+ !nested_join);
+}
+
+
+/*
+ Retrieve the first (left-most) leaf in a nested join tree with
+ respect to name resolution.
+
+ SYNOPSIS
+ st_table_list::first_leaf_for_name_resolution()
+
+ DESCRIPTION
+ Given that 'this' is a nested table reference, recursively walk
+ down the left-most children of 'this' until we reach a leaf
+ table reference with respect to name resolution.
+
+ IMPLEMENTATION
+ The left-most child of a nested table reference is the last element
+ in the list of children because the children are inserted in
+ reverse order.
+
+ RETURN
+ If 'this' is a nested table reference - the left-most child of
+ the tree rooted in 'this',
+ else return 'this'
+*/
+
+TABLE_LIST *st_table_list::first_leaf_for_name_resolution()
+{
+ TABLE_LIST *cur_table_ref;
+ NESTED_JOIN *cur_nested_join;
+ LINT_INIT(cur_table_ref);
+
+ if (is_leaf_for_name_resolution())
+ return this;
+ DBUG_ASSERT(nested_join);
+
+ for (cur_nested_join= nested_join;
+ cur_nested_join;
+ cur_nested_join= cur_table_ref->nested_join)
+ {
+ List_iterator_fast<TABLE_LIST> it(cur_nested_join->join_list);
+ cur_table_ref= it++;
+ /*
+ If 'this' is a RIGHT JOIN, the operands in 'join_list' are in reverse
+ order, thus the first operand is already at the front of the list.
+ */
+ if (!(cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
+ {
+ TABLE_LIST *next;
+ while ((next= it++))
+ cur_table_ref= next;
+ }
+ if (cur_table_ref->is_leaf_for_name_resolution())
+ break;
+ }
+ return cur_table_ref;
+}
+
+
+/*
+ Retrieve the last (right-most) leaf in a nested join tree with
+ respect to name resolution.
+
+ SYNOPSIS
+ st_table_list::last_leaf_for_name_resolution()
+
+ DESCRIPTION
+ Given that 'this' is a nested table reference, recursively walk
+ down the right-most children of 'this' until we reach a leaf
+ table reference with respect to name resolution.
+
+ IMPLEMENTATION
+ The right-most child of a nested table reference is the first
+ element in the list of children because the children are inserted
+ in reverse order.
+
+ RETURN
+ - If 'this' is a nested table reference - the right-most child of
+ the tree rooted in 'this',
+ - else - 'this'
+*/
+
+TABLE_LIST *st_table_list::last_leaf_for_name_resolution()
+{
+ TABLE_LIST *cur_table_ref= this;
+ NESTED_JOIN *cur_nested_join;
+
+ if (is_leaf_for_name_resolution())
+ return this;
+ DBUG_ASSERT(nested_join);
+
+ for (cur_nested_join= nested_join;
+ cur_nested_join;
+ cur_nested_join= cur_table_ref->nested_join)
+ {
+ /*
+ If 'this' is a RIGHT JOIN, the operands in 'join_list' are in reverse
+ order, thus the last operand is in the end of the list.
+ */
+ if ((cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
+ {
+ List_iterator_fast<TABLE_LIST> it(cur_nested_join->join_list);
+ TABLE_LIST *next;
+ cur_table_ref= it++;
+ while ((next= it++))
+ cur_table_ref= next;
+ }
+ else
+ cur_table_ref= cur_nested_join->join_list.head();
+ if (cur_table_ref->is_leaf_for_name_resolution())
+ break;
+ }
+ return cur_table_ref;
+}
+
+
+Natural_join_column::Natural_join_column(Field_translator *field_param,
+ TABLE_LIST *tab)
+{
+ DBUG_ASSERT(tab->field_translation);
+ view_field= field_param;
+ table_field= NULL;
+ table_ref= tab;
+ is_common= FALSE;
+}
+
+
+Natural_join_column::Natural_join_column(Field *field_param,
+ TABLE_LIST *tab)
+{
+ DBUG_ASSERT(tab->table == field_param->table);
+ table_field= field_param;
+ view_field= NULL;
+ table_ref= tab;
+ is_common= FALSE;
+}
+
+
+const char *Natural_join_column::name()
+{
+ if (view_field)
+ {
+ DBUG_ASSERT(table_field == NULL);
+ return view_field->name;
+ }
+
+ return table_field->field_name;
+}
+
+
+Item *Natural_join_column::create_item(THD *thd)
+{
+ if (view_field)
+ {
+ DBUG_ASSERT(table_field == NULL);
+ return create_view_field(thd, table_ref, &view_field->item,
+ view_field->name);
+ }
+ return new Item_field(thd, &thd->lex->current_select->context, table_field);
+}
+
+
+Field *Natural_join_column::field()
+{
+ if (view_field)
+ {
+ DBUG_ASSERT(table_field == NULL);
+ return NULL;
+ }
+ return table_field;
+}
+
+
+const char *Natural_join_column::table_name()
+{
+ return table_ref->alias;
+ /*
+ TODO:
+ I think that it is sufficient to return just
+ table->alias, which is correctly set to either
+ the view name, the table name, or the alias to
+ the table reference (view or stored table).
+ */
+#ifdef NOT_YET
+ if (view_field)
+ return table_ref->view_name.str;
+
+ DBUG_ASSERT(!strcmp(table_ref->table_name,
+ table_ref->table->s->table_name));
+ return table_ref->table_name;
+}
+#endif
+}
+
+
+const char *Natural_join_column::db_name()
+{
+ if (view_field)
+ return table_ref->view_db.str;
+
+ DBUG_ASSERT(!strcmp(table_ref->db,
+ table_ref->table->s->db));
+ return table_ref->db;
+}
+
+
+GRANT_INFO *Natural_join_column::grant()
+{
+ if (view_field)
+ return &(table_ref->grant);
+ return &(table_ref->table->grant);
+}
+
+
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+
+/*
+ Check the access rights for the current join column.
+ columns.
+
+ SYNOPSIS
+ Natural_join_column::check_grants()
+
+ DESCRIPTION
+ Check the access rights to a column from a natural join in a generic
+ way that hides the heterogeneity of the column representation - whether
+ it is a view or a stored table colum.
+
+ RETURN
+ FALSE The column can be accessed
+ TRUE There are no access rights to all equivalent columns
+*/
+
+bool
+Natural_join_column::check_grants(THD *thd, const char *name, uint length)
+{
+ GRANT_INFO *grant;
+ const char *db_name;
+ const char *table_name;
+
+ if (view_field)
+ {
+ DBUG_ASSERT(table_field == NULL);
+ grant= &(table_ref->grant);
+ db_name= table_ref->view_db.str;
+ table_name= table_ref->view_name.str;
+ }
+ else
+ {
+ DBUG_ASSERT(table_field && view_field == NULL);
+ grant= &(table_ref->table->grant);
+ db_name= table_ref->table->s->db;
+ table_name= table_ref->table->s->table_name;
+ }
+
+ return check_grant_column(thd, grant, db_name, table_name, name, length);
+}
+#endif
+
+
+void Field_iterator_view::set(TABLE_LIST *table)
+{
+ DBUG_ASSERT(table->field_translation);
+ view= table;
+ ptr= table->field_translation;
+ array_end= table->field_translation_end;
+}
+
+
+const char *Field_iterator_table::name()
+{
+ return (*ptr)->field_name;
+}
+
+
+Item *Field_iterator_table::create_item(THD *thd)
+{
+ return new Item_field(thd, &thd->lex->current_select->context, *ptr);
+}
+
+
+const char *Field_iterator_view::name()
+{
+ return ptr->name;
+}
+
+
+Item *Field_iterator_view::create_item(THD *thd)
+{
+ return create_view_field(thd, view, &ptr->item, ptr->name);
+}
+
+Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
+ const char *name)
+{
+ bool save_wrapper= thd->lex->select_lex.no_wrap_view_item;
+ Item *field= *field_ref;
+ DBUG_ENTER("create_view_field");
+
+ if (view->schema_table_reformed)
+ {
+ /*
+ In case of SHOW command (schema_table_reformed set) all items are
+ fixed
+ */
+ DBUG_ASSERT(field && field->fixed);
+ DBUG_RETURN(field);
+ }
+
+ DBUG_ASSERT(field);
+ thd->lex->current_select->no_wrap_view_item= TRUE;
+ if (!field->fixed)
+ {
+ if (field->fix_fields(thd, field_ref))
+ {
+ thd->lex->current_select->no_wrap_view_item= save_wrapper;
+ DBUG_RETURN(0);
+ }
+ field= *field_ref;
+ }
+ thd->lex->current_select->no_wrap_view_item= save_wrapper;
+ if (thd->lex->current_select->no_wrap_view_item)
+ {
+ DBUG_RETURN(field);
+ }
+ Item *item= new Item_direct_view_ref(&view->view->select_lex.context,
+ field_ref, view->view_name.str,
+ name);
+ DBUG_RETURN(item);
+}
+
+
+void Field_iterator_natural_join::set(TABLE_LIST *table_ref)
+{
+ DBUG_ASSERT(table_ref->join_columns);
+ delete column_ref_it;
+
+ /*
+ TODO: try not to allocate new iterator every time. If we have to,
+ then check for out of memory condition.
+ */
+ column_ref_it= new List_iterator_fast<Natural_join_column>
+ (*(table_ref->join_columns));
+ cur_column_ref= (*column_ref_it)++;
+}
+
+
+void Field_iterator_natural_join::next()
+{
+ cur_column_ref= (*column_ref_it)++;
+ DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field ||
+ cur_column_ref->table_ref->table ==
+ cur_column_ref->table_field->table);
+}
+
+
+void Field_iterator_table_ref::set_field_iterator()
+{
+ DBUG_ENTER("Field_iterator_table_ref::set_field_iterator");
+ /*
+ If the table reference we are iterating over is a natural join, or it is
+ an operand of a natural join, and TABLE_LIST::join_columns contains all
+ the columns of the join operand, then we pick the columns from
+ TABLE_LIST::join_columns, instead of the orginial container of the
+ columns of the join operator.
+ */
+ if (table_ref->is_join_columns_complete)
+ {
+ /* Necesary, but insufficient conditions. */
+ DBUG_ASSERT(table_ref->is_natural_join ||
+ table_ref->nested_join ||
+ table_ref->join_columns &&
+ /* This is a merge view. */
+ ((table_ref->field_translation &&
+ table_ref->join_columns->elements ==
+ (ulong)(table_ref->field_translation_end -
+ table_ref->field_translation)) ||
+ /* This is stored table or a tmptable view. */
+ (!table_ref->field_translation &&
+ table_ref->join_columns->elements ==
+ table_ref->table->s->fields)));
+ field_it= &natural_join_it;
+ DBUG_PRINT("info",("field_it for '%s' is Field_iterator_natural_join",
+ table_ref->alias));
+ }
+ /* This is a merge view, so use field_translation. */
+ else if (table_ref->field_translation)
+ {
+ DBUG_ASSERT(table_ref->view &&
+ table_ref->effective_algorithm == VIEW_ALGORITHM_MERGE);
+ field_it= &view_field_it;
+ DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_view",
+ table_ref->alias));
+ }
+ /* This is a base table or stored view. */
+ else
+ {
+ DBUG_ASSERT(table_ref->table || table_ref->view);
+ field_it= &table_field_it;
+ DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_table",
+ table_ref->alias));
+ }
+ field_it->set(table_ref);
+ DBUG_VOID_RETURN;
+}
+
+
+void Field_iterator_table_ref::set(TABLE_LIST *table)
+{
+ DBUG_ASSERT(table);
+ first_leaf= table->first_leaf_for_name_resolution();
+ last_leaf= table->last_leaf_for_name_resolution();
+ DBUG_ASSERT(first_leaf && last_leaf);
+ table_ref= first_leaf;
+ set_field_iterator();
+}
+
+
+void Field_iterator_table_ref::next()
+{
+ /* Move to the next field in the current table reference. */
+ field_it->next();
+ /*
+ If all fields of the current table reference are exhausted, move to
+ the next leaf table reference.
+ */
+ if (field_it->end_of_fields() && table_ref != last_leaf)
+ {
+ table_ref= table_ref->next_name_resolution_table;
+ DBUG_ASSERT(table_ref);
+ set_field_iterator();
+ }
+}
+
+
+const char *Field_iterator_table_ref::table_name()
+{
+ if (table_ref->view)
+ return table_ref->view_name.str;
+ else if (table_ref->is_natural_join)
+ return natural_join_it.column_ref()->table_name();
+
+ DBUG_ASSERT(!strcmp(table_ref->table_name,
+ table_ref->table->s->table_name));
+ return table_ref->table_name;
+}
+
+
+const char *Field_iterator_table_ref::db_name()
+{
+ if (table_ref->view)
+ return table_ref->view_db.str;
+ else if (table_ref->is_natural_join)
+ return natural_join_it.column_ref()->db_name();
+
+ DBUG_ASSERT(!strcmp(table_ref->db, table_ref->table->s->db));
+ return table_ref->db;
+}
+
+
+GRANT_INFO *Field_iterator_table_ref::grant()
+{
+ if (table_ref->view)
+ return &(table_ref->grant);
+ else if (table_ref->is_natural_join)
+ return natural_join_it.column_ref()->grant();
+ return &(table_ref->table->grant);
+}
+
+
+/*
+ Create new or return existing column reference to a column of a
+ natural/using join.
+
+ SYNOPSIS
+ Field_iterator_table_ref::get_or_create_column_ref()
+ thd [in] pointer to current thread
+ is_created [out] set to TRUE if the column was created,
+ FALSE if we return an already created colum
+
+ DESCRIPTION
+ TODO
+
+ RETURN
+ # Pointer to a column of a natural join (or its operand)
+ NULL No memory to allocate the column
+*/
+
+Natural_join_column *
+Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created)
+{
+ Natural_join_column *nj_col;
+
+ *is_created= TRUE;
+ if (field_it == &table_field_it)
+ {
+ /* The field belongs to a stored table. */
+ Field *field= table_field_it.field();
+ nj_col= new Natural_join_column(field, table_ref);
+ }
+ else if (field_it == &view_field_it)
+ {
+ /* The field belongs to a merge view or information schema table. */
+ Field_translator *translated_field= view_field_it.field_translator();
+ nj_col= new Natural_join_column(translated_field, table_ref);
+ }
+ else
+ {
+ /*
+ The field belongs to a NATURAL join, therefore the column reference was
+ already created via one of the two constructor calls above. In this case
+ we just return the already created column reference.
+ */
+ *is_created= FALSE;
+ nj_col= natural_join_it.column_ref();
+ DBUG_ASSERT(nj_col);
+ }
+ DBUG_ASSERT(!nj_col->table_field ||
+ nj_col->table_ref->table == nj_col->table_field->table);
+ return nj_col;
}
@@ -1549,7 +2719,7 @@ db_type get_table_type(const char *name)
** Instansiate templates
*****************************************************************************/
-#ifdef __GNUC__
+#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List<String>;
template class List_iterator<String>;
#endif
diff --git a/sql/table.h b/sql/table.h
index 77153e5d8cd..43b6fddeee6 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -20,6 +20,8 @@
class Item; /* Needed by ORDER */
class GRANT_TABLE;
class st_select_lex_unit;
+class st_select_lex;
+class COND_EQUAL;
/* Order clause list element */
@@ -27,12 +29,16 @@ typedef struct st_order {
struct st_order *next;
Item **item; /* Point at item in select fields */
Item *item_ptr; /* Storage for initial item */
+ Item **item_copy; /* For SPs; the original item ptr */
+ int counter; /* position in SELECT list, correct
+ only if counter_used is true*/
bool asc; /* true if ascending */
bool free_me; /* true if item isn't shared */
bool in_field_list; /* true if in select field list */
+ bool counter_used; /* parameter was counter of columns */
Field *field; /* If tmp-table group */
char *buff; /* If tmp-table group */
- table_map used,depend_map;
+ table_map used, depend_map;
} ORDER;
typedef struct st_grant_info
@@ -43,7 +49,15 @@ typedef struct st_grant_info
ulong want_privilege;
} GRANT_INFO;
-enum tmp_table_type {NO_TMP_TABLE=0, TMP_TABLE=1, TRANSACTIONAL_TMP_TABLE=2};
+enum tmp_table_type {NO_TMP_TABLE=0, TMP_TABLE=1, TRANSACTIONAL_TMP_TABLE=2,
+ SYSTEM_TMP_TABLE=3};
+
+enum frm_type_enum
+{
+ FRMTYPE_ERROR= 0,
+ FRMTYPE_TABLE,
+ FRMTYPE_VIEW
+};
typedef struct st_filesort_info
{
@@ -75,49 +89,130 @@ enum timestamp_auto_set_type
#define clear_timestamp_auto_bits(_target_, _bits_) \
(_target_)= (enum timestamp_auto_set_type)((int)(_target_) & ~(int)(_bits_))
-/* Table cache entry struct */
-
class Field_timestamp;
class Field_blob;
+class Table_triggers_list;
-struct st_table {
- handler *file;
- Field **field; /* Pointer to fields */
- Field_blob **blob_field; /* Pointer to blob fields */
+/*
+ This structure is shared between different table objects. There is one
+ instance of table share per one table in the database.
+*/
+
+typedef struct st_table_share
+{
/* hash of field names (contains pointers to elements of field array) */
- HASH name_hash;
- byte *record[2]; /* Pointer to records */
- byte *default_values; /* Default values for INSERT */
- byte *insert_values; /* used by INSERT ... UPDATE */
- uint fields; /* field count */
- uint reclength; /* Recordlength */
- uint rec_buff_length;
- uint keys,key_parts,primary_key,max_key_length,max_unique_length;
- uint total_key_length;
- uint uniques;
- uint null_fields; /* number of null fields */
- uint blob_fields; /* number of blob fields */
- key_map keys_in_use, keys_for_keyread, read_only_keys;
- key_map quick_keys;
- key_map used_keys; /* keys that cover all used table fields */
- key_map keys_in_use_for_query;
- KEY *key_info; /* data of keys in database */
+ HASH name_hash; /* hash of field names */
+ MEM_ROOT mem_root;
TYPELIB keynames; /* Pointers to keynames */
- ha_rows max_rows; /* create information */
- ha_rows min_rows; /* create information */
- ulong avg_row_length; /* create information */
- ulong raid_chunksize;
TYPELIB fieldnames; /* Pointer to fieldnames */
TYPELIB *intervals; /* pointer to interval info */
+#ifdef NOT_YET
+ pthread_mutex_t mutex; /* For locking the share */
+ pthread_cond_t cond; /* To signal that share is ready */
+ struct st_table *open_tables; /* link to open tables */
+ struct st_table *used_next, /* Link to used tables */
+ **used_prev;
+ /* The following is copied to each TABLE on OPEN */
+ Field **field;
+ KEY *key_info; /* data of keys in database */
+#endif
+ uint *blob_field; /* Index to blobs in Field arrray*/
+ byte *default_values; /* row with default values */
+ char *comment; /* Comment about table */
+ CHARSET_INFO *table_charset; /* Default charset of string fields */
+
+ /* A pair "database_name\0table_name\0", widely used as simply a db name */
+ char *table_cache_key;
+ const char *db; /* Pointer to db */
+ const char *table_name; /* Table name (for open) */
+ const char *path; /* Path to .frm file (from datadir) */
+ LEX_STRING connect_string;
+ key_map keys_in_use; /* Keys in use for table */
+ key_map keys_for_keyread;
+ ulong avg_row_length; /* create information */
+ ulong raid_chunksize;
+ ulong version, flush_version, mysql_version;
+ ulong timestamp_offset; /* Set to offset+1 of record */
+ ulong reclength; /* Recordlength */
+
+ ha_rows min_rows, max_rows; /* create information */
enum db_type db_type; /* table_type for handler */
enum row_type row_type; /* How rows are stored */
+ enum tmp_table_type tmp_table;
+
+ uint blob_ptr_size; /* 4 or 8 */
+ uint null_bytes;
+ uint key_length; /* Length of table_cache_key */
+ uint fields; /* Number of fields */
+ uint rec_buff_length; /* Size of table->record[] buffer */
+ uint keys, key_parts;
+ uint max_key_length, max_unique_length, total_key_length;
+ uint uniques; /* Number of UNIQUE index */
+ uint null_fields; /* number of null fields */
+ uint blob_fields; /* number of blob fields */
+ uint varchar_fields; /* number of varchar fields */
uint db_create_options; /* Create options from database */
uint db_options_in_use; /* Options in use */
uint db_record_offset; /* if HA_REC_IN_SEQ */
- uint db_stat; /* mode of file as in handler.h */
- uint raid_type,raid_chunks;
- uint status; /* Used by postfix.. */
- uint system; /* Set if system record */
+ uint raid_type, raid_chunks;
+ uint open_count; /* Number of tables in open list */
+ /* Index of auto-updated TIMESTAMP field in field array */
+ uint primary_key;
+ uint timestamp_field_offset;
+ uint next_number_index;
+ uint next_number_key_offset;
+ uchar frm_version;
+ my_bool system; /* Set if system record */
+ my_bool crypted; /* If .frm file is crypted */
+ my_bool db_low_byte_first; /* Portable row format */
+ my_bool crashed;
+ my_bool is_view;
+ my_bool name_lock, replace_with_name_lock;
+ /*
+ TRUE if this is a system table like 'mysql.proc', which we want to be
+ able to open and lock even when we already have some tables open and
+ locked. To avoid deadlocks we have to put certain restrictions on
+ locking of this table for writing. FALSE - otherwise.
+ */
+ my_bool system_table;
+} TABLE_SHARE;
+
+
+/* Information for one open table */
+
+struct st_table {
+ TABLE_SHARE *s;
+ handler *file;
+#ifdef NOT_YET
+ struct st_table *used_next, **used_prev; /* Link to used tables */
+ struct st_table *open_next, **open_prev; /* Link to open tables */
+#endif
+ struct st_table *next, *prev;
+
+ THD *in_use; /* Which thread uses this */
+ Field **field; /* Pointer to fields */
+
+ byte *record[2]; /* Pointer to records */
+ byte *insert_values; /* used by INSERT ... UPDATE */
+ key_map quick_keys, used_keys, keys_in_use_for_query;
+ KEY *key_info; /* data of keys in database */
+
+ Field *next_number_field, /* Set if next_number is activated */
+ *found_next_number_field, /* Set on open */
+ *rowid_field;
+ Field_timestamp *timestamp_field;
+
+ /* Table's triggers, 0 if there are no of them */
+ Table_triggers_list *triggers;
+ struct st_table_list *pos_in_table_list;/* Element referring to this table */
+ ORDER *group;
+ const char *alias; /* alias or table name */
+ uchar *null_flags;
+ query_id_t query_id;
+
+ ha_rows quick_rows[MAX_KEY];
+ key_part_map const_key_parts[MAX_KEY];
+ uint quick_key_parts[MAX_KEY];
/*
If this table has TIMESTAMP field with auto-set property (pointed by
@@ -132,111 +227,539 @@ struct st_table {
as example).
*/
timestamp_auto_set_type timestamp_field_type;
- /* Index of auto-updated TIMESTAMP field in field array */
- uint timestamp_field_offset;
+ table_map map; /* ID bit of table (1,2,4,8,16...) */
- uint next_number_index;
- uint blob_ptr_size; /* 4 or 8 */
- uint next_number_key_offset;
- int current_lock; /* Type of lock on table */
- enum tmp_table_type tmp_table;
+ uint tablenr,used_fields;
+ uint temp_pool_slot; /* Used by intern temp tables */
+ uint status; /* What's in record[0] */
+ uint db_stat; /* mode of file as in handler.h */
+ /* number of select if it is derived table */
+ uint derived_select_number;
+ int current_lock; /* Type of lock on table */
my_bool copy_blobs; /* copy_blobs when storing */
+
+ /*
+ 0 or JOIN_TYPE_{LEFT|RIGHT}. Currently this is only compared to 0.
+ If maybe_null !=0, this table is inner w.r.t. some outer join operation,
+ and null_row may be true.
+ */
+ uint maybe_null;
/*
- Used in outer joins: if true, all columns are considered to have NULL
- values, including columns declared as "not null".
+ If true, the current table row is considered to have all columns set to
+ NULL, including columns declared as "not null" (see maybe_null).
*/
my_bool null_row;
- /* 0 or JOIN_TYPE_{LEFT|RIGHT}, same as TABLE_LIST::outer_join */
- my_bool outer_join;
- my_bool maybe_null; /* true if (outer_join != 0) */
my_bool force_index;
my_bool distinct,const_table,no_rows;
- my_bool key_read;
- my_bool crypted;
- my_bool db_low_byte_first; /* Portable row format */
+ my_bool key_read, no_keyread;
my_bool locked_by_flush;
my_bool locked_by_name;
my_bool fulltext_searched;
- my_bool crashed;
- my_bool is_view;
- my_bool no_keyread, no_cache;
- my_bool clear_query_id; /* To reset query_id for tables and cols */
+ my_bool no_cache;
+ /* To signal that we should reset query_id for tables and cols */
+ my_bool clear_query_id;
my_bool auto_increment_field_not_null;
- Field *next_number_field, /* Set if next_number is activated */
- *found_next_number_field, /* Set on open */
- *rowid_field;
- Field_timestamp *timestamp_field;
-#if MYSQL_VERSION_ID < 40100
- /*
- Indicates whenever we have to set field_length members of all TIMESTAMP
- fields to 19 (to honour 'new_mode' variable) or to original
- field_length values.
- */
- my_bool timestamp_mode;
-#endif
- my_string comment; /* Comment about table */
- CHARSET_INFO *table_charset; /* Default charset of string fields */
+ my_bool insert_or_update; /* Can be used by the handler */
+ my_bool alias_name_used; /* true if table_name is alias */
+
REGINFO reginfo; /* field connections */
MEM_ROOT mem_root;
GRANT_INFO grant;
-
- /* A pair "database_name\0table_name\0", widely used as simply a db name */
- char *table_cache_key;
- char *table_name,*real_name,*path;
- uint key_length; /* Length of key */
- uint tablenr,used_fields,null_bytes;
- table_map map; /* ID bit of table (1,2,4,8,16...) */
- ulong version,flush_version;
- uchar *null_flags;
FILESORT_INFO sort;
- ORDER *group;
- ha_rows quick_rows[MAX_KEY];
- uint quick_key_parts[MAX_KEY];
- key_part_map const_key_parts[MAX_KEY];
- ulong query_id;
- uchar frm_version;
+ TABLE_SHARE share_not_to_be_used; /* To be deleted when true shares */
+};
- union /* Temporary variables */
- {
- uint temp_pool_slot; /* Used by intern temp tables */
- struct st_table_list *pos_in_table_list;
- };
- /* number of select if it is derived table */
- uint derived_select_number;
- THD *in_use; /* Which thread uses this */
- struct st_table *next,*prev;
+
+typedef struct st_foreign_key_info
+{
+ LEX_STRING *forein_id;
+ LEX_STRING *referenced_db;
+ LEX_STRING *referenced_table;
+ LEX_STRING *constraint_method;
+ List<LEX_STRING> foreign_fields;
+ List<LEX_STRING> referenced_fields;
+} FOREIGN_KEY_INFO;
+
+
+enum enum_schema_tables
+{
+ SCH_CHARSETS= 0,
+ SCH_COLLATIONS,
+ SCH_COLLATION_CHARACTER_SET_APPLICABILITY,
+ SCH_COLUMNS,
+ SCH_COLUMN_PRIVILEGES,
+ SCH_KEY_COLUMN_USAGE,
+ SCH_OPEN_TABLES,
+ SCH_PROCEDURES,
+ SCH_SCHEMATA,
+ SCH_SCHEMA_PRIVILEGES,
+ SCH_STATISTICS,
+ SCH_STATUS,
+ SCH_TABLES,
+ SCH_TABLE_CONSTRAINTS,
+ SCH_TABLE_NAMES,
+ SCH_TABLE_PRIVILEGES,
+ SCH_TRIGGERS,
+ SCH_VARIABLES,
+ SCH_VIEWS,
+ SCH_USER_PRIVILEGES
};
+typedef struct st_field_info
+{
+ const char* field_name;
+ uint field_length;
+ enum enum_field_types field_type;
+ int value;
+ bool maybe_null;
+ const char* old_name;
+} ST_FIELD_INFO;
+
+
+struct st_table_list;
+typedef class Item COND;
+
+typedef struct st_schema_table
+{
+ const char* table_name;
+ ST_FIELD_INFO *fields_info;
+ /* Create information_schema table */
+ TABLE *(*create_table) (THD *thd, struct st_table_list *table_list);
+ /* Fill table with data */
+ int (*fill_table) (THD *thd, struct st_table_list *tables, COND *cond);
+ /* Handle fileds for old SHOW */
+ int (*old_format) (THD *thd, struct st_schema_table *schema_table);
+ int (*process_table) (THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res, const char *base_name,
+ const char *file_name);
+ int idx_field1, idx_field2;
+ bool hidden;
+} ST_SCHEMA_TABLE;
+
+
#define JOIN_TYPE_LEFT 1
#define JOIN_TYPE_RIGHT 2
+#define VIEW_ALGORITHM_UNDEFINED 0
+#define VIEW_ALGORITHM_TMPTABLE 1
+#define VIEW_ALGORITHM_MERGE 2
+
+/* view WITH CHECK OPTION parameter options */
+#define VIEW_CHECK_NONE 0
+#define VIEW_CHECK_LOCAL 1
+#define VIEW_CHECK_CASCADED 2
+
+/* result of view WITH CHECK OPTION parameter check */
+#define VIEW_CHECK_OK 0
+#define VIEW_CHECK_ERROR 1
+#define VIEW_CHECK_SKIP 2
+
+struct st_lex;
+struct st_table_list;
+class select_union;
+class TMP_TABLE_PARAM;
+
+Item *create_view_field(THD *thd, st_table_list *view, Item **field_ref,
+ const char *name);
+
+struct Field_translator
+{
+ Item *item;
+ const char *name;
+};
+
+
+/*
+ Column reference of a NATURAL/USING join. Since column references in
+ joins can be both from views and stored tables, may point to either a
+ Field (for tables), or a Field_translator (for views).
+*/
+
+class Natural_join_column: public Sql_alloc
+{
+public:
+ Field_translator *view_field; /* Column reference of merge view. */
+ Field *table_field; /* Column reference of table or temp view. */
+ st_table_list *table_ref; /* Original base table/view reference. */
+ /*
+ True if a common join column of two NATURAL/USING join operands. Notice
+ that when we have a hierarchy of nested NATURAL/USING joins, a column can
+ be common at some level of nesting but it may not be common at higher
+ levels of nesting. Thus this flag may change depending on at which level
+ we are looking at some column.
+ */
+ bool is_common;
+public:
+ Natural_join_column(Field_translator *field_param, st_table_list *tab);
+ Natural_join_column(Field *field_param, st_table_list *tab);
+ const char *name();
+ Item *create_item(THD *thd);
+ Field *field();
+ const char *table_name();
+ const char *db_name();
+ GRANT_INFO *grant();
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ bool check_grants(THD *thd, const char *name, uint length);
+#endif
+};
+
+
+/*
+ Table reference in the FROM clause.
+
+ These table references can be of several types that correspond to
+ different SQL elements. Below we list all types of TABLE_LISTs with
+ the necessary conditions to determine when a TABLE_LIST instance
+ belongs to a certain type.
+
+ 1) table (TABLE_LIST::view == NULL)
+ - base table
+ (TABLE_LIST::derived == NULL)
+ - subquery - TABLE_LIST::table is a temp table
+ (TABLE_LIST::derived != NULL)
+ - information schema table
+ (TABLE_LIST::schema_table != NULL)
+ NOTICE: for schema tables TABLE_LIST::field_translation may be != NULL
+ 2) view (TABLE_LIST::view != NULL)
+ - merge (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_MERGE)
+ also (TABLE_LIST::field_translation != NULL)
+ - tmptable (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_TMPTABLE)
+ also (TABLE_LIST::field_translation == NULL)
+ 3) nested table reference (TABLE_LIST::nested_join != NULL)
+ - table sequence - e.g. (t1, t2, t3)
+ TODO: how to distinguish from a JOIN?
+ - general JOIN
+ TODO: how to distinguish from a table sequence?
+ - NATURAL JOIN
+ (TABLE_LIST::natural_join != NULL)
+ - JOIN ... USING
+ (TABLE_LIST::join_using_fields != NULL)
+*/
+
typedef struct st_table_list
{
- struct st_table_list *next;
- char *db, *alias, *real_name;
- char *option; /* Used by cache index */
+ /*
+ List of tables local to a subquery (used by SQL_LIST). Considers
+ views as leaves (unlike 'next_leaf' below). Created at parse time
+ in st_select_lex::add_table_to_list() -> table_list.link_in_list().
+ */
+ struct st_table_list *next_local;
+ /* link in a global list of all queries tables */
+ struct st_table_list *next_global, **prev_global;
+ char *db, *alias, *table_name, *schema_table_name;
+ char *option; /* Used by cache index */
Item *on_expr; /* Used with outer join */
- struct st_table_list *natural_join; /* natural join on this table*/
- /* ... join ... USE INDEX ... IGNORE INDEX */
- List<String> *use_index, *ignore_index;
- TABLE *table; /* opened table */
- st_table_list *table_list; /* pointer to node of list of all tables */
- class st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
- GRANT_INFO grant;
+ /*
+ The structure of ON expression presented in the member above
+ can be changed during certain optimizations. This member
+ contains a snapshot of AND-OR structure of the ON expression
+ made after permanent transformations of the parse tree, and is
+ used to restore ON clause before every reexecution of a prepared
+ statement or stored procedure.
+ */
+ Item *prep_on_expr;
+ COND_EQUAL *cond_equal; /* Used with outer join */
+ /*
+ During parsing - left operand of NATURAL/USING join where 'this' is
+ the right operand. After parsing (this->natural_join == this) iff
+ 'this' represents a NATURAL or USING join operation. Thus after
+ parsing 'this' is a NATURAL/USING join iff (natural_join != NULL).
+ */
+ struct st_table_list *natural_join;
+ /*
+ True if 'this' represents a nested join that is a NATURAL JOIN.
+ For one of the operands of 'this', the member 'natural_join' points
+ to the other operand of 'this'.
+ */
+ bool is_natural_join;
+ /* Field names in a USING clause for JOIN ... USING. */
+ List<String> *join_using_fields;
+ /*
+ Explicitly store the result columns of either a NATURAL/USING join or
+ an operand of such a join.
+ */
+ List<Natural_join_column> *join_columns;
+ /* TRUE if join_columns contains all columns of this table reference. */
+ bool is_join_columns_complete;
+
+ /*
+ List of nodes in a nested join tree, that should be considered as
+ leaves with respect to name resolution. The leaves are: views,
+ top-most nodes representing NATURAL/USING joins, subqueries, and
+ base tables. All of these TABLE_LIST instances contain a
+ materialized list of columns. The list is local to a subquery.
+ */
+ struct st_table_list *next_name_resolution_table;
+ /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
+ List<String> *use_index, *ignore_index;
+ TABLE *table; /* opened table */
+ /*
+ select_result for derived table to pass it from table creation to table
+ filling procedure
+ */
+ select_union *derived_result;
+ /*
+ Reference from aux_tables to local list entry of main select of
+ multi-delete statement:
+ delete t1 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+ here it will be reference of first occurrence of t1 to second (as you
+ can see this lists can't be merged)
+ */
+ st_table_list *correspondent_table;
+ st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
+ ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
+ st_select_lex *schema_select_lex;
+ /*
+ True when the view field translation table is used to convert
+ schema table fields for backwards compatibility with SHOW command.
+ */
+ bool schema_table_reformed;
+ TMP_TABLE_PARAM *schema_table_param;
+ /* link to select_lex where this table was used */
+ st_select_lex *select_lex;
+ st_lex *view; /* link on VIEW lex for merging */
+ Field_translator *field_translation; /* array of VIEW fields */
+ /* pointer to element after last one in translation table above */
+ Field_translator *field_translation_end;
+ /* list of ancestor(s) of this table (underlying table(s)/view(s) */
+ st_table_list *ancestor;
+ /* most upper view this table belongs to */
+ st_table_list *belong_to_view;
+ /*
+ List of all base tables local to a subquery including all view
+ tables. Unlike 'next_local', this in this list views are *not*
+ leaves. Created in setup_tables() -> make_leaves_list().
+ */
+ st_table_list *next_leaf;
+ Item *where; /* VIEW WHERE clause condition */
+ Item *check_option; /* WITH CHECK OPTION condition */
+ LEX_STRING query; /* text of (CRETE/SELECT) statement */
+ LEX_STRING md5; /* md5 of query text */
+ LEX_STRING source; /* source of CREATE VIEW */
+ LEX_STRING view_db; /* saved view database */
+ LEX_STRING view_name; /* saved view name */
+ LEX_STRING timestamp; /* GMT time stamp of last operation */
+ st_lex_user definer; /* definer of view */
+ ulonglong file_version; /* version of file's field set */
+ ulonglong updatable_view; /* VIEW can be updated */
+ ulonglong revision; /* revision control number */
+ ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */
+ ulonglong view_suid; /* view is suid (TRUE dy default) */
+ ulonglong with_check; /* WITH CHECK OPTION */
+ /*
+ effective value of WITH CHECK OPTION (differ for temporary table
+ algorithm)
+ */
+ uint8 effective_with_check;
+ uint8 effective_algorithm; /* which algorithm was really used */
+ GRANT_INFO grant;
+ /* data need by some engines in query cache*/
+ ulonglong engine_data;
+ /* call back function for asking handler about caching in query cache */
+ qc_engine_callback callback_func;
thr_lock_type lock_type;
uint outer_join; /* Which join type */
uint shared; /* Used in multi-upd */
- uint32 db_length, real_name_length;
+ uint32 db_length, table_name_length;
+ bool updatable; /* VIEW/TABLE can be updated now */
bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */
- bool force_index; /* Prefer index over table scan */
- bool ignore_leaves; /* Preload only non-leaf nodes */
+ bool force_index; /* prefer index over table scan */
+ bool ignore_leaves; /* preload only non-leaf nodes */
+ table_map dep_tables; /* tables the table depends on */
+ table_map on_expr_dep_tables; /* tables on expression depends on */
+ struct st_nested_join *nested_join; /* if the element is a nested join */
+ st_table_list *embedding; /* nested join containing the table */
+ List<struct st_table_list> *join_list;/* join list the table belongs to */
bool cacheable_table; /* stop PS caching */
- /* used in multi-upd privelege check */
- bool table_in_update_from_clause;
+ /* used in multi-upd/views privilege check */
+ bool table_in_first_from_clause;
+ bool skip_temporary; /* this table shouldn't be temporary */
+ /* TRUE if this merged view contain auto_increment field */
+ bool contain_auto_increment;
+ bool multitable_view; /* TRUE iff this is multitable view */
+ bool compact_view_format; /* Use compact format for SHOW CREATE VIEW */
+ /* view where processed */
+ bool where_processed;
+ /* db part was not defined in table definition */
+ bool current_db_used;
+ /* FRMTYPE_ERROR if any type is acceptable */
+ enum frm_type_enum required_type;
+ char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
+ /*
+ This TABLE_LIST object is just placeholder for prelocking, it will be
+ used for implicit LOCK TABLES only and won't be used in real statement.
+ */
+ bool prelocking_placeholder;
+
+ void calc_md5(char *buffer);
+ void set_ancestor();
+ int view_check_option(THD *thd, bool ignore_failure);
+ bool setup_ancestor(THD *thd);
+ void cleanup_items();
+ bool placeholder() {return derived || view; }
+ void print(THD *thd, String *str);
+ bool check_single_table(st_table_list **table, table_map map,
+ st_table_list *view);
+ bool set_insert_values(MEM_ROOT *mem_root);
+ void hide_view_error(THD *thd);
+ st_table_list *find_underlying_table(TABLE *table);
+ st_table_list *first_leaf_for_name_resolution();
+ st_table_list *last_leaf_for_name_resolution();
+ bool is_leaf_for_name_resolution();
+ inline st_table_list *top_table()
+ { return belong_to_view ? belong_to_view : this; }
+ inline bool prepare_check_option(THD *thd)
+ {
+ bool res= FALSE;
+ if (effective_with_check)
+ res= prep_check_option(thd, effective_with_check);
+ return res;
+ }
+ inline bool prepare_where(THD *thd, Item **conds,
+ bool no_where_clause)
+ {
+ if (effective_algorithm == VIEW_ALGORITHM_MERGE)
+ return prep_where(thd, conds, no_where_clause);
+ return FALSE;
+ }
+private:
+ bool prep_check_option(THD *thd, uint8 check_opt_type);
+ bool prep_where(THD *thd, Item **conds, bool no_where_clause);
} TABLE_LIST;
+class Item;
+
+/*
+ Iterator over the fields of a generic table reference.
+*/
+
+class Field_iterator: public Sql_alloc
+{
+public:
+ virtual ~Field_iterator() {}
+ virtual void set(TABLE_LIST *)= 0;
+ virtual void next()= 0;
+ virtual bool end_of_fields()= 0; /* Return 1 at end of list */
+ virtual const char *name()= 0;
+ virtual Item *create_item(THD *)= 0;
+ virtual Field *field()= 0;
+};
+
+
+/*
+ Iterator over the fields of a base table, view with temporary
+ table, or subquery.
+*/
+
+class Field_iterator_table: public Field_iterator
+{
+ Field **ptr;
+public:
+ Field_iterator_table() :ptr(0) {}
+ void set(TABLE_LIST *table) { ptr= table->table->field; }
+ void set_table(TABLE *table) { ptr= table->field; }
+ void next() { ptr++; }
+ bool end_of_fields() { return *ptr == 0; }
+ const char *name();
+ Item *create_item(THD *thd);
+ Field *field() { return *ptr; }
+};
+
+
+/* Iterator over the fields of a merge view. */
+
+class Field_iterator_view: public Field_iterator
+{
+ Field_translator *ptr, *array_end;
+ TABLE_LIST *view;
+public:
+ Field_iterator_view() :ptr(0), array_end(0) {}
+ void set(TABLE_LIST *table);
+ void next() { ptr++; }
+ bool end_of_fields() { return ptr == array_end; }
+ const char *name();
+ Item *create_item(THD *thd);
+ Item **item_ptr() {return &ptr->item; }
+ Field *field() { return 0; }
+ inline Item *item() { return ptr->item; }
+ Field_translator *field_translator() { return ptr; }
+};
+
+
+/*
+ Field_iterator interface to the list of materialized fields of a
+ NATURAL/USING join.
+*/
+
+class Field_iterator_natural_join: public Field_iterator
+{
+ List_iterator_fast<Natural_join_column> *column_ref_it;
+ Natural_join_column *cur_column_ref;
+public:
+ Field_iterator_natural_join() :column_ref_it(NULL), cur_column_ref(NULL) {}
+ ~Field_iterator_natural_join() { delete column_ref_it; }
+ void set(TABLE_LIST *table);
+ void next();
+ bool end_of_fields() { return !cur_column_ref; }
+ const char *name() { return cur_column_ref->name(); }
+ Item *create_item(THD *thd) { return cur_column_ref->create_item(thd); }
+ Field *field() { return cur_column_ref->field(); }
+ Natural_join_column *column_ref() { return cur_column_ref; }
+};
+
+
+/*
+ Generic iterator over the fields of an arbitrary table reference.
+
+ DESCRIPTION
+ This class unifies the various ways of iterating over the columns
+ of a table reference depending on the type of SQL entity it
+ represents. If such an entity represents a nested table reference,
+ this iterator encapsulates the iteration over the columns of the
+ members of the table reference.
+
+ IMPLEMENTATION
+ The implementation assumes that all underlying NATURAL/USING table
+ references already contain their result columns and are linked into
+ the list TABLE_LIST::next_name_resolution_table.
+*/
+
+class Field_iterator_table_ref: public Field_iterator
+{
+ TABLE_LIST *table_ref, *first_leaf, *last_leaf;
+ Field_iterator_table table_field_it;
+ Field_iterator_view view_field_it;
+ Field_iterator_natural_join natural_join_it;
+ Field_iterator *field_it;
+ void set_field_iterator();
+public:
+ Field_iterator_table_ref() :field_it(NULL) {}
+ void set(TABLE_LIST *table);
+ void next();
+ bool end_of_fields()
+ { return (table_ref == last_leaf && field_it->end_of_fields()); }
+ const char *name() { return field_it->name(); }
+ const char *table_name();
+ const char *db_name();
+ GRANT_INFO *grant();
+ Item *create_item(THD *thd) { return field_it->create_item(thd); }
+ Field *field() { return field_it->field(); }
+ Natural_join_column *get_or_create_column_ref(THD *thd, bool *is_created);
+};
+
+
+typedef struct st_nested_join
+{
+ List<TABLE_LIST> join_list; /* list of elements in the nested join */
+ table_map used_tables; /* bitmap of tables in the nested join */
+ table_map not_null_tables; /* tables that rejects nulls */
+ struct st_join_table *first_nested;/* the first nested table in the plan */
+ uint counter; /* to count tables in the nested join */
+} NESTED_JOIN;
+
+
typedef struct st_changed_table_list
{
struct st_changed_table_list *next;
@@ -244,8 +767,8 @@ typedef struct st_changed_table_list
uint32 key_length;
} CHANGED_TABLE_LIST;
-typedef struct st_open_table_list
-{
+
+typedef struct st_open_table_list{
struct st_open_table_list *next;
char *db,*table;
uint32 in_use,locked;
diff --git a/sql/time.cc b/sql/time.cc
index e76b169b336..5069031081d 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -33,15 +33,6 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week)
DBUG_RETURN ((int) ((daynr + 5L + (sunday_first_day_of_week ? 1L : 0L)) % 7));
}
- /* Calc days in one year. works with 0 <= year <= 99 */
-
-uint calc_days_in_year(uint year)
-{
- return (year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ?
- 366 : 365;
-}
-
-
/*
The bits in week_format has the following meaning:
WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
@@ -195,14 +186,22 @@ ulong convert_month_to_period(ulong month)
NOTE
See description of str_to_datetime() for more information.
*/
+
timestamp_type
str_to_datetime_with_warn(const char *str, uint length, TIME *l_time,
uint flags)
{
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);
+ THD *thd= current_thd;
+ timestamp_type ts_type;
+
+ ts_type= str_to_datetime(str, length, l_time,
+ (flags | (thd->variables.sql_mode &
+ (MODE_INVALID_DATES |
+ MODE_NO_ZERO_DATE))),
+ &was_cut);
+ if (was_cut || ts_type <= MYSQL_TIMESTAMP_ERROR)
+ make_truncated_value_warning(current_thd, str, length, ts_type, NullS);
return ts_type;
}
@@ -224,7 +223,7 @@ str_to_datetime_with_warn(const char *str, uint length, TIME *l_time,
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 TIME_to_timestamp(THD *thd, const TIME *t, my_bool *in_dst_time_gap)
{
my_time_t timestamp;
@@ -258,101 +257,13 @@ str_to_time_with_warn(const char *str, uint length, TIME *l_time)
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);
+ make_truncated_value_warning(current_thd, str, length,
+ MYSQL_TIMESTAMP_TIME, NullS);
return ret_val;
}
/*
- Convert datetime value specified as number to broken-down TIME
- representation and form value of DATETIME type as side-effect.
-
- SYNOPSIS
- 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.
-*/
-
-longlong number_to_TIME(longlong nr, TIME *time_res, bool fuzzy_date,
- int *was_cut)
-{
- long part1,part2;
-
- *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)
- {
- 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 &&
- (fuzzy_date || (time_res->month != 0 && time_res->day != 0) || nr==0))
- return nr;
-
- err:
-
- *was_cut= 1;
- return LL(0);
-}
-
-
-/*
Convert a system time structure to TIME
*/
@@ -772,16 +683,15 @@ void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
void make_truncated_value_warning(THD *thd, const char *str_val,
- uint str_length, timestamp_type time_type)
+ uint str_length, timestamp_type time_type,
+ const char *field_name)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
const char *type_str;
-
+ CHARSET_INFO *cs= &my_charset_latin1;
char buff[128];
String str(buff,(uint32) sizeof(buff), system_charset_info);
- str.length(0);
- str.append(str_val, str_length);
- str.append('\0');
+ str.copy(str_val, str_length, system_charset_info);
switch (time_type) {
case MYSQL_TIMESTAMP_DATE:
@@ -795,84 +705,18 @@ void make_truncated_value_warning(THD *thd, const char *str_val,
type_str= "datetime";
break;
}
- sprintf(warn_buff, ER(ER_TRUNCATED_WRONG_VALUE),
- type_str, str.ptr());
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE, warn_buff);
-}
-
-
-/* Convert time value to integer in YYYYMMDDHHMMSS format */
-
-ulonglong TIME_to_ulonglong_datetime(const TIME *time)
-{
- return ((ulonglong) (time->year * 10000UL +
- time->month * 100UL +
- time->day) * ULL(1000000) +
- (ulonglong) (time->hour * 10000UL +
- time->minute * 100UL +
- time->second));
-}
-
-
-/* Convert TIME value to integer in YYYYMMDD format */
-
-ulonglong TIME_to_ulonglong_date(const TIME *time)
-{
- return (ulonglong) (time->year * 10000UL + time->month * 100UL + time->day);
-}
-
-
-/*
- Convert TIME value to integer in HHMMSS format.
- This function doesn't take into account time->day member:
- it's assumed that days have been converted to hours already.
-*/
-
-ulonglong TIME_to_ulonglong_time(const TIME *time)
-{
- return (ulonglong) (time->hour * 10000UL +
- time->minute * 100UL +
- time->second);
+ if (field_name)
+ cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
+ ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
+ type_str, str.c_ptr(), field_name,
+ (ulong) thd->row_count);
+ else
+ cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
+ ER(ER_TRUNCATED_WRONG_VALUE),
+ type_str, str.c_ptr());
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE, warn_buff);
}
-/*
- Convert struct TIME (date and time split into year/month/day/hour/...
- to a number in format YYYYMMDDHHMMSS (DATETIME),
- YYYYMMDD (DATE) or HHMMSS (TIME).
-
- SYNOPSIS
- TIME_to_ulonglong()
-
- DESCRIPTION
- The function is used when we need to convert value of time item
- to a number if it's used in numeric context, i. e.:
- SELECT NOW()+1, CURDATE()+0, CURTIMIE()+0;
- SELECT ?+1;
-
- NOTE
- This function doesn't check that given TIME structure members are
- in valid range. If they are not, return value won't reflect any
- valid date either.
-*/
-
-ulonglong TIME_to_ulonglong(const TIME *time)
-{
- switch (time->time_type) {
- case MYSQL_TIMESTAMP_DATETIME:
- return TIME_to_ulonglong_datetime(time);
- case MYSQL_TIMESTAMP_DATE:
- return TIME_to_ulonglong_date(time);
- case MYSQL_TIMESTAMP_TIME:
- return TIME_to_ulonglong_time(time);
- case MYSQL_TIMESTAMP_NONE:
- case MYSQL_TIMESTAMP_ERROR:
- return ULL(0);
- default:
- DBUG_ASSERT(0);
- }
- return 0;
-}
-
#endif
diff --git a/sql/tztime.cc b/sql/tztime.cc
index b5ebc9f350a..537050e94db 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -880,12 +880,12 @@ sec_since_epoch(int year, int mon, int mday, int hour, int min ,int sec)
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)
+TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp,
+ my_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 */
@@ -962,7 +962,7 @@ 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;
+ my_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;
};
@@ -994,7 +994,7 @@ public:
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
+Time_zone_system::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const
{
long not_used;
return my_system_gmt_sec(t, &not_used, in_dst_time_gap);
@@ -1055,7 +1055,7 @@ 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;
+ my_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;
};
@@ -1081,7 +1081,7 @@ public:
0
*/
my_time_t
-Time_zone_utc::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const
+Time_zone_utc::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const
{
/* Should be never called */
DBUG_ASSERT(0);
@@ -1144,7 +1144,7 @@ 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;
+ my_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:
@@ -1193,7 +1193,7 @@ Time_zone_db::Time_zone_db(TIME_ZONE_INFO *tz_info_arg,
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
+Time_zone_db::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const
{
return ::TIME_to_gmt_sec(t, tz_info, in_dst_time_gap);
}
@@ -1240,7 +1240,7 @@ 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;
+ my_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;
/*
@@ -1292,7 +1292,7 @@ Time_zone_offset::Time_zone_offset(long tz_offset_arg):
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
+Time_zone_offset::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const
{
return sec_since_epoch(t->year, t->month, t->day,
t->hour, t->minute, t->second) -
@@ -1396,44 +1396,72 @@ extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length,
/*
- Prepare table list with time zone related tables from preallocated array.
+ Prepare table list with time zone related tables from preallocated array
+ and add to global table list.
SYNOPSIS
tz_init_table_list()
- tz_tabs - pointer to preallocated array of 4 TABLE_LIST objects.
+ tz_tabs - pointer to preallocated array of 4 TABLE_LIST objects
+ global_next_ptr - pointer to variable which points to global_next member
+ of last element of global table list (or list root
+ then list is empty) (in/out).
DESCRIPTION
This function prepares list of TABLE_LIST objects which can be used
- for opening of time zone tables from preallocated array.
+ for opening of time zone tables from preallocated array. It also links
+ this list to the end of global table list (it will read and update
+ accordingly variable pointed by global_next_ptr for this).
*/
-void
-tz_init_table_list(TABLE_LIST *tz_tabs)
+static void
+tz_init_table_list(TABLE_LIST *tz_tabs, TABLE_LIST ***global_next_ptr)
{
bzero(tz_tabs, sizeof(TABLE_LIST) * 4);
- tz_tabs[0].alias= tz_tabs[0].real_name= (char*)"time_zone_name";
- tz_tabs[1].alias= tz_tabs[1].real_name= (char*)"time_zone";
- tz_tabs[2].alias= tz_tabs[2].real_name= (char*)"time_zone_transition_type";
- tz_tabs[3].alias= tz_tabs[3].real_name= (char*)"time_zone_transition";
- tz_tabs[0].next= tz_tabs+1;
- tz_tabs[1].next= tz_tabs+2;
- tz_tabs[2].next= tz_tabs+3;
+ tz_tabs[0].alias= tz_tabs[0].table_name= (char*)"time_zone_name";
+ tz_tabs[1].alias= tz_tabs[1].table_name= (char*)"time_zone";
+ tz_tabs[2].alias= tz_tabs[2].table_name= (char*)"time_zone_transition_type";
+ tz_tabs[3].alias= tz_tabs[3].table_name= (char*)"time_zone_transition";
+ tz_tabs[0].next_global= tz_tabs[0].next_local= tz_tabs+1;
+ tz_tabs[1].next_global= tz_tabs[1].next_local= tz_tabs+2;
+ tz_tabs[2].next_global= tz_tabs[2].next_local= tz_tabs+3;
tz_tabs[0].lock_type= tz_tabs[1].lock_type= tz_tabs[2].lock_type=
tz_tabs[3].lock_type= TL_READ;
tz_tabs[0].db= tz_tabs[1].db= tz_tabs[2].db= tz_tabs[3].db= (char *)"mysql";
+
+ /* Link into global list */
+ tz_tabs[0].prev_global= *global_next_ptr;
+ tz_tabs[1].prev_global= &tz_tabs[0].next_global;
+ tz_tabs[2].prev_global= &tz_tabs[1].next_global;
+ tz_tabs[3].prev_global= &tz_tabs[2].next_global;
+
+ **global_next_ptr= tz_tabs;
+ /* Update last-global-pointer to point to pointer in last table */
+ *global_next_ptr= &tz_tabs[3].next_global;
}
/*
- Create table list with time zone related tables.
+ Fake table list object, pointer to which is returned by
+ my_tz_get_tables_list() as indication of error.
+*/
+TABLE_LIST fake_time_zone_tables_list;
+
+/*
+ Create table list with time zone related tables and add it to the end
+ of global table list.
SYNOPSIS
my_tz_get_table_list()
- thd - current thread object
+ thd - current thread object
+ global_next_ptr - pointer to variable which points to global_next member
+ of last element of global table list (or list root
+ then list is empty) (in/out).
DESCRIPTION
This function creates list of TABLE_LIST objects allocated in thd's
- memroot, which can be used for opening of time zone tables.
+ memroot, which can be used for opening of time zone tables. It will also
+ link this list to the end of global table list (it will read and update
+ accordingly variable pointed by global_next_ptr for this).
NOTE
my_tz_check_n_skip_implicit_tables() function depends on fact that
@@ -1445,19 +1473,20 @@ tz_init_table_list(TABLE_LIST *tz_tabs)
*/
TABLE_LIST *
-my_tz_get_table_list(THD *thd)
+my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr)
{
TABLE_LIST *tz_tabs;
+ DBUG_ENTER("my_tz_get_table_list");
if (!time_zone_tables_exist)
- return 0;
+ DBUG_RETURN(0);
if (!(tz_tabs= (TABLE_LIST *)thd->alloc(sizeof(TABLE_LIST) * 4)))
- return &fake_time_zone_tables_list;
+ DBUG_RETURN(&fake_time_zone_tables_list);
- tz_init_table_list(tz_tabs);
+ tz_init_table_list(tz_tabs, global_next_ptr);
- return tz_tabs;
+ DBUG_RETURN(tz_tabs);
}
@@ -1491,12 +1520,11 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
{
THD *thd;
TABLE_LIST *tables= 0;
- TABLE_LIST tables_buff[5];
+ TABLE_LIST tables_buff[5], **last_global_next_ptr;
TABLE *table;
TZ_NAMES_ENTRY *tmp_tzname;
my_bool return_val= 1;
int res;
- uint counter;
DBUG_ENTER("my_tz_init");
/*
@@ -1554,16 +1582,18 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
thd->db= my_strdup("mysql",MYF(0));
thd->db_length= 5; // Safety
bzero((char*) &tables_buff, sizeof(TABLE_LIST));
- tables_buff[0].alias= tables_buff[0].real_name=
+ tables_buff[0].alias= tables_buff[0].table_name=
(char*)"time_zone_leap_second";
tables_buff[0].lock_type= TL_READ;
tables_buff[0].db= thd->db;
- tables_buff[0].next= tables_buff + 1;
- /* Fill TABLE_LIST for rest of the time zone describing tables */
- tz_init_table_list(tables_buff + 1);
+ /*
+ Fill TABLE_LIST for the rest of the time zone describing tables
+ and link it to first one.
+ */
+ last_global_next_ptr= &(tables_buff[0].next_global);
+ tz_init_table_list(tables_buff + 1, &last_global_next_ptr);
- if (open_tables(thd, tables_buff, &counter) ||
- lock_tables(thd, tables_buff, counter))
+ if (simple_open_n_lock_tables(thd, tables_buff))
{
sql_print_warning("Can't open and lock time zone table: %s "
"trying to live without them", thd->net.last_error);
@@ -1762,8 +1792,9 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
and it is specifically for this purpose).
*/
table= tz_tables->table;
- tz_tables= tz_tables->next;
- table->field[0]->store(tz_name->ptr(), tz_name->length(), &my_charset_latin1);
+ tz_tables= tz_tables->next_local;
+ table->field[0]->store(tz_name->ptr(), tz_name->length(),
+ &my_charset_latin1);
/*
It is OK to ignore ha_index_init()/ha_index_end() return values since
mysql.time_zone* tables are MyISAM and these operations always succeed
@@ -1794,8 +1825,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
using the only index in this table).
*/
table= tz_tables->table;
- tz_tables= tz_tables->next;
- table->field[0]->store((longlong)tzid);
+ tz_tables= tz_tables->next_local;
+ table->field[0]->store((longlong) tzid, TRUE);
(void)table->file->ha_index_init(0);
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
@@ -1821,8 +1852,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
Right - using special index.
*/
table= tz_tables->table;
- tz_tables= tz_tables->next;
- table->field[0]->store((longlong)tzid);
+ tz_tables= tz_tables->next_local;
+ table->field[0]->store((longlong) tzid, TRUE);
(void)table->file->ha_index_init(0);
// FIXME Is there any better approach than explicitly specifying 4 ???
@@ -1894,7 +1925,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
in ascending order by index scan also satisfies us.
*/
table= tz_tables->table;
- table->field[0]->store((longlong)tzid);
+ table->field[0]->store((longlong) tzid, TRUE);
(void)table->file->ha_index_init(0);
// FIXME Is there any better approach than explicitly specifying 4 ???
@@ -2148,7 +2179,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
DBUG_PRINT("enter", ("time zone name='%s'",
name ? ((String *)name)->c_ptr() : "NULL"));
- DBUG_ASSERT(!time_zone_tables_exist || tz_tables);
+ DBUG_ASSERT(!time_zone_tables_exist || tz_tables || current_thd->slave_thread);
if (!name)
DBUG_RETURN(0);
@@ -2180,7 +2211,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
(const byte *)name->ptr(),
name->length())))
result_tz= tmp_tzname->tz;
- else if (time_zone_tables_exist)
+ else if (time_zone_tables_exist && tz_tables)
result_tz= tz_load_from_open_tables(name, tz_tables);
}
@@ -2189,6 +2220,58 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
DBUG_RETURN(result_tz);
}
+
+/*
+ A more standalone version of my_tz_find(): will open tz tables if needed.
+ This is so far only used by replication, where time zone setting does not
+ happen in the usual query context.
+
+ SYNOPSIS
+ my_tz_find_with_opening_tz_tables()
+ thd - pointer to thread's THD structure
+ name - time zone specification
+
+ DESCRIPTION
+ This function tries to find a time zone which matches the named passed in
+ argument. If it fails, it will open time zone tables and re-try the
+ search.
+ This function is needed for the slave SQL thread, which does not do the
+ addition of time zone tables which is usually done during query parsing
+ (as time zone setting by slave does not happen in mysql_parse() but
+ before). So it needs to open tz tables by itself if needed.
+ See notes of my_tz_find() as they also apply here.
+
+ RETURN VALUE
+ Pointer to corresponding Time_zone object. 0 - in case of bad time zone
+ specification or other error.
+
+*/
+Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name)
+{
+ Time_zone *tz;
+ DBUG_ENTER("my_tz_find_with_opening_tables");
+ DBUG_ASSERT(thd);
+ DBUG_ASSERT(thd->slave_thread); // intended for use with slave thread only
+ if (!(tz= my_tz_find(name, 0)) && time_zone_tables_exist)
+ {
+ /*
+ Probably we have not loaded this time zone yet so let us look it up in
+ our time zone tables. Note that if we don't have tz tables on this
+ slave, we don't even try.
+ */
+ TABLE_LIST tables[4];
+ TABLE_LIST *dummy;
+ TABLE_LIST **dummyp= &dummy;
+ tz_init_table_list(tables, &dummyp);
+ if (simple_open_n_lock_tables(thd, tables))
+ DBUG_RETURN(0);
+ tz= my_tz_find(name, tables);
+ /* We need to close tables _now_ to not pollute coming query */
+ close_thread_tables(thd);
+ }
+ DBUG_RETURN(tz);
+}
+
#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
@@ -2466,8 +2549,6 @@ main(int argc, char **argv)
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]);
@@ -2577,14 +2658,21 @@ main(int argc, char **argv)
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)
{
+ long not_used;
+ my_bool not_used_2;
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)
@@ -2616,6 +2704,11 @@ main(int argc, char **argv)
return 1;
}
}
+ }
+ }
+ }
+ }
+ }
printf("TIME_to_gmt_sec = my_system_gmt_sec for test range\n");
diff --git a/sql/tztime.h b/sql/tztime.h
index e1ff71b6703..a168fe4fb73 100644
--- a/sql/tztime.h
+++ b/sql/tztime.h
@@ -37,7 +37,7 @@ public:
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;
+ my_bool *in_dst_time_gap) const = 0;
/*
Converts time in my_time_t representation to local time in
broken down TIME representation.
@@ -59,11 +59,13 @@ public:
extern Time_zone * my_tz_UTC;
extern Time_zone * my_tz_SYSTEM;
-extern TABLE_LIST * my_tz_get_table_list(THD *thd);
+extern TABLE_LIST * my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr);
extern Time_zone * my_tz_find(const String *name, TABLE_LIST *tz_tables);
+extern Time_zone * my_tz_find_with_opening_tz_tables(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();
+extern TABLE_LIST fake_time_zone_tables_list;
/*
Check if we have pointer to the begining of list of implicitly used time
@@ -95,10 +97,4 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table,
return FALSE;
}
-/*
- 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/udf_example.cc b/sql/udf_example.cc
index 50de0f187fe..a186b4fbf6c 100644
--- a/sql/udf_example.cc
+++ b/sql/udf_example.cc
@@ -56,7 +56,9 @@
**
** Function 'myfunc_int' returns summary length of all its arguments.
**
-** Function 'sequence' returns an sequence starting from a certain number
+** Function 'sequence' returns an sequence starting from a certain number.
+**
+** Function 'myfunc_argument_name' returns name of argument.
**
** On the end is a couple of functions that converts hostnames to ip and
** vice versa.
@@ -82,6 +84,7 @@
** CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
** CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
** CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so";
+** CREATE FUNCTION myfunc_argument_name RETURNS STRING SONAME "udf_example.so";
**
** After this the functions will work exactly like native MySQL functions.
** Functions should be created only once.
@@ -94,6 +97,7 @@
** DROP FUNCTION lookup;
** DROP FUNCTION reverse_lookup;
** DROP FUNCTION avgcost;
+** DROP FUNCTION myfunc_argument_name;
**
** The CREATE FUNCTION and DROP FUNCTION update the func@mysql table. All
** Active function will be reloaded on every restart of server
@@ -987,4 +991,43 @@ avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error )
return data->totalprice/double(data->totalquantity);
}
+extern "C" {
+my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args,
+ char *message);
+char *myfunc_argument_name(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *length, char *null_value,
+ char *error);
+}
+
+my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args,
+ char *message)
+{
+ if (args->arg_count != 1)
+ {
+ strmov(message,"myfunc_argument_name_init accepts only one argument");
+ return 1;
+ }
+ initid->max_length= args->attribute_lengths[0];
+ initid->maybe_null= 1;
+ initid->const_item= 1;
+ return 0;
+}
+
+char *myfunc_argument_name(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *length, char *null_value,
+ char *error)
+{
+ if (!args->attributes[0])
+ {
+ null_value= 0;
+ return 0;
+ }
+ (*length)--; // space for ending \0 (for debugging purposes)
+ if (*length > args->attribute_lengths[0])
+ *length= args->attribute_lengths[0];
+ memcpy(result, args->attributes[0], *length);
+ result[*length]= 0;
+ return result;
+}
+
#endif /* HAVE_DLOPEN */
diff --git a/sql/uniques.cc b/sql/uniques.cc
index d060965aa66..367aed2d113 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -63,12 +63,255 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
comp_func_fixed_arg);
/* If the following fail's the next add will also fail */
my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16);
+ /*
+ If you change the following, change it in get_max_elements function, too.
+ */
max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size);
open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE,
MYF(MY_WME));
}
+/*
+ Calculate log2(n!)
+
+ NOTES
+ Stirling's approximate formula is used:
+
+ n! ~= sqrt(2*M_PI*n) * (n/M_E)^n
+
+ Derivation of formula used for calculations is as follows:
+
+ log2(n!) = log(n!)/log(2) = log(sqrt(2*M_PI*n)*(n/M_E)^n) / log(2) =
+
+ = (log(2*M_PI*n)/2 + n*log(n/M_E)) / log(2).
+*/
+
+inline double log2_n_fact(double x)
+{
+ return (log(2*M_PI*x)/2 + x*log(x/M_E)) / M_LN2;
+}
+
+
+/*
+ Calculate cost of merge_buffers function call for given sequence of
+ input stream lengths and store the number of rows in result stream in *last.
+
+ SYNOPSIS
+ get_merge_buffers_cost()
+ buff_elems Array of #s of elements in buffers
+ elem_size Size of element stored in buffer
+ first Pointer to first merged element size
+ last Pointer to last merged element size
+
+ RETURN
+ Cost of merge_buffers operation in disk seeks.
+
+ NOTES
+ It is assumed that no rows are eliminated during merge.
+ The cost is calculated as
+
+ cost(read_and_write) + cost(merge_comparisons).
+
+ All bytes in the sequences is read and written back during merge so cost
+ of disk io is 2*elem_size*total_buf_elems/IO_SIZE (2 is for read + write)
+
+ For comparisons cost calculations we assume that all merged sequences have
+ the same length, so each of total_buf_size elements will be added to a sort
+ heap with (n_buffers-1) elements. This gives the comparison cost:
+
+ total_buf_elems* log2(n_buffers) / TIME_FOR_COMPARE_ROWID;
+*/
+
+static double get_merge_buffers_cost(uint *buff_elems, uint elem_size,
+ uint *first, uint *last)
+{
+ uint total_buf_elems= 0;
+ for (uint *pbuf= first; pbuf <= last; pbuf++)
+ total_buf_elems+= *pbuf;
+ *last= total_buf_elems;
+
+ int n_buffers= last - first + 1;
+
+ /* Using log2(n)=log(n)/log(2) formula */
+ return 2*((double)total_buf_elems*elem_size) / IO_SIZE +
+ total_buf_elems*log((double) n_buffers) / (TIME_FOR_COMPARE_ROWID * M_LN2);
+}
+
+
+/*
+ Calculate cost of merging buffers into one in Unique::get, i.e. calculate
+ how long (in terms of disk seeks) the two calls
+ merge_many_buffs(...);
+ merge_buffers(...);
+ will take.
+
+ SYNOPSIS
+ get_merge_many_buffs_cost()
+ buffer buffer space for temporary data, at least
+ Unique::get_cost_calc_buff_size bytes
+ maxbuffer # of full buffers
+ max_n_elems # of elements in first maxbuffer buffers
+ last_n_elems # of elements in last buffer
+ elem_size size of buffer element
+
+ NOTES
+ maxbuffer+1 buffers are merged, where first maxbuffer buffers contain
+ max_n_elems elements each and last buffer contains last_n_elems elements.
+
+ The current implementation does a dumb simulation of merge_many_buffs
+ function actions.
+
+ RETURN
+ Cost of merge in disk seeks.
+*/
+
+static double get_merge_many_buffs_cost(uint *buffer,
+ uint maxbuffer, uint max_n_elems,
+ uint last_n_elems, int elem_size)
+{
+ register int i;
+ double total_cost= 0.0;
+ uint *buff_elems= buffer; /* #s of elements in each of merged sequences */
+
+ /*
+ Set initial state: first maxbuffer sequences contain max_n_elems elements
+ each, last sequence contains last_n_elems elements.
+ */
+ for (i = 0; i < (int)maxbuffer; i++)
+ buff_elems[i]= max_n_elems;
+ buff_elems[maxbuffer]= last_n_elems;
+
+ /*
+ Do it exactly as merge_many_buff function does, calling
+ get_merge_buffers_cost to get cost of merge_buffers.
+ */
+ if (maxbuffer >= MERGEBUFF2)
+ {
+ while (maxbuffer >= MERGEBUFF2)
+ {
+ uint lastbuff= 0;
+ for (i = 0; i <= (int) maxbuffer - MERGEBUFF*3/2; i += MERGEBUFF)
+ {
+ total_cost+=get_merge_buffers_cost(buff_elems, elem_size,
+ buff_elems + i,
+ buff_elems + i + MERGEBUFF-1);
+ lastbuff++;
+ }
+ total_cost+=get_merge_buffers_cost(buff_elems, elem_size,
+ buff_elems + i,
+ buff_elems + maxbuffer);
+ maxbuffer= lastbuff;
+ }
+ }
+
+ /* Simulate final merge_buff call. */
+ total_cost += get_merge_buffers_cost(buff_elems, elem_size,
+ buff_elems, buff_elems + maxbuffer);
+ return total_cost;
+}
+
+
+/*
+ Calculate cost of using Unique for processing nkeys elements of size
+ key_size using max_in_memory_size memory.
+
+ SYNOPSIS
+ Unique::get_use_cost()
+ buffer space for temporary data, use Unique::get_cost_calc_buff_size
+ to get # bytes needed.
+ nkeys #of elements in Unique
+ key_size size of each elements in bytes
+ max_in_memory_size amount of memory Unique will be allowed to use
+
+ RETURN
+ Cost in disk seeks.
+
+ NOTES
+ cost(using_unqiue) =
+ cost(create_trees) + (see #1)
+ cost(merge) + (see #2)
+ cost(read_result) (see #3)
+
+ 1. Cost of trees creation
+ For each Unique::put operation there will be 2*log2(n+1) elements
+ comparisons, where n runs from 1 tree_size (we assume that all added
+ elements are different). Together this gives:
+
+ n_compares = 2*(log2(2) + log2(3) + ... + log2(N+1)) = 2*log2((N+1)!)
+
+ then cost(tree_creation) = n_compares*ROWID_COMPARE_COST;
+
+ Total cost of creating trees:
+ (n_trees - 1)*max_size_tree_cost + non_max_size_tree_cost.
+
+ Approximate value of log2(N!) is calculated by log2_n_fact function.
+
+ 2. Cost of merging.
+ If only one tree is created by Unique no merging will be necessary.
+ Otherwise, we model execution of merge_many_buff function and count
+ #of merges. (The reason behind this is that number of buffers is small,
+ while size of buffers is big and we don't want to loose precision with
+ O(x)-style formula)
+
+ 3. If only one tree is created by Unique no disk io will happen.
+ Otherwise, ceil(key_len*n_keys) disk seeks are necessary. We assume
+ these will be random seeks.
+*/
+
+double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size,
+ ulong max_in_memory_size)
+{
+ ulong max_elements_in_tree;
+ ulong last_tree_elems;
+ int n_full_trees; /* number of trees in unique - 1 */
+ double result;
+
+ max_elements_in_tree=
+ max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size);
+
+ n_full_trees= nkeys / max_elements_in_tree;
+ last_tree_elems= nkeys % max_elements_in_tree;
+
+ /* Calculate cost of creating trees */
+ result= 2*log2_n_fact(last_tree_elems + 1.0);
+ if (n_full_trees)
+ result+= n_full_trees * log2_n_fact(max_elements_in_tree + 1.0);
+ result /= TIME_FOR_COMPARE_ROWID;
+
+ DBUG_PRINT("info",("unique trees sizes: %u=%u*%lu + %lu", nkeys,
+ n_full_trees, n_full_trees?max_elements_in_tree:0,
+ last_tree_elems));
+
+ if (!n_full_trees)
+ return result;
+
+ /*
+ There is more then one tree and merging is necessary.
+ First, add cost of writing all trees to disk, assuming that all disk
+ writes are sequential.
+ */
+ result += DISK_SEEK_BASE_COST * n_full_trees *
+ ceil(((double) key_size)*max_elements_in_tree / IO_SIZE);
+ result += DISK_SEEK_BASE_COST * ceil(((double) key_size)*last_tree_elems / IO_SIZE);
+
+ /* Cost of merge */
+ double merge_cost= get_merge_many_buffs_cost(buffer, n_full_trees,
+ max_elements_in_tree,
+ last_tree_elems, key_size);
+ if (merge_cost < 0.0)
+ return merge_cost;
+
+ result += merge_cost;
+ /*
+ Add cost of reading the resulting sequence, assuming there were no
+ duplicate elements.
+ */
+ result += ceil((double)key_size*nkeys/IO_SIZE);
+
+ return result;
+}
+
Unique::~Unique()
{
close_cached_file(&file);
@@ -84,6 +327,7 @@ bool Unique::flush()
elements+= tree.elements_in_tree;
file_ptr.count=tree.elements_in_tree;
file_ptr.file_pos=my_b_tell(&file);
+
if (tree_walk(&tree, (tree_walk_action) unique_write_to_file,
(void*) this, left_root_right) ||
insert_dynamic(&file_ptrs, (gptr) &file_ptr))
@@ -94,6 +338,237 @@ bool Unique::flush()
/*
+ Clear the tree and the file.
+ You must call reset() if you want to reuse Unique after walk().
+*/
+
+void
+Unique::reset()
+{
+ reset_tree(&tree);
+ /*
+ If elements != 0, some trees were stored in the file (see how
+ flush() works). Note, that we can not count on my_b_tell(&file) == 0
+ here, because it can return 0 right after walk(), and walk() does not
+ reset any Unique member.
+ */
+ if (elements)
+ {
+ reset_dynamic(&file_ptrs);
+ reinit_io_cache(&file, WRITE_CACHE, 0L, 0, 1);
+ }
+ elements= 0;
+}
+
+/*
+ The comparison function, passed to queue_init() in merge_walk() must
+ use comparison function of Uniques::tree, but compare members of struct
+ BUFFPEK.
+*/
+
+struct BUFFPEK_COMPARE_CONTEXT
+{
+ qsort_cmp2 key_compare;
+ void *key_compare_arg;
+};
+
+C_MODE_START
+
+static int buffpek_compare(void *arg, byte *key_ptr1, byte *key_ptr2)
+{
+ BUFFPEK_COMPARE_CONTEXT *ctx= (BUFFPEK_COMPARE_CONTEXT *) arg;
+ return ctx->key_compare(ctx->key_compare_arg,
+ *((byte **) key_ptr1), *((byte **)key_ptr2));
+}
+
+C_MODE_END
+
+
+/*
+ DESCRIPTION
+ Function is very similar to merge_buffers, but instead of writing sorted
+ unique keys to the output file, it invokes walk_action for each key.
+ This saves I/O if you need to pass through all unique keys only once.
+ SYNOPSIS
+ merge_walk()
+ All params are 'IN' (but see comment for begin, end):
+ merge_buffer buffer to perform cached piece-by-piece loading
+ of trees; initially the buffer is empty
+ merge_buffer_size size of merge_buffer. Must be aligned with
+ key_length
+ key_length size of tree element; key_length * (end - begin)
+ must be less or equal than merge_buffer_size.
+ begin pointer to BUFFPEK struct for the first tree.
+ end pointer to BUFFPEK struct for the last tree;
+ end > begin and [begin, end) form a consecutive
+ range. BUFFPEKs structs in that range are used and
+ overwritten in merge_walk().
+ walk_action element visitor. Action is called for each unique
+ key.
+ walk_action_arg argument to walk action. Passed to it on each call.
+ compare elements comparison function
+ compare_arg comparison function argument
+ file file with all trees dumped. Trees in the file
+ must contain sorted unique values. Cache must be
+ initialized in read mode.
+ RETURN VALUE
+ 0 ok
+ <> 0 error
+*/
+
+static bool merge_walk(uchar *merge_buffer, uint merge_buffer_size,
+ uint key_length, BUFFPEK *begin, BUFFPEK *end,
+ tree_walk_action walk_action, void *walk_action_arg,
+ qsort_cmp2 compare, void *compare_arg,
+ IO_CACHE *file)
+{
+ BUFFPEK_COMPARE_CONTEXT compare_context = { compare, compare_arg };
+ QUEUE queue;
+ if (end <= begin ||
+ merge_buffer_size < key_length * (end - begin + 1) ||
+ init_queue(&queue, end - begin, offsetof(BUFFPEK, key), 0,
+ buffpek_compare, &compare_context))
+ return 1;
+ /* we need space for one key when a piece of merge buffer is re-read */
+ merge_buffer_size-= key_length;
+ uchar *save_key_buff= merge_buffer + merge_buffer_size;
+ uint max_key_count_per_piece= merge_buffer_size/(end-begin)/key_length;
+ /* if piece_size is aligned reuse_freed_buffer will always hit */
+ uint piece_size= max_key_count_per_piece * key_length;
+ uint bytes_read; /* to hold return value of read_to_buffer */
+ BUFFPEK *top;
+ int res= 1;
+ /*
+ Invariant: queue must contain top element from each tree, until a tree
+ is not completely walked through.
+ Here we're forcing the invariant, inserting one element from each tree
+ to the queue.
+ */
+ for (top= begin; top != end; ++top)
+ {
+ top->base= merge_buffer + (top - begin) * piece_size;
+ top->max_keys= max_key_count_per_piece;
+ bytes_read= read_to_buffer(file, top, key_length);
+ if (bytes_read == (uint) (-1))
+ goto end;
+ DBUG_ASSERT(bytes_read);
+ queue_insert(&queue, (byte *) top);
+ }
+ top= (BUFFPEK *) queue_top(&queue);
+ while (queue.elements > 1)
+ {
+ /*
+ Every iteration one element is removed from the queue, and one is
+ inserted by the rules of the invariant. If two adjacent elements on
+ the top of the queue are not equal, biggest one is unique, because all
+ elements in each tree are unique. Action is applied only to unique
+ elements.
+ */
+ void *old_key= top->key;
+ /*
+ read next key from the cache or from the file and push it to the
+ queue; this gives new top.
+ */
+ top->key+= key_length;
+ if (--top->mem_count)
+ queue_replaced(&queue);
+ else /* next piece should be read */
+ {
+ /* save old_key not to overwrite it in read_to_buffer */
+ memcpy(save_key_buff, old_key, key_length);
+ old_key= save_key_buff;
+ bytes_read= read_to_buffer(file, top, key_length);
+ if (bytes_read == (uint) (-1))
+ goto end;
+ else if (bytes_read > 0) /* top->key, top->mem_count are reset */
+ queue_replaced(&queue); /* in read_to_buffer */
+ else
+ {
+ /*
+ Tree for old 'top' element is empty: remove it from the queue and
+ give all its memory to the nearest tree.
+ */
+ queue_remove(&queue, 0);
+ reuse_freed_buff(&queue, top, key_length);
+ }
+ }
+ top= (BUFFPEK *) queue_top(&queue);
+ /* new top has been obtained; if old top is unique, apply the action */
+ if (compare(compare_arg, old_key, top->key))
+ {
+ if (walk_action(old_key, 1, walk_action_arg))
+ goto end;
+ }
+ }
+ /*
+ Applying walk_action to the tail of the last tree: this is safe because
+ either we had only one tree in the beginning, either we work with the
+ last tree in the queue.
+ */
+ do
+ {
+ do
+ {
+ if (walk_action(top->key, 1, walk_action_arg))
+ goto end;
+ top->key+= key_length;
+ }
+ while (--top->mem_count);
+ bytes_read= read_to_buffer(file, top, key_length);
+ if (bytes_read == (uint) (-1))
+ goto end;
+ }
+ while (bytes_read);
+ res= 0;
+end:
+ delete_queue(&queue);
+ return res;
+}
+
+
+/*
+ DESCRIPTION
+ Walks consecutively through all unique elements:
+ if all elements are in memory, then it simply invokes 'tree_walk', else
+ all flushed trees are loaded to memory piece-by-piece, pieces are
+ sorted, and action is called for each unique value.
+ Note: so as merging resets file_ptrs state, this method can change
+ internal Unique state to undefined: if you want to reuse Unique after
+ walk() you must call reset() first!
+ SYNOPSIS
+ Unique:walk()
+ All params are 'IN':
+ action function-visitor, typed in include/my_tree.h
+ function is called for each unique element
+ arg argument for visitor, which is passed to it on each call
+ RETURN VALUE
+ 0 OK
+ <> 0 error
+ */
+
+bool Unique::walk(tree_walk_action action, void *walk_action_arg)
+{
+ if (elements == 0) /* the whole tree is in memory */
+ return tree_walk(&tree, action, walk_action_arg, left_root_right);
+
+ /* flush current tree to the file to have some memory for merge buffer */
+ if (flush())
+ return 1;
+ if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
+ return 1;
+ uchar *merge_buffer= (uchar *) my_malloc(max_in_memory_size, MYF(0));
+ if (merge_buffer == 0)
+ return 1;
+ int res= merge_walk(merge_buffer, max_in_memory_size, size,
+ (BUFFPEK *) file_ptrs.buffer,
+ (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
+ action, walk_action_arg,
+ tree.compare, tree.custom_arg, &file);
+ x_free(merge_buffer);
+ return res;
+}
+
+/*
Modify the TABLE element so that when one calls init_records()
the rows will be read in priority order.
*/
@@ -114,7 +589,7 @@ bool Unique::get(TABLE *table)
return 0;
}
}
- /* Not enough memory; Save the result to file */
+ /* Not enough memory; Save the result to file && free memory used by tree */
if (flush())
return 1;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index e3bf763f700..1ac8be0f49a 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -43,11 +43,10 @@ static uint get_interval_id(uint *int_count,List<create_field> &create_fields,
create_field *last_field);
static bool pack_fields(File file, List<create_field> &create_fields,
ulong data_offset);
-static bool make_empty_rec(int file, enum db_type table_type,
+static bool make_empty_rec(THD *thd, int file, enum db_type table_type,
uint table_options,
List<create_field> &create_fields,
- uint reclength, uint null_fields,
- ulong data_offset);
+ uint reclength, ulong data_offset);
/*
Create a frm (table definition) file
@@ -76,7 +75,8 @@ bool mysql_create_frm(THD *thd, my_string file_name,
uint keys, KEY *key_info,
handler *db_file)
{
- uint reclength,info_length,screens,key_info_length,maxlength,null_fields;
+ uint reclength,info_length,screens,key_info_length,maxlength;
+ ulong key_buff_length;
File file;
ulong filepos, data_offset;
uchar fileinfo[64],forminfo[288],*keybuff;
@@ -115,16 +115,15 @@ bool mysql_create_frm(THD *thd, my_string file_name,
}
}
reclength=uint2korr(forminfo+266);
- null_fields=uint2korr(forminfo+282);
- if ((file=create_frm(file_name, db, table, reclength, fileinfo,
+ if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
create_info, keys)) < 0)
{
my_free((gptr) screen_buff,MYF(0));
DBUG_RETURN(1);
}
- uint key_buff_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16;
+ key_buff_length= uint4korr(fileinfo+47);
keybuff=(uchar*) my_malloc(key_buff_length, MYF(0));
key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
VOID(get_form_pos(file,fileinfo,&formnames));
@@ -133,7 +132,6 @@ bool mysql_create_frm(THD *thd, my_string file_name,
maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000));
int2store(forminfo+2,maxlength);
int4store(fileinfo+10,(ulong) (filepos+maxlength));
- int4store(fileinfo+47,key_buff_length);
fileinfo[26]= (uchar) test((create_info->max_rows == 1) &&
(create_info->min_rows == 1) && (keys == 0));
int2store(fileinfo+28,key_info_length);
@@ -148,9 +146,18 @@ bool mysql_create_frm(THD *thd, my_string file_name,
VOID(my_seek(file,
(ulong) uint2korr(fileinfo+6)+ (ulong) key_buff_length,
MY_SEEK_SET,MYF(0)));
- if (make_empty_rec(file,create_info->db_type,create_info->table_options,
- create_fields,reclength, null_fields, data_offset))
+ if (make_empty_rec(thd,file,create_info->db_type,create_info->table_options,
+ create_fields,reclength, data_offset))
goto err;
+ if (create_info->connect_string.length)
+ {
+ char buff[2];
+ int2store(buff,create_info->connect_string.length);
+ if (my_write(file, buff, sizeof(buff), MYF(MY_NABP)) ||
+ my_write(file, create_info->connect_string.str,
+ create_info->connect_string.length, MYF(MY_NABP)))
+ goto err;
+ }
VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
if (my_write(file,(byte*) forminfo,288,MYF_RW) ||
@@ -226,7 +233,7 @@ err3:
keys number of keys to create
key_info Keys to create
db_file Handler to use. May be zero, in which case we use
- create_info->db_type
+ create_info->db_type
RETURN
0 ok
1 error
@@ -241,11 +248,11 @@ int rea_create_table(THD *thd, my_string file_name,
DBUG_ENTER("rea_create_table");
if (mysql_create_frm(thd, file_name, db, table, create_info,
- create_fields, keys, key_info, NULL))
+ create_fields, keys, key_info, NULL))
DBUG_RETURN(1);
- if (ha_create_table(file_name,create_info,0))
+ if (!create_info->frm_only && ha_create_table(file_name,create_info,0))
{
- my_delete(file_name,MYF(0));
+ my_delete(file_name,MYF(0));
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -350,7 +357,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
pos[6]=pos[7]=0; // For the future
pos+=8;
key_parts+=key->key_parts;
- DBUG_PRINT("loop",("flags: %d key_parts: %d at %lx",
+ DBUG_PRINT("loop",("flags: %d key_parts: %d at 0x%lx",
key->flags,key->key_parts,
key->key_part));
for (key_part=key->key_part,key_part_end=key_part+key->key_parts ;
@@ -415,11 +422,12 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
if (create_fields.elements > MAX_FIELDS)
{
- my_error(ER_TOO_MANY_FIELDS,MYF(0));
+ my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
DBUG_RETURN(1);
}
- totlength=reclength=0L;
+ totlength= 0L;
+ reclength= data_offset;
no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
com_length=0;
n_length=2L;
@@ -448,6 +456,8 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
!time_stamp_pos)
time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
length=field->pack_length;
+ /* Ensure we don't have any bugs when generating offsets */
+ DBUG_ASSERT(reclength == field->offset + data_offset);
if ((uint) field->offset+ (uint) data_offset+ length > reclength)
reclength=(uint) (field->offset+ data_offset + length);
n_length+= (ulong) strlen(field->field_name)+1;
@@ -502,7 +512,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
if (info_length+(ulong) create_fields.elements*FCOMP+288+
n_length+int_length+com_length > 65535L || int_count > 255)
{
- my_error(ER_TOO_MANY_FIELDS,MYF(0));
+ my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
DBUG_RETURN(1);
}
@@ -525,6 +535,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
int2store(forminfo+280,22); /* Rows needed */
int2store(forminfo+282,null_fields);
int2store(forminfo+284,com_length);
+ /* Up to forminfo+288 is free to use for additional information */
DBUG_RETURN(0);
} /* pack_header */
@@ -664,23 +675,25 @@ static bool pack_fields(File file, List<create_field> &create_fields,
/* save an empty record on start of formfile */
-static bool make_empty_rec(File file,enum db_type table_type,
+static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
uint table_options,
List<create_field> &create_fields,
- uint reclength, uint null_fields,
+ uint reclength,
ulong data_offset)
{
int error;
Field::utype type;
- uint firstpos,null_count;
+ uint null_count;
uchar *buff,*null_pos;
TABLE table;
create_field *field;
handler *handler;
+ enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
DBUG_ENTER("make_empty_rec");
/* We need a table to generate columns for default values */
bzero((char*) &table,sizeof(table));
+ table.s= &table.share_not_to_be_used;
handler= get_new_handler((TABLE*) 0, table_type);
if (!handler ||
@@ -690,26 +703,29 @@ 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;
+ table.in_use= thd;
+ table.s->db_low_byte_first= handler->low_byte_first();
+ table.s->blob_ptr_size= portable_sizeof_char_ptr;
- firstpos=reclength;
null_count=0;
if (!(table_options & HA_OPTION_PACK_RECORD))
+ {
null_count++; // Need one bit for delete mark
- DBUG_ASSERT(data_offset == ((null_fields + null_count + 7) / 8));
- bfill(buff, (uint) data_offset, 255);
- null_pos=buff;
+ *buff|= 1;
+ }
+ null_pos= buff;
List_iterator<create_field> it(create_fields);
+ thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values
while ((field=it++))
{
+ /*
+ regfield don't have to be deleted as it's allocated with sql_alloc()
+ */
Field *regfield=make_field((char*) buff+field->offset + data_offset,
field->length,
- field->flags & NOT_NULL_FLAG ? 0:
- null_pos+null_count/8,
- 1 << (null_count & 7),
+ null_pos + null_count / 8,
+ null_count & 7,
field->pack_flag,
field->sql_type,
field->charset,
@@ -718,25 +734,36 @@ static bool make_empty_rec(File file,enum db_type table_type,
field->interval,
field->field_name,
&table);
+ if (!regfield)
+ goto err; // End of memory
if (!(field->flags & NOT_NULL_FLAG))
+ {
+ *regfield->null_ptr|= regfield->null_bit;
null_count++;
+ }
- if ((uint) (field->offset + data_offset) < firstpos &&
- regfield->type() != FIELD_TYPE_NULL)
- firstpos= field->offset + data_offset;
+ if (field->sql_type == FIELD_TYPE_BIT && !f_bit_as_char(field->pack_flag))
+ null_count+= field->length & 7;
type= (Field::utype) MTYP_TYPENR(field->unireg_check);
if (field->def &&
(regfield->real_type() != FIELD_TYPE_YEAR ||
field->def->val_int() != 0))
- (void) field->def->save_in_field(regfield, 1);
+ {
+ if (field->def->save_in_field(regfield, 1))
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
+ error= 1;
+ goto err;
+ }
+ }
else if (regfield->real_type() == FIELD_TYPE_ENUM &&
(field->flags & NOT_NULL_FLAG))
{
regfield->set_notnull();
- regfield->store((longlong) 1);
+ regfield->store((longlong) 1, TRUE);
}
else if (type == Field::YES) // Old unireg type
regfield->store(ER(ER_YES),(uint) strlen(ER(ER_YES)),system_charset_info);
@@ -744,13 +771,21 @@ static bool make_empty_rec(File file,enum db_type table_type,
regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)),system_charset_info);
else
regfield->reset();
- delete regfield;
}
+ DBUG_ASSERT(data_offset == ((null_count + 7) / 8));
+
+ /*
+ We need to set the unused bits to 1. If the number of bits is a multiple
+ of 8 there are no unused bits.
+ */
+ if (null_count & 7)
+ *(null_pos + null_count / 8)|= ~(((uchar) 1 << (null_count & 7)) - 1);
- /* Fill not used startpos */
- bfill((byte*) buff+data_offset, firstpos- (uint) data_offset, 255);
error=(int) my_write(file,(byte*) buff, (uint) reclength,MYF_RW);
+
+err:
my_free((gptr) buff,MYF(MY_FAE));
delete handler;
+ thd->count_cuted_fields= old_count_cuted_fields;
DBUG_RETURN(error);
} /* make_empty_rec */
diff --git a/sql/unireg.h b/sql/unireg.h
index 70df9a89c8f..6afefa579e8 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -37,8 +37,8 @@
#define SHAREDIR "share/"
#endif
-#define ER(X) errmesg[(X)-1000]
-#define ER_SAFE(X) (((X) >= 1000 && (X) < ER_ERROR_MESSAGES + 1000) ? ER(X) : "Invalid error code")
+#define ER(X) errmesg[(X) - ER_ERROR_FIRST]
+#define ER_SAFE(X) (((X) >= ER_ERROR_FIRST && (X) <= ER_ERROR_LAST) ? ER(X) : "Invalid error code")
#define ERRMAPP 1 /* Errormap f|r my_error */
@@ -50,7 +50,11 @@
#define MAX_SYS_VAR_LENGTH 32
#define MAX_KEY 64 /* Max used keys */
#define MAX_REF_PARTS 16 /* Max parts used as ref */
-#define MAX_KEY_LENGTH 1024 /* max possible key */
+#if SIZEOF_CHARP > 4
+#define MAX_KEY_LENGTH 3072 /* max possible key, if 64 bits */
+#else
+#define MAX_KEY_LENGTH 1024 /* max possible key, if 32 bits */
+#endif
#if SIZEOF_OFF_T > 4
#define MAX_REFLENGTH 8 /* Max length for record ref */
#else
@@ -60,9 +64,14 @@
#define MAX_MBWIDTH 3 /* Max multibyte sequence */
#define MAX_FIELD_CHARLENGTH 255
+#define MAX_FIELD_VARCHARLENGTH 65535
+#define CONVERT_IF_BIGGER_TO_BLOB 512 /* Used for CREATE ... SELECT */
+
/* Max column width +1 */
#define MAX_FIELD_WIDTH (MAX_FIELD_CHARLENGTH*MAX_MBWIDTH+1)
+#define MAX_BIT_FIELD_LENGTH 64 /* Max length in bits for bit fields */
+
#define MAX_DATE_WIDTH 10 /* YYYY-MM-DD */
#define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */
#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */
@@ -118,12 +127,12 @@
#define SPECIAL_LOG_QUERIES_NOT_USING_INDEXES 4096 /* Log q not using indexes */
/* Extern defines */
-#define store_record(A,B) bmove_align((A)->B,(A)->record[0],(size_t) (A)->reclength)
-#define restore_record(A,B) bmove_align((A)->record[0],(A)->B,(size_t) (A)->reclength)
-#define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->reclength)
+#define store_record(A,B) bmove_align((A)->B,(A)->record[0],(size_t) (A)->s->reclength)
+#define restore_record(A,B) bmove_align((A)->record[0],(A)->B,(size_t) (A)->s->reclength)
+#define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->s->reclength)
#define empty_record(A) { \
- restore_record((A),default_values); \
- bfill((A)->null_flags,(A)->null_bytes,255);\
+ restore_record((A),s->default_values); \
+ bfill((A)->null_flags,(A)->s->null_bytes,255);\
}
/* Defines for use with openfrm, openprt and openfrd */
@@ -141,11 +150,13 @@
#define DONT_GIVE_ERROR 256 /* Don't do frm_error on openfrm */
#define READ_SCREENS 1024 /* Read screens, info and helpfile */
#define DELAYED_OPEN 4096 /* Open table later */
+#define NO_ERR_ON_NEW_FRM 8192 /* stop error sending on new format */
#define SC_INFO_LENGTH 4 /* Form format constant */
#define TE_INFO_LENGTH 3
#define MTYP_NOEMPTY_BIT 128
+#define FRM_VER_TRUE_VARCHAR (FRM_VER+4)
/*
Minimum length pattern before Turbo Boyer-Moore is used
for SELECT "text" LIKE "%pattern%", excluding the two
diff --git a/strings/Makefile.am b/strings/Makefile.am
index 97b35075277..c43cf0f290a 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -16,36 +16,35 @@
# This file is public domain and comes with NO WARRANTY of any kind
-INCLUDES = @MT_INCLUDES@ \
- -I$(top_builddir)/include -I$(top_srcdir)/include
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
pkglib_LIBRARIES = libmystrings.a
# Exact one of ASSEMBLER_X
if ASSEMBLER_x86
ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s
-CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c longlong2str_asm.c
+CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c str_alloc.c longlong2str_asm.c
else
if ASSEMBLER_sparc32
# These file MUST all be on the same line!! Otherwise automake
# generats a very broken makefile
ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s
-CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c
+CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c
else
#no assembler
ASRCS =
# These file MUST all be on the same line!! Otherwise automake
# generats a very broken makefile
-CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c
+CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c decimal.c ctype-extra.c my_strtoll10.c str_alloc.c
endif
endif
libmystrings_a_SOURCES = $(ASRCS) $(CSRCS)
noinst_PROGRAMS = conf_to_src
# Default charset definitions
-EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-win1250ch.c \
- ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-utf8.c \
- ctype-ucs2.c ctype-uca.c ctype-tis620.c ctype-ujis.c \
- xml.c strto.c strings-x86.s \
+EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-eucjpms.c ctype-euc_kr.c ctype-win1250ch.c \
+ ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-utf8.c \
+ ctype-ucs2.c ctype-uca.c ctype-tis620.c ctype-ujis.c \
+ xml.c decimal.c strto.c strings-x86.s \
longlong2str.c longlong2str-x86.s longlong2str_asm.c \
my_strtoll10.c my_strtoll10-x86.s \
strxmov.c bmove_upp.c strappend.c strcont.c strend.c \
@@ -54,7 +53,7 @@ EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-win1
bmove_upp-sparc.s strappend-sparc.s strend-sparc.s \
strinstr-sparc.s strmake-sparc.s strmov-sparc.s \
strnmov-sparc.s strstr-sparc.s strxmov-sparc.s \
- t_ctype.h
+ t_ctype.h
libmystrings_a_LIBADD=
conf_to_src_SOURCES = conf_to_src.c xml.c ctype.c bcmp.c
@@ -73,8 +72,16 @@ if ASSEMBLER
$(AS) $(ASFLAGS) -o $@ $<
endif
-str_test: str_test.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $INCLUDES $(srcdir)/str_test.c $(LDADD) $(LIBS) $(pkglib_LIBRARIES)
+FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @NOINST_LDFLAGS@
+
+str_test: str_test.c $(pkglib_LIBRARIES)
+ $(LINK) $(FLAGS) -DMAIN $(INCLUDES) $(srcdir)/str_test.c $(LDADD) $(pkglib_LIBRARIES)
+
+test_decimal$(EXEEXT): decimal.c $(pkglib_LIBRARIES)
+ $(CP) $(srcdir)/decimal.c ./test_decimal.c
+ $(LINK) $(FLAGS) -DMAIN ./test_decimal.c $(LDADD) $(pkglib_LIBRARIES)
+ $(RM) -f ./test_decimal.c
# Don't update the files from bitkeeper
%::SCCS/s.%
+
diff --git a/strings/conf_to_src.c b/strings/conf_to_src.c
index d5ffa15ee0c..5a6adb398da 100644
--- a/strings/conf_to_src.c
+++ b/strings/conf_to_src.c
@@ -75,6 +75,8 @@ static int get_charset_number(const char *charset_name)
char *mdup(const char *src, uint len)
{
char *dst=(char*)malloc(len);
+ if (!dst)
+ exit(1);
memcpy(dst,src,len);
return dst;
}
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 76a4e197405..5069a1dc082 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -264,24 +264,33 @@ static int my_strnncoll_big5(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_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 diff_if_only_endspace_difference)
{
uint length= min(a_length, b_length);
int res= my_strnncoll_big5_internal(&a, &b, length);
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
+
if (!res && a_length != b_length)
{
const uchar *end;
int swap= 1;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
*/
if (a_length < b_length)
{
- /* put shorter key in a */
+ /* put longer key in a */
a_length= b_length;
a= b;
- swap= -1; /* swap sign of result */
+ swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -415,7 +424,7 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)),
*min_str++= *max_str++ = *ptr;
continue;
}
- if (*ptr == w_one) /* '_' in SQL */
+ if (*ptr == w_one) /* '_' in SQL */
{
*min_str++='\0'; /* This should be min char */
*max_str++=max_sort_char;
@@ -423,7 +432,13 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str-min_org);
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
*max_length= res_length;
do {
*min_str++ = 0;
@@ -433,26 +448,27 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)),
}
*min_str++= *max_str++ = *ptr;
}
- *min_length= *max_length= (uint) (min_str-min_org);
+
+ *min_length= *max_length= (uint) (min_str-min_org);
while (min_str != min_end)
- {
- *min_str++ = ' '; /* Because if key compression */
- *max_str++ = ' ';
- }
+ *min_str++= *max_str++= ' ';
return 0;
}
+
static int ismbchar_big5(CHARSET_INFO *cs __attribute__((unused)),
const char* p, const char *e)
{
return (isbig5head(*(p)) && (e)-(p)>1 && isbig5tail(*((p)+1))? 2: 0);
}
+
static int mbcharlen_big5(CHARSET_INFO *cs __attribute__((unused)), uint c)
{
return (isbig5head(c)? 2 : 1);
}
+
/* page 0 0xA140-0xC7FC */
static uint16 tab_big5_uni0[]={
0x3000,0xFF0C,0x3001,0x3002,0xFF0E,0x2022,0xFF1B,0xFF1A,
@@ -6319,11 +6335,13 @@ static MY_COLLATION_HANDLER my_collation_big5_chinese_ci_handler =
my_strnncoll_big5,
my_strnncollsp_big5,
my_strnxfrm_big5,
+ my_strnxfrmlen_simple,
my_like_range_big5,
my_wildcmp_mb,
my_strcasecmp_mb,
my_instr_mb,
- my_hash_sort_simple
+ my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_big5_handler=
@@ -6371,9 +6389,12 @@ CHARSET_INFO my_charset_big5_chinese_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
@@ -6400,9 +6421,12 @@ CHARSET_INFO my_charset_big5_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 1ac79ac9ca0..0fcd9021c4b 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -110,7 +110,9 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
static int my_strnncollsp_binary(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference
+ __attribute__((unused)))
{
return my_strnncoll_binary(cs,s,slen,t,tlen,0);
}
@@ -137,6 +139,9 @@ static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
slen Length of 's'
t String to compare
tlen Length of 't'
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
NOTE
This function is used for character strings with binary collations.
@@ -151,10 +156,16 @@ static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
static int my_strnncollsp_8bit_bin(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 diff_if_only_endspace_difference)
{
const uchar *end;
uint length;
+ int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
end= a + (length= min(a_length, b_length));
while (a < end)
@@ -162,6 +173,7 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
if (*a++ != *b++)
return ((int) a[-1] - (int) b[-1]);
}
+ res= 0;
if (a_length != b_length)
{
int swap= 1;
@@ -169,12 +181,15 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
*/
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
if (a_length < b_length)
{
/* put shorter key in s */
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -182,7 +197,7 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
return (*a < ' ') ? -swap : swap;
}
}
- return 0;
+ return res;
}
@@ -193,10 +208,13 @@ static void my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)),
{
}
-static void my_case_bin(CHARSET_INFO *cs __attribute__((unused)),
- char *str __attribute__((unused)),
- uint length __attribute__((unused)))
+static uint my_case_bin(CHARSET_INFO *cs __attribute__((unused)),
+ char *src __attribute__((unused)),
+ uint srclen,
+ char *dst __attribute__((unused)),
+ uint dstlen __attribute__((unused)))
{
+ return srclen;
}
@@ -415,7 +433,7 @@ skip:
if (nmatch > 0)
{
match[0].beg= 0;
- match[0].end= str- (const uchar*)b-1;
+ match[0].end= (uint) (str- (const uchar*)b-1);
match[0].mblen= match[0].end;
if (nmatch > 1)
@@ -439,11 +457,13 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler =
my_strnncoll_8bit_bin,
my_strnncollsp_8bit_bin,
my_strnxfrm_8bit_bin,
+ my_strnxfrmlen_simple,
my_like_range_simple,
my_wildcmp_bin,
my_strcasecmp_bin,
my_instr_bin,
- my_hash_sort_bin
+ my_hash_sort_bin,
+ my_propagate_simple
};
@@ -453,11 +473,13 @@ static MY_COLLATION_HANDLER my_collation_binary_handler =
my_strnncoll_binary,
my_strnncollsp_binary,
my_strnxfrm_bin,
+ my_strnxfrmlen_simple,
my_like_range_simple,
my_wildcmp_bin,
my_strcasecmp_bin,
my_instr_bin,
- my_hash_sort_bin
+ my_hash_sort_bin,
+ my_propagate_simple
};
@@ -507,9 +529,12 @@ CHARSET_INFO my_charset_bin =
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c
index e476130b706..b5f36c030bd 100644
--- a/strings/ctype-cp932.c
+++ b/strings/ctype-cp932.c
@@ -213,7 +213,7 @@ static int my_strnncoll_cp932_internal(CHARSET_INFO *cs,
uint a_char= cp932code(*a, *(a+1));
uint b_char= cp932code(*b, *(b+1));
if (a_char != b_char)
- return (int) a_char - (int) b_char;
+ return a_char - b_char;
a += 2;
b += 2;
} else
@@ -244,7 +244,9 @@ static int my_strnncoll_cp932(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_cp932(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 diff_if_only_endspace_difference
+ __attribute__((unused)))
{
const uchar *a_end= a + a_length;
const uchar *b_end= b + b_length;
@@ -322,14 +324,9 @@ static my_bool my_like_range_cp932(CHARSET_INFO *cs __attribute__((unused)),
uint res_length, char *min_str,char *max_str,
uint *min_length,uint *max_length)
{
- const char *end;
+ const char *end=ptr+ptr_length;
char *min_org=min_str;
char *min_end=min_str+res_length;
- uint charlen= my_charpos(cs, ptr, ptr+ptr_length, res_length/cs->mbmaxlen);
-
- if (charlen < ptr_length)
- ptr_length= charlen;
- end= ptr + ptr_length;
while (ptr < end && min_str < min_end) {
if (ismbchar_cp932(cs, ptr, end)) {
@@ -5420,7 +5417,7 @@ uint my_well_formed_len_cp932(CHARSET_INFO *cs __attribute__((unused)),
{
const char *b0= b;
*error= 0;
- while (pos-- && b < e)
+ while (pos && b < e)
{
/*
Cast to int8 for extra safety.
@@ -5459,11 +5456,13 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncoll_cp932,
my_strnncollsp_cp932,
my_strnxfrm_cp932,
+ my_strnxfrmlen_simple,
my_like_range_cp932,
my_wildcmp_mb, /* wildcmp */
my_strcasecmp_8bit,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
@@ -5513,9 +5512,12 @@ CHARSET_INFO my_charset_cp932_japanese_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
@@ -5541,9 +5543,12 @@ CHARSET_INFO my_charset_cp932_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index 4bd2fbddbc4..bdafc5c94b6 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -275,8 +275,10 @@ static int my_strnncoll_czech(CHARSET_INFO *cs __attribute__((unused)),
static
int my_strnncollsp_czech(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 diff_if_only_endspace_difference
+ __attribute__((unused)))
{
for ( ; slen && s[slen-1] == ' ' ; slen--);
for ( ; tlen && t[tlen-1] == ' ' ; tlen--);
@@ -354,7 +356,7 @@ static int my_strnxfrm_czech(CHARSET_INFO *cs __attribute__((unused)),
#ifdef REAL_MYSQL
-#define min_sort_char ' '
+#define min_sort_char 0
#define max_sort_char '9'
#define EXAMPLE
@@ -393,8 +395,17 @@ static my_bool my_like_range_czech(CHARSET_INFO *cs __attribute__((unused)),
*min_str++= *max_str++ = *ptr;
}
- *min_length= (uint) (min_str - min_org);
+
+ if (cs->state & MY_CS_BINSORT)
+ *min_length= (uint) (min_str - min_org);
+ else
+ {
+ /* 'a\0\0... is the smallest possible string */
+ *min_length= res_length;
+ }
+ /* a\ff\ff... is the biggest possible string */
*max_length= res_length;
+
while (min_str != min_end)
{
*min_str++ = min_sort_char; /* Because of key compression */
@@ -582,11 +593,13 @@ static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler =
my_strnncoll_czech,
my_strnncollsp_czech,
my_strnxfrm_czech,
+ my_strnxfrmlen_simple,
my_like_range_czech,
my_wildcmp_8bit,
my_strcasecmp_8bit,
my_instr_simple,
my_hash_sort_simple,
+ my_propagate_simple
};
CHARSET_INFO my_charset_latin2_czech_ci =
@@ -605,9 +618,12 @@ CHARSET_INFO my_charset_latin2_czech_ci =
NULL, /* sort_order_big*/
tab_8859_2_uni, /* tab_to_uni */
idx_uni_8859_2, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
4, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index f15e97de5be..b529bbb0308 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -8641,11 +8641,13 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncoll_simple, /* strnncoll */
my_strnncollsp_simple,
my_strnxfrm_simple, /* strnxfrm */
+ my_strnxfrmlen_simple,
my_like_range_simple, /* like_range */
my_wildcmp_mb, /* wildcmp */
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
@@ -8694,9 +8696,12 @@ CHARSET_INFO my_charset_euckr_korean_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
@@ -8723,9 +8728,12 @@ CHARSET_INFO my_charset_euckr_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c
new file mode 100644
index 00000000000..ccdca2ba595
--- /dev/null
+++ b/strings/ctype-eucjpms.c
@@ -0,0 +1,8749 @@
+/* Copyright (C) 2002 MySQL AB & tommy@valley.ne.jp.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA */
+
+/* This file is for Japanese EUC charset, and created based on
+ctype-ujis.c file.
+ */
+
+/*
+ * This comment is parsed by configure to create ctype.c,
+ * so don't change it unless you know what you are doing.
+ *
+ * .configure. mbmaxlen_eucjpms=3
+ */
+
+#include <my_global.h>
+#include "m_string.h"
+#include "m_ctype.h"
+
+#ifdef HAVE_CHARSET_eucjpms
+
+
+static uchar NEAR ctype_eucjpms[257] =
+{
+ 0, /* For standard library */
+ 0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
+ 0040, 0050, 0050, 0050, 0050, 0050, 0040, 0040, /* ^H - ^O */
+ 0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* ^P - ^W */
+ 0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* ^X - ^Z ^[ ^\ ^] ^^ ^_ */
+ 0110, 0020, 0020, 0020, 0020, 0020, 0020, 0020, /* SPC ! " # $ % ^ ' */
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020, /* ( ) * + , - . / */
+ 0204, 0204, 0204, 0204, 0204, 0204, 0204, 0204, /* 0 1 2 3 4 5 6 7 */
+ 0204, 0204, 0020, 0020, 0020, 0020, 0020, 0020, /* 8 9 : ; < = > ? */
+ 0020, 0201, 0201, 0201, 0201, 0201, 0201, 0001, /* @ A B C D E F G */
+ 0001, 0001, 0001, 0001, 0001, 0001, 0001, 0001, /* H I J K L M N O */
+ 0001, 0001, 0001, 0001, 0001, 0001, 0001, 0001, /* P Q R S T U V W */
+ 0001, 0001, 0001, 0020, 0020, 0020, 0020, 0020, /* X Y Z [ \ ] ^ _ */
+ 0020, 0202, 0202, 0202, 0202, 0202, 0202, 0002, /* ` a b c d e f g */
+ 0002, 0002, 0002, 0002, 0002, 0002, 0002, 0002, /* h i j k l m n o */
+ 0002, 0002, 0002, 0002, 0002, 0002, 0002, 0002, /* p q r s t u v w */
+ 0002, 0002, 0002, 0020, 0020, 0020, 0020, 0040, /* x y z { | } + DEL */
+ 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
+ 0000, 0000, 0000, 0000, 0000, 0000, 0020, 0020,
+ 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
+ 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
+ 0000, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0020,
+ 0020, 0020, 0020, 0020, 0020, 0020, 0020, 0000,
+};
+
+static uchar NEAR to_lower_eucjpms[]=
+{
+ '\000','\001','\002','\003','\004','\005','\006','\007',
+ '\010','\011','\012','\013','\014','\015','\016','\017',
+ '\020','\021','\022','\023','\024','\025','\026','\027',
+ '\030','\031','\032','\033','\034','\035','\036','\037',
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '[', '\\', ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '{', '|', '}', '~', '\177',
+ (uchar) '\200',(uchar) '\201',(uchar) '\202',(uchar) '\203',(uchar) '\204',(uchar) '\205',(uchar) '\206',(uchar) '\207',
+ (uchar) '\210',(uchar) '\211',(uchar) '\212',(uchar) '\213',(uchar) '\214',(uchar) '\215',(uchar) '\216',(uchar) '\217',
+ (uchar) '\220',(uchar) '\221',(uchar) '\222',(uchar) '\223',(uchar) '\224',(uchar) '\225',(uchar) '\226',(uchar) '\227',
+ (uchar) '\230',(uchar) '\231',(uchar) '\232',(uchar) '\233',(uchar) '\234',(uchar) '\235',(uchar) '\236',(uchar) '\237',
+ (uchar) '\240',(uchar) '\241',(uchar) '\242',(uchar) '\243',(uchar) '\244',(uchar) '\245',(uchar) '\246',(uchar) '\247',
+ (uchar) '\250',(uchar) '\251',(uchar) '\252',(uchar) '\253',(uchar) '\254',(uchar) '\255',(uchar) '\256',(uchar) '\257',
+ (uchar) '\260',(uchar) '\261',(uchar) '\262',(uchar) '\263',(uchar) '\264',(uchar) '\265',(uchar) '\266',(uchar) '\267',
+ (uchar) '\270',(uchar) '\271',(uchar) '\272',(uchar) '\273',(uchar) '\274',(uchar) '\275',(uchar) '\276',(uchar) '\277',
+ (uchar) '\300',(uchar) '\301',(uchar) '\302',(uchar) '\303',(uchar) '\304',(uchar) '\305',(uchar) '\306',(uchar) '\307',
+ (uchar) '\310',(uchar) '\311',(uchar) '\312',(uchar) '\313',(uchar) '\314',(uchar) '\315',(uchar) '\316',(uchar) '\317',
+ (uchar) '\320',(uchar) '\321',(uchar) '\322',(uchar) '\323',(uchar) '\324',(uchar) '\325',(uchar) '\326',(uchar) '\327',
+ (uchar) '\330',(uchar) '\331',(uchar) '\332',(uchar) '\333',(uchar) '\334',(uchar) '\335',(uchar) '\336',(uchar) '\337',
+ (uchar) '\340',(uchar) '\341',(uchar) '\342',(uchar) '\343',(uchar) '\344',(uchar) '\345',(uchar) '\346',(uchar) '\347',
+ (uchar) '\350',(uchar) '\351',(uchar) '\352',(uchar) '\353',(uchar) '\354',(uchar) '\355',(uchar) '\356',(uchar) '\357',
+ (uchar) '\360',(uchar) '\361',(uchar) '\362',(uchar) '\363',(uchar) '\364',(uchar) '\365',(uchar) '\366',(uchar) '\367',
+ (uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
+};
+
+static uchar NEAR to_upper_eucjpms[]=
+{
+ '\000','\001','\002','\003','\004','\005','\006','\007',
+ '\010','\011','\012','\013','\014','\015','\016','\017',
+ '\020','\021','\022','\023','\024','\025','\026','\027',
+ '\030','\031','\032','\033','\034','\035','\036','\037',
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '{', '|', '}', '~', '\177',
+ (uchar) '\200',(uchar) '\201',(uchar) '\202',(uchar) '\203',(uchar) '\204',(uchar) '\205',(uchar) '\206',(uchar) '\207',
+ (uchar) '\210',(uchar) '\211',(uchar) '\212',(uchar) '\213',(uchar) '\214',(uchar) '\215',(uchar) '\216',(uchar) '\217',
+ (uchar) '\220',(uchar) '\221',(uchar) '\222',(uchar) '\223',(uchar) '\224',(uchar) '\225',(uchar) '\226',(uchar) '\227',
+ (uchar) '\230',(uchar) '\231',(uchar) '\232',(uchar) '\233',(uchar) '\234',(uchar) '\235',(uchar) '\236',(uchar) '\237',
+ (uchar) '\240',(uchar) '\241',(uchar) '\242',(uchar) '\243',(uchar) '\244',(uchar) '\245',(uchar) '\246',(uchar) '\247',
+ (uchar) '\250',(uchar) '\251',(uchar) '\252',(uchar) '\253',(uchar) '\254',(uchar) '\255',(uchar) '\256',(uchar) '\257',
+ (uchar) '\260',(uchar) '\261',(uchar) '\262',(uchar) '\263',(uchar) '\264',(uchar) '\265',(uchar) '\266',(uchar) '\267',
+ (uchar) '\270',(uchar) '\271',(uchar) '\272',(uchar) '\273',(uchar) '\274',(uchar) '\275',(uchar) '\276',(uchar) '\277',
+ (uchar) '\300',(uchar) '\301',(uchar) '\302',(uchar) '\303',(uchar) '\304',(uchar) '\305',(uchar) '\306',(uchar) '\307',
+ (uchar) '\310',(uchar) '\311',(uchar) '\312',(uchar) '\313',(uchar) '\314',(uchar) '\315',(uchar) '\316',(uchar) '\317',
+ (uchar) '\320',(uchar) '\321',(uchar) '\322',(uchar) '\323',(uchar) '\324',(uchar) '\325',(uchar) '\326',(uchar) '\327',
+ (uchar) '\330',(uchar) '\331',(uchar) '\332',(uchar) '\333',(uchar) '\334',(uchar) '\335',(uchar) '\336',(uchar) '\337',
+ (uchar) '\340',(uchar) '\341',(uchar) '\342',(uchar) '\343',(uchar) '\344',(uchar) '\345',(uchar) '\346',(uchar) '\347',
+ (uchar) '\350',(uchar) '\351',(uchar) '\352',(uchar) '\353',(uchar) '\354',(uchar) '\355',(uchar) '\356',(uchar) '\357',
+ (uchar) '\360',(uchar) '\361',(uchar) '\362',(uchar) '\363',(uchar) '\364',(uchar) '\365',(uchar) '\366',(uchar) '\367',
+ (uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
+};
+
+static uchar NEAR sort_order_eucjpms[]=
+{
+ '\000','\001','\002','\003','\004','\005','\006','\007',
+ '\010','\011','\012','\013','\014','\015','\016','\017',
+ '\020','\021','\022','\023','\024','\025','\026','\027',
+ '\030','\031','\032','\033','\034','\035','\036','\037',
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '{', '|', '}', '~', '\177',
+ (uchar) '\200',(uchar) '\201',(uchar) '\202',(uchar) '\203',(uchar) '\204',(uchar) '\205',(uchar) '\206',(uchar) '\207',
+ (uchar) '\210',(uchar) '\211',(uchar) '\212',(uchar) '\213',(uchar) '\214',(uchar) '\215',(uchar) '\216',(uchar) '\217',
+ (uchar) '\220',(uchar) '\221',(uchar) '\222',(uchar) '\223',(uchar) '\224',(uchar) '\225',(uchar) '\226',(uchar) '\227',
+ (uchar) '\230',(uchar) '\231',(uchar) '\232',(uchar) '\233',(uchar) '\234',(uchar) '\235',(uchar) '\236',(uchar) '\237',
+ (uchar) '\240',(uchar) '\241',(uchar) '\242',(uchar) '\243',(uchar) '\244',(uchar) '\245',(uchar) '\246',(uchar) '\247',
+ (uchar) '\250',(uchar) '\251',(uchar) '\252',(uchar) '\253',(uchar) '\254',(uchar) '\255',(uchar) '\256',(uchar) '\257',
+ (uchar) '\260',(uchar) '\261',(uchar) '\262',(uchar) '\263',(uchar) '\264',(uchar) '\265',(uchar) '\266',(uchar) '\267',
+ (uchar) '\270',(uchar) '\271',(uchar) '\272',(uchar) '\273',(uchar) '\274',(uchar) '\275',(uchar) '\276',(uchar) '\277',
+ (uchar) '\300',(uchar) '\301',(uchar) '\302',(uchar) '\303',(uchar) '\304',(uchar) '\305',(uchar) '\306',(uchar) '\307',
+ (uchar) '\310',(uchar) '\311',(uchar) '\312',(uchar) '\313',(uchar) '\314',(uchar) '\315',(uchar) '\316',(uchar) '\317',
+ (uchar) '\320',(uchar) '\321',(uchar) '\322',(uchar) '\323',(uchar) '\324',(uchar) '\325',(uchar) '\326',(uchar) '\327',
+ (uchar) '\330',(uchar) '\331',(uchar) '\332',(uchar) '\333',(uchar) '\334',(uchar) '\335',(uchar) '\336',(uchar) '\337',
+ (uchar) '\340',(uchar) '\341',(uchar) '\342',(uchar) '\343',(uchar) '\344',(uchar) '\345',(uchar) '\346',(uchar) '\347',
+ (uchar) '\350',(uchar) '\351',(uchar) '\352',(uchar) '\353',(uchar) '\354',(uchar) '\355',(uchar) '\356',(uchar) '\357',
+ (uchar) '\360',(uchar) '\361',(uchar) '\362',(uchar) '\363',(uchar) '\364',(uchar) '\365',(uchar) '\366',(uchar) '\367',
+ (uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375', (uchar) (uchar) '\376', (uchar) '\377'
+};
+
+
+#define iseucjpms(c) ((0xa1<=((c)&0xff) && ((c)&0xff)<=0xfe))
+#define iskata(c) ((0xa1<=((c)&0xff) && ((c)&0xff)<=0xdf))
+#define iseucjpms_ss2(c) (((c)&0xff) == 0x8e)
+#define iseucjpms_ss3(c) (((c)&0xff) == 0x8f)
+
+
+static int ismbchar_eucjpms(CHARSET_INFO *cs __attribute__((unused)),
+ const char* p, const char *e)
+{
+ return ((*(uchar*)(p)<0x80)? 0:\
+ iseucjpms(*(p)) && (e)-(p)>1 && iseucjpms(*((p)+1))? 2:\
+ iseucjpms_ss2(*(p)) && (e)-(p)>1 && iskata(*((p)+1))? 2:\
+ iseucjpms_ss3(*(p)) && (e)-(p)>2 && iseucjpms(*((p)+1)) && iseucjpms(*((p)+2))? 3:\
+ 0);
+}
+
+static int mbcharlen_eucjpms(CHARSET_INFO *cs __attribute__((unused)),uint c)
+{
+ return (iseucjpms(c)? 2: iseucjpms_ss2(c)? 2: iseucjpms_ss3(c)? 3: 1);
+}
+
+
+static uint16 tab_jisx0201_uni[256]={
+ 0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E, 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,0xFF61,0xFF62,0xFF63,0xFF64,0xFF65,0xFF66,0xFF67,
+0xFF68,0xFF69,0xFF6A,0xFF6B,0xFF6C,0xFF6D,0xFF6E,0xFF6F,
+0xFF70,0xFF71,0xFF72,0xFF73,0xFF74,0xFF75,0xFF76,0xFF77,
+0xFF78,0xFF79,0xFF7A,0xFF7B,0xFF7C,0xFF7D,0xFF7E,0xFF7F,
+0xFF80,0xFF81,0xFF82,0xFF83,0xFF84,0xFF85,0xFF86,0xFF87,
+0xFF88,0xFF89,0xFF8A,0xFF8B,0xFF8C,0xFF8D,0xFF8E,0xFF8F,
+0xFF90,0xFF91,0xFF92,0xFF93,0xFF94,0xFF95,0xFF96,0xFF97,
+0xFF98,0xFF99,0xFF9A,0xFF9B,0xFF9C,0xFF9D,0xFF9E,0xFF9F,
+ 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
+};
+
+
+static int
+my_mb_wc_jisx0201(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t *wc,const uchar *s,
+ const uchar *e __attribute__((unused)))
+{
+ wc[0]=tab_jisx0201_uni[*s];
+ return (!wc[0] && s[0]) ? MY_CS_ILSEQ : 1;
+}
+
+
+static int
+my_wc_mb_jisx0201(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, uchar *s,
+ uchar *e __attribute__((unused)))
+{
+
+ if ((int) wc <= 0x7D)
+ {
+ *s = (uchar) wc;
+ return (wc == 0x5C) ? MY_CS_ILUNI : 1;
+ }
+
+ if (wc >= 0xFF61 && wc <= 0xFF9F)
+ {
+ *s = (uchar) (wc - 0xFEC0);
+ return 1;
+ }
+
+ return MY_CS_ILUNI;
+}
+
+
+/* page 0 0x2121-0x217E */
+static uint16 tab_jisx0208_uni0[]={
+0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
+0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
+0xFFE3,0xFF3F,0x30FD,0x30FE,0x309D,0x309E,0x3003,0x4EDD,
+0x3005,0x3006,0x3007,0x30FC,0x2015,0x2010,0xFF0F,0xFF3C,
+0xFF5E,0x2225,0xFF5C,0x2026,0x2025,0x2018,0x2019,0x201C,
+0x201D,0xFF08,0xFF09,0x3014,0x3015,0xFF3B,0xFF3D,0xFF5B,
+0xFF5D,0x3008,0x3009,0x300A,0x300B,0x300C,0x300D,0x300E,
+0x300F,0x3010,0x3011,0xFF0B,0xFF0D,0x00B1,0x00D7,0x00F7,
+0xFF1D,0x2260,0xFF1C,0xFF1E,0x2266,0x2267,0x221E,0x2234,
+0x2642,0x2640,0x00B0,0x2032,0x2033,0x2103,0xFFE5,0xFF04,
+0xFFE0,0xFFE1,0xFF05,0xFF03,0xFF06,0xFF0A,0xFF20,0x00A7,
+0x2606,0x2605,0x25CB,0x25CF,0x25CE,0x25C7};
+
+/* page 1 0x2221-0x227E */
+static uint16 tab_jisx0208_uni1[]={
+0x25C6,0x25A1,0x25A0,0x25B3,0x25B2,0x25BD,0x25BC,0x203B,
+0x3012,0x2192,0x2190,0x2191,0x2193,0x3013, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2208,0x220B,0x2286,0x2287,0x2282,0x2283,0x222A,
+0x2229, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2227,0x2228,0xFFE2,0x21D2,0x21D4,0x2200,0x2203,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2220,0x22A5,0x2312,0x2202,0x2207,
+0x2261,0x2252,0x226A,0x226B,0x221A,0x223D,0x221D,0x2235,
+0x222B,0x222C, 0, 0, 0, 0, 0, 0,
+ 0,0x212B,0x2030,0x266F,0x266D,0x266A,0x2020,0x2021,
+0x00B6, 0, 0, 0, 0,0x25EF};
+
+/* page 2 0x2330-0x237A */
+static uint16 tab_jisx0208_uni2[]={
+0xFF10,0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,
+0xFF18,0xFF19, 0, 0, 0, 0, 0, 0,
+ 0,0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,
+0xFF28,0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,
+0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,
+0xFF38,0xFF39,0xFF3A, 0, 0, 0, 0, 0,
+ 0,0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,
+0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,
+0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,
+0xFF58,0xFF59,0xFF5A};
+
+/* page 3 0x2421-0x2473 */
+static uint16 tab_jisx0208_uni3[]={
+0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,
+0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,
+0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,
+0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F,0x3060,
+0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,0x3068,
+0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F,0x3070,
+0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,0x3078,
+0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F,0x3080,
+0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088,
+0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F,0x3090,
+0x3091,0x3092,0x3093};
+
+/* page 4 0x2521-0x2576 */
+static uint16 tab_jisx0208_uni4[]={
+0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,
+0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,
+0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,
+0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,0x30C0,
+0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,0x30C8,
+0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,0x30D0,
+0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,0x30D8,
+0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF,0x30E0,
+0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,0x30E8,
+0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF,0x30F0,
+0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6};
+
+/* page 5 0x2621-0x2658 */
+static uint16 tab_jisx0208_uni5[]={
+0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,
+0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,0x03A0,
+0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,0x03B8,
+0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF,0x03C0,
+0x03C1,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,0x03C9
+};
+
+/* page 6 0x2721-0x2771 */
+static uint16 tab_jisx0208_uni6[]={
+0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,0x0416,
+0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,
+0x041F,0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,
+0x0427,0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,
+0x042F, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451,0x0436,
+0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,
+0x043F,0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,
+0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,0x044E,
+0x044F};
+
+/* page 7 0x2821-0x2840 */
+static uint16 tab_jisx0208_uni7[]={
+0x2500,0x2502,0x250C,0x2510,0x2518,0x2514,0x251C,0x252C,
+0x2524,0x2534,0x253C,0x2501,0x2503,0x250F,0x2513,0x251B,
+0x2517,0x2523,0x2533,0x252B,0x253B,0x254B,0x2520,0x252F,
+0x2528,0x2537,0x253F,0x251D,0x2530,0x2525,0x2538,0x2542
+};
+
+/* page 8 0x3021-0x307E */
+static uint16 tab_jisx0208_uni8[]={
+0x4E9C,0x5516,0x5A03,0x963F,0x54C0,0x611B,0x6328,0x59F6,
+0x9022,0x8475,0x831C,0x7A50,0x60AA,0x63E1,0x6E25,0x65ED,
+0x8466,0x82A6,0x9BF5,0x6893,0x5727,0x65A1,0x6271,0x5B9B,
+0x59D0,0x867B,0x98F4,0x7D62,0x7DBE,0x9B8E,0x6216,0x7C9F,
+0x88B7,0x5B89,0x5EB5,0x6309,0x6697,0x6848,0x95C7,0x978D,
+0x674F,0x4EE5,0x4F0A,0x4F4D,0x4F9D,0x5049,0x56F2,0x5937,
+0x59D4,0x5A01,0x5C09,0x60DF,0x610F,0x6170,0x6613,0x6905,
+0x70BA,0x754F,0x7570,0x79FB,0x7DAD,0x7DEF,0x80C3,0x840E,
+0x8863,0x8B02,0x9055,0x907A,0x533B,0x4E95,0x4EA5,0x57DF,
+0x80B2,0x90C1,0x78EF,0x4E00,0x58F1,0x6EA2,0x9038,0x7A32,
+0x8328,0x828B,0x9C2F,0x5141,0x5370,0x54BD,0x54E1,0x56E0,
+0x59FB,0x5F15,0x98F2,0x6DEB,0x80E4,0x852D};
+
+/* page 9 0x3121-0x317E */
+static uint16 tab_jisx0208_uni9[]={
+0x9662,0x9670,0x96A0,0x97FB,0x540B,0x53F3,0x5B87,0x70CF,
+0x7FBD,0x8FC2,0x96E8,0x536F,0x9D5C,0x7ABA,0x4E11,0x7893,
+0x81FC,0x6E26,0x5618,0x5504,0x6B1D,0x851A,0x9C3B,0x59E5,
+0x53A9,0x6D66,0x74DC,0x958F,0x5642,0x4E91,0x904B,0x96F2,
+0x834F,0x990C,0x53E1,0x55B6,0x5B30,0x5F71,0x6620,0x66F3,
+0x6804,0x6C38,0x6CF3,0x6D29,0x745B,0x76C8,0x7A4E,0x9834,
+0x82F1,0x885B,0x8A60,0x92ED,0x6DB2,0x75AB,0x76CA,0x99C5,
+0x60A6,0x8B01,0x8D8A,0x95B2,0x698E,0x53AD,0x5186,0x5712,
+0x5830,0x5944,0x5BB4,0x5EF6,0x6028,0x63A9,0x63F4,0x6CBF,
+0x6F14,0x708E,0x7114,0x7159,0x71D5,0x733F,0x7E01,0x8276,
+0x82D1,0x8597,0x9060,0x925B,0x9D1B,0x5869,0x65BC,0x6C5A,
+0x7525,0x51F9,0x592E,0x5965,0x5F80,0x5FDC};
+
+/* page 10 0x3221-0x327E */
+static uint16 tab_jisx0208_uni10[]={
+0x62BC,0x65FA,0x6A2A,0x6B27,0x6BB4,0x738B,0x7FC1,0x8956,
+0x9D2C,0x9D0E,0x9EC4,0x5CA1,0x6C96,0x837B,0x5104,0x5C4B,
+0x61B6,0x81C6,0x6876,0x7261,0x4E59,0x4FFA,0x5378,0x6069,
+0x6E29,0x7A4F,0x97F3,0x4E0B,0x5316,0x4EEE,0x4F55,0x4F3D,
+0x4FA1,0x4F73,0x52A0,0x53EF,0x5609,0x590F,0x5AC1,0x5BB6,
+0x5BE1,0x79D1,0x6687,0x679C,0x67B6,0x6B4C,0x6CB3,0x706B,
+0x73C2,0x798D,0x79BE,0x7A3C,0x7B87,0x82B1,0x82DB,0x8304,
+0x8377,0x83EF,0x83D3,0x8766,0x8AB2,0x5629,0x8CA8,0x8FE6,
+0x904E,0x971E,0x868A,0x4FC4,0x5CE8,0x6211,0x7259,0x753B,
+0x81E5,0x82BD,0x86FE,0x8CC0,0x96C5,0x9913,0x99D5,0x4ECB,
+0x4F1A,0x89E3,0x56DE,0x584A,0x58CA,0x5EFB,0x5FEB,0x602A,
+0x6094,0x6062,0x61D0,0x6212,0x62D0,0x6539};
+
+/* page 11 0x3321-0x337E */
+static uint16 tab_jisx0208_uni11[]={
+0x9B41,0x6666,0x68B0,0x6D77,0x7070,0x754C,0x7686,0x7D75,
+0x82A5,0x87F9,0x958B,0x968E,0x8C9D,0x51F1,0x52BE,0x5916,
+0x54B3,0x5BB3,0x5D16,0x6168,0x6982,0x6DAF,0x788D,0x84CB,
+0x8857,0x8A72,0x93A7,0x9AB8,0x6D6C,0x99A8,0x86D9,0x57A3,
+0x67FF,0x86CE,0x920E,0x5283,0x5687,0x5404,0x5ED3,0x62E1,
+0x64B9,0x683C,0x6838,0x6BBB,0x7372,0x78BA,0x7A6B,0x899A,
+0x89D2,0x8D6B,0x8F03,0x90ED,0x95A3,0x9694,0x9769,0x5B66,
+0x5CB3,0x697D,0x984D,0x984E,0x639B,0x7B20,0x6A2B,0x6A7F,
+0x68B6,0x9C0D,0x6F5F,0x5272,0x559D,0x6070,0x62EC,0x6D3B,
+0x6E07,0x6ED1,0x845B,0x8910,0x8F44,0x4E14,0x9C39,0x53F6,
+0x691B,0x6A3A,0x9784,0x682A,0x515C,0x7AC3,0x84B2,0x91DC,
+0x938C,0x565B,0x9D28,0x6822,0x8305,0x8431};
+
+/* page 12 0x3421-0x347E */
+static uint16 tab_jisx0208_uni12[]={
+0x7CA5,0x5208,0x82C5,0x74E6,0x4E7E,0x4F83,0x51A0,0x5BD2,
+0x520A,0x52D8,0x52E7,0x5DFB,0x559A,0x582A,0x59E6,0x5B8C,
+0x5B98,0x5BDB,0x5E72,0x5E79,0x60A3,0x611F,0x6163,0x61BE,
+0x63DB,0x6562,0x67D1,0x6853,0x68FA,0x6B3E,0x6B53,0x6C57,
+0x6F22,0x6F97,0x6F45,0x74B0,0x7518,0x76E3,0x770B,0x7AFF,
+0x7BA1,0x7C21,0x7DE9,0x7F36,0x7FF0,0x809D,0x8266,0x839E,
+0x89B3,0x8ACC,0x8CAB,0x9084,0x9451,0x9593,0x9591,0x95A2,
+0x9665,0x97D3,0x9928,0x8218,0x4E38,0x542B,0x5CB8,0x5DCC,
+0x73A9,0x764C,0x773C,0x5CA9,0x7FEB,0x8D0B,0x96C1,0x9811,
+0x9854,0x9858,0x4F01,0x4F0E,0x5371,0x559C,0x5668,0x57FA,
+0x5947,0x5B09,0x5BC4,0x5C90,0x5E0C,0x5E7E,0x5FCC,0x63EE,
+0x673A,0x65D7,0x65E2,0x671F,0x68CB,0x68C4};
+
+/* page 13 0x3521-0x357E */
+static uint16 tab_jisx0208_uni13[]={
+0x6A5F,0x5E30,0x6BC5,0x6C17,0x6C7D,0x757F,0x7948,0x5B63,
+0x7A00,0x7D00,0x5FBD,0x898F,0x8A18,0x8CB4,0x8D77,0x8ECC,
+0x8F1D,0x98E2,0x9A0E,0x9B3C,0x4E80,0x507D,0x5100,0x5993,
+0x5B9C,0x622F,0x6280,0x64EC,0x6B3A,0x72A0,0x7591,0x7947,
+0x7FA9,0x87FB,0x8ABC,0x8B70,0x63AC,0x83CA,0x97A0,0x5409,
+0x5403,0x55AB,0x6854,0x6A58,0x8A70,0x7827,0x6775,0x9ECD,
+0x5374,0x5BA2,0x811A,0x8650,0x9006,0x4E18,0x4E45,0x4EC7,
+0x4F11,0x53CA,0x5438,0x5BAE,0x5F13,0x6025,0x6551,0x673D,
+0x6C42,0x6C72,0x6CE3,0x7078,0x7403,0x7A76,0x7AAE,0x7B08,
+0x7D1A,0x7CFE,0x7D66,0x65E7,0x725B,0x53BB,0x5C45,0x5DE8,
+0x62D2,0x62E0,0x6319,0x6E20,0x865A,0x8A31,0x8DDD,0x92F8,
+0x6F01,0x79A6,0x9B5A,0x4EA8,0x4EAB,0x4EAC};
+
+/* page 14 0x3621-0x367E */
+static uint16 tab_jisx0208_uni14[]={
+0x4F9B,0x4FA0,0x50D1,0x5147,0x7AF6,0x5171,0x51F6,0x5354,
+0x5321,0x537F,0x53EB,0x55AC,0x5883,0x5CE1,0x5F37,0x5F4A,
+0x602F,0x6050,0x606D,0x631F,0x6559,0x6A4B,0x6CC1,0x72C2,
+0x72ED,0x77EF,0x80F8,0x8105,0x8208,0x854E,0x90F7,0x93E1,
+0x97FF,0x9957,0x9A5A,0x4EF0,0x51DD,0x5C2D,0x6681,0x696D,
+0x5C40,0x66F2,0x6975,0x7389,0x6850,0x7C81,0x50C5,0x52E4,
+0x5747,0x5DFE,0x9326,0x65A4,0x6B23,0x6B3D,0x7434,0x7981,
+0x79BD,0x7B4B,0x7DCA,0x82B9,0x83CC,0x887F,0x895F,0x8B39,
+0x8FD1,0x91D1,0x541F,0x9280,0x4E5D,0x5036,0x53E5,0x533A,
+0x72D7,0x7396,0x77E9,0x82E6,0x8EAF,0x99C6,0x99C8,0x99D2,
+0x5177,0x611A,0x865E,0x55B0,0x7A7A,0x5076,0x5BD3,0x9047,
+0x9685,0x4E32,0x6ADB,0x91E7,0x5C51,0x5C48};
+
+/* page 15 0x3721-0x377E */
+static uint16 tab_jisx0208_uni15[]={
+0x6398,0x7A9F,0x6C93,0x9774,0x8F61,0x7AAA,0x718A,0x9688,
+0x7C82,0x6817,0x7E70,0x6851,0x936C,0x52F2,0x541B,0x85AB,
+0x8A13,0x7FA4,0x8ECD,0x90E1,0x5366,0x8888,0x7941,0x4FC2,
+0x50BE,0x5211,0x5144,0x5553,0x572D,0x73EA,0x578B,0x5951,
+0x5F62,0x5F84,0x6075,0x6176,0x6167,0x61A9,0x63B2,0x643A,
+0x656C,0x666F,0x6842,0x6E13,0x7566,0x7A3D,0x7CFB,0x7D4C,
+0x7D99,0x7E4B,0x7F6B,0x830E,0x834A,0x86CD,0x8A08,0x8A63,
+0x8B66,0x8EFD,0x981A,0x9D8F,0x82B8,0x8FCE,0x9BE8,0x5287,
+0x621F,0x6483,0x6FC0,0x9699,0x6841,0x5091,0x6B20,0x6C7A,
+0x6F54,0x7A74,0x7D50,0x8840,0x8A23,0x6708,0x4EF6,0x5039,
+0x5026,0x5065,0x517C,0x5238,0x5263,0x55A7,0x570F,0x5805,
+0x5ACC,0x5EFA,0x61B2,0x61F8,0x62F3,0x6372};
+
+/* page 16 0x3821-0x387E */
+static uint16 tab_jisx0208_uni16[]={
+0x691C,0x6A29,0x727D,0x72AC,0x732E,0x7814,0x786F,0x7D79,
+0x770C,0x80A9,0x898B,0x8B19,0x8CE2,0x8ED2,0x9063,0x9375,
+0x967A,0x9855,0x9A13,0x9E78,0x5143,0x539F,0x53B3,0x5E7B,
+0x5F26,0x6E1B,0x6E90,0x7384,0x73FE,0x7D43,0x8237,0x8A00,
+0x8AFA,0x9650,0x4E4E,0x500B,0x53E4,0x547C,0x56FA,0x59D1,
+0x5B64,0x5DF1,0x5EAB,0x5F27,0x6238,0x6545,0x67AF,0x6E56,
+0x72D0,0x7CCA,0x88B4,0x80A1,0x80E1,0x83F0,0x864E,0x8A87,
+0x8DE8,0x9237,0x96C7,0x9867,0x9F13,0x4E94,0x4E92,0x4F0D,
+0x5348,0x5449,0x543E,0x5A2F,0x5F8C,0x5FA1,0x609F,0x68A7,
+0x6A8E,0x745A,0x7881,0x8A9E,0x8AA4,0x8B77,0x9190,0x4E5E,
+0x9BC9,0x4EA4,0x4F7C,0x4FAF,0x5019,0x5016,0x5149,0x516C,
+0x529F,0x52B9,0x52FE,0x539A,0x53E3,0x5411};
+
+/* page 17 0x3921-0x397E */
+static uint16 tab_jisx0208_uni17[]={
+0x540E,0x5589,0x5751,0x57A2,0x597D,0x5B54,0x5B5D,0x5B8F,
+0x5DE5,0x5DE7,0x5DF7,0x5E78,0x5E83,0x5E9A,0x5EB7,0x5F18,
+0x6052,0x614C,0x6297,0x62D8,0x63A7,0x653B,0x6602,0x6643,
+0x66F4,0x676D,0x6821,0x6897,0x69CB,0x6C5F,0x6D2A,0x6D69,
+0x6E2F,0x6E9D,0x7532,0x7687,0x786C,0x7A3F,0x7CE0,0x7D05,
+0x7D18,0x7D5E,0x7DB1,0x8015,0x8003,0x80AF,0x80B1,0x8154,
+0x818F,0x822A,0x8352,0x884C,0x8861,0x8B1B,0x8CA2,0x8CFC,
+0x90CA,0x9175,0x9271,0x783F,0x92FC,0x95A4,0x964D,0x9805,
+0x9999,0x9AD8,0x9D3B,0x525B,0x52AB,0x53F7,0x5408,0x58D5,
+0x62F7,0x6FE0,0x8C6A,0x8F5F,0x9EB9,0x514B,0x523B,0x544A,
+0x56FD,0x7A40,0x9177,0x9D60,0x9ED2,0x7344,0x6F09,0x8170,
+0x7511,0x5FFD,0x60DA,0x9AA8,0x72DB,0x8FBC};
+
+/* page 18 0x3A21-0x3A7E */
+static uint16 tab_jisx0208_uni18[]={
+0x6B64,0x9803,0x4ECA,0x56F0,0x5764,0x58BE,0x5A5A,0x6068,
+0x61C7,0x660F,0x6606,0x6839,0x68B1,0x6DF7,0x75D5,0x7D3A,
+0x826E,0x9B42,0x4E9B,0x4F50,0x53C9,0x5506,0x5D6F,0x5DE6,
+0x5DEE,0x67FB,0x6C99,0x7473,0x7802,0x8A50,0x9396,0x88DF,
+0x5750,0x5EA7,0x632B,0x50B5,0x50AC,0x518D,0x6700,0x54C9,
+0x585E,0x59BB,0x5BB0,0x5F69,0x624D,0x63A1,0x683D,0x6B73,
+0x6E08,0x707D,0x91C7,0x7280,0x7815,0x7826,0x796D,0x658E,
+0x7D30,0x83DC,0x88C1,0x8F09,0x969B,0x5264,0x5728,0x6750,
+0x7F6A,0x8CA1,0x51B4,0x5742,0x962A,0x583A,0x698A,0x80B4,
+0x54B2,0x5D0E,0x57FC,0x7895,0x9DFA,0x4F5C,0x524A,0x548B,
+0x643E,0x6628,0x6714,0x67F5,0x7A84,0x7B56,0x7D22,0x932F,
+0x685C,0x9BAD,0x7B39,0x5319,0x518A,0x5237};
+
+/* page 19 0x3B21-0x3B7E */
+static uint16 tab_jisx0208_uni19[]={
+0x5BDF,0x62F6,0x64AE,0x64E6,0x672D,0x6BBA,0x85A9,0x96D1,
+0x7690,0x9BD6,0x634C,0x9306,0x9BAB,0x76BF,0x6652,0x4E09,
+0x5098,0x53C2,0x5C71,0x60E8,0x6492,0x6563,0x685F,0x71E6,
+0x73CA,0x7523,0x7B97,0x7E82,0x8695,0x8B83,0x8CDB,0x9178,
+0x9910,0x65AC,0x66AB,0x6B8B,0x4ED5,0x4ED4,0x4F3A,0x4F7F,
+0x523A,0x53F8,0x53F2,0x55E3,0x56DB,0x58EB,0x59CB,0x59C9,
+0x59FF,0x5B50,0x5C4D,0x5E02,0x5E2B,0x5FD7,0x601D,0x6307,
+0x652F,0x5B5C,0x65AF,0x65BD,0x65E8,0x679D,0x6B62,0x6B7B,
+0x6C0F,0x7345,0x7949,0x79C1,0x7CF8,0x7D19,0x7D2B,0x80A2,
+0x8102,0x81F3,0x8996,0x8A5E,0x8A69,0x8A66,0x8A8C,0x8AEE,
+0x8CC7,0x8CDC,0x96CC,0x98FC,0x6B6F,0x4E8B,0x4F3C,0x4F8D,
+0x5150,0x5B57,0x5BFA,0x6148,0x6301,0x6642};
+
+/* page 20 0x3C21-0x3C7E */
+static uint16 tab_jisx0208_uni20[]={
+0x6B21,0x6ECB,0x6CBB,0x723E,0x74BD,0x75D4,0x78C1,0x793A,
+0x800C,0x8033,0x81EA,0x8494,0x8F9E,0x6C50,0x9E7F,0x5F0F,
+0x8B58,0x9D2B,0x7AFA,0x8EF8,0x5B8D,0x96EB,0x4E03,0x53F1,
+0x57F7,0x5931,0x5AC9,0x5BA4,0x6089,0x6E7F,0x6F06,0x75BE,
+0x8CEA,0x5B9F,0x8500,0x7BE0,0x5072,0x67F4,0x829D,0x5C61,
+0x854A,0x7E1E,0x820E,0x5199,0x5C04,0x6368,0x8D66,0x659C,
+0x716E,0x793E,0x7D17,0x8005,0x8B1D,0x8ECA,0x906E,0x86C7,
+0x90AA,0x501F,0x52FA,0x5C3A,0x6753,0x707C,0x7235,0x914C,
+0x91C8,0x932B,0x82E5,0x5BC2,0x5F31,0x60F9,0x4E3B,0x53D6,
+0x5B88,0x624B,0x6731,0x6B8A,0x72E9,0x73E0,0x7A2E,0x816B,
+0x8DA3,0x9152,0x9996,0x5112,0x53D7,0x546A,0x5BFF,0x6388,
+0x6A39,0x7DAC,0x9700,0x56DA,0x53CE,0x5468};
+
+/* page 21 0x3D21-0x3D7E */
+static uint16 tab_jisx0208_uni21[]={
+0x5B97,0x5C31,0x5DDE,0x4FEE,0x6101,0x62FE,0x6D32,0x79C0,
+0x79CB,0x7D42,0x7E4D,0x7FD2,0x81ED,0x821F,0x8490,0x8846,
+0x8972,0x8B90,0x8E74,0x8F2F,0x9031,0x914B,0x916C,0x96C6,
+0x919C,0x4EC0,0x4F4F,0x5145,0x5341,0x5F93,0x620E,0x67D4,
+0x6C41,0x6E0B,0x7363,0x7E26,0x91CD,0x9283,0x53D4,0x5919,
+0x5BBF,0x6DD1,0x795D,0x7E2E,0x7C9B,0x587E,0x719F,0x51FA,
+0x8853,0x8FF0,0x4FCA,0x5CFB,0x6625,0x77AC,0x7AE3,0x821C,
+0x99FF,0x51C6,0x5FAA,0x65EC,0x696F,0x6B89,0x6DF3,0x6E96,
+0x6F64,0x76FE,0x7D14,0x5DE1,0x9075,0x9187,0x9806,0x51E6,
+0x521D,0x6240,0x6691,0x66D9,0x6E1A,0x5EB6,0x7DD2,0x7F72,
+0x66F8,0x85AF,0x85F7,0x8AF8,0x52A9,0x53D9,0x5973,0x5E8F,
+0x5F90,0x6055,0x92E4,0x9664,0x50B7,0x511F};
+
+/* page 22 0x3E21-0x3E7E */
+static uint16 tab_jisx0208_uni22[]={
+0x52DD,0x5320,0x5347,0x53EC,0x54E8,0x5546,0x5531,0x5617,
+0x5968,0x59BE,0x5A3C,0x5BB5,0x5C06,0x5C0F,0x5C11,0x5C1A,
+0x5E84,0x5E8A,0x5EE0,0x5F70,0x627F,0x6284,0x62DB,0x638C,
+0x6377,0x6607,0x660C,0x662D,0x6676,0x677E,0x68A2,0x6A1F,
+0x6A35,0x6CBC,0x6D88,0x6E09,0x6E58,0x713C,0x7126,0x7167,
+0x75C7,0x7701,0x785D,0x7901,0x7965,0x79F0,0x7AE0,0x7B11,
+0x7CA7,0x7D39,0x8096,0x83D6,0x848B,0x8549,0x885D,0x88F3,
+0x8A1F,0x8A3C,0x8A54,0x8A73,0x8C61,0x8CDE,0x91A4,0x9266,
+0x937E,0x9418,0x969C,0x9798,0x4E0A,0x4E08,0x4E1E,0x4E57,
+0x5197,0x5270,0x57CE,0x5834,0x58CC,0x5B22,0x5E38,0x60C5,
+0x64FE,0x6761,0x6756,0x6D44,0x72B6,0x7573,0x7A63,0x84B8,
+0x8B72,0x91B8,0x9320,0x5631,0x57F4,0x98FE};
+
+/* page 23 0x3F21-0x3F7E */
+static uint16 tab_jisx0208_uni23[]={
+0x62ED,0x690D,0x6B96,0x71ED,0x7E54,0x8077,0x8272,0x89E6,
+0x98DF,0x8755,0x8FB1,0x5C3B,0x4F38,0x4FE1,0x4FB5,0x5507,
+0x5A20,0x5BDD,0x5BE9,0x5FC3,0x614E,0x632F,0x65B0,0x664B,
+0x68EE,0x699B,0x6D78,0x6DF1,0x7533,0x75B9,0x771F,0x795E,
+0x79E6,0x7D33,0x81E3,0x82AF,0x85AA,0x89AA,0x8A3A,0x8EAB,
+0x8F9B,0x9032,0x91DD,0x9707,0x4EBA,0x4EC1,0x5203,0x5875,
+0x58EC,0x5C0B,0x751A,0x5C3D,0x814E,0x8A0A,0x8FC5,0x9663,
+0x976D,0x7B25,0x8ACF,0x9808,0x9162,0x56F3,0x53A8,0x9017,
+0x5439,0x5782,0x5E25,0x63A8,0x6C34,0x708A,0x7761,0x7C8B,
+0x7FE0,0x8870,0x9042,0x9154,0x9310,0x9318,0x968F,0x745E,
+0x9AC4,0x5D07,0x5D69,0x6570,0x67A2,0x8DA8,0x96DB,0x636E,
+0x6749,0x6919,0x83C5,0x9817,0x96C0,0x88FE};
+
+/* page 24 0x4021-0x407E */
+static uint16 tab_jisx0208_uni24[]={
+0x6F84,0x647A,0x5BF8,0x4E16,0x702C,0x755D,0x662F,0x51C4,
+0x5236,0x52E2,0x59D3,0x5F81,0x6027,0x6210,0x653F,0x6574,
+0x661F,0x6674,0x68F2,0x6816,0x6B63,0x6E05,0x7272,0x751F,
+0x76DB,0x7CBE,0x8056,0x58F0,0x88FD,0x897F,0x8AA0,0x8A93,
+0x8ACB,0x901D,0x9192,0x9752,0x9759,0x6589,0x7A0E,0x8106,
+0x96BB,0x5E2D,0x60DC,0x621A,0x65A5,0x6614,0x6790,0x77F3,
+0x7A4D,0x7C4D,0x7E3E,0x810A,0x8CAC,0x8D64,0x8DE1,0x8E5F,
+0x78A9,0x5207,0x62D9,0x63A5,0x6442,0x6298,0x8A2D,0x7A83,
+0x7BC0,0x8AAC,0x96EA,0x7D76,0x820C,0x8749,0x4ED9,0x5148,
+0x5343,0x5360,0x5BA3,0x5C02,0x5C16,0x5DDD,0x6226,0x6247,
+0x64B0,0x6813,0x6834,0x6CC9,0x6D45,0x6D17,0x67D3,0x6F5C,
+0x714E,0x717D,0x65CB,0x7A7F,0x7BAD,0x7DDA};
+
+/* page 25 0x4121-0x417E */
+static uint16 tab_jisx0208_uni25[]={
+0x7E4A,0x7FA8,0x817A,0x821B,0x8239,0x85A6,0x8A6E,0x8CCE,
+0x8DF5,0x9078,0x9077,0x92AD,0x9291,0x9583,0x9BAE,0x524D,
+0x5584,0x6F38,0x7136,0x5168,0x7985,0x7E55,0x81B3,0x7CCE,
+0x564C,0x5851,0x5CA8,0x63AA,0x66FE,0x66FD,0x695A,0x72D9,
+0x758F,0x758E,0x790E,0x7956,0x79DF,0x7C97,0x7D20,0x7D44,
+0x8607,0x8A34,0x963B,0x9061,0x9F20,0x50E7,0x5275,0x53CC,
+0x53E2,0x5009,0x55AA,0x58EE,0x594F,0x723D,0x5B8B,0x5C64,
+0x531D,0x60E3,0x60F3,0x635C,0x6383,0x633F,0x63BB,0x64CD,
+0x65E9,0x66F9,0x5DE3,0x69CD,0x69FD,0x6F15,0x71E5,0x4E89,
+0x75E9,0x76F8,0x7A93,0x7CDF,0x7DCF,0x7D9C,0x8061,0x8349,
+0x8358,0x846C,0x84BC,0x85FB,0x88C5,0x8D70,0x9001,0x906D,
+0x9397,0x971C,0x9A12,0x50CF,0x5897,0x618E};
+
+/* page 26 0x4221-0x427E */
+static uint16 tab_jisx0208_uni26[]={
+0x81D3,0x8535,0x8D08,0x9020,0x4FC3,0x5074,0x5247,0x5373,
+0x606F,0x6349,0x675F,0x6E2C,0x8DB3,0x901F,0x4FD7,0x5C5E,
+0x8CCA,0x65CF,0x7D9A,0x5352,0x8896,0x5176,0x63C3,0x5B58,
+0x5B6B,0x5C0A,0x640D,0x6751,0x905C,0x4ED6,0x591A,0x592A,
+0x6C70,0x8A51,0x553E,0x5815,0x59A5,0x60F0,0x6253,0x67C1,
+0x8235,0x6955,0x9640,0x99C4,0x9A28,0x4F53,0x5806,0x5BFE,
+0x8010,0x5CB1,0x5E2F,0x5F85,0x6020,0x614B,0x6234,0x66FF,
+0x6CF0,0x6EDE,0x80CE,0x817F,0x82D4,0x888B,0x8CB8,0x9000,
+0x902E,0x968A,0x9EDB,0x9BDB,0x4EE3,0x53F0,0x5927,0x7B2C,
+0x918D,0x984C,0x9DF9,0x6EDD,0x7027,0x5353,0x5544,0x5B85,
+0x6258,0x629E,0x62D3,0x6CA2,0x6FEF,0x7422,0x8A17,0x9438,
+0x6FC1,0x8AFE,0x8338,0x51E7,0x86F8,0x53EA};
+
+/* page 27 0x4321-0x437E */
+static uint16 tab_jisx0208_uni27[]={
+0x53E9,0x4F46,0x9054,0x8FB0,0x596A,0x8131,0x5DFD,0x7AEA,
+0x8FBF,0x68DA,0x8C37,0x72F8,0x9C48,0x6A3D,0x8AB0,0x4E39,
+0x5358,0x5606,0x5766,0x62C5,0x63A2,0x65E6,0x6B4E,0x6DE1,
+0x6E5B,0x70AD,0x77ED,0x7AEF,0x7BAA,0x7DBB,0x803D,0x80C6,
+0x86CB,0x8A95,0x935B,0x56E3,0x58C7,0x5F3E,0x65AD,0x6696,
+0x6A80,0x6BB5,0x7537,0x8AC7,0x5024,0x77E5,0x5730,0x5F1B,
+0x6065,0x667A,0x6C60,0x75F4,0x7A1A,0x7F6E,0x81F4,0x8718,
+0x9045,0x99B3,0x7BC9,0x755C,0x7AF9,0x7B51,0x84C4,0x9010,
+0x79E9,0x7A92,0x8336,0x5AE1,0x7740,0x4E2D,0x4EF2,0x5B99,
+0x5FE0,0x62BD,0x663C,0x67F1,0x6CE8,0x866B,0x8877,0x8A3B,
+0x914E,0x92F3,0x99D0,0x6A17,0x7026,0x732A,0x82E7,0x8457,
+0x8CAF,0x4E01,0x5146,0x51CB,0x558B,0x5BF5};
+
+/* page 28 0x4421-0x447E */
+static uint16 tab_jisx0208_uni28[]={
+0x5E16,0x5E33,0x5E81,0x5F14,0x5F35,0x5F6B,0x5FB4,0x61F2,
+0x6311,0x66A2,0x671D,0x6F6E,0x7252,0x753A,0x773A,0x8074,
+0x8139,0x8178,0x8776,0x8ABF,0x8ADC,0x8D85,0x8DF3,0x929A,
+0x9577,0x9802,0x9CE5,0x52C5,0x6357,0x76F4,0x6715,0x6C88,
+0x73CD,0x8CC3,0x93AE,0x9673,0x6D25,0x589C,0x690E,0x69CC,
+0x8FFD,0x939A,0x75DB,0x901A,0x585A,0x6802,0x63B4,0x69FB,
+0x4F43,0x6F2C,0x67D8,0x8FBB,0x8526,0x7DB4,0x9354,0x693F,
+0x6F70,0x576A,0x58F7,0x5B2C,0x7D2C,0x722A,0x540A,0x91E3,
+0x9DB4,0x4EAD,0x4F4E,0x505C,0x5075,0x5243,0x8C9E,0x5448,
+0x5824,0x5B9A,0x5E1D,0x5E95,0x5EAD,0x5EF7,0x5F1F,0x608C,
+0x62B5,0x633A,0x63D0,0x68AF,0x6C40,0x7887,0x798E,0x7A0B,
+0x7DE0,0x8247,0x8A02,0x8AE6,0x8E44,0x9013};
+
+/* page 29 0x4521-0x457E */
+static uint16 tab_jisx0208_uni29[]={
+0x90B8,0x912D,0x91D8,0x9F0E,0x6CE5,0x6458,0x64E2,0x6575,
+0x6EF4,0x7684,0x7B1B,0x9069,0x93D1,0x6EBA,0x54F2,0x5FB9,
+0x64A4,0x8F4D,0x8FED,0x9244,0x5178,0x586B,0x5929,0x5C55,
+0x5E97,0x6DFB,0x7E8F,0x751C,0x8CBC,0x8EE2,0x985B,0x70B9,
+0x4F1D,0x6BBF,0x6FB1,0x7530,0x96FB,0x514E,0x5410,0x5835,
+0x5857,0x59AC,0x5C60,0x5F92,0x6597,0x675C,0x6E21,0x767B,
+0x83DF,0x8CED,0x9014,0x90FD,0x934D,0x7825,0x783A,0x52AA,
+0x5EA6,0x571F,0x5974,0x6012,0x5012,0x515A,0x51AC,0x51CD,
+0x5200,0x5510,0x5854,0x5858,0x5957,0x5B95,0x5CF6,0x5D8B,
+0x60BC,0x6295,0x642D,0x6771,0x6843,0x68BC,0x68DF,0x76D7,
+0x6DD8,0x6E6F,0x6D9B,0x706F,0x71C8,0x5F53,0x75D8,0x7977,
+0x7B49,0x7B54,0x7B52,0x7CD6,0x7D71,0x5230};
+
+/* page 30 0x4621-0x467E */
+static uint16 tab_jisx0208_uni30[]={
+0x8463,0x8569,0x85E4,0x8A0E,0x8B04,0x8C46,0x8E0F,0x9003,
+0x900F,0x9419,0x9676,0x982D,0x9A30,0x95D8,0x50CD,0x52D5,
+0x540C,0x5802,0x5C0E,0x61A7,0x649E,0x6D1E,0x77B3,0x7AE5,
+0x80F4,0x8404,0x9053,0x9285,0x5CE0,0x9D07,0x533F,0x5F97,
+0x5FB3,0x6D9C,0x7279,0x7763,0x79BF,0x7BE4,0x6BD2,0x72EC,
+0x8AAD,0x6803,0x6A61,0x51F8,0x7A81,0x6934,0x5C4A,0x9CF6,
+0x82EB,0x5BC5,0x9149,0x701E,0x5678,0x5C6F,0x60C7,0x6566,
+0x6C8C,0x8C5A,0x9041,0x9813,0x5451,0x66C7,0x920D,0x5948,
+0x90A3,0x5185,0x4E4D,0x51EA,0x8599,0x8B0E,0x7058,0x637A,
+0x934B,0x6962,0x99B4,0x7E04,0x7577,0x5357,0x6960,0x8EDF,
+0x96E3,0x6C5D,0x4E8C,0x5C3C,0x5F10,0x8FE9,0x5302,0x8CD1,
+0x8089,0x8679,0x5EFF,0x65E5,0x4E73,0x5165};
+
+/* page 31 0x4721-0x477E */
+static uint16 tab_jisx0208_uni31[]={
+0x5982,0x5C3F,0x97EE,0x4EFB,0x598A,0x5FCD,0x8A8D,0x6FE1,
+0x79B0,0x7962,0x5BE7,0x8471,0x732B,0x71B1,0x5E74,0x5FF5,
+0x637B,0x649A,0x71C3,0x7C98,0x4E43,0x5EFC,0x4E4B,0x57DC,
+0x56A2,0x60A9,0x6FC3,0x7D0D,0x80FD,0x8133,0x81BF,0x8FB2,
+0x8997,0x86A4,0x5DF4,0x628A,0x64AD,0x8987,0x6777,0x6CE2,
+0x6D3E,0x7436,0x7834,0x5A46,0x7F75,0x82AD,0x99AC,0x4FF3,
+0x5EC3,0x62DD,0x6392,0x6557,0x676F,0x76C3,0x724C,0x80CC,
+0x80BA,0x8F29,0x914D,0x500D,0x57F9,0x5A92,0x6885,0x6973,
+0x7164,0x72FD,0x8CB7,0x58F2,0x8CE0,0x966A,0x9019,0x877F,
+0x79E4,0x77E7,0x8429,0x4F2F,0x5265,0x535A,0x62CD,0x67CF,
+0x6CCA,0x767D,0x7B94,0x7C95,0x8236,0x8584,0x8FEB,0x66DD,
+0x6F20,0x7206,0x7E1B,0x83AB,0x99C1,0x9EA6};
+
+/* page 32 0x4821-0x487E */
+static uint16 tab_jisx0208_uni32[]={
+0x51FD,0x7BB1,0x7872,0x7BB8,0x8087,0x7B48,0x6AE8,0x5E61,
+0x808C,0x7551,0x7560,0x516B,0x9262,0x6E8C,0x767A,0x9197,
+0x9AEA,0x4F10,0x7F70,0x629C,0x7B4F,0x95A5,0x9CE9,0x567A,
+0x5859,0x86E4,0x96BC,0x4F34,0x5224,0x534A,0x53CD,0x53DB,
+0x5E06,0x642C,0x6591,0x677F,0x6C3E,0x6C4E,0x7248,0x72AF,
+0x73ED,0x7554,0x7E41,0x822C,0x85E9,0x8CA9,0x7BC4,0x91C6,
+0x7169,0x9812,0x98EF,0x633D,0x6669,0x756A,0x76E4,0x78D0,
+0x8543,0x86EE,0x532A,0x5351,0x5426,0x5983,0x5E87,0x5F7C,
+0x60B2,0x6249,0x6279,0x62AB,0x6590,0x6BD4,0x6CCC,0x75B2,
+0x76AE,0x7891,0x79D8,0x7DCB,0x7F77,0x80A5,0x88AB,0x8AB9,
+0x8CBB,0x907F,0x975E,0x98DB,0x6A0B,0x7C38,0x5099,0x5C3E,
+0x5FAE,0x6787,0x6BD8,0x7435,0x7709,0x7F8E};
+
+/* page 33 0x4921-0x497E */
+static uint16 tab_jisx0208_uni33[]={
+0x9F3B,0x67CA,0x7A17,0x5339,0x758B,0x9AED,0x5F66,0x819D,
+0x83F1,0x8098,0x5F3C,0x5FC5,0x7562,0x7B46,0x903C,0x6867,
+0x59EB,0x5A9B,0x7D10,0x767E,0x8B2C,0x4FF5,0x5F6A,0x6A19,
+0x6C37,0x6F02,0x74E2,0x7968,0x8868,0x8A55,0x8C79,0x5EDF,
+0x63CF,0x75C5,0x79D2,0x82D7,0x9328,0x92F2,0x849C,0x86ED,
+0x9C2D,0x54C1,0x5F6C,0x658C,0x6D5C,0x7015,0x8CA7,0x8CD3,
+0x983B,0x654F,0x74F6,0x4E0D,0x4ED8,0x57E0,0x592B,0x5A66,
+0x5BCC,0x51A8,0x5E03,0x5E9C,0x6016,0x6276,0x6577,0x65A7,
+0x666E,0x6D6E,0x7236,0x7B26,0x8150,0x819A,0x8299,0x8B5C,
+0x8CA0,0x8CE6,0x8D74,0x961C,0x9644,0x4FAE,0x64AB,0x6B66,
+0x821E,0x8461,0x856A,0x90E8,0x5C01,0x6953,0x98A8,0x847A,
+0x8557,0x4F0F,0x526F,0x5FA9,0x5E45,0x670D};
+
+/* page 34 0x4A21-0x4A7E */
+static uint16 tab_jisx0208_uni34[]={
+0x798F,0x8179,0x8907,0x8986,0x6DF5,0x5F17,0x6255,0x6CB8,
+0x4ECF,0x7269,0x9B92,0x5206,0x543B,0x5674,0x58B3,0x61A4,
+0x626E,0x711A,0x596E,0x7C89,0x7CDE,0x7D1B,0x96F0,0x6587,
+0x805E,0x4E19,0x4F75,0x5175,0x5840,0x5E63,0x5E73,0x5F0A,
+0x67C4,0x4E26,0x853D,0x9589,0x965B,0x7C73,0x9801,0x50FB,
+0x58C1,0x7656,0x78A7,0x5225,0x77A5,0x8511,0x7B86,0x504F,
+0x5909,0x7247,0x7BC7,0x7DE8,0x8FBA,0x8FD4,0x904D,0x4FBF,
+0x52C9,0x5A29,0x5F01,0x97AD,0x4FDD,0x8217,0x92EA,0x5703,
+0x6355,0x6B69,0x752B,0x88DC,0x8F14,0x7A42,0x52DF,0x5893,
+0x6155,0x620A,0x66AE,0x6BCD,0x7C3F,0x83E9,0x5023,0x4FF8,
+0x5305,0x5446,0x5831,0x5949,0x5B9D,0x5CF0,0x5CEF,0x5D29,
+0x5E96,0x62B1,0x6367,0x653E,0x65B9,0x670B};
+
+/* page 35 0x4B21-0x4B7E */
+static uint16 tab_jisx0208_uni35[]={
+0x6CD5,0x6CE1,0x70F9,0x7832,0x7E2B,0x80DE,0x82B3,0x840C,
+0x84EC,0x8702,0x8912,0x8A2A,0x8C4A,0x90A6,0x92D2,0x98FD,
+0x9CF3,0x9D6C,0x4E4F,0x4EA1,0x508D,0x5256,0x574A,0x59A8,
+0x5E3D,0x5FD8,0x5FD9,0x623F,0x66B4,0x671B,0x67D0,0x68D2,
+0x5192,0x7D21,0x80AA,0x81A8,0x8B00,0x8C8C,0x8CBF,0x927E,
+0x9632,0x5420,0x982C,0x5317,0x50D5,0x535C,0x58A8,0x64B2,
+0x6734,0x7267,0x7766,0x7A46,0x91E6,0x52C3,0x6CA1,0x6B86,
+0x5800,0x5E4C,0x5954,0x672C,0x7FFB,0x51E1,0x76C6,0x6469,
+0x78E8,0x9B54,0x9EBB,0x57CB,0x59B9,0x6627,0x679A,0x6BCE,
+0x54E9,0x69D9,0x5E55,0x819C,0x6795,0x9BAA,0x67FE,0x9C52,
+0x685D,0x4EA6,0x4FE3,0x53C8,0x62B9,0x672B,0x6CAB,0x8FC4,
+0x4FAD,0x7E6D,0x9EBF,0x4E07,0x6162,0x6E80};
+
+/* page 36 0x4C21-0x4C7E */
+static uint16 tab_jisx0208_uni36[]={
+0x6F2B,0x8513,0x5473,0x672A,0x9B45,0x5DF3,0x7B95,0x5CAC,
+0x5BC6,0x871C,0x6E4A,0x84D1,0x7A14,0x8108,0x5999,0x7C8D,
+0x6C11,0x7720,0x52D9,0x5922,0x7121,0x725F,0x77DB,0x9727,
+0x9D61,0x690B,0x5A7F,0x5A18,0x51A5,0x540D,0x547D,0x660E,
+0x76DF,0x8FF7,0x9298,0x9CF4,0x59EA,0x725D,0x6EC5,0x514D,
+0x68C9,0x7DBF,0x7DEC,0x9762,0x9EBA,0x6478,0x6A21,0x8302,
+0x5984,0x5B5F,0x6BDB,0x731B,0x76F2,0x7DB2,0x8017,0x8499,
+0x5132,0x6728,0x9ED9,0x76EE,0x6762,0x52FF,0x9905,0x5C24,
+0x623B,0x7C7E,0x8CB0,0x554F,0x60B6,0x7D0B,0x9580,0x5301,
+0x4E5F,0x51B6,0x591C,0x723A,0x8036,0x91CE,0x5F25,0x77E2,
+0x5384,0x5F79,0x7D04,0x85AC,0x8A33,0x8E8D,0x9756,0x67F3,
+0x85AE,0x9453,0x6109,0x6108,0x6CB9,0x7652};
+
+/* page 37 0x4D21-0x4D7E */
+static uint16 tab_jisx0208_uni37[]={
+0x8AED,0x8F38,0x552F,0x4F51,0x512A,0x52C7,0x53CB,0x5BA5,
+0x5E7D,0x60A0,0x6182,0x63D6,0x6709,0x67DA,0x6E67,0x6D8C,
+0x7336,0x7337,0x7531,0x7950,0x88D5,0x8A98,0x904A,0x9091,
+0x90F5,0x96C4,0x878D,0x5915,0x4E88,0x4F59,0x4E0E,0x8A89,
+0x8F3F,0x9810,0x50AD,0x5E7C,0x5996,0x5BB9,0x5EB8,0x63DA,
+0x63FA,0x64C1,0x66DC,0x694A,0x69D8,0x6D0B,0x6EB6,0x7194,
+0x7528,0x7AAF,0x7F8A,0x8000,0x8449,0x84C9,0x8981,0x8B21,
+0x8E0A,0x9065,0x967D,0x990A,0x617E,0x6291,0x6B32,0x6C83,
+0x6D74,0x7FCC,0x7FFC,0x6DC0,0x7F85,0x87BA,0x88F8,0x6765,
+0x83B1,0x983C,0x96F7,0x6D1B,0x7D61,0x843D,0x916A,0x4E71,
+0x5375,0x5D50,0x6B04,0x6FEB,0x85CD,0x862D,0x89A7,0x5229,
+0x540F,0x5C65,0x674E,0x68A8,0x7406,0x7483};
+
+/* page 38 0x4E21-0x4E7E */
+static uint16 tab_jisx0208_uni38[]={
+0x75E2,0x88CF,0x88E1,0x91CC,0x96E2,0x9678,0x5F8B,0x7387,
+0x7ACB,0x844E,0x63A0,0x7565,0x5289,0x6D41,0x6E9C,0x7409,
+0x7559,0x786B,0x7C92,0x9686,0x7ADC,0x9F8D,0x4FB6,0x616E,
+0x65C5,0x865C,0x4E86,0x4EAE,0x50DA,0x4E21,0x51CC,0x5BEE,
+0x6599,0x6881,0x6DBC,0x731F,0x7642,0x77AD,0x7A1C,0x7CE7,
+0x826F,0x8AD2,0x907C,0x91CF,0x9675,0x9818,0x529B,0x7DD1,
+0x502B,0x5398,0x6797,0x6DCB,0x71D0,0x7433,0x81E8,0x8F2A,
+0x96A3,0x9C57,0x9E9F,0x7460,0x5841,0x6D99,0x7D2F,0x985E,
+0x4EE4,0x4F36,0x4F8B,0x51B7,0x52B1,0x5DBA,0x601C,0x73B2,
+0x793C,0x82D3,0x9234,0x96B7,0x96F6,0x970A,0x9E97,0x9F62,
+0x66A6,0x6B74,0x5217,0x52A3,0x70C8,0x88C2,0x5EC9,0x604B,
+0x6190,0x6F23,0x7149,0x7C3E,0x7DF4,0x806F};
+
+/* page 39 0x4F21-0x4F53 */
+static uint16 tab_jisx0208_uni39[]={
+0x84EE,0x9023,0x932C,0x5442,0x9B6F,0x6AD3,0x7089,0x8CC2,
+0x8DEF,0x9732,0x52B4,0x5A41,0x5ECA,0x5F04,0x6717,0x697C,
+0x6994,0x6D6A,0x6F0F,0x7262,0x72FC,0x7BED,0x8001,0x807E,
+0x874B,0x90CE,0x516D,0x9E93,0x7984,0x808B,0x9332,0x8AD6,
+0x502D,0x548C,0x8A71,0x6B6A,0x8CC4,0x8107,0x60D1,0x67A0,
+0x9DF2,0x4E99,0x4E98,0x9C10,0x8A6B,0x85C1,0x8568,0x6900,
+0x6E7E,0x7897,0x8155};
+
+/* page 40 0x5021-0x507E */
+static uint16 tab_jisx0208_uni40[]={
+0x5F0C,0x4E10,0x4E15,0x4E2A,0x4E31,0x4E36,0x4E3C,0x4E3F,
+0x4E42,0x4E56,0x4E58,0x4E82,0x4E85,0x8C6B,0x4E8A,0x8212,
+0x5F0D,0x4E8E,0x4E9E,0x4E9F,0x4EA0,0x4EA2,0x4EB0,0x4EB3,
+0x4EB6,0x4ECE,0x4ECD,0x4EC4,0x4EC6,0x4EC2,0x4ED7,0x4EDE,
+0x4EED,0x4EDF,0x4EF7,0x4F09,0x4F5A,0x4F30,0x4F5B,0x4F5D,
+0x4F57,0x4F47,0x4F76,0x4F88,0x4F8F,0x4F98,0x4F7B,0x4F69,
+0x4F70,0x4F91,0x4F6F,0x4F86,0x4F96,0x5118,0x4FD4,0x4FDF,
+0x4FCE,0x4FD8,0x4FDB,0x4FD1,0x4FDA,0x4FD0,0x4FE4,0x4FE5,
+0x501A,0x5028,0x5014,0x502A,0x5025,0x5005,0x4F1C,0x4FF6,
+0x5021,0x5029,0x502C,0x4FFE,0x4FEF,0x5011,0x5006,0x5043,
+0x5047,0x6703,0x5055,0x5050,0x5048,0x505A,0x5056,0x506C,
+0x5078,0x5080,0x509A,0x5085,0x50B4,0x50B2};
+
+/* page 41 0x5121-0x517E */
+static uint16 tab_jisx0208_uni41[]={
+0x50C9,0x50CA,0x50B3,0x50C2,0x50D6,0x50DE,0x50E5,0x50ED,
+0x50E3,0x50EE,0x50F9,0x50F5,0x5109,0x5101,0x5102,0x5116,
+0x5115,0x5114,0x511A,0x5121,0x513A,0x5137,0x513C,0x513B,
+0x513F,0x5140,0x5152,0x514C,0x5154,0x5162,0x7AF8,0x5169,
+0x516A,0x516E,0x5180,0x5182,0x56D8,0x518C,0x5189,0x518F,
+0x5191,0x5193,0x5195,0x5196,0x51A4,0x51A6,0x51A2,0x51A9,
+0x51AA,0x51AB,0x51B3,0x51B1,0x51B2,0x51B0,0x51B5,0x51BD,
+0x51C5,0x51C9,0x51DB,0x51E0,0x8655,0x51E9,0x51ED,0x51F0,
+0x51F5,0x51FE,0x5204,0x520B,0x5214,0x520E,0x5227,0x522A,
+0x522E,0x5233,0x5239,0x524F,0x5244,0x524B,0x524C,0x525E,
+0x5254,0x526A,0x5274,0x5269,0x5273,0x527F,0x527D,0x528D,
+0x5294,0x5292,0x5271,0x5288,0x5291,0x8FA8};
+
+/* page 42 0x5221-0x527E */
+static uint16 tab_jisx0208_uni42[]={
+0x8FA7,0x52AC,0x52AD,0x52BC,0x52B5,0x52C1,0x52CD,0x52D7,
+0x52DE,0x52E3,0x52E6,0x98ED,0x52E0,0x52F3,0x52F5,0x52F8,
+0x52F9,0x5306,0x5308,0x7538,0x530D,0x5310,0x530F,0x5315,
+0x531A,0x5323,0x532F,0x5331,0x5333,0x5338,0x5340,0x5346,
+0x5345,0x4E17,0x5349,0x534D,0x51D6,0x535E,0x5369,0x536E,
+0x5918,0x537B,0x5377,0x5382,0x5396,0x53A0,0x53A6,0x53A5,
+0x53AE,0x53B0,0x53B6,0x53C3,0x7C12,0x96D9,0x53DF,0x66FC,
+0x71EE,0x53EE,0x53E8,0x53ED,0x53FA,0x5401,0x543D,0x5440,
+0x542C,0x542D,0x543C,0x542E,0x5436,0x5429,0x541D,0x544E,
+0x548F,0x5475,0x548E,0x545F,0x5471,0x5477,0x5470,0x5492,
+0x547B,0x5480,0x5476,0x5484,0x5490,0x5486,0x54C7,0x54A2,
+0x54B8,0x54A5,0x54AC,0x54C4,0x54C8,0x54A8};
+
+/* page 43 0x5321-0x537E */
+static uint16 tab_jisx0208_uni43[]={
+0x54AB,0x54C2,0x54A4,0x54BE,0x54BC,0x54D8,0x54E5,0x54E6,
+0x550F,0x5514,0x54FD,0x54EE,0x54ED,0x54FA,0x54E2,0x5539,
+0x5540,0x5563,0x554C,0x552E,0x555C,0x5545,0x5556,0x5557,
+0x5538,0x5533,0x555D,0x5599,0x5580,0x54AF,0x558A,0x559F,
+0x557B,0x557E,0x5598,0x559E,0x55AE,0x557C,0x5583,0x55A9,
+0x5587,0x55A8,0x55DA,0x55C5,0x55DF,0x55C4,0x55DC,0x55E4,
+0x55D4,0x5614,0x55F7,0x5616,0x55FE,0x55FD,0x561B,0x55F9,
+0x564E,0x5650,0x71DF,0x5634,0x5636,0x5632,0x5638,0x566B,
+0x5664,0x562F,0x566C,0x566A,0x5686,0x5680,0x568A,0x56A0,
+0x5694,0x568F,0x56A5,0x56AE,0x56B6,0x56B4,0x56C2,0x56BC,
+0x56C1,0x56C3,0x56C0,0x56C8,0x56CE,0x56D1,0x56D3,0x56D7,
+0x56EE,0x56F9,0x5700,0x56FF,0x5704,0x5709};
+
+/* page 44 0x5421-0x547E */
+static uint16 tab_jisx0208_uni44[]={
+0x5708,0x570B,0x570D,0x5713,0x5718,0x5716,0x55C7,0x571C,
+0x5726,0x5737,0x5738,0x574E,0x573B,0x5740,0x574F,0x5769,
+0x57C0,0x5788,0x5761,0x577F,0x5789,0x5793,0x57A0,0x57B3,
+0x57A4,0x57AA,0x57B0,0x57C3,0x57C6,0x57D4,0x57D2,0x57D3,
+0x580A,0x57D6,0x57E3,0x580B,0x5819,0x581D,0x5872,0x5821,
+0x5862,0x584B,0x5870,0x6BC0,0x5852,0x583D,0x5879,0x5885,
+0x58B9,0x589F,0x58AB,0x58BA,0x58DE,0x58BB,0x58B8,0x58AE,
+0x58C5,0x58D3,0x58D1,0x58D7,0x58D9,0x58D8,0x58E5,0x58DC,
+0x58E4,0x58DF,0x58EF,0x58FA,0x58F9,0x58FB,0x58FC,0x58FD,
+0x5902,0x590A,0x5910,0x591B,0x68A6,0x5925,0x592C,0x592D,
+0x5932,0x5938,0x593E,0x7AD2,0x5955,0x5950,0x594E,0x595A,
+0x5958,0x5962,0x5960,0x5967,0x596C,0x5969};
+
+/* page 45 0x5521-0x557E */
+static uint16 tab_jisx0208_uni45[]={
+0x5978,0x5981,0x599D,0x4F5E,0x4FAB,0x59A3,0x59B2,0x59C6,
+0x59E8,0x59DC,0x598D,0x59D9,0x59DA,0x5A25,0x5A1F,0x5A11,
+0x5A1C,0x5A09,0x5A1A,0x5A40,0x5A6C,0x5A49,0x5A35,0x5A36,
+0x5A62,0x5A6A,0x5A9A,0x5ABC,0x5ABE,0x5ACB,0x5AC2,0x5ABD,
+0x5AE3,0x5AD7,0x5AE6,0x5AE9,0x5AD6,0x5AFA,0x5AFB,0x5B0C,
+0x5B0B,0x5B16,0x5B32,0x5AD0,0x5B2A,0x5B36,0x5B3E,0x5B43,
+0x5B45,0x5B40,0x5B51,0x5B55,0x5B5A,0x5B5B,0x5B65,0x5B69,
+0x5B70,0x5B73,0x5B75,0x5B78,0x6588,0x5B7A,0x5B80,0x5B83,
+0x5BA6,0x5BB8,0x5BC3,0x5BC7,0x5BC9,0x5BD4,0x5BD0,0x5BE4,
+0x5BE6,0x5BE2,0x5BDE,0x5BE5,0x5BEB,0x5BF0,0x5BF6,0x5BF3,
+0x5C05,0x5C07,0x5C08,0x5C0D,0x5C13,0x5C20,0x5C22,0x5C28,
+0x5C38,0x5C39,0x5C41,0x5C46,0x5C4E,0x5C53};
+
+/* page 46 0x5621-0x567E */
+static uint16 tab_jisx0208_uni46[]={
+0x5C50,0x5C4F,0x5B71,0x5C6C,0x5C6E,0x4E62,0x5C76,0x5C79,
+0x5C8C,0x5C91,0x5C94,0x599B,0x5CAB,0x5CBB,0x5CB6,0x5CBC,
+0x5CB7,0x5CC5,0x5CBE,0x5CC7,0x5CD9,0x5CE9,0x5CFD,0x5CFA,
+0x5CED,0x5D8C,0x5CEA,0x5D0B,0x5D15,0x5D17,0x5D5C,0x5D1F,
+0x5D1B,0x5D11,0x5D14,0x5D22,0x5D1A,0x5D19,0x5D18,0x5D4C,
+0x5D52,0x5D4E,0x5D4B,0x5D6C,0x5D73,0x5D76,0x5D87,0x5D84,
+0x5D82,0x5DA2,0x5D9D,0x5DAC,0x5DAE,0x5DBD,0x5D90,0x5DB7,
+0x5DBC,0x5DC9,0x5DCD,0x5DD3,0x5DD2,0x5DD6,0x5DDB,0x5DEB,
+0x5DF2,0x5DF5,0x5E0B,0x5E1A,0x5E19,0x5E11,0x5E1B,0x5E36,
+0x5E37,0x5E44,0x5E43,0x5E40,0x5E4E,0x5E57,0x5E54,0x5E5F,
+0x5E62,0x5E64,0x5E47,0x5E75,0x5E76,0x5E7A,0x9EBC,0x5E7F,
+0x5EA0,0x5EC1,0x5EC2,0x5EC8,0x5ED0,0x5ECF};
+
+/* page 47 0x5721-0x577E */
+static uint16 tab_jisx0208_uni47[]={
+0x5ED6,0x5EE3,0x5EDD,0x5EDA,0x5EDB,0x5EE2,0x5EE1,0x5EE8,
+0x5EE9,0x5EEC,0x5EF1,0x5EF3,0x5EF0,0x5EF4,0x5EF8,0x5EFE,
+0x5F03,0x5F09,0x5F5D,0x5F5C,0x5F0B,0x5F11,0x5F16,0x5F29,
+0x5F2D,0x5F38,0x5F41,0x5F48,0x5F4C,0x5F4E,0x5F2F,0x5F51,
+0x5F56,0x5F57,0x5F59,0x5F61,0x5F6D,0x5F73,0x5F77,0x5F83,
+0x5F82,0x5F7F,0x5F8A,0x5F88,0x5F91,0x5F87,0x5F9E,0x5F99,
+0x5F98,0x5FA0,0x5FA8,0x5FAD,0x5FBC,0x5FD6,0x5FFB,0x5FE4,
+0x5FF8,0x5FF1,0x5FDD,0x60B3,0x5FFF,0x6021,0x6060,0x6019,
+0x6010,0x6029,0x600E,0x6031,0x601B,0x6015,0x602B,0x6026,
+0x600F,0x603A,0x605A,0x6041,0x606A,0x6077,0x605F,0x604A,
+0x6046,0x604D,0x6063,0x6043,0x6064,0x6042,0x606C,0x606B,
+0x6059,0x6081,0x608D,0x60E7,0x6083,0x609A};
+
+/* page 48 0x5821-0x587E */
+static uint16 tab_jisx0208_uni48[]={
+0x6084,0x609B,0x6096,0x6097,0x6092,0x60A7,0x608B,0x60E1,
+0x60B8,0x60E0,0x60D3,0x60B4,0x5FF0,0x60BD,0x60C6,0x60B5,
+0x60D8,0x614D,0x6115,0x6106,0x60F6,0x60F7,0x6100,0x60F4,
+0x60FA,0x6103,0x6121,0x60FB,0x60F1,0x610D,0x610E,0x6147,
+0x613E,0x6128,0x6127,0x614A,0x613F,0x613C,0x612C,0x6134,
+0x613D,0x6142,0x6144,0x6173,0x6177,0x6158,0x6159,0x615A,
+0x616B,0x6174,0x616F,0x6165,0x6171,0x615F,0x615D,0x6153,
+0x6175,0x6199,0x6196,0x6187,0x61AC,0x6194,0x619A,0x618A,
+0x6191,0x61AB,0x61AE,0x61CC,0x61CA,0x61C9,0x61F7,0x61C8,
+0x61C3,0x61C6,0x61BA,0x61CB,0x7F79,0x61CD,0x61E6,0x61E3,
+0x61F6,0x61FA,0x61F4,0x61FF,0x61FD,0x61FC,0x61FE,0x6200,
+0x6208,0x6209,0x620D,0x620C,0x6214,0x621B};
+
+/* page 49 0x5921-0x597E */
+static uint16 tab_jisx0208_uni49[]={
+0x621E,0x6221,0x622A,0x622E,0x6230,0x6232,0x6233,0x6241,
+0x624E,0x625E,0x6263,0x625B,0x6260,0x6268,0x627C,0x6282,
+0x6289,0x627E,0x6292,0x6293,0x6296,0x62D4,0x6283,0x6294,
+0x62D7,0x62D1,0x62BB,0x62CF,0x62FF,0x62C6,0x64D4,0x62C8,
+0x62DC,0x62CC,0x62CA,0x62C2,0x62C7,0x629B,0x62C9,0x630C,
+0x62EE,0x62F1,0x6327,0x6302,0x6308,0x62EF,0x62F5,0x6350,
+0x633E,0x634D,0x641C,0x634F,0x6396,0x638E,0x6380,0x63AB,
+0x6376,0x63A3,0x638F,0x6389,0x639F,0x63B5,0x636B,0x6369,
+0x63BE,0x63E9,0x63C0,0x63C6,0x63E3,0x63C9,0x63D2,0x63F6,
+0x63C4,0x6416,0x6434,0x6406,0x6413,0x6426,0x6436,0x651D,
+0x6417,0x6428,0x640F,0x6467,0x646F,0x6476,0x644E,0x652A,
+0x6495,0x6493,0x64A5,0x64A9,0x6488,0x64BC};
+
+/* page 50 0x5A21-0x5A7E */
+static uint16 tab_jisx0208_uni50[]={
+0x64DA,0x64D2,0x64C5,0x64C7,0x64BB,0x64D8,0x64C2,0x64F1,
+0x64E7,0x8209,0x64E0,0x64E1,0x62AC,0x64E3,0x64EF,0x652C,
+0x64F6,0x64F4,0x64F2,0x64FA,0x6500,0x64FD,0x6518,0x651C,
+0x6505,0x6524,0x6523,0x652B,0x6534,0x6535,0x6537,0x6536,
+0x6538,0x754B,0x6548,0x6556,0x6555,0x654D,0x6558,0x655E,
+0x655D,0x6572,0x6578,0x6582,0x6583,0x8B8A,0x659B,0x659F,
+0x65AB,0x65B7,0x65C3,0x65C6,0x65C1,0x65C4,0x65CC,0x65D2,
+0x65DB,0x65D9,0x65E0,0x65E1,0x65F1,0x6772,0x660A,0x6603,
+0x65FB,0x6773,0x6635,0x6636,0x6634,0x661C,0x664F,0x6644,
+0x6649,0x6641,0x665E,0x665D,0x6664,0x6667,0x6668,0x665F,
+0x6662,0x6670,0x6683,0x6688,0x668E,0x6689,0x6684,0x6698,
+0x669D,0x66C1,0x66B9,0x66C9,0x66BE,0x66BC};
+
+/* page 51 0x5B21-0x5B7E */
+static uint16 tab_jisx0208_uni51[]={
+0x66C4,0x66B8,0x66D6,0x66DA,0x66E0,0x663F,0x66E6,0x66E9,
+0x66F0,0x66F5,0x66F7,0x670F,0x6716,0x671E,0x6726,0x6727,
+0x9738,0x672E,0x673F,0x6736,0x6741,0x6738,0x6737,0x6746,
+0x675E,0x6760,0x6759,0x6763,0x6764,0x6789,0x6770,0x67A9,
+0x677C,0x676A,0x678C,0x678B,0x67A6,0x67A1,0x6785,0x67B7,
+0x67EF,0x67B4,0x67EC,0x67B3,0x67E9,0x67B8,0x67E4,0x67DE,
+0x67DD,0x67E2,0x67EE,0x67B9,0x67CE,0x67C6,0x67E7,0x6A9C,
+0x681E,0x6846,0x6829,0x6840,0x684D,0x6832,0x684E,0x68B3,
+0x682B,0x6859,0x6863,0x6877,0x687F,0x689F,0x688F,0x68AD,
+0x6894,0x689D,0x689B,0x6883,0x6AAE,0x68B9,0x6874,0x68B5,
+0x68A0,0x68BA,0x690F,0x688D,0x687E,0x6901,0x68CA,0x6908,
+0x68D8,0x6922,0x6926,0x68E1,0x690C,0x68CD};
+
+/* page 52 0x5C21-0x5C7E */
+static uint16 tab_jisx0208_uni52[]={
+0x68D4,0x68E7,0x68D5,0x6936,0x6912,0x6904,0x68D7,0x68E3,
+0x6925,0x68F9,0x68E0,0x68EF,0x6928,0x692A,0x691A,0x6923,
+0x6921,0x68C6,0x6979,0x6977,0x695C,0x6978,0x696B,0x6954,
+0x697E,0x696E,0x6939,0x6974,0x693D,0x6959,0x6930,0x6961,
+0x695E,0x695D,0x6981,0x696A,0x69B2,0x69AE,0x69D0,0x69BF,
+0x69C1,0x69D3,0x69BE,0x69CE,0x5BE8,0x69CA,0x69DD,0x69BB,
+0x69C3,0x69A7,0x6A2E,0x6991,0x69A0,0x699C,0x6995,0x69B4,
+0x69DE,0x69E8,0x6A02,0x6A1B,0x69FF,0x6B0A,0x69F9,0x69F2,
+0x69E7,0x6A05,0x69B1,0x6A1E,0x69ED,0x6A14,0x69EB,0x6A0A,
+0x6A12,0x6AC1,0x6A23,0x6A13,0x6A44,0x6A0C,0x6A72,0x6A36,
+0x6A78,0x6A47,0x6A62,0x6A59,0x6A66,0x6A48,0x6A38,0x6A22,
+0x6A90,0x6A8D,0x6AA0,0x6A84,0x6AA2,0x6AA3};
+
+/* page 53 0x5D21-0x5D7E */
+static uint16 tab_jisx0208_uni53[]={
+0x6A97,0x8617,0x6ABB,0x6AC3,0x6AC2,0x6AB8,0x6AB3,0x6AAC,
+0x6ADE,0x6AD1,0x6ADF,0x6AAA,0x6ADA,0x6AEA,0x6AFB,0x6B05,
+0x8616,0x6AFA,0x6B12,0x6B16,0x9B31,0x6B1F,0x6B38,0x6B37,
+0x76DC,0x6B39,0x98EE,0x6B47,0x6B43,0x6B49,0x6B50,0x6B59,
+0x6B54,0x6B5B,0x6B5F,0x6B61,0x6B78,0x6B79,0x6B7F,0x6B80,
+0x6B84,0x6B83,0x6B8D,0x6B98,0x6B95,0x6B9E,0x6BA4,0x6BAA,
+0x6BAB,0x6BAF,0x6BB2,0x6BB1,0x6BB3,0x6BB7,0x6BBC,0x6BC6,
+0x6BCB,0x6BD3,0x6BDF,0x6BEC,0x6BEB,0x6BF3,0x6BEF,0x9EBE,
+0x6C08,0x6C13,0x6C14,0x6C1B,0x6C24,0x6C23,0x6C5E,0x6C55,
+0x6C62,0x6C6A,0x6C82,0x6C8D,0x6C9A,0x6C81,0x6C9B,0x6C7E,
+0x6C68,0x6C73,0x6C92,0x6C90,0x6CC4,0x6CF1,0x6CD3,0x6CBD,
+0x6CD7,0x6CC5,0x6CDD,0x6CAE,0x6CB1,0x6CBE};
+
+/* page 54 0x5E21-0x5E7E */
+static uint16 tab_jisx0208_uni54[]={
+0x6CBA,0x6CDB,0x6CEF,0x6CD9,0x6CEA,0x6D1F,0x884D,0x6D36,
+0x6D2B,0x6D3D,0x6D38,0x6D19,0x6D35,0x6D33,0x6D12,0x6D0C,
+0x6D63,0x6D93,0x6D64,0x6D5A,0x6D79,0x6D59,0x6D8E,0x6D95,
+0x6FE4,0x6D85,0x6DF9,0x6E15,0x6E0A,0x6DB5,0x6DC7,0x6DE6,
+0x6DB8,0x6DC6,0x6DEC,0x6DDE,0x6DCC,0x6DE8,0x6DD2,0x6DC5,
+0x6DFA,0x6DD9,0x6DE4,0x6DD5,0x6DEA,0x6DEE,0x6E2D,0x6E6E,
+0x6E2E,0x6E19,0x6E72,0x6E5F,0x6E3E,0x6E23,0x6E6B,0x6E2B,
+0x6E76,0x6E4D,0x6E1F,0x6E43,0x6E3A,0x6E4E,0x6E24,0x6EFF,
+0x6E1D,0x6E38,0x6E82,0x6EAA,0x6E98,0x6EC9,0x6EB7,0x6ED3,
+0x6EBD,0x6EAF,0x6EC4,0x6EB2,0x6ED4,0x6ED5,0x6E8F,0x6EA5,
+0x6EC2,0x6E9F,0x6F41,0x6F11,0x704C,0x6EEC,0x6EF8,0x6EFE,
+0x6F3F,0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC};
+
+/* page 55 0x5F21-0x5F7E */
+static uint16 tab_jisx0208_uni55[]={
+0x6F3E,0x6F13,0x6EF7,0x6F86,0x6F7A,0x6F78,0x6F81,0x6F80,
+0x6F6F,0x6F5B,0x6FF3,0x6F6D,0x6F82,0x6F7C,0x6F58,0x6F8E,
+0x6F91,0x6FC2,0x6F66,0x6FB3,0x6FA3,0x6FA1,0x6FA4,0x6FB9,
+0x6FC6,0x6FAA,0x6FDF,0x6FD5,0x6FEC,0x6FD4,0x6FD8,0x6FF1,
+0x6FEE,0x6FDB,0x7009,0x700B,0x6FFA,0x7011,0x7001,0x700F,
+0x6FFE,0x701B,0x701A,0x6F74,0x701D,0x7018,0x701F,0x7030,
+0x703E,0x7032,0x7051,0x7063,0x7099,0x7092,0x70AF,0x70F1,
+0x70AC,0x70B8,0x70B3,0x70AE,0x70DF,0x70CB,0x70DD,0x70D9,
+0x7109,0x70FD,0x711C,0x7119,0x7165,0x7155,0x7188,0x7166,
+0x7162,0x714C,0x7156,0x716C,0x718F,0x71FB,0x7184,0x7195,
+0x71A8,0x71AC,0x71D7,0x71B9,0x71BE,0x71D2,0x71C9,0x71D4,
+0x71CE,0x71E0,0x71EC,0x71E7,0x71F5,0x71FC};
+
+/* page 56 0x6021-0x607E */
+static uint16 tab_jisx0208_uni56[]={
+0x71F9,0x71FF,0x720D,0x7210,0x721B,0x7228,0x722D,0x722C,
+0x7230,0x7232,0x723B,0x723C,0x723F,0x7240,0x7246,0x724B,
+0x7258,0x7274,0x727E,0x7282,0x7281,0x7287,0x7292,0x7296,
+0x72A2,0x72A7,0x72B9,0x72B2,0x72C3,0x72C6,0x72C4,0x72CE,
+0x72D2,0x72E2,0x72E0,0x72E1,0x72F9,0x72F7,0x500F,0x7317,
+0x730A,0x731C,0x7316,0x731D,0x7334,0x732F,0x7329,0x7325,
+0x733E,0x734E,0x734F,0x9ED8,0x7357,0x736A,0x7368,0x7370,
+0x7378,0x7375,0x737B,0x737A,0x73C8,0x73B3,0x73CE,0x73BB,
+0x73C0,0x73E5,0x73EE,0x73DE,0x74A2,0x7405,0x746F,0x7425,
+0x73F8,0x7432,0x743A,0x7455,0x743F,0x745F,0x7459,0x7441,
+0x745C,0x7469,0x7470,0x7463,0x746A,0x7476,0x747E,0x748B,
+0x749E,0x74A7,0x74CA,0x74CF,0x74D4,0x73F1};
+
+/* page 57 0x6121-0x617E */
+static uint16 tab_jisx0208_uni57[]={
+0x74E0,0x74E3,0x74E7,0x74E9,0x74EE,0x74F2,0x74F0,0x74F1,
+0x74F8,0x74F7,0x7504,0x7503,0x7505,0x750C,0x750E,0x750D,
+0x7515,0x7513,0x751E,0x7526,0x752C,0x753C,0x7544,0x754D,
+0x754A,0x7549,0x755B,0x7546,0x755A,0x7569,0x7564,0x7567,
+0x756B,0x756D,0x7578,0x7576,0x7586,0x7587,0x7574,0x758A,
+0x7589,0x7582,0x7594,0x759A,0x759D,0x75A5,0x75A3,0x75C2,
+0x75B3,0x75C3,0x75B5,0x75BD,0x75B8,0x75BC,0x75B1,0x75CD,
+0x75CA,0x75D2,0x75D9,0x75E3,0x75DE,0x75FE,0x75FF,0x75FC,
+0x7601,0x75F0,0x75FA,0x75F2,0x75F3,0x760B,0x760D,0x7609,
+0x761F,0x7627,0x7620,0x7621,0x7622,0x7624,0x7634,0x7630,
+0x763B,0x7647,0x7648,0x7646,0x765C,0x7658,0x7661,0x7662,
+0x7668,0x7669,0x766A,0x7667,0x766C,0x7670};
+
+/* page 58 0x6221-0x627E */
+static uint16 tab_jisx0208_uni58[]={
+0x7672,0x7676,0x7678,0x767C,0x7680,0x7683,0x7688,0x768B,
+0x768E,0x7696,0x7693,0x7699,0x769A,0x76B0,0x76B4,0x76B8,
+0x76B9,0x76BA,0x76C2,0x76CD,0x76D6,0x76D2,0x76DE,0x76E1,
+0x76E5,0x76E7,0x76EA,0x862F,0x76FB,0x7708,0x7707,0x7704,
+0x7729,0x7724,0x771E,0x7725,0x7726,0x771B,0x7737,0x7738,
+0x7747,0x775A,0x7768,0x776B,0x775B,0x7765,0x777F,0x777E,
+0x7779,0x778E,0x778B,0x7791,0x77A0,0x779E,0x77B0,0x77B6,
+0x77B9,0x77BF,0x77BC,0x77BD,0x77BB,0x77C7,0x77CD,0x77D7,
+0x77DA,0x77DC,0x77E3,0x77EE,0x77FC,0x780C,0x7812,0x7926,
+0x7820,0x792A,0x7845,0x788E,0x7874,0x7886,0x787C,0x789A,
+0x788C,0x78A3,0x78B5,0x78AA,0x78AF,0x78D1,0x78C6,0x78CB,
+0x78D4,0x78BE,0x78BC,0x78C5,0x78CA,0x78EC};
+
+/* page 59 0x6321-0x637E */
+static uint16 tab_jisx0208_uni59[]={
+0x78E7,0x78DA,0x78FD,0x78F4,0x7907,0x7912,0x7911,0x7919,
+0x792C,0x792B,0x7940,0x7960,0x7957,0x795F,0x795A,0x7955,
+0x7953,0x797A,0x797F,0x798A,0x799D,0x79A7,0x9F4B,0x79AA,
+0x79AE,0x79B3,0x79B9,0x79BA,0x79C9,0x79D5,0x79E7,0x79EC,
+0x79E1,0x79E3,0x7A08,0x7A0D,0x7A18,0x7A19,0x7A20,0x7A1F,
+0x7980,0x7A31,0x7A3B,0x7A3E,0x7A37,0x7A43,0x7A57,0x7A49,
+0x7A61,0x7A62,0x7A69,0x9F9D,0x7A70,0x7A79,0x7A7D,0x7A88,
+0x7A97,0x7A95,0x7A98,0x7A96,0x7AA9,0x7AC8,0x7AB0,0x7AB6,
+0x7AC5,0x7AC4,0x7ABF,0x9083,0x7AC7,0x7ACA,0x7ACD,0x7ACF,
+0x7AD5,0x7AD3,0x7AD9,0x7ADA,0x7ADD,0x7AE1,0x7AE2,0x7AE6,
+0x7AED,0x7AF0,0x7B02,0x7B0F,0x7B0A,0x7B06,0x7B33,0x7B18,
+0x7B19,0x7B1E,0x7B35,0x7B28,0x7B36,0x7B50};
+
+/* page 60 0x6421-0x647E */
+static uint16 tab_jisx0208_uni60[]={
+0x7B7A,0x7B04,0x7B4D,0x7B0B,0x7B4C,0x7B45,0x7B75,0x7B65,
+0x7B74,0x7B67,0x7B70,0x7B71,0x7B6C,0x7B6E,0x7B9D,0x7B98,
+0x7B9F,0x7B8D,0x7B9C,0x7B9A,0x7B8B,0x7B92,0x7B8F,0x7B5D,
+0x7B99,0x7BCB,0x7BC1,0x7BCC,0x7BCF,0x7BB4,0x7BC6,0x7BDD,
+0x7BE9,0x7C11,0x7C14,0x7BE6,0x7BE5,0x7C60,0x7C00,0x7C07,
+0x7C13,0x7BF3,0x7BF7,0x7C17,0x7C0D,0x7BF6,0x7C23,0x7C27,
+0x7C2A,0x7C1F,0x7C37,0x7C2B,0x7C3D,0x7C4C,0x7C43,0x7C54,
+0x7C4F,0x7C40,0x7C50,0x7C58,0x7C5F,0x7C64,0x7C56,0x7C65,
+0x7C6C,0x7C75,0x7C83,0x7C90,0x7CA4,0x7CAD,0x7CA2,0x7CAB,
+0x7CA1,0x7CA8,0x7CB3,0x7CB2,0x7CB1,0x7CAE,0x7CB9,0x7CBD,
+0x7CC0,0x7CC5,0x7CC2,0x7CD8,0x7CD2,0x7CDC,0x7CE2,0x9B3B,
+0x7CEF,0x7CF2,0x7CF4,0x7CF6,0x7CFA,0x7D06};
+
+/* page 61 0x6521-0x657E */
+static uint16 tab_jisx0208_uni61[]={
+0x7D02,0x7D1C,0x7D15,0x7D0A,0x7D45,0x7D4B,0x7D2E,0x7D32,
+0x7D3F,0x7D35,0x7D46,0x7D73,0x7D56,0x7D4E,0x7D72,0x7D68,
+0x7D6E,0x7D4F,0x7D63,0x7D93,0x7D89,0x7D5B,0x7D8F,0x7D7D,
+0x7D9B,0x7DBA,0x7DAE,0x7DA3,0x7DB5,0x7DC7,0x7DBD,0x7DAB,
+0x7E3D,0x7DA2,0x7DAF,0x7DDC,0x7DB8,0x7D9F,0x7DB0,0x7DD8,
+0x7DDD,0x7DE4,0x7DDE,0x7DFB,0x7DF2,0x7DE1,0x7E05,0x7E0A,
+0x7E23,0x7E21,0x7E12,0x7E31,0x7E1F,0x7E09,0x7E0B,0x7E22,
+0x7E46,0x7E66,0x7E3B,0x7E35,0x7E39,0x7E43,0x7E37,0x7E32,
+0x7E3A,0x7E67,0x7E5D,0x7E56,0x7E5E,0x7E59,0x7E5A,0x7E79,
+0x7E6A,0x7E69,0x7E7C,0x7E7B,0x7E83,0x7DD5,0x7E7D,0x8FAE,
+0x7E7F,0x7E88,0x7E89,0x7E8C,0x7E92,0x7E90,0x7E93,0x7E94,
+0x7E96,0x7E8E,0x7E9B,0x7E9C,0x7F38,0x7F3A};
+
+/* page 62 0x6621-0x667E */
+static uint16 tab_jisx0208_uni62[]={
+0x7F45,0x7F4C,0x7F4D,0x7F4E,0x7F50,0x7F51,0x7F55,0x7F54,
+0x7F58,0x7F5F,0x7F60,0x7F68,0x7F69,0x7F67,0x7F78,0x7F82,
+0x7F86,0x7F83,0x7F88,0x7F87,0x7F8C,0x7F94,0x7F9E,0x7F9D,
+0x7F9A,0x7FA3,0x7FAF,0x7FB2,0x7FB9,0x7FAE,0x7FB6,0x7FB8,
+0x8B71,0x7FC5,0x7FC6,0x7FCA,0x7FD5,0x7FD4,0x7FE1,0x7FE6,
+0x7FE9,0x7FF3,0x7FF9,0x98DC,0x8006,0x8004,0x800B,0x8012,
+0x8018,0x8019,0x801C,0x8021,0x8028,0x803F,0x803B,0x804A,
+0x8046,0x8052,0x8058,0x805A,0x805F,0x8062,0x8068,0x8073,
+0x8072,0x8070,0x8076,0x8079,0x807D,0x807F,0x8084,0x8086,
+0x8085,0x809B,0x8093,0x809A,0x80AD,0x5190,0x80AC,0x80DB,
+0x80E5,0x80D9,0x80DD,0x80C4,0x80DA,0x80D6,0x8109,0x80EF,
+0x80F1,0x811B,0x8129,0x8123,0x812F,0x814B};
+
+/* page 63 0x6721-0x677E */
+static uint16 tab_jisx0208_uni63[]={
+0x968B,0x8146,0x813E,0x8153,0x8151,0x80FC,0x8171,0x816E,
+0x8165,0x8166,0x8174,0x8183,0x8188,0x818A,0x8180,0x8182,
+0x81A0,0x8195,0x81A4,0x81A3,0x815F,0x8193,0x81A9,0x81B0,
+0x81B5,0x81BE,0x81B8,0x81BD,0x81C0,0x81C2,0x81BA,0x81C9,
+0x81CD,0x81D1,0x81D9,0x81D8,0x81C8,0x81DA,0x81DF,0x81E0,
+0x81E7,0x81FA,0x81FB,0x81FE,0x8201,0x8202,0x8205,0x8207,
+0x820A,0x820D,0x8210,0x8216,0x8229,0x822B,0x8238,0x8233,
+0x8240,0x8259,0x8258,0x825D,0x825A,0x825F,0x8264,0x8262,
+0x8268,0x826A,0x826B,0x822E,0x8271,0x8277,0x8278,0x827E,
+0x828D,0x8292,0x82AB,0x829F,0x82BB,0x82AC,0x82E1,0x82E3,
+0x82DF,0x82D2,0x82F4,0x82F3,0x82FA,0x8393,0x8303,0x82FB,
+0x82F9,0x82DE,0x8306,0x82DC,0x8309,0x82D9};
+
+/* page 64 0x6821-0x687E */
+static uint16 tab_jisx0208_uni64[]={
+0x8335,0x8334,0x8316,0x8332,0x8331,0x8340,0x8339,0x8350,
+0x8345,0x832F,0x832B,0x8317,0x8318,0x8385,0x839A,0x83AA,
+0x839F,0x83A2,0x8396,0x8323,0x838E,0x8387,0x838A,0x837C,
+0x83B5,0x8373,0x8375,0x83A0,0x8389,0x83A8,0x83F4,0x8413,
+0x83EB,0x83CE,0x83FD,0x8403,0x83D8,0x840B,0x83C1,0x83F7,
+0x8407,0x83E0,0x83F2,0x840D,0x8422,0x8420,0x83BD,0x8438,
+0x8506,0x83FB,0x846D,0x842A,0x843C,0x855A,0x8484,0x8477,
+0x846B,0x84AD,0x846E,0x8482,0x8469,0x8446,0x842C,0x846F,
+0x8479,0x8435,0x84CA,0x8462,0x84B9,0x84BF,0x849F,0x84D9,
+0x84CD,0x84BB,0x84DA,0x84D0,0x84C1,0x84C6,0x84D6,0x84A1,
+0x8521,0x84FF,0x84F4,0x8517,0x8518,0x852C,0x851F,0x8515,
+0x8514,0x84FC,0x8540,0x8563,0x8558,0x8548};
+
+/* page 65 0x6921-0x697E */
+static uint16 tab_jisx0208_uni65[]={
+0x8541,0x8602,0x854B,0x8555,0x8580,0x85A4,0x8588,0x8591,
+0x858A,0x85A8,0x856D,0x8594,0x859B,0x85EA,0x8587,0x859C,
+0x8577,0x857E,0x8590,0x85C9,0x85BA,0x85CF,0x85B9,0x85D0,
+0x85D5,0x85DD,0x85E5,0x85DC,0x85F9,0x860A,0x8613,0x860B,
+0x85FE,0x85FA,0x8606,0x8622,0x861A,0x8630,0x863F,0x864D,
+0x4E55,0x8654,0x865F,0x8667,0x8671,0x8693,0x86A3,0x86A9,
+0x86AA,0x868B,0x868C,0x86B6,0x86AF,0x86C4,0x86C6,0x86B0,
+0x86C9,0x8823,0x86AB,0x86D4,0x86DE,0x86E9,0x86EC,0x86DF,
+0x86DB,0x86EF,0x8712,0x8706,0x8708,0x8700,0x8703,0x86FB,
+0x8711,0x8709,0x870D,0x86F9,0x870A,0x8734,0x873F,0x8737,
+0x873B,0x8725,0x8729,0x871A,0x8760,0x875F,0x8778,0x874C,
+0x874E,0x8774,0x8757,0x8768,0x876E,0x8759};
+
+/* page 66 0x6A21-0x6A7E */
+static uint16 tab_jisx0208_uni66[]={
+0x8753,0x8763,0x876A,0x8805,0x87A2,0x879F,0x8782,0x87AF,
+0x87CB,0x87BD,0x87C0,0x87D0,0x96D6,0x87AB,0x87C4,0x87B3,
+0x87C7,0x87C6,0x87BB,0x87EF,0x87F2,0x87E0,0x880F,0x880D,
+0x87FE,0x87F6,0x87F7,0x880E,0x87D2,0x8811,0x8816,0x8815,
+0x8822,0x8821,0x8831,0x8836,0x8839,0x8827,0x883B,0x8844,
+0x8842,0x8852,0x8859,0x885E,0x8862,0x886B,0x8881,0x887E,
+0x889E,0x8875,0x887D,0x88B5,0x8872,0x8882,0x8897,0x8892,
+0x88AE,0x8899,0x88A2,0x888D,0x88A4,0x88B0,0x88BF,0x88B1,
+0x88C3,0x88C4,0x88D4,0x88D8,0x88D9,0x88DD,0x88F9,0x8902,
+0x88FC,0x88F4,0x88E8,0x88F2,0x8904,0x890C,0x890A,0x8913,
+0x8943,0x891E,0x8925,0x892A,0x892B,0x8941,0x8944,0x893B,
+0x8936,0x8938,0x894C,0x891D,0x8960,0x895E};
+
+/* page 67 0x6B21-0x6B7E */
+static uint16 tab_jisx0208_uni67[]={
+0x8966,0x8964,0x896D,0x896A,0x896F,0x8974,0x8977,0x897E,
+0x8983,0x8988,0x898A,0x8993,0x8998,0x89A1,0x89A9,0x89A6,
+0x89AC,0x89AF,0x89B2,0x89BA,0x89BD,0x89BF,0x89C0,0x89DA,
+0x89DC,0x89DD,0x89E7,0x89F4,0x89F8,0x8A03,0x8A16,0x8A10,
+0x8A0C,0x8A1B,0x8A1D,0x8A25,0x8A36,0x8A41,0x8A5B,0x8A52,
+0x8A46,0x8A48,0x8A7C,0x8A6D,0x8A6C,0x8A62,0x8A85,0x8A82,
+0x8A84,0x8AA8,0x8AA1,0x8A91,0x8AA5,0x8AA6,0x8A9A,0x8AA3,
+0x8AC4,0x8ACD,0x8AC2,0x8ADA,0x8AEB,0x8AF3,0x8AE7,0x8AE4,
+0x8AF1,0x8B14,0x8AE0,0x8AE2,0x8AF7,0x8ADE,0x8ADB,0x8B0C,
+0x8B07,0x8B1A,0x8AE1,0x8B16,0x8B10,0x8B17,0x8B20,0x8B33,
+0x97AB,0x8B26,0x8B2B,0x8B3E,0x8B28,0x8B41,0x8B4C,0x8B4F,
+0x8B4E,0x8B49,0x8B56,0x8B5B,0x8B5A,0x8B6B};
+
+/* page 68 0x6C21-0x6C7E */
+static uint16 tab_jisx0208_uni68[]={
+0x8B5F,0x8B6C,0x8B6F,0x8B74,0x8B7D,0x8B80,0x8B8C,0x8B8E,
+0x8B92,0x8B93,0x8B96,0x8B99,0x8B9A,0x8C3A,0x8C41,0x8C3F,
+0x8C48,0x8C4C,0x8C4E,0x8C50,0x8C55,0x8C62,0x8C6C,0x8C78,
+0x8C7A,0x8C82,0x8C89,0x8C85,0x8C8A,0x8C8D,0x8C8E,0x8C94,
+0x8C7C,0x8C98,0x621D,0x8CAD,0x8CAA,0x8CBD,0x8CB2,0x8CB3,
+0x8CAE,0x8CB6,0x8CC8,0x8CC1,0x8CE4,0x8CE3,0x8CDA,0x8CFD,
+0x8CFA,0x8CFB,0x8D04,0x8D05,0x8D0A,0x8D07,0x8D0F,0x8D0D,
+0x8D10,0x9F4E,0x8D13,0x8CCD,0x8D14,0x8D16,0x8D67,0x8D6D,
+0x8D71,0x8D73,0x8D81,0x8D99,0x8DC2,0x8DBE,0x8DBA,0x8DCF,
+0x8DDA,0x8DD6,0x8DCC,0x8DDB,0x8DCB,0x8DEA,0x8DEB,0x8DDF,
+0x8DE3,0x8DFC,0x8E08,0x8E09,0x8DFF,0x8E1D,0x8E1E,0x8E10,
+0x8E1F,0x8E42,0x8E35,0x8E30,0x8E34,0x8E4A};
+
+/* page 69 0x6D21-0x6D7E */
+static uint16 tab_jisx0208_uni69[]={
+0x8E47,0x8E49,0x8E4C,0x8E50,0x8E48,0x8E59,0x8E64,0x8E60,
+0x8E2A,0x8E63,0x8E55,0x8E76,0x8E72,0x8E7C,0x8E81,0x8E87,
+0x8E85,0x8E84,0x8E8B,0x8E8A,0x8E93,0x8E91,0x8E94,0x8E99,
+0x8EAA,0x8EA1,0x8EAC,0x8EB0,0x8EC6,0x8EB1,0x8EBE,0x8EC5,
+0x8EC8,0x8ECB,0x8EDB,0x8EE3,0x8EFC,0x8EFB,0x8EEB,0x8EFE,
+0x8F0A,0x8F05,0x8F15,0x8F12,0x8F19,0x8F13,0x8F1C,0x8F1F,
+0x8F1B,0x8F0C,0x8F26,0x8F33,0x8F3B,0x8F39,0x8F45,0x8F42,
+0x8F3E,0x8F4C,0x8F49,0x8F46,0x8F4E,0x8F57,0x8F5C,0x8F62,
+0x8F63,0x8F64,0x8F9C,0x8F9F,0x8FA3,0x8FAD,0x8FAF,0x8FB7,
+0x8FDA,0x8FE5,0x8FE2,0x8FEA,0x8FEF,0x9087,0x8FF4,0x9005,
+0x8FF9,0x8FFA,0x9011,0x9015,0x9021,0x900D,0x901E,0x9016,
+0x900B,0x9027,0x9036,0x9035,0x9039,0x8FF8};
+
+/* page 70 0x6E21-0x6E7E */
+static uint16 tab_jisx0208_uni70[]={
+0x904F,0x9050,0x9051,0x9052,0x900E,0x9049,0x903E,0x9056,
+0x9058,0x905E,0x9068,0x906F,0x9076,0x96A8,0x9072,0x9082,
+0x907D,0x9081,0x9080,0x908A,0x9089,0x908F,0x90A8,0x90AF,
+0x90B1,0x90B5,0x90E2,0x90E4,0x6248,0x90DB,0x9102,0x9112,
+0x9119,0x9132,0x9130,0x914A,0x9156,0x9158,0x9163,0x9165,
+0x9169,0x9173,0x9172,0x918B,0x9189,0x9182,0x91A2,0x91AB,
+0x91AF,0x91AA,0x91B5,0x91B4,0x91BA,0x91C0,0x91C1,0x91C9,
+0x91CB,0x91D0,0x91D6,0x91DF,0x91E1,0x91DB,0x91FC,0x91F5,
+0x91F6,0x921E,0x91FF,0x9214,0x922C,0x9215,0x9211,0x925E,
+0x9257,0x9245,0x9249,0x9264,0x9248,0x9295,0x923F,0x924B,
+0x9250,0x929C,0x9296,0x9293,0x929B,0x925A,0x92CF,0x92B9,
+0x92B7,0x92E9,0x930F,0x92FA,0x9344,0x932E};
+
+/* page 71 0x6F21-0x6F7E */
+static uint16 tab_jisx0208_uni71[]={
+0x9319,0x9322,0x931A,0x9323,0x933A,0x9335,0x933B,0x935C,
+0x9360,0x937C,0x936E,0x9356,0x93B0,0x93AC,0x93AD,0x9394,
+0x93B9,0x93D6,0x93D7,0x93E8,0x93E5,0x93D8,0x93C3,0x93DD,
+0x93D0,0x93C8,0x93E4,0x941A,0x9414,0x9413,0x9403,0x9407,
+0x9410,0x9436,0x942B,0x9435,0x9421,0x943A,0x9441,0x9452,
+0x9444,0x945B,0x9460,0x9462,0x945E,0x946A,0x9229,0x9470,
+0x9475,0x9477,0x947D,0x945A,0x947C,0x947E,0x9481,0x947F,
+0x9582,0x9587,0x958A,0x9594,0x9596,0x9598,0x9599,0x95A0,
+0x95A8,0x95A7,0x95AD,0x95BC,0x95BB,0x95B9,0x95BE,0x95CA,
+0x6FF6,0x95C3,0x95CD,0x95CC,0x95D5,0x95D4,0x95D6,0x95DC,
+0x95E1,0x95E5,0x95E2,0x9621,0x9628,0x962E,0x962F,0x9642,
+0x964C,0x964F,0x964B,0x9677,0x965C,0x965E};
+
+/* page 72 0x7021-0x707E */
+static uint16 tab_jisx0208_uni72[]={
+0x965D,0x965F,0x9666,0x9672,0x966C,0x968D,0x9698,0x9695,
+0x9697,0x96AA,0x96A7,0x96B1,0x96B2,0x96B0,0x96B4,0x96B6,
+0x96B8,0x96B9,0x96CE,0x96CB,0x96C9,0x96CD,0x894D,0x96DC,
+0x970D,0x96D5,0x96F9,0x9704,0x9706,0x9708,0x9713,0x970E,
+0x9711,0x970F,0x9716,0x9719,0x9724,0x972A,0x9730,0x9739,
+0x973D,0x973E,0x9744,0x9746,0x9748,0x9742,0x9749,0x975C,
+0x9760,0x9764,0x9766,0x9768,0x52D2,0x976B,0x9771,0x9779,
+0x9785,0x977C,0x9781,0x977A,0x9786,0x978B,0x978F,0x9790,
+0x979C,0x97A8,0x97A6,0x97A3,0x97B3,0x97B4,0x97C3,0x97C6,
+0x97C8,0x97CB,0x97DC,0x97ED,0x9F4F,0x97F2,0x7ADF,0x97F6,
+0x97F5,0x980F,0x980C,0x9838,0x9824,0x9821,0x9837,0x983D,
+0x9846,0x984F,0x984B,0x986B,0x986F,0x9870};
+
+/* page 73 0x7121-0x717E */
+static uint16 tab_jisx0208_uni73[]={
+0x9871,0x9874,0x9873,0x98AA,0x98AF,0x98B1,0x98B6,0x98C4,
+0x98C3,0x98C6,0x98E9,0x98EB,0x9903,0x9909,0x9912,0x9914,
+0x9918,0x9921,0x991D,0x991E,0x9924,0x9920,0x992C,0x992E,
+0x993D,0x993E,0x9942,0x9949,0x9945,0x9950,0x994B,0x9951,
+0x9952,0x994C,0x9955,0x9997,0x9998,0x99A5,0x99AD,0x99AE,
+0x99BC,0x99DF,0x99DB,0x99DD,0x99D8,0x99D1,0x99ED,0x99EE,
+0x99F1,0x99F2,0x99FB,0x99F8,0x9A01,0x9A0F,0x9A05,0x99E2,
+0x9A19,0x9A2B,0x9A37,0x9A45,0x9A42,0x9A40,0x9A43,0x9A3E,
+0x9A55,0x9A4D,0x9A5B,0x9A57,0x9A5F,0x9A62,0x9A65,0x9A64,
+0x9A69,0x9A6B,0x9A6A,0x9AAD,0x9AB0,0x9ABC,0x9AC0,0x9ACF,
+0x9AD1,0x9AD3,0x9AD4,0x9ADE,0x9ADF,0x9AE2,0x9AE3,0x9AE6,
+0x9AEF,0x9AEB,0x9AEE,0x9AF4,0x9AF1,0x9AF7};
+
+/* page 74 0x7221-0x727E */
+static uint16 tab_jisx0208_uni74[]={
+0x9AFB,0x9B06,0x9B18,0x9B1A,0x9B1F,0x9B22,0x9B23,0x9B25,
+0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2E,0x9B2F,0x9B32,0x9B44,
+0x9B43,0x9B4F,0x9B4D,0x9B4E,0x9B51,0x9B58,0x9B74,0x9B93,
+0x9B83,0x9B91,0x9B96,0x9B97,0x9B9F,0x9BA0,0x9BA8,0x9BB4,
+0x9BC0,0x9BCA,0x9BB9,0x9BC6,0x9BCF,0x9BD1,0x9BD2,0x9BE3,
+0x9BE2,0x9BE4,0x9BD4,0x9BE1,0x9C3A,0x9BF2,0x9BF1,0x9BF0,
+0x9C15,0x9C14,0x9C09,0x9C13,0x9C0C,0x9C06,0x9C08,0x9C12,
+0x9C0A,0x9C04,0x9C2E,0x9C1B,0x9C25,0x9C24,0x9C21,0x9C30,
+0x9C47,0x9C32,0x9C46,0x9C3E,0x9C5A,0x9C60,0x9C67,0x9C76,
+0x9C78,0x9CE7,0x9CEC,0x9CF0,0x9D09,0x9D08,0x9CEB,0x9D03,
+0x9D06,0x9D2A,0x9D26,0x9DAF,0x9D23,0x9D1F,0x9D44,0x9D15,
+0x9D12,0x9D41,0x9D3F,0x9D3E,0x9D46,0x9D48};
+
+/* page 75 0x7321-0x737E */
+static uint16 tab_jisx0208_uni75[]={
+0x9D5D,0x9D5E,0x9D64,0x9D51,0x9D50,0x9D59,0x9D72,0x9D89,
+0x9D87,0x9DAB,0x9D6F,0x9D7A,0x9D9A,0x9DA4,0x9DA9,0x9DB2,
+0x9DC4,0x9DC1,0x9DBB,0x9DB8,0x9DBA,0x9DC6,0x9DCF,0x9DC2,
+0x9DD9,0x9DD3,0x9DF8,0x9DE6,0x9DED,0x9DEF,0x9DFD,0x9E1A,
+0x9E1B,0x9E1E,0x9E75,0x9E79,0x9E7D,0x9E81,0x9E88,0x9E8B,
+0x9E8C,0x9E92,0x9E95,0x9E91,0x9E9D,0x9EA5,0x9EA9,0x9EB8,
+0x9EAA,0x9EAD,0x9761,0x9ECC,0x9ECE,0x9ECF,0x9ED0,0x9ED4,
+0x9EDC,0x9EDE,0x9EDD,0x9EE0,0x9EE5,0x9EE8,0x9EEF,0x9EF4,
+0x9EF6,0x9EF7,0x9EF9,0x9EFB,0x9EFC,0x9EFD,0x9F07,0x9F08,
+0x76B7,0x9F15,0x9F21,0x9F2C,0x9F3E,0x9F4A,0x9F52,0x9F54,
+0x9F63,0x9F5F,0x9F60,0x9F61,0x9F66,0x9F67,0x9F6C,0x9F6A,
+0x9F77,0x9F72,0x9F76,0x9F95,0x9F9C,0x9FA0};
+
+/* page 76 0x7421-0x7426 */
+static uint16 tab_jisx0208_uni76[]={
+0x582F,0x69C7,0x9059,0x7464,0x51DC,0x7199};
+
+/* page 77 0x2D21 - 0x2D7C */
+static uint16 tab_nec13_uni0[]={
+0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,
+0x2468,0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,
+0x2470,0x2471,0x2472,0x2473,0x2160,0x2161,0x2162,0x2163,
+0x2164,0x2165,0x2166,0x2167,0x2168,0x2169, 0,0x3349,
+0x3314,0x3322,0x334D,0x3318,0x3327,0x3303,0x3336,0x3351,
+0x3357,0x330D,0x3326,0x3323,0x332B,0x334A,0x333B,0x339C,
+0x339D,0x339E,0x338E,0x338F,0x33C4,0x33A1, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x337B,0x301D,
+0x301F,0x2116,0x33CD,0x2121,0x32A4,0x32A5,0x32A6,0x32A7,
+0x32A8,0x3231,0x3232,0x3239,0x337E,0x337D,0x337C,0x2252,
+0x2261,0x222B,0x222E,0x2211,0x221A,0x22A5,0x2220,0x221F,
+0x22BF,0x2235,0x2229,0x222A};
+
+static int
+my_jisx0208_uni_onechar(int code){
+ if ((code>=0x2121)&&(code<=0x217E))
+ return(tab_jisx0208_uni0[code-0x2121]);
+ if ((code>=0x2221)&&(code<=0x227E))
+ return(tab_jisx0208_uni1[code-0x2221]);
+ if ((code>=0x2330)&&(code<=0x237A))
+ return(tab_jisx0208_uni2[code-0x2330]);
+ if ((code>=0x2421)&&(code<=0x2473))
+ return(tab_jisx0208_uni3[code-0x2421]);
+ if ((code>=0x2521)&&(code<=0x2576))
+ return(tab_jisx0208_uni4[code-0x2521]);
+ if ((code>=0x2621)&&(code<=0x2658))
+ return(tab_jisx0208_uni5[code-0x2621]);
+ if ((code>=0x2721)&&(code<=0x2771))
+ return(tab_jisx0208_uni6[code-0x2721]);
+ if ((code>=0x2821)&&(code<=0x2840))
+ return(tab_jisx0208_uni7[code-0x2821]);
+ if ((code>=0x3021)&&(code<=0x307E))
+ return(tab_jisx0208_uni8[code-0x3021]);
+ if ((code>=0x3121)&&(code<=0x317E))
+ return(tab_jisx0208_uni9[code-0x3121]);
+ if ((code>=0x3221)&&(code<=0x327E))
+ return(tab_jisx0208_uni10[code-0x3221]);
+ if ((code>=0x3321)&&(code<=0x337E))
+ return(tab_jisx0208_uni11[code-0x3321]);
+ if ((code>=0x3421)&&(code<=0x347E))
+ return(tab_jisx0208_uni12[code-0x3421]);
+ if ((code>=0x3521)&&(code<=0x357E))
+ return(tab_jisx0208_uni13[code-0x3521]);
+ if ((code>=0x3621)&&(code<=0x367E))
+ return(tab_jisx0208_uni14[code-0x3621]);
+ if ((code>=0x3721)&&(code<=0x377E))
+ return(tab_jisx0208_uni15[code-0x3721]);
+ if ((code>=0x3821)&&(code<=0x387E))
+ return(tab_jisx0208_uni16[code-0x3821]);
+ if ((code>=0x3921)&&(code<=0x397E))
+ return(tab_jisx0208_uni17[code-0x3921]);
+ if ((code>=0x3A21)&&(code<=0x3A7E))
+ return(tab_jisx0208_uni18[code-0x3A21]);
+ if ((code>=0x3B21)&&(code<=0x3B7E))
+ return(tab_jisx0208_uni19[code-0x3B21]);
+ if ((code>=0x3C21)&&(code<=0x3C7E))
+ return(tab_jisx0208_uni20[code-0x3C21]);
+ if ((code>=0x3D21)&&(code<=0x3D7E))
+ return(tab_jisx0208_uni21[code-0x3D21]);
+ if ((code>=0x3E21)&&(code<=0x3E7E))
+ return(tab_jisx0208_uni22[code-0x3E21]);
+ if ((code>=0x3F21)&&(code<=0x3F7E))
+ return(tab_jisx0208_uni23[code-0x3F21]);
+ if ((code>=0x4021)&&(code<=0x407E))
+ return(tab_jisx0208_uni24[code-0x4021]);
+ if ((code>=0x4121)&&(code<=0x417E))
+ return(tab_jisx0208_uni25[code-0x4121]);
+ if ((code>=0x4221)&&(code<=0x427E))
+ return(tab_jisx0208_uni26[code-0x4221]);
+ if ((code>=0x4321)&&(code<=0x437E))
+ return(tab_jisx0208_uni27[code-0x4321]);
+ if ((code>=0x4421)&&(code<=0x447E))
+ return(tab_jisx0208_uni28[code-0x4421]);
+ if ((code>=0x4521)&&(code<=0x457E))
+ return(tab_jisx0208_uni29[code-0x4521]);
+ if ((code>=0x4621)&&(code<=0x467E))
+ return(tab_jisx0208_uni30[code-0x4621]);
+ if ((code>=0x4721)&&(code<=0x477E))
+ return(tab_jisx0208_uni31[code-0x4721]);
+ if ((code>=0x4821)&&(code<=0x487E))
+ return(tab_jisx0208_uni32[code-0x4821]);
+ if ((code>=0x4921)&&(code<=0x497E))
+ return(tab_jisx0208_uni33[code-0x4921]);
+ if ((code>=0x4A21)&&(code<=0x4A7E))
+ return(tab_jisx0208_uni34[code-0x4A21]);
+ if ((code>=0x4B21)&&(code<=0x4B7E))
+ return(tab_jisx0208_uni35[code-0x4B21]);
+ if ((code>=0x4C21)&&(code<=0x4C7E))
+ return(tab_jisx0208_uni36[code-0x4C21]);
+ if ((code>=0x4D21)&&(code<=0x4D7E))
+ return(tab_jisx0208_uni37[code-0x4D21]);
+ if ((code>=0x4E21)&&(code<=0x4E7E))
+ return(tab_jisx0208_uni38[code-0x4E21]);
+ if ((code>=0x4F21)&&(code<=0x4F53))
+ return(tab_jisx0208_uni39[code-0x4F21]);
+ if ((code>=0x5021)&&(code<=0x507E))
+ return(tab_jisx0208_uni40[code-0x5021]);
+ if ((code>=0x5121)&&(code<=0x517E))
+ return(tab_jisx0208_uni41[code-0x5121]);
+ if ((code>=0x5221)&&(code<=0x527E))
+ return(tab_jisx0208_uni42[code-0x5221]);
+ if ((code>=0x5321)&&(code<=0x537E))
+ return(tab_jisx0208_uni43[code-0x5321]);
+ if ((code>=0x5421)&&(code<=0x547E))
+ return(tab_jisx0208_uni44[code-0x5421]);
+ if ((code>=0x5521)&&(code<=0x557E))
+ return(tab_jisx0208_uni45[code-0x5521]);
+ if ((code>=0x5621)&&(code<=0x567E))
+ return(tab_jisx0208_uni46[code-0x5621]);
+ if ((code>=0x5721)&&(code<=0x577E))
+ return(tab_jisx0208_uni47[code-0x5721]);
+ if ((code>=0x5821)&&(code<=0x587E))
+ return(tab_jisx0208_uni48[code-0x5821]);
+ if ((code>=0x5921)&&(code<=0x597E))
+ return(tab_jisx0208_uni49[code-0x5921]);
+ if ((code>=0x5A21)&&(code<=0x5A7E))
+ return(tab_jisx0208_uni50[code-0x5A21]);
+ if ((code>=0x5B21)&&(code<=0x5B7E))
+ return(tab_jisx0208_uni51[code-0x5B21]);
+ if ((code>=0x5C21)&&(code<=0x5C7E))
+ return(tab_jisx0208_uni52[code-0x5C21]);
+ if ((code>=0x5D21)&&(code<=0x5D7E))
+ return(tab_jisx0208_uni53[code-0x5D21]);
+ if ((code>=0x5E21)&&(code<=0x5E7E))
+ return(tab_jisx0208_uni54[code-0x5E21]);
+ if ((code>=0x5F21)&&(code<=0x5F7E))
+ return(tab_jisx0208_uni55[code-0x5F21]);
+ if ((code>=0x6021)&&(code<=0x607E))
+ return(tab_jisx0208_uni56[code-0x6021]);
+ if ((code>=0x6121)&&(code<=0x617E))
+ return(tab_jisx0208_uni57[code-0x6121]);
+ if ((code>=0x6221)&&(code<=0x627E))
+ return(tab_jisx0208_uni58[code-0x6221]);
+ if ((code>=0x6321)&&(code<=0x637E))
+ return(tab_jisx0208_uni59[code-0x6321]);
+ if ((code>=0x6421)&&(code<=0x647E))
+ return(tab_jisx0208_uni60[code-0x6421]);
+ if ((code>=0x6521)&&(code<=0x657E))
+ return(tab_jisx0208_uni61[code-0x6521]);
+ if ((code>=0x6621)&&(code<=0x667E))
+ return(tab_jisx0208_uni62[code-0x6621]);
+ if ((code>=0x6721)&&(code<=0x677E))
+ return(tab_jisx0208_uni63[code-0x6721]);
+ if ((code>=0x6821)&&(code<=0x687E))
+ return(tab_jisx0208_uni64[code-0x6821]);
+ if ((code>=0x6921)&&(code<=0x697E))
+ return(tab_jisx0208_uni65[code-0x6921]);
+ if ((code>=0x6A21)&&(code<=0x6A7E))
+ return(tab_jisx0208_uni66[code-0x6A21]);
+ if ((code>=0x6B21)&&(code<=0x6B7E))
+ return(tab_jisx0208_uni67[code-0x6B21]);
+ if ((code>=0x6C21)&&(code<=0x6C7E))
+ return(tab_jisx0208_uni68[code-0x6C21]);
+ if ((code>=0x6D21)&&(code<=0x6D7E))
+ return(tab_jisx0208_uni69[code-0x6D21]);
+ if ((code>=0x6E21)&&(code<=0x6E7E))
+ return(tab_jisx0208_uni70[code-0x6E21]);
+ if ((code>=0x6F21)&&(code<=0x6F7E))
+ return(tab_jisx0208_uni71[code-0x6F21]);
+ if ((code>=0x7021)&&(code<=0x707E))
+ return(tab_jisx0208_uni72[code-0x7021]);
+ if ((code>=0x7121)&&(code<=0x717E))
+ return(tab_jisx0208_uni73[code-0x7121]);
+ if ((code>=0x7221)&&(code<=0x727E))
+ return(tab_jisx0208_uni74[code-0x7221]);
+ if ((code>=0x7321)&&(code<=0x737E))
+ return(tab_jisx0208_uni75[code-0x7321]);
+ if ((code>=0x7421)&&(code<=0x7426))
+ return(tab_jisx0208_uni76[code-0x7421]);
+ if ((code>=0x2D21)&&(code<=0x2D7C))
+ return(tab_nec13_uni0[code-0x2D21]);
+ return(0);
+}
+
+/* page 0 0x005C-0x005C */
+static uint16 tab_uni_jisx02080[]={
+0x5C};
+
+/* page 1 0x00A2-0x00B6 */
+static uint16 tab_uni_jisx02081[]={
+ 0, 0, 0, 0, 0,0x2178,0x212F, 0,
+ 0, 0, 0, 0, 0, 0,0x216B,0x215E,
+ 0, 0,0x212D, 0,0x2279};
+
+/* page 2 0x00D7-0x00D7 */
+static uint16 tab_uni_jisx02082[]={
+0x215F};
+
+/* page 3 0x00F7-0x00F7 */
+static uint16 tab_uni_jisx02083[]={
+0x2160};
+
+/* page 4 0x0391-0x03C9 */
+static uint16 tab_uni_jisx02084[]={
+0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627,0x2628,
+0x2629,0x262A,0x262B,0x262C,0x262D,0x262E,0x262F,0x2630,
+0x2631, 0,0x2632,0x2633,0x2634,0x2635,0x2636,0x2637,
+0x2638, 0, 0, 0, 0, 0, 0, 0,
+0x2641,0x2642,0x2643,0x2644,0x2645,0x2646,0x2647,0x2648,
+0x2649,0x264A,0x264B,0x264C,0x264D,0x264E,0x264F,0x2650,
+0x2651, 0,0x2652,0x2653,0x2654,0x2655,0x2656,0x2657,
+0x2658};
+
+/* page 5 0x0401-0x0451 */
+static uint16 tab_uni_jisx02085[]={
+0x2727, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2721,
+0x2722,0x2723,0x2724,0x2725,0x2726,0x2728,0x2729,0x272A,
+0x272B,0x272C,0x272D,0x272E,0x272F,0x2730,0x2731,0x2732,
+0x2733,0x2734,0x2735,0x2736,0x2737,0x2738,0x2739,0x273A,
+0x273B,0x273C,0x273D,0x273E,0x273F,0x2740,0x2741,0x2751,
+0x2752,0x2753,0x2754,0x2755,0x2756,0x2758,0x2759,0x275A,
+0x275B,0x275C,0x275D,0x275E,0x275F,0x2760,0x2761,0x2762,
+0x2763,0x2764,0x2765,0x2766,0x2767,0x2768,0x2769,0x276A,
+0x276B,0x276C,0x276D,0x276E,0x276F,0x2770,0x2771, 0,
+0x2757};
+
+/* page 6 0x2010-0x203B */
+static uint16 tab_uni_jisx02086[]={
+0x213E, 0, 0, 0, 0,0x213D, 0, 0,
+0x2146,0x2147, 0, 0,0x2148,0x2149, 0, 0,
+0x2277,0x2278, 0, 0, 0,0x2145,0x2144, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2273, 0,0x216C,0x216D, 0, 0, 0, 0,
+ 0, 0, 0,0x2228};
+
+/* page 7 0x2100-0x2116 */
+static uint16 tab_uni_jisx02087[]={
+ 0, 0, 0,0x216E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2D62};
+
+/* page 8 0x2120-0x212B */
+static uint16 tab_uni_jisx02088[]={
+ 0,0x2D64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2272};
+
+/* page 9 0x2160-0x2169 */
+static uint16 tab_uni_jisx02089[]={
+0x2D35,0x2D36,0x2D37,0x2D38,0x2D39,0x2D3A,0x2D3B,0x2D3C,
+0x2D3D,0x2D3E};
+
+/* page 10 0x2190-0x2193 */
+static uint16 tab_uni_jisx020810[]={
+0x222B,0x222C,0x222A,0x222D};
+
+/* page 11 0x21D2-0x21D4 */
+static uint16 tab_uni_jisx020811[]={
+0x224D, 0,0x224E};
+
+/* page 12 0x2200-0x223D */
+static uint16 tab_uni_jisx020812[]={
+0x224F, 0,0x225F,0x2250, 0, 0, 0,0x2260,
+0x223A, 0, 0,0x223B, 0, 0, 0, 0,
+ 0,0x2D74, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2265, 0, 0,0x2267,0x2167,0x2D78,
+0x225C, 0, 0, 0, 0,0x2142, 0,0x224A,
+0x224B,0x2241,0x2240,0x2269,0x226A, 0,0x2D73, 0,
+ 0, 0, 0, 0,0x2168,0x2268, 0, 0,
+ 0, 0, 0, 0, 0,0x2266};
+
+/* page 13 0x2252-0x226B */
+static uint16 tab_uni_jisx020813[]={
+0x2262, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2162,0x2261,
+ 0, 0, 0, 0,0x2165,0x2166, 0, 0,
+0x2263,0x2264};
+
+/* page 14 0x2282-0x2287 */
+static uint16 tab_uni_jisx020814[]={
+0x223E,0x223F, 0, 0,0x223C,0x223D};
+
+/* page 15 0x22A0-0x22BF */
+static uint16 tab_uni_jisx020815[]={
+ 0, 0, 0, 0, 0,0x225D, 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,0x2D79};
+
+/* page 16 0x2312-0x2312 */
+static uint16 tab_uni_jisx020816[]={
+0x225E};
+
+/* page 17 0x2460-0x2473 */
+static uint16 tab_uni_jisx020817[]={
+0x2D21,0x2D22,0x2D23,0x2D24,0x2D25,0x2D26,0x2D27,0x2D28,
+0x2D29,0x2D2A,0x2D2B,0x2D2C,0x2D2D,0x2D2E,0x2D2F,0x2D30,
+0x2D31,0x2D32,0x2D33,0x2D34};
+
+/* page 18 0x2500-0x254B */
+static uint16 tab_uni_jisx020818[]={
+0x2821,0x282C,0x2822,0x282D, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2823, 0, 0,0x282E,
+0x2824, 0, 0,0x282F,0x2826, 0, 0,0x2831,
+0x2825, 0, 0,0x2830,0x2827,0x283C, 0, 0,
+0x2837, 0, 0,0x2832,0x2829,0x283E, 0, 0,
+0x2839, 0, 0,0x2834,0x2828, 0, 0,0x2838,
+0x283D, 0, 0,0x2833,0x282A, 0, 0,0x283A,
+0x283F, 0, 0,0x2835,0x282B, 0, 0,0x283B,
+ 0, 0,0x2840, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x2836};
+
+/* page 19 0x25A0-0x25CF */
+static uint16 tab_uni_jisx020819[]={
+0x2223,0x2222, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2225,0x2224, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2227,0x2226, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2221,0x217E,
+ 0, 0, 0,0x217B, 0, 0,0x217D,0x217C
+};
+
+/* page 20 0x25EF-0x25EF */
+static uint16 tab_uni_jisx020820[]={
+0x227E};
+
+/* page 21 0x2605-0x2606 */
+static uint16 tab_uni_jisx020821[]={
+0x217A,0x2179};
+
+/* page 22 0x2640-0x2642 */
+static uint16 tab_uni_jisx020822[]={
+0x216A, 0,0x2169};
+
+/* page 23 0x266A-0x266F */
+static uint16 tab_uni_jisx020823[]={
+0x2276, 0, 0,0x2275, 0,0x2274};
+
+/* page 24 0x3000-0x301F */
+static uint16 tab_uni_jisx020824[]={
+0x2121,0x2122,0x2123,0x2137, 0,0x2139,0x213A,0x213B,
+0x2152,0x2153,0x2154,0x2155,0x2156,0x2157,0x2158,0x2159,
+0x215A,0x215B,0x2229,0x222E,0x214C,0x214D, 0, 0,
+ 0, 0, 0, 0, 0,0x2D60, 0,0x2D61};
+
+/* page 25 0x3041-0x30FE */
+static uint16 tab_uni_jisx020825[]={
+0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427,0x2428,
+0x2429,0x242A,0x242B,0x242C,0x242D,0x242E,0x242F,0x2430,
+0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437,0x2438,
+0x2439,0x243A,0x243B,0x243C,0x243D,0x243E,0x243F,0x2440,
+0x2441,0x2442,0x2443,0x2444,0x2445,0x2446,0x2447,0x2448,
+0x2449,0x244A,0x244B,0x244C,0x244D,0x244E,0x244F,0x2450,
+0x2451,0x2452,0x2453,0x2454,0x2455,0x2456,0x2457,0x2458,
+0x2459,0x245A,0x245B,0x245C,0x245D,0x245E,0x245F,0x2460,
+0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,0x2468,
+0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,0x2470,
+0x2471,0x2472,0x2473, 0, 0, 0, 0, 0,
+ 0, 0,0x212B,0x212C,0x2135,0x2136, 0, 0,
+0x2521,0x2522,0x2523,0x2524,0x2525,0x2526,0x2527,0x2528,
+0x2529,0x252A,0x252B,0x252C,0x252D,0x252E,0x252F,0x2530,
+0x2531,0x2532,0x2533,0x2534,0x2535,0x2536,0x2537,0x2538,
+0x2539,0x253A,0x253B,0x253C,0x253D,0x253E,0x253F,0x2540,
+0x2541,0x2542,0x2543,0x2544,0x2545,0x2546,0x2547,0x2548,
+0x2549,0x254A,0x254B,0x254C,0x254D,0x254E,0x254F,0x2550,
+0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557,0x2558,
+0x2559,0x255A,0x255B,0x255C,0x255D,0x255E,0x255F,0x2560,
+0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567,0x2568,
+0x2569,0x256A,0x256B,0x256C,0x256D,0x256E,0x256F,0x2570,
+0x2571,0x2572,0x2573,0x2574,0x2575,0x2576, 0, 0,
+ 0, 0,0x2126,0x213C,0x2133,0x2134};
+
+/* page 26 0x3230-0x3239 */
+static uint16 tab_uni_jisx020826[]={
+ 0,0x2D6A,0x2D6B, 0, 0, 0, 0, 0,
+ 0,0x2D6C};
+
+/* page 27 0x32A0-0x32A8 */
+static uint16 tab_uni_jisx020827[]={
+ 0, 0, 0, 0,0x2D65,0x2D66,0x2D67,0x2D68,
+0x2D69};
+
+/* page 28 0x3300-0x33CD */
+static uint16 tab_uni_jisx020828[]={
+ 0, 0, 0,0x2D46, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x2D4A, 0, 0,
+ 0, 0, 0, 0,0x2D41, 0, 0, 0,
+0x2D44, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2D42,0x2D4C, 0, 0,0x2D4B,0x2D45,
+ 0, 0, 0,0x2D4D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2D47, 0,
+ 0, 0, 0,0x2D4F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2D40,0x2D4E, 0, 0,0x2D43, 0, 0,
+ 0,0x2D48, 0, 0, 0, 0, 0,0x2D49,
+ 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,0x2D5F,0x2D6F,0x2D6E,0x2D6D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2D53,0x2D54,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2D50,0x2D51,0x2D52, 0,
+ 0,0x2D56, 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,0x2D55, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x2D63};
+
+/* page 29 0x4E00-0x5516 */
+static uint16 tab_uni_jisx020829[]={
+0x306C,0x437A, 0,0x3C37, 0, 0, 0,0x4B7C,
+0x3E66,0x3B30,0x3E65,0x323C, 0,0x4954,0x4D3F, 0,
+0x5022,0x312F, 0, 0,0x336E,0x5023,0x4024,0x5242,
+0x3556,0x4A3A, 0, 0, 0, 0,0x3E67, 0,
+ 0,0x4E3E, 0, 0, 0, 0,0x4A42, 0,
+ 0, 0,0x5024, 0, 0,0x4366, 0, 0,
+ 0,0x5025,0x367A, 0, 0, 0,0x5026, 0,
+0x345D,0x4330, 0,0x3C67,0x5027, 0, 0,0x5028,
+ 0, 0,0x5029,0x4735, 0,0x3557, 0, 0,
+ 0, 0, 0,0x4737, 0,0x4663,0x3843,0x4B33,
+ 0, 0, 0, 0, 0,0x6949,0x502A,0x3E68,
+0x502B,0x3235, 0, 0, 0,0x3665,0x3870,0x4C69,
+ 0, 0,0x5626, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4D70, 0,0x467D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3425, 0,
+0x3535, 0,0x502C, 0, 0,0x502D,0x4E3B, 0,
+0x4D3D,0x4168,0x502F,0x3B76,0x4673, 0,0x5032, 0,
+ 0,0x313E,0x385F, 0,0x385E,0x3066, 0, 0,
+0x4F4B,0x4F4A, 0,0x3A33,0x3021, 0,0x5033,0x5034,
+0x5035,0x4B34,0x5036, 0,0x3872,0x3067,0x4B72, 0,
+0x357C, 0, 0,0x357D,0x357E,0x4462,0x4E3C, 0,
+0x5037, 0, 0,0x5038, 0, 0,0x5039, 0,
+ 0, 0,0x3F4D, 0, 0, 0, 0, 0,
+0x3D3A,0x3F4E,0x503E, 0,0x503C, 0,0x503D,0x3558,
+ 0, 0,0x3A23,0x3270, 0,0x503B,0x503A,0x4A29,
+ 0, 0, 0, 0,0x3B46,0x3B45,0x423E,0x503F,
+0x4955,0x4067, 0, 0, 0,0x2138,0x5040,0x5042,
+ 0, 0, 0,0x4265,0x4E61,0x304A, 0, 0,
+ 0, 0, 0, 0, 0,0x5041,0x323E, 0,
+0x3644, 0,0x4367, 0, 0, 0,0x376F,0x5043,
+ 0, 0, 0,0x4724, 0, 0, 0, 0,
+ 0,0x346B, 0, 0, 0, 0, 0, 0,
+ 0,0x5044,0x304B, 0, 0,0x3860,0x346C,0x497A,
+0x4832,0x3559, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3271, 0,0x5067,0x4541, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x476C,
+0x5046, 0, 0, 0,0x483C, 0,0x4E62, 0,
+0x3F2D, 0,0x3B47, 0,0x3B77,0x3240, 0, 0,
+ 0, 0, 0,0x4451, 0, 0,0x4322,0x504A,
+ 0, 0, 0, 0, 0,0x304C,0x4463,0x3D3B,
+0x3A34,0x4D24, 0,0x424E, 0,0x323F, 0,0x5049,
+ 0,0x4D3E,0x5045,0x5047,0x3A6E,0x5048,0x5524, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5050, 0, 0, 0, 0, 0,0x5053,
+0x5051, 0, 0,0x3242, 0,0x4A3B,0x504B, 0,
+ 0, 0, 0,0x504F,0x3873, 0, 0,0x3B48,
+ 0, 0, 0,0x3426, 0, 0,0x5054, 0,
+0x504C, 0, 0,0x4E63, 0,0x3B78, 0,0x504D,
+ 0,0x5052, 0, 0, 0, 0,0x5055, 0,
+0x504E, 0, 0,0x3621, 0,0x304D, 0, 0,
+0x3622,0x3241, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5525, 0,0x4B79,0x496E,0x3874,
+ 0, 0, 0, 0, 0,0x3F2F,0x4E37, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4A58,
+ 0, 0,0x3738,0x4225,0x3264, 0, 0, 0,
+ 0, 0,0x3D53, 0, 0, 0,0x5059, 0,
+0x505E,0x505C, 0, 0,0x5057, 0, 0,0x422F,
+0x505A, 0,0x505D,0x505B, 0,0x4A5D, 0,0x5058,
+ 0,0x3F2E, 0,0x4B73,0x505F,0x5060, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3D24,0x506D,
+ 0, 0, 0,0x4750, 0,0x4936,0x5068, 0,
+0x4A70, 0,0x3236, 0, 0, 0,0x506C, 0,
+ 0, 0, 0, 0, 0,0x5066,0x506F, 0,
+ 0,0x4152, 0,0x3844, 0,0x475C, 0,0x6047,
+ 0,0x506E,0x455D, 0,0x5063, 0,0x3876, 0,
+ 0,0x3875,0x5061, 0, 0, 0, 0,0x3C5A,
+ 0,0x5069, 0,0x4A6F,0x434D,0x5065,0x3771, 0,
+0x5062,0x506A,0x5064,0x4E51,0x506B,0x4F41, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3666, 0,
+ 0,0x3770, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5070, 0, 0, 0,0x5071,
+0x5075,0x304E, 0, 0, 0, 0, 0,0x4A50,
+0x5074, 0, 0, 0, 0,0x5073,0x5077, 0,
+ 0, 0,0x5076, 0,0x4464, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3772, 0, 0,
+ 0, 0, 0, 0,0x5078, 0, 0, 0,
+ 0, 0,0x3C45, 0,0x4226,0x4465,0x3676, 0,
+0x5079, 0, 0, 0, 0,0x3536, 0, 0,
+0x507A, 0, 0, 0, 0,0x507C, 0, 0,
+ 0, 0, 0, 0, 0,0x4B35, 0, 0,
+ 0,0x3766, 0, 0, 0, 0, 0, 0,
+0x3B31,0x4877,0x507B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3A45,0x4D43, 0, 0,
+ 0, 0,0x507E,0x5123,0x507D,0x3A44, 0,0x3D7D,
+ 0, 0, 0, 0, 0, 0,0x3739, 0,
+ 0, 0,0x5124, 0, 0,0x364F, 0, 0,
+ 0,0x5121,0x5122, 0, 0,0x462F, 0,0x417C,
+ 0,0x3623, 0, 0, 0,0x4B4D,0x5125, 0,
+ 0, 0,0x4E3D, 0, 0, 0,0x5126, 0,
+ 0, 0, 0,0x5129, 0,0x5127, 0,0x414E,
+ 0, 0, 0, 0, 0,0x5128,0x512A, 0,
+ 0, 0, 0, 0, 0,0x512C, 0, 0,
+ 0,0x512B, 0,0x4A48, 0, 0, 0, 0,
+0x3537,0x512E,0x512F, 0,0x322F, 0, 0, 0,
+ 0,0x512D, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3C74, 0,0x5132,0x5131,0x5130, 0,
+0x5056, 0,0x5133, 0, 0, 0, 0,0x3D7E,
+ 0,0x5134, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4D25, 0, 0, 0, 0, 0,
+ 0, 0,0x4C59, 0, 0, 0, 0,0x5136,
+ 0, 0,0x5135,0x5138,0x5137, 0, 0,0x5139,
+0x513A,0x3074, 0,0x3835,0x373B,0x3D3C,0x437B,0x3624,
+0x4068,0x3877, 0,0x396E,0x513C,0x4C48,0x4546, 0,
+0x3B79, 0,0x513B, 0,0x513D, 0, 0, 0,
+ 0, 0,0x455E, 0,0x3375, 0, 0, 0,
+ 0, 0,0x513E, 0, 0,0x467E, 0, 0,
+0x4134,0x5140,0x5141,0x482C,0x3878,0x4F3B,0x5142, 0,
+ 0,0x3626, 0, 0, 0,0x4A3C,0x4236,0x3671,
+0x4535, 0, 0, 0,0x3773, 0, 0, 0,
+0x5143, 0,0x5144, 0, 0,0x4662,0x315F, 0,
+ 0,0x5147,0x3A7D, 0,0x5146,0x3A46, 0,0x5148,
+0x666E,0x5149,0x4B41,0x514A, 0,0x514B,0x514C,0x3E69,
+ 0,0x3C4C, 0, 0, 0, 0, 0, 0,
+0x3427, 0,0x514F, 0,0x514D,0x4C3D,0x514E, 0,
+0x495A,0x5150,0x5151,0x5152,0x455F, 0, 0, 0,
+0x5156,0x5154,0x5155,0x5153,0x3A63,0x5157,0x4C6A,0x4E64,
+ 0, 0, 0, 0, 0,0x5158, 0, 0,
+ 0, 0, 0, 0,0x4028,0x5159,0x3D5A, 0,
+ 0,0x515A, 0,0x437C,0x4E3F,0x4560, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5245, 0,
+ 0, 0, 0,0x515B,0x7425,0x3645, 0, 0,
+0x515C,0x4B5E, 0, 0, 0, 0,0x3D68,0x427C,
+ 0,0x515E,0x4664, 0, 0,0x515F, 0, 0,
+0x5160,0x332E, 0, 0, 0,0x5161,0x3627, 0,
+0x464C,0x317A,0x3D50, 0, 0,0x4821,0x5162, 0,
+0x4561, 0, 0,0x3F4F,0x5163, 0,0x4A2C,0x405A,
+0x3422, 0,0x3429,0x5164, 0, 0,0x5166, 0,
+ 0,0x373A, 0, 0,0x5165, 0, 0,0x4E73,
+ 0, 0, 0, 0, 0,0x3D69, 0, 0,
+ 0, 0, 0, 0,0x483D,0x4A4C, 0,0x5167,
+ 0,0x4D78,0x5168, 0, 0, 0,0x5169, 0,
+0x457E, 0, 0,0x516A, 0, 0,0x4029,0x3A7E,
+0x3774,0x516B,0x3B49,0x396F, 0, 0, 0, 0,
+ 0, 0, 0,0x4466,0x516D, 0, 0,0x4227,
+ 0, 0,0x3A6F,0x516E,0x516F,0x4130, 0,0x516C,
+ 0, 0, 0, 0,0x5171, 0,0x4B36, 0,
+ 0, 0, 0,0x3964, 0, 0,0x5170, 0,
+ 0, 0, 0,0x3775,0x3A5E,0x476D, 0, 0,
+ 0,0x5174,0x5172, 0, 0, 0, 0,0x497B,
+0x3E6A,0x517B,0x3364,0x5175,0x5173,0x414F, 0, 0,
+ 0, 0, 0, 0, 0,0x5177, 0,0x5176,
+ 0, 0, 0,0x3344, 0, 0, 0,0x3760,
+0x517C,0x4E2D, 0, 0, 0,0x5178, 0, 0,
+ 0,0x517D,0x517A, 0,0x5179, 0, 0, 0,
+ 0, 0, 0,0x4E4F, 0, 0, 0,0x3879,
+0x3243, 0, 0,0x4E74, 0, 0, 0, 0,
+ 0,0x3D75,0x4558,0x3965,0x5222,0x5223, 0, 0,
+ 0,0x4E65, 0, 0,0x4F2B,0x5225, 0, 0,
+ 0,0x387A, 0, 0,0x5224, 0,0x332F, 0,
+ 0,0x5226, 0,0x4B56, 0,0x443C, 0,0x4D26,
+ 0,0x4A59, 0, 0, 0,0x5227, 0, 0,
+ 0, 0,0x7055, 0, 0,0x4630, 0,0x5228,
+0x342A,0x4C33, 0, 0, 0,0x3E21,0x5229,0x4A67,
+0x522D, 0,0x402A,0x522A,0x3650, 0,0x522B,0x342B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x372E,0x522E, 0,0x522F, 0, 0,
+0x5230,0x5231,0x3C5B, 0, 0, 0,0x387B,0x4C5E,
+ 0,0x4C68,0x4677, 0, 0,0x4A71,0x5232, 0,
+0x5233, 0, 0, 0, 0,0x5235, 0,0x5237,
+0x5236, 0, 0, 0, 0,0x5238,0x323D,0x4B4C,
+ 0,0x3A7C,0x5239, 0, 0,0x4159, 0, 0,
+0x3E22,0x3629, 0,0x523A, 0, 0, 0, 0,
+ 0, 0,0x485B, 0, 0, 0, 0,0x523B,
+ 0,0x523C, 0,0x523D, 0, 0, 0, 0,
+0x523E,0x4924,0x3668,0x3065, 0, 0, 0,0x463F,
+0x523F,0x3D3D, 0,0x4069, 0,0x5241,0x5240,0x3E23,
+0x3861,0x5243,0x483E, 0, 0,0x5244, 0, 0,
+ 0,0x485C,0x4234,0x426E,0x3628, 0, 0,0x466E,
+0x4331, 0,0x476E, 0,0x4B4E, 0,0x5246, 0,
+0x406A, 0, 0, 0, 0, 0,0x3735, 0,
+ 0,0x5247, 0, 0, 0, 0,0x5248,0x312C,
+0x3075,0x346D, 0,0x4228,0x3551,0x4D71, 0,0x524B,
+0x3237, 0, 0,0x524A, 0, 0, 0,0x362A,
+ 0, 0,0x524C, 0,0x4C71, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x524D, 0,
+0x4E52, 0,0x387C, 0, 0, 0, 0,0x3836,
+0x524E, 0, 0, 0, 0,0x5250,0x524F, 0,
+0x3F5F,0x3139, 0, 0, 0,0x315E,0x5251, 0,
+0x5252, 0, 0,0x3837, 0, 0,0x5253, 0,
+ 0, 0, 0,0x356E, 0, 0, 0, 0,
+ 0, 0,0x3B32,0x5254, 0, 0, 0, 0,
+0x4B74,0x3A35,0x355A,0x4D27,0x4150,0x483F,0x3C7D, 0,
+ 0, 0, 0, 0,0x3D47, 0,0x3C68,0x3C75,
+ 0,0x3D76, 0,0x4840, 0, 0, 0,0x5257,
+ 0,0x3143,0x4151,0x387D,0x3845,0x3667, 0, 0,
+0x525B,0x4321,0x427E,0x362B,0x3E24,0x525C,0x525A,0x3244,
+0x4266,0x3C38,0x3B4B,0x3126, 0, 0,0x3370,0x3966,
+0x3B4A, 0,0x525D, 0, 0, 0, 0, 0,
+ 0,0x525E, 0,0x3549,0x3346, 0, 0, 0,
+0x3967,0x3548,0x445F,0x3125,0x4631,0x4C3E,0x3921,0x4D79,
+0x4547,0x387E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x372F, 0,0x5267, 0,0x3663,
+0x4B4A, 0, 0, 0, 0, 0,0x485D, 0,
+ 0,0x5266, 0,0x345E,0x5261,0x5262,0x5264, 0,
+ 0, 0, 0, 0, 0, 0,0x5265, 0,
+0x355B,0x3F61, 0,0x4A2D,0x5263,0x525F,0x3863, 0,
+0x5260, 0,0x4F24, 0, 0, 0,0x4A72, 0,
+0x4468,0x3862,0x3970, 0, 0, 0,0x5268, 0,
+ 0,0x465D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x526C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3C7E, 0,0x3C76, 0, 0, 0, 0, 0,
+0x526F,0x526D, 0,0x4C23, 0,0x526A,0x5273,0x526E,
+ 0, 0, 0,0x5271,0x3846,0x4C3F, 0, 0,
+0x5272, 0, 0, 0,0x5274, 0,0x5276, 0,
+ 0, 0, 0,0x3A70,0x4F42, 0,0x526B,0x5269,
+0x5275, 0,0x5270, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5278, 0,0x5323,0x527A, 0, 0,
+0x527E, 0, 0,0x5321,0x527B, 0, 0,0x533E,
+ 0, 0,0x3A69,0x3331, 0, 0, 0, 0,
+0x5279, 0, 0, 0,0x5325,0x3076,0x5324, 0,
+0x3025,0x494A,0x5322, 0,0x527C, 0, 0,0x5277,
+0x527D,0x3A48, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5326, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3077,0x532F, 0, 0,0x5327,0x5328, 0,
+0x3E25,0x4B69, 0, 0, 0,0x532D,0x532C, 0,
+ 0, 0,0x452F, 0, 0, 0, 0, 0,
+ 0, 0,0x532E, 0, 0,0x532B, 0, 0,
+ 0, 0, 0, 0,0x3134, 0,0x3A36,0x3F30,
+ 0, 0, 0, 0, 0, 0, 0,0x5329,
+0x4562, 0, 0, 0,0x532A, 0,0x3022};
+
+/* page 30 0x552E-0x5563 */
+static uint16 tab_uni_jisx020830[]={
+0x5334,0x4D23, 0,0x3E27, 0,0x533A, 0, 0,
+ 0, 0,0x5339,0x5330, 0, 0, 0, 0,
+0x4243, 0,0x5331, 0, 0, 0,0x426F,0x5336,
+0x3E26, 0, 0, 0, 0, 0,0x5333, 0,
+ 0,0x4C64, 0, 0, 0,0x373C, 0, 0,
+0x5337,0x5338, 0, 0, 0, 0,0x5335,0x533B,
+ 0, 0, 0, 0, 0,0x5332};
+
+/* page 31 0x557B-0x576A */
+static uint16 tab_uni_jisx020831[]={
+0x5341,0x5346, 0,0x5342, 0,0x533D, 0, 0,
+0x5347,0x4131, 0, 0,0x5349, 0,0x3922,0x533F,
+0x437D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5343,0x533C,0x342D,
+ 0,0x346E,0x3365,0x5344,0x5340, 0, 0, 0,
+ 0, 0, 0, 0,0x3776,0x534A,0x5348,0x4153,
+0x354A,0x362C, 0,0x5345, 0,0x3674, 0, 0,
+ 0, 0, 0,0x3144, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x534E,0x534C, 0,0x5427, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5351, 0, 0, 0, 0, 0,0x534B,
+ 0,0x534F, 0, 0,0x534D, 0, 0, 0,
+0x3B4C,0x5350, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5353, 0,0x5358, 0,
+ 0, 0,0x5356,0x5355, 0, 0, 0, 0,
+ 0, 0, 0,0x4332, 0, 0,0x3245, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5352, 0,0x5354,0x3E28,0x3133, 0, 0,
+0x5357, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x325E, 0,
+ 0, 0, 0, 0,0x5362, 0,0x3E7C,0x535E,
+ 0,0x535C, 0,0x535D, 0,0x535F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x313D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4139, 0,0x5359, 0,0x535A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x337A, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5361, 0, 0, 0,0x346F, 0,0x5364,
+0x5360,0x5363, 0, 0, 0, 0, 0, 0,
+ 0,0x4A2E, 0, 0, 0,0x4655, 0,0x4838,
+ 0, 0, 0, 0, 0,0x5366, 0, 0,
+ 0, 0, 0,0x5365,0x3345, 0, 0,0x5367,
+ 0, 0, 0, 0,0x536A, 0, 0, 0,
+ 0,0x5369, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5368, 0,0x4739,
+ 0, 0,0x536B, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x536C, 0, 0, 0, 0,
+ 0,0x536E, 0,0x536D, 0, 0, 0, 0,
+ 0,0x5370, 0, 0, 0,0x5373,0x5371,0x536F,
+0x5372, 0, 0, 0, 0,0x5374, 0, 0,
+ 0, 0, 0,0x5375, 0, 0,0x5376, 0,
+0x5377, 0, 0, 0,0x5378,0x5145, 0,0x3C7C,
+0x3B4D, 0, 0,0x3273, 0,0x3078, 0, 0,
+0x4344, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5379, 0,0x3A24, 0,0x304F,
+0x3F5E, 0, 0, 0, 0, 0,0x537A,0x3847,
+ 0, 0,0x3971, 0,0x537C,0x537B, 0, 0,
+0x4A60,0x537D, 0, 0, 0,0x5421,0x537E, 0,
+0x5422, 0,0x5423, 0,0x3777, 0, 0,0x3160,
+0x5424, 0, 0,0x5426, 0,0x5425, 0, 0,
+ 0,0x5428, 0, 0,0x455A, 0, 0, 0,
+ 0, 0, 0,0x5429,0x3035,0x3A5F, 0, 0,
+ 0, 0,0x373D, 0, 0,0x434F, 0, 0,
+ 0, 0, 0, 0,0x542A,0x542B, 0, 0,
+0x542D, 0, 0, 0, 0,0x542E, 0,0x3A64,
+ 0, 0, 0, 0,0x3651, 0, 0,0x4B37,
+ 0, 0, 0,0x542C,0x542F,0x3A41,0x3923, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5433, 0,
+ 0,0x3A25, 0,0x4333, 0, 0,0x5430,0x445A
+};
+
+/* page 32 0x577F-0x5A9B */
+static uint16 tab_uni_jisx020832[]={
+0x5434, 0, 0,0x3F62, 0, 0, 0, 0,
+ 0,0x5432,0x5435, 0,0x373F, 0, 0, 0,
+ 0, 0, 0, 0,0x5436, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5437, 0,0x3924,0x3340,0x5439, 0, 0,
+ 0, 0, 0,0x543A, 0, 0, 0, 0,
+ 0,0x543B, 0, 0,0x5438, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5431, 0, 0,0x543C, 0, 0,0x543D,
+ 0, 0, 0, 0,0x4B64, 0, 0,0x3E6B,
+ 0, 0, 0,0x543F,0x5440,0x543E, 0,0x5442,
+ 0, 0, 0, 0, 0,0x4738, 0, 0,
+0x3068,0x4956, 0, 0,0x5443, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3E7D, 0, 0,
+0x3C39, 0,0x475D,0x3470, 0,0x3A6B, 0, 0,
+ 0,0x4B59, 0,0x4632, 0, 0,0x3778,0x424F,
+ 0, 0, 0,0x5441,0x5444, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4244, 0,
+ 0, 0,0x5445, 0, 0, 0,0x5446, 0,
+ 0, 0,0x5448, 0, 0,0x4469, 0, 0,
+ 0, 0, 0,0x342E, 0, 0, 0, 0,
+0x7421,0x3161,0x4A73, 0, 0,0x3E6C,0x4548, 0,
+ 0, 0, 0,0x3A66, 0, 0,0x544E, 0,
+ 0,0x4A3D,0x4E5D, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3274,0x544A, 0, 0, 0,
+ 0, 0,0x413A,0x544D, 0,0x4563, 0, 0,
+0x4549,0x4564,0x4839,0x444D, 0, 0, 0,0x3A49,
+ 0, 0, 0,0x5449, 0, 0, 0, 0,
+ 0, 0,0x3176, 0,0x4536, 0, 0, 0,
+ 0,0x544B, 0,0x5447, 0, 0,0x3F50, 0,
+ 0, 0,0x544F, 0, 0, 0, 0,0x3D4E,
+ 0, 0, 0, 0,0x362D, 0,0x5450, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4A68, 0, 0, 0,
+0x417D, 0, 0, 0, 0,0x4446, 0, 0,
+0x5452, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4B4F, 0, 0,0x5453, 0, 0,0x5458,
+ 0, 0, 0, 0,0x4A2F, 0, 0, 0,
+ 0,0x5457,0x5451,0x5454,0x5456, 0, 0,0x3A26,
+ 0, 0,0x4A49, 0, 0, 0,0x5459, 0,
+0x4345, 0, 0,0x3275, 0,0x3E6D, 0, 0,
+ 0, 0,0x545B, 0,0x545A, 0,0x3968, 0,
+0x545C,0x545E,0x545D, 0, 0,0x5460, 0,0x5455,
+0x5462, 0, 0, 0, 0,0x5461,0x545F, 0,
+ 0, 0, 0, 0,0x3B4E,0x3F51, 0,0x4154,
+0x5463,0x403C,0x306D,0x4764, 0, 0, 0, 0,
+0x445B, 0,0x5465,0x5464,0x5466,0x5467,0x5468, 0,
+ 0, 0, 0,0x5469, 0, 0, 0, 0,
+ 0, 0,0x4A51,0x546A, 0, 0, 0, 0,
+0x3246,0x546B, 0, 0, 0, 0,0x4D3C,0x3330,
+ 0,0x5249,0x3D48,0x423F,0x546C,0x4C6B, 0, 0,
+ 0, 0, 0,0x4C34, 0, 0,0x546E, 0,
+0x4267, 0,0x4537,0x4240,0x4957,0x546F,0x5470,0x317B,
+ 0, 0,0x3C3A,0x5471, 0, 0, 0, 0,
+0x3050,0x5472, 0, 0, 0, 0, 0,0x5473,
+ 0, 0, 0, 0, 0,0x3162, 0, 0,
+0x3471,0x4660,0x4A74, 0, 0, 0, 0,0x5477,
+0x4155,0x5476,0x3740, 0, 0,0x4B5B,0x5475, 0,
+0x4565,0x5479, 0,0x5478, 0, 0, 0, 0,
+ 0,0x547B, 0,0x547A, 0, 0,0x317C, 0,
+0x547C,0x3E29,0x547E,0x4325, 0,0x547D, 0,0x4A33,
+ 0, 0, 0, 0,0x3D77,0x455B, 0, 0,
+ 0,0x5521, 0, 0, 0, 0,0x3925, 0,
+ 0, 0,0x5522,0x4721,0x485E,0x4C51, 0, 0,
+ 0, 0, 0,0x4725, 0, 0,0x552B, 0,
+ 0, 0, 0, 0,0x3538, 0, 0,0x4D45,
+ 0, 0,0x4C2F, 0,0x562C, 0,0x5523, 0,
+ 0, 0, 0, 0,0x5526, 0,0x4245, 0,
+ 0,0x4B38, 0, 0, 0,0x454A, 0, 0,
+ 0, 0, 0,0x5527, 0, 0, 0, 0,
+ 0, 0,0x4B65, 0,0x3A4A, 0, 0,0x3E2A,
+ 0, 0, 0, 0, 0, 0, 0,0x5528,
+ 0, 0,0x3B50, 0,0x3B4F, 0, 0, 0,
+ 0,0x3039,0x3848, 0,0x402B,0x3051, 0, 0,
+ 0, 0,0x552C,0x552D, 0,0x552A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3138,0x342F,
+ 0,0x5529, 0,0x4C45,0x4931, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3028,
+ 0, 0, 0, 0,0x3079, 0, 0, 0,
+0x3B51, 0,0x3052, 0,0x3023, 0, 0, 0,
+ 0, 0,0x5532, 0, 0, 0, 0, 0,
+ 0, 0,0x5530, 0, 0, 0, 0, 0,
+ 0,0x4C3C, 0,0x5533, 0,0x5531, 0, 0,
+0x552F,0x3F31, 0, 0, 0, 0,0x552E, 0,
+ 0, 0,0x4A5A, 0, 0, 0, 0, 0,
+0x3864, 0, 0, 0, 0, 0,0x5537,0x5538,
+ 0, 0, 0, 0, 0,0x3E2B, 0, 0,
+ 0,0x5534,0x4F2C, 0, 0, 0, 0,0x474C,
+ 0, 0,0x5536, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3A27, 0, 0, 0, 0,
+ 0, 0, 0,0x5539, 0, 0, 0,0x4958,
+ 0, 0, 0,0x553A, 0,0x5535, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4C3B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x475E, 0, 0, 0, 0,
+ 0, 0, 0,0x553B,0x4932};
+
+/* page 33 0x5ABC-0x5D29 */
+static uint16 tab_uni_jisx020833[]={
+0x553C,0x5540,0x553D, 0, 0,0x3247,0x553F, 0,
+ 0, 0, 0, 0, 0,0x3C3B, 0,0x553E,
+0x3779, 0, 0, 0,0x554C, 0, 0, 0,
+ 0, 0,0x5545,0x5542, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4364, 0,0x5541,
+ 0, 0,0x5543, 0, 0,0x5544, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5546,0x5547,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3472, 0,0x5549,
+0x5548, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x554A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3E6E, 0,
+ 0, 0, 0, 0, 0, 0,0x554D, 0,
+0x445C, 0, 0, 0,0x3145, 0,0x554B, 0,
+ 0, 0,0x554E, 0, 0, 0, 0, 0,
+ 0, 0,0x554F, 0,0x5552, 0, 0,0x5550,
+ 0,0x5551, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3B52,0x5553, 0, 0,
+0x3926,0x5554, 0,0x3B7A,0x4238, 0,0x5555,0x5556,
+0x3B5A,0x3927, 0,0x4C52, 0, 0, 0,0x3528,
+0x3849,0x5557,0x3358, 0, 0,0x5558, 0,0x4239,
+ 0, 0, 0, 0,0x5559,0x5623, 0,0x555A,
+ 0,0x555B, 0, 0,0x555C, 0,0x555E, 0,
+ 0, 0, 0, 0,0x555F, 0, 0,0x5560,
+ 0,0x4270, 0,0x3127,0x3C69,0x3042, 0,0x4157,
+0x3430,0x3C35, 0,0x3928, 0, 0, 0, 0,
+ 0,0x4566, 0,0x3D21,0x3431,0x4368,0x446A,0x3038,
+0x3539,0x4A75, 0,0x3C42, 0, 0,0x3552,0x406B,
+0x3C3C,0x4D28,0x5561, 0, 0, 0, 0, 0,
+ 0, 0,0x355C, 0,0x3A4B, 0, 0,0x3332,
+0x3163,0x3E2C,0x3248, 0,0x5562,0x4D46, 0, 0,
+ 0, 0, 0,0x3D49, 0, 0,0x3C64,0x5563,
+0x3473,0x4652,0x4C29,0x5564, 0,0x5565, 0, 0,
+0x4959, 0, 0, 0,0x5567, 0,0x3428,0x3677,
+0x5566, 0, 0, 0, 0, 0, 0,0x3432,
+ 0,0x3F32,0x556B,0x3B21, 0,0x3249,0x556A, 0,
+0x5568,0x556C,0x5569,0x472B,0x5C4D,0x3F33, 0,0x556D,
+ 0, 0,0x4E40, 0,0x556E, 0, 0,0x5570,
+ 0,0x437E,0x556F, 0,0x4023, 0,0x3B7B, 0,
+ 0, 0,0x4250,0x3C77, 0,0x4975,0x406C, 0,
+0x3C4D,0x5571,0x3E2D,0x5572,0x5573,0x3053,0x423A,0x3F52,
+ 0,0x5574,0x4633,0x3E2E, 0,0x3E2F, 0,0x5575,
+ 0, 0,0x406D, 0, 0, 0,0x3E30, 0,
+ 0, 0, 0, 0,0x5576, 0,0x5577, 0,
+0x4C60, 0, 0, 0,0x5578, 0, 0, 0,
+ 0,0x3646, 0, 0, 0,0x3D22, 0, 0,
+ 0, 0, 0, 0,0x5579,0x557A,0x3C5C,0x3F2C,
+0x4674,0x3F54,0x4878,0x4722,0x3649,0x557B, 0, 0,
+ 0,0x356F,0x557C, 0,0x367E, 0,0x464F,0x3230,
+ 0,0x3B53,0x557D,0x5622,0x5621,0x367D, 0,0x557E,
+ 0,0x4538, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4230, 0,0x454B,0x3C48, 0, 0,
+0x4158,0x4D7A, 0, 0, 0, 0, 0, 0,
+0x5624, 0,0x5625,0x4656, 0,0x3B33, 0, 0,
+ 0, 0,0x5627, 0, 0,0x5628, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5629, 0, 0, 0,0x3474,0x562A, 0, 0,
+0x562B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x322C, 0, 0,
+ 0, 0, 0, 0,0x413B,0x3464, 0,0x562D,
+0x4C28, 0, 0, 0, 0,0x4252, 0,0x3359,
+ 0, 0,0x562F,0x5631,0x345F, 0, 0,0x562E,
+0x5630, 0,0x5633, 0, 0, 0, 0, 0,
+ 0,0x5632, 0,0x5634, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5635, 0, 0,
+ 0, 0, 0, 0,0x463D,0x362E, 0, 0,
+ 0, 0, 0, 0,0x3265,0x5636,0x563B, 0,
+ 0,0x5639, 0,0x4A77,0x4A76, 0, 0, 0,
+ 0, 0,0x4567, 0, 0, 0,0x5638,0x3D54,
+ 0,0x5637, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3F72, 0, 0, 0,0x563C,
+ 0, 0,0x3A6A, 0, 0,0x5642, 0, 0,
+0x5643,0x563D,0x3333,0x563E,0x5647,0x5646,0x5645,0x5641,
+ 0, 0, 0,0x5640, 0, 0,0x5644, 0,
+ 0, 0, 0, 0, 0,0x4A78};
+
+/* page 34 0x5D4B-0x6BF3 */
+static uint16 tab_uni_jisx020834[]={
+0x564B,0x5648, 0,0x564A, 0,0x4D72, 0,0x5649,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x563F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3F73, 0,
+ 0,0x564C, 0, 0,0x3A37, 0, 0, 0,
+0x564D, 0, 0,0x564E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5651,
+ 0,0x5650, 0, 0,0x564F, 0, 0, 0,
+0x4568,0x563A, 0, 0, 0,0x5657, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5653, 0, 0, 0, 0,0x5652,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5654, 0,0x5655, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5658, 0, 0,0x4E66,
+ 0,0x5659,0x5656, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x565A, 0,
+ 0,0x3460,0x565B, 0, 0, 0, 0,0x565D,
+0x565C, 0, 0,0x565E, 0, 0, 0, 0,
+0x565F, 0,0x406E,0x3D23, 0, 0,0x3D64, 0,
+0x4163, 0,0x3929,0x3A38,0x392A,0x3570, 0, 0,
+0x5660, 0, 0,0x3A39, 0, 0,0x384A,0x5661,
+0x4C26,0x4743,0x5662, 0,0x392B, 0, 0, 0,
+0x342C, 0,0x4327,0x3652, 0, 0, 0,0x3B54,
+0x495B, 0, 0,0x4841, 0, 0, 0, 0,
+0x5663,0x3475, 0, 0, 0, 0,0x5666, 0,
+ 0, 0, 0,0x4421, 0, 0,0x5665,0x5664,
+0x5667, 0,0x446B, 0, 0, 0, 0, 0,
+ 0, 0,0x3F63, 0, 0, 0, 0, 0,
+0x3B55, 0,0x404A, 0,0x4253,0x3522, 0, 0,
+0x4422, 0, 0,0x5668,0x5669,0x3E6F, 0, 0,
+ 0, 0,0x4B39, 0, 0,0x566C, 0, 0,
+0x566B,0x566A,0x497D, 0,0x5673, 0, 0, 0,
+ 0,0x4B5A, 0,0x566D, 0, 0, 0, 0,
+ 0,0x566F,0x4B6B, 0,0x566E, 0, 0, 0,
+ 0, 0, 0, 0,0x5670, 0,0x4828,0x5671,
+0x4A3E,0x5672, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3433,
+0x4A3F,0x472F,0x5674,0x5675, 0,0x392C,0x3434,0x5676,
+0x3838,0x4D44,0x4D29,0x3476,0x5678, 0,0x4423, 0,
+0x392D,0x3E31, 0, 0,0x485F, 0, 0,0x3E32,
+ 0, 0, 0, 0,0x3D78, 0, 0, 0,
+ 0, 0,0x446C,0x4A79,0x4539, 0, 0,0x392E,
+ 0,0x495C, 0, 0, 0,0x5679, 0, 0,
+ 0, 0, 0,0x4559,0x3A42, 0, 0, 0,
+0x384B, 0,0x446D, 0, 0, 0, 0, 0,
+ 0, 0,0x3043,0x3D6E,0x392F,0x4D47, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x567A,0x567B,
+0x4751, 0, 0, 0, 0,0x567C,0x4E77,0x4F2D,
+ 0, 0, 0, 0,0x567E,0x567D, 0, 0,
+0x3347, 0, 0,0x5721, 0, 0, 0,0x5724,
+0x5725, 0,0x5723, 0,0x4940,0x3E33,0x5727,0x5726,
+0x5722, 0, 0, 0, 0,0x5728,0x5729, 0,
+ 0,0x572A, 0, 0, 0,0x572D,0x572B, 0,
+0x572C,0x572E, 0,0x3164,0x446E,0x572F, 0,0x377A,
+0x3276,0x4736, 0,0x5730,0x467B, 0,0x4A5B, 0,
+0x5731,0x4F2E, 0, 0, 0, 0,0x5732,0x4A40,
+0x5735,0x5021,0x5031, 0,0x3C30,0x4675,0x5736, 0,
+0x355D,0x4424,0x307A,0x5737,0x4A26,0x3930, 0, 0,
+0x4350, 0, 0, 0,0x446F, 0, 0, 0,
+ 0, 0,0x4C6F,0x3839,0x384C, 0,0x5738, 0,
+ 0, 0,0x5739, 0,0x573F, 0,0x3C65, 0,
+ 0, 0,0x4425, 0,0x362F,0x573A, 0, 0,
+ 0,0x492B, 0,0x4346, 0, 0,0x573B, 0,
+ 0, 0, 0, 0, 0,0x573C, 0,0x3630,
+ 0,0x573D, 0,0x573E, 0, 0,0x5740, 0,
+0x4576, 0, 0,0x5741,0x5742, 0,0x5743, 0,
+ 0,0x5734,0x5733, 0, 0, 0,0x5744,0x3741,
+ 0, 0, 0,0x4927, 0, 0,0x3A4C,0x4937,
+0x4426,0x494B,0x5745, 0, 0,0x3E34,0x3146, 0,
+0x5746, 0, 0, 0,0x5747, 0,0x4C72, 0,
+ 0,0x4860, 0, 0,0x574A,0x317D,0x402C,0x5749,
+0x5748,0x3742,0x4254, 0,0x574E,0x574C, 0,0x574B,
+0x4E27,0x3865, 0, 0, 0,0x3D79,0x574D,0x454C,
+0x3D3E, 0, 0, 0,0x4640,0x5751,0x5750, 0,
+ 0, 0, 0,0x574F, 0,0x5752,0x3866, 0,
+ 0, 0, 0, 0, 0,0x5753,0x497C,0x3D5B,
+ 0, 0,0x5754,0x4879, 0, 0, 0, 0,
+0x4641,0x4427, 0, 0, 0, 0,0x4530, 0,
+ 0,0x5755,0x352B, 0, 0, 0, 0, 0,
+0x3F34, 0,0x492C, 0, 0, 0, 0, 0,
+ 0,0x3477,0x4726, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5756,0x3B56,0x4B3A,0x4B3B, 0,
+ 0,0x317E,0x575B, 0, 0,0x4369, 0, 0,
+ 0,0x5758, 0, 0, 0, 0, 0, 0,
+0x3277, 0, 0, 0, 0,0x582D,0x575A, 0,
+ 0, 0,0x4730, 0, 0,0x5759, 0, 0,
+0x5757, 0,0x397A, 0,0x575D, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5763,0x5769,0x5761, 0,0x455C,
+ 0, 0,0x5766,0x495D, 0, 0,0x5760, 0,
+0x5765,0x4E67,0x3B57, 0, 0,0x4255,0x575E, 0,
+ 0, 0,0x355E,0x5768,0x402D,0x3165,0x5762,0x3278,
+0x5767, 0, 0, 0,0x3631, 0,0x5764, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x576A,
+ 0, 0, 0, 0, 0, 0,0x576C,0x5776,
+0x5774, 0, 0,0x5771, 0, 0, 0,0x5770,
+0x4E78, 0,0x5772, 0, 0,0x3632, 0,0x3931,
+ 0, 0,0x3D7A, 0, 0, 0,0x5779,0x576B,
+ 0, 0, 0, 0,0x576F,0x575F, 0,0x327A,
+0x5773,0x5775,0x4351, 0, 0,0x3A28,0x3238,0x576D,
+0x5778,0x5777,0x3633, 0,0x4229,0x3366, 0, 0,
+ 0, 0,0x3743, 0,0x576E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x577A, 0,
+0x577D,0x5821, 0, 0, 0, 0,0x3C3D, 0,
+0x5827,0x4470,0x577B, 0, 0, 0, 0,0x5825,
+ 0,0x3279, 0,0x5823,0x5824, 0, 0,0x577E,
+0x5822, 0, 0, 0,0x3867,0x4D2A, 0, 0,
+0x3435, 0, 0,0x3159,0x5826, 0,0x473A,0x302D,
+ 0, 0, 0, 0, 0, 0, 0,0x4861,
+0x575C,0x582C,0x5830,0x4C65, 0,0x5829, 0, 0,
+ 0,0x4569,0x582E, 0, 0, 0, 0, 0,
+ 0, 0,0x3E70,0x582F,0x4657, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4F47, 0,
+0x582B, 0, 0, 0, 0,0x5831, 0,0x397B,
+ 0,0x404B, 0, 0,0x3054,0x582A,0x5828, 0,
+0x415A, 0, 0, 0,0x577C,0x3B34, 0, 0,
+ 0, 0, 0, 0, 0,0x4246,0x583D, 0,
+0x415B,0x5838, 0,0x5835,0x5836, 0,0x3C66,0x5839,
+0x583C, 0, 0, 0, 0,0x5837,0x3D25, 0,
+0x583A, 0, 0,0x5834, 0,0x4C7C,0x4C7B, 0,
+ 0, 0,0x583E,0x583F,0x3055, 0, 0, 0,
+ 0, 0,0x5833, 0, 0, 0, 0,0x3672,
+0x3026, 0, 0, 0,0x3436, 0,0x583B, 0,
+ 0, 0, 0, 0,0x5843,0x5842, 0, 0,
+ 0,0x5847, 0, 0, 0, 0, 0, 0,
+ 0,0x5848, 0, 0, 0, 0, 0, 0,
+ 0,0x5846,0x5849,0x5841,0x5845, 0, 0,0x584A,
+ 0,0x584B, 0, 0,0x5840,0x3B7C, 0,0x5844,
+0x4256,0x3932,0x5832,0x3F35, 0, 0, 0, 0,
+0x5858, 0,0x4A69, 0, 0,0x584E,0x584F,0x5850,
+ 0, 0,0x5857, 0,0x5856, 0, 0,0x4B7D,
+0x3437, 0,0x5854, 0,0x3745,0x3334, 0, 0,
+0x5851, 0, 0,0x4E38,0x5853,0x3056,0x5855, 0,
+0x584C,0x5852,0x5859,0x3744,0x584D, 0, 0, 0,
+ 0, 0, 0,0x4D5D, 0, 0, 0,0x4D2B,
+ 0, 0, 0, 0,0x585C, 0, 0,0x5860,
+ 0, 0, 0,0x417E, 0,0x4E79,0x5861, 0,
+ 0,0x585E, 0,0x585B, 0, 0,0x585A,0x585F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4A30, 0, 0,0x4634, 0,0x3746, 0,
+0x5862,0x585D, 0,0x5863, 0, 0, 0,0x377B,
+ 0, 0, 0,0x3231, 0, 0, 0,0x586B,
+ 0, 0, 0,0x3438, 0, 0, 0, 0,
+0x5869, 0, 0,0x586A,0x3A29,0x5868,0x5866,0x5865,
+0x586C,0x5864,0x586E, 0, 0,0x327B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5870, 0, 0,0x586F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4428,
+ 0,0x5873, 0,0x5871,0x5867,0x377C, 0,0x5872,
+ 0,0x5876,0x5875,0x5877,0x5874,0x5878, 0, 0,
+ 0, 0, 0, 0, 0,0x5879,0x587A,0x4A6A,
+ 0,0x587C,0x587B,0x3D3F, 0,0x402E,0x3266,0x327C,
+ 0,0x587D, 0,0x303F, 0, 0, 0,0x404C,
+0x587E, 0,0x6C43,0x5921,0x3761, 0,0x5922, 0,
+ 0, 0, 0,0x406F, 0, 0, 0,0x5923,
+ 0, 0, 0,0x5924,0x353A,0x5925, 0,0x5926,
+0x5927,0x4257, 0, 0, 0,0x384D, 0, 0,
+0x4C61, 0, 0, 0,0x4B3C,0x3D6A,0x5928, 0,
+ 0, 0, 0, 0,0x4070,0x6E3D,0x4862, 0,
+0x3C6A, 0,0x3A4D,0x5929, 0, 0, 0, 0,
+0x4247, 0,0x4A27, 0, 0,0x4271, 0, 0,
+0x592C, 0, 0,0x592A, 0,0x592D, 0, 0,
+0x592B, 0, 0, 0, 0,0x592E, 0, 0,
+ 0, 0, 0,0x4A31, 0, 0,0x3037, 0,
+ 0, 0, 0,0x495E, 0, 0,0x4863, 0,
+ 0,0x592F, 0,0x5932,0x3E35,0x353B, 0,0x5930,
+0x5937,0x3E36, 0, 0, 0, 0,0x5931,0x4744,
+ 0, 0, 0, 0, 0, 0,0x4D5E,0x5933,
+0x5934,0x5938,0x456A,0x5935,0x3933,0x405E, 0, 0,
+0x5946,0x4834, 0,0x4272, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4864,0x5A2D, 0, 0, 0, 0,0x4A7A, 0,
+ 0, 0,0x4471, 0, 0, 0,0x4B75, 0,
+0x593B,0x3221,0x436A, 0, 0, 0, 0,0x5944,
+ 0, 0,0x4334,0x593E,0x5945,0x5940,0x5947,0x5943,
+ 0,0x5942,0x476F, 0,0x593C,0x327D,0x593A,0x3571,
+0x4273,0x5936, 0, 0,0x5939,0x3934,0x405B, 0,
+0x3E37,0x5941,0x4752, 0, 0,0x3572,0x3348, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3367,0x3F21,0x5949,0x594E, 0,0x594A, 0,
+0x377D, 0,0x594F,0x3B22,0x3969, 0, 0, 0,
+ 0, 0, 0,0x3D26,0x593D, 0,0x3B7D,0x594C,
+ 0, 0, 0, 0,0x3B58,0x594D,0x3044, 0,
+ 0,0x5948, 0, 0, 0, 0,0x4429, 0,
+ 0, 0, 0, 0, 0, 0,0x3573, 0,
+ 0, 0, 0, 0,0x3634, 0, 0, 0,
+ 0, 0, 0, 0,0x594B,0x3027, 0, 0,
+0x3A43, 0, 0, 0,0x3F36, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4472,
+ 0, 0,0x4854,0x5951,0x415E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x422A, 0,
+ 0,0x3B2B,0x5952, 0,0x5954,0x5950, 0, 0,
+ 0, 0,0x4A61, 0,0x443D, 0, 0, 0,
+ 0,0x415C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4A7B,0x3C4E,0x5960, 0,
+0x595F, 0, 0,0x3F78, 0, 0, 0,0x377E,
+ 0, 0, 0,0x5959,0x3E39, 0, 0,0x4668,
+0x4731, 0, 0, 0, 0,0x5957, 0, 0,
+0x415D, 0, 0, 0, 0,0x3C78,0x595C, 0,
+ 0,0x3E38, 0,0x5956,0x595B, 0, 0,0x4753,
+ 0, 0, 0,0x5955, 0,0x3721, 0, 0,
+0x335D, 0, 0, 0,0x595D,0x4E2B,0x3A4E,0x4335,
+0x595A, 0,0x405C, 0,0x3935,0x3F64,0x3166,0x413C,
+0x5958,0x3545, 0, 0, 0, 0, 0,0x3747,
+ 0,0x444F,0x595E, 0, 0, 0, 0, 0,
+0x415F, 0, 0,0x5961, 0,0x5963, 0, 0,
+0x4237,0x5969, 0,0x5964, 0, 0,0x5966, 0,
+ 0, 0, 0, 0,0x4941,0x4473, 0,0x5967,
+ 0, 0, 0,0x4D2C, 0, 0, 0,0x4D48,
+0x3439, 0, 0, 0, 0, 0,0x302E, 0,
+0x5965, 0, 0, 0, 0, 0,0x5962, 0,
+ 0, 0, 0,0x3478, 0, 0, 0, 0,
+ 0,0x3167, 0,0x5968, 0, 0, 0,0x4D49,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x596C, 0, 0, 0, 0,
+ 0, 0,0x423B, 0,0x5973, 0, 0, 0,
+0x596D, 0, 0,0x596A,0x5971, 0, 0, 0,
+ 0,0x5953, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x596E, 0,0x5972, 0, 0,
+ 0,0x4842,0x456B, 0, 0, 0, 0, 0,
+ 0,0x596B, 0,0x596F, 0, 0, 0,0x3748,
+ 0, 0, 0,0x3A71, 0, 0, 0,0x405D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5977, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4526, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5974, 0,0x4B60, 0,
+ 0, 0, 0, 0,0x5975, 0, 0, 0,
+ 0, 0, 0,0x5976, 0,0x4C4E, 0,0x4022,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3762, 0, 0, 0, 0,0x597D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3B35,
+0x597A, 0,0x5979, 0, 0, 0, 0,0x4732,
+ 0, 0, 0,0x4635, 0, 0, 0, 0,
+ 0,0x4531,0x597B, 0, 0, 0,0x597C, 0,
+0x496F, 0,0x4745,0x3B23, 0,0x4071, 0,0x4B50,
+ 0, 0, 0, 0, 0, 0,0x3349, 0,
+0x5A25,0x597E, 0, 0, 0, 0,0x4D4A,0x5A27,
+ 0, 0,0x5A23, 0,0x5A24, 0, 0, 0,
+ 0, 0,0x4160, 0, 0, 0, 0,0x5A22,
+ 0,0x593F, 0, 0, 0,0x5A26, 0,0x5A21,
+ 0, 0, 0, 0, 0,0x5A2B,0x5A2C,0x4527,
+0x5A2E, 0, 0,0x3B24,0x5A29, 0, 0, 0,
+ 0,0x353C, 0, 0,0x5A2F, 0,0x5A28,0x5A33,
+ 0,0x5A32, 0,0x5A31, 0, 0, 0,0x5A34,
+ 0, 0,0x5A36,0x3E71, 0,0x5A35, 0, 0,
+ 0, 0,0x5A39, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5A37, 0, 0,
+ 0,0x5A38,0x5970, 0, 0, 0, 0, 0,
+0x5A3B,0x5A3A, 0, 0, 0, 0, 0,0x5978,
+0x5A3C,0x5A30, 0, 0,0x3B59, 0, 0, 0,
+ 0,0x5A3D,0x5A3E,0x5A40,0x5A3F,0x5A41,0x327E, 0,
+0x3936, 0, 0,0x4A7C,0x402F, 0, 0, 0,
+ 0, 0,0x384E, 0, 0,0x5A43, 0, 0,
+ 0, 0,0x5A46, 0,0x4952, 0,0x355F, 0,
+ 0, 0,0x5A45,0x5A44,0x4754,0x5A47,0x3635, 0,
+ 0, 0,0x5A49,0x5A48, 0, 0, 0,0x343A,
+0x3B36, 0, 0,0x4658, 0, 0, 0, 0,
+ 0,0x3749, 0, 0, 0,0x3F74, 0,0x5A4A,
+ 0,0x4030,0x4528, 0,0x495F,0x5A4B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5A4C,
+0x5A4D, 0, 0, 0,0x4A38,0x555D,0x4046, 0,
+ 0,0x494C, 0,0x3A58, 0,0x4865,0x4843, 0,
+ 0, 0, 0, 0,0x454D, 0,0x4E41, 0,
+0x5A4F,0x3C50, 0, 0,0x5A50, 0,0x3036, 0,
+ 0,0x3654,0x404D, 0,0x4960, 0, 0, 0,
+0x5A51,0x3B42,0x4347, 0,0x3B5B,0x3F37, 0, 0,
+ 0, 0, 0, 0,0x5A52, 0,0x4A7D, 0,
+ 0,0x3177,0x3B5C, 0, 0, 0,0x5A55, 0,
+0x5A53,0x5A56,0x4E39,0x5A54, 0, 0, 0, 0,
+0x407B,0x5A57, 0, 0,0x4232, 0, 0,0x5A58,
+ 0, 0, 0, 0,0x347A, 0,0x5A5A, 0,
+0x5A59, 0, 0, 0, 0,0x5A5B,0x5A5C,0x347B,
+ 0, 0,0x467C,0x4336,0x356C,0x3B5D,0x4161, 0,
+ 0,0x3D5C,0x3030, 0, 0, 0,0x5A5D, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3222,
+0x5A61, 0, 0, 0, 0, 0, 0,0x3937,
+0x5A60, 0, 0,0x3A2B,0x3E3A, 0, 0,0x5A5F,
+ 0,0x3E3B, 0,0x4C40,0x3A2A, 0, 0, 0,
+0x3057,0x404E, 0, 0, 0, 0, 0, 0,
+ 0,0x5A66, 0, 0,0x4031,0x3147, 0, 0,
+ 0, 0,0x3D55, 0,0x4B66,0x3A72, 0, 0,
+ 0, 0,0x3E3C, 0,0x4027, 0, 0, 0,
+ 0,0x5A65,0x5A63,0x5A64, 0, 0, 0, 0,
+ 0,0x436B, 0, 0,0x5B26, 0,0x5A6A,0x3B7E,
+0x3938,0x5A68, 0, 0, 0, 0,0x5A69, 0,
+0x3F38, 0, 0, 0,0x5A67, 0, 0,0x3B2F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5A6C,0x5A6B,0x5A70, 0, 0,0x5A71,
+ 0,0x5A6D, 0,0x3322,0x5A6E,0x5A6F,0x4855, 0,
+ 0, 0, 0,0x4961,0x374A,0x5A72, 0, 0,
+ 0,0x4032, 0,0x3E3D, 0, 0, 0,0x4352,
+ 0, 0, 0, 0, 0, 0,0x3647, 0,
+0x5A73,0x5A77, 0, 0,0x324B,0x5A74,0x5A76, 0,
+ 0, 0, 0,0x5A75, 0, 0,0x3D6B, 0,
+ 0, 0, 0,0x4348,0x3045,0x5A78, 0, 0,
+ 0, 0,0x5A79, 0, 0, 0, 0,0x442A,
+ 0, 0, 0,0x4E71, 0, 0, 0, 0,
+0x3B43, 0, 0,0x4A6B, 0, 0, 0, 0,
+ 0,0x4B3D, 0, 0, 0,0x5B22,0x5A7B, 0,
+ 0,0x5A7E, 0,0x5A7D, 0, 0,0x5A7A, 0,
+ 0,0x5B21, 0, 0,0x465E, 0,0x5A7C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5B23, 0, 0,0x3D6C,0x5B24,
+ 0,0x4D4B,0x4778, 0, 0,0x5B25, 0, 0,
+ 0, 0, 0,0x5B27, 0, 0,0x5B28, 0,
+ 0, 0, 0, 0, 0,0x5B29, 0,0x364A,
+0x3148,0x3939,0x5B2A, 0,0x5B2B,0x3D71,0x4162, 0,
+ 0,0x5258,0x413E,0x413D,0x4258,0x3A47, 0, 0,
+0x5072, 0, 0, 0, 0,0x376E,0x4D2D, 0,
+0x4A7E, 0,0x497E, 0,0x5B2C, 0, 0, 0,
+ 0,0x3A73,0x443F,0x5B2D,0x4F2F, 0, 0, 0,
+0x4B3E, 0,0x442B,0x5B2E,0x347C, 0, 0, 0,
+ 0, 0, 0,0x5B2F,0x5B30,0x4C5A, 0,0x4C24,
+0x4B76,0x4B5C,0x3B25,0x5B32, 0, 0,0x3C6B, 0,
+ 0,0x4B51, 0,0x5B34,0x5B37,0x5B36, 0,0x3479,
+ 0, 0,0x3560, 0,0x5B33, 0,0x5B35, 0,
+ 0, 0, 0,0x5B38, 0, 0,0x3F79, 0,
+ 0, 0, 0,0x4D7B,0x3049,0x3A60,0x423C, 0,
+0x3C5D, 0, 0,0x3E73, 0, 0,0x5B3B, 0,
+ 0,0x454E, 0,0x5B39,0x422B,0x5B3A,0x3E72,0x4C5D,
+0x5B3C,0x5B3D,0x4D68, 0, 0, 0, 0,0x5B42,
+ 0, 0,0x393A, 0,0x4755,0x5B3F,0x456C,0x5A5E,
+0x5A62, 0,0x354F, 0,0x4747, 0, 0, 0,
+ 0,0x5B41, 0,0x3E3E,0x4844, 0, 0, 0,
+ 0, 0,0x5B47, 0,0x487A, 0,0x5B3E, 0,
+0x5B44,0x5B43, 0, 0, 0,0x404F, 0, 0,
+ 0, 0,0x4B6D, 0,0x4E53, 0, 0,0x4B67,
+ 0,0x324C,0x3B5E, 0, 0,0x4F48,0x5B46,0x3F75,
+ 0, 0, 0,0x5B45, 0, 0,0x5B40, 0,
+ 0, 0, 0, 0,0x384F, 0, 0, 0,
+0x5B4C,0x5B4A, 0,0x324D,0x5B48,0x5B4E,0x5B54, 0,
+ 0, 0, 0, 0, 0, 0,0x4248, 0,
+ 0,0x4A41, 0,0x5B56, 0, 0, 0,0x4922,
+ 0, 0, 0,0x5B55,0x4770,0x4B3F,0x343B, 0,
+0x4077,0x3D40, 0, 0, 0,0x4453, 0,0x4D2E,
+ 0, 0,0x5B51,0x5B50, 0, 0, 0,0x5B52,
+ 0,0x5B4F, 0, 0,0x5B57, 0,0x5B4D, 0,
+ 0,0x5B4B, 0,0x5B53,0x5B49, 0,0x436C, 0,
+0x4C78,0x3C46,0x3A74, 0, 0, 0, 0, 0,
+0x3A3A, 0, 0,0x4B6F,0x3341, 0, 0,0x444E,
+0x464A,0x3149, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4072, 0, 0,0x4034,0x372A, 0, 0, 0,
+ 0, 0, 0,0x5B59, 0, 0,0x393B,0x337C,
+ 0, 0, 0, 0, 0, 0,0x5B5B,0x3374,
+0x5B61, 0, 0, 0, 0, 0, 0,0x5B5E,
+ 0,0x4073, 0, 0, 0,0x334B,0x3A2C, 0,
+ 0,0x334A,0x3A4F, 0, 0,0x5B5C,0x3765,0x374B,
+0x456D, 0, 0,0x5B5A, 0,0x3046, 0, 0,
+ 0, 0,0x5B5D,0x5B5F, 0,0x364D,0x372C, 0,
+0x343C,0x354B, 0, 0, 0, 0,0x5B62, 0,
+ 0,0x3A79,0x4B71, 0,0x3B37, 0, 0, 0,
+0x5B63, 0, 0, 0,0x4930, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5B6F, 0,0x3233,0x5B64, 0, 0, 0,
+ 0, 0, 0,0x5B75,0x5B65, 0,0x4E42, 0,
+0x5B6C, 0,0x475F, 0, 0, 0, 0, 0,
+ 0, 0,0x5B74, 0,0x5B67, 0, 0, 0,
+0x3034,0x5B69, 0, 0,0x393C, 0, 0, 0,
+0x5B6B, 0,0x5B6A, 0,0x5B66,0x5B71, 0,0x3E3F,
+ 0, 0, 0,0x546D,0x3868,0x4D7C, 0, 0,
+ 0, 0,0x5B68, 0,0x4474,0x3323,0x3A2D, 0,
+0x5B60, 0,0x5B70,0x3361, 0, 0,0x5B6E,0x5B72,
+ 0,0x456E, 0, 0, 0, 0, 0, 0,
+ 0,0x347E, 0,0x5C32, 0, 0,0x4C49,0x5B77,
+0x347D, 0,0x5B7E, 0, 0, 0, 0,0x4B40,
+ 0,0x5C21,0x5C23, 0,0x5C27,0x5B79, 0,0x432A,
+ 0, 0, 0, 0,0x456F,0x5C2B,0x5B7C, 0,
+0x5C28, 0, 0, 0,0x5C22, 0, 0, 0,
+ 0, 0, 0,0x3F39,0x5C2C, 0, 0,0x4033,
+ 0, 0, 0, 0, 0, 0,0x5C2A,0x343D,
+ 0, 0, 0, 0, 0,0x4F50,0x5B76, 0,
+ 0,0x5C26,0x3058, 0, 0,0x5B78, 0, 0,
+0x4C3A,0x5B7D,0x3F22,0x4447,0x5B73, 0, 0,0x5C25,
+ 0, 0, 0, 0, 0, 0,0x3F7A,0x5C2F,
+0x3371,0x3821, 0, 0, 0, 0,0x5C31,0x5B7A,
+0x5C30, 0,0x5C29,0x5B7B, 0,0x5C2D, 0,0x5C2E,
+ 0, 0, 0, 0, 0,0x5C3F, 0, 0,
+ 0,0x464E, 0,0x5C24, 0, 0,0x5C3B, 0,
+ 0, 0,0x5C3D, 0,0x4458, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4D4C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4976,0x5C38,0x424A, 0, 0, 0,0x5C3E,0x413F,
+ 0,0x5C35,0x5C42,0x5C41, 0,0x466F,0x5C40,0x466A,
+ 0, 0, 0, 0, 0, 0, 0,0x5C44,
+0x5C37, 0,0x3648,0x5C3A,0x3D5D, 0, 0, 0,
+0x4760,0x5C3C,0x364B, 0,0x5C34,0x5C36,0x5C33, 0,
+ 0,0x4F30,0x335A,0x5C39, 0, 0,0x5C43,0x3335,
+ 0, 0, 0, 0, 0, 0, 0,0x3A67,
+ 0, 0, 0,0x315D, 0, 0,0x5C54, 0,
+ 0,0x4F31,0x5C57, 0, 0, 0, 0, 0,
+0x3F3A,0x5C56, 0, 0, 0,0x5C55, 0, 0,
+ 0, 0, 0, 0,0x5C52, 0, 0, 0,
+ 0, 0, 0,0x5C46, 0, 0,0x5C63,0x5C45,
+ 0,0x5C58, 0, 0, 0, 0, 0, 0,
+0x5C50, 0, 0,0x5C4B,0x5C48, 0,0x5C49, 0,
+0x5C51, 0, 0, 0,0x7422, 0, 0,0x5C4E,
+0x393D,0x4448,0x4164,0x5C4C, 0,0x5C47, 0, 0,
+0x5C4A, 0, 0, 0, 0,0x4D4D,0x4B6A, 0,
+ 0, 0,0x5C4F,0x5C59, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5C61,0x5C5A, 0, 0,
+0x5C67, 0,0x5C65, 0, 0, 0, 0,0x5C60,
+ 0, 0, 0, 0, 0, 0,0x5C5F, 0,
+0x4450, 0,0x4165, 0,0x5C5D, 0, 0,0x5C5B,
+ 0, 0,0x5C62, 0, 0, 0, 0,0x5C68,
+0x4875,0x5C6E, 0, 0, 0, 0, 0,0x5C69,
+0x5C6C,0x5C66, 0, 0,0x4374, 0,0x4938, 0,
+0x5C5C, 0, 0,0x5C64,0x3E40, 0,0x4C4F,0x5C78,
+0x5C6B, 0, 0, 0, 0, 0,0x3822,0x3223,
+0x335F, 0, 0,0x5C53, 0, 0, 0, 0,
+ 0, 0,0x3E41,0x5C70, 0,0x5C77,0x3C79,0x3372,
+ 0, 0,0x432E, 0, 0, 0, 0, 0,
+ 0,0x5C6D, 0, 0,0x5C72,0x5C76, 0, 0,
+0x3636, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x354C,0x5C74, 0,
+ 0, 0, 0, 0,0x3521, 0,0x464B,0x5C73,
+ 0, 0, 0,0x5C75, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5C6F,
+ 0, 0, 0, 0, 0,0x5C71, 0, 0,
+ 0, 0, 0, 0,0x3360,0x4349, 0, 0,
+ 0,0x5C7C, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5C7A,0x3869, 0,0x5C79, 0, 0,
+ 0, 0, 0, 0,0x5D21, 0, 0, 0,
+ 0,0x5B58, 0, 0, 0,0x5C7B, 0,0x5C7D,
+0x5C7E, 0, 0, 0, 0, 0, 0,0x5D2C,
+ 0,0x5D28, 0,0x5B6D, 0, 0, 0, 0,
+0x5D27, 0, 0, 0, 0,0x5D26, 0, 0,
+0x5D23, 0, 0, 0, 0, 0,0x5C6A,0x5D25,
+0x5D24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5D2A, 0,
+0x4F26, 0, 0, 0, 0, 0, 0,0x5D2D,
+0x367B, 0, 0,0x5D29,0x5D2B, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4827, 0,0x5D2E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5D32,
+0x5D2F, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4D73,0x5D30, 0, 0, 0, 0,0x5C5E,
+ 0, 0, 0, 0, 0, 0, 0,0x5D33,
+ 0, 0, 0,0x5D34, 0, 0, 0, 0,
+ 0, 0,0x3135, 0,0x5D36,0x3767,0x3C21, 0,
+0x3655, 0, 0, 0,0x3224, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4D5F,
+ 0, 0, 0, 0,0x5D38,0x5D37,0x5D3A,0x353D,
+ 0, 0,0x3656,0x343E, 0, 0, 0, 0,
+0x5D3D, 0, 0, 0,0x5D3C, 0,0x5D3E, 0,
+ 0,0x324E, 0,0x4337, 0,0x5D3F, 0, 0,
+0x343F,0x5D41, 0, 0, 0, 0,0x5D40, 0,
+0x5D42, 0, 0, 0,0x5D43, 0,0x5D44,0x3B5F,
+0x4035,0x3A21, 0,0x4970, 0, 0,0x4A62,0x4F44,
+ 0, 0, 0, 0,0x3B75, 0, 0, 0,
+0x3A50,0x4E72, 0, 0, 0,0x5D45,0x5D46, 0,
+0x3B60, 0, 0, 0,0x5D47,0x5D48, 0, 0,
+0x5D4A,0x5D49, 0,0x4B58, 0, 0,0x3D5E,0x3C6C,
+0x3B44, 0,0x5D4B, 0, 0, 0, 0, 0,
+ 0, 0,0x5D4D,0x3F23, 0,0x5D4C, 0, 0,
+ 0, 0, 0,0x5D4E, 0, 0, 0, 0,
+ 0,0x5D4F, 0, 0, 0, 0, 0,0x5D50,
+0x5D51, 0, 0, 0,0x5D52, 0,0x5D54,0x5D53,
+0x5D55,0x3225,0x434A, 0,0x5D56, 0, 0,0x3B26,
+0x334C,0x5D57, 0, 0,0x4542,0x544C, 0, 0,
+ 0, 0,0x3523,0x5D58, 0, 0, 0, 0,
+0x5D59, 0,0x4A6C,0x4B68, 0, 0, 0,0x4647,
+0x5D5A,0x4866, 0, 0, 0,0x487B, 0, 0,
+0x4C53, 0, 0, 0,0x5D5B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5D5D,0x5D5C, 0, 0,0x5D5F, 0, 0, 0,
+0x5D5E};
+
+/* page 35 0x6C08-0x6CF3 */
+static uint16 tab_uni_jisx020835[]={
+0x5D61, 0, 0, 0, 0, 0, 0,0x3B61,
+ 0,0x4C31, 0,0x5D62,0x5D63, 0, 0,0x3524,
+ 0, 0, 0,0x5D64, 0, 0, 0, 0,
+ 0, 0, 0,0x5D66,0x5D65, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3F65, 0, 0,0x4939,
+0x314A, 0, 0, 0, 0, 0,0x4845, 0,
+0x4475,0x3D41,0x3561, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4846, 0,
+0x3C2E, 0, 0, 0, 0,0x5D68, 0,0x3440,
+ 0, 0,0x3178, 0, 0,0x4672,0x5D67,0x393E,
+0x4353, 0,0x5D69, 0, 0, 0, 0, 0,
+0x5D71, 0,0x5D6A, 0, 0, 0, 0, 0,
+0x4241, 0,0x3562,0x5D72, 0, 0, 0, 0,
+ 0, 0,0x3768, 0, 0,0x3525,0x5D70, 0,
+ 0,0x5D6E,0x5D6B,0x4D60, 0, 0, 0, 0,
+0x4440, 0, 0, 0,0x4659,0x5D6C, 0, 0,
+0x5D74, 0,0x5D73,0x3723, 0, 0,0x322D, 0,
+ 0,0x3A3B,0x5D6D,0x5D6F, 0, 0, 0, 0,
+ 0,0x4B57,0x4274, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4B77, 0, 0,0x5D7C, 0,
+ 0,0x5D7D, 0,0x324F, 0, 0, 0, 0,
+0x4A28,0x4C7D,0x5E21,0x3C23,0x3E42,0x5D78,0x5D7E,0x3168,
+ 0,0x3637, 0, 0,0x5D75,0x5D7A, 0, 0,
+ 0,0x4074,0x4771, 0,0x4867, 0, 0, 0,
+ 0, 0, 0,0x5D77, 0,0x4B21, 0,0x5D79,
+ 0,0x5E24, 0,0x5E22, 0,0x5D7B, 0, 0,
+ 0,0x4B22,0x4748,0x3563, 0,0x4525, 0, 0,
+0x436D, 0,0x5E25, 0, 0, 0, 0,0x5E23,
+0x4259,0x5D76, 0,0x314B};
+
+/* page 36 0x6D0B-0x7409 */
+static uint16 tab_uni_jisx020836[]={
+0x4D4E,0x5E30, 0, 0, 0, 0, 0,0x5E2F,
+ 0, 0, 0, 0,0x4076, 0,0x5E2C, 0,
+0x4D6C, 0, 0,0x4636,0x5E26, 0, 0, 0,
+ 0, 0,0x4445, 0, 0, 0,0x314C,0x393F,
+0x5E29, 0, 0, 0, 0, 0, 0,0x3D27,
+0x5E2E, 0,0x5E2D,0x5E28, 0,0x5E2B, 0, 0,
+0x3368, 0,0x5E2A,0x4749, 0, 0,0x4E2E, 0,
+ 0,0x3E74,0x4075, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5E36,0x5E34,
+ 0,0x494D, 0, 0, 0, 0, 0, 0,
+0x5E31,0x5E33, 0,0x313A, 0, 0,0x3940,0x4F32,
+ 0,0x333D, 0,0x4962, 0, 0, 0, 0,
+ 0,0x4D61, 0, 0,0x3324,0x3F3B,0x5E35, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5E3A, 0, 0,0x3E43, 0, 0,
+ 0,0x4D30, 0,0x5E37, 0, 0, 0, 0,
+0x5E32, 0,0x5E38, 0, 0, 0,0x4E5E, 0,
+0x4573,0x4642, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3336, 0, 0,0x3155,
+ 0, 0,0x5E3E, 0, 0,0x5E41, 0, 0,
+ 0,0x4E43, 0, 0, 0,0x4D64, 0, 0,
+ 0, 0,0x5E48,0x5E42,0x5E3F, 0, 0, 0,
+0x4E54,0x5E45, 0, 0, 0, 0,0x3D4A,0x5E47,
+ 0, 0,0x5E4C, 0, 0,0x4571,0x5E4A, 0,
+ 0, 0, 0,0x5E44, 0, 0,0x4338, 0,
+ 0,0x5E4B, 0,0x5E40, 0,0x5E46, 0,0x5E4D,
+0x307C,0x5E43, 0,0x5E4E, 0, 0,0x3F3C, 0,
+0x3D5F, 0,0x4A25, 0,0x3A2E, 0,0x5E3B,0x5E49,
+0x453A, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4036, 0,0x3369,0x3A51,0x3E44,0x5E3D,
+0x3D42, 0, 0, 0, 0, 0, 0, 0,
+0x374C, 0,0x5E3C, 0, 0, 0,0x5E52,0x3D6D,
+0x383A, 0,0x5E61, 0,0x5E5B,0x3574,0x454F, 0,
+0x5E56,0x5E5F,0x302F,0x3132, 0, 0,0x3239, 0,
+0x5E58,0x422C,0x5E4F,0x5E51,0x3941, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5E62, 0,0x5E5D,
+ 0, 0, 0,0x5E55, 0, 0, 0, 0,
+0x5E5C, 0, 0, 0, 0, 0, 0,0x4C2B,
+ 0, 0,0x5E5A,0x5E5E, 0, 0, 0, 0,
+ 0, 0, 0,0x3850, 0,0x3E45, 0, 0,
+0x4339, 0, 0, 0,0x5E54, 0, 0, 0,
+ 0, 0, 0, 0,0x4D2F, 0, 0, 0,
+0x5E57, 0, 0,0x5E50,0x4572, 0, 0,0x5E53,
+ 0, 0, 0,0x5E59, 0, 0, 0, 0,
+ 0, 0, 0,0x4F51,0x3C3E,0x4B7E, 0,0x5E63,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x482E, 0, 0,0x5E6F,0x383B, 0, 0,
+ 0, 0, 0,0x3D60, 0,0x5E65, 0, 0,
+ 0,0x4E2F,0x3942, 0,0x5E72, 0, 0,0x306E,
+ 0, 0,0x5E70, 0, 0, 0, 0,0x5E64,
+ 0, 0, 0, 0,0x5E6A, 0, 0,0x5E6C,
+ 0, 0, 0,0x4D4F,0x5E67, 0, 0,0x452E,
+ 0, 0,0x5E69, 0, 0, 0, 0,0x5E71,
+ 0,0x5E6B,0x4C47, 0, 0, 0,0x5E66, 0,
+0x3C22,0x5E7E, 0, 0, 0, 0,0x336A, 0,
+0x5E68,0x5E6D,0x5E6E, 0, 0, 0, 0, 0,
+ 0, 0,0x426C,0x425A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E76, 0, 0,0x5E7C, 0, 0,0x5E7A,
+ 0,0x4529, 0, 0,0x5F23,0x5E77, 0, 0,
+ 0, 0, 0,0x5E78,0x5E60, 0,0x3579,0x493A,
+ 0, 0, 0,0x3C3F, 0, 0,0x3977, 0,
+ 0, 0, 0, 0,0x4F33, 0,0x5E74, 0,
+0x5F22,0x3169,0x4166, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4779, 0,0x3441,
+0x4E7A, 0, 0, 0, 0, 0, 0, 0,
+0x4C21,0x4452, 0, 0, 0, 0,0x5E7B,0x5E7D,
+ 0, 0, 0, 0, 0,0x4132, 0, 0,
+ 0, 0, 0,0x5F21,0x5E79, 0,0x5E73, 0,
+ 0, 0,0x3443, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3769, 0, 0, 0,0x5F2F, 0, 0,
+0x5F2A,0x4078, 0, 0,0x3363, 0, 0, 0,
+ 0,0x3D61, 0,0x5F33, 0, 0, 0, 0,
+ 0, 0,0x5F2C,0x442C,0x5F29,0x4459, 0, 0,
+ 0,0x5F4C, 0, 0, 0,0x5F26, 0,0x5F25,
+ 0,0x5F2E, 0, 0, 0,0x5F28,0x5F27,0x5F2D,
+ 0,0x4021, 0,0x5F24, 0, 0, 0, 0,
+ 0, 0, 0,0x5F30, 0, 0,0x5F31, 0,
+ 0, 0, 0, 0,0x3442, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5F36, 0,
+0x5F35,0x5F37, 0, 0, 0, 0, 0,0x5F3A,
+ 0, 0, 0, 0, 0, 0,0x4543, 0,
+0x5F34, 0, 0, 0, 0, 0,0x5F38, 0,
+ 0, 0, 0, 0, 0,0x3763,0x4279,0x5F32,
+0x473B, 0, 0,0x5F39, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F3E,0x5F3C, 0, 0,0x5F3F, 0, 0,
+0x5F42, 0, 0, 0,0x5F3B,0x396A,0x4728, 0,
+ 0,0x5E39, 0, 0, 0, 0, 0, 0,
+0x4D74,0x5F3D, 0,0x5F41,0x4275, 0,0x5F40, 0,
+0x5F2B, 0, 0,0x6F69, 0, 0, 0,0x5F45,
+ 0, 0, 0,0x5F49, 0, 0,0x5F47, 0,
+ 0, 0, 0, 0, 0, 0,0x5F43, 0,
+0x5F44, 0, 0, 0,0x5F48, 0,0x5F46, 0,
+ 0, 0,0x494E, 0, 0,0x5F4E, 0,0x5F4B,
+0x5F4A, 0,0x5F4D,0x4654,0x5F4F, 0, 0, 0,
+ 0, 0, 0,0x4375,0x426D, 0, 0, 0,
+ 0,0x4025, 0, 0, 0,0x5F50, 0,0x5F52,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5F51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E75, 0, 0, 0, 0,0x5F53, 0,
+ 0, 0, 0, 0, 0,0x4667, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5F54, 0, 0, 0, 0, 0, 0, 0,
+0x3250, 0, 0, 0,0x4574,0x3325, 0, 0,
+ 0, 0, 0, 0, 0,0x3564, 0, 0,
+ 0,0x3C5E,0x3A52, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4F27,0x3F66,
+ 0, 0, 0,0x316A, 0, 0, 0,0x5F56,
+ 0, 0, 0, 0, 0, 0,0x5F55, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F59,0x433A,0x5F5C,0x5F57, 0, 0, 0,
+0x5F5B, 0, 0, 0, 0,0x5F5A,0x4540,0x3059,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4E75, 0, 0,
+0x5F5E, 0, 0, 0,0x3128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5F60, 0,
+ 0, 0,0x5F5F, 0,0x5F5D, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5F58, 0,
+ 0, 0, 0, 0, 0, 0,0x4B23, 0,
+ 0, 0,0x5F62, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5F61, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x316B, 0, 0, 0, 0,0x5F64,0x4A32,
+ 0,0x5F63, 0, 0, 0, 0,0x4C35, 0,
+ 0, 0, 0,0x3E47, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4133, 0, 0, 0, 0,
+ 0,0x3E46, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4E7B, 0,
+ 0,0x5F6A, 0,0x4079, 0, 0, 0, 0,
+ 0, 0,0x5F66,0x5F6B, 0, 0,0x316C, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5F69,
+ 0,0x4761,0x5F65,0x5F68,0x3E48, 0,0x4851, 0,
+ 0,0x5F6C, 0,0x3C51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x407A, 0, 0, 0, 0, 0,
+ 0,0x5F6F, 0, 0, 0,0x5F67, 0,0x3727,
+ 0, 0, 0, 0,0x5F6D, 0, 0, 0,
+ 0,0x4D50,0x5F70, 0, 0, 0,0x7426, 0,
+ 0, 0, 0, 0,0x3D4F, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5F71, 0, 0,
+ 0,0x5F72, 0, 0, 0, 0,0x472E, 0,
+ 0, 0, 0, 0, 0, 0,0x5F74, 0,
+ 0, 0, 0,0x5F75, 0, 0, 0, 0,
+0x4733, 0, 0, 0, 0,0x4575,0x5F77, 0,
+ 0, 0, 0,0x5F79, 0,0x4E55, 0,0x5F76,
+ 0,0x5F78,0x316D, 0,0x5F73, 0, 0, 0,
+ 0, 0, 0, 0,0x535B,0x5F7A, 0, 0,
+ 0, 0,0x4167,0x3B38,0x5F7C, 0, 0, 0,
+ 0,0x5F7B,0x3F24,0x5259, 0, 0, 0, 0,
+ 0, 0,0x5F7D, 0, 0, 0,0x6021, 0,
+0x5F6E,0x5F7E, 0, 0,0x6022, 0, 0, 0,
+ 0, 0, 0,0x477A, 0, 0, 0, 0,
+ 0, 0,0x6023, 0, 0,0x6024, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6025, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6026, 0,0x445E,
+ 0,0x6028,0x6027, 0, 0,0x6029, 0,0x602A,
+ 0, 0,0x3C5F,0x4963, 0, 0, 0,0x4C6C,
+0x602B,0x602C,0x4156,0x3C24,0x602D,0x602E, 0, 0,
+ 0, 0, 0,0x602F,0x4A52,0x4847, 0, 0,
+0x6030,0x4757, 0, 0, 0, 0, 0,0x442D,
+ 0, 0, 0, 0, 0,0x6031,0x3267, 0,
+0x356D, 0,0x4C46, 0,0x4C36, 0,0x3234,0x4F34,
+ 0, 0, 0, 0,0x4B52, 0,0x4A2A, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4037,
+ 0,0x6032, 0, 0, 0, 0,0x4643, 0,
+ 0, 0,0x3823,0x6033, 0,0x3A54,0x6035,0x6034,
+ 0, 0, 0, 0,0x6036, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6037,
+ 0, 0, 0,0x6038, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x353E, 0,0x6039,
+ 0, 0, 0, 0,0x603A, 0, 0, 0,
+ 0,0x3824, 0, 0,0x4848, 0, 0,0x603C,
+ 0, 0, 0,0x3E75, 0, 0,0x603B, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3638,
+0x603D,0x603F, 0,0x603E, 0, 0, 0, 0,
+ 0, 0, 0,0x6040, 0,0x3851, 0,0x6041,
+ 0, 0, 0, 0,0x3669, 0,0x4140, 0,
+0x397D, 0, 0, 0, 0,0x6043,0x6044,0x6042,
+ 0, 0, 0, 0, 0, 0,0x3C6D, 0,
+ 0,0x4648,0x3639, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6046,0x432C,0x6045, 0,
+ 0,0x4F35,0x4762, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6049,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x604B,0x6048, 0, 0, 0,
+0x4C54,0x604A,0x604C, 0,0x4E44, 0, 0, 0,
+ 0, 0,0x6050, 0, 0, 0,0x604F,0x4376,
+0x472D, 0, 0,0x3825,0x604E, 0, 0, 0,
+ 0,0x604D, 0,0x4D31,0x4D32, 0, 0, 0,
+ 0, 0, 0,0x6051,0x316E, 0, 0, 0,
+ 0,0x3976,0x3B62, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6052,0x6053, 0, 0, 0,
+ 0, 0, 0, 0,0x6055, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3D43, 0, 0, 0, 0,0x6057, 0,0x6056,
+ 0, 0, 0, 0, 0,0x6058, 0,0x334D,
+ 0, 0,0x605A, 0, 0,0x6059, 0,0x605C,
+0x605B, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x383C, 0, 0,0x4E28, 0,0x364C, 0,
+0x3226, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x366A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3461, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4E68,
+0x605E, 0, 0, 0, 0, 0, 0, 0,
+0x6060, 0, 0, 0, 0,0x6061, 0,0x3251,
+ 0, 0, 0, 0, 0,0x605D, 0,0x3B39,
+ 0, 0,0x4441,0x605F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6064, 0,0x3C6E, 0, 0,
+ 0, 0,0x6062, 0, 0, 0, 0,0x373E,
+ 0, 0,0x4849,0x6063, 0, 0,0x607E, 0,
+ 0, 0, 0, 0, 0,0x6069, 0, 0,
+ 0, 0, 0,0x383D, 0, 0, 0, 0,
+0x3565, 0,0x6066,0x4D7D, 0, 0,0x4E30};
+
+/* page 37 0x7422-0x7845 */
+static uint16 tab_uni_jisx020837[]={
+0x4276, 0, 0,0x6068, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x606A,0x4E56,0x3657,0x487C,0x474A, 0, 0, 0,
+0x606B, 0, 0, 0, 0,0x606D, 0,0x6070,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x606C, 0, 0, 0,0x606F,
+0x386A,0x314D,0x6071, 0,0x3F70,0x606E,0x4E5C, 0,
+ 0,0x6074,0x7424, 0, 0, 0, 0,0x6072,
+0x6075, 0, 0, 0, 0,0x6067,0x6073, 0,
+ 0,0x3A3C, 0, 0,0x6076, 0, 0, 0,
+ 0, 0, 0, 0,0x6077, 0, 0, 0,
+ 0,0x4D7E, 0, 0, 0, 0, 0, 0,
+ 0,0x6078, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6079, 0, 0, 0,
+0x6065, 0, 0, 0, 0,0x607A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3444, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3C25, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x607B, 0, 0, 0, 0,0x607C, 0, 0,
+ 0, 0,0x607D, 0, 0, 0, 0, 0,
+ 0, 0,0x313B, 0, 0, 0,0x6121, 0,
+0x493B,0x6122, 0, 0,0x3424,0x6123, 0,0x6124,
+ 0, 0, 0, 0,0x6125, 0,0x6127,0x6128,
+0x6126, 0, 0, 0,0x4953,0x612A,0x6129, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x612C,0x612B,0x612D, 0, 0, 0, 0,
+ 0, 0,0x612E,0x6130,0x612F, 0, 0,0x3979,
+ 0,0x6132, 0,0x6131, 0, 0,0x3445, 0,
+0x3F53, 0,0x453C, 0,0x6133,0x4038, 0, 0,
+ 0,0x3B3A, 0,0x3179,0x6134, 0,0x4D51, 0,
+ 0,0x4A63,0x6135, 0, 0, 0,0x4544,0x4D33,
+0x3943,0x3F3D, 0, 0, 0,0x434B,0x5234, 0,
+0x442E,0x3268,0x6136, 0, 0, 0, 0, 0,
+ 0, 0,0x6137, 0,0x613C, 0, 0,0x613A,
+0x6139,0x5A42,0x3326,0x6138, 0,0x305A, 0,0x482A,
+ 0, 0,0x484A, 0, 0, 0, 0,0x4E31,
+0x613D,0x613B,0x435C,0x4026, 0, 0,0x482B, 0,
+0x492D, 0,0x613F,0x4E2C,0x374D,0x6140, 0,0x613E,
+0x4856,0x6141, 0,0x6142, 0, 0,0x305B, 0,
+ 0,0x3E76,0x6147, 0,0x6144,0x466D,0x6143, 0,
+ 0, 0, 0, 0, 0,0x3526, 0, 0,
+0x614A, 0, 0, 0,0x6145,0x6146, 0,0x6149,
+0x6148,0x4925, 0, 0,0x4142,0x4141, 0,0x353F,
+ 0, 0,0x614B, 0, 0, 0, 0, 0,
+0x614C, 0, 0,0x614D, 0, 0, 0, 0,
+ 0,0x614F, 0,0x614E, 0, 0, 0, 0,
+ 0,0x3156, 0, 0, 0, 0, 0,0x6157,
+0x4868,0x6151, 0,0x6153, 0, 0,0x6155,0x3F3E,
+ 0, 0,0x6156,0x6154,0x3C40, 0, 0, 0,
+0x6150,0x6152, 0,0x4942, 0,0x3E49, 0, 0,
+0x6159, 0, 0,0x6158, 0, 0, 0, 0,
+0x615A, 0,0x3C26,0x3A2F, 0, 0,0x4577,0x615B,
+ 0,0x444B, 0, 0,0x615D, 0, 0, 0,
+0x4E21,0x615C, 0, 0, 0, 0, 0,0x4169,
+ 0, 0, 0, 0, 0, 0,0x6162, 0,
+0x6164,0x6165,0x4354, 0, 0, 0, 0, 0,
+0x6163, 0,0x6160, 0,0x615E,0x615F, 0,0x6161,
+ 0, 0, 0, 0, 0, 0, 0,0x6168,
+ 0,0x6166, 0,0x6167, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6169,0x616B,0x616C,
+0x616D, 0,0x616E, 0, 0,0x616A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6170, 0,
+ 0, 0,0x616F, 0, 0, 0, 0, 0,
+ 0,0x6171, 0, 0, 0, 0, 0, 0,
+0x4E45, 0, 0, 0,0x6174,0x6172,0x6173, 0,
+ 0, 0,0x3462, 0, 0, 0, 0, 0,
+0x4C7E, 0, 0, 0,0x4A4A, 0,0x6176, 0,
+ 0, 0,0x6175, 0, 0, 0, 0,0x6177,
+0x6178, 0, 0, 0, 0,0x617C,0x6179,0x617A,
+0x617B, 0,0x617D, 0, 0, 0,0x617E, 0,
+0x6221, 0, 0, 0,0x6222, 0,0x6223, 0,
+0x482F,0x4550,0x6224,0x4772,0x4934, 0,0x6225, 0,
+ 0,0x6226,0x452A, 0,0x3327,0x3944,0x6227, 0,
+ 0,0x6228, 0, 0,0x6229, 0,0x3B29, 0,
+ 0,0x622B, 0, 0,0x622A, 0, 0,0x622C,
+0x622D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4869, 0,0x622E, 0,
+ 0, 0,0x622F, 0, 0,0x7369,0x6230,0x6231,
+0x6232, 0, 0, 0, 0,0x3B2E, 0, 0,
+0x6233,0x4756, 0, 0,0x4B5F, 0,0x314E, 0,
+0x3157, 0, 0,0x6234, 0, 0, 0, 0,
+0x6236, 0, 0, 0,0x6235,0x4570, 0, 0,
+ 0,0x4039,0x5D39, 0,0x6237,0x4C41, 0,0x6238,
+ 0,0x3446,0x4857,0x6239, 0,0x623A, 0, 0,
+0x623B, 0, 0, 0,0x4C5C, 0, 0, 0,
+0x4C55, 0,0x443E, 0, 0, 0,0x416A, 0,
+ 0,0x623D, 0, 0,0x3D62, 0, 0,0x3E4A,
+ 0, 0,0x6240, 0, 0,0x623F,0x623E,0x487D,
+ 0,0x3447,0x3829, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6246, 0, 0,0x6243,0x3F3F,0x4C32, 0,
+ 0, 0,0x6242,0x6244,0x6245, 0, 0,0x6241,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6247,0x6248, 0,
+0x442F, 0,0x3463, 0, 0, 0,0x4365, 0,
+ 0, 0, 0, 0, 0,0x6249, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x624A,0x624D, 0, 0, 0, 0, 0,0x3F67,
+ 0,0x4644, 0,0x624E,0x4B53, 0,0x624B, 0,
+ 0,0x624C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6251,
+ 0, 0, 0, 0,0x6250,0x624F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6253, 0, 0,0x6252, 0, 0,0x6254,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6256, 0,0x6255, 0,
+ 0, 0, 0,0x4A4D, 0, 0, 0, 0,
+ 0, 0,0x3D56,0x4E46, 0, 0,0x6257, 0,
+ 0,0x4637, 0, 0,0x6258, 0, 0,0x6259,
+ 0,0x625D,0x625B,0x625C, 0,0x625A, 0, 0,
+ 0, 0, 0, 0, 0,0x625E, 0, 0,
+ 0, 0, 0,0x625F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6260, 0, 0,
+0x6261,0x4C37,0x6262, 0, 0, 0, 0, 0,
+0x4C70,0x6263, 0,0x434E, 0,0x476A, 0,0x366B,
+ 0, 0, 0,0x433B,0x6264,0x363A, 0, 0,
+ 0,0x4050, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6265, 0, 0, 0, 0, 0,
+0x3A3D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6266, 0, 0, 0, 0, 0,
+0x6267, 0,0x3826,0x3A55, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6269, 0,
+ 0, 0, 0,0x4556,0x3A56,0x354E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4B24, 0,0x474B, 0, 0, 0, 0, 0,
+0x4557, 0, 0, 0, 0,0x395C, 0, 0,
+ 0, 0, 0,0x626B};
+
+/* page 38 0x785D-0x7E9C */
+static uint16 tab_uni_jisx020838[]={
+0x3E4B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4E32,0x3945,
+ 0, 0,0x3827, 0, 0,0x4823, 0,0x626D,
+ 0, 0, 0, 0, 0, 0, 0,0x626F,
+ 0, 0, 0, 0,0x386B, 0, 0, 0,
+ 0,0x626E,0x4476, 0, 0, 0, 0,0x6271,
+0x3337,0x626C, 0, 0,0x486A, 0,0x3130, 0,
+0x3A6C, 0,0x4F52, 0, 0,0x6270, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6272, 0,
+ 0, 0,0x4A4B, 0,0x4059,0x6274, 0, 0,
+ 0, 0,0x6275, 0, 0, 0, 0, 0,
+0x6273, 0, 0, 0, 0,0x334E, 0,0x627B,
+ 0,0x627A, 0, 0,0x3C27, 0, 0, 0,
+0x627C,0x6277, 0, 0, 0,0x627D,0x6278, 0,
+ 0, 0, 0,0x4858,0x6276, 0, 0,0x6279,
+ 0, 0, 0, 0, 0,0x6322, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6321,0x4B61, 0, 0, 0,0x627E,
+ 0, 0,0x306B, 0, 0, 0, 0,0x6324,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6323, 0, 0, 0,0x3E4C, 0, 0, 0,
+ 0, 0,0x6325, 0, 0, 0, 0, 0,
+ 0,0x4143, 0, 0,0x6327,0x6326, 0, 0,
+ 0, 0, 0, 0,0x6328, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6268, 0, 0, 0,0x626A,0x632A,0x6329,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3C28, 0,0x4E69,
+ 0,0x3C52, 0,0x632B,0x3737, 0, 0, 0,
+ 0, 0,0x3540,0x3527,0x3B63, 0, 0, 0,
+ 0, 0, 0,0x4D34, 0, 0,0x6331, 0,
+0x6330,0x4144,0x632D, 0, 0,0x632F, 0, 0,
+0x3D4B,0x3F40,0x632E,0x632C, 0,0x472A, 0, 0,
+0x3E4D, 0, 0,0x493C, 0, 0, 0, 0,
+0x3A57, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4578, 0, 0,0x6332, 0, 0,
+ 0, 0,0x6333,0x6349,0x3658, 0, 0,0x4F3D,
+0x4135, 0, 0, 0, 0,0x6334, 0, 0,
+0x3252,0x4477,0x4A21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6335, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x357A,0x6336, 0, 0,0x6338, 0, 0,
+ 0,0x6339, 0,0x4729, 0, 0,0x633A, 0,
+ 0, 0, 0, 0,0x633B,0x633C, 0, 0,
+0x3659,0x3253,0x4645,0x3D28,0x3B64, 0, 0, 0,
+ 0, 0, 0, 0,0x633D, 0,0x3D29, 0,
+ 0, 0, 0, 0,0x324A,0x4943, 0, 0,
+0x633E, 0, 0,0x486B, 0, 0, 0, 0,
+ 0, 0,0x4145, 0,0x6341, 0,0x6342,0x4769,
+ 0,0x3F41,0x633F, 0,0x4361, 0, 0,0x6340,
+ 0, 0, 0,0x3E4E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x305C, 0,
+ 0, 0, 0,0x3529, 0, 0, 0, 0,
+ 0, 0, 0,0x6343, 0, 0,0x4478, 0,
+0x6344,0x4047, 0, 0, 0, 0, 0,0x4C2D,
+ 0, 0,0x4923,0x6345,0x6346,0x4355, 0,0x4E47,
+ 0, 0,0x6348,0x6347, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3C6F, 0, 0,0x634A,0x3070, 0, 0,
+ 0, 0,0x634D, 0, 0, 0,0x634B,0x3254,
+0x374E,0x634C,0x3946,0x3972, 0,0x4A66,0x634E, 0,
+ 0,0x4B54, 0, 0,0x6350, 0, 0, 0,
+0x4051,0x314F,0x323A,0x302C, 0, 0, 0, 0,
+ 0, 0,0x634F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6351,0x6352,0x3E77, 0,
+ 0, 0, 0, 0,0x6353, 0,0x334F, 0,
+ 0, 0, 0,0x6355, 0, 0, 0,0x376A,
+ 0,0x3566, 0, 0,0x6356,0x3675, 0, 0,
+0x6357, 0,0x407C, 0,0x464D, 0,0x4060,0x3A75,
+ 0, 0, 0,0x6358, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4362,0x416B, 0,
+0x635A,0x635C,0x6359,0x635B, 0, 0, 0, 0,
+ 0, 0,0x3722, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x635D,0x3726, 0, 0,
+ 0,0x3567,0x4D52,0x635F, 0, 0, 0, 0,
+ 0,0x6360, 0, 0, 0,0x312E, 0, 0,
+ 0, 0,0x6363, 0, 0, 0,0x3376,0x6362,
+0x6361, 0,0x6365,0x635E, 0,0x6366,0x4E29, 0,
+0x6367, 0,0x6368, 0, 0,0x5474,0x636A, 0,
+0x6369, 0, 0, 0,0x636B,0x636C, 0,0x4E35,
+0x636D, 0,0x706F,0x3E4F,0x636E,0x636F,0x3D57, 0,
+0x4638,0x6370, 0, 0, 0,0x4328, 0, 0,
+0x6371, 0,0x433C,0x6372, 0, 0, 0, 0,
+ 0,0x3625, 0,0x513F,0x435D,0x3C33, 0, 0,
+ 0, 0,0x3448, 0, 0,0x6373, 0,0x6422,
+ 0,0x6376, 0,0x3568, 0,0x6375,0x6424, 0,
+ 0, 0,0x6374, 0,0x3E50, 0, 0, 0,
+ 0, 0, 0,0x6378,0x6379, 0,0x452B, 0,
+ 0,0x637A, 0,0x335E, 0, 0, 0, 0,
+0x3F5A,0x4964, 0,0x637C, 0, 0, 0,0x4268,
+ 0, 0, 0, 0, 0, 0,0x6377, 0,
+0x637B,0x637D, 0, 0,0x3A7B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6426,0x492E, 0,0x4826,0x4579, 0,0x365A,0x6425,
+0x6423, 0,0x4835,0x637E,0x435E,0x457B, 0,0x457A,
+ 0,0x3A76, 0, 0, 0, 0, 0, 0,
+0x6438, 0, 0, 0, 0, 0, 0, 0,
+0x6428, 0,0x642A, 0, 0, 0, 0,0x642D,
+ 0,0x642E, 0,0x642B,0x642C, 0, 0,0x6429,
+0x6427, 0, 0, 0, 0,0x6421, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4A4F,0x3255, 0, 0, 0,0x6435, 0,
+0x6432, 0,0x6437, 0, 0,0x6436, 0,0x4773,
+0x4C27, 0,0x3B3B,0x6430,0x6439,0x6434, 0,0x6433,
+0x642F, 0,0x6431, 0,0x3449, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x433D, 0, 0,
+0x407D, 0, 0, 0,0x4822, 0, 0,0x643E,
+ 0, 0, 0,0x4824, 0, 0, 0, 0,
+ 0, 0, 0,0x4061,0x643B, 0, 0,0x484F,
+ 0,0x643F,0x4A53, 0,0x435B, 0,0x643A,0x643C,
+ 0, 0,0x643D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6440, 0, 0,0x3C44, 0, 0, 0,0x4646,
+0x6445,0x6444, 0, 0,0x6441, 0, 0, 0,
+0x4F36, 0, 0, 0, 0, 0,0x644A, 0,
+ 0,0x644E,0x644B, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6447, 0, 0, 0, 0,
+ 0, 0,0x6448, 0, 0, 0, 0, 0,
+0x644D, 0, 0, 0,0x6442,0x5255,0x6449,0x6443,
+ 0, 0,0x644C, 0, 0, 0, 0, 0,
+ 0, 0,0x6452, 0,0x344A, 0,0x644F, 0,
+ 0, 0,0x6450, 0, 0,0x6451,0x6454, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6453,0x4876, 0, 0, 0, 0,
+0x6455,0x4E7C,0x4A6D,0x645A, 0, 0,0x6457, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6456,
+0x4052, 0,0x6459,0x645B, 0, 0, 0,0x6458,
+ 0,0x645F, 0,0x645C, 0, 0, 0, 0,
+ 0, 0,0x645D,0x6446, 0, 0, 0,0x645E,
+0x6460, 0, 0, 0, 0, 0, 0,0x6461,
+ 0, 0, 0, 0, 0, 0,0x4A46, 0,
+0x6462, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4C62, 0, 0,0x364E,0x3729,0x6463, 0,
+ 0, 0, 0, 0,0x4A34, 0,0x3F68, 0,
+0x4C30, 0, 0,0x6464, 0,0x4E33, 0, 0,
+0x4774, 0,0x4146,0x4734, 0, 0,0x3D4D, 0,
+ 0, 0,0x3040, 0,0x6469,0x6467, 0,0x6465,
+0x3421, 0,0x3E51,0x646A, 0, 0,0x6468, 0,
+0x6466,0x646E, 0, 0,0x646D,0x646C,0x646B, 0,
+ 0, 0, 0, 0,0x646F, 0, 0, 0,
+0x6470,0x403A, 0,0x6471, 0,0x6473, 0, 0,
+0x6472, 0, 0, 0, 0,0x3852, 0, 0,
+ 0,0x4138, 0, 0, 0,0x6475, 0, 0,
+ 0,0x457C, 0,0x6474, 0, 0, 0,0x6476,
+ 0,0x4A35,0x416C,0x3947, 0,0x6477, 0, 0,
+ 0, 0,0x4E48, 0, 0, 0, 0, 0,
+ 0, 0,0x6479, 0, 0,0x647A, 0,0x647B,
+ 0,0x647C, 0,0x3B65, 0,0x647D,0x374F, 0,
+ 0,0x356A, 0,0x352A, 0,0x6521, 0,0x4C73,
+0x3948,0x647E, 0, 0, 0,0x6524,0x4C66, 0,
+0x473C, 0, 0,0x4933, 0, 0, 0,0x3D63,
+0x6523, 0,0x3C53,0x3949,0x3B66,0x3569,0x4A36,0x6522,
+ 0, 0, 0,0x4147,0x4B42,0x3A77, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3B67,0x445D,
+ 0,0x6527,0x4E5F,0x3A59, 0,0x6528,0x3F42, 0,
+0x652A, 0, 0, 0,0x3E52,0x3A30, 0, 0,
+ 0, 0,0x6529, 0, 0,0x3D2A,0x383E,0x4148,
+0x6525,0x652B, 0, 0, 0, 0,0x6526,0x3750,
+ 0,0x652E,0x6532,0x376B, 0, 0, 0, 0,
+ 0,0x652D, 0, 0, 0, 0,0x6536, 0,
+ 0,0x394A, 0, 0,0x4D6D,0x303C,0x6533, 0,
+ 0,0x356B, 0,0x6530, 0, 0, 0, 0,
+ 0,0x6531, 0, 0,0x457D,0x652F,0x652C, 0,
+0x3328,0x4064, 0, 0,0x3828, 0, 0, 0,
+0x6538, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6535, 0, 0, 0,
+ 0, 0,0x6537, 0, 0, 0,0x6534, 0,
+ 0, 0, 0, 0,0x3751,0x4233,0x6539,0x416E,
+ 0, 0,0x6546, 0, 0,0x6542,0x653C, 0,
+ 0, 0, 0, 0, 0, 0,0x6540,0x3C7A,
+0x305D,0x653B,0x6543,0x6547,0x394B,0x4C56, 0,0x4456,
+0x653D, 0, 0,0x6545, 0,0x653A,0x433E, 0,
+0x653F,0x303D,0x4C4A, 0, 0, 0, 0, 0,
+ 0, 0,0x653E, 0, 0,0x365B,0x486C, 0,
+ 0, 0,0x416D, 0,0x4E50,0x3D6F, 0, 0,
+0x656E, 0, 0,0x6548, 0,0x407E, 0,0x6544,
+0x6549,0x654B, 0,0x4479,0x654E, 0, 0,0x654A,
+ 0, 0, 0,0x4A54,0x344B, 0, 0,0x4C4B,
+ 0, 0,0x305E, 0, 0,0x654D, 0,0x4E7D,
+ 0, 0, 0, 0, 0, 0,0x654C, 0,
+ 0, 0, 0, 0,0x316F, 0, 0,0x466C,
+0x654F, 0, 0, 0,0x6556,0x6550,0x6557, 0,
+ 0, 0, 0, 0, 0,0x6553, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x477B, 0,
+ 0,0x3C4A,0x6555, 0,0x6552,0x6558,0x6551, 0,
+ 0,0x3D44, 0, 0, 0, 0,0x4B25, 0,
+ 0,0x3D4C, 0, 0,0x6554,0x6560, 0, 0,
+0x655C, 0,0x655F, 0,0x655D,0x6561,0x655B, 0,
+0x6541,0x4053, 0, 0,0x484B, 0,0x655E, 0,
+ 0,0x6559, 0, 0, 0,0x4121,0x3752, 0,
+0x3D2B, 0, 0, 0, 0, 0, 0,0x3F25,
+0x4136,0x6564, 0, 0,0x6566,0x6567, 0, 0,
+0x6563,0x6565, 0, 0, 0, 0, 0, 0,
+ 0,0x655A,0x6562, 0,0x656A,0x6569, 0, 0,
+0x4B7A, 0, 0,0x372B, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6568, 0,0x656C,0x656B,
+0x656F, 0,0x6571, 0, 0,0x3B3C,0x656D, 0,
+ 0, 0, 0,0x6572,0x6573, 0, 0,0x6574,
+ 0,0x657A,0x453B,0x6576, 0,0x6575,0x6577,0x6578,
+ 0,0x6579, 0, 0, 0, 0,0x657B,0x657C
+};
+
+/* page 39 0x7F36-0x8358 */
+static uint16 tab_uni_jisx020839[]={
+0x344C, 0,0x657D, 0,0x657E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6621,
+ 0, 0, 0, 0, 0, 0,0x6622,0x6623,
+0x6624, 0,0x6625,0x6626, 0, 0,0x6628,0x6627,
+ 0, 0,0x6629, 0, 0, 0, 0, 0,
+ 0,0x662A,0x662B, 0, 0, 0, 0, 0,
+ 0,0x662E,0x662C,0x662D,0x3A61,0x3753, 0, 0,
+0x4356, 0,0x4833, 0,0x3D70, 0, 0,0x474D,
+ 0,0x486D,0x662F,0x586D, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6630,0x6632, 0,0x4D65,
+0x6631,0x6634,0x6633, 0,0x4D53, 0,0x6635, 0,
+0x487E, 0, 0, 0, 0, 0,0x6636, 0,
+ 0, 0, 0, 0,0x6639, 0, 0,0x6638,
+0x6637, 0, 0, 0, 0,0x663A,0x3732, 0,
+ 0, 0,0x4122,0x3541, 0, 0, 0, 0,
+0x663E,0x663B, 0, 0,0x663C, 0, 0, 0,
+0x663F, 0,0x6640,0x663D, 0, 0, 0,0x3129,
+ 0, 0, 0,0x3227, 0, 0, 0,0x6642,
+0x6643, 0, 0, 0,0x6644, 0,0x4D62, 0,
+ 0, 0, 0, 0,0x3D2C, 0,0x6646,0x6645,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3F69,0x6647, 0, 0, 0, 0,
+0x6648, 0, 0,0x6649, 0,0x3465, 0, 0,
+ 0, 0,0x344D, 0, 0,0x664A, 0, 0,
+ 0, 0, 0,0x664B, 0,0x4B5D,0x4D63, 0,
+ 0, 0,0x4D54,0x4F37, 0,0x394D,0x664E,0x3C54,
+0x664D, 0, 0, 0, 0,0x664F,0x3C29, 0,
+ 0, 0,0x4251, 0,0x6650, 0, 0,0x394C,
+ 0,0x4C57,0x6651,0x6652, 0, 0,0x6653, 0,
+ 0, 0, 0,0x6654, 0, 0, 0, 0,
+ 0, 0,0x6655, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3C2A, 0, 0,
+0x4C6D, 0, 0, 0, 0,0x6657, 0,0x433F,
+ 0,0x6656, 0, 0, 0, 0, 0, 0,
+0x6659, 0, 0, 0,0x6658, 0, 0, 0,
+ 0, 0, 0, 0,0x665A, 0, 0, 0,
+0x403B, 0,0x665B, 0,0x665C, 0, 0, 0,
+0x4A39,0x665D, 0,0x416F,0x665E, 0, 0, 0,
+ 0, 0,0x665F, 0, 0, 0, 0, 0,
+ 0,0x4E7E,0x6662, 0,0x6661,0x6660,0x4430, 0,
+0x6663,0x3F26, 0,0x6664, 0, 0, 0,0x6665,
+0x4F38,0x6666, 0, 0, 0, 0,0x6667,0x6669,
+0x6668,0x4825, 0,0x4679, 0,0x4F3E,0x4829, 0,
+ 0, 0, 0, 0, 0,0x666B, 0, 0,
+0x3E53, 0,0x492A, 0,0x666C,0x666A, 0,0x344E,
+ 0, 0, 0,0x3854,0x3B68, 0, 0,0x486E,
+ 0, 0, 0,0x382A,0x4B43, 0,0x666F,0x666D,
+ 0,0x394E, 0,0x394F,0x3069, 0,0x3A68, 0,
+ 0, 0, 0, 0,0x4759, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x305F,0x6674, 0,
+0x4340, 0, 0, 0, 0, 0,0x4758, 0,
+0x425B, 0, 0, 0, 0, 0, 0, 0,
+0x6676, 0, 0,0x6672,0x6675,0x6670, 0,0x6673,
+0x4B26, 0, 0,0x3855, 0, 0,0x307D,0x6671,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6678, 0,0x6679, 0, 0,0x4639, 0,
+ 0, 0,0x363B, 0, 0, 0,0x6726,0x473D,
+ 0, 0, 0, 0,0x3B69, 0, 0,0x363C,
+0x4048,0x4F46,0x4C2E,0x6677,0x4054, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3553,0x667A, 0, 0,
+ 0, 0, 0, 0, 0,0x667C, 0, 0,
+ 0, 0, 0,0x667B, 0, 0, 0, 0,
+ 0,0x667D, 0,0x4326, 0,0x473E, 0, 0,
+ 0, 0, 0,0x4431, 0, 0, 0, 0,
+0x6723, 0, 0, 0, 0, 0, 0, 0,
+0x6722, 0, 0, 0, 0,0x667E, 0, 0,
+0x3F55, 0,0x4965,0x6725, 0,0x6724,0x3950,0x4F53,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6735, 0, 0, 0, 0, 0,0x6729,
+0x672A, 0, 0, 0, 0,0x3C70, 0, 0,
+0x6728, 0,0x3978,0x6727, 0, 0,0x672B, 0,
+ 0, 0,0x4432,0x4A22,0x4123, 0, 0, 0,
+ 0,0x425C,0x672F, 0,0x6730,0x672C, 0, 0,
+ 0, 0,0x672D, 0,0x672E, 0, 0, 0,
+ 0,0x3951, 0, 0, 0,0x6736, 0,0x6732,
+ 0, 0, 0, 0,0x4966, 0,0x4B6C,0x4928,
+ 0, 0,0x6731, 0, 0,0x6734,0x6733, 0,
+ 0, 0,0x4B44,0x6737, 0, 0, 0, 0,
+ 0, 0,0x6738, 0, 0,0x4137, 0,0x6739,
+ 0, 0,0x673B, 0,0x673F, 0, 0,0x673C,
+0x673A,0x473F,0x673D, 0,0x673E, 0, 0, 0,
+0x3232, 0,0x6745,0x6740, 0, 0, 0,0x6741,
+ 0, 0, 0,0x6742, 0,0x4221, 0, 0,
+ 0, 0,0x6744,0x6743,0x6746, 0, 0, 0,
+ 0,0x6747,0x6748, 0, 0,0x3F43, 0,0x3269,
+ 0,0x6749,0x4E57, 0,0x3C2B, 0, 0,0x3D2D,
+ 0, 0, 0, 0, 0,0x3B6A,0x4357, 0,
+ 0, 0, 0, 0,0x674A,0x674B,0x3131, 0,
+0x674C, 0, 0,0x674D,0x674E, 0, 0,0x674F,
+ 0,0x6750,0x363D,0x5A2A,0x6751, 0,0x4065,0x6752,
+0x3C4B, 0,0x6753, 0,0x5030, 0, 0, 0,
+0x6754,0x4A5E,0x345C, 0, 0,0x4124,0x3D58, 0,
+0x4971,0x3D2E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6755,0x3952,0x6756,0x484C, 0,
+0x6764, 0, 0, 0, 0,0x6758, 0,0x4249,
+0x4775,0x383F,0x6757,0x4125, 0, 0, 0, 0,
+ 0, 0,0x6759, 0, 0, 0, 0, 0,
+ 0,0x447A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x675B,0x675A,0x675D, 0, 0,0x675C,
+ 0,0x675E, 0, 0,0x6760, 0,0x675F, 0,
+0x344F, 0,0x6761, 0,0x6762,0x6763, 0, 0,
+0x3A31,0x4E49, 0,0x6765,0x3F27, 0, 0, 0,
+0x3170,0x6766,0x6767, 0, 0, 0, 0, 0,
+0x6768, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3072, 0,0x6769,
+ 0, 0, 0, 0,0x676A, 0, 0, 0,
+ 0, 0, 0,0x4967, 0, 0, 0,0x3C47,
+ 0,0x676C, 0, 0, 0, 0, 0,0x3329,
+0x3032, 0, 0, 0, 0,0x676B,0x676E,0x474E,
+ 0,0x3F44, 0,0x3256, 0,0x4B27, 0, 0,
+ 0, 0,0x375D,0x365C, 0,0x676D, 0,0x326A,
+ 0, 0, 0, 0, 0, 0, 0,0x3423,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3171,0x6772,0x4E6A,0x425D, 0,
+ 0,0x4944, 0,0x677E, 0,0x3257,0x677C, 0,
+0x677A,0x6771, 0,0x676F, 0,0x6770, 0,0x3C63,
+0x366C,0x4377, 0, 0, 0,0x4651, 0, 0,
+ 0, 0, 0,0x3151, 0,0x6774,0x6773, 0,
+ 0, 0, 0,0x6779,0x6775,0x6778, 0, 0,
+ 0, 0, 0, 0,0x4C50,0x6777,0x3258,0x337D,
+0x677B, 0, 0,0x677D, 0, 0, 0, 0,
+0x3754, 0, 0, 0, 0, 0, 0, 0,
+0x6823,0x682C,0x682D, 0, 0, 0,0x302B, 0,
+ 0, 0, 0, 0, 0,0x6834, 0, 0,
+ 0, 0,0x3071, 0, 0,0x682B, 0, 0,
+ 0,0x682A, 0,0x6825,0x6824, 0,0x6822,0x6821,
+0x4363, 0,0x427B,0x6827, 0, 0, 0, 0,
+ 0, 0,0x6826, 0, 0, 0, 0,0x6829,
+ 0, 0, 0,0x4170,0x3755, 0, 0, 0,
+ 0,0x3141,0x6828, 0,0x3953, 0, 0, 0,
+ 0, 0,0x4171};
+
+/* page 40 0x8373-0x8B9A */
+static uint16 tab_uni_jisx020840[]={
+0x683A, 0,0x683B, 0,0x3259, 0, 0, 0,
+0x322E,0x6838, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x682E, 0,0x6836, 0,0x683D,0x6837,
+ 0, 0, 0,0x6835, 0, 0, 0, 0,
+0x6776, 0, 0,0x6833, 0, 0, 0,0x682F,
+ 0, 0, 0,0x3450,0x6831,0x683C, 0,0x6832,
+ 0, 0, 0, 0, 0,0x683E, 0,0x6830,
+0x477C, 0, 0, 0, 0, 0,0x4D69, 0,
+ 0, 0,0x6839, 0, 0, 0, 0, 0,
+ 0, 0,0x684F, 0, 0, 0,0x6847, 0,
+ 0, 0,0x3F7B, 0, 0, 0, 0,0x3546,
+ 0,0x365D, 0,0x6842, 0, 0, 0, 0,
+0x325B, 0, 0,0x3E54, 0,0x6845, 0, 0,
+ 0,0x3A5A, 0, 0,0x4551,0x684A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A6E, 0,
+0x6841, 0, 0, 0,0x325A,0x3856,0x4929,0x684B,
+ 0,0x683F, 0, 0,0x6848, 0, 0, 0,
+0x6852, 0,0x6843, 0, 0, 0, 0, 0,
+0x6844,0x463A, 0, 0,0x6849, 0, 0, 0,
+0x6846,0x4B28,0x684C,0x3060, 0, 0, 0, 0,
+0x6840, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x684E, 0,0x684D,
+ 0, 0, 0, 0, 0, 0,0x476B,0x6854,
+ 0,0x685F, 0, 0, 0, 0,0x337E, 0,
+ 0, 0,0x6862, 0, 0,0x6850, 0, 0,
+ 0,0x6855,0x4D6E, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x685E, 0, 0,0x4D55, 0,
+ 0, 0, 0,0x4E2A, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4378, 0, 0, 0,
+0x336B, 0, 0, 0, 0, 0,0x4972,0x6864,
+0x4621, 0, 0,0x3031, 0, 0,0x685D, 0,
+0x6859,0x4172,0x6853,0x685B,0x6860, 0,0x472C, 0,
+ 0, 0,0x302A, 0,0x6858, 0,0x6861,0x4978,
+ 0, 0, 0, 0, 0, 0, 0,0x685C,
+ 0,0x6857, 0, 0, 0, 0, 0, 0,
+0x3E55, 0, 0, 0, 0,0x3D2F, 0, 0,
+ 0,0x3C2C, 0, 0, 0, 0,0x4C58, 0,
+ 0,0x4947, 0, 0,0x6867, 0,0x6870, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x685A, 0, 0, 0, 0,0x3377,
+ 0, 0, 0, 0, 0,0x3E78,0x6865, 0,
+0x686A,0x4173, 0, 0,0x6866, 0,0x686D, 0,
+ 0,0x435F, 0,0x686E, 0, 0,0x4D56,0x6863,
+0x3338, 0,0x6869, 0, 0,0x686C,0x4C2C, 0,
+ 0, 0, 0,0x686F, 0, 0,0x6868,0x686B,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4B29, 0,0x4F21, 0, 0, 0, 0,
+ 0,0x6873, 0, 0, 0, 0, 0, 0,
+ 0,0x687A, 0, 0,0x6872,0x3C43, 0, 0,
+ 0, 0, 0,0x6851, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A4E, 0,
+0x4C22,0x6879,0x6878, 0,0x6874,0x6875, 0,0x3136,
+ 0, 0, 0, 0,0x6877, 0,0x6871, 0,
+ 0, 0, 0,0x4455, 0, 0, 0, 0,
+ 0,0x6876,0x307E, 0, 0, 0, 0, 0,
+ 0, 0,0x4222, 0, 0, 0, 0, 0,
+ 0, 0,0x4A43, 0, 0,0x687B,0x6921, 0,
+0x4859, 0, 0, 0, 0,0x687E,0x3E56,0x3C49,
+0x6923, 0, 0,0x363E, 0, 0, 0, 0,
+ 0, 0,0x6924, 0,0x4979,0x687D, 0,0x6856,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x687C, 0, 0, 0, 0,0x4F4F,0x4622,0x4973,
+ 0, 0,0x692B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6931, 0, 0, 0,
+ 0, 0, 0,0x6932, 0,0x6925, 0, 0,
+ 0,0x4776, 0, 0,0x692F,0x6927, 0,0x6929,
+ 0, 0, 0, 0, 0,0x6933,0x6928, 0,
+ 0,0x692C, 0, 0,0x3172, 0,0x4665, 0,
+0x692D,0x6930, 0, 0, 0, 0, 0, 0,
+ 0,0x6926, 0,0x4126, 0,0x692A,0x3B27,0x3F45,
+0x3730,0x4C74, 0,0x4C79,0x3D72, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6937,0x6935,
+ 0, 0, 0, 0, 0, 0,0x4F4E, 0,
+ 0, 0, 0, 0, 0, 0,0x6934, 0,
+ 0, 0,0x4D75, 0,0x6936,0x6938, 0, 0,
+ 0, 0,0x6939, 0, 0, 0, 0, 0,
+ 0,0x693C,0x693A, 0, 0, 0, 0, 0,
+ 0,0x4623,0x693B, 0, 0, 0,0x484D,0x692E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3D73, 0,0x693D,0x6942,
+0x4174, 0, 0,0x6941, 0, 0, 0,0x6922,
+ 0, 0, 0,0x6943,0x4149, 0, 0,0x693E,
+0x6940, 0, 0, 0, 0, 0, 0, 0,
+0x693F, 0, 0,0x5D31,0x5D22, 0, 0,0x6945,
+ 0, 0, 0, 0, 0, 0, 0,0x6944,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4D76, 0,0x623C,0x6946, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6947, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6948,0x3857, 0,0x3554, 0, 0,
+ 0,0x694A,0x515D, 0, 0, 0, 0,0x3575,
+ 0,0x4E3A, 0,0x3673,0x694B, 0, 0, 0,
+ 0, 0, 0, 0,0x694C, 0, 0, 0,
+0x436E, 0, 0, 0, 0, 0,0x694D, 0,
+ 0, 0, 0, 0, 0, 0,0x467A, 0,
+0x303A, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3263,
+0x6952,0x6953, 0, 0, 0, 0, 0, 0,
+0x694E, 0,0x3B3D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x694F,0x4742, 0, 0, 0, 0,0x6950,0x6951,
+0x695B, 0, 0, 0,0x6955,0x6958, 0, 0,
+ 0, 0, 0,0x6954, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6956, 0,0x6957,0x3C58, 0,0x6959, 0,
+0x4341, 0,0x3756,0x3342, 0, 0, 0, 0,
+ 0,0x695C, 0, 0, 0, 0,0x333F, 0,
+0x6961, 0, 0,0x695D,0x6960, 0, 0, 0,
+ 0,0x483A, 0, 0, 0, 0,0x695E, 0,
+ 0,0x695F,0x4948,0x485A,0x6962, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x427D,0x696C, 0,
+0x6968, 0, 0,0x326B, 0,0x6966, 0,0x4B2A,
+0x6967, 0, 0,0x6964, 0,0x6965,0x696A,0x696D,
+ 0, 0,0x696B, 0, 0, 0,0x6969,0x6963,
+ 0, 0, 0, 0, 0,0x4358, 0,0x6974,
+ 0,0x4C2A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6972, 0, 0, 0,0x6973, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x696E, 0, 0,0x6970, 0, 0, 0,
+0x6971, 0, 0, 0,0x696F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4066, 0,
+0x4F39,0x6978, 0,0x6979, 0, 0, 0, 0,
+0x6A21, 0,0x3F2A, 0,0x697B, 0,0x697E, 0,
+ 0, 0, 0, 0,0x6976,0x6975, 0, 0,
+0x6A22, 0, 0,0x325C, 0,0x697C, 0,0x6A23,
+ 0, 0, 0,0x697D, 0, 0, 0, 0,
+ 0,0x697A, 0,0x4433, 0,0x6977, 0, 0,
+ 0, 0, 0, 0,0x4768, 0, 0,0x6A27,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4D3B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6A26, 0, 0,0x6A25,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6A2E, 0, 0, 0,0x6A28, 0, 0, 0,
+0x6A30, 0, 0, 0, 0, 0, 0,0x4D66,
+0x6A33, 0,0x6A2A, 0, 0,0x6A2B, 0, 0,
+ 0,0x6A2F, 0,0x6A32,0x6A31, 0, 0, 0,
+0x6A29, 0, 0, 0, 0,0x6A2C, 0,0x6A3D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6A36, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6A34, 0, 0,0x6A35,
+ 0, 0, 0,0x6A3A,0x6A3B, 0,0x332A, 0,
+0x3542, 0, 0,0x6A39, 0, 0, 0, 0,
+ 0, 0,0x6A24, 0, 0, 0, 0, 0,
+ 0, 0,0x6A38,0x6A3C,0x6A37, 0,0x6A3E, 0,
+ 0, 0,0x6A40,0x6A3F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6A42,0x6A41,
+0x695A, 0, 0, 0,0x6A46, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6A43, 0,
+ 0, 0, 0,0x6A44, 0, 0,0x6A45, 0,
+0x6A47, 0, 0, 0, 0,0x376C, 0,0x6A49,
+ 0,0x6A48, 0,0x3D30, 0, 0, 0, 0,
+ 0,0x3954,0x5E27, 0, 0, 0, 0,0x6A4A,
+0x3D51, 0, 0, 0,0x3339, 0,0x6A4B, 0,
+0x3152, 0,0x3E57,0x6A4C, 0, 0,0x3955,0x6A4D,
+0x3061, 0, 0, 0, 0,0x493D, 0, 0,
+0x6A4E, 0, 0, 0, 0,0x3F6A, 0,0x6A55,
+ 0, 0,0x6A52, 0,0x436F, 0, 0, 0,
+ 0, 0,0x6A53,0x6A50,0x365E, 0,0x6A4F,0x6A56,
+ 0, 0, 0, 0, 0,0x3736, 0, 0,
+0x425E, 0,0x6A5C, 0, 0, 0, 0,0x6A58,
+ 0, 0, 0,0x4235,0x6A57, 0,0x6A5A, 0,
+ 0, 0, 0,0x6A51, 0, 0, 0,0x6A5B,
+ 0,0x6A5D, 0, 0, 0, 0, 0, 0,
+0x486F, 0, 0,0x6A59, 0,0x6A5E,0x6A60, 0,
+ 0,0x3853,0x6A54, 0,0x3041, 0, 0, 0,
+ 0, 0, 0, 0,0x6A5F, 0,0x3A5B,0x4E76,
+0x6A61,0x6A62,0x4175, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4E22, 0, 0, 0,
+ 0,0x6A63,0x4D35, 0, 0,0x6A64,0x6A65, 0,
+ 0,0x4A64,0x6A66, 0,0x3A40, 0,0x4E23, 0,
+ 0, 0, 0, 0, 0,0x6A6B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6A6C,
+0x3E58,0x6A6A, 0, 0, 0,0x4D67,0x6A67, 0,
+ 0,0x6A69,0x403D,0x3F7E, 0, 0, 0,0x6A68,
+ 0,0x6A6D, 0, 0,0x4A23, 0, 0,0x6A6F,
+ 0,0x6A6E, 0, 0, 0,0x336C, 0,0x4B2B,
+0x6A70, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6A7C,0x6A72, 0, 0, 0, 0,
+ 0, 0,0x6A73, 0, 0, 0, 0,0x6A74,
+0x6A75, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6A79, 0,0x6A7A, 0, 0,
+0x6A78, 0, 0, 0, 0, 0,0x6A76, 0,
+0x6A71,0x6A77, 0, 0, 0, 0, 0, 0,
+ 0,0x6A7B,0x7037, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3228, 0, 0, 0, 0,
+ 0, 0, 0,0x6A7E,0x365F,0x6A7D, 0, 0,
+ 0,0x6B22, 0,0x6B21, 0, 0, 0,0x6B24,
+ 0, 0,0x6B23, 0,0x6B25, 0, 0,0x3D31,
+ 0,0x6B26, 0, 0,0x6B27, 0, 0, 0,
+ 0, 0, 0,0x6B28,0x403E, 0,0x4D57, 0,
+0x6B29, 0, 0,0x4A24,0x4746,0x6B2A, 0,0x6B2B,
+0x382B, 0, 0, 0,0x352C, 0, 0, 0,
+0x6B2C, 0, 0,0x3B6B,0x4741,0x6B2D, 0,0x3350,
+ 0, 0, 0, 0, 0, 0,0x6B2E, 0,
+ 0, 0, 0,0x6B30,0x4D77, 0,0x6B2F,0x3F46,
+ 0,0x6B31, 0, 0,0x6B32, 0, 0,0x6B33,
+0x3451, 0, 0, 0, 0, 0, 0,0x6B34,
+ 0, 0,0x6B35, 0,0x6B36,0x6B37, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3351,
+ 0, 0, 0, 0, 0, 0, 0,0x6B38,
+ 0,0x6B39,0x6B3A, 0, 0, 0, 0, 0,
+0x3272, 0, 0,0x3F28,0x6B3B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B3C, 0, 0, 0,0x6B3D, 0, 0,
+ 0, 0, 0, 0, 0,0x3840, 0,0x447B,
+0x6B3E, 0, 0, 0, 0,0x3757, 0,0x3F56,
+ 0,0x6B41, 0,0x4624, 0,0x6B40, 0, 0,
+0x3731, 0, 0,0x6B3F,0x4277,0x352D, 0, 0,
+0x6B42, 0,0x6B43, 0,0x3E59, 0, 0, 0,
+0x376D, 0,0x6B44, 0, 0, 0, 0,0x4B2C,
+ 0, 0,0x405F, 0, 0, 0,0x3576, 0,
+0x4C75,0x414A, 0,0x6B45, 0, 0, 0,0x3F47,
+0x4370,0x3E5A, 0, 0, 0, 0,0x6B46, 0,
+ 0, 0, 0,0x6B49, 0,0x6B4A, 0, 0,
+ 0, 0, 0, 0, 0,0x3A3E,0x4242,0x6B48,
+ 0,0x3E5B,0x493E, 0, 0, 0, 0, 0,
+0x6B47, 0, 0,0x3B6C, 0,0x3153, 0,0x6B4E,
+0x3758, 0, 0,0x3B6E, 0, 0,0x3B6D, 0,
+0x4F4D,0x6B4D,0x6B4C,0x4127, 0,0x354D,0x4F43,0x333A,
+0x3E5C, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B4B, 0, 0, 0, 0, 0,0x6B50,
+ 0,0x6B51,0x6B4F, 0,0x3858, 0,0x4D40, 0,
+ 0,0x3B6F,0x4727, 0, 0, 0,0x6B54, 0,
+0x4040, 0,0x4342, 0, 0,0x4D36, 0,0x6B57,
+ 0, 0, 0,0x386C, 0,0x403F,0x6B53, 0,
+0x6B58,0x386D,0x6B55,0x6B56, 0,0x6B52, 0, 0,
+ 0,0x4062,0x4649, 0, 0,0x432F, 0,0x325D,
+ 0, 0, 0, 0, 0, 0,0x4870, 0,
+ 0,0x3543, 0, 0,0x4434, 0, 0,0x6B5B,
+ 0,0x6B59, 0, 0,0x434C, 0, 0, 0,
+0x4041,0x3452,0x6B5A, 0,0x3F5B, 0, 0,0x4E4A,
+ 0, 0, 0,0x4F40, 0, 0, 0,0x6B5C,
+0x6B67,0x4435, 0,0x6B66, 0,0x6B63,0x6B6B,0x6B64,
+ 0,0x6B60, 0,0x447C,0x6B5F, 0, 0, 0,
+0x6B5D, 0,0x4D21,0x3B70, 0, 0,0x6B61, 0,
+0x6B5E, 0, 0, 0,0x6B65,0x3D74, 0,0x3841,
+ 0, 0, 0,0x427A, 0,0x4B45,0x315A,0x3062,
+ 0,0x4625, 0, 0,0x6B69, 0, 0, 0,
+ 0,0x6B68, 0,0x4666, 0,0x6B6D, 0, 0,
+ 0,0x6B62, 0,0x6B6C,0x6B6E, 0,0x382C,0x6B6A,
+0x3956, 0,0x3C55, 0, 0,0x6B6F,0x4D58, 0,
+ 0, 0, 0,0x6B72, 0,0x6B75, 0, 0,
+0x6B73,0x4935, 0, 0, 0, 0, 0, 0,
+0x6B70, 0, 0, 0, 0, 0,0x3660, 0,
+ 0, 0, 0,0x6B74, 0, 0,0x6B76, 0,
+ 0, 0, 0, 0, 0, 0,0x6B7A, 0,
+ 0,0x6B77, 0,0x6B79,0x6B78, 0, 0, 0,
+ 0, 0, 0,0x6B7B, 0,0x3C31, 0,0x6B7D,
+0x6B7C,0x4968, 0, 0,0x6C21, 0, 0, 0,
+ 0, 0, 0,0x3759, 0, 0, 0, 0,
+0x6B7E,0x6C22, 0, 0,0x6C23,0x3544,0x6641,0x3E79,
+ 0,0x6C24, 0, 0,0x386E, 0, 0, 0,
+ 0, 0,0x6C25, 0, 0,0x6C26, 0, 0,
+0x3B3E, 0, 0, 0, 0, 0, 0,0x5A4E,
+ 0,0x6C27, 0,0x6C28, 0,0x3D32, 0,0x6C29,
+0x6C2A, 0, 0,0x6C2B, 0, 0,0x6C2C,0x6C2D
+};
+
+/* page 41 0x8C37-0x8D16 */
+static uint16 tab_uni_jisx020841[]={
+0x432B, 0, 0,0x6C2E, 0, 0, 0, 0,
+0x6C30, 0,0x6C2F, 0, 0, 0, 0,0x4626,
+ 0,0x6C31, 0,0x4B2D, 0,0x6C32, 0,0x6C33,
+ 0,0x6C34, 0, 0, 0, 0,0x6C35, 0,
+ 0, 0, 0,0x465A, 0, 0, 0, 0,
+ 0, 0,0x3E5D,0x6C36, 0, 0, 0, 0,
+ 0, 0, 0,0x396B,0x502E,0x6C37, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C38,0x493F,0x6C39, 0,0x6C41, 0, 0,
+ 0, 0, 0,0x6C3A, 0, 0,0x6C3C, 0,
+ 0, 0,0x6C3B,0x6C3D, 0,0x4B46,0x6C3E,0x6C3F,
+ 0, 0, 0, 0, 0,0x6C40, 0, 0,
+ 0,0x6C42, 0, 0, 0, 0,0x332D,0x4467,
+ 0,0x4969,0x3A62,0x3957, 0, 0, 0, 0,
+0x494F,0x325F,0x484E,0x6C45,0x3453,0x4055,0x6C44,0x6C49,
+0x4379,0x4C63, 0,0x6C47,0x6C48,0x352E, 0,0x6C4A,
+0x4763,0x425F, 0, 0,0x4871,0x453D,0x6C46, 0,
+0x4B47,0x326C,0x6C4C,0x4F28,0x4442,0x4F45, 0, 0,
+0x3B71,0x6C4B, 0,0x4231, 0, 0,0x6C5C,0x4128,
+ 0, 0,0x4678, 0,0x4950, 0, 0, 0,
+ 0, 0, 0,0x6C4F,0x3B3F,0x3B72, 0,0x3E5E,
+ 0,0x4765, 0,0x382D,0x6C4E,0x6C4D, 0,0x496A,
+ 0, 0, 0,0x3C41, 0, 0,0x4552, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C51,0x6C52,0x3958,0x6C50, 0,
+ 0, 0, 0, 0, 0,0x6C53,0x6C54, 0,
+0x6C56,0x4223, 0,0x6C55,0x3466, 0,0x6C58, 0,
+0x6C57,0x6C59, 0, 0,0x6C5B,0x6C5D, 0,0x6C5E
+};
+
+/* page 42 0x8D64-0x8F64 */
+static uint16 tab_uni_jisx020842[]={
+0x4056, 0,0x3C4F,0x6C5F, 0, 0, 0,0x3352,
+ 0,0x6C60, 0, 0,0x4176,0x6C61, 0,0x6C62,
+0x496B, 0, 0,0x352F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C63, 0, 0,
+ 0,0x4436, 0, 0, 0, 0,0x315B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C64, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C71,
+ 0, 0, 0, 0,0x3F76, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x422D,
+ 0, 0, 0, 0, 0, 0,0x6C67, 0,
+ 0, 0,0x6C66, 0, 0, 0,0x6C65, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6C6D,
+0x6C6B, 0, 0,0x6C68, 0, 0, 0, 0,
+ 0, 0,0x6C6A, 0, 0, 0,0x6C69,0x6C6C,
+ 0,0x3577, 0,0x6C70, 0,0x4057, 0,0x6C71,
+ 0, 0, 0, 0,0x3859, 0,0x6C6E,0x6C6F,
+ 0, 0, 0,0x4F29, 0, 0, 0,0x4437,
+ 0,0x4129, 0, 0, 0, 0, 0, 0,
+0x6C72, 0, 0,0x6C75, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6C73,0x6C74,0x4D59, 0,
+ 0, 0, 0,0x4627,0x6C78, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C76,0x6C77,0x6C79, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D29, 0,
+ 0, 0, 0, 0,0x6C7C, 0, 0, 0,
+0x6C7D,0x6C7B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6C7A, 0,
+0x447D, 0, 0,0x6D21,0x6D25,0x6D22,0x6C7E, 0,
+0x6D23, 0, 0, 0,0x6D24, 0, 0, 0,
+ 0,0x6D2B, 0, 0, 0,0x6D26, 0, 0,
+ 0, 0, 0,0x4058,0x6D28, 0, 0,0x6D2A,
+0x6D27, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D2D, 0,
+0x3D33, 0,0x6D2C, 0, 0, 0, 0, 0,
+0x6D2E, 0, 0, 0, 0,0x6D2F, 0, 0,
+0x6D32,0x6D31, 0,0x6D30, 0, 0,0x6D34,0x6D33,
+ 0,0x4C76, 0, 0, 0,0x6D36, 0,0x6D35,
+0x6D37, 0, 0, 0, 0,0x6D38, 0, 0,
+ 0, 0, 0, 0, 0,0x6D3A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D39,0x3F48,
+0x6D3B, 0, 0,0x366D,0x6D3C,0x6D3E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6D3F, 0, 0, 0, 0, 0,
+ 0,0x6D40,0x6D3D, 0,0x6D41, 0,0x3C56,0x6D42,
+0x3530,0x3733, 0, 0, 0, 0,0x382E, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6D43,
+ 0, 0, 0,0x4670, 0, 0,0x453E,0x6D44,
+ 0, 0, 0, 0, 0, 0, 0,0x6D47,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3C34, 0, 0,0x6D46,
+0x6D45,0x375A,0x6D48, 0, 0, 0, 0,0x3353,
+ 0,0x6D4A, 0, 0, 0,0x3A5C,0x6D49, 0,
+0x6D52, 0, 0, 0, 0, 0,0x6D4C,0x6D4E,
+0x4A65,0x6D4B, 0, 0, 0,0x6D4D, 0,0x6D51,
+0x6D4F,0x3531, 0,0x6D50, 0, 0, 0, 0,
+ 0, 0,0x6D53, 0, 0,0x475A,0x4E58, 0,
+ 0, 0, 0,0x3D34, 0, 0, 0,0x6D54,
+ 0, 0, 0, 0,0x4D22,0x6D56, 0,0x6D55,
+ 0, 0,0x6D59,0x4D41, 0, 0,0x6D58, 0,
+0x336D,0x6D57,0x6D5C, 0, 0,0x6D5B, 0, 0,
+0x6D5A,0x4532,0x6D5D, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6D5E, 0, 0, 0, 0,
+0x6D5F, 0, 0,0x396C, 0,0x3725,0x6D60,0x6D61,
+0x6D62};
+
+/* page 43 0x8F9B-0x9132 */
+static uint16 tab_uni_jisx020843[]={
+0x3F49,0x6D63, 0,0x3C2D,0x6D64, 0, 0, 0,
+0x6D65, 0, 0, 0,0x5221,0x517E, 0, 0,
+ 0, 0,0x6D66,0x6570,0x6D67,0x4324,0x3F2B,0x4740,
+ 0, 0, 0, 0,0x6D68, 0, 0,0x4A55,
+0x4454,0x397E, 0, 0,0x4329, 0, 0,0x312A,
+ 0,0x4B78,0x3F57, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x375E, 0, 0,0x3661, 0,
+ 0,0x4A56, 0, 0, 0, 0, 0,0x6D69,
+ 0, 0, 0, 0, 0, 0, 0,0x6D6B,
+ 0, 0,0x6D6A,0x3260, 0, 0,0x4676,0x6D6C,
+0x4777, 0,0x4533, 0,0x6D6D,0x3D52, 0, 0,
+ 0,0x6D6F, 0, 0,0x4C42,0x6D7E,0x6D71,0x6D72,
+ 0, 0,0x4449, 0, 0,0x4260,0x4177, 0,
+0x4628, 0,0x6D70,0x3555, 0, 0, 0, 0,
+0x6D79, 0,0x6D76,0x6E25,0x4629,0x4360,0x6D73, 0,
+0x447E,0x4553,0x6D74,0x6D78,0x3F60, 0,0x4767,0x444C,
+ 0, 0,0x4042,0x6D77,0x422E,0x4224,0x6D75,0x3029,
+0x4F22, 0, 0, 0,0x6D7A, 0, 0, 0,
+ 0, 0, 0,0x4261, 0, 0,0x3D35,0x3F4A,
+ 0, 0,0x6D7C,0x6D7B, 0,0x306F,0x6D7D, 0,
+ 0,0x492F, 0,0x6E27, 0, 0,0x465B,0x3F6B,
+ 0, 0,0x4359, 0,0x3678, 0,0x6E26,0x4D37,
+0x313F, 0,0x4A57,0x3261,0x6E21,0x6E22,0x6E23,0x6E24,
+0x463B,0x4323,0x3063,0x6E28, 0,0x6E29,0x7423, 0,
+ 0,0x423D, 0,0x6E2A, 0,0x3173,0x414C, 0,
+0x382F, 0,0x4D5A, 0, 0,0x6E2B,0x452C, 0,
+ 0, 0,0x4178,0x3C57,0x6E2C, 0, 0,0x6E2F,
+ 0, 0,0x3D65,0x6E2D,0x412B,0x412A, 0,0x3064,
+ 0,0x4E4B,0x6E31, 0,0x4872,0x6E33,0x6E32,0x6E30,
+0x6364,0x3454, 0, 0,0x6D6E, 0,0x6E35,0x6E34,
+ 0, 0, 0, 0,0x6E36, 0,0x4D38, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4661, 0, 0,0x4B2E, 0,0x6E37, 0,0x3C59,
+ 0, 0, 0, 0,0x6E38, 0,0x6E39, 0,
+ 0, 0,0x6E3A, 0, 0,0x4521, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x306A, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3959,
+ 0, 0, 0,0x4F3A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6E3E, 0, 0, 0, 0, 0,0x3734,0x6E3B,
+ 0,0x6E3C, 0, 0, 0,0x4974, 0, 0,
+ 0, 0,0x3354, 0, 0, 0, 0, 0,
+ 0, 0,0x4D39, 0,0x363F, 0, 0, 0,
+ 0, 0,0x4554, 0, 0, 0, 0,0x6E3F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6E40,
+ 0, 0, 0, 0, 0, 0,0x6E41, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4522, 0, 0,0x6E43, 0,0x6E42
+};
+
+/* page 44 0x9149-0x92B9 */
+static uint16 tab_uni_jisx020844[]={
+0x4653,0x6E44,0x3D36,0x3C60,0x475B,0x4371, 0, 0,
+ 0,0x3C72, 0,0x3F6C, 0,0x6E45, 0,0x6E46,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3F5D,0x6E47, 0,0x6E48, 0, 0, 0,
+0x6E49,0x4D6F, 0,0x3D37, 0, 0, 0, 0,
+ 0,0x6E4B,0x6E4A, 0,0x395A, 0,0x3973,0x3B40,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6E4E, 0, 0, 0, 0,0x3D66, 0,
+0x6E4D, 0,0x6E4C, 0,0x4269, 0, 0,0x386F,
+ 0,0x4043, 0, 0, 0, 0,0x4830, 0,
+ 0, 0, 0,0x3D39, 0, 0, 0, 0,
+ 0,0x6E4F, 0,0x3E5F, 0, 0, 0, 0,
+ 0,0x6E52,0x6E50, 0, 0, 0,0x6E51, 0,
+ 0, 0, 0,0x6E54,0x6E53, 0, 0,0x3E7A,
+ 0,0x6E55, 0, 0, 0, 0, 0,0x6E56,
+0x6E57, 0, 0, 0, 0,0x4850,0x3A53,0x3C61,
+0x6E58, 0,0x6E59,0x4E24,0x3D45,0x4C6E,0x4E4C,0x6E5A,
+0x3662, 0, 0, 0, 0,0x6E5B, 0,0x4523,
+ 0, 0,0x6E5E,0x3378,0x3F4B, 0,0x6E5C, 0,
+0x6E5D, 0,0x4460, 0, 0,0x4B55,0x367C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6E60,0x6E61, 0, 0,
+ 0, 0, 0,0x6E5F, 0, 0,0x6E63, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x465F,0x3343, 0, 0,
+0x6E67, 0, 0,0x6E64,0x6E66, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6E62, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6F4F, 0, 0,0x6E65, 0, 0, 0, 0,
+ 0, 0, 0,0x4E6B, 0, 0,0x385A, 0,
+ 0, 0, 0, 0, 0, 0,0x6E6F, 0,
+ 0, 0, 0,0x4534,0x6E6A, 0, 0,0x6E6D,
+0x6E6B, 0,0x6E70, 0, 0, 0, 0,0x6E71,
+ 0, 0, 0, 0, 0, 0,0x6E69, 0,
+ 0,0x6E76,0x3174, 0, 0,0x6E68, 0, 0,
+ 0,0x482D, 0,0x6E6C, 0,0x3E60, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x395B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4B48, 0,0x3664,
+ 0, 0,0x3D46, 0,0x463C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x412D, 0,0x6E74, 0,0x6E6E,0x6E73, 0,0x4C43,
+ 0,0x4438,0x6E75,0x6E72, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x412C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6E79, 0,
+0x6E78};
+
+/* page 45 0x92CF-0x93E8 */
+static uint16 tab_uni_jisx020845[]={
+0x6E77, 0, 0,0x4B2F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3D7B, 0, 0,
+ 0, 0,0x6E7A,0x4A5F, 0, 0,0x3154, 0,
+ 0, 0, 0,0x4946,0x4372, 0, 0, 0,
+ 0,0x3578, 0,0x6E7C, 0,0x395D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3B2C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6E7B,0x3F6D, 0, 0, 0, 0, 0, 0,
+ 0,0x3F6E,0x6F21,0x6F23, 0, 0, 0, 0,
+ 0,0x3E7B, 0,0x6F22,0x6F24, 0, 0,0x3653,
+ 0,0x4945, 0, 0,0x3C62,0x4F23, 0,0x6E7E,
+0x3A78, 0, 0,0x4F3F, 0, 0,0x6F26, 0,
+ 0, 0, 0,0x6F25,0x6F27, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6E7D, 0, 0,
+ 0, 0, 0, 0,0x4669, 0,0x4555, 0,
+ 0, 0, 0, 0, 0,0x4457, 0,0x6F2C,
+ 0, 0, 0, 0,0x4343,0x6F28, 0, 0,
+ 0,0x6F29, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x372D, 0,0x6F2B,
+ 0, 0, 0, 0, 0, 0,0x3830, 0,
+ 0, 0, 0, 0, 0,0x6F2A, 0,0x3E61,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3379, 0, 0,
+ 0, 0, 0, 0, 0,0x6F30, 0,0x3A3F,
+0x4179, 0, 0,0x444A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x333B, 0, 0, 0, 0,0x6F2E,0x6F2F,0x4443,
+ 0,0x6F2D, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6F31, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6F37, 0, 0, 0,
+ 0,0x6F3A, 0, 0, 0, 0, 0, 0,
+ 0,0x6F39,0x452D, 0, 0, 0, 0,0x6F32,
+0x6F33,0x6F36, 0, 0, 0, 0,0x6F38, 0,
+ 0, 0,0x3640, 0, 0,0x6F3B,0x6F35, 0,
+ 0,0x6F34};
+
+/* page 46 0x9403-0x9481 */
+static uint16 tab_uni_jisx020846[]={
+0x6F3F, 0, 0, 0,0x6F40, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6F41, 0, 0,
+0x6F3E,0x6F3D, 0, 0, 0,0x3E62,0x462A,0x6F3C,
+ 0, 0, 0, 0, 0, 0,0x6F45, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6F43, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6F44,0x6F42, 0,0x4278, 0,0x6F46,
+ 0, 0, 0, 0, 0, 0,0x6F47, 0,
+ 0,0x6F49, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3455,0x6F48,
+0x4C7A, 0, 0, 0, 0, 0, 0,0x6F54,
+0x6F4A, 0, 0,0x6F4D, 0,0x6F4B, 0,0x6F4C,
+ 0, 0, 0, 0, 0, 0, 0,0x6F4E,
+ 0, 0, 0, 0, 0,0x6F50, 0, 0,
+ 0, 0,0x6F51, 0,0x6F52, 0, 0, 0,
+ 0,0x6F55,0x6F53,0x6F56,0x6F58, 0,0x6F57};
+
+/* page 47 0x9577-0x95E5 */
+static uint16 tab_uni_jisx020847[]={
+0x4439, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4C67, 0,0x6F59,0x412E, 0, 0, 0,
+0x6F5A, 0,0x4A44,0x6F5B,0x332B, 0, 0, 0,
+0x313C, 0,0x3457, 0,0x3456,0x6F5C, 0,0x6F5D,
+ 0,0x6F5E,0x6F5F, 0, 0, 0, 0, 0,
+ 0,0x6F60, 0,0x3458,0x3355,0x395E,0x4836, 0,
+0x6F62,0x6F61, 0, 0, 0, 0,0x6F63, 0,
+ 0, 0, 0,0x315C, 0, 0, 0, 0,
+ 0, 0,0x6F66, 0,0x6F65,0x6F64, 0,0x6F67,
+ 0, 0, 0, 0,0x6F6A, 0, 0, 0,
+0x3047, 0, 0,0x6F68, 0,0x6F6C,0x6F6B, 0,
+ 0, 0, 0, 0, 0,0x6F6E,0x6F6D,0x6F6F,
+ 0,0x462E, 0, 0, 0,0x6F70, 0, 0,
+ 0, 0,0x6F71,0x6F73, 0, 0,0x6F72};
+
+/* page 48 0x961C-0x9874 */
+static uint16 tab_uni_jisx020848[]={
+0x496C, 0, 0, 0, 0,0x6F74, 0, 0,
+ 0, 0, 0, 0,0x6F75, 0,0x3A65, 0,
+ 0, 0,0x6F76,0x6F77, 0, 0,0x4B49, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x414B,
+ 0, 0, 0,0x3024,0x424B, 0,0x6F78, 0,
+0x496D, 0, 0, 0, 0, 0, 0,0x6F7B,
+0x6F79,0x395F, 0,0x6F7A,0x3842, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4A45,
+0x6F7D,0x7021,0x6F7E,0x7022, 0, 0,0x3121,0x3F58,
+0x3D7C,0x3459,0x7023, 0, 0, 0,0x4766, 0,
+0x7025, 0, 0, 0,0x3122, 0,0x7024,0x4444,
+ 0,0x4E4D,0x462B,0x6F7C,0x4E26, 0,0x3831, 0,
+ 0,0x4D5B, 0, 0, 0, 0, 0, 0,
+ 0,0x3679,0x4E34, 0,0x3728, 0,0x4262,0x6721,
+ 0,0x7026,0x332C,0x3F6F, 0, 0, 0, 0,
+0x3356,0x7028, 0,0x7029,0x7027,0x3764, 0,0x3A5D,
+0x3E63, 0, 0, 0,0x3123, 0, 0,0x4E59,
+ 0, 0, 0,0x702B,0x6E2E, 0,0x702A, 0,
+ 0, 0, 0, 0,0x702E,0x702C,0x702D, 0,
+0x702F, 0,0x7030,0x4E6C,0x7031,0x7032, 0,0x4049,
+0x483B, 0, 0, 0,0x3F7D,0x3467, 0, 0,
+0x4D3A,0x326D,0x3D38,0x385B, 0,0x7035, 0,0x7034,
+0x3B73,0x7036,0x7033, 0, 0,0x3B28, 0, 0,
+ 0,0x703A,0x6A2D, 0, 0,0x5256, 0,0x3F77,
+0x7038, 0, 0, 0, 0, 0,0x4E25,0x4671,
+ 0, 0, 0, 0,0x312B, 0,0x4063,0x3C36,
+ 0, 0, 0, 0,0x4A37, 0,0x3140, 0,
+ 0, 0,0x4E6D,0x4D6B, 0,0x703B, 0,0x4545,
+ 0, 0, 0, 0,0x3C7B, 0, 0, 0,
+0x703C, 0,0x703D,0x3F4C,0x703E, 0,0x4E6E, 0,
+ 0,0x7039,0x7040,0x7042, 0,0x7041, 0,0x703F,
+ 0, 0,0x7043, 0, 0,0x7044, 0, 0,
+0x417A, 0,0x3262, 0, 0, 0, 0, 0,
+0x7045, 0, 0,0x4C38, 0, 0,0x7046, 0,
+ 0, 0, 0, 0,0x7047, 0,0x4F2A, 0,
+ 0, 0, 0, 0,0x5B31,0x7048, 0, 0,
+ 0,0x7049,0x704A, 0, 0, 0,0x704E, 0,
+0x704B, 0,0x704C, 0,0x704D,0x704F, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4044, 0,
+ 0, 0,0x4C77, 0, 0,0x4045, 0, 0,
+0x7050, 0,0x4873, 0,0x7051,0x7353,0x4C4C, 0,
+0x7052, 0,0x7053, 0,0x7054,0x3357, 0,0x7056,
+ 0,0x3F59, 0, 0, 0,0x7057, 0, 0,
+0x3724, 0, 0, 0, 0,0x7058,0x705C, 0,
+0x705A, 0, 0, 0, 0,0x705B, 0, 0,
+0x3373,0x7059,0x705D, 0, 0, 0, 0,0x705E,
+ 0,0x3048, 0,0x705F,0x7060, 0, 0, 0,
+ 0, 0, 0, 0,0x3E64, 0, 0, 0,
+0x7061, 0, 0, 0,0x3547, 0, 0,0x7064,
+ 0, 0,0x7063, 0,0x7062, 0, 0,0x6B71,
+ 0,0x4A5C, 0, 0, 0, 0, 0,0x7065,
+0x7066, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7067,
+ 0, 0,0x7068, 0,0x7069, 0, 0,0x706A,
+ 0, 0, 0, 0, 0, 0, 0,0x345A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x706B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x706C,0x4723, 0, 0, 0,0x706E,0x323B,
+ 0,0x7071,0x7070, 0, 0, 0, 0,0x3124,
+ 0, 0, 0,0x3641, 0,0x4A47,0x443A,0x3A22,
+ 0,0x3960,0x3D67, 0,0x3F5C, 0, 0, 0,
+0x7073, 0, 0,0x7072,0x4D42,0x3468,0x4852,0x465C,
+ 0, 0, 0,0x3F7C,0x4E4E, 0,0x375B, 0,
+ 0, 0, 0, 0, 0,0x7076, 0, 0,
+0x7075, 0, 0, 0, 0, 0, 0, 0,
+0x4B4B,0x462C, 0, 0, 0, 0, 0, 0,
+0x3150, 0, 0,0x7077,0x7074, 0, 0,0x4951,
+0x4D6A,0x7078, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7079, 0, 0, 0, 0,0x707B,
+0x426A,0x335B,0x335C,0x707A, 0, 0, 0, 0,
+0x3469,0x3832, 0, 0,0x346A, 0, 0,0x453F,
+ 0, 0,0x4E60, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x385C, 0, 0, 0,0x707C,
+ 0, 0, 0,0x707D,0x707E,0x7121, 0,0x7123,
+0x7122};
+
+/* page 49 0x98A8-0x98C6 */
+static uint16 tab_uni_jisx020849[]={
+0x4977, 0,0x7124, 0, 0, 0, 0,0x7125,
+ 0,0x7126, 0, 0, 0, 0,0x7127, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x7129,0x7128, 0,0x712A};
+
+/* page 50 0x98DB-0x9957 */
+static uint16 tab_uni_jisx020850[]={
+0x4874,0x664C, 0, 0,0x3F29, 0, 0,0x3532,
+ 0, 0, 0, 0, 0, 0,0x712B, 0,
+0x712C, 0,0x522C,0x5D3B,0x4853, 0, 0,0x307B,
+ 0,0x303B, 0, 0, 0, 0, 0, 0,
+ 0,0x3B74,0x4B30,0x3E7E, 0, 0, 0, 0,
+0x712D, 0,0x4C5F, 0, 0, 0,0x712E,0x4D5C,
+ 0,0x3142, 0, 0, 0,0x3B41, 0,0x712F,
+0x326E,0x7130, 0, 0, 0,0x7131, 0, 0,
+ 0, 0,0x7133,0x7134, 0,0x7136,0x7132, 0,
+ 0,0x7135, 0, 0, 0,0x345B, 0, 0,
+ 0,0x7137, 0,0x7138, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7139,0x713A, 0, 0, 0,0x713B,
+ 0, 0,0x713D, 0, 0, 0,0x713C, 0,
+0x713F,0x7142, 0, 0, 0,0x713E,0x7140,0x7141,
+ 0, 0,0x7143, 0,0x3642};
+
+/* page 51 0x9996-0x9A6B */
+static uint16 tab_uni_jisx020851[]={
+0x3C73,0x7144,0x7145,0x3961, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7146,
+ 0, 0,0x333E, 0, 0, 0,0x474F,0x7147,
+0x7148, 0, 0, 0, 0,0x435A,0x466B, 0,
+ 0, 0, 0, 0, 0, 0,0x7149, 0,
+ 0, 0, 0,0x477D, 0, 0,0x424C,0x3158,
+0x366E, 0,0x366F, 0, 0, 0, 0, 0,
+ 0, 0,0x4373,0x714E,0x3670, 0, 0,0x326F,
+ 0, 0,0x714D, 0, 0,0x714B, 0,0x714C,
+ 0,0x714A, 0, 0,0x7158, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x714F,
+0x7150, 0, 0,0x7151,0x7152, 0, 0, 0,
+ 0, 0,0x7154, 0, 0,0x7153, 0, 0,
+ 0,0x3D59, 0,0x7155, 0, 0, 0,0x7157,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3533,0x7156, 0, 0,0x417B,0x3833, 0, 0,
+ 0, 0, 0,0x7159, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x424D, 0, 0,0x715A, 0, 0,
+ 0, 0,0x462D, 0, 0, 0, 0, 0,
+ 0,0x715B, 0, 0, 0, 0, 0, 0,
+0x7160, 0,0x715E, 0,0x715D,0x715F, 0,0x715C,
+ 0, 0, 0, 0, 0, 0, 0,0x7162,
+ 0, 0, 0, 0, 0, 0, 0,0x7161,
+ 0,0x7164, 0, 0,0x3643,0x7163, 0, 0,
+ 0,0x7165, 0, 0,0x7166, 0,0x7168,0x7167,
+ 0, 0, 0,0x7169,0x716B,0x716A};
+
+/* page 52 0x9AA8-0x9B5A */
+static uint16 tab_uni_jisx020852[]={
+0x397C, 0, 0, 0, 0,0x716C, 0, 0,
+0x716D, 0, 0, 0, 0, 0, 0, 0,
+0x333C, 0, 0, 0,0x716E, 0, 0, 0,
+0x716F, 0, 0, 0,0x3F71, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7170,
+ 0,0x7171, 0,0x7172,0x7173, 0, 0, 0,
+0x3962, 0, 0, 0, 0, 0,0x7174,0x7175,
+ 0, 0,0x7176,0x7177, 0, 0,0x7178, 0,
+ 0, 0,0x4831,0x717A, 0,0x4926,0x717B,0x7179,
+ 0,0x717D, 0, 0,0x717C, 0, 0,0x717E,
+ 0, 0, 0,0x7221, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7222, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7223, 0,0x7224, 0, 0, 0, 0,0x7225,
+ 0, 0,0x7226,0x7227, 0,0x7228, 0,0x7229,
+0x722A,0x722B,0x722C, 0, 0, 0,0x722D,0x722E,
+ 0,0x5D35,0x722F, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6478,0x3534, 0, 0, 0,
+ 0,0x3321,0x3A32,0x7231,0x7230,0x4C25, 0, 0,
+ 0, 0, 0, 0, 0,0x7233,0x7234,0x7232,
+ 0,0x7235, 0, 0,0x4B62, 0, 0, 0,
+0x7236, 0,0x357B};
+
+/* page 53 0x9B6F-0x9C78 */
+static uint16 tab_uni_jisx020853[]={
+0x4F25, 0, 0, 0, 0,0x7237, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x7239, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x303E,
+ 0, 0,0x723A,0x4A2B,0x7238, 0, 0,0x723B,
+0x723C, 0, 0, 0, 0, 0, 0, 0,
+0x723D,0x723E, 0, 0, 0, 0, 0, 0,
+ 0,0x723F, 0,0x4B6E,0x3B2D, 0,0x3A7A,0x412F,
+ 0, 0, 0, 0, 0,0x7240, 0, 0,
+ 0, 0,0x7243, 0, 0, 0, 0, 0,
+ 0,0x7241, 0, 0, 0, 0, 0,0x7244,
+ 0, 0,0x3871,0x7242, 0, 0, 0, 0,
+0x7245, 0,0x7246,0x7247, 0,0x724B, 0,0x3B2A,
+ 0, 0, 0, 0,0x4264, 0, 0, 0,
+ 0, 0,0x724C,0x7249,0x7248,0x724A, 0, 0,
+ 0,0x375F, 0, 0, 0, 0, 0, 0,
+ 0,0x7250,0x724F,0x724E, 0, 0,0x3033, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x725A, 0,0x7256,
+ 0,0x7257,0x7253,0x7259, 0,0x7255,0x3362, 0,
+ 0,0x4F4C, 0,0x7258,0x7254,0x7252,0x7251, 0,
+ 0, 0, 0, 0,0x725C, 0, 0, 0,
+ 0, 0,0x725F, 0, 0,0x725E,0x725D, 0,
+ 0, 0, 0, 0, 0, 0,0x4949,0x725B,
+0x3073,0x7260, 0,0x7262, 0, 0, 0, 0,
+ 0, 0,0x336F,0x724D,0x3137, 0, 0,0x7264,
+ 0, 0, 0, 0, 0, 0, 0,0x7263,
+0x7261,0x432D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4B70, 0, 0, 0, 0,
+0x4E5A, 0, 0,0x7265, 0, 0, 0, 0,
+ 0,0x7266, 0, 0, 0, 0, 0, 0,
+0x7267, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7268,
+ 0,0x7269};
+
+/* page 54 0x9CE5-0x9DFD */
+static uint16 tab_uni_jisx020854[]={
+0x443B, 0,0x726A, 0,0x4837, 0,0x726F,0x726B,
+ 0, 0, 0,0x726C, 0, 0,0x4B31,0x4C44,
+ 0,0x4650, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7270, 0,
+ 0,0x7271,0x463E,0x726E,0x726D, 0, 0, 0,
+ 0,0x322A, 0, 0, 0,0x7279, 0, 0,
+0x7278, 0, 0, 0, 0, 0,0x3175, 0,
+ 0, 0,0x7276, 0, 0, 0,0x7275, 0,
+ 0,0x7273, 0,0x337B, 0,0x7272,0x3C32,0x3229,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3963, 0,
+ 0,0x727C,0x727B, 0,0x727A, 0, 0,0x7277,
+ 0,0x727D, 0,0x727E, 0, 0, 0, 0,
+ 0, 0, 0,0x7325,0x7324, 0, 0, 0,
+ 0, 0, 0, 0,0x7326, 0, 0,0x312D,
+0x7321,0x7322, 0,0x3974,0x4C39, 0, 0,0x7323,
+ 0, 0, 0, 0, 0, 0, 0,0x4B32,
+ 0, 0,0x732B, 0, 0,0x7327, 0, 0,
+ 0, 0, 0, 0, 0,0x732C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7329, 0,0x7328, 0, 0, 0,
+ 0, 0,0x375C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x732D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x732E,
+ 0, 0, 0, 0,0x732F, 0,0x732A, 0,
+ 0, 0,0x7274, 0, 0,0x7330, 0,0x4461,
+ 0, 0, 0,0x7334, 0,0x7335,0x7333, 0,
+ 0, 0, 0, 0,0x7332,0x7338, 0,0x7331,
+ 0,0x7336, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7337, 0, 0, 0,0x733A, 0,
+ 0, 0, 0, 0,0x7339, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x733C, 0, 0, 0, 0, 0, 0,
+0x733D, 0,0x733E, 0, 0,0x4F49, 0, 0,
+ 0, 0, 0,0x733B,0x426B,0x3A6D, 0, 0,
+0x733F};
+
+/* page 55 0x9E1A-0x9E1E */
+static uint16 tab_uni_jisx020855[]={
+0x7340,0x7341, 0, 0,0x7342};
+
+/* page 56 0x9E75-0x9F77 */
+static uint16 tab_uni_jisx020856[]={
+0x7343, 0, 0,0x3834,0x7344, 0, 0, 0,
+0x7345, 0,0x3C2F, 0,0x7346, 0, 0, 0,
+ 0, 0, 0,0x7347, 0, 0,0x7348,0x7349,
+ 0, 0, 0, 0,0x734C,0x734A,0x4F3C, 0,
+0x734B, 0,0x4E6F, 0, 0, 0, 0, 0,
+0x734D, 0,0x4E5B, 0, 0, 0, 0, 0,
+0x734E,0x477E, 0, 0,0x734F,0x7351, 0, 0,
+0x7352, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x7350,0x396D,0x4C4D,0x4B63,0x5677,
+ 0,0x5D60,0x4B7B, 0, 0, 0, 0,0x322B,
+ 0, 0, 0, 0, 0, 0, 0,0x7354,
+0x3550,0x7355,0x7356,0x7357, 0,0x3975, 0,0x7358,
+ 0, 0, 0,0x6054,0x4C5B, 0,0x4263,0x7359,
+0x735B,0x735A, 0,0x735C, 0, 0, 0, 0,
+0x735D, 0, 0,0x735E, 0, 0, 0, 0,
+ 0, 0,0x735F, 0, 0, 0, 0,0x7360,
+ 0,0x7361,0x7362, 0,0x7363, 0,0x7364,0x7365,
+0x7366, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7367,0x7368, 0, 0, 0, 0,
+ 0,0x4524, 0, 0, 0, 0,0x385D, 0,
+0x736A, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x414D,0x736B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x736C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4921, 0,
+ 0,0x736D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x736E,0x6337, 0,
+ 0,0x6C5A,0x706D, 0, 0,0x736F, 0,0x7370,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7372,0x7373,0x7374,0x4E70,0x7371, 0,
+ 0,0x7375,0x7376, 0, 0,0x7378, 0,0x7377,
+ 0, 0, 0, 0, 0,0x737A, 0, 0,
+ 0,0x737B,0x7379};
+
+/* page 57 0x9F8D-0x9FA0 */
+static uint16 tab_uni_jisx020857[]={
+0x4E36, 0, 0, 0, 0, 0, 0, 0,
+0x737C, 0, 0, 0, 0, 0, 0,0x737D,
+0x6354, 0, 0,0x737E};
+
+/* page 58 0xFF01-0xFF5E */
+static uint16 tab_uni_jisx020858[]={
+0x212A, 0,0x2174,0x2170,0x2173,0x2175, 0,0x214A,
+0x214B,0x2176,0x215C,0x2124,0x215D,0x2125,0x213F,0x2330,
+0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,0x2338,
+0x2339,0x2127,0x2128,0x2163,0x2161,0x2164,0x2129,0x2177,
+0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347,0x2348,
+0x2349,0x234A,0x234B,0x234C,0x234D,0x234E,0x234F,0x2350,
+0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357,0x2358,
+0x2359,0x235A,0x214E,0x2140,0x214F,0x2130,0x2132,0x212E,
+0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367,0x2368,
+0x2369,0x236A,0x236B,0x236C,0x236D,0x236E,0x236F,0x2370,
+0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377,0x2378,
+0x2379,0x237A,0x2150,0x2143,0x2151,0x2141};
+
+/* page 59 0xFFE0-0xFFE5 */
+static uint16 tab_uni_jisx020859[]={
+0x2171,0x2172,0x224C,0x2131, 0,0x216F};
+
+static int
+my_uni_jisx0208_onechar(int code){
+ if ((code>=0x005C)&&(code<=0x005C))
+ return(tab_uni_jisx02080[code-0x005C]);
+ if ((code>=0x00A2)&&(code<=0x00B6))
+ return(tab_uni_jisx02081[code-0x00A2]);
+ if ((code>=0x00D7)&&(code<=0x00D7))
+ return(tab_uni_jisx02082[code-0x00D7]);
+ if ((code>=0x00F7)&&(code<=0x00F7))
+ return(tab_uni_jisx02083[code-0x00F7]);
+ if ((code>=0x0391)&&(code<=0x03C9))
+ return(tab_uni_jisx02084[code-0x0391]);
+ if ((code>=0x0401)&&(code<=0x0451))
+ return(tab_uni_jisx02085[code-0x0401]);
+ if ((code>=0x2010)&&(code<=0x203B))
+ return(tab_uni_jisx02086[code-0x2010]);
+ if ((code>=0x2100)&&(code<=0x2116))
+ return(tab_uni_jisx02087[code-0x2100]);
+ if ((code>=0x2120)&&(code<=0x212B))
+ return(tab_uni_jisx02088[code-0x2120]);
+ if ((code>=0x2160)&&(code<=0x2169))
+ return(tab_uni_jisx02089[code-0x2160]);
+ if ((code>=0x2190)&&(code<=0x2193))
+ return(tab_uni_jisx020810[code-0x2190]);
+ if ((code>=0x21D2)&&(code<=0x21D4))
+ return(tab_uni_jisx020811[code-0x21D2]);
+ if ((code>=0x2200)&&(code<=0x223D))
+ return(tab_uni_jisx020812[code-0x2200]);
+ if ((code>=0x2252)&&(code<=0x226B))
+ return(tab_uni_jisx020813[code-0x2252]);
+ if ((code>=0x2282)&&(code<=0x2287))
+ return(tab_uni_jisx020814[code-0x2282]);
+ if ((code>=0x22A0)&&(code<=0x22BF))
+ return(tab_uni_jisx020815[code-0x22A0]);
+ if ((code>=0x2312)&&(code<=0x2312))
+ return(tab_uni_jisx020816[code-0x2312]);
+ if ((code>=0x2460)&&(code<=0x2473))
+ return(tab_uni_jisx020817[code-0x2460]);
+ if ((code>=0x2500)&&(code<=0x254B))
+ return(tab_uni_jisx020818[code-0x2500]);
+ if ((code>=0x25A0)&&(code<=0x25CF))
+ return(tab_uni_jisx020819[code-0x25A0]);
+ if ((code>=0x25EF)&&(code<=0x25EF))
+ return(tab_uni_jisx020820[code-0x25EF]);
+ if ((code>=0x2605)&&(code<=0x2606))
+ return(tab_uni_jisx020821[code-0x2605]);
+ if ((code>=0x2640)&&(code<=0x2642))
+ return(tab_uni_jisx020822[code-0x2640]);
+ if ((code>=0x266A)&&(code<=0x266F))
+ return(tab_uni_jisx020823[code-0x266A]);
+ if ((code>=0x3000)&&(code<=0x301F))
+ return(tab_uni_jisx020824[code-0x3000]);
+ if ((code>=0x3041)&&(code<=0x30FE))
+ return(tab_uni_jisx020825[code-0x3041]);
+ if ((code>=0x3230)&&(code<=0x3239))
+ return(tab_uni_jisx020826[code-0x3230]);
+ if ((code>=0x32A0)&&(code<=0x32A8))
+ return(tab_uni_jisx020827[code-0x32A0]);
+ if ((code>=0x3300)&&(code<=0x33CD))
+ return(tab_uni_jisx020828[code-0x3300]);
+ if ((code>=0x4E00)&&(code<=0x5516))
+ return(tab_uni_jisx020829[code-0x4E00]);
+ if ((code>=0x552E)&&(code<=0x5563))
+ return(tab_uni_jisx020830[code-0x552E]);
+ if ((code>=0x557B)&&(code<=0x576A))
+ return(tab_uni_jisx020831[code-0x557B]);
+ if ((code>=0x577F)&&(code<=0x5A9B))
+ return(tab_uni_jisx020832[code-0x577F]);
+ if ((code>=0x5ABC)&&(code<=0x5D29))
+ return(tab_uni_jisx020833[code-0x5ABC]);
+ if ((code>=0x5D4B)&&(code<=0x6BF3))
+ return(tab_uni_jisx020834[code-0x5D4B]);
+ if ((code>=0x6C08)&&(code<=0x6CF3))
+ return(tab_uni_jisx020835[code-0x6C08]);
+ if ((code>=0x6D0B)&&(code<=0x7409))
+ return(tab_uni_jisx020836[code-0x6D0B]);
+ if ((code>=0x7422)&&(code<=0x7845))
+ return(tab_uni_jisx020837[code-0x7422]);
+ if ((code>=0x785D)&&(code<=0x7E9C))
+ return(tab_uni_jisx020838[code-0x785D]);
+ if ((code>=0x7F36)&&(code<=0x8358))
+ return(tab_uni_jisx020839[code-0x7F36]);
+ if ((code>=0x8373)&&(code<=0x8B9A))
+ return(tab_uni_jisx020840[code-0x8373]);
+ if ((code>=0x8C37)&&(code<=0x8D16))
+ return(tab_uni_jisx020841[code-0x8C37]);
+ if ((code>=0x8D64)&&(code<=0x8F64))
+ return(tab_uni_jisx020842[code-0x8D64]);
+ if ((code>=0x8F9B)&&(code<=0x9132))
+ return(tab_uni_jisx020843[code-0x8F9B]);
+ if ((code>=0x9149)&&(code<=0x92B9))
+ return(tab_uni_jisx020844[code-0x9149]);
+ if ((code>=0x92CF)&&(code<=0x93E8))
+ return(tab_uni_jisx020845[code-0x92CF]);
+ if ((code>=0x9403)&&(code<=0x9481))
+ return(tab_uni_jisx020846[code-0x9403]);
+ if ((code>=0x9577)&&(code<=0x95E5))
+ return(tab_uni_jisx020847[code-0x9577]);
+ if ((code>=0x961C)&&(code<=0x9874))
+ return(tab_uni_jisx020848[code-0x961C]);
+ if ((code>=0x98A8)&&(code<=0x98C6))
+ return(tab_uni_jisx020849[code-0x98A8]);
+ if ((code>=0x98DB)&&(code<=0x9957))
+ return(tab_uni_jisx020850[code-0x98DB]);
+ if ((code>=0x9996)&&(code<=0x9A6B))
+ return(tab_uni_jisx020851[code-0x9996]);
+ if ((code>=0x9AA8)&&(code<=0x9B5A))
+ return(tab_uni_jisx020852[code-0x9AA8]);
+ if ((code>=0x9B6F)&&(code<=0x9C78))
+ return(tab_uni_jisx020853[code-0x9B6F]);
+ if ((code>=0x9CE5)&&(code<=0x9DFD))
+ return(tab_uni_jisx020854[code-0x9CE5]);
+ if ((code>=0x9E1A)&&(code<=0x9E1E))
+ return(tab_uni_jisx020855[code-0x9E1A]);
+ if ((code>=0x9E75)&&(code<=0x9F77))
+ return(tab_uni_jisx020856[code-0x9E75]);
+ if ((code>=0x9F8D)&&(code<=0x9FA0))
+ return(tab_uni_jisx020857[code-0x9F8D]);
+ if ((code>=0xFF01)&&(code<=0xFF5E))
+ return(tab_uni_jisx020858[code-0xFF01]);
+ if ((code>=0xFFE0)&&(code<=0xFFE5))
+ return(tab_uni_jisx020859[code-0xFFE0]);
+ return(0);
+}
+
+
+/* page 0 0x007E-0x007E */
+static uint16 tab_uni_jisx02120[]={
+ 0};
+
+/* page 1 0x00A1-0x017E */
+static uint16 tab_uni_jisx02121[]={
+0x2242, 0, 0,0x2270, 0, 0, 0, 0,
+0x226D,0x226C, 0, 0, 0,0x226E,0x2234, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2231,
+ 0,0x226B, 0, 0, 0, 0,0x2244,0x2A22,
+0x2A21,0x2A24,0x2A2A,0x2A23,0x2A29,0x2921,0x2A2E,0x2A32,
+0x2A31,0x2A34,0x2A33,0x2A40,0x2A3F,0x2A42,0x2A41, 0,
+0x2A50,0x2A52,0x2A51,0x2A54,0x2A58,0x2A53, 0,0x292C,
+0x2A63,0x2A62,0x2A65,0x2A64,0x2A72,0x2930,0x294E,0x2B22,
+0x2B21,0x2B24,0x2B2A,0x2B23,0x2B29,0x2941,0x2B2E,0x2B32,
+0x2B31,0x2B34,0x2B33,0x2B40,0x2B3F,0x2B42,0x2B41,0x2943,
+0x2B50,0x2B52,0x2B51,0x2B54,0x2B58,0x2B53, 0,0x294C,
+0x2B63,0x2B62,0x2B65,0x2B64,0x2B72,0x2950,0x2B73,0x2A27,
+0x2B27,0x2A25,0x2B25,0x2A28,0x2B28,0x2A2B,0x2B2B,0x2A2C,
+0x2B2C,0x2A2F,0x2B2F,0x2A2D,0x2B2D,0x2A30,0x2B30,0x2922,
+0x2942,0x2A37,0x2B37, 0, 0,0x2A36,0x2B36,0x2A38,
+0x2B38,0x2A35,0x2B35,0x2A3A,0x2B3A,0x2A3B,0x2B3B,0x2A3D,
+0x2B3D,0x2A3C, 0,0x2A3E,0x2B3E,0x2924,0x2944,0x2A47,
+0x2B47,0x2A45,0x2B45, 0, 0,0x2A46,0x2B46,0x2A44,
+0x2945,0x2926,0x2946,0x2A48,0x2B48,0x2A49,0x2B49,0x2947,
+0x2A4A,0x2B4A,0x2A4C,0x2B4C,0x2A4B,0x2B4B,0x2929,0x2949,
+0x2928,0x2948,0x2A4D,0x2B4D,0x2A4F,0x2B4F,0x2A4E,0x2B4E,
+0x294A,0x292B,0x294B,0x2A57,0x2B57, 0, 0,0x2A56,
+0x2B56,0x292D,0x294D,0x2A59,0x2B59,0x2A5B,0x2B5B,0x2A5A,
+0x2B5A,0x2A5C,0x2B5C,0x2A5D,0x2B5D,0x2A5F,0x2B5F,0x2A5E,
+0x2B5E,0x2A61,0x2B61,0x2A60,0x2B60,0x292F,0x294F,0x2A6C,
+0x2B6C,0x2A69,0x2B69,0x2A66,0x2B66,0x2A6B,0x2B6B,0x2A68,
+0x2B68,0x2A6A,0x2B6A,0x2A71,0x2B71,0x2A74,0x2B74,0x2A73,
+0x2A75,0x2B75,0x2A77,0x2B77,0x2A76,0x2B76};
+
+/* page 2 0x01CD-0x01DC */
+static uint16 tab_uni_jisx02122[]={
+0x2A26,0x2B26,0x2A43,0x2B43,0x2A55,0x2B55,0x2A67,0x2B67,
+0x2A70,0x2B70,0x2A6D,0x2B6D,0x2A6F,0x2B6F,0x2A6E,0x2B6E
+};
+
+/* page 3 0x01F5-0x01F5 */
+static uint16 tab_uni_jisx02123[]={
+0x2B39};
+
+/* page 4 0x02C7-0x02DD */
+static uint16 tab_uni_jisx02124[]={
+0x2230, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x222F,0x2232,0x2236,0x2235, 0,0x2233};
+
+/* page 5 0x0384-0x0390 */
+static uint16 tab_uni_jisx02125[]={
+0x2238,0x2239,0x2661, 0,0x2662,0x2663,0x2664, 0,
+0x2667, 0,0x2669,0x266C,0x2676};
+
+/* page 6 0x03AA-0x03CE */
+static uint16 tab_uni_jisx02126[]={
+0x2665,0x266A,0x2671,0x2672,0x2673,0x2674,0x267B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x2678, 0, 0, 0, 0, 0, 0, 0,
+0x2675,0x267A,0x2677,0x2679,0x267C};
+
+/* page 7 0x0402-0x040F */
+static uint16 tab_uni_jisx02127[]={
+0x2742,0x2743,0x2744,0x2745,0x2746,0x2747,0x2748,0x2749,
+0x274A,0x274B,0x274C, 0,0x274D,0x274E};
+
+/* page 8 0x0452-0x045F */
+static uint16 tab_uni_jisx02128[]={
+0x2772,0x2773,0x2774,0x2775,0x2776,0x2777,0x2778,0x2779,
+0x277A,0x277B,0x277C, 0,0x277D,0x277E};
+
+/* page 9 0x2122-0x2122 */
+static uint16 tab_uni_jisx02129[]={
+0x226F};
+
+/* page 10 0x2170-0x2179 */
+static uint16 tab_uni_jisx021210[]={
+0x7373,0x7374,0x7375,0x7376,0x7377,0x7378,0x7379,0x737A,
+0x737B,0x737C};
+
+/* page 11 0x4E02-0x4F19 */
+static uint16 tab_uni_jisx021211[]={
+0x3021, 0,0x3022,0x3023, 0, 0, 0, 0,
+ 0, 0,0x3024, 0, 0, 0, 0, 0,
+0x3025, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3026, 0, 0,
+ 0,0x3027,0x3028, 0, 0, 0,0x3029, 0,
+ 0,0x302A, 0, 0,0x302B,0x302C,0x302D, 0,
+ 0, 0, 0,0x302E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x302F,0x3030,
+ 0, 0,0x3031, 0, 0,0x3032, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3033,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3034, 0,0x3035, 0, 0, 0, 0, 0,
+ 0,0x3036, 0, 0, 0, 0,0x3037,0x3038,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3039,0x303A, 0, 0, 0,0x303B,
+ 0, 0, 0, 0, 0,0x303C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x303D, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x303E,0x303F, 0, 0,
+ 0, 0, 0,0x3040, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3041, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3042,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3043, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3044, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3045,0x3046, 0, 0, 0, 0,0x3047,0x3048,
+0x3049, 0, 0, 0, 0, 0,0x304A, 0,
+ 0, 0, 0, 0, 0,0x304B, 0,0x304C,
+ 0,0x304D, 0,0x304E, 0, 0, 0, 0,
+ 0, 0,0x742F,0x304F,0x3050,0x3051,0x3052, 0,
+0x3053,0x3054, 0, 0, 0, 0,0x3055, 0,
+ 0,0x3056,0x3057, 0, 0, 0, 0, 0,
+0x3058, 0, 0,0x3059,0x305A,0x305B, 0,0x305C
+};
+
+/* page 12 0x4F2E-0x5166 */
+static uint16 tab_uni_jisx021212[]={
+0x305D, 0, 0,0x305E, 0,0x3060, 0,0x3061,
+ 0,0x3062, 0,0x3063, 0,0x3064, 0, 0,
+0x3065, 0,0x3066, 0,0x3067, 0, 0, 0,
+ 0, 0,0x3068,0x3069, 0,0x306A,0x306B, 0,
+ 0, 0, 0, 0,0x306C, 0,0x306D, 0,
+0x306E, 0,0x306F, 0, 0, 0, 0, 0,
+ 0,0x3070,0x305F, 0, 0,0x3071, 0, 0,
+ 0, 0, 0, 0,0x3072, 0,0x3073, 0,
+0x3074, 0, 0,0x3075, 0, 0, 0, 0,
+ 0,0x3076,0x3077,0x3078,0x3079, 0, 0,0x307A,
+0x307B, 0, 0,0x307C,0x307D, 0,0x307E,0x3121,
+ 0, 0, 0,0x3122,0x3123, 0,0x3124, 0,
+0x3125, 0,0x3126, 0,0x3127,0x3128,0x3129, 0,
+ 0,0x312A, 0,0x312B,0x312C, 0, 0, 0,
+0x312D,0x312E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x312F, 0, 0, 0,
+ 0,0x3130, 0,0x3131, 0,0x3132,0x3133,0x3134,
+0x3135, 0,0x3136,0x3137, 0, 0, 0,0x3138,
+0x3139, 0,0x313A,0x313B, 0,0x313C,0x313D,0x313E,
+ 0,0x313F, 0, 0,0x3140, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3141, 0,
+ 0, 0,0x3142, 0,0x3143, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3144, 0,0x3145, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3146,0x3147,
+ 0,0x3148,0x3149,0x314A, 0, 0,0x314B, 0,
+ 0,0x314C, 0, 0,0x314D, 0,0x314E, 0,
+0x314F, 0,0x3150, 0, 0,0x3151, 0, 0,
+ 0,0x3152,0x3153, 0, 0,0x3154,0x3155,0x3156,
+0x3157, 0, 0, 0,0x3158, 0, 0, 0,
+ 0,0x3159, 0, 0, 0, 0, 0, 0,
+0x315A, 0,0x315B, 0,0x315C,0x315D, 0,0x315E,
+ 0, 0, 0, 0, 0,0x3176, 0, 0,
+ 0, 0,0x315F,0x3160,0x3161, 0, 0,0x3162,
+0x3163, 0, 0, 0,0x3164, 0,0x3165, 0,
+0x3166, 0, 0,0x3167,0x3168,0x3169, 0, 0,
+ 0,0x316A, 0,0x316B, 0, 0, 0, 0,
+ 0,0x316C,0x316D, 0,0x316E,0x316F, 0, 0,
+0x3170,0x3171, 0, 0,0x3172, 0, 0,0x3173,
+ 0, 0,0x3174,0x3175, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3177, 0,0x3178,0x3179, 0,
+0x317A, 0, 0, 0,0x317B, 0, 0, 0,
+0x317C,0x317D,0x317E, 0,0x3221,0x3222,0x3223, 0,
+0x3224, 0, 0, 0, 0,0x3225,0x3226, 0,
+0x3227,0x3228,0x3229,0x322A,0x322B, 0, 0, 0,
+ 0, 0, 0, 0,0x322C, 0, 0, 0,
+ 0,0x322D,0x322E, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x322F,0x3230, 0, 0,0x3231,
+ 0, 0,0x3232, 0, 0,0x3233,0x3234, 0,
+ 0,0x3235, 0, 0, 0, 0,0x3236, 0,
+0x3237, 0,0x3238, 0, 0,0x3239,0x323A, 0,
+ 0, 0,0x323B, 0, 0, 0,0x323C,0x323D,
+ 0,0x323E, 0, 0,0x323F, 0,0x3240, 0,
+0x3241, 0,0x3242,0x3243, 0, 0, 0, 0,
+ 0,0x3244, 0,0x3245,0x3251, 0,0x7430, 0,
+0x3246, 0, 0, 0,0x3247, 0, 0, 0,
+0x3248, 0, 0, 0, 0,0x3249, 0, 0,
+0x324A,0x324B,0x324C, 0, 0,0x324D,0x324E,0x324F,
+0x3250, 0,0x3252, 0, 0, 0, 0, 0,
+ 0,0x3253, 0,0x3254, 0,0x3255,0x3256,0x3257,
+0x3258, 0, 0, 0, 0,0x3259, 0, 0,
+ 0,0x325A,0x325B, 0, 0, 0,0x325C,0x325D,
+ 0,0x325E, 0,0x325F, 0,0x3260,0x3261,0x3262,
+ 0, 0,0x3263,0x3264, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3265, 0, 0, 0,
+ 0, 0, 0, 0,0x3266, 0, 0, 0,
+ 0,0x3267, 0, 0, 0,0x3268, 0,0x3269,
+ 0,0x326A,0x326B, 0, 0, 0, 0, 0,
+ 0,0x326C, 0, 0, 0, 0,0x326D, 0,
+0x326E};
+
+/* page 13 0x517E-0x5515 */
+static uint16 tab_uni_jisx021213[]={
+0x326F, 0, 0, 0, 0,0x3270,0x3271, 0,
+ 0, 0, 0, 0, 0,0x3272, 0, 0,
+0x3273, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3274, 0, 0, 0, 0,0x3275,
+ 0, 0, 0,0x3276, 0,0x3277, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3278,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3279, 0,0x327A, 0,0x327B, 0,
+0x327C,0x327D, 0, 0,0x327E, 0, 0, 0,
+ 0, 0,0x3321, 0, 0, 0, 0, 0,
+ 0,0x3322, 0,0x3323,0x3324,0x3325, 0,0x3326,
+ 0, 0,0x3327, 0, 0, 0, 0, 0,
+0x3328, 0, 0, 0,0x3329, 0, 0,0x332A,
+ 0, 0, 0, 0, 0, 0,0x7431, 0,
+0x332B, 0, 0, 0,0x332C,0x332D,0x332E, 0,
+ 0,0x332F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3330,0x3331, 0, 0,0x3332,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3333,0x3334, 0,0x3335,
+0x3336, 0,0x3337, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3338, 0, 0, 0,
+ 0, 0,0x3339, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x333A,0x333B, 0, 0,0x333C,
+ 0, 0, 0, 0, 0, 0,0x333D, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x333E,
+ 0, 0, 0,0x333F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3340,
+ 0,0x3341,0x3342, 0,0x3343, 0,0x3344, 0,
+ 0,0x3345,0x3346,0x3347, 0, 0, 0, 0,
+0x3348, 0, 0, 0, 0, 0, 0, 0,
+0x3349, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x334A,0x334B,0x334C, 0, 0, 0, 0,
+ 0, 0,0x334D, 0,0x334E, 0, 0,0x334F,
+ 0, 0, 0, 0,0x3350, 0,0x3351, 0,
+ 0, 0, 0, 0, 0,0x3352, 0,0x3353,
+0x3354,0x3355,0x3356, 0,0x3357, 0,0x3358, 0,
+ 0, 0, 0, 0, 0, 0,0x3359,0x335A,
+0x335B,0x335C, 0, 0, 0, 0, 0, 0,
+ 0,0x335D,0x335E, 0, 0, 0, 0, 0,
+0x335F,0x3360,0x3361, 0,0x3362,0x3363, 0,0x3364,
+ 0, 0,0x3365, 0, 0, 0,0x3366, 0,
+0x3367, 0,0x3368, 0, 0, 0,0x3369, 0,
+ 0,0x336A, 0,0x336B, 0, 0,0x336C, 0,
+0x336D, 0, 0, 0, 0,0x336E,0x336F, 0,
+ 0, 0, 0,0x3370, 0, 0, 0,0x3371,
+ 0, 0,0x3372,0x3373,0x3374, 0,0x3375, 0,
+ 0, 0,0x3376,0x3377, 0, 0,0x3378, 0,
+0x3379,0x337A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x337B, 0, 0,0x337C, 0, 0,
+ 0,0x7432, 0, 0,0x337D,0x337E,0x3421, 0,
+ 0, 0, 0,0x3422, 0,0x3423, 0, 0,
+ 0, 0,0x3424, 0, 0,0x3425,0x3426, 0,
+0x3427,0x3428, 0, 0, 0, 0,0x7433,0x3429,
+ 0,0x342A,0x342B,0x342C, 0,0x342D,0x342E,0x342F,
+ 0, 0,0x3430, 0,0x3431, 0, 0,0x3432,
+ 0, 0, 0, 0, 0, 0,0x3433,0x3434,
+0x3435, 0, 0, 0,0x3436, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3438,0x3437, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3439, 0,0x343A, 0, 0,
+ 0, 0, 0,0x343B, 0,0x343C, 0,0x343D,
+ 0, 0, 0, 0, 0, 0,0x343E,0x343F,
+ 0, 0, 0, 0,0x3440, 0, 0, 0,
+ 0, 0, 0,0x3441, 0, 0, 0, 0,
+0x3442, 0, 0, 0, 0,0x3443, 0, 0,
+ 0,0x3444,0x3445, 0, 0, 0, 0, 0,
+0x3446, 0, 0, 0, 0,0x3447,0x3448, 0,
+ 0, 0, 0,0x3449, 0, 0, 0,0x344A,
+ 0, 0, 0,0x344B, 0, 0,0x344C, 0,
+ 0, 0, 0, 0,0x344D,0x344E, 0, 0,
+ 0,0x344F, 0, 0,0x3450, 0,0x3451,0x3452,
+ 0,0x3453,0x3454, 0,0x3455, 0, 0,0x3456,
+ 0, 0,0x3457, 0, 0, 0, 0,0x3458,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3459, 0, 0,0x345A,0x345B, 0,0x345C,
+ 0, 0, 0, 0,0x345D, 0, 0,0x345E,
+0x345F, 0,0x3460, 0, 0, 0, 0, 0,
+0x3461,0x3462, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3463,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3464, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3465, 0, 0,
+ 0, 0, 0, 0,0x3466, 0, 0, 0,
+ 0, 0, 0,0x3467, 0, 0, 0, 0,
+ 0,0x3468,0x3469, 0,0x346A, 0, 0, 0,
+ 0,0x346B, 0,0x346C, 0, 0,0x346D,0x346E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x346F,0x3470, 0,
+ 0,0x3471, 0, 0, 0, 0, 0,0x3472,
+ 0,0x3473, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3474, 0, 0, 0,0x3475, 0,0x3476, 0,
+0x3477,0x3478, 0,0x3479, 0,0x347A, 0,0x347B,
+0x347C, 0, 0, 0, 0, 0,0x347D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x347E, 0,0x3521, 0,0x3522, 0,0x3523,
+ 0, 0,0x3524,0x3525,0x7435, 0, 0,0x3526,
+ 0, 0, 0,0x3527, 0, 0, 0,0x3528,
+0x3529, 0, 0, 0, 0, 0,0x352A, 0,
+ 0,0x352B, 0,0x352C, 0, 0, 0, 0,
+0x352D,0x352E, 0,0x352F,0x3530, 0, 0,0x3531,
+0x3532, 0, 0,0x3533, 0, 0, 0, 0,
+ 0,0x3534, 0,0x3535,0x3536,0x3537, 0, 0,
+ 0,0x3538, 0, 0, 0, 0, 0, 0,
+0x3539, 0, 0, 0,0x353A, 0, 0,0x353B,
+0x353C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x353D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x353E, 0,0x353F, 0,
+ 0,0x3540, 0, 0, 0, 0, 0, 0,
+0x3541, 0, 0, 0, 0, 0,0x3542, 0,
+0x3543,0x3544,0x3545,0x3546, 0, 0, 0,0x3547,
+ 0, 0,0x3548,0x3549, 0, 0,0x354A,0x354B,
+0x354C, 0, 0, 0, 0, 0, 0,0x354D
+};
+
+/* page 14 0x552A-0x5566 */
+static uint16 tab_uni_jisx021214[]={
+0x354E,0x354F, 0, 0, 0, 0, 0, 0,
+0x3550, 0, 0,0x3551,0x3552, 0, 0, 0,
+ 0,0x3553,0x3554,0x3555, 0, 0, 0,0x3556,
+ 0, 0, 0, 0, 0,0x3557, 0,0x3558,
+0x3559, 0, 0,0x355A, 0, 0,0x355B,0x355C,
+ 0, 0, 0, 0, 0, 0,0x355D, 0,
+0x355E,0x355F, 0, 0,0x3560, 0,0x3561,0x3562,
+ 0, 0,0x3563, 0,0x3564};
+
+/* page 15 0x557F-0x5C36 */
+static uint16 tab_uni_jisx021215[]={
+0x3565, 0,0x3566,0x3567, 0, 0, 0,0x3568,
+ 0,0x3569, 0, 0, 0, 0, 0,0x356A,
+0x356B, 0,0x356C,0x356D,0x356E,0x356F, 0, 0,
+0x3570, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3571,0x3572, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3573, 0,
+ 0, 0, 0,0x3574, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3575, 0,0x3576, 0,0x3577, 0, 0,0x3578,
+ 0, 0,0x3579, 0,0x357A,0x357B, 0,0x357C,
+ 0, 0,0x357D,0x357E,0x3621, 0, 0, 0,
+0x3622,0x3623, 0, 0,0x3624, 0, 0,0x3625,
+ 0, 0, 0,0x3626, 0, 0, 0, 0,
+ 0, 0,0x3627, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3628,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3629, 0, 0, 0, 0, 0,0x362A, 0,
+ 0,0x362B, 0,0x362C, 0, 0,0x362D,0x362E,
+0x362F,0x3630,0x3631,0x3632, 0, 0, 0, 0,
+ 0, 0,0x3633, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3634, 0, 0,
+ 0,0x3635, 0, 0,0x3636, 0,0x3637, 0,
+0x3638, 0,0x3639, 0,0x363A,0x363B,0x363C, 0,
+0x363D,0x363E,0x363F, 0,0x3640,0x3641, 0,0x3642,
+ 0, 0,0x3643, 0,0x3644, 0,0x3645, 0,
+0x3646, 0, 0, 0, 0,0x3647, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3648,
+ 0,0x3649,0x364A,0x364B,0x364C, 0, 0,0x364D,
+ 0, 0,0x364E, 0, 0, 0,0x364F, 0,
+0x3650, 0,0x3651,0x3652, 0, 0,0x3653, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3654,0x3655, 0,
+ 0,0x3656, 0, 0,0x3657,0x3658, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3659, 0,
+ 0, 0,0x365A,0x365B, 0, 0,0x365C,0x365D,
+0x365E, 0, 0, 0, 0, 0, 0,0x365F,
+0x3660,0x3661,0x3662, 0,0x3663,0x3664,0x3665, 0,
+ 0, 0,0x3666, 0,0x3667, 0, 0, 0,
+0x3668, 0, 0, 0, 0, 0, 0,0x3669,
+ 0, 0, 0, 0, 0, 0,0x366A, 0,
+ 0, 0,0x366B,0x366C,0x366D,0x3670,0x3671, 0,
+0x366E,0x366F, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3672, 0, 0,0x3673,0x3674, 0,
+0x3675, 0,0x3676, 0, 0,0x3677,0x3678,0x3679,
+0x367A,0x367B, 0, 0,0x367D, 0,0x367E, 0,
+ 0, 0,0x367C, 0, 0, 0, 0,0x3721,
+0x3722, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3723,0x3724, 0, 0, 0, 0,
+0x3725, 0, 0,0x3726, 0,0x3727, 0, 0,
+ 0, 0,0x3728, 0, 0, 0,0x3729, 0,
+ 0, 0, 0,0x372A,0x372B, 0,0x372C, 0,
+ 0,0x372D, 0,0x372E,0x372F,0x3730,0x3731, 0,
+ 0, 0,0x3732,0x3733, 0,0x3734, 0,0x3735,
+0x3736, 0, 0, 0,0x3737,0x3738, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3739,0x373A,
+0x373B, 0, 0, 0, 0, 0,0x373C,0x373D,
+ 0, 0, 0, 0, 0,0x373E,0x373F, 0,
+ 0, 0, 0,0x3740, 0, 0, 0, 0,
+ 0, 0,0x7436, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3741, 0, 0,0x3742, 0,
+0x3743,0x3744, 0, 0,0x3745, 0,0x3746,0x3747,
+0x3748,0x3749,0x374A, 0,0x374B,0x374C,0x374D, 0,
+0x374E, 0,0x374F,0x3750,0x3751,0x3752, 0,0x3753,
+ 0, 0,0x3754, 0,0x3755, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3756, 0, 0,
+ 0, 0, 0, 0, 0,0x3757,0x3760, 0,
+0x3758, 0,0x3759,0x375A, 0,0x375B,0x375C,0x375D,
+0x375E, 0,0x375F, 0, 0, 0, 0, 0,
+0x3761,0x3762,0x3763, 0, 0,0x3764, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3765, 0, 0, 0, 0,0x3766, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3767,0x3768, 0, 0, 0,0x3769, 0, 0,
+0x376A, 0, 0, 0, 0, 0,0x376B, 0,
+ 0, 0, 0, 0, 0, 0,0x376C,0x376D,
+ 0, 0,0x377E, 0, 0,0x376E, 0,0x376F,
+0x3770, 0,0x3771, 0, 0, 0,0x3772, 0,
+ 0,0x3773, 0, 0, 0, 0,0x3774,0x3775,
+ 0,0x3776, 0, 0, 0, 0,0x3777,0x3778,
+0x3779, 0, 0, 0,0x377A,0x377B, 0, 0,
+ 0,0x377C,0x377D, 0, 0,0x3821,0x3822, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3823, 0, 0,0x3824,
+0x3825,0x3826, 0, 0, 0, 0, 0,0x3827,
+0x3828, 0, 0, 0, 0, 0,0x3829, 0,
+ 0, 0, 0,0x382A, 0, 0, 0, 0,
+ 0, 0,0x382B, 0, 0, 0, 0, 0,
+0x382C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x382D, 0, 0,0x382E,0x382F, 0,
+0x3830,0x3831, 0, 0, 0, 0,0x3832, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3833, 0,0x3834, 0, 0,0x3835, 0, 0,
+0x3836,0x3837, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3838, 0, 0, 0,0x3839, 0, 0,
+0x383A,0x383B,0x383C, 0, 0, 0, 0, 0,
+0x383D,0x383E,0x383F,0x3840, 0,0x3841,0x3842, 0,
+0x3843,0x3844, 0, 0, 0,0x3845, 0,0x3846,
+ 0, 0, 0, 0, 0, 0,0x3847,0x7439,
+ 0,0x3848,0x3849,0x384A, 0, 0, 0,0x384B,
+ 0, 0,0x384C, 0, 0, 0, 0, 0,
+ 0, 0,0x384D,0x384E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3850, 0, 0,
+ 0, 0, 0,0x3851, 0,0x384F, 0, 0,
+ 0,0x3852, 0, 0, 0, 0,0x3853,0x3854,
+ 0,0x3855, 0,0x3856, 0,0x3857, 0,0x3858,
+ 0, 0, 0,0x3859, 0, 0,0x385A, 0,
+ 0, 0,0x385B,0x385C, 0, 0, 0, 0,
+ 0, 0,0x385D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x385E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x385F,0x3860,
+ 0, 0, 0, 0,0x3861,0x3862, 0, 0,
+ 0, 0, 0,0x3863,0x3864,0x3865, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3867, 0,
+ 0, 0,0x3868, 0,0x3869,0x386A, 0, 0,
+ 0,0x386B, 0, 0, 0, 0, 0, 0,
+0x386C,0x386D, 0, 0,0x386E, 0,0x386F,0x3870,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3871, 0, 0, 0,0x3872, 0, 0,0x3873,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3874,0x3875, 0, 0, 0,
+ 0, 0,0x3876, 0,0x3877, 0,0x3878,0x3879,
+0x387A, 0,0x387B, 0,0x387C, 0, 0, 0,
+ 0, 0, 0, 0,0x387D, 0,0x387E, 0,
+0x3921, 0, 0,0x3922, 0, 0,0x3923,0x3924,
+ 0, 0,0x3925, 0,0x3926,0x3927, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3928,0x3929, 0,0x392A,
+ 0, 0, 0,0x392B, 0, 0,0x392C, 0,
+0x392D, 0, 0, 0, 0, 0, 0, 0,
+0x392E, 0, 0, 0, 0,0x392F, 0, 0,
+0x3930, 0, 0, 0, 0, 0,0x3931,0x3932,
+0x3933,0x3934, 0, 0,0x3935, 0, 0, 0,
+0x3936, 0, 0,0x3937, 0,0x3938, 0, 0,
+ 0, 0,0x3939, 0,0x393A,0x393B, 0, 0,
+ 0,0x393C, 0,0x393D, 0, 0,0x393E, 0,
+ 0, 0, 0,0x393F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3940,0x3941,
+0x3942, 0, 0, 0,0x3943,0x3944, 0, 0,
+0x3945, 0, 0, 0, 0, 0, 0,0x3946,
+0x3947, 0,0x3948,0x3949, 0,0x394A, 0, 0,
+0x394B, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x394C, 0, 0, 0,0x394D, 0, 0,
+ 0, 0, 0, 0, 0,0x394E,0x394F,0x3950,
+ 0, 0, 0,0x3951,0x3952, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3953,
+ 0, 0, 0, 0,0x3954,0x3955, 0, 0,
+0x3956,0x3957, 0,0x3958, 0, 0,0x3959, 0,
+ 0,0x395A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x395B,0x395C, 0,
+0x395D,0x395E, 0, 0, 0,0x395F, 0, 0,
+ 0,0x3960, 0, 0, 0, 0,0x3961, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3962,
+ 0, 0, 0, 0,0x3963, 0,0x3964, 0,
+0x3965, 0, 0, 0, 0, 0,0x3966, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3967, 0, 0,0x3968,0x3969, 0, 0,0x396A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x396B, 0, 0, 0,
+ 0,0x396C, 0, 0,0x396D, 0, 0,0x396E,
+ 0, 0,0x396F, 0, 0,0x3970, 0,0x3971,
+0x3972,0x3973, 0,0x3974, 0, 0, 0, 0,
+0x3975, 0, 0, 0, 0,0x3976, 0, 0,
+ 0, 0,0x3977,0x3978,0x3979, 0,0x397A, 0,
+ 0,0x397B, 0,0x397C,0x397D, 0, 0, 0,
+0x397E, 0, 0, 0, 0,0x3A21, 0,0x3A22,
+ 0,0x3A23, 0, 0, 0, 0, 0, 0,
+0x3A24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3A25, 0,0x3A26, 0, 0,
+ 0,0x3A27, 0, 0, 0, 0,0x3A28, 0,
+ 0, 0, 0,0x3A29, 0, 0, 0,0x3A2A,
+ 0, 0, 0, 0, 0, 0,0x3A2B,0x3A2C,
+ 0, 0, 0, 0, 0, 0,0x3A2D, 0,
+ 0,0x3A2E,0x3A2F, 0, 0, 0, 0, 0,
+ 0,0x3A30, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3A31, 0,0x3A33, 0,0x3A34, 0,0x3A35, 0,
+ 0, 0,0x3A36, 0, 0, 0,0x3A37, 0,
+ 0, 0, 0, 0, 0, 0,0x3A38, 0,
+ 0, 0, 0, 0, 0,0x3A32, 0, 0,
+ 0,0x3A39, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3A3A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3A3B,0x3A3C, 0, 0,
+ 0, 0, 0,0x3A3D, 0, 0, 0,0x3A3E,
+ 0, 0, 0, 0, 0, 0, 0,0x3A3F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3A40, 0, 0, 0, 0, 0,0x3A41,
+0x3A42, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3A43,0x3A44,0x3A45,
+0x3A46, 0,0x3A47, 0, 0,0x3A48, 0,0x3A49,
+ 0, 0, 0,0x3A4A, 0, 0, 0,0x3A4B,
+ 0,0x3A4C,0x3A4D, 0,0x3A4E,0x3A4F, 0,0x3A50,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3A51,0x3A52, 0, 0,0x3A53,0x3A54, 0,
+0x3A55, 0,0x3A56,0x3A57, 0, 0, 0, 0,
+0x3A58, 0, 0,0x3A59, 0,0x3A5A, 0, 0,
+ 0,0x3A5B,0x3A5C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3A5D, 0,
+0x3A5E, 0, 0, 0, 0, 0, 0,0x3A5F,
+0x3A60,0x3A61,0x3A62,0x3A63, 0, 0, 0, 0,
+ 0,0x3A64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x743A, 0, 0,
+0x3A65, 0,0x3A66, 0, 0,0x3A67, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3A68, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3A69, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3A6A, 0, 0, 0, 0, 0, 0,0x3A6B,
+0x3A6C, 0, 0, 0,0x3A6D, 0, 0,0x3A6E,
+ 0, 0,0x3A6F, 0,0x3A70,0x3A71, 0,0x3A72,
+ 0,0x3A73, 0,0x3A74, 0, 0,0x3A75,0x3A76
+};
+
+/* page 16 0x5C59-0x5EEB */
+static uint16 tab_uni_jisx021216[]={
+0x3A77,0x3A78, 0,0x3A79, 0, 0, 0, 0,
+ 0,0x3A7A,0x3A7B, 0, 0, 0,0x3A7C,0x3A7D,
+0x3A7E, 0, 0, 0,0x3B21, 0, 0,0x3B22,
+ 0, 0, 0,0x3B23,0x3B24, 0, 0, 0,
+ 0,0x3B25,0x3B26,0x3B27,0x3B28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3B29,0x3B2A,
+ 0,0x3B2B, 0, 0, 0, 0,0x3B2C, 0,
+ 0,0x3B2D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3B2E, 0,0x3B2F,0x3B30,
+ 0,0x3B31,0x3B32, 0, 0,0x3B33, 0, 0,
+ 0,0x3B34, 0, 0, 0, 0, 0, 0,
+ 0,0x3B35, 0,0x3B36,0x3B37, 0, 0, 0,
+ 0,0x3B38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3B39, 0,0x3B3A, 0, 0, 0, 0, 0,
+ 0,0x3B3B, 0, 0, 0, 0,0x3B3D, 0,
+ 0, 0, 0, 0,0x3B3C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3B3E, 0, 0,
+0x3B3F,0x3B40, 0,0x3B41,0x743B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3B42, 0, 0, 0, 0,0x3B43, 0, 0,
+ 0, 0, 0, 0,0x3B44, 0, 0, 0,
+ 0,0x3B45, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3B47,0x3B48, 0,0x3B49,0x3B4A, 0,
+ 0, 0,0x3B46, 0, 0, 0, 0, 0,
+0x3B4B, 0, 0,0x3B4C, 0, 0, 0, 0,
+0x3B4D, 0, 0, 0,0x3B4E, 0,0x3B4F, 0,
+ 0,0x3B50,0x3B51, 0, 0,0x3B52, 0,0x3B53,
+ 0,0x3B57, 0, 0, 0, 0, 0, 0,
+0x3B55, 0,0x743C, 0,0x3B54, 0, 0, 0,
+0x3B56, 0, 0, 0, 0, 0,0x3B58,0x3B59,
+0x3B5A,0x3B5B, 0,0x3B5C, 0, 0, 0, 0,
+ 0,0x3B5D, 0, 0,0x3B5E, 0, 0,0x3B5F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3B60,0x3B61, 0, 0, 0,0x3B62,0x3B63, 0,
+0x3B64, 0,0x3B65, 0, 0, 0, 0,0x3B66,
+ 0,0x3B67, 0, 0, 0, 0, 0, 0,
+ 0,0x3B68,0x3B69,0x3B6A,0x3B6B, 0, 0, 0,
+0x3B6C, 0,0x3B6D, 0, 0, 0,0x3B6E,0x3B6F,
+ 0, 0, 0, 0, 0, 0,0x3B70, 0,
+ 0, 0,0x3B71, 0, 0, 0, 0,0x3B72,
+ 0,0x6674, 0,0x3B73, 0, 0, 0,0x3B74,
+0x3B75, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3B76, 0, 0, 0,0x3B77, 0,
+ 0, 0,0x3B78, 0, 0,0x3B7A, 0,0x3B79,
+ 0, 0, 0, 0, 0, 0, 0,0x3B7B,
+0x3B7C, 0, 0, 0, 0, 0, 0,0x3B7D,
+ 0, 0, 0,0x3B7E, 0, 0, 0, 0,
+0x3C21, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C22,
+0x3C23, 0, 0, 0, 0, 0, 0,0x3C24,
+ 0, 0, 0, 0, 0, 0,0x3C25, 0,
+ 0, 0, 0, 0,0x3C26, 0, 0, 0,
+ 0,0x3C27, 0,0x3C28,0x3C29, 0, 0,0x3C2A,
+ 0, 0, 0, 0, 0, 0,0x3C2B,0x3C2C,
+ 0, 0, 0, 0, 0, 0, 0,0x3C2E,
+ 0, 0, 0, 0, 0,0x3C2D, 0, 0,
+ 0,0x3C2F, 0, 0,0x3C30, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3C31, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3C34, 0,0x3C32, 0, 0, 0, 0,0x3C33,
+0x3C35, 0, 0, 0, 0,0x3C36, 0,0x3C37,
+ 0, 0,0x3C38,0x3C39, 0,0x3C3A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C3B,
+ 0,0x3C3C,0x3C3D,0x3C3E,0x3C3F,0x3C40, 0,0x3C41,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C42,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3C43, 0, 0,0x3C44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3C45, 0,0x3C46,0x3C47, 0, 0,0x3C48,
+ 0,0x3C49, 0,0x3C4A, 0, 0, 0, 0,
+0x3C4B, 0,0x3C4C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3C4D,0x3C4E,0x3C4F, 0,
+ 0, 0, 0, 0, 0,0x3C50, 0, 0,
+ 0, 0,0x3C52,0x3C51, 0,0x3C53, 0, 0,
+0x3C54,0x3C55, 0,0x3C56,0x3C57, 0, 0, 0,
+ 0, 0, 0,0x3C58, 0,0x3C59, 0, 0,
+ 0, 0, 0, 0,0x3C5A, 0, 0, 0,
+ 0, 0,0x3C5B};
+
+/* page 17 0x5F02-0x6149 */
+static uint16 tab_uni_jisx021217[]={
+0x3C5C, 0, 0, 0,0x3C5D,0x3C5E,0x3C5F, 0,
+ 0, 0, 0, 0,0x3C60, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C61,
+ 0, 0,0x3C62,0x3C63, 0, 0, 0,0x3C64,
+0x3C65,0x3C66,0x3C67, 0, 0, 0,0x3C68, 0,
+ 0,0x3C69,0x3C6A, 0,0x3C6B, 0,0x3C6C, 0,
+ 0, 0,0x3C6D, 0,0x3C6E, 0, 0, 0,
+ 0,0x3C6F, 0,0x3C70, 0,0x3C71,0x3C72, 0,
+ 0, 0,0x3C73,0x3C74, 0,0x3C75, 0, 0,
+ 0, 0, 0,0x3C76, 0, 0,0x3C77, 0,
+ 0, 0,0x3C78, 0, 0, 0,0x3C79, 0,
+ 0,0x3C7A, 0, 0, 0, 0,0x3C7B, 0,
+ 0,0x3C7C,0x3C7D, 0, 0,0x3C7E, 0, 0,
+ 0, 0, 0, 0, 0,0x3D21, 0, 0,
+0x3D22, 0,0x3D23,0x3D24, 0, 0,0x3D25, 0,
+0x3D26, 0, 0,0x3D27,0x3D28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3D29,
+ 0, 0, 0,0x3D2A, 0,0x3D2B, 0, 0,
+ 0, 0, 0, 0,0x3D2C, 0, 0, 0,
+ 0, 0,0x3D2D,0x3D2E, 0, 0, 0, 0,
+0x3D2F, 0,0x3D32, 0, 0,0x3D30, 0, 0,
+ 0,0x3D31,0x3D33, 0, 0,0x3D34,0x3D35,0x3D36,
+ 0, 0, 0, 0, 0,0x743E,0x3D37, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3D38, 0, 0,0x3D39,0x3D3A,0x3D3B,
+ 0,0x3D3C, 0, 0, 0, 0,0x3D3D,0x3D3E,
+0x3D3F,0x3D40,0x3D41, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3D42, 0, 0,0x3D43,
+0x3D44, 0, 0, 0, 0, 0,0x3D45,0x3D46,
+0x3D47, 0,0x3D48,0x3D49,0x3D4A,0x3D4B, 0, 0,
+0x3D4C,0x3D4D, 0, 0,0x3D4E, 0, 0, 0,
+0x3D4F, 0,0x3D50, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3D51, 0, 0,
+0x3D52, 0, 0,0x3D53, 0, 0, 0, 0,
+ 0,0x3D54,0x3D55, 0, 0,0x3D56,0x3D57, 0,
+0x3D58, 0, 0, 0, 0,0x3D59, 0, 0,
+ 0, 0,0x3D5A, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3D5B, 0, 0, 0, 0,
+ 0,0x3D5C, 0,0x3D5D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3D5E, 0,
+ 0, 0, 0, 0, 0,0x3D5F,0x3D60,0x3D61,
+ 0, 0,0x3D62, 0, 0, 0, 0,0x3D63,
+ 0, 0,0x3D64, 0,0x3D65,0x3D66, 0, 0,
+ 0, 0, 0,0x3D67, 0, 0, 0,0x3D68,
+ 0, 0, 0, 0, 0,0x3D69, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3D6A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3D6B,0x3D6C, 0, 0,
+0x3D6D, 0, 0,0x743F,0x3D6E, 0,0x3D6F, 0,
+0x3D70, 0, 0, 0,0x3D71, 0, 0,0x3D72,
+ 0,0x3D73, 0,0x3D74, 0, 0,0x3D75, 0,
+ 0, 0, 0,0x3D76,0x3D77, 0, 0, 0,
+0x3D78, 0,0x3D79,0x3D7A, 0, 0,0x3D7B, 0,
+ 0, 0, 0, 0, 0, 0,0x3D7C,0x3D7D,
+ 0, 0, 0, 0, 0,0x3D7E, 0, 0,
+ 0,0x3E21, 0, 0,0x3E22, 0, 0, 0,
+0x3E23, 0,0x3E24, 0, 0, 0,0x3E25,0x3E26,
+0x3E27,0x3E28, 0, 0,0x3E29,0x3E2A, 0, 0,
+ 0, 0,0x3E2B,0x3E2C, 0, 0, 0,0x3E2D,
+ 0,0x3E2E, 0,0x3E2F,0x3E30, 0, 0, 0,
+0x3E31, 0, 0,0x3E32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3E33, 0, 0,0x3E34, 0, 0,0x3E35, 0,
+ 0, 0,0x3E36,0x3E37, 0, 0, 0, 0,
+0x3E38, 0, 0, 0, 0,0x3E39, 0, 0,
+0x3E3A, 0,0x3E3B, 0, 0, 0,0x3E3C,0x3E3D,
+0x3E3E,0x3E3F,0x3E40, 0,0x3E41,0x3E42, 0,0x3E43,
+ 0, 0,0x3E44, 0,0x3E45, 0,0x7440, 0,
+0x3E46, 0, 0, 0, 0, 0, 0, 0,
+0x3E47,0x3E48, 0, 0, 0, 0,0x3E49,0x3E4A,
+ 0, 0, 0,0x3E4B,0x3E4C,0x3E4D, 0,0x3E4E,
+ 0, 0, 0, 0, 0, 0, 0,0x3E4F,
+ 0, 0, 0,0x3E50,0x3E51, 0, 0,0x3E52
+};
+
+/* page 18 0x615E-0x6290 */
+static uint16 tab_uni_jisx021218[]={
+0x3E53, 0,0x3E54, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3E55, 0,
+ 0, 0, 0, 0,0x3E56, 0, 0, 0,
+ 0, 0,0x3E57, 0, 0,0x3E58,0x3E59, 0,
+ 0,0x3E5A,0x3E5B,0x3E5C, 0,0x3E5D,0x3E5E, 0,
+ 0, 0, 0, 0, 0,0x3E5F, 0,0x3E60,
+ 0, 0, 0, 0,0x3E61,0x3E62, 0, 0,
+ 0,0x3E63,0x3E64, 0, 0, 0,0x3E65,0x3E66,
+ 0,0x3E67,0x3E68, 0, 0, 0, 0,0x3E69,
+ 0, 0,0x3E6A, 0,0x3E6B, 0, 0,0x3E6C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3E6D,0x3E6E, 0, 0,0x3E6F, 0,
+ 0, 0,0x3E70,0x3E71,0x3E72, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3E73,0x3E74, 0, 0, 0, 0, 0,0x3E75,
+ 0, 0, 0, 0, 0, 0,0x3E76,0x3E77,
+0x3E78,0x3E79, 0,0x3E7A,0x3E7B, 0, 0,0x3E7E,
+ 0,0x3E7C, 0,0x3E7D, 0, 0,0x3F21,0x3F22,
+ 0,0x3F23, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3F24, 0,0x3F25,0x3F26, 0,
+ 0,0x3F27, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3F28, 0,0x3F29,
+ 0, 0, 0, 0, 0, 0,0x3F2A, 0,
+ 0, 0,0x3F2B, 0,0x3F2C,0x3F2D, 0, 0,
+ 0,0x3F2E, 0,0x3F2F, 0,0x3F30, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3F31, 0, 0, 0,0x3F32,
+ 0, 0, 0, 0,0x3F33,0x3F34,0x3F35, 0,
+0x3F36, 0, 0, 0, 0, 0,0x3F37, 0,
+ 0, 0,0x3F38,0x3F39,0x3F3A, 0,0x3F3B, 0,
+0x3F3C, 0, 0, 0,0x3F3D, 0,0x3F3E, 0,
+ 0, 0, 0, 0, 0, 0,0x3F3F, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3F40,
+ 0,0x3F41, 0, 0, 0,0x3F42, 0, 0,
+ 0, 0, 0, 0,0x3F43, 0, 0,0x3F44,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3F45,
+0x3F46,0x3F47,0x3F48};
+
+/* page 19 0x62A6-0x679B */
+static uint16 tab_uni_jisx021219[]={
+0x3F49, 0,0x3F4A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3F4B, 0, 0,
+0x3F4C,0x3F4D, 0, 0,0x3F4E, 0, 0, 0,
+0x3F4F,0x3F50, 0, 0, 0, 0,0x3F51, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x3F52, 0, 0, 0, 0, 0, 0,0x3F53,
+0x3F54, 0, 0, 0,0x3F55, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x3F56, 0, 0, 0,
+ 0, 0, 0, 0,0x3F57, 0,0x3F58, 0,
+ 0, 0, 0, 0, 0, 0,0x3F59,0x3F5A,
+ 0, 0, 0, 0, 0,0x3F5B,0x3F5C, 0,
+ 0, 0, 0, 0,0x3F5D,0x3F5E, 0,0x3F5F,
+ 0, 0,0x3F60, 0, 0,0x3F61, 0, 0,
+0x3F62, 0,0x3F63, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x3F64,0x3F65, 0, 0,0x3F66,
+ 0, 0, 0, 0, 0, 0, 0,0x3F67,
+0x3F68, 0, 0,0x3F69, 0, 0,0x3F6A, 0,
+ 0, 0, 0,0x3F6B,0x3F6C,0x3F6D,0x3F6E, 0,
+0x3F6F, 0, 0, 0,0x3F70,0x3F71, 0, 0,
+0x3F72, 0, 0, 0,0x3F73,0x3F74,0x3F75, 0,
+ 0, 0,0x3F76, 0, 0,0x3F77, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3F78,
+0x3F79, 0, 0, 0, 0, 0,0x3F7A,0x3F7B,
+ 0, 0, 0,0x3F7C, 0, 0,0x3F7D,0x3F7E,
+ 0, 0,0x4021, 0, 0, 0,0x4022,0x4023,
+ 0,0x4024, 0, 0,0x4025, 0,0x4026, 0,
+ 0,0x4027, 0, 0,0x4028, 0, 0, 0,
+ 0, 0,0x4029, 0, 0, 0,0x402A,0x402B,
+ 0, 0, 0,0x402C,0x402D, 0, 0, 0,
+0x402E, 0, 0, 0, 0, 0,0x402F, 0,
+0x4030, 0, 0, 0, 0, 0, 0,0x4031,
+0x4032,0x4033, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4034,
+ 0, 0, 0,0x4035, 0, 0, 0,0x4036,
+ 0, 0,0x4037, 0, 0, 0, 0, 0,
+0x4038, 0, 0,0x4039, 0,0x403A,0x403B,0x403C,
+ 0, 0, 0, 0, 0, 0,0x403D, 0,
+ 0, 0,0x403E, 0, 0, 0, 0,0x403F,
+ 0, 0, 0, 0,0x4040, 0,0x4041, 0,
+ 0, 0, 0, 0,0x4042,0x4043, 0,0x4044,
+ 0, 0,0x4045,0x4046, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4047,0x4048, 0, 0, 0,
+ 0, 0,0x4049, 0,0x404A, 0,0x404B, 0,
+ 0, 0,0x404C, 0, 0, 0, 0, 0,
+0x404D, 0,0x404E, 0,0x404F, 0,0x4050,0x4051,
+ 0, 0, 0,0x4052,0x4053, 0, 0, 0,
+ 0,0x4054,0x4055, 0, 0, 0, 0,0x4056,
+ 0, 0, 0, 0, 0, 0, 0,0x4057,
+ 0,0x4058, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4059, 0, 0,
+ 0,0x405A, 0,0x405B,0x405C,0x405D,0x405E, 0,
+ 0, 0, 0, 0,0x405F,0x4060,0x4061,0x4062,
+ 0,0x4063,0x4064,0x4065, 0,0x4066, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4067,
+ 0, 0, 0, 0, 0,0x4068,0x4069, 0,
+ 0, 0, 0, 0, 0,0x406A, 0,0x406B,
+ 0, 0, 0, 0, 0, 0, 0,0x406C,
+ 0,0x406D, 0, 0, 0, 0, 0, 0,
+ 0,0x406E,0x406F,0x4070, 0, 0, 0, 0,
+ 0, 0,0x4071,0x4072, 0,0x4073, 0,0x4074,
+ 0,0x4075, 0,0x4076, 0,0x4077, 0, 0,
+0x4078, 0,0x4079, 0, 0, 0,0x407A, 0,
+ 0, 0, 0, 0, 0,0x407B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x407C,
+0x407D,0x407E, 0, 0, 0, 0,0x4121, 0,
+ 0, 0, 0,0x4122,0x4123,0x4124,0x4125, 0,
+0x4126, 0,0x4127,0x4128, 0, 0, 0,0x4129,
+ 0,0x412A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x412B,0x412C,
+ 0, 0, 0,0x412D,0x412E, 0, 0,0x412F,
+ 0, 0,0x4130, 0, 0, 0, 0,0x4131,
+ 0,0x4132, 0, 0, 0,0x4133, 0, 0,
+ 0,0x4134, 0,0x4135, 0, 0,0x4136, 0,
+ 0, 0,0x4137,0x4138,0x4139, 0, 0, 0,
+ 0,0x413A, 0, 0, 0,0x413B,0x413C, 0,
+0x413D, 0, 0,0x413E, 0,0x413F, 0, 0,
+0x4140,0x4141, 0, 0,0x4142, 0, 0, 0,
+0x4143, 0, 0,0x4144, 0, 0, 0, 0,
+0x4145, 0, 0,0x4146, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4147, 0,0x4148,0x4149,
+ 0, 0, 0, 0, 0,0x414A, 0, 0,
+ 0,0x414B, 0,0x414C, 0, 0, 0, 0,
+0x7441, 0,0x414D, 0,0x414E, 0,0x414F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4150,0x4151, 0, 0, 0, 0, 0,
+ 0,0x4152, 0, 0, 0,0x4153, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4154, 0, 0,0x4155,
+ 0, 0, 0,0x4156, 0, 0, 0,0x4157,
+ 0, 0, 0, 0,0x4158, 0, 0, 0,
+ 0, 0, 0, 0,0x4159, 0, 0,0x415A,
+ 0, 0,0x415B, 0, 0, 0, 0,0x415C,
+ 0, 0,0x415D, 0, 0,0x415E, 0, 0,
+0x415F, 0, 0, 0, 0, 0, 0, 0,
+0x4160, 0, 0, 0,0x4161,0x4162,0x4163, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4164, 0, 0,0x4165, 0, 0, 0,
+ 0, 0,0x4166,0x4167, 0, 0, 0, 0,
+0x4168, 0,0x4169, 0, 0, 0,0x416A, 0,
+0x416B, 0,0x416C, 0, 0, 0, 0, 0,
+ 0,0x416D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x416E, 0,0x416F, 0,0x4170,0x4171,
+ 0, 0, 0,0x4172, 0, 0, 0, 0,
+0x4173,0x4174,0x4175, 0, 0, 0,0x4176, 0,
+ 0, 0,0x4177,0x4178, 0, 0, 0,0x4179,
+ 0, 0, 0,0x417A,0x417B, 0, 0,0x417C,
+0x417D, 0, 0, 0, 0, 0, 0,0x417E,
+0x4221, 0, 0,0x4222,0x4223,0x4224,0x4225, 0,
+0x4226, 0, 0,0x4227,0x4228,0x4229,0x422A, 0,
+0x422B, 0,0x422C,0x422D, 0,0x422E, 0, 0,
+ 0,0x4230, 0,0x422F, 0,0x7442, 0, 0,
+ 0, 0,0x4231, 0, 0, 0, 0,0x4232,
+0x4233, 0, 0, 0,0x4234, 0,0x4235, 0,
+0x4237, 0, 0,0x4236, 0, 0, 0, 0,
+ 0,0x4238,0x4239,0x423A, 0,0x423B,0x423C, 0,
+ 0, 0,0x423D,0x423E, 0, 0, 0,0x7443,
+ 0, 0, 0, 0,0x4240,0x4241,0x4242, 0,
+ 0, 0, 0, 0, 0,0x4244, 0,0x4245,
+ 0,0x4247,0x4248,0x4249, 0,0x424A,0x424C, 0,
+0x4243,0x4246,0x424B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x424D,0x424E,0x424F,
+ 0, 0,0x4250, 0,0x4251, 0, 0, 0,
+ 0, 0, 0,0x4252,0x4253,0x4254,0x4255, 0,
+ 0,0x4256,0x4257, 0, 0, 0,0x4258, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4259,
+ 0, 0, 0,0x425A,0x425B, 0, 0,0x425C,
+ 0, 0, 0, 0, 0,0x425D, 0, 0,
+ 0,0x425E,0x425F, 0,0x4260,0x4261, 0, 0,
+ 0, 0,0x4262, 0, 0, 0,0x4263, 0,
+0x4264,0x4265, 0, 0, 0, 0,0x4266, 0,
+ 0, 0, 0, 0, 0,0x4267, 0, 0,
+ 0,0x4268, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4269, 0, 0,0x426A,0x426B, 0,
+0x426C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x426D,0x423F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x426E,
+ 0,0x426F, 0, 0, 0, 0, 0, 0,
+0x4270, 0, 0, 0, 0,0x4271, 0, 0,
+ 0, 0, 0,0x4272, 0, 0,0x4273, 0,
+ 0, 0,0x4274, 0,0x4275, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4276, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4277, 0, 0, 0, 0, 0, 0,0x4278,
+ 0,0x4279,0x427A, 0, 0, 0,0x427B, 0,
+ 0, 0, 0, 0, 0, 0,0x427C,0x427D,
+ 0, 0, 0, 0, 0, 0, 0,0x427E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4321, 0, 0, 0, 0, 0,0x4322, 0,
+0x4323, 0, 0, 0, 0, 0,0x4324, 0,
+0x4325, 0, 0, 0, 0,0x4326, 0, 0,
+ 0, 0, 0,0x4327, 0, 0,0x4328, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4329,0x432A, 0,0x432B, 0,0x432C, 0, 0,
+0x432D, 0,0x432E,0x432F, 0,0x4330};
+
+/* page 20 0x67B0-0x6801 */
+static uint16 tab_uni_jisx021220[]={
+0x4331,0x4332,0x4333, 0, 0,0x4334, 0, 0,
+ 0, 0, 0,0x4335,0x4336,0x4337, 0, 0,
+0x4339, 0,0x433A,0x433B, 0,0x433C, 0, 0,
+0x433D,0x433E, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x433F, 0, 0, 0, 0,0x4340,
+ 0,0x4341, 0, 0,0x4342, 0, 0, 0,
+ 0,0x4343, 0, 0, 0, 0,0x4344, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4345, 0,0x4346, 0, 0, 0,0x4347,0x4348,
+ 0,0x4338, 0, 0, 0, 0, 0, 0,
+ 0,0x7446};
+
+/* page 21 0x6814-0x6917 */
+static uint16 tab_uni_jisx021221[]={
+0x434A, 0, 0, 0, 0,0x434B, 0, 0,
+ 0,0x434C, 0,0x434D, 0, 0, 0, 0,
+ 0, 0, 0,0x434F,0x434E, 0, 0, 0,
+0x4350,0x4351, 0,0x4352,0x4353,0x4354, 0,0x4355,
+ 0, 0, 0, 0, 0, 0, 0,0x4356,
+ 0, 0, 0,0x4357, 0, 0, 0, 0,
+0x4358,0x4359, 0, 0, 0, 0,0x435A, 0,
+0x435B, 0, 0, 0, 0, 0,0x4349, 0,
+ 0,0x435C, 0,0x435D,0x435E, 0, 0,0x435F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4360,
+ 0, 0,0x4361,0x4362,0x4363,0x4364,0x4365, 0,
+ 0,0x4366, 0, 0, 0,0x4367,0x4368,0x4369,
+0x436A, 0, 0, 0, 0, 0,0x436B, 0,
+0x436C, 0,0x436D, 0,0x436E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x436F, 0,0x4370, 0,0x4371, 0,
+0x4372, 0, 0, 0, 0,0x4373, 0,0x4374,
+ 0,0x4375, 0, 0, 0,0x4376,0x4377, 0,
+ 0, 0,0x4378, 0, 0, 0,0x4379, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x437A,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x437B, 0, 0,0x437C, 0, 0, 0,
+0x437D, 0, 0,0x437E,0x4421,0x4422, 0,0x4423,
+ 0, 0,0x4424, 0, 0,0x4425, 0, 0,
+0x4426,0x4427, 0, 0, 0, 0, 0, 0,
+ 0,0x4428, 0, 0,0x4429, 0,0x442A,0x442B,
+0x442C,0x442D, 0, 0,0x442E,0x442F, 0, 0,
+ 0,0x4430,0x4431, 0, 0, 0, 0,0x4432,
+0x4433,0x4434, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4435, 0, 0,0x4436,0x4437, 0,
+ 0, 0, 0, 0,0x4438,0x4439, 0,0x443A,
+ 0, 0,0x443B,0x443C};
+
+/* page 22 0x6931-0x6D3F */
+static uint16 tab_uni_jisx021222[]={
+0x443D, 0,0x443E, 0,0x443F, 0, 0,0x4440,
+ 0, 0,0x4441, 0, 0, 0, 0, 0,
+ 0,0x4442, 0, 0,0x4443, 0, 0, 0,
+0x4444, 0, 0, 0, 0,0x4445, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4446, 0,
+ 0, 0,0x4447, 0, 0, 0, 0, 0,
+ 0, 0,0x4448,0x4449,0x444A,0x444B, 0,0x444C,
+0x444D, 0, 0,0x444E, 0, 0, 0,0x444F,
+0x4450,0x4451, 0, 0, 0, 0, 0, 0,
+ 0,0x4452,0x4453, 0, 0, 0,0x4454,0x4455,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4456, 0, 0, 0,
+ 0,0x4457, 0, 0, 0,0x4458, 0,0x4459,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x445A, 0, 0, 0,0x445B,0x445C, 0,0x445D,
+ 0, 0,0x445E, 0,0x445F, 0,0x4460, 0,
+ 0, 0, 0, 0, 0, 0,0x4461,0x4462,
+ 0,0x4463, 0,0x4464, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4465, 0, 0,0x4466,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4467, 0, 0, 0, 0,0x4468,0x4469, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x446A, 0, 0,0x446B, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x446C,0x446D, 0,
+0x446E, 0,0x446F, 0,0x4470, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4471, 0,0x4472,
+0x4473, 0,0x4474, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4475, 0,
+0x4476, 0, 0, 0,0x4477, 0, 0, 0,
+ 0,0x4478, 0, 0,0x4479, 0, 0,0x447A,
+ 0, 0, 0,0x447B, 0, 0, 0,0x447C,
+ 0, 0, 0, 0, 0, 0, 0,0x447D,
+ 0,0x447E, 0,0x4521, 0, 0,0x4522, 0,
+ 0, 0,0x4523, 0, 0,0x4524,0x4525, 0,
+ 0, 0, 0, 0,0x4526,0x4527, 0, 0,
+0x4528,0x4529, 0, 0, 0,0x452A, 0,0x452B,
+0x452C,0x452D, 0, 0,0x452E,0x452F, 0, 0,
+ 0, 0,0x4530, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4531, 0, 0,0x4532, 0,
+ 0,0x4533,0x7449, 0, 0, 0, 0, 0,
+0x4534, 0,0x4535, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4536, 0, 0,
+0x4537, 0,0x4538, 0, 0,0x4539,0x453A, 0,
+0x453B, 0,0x453C, 0, 0, 0, 0, 0,
+0x453D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x453E, 0,0x453F,0x4540,0x4541, 0,
+ 0, 0, 0, 0,0x4542, 0, 0, 0,
+ 0, 0,0x4543, 0, 0, 0,0x4544,0x4545,
+0x4546, 0, 0,0x4547, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4548,0x4549,0x454A, 0,
+ 0, 0, 0, 0, 0,0x454B, 0,0x454D,
+0x454C, 0, 0,0x454E, 0, 0, 0,0x454F,
+ 0, 0, 0,0x4550,0x4551,0x4552, 0, 0,
+ 0, 0, 0,0x4553,0x4554, 0, 0, 0,
+ 0,0x744A, 0,0x4555, 0, 0,0x4556, 0,
+ 0, 0, 0,0x4557, 0, 0, 0,0x4558,
+0x4559,0x455A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x455B,0x455C, 0, 0, 0,
+ 0,0x455D,0x455E, 0, 0,0x455F,0x4560, 0,
+0x4561, 0, 0, 0, 0, 0,0x4562,0x4563,
+0x4564, 0, 0, 0, 0, 0,0x4565, 0,
+ 0, 0,0x4566, 0, 0,0x4567, 0, 0,
+ 0, 0, 0,0x4568, 0, 0, 0,0x4569,
+ 0, 0,0x456A,0x456B, 0, 0,0x456C, 0,
+ 0, 0, 0, 0,0x456D,0x456E, 0, 0,
+ 0, 0,0x456F, 0, 0, 0,0x4570, 0,
+ 0, 0, 0, 0, 0,0x4571, 0, 0,
+ 0,0x4572, 0, 0,0x4573, 0, 0, 0,
+ 0,0x4574, 0, 0, 0,0x4575, 0,0x4576,
+ 0, 0, 0, 0,0x4577, 0, 0,0x4578,
+ 0, 0, 0, 0, 0, 0,0x4579, 0,
+ 0, 0,0x457A, 0, 0,0x457B, 0,0x457C,
+ 0, 0, 0, 0,0x457D, 0, 0, 0,
+ 0, 0, 0, 0,0x457E,0x4621, 0, 0,
+ 0,0x4622, 0, 0,0x4623, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4624, 0,
+ 0, 0,0x4625, 0, 0, 0,0x4626,0x4627,
+ 0,0x4628,0x4629, 0, 0, 0, 0,0x462A,
+0x462B, 0, 0,0x462C,0x462D,0x462E, 0,0x462F,
+ 0, 0, 0, 0, 0, 0, 0,0x4630,
+0x4631, 0, 0, 0,0x4632,0x4633, 0, 0,
+ 0, 0,0x4634,0x4635, 0, 0, 0, 0,
+0x4636, 0, 0,0x4637, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4638, 0, 0,
+ 0,0x4639, 0, 0, 0, 0, 0, 0,
+0x463A, 0,0x463B, 0, 0,0x463C,0x463D, 0,
+ 0, 0, 0, 0, 0,0x463E, 0, 0,
+0x463F, 0, 0, 0, 0, 0,0x4640, 0,
+0x4641, 0, 0, 0, 0, 0,0x4642, 0,
+ 0,0x4643, 0,0x4644,0x4645, 0, 0, 0,
+0x4646, 0, 0, 0,0x4647,0x4648, 0,0x4649,
+ 0,0x464A, 0, 0, 0, 0, 0, 0,
+0x464B, 0, 0, 0, 0, 0,0x464C, 0,
+ 0, 0, 0, 0, 0,0x464D,0x464E,0x464F,
+ 0, 0, 0,0x4650, 0,0x4651, 0, 0,
+ 0, 0,0x4652, 0,0x4653,0x4654, 0, 0,
+ 0,0x4655,0x4656, 0, 0, 0,0x4657, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4658,0x4659, 0,0x465A, 0,0x465B, 0,
+ 0,0x465C, 0,0x465D, 0, 0, 0, 0,
+0x465E, 0,0x465F,0x4660, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4736, 0,
+ 0, 0,0x4661, 0,0x4662, 0,0x4663, 0,
+ 0, 0, 0,0x4664, 0,0x4665, 0,0x4666,
+0x4667, 0,0x4668, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4669,0x466A,0x466B, 0,
+0x466C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x466D,0x466E, 0,0x466F,0x4670,
+ 0, 0, 0,0x4671, 0, 0,0x4672, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4673,
+ 0,0x4674, 0,0x4675, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4676, 0, 0, 0,0x4677, 0, 0,
+ 0, 0, 0, 0,0x4678, 0,0x4679,0x467A,
+0x467B,0x467C, 0,0x467D, 0,0x467E, 0, 0,
+ 0,0x4721, 0,0x4722, 0, 0, 0,0x4723,
+ 0, 0, 0, 0, 0, 0,0x4724, 0,
+0x4725, 0,0x4726,0x4727, 0,0x4728, 0, 0,
+ 0,0x4729, 0,0x472A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x472B, 0, 0,0x472C, 0,
+ 0,0x472D, 0, 0, 0,0x472E,0x472F, 0,
+0x4730, 0,0x4731, 0, 0, 0, 0, 0,
+ 0,0x4732, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4733,0x4734,0x4735,
+ 0, 0, 0, 0, 0,0x4737,0x4738, 0,
+0x4739, 0, 0, 0, 0, 0, 0, 0,
+0x473A, 0, 0,0x473B, 0, 0,0x473C};
+
+/* page 23 0x6D57-0x6E04 */
+static uint16 tab_uni_jisx021223[]={
+0x473D, 0, 0, 0, 0, 0, 0,0x473E,
+0x473F, 0,0x4740, 0, 0, 0,0x4741, 0,
+0x4742, 0, 0, 0, 0, 0, 0, 0,
+0x4743,0x4744, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4745, 0, 0,
+ 0, 0, 0,0x4746, 0, 0, 0, 0,
+0x4747, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4748,0x4749, 0,0x474A, 0,0x474B,
+0x474C,0x474D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x474E, 0,0x474F, 0, 0,
+ 0, 0, 0, 0, 0,0x4750, 0, 0,
+0x4751, 0,0x4752, 0, 0, 0,0x4753, 0,
+0x4754, 0, 0, 0, 0,0x4755, 0, 0,
+ 0,0x4756, 0,0x4757, 0, 0, 0,0x4758,
+0x4759, 0, 0, 0, 0, 0, 0,0x475A,
+ 0, 0, 0, 0,0x475B, 0,0x475C, 0,
+0x475D,0x475E, 0,0x475F, 0, 0,0x4760, 0,
+ 0, 0,0x4761, 0, 0, 0, 0, 0,
+0x4762,0x4763, 0,0x744C, 0,0x4764, 0,0x4765,
+ 0,0x744B, 0, 0, 0,0x4766, 0, 0,
+ 0,0x4767, 0, 0, 0,0x4768};
+
+/* page 24 0x6E1E-0x6ECF */
+static uint16 tab_uni_jisx021224[]={
+0x4769, 0, 0, 0,0x476A, 0, 0, 0,
+ 0,0x476B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x476C, 0, 0, 0,
+0x476D, 0, 0,0x476E, 0,0x476F,0x4770, 0,
+ 0, 0, 0, 0, 0, 0,0x4771,0x4772,
+ 0, 0,0x4773,0x4774, 0,0x4775, 0, 0,
+ 0,0x4776, 0,0x4777,0x4778,0x4779,0x477A, 0,
+ 0,0x477B, 0, 0, 0, 0,0x477C,0x477D,
+0x477E, 0, 0, 0,0x4821,0x4822, 0, 0,
+ 0, 0,0x4823, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4824, 0, 0,
+ 0, 0, 0, 0, 0,0x4825, 0,0x4826,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4827,
+ 0, 0, 0, 0, 0,0x4828, 0, 0,
+ 0, 0, 0,0x4829, 0, 0, 0, 0,
+ 0, 0,0x482A, 0, 0, 0, 0, 0,
+ 0,0x482B, 0, 0, 0, 0, 0,0x482C,
+0x482D, 0, 0,0x482E, 0,0x482F, 0, 0,
+ 0, 0, 0, 0, 0,0x4830, 0, 0,
+ 0,0x4831,0x4832,0x4833, 0,0x4834, 0, 0,
+ 0,0x4835,0x4836, 0,0x4837, 0, 0,0x4838,
+0x4839,0x483A};
+
+/* page 25 0x6EEB-0x70E4 */
+static uint16 tab_uni_jisx021225[]={
+0x483B, 0,0x483C,0x483D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x483E, 0,
+0x483F, 0,0x4840, 0, 0, 0, 0, 0,
+ 0,0x4841, 0, 0, 0,0x4842, 0,0x4843,
+ 0,0x4844,0x4845, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4846, 0,0x4847, 0,0x4848,
+0x4849, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x484A, 0, 0,0x484B,0x484C,
+ 0, 0,0x4853, 0,0x484D,0x484E, 0, 0,
+0x484F, 0, 0,0x4850, 0, 0, 0, 0,
+0x4851,0x4852, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4854, 0,0x4855,0x4856,
+0x4857, 0, 0, 0,0x4858, 0,0x4859,0x485A,
+ 0, 0,0x485B,0x485C, 0, 0,0x485D,0x485E,
+ 0, 0, 0, 0, 0,0x485F, 0, 0,
+ 0,0x4860, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4861,0x4862, 0, 0, 0, 0,
+0x4863, 0, 0, 0,0x4864,0x4865, 0, 0,
+0x4866,0x4867,0x4868, 0, 0,0x4869, 0,0x486A,
+0x486B,0x486C, 0,0x486D, 0, 0, 0,0x486E,
+ 0, 0, 0, 0,0x486F,0x4870, 0, 0,
+ 0, 0,0x4871,0x4872,0x4873,0x4874, 0, 0,
+ 0, 0, 0,0x4875,0x4876,0x4877, 0, 0,
+ 0, 0,0x4878,0x4879, 0, 0, 0, 0,
+ 0,0x487A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x487B, 0,0x487C,0x487D, 0,0x487E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4921,
+ 0, 0, 0,0x4922, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4923,0x4924, 0,
+ 0, 0, 0, 0, 0,0x4925, 0, 0,
+ 0, 0,0x4926, 0, 0, 0,0x4927, 0,
+ 0,0x4928,0x4929, 0, 0,0x492A, 0, 0,
+ 0, 0,0x492B,0x492C,0x492D, 0, 0, 0,
+ 0, 0,0x492E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x492F, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4930, 0, 0,
+0x4931, 0, 0, 0, 0,0x744D, 0, 0,
+ 0, 0, 0, 0,0x4932, 0, 0, 0,
+ 0,0x4933, 0, 0,0x4934, 0,0x4935, 0,
+ 0,0x4936, 0, 0, 0, 0, 0, 0,
+0x4937,0x4938, 0, 0, 0,0x4939,0x493A,0x493B,
+0x493C, 0, 0,0x4941, 0, 0, 0, 0,
+ 0,0x493D,0x493E, 0, 0, 0, 0, 0,
+ 0, 0,0x493F,0x4940, 0, 0, 0, 0,
+ 0,0x4942,0x4943, 0, 0, 0, 0, 0,
+ 0,0x4944, 0,0x4945, 0, 0, 0, 0,
+ 0, 0,0x4946,0x4947, 0, 0, 0, 0,
+ 0, 0, 0,0x4948, 0, 0,0x4949, 0,
+ 0, 0,0x494A,0x494B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x494C,0x494D,0x494E,0x494F,0x4950, 0, 0,
+0x4951, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4952, 0, 0, 0, 0, 0, 0,
+0x4953, 0, 0, 0, 0,0x4954,0x4955, 0,
+ 0,0x4956, 0, 0,0x4957, 0, 0, 0,
+0x742E, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4958,
+ 0, 0, 0, 0, 0, 0,0x4959, 0,
+0x495A,0x495B,0x495C,0x495D, 0,0x495E, 0, 0,
+ 0,0x495F, 0, 0, 0, 0, 0, 0,
+ 0,0x4960};
+
+/* page 26 0x70FA-0x71DC */
+static uint16 tab_uni_jisx021226[]={
+0x4961, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4962,0x4963,0x4964,0x4965,0x4966, 0, 0,
+ 0,0x4967,0x4968, 0, 0,0x4969, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x496A, 0,0x496B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x496C, 0,0x496D, 0,0x496E,0x496F,0x4970,
+ 0, 0, 0, 0, 0, 0,0x4971, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4972,
+ 0, 0, 0,0x4973,0x4974,0x4975, 0, 0,
+0x4976,0x4977, 0, 0, 0, 0,0x4978, 0,
+0x4979, 0, 0, 0, 0,0x497A, 0, 0,
+0x497B, 0,0x497C, 0,0x497D, 0,0x497E, 0,
+ 0, 0, 0, 0, 0, 0,0x4A21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4A22,
+ 0, 0, 0, 0, 0, 0,0x4A23, 0,
+ 0, 0, 0,0x4A24, 0,0x4A25, 0, 0,
+ 0, 0,0x4A26, 0, 0, 0, 0, 0,
+0x4A27, 0, 0, 0, 0, 0, 0, 0,
+0x4A28,0x4A29, 0, 0, 0, 0,0x4A2A, 0,
+0x4A2B, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4A2C,0x4A2D, 0,
+0x4A2E,0x4A2F, 0, 0, 0, 0, 0, 0,
+0x4A30, 0, 0, 0, 0,0x4A31,0x4A32,0x4A33,
+ 0, 0,0x4A34, 0, 0, 0, 0, 0,
+ 0,0x4A35,0x4A36, 0, 0, 0, 0, 0,
+ 0,0x4A37, 0, 0,0x4A38, 0, 0,0x4A39,
+0x4A3A, 0,0x4A3B};
+
+/* page 27 0x71F8-0x7E9E */
+static uint16 tab_uni_jisx021227[]={
+0x4A3C, 0, 0, 0, 0, 0,0x4A3D, 0,
+0x4A3E, 0, 0, 0, 0, 0, 0,0x4A3F,
+0x4A40,0x4A41, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4A42, 0, 0, 0,0x4A43,
+ 0, 0,0x4A44, 0, 0,0x4A45, 0,0x4A46,
+ 0, 0, 0, 0,0x4A47, 0, 0, 0,
+ 0, 0, 0,0x4A48, 0, 0, 0,0x4A49,
+ 0, 0, 0, 0,0x4A4A, 0, 0, 0,
+0x4A4B,0x4A4C, 0, 0, 0, 0, 0, 0,
+ 0,0x4A4D,0x4A4E,0x4A4F, 0,0x4A50, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A51,0x4A52,
+0x4A53, 0, 0,0x4A54, 0,0x4A55,0x4A56, 0,
+ 0, 0,0x4A57, 0,0x4A58, 0,0x4A59, 0,
+0x4A5A, 0, 0,0x4A5B, 0, 0, 0, 0,
+0x4A5C, 0, 0,0x4A5D, 0, 0,0x4A5E,0x4A5F,
+ 0,0x4A60, 0, 0, 0, 0, 0,0x4A61,
+0x4A62, 0, 0,0x4A63,0x4A64, 0, 0,0x4A65,
+ 0, 0, 0, 0,0x4A66, 0, 0, 0,
+ 0,0x4A67, 0, 0, 0,0x4A68,0x4A69, 0,
+ 0, 0, 0,0x4A6A, 0, 0, 0, 0,
+ 0, 0, 0,0x4A6B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4A6C, 0, 0, 0, 0,0x4A6D,0x4A6E, 0,
+ 0,0x4A6F, 0, 0,0x4A70, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A71, 0,
+ 0,0x4A72, 0, 0, 0, 0, 0,0x4A73,
+ 0,0x4A74, 0, 0,0x4A75, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4A76,0x4A77, 0,
+0x4A78, 0, 0, 0, 0, 0, 0,0x4A79,
+ 0, 0, 0, 0, 0,0x4A7A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4A7B,0x4A7C, 0, 0, 0,
+ 0, 0,0x4A7D,0x4A7E, 0, 0,0x4B21, 0,
+ 0, 0,0x4B22, 0,0x4B23,0x4B24, 0,0x4B25,
+ 0, 0, 0,0x4B26, 0,0x4B27, 0, 0,
+ 0, 0,0x4B28,0x4B29, 0, 0, 0, 0,
+0x4B2A,0x4B2B, 0, 0, 0, 0,0x4B2C, 0,
+ 0, 0,0x4B2D, 0,0x4B2E, 0, 0,0x4B2F,
+0x4B30, 0, 0, 0,0x4B31, 0, 0, 0,
+ 0,0x4B32,0x4B33, 0, 0,0x4B34, 0, 0,
+ 0, 0,0x4B35,0x4B36, 0,0x4B37, 0, 0,
+ 0, 0, 0,0x4B38, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4B39, 0, 0,
+0x4B3A, 0,0x4B3B, 0, 0, 0,0x4B3C, 0,
+0x4B3D, 0, 0, 0, 0,0x4B3E,0x4B3F,0x4B40,
+0x4B41, 0, 0, 0, 0, 0,0x4B42,0x4B43,
+ 0,0x4B44, 0,0x4B45,0x4B46, 0,0x4B47,0x4B48,
+ 0,0x4B49, 0, 0, 0, 0, 0,0x4B4A,
+ 0,0x4B4B, 0, 0,0x4B4C, 0, 0, 0,
+0x4B4D,0x4B4E, 0,0x4B4F, 0,0x4B50,0x4B51, 0,
+ 0, 0, 0, 0, 0, 0,0x4B52, 0,
+0x4B53, 0, 0,0x4B54, 0,0x4B55, 0,0x4B56,
+0x4B57, 0, 0, 0,0x4B58, 0,0x4B59,0x4B5A,
+0x4B5B, 0,0x4B5C, 0, 0,0x4B5D,0x4B5E, 0,
+ 0, 0,0x4B5F,0x4B60, 0,0x4B61, 0, 0,
+ 0, 0, 0, 0, 0,0x4B62, 0,0x4B63,
+ 0,0x4B64, 0, 0,0x4B65,0x4B66, 0,0x4B67,
+ 0, 0, 0, 0, 0,0x4B68,0x4B69, 0,
+ 0,0x4B6A, 0,0x4B6B,0x4B6C, 0, 0,0x4B6D,
+ 0, 0,0x4B6E,0x4B6F, 0, 0,0x4B70, 0,
+ 0,0x4B71, 0, 0, 0,0x4B72, 0, 0,
+ 0,0x4B73, 0,0x4B74, 0, 0,0x4B75,0x4B76,
+ 0,0x4B77, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4B78,0x4B79, 0,0x4B7A,
+ 0,0x4B7B,0x4B7C,0x4B7D, 0,0x4B7E, 0,0x4C21,
+0x4C22,0x4C23, 0, 0,0x4C24, 0, 0,0x4C25,
+ 0, 0,0x4C26, 0, 0, 0, 0, 0,
+ 0,0x4C27, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4C28,0x4C29, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4C2A, 0,0x4C2B, 0,
+0x4C2C,0x4C2D,0x4C2E,0x4C2F,0x4C30,0x4C31,0x4C32,0x4C33,
+0x4C34,0x4C35, 0, 0, 0, 0, 0, 0,
+ 0,0x4C36, 0, 0, 0, 0, 0, 0,
+0x4C37, 0, 0,0x4C38,0x4C39, 0,0x4C3A,0x4C3B,
+ 0, 0, 0,0x4C3C, 0,0x4C3D, 0, 0,
+ 0,0x4C3E,0x4C3F, 0, 0, 0, 0,0x4C40,
+ 0, 0, 0, 0, 0,0x4C41, 0, 0,
+ 0, 0,0x4C42, 0, 0, 0,0x4C43,0x4C44,
+0x4C45, 0, 0,0x4C46, 0,0x4C47,0x4C48, 0,
+ 0,0x4C49,0x4C4A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4C4B,0x4C4C, 0, 0, 0,0x4C4D,0x4C4E,0x4C4F,
+ 0,0x4C50, 0, 0, 0, 0, 0,0x4C51,
+0x4C52,0x4C53,0x4C54, 0, 0, 0, 0, 0,
+0x4C55,0x4C56,0x4C57, 0,0x4C58, 0, 0,0x4C59,
+0x4C5A,0x4C5B, 0,0x4C5C, 0, 0,0x4C5D, 0,
+0x4C5E,0x4C5F,0x4C60,0x4C61, 0, 0,0x4C62,0x4C63,
+ 0,0x4C64,0x4C65, 0, 0,0x4C66, 0, 0,
+ 0,0x4C67, 0,0x4C68, 0, 0, 0,0x4C69,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4C6A,0x4C6B, 0, 0,0x4C6C, 0, 0, 0,
+0x4C6D, 0, 0,0x4C6E, 0, 0, 0, 0,
+0x4C6F, 0,0x4C70,0x4C71, 0, 0,0x4C72,0x4C73,
+ 0, 0, 0, 0,0x4C74, 0, 0, 0,
+0x4C75, 0,0x4C76,0x4C77, 0, 0, 0,0x4C78,
+ 0, 0, 0, 0,0x4C79, 0, 0, 0,
+ 0, 0,0x4C7A,0x4C7B,0x4C7C, 0, 0,0x4C7D,
+ 0,0x7450, 0, 0, 0, 0,0x4C7E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4D21, 0, 0, 0,0x4D22,0x4D23,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4D24,0x4D25, 0, 0,0x4D26, 0, 0,0x4D27,
+ 0,0x4D28,0x4D29, 0, 0, 0, 0,0x4D2A,
+ 0, 0, 0, 0, 0, 0,0x4D2B, 0,
+ 0,0x4D2C, 0, 0, 0,0x4D2D,0x4D2E,0x4D2F,
+0x4D30, 0, 0,0x4D31, 0, 0, 0,0x4D32,
+0x4D33, 0, 0, 0, 0, 0,0x4D34, 0,
+0x4D35, 0,0x4D36, 0, 0, 0, 0,0x4D37,
+ 0, 0, 0, 0, 0, 0,0x4D38,0x4D39,
+ 0,0x4D3A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4D3B,
+ 0,0x4D3C, 0, 0, 0, 0, 0, 0,
+ 0,0x4D3D,0x4D3E,0x4D3F,0x4D40,0x4D41,0x4D42, 0,
+ 0,0x4D43, 0, 0, 0,0x4D44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4D45, 0,0x4D46,0x4D47, 0,0x4D48, 0, 0,
+ 0,0x4D49, 0, 0,0x4D4A, 0, 0, 0,
+ 0, 0,0x4D4B, 0,0x4D4C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4D4D, 0, 0, 0,
+ 0, 0,0x4D4E, 0, 0, 0, 0,0x4D4F,
+0x4D50,0x4D51, 0, 0,0x4D52, 0,0x4D53, 0,
+ 0, 0, 0, 0,0x4D54, 0,0x4D55,0x4D56,
+ 0, 0, 0, 0, 0, 0, 0,0x4D57,
+ 0, 0, 0, 0,0x4D58, 0, 0,0x4D59,
+0x4D5A,0x4D5B, 0, 0,0x4D5C, 0, 0,0x4D5D,
+ 0, 0, 0, 0,0x4D5E, 0,0x4D5F,0x4D60,
+ 0,0x4D61, 0, 0, 0, 0, 0, 0,
+ 0,0x4D62, 0, 0, 0, 0, 0, 0,
+0x4D63, 0,0x4D64,0x4D65,0x4D66, 0, 0,0x4D67,
+0x4D68, 0,0x4D69, 0,0x4D6A, 0, 0,0x4D6B,
+ 0, 0,0x4D6C,0x4D6D, 0,0x4D6E,0x4D6F, 0,
+ 0,0x4D70, 0,0x4D71,0x4D72,0x4D73,0x4D74, 0,
+ 0, 0, 0,0x4D75, 0,0x4D76,0x4D77, 0,
+ 0,0x4D78, 0, 0, 0,0x4D79, 0, 0,
+ 0, 0,0x4D7A,0x4D7B, 0,0x4D7C, 0, 0,
+0x4D7D,0x4D7E,0x4E21, 0,0x4E22, 0, 0, 0,
+0x4E24,0x4E25, 0,0x4E26,0x4E27,0x4E28, 0, 0,
+ 0,0x4E29,0x4E23,0x4E2A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4E2B, 0, 0,
+ 0,0x4E2C, 0, 0, 0, 0, 0,0x4E2D,
+ 0, 0, 0, 0,0x4E2E,0x4E2F, 0, 0,
+ 0, 0, 0, 0, 0,0x4E30,0x4E31,0x4E32,
+ 0,0x4E33, 0, 0,0x4E34, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x4E35,0x7451, 0, 0,0x4E36, 0, 0,
+ 0, 0, 0, 0,0x4E37,0x4E38, 0, 0,
+ 0, 0, 0, 0, 0,0x4E39, 0, 0,
+ 0, 0, 0,0x4E3A,0x4E3B,0x4E3C,0x7452,0x4E3D,
+0x4E3E, 0,0x4E3F,0x4E40,0x4E41,0x4E42,0x4E43,0x4E44,
+0x4E45, 0,0x4E46, 0, 0,0x4E47, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4E48, 0, 0,
+ 0,0x4E49, 0, 0, 0,0x4E4A, 0, 0,
+ 0,0x4E4B, 0,0x4E4C,0x4E4D, 0,0x4E4E, 0,
+ 0, 0, 0, 0,0x4E4F, 0, 0, 0,
+ 0,0x4E50, 0, 0, 0, 0, 0, 0,
+0x4E51, 0, 0, 0, 0, 0,0x4E52, 0,
+0x4E53, 0, 0, 0,0x4E54, 0, 0, 0,
+0x4E55,0x4E56, 0, 0, 0, 0,0x4E57, 0,
+ 0,0x4E58, 0, 0,0x4E59, 0, 0, 0,
+0x4E5A, 0, 0, 0, 0, 0,0x4E5B, 0,
+ 0, 0,0x4E5C, 0, 0, 0,0x4E5D, 0,
+ 0, 0,0x4E5E, 0,0x4E5F,0x4E60, 0,0x4E61,
+ 0,0x4E62,0x4E63, 0,0x4E64, 0, 0, 0,
+ 0, 0,0x4E65, 0, 0, 0, 0, 0,
+0x4E66, 0, 0, 0, 0,0x4E67,0x4E68,0x4E69,
+ 0, 0, 0, 0,0x4E6A,0x4E6B,0x4E6C, 0,
+ 0,0x4E6D, 0, 0, 0,0x4E6E,0x4E6F, 0,
+ 0, 0,0x4E70, 0, 0,0x4E71,0x4E72, 0,
+ 0, 0,0x4E73, 0, 0,0x4E74,0x4E75,0x4E76,
+ 0, 0,0x4E77, 0, 0, 0,0x4E78,0x4E79,
+ 0, 0, 0, 0,0x4E7A, 0,0x4E7B,0x4E7C,
+0x4E7D, 0,0x4E7E, 0,0x4F21, 0, 0,0x4F22,
+ 0, 0,0x4F23, 0,0x4F24, 0, 0, 0,
+0x4F25, 0,0x4F26,0x4F27,0x4F28, 0, 0, 0,
+ 0, 0,0x4F29, 0, 0,0x4F2A, 0, 0,
+0x4F2B, 0, 0, 0,0x4F2C, 0, 0, 0,
+ 0, 0, 0, 0,0x4F2D,0x4F2E, 0, 0,
+ 0, 0, 0, 0,0x4F2F,0x4F30,0x4F31, 0,
+ 0, 0,0x4F32, 0, 0, 0, 0,0x4F33,
+ 0, 0,0x4F34, 0, 0, 0, 0,0x4F35,
+ 0, 0,0x4F36, 0, 0, 0,0x4F37,0x4F38,
+ 0,0x4F39, 0, 0, 0,0x4F3A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4F3B, 0,
+ 0, 0, 0,0x4F3C, 0, 0, 0, 0,
+ 0,0x4F3D, 0, 0, 0, 0, 0, 0,
+ 0,0x4F3E,0x4F3F, 0, 0,0x4F40, 0, 0,
+ 0,0x4F41, 0, 0, 0, 0,0x4F42,0x4F43,
+0x4F44, 0, 0, 0,0x4F45, 0,0x4F46, 0,
+ 0, 0,0x4F47, 0,0x4F48, 0, 0, 0,
+0x4F49,0x4F4A, 0, 0,0x4F4B, 0, 0, 0,
+0x4F4C, 0, 0,0x4F4D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4F4E,0x4F4F, 0,
+ 0,0x4F50, 0, 0, 0,0x4F51,0x4F52, 0,
+ 0,0x4F53, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4F54, 0, 0,
+ 0,0x4F55,0x4F56,0x4F57, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4F58,0x4F59, 0,
+0x4F5A, 0, 0, 0, 0,0x4F5B, 0,0x4F5C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4F5D,0x4F5E, 0, 0,0x4F5F,
+0x4F60, 0, 0, 0,0x4F61, 0,0x4F62, 0,
+ 0, 0,0x4F63, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x4F64, 0,0x4F65, 0,
+0x4F66,0x4F67, 0,0x4F68,0x4F69, 0, 0, 0,
+0x4F6A, 0,0x4F6B, 0, 0, 0,0x4F6C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4F6D, 0, 0, 0,0x4F6E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x4F6F, 0, 0, 0, 0,0x4F70,
+ 0, 0, 0, 0,0x4F71, 0, 0, 0,
+0x4F72, 0, 0, 0, 0,0x4F74,0x4F75,0x4F76,
+ 0,0x4F73, 0, 0,0x4F77, 0, 0, 0,
+0x4F78, 0, 0, 0,0x4F79,0x4F7A, 0, 0,
+0x4F7B,0x4F7C,0x4F7D,0x4F7E, 0, 0, 0, 0,
+ 0, 0, 0,0x5021, 0,0x5022, 0,0x5023,
+ 0, 0, 0, 0, 0, 0, 0,0x5024,
+0x5025,0x5026, 0, 0,0x5027, 0,0x5028, 0,
+ 0, 0,0x5029,0x502A, 0,0x502B,0x502C, 0,
+ 0, 0, 0,0x502E, 0, 0, 0,0x502F,
+0x5030,0x5031, 0, 0,0x502D, 0,0x5032, 0,
+ 0, 0,0x5033, 0, 0, 0, 0, 0,
+ 0, 0,0x5034,0x5035, 0, 0,0x5037,0x5038,
+ 0, 0,0x5039,0x503A, 0, 0, 0,0x503B,
+0x5036, 0, 0, 0, 0, 0,0x503C, 0,
+ 0, 0, 0, 0,0x503D, 0, 0, 0,
+0x503E, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x503F, 0,0x5040, 0,0x5041,0x5042,
+0x5043, 0, 0, 0, 0,0x5044, 0,0x5045,
+ 0,0x5046, 0, 0, 0,0x5047, 0, 0,
+0x7454,0x5048, 0, 0,0x5049,0x504A, 0, 0,
+ 0, 0, 0,0x504B, 0,0x504C, 0,0x504D,
+ 0, 0, 0, 0,0x504E,0x504F,0x5050, 0,
+ 0, 0,0x5051,0x5052, 0, 0, 0,0x5053,
+ 0,0x5054, 0, 0,0x5055, 0, 0, 0,
+0x5056, 0, 0,0x5057,0x5058, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5059,
+ 0,0x505A, 0,0x505B, 0, 0, 0, 0,
+ 0, 0,0x505C, 0, 0, 0, 0, 0,
+ 0,0x505D, 0,0x505E,0x505F, 0,0x5060, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5061,0x5062, 0, 0, 0,
+ 0,0x5063, 0,0x5064,0x5065,0x5066,0x5067, 0,
+0x5068, 0, 0,0x5069,0x506A, 0, 0, 0,
+ 0,0x506B, 0, 0, 0, 0, 0, 0,
+0x506C,0x506D, 0,0x506E, 0, 0, 0,0x506F,
+ 0,0x5070, 0, 0,0x5071, 0, 0, 0,
+0x5072, 0, 0,0x5073, 0, 0, 0, 0,
+ 0, 0,0x5074, 0,0x5075, 0, 0,0x5076,
+0x5077, 0,0x5078, 0, 0, 0, 0,0x5079,
+ 0, 0, 0, 0,0x507A, 0,0x507B, 0,
+ 0, 0,0x507C, 0, 0,0x507D,0x507E, 0,
+0x5121, 0,0x5122, 0, 0,0x5123, 0, 0,
+ 0, 0,0x5124,0x5125, 0,0x5126, 0, 0,
+ 0,0x5127, 0, 0, 0, 0, 0, 0,
+0x5128, 0, 0, 0,0x5129, 0, 0, 0,
+ 0, 0,0x512A,0x512B, 0, 0, 0,0x512C,
+ 0,0x512D,0x512E, 0,0x512F, 0, 0, 0,
+ 0,0x5130, 0, 0, 0,0x5131, 0, 0,
+ 0, 0, 0,0x5132, 0, 0,0x5133, 0,
+ 0,0x5134, 0, 0, 0, 0, 0,0x5135,
+ 0, 0, 0,0x5136, 0,0x5137, 0,0x5138,
+0x5139, 0, 0, 0,0x513A,0x513B, 0, 0,
+0x513C,0x513D,0x513E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x513F,0x5140, 0,0x5141,
+0x5142, 0, 0, 0,0x5143, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5144,0x5145, 0,
+ 0,0x5146, 0, 0,0x5147,0x5148, 0,0x5149,
+0x514A, 0, 0, 0, 0,0x514B, 0,0x514C,
+ 0, 0,0x514D, 0, 0,0x514E, 0, 0,
+ 0, 0, 0, 0, 0,0x514F, 0, 0,
+0x5150, 0, 0, 0, 0, 0,0x5151, 0,
+0x5152, 0,0x5153, 0, 0,0x5154,0x5155, 0,
+ 0, 0,0x5156,0x5157, 0, 0, 0, 0,
+0x5158,0x5159, 0, 0,0x515A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x515B, 0,
+0x515C, 0, 0,0x515D, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x515E, 0, 0, 0,
+ 0, 0, 0,0x515F, 0,0x5160, 0, 0,
+ 0,0x5161, 0,0x5162,0x5163, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5164, 0,
+ 0,0x5165, 0, 0,0x5166, 0,0x5167, 0,
+ 0,0x5168, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5169, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7459,
+0x516A,0x516B, 0,0x516C,0x516D, 0, 0, 0,
+ 0,0x516E, 0, 0,0x516F, 0, 0, 0,
+ 0, 0, 0,0x5170, 0,0x5171,0x5172, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5173,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5174, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5175,
+ 0, 0, 0,0x5176, 0, 0, 0,0x5177,
+ 0,0x5178,0x5179,0x517A, 0,0x517B,0x517C,0x517D,
+0x517E,0x5221, 0, 0,0x5222, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5223, 0,0x5224,
+0x5225,0x5226, 0, 0, 0, 0, 0,0x5227,
+ 0, 0, 0, 0, 0, 0,0x5228, 0,
+ 0, 0, 0, 0, 0,0x5229, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x522A, 0, 0, 0,0x522B, 0,0x522C, 0,
+ 0,0x522D,0x522E, 0, 0,0x522F, 0,0x5230,
+ 0, 0,0x5231,0x5232, 0, 0, 0,0x5233,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5234, 0, 0, 0,
+ 0,0x5235, 0, 0, 0, 0,0x5236, 0,
+0x5237,0x5238, 0, 0, 0, 0,0x5239, 0,
+ 0, 0, 0,0x523A, 0, 0,0x523B, 0,
+0x523C, 0, 0, 0, 0,0x523D, 0, 0,
+ 0, 0, 0, 0,0x523E, 0, 0,0x523F,
+0x5240, 0,0x5241, 0, 0,0x5242,0x5243, 0,
+ 0, 0,0x5244,0x5245,0x5246,0x5247, 0, 0,
+ 0, 0,0x5248, 0, 0,0x5249, 0, 0,
+0x524A, 0,0x524B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x524C, 0,0x524D,0x524E,
+ 0,0x524F,0x5250,0x5251, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5252, 0,0x5253, 0, 0, 0, 0, 0,
+ 0, 0,0x5254, 0,0x5255,0x5256, 0, 0,
+0x5257,0x5258,0x5259, 0,0x525A, 0,0x525B, 0,
+ 0,0x525C,0x525D,0x525E,0x525F, 0,0x5260, 0,
+ 0,0x5261, 0,0x5262,0x5263, 0,0x5264,0x5265,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5266, 0,0x5267, 0, 0, 0, 0,
+0x5268, 0, 0, 0, 0,0x5269,0x526A, 0,
+0x526B, 0, 0, 0,0x526C, 0, 0, 0,
+ 0,0x526D, 0,0x526E,0x526F, 0,0x5270, 0,
+ 0,0x5271,0x5272, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5273, 0,
+ 0, 0,0x5274, 0, 0, 0, 0, 0,
+ 0,0x5276,0x5277,0x5278, 0,0x5275, 0, 0,
+ 0,0x5279,0x527A,0x527B,0x527C,0x527D,0x527E, 0,
+ 0,0x5321, 0,0x5322, 0, 0, 0,0x5323,
+ 0,0x5324, 0, 0, 0,0x5325,0x5326, 0,
+0x5327, 0,0x5328, 0, 0, 0, 0, 0,
+ 0,0x5329, 0, 0,0x532A,0x532B, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x532C,0x532D,
+ 0, 0, 0, 0, 0, 0, 0,0x532E,
+ 0, 0, 0, 0,0x532F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5330, 0,
+0x5331, 0, 0, 0, 0, 0,0x5332, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5333, 0, 0, 0, 0, 0,0x5334,0x5335,
+ 0, 0,0x5336,0x5337,0x5338, 0, 0,0x5339,
+ 0, 0, 0, 0,0x533A, 0, 0,0x533B,
+0x533C,0x533D, 0, 0, 0,0x533E, 0,0x533F,
+ 0, 0, 0,0x5340,0x5341,0x5342, 0,0x5343,
+ 0,0x5344,0x5345, 0, 0,0x5346, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5347, 0,
+ 0,0x5348, 0,0x5349, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x534A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x534B, 0, 0, 0,0x534C,
+0x534D,0x534E, 0, 0, 0, 0, 0,0x534F,
+ 0,0x5350,0x5351,0x5352, 0, 0,0x5353, 0,
+ 0, 0, 0, 0, 0,0x5354,0x5355, 0,
+ 0, 0, 0,0x5356, 0, 0,0x5357, 0,
+ 0, 0,0x5358, 0, 0,0x5359, 0, 0,
+ 0,0x535A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x535B,0x535C,0x535D, 0,
+0x535E,0x535F, 0, 0, 0, 0, 0,0x5360,
+0x5361, 0, 0, 0, 0,0x5362, 0, 0,
+ 0,0x5363, 0,0x5364, 0, 0, 0,0x5365,
+ 0,0x5366,0x5367, 0,0x5368,0x5369, 0, 0,
+ 0, 0, 0, 0, 0,0x536A, 0,0x536B,
+ 0, 0,0x536C, 0, 0, 0, 0, 0,
+0x536D, 0, 0, 0, 0, 0, 0, 0,
+0x536E, 0,0x536F,0x5370, 0, 0, 0,0x5371,
+ 0,0x5372,0x5373,0x5374, 0,0x5375,0x5376, 0,
+0x5377, 0, 0,0x5378,0x5379,0x537A, 0, 0,
+ 0,0x537B, 0, 0, 0, 0,0x537C,0x537D,
+ 0, 0, 0, 0, 0,0x537E,0x5421, 0,
+0x745C, 0, 0, 0, 0, 0,0x5422,0x5423,
+ 0, 0,0x5424, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5425, 0, 0,0x5426,0x5427,
+ 0,0x5428, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5429,0x542A,0x542B,0x542C,0x542D, 0,
+ 0, 0, 0, 0,0x542E,0x542F,0x5430, 0,
+ 0, 0, 0, 0, 0, 0,0x745D,0x5431,
+ 0,0x5432, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5434, 0, 0,0x5435,0x5436, 0,
+ 0, 0,0x5437,0x5438, 0,0x5439, 0, 0,
+ 0,0x543A, 0, 0, 0,0x543B,0x543C, 0,
+ 0,0x543D,0x543E, 0, 0, 0, 0, 0,
+0x5433, 0, 0, 0, 0, 0, 0, 0,
+0x543F, 0, 0, 0, 0, 0, 0, 0,
+0x5440,0x5441, 0, 0, 0,0x5442, 0,0x5443,
+ 0, 0, 0, 0,0x5444,0x5445, 0, 0,
+0x5446, 0, 0, 0, 0, 0, 0,0x5447,
+0x5448, 0, 0, 0,0x5449,0x544A, 0,0x544B,
+ 0, 0, 0,0x544C, 0, 0,0x544D, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x544E,
+ 0, 0, 0, 0,0x544F,0x5450, 0,0x5451,
+ 0, 0, 0, 0, 0, 0,0x5452, 0,
+0x5453, 0,0x5454, 0, 0, 0, 0, 0,
+0x5455, 0, 0, 0, 0, 0, 0,0x5456,
+ 0,0x5457,0x5458, 0, 0,0x5459, 0, 0,
+ 0, 0, 0,0x545A, 0, 0,0x545B,0x545C,
+ 0, 0, 0,0x545D, 0, 0, 0, 0,
+0x545E, 0, 0, 0, 0, 0,0x545F, 0,
+ 0,0x5460, 0, 0, 0, 0,0x5461,0x5462,
+ 0, 0,0x5463, 0, 0,0x5464, 0, 0,
+ 0,0x5465, 0, 0, 0,0x5466, 0, 0,
+0x5467, 0,0x5468, 0, 0,0x5469,0x546A};
+
+/* page 28 0x7F3B-0x8044 */
+static uint16 tab_uni_jisx021228[]={
+0x546C,0x546B,0x546D,0x546E,0x546F, 0, 0, 0,
+0x5470,0x5471, 0, 0,0x5472, 0, 0, 0,
+ 0, 0, 0, 0,0x5473, 0, 0,0x5474,
+0x5475, 0, 0, 0, 0, 0, 0, 0,
+0x5476,0x5477,0x5478, 0, 0, 0,0x5479, 0,
+0x547A,0x547B,0x547C,0x547D, 0, 0, 0, 0,
+ 0, 0,0x547E, 0, 0, 0,0x5521, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5522,0x5523,0x5524,0x5525, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5526, 0,0x5527, 0,0x5528,0x5529,0x552A, 0,
+ 0, 0, 0,0x552B,0x552C, 0, 0, 0,
+ 0,0x552D, 0, 0, 0, 0,0x552E,0x552F,
+ 0, 0, 0,0x5530, 0, 0, 0,0x5531,
+ 0, 0,0x5532, 0, 0, 0, 0, 0,
+ 0,0x5533, 0, 0, 0, 0, 0, 0,
+ 0,0x5534, 0, 0,0x5535,0x5536, 0, 0,
+0x5537, 0, 0, 0, 0,0x5538, 0, 0,
+ 0, 0, 0,0x5539,0x553A, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x553B, 0, 0, 0,0x553C, 0, 0, 0,
+0x553D, 0,0x553E, 0, 0,0x553F, 0, 0,
+ 0,0x5540, 0,0x5541,0x5542, 0, 0,0x5543,
+ 0, 0, 0, 0, 0, 0, 0,0x5544,
+ 0, 0,0x5545,0x5546,0x5547, 0, 0, 0,
+ 0, 0, 0, 0,0x5548,0x5549, 0,0x554A,
+ 0, 0,0x554B,0x554C,0x554D, 0,0x554E, 0,
+0x554F,0x5550, 0,0x5551, 0, 0, 0, 0,
+ 0, 0,0x5552,0x5553,0x5554,0x5555, 0, 0,
+ 0,0x5556, 0,0x5557, 0, 0, 0, 0,
+ 0,0x5558, 0,0x5559, 0,0x555A, 0, 0,
+ 0,0x555B,0x555C, 0,0x555D, 0,0x555E,0x555F,
+ 0,0x5560, 0,0x5561, 0,0x5562, 0, 0,
+ 0,0x5563};
+
+/* page 29 0x8060-0x8362 */
+static uint16 tab_uni_jisx021229[]={
+0x5564, 0, 0, 0,0x5565, 0,0x5566, 0,
+ 0, 0, 0, 0, 0,0x5567, 0, 0,
+ 0,0x5568, 0, 0, 0,0x5569, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x556A, 0, 0, 0, 0, 0, 0,
+0x556B, 0, 0, 0, 0, 0,0x556C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x556D, 0,0x556E, 0,
+ 0, 0, 0, 0, 0, 0,0x556F,0x5570,
+ 0, 0, 0,0x5571, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5572,0x5573, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5574, 0, 0, 0, 0,0x5575, 0,0x5576,
+ 0, 0,0x5577, 0,0x5578,0x5579, 0,0x557A,
+0x557B, 0, 0, 0, 0, 0, 0, 0,
+0x557C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x557D,0x557E, 0,
+0x5621, 0,0x5622,0x5623, 0, 0,0x5624, 0,
+ 0,0x5625,0x5626, 0, 0, 0,0x5627, 0,
+ 0, 0, 0,0x5628, 0, 0, 0, 0,
+ 0, 0, 0,0x5629, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x562A,0x562B,
+0x562C, 0, 0, 0,0x562D, 0,0x562E, 0,
+0x562F, 0, 0, 0,0x5630, 0, 0,0x5631,
+ 0, 0, 0, 0,0x5632, 0, 0, 0,
+0x5633, 0, 0, 0, 0,0x5634, 0, 0,
+ 0, 0,0x5635, 0,0x5636, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5637, 0,0x5638,
+ 0, 0,0x5639, 0,0x563A, 0, 0, 0,
+ 0, 0,0x563B, 0, 0, 0, 0,0x563C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x563D,0x563E, 0, 0, 0, 0, 0,0x563F,
+0x5640,0x5641, 0, 0, 0,0x5642, 0,0x5643,
+ 0, 0, 0, 0, 0, 0, 0,0x5644,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5645, 0, 0,0x5647,0x5648,0x5649, 0,
+ 0, 0, 0,0x564A, 0, 0,0x564B, 0,
+0x5646, 0, 0, 0, 0, 0,0x564C, 0,
+0x564D, 0, 0,0x564E, 0, 0,0x564F, 0,
+ 0, 0,0x5650, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5651, 0,
+ 0, 0,0x5652, 0,0x5653, 0, 0, 0,
+ 0, 0, 0,0x5654, 0, 0, 0, 0,
+ 0, 0, 0,0x5656, 0,0x5657, 0, 0,
+ 0, 0,0x5658,0x5655, 0, 0,0x5659,0x565A,
+ 0, 0, 0, 0, 0,0x565B, 0,0x565C,
+ 0, 0, 0,0x565D, 0,0x565E,0x565F, 0,
+ 0,0x5660, 0, 0,0x5661, 0, 0, 0,
+ 0, 0, 0,0x5662,0x5663, 0, 0, 0,
+0x5664,0x5665,0x5666, 0, 0,0x5667,0x5668, 0,
+0x5669,0x566A, 0, 0, 0,0x566B, 0,0x566C,
+0x566D, 0, 0,0x566E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x566F,
+ 0, 0, 0,0x5670,0x5671, 0, 0, 0,
+ 0,0x5672,0x5673, 0, 0,0x5674, 0, 0,
+ 0,0x5675,0x5676, 0, 0, 0, 0, 0,
+0x5677, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5678, 0,0x5679, 0, 0, 0,
+ 0, 0,0x567A, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x567B,0x567C,0x567D,0x567E, 0,
+ 0, 0, 0,0x5721, 0, 0,0x5722,0x5723,
+ 0,0x5724, 0, 0, 0, 0,0x5725, 0,
+ 0, 0, 0, 0,0x5726, 0, 0, 0,
+0x5727, 0, 0,0x5728, 0, 0, 0,0x5729,
+ 0, 0, 0, 0, 0,0x572A, 0, 0,
+ 0, 0, 0, 0,0x572B, 0, 0, 0,
+ 0, 0, 0,0x572C, 0,0x572D, 0,0x572E,
+0x572F,0x5730, 0,0x5731,0x5732, 0, 0,0x5733,
+ 0,0x5734,0x5735, 0, 0, 0,0x5736, 0,
+ 0,0x5737, 0, 0,0x5738, 0,0x5739, 0,
+0x573A, 0,0x573B,0x573C, 0, 0, 0, 0,
+0x573D,0x573E, 0,0x573F,0x5740, 0, 0,0x5741,
+0x5742,0x5743,0x5744, 0, 0, 0,0x5745, 0,
+0x5746, 0,0x5747, 0,0x5748, 0, 0,0x5749,
+ 0, 0,0x574A, 0,0x574B, 0,0x574C,0x574D,
+ 0, 0, 0, 0, 0, 0,0x574E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x574F, 0, 0, 0, 0,0x5750, 0, 0,
+ 0, 0,0x5751, 0, 0, 0, 0, 0,
+0x5752, 0,0x5753, 0,0x5754, 0, 0, 0,
+0x5755, 0,0x5756, 0, 0,0x5757, 0,0x5758,
+ 0, 0, 0, 0, 0, 0,0x5759,0x575A,
+ 0, 0, 0, 0, 0,0x575B,0x575C, 0,
+0x575D,0x575E, 0, 0, 0, 0, 0,0x575F,
+0x5760, 0,0x5761,0x5762, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5764, 0,0x5765,0x5766,0x5767,
+ 0,0x5768,0x5769, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x576A,0x576B,0x576C, 0,
+0x576D, 0, 0,0x576E, 0, 0, 0,0x576F,
+ 0, 0,0x5770, 0,0x5771,0x5772, 0, 0,
+ 0, 0,0x5773,0x5774,0x5775, 0, 0,0x5776,
+ 0, 0, 0, 0, 0,0x5777,0x5778, 0,
+ 0,0x5779, 0,0x583E,0x5763,0x577A,0x577B,0x577C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x745F};
+
+/* page 30 0x8370-0x8419 */
+static uint16 tab_uni_jisx021230[]={
+0x577D, 0, 0, 0, 0, 0, 0, 0,
+0x577E, 0, 0, 0, 0,0x5821, 0,0x5822,
+0x5823, 0,0x5824, 0,0x5825, 0,0x5826, 0,
+ 0, 0, 0, 0, 0,0x5827, 0, 0,
+ 0, 0,0x5828, 0,0x5829,0x582A, 0, 0,
+0x582B,0x582C, 0,0x582D,0x582E,0x582F, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5830,0x5831,
+ 0,0x5832, 0, 0,0x5833,0x584C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5834,0x5835,
+0x5836, 0, 0, 0, 0, 0, 0,0x5837,
+ 0,0x5838, 0, 0, 0, 0, 0,0x5839,
+0x583A,0x583B, 0, 0,0x583C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x583D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x583F, 0,0x5840, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5841, 0,
+0x5842,0x5843, 0, 0,0x5844, 0, 0, 0,
+ 0,0x5845, 0, 0, 0, 0,0x5846, 0,
+ 0, 0,0x5847, 0, 0, 0, 0,0x5848,
+ 0,0x5849, 0, 0, 0,0x584A, 0, 0,
+ 0,0x584B};
+
+/* page 31 0x842F-0x8880 */
+static uint16 tab_uni_jisx021231[]={
+0x584D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x584E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x584F, 0,
+0x5850,0x5851, 0,0x5852, 0, 0,0x5853, 0,
+0x5854, 0,0x5855,0x5856, 0, 0, 0,0x5857,
+ 0,0x5858,0x5859,0x585A, 0,0x585B, 0, 0,
+ 0,0x585C, 0, 0, 0,0x585D,0x585E, 0,
+0x585F, 0, 0,0x5860, 0, 0, 0, 0,
+ 0,0x5861, 0, 0,0x5862,0x5863, 0,0x5864,
+ 0,0x5865, 0, 0, 0,0x5866,0x5867, 0,
+ 0, 0,0x5868, 0, 0, 0,0x5869, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x586A,0x586B, 0,0x586C, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x586D,
+ 0, 0, 0, 0, 0, 0, 0,0x586E,
+ 0,0x586F,0x5870,0x5871, 0, 0, 0, 0,
+0x5872, 0,0x5873, 0, 0,0x5874, 0, 0,
+ 0, 0, 0,0x5875, 0, 0,0x5876,0x5877,
+ 0,0x5878, 0,0x5879, 0, 0, 0, 0,
+0x587A,0x587B, 0, 0, 0,0x587C, 0, 0,
+0x587D, 0, 0, 0,0x587E, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5921, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5922, 0, 0,0x5923, 0, 0, 0, 0,
+0x5924,0x5925,0x5926,0x5927, 0, 0, 0, 0,
+0x5928, 0, 0,0x592A,0x592B, 0,0x592C, 0,
+ 0, 0, 0,0x592D,0x592E, 0, 0, 0,
+0x592F, 0, 0, 0, 0,0x5930, 0,0x5931,
+ 0,0x5932, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5933, 0,0x5934,
+ 0, 0, 0,0x5935,0x5936,0x5937,0x5938, 0,
+0x5939, 0, 0,0x593A,0x593B, 0, 0, 0,
+0x593C, 0, 0,0x5929,0x593D,0x593E, 0,0x593F,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5940, 0, 0, 0, 0, 0, 0,0x5941,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5942,0x5943,0x5944,0x5945,0x5946, 0, 0,0x5947,
+ 0, 0,0x5948, 0, 0,0x5949,0x594A,0x594B,
+0x594C,0x594D,0x594E,0x594F, 0,0x5950, 0, 0,
+ 0, 0, 0, 0,0x5951, 0, 0, 0,
+0x5952, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5953,0x5954,0x5955, 0,0x5956, 0,
+0x5957, 0,0x5958, 0, 0, 0,0x5959,0x595A,
+ 0, 0,0x595B, 0,0x595C,0x595D, 0, 0,
+0x595E, 0, 0, 0,0x595F, 0, 0, 0,
+ 0,0x5960, 0, 0, 0, 0,0x5961, 0,
+0x5962,0x5963, 0,0x5964, 0, 0,0x5965, 0,
+0x5966, 0, 0, 0, 0, 0,0x5974, 0,
+ 0,0x7461, 0, 0, 0,0x5967, 0,0x5968,
+0x5969,0x596A, 0, 0, 0,0x596B,0x596C,0x596D,
+0x596E, 0, 0,0x596F, 0, 0, 0, 0,
+0x5970, 0, 0,0x5971,0x5972, 0, 0,0x5973,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5975, 0,0x5976, 0, 0, 0, 0,
+0x5977,0x5978, 0, 0, 0, 0, 0,0x5979,
+ 0,0x597A, 0, 0, 0, 0,0x597B, 0,
+ 0, 0, 0, 0,0x597C, 0, 0,0x597D,
+ 0, 0, 0, 0, 0,0x597E, 0, 0,
+0x5A21,0x5A22, 0, 0, 0,0x5A23,0x5A24, 0,
+ 0, 0, 0, 0, 0, 0,0x5A25,0x5A26,
+ 0,0x5A27,0x5A28,0x5A29, 0, 0, 0, 0,
+ 0,0x5A2A,0x5A2B, 0,0x5A2C, 0, 0,0x5A2D,
+ 0, 0,0x5A2E, 0, 0, 0, 0, 0,
+0x5A2F, 0,0x5A30, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5A31,
+ 0,0x5A32, 0,0x5A33, 0,0x5A34,0x5A35, 0,
+ 0,0x5A36,0x3866,0x5A37, 0, 0, 0,0x5A38,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5A39,0x5A3A, 0, 0,0x5A3B,
+0x5A3C,0x5A3D,0x5A3E, 0, 0, 0,0x5A3F, 0,
+ 0,0x5A40,0x5A41,0x5A42,0x5A43,0x5A44, 0, 0,
+ 0, 0,0x5A45, 0, 0,0x5A46, 0, 0,
+0x5A47, 0, 0, 0, 0, 0,0x5A48,0x5A49,
+0x5A4A, 0, 0,0x5A4B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5A6D, 0, 0, 0, 0,0x5A4C, 0,
+ 0, 0,0x5A4D, 0, 0, 0, 0,0x5A4E,
+ 0,0x5A4F, 0,0x5A50, 0,0x5A51, 0, 0,
+ 0, 0,0x5A52, 0, 0, 0, 0,0x5A53,
+0x5A54,0x5A55, 0, 0, 0, 0,0x5A56, 0,
+ 0, 0,0x5A57, 0,0x5A58,0x5A59,0x5A5A, 0,
+0x5A5B,0x5A5C,0x5A5D, 0, 0, 0, 0, 0,
+0x5A5E,0x5A5F,0x5A60, 0,0x5A61, 0,0x5A62, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5A63,0x5A64, 0, 0,0x5A65, 0,
+0x5A66, 0, 0,0x5A67, 0,0x5A68, 0, 0,
+ 0,0x5A69, 0, 0,0x5A6A, 0,0x5A6B, 0,
+0x5A6C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5A6E, 0,0x5A6F,0x5A70, 0,
+ 0, 0, 0, 0, 0,0x5A71,0x5A72, 0,
+0x5A73, 0, 0, 0,0x5A74, 0, 0,0x5A75,
+0x5A76,0x5A77, 0, 0,0x5A78,0x5A79, 0, 0,
+ 0, 0,0x5A7A, 0, 0, 0, 0,0x5A7B,
+0x5A7C, 0,0x5A7D, 0,0x5A7E, 0, 0, 0,
+ 0,0x5B21, 0, 0, 0, 0, 0,0x5B22,
+0x5B23, 0,0x5B24,0x5B25, 0, 0, 0, 0,
+ 0, 0,0x5B26,0x5B27, 0,0x5B28,0x5B29,0x5B2A,
+ 0,0x5B2B, 0, 0,0x5B2C, 0,0x5B2D, 0,
+ 0, 0, 0, 0, 0, 0,0x5B2E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5B2F, 0, 0, 0, 0,0x5B30, 0,
+ 0, 0,0x5B31, 0, 0,0x5B32,0x5B33, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5B34, 0,0x5B35,0x5B36, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5B37, 0, 0, 0,
+ 0, 0, 0, 0,0x5B38,0x5B39,0x5B3A,0x5B3B,
+0x5B3C,0x5B3D,0x5B3E, 0,0x5B3F,0x5B40, 0, 0,
+ 0,0x5B41, 0, 0,0x5B42, 0,0x5B43, 0,
+0x5B44,0x5B45,0x5B46, 0, 0, 0, 0,0x5B47,
+ 0,0x5B48, 0, 0,0x5B49, 0, 0, 0,
+0x5B4A, 0, 0, 0, 0,0x5B4B,0x5B4C,0x5B4D,
+ 0, 0,0x5B4E, 0, 0, 0,0x5B4F, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5B50,
+0x5B51, 0,0x5B52, 0, 0, 0, 0, 0,
+ 0,0x5B53,0x5B54,0x5B55, 0, 0, 0,0x5B56,
+ 0, 0, 0, 0, 0, 0,0x5B57,0x5B58,
+ 0, 0,0x5B59,0x5B5A, 0,0x5B5B, 0, 0,
+0x5B5C, 0, 0,0x5B5D,0x5B5E,0x5B5F, 0, 0,
+ 0, 0, 0,0x5B60,0x5B61, 0,0x5B62, 0,
+ 0, 0,0x5B63, 0,0x5B64, 0, 0, 0,
+ 0,0x5B65, 0,0x5B66, 0, 0, 0, 0,
+0x5B67, 0,0x5B68, 0,0x5B69, 0, 0,0x5B6A,
+0x7464, 0,0x5B6B,0x5B6C,0x5B6D, 0, 0, 0,
+ 0,0x5B6E, 0,0x5B70,0x5B71,0x5B72, 0, 0,
+ 0,0x5B73,0x5B6F,0x5B74,0x5B75,0x5B76, 0,0x5B77,
+0x5B78, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5B79, 0, 0, 0, 0,0x5B7A,0x5B7B,
+ 0,0x5B7C, 0,0x5B7D, 0, 0,0x5B7E, 0,
+ 0, 0, 0,0x5C21, 0,0x5C22, 0, 0,
+ 0, 0,0x5C23, 0,0x5C24, 0,0x5C25, 0,
+ 0,0x5C26,0x5C27,0x5C28,0x5C29, 0, 0,0x5C2A,
+ 0, 0,0x5C2B, 0, 0, 0,0x5C2C,0x5C2D,
+ 0,0x5C2E, 0,0x5C2F, 0,0x5C30, 0, 0,
+0x5C31,0x5C32, 0, 0, 0,0x5C33, 0, 0,
+ 0, 0,0x5C34, 0, 0, 0, 0, 0,
+ 0, 0,0x5C35, 0, 0, 0, 0, 0,
+ 0, 0,0x5C36, 0,0x5C37, 0, 0, 0,
+ 0,0x5C38};
+
+/* page 32 0x8898-0x89BC */
+static uint16 tab_uni_jisx021232[]={
+0x5C39, 0,0x5C3A,0x5C3B,0x5C3C, 0, 0,0x5C3D,
+0x5C3E, 0, 0, 0, 0, 0, 0, 0,
+0x5C3F, 0,0x5C40, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5C41, 0, 0,0x5C42,0x5C43, 0,
+0x5C44, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5C45,0x5C46,0x5C47,0x5C48,0x5C49, 0,
+ 0,0x5C4A,0x5C4B,0x5C4C, 0, 0, 0, 0,
+ 0, 0, 0,0x5C4D, 0, 0,0x5C4E, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5C4F,
+ 0, 0, 0, 0, 0, 0, 0,0x5C50,
+0x5C51,0x5C52, 0, 0, 0,0x5C53, 0,0x5C54,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5C55, 0, 0, 0, 0,0x5C56, 0,
+ 0, 0, 0, 0, 0,0x5C57,0x5C58,0x5C59,
+ 0, 0, 0, 0, 0,0x5C5A,0x5C5B, 0,
+0x5C5C,0x5C5D,0x5C5E, 0,0x5C5F, 0, 0, 0,
+0x5C60, 0, 0, 0, 0, 0,0x5C61,0x5C62,
+0x5C63, 0, 0, 0, 0, 0, 0, 0,
+0x5C64,0x5C65,0x5C66, 0, 0,0x5C67, 0, 0,
+ 0,0x5C68,0x5C69, 0, 0, 0,0x5C6A, 0,
+0x5C6B, 0,0x5C6C, 0, 0,0x5C6D,0x5C6E, 0,
+ 0,0x5C6F, 0, 0, 0, 0, 0,0x5C70,
+ 0, 0,0x5C71, 0, 0, 0, 0,0x5C72,
+ 0, 0,0x5C73,0x5C74,0x5C75, 0, 0, 0,
+ 0,0x5C76,0x5C77,0x5C78, 0, 0, 0, 0,
+ 0, 0, 0,0x5C79, 0, 0,0x5C7A, 0,
+0x5C7B, 0, 0,0x5C7C, 0,0x5C7D, 0, 0,
+ 0, 0,0x5C7E,0x5D21,0x5D22,0x5D23, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5D24, 0, 0, 0,0x5D25, 0, 0,
+0x5D26, 0, 0, 0,0x5D27,0x5D28, 0, 0,
+ 0, 0, 0,0x5D29,0x5D2A, 0, 0,0x5D2B,
+0x5D2C, 0, 0, 0, 0,0x5D2D, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5D2E, 0, 0, 0,0x5D2F,0x5D30,0x5D31,0x5D32,
+ 0, 0, 0, 0,0x5D33};
+
+/* page 33 0x89D4-0x8B9F */
+static uint16 tab_uni_jisx021233[]={
+0x5D34,0x5D35,0x5D36,0x5D37,0x5D38, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5D39, 0, 0, 0,0x5D3A, 0,0x5D3B,
+ 0,0x5D3C, 0, 0, 0,0x5D3D, 0,0x5D3E,
+ 0, 0,0x5D3F, 0, 0,0x5D40, 0, 0,
+ 0,0x5D41, 0,0x5D42, 0, 0, 0, 0,
+0x5D43,0x5D44, 0,0x5D45, 0, 0, 0, 0,
+ 0, 0, 0,0x5D46, 0,0x5D47,0x5D48, 0,
+0x5D49,0x5D4A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5D4B, 0,0x5D4C, 0,0x5D4D, 0,
+0x5D4E, 0,0x5D4F, 0, 0, 0, 0,0x5D50,
+0x5D51, 0, 0,0x5D52, 0, 0, 0, 0,
+ 0,0x5D53, 0,0x5D54, 0, 0, 0, 0,
+ 0,0x5D55,0x5D56, 0,0x5D57, 0, 0,0x5D58,
+ 0,0x5D59, 0,0x5D5A, 0,0x5D5B, 0, 0,
+ 0,0x5D5C,0x5D5D, 0, 0, 0, 0,0x5D5E,
+ 0, 0,0x5D5F,0x5D60,0x5D61, 0, 0, 0,
+0x5D62,0x5D63, 0, 0, 0,0x5D64, 0, 0,
+ 0,0x5D65, 0,0x5D66, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5D67,0x5D68,0x5D69, 0,0x5D6A,0x5D6B,0x5D6C,
+ 0, 0,0x5D6D,0x5D6E,0x5D6F, 0, 0,0x5D70,
+ 0, 0,0x5D71, 0, 0, 0, 0,0x5D72,
+ 0, 0, 0,0x5D73,0x5D74, 0,0x5D75, 0,
+ 0, 0,0x5D76,0x5D77, 0,0x5D78, 0, 0,
+ 0, 0, 0,0x5D79, 0, 0, 0, 0,
+ 0, 0, 0,0x5D7A, 0,0x5D7B, 0, 0,
+ 0, 0,0x5D7C,0x5D7D, 0, 0, 0,0x5D7E,
+ 0, 0,0x5E21,0x5E22, 0, 0, 0,0x5E23,
+ 0, 0,0x5E24, 0, 0, 0, 0,0x5E25,
+ 0, 0,0x5E26, 0,0x5E27,0x5E28,0x5E29, 0,
+ 0, 0, 0, 0, 0,0x5E2A, 0,0x5E2B,
+0x5E2C,0x5E2D, 0,0x5E2E, 0, 0, 0, 0,
+ 0,0x5E2F, 0,0x5E30, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5E31, 0, 0, 0,0x5E32, 0, 0, 0,
+0x5E33,0x5E34,0x5E35, 0, 0, 0, 0, 0,
+0x5E36, 0, 0,0x5E37, 0, 0, 0, 0,
+ 0,0x5E38,0x5E39, 0, 0, 0,0x5E3F,0x5E3A,
+ 0, 0, 0, 0, 0,0x5E3B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5E3C, 0,0x5E3D,0x5E3E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E40, 0, 0,0x5E41, 0, 0, 0,
+ 0, 0, 0,0x5E42, 0, 0, 0, 0,
+0x5E43, 0, 0, 0, 0, 0,0x5E44,0x5E45,
+0x5E46,0x5E47,0x5E48, 0,0x5E49, 0, 0, 0,
+ 0,0x5E4E, 0, 0, 0, 0,0x5E4A,0x5E4B,
+0x5E4C, 0, 0, 0, 0,0x5E4D, 0, 0,
+ 0, 0,0x5E4F, 0, 0, 0, 0,0x5E50,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E51, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5E52, 0,0x5E53,0x5E54, 0, 0,
+0x5E55, 0,0x5E56,0x7466, 0,0x5E57, 0, 0,
+0x5E58,0x5E59, 0, 0, 0, 0, 0,0x5E5A,
+ 0,0x5E5B, 0,0x5E5C, 0, 0, 0, 0,
+0x5E5D,0x5E5E, 0, 0, 0, 0, 0, 0,
+0x5E5F, 0,0x5E60,0x5E61};
+
+/* page 34 0x8C38-0x8CA4 */
+static uint16 tab_uni_jisx021234[]={
+0x5E62,0x5E63, 0, 0, 0,0x5E64,0x5E65, 0,
+ 0, 0, 0, 0, 0,0x5E66, 0,0x5E67,
+ 0,0x5E68, 0,0x5E69, 0, 0, 0,0x5E6A,
+ 0,0x5E6B, 0,0x5E6C,0x5E6D, 0, 0,0x5E6E,
+0x5E6F,0x5E72, 0,0x5E70, 0,0x5E71, 0, 0,
+ 0, 0, 0,0x5E73,0x5E74, 0,0x5E75, 0,
+0x5E76,0x5E77, 0, 0, 0,0x5E78, 0, 0,
+ 0, 0, 0,0x5E79, 0,0x5E7A,0x5E7B, 0,
+ 0, 0, 0,0x5E7C, 0, 0,0x5E7D, 0,
+ 0, 0, 0, 0, 0, 0,0x5E7E,0x5F21,
+ 0, 0, 0,0x5F22, 0, 0, 0, 0,
+0x5F23, 0,0x5F24,0x5F25, 0, 0, 0, 0,
+ 0,0x5F26, 0,0x5F27,0x5F28, 0, 0, 0,
+ 0, 0, 0, 0,0x5F29};
+
+/* page 35 0x8CB9-0x8D1B */
+static uint16 tab_uni_jisx021235[]={
+0x5F2A,0x5F2B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5F2C,0x5F2D, 0, 0,
+0x5F2E, 0,0x5F2F, 0, 0, 0,0x5F30, 0,
+ 0, 0, 0, 0,0x5F32,0x5F31, 0, 0,
+0x5F33, 0, 0, 0,0x5F34, 0, 0, 0,
+0x5F35, 0, 0, 0, 0, 0, 0,0x5F36,
+ 0, 0, 0,0x5F37, 0, 0,0x5F38,0x5F39,
+ 0,0x5F3A, 0,0x7467,0x5F3B, 0,0x5F3C,0x5F3D,
+ 0, 0, 0, 0, 0,0x5F3E,0x5F3F, 0,
+0x5F40, 0,0x5F41, 0, 0, 0, 0, 0,
+0x5F42, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F43, 0, 0, 0, 0,0x5F44, 0,
+ 0, 0,0x5F45};
+
+/* page 36 0x8D65-0x8F65 */
+static uint16 tab_uni_jisx021236[]={
+0x5F46, 0, 0, 0,0x5F47, 0, 0,0x5F48,
+ 0,0x5F49, 0, 0, 0, 0, 0, 0,
+ 0,0x7468, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5F4A, 0, 0,0x5F4B, 0,0x5F4C,
+ 0, 0, 0,0x5F4D, 0, 0, 0, 0,
+0x5F4E, 0, 0,0x5F4F,0x5F50, 0, 0, 0,
+0x5F51, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F52,0x5F53,0x5F54, 0, 0, 0, 0,
+ 0,0x5F55, 0, 0, 0, 0,0x5F56,0x5F57,
+ 0, 0,0x5F58, 0, 0,0x5F59, 0, 0,
+0x5F5A, 0,0x5F5B, 0,0x5F5C, 0,0x5F5D,0x5F6F,
+ 0, 0, 0,0x5F5E, 0, 0, 0, 0,
+0x5F5F,0x5F60,0x5F61,0x5F62, 0,0x5F63, 0, 0,
+ 0,0x5F64, 0, 0,0x5F65, 0, 0,0x5F66,
+0x5F67, 0,0x5F68, 0,0x5F69, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5F6A,
+0x5F6B, 0,0x5F6C, 0, 0, 0, 0,0x5F6D,
+ 0, 0, 0,0x5F6E,0x5F70,0x5F71, 0,0x5F72,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5F73, 0, 0, 0,0x5F74, 0, 0,0x5F75,
+0x5F76,0x5F77, 0, 0, 0, 0,0x5F78, 0,
+ 0, 0, 0, 0,0x5F79, 0, 0,0x5F7A,
+ 0,0x5F7B, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5F7C,0x5F7D,0x5F7E,0x6021, 0,
+ 0,0x6022,0x6023, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6024, 0,0x6025, 0,
+ 0,0x6026,0x6027,0x6028,0x6029, 0, 0, 0,
+0x602A, 0, 0,0x602B,0x602C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x602D, 0,
+0x602E,0x602F,0x6030, 0, 0, 0, 0,0x6031,
+ 0, 0, 0, 0, 0, 0,0x6032,0x6033,
+0x6034,0x6035, 0, 0,0x6036,0x6037, 0, 0,
+ 0, 0, 0, 0,0x6038, 0, 0,0x6039,
+0x603A, 0,0x603B,0x603C,0x603D, 0, 0, 0,
+ 0, 0, 0, 0,0x603E,0x603F,0x6040, 0,
+ 0, 0, 0, 0, 0,0x6041,0x6042, 0,
+ 0, 0, 0, 0,0x6043, 0, 0, 0,
+ 0, 0, 0,0x6044, 0,0x6045, 0, 0,
+0x6046, 0, 0, 0, 0,0x6047,0x6048, 0,
+0x6049,0x604A, 0, 0, 0,0x604B, 0, 0,
+ 0, 0,0x604C, 0,0x604D, 0, 0, 0,
+0x604E,0x604F, 0, 0, 0, 0,0x6050, 0,
+0x6051, 0, 0, 0, 0,0x6052,0x6053, 0,
+ 0, 0, 0,0x6054,0x6055, 0,0x6056,0x6057,
+ 0, 0,0x6058, 0, 0, 0, 0, 0,
+ 0, 0,0x6059, 0,0x605A, 0, 0,0x605B,
+ 0, 0, 0, 0, 0, 0, 0,0x605C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x605D, 0, 0, 0, 0,
+0x6064,0x605E, 0,0x605F,0x6060, 0, 0, 0,
+ 0, 0,0x6061, 0,0x6062,0x6063, 0, 0,
+ 0, 0, 0,0x6065, 0,0x6066, 0, 0,
+ 0, 0,0x6067,0x6068, 0, 0, 0, 0,
+ 0, 0,0x6069,0x606A, 0, 0, 0, 0,
+ 0,0x606B,0x606C,0x606D, 0, 0, 0, 0,
+ 0,0x606E, 0,0x606F,0x6070, 0,0x6071, 0,
+0x6072, 0,0x6073,0x6074, 0, 0, 0,0x6075,
+0x6076,0x6077, 0, 0, 0, 0, 0,0x6078,
+0x6079,0x607A,0x607B, 0, 0,0x607C, 0, 0,
+ 0, 0, 0,0x607D,0x607E, 0,0x6121, 0,
+ 0, 0,0x6122, 0, 0, 0, 0, 0,
+ 0, 0,0x6123, 0,0x6124,0x6125,0x6126,0x6127,
+0x6128, 0, 0,0x6129, 0, 0, 0, 0,
+0x612A,0x612B, 0, 0, 0, 0, 0, 0,
+0x612C};
+
+/* page 37 0x8F9D-0x9484 */
+static uint16 tab_uni_jisx021237[]={
+0x612D, 0, 0,0x612E,0x612F, 0, 0,0x6130,
+0x6131,0x6132, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6133,0x6134, 0,0x6135, 0, 0, 0, 0,
+ 0,0x6136, 0,0x6137,0x6138, 0, 0, 0,
+ 0,0x6139, 0, 0, 0,0x613A,0x613B, 0,
+0x613C, 0, 0,0x613D, 0,0x613E,0x613F, 0,
+0x6140, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6141, 0, 0,0x6142,0x6143,
+ 0, 0, 0,0x6144, 0, 0, 0, 0,
+ 0,0x6145, 0, 0,0x6146, 0, 0, 0,
+0x6147,0x6148, 0, 0, 0, 0,0x6149, 0,
+ 0,0x614A, 0, 0, 0,0x614B, 0,0x614C,
+ 0, 0, 0,0x614D, 0, 0, 0,0x614E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x614F, 0, 0,0x6150, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6151,0x6152,0x6154, 0,0x6155,
+0x6156, 0,0x6153, 0, 0, 0,0x6157,0x6158,
+ 0, 0,0x6159, 0, 0, 0, 0, 0,
+ 0, 0,0x615A, 0, 0, 0,0x615B,0x615C,
+ 0, 0, 0, 0, 0, 0, 0,0x615D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x615E, 0,
+0x615F, 0, 0, 0, 0,0x6160, 0, 0,
+ 0,0x6161,0x6162, 0, 0, 0, 0,0x6163,
+ 0, 0, 0,0x6164, 0, 0, 0,0x6165,
+ 0, 0, 0, 0,0x6166, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6167, 0, 0,0x6168, 0, 0,0x6169,0x616A,
+ 0,0x616B, 0,0x616C, 0, 0, 0, 0,
+0x616D, 0,0x616E,0x616F,0x6170, 0,0x6171, 0,
+ 0, 0, 0,0x6172,0x6173,0x6174, 0, 0,
+0x6175, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6176, 0,0x6177,0x6178,0x6179,
+ 0,0x617A, 0, 0, 0, 0, 0, 0,
+0x617B,0x617D, 0, 0, 0, 0,0x617E,0x6221,
+0x6222, 0,0x6223,0x6224, 0, 0, 0,0x617C,
+ 0, 0, 0, 0, 0,0x622D, 0, 0,
+0x6225, 0,0x6226,0x6227,0x6228, 0, 0,0x6229,
+0x622A,0x746C,0x622B, 0, 0, 0, 0, 0,
+0x622C, 0, 0, 0, 0, 0,0x622F, 0,
+ 0, 0,0x6230,0x6231, 0, 0, 0,0x6232,
+ 0,0x622E, 0, 0, 0, 0, 0, 0,
+ 0,0x6233,0x6234,0x6235, 0, 0, 0,0x6236,
+0x6237,0x6238, 0,0x6239, 0, 0, 0, 0,
+0x623A, 0, 0,0x623B, 0, 0, 0,0x623C,
+0x746E,0x623D,0x623E,0x623F, 0,0x6240, 0,0x6241,
+ 0,0x6242, 0,0x6243, 0,0x6245,0x6246, 0,
+0x6244, 0,0x6247, 0,0x6248, 0, 0, 0,
+ 0,0x6249,0x624A, 0,0x624B, 0, 0,0x624C,
+ 0,0x624D,0x624E, 0,0x624F,0x6250, 0,0x6251,
+0x6252, 0, 0, 0, 0, 0,0x6253, 0,
+ 0, 0,0x6254,0x6255, 0, 0, 0, 0,
+ 0, 0,0x6256, 0, 0, 0,0x6257, 0,
+ 0, 0,0x6258, 0,0x6259,0x625A,0x625B, 0,
+ 0, 0, 0, 0,0x625C, 0, 0,0x625D,
+ 0, 0,0x625E, 0, 0, 0, 0, 0,
+0x625F, 0, 0, 0, 0, 0, 0,0x6260,
+ 0, 0, 0, 0,0x6261,0x6262,0x6263, 0,
+ 0, 0, 0, 0,0x6264, 0,0x6265, 0,
+0x6266,0x6267, 0, 0, 0,0x6268, 0, 0,
+ 0,0x6269, 0, 0,0x626A, 0,0x626B,0x626C,
+0x626D, 0, 0,0x626E, 0, 0, 0, 0,
+ 0,0x626F, 0, 0,0x6270, 0, 0, 0,
+ 0,0x6271, 0,0x6272, 0, 0, 0,0x6273,
+0x6274,0x6275, 0,0x6276,0x6277,0x6278,0x6279, 0,
+ 0,0x627A, 0, 0, 0, 0,0x627B,0x627C,
+0x627D, 0,0x627E, 0, 0,0x6321,0x6322, 0,
+0x6323, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6324,0x6325,
+ 0, 0,0x6326, 0,0x6327,0x6328, 0, 0,
+ 0,0x6329, 0, 0, 0, 0, 0,0x632A,
+0x632B, 0, 0, 0,0x632C,0x632D, 0,0x632E,
+0x632F,0x6330,0x6331,0x6332,0x6333, 0, 0, 0,
+ 0, 0,0x6334, 0,0x6335, 0,0x6336, 0,
+0x6337, 0, 0,0x6338,0x6339, 0, 0,0x633A,
+0x633B,0x633C,0x633D, 0,0x633E,0x633F, 0,0x6340,
+ 0, 0, 0,0x6341, 0,0x6342,0x6343, 0,
+ 0,0x6344, 0,0x6345, 0, 0, 0,0x6346,
+0x6347, 0, 0, 0, 0, 0,0x6348,0x6349,
+0x634A,0x634B, 0,0x634C, 0, 0, 0, 0,
+ 0,0x634D,0x634E,0x634F, 0, 0,0x6350, 0,
+0x6351,0x6352, 0,0x6353,0x6354,0x6355, 0,0x6356,
+ 0,0x6357, 0,0x6358, 0,0x6359,0x635A, 0,
+ 0,0x635B,0x635C, 0, 0,0x635D, 0, 0,
+0x635E,0x635F,0x6360, 0,0x6361, 0, 0, 0,
+ 0, 0, 0,0x6362,0x6363, 0, 0,0x6364,
+0x6365, 0, 0,0x6366,0x6367, 0, 0, 0,
+0x6368, 0,0x6369,0x636A,0x636B, 0, 0, 0,
+ 0,0x636C,0x636D,0x636E, 0, 0, 0, 0,
+0x636F,0x6370,0x6371,0x6372,0x6373, 0,0x6374,0x6375,
+0x6376, 0,0x6377, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6378,0x6379,0x637A, 0, 0,
+0x637B,0x637C, 0, 0, 0,0x637D, 0, 0,
+ 0, 0,0x637E, 0,0x6421, 0, 0, 0,
+ 0, 0,0x6422,0x6423, 0, 0, 0,0x6424,
+0x6425, 0,0x6426,0x6427, 0, 0,0x6428, 0,
+ 0, 0,0x6429, 0, 0,0x642A, 0, 0,
+ 0,0x642B, 0,0x642C, 0,0x642D,0x642E,0x642F,
+0x6430, 0,0x6431,0x6432,0x6433,0x6434,0x6435, 0,
+0x6436,0x6437,0x6438,0x6439, 0, 0,0x643A,0x643B,
+0x643C,0x643D, 0,0x643E, 0, 0,0x643F, 0,
+0x6440, 0,0x6441,0x6442,0x6443, 0, 0,0x6444,
+0x6445, 0,0x6446,0x6447,0x6448, 0,0x6449, 0,
+0x644A, 0,0x644B,0x644C, 0, 0, 0,0x644D,
+ 0,0x644E, 0,0x644F, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6450, 0,0x6451, 0,
+ 0, 0,0x6452,0x6453, 0,0x6454, 0, 0,
+ 0, 0, 0,0x6455, 0, 0, 0, 0,
+0x6456, 0, 0, 0,0x6457, 0, 0,0x6458,
+0x6459, 0, 0, 0, 0, 0, 0,0x645A,
+0x645B,0x645C,0x645D, 0,0x645E, 0, 0,0x645F,
+0x6460, 0,0x6461, 0,0x6462,0x6463, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6464,0x6465,
+ 0,0x6466,0x6467, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6468,0x6469,0x646A, 0, 0, 0,
+ 0, 0, 0,0x646B,0x646C,0x646D, 0, 0,
+0x646E, 0,0x646F,0x6470, 0,0x6471, 0, 0,
+ 0,0x6472, 0, 0, 0, 0, 0,0x6473,
+0x6474, 0,0x6475, 0,0x6476,0x6477, 0, 0,
+0x6478, 0,0x6479,0x647A,0x647B, 0,0x647C,0x647D,
+ 0,0x647E, 0, 0, 0,0x6521, 0, 0,
+0x6522, 0,0x6523,0x6524,0x6525,0x6526, 0, 0,
+ 0, 0, 0,0x6527, 0,0x6528,0x6529, 0,
+0x652A, 0,0x652B, 0, 0,0x652C, 0, 0,
+0x652D, 0, 0,0x652E, 0, 0,0x652F, 0,
+ 0,0x6530, 0, 0,0x6531, 0,0x6532,0x6533,
+ 0,0x6534, 0,0x6535,0x653B, 0,0x6536, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x6537,
+0x6538,0x6539, 0, 0, 0,0x653A, 0, 0,
+ 0, 0, 0, 0,0x653C, 0, 0,0x653D,
+0x653E,0x653F,0x6540, 0,0x6541,0x6542,0x6543,0x6544,
+0x6545, 0, 0, 0, 0, 0,0x6546, 0,
+ 0, 0, 0, 0,0x6547, 0, 0,0x6548,
+ 0,0x6549,0x654A, 0, 0,0x654B, 0, 0,
+ 0,0x654C,0x654D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x654F,0x6550,0x654E,0x6551,0x6552, 0,
+0x6553, 0, 0, 0,0x6554,0x6555, 0,0x6556,
+ 0, 0, 0,0x6557,0x6558, 0, 0, 0,
+0x6559,0x655A,0x655B, 0, 0, 0, 0, 0,
+0x655C,0x655D,0x655E, 0, 0, 0, 0, 0,
+ 0, 0,0x655F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6560,0x6561, 0,0x6562,0x6563,0x6564,0x6565,
+ 0, 0, 0, 0, 0, 0,0x6566, 0,
+0x6568, 0,0x6567, 0, 0, 0,0x6569, 0,
+0x656A, 0, 0,0x656B, 0,0x656C, 0,0x656D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x656E, 0, 0, 0,0x656F, 0, 0,0x6570,
+ 0, 0,0x6571, 0,0x6572, 0,0x6573, 0,
+ 0, 0, 0,0x6574, 0, 0,0x6575, 0,
+0x6576,0x6577,0x6578, 0,0x6579,0x657A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x657C,0x657B
+};
+
+/* page 38 0x9578-0x95E6 */
+static uint16 tab_uni_jisx021238[]={
+0x657D,0x657E, 0, 0, 0, 0,0x6621, 0,
+ 0, 0, 0, 0,0x6622, 0, 0, 0,
+0x6623, 0, 0, 0,0x6624,0x6625,0x6626, 0,
+ 0, 0,0x7471, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6627,0x6628,0x6629,
+ 0,0x662A, 0, 0, 0, 0,0x662B, 0,
+ 0,0x662C, 0,0x662D,0x662E, 0, 0, 0,
+ 0, 0, 0, 0,0x662F, 0,0x6630, 0,
+ 0, 0,0x6631, 0, 0,0x6632, 0,0x6633,
+ 0, 0, 0, 0, 0, 0,0x6634, 0,
+0x6635,0x6636, 0,0x6637, 0, 0, 0, 0,
+0x6638,0x6639,0x663A,0x663B, 0, 0, 0, 0,
+ 0,0x663C,0x663D, 0, 0,0x663E,0x663F,0x6640,
+0x6641, 0, 0, 0,0x6642, 0,0x6643};
+
+/* page 39 0x961D-0x986C */
+static uint16 tab_uni_jisx021239[]={
+0x6644,0x6645, 0, 0, 0,0x6646, 0,0x6647,
+0x6648,0x6649, 0, 0, 0, 0, 0,0x664A,
+ 0, 0, 0, 0,0x664B, 0,0x664C, 0,
+ 0, 0,0x664D,0x664E,0x664F,0x6650, 0,0x6651,
+0x6652, 0, 0, 0,0x6653, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6654, 0,0x6655,
+ 0,0x6656,0x6657,0x6658, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6659, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x665A, 0, 0, 0, 0, 0,0x665B,
+ 0, 0, 0, 0, 0, 0,0x665C,0x665D,
+ 0,0x665E,0x665F, 0,0x6660,0x6661,0x6662,0x6663,
+ 0, 0, 0, 0,0x6664, 0, 0, 0,
+ 0, 0, 0, 0,0x6665, 0, 0, 0,
+ 0,0x6666, 0, 0, 0,0x6667, 0, 0,
+0x6668, 0,0x6669, 0, 0, 0, 0,0x666A,
+0x666B,0x666C, 0, 0,0x666D, 0, 0, 0,
+ 0,0x666E,0x666F, 0, 0, 0,0x6670, 0,
+ 0, 0, 0, 0, 0,0x6671, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6672, 0, 0,
+ 0, 0, 0, 0, 0,0x6673, 0, 0,
+ 0, 0, 0,0x6675, 0,0x6676, 0, 0,
+0x6677,0x6678,0x6679, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x667A, 0, 0, 0,
+ 0, 0,0x667B, 0,0x667C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x667D, 0, 0,
+ 0, 0, 0, 0, 0,0x667E,0x6721, 0,
+0x6722, 0, 0, 0,0x6723, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6724,0x6725, 0,
+0x6726, 0, 0, 0,0x6727,0x6728,0x6729, 0,
+ 0, 0, 0,0x672A, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x672B, 0,0x672C, 0,
+ 0, 0, 0, 0, 0, 0,0x7474, 0,
+ 0, 0, 0, 0,0x672D, 0,0x672E, 0,
+ 0, 0, 0, 0, 0,0x672F, 0, 0,
+0x7475,0x6730,0x6731, 0,0x7476, 0, 0, 0,
+0x6732, 0,0x6733,0x6734, 0,0x6735,0x6736, 0,
+ 0, 0, 0, 0, 0, 0,0x6737, 0,
+ 0, 0,0x6738, 0, 0,0x6739, 0, 0,
+ 0,0x673A, 0, 0, 0, 0,0x673B, 0,
+ 0,0x673C,0x673D,0x673E, 0, 0,0x673F, 0,
+0x6740, 0,0x6741,0x6742, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6743, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6744,0x6745,0x6746, 0,0x6747,0x6748, 0, 0,
+ 0,0x6749,0x674A, 0, 0,0x674B, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x674C,
+ 0,0x674D, 0, 0,0x674E,0x674F, 0, 0,
+0x6750,0x6751, 0,0x6752,0x6753,0x6754, 0,0x6755,
+ 0,0x6756,0x6757, 0,0x6758, 0, 0,0x6759,
+0x675A, 0,0x675B, 0,0x675C,0x675D, 0,0x675E,
+0x675F,0x6760, 0,0x6761,0x6762, 0, 0,0x6763,
+ 0, 0,0x6764,0x6765,0x6766, 0,0x676A, 0,
+0x6767,0x6768, 0,0x6769,0x676B, 0, 0,0x676C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x676D, 0,0x676E, 0, 0,0x676F,
+ 0, 0,0x6770,0x6771, 0,0x6772, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6773, 0, 0,0x6774, 0, 0,
+0x6776,0x6777, 0, 0, 0, 0, 0,0x6778,
+ 0,0x6779, 0, 0,0x6775, 0, 0,0x677A,
+ 0,0x677B, 0,0x677C, 0, 0,0x677D, 0,
+0x6828,0x677E, 0, 0, 0, 0,0x6821, 0,
+ 0,0x6822,0x6823,0x6824, 0,0x6825,0x6826, 0,
+0x6827, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6829, 0, 0, 0, 0, 0,0x682A,
+ 0, 0,0x682B, 0, 0,0x682C, 0, 0,
+ 0, 0, 0, 0,0x682D,0x682E,0x682F, 0,
+ 0,0x6830,0x6831, 0,0x6832,0x6833, 0, 0,
+ 0, 0, 0, 0, 0,0x6834,0x6835, 0,
+0x6836,0x6837, 0, 0, 0,0x6838, 0,0x6839
+};
+
+/* page 40 0x98AB-0x98CC */
+static uint16 tab_uni_jisx021240[]={
+0x683A, 0,0x683B,0x683C, 0,0x683D, 0, 0,
+ 0,0x683E, 0, 0,0x683F,0x6840, 0,0x6841,
+0x6842, 0, 0, 0,0x6843, 0, 0,0x6844,
+ 0, 0,0x6845, 0, 0,0x6846, 0, 0,
+ 0,0x6847};
+
+/* page 41 0x98E1-0x9960 */
+static uint16 tab_uni_jisx021241[]={
+0x6848, 0,0x6849, 0,0x684A,0x684B,0x684C, 0,
+ 0,0x684D, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x684E, 0, 0,0x684F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6850, 0, 0, 0, 0,0x6851,0x6852,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6853, 0, 0, 0,0x6854,0x6855,0x6856, 0,
+ 0,0x6857,0x6858,0x6859, 0, 0,0x685A, 0,
+ 0,0x685B, 0, 0, 0,0x685C,0x685D, 0,
+ 0, 0,0x685E, 0, 0, 0, 0, 0,
+0x685F,0x6860,0x6861,0x6862,0x6863, 0, 0, 0,
+0x6864,0x6865,0x6866,0x6867, 0, 0, 0,0x6868,
+0x6869, 0, 0, 0, 0,0x686A,0x686B,0x686C,
+ 0, 0, 0, 0,0x686D,0x686E, 0, 0,
+ 0, 0, 0,0x686F, 0, 0, 0,0x6870,
+0x6871, 0,0x6872,0x6873, 0,0x6874,0x6875,0x6876
+};
+
+/* page 42 0x999B-0x9A5D */
+static uint16 tab_uni_jisx021242[]={
+0x6877, 0,0x6878,0x747A,0x6879, 0, 0, 0,
+ 0, 0, 0,0x687A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x687B,0x687C,0x687D,
+ 0, 0,0x687E, 0, 0, 0,0x6921,0x6922,
+ 0, 0,0x6923, 0,0x6924, 0, 0, 0,
+0x6925, 0, 0, 0, 0, 0,0x6926, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6927,0x6928, 0, 0, 0, 0,0x6929,0x692A,
+ 0,0x692B, 0,0x692C, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x692D, 0, 0,0x692E,
+0x692F,0x6930, 0, 0, 0,0x6931, 0, 0,
+ 0,0x6932,0x6933, 0, 0, 0,0x6934, 0,
+ 0, 0,0x6935,0x6936, 0, 0, 0,0x6937,
+0x6938,0x6939, 0, 0, 0, 0, 0, 0,
+0x693A,0x693B, 0, 0, 0,0x693C,0x693D, 0,
+ 0, 0, 0,0x693E, 0, 0, 0, 0,
+ 0, 0, 0,0x693F, 0,0x6940, 0,0x6941,
+0x6942,0x6943, 0, 0,0x6944, 0, 0, 0,
+ 0, 0,0x6945,0x6946, 0, 0, 0, 0,
+0x6947, 0,0x6948,0x6949, 0,0x694A, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x694C, 0,
+ 0,0x694D, 0, 0,0x694B, 0, 0,0x694E,
+0x694F,0x6950, 0,0x6951, 0, 0,0x6952, 0,
+ 0,0x6953, 0,0x6954, 0, 0, 0, 0,
+ 0, 0,0x6955};
+
+/* page 43 0x9AAA-0x9C7B */
+static uint16 tab_uni_jisx021243[]={
+0x6956, 0,0x6957, 0,0x6958,0x6959, 0, 0,
+0x695A, 0,0x695B,0x695C,0x695D, 0, 0,0x695E,
+ 0,0x695F, 0, 0,0x6960,0x6961, 0,0x6962,
+ 0,0x6963, 0, 0,0x6964, 0,0x6965, 0,
+ 0, 0, 0, 0,0x6966, 0,0x6967, 0,
+0x6968, 0, 0,0x6969,0x696A,0x696B, 0,0x747B,
+ 0,0x696C,0x696D, 0, 0, 0,0x696E, 0,
+ 0, 0,0x696F,0x6970, 0,0x6971, 0,0x6972,
+ 0, 0,0x6973, 0, 0, 0, 0, 0,
+0x6974,0x6975, 0,0x6976, 0, 0, 0,0x6977,
+0x6978, 0, 0,0x6979, 0,0x697A,0x697B,0x697C,
+0x697D,0x697E,0x6A21,0x6A22, 0, 0,0x6A23,0x6A24,
+ 0,0x6A25,0x6A26,0x6A27,0x6A28, 0,0x6A29, 0,
+0x6A2A, 0, 0, 0,0x6A2B, 0, 0,0x6A2C,
+ 0,0x6A2D,0x6A2E, 0, 0, 0,0x6A2F, 0,
+ 0, 0, 0, 0,0x6A30, 0, 0, 0,
+ 0,0x6A31, 0,0x6A32, 0, 0, 0, 0,
+ 0,0x6A33,0x6A34,0x6A35, 0,0x6A36, 0,0x6A37,
+0x6A38, 0, 0,0x6A39, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6A3A, 0,
+ 0,0x6A3B,0x6A3C, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6A3D,0x6A3E,0x6A3F, 0, 0,
+ 0,0x6A40, 0, 0,0x6A41, 0, 0,0x6A42,
+ 0,0x6A43, 0,0x6A44,0x6A45, 0,0x6A46, 0,
+0x6A47,0x6A48,0x6A49,0x6A4A,0x6A4B, 0, 0, 0,
+0x747C,0x6A4C, 0,0x6A4D, 0,0x6A4E,0x6A4F,0x6A50,
+ 0, 0, 0, 0, 0,0x6A51,0x6A52, 0,
+ 0, 0,0x6A53,0x6A54,0x6A55,0x6A56, 0,0x6A57,
+0x6A58,0x6A59, 0,0x6A5A, 0,0x6A5B,0x6A5C, 0,
+ 0, 0,0x6A5D, 0, 0, 0, 0, 0,
+0x6A5E, 0, 0,0x6A5F,0x6A60, 0, 0, 0,
+ 0, 0, 0, 0,0x6A61,0x6A62, 0,0x6A63,
+ 0, 0,0x6A64, 0, 0, 0,0x6A65,0x6A66,
+0x6A67, 0, 0, 0, 0,0x6A68,0x6A69, 0,
+ 0,0x6A6A,0x6A6B, 0,0x6A6C,0x6A6D, 0,0x6A6E,
+ 0, 0, 0, 0, 0,0x6A6F,0x6A70, 0,
+ 0, 0, 0, 0,0x6A71, 0,0x6A72, 0,
+ 0, 0, 0, 0, 0,0x6A73,0x6A74, 0,
+ 0, 0, 0,0x6A75, 0,0x6A76, 0, 0,
+ 0, 0, 0,0x6A77, 0,0x6A78, 0, 0,
+0x6A79,0x6A7A, 0, 0, 0,0x6A7B, 0, 0,
+ 0,0x6A7C, 0, 0, 0,0x6A7D,0x6A7E,0x6B21,
+0x6B22, 0, 0,0x6B23, 0,0x6B24,0x6B25, 0,
+0x6B26, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B27, 0, 0, 0,0x6B28, 0,0x6B29,
+ 0, 0, 0, 0,0x6B2A, 0,0x6B2B,0x6B2C,
+0x6B2D, 0,0x6B2E, 0,0x6B2F, 0, 0, 0,
+0x6B30,0x6B31, 0, 0,0x6B32,0x6B33,0x6B34,0x6B35,
+0x6B36, 0, 0, 0, 0, 0, 0,0x6B37,
+ 0, 0, 0,0x6B38,0x6B39,0x6B3A, 0, 0,
+ 0, 0, 0,0x6B3B, 0, 0, 0,0x6B3C,
+ 0,0x6B3D,0x6B3E,0x6B3F, 0, 0, 0,0x6B40,
+0x6B41, 0, 0, 0,0x6B42,0x6B43,0x6B44, 0,
+ 0,0x6B45,0x6B46, 0,0x6B47, 0,0x6B48, 0,
+ 0,0x6B49,0x6B50,0x6B4A,0x6B4B,0x6B4C, 0, 0,
+ 0,0x6B4D, 0, 0, 0, 0,0x6B52,0x6B4E,
+0x6B4F,0x6B51, 0, 0,0x6B53, 0,0x6B54, 0,
+0x6B55, 0, 0,0x6B56, 0,0x6B57, 0, 0,
+ 0,0x6B58};
+
+/* page 44 0x9CE6-0x9E1D */
+static uint16 tab_uni_jisx021244[]={
+0x6B59, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6B5A, 0, 0, 0,
+ 0,0x6B5B, 0,0x6B5C, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6B5E, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6B5D, 0, 0,
+ 0, 0, 0,0x6B5F, 0, 0, 0, 0,
+ 0,0x6B60,0x6B61, 0, 0, 0,0x6B62,0x6B63,
+0x6B64, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B65,0x6B66, 0,0x6B67,0x6B68,0x6B69, 0,
+ 0, 0, 0, 0,0x6B6A, 0,0x6B6B,0x6B6D,
+ 0, 0, 0, 0,0x6B6E,0x6B6F, 0,0x6B6C,
+ 0,0x6B70, 0, 0,0x6B71, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6B72,0x6B73, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6B74, 0, 0,0x6B76,0x6B75, 0,0x6B77,
+ 0, 0, 0,0x6B78,0x6B79,0x6B7A, 0, 0,
+ 0, 0,0x6B7B, 0, 0, 0, 0, 0,
+0x6B7C,0x6B7D, 0, 0, 0,0x6B7E,0x6C21, 0,
+0x6C22, 0, 0, 0, 0,0x6C23,0x6C24, 0,
+0x6C25, 0, 0, 0,0x6C26, 0, 0,0x6C27,
+0x6C28, 0, 0, 0,0x6C29,0x6C2A, 0,0x6C2B,
+0x6C2C,0x6C2D,0x6C2E, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x6C2F, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6C30, 0,0x6C31, 0,
+0x6C32, 0, 0,0x6C33, 0, 0, 0,0x6C34,
+ 0, 0, 0,0x6C35, 0, 0,0x6C36, 0,
+ 0,0x6C37, 0, 0, 0,0x6C38, 0, 0,
+ 0,0x6C39, 0,0x6C3A,0x6C3B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6C3C,0x6C3D,
+0x6C3E,0x6C3F, 0, 0,0x6C40, 0, 0, 0,
+0x6C41,0x6C42,0x6C43, 0, 0, 0, 0,0x6C44,
+ 0,0x6C45, 0,0x6C46, 0,0x6C47, 0, 0,
+0x6C48, 0,0x6C49, 0, 0,0x6C4A,0x6C4B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x6C4C, 0, 0, 0,0x6C4E, 0, 0, 0,
+ 0,0x6C4F, 0, 0,0x6C4D, 0, 0, 0,
+0x6C50, 0,0x6C51,0x6C52,0x6C53, 0, 0,0x6C54,
+0x6C55, 0, 0,0x6C56, 0, 0,0x6C57,0x6C58
+};
+
+/* page 45 0x9E7A-0x9FA5 */
+static uint16 tab_uni_jisx021245[]={
+0x6C59,0x6C5A,0x6C5B, 0, 0, 0,0x6C5C, 0,
+0x6C5D,0x6C5E,0x6C5F,0x6C60, 0,0x6C61, 0, 0,
+ 0, 0, 0, 0,0x6C62,0x6C63, 0, 0,
+ 0, 0, 0, 0,0x6C64, 0,0x6C65, 0,
+ 0,0x6C66, 0, 0,0x6C67, 0, 0, 0,
+ 0, 0,0x6C68, 0, 0, 0,0x6C69, 0,
+ 0, 0,0x6C6A, 0,0x6C6B,0x6C6C,0x6C6D, 0,
+ 0,0x6C6E,0x6C6F,0x6C70, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x6C71, 0,0x6C72, 0,
+ 0,0x6C73, 0, 0, 0, 0, 0,0x747E,
+ 0, 0, 0,0x6C74, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C75, 0, 0,
+ 0, 0,0x6C76, 0, 0,0x6C77, 0, 0,
+ 0, 0,0x6C78,0x6C79,0x6C7A, 0,0x6C7B,0x6C7C,
+0x6C7D, 0, 0,0x6C7E, 0, 0,0x6D21, 0,
+ 0, 0, 0, 0, 0,0x6D22, 0, 0,
+0x6D23,0x6D24, 0, 0, 0, 0, 0,0x6D25,
+ 0, 0, 0, 0, 0,0x6D26,0x6D27,0x6D28,
+0x6D29, 0,0x6D2A, 0,0x6D2B,0x6D2C, 0,0x6D2D,
+0x6D2E,0x6D2F, 0, 0, 0,0x6D30, 0, 0,
+0x6D31, 0, 0, 0,0x6D32, 0, 0, 0,
+0x6D33,0x6D34, 0, 0, 0,0x6D35, 0,0x6D36,
+0x6D37, 0,0x6D38, 0, 0,0x6D39, 0,0x6D3A,
+0x6D3B, 0,0x6D3C,0x6D3D, 0,0x6D3E, 0,0x6D3F,
+ 0,0x6D40,0x6D41,0x6D42,0x6D43,0x6D44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6D45, 0,0x6D46,0x6D47,0x6D48,0x6D49, 0,
+0x6D4A, 0, 0,0x6D4B,0x6D4C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x6D4D,0x6D4E,
+ 0, 0, 0,0x6D4F,0x6D50,0x6D51,0x6D52,0x6D53,
+ 0,0x6D54, 0,0x6D55, 0, 0, 0, 0,
+0x6D56, 0, 0,0x6D57, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6D58,0x6D59,0x6D5A,
+0x6D5B, 0,0x6D5C, 0,0x6D5D,0x6D5E, 0, 0,
+ 0, 0, 0, 0,0x6D5F, 0, 0,0x6D60,
+0x6D61,0x6D62, 0,0x6D63};
+
+/* page 46 0xF929-0xF929 */
+static uint16 tab_uni_jisx021246[]={
+0x7445};
+
+/* page 47 0xF9DC-0xF9DC */
+static uint16 tab_uni_jisx021247[]={
+0x7472};
+
+/* page 48 0xFA00-0xFA2D */
+static uint16 tab_uni_jisx021248[]={
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7434,0x7437,
+0x7438,0x743D,0x7444,0x7447,0x7448,0x744E,0x744F,0x7453,
+0x7455,0x7456,0x7457,0x7458,0x745A,0x745B,0x745E,0x7460,
+0x7462,0x7463,0x7465,0x7469,0x746A,0x746B,0x746D,0x746F,
+0x7470,0x7473,0x7477,0x7478,0x7479,0x747D};
+
+/* page 49 0xFF00-0XFF07 */
+static uint16 tab_uni_jisx021249[]={
+ 0, 0,0x742A, 0, 0, 0, 0,0x7429};
+
+/* page 50 0xFFE4-0xFFE4 */
+static uint16 tab_uni_jisx021250[]={
+0x2243};
+
+static int
+my_uni_jisx0212_onechar(int code){
+ if ((code>=0x007E)&&(code<=0x007E))
+ return(tab_uni_jisx02120[code-0x007E]);
+ if ((code>=0x00A1)&&(code<=0x017E))
+ return(tab_uni_jisx02121[code-0x00A1]);
+ if ((code>=0x01CD)&&(code<=0x01DC))
+ return(tab_uni_jisx02122[code-0x01CD]);
+ if ((code>=0x01F5)&&(code<=0x01F5))
+ return(tab_uni_jisx02123[code-0x01F5]);
+ if ((code>=0x02C7)&&(code<=0x02DD))
+ return(tab_uni_jisx02124[code-0x02C7]);
+ if ((code>=0x0384)&&(code<=0x0390))
+ return(tab_uni_jisx02125[code-0x0384]);
+ if ((code>=0x03AA)&&(code<=0x03CE))
+ return(tab_uni_jisx02126[code-0x03AA]);
+ if ((code>=0x0402)&&(code<=0x040F))
+ return(tab_uni_jisx02127[code-0x0402]);
+ if ((code>=0x0452)&&(code<=0x045F))
+ return(tab_uni_jisx02128[code-0x0452]);
+ if ((code>=0x2122)&&(code<=0x2122))
+ return(tab_uni_jisx02129[code-0x2122]);
+ if ((code>=0x2170)&&(code<=0x2179))
+ return(tab_uni_jisx021210[code-0x2170]);
+ if ((code>=0x4E02)&&(code<=0x4F19))
+ return(tab_uni_jisx021211[code-0x4E02]);
+ if ((code>=0x4F2E)&&(code<=0x5166))
+ return(tab_uni_jisx021212[code-0x4F2E]);
+ if ((code>=0x517E)&&(code<=0x5515))
+ return(tab_uni_jisx021213[code-0x517E]);
+ if ((code>=0x552A)&&(code<=0x5566))
+ return(tab_uni_jisx021214[code-0x552A]);
+ if ((code>=0x557F)&&(code<=0x5C36))
+ return(tab_uni_jisx021215[code-0x557F]);
+ if ((code>=0x5C59)&&(code<=0x5EEB))
+ return(tab_uni_jisx021216[code-0x5C59]);
+ if ((code>=0x5F02)&&(code<=0x6149))
+ return(tab_uni_jisx021217[code-0x5F02]);
+ if ((code>=0x615E)&&(code<=0x6290))
+ return(tab_uni_jisx021218[code-0x615E]);
+ if ((code>=0x62A6)&&(code<=0x679B))
+ return(tab_uni_jisx021219[code-0x62A6]);
+ if ((code>=0x67B0)&&(code<=0x6801))
+ return(tab_uni_jisx021220[code-0x67B0]);
+ if ((code>=0x6814)&&(code<=0x6917))
+ return(tab_uni_jisx021221[code-0x6814]);
+ if ((code>=0x6931)&&(code<=0x6D3F))
+ return(tab_uni_jisx021222[code-0x6931]);
+ if ((code>=0x6D57)&&(code<=0x6E04))
+ return(tab_uni_jisx021223[code-0x6D57]);
+ if ((code>=0x6E1E)&&(code<=0x6ECF))
+ return(tab_uni_jisx021224[code-0x6E1E]);
+ if ((code>=0x6EEB)&&(code<=0x70E4))
+ return(tab_uni_jisx021225[code-0x6EEB]);
+ if ((code>=0x70FA)&&(code<=0x71DC))
+ return(tab_uni_jisx021226[code-0x70FA]);
+ if ((code>=0x71F8)&&(code<=0x7E9E))
+ return(tab_uni_jisx021227[code-0x71F8]);
+ if ((code>=0x7F3B)&&(code<=0x8044))
+ return(tab_uni_jisx021228[code-0x7F3B]);
+ if ((code>=0x8060)&&(code<=0x8362))
+ return(tab_uni_jisx021229[code-0x8060]);
+ if ((code>=0x8370)&&(code<=0x8419))
+ return(tab_uni_jisx021230[code-0x8370]);
+ if ((code>=0x842F)&&(code<=0x8880))
+ return(tab_uni_jisx021231[code-0x842F]);
+ if ((code>=0x8898)&&(code<=0x89BC))
+ return(tab_uni_jisx021232[code-0x8898]);
+ if ((code>=0x89D4)&&(code<=0x8B9F))
+ return(tab_uni_jisx021233[code-0x89D4]);
+ if ((code>=0x8C38)&&(code<=0x8CA4))
+ return(tab_uni_jisx021234[code-0x8C38]);
+ if ((code>=0x8CB9)&&(code<=0x8D1B))
+ return(tab_uni_jisx021235[code-0x8CB9]);
+ if ((code>=0x8D65)&&(code<=0x8F65))
+ return(tab_uni_jisx021236[code-0x8D65]);
+ if ((code>=0x8F9D)&&(code<=0x9484))
+ return(tab_uni_jisx021237[code-0x8F9D]);
+ if ((code>=0x9578)&&(code<=0x95E6))
+ return(tab_uni_jisx021238[code-0x9578]);
+ if ((code>=0x961D)&&(code<=0x986C))
+ return(tab_uni_jisx021239[code-0x961D]);
+ if ((code>=0x98AB)&&(code<=0x98CC))
+ return(tab_uni_jisx021240[code-0x98AB]);
+ if ((code>=0x98E1)&&(code<=0x9960))
+ return(tab_uni_jisx021241[code-0x98E1]);
+ if ((code>=0x999B)&&(code<=0x9A5D))
+ return(tab_uni_jisx021242[code-0x999B]);
+ if ((code>=0x9AAA)&&(code<=0x9C7B))
+ return(tab_uni_jisx021243[code-0x9AAA]);
+ if ((code>=0x9CE6)&&(code<=0x9E1D))
+ return(tab_uni_jisx021244[code-0x9CE6]);
+ if ((code>=0x9E7A)&&(code<=0x9FA5))
+ return(tab_uni_jisx021245[code-0x9E7A]);
+ if ((code>=0xF929)&&(code<=0xF929))
+ return(tab_uni_jisx021246[code-0xF929]);
+ if ((code>=0xF9DC)&&(code<=0xF9DC))
+ return(tab_uni_jisx021247[code-0xF9DC]);
+ if ((code>=0xFA00)&&(code<=0xFA2D))
+ return(tab_uni_jisx021248[code-0xFA00]);
+ if ((code>=0xFF00)&&(code<=0xFF07))
+ return(tab_uni_jisx021249[code-0xFF00]);
+ if ((code>=0xFFE4)&&(code<=0xFFE4))
+ return(tab_uni_jisx021250[code-0xFFE4]);
+ return(0);
+}
+
+/* page 0 0x222F-0x2244 */
+static uint16 tab_jisx0212_uni0[]={
+0x02D8,0x02C7,0x00B8,0x02D9,0x02DD,0x00AF,0x02DB,0x02DA,
+0xFF5E,0x0384,0x0385, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x00A1,0xFFE4,0x00BF};
+
+/* page 1 0x226B-0x2271 */
+static uint16 tab_jisx0212_uni1[]={
+0x00BA,0x00AA,0x00A9,0x00AE,0x2122,0x00A4,0x2116};
+
+/* page 2 0x2661-0x267C */
+static uint16 tab_jisx0212_uni2[]={
+0x0386,0x0388,0x0389,0x038A,0x03AA, 0,0x038C, 0,
+0x038E,0x03AB, 0,0x038F, 0, 0, 0, 0,
+0x03AC,0x03AD,0x03AE,0x03AF,0x03CA,0x0390,0x03CC,0x03C2,
+0x03CD,0x03CB,0x03B0,0x03CE};
+
+/* page 3 0x2742-0x274E */
+static uint16 tab_jisx0212_uni3[]={
+0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,0x0408,0x0409,
+0x040A,0x040B,0x040C,0x040E,0x040F};
+
+/* page 4 0x2772-0x277E */
+static uint16 tab_jisx0212_uni4[]={
+0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,0x0458,0x0459,
+0x045A,0x045B,0x045C,0x045E,0x045F};
+
+/* page 5 0x2921-0x2950 */
+static uint16 tab_jisx0212_uni5[]={
+0x00C6,0x0110, 0,0x0126, 0,0x0132, 0,0x0141,
+0x013F, 0,0x014A,0x00D8,0x0152, 0,0x0166,0x00DE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x00E6,0x0111,0x00F0,0x0127,0x0131,0x0133,0x0138,0x0142,
+0x0140,0x0149,0x014B,0x00F8,0x0153,0x00DF,0x0167,0x00FE
+};
+
+/* page 6 0x2A21-0x2A77 */
+static uint16 tab_jisx0212_uni6[]={
+0x00C1,0x00C0,0x00C4,0x00C2,0x0102,0x01CD,0x0100,0x0104,
+0x00C5,0x00C3,0x0106,0x0108,0x010C,0x00C7,0x010A,0x010E,
+0x00C9,0x00C8,0x00CB,0x00CA,0x011A,0x0116,0x0112,0x0118,
+ 0,0x011C,0x011E,0x0122,0x0120,0x0124,0x00CD,0x00CC,
+0x00CF,0x00CE,0x01CF,0x0130,0x012A,0x012E,0x0128,0x0134,
+0x0136,0x0139,0x013D,0x013B,0x0143,0x0147,0x0145,0x00D1,
+0x00D3,0x00D2,0x00D6,0x00D4,0x01D1,0x0150,0x014C,0x00D5,
+0x0154,0x0158,0x0156,0x015A,0x015C,0x0160,0x015E,0x0164,
+0x0162,0x00DA,0x00D9,0x00DC,0x00DB,0x016C,0x01D3,0x0170,
+0x016A,0x0172,0x016E,0x0168,0x01D7,0x01DB,0x01D9,0x01D5,
+0x0174,0x00DD,0x0178,0x0176,0x0179,0x017D,0x017B};
+
+/* page 7 0x2B21-0x2B77 */
+static uint16 tab_jisx0212_uni7[]={
+0x00E1,0x00E0,0x00E4,0x00E2,0x0103,0x01CE,0x0101,0x0105,
+0x00E5,0x00E3,0x0107,0x0109,0x010D,0x00E7,0x010B,0x010F,
+0x00E9,0x00E8,0x00EB,0x00EA,0x011B,0x0117,0x0113,0x0119,
+0x01F5,0x011D,0x011F, 0,0x0121,0x0125,0x00ED,0x00EC,
+0x00EF,0x00EE,0x01D0, 0,0x012B,0x012F,0x0129,0x0135,
+0x0137,0x013A,0x013E,0x013C,0x0144,0x0148,0x0146,0x00F1,
+0x00F3,0x00F2,0x00F6,0x00F4,0x01D2,0x0151,0x014D,0x00F5,
+0x0155,0x0159,0x0157,0x015B,0x015D,0x0161,0x015F,0x0165,
+0x0163,0x00FA,0x00F9,0x00FC,0x00FB,0x016D,0x01D4,0x0171,
+0x016B,0x0173,0x016F,0x0169,0x01D8,0x01DC,0x01DA,0x01D6,
+0x0175,0x00FD,0x00FF,0x0177,0x017A,0x017E,0x017C};
+
+/* page 8 0x3021-0x307E */
+static uint16 tab_jisx0212_uni8[]={
+0x4E02,0x4E04,0x4E05,0x4E0C,0x4E12,0x4E1F,0x4E23,0x4E24,
+0x4E28,0x4E2B,0x4E2E,0x4E2F,0x4E30,0x4E35,0x4E40,0x4E41,
+0x4E44,0x4E47,0x4E51,0x4E5A,0x4E5C,0x4E63,0x4E68,0x4E69,
+0x4E74,0x4E75,0x4E79,0x4E7F,0x4E8D,0x4E96,0x4E97,0x4E9D,
+0x4EAF,0x4EB9,0x4EC3,0x4ED0,0x4EDA,0x4EDB,0x4EE0,0x4EE1,
+0x4EE2,0x4EE8,0x4EEF,0x4EF1,0x4EF3,0x4EF5,0x4EFD,0x4EFE,
+0x4EFF,0x4F00,0x4F02,0x4F03,0x4F08,0x4F0B,0x4F0C,0x4F12,
+0x4F15,0x4F16,0x4F17,0x4F19,0x4F2E,0x4F31,0x4F60,0x4F33,
+0x4F35,0x4F37,0x4F39,0x4F3B,0x4F3E,0x4F40,0x4F42,0x4F48,
+0x4F49,0x4F4B,0x4F4C,0x4F52,0x4F54,0x4F56,0x4F58,0x4F5F,
+0x4F63,0x4F6A,0x4F6C,0x4F6E,0x4F71,0x4F77,0x4F78,0x4F79,
+0x4F7A,0x4F7D,0x4F7E,0x4F81,0x4F82,0x4F84};
+
+/* page 9 0x3121-0x317E */
+static uint16 tab_jisx0212_uni9[]={
+0x4F85,0x4F89,0x4F8A,0x4F8C,0x4F8E,0x4F90,0x4F92,0x4F93,
+0x4F94,0x4F97,0x4F99,0x4F9A,0x4F9E,0x4F9F,0x4FB2,0x4FB7,
+0x4FB9,0x4FBB,0x4FBC,0x4FBD,0x4FBE,0x4FC0,0x4FC1,0x4FC5,
+0x4FC6,0x4FC8,0x4FC9,0x4FCB,0x4FCC,0x4FCD,0x4FCF,0x4FD2,
+0x4FDC,0x4FE0,0x4FE2,0x4FF0,0x4FF2,0x4FFC,0x4FFD,0x4FFF,
+0x5000,0x5001,0x5004,0x5007,0x500A,0x500C,0x500E,0x5010,
+0x5013,0x5017,0x5018,0x501B,0x501C,0x501D,0x501E,0x5022,
+0x5027,0x502E,0x5030,0x5032,0x5033,0x5035,0x5040,0x5041,
+0x5042,0x5045,0x5046,0x504A,0x504C,0x504E,0x5051,0x5052,
+0x5053,0x5057,0x5059,0x505F,0x5060,0x5062,0x5063,0x5066,
+0x5067,0x506A,0x506D,0x5070,0x5071,0x503B,0x5081,0x5083,
+0x5084,0x5086,0x508A,0x508E,0x508F,0x5090};
+
+/* page 10 0x3221-0x327E */
+static uint16 tab_jisx0212_uni10[]={
+0x5092,0x5093,0x5094,0x5096,0x509B,0x509C,0x509E,0x509F,
+0x50A0,0x50A1,0x50A2,0x50AA,0x50AF,0x50B0,0x50B9,0x50BA,
+0x50BD,0x50C0,0x50C3,0x50C4,0x50C7,0x50CC,0x50CE,0x50D0,
+0x50D3,0x50D4,0x50D8,0x50DC,0x50DD,0x50DF,0x50E2,0x50E4,
+0x50E6,0x50E8,0x50E9,0x50EF,0x50F1,0x50F6,0x50FA,0x50FE,
+0x5103,0x5106,0x5107,0x5108,0x510B,0x510C,0x510D,0x510E,
+0x50F2,0x5110,0x5117,0x5119,0x511B,0x511C,0x511D,0x511E,
+0x5123,0x5127,0x5128,0x512C,0x512D,0x512F,0x5131,0x5133,
+0x5134,0x5135,0x5138,0x5139,0x5142,0x514A,0x514F,0x5153,
+0x5155,0x5157,0x5158,0x515F,0x5164,0x5166,0x517E,0x5183,
+0x5184,0x518B,0x518E,0x5198,0x519D,0x51A1,0x51A3,0x51AD,
+0x51B8,0x51BA,0x51BC,0x51BE,0x51BF,0x51C2};
+
+/* page 11 0x3321-0x337E */
+static uint16 tab_jisx0212_uni11[]={
+0x51C8,0x51CF,0x51D1,0x51D2,0x51D3,0x51D5,0x51D8,0x51DE,
+0x51E2,0x51E5,0x51EE,0x51F2,0x51F3,0x51F4,0x51F7,0x5201,
+0x5202,0x5205,0x5212,0x5213,0x5215,0x5216,0x5218,0x5222,
+0x5228,0x5231,0x5232,0x5235,0x523C,0x5245,0x5249,0x5255,
+0x5257,0x5258,0x525A,0x525C,0x525F,0x5260,0x5261,0x5266,
+0x526E,0x5277,0x5278,0x5279,0x5280,0x5282,0x5285,0x528A,
+0x528C,0x5293,0x5295,0x5296,0x5297,0x5298,0x529A,0x529C,
+0x52A4,0x52A5,0x52A6,0x52A7,0x52AF,0x52B0,0x52B6,0x52B7,
+0x52B8,0x52BA,0x52BB,0x52BD,0x52C0,0x52C4,0x52C6,0x52C8,
+0x52CC,0x52CF,0x52D1,0x52D4,0x52D6,0x52DB,0x52DC,0x52E1,
+0x52E5,0x52E8,0x52E9,0x52EA,0x52EC,0x52F0,0x52F1,0x52F4,
+0x52F6,0x52F7,0x5300,0x5303,0x530A,0x530B};
+
+/* page 12 0x3421-0x347E */
+static uint16 tab_jisx0212_uni12[]={
+0x530C,0x5311,0x5313,0x5318,0x531B,0x531C,0x531E,0x531F,
+0x5325,0x5327,0x5328,0x5329,0x532B,0x532C,0x532D,0x5330,
+0x5332,0x5335,0x533C,0x533D,0x533E,0x5342,0x534C,0x534B,
+0x5359,0x535B,0x5361,0x5363,0x5365,0x536C,0x536D,0x5372,
+0x5379,0x537E,0x5383,0x5387,0x5388,0x538E,0x5393,0x5394,
+0x5399,0x539D,0x53A1,0x53A4,0x53AA,0x53AB,0x53AF,0x53B2,
+0x53B4,0x53B5,0x53B7,0x53B8,0x53BA,0x53BD,0x53C0,0x53C5,
+0x53CF,0x53D2,0x53D3,0x53D5,0x53DA,0x53DD,0x53DE,0x53E0,
+0x53E6,0x53E7,0x53F5,0x5402,0x5413,0x541A,0x5421,0x5427,
+0x5428,0x542A,0x542F,0x5431,0x5434,0x5435,0x5443,0x5444,
+0x5447,0x544D,0x544F,0x545E,0x5462,0x5464,0x5466,0x5467,
+0x5469,0x546B,0x546D,0x546E,0x5474,0x547F};
+
+/* page 13 0x3521-0x357E */
+static uint16 tab_jisx0212_uni13[]={
+0x5481,0x5483,0x5485,0x5488,0x5489,0x548D,0x5491,0x5495,
+0x5496,0x549C,0x549F,0x54A1,0x54A6,0x54A7,0x54A9,0x54AA,
+0x54AD,0x54AE,0x54B1,0x54B7,0x54B9,0x54BA,0x54BB,0x54BF,
+0x54C6,0x54CA,0x54CD,0x54CE,0x54E0,0x54EA,0x54EC,0x54EF,
+0x54F6,0x54FC,0x54FE,0x54FF,0x5500,0x5501,0x5505,0x5508,
+0x5509,0x550C,0x550D,0x550E,0x5515,0x552A,0x552B,0x5532,
+0x5535,0x5536,0x553B,0x553C,0x553D,0x5541,0x5547,0x5549,
+0x554A,0x554D,0x5550,0x5551,0x5558,0x555A,0x555B,0x555E,
+0x5560,0x5561,0x5564,0x5566,0x557F,0x5581,0x5582,0x5586,
+0x5588,0x558E,0x558F,0x5591,0x5592,0x5593,0x5594,0x5597,
+0x55A3,0x55A4,0x55AD,0x55B2,0x55BF,0x55C1,0x55C3,0x55C6,
+0x55C9,0x55CB,0x55CC,0x55CE,0x55D1,0x55D2};
+
+/* page 14 0x3621-0x367E */
+static uint16 tab_jisx0212_uni14[]={
+0x55D3,0x55D7,0x55D8,0x55DB,0x55DE,0x55E2,0x55E9,0x55F6,
+0x55FF,0x5605,0x5608,0x560A,0x560D,0x560E,0x560F,0x5610,
+0x5611,0x5612,0x5619,0x562C,0x5630,0x5633,0x5635,0x5637,
+0x5639,0x563B,0x563C,0x563D,0x563F,0x5640,0x5641,0x5643,
+0x5644,0x5646,0x5649,0x564B,0x564D,0x564F,0x5654,0x565E,
+0x5660,0x5661,0x5662,0x5663,0x5666,0x5669,0x566D,0x566F,
+0x5671,0x5672,0x5675,0x5684,0x5685,0x5688,0x568B,0x568C,
+0x5695,0x5699,0x569A,0x569D,0x569E,0x569F,0x56A6,0x56A7,
+0x56A8,0x56A9,0x56AB,0x56AC,0x56AD,0x56B1,0x56B3,0x56B7,
+0x56BE,0x56C5,0x56C9,0x56CA,0x56CB,0x56CF,0x56D0,0x56CC,
+0x56CD,0x56D9,0x56DC,0x56DD,0x56DF,0x56E1,0x56E4,0x56E5,
+0x56E6,0x56E7,0x56E8,0x56F1,0x56EB,0x56ED};
+
+/* page 15 0x3721-0x377E */
+static uint16 tab_jisx0212_uni15[]={
+0x56F6,0x56F7,0x5701,0x5702,0x5707,0x570A,0x570C,0x5711,
+0x5715,0x571A,0x571B,0x571D,0x5720,0x5722,0x5723,0x5724,
+0x5725,0x5729,0x572A,0x572C,0x572E,0x572F,0x5733,0x5734,
+0x573D,0x573E,0x573F,0x5745,0x5746,0x574C,0x574D,0x5752,
+0x5762,0x5765,0x5767,0x5768,0x576B,0x576D,0x576E,0x576F,
+0x5770,0x5771,0x5773,0x5774,0x5775,0x5777,0x5779,0x577A,
+0x577B,0x577C,0x577E,0x5781,0x5783,0x578C,0x5794,0x5797,
+0x5799,0x579A,0x579C,0x579D,0x579E,0x579F,0x57A1,0x5795,
+0x57A7,0x57A8,0x57A9,0x57AC,0x57B8,0x57BD,0x57C7,0x57C8,
+0x57CC,0x57CF,0x57D5,0x57DD,0x57DE,0x57E4,0x57E6,0x57E7,
+0x57E9,0x57ED,0x57F0,0x57F5,0x57F6,0x57F8,0x57FD,0x57FE,
+0x57FF,0x5803,0x5804,0x5808,0x5809,0x57E1};
+
+/* page 16 0x3821-0x387E */
+static uint16 tab_jisx0212_uni16[]={
+0x580C,0x580D,0x581B,0x581E,0x581F,0x5820,0x5826,0x5827,
+0x582D,0x5832,0x5839,0x583F,0x5849,0x584C,0x584D,0x584F,
+0x5850,0x5855,0x585F,0x5861,0x5864,0x5867,0x5868,0x5878,
+0x587C,0x587F,0x5880,0x5881,0x5887,0x5888,0x5889,0x588A,
+0x588C,0x588D,0x588F,0x5890,0x5894,0x5896,0x589D,0x58A0,
+0x58A1,0x58A2,0x58A6,0x58A9,0x58B1,0x58B2,0x58C4,0x58BC,
+0x58C2,0x58C8,0x58CD,0x58CE,0x58D0,0x58D2,0x58D4,0x58D6,
+0x58DA,0x58DD,0x58E1,0x58E2,0x58E9,0x58F3,0x5905,0x5906,
+0x590B,0x590C,0x5912,0x5913,0x5914,0x8641,0x591D,0x5921,
+0x5923,0x5924,0x5928,0x592F,0x5930,0x5933,0x5935,0x5936,
+0x593F,0x5943,0x5946,0x5952,0x5953,0x5959,0x595B,0x595D,
+0x595E,0x595F,0x5961,0x5963,0x596B,0x596D};
+
+/* page 17 0x3921-0x397E */
+static uint16 tab_jisx0212_uni17[]={
+0x596F,0x5972,0x5975,0x5976,0x5979,0x597B,0x597C,0x598B,
+0x598C,0x598E,0x5992,0x5995,0x5997,0x599F,0x59A4,0x59A7,
+0x59AD,0x59AE,0x59AF,0x59B0,0x59B3,0x59B7,0x59BA,0x59BC,
+0x59C1,0x59C3,0x59C4,0x59C8,0x59CA,0x59CD,0x59D2,0x59DD,
+0x59DE,0x59DF,0x59E3,0x59E4,0x59E7,0x59EE,0x59EF,0x59F1,
+0x59F2,0x59F4,0x59F7,0x5A00,0x5A04,0x5A0C,0x5A0D,0x5A0E,
+0x5A12,0x5A13,0x5A1E,0x5A23,0x5A24,0x5A27,0x5A28,0x5A2A,
+0x5A2D,0x5A30,0x5A44,0x5A45,0x5A47,0x5A48,0x5A4C,0x5A50,
+0x5A55,0x5A5E,0x5A63,0x5A65,0x5A67,0x5A6D,0x5A77,0x5A7A,
+0x5A7B,0x5A7E,0x5A8B,0x5A90,0x5A93,0x5A96,0x5A99,0x5A9C,
+0x5A9E,0x5A9F,0x5AA0,0x5AA2,0x5AA7,0x5AAC,0x5AB1,0x5AB2,
+0x5AB3,0x5AB5,0x5AB8,0x5ABA,0x5ABB,0x5ABF};
+
+/* page 18 0x3A21-0x3A7E */
+static uint16 tab_jisx0212_uni18[]={
+0x5AC4,0x5AC6,0x5AC8,0x5ACF,0x5ADA,0x5ADC,0x5AE0,0x5AE5,
+0x5AEA,0x5AEE,0x5AF5,0x5AF6,0x5AFD,0x5B00,0x5B01,0x5B08,
+0x5B17,0x5B34,0x5B19,0x5B1B,0x5B1D,0x5B21,0x5B25,0x5B2D,
+0x5B38,0x5B41,0x5B4B,0x5B4C,0x5B52,0x5B56,0x5B5E,0x5B68,
+0x5B6E,0x5B6F,0x5B7C,0x5B7D,0x5B7E,0x5B7F,0x5B81,0x5B84,
+0x5B86,0x5B8A,0x5B8E,0x5B90,0x5B91,0x5B93,0x5B94,0x5B96,
+0x5BA8,0x5BA9,0x5BAC,0x5BAD,0x5BAF,0x5BB1,0x5BB2,0x5BB7,
+0x5BBA,0x5BBC,0x5BC0,0x5BC1,0x5BCD,0x5BCF,0x5BD6,0x5BD7,
+0x5BD8,0x5BD9,0x5BDA,0x5BE0,0x5BEF,0x5BF1,0x5BF4,0x5BFD,
+0x5C0C,0x5C17,0x5C1E,0x5C1F,0x5C23,0x5C26,0x5C29,0x5C2B,
+0x5C2C,0x5C2E,0x5C30,0x5C32,0x5C35,0x5C36,0x5C59,0x5C5A,
+0x5C5C,0x5C62,0x5C63,0x5C67,0x5C68,0x5C69};
+
+/* page 19 0x3B21-0x3B7E */
+static uint16 tab_jisx0212_uni19[]={
+0x5C6D,0x5C70,0x5C74,0x5C75,0x5C7A,0x5C7B,0x5C7C,0x5C7D,
+0x5C87,0x5C88,0x5C8A,0x5C8F,0x5C92,0x5C9D,0x5C9F,0x5CA0,
+0x5CA2,0x5CA3,0x5CA6,0x5CAA,0x5CB2,0x5CB4,0x5CB5,0x5CBA,
+0x5CC9,0x5CCB,0x5CD2,0x5CDD,0x5CD7,0x5CEE,0x5CF1,0x5CF2,
+0x5CF4,0x5D01,0x5D06,0x5D0D,0x5D12,0x5D2B,0x5D23,0x5D24,
+0x5D26,0x5D27,0x5D31,0x5D34,0x5D39,0x5D3D,0x5D3F,0x5D42,
+0x5D43,0x5D46,0x5D48,0x5D55,0x5D51,0x5D59,0x5D4A,0x5D5F,
+0x5D60,0x5D61,0x5D62,0x5D64,0x5D6A,0x5D6D,0x5D70,0x5D79,
+0x5D7A,0x5D7E,0x5D7F,0x5D81,0x5D83,0x5D88,0x5D8A,0x5D92,
+0x5D93,0x5D94,0x5D95,0x5D99,0x5D9B,0x5D9F,0x5DA0,0x5DA7,
+0x5DAB,0x5DB0,0x5DB4,0x5DB8,0x5DB9,0x5DC3,0x5DC7,0x5DCB,
+0x5DD0,0x5DCE,0x5DD8,0x5DD9,0x5DE0,0x5DE4};
+
+/* page 20 0x3C21-0x3C7E */
+static uint16 tab_jisx0212_uni20[]={
+0x5DE9,0x5DF8,0x5DF9,0x5E00,0x5E07,0x5E0D,0x5E12,0x5E14,
+0x5E15,0x5E18,0x5E1F,0x5E20,0x5E2E,0x5E28,0x5E32,0x5E35,
+0x5E3E,0x5E4B,0x5E50,0x5E49,0x5E51,0x5E56,0x5E58,0x5E5B,
+0x5E5C,0x5E5E,0x5E68,0x5E6A,0x5E6B,0x5E6C,0x5E6D,0x5E6E,
+0x5E70,0x5E80,0x5E8B,0x5E8E,0x5EA2,0x5EA4,0x5EA5,0x5EA8,
+0x5EAA,0x5EAC,0x5EB1,0x5EB3,0x5EBD,0x5EBE,0x5EBF,0x5EC6,
+0x5ECC,0x5ECB,0x5ECE,0x5ED1,0x5ED2,0x5ED4,0x5ED5,0x5EDC,
+0x5EDE,0x5EE5,0x5EEB,0x5F02,0x5F06,0x5F07,0x5F08,0x5F0E,
+0x5F19,0x5F1C,0x5F1D,0x5F21,0x5F22,0x5F23,0x5F24,0x5F28,
+0x5F2B,0x5F2C,0x5F2E,0x5F30,0x5F34,0x5F36,0x5F3B,0x5F3D,
+0x5F3F,0x5F40,0x5F44,0x5F45,0x5F47,0x5F4D,0x5F50,0x5F54,
+0x5F58,0x5F5B,0x5F60,0x5F63,0x5F64,0x5F67};
+
+/* page 21 0x3D21-0x3D7E */
+static uint16 tab_jisx0212_uni21[]={
+0x5F6F,0x5F72,0x5F74,0x5F75,0x5F78,0x5F7A,0x5F7D,0x5F7E,
+0x5F89,0x5F8D,0x5F8F,0x5F96,0x5F9C,0x5F9D,0x5FA2,0x5FA7,
+0x5FAB,0x5FA4,0x5FAC,0x5FAF,0x5FB0,0x5FB1,0x5FB8,0x5FC4,
+0x5FC7,0x5FC8,0x5FC9,0x5FCB,0x5FD0,0x5FD1,0x5FD2,0x5FD3,
+0x5FD4,0x5FDE,0x5FE1,0x5FE2,0x5FE8,0x5FE9,0x5FEA,0x5FEC,
+0x5FED,0x5FEE,0x5FEF,0x5FF2,0x5FF3,0x5FF6,0x5FFA,0x5FFC,
+0x6007,0x600A,0x600D,0x6013,0x6014,0x6017,0x6018,0x601A,
+0x601F,0x6024,0x602D,0x6033,0x6035,0x6040,0x6047,0x6048,
+0x6049,0x604C,0x6051,0x6054,0x6056,0x6057,0x605D,0x6061,
+0x6067,0x6071,0x607E,0x607F,0x6082,0x6086,0x6088,0x608A,
+0x608E,0x6091,0x6093,0x6095,0x6098,0x609D,0x609E,0x60A2,
+0x60A4,0x60A5,0x60A8,0x60B0,0x60B1,0x60B7};
+
+/* page 22 0x3E21-0x3E7E */
+static uint16 tab_jisx0212_uni22[]={
+0x60BB,0x60BE,0x60C2,0x60C4,0x60C8,0x60C9,0x60CA,0x60CB,
+0x60CE,0x60CF,0x60D4,0x60D5,0x60D9,0x60DB,0x60DD,0x60DE,
+0x60E2,0x60E5,0x60F2,0x60F5,0x60F8,0x60FC,0x60FD,0x6102,
+0x6107,0x610A,0x610C,0x6110,0x6111,0x6112,0x6113,0x6114,
+0x6116,0x6117,0x6119,0x611C,0x611E,0x6122,0x612A,0x612B,
+0x6130,0x6131,0x6135,0x6136,0x6137,0x6139,0x6141,0x6145,
+0x6146,0x6149,0x615E,0x6160,0x616C,0x6172,0x6178,0x617B,
+0x617C,0x617F,0x6180,0x6181,0x6183,0x6184,0x618B,0x618D,
+0x6192,0x6193,0x6197,0x6198,0x619C,0x619D,0x619F,0x61A0,
+0x61A5,0x61A8,0x61AA,0x61AD,0x61B8,0x61B9,0x61BC,0x61C0,
+0x61C1,0x61C2,0x61CE,0x61CF,0x61D5,0x61DC,0x61DD,0x61DE,
+0x61DF,0x61E1,0x61E2,0x61E7,0x61E9,0x61E5};
+
+/* page 23 0x3F21-0x3F7E */
+static uint16 tab_jisx0212_uni23[]={
+0x61EC,0x61ED,0x61EF,0x6201,0x6203,0x6204,0x6207,0x6213,
+0x6215,0x621C,0x6220,0x6222,0x6223,0x6227,0x6229,0x622B,
+0x6239,0x623D,0x6242,0x6243,0x6244,0x6246,0x624C,0x6250,
+0x6251,0x6252,0x6254,0x6256,0x625A,0x625C,0x6264,0x626D,
+0x626F,0x6273,0x627A,0x627D,0x628D,0x628E,0x628F,0x6290,
+0x62A6,0x62A8,0x62B3,0x62B6,0x62B7,0x62BA,0x62BE,0x62BF,
+0x62C4,0x62CE,0x62D5,0x62D6,0x62DA,0x62EA,0x62F2,0x62F4,
+0x62FC,0x62FD,0x6303,0x6304,0x630A,0x630B,0x630D,0x6310,
+0x6313,0x6316,0x6318,0x6329,0x632A,0x632D,0x6335,0x6336,
+0x6339,0x633C,0x6341,0x6342,0x6343,0x6344,0x6346,0x634A,
+0x634B,0x634E,0x6352,0x6353,0x6354,0x6358,0x635B,0x6365,
+0x6366,0x636C,0x636D,0x6371,0x6374,0x6375};
+
+/* page 24 0x4021-0x407E */
+static uint16 tab_jisx0212_uni24[]={
+0x6378,0x637C,0x637D,0x637F,0x6382,0x6384,0x6387,0x638A,
+0x6390,0x6394,0x6395,0x6399,0x639A,0x639E,0x63A4,0x63A6,
+0x63AD,0x63AE,0x63AF,0x63BD,0x63C1,0x63C5,0x63C8,0x63CE,
+0x63D1,0x63D3,0x63D4,0x63D5,0x63DC,0x63E0,0x63E5,0x63EA,
+0x63EC,0x63F2,0x63F3,0x63F5,0x63F8,0x63F9,0x6409,0x640A,
+0x6410,0x6412,0x6414,0x6418,0x641E,0x6420,0x6422,0x6424,
+0x6425,0x6429,0x642A,0x642F,0x6430,0x6435,0x643D,0x643F,
+0x644B,0x644F,0x6451,0x6452,0x6453,0x6454,0x645A,0x645B,
+0x645C,0x645D,0x645F,0x6460,0x6461,0x6463,0x646D,0x6473,
+0x6474,0x647B,0x647D,0x6485,0x6487,0x648F,0x6490,0x6491,
+0x6498,0x6499,0x649B,0x649D,0x649F,0x64A1,0x64A3,0x64A6,
+0x64A8,0x64AC,0x64B3,0x64BD,0x64BE,0x64BF};
+
+/* page 25 0x4121-0x417E */
+static uint16 tab_jisx0212_uni25[]={
+0x64C4,0x64C9,0x64CA,0x64CB,0x64CC,0x64CE,0x64D0,0x64D1,
+0x64D5,0x64D7,0x64E4,0x64E5,0x64E9,0x64EA,0x64ED,0x64F0,
+0x64F5,0x64F7,0x64FB,0x64FF,0x6501,0x6504,0x6508,0x6509,
+0x650A,0x650F,0x6513,0x6514,0x6516,0x6519,0x651B,0x651E,
+0x651F,0x6522,0x6526,0x6529,0x652E,0x6531,0x653A,0x653C,
+0x653D,0x6543,0x6547,0x6549,0x6550,0x6552,0x6554,0x655F,
+0x6560,0x6567,0x656B,0x657A,0x657D,0x6581,0x6585,0x658A,
+0x6592,0x6595,0x6598,0x659D,0x65A0,0x65A3,0x65A6,0x65AE,
+0x65B2,0x65B3,0x65B4,0x65BF,0x65C2,0x65C8,0x65C9,0x65CE,
+0x65D0,0x65D4,0x65D6,0x65D8,0x65DF,0x65F0,0x65F2,0x65F4,
+0x65F5,0x65F9,0x65FE,0x65FF,0x6600,0x6604,0x6608,0x6609,
+0x660D,0x6611,0x6612,0x6615,0x6616,0x661D};
+
+/* page 26 0x4221-0x427E */
+static uint16 tab_jisx0212_uni26[]={
+0x661E,0x6621,0x6622,0x6623,0x6624,0x6626,0x6629,0x662A,
+0x662B,0x662C,0x662E,0x6630,0x6631,0x6633,0x6639,0x6637,
+0x6640,0x6645,0x6646,0x664A,0x664C,0x6651,0x664E,0x6657,
+0x6658,0x6659,0x665B,0x665C,0x6660,0x6661,0x66FB,0x666A,
+0x666B,0x666C,0x667E,0x6673,0x6675,0x667F,0x6677,0x6678,
+0x6679,0x667B,0x6680,0x667C,0x668B,0x668C,0x668D,0x6690,
+0x6692,0x6699,0x669A,0x669B,0x669C,0x669F,0x66A0,0x66A4,
+0x66AD,0x66B1,0x66B2,0x66B5,0x66BB,0x66BF,0x66C0,0x66C2,
+0x66C3,0x66C8,0x66CC,0x66CE,0x66CF,0x66D4,0x66DB,0x66DF,
+0x66E8,0x66EB,0x66EC,0x66EE,0x66FA,0x6705,0x6707,0x670E,
+0x6713,0x6719,0x671C,0x6720,0x6722,0x6733,0x673E,0x6745,
+0x6747,0x6748,0x674C,0x6754,0x6755,0x675D};
+
+/* page 27 0x4321-0x437E */
+static uint16 tab_jisx0212_uni27[]={
+0x6766,0x676C,0x676E,0x6774,0x6776,0x677B,0x6781,0x6784,
+0x678E,0x678F,0x6791,0x6793,0x6796,0x6798,0x6799,0x679B,
+0x67B0,0x67B1,0x67B2,0x67B5,0x67BB,0x67BC,0x67BD,0x67F9,
+0x67C0,0x67C2,0x67C3,0x67C5,0x67C8,0x67C9,0x67D2,0x67D7,
+0x67D9,0x67DC,0x67E1,0x67E6,0x67F0,0x67F2,0x67F6,0x67F7,
+0x6852,0x6814,0x6819,0x681D,0x681F,0x6828,0x6827,0x682C,
+0x682D,0x682F,0x6830,0x6831,0x6833,0x683B,0x683F,0x6844,
+0x6845,0x684A,0x684C,0x6855,0x6857,0x6858,0x685B,0x686B,
+0x686E,0x686F,0x6870,0x6871,0x6872,0x6875,0x6879,0x687A,
+0x687B,0x687C,0x6882,0x6884,0x6886,0x6888,0x6896,0x6898,
+0x689A,0x689C,0x68A1,0x68A3,0x68A5,0x68A9,0x68AA,0x68AE,
+0x68B2,0x68BB,0x68C5,0x68C8,0x68CC,0x68CF};
+
+/* page 28 0x4421-0x447E */
+static uint16 tab_jisx0212_uni28[]={
+0x68D0,0x68D1,0x68D3,0x68D6,0x68D9,0x68DC,0x68DD,0x68E5,
+0x68E8,0x68EA,0x68EB,0x68EC,0x68ED,0x68F0,0x68F1,0x68F5,
+0x68F6,0x68FB,0x68FC,0x68FD,0x6906,0x6909,0x690A,0x6910,
+0x6911,0x6913,0x6916,0x6917,0x6931,0x6933,0x6935,0x6938,
+0x693B,0x6942,0x6945,0x6949,0x694E,0x6957,0x695B,0x6963,
+0x6964,0x6965,0x6966,0x6968,0x6969,0x696C,0x6970,0x6971,
+0x6972,0x697A,0x697B,0x697F,0x6980,0x698D,0x6992,0x6996,
+0x6998,0x69A1,0x69A5,0x69A6,0x69A8,0x69AB,0x69AD,0x69AF,
+0x69B7,0x69B8,0x69BA,0x69BC,0x69C5,0x69C8,0x69D1,0x69D6,
+0x69D7,0x69E2,0x69E5,0x69EE,0x69EF,0x69F1,0x69F3,0x69F5,
+0x69FE,0x6A00,0x6A01,0x6A03,0x6A0F,0x6A11,0x6A15,0x6A1A,
+0x6A1D,0x6A20,0x6A24,0x6A28,0x6A30,0x6A32};
+
+/* page 29 0x4521-0x457E */
+static uint16 tab_jisx0212_uni29[]={
+0x6A34,0x6A37,0x6A3B,0x6A3E,0x6A3F,0x6A45,0x6A46,0x6A49,
+0x6A4A,0x6A4E,0x6A50,0x6A51,0x6A52,0x6A55,0x6A56,0x6A5B,
+0x6A64,0x6A67,0x6A6A,0x6A71,0x6A73,0x6A7E,0x6A81,0x6A83,
+0x6A86,0x6A87,0x6A89,0x6A8B,0x6A91,0x6A9B,0x6A9D,0x6A9E,
+0x6A9F,0x6AA5,0x6AAB,0x6AAF,0x6AB0,0x6AB1,0x6AB4,0x6ABD,
+0x6ABE,0x6ABF,0x6AC6,0x6AC9,0x6AC8,0x6ACC,0x6AD0,0x6AD4,
+0x6AD5,0x6AD6,0x6ADC,0x6ADD,0x6AE4,0x6AE7,0x6AEC,0x6AF0,
+0x6AF1,0x6AF2,0x6AFC,0x6AFD,0x6B02,0x6B03,0x6B06,0x6B07,
+0x6B09,0x6B0F,0x6B10,0x6B11,0x6B17,0x6B1B,0x6B1E,0x6B24,
+0x6B28,0x6B2B,0x6B2C,0x6B2F,0x6B35,0x6B36,0x6B3B,0x6B3F,
+0x6B46,0x6B4A,0x6B4D,0x6B52,0x6B56,0x6B58,0x6B5D,0x6B60,
+0x6B67,0x6B6B,0x6B6E,0x6B70,0x6B75,0x6B7D};
+
+/* page 30 0x4621-0x467E */
+static uint16 tab_jisx0212_uni30[]={
+0x6B7E,0x6B82,0x6B85,0x6B97,0x6B9B,0x6B9F,0x6BA0,0x6BA2,
+0x6BA3,0x6BA8,0x6BA9,0x6BAC,0x6BAD,0x6BAE,0x6BB0,0x6BB8,
+0x6BB9,0x6BBD,0x6BBE,0x6BC3,0x6BC4,0x6BC9,0x6BCC,0x6BD6,
+0x6BDA,0x6BE1,0x6BE3,0x6BE6,0x6BE7,0x6BEE,0x6BF1,0x6BF7,
+0x6BF9,0x6BFF,0x6C02,0x6C04,0x6C05,0x6C09,0x6C0D,0x6C0E,
+0x6C10,0x6C12,0x6C19,0x6C1F,0x6C26,0x6C27,0x6C28,0x6C2C,
+0x6C2E,0x6C33,0x6C35,0x6C36,0x6C3A,0x6C3B,0x6C3F,0x6C4A,
+0x6C4B,0x6C4D,0x6C4F,0x6C52,0x6C54,0x6C59,0x6C5B,0x6C5C,
+0x6C6B,0x6C6D,0x6C6F,0x6C74,0x6C76,0x6C78,0x6C79,0x6C7B,
+0x6C85,0x6C86,0x6C87,0x6C89,0x6C94,0x6C95,0x6C97,0x6C98,
+0x6C9C,0x6C9F,0x6CB0,0x6CB2,0x6CB4,0x6CC2,0x6CC6,0x6CCD,
+0x6CCF,0x6CD0,0x6CD1,0x6CD2,0x6CD4,0x6CD6};
+
+/* page 31 0x4721-0x477E */
+static uint16 tab_jisx0212_uni31[]={
+0x6CDA,0x6CDC,0x6CE0,0x6CE7,0x6CE9,0x6CEB,0x6CEC,0x6CEE,
+0x6CF2,0x6CF4,0x6D04,0x6D07,0x6D0A,0x6D0E,0x6D0F,0x6D11,
+0x6D13,0x6D1A,0x6D26,0x6D27,0x6D28,0x6C67,0x6D2E,0x6D2F,
+0x6D31,0x6D39,0x6D3C,0x6D3F,0x6D57,0x6D5E,0x6D5F,0x6D61,
+0x6D65,0x6D67,0x6D6F,0x6D70,0x6D7C,0x6D82,0x6D87,0x6D91,
+0x6D92,0x6D94,0x6D96,0x6D97,0x6D98,0x6DAA,0x6DAC,0x6DB4,
+0x6DB7,0x6DB9,0x6DBD,0x6DBF,0x6DC4,0x6DC8,0x6DCA,0x6DCE,
+0x6DCF,0x6DD6,0x6DDB,0x6DDD,0x6DDF,0x6DE0,0x6DE2,0x6DE5,
+0x6DE9,0x6DEF,0x6DF0,0x6DF4,0x6DF6,0x6DFC,0x6E00,0x6E04,
+0x6E1E,0x6E22,0x6E27,0x6E32,0x6E36,0x6E39,0x6E3B,0x6E3C,
+0x6E44,0x6E45,0x6E48,0x6E49,0x6E4B,0x6E4F,0x6E51,0x6E52,
+0x6E53,0x6E54,0x6E57,0x6E5C,0x6E5D,0x6E5E};
+
+/* page 32 0x4821-0x487E */
+static uint16 tab_jisx0212_uni32[]={
+0x6E62,0x6E63,0x6E68,0x6E73,0x6E7B,0x6E7D,0x6E8D,0x6E93,
+0x6E99,0x6EA0,0x6EA7,0x6EAD,0x6EAE,0x6EB1,0x6EB3,0x6EBB,
+0x6EBF,0x6EC0,0x6EC1,0x6EC3,0x6EC7,0x6EC8,0x6ECA,0x6ECD,
+0x6ECE,0x6ECF,0x6EEB,0x6EED,0x6EEE,0x6EF9,0x6EFB,0x6EFD,
+0x6F04,0x6F08,0x6F0A,0x6F0C,0x6F0D,0x6F16,0x6F18,0x6F1A,
+0x6F1B,0x6F26,0x6F29,0x6F2A,0x6F2F,0x6F30,0x6F33,0x6F36,
+0x6F3B,0x6F3C,0x6F2D,0x6F4F,0x6F51,0x6F52,0x6F53,0x6F57,
+0x6F59,0x6F5A,0x6F5D,0x6F5E,0x6F61,0x6F62,0x6F68,0x6F6C,
+0x6F7D,0x6F7E,0x6F83,0x6F87,0x6F88,0x6F8B,0x6F8C,0x6F8D,
+0x6F90,0x6F92,0x6F93,0x6F94,0x6F96,0x6F9A,0x6F9F,0x6FA0,
+0x6FA5,0x6FA6,0x6FA7,0x6FA8,0x6FAE,0x6FAF,0x6FB0,0x6FB5,
+0x6FB6,0x6FBC,0x6FC5,0x6FC7,0x6FC8,0x6FCA};
+
+/* page 33 0x4921-0x497E */
+static uint16 tab_jisx0212_uni33[]={
+0x6FDA,0x6FDE,0x6FE8,0x6FE9,0x6FF0,0x6FF5,0x6FF9,0x6FFC,
+0x6FFD,0x7000,0x7005,0x7006,0x7007,0x700D,0x7017,0x7020,
+0x7023,0x702F,0x7034,0x7037,0x7039,0x703C,0x7043,0x7044,
+0x7048,0x7049,0x704A,0x704B,0x7054,0x7055,0x705D,0x705E,
+0x704E,0x7064,0x7065,0x706C,0x706E,0x7075,0x7076,0x707E,
+0x7081,0x7085,0x7086,0x7094,0x7095,0x7096,0x7097,0x7098,
+0x709B,0x70A4,0x70AB,0x70B0,0x70B1,0x70B4,0x70B7,0x70CA,
+0x70D1,0x70D3,0x70D4,0x70D5,0x70D6,0x70D8,0x70DC,0x70E4,
+0x70FA,0x7103,0x7104,0x7105,0x7106,0x7107,0x710B,0x710C,
+0x710F,0x711E,0x7120,0x712B,0x712D,0x712F,0x7130,0x7131,
+0x7138,0x7141,0x7145,0x7146,0x7147,0x714A,0x714B,0x7150,
+0x7152,0x7157,0x715A,0x715C,0x715E,0x7160};
+
+/* page 34 0x4A21-0x4A7E */
+static uint16 tab_jisx0212_uni34[]={
+0x7168,0x7179,0x7180,0x7185,0x7187,0x718C,0x7192,0x719A,
+0x719B,0x71A0,0x71A2,0x71AF,0x71B0,0x71B2,0x71B3,0x71BA,
+0x71BF,0x71C0,0x71C1,0x71C4,0x71CB,0x71CC,0x71D3,0x71D6,
+0x71D9,0x71DA,0x71DC,0x71F8,0x71FE,0x7200,0x7207,0x7208,
+0x7209,0x7213,0x7217,0x721A,0x721D,0x721F,0x7224,0x722B,
+0x722F,0x7234,0x7238,0x7239,0x7241,0x7242,0x7243,0x7245,
+0x724E,0x724F,0x7250,0x7253,0x7255,0x7256,0x725A,0x725C,
+0x725E,0x7260,0x7263,0x7268,0x726B,0x726E,0x726F,0x7271,
+0x7277,0x7278,0x727B,0x727C,0x727F,0x7284,0x7289,0x728D,
+0x728E,0x7293,0x729B,0x72A8,0x72AD,0x72AE,0x72B1,0x72B4,
+0x72BE,0x72C1,0x72C7,0x72C9,0x72CC,0x72D5,0x72D6,0x72D8,
+0x72DF,0x72E5,0x72F3,0x72F4,0x72FA,0x72FB};
+
+/* page 35 0x4B21-0x4B7E */
+static uint16 tab_jisx0212_uni35[]={
+0x72FE,0x7302,0x7304,0x7305,0x7307,0x730B,0x730D,0x7312,
+0x7313,0x7318,0x7319,0x731E,0x7322,0x7324,0x7327,0x7328,
+0x732C,0x7331,0x7332,0x7335,0x733A,0x733B,0x733D,0x7343,
+0x734D,0x7350,0x7352,0x7356,0x7358,0x735D,0x735E,0x735F,
+0x7360,0x7366,0x7367,0x7369,0x736B,0x736C,0x736E,0x736F,
+0x7371,0x7377,0x7379,0x737C,0x7380,0x7381,0x7383,0x7385,
+0x7386,0x738E,0x7390,0x7393,0x7395,0x7397,0x7398,0x739C,
+0x739E,0x739F,0x73A0,0x73A2,0x73A5,0x73A6,0x73AA,0x73AB,
+0x73AD,0x73B5,0x73B7,0x73B9,0x73BC,0x73BD,0x73BF,0x73C5,
+0x73C6,0x73C9,0x73CB,0x73CC,0x73CF,0x73D2,0x73D3,0x73D6,
+0x73D9,0x73DD,0x73E1,0x73E3,0x73E6,0x73E7,0x73E9,0x73F4,
+0x73F5,0x73F7,0x73F9,0x73FA,0x73FB,0x73FD};
+
+/* page 36 0x4C21-0x4C7E */
+static uint16 tab_jisx0212_uni36[]={
+0x73FF,0x7400,0x7401,0x7404,0x7407,0x740A,0x7411,0x741A,
+0x741B,0x7424,0x7426,0x7428,0x7429,0x742A,0x742B,0x742C,
+0x742D,0x742E,0x742F,0x7430,0x7431,0x7439,0x7440,0x7443,
+0x7444,0x7446,0x7447,0x744B,0x744D,0x7451,0x7452,0x7457,
+0x745D,0x7462,0x7466,0x7467,0x7468,0x746B,0x746D,0x746E,
+0x7471,0x7472,0x7480,0x7481,0x7485,0x7486,0x7487,0x7489,
+0x748F,0x7490,0x7491,0x7492,0x7498,0x7499,0x749A,0x749C,
+0x749F,0x74A0,0x74A1,0x74A3,0x74A6,0x74A8,0x74A9,0x74AA,
+0x74AB,0x74AE,0x74AF,0x74B1,0x74B2,0x74B5,0x74B9,0x74BB,
+0x74BF,0x74C8,0x74C9,0x74CC,0x74D0,0x74D3,0x74D8,0x74DA,
+0x74DB,0x74DE,0x74DF,0x74E4,0x74E8,0x74EA,0x74EB,0x74EF,
+0x74F4,0x74FA,0x74FB,0x74FC,0x74FF,0x7506};
+
+/* page 37 0x4D21-0x4D7E */
+static uint16 tab_jisx0212_uni37[]={
+0x7512,0x7516,0x7517,0x7520,0x7521,0x7524,0x7527,0x7529,
+0x752A,0x752F,0x7536,0x7539,0x753D,0x753E,0x753F,0x7540,
+0x7543,0x7547,0x7548,0x754E,0x7550,0x7552,0x7557,0x755E,
+0x755F,0x7561,0x756F,0x7571,0x7579,0x757A,0x757B,0x757C,
+0x757D,0x757E,0x7581,0x7585,0x7590,0x7592,0x7593,0x7595,
+0x7599,0x759C,0x75A2,0x75A4,0x75B4,0x75BA,0x75BF,0x75C0,
+0x75C1,0x75C4,0x75C6,0x75CC,0x75CE,0x75CF,0x75D7,0x75DC,
+0x75DF,0x75E0,0x75E1,0x75E4,0x75E7,0x75EC,0x75EE,0x75EF,
+0x75F1,0x75F9,0x7600,0x7602,0x7603,0x7604,0x7607,0x7608,
+0x760A,0x760C,0x760F,0x7612,0x7613,0x7615,0x7616,0x7619,
+0x761B,0x761C,0x761D,0x761E,0x7623,0x7625,0x7626,0x7629,
+0x762D,0x7632,0x7633,0x7635,0x7638,0x7639};
+
+/* page 38 0x4E21-0x4E7E */
+static uint16 tab_jisx0212_uni38[]={
+0x763A,0x763C,0x764A,0x7640,0x7641,0x7643,0x7644,0x7645,
+0x7649,0x764B,0x7655,0x7659,0x765F,0x7664,0x7665,0x766D,
+0x766E,0x766F,0x7671,0x7674,0x7681,0x7685,0x768C,0x768D,
+0x7695,0x769B,0x769C,0x769D,0x769F,0x76A0,0x76A2,0x76A3,
+0x76A4,0x76A5,0x76A6,0x76A7,0x76A8,0x76AA,0x76AD,0x76BD,
+0x76C1,0x76C5,0x76C9,0x76CB,0x76CC,0x76CE,0x76D4,0x76D9,
+0x76E0,0x76E6,0x76E8,0x76EC,0x76F0,0x76F1,0x76F6,0x76F9,
+0x76FC,0x7700,0x7706,0x770A,0x770E,0x7712,0x7714,0x7715,
+0x7717,0x7719,0x771A,0x771C,0x7722,0x7728,0x772D,0x772E,
+0x772F,0x7734,0x7735,0x7736,0x7739,0x773D,0x773E,0x7742,
+0x7745,0x7746,0x774A,0x774D,0x774E,0x774F,0x7752,0x7756,
+0x7757,0x775C,0x775E,0x775F,0x7760,0x7762};
+
+/* page 39 0x4F21-0x4F7E */
+static uint16 tab_jisx0212_uni39[]={
+0x7764,0x7767,0x776A,0x776C,0x7770,0x7772,0x7773,0x7774,
+0x777A,0x777D,0x7780,0x7784,0x778C,0x778D,0x7794,0x7795,
+0x7796,0x779A,0x779F,0x77A2,0x77A7,0x77AA,0x77AE,0x77AF,
+0x77B1,0x77B5,0x77BE,0x77C3,0x77C9,0x77D1,0x77D2,0x77D5,
+0x77D9,0x77DE,0x77DF,0x77E0,0x77E4,0x77E6,0x77EA,0x77EC,
+0x77F0,0x77F1,0x77F4,0x77F8,0x77FB,0x7805,0x7806,0x7809,
+0x780D,0x780E,0x7811,0x781D,0x7821,0x7822,0x7823,0x782D,
+0x782E,0x7830,0x7835,0x7837,0x7843,0x7844,0x7847,0x7848,
+0x784C,0x784E,0x7852,0x785C,0x785E,0x7860,0x7861,0x7863,
+0x7864,0x7868,0x786A,0x786E,0x787A,0x787E,0x788A,0x788F,
+0x7894,0x7898,0x78A1,0x789D,0x789E,0x789F,0x78A4,0x78A8,
+0x78AC,0x78AD,0x78B0,0x78B1,0x78B2,0x78B3};
+
+/* page 40 0x5021-0x507E */
+static uint16 tab_jisx0212_uni40[]={
+0x78BB,0x78BD,0x78BF,0x78C7,0x78C8,0x78C9,0x78CC,0x78CE,
+0x78D2,0x78D3,0x78D5,0x78D6,0x78E4,0x78DB,0x78DF,0x78E0,
+0x78E1,0x78E6,0x78EA,0x78F2,0x78F3,0x7900,0x78F6,0x78F7,
+0x78FA,0x78FB,0x78FF,0x7906,0x790C,0x7910,0x791A,0x791C,
+0x791E,0x791F,0x7920,0x7925,0x7927,0x7929,0x792D,0x7931,
+0x7934,0x7935,0x793B,0x793D,0x793F,0x7944,0x7945,0x7946,
+0x794A,0x794B,0x794F,0x7951,0x7954,0x7958,0x795B,0x795C,
+0x7967,0x7969,0x796B,0x7972,0x7979,0x797B,0x797C,0x797E,
+0x798B,0x798C,0x7991,0x7993,0x7994,0x7995,0x7996,0x7998,
+0x799B,0x799C,0x79A1,0x79A8,0x79A9,0x79AB,0x79AF,0x79B1,
+0x79B4,0x79B8,0x79BB,0x79C2,0x79C4,0x79C7,0x79C8,0x79CA,
+0x79CF,0x79D4,0x79D6,0x79DA,0x79DD,0x79DE};
+
+/* page 41 0x5121-0x517E */
+static uint16 tab_jisx0212_uni41[]={
+0x79E0,0x79E2,0x79E5,0x79EA,0x79EB,0x79ED,0x79F1,0x79F8,
+0x79FC,0x7A02,0x7A03,0x7A07,0x7A09,0x7A0A,0x7A0C,0x7A11,
+0x7A15,0x7A1B,0x7A1E,0x7A21,0x7A27,0x7A2B,0x7A2D,0x7A2F,
+0x7A30,0x7A34,0x7A35,0x7A38,0x7A39,0x7A3A,0x7A44,0x7A45,
+0x7A47,0x7A48,0x7A4C,0x7A55,0x7A56,0x7A59,0x7A5C,0x7A5D,
+0x7A5F,0x7A60,0x7A65,0x7A67,0x7A6A,0x7A6D,0x7A75,0x7A78,
+0x7A7E,0x7A80,0x7A82,0x7A85,0x7A86,0x7A8A,0x7A8B,0x7A90,
+0x7A91,0x7A94,0x7A9E,0x7AA0,0x7AA3,0x7AAC,0x7AB3,0x7AB5,
+0x7AB9,0x7ABB,0x7ABC,0x7AC6,0x7AC9,0x7ACC,0x7ACE,0x7AD1,
+0x7ADB,0x7AE8,0x7AE9,0x7AEB,0x7AEC,0x7AF1,0x7AF4,0x7AFB,
+0x7AFD,0x7AFE,0x7B07,0x7B14,0x7B1F,0x7B23,0x7B27,0x7B29,
+0x7B2A,0x7B2B,0x7B2D,0x7B2E,0x7B2F,0x7B30};
+
+/* page 42 0x5221-0x527E */
+static uint16 tab_jisx0212_uni42[]={
+0x7B31,0x7B34,0x7B3D,0x7B3F,0x7B40,0x7B41,0x7B47,0x7B4E,
+0x7B55,0x7B60,0x7B64,0x7B66,0x7B69,0x7B6A,0x7B6D,0x7B6F,
+0x7B72,0x7B73,0x7B77,0x7B84,0x7B89,0x7B8E,0x7B90,0x7B91,
+0x7B96,0x7B9B,0x7B9E,0x7BA0,0x7BA5,0x7BAC,0x7BAF,0x7BB0,
+0x7BB2,0x7BB5,0x7BB6,0x7BBA,0x7BBB,0x7BBC,0x7BBD,0x7BC2,
+0x7BC5,0x7BC8,0x7BCA,0x7BD4,0x7BD6,0x7BD7,0x7BD9,0x7BDA,
+0x7BDB,0x7BE8,0x7BEA,0x7BF2,0x7BF4,0x7BF5,0x7BF8,0x7BF9,
+0x7BFA,0x7BFC,0x7BFE,0x7C01,0x7C02,0x7C03,0x7C04,0x7C06,
+0x7C09,0x7C0B,0x7C0C,0x7C0E,0x7C0F,0x7C19,0x7C1B,0x7C20,
+0x7C25,0x7C26,0x7C28,0x7C2C,0x7C31,0x7C33,0x7C34,0x7C36,
+0x7C39,0x7C3A,0x7C46,0x7C4A,0x7C55,0x7C51,0x7C52,0x7C53,
+0x7C59,0x7C5A,0x7C5B,0x7C5C,0x7C5D,0x7C5E};
+
+/* page 43 0x5321-0x537E */
+static uint16 tab_jisx0212_uni43[]={
+0x7C61,0x7C63,0x7C67,0x7C69,0x7C6D,0x7C6E,0x7C70,0x7C72,
+0x7C79,0x7C7C,0x7C7D,0x7C86,0x7C87,0x7C8F,0x7C94,0x7C9E,
+0x7CA0,0x7CA6,0x7CB0,0x7CB6,0x7CB7,0x7CBA,0x7CBB,0x7CBC,
+0x7CBF,0x7CC4,0x7CC7,0x7CC8,0x7CC9,0x7CCD,0x7CCF,0x7CD3,
+0x7CD4,0x7CD5,0x7CD7,0x7CD9,0x7CDA,0x7CDD,0x7CE6,0x7CE9,
+0x7CEB,0x7CF5,0x7D03,0x7D07,0x7D08,0x7D09,0x7D0F,0x7D11,
+0x7D12,0x7D13,0x7D16,0x7D1D,0x7D1E,0x7D23,0x7D26,0x7D2A,
+0x7D2D,0x7D31,0x7D3C,0x7D3D,0x7D3E,0x7D40,0x7D41,0x7D47,
+0x7D48,0x7D4D,0x7D51,0x7D53,0x7D57,0x7D59,0x7D5A,0x7D5C,
+0x7D5D,0x7D65,0x7D67,0x7D6A,0x7D70,0x7D78,0x7D7A,0x7D7B,
+0x7D7F,0x7D81,0x7D82,0x7D83,0x7D85,0x7D86,0x7D88,0x7D8B,
+0x7D8C,0x7D8D,0x7D91,0x7D96,0x7D97,0x7D9D};
+
+/* page 44 0x5421-0x547E */
+static uint16 tab_jisx0212_uni44[]={
+0x7D9E,0x7DA6,0x7DA7,0x7DAA,0x7DB3,0x7DB6,0x7DB7,0x7DB9,
+0x7DC2,0x7DC3,0x7DC4,0x7DC5,0x7DC6,0x7DCC,0x7DCD,0x7DCE,
+0x7DD7,0x7DD9,0x7E00,0x7DE2,0x7DE5,0x7DE6,0x7DEA,0x7DEB,
+0x7DED,0x7DF1,0x7DF5,0x7DF6,0x7DF9,0x7DFA,0x7E08,0x7E10,
+0x7E11,0x7E15,0x7E17,0x7E1C,0x7E1D,0x7E20,0x7E27,0x7E28,
+0x7E2C,0x7E2D,0x7E2F,0x7E33,0x7E36,0x7E3F,0x7E44,0x7E45,
+0x7E47,0x7E4E,0x7E50,0x7E52,0x7E58,0x7E5F,0x7E61,0x7E62,
+0x7E65,0x7E6B,0x7E6E,0x7E6F,0x7E73,0x7E78,0x7E7E,0x7E81,
+0x7E86,0x7E87,0x7E8A,0x7E8D,0x7E91,0x7E95,0x7E98,0x7E9A,
+0x7E9D,0x7E9E,0x7F3C,0x7F3B,0x7F3D,0x7F3E,0x7F3F,0x7F43,
+0x7F44,0x7F47,0x7F4F,0x7F52,0x7F53,0x7F5B,0x7F5C,0x7F5D,
+0x7F61,0x7F63,0x7F64,0x7F65,0x7F66,0x7F6D};
+
+/* page 45 0x5521-0x557E */
+static uint16 tab_jisx0212_uni45[]={
+0x7F71,0x7F7D,0x7F7E,0x7F7F,0x7F80,0x7F8B,0x7F8D,0x7F8F,
+0x7F90,0x7F91,0x7F96,0x7F97,0x7F9C,0x7FA1,0x7FA2,0x7FA6,
+0x7FAA,0x7FAD,0x7FB4,0x7FBC,0x7FBF,0x7FC0,0x7FC3,0x7FC8,
+0x7FCE,0x7FCF,0x7FDB,0x7FDF,0x7FE3,0x7FE5,0x7FE8,0x7FEC,
+0x7FEE,0x7FEF,0x7FF2,0x7FFA,0x7FFD,0x7FFE,0x7FFF,0x8007,
+0x8008,0x800A,0x800D,0x800E,0x800F,0x8011,0x8013,0x8014,
+0x8016,0x801D,0x801E,0x801F,0x8020,0x8024,0x8026,0x802C,
+0x802E,0x8030,0x8034,0x8035,0x8037,0x8039,0x803A,0x803C,
+0x803E,0x8040,0x8044,0x8060,0x8064,0x8066,0x806D,0x8071,
+0x8075,0x8081,0x8088,0x808E,0x809C,0x809E,0x80A6,0x80A7,
+0x80AB,0x80B8,0x80B9,0x80C8,0x80CD,0x80CF,0x80D2,0x80D4,
+0x80D5,0x80D7,0x80D8,0x80E0,0x80ED,0x80EE};
+
+/* page 46 0x5621-0x567E */
+static uint16 tab_jisx0212_uni46[]={
+0x80F0,0x80F2,0x80F3,0x80F6,0x80F9,0x80FA,0x80FE,0x8103,
+0x810B,0x8116,0x8117,0x8118,0x811C,0x811E,0x8120,0x8124,
+0x8127,0x812C,0x8130,0x8135,0x813A,0x813C,0x8145,0x8147,
+0x814A,0x814C,0x8152,0x8157,0x8160,0x8161,0x8167,0x8168,
+0x8169,0x816D,0x816F,0x8177,0x8181,0x8190,0x8184,0x8185,
+0x8186,0x818B,0x818E,0x8196,0x8198,0x819B,0x819E,0x81A2,
+0x81AE,0x81B2,0x81B4,0x81BB,0x81CB,0x81C3,0x81C5,0x81CA,
+0x81CE,0x81CF,0x81D5,0x81D7,0x81DB,0x81DD,0x81DE,0x81E1,
+0x81E4,0x81EB,0x81EC,0x81F0,0x81F1,0x81F2,0x81F5,0x81F6,
+0x81F8,0x81F9,0x81FD,0x81FF,0x8200,0x8203,0x820F,0x8213,
+0x8214,0x8219,0x821A,0x821D,0x8221,0x8222,0x8228,0x8232,
+0x8234,0x823A,0x8243,0x8244,0x8245,0x8246};
+
+/* page 47 0x5721-0x577E */
+static uint16 tab_jisx0212_uni47[]={
+0x824B,0x824E,0x824F,0x8251,0x8256,0x825C,0x8260,0x8263,
+0x8267,0x826D,0x8274,0x827B,0x827D,0x827F,0x8280,0x8281,
+0x8283,0x8284,0x8287,0x8289,0x828A,0x828E,0x8291,0x8294,
+0x8296,0x8298,0x829A,0x829B,0x82A0,0x82A1,0x82A3,0x82A4,
+0x82A7,0x82A8,0x82A9,0x82AA,0x82AE,0x82B0,0x82B2,0x82B4,
+0x82B7,0x82BA,0x82BC,0x82BE,0x82BF,0x82C6,0x82D0,0x82D5,
+0x82DA,0x82E0,0x82E2,0x82E4,0x82E8,0x82EA,0x82ED,0x82EF,
+0x82F6,0x82F7,0x82FD,0x82FE,0x8300,0x8301,0x8307,0x8308,
+0x830A,0x830B,0x8354,0x831B,0x831D,0x831E,0x831F,0x8321,
+0x8322,0x832C,0x832D,0x832E,0x8330,0x8333,0x8337,0x833A,
+0x833C,0x833D,0x8342,0x8343,0x8344,0x8347,0x834D,0x834E,
+0x8351,0x8355,0x8356,0x8357,0x8370,0x8378};
+
+/* page 48 0x5821-0x587E */
+static uint16 tab_jisx0212_uni48[]={
+0x837D,0x837F,0x8380,0x8382,0x8384,0x8386,0x838D,0x8392,
+0x8394,0x8395,0x8398,0x8399,0x839B,0x839C,0x839D,0x83A6,
+0x83A7,0x83A9,0x83AC,0x83BE,0x83BF,0x83C0,0x83C7,0x83C9,
+0x83CF,0x83D0,0x83D1,0x83D4,0x83DD,0x8353,0x83E8,0x83EA,
+0x83F6,0x83F8,0x83F9,0x83FC,0x8401,0x8406,0x840A,0x840F,
+0x8411,0x8415,0x8419,0x83AD,0x842F,0x8439,0x8445,0x8447,
+0x8448,0x844A,0x844D,0x844F,0x8451,0x8452,0x8456,0x8458,
+0x8459,0x845A,0x845C,0x8460,0x8464,0x8465,0x8467,0x846A,
+0x8470,0x8473,0x8474,0x8476,0x8478,0x847C,0x847D,0x8481,
+0x8485,0x8492,0x8493,0x8495,0x849E,0x84A6,0x84A8,0x84A9,
+0x84AA,0x84AF,0x84B1,0x84B4,0x84BA,0x84BD,0x84BE,0x84C0,
+0x84C2,0x84C7,0x84C8,0x84CC,0x84CF,0x84D3};
+
+/* page 49 0x5921-0x597E */
+static uint16 tab_jisx0212_uni49[]={
+0x84DC,0x84E7,0x84EA,0x84EF,0x84F0,0x84F1,0x84F2,0x84F7,
+0x8532,0x84FA,0x84FB,0x84FD,0x8502,0x8503,0x8507,0x850C,
+0x850E,0x8510,0x851C,0x851E,0x8522,0x8523,0x8524,0x8525,
+0x8527,0x852A,0x852B,0x852F,0x8533,0x8534,0x8536,0x853F,
+0x8546,0x854F,0x8550,0x8551,0x8552,0x8553,0x8556,0x8559,
+0x855C,0x855D,0x855E,0x855F,0x8560,0x8561,0x8562,0x8564,
+0x856B,0x856F,0x8579,0x857A,0x857B,0x857D,0x857F,0x8581,
+0x8585,0x8586,0x8589,0x858B,0x858C,0x858F,0x8593,0x8598,
+0x859D,0x859F,0x85A0,0x85A2,0x85A5,0x85A7,0x85B4,0x85B6,
+0x85B7,0x85B8,0x85BC,0x85BD,0x85BE,0x85BF,0x85C2,0x85C7,
+0x85CA,0x85CB,0x85CE,0x85AD,0x85D8,0x85DA,0x85DF,0x85E0,
+0x85E6,0x85E8,0x85ED,0x85F3,0x85F6,0x85FC};
+
+/* page 50 0x5A21-0x5A7E */
+static uint16 tab_jisx0212_uni50[]={
+0x85FF,0x8600,0x8604,0x8605,0x860D,0x860E,0x8610,0x8611,
+0x8612,0x8618,0x8619,0x861B,0x861E,0x8621,0x8627,0x8629,
+0x8636,0x8638,0x863A,0x863C,0x863D,0x8640,0x8642,0x8646,
+0x8652,0x8653,0x8656,0x8657,0x8658,0x8659,0x865D,0x8660,
+0x8661,0x8662,0x8663,0x8664,0x8669,0x866C,0x866F,0x8675,
+0x8676,0x8677,0x867A,0x868D,0x8691,0x8696,0x8698,0x869A,
+0x869C,0x86A1,0x86A6,0x86A7,0x86A8,0x86AD,0x86B1,0x86B3,
+0x86B4,0x86B5,0x86B7,0x86B8,0x86B9,0x86BF,0x86C0,0x86C1,
+0x86C3,0x86C5,0x86D1,0x86D2,0x86D5,0x86D7,0x86DA,0x86DC,
+0x86E0,0x86E3,0x86E5,0x86E7,0x8688,0x86FA,0x86FC,0x86FD,
+0x8704,0x8705,0x8707,0x870B,0x870E,0x870F,0x8710,0x8713,
+0x8714,0x8719,0x871E,0x871F,0x8721,0x8723};
+
+/* page 51 0x5B21-0x5B7E */
+static uint16 tab_jisx0212_uni51[]={
+0x8728,0x872E,0x872F,0x8731,0x8732,0x8739,0x873A,0x873C,
+0x873D,0x873E,0x8740,0x8743,0x8745,0x874D,0x8758,0x875D,
+0x8761,0x8764,0x8765,0x876F,0x8771,0x8772,0x877B,0x8783,
+0x8784,0x8785,0x8786,0x8787,0x8788,0x8789,0x878B,0x878C,
+0x8790,0x8793,0x8795,0x8797,0x8798,0x8799,0x879E,0x87A0,
+0x87A3,0x87A7,0x87AC,0x87AD,0x87AE,0x87B1,0x87B5,0x87BE,
+0x87BF,0x87C1,0x87C8,0x87C9,0x87CA,0x87CE,0x87D5,0x87D6,
+0x87D9,0x87DA,0x87DC,0x87DF,0x87E2,0x87E3,0x87E4,0x87EA,
+0x87EB,0x87ED,0x87F1,0x87F3,0x87F8,0x87FA,0x87FF,0x8801,
+0x8803,0x8806,0x8809,0x880A,0x880B,0x8810,0x8819,0x8812,
+0x8813,0x8814,0x8818,0x881A,0x881B,0x881C,0x881E,0x881F,
+0x8828,0x882D,0x882E,0x8830,0x8832,0x8835};
+
+/* page 52 0x5C21-0x5C7E */
+static uint16 tab_jisx0212_uni52[]={
+0x883A,0x883C,0x8841,0x8843,0x8845,0x8848,0x8849,0x884A,
+0x884B,0x884E,0x8851,0x8855,0x8856,0x8858,0x885A,0x885C,
+0x885F,0x8860,0x8864,0x8869,0x8871,0x8879,0x887B,0x8880,
+0x8898,0x889A,0x889B,0x889C,0x889F,0x88A0,0x88A8,0x88AA,
+0x88BA,0x88BD,0x88BE,0x88C0,0x88CA,0x88CB,0x88CC,0x88CD,
+0x88CE,0x88D1,0x88D2,0x88D3,0x88DB,0x88DE,0x88E7,0x88EF,
+0x88F0,0x88F1,0x88F5,0x88F7,0x8901,0x8906,0x890D,0x890E,
+0x890F,0x8915,0x8916,0x8918,0x8919,0x891A,0x891C,0x8920,
+0x8926,0x8927,0x8928,0x8930,0x8931,0x8932,0x8935,0x8939,
+0x893A,0x893E,0x8940,0x8942,0x8945,0x8946,0x8949,0x894F,
+0x8952,0x8957,0x895A,0x895B,0x895C,0x8961,0x8962,0x8963,
+0x896B,0x896E,0x8970,0x8973,0x8975,0x897A};
+
+/* page 53 0x5D21-0x5D7E */
+static uint16 tab_jisx0212_uni53[]={
+0x897B,0x897C,0x897D,0x8989,0x898D,0x8990,0x8994,0x8995,
+0x899B,0x899C,0x899F,0x89A0,0x89A5,0x89B0,0x89B4,0x89B5,
+0x89B6,0x89B7,0x89BC,0x89D4,0x89D5,0x89D6,0x89D7,0x89D8,
+0x89E5,0x89E9,0x89EB,0x89ED,0x89F1,0x89F3,0x89F6,0x89F9,
+0x89FD,0x89FF,0x8A04,0x8A05,0x8A07,0x8A0F,0x8A11,0x8A12,
+0x8A14,0x8A15,0x8A1E,0x8A20,0x8A22,0x8A24,0x8A26,0x8A2B,
+0x8A2C,0x8A2F,0x8A35,0x8A37,0x8A3D,0x8A3E,0x8A40,0x8A43,
+0x8A45,0x8A47,0x8A49,0x8A4D,0x8A4E,0x8A53,0x8A56,0x8A57,
+0x8A58,0x8A5C,0x8A5D,0x8A61,0x8A65,0x8A67,0x8A75,0x8A76,
+0x8A77,0x8A79,0x8A7A,0x8A7B,0x8A7E,0x8A7F,0x8A80,0x8A83,
+0x8A86,0x8A8B,0x8A8F,0x8A90,0x8A92,0x8A96,0x8A97,0x8A99,
+0x8A9F,0x8AA7,0x8AA9,0x8AAE,0x8AAF,0x8AB3};
+
+/* page 54 0x5E21-0x5E7E */
+static uint16 tab_jisx0212_uni54[]={
+0x8AB6,0x8AB7,0x8ABB,0x8ABE,0x8AC3,0x8AC6,0x8AC8,0x8AC9,
+0x8ACA,0x8AD1,0x8AD3,0x8AD4,0x8AD5,0x8AD7,0x8ADD,0x8ADF,
+0x8AEC,0x8AF0,0x8AF4,0x8AF5,0x8AF6,0x8AFC,0x8AFF,0x8B05,
+0x8B06,0x8B0B,0x8B11,0x8B1C,0x8B1E,0x8B1F,0x8B0A,0x8B2D,
+0x8B30,0x8B37,0x8B3C,0x8B42,0x8B43,0x8B44,0x8B45,0x8B46,
+0x8B48,0x8B52,0x8B53,0x8B54,0x8B59,0x8B4D,0x8B5E,0x8B63,
+0x8B6D,0x8B76,0x8B78,0x8B79,0x8B7C,0x8B7E,0x8B81,0x8B84,
+0x8B85,0x8B8B,0x8B8D,0x8B8F,0x8B94,0x8B95,0x8B9C,0x8B9E,
+0x8B9F,0x8C38,0x8C39,0x8C3D,0x8C3E,0x8C45,0x8C47,0x8C49,
+0x8C4B,0x8C4F,0x8C51,0x8C53,0x8C54,0x8C57,0x8C58,0x8C5B,
+0x8C5D,0x8C59,0x8C63,0x8C64,0x8C66,0x8C68,0x8C69,0x8C6D,
+0x8C73,0x8C75,0x8C76,0x8C7B,0x8C7E,0x8C86};
+
+/* page 55 0x5F21-0x5F7E */
+static uint16 tab_jisx0212_uni55[]={
+0x8C87,0x8C8B,0x8C90,0x8C92,0x8C93,0x8C99,0x8C9B,0x8C9C,
+0x8CA4,0x8CB9,0x8CBA,0x8CC5,0x8CC6,0x8CC9,0x8CCB,0x8CCF,
+0x8CD6,0x8CD5,0x8CD9,0x8CDD,0x8CE1,0x8CE8,0x8CEC,0x8CEF,
+0x8CF0,0x8CF2,0x8CF5,0x8CF7,0x8CF8,0x8CFE,0x8CFF,0x8D01,
+0x8D03,0x8D09,0x8D12,0x8D17,0x8D1B,0x8D65,0x8D69,0x8D6C,
+0x8D6E,0x8D7F,0x8D82,0x8D84,0x8D88,0x8D8D,0x8D90,0x8D91,
+0x8D95,0x8D9E,0x8D9F,0x8DA0,0x8DA6,0x8DAB,0x8DAC,0x8DAF,
+0x8DB2,0x8DB5,0x8DB7,0x8DB9,0x8DBB,0x8DC0,0x8DC5,0x8DC6,
+0x8DC7,0x8DC8,0x8DCA,0x8DCE,0x8DD1,0x8DD4,0x8DD5,0x8DD7,
+0x8DD9,0x8DE4,0x8DE5,0x8DE7,0x8DEC,0x8DF0,0x8DBC,0x8DF1,
+0x8DF2,0x8DF4,0x8DFD,0x8E01,0x8E04,0x8E05,0x8E06,0x8E0B,
+0x8E11,0x8E14,0x8E16,0x8E20,0x8E21,0x8E22};
+
+/* page 56 0x6021-0x607E */
+static uint16 tab_jisx0212_uni56[]={
+0x8E23,0x8E26,0x8E27,0x8E31,0x8E33,0x8E36,0x8E37,0x8E38,
+0x8E39,0x8E3D,0x8E40,0x8E41,0x8E4B,0x8E4D,0x8E4E,0x8E4F,
+0x8E54,0x8E5B,0x8E5C,0x8E5D,0x8E5E,0x8E61,0x8E62,0x8E69,
+0x8E6C,0x8E6D,0x8E6F,0x8E70,0x8E71,0x8E79,0x8E7A,0x8E7B,
+0x8E82,0x8E83,0x8E89,0x8E90,0x8E92,0x8E95,0x8E9A,0x8E9B,
+0x8E9D,0x8E9E,0x8EA2,0x8EA7,0x8EA9,0x8EAD,0x8EAE,0x8EB3,
+0x8EB5,0x8EBA,0x8EBB,0x8EC0,0x8EC1,0x8EC3,0x8EC4,0x8EC7,
+0x8ECF,0x8ED1,0x8ED4,0x8EDC,0x8EE8,0x8EEE,0x8EF0,0x8EF1,
+0x8EF7,0x8EF9,0x8EFA,0x8EED,0x8F00,0x8F02,0x8F07,0x8F08,
+0x8F0F,0x8F10,0x8F16,0x8F17,0x8F18,0x8F1E,0x8F20,0x8F21,
+0x8F23,0x8F25,0x8F27,0x8F28,0x8F2C,0x8F2D,0x8F2E,0x8F34,
+0x8F35,0x8F36,0x8F37,0x8F3A,0x8F40,0x8F41};
+
+/* page 57 0x6121-0x617E */
+static uint16 tab_jisx0212_uni57[]={
+0x8F43,0x8F47,0x8F4F,0x8F51,0x8F52,0x8F53,0x8F54,0x8F55,
+0x8F58,0x8F5D,0x8F5E,0x8F65,0x8F9D,0x8FA0,0x8FA1,0x8FA4,
+0x8FA5,0x8FA6,0x8FB5,0x8FB6,0x8FB8,0x8FBE,0x8FC0,0x8FC1,
+0x8FC6,0x8FCA,0x8FCB,0x8FCD,0x8FD0,0x8FD2,0x8FD3,0x8FD5,
+0x8FE0,0x8FE3,0x8FE4,0x8FE8,0x8FEE,0x8FF1,0x8FF5,0x8FF6,
+0x8FFB,0x8FFE,0x9002,0x9004,0x9008,0x900C,0x9018,0x901B,
+0x9028,0x9029,0x902F,0x902A,0x902C,0x902D,0x9033,0x9034,
+0x9037,0x903F,0x9043,0x9044,0x904C,0x905B,0x905D,0x9062,
+0x9066,0x9067,0x906C,0x9070,0x9074,0x9079,0x9085,0x9088,
+0x908B,0x908C,0x908E,0x9090,0x9095,0x9097,0x9098,0x9099,
+0x909B,0x90A0,0x90A1,0x90A2,0x90A5,0x90B0,0x90B2,0x90B3,
+0x90B4,0x90B6,0x90BD,0x90CC,0x90BE,0x90C3};
+
+/* page 58 0x6221-0x627E */
+static uint16 tab_jisx0212_uni58[]={
+0x90C4,0x90C5,0x90C7,0x90C8,0x90D5,0x90D7,0x90D8,0x90D9,
+0x90DC,0x90DD,0x90DF,0x90E5,0x90D2,0x90F6,0x90EB,0x90EF,
+0x90F0,0x90F4,0x90FE,0x90FF,0x9100,0x9104,0x9105,0x9106,
+0x9108,0x910D,0x9110,0x9114,0x9116,0x9117,0x9118,0x911A,
+0x911C,0x911E,0x9120,0x9125,0x9122,0x9123,0x9127,0x9129,
+0x912E,0x912F,0x9131,0x9134,0x9136,0x9137,0x9139,0x913A,
+0x913C,0x913D,0x9143,0x9147,0x9148,0x914F,0x9153,0x9157,
+0x9159,0x915A,0x915B,0x9161,0x9164,0x9167,0x916D,0x9174,
+0x9179,0x917A,0x917B,0x9181,0x9183,0x9185,0x9186,0x918A,
+0x918E,0x9191,0x9193,0x9194,0x9195,0x9198,0x919E,0x91A1,
+0x91A6,0x91A8,0x91AC,0x91AD,0x91AE,0x91B0,0x91B1,0x91B2,
+0x91B3,0x91B6,0x91BB,0x91BC,0x91BD,0x91BF};
+
+/* page 59 0x6321-0x637E */
+static uint16 tab_jisx0212_uni59[]={
+0x91C2,0x91C3,0x91C5,0x91D3,0x91D4,0x91D7,0x91D9,0x91DA,
+0x91DE,0x91E4,0x91E5,0x91E9,0x91EA,0x91EC,0x91ED,0x91EE,
+0x91EF,0x91F0,0x91F1,0x91F7,0x91F9,0x91FB,0x91FD,0x9200,
+0x9201,0x9204,0x9205,0x9206,0x9207,0x9209,0x920A,0x920C,
+0x9210,0x9212,0x9213,0x9216,0x9218,0x921C,0x921D,0x9223,
+0x9224,0x9225,0x9226,0x9228,0x922E,0x922F,0x9230,0x9233,
+0x9235,0x9236,0x9238,0x9239,0x923A,0x923C,0x923E,0x9240,
+0x9242,0x9243,0x9246,0x9247,0x924A,0x924D,0x924E,0x924F,
+0x9251,0x9258,0x9259,0x925C,0x925D,0x9260,0x9261,0x9265,
+0x9267,0x9268,0x9269,0x926E,0x926F,0x9270,0x9275,0x9276,
+0x9277,0x9278,0x9279,0x927B,0x927C,0x927D,0x927F,0x9288,
+0x9289,0x928A,0x928D,0x928E,0x9292,0x9297};
+
+/* page 60 0x6421-0x647E */
+static uint16 tab_jisx0212_uni60[]={
+0x9299,0x929F,0x92A0,0x92A4,0x92A5,0x92A7,0x92A8,0x92AB,
+0x92AF,0x92B2,0x92B6,0x92B8,0x92BA,0x92BB,0x92BC,0x92BD,
+0x92BF,0x92C0,0x92C1,0x92C2,0x92C3,0x92C5,0x92C6,0x92C7,
+0x92C8,0x92CB,0x92CC,0x92CD,0x92CE,0x92D0,0x92D3,0x92D5,
+0x92D7,0x92D8,0x92D9,0x92DC,0x92DD,0x92DF,0x92E0,0x92E1,
+0x92E3,0x92E5,0x92E7,0x92E8,0x92EC,0x92EE,0x92F0,0x92F9,
+0x92FB,0x92FF,0x9300,0x9302,0x9308,0x930D,0x9311,0x9314,
+0x9315,0x931C,0x931D,0x931E,0x931F,0x9321,0x9324,0x9325,
+0x9327,0x9329,0x932A,0x9333,0x9334,0x9336,0x9337,0x9347,
+0x9348,0x9349,0x9350,0x9351,0x9352,0x9355,0x9357,0x9358,
+0x935A,0x935E,0x9364,0x9365,0x9367,0x9369,0x936A,0x936D,
+0x936F,0x9370,0x9371,0x9373,0x9374,0x9376};
+
+/* page 61 0x6521-0x657E */
+static uint16 tab_jisx0212_uni61[]={
+0x937A,0x937D,0x937F,0x9380,0x9381,0x9382,0x9388,0x938A,
+0x938B,0x938D,0x938F,0x9392,0x9395,0x9398,0x939B,0x939E,
+0x93A1,0x93A3,0x93A4,0x93A6,0x93A8,0x93AB,0x93B4,0x93B5,
+0x93B6,0x93BA,0x93A9,0x93C1,0x93C4,0x93C5,0x93C6,0x93C7,
+0x93C9,0x93CA,0x93CB,0x93CC,0x93CD,0x93D3,0x93D9,0x93DC,
+0x93DE,0x93DF,0x93E2,0x93E6,0x93E7,0x93F9,0x93F7,0x93F8,
+0x93FA,0x93FB,0x93FD,0x9401,0x9402,0x9404,0x9408,0x9409,
+0x940D,0x940E,0x940F,0x9415,0x9416,0x9417,0x941F,0x942E,
+0x942F,0x9431,0x9432,0x9433,0x9434,0x943B,0x943F,0x943D,
+0x9443,0x9445,0x9448,0x944A,0x944C,0x9455,0x9459,0x945C,
+0x945F,0x9461,0x9463,0x9468,0x946B,0x946D,0x946E,0x946F,
+0x9471,0x9472,0x9484,0x9483,0x9578,0x9579};
+
+/* page 62 0x6621-0x667E */
+static uint16 tab_jisx0212_uni62[]={
+0x957E,0x9584,0x9588,0x958C,0x958D,0x958E,0x959D,0x959E,
+0x959F,0x95A1,0x95A6,0x95A9,0x95AB,0x95AC,0x95B4,0x95B6,
+0x95BA,0x95BD,0x95BF,0x95C6,0x95C8,0x95C9,0x95CB,0x95D0,
+0x95D1,0x95D2,0x95D3,0x95D9,0x95DA,0x95DD,0x95DE,0x95DF,
+0x95E0,0x95E4,0x95E6,0x961D,0x961E,0x9622,0x9624,0x9625,
+0x9626,0x962C,0x9631,0x9633,0x9637,0x9638,0x9639,0x963A,
+0x963C,0x963D,0x9641,0x9652,0x9654,0x9656,0x9657,0x9658,
+0x9661,0x966E,0x9674,0x967B,0x967C,0x967E,0x967F,0x9681,
+0x9682,0x9683,0x9684,0x9689,0x9691,0x9696,0x969A,0x969D,
+0x969F,0x96A4,0x96A5,0x96A6,0x96A9,0x96AE,0x96AF,0x96B3,
+0x96BA,0x96CA,0x96D2,0x5DB2,0x96D8,0x96DA,0x96DD,0x96DE,
+0x96DF,0x96E9,0x96EF,0x96F1,0x96FA,0x9702};
+
+/* page 63 0x6721-0x677E */
+static uint16 tab_jisx0212_uni63[]={
+0x9703,0x9705,0x9709,0x971A,0x971B,0x971D,0x9721,0x9722,
+0x9723,0x9728,0x9731,0x9733,0x9741,0x9743,0x974A,0x974E,
+0x974F,0x9755,0x9757,0x9758,0x975A,0x975B,0x9763,0x9767,
+0x976A,0x976E,0x9773,0x9776,0x9777,0x9778,0x977B,0x977D,
+0x977F,0x9780,0x9789,0x9795,0x9796,0x9797,0x9799,0x979A,
+0x979E,0x979F,0x97A2,0x97AC,0x97AE,0x97B1,0x97B2,0x97B5,
+0x97B6,0x97B8,0x97B9,0x97BA,0x97BC,0x97BE,0x97BF,0x97C1,
+0x97C4,0x97C5,0x97C7,0x97C9,0x97CA,0x97CC,0x97CD,0x97CE,
+0x97D0,0x97D1,0x97D4,0x97D7,0x97D8,0x97D9,0x97DD,0x97DE,
+0x97E0,0x97DB,0x97E1,0x97E4,0x97EF,0x97F1,0x97F4,0x97F7,
+0x97F8,0x97FA,0x9807,0x980A,0x9819,0x980D,0x980E,0x9814,
+0x9816,0x981C,0x981E,0x9820,0x9823,0x9826};
+
+/* page 64 0x6821-0x687E */
+static uint16 tab_jisx0212_uni64[]={
+0x982B,0x982E,0x982F,0x9830,0x9832,0x9833,0x9835,0x9825,
+0x983E,0x9844,0x9847,0x984A,0x9851,0x9852,0x9853,0x9856,
+0x9857,0x9859,0x985A,0x9862,0x9863,0x9865,0x9866,0x986A,
+0x986C,0x98AB,0x98AD,0x98AE,0x98B0,0x98B4,0x98B7,0x98B8,
+0x98BA,0x98BB,0x98BF,0x98C2,0x98C5,0x98C8,0x98CC,0x98E1,
+0x98E3,0x98E5,0x98E6,0x98E7,0x98EA,0x98F3,0x98F6,0x9902,
+0x9907,0x9908,0x9911,0x9915,0x9916,0x9917,0x991A,0x991B,
+0x991C,0x991F,0x9922,0x9926,0x9927,0x992B,0x9931,0x9932,
+0x9933,0x9934,0x9935,0x9939,0x993A,0x993B,0x993C,0x9940,
+0x9941,0x9946,0x9947,0x9948,0x994D,0x994E,0x9954,0x9958,
+0x9959,0x995B,0x995C,0x995E,0x995F,0x9960,0x999B,0x999D,
+0x999F,0x99A6,0x99B0,0x99B1,0x99B2,0x99B5};
+
+/* page 65 0x6921-0x697E */
+static uint16 tab_jisx0212_uni65[]={
+0x99B9,0x99BA,0x99BD,0x99BF,0x99C3,0x99C9,0x99D3,0x99D4,
+0x99D9,0x99DA,0x99DC,0x99DE,0x99E7,0x99EA,0x99EB,0x99EC,
+0x99F0,0x99F4,0x99F5,0x99F9,0x99FD,0x99FE,0x9A02,0x9A03,
+0x9A04,0x9A0B,0x9A0C,0x9A10,0x9A11,0x9A16,0x9A1E,0x9A20,
+0x9A22,0x9A23,0x9A24,0x9A27,0x9A2D,0x9A2E,0x9A33,0x9A35,
+0x9A36,0x9A38,0x9A47,0x9A41,0x9A44,0x9A4A,0x9A4B,0x9A4C,
+0x9A4E,0x9A51,0x9A54,0x9A56,0x9A5D,0x9AAA,0x9AAC,0x9AAE,
+0x9AAF,0x9AB2,0x9AB4,0x9AB5,0x9AB6,0x9AB9,0x9ABB,0x9ABE,
+0x9ABF,0x9AC1,0x9AC3,0x9AC6,0x9AC8,0x9ACE,0x9AD0,0x9AD2,
+0x9AD5,0x9AD6,0x9AD7,0x9ADB,0x9ADC,0x9AE0,0x9AE4,0x9AE5,
+0x9AE7,0x9AE9,0x9AEC,0x9AF2,0x9AF3,0x9AF5,0x9AF9,0x9AFA,
+0x9AFD,0x9AFF,0x9B00,0x9B01,0x9B02,0x9B03};
+
+/* page 66 0x6A21-0x6A7E */
+static uint16 tab_jisx0212_uni66[]={
+0x9B04,0x9B05,0x9B08,0x9B09,0x9B0B,0x9B0C,0x9B0D,0x9B0E,
+0x9B10,0x9B12,0x9B16,0x9B19,0x9B1B,0x9B1C,0x9B20,0x9B26,
+0x9B2B,0x9B2D,0x9B33,0x9B34,0x9B35,0x9B37,0x9B39,0x9B3A,
+0x9B3D,0x9B48,0x9B4B,0x9B4C,0x9B55,0x9B56,0x9B57,0x9B5B,
+0x9B5E,0x9B61,0x9B63,0x9B65,0x9B66,0x9B68,0x9B6A,0x9B6B,
+0x9B6C,0x9B6D,0x9B6E,0x9B73,0x9B75,0x9B77,0x9B78,0x9B79,
+0x9B7F,0x9B80,0x9B84,0x9B85,0x9B86,0x9B87,0x9B89,0x9B8A,
+0x9B8B,0x9B8D,0x9B8F,0x9B90,0x9B94,0x9B9A,0x9B9D,0x9B9E,
+0x9BA6,0x9BA7,0x9BA9,0x9BAC,0x9BB0,0x9BB1,0x9BB2,0x9BB7,
+0x9BB8,0x9BBB,0x9BBC,0x9BBE,0x9BBF,0x9BC1,0x9BC7,0x9BC8,
+0x9BCE,0x9BD0,0x9BD7,0x9BD8,0x9BDD,0x9BDF,0x9BE5,0x9BE7,
+0x9BEA,0x9BEB,0x9BEF,0x9BF3,0x9BF7,0x9BF8};
+
+/* page 67 0x6B21-0x6B7E */
+static uint16 tab_jisx0212_uni67[]={
+0x9BF9,0x9BFA,0x9BFD,0x9BFF,0x9C00,0x9C02,0x9C0B,0x9C0F,
+0x9C11,0x9C16,0x9C18,0x9C19,0x9C1A,0x9C1C,0x9C1E,0x9C22,
+0x9C23,0x9C26,0x9C27,0x9C28,0x9C29,0x9C2A,0x9C31,0x9C35,
+0x9C36,0x9C37,0x9C3D,0x9C41,0x9C43,0x9C44,0x9C45,0x9C49,
+0x9C4A,0x9C4E,0x9C4F,0x9C50,0x9C53,0x9C54,0x9C56,0x9C58,
+0x9C5B,0x9C5D,0x9C5E,0x9C5F,0x9C63,0x9C69,0x9C6A,0x9C5C,
+0x9C6B,0x9C68,0x9C6E,0x9C70,0x9C72,0x9C75,0x9C77,0x9C7B,
+0x9CE6,0x9CF2,0x9CF7,0x9CF9,0x9D0B,0x9D02,0x9D11,0x9D17,
+0x9D18,0x9D1C,0x9D1D,0x9D1E,0x9D2F,0x9D30,0x9D32,0x9D33,
+0x9D34,0x9D3A,0x9D3C,0x9D45,0x9D3D,0x9D42,0x9D43,0x9D47,
+0x9D4A,0x9D53,0x9D54,0x9D5F,0x9D63,0x9D62,0x9D65,0x9D69,
+0x9D6A,0x9D6B,0x9D70,0x9D76,0x9D77,0x9D7B};
+
+/* page 68 0x6C21-0x6C7E */
+static uint16 tab_jisx0212_uni68[]={
+0x9D7C,0x9D7E,0x9D83,0x9D84,0x9D86,0x9D8A,0x9D8D,0x9D8E,
+0x9D92,0x9D93,0x9D95,0x9D96,0x9D97,0x9D98,0x9DA1,0x9DAA,
+0x9DAC,0x9DAE,0x9DB1,0x9DB5,0x9DB9,0x9DBC,0x9DBF,0x9DC3,
+0x9DC7,0x9DC9,0x9DCA,0x9DD4,0x9DD5,0x9DD6,0x9DD7,0x9DDA,
+0x9DDE,0x9DDF,0x9DE0,0x9DE5,0x9DE7,0x9DE9,0x9DEB,0x9DEE,
+0x9DF0,0x9DF3,0x9DF4,0x9DFE,0x9E0A,0x9E02,0x9E07,0x9E0E,
+0x9E10,0x9E11,0x9E12,0x9E15,0x9E16,0x9E19,0x9E1C,0x9E1D,
+0x9E7A,0x9E7B,0x9E7C,0x9E80,0x9E82,0x9E83,0x9E84,0x9E85,
+0x9E87,0x9E8E,0x9E8F,0x9E96,0x9E98,0x9E9B,0x9E9E,0x9EA4,
+0x9EA8,0x9EAC,0x9EAE,0x9EAF,0x9EB0,0x9EB3,0x9EB4,0x9EB5,
+0x9EC6,0x9EC8,0x9ECB,0x9ED5,0x9EDF,0x9EE4,0x9EE7,0x9EEC,
+0x9EED,0x9EEE,0x9EF0,0x9EF1,0x9EF2,0x9EF5};
+
+/* page 69 0x6D21-0x6D63 */
+static uint16 tab_jisx0212_uni69[]={
+0x9EF8,0x9EFF,0x9F02,0x9F03,0x9F09,0x9F0F,0x9F10,0x9F11,
+0x9F12,0x9F14,0x9F16,0x9F17,0x9F19,0x9F1A,0x9F1B,0x9F1F,
+0x9F22,0x9F26,0x9F2A,0x9F2B,0x9F2F,0x9F31,0x9F32,0x9F34,
+0x9F37,0x9F39,0x9F3A,0x9F3C,0x9F3D,0x9F3F,0x9F41,0x9F43,
+0x9F44,0x9F45,0x9F46,0x9F47,0x9F53,0x9F55,0x9F56,0x9F57,
+0x9F58,0x9F5A,0x9F5D,0x9F5E,0x9F68,0x9F69,0x9F6D,0x9F6E,
+0x9F6F,0x9F70,0x9F71,0x9F73,0x9F75,0x9F7A,0x9F7D,0x9F8F,
+0x9F90,0x9F91,0x9F92,0x9F94,0x9F96,0x9F97,0x9F9E,0x9FA1,
+0x9FA2,0x9FA3,0x9FA5};
+
+/* page 70 0x7371-0x737E IBM Kanji and Nonkanji */
+static uint16 tab_jisx0212_uni70[]={
+ 0, 0,0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,
+0x2176,0x2177,0x2178,0x2179,0x2160,0x2161};
+
+/* page 71 0x7421-0x747E IBM Kanji and Nonkanji*/
+static uint16 tab_jisx0212_uni71[]={
+0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,
+0xFF07,0xFF02,0x3231,0x2116,0x2121,0x70BB,0x4EFC,0x50F4,
+0x51EC,0x5307,0x5324,0xFA0E,0x548A,0x5759,0xFA0F,0xFA10,
+0x589E,0x5BEC,0x5CF5,0x5D53,0xFA11,0x5FB7,0x6085,0x6120,
+0x654E,0x663B,0x6665,0xFA12,0xF929,0x6801,0xFA13,0xFA14,
+0x6A6B,0x6AE2,0x6DF8,0x6DF2,0x7028,0xFA15,0xFA16,0x7501,
+0x7682,0x769E,0xFA17,0x7930,0xFA18,0xFA19,0xFA1A,0xFA1B,
+0x7AE7,0xFA1C,0xFA1D,0x7DA0,0x7DD6,0xFA1E,0x8362,0xFA1F,
+0x85B0,0xFA20,0xFA21,0x8807,0xFA22,0x8B7F,0x8CF4,0x8D76,
+0xFA23,0xFA24,0xFA25,0x90DE,0xFA26,0x9115,0xFA27,0xFA28,
+0x9592,0xF9DC,0xFA29,0x973B,0x974D,0x9751,0xFA2A,0xFA2B,
+0xFA2C,0x999E,0x9AD9,0x9B72,0xFA2D,0x9ED1};
+
+static int
+my_jisx0212_uni_onechar(int code){
+ if ((code>=0x222F)&&(code<=0x2244))
+ return(tab_jisx0212_uni0[code-0x222F]);
+ if ((code>=0x226B)&&(code<=0x2271))
+ return(tab_jisx0212_uni1[code-0x226B]);
+ if ((code>=0x2661)&&(code<=0x267C))
+ return(tab_jisx0212_uni2[code-0x2661]);
+ if ((code>=0x2742)&&(code<=0x274E))
+ return(tab_jisx0212_uni3[code-0x2742]);
+ if ((code>=0x2772)&&(code<=0x277E))
+ return(tab_jisx0212_uni4[code-0x2772]);
+ if ((code>=0x2921)&&(code<=0x2950))
+ return(tab_jisx0212_uni5[code-0x2921]);
+ if ((code>=0x2A21)&&(code<=0x2A77))
+ return(tab_jisx0212_uni6[code-0x2A21]);
+ if ((code>=0x2B21)&&(code<=0x2B77))
+ return(tab_jisx0212_uni7[code-0x2B21]);
+ if ((code>=0x3021)&&(code<=0x307E))
+ return(tab_jisx0212_uni8[code-0x3021]);
+ if ((code>=0x3121)&&(code<=0x317E))
+ return(tab_jisx0212_uni9[code-0x3121]);
+ if ((code>=0x3221)&&(code<=0x327E))
+ return(tab_jisx0212_uni10[code-0x3221]);
+ if ((code>=0x3321)&&(code<=0x337E))
+ return(tab_jisx0212_uni11[code-0x3321]);
+ if ((code>=0x3421)&&(code<=0x347E))
+ return(tab_jisx0212_uni12[code-0x3421]);
+ if ((code>=0x3521)&&(code<=0x357E))
+ return(tab_jisx0212_uni13[code-0x3521]);
+ if ((code>=0x3621)&&(code<=0x367E))
+ return(tab_jisx0212_uni14[code-0x3621]);
+ if ((code>=0x3721)&&(code<=0x377E))
+ return(tab_jisx0212_uni15[code-0x3721]);
+ if ((code>=0x3821)&&(code<=0x387E))
+ return(tab_jisx0212_uni16[code-0x3821]);
+ if ((code>=0x3921)&&(code<=0x397E))
+ return(tab_jisx0212_uni17[code-0x3921]);
+ if ((code>=0x3A21)&&(code<=0x3A7E))
+ return(tab_jisx0212_uni18[code-0x3A21]);
+ if ((code>=0x3B21)&&(code<=0x3B7E))
+ return(tab_jisx0212_uni19[code-0x3B21]);
+ if ((code>=0x3C21)&&(code<=0x3C7E))
+ return(tab_jisx0212_uni20[code-0x3C21]);
+ if ((code>=0x3D21)&&(code<=0x3D7E))
+ return(tab_jisx0212_uni21[code-0x3D21]);
+ if ((code>=0x3E21)&&(code<=0x3E7E))
+ return(tab_jisx0212_uni22[code-0x3E21]);
+ if ((code>=0x3F21)&&(code<=0x3F7E))
+ return(tab_jisx0212_uni23[code-0x3F21]);
+ if ((code>=0x4021)&&(code<=0x407E))
+ return(tab_jisx0212_uni24[code-0x4021]);
+ if ((code>=0x4121)&&(code<=0x417E))
+ return(tab_jisx0212_uni25[code-0x4121]);
+ if ((code>=0x4221)&&(code<=0x427E))
+ return(tab_jisx0212_uni26[code-0x4221]);
+ if ((code>=0x4321)&&(code<=0x437E))
+ return(tab_jisx0212_uni27[code-0x4321]);
+ if ((code>=0x4421)&&(code<=0x447E))
+ return(tab_jisx0212_uni28[code-0x4421]);
+ if ((code>=0x4521)&&(code<=0x457E))
+ return(tab_jisx0212_uni29[code-0x4521]);
+ if ((code>=0x4621)&&(code<=0x467E))
+ return(tab_jisx0212_uni30[code-0x4621]);
+ if ((code>=0x4721)&&(code<=0x477E))
+ return(tab_jisx0212_uni31[code-0x4721]);
+ if ((code>=0x4821)&&(code<=0x487E))
+ return(tab_jisx0212_uni32[code-0x4821]);
+ if ((code>=0x4921)&&(code<=0x497E))
+ return(tab_jisx0212_uni33[code-0x4921]);
+ if ((code>=0x4A21)&&(code<=0x4A7E))
+ return(tab_jisx0212_uni34[code-0x4A21]);
+ if ((code>=0x4B21)&&(code<=0x4B7E))
+ return(tab_jisx0212_uni35[code-0x4B21]);
+ if ((code>=0x4C21)&&(code<=0x4C7E))
+ return(tab_jisx0212_uni36[code-0x4C21]);
+ if ((code>=0x4D21)&&(code<=0x4D7E))
+ return(tab_jisx0212_uni37[code-0x4D21]);
+ if ((code>=0x4E21)&&(code<=0x4E7E))
+ return(tab_jisx0212_uni38[code-0x4E21]);
+ if ((code>=0x4F21)&&(code<=0x4F7E))
+ return(tab_jisx0212_uni39[code-0x4F21]);
+ if ((code>=0x5021)&&(code<=0x507E))
+ return(tab_jisx0212_uni40[code-0x5021]);
+ if ((code>=0x5121)&&(code<=0x517E))
+ return(tab_jisx0212_uni41[code-0x5121]);
+ if ((code>=0x5221)&&(code<=0x527E))
+ return(tab_jisx0212_uni42[code-0x5221]);
+ if ((code>=0x5321)&&(code<=0x537E))
+ return(tab_jisx0212_uni43[code-0x5321]);
+ if ((code>=0x5421)&&(code<=0x547E))
+ return(tab_jisx0212_uni44[code-0x5421]);
+ if ((code>=0x5521)&&(code<=0x557E))
+ return(tab_jisx0212_uni45[code-0x5521]);
+ if ((code>=0x5621)&&(code<=0x567E))
+ return(tab_jisx0212_uni46[code-0x5621]);
+ if ((code>=0x5721)&&(code<=0x577E))
+ return(tab_jisx0212_uni47[code-0x5721]);
+ if ((code>=0x5821)&&(code<=0x587E))
+ return(tab_jisx0212_uni48[code-0x5821]);
+ if ((code>=0x5921)&&(code<=0x597E))
+ return(tab_jisx0212_uni49[code-0x5921]);
+ if ((code>=0x5A21)&&(code<=0x5A7E))
+ return(tab_jisx0212_uni50[code-0x5A21]);
+ if ((code>=0x5B21)&&(code<=0x5B7E))
+ return(tab_jisx0212_uni51[code-0x5B21]);
+ if ((code>=0x5C21)&&(code<=0x5C7E))
+ return(tab_jisx0212_uni52[code-0x5C21]);
+ if ((code>=0x5D21)&&(code<=0x5D7E))
+ return(tab_jisx0212_uni53[code-0x5D21]);
+ if ((code>=0x5E21)&&(code<=0x5E7E))
+ return(tab_jisx0212_uni54[code-0x5E21]);
+ if ((code>=0x5F21)&&(code<=0x5F7E))
+ return(tab_jisx0212_uni55[code-0x5F21]);
+ if ((code>=0x6021)&&(code<=0x607E))
+ return(tab_jisx0212_uni56[code-0x6021]);
+ if ((code>=0x6121)&&(code<=0x617E))
+ return(tab_jisx0212_uni57[code-0x6121]);
+ if ((code>=0x6221)&&(code<=0x627E))
+ return(tab_jisx0212_uni58[code-0x6221]);
+ if ((code>=0x6321)&&(code<=0x637E))
+ return(tab_jisx0212_uni59[code-0x6321]);
+ if ((code>=0x6421)&&(code<=0x647E))
+ return(tab_jisx0212_uni60[code-0x6421]);
+ if ((code>=0x6521)&&(code<=0x657E))
+ return(tab_jisx0212_uni61[code-0x6521]);
+ if ((code>=0x6621)&&(code<=0x667E))
+ return(tab_jisx0212_uni62[code-0x6621]);
+ if ((code>=0x6721)&&(code<=0x677E))
+ return(tab_jisx0212_uni63[code-0x6721]);
+ if ((code>=0x6821)&&(code<=0x687E))
+ return(tab_jisx0212_uni64[code-0x6821]);
+ if ((code>=0x6921)&&(code<=0x697E))
+ return(tab_jisx0212_uni65[code-0x6921]);
+ if ((code>=0x6A21)&&(code<=0x6A7E))
+ return(tab_jisx0212_uni66[code-0x6A21]);
+ if ((code>=0x6B21)&&(code<=0x6B7E))
+ return(tab_jisx0212_uni67[code-0x6B21]);
+ if ((code>=0x6C21)&&(code<=0x6C7E))
+ return(tab_jisx0212_uni68[code-0x6C21]);
+ if ((code>=0x6D21)&&(code<=0x6D63))
+ return(tab_jisx0212_uni69[code-0x6D21]);
+ if ((code>=0x7371)&&(code<=0x737E))
+ return(tab_jisx0212_uni70[code-0x7371]);
+ if ((code>=0x7421)&&(code<=0x747E))
+ return(tab_jisx0212_uni71[code-0x7421]);
+ return(0);
+}
+
+/*
+ EUC-JP encoding subcomponents:
+ [x00-x7F] # ASCII/JIS-Roman (one-byte/character)
+ [x8E][xA0-xDF] # half-width katakana (two bytes/char)
+ [x8F][xA1-xFE][xA1-xFE] # JIS X 0212-1990 (three bytes/char)
+ [xA1-xFE][xA1-xFE] # JIS X 0208:1997 (two bytes/char)
+*/
+
+static
+uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)),
+ const char *beg, const char *end, uint pos, int *error)
+{
+ const uchar *b= (uchar *) beg;
+ *error=0;
+
+ for ( ; pos && b < (uchar*) end; pos--, b++)
+ {
+ char *chbeg;
+ uint ch= *b;
+
+ if (ch <= 0x7F) /* one byte */
+ continue;
+
+ chbeg= (char *) b++;
+ if (b >= (uchar *) end) /* need more bytes */
+ return (uint) (chbeg - beg); /* unexpected EOL */
+
+ if (ch == 0x8E) /* [x8E][xA0-xDF] */
+ {
+ if (*b >= 0xA0 && *b <= 0xDF)
+ continue;
+ *error=1;
+ return (uint) (chbeg - beg); /* invalid sequence */
+ }
+
+ if (ch == 0x8F) /* [x8F][xA1-xFE][xA1-xFE] */
+ {
+ ch= *b++;
+ if (b >= (uchar*) end)
+ {
+ *error= 1;
+ return (uint)(chbeg - beg); /* unexpected EOL */
+ }
+ }
+
+ if (ch >= 0xA1 && ch <= 0xFE &&
+ *b >= 0xA1 && *b <= 0xFE) /* [xA1-xFE][xA1-xFE] */
+ continue;
+ *error=1;
+ return (uint) (chbeg - beg); /* invalid sequence */
+ }
+ return (uint) (b - (uchar *) beg);
+}
+
+
+static
+uint my_numcells_eucjp(CHARSET_INFO *cs __attribute__((unused)),
+ const char *str, const char *strend)
+{
+ uint clen= 0;
+ const unsigned char *b= (const unsigned char *) str;
+ const unsigned char *e= (const unsigned char *) strend;
+
+ for (clen= 0; b < e; )
+ {
+ if (*b == 0x8E)
+ {
+ clen++;
+ b+= 2;
+ }
+ else if (*b == 0x8F)
+ {
+ clen+= 2;
+ b+= 3;
+ }
+ else if (*b & 0x80)
+ {
+ clen+= 2;
+ b+= 2;
+ }
+ else
+ {
+ clen++;
+ b++;
+ }
+ }
+ return clen;
+}
+
+static int
+my_mb_wc_euc_jp(CHARSET_INFO *cs,my_wc_t *pwc, const uchar *s, const uchar *e)
+{
+ int c1,c2,c3;
+
+ if (s >= e)
+ return MY_CS_TOOFEW(0);
+
+ c1=s[0];
+
+ /* Ascii code set */
+ if (c1<=0x7F)
+ {
+ *pwc=c1;
+ return 1;
+ }
+
+ if (s+2>e)
+ return MY_CS_TOOFEW(0);
+
+ c2=s[1];
+
+
+ /* JIS X 0208 code set */
+ if (c1>=0xA1 && c1<=0xFE)
+ {
+ if (c2 < 0xA1 || c2 >0xFE)
+ return MY_CS_ILSEQ;
+
+ if (c1 < 0xF5)
+ {
+ pwc[0]=my_jisx0208_uni_onechar( ((c1-0x80) << 8) + (c2-0x80));
+ if (!pwc[0])
+ return MY_CS_ILSEQ;
+ }
+ else
+ {
+ /* User defined range */
+ pwc[0]=0xE000 + 94*(c1-0xF5) +(c2-0xA1);
+ }
+ return 2;
+ }
+
+ /* JIS X 0201 code set (Half Width Tatakana) */
+ if (c1==0x8E)
+ {
+ int ret;
+
+ if (c2<0xA1 || c2>0xDF)
+ return MY_CS_ILSEQ;
+
+ ret = my_mb_wc_jisx0201(cs,pwc,s+1,e);
+ if (ret!=1)
+ return ret;
+ return 2;
+ }
+
+ /* JIS X 0212 code set */
+ if (c1==0x8F)
+ {
+ if (c2<0xA1 || c2>=0xFF)
+ return MY_CS_ILSEQ;
+
+ if (s+3>e)
+ return MY_CS_TOOFEW(0);
+
+ c3=s[2];
+ if (c3 < 0xA1 || c3>=0xFF)
+ return MY_CS_ILSEQ;
+
+ if (c2<0xF5)
+ {
+ pwc[0]=my_jisx0212_uni_onechar((c2-0x80)*256 + (c3-0x80));
+ if (!pwc)
+ return MY_CS_ILSEQ;
+ }
+ else
+ {
+ /* User defined range */
+ pwc[0]= 0xE3AC + 94*(c2-0xF5) + (c3-0xA1);
+ }
+ return 3;
+ }
+
+ return MY_CS_ILSEQ;
+}
+
+static int
+my_wc_mb_euc_jp(CHARSET_INFO *c,my_wc_t wc, unsigned char *s, unsigned char *e)
+{
+ unsigned char c1;
+ int jp;
+
+ if (s >= e)
+ return MY_CS_TOOSMALL;
+
+ if ((int) wc < 0x80)
+ {
+ *s= (uchar) wc;
+ return 1;
+ }
+
+ if ((jp=my_uni_jisx0208_onechar(wc)))
+ {
+ if (s+2>e)
+ return MY_CS_TOOSMALL;
+
+ jp+=0x8080;
+ s[0]=jp>>8;
+ s[1]=jp&0xFF;
+ return 2;
+ }
+
+ /* Half width Katakana */
+ if (my_wc_mb_jisx0201(c,wc,s,e) == 1)
+ {
+ if (s+2>e)
+ return MY_CS_TOOSMALL;
+ s[1]= s[0];
+ s[0]= 0x8E;
+ return 2;
+ }
+
+
+ if ((jp=my_uni_jisx0212_onechar(wc)))
+ {
+ if (s+3>e)
+ return MY_CS_TOOSMALL;
+
+ jp+=0x8080;
+ s[0]=0x8F;
+ s[1]=jp>>8;
+ s[2]=jp&0xFF;
+ return 3;
+ }
+
+
+ /* User defined range */
+ if (wc>=0xE000 && wc<0xE3AC)
+ {
+ if (s+2>e)
+ return MY_CS_TOOSMALL;
+
+ c1=((unsigned)(wc-0xE000)/94)+0xF5;
+ s[0]=c1;
+ c1=((unsigned)(wc-0xE000)%94)+0xa1;
+ s[1]=c1;
+ return 2;
+ }
+
+
+ /* User defined range */
+ if (wc>=0xE3AC && wc<0xE758)
+ {
+ if (s+3>e)
+ return MY_CS_TOOSMALL;
+
+ s[0]=0x8F;
+ c1=((unsigned)(wc-0xE3AC)/94)+0xF5;
+ s[1]=c1;
+ c1=((unsigned)(wc-0xE3AC)%94)+0xa1;
+ s[2]=c1;
+ return 3;
+ }
+
+ return MY_CS_ILUNI;
+}
+
+
+static MY_COLLATION_HANDLER my_collation_ci_handler =
+{
+ NULL, /* init */
+ my_strnncoll_simple,/* strnncoll */
+ my_strnncollsp_simple,
+ my_strnxfrm_simple, /* strnxfrm */
+ my_strnxfrmlen_simple,
+ my_like_range_simple,/* like_range */
+ my_wildcmp_mb, /* wildcmp */
+ my_strcasecmp_mb,
+ my_instr_mb,
+ my_hash_sort_simple,
+ my_propagate_simple
+};
+
+static MY_CHARSET_HANDLER my_charset_handler=
+{
+ NULL, /* init */
+ ismbchar_eucjpms,
+ mbcharlen_eucjpms,
+ my_numchars_mb,
+ my_charpos_mb,
+ my_well_formed_len_eucjpms,
+ my_lengthsp_8bit,
+ my_numcells_eucjp,
+ 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,
+ my_casedn_mb,
+ my_snprintf_8bit,
+ my_long10_to_str_8bit,
+ my_longlong10_to_str_8bit,
+ my_fill_8bit,
+ my_strntol_8bit,
+ my_strntoul_8bit,
+ my_strntoll_8bit,
+ my_strntoull_8bit,
+ my_strntod_8bit,
+ my_strtoll10_8bit,
+ my_scan_8bit
+};
+
+
+
+CHARSET_INFO my_charset_eucjpms_japanese_ci=
+{
+ 97,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "eucjpms", /* cs name */
+ "eucjpms_japanese_ci", /* name */
+ "", /* comment */
+ NULL, /* tailoring */
+ ctype_eucjpms,
+ to_lower_eucjpms,
+ to_upper_eucjpms,
+ sort_order_eucjpms,
+ NULL, /* sort_order_big*/
+ NULL, /* contractions */
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
+ 1, /* mbminlen */
+ 3, /* mbmaxlen */
+ 0, /* min_sort_char */
+ 255, /* max_sort_char */
+ 0, /* escape_with_backslash_is_dangerous */
+ &my_charset_handler,
+ &my_collation_ci_handler
+};
+
+
+CHARSET_INFO my_charset_eucjpms_bin=
+{
+ 98,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_BINSORT, /* state */
+ "eucjpms", /* cs name */
+ "eucjpms_bin", /* name */
+ "", /* comment */
+ NULL, /* tailoring */
+ ctype_eucjpms,
+ to_lower_eucjpms,
+ to_upper_eucjpms,
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
+ 1, /* mbminlen */
+ 3, /* mbmaxlen */
+ 0, /* min_sort_char */
+ 255, /* max_sort_char */
+ 0, /* escape_with_backslash_is_dangerous */
+ &my_charset_handler,
+ &my_collation_mb_bin_handler
+};
+
+
+#endif
diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c
index 1c786c16ec5..e9a9598abdf 100644
--- a/strings/ctype-extra.c
+++ b/strings/ctype-extra.c
@@ -33,9 +33,12 @@ CHARSET_INFO compiled_charsets[] = {
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
0, /* strxfrm_mul */
+ 0, /* caseup_mul */
+ 0, /* casedn_mul */
0, /* mbminlen */
0, /* mbmaxlen */
0, /* min_sort_ord */
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index 0cbad2d1c55..3d9a17205cd 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -5692,11 +5692,13 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncoll_simple, /* strnncoll */
my_strnncollsp_simple,
my_strnxfrm_simple, /* strnxfrm */
+ my_strnxfrmlen_simple,
my_like_range_simple, /* like_range */
my_wildcmp_mb, /* wildcmp */
my_strcasecmp_mb, /* instr */
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
@@ -5745,9 +5747,12 @@ CHARSET_INFO my_charset_gb2312_chinese_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
@@ -5773,9 +5778,12 @@ CHARSET_INFO my_charset_gb2312_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 82c76b8ee96..5c220a285dd 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -2625,14 +2625,22 @@ int my_strnncoll_gbk(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_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 diff_if_only_endspace_difference)
{
uint length= min(a_length, b_length);
int res= my_strnncoll_gbk_internal(&a, &b, length);
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
+
if (!res && a_length != b_length)
{
const uchar *end;
int swap= 1;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -2643,6 +2651,7 @@ static int my_strnncollsp_gbk(CHARSET_INFO * cs __attribute__((unused)),
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -2736,22 +2745,26 @@ static my_bool my_like_range_gbk(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str - min_org);
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
*max_length= res_length;
do {
*min_str++= 0;
- *max_str++ = max_sort_char;
+ *max_str++= max_sort_char;
} while (min_str != min_end);
return 0;
}
*min_str++= *max_str++ = *ptr;
}
+
*min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
- {
- *min_str++ = ' '; /* Because if key compression */
- *max_str++ = ' ';
- }
+ *min_str++= *max_str++= ' '; /* Because if key compression */
return 0;
}
@@ -9968,11 +9981,13 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncoll_gbk,
my_strnncollsp_gbk,
my_strnxfrm_gbk,
+ my_strnxfrmlen_simple,
my_like_range_gbk,
my_wildcmp_mb,
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
@@ -10021,9 +10036,12 @@ CHARSET_INFO my_charset_gbk_chinese_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
@@ -10049,9 +10067,12 @@ CHARSET_INFO my_charset_gbk_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index b6e3e300c34..9075710610b 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -431,9 +431,12 @@ CHARSET_INFO my_charset_latin1=
NULL, /* sort_order_big*/
cs_to_uni, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
@@ -580,11 +583,16 @@ static int my_strnncoll_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_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 diff_if_only_endspace_difference)
{
- const uchar *a_end= a + a_length;
- const uchar *b_end= b + b_length;
+ const uchar *a_end= a + a_length, *b_end= b + b_length;
uchar a_char, a_extend= 0, b_char, b_extend= 0;
+ int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
while ((a < a_end || a_extend) && (b < b_end || b_extend))
{
@@ -617,9 +625,12 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
if (b_extend)
return -1;
+ res= 0;
if (a != a_end || b != b_end)
{
int swap= 1;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -630,6 +641,7 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
a_end= b_end;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for ( ; a < a_end ; a++)
{
@@ -637,7 +649,7 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
return (*a < ' ') ? -swap : swap;
}
}
- return 0;
+ return res;
}
@@ -692,11 +704,13 @@ static MY_COLLATION_HANDLER my_collation_german2_ci_handler=
my_strnncoll_latin1_de,
my_strnncollsp_latin1_de,
my_strnxfrm_latin1_de,
+ my_strnxfrmlen_simple,
my_like_range_simple,
my_wildcmp_8bit,
my_strcasecmp_8bit,
my_instr_simple,
- my_hash_sort_latin1_de
+ my_hash_sort_latin1_de,
+ my_propagate_complex
};
@@ -716,9 +730,12 @@ CHARSET_INFO my_charset_latin1_german2_ci=
NULL, /* sort_order_big*/
cs_to_uni, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
2, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
@@ -745,9 +762,12 @@ CHARSET_INFO my_charset_latin1_bin=
NULL, /* sort_order_big*/
cs_to_uni, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 4b22f158284..6f171c03845 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -57,40 +57,48 @@ void my_casedn_str_mb(CHARSET_INFO * cs, char *str)
}
}
-void my_caseup_mb(CHARSET_INFO * cs, char *str, uint length)
+uint my_caseup_mb(CHARSET_INFO * cs, char *src, uint srclen,
+ char *dst __attribute__((unused)),
+ uint dstlen __attribute__((unused)))
{
register uint32 l;
- register char *end=str+length;
- register uchar *map=cs->to_upper;
-
- while (str<end)
+ register char *srcend= src + srclen;
+ register uchar *map= cs->to_upper;
+
+ DBUG_ASSERT(src == dst && srclen == dstlen);
+ while (src < srcend)
{
- if ((l=my_ismbchar(cs, str,end)))
- str+=l;
+ if ((l=my_ismbchar(cs, src, srcend)))
+ src+= l;
else
{
- *str=(char) map[(uchar)*str];
- str++;
+ *src=(char) map[(uchar) *src];
+ src++;
}
}
+ return srclen;
}
-void my_casedn_mb(CHARSET_INFO * cs, char *str, uint length)
+uint my_casedn_mb(CHARSET_INFO * cs, char *src, uint srclen,
+ char *dst __attribute__((unused)),
+ uint dstlen __attribute__((unused)))
{
register uint32 l;
- register char *end=str+length;
+ register char *srcend= src + srclen;
register uchar *map=cs->to_lower;
-
- while (str<end)
+
+ DBUG_ASSERT(src == dst && srclen == dstlen);
+ while (src < srcend)
{
- if ((l=my_ismbchar(cs, str,end)))
- str+=l;
+ if ((l= my_ismbchar(cs, src, srcend)))
+ src+= l;
else
{
- *str=(char) map[(uchar)*str];
- str++;
+ *src= (char) map[(uchar)*src];
+ src++;
}
}
+ return srclen;
}
int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
@@ -260,7 +268,7 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
pos+= (mblen= my_ismbchar(cs, pos, end)) ? mblen : 1;
length--;
}
- return length ? (uint) (end + 2 - start) : (uint) (pos - start);
+ return (uint) (length ? end+2-start : pos-start);
}
@@ -321,7 +329,7 @@ uint my_instr_mb(CHARSET_INFO *cs,
if (nmatch)
{
match[0].beg= 0;
- match[0].end= b-b0;
+ match[0].end= (uint) (b-b0);
match[0].mblen= res;
if (nmatch > 1)
{
@@ -365,6 +373,9 @@ static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
slen Length of 's'
t String to compare
tlen Length of 't'
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
NOTE
This function is used for character strings with binary collations.
@@ -379,10 +390,16 @@ static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
static int my_strnncollsp_mb_bin(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 diff_if_only_endspace_difference)
{
const uchar *end;
uint length;
+ int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
end= a + (length= min(a_length, b_length));
while (a < end)
@@ -390,9 +407,12 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
if (*a++ != *b++)
return ((int) a[-1] - (int) b[-1]);
}
+ res= 0;
if (a_length != b_length)
{
int swap= 1;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -403,6 +423,7 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -410,7 +431,7 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
return (*a < ' ') ? -swap : swap;
}
}
- return 0;
+ return res;
}
@@ -527,9 +548,15 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
if (charlen < (uint) (min_str - min_org))
min_str= min_org + charlen;
- /* Write min key */
- *min_length= (uint) (min_str - min_org);
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
*max_length= res_length;
+ /* Create min key */
do
{
*min_str++= (char) cs->min_sort_char;
@@ -545,14 +572,14 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
}
*min_str++= *max_str++ = *ptr;
}
- *min_length= *max_length = (uint) (min_str - min_org);
+ *min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
- *min_str++= ' '; /* Because if key compression */
- pad_max_char(cs, max_str, max_end);
+ *min_str++= *max_str++= ' '; /* Because if key compression */
return 0;
}
+
static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
const char *str,const char *str_end,
const char *wildstr,const char *wildend,
@@ -896,11 +923,13 @@ MY_COLLATION_HANDLER my_collation_mb_bin_handler =
my_strnncoll_mb_bin,
my_strnncollsp_mb_bin,
my_strnxfrm_mb_bin,
+ my_strnxfrmlen_simple,
my_like_range_simple,
my_wildcmp_mb_bin,
my_strcasecmp_mb_bin,
my_instr_mb,
- my_hash_sort_mb_bin
+ my_hash_sort_mb_bin,
+ my_propagate_simple
};
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index af673b78254..208c38edd30 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -22,6 +22,15 @@
#include "stdarg.h"
/*
+ Returns the number of bytes required for strnxfrm().
+*/
+uint my_strnxfrmlen_simple(CHARSET_INFO *cs, uint len)
+{
+ return len * (cs->strxfrm_multiply ? cs->strxfrm_multiply : 1);
+}
+
+
+/*
Converts a string into its sort key.
SYNOPSIS
@@ -112,6 +121,9 @@ int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
a_length Length of 'a'
b Second string to compare
b_length Length of 'b'
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
IMPLEMENTATION
If one string is shorter as the other, then we space extend the other
@@ -130,10 +142,16 @@ int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
*/
int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
const uchar *map= cs->sort_order, *end;
uint length;
+ int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
end= a + (length= min(a_length, b_length));
while (a < end)
@@ -141,9 +159,12 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
if (map[*a++] != map[*b++])
return ((int) map[a[-1]] - (int) map[b[-1]]);
}
+ res= 0;
if (a_length != b_length)
{
int swap= 1;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -154,6 +175,7 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -161,7 +183,7 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
return (*a < ' ') ? -swap : swap;
}
}
- return 0;
+ return res;
}
@@ -179,18 +201,28 @@ void my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
str++;
}
-void my_caseup_8bit(CHARSET_INFO * cs, char *str, uint length)
+uint my_caseup_8bit(CHARSET_INFO * cs, char *src, uint srclen,
+ char *dst __attribute__((unused)),
+ uint dstlen __attribute__((unused)))
{
- register uchar *map=cs->to_upper;
- for ( ; length>0 ; length--, str++)
- *str= (char) map[(uchar)*str];
+ uint srclen0= srclen;
+ register uchar *map= cs->to_upper;
+ DBUG_ASSERT(src == dst && srclen == dstlen);
+ for ( ; srclen > 0 ; srclen--, src++)
+ *src= (char) map[(uchar) *src];
+ return srclen0;
}
-void my_casedn_8bit(CHARSET_INFO * cs, char *str, uint length)
+uint my_casedn_8bit(CHARSET_INFO * cs, char *src, uint srclen,
+ char *dst __attribute__((unused)),
+ uint dstlen __attribute__((unused)))
{
+ uint srclen0= srclen;
register uchar *map=cs->to_lower;
- for ( ; length>0 ; length--, str++)
- *str= (char) map[(uchar) *str];
+ DBUG_ASSERT(src == dst && srclen == dstlen);
+ for ( ; srclen > 0 ; srclen--, src++)
+ *src= (char) map[(uchar) *src];
+ return srclen0;
}
int my_strcasecmp_8bit(CHARSET_INFO * cs,const char *s, const char *t)
@@ -259,14 +291,19 @@ void my_hash_sort_simple(CHARSET_INFO *cs,
ulong *nr1, ulong *nr2)
{
register uchar *sort_order=cs->sort_order;
- const uchar *pos = key;
+ const uchar *end= key + len;
- key+= len;
+ /*
+ Remove end space. We have to do this to be able to compare
+ 'A ' and 'A' as identical
+ */
+ while (end > key && end[-1] == ' ')
+ end--;
- for (; pos < (uchar*) key ; pos++)
+ for (; key < (uchar*) end ; key++)
{
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
- ((uint) sort_order[(uint) *pos])) + (nr1[0] << 8);
+ ((uint) sort_order[(uint) *key])) + (nr1[0] << 8);
nr2[0]+=3;
}
}
@@ -867,7 +904,7 @@ int my_longlong10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)),
while (long_val != 0)
{
long quo= long_val/10;
- *--p = '0' + (long_val - quo*10);
+ *--p = '0' + (char)(long_val - quo*10);
long_val= quo;
}
@@ -1023,8 +1060,10 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
}
if (*ptr == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
+ /* Calculate length of keys */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
do
{
*min_str++= 0;
@@ -1034,10 +1073,10 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
}
*min_str++= *max_str++ = *ptr;
}
- *min_length= *max_length = (uint) (min_str - min_org);
+ *min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
- *min_str++ = *max_str++ = ' '; /* Because if key compression */
+ *min_str++= *max_str++ = ' '; /* Because if key compression */
return 0;
}
@@ -1160,7 +1199,7 @@ skip:
if (nmatch > 0)
{
match[0].beg= 0;
- match[0].end= str- (const uchar*)b-1;
+ match[0].end= (uint) (str- (const uchar*)b-1);
match[0].mblen= match[0].end;
if (nmatch > 1)
@@ -1280,6 +1319,8 @@ static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(uint))
static my_bool my_cset_init_8bit(CHARSET_INFO *cs, void *(*alloc)(uint))
{
+ cs->caseup_multiply= 1;
+ cs->casedn_multiply= 1;
return create_fromuni(cs, alloc);
}
@@ -1317,6 +1358,60 @@ longlong my_strtoll10_8bit(CHARSET_INFO *cs __attribute__((unused)),
}
+/*
+ Check if a constant can be propagated
+
+ SYNOPSIS:
+ my_propagate_simple()
+ cs Character set information
+ str String to convert to double
+ length Optional length for string.
+
+ NOTES:
+ Takes the string in the given charset and check
+ if it can be safely propagated in the optimizer.
+
+ create table t1 (
+ s char(5) character set latin1 collate latin1_german2_ci);
+ insert into t1 values (0xf6); -- o-umlaut
+ select * from t1 where length(s)=1 and s='oe';
+
+ The above query should return one row.
+ We cannot convert this query into:
+ select * from t1 where length('oe')=1 and s='oe';
+
+ Currently we don't check the constant itself,
+ and decide not to propagate a constant
+ just if the collation itself allows tricky things
+ like expansions and contractions. In the future
+ we can write a more sophisticated functions to
+ check the constants. For example, 'oa' can always
+ be safety propagated in German2 because unlike
+ 'oe' it does not have any special meaning.
+
+ RETURN
+ 1 if constant can be safely propagated
+ 0 if it is not safe to propagate the constant
+*/
+
+
+
+my_bool my_propagate_simple(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *str __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+ return 1;
+}
+
+
+my_bool my_propagate_complex(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *str __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+ return 0;
+}
+
+
MY_CHARSET_HANDLER my_charset_8bit_handler=
{
my_cset_init_8bit,
@@ -1352,9 +1447,11 @@ MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler =
my_strnncoll_simple,
my_strnncollsp_simple,
my_strnxfrm_simple,
+ my_strnxfrmlen_simple,
my_like_range_simple,
my_wildcmp_8bit,
my_strcasecmp_8bit,
my_instr_simple,
- my_hash_sort_simple
+ my_hash_sort_simple,
+ my_propagate_simple
};
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 4342fc670df..c0a395b5792 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -244,14 +244,21 @@ static int my_strnncoll_sjis(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_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 diff_if_only_endspace_difference)
{
- const uchar *a_end= a + a_length;
- const uchar *b_end= b + b_length;
+ const uchar *a_end= a + a_length, *b_end= b + b_length;
int res= my_strnncoll_sjis_internal(cs, &a, a_length, &b, b_length);
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
+
if (!res && (a != a_end || b != b_end))
{
int swap= 1;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -262,6 +269,7 @@ static int my_strnncollsp_sjis(CHARSET_INFO *cs __attribute__((unused)),
a_end= b_end;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (; a < a_end ; a++)
{
@@ -354,8 +362,14 @@ static my_bool my_like_range_sjis(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == w_many)
{ /* '%' in SQL */
- *min_length = (uint)(min_str - min_org);
- *max_length = res_length;
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
do
{
*min_str++= 0;
@@ -365,9 +379,10 @@ static my_bool my_like_range_sjis(CHARSET_INFO *cs __attribute__((unused)),
}
*min_str++ = *max_str++ = *ptr++;
}
- *min_length = *max_length = (uint)(min_str - min_org);
- while (min_str < min_end)
- *min_str++ = *max_str++ = ' '; /* Because if key compression */
+
+ *min_length= *max_length= (uint) (min_str - min_org);
+ while (min_str != min_end)
+ *min_str++= *max_str++= ' '; /* Because if key compression */
return 0;
}
@@ -4615,11 +4630,13 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncoll_sjis,
my_strnncollsp_sjis,
my_strnxfrm_sjis,
+ my_strnxfrmlen_simple,
my_like_range_sjis,
my_wildcmp_mb, /* wildcmp */
my_strcasecmp_8bit,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
@@ -4669,9 +4686,12 @@ CHARSET_INFO my_charset_sjis_japanese_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
@@ -4697,9 +4717,12 @@ CHARSET_INFO my_charset_sjis_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 208168bb946..2003eaa0789 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -320,7 +320,7 @@ static int t_ctype[][TOT_LEVELS] = {
/*0xFC*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xFD*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xFE*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
-/* Utilize 0xFF for max_sort_chr in my_like_range_tis620 */
+ /* Utilize 0xFF for max_sort_chr in my_like_range_tis620 */
/*0xFF*/ { 255 /*IGNORE*/, IGNORE, IGNORE, IGNORE, X },
};
@@ -541,7 +541,7 @@ int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
tc1= buf;
if ((len1 + len2 +2) > (int) sizeof(buf))
- tc1= (uchar*) malloc(len1+len2+2);
+ tc1= (uchar*) my_str_malloc(len1+len2+2);
tc2= tc1 + len1+1;
memcpy((char*) tc1, (char*) s1, len1);
tc1[len1]= 0; /* if length(s1)> len1, need to put 'end of string' */
@@ -551,7 +551,7 @@ int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
thai2sortable(tc2, len2);
i= strcmp((char*)tc1, (char*)tc2);
if (tc1 != buf)
- free(tc1);
+ my_str_free(tc1);
return i;
}
@@ -559,16 +559,20 @@ int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
static
int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
const uchar *a0, uint a_length,
- const uchar *b0, uint b_length)
+ const uchar *b0, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
- uchar buf[80] ;
- uchar *end, *a, *b, *alloced= NULL;
+ uchar buf[80], *end, *a, *b, *alloced= NULL;
uint length;
int res= 0;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
a= buf;
if ((a_length + b_length +2) > (int) sizeof(buf))
- alloced= a= (uchar*) malloc(a_length+b_length+2);
+ alloced= a= (uchar*) my_str_malloc(a_length+b_length+2);
b= a + a_length+1;
memcpy((char*) a, (char*) a0, a_length);
@@ -590,6 +594,8 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
if (a_length != b_length)
{
int swap= 1;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -600,6 +606,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -614,7 +621,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
ret:
if (alloced)
- free(alloced);
+ my_str_free(alloced);
return res;
}
@@ -687,8 +694,14 @@ my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
do
{
*min_str++ = 0;
@@ -698,10 +711,10 @@ my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)),
}
*min_str++= *max_str++ = *ptr;
}
- *min_length= *max_length = (uint) (min_str - min_org);
+ *min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
- *min_str++ = *max_str++ = ' '; /* Because of key compression */
+ *min_str++= *max_str++ = ' '; /* Because of key compression */
return 0;
}
@@ -914,11 +927,13 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncoll_tis620,
my_strnncollsp_tis620,
my_strnxfrm_tis620,
+ my_strnxfrmlen_simple,
my_like_range_tis620,
my_wildcmp_8bit, /* wildcmp */
my_strcasecmp_8bit,
my_instr_simple, /* QQ: To be fixed */
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
@@ -968,9 +983,12 @@ CHARSET_INFO my_charset_tis620_thai_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
4, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
@@ -996,9 +1014,12 @@ CHARSET_INFO my_charset_tis620_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index 010250521c7..a280ed59352 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -6692,6 +6692,18 @@ static const char persian[]=
" < \\uFEF5 < \\uFEF6 < \\uFEF7 < \\uFEF8 < \\uFEF9 < \\uFEFA"
" < \\uFEFB < \\uFEFC";
+/*
+ Esperanto tailoring.
+ Contributed by Bertilo Wennergren <bertilow at gmail dot com>
+ September 1, 2005
+*/
+static const char esperanto[]=
+ "& C < \\u0109 <<< \\u0108"
+ "& G < \\u011D <<< \\u011C"
+ "& H < \\u0125 <<< \\u0124"
+ "& J < \\u0135 <<< \\u0134"
+ "& S < \\u015d <<< \\u015c"
+ "& U < \\u016d <<< \\u016c";
/*
Unicode Collation Algorithm:
@@ -7048,6 +7060,9 @@ static int my_strnncoll_uca(CHARSET_INFO *cs,
slen First string length
t Second string
tlen Seconf string length
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
NOTES:
Works exactly the same with my_strnncoll_uca(),
@@ -7085,13 +7100,16 @@ static int my_strnncoll_uca(CHARSET_INFO *cs,
static int my_strnncollsp_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 diff_if_only_endspace_difference)
{
- my_uca_scanner sscanner;
- my_uca_scanner tscanner;
- int s_res;
- int t_res;
+ my_uca_scanner sscanner, tscanner;
+ int s_res, t_res;
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
+
scanner_handler->init(&sscanner, cs, s, slen);
scanner_handler->init(&tscanner, cs, t, tlen);
@@ -7113,7 +7131,7 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
return (s_res - t_res);
s_res= scanner_handler->next(&sscanner);
} while (s_res > 0);
- return 0;
+ return diff_if_only_endspace_difference ? 1 : 0;
}
if (s_res < 0 && t_res > 0)
@@ -7128,7 +7146,7 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
return (s_res - t_res);
t_res= scanner_handler->next(&tscanner);
} while (t_res > 0);
- return 0;
+ return diff_if_only_endspace_difference ? -1 : 0;
}
return ( s_res - t_res );
@@ -7521,7 +7539,7 @@ static void my_coll_lexem_print_error(MY_COLL_LEXEM *lexem,
{
char tail[30];
size_t len= lexem->end - lexem->prev;
- strmake (tail, lexem->prev, min(len, sizeof(tail)-1));
+ strmake (tail, lexem->prev, (uint) min(len, sizeof(tail)-1));
errstr[errsize-1]= '\0';
my_snprintf(errstr,errsize-1,"%s at '%s'", txt, tail);
}
@@ -7763,7 +7781,7 @@ static int my_coll_rule_parse(MY_COLL_RULE *rule, size_t mitems,
continue;
}
}
- return (size_t) nitems;
+ return (int) nitems;
}
#define MY_MAX_COLL_RULE 128
@@ -7949,11 +7967,13 @@ static int my_strnncoll_any_uca(CHARSET_INFO *cs,
}
static int my_strnncollsp_any_uca(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 diff_if_only_endspace_difference)
{
return my_strnncollsp_uca(cs, &my_any_uca_scanner_handler,
- s, slen, t, tlen);
+ s, slen, t, tlen,
+ diff_if_only_endspace_difference);
}
static void my_hash_sort_any_uca(CHARSET_INFO *cs,
@@ -7986,11 +8006,13 @@ static int my_strnncoll_ucs2_uca(CHARSET_INFO *cs,
}
static int my_strnncollsp_ucs2_uca(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 diff_if_only_endspace_difference)
{
return my_strnncollsp_uca(cs, &my_ucs2_uca_scanner_handler,
- s, slen, t, tlen);
+ s, slen, t, tlen,
+ diff_if_only_endspace_difference);
}
static void my_hash_sort_ucs2_uca(CHARSET_INFO *cs,
@@ -8014,11 +8036,13 @@ MY_COLLATION_HANDLER my_collation_ucs2_uca_handler =
my_strnncoll_ucs2_uca,
my_strnncollsp_ucs2_uca,
my_strnxfrm_ucs2_uca,
+ my_strnxfrmlen_simple,
my_like_range_ucs2,
my_wildcmp_uca,
NULL,
my_instr_mb,
- my_hash_sort_ucs2_uca
+ my_hash_sort_ucs2_uca,
+ my_propagate_complex
};
CHARSET_INFO my_charset_ucs2_general_uca=
@@ -8037,9 +8061,12 @@ CHARSET_INFO my_charset_ucs2_general_uca=
uca_weight, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8065,9 +8092,12 @@ CHARSET_INFO my_charset_ucs2_icelandic_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8093,9 +8123,12 @@ CHARSET_INFO my_charset_ucs2_latvian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8121,9 +8154,12 @@ CHARSET_INFO my_charset_ucs2_romanian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8149,9 +8185,12 @@ CHARSET_INFO my_charset_ucs2_slovenian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8177,9 +8216,12 @@ CHARSET_INFO my_charset_ucs2_polish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8205,9 +8247,12 @@ CHARSET_INFO my_charset_ucs2_estonian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8233,9 +8278,12 @@ CHARSET_INFO my_charset_ucs2_spanish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8261,9 +8309,12 @@ CHARSET_INFO my_charset_ucs2_swedish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8289,9 +8340,12 @@ CHARSET_INFO my_charset_ucs2_turkish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_turkish, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8317,9 +8371,12 @@ CHARSET_INFO my_charset_ucs2_czech_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8346,9 +8403,12 @@ CHARSET_INFO my_charset_ucs2_danish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8374,9 +8434,12 @@ CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8402,9 +8465,12 @@ CHARSET_INFO my_charset_ucs2_slovak_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8430,9 +8496,12 @@ CHARSET_INFO my_charset_ucs2_spanish2_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8459,9 +8528,12 @@ CHARSET_INFO my_charset_ucs2_roman_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8488,9 +8560,44 @@ CHARSET_INFO my_charset_ucs2_persian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ 0, /* escape_with_backslash_is_dangerous */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+
+CHARSET_INFO my_charset_ucs2_esperanto_uca_ci=
+{
+ 145,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* cs name */
+ "ucs2_esperanto_ci",/* name */
+ "", /* comment */
+ esperanto, /* 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 */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
9, /* min_sort_char */
@@ -8511,11 +8618,13 @@ MY_COLLATION_HANDLER my_collation_any_uca_handler =
my_strnncoll_any_uca,
my_strnncollsp_any_uca,
my_strnxfrm_any_uca,
+ my_strnxfrmlen_simple,
my_like_range_mb,
my_wildcmp_uca,
NULL,
my_instr_mb,
- my_hash_sort_any_uca
+ my_hash_sort_any_uca,
+ my_propagate_complex
};
/*
@@ -8562,9 +8671,12 @@ CHARSET_INFO my_charset_utf8_general_uca_ci=
uca_weight, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8591,9 +8703,12 @@ CHARSET_INFO my_charset_utf8_icelandic_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8619,9 +8734,12 @@ CHARSET_INFO my_charset_utf8_latvian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8647,9 +8765,12 @@ CHARSET_INFO my_charset_utf8_romanian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8675,9 +8796,12 @@ CHARSET_INFO my_charset_utf8_slovenian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8703,9 +8827,12 @@ CHARSET_INFO my_charset_utf8_polish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8731,9 +8858,12 @@ CHARSET_INFO my_charset_utf8_estonian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8759,9 +8889,12 @@ CHARSET_INFO my_charset_utf8_spanish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8787,9 +8920,12 @@ CHARSET_INFO my_charset_utf8_swedish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8815,9 +8951,12 @@ CHARSET_INFO my_charset_utf8_turkish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_turkish, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 2, /* caseup_multiply */
+ 2, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8843,9 +8982,12 @@ CHARSET_INFO my_charset_utf8_czech_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8872,9 +9014,12 @@ CHARSET_INFO my_charset_utf8_danish_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8900,9 +9045,12 @@ CHARSET_INFO my_charset_utf8_lithuanian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8928,9 +9076,12 @@ CHARSET_INFO my_charset_utf8_slovak_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8956,9 +9107,12 @@ CHARSET_INFO my_charset_utf8_spanish2_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -8984,9 +9138,12 @@ CHARSET_INFO my_charset_utf8_roman_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
@@ -9012,9 +9169,43 @@ CHARSET_INFO my_charset_utf8_persian_uca_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
+ 1, /* mbminlen */
+ 3, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ 0, /* escape_with_backslash_is_dangerous */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
+CHARSET_INFO my_charset_utf8_esperanto_uca_ci=
+{
+ 209,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_esperanto_ci",/* name */
+ "", /* comment */
+ esperanto, /* 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 */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
9, /* min_sort_char */
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 2761e781724..41ab055d2de 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -30,7 +30,6 @@
#define EILSEQ ENOENT
#endif
-extern MY_UNICASE_INFO *uni_plane[256];
static uchar ctype_ucs2[] = {
0,
@@ -113,20 +112,26 @@ static int my_uni_ucs2(CHARSET_INFO *cs __attribute__((unused)) ,
}
-static void my_caseup_ucs2(CHARSET_INFO *cs, char *s, uint slen)
+static uint my_caseup_ucs2(CHARSET_INFO *cs, char *src, uint srclen,
+ char *dst __attribute__((unused)),
+ uint dstlen __attribute__((unused)))
{
my_wc_t wc;
int res;
- char *e=s+slen;
-
- while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
+ char *srcend= src + srclen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ DBUG_ASSERT(src == dst && srclen == dstlen);
+
+ while ((src < srcend) &&
+ (res= my_ucs2_uni(cs, &wc, (uchar *)src, (uchar*) srcend)) > 0)
{
- int plane = (wc>>8) & 0xFF;
- wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
- if (res != my_uni_ucs2(cs,wc,(uchar*)s,(uchar*)e))
+ int plane= (wc>>8) & 0xFF;
+ wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
+ if (res != my_uni_ucs2(cs, wc, (uchar*) src, (uchar*) srcend))
break;
- s+=res;
+ src+= res;
}
+ return srclen;
}
@@ -136,6 +141,10 @@ static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, uint slen,
my_wc_t wc;
int res;
const uchar *e=s+slen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+
+ while (e > s+1 && e[-1] == ' ' && e[-2] == '\0')
+ e-= 2;
while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e)) >0)
{
@@ -157,22 +166,26 @@ static void my_caseup_str_ucs2(CHARSET_INFO * cs __attribute__((unused)),
-static void my_casedn_ucs2(CHARSET_INFO *cs, char *s, uint slen)
+static uint my_casedn_ucs2(CHARSET_INFO *cs, char *src, uint srclen,
+ char *dst __attribute__((unused)),
+ uint dstlen __attribute__((unused)))
{
my_wc_t wc;
int res;
- char *e=s+slen;
+ char *srcend= src + srclen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ DBUG_ASSERT(src == dst && srclen == dstlen);
- while ((s < e) && (res=my_ucs2_uni(cs, &wc, (uchar*)s, (uchar*)e))>0)
+ while ((src < srcend) &&
+ (res= my_ucs2_uni(cs, &wc, (uchar*) src, (uchar*) srcend)) > 0)
{
- int plane = (wc>>8) & 0xFF;
- wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc;
- if (res != my_uni_ucs2(cs, wc, (uchar*)s, (uchar*)e))
- {
+ int plane= (wc>>8) & 0xFF;
+ wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc;
+ if (res != my_uni_ucs2(cs, wc, (uchar*) src, (uchar*) srcend))
break;
- }
- s+=res;
+ src+= res;
}
+ return srclen;
}
static void my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)),
@@ -190,6 +203,7 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs,
my_wc_t s_wc,t_wc;
const uchar *se=s+slen;
const uchar *te=t+tlen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
while ( s < se && t < te )
{
@@ -215,7 +229,7 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return t_is_prefix ? (int) (t - te) : (int) ((se - s) - (te - t));
+ return (int) (t_is_prefix ? t-te : ((se-s) - (te-t)));
}
/*
@@ -247,14 +261,17 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs,
static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)),
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference
+ __attribute__((unused)))
{
const uchar *se, *te;
uint minlen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
/* extra safety to make sure the lengths are even numbers */
- slen= (slen >> 1) << 1;
- tlen= (tlen >> 1) << 1;
+ slen&= ~1;
+ tlen&= ~1;
se= s + slen;
te= t + tlen;
@@ -300,6 +317,7 @@ static int my_strncasecmp_ucs2(CHARSET_INFO *cs,
my_wc_t s_wc,t_wc;
const char *se=s+len;
const char *te=t+len;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
while ( s < se && t < te )
{
@@ -332,8 +350,8 @@ static int my_strncasecmp_ucs2(CHARSET_INFO *cs,
static int my_strcasecmp_ucs2(CHARSET_INFO *cs, const char *s, const char *t)
{
- uint s_len=strlen(s);
- uint t_len=strlen(t);
+ uint s_len= (uint) strlen(s);
+ uint t_len= (uint) strlen(t);
uint len = (s_len > t_len) ? s_len : t_len;
return my_strncasecmp_ucs2(cs, s, t, len);
}
@@ -347,6 +365,7 @@ static int my_strnxfrm_ucs2(CHARSET_INFO *cs,
int plane;
uchar *de = dst + dstlen;
const uchar *se = src + srclen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
while( src < se && dst < de )
{
@@ -367,7 +386,7 @@ static int my_strnxfrm_ucs2(CHARSET_INFO *cs,
dst+=res;
}
if (dst < de)
- cs->cset->fill(cs, dst, de - dst, ' ');
+ cs->cset->fill(cs, (char*) dst, (uint) (de - dst), ' ');
return dstlen;
}
@@ -921,15 +940,16 @@ bs:
return (negative ? -((longlong) res) : (longlong) res);
}
-double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
- char *nptr, uint length,
- char **endptr, int *err)
+
+double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ char *nptr, uint length,
+ char **endptr, int *err)
{
char buf[256];
double res;
register char *b=buf;
register const uchar *s= (const uchar*) nptr;
- register const uchar *end;
+ const uchar *end;
my_wc_t wc;
int cnv;
@@ -1043,7 +1063,7 @@ int my_ll10tostr_ucs2(CHARSET_INFO *cs __attribute__((unused)),
while (long_val != 0)
{
long quo= long_val/10;
- *--p = '0' + (long_val - quo*10);
+ *--p = '0' + (char)(long_val - quo*10);
long_val= quo;
}
@@ -1304,6 +1324,7 @@ int my_wildcmp_ucs2_ci(CHARSET_INFO *cs,
const char *wildstr,const char *wildend,
int escape, int w_one, int w_many)
{
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
return my_wildcmp_unicode(cs,str,str_end,wildstr,wildend,
escape,w_one,w_many,uni_plane);
}
@@ -1349,13 +1370,16 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return t_is_prefix ? (int) (t - te) : (int) ((se-s) - (te-t));
+ return (int) (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)
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference
+ __attribute__((unused)))
{
+ /* TODO: Needs to be fixed to handle end space! */
return my_strnncoll_ucs2_bin(cs,s,slen,t,tlen,0);
}
@@ -1363,8 +1387,8 @@ static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs,
static
int my_strcasecmp_ucs2_bin(CHARSET_INFO *cs, const char *s, const char *t)
{
- uint s_len=strlen(s);
- uint t_len=strlen(t);
+ uint s_len= (uint) strlen(s);
+ uint t_len= (uint) strlen(t);
uint len = (s_len > t_len) ? s_len : t_len;
return my_strncasecmp_ucs2(cs, s, t, len);
}
@@ -1378,7 +1402,7 @@ int my_strnxfrm_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)),
if (dst != src)
memcpy(dst,src,srclen= min(dstlen,srclen));
if (dstlen > srclen)
- cs->cset->fill(cs, dst + srclen, dstlen - srclen, ' ');
+ cs->cset->fill(cs, (char*) dst + srclen, dstlen - srclen, ' ');
return dstlen;
}
@@ -1446,8 +1470,14 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
}
if (ptr[0] == '\0' && ptr[1] == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
do {
*min_str++ = 0;
*min_str++ = 0;
@@ -1459,7 +1489,6 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
*min_str++= *max_str++ = ptr[0];
*min_str++= *max_str++ = ptr[1];
}
- *min_length= *max_length = (uint) (min_str - min_org);
/* Temporary fix for handling w_one at end of string (key compression) */
{
@@ -1471,15 +1500,17 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
}
}
+ *min_length= *max_length = (uint) (min_str - min_org);
while (min_str + 1 < min_end)
{
*min_str++ = *max_str++ = '\0';
- *min_str++ = *max_str++ = ' '; /* Because if key compression */
+ *min_str++ = *max_str++ = ' '; /* Because if key compression */
}
return 0;
}
+
ulong my_scan_ucs2(CHARSET_INFO *cs __attribute__((unused)),
const char *str, const char *end, int sequence_type)
{
@@ -1508,11 +1539,13 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler =
my_strnncoll_ucs2,
my_strnncollsp_ucs2,
my_strnxfrm_ucs2,
+ my_strnxfrmlen_simple,
my_like_range_ucs2,
my_wildcmp_ucs2_ci,
my_strcasecmp_ucs2,
my_instr_mb,
- my_hash_sort_ucs2
+ my_hash_sort_ucs2,
+ my_propagate_simple
};
@@ -1522,11 +1555,13 @@ static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler =
my_strnncoll_ucs2_bin,
my_strnncollsp_ucs2_bin,
my_strnxfrm_ucs2_bin,
+ my_strnxfrmlen_simple,
my_like_range_simple,
my_wildcmp_ucs2_bin,
my_strcasecmp_ucs2_bin,
my_instr_mb,
- my_hash_sort_ucs2_bin
+ my_hash_sort_ucs2_bin,
+ my_propagate_simple
};
@@ -1576,9 +1611,12 @@ CHARSET_INFO my_charset_ucs2_general_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
@@ -1604,9 +1642,12 @@ CHARSET_INFO my_charset_ucs2_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
2, /* mbminlen */
2, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index b3bba85968e..57ca2de2852 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -8287,7 +8287,7 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)),
if (b >= (uchar*) end)
{
*error= 1;
- return (uint) (chbeg - beg);/* unexpected EOL */
+ return (uint) (chbeg - beg); /* unexpected EOL */
}
}
@@ -8510,11 +8510,13 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncoll_simple,/* strnncoll */
my_strnncollsp_simple,
my_strnxfrm_simple, /* strnxfrm */
+ my_strnxfrmlen_simple,
my_like_range_simple,/* like_range */
my_wildcmp_mb, /* wildcmp */
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
@@ -8564,9 +8566,12 @@ CHARSET_INFO my_charset_ujis_japanese_ci=
NULL, /* contractions */
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
@@ -8593,9 +8598,12 @@ CHARSET_INFO my_charset_ujis_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index b3e78ce27e9..88b6b7d5c86 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -172,6 +172,8 @@ static MY_UNICASE_INFO plane00[]={
{0x00DE,0x00FE,0x00DE}, {0x0178,0x00FF,0x0059}
};
+
+
static MY_UNICASE_INFO plane01[]={
{0x0100,0x0101,0x0041}, {0x0100,0x0101,0x0041},
{0x0102,0x0103,0x0041}, {0x0102,0x0103,0x0041},
@@ -1482,7 +1484,7 @@ static MY_UNICASE_INFO planeFF[]={
{0xFFFE,0xFFFE,0xFFFE}, {0xFFFF,0xFFFF,0xFFFF}
};
-MY_UNICASE_INFO *uni_plane[256]={
+MY_UNICASE_INFO *my_unicase_default[256]={
plane00, plane01, plane02, plane03, plane04, plane05, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1520,6 +1522,186 @@ MY_UNICASE_INFO *uni_plane[256]={
/*
+ Turkish lower/upper mapping:
+ 1. LOWER(0x0049 LATIN CAPITAL LETTER I) ->
+ 0x0131 LATIN SMALL LETTER DOTLESS I
+ 2. UPPER(0x0069 LATIN SMALL LETTER I) ->
+ 0x0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
+*/
+
+static MY_UNICASE_INFO turk00[]=
+{
+ {0x0000,0x0000,0x0000}, {0x0001,0x0001,0x0001},
+ {0x0002,0x0002,0x0002}, {0x0003,0x0003,0x0003},
+ {0x0004,0x0004,0x0004}, {0x0005,0x0005,0x0005},
+ {0x0006,0x0006,0x0006}, {0x0007,0x0007,0x0007},
+ {0x0008,0x0008,0x0008}, {0x0009,0x0009,0x0009},
+ {0x000A,0x000A,0x000A}, {0x000B,0x000B,0x000B},
+ {0x000C,0x000C,0x000C}, {0x000D,0x000D,0x000D},
+ {0x000E,0x000E,0x000E}, {0x000F,0x000F,0x000F},
+ {0x0010,0x0010,0x0010}, {0x0011,0x0011,0x0011},
+ {0x0012,0x0012,0x0012}, {0x0013,0x0013,0x0013},
+ {0x0014,0x0014,0x0014}, {0x0015,0x0015,0x0015},
+ {0x0016,0x0016,0x0016}, {0x0017,0x0017,0x0017},
+ {0x0018,0x0018,0x0018}, {0x0019,0x0019,0x0019},
+ {0x001A,0x001A,0x001A}, {0x001B,0x001B,0x001B},
+ {0x001C,0x001C,0x001C}, {0x001D,0x001D,0x001D},
+ {0x001E,0x001E,0x001E}, {0x001F,0x001F,0x001F},
+ {0x0020,0x0020,0x0020}, {0x0021,0x0021,0x0021},
+ {0x0022,0x0022,0x0022}, {0x0023,0x0023,0x0023},
+ {0x0024,0x0024,0x0024}, {0x0025,0x0025,0x0025},
+ {0x0026,0x0026,0x0026}, {0x0027,0x0027,0x0027},
+ {0x0028,0x0028,0x0028}, {0x0029,0x0029,0x0029},
+ {0x002A,0x002A,0x002A}, {0x002B,0x002B,0x002B},
+ {0x002C,0x002C,0x002C}, {0x002D,0x002D,0x002D},
+ {0x002E,0x002E,0x002E}, {0x002F,0x002F,0x002F},
+ {0x0030,0x0030,0x0030}, {0x0031,0x0031,0x0031},
+ {0x0032,0x0032,0x0032}, {0x0033,0x0033,0x0033},
+ {0x0034,0x0034,0x0034}, {0x0035,0x0035,0x0035},
+ {0x0036,0x0036,0x0036}, {0x0037,0x0037,0x0037},
+ {0x0038,0x0038,0x0038}, {0x0039,0x0039,0x0039},
+ {0x003A,0x003A,0x003A}, {0x003B,0x003B,0x003B},
+ {0x003C,0x003C,0x003C}, {0x003D,0x003D,0x003D},
+ {0x003E,0x003E,0x003E}, {0x003F,0x003F,0x003F},
+ {0x0040,0x0040,0x0040}, {0x0041,0x0061,0x0041},
+ {0x0042,0x0062,0x0042}, {0x0043,0x0063,0x0043},
+ {0x0044,0x0064,0x0044}, {0x0045,0x0065,0x0045},
+ {0x0046,0x0066,0x0046}, {0x0047,0x0067,0x0047},
+ {0x0048,0x0068,0x0048}, {0x0049,0x0131,0x0049},
+ {0x004A,0x006A,0x004A}, {0x004B,0x006B,0x004B},
+ {0x004C,0x006C,0x004C}, {0x004D,0x006D,0x004D},
+ {0x004E,0x006E,0x004E}, {0x004F,0x006F,0x004F},
+ {0x0050,0x0070,0x0050}, {0x0051,0x0071,0x0051},
+ {0x0052,0x0072,0x0052}, {0x0053,0x0073,0x0053},
+ {0x0054,0x0074,0x0054}, {0x0055,0x0075,0x0055},
+ {0x0056,0x0076,0x0056}, {0x0057,0x0077,0x0057},
+ {0x0058,0x0078,0x0058}, {0x0059,0x0079,0x0059},
+ {0x005A,0x007A,0x005A}, {0x005B,0x005B,0x005B},
+ {0x005C,0x005C,0x005C}, {0x005D,0x005D,0x005D},
+ {0x005E,0x005E,0x005E}, {0x005F,0x005F,0x005F},
+ {0x0060,0x0060,0x0060}, {0x0041,0x0061,0x0041},
+ {0x0042,0x0062,0x0042}, {0x0043,0x0063,0x0043},
+ {0x0044,0x0064,0x0044}, {0x0045,0x0065,0x0045},
+ {0x0046,0x0066,0x0046}, {0x0047,0x0067,0x0047},
+ {0x0048,0x0068,0x0048}, {0x0130,0x0069,0x0049},
+ {0x004A,0x006A,0x004A}, {0x004B,0x006B,0x004B},
+ {0x004C,0x006C,0x004C}, {0x004D,0x006D,0x004D},
+ {0x004E,0x006E,0x004E}, {0x004F,0x006F,0x004F},
+ {0x0050,0x0070,0x0050}, {0x0051,0x0071,0x0051},
+ {0x0052,0x0072,0x0052}, {0x0053,0x0073,0x0053},
+ {0x0054,0x0074,0x0054}, {0x0055,0x0075,0x0055},
+ {0x0056,0x0076,0x0056}, {0x0057,0x0077,0x0057},
+ {0x0058,0x0078,0x0058}, {0x0059,0x0079,0x0059},
+ {0x005A,0x007A,0x005A}, {0x007B,0x007B,0x007B},
+ {0x007C,0x007C,0x007C}, {0x007D,0x007D,0x007D},
+ {0x007E,0x007E,0x007E}, {0x007F,0x007F,0x007F},
+ {0x0080,0x0080,0x0080}, {0x0081,0x0081,0x0081},
+ {0x0082,0x0082,0x0082}, {0x0083,0x0083,0x0083},
+ {0x0084,0x0084,0x0084}, {0x0085,0x0085,0x0085},
+ {0x0086,0x0086,0x0086}, {0x0087,0x0087,0x0087},
+ {0x0088,0x0088,0x0088}, {0x0089,0x0089,0x0089},
+ {0x008A,0x008A,0x008A}, {0x008B,0x008B,0x008B},
+ {0x008C,0x008C,0x008C}, {0x008D,0x008D,0x008D},
+ {0x008E,0x008E,0x008E}, {0x008F,0x008F,0x008F},
+ {0x0090,0x0090,0x0090}, {0x0091,0x0091,0x0091},
+ {0x0092,0x0092,0x0092}, {0x0093,0x0093,0x0093},
+ {0x0094,0x0094,0x0094}, {0x0095,0x0095,0x0095},
+ {0x0096,0x0096,0x0096}, {0x0097,0x0097,0x0097},
+ {0x0098,0x0098,0x0098}, {0x0099,0x0099,0x0099},
+ {0x009A,0x009A,0x009A}, {0x009B,0x009B,0x009B},
+ {0x009C,0x009C,0x009C}, {0x009D,0x009D,0x009D},
+ {0x009E,0x009E,0x009E}, {0x009F,0x009F,0x009F},
+ {0x00A0,0x00A0,0x00A0}, {0x00A1,0x00A1,0x00A1},
+ {0x00A2,0x00A2,0x00A2}, {0x00A3,0x00A3,0x00A3},
+ {0x00A4,0x00A4,0x00A4}, {0x00A5,0x00A5,0x00A5},
+ {0x00A6,0x00A6,0x00A6}, {0x00A7,0x00A7,0x00A7},
+ {0x00A8,0x00A8,0x00A8}, {0x00A9,0x00A9,0x00A9},
+ {0x00AA,0x00AA,0x00AA}, {0x00AB,0x00AB,0x00AB},
+ {0x00AC,0x00AC,0x00AC}, {0x00AD,0x00AD,0x00AD},
+ {0x00AE,0x00AE,0x00AE}, {0x00AF,0x00AF,0x00AF},
+ {0x00B0,0x00B0,0x00B0}, {0x00B1,0x00B1,0x00B1},
+ {0x00B2,0x00B2,0x00B2}, {0x00B3,0x00B3,0x00B3},
+ {0x00B4,0x00B4,0x00B4}, {0x039C,0x00B5,0x039C},
+ {0x00B6,0x00B6,0x00B6}, {0x00B7,0x00B7,0x00B7},
+ {0x00B8,0x00B8,0x00B8}, {0x00B9,0x00B9,0x00B9},
+ {0x00BA,0x00BA,0x00BA}, {0x00BB,0x00BB,0x00BB},
+ {0x00BC,0x00BC,0x00BC}, {0x00BD,0x00BD,0x00BD},
+ {0x00BE,0x00BE,0x00BE}, {0x00BF,0x00BF,0x00BF},
+ {0x00C0,0x00E0,0x0041}, {0x00C1,0x00E1,0x0041},
+ {0x00C2,0x00E2,0x0041}, {0x00C3,0x00E3,0x0041},
+ {0x00C4,0x00E4,0x0041}, {0x00C5,0x00E5,0x0041},
+ {0x00C6,0x00E6,0x00C6}, {0x00C7,0x00E7,0x0043},
+ {0x00C8,0x00E8,0x0045}, {0x00C9,0x00E9,0x0045},
+ {0x00CA,0x00EA,0x0045}, {0x00CB,0x00EB,0x0045},
+ {0x00CC,0x00EC,0x0049}, {0x00CD,0x00ED,0x0049},
+ {0x00CE,0x00EE,0x0049}, {0x00CF,0x00EF,0x0049},
+ {0x00D0,0x00F0,0x00D0}, {0x00D1,0x00F1,0x004E},
+ {0x00D2,0x00F2,0x004F}, {0x00D3,0x00F3,0x004F},
+ {0x00D4,0x00F4,0x004F}, {0x00D5,0x00F5,0x004F},
+ {0x00D6,0x00F6,0x004F}, {0x00D7,0x00D7,0x00D7},
+ {0x00D8,0x00F8,0x00D8}, {0x00D9,0x00F9,0x0055},
+ {0x00DA,0x00FA,0x0055}, {0x00DB,0x00FB,0x0055},
+ {0x00DC,0x00FC,0x0055}, {0x00DD,0x00FD,0x0059},
+ {0x00DE,0x00FE,0x00DE}, {0x00DF,0x00DF,0x00DF},
+ {0x00C0,0x00E0,0x0041}, {0x00C1,0x00E1,0x0041},
+ {0x00C2,0x00E2,0x0041}, {0x00C3,0x00E3,0x0041},
+ {0x00C4,0x00E4,0x0041}, {0x00C5,0x00E5,0x0041},
+ {0x00C6,0x00E6,0x00C6}, {0x00C7,0x00E7,0x0043},
+ {0x00C8,0x00E8,0x0045}, {0x00C9,0x00E9,0x0045},
+ {0x00CA,0x00EA,0x0045}, {0x00CB,0x00EB,0x0045},
+ {0x00CC,0x00EC,0x0049}, {0x00CD,0x00ED,0x0049},
+ {0x00CE,0x00EE,0x0049}, {0x00CF,0x00EF,0x0049},
+ {0x00D0,0x00F0,0x00D0}, {0x00D1,0x00F1,0x004E},
+ {0x00D2,0x00F2,0x004F}, {0x00D3,0x00F3,0x004F},
+ {0x00D4,0x00F4,0x004F}, {0x00D5,0x00F5,0x004F},
+ {0x00D6,0x00F6,0x004F}, {0x00F7,0x00F7,0x00F7},
+ {0x00D8,0x00F8,0x00D8}, {0x00D9,0x00F9,0x0055},
+ {0x00DA,0x00FA,0x0055}, {0x00DB,0x00FB,0x0055},
+ {0x00DC,0x00FC,0x0055}, {0x00DD,0x00FD,0x0059},
+ {0x00DE,0x00FE,0x00DE}, {0x0178,0x00FF,0x0059}
+};
+
+
+
+MY_UNICASE_INFO *my_unicase_turkish[256]=
+{
+ turk00, plane01, plane02, plane03, plane04, plane05, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, plane1E, plane1F,
+ NULL, plane21, NULL, NULL, plane24, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, planeFF
+};
+
+
+
+/*
** Compare string against string with wildcard
** This function is used in UTF8 and UCS2
**
@@ -1752,7 +1934,7 @@ static uchar to_upper_utf8[] = {
static inline int bincmp(const uchar *s, const uchar *se,
const uchar *t, const uchar *te)
{
- int slen=se-s, tlen=te-t;
+ int slen= (int) (se-s), tlen= (int) (te-t);
int len=min(slen,tlen);
int cmp= memcmp(s,t,len);
return cmp ? cmp : slen-tlen;
@@ -1909,27 +2091,42 @@ static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) ,
}
-static void my_caseup_utf8(CHARSET_INFO *cs, char *s, uint slen)
+static uint my_caseup_utf8(CHARSET_INFO *cs, char *src, uint srclen,
+ char *dst, uint dstlen)
{
my_wc_t wc;
- int res;
- char *e=s+slen;
+ int srcres, dstres;
+ char *srcend= src + srclen, *dstend= dst + dstlen, *dst0= dst;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ DBUG_ASSERT(src != dst || cs->caseup_multiply == 1);
- while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
+ while ((src < srcend) &&
+ (srcres= my_utf8_uni(cs, &wc, (uchar *) src, (uchar*) srcend)) > 0)
{
- int plane = (wc>>8) & 0xFF;
- wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
- if (res != my_uni_utf8(cs,wc,(uchar*)s,(uchar*)e))
+ int plane= (wc>>8) & 0xFF;
+ wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
+ if ((dstres= my_uni_utf8(cs, wc, (uchar*) dst, (uchar*) dstend)) <= 0)
break;
- s+=res;
+ src+= srcres;
+ dst+= dstres;
}
+ return (uint) (dst - dst0);
}
-static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen, ulong *n1, ulong *n2)
+static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen,
+ ulong *n1, ulong *n2)
{
my_wc_t wc;
int res;
const uchar *e=s+slen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+
+ /*
+ Remove end space. We have to do this to be able to compare
+ 'A ' and 'A' as identical
+ */
+ while (e > s && e[-1] == ' ')
+ e--;
while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
{
@@ -1946,31 +2143,37 @@ static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen, ulong
static void my_caseup_str_utf8(CHARSET_INFO * cs, char * s)
{
- my_caseup_utf8(cs, s, strlen(s));
+ uint len= (uint) strlen(s);
+ my_caseup_utf8(cs, s, len, s, len);
}
-static void my_casedn_utf8(CHARSET_INFO *cs, char *s, uint slen)
+static uint my_casedn_utf8(CHARSET_INFO *cs, char *src, uint srclen,
+ char *dst, uint dstlen)
{
my_wc_t wc;
- int res;
- char *e=s+slen;
+ int srcres, dstres;
+ char *srcend= src + srclen, *dstend= dst + dstlen, *dst0= dst;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ DBUG_ASSERT(src != dst || cs->casedn_multiply == 1);
- while ((s < e) && (res=my_utf8_uni(cs, &wc, (uchar*)s, (uchar*)e))>0)
+ while ((src < srcend) &&
+ (srcres= my_utf8_uni(cs, &wc, (uchar*) src, (uchar*)srcend)) > 0)
{
- int plane = (wc>>8) & 0xFF;
- wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc;
- if (res != my_uni_utf8(cs, wc, (uchar*)s, (uchar*)e))
- {
+ int plane= (wc>>8) & 0xFF;
+ wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc;
+ if ((dstres= my_uni_utf8(cs, wc, (uchar*) dst, (uchar*) dstend)) <= 0)
break;
- }
- s+=res;
+ src+= srcres;
+ dst+= dstres;
}
+ return (uint) (dst - dst0);
}
static void my_casedn_str_utf8(CHARSET_INFO *cs, char * s)
{
- my_casedn_utf8(cs, s, strlen(s));
+ uint len= (uint) strlen(s);
+ my_casedn_utf8(cs, s, len, s, len);
}
@@ -1983,6 +2186,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
my_wc_t s_wc,t_wc;
const uchar *se=s+slen;
const uchar *te=t+tlen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
while ( s < se && t < te )
{
@@ -2008,7 +2212,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
s+=s_res;
t+=t_res;
}
- return t_is_prefix ? (int) (t-te) : (int) ((se-s) - (te-t));
+ return (int) (t_is_prefix ? t-te : ((se-s) - (te-t)));
}
@@ -2023,6 +2227,9 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
a_length Length of 'a'
b Second string to compare
b_length Length of 'b'
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
IMPLEMENTATION
If one string is shorter as the other, then we space extend the other
@@ -2041,13 +2248,18 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
*/
static int my_strnncollsp_utf8(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 diff_if_only_endspace_difference)
{
- int s_res,t_res;
+ int s_res, t_res, res;
my_wc_t s_wc,t_wc;
- const uchar *se= s+slen;
- const uchar *te= t+tlen;
+ const uchar *se= s+slen, *te= t+tlen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
while ( s < se && t < te )
{
@@ -2074,18 +2286,22 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
t+=t_res;
}
- slen= se-s;
- tlen= te-t;
+ slen= (uint) (se-s);
+ tlen= (uint) (te-t);
+ res= 0;
if (slen != tlen)
{
int swap= 1;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
if (slen < tlen)
{
slen= tlen;
s= t;
se= te;
swap= -1;
+ res= -res;
}
/*
This following loop uses the fact that in UTF-8
@@ -2103,7 +2319,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
return (*s < ' ') ? -swap : swap;
}
}
- return 0;
+ return res;
}
@@ -2127,6 +2343,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
static
int my_strcasecmp_utf8(CHARSET_INFO *cs, const char *s, const char *t)
{
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
while (s[0] && t[0])
{
my_wc_t s_wc,t_wc;
@@ -2211,11 +2428,18 @@ int my_wildcmp_utf8(CHARSET_INFO *cs,
const char *wildstr,const char *wildend,
int escape, int w_one, int w_many)
{
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
return my_wildcmp_unicode(cs,str,str_end,wildstr,wildend,
escape,w_one,w_many,uni_plane);
}
+static
+uint my_strnxfrmlen_utf8(CHARSET_INFO *cs __attribute__((unused)), uint len)
+{
+ return (len * 2 + 2) / 3;
+}
+
static int my_strnxfrm_utf8(CHARSET_INFO *cs,
uchar *dst, uint dstlen,
const uchar *src, uint srclen)
@@ -2223,29 +2447,34 @@ static int my_strnxfrm_utf8(CHARSET_INFO *cs,
my_wc_t wc;
int res;
int plane;
- uchar *de = dst + dstlen;
+ uchar *de= dst + dstlen;
+ uchar *de_beg= de - 1;
const uchar *se = src + srclen;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
- while( src < se && dst < de )
+ while (dst < de_beg)
{
- if ((res=my_utf8_uni(cs,&wc, src, se))<0)
- {
+ if ((res=my_utf8_uni(cs,&wc, src, se)) <= 0)
break;
- }
src+=res;
- srclen-=res;
plane=(wc>>8) & 0xFF;
wc = uni_plane[plane] ? uni_plane[plane][wc & 0xFF].sort : wc;
- if ((res=my_uni_utf8(cs,wc,dst,de)) <0)
- {
- break;
- }
- dst+=res;
+ *dst++= (uchar)(wc >> 8);
+ *dst++= (uchar)(wc & 0xFF);
+
+ }
+
+ while (dst < de_beg) /* Fill the tail with keys for space character */
+ {
+ *dst++= 0x00;
+ *dst++= 0x20;
}
- if (dst < de)
- bfill(dst, de - dst, ' ');
+
+ if (dst < de) /* Clear the last byte, if "dstlen" was an odd number */
+ *dst= 0x00;
+
return dstlen;
}
@@ -2284,11 +2513,13 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strnncoll_utf8,
my_strnncollsp_utf8,
my_strnxfrm_utf8,
+ my_strnxfrmlen_utf8,
my_like_range_mb,
my_wildcmp_utf8,
my_strcasecmp_utf8,
my_instr_mb,
- my_hash_sort_utf8
+ my_hash_sort_utf8,
+ my_propagate_complex
};
MY_CHARSET_HANDLER my_charset_utf8_handler=
@@ -2338,9 +2569,12 @@ CHARSET_INFO my_charset_utf8_general_ci=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
@@ -2367,9 +2601,12 @@ CHARSET_INFO my_charset_utf8_bin=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
@@ -2514,7 +2751,8 @@ static MY_COLLATION_HANDLER my_collation_cs_handler =
my_wildcmp_mb,
my_strcasecmp_utf8,
my_instr_mb,
- my_hash_sort_utf8
+ my_hash_sort_utf8,
+ my_propagate_simple
};
CHARSET_INFO my_charset_utf8_general_cs=
@@ -2533,9 +2771,12 @@ CHARSET_INFO my_charset_utf8_general_cs=
NULL, /* sort_order_big*/
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
1, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
@@ -2554,7 +2795,7 @@ static void test_mb(CHARSET_INFO *cs, uchar *s)
{
while(*s)
{
- if(my_ismbhead_utf8(cs,*s))
+ if (my_ismbhead_utf8(cs,*s))
{
int len=my_mbcharlen_utf8(cs,*s);
while(len--)
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index 351af3de23e..c6b396658d4 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -479,7 +479,9 @@ static int my_strnncoll_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
static
int my_strnncollsp_win1250ch(CHARSET_INFO * cs,
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference
+ __attribute__((unused)))
{
for ( ; slen && s[slen-1] == ' ' ; slen--);
for ( ; tlen && t[tlen-1] == ' ' ; tlen--);
@@ -596,11 +598,19 @@ my_like_range_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
if (*min_str != min_sort_char)
only_min_found= 0;
min_str++;
- *max_str++ = like_range_prefix_max_win1250ch[(uint)(*ptr)];
+ *max_str++= like_range_prefix_max_win1250ch[(uint)(*ptr)];
}
- *min_length = (uint) (min_str - min_org);
- *max_length = res_length;
+ if (cs->state & MY_CS_BINSORT)
+ *min_length= (uint) (min_str - min_org);
+ else
+ {
+ /* 'a\0\0... is the smallest possible string */
+ *min_length= res_length;
+ }
+ /* a\ff\ff... is the biggest possible string */
+ *max_length= res_length;
+
while (min_str != min_end)
{
*min_str++ = min_sort_char;
@@ -616,11 +626,13 @@ static MY_COLLATION_HANDLER my_collation_czech_ci_handler =
my_strnncoll_win1250ch,
my_strnncollsp_win1250ch,
my_strnxfrm_win1250ch,
+ my_strnxfrmlen_simple,
my_like_range_win1250ch,
my_wildcmp_8bit,
my_strcasecmp_8bit,
my_instr_simple,
- my_hash_sort_simple
+ my_hash_sort_simple,
+ my_propagate_simple
};
@@ -640,9 +652,12 @@ CHARSET_INFO my_charset_cp1250_czech_ci =
NULL, /* sort_order_big*/
tab_cp1250_uni, /* tab_to_uni */
idx_uni_cp1250, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
NULL, /* state_map */
NULL, /* ident_map */
2, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
diff --git a/strings/ctype.c b/strings/ctype.c
index 4454d3c45e1..91fa1413259 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -216,15 +216,7 @@ static int cs_value(MY_XML_PARSER *st,const char *attr, uint len)
{
struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
struct my_cs_file_section_st *s;
- int state= (s=cs_file_sec(st->attr,strlen(st->attr))) ? s->state : 0;
-
-#ifndef DBUG_OFF
- if(0){
- char str[1024];
- mstr(str,attr,len,sizeof(str)-1);
- printf("VALUE %d %s='%s'\n",state,st->attr,str);
- }
-#endif
+ int state= (int)((s=cs_file_sec(st->attr, (int) strlen(st->attr))) ? s->state : 0);
switch (state) {
case _CS_ID:
diff --git a/strings/decimal.c b/strings/decimal.c
new file mode 100644
index 00000000000..7816f340eef
--- /dev/null
+++ b/strings/decimal.c
@@ -0,0 +1,3065 @@
+/* Copyright (C) 2000 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 */
+
+#line 18 "decimal.c"
+
+/*
+=======================================================================
+ NOTE: this library implements SQL standard "exact numeric" type
+ and is not at all generic, but rather intentinally crippled to
+ follow the standard :)
+=======================================================================
+ Quoting the standard
+ (SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
+
+4.4.2 Characteristics of numbers, page 27:
+
+ An exact numeric type has a precision P and a scale S. P is a positive
+ integer that determines the number of significant digits in a
+ particular radix R, where R is either 2 or 10. S is a non-negative
+ integer. Every value of an exact numeric type of scale S is of the
+ form n*10^{-S}, where n is an integer such that ­-R^P <= n <= R^P.
+
+ [...]
+
+ If an assignment of some number would result in a loss of its most
+ significant digit, an exception condition is raised. If least
+ significant digits are lost, implementation-defined rounding or
+ truncating occurs, with no exception condition being raised.
+
+ [...]
+
+ Whenever an exact or approximate numeric value is assigned to an exact
+ numeric value site, an approximation of its value that preserves
+ leading significant digits after rounding or truncating is represented
+ in the declared type of the target. The value is converted to have the
+ precision and scale of the target. The choice of whether to truncate
+ or round is implementation-defined.
+
+ [...]
+
+ All numeric values between the smallest and the largest value,
+ inclusive, in a given exact numeric type have an approximation
+ obtained by rounding or truncation for that type; it is
+ implementation-defined which other numeric values have such
+ approximations.
+
+5.3 <literal>, page 143
+
+ <exact numeric literal> ::=
+ <unsigned integer> [ <period> [ <unsigned integer> ] ]
+ | <period> <unsigned integer>
+
+6.1 <data type>, page 165:
+
+ 19) The <scale> of an <exact numeric type> shall not be greater than
+ the <precision> of the <exact numeric type>.
+
+ 20) For the <exact numeric type>s DECIMAL and NUMERIC:
+
+ a) The maximum value of <precision> is implementation-defined.
+ <precision> shall not be greater than this value.
+ b) The maximum value of <scale> is implementation-defined. <scale>
+ shall not be greater than this maximum value.
+
+ 21) NUMERIC specifies the data type exact numeric, with the decimal
+ precision and scale specified by the <precision> and <scale>.
+
+ 22) DECIMAL specifies the data type exact numeric, with the decimal
+ scale specified by the <scale> and the implementation-defined
+ decimal precision equal to or greater than the value of the
+ specified <precision>.
+
+6.26 <numeric value expression>, page 241:
+
+ 1) If the declared type of both operands of a dyadic arithmetic
+ operator is exact numeric, then the declared type of the result is
+ an implementation-defined exact numeric type, with precision and
+ scale determined as follows:
+
+ a) Let S1 and S2 be the scale of the first and second operands
+ respectively.
+ b) The precision of the result of addition and subtraction is
+ implementation-defined, and the scale is the maximum of S1 and S2.
+ c) The precision of the result of multiplication is
+ implementation-defined, and the scale is S1 + S2.
+ d) The precision and scale of the result of division are
+ implementation-defined.
+*/
+
+#include <my_global.h>
+#include <m_ctype.h>
+#include <myisampack.h>
+#include <my_sys.h> /* for my_alloca */
+#include <m_string.h>
+#include <decimal.h>
+
+/*
+ Internally decimal numbers are stored base 10^9 (see DIG_BASE below)
+ So one variable of type decimal_digit_t is limited:
+
+ 0 < decimal_digit <= DIG_MAX < DIG_BASE
+
+ in the struct st_decimal_t:
+
+ intg is the number of *decimal* digits (NOT number of decimal_digit_t's !)
+ before the point
+ frac - number of decimal digits after the point
+ buf is an array of decimal_digit_t's
+ len is the length of buf (length of allocated space) in decimal_digit_t's,
+ not in bytes
+*/
+typedef decimal_digit_t dec1;
+typedef longlong dec2;
+
+#define DIG_PER_DEC1 9
+#define DIG_MASK 100000000
+#define DIG_BASE 1000000000
+#define DIG_MAX (DIG_BASE-1)
+#define DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE)
+#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
+static const dec1 powers10[DIG_PER_DEC1+1]={
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
+static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
+static const dec1 frac_max[DIG_PER_DEC1-1]={
+ 900000000, 990000000, 999000000,
+ 999900000, 999990000, 999999000,
+ 999999900, 999999990 };
+
+#ifdef HAVE_purify
+#define sanity(d) DBUG_ASSERT((d)->len > 0)
+#else
+#define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
+ (d)->buf[(d)->len-1] | 1))
+#endif
+
+#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
+ do \
+ { \
+ if (unlikely(intg1+frac1 > (len))) \
+ { \
+ if (unlikely(intg1 > (len))) \
+ { \
+ intg1=(len); \
+ frac1=0; \
+ error=E_DEC_OVERFLOW; \
+ } \
+ else \
+ { \
+ frac1=(len)-intg1; \
+ error=E_DEC_TRUNCATED; \
+ } \
+ } \
+ else \
+ error=E_DEC_OK; \
+ } while(0)
+
+#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
+ do \
+ { \
+ dec1 a=(from1)+(from2)+(carry); \
+ if (((carry)= a >= DIG_BASE)) /* no division here! */ \
+ a-=DIG_BASE; \
+ (to)=a; \
+ } while(0)
+
+#define ADD2(to, from1, from2, carry) \
+ do \
+ { \
+ dec1 a=(from1)+(from2)+(carry); \
+ if (((carry)= a >= DIG_BASE)) \
+ a-=DIG_BASE; \
+ if (unlikely(a >= DIG_BASE)) \
+ { \
+ a-=DIG_BASE; \
+ carry++; \
+ } \
+ (to)=a; \
+ } while(0)
+
+#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
+ do \
+ { \
+ dec1 a=(from1)-(from2)-(carry); \
+ if (((carry)= a < 0)) \
+ a+=DIG_BASE; \
+ (to)=a; \
+ } while(0)
+
+#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
+ do \
+ { \
+ dec1 a=(from1)-(from2)-(carry); \
+ if (((carry)= a < 0)) \
+ a+=DIG_BASE; \
+ if (unlikely(a < 0)) \
+ { \
+ a+=DIG_BASE; \
+ carry++; \
+ } \
+ (to)=a; \
+ } while(0)
+
+/*
+ Get maximum value for given precision and scale
+
+ SYNOPSIS
+ max_decimal()
+ precision/scale - see decimal_bin_size() below
+ to - decimal where where the result will be stored
+ to->buf and to->len must be set.
+*/
+
+void max_decimal(int precision, int frac, decimal_t *to)
+{
+ int intpart;
+ dec1 *buf= to->buf;
+ DBUG_ASSERT(precision && precision >= frac);
+
+ to->sign= 0;
+ if ((intpart= to->intg= (precision - frac)))
+ {
+ int firstdigits= intpart % DIG_PER_DEC1;
+ if (firstdigits)
+ *buf++= powers10[firstdigits] - 1; /* get 9 99 999 ... */
+ for(intpart/= DIG_PER_DEC1; intpart; intpart--)
+ *buf++= DIG_MAX;
+ }
+
+ if ((to->frac= frac))
+ {
+ int lastdigits= frac % DIG_PER_DEC1;
+ for(frac/= DIG_PER_DEC1; frac; frac--)
+ *buf++= DIG_MAX;
+ if (lastdigits)
+ *buf= frac_max[lastdigits - 1];
+ }
+}
+
+
+static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
+{
+ int intg= from->intg, i;
+ dec1 *buf0= from->buf;
+ i= ((intg - 1) % DIG_PER_DEC1) + 1;
+ while (intg > 0 && *buf0 == 0)
+ {
+ intg-= i;
+ i= DIG_PER_DEC1;
+ buf0++;
+ }
+ if (intg > 0)
+ {
+ for (i= (intg - 1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) ;
+ DBUG_ASSERT(intg > 0);
+ }
+ else
+ intg=0;
+ *intg_result= intg;
+ return buf0;
+}
+
+
+/*
+ Count actual length of fraction part (without ending zeroes)
+
+ SYNOPSIS
+ decimal_actual_fraction()
+ from number for processing
+*/
+
+int decimal_actual_fraction(decimal_t *from)
+{
+ int frac= from->frac, i;
+ dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
+
+ if (frac == 0)
+ return 0;
+
+ i= ((frac - 1) % DIG_PER_DEC1 + 1);
+ while (frac > 0 && *buf0 == 0)
+ {
+ frac-= i;
+ i= DIG_PER_DEC1;
+ buf0--;
+ }
+ if (frac > 0)
+ {
+ for (i= DIG_PER_DEC1 - ((frac - 1) % DIG_PER_DEC1);
+ *buf0 % powers10[i++] == 0;
+ frac--);
+ }
+ return frac;
+}
+
+
+/*
+ Convert decimal to its printable string representation
+
+ SYNOPSIS
+ decimal2string()
+ from - value to convert
+ to - points to buffer where string representation
+ should be stored
+ *to_len - in: size of to buffer
+ out: length of the actually written string
+ fixed_precision - 0 if representation can be variable length and
+ fixed_decimals will not be checked in this case.
+ Put number as with fixed point position with this
+ number of digits (sign counted and decimal point is
+ counted)
+ fixed_decimals - number digits after point.
+ filler - character to fill gaps in case of fixed_precision > 0
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
+*/
+
+int decimal2string(decimal_t *from, char *to, int *to_len,
+ int fixed_precision, int fixed_decimals,
+ char filler)
+{
+ int len, intg, frac= from->frac, i, intg_len, frac_len, fill;
+ /* number digits before decimal point */
+ int fixed_intg= (fixed_precision ?
+ (fixed_precision - fixed_decimals) : 0);
+ int error=E_DEC_OK;
+ char *s=to;
+ dec1 *buf, *buf0=from->buf, tmp;
+
+ DBUG_ASSERT(*to_len >= 2+from->sign);
+
+ /* removing leading zeroes */
+ buf0= remove_leading_zeroes(from, &intg);
+ if (unlikely(intg+frac==0))
+ {
+ intg=1;
+ tmp=0;
+ buf0=&tmp;
+ }
+
+ if (!(intg_len= fixed_precision ? fixed_intg : intg))
+ intg_len= 1;
+ frac_len= fixed_precision ? fixed_decimals : frac;
+ len= from->sign + intg_len + test(frac) + frac_len;
+ if (fixed_precision)
+ {
+ if (frac > fixed_decimals)
+ {
+ error= E_DEC_TRUNCATED;
+ frac= fixed_decimals;
+ }
+ if (intg > fixed_intg)
+ {
+ error= E_DEC_OVERFLOW;
+ intg= fixed_intg;
+ }
+ }
+ else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */
+ {
+ int i=len-*to_len;
+ error= (frac && i <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
+ if (frac && i >= frac + 1) i--;
+ if (i > frac)
+ {
+ intg-= i-frac;
+ frac= 0;
+ }
+ else
+ frac-=i;
+ len= from->sign + intg_len + test(frac) + frac_len;
+ }
+ *to_len=len;
+ s[len]=0;
+
+ if (from->sign)
+ *s++='-';
+
+ if (frac)
+ {
+ char *s1= s + intg_len;
+ fill= frac_len - frac;
+ buf=buf0+ROUND_UP(intg);
+ *s1++='.';
+ for (; frac>0; frac-=DIG_PER_DEC1)
+ {
+ dec1 x=*buf++;
+ for (i=min(frac, DIG_PER_DEC1); i; i--)
+ {
+ dec1 y=x/DIG_MASK;
+ *s1++='0'+(uchar)y;
+ x-=y*DIG_MASK;
+ x*=10;
+ }
+ }
+ for(; fill; fill--)
+ *s1++=filler;
+ }
+
+ fill= intg_len - intg;
+ if (intg == 0)
+ fill--; /* symbol 0 before digital point */
+ for(; fill; fill--)
+ *s++=filler;
+ if (intg)
+ {
+ s+=intg;
+ for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
+ {
+ dec1 x=*--buf;
+ for (i=min(intg, DIG_PER_DEC1); i; i--)
+ {
+ dec1 y=x/10;
+ *--s='0'+(uchar)(x-y*10);
+ x=y;
+ }
+ }
+ }
+ else
+ *s= '0';
+ return error;
+}
+
+
+/*
+ Return bounds of decimal digits in the number
+
+ SYNOPSIS
+ digits_bounds()
+ from - decimal number for processing
+ start_result - index (from 0 ) of first decimal digits will
+ be written by this address
+ end_result - index of position just after last decimal digit
+ be written by this address
+*/
+
+static void digits_bounds(decimal_t *from, int *start_result, int *end_result)
+{
+ int start, stop, i;
+ dec1 *buf_beg= from->buf;
+ dec1 *end= from->buf + ROUND_UP(from->intg) + ROUND_UP(from->frac);
+ dec1 *buf_end= end - 1;
+
+ /* find non-zero digit from number begining */
+ while (buf_beg < end && *buf_beg == 0)
+ buf_beg++;
+
+ if (buf_beg >= end)
+ {
+ /* it is zero */
+ *start_result= *end_result= 0;
+ return;
+ }
+
+ /* find non-zero decimal digit from number begining */
+ if (buf_beg == from->buf && from->intg)
+ {
+ start= DIG_PER_DEC1 - (i= ((from->intg-1) % DIG_PER_DEC1 + 1));
+ i--;
+ }
+ else
+ {
+ i= DIG_PER_DEC1 - 1;
+ start= (int) ((buf_beg - from->buf) * DIG_PER_DEC1);
+ }
+ if (buf_beg < end)
+ for (; *buf_beg < powers10[i--]; start++) ;
+ *start_result= start; /* index of first decimal digit (from 0) */
+
+ /* find non-zero digit at the end */
+ while (buf_end > buf_beg && *buf_end == 0)
+ buf_end--;
+ /* find non-zero decimal digit from the end */
+ if (buf_end == end - 1 && from->frac)
+ {
+ stop= (int) (((buf_end - from->buf) * DIG_PER_DEC1 +
+ (i= ((from->frac - 1) % DIG_PER_DEC1 + 1))));
+ i= DIG_PER_DEC1 - i + 1;
+ }
+ else
+ {
+ stop= (int) ((buf_end - from->buf + 1) * DIG_PER_DEC1);
+ i= 1;
+ }
+ for (; *buf_end % powers10[i++] == 0; stop--);
+ *end_result= stop; /* index of position after last decimal digit (from 0) */
+}
+
+
+/*
+ Left shift for alignment of data in buffer
+
+ SYNOPSIS
+ do_mini_left_shift()
+ dec pointer to decimal number which have to be shifted
+ shift number of decimal digits on which it should be shifted
+ beg/end bounds of decimal digits (see digits_bounds())
+
+ NOTE
+ Result fitting in the buffer should be garanted.
+ 'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
+*/
+
+void do_mini_left_shift(decimal_t *dec, int shift, int beg, int last)
+{
+ dec1 *from= dec->buf + ROUND_UP(beg + 1) - 1;
+ dec1 *end= dec->buf + ROUND_UP(last) - 1;
+ int c_shift= DIG_PER_DEC1 - shift;
+ DBUG_ASSERT(from >= dec->buf);
+ DBUG_ASSERT(end < dec->buf + dec->len);
+ if (beg % DIG_PER_DEC1 < shift)
+ *(from - 1)= (*from) / powers10[c_shift];
+ for(; from < end; from++)
+ *from= ((*from % powers10[c_shift]) * powers10[shift] +
+ (*(from + 1)) / powers10[c_shift]);
+ *from= (*from % powers10[c_shift]) * powers10[shift];
+}
+
+
+/*
+ Right shift for alignment of data in buffer
+
+ SYNOPSIS
+ do_mini_left_shift()
+ dec pointer to decimal number which have to be shifted
+ shift number of decimal digits on which it should be shifted
+ beg/end bounds of decimal digits (see digits_bounds())
+
+ NOTE
+ Result fitting in the buffer should be garanted.
+ 'shift' have to be from 1 to DIG_PER_DEC1-1 (inclusive)
+*/
+
+void do_mini_right_shift(decimal_t *dec, int shift, int beg, int last)
+{
+ dec1 *from= dec->buf + ROUND_UP(last) - 1;
+ dec1 *end= dec->buf + ROUND_UP(beg + 1) - 1;
+ int c_shift= DIG_PER_DEC1 - shift;
+ DBUG_ASSERT(from < dec->buf + dec->len);
+ DBUG_ASSERT(end >= dec->buf);
+ if (DIG_PER_DEC1 - ((last - 1) % DIG_PER_DEC1 + 1) < shift)
+ *(from + 1)= (*from % powers10[shift]) * powers10[c_shift];
+ for(; from > end; from--)
+ *from= (*from / powers10[shift] +
+ (*(from - 1) % powers10[shift]) * powers10[c_shift]);
+ *from= *from / powers10[shift];
+}
+
+
+/*
+ Shift of decimal digits in given number (with rounding if it need)
+
+ SYNOPSIS
+ decimal_shift()
+ dec number to be shifted
+ shift number of decimal positions
+ shift > 0 means shift to left shift
+ shift < 0 meand right shift
+ NOTE
+ In fact it is multipling on 10^shift.
+ RETURN
+ E_DEC_OK OK
+ E_DEC_OVERFLOW operation lead to overflow, number is untoched
+ E_DEC_TRUNCATED number was rounded to fit into buffer
+*/
+
+int decimal_shift(decimal_t *dec, int shift)
+{
+ /* index of first non zero digit (all indexes from 0) */
+ int beg;
+ /* index of position after last decimal digit */
+ int end;
+ /* index of digit position just after point */
+ int point= ROUND_UP(dec->intg) * DIG_PER_DEC1;
+ /* new point position */
+ int new_point= point + shift;
+ /* number of digits in result */
+ int digits_int, digits_frac;
+ /* length of result and new fraction in big digits*/
+ int new_len, new_frac_len;
+ /* return code */
+ int err= E_DEC_OK;
+ int new_front;
+
+ if (shift == 0)
+ return E_DEC_OK;
+
+ digits_bounds(dec, &beg, &end);
+
+ if (beg == end)
+ {
+ decimal_make_zero(dec);
+ return E_DEC_OK;
+ }
+
+ digits_int= new_point - beg;
+ set_if_bigger(digits_int, 0);
+ digits_frac= end - new_point;
+ set_if_bigger(digits_frac, 0);
+
+ if ((new_len= ROUND_UP(digits_int) + (new_frac_len= ROUND_UP(digits_frac))) >
+ dec->len)
+ {
+ int lack= new_len - dec->len;
+ int diff;
+
+ if (new_frac_len < lack)
+ return E_DEC_OVERFLOW; /* lack more then we have in fraction */
+
+ /* cat off fraction part to allow new number to fit in our buffer */
+ err= E_DEC_TRUNCATED;
+ new_frac_len-= lack;
+ diff= digits_frac - (new_frac_len * DIG_PER_DEC1);
+ /* Make rounding method as parameter? */
+ decimal_round(dec, dec, end - point - diff, HALF_UP);
+ end-= diff;
+ digits_frac= new_frac_len * DIG_PER_DEC1;
+
+ if (end <= beg)
+ {
+ /*
+ we lost all digits (they will be shifted out of buffer), so we can
+ just return 0
+ */
+ decimal_make_zero(dec);
+ return E_DEC_TRUNCATED;
+ }
+ }
+
+ if (shift % DIG_PER_DEC1)
+ {
+ int l_mini_shift, r_mini_shift, mini_shift;
+ int do_left;
+ /*
+ Calculate left/right shift to align decimal digits inside our bug
+ digits correctly
+ */
+ if (shift > 0)
+ {
+ l_mini_shift= shift % DIG_PER_DEC1;
+ r_mini_shift= DIG_PER_DEC1 - l_mini_shift;
+ /*
+ It is left shift so prefer left shift, but if we have not place from
+ left, we have to have it from right, because we checked length of
+ result
+ */
+ do_left= l_mini_shift <= beg;
+ DBUG_ASSERT(do_left || (dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
+ }
+ else
+ {
+ r_mini_shift= (-shift) % DIG_PER_DEC1;
+ l_mini_shift= DIG_PER_DEC1 - r_mini_shift;
+ /* see comment above */
+ do_left= !((dec->len * DIG_PER_DEC1 - end) >= r_mini_shift);
+ DBUG_ASSERT(!do_left || l_mini_shift <= beg);
+ }
+ if (do_left)
+ {
+ do_mini_left_shift(dec, l_mini_shift, beg, end);
+ mini_shift=- l_mini_shift;
+ }
+ else
+ {
+ do_mini_right_shift(dec, r_mini_shift, beg, end);
+ mini_shift= r_mini_shift;
+ }
+ new_point+= mini_shift;
+ /*
+ If number is shifted and correctly aligned in buffer we can
+ finish
+ */
+ if (!(shift+= mini_shift) && (new_point - digits_int) < DIG_PER_DEC1)
+ {
+ dec->intg= digits_int;
+ dec->frac= digits_frac;
+ return err; /* already shifted as it should be */
+ }
+ beg+= mini_shift;
+ end+= mini_shift;
+ }
+
+ /* if new 'decimal front' is in first digit, we do not need move digits */
+ if ((new_front= (new_point - digits_int)) >= DIG_PER_DEC1 ||
+ new_front < 0)
+ {
+ /* need to move digits */
+ int d_shift;
+ dec1 *to, *barier;
+ if (new_front > 0)
+ {
+ /* move left */
+ d_shift= new_front / DIG_PER_DEC1;
+ to= dec->buf + (ROUND_UP(beg + 1) - 1 - d_shift);
+ barier= dec->buf + (ROUND_UP(end) - 1 - d_shift);
+ DBUG_ASSERT(to >= dec->buf);
+ DBUG_ASSERT(barier + d_shift < dec->buf + dec->len);
+ for(; to <= barier; to++)
+ *to= *(to + d_shift);
+ for(barier+= d_shift; to <= barier; to++)
+ *to= 0;
+ d_shift= -d_shift;
+ }
+ else
+ {
+ /* move right */
+ d_shift= (1 - new_front) / DIG_PER_DEC1;
+ to= dec->buf + ROUND_UP(end) - 1 + d_shift;
+ barier= dec->buf + ROUND_UP(beg + 1) - 1 + d_shift;
+ DBUG_ASSERT(to < dec->buf + dec->len);
+ DBUG_ASSERT(barier - d_shift >= dec->buf);
+ for(; to >= barier; to--)
+ *to= *(to - d_shift);
+ for(barier-= d_shift; to >= barier; to--)
+ *to= 0;
+ }
+ d_shift*= DIG_PER_DEC1;
+ beg+= d_shift;
+ end+= d_shift;
+ new_point+= d_shift;
+ }
+
+ /*
+ If there are gaps then fill ren with 0.
+
+ Only one of following 'for' loops will work becouse beg <= end
+ */
+ beg= ROUND_UP(beg + 1) - 1;
+ end= ROUND_UP(end) - 1;
+ DBUG_ASSERT(new_point >= 0);
+
+ /* We don't want negative new_point below */
+ if (new_point != 0)
+ new_point= ROUND_UP(new_point) - 1;
+
+ if (new_point > end)
+ {
+ do
+ {
+ dec->buf[new_point]=0;
+ } while (--new_point > end);
+ }
+ else
+ {
+ for (; new_point < beg; new_point++)
+ dec->buf[new_point]= 0;
+ }
+ dec->intg= digits_int;
+ dec->frac= digits_frac;
+ return err;
+}
+
+
+/*
+ Convert string to decimal
+
+ SYNOPSIS
+ internal_str2decl()
+ from - value to convert. Doesn't have to be \0 terminated!
+ to - decimal where where the result will be stored
+ to->buf and to->len must be set.
+ end - Pointer to pointer to end of string. Will on return be
+ set to the char after the last used character
+ fixed - use to->intg, to->frac as limits for input number
+
+ NOTE
+ to->intg and to->frac can be modified even when fixed=1
+ (but only decreased, in this case)
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
+ In case of E_DEC_FATAL_ERROR *to is set to decimal zero
+ (to make error handling easier)
+*/
+
+int
+internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed)
+{
+ const char *s= from, *s1, *endp, *end_of_string= *end;
+ int i, intg, frac, error, intg1, frac1;
+ dec1 x,*buf;
+ sanity(to);
+
+ error= E_DEC_BAD_NUM; /* In case of bad number */
+ while (s < end_of_string && my_isspace(&my_charset_latin1, *s))
+ s++;
+ if (s == end_of_string)
+ goto fatal_error;
+
+ if ((to->sign= (*s == '-')))
+ s++;
+ else if (*s == '+')
+ s++;
+
+ s1=s;
+ while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
+ s++;
+ intg= (int) (s-s1);
+ if (s < end_of_string && *s=='.')
+ {
+ endp= s+1;
+ while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp))
+ endp++;
+ frac= (int) (endp - s - 1);
+ }
+ else
+ {
+ frac= 0;
+ endp= s;
+ }
+
+ *end= (char*) endp;
+
+ if (frac+intg == 0)
+ goto fatal_error;
+
+ error= 0;
+ if (fixed)
+ {
+ if (frac > to->frac)
+ {
+ error=E_DEC_TRUNCATED;
+ frac=to->frac;
+ }
+ if (intg > to->intg)
+ {
+ error=E_DEC_OVERFLOW;
+ intg=to->intg;
+ }
+ intg1=ROUND_UP(intg);
+ frac1=ROUND_UP(frac);
+ if (intg1+frac1 > to->len)
+ {
+ error= E_DEC_OOM;
+ goto fatal_error;
+ }
+ }
+ else
+ {
+ intg1=ROUND_UP(intg);
+ frac1=ROUND_UP(frac);
+ FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
+ if (unlikely(error))
+ {
+ frac=frac1*DIG_PER_DEC1;
+ if (error == E_DEC_OVERFLOW)
+ intg=intg1*DIG_PER_DEC1;
+ }
+ }
+ /* Error is guranteed to be set here */
+ to->intg=intg;
+ to->frac=frac;
+
+ buf=to->buf+intg1;
+ s1=s;
+
+ for (x=0, i=0; intg; intg--)
+ {
+ x+= (*--s - '0')*powers10[i];
+
+ if (unlikely(++i == DIG_PER_DEC1))
+ {
+ *--buf=x;
+ x=0;
+ i=0;
+ }
+ }
+ if (i)
+ *--buf=x;
+
+ buf=to->buf+intg1;
+ for (x=0, i=0; frac; frac--)
+ {
+ x= (*++s1 - '0') + x*10;
+
+ if (unlikely(++i == DIG_PER_DEC1))
+ {
+ *buf++=x;
+ x=0;
+ i=0;
+ }
+ }
+ if (i)
+ *buf=x*powers10[DIG_PER_DEC1-i];
+
+ /* Handle exponent */
+ if (endp+1 < end_of_string && (*endp == 'e' || *endp == 'E'))
+ {
+ int str_error;
+ longlong exp= my_strtoll10(endp+1, (char**) &end_of_string, &str_error);
+
+ if (end_of_string != endp +1) /* If at least one digit */
+ {
+ *end= (char*) end_of_string;
+ if (str_error > 0)
+ {
+ error= E_DEC_BAD_NUM;
+ goto fatal_error;
+ }
+ if (exp > INT_MAX/2 || (str_error == 0 && exp < 0))
+ {
+ error= E_DEC_OVERFLOW;
+ goto fatal_error;
+ }
+ if (exp < INT_MIN/2 && error != E_DEC_OVERFLOW)
+ {
+ error= E_DEC_TRUNCATED;
+ goto fatal_error;
+ }
+ if (error != E_DEC_OVERFLOW)
+ error= decimal_shift(to, (int) exp);
+ }
+ }
+ return error;
+
+fatal_error:
+ decimal_make_zero(to);
+ return error;
+}
+
+
+/*
+ Convert decimal to double
+
+ SYNOPSIS
+ decimal2double()
+ from - value to convert
+ to - result will be stored there
+
+ RETURN VALUE
+ E_DEC_OK
+*/
+
+int decimal2double(decimal_t *from, double *to)
+{
+ double x=0, t=DIG_BASE;
+ int intg, frac;
+ dec1 *buf=from->buf;
+
+ for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
+ x=x*DIG_BASE + *buf++;
+ for (frac=from->frac; frac > 0; frac-=DIG_PER_DEC1, t*=DIG_BASE)
+ x+=*buf++/t;
+ *to=from->sign ? -x : x;
+ return E_DEC_OK;
+}
+
+/*
+ Convert double to decimal
+
+ SYNOPSIS
+ double2decimal()
+ from - value to convert
+ to - result will be stored there
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_OVERFLOW/E_DEC_TRUNCATED
+*/
+
+int double2decimal(double from, decimal_t *to)
+{
+ /* TODO: fix it, when we'll have dtoa */
+ char s[400], *end;
+ sprintf(s, "%f", from);
+ end= strend(s);
+ return string2decimal(s, to, &end);
+}
+
+static int ull2dec(ulonglong from, decimal_t *to)
+{
+ int intg1, error=E_DEC_OK;
+ ulonglong x=from;
+ dec1 *buf;
+
+ sanity(to);
+
+ for (intg1=1; from >= DIG_BASE; intg1++, from/=DIG_BASE);
+ if (unlikely(intg1 > to->len))
+ {
+ intg1=to->len;
+ error=E_DEC_OVERFLOW;
+ }
+ to->frac=0;
+ to->intg=intg1*DIG_PER_DEC1;
+
+ for (buf=to->buf+intg1; intg1; intg1--)
+ {
+ ulonglong y=x/DIG_BASE;
+ *--buf=(dec1)(x-y*DIG_BASE);
+ x=y;
+ }
+ return error;
+}
+
+int ulonglong2decimal(ulonglong from, decimal_t *to)
+{
+ to->sign=0;
+ return ull2dec(from, to);
+}
+
+int longlong2decimal(longlong from, decimal_t *to)
+{
+ if ((to->sign= from < 0))
+ return ull2dec(-from, to);
+ return ull2dec(from, to);
+}
+
+int decimal2ulonglong(decimal_t *from, ulonglong *to)
+{
+ dec1 *buf=from->buf;
+ ulonglong x=0;
+ int intg, frac;
+
+ if (from->sign)
+ {
+ *to=ULL(0);
+ return E_DEC_OVERFLOW;
+ }
+
+ for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
+ {
+ ulonglong y=x;
+ x=x*DIG_BASE + *buf++;
+ if (unlikely(y > (ULONGLONG_MAX/DIG_BASE) || x < y))
+ {
+ *to=y;
+ return E_DEC_OVERFLOW;
+ }
+ }
+ *to=x;
+ for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
+ if (*buf++)
+ return E_DEC_TRUNCATED;
+ return E_DEC_OK;
+}
+
+int decimal2longlong(decimal_t *from, longlong *to)
+{
+ dec1 *buf=from->buf;
+ longlong x=0;
+ int intg, frac;
+
+ for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
+ {
+ longlong y=x;
+ /*
+ Attention: trick!
+ we're calculating -|from| instead of |from| here
+ because |LONGLONG_MIN| > LONGLONG_MAX
+ so we can convert -9223372036854775808 correctly
+ */
+ x=x*DIG_BASE - *buf++;
+ if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
+ {
+ *to= from->sign ? y : -y;
+ return E_DEC_OVERFLOW;
+ }
+ }
+ /* boundary case: 9223372036854775808 */
+ if (unlikely(from->sign==0 && x < 0 && -x < 0))
+ {
+ *to= -1-x;
+ return E_DEC_OVERFLOW;
+ }
+
+ *to=from->sign ? x : -x;
+ for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
+ if (*buf++)
+ return E_DEC_TRUNCATED;
+ return E_DEC_OK;
+}
+
+/*
+ Convert decimal to its binary fixed-length representation
+ two representations of the same length can be compared with memcmp
+ with the correct -1/0/+1 result
+
+ SYNOPSIS
+ decimal2bin()
+ from - value to convert
+ to - points to buffer where string representation should be stored
+ precision/scale - see decimal_bin_size() below
+
+ NOTE
+ the buffer is assumed to be of the size decimal_bin_size(precision, scale)
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
+
+ DESCRIPTION
+ for storage decimal numbers are converted to the "binary" format.
+
+ This format has the following properties:
+ 1. length of the binary representation depends on the {precision, scale}
+ as provided by the caller and NOT on the intg/frac of the decimal to
+ convert.
+ 2. binary representations of the same {precision, scale} can be compared
+ with memcmp - with the same result as decimal_cmp() of the original
+ decimals (not taking into account possible precision loss during
+ conversion).
+
+ This binary format is as follows:
+ 1. First the number is converted to have a requested precision and scale.
+ 2. Every full DIG_PER_DEC1 digits of intg part are stored in 4 bytes
+ as is
+ 3. The first intg % DIG_PER_DEC1 digits are stored in the reduced
+ number of bytes (enough bytes to store this number of digits -
+ see dig2bytes)
+ 4. same for frac - full decimal_digit_t's are stored as is,
+ the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes.
+ 5. If the number is negative - every byte is inversed.
+ 5. The very first bit of the resulting byte array is inverted (because
+ memcmp compares unsigned bytes, see property 2 above)
+
+ Example:
+
+ 1234567890.1234
+
+ internally is represented as 3 decimal_digit_t's
+
+ 1 234567890 123400000
+
+ (assuming we want a binary representation with precision=14, scale=4)
+ in hex it's
+
+ 00-00-00-01 0D-FB-38-D2 07-5A-EF-40
+
+ now, middle decimal_digit_t is full - it stores 9 decimal digits. It goes
+ into binary representation as is:
+
+
+ ........... 0D-FB-38-D2 ............
+
+ First decimal_digit_t has only one decimal digit. We can store one digit in
+ one byte, no need to waste four:
+
+ 01 0D-FB-38-D2 ............
+
+ now, last digit. It's 123400000. We can store 1234 in two bytes:
+
+ 01 0D-FB-38-D2 04-D2
+
+ So, we've packed 12 bytes number in 7 bytes.
+ And now we invert the highest bit to get the final result:
+
+ 81 0D FB 38 D2 04 D2
+
+ And for -1234567890.1234 it would be
+
+ 7E F2 04 37 2D FB 2D
+*/
+int decimal2bin(decimal_t *from, char *to, int precision, int frac)
+{
+ dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
+ int error=E_DEC_OK, intg=precision-frac,
+ isize1, intg1, intg1x, from_intg,
+ intg0=intg/DIG_PER_DEC1,
+ frac0=frac/DIG_PER_DEC1,
+ intg0x=intg-intg0*DIG_PER_DEC1,
+ frac0x=frac-frac0*DIG_PER_DEC1,
+ frac1=from->frac/DIG_PER_DEC1,
+ frac1x=from->frac-frac1*DIG_PER_DEC1,
+ isize0=intg0*sizeof(dec1)+dig2bytes[intg0x],
+ fsize0=frac0*sizeof(dec1)+dig2bytes[frac0x],
+ fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
+ const int orig_isize0= isize0;
+ const int orig_fsize0= fsize0;
+ char *orig_to= to;
+
+ buf1= remove_leading_zeroes(from, &from_intg);
+
+ if (unlikely(from_intg+fsize1==0))
+ {
+ mask=0; /* just in case */
+ intg=1;
+ buf1=&mask;
+ }
+
+ intg1=from_intg/DIG_PER_DEC1;
+ intg1x=from_intg-intg1*DIG_PER_DEC1;
+ isize1=intg1*sizeof(dec1)+dig2bytes[intg1x];
+
+ if (intg < from_intg)
+ {
+ buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);
+ intg1=intg0; intg1x=intg0x;
+ error=E_DEC_OVERFLOW;
+ }
+ else if (isize0 > isize1)
+ {
+ while (isize0-- > isize1)
+ *to++= (char)mask;
+ }
+ if (fsize0 < fsize1)
+ {
+ frac1=frac0; frac1x=frac0x;
+ error=E_DEC_TRUNCATED;
+ }
+ else if (fsize0 > fsize1 && frac1x)
+ {
+ if (frac0 == frac1)
+ {
+ frac1x=frac0x;
+ fsize0= fsize1;
+ }
+ else
+ {
+ frac1++;
+ frac1x=0;
+ }
+ }
+
+ /* intg1x part */
+ if (intg1x)
+ {
+ int i=dig2bytes[intg1x];
+ dec1 x=(*buf1++ % powers10[intg1x]) ^ mask;
+ switch (i)
+ {
+ case 1: mi_int1store(to, x); break;
+ case 2: mi_int2store(to, x); break;
+ case 3: mi_int3store(to, x); break;
+ case 4: mi_int4store(to, x); break;
+ default: DBUG_ASSERT(0);
+ }
+ to+=i;
+ }
+
+ /* intg1+frac1 part */
+ for (stop1=buf1+intg1+frac1; buf1 < stop1; to+=sizeof(dec1))
+ {
+ dec1 x=*buf1++ ^ mask;
+ DBUG_ASSERT(sizeof(dec1) == 4);
+ mi_int4store(to, x);
+ }
+
+ /* frac1x part */
+ if (frac1x)
+ {
+ dec1 x;
+ int i=dig2bytes[frac1x],
+ lim=(frac1 < frac0 ? DIG_PER_DEC1 : frac0x);
+ while (frac1x < lim && dig2bytes[frac1x] == i)
+ frac1x++;
+ x=(*buf1 / powers10[DIG_PER_DEC1 - frac1x]) ^ mask;
+ switch (i)
+ {
+ case 1: mi_int1store(to, x); break;
+ case 2: mi_int2store(to, x); break;
+ case 3: mi_int3store(to, x); break;
+ case 4: mi_int4store(to, x); break;
+ default: DBUG_ASSERT(0);
+ }
+ to+=i;
+ }
+ if (fsize0 > fsize1)
+ {
+ char *to_end= orig_to + orig_fsize0 + orig_isize0;
+
+ while (fsize0-- > fsize1 && to < to_end)
+ *to++=(uchar)mask;
+ }
+ orig_to[0]^= 0x80;
+
+ /* Check that we have written the whole decimal and nothing more */
+ DBUG_ASSERT(to == orig_to + orig_fsize0 + orig_isize0);
+ return error;
+}
+
+/*
+ Restores decimal from its binary fixed-length representation
+
+ SYNOPSIS
+ bin2decimal()
+ from - value to convert
+ to - result
+ precision/scale - see decimal_bin_size() below
+
+ NOTE
+ see decimal2bin()
+ the buffer is assumed to be of the size decimal_bin_size(precision, scale)
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
+*/
+
+int bin2decimal(char *from, decimal_t *to, int precision, int scale)
+{
+ int error=E_DEC_OK, intg=precision-scale,
+ intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
+ intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1,
+ intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0);
+ dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1;
+ char *stop;
+ char *d_copy;
+ int bin_size= decimal_bin_size(precision, scale);
+
+ sanity(to);
+ d_copy= (char *)my_alloca(bin_size);
+ memcpy(d_copy, from, bin_size);
+ d_copy[0]^= 0x80;
+ from= d_copy;
+
+ FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
+ if (unlikely(error))
+ {
+ if (intg1 < intg0+(intg0x>0))
+ {
+ from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1);
+ frac0=frac0x=intg0x=0;
+ intg0=intg1;
+ }
+ else
+ {
+ frac0x=0;
+ frac0=frac1;
+ }
+ }
+
+ to->sign=(mask != 0);
+ to->intg=intg0*DIG_PER_DEC1+intg0x;
+ to->frac=frac0*DIG_PER_DEC1+frac0x;
+
+ if (intg0x)
+ {
+ int i=dig2bytes[intg0x];
+ dec1 x;
+ switch (i)
+ {
+ case 1: x=mi_sint1korr(from); break;
+ case 2: x=mi_sint2korr(from); break;
+ case 3: x=mi_sint3korr(from); break;
+ case 4: x=mi_sint4korr(from); break;
+ default: DBUG_ASSERT(0);
+ }
+ from+=i;
+ *buf=x ^ mask;
+ if (buf > to->buf || *buf != 0)
+ buf++;
+ else
+ to->intg-=intg0x;
+ }
+ for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
+ {
+ DBUG_ASSERT(sizeof(dec1) == 4);
+ *buf=mi_sint4korr(from) ^ mask;
+ if (buf > to->buf || *buf != 0)
+ buf++;
+ else
+ to->intg-=DIG_PER_DEC1;
+ }
+ DBUG_ASSERT(to->intg >=0);
+ for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
+ {
+ DBUG_ASSERT(sizeof(dec1) == 4);
+ *buf=mi_sint4korr(from) ^ mask;
+ buf++;
+ }
+ if (frac0x)
+ {
+ int i=dig2bytes[frac0x];
+ dec1 x;
+ switch (i)
+ {
+ case 1: x=mi_sint1korr(from); break;
+ case 2: x=mi_sint2korr(from); break;
+ case 3: x=mi_sint3korr(from); break;
+ case 4: x=mi_sint4korr(from); break;
+ default: DBUG_ASSERT(0);
+ }
+ *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
+ buf++;
+ }
+ my_afree(d_copy);
+ return error;
+}
+
+/*
+ Returns the size of array to hold a decimal with given precision and scale
+
+ RETURN VALUE
+ size in dec1
+ (multiply by sizeof(dec1) to get the size if bytes)
+*/
+
+int decimal_size(int precision, int scale)
+{
+ DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
+ return ROUND_UP(precision-scale)+ROUND_UP(scale);
+}
+
+/*
+ Returns the size of array to hold a binary representation of a decimal
+
+ RETURN VALUE
+ size in bytes
+*/
+
+int decimal_bin_size(int precision, int scale)
+{
+ int intg=precision-scale,
+ intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
+ intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
+
+ DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
+ return intg0*sizeof(dec1)+dig2bytes[intg0x]+
+ frac0*sizeof(dec1)+dig2bytes[frac0x];
+}
+
+/*
+ Rounds the decimal to "scale" digits
+
+ SYNOPSIS
+ decimal_round()
+ from - decimal to round,
+ to - result buffer. from==to is allowed
+ scale - to what position to round. can be negative!
+ mode - round to nearest even or truncate
+
+ NOTES
+ scale can be negative !
+ one TRUNCATED error (line XXX below) isn't treated very logical :(
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED
+*/
+
+int
+decimal_round(decimal_t *from, decimal_t *to, int scale,
+ decimal_round_mode mode)
+{
+ int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
+ frac1=ROUND_UP(from->frac), round_digit,
+ intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
+ intg1=ROUND_UP(from->intg +
+ (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX)));
+ dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0;
+ int first_dig;
+
+ sanity(to);
+
+ switch (mode) {
+ case HALF_UP:
+ case HALF_EVEN: round_digit=5; break;
+ case CEILING: round_digit= from->sign ? 10 : 0; break;
+ case FLOOR: round_digit= from->sign ? 0 : 10; break;
+ case TRUNCATE: round_digit=10; break;
+ default: DBUG_ASSERT(0);
+ }
+
+ if (unlikely(frac0+intg0 > len))
+ {
+ frac0=len-intg0;
+ scale=frac0*DIG_PER_DEC1;
+ error=E_DEC_TRUNCATED;
+ }
+
+ if (scale+from->intg < 0)
+ {
+ decimal_make_zero(to);
+ return E_DEC_OK;
+ }
+
+ if (to != from || intg1>intg0)
+ {
+ dec1 *p0= buf0+intg0+max(frac1, frac0);
+ dec1 *p1= buf1+intg1+max(frac1, frac0);
+
+ to->buf[0]= 0;
+ while (buf0 < p0)
+ *(--p1) = *(--p0);
+
+ intg0= intg1;
+ buf0=to->buf;
+ buf1=to->buf;
+ to->sign=from->sign;
+ to->intg=min(intg0, len)*DIG_PER_DEC1;
+ }
+
+ if (frac0 > frac1)
+ {
+ buf1+=intg0+frac1;
+ while (frac0-- > frac1)
+ *buf1++=0;
+ goto done;
+ }
+
+ if (scale >= from->frac)
+ goto done; /* nothing to do */
+
+ buf0+=intg0+frac0-1;
+ buf1+=intg0+frac0-1;
+ if (scale == frac0*DIG_PER_DEC1)
+ {
+ int do_inc= FALSE;
+ DBUG_ASSERT(frac0+intg0 >= 0);
+ switch (round_digit) {
+ case 0:
+ {
+ dec1 *p0= buf0 + (frac1-frac0);
+ for (; p0 > buf0; p0--)
+ {
+ if (*p0)
+ {
+ do_inc= TRUE;
+ break;
+ }
+ }
+ break;
+ }
+ case 5:
+ {
+ x= buf0[1]/DIG_MASK;
+ do_inc= (x>5) || ((x == 5) &&
+ (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1)));
+ break;
+ }
+ default:
+ break;
+ }
+ if (do_inc)
+ {
+ if (frac0+intg0>0)
+ (*buf1)++;
+ else
+ *(++buf1)=DIG_BASE;
+ }
+ else if (frac0+intg0==0)
+ {
+ decimal_make_zero(to);
+ return E_DEC_OK;
+ }
+ }
+ else
+ {
+ /* TODO - fix this code as it won't work for CEILING mode */
+ int pos=frac0*DIG_PER_DEC1-scale-1;
+ DBUG_ASSERT(frac0+intg0 > 0);
+ x=*buf1 / powers10[pos];
+ y=x % 10;
+ if (y > round_digit ||
+ (round_digit == 5 && y == 5 && (mode == HALF_UP || (x/10) & 1)))
+ x+=10;
+ *buf1=powers10[pos]*(x-y);
+ }
+ if (frac0 < 0)
+ {
+ dec1 *end=to->buf+intg0, *buf=buf1+1;
+ while (buf < end)
+ *buf++=0;
+ }
+ if (*buf1 >= DIG_BASE)
+ {
+ carry=1;
+ *buf1-=DIG_BASE;
+ while (carry && --buf1 >= to->buf)
+ ADD(*buf1, *buf1, 0, carry);
+ if (unlikely(carry))
+ {
+ /* shifting the number to create space for new digit */
+ if (frac0+intg0 >= len)
+ {
+ frac0--;
+ scale=frac0*DIG_PER_DEC1;
+ error=E_DEC_TRUNCATED; /* XXX */
+ }
+ for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--)
+ {
+ buf1[0]=buf1[-1];
+ }
+ *buf1=1;
+ to->intg++;
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ if (likely(*buf1))
+ break;
+ if (buf1-- == to->buf)
+ {
+ /* making 'zero' with the proper scale */
+ dec1 *p0= to->buf + frac0 + 1;
+ to->intg=1;
+ to->frac= max(scale, 0);
+ to->sign= 0;
+ for (buf1= to->buf; buf1<p0; buf1++)
+ *buf1= 0;
+ return E_DEC_OK;
+ }
+ }
+ }
+
+ /* Here we check 999.9 -> 1000 case when we need to increase intg */
+ first_dig= to->intg % DIG_PER_DEC1;
+ if (first_dig && (*buf1 >= powers10[first_dig]))
+ to->intg++;
+
+ if (scale<0)
+ scale=0;
+
+done:
+ to->frac=scale;
+ return error;
+}
+
+/*
+ Returns the size of the result of the operation
+
+ SYNOPSIS
+ decimal_result_size()
+ from1 - operand of the unary operation or first operand of the
+ binary operation
+ from2 - second operand of the binary operation
+ op - operation. one char '+', '-', '*', '/' are allowed
+ others may be added later
+ param - extra param to the operation. unused for '+', '-', '*'
+ scale increment for '/'
+
+ NOTE
+ returned valued may be larger than the actual buffer requred
+ in the operation, as decimal_result_size, by design, operates on
+ precision/scale values only and not on the actual decimal number
+
+ RETURN VALUE
+ size of to->buf array in dec1 elements. to get size in bytes
+ multiply by sizeof(dec1)
+*/
+
+int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param)
+{
+ switch (op) {
+ case '-':
+ return ROUND_UP(max(from1->intg, from2->intg)) +
+ ROUND_UP(max(from1->frac, from2->frac));
+ case '+':
+ return ROUND_UP(max(from1->intg, from2->intg)+1) +
+ ROUND_UP(max(from1->frac, from2->frac));
+ case '*':
+ return ROUND_UP(from1->intg+from2->intg)+
+ ROUND_UP(from1->frac)+ROUND_UP(from2->frac);
+ case '/':
+ return ROUND_UP(from1->intg+from2->intg+1+from1->frac+from2->frac+param);
+ default: DBUG_ASSERT(0);
+ }
+ return -1; /* shut up the warning */
+}
+
+static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
+{
+ int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
+ frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
+ frac0=max(frac1, frac2), intg0=max(intg1, intg2), error;
+ dec1 *buf1, *buf2, *buf0, *stop, *stop2, x, carry;
+
+ sanity(to);
+
+ /* is there a need for extra word because of carry ? */
+ x=intg1 > intg2 ? from1->buf[0] :
+ intg2 > intg1 ? from2->buf[0] :
+ from1->buf[0] + from2->buf[0] ;
+ if (unlikely(x > DIG_MAX-1)) /* yes, there is */
+ {
+ intg0++;
+ to->buf[0]=0; /* safety */
+ }
+
+ FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
+ if (unlikely(error == E_DEC_OVERFLOW))
+ {
+ max_decimal(to->len * DIG_PER_DEC1, 0, to);
+ return error;
+ }
+
+ buf0=to->buf+intg0+frac0;
+
+ to->sign=from1->sign;
+ to->frac=max(from1->frac, from2->frac);
+ to->intg=intg0*DIG_PER_DEC1;
+ if (unlikely(error))
+ {
+ set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
+ set_if_smaller(frac1, frac0);
+ set_if_smaller(frac2, frac0);
+ set_if_smaller(intg1, intg0);
+ set_if_smaller(intg2, intg0);
+ }
+
+ /* part 1 - max(frac) ... min (frac) */
+ if (frac1 > frac2)
+ {
+ buf1=from1->buf+intg1+frac1;
+ stop=from1->buf+intg1+frac2;
+ buf2=from2->buf+intg2+frac2;
+ stop2=from1->buf+(intg1 > intg2 ? intg1-intg2 : 0);
+ }
+ else
+ {
+ buf1=from2->buf+intg2+frac2;
+ stop=from2->buf+intg2+frac1;
+ buf2=from1->buf+intg1+frac1;
+ stop2=from2->buf+(intg2 > intg1 ? intg2-intg1 : 0);
+ }
+ while (buf1 > stop)
+ *--buf0=*--buf1;
+
+ /* part 2 - min(frac) ... min(intg) */
+ carry=0;
+ while (buf1 > stop2)
+ {
+ ADD(*--buf0, *--buf1, *--buf2, carry);
+ }
+
+ /* part 3 - min(intg) ... max(intg) */
+ buf1= intg1 > intg2 ? ((stop=from1->buf)+intg1-intg2) :
+ ((stop=from2->buf)+intg2-intg1) ;
+ while (buf1 > stop)
+ {
+ ADD(*--buf0, *--buf1, 0, carry);
+ }
+
+ if (unlikely(carry))
+ *--buf0=1;
+ DBUG_ASSERT(buf0 == to->buf || buf0 == to->buf+1);
+
+ return error;
+}
+
+/* to=from1-from2.
+ if to==0, return -1/0/+1 - the result of the comparison */
+static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
+{
+ int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
+ frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac);
+ int frac0=max(frac1, frac2), error;
+ dec1 *buf1, *buf2, *buf0, *stop1, *stop2, *start1, *start2, carry=0;
+
+ /* let carry:=1 if from2 > from1 */
+ start1=buf1=from1->buf; stop1=buf1+intg1;
+ start2=buf2=from2->buf; stop2=buf2+intg2;
+ if (unlikely(*buf1 == 0))
+ {
+ while (buf1 < stop1 && *buf1 == 0)
+ buf1++;
+ start1=buf1;
+ intg1= (int) (stop1-buf1);
+ }
+ if (unlikely(*buf2 == 0))
+ {
+ while (buf2 < stop2 && *buf2 == 0)
+ buf2++;
+ start2=buf2;
+ intg2= (int) (stop2-buf2);
+ }
+ if (intg2 > intg1)
+ carry=1;
+ else if (intg2 == intg1)
+ {
+ dec1 *end1= stop1 + (frac1 - 1);
+ dec1 *end2= stop2 + (frac2 - 1);
+ while (unlikely((buf1 <= end1) && (*end1 == 0)))
+ end1--;
+ while (unlikely((buf2 <= end2) && (*end2 == 0)))
+ end2--;
+ frac1= (int) (end1 - stop1) + 1;
+ frac2= (int) (end2 - stop2) + 1;
+ while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
+ buf1++, buf2++;
+ if (buf1 <= end1)
+ {
+ if (buf2 <= end2)
+ carry= *buf2 > *buf1;
+ else
+ carry= 0;
+ }
+ else
+ {
+ if (buf2 <= end2)
+ carry=1;
+ else /* short-circuit everything: from1 == from2 */
+ {
+ if (to == 0) /* decimal_cmp() */
+ return 0;
+ decimal_make_zero(to);
+ return E_DEC_OK;
+ }
+ }
+ }
+
+ if (to == 0) /* decimal_cmp() */
+ return carry == from1->sign ? 1 : -1;
+
+ sanity(to);
+
+ to->sign=from1->sign;
+
+ /* ensure that always from1 > from2 (and intg1 >= intg2) */
+ if (carry)
+ {
+ swap_variables(decimal_t *,from1,from1);
+ swap_variables(dec1 *,start1, start2);
+ swap_variables(int,intg1,intg2);
+ swap_variables(int,frac1,frac2);
+ to->sign= 1 - to->sign;
+ }
+
+ FIX_INTG_FRAC_ERROR(to->len, intg1, frac0, error);
+ buf0=to->buf+intg1+frac0;
+
+ to->frac=max(from1->frac, from2->frac);
+ to->intg=intg1*DIG_PER_DEC1;
+ if (unlikely(error))
+ {
+ set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
+ set_if_smaller(frac1, frac0);
+ set_if_smaller(frac2, frac0);
+ set_if_smaller(intg2, intg1);
+ }
+ carry=0;
+
+ /* part 1 - max(frac) ... min (frac) */
+ if (frac1 > frac2)
+ {
+ buf1=start1+intg1+frac1;
+ stop1=start1+intg1+frac2;
+ buf2=start2+intg2+frac2;
+ while (frac0-- > frac1)
+ *--buf0=0;
+ while (buf1 > stop1)
+ *--buf0=*--buf1;
+ }
+ else
+ {
+ buf1=start1+intg1+frac1;
+ buf2=start2+intg2+frac2;
+ stop2=start2+intg2+frac1;
+ while (frac0-- > frac2)
+ *--buf0=0;
+ while (buf2 > stop2)
+ {
+ SUB(*--buf0, 0, *--buf2, carry);
+ }
+ }
+
+ /* part 2 - min(frac) ... intg2 */
+ while (buf2 > start2)
+ {
+ SUB(*--buf0, *--buf1, *--buf2, carry);
+ }
+
+ /* part 3 - intg2 ... intg1 */
+ while (carry && buf1 > start1)
+ {
+ SUB(*--buf0, *--buf1, 0, carry);
+ }
+
+ while (buf1 > start1)
+ *--buf0=*--buf1;
+
+ while (buf0 > to->buf)
+ *--buf0=0;
+
+ return error;
+}
+
+int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
+{
+ if (likely(from1->sign == from2->sign))
+ return do_add(from1, from2, to);
+ return do_sub(from1, from2, to);
+}
+
+int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
+{
+ if (likely(from1->sign == from2->sign))
+ return do_sub(from1, from2, to);
+ return do_add(from1, from2, to);
+}
+
+int decimal_cmp(decimal_t *from1, decimal_t *from2)
+{
+ if (likely(from1->sign == from2->sign))
+ return do_sub(from1, from2, 0);
+ return from1->sign > from2->sign ? -1 : 1;
+}
+
+int decimal_is_zero(decimal_t *from)
+{
+ dec1 *buf1=from->buf,
+ *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
+ while (buf1 < end)
+ if (*buf1++)
+ return 0;
+ return 1;
+}
+
+/*
+ multiply two decimals
+
+ SYNOPSIS
+ decimal_mul()
+ from1, from2 - factors
+ to - product
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW;
+
+ NOTES
+ in this implementation, with sizeof(dec1)=4 we have DIG_PER_DEC1=9,
+ and 63-digit number will take only 7 dec1 words (basically a 7-digit
+ "base 999999999" number). Thus there's no need in fast multiplication
+ algorithms, 7-digit numbers can be multiplied with a naive O(n*n)
+ method.
+
+ XXX if this library is to be used with huge numbers of thousands of
+ digits, fast multiplication must be implemented.
+*/
+int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
+{
+ int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
+ frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
+ intg0=ROUND_UP(from1->intg+from2->intg),
+ frac0=frac1+frac2, error, i, j, d_to_move;
+ dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
+ *start2, *stop2, *stop1, *start0, carry;
+
+ sanity(to);
+
+ i=intg0;
+ j=frac0;
+ FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
+ to->sign=from1->sign != from2->sign;
+ to->frac=from1->frac+from2->frac;
+ to->intg=intg0*DIG_PER_DEC1;
+
+ if (unlikely(error))
+ {
+ set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
+ set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
+ if (unlikely(i > intg0))
+ {
+ i-=intg0;
+ j=i >> 1;
+ intg1-= j;
+ intg2-=i-j;
+ frac1=frac2=0; /* frac0 is already 0 here */
+ }
+ else
+ {
+ j-=frac0;
+ i=j >> 1;
+ frac1-= i;
+ frac2-=j-i;
+ }
+ }
+ start0=to->buf+intg0+frac0-1;
+ start2=buf2+frac2-1;
+ stop1=buf1-intg1;
+ stop2=buf2-intg2;
+
+ bzero(to->buf, (intg0+frac0)*sizeof(dec1));
+
+ for (buf1+=frac1-1; buf1 >= stop1; buf1--, start0--)
+ {
+ carry=0;
+ for (buf0=start0, buf2=start2; buf2 >= stop2; buf2--, buf0--)
+ {
+ dec1 hi, lo;
+ dec2 p= ((dec2)*buf1) * ((dec2)*buf2);
+ hi=(dec1)(p/DIG_BASE);
+ lo=(dec1)(p-((dec2)hi)*DIG_BASE);
+ ADD2(*buf0, *buf0, lo, carry);
+ carry+=hi;
+ }
+ for (; carry; buf0--)
+ ADD(*buf0, *buf0, 0, carry);
+ }
+
+ /* Now we have to check for -0.000 case */
+ if (to->sign)
+ {
+ dec1 *buf= to->buf;
+ dec1 *end= to->buf + intg0 + frac0;
+ DBUG_ASSERT(buf != end);
+ for (;;)
+ {
+ if (*buf)
+ break;
+ if (++buf == end)
+ {
+ /* We got decimal zero */
+ decimal_make_zero(to);
+ break;
+ }
+ }
+ }
+ buf1= to->buf;
+ d_to_move= intg0 + ROUND_UP(to->frac);
+ while (!*buf1 && (to->intg > DIG_PER_DEC1))
+ {
+ buf1++;
+ to->intg-= DIG_PER_DEC1;
+ d_to_move--;
+ }
+ if (to->buf < buf1)
+ {
+ dec1 *cur_d= to->buf;
+ for (; d_to_move; d_to_move--, cur_d++, buf1++)
+ *cur_d= *buf1;
+ }
+ return error;
+}
+
+/*
+ naive division algorithm (Knuth's Algorithm D in 4.3.1) -
+ it's ok for short numbers
+ also we're using alloca() to allocate a temporary buffer
+
+ XXX if this library is to be used with huge numbers of thousands of
+ digits, fast division must be implemented and alloca should be
+ changed to malloc (or at least fallback to malloc if alloca() fails)
+ but then, decimal_mul() should be rewritten too :(
+*/
+static int do_div_mod(decimal_t *from1, decimal_t *from2,
+ decimal_t *to, decimal_t *mod, int scale_incr)
+{
+ int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
+ frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
+ error, i, intg0, frac0, len1, len2, dintg, div=(!mod);
+ dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
+ *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry;
+ dec2 norm_factor, x, guess, y;
+
+ LINT_INIT(error);
+
+ if (mod)
+ to=mod;
+
+ sanity(to);
+
+ /* removing all the leading zeroes */
+ i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
+ while (prec2 > 0 && *buf2 == 0)
+ {
+ prec2-= i;
+ i= DIG_PER_DEC1;
+ buf2++;
+ }
+ if (prec2 <= 0) /* short-circuit everything: from2 == 0 */
+ return E_DEC_DIV_ZERO;
+ for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
+ DBUG_ASSERT(prec2 > 0);
+
+ i=((prec1-1) % DIG_PER_DEC1)+1;
+ while (prec1 > 0 && *buf1 == 0)
+ {
+ prec1-=i;
+ i=DIG_PER_DEC1;
+ buf1++;
+ }
+ if (prec1 <= 0)
+ { /* short-circuit everything: from1 == 0 */
+ decimal_make_zero(to);
+ return E_DEC_OK;
+ }
+ for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
+ DBUG_ASSERT(prec1 > 0);
+
+ /* let's fix scale_incr, taking into account frac1,frac2 increase */
+ if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
+ scale_incr=0;
+
+ dintg=(prec1-frac1)-(prec2-frac2)+(*buf1 >= *buf2);
+ if (dintg < 0)
+ {
+ dintg/=DIG_PER_DEC1;
+ intg0=0;
+ }
+ else
+ intg0=ROUND_UP(dintg);
+ if (mod)
+ {
+ /* we're calculating N1 % N2.
+ The result will have
+ frac=max(frac1, frac2), as for subtraction
+ intg=intg2
+ */
+ to->sign=from1->sign;
+ to->frac=max(from1->frac, from2->frac);
+ frac0=0;
+ }
+ else
+ {
+ /*
+ we're calculating N1/N2. N1 is in the buf1, has prec1 digits
+ N2 is in the buf2, has prec2 digits. Scales are frac1 and
+ frac2 accordingly.
+ Thus, the result will have
+ frac = ROUND_UP(frac1+frac2+scale_incr)
+ and
+ intg = (prec1-frac1) - (prec2-frac2) + 1
+ prec = intg+frac
+ */
+ frac0=ROUND_UP(frac1+frac2+scale_incr);
+ FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
+ to->sign=from1->sign != from2->sign;
+ to->intg=intg0*DIG_PER_DEC1;
+ to->frac=frac0*DIG_PER_DEC1;
+ }
+ buf0=to->buf;
+ stop0=buf0+intg0+frac0;
+ if (likely(div))
+ while (dintg++ < 0)
+ *buf0++=0;
+
+ len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1) + 1;
+ set_if_bigger(len1, 3);
+ if (!(tmp1=(dec1 *)my_alloca(len1*sizeof(dec1))))
+ return E_DEC_OOM;
+ memcpy(tmp1, buf1, i*sizeof(dec1));
+ bzero(tmp1+i, (len1-i)*sizeof(dec1));
+
+ start1=tmp1;
+ stop1=start1+len1;
+ start2=buf2;
+ stop2=buf2+ROUND_UP(prec2)-1;
+
+ /* removing end zeroes */
+ while (*stop2 == 0 && stop2 >= start2)
+ stop2--;
+ len2= (int) (stop2++ - start2);
+
+ /*
+ calculating norm2 (normalized *start2) - we need *start2 to be large
+ (at least > DIG_BASE/2), but unlike Knuth's Alg. D we don't want to
+ normalize input numbers (as we don't make a copy of the divisor).
+ Thus we normalize first dec1 of buf2 only, and we'll normalize *start1
+ on the fly for the purpose of guesstimation only.
+ It's also faster, as we're saving on normalization of buf2
+ */
+ norm_factor=DIG_BASE/(*start2+1);
+ norm2=(dec1)(norm_factor*start2[0]);
+ if (likely(len2>0))
+ norm2+=(dec1)(norm_factor*start2[1]/DIG_BASE);
+
+ if (*start1 < *start2)
+ dcarry=*start1++;
+ else
+ dcarry=0;
+
+ /* main loop */
+ for (; buf0 < stop0; buf0++)
+ {
+ /* short-circuit, if possible */
+ if (unlikely(dcarry == 0 && *start1 < *start2))
+ guess=0;
+ else
+ {
+ /* D3: make a guess */
+ x=start1[0]+((dec2)dcarry)*DIG_BASE;
+ y=start1[1];
+ guess=(norm_factor*x+norm_factor*y/DIG_BASE)/norm2;
+ if (unlikely(guess >= DIG_BASE))
+ guess=DIG_BASE-1;
+ if (likely(len2>0))
+ {
+ /* hmm, this is a suspicious trick - I removed normalization here */
+ if (start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y)
+ guess--;
+ if (unlikely(start2[1]*guess > (x-guess*start2[0])*DIG_BASE+y))
+ guess--;
+ DBUG_ASSERT(start2[1]*guess <= (x-guess*start2[0])*DIG_BASE+y);
+ }
+
+ /* D4: multiply and subtract */
+ buf2=stop2;
+ buf1=start1+len2;
+ DBUG_ASSERT(buf1 < stop1);
+ for (carry=0; buf2 > start2; buf1--)
+ {
+ dec1 hi, lo;
+ x=guess * (*--buf2);
+ hi=(dec1)(x/DIG_BASE);
+ lo=(dec1)(x-((dec2)hi)*DIG_BASE);
+ SUB2(*buf1, *buf1, lo, carry);
+ carry+=hi;
+ }
+ carry= dcarry < carry;
+
+ /* D5: check the remainder */
+ if (unlikely(carry))
+ {
+ /* D6: correct the guess */
+ guess--;
+ buf2=stop2;
+ buf1=start1+len2;
+ for (carry=0; buf2 > start2; buf1--)
+ {
+ ADD(*buf1, *buf1, *--buf2, carry);
+ }
+ }
+ }
+ if (likely(div))
+ *buf0=(dec1)guess;
+ dcarry= *start1;
+ start1++;
+ }
+ if (mod)
+ {
+ /*
+ now the result is in tmp1, it has
+ intg=prec1-frac1
+ frac=max(frac1, frac2)=to->frac
+ */
+ if (dcarry)
+ *--start1=dcarry;
+ buf0=to->buf;
+ intg0=(int) (ROUND_UP(prec1-frac1)-(start1-tmp1));
+ frac0=ROUND_UP(to->frac);
+ error=E_DEC_OK;
+ if (unlikely(frac0==0 && intg0==0))
+ {
+ decimal_make_zero(to);
+ goto done;
+ }
+ if (intg0<=0)
+ {
+ if (unlikely(-intg0 >= to->len))
+ {
+ decimal_make_zero(to);
+ error=E_DEC_TRUNCATED;
+ goto done;
+ }
+ stop1=start1+frac0;
+ frac0+=intg0;
+ to->intg=0;
+ while (intg0++ < 0)
+ *buf0++=0;
+ }
+ else
+ {
+ if (unlikely(intg0 > to->len))
+ {
+ frac0=0;
+ intg0=to->len;
+ error=E_DEC_OVERFLOW;
+ goto done;
+ }
+ DBUG_ASSERT(intg0 <= ROUND_UP(from2->intg));
+ stop1=start1+frac0+intg0;
+ to->intg=min(intg0*DIG_PER_DEC1, from2->intg);
+ }
+ if (unlikely(intg0+frac0 > to->len))
+ {
+ stop1-=to->len-frac0-intg0;
+ frac0=to->len-intg0;
+ to->frac=frac0*DIG_PER_DEC1;
+ error=E_DEC_TRUNCATED;
+ }
+ while (start1 < stop1)
+ *buf0++=*start1++;
+ }
+done:
+ my_afree(tmp1);
+ return error;
+}
+
+/*
+ division of two decimals
+
+ SYNOPSIS
+ decimal_div()
+ from1 - dividend
+ from2 - divisor
+ to - quotient
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
+
+ NOTES
+ see do_div_mod()
+*/
+
+int
+decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to, int scale_incr)
+{
+ return do_div_mod(from1, from2, to, 0, scale_incr);
+}
+
+/*
+ modulus
+
+ SYNOPSIS
+ decimal_mod()
+ from1 - dividend
+ from2 - divisor
+ to - modulus
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_DIV_ZERO;
+
+ NOTES
+ see do_div_mod()
+
+ DESCRIPTION
+ the modulus R in R = M mod N
+
+ is defined as
+
+ 0 <= |R| < |M|
+ sign R == sign M
+ R = M - k*N, where k is integer
+
+ thus, there's no requirement for M or N to be integers
+*/
+
+int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to)
+{
+ return do_div_mod(from1, from2, 0, to, 0);
+}
+
+#ifdef MAIN
+
+int full= 0;
+decimal_t a, b, c;
+char buf1[100], buf2[100], buf3[100];
+
+void dump_decimal(decimal_t *d)
+{
+ int i;
+ printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
+ for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
+ printf("%09d, ", d->buf[i]);
+ printf("%09d} */ ", d->buf[i]);
+}
+
+
+void check_result_code(int actual, int want)
+{
+ if (actual != want)
+ {
+ printf("\n^^^^^^^^^^^^^ must return %d\n", want);
+ exit(1);
+ }
+}
+
+
+void print_decimal(decimal_t *d, const char *orig, int actual, int want)
+{
+ char s[100];
+ int slen=sizeof(s);
+
+ if (full) dump_decimal(d);
+ decimal2string(d, s, &slen, 0, 0, 0);
+ printf("'%s'", s);
+ check_result_code(actual, want);
+ if (orig && strcmp(orig, s))
+ {
+ printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
+ exit(1);
+ }
+}
+
+void test_d2s()
+{
+ char s[100];
+ int slen, res;
+
+ /***********************************/
+ printf("==== decimal2string ====\n");
+ a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
+ slen=sizeof(s);
+ res=decimal2string(&a, s, &slen, 0, 0, 0);
+ dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
+
+ a.buf[1]=987000000; a.frac=3;
+ slen=sizeof(s);
+ res=decimal2string(&a, s, &slen, 0, 0, 0);
+ dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
+
+ a.sign=1;
+ slen=sizeof(s);
+ res=decimal2string(&a, s, &slen, 0, 0, 0);
+ dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
+
+ slen=8;
+ res=decimal2string(&a, s, &slen, 0, 0, 0);
+ dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
+
+ slen=5;
+ res=decimal2string(&a, s, &slen, 0, 0, 0);
+ dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
+
+ a.buf[0]=987000000; a.frac=3; a.intg=0;
+ slen=sizeof(s);
+ res=decimal2string(&a, s, &slen, 0, 0, 0);
+ dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
+}
+
+void test_s2d(const char *s, const char *orig, int ex)
+{
+ char s1[100], *end;
+ int res;
+ sprintf(s1, "'%s'", s);
+ end= strend(s);
+ printf("len=%2d %-30s => res=%d ", a.len, s1,
+ (res= string2decimal(s, &a, &end)));
+ print_decimal(&a, orig, res, ex);
+ printf("\n");
+}
+
+void test_d2f(const char *s, int ex)
+{
+ char s1[100], *end;
+ double x;
+ int res;
+
+ sprintf(s1, "'%s'", s);
+ end= strend(s);
+ string2decimal(s, &a, &end);
+ res=decimal2double(&a, &x);
+ if (full) dump_decimal(&a);
+ printf("%-40s => res=%d %.*g\n", s1, res, a.intg+a.frac, x);
+ check_result_code(res, ex);
+}
+
+void test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
+{
+ char s1[100], buf[100], *end;
+ int res, i, size=decimal_bin_size(p, s);
+
+ sprintf(s1, "'%s'", str);
+ end= strend(str);
+ string2decimal(str, &a, &end);
+ res=decimal2bin(&a, buf, p, s);
+ printf("%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
+ if (full)
+ {
+ printf("0x");
+ for (i=0; i < size; i++)
+ printf("%02x", ((uchar *)buf)[i]);
+ }
+ res=bin2decimal(buf, &a, p, s);
+ printf(" => res=%d ", res);
+ print_decimal(&a, orig, res, ex);
+ printf("\n");
+}
+
+void test_f2d(double from, int ex)
+{
+ int res;
+
+ res=double2decimal(from, &a);
+ printf("%-40.*f => res=%d ", DBL_DIG-2, from, res);
+ print_decimal(&a, 0, res, ex);
+ printf("\n");
+}
+
+void test_ull2d(ulonglong from, const char *orig, int ex)
+{
+ char s[100];
+ int res;
+
+ res=ulonglong2decimal(from, &a);
+ longlong10_to_str(from,s,10);
+ printf("%-40s => res=%d ", s, res);
+ print_decimal(&a, orig, res, ex);
+ printf("\n");
+}
+
+void test_ll2d(longlong from, const char *orig, int ex)
+{
+ char s[100];
+ int res;
+
+ res=longlong2decimal(from, &a);
+ longlong10_to_str(from,s,-10);
+ printf("%-40s => res=%d ", s, res);
+ print_decimal(&a, orig, res, ex);
+ printf("\n");
+}
+
+void test_d2ull(const char *s, const char *orig, int ex)
+{
+ char s1[100], *end;
+ ulonglong x;
+ int res;
+
+ end= strend(s);
+ string2decimal(s, &a, &end);
+ res=decimal2ulonglong(&a, &x);
+ if (full) dump_decimal(&a);
+ longlong10_to_str(x,s1,10);
+ printf("%-40s => res=%d %s\n", s, res, s1);
+ check_result_code(res, ex);
+ if (orig && strcmp(orig, s1))
+ {
+ printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
+ exit(1);
+ }
+}
+
+void test_d2ll(const char *s, const char *orig, int ex)
+{
+ char s1[100], *end;
+ longlong x;
+ int res;
+
+ end= strend(s);
+ string2decimal(s, &a, &end);
+ res=decimal2longlong(&a, &x);
+ if (full) dump_decimal(&a);
+ longlong10_to_str(x,s1,-10);
+ printf("%-40s => res=%d %s\n", s, res, s1);
+ check_result_code(res, ex);
+ if (orig && strcmp(orig, s1))
+ {
+ printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
+ exit(1);
+ }
+}
+
+void test_da(const char *s1, const char *s2, const char *orig, int ex)
+{
+ char s[100], *end;
+ int res;
+ sprintf(s, "'%s' + '%s'", s1, s2);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ end= strend(s2);
+ string2decimal(s2, &b, &end);
+ res=decimal_add(&a, &b, &c);
+ printf("%-40s => res=%d ", s, res);
+ print_decimal(&c, orig, res, ex);
+ printf("\n");
+}
+
+void test_ds(const char *s1, const char *s2, const char *orig, int ex)
+{
+ char s[100], *end;
+ int res;
+ sprintf(s, "'%s' - '%s'", s1, s2);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ end= strend(s2);
+ string2decimal(s2, &b, &end);
+ res=decimal_sub(&a, &b, &c);
+ printf("%-40s => res=%d ", s, res);
+ print_decimal(&c, orig, res, ex);
+ printf("\n");
+}
+
+void test_dc(const char *s1, const char *s2, int orig)
+{
+ char s[100], *end;
+ int res;
+ sprintf(s, "'%s' <=> '%s'", s1, s2);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ end= strend(s2);
+ string2decimal(s2, &b, &end);
+ res=decimal_cmp(&a, &b);
+ printf("%-40s => res=%d\n", s, res);
+ if (orig != res)
+ {
+ printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
+ exit(1);
+ }
+}
+
+void test_dm(const char *s1, const char *s2, const char *orig, int ex)
+{
+ char s[100], *end;
+ int res;
+ sprintf(s, "'%s' * '%s'", s1, s2);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ end= strend(s2);
+ string2decimal(s2, &b, &end);
+ res=decimal_mul(&a, &b, &c);
+ printf("%-40s => res=%d ", s, res);
+ print_decimal(&c, orig, res, ex);
+ printf("\n");
+}
+
+void test_dv(const char *s1, const char *s2, const char *orig, int ex)
+{
+ char s[100], *end;
+ int res;
+ sprintf(s, "'%s' / '%s'", s1, s2);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ end= strend(s2);
+ string2decimal(s2, &b, &end);
+ res=decimal_div(&a, &b, &c, 5);
+ printf("%-40s => res=%d ", s, res);
+ check_result_code(res, ex);
+ if (res == E_DEC_DIV_ZERO)
+ printf("E_DEC_DIV_ZERO");
+ else
+ print_decimal(&c, orig, res, ex);
+ printf("\n");
+}
+
+void test_md(const char *s1, const char *s2, const char *orig, int ex)
+{
+ char s[100], *end;
+ int res;
+ sprintf(s, "'%s' %% '%s'", s1, s2);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ end= strend(s2);
+ string2decimal(s2, &b, &end);
+ res=decimal_mod(&a, &b, &c);
+ printf("%-40s => res=%d ", s, res);
+ check_result_code(res, ex);
+ if (res == E_DEC_DIV_ZERO)
+ printf("E_DEC_DIV_ZERO");
+ else
+ print_decimal(&c, orig, res, ex);
+ printf("\n");
+}
+
+const char *round_mode[]=
+{"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
+
+void test_ro(const char *s1, int n, decimal_round_mode mode, const char *orig,
+ int ex)
+{
+ char s[100], *end;
+ int res;
+ sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ res=decimal_round(&a, &b, n, mode);
+ printf("%-40s => res=%d ", s, res);
+ print_decimal(&b, orig, res, ex);
+ printf("\n");
+}
+
+
+void test_mx(int precision, int frac, const char *orig)
+{
+ char s[100];
+ sprintf(s, "%d, %d", precision, frac);
+ max_decimal(precision, frac, &a);
+ printf("%-40s => ", s);
+ print_decimal(&a, orig, 0, 0);
+ printf("\n");
+}
+
+
+void test_pr(const char *s1, int prec, int dec, char filler, const char *orig,
+ int ex)
+{
+ char s[100], *end;
+ char s2[100];
+ int slen= sizeof(s2);
+ int res;
+
+ sprintf(s, "'%s', %d, %d, '%c'", s1, prec, dec, filler);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ res= decimal2string(&a, s2, &slen, prec, dec, filler);
+ printf("%-40s => res=%d '%s'", s, res, s2);
+ check_result_code(res, ex);
+ if (orig && strcmp(orig, s2))
+ {
+ printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
+ exit(1);
+ }
+ printf("\n");
+}
+
+
+void test_sh(const char *s1, int shift, const char *orig, int ex)
+{
+ char s[100], *end;
+ int res;
+ sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ res= decimal_shift(&a, shift);
+ printf("%-40s => res=%d ", s, res);
+ print_decimal(&a, orig, res, ex);
+ printf("\n");
+}
+
+
+void test_fr(const char *s1, const char *orig)
+{
+ char s[100], *end;
+ sprintf(s, "'%s'", s1);
+ printf("%-40s => ", s);
+ end= strend(s1);
+ string2decimal(s1, &a, &end);
+ a.frac= decimal_actual_fraction(&a);
+ print_decimal(&a, orig, 0, 0);
+ printf("\n");
+}
+
+
+int main()
+{
+ a.buf=(void*)buf1;
+ a.len=sizeof(buf1)/sizeof(dec1);
+ b.buf=(void*)buf2;
+ b.len=sizeof(buf2)/sizeof(dec1);
+ c.buf=(void*)buf3;
+ c.len=sizeof(buf3)/sizeof(dec1);
+
+ if (full)
+ test_d2s();
+
+ printf("==== string2decimal ====\n");
+ test_s2d("12345", "12345", 0);
+ test_s2d("12345.", "12345", 0);
+ test_s2d("123.45", "123.45", 0);
+ test_s2d("-123.45", "-123.45", 0);
+ test_s2d(".00012345000098765", "0.00012345000098765", 0);
+ test_s2d(".12345000098765", "0.12345000098765", 0);
+ test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
+ test_s2d("1234500009876.5", "1234500009876.5", 0);
+ a.len=1;
+ test_s2d("123450000098765", "98765", 2);
+ test_s2d("123450.000098765", "123450", 1);
+ a.len=sizeof(buf1)/sizeof(dec1);
+ test_s2d("123E5", "12300000", 0);
+ test_s2d("123E-2", "1.23", 0);
+
+ printf("==== decimal2double ====\n");
+ test_d2f("12345", 0);
+ test_d2f("123.45", 0);
+ test_d2f("-123.45", 0);
+ test_d2f("0.00012345000098765", 0);
+ test_d2f("1234500009876.5", 0);
+
+ printf("==== double2decimal ====\n");
+ test_f2d(12345, 0);
+ test_f2d(1.0/3, 0);
+ test_f2d(-123.45, 0);
+ test_f2d(0.00012345000098765, 0);
+ test_f2d(1234500009876.5, 0);
+
+ printf("==== ulonglong2decimal ====\n");
+ test_ull2d(ULL(12345), "12345", 0);
+ test_ull2d(ULL(0), "0", 0);
+ test_ull2d(ULL(18446744073709551615), "18446744073709551615", 0);
+
+ printf("==== decimal2ulonglong ====\n");
+ test_d2ull("12345", "12345", 0);
+ test_d2ull("0", "0", 0);
+ test_d2ull("18446744073709551615", "18446744073709551615", 0);
+ test_d2ull("18446744073709551616", "18446744073", 2);
+ test_d2ull("-1", "0", 2);
+ test_d2ull("1.23", "1", 1);
+ test_d2ull("9999999999999999999999999.000", "9999999999999999", 2);
+
+ printf("==== longlong2decimal ====\n");
+ test_ll2d(LL(-12345), "-12345", 0);
+ test_ll2d(LL(-1), "-1", 0);
+ test_ll2d(LL(-9223372036854775807), "-9223372036854775807", 0);
+ test_ll2d(ULL(9223372036854775808), "-9223372036854775808", 0);
+
+ printf("==== decimal2longlong ====\n");
+ test_d2ll("18446744073709551615", "18446744073", 2);
+ test_d2ll("-1", "-1", 0);
+ test_d2ll("-1.23", "-1", 1);
+ test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
+ test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
+ test_d2ll("9223372036854775808", "9223372036854775807", 2);
+
+ printf("==== do_add ====\n");
+ test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
+ test_da(".1" ,".45", "0.55", 0);
+ test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
+ test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
+ test_da("99999999" ,"1", "100000000", 0);
+ test_da("989999999" ,"1", "990000000", 0);
+ test_da("999999999" ,"1", "1000000000", 0);
+ test_da("12345" ,"123.45", "12468.45", 0);
+ test_da("-12345" ,"-123.45", "-12468.45", 0);
+ test_ds("-12345" ,"123.45", "-12468.45", 0);
+ test_ds("12345" ,"-123.45", "12468.45", 0);
+
+ printf("==== do_sub ====\n");
+ test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
+ test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
+ test_ds("9999900000000.5", ".555","9999899999999.945", 0);
+ test_ds("1111.5551", "1111.555","0.0001", 0);
+ test_ds(".555", ".555","0", 0);
+ test_ds("10000000", "1","9999999", 0);
+ test_ds("1000001000", ".1","1000000999.9", 0);
+ test_ds("1000000000", ".1","999999999.9", 0);
+ test_ds("12345", "123.45","12221.55", 0);
+ test_ds("-12345", "-123.45","-12221.55", 0);
+ test_da("-12345", "123.45","-12221.55", 0);
+ test_da("12345", "-123.45","12221.55", 0);
+ test_ds("123.45", "12345","-12221.55", 0);
+ test_ds("-123.45", "-12345","12221.55", 0);
+ test_da("123.45", "-12345","-12221.55", 0);
+ test_da("-123.45", "12345","12221.55", 0);
+ test_da("5", "-6.0","-1.0", 0);
+
+ printf("==== decimal_mul ====\n");
+ test_dm("12", "10","120", 0);
+ test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
+ test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
+ test_dm("123456", "987654321","121931851853376", 0);
+ test_dm("123456", "9876543210","1219318518533760", 0);
+ test_dm("123", "0.01","1.23", 0);
+ test_dm("123", "0","0", 0);
+
+ printf("==== decimal_div ====\n");
+ test_dv("120", "10","12.000000000", 0);
+ test_dv("123", "0.01","12300.000000000", 0);
+ test_dv("120", "100000000000.00000","0.000000001200000000", 0);
+ test_dv("123", "0","", 4);
+ test_dv("0", "0", "", 4);
+ test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
+ test_dv("121931851853376", "987654321","123456.000000000", 0);
+ test_dv("0", "987","0", 0);
+ test_dv("1", "3","0.333333333", 0);
+ test_dv("1.000000000000", "3","0.333333333333333333", 0);
+ test_dv("1", "1","1.000000000", 0);
+ test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
+ test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
+ test_dv("10.000000000060", "2","5.000000000030000000", 0);
+
+ printf("==== decimal_mod ====\n");
+ test_md("234","10","4", 0);
+ test_md("234.567","10.555","2.357", 0);
+ test_md("-234.567","10.555","-2.357", 0);
+ test_md("234.567","-10.555","2.357", 0);
+ c.buf[1]=0x3ABECA;
+ test_md("99999999999999999999999999999999999999","3","0", 0);
+ if (c.buf[1] != 0x3ABECA)
+ {
+ printf("%X - overflow\n", c.buf[1]);
+ exit(1);
+ }
+
+ printf("==== decimal2bin/bin2decimal ====\n");
+ test_d2b2d("-10.55", 4, 2,"-10.55", 0);
+ test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
+ test_d2b2d("12345", 5, 0,"12345", 0);
+ test_d2b2d("12345", 10, 3,"12345.000", 0);
+ test_d2b2d("123.45", 10, 3,"123.450", 0);
+ test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
+ test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
+ test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
+ test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
+ test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
+ test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
+ test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
+ test_d2b2d("000000000.01", 7, 3,"0.010", 0);
+ test_d2b2d("123.4", 10, 2, "123.40", 0);
+
+
+ printf("==== decimal_cmp ====\n");
+ test_dc("12","13",-1);
+ test_dc("13","12",1);
+ test_dc("-10","10",-1);
+ test_dc("10","-10",1);
+ test_dc("-12","-13",1);
+ test_dc("0","12",-1);
+ test_dc("-10","0",-1);
+ test_dc("4","4",0);
+
+ printf("==== decimal_round ====\n");
+ test_ro("5678.123451",-4,TRUNCATE,"0", 0);
+ test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
+ test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
+ test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
+ test_ro("5678.123451",0,TRUNCATE,"5678", 0);
+ test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
+ test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
+ test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
+ test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
+ test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
+ test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
+ test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
+ memset(buf2, 33, sizeof(buf2));
+ test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
+ test_ro("15.1",0,HALF_UP,"15", 0);
+ test_ro("15.5",0,HALF_UP,"16", 0);
+ test_ro("15.9",0,HALF_UP,"16", 0);
+ test_ro("-15.1",0,HALF_UP,"-15", 0);
+ test_ro("-15.5",0,HALF_UP,"-16", 0);
+ test_ro("-15.9",0,HALF_UP,"-16", 0);
+ test_ro("15.1",1,HALF_UP,"15.1", 0);
+ test_ro("-15.1",1,HALF_UP,"-15.1", 0);
+ test_ro("15.17",1,HALF_UP,"15.2", 0);
+ test_ro("15.4",-1,HALF_UP,"20", 0);
+ test_ro("-15.4",-1,HALF_UP,"-20", 0);
+ test_ro("5.4",-1,HALF_UP,"10", 0);
+ test_ro(".999", 0, HALF_UP, "1", 0);
+ memset(buf2, 33, sizeof(buf2));
+ test_ro("999999999", -9, HALF_UP, "1000000000", 0);
+ test_ro("15.1",0,HALF_EVEN,"15", 0);
+ test_ro("15.5",0,HALF_EVEN,"16", 0);
+ test_ro("14.5",0,HALF_EVEN,"14", 0);
+ test_ro("15.9",0,HALF_EVEN,"16", 0);
+ test_ro("15.1",0,CEILING,"16", 0);
+ test_ro("-15.1",0,CEILING,"-15", 0);
+ test_ro("15.1",0,FLOOR,"15", 0);
+ test_ro("-15.1",0,FLOOR,"-16", 0);
+ test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
+ test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
+
+ b.buf[0]=DIG_BASE+1;
+ b.buf++;
+ test_ro(".3", 0, HALF_UP, "0", 0);
+ b.buf--;
+ if (b.buf[0] != DIG_BASE+1)
+ {
+ printf("%d - underflow\n", b.buf[0]);
+ exit(1);
+ }
+
+ printf("==== max_decimal ====\n");
+ test_mx(1,1,"0.9");
+ test_mx(1,0,"9");
+ test_mx(2,1,"9.9");
+ test_mx(4,2,"99.99");
+ test_mx(6,3,"999.999");
+ test_mx(8,4,"9999.9999");
+ test_mx(10,5,"99999.99999");
+ test_mx(12,6,"999999.999999");
+ test_mx(14,7,"9999999.9999999");
+ test_mx(16,8,"99999999.99999999");
+ test_mx(18,9,"999999999.999999999");
+ test_mx(20,10,"9999999999.9999999999");
+ test_mx(20,20,"0.99999999999999999999");
+ test_mx(20,0,"99999999999999999999");
+ test_mx(40,20,"99999999999999999999.99999999999999999999");
+
+ printf("==== decimal2string ====\n");
+ test_pr("123.123", 0, 0, 0, "123.123", 0);
+ test_pr("123.123", 7, 3, '0', "123.123", 0);
+ test_pr("123.123", 9, 3, '0', "00123.123", 0);
+ test_pr("123.123", 9, 4, '0', "0123.1230", 0);
+ test_pr("123.123", 9, 5, '0', "123.12300", 0);
+ test_pr("123.123", 9, 2, '0', "000123.12", 1);
+ test_pr("123.123", 9, 6, '0', "23.123000", 2);
+
+ printf("==== decimal_shift ====\n");
+ test_sh("123.123", 1, "1231.23", 0);
+ test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
+ test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
+ test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
+ test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
+ test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
+ test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
+ test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
+ test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
+ test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
+ test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
+ test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
+ test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
+ test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
+ test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
+ test_sh("123", 1, "1230", 0);
+ test_sh("123", 10, "1230000000000", 0);
+ test_sh(".123", 1, "1.23", 0);
+ test_sh(".123", 10, "1230000000", 0);
+ test_sh(".123", 14, "12300000000000", 0);
+ test_sh("000.000", 1000, "0", 0);
+ test_sh("000.", 1000, "0", 0);
+ test_sh(".000", 1000, "0", 0);
+ test_sh("1", 1000, "1", 2);
+ test_sh("123.123", -1, "12.3123", 0);
+ test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
+ test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
+ test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
+ test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
+ test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
+ test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
+ test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
+ test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
+ test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
+ test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
+ test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
+ a.len= 2;
+ test_sh("123.123", -2, "1.23123", 0);
+ test_sh("123.123", -3, "0.123123", 0);
+ test_sh("123.123", -6, "0.000123123", 0);
+ test_sh("123.123", -7, "0.0000123123", 0);
+ test_sh("123.123", -15, "0.000000000000123123", 0);
+ test_sh("123.123", -16, "0.000000000000012312", 1);
+ test_sh("123.123", -17, "0.000000000000001231", 1);
+ test_sh("123.123", -18, "0.000000000000000123", 1);
+ test_sh("123.123", -19, "0.000000000000000012", 1);
+ test_sh("123.123", -20, "0.000000000000000001", 1);
+ test_sh("123.123", -21, "0", 1);
+ test_sh(".000000000123", -1, "0.0000000000123", 0);
+ test_sh(".000000000123", -6, "0.000000000000000123", 0);
+ test_sh(".000000000123", -7, "0.000000000000000012", 1);
+ test_sh(".000000000123", -8, "0.000000000000000001", 1);
+ test_sh(".000000000123", -9, "0", 1);
+ test_sh(".000000000123", 1, "0.00000000123", 0);
+ test_sh(".000000000123", 8, "0.0123", 0);
+ test_sh(".000000000123", 9, "0.123", 0);
+ test_sh(".000000000123", 10, "1.23", 0);
+ test_sh(".000000000123", 17, "12300000", 0);
+ test_sh(".000000000123", 18, "123000000", 0);
+ test_sh(".000000000123", 19, "1230000000", 0);
+ test_sh(".000000000123", 20, "12300000000", 0);
+ test_sh(".000000000123", 21, "123000000000", 0);
+ test_sh(".000000000123", 22, "1230000000000", 0);
+ test_sh(".000000000123", 23, "12300000000000", 0);
+ test_sh(".000000000123", 24, "123000000000000", 0);
+ test_sh(".000000000123", 25, "1230000000000000", 0);
+ test_sh(".000000000123", 26, "12300000000000000", 0);
+ test_sh(".000000000123", 27, "123000000000000000", 0);
+ test_sh(".000000000123", 28, "0.000000000123", 2);
+ test_sh("123456789.987654321", -1, "12345678.998765432", 1);
+ test_sh("123456789.987654321", -2, "1234567.899876543", 1);
+ test_sh("123456789.987654321", -8, "1.234567900", 1);
+ test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
+ test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
+ test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
+ test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
+ test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
+ test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
+ test_sh("123456789.987654321", -27, "0", 1);
+ test_sh("123456789.987654321", 1, "1234567900", 1);
+ test_sh("123456789.987654321", 2, "12345678999", 1);
+ test_sh("123456789.987654321", 4, "1234567899877", 1);
+ test_sh("123456789.987654321", 8, "12345678998765432", 1);
+ test_sh("123456789.987654321", 9, "123456789987654321", 0);
+ test_sh("123456789.987654321", 10, "123456789.987654321", 2);
+ test_sh("123456789.987654321", 0, "123456789.987654321", 0);
+ a.len= sizeof(buf1)/sizeof(dec1);
+
+ printf("==== decimal_actual_fraction ====\n");
+ test_fr("1.123456789000000000", "1.123456789");
+ test_fr("1.12345678000000000", "1.12345678");
+ test_fr("1.1234567000000000", "1.1234567");
+ test_fr("1.123456000000000", "1.123456");
+ test_fr("1.12345000000000", "1.12345");
+ test_fr("1.1234000000000", "1.1234");
+ test_fr("1.123000000000", "1.123");
+ test_fr("1.12000000000", "1.12");
+ test_fr("1.1000000000", "1.1");
+ test_fr("1.000000000", "1");
+ test_fr("1.0", "1");
+ test_fr("10000000000000000000.0", "10000000000000000000");
+
+ return 0;
+}
+#endif
diff --git a/strings/llstr.c b/strings/llstr.c
index 966b347ac7e..ac034cbe2e2 100644
--- a/strings/llstr.c
+++ b/strings/llstr.c
@@ -30,6 +30,6 @@
char *llstr(longlong value,char *buff)
{
- longlong2str(value,buff,-10);
+ longlong10_to_str(value,buff,-10);
return buff;
}
diff --git a/strings/my_strtoll10.c b/strings/my_strtoll10.c
index 5217564087c..1f4cf1435fe 100644
--- a/strings/my_strtoll10.c
+++ b/strings/my_strtoll10.c
@@ -19,7 +19,13 @@
#include <m_string.h>
#undef ULONGLONG_MAX
+/* Needed under MetroWerks Compiler, since MetroWerks compiler does not properly handle a constant expression containing a mod operator */
+#if defined(__NETWARE__) && defined(__MWERKS__)
+ulonglong tmp;
+#define ULONGLONG_MAX (tmp =(~(ulonglong) 0))
+#else
#define ULONGLONG_MAX (~(ulonglong) 0)
+#endif /* __NETWARE__ && __MWERKS__ */
#define MAX_NEGATIVE_NUMBER ((ulonglong) LL(0x8000000000000000))
#define INIT_CNT 9
#define LFACTOR ULL(1000000000)
@@ -46,7 +52,7 @@ static unsigned long lfactor[9]=
from string nptr and converts it to an signed or unsigned
long long integer value.
Space characters and tab are ignored.
- A sign character might precede the the digit characters. The number
+ A sign character might precede the digit characters. The number
may have any number of pre-zero digits.
The function stops reading the string nptr at the first character
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
index d0e529288f7..0e036c2bbcd 100644
--- a/strings/my_vsnprintf.c
+++ b/strings/my_vsnprintf.c
@@ -52,15 +52,30 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
if (*fmt == '-')
fmt++;
length= width= pre_zero= have_long= 0;
- for (;my_isdigit(&my_charset_latin1,*fmt); fmt++)
+ if (*fmt == '*')
{
- length=length*10+ (uint) (*fmt-'0');
- if (!length)
- pre_zero= 1; /* first digit was 0 */
+ fmt++;
+ length= va_arg(ap, int);
}
+ else
+ for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
+ {
+ length= length * 10 + (uint)(*fmt - '0');
+ if (!length)
+ pre_zero= 1; /* first digit was 0 */
+ }
if (*fmt == '.')
- for (fmt++;my_isdigit(&my_charset_latin1,*fmt); fmt++)
- width=width*10+ (uint) (*fmt-'0');
+ {
+ fmt++;
+ if (*fmt == '*')
+ {
+ fmt++;
+ width= va_arg(ap, int);
+ }
+ else
+ for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
+ width= width * 10 + (uint)(*fmt - '0');
+ }
else
width= ~0;
if (*fmt == 'l')
@@ -120,6 +135,16 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
to+= res_length;
continue;
}
+ else if (*fmt == 'c') /* Character parameter */
+ {
+ register int larg;
+ if (to == end)
+ break;
+ larg = va_arg(ap, int);
+ *to++= (char) larg;
+ continue;
+ }
+
/* We come here on '%%', unknown code or too long parameter */
if (to == end)
break;
diff --git a/merge/mrg_update.c b/strings/str_alloc.c
index a6650267f36..158fa7e75bb 100644
--- a/merge/mrg_update.c
+++ b/strings/str_alloc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000 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
@@ -14,18 +14,21 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Update last read record */
+#include <my_global.h>
+#include <m_string.h>
-#include "mrg_def.h"
+static void *my_str_malloc_default(size_t size)
+{
+ void *ret= malloc(size);
+ if (!ret)
+ exit(1);
+ return ret;
+}
-int mrg_update(
-register MRG_INFO *info,
-const byte *oldrec, const byte *newrec)
+static void my_str_free_default(void *ptr)
{
- if (!info->current_table)
- {
- my_errno=HA_ERR_NO_ACTIVE_RECORD;
- return(-1);
- }
- return nisam_update(info->current_table->table,oldrec,newrec);
+ free(ptr);
}
+
+void *(*my_str_malloc)(size_t)= &my_str_malloc_default;
+void (*my_str_free)(void *)= &my_str_free_default;
diff --git a/strings/xml.c b/strings/xml.c
index 6ba52ea41a8..02ca3932c39 100644
--- a/strings/xml.c
+++ b/strings/xml.c
@@ -96,13 +96,13 @@ static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a)
a->end=p->cur;
lex=a->beg[0];
}
- else if ( (p->cur[0]=='"') || (p->cur[0]=='\'') )
+ else if ( (p->cur[0] == '"') || (p->cur[0] == '\'') )
{
p->cur++;
for( ; ( p->cur < p->end ) && (p->cur[0] != a->beg[0]); p->cur++)
{}
a->end=p->cur;
- if (a->beg[0]==p->cur[0])p->cur++;
+ if (a->beg[0] == p->cur[0])p->cur++;
a->beg++;
my_xml_norm_text(a);
lex=MY_XML_STRING;
@@ -135,7 +135,7 @@ static int my_xml_value(MY_XML_PARSER *st, const char *str, uint len)
static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
{
- if ( (st->attrend-st->attr+len+1)>sizeof(st->attr))
+ if ((uint) (st->attrend-st->attr+len+1) > sizeof(st->attr))
{
sprintf(st->errstr,"To deep XML");
return MY_XML_ERROR;
@@ -148,7 +148,7 @@ static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
memcpy(st->attrend,str,len);
st->attrend+=len;
st->attrend[0]='\0';
- return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
+ return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
}
@@ -169,8 +169,8 @@ static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
int rc;
/* Find previous '.' or beginning */
- for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--);
- glen = (e[0]=='.') ? (p->attrend-e-1) : p->attrend-e;
+ for( e=p->attrend; (e>p->attr) && (e[0] != '.') ; e--);
+ glen = (uint) ((e[0] == '.') ? (p->attrend-e-1) : p->attrend-e);
if (str && (slen != glen))
{
@@ -180,7 +180,7 @@ static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
return MY_XML_ERROR;
}
- rc = p->leave_xml ? p->leave_xml(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
+ rc = p->leave_xml ? p->leave_xml(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
*e='\0';
p->attrend=e;
@@ -199,7 +199,7 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
while ( p->cur < p->end )
{
MY_XML_ATTR a;
- if(p->cur[0]=='<')
+ if (p->cur[0] == '<')
{
int lex;
int question=0;
@@ -207,40 +207,40 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
lex=my_xml_scan(p,&a);
- if (MY_XML_COMMENT==lex)
+ if (MY_XML_COMMENT == lex)
{
continue;
}
lex=my_xml_scan(p,&a);
- if (MY_XML_SLASH==lex)
+ if (MY_XML_SLASH == lex)
{
- if(MY_XML_IDENT!=(lex=my_xml_scan(p,&a)))
+ if (MY_XML_IDENT != (lex=my_xml_scan(p,&a)))
{
sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex));
return MY_XML_ERROR;
}
- if(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg))
+ if (MY_XML_OK != my_xml_leave(p,a.beg,(uint) (a.end-a.beg)))
return MY_XML_ERROR;
lex=my_xml_scan(p,&a);
goto gt;
}
- if (MY_XML_EXCLAM==lex)
+ if (MY_XML_EXCLAM == lex)
{
lex=my_xml_scan(p,&a);
exclam=1;
}
- else if (MY_XML_QUESTION==lex)
+ else if (MY_XML_QUESTION == lex)
{
lex=my_xml_scan(p,&a);
question=1;
}
- if (MY_XML_IDENT==lex)
+ if (MY_XML_IDENT == lex)
{
- if(MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))
+ if (MY_XML_OK != my_xml_enter(p,a.beg,(uint) (a.end-a.beg)))
return MY_XML_ERROR;
}
else
@@ -250,17 +250,18 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
return MY_XML_ERROR;
}
- while ((MY_XML_IDENT==(lex=my_xml_scan(p,&a))) || (MY_XML_STRING==lex))
+ while ((MY_XML_IDENT == (lex=my_xml_scan(p,&a))) ||
+ (MY_XML_STRING == lex))
{
MY_XML_ATTR b;
- if(MY_XML_EQ==(lex=my_xml_scan(p,&b)))
+ if (MY_XML_EQ == (lex=my_xml_scan(p,&b)))
{
lex=my_xml_scan(p,&b);
- if ( (lex==MY_XML_IDENT) || (lex==MY_XML_STRING) )
+ if ( (lex == MY_XML_IDENT) || (lex == MY_XML_STRING) )
{
- if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
- (MY_XML_OK!=my_xml_value(p,b.beg,b.end-b.beg)) ||
- (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ if ((MY_XML_OK != my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) ||
+ (MY_XML_OK != my_xml_value(p,b.beg,(uint) (b.end-b.beg))) ||
+ (MY_XML_OK != my_xml_leave(p,a.beg,(uint) (a.end-a.beg))))
return MY_XML_ERROR;
}
else
@@ -270,19 +271,19 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
return MY_XML_ERROR;
}
}
- else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) )
+ else if ((MY_XML_STRING == lex) || (MY_XML_IDENT == lex))
{
- if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
- (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ if ((MY_XML_OK != my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) ||
+ (MY_XML_OK != my_xml_leave(p,a.beg,(uint) (a.end-a.beg))))
return MY_XML_ERROR;
}
else
break;
}
- if (lex==MY_XML_SLASH)
+ if (lex == MY_XML_SLASH)
{
- if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ if (MY_XML_OK != my_xml_leave(p,NULL,0))
return MY_XML_ERROR;
lex=my_xml_scan(p,&a);
}
@@ -290,23 +291,23 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
gt:
if (question)
{
- if (lex!=MY_XML_QUESTION)
+ if (lex != MY_XML_QUESTION)
{
sprintf(p->errstr,"6: %s unexpected ('?' wanted)",lex2str(lex));
return MY_XML_ERROR;
}
- if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ if (MY_XML_OK != my_xml_leave(p,NULL,0))
return MY_XML_ERROR;
lex=my_xml_scan(p,&a);
}
if (exclam)
{
- if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ if (MY_XML_OK != my_xml_leave(p,NULL,0))
return MY_XML_ERROR;
}
- if (lex!=MY_XML_GT)
+ if (lex != MY_XML_GT)
{
sprintf(p->errstr,"5: %s unexpected ('>' wanted)",lex2str(lex));
return MY_XML_ERROR;
@@ -315,13 +316,13 @@ gt:
else
{
a.beg=p->cur;
- for ( ; (p->cur < p->end) && (p->cur[0]!='<') ; p->cur++);
+ for ( ; (p->cur < p->end) && (p->cur[0] != '<') ; p->cur++);
a.end=p->cur;
my_xml_norm_text(&a);
- if (a.beg!=a.end)
+ if (a.beg != a.end)
{
- my_xml_value(p,a.beg,a.end-a.beg);
+ my_xml_value(p,a.beg,(uint) (a.end-a.beg));
}
}
}
@@ -381,19 +382,19 @@ uint my_xml_error_pos(MY_XML_PARSER *p)
const char *s;
for ( s=p->beg ; s<p->cur; s++)
{
- if (s[0]=='\n')
+ if (s[0] == '\n')
beg=s;
}
- return p->cur-beg;
+ return (uint) (p->cur-beg);
}
uint my_xml_error_lineno(MY_XML_PARSER *p)
{
uint res=0;
const char *s;
- for ( s=p->beg ; s<p->cur; s++)
+ for (s=p->beg ; s<p->cur; s++)
{
- if (s[0]=='\n')
+ if (s[0] == '\n')
res++;
}
return res;
diff --git a/support-files/MacOSX/Info.plist.sh b/support-files/MacOSX/Info.plist.sh
index f14902ff379..fdfb0c7a17c 100644
--- a/support-files/MacOSX/Info.plist.sh
+++ b/support-files/MacOSX/Info.plist.sh
@@ -9,11 +9,7 @@
<key>CFBundleName</key>
<string>MySQL</string>
<key>CFBundleShortVersionString</key>
- <string>@VERSION@</string>
- <key>IFMajorVersion</key>
- <integer>4</integer>
- <key>IFMinorVersion</key>
- <integer>0</integer>
+ <string>@MYSQL_NO_DASH_VERSION@</string>
<key>IFPkgFlagAllowBackRev</key>
<false/>
<key>IFPkgFlagAuthorizationAction</key>
diff --git a/support-files/MacOSX/Makefile.am b/support-files/MacOSX/Makefile.am
index d751ed7ca5b..ea99c46389d 100644
--- a/support-files/MacOSX/Makefile.am
+++ b/support-files/MacOSX/Makefile.am
@@ -47,6 +47,7 @@ SUFFIXES = .sh
@SED@ \
-e 's!@''prefix''@!$(prefix)!g' \
-e 's!@''VERSION''@!@VERSION@!' \
+ -e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \
-e 's!@''MYSQL_SERVER_SUFFIX''@!@MYSQL_SERVER_SUFFIX@!' \
-e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \
$< > $@-t
diff --git a/support-files/MySQL-shared-compat.spec.sh b/support-files/MySQL-shared-compat.spec.sh
index e3c88c9415f..ffc96fd6fff 100644
--- a/support-files/MySQL-shared-compat.spec.sh
+++ b/support-files/MySQL-shared-compat.spec.sh
@@ -26,7 +26,8 @@
#
# Change this to match the version of the shared libs you want to include
#
-%define version41 @MYSQL_NO_DASH_VERSION@
+%define version50 @MYSQL_NO_DASH_VERSION@
+%define version41 4.1.9
%define version40 4.0.23
%define version3 3.23.58
@@ -37,30 +38,32 @@ License: GPL
Group: Applications/Databases
URL: http://www.mysql.com/
Autoreqprov: on
-Version: %{version41}
+Version: %{version50}
Release: 0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Obsoletes: MySQL-shared, mysql-shared
Provides: MySQL-shared
-Summary: MySQL shared client libraries for MySQL %{version41}, %{version40} and %{version3}
+Summary: MySQL shared client libraries for MySQL %{version}, %{version41}, %{version40} and %{version3}
# We simply use the "MySQL-shared" subpackages as input sources instead of
# rebuilding all from source
-Source0: MySQL-shared-%{version41}-0.%{_arch}.rpm
-Source1: MySQL-shared-%{version40}-0.%{_arch}.rpm
-Source2: MySQL-shared-%{version3}-1.%{_arch}.rpm
+Source0: MySQL-shared-%{version50}-0.%{_arch}.rpm
+Source1: MySQL-shared-%{version41}-0.%{_arch}.rpm
+Source2: MySQL-shared-%{version40}-0.%{_arch}.rpm
+Source3: MySQL-shared-%{version3}-1.%{_arch}.rpm
# No need to include the RPMs once more - they can be downloaded seperately
# if you want to rebuild this package
NoSource: 0
NoSource: 1
NoSource: 2
+NoSource: 3
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%description
-This package includes the shared libraries for both MySQL %{version3},
-MySQL %{version40} as well as MySQL %{version41}.
+This package includes the shared libraries for MySQL %{version3},
+MySQL %{version40}, %{version41} as well as MySQL %{version50}.
Install this package instead of "MySQL-shared", if you have applications
installed that are dynamically linked against older versions of the MySQL
-client library but you want to upgrade to MySQL 4.1.xx without breaking the
+client library but you want to upgrade to MySQL %{version} without breaking the
library dependencies.
%install
@@ -70,6 +73,7 @@ cd $RPM_BUILD_ROOT
rpm2cpio %{SOURCE0} | cpio -iv --make-directories
rpm2cpio %{SOURCE1} | cpio -iv --make-directories
rpm2cpio %{SOURCE2} | cpio -iv --make-directories
+rpm2cpio %{SOURCE3} | cpio -iv --make-directories
/sbin/ldconfig -n $RPM_BUILD_ROOT%{_libdir}
%clean
diff --git a/support-files/debian/gomi b/support-files/debian/gomi
index 4c9460578be..70251058af0 100644
--- a/support-files/debian/gomi
+++ b/support-files/debian/gomi
@@ -2,8 +2,6 @@ Docs/Makefile
dbug/Makefile
extra/Makefile
heap/Makefile
-isam/Makefile
-merge/Makefile
mysys/Makefile
readline/Makefile
regex/Makefile
diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh
index d25686f1c21..f7a47054658 100644
--- a/support-files/my-huge.cnf.sh
+++ b/support-files/my-huge.cnf.sh
@@ -48,7 +48,7 @@ thread_concurrency = 8
# Replication Master Server (default)
# binary logging is required for replication
-log-bin
+log-bin=mysql-bin
# required unique id between 1 and 2^32 - 1
# defaults to 1 if master-host is not set
@@ -108,7 +108,7 @@ server-id = 1
#master-port = <port>
#
# binary logging - not required for slaves, but recommended
-#log-bin
+#log-bin=mysql-bin
# Point the following paths to different dedicated disks
#tmpdir = /tmp/
diff --git a/support-files/my-innodb-heavy-4G.cnf.sh b/support-files/my-innodb-heavy-4G.cnf.sh
index 062d106ce6a..b3f43272a7d 100644
--- a/support-files/my-innodb-heavy-4G.cnf.sh
+++ b/support-files/my-innodb-heavy-4G.cnf.sh
@@ -189,7 +189,7 @@ tmp_table_size = 64M
# Enable binary logging. This is required for acting as a MASTER in a
# replication configuration. You also need the binary log if you need
# the ability to do point in time recovery from your latest backup.
-log_bin
+log-bin=mysql-bin
# If you're using replication with chained slaves (A->B->C), you need to
# enable this option on server B. It enables logging of updates done by
diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh
index 59aca4b32f2..1e7d9f7aade 100644
--- a/support-files/my-large.cnf.sh
+++ b/support-files/my-large.cnf.sh
@@ -48,7 +48,7 @@ thread_concurrency = 8
# Replication Master Server (default)
# binary logging is required for replication
-log-bin
+log-bin=mysql-bin
# required unique id between 1 and 2^32 - 1
# defaults to 1 if master-host is not set
@@ -108,7 +108,7 @@ server-id = 1
#master-port = <port>
#
# binary logging - not required for slaves, but recommended
-#log-bin
+#log-bin=mysql-bin
# Point the following paths to different dedicated disks
#tmpdir = /tmp/
diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh
index 529740d59f0..99b6e823f39 100644
--- a/support-files/my-medium.cnf.sh
+++ b/support-files/my-medium.cnf.sh
@@ -46,7 +46,7 @@ myisam_sort_buffer_size = 8M
# Replication Master Server (default)
# binary logging is required for replication
-log-bin
+log-bin=mysql-bin
# required unique id between 1 and 2^32 - 1
# defaults to 1 if master-host is not set
@@ -106,7 +106,7 @@ server-id = 1
#master-port = <port>
#
# binary logging - not required for slaves, but recommended
-#log-bin
+#log-bin=mysql-bin
# Point the following paths to different dedicated disks
#tmpdir = /tmp/
diff --git a/support-files/my-small.cnf.sh b/support-files/my-small.cnf.sh
index b2ecca6127e..288df893b4c 100644
--- a/support-files/my-small.cnf.sh
+++ b/support-files/my-small.cnf.sh
@@ -46,7 +46,7 @@ thread_stack = 64K
server-id = 1
# Uncomment the following if you want to log updates
-#log-bin
+#log-bin=mysql-bin
# Uncomment the following if you are NOT using BDB tables
#skip-bdb
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index 150a8a151ba..6dbffdc9778 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -39,19 +39,31 @@
# If you want to affect other MySQL variables, you should make your changes
# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files.
+# If you change base dir, you must also change datadir. These may get
+# overwritten by settings in the MySQL configuration files.
+
basedir=
+datadir=
# The following variables are only set for letting mysql.server find things.
# Set some defaults
-datadir=@localstatedir@
pid_file=
+server_pid_file=
+use_mysqld_safe=1
+user=@MYSQLD_USER@
if test -z "$basedir"
then
basedir=@prefix@
bindir=@bindir@
+ datadir=@localstatedir@
+ sbindir=@sbindir@
+ libexecdir=@libexecdir@
else
bindir="$basedir/bin"
+ datadir="$basedir/data"
+ sbindir="$basedir/sbin"
+ libexecdir="$basedir/libexec"
fi
#
@@ -82,12 +94,29 @@ case `echo "testing\c"`,`echo -n testing` in
*) echo_n= echo_c='\c' ;;
esac
-parse_arguments() {
+parse_server_arguments() {
for arg do
case "$arg" in
- --basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'`
+ bindir="$basedir/bin"
+ datadir="$basedir/data"
+ sbindir="$basedir/sbin"
+ libexecdir="$basedir/libexec"
+ ;;
--datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --pid-file=*) server_pid_file=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --use-mysqld_safe) use_mysqld_safe=1;;
+ --use-manager) use_mysqld_safe=0;;
+ esac
+ done
+}
+
+parse_manager_arguments() {
+ for arg do
+ case "$arg" in
--pid-file=*) pid_file=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
esac
done
}
@@ -120,7 +149,7 @@ wait_for_pid () {
}
# Get arguments from the my.cnf file,
-# groups [mysqld] [mysql_server] and [mysql.server]
+# the only group, which is read from now on is [mysqld]
if test -x ./bin/my_print_defaults
then
print_defaults="./bin/my_print_defaults"
@@ -159,30 +188,47 @@ else
fi
#
-# Test if someone changed datadir; In this case we should also read the
-# default arguments from this directory
+# Read defaults file from 'basedir'. If there is no defaults file there
+# check if it's in the old (depricated) place (datadir) and read it from there
#
extra_args=""
-if test "$datadir" != "@localstatedir@"
+if test -r "$basedir/my.cnf"
then
- extra_args="-e $datadir/my.cnf"
+ extra_args="-e $basedir/my.cnf"
+else
+ if test -r "$datadir/my.cnf"
+ then
+ extra_args="-e $datadir/my.cnf"
+ fi
fi
-parse_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`
+parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`
+
+# Look for the pidfile
+parse_manager_arguments `$print_defaults $extra_args manager`
#
# Set pid file if not given
#
if test -z "$pid_file"
then
- pid_file=$datadir/`@HOSTNAME@`.pid
+ pid_file=$datadir/mysqlmanager-`@HOSTNAME@`.pid
else
case "$pid_file" in
/* ) ;;
* ) pid_file="$datadir/$pid_file" ;;
esac
fi
+if test -z "$server_pid_file"
+then
+ server_pid_file=$datadir/`@HOSTNAME@`.pid
+else
+ case "$server_pid_file" in
+ /* ) ;;
+ * ) server_pid_file="$datadir/$server_pid_file" ;;
+ esac
+fi
# Safeguard (relative paths, core dumps..)
cd $basedir
@@ -191,42 +237,75 @@ case "$mode" in
'start')
# Start daemon
- if test -x $bindir/mysqld_safe
+ manager=$bindir/mysqlmanager
+ if test -x $libexecdir/mysqlmanager
+ then
+ manager=$libexecdir/mysqlmanager
+ elif test -x $sbindir/mysqlmanager
+ then
+ manager=$sbindir/mysqlmanager
+ fi
+
+ echo $echo_n "Starting MySQL"
+ if test -x $manager -a "$use_mysqld_safe" = "0"
then
# Give extra arguments to mysqld with the my.cnf file. This script may
# be overwritten at next upgrade.
- echo $echo_n "Starting MySQL"
- $bindir/mysqld_safe --datadir=$datadir --pid-file=$pid_file >/dev/null 2>&1 &
+ $manager --user=$user --pid-file=$pid_file >/dev/null 2>&1 &
+ wait_for_pid created
+
+ # Make lock for RedHat / SuSE
+ if test -w /var/lock/subsys
+ then
+ touch /var/lock/subsys/mysqlmanager
+ fi
+ elif test -x $bindir/mysqld_safe
+ then
+ # Give extra arguments to mysqld with the my.cnf file. This script
+ # may be overwritten at next upgrade.
+ pid_file=$server_pid_file
+ $bindir/mysqld_safe --datadir=$datadir --pid-file=$server_pid_file >/dev/null 2>&1 &
wait_for_pid created
-
+
# Make lock for RedHat / SuSE
if test -w /var/lock/subsys
then
touch /var/lock/subsys/mysql
fi
else
- log_failure_msg "Can't execute $bindir/mysqld_safe"
+ log_failure_msg "Couldn't find MySQL manager or server"
fi
;;
'stop')
# Stop daemon. We use a signal here to avoid having to know the
# root password.
+
+ # The RedHat / SuSE lock directory to remove
+ lock_dir=/var/lock/subsys/mysqlmanager
+
+ # If the manager pid_file doesn't exist, try the server's
+ if test ! -s "$pid_file"
+ then
+ pid_file=$server_pid_file
+ lock_dir=/var/lock/subsys/mysql
+ fi
+
if test -s "$pid_file"
then
- mysqld_pid=`cat $pid_file`
+ mysqlmanager_pid=`cat $pid_file`
echo $echo_n "Shutting down MySQL"
- kill $mysqld_pid
- # mysqld should remove the pid_file when it exits, so wait for it.
+ kill $mysqlmanager_pid
+ # mysqlmanager should remove the pid_file when it exits, so wait for it.
wait_for_pid removed
# delete lock for RedHat / SuSE
- if test -f /var/lock/subsys/mysql
+ if test -f $lock_dir
then
- rm -f /var/lock/subsys/mysql
+ rm -f $lock_dir
fi
else
- log_failure_msg "MySQL PID file could not be found!"
+ log_failure_msg "MySQL manager or server PID file could not be found!"
fi
;;
@@ -235,17 +314,17 @@ case "$mode" in
# running or not, start it again.
$0 stop
$0 start
- ;;
+ ;;
'reload')
- if test -s "$pid_file" ; then
- mysqld_pid=`cat $pid_file`
+ if test -s "$server_pid_file" ; then
+ mysqld_pid=`cat $server_pid_file`
kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL"
- touch $pid_file
+ touch $server_pid_file
else
log_failure_msg "MySQL PID file could not be found!"
fi
- ;;
+ ;;
*)
# usage
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index af9abd2fce1..637a0402b8e 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -188,7 +188,7 @@ Optional MySQL server binary that supports additional features like:
- Archive Storage Engine
- CSV Storage Engine
- Example Storage Engine
- - MyISAM RAID
+ - Federated Storage Engine
- User Defined Functions (UDFs).
To activate this binary, just install this package in addition to
@@ -299,11 +299,11 @@ BuildMySQL "--enable-shared \
--with-berkeley-db \
--with-innodb \
--with-ndbcluster \
- --with-raid \
--with-archive-storage-engine \
--with-csv-storage-engine \
--with-example-storage-engine \
--with-blackhole-storage-engine \
+ --with-federated-storage-engine \
--with-embedded-server \
--with-comment=\"MySQL Community Edition - Max (GPL)\" \
--with-server-suffix='-Max'"
@@ -334,6 +334,7 @@ fi
# Save libraries
(cd libmysql/.libs; tar cf $RBR/shared-libs.tar *.so*)
(cd libmysql_r/.libs; tar rf $RBR/shared-libs.tar *.so*)
+(cd ndb/src/.libs; tar rf $RBR/shared-libs.tar *.so*)
# Now clean up
make clean
@@ -400,9 +401,11 @@ ln -s %{_sysconfdir}/init.d/mysql $RPM_BUILD_ROOT%{_sbindir}/rcmysql
# (safe_mysqld will be gone in MySQL 4.1)
ln -sf ./mysqld_safe $RBR%{_bindir}/safe_mysqld
-# Touch the place where the my.cnf config file might be located
+# Touch the place where the my.cnf config file and mysqlmanager.passwd
+# (MySQL Instance Manager password file) might be located
# Just to make sure it's in the file list and marked as a config file
touch $RBR%{_sysconfdir}/my.cnf
+touch $RBR%{_sysconfdir}/mysqlmanager.passwd
%pre server
# Shut down a previously installed server first
@@ -512,8 +515,6 @@ fi
%doc %attr(644, root, root) %{_infodir}/mysql.info*
-%doc %attr(644, root, man) %{_mandir}/man1/isamchk.1*
-%doc %attr(644, root, man) %{_mandir}/man1/isamlog.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1*
@@ -523,9 +524,8 @@ fi
%doc %attr(644, root, man) %{_mandir}/man1/replace.1*
%ghost %config(noreplace,missingok) %{_sysconfdir}/my.cnf
+%ghost %config(noreplace,missingok) %{_sysconfdir}/mysqlmanager.passwd
-%attr(755, root, root) %{_bindir}/isamchk
-%attr(755, root, root) %{_bindir}/isamlog
%attr(755, root, root) %{_bindir}/my_print_defaults
%attr(755, root, root) %{_bindir}/myisamchk
%attr(755, root, root) %{_bindir}/myisam_ftdump
@@ -546,7 +546,6 @@ fi
%attr(755, root, root) %{_bindir}/mysqld_safe
%attr(755, root, root) %{_bindir}/mysqlhotcopy
%attr(755, root, root) %{_bindir}/mysqltest
-%attr(755, root, root) %{_bindir}/pack_isam
%attr(755, root, root) %{_bindir}/perror
%attr(755, root, root) %{_bindir}/replace
%attr(755, root, root) %{_bindir}/resolve_stack_dump
@@ -554,6 +553,7 @@ fi
%attr(755, root, root) %{_bindir}/safe_mysqld
%attr(755, root, root) %{_sbindir}/mysqld
+%attr(755, root, root) %{_sbindir}/mysqlmanager
%attr(755, root, root) %{_sbindir}/rcmysql
%attr(644, root, root) %{_libdir}/mysql/mysqld.sym
@@ -626,7 +626,6 @@ fi
%{_includedir}/mysql/*
%{_libdir}/mysql/libdbug.a
%{_libdir}/mysql/libheap.a
-%{_libdir}/mysql/libmerge.a
%if %{have_libgcc}
%{_libdir}/mysql/libmygcc.a
%endif
@@ -638,7 +637,8 @@ fi
%{_libdir}/mysql/libmysqlclient_r.la
%{_libdir}/mysql/libmystrings.a
%{_libdir}/mysql/libmysys.a
-%{_libdir}/mysql/libnisam.a
+%{_libdir}/mysql/libndbclient.a
+%{_libdir}/mysql/libndbclient.la
%{_libdir}/mysql/libvio.a
%files shared
@@ -650,10 +650,10 @@ fi
%defattr(-, root, root, 0755)
%attr(-, root, root) %{_datadir}/sql-bench
%attr(-, root, root) %{_datadir}/mysql-test
-%attr(755, root, root) %{_bindir}/mysql_client_test
-%attr(755, root, root) %{_bindir}/mysqlmanager
-%attr(755, root, root) %{_bindir}/mysqlmanagerc
-%attr(755, root, root) %{_bindir}/mysqlmanager-pwgen
+%attr(755, rott, root) %{_bindir}/mysql_client_test
+%attr(755, root, root) %{_bindir}/mysqltestmanager
+%attr(755, root, root) %{_bindir}/mysqltestmanager-pwgen
+%attr(755, root, root) %{_bindir}/mysqltestmanagerc
%files Max
%defattr(-, root, root, 0755)
@@ -693,6 +693,7 @@ fi
* Mon Jun 06 2005 Lenz Grimmer <lenz@mysql.com>
- added mysql_client_test to the "bench" subpackage (BUG 10676)
+- added the libndbclient static and shared libraries (BUG 10676)
* Wed Jun 01 2005 Lenz Grimmer <lenz@mysql.com>
@@ -714,6 +715,21 @@ fi
- removed the MySQL manual files (html/ps/texi) - they have been removed
from the MySQL sources and are now available seperately.
+* Mon Apr 4 2005 Petr Chardin <petr@mysql.com>
+
+- old mysqlmanager, mysqlmanagerc and mysqlmanager-pwger renamed into
+ mysqltestmanager, mysqltestmanager and mysqltestmanager-pwgen respectively
+
+* Fri Mar 18 2005 Lenz Grimmer <lenz@mysql.com>
+
+- Disabled RAID in the Max binaries once and for all (it has finally been
+ removed from the source tree)
+
+* Sun Feb 20 2005 Petr Chardin <petr@mysql.com>
+
+- Install MySQL Instance Manager together with mysqld, touch mysqlmanager
+ password file
+
* Mon Feb 14 2005 Lenz Grimmer <lenz@mysql.com>
- Fixed the compilation comments and moved them into the separate build sections
@@ -729,6 +745,15 @@ fi
- replaced obsoleted "BuildPrereq" with "BuildRequires" instead
+* Thu Jan 13 2005 Lenz Grimmer <lenz@mysql.com>
+
+- enabled the "Federated" storage engine for the max binary
+
+* Tue Jan 04 2005 Petr Chardin <petr@mysql.com>
+
+- ISAM and merge storage engines were purged. As well as appropriate
+ tools and manpages (isamchk and isamlog)
+
* Thu Dec 31 2004 Lenz Grimmer <lenz@mysql.com>
- enabled the "Archive" storage engine for the max binary
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3c781b7e45b..131f8b1b625 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -17,6 +17,11 @@
## Process this file with automake to create Makefile.in
+if HAVE_YASSL
+ yassl_dummy_link_fix= $(top_srcdir)/extra/yassl/src/dummy.cpp
+else
+ yassl_dummy_link_fix=
+endif
EXTRA_DIST = auto_increment.res auto_increment.tst \
function.res function.tst lock_test.pl lock_test.res \
export.pl big_record.pl \
@@ -35,9 +40,12 @@ noinst_PROGRAMS = insert_test select_test thread_test
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
$(openssl_includes)
LIBS = @CLIENT_LIBS@
-LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la
-mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS)
-mysql_client_test_SOURCES= mysql_client_test.c
+LDADD = @CLIENT_EXTRA_LDFLAGS@ \
+ $(top_builddir)/libmysql/libmysqlclient.la
+mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS)
+mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix)
+insert_test_SOURCES= insert_test.c $(yassl_dummy_link_fix)
+select_test_SOURCES= select_test.c $(yassl_dummy_link_fix)
insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
select_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
@@ -45,7 +53,7 @@ select_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
DEFS = -DUNDEF_THREADS_HACK
thread_test.o: thread_test.c
- $(COMPILE) -c @MT_INCLUDES@ $(INCLUDES) $<
+ $(COMPILE) -c $(INCLUDES) $<
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/tests/connect_test.c b/tests/connect_test.c
index fd81ad635ad..c68ade9f78f 100644
--- a/tests/connect_test.c
+++ b/tests/connect_test.c
@@ -46,6 +46,7 @@ int main(int argc, char **argv)
perror("");
exit(1);
}
+ sock->reconnect= 1;
if (mysql_select_db(sock,"test"))
{
diff --git a/tests/deadlock_test.c b/tests/deadlock_test.c
index 65a0df5c215..ab8158e0cd8 100644
--- a/tests/deadlock_test.c
+++ b/tests/deadlock_test.c
@@ -227,6 +227,7 @@ int main()
!mysql_real_connect(&sel, host, user, pass, db, 0,0,0 ) ||
!mysql_real_connect(&del_ins, host, user, pass, db, 0,0,0 ))
die("Error in mysql_real_connect(): %s", mysql_error(&lock));
+ lock.reconnect= sel.reconnect= del_ins.reconnect= 1;
permute(order, num_queries);
printf("count = %d\n", count);
diff --git a/tests/fork_big2.pl b/tests/fork_big2.pl
index a1c55ac4c11..567cfafa176 100644
--- a/tests/fork_big2.pl
+++ b/tests/fork_big2.pl
@@ -300,7 +300,7 @@ sub test_select
#
# Do big select count(distinct..) over the table
-#
+#
sub test_select_count
{
diff --git a/tests/grant.pl b/tests/grant.pl
index cd6a2eb80de..4f2bd1a61cb 100644
--- a/tests/grant.pl
+++ b/tests/grant.pl
@@ -201,7 +201,7 @@ safe_query("select * from mysql.db where user = '$opt_user'");
safe_query("grant CREATE,UPDATE,DROP on $opt_database.* to $user");
user_connect(0);
user_query("create table $opt_database.test2 (a int not null)");
-user_query("update test,test2 SET test.a=1 where 1");
+user_query("update test,test2 SET test.a=1 where 1",1);
user_query("update test,test2 SET test.a=test2.a where 1",1);
safe_query("grant SELECT on $opt_database.* to $user");
user_connect(0);
@@ -375,7 +375,7 @@ user_query("delete from $opt_database.test where a=2");
user_query("delete from $opt_database.test where A=2");
user_query("update test set b=5 where b>0");
user_query("update test set a=11 where b>5",1);
-user_query("update test,test2 SET test.b=5 where b>0");
+user_query("update test,test2 SET test.b=5 where b>0",1);
user_query("update test,test2 SET test.a=11 where b>0",1);
user_query("update test,test2 SET test.b=test2.a where b>0",1);
user_query("update test,test2 SET test.b=11 where test2.a>0",1);
diff --git a/tests/insert_test.c b/tests/insert_test.c
index 052c12bfdf0..2b659e9eecb 100644
--- a/tests/insert_test.c
+++ b/tests/insert_test.c
@@ -40,6 +40,7 @@ int main(int argc, char **argv)
perror("");
exit(1);
}
+ mysql.reconnect= 1;
num = atoi(argv[2]);
count = 0;
diff --git a/tests/list_test.c b/tests/list_test.c
index 06bf16d2751..1d50e703133 100644
--- a/tests/list_test.c
+++ b/tests/list_test.c
@@ -43,6 +43,7 @@ int main(int argc, char **argv)
perror("");
exit(1);
}
+ mysql.reconnect= 1;
if (mysql_select_db(sock,argv[1]) < 0)
{
diff --git a/tests/mail_to_db.pl b/tests/mail_to_db.pl
index dc40fb3ede6..5ceda392313 100755
--- a/tests/mail_to_db.pl
+++ b/tests/mail_to_db.pl
@@ -17,7 +17,7 @@ use DBI;
use Getopt::Long;
$| = 1;
-$VER = "2.6";
+$VER = "3.0";
$opt_help = 0;
$opt_version = 0;
@@ -26,7 +26,6 @@ $opt_host = undef();
$opt_port = undef();
$opt_socket = undef();
$opt_db = "mail";
-$opt_table = "mails";
$opt_user = undef();
$opt_password = undef();
$opt_max_mail_size = 65536;
@@ -97,7 +96,7 @@ sub main
print "the my.cnf file. This command is available from the latest MySQL\n";
print "distribution.\n";
}
- GetOptions("help","version","host=s","port=i","socket=s","db=s","table=s",
+ GetOptions("help","version","host=s","port=i","socket=s","db=s",
"user=s","password=s","max_mail_size=i","create","test",
"no_path","debug","stop_on_error","stdin")
|| die "Wrong option! See $progname --help\n";
@@ -123,7 +122,6 @@ sub main
|| die "Couldn't connect: $DBI::errstr\n";
die "You must specify the database; use --db=" if (!defined($opt_db));
- die "You must specify the table; use --table=" if (!defined($opt_table));
create_table($dbh) if ($opt_create);
@@ -218,9 +216,9 @@ sub main
print "Total number of mails:\t\t\t\t";
print $mail_inserted + $ignored;
print " (OK: ";
- print sprintf("%.1f", (($mail_inserted / ($mail_inserted+$ignored)) * 100));
+ print sprintf("%.1f", ($mail_inserted + $ignored) ? (($mail_inserted / ($mail_inserted+$ignored)) * 100) : 0.0);
print "% Ignored: ";
- print sprintf("%.1f", (($ignored / ($mail_inserted + $ignored)) * 100));
+ print sprintf("%.1f", ($mail_inserted + $ignored) ? (($ignored / ($mail_inserted + $ignored)) * 100) : 0);
print "%)\n";
print "################################ End Report ##################################\n";
exit(0);
@@ -232,13 +230,15 @@ sub main
sub create_table
{
- my ($dbh) = @_;
+ my ($dbh)= @_;
my ($sth, $query);
- $query = <<EOF;
-CREATE TABLE $opt_table
+ $query= <<EOF;
+CREATE TABLE my_mail
(
mail_id MEDIUMINT UNSIGNED NOT NULL auto_increment,
+ message_id VARCHAR(255),
+ in_reply_to VARCHAR(255),
date DATETIME NOT NULL,
time_zone VARCHAR(20),
mail_from VARCHAR(120) NOT NULL,
@@ -250,6 +250,8 @@ CREATE TABLE $opt_table
file VARCHAR(64) NOT NULL,
hash INTEGER NOT NULL,
KEY (mail_id),
+ KEY (message_id),
+ KEY (in_reply_to),
PRIMARY KEY (mail_from, date, hash))
TYPE=MyISAM COMMENT=''
EOF
@@ -277,7 +279,7 @@ sub process_mail_file
chop if (substr($_, -1, 1) eq "\r");
if ($type ne "message")
{
- if (/^Reply-To: (.*)/i)
+ if (/^Reply-To:\s*(.*)/i)
{
$type = "reply";
$values{$type} = $1;
@@ -302,14 +304,27 @@ sub process_mail_file
$type = "subject";
$values{$type} = $1;
}
+ elsif (/^Message-Id:\s*(.*)/i)
+ {
+ $type = "message_id";
+ s/^\s*(<.*>)\s*/$1/;
+ $values{$type} = $1;
+ }
+ elsif (/^In-Reply-To:\s*(.*)/i)
+ {
+ $type = "in_reply_to";
+ s/^\s*(<.*>)\s*/$1/;
+ $values{$type} = $1;
+ }
elsif (/^Date: (.*)/i)
{
date_parser($1, \%values, $file_name);
$type = "rubbish";
}
- elsif (/^[\w\W-]+:\s/)
+ # Catch those fields that we don't or can't handle (yet)
+ elsif (/^[\w\W-]+:/)
{
- $type = "rubbish";
+ $type = "rubbish";
}
elsif ($_ eq "")
{
@@ -319,6 +334,10 @@ sub process_mail_file
else
{
s/^\s*/ /;
+ if ($type eq 'message_id' || $type eq 'in_reply_to')
+ {
+ s/^\s*(<.*>)\s*/$1/;
+ }
$values{$type} .= $_;
}
}
@@ -421,8 +440,10 @@ sub update_table
goto restart; # Some mails may have duplicated messages
}
- $q = "INSERT INTO $opt_table (";
+ $q = "INSERT INTO my_mail (";
$q.= "mail_id,";
+ $q.= "message_id,";
+ $q.= "in_reply_to,";
$q.= "date,";
$q.= "time_zone,";
$q.= "mail_from,";
@@ -435,6 +456,12 @@ sub update_table
$q.= "hash";
$q.= ") VALUES (";
$q.= "NULL,";
+ $q.= (defined($values->{'message_id'}) ?
+ $dbh->quote($values->{'message_id'}) : "NULL");
+ $q.= ",";
+ $q.= (defined($values->{'in_reply_to'}) ?
+ $dbh->quote($values->{'in_reply_to'}) : "NULL");
+ $q.= ",";
$q.= "'" . $values->{'date'} . "',";
$q.= (defined($values->{'time_zone'}) ?
$dbh->quote($values->{'time_zone'}) : "NULL");
@@ -575,7 +602,6 @@ Options:
--port=# TCP/IP port to be used with connection.
--socket=... MySQL UNIX socket to be used with connection.
--db=... Database to be used.
---table=... Table name for mails.
--user=... Username for connecting.
--password=... Password for the user.
--stdin Read mails from stdin.
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index eadbd37f8f6..84a32b52284 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -21,6 +21,12 @@
Main author: venu ( venu@mysql.com )
***************************************************************************/
+/*
+ XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
+ DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
+*/
+
+
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
@@ -30,6 +36,7 @@
#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
+#define MAX_KEY 64
#define MAX_SERVER_ARGS 64
/* set default options */
@@ -48,6 +55,7 @@ static char current_db[]= "client_test_db";
static unsigned int test_count= 0;
static unsigned int opt_count= 0;
static unsigned int iter_count= 0;
+static my_bool have_innodb= FALSE;
static const char *opt_basedir= "./";
@@ -64,7 +72,7 @@ static const char *embedded_server_groups[]= {
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/mysql_client_test.trace";
struct my_tests_st
{
@@ -213,6 +221,28 @@ static void print_st_error(MYSQL_STMT *stmt, const char *msg)
}
}
+/* Check if the connection has InnoDB tables */
+
+static my_bool check_have_innodb(MYSQL *conn)
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int rc;
+ my_bool result;
+
+ rc= mysql_query(conn, "show variables like 'have_innodb'");
+ myquery(rc);
+ res= mysql_use_result(conn);
+ DIE_UNLESS(res);
+
+ row= mysql_fetch_row(res);
+ DIE_UNLESS(row);
+
+ result= strcmp(row[1], "YES") == 0;
+ mysql_free_result(res);
+ return result;
+}
+
/*
This is to be what mysql_query() is for mysql_real_query(), for
@@ -234,7 +264,7 @@ mysql_simple_prepare(MYSQL *mysql, const char *query)
/* Connect to the server */
-static void client_connect()
+static void client_connect(ulong flag)
{
int rc;
myheader_r("client_connect");
@@ -252,7 +282,7 @@ static void client_connect()
if (!(mysql_real_connect(mysql, opt_host, opt_user,
opt_password, opt_db ? opt_db:"test", opt_port,
- opt_unix_socket, 0)))
+ opt_unix_socket, flag)))
{
opt_silent= 0;
myerror("connection failed");
@@ -260,6 +290,7 @@ static void client_connect()
fprintf(stdout, "\n Check the connection options using --help or -?\n");
exit(1);
}
+ mysql->reconnect= 1;
if (!opt_silent)
fprintf(stdout, " OK");
@@ -268,7 +299,12 @@ static void client_connect()
mysql_autocommit(mysql, TRUE);
if (!opt_silent)
+ {
+ fprintf(stdout, "\nConnected to MySQL server version: %s (%lu)\n",
+ mysql_get_server_info(mysql),
+ (ulong) mysql_get_server_version(mysql));
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);
@@ -277,6 +313,7 @@ static void client_connect()
strxmov(query, "USE ", current_db, NullS);
rc= mysql_query(mysql, query);
myquery(rc);
+ have_innodb= check_have_innodb(mysql);
if (!opt_silent)
fprintf(stdout, " OK");
@@ -533,16 +570,18 @@ int my_process_stmt_result(MYSQL_STMT *stmt)
buffer[i].buffer= (void *) data[i];
buffer[i].is_null= &is_null[i];
}
- my_print_result_metadata(result);
rc= mysql_stmt_bind_result(stmt, buffer);
check_execute(stmt, rc);
+ rc= 1;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*)&rc);
rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
+ my_print_result_metadata(result);
mysql_field_seek(result, 0);
- while (mysql_stmt_fetch(stmt) == 0)
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
{
if (!opt_silent)
{
@@ -575,6 +614,7 @@ int my_process_stmt_result(MYSQL_STMT *stmt)
}
row_count++;
}
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
if (!opt_silent)
{
if (row_count)
@@ -650,13 +690,20 @@ static void verify_col_data(const char *table, const char *col,
/* 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)
+#define verify_prepare_field(result,no,name,org_name,type,table,\
+ org_table,db,length,def) \
+ do_verify_prepare_field((result),(no),(name),(org_name),(type), \
+ (table),(org_table),(db),(length),(def), \
+ __FILE__, __LINE__)
+
+static void do_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,
+ const char *file, int line)
{
MYSQL_FIELD *field;
CHARSET_INFO *cs;
@@ -675,10 +722,12 @@ static void verify_prepare_field(MYSQL_RES *result,
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);
+ if (table)
+ fprintf(stdout, "\n table :`%s`\t(expected: `%s`)",
+ field->table, table);
+ if (org_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 :`%lu`\t(expected: `%lu`)",
field->length, length * cs->mbmaxlen);
@@ -698,16 +747,31 @@ static void verify_prepare_field(MYSQL_RES *result,
expect.
*/
if (cs->mbmaxlen == 1)
- DIE_UNLESS(field->type == type);
- DIE_UNLESS(strcmp(field->table, table) == 0);
- DIE_UNLESS(strcmp(field->org_table, org_table) == 0);
+ {
+ if (field->type != type)
+ {
+ fprintf(stderr,
+ "Expected field type: %d, got type: %d in file %s, line %d\n",
+ (int) type, (int) field->type, file, line);
+ DIE_UNLESS(field->type == type);
+ }
+ }
+ if (table)
+ DIE_UNLESS(strcmp(field->table, table) == 0);
+ if (org_table)
+ DIE_UNLESS(strcmp(field->org_table, org_table) == 0);
DIE_UNLESS(strcmp(field->db, db) == 0);
/*
Character set should be taken into account for multibyte encodings, such
as utf8. Field length is calculated as number of characters * maximum
number of bytes a character can occupy.
*/
- DIE_UNLESS(field->length == length * cs->mbmaxlen);
+ if (length && field->length != length * cs->mbmaxlen)
+ {
+ fprintf(stderr, "Expected field length: %d, got length: %d\n",
+ (int) (length * cs->mbmaxlen), (int) field->length);
+ DIE_UNLESS(field->length == length * cs->mbmaxlen);
+ }
if (def)
DIE_UNLESS(strcmp(field->def, def) == 0);
}
@@ -731,8 +795,8 @@ static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count)
{
ulonglong affected_rows= mysql_stmt_affected_rows(stmt);
if (!opt_silent)
- fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
- affected_rows, exp_count);
+ fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
+ (long) affected_rows, (long) exp_count);
DIE_UNLESS(affected_rows == exp_count);
}
@@ -743,8 +807,8 @@ static void verify_affected_rows(ulonglong exp_count)
{
ulonglong affected_rows= mysql_affected_rows(mysql);
if (!opt_silent)
- fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
- affected_rows, exp_count);
+ fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
+ (long) affected_rows, (long) exp_count);
DIE_UNLESS(affected_rows == exp_count);
}
@@ -763,6 +827,7 @@ static void verify_field_count(MYSQL_RES *result, uint exp_count)
/* Utility function to execute a query using prepare-execute */
+#ifndef EMBEDDED_LIBRARY
static void execute_prepare_query(const char *query, ulonglong exp_count)
{
MYSQL_STMT *stmt;
@@ -777,13 +842,13 @@ static void execute_prepare_query(const char *query, ulonglong exp_count)
affected_rows= mysql_stmt_affected_rows(stmt);
if (!opt_silent)
- fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
- affected_rows, exp_count);
+ fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)",
+ (long) affected_rows, (long) exp_count);
DIE_UNLESS(affected_rows == exp_count);
mysql_stmt_close(stmt);
}
-
+#endif
/* Store result processing */
@@ -826,6 +891,218 @@ static void client_use_result()
}
+/*
+ Accepts arbitrary number of queries and runs them against the database.
+ Used to fill tables for each test.
+*/
+
+void fill_tables(const char **query_list, unsigned query_count)
+{
+ int rc;
+ const char **query;
+ DBUG_ENTER("fill_tables");
+ for (query= query_list; query < query_list + query_count;
+ ++query)
+ {
+ rc= mysql_query(mysql, *query);
+ myquery(rc);
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*
+ All state of fetch from one statement: statement handle, out buffers,
+ fetch position.
+ See fetch_n for for the only use case.
+*/
+
+enum { MAX_COLUMN_LENGTH= 255 };
+
+typedef struct st_stmt_fetch
+{
+ const char *query;
+ unsigned stmt_no;
+ MYSQL_STMT *handle;
+ my_bool is_open;
+ MYSQL_BIND *bind_array;
+ char **out_data;
+ unsigned long *out_data_length;
+ unsigned column_count;
+ unsigned row_count;
+} Stmt_fetch;
+
+
+/*
+ Create statement handle, prepare it with statement, execute and allocate
+ fetch buffers.
+*/
+
+void stmt_fetch_init(Stmt_fetch *fetch, unsigned stmt_no_arg,
+ const char *query_arg)
+{
+ unsigned long type= CURSOR_TYPE_READ_ONLY;
+ int rc;
+ unsigned i;
+ MYSQL_RES *metadata;
+ DBUG_ENTER("stmt_fetch_init");
+
+ /* Save query and statement number for error messages */
+ fetch->stmt_no= stmt_no_arg;
+ fetch->query= query_arg;
+
+ fetch->handle= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(fetch->handle, fetch->query, strlen(fetch->query));
+ check_execute(fetch->handle, rc);
+
+ /*
+ The attribute is sent to server on execute and asks to open read-only
+ for result set
+ */
+ mysql_stmt_attr_set(fetch->handle, STMT_ATTR_CURSOR_TYPE,
+ (const void*) &type);
+
+ rc= mysql_stmt_execute(fetch->handle);
+ check_execute(fetch->handle, rc);
+
+ /* Find out total number of columns in result set */
+ metadata= mysql_stmt_result_metadata(fetch->handle);
+ fetch->column_count= mysql_num_fields(metadata);
+ mysql_free_result(metadata);
+
+ /*
+ Now allocate bind handles and buffers for output data:
+ calloc memory to reduce number of MYSQL_BIND members we need to
+ set up.
+ */
+
+ fetch->bind_array= (MYSQL_BIND *) calloc(1, sizeof(MYSQL_BIND) *
+ fetch->column_count);
+ fetch->out_data= (char**) calloc(1, sizeof(char*) * fetch->column_count);
+ fetch->out_data_length= (ulong*) calloc(1, sizeof(ulong) *
+ fetch->column_count);
+ for (i= 0; i < fetch->column_count; ++i)
+ {
+ fetch->out_data[i]= (char*) calloc(1, MAX_COLUMN_LENGTH);
+ fetch->bind_array[i].buffer_type= MYSQL_TYPE_STRING;
+ fetch->bind_array[i].buffer= fetch->out_data[i];
+ fetch->bind_array[i].buffer_length= MAX_COLUMN_LENGTH;
+ fetch->bind_array[i].length= fetch->out_data_length + i;
+ }
+
+ mysql_stmt_bind_result(fetch->handle, fetch->bind_array);
+
+ fetch->row_count= 0;
+ fetch->is_open= TRUE;
+
+ /* Ready for reading rows */
+ DBUG_VOID_RETURN;
+}
+
+
+/* Fetch and print one row from cursor */
+
+int stmt_fetch_fetch_row(Stmt_fetch *fetch)
+{
+ int rc;
+ unsigned i;
+ DBUG_ENTER("stmt_fetch_fetch_row");
+
+ if ((rc= mysql_stmt_fetch(fetch->handle)) == 0)
+ {
+ ++fetch->row_count;
+ if (!opt_silent)
+ printf("Stmt %d fetched row %d:\n", fetch->stmt_no, fetch->row_count);
+ for (i= 0; i < fetch->column_count; ++i)
+ {
+ fetch->out_data[i][fetch->out_data_length[i]]= '\0';
+ if (!opt_silent)
+ printf("column %d: %s\n", i+1, fetch->out_data[i]);
+ }
+ }
+ else
+ fetch->is_open= FALSE;
+ DBUG_RETURN(rc);
+}
+
+
+void stmt_fetch_close(Stmt_fetch *fetch)
+{
+ unsigned i;
+ DBUG_ENTER("stmt_fetch_close");
+
+ for (i= 0; i < fetch->column_count; ++i)
+ free(fetch->out_data[i]);
+ free(fetch->out_data);
+ free(fetch->out_data_length);
+ free(fetch->bind_array);
+ mysql_stmt_close(fetch->handle);
+ DBUG_VOID_RETURN;
+}
+
+/*
+ For given array of queries, open query_count cursors and fetch
+ from them in simultaneous manner.
+ In case there was an error in one of the cursors, continue
+ reading from the rest.
+*/
+
+my_bool fetch_n(const char **query_list, unsigned query_count)
+{
+ unsigned open_statements= query_count;
+ int rc, error_count= 0;
+ Stmt_fetch *fetch_array= (Stmt_fetch*) calloc(1, sizeof(Stmt_fetch) *
+ query_count);
+ Stmt_fetch *fetch;
+ DBUG_ENTER("fetch_n");
+
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ {
+ /* Init will exit(1) in case of error */
+ stmt_fetch_init(fetch, fetch - fetch_array,
+ query_list[fetch - fetch_array]);
+ }
+
+ while (open_statements)
+ {
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ {
+ if (fetch->is_open && (rc= stmt_fetch_fetch_row(fetch)))
+ {
+ open_statements--;
+ /*
+ We try to fetch from the rest of the statements in case of
+ error
+ */
+ if (rc != MYSQL_NO_DATA)
+ {
+ fprintf(stderr,
+ "Got error reading rows from statement %d,\n"
+ "query is: %s,\n"
+ "error message: %s", (int) (fetch - fetch_array),
+ fetch->query,
+ mysql_stmt_error(fetch->handle));
+ error_count++;
+ }
+ }
+ }
+ }
+ if (error_count)
+ fprintf(stderr, "Fetch FAILED");
+ else
+ {
+ unsigned total_row_count= 0;
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ total_row_count+= fetch->row_count;
+ if (!opt_silent)
+ printf("Success, total rows fetched: %d\n", total_row_count);
+ }
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ stmt_fetch_close(fetch);
+ free(fetch_array);
+ DBUG_RETURN(error_count != 0);
+}
+
/* Separate thread query to test some cases */
static my_bool thread_query(char *query)
@@ -849,6 +1126,7 @@ static my_bool thread_query(char *query)
error= 1;
goto end;
}
+ l_mysql->reconnect= 1;
if (mysql_query(l_mysql, (char *)query))
{
fprintf(stderr, "Query failed (%s)\n", mysql_error(l_mysql));
@@ -1208,7 +1486,9 @@ static void test_prepare_field_result()
"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_VAR_STRING,
+ verify_prepare_field(result, 4, "char_c", "char_c",
+ (mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING),
"t1", "test_prepare_field_result", current_db, 4, 0);
verify_field_count(result, 5);
@@ -1262,6 +1542,7 @@ static void test_prepare()
double double_data, o_double_data;
ulong length[7], len;
my_bool is_null[7];
+ char llbuf[22];
MYSQL_BIND bind[7];
myheader("test_prepare");
@@ -1376,11 +1657,11 @@ static void test_prepare()
if (!opt_silent)
{
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 big : %s (%lu)", llstr(big_data, llbuf),
+ length[4]);
fprintf(stdout, "\n\t float : %f (%lu)", real_data, length[5]);
fprintf(stdout, "\n\t double : %f (%lu)", double_data, length[6]);
@@ -1719,6 +2000,7 @@ static void test_fetch_null()
myquery(rc);
/* fetch */
+ bzero((char*) bind, sizeof(bind));
for (i= 0; i < (int) array_elements(bind); i++)
{
bind[i].buffer_type= MYSQL_TYPE_LONG;
@@ -2028,7 +2310,7 @@ static void test_ps_conj_select()
check_execute(stmt, rc);
int_data= 1;
- strcpy(str_data, "hh");
+ strmov(str_data, "hh");
str_length= strlen(str_data);
rc= mysql_stmt_execute(stmt);
@@ -2072,7 +2354,9 @@ session_id char(9) NOT NULL, \
"(\"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), "
+ "(\"abq\", 1, 2, 3, 2003-08-30) ");
+ myquery(rc);
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES "
"(\"abw\", 1, 2, 3, 2003-08-30), "
"(\"abe\", 1, 2, 3, 2003-08-30), "
"(\"abr\", 1, 2, 3, 2003-08-30), "
@@ -2787,11 +3071,13 @@ static void test_long_data_str1()
bind[0].buffer= (void *) &data; /* this buffer won't be altered */
bind[0].buffer_length= 16;
bind[0].length= &blob_length;
+ bind[0].error= &bind[0].error_value;
rc= mysql_stmt_bind_result(stmt, bind);
data[16]= 0;
rc= mysql_stmt_fetch(stmt);
- DIE_UNLESS(rc == 0);
+ DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
+ DIE_UNLESS(bind[0].error_value);
DIE_UNLESS(strlen(data) == 16);
DIE_UNLESS(blob_length == max_blob_length);
@@ -3128,7 +3414,7 @@ static void test_bind_result()
MYSQL_STMT *stmt;
int rc;
int nData;
- ulong length, length1;
+ ulong length1;
char szData[100];
MYSQL_BIND bind[2];
my_bool is_null[2];
@@ -3155,10 +3441,10 @@ static void test_bind_result()
/* fetch */
+ bzero((char*) bind, sizeof(bind));
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= MYSQL_TYPE_STRING;
bind[1].buffer= szData; /* string data */
@@ -3193,7 +3479,6 @@ static void test_bind_result()
DIE_UNLESS(strcmp(szData, "MySQL") == 0);
DIE_UNLESS(length1 == 5);
- length= 99;
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
@@ -3227,7 +3512,7 @@ static void test_bind_result_ext()
MYSQL_BIND bind[8];
ulong length[8];
my_bool is_null[8];
-
+ char llbuf[22];
myheader("test_bind_result_ext");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
@@ -3249,6 +3534,7 @@ static void test_bind_result_ext()
rc= mysql_commit(mysql);
myquery(rc);
+ bzero((char*) bind, sizeof(bind));
for (i= 0; i < (int) array_elements(bind); i++)
{
bind[i].length= &length[i];
@@ -3300,7 +3586,7 @@ static void test_bind_result_ext()
fprintf(stdout, "\n data (tiny) : %d", t_data);
fprintf(stdout, "\n data (short) : %d", s_data);
fprintf(stdout, "\n data (int) : %d", i_data);
- fprintf(stdout, "\n data (big) : %lld", b_data);
+ fprintf(stdout, "\n data (big) : %s", llstr(b_data, llbuf));
fprintf(stdout, "\n data (float) : %f", f_data);
fprintf(stdout, "\n data (double) : %f", d_data);
@@ -3367,37 +3653,46 @@ static void test_bind_result_ext1()
rc= mysql_commit(mysql);
myquery(rc);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= (void *) t_data;
bind[0].buffer_length= sizeof(t_data);
+ bind[0].error= &bind[0].error_value;
bind[1].buffer_type= MYSQL_TYPE_FLOAT;
bind[1].buffer= (void *)&s_data;
bind[1].buffer_length= 0;
+ bind[1].error= &bind[1].error_value;
bind[2].buffer_type= MYSQL_TYPE_SHORT;
bind[2].buffer= (void *)&i_data;
bind[2].buffer_length= 0;
+ bind[2].error= &bind[2].error_value;
bind[3].buffer_type= MYSQL_TYPE_TINY;
bind[3].buffer= (void *)&b_data;
bind[3].buffer_length= 0;
+ bind[3].error= &bind[3].error_value;
bind[4].buffer_type= MYSQL_TYPE_LONG;
bind[4].buffer= (void *)&f_data;
bind[4].buffer_length= 0;
+ bind[4].error= &bind[4].error_value;
bind[5].buffer_type= MYSQL_TYPE_STRING;
bind[5].buffer= (void *)d_data;
bind[5].buffer_length= sizeof(d_data);
+ bind[5].error= &bind[5].error_value;
bind[6].buffer_type= MYSQL_TYPE_LONG;
bind[6].buffer= (void *)&bData;
bind[6].buffer_length= 0;
+ bind[6].error= &bind[6].error_value;
bind[7].buffer_type= MYSQL_TYPE_DOUBLE;
bind[7].buffer= (void *)&szData;
bind[7].buffer_length= 0;
+ bind[7].error= &bind[7].error_value;
for (i= 0; i < array_elements(bind); i++)
{
@@ -3415,7 +3710,8 @@ static void test_bind_result_ext1()
check_execute(stmt, rc);
rc= mysql_stmt_fetch(stmt);
- check_execute(stmt, rc);
+ printf("rc=%d\n", rc);
+ DIE_UNLESS(rc == 0);
if (!opt_silent)
{
@@ -3650,6 +3946,7 @@ static void test_fetch_date()
rc= mysql_commit(mysql);
myquery(rc);
+ bzero((char*) bind, sizeof(bind));
for (i= 0; i < array_elements(bind); i++)
{
bind[i].is_null= &is_null[i];
@@ -3931,40 +4228,40 @@ static void test_prepare_ext()
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'))";
+ 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);
@@ -4330,6 +4627,7 @@ static void test_stmt_close()
myerror("connection failed");
exit(1);
}
+ lmysql->reconnect= 1;
if (!opt_silent)
fprintf(stdout, " OK");
@@ -4451,8 +4749,6 @@ static void test_set_variable()
get_bind[1].buffer_type= MYSQL_TYPE_LONG;
get_bind[1].buffer= (void *)&get_count;
- get_bind[1].is_null= 0;
- get_bind[1].length= 0;
rc= mysql_stmt_execute(stmt1);
check_execute(stmt1, rc);
@@ -5056,7 +5352,7 @@ static void test_manual_sample()
affected_rows= mysql_stmt_affected_rows(stmt);
if (!opt_silent)
- fprintf(stdout, "\n total affected rows: %lld", affected_rows);
+ fprintf(stdout, "\n total affected rows: %ld", (ulong) affected_rows);
if (affected_rows != 1) /* validate affected rows */
{
fprintf(stderr, "\n invalid affected rows by MySQL");
@@ -5081,7 +5377,7 @@ static void test_manual_sample()
affected_rows= mysql_stmt_affected_rows(stmt);
if (!opt_silent)
- fprintf(stdout, "\n total affected rows: %lld", affected_rows);
+ fprintf(stdout, "\n total affected rows: %ld", (ulong) affected_rows);
if (affected_rows != 1) /* validate affected rows */
{
fprintf(stderr, "\n invalid affected rows by MySQL");
@@ -5116,7 +5412,6 @@ static void test_prepare_alter()
{
MYSQL_STMT *stmt;
int rc, id;
- long length;
MYSQL_BIND bind[1];
my_bool is_null;
@@ -5151,7 +5446,6 @@ static void test_prepare_alter()
check_execute(stmt, rc);
id= 30;
- length= 0;
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -5222,6 +5516,7 @@ DROP TABLE IF EXISTS test_multi_tab";
fprintf(stdout, "\n connection failed(%s)", mysql_error(mysql_local));
exit(1);
}
+ mysql_local->reconnect= 1;
rc= mysql_query(mysql_local, query);
myquery(rc);
@@ -5236,9 +5531,9 @@ DROP TABLE IF EXISTS test_multi_tab";
mysql_free_result(result);
}
else if (!opt_silent)
- fprintf(stdout, "OK, %lld row(s) affected, %d warning(s)\n",
- mysql_affected_rows(mysql_local),
- mysql_warning_count(mysql_local));
+ fprintf(stdout, "OK, %ld row(s) affected, %ld warning(s)\n",
+ (ulong) mysql_affected_rows(mysql_local),
+ (ulong) mysql_warning_count(mysql_local));
exp_value= (uint) mysql_affected_rows(mysql_local);
if (rows[count] != exp_value)
@@ -5330,6 +5625,7 @@ static void test_prepare_multi_statements()
fprintf(stderr, "\n connection failed(%s)", mysql_error(mysql_local));
exit(1);
}
+ mysql_local->reconnect= 1;
strmov(query, "select 1; select 'another value'");
stmt= mysql_simple_prepare(mysql_local, query);
check_stmt_r(stmt);
@@ -5367,6 +5663,7 @@ static void test_store_result()
myquery(rc);
/* fetch */
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (void *) &nData; /* integer data */
bind[0].length= &length;
@@ -5616,6 +5913,7 @@ static void test_subselect()
MYSQL_STMT *stmt;
int rc, id;
MYSQL_BIND bind[1];
+ DBUG_ENTER("test_subselect");
myheader("test_subselect");
@@ -5721,6 +6019,7 @@ static void test_subselect()
DIE_UNLESS(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
+ DBUG_VOID_RETURN;
}
@@ -5828,7 +6127,7 @@ static void test_bind_date_conv(uint row_count)
for (count= 0; count < row_count; count++)
{
rc= mysql_stmt_fetch(stmt);
- check_execute(stmt, rc);
+ DIE_UNLESS(rc == 0 || rc == MYSQL_DATA_TRUNCATED);
if (!opt_silent)
fprintf(stdout, "\n");
@@ -5844,14 +6143,8 @@ static void test_bind_date_conv(uint row_count)
DIE_UNLESS(tm[i].day == 0 || tm[i].day == day+count);
DIE_UNLESS(tm[i].hour == 0 || tm[i].hour == hour+count);
-#ifdef NOT_USED
- /*
- minute causes problems from date<->time, don't assert, instead
- validate separatly in another routine
- */
DIE_UNLESS(tm[i].minute == 0 || tm[i].minute == minute+count);
DIE_UNLESS(tm[i].second == 0 || tm[i].second == sec+count);
-#endif
DIE_UNLESS(tm[i].second_part == 0 ||
tm[i].second_part == second_part+count);
}
@@ -6082,13 +6375,15 @@ static void test_buffers()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- bzero(buffer, 20); /* Avoid overruns in printf() */
+ bzero(buffer, sizeof(buffer)); /* Avoid overruns in printf() */
+ bzero((char*) bind, sizeof(bind));
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= (void *)buffer;
+ bind[0].error= &bind[0].error_value;
rc= mysql_stmt_bind_result(stmt, bind);
check_execute(stmt, rc);
@@ -6098,7 +6393,8 @@ static void test_buffers()
buffer[1]= 'X';
rc= mysql_stmt_fetch(stmt);
- check_execute(stmt, rc);
+ DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
+ DIE_UNLESS(bind[0].error_value);
if (!opt_silent)
fprintf(stdout, "\n data: %s (%lu)", buffer, length);
DIE_UNLESS(buffer[0] == 'M');
@@ -6132,7 +6428,8 @@ static void test_buffers()
check_execute(stmt, rc);
rc= mysql_stmt_fetch(stmt);
- check_execute(stmt, rc);
+ DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
+ DIE_UNLESS(bind[0].error_value);
if (!opt_silent)
fprintf(stdout, "\n data: %s (%lu)", buffer, length);
DIE_UNLESS(strncmp(buffer, "Popula", 6) == 0);
@@ -6269,10 +6566,9 @@ static void test_fetch_nobuffs()
fprintf(stdout, "\n total rows : %d", rc);
DIE_UNLESS(rc == 1);
+ bzero((char*) bind, sizeof(MYSQL_BIND));
bind[0].buffer_type= MYSQL_TYPE_STRING;
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= (void *)str[1];
@@ -6317,7 +6613,7 @@ static void test_ushort_bug()
ulonglong longlong_value;
int rc;
uchar tiny_value;
-
+ char llbuf[22];
myheader("test_ushort_bug");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ushort");
@@ -6329,7 +6625,8 @@ static void test_ushort_bug()
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);
@@ -6339,24 +6636,23 @@ static void test_ushort_bug()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_SHORT;
bind[0].buffer= (void *)&short_value;
- bind[0].is_null= 0;
+ bind[0].is_unsigned= TRUE;
bind[0].length= &s_length;
bind[1].buffer_type= MYSQL_TYPE_LONG;
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= (void *)&longlong_value;
- bind[2].is_null= 0;
bind[2].length= &ll_length;
bind[3].buffer_type= MYSQL_TYPE_TINY;
bind[3].buffer= (void *)&tiny_value;
- bind[3].is_null= 0;
+ bind[3].is_unsigned= TRUE;
bind[3].length= &t_length;
rc= mysql_stmt_bind_result(stmt, bind);
@@ -6369,7 +6665,8 @@ static void test_ushort_bug()
{
fprintf(stdout, "\n ushort : %d (%ld)", short_value, s_length);
fprintf(stdout, "\n ulong : %lu (%ld)", (ulong) long_value, l_length);
- fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n longlong : %s (%ld)", llstr(longlong_value, llbuf),
+ ll_length);
fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
}
@@ -6404,6 +6701,7 @@ static void test_sshort_bug()
ulonglong longlong_value;
int rc;
uchar tiny_value;
+ char llbuf[22];
myheader("test_sshort_bug");
@@ -6426,24 +6724,22 @@ static void test_sshort_bug()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_SHORT;
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= (void *)&long_value;
- bind[1].is_null= 0;
bind[1].length= &l_length;
bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
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= (void *)&tiny_value;
- bind[3].is_null= 0;
+ bind[3].is_unsigned= TRUE;
bind[3].length= &t_length;
rc= mysql_stmt_bind_result(stmt, bind);
@@ -6456,7 +6752,8 @@ static void test_sshort_bug()
{
fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length);
fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length);
- fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n longlong : %s (%ld)", llstr(longlong_value, llbuf),
+ ll_length);
fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
}
@@ -6491,6 +6788,7 @@ static void test_stiny_bug()
ulonglong longlong_value;
int rc;
uchar tiny_value;
+ char llbuf[22];
myheader("test_stiny_bug");
@@ -6513,24 +6811,21 @@ static void test_stiny_bug()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_SHORT;
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= (void *)&long_value;
- bind[1].is_null= 0;
bind[1].length= &l_length;
bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
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= (void *)&tiny_value;
- bind[3].is_null= 0;
bind[3].length= &t_length;
rc= mysql_stmt_bind_result(stmt, bind);
@@ -6543,7 +6838,8 @@ static void test_stiny_bug()
{
fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length);
fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length);
- fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n longlong : %s (%ld)", llstr(longlong_value, llbuf),
+ ll_length);
fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
}
@@ -6623,10 +6919,10 @@ static void test_field_misc()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= table_type;
bind[0].length= &type_length;
- bind[0].is_null= 0;
bind[0].buffer_length= NAME_LEN;
rc= mysql_stmt_bind_result(stmt, bind);
@@ -6656,7 +6952,8 @@ static void test_field_misc()
verify_prepare_field(result, 0,
"@@table_type", "", /* field and its org name */
- MYSQL_TYPE_STRING, /* field type */
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
"", "", /* table and its org name */
"", type_length, 0); /* db name, length */
@@ -6696,10 +6993,10 @@ static void test_field_misc()
DIE_UNLESS(1 == my_process_stmt_result(stmt));
verify_prepare_field(result, 0,
- "@@max_allowed_packet", "", /* field and its org name */
+ "@@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);
@@ -6857,6 +7154,7 @@ static void test_prepare_grant()
mysql_close(lmysql);
exit(1);
}
+ lmysql->reconnect= 1;
if (!opt_silent)
fprintf(stdout, " OK");
@@ -6932,11 +7230,10 @@ static void test_frm_bug()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= data_dir;
bind[0].buffer_length= FN_REFLEN;
- bind[0].is_null= 0;
- bind[0].length= 0;
bind[1]= bind[0];
rc= mysql_stmt_bind_result(stmt, bind);
@@ -7023,7 +7320,7 @@ static void test_decimal_bug()
*/
bzero((char*) bind, sizeof(bind));
- bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer_type= MYSQL_TYPE_NEWDECIMAL;
bind[0].buffer= (void *)data;
bind[0].buffer_length= 25;
bind[0].is_null= &is_null;
@@ -7032,7 +7329,7 @@ static void test_decimal_bug()
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- strcpy(data, "8.0");
+ strmov(data, "8.0");
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -7050,7 +7347,7 @@ static void test_decimal_bug()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
- strcpy(data, "5.61");
+ strmov(data, "5.61");
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -7075,7 +7372,7 @@ static void test_decimal_bug()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
- strcpy(data, "10.22"); is_null= 0;
+ strmov(data, "10.22"); is_null= 0;
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -7132,23 +7429,33 @@ static void test_explain_bug()
mysql_num_fields(result));
DIE_UNLESS(6 == mysql_num_fields(result));
- verify_prepare_field(result, 0, "Field", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", NAME_LEN, 0);
+ verify_prepare_field(result, 0, "Field", "COLUMN_NAME",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 64, 0);
- verify_prepare_field(result, 1, "Type", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", 40, 0);
+ verify_prepare_field(result, 1, "Type", "COLUMN_TYPE", MYSQL_TYPE_BLOB,
+ 0, 0, "", 0, 0);
- verify_prepare_field(result, 2, "Null", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", 1, 0);
+ verify_prepare_field(result, 2, "Null", "IS_NULLABLE",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 3, 0);
- verify_prepare_field(result, 3, "Key", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", 3, 0);
+ verify_prepare_field(result, 3, "Key", "COLUMN_KEY",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 3, 0);
- verify_prepare_field(result, 4, "Default", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", NAME_LEN, 0);
+ verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 64, 0);
- verify_prepare_field(result, 5, "Extra", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", 20, 0);
+ verify_prepare_field(result, 5, "Extra", "EXTRA",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 20, 0);
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -7183,17 +7490,21 @@ static void test_explain_bug()
"", "", "", 10, 0);
verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", NAME_LEN*64, 0);
+ "", "", "", NAME_LEN*MAX_KEY, 0);
verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN, 0);
- verify_prepare_field(result, 6, "key_len", "",
- (mysql_get_server_version(mysql) <= 50000 ?
- MYSQL_TYPE_LONGLONG : MYSQL_TYPE_VAR_STRING),
- "", "", "",
- (mysql_get_server_version(mysql) <= 50000 ? 3 : 4096),
- 0);
+ if (mysql_get_server_version(mysql) <= 50000)
+ {
+ verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_LONGLONG, "",
+ "", "", 3, 0);
+ }
+ else
+ {
+ verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "",
+ "", "", NAME_LEN*MAX_KEY, 0);
+ }
verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*16, 0);
@@ -7292,6 +7603,7 @@ static void test_drop_temp()
mysql_close(lmysql);
exit(1);
}
+ lmysql->reconnect= 1;
if (!opt_silent)
fprintf(stdout, " OK");
@@ -7504,13 +7816,13 @@ static void test_logs()
if (!opt_silent)
{
- fprintf(stdout, "\n id : %d", id);
- fprintf(stdout, "\n name : %s(%ld)", data, length);
+ fprintf(stdout, "id : %d\n", id);
+ fprintf(stdout, "name : %s(%ld)\n", data, length);
}
DIE_UNLESS(id == 9876);
- DIE_UNLESS(length == 19); /* Due to VARCHAR(20) */
- DIE_UNLESS(strcmp(data, "MySQL - Open Source") == 0);
+ DIE_UNLESS(length == 19 || length == 20); /* Due to VARCHAR(20) */
+ DIE_UNLESS(is_prefix(data, "MySQL - Open Source") == 1);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
@@ -7656,17 +7968,13 @@ static void test_fetch_seek()
stmt= mysql_simple_prepare(mysql, "select * from t1");
check_stmt(stmt);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
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= (void *)c2;
bind[1].buffer_length= sizeof(c2);
- bind[1].is_null= 0;
- bind[1].length= 0;
bind[2]= bind[1];
bind[2].buffer= (void *)c3;
@@ -7756,6 +8064,7 @@ static void test_fetch_offset()
stmt= mysql_simple_prepare(mysql, "select * from t1");
check_stmt(stmt);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= (void *)data;
bind[0].buffer_length= 11;
@@ -7842,6 +8151,7 @@ static void test_fetch_column()
stmt= mysql_simple_prepare(mysql, "select * from t1 order by c2 desc");
check_stmt(stmt);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (void *)&bc1;
bind[0].buffer_length= 0;
@@ -8089,10 +8399,9 @@ static void test_free_result()
stmt= mysql_simple_prepare(mysql, "select * from test_free_result");
check_stmt(stmt);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (void *)&bc1;
- bind[0].buffer_length= 0;
- bind[0].is_null= 0;
bind[0].length= &bl1;
rc= mysql_stmt_execute(stmt);
@@ -8170,6 +8479,7 @@ static void test_free_store_result()
stmt= mysql_simple_prepare(mysql, "select * from test_free_result");
check_stmt(stmt);
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (void *)&bc1;
bind[0].buffer_length= 0;
@@ -8245,13 +8555,13 @@ static void test_sqlmode()
myquery(rc);
/* PIPES_AS_CONCAT */
- strcpy(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\"");
+ strmov(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\"");
if (!opt_silent)
fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
- strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
+ strmov(query, "INSERT INTO test_piping VALUES(?||?)");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
@@ -8277,7 +8587,7 @@ static void test_sqlmode()
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- strcpy(c1, "My"); strcpy(c2, "SQL");
+ strmov(c1, "My"); strmov(c2, "SQL");
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -8287,20 +8597,20 @@ static void test_sqlmode()
rc= mysql_query(mysql, "DELETE FROM test_piping");
myquery(rc);
- strcpy(query, "SELECT connection_id ()");
+ strmov(query, "SELECT connection_id ()");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
check_stmt_r(stmt);
/* ANSI */
- strcpy(query, "SET SQL_MODE= \"ANSI\"");
+ strmov(query, "SET SQL_MODE= \"ANSI\"");
if (!opt_silent)
fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
- strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
+ strmov(query, "INSERT INTO test_piping VALUES(?||?)");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
@@ -8311,7 +8621,7 @@ static void test_sqlmode()
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- strcpy(c1, "My"); strcpy(c2, "SQL");
+ strmov(c1, "My"); strmov(c2, "SQL");
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -8319,7 +8629,7 @@ static void test_sqlmode()
verify_col_data("test_piping", "name", "MySQL");
/* ANSI mode spaces ... */
- strcpy(query, "SELECT connection_id ()");
+ strmov(query, "SELECT connection_id ()");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
@@ -8339,13 +8649,13 @@ static void test_sqlmode()
mysql_stmt_close(stmt);
/* IGNORE SPACE MODE */
- strcpy(query, "SET SQL_MODE= \"IGNORE_SPACE\"");
+ strmov(query, "SET SQL_MODE= \"IGNORE_SPACE\"");
if (!opt_silent)
fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
- strcpy(query, "SELECT connection_id ()");
+ strmov(query, "SELECT connection_id ()");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
@@ -8560,10 +8870,6 @@ static void test_bug1500()
rc= my_process_stmt_result(stmt);
DIE_UNLESS(rc == 1);
- /*
- 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 */
@@ -8734,7 +9040,7 @@ static void test_subqueries()
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";
- myheader("test_subquery");
+ myheader("test_subqueries");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
myquery(rc);
@@ -8785,7 +9091,7 @@ static void test_distinct()
const char *query=
"SELECT 2+count(distinct b), group_concat(a) FROM t1 group by a";
- myheader("test_subquery");
+ myheader("test_distinct");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
@@ -8854,7 +9160,7 @@ static void test_bug2248()
/* This too should not hang but should return proper error */
rc= mysql_stmt_fetch(stmt);
- DIE_UNLESS(rc == MYSQL_NO_DATA);
+ DIE_UNLESS(rc == 1);
/* This too should not hang but should not bark */
rc= mysql_stmt_store_result(stmt);
@@ -8863,7 +9169,7 @@ static void test_bug2248()
/* This should return proper error */
rc= mysql_stmt_fetch(stmt);
check_execute_r(stmt, rc);
- DIE_UNLESS(rc == MYSQL_NO_DATA);
+ DIE_UNLESS(rc == 1);
mysql_stmt_close(stmt);
@@ -9583,7 +9889,7 @@ static void test_bug3035()
{
MYSQL_STMT *stmt;
int rc;
- MYSQL_BIND bind_array[12];
+ MYSQL_BIND bind_array[12], *bind= bind_array, *bind_end= bind + 12;
int8 int8_val;
uint8 uint8_val;
int16 int16_val;
@@ -9634,7 +9940,10 @@ static void test_bug3035()
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
- bzero(bind_array, sizeof(bind_array));
+ bzero((char*) bind_array, sizeof(bind_array));
+
+ for (bind= bind_array; bind < bind_end; bind++)
+ bind->error= &bind->error_value;
bind_array[0].buffer_type= MYSQL_TYPE_TINY;
bind_array[0].buffer= (void *) &int8_val;
@@ -9742,7 +10051,15 @@ static void test_bug3035()
DIE_UNLESS(!strcmp(ulonglong_as_string, "0"));
rc= mysql_stmt_fetch(stmt);
- check_execute(stmt, rc);
+
+ if (!opt_silent)
+ {
+ printf("Truncation mask: ");
+ for (bind= bind_array; bind < bind_end; bind++)
+ printf("%d", (int) bind->error_value);
+ printf("\n");
+ }
+ DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED || rc == 0);
DIE_UNLESS(int8_val == int8_max);
DIE_UNLESS(uint8_val == uint8_max);
@@ -9832,7 +10149,7 @@ static void test_bug1664()
verify_param_count(stmt, 2);
- bzero(&bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= (void *)str_data;
@@ -9996,7 +10313,7 @@ static void test_union_param()
my_bool my_null= FALSE;
myheader("test_union_param");
- strcpy(my_val, "abc");
+ strmov(my_val, "abc");
query= (char*)"select ? as my_col union distinct select ?";
stmt= mysql_simple_prepare(mysql, query);
@@ -10072,7 +10389,7 @@ static void test_ps_i18n()
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
- bzero(bind_array, sizeof(bind_array));
+ bzero((char*) bind_array, sizeof(bind_array));
bind_array[0].buffer_type= MYSQL_TYPE_STRING;
bind_array[0].buffer= (void *) koi8;
@@ -10256,7 +10573,7 @@ static void test_bug3796()
check_execute(stmt, rc);
/* Bind input buffers */
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= (void *) concat_arg0;
@@ -10278,14 +10595,14 @@ static void test_bug3796()
if (!opt_silent)
printf("Concat result: '%s'\n", out_buff);
check_execute(stmt, rc);
- strcpy(canonical_buff, concat_arg0);
+ strmov(canonical_buff, concat_arg0);
strcat(canonical_buff, "ONE");
DIE_UNLESS(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");
+ strmov(canonical_buff + strlen(concat_arg0), "TWO");
DIE_UNLESS(strlen(canonical_buff) == out_length &&
strncmp(out_buff, canonical_buff, out_length) == 0);
if (!opt_silent)
@@ -10323,11 +10640,11 @@ static void test_bug4026()
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));
+ bzero((char*) bind, sizeof(bind));
+ bzero((char*) &time_in, sizeof(time_in));
+ bzero((char*) &time_out, sizeof(time_out));
+ bzero((char*) &datetime_in, sizeof(datetime_in));
+ bzero((char*) &datetime_out, sizeof(datetime_out));
bind[0].buffer_type= MYSQL_TYPE_TIME;
bind[0].buffer= (void *) &time_in;
@@ -10405,7 +10722,7 @@ static void test_bug4079()
check_execute(stmt, rc);
/* Bind input buffers */
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (void *) &res;
@@ -10474,13 +10791,13 @@ static void test_bug4030()
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));
+ bzero((char*) bind, sizeof(bind));
+ bzero((char*) &time_canonical, sizeof(time_canonical));
+ bzero((char*) &time_out, sizeof(time_out));
+ bzero((char*) &date_canonical, sizeof(date_canonical));
+ bzero((char*) &date_out, sizeof(date_out));
+ bzero((char*) &datetime_canonical, sizeof(datetime_canonical));
+ bzero((char*) &datetime_out, sizeof(datetime_out));
bind[0].buffer_type= MYSQL_TYPE_TIME;
bind[0].buffer= (void *) &time_out;
@@ -10526,6 +10843,438 @@ static void test_bug4030()
mysql_stmt_close(stmt);
}
+static void test_view()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ MYSQL_BIND bind[1];
+ char str_data[50];
+ ulong length = 0L;
+ long is_null = 0L;
+ const char *query=
+ "SELECT COUNT(*) FROM v1 WHERE SERVERNAME=?";
+
+ myheader("test_view");
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2,t3,v1");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,t1,t2,t3");
+ myquery(rc);
+ rc= mysql_query(mysql,"CREATE TABLE t1 ("
+ " SERVERGRP varchar(20) NOT NULL default '', "
+ " DBINSTANCE varchar(20) NOT NULL default '', "
+ " PRIMARY KEY (SERVERGRP)) "
+ " CHARSET=latin1 collate=latin1_bin");
+ myquery(rc);
+ rc= mysql_query(mysql,"CREATE TABLE t2 ("
+ " SERVERNAME varchar(20) NOT NULL, "
+ " SERVERGRP varchar(20) NOT NULL, "
+ " PRIMARY KEY (SERVERNAME)) "
+ " CHARSET=latin1 COLLATE latin1_bin");
+ myquery(rc);
+ rc= mysql_query(mysql,
+ "CREATE TABLE t3 ("
+ " SERVERGRP varchar(20) BINARY NOT NULL, "
+ " TABNAME varchar(30) NOT NULL, MAPSTATE char(1) NOT NULL, "
+ " ACTSTATE char(1) NOT NULL , "
+ " LOCAL_NAME varchar(30) NOT NULL, "
+ " CHG_DATE varchar(8) NOT NULL default '00000000', "
+ " CHG_TIME varchar(6) NOT NULL default '000000', "
+ " MXUSER varchar(12) NOT NULL default '', "
+ " PRIMARY KEY (SERVERGRP, TABNAME, MAPSTATE, ACTSTATE, "
+ " LOCAL_NAME)) CHARSET=latin1 COLLATE latin1_bin");
+ myquery(rc);
+ rc= mysql_query(mysql,"CREATE VIEW v1 AS select sql_no_cache"
+ " T0001.SERVERNAME AS SERVERNAME, T0003.TABNAME AS"
+ " TABNAME,T0003.LOCAL_NAME AS LOCAL_NAME,T0002.DBINSTANCE AS"
+ " DBINSTANCE from t2 T0001 join t1 T0002 join t3 T0003 where"
+ " ((T0002.SERVERGRP = T0001.SERVERGRP) and"
+ " (T0002.SERVERGRP = T0003.SERVERGRP)"
+ " and (T0003.MAPSTATE = _latin1'A') and"
+ " (T0003.ACTSTATE = _latin1' '))");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ check_execute(stmt, rc);
+
+ strmov(str_data, "TEST");
+ bzero((char*) bind, sizeof(bind));
+ bind[0].buffer_type= FIELD_TYPE_STRING;
+ bind[0].buffer= (char *)&str_data;
+ bind[0].buffer_length= 50;
+ bind[0].length= &length;
+ length= 4;
+ bind[0].is_null= (char*)&is_null;
+ 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);
+ assert(1 == my_process_stmt_result(stmt));
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1,t2,t3");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ myquery(rc);
+}
+
+
+static void test_view_where()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query=
+ "select v1.c,v2.c from v1, v2";
+
+ myheader("test_view_where");
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1,v2");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,v2,t1");
+ myquery(rc);
+ rc= mysql_query(mysql,"CREATE TABLE t1 (a int, b int)");
+ myquery(rc);
+ rc= mysql_query(mysql,"insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10)");
+ myquery(rc);
+ rc= mysql_query(mysql,"create view v1 (c) as select b from t1 where a<3");
+ myquery(rc);
+ rc= mysql_query(mysql,"create view v2 (c) as select b from t1 where a>=3");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ check_execute(stmt, rc);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ assert(4 == my_process_stmt_result(stmt));
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP VIEW v1, v2");
+ myquery(rc);
+}
+
+
+static void test_view_2where()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ MYSQL_BIND bind[8];
+ char parms[8][100];
+ ulong length[8];
+ const char *query=
+ "select relid, report, handle, log_group, username, variant, type, "
+ "version, erfdat, erftime, erfname, aedat, aetime, aename, dependvars, "
+ "inactive from V_LTDX where mandt = ? and relid = ? and report = ? and "
+ "handle = ? and log_group = ? and username in ( ? , ? ) and type = ?";
+
+ myheader("test_view_2where");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS LTDX");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS V_LTDX");
+ myquery(rc);
+ rc= mysql_query(mysql,
+ "CREATE TABLE LTDX (MANDT char(3) NOT NULL default '000', "
+ " RELID char(2) NOT NULL, REPORT varchar(40) NOT NULL,"
+ " HANDLE varchar(4) NOT NULL, LOG_GROUP varchar(4) NOT NULL,"
+ " USERNAME varchar(12) NOT NULL,"
+ " VARIANT varchar(12) NOT NULL,"
+ " TYPE char(1) NOT NULL, SRTF2 int(11) NOT NULL,"
+ " VERSION varchar(6) NOT NULL default '000000',"
+ " ERFDAT varchar(8) NOT NULL default '00000000',"
+ " ERFTIME varchar(6) NOT NULL default '000000',"
+ " ERFNAME varchar(12) NOT NULL,"
+ " AEDAT varchar(8) NOT NULL default '00000000',"
+ " AETIME varchar(6) NOT NULL default '000000',"
+ " AENAME varchar(12) NOT NULL,"
+ " DEPENDVARS varchar(10) NOT NULL,"
+ " INACTIVE char(1) NOT NULL, CLUSTR smallint(6) NOT NULL,"
+ " CLUSTD blob,"
+ " PRIMARY KEY (MANDT, RELID, REPORT, HANDLE, LOG_GROUP, "
+ "USERNAME, VARIANT, TYPE, SRTF2))"
+ " CHARSET=latin1 COLLATE latin1_bin");
+ myquery(rc);
+ rc= mysql_query(mysql,
+ "CREATE VIEW V_LTDX AS select T0001.MANDT AS "
+ " MANDT,T0001.RELID AS RELID,T0001.REPORT AS "
+ " REPORT,T0001.HANDLE AS HANDLE,T0001.LOG_GROUP AS "
+ " LOG_GROUP,T0001.USERNAME AS USERNAME,T0001.VARIANT AS "
+ " VARIANT,T0001.TYPE AS TYPE,T0001.VERSION AS "
+ " VERSION,T0001.ERFDAT AS ERFDAT,T0001.ERFTIME AS "
+ " ERFTIME,T0001.ERFNAME AS ERFNAME,T0001.AEDAT AS "
+ " AEDAT,T0001.AETIME AS AETIME,T0001.AENAME AS "
+ " AENAME,T0001.DEPENDVARS AS DEPENDVARS,T0001.INACTIVE AS "
+ " INACTIVE from LTDX T0001 where (T0001.SRTF2 = 0)");
+ myquery(rc);
+ bzero((char*) bind, sizeof(bind));
+ for (i=0; i < 8; i++) {
+ strmov(parms[i], "1");
+ bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+ bind[i].buffer = (char *)&parms[i];
+ bind[i].buffer_length = 100;
+ bind[i].is_null = 0;
+ bind[i].length = &length[i];
+ length[i] = 1;
+ }
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ 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(0 == my_process_stmt_result(stmt));
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP VIEW V_LTDX");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP TABLE LTDX");
+ myquery(rc);
+}
+
+
+static void test_view_star()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ MYSQL_BIND bind[8];
+ char parms[8][100];
+ ulong length[8];
+ const char *query= "SELECT * FROM vt1 WHERE a IN (?,?)";
+
+ myheader("test_view_star");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, vt1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS t1, vt1");
+ myquery(rc);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ myquery(rc);
+ rc= mysql_query(mysql, "CREATE VIEW vt1 AS SELECT a FROM t1");
+ myquery(rc);
+ bzero((char*) bind, sizeof(bind));
+ for (i= 0; i < 2; i++) {
+ sprintf((char *)&parms[i], "%d", i);
+ bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+ bind[i].buffer = (char *)&parms[i];
+ bind[i].buffer_length = 100;
+ bind[i].is_null = 0;
+ bind[i].length = &length[i];
+ length[i] = 1;
+ }
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ 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);
+ assert(0 == my_process_stmt_result(stmt));
+ }
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP VIEW vt1");
+ myquery(rc);
+}
+
+
+static void test_view_insert()
+{
+ MYSQL_STMT *insert_stmt, *select_stmt;
+ int rc, i;
+ MYSQL_BIND bind[1];
+ int my_val = 0;
+ ulong my_length = 0L;
+ long my_null = 0L;
+ const char *query=
+ "insert into v1 values (?)";
+
+ myheader("test_view_insert");
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1");
+ myquery(rc);
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS t1,v1");
+ myquery(rc);
+
+ rc= mysql_query(mysql,"create table t1 (a int, primary key (a))");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "create view v1 as select a from t1 where a>=1");
+ myquery(rc);
+
+ insert_stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(insert_stmt, query, strlen(query));
+ check_execute(insert_stmt, rc);
+ query= "select * from t1";
+ select_stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(select_stmt, query, strlen(query));
+ check_execute(select_stmt, rc);
+
+ 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;
+ rc= mysql_stmt_bind_param(insert_stmt, bind);
+ check_execute(insert_stmt, rc);
+
+ for (i= 0; i < 3; i++)
+ {
+ my_val= i;
+
+ rc= mysql_stmt_execute(insert_stmt);
+ check_execute(insert_stmt, rc);
+
+ rc= mysql_stmt_execute(select_stmt);
+ check_execute(select_stmt, rc);
+ assert(i + 1 == (int) my_process_stmt_result(select_stmt));
+ }
+ mysql_stmt_close(insert_stmt);
+ mysql_stmt_close(select_stmt);
+
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+}
+
+
+static void test_left_join_view()
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query=
+ "select t1.a, v1.x from t1 left join v1 on (t1.a= v1.x);";
+
+ myheader("test_left_join_view");
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,t1");
+ myquery(rc);
+ rc= mysql_query(mysql,"CREATE TABLE t1 (a int)");
+ myquery(rc);
+ rc= mysql_query(mysql,"insert into t1 values (1), (2), (3)");
+ myquery(rc);
+ rc= mysql_query(mysql,"create view v1 (x) as select a from t1 where a > 1");
+ myquery(rc);
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ check_execute(stmt, rc);
+
+ for (i= 0; i < 3; i++)
+ {
+ 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 VIEW v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+}
+
+
+static void test_view_insert_fields()
+{
+ MYSQL_STMT *stmt;
+ char parm[11][1000];
+ ulong l[11];
+ int rc, i;
+ MYSQL_BIND bind[11];
+ const char *query= "INSERT INTO `v1` ( `K1C4` ,`K2C4` ,`K3C4` ,`K4N4` ,`F1C4` ,`F2I4` ,`F3N5` ,`F7F8` ,`F6N4` ,`F5C8` ,`F9D8` ) VALUES( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? )";
+
+ myheader("test_view_insert_fields");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS t1, v1");
+ myquery(rc);
+ rc= mysql_query(mysql,
+ "CREATE TABLE t1 (K1C4 varchar(4) NOT NULL,"
+ "K2C4 varchar(4) NOT NULL, K3C4 varchar(4) NOT NULL,"
+ "K4N4 varchar(4) NOT NULL default '0000',"
+ "F1C4 varchar(4) NOT NULL, F2I4 int(11) NOT NULL,"
+ "F3N5 varchar(5) NOT NULL default '00000',"
+ "F4I4 int(11) NOT NULL default '0', F5C8 varchar(8) NOT NULL,"
+ "F6N4 varchar(4) NOT NULL default '0000',"
+ "F7F8 double NOT NULL default '0',"
+ "F8F8 double NOT NULL default '0',"
+ "F9D8 decimal(8,2) NOT NULL default '0.00',"
+ "PRIMARY KEY (K1C4,K2C4,K3C4,K4N4)) "
+ "CHARSET=latin1 COLLATE latin1_bin");
+ myquery(rc);
+ rc= mysql_query(mysql,
+ "CREATE VIEW v1 AS select sql_no_cache "
+ " K1C4 AS K1C4, K2C4 AS K2C4, K3C4 AS K3C4, K4N4 AS K4N4, "
+ " F1C4 AS F1C4, F2I4 AS F2I4, F3N5 AS F3N5,"
+ " F7F8 AS F7F8, F6N4 AS F6N4, F5C8 AS F5C8, F9D8 AS F9D8"
+ " from t1 T0001");
+
+ bzero((char*) bind, sizeof(bind));
+ for (i= 0; i < 11; i++)
+ {
+ l[i]= 20;
+ bind[i].buffer_type= MYSQL_TYPE_STRING;
+ bind[i].is_null= 0;
+ bind[i].buffer= (char *)&parm[i];
+
+ strmov(parm[i], "1");
+ bind[i].buffer_length= 2;
+ bind[i].length= &l[i];
+ }
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ mysql_stmt_close(stmt);
+
+ query= "select * from t1";
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ 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 VIEW v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+
+}
static void test_bug5126()
{
@@ -10557,7 +11306,7 @@ static void test_bug5126()
check_execute(stmt, rc);
/* Bind output buffers */
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= &c1;
@@ -10603,8 +11352,8 @@ static void test_bug4231()
check_execute(stmt, rc);
/* Bind input buffers */
- bzero(bind, sizeof(bind));
- bzero(tm, sizeof(tm));
+ bzero((char*) bind, sizeof(bind));
+ bzero((char*) tm, sizeof(tm));
bind[0].buffer_type= MYSQL_TYPE_DATE;
bind[0].buffer= &tm[0];
@@ -10664,13 +11413,13 @@ static void test_bug5399()
myheader("test_bug5399");
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= &no;
for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt)
{
- sprintf(buff, "select %d", stmt - stmt_list);
+ sprintf(buff, "select %d", (int) (stmt - stmt_list));
*stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(*stmt, buff, strlen(buff));
check_execute(*stmt, rc);
@@ -10824,7 +11573,7 @@ static void test_bug5194()
param_str_length= strlen(param_str);
/* setup bind array */
- bzero(bind, MAX_PARAM_COUNT * sizeof(MYSQL_BIND));
+ bzero((char*) bind, MAX_PARAM_COUNT * sizeof(MYSQL_BIND));
for (i= 0; i < MAX_PARAM_COUNT; ++i)
{
bind[i].buffer_type= MYSQL_TYPE_FLOAT;
@@ -10865,7 +11614,7 @@ static void test_bug5194()
if (!opt_silent)
printf("Insert: query length= %d, row count= %d, param count= %lu\n",
- strlen(query), nrows, mysql_stmt_param_count(stmt));
+ (int) strlen(query), nrows, mysql_stmt_param_count(stmt));
/* bind the parameter array and execute the query */
rc= mysql_stmt_bind_param(stmt, bind);
@@ -10942,7 +11691,7 @@ static void test_bug6049()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = &buffer;
bind[0].buffer_length = sizeof(buffer);
@@ -10991,7 +11740,7 @@ static void test_bug6058()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = &buffer;
bind[0].buffer_length = sizeof(buffer);
@@ -11018,14 +11767,13 @@ static void test_bug6059()
{
MYSQL_STMT *stmt;
const char *stmt_text;
- int rc;
myheader("test_bug6059");
stmt_text= "SELECT 'foo' INTO OUTFILE 'x.3'";
stmt= mysql_stmt_init(mysql);
- rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ (void) mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
DIE_UNLESS(mysql_stmt_field_count(stmt) == 0);
mysql_stmt_close(stmt);
}
@@ -11060,7 +11808,7 @@ static void test_bug6046()
check_execute(stmt, rc);
b= 1;
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer= &b;
bind[0].buffer_type= MYSQL_TYPE_SHORT;
@@ -11077,6 +11825,62 @@ static void test_bug6046()
}
+
+static void test_basic_cursors()
+{
+ const char *basic_tables[]=
+ {
+ "DROP TABLE IF EXISTS t1, t2",
+
+ "CREATE TABLE t1 "
+ "(id INTEGER NOT NULL PRIMARY KEY, "
+ " name VARCHAR(20) NOT NULL)",
+
+ "INSERT INTO t1 (id, name) VALUES "
+ " (2, 'Ja'), (3, 'Ede'), "
+ " (4, 'Haag'), (5, 'Kabul'), "
+ " (6, 'Almere'), (7, 'Utrecht'), "
+ " (8, 'Qandahar'), (9, 'Amsterdam'), "
+ " (10, 'Amersfoort'), (11, 'Constantine')",
+
+ "CREATE TABLE t2 "
+ "(id INTEGER NOT NULL PRIMARY KEY, "
+ " name VARCHAR(20) NOT NULL)",
+
+ "INSERT INTO t2 (id, name) VALUES "
+ " (4, 'Guam'), (5, 'Aruba'), "
+ " (6, 'Angola'), (7, 'Albania'), "
+ " (8, 'Anguilla'), (9, 'Argentina'), "
+ " (10, 'Azerbaijan'), (11, 'Afghanistan'), "
+ " (12, 'Burkina Faso'), (13, 'Faroe Islands')"
+ };
+ const char *queries[]=
+ {
+ "SELECT * FROM t1",
+ "SELECT * FROM t2"
+ };
+
+ DBUG_ENTER("test_basic_cursors");
+ myheader("test_basic_cursors");
+
+ fill_tables(basic_tables, sizeof(basic_tables)/sizeof(*basic_tables));
+
+ fetch_n(queries, sizeof(queries)/sizeof(*queries));
+ DBUG_VOID_RETURN;
+}
+
+
+static void test_cursors_with_union()
+{
+ const char *queries[]=
+ {
+ "SELECT t1.name FROM t1 UNION SELECT t2.name FROM t2",
+ "SELECT t1.id FROM t1 WHERE t1.id < 5"
+ };
+ myheader("test_cursors_with_union");
+ fetch_n(queries, sizeof(queries)/sizeof(*queries));
+}
+
/*
Altough mysql_create_db(), mysql_rm_db() are deprecated since 4.0 they
should not crash server and should not hang in case of errors.
@@ -11115,6 +11919,7 @@ static void test_bug6096()
MYSQL_FIELD *query_field_list, *stmt_field_list;
ulong query_field_count, stmt_field_count;
int rc;
+ my_bool update_max_length= TRUE;
uint i;
myheader("test_bug6096");
@@ -11150,8 +11955,8 @@ static void test_bug6096()
check_execute(stmt, rc);
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- rc= 1;
- mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*)&rc);
+ mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH,
+ (void*) &update_max_length);
mysql_stmt_store_result(stmt);
stmt_metadata= mysql_stmt_result_metadata(stmt);
stmt_field_list= mysql_fetch_fields(stmt_metadata);
@@ -11182,7 +11987,7 @@ static void test_bug6096()
/* Bind and fetch the data */
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
for (i= 0; i < stmt_field_count; ++i)
{
bind[i].buffer_type= MYSQL_TYPE_STRING;
@@ -11237,7 +12042,7 @@ static void test_datetime_ranges()
check_stmt(stmt);
verify_param_count(stmt, 6);
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
for (i= 0; i < 6; i++)
{
bind[i].buffer_type= MYSQL_TYPE_DATETIME;
@@ -11326,7 +12131,7 @@ static void test_datetime_ranges()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- DIE_UNLESS(mysql_warning_count(mysql) != 2);
+ DIE_UNLESS(mysql_warning_count(mysql) == 2);
verify_col_data("t1", "day_ovfl", "838:59:59");
verify_col_data("t1", "day", "828:30:30");
@@ -11368,7 +12173,7 @@ static void test_bug4172()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= f;
bind[0].buffer_length= sizeof(f);
@@ -11435,7 +12240,7 @@ static void test_conversion()
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
check_execute(stmt, rc);
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
bind[0].buffer= buff;
bind[0].length= &length;
bind[0].buffer_type= MYSQL_TYPE_STRING;
@@ -11498,7 +12303,7 @@ static void test_rewind(void)
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
check_execute(stmt, rc);
- bzero(&bind,sizeof(MYSQL_BIND));
+ bzero((char*) &bind, sizeof(MYSQL_BIND));
bind.buffer_type= MYSQL_TYPE_LONG;
bind.buffer= (void *)&Data; /* this buffer won't be altered */
bind.length= &length;
@@ -11537,6 +12342,299 @@ static void test_rewind(void)
}
+static void test_truncation()
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ uint bind_count;
+ MYSQL_BIND *bind_array, *bind;
+
+ myheader("test_truncation");
+
+ /* Prepare the test table */
+ rc= mysql_query(mysql, "drop table if exists t1");
+ myquery(rc);
+
+ stmt_text= "create table t1 ("
+ "i8 tinyint, ui8 tinyint unsigned, "
+ "i16 smallint, i16_1 smallint, "
+ "ui16 smallint unsigned, i32 int, i32_1 int, "
+ "d double, d_1 double, ch char(30), ch_1 char(30), "
+ "tx text, tx_1 text, ch_2 char(30) "
+ ")";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "insert into t1 VALUES ("
+ "-10, " /* i8 */
+ "200, " /* ui8 */
+ "32000, " /* i16 */
+ "-32767, " /* i16_1 */
+ "64000, " /* ui16 */
+ "1073741824, " /* i32 */
+ "1073741825, " /* i32_1 */
+ "123.456, " /* d */
+ "-12345678910, " /* d_1 */
+ "'111111111111111111111111111111',"/* ch */
+ "'abcdef', " /* ch_1 */
+ "'12345 ', " /* tx */
+ "'12345.67 ', " /* tx_1 */
+ "'12345.67abc'" /* ch_2 */
+ ")";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "select i8 c1, i8 c2, ui8 c3, i16_1 c4, ui16 c5, "
+ " i16 c6, ui16 c7, i32 c8, i32_1 c9, i32_1 c10, "
+ " d c11, d_1 c12, d_1 c13, ch c14, ch_1 c15, tx c16, "
+ " tx_1 c17, ch_2 c18 "
+ "from t1";
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ bind_count= (uint) mysql_stmt_field_count(stmt);
+
+ /*************** Fill in the bind structure and bind it **************/
+ bind_array= malloc(sizeof(MYSQL_BIND) * bind_count);
+ bzero((char*) bind_array, sizeof(MYSQL_BIND) * bind_count);
+ for (bind= bind_array; bind < bind_array + bind_count; bind++)
+ bind->error= &bind->error_value;
+ bind= bind_array;
+
+ bind->buffer= malloc(sizeof(uint8));
+ bind->buffer_type= MYSQL_TYPE_TINY;
+ bind->is_unsigned= TRUE;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(uint32));
+ bind->buffer_type= MYSQL_TYPE_LONG;
+ bind->is_unsigned= TRUE;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(int8));
+ bind->buffer_type= MYSQL_TYPE_TINY;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(uint16));
+ bind->buffer_type= MYSQL_TYPE_SHORT;
+ bind->is_unsigned= TRUE;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(int16));
+ bind->buffer_type= MYSQL_TYPE_SHORT;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(uint16));
+ bind->buffer_type= MYSQL_TYPE_SHORT;
+ bind->is_unsigned= TRUE;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(int8));
+ bind->buffer_type= MYSQL_TYPE_TINY;
+ bind->is_unsigned= TRUE;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(float));
+ bind->buffer_type= MYSQL_TYPE_FLOAT;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(float));
+ bind->buffer_type= MYSQL_TYPE_FLOAT;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(double));
+ bind->buffer_type= MYSQL_TYPE_DOUBLE;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(longlong));
+ bind->buffer_type= MYSQL_TYPE_LONGLONG;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(ulonglong));
+ bind->buffer_type= MYSQL_TYPE_LONGLONG;
+ bind->is_unsigned= TRUE;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(longlong));
+ bind->buffer_type= MYSQL_TYPE_LONGLONG;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(longlong));
+ bind->buffer_type= MYSQL_TYPE_LONGLONG;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(longlong));
+ bind->buffer_type= MYSQL_TYPE_LONGLONG;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(longlong));
+ bind->buffer_type= MYSQL_TYPE_LONGLONG;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(double));
+ bind->buffer_type= MYSQL_TYPE_DOUBLE;
+
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ bind->buffer= malloc(sizeof(double));
+ bind->buffer_type= MYSQL_TYPE_DOUBLE;
+
+ rc= mysql_stmt_bind_result(stmt, bind_array);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
+
+ /*************** Verify truncation results ***************************/
+ bind= bind_array;
+
+ /* signed tiny -> tiny */
+ DIE_UNLESS(*bind->error && * (int8*) bind->buffer == -10);
+
+ /* signed tiny -> uint32 */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(*bind->error && * (int32*) bind->buffer == -10);
+
+ /* unsigned tiny -> tiny */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(*bind->error && * (uint8*) bind->buffer == 200);
+
+ /* short -> ushort */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(*bind->error && * (int16*) bind->buffer == -32767);
+
+ /* ushort -> short */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(*bind->error && * (uint16*) bind->buffer == 64000);
+
+ /* short -> ushort (no truncation, data is in the range of target type) */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(! *bind->error && * (uint16*) bind->buffer == 32000);
+
+ /* ushort -> utiny */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(*bind->error && * (int8*) bind->buffer == 0);
+
+ /* int -> float: no truncation, the number is a power of two */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(! *bind->error && * (float*) bind->buffer == 1073741824);
+
+ /* int -> float: truncation, not enough bits in float */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(*bind->error);
+
+ /* int -> double: no truncation */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(! *bind->error && * (double*) bind->buffer == 1073741825);
+
+ /* double -> longlong: fractional part is lost */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+
+ /* double -> ulonglong, negative fp number to unsigned integer */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ /* Value in the buffer is not defined: don't test it */
+ DIE_UNLESS(*bind->error);
+
+ /* double -> longlong, negative fp number to signed integer: no loss */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(! *bind->error && * (longlong*) bind->buffer == LL(-12345678910));
+
+ /* big numeric string -> number */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(*bind->error);
+
+ /* junk string -> number */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(*bind->error && *(longlong*) bind->buffer == 0);
+
+ /* string with trailing spaces -> number */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(! *bind->error && *(longlong*) bind->buffer == 12345);
+
+ /* string with trailing spaces -> double */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ DIE_UNLESS(! *bind->error && *(double*) bind->buffer == 12345.67);
+
+ /* string with trailing junk -> double */
+ DIE_UNLESS(++bind < bind_array + bind_count);
+ /*
+ XXX: There must be a truncation error: but it's not the way the server
+ behaves, so let's leave it for now.
+ */
+ DIE_UNLESS(*(double*) bind->buffer == 12345.67);
+ /*
+ TODO: string -> double, double -> time, double -> string (truncation
+ errors are not supported here yet)
+ longlong -> time/date/datetime
+ date -> time, date -> timestamp, date -> number
+ time -> string, time -> date, time -> timestamp,
+ number -> date string -> date
+ */
+ /*************** Cleanup *********************************************/
+
+ mysql_stmt_close(stmt);
+
+ for (bind= bind_array; bind < bind_array + bind_count; bind++)
+ free(bind->buffer);
+ free(bind_array);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+static void test_truncation_option()
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ uint8 buf;
+ my_bool option= 0;
+ my_bool error;
+ MYSQL_BIND bind;
+
+ myheader("test_truncation_option");
+
+ /* Prepare the test table */
+ stmt_text= "select -1";
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bzero((char*) &bind, sizeof(MYSQL_BIND));
+
+ bind.buffer= (void*) &buf;
+ bind.buffer_type= MYSQL_TYPE_TINY;
+ bind.is_unsigned= TRUE;
+ bind.error= &error;
+
+ rc= mysql_stmt_bind_result(stmt, &bind);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
+ DIE_UNLESS(error);
+ rc= mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char*) &option);
+ myquery(rc);
+ /* need to rebind for the new setting to take effect */
+ rc= mysql_stmt_bind_result(stmt, &bind);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ /* The only change is rc - error pointers are still filled in */
+ DIE_UNLESS(error == 1);
+ /* restore back the defaults */
+ option= 1;
+ mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char*) &option);
+
+ mysql_stmt_close(stmt);
+}
+
+
/* Bug#6761 - mysql_list_fields doesn't work */
static void test_bug6761(void)
@@ -11581,7 +12679,7 @@ static void test_bug8330()
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
- bzero(bind, sizeof(bind));
+ bzero((char*) bind, sizeof(bind));
for (i=0; i < 2; i++)
{
stmt[i]= mysql_stmt_init(mysql);
@@ -11631,6 +12729,42 @@ static void test_bug7990()
}
+static void test_view_sp_list_fields()
+{
+ int rc;
+ MYSQL_RES *res;
+
+ myheader("test_view_sp_list_fields");
+
+ rc= mysql_query(mysql, "DROP FUNCTION IF EXISTS f1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS v1, t1, t2");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS v1, t1, t2");
+ myquery(rc);
+ rc= mysql_query(mysql, "create function f1 () returns int return 5");
+ myquery(rc);
+ rc= mysql_query(mysql, "create table t1 (s1 char,s2 char)");
+ myquery(rc);
+ rc= mysql_query(mysql, "create table t2 (s1 int);");
+ myquery(rc);
+ rc= mysql_query(mysql, "create view v1 as select s2,sum(s1) - \
+count(s2) as vx from t1 group by s2 having sum(s1) - count(s2) < (select f1() \
+from t2);");
+ myquery(rc);
+ res= mysql_list_fields(mysql, "v1", NullS);
+ DIE_UNLESS(res != 0 && mysql_num_fields(res) != 0);
+ rc= mysql_query(mysql, "DROP FUNCTION f1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "DROP TABLE t1, t2");
+ mysql_free_result(res);
+ myquery(rc);
+
+}
+
+
/*
Test mysql_real_escape_string() with gbk charset
@@ -11682,6 +12816,856 @@ static void test_bug8378()
}
+static void test_bug8722()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text;
+
+ myheader("test_bug8722");
+ /* Prepare test data */
+ stmt_text= "drop table if exists t1, v1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "CREATE TABLE t1 (c1 varchar(10), c2 varchar(10), c3 varchar(10),"
+ " c4 varchar(10), c5 varchar(10), c6 varchar(10),"
+ " c7 varchar(10), c8 varchar(10), c9 varchar(10),"
+ "c10 varchar(10))";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "INSERT INTO t1 VALUES (1,2,3,4,5,6,7,8,9,10)";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "CREATE VIEW v1 AS SELECT * FROM t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ /* Note: if you uncomment following block everything works fine */
+/*
+ rc= mysql_query(mysql, "sellect * from v1");
+ myquery(rc);
+ mysql_free_result(mysql_store_result(mysql));
+*/
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "select * from v1";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ mysql_stmt_close(stmt);
+ stmt_text= "drop table if exists t1, v1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+}
+
+
+MYSQL_STMT *open_cursor(const char *query)
+{
+ int rc;
+ const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
+
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ check_execute(stmt, rc);
+
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ return stmt;
+}
+
+
+static void test_bug8880()
+{
+ MYSQL_STMT *stmt_list[2], **stmt;
+ MYSQL_STMT **stmt_list_end= (MYSQL_STMT**) stmt_list + 2;
+ int rc;
+
+ myheader("test_bug8880");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
+ rc= mysql_query(mysql, "insert into t1 values (1,1)");
+ myquery(rc); /* one check is enough */
+ /*
+ when inserting 2 rows everything works well
+ mysql_query(mysql, "INSERT INTO t1 VALUES (1,1),(2,2)");
+ */
+ for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
+ *stmt= open_cursor("select a from t1");
+ for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
+ {
+ rc= mysql_stmt_execute(*stmt);
+ check_execute(*stmt, rc);
+ }
+ for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
+ mysql_stmt_close(*stmt);
+}
+
+
+static void test_bug9159()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text= "select a, b from t1";
+ const unsigned long type= CURSOR_TYPE_READ_ONLY;
+
+ myheader("test_bug9159");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
+ rc= mysql_query(mysql, "insert into t1 values (1,1)");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+ mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void *)&type);
+
+ mysql_stmt_execute(stmt);
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table if exists t1");
+ myquery(rc);
+}
+
+
+/* Crash when opening a cursor to a query with DISTICNT and no key */
+
+static void test_bug9520()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char a[6];
+ ulong a_len;
+ int rc, row_count= 0;
+
+ myheader("test_bug9520");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (a char(5), b char(5), c char(5),"
+ " primary key (a, b, c))");
+ rc= mysql_query(mysql, "insert into t1 values ('x', 'y', 'z'), "
+ " ('a', 'b', 'c'), ('k', 'l', 'm')");
+ myquery(rc);
+
+ stmt= open_cursor("select distinct b from t1");
+
+ /*
+ Not crashes with:
+ stmt= open_cursor("select distinct a from t1");
+ */
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bzero((char*) bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char*) a;
+ bind[0].buffer_length= sizeof(a);
+ bind[0].length= &a_len;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ while (!(rc= mysql_stmt_fetch(stmt)))
+ row_count++;
+
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ printf("Fetched %d rows\n", row_count);
+ DBUG_ASSERT(row_count == 3);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
+/*
+ We can't have more than one cursor open for a prepared statement.
+ Test re-executions of a PS with cursor; mysql_stmt_reset must close
+ the cursor attached to the statement, if there is one.
+*/
+
+static void test_bug9478()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char a[6];
+ ulong a_len;
+ int rc, i;
+ DBUG_ENTER("test_bug9478");
+
+ myheader("test_bug9478");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key, "
+ " name varchar(20) not null)");
+ rc= mysql_query(mysql, "insert into t1 (id, name) values "
+ " (1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
+ myquery(rc);
+
+ stmt= open_cursor("select name from t1 where id=2");
+
+ bzero((char*) bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char*) a;
+ bind[0].buffer_length= sizeof(a);
+ bind[0].length= &a_len;
+ mysql_stmt_bind_result(stmt, bind);
+
+ for (i= 0; i < 5; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+
+ /*
+ The query above is a one-row result set. Therefore, there is no
+ cursor associated with it, as the server won't bother with opening
+ a cursor for a one-row result set. The first row was read from the
+ server in the fetch above. But there is eof packet pending in the
+ network. mysql_stmt_execute will flush the packet and successfully
+ execute the statement.
+ */
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ {
+ char buff[8];
+ /* Fill in the fethc packet */
+ int4store(buff, stmt->stmt_id);
+ buff[4]= 1; /* prefetch rows */
+ rc= ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH, buff,
+ sizeof(buff), 0,0,1) ||
+ (*mysql->methods->read_query_result)(mysql));
+ DIE_UNLESS(rc);
+ if (!opt_silent && i == 0)
+ printf("Got error (as expected): %s\n", mysql_error(mysql));
+ }
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+
+ rc= mysql_stmt_reset(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt));
+ if (!opt_silent && i == 0)
+ printf("Got error (as expected): %s\n", mysql_stmt_error(stmt));
+ }
+ rc= mysql_stmt_close(stmt);
+ DIE_UNLESS(rc == 0);
+
+ /* Test the case with a server side cursor */
+ stmt= open_cursor("select name from t1");
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ for (i= 0; i < 5; i++)
+ {
+ DBUG_PRINT("loop",("i: %d", i));
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ while (! (rc= mysql_stmt_fetch(stmt)))
+ {
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+ }
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+
+ rc= mysql_stmt_reset(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt));
+ if (!opt_silent && i == 0)
+ printf("Got error (as expected): %s\n", mysql_stmt_error(stmt));
+ }
+
+ rc= mysql_stmt_close(stmt);
+ DIE_UNLESS(rc == 0);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Error message is returned for unsupported features.
+ Test also cursors with non-default PREFETCH_ROWS
+*/
+
+static void test_bug9643()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ int32 a;
+ int rc;
+ const char *stmt_text;
+ int num_rows= 0;
+ ulong type;
+ ulong prefetch_rows= 5;
+
+ myheader("test_bug9643");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key)");
+ rc= mysql_query(mysql, "insert into t1 (id) values "
+ " (1), (2), (3), (4), (5), (6), (7), (8), (9)");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+ /* Not implemented in 5.0 */
+ type= (ulong) CURSOR_TYPE_SCROLLABLE;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ DIE_UNLESS(rc);
+ if (! opt_silent)
+ printf("Got error (as expected): %s\n", mysql_stmt_error(stmt));
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS,
+ (void*) &prefetch_rows);
+ check_execute(stmt, rc);
+ stmt_text= "select * from t1";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ bzero((char*) bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void*) &a;
+ bind[0].buffer_length= sizeof(a);
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ ++num_rows;
+ DIE_UNLESS(num_rows == 9);
+
+ rc= mysql_stmt_close(stmt);
+ DIE_UNLESS(rc == 0);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+/*
+ Bug#11111: fetch from view returns wrong data
+*/
+
+static void test_bug11111()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[2];
+ char buf[2][20];
+ ulong len[2];
+ int i;
+ int rc;
+ const char *query= "SELECT DISTINCT f1,ff2 FROM v1";
+
+ myheader("test_bug11111");
+
+ rc= mysql_query(mysql, "drop table if exists t1, t2, v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "drop view if exists t1, t2, v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "create table t1 (f1 int, f2 int)");
+ myquery(rc);
+ rc= mysql_query(mysql, "create table t2 (ff1 int, ff2 int)");
+ myquery(rc);
+ rc= mysql_query(mysql, "create view v1 as select * from t1, t2 where f1=ff1");
+ myquery(rc);
+ rc= mysql_query(mysql, "insert into t1 values (1,1), (2,2), (3,3)");
+ myquery(rc);
+ rc= mysql_query(mysql, "insert into t2 values (1,1), (2,2), (3,3)");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+
+ mysql_stmt_prepare(stmt, query, strlen(query));
+ mysql_stmt_execute(stmt);
+
+ bzero((char*) bind, sizeof(bind));
+ for (i=0; i < 2; i++)
+ {
+ bind[i].buffer_type= MYSQL_TYPE_STRING;
+ bind[i].buffer= (gptr *)&buf[i];
+ bind[i].buffer_length= 20;
+ bind[i].length= &len[i];
+ }
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent)
+ printf("return: %s", buf[1]);
+ DIE_UNLESS(!strcmp(buf[1],"1"));
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop view v1");
+ myquery(rc);
+ rc= mysql_query(mysql, "drop table t1, t2");
+ myquery(rc);
+}
+
+/*
+ Check that proper cleanups are done for prepared statement when
+ fetching thorugh a cursor.
+*/
+
+static void test_bug10729()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char a[21];
+ int rc;
+ const char *stmt_text;
+ int i= 0;
+ const char *name_array[3]= { "aaa", "bbb", "ccc" };
+ ulong type;
+
+ myheader("test_bug10729");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "name VARCHAR(20) NOT NULL)");
+ rc= mysql_query(mysql, "insert into t1 (id, name) values "
+ "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_execute(stmt, rc);
+ stmt_text= "select name from t1";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ bzero((char*) bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void*) a;
+ bind[0].buffer_length= sizeof(a);
+ mysql_stmt_bind_result(stmt, bind);
+
+ for (i= 0; i < 3; i++)
+ {
+ int row_no= 0;
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ {
+ DIE_UNLESS(strcmp(a, name_array[row_no]) == 0);
+ if (!opt_silent)
+ printf("%d: %s\n", row_no, a);
+ ++row_no;
+ }
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+ }
+ rc= mysql_stmt_close(stmt);
+ DIE_UNLESS(rc == 0);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
+/*
+ Check that mysql_next_result works properly in case when one of
+ the statements used in a multi-statement query is erroneous
+*/
+
+static void test_bug9992()
+{
+ MYSQL *mysql1;
+ MYSQL_RES* res ;
+ int rc;
+
+ myheader("test_bug9992");
+
+ if (!opt_silent)
+ printf("Establishing a connection with option CLIENT_MULTI_STATEMENTS..\n");
+
+ mysql1= mysql_init(NULL);
+
+ if (!mysql_real_connect(mysql1, opt_host, opt_user, opt_password,
+ opt_db ? opt_db : "test", opt_port, opt_unix_socket,
+ CLIENT_MULTI_STATEMENTS))
+ {
+ fprintf(stderr, "Failed to connect to the database\n");
+ DIE_UNLESS(0);
+ }
+
+
+ /* Sic: SHOW DATABASE is incorrect syntax. */
+ rc= mysql_query(mysql1, "SHOW TABLES; SHOW DATABASE; SELECT 1;");
+
+ if (rc)
+ {
+ fprintf(stderr, "[%d] %s\n", mysql_errno(mysql1), mysql_error(mysql1));
+ DIE_UNLESS(0);
+ }
+
+ if (!opt_silent)
+ printf("Testing mysql_store_result/mysql_next_result..\n");
+
+ res= mysql_store_result(mysql1);
+ DIE_UNLESS(res);
+ mysql_free_result(res);
+ rc= mysql_next_result(mysql1);
+ DIE_UNLESS(rc == 1); /* Got errors, as expected */
+
+ if (!opt_silent)
+ fprintf(stdout, "Got error, as expected:\n [%d] %s\n",
+ mysql_errno(mysql1), mysql_error(mysql1));
+
+ mysql_close(mysql1);
+}
+
+/* Bug#10736: cursors and subqueries, memroot management */
+
+static void test_bug10736()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char a[21];
+ int rc;
+ const char *stmt_text;
+ int i= 0;
+ ulong type;
+
+ myheader("test_bug10736");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "name VARCHAR(20) NOT NULL)");
+ rc= mysql_query(mysql, "insert into t1 (id, name) values "
+ "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_execute(stmt, rc);
+ stmt_text= "select name from t1 where name=(select name from t1 where id=2)";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ bzero((char*) bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void*) a;
+ bind[0].buffer_length= sizeof(a);
+ mysql_stmt_bind_result(stmt, bind);
+
+ for (i= 0; i < 3; i++)
+ {
+ int row_no= 0;
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ {
+ if (!opt_silent)
+ printf("%d: %s\n", row_no, a);
+ ++row_no;
+ }
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+ }
+ rc= mysql_stmt_close(stmt);
+ DIE_UNLESS(rc == 0);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+/* Bug#10794: cursors, packets out of order */
+
+static void test_bug10794()
+{
+ MYSQL_STMT *stmt, *stmt1;
+ MYSQL_BIND bind[2];
+ char a[21];
+ int id_val;
+ ulong a_len;
+ int rc;
+ const char *stmt_text;
+ int i= 0;
+ ulong type;
+
+ myheader("test_bug10794");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "name varchar(20) not null)");
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "insert into t1 (id, name) values (?, ?)";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ bzero((char*) bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void*) &id_val;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (void*) a;
+ bind[1].length= &a_len;
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+ for (i= 0; i < 42; i++)
+ {
+ id_val= (i+1)*10;
+ sprintf(a, "a%d", i);
+ a_len= strlen(a); /* safety against broken sprintf */
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ }
+ stmt_text= "select name from t1";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ stmt1= mysql_stmt_init(mysql);
+ mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ bzero((char*) bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void*) a;
+ bind[0].buffer_length= sizeof(a);
+ bind[0].length= &a_len;
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent)
+ printf("Fetched row from stmt: %s\n", a);
+ /* Don't optimize: an attribute of the original test case */
+ mysql_stmt_free_result(stmt);
+ mysql_stmt_reset(stmt);
+ stmt_text= "select name from t1 where id=10";
+ rc= mysql_stmt_prepare(stmt1, stmt_text, strlen(stmt_text));
+ check_execute(stmt1, rc);
+ rc= mysql_stmt_bind_result(stmt1, bind);
+ check_execute(stmt1, rc);
+ rc= mysql_stmt_execute(stmt1);
+ while (1)
+ {
+ rc= mysql_stmt_fetch(stmt1);
+ if (rc == MYSQL_NO_DATA)
+ {
+ if (!opt_silent)
+ printf("End of data in stmt1\n");
+ break;
+ }
+ check_execute(stmt1, rc);
+ if (!opt_silent)
+ printf("Fetched row from stmt1: %s\n", a);
+ }
+ mysql_stmt_close(stmt);
+ mysql_stmt_close(stmt1);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
+/* Bug#11172: cursors, crash on a fetch from a datetime column */
+
+static void test_bug11172()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind_in[1], bind_out[2];
+ MYSQL_TIME hired;
+ int rc;
+ const char *stmt_text;
+ int i= 0, id;
+ ulong type;
+
+ myheader("test_bug11172");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "hired date not null)");
+ rc= mysql_query(mysql,
+ "insert into t1 (id, hired) values (1, '1933-08-24'), "
+ "(2, '1965-01-01'), (3, '1949-08-17'), (4, '1945-07-07'), "
+ "(5, '1941-05-15'), (6, '1978-09-15'), (7, '1936-03-28')");
+ myquery(rc);
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT id, hired FROM t1 WHERE hired=?";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ bzero((char*) bind_in, sizeof(bind_in));
+ bzero((char*) bind_out, sizeof(bind_out));
+ bzero((char*) &hired, sizeof(hired));
+ hired.year= 1965;
+ hired.month= 1;
+ hired.day= 1;
+ bind_in[0].buffer_type= MYSQL_TYPE_DATE;
+ bind_in[0].buffer= (void*) &hired;
+ bind_in[0].buffer_length= sizeof(hired);
+ bind_out[0].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[0].buffer= (void*) &id;
+ bind_out[1]= bind_in[0];
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_bind_param(stmt, bind_in);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_bind_result(stmt, bind_out);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ {
+ if (!opt_silent)
+ printf("fetched data %d:%d-%d-%d\n", id,
+ hired.year, hired.month, hired.day);
+ }
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+ mysql_stmt_free_result(stmt) || mysql_stmt_reset(stmt);
+ }
+ mysql_stmt_close(stmt);
+ mysql_rollback(mysql);
+ mysql_rollback(mysql);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
+/* Bug#11656: cursors, crash on a fetch from a query with distinct. */
+
+static void test_bug11656()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[2];
+ int rc;
+ const char *stmt_text;
+ char buf[2][20];
+ int i= 0;
+ ulong type;
+
+ myheader("test_bug11656");
+
+ mysql_query(mysql, "drop table if exists t1");
+
+ rc= mysql_query(mysql, "create table t1 ("
+ "server varchar(40) not null, "
+ "test_kind varchar(1) not null, "
+ "test_id varchar(30) not null , "
+ "primary key (server,test_kind,test_id))");
+ myquery(rc);
+
+ stmt_text= "select distinct test_kind, test_id from t1 "
+ "where server in (?, ?)";
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ bzero((char*) bind, sizeof(bind));
+ strmov(buf[0], "pcint502_MY2");
+ strmov(buf[1], "*");
+ for (i=0; i < 2; i++)
+ {
+ bind[i].buffer_type= MYSQL_TYPE_STRING;
+ bind[i].buffer= (gptr *)&buf[i];
+ bind[i].buffer_length= strlen(buf[i]);
+ }
+ mysql_stmt_bind_param(stmt, bind);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
+/*
+ Check that the server signals when NO_BACKSLASH_ESCAPES mode is in effect,
+ and mysql_real_escape_string() does the right thing as a result.
+*/
+
+static void test_bug10214()
+{
+ int len;
+ char out[8];
+
+ myheader("test_bug10214");
+
+ DIE_UNLESS(!(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES));
+
+ len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
+ DIE_UNLESS(memcmp(out, "a\\'b\\\\c", len) == 0);
+
+ mysql_query(mysql, "set sql_mode='NO_BACKSLASH_ESCAPES'");
+ DIE_UNLESS(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES);
+
+ len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
+ DIE_UNLESS(memcmp(out, "a''b\\c", len) == 0);
+
+ mysql_query(mysql, "set sql_mode=''");
+}
+
+static void test_client_character_set()
+{
+ MY_CHARSET_INFO cs;
+ char *csname= (char*) "utf8";
+ char *csdefault= (char*)mysql_character_set_name(mysql);
+ int rc;
+
+ myheader("test_client_character_set");
+
+ rc= mysql_set_character_set(mysql, csname);
+ DIE_UNLESS(rc == 0);
+
+ mysql_get_character_set_info(mysql, &cs);
+ DIE_UNLESS(!strcmp(cs.csname, "utf8"));
+ DIE_UNLESS(!strcmp(cs.name, "utf8_general_ci"));
+ /* Restore the default character set */
+ rc= mysql_set_character_set(mysql, csdefault);
+ myquery(rc);
+}
+
/* Test correct max length for MEDIUMTEXT and LONGTEXT columns */
static void test_bug9735()
@@ -11708,6 +13692,7 @@ static void test_bug9735()
myquery(rc);
}
+
/* Bug#11183 "mysql_stmt_reset() doesn't reset information about error" */
static void test_bug11183()
@@ -11752,15 +13737,166 @@ static void test_bug11183()
myquery(rc);
}
+static void test_bug11037()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text;
+
+ myheader("test_bug11037");
+
+ mysql_query(mysql, "drop table if exists t1");
+
+ rc= mysql_query(mysql, "create table t1 (id int not null)");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "insert into t1 values (1)");
+ myquery(rc);
+
+ stmt_text= "select id FROM t1";
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+
+ /* expected error */
+ rc = mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc==1);
+ if (!opt_silent)
+ fprintf(stdout, "Got error, as expected:\n [%d] %s\n",
+ mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc==0);
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc==MYSQL_NO_DATA);
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc==MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+/* Bug#10760: cursors, crash in a fetch after rollback. */
+
+static void test_bug10760()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ int rc;
+ const char *stmt_text;
+ char id_buf[20];
+ ulong id_len;
+ int i= 0;
+ ulong type;
+
+ myheader("test_bug10760");
+
+ mysql_query(mysql, "drop table if exists t1, t2");
+
+ /* create tables */
+ rc= mysql_query(mysql, "create table t1 (id integer not null primary key)"
+ " engine=MyISAM");
+ myquery(rc);
+ for (; i < 42; ++i)
+ {
+ char buf[100];
+ sprintf(buf, "insert into t1 (id) values (%d)", i+1);
+ rc= mysql_query(mysql, buf);
+ myquery(rc);
+ }
+ mysql_autocommit(mysql, FALSE);
+ /* create statement */
+ stmt= mysql_stmt_init(mysql);
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ /*
+ 1: check that a deadlock within the same connection
+ is resolved and an error is returned. The deadlock is modelled
+ as follows:
+ con1: open cursor for select * from t1;
+ con1: insert into t1 (id) values (1)
+ */
+ stmt_text= "select id from t1 order by 1";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_query(mysql, "update t1 set id=id+100");
+ DIE_UNLESS(rc);
+ if (!opt_silent)
+ printf("Got error (as expected): %s\n", mysql_error(mysql));
+ /*
+ 2: check that MyISAM tables used in cursors survive
+ COMMIT/ROLLBACK.
+ */
+ rc= mysql_rollback(mysql); /* should not close the cursor */
+ myquery(rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
+ /*
+ 3: check that cursors to InnoDB tables are closed (for now) by
+ COMMIT/ROLLBACK.
+ */
+ if (! have_innodb)
+ {
+ if (!opt_silent)
+ printf("Testing that cursors are closed at COMMIT/ROLLBACK requires "
+ "InnoDB.\n");
+ }
+ else
+ {
+ stmt_text= "select id from t1 order by 1";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ rc= mysql_query(mysql, "alter table t1 engine=InnoDB");
+ myquery(rc);
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (void*) id_buf;
+ bind[0].buffer_length= sizeof(id_buf);
+ bind[0].length= &id_len;
+ check_execute(stmt, rc);
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_execute(stmt);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == 0);
+ if (!opt_silent)
+ printf("Fetched row %s\n", id_buf);
+ rc= mysql_rollback(mysql); /* should close the cursor */
+ myquery(rc);
+#if 0
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc);
+ if (!opt_silent)
+ printf("Got error (as expected): %s\n", mysql_error(mysql));
+#endif
+ }
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+ mysql_autocommit(mysql, TRUE); /* restore default */
+}
+
static void test_bug12001()
{
MYSQL *mysql_local;
MYSQL_RES *result;
const char *query= "DROP TABLE IF EXISTS test_table;"
- "CREATE TABLE test_table(id INT);"
- "INSERT INTO test_table VALUES(10);"
- "UPDATE test_table SET id=20 WHERE id=10;"
- "SELECT * FROM test_table;"
+ "CREATE TABLE test_table(id INT);"
+ "INSERT INTO test_table VALUES(10);"
+ "UPDATE test_table SET id=20 WHERE id=10;"
+ "SELECT * FROM test_table;"
"INSERT INTO non_existent_table VALUES(11);";
int rc, res;
@@ -11775,7 +13911,9 @@ static void test_bug12001()
/* Create connection that supports multi statements */
if (!mysql_real_connect(mysql_local, opt_host, opt_user,
opt_password, current_db, opt_port,
- opt_unix_socket, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS)) {
+ opt_unix_socket, CLIENT_MULTI_STATEMENTS |
+ CLIENT_MULTI_RESULTS))
+ {
fprintf(stdout, "\n mysql_real_connect() failed");
exit(1);
}
@@ -11783,12 +13921,16 @@ static void test_bug12001()
rc= mysql_query(mysql_local, query);
myquery(rc);
- do {
- if (mysql_field_count(mysql_local) && (result= mysql_use_result(mysql_local))) {
- mysql_free_result(result);
+ do
+ {
+ if (mysql_field_count(mysql_local) &&
+ (result= mysql_use_result(mysql_local)))
+ {
+ mysql_free_result(result);
}
- } while (!(res= mysql_next_result(mysql_local)));
-
+ }
+ while (!(res= mysql_next_result(mysql_local)));
+
rc= mysql_query(mysql_local, "DROP TABLE IF EXISTS test_table");
myquery(rc);
@@ -11796,6 +13938,382 @@ static void test_bug12001()
DIE_UNLESS(res==1);
}
+
+/* Bug#11909: wrong metadata if fetching from two cursors */
+
+static void test_bug11909()
+{
+ MYSQL_STMT *stmt1, *stmt2;
+ MYSQL_BIND bind[7];
+ int rc;
+ char firstname[20], midinit[20], lastname[20], workdept[20];
+ ulong firstname_len, midinit_len, lastname_len, workdept_len;
+ uint32 empno;
+ double salary;
+ float bonus;
+ const char *stmt_text;
+
+ myheader("test_bug11909");
+
+ stmt_text= "drop table if exists t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "create table t1 ("
+ " empno int(11) not null, firstname varchar(20) not null,"
+ " midinit varchar(20) not null, lastname varchar(20) not null,"
+ " workdept varchar(6) not null, salary double not null,"
+ " bonus float not null, primary key (empno)"
+ ") default charset=latin1 collate=latin1_bin";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "insert into t1 values "
+ "(10, 'CHRISTINE', 'I', 'HAAS', 'A00', 52750, 1000), "
+ "(20, 'MICHAEL', 'L', 'THOMPSON', 'B01', 41250, 800),"
+ "(30, 'SALLY', 'A', 'KWAN', 'C01', 38250, 800),"
+ "(50, 'JOHN', 'B', 'GEYER', 'E01', 40175, 800), "
+ "(60, 'IRVING', 'F', 'STERN', 'D11', 32250, 500)";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ /* ****** Begin of trace ****** */
+
+ stmt1= open_cursor("SELECT empno, firstname, midinit, lastname,"
+ "workdept, salary, bonus FROM t1");
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (void*) &empno;
+
+ bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ bind[1].buffer= (void*) firstname;
+ bind[1].buffer_length= sizeof(firstname);
+ bind[1].length= &firstname_len;
+
+ bind[2].buffer_type= MYSQL_TYPE_VAR_STRING;
+ bind[2].buffer= (void*) midinit;
+ bind[2].buffer_length= sizeof(midinit);
+ bind[2].length= &midinit_len;
+
+ bind[3].buffer_type= MYSQL_TYPE_VAR_STRING;
+ bind[3].buffer= (void*) lastname;
+ bind[3].buffer_length= sizeof(lastname);
+ bind[3].length= &lastname_len;
+
+ bind[4].buffer_type= MYSQL_TYPE_VAR_STRING;
+ bind[4].buffer= (void*) workdept;
+ bind[4].buffer_length= sizeof(workdept);
+ bind[4].length= &workdept_len;
+
+ bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind[5].buffer= (void*) &salary;
+
+ bind[6].buffer_type= MYSQL_TYPE_FLOAT;
+ bind[6].buffer= (void*) &bonus;
+ rc= mysql_stmt_bind_result(stmt1, bind);
+ check_execute(stmt1, rc);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_execute(stmt1, rc);
+
+ rc= mysql_stmt_fetch(stmt1);
+ DIE_UNLESS(rc == 0);
+ DIE_UNLESS(empno == 10);
+ DIE_UNLESS(strcmp(firstname, "CHRISTINE") == 0);
+ DIE_UNLESS(strcmp(midinit, "I") == 0);
+ DIE_UNLESS(strcmp(lastname, "HAAS") == 0);
+ DIE_UNLESS(strcmp(workdept, "A00") == 0);
+ DIE_UNLESS(salary == (double) 52750.0);
+ DIE_UNLESS(bonus == (float) 1000.0);
+
+ stmt2= open_cursor("SELECT empno, firstname FROM t1");
+ rc= mysql_stmt_bind_result(stmt2, bind);
+ check_execute(stmt2, rc);
+
+ rc= mysql_stmt_execute(stmt2);
+ check_execute(stmt2, rc);
+
+ rc= mysql_stmt_fetch(stmt2);
+ DIE_UNLESS(rc == 0);
+
+ DIE_UNLESS(empno == 10);
+ DIE_UNLESS(strcmp(firstname, "CHRISTINE") == 0);
+
+ rc= mysql_stmt_reset(stmt2);
+ check_execute(stmt2, rc);
+
+ /* ERROR: next statement should return 0 */
+
+ rc= mysql_stmt_fetch(stmt1);
+ DIE_UNLESS(rc == 0);
+
+ mysql_stmt_close(stmt1);
+ mysql_stmt_close(stmt2);
+ rc= mysql_rollback(mysql);
+ myquery(rc);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+/* Cursors: opening a cursor to a compilicated query with ORDER BY */
+
+static void test_bug11901()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[2];
+ int rc;
+ char workdept[20];
+ ulong workdept_len;
+ uint32 empno;
+ const char *stmt_text;
+
+ myheader("test_bug11901");
+
+ stmt_text= "drop table if exists t1, t2";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "create table t1 ("
+ " empno int(11) not null, firstname varchar(20) not null,"
+ " midinit varchar(20) not null, lastname varchar(20) not null,"
+ " workdept varchar(6) not null, salary double not null,"
+ " bonus float not null, primary key (empno), "
+ " unique key (workdept, empno) "
+ ") default charset=latin1 collate=latin1_bin";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "insert into t1 values "
+ "(10, 'CHRISTINE', 'I', 'HAAS', 'A00', 52750, 1000),"
+ "(20, 'MICHAEL', 'L', 'THOMPSON', 'B01', 41250, 800), "
+ "(30, 'SALLY', 'A', 'KWAN', 'C01', 38250, 800), "
+ "(50, 'JOHN', 'B', 'GEYER', 'E01', 40175, 800), "
+ "(60, 'IRVING', 'F', 'STERN', 'D11', 32250, 500), "
+ "(70, 'EVA', 'D', 'PULASKI', 'D21', 36170, 700), "
+ "(90, 'EILEEN', 'W', 'HENDERSON', 'E11', 29750, 600), "
+ "(100, 'THEODORE', 'Q', 'SPENSER', 'E21', 26150, 500), "
+ "(110, 'VINCENZO', 'G', 'LUCCHESSI', 'A00', 46500, 900), "
+ "(120, 'SEAN', '', 'O\\'CONNELL', 'A00', 29250, 600), "
+ "(130, 'DOLORES', 'M', 'QUINTANA', 'C01', 23800, 500), "
+ "(140, 'HEATHER', 'A', 'NICHOLLS', 'C01', 28420, 600), "
+ "(150, 'BRUCE', '', 'ADAMSON', 'D11', 25280, 500), "
+ "(160, 'ELIZABETH', 'R', 'PIANKA', 'D11', 22250, 400), "
+ "(170, 'MASATOSHI', 'J', 'YOSHIMURA', 'D11', 24680, 500), "
+ "(180, 'MARILYN', 'S', 'SCOUTTEN', 'D11', 21340, 500), "
+ "(190, 'JAMES', 'H', 'WALKER', 'D11', 20450, 400), "
+ "(200, 'DAVID', '', 'BROWN', 'D11', 27740, 600), "
+ "(210, 'WILLIAM', 'T', 'JONES', 'D11', 18270, 400), "
+ "(220, 'JENNIFER', 'K', 'LUTZ', 'D11', 29840, 600), "
+ "(230, 'JAMES', 'J', 'JEFFERSON', 'D21', 22180, 400), "
+ "(240, 'SALVATORE', 'M', 'MARINO', 'D21', 28760, 600), "
+ "(250, 'DANIEL', 'S', 'SMITH', 'D21', 19180, 400), "
+ "(260, 'SYBIL', 'P', 'JOHNSON', 'D21', 17250, 300), "
+ "(270, 'MARIA', 'L', 'PEREZ', 'D21', 27380, 500), "
+ "(280, 'ETHEL', 'R', 'SCHNEIDER', 'E11', 26250, 500), "
+ "(290, 'JOHN', 'R', 'PARKER', 'E11', 15340, 300), "
+ "(300, 'PHILIP', 'X', 'SMITH', 'E11', 17750, 400), "
+ "(310, 'MAUDE', 'F', 'SETRIGHT', 'E11', 15900, 300), "
+ "(320, 'RAMLAL', 'V', 'MEHTA', 'E21', 19950, 400), "
+ "(330, 'WING', '', 'LEE', 'E21', 25370, 500), "
+ "(340, 'JASON', 'R', 'GOUNOT', 'E21', 23840, 500)";
+
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "create table t2 ("
+ " deptno varchar(6) not null, deptname varchar(20) not null,"
+ " mgrno int(11) not null, location varchar(20) not null,"
+ " admrdept varchar(6) not null, refcntd int(11) not null,"
+ " refcntu int(11) not null, primary key (deptno)"
+ ") default charset=latin1 collate=latin1_bin";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "insert into t2 values "
+ "('A00', 'SPIFFY COMPUTER SERV', 10, '', 'A00', 0, 0), "
+ "('B01', 'PLANNING', 20, '', 'A00', 0, 0), "
+ "('C01', 'INFORMATION CENTER', 30, '', 'A00', 0, 0), "
+ "('D01', 'DEVELOPMENT CENTER', 0, '', 'A00', 0, 0),"
+ "('D11', 'MANUFACTURING SYSTEM', 60, '', 'D01', 0, 0), "
+ "('D21', 'ADMINISTRATION SYSTE', 70, '', 'D01', 0, 0), "
+ "('E01', 'SUPPORT SERVICES', 50, '', 'A00', 0, 0), "
+ "('E11', 'OPERATIONS', 90, '', 'E01', 0, 0), "
+ "('E21', 'SOFTWARE SUPPORT', 100,'', 'E01', 0, 0)";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ /* ****** Begin of trace ****** */
+
+ stmt= open_cursor("select t1.empno, t1.workdept "
+ "from (t1 left join t2 on t2.deptno = t1.workdept) "
+ "where t2.deptno in "
+ " (select t2.deptno "
+ " from (t1 left join t2 on t2.deptno = t1.workdept) "
+ " where t1.empno = ?) "
+ "order by 1");
+ bzero(bind, sizeof(bind));
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= &empno;
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ bind[1].buffer= (void*) workdept;
+ bind[1].buffer_length= sizeof(workdept);
+ bind[1].length= &workdept_len;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_execute(stmt, rc);
+
+ empno= 10;
+ /* ERROR: next statement causes a server crash */
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1, t2");
+ myquery(rc);
+}
+
+/* Bug#11904: mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY grouping wrong result */
+
+static void test_bug11904()
+{
+ MYSQL_STMT *stmt1;
+ int rc;
+ const char *stmt_text;
+ const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
+ MYSQL_BIND bind[2];
+ int country_id=0;
+ char row_data[11]= {0};
+
+ myheader("test_bug11904");
+
+ /* create tables */
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bug11904b");
+ myquery(rc);
+ rc= mysql_query(mysql, "CREATE TABLE bug11904b (id int, name char(10), primary key(id, name))");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "INSERT INTO bug11904b VALUES (1, 'sofia'), (1,'plovdiv'),"
+ " (1,'varna'), (2,'LA'), (2,'new york'), (3,'heidelberg'),"
+ " (3,'berlin'), (3, 'frankfurt')");
+
+ myquery(rc);
+ mysql_commit(mysql);
+ /* create statement */
+ stmt1= mysql_stmt_init(mysql);
+ mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ stmt_text= "SELECT id, MIN(name) FROM bug11904b GROUP BY id";
+
+ rc= mysql_stmt_prepare(stmt1, stmt_text, strlen(stmt_text));
+ check_execute(stmt1, rc);
+
+ memset(bind, 0, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer=& country_id;
+ bind[0].buffer_length= 0;
+ bind[0].length= 0;
+
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer=& row_data;
+ bind[1].buffer_length= sizeof(row_data) - 1;
+ bind[1].length= 0;
+
+ rc= mysql_stmt_bind_result(stmt1, bind);
+ check_execute(stmt1, rc);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_execute(stmt1, rc);
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_execute(stmt1, rc);
+ DIE_UNLESS(country_id == 1);
+ DIE_UNLESS(memcmp(row_data, "plovdiv", 7) == 0);
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_execute(stmt1, rc);
+ DIE_UNLESS(country_id == 2);
+ DIE_UNLESS(memcmp(row_data, "LA", 2) == 0);
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_execute(stmt1, rc);
+ DIE_UNLESS(country_id == 3);
+ DIE_UNLESS(memcmp(row_data, "berlin", 6) == 0);
+
+ rc= mysql_stmt_close(stmt1);
+ check_execute(stmt1, rc);
+
+ rc= mysql_query(mysql, "drop table bug11904b");
+ myquery(rc);
+}
+
+
+/* Bug#12243: multiple cursors, crash in a fetch after commit. */
+
+static void test_bug12243()
+{
+ MYSQL_STMT *stmt1, *stmt2;
+ int rc;
+ const char *stmt_text;
+ ulong type;
+
+ myheader("test_bug12243");
+
+ if (! have_innodb)
+ {
+ if (!opt_silent)
+ printf("This test requires InnoDB.\n");
+ return;
+ }
+
+ /* create tables */
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (a int) engine=InnoDB");
+ rc= mysql_query(mysql, "insert into t1 (a) values (1), (2)");
+ myquery(rc);
+ mysql_autocommit(mysql, FALSE);
+ /* create statement */
+ stmt1= mysql_stmt_init(mysql);
+ stmt2= mysql_stmt_init(mysql);
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ stmt_text= "select a from t1";
+
+ rc= mysql_stmt_prepare(stmt1, stmt_text, strlen(stmt_text));
+ check_execute(stmt1, rc);
+ rc= mysql_stmt_execute(stmt1);
+ check_execute(stmt1, rc);
+ rc= mysql_stmt_fetch(stmt1);
+ check_execute(stmt1, rc);
+
+ rc= mysql_stmt_prepare(stmt2, stmt_text, strlen(stmt_text));
+ check_execute(stmt2, rc);
+ rc= mysql_stmt_execute(stmt2);
+ check_execute(stmt2, rc);
+ rc= mysql_stmt_fetch(stmt2);
+ check_execute(stmt2, rc);
+
+ rc= mysql_stmt_close(stmt1);
+ check_execute(stmt1, rc);
+ rc= mysql_commit(mysql);
+ myquery(rc);
+ rc= mysql_stmt_fetch(stmt2);
+ check_execute(stmt2, rc);
+
+ mysql_stmt_close(stmt2);
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+ mysql_autocommit(mysql, TRUE); /* restore default */
+}
+
/*
Bug#11718: query with function, join and order by returns wrong type
*/
@@ -11895,6 +14413,7 @@ and you are welcome to modify and redistribute it under the GPL license\n");
static struct my_tests_st my_tests[]= {
+ { "test_view_sp_list_fields", test_view_sp_list_fields},
{ "client_query", client_query },
{ "test_prepare_insert_update", test_prepare_insert_update},
#if NOT_YET_WORKING
@@ -12041,13 +14560,45 @@ static struct my_tests_st my_tests[]= {
{ "test_conversion", test_conversion },
{ "test_rewind", test_rewind },
{ "test_bug6761", test_bug6761 },
+ { "test_view", test_view },
+ { "test_view_where", test_view_where },
+ { "test_view_2where", test_view_2where },
+ { "test_view_star", test_view_star },
+ { "test_view_insert", test_view_insert },
+ { "test_left_join_view", test_left_join_view },
+ { "test_view_insert_fields", test_view_insert_fields },
+ { "test_basic_cursors", test_basic_cursors },
+ { "test_cursors_with_union", test_cursors_with_union },
+ { "test_truncation", test_truncation },
+ { "test_truncation_option", test_truncation_option },
+ { "test_client_character_set", test_client_character_set },
{ "test_bug8330", test_bug8330 },
{ "test_bug7990", test_bug7990 },
{ "test_bug8378", test_bug8378 },
+ { "test_bug8722", test_bug8722 },
+ { "test_bug8880", test_bug8880 },
+ { "test_bug9159", test_bug9159 },
+ { "test_bug9520", test_bug9520 },
+ { "test_bug9478", test_bug9478 },
+ { "test_bug9643", test_bug9643 },
+ { "test_bug10729", test_bug10729 },
+ { "test_bug11111", test_bug11111 },
+ { "test_bug9992", test_bug9992 },
+ { "test_bug10736", test_bug10736 },
+ { "test_bug10794", test_bug10794 },
+ { "test_bug11172", test_bug11172 },
+ { "test_bug11656", test_bug11656 },
+ { "test_bug10214", test_bug10214 },
{ "test_bug9735", test_bug9735 },
{ "test_bug11183", test_bug11183 },
+ { "test_bug11037", test_bug11037 },
+ { "test_bug10760", test_bug10760 },
{ "test_bug12001", test_bug12001 },
{ "test_bug11718", test_bug11718 },
+ { "test_bug11909", test_bug11909 },
+ { "test_bug11901", test_bug11901 },
+ { "test_bug11904", test_bug11904 },
+ { "test_bug12243", test_bug12243 },
{ 0, 0 }
};
@@ -12152,7 +14703,6 @@ static void print_test_output()
}
}
-
/***************************************************************************
main routine
***************************************************************************/
@@ -12174,7 +14724,7 @@ int main(int argc, char **argv)
(char**) embedded_server_groups))
DIE("Can't initialize MySQL server");
- client_connect(); /* connect to server */
+ client_connect(0); /* connect to server */
total_time= 0;
for (iter_count= 1; iter_count <= opt_count; iter_count++)
@@ -12182,7 +14732,6 @@ int main(int argc, char **argv)
/* Start of tests */
test_count= 1;
start_time= time((time_t *)0);
-
if (!argc)
{
for (fptr= my_tests; fptr->name; fptr++)
@@ -12212,11 +14761,6 @@ int main(int argc, char **argv)
}
}
- /*
- 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);
@@ -12224,6 +14768,7 @@ int main(int argc, char **argv)
}
client_disconnect(); /* disconnect from server */
+
free_defaults(defaults_argv);
print_test_output();
diff --git a/tests/pmail.pl b/tests/pmail.pl
index c7f8d4ee368..02d5d60ac0f 100755
--- a/tests/pmail.pl
+++ b/tests/pmail.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/perl -w
#
# Prints mails to standard output
#
@@ -9,21 +9,25 @@
use DBI;
use Getopt::Long;
-$VER="1.5";
+$VER="2.0";
@fldnms= ("mail_from","mail_to","cc","date","time_zone","file","sbj","txt");
-$fields=8;
-@mail= (@from,@to,@cc,@date,@time_zone,@file,@sbj,@txt);
+my $fields= 0;
+my $base_q= "";
+my $mail_count= 0;
$opt_user= $opt_password= "";
$opt_socket= "/tmp/mysql.sock";
$opt_port= 3306;
$opt_db="mail";
-$opt_table="mails";
+$opt_table="my_mail";
$opt_help=$opt_count=0;
+$opt_thread= 0;
+$opt_host= "";
+$opt_message_id= 0;
GetOptions("help","count","port=i","db=s","table=s","host=s","password=s",
- "user=s","socket=s") || usage();
+ "user=s","socket=s", "thread","message_id") || usage();
if ($opt_host eq '')
{
@@ -39,81 +43,194 @@ if ($opt_help || !$ARGV[0])
#### Connect and parsing the query to MySQL
####
-$dbh= DBI->connect("DBI:mysql:$opt_db:$opt_host:port=$opt_port:mysql_socket=$opt_mysql_socket", $opt_user,$opt_password, { PrintError => 0})
+$dbh= DBI->connect("DBI:mysql:$opt_db:$opt_host:port=$opt_port:mysql_socket=$opt_socket", $opt_user,$opt_password, { PrintError => 0})
|| die $DBI::errstr;
-if ($opt_count)
-{
- count_mails();
-}
+main();
-$fields=0;
-$query = "select ";
-foreach $val (@fldnms)
+####
+#### main
+####
+
+sub main
{
- if (!$fields)
+ my ($row, $val, $q, $mail, $sth);
+
+ if ($opt_count)
{
- $query.= "$val";
+ count_mails();
}
- else
+
+ $base_q= "SELECT ";
+ foreach $val (@fldnms)
+ {
+ if (!$fields)
+ {
+ $base_q.= "$val";
+ }
+ else
+ {
+ $base_q.= ",$val";
+ }
+ $fields++;
+ }
+ $base_q.= ",message_id" if ($opt_thread || $opt_message_id);
+ $base_q.= " FROM $opt_table";
+ $q= " WHERE $ARGV[0]";
+
+ $sth= $dbh->prepare($base_q . $q);
+ if (!$sth->execute)
+ {
+ print "$DBI::errstr\n";
+ $sth->finish;
+ die;
+ }
+ for (; ($row= $sth->fetchrow_arrayref); $mail_count++)
{
- $query.= ",$val";
+ for ($i= 0; $i < $fields; $i++)
+ {
+ if ($opt_message_id)
+ {
+ $mail[$fields][$mail_count]= $row->[$fields];
+ $mail[$fields][$mail_count].= "\nNumber of Replies: " . get_nr_replies($row->[$fields]);
+ }
+ $mail[$i][$mail_count]= $row->[$i];
+ }
+ if ($opt_thread)
+ {
+ get_mail_by_message_id($row->[$fields], $mail);
+ }
}
- $fields++;
+ print_mails($mail);
}
-$query.= " from $opt_table where $ARGV[0] order by date desc";
####
-#### Send query and save result
+#### Function, which fetches mail by searching in-reply-to with
+#### a given message_id. Saves the value (mail) in mail variable.
+#### Returns the message id of the mail found and searches again
+#### and saves, until no more mails are found with that message_id.
####
-$sth= $dbh->prepare($query);
-if (!$sth->execute)
+sub get_mail_by_message_id
{
- print "$DBI::errstr\n";
- $sth->finish;
- die;
-}
-for ($i=0; ($row= $sth->fetchrow_arrayref); $i++)
-{
- for ($j=0; $j < $fields; $j++)
+ my ($message_id, $mail)= @_;
+ my ($q, $query, $i, $row, $sth);
+
+ $q= " WHERE in_reply_to = \"$message_id\"";
+ $query= $base_q . $q;
+ $sth= $dbh->prepare($query);
+ if (!$sth->execute)
+ {
+ print "QUERY: $query\n$DBI::errstr\n";
+ $sth->finish;
+ die;
+ }
+ while (($row= $sth->fetchrow_arrayref))
{
- $mail[$j][$i]= $row->[$j];
+ $mail_count++;
+ for ($i= 0; $i < $fields; $i++)
+ {
+ if ($opt_message_id)
+ {
+ $mail[$fields][$mail_count]= $row->[$fields];
+ $mail[$fields][$mail_count].= "\nNumber of Replies: " . get_nr_replies($row->[$fields]);
+ }
+ $mail[$i][$mail_count]= $row->[$i];
+ }
+ $new_message_id= $row->[$fields];
+ if (defined($new_message_id) && length($new_message_id))
+ {
+ get_mail_by_message_id($new_message_id, $mail);
+ }
}
+ return;
}
####
-#### Print to stderr
+#### Get number of replies for a given message_id
####
-for ($i=0; $mail[0][$i]; $i++)
+sub get_nr_replies
{
- print "#" x 33;
- print " " . ($i+1) . ". Mail ";
- print "#" x 33;
- print "\nFrom: $mail[0][$i]\n";
- print "To: $mail[1][$i]\n";
- print "Cc: $mail[2][$i]\n";
- print "Date: $mail[3][$i]\n";
- print "Timezone: $mail[4][$i]\n";
- print "File: $mail[5][$i]\n";
- print "Subject: $mail[6][$i]\n";
- print "Message:\n$mail[7][$i]\n";
-}
-print "#" x 20;
-print " Summary: ";
-if ($i == 1)
-{
- print "$i Mail ";
- print "matches the query ";
+ my ($message_id)= @_;
+ my ($sth, $sth2, $q, $row, $row2, $nr_replies);
+
+ $nr_replies= 0;
+ $q= "SELECT COUNT(*) FROM my_mail WHERE in_reply_to=\"$message_id\"";
+ $sth= $dbh->prepare($q);
+ if (!$sth->execute)
+ {
+ print "QUERY: $q\n$DBI::errstr\n";
+ $sth->finish;
+ die;
+ }
+ while (($row= $sth->fetchrow_arrayref))
+ {
+ if (($nr_replies= $row->[0]))
+ {
+ $q= "SELECT message_id FROM my_mail WHERE in_reply_to=\"$message_id\"";
+ $sth2= $dbh->prepare($q);
+ if (!$sth2->execute)
+ {
+ print "QUERY: $q\n$DBI::errstr\n";
+ $sth->finish;
+ die;
+ }
+ while (($row2= $sth2->fetchrow_arrayref))
+ {
+ # There may be several replies to the same mail. Also the
+ # replies to the 'parent' mail may contain several replies
+ # and so on. Thus we need to calculate it recursively.
+ $nr_replies+= get_nr_replies($row2->[0]);
+ }
+ }
+ return $nr_replies;
+ }
}
-else
+
+####
+#### Print mails
+####
+
+sub print_mails
{
- print "$i Mails ";
- print "match the query ";
-}
-print "#" x 20;
-print "\n";
+ my ($mail)= @_;
+ my ($i);
+
+ for ($i=0; $mail[0][$i]; $i++)
+ {
+ print "#" x 33;
+ print " " . ($i+1) . ". Mail ";
+ print "#" x 33;
+ print "\n";
+ if ($opt_message_id)
+ {
+ print "Msg ID: $mail[$fields][$i]\n";
+ }
+ print "From: $mail[0][$i]\n";
+ print "To: $mail[1][$i]\n";
+ print "Cc:" . (defined($mail[2][$i]) ? $mail[2][$i] : "") . "\n";
+ print "Date: $mail[3][$i]\n";
+ print "Timezone: $mail[4][$i]\n";
+ print "File: $mail[5][$i]\n";
+ print "Subject: $mail[6][$i]\n";
+ print "Message:\n$mail[7][$i]\n";
+ }
+ print "#" x 20;
+ print " Summary: ";
+ if ($i == 1)
+ {
+ print "$i Mail ";
+ print "matches the query ";
+ }
+ else
+ {
+ print "$i Mails ";
+ print "match the query ";
+ }
+ print "#" x 20;
+ print "\n";
+}
####
#### Count mails that matches the query, but don't show them
@@ -121,6 +238,8 @@ print "\n";
sub count_mails
{
+ my ($sth);
+
$sth= $dbh->prepare("select count(*) from $opt_table where $ARGV[0]");
if (!$sth->execute)
{
@@ -154,15 +273,21 @@ sub usage
Usage: pmail [options] "SQL where clause"
Options:
- --help show this help
- --count Shows how many mails matches the query, but not the mails.
- --db= database to use (Default: $opt_db)
- --table= table to use (Default: $opt_table)
- --host= Hostname which to connect (Default: $opt_host)
- --socket= Unix socket to be used for connection (Default: $opt_socket)
- --password= Password to use for mysql
- --user= User to be used for mysql connection, if not current user
- --port= mysql port to be used (Default: $opt_port)
+ --help show this help
+ --count Shows how many mails matches the query, but not the mails.
+ --db= database to use (Default: $opt_db)
+ --host= Hostname which to connect (Default: $opt_host)
+ --socket= Unix socket to be used for connection (Default: $opt_socket)
+ --password= Password to use for mysql
+ --user= User to be used for mysql connection, if not current user
+ --port= mysql port to be used (Default: $opt_port)
+ --thread Will search for possible replies to emails found by the search
+ criteria. Replies, if found, will be displayed right after the
+ original mail.
+ --message_id Display message_id on top of each mail. Useful when searching
+ email threads with --thread. On the second line is the number
+ of replies to the same thread, starting counting from that
+ mail (excluding possible parent mails).
"SQL where clause" is the end of the select clause,
where the condition is expressed. The result will
be the mail(s) that matches the condition and
@@ -176,18 +301,20 @@ sub usage
- Subject
- Message text
The field names that can be used in the where clause are:
- Field Type
- - mail_from varchar(120)
- - date datetime
- - sbj varchar(200)
- - txt mediumtext
- - cc text
- - mail_to text
- - time_zone varchar(6)
- - reply varchar(120)
- - file varchar(32)
- - hash int(11)
- An example of the pmail:
+ Field Type
+ - message_id varchar(255) # Use with --thread and --message_id
+ - in_reply_to varchar(255) # Internally used by --thread
+ - mail_from varchar(120)
+ - date datetime
+ - sbj varchar(200)
+ - txt mediumtext
+ - cc text
+ - mail_to text
+ - time_zone varchar(6)
+ - reply varchar(120)
+ - file varchar(32)
+ - hash int(11)
+ An example of pmail:
pmail "txt like '%libmysql.dll%' and sbj like '%delphi%'"
NOTE: the txt field is NOT case sensitive!
EOF
diff --git a/tests/select_test.c b/tests/select_test.c
index ee2a9192865..64c4fec5167 100644
--- a/tests/select_test.c
+++ b/tests/select_test.c
@@ -44,6 +44,7 @@ int main(int argc, char **argv)
perror("");
exit(1);
}
+ mysql.reconnect= 1;
count = 0;
num = atoi(argv[2]);
diff --git a/tests/showdb_test.c b/tests/showdb_test.c
index df2b3037c00..08229fc51ee 100644
--- a/tests/showdb_test.c
+++ b/tests/showdb_test.c
@@ -45,6 +45,7 @@ int main(int argc, char **argv)
perror("");
exit(1);
}
+ mysql.reconnect= 1;
count = 0;
num = atoi(argv[2]);
diff --git a/tests/ssl_test.c b/tests/ssl_test.c
index b18e493c267..85f490cb02e 100644
--- a/tests/ssl_test.c
+++ b/tests/ssl_test.c
@@ -51,6 +51,7 @@ int main(int argc, char **argv)
perror("");
exit(1);
}
+ mysql.reconnect= 1;
count = 0;
num = atoi(argv[2]);
while (count < num)
diff --git a/tests/thread_test.c b/tests/thread_test.c
index 06f335fe1a6..f8577857d0a 100644
--- a/tests/thread_test.c
+++ b/tests/thread_test.c
@@ -55,6 +55,7 @@ unsigned __stdcall test_thread(void *arg __attribute__((unused)))
perror("");
goto end;
}
+ mysql.reconnect= 1;
if (verbose) { putchar('*'); fflush(stdout); }
for (count=0 ; count < number_of_tests ; count++)
{
diff --git a/tests/udf_test b/tests/udf_test
index 4621a7b34a5..15ad640f984 100644
--- a/tests/udf_test
+++ b/tests/udf_test
@@ -9,6 +9,7 @@ CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so";
+CREATE FUNCTION myfunc_argument_name RETURNS STRING SONAME "udf_example.so";
select metaphon("hello");
select myfunc_double("hello","world");
@@ -20,6 +21,7 @@ create temporary table t1 (a int,b double);
insert into t1 values (1,5),(1,4),(2,8),(3,9),(4,11);
select avgcost(a,b) from t1;
select avgcost(a,b) from t1 group by a;
+select a, myfunc_argument_name(a), myfunc_argument_name(a as b) from t1;
drop table t1;
DROP FUNCTION metaphon;
@@ -28,3 +30,4 @@ DROP FUNCTION myfunc_int;
DROP FUNCTION lookup;
DROP FUNCTION reverse_lookup;
DROP FUNCTION avgcost;
+DROP FUNCTION myfunc_argument_name;
diff --git a/tests/udf_test.res b/tests/udf_test.res
index 66634e13616..de9e9969f3a 100644
--- a/tests/udf_test.res
+++ b/tests/udf_test.res
@@ -35,6 +35,12 @@ CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so"
Query OK, 0 rows affected
--------------
+CREATE FUNCTION myfunc_argument_name RETURNS STRING SONAME "udf_example.so"
+--------------
+
+Query OK, 0 rows affected
+
+--------------
select metaphon("hello")
--------------
@@ -107,6 +113,18 @@ avgcost(a,b)
4 rows in set
--------------
+select a, myfunc_argument_name(a) from t1;
+--------------
+
+a myfunc_argument_name(a) myfunc_argument_name(a as b)
+1 a b
+1 a b
+2 a b
+3 a b
+4 a b
+5 rows in set
+
+--------------
drop table t1
--------------
@@ -148,4 +166,10 @@ DROP FUNCTION avgcost
Query OK, 0 rows affected
+--------------
+DROP FUNCTION myfunc_argument_name;
+--------------
+
+Query OK, 0 rows affected
+
Bye
diff --git a/tools/Makefile.am b/tools/Makefile.am
index bf81005ca2c..0f726bd5fc3 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -15,14 +15,19 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Process this file with automake to create Makefile.in
-INCLUDES= @MT_INCLUDES@ -I$(top_builddir)/include \
- -I$(top_srcdir)/include $(openssl_includes)
-LDADD= @CLIENT_EXTRA_LDFLAGS@ @openssl_libs@ \
- $(top_builddir)/libmysql_r/libmysqlclient_r.la \
- @ZLIB_LIBS@
-bin_PROGRAMS= mysqlmanager
-mysqlmanager_SOURCES= mysqlmanager.c
-mysqlmanager_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
+if HAVE_YASSL
+ yassl_dummy_link_fix= $(top_srcdir)/extra/yassl/src/dummy.cpp
+else
+ yassl_dummy_link_fix=
+endif
+INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \
+ $(openssl_includes)
+LDADD= @CLIENT_EXTRA_LDFLAGS@ \
+ $(top_builddir)/libmysql_r/libmysqlclient_r.la \
+ @openssl_libs@ @ZLIB_LIBS@
+bin_PROGRAMS= mysqltestmanager
+mysqltestmanager_SOURCES= mysqlmanager.c $(yassl_dummy_link_fix)
+mysqltestmanager_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
DEF= -DUNDEF_THREADS_HACK
# Don't update the files from bitkeeper
diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c
index 27caa1e0255..4a5c08be50a 100644
--- a/tools/mysqlmanager.c
+++ b/tools/mysqlmanager.c
@@ -557,14 +557,13 @@ HANDLE_DECL(handle_set_exec_stderr)
static int set_exec_param(struct manager_thd* thd, char* args_start,
char* args_end, PARAM_TYPE param_type)
{
- int num_args;
const char* error=0;
struct manager_exec* e;
char* arg_p;
char* param;
int param_size;
- if ((num_args=tokenize_args(args_start,&args_end))<2)
+ if (tokenize_args(args_start,&args_end) < 2)
{
error="Too few arguments";
goto err;
@@ -607,12 +606,11 @@ err:
HANDLE_DECL(handle_start_exec)
{
- int num_args;
struct manager_exec* e;
int ident_len;
const char* error=0;
struct timespec t;
- if ((num_args=tokenize_args(args_start,&args_end))<1)
+ if (tokenize_args(args_start,&args_end) < 1)
{
error="Too few arguments";
goto err;
@@ -656,12 +654,11 @@ err:
HANDLE_DECL(handle_stop_exec)
{
- int num_args;
struct timespec abstime;
struct manager_exec* e;
int ident_len;
const char* error=0;
- if ((num_args=tokenize_args(args_start,&args_end))<2)
+ if (tokenize_args(args_start,&args_end) <2)
{
error="Too few arguments";
goto err;
@@ -877,7 +874,10 @@ static void manager_exec_connect(struct manager_exec* e)
{
if (mysql_real_connect(&e->mysql,e->con_host,e->con_user,e->con_pass,0,
e->con_port,e->con_sock,0))
+ {
+ e->mysql.reconnect= 1;
return;
+ }
sleep(1);
}
e->error="Could not connect to MySQL server withing the number of tries";
diff --git a/vio/Makefile.am b/vio/Makefile.am
index e27daa7ac35..0d4f052b30a 100644
--- a/vio/Makefile.am
+++ b/vio/Makefile.am
@@ -14,21 +14,26 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+if HAVE_YASSL
+ yassl_dummy_link_fix= $(top_srcdir)/extra/yassl/src/dummy.cpp
+else
+ yassl_dummy_link_fix=
+endif
INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \
$(openssl_includes)
LDADD= @CLIENT_EXTRA_LDFLAGS@ $(openssl_libs)
pkglib_LIBRARIES= libvio.a
noinst_PROGRAMS = test-ssl test-sslserver test-sslclient
noinst_HEADERS= vio_priv.h
-test_ssl_SOURCES= test-ssl.c
+test_ssl_SOURCES= test-ssl.c $(yassl_dummy_link_fix)
test_ssl_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs)
-test_sslserver_SOURCES= test-sslserver.c
+test_sslserver_SOURCES= test-sslserver.c $(yassl_dummy_link_fix)
test_sslserver_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs)
-test_sslclient_SOURCES= test-sslclient.c
+test_sslclient_SOURCES= test-sslclient.c $(yassl_dummy_link_fix)
test_sslclient_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs)
diff --git a/vio/test-sslserver.c b/vio/test-sslserver.c
index d05e50af16b..e4d32a75264 100644
--- a/vio/test-sslserver.c
+++ b/vio/test-sslserver.c
@@ -91,12 +91,7 @@ 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
+ size_socket client_len;
int reuseaddr = 1; /* better testing, uh? */
MY_INIT(argv[0]);
diff --git a/vio/vio.c b/vio/vio.c
index 45572b93ed6..e444c634c96 100644
--- a/vio/vio.c
+++ b/vio/vio.c
@@ -27,19 +27,23 @@
* Helper to fill most of the Vio* with defaults.
*/
-void vio_reset(Vio* vio, enum enum_vio_type type,
- my_socket sd, HANDLE hPipe,
- my_bool localhost)
+static void vio_init(Vio* vio, enum enum_vio_type type,
+ my_socket sd, HANDLE hPipe, uint flags)
{
- DBUG_ENTER("vio_reset");
- DBUG_PRINT("enter", ("type=%d sd=%d localhost=%d", type, sd, localhost));
+ DBUG_ENTER("vio_init");
+ DBUG_PRINT("enter", ("type: %d sd: %d flags: %d", type, sd, flags));
+#ifndef HAVE_VIO_READ_BUFF
+ flags&= ~VIO_BUFFERED_READ;
+#endif
bzero((char*) vio, sizeof(*vio));
vio->type = type;
vio->sd = sd;
vio->hPipe = hPipe;
- vio->localhost= localhost;
-#ifdef HAVE_VIO
+ vio->localhost= flags & VIO_LOCALHOST;
+ if ((flags & VIO_BUFFERED_READ) &&
+ !(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE, MYF(MY_WME))))
+ flags&= ~VIO_BUFFERED_READ;
#ifdef __WIN__
if (type == VIO_TYPE_NAMEDPIPE)
{
@@ -103,7 +107,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
{
vio->viodelete =vio_delete;
vio->vioerrno =vio_errno;
- vio->read =vio_read;
+ vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read;
vio->write =vio_write;
vio->fastsend =vio_fastsend;
vio->viokeepalive =vio_keepalive;
@@ -116,21 +120,30 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->is_blocking =vio_is_blocking;
vio->timeout =vio_timeout;
}
-#endif /* HAVE_VIO */
DBUG_VOID_RETURN;
}
+/* Reset initialized VIO to use with another transport type */
+
+void vio_reset(Vio* vio, enum enum_vio_type type,
+ my_socket sd, HANDLE hPipe, uint flags)
+{
+ my_free(vio->read_buffer, MYF(MY_ALLOW_ZERO_PTR));
+ vio_init(vio, type, sd, hPipe, flags);
+}
+
+
/* Open the socket or TCP/IP connection and read the fnctl() status */
-Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
+Vio *vio_new(my_socket sd, enum enum_vio_type type, uint flags)
{
Vio *vio;
DBUG_ENTER("vio_new");
- DBUG_PRINT("enter", ("sd=%d", sd));
+ DBUG_PRINT("enter", ("sd: %d", sd));
if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
{
- vio_reset(vio, type, sd, 0, localhost);
+ vio_init(vio, type, sd, 0, flags);
sprintf(vio->desc,
(vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
vio->sd);
@@ -166,7 +179,7 @@ Vio *vio_new_win32pipe(HANDLE hPipe)
DBUG_ENTER("vio_new_handle");
if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
{
- vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
+ vio_init(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, VIO_LOCALHOST);
strmov(vio->desc, "named pipe");
}
DBUG_RETURN(vio);
@@ -182,7 +195,7 @@ Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_m
DBUG_ENTER("vio_new_win32shared_memory");
if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
{
- vio_reset(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, TRUE);
+ vio_init(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, VIO_LOCALHOST);
vio->handle_file_map= handle_file_map;
vio->handle_map= handle_map;
vio->event_server_wrote= event_server_wrote;
@@ -207,11 +220,8 @@ void vio_delete(Vio* vio)
if (vio)
{
if (vio->type != VIO_CLOSED)
-#ifdef HAVE_VIO /*WAX*/
vio->vioclose(vio);
-#else
- vio_close(vio);
-#endif
+ my_free((gptr) vio->read_buffer, MYF(MY_ALLOW_ZERO_PTR));
my_free((gptr) vio,MYF(0));
}
}
diff --git a/vio/viosocket.c b/vio/viosocket.c
index 5213390e2e6..ea45d7ce5a7 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -33,8 +33,10 @@ int vio_read(Vio * vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_read");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
+ DBUG_ASSERT(vio->read_end == vio->read_pos);
#ifdef __WIN__
r = recv(vio->sd, buf, size,0);
#else
@@ -52,11 +54,55 @@ int vio_read(Vio * vio, gptr buf, int size)
}
+/*
+ Buffered read: if average read size is small it may
+ reduce number of syscalls.
+*/
+
+int vio_read_buff(Vio *vio, gptr buf, int size)
+{
+ int rc;
+#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
+ DBUG_ENTER("vio_read_buff");
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+
+ if (vio->read_pos < vio->read_end)
+ {
+ rc= min(vio->read_end - vio->read_pos, size);
+ memcpy(buf, vio->read_pos, rc);
+ vio->read_pos+= rc;
+ /*
+ Do not try to read from the socket now even if rc < size:
+ vio_read can return -1 due to an error or non-blocking mode, and
+ the safest way to handle it is to move to a separate branch.
+ */
+ }
+ else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
+ {
+ rc= vio_read(vio, vio->read_buffer, VIO_READ_BUFFER_SIZE);
+ if (rc > 0)
+ {
+ if (rc > size)
+ {
+ vio->read_pos= vio->read_buffer + size;
+ vio->read_end= vio->read_buffer + rc;
+ rc= size;
+ }
+ memcpy(buf, vio->read_buffer, rc);
+ }
+ }
+ else
+ rc= vio_read(vio, buf, size);
+ DBUG_RETURN(rc);
+#undef VIO_UNBUFFERED_READ_MIN_SIZE
+}
+
+
int vio_write(Vio * vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_write");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
#ifdef __WIN__
r = send(vio->sd, buf, size,0);
#else
@@ -174,7 +220,7 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive)
int r=0;
uint opt = 0;
DBUG_ENTER("vio_keepalive");
- DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
+ DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int)
set_keep_alive));
if (vio->type != VIO_TYPE_NAMEDPIPE)
{
@@ -344,7 +390,7 @@ int vio_read_pipe(Vio * vio, gptr buf, int size)
{
DWORD length;
DBUG_ENTER("vio_read_pipe");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
DBUG_RETURN(-1);
@@ -358,7 +404,7 @@ int vio_write_pipe(Vio * vio, const gptr buf, int size)
{
DWORD length;
DBUG_ENTER("vio_write_pipe");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
DBUG_RETURN(-1);
@@ -403,7 +449,7 @@ int vio_read_shared_memory(Vio * vio, gptr buf, int size)
char *current_postion;
DBUG_ENTER("vio_read_shared_memory");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
remain_local = size;
current_postion=buf;
@@ -464,7 +510,7 @@ int vio_write_shared_memory(Vio * vio, const gptr buf, int size)
char *current_postion;
DBUG_ENTER("vio_write_shared_memory");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
remain = size;
current_postion = buf;
diff --git a/vio/viossl.c b/vio/viossl.c
index a3a2e7190bd..e6af07c4b0b 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -99,7 +99,7 @@ int vio_ssl_read(Vio * vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_read");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d, ssl_=%p",
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d, ssl_: 0x%p",
vio->sd, buf, size, vio->ssl_arg));
if ((r= SSL_read((SSL*) vio->ssl_arg, buf, size)) < 0)
@@ -117,7 +117,7 @@ int vio_ssl_write(Vio * vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_write");
- DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
if ((r= SSL_write((SSL*) vio->ssl_arg, buf, size)) < 0)
report_errors();
@@ -163,7 +163,7 @@ int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive)
{
int r=0;
DBUG_ENTER("vio_ssl_keepalive");
- DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
+ DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int)
set_keep_alive));
if (vio->type != VIO_TYPE_NAMEDPIPE)
{
@@ -242,7 +242,7 @@ my_socket vio_ssl_fd(Vio* vio)
my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port)
{
DBUG_ENTER("vio_ssl_peer_addr");
- DBUG_PRINT("enter", ("sd=%d", vio->sd));
+ DBUG_PRINT("enter", ("sd: %d", vio->sd));
if (vio->localhost)
{
strmov(buf,"127.0.0.1");
@@ -265,7 +265,7 @@ my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port)
*port= 0;
#endif
}
- DBUG_PRINT("exit", ("addr=%s", buf));
+ DBUG_PRINT("exit", ("addr: %s", buf));
DBUG_RETURN(0);
}
@@ -292,9 +292,10 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
X509* client_cert;
my_bool unused;
my_bool net_blocking;
- enum enum_vio_type old_type;
+ enum enum_vio_type old_type;
DBUG_ENTER("sslaccept");
- DBUG_PRINT("enter", ("sd=%d ptr=%p", vio->sd,ptr));
+ DBUG_PRINT("enter", ("sd: %d ptr: Ox%p, timeout: %d",
+ vio->sd, ptr, timeout));
old_type= vio->type;
net_blocking = vio_is_blocking(vio);
@@ -309,7 +310,8 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
- DBUG_PRINT("info", ("ssl_=%p timeout=%ld",(SSL*) vio->ssl_arg, timeout));
+ DBUG_PRINT("info", ("ssl_: Ox%p timeout: %ld",
+ (SSL*) vio->ssl_arg, timeout));
SSL_clear((SSL*) vio->ssl_arg);
SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout);
SSL_set_fd((SSL*) vio->ssl_arg,vio->sd);
@@ -367,7 +369,8 @@ int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
my_bool net_blocking;
enum enum_vio_type old_type;
DBUG_ENTER("sslconnect");
- DBUG_PRINT("enter", ("sd=%d ptr=%p ctx: %p", vio->sd,ptr,ptr->ssl_context));
+ DBUG_PRINT("enter", ("sd: %d ptr: 0x%p ctx: 0x%p",
+ vio->sd,ptr,ptr->ssl_context));
old_type= vio->type;
net_blocking = vio_is_blocking(vio);
@@ -382,10 +385,11 @@ int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
- DBUG_PRINT("info", ("ssl_=%p timeout=%ld",(SSL*) vio->ssl_arg, timeout));
+ DBUG_PRINT("info", ("ssl_: 0x%p timeout: %ld",
+ (SSL*) vio->ssl_arg, timeout));
SSL_clear((SSL*) vio->ssl_arg);
SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout);
- SSL_set_fd ((SSL*) vio->ssl_arg, vio->sd);
+ SSL_set_fd ((SSL*) vio->ssl_arg, vio_ssl_fd(vio));
SSL_set_connect_state((SSL*) vio->ssl_arg);
if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1)
{
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 498d10da0ee..766d835d2c0 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -80,7 +80,7 @@ static int
vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
{
DBUG_ENTER("vio_set_cert_stuff");
- DBUG_PRINT("enter", ("ctx=%p, cert_file=%s, key_file=%s",
+ DBUG_PRINT("enter", ("ctx: %p, cert_file: %s, key_file: %s",
ctx, cert_file, key_file));
if (cert_file != NULL)
{
@@ -131,7 +131,7 @@ vio_verify_callback(int ok, X509_STORE_CTX *ctx)
int err,depth;
DBUG_ENTER("vio_verify_callback");
- DBUG_PRINT("enter", ("ok=%d, ctx=%p", ok, ctx));
+ DBUG_PRINT("enter", ("ok: %d, ctx: 0x%p", ok, ctx));
err_cert=X509_STORE_CTX_get_current_cert(ctx);
err= X509_STORE_CTX_get_error(ctx);
depth= X509_STORE_CTX_get_error_depth(ctx);
@@ -219,9 +219,6 @@ new_VioSSLConnectorFd(const char* key_file,
int result;
DH *dh;
DBUG_ENTER("new_VioSSLConnectorFd");
- DBUG_PRINT("enter",
- ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
- key_file, cert_file, ca_path, ca_file, cipher));
if (!(ptr=((struct st_VioSSLConnectorFd*)
my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0)))))
@@ -314,9 +311,6 @@ new_VioSSLAcceptorFd(const char *key_file,
int result;
DH *dh;
DBUG_ENTER("new_VioSSLAcceptorFd");
- DBUG_PRINT("enter",
- ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
- key_file, cert_file, ca_path, ca_file, cipher));
ptr= ((struct st_VioSSLAcceptorFd*)
my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0)));